From 04c393f3e77f53b3ff7c6e82199f9c5b2ac89c86 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 29 Jan 2020 18:50:13 -0500 Subject: [PATCH 0001/1210] Initial commit --- bin/.keep | 0 modules/.keep | 0 primitives/.keep | 0 relays/.keep | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 bin/.keep create mode 100644 modules/.keep create mode 100644 primitives/.keep create mode 100644 relays/.keep diff --git a/bin/.keep b/bin/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/modules/.keep b/modules/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/primitives/.keep b/primitives/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/relays/.keep b/relays/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d From 80721922a955d6b99280f0ef384f5f3411d178a5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 29 Jan 2020 19:51:31 -0500 Subject: [PATCH 0002/1210] Squashed commit of hc-jp-bridge-module: commit 265365920836bb1d286c9b48b1902a2de278fdd9 Author: Hernando Castano Date: Wed Jan 29 19:51:15 2020 -0500 Move hc-jp-bridge repo to different folder commit 8271991e95320baba70bd1cb9c4234d0ffd5b638 Merge: 04c393f 304cbc5 Author: Hernando Castano Date: Wed Jan 29 19:36:41 2020 -0500 Merge branch 'hc-jp-bridge-module' of hc-jp-bridge-module commit 304cbc5f02d003ffa5404c1c01e461e5b8539888 Author: Hernando Castano Date: Wed Jan 29 00:38:27 2020 -0500 Update bridge pallet to work with the (almost) lastest master (#4672) * Update decl_error usage * WIP: Update error handling to use DispatchResult * Get module compiling with new error handling * Make tests compile again Main change was updating the usage of InMemoryBackend * Move `sp-state-machine` into dev-dependencies * Bump dependencies to v2.0.0 * Remove some stray comments * Appy code review suggestion commit 510cd6d96372688517496efa61773ea2839f8474 Author: Hernando Castano Date: Tue Dec 17 12:52:51 2019 -0500 Move Bridge Pallet into FRAME (#4373) * Move `bridge` crate into `frame` folder * Make `bridge` pallet compile after `the-big-reorg` commit ab54e838ef75e6a3f68fd0944bf22598c10c552f Author: Hernando Castano Date: Mon Nov 11 21:56:40 2019 +0100 Use new StorageProof type from #3834 commit 8fc8911fd1b4acc2274c6863fb3dba91b30c90af Author: Hernando Castano Date: Tue Nov 5 00:50:34 2019 +0100 Verify Ancestry between Headers (#3963) * Create module for checking ancestry proofs * Use Vec of Headers instead of a HashMap * Move the ancestry verification into the lib.rs file * Change the proof format to exclude `child` and `ancestor` headers * Add a testing function for building header chains * Rename AncestorNotFound error to InvalidAncestryProof * Use ancestor hash instead of header when verifying ancestry * Clean up some stuff missed in the merge commit dbe85738b68358b790cf927b34a804b965a88f96 or: Hernando Castano Date: Fri Nov 1 15:41:58 2019 +0100 Check given Grandpa validator set against set found in storage (#3915) * Make StorageProofChecker happy * Update some tests * Check given validator set against set found in storage * Use Finality Grandpa's Authority Id and Weight * Add better error handling * Use error type from decl_error! macro commit 31b09216603d3e9c21144ce8c0b6bf59307a4f97 or: Hernando Castano Date: Wed Oct 23 14:55:37 2019 +0200 Make tests work after the changes introduced in #3793 (#3874) * Make tests work after the changes introduced in #3793 * Remove unneccessary import commit bce6d804aa86504599ff912387295c58f846cbf3 Author: Jim Posen Date: Thu Oct 10 12:18:58 2019 +0200 Logic for checking Substrate proofs from within runtime module. (#3783) commit a7013e94b6c772c1d45a7cacbb445f73f6554fca Author: Hernando Castano Date: Fri Oct 4 15:21:00 2019 +0300 Allow tracking of multiple bridges commit 3cf648242d631e32bd553a67df54bf5a48912839 Author: Hernando Castano Date: Tue Oct 1 14:55:04 2019 +0200 Add BridgeId => Bridge mapping commit 001c74c45072213e01857d0a2454379b447c5a76 Author: Hernando Castano Date: Tue Oct 1 11:10:19 2019 +0200 Get the mock runtime for tests set up commit 38443a1e8b424ed2f148eb95121d009f730e3b5a Author: Hernando Castano Date: Fri Sep 27 14:52:53 2019 +0200 Clean up some warnings commit bdc3b01401e89c7111f8bf71f84c50750d25089f Author: Hernando Castano Date: Thu Sep 26 16:41:01 2019 +0200 Add more skeleton code commit 26995efbf4bac2842eb2822322f7ad3c3e88feb8 Author: Hernando Castano Date: Wed Sep 25 15:16:57 2019 +0200 Create `bridge` module skeleton --- modules/substrate/lib.rs | 453 +++++++++++++++++++++++++++++ modules/substrate/storage_proof.rs | 112 +++++++ modules/subtrate | 38 +++ 3 files changed, 603 insertions(+) create mode 100644 modules/substrate/lib.rs create mode 100644 modules/substrate/storage_proof.rs create mode 100644 modules/subtrate diff --git a/modules/substrate/lib.rs b/modules/substrate/lib.rs new file mode 100644 index 0000000000000..910c38ce7e333 --- /dev/null +++ b/modules/substrate/lib.rs @@ -0,0 +1,453 @@ +// 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 . + +//! # Bridge Module +//! +//! This will eventually have some useful documentation. +//! For now though, enjoy this cow's wisdom. +//! +//!```ignore +//!________________________________________ +//! / You are only young once, but you can \ +//! \ stay immature indefinitely. / +//! ---------------------------------------- +//! \ ^__^ +//! \ (oo)\_______ +//! (__)\ )\/\ +//! ||----w | +//! || || +//!``` + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod storage_proof; + +use crate::storage_proof::{StorageProof, StorageProofChecker}; +use codec::{Encode, Decode}; +use sp_finality_grandpa::{AuthorityId, AuthorityWeight, GRANDPA_AUTHORITIES_KEY}; +use sp_runtime::traits::Header; +use frame_support::{ + dispatch::{DispatchResult, DispatchError}, + decl_error, decl_module, decl_storage, +}; +use frame_system::{self as system, ensure_signed}; +use storage_proof::Error as StorageError; + +#[derive(Encode, Decode, Clone, PartialEq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct BridgeInfo { + last_finalized_block_number: T::BlockNumber, + last_finalized_block_hash: T::Hash, + last_finalized_state_root: T::Hash, + current_validator_set: Vec<(AuthorityId, AuthorityWeight)>, +} + +impl BridgeInfo { + pub fn new( + block_number: &T::BlockNumber, + block_hash: &T::Hash, + state_root: &T::Hash, + validator_set: Vec<(AuthorityId, AuthorityWeight)>, + ) -> Self + { + // I don't like how this is done, should come back to... + BridgeInfo { + last_finalized_block_number: *block_number, + last_finalized_block_hash: *block_hash, + last_finalized_state_root: *state_root, + current_validator_set: validator_set, + } + } +} + +type BridgeId = u64; + +pub trait Trait: system::Trait {} + +decl_storage! { + trait Store for Module as Bridge { + /// The number of current bridges managed by the module. + pub NumBridges get(num_bridges) config(): BridgeId; + + /// Maps a bridge id to a bridge struct. Allows a single + /// `bridge` module to manage multiple bridges. + pub TrackedBridges get(tracked_bridges): map BridgeId => Option>; + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + fn initialize_bridge( + origin, + block_header: T::Header, + validator_set: Vec<(AuthorityId, AuthorityWeight)>, + validator_set_proof: StorageProof, + ) { + // NOTE: Will want to make this a governance issued call + let _sender = ensure_signed(origin)?; + + let block_number = block_header.number(); + let block_hash = block_header.hash(); + let state_root = block_header.state_root(); + + Self::check_validator_set_proof(state_root, validator_set_proof, &validator_set)?; + + let bridge_info = BridgeInfo::new(block_number, &block_hash, state_root, validator_set); + + let new_bridge_id = NumBridges::get() + 1; + >::insert(new_bridge_id, bridge_info); + + NumBridges::put(new_bridge_id); + } + + fn submit_finalized_headers(origin) { + let _sender = ensure_signed(origin)?; + } + } +} + +decl_error! { + // Error for the Bridge module + pub enum Error for Module { + InvalidStorageProof, + StorageRootMismatch, + StorageValueUnavailable, + InvalidValidatorSetProof, + ValidatorSetMismatch, + InvalidAncestryProof, + } +} + +impl Module { + fn check_validator_set_proof( + state_root: &T::Hash, + proof: StorageProof, + validator_set: &Vec<(AuthorityId, AuthorityWeight)>, + ) -> DispatchResult { + + let checker = ::Hasher>>::new( + *state_root, + proof.clone() + ); + + let checker = checker.map_err(Self::map_storage_err)?; + + // By encoding the given set we should have an easy way to compare + // with the stuff we get out of storage via `read_value` + let encoded_validator_set = validator_set.encode(); + + let c = checker.read_value(GRANDPA_AUTHORITIES_KEY).map_err(Self::map_storage_err)?; + let actual_validator_set = c.ok_or(Error::::StorageValueUnavailable)?; + + if encoded_validator_set == actual_validator_set { + Ok(()) + } else { + Err(Error::::ValidatorSetMismatch.into()) + } + } + + // A naive way to check whether a `child` header is a decendent + // of an `ancestor` header. For this it requires a proof which + // is a chain of headers between (but not including) the `child` + // and `ancestor`. This could be updated to use something like + // Log2 Ancestors (#2053) in the future. + fn verify_ancestry(proof: Vec, ancestor_hash: H::Hash, child: H) -> DispatchResult + where + H: Header, + { + let mut parent_hash = child.parent_hash(); + + // If we find that the header's parent hash matches our ancestor's hash we're done + for header in proof.iter() { + // Need to check that blocks are actually related + if header.hash() != *parent_hash { + break; + } + + parent_hash = header.parent_hash(); + if *parent_hash == ancestor_hash { + return Ok(()) + } + } + + Err(Error::::InvalidAncestryProof.into()) + } + + fn map_storage_err(e: StorageError) -> DispatchError { + match e { + StorageError::StorageRootMismatch => Error::::StorageRootMismatch, + StorageError::StorageValueUnavailable => Error::::StorageValueUnavailable, + }.into() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use sp_core::{Blake2Hasher, H256, Public}; + use sp_runtime::{ + Perbill, traits::{Header as HeaderT, IdentityLookup}, testing::Header, generic::Digest, + }; + use frame_support::{assert_ok, assert_err, impl_outer_origin, parameter_types}; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + #[derive(Clone, PartialEq, Eq, Debug)] + pub struct Test; + + type _System = system::Module; + type MockBridge = Module; + + // TODO: Figure out what I actually need from here + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: u32 = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const MinimumPeriod: u64 = 5; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + type DummyAuthorityId = u64; + + impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Call = (); + type Hash = H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = DummyAuthorityId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = (); + type MaximumBlockWeight = (); + type AvailableBlockRatio = (); + type MaximumBlockLength = (); + type Version = (); + type ModuleToIndex = (); + } + + impl Trait for Test {} + + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = system::GenesisConfig::default().build_storage::().unwrap(); + GenesisConfig { + num_bridges: 0, + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn it_works_for_default_value() { + new_test_ext().execute_with(|| { + assert_eq!(MockBridge::num_bridges(), 0); + }); + } + + fn get_dummy_authorities() -> Vec<(AuthorityId, AuthorityWeight)> { + let authority1 = (AuthorityId::from_slice(&[1; 32]), 1); + let authority2 = (AuthorityId::from_slice(&[2; 32]), 1); + let authority3 = (AuthorityId::from_slice(&[3; 32]), 1); + + vec![authority1, authority2, authority3] + } + + fn create_dummy_validator_proof(validator_set: Vec<(AuthorityId, AuthorityWeight)>) -> (H256, StorageProof) { + use sp_state_machine::{prove_read, backend::Backend, InMemoryBackend}; + + let encoded_set = validator_set.encode(); + + // construct storage proof + let backend = >::from(vec![ + (None, vec![(GRANDPA_AUTHORITIES_KEY.to_vec(), Some(encoded_set))]), + ]); + let root = backend.storage_root(std::iter::empty()).0; + + // Generates a storage read proof + let proof: StorageProof = prove_read(backend, &[&GRANDPA_AUTHORITIES_KEY[..]]) + .unwrap() + .iter_nodes() + .collect(); + + (root, proof) + } + + #[test] + fn it_can_validate_validator_sets() { + let authorities = get_dummy_authorities(); + let (root, proof) = create_dummy_validator_proof(authorities.clone()); + + assert_ok!(MockBridge::check_validator_set_proof(&root, proof, &authorities)); + } + + #[test] + fn it_rejects_invalid_validator_sets() { + let mut authorities = get_dummy_authorities(); + let (root, proof) = create_dummy_validator_proof(authorities.clone()); + + // Do something to make the authority set invalid + authorities.reverse(); + let invalid_authorities = authorities; + + assert_err!( + MockBridge::check_validator_set_proof(&root, proof, &invalid_authorities), + Error::::ValidatorSetMismatch + ); + } + + #[test] + fn it_creates_a_new_bridge() { + let authorities = get_dummy_authorities(); + let (root, proof) = create_dummy_validator_proof(authorities.clone()); + + let test_header = Header { + parent_hash: H256::default(), + number: 42, + state_root: root, + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + let test_hash = test_header.hash(); + + new_test_ext().execute_with(|| { + assert_eq!(MockBridge::num_bridges(), 0); + dbg!(&test_header); + assert_ok!( + MockBridge::initialize_bridge( + Origin::signed(1), + test_header, + authorities.clone(), + proof, + )); + + assert_eq!( + MockBridge::tracked_bridges(1), + Some(BridgeInfo { + last_finalized_block_number: 42, + last_finalized_block_hash: test_hash, + last_finalized_state_root: root, + current_validator_set: authorities.clone(), + })); + + assert_eq!(MockBridge::num_bridges(), 1); + }); + } + + fn build_header_chain(root_header: Header, len: usize) -> Vec
{ + let mut header_chain = vec![root_header]; + for i in 1..len { + let parent = &header_chain[i - 1]; + + let h = Header { + parent_hash: parent.hash(), + number: parent.number() + 1, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + + header_chain.push(h); + } + + // We want our proofs to go from newest to older headers + header_chain.reverse(); + // We don't actually need the oldest header in the proof + header_chain.pop(); + header_chain + } + + #[test] + fn check_that_child_is_ancestor_of_grandparent() { + let ancestor = Header { + parent_hash: H256::default(), + number: 1, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + + // A valid proof doesn't include the child header, so remove it + let mut proof = build_header_chain(ancestor.clone(), 10); + let child = proof.remove(0); + + assert_ok!(MockBridge::verify_ancestry(proof, ancestor.hash(), child)); + } + + #[test] + fn fake_ancestor_is_not_found_in_child_ancestry() { + let ancestor = Header { + parent_hash: H256::default(), + number: 1, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + + // A valid proof doesn't include the child header, so remove it + let mut proof = build_header_chain(ancestor, 10); + let child = proof.remove(0); + + let fake_ancestor = Header { + parent_hash: H256::from_slice(&[1u8; 32]), + number: 42, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + + assert_err!( + MockBridge::verify_ancestry(proof, fake_ancestor.hash(), child), + Error::::InvalidAncestryProof + ); + } + + #[test] + fn checker_fails_if_given_an_unrelated_header() { + let ancestor = Header { + parent_hash: H256::default(), + number: 1, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + + // A valid proof doesn't include the child header, so remove it + let mut invalid_proof = build_header_chain(ancestor.clone(), 10); + let child = invalid_proof.remove(0); + + let fake_ancestor = Header { + parent_hash: H256::from_slice(&[1u8; 32]), + number: 42, + state_root: H256::default(), + extrinsics_root: H256::default(), + digest: Digest::default(), + }; + + invalid_proof.insert(5, fake_ancestor); + + assert_err!( + MockBridge::verify_ancestry(invalid_proof, ancestor.hash(), child), + Error::::InvalidAncestryProof + ); + } +} diff --git a/modules/substrate/storage_proof.rs b/modules/substrate/storage_proof.rs new file mode 100644 index 0000000000000..cda8311fd03df --- /dev/null +++ b/modules/substrate/storage_proof.rs @@ -0,0 +1,112 @@ +// 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 sp_trie::{MemoryDB, Trie, trie_types::TrieDB}; +use sp_runtime::RuntimeDebug; + +pub(crate) type StorageProof = Vec>; + +/// 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: StorageProof) -> 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>, Error> { + self.trie()? + .get(key) + .map(|value| value.map(|value| value.to_vec())) + .map_err(|_| Error::StorageValueUnavailable) + } + + fn trie(&self) -> Result, Error> { + TrieDB::new(&self.db, &self.root) + .map_err(|_| Error::StorageRootMismatch) + } +} + +#[derive(RuntimeDebug, PartialEq)] +pub enum Error { + StorageRootMismatch, + StorageValueUnavailable, +} + +#[cfg(test)] +mod tests { + use super::*; + + use sp_core::{Blake2Hasher, H256}; + use sp_state_machine::{prove_read, backend::Backend, InMemoryBackend}; + + #[test] + fn storage_proof_check() { + // construct storage proof + let backend = >::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 = prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) + .unwrap() + .iter_nodes() + .collect(); + + // check proof in runtime + let checker = >::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!( + >::new(H256::random(), proof).err(), + Some(Error::StorageRootMismatch) + ); + } +} diff --git a/modules/subtrate b/modules/subtrate new file mode 100644 index 0000000000000..335bd1307f84b --- /dev/null +++ b/modules/subtrate @@ -0,0 +1,38 @@ +[package] +name = "pallet-bridge" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } +hash-db = { version = "0.15.2", default-features = false } +pallet-session = { version = "2.0.0", default-features = false, path = "../session" } +serde = { version = "1.0", optional = true } +sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } +sp-finality-grandpa = { version = "2.0.0", default-features = false, path = "../../primitives/finality-grandpa" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +sp-trie = { version = "2.0.0", default-features = false, path = "../../primitives/trie" } + +[dev-dependencies] +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-session/std", + "sp-core/std", + "sp-finality-grandpa/std", + "sp-runtime/std", + "sp-trie/std", + "sp-io/std", +] From 7bc5f618f09e563cdd9296d755b4b4c214d87ef6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 29 Jan 2020 20:14:48 -0500 Subject: [PATCH 0003/1210] Squashed commit of slava-async-bridge: commit 657deb4cf4b90f24b9c5bfd62764b197776c262c Author: Hernando Castano Date: Wed Jan 29 20:14:20 2020 -0500 Move Slava's bridge code into relays folder commit 4868c42c7da959dde7252766996b3ed4e408e439 Author: Hernando Castano Date: Wed Jan 29 20:01:06 2020 -0500 Move files into `modules/ethereum` commit d1093f3e4238acb1a1a020011452cb928d3f8d7a Merge: 29dc6f9 bfd30ef Author: Hernando Castano Date: Wed Jan 29 19:59:27 2020 -0500 Merge branch 'master' of slava-async-bridge commit 29dc6f97b1b7d1db99086d35a5336f43d2f0f8af Author: Hernando Castano Date: Wed Jan 29 19:51:31 2020 -0500 Squashed commit of the following: commit 265365920836bb1d286c9b48b1902a2de278fdd9 Author: Hernando Castano Date: Wed Jan 29 19:51:15 2020 -0500 Move hc-jp-bridge repo to different folder commit 8271991e95320baba70bd1cb9c4234d0ffd5b638 Merge: 04c393f 304cbc5 Author: Hernando Castano Date: Wed Jan 29 19:36:41 2020 -0500 Merge branch 'hc-jp-bridge-module' of hc-jp-bridge-module commit 304cbc5f02d003ffa5404c1c01e461e5b8539888 Author: Hernando Castano Date: Wed Jan 29 00:38:27 2020 -0500 Update bridge pallet to work with the (almost) lastest master (#4672) * Update decl_error usage * WIP: Update error handling to use DispatchResult * Get module compiling with new error handling * Make tests compile again Main change was updating the usage of InMemoryBackend * Move `sp-state-machine` into dev-dependencies * Bump dependencies to v2.0.0 * Remove some stray comments * Appy code review suggestion commit 510cd6d96372688517496efa61773ea2839f8474 Author: Hernando Castano Date: Tue Dec 17 12:52:51 2019 -0500 Move Bridge Pallet into FRAME (#4373) * Move `bridge` crate into `frame` folder * Make `bridge` pallet compile after `the-big-reorg` commit ab54e838ef75e6a3f68fd0944bf22598c10c552f Author: Hernando Castano Date: Mon Nov 11 21:56:40 2019 +0100 Use new StorageProof type from #3834 commit 8fc8911fd1b4acc2274c6863fb3dba91b30c90af Author: Hernando Castano Date: Tue Nov 5 00:50:34 2019 +0100 Verify Ancestry between Headers (#3963) * Create module for checking ancestry proofs * Use Vec of Headers instead of a HashMap * Move the ancestry verification into the lib.rs file * Change the proof format to exclude `child` and `ancestor` headers * Add a testing function for building header chains * Rename AncestorNotFound error to InvalidAncestryProof * Use ancestor hash instead of header when verifying ancestry * Clean up some stuff missed in the merge commit dbe85738b68358b790cf927b34a804b965a88f96 or: Hernando Castano Date: Fri Nov 1 15:41:58 2019 +0100 Check given Grandpa validator set against set found in storage (#3915) * Make StorageProofChecker happy * Update some tests * Check given validator set against set found in storage * Use Finality Grandpa's Authority Id and Weight * Add better error handling * Use error type from decl_error! macro commit 31b09216603d3e9c21144ce8c0b6bf59307a4f97 or: Hernando Castano Date: Wed Oct 23 14:55:37 2019 +0200 Make tests work after the changes introduced in #3793 (#3874) * Make tests work after the changes introduced in #3793 * Remove unneccessary import commit bce6d804aa86504599ff912387295c58f846cbf3 Author: Jim Posen Date: Thu Oct 10 12:18:58 2019 +0200 Logic for checking Substrate proofs from within runtime module. (#3783) commit a7013e94b6c772c1d45a7cacbb445f73f6554fca Author: Hernando Castano Date: Fri Oct 4 15:21:00 2019 +0300 Allow tracking of multiple bridges commit 3cf648242d631e32bd553a67df54bf5a48912839 Author: Hernando Castano Date: Tue Oct 1 14:55:04 2019 +0200 Add BridgeId => Bridge mapping commit 001c74c45072213e01857d0a2454379b447c5a76 Author: Hernando Castano Date: Tue Oct 1 11:10:19 2019 +0200 Get the mock runtime for tests set up commit 38443a1e8b424ed2f148eb95121d009f730e3b5a Author: Hernando Castano Date: Fri Sep 27 14:52:53 2019 +0200 Clean up some warnings commit bdc3b01401e89c7111f8bf71f84c50750d25089f Author: Hernando Castano Date: Thu Sep 26 16:41:01 2019 +0200 Add more skeleton code commit 26995efbf4bac2842eb2822322f7ad3c3e88feb8 Author: Hernando Castano Date: Wed Sep 25 15:16:57 2019 +0200 Create `bridge` module skeleton commit bfd30ef8363b1483ef1107ae1eb958a4e944c93b Author: Svyatoslav Nikolsky Date: Tue Dec 10 12:10:53 2019 +0300 actually use signer from CLI to sign Substrate transactions commit 504028eac60d9d14ba95b506cd355b0d2f405ce0 Author: Svyatoslav Nikolsky Date: Tue Dec 10 12:02:22 2019 +0300 go offline for a bit on connection error commit 446d0c8d20187dfd1beb173958ea28f2ad97887d Author: Svyatoslav Nikolsky Date: Tue Dec 10 11:25:50 2019 +0300 enable info logs by default commit d039c60ec72bc91adfdad85442bc99a93b7f8e8d Author: Svyatoslav Nikolsky Date: Tue Dec 10 11:12:51 2019 +0300 support basic CLI arguments commit 65c6d48e23576f36e8541878b920a03730226392 Author: Svyatoslav Nikolsky Date: Mon Dec 9 15:37:48 2019 +0300 fix restart commit 96e94c1c4b22d732078f8c401b872c5f8246c3fe Author: Svyatoslav Nikolsky Date: Mon Dec 9 14:57:53 2019 +0300 license commit 68f4191e6cdd211ac8975e0b79f8a6f46a3ca953 Author: Svyatoslav Nikolsky Date: Mon Dec 9 14:56:05 2019 +0300 restart sync when Substrate reorgs && we are unlucky commit 29887c446167d580d73cc03a0b71c31890cafb51 Author: Svyatoslav Nikolsky Date: Mon Dec 9 13:49:31 2019 +0300 only read genesis hash once commit 832492b8393fe2063adf9c58c2b9e060dc3e4efb Author: Svyatoslav Nikolsky Date: Mon Dec 9 13:23:26 2019 +0300 changed TODO commit 9dbc130e5fa036ae63d973819daf30f4ed6ffb5b Author: Svyatoslav Nikolsky Date: Mon Dec 9 13:16:56 2019 +0300 removed obsolete exit future commit d03408cd8284eb0c61e7e96429b4f6199353e030 Author: Svyatoslav Nikolsky Date: Mon Dec 9 13:16:17 2019 +0300 removed obsolete TODOs + moved a couple of TODOs to runtime module commit ed8bec44b79f9a2ce829e59f10181368b2f42139 Author: Svyatoslav Nikolsky Date: Mon Dec 9 12:37:05 2019 +0300 explained TODO fix commit aa9c4c66ec2904eeb6072d654718b0ac0b7d8803 Author: Svyatoslav Nikolsky Date: Mon Dec 9 12:28:09 2019 +0300 fix tx outcome serialization commit 126f8f5484dac8c4af588ae86dc8855919d6c822 Author: Svyatoslav Nikolsky Date: Mon Dec 9 12:05:05 2019 +0300 prune old ethereum headers when Substrate best header is too far in the future commit c7bd301e631a44fe3263e188d0956081aa84f31e Author: Svyatoslav Nikolsky Date: Fri Dec 6 12:51:50 2019 +0300 fix trace commit 549bb7acdb30cfdafe6c8600f0410212539ea63d Author: Svyatoslav Nikolsky Date: Fri Dec 6 12:51:26 2019 +0300 tx hashes are already a part of Block response commit 7864017909f87ea36955d605a924c3c88bc88df3 Author: Svyatoslav Nikolsky Date: Thu Dec 5 12:29:37 2019 +0300 submit bunch of headers at once + some fixes commit 96485f85d38c144f0771f02ba692216a60356665 Author: Svyatoslav Nikolsky Date: Wed Dec 4 17:22:13 2019 +0300 print status messages commit ae0ec4c087136db653339537daab7f96a8c21b65 Author: Svyatoslav Nikolsky Date: Wed Dec 4 17:06:00 2019 +0300 continue actual Substrate client implementation commit 8146293740d70b88904568ff8e5acdfbadf06fd3 Author: Svyatoslav Nikolsky Date: Wed Dec 4 13:49:30 2019 +0300 fix IncompleteHeader condition commit 767c6201157dabcccf7f62e643681ca298224fb1 Author: Svyatoslav Nikolsky Date: Wed Dec 4 10:55:06 2019 +0300 actual Substrate client implementation commit 221fd4ccd2b1eea12c9dacf800d80e15ec115c1b Author: Svyatoslav Nikolsky Date: Wed Nov 20 17:28:13 2019 +0300 initial commit --- relays/ethereum/Cargo.lock | 6274 +++++++++++++++++++++ relays/ethereum/Cargo.toml | 32 + relays/ethereum/LICENSE | 675 +++ relays/ethereum/README.md | 7 + relays/ethereum/src/cli.yml | 33 + relays/ethereum/src/ethereum_client.rs | 170 + relays/ethereum/src/ethereum_headers.rs | 761 +++ relays/ethereum/src/ethereum_sync.rs | 311 + relays/ethereum/src/ethereum_sync_loop.rs | 486 ++ relays/ethereum/src/ethereum_types.rs | 110 + relays/ethereum/src/main.rs | 102 + relays/ethereum/src/substrate_client.rs | 320 ++ relays/ethereum/src/substrate_types.rs | 68 + 13 files changed, 9349 insertions(+) create mode 100644 relays/ethereum/Cargo.lock create mode 100644 relays/ethereum/Cargo.toml create mode 100644 relays/ethereum/LICENSE create mode 100644 relays/ethereum/README.md create mode 100644 relays/ethereum/src/cli.yml create mode 100644 relays/ethereum/src/ethereum_client.rs create mode 100644 relays/ethereum/src/ethereum_headers.rs create mode 100644 relays/ethereum/src/ethereum_sync.rs create mode 100644 relays/ethereum/src/ethereum_sync_loop.rs create mode 100644 relays/ethereum/src/ethereum_types.rs create mode 100644 relays/ethereum/src/main.rs create mode 100644 relays/ethereum/src/substrate_client.rs create mode 100644 relays/ethereum/src/substrate_types.rs diff --git a/relays/ethereum/Cargo.lock b/relays/ethereum/Cargo.lock new file mode 100644 index 0000000000000..284a4f341bcef --- /dev/null +++ b/relays/ethereum/Cargo.lock @@ -0,0 +1,6274 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "adler32" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "aes" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-ctr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aes-soft" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aesni" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ahash" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "anyhow" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arc-swap" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "asn1_der" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "asn1_der_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-bridge" +version = "0.1.0" +dependencies = [ + "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", + "jsonrpsee-http 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "node-primitives 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "node-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-transaction-payment 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (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)", + "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)", + "sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "web3 0.8.0 (git+https://github.com/svyatonik/rust-web3.git?branch=fix_receipt)", +] + +[[package]] +name = "async-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-macros" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-std" +version = "0.99.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-macros 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-std" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "async-stream-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-stream-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "async-task" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base58" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitmask" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitvec" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-cipher-trait" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-modes" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bs58" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bstr" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bumpalo" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-slice-cast" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "c2-chacha" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "c_linked_list" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "chrono" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random-macro" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "core-foundation" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ctr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cuckoofilter" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "data-encoding" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "derive_more" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derive_more" +version = "0.99.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "elastic-array" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "environmental" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "erased-serde" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "err-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "error-chain" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethabi" +version = "9.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 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)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethbloom" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethereum-transaction" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethereum-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethsign" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-crypto 0.4.2 (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)", + "secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fixed-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +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)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "flate2" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "frame-executive" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "frame-metadata" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "frame-support" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-metadata 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-support-procedural 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-arithmetic 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-procedural" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support-procedural-tools 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support-procedural-tools-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "frame-system" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.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-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "frame-system-rpc-runtime-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "frame-utility" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-core-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-executor" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-executor-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-io-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-join-macro-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-macro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-select-macro-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-sink" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-sink-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-timer" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-timer" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-timer" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-timer" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-util-preview" +version = "0.3.0-alpha.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-join-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-select-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "get_if_addrs" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "get_if_addrs-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "globset" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "h2" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "h2" +version = "0.2.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hermit-abi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hex-literal" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex-literal-impl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "http" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "http-body" +version = "0.2.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper" +version = "0.12.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper" +version = "0.13.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-make 0.3.0-alpha.2a (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-tls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-rlp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.1.1" +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)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "indexmap" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ipnet" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itoa" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "js-sys" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpc-core" +version = "14.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 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)", +] + +[[package]] +name = "jsonrpsee-core" +version = "1.0.0" +source = "git+https://github.com/paritytech/jsonrpsee.git#3e4cf9ba52821b113bb5dd14d16cb15d75a1a19c" +dependencies = [ + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (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)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpsee-http" +version = "1.0.0" +source = "git+https://github.com/paritytech/jsonrpsee.git#3e4cf9ba52821b113bb5dd14d16cb15d75a1a19c" +dependencies = [ + "async-std 0.99.12 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", + "jsonrpsee-server-utils 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (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)", + "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpsee-server-utils" +version = "1.0.0" +source = "git+https://github.com/paritytech/jsonrpsee.git#3e4cf9ba52821b113bb5dd14d16cb15d75a1a19c" +dependencies = [ + "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvdb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libp2p" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core-derive 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-deflate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-dns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-floodsub 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-identify 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-kad 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mdns 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-mplex 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-noise 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-ping 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-plaintext 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-secio 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-tcp 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-uds 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-wasm-ext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-websocket 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-yamux 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "multistream-select 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-core-derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-deflate" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-dns" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-floodsub" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-identify" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-kad" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mdns" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-mplex" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-noise" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "snow 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-ping" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-plaintext" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-secio" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-swarm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-tcp" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnet 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-uds" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-wasm-ext" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-websocket" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libp2p-yamux" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "yamux 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libsecp256k1" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libz-sys" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lru" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "malloc_size_of_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memoffset" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memory-db" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", + "parity-util-mem 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memory_units" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "merlin" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "multistream-select" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "native-tls" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "node-primitives" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "node-runtime" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-executive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-utility 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "node-primitives 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-authority-discovery 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-collective 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-contracts 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-contracts-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-democracy 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-elections-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-grandpa 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-im-online 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-indices 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-membership 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-nicks 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-offences 1.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-randomness-collective-flip 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-staking-reward-curve 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-sudo 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-transaction-payment 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-transaction-payment-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-treasury 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (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 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-authority-discovery 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-consensus-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-offchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-transaction-pool-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "substrate-wasm-builder-runner 1.0.4 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nohash-hasher" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "once_cell" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl" +version = "0.10.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pallet-authority-discovery" +version = "0.1.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-authority-discovery 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-authorship" +version = "0.1.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-authorship 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-babe" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-consensus-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-balances" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-bridge-eth-poa" +version = "0.1.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-collective" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-contracts" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-sandbox 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pallet-contracts-rpc-runtime-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.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 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-democracy" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-elections-phragmen" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-finality-tracker" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-grandpa" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-finality-granpda 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-im-online" +version = "0.1.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-indices" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-membership" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-nicks" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-offences" +version = "1.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-randomness-collective-flip" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-session" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-staking" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.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-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-staking-reward-curve" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pallet-sudo" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-timestamp" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-transaction-payment" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-transaction-payment-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.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 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "pallet-treasury" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "parity-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parity-crypto" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multiaddr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-multihash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec-derive 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-send-wrapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parity-util-mem" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-wasm" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-project" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "primitive-types" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-error" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-nested" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "protobuf" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pwasm-utils" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "remove_dir_all" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ring" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +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)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-hex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustls" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rw-stream-sink" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "safe-mix" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sc-application-crypto" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sc-block-builder" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sc-client-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (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)", + "kvdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sc-executor 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sc-telemetry 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-transaction-pool-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sc-consensus-slots" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-client-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sc-telemetry 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sc-executor" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-panic-handler 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-serializer 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-wasm-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sc-telemetry" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 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)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)", + "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schannel" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scrypt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sct" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "secp256k1" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "send_wrapper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde-big-array" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slab" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slog" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slog-async" +version = "2.3.0" +source = "git+https://github.com/paritytech/slog-async#107848e7ded5e80dc43f6296c2b96039eb92c0a5" +dependencies = [ + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slog-json" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "erased-serde 0.3.9 (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)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slog-scope" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "snow" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "soketto" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (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)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sourcefile" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sp-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-api-proc-macro" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-arithmetic" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-authority-discovery" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-authorship" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-block-builder" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-blockchain" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lru 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-bridge-eth-poa" +version = "0.1.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde-big-array 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-consensus" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libp2p 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-consensus-babe" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sc-consensus-slots 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-core" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", + "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)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core-storage 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-core-storage" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-debug-derive" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-externalities" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core-storage 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-finality-granpda" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-finality-tracker" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-inherents" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-io" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-keyring" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-offchain" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-panic-handler" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-phragmen" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-runtime" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-arithmetic 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-runtime-interface" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime-interface-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-wasm-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-sandbox" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sp-serializer" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "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)", +] + +[[package]] +name = "sp-session" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-staking" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-state-machine" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 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)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-panic-handler 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "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)", +] + +[[package]] +name = "sp-std" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" + +[[package]] +name = "sp-timestamp" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-transaction-pool-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-transaction-pool-runtime-api" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-trie" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "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)", +] + +[[package]] +name = "sp-version" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", + "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", +] + +[[package]] +name = "sp-wasm-interface" +version = "2.0.0" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" +dependencies = [ + "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stream-cipher" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "string" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strum" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strum_macros" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-bip39" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-wasm-builder-runner" +version = "1.0.4" +source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" + +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (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)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termcolor" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-bip39" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-dns-unofficial" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-fs" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-macros" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-net" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-rustls" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.2.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.3.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tls" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tower-make" +version = "0.3.0-alpha.2a" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tower-service" +version = "0.3.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tracing" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tracing-core" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "trie-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", +] + +[[package]] +name = "trie-root" +version = "0.15.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)", +] + +[[package]] +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "twofish" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twox-hash" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "uint" +version = "0.8.2" +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)", + "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unsigned-varint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "untrusted" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "url" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "vcpkg" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "want" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen" +version = "0.2.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen-webidl" +version = "0.2.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-timer" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmi" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmi-validation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "web-sys" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "web3" +version = "0.8.0" +source = "git+https://github.com/svyatonik/rust-web3.git?branch=fix_receipt#0d061ab0642c0def7e32f586ebff8fb145d29cd6" +dependencies = [ + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-transaction 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethsign 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (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)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki-roots" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "websocket" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "weedle" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wincolor" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "x25519-dalek" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "yaml-rust" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "yamux" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "nohash-hasher 0.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)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize_derive" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "zeroize_derive" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" +"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" +"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" +"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" +"checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" +"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" +"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +"checksum asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" +"checksum asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" +"checksum async-macros 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e421d59b24c1feea2496e409b3e0a8de23e5fc130a2ddc0b012e551f3b272bba" +"checksum async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "644a5a8de80f2085a1e7e57cd1544a2a7438f6e003c0790999bd43b92a77cdb2" +"checksum async-std 0.99.12 (registry+https://github.com/rust-lang/crates.io-index)" = "44501a9f7961bb539b67be0c428b3694e26557046a52759ca7eaf790030a64cc" +"checksum async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "513ee3c49800679a319912340f5601afda9e72848d7dea3a48bab489e8c1a46f" +"checksum async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58982858be7540a465c790b95aaea6710e5139bf8956b1d1344d014fa40100b0" +"checksum async-stream-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393356ed99aa7bff0ac486dde592633b83ab02bd254d8c209d5b9f1d0f533480" +"checksum async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de6bd58f7b9cc49032559422595c81cbfcf04db2f2133592f70af19e258a1ced" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" +"checksum bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" +"checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" +"checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" +"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +"checksum bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" +"checksum byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f6209f3b2c1edea170002e016d5ead6903d3bb0a846477f53bbeb614967a52a9" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" +"checksum c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" +"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" +"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" +"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" +"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" +"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" +"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" +"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" +"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" +"checksum ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "845aaacc16f01178f33349e7c992ecd0cee095aa5e577f0f4dee35971bd36455" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +"checksum elastic-array 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "580f3768bd6465780d063f5b8213a2ebd506e139b345e4a81eb301ceae3d61e1" +"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +"checksum environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34f8467a0284de039e6bd0e25c14519538462ba5beb548bb1f03e645097837a8" +"checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" +"checksum err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b41487fadaa500d02a819eefcde5f713599a01dd51626ef25d2d72d87115667b" +"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" +"checksum ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "965126c64662832991f5a748893577630b558e47fa94e7f35aefcd20d737cef7" +"checksum ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cfe1c169414b709cf28aa30c74060bdb830a03a8ba473314d079ac79d80a5f" +"checksum ethereum-transaction 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6689c8377635a1878c1216b8cb5496a36c3009e85425f55e4a562421b35df38d" +"checksum ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba744248e3553a393143d5ebb68939fc3a4ec0c22a269682535f5ffe7fed728c" +"checksum ethsign 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b656fefa0b59f41b39000532c69359e927c0f1850186808ccf1586734ac3365f" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72fe7539e2c5692c6989f2f9c0457e42f1e5768f96b85c87d273574670ae459f" +"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum frame-executive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-metadata 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-support-procedural 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-support-procedural-tools 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-support-procedural-tools-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-system-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum frame-utility 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" +"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" +"checksum futures-join-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "59e260e6b48ce7d99936c40a7088d782a499a67bef41da5481d21b439454bcea" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" +"checksum futures-select-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "df2ae43560eb10b5e50604c53bead6c9c75eade7081390cd3cce66e1582958f7" +"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +"checksum futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f9eb554aa23143abc64ec4d0016f038caf53bb7cbc3d91490835c54edc96550" +"checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" +"checksum futures-timer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7946248e9429ff093345d3e8fdf4eb0f9b2d79091611c9c14f744971a6f8be45" +"checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" +"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" +"checksum get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +"checksum h2 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f107db1419ef8271686187b1a5d47c6431af4a7f4d98b495e7b7fc249bb0a78" +"checksum hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +"checksum hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" +"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" +"checksum hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" +"checksum hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d4c5c844e2fee0bf673d54c2c177f1713b3d2af2ff6e666b49cb7572e6cf42d" +"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +"checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" +"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +"checksum http-body 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f3aef6f3de2bd8585f5b366f3f550b5774500b4764d00cf00f903c95749eec3" +"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" +"checksum hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2d05aa523087ac0b9d8b93dd80d5d482a697308ed3b0dca7b0667511a7fa7cdc" +"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +"checksum impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" +"checksum impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" +"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" +"checksum impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" +"checksum impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" +"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" +"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum ipnet 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f4b06b21db0228860c8dfd17d2106c49c7c6bd07477a4036985347d84def04" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "1c840fdb2167497b0bd0db43d6dfe61e91637fa72f9d061f8bd17ddc44ba6414" +"checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" +"checksum jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)" = "" +"checksum jsonrpsee-http 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)" = "" +"checksum jsonrpsee-server-utils 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)" = "" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" +"checksum kvdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b2f251f01a7224426abdb2563707d856f7de995d821744fd8fa8e2874f69e3" +"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum libp2p 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fab3090cd3af0f0ff5e6c2cc0f6fe6607e9f9282680cf7cd3bdd4cda38ea722" +"checksum libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3def059145c191b6975e51784d5edc59e77e1ed5b25402fccac704dd7731f3" +"checksum libp2p-core-derive 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eeb2704ac14c60f31967e351ed928b848526a5fc6db4104520020665012826f" +"checksum libp2p-deflate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2b0bf5d37692ac90e2bffa436bec26c0b0def6c0cab7ea85ff67a353d58aaa" +"checksum libp2p-dns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3175fb0fc9016c95c8517a297bbdb5fb6bfbd5665bacd2eb23495d1cbdeb033" +"checksum libp2p-floodsub 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92c11b95281e8cb87eb83c204b3ca4988fa665ed9351199b5bcc323056f49816" +"checksum libp2p-identify 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b4e4b0b4bcf410f77361b08335022d5705df34970dc1744ff58d4bb902309547" +"checksum libp2p-kad 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fd25360fc12b23edb1ed13f73426325a38d32e0927a46fec26ddb6873d7644d" +"checksum libp2p-mdns 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4c2e225a7dfc571c3ad77a0a5ecccc9537afe42d72289ac9f19768567cd677d" +"checksum libp2p-mplex 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2fe584816d993dc0f893396521a3c93191d78a6f28a892b150baa714a12c3e5" +"checksum libp2p-noise 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a30ec2640262a7ad6b1a8b28f6cd8281e620a6802f700adf9ff26e61487c333a" +"checksum libp2p-ping 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b975ad345eb9bb29ddc64670664a50a8ab3e66e28357abb0f83cfc0a9ca2d78" +"checksum libp2p-plaintext 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4fe82189f5c20e8f0a11deaa04d492703c501cefd2428ad68f4f64aefab76f" +"checksum libp2p-secio 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee09e259ceb7633a52fd17f187bedf94e3545b1746487beedbd3a0a07d99817" +"checksum libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd55bc9f5f9eac2bb1ff24ca3c8a655810a566ac38c7a6ee1f30aced5a62905b" +"checksum libp2p-tcp 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "234a7093d05651ab5630db926a4a42ca8978a65bab8c27c2ce2b66b200c76989" +"checksum libp2p-uds 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e2fe0648967da3e56e4a55055c857c8c48326b66be0047d0e04c8ca60d34630" +"checksum libp2p-wasm-ext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7b8f2bd81fb356e81352d4513856bc21215ecf91502aa1f55b6449642a9acf" +"checksum libp2p-websocket 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d74d4fc229ad7e8d1a973178786bdcd5dadbdd7b9822c4477c8687df6f82f66" +"checksum libp2p-yamux 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1913eb7dd6eb5515957b6f1770296f6921968db87bc9b985f0e974b6657e1003" +"checksum libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd9a7c16c9487e710536b699c962f022266347c94201174aa0a7eb0546051aa" +"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" +"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum lru 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a57ada89b072a15fa9e1b9d1e18d0e161fd25a47e0a3ae4868cf53aada8ba97" +"checksum malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e37c5d4cd9473c5f4c9c111f033f15d4df9bd378fdf615944e360a4f55a05f0b" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"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.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5dabfe0a8c69954ae3bcfc5fc14260a85fb80e1bf9f86a155f668d10a67e93dd" +"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" +"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum multistream-select 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1242e4ecf2060b35fb58002988e4720fbb3a2cbd4c136d369c420fa028f69efe" +"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum node-primitives 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum node-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +"checksum nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e657a6ec97f9a3ba46f6f7034ea6db9fcd5b71d25ef1074b7bc03da49be0e8e" +"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +"checksum once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d584f08c2d717d5c23a6414fc2822b71c651560713e54fa7eace675f758a355e" +"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" +"checksum pallet-authority-discovery 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-collective 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-contracts 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-contracts-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-democracy 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-elections-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-grandpa 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-im-online 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-indices 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-membership 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-nicks 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-offences 1.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-randomness-collective-flip 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-staking-reward-curve 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-sudo 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-transaction-payment 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-transaction-payment-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum pallet-treasury 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c276d76c5333b8c2579e02d49a06733a55b8282d2d9b13e8d53b6406bd7e30a" +"checksum parity-crypto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a9c2b525c93d717a234eb220c26474f8d97b08ac50d79faeac4cb6c74bf0b9" +"checksum parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82afcb7461eae5d122543d8be1c57d306ed89af2d6ff7f8b0f5a3cc8f7e511bc" +"checksum parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c70cad855872dd51ce6679e823efb6434061a2c1782a1686438aabf506392cdd" +"checksum parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f9d99dae413590a5f37e43cd99b94d4e62a244160562899126913ea7108673" +"checksum parity-scale-codec-derive 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "492ac3aa93d6caa5d20e4e3e0b75d08e2dcd9dd8a50d19529548b6fe11b3f295" +"checksum parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" +"checksum parity-util-mem 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "570093f39f786beea92dcc09e45d8aae7841516ac19a50431953ac82a0e8f85c" +"checksum parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" +"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" +"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" +"checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +"checksum primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0253db64c26d8b4e7896dd2063b516d2a1b9e0a5da26b5b78335f236d1e9522" +"checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" +"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20" +"checksum pwasm-utils 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" +"checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" +"checksum rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a44d5ae8afcb238af8b75640907edc6c931efcfab2c854e81ed35fa080f84cd" +"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_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 rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9cbe61c20455d3015b2bb7be39e1872310283b8e5a52f5b242b0ac7581fe78" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" +"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +"checksum sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sc-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sc-client-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sc-consensus-slots 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sc-executor 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sc-telemetry 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" +"checksum schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" +"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" +"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +"checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a" +"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" +"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +"checksum serde-big-array 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "883eee5198ea51720eab8be52a36cf6c0164ac90eea0ed95b649d5e35382404e" +"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" +"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99" +"checksum slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)" = "" +"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" +"checksum slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" +"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +"checksum snow 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "afb767eee7d257ba202f0b9b08673bc13b22281632ef45267b19f13100accd2f" +"checksum soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bceb1a3a15232d013d9a3b7cac9e5ce8e2313f348f01d4bc1097e5e53aa07095" +"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" +"checksum sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-api-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-arithmetic 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-authority-discovery 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-authorship 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-consensus-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-core-storage 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-finality-granpda 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-offchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-panic-handler 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-runtime-interface-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-sandbox 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-serializer 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-transaction-pool-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-transaction-pool-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum sp-wasm-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +"checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" +"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22" +"checksum strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81" +"checksum substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" +"checksum substrate-wasm-builder-runner 1.0.4 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +"checksum subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" +"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +"checksum tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69" +"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f17f5d6ab0f35c1506678b28fb1798bdf74fcb737e9843c7b17b73e426eba38" +"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9f5d22fd1e84bd4045d28813491cb7d7caae34d45c80517c2213f09a85e8787a" +"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" +"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" +"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" +"checksum tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" +"checksum tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" +"checksum tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf85e16971e06e680c622e0c1b455be94b086275c5ddcd6d4a83a2bfbb83cda" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "112784d5543df30660b04a72ca423bfbd90e8bb32f94dcf610f15401218b22c5" +"checksum tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "86b616374bcdadd95974e1f0dfca07dc913f1163c53840c0d664aca35114964e" +"checksum tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a441682cd32f3559383112c4a7f372f5c9fa1950c5cf8c8dd05274a2ce8c2654" +"checksum tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" +"checksum tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1df2fa53ac211c136832f530ccb081af9af891af22d685a9493e232c7a359bc2" +"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" +"checksum tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c" +"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" +"checksum tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" +"checksum tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b97c1587fe71018eb245a4a9daa13a5a3b681bbc1f7fdadfe24720e141472c13" +"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" +"checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" +"checksum tower-make 0.3.0-alpha.2a (registry+https://github.com/rust-lang/crates.io-index)" = "316d47dd40cde4ac5d88110eaf9a10a4e2a68612d9c056cd2aa24e37dcb484cd" +"checksum tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "63ff37396cd966ce43bea418bfa339f802857495f797dafa00bea5b7221ebdfa" +"checksum tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ff4e4f59e752cb3beb5b61c6d5e11191c7946231ba84faec2902c9efdd8691c5" +"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-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 try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" +"checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" +"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f0023a96687fe169081e8adce3f65e3874426b7886e9234d490af2dc077959" +"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" +"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "29ae32af33bacd663a9a28241abecf01f2be64e6a185c6139b04f18b6385c5f2" +"checksum wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "1845584bd3593442dc0de6e6d9f84454a59a057722f36f005e44665d6ab19d85" +"checksum wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c" +"checksum wasm-bindgen-macro 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "87fcc747e6b73c93d22c947a6334644d22cfec5abd8b66238484dc2b0aeb9fe4" +"checksum wasm-bindgen-macro-support 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc4b3f2c4078c8c4a5f363b92fcf62604c5913cbd16c6ff5aaf0f74ec03f570" +"checksum wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "ca0b78d6d3be8589b95d1d49cdc0794728ca734adf36d7c9f07e6459508bb53d" +"checksum wasm-bindgen-webidl 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "3126356474ceb717c8fb5549ae387c9fbf4872818454f4d87708bee997214bb5" +"checksum wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aa3e01d234bb71760e685cfafa5e2c96f8ad877c161a721646356651069e26ac" +"checksum wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff" +"checksum wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93" +"checksum web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "98405c0a2e722ed3db341b4c5b70eb9fe0021621f7350bab76df93b09b649bbf" +"checksum web3 0.8.0 (git+https://github.com/svyatonik/rust-web3.git?branch=fix_receipt)" = "" +"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" +"checksum webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" +"checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" +"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" +"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" +"checksum yamux 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2758f29014c1cb7a6e74c1b1160ac8c8203be342d35b73462fc6a13cc6385423" +"checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" +"checksum zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" +"checksum zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "080616bd0e31f36095288bb0acdf1f78ef02c2fa15527d7e993f2a6c7591643e" +"checksum zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml new file mode 100644 index 0000000000000..f8822fe0a31ed --- /dev/null +++ b/relays/ethereum/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "async-bridge" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +ansi_term = "0.9" +async-std = "1.0.1" +async-stream = "0.2.0" +clap = { version = "2.33.0", features = ["yaml"] } +codec = { package = "parity-scale-codec", version = "1.0.0" } +env_logger = "0.7.0" +frame-system = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +futures = "0.3.1" +jsonrpsee-core = { git = "https://github.com/paritytech/jsonrpsee.git" } +jsonrpsee-http = { git = "https://github.com/paritytech/jsonrpsee.git" } +linked-hash-map = "0.5.2" +log = "0.4.8" +node-primitives = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +node-runtime = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +pallet-transaction-payment = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +parking_lot = "0.9.0" +rustc-hex = "2.0.1" +serde = { version = "1.0.40", features = ["derive"] } +serde_json = "1.0.40" +sp-bridge-eth-poa = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +sp-core = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +sp-keyring = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +sp-runtime = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +time = "0.1" +web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "fix_receipt" } diff --git a/relays/ethereum/LICENSE b/relays/ethereum/LICENSE new file mode 100644 index 0000000000000..733c072369ca7 --- /dev/null +++ b/relays/ethereum/LICENSE @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/relays/ethereum/README.md b/relays/ethereum/README.md new file mode 100644 index 0000000000000..9fe2f623fd05a --- /dev/null +++ b/relays/ethereum/README.md @@ -0,0 +1,7 @@ +# PoA <> Substrate Bridge + +**DISCLAIMER:** *we recommend not using the bridge in "production" (to bridge significant amounts) just yet. +it's missing a code audit and should still be considered alpha. we can't rule out that there are bugs that might result in loss of the bridged amounts. +we'll update this disclaimer once that changes* + +These docs are very incomplete yet. Describe high-level goals here in the (near) future. diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml new file mode 100644 index 0000000000000..7a3dcbe2b7ece --- /dev/null +++ b/relays/ethereum/src/cli.yml @@ -0,0 +1,33 @@ +name: ethsub-bridge +version: "0.1.0" +author: Parity Technologies +about: Parity Ethereum (PoA) <-> Substrate bridge +args: + - eth-host: + long: eth-host + value_name: ETH_HOST + help: Connect to Ethereum node at given host. + takes_value: true + - eth-port: + long: eth-port + value_name: ETH_PORT + help: Connect to Ethereum node at given port. + takes_value: true + - sub-host: + long: sub-host + value_name: SUB_HOST + help: Connect to Substrate node at given host. + takes_value: true + - sub-port: + long: sub-port + value_name: SUB_PORT + help: Connect to Substrate node at given port. + takes_value: true + - sub-signer: + long: sub-signer + value_name: SUB_SIGNER + help: The SURI of secret key to use when transactions are submitted to the Substrate node. + - sub-signer-password: + long: sub-signer-password + value_name: SUB_SIGNER_PASSWORD + help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. \ No newline at end of file diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs new file mode 100644 index 0000000000000..e04a915d46e27 --- /dev/null +++ b/relays/ethereum/src/ethereum_client.rs @@ -0,0 +1,170 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use jsonrpsee_core::{client::ClientError, common::Params}; +use jsonrpsee_http::{HttpClient, RequestError, http_client}; +use serde::de::DeserializeOwned; +use serde_json::{from_value, to_value}; +use crate::ethereum_sync_loop::MaybeConnectionError; +use crate::ethereum_types::{H256, Header, HeaderId, Receipt, U64}; + +/// Proof of hash serialization success. +const HASH_SERIALIZATION_PROOF: &'static str = "hash serialization never fails; qed"; +/// Proof of integer serialization success. +const INT_SERIALIZATION_PROOF: &'static str = "integer serialization never fails; qed"; +/// Proof of bool serialization success. +const BOOL_SERIALIZATION_PROOF: &'static str = "bool serialization never fails; qed"; + +/// Ethereum client type. +pub type Client = HttpClient; + +/// All possible errors that can occur during interacting with Ethereum node. +#[derive(Debug)] +pub enum Error { + /// Request start failed. + StartRequestFailed(RequestError), + /// Request not found (should never occur?). + RequestNotFound, + /// Failed to receive response. + ResponseRetrievalFailed(ClientError), + /// Failed to parse response. + ResponseParseFailed(serde_json::Error), + /// We have received header with missing number and hash fields. + IncompleteHeader, + /// We have received receipt with missing gas_used field. + IncompleteReceipt, +} + +impl MaybeConnectionError for Error { + fn is_connection_error(&self) -> bool { + match *self { + Error::StartRequestFailed(_) | Error::ResponseRetrievalFailed(_) => true, + _ => false, + } + } +} + +/// Returns client that is able to call RPCs on Ethereum node. +pub fn client(uri: &str) -> Client { + http_client(uri) +} + +/// Retrieve best known block number from Ethereum node. +pub async fn best_block_number(client: Client) -> (Client, Result) { + let (client, result) = call_rpc::( + client, + "eth_blockNumber", + Params::None, + ).await; + (client, result.map(|x| x.as_u64())) +} + +/// Retrieve block header by its number from Ethereum node. +pub async fn header_by_number(client: Client, number: u64) -> (Client, Result) { + let (client, header) = call_rpc( + client, + "eth_getBlockByNumber", + Params::Array(vec![ + to_value(U64::from(number)).expect(INT_SERIALIZATION_PROOF), + to_value(false).expect(BOOL_SERIALIZATION_PROOF), + ]), + ).await; + (client, header.and_then(|header: Header| match header.number.is_some() && header.hash.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + })) +} + +/// Retrieve block header by its hash from Ethereum node. +pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result) { + let (client, header) = call_rpc( + client, + "eth_getBlockByHash", + Params::Array(vec![ + to_value(hash).expect(HASH_SERIALIZATION_PROOF), + to_value(false).expect(BOOL_SERIALIZATION_PROOF), + ]), + ).await; + (client, header.and_then(|header: Header| match header.number.is_none() && header.hash.is_none() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + })) +} + +/// Retrieve transactions receipts for given block. +pub async fn transactions_receipts( + mut client: Client, + id: HeaderId, + transacactions: Vec, +) -> (Client, Result<(HeaderId, Vec), Error>) { + let mut transactions_receipts = Vec::with_capacity(transacactions.len()); + for transacaction in transacactions { + let (next_client, transaction_receipt) = transaction_receipt(client, transacaction).await; + let transaction_receipt = match transaction_receipt { + Ok(transaction_receipt) => transaction_receipt, + Err(error) => return (next_client, Err(error)), + }; + transactions_receipts.push(transaction_receipt); + client = next_client; + } + (client, Ok((id, transactions_receipts))) +} + +/// Retrieve transaction receipt by transaction hash. +async fn transaction_receipt(client: Client, hash: H256) -> (Client, Result) { + let (client, receipt) = call_rpc::( + client, + "eth_getTransactionReceipt", + Params::Array(vec![ + to_value(hash).expect(HASH_SERIALIZATION_PROOF), + ]), + ).await; + (client, receipt.and_then(|receipt| { + match receipt.gas_used.is_some() { + true => Ok(receipt), + false => Err(Error::IncompleteReceipt), + } + })) +} + +/// Calls RPC on Ethereum node. +async fn call_rpc( + mut client: Client, + method: &'static str, + params: Params, +) -> (Client, Result) { + async fn do_call_rpc( + client: &mut Client, + method: &'static str, + params: Params, + ) -> Result { + let request_id = client + .start_request(method, params) + .await + .map_err(Error::StartRequestFailed)?; + // WARN: if there'll be need for executing >1 request at a time, we should avoid + // calling request_by_id + let response = client + .request_by_id(request_id) + .ok_or(Error::RequestNotFound)? + .await + .map_err(Error::ResponseRetrievalFailed)?; + from_value(response).map_err(Error::ResponseParseFailed) + } + + let result = do_call_rpc(&mut client, method, params).await; + (client, result) +} diff --git a/relays/ethereum/src/ethereum_headers.rs b/relays/ethereum/src/ethereum_headers.rs new file mode 100644 index 0000000000000..154f9256acb15 --- /dev/null +++ b/relays/ethereum/src/ethereum_headers.rs @@ -0,0 +1,761 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use std::collections::{ + BTreeMap, HashMap, HashSet, + btree_map::Entry as BTreeMapEntry, + hash_map::Entry as HashMapEntry, +}; +use crate::ethereum_types::{H256, Header, HeaderId, HeaderStatus, QueuedHeader, Receipt}; + +type HeadersQueue = BTreeMap>; +type KnownHeaders = BTreeMap>; + +/// Ethereum headers queue. +#[derive(Debug, Default)] +pub struct QueuedHeaders { + /// Headers that are received from Ethereum node, but we (native ethereum sync code) have + /// never seen their parents. So we need to check if we can/should submit this header. + maybe_orphan: HeadersQueue, + /// Headers that are received from Ethreum node, and we (native ethereum sync code) have + /// checked that Substrate runtime doesn't know their parents. So we need to submit parents + /// first. + orphan: HeadersQueue, + /// Headers that are ready to be submitted to Substrate runtime, but we need to check + /// whether submission requires transactions receipts to be provided. + maybe_receipts: HeadersQueue, + /// Headers that are ready to be submitted to Substrate runtime, but we need to retrieve + /// transactions receipts first. + receipts: HeadersQueue, + /// Headers that are ready to be submitted to Substrate runtime. + ready: HeadersQueue, + /// Headers that are (we believe) are currently submitted to Substrate runtime by our, + /// not-yet mined transactions. + submitted: HeadersQueue, + /// Pointers to all headers that we ever seen and we believe we can touch in the future. + known_headers: KnownHeaders, + /// Pruned blocks border. We do not store or accept any blocks with number less than + /// this number. + prune_border: u64, +} + +impl QueuedHeaders { + /// Returns prune border. + #[cfg(test)] + pub fn prune_border(&self) -> u64 { + self.prune_border + } + + /// Returns number of headers that are currently in given queue. + pub fn headers_in_status(&self, status: HeaderStatus) -> usize { + match status { + HeaderStatus::Unknown | HeaderStatus::Synced => return 0, + HeaderStatus::MaybeOrphan => self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Orphan => self.orphan.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeReceipts => self.maybe_receipts.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Receipts => self.receipts.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Ready => self.ready.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Submitted => self.submitted.values().fold(0, |total, headers| total + headers.len()), + } + } + + /// Returns number of headers that are currently in the queue. + pub fn total_headers(&self) -> usize { + self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()) + + self.orphan.values().fold(0, |total, headers| total + headers.len()) + + self.maybe_receipts.values().fold(0, |total, headers| total + headers.len()) + + self.receipts.values().fold(0, |total, headers| total + headers.len()) + + self.ready.values().fold(0, |total, headers| total + headers.len()) + } + + /// Returns number of best block in the queue. + pub fn best_queued_number(&self) -> u64 { + std::cmp::max( + self.maybe_orphan.keys().next_back().cloned().unwrap_or(0), + std::cmp::max( + self.orphan.keys().next_back().cloned().unwrap_or(0), + std::cmp::max( + self.maybe_receipts.keys().next_back().cloned().unwrap_or(0), + std::cmp::max( + self.receipts.keys().next_back().cloned().unwrap_or(0), + self.ready.keys().next_back().cloned().unwrap_or(0), + ), + ), + ), + ) + } + + /// Returns synchronization status of the header. + pub fn status(&self, id: &HeaderId) -> HeaderStatus { + self.known_headers + .get(&id.0) + .and_then(|x| x.get(&id.1)) + .cloned() + .unwrap_or(HeaderStatus::Unknown) + } + + /// Get oldest header from given queue. + pub fn header(&self, status: HeaderStatus) -> Option<&QueuedHeader> { + match status { + HeaderStatus::Unknown | HeaderStatus::Synced => return None, + HeaderStatus::MaybeOrphan => oldest_header(&self.maybe_orphan), + HeaderStatus::Orphan => oldest_header(&self.orphan), + HeaderStatus::MaybeReceipts => oldest_header(&self.maybe_receipts), + HeaderStatus::Receipts => oldest_header(&self.receipts), + HeaderStatus::Ready => oldest_header(&self.ready), + HeaderStatus::Submitted => oldest_header(&self.submitted), + } + } + + /// Get oldest headers from given queue until functor will return false. + pub fn headers(&self, status: HeaderStatus, f: impl FnMut(&QueuedHeader) -> bool) -> Option> { + match status { + HeaderStatus::Unknown | HeaderStatus::Synced => return None, + HeaderStatus::MaybeOrphan => oldest_headers(&self.maybe_orphan, f), + HeaderStatus::Orphan => oldest_headers(&self.orphan, f), + HeaderStatus::MaybeReceipts => oldest_headers(&self.maybe_receipts, f), + HeaderStatus::Receipts => oldest_headers(&self.receipts, f), + HeaderStatus::Ready => oldest_headers(&self.ready, f), + HeaderStatus::Submitted => oldest_headers(&self.submitted, f), + } + } + + /// Appends new header to the queue. + pub fn header_response(&mut self, header: Header) { + let id = (&header).into(); + let status = self.status(&id); + if status != HeaderStatus::Unknown { + log::debug!(target: "bridge", "Ignoring new Ethereum header: {:?}. Status is {:?}.", id, status); + return; + } + + if id.0 < self.prune_border { + log::debug!(target: "bridge", "Ignoring ancient new Ethereum header: {:?}.", id); + return; + } + + let parent_id = HeaderId(id.0 - 1, header.parent_hash); + let parent_status = self.status(&parent_id); + let header = QueuedHeader::new(header); + + let status = match parent_status { + HeaderStatus::Unknown | HeaderStatus::MaybeOrphan => { + insert_header(&mut self.maybe_orphan, id, header); + HeaderStatus::MaybeOrphan + }, + HeaderStatus::Orphan => { + insert_header(&mut self.orphan, id, header); + HeaderStatus::Orphan + } + HeaderStatus::MaybeReceipts | HeaderStatus::Receipts | HeaderStatus::Ready + | HeaderStatus::Submitted | HeaderStatus::Synced => { + insert_header(&mut self.maybe_receipts, id, header); + HeaderStatus::MaybeReceipts + }, + }; + + self.known_headers.entry(id.0).or_default().insert(id.1, status); + log::debug!(target: "bridge", "Queueing new Ethereum header: {:?}. Queue: {:?}.", id, status); + } + + /// Receive Substrate best header. + pub fn substrate_best_header_response(&mut self, id: &HeaderId) { + // all ancestors of this header are now synced => let's remove them from + // queues + let mut current = *id; + loop { + let header = match self.status(¤t) { + HeaderStatus::Unknown => break, + HeaderStatus::MaybeOrphan => remove_header(&mut self.maybe_orphan, ¤t), + HeaderStatus::Orphan => remove_header(&mut self.orphan, ¤t), + HeaderStatus::MaybeReceipts => remove_header(&mut self.maybe_receipts, ¤t), + HeaderStatus::Receipts => remove_header(&mut self.receipts, ¤t), + HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), + HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), + HeaderStatus::Synced => break, + }.expect("header has a given status; given queue has the header; qed"); + + log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", current, HeaderStatus::Synced); + *self.known_headers + .entry(current.0) + .or_default() + .entry(current.1) + .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; + current = header.parent_id(); + } + + // remember that the header is synced + log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", id, HeaderStatus::Synced); + *self.known_headers + .entry(id.0) + .or_default() + .entry(id.1) + .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; + + // now let's move all descendants from maybe_orphan && orphan queues to + // maybe_receipts queue + move_header_descendants( + &mut [&mut self.maybe_orphan, &mut self.orphan], + &mut self.maybe_receipts, + &mut self.known_headers, + HeaderStatus::MaybeReceipts, + id, + ); + } + + /// Receive Substrate response for MaybeOrphan request. + pub fn maybe_orphan_response(&mut self, id: &HeaderId, response: bool) { + if !response { + move_header_descendants( + &mut [&mut self.maybe_orphan], + &mut self.orphan, + &mut self.known_headers, + HeaderStatus::Orphan, + &id, + ); + return; + } + + move_header_descendants( + &mut [&mut self.maybe_orphan, &mut self.orphan], + &mut self.maybe_receipts, + &mut self.known_headers, + HeaderStatus::MaybeReceipts, + &id, + ); + } + + /// Receive Substrate response for MaybeReceipts request. + pub fn maybe_receipts_response(&mut self, id: &HeaderId, response: bool) { + let (destination_status, destination_queue) = if response { + (HeaderStatus::Receipts, &mut self.receipts) + } else { + (HeaderStatus::Ready, &mut self.ready) + }; + + move_header( + &mut self.maybe_receipts, + destination_queue, + &mut self.known_headers, + destination_status, + &id, + |header| header, + ); + } + + /// Receive transactions receipts from Ethereum node. + pub fn receipts_response(&mut self, id: &HeaderId, receipts: Vec) { + move_header( + &mut self.receipts, + &mut self.ready, + &mut self.known_headers, + HeaderStatus::Ready, + id, + |header| header.set_receipts(receipts), + ); + } + + /// When header is submitted to Substrate node. + pub fn headers_submitted(&mut self, ids: Vec) { + for id in ids { + move_header( + &mut self.ready, + &mut self.submitted, + &mut self.known_headers, + HeaderStatus::Submitted, + &id, + |header| header, + ); + } + } + + /// Prune and never accep headers before this block. + pub fn prune(&mut self, prune_border: u64) { + if prune_border <= self.prune_border { + return; + } + + prune_queue(&mut self.maybe_orphan, prune_border); + prune_queue(&mut self.orphan, prune_border); + prune_queue(&mut self.maybe_receipts, prune_border); + prune_queue(&mut self.receipts, prune_border); + prune_queue(&mut self.ready, prune_border); + prune_queue(&mut self.submitted, prune_border); + prune_known_headers(&mut self.known_headers, prune_border); + self.prune_border = prune_border; + } + + /// Forgets all ever known headers. + pub fn clear(&mut self) { + self.maybe_orphan.clear(); + self.orphan.clear(); + self.maybe_receipts.clear(); + self.receipts.clear(); + self.ready.clear(); + self.submitted.clear(); + self.known_headers.clear(); + self.prune_border = 0; + } +} + +/// Insert header to the queue. +fn insert_header(queue: &mut HeadersQueue, id: HeaderId, header: QueuedHeader) { + queue.entry(id.0).or_default().insert(id.1, header); +} + +/// Remove header from the queue. +fn remove_header(queue: &mut HeadersQueue, id: &HeaderId) -> Option { + let mut headers_at = match queue.entry(id.0) { + BTreeMapEntry::Occupied(headers_at) => headers_at, + BTreeMapEntry::Vacant(_) => return None, + }; + + let header = headers_at.get_mut().remove(&id.1); + if headers_at.get().is_empty() { + headers_at.remove(); + } + header +} + +/// Move header from source to destination queue. +fn move_header( + source_queue: &mut HeadersQueue, + destination_queue: &mut HeadersQueue, + known_headers: &mut KnownHeaders, + destination_status: HeaderStatus, + id: &HeaderId, + prepare: impl FnOnce(QueuedHeader) -> QueuedHeader, +) { + let header = match remove_header(source_queue, id) { + Some(header) => prepare(header), + None => return, + }; + + known_headers.entry(id.0).or_default().insert(id.1, destination_status); + destination_queue.entry(id.0).or_default().insert(id.1, header); + + log::debug!( + target: "bridge", + "Ethereum header {:?} is now {:?}", + id, + destination_status, + ); +} + +/// Move all descendant headers from the source to destination queue. +fn move_header_descendants( + source_queues: &mut [&mut HeadersQueue], + destination_queue: &mut HeadersQueue, + known_headers: &mut KnownHeaders, + destination_status: HeaderStatus, + id: &HeaderId, +) { + let mut current_number = id.0 + 1; + let mut current_parents = HashSet::new(); + current_parents.insert(id.1); + + while !current_parents.is_empty() { + let mut next_parents = HashSet::new(); + for source_queue in source_queues.iter_mut() { + let mut source_entry = match source_queue.entry(current_number) { + BTreeMapEntry::Occupied(source_entry) => source_entry, + BTreeMapEntry::Vacant(_) => continue, + }; + + let mut headers_to_move = Vec::new(); + let children_at_number = source_entry.get().keys().cloned().collect::>(); + for key in children_at_number { + let entry = match source_entry.get_mut().entry(key) { + HashMapEntry::Occupied(entry) => entry, + HashMapEntry::Vacant(_) => unreachable!("iterating existing keys; qed"), + }; + + if current_parents.contains(&entry.get().header().parent_hash) { + let header_to_move = entry.remove(); + let header_to_move_id = header_to_move.id(); + known_headers.entry(header_to_move_id.0).or_default().insert(header_to_move_id.1, destination_status); + headers_to_move.push((header_to_move_id, header_to_move)); + + log::debug!( + target: "bridge", + "Ethereum header {:?} is now {:?}", + header_to_move_id, + destination_status, + ); + } + } + + if source_entry.get().is_empty() { + source_entry.remove(); + } + + next_parents.extend(headers_to_move.iter().map(|(id, _)| id.1)); + + destination_queue + .entry(current_number) + .or_default() + .extend(headers_to_move.into_iter().map(|(id, h)| (id.1, h))) + } + + current_number = current_number + 1; + std::mem::swap(&mut current_parents, &mut next_parents); + } +} + +/// Return oldest header from the queue. +fn oldest_header(queue: &HeadersQueue) -> Option<&QueuedHeader> { + queue.values().flat_map(|h| h.values()).next() +} + +/// Return oldest headers from the queue until functor will return false. +fn oldest_headers(queue: &HeadersQueue, mut f: impl FnMut(&QueuedHeader) -> bool) -> Option> { + let result = queue.values() + .flat_map(|h| h.values()) + .take_while(|h| f(h)) + .collect::>(); + if result.is_empty() { + None + } else { + Some(result) + } +} + +/// Forget all headers with number less than given. +fn prune_queue(queue: &mut HeadersQueue, prune_border: u64) { + *queue = queue.split_off(&prune_border); +} + +/// Forget all known headers with number less than given. +fn prune_known_headers(known_headers: &mut KnownHeaders, prune_border: u64) { + let new_known_headers = known_headers.split_off(&prune_border); + for (pruned_number, pruned_headers) in &*known_headers { + for pruned_hash in pruned_headers.keys() { + log::debug!(target: "bridge", "Pruning header {:?}.", HeaderId(*pruned_number, *pruned_hash)); + } + } + *known_headers = new_known_headers; +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + + pub(crate) fn header(number: u64) -> QueuedHeader { + QueuedHeader::new(Header { + number: Some(number.into()), + hash: Some(hash(number)), + parent_hash: hash(number - 1), + ..Default::default() + }) + } + + pub(crate) fn hash(number: u64) -> H256 { + H256::from_low_u64_le(number) + } + + pub(crate) fn id(number: u64) -> HeaderId { + HeaderId(number, hash(number)) + } + + #[test] + fn total_headers_works() { + // total headers just sums up number of headers in every queue + let mut queue = QueuedHeaders::default(); + queue.maybe_orphan.entry(1).or_default().insert(hash(1), Default::default()); + queue.maybe_orphan.entry(1).or_default().insert(hash(2), Default::default()); + queue.maybe_orphan.entry(2).or_default().insert(hash(3), Default::default()); + queue.orphan.entry(3).or_default().insert(hash(4), Default::default()); + queue.maybe_receipts.entry(4).or_default().insert(hash(5), Default::default()); + queue.ready.entry(5).or_default().insert(hash(6), Default::default()); + assert_eq!(queue.total_headers(), 6); + } + + #[test] + fn best_queued_number_works() { + // initially there are headers in MaybeOrphan queue only + let mut queue = QueuedHeaders::default(); + queue.maybe_orphan.entry(1).or_default().insert(hash(1), Default::default()); + queue.maybe_orphan.entry(1).or_default().insert(hash(2), Default::default()); + queue.maybe_orphan.entry(3).or_default().insert(hash(3), Default::default()); + assert_eq!(queue.best_queued_number(), 3); + // and then there's better header in Orphan + queue.orphan.entry(10).or_default().insert(hash(10), Default::default()); + assert_eq!(queue.best_queued_number(), 10); + // and then there's better header in MaybeReceipts + queue.maybe_receipts.entry(20).or_default().insert(hash(20), Default::default()); + assert_eq!(queue.best_queued_number(), 20); + // and then there's better header in Ready + queue.ready.entry(30).or_default().insert(hash(30), Default::default()); + assert_eq!(queue.best_queued_number(), 30); + // and then there's better header in MaybeOrphan again + queue.maybe_orphan.entry(40).or_default().insert(hash(40), Default::default()); + assert_eq!(queue.best_queued_number(), 40); + } + + #[test] + fn status_works() { + // all headers are unknown initially + let mut queue = QueuedHeaders::default(); + assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); + // and status is read from the KnownHeaders + queue.known_headers.entry(10).or_default().insert(hash(10), HeaderStatus::Ready); + assert_eq!(queue.status(&id(10)), HeaderStatus::Ready); + } + + #[test] + fn header_works() { + // initially we have oldest header #10 + let mut queue = QueuedHeaders::default(); + queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); + assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(100)); + // inserting #20 changes nothing + queue.maybe_orphan.entry(20).or_default().insert(hash(1), header(101)); + assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(100)); + // inserting #5 makes it oldest + queue.maybe_orphan.entry(5).or_default().insert(hash(1), header(102)); + assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(102)); + } + + #[test] + fn header_response_works() { + // when parent is Synced, we insert to MaybeReceipts + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Synced); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + + // when parent is Ready, we insert to MaybeReceipts + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + + // when parent is Receipts, we insert to MaybeReceipts + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Receipts); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + + // when parent is MaybeReceipts, we insert to MaybeReceipts + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + + // when parent is Orphan, we insert to Orphan + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Orphan); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); + + // when parent is MaybeOrphan, we insert to MaybeOrphan + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); + + // when parent is unknown, we insert to MaybeOrphan + let mut queue = QueuedHeaders::default(); + queue.header_response(header(101).header().clone()); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); + } + + #[test] + fn ancestors_are_synced_on_substrate_best_header_response() { + // let's say someone else has submitted transaction to bridge that changes + // its best block to #100. At this time we have: + // #100 in MaybeOrphan + // #99 in Orphan + // #98 in MaybeReceipts + // #97 in Receipts + // #96 in Ready + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); + queue.known_headers.entry(99).or_default().insert(hash(99), HeaderStatus::Orphan); + queue.orphan.entry(99).or_default().insert(hash(99), header(99)); + queue.known_headers.entry(98).or_default().insert(hash(98), HeaderStatus::MaybeReceipts); + queue.maybe_receipts.entry(98).or_default().insert(hash(98), header(98)); + queue.known_headers.entry(97).or_default().insert(hash(97), HeaderStatus::Receipts); + queue.receipts.entry(97).or_default().insert(hash(97), header(97)); + queue.known_headers.entry(96).or_default().insert(hash(96), HeaderStatus::Ready); + queue.ready.entry(96).or_default().insert(hash(96), header(96)); + queue.substrate_best_header_response(&id(100)); + + // then the #100 and all ancestors of #100 (#96..#99) are treated as synced + assert!(queue.maybe_orphan.is_empty()); + assert!(queue.orphan.is_empty()); + assert!(queue.maybe_receipts.is_empty()); + assert!(queue.receipts.is_empty()); + assert!(queue.ready.is_empty()); + assert_eq!(queue.known_headers.len(), 5); + assert!(queue.known_headers.values().all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); + } + + #[test] + fn descendants_are_moved_on_substrate_best_header_response() { + // let's say someone else has submitted transaction to bridge that changes + // its best block to #100. At this time we have: + // #101 in Orphan + // #102 in MaybeOrphan + // #103 in Orphan + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Orphan); + queue.orphan.entry(101).or_default().insert(hash(101), header(101)); + queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); + queue.known_headers.entry(103).or_default().insert(hash(103), HeaderStatus::Orphan); + queue.orphan.entry(103).or_default().insert(hash(103), header(103)); + queue.substrate_best_header_response(&id(100)); + + // all descendants are moved to MaybeReceipts + assert!(queue.maybe_orphan.is_empty()); + assert!(queue.orphan.is_empty()); + assert_eq!(queue.maybe_receipts.len(), 3); + assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeReceipts); + assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeReceipts); + assert_eq!(queue.known_headers[&103][&hash(103)], HeaderStatus::MaybeReceipts); + } + + #[test] + fn positive_maybe_orphan_response_works() { + // let's say we have: + // #100 in MaybeOrphan + // #101 in Orphan + // #102 in MaybeOrphan + // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) + // and the response is: YES, #99 is known to the Substrate runtime + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); + queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Orphan); + queue.orphan.entry(101).or_default().insert(hash(101), header(101)); + queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); + queue.maybe_orphan_response(&id(99), true); + + // then all headers (#100..#103) are moved to the MaybeReceipts queue + assert!(queue.orphan.is_empty()); + assert!(queue.maybe_orphan.is_empty()); + assert_eq!(queue.maybe_receipts.len(), 3); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::MaybeReceipts); + assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeReceipts); + assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeReceipts); + } + + #[test] + fn negative_maybe_orphan_response_works() { + // let's say we have: + // #100 in MaybeOrphan + // #101 in MaybeOrphan + // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) + // and the response is: NO, #99 is NOT known to the Substrate runtime + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); + queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(101).or_default().insert(hash(101), header(101)); + queue.maybe_orphan_response(&id(99), false); + + // then all headers (#100..#101) are moved to the Orphan queue + assert!(queue.maybe_orphan.is_empty()); + assert_eq!(queue.orphan.len(), 2); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Orphan); + assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::Orphan); + } + + #[test] + fn positive_maybe_receipts_response_works() { + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); + queue.maybe_receipts.entry(100).or_default().insert(hash(100), header(100)); + queue.maybe_receipts_response(&id(100), true); + assert!(queue.maybe_receipts.is_empty()); + assert_eq!(queue.receipts.len(), 1); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Receipts); + } + + #[test] + fn negative_maybe_receipts_response_works() { + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); + queue.maybe_receipts.entry(100).or_default().insert(hash(100), header(100)); + queue.maybe_receipts_response(&id(100), false); + assert!(queue.maybe_receipts.is_empty()); + assert_eq!(queue.ready.len(), 1); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); + } + + #[test] + fn receipts_response_works() { + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Receipts); + queue.receipts.entry(100).or_default().insert(hash(100), header(100)); + queue.receipts_response(&id(100), Vec::new()); + assert!(queue.receipts.is_empty()); + assert_eq!(queue.ready.len(), 1); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); + } + + #[test] + fn header_submitted_works() { + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue.ready.entry(100).or_default().insert(hash(100), header(100)); + queue.headers_submitted(vec![id(100)]); + assert!(queue.ready.is_empty()); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Submitted); + } + + #[test] + fn prune_works() { + let mut queue = QueuedHeaders::default(); + queue.known_headers.entry(104).or_default().insert(hash(104), HeaderStatus::MaybeOrphan); + queue.maybe_orphan.entry(104).or_default().insert(hash(104), header(104)); + queue.known_headers.entry(103).or_default().insert(hash(103), HeaderStatus::Orphan); + queue.orphan.entry(103).or_default().insert(hash(103), header(103)); + queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeReceipts); + queue.maybe_receipts.entry(102).or_default().insert(hash(102), header(102)); + queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Receipts); + queue.receipts.entry(101).or_default().insert(hash(101), header(101)); + queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue.ready.entry(100).or_default().insert(hash(100), header(100)); + + queue.prune(102); + + assert_eq!(queue.ready.len(), 0); + assert_eq!(queue.receipts.len(), 0); + assert_eq!(queue.maybe_receipts.len(), 1); + assert_eq!(queue.orphan.len(), 1); + assert_eq!(queue.maybe_orphan.len(), 1); + assert_eq!(queue.known_headers.len(), 3); + + queue.prune(110); + + assert_eq!(queue.ready.len(), 0); + assert_eq!(queue.receipts.len(), 0); + assert_eq!(queue.maybe_receipts.len(), 0); + assert_eq!(queue.orphan.len(), 0); + assert_eq!(queue.maybe_orphan.len(), 0); + assert_eq!(queue.known_headers.len(), 0); + + queue.header_response(header(109).header().clone()); + assert_eq!(queue.known_headers.len(), 0); + + queue.header_response(header(110).header().clone()); + assert_eq!(queue.known_headers.len(), 1); + } +} diff --git a/relays/ethereum/src/ethereum_sync.rs b/relays/ethereum/src/ethereum_sync.rs new file mode 100644 index 0000000000000..93ed761bd01ca --- /dev/null +++ b/relays/ethereum/src/ethereum_sync.rs @@ -0,0 +1,311 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use codec::Encode; +use crate::ethereum_headers::QueuedHeaders; +use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; +use crate::ethereum_sync_loop::EthereumSyncParams; +use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; + +/// Ethereum headers synchronization context. +#[derive(Debug)] +pub struct HeadersSync { + /// Synchronization parameters. + params: EthereumSyncParams, + /// Best header number known to Ethereum node. + target_header_number: Option, + /// Best header known to Substrate node. + best_header: Option, + /// Headers queue. + headers: QueuedHeaders, +} + +impl HeadersSync { + /// Creates new Ethereum headers synchronizer. + pub fn new(params: EthereumSyncParams) -> Self { + HeadersSync { + params, + target_header_number: None, + best_header: None, + headers: Default::default(), + } + } + + /// Returns true if we have synced almost all known headers. + pub fn is_almost_synced(&self) -> bool { + match self.target_header_number { + Some(target_header_number) => self.best_header + .map(|best| target_header_number.saturating_sub(best.0) < 4) + .unwrap_or(false), + None => true, + } + } + + /// Returns synchronization status. + pub fn status(&self) -> (&Option, &Option) { + (&self.best_header, &self.target_header_number) + } + + /// Returns reference to the headers queue. + pub fn headers(&self) -> &QueuedHeaders { + &self.headers + } + + /// Returns mutable reference to the headers queue. + pub fn headers_mut(&mut self) -> &mut QueuedHeaders { + &mut self.headers + } + + /// Select header that needs to be downloaded from the Ethereum node. + pub fn select_new_header_to_download(&self) -> Option { + // if we haven't received best header from Ethereum node yet, there's nothing we can download + let target_header_number = self.target_header_number.clone()?; + + // if we haven't received known best header from Substrate node yet, there's nothing we can download + let best_header = self.best_header.as_ref()?; + + // if there's too many headers in the queue, stop downloading + let in_memory_headers = self.headers.total_headers(); + if in_memory_headers >= self.params.max_future_headers_to_download { + return None; + } + + // we assume that there were no reorgs if we have already downloaded best header + let best_downloaded_number = std::cmp::max( + self.headers.best_queued_number(), + best_header.0, + ); + if best_downloaded_number == target_header_number { + return None; + } + + // download new header + Some(best_downloaded_number + 1) + } + + /// Select headers that need to be submitted to the Substrate node. + pub fn select_headers_to_submit(&self) -> Option> { + let headers_in_submit_status = self.headers.headers_in_status(HeaderStatus::Submitted); + let headers_to_submit_count = self.params.max_headers_in_submitted_status + .checked_sub(headers_in_submit_status)?; + + let mut total_size = 0; + let mut total_headers = 0; + self.headers.headers(HeaderStatus::Ready, |header| { + if total_headers == headers_to_submit_count { + return false; + } + if total_headers == self.params.max_headers_in_single_submit { + return false; + } + + let encoded_size = into_substrate_ethereum_header(header.header()).encode().len() + + into_substrate_ethereum_receipts(header.receipts()).map(|receipts| receipts.encode().len()) + .unwrap_or(0); + if total_headers != 0 && total_size + encoded_size > self.params.max_headers_size_in_single_submit { + return false; + } + + total_size += encoded_size; + total_headers += 1; + + true + }) + } + + /// Receive new target header number from the Ethereum node. + pub fn ethereum_best_header_number_response(&mut self, best_header_number: u64) { + log::debug!(target: "bridge", "Received best header number from Ethereum: {}", best_header_number); + self.target_header_number = Some(best_header_number); + } + + /// Receive new best header from the Substrate node. + /// Returns true if it is different from the previous block known to us. + pub fn substrate_best_header_response(&mut self, best_header: HeaderId) -> bool { + log::debug!(target: "bridge", "Received best known header from Substrate: {:?}", best_header); + + // early return if it is still the same + if self.best_header == Some(best_header) { + return false; + } + + // remember that this header is now known to the Substrate runtime + self.headers.substrate_best_header_response(&best_header); + + // prune ancient headers + self.headers.prune(best_header.0.saturating_sub(self.params.prune_depth)); + + // finally remember the best header itself + self.best_header = Some(best_header); + + true + } + + /// Restart synchronization. + pub fn restart(&mut self) { + self.target_header_number = None; + self.best_header = None; + self.headers.clear(); + } +} + +#[cfg(test)] +mod tests { + use crate::ethereum_headers::tests::{header, id}; + use crate::ethereum_types::{H256, HeaderStatus}; + use super::*; + + fn side_hash(number: u64) -> H256 { + H256::from_low_u64_le(1000 + number) + } + + #[test] + fn select_new_header_to_download_works() { + let mut eth_sync = HeadersSync::new(Default::default()); + + // both best && target headers are unknown + assert_eq!(eth_sync.select_new_header_to_download(), None); + + // best header is known, target header is unknown + eth_sync.best_header = Some(HeaderId(0, Default::default())); + assert_eq!(eth_sync.select_new_header_to_download(), None); + + // target header is known, best header is unknown + eth_sync.best_header = None; + eth_sync.target_header_number = Some(100); + assert_eq!(eth_sync.select_new_header_to_download(), None); + + // when our best block has the same number as the target + eth_sync.best_header = Some(HeaderId(100, Default::default())); + assert_eq!(eth_sync.select_new_header_to_download(), None); + + // when we actually need a new header + eth_sync.target_header_number = Some(101); + assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); + + // when there are too many headers scheduled for submitting + for i in 1..1000 { + eth_sync.headers.header_response(header(i).header().clone()); + } + assert_eq!(eth_sync.select_new_header_to_download(), None); + } + + #[test] + fn sync_without_reorgs_works() { + let mut eth_sync = HeadersSync::new(Default::default()); + eth_sync.params.max_headers_in_submitted_status = 1; + + // ethereum reports best header #102 + eth_sync.ethereum_best_header_number_response(102); + + // substrate reports that it is at block #100 + eth_sync.substrate_best_header_response(id(100)); + + // block #101 is downloaded first + assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); + eth_sync.headers.header_response(header(101).header().clone()); + + // now header #101 is ready to be submitted + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(101))); + eth_sync.headers.maybe_receipts_response(&id(101), false); + assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(101))); + assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(101)])); + + // and header #102 is ready to be downloaded + assert_eq!(eth_sync.select_new_header_to_download(), Some(102)); + eth_sync.headers.header_response(header(102).header().clone()); + + // receive submission confirmation + eth_sync.headers.headers_submitted(vec![id(101)]); + + // we have nothing to submit because previous header hasn't been confirmed yet + // (and we allow max 1 submit transaction in the wild) + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(102))); + eth_sync.headers.maybe_receipts_response(&id(102), false); + assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(102))); + assert_eq!(eth_sync.select_headers_to_submit(), None); + + // substrate reports that it has imported block #101 + eth_sync.substrate_best_header_response(id(101)); + + // and we are ready to submit #102 + assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(102)])); + eth_sync.headers.headers_submitted(vec![id(102)]); + + // substrate reports that it has imported block #102 + eth_sync.substrate_best_header_response(id(102)); + + // and we have nothing to download + assert_eq!(eth_sync.select_new_header_to_download(), None); + } + + #[test] + fn sync_with_orphan_headers_work() { + let mut eth_sync = HeadersSync::new(Default::default()); + + // ethereum reports best header #102 + eth_sync.ethereum_best_header_number_response(102); + + // substrate reports that it is at block #100, but it isn't part of best chain + eth_sync.substrate_best_header_response(HeaderId(100, side_hash(100))); + + // block #101 is downloaded first + assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); + eth_sync.headers.header_response(header(101).header().clone()); + + // we can't submit header #101, because its parent status is unknown + assert_eq!(eth_sync.select_headers_to_submit(), None); + + // instead we are trying to determine status of its parent (#100) + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeOrphan), Some(&header(101))); + + // and the status is still unknown + eth_sync.headers.maybe_orphan_response(&id(100), false); + + // so we consider #101 orphaned now && will download its parent - #100 + assert_eq!(eth_sync.headers.header(HeaderStatus::Orphan), Some(&header(101))); + eth_sync.headers.header_response(header(100).header().clone()); + + // we can't submit header #100, because its parent status is unknown + assert_eq!(eth_sync.select_headers_to_submit(), None); + + // instead we are trying to determine status of its parent (#99) + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeOrphan), Some(&header(100))); + + // and the status is known, so we move previously orphaned #100 and #101 to ready queue + eth_sync.headers.maybe_orphan_response(&id(99), true); + + // and we are ready to submit #100 + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(100))); + eth_sync.headers.maybe_receipts_response(&id(100), false); + assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(100)])); + eth_sync.headers.headers_submitted(vec![id(100)]); + + // and we are ready to submit #101 + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(101))); + eth_sync.headers.maybe_receipts_response(&id(101), false); + assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(101)])); + eth_sync.headers.headers_submitted(vec![id(101)]); + } + + #[test] + fn pruning_happens_on_substrate_best_header_response() { + let mut eth_sync = HeadersSync::new(Default::default()); + eth_sync.params.prune_depth = 50; + eth_sync.substrate_best_header_response(id(100)); + assert_eq!(eth_sync.headers.prune_border(), 50); + } +} diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs new file mode 100644 index 0000000000000..59fae12ad3330 --- /dev/null +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -0,0 +1,486 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use futures::{future::FutureExt, stream::StreamExt}; +use crate::ethereum_client; +use crate::ethereum_types::HeaderStatus as EthereumHeaderStatus; +use crate::substrate_client; + +// TODO: when SharedClient will be available, switch to Substrate headers subscription +// (because we do not need old Substrate headers) + +/// Interval (in ms) at which we check new Ethereum headers when we are synced/almost synced. +const ETHEREUM_TICK_INTERVAL_MS: u64 = 10_000; +/// Interval (in ms) at which we check new Substrate blocks. +const SUBSTRATE_TICK_INTERVAL_MS: u64 = 5_000; +/// When we submit Ethereum headers to Substrate runtime, but see no updates of best +/// Ethereum block known to Substrate runtime during STALL_SYNC_TIMEOUT_MS milliseconds, +/// we consider that our headers are rejected because there has been reorg in Substrate. +/// This reorg could invalidate our knowledge about sync process (i.e. we have asked if +/// HeaderA is known to Substrate, but then reorg happened and the answer is different +/// now) => we need to reset sync. +/// The other option is to receive **EVERY** best Substrate header and check if it is +/// direct child of previous best header. But: (1) subscription doesn't guarantee that +/// the subscriber will receive every best header (2) reorg won't always lead to sync +/// stall and restart is a heavy operation (we forget all in-memory headers). +const STALL_SYNC_TIMEOUT_MS: u64 = 30_000; +/// Delay (in milliseconds) after connection-related error happened before we'll try +/// reconnection again. +const CONNECTION_ERROR_DELAY_MS: u64 = 10_000; + +/// Error type that can signal connection errors. +pub trait MaybeConnectionError { + /// Returns true if error (maybe) represents connection error. + fn is_connection_error(&self) -> bool; +} + +/// Ethereum synchronization parameters. +pub struct EthereumSyncParams { + /// Ethereum RPC host. + pub eth_host: String, + /// Ethereum RPC port. + pub eth_port: u16, + /// Substrate RPC host. + pub sub_host: String, + /// Substrate RPC port. + pub sub_port: u16, + /// Substrate transactions signer. + pub sub_signer: sp_core::sr25519::Pair, + /// Maximal number of ethereum headers to pre-download. + pub max_future_headers_to_download: usize, + /// Maximal number of active (we believe) submit header transactions. + pub max_headers_in_submitted_status: usize, + /// Maximal number of headers in single submit request. + pub max_headers_in_single_submit: usize, + /// Maximal total headers size in single submit request. + pub max_headers_size_in_single_submit: usize, + /// We only may store and accept (from Ethereum node) headers that have + /// number >= than best_substrate_header.number - prune_depth. + pub prune_depth: u64, +} + +impl std::fmt::Debug for EthereumSyncParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("EthereumSyncParams") + .field("eth_host", &self.eth_host) + .field("eth_port", &self.eth_port) + .field("sub_host", &self.sub_port) + .field("sub_port", &self.sub_port) + .field("max_future_headers_to_download", &self.max_future_headers_to_download) + .field("max_headers_in_submitted_status", &self.max_headers_in_submitted_status) + .field("max_headers_in_single_submit", &self.max_headers_in_single_submit) + .field("max_headers_size_in_single_submit", &self.max_headers_size_in_single_submit) + .field("prune_depth", &self.prune_depth) + .finish() + } +} + +impl Default for EthereumSyncParams { + fn default() -> Self { + EthereumSyncParams { + eth_host: "localhost".into(), + eth_port: 8545, + sub_host: "localhost".into(), + sub_port: 9933, + sub_signer: sp_keyring::AccountKeyring::Alice.pair(), + max_future_headers_to_download: 128, + max_headers_in_submitted_status: 128, + max_headers_in_single_submit: 32, + max_headers_size_in_single_submit: 131_072, + prune_depth: 4096, + } + } +} + +/// Run Ethereum headers synchronization. +pub fn run(params: EthereumSyncParams) { + let mut local_pool = futures::executor::LocalPool::new(); + let mut progress_context = (std::time::Instant::now(), None, None); + + local_pool.run_until(async move { + let eth_uri = format!("http://{}:{}", params.eth_host, params.eth_port); + let sub_uri = format!("http://{}:{}", params.sub_host, params.sub_port); + let sub_signer = params.sub_signer.clone(); + + let mut eth_sync = crate::ethereum_sync::HeadersSync::new(params); + let mut stall_countdown = None; + + let mut eth_maybe_client = None; + let mut eth_best_block_number_required = false; + let eth_best_block_number_future = ethereum_client::best_block_number( + ethereum_client::client(ð_uri) + ).fuse(); + let eth_new_header_future = futures::future::Fuse::terminated(); + let eth_orphan_header_future = futures::future::Fuse::terminated(); + let eth_receipts_future = futures::future::Fuse::terminated(); + let eth_go_offline_future = futures::future::Fuse::terminated(); + let eth_tick_stream = interval(ETHEREUM_TICK_INTERVAL_MS).fuse(); + + let mut sub_maybe_client = None; + let mut sub_best_block_required = false; + let sub_best_block_future = substrate_client::best_ethereum_block( + substrate_client::client(&sub_uri, sub_signer), + ).fuse(); + let sub_receipts_check_future = futures::future::Fuse::terminated(); + let sub_existence_status_future = futures::future::Fuse::terminated(); + let sub_submit_header_future = futures::future::Fuse::terminated(); + let sub_go_offline_future = futures::future::Fuse::terminated(); + let sub_tick_stream = interval(SUBSTRATE_TICK_INTERVAL_MS).fuse(); + + futures::pin_mut!( + eth_best_block_number_future, + eth_new_header_future, + eth_orphan_header_future, + eth_receipts_future, + eth_go_offline_future, + eth_tick_stream, + sub_best_block_future, + sub_receipts_check_future, + sub_existence_status_future, + sub_submit_header_future, + sub_go_offline_future, + sub_tick_stream + ); + + loop { + futures::select! { + (eth_client, eth_best_block_number) = eth_best_block_number_future => { + eth_best_block_number_required = false; + + process_future_result( + &mut eth_maybe_client, + eth_client, + eth_best_block_number, + |eth_best_block_number| eth_sync.ethereum_best_header_number_response(eth_best_block_number), + &mut eth_go_offline_future, + |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), + "Error retrieving best header number from Ethereum number", + ); + }, + (eth_client, eth_new_header) = eth_new_header_future => { + process_future_result( + &mut eth_maybe_client, + eth_client, + eth_new_header, + |eth_new_header| eth_sync.headers_mut().header_response(eth_new_header), + &mut eth_go_offline_future, + |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), + "Error retrieving header from Ethereum node", + ); + }, + (eth_client, eth_orphan_header) = eth_orphan_header_future => { + process_future_result( + &mut eth_maybe_client, + eth_client, + eth_orphan_header, + |eth_orphan_header| eth_sync.headers_mut().header_response(eth_orphan_header), + &mut eth_go_offline_future, + |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), + "Error retrieving orphan header from Ethereum node", + ); + }, + (eth_client, eth_receipts) = eth_receipts_future => { + process_future_result( + &mut eth_maybe_client, + eth_client, + eth_receipts, + |(header, receipts)| eth_sync.headers_mut().receipts_response(&header, receipts), + &mut eth_go_offline_future, + |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), + "Error retrieving transactions receipts from Ethereum node", + ); + }, + eth_client = eth_go_offline_future => { + eth_maybe_client = Some(eth_client); + }, + _ = eth_tick_stream.next() => { + if eth_sync.is_almost_synced() { + eth_best_block_number_required = true; + } + }, + (sub_client, sub_best_block) = sub_best_block_future => { + sub_best_block_required = false; + + process_future_result( + &mut sub_maybe_client, + sub_client, + sub_best_block, + |sub_best_block| { + let head_updated = eth_sync.substrate_best_header_response(sub_best_block); + match head_updated { + // IF head is updated AND there are still our transactions: + // => restart stall countdown timer + true if eth_sync.headers().headers_in_status(EthereumHeaderStatus::Submitted) != 0 => + stall_countdown = Some(std::time::Instant::now()), + // IF head is updated AND there are no our transactions: + // => stop stall countdown timer + true => stall_countdown = None, + // IF head is not updated AND stall countdown is not yet completed + // => do nothing + false if stall_countdown + .map(|stall_countdown| std::time::Instant::now() - stall_countdown < + std::time::Duration::from_millis(STALL_SYNC_TIMEOUT_MS)) + .unwrap_or(true) + => (), + // IF head is not updated AND stall countdown has completed + // => restart sync + false => { + log::info!( + target: "bridge", + "Possible Substrate fork detected. Restarting Ethereum headers synchronization.", + ); + stall_countdown = None; + eth_sync.restart(); + }, + } + }, + &mut sub_go_offline_future, + |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), + "Error retrieving best known header from Substrate node", + ); + }, + (sub_client, sub_existence_status) = sub_existence_status_future => { + process_future_result( + &mut sub_maybe_client, + sub_client, + sub_existence_status, + |(sub_header, sub_existence_status)| eth_sync + .headers_mut() + .maybe_orphan_response(&sub_header, sub_existence_status), + &mut sub_go_offline_future, + |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), + "Error retrieving existence status from Substrate node", + ); + }, + (sub_client, sub_submit_header_result) = sub_submit_header_future => { + process_future_result( + &mut sub_maybe_client, + sub_client, + sub_submit_header_result, + |(_, submitted_headers)| eth_sync.headers_mut().headers_submitted(submitted_headers), + &mut sub_go_offline_future, + |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), + "Error submitting headers to Substrate node", + ); + }, + (sub_client, sub_receipts_check_result) = sub_receipts_check_future => { + // we can minimize number of receipts_check calls by checking header + // logs bloom here, but it may give us false positives (when authorities + // source is contract, we never need any logs) + process_future_result( + &mut sub_maybe_client, + sub_client, + sub_receipts_check_result, + |(header, receipts_check_result)| eth_sync + .headers_mut() + .maybe_receipts_response(&header, receipts_check_result), + &mut sub_go_offline_future, + |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), + "Error retrieving receipts requirement from Substrate node", + ); + }, + sub_client = sub_go_offline_future => { + sub_maybe_client = Some(sub_client); + }, + _ = sub_tick_stream.next() => { + sub_best_block_required = true; + }, + } + + // print progress + progress_context = print_progress(progress_context, ð_sync); + + // if client is available: wait, or call Substrate RPC methods + if let Some(sub_client) = sub_maybe_client.take() { + // the priority is to: + // 1) get best block - it stops us from downloading/submitting new blocks + we call it rarely; + // 2) check transactions receipts - it stops us from downloading/submitting new blocks; + // 3) check existence - it stops us from submitting new blocks; + // 4) submit header + + if sub_best_block_required { + log::debug!(target: "bridge", "Asking Substrate about best block"); + sub_best_block_future.set(substrate_client::best_ethereum_block(sub_client).fuse()); + } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::MaybeReceipts) { + log::debug!( + target: "bridge", + "Checking if header submission requires receipts: {:?}", + header.id(), + ); + + let header = header.clone(); + sub_receipts_check_future.set( + substrate_client::ethereum_receipts_required(sub_client, header).fuse() + ); + } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::MaybeOrphan) { + // for MaybeOrphan we actually ask for parent' header existence + let parent_id = header.parent_id(); + + log::debug!( + target: "bridge", + "Asking Substrate node for existence of: {:?}", + parent_id, + ); + + sub_existence_status_future.set( + substrate_client::ethereum_header_known(sub_client, parent_id).fuse(), + ); + } else if let Some(headers) = eth_sync.select_headers_to_submit() { + let ids = match headers.len() { + 1 => format!("{:?}", headers[0].id()), + 2 => format!("[{:?}, {:?}]", headers[0].id(), headers[1].id()), + len => format!("[{:?} ... {:?}]", headers[0].id(), headers[len - 1].id()), + }; + log::debug!( + target: "bridge", + "Submitting {} header(s) to Substrate node: {:?}", + headers.len(), + ids, + ); + + let headers = headers.into_iter().cloned().collect(); + sub_submit_header_future.set( + substrate_client::submit_ethereum_headers(sub_client, headers).fuse(), + ); + + // remember that we have submitted some headers + if stall_countdown.is_none() { + stall_countdown = Some(std::time::Instant::now()); + } + } else { + sub_maybe_client = Some(sub_client); + } + } + + // if client is available: wait, or call Ethereum RPC methods + if let Some(eth_client) = eth_maybe_client.take() { + // the priority is to: + // 1) get best block - it stops us from downloading new blocks + we call it rarely; + // 2) check transactions receipts - it stops us from downloading/submitting new blocks; + // 3) check existence - it stops us from submitting new blocks; + // 4) submit header + + if eth_best_block_number_required { + log::debug!(target: "bridge", "Asking Ethereum node about best block number"); + eth_best_block_number_future.set(ethereum_client::best_block_number(eth_client).fuse()); + } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::Receipts) { + let id = header.id(); + log::debug!( + target: "bridge", + "Retrieving receipts for header: {:?}", + id, + ); + eth_receipts_future.set( + ethereum_client::transactions_receipts( + eth_client, + id, + header.header().transactions.clone(), + ).fuse() + ); + } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::Orphan) { + // for Orphan we actually ask for parent' header + let parent_id = header.parent_id(); + + log::debug!( + target: "bridge", + "Going to download orphan header from Ethereum node: {:?}", + parent_id, + ); + + eth_orphan_header_future.set( + ethereum_client::header_by_hash(eth_client, parent_id.1).fuse(), + ); + } else if let Some(id) = eth_sync.select_new_header_to_download() { + log::debug!( + target: "bridge", + "Going to download new header from Ethereum node: {:?}", + id, + ); + + eth_new_header_future.set( + ethereum_client::header_by_number(eth_client, id).fuse(), + ); + } else { + eth_maybe_client = Some(eth_client); + } + } + } + }); +} + +fn print_progress( + progress_context: (std::time::Instant, Option, Option), + eth_sync: &crate::ethereum_sync::HeadersSync, +) -> (std::time::Instant, Option, Option) { + let (prev_time, prev_best_header, prev_target_header) = progress_context; + let now_time = std::time::Instant::now(); + let (now_best_header, now_target_header) = eth_sync.status(); + + let need_update = now_time - prev_time > std::time::Duration::from_secs(10) + || match (prev_best_header, now_best_header) { + (Some(prev_best_header), Some(now_best_header)) => now_best_header.0.saturating_sub(prev_best_header) > 10, + _ => false, + }; + if !need_update { + return (prev_time, prev_best_header, prev_target_header); + } + + log::info!( + target: "bridge", + "Synced {:?} of {:?} headers", + now_best_header.map(|id| id.0), + now_target_header, + ); + (now_time, now_best_header.clone().map(|id| id.0), *now_target_header) +} + +async fn delay(timeout_ms: u64, retval: T) -> T { + async_std::task::sleep(std::time::Duration::from_millis(timeout_ms)).await; + retval +} + +fn interval(timeout_ms: u64) -> impl futures::Stream { + futures::stream::unfold((), move |_| async move { delay(timeout_ms, ()).await; Some(((), ())) }) +} + +fn process_future_result( + maybe_client: &mut Option, + client: TClient, + result: Result, + on_success: impl FnOnce(TResult), + go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, + go_offline: impl FnOnce(TClient) -> TGoOfflineFuture, + error_pattern: &'static str, +) where + TError: std::fmt::Debug + MaybeConnectionError, + TGoOfflineFuture: FutureExt, +{ + match result { + Ok(result) => { + *maybe_client = Some(client); + on_success(result); + }, + Err(error) => { + if error.is_connection_error() { + go_offline_future.set(go_offline(client).fuse()); + } else { + *maybe_client = Some(client); + } + + log::error!(target: "bridge", "{}: {:?}", error_pattern, error); + }, + } +} diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs new file mode 100644 index 0000000000000..c5aaaf0531785 --- /dev/null +++ b/relays/ethereum/src/ethereum_types.rs @@ -0,0 +1,110 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +pub use web3::types::{Bytes, H256, U128, U64}; + +/// When header is just received from the Ethereum node, we check that it has +/// both number and hash fields filled. +pub const HEADER_ID_PROOF: &'static str = "checked on retrieval; qed"; + +/// When receipt is just received from the Ethereum node, we check that it has +/// gas_used field filled. +pub const RECEIPT_GAS_USED_PROOF: &'static str = "checked on retrieval; qed"; + +/// Ethereum header type. +pub type Header = web3::types::Block; + +/// Ethereum transaction receipt type. +pub type Receipt = web3::types::TransactionReceipt; + +/// Ethereum header Id. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct HeaderId(pub u64, pub H256); + +impl From<&Header> for HeaderId { + fn from(header: &Header) -> HeaderId { + HeaderId(header.number.expect(HEADER_ID_PROOF).as_u64(), header.hash.expect(HEADER_ID_PROOF)) + } +} + +/// Ethereum header synchronization status. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum HeaderStatus { + /// Header is unknown. + Unknown, + /// Header is in MaybeOrphan queue. + MaybeOrphan, + /// Header is in Orphan queue. + Orphan, + /// Header is in MaybeReceipts queue. + MaybeReceipts, + /// Header is in Receipts queue. + Receipts, + /// Header is in Ready queue. + Ready, + /// Header has been recently submitted to the Substrate runtime. + Submitted, + /// Header is known to the Substrate runtime. + Synced, +} + +#[derive(Clone, Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] +pub struct QueuedHeader { + header: Header, + receipts: Option>, +} + +impl QueuedHeader { + /// Creates new queued header. + pub fn new(header: Header) -> Self { + QueuedHeader { header, receipts: None } + } + + /// Returns ID of header. + pub fn id(&self) -> HeaderId { + (&self.header).into() + } + + /// Returns ID of parent header. + pub fn parent_id(&self) -> HeaderId { + HeaderId( + self.header.number.expect(HEADER_ID_PROOF).as_u64() - 1, + self.header.parent_hash, + ) + } + + /// Returns reference to header. + pub fn header(&self) -> &Header { + &self.header + } + + /// Returns reference to transactions receipts. + pub fn receipts(&self) -> &Option> { + &self.receipts + } + + /// Extract header and receipts from self. + pub fn extract(self) -> (Header, Option>) { + (self.header, self.receipts) + } + + /// Set associated transaction receipts. + pub fn set_receipts(mut self, receipts: Vec) -> Self { + self.receipts = Some(receipts); + self + } +} diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs new file mode 100644 index 0000000000000..de9546bfa6fdb --- /dev/null +++ b/relays/ethereum/src/main.rs @@ -0,0 +1,102 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +#![recursion_limit="1024"] + +mod ethereum_client; +mod ethereum_headers; +mod ethereum_sync; +mod ethereum_sync_loop; +mod ethereum_types; +mod substrate_client; +mod substrate_types; + +use std::io::Write; +use sp_core::crypto::Pair; + +fn main() { + initialize(); + + ethereum_sync_loop::run(match ethereum_sync_params() { + Ok(ethereum_sync_params) => ethereum_sync_params, + Err(err) => { + log::error!(target: "bridge", "Error parsing parameters: {}", err); + return; + }, + }); +} + +fn initialize() { + let mut builder = env_logger::Builder::new(); + + let filters = match std::env::var("RUST_LOG") { + Ok(env_filters) => format!("bridge=info,{}", env_filters), + Err(_) => "bridge=info".into(), + }; + + builder.parse_filters(&filters); + builder.format(move |buf, record| { + writeln!(buf, "{}", { + let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()) + .expect("Time is incorrectly formatted"); + if cfg!(windows) { + format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) + } else { + use ansi_term::Colour as Color; + let log_level = match record.level() { + log::Level::Error => Color::Fixed(9).bold().paint(record.level().to_string()), + log::Level::Warn => Color::Fixed(11).bold().paint(record.level().to_string()), + log::Level::Info => Color::Fixed(10).paint(record.level().to_string()), + log::Level::Debug => Color::Fixed(14).paint(record.level().to_string()), + log::Level::Trace => Color::Fixed(12).paint(record.level().to_string()), + }; + format!("{} {} {} {}" + , Color::Fixed(8).bold().paint(timestamp) + , log_level + , Color::Fixed(8).paint(record.target()) + , record.args()) + } + }) + }); + + builder.init(); +} + +fn ethereum_sync_params() -> Result { + let yaml = clap::load_yaml!("cli.yml"); + let matches = clap::App::from_yaml(yaml).get_matches(); + + let mut eth_sync_params = ethereum_sync_loop::EthereumSyncParams::default(); + if let Some(eth_host) = matches.value_of("eth-host") { + eth_sync_params.eth_host = eth_host.into(); + } + if let Some(eth_port) = matches.value_of("eth-port") { + eth_sync_params.eth_port = eth_port.parse().map_err(|e| format!("{}", e))?; + } + if let Some(sub_host) = matches.value_of("sub-host") { + eth_sync_params.sub_host = sub_host.into(); + } + if let Some(sub_port) = matches.value_of("sub-port") { + eth_sync_params.sub_port = sub_port.parse().map_err(|e| format!("{}", e))?; + } + if let Some(sub_signer) = matches.value_of("sub-signer") { + let sub_signer_password = matches.value_of("sub-signer-password"); + eth_sync_params.sub_signer = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) + .map_err(|e| format!("{:?}", e))?; + } + + Ok(eth_sync_params) +} diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs new file mode 100644 index 0000000000000..f66395b1cd369 --- /dev/null +++ b/relays/ethereum/src/substrate_client.rs @@ -0,0 +1,320 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use codec::{Encode, Decode}; +use jsonrpsee_core::{client::ClientError, common::Params}; +use jsonrpsee_http::{HttpClient, RequestError, http_client}; +use serde_json::{from_value, to_value}; +use sp_core::crypto::Pair; +use sp_runtime::traits::IdentifyAccount; +use crate::ethereum_sync_loop::MaybeConnectionError; +use crate::ethereum_types::{ + Bytes, + H256, + HeaderId as EthereumHeaderId, + QueuedHeader as QueuedEthereumHeader, +}; +use crate::substrate_types::{ + TransactionHash, + into_substrate_ethereum_header, + into_substrate_ethereum_receipts, +}; + +/// Substrate client type. +pub struct Client { + /// Substrate RPC client. + rpc_client: HttpClient, + /// Transactions signer. + signer: sp_core::sr25519::Pair, + /// Genesis block hash. + genesis_hash: Option, +} + +/// All possible errors that can occur during interacting with Ethereum node. +#[derive(Debug)] +pub enum Error { + /// Request start failed. + StartRequestFailed(RequestError), + /// Request not found (should never occur?). + RequestNotFound, + /// Failed to receive response. + ResponseRetrievalFailed(ClientError), + /// Failed to parse response. + ResponseParseFailed, +} + +impl MaybeConnectionError for Error { + fn is_connection_error(&self) -> bool { + match *self { + Error::StartRequestFailed(_) | Error::ResponseRetrievalFailed(_) => true, + _ => false, + } + } +} + +/// Returns client that is able to call RPCs on Substrate node. +pub fn client(uri: &str, signer: sp_core::sr25519::Pair) -> Client { + Client { + rpc_client: http_client(uri), + signer, + genesis_hash: None, + } +} + +/// Returns best Ethereum block that Substrate runtime knows of. +pub async fn best_ethereum_block(client: Client) -> (Client, Result) { + let (client, result) = call_rpc::<(u64, H256)>( + client, + "state_call", + Params::Array(vec![ + to_value("EthereumHeadersApi_best_block").unwrap(), + to_value("0x").unwrap(), + ]), + ).await; + (client, result.map(|(num, hash)| EthereumHeaderId(num, hash))) +} + +/// Returns true if transactions receipts are required for Ethereum header submission. +pub async fn ethereum_receipts_required( + client: Client, + header: QueuedEthereumHeader, +) -> (Client, Result<(EthereumHeaderId, bool), Error>) { + let id = header.id(); + let header = into_substrate_ethereum_header(header.header()); + let encoded_header = header.encode(); + let (client, receipts_required) = call_rpc( + client, + "state_call", + Params::Array(vec![ + to_value("EthereumHeadersApi_is_import_requires_receipts").unwrap(), + to_value(Bytes(encoded_header)).unwrap(), + ]), + ).await; + (client, receipts_required.map(|receipts_required| (id, receipts_required))) +} + +/// Returns true if Ethereum header is known to Substrate runtime. +pub async fn ethereum_header_known( + client: Client, + id: EthereumHeaderId, +) -> (Client, Result<(EthereumHeaderId, bool), Error>) { + // Substrate module could prune old headers. So this fn could return false even + // if header is synced. And we'll mark corresponding Ethereum header as Orphan. + // + // But when we'll read best header from Substrate next time, we will know that + // there's a better header => this Orphan will either be marked as synced, or + // eventually pruned. + let encoded_id = id.1.encode(); + let (client, is_known_block) = call_rpc( + client, + "state_call", + Params::Array(vec![ + to_value("EthereumHeadersApi_is_known_block").unwrap(), + to_value(Bytes(encoded_id)).unwrap(), + ]), + ).await; + (client, is_known_block.map(|is_known_block| (id, is_known_block))) +} + +/// Submits Ethereum header to Substrate runtime. +pub async fn submit_ethereum_headers( + client: Client, + headers: Vec, +) -> (Client, Result<(TransactionHash, Vec), Error>) { + let ids = headers.iter().map(|header| header.id()).collect(); + let (client, genesis_hash) = match client.genesis_hash { + Some(genesis_hash) => (client, genesis_hash), + None => { + let (mut client, genesis_hash) = block_hash_by_number(client, 0).await; + let genesis_hash = match genesis_hash { + Ok(genesis_hash) => genesis_hash, + Err(err) => return (client, Err(err)), + }; + client.genesis_hash = Some(genesis_hash); + (client, genesis_hash) + }, + }; + let account_id = client.signer.public().as_array_ref().clone().into(); + let (client, nonce) = next_account_index(client, account_id).await; + let nonce = match nonce { + Ok(nonce) => nonce, + Err(err) => return (client, Err(err)), + }; + let transaction = create_submit_transaction( + headers, + &client.signer, + nonce, + genesis_hash, + ); + let encoded_transaction = transaction.encode(); + let (client, transaction_hash) = call_rpc( + client, + "author_submitExtrinsic", + Params::Array(vec![ + to_value(Bytes(encoded_transaction)).unwrap(), + ]), + ).await; + (client, transaction_hash.map(|transaction_hash| (transaction_hash, ids))) +} + +/// Get Substrate block hash by its number. +async fn block_hash_by_number(client: Client, number: u64) -> (Client, Result) { + call_rpc( + client, + "chain_getBlockHash", + Params::Array(vec![ + to_value(number).unwrap(), + ]), + ).await +} + +/// Get substrate account nonce. +async fn next_account_index( + client: Client, + account: node_primitives::AccountId, +) -> (Client, Result) { + use sp_core::crypto::Ss58Codec; + + let (client, index) = call_rpc_u64( + client, + "system_accountNextIndex", + Params::Array(vec![ + to_value(account.to_ss58check()).unwrap(), + ]), + ).await; + (client, index.map(|index| index as _)) +} + +/// Calls RPC on Substrate node that returns Bytes. +async fn call_rpc( + mut client: Client, + method: &'static str, + params: Params, +) -> (Client, Result) { + async fn do_call_rpc( + client: &mut Client, + method: &'static str, + params: Params, + ) -> Result { + let request_id = client + .rpc_client + .start_request(method, params) + .await + .map_err(Error::StartRequestFailed)?; + // WARN: if there'll be need for executing >1 request at a time, we should avoid + // calling request_by_id + let response = client + .rpc_client + .request_by_id(request_id) + .ok_or(Error::RequestNotFound)? + .await + .map_err(Error::ResponseRetrievalFailed)?; + let encoded_response: Bytes = from_value(response).map_err(|_| Error::ResponseParseFailed)?; + Decode::decode(&mut &encoded_response.0[..]).map_err(|_| Error::ResponseParseFailed) + } + + let result = do_call_rpc(&mut client, method, params).await; + (client, result) +} + +/// Calls RPC on Substrate node that returns u64. +async fn call_rpc_u64( + mut client: Client, + method: &'static str, + params: Params, +) -> (Client, Result) { + async fn do_call_rpc( + client: &mut Client, + method: &'static str, + params: Params, + ) -> Result { + let request_id = client + .rpc_client + .start_request(method, params) + .await + .map_err(Error::StartRequestFailed)?; + // WARN: if there'll be need for executing >1 request at a time, we should avoid + // calling request_by_id + let response = client + .rpc_client + .request_by_id(request_id) + .ok_or(Error::RequestNotFound)? + .await + .map_err(Error::ResponseRetrievalFailed)?; + response.as_u64().ok_or(Error::ResponseParseFailed) + } + + let result = do_call_rpc(&mut client, method, params).await; + (client, result) +} + +/// Create Substrate transaction for submitting Ethereum header. +fn create_submit_transaction( + headers: Vec, + signer: &sp_core::sr25519::Pair, + index: node_primitives::Index, + genesis_hash: H256, +) -> node_runtime::UncheckedExtrinsic { + let function = node_runtime::Call::BridgeEthPoa( + node_runtime::BridgeEthPoaCall::import_headers( + headers + .into_iter() + .map(|header| { + let (header, receipts) = header.extract(); + ( + into_substrate_ethereum_header(&header), + into_substrate_ethereum_receipts(&receipts), + ) + }) + .collect(), + ), + ); + + let extra = |i: node_primitives::Index, f: node_primitives::Balance| { + ( + frame_system::CheckVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::::from(i), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(f), + Default::default(), + ) + }; + let raw_payload = node_runtime::SignedPayload::from_raw( + function, + extra(index, 0), + ( + 198, // VERSION.spec_version as u32, + genesis_hash, + genesis_hash, + (), + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (function, extra, _) = raw_payload.deconstruct(); + + node_runtime::UncheckedExtrinsic::new_signed( + function, + signer.into_account().into(), + signature.into(), + extra, + ) +} diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs new file mode 100644 index 0000000000000..8cf5d86cb1481 --- /dev/null +++ b/relays/ethereum/src/substrate_types.rs @@ -0,0 +1,68 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +pub use sp_bridge_eth_poa::{ + Address, Bloom, Bytes, H256, Header as SubstrateEthereumHeader, + LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, + TransactionOutcome as SubstrateEthereumTransactionOutcome, U256, +}; +pub use crate::ethereum_types::H256 as TransactionHash; +use crate::ethereum_types::{ + HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, + RECEIPT_GAS_USED_PROOF as ETHEREUM_RECEIPT_GAS_USED_PROOF, + Header as EthereumHeader, + Receipt as EthereumReceipt, +}; + +/// Convert Ethereum header into Ethereum header for Substrate. +pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEthereumHeader { + SubstrateEthereumHeader { + parent_hash: header.parent_hash, + timestamp: header.timestamp.as_u64(), + number: header.number.expect(ETHEREUM_HEADER_ID_PROOF).as_u64(), + author: header.author, + transactions_root: header.transactions_root, + uncles_hash: header.uncles_hash, + extra_data: header.extra_data.0.clone(), + state_root: header.state_root, + receipts_root: header.receipts_root, + log_bloom: header.logs_bloom.data().into(), + gas_used: header.gas_used, + gas_limit: header.gas_limit, + difficulty: header.difficulty, + seal: header.seal_fields.iter().map(|s| s.0.clone()).collect(), + } +} + +/// Convert Ethereum transactions receipts into Ethereum transactions receipts for Substrate. +pub fn into_substrate_ethereum_receipts( + receipts: &Option>, +) -> Option> { + receipts.as_ref().map(|receipts| receipts.iter().map(|receipt| SubstrateEthereumReceipt { + gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), + log_bloom: receipt.logs_bloom.data().into(), + logs: receipt.logs.iter().map(|log_entry| SubstrateEthereumLogEntry { + address: log_entry.address, + topics: log_entry.topics.clone(), + data: log_entry.data.0.clone(), + }).collect(), + outcome: match (receipt.status, receipt.root) { + (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), + (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), + _ => SubstrateEthereumTransactionOutcome::Unknown, + }, + }).collect()) +} From 86df4d6ce2a5732f1c0f05f1d47833629815b1c6 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 29 Jan 2020 22:34:08 -0500 Subject: [PATCH 0004/1210] Squashed commit of slava-bridge-runtime: commit ae4139bbb3cd4681ff4ad3f335b57e17f49ee895 Author: Hernando Castano Date: Wed Jan 29 22:18:42 2020 -0500 Move slava-bridge-runtime into modules/ethereum/ commit feb522fff241b36bd74638ab5de04ee1068efd0b Merge: 7bc5f61 00fe0de Author: Hernando Castano Date: Wed Jan 29 22:17:26 2020 -0500 Merge branch 'bridge_runtime' of slava-bridge-runtime commit 00fe0dee5f50dd648e7c0f4af7fcb07f422a30af Author: Hernando Castano Date: Wed Jan 29 22:14:03 2020 -0500 Move all files into one folder commit 46d9bdcc35b022bd802e3f99d3f7477110813e2d Author: Hernando Castano Date: Wed Jan 29 22:02:37 2020 -0500 Move files I'm keeping into folder commit 6d10776610283439764de7897f25e921d08e99dc Author: Hernando Castano Date: Sun Jan 12 20:42:03 2020 -0500 Make the bridge-eth-poa module compile again commit 95283a8672d692ed34501e4e7c380a3038099bf8 Author: Hernando Castano Date: Sun Jan 12 20:39:23 2020 -0500 Add `sp-api` dependency back commit 31c476ac25391fb8f896b718998e9e80976a4cfd Author: Hernando Castano Date: Sun Jan 12 20:28:26 2020 -0500 Bump dependencies Uses new frame-* and pallet-* versioned dependencies but a few other packages came along for the bump ride commit e22f41d97758712cd4094b98dc3a884098059bb8 Author: Svyatoslav Nikolsky Date: Tue Dec 10 14:52:04 2019 +0300 reward + penalize for Eth headers commit 34d35e7731c79b9e9ff21252063f939400ecfdb4 Author: Svyatoslav Nikolsky Date: Mon Dec 9 12:56:31 2019 +0300 added couple of TODOs commit 1a80caf9b643be4b823c9559a132285606641811 Author: Svyatoslav Nikolsky Date: Mon Dec 9 12:11:35 2019 +0300 removed debug print commit c590908bfb7e9d2075d1fd77556418eda7f330d3 Author: Svyatoslav Nikolsky Date: Mon Dec 9 11:55:09 2019 +0300 fixed bridge tests commit ab164f87019037bbc5cd2a69364ee4623e44ebbc Author: Svyatoslav Nikolsky Date: Mon Dec 9 11:15:46 2019 +0300 lost deps commit 649e90068040a12a1aa78788dd834394201753fa Author: Svyatoslav Nikolsky Date: Mon Dec 9 09:57:09 2019 +0300 fix compilation again commit cece62c2c2ddf772f01151ce3bf6dec28f4d0cca Author: Svyatoslav Nikolsky Date: Mon Dec 9 09:52:30 2019 +0300 fix receipts root calculation commit 92f4026896efbe3e315a909161af06dc1e2a1ff4 Author: Svyatoslav Nikolsky Date: Thu Dec 5 16:09:23 2019 +0300 check transactions receipts root commit 2e6a5af5e1bcb843262c5ba475f950cf989eb39b Author: Svyatoslav Nikolsky Date: Thu Dec 5 15:39:30 2019 +0300 provide keccak_256_ordered_root to runtime commit 2970aae4648beb8c531ec7c2ff706b65ea06ba63 Author: Svyatoslav Nikolsky Date: Thu Dec 5 15:15:03 2019 +0300 use existing keccak builtin from bridge runtime commit 75c498b0fe600be32b35a3e0d0da3b52ec5fd3b6 Author: Svyatoslav Nikolsky Date: Thu Dec 5 10:32:57 2019 +0300 submit multiple headers at once commit cdfdafc21efb4a667f2407c7139921d4b948fd7e Author: Svyatoslav Nikolsky Date: Wed Dec 4 13:48:42 2019 +0300 expose && initialize bridge configuration commit 383b93be54981b13c564218652a85af78c88c4f7 Author: Svyatoslav Nikolsky Date: Wed Dec 4 11:28:22 2019 +0300 export bridge Call commit dacc2939db51859a3e1b87250b289b269a80793b Author: Svyatoslav Nikolsky Date: Wed Dec 4 11:13:56 2019 +0300 expose BridgeEthPoaCall commit a5281c9387e622e28cbc89a62d268b359cb2f724 Author: Svyatoslav Nikolsky Date: Wed Dec 4 10:42:41 2019 +0300 EthereumHeadersApi::is_known_block commit c5658e1563be9b688355d03b20a62345418e3b78 Author: Svyatoslav Nikolsky Date: Wed Dec 4 10:14:42 2019 +0300 pub use parity_bytes::Bytes; commit 94cd24e5535101e871436ca35dcfda27f7955590 Author: Svyatoslav Nikolsky Date: Wed Dec 4 10:01:25 2019 +0300 exposed EthereumHeadersApi commit 607ec1760d146e8046122a1d2f868d70e15490e6 Author: Svyatoslav Nikolsky Date: Tue Dec 3 14:51:40 2019 +0300 EthPoA bridge: runtime --- .../bridge-runtime/bin/node/cli/Cargo.toml | 128 +++ .../bin/node/cli/src/chain_spec.rs | 449 ++++++++ .../bin/node/runtime/Cargo.toml | 127 +++ .../bin/node/runtime/src/lib.rs | 836 +++++++++++++++ .../bin/node/testing/Cargo.toml | 32 + .../bin/node/testing/src/genesis.rs | 144 +++ .../frame/bridge-eth-poa/Cargo.toml | 33 + .../frame/bridge-eth-poa/src/error.rs | 84 ++ .../frame/bridge-eth-poa/src/finality.rs | 284 +++++ .../frame/bridge-eth-poa/src/import.rs | 347 +++++++ .../frame/bridge-eth-poa/src/lib.rs | 740 +++++++++++++ .../frame/bridge-eth-poa/src/validators.rs | 394 +++++++ .../frame/bridge-eth-poa/src/verification.rs | 448 ++++++++ .../primitives/bridge-eth-poa/Cargo.toml | 49 + .../primitives/bridge-eth-poa/src/lib.rs | 361 +++++++ .../primitives/core/src/hasher.rs | 85 ++ .../bridge-runtime/primitives/core/src/lib.rs | 312 ++++++ .../bridge-runtime/primitives/io/Cargo.toml | 40 + .../bridge-runtime/primitives/io/src/lib.rs | 974 ++++++++++++++++++ 19 files changed, 5867 insertions(+) create mode 100644 modules/ethereum/bridge-runtime/bin/node/cli/Cargo.toml create mode 100644 modules/ethereum/bridge-runtime/bin/node/cli/src/chain_spec.rs create mode 100644 modules/ethereum/bridge-runtime/bin/node/runtime/Cargo.toml create mode 100644 modules/ethereum/bridge-runtime/bin/node/runtime/src/lib.rs create mode 100644 modules/ethereum/bridge-runtime/bin/node/testing/Cargo.toml create mode 100644 modules/ethereum/bridge-runtime/bin/node/testing/src/genesis.rs create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/error.rs create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/finality.rs create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/import.rs create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/validators.rs create mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/verification.rs create mode 100644 modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml create mode 100644 modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/src/lib.rs create mode 100644 modules/ethereum/bridge-runtime/primitives/core/src/hasher.rs create mode 100644 modules/ethereum/bridge-runtime/primitives/core/src/lib.rs create mode 100644 modules/ethereum/bridge-runtime/primitives/io/Cargo.toml create mode 100644 modules/ethereum/bridge-runtime/primitives/io/src/lib.rs diff --git a/modules/ethereum/bridge-runtime/bin/node/cli/Cargo.toml b/modules/ethereum/bridge-runtime/bin/node/cli/Cargo.toml new file mode 100644 index 0000000000000..4df7401f23b9b --- /dev/null +++ b/modules/ethereum/bridge-runtime/bin/node/cli/Cargo.toml @@ -0,0 +1,128 @@ +[package] +name = "node-cli" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Substrate node implementation in Rust." +build = "build.rs" +edition = "2018" +default-run = "substrate" + +[badges] +travis-ci = { repository = "paritytech/substrate", branch = "master" } +maintenance = { status = "actively-developed" } +is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } +is-it-maintained-open-issues = { repository = "paritytech/substrate" } + +[[bin]] +name = "substrate" +path = "bin/main.rs" +required-features = ["cli"] + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "1.0.6" } +serde = { version = "1.0.102", features = ["derive"] } +futures01 = { package = "futures", version = "0.1.29" } +futures = { version = "0.3.1", features = ["compat"] } +hex-literal = "0.2.1" +jsonrpc-core = "14.0.3" +log = "0.4.8" +rand = "0.7.2" +structopt = "=0.3.7" + +# primitives +sp-authority-discovery = { version = "2.0.0", path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8", path = "../../../primitives/consensus/babe" } +grandpa-primitives = { version = "2.0.0", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +sp-timestamp = { version = "2.0.0", default-features = false, path = "../../../primitives/timestamp" } +sp-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../primitives/finality-tracker" } +sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } +sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } +sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa" } + +# client dependencies +sc-client-api = { version = "2.0.0", path = "../../../client/api" } +sc-client = { version = "2.0.0", path = "../../../client/" } +sc-chain-spec = { version = "2.0.0", path = "../../../client/chain-spec" } +sc-transaction-pool = { version = "2.0.0", path = "../../../client/transaction-pool" } +sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" } +sc-network = { version = "0.8", path = "../../../client/network" } +sc-consensus-babe = { version = "0.8", path = "../../../client/consensus/babe" } +grandpa = { version = "2.0.0", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } +sc-client-db = { version = "2.0.0", default-features = false, path = "../../../client/db" } +sc-offchain = { version = "2.0.0", path = "../../../client/offchain" } +sc-rpc = { version = "2.0.0", path = "../../../client/rpc" } +sc-basic-authority = { version = "2.0.0", path = "../../../client/basic-authorship" } +sc-service = { version = "2.0.0", default-features = false, path = "../../../client/service" } +sc-telemetry = { version = "2.0.0", path = "../../../client/telemetry" } +sc-authority-discovery = { version = "2.0.0", path = "../../../client/authority-discovery" } + +# frame dependencies +pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" } +pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } +frame-system = { version = "2.0.0", path = "../../../frame/system" } +pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } +pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } +frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } +pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" } +pallet-authority-discovery = { version = "2.0.0", path = "../../../frame/authority-discovery" } + +# node-specific dependencies +node-runtime = { version = "2.0.0", path = "../runtime" } +node-rpc = { version = "2.0.0", path = "../rpc" } +node-primitives = { version = "2.0.0", path = "../primitives" } +node-executor = { version = "2.0.0", path = "../executor" } + +# CLI-specific dependencies +tokio = { version = "0.1.22", optional = true } +sc-cli = { version = "2.0.0", optional = true, path = "../../../client/cli" } +ctrlc = { version = "3.1.3", features = ["termination"], optional = true } +node-transaction-factory = { version = "2.0.0", optional = true, path = "../transaction-factory" } + +# WASM-specific dependencies +wasm-bindgen = { version = "0.2.57", optional = true } +wasm-bindgen-futures = { version = "0.4.7", optional = true } +browser-utils = { path = "../../../utils/browser", optional = true } + +[dev-dependencies] +sc-keystore = { version = "2.0.0", path = "../../../client/keystore" } +sc-consensus-babe = { version = "0.8", features = ["test-helpers"], path = "../../../client/consensus/babe" } +sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } +futures = "0.3.1" +tempfile = "3.1.0" + +[build-dependencies] +sc-cli = { version = "2.0.0", package = "sc-cli", path = "../../../client/cli" } +build-script-utils = { version = "2.0.0", package = "substrate-build-script-utils", path = "../../../utils/build-script-utils" } +structopt = "=0.3.7" +vergen = "3.0.4" + +[features] +default = ["cli", "wasmtime"] +browser = [ + "browser-utils", + "wasm-bindgen", + "wasm-bindgen-futures", +] +cli = [ + "sc-cli", + "node-transaction-factory", + "tokio", + "ctrlc", + "sc-service/rocksdb", + "node-executor/wasmi-errno", +] +wasmtime = [ + "cli", + "node-executor/wasmtime", + "sc-cli/wasmtime", + "sc-service/wasmtime", +] diff --git a/modules/ethereum/bridge-runtime/bin/node/cli/src/chain_spec.rs b/modules/ethereum/bridge-runtime/bin/node/cli/src/chain_spec.rs new file mode 100644 index 0000000000000..8a0af961578ac --- /dev/null +++ b/modules/ethereum/bridge-runtime/bin/node/cli/src/chain_spec.rs @@ -0,0 +1,449 @@ +// Copyright 2018-2020 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 . + +//! Substrate chain configurations. + +use sc_chain_spec::ChainSpecExtension; +use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519}; +use serde::{Serialize, Deserialize}; +use node_runtime::{ + AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, + GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, + SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, BridgeEthPoaConfig, +}; +use node_runtime::Block; +use node_runtime::constants::currency::*; +use sc_service; +use hex_literal::hex; +use sc_telemetry::TelemetryEndpoints; +use grandpa_primitives::{AuthorityId as GrandpaId}; +use sp_consensus_babe::{AuthorityId as BabeId}; +use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use sp_runtime::{Perbill, traits::{Verify, IdentifyAccount}}; + +pub use node_primitives::{AccountId, Balance, Signature}; +pub use node_runtime::GenesisConfig; + +type AccountPublic = ::Signer; + +const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; + +/// Node `ChainSpec` extensions. +/// +/// Additional parameters for some Substrate core modules, +/// customizable from the chain spec. +#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] +#[serde(rename_all = "camelCase")] +pub struct Extensions { + /// Block numbers with known hashes. + pub fork_blocks: sc_client::ForkBlocks, + /// Known bad block hashes. + pub bad_blocks: sc_client::BadBlocks, +} + +/// Specialized `ChainSpec`. +pub type ChainSpec = sc_service::ChainSpec< + GenesisConfig, + Extensions, +>; +/// Flaming Fir testnet generator +pub fn flaming_fir_config() -> Result { + ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) +} + +fn session_keys( + grandpa: GrandpaId, + babe: BabeId, + im_online: ImOnlineId, + authority_discovery: AuthorityDiscoveryId, +) -> SessionKeys { + SessionKeys { grandpa, babe, im_online, authority_discovery } +} + +fn staging_testnet_config_genesis() -> GenesisConfig { + // stash, controller, session-key + // generated with secret: + // for i in 1 2 3 4 ; do for j in stash controller; do subkey inspect "$secret"/fir/$j/$i; done; done + // and + // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done + + let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)> = vec![( + // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy + hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].into(), + // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq + hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].into(), + // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC + hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 + hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), + ),( + // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 + hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].into(), + // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF + hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].into(), + // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE + hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ + hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), + ),( + // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp + hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].into(), + // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 + hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].into(), + // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d + hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH + hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), + ),( + // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 + hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].into(), + // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn + hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].into(), + // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 + hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x + hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), + )]; + + // generated with secret: subkey inspect "$secret"/fir + let root_key: AccountId = hex![ + // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo + "9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809" + ].into(); + + let endowed_accounts: Vec = vec![root_key.clone()]; + + testnet_genesis( + initial_authorities, + root_key, + Some(endowed_accounts), + false, + ) +} + +/// Staging testnet config. +pub fn staging_testnet_config() -> ChainSpec { + let boot_nodes = vec![]; + ChainSpec::from_genesis( + "Staging Testnet", + "staging_testnet", + staging_testnet_config_genesis, + boot_nodes, + Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), + None, + None, + Default::default(), + ) +} + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId where + AccountPublic: From<::Public> +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate stash, controller and session key from seed +pub fn get_authority_keys_from_seed(seed: &str) -> ( + AccountId, + AccountId, + GrandpaId, + BabeId, + ImOnlineId, + AuthorityDiscoveryId, +) { + ( + get_account_id_from_seed::(&format!("{}//stash", seed)), + get_account_id_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + get_from_seed::(seed), + ) +} + +/// Helper function to create GenesisConfig for testing +pub fn testnet_genesis( + initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)>, + root_key: AccountId, + endowed_accounts: Option>, + enable_println: bool, +) -> GenesisConfig { + let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(|| { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ] + }); + let num_endowed_accounts = endowed_accounts.len(); + + const ENDOWMENT: Balance = 10_000_000 * DOLLARS; + const STASH: Balance = 100 * DOLLARS; + + GenesisConfig { + frame_system: Some(SystemConfig { + code: WASM_BINARY.to_vec(), + changes_trie_config: Default::default(), + }), + pallet_balances: Some(BalancesConfig { + balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT)) + .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) + .collect(), + vesting: vec![], + }), + pallet_indices: Some(IndicesConfig { + ids: endowed_accounts.iter().cloned() + .chain(initial_authorities.iter().map(|x| x.0.clone())) + .collect::>(), + }), + pallet_session: Some(SessionConfig { + keys: initial_authorities.iter().map(|x| { + (x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone())) + }).collect::>(), + }), + pallet_staking: Some(StakingConfig { + current_era: 0, + validator_count: initial_authorities.len() as u32 * 2, + minimum_validator_count: initial_authorities.len() as u32, + stakers: initial_authorities.iter().map(|x| { + (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator) + }).collect(), + invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), + slash_reward_fraction: Perbill::from_percent(10), + .. Default::default() + }), + pallet_democracy: Some(DemocracyConfig::default()), + pallet_collective_Instance1: Some(CouncilConfig { + members: endowed_accounts.iter().cloned() + .collect::>()[..(num_endowed_accounts + 1) / 2].to_vec(), + phantom: Default::default(), + }), + pallet_collective_Instance2: Some(TechnicalCommitteeConfig { + members: endowed_accounts.iter().cloned() + .collect::>()[..(num_endowed_accounts + 1) / 2].to_vec(), + phantom: Default::default(), + }), + pallet_contracts: Some(ContractsConfig { + current_schedule: pallet_contracts::Schedule { + enable_println, // this should only be enabled on development chains + ..Default::default() + }, + gas_price: 1 * MILLICENTS, + }), + pallet_sudo: Some(SudoConfig { + key: root_key, + }), + pallet_babe: Some(BabeConfig { + authorities: vec![], + }), + pallet_im_online: Some(ImOnlineConfig { + keys: vec![], + }), + pallet_authority_discovery: Some(AuthorityDiscoveryConfig { + keys: vec![], + }), + pallet_grandpa: Some(GrandpaConfig { + authorities: vec![], + }), + pallet_membership_Instance1: Some(Default::default()), + pallet_treasury: Some(Default::default()), + // here comes configuration for Kovan chain + bridge_eth_poa: Some(BridgeEthPoaConfig { + initial_header: sp_bridge_eth_poa::Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), + uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), + extra_data: vec![], + state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), + receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 6000000.into(), + difficulty: 131072.into(), + seal: vec![ + vec![128].into(), + vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), + ], + }, + initial_difficulty: 0.into(), + initial_validators: vec![ + [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, + 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), + [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, + 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), + [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, + 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), + [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, + 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), + [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, + 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), + [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, + 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), + [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, + 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), + [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, + 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), + [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, + 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + ], + }), + } +} + +fn development_config_genesis() -> GenesisConfig { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + None, + true, + ) +} + +/// Development config (single validator Alice) +pub fn development_config() -> ChainSpec { + ChainSpec::from_genesis( + "Development", + "dev", + development_config_genesis, + vec![], + None, + None, + None, + Default::default(), + ) +} + +fn local_testnet_genesis() -> GenesisConfig { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), + ], + get_account_id_from_seed::("Alice"), + None, + false, + ) +} + +/// Local testnet config (multivalidator Alice + Bob) +pub fn local_testnet_config() -> ChainSpec { + ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + local_testnet_genesis, + vec![], + None, + None, + None, + Default::default(), + ) +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + use crate::service::{new_full, new_light}; + use sc_service_test; + + fn local_testnet_genesis_instant_single() -> GenesisConfig { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + None, + false, + ) + } + + /// Local testnet config (single validator - Alice) + pub fn integration_test_config_with_single_authority() -> ChainSpec { + ChainSpec::from_genesis( + "Integration Test", + "test", + local_testnet_genesis_instant_single, + vec![], + None, + None, + None, + Default::default(), + ) + } + + /// Local testnet config (multivalidator Alice + Bob) + pub fn integration_test_config_with_two_authorities() -> ChainSpec { + ChainSpec::from_genesis( + "Integration Test", + "test", + local_testnet_genesis, + vec![], + None, + None, + None, + Default::default(), + ) + } + + #[test] + #[ignore] + fn test_connectivity() { + sc_service_test::connectivity( + integration_test_config_with_two_authorities(), + |config| new_full(config), + |config| new_light(config), + ); + } +} diff --git a/modules/ethereum/bridge-runtime/bin/node/runtime/Cargo.toml b/modules/ethereum/bridge-runtime/bin/node/runtime/Cargo.toml new file mode 100644 index 0000000000000..7ca943621b28d --- /dev/null +++ b/modules/ethereum/bridge-runtime/bin/node/runtime/Cargo.toml @@ -0,0 +1,127 @@ +[package] +name = "node-runtime" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } +integer-sqrt = { version = "0.1.2" } +safe-mix = { version = "1.0", default-features = false } +rustc-hex = { version = "2.0", optional = true } +serde = { version = "1.0.102", optional = true } + +# primitives +sp-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../primitives/authority-discovery" } +sp-consensus-babe = { version = "0.8", default-features = false, path = "../../../primitives/consensus/babe" } +sp-block-builder = { path = "../../../primitives/block-builder", default-features = false} +sp-inherents = { version = "2.0.0", default-features = false, path = "../../../primitives/inherents" } +node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } +sp-offchain = { version = "2.0.0", default-features = false, path = "../../../primitives/offchain" } +sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } +sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" } +sp-api = { version = "2.0.0", default-features = false, path = "../../../primitives/api" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } +sp-staking = { version = "2.0.0", default-features = false, path = "../../../primitives/staking" } +sp-keyring = { version = "2.0.0", optional = true, path = "../../../primitives/keyring" } +sp-session = { version = "2.0.0", default-features = false, path = "../../../primitives/session" } +sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../../primitives/transaction-pool" } +sp-version = { version = "2.0.0", default-features = false, path = "../../../primitives/version" } +sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa", default-features = false } + +# frame dependencies +frame-executive = { version = "2.0.0", default-features = false, path = "../../../frame/executive" } +frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } +frame-system = { version = "2.0.0", default-features = false, path = "../../../frame/system" } +frame-system-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } +pallet-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../frame/authority-discovery" } +pallet-authorship = { version = "2.0.0", default-features = false, path = "../../../frame/authorship" } +pallet-babe = { version = "2.0.0", default-features = false, path = "../../../frame/babe" } +pallet-balances = { version = "2.0.0", default-features = false, path = "../../../frame/balances" } +pallet-collective = { version = "2.0.0", default-features = false, path = "../../../frame/collective" } +pallet-contracts = { version = "2.0.0", default-features = false, path = "../../../frame/contracts" } +pallet-contracts-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } +pallet-democracy = { version = "2.0.0", default-features = false, path = "../../../frame/democracy" } +pallet-elections-phragmen = { version = "2.0.0", default-features = false, path = "../../../frame/elections-phragmen" } +pallet-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../frame/finality-tracker" } +pallet-grandpa = { version = "2.0.0", default-features = false, path = "../../../frame/grandpa" } +pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" } +pallet-indices = { version = "2.0.0", default-features = false, path = "../../../frame/indices" } +pallet-membership = { version = "2.0.0", default-features = false, path = "../../../frame/membership" } +pallet-nicks = { version = "2.0.0", default-features = false, path = "../../../frame/nicks" } +pallet-offences = { version = "2.0.0", default-features = false, path = "../../../frame/offences" } +pallet-randomness-collective-flip = { version = "2.0.0", default-features = false, path = "../../../frame/randomness-collective-flip" } +pallet-session = { version = "2.0.0", features = ["historical"], path = "../../../frame/session", default-features = false } +pallet-staking = { version = "2.0.0", features = ["migrate"], path = "../../../frame/staking", default-features = false } +pallet-staking-reward-curve = { version = "2.0.0", path = "../../../frame/staking/reward-curve" } +pallet-sudo = { version = "2.0.0", default-features = false, path = "../../../frame/sudo" } +pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" } +pallet-treasury = { version = "2.0.0", default-features = false, path = "../../../frame/treasury" } +pallet-utility = { version = "2.0.0", default-features = false, path = "../../../frame/utility" } +pallet-transaction-payment = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment" } +pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } +# TODO: Update this +bridge-eth-poa = { package = "pallet-bridge-eth-poa", path = "../../../frame/bridge-eth-poa", default-features = false } + +[build-dependencies] +wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } + +[dev-dependencies] +sp-io = { version = "2.0.0", path = "../../../primitives/io" } + +[features] +default = ["std"] +std = [ + "sp-authority-discovery/std", + "pallet-authority-discovery/std", + "pallet-authorship/std", + "sp-consensus-babe/std", + "pallet-babe/std", + "pallet-balances/std", + "sp-block-builder/std", + "sp-bridge-eth-poa/std", + "bridge-eth-poa/std", # TODO: Update this + "codec/std", + "pallet-collective/std", + "pallet-contracts-rpc-runtime-api/std", + "pallet-contracts/std", + "pallet-democracy/std", + "pallet-elections-phragmen/std", + "frame-executive/std", + "pallet-finality-tracker/std", + "pallet-grandpa/std", + "pallet-im-online/std", + "pallet-indices/std", + "sp-inherents/std", + "pallet-membership/std", + "pallet-nicks/std", + "node-primitives/std", + "sp-offchain/std", + "pallet-offences/std", + "sp-core/std", + "pallet-randomness-collective-flip/std", + "sp-std/std", + "rustc-hex", + "safe-mix/std", + "serde", + "pallet-session/std", + "sp-api/std", + "sp-runtime/std", + "sp-staking/std", + "pallet-staking/std", + "sp-keyring", + "sp-session/std", + "pallet-sudo/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-treasury/std", + "sp-transaction-pool/std", + "pallet-utility/std", + "sp-version/std", +] diff --git a/modules/ethereum/bridge-runtime/bin/node/runtime/src/lib.rs b/modules/ethereum/bridge-runtime/bin/node/runtime/src/lib.rs new file mode 100644 index 0000000000000..21cfc6d8bc501 --- /dev/null +++ b/modules/ethereum/bridge-runtime/bin/node/runtime/src/lib.rs @@ -0,0 +1,836 @@ +// Copyright 2018-2020 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 . + +//! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit="256"] + +use sp_std::prelude::*; +use frame_support::{ + construct_runtime, parameter_types, debug, + weights::Weight, + traits::{SplitTwoWays, Currency, Randomness}, +}; +use sp_core::u32_trait::{_1, _2, _3, _4}; +use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature}; +use sp_api::impl_runtime_apis; +use sp_runtime::{ + Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str +}; +use sp_runtime::curve::PiecewiseLinear; +use sp_runtime::transaction_validity::TransactionValidity; +use sp_runtime::traits::{ + self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, + OpaqueKeys, +}; +use sp_version::RuntimeVersion; +#[cfg(any(feature = "std", test))] +use sp_version::NativeVersion; +use sp_core::OpaqueMetadata; +use pallet_grandpa::AuthorityList as GrandpaAuthorityList; +use pallet_grandpa::fg_primitives; +use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; +use pallet_contracts_rpc_runtime_api::ContractExecResult; +use frame_system::offchain::TransactionSubmitter; +use sp_inherents::{InherentData, CheckInherentsResult}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use pallet_timestamp::Call as TimestampCall; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_contracts::Gas; +pub use frame_support::StorageValue; +pub use pallet_staking::StakerStatus; +pub use bridge_eth_poa::Call as BridgeEthPoaCall; // TODO: Update name + +/// Implementations of some helper traits passed into runtime modules as associated types. +pub mod impls; +use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; + +/// Constant values used within the runtime. +pub mod constants; +use constants::{time::*, currency::*}; + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +/// Runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("node"), + impl_name: create_runtime_str!("substrate-node"), + authoring_version: 10, + // Per convention: if the runtime behavior changes, increment spec_version + // and set impl_version to equal spec_version. If only runtime + // implementation changes and behavior does not, then leave spec_version as + // is and increment impl_version. + spec_version: 202, + impl_version: 202, + apis: RUNTIME_API_VERSIONS, +}; + +/// Native version. +#[cfg(any(feature = "std", test))] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +type NegativeImbalance = >::NegativeImbalance; + +pub type DealWithFees = SplitTwoWays< + Balance, + NegativeImbalance, + _4, Treasury, // 4 parts (80%) goes to the treasury. + _1, Author, // 1 part (20%) goes to the block author. +>; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const MaximumBlockWeight: Weight = 1_000_000_000; + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); +} + +impl frame_system::Trait for Runtime { + type Origin = Origin; + type Call = Call; + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = Indices; + type Header = generic::Header; + type Event = Event; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = Version; + type ModuleToIndex = ModuleToIndex; +} + +parameter_types! { + // One storage item; value is size 4+4+16+32 bytes = 56 bytes. + pub const MultisigDepositBase: Balance = 30 * CENTS; + // Additional storage item size of 32 bytes. + pub const MultisigDepositFactor: Balance = 5 * CENTS; + pub const MaxSignatories: u16 = 100; +} + +impl pallet_utility::Trait for Runtime { + type Event = Event; + type Call = Call; + type Currency = Balances; + type MultisigDepositBase = MultisigDepositBase; + type MultisigDepositFactor = MultisigDepositFactor; + type MaxSignatories = MaxSignatories; +} + +parameter_types! { + pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS; + pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; +} + +impl pallet_babe::Trait for Runtime { + type EpochDuration = EpochDuration; + type ExpectedBlockTime = ExpectedBlockTime; + type EpochChangeTrigger = pallet_babe::ExternalTrigger; +} + +impl pallet_indices::Trait for Runtime { + type AccountIndex = AccountIndex; + type IsDeadAccount = Balances; + type ResolveHint = pallet_indices::SimpleResolveHint; + type Event = Event; +} + +parameter_types! { + pub const ExistentialDeposit: Balance = 1 * DOLLARS; + pub const TransferFee: Balance = 1 * CENTS; + pub const CreationFee: Balance = 1 * CENTS; +} + +impl pallet_balances::Trait for Runtime { + type Balance = Balance; + type OnFreeBalanceZero = ((Staking, Contracts), Session); + type OnReapAccount = System; + type OnNewAccount = Indices; + type Event = Event; + type DustRemoval = (); + type TransferPayment = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 1 * CENTS; + pub const TransactionByteFee: Balance = 10 * MILLICENTS; + // setting this to zero will disable the weight fee. + pub const WeightFeeCoefficient: Balance = 1_000; + // for a sane configuration, this should always be less than `AvailableBlockRatio`. + pub const TargetBlockFullness: Perbill = Perbill::from_percent(25); +} + +impl pallet_transaction_payment::Trait for Runtime { + type Currency = Balances; + type OnTransactionPayment = DealWithFees; + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = LinearWeightToFee; + type FeeMultiplierUpdate = TargetedFeeAdjustment; +} + +parameter_types! { + pub const MinimumPeriod: Moment = SLOT_DURATION / 2; +} +impl pallet_timestamp::Trait for Runtime { + type Moment = Moment; + type OnTimestampSet = Babe; + type MinimumPeriod = MinimumPeriod; +} + +parameter_types! { + pub const UncleGenerations: BlockNumber = 5; +} + +impl pallet_authorship::Trait for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = (Staking, ImOnline); +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub grandpa: Grandpa, + pub babe: Babe, + pub im_online: ImOnline, + pub authority_discovery: AuthorityDiscovery, + } +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); +} + +impl pallet_session::Trait for Runtime { + type OnSessionEnding = Staking; + type SessionHandler = ::KeyTypeIdProviders; + type ShouldEndSession = Babe; + type Event = Event; + type Keys = SessionKeys; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_staking::StashOf; + type SelectInitialValidators = Staking; + type DisabledValidatorsThreshold = DisabledValidatorsThreshold; +} + +impl pallet_session::historical::Trait for Runtime { + type FullIdentification = pallet_staking::Exposure; + type FullIdentificationOf = pallet_staking::ExposureOf; +} + +pallet_staking_reward_curve::build! { + const REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_025_000, + max_inflation: 0_100_000, + ideal_stake: 0_500_000, + falloff: 0_050_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + +parameter_types! { + pub const SessionsPerEra: sp_staking::SessionIndex = 6; + pub const BondingDuration: pallet_staking::EraIndex = 24 * 28; + pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. + pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; +} + +impl pallet_staking::Trait for Runtime { + type Currency = Balances; + type Time = Timestamp; + type CurrencyToVote = CurrencyToVoteHandler; + type RewardRemainder = Treasury; + type Event = Event; + type Slash = Treasury; // send the slashed funds to the treasury. + type Reward = (); // rewards are minted from the void + type SessionsPerEra = SessionsPerEra; + type BondingDuration = BondingDuration; + type SlashDeferDuration = SlashDeferDuration; + /// A super-majority of the council can cancel the slash. + type SlashCancelOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + type SessionInterface = Self; + type RewardCurve = RewardCurve; +} + +parameter_types! { + pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; + pub const MinimumDeposit: Balance = 100 * DOLLARS; + pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; + pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + // One cent: $10,000 / MB + pub const PreimageByteDeposit: Balance = 1 * CENTS; +} + +impl pallet_democracy::Trait for Runtime { + type Proposal = Call; + type Event = Event; + type Currency = Balances; + type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type EmergencyVotingPeriod = EmergencyVotingPeriod; + type MinimumDeposit = MinimumDeposit; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; + /// A unanimous council can have the next scheduled referendum be a straight default-carries + /// (NTB) vote. + type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>; + /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote + /// be tabled immediately and with a shorter voting/enactment period. + type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cooloff period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = CooloffPeriod; + type PreimageByteDeposit = PreimageByteDeposit; + type Slash = Treasury; +} + +type CouncilCollective = pallet_collective::Instance1; +impl pallet_collective::Trait for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; +} + +parameter_types! { + pub const CandidacyBond: Balance = 10 * DOLLARS; + pub const VotingBond: Balance = 1 * DOLLARS; + pub const TermDuration: BlockNumber = 7 * DAYS; + pub const DesiredMembers: u32 = 13; + pub const DesiredRunnersUp: u32 = 7; +} + +impl pallet_elections_phragmen::Trait for Runtime { + type Event = Event; + type Currency = Balances; + type CurrencyToVote = CurrencyToVoteHandler; + type CandidacyBond = CandidacyBond; + type VotingBond = VotingBond; + type TermDuration = TermDuration; + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = DesiredRunnersUp; + type LoserCandidate = (); + type BadReport = (); + type KickedMember = (); + type ChangeMembers = Council; +} + +type TechnicalCollective = pallet_collective::Instance2; +impl pallet_collective::Trait for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; +} + +impl pallet_membership::Trait for Runtime { + type Event = Event; + type AddOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type RemoveOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type SwapOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type ResetOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; + type MembershipInitialized = TechnicalCommittee; + type MembershipChanged = TechnicalCommittee; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 1 * DOLLARS; + pub const SpendPeriod: BlockNumber = 1 * DAYS; + pub const Burn: Permill = Permill::from_percent(50); + pub const TipCountdown: BlockNumber = 1 * DAYS; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub const TipReportDepositBase: Balance = 1 * DOLLARS; + pub const TipReportDepositPerByte: Balance = 1 * CENTS; +} + +impl pallet_treasury::Trait for Runtime { + type Currency = Balances; + type ApproveOrigin = pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective>; + type RejectOrigin = pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective>; + type Event = Event; + type ProposalRejection = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type SpendPeriod = SpendPeriod; + type Burn = Burn; + type Tippers = Elections; + type TipCountdown = TipCountdown; + type TipFindersFee = TipFindersFee; + type TipReportDepositBase = TipReportDepositBase; + type TipReportDepositPerByte = TipReportDepositPerByte; +} + +parameter_types! { + pub const ContractTransferFee: Balance = 1 * CENTS; + pub const ContractCreationFee: Balance = 1 * CENTS; + pub const ContractTransactionBaseFee: Balance = 1 * CENTS; + pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS; + pub const ContractFee: Balance = 1 * CENTS; + pub const TombstoneDeposit: Balance = 1 * DOLLARS; + pub const RentByteFee: Balance = 1 * DOLLARS; + pub const RentDepositOffset: Balance = 1000 * DOLLARS; + pub const SurchargeReward: Balance = 150 * DOLLARS; +} + +impl pallet_contracts::Trait for Runtime { + type Currency = Balances; + type Time = Timestamp; + type Randomness = RandomnessCollectiveFlip; + type Call = Call; + type Event = Event; + type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminator; + type ComputeDispatchFee = pallet_contracts::DefaultDispatchFeeComputor; + type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter; + type GasPayment = (); + type RentPayment = (); + type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap; + type TombstoneDeposit = TombstoneDeposit; + type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset; + type RentByteFee = RentByteFee; + type RentDepositOffset = RentDepositOffset; + type SurchargeReward = SurchargeReward; + type TransferFee = ContractTransferFee; + type CreationFee = ContractCreationFee; + type TransactionBaseFee = ContractTransactionBaseFee; + type TransactionByteFee = ContractTransactionByteFee; + type ContractFee = ContractFee; + type CallBaseFee = pallet_contracts::DefaultCallBaseFee; + type InstantiateBaseFee = pallet_contracts::DefaultInstantiateBaseFee; + type MaxDepth = pallet_contracts::DefaultMaxDepth; + type MaxValueSize = pallet_contracts::DefaultMaxValueSize; + type BlockGasLimit = pallet_contracts::DefaultBlockGasLimit; +} + +impl pallet_sudo::Trait for Runtime { + type Event = Event; + type Proposal = Call; +} + +/// A runtime transaction submitter. +pub type SubmitTransaction = TransactionSubmitter; + +parameter_types! { + pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _; +} + +impl pallet_im_online::Trait for Runtime { + type AuthorityId = ImOnlineId; + type Call = Call; + type Event = Event; + type SubmitTransaction = SubmitTransaction; + type ReportUnresponsiveness = Offences; + type SessionDuration = SessionDuration; +} + +impl pallet_offences::Trait for Runtime { + type Event = Event; + type IdentificationTuple = pallet_session::historical::IdentificationTuple; + type OnOffenceHandler = Staking; +} + +impl pallet_authority_discovery::Trait for Runtime {} + +impl pallet_grandpa::Trait for Runtime { + type Event = Event; +} + +parameter_types! { + pub const WindowSize: BlockNumber = 101; + pub const ReportLatency: BlockNumber = 1000; +} + +impl pallet_finality_tracker::Trait for Runtime { + type OnFinalizationStalled = Grandpa; + type WindowSize = WindowSize; + type ReportLatency = ReportLatency; +} + +parameter_types! { + pub const ReservationFee: Balance = 1 * DOLLARS; + pub const MinLength: usize = 3; + pub const MaxLength: usize = 16; +} + +impl pallet_nicks::Trait for Runtime { + type Event = Event; + type Currency = Balances; + type ReservationFee = ReservationFee; + type Slashed = Treasury; + type ForceOrigin = pallet_collective::EnsureMember; + type MinLength = MinLength; + type MaxLength = MaxLength; +} + +impl frame_system::offchain::CreateTransaction for Runtime { + type Public = ::Signer; + type Signature = Signature; + + fn create_transaction>( + call: Call, + public: Self::Public, + account: AccountId, + index: Index, + ) -> Option<(Call, ::SignaturePayload)> { + // take the biggest period possible. + let period = BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; + let current_block = System::block_number() + .saturated_into::() + // The `System::block_number` is initialized with `n+1`, + // so the actual block number is `n`. + .saturating_sub(1); + let tip = 0; + let extra: SignedExtra = ( + frame_system::CheckVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), + frame_system::CheckNonce::::from(index), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + Default::default(), + ); + let raw_payload = SignedPayload::new(call, extra).map_err(|e| { + debug::warn!("Unable to create signed payload: {:?}", e); + }).ok()?; + let signature = TSigner::sign(public, &raw_payload)?; + let address = Indices::unlookup(account); + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature, extra))) + } +} + +impl bridge_eth_poa::Trait for Runtime { + type OnHeadersSubmitted = (); +} + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = node_primitives::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Module, Call, Storage, Config, Event}, + Utility: pallet_utility::{Module, Call, Storage, Event}, + Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)}, + Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, + Authorship: pallet_authorship::{Module, Call, Storage, Inherent}, + Indices: pallet_indices, + Balances: pallet_balances, + TransactionPayment: pallet_transaction_payment::{Module, Storage}, + Staking: pallet_staking, + Session: pallet_session::{Module, Call, Storage, Event, Config}, + Democracy: pallet_democracy::{Module, Call, Storage, Config, Event}, + Council: pallet_collective::::{Module, Call, Storage, Origin, Event, Config}, + TechnicalCommittee: pallet_collective::::{Module, Call, Storage, Origin, Event, Config}, + Elections: pallet_elections_phragmen::{Module, Call, Storage, Event}, + TechnicalMembership: pallet_membership::::{Module, Call, Storage, Event, Config}, + FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent}, + Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, + Treasury: pallet_treasury::{Module, Call, Storage, Config, Event}, + Contracts: pallet_contracts, + Sudo: pallet_sudo, + ImOnline: pallet_im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, + AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config}, + Offences: pallet_offences::{Module, Call, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, + Nicks: pallet_nicks::{Module, Call, Storage, Event}, + BridgeEthPoa: bridge_eth_poa::{Module, Call, Config}, // TODO: Update this + } +); + +/// The address format for describing accounts. +pub type Address = ::Source; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, + pallet_contracts::CheckBlockGasLimit, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive, Runtime, AllModules>; + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult { + data.check_extrinsics(&block) + } + + fn random_seed() -> ::Hash { + RandomnessCollectiveFlip::random_seed() + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { + Executive::validate_transaction(tx) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + } + + impl sp_consensus_babe::BabeApi for Runtime { + fn configuration() -> sp_consensus_babe::BabeConfiguration { + // The choice of `c` parameter (where `1 - c` represents the + // probability of a slot being empty), is done in accordance to the + // slot duration and expected target block time, for safely + // resisting network delays of maximum two seconds. + // + sp_consensus_babe::BabeConfiguration { + slot_duration: Babe::slot_duration(), + epoch_length: EpochDuration::get(), + c: PRIMARY_PROBABILITY, + genesis_authorities: Babe::authorities(), + randomness: Babe::randomness(), + secondary_slots: true, + } + } + } + + impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { + fn authorities() -> Vec { + AuthorityDiscovery::authorities() + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl pallet_contracts_rpc_runtime_api::ContractsApi for Runtime { + fn call( + origin: AccountId, + dest: AccountId, + value: Balance, + gas_limit: u64, + input_data: Vec, + ) -> ContractExecResult { + let exec_result = Contracts::bare_call( + origin, + dest.into(), + value, + gas_limit, + input_data, + ); + match exec_result { + Ok(v) => ContractExecResult::Success { + status: v.status, + data: v.data, + }, + Err(_) => ContractExecResult::Error, + } + } + + fn get_storage( + address: AccountId, + key: [u8; 32], + ) -> pallet_contracts_rpc_runtime_api::GetStorageResult { + Contracts::get_storage(address, key).map_err(|rpc_err| { + use pallet_contracts::GetStorageError; + use pallet_contracts_rpc_runtime_api::{GetStorageError as RpcGetStorageError}; + /// Map the contract error into the RPC layer error. + match rpc_err { + GetStorageError::ContractDoesntExist => RpcGetStorageError::ContractDoesntExist, + GetStorageError::IsTombstone => RpcGetStorageError::IsTombstone, + } + }) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< + Block, + Balance, + UncheckedExtrinsic, + > for Runtime { + fn query_info(uxt: UncheckedExtrinsic, len: u32) -> RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + } + + impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { + fn best_block() -> (u64, sp_bridge_eth_poa::H256) { + BridgeEthPoa::best_block() + } + + fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { + BridgeEthPoa::is_import_requires_receipts(header) + } + + fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { + BridgeEthPoa::is_known_block(hash) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_system::offchain::{SignAndSubmitTransaction, SubmitSignedTransaction}; + + #[test] + fn validate_transaction_submitter_bounds() { + fn is_submit_signed_transaction() where + T: SubmitSignedTransaction< + Runtime, + Call, + >, + {} + + fn is_sign_and_submit_transaction() where + T: SignAndSubmitTransaction< + Runtime, + Call, + Extrinsic=UncheckedExtrinsic, + CreateTransaction=Runtime, + Signer=ImOnlineId, + >, + {} + + is_submit_signed_transaction::(); + is_sign_and_submit_transaction::(); + } + + #[test] + fn block_hooks_weight_should_not_exceed_limits() { + use frame_support::weights::WeighBlock; + let check_for_block = |b| { + let block_hooks_weight = + >::on_initialize(b) + + >::on_finalize(b); + + assert_eq!( + block_hooks_weight, + 0, + "This test might fail simply because the value being compared to has increased to a \ + module declaring a new weight for a hook or call. In this case update the test and \ + happily move on.", + ); + + // Invariant. Always must be like this to have a sane chain. + assert!(block_hooks_weight < MaximumBlockWeight::get()); + + // Warning. + if block_hooks_weight > MaximumBlockWeight::get() / 2 { + println!( + "block hooks weight is consuming more than a block's capacity. You probably want \ + to re-think this. This test will fail now." + ); + assert!(false); + } + }; + + let _ = (0..100_000).for_each(check_for_block); + } +} diff --git a/modules/ethereum/bridge-runtime/bin/node/testing/Cargo.toml b/modules/ethereum/bridge-runtime/bin/node/testing/Cargo.toml new file mode 100644 index 0000000000000..c0707ad0ee319 --- /dev/null +++ b/modules/ethereum/bridge-runtime/bin/node/testing/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "node-testing" +version = "2.0.0" +authors = ["Parity Technologies "] +description = "Test utilities for Substrate node." +edition = "2018" + +[dependencies] +pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } +sc-client = { version = "2.0.0", path = "../../../client/" } +codec = { package = "parity-scale-codec", version = "1.0.0" } +pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } +pallet-grandpa = { version = "2.0.0", path = "../../../frame/grandpa" } +pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } +sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } +node-executor = { version = "2.0.0", path = "../executor" } +node-primitives = { version = "2.0.0", path = "../primitives" } +node-runtime = { version = "2.0.0", path = "../runtime" } +sp-core = { version = "2.0.0", path = "../../../primitives/core" } +sp-io = { version = "2.0.0", path = "../../../primitives/io" } +frame-support = { version = "2.0.0", path = "../../../frame/support" } +pallet-session = { version = "2.0.0", path = "../../../frame/session" } +sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } +pallet-staking = { version = "2.0.0", path = "../../../frame/staking" } +sc-executor = { version = "2.0.0", path = "../../../client/executor" } +frame-system = { version = "2.0.0", path = "../../../frame/system" } +substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } +pallet-timestamp = { version = "2.0.0", path = "../../../frame/timestamp" } +pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } +pallet-treasury = { version = "2.0.0", path = "../../../frame/treasury" } +wabt = "0.9.2" +sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa" } diff --git a/modules/ethereum/bridge-runtime/bin/node/testing/src/genesis.rs b/modules/ethereum/bridge-runtime/bin/node/testing/src/genesis.rs new file mode 100644 index 0000000000000..85dddc808e7cf --- /dev/null +++ b/modules/ethereum/bridge-runtime/bin/node/testing/src/genesis.rs @@ -0,0 +1,144 @@ +// Copyright 2019-2020 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 . + +//! Genesis Configuration. + +use crate::keyring::*; +use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; +use node_runtime::{ + GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, + GrandpaConfig, IndicesConfig, ContractsConfig, WASM_BINARY, BridgeEthPoaConfig, +}; +use node_runtime::constants::currency::*; +use sp_core::ChangesTrieConfiguration; +use sp_runtime::Perbill; + + +/// Create genesis runtime configuration for tests. +pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig { + GenesisConfig { + frame_system: Some(SystemConfig { + changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { + digest_interval: 2, + digest_levels: 2, + }) } else { None }, + code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()), + }), + pallet_indices: Some(IndicesConfig { + ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], + }), + pallet_balances: Some(BalancesConfig { + balances: vec![ + (alice(), 111 * DOLLARS), + (bob(), 100 * DOLLARS), + (charlie(), 100_000_000 * DOLLARS), + (dave(), 111 * DOLLARS), + (eve(), 101 * DOLLARS), + (ferdie(), 100 * DOLLARS), + ], + vesting: vec![], + }), + pallet_session: Some(SessionConfig { + keys: vec![ + (alice(), to_session_keys( + &Ed25519Keyring::Alice, + &Sr25519Keyring::Alice, + )), + (bob(), to_session_keys( + &Ed25519Keyring::Bob, + &Sr25519Keyring::Bob, + )), + (charlie(), to_session_keys( + &Ed25519Keyring::Charlie, + &Sr25519Keyring::Charlie, + )), + ] + }), + pallet_staking: Some(StakingConfig { + current_era: 0, + stakers: vec![ + (dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator), + (eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator), + (ferdie(), charlie(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator) + ], + validator_count: 3, + minimum_validator_count: 0, + slash_reward_fraction: Perbill::from_percent(10), + invulnerables: vec![alice(), bob(), charlie()], + .. Default::default() + }), + pallet_contracts: Some(ContractsConfig { + current_schedule: Default::default(), + gas_price: 1 * MILLICENTS, + }), + pallet_babe: Some(Default::default()), + pallet_grandpa: Some(GrandpaConfig { + authorities: vec![], + }), + pallet_im_online: Some(Default::default()), + pallet_authority_discovery: Some(Default::default()), + pallet_democracy: Some(Default::default()), + pallet_collective_Instance1: Some(Default::default()), + pallet_collective_Instance2: Some(Default::default()), + pallet_membership_Instance1: Some(Default::default()), + pallet_sudo: Some(Default::default()), + pallet_treasury: Some(Default::default()), + // here comes configuration for Kovan chain + // TODO: Update Name + bridge_eth_poa: Some(BridgeEthPoaConfig { + initial_header: sp_bridge_eth_poa::Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), + uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), + extra_data: vec![], + state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), + receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 6000000.into(), + difficulty: 131072.into(), + seal: vec![ + vec![128].into(), + vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), + ], + }, + initial_difficulty: 0.into(), + initial_validators: vec![ + [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, + 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), + [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, + 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), + [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, + 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), + [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, + 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), + [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, + 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), + [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, + 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), + [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, + 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), + [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, + 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), + [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, + 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + ], + }), + } +} diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml new file mode 100644 index 0000000000000..b8f195adba5c5 --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "pallet-bridge-eth-poa" +description = "A Substrate Runtime module that is able to verify PoA headers and their finality." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } # TODO: Rename +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } # TODO: Rename +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/bridge-eth-poa", default-features = false } + +[dev-dependencies] +primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/bridge-eth-poa", features = ["std", "test-helpers"] } +parity-crypto = { version = "0.4", features = ["publickey"] } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", + "sp-io/std", + "primitives/std", +] diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/error.rs b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/error.rs new file mode 100644 index 0000000000000..f716a7e066185 --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/error.rs @@ -0,0 +1,84 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use sp_runtime::RuntimeDebug; + +/// Header import error. +#[derive(RuntimeDebug)] +#[cfg_attr(feature = "std", derive(PartialEq))] +pub enum Error { + /// The header is beyound last finalized and can not be imported. + AncientHeader, + /// The header is already imported. + KnownHeader, + /// Seal has an incorrect format. + InvalidSealArity, + /// Block number isn't sensible. + RidiculousNumber, + /// Block has too much gas used. + TooMuchGasUsed, + /// Gas limit header field is invalid. + InvalidGasLimit, + /// Extra data is of an invalid length. + ExtraDataOutOfBounds, + /// Timestamp header overflowed. + TimestampOverflow, + /// The parent header is missing from the blockchain. + MissingParentBlock, + /// The header step is missing from the header. + MissingStep, + /// The header signature is missing from the header. + MissingSignature, + /// Empty steps are missing from the header. + MissingEmptySteps, + /// The same author issued different votes at the same step. + DoubleVote, + /// Validation proof insufficient. + InsufficientProof, + /// Difficulty header field is invalid. + InvalidDifficulty, + /// The received block is from an incorrect proposer. + NotValidator, + /// Missing transaction receipts for the operation. + MissingTransactionsReceipts, + /// Provided transactions receipts are not matching the header. + TransactionsReceiptsMismatch, +} + +impl Error { + pub fn msg(&self) -> &'static str { + match *self { + Error::AncientHeader => "Header is beyound last finalized and can not be imported", + Error::KnownHeader => "Header is already imported", + Error::InvalidSealArity => "Header has an incorrect seal", + Error::RidiculousNumber => "Header has too large number", + Error::TooMuchGasUsed => "Header has too much gas used", + Error::InvalidGasLimit => "Header has invalid gas limit", + Error::ExtraDataOutOfBounds => "Header has too large extra data", + Error::TimestampOverflow => "Header has too large timestamp", + Error::MissingParentBlock => "Header has unknown parent hash", + Error::MissingStep => "Header is missing step seal", + Error::MissingSignature => "Header is missing signature seal", + Error::MissingEmptySteps => "Header is missing empty steps seal", + Error::DoubleVote => "Header has invalid step in seal", + Error::InsufficientProof => "Header has insufficient proof", + Error::InvalidDifficulty => "Header has invalid difficulty", + Error::NotValidator => "Header is sealed by unexpected validator", + Error::MissingTransactionsReceipts => "The import operation requires transactions receipts", + Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided", + } + } +} diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/finality.rs b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/finality.rs new file mode 100644 index 0000000000000..74c1660e8c6be --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/finality.rs @@ -0,0 +1,284 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use sp_std::prelude::*; +use sp_std::collections::{ + btree_map::{BTreeMap, Entry}, + btree_set::BTreeSet, + vec_deque::VecDeque, +}; +use sp_io::crypto::secp256k1_ecdsa_recover; +use primitives::{Address, H256, Header, SealedEmptyStep, public_to_address}; +use crate::{Storage, ancestry}; +use crate::error::Error; + +/// Tries to finalize blocks when given block is imported. +/// +/// Returns numbers and hashes of finalized blocks in ascending order. +pub fn finalize_blocks( + storage: &S, + best_finalized_hash: &H256, + header_validators: (&H256, &[Address]), + hash: &H256, + header: &Header, + two_thirds_majority_transition: u64, +) -> Result, Error> { + // compute count of voters for every unfinalized block in ancestry + let validators = header_validators.1.iter().collect(); + let (mut votes, mut headers) = prepare_votes( + storage, + best_finalized_hash, + &header_validators.0, + &validators, + hash, + header, + two_thirds_majority_transition, + )?; + + // now let's iterate in reverse order && find just finalized blocks + let mut newly_finalized = Vec::new(); + while let Some((oldest_hash, oldest_number, signers)) = headers.pop_front() { + if !is_finalized(&validators, &votes, oldest_number >= two_thirds_majority_transition) { + break; + } + + remove_signers_votes(&signers, &mut votes); + newly_finalized.push((oldest_number, oldest_hash)); + } + + Ok(newly_finalized) +} + +/// Returns true if there are enough votes to treat this header as finalized. +fn is_finalized( + validators: &BTreeSet<&Address>, + votes: &BTreeMap, + requires_two_thirds_majority: bool, +) -> bool { + (!requires_two_thirds_majority && votes.len() * 2 > validators.len()) || + (requires_two_thirds_majority && votes.len() * 3 > validators.len() * 2) +} + +/// Prepare 'votes' of header and its ancestors' signers. +fn prepare_votes( + storage: &S, + best_finalized_hash: &H256, + validators_begin: &H256, + validators: &BTreeSet<&Address>, + hash: &H256, + header: &Header, + two_thirds_majority_transition: u64, +) -> Result<(BTreeMap, VecDeque<(H256, u64, BTreeSet
)>), Error> { + // this fn can only work with single validators set + if !validators.contains(&header.author) { + return Err(Error::NotValidator); + } + + // prepare iterator of signers of all ancestors of the header + // we only take ancestors that are not yet pruned and those signed by + // the same set of validators + let mut parent_empty_step_signers = empty_steps_signers(header); + let ancestry = ancestry(storage, header) + .map(|(hash, header)| { + let mut signers = BTreeSet::new(); + sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); + signers.insert(header.author); + + let empty_step_signers = empty_steps_signers(&header); + let res = (hash, header.number, signers); + parent_empty_step_signers = empty_step_signers; + res + }) + .take_while(|&(hash, _, _)| hash != *validators_begin && hash != *best_finalized_hash); + + // now let's iterate built iterator and compute number of validators + // 'voted' for each header + // we stop when finalized block is met (because we only interested in + // just finalized blocks) + let mut votes = BTreeMap::new(); + let mut headers = VecDeque::new(); + for (hash, number, signers) in ancestry { + add_signers_votes(validators, &signers, &mut votes)?; + if is_finalized(validators, &votes, number >= two_thirds_majority_transition) { + remove_signers_votes(&signers, &mut votes); + break; + } + + headers.push_front((hash, number, signers)); + } + + // update votes with last header vote + let mut header_signers = BTreeSet::new(); + header_signers.insert(header.author); + *votes.entry(header.author).or_insert(0) += 1; + headers.push_back((*hash, header.number, header_signers)); + + Ok((votes, headers)) +} + +/// Increase count of 'votes' for every passed signer. +/// Fails if at least one of signers is not in the `validators` set. +fn add_signers_votes( + validators: &BTreeSet<&Address>, + signers_to_add: &BTreeSet
, + votes: &mut BTreeMap, +) -> Result<(), Error> { + for signer in signers_to_add { + if !validators.contains(signer) { + return Err(Error::NotValidator); + } + + *votes.entry(*signer).or_insert(0) += 1; + } + + Ok(()) +} + +/// Decrease 'votes' count for every passed signer. +fn remove_signers_votes(signers_to_remove: &BTreeSet
, votes: &mut BTreeMap) { + for signer in signers_to_remove { + match votes.entry(*signer) { + Entry::Occupied(mut entry) => { + if *entry.get() <= 1 { + entry.remove(); + } else { + *entry.get_mut() -= 1; + } + }, + Entry::Vacant(_) => unreachable!("we only remove signers that have been added; qed"), + } + } +} + +/// Returns unique set of empty steps signers. +fn empty_steps_signers(header: &Header) -> BTreeSet
{ + header.empty_steps() + .into_iter() + .flat_map(|steps| steps) + .filter_map(|step| empty_step_signer(&step, &header.parent_hash)) + .collect::>() +} + +/// Returns author of empty step signature. +fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option
{ + let message = empty_step.message(parent_hash); + secp256k1_ecdsa_recover(empty_step.signature.as_fixed_bytes(), message.as_fixed_bytes()) + .ok() + .map(|public| public_to_address(&public)) +} + +#[cfg(test)] +mod tests { + use crate::HeaderToImport; + use crate::tests::{InMemoryStorage, genesis, validator, validators_addresses}; + use super::*; + + #[test] + fn verifies_header_author() { + assert_eq!( + finalize_blocks( + &InMemoryStorage::new(genesis(), validators_addresses(5)), + &Default::default(), + (&Default::default(), &[]), + &Default::default(), + &Header::default(), + 0, + ), + Err(Error::NotValidator), + ); + } + + #[test] + fn prepares_votes() { + // let's say we have 5 validators (we need 'votes' from 3 validators to achieve + // finality) + let mut storage = InMemoryStorage::new(genesis(), validators_addresses(5)); + + // when header#1 is inserted, nothing is finalized (1 vote) + let header1 = Header { + author: validator(0).address().as_fixed_bytes().into(), + parent_hash: genesis().hash(), + number: 1, + ..Default::default() + }; + let hash1 = header1.hash(); + let mut header_to_import = HeaderToImport { + context: storage.import_context(&genesis().hash()).unwrap(), + is_best: true, + hash: hash1, + header: header1, + total_difficulty: 0.into(), + enacted_change: None, + scheduled_change: None, + }; + assert_eq!( + finalize_blocks( + &storage, + &Default::default(), + (&Default::default(), &validators_addresses(5)), + &hash1, + &header_to_import.header, + u64::max_value(), + ), + Ok(Vec::new()), + ); + storage.insert_header(header_to_import.clone()); + + // when header#2 is inserted, nothing is finalized (2 votes) + header_to_import.header = Header { + author: validator(1).address().as_fixed_bytes().into(), + parent_hash: hash1, + number: 2, + ..Default::default() + }; + header_to_import.hash = header_to_import.header.hash(); + let hash2 = header_to_import.header.hash(); + assert_eq!( + finalize_blocks( + &storage, + &Default::default(), + (&Default::default(), &validators_addresses(5)), + &hash2, + &header_to_import.header, + u64::max_value(), + ), + Ok(Vec::new()), + ); + storage.insert_header(header_to_import.clone()); + + // when header#3 is inserted, header#1 is finalized (3 votes) + header_to_import.header = Header { + author: validator(2).address().as_fixed_bytes().into(), + parent_hash: hash2, + number: 3, + ..Default::default() + }; + header_to_import.hash = header_to_import.header.hash(); + let hash3 = header_to_import.header.hash(); + assert_eq!( + finalize_blocks( + &storage, + &Default::default(), + (&Default::default(), &validators_addresses(5)), + &hash3, + &header_to_import.header, + u64::max_value(), + ), + Ok(vec![(1, hash1)]), + ); + storage.insert_header(header_to_import); + } +} diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/import.rs b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/import.rs new file mode 100644 index 0000000000000..318fea1bcc999 --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/import.rs @@ -0,0 +1,347 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use sp_std::prelude::*; +use primitives::{H256, Header, Receipt}; +use crate::{AuraConfiguration, Storage}; +use crate::error::Error; +use crate::finality::finalize_blocks; +use crate::validators::{Validators, ValidatorsConfiguration}; +use crate::verification::verify_aura_header; + +/// Maximal number of headers behind best blocks that we are aiming to store. When there +/// are too many unfinalized headers, it slows down finalization tracking significantly. +/// That's why we won't consider imports/reorganizations to blocks of PRUNE_DEPTH age. +/// If there's more headers than that, we prune the oldest. The only exception is +/// when unfinalized header schedules validators set change. We can't compute finality +/// for pruned headers => we won't know when to enact validators set change. That's +/// why we never prune headers with scheduled changes. +pub(crate) const PRUNE_DEPTH: u64 = 4096; + +/// Imports bunch of headers and updates blocks finality. +/// +/// Transactions receipts must be provided if `header_import_requires_receipts()` +/// has returned true. +/// If successful, returns tuple where first element is the number of useful headers +/// we have imported and the second element is the number of useless headers (duplicate) +/// we have NOT imported. +/// Returns error if fatal error has occured during import. Some valid headers may be +/// imported in this case. +pub fn import_headers( + storage: &mut S, + aura_config: &AuraConfiguration, + validators_config: &ValidatorsConfiguration, + prune_depth: u64, + headers: Vec<(Header, Option>)>, +) -> Result<(u64, u64), Error> { + let mut useful = 0; + let mut useless = 0; + for (header, receipts) in headers { + let import_result = import_header( + storage, + aura_config, + validators_config, + prune_depth, + header, + receipts, + ); + + match import_result { + Ok(_) => useful += 1, + Err(Error::AncientHeader) | Err(Error::KnownHeader) => useless += 1, + Err(error) => return Err(error), + } + } + + Ok((useful, useless)) +} + +/// Imports given header and updates blocks finality (if required). +/// +/// Transactions receipts must be provided if `header_import_requires_receipts()` +/// has returned true. +pub fn import_header( + storage: &mut S, + aura_config: &AuraConfiguration, + validators_config: &ValidatorsConfiguration, + prune_depth: u64, + header: Header, + receipts: Option>, +) -> Result { + // first check that we are able to import this header at all + let (hash, prev_finalized_hash) = is_importable_header(storage, &header)?; + + // verify header + let import_context = verify_aura_header( + storage, + aura_config, + &header, + )?; + + // check if block schedules new validators + let validators = Validators::new(validators_config); + let (scheduled_change, enacted_change) = + validators.extract_validators_change(&header, receipts)?; + + // check if block finalizes some other blocks and corresponding scheduled validators + let finalized_blocks = finalize_blocks( + storage, + &prev_finalized_hash, + (import_context.validators_start(), import_context.validators()), + &hash, + &header, + aura_config.two_thirds_majority_transition, + )?; + let enacted_change = enacted_change + .or_else(|| validators.finalize_validators_change(storage, &finalized_blocks)); + + // NOTE: we can't return Err() from anywhere below this line + // (because otherwise we'll have inconsistent storage if transaction will fail) + + // and finally insert the block + let (_, _, best_total_difficulty) = storage.best_block(); + let total_difficulty = import_context.total_difficulty() + header.difficulty; + let is_best = total_difficulty > best_total_difficulty; + let header_number = header.number; + storage.insert_header(import_context.into_import_header( + is_best, + hash, + header, + total_difficulty, + enacted_change, + scheduled_change, + )); + + // now mark finalized headers && prune old headers + storage.finalize_headers( + finalized_blocks.last().cloned(), + match is_best { + true => header_number.checked_sub(prune_depth), + false => None, + }, + ); + + Ok(hash) +} + +/// Returns true if transactions receipts are required to import given header. +pub fn header_import_requires_receipts( + storage: &S, + validators_config: &ValidatorsConfiguration, + header: &Header, +) -> bool { + is_importable_header(storage, header) + .map(|_| Validators::new(validators_config)) + .map(|validators| validators.maybe_signals_validators_change(header)) + .unwrap_or(false) +} + +/// Checks that we are able to ***try to** import this header. +/// Returns error if we should not try to import this block. +/// Returns hash of the header and number of the last finalized block. +fn is_importable_header(storage: &S, header: &Header) -> Result<(H256, H256), Error> { + // we never import any header that competes with finalized header + let (finalized_block_number, finalized_block_hash) = storage.finalized_block(); + if header.number <= finalized_block_number { + return Err(Error::AncientHeader); + } + // we never import any header with known hash + let hash = header.hash(); + if storage.header(&hash).is_some() { + return Err(Error::KnownHeader); + } + + Ok((hash, finalized_block_hash)) +} + +#[cfg(test)] +mod tests { + use crate::{kovan_aura_config, kovan_validators_config}; + use crate::tests::{ + InMemoryStorage, + block_i, custom_block_i, signed_header, genesis, + validator, validators_addresses, + }; + use crate::validators::ValidatorsSource; + use super::*; + + #[test] + fn rejects_finalized_block_competitors() { + let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + storage.finalize_headers(Some((100, Default::default())), None); + assert_eq!( + import_header( + &mut storage, + &kovan_aura_config(), + &kovan_validators_config(), + PRUNE_DEPTH, + Default::default(), + None, + ), + Err(Error::AncientHeader), + ); + } + + #[test] + fn rejects_known_header() { + let validators = (0..3).map(|i| validator(i as u8)).collect::>(); + let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + let block = block_i(&storage, 1, &validators); + assert_eq!( + import_header( + &mut storage, + &kovan_aura_config(), + &kovan_validators_config(), + PRUNE_DEPTH, + block.clone(), + None, + ).map(|_| ()), + Ok(()), + ); + assert_eq!( + import_header( + &mut storage, + &kovan_aura_config(), + &kovan_validators_config(), + PRUNE_DEPTH, + block, + None, + ).map(|_| ()), + Err(Error::KnownHeader), + ); + } + + #[test] + fn import_header_works() { + let validators_config = ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(validators_addresses(3))), + (1, ValidatorsSource::List(validators_addresses(2))), + ]); + let validators = (0..3).map(|i| validator(i as u8)).collect::>(); + let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + let header = block_i(&storage, 1, &validators); + let hash = header.hash(); + assert_eq!( + import_header(&mut storage, &kovan_aura_config(), &validators_config, PRUNE_DEPTH, header, None) + .map(|_| ()), + Ok(()), + ); + + // check that new validators will be used for next header + let imported_header = storage.stored_header(&hash).unwrap(); + assert_eq!( + imported_header.next_validators_set_id, + 1, // new set is enacted from config + ); + } + + #[test] + fn headers_are_pruned() { + let validators_config = ValidatorsConfiguration::Single( + ValidatorsSource::Contract([3; 20].into(), validators_addresses(3)), + ); + let validators = vec![validator(0), validator(1), validator(2)]; + let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + + // header [0..11] are finalizing blocks [0; 9] + // => since we want to keep 10 finalized blocks, we aren't pruning anything + let mut last_block_hash = Default::default(); + for i in 1..11 { + let header = block_i(&storage, i, &validators); + last_block_hash = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + header, + None, + ).unwrap(); + } + assert!(storage.header(&genesis().hash()).is_some()); + + // header 11 finalizes headers [10] AND schedules change + // => we prune header#0 + let header = custom_block_i(&storage, 11, &validators, |header| { + header.log_bloom = (&[0xff; 256]).into(); + header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951".parse().unwrap(); + }); + last_block_hash = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + header, + Some(vec![crate::validators::tests::validators_change_recept(last_block_hash)]), + ).unwrap(); + assert!(storage.header(&genesis().hash()).is_none()); + + // and now let's say validators 1 && 2 went offline + // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers + // until header#11 is met. we can't prune #11, because it schedules change + let mut step = 56; + for i in 12..25 { + let header = Header { + number: i as _, + parent_hash: last_block_hash, + gas_limit: 0x2000.into(), + author: validator(2).address().to_fixed_bytes().into(), + seal: vec![ + vec![step].into(), + vec![].into(), + ], + difficulty: i.into(), + ..Default::default() + }; + let header = signed_header(&validators, header, step as _); + last_block_hash = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + header, + None, + ).unwrap(); + step += 3; + } + assert_eq!(storage.oldest_unpruned_block(), 11); + + // now let's insert block signed by validator 1 + // => blocks 11..24 are finalized and blocks 11..14 are pruned + step -= 2; + let header = Header { + number: 25, + parent_hash: last_block_hash, + gas_limit: 0x2000.into(), + author: validator(0).address().to_fixed_bytes().into(), + seal: vec![ + vec![step].into(), + vec![].into(), + ], + difficulty: 25.into(), + ..Default::default() + }; + let header = signed_header(&validators, header, step as _); + import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + header, + None, + ).unwrap(); + assert_eq!(storage.oldest_unpruned_block(), 15); + } +} diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs new file mode 100644 index 0000000000000..430a950d3c779 --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs @@ -0,0 +1,740 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{prelude::*, iter::from_fn}; +use codec::{Decode, Encode}; +use frame_support::{decl_module, decl_storage}; +use sp_runtime::RuntimeDebug; +use primitives::{Address, U256, H256, Header, Receipt}; +use validators::{ValidatorsSource, ValidatorsConfiguration}; + +pub use import::{import_header, header_import_requires_receipts}; + +mod error; +mod finality; +mod import; +mod validators; +mod verification; + +/// Authority round engine configuration parameters. +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +pub struct AuraConfiguration { + /// Empty step messages transition block. + pub empty_steps_transition: u64, + /// Transition block to strict empty steps validation. + pub strict_empty_steps_transition: u64, + /// Monotonic step validation transition block. + pub validate_step_transition: u64, + /// Chain score validation transition block. + pub validate_score_transition: u64, + /// First block for which a 2/3 quorum (instead of 1/2) is required. + pub two_thirds_majority_transition: u64, + /// Minimum gas limit. + pub min_gas_limit: U256, + /// Maximum gas limit. + pub max_gas_limit: U256, + /// Maximum size of extra data. + pub maximum_extra_data_size: u64, +} + +/// Block header as it is stored in the runtime storage. +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +pub struct StoredHeader { + /// The block header itself. + pub header: Header, + /// Total difficulty of the chain. + pub total_difficulty: U256, + /// The ID of set of validators that is expected to produce direct descendants of + /// this block. If header enacts new set, this would be the new set. Otherwise + /// this is the set that has produced the block itself. + /// The hash is the hash of block where validators set has been enacted. + pub next_validators_set_id: u64, +} + +/// Header that we're importing. +#[derive(RuntimeDebug)] +#[cfg_attr(test, derive(Clone, PartialEq))] +pub struct HeaderToImport { + /// Header import context, + pub context: ImportContext, + /// Should we consider this header as best? + pub is_best: bool, + /// The hash of the header. + pub hash: H256, + /// The header itself. + pub header: Header, + /// Total chain difficulty at the header. + pub total_difficulty: U256, + /// Validators set enacted change, if happened at the header. + pub enacted_change: Option>, + /// Validators set scheduled change, if happened at the header. + pub scheduled_change: Option>, +} + +/// Header import context. +#[derive(RuntimeDebug)] +#[cfg_attr(test, derive(Clone, PartialEq))] +pub struct ImportContext { + parent_header: Header, + parent_total_difficulty: U256, + next_validators_set_id: u64, + next_validators_set: (H256, Vec
), +} + +impl ImportContext { + /// Create import context using passing parameters; + pub fn new( + parent_header: Header, + parent_total_difficulty: U256, + next_validators_set_id: u64, + next_validators_set: (H256, Vec
), + ) -> Self { + ImportContext { + parent_header, + parent_total_difficulty, + next_validators_set_id, + next_validators_set, + } + } + + /// Returns reference to parent header. + pub fn parent_header(&self) -> &Header { + &self.parent_header + } + + /// Returns total chain difficulty at parent block. + pub fn total_difficulty(&self) -> &U256 { + &self.parent_total_difficulty + } + + /// Returns id of the set of validators. + pub fn validators_set_id(&self) -> u64 { + self.next_validators_set_id + } + + /// Returns block whenre validators set has been enacted. + pub fn validators_start(&self) -> &H256 { + &self.next_validators_set.0 + } + + /// Returns reference to the set of validators of the block we're going to import. + pub fn validators(&self) -> &[Address] { + &self.next_validators_set.1 + } + + /// Converts import context into header we're going to import. + pub fn into_import_header( + self, + is_best: bool, + hash: H256, + header: Header, + total_difficulty: U256, + enacted_change: Option>, + scheduled_change: Option>, + ) -> HeaderToImport { + HeaderToImport { + context: self, + is_best, + hash, + header, + total_difficulty, + enacted_change, + scheduled_change, + } + } +} + +/// The storage that is used by the client. +/// +/// Storage modification must be discarded if block import has failed. +pub trait Storage { + /// Get best known block. + fn best_block(&self) -> (u64, H256, U256); + /// Get last finalized block. + fn finalized_block(&self) -> (u64, H256); + /// Get imported header by its hash. + fn header(&self, hash: &H256) -> Option
; + /// Get header import context by parent header hash. + fn import_context(&self, parent_hash: &H256) -> Option; + /// Get new validators that are scheduled by given header. + fn scheduled_change(&self, hash: &H256) -> Option>; + /// Insert imported header. + fn insert_header(&mut self, header: HeaderToImport); + /// Finalize given block and prune all headers with number < prune_end. + /// The headers in the pruning range could be either finalized, or not. + /// It is the storage duty to ensure that unfinalized headers that have + /// scheduled changes won't be pruned until they or their competitors + /// are finalized. + fn finalize_headers( + &mut self, + finalized: Option<(u64, H256)>, + prune_end: Option, + ); +} + +/// Decides whether the session should be ended. +pub trait OnHeadersSubmitted { + /// Called when valid headers have been submitted. + fn on_valid_headers_submitted(submitter: AccountId, useful: u64, useless: u64); + /// Called when invalid headers have been submitted. + fn on_invalid_headers_submitted(submitter: AccountId); +} + +impl OnHeadersSubmitted for () { + fn on_valid_headers_submitted(_submitter: AccountId, _useful: u64, _useless: u64) {} + fn on_invalid_headers_submitted(_submitter: AccountId) {} +} + +/// The module configuration trait +pub trait Trait: frame_system::Trait { + /// Handler for headers submission result. + type OnHeadersSubmitted: OnHeadersSubmitted; +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Import Aura chain headers. Ignores non-fatal errors (like when known + /// header is provided), rewards for successful headers import and penalizes + /// for fatal errors. + /// + /// This should be used with caution - passing too many headers could lead to + /// enormous block production/import time. + pub fn import_headers(origin, headers_with_receipts: Vec<(Header, Option>)>) { + let submitter = frame_system::ensure_signed(origin)?; + let import_result = import::import_headers( + &mut BridgeStorage, + &kovan_aura_config(), + &kovan_validators_config(), + crate::import::PRUNE_DEPTH, + headers_with_receipts, + ); + + match import_result { + Ok((useful, useless)) => + T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), + Err(error) => { + // even though we may have accept some headers, we do not want to reward someone + // who provides invalid headers + T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter); + return Err(error.msg().into()); + }, + } + } + } +} + +decl_storage! { + trait Store for Module as Bridge { + /// Best known block. + BestBlock: (u64, H256, U256); + /// Best finalized block. + FinalizedBlock: (u64, H256); + /// Oldest unpruned block(s) number. + OldestUnprunedBlock: u64; + /// Map of imported headers by hash. + Headers: map H256 => Option; + /// Map of imported header hashes by number. + HeadersByNumber: map u64 => Option>; + /// The ID of next validator set. + NextValidatorsSetId: u64; + /// Map of validators sets by their id. + ValidatorsSets: map u64 => Option<(H256, Vec
)>; + /// Validators sets reference count. Each header that is authored by this set increases + /// the reference count. When we prune this header, we decrease the reference count. + /// When it reaches zero, we are free to prune validator set as well. + ValidatorsSetsRc: map u64 => Option; + /// Map of validators set changes scheduled by given header. + ScheduledChanges: map H256 => Option>; + } + add_extra_genesis { + config(initial_header): Header; + config(initial_difficulty): U256; + config(initial_validators): Vec
; + build(|config| { + // the initial blocks should be selected so that: + // 1) it doesn't signal validators changes; + // 2) there are no scheduled validators changes from previous blocks; + // 3) (implied) all direct children of initial block are authred by the same validators set. + + assert!( + !config.initial_validators.is_empty(), + "Initial validators set can't be empty", + ); + + let initial_hash = config.initial_header.hash(); + BestBlock::put((config.initial_header.number, initial_hash, config.initial_difficulty)); + FinalizedBlock::put((config.initial_header.number, initial_hash)); + OldestUnprunedBlock::put(config.initial_header.number); + HeadersByNumber::insert(config.initial_header.number, vec![initial_hash]); + Headers::insert(initial_hash, StoredHeader { + header: config.initial_header.clone(), + total_difficulty: config.initial_difficulty, + next_validators_set_id: 0, + }); + NextValidatorsSetId::put(1); + ValidatorsSets::insert(0, (initial_hash, config.initial_validators.clone())); + ValidatorsSetsRc::insert(0, 1); + }) + } +} + +impl Module { + /// Returns number and hash of the best block known to the bridge module. + /// The caller should only submit `import_header` transaction that makes + /// (or leads to making) other header the best one. + pub fn best_block() -> (u64, H256) { + let (number, hash, _) = BridgeStorage.best_block(); + (number, hash) + } + + /// Returns true if the import of given block requires transactions receipts. + pub fn is_import_requires_receipts(header: Header) -> bool { + import::header_import_requires_receipts( + &BridgeStorage, + &kovan_validators_config(), + &header, + ) + } + + /// Returns true if header is known to the runtime. + pub fn is_known_block(hash: H256) -> bool { + BridgeStorage.header(&hash).is_some() + } +} + +/// Runtime bridge storage. +struct BridgeStorage; + +impl Storage for BridgeStorage { + fn best_block(&self) -> (u64, H256, U256) { + BestBlock::get() + } + + fn finalized_block(&self) -> (u64, H256) { + FinalizedBlock::get() + } + + fn header(&self, hash: &H256) -> Option
{ + Headers::get(hash).map(|header| header.header) + } + + fn import_context(&self, parent_hash: &H256) -> Option { + Headers::get(parent_hash) + .map(|parent_header| { + let (next_validators_set_start, next_validators) = + ValidatorsSets::get(parent_header.next_validators_set_id) + .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); + ImportContext { + parent_header: parent_header.header, + parent_total_difficulty: parent_header.total_difficulty, + next_validators_set_id: parent_header.next_validators_set_id, + next_validators_set: (next_validators_set_start, next_validators), + } + }) + } + + fn scheduled_change(&self, hash: &H256) -> Option> { + ScheduledChanges::get(hash) + } + + fn insert_header(&mut self, header: HeaderToImport) { + if header.is_best { + BestBlock::put((header.header.number, header.hash, header.total_difficulty)); + } + if let Some(scheduled_change) = header.scheduled_change { + ScheduledChanges::insert(&header.hash, scheduled_change); + } + let next_validators_set_id = match header.enacted_change { + Some(enacted_change) => { + let next_validators_set_id = NextValidatorsSetId::mutate(|set_id| { + let next_set_id = *set_id; + *set_id += 1; + next_set_id + }); + ValidatorsSets::insert(next_validators_set_id, (header.hash, enacted_change)); + ValidatorsSetsRc::insert(next_validators_set_id, 1); + next_validators_set_id + }, + None => { + ValidatorsSetsRc::mutate( + header.context.next_validators_set_id, + |rc| { + *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); + *rc + }, + ); + header.context.next_validators_set_id + }, + }; + + HeadersByNumber::append_or_insert(header.header.number, vec![header.hash]); + Headers::insert(&header.hash, StoredHeader { + header: header.header, + total_difficulty: header.total_difficulty, + next_validators_set_id, + }); + } + + fn finalize_headers( + &mut self, + finalized: Option<(u64, H256)>, + prune_end: Option, + ) { + // remember just finalized block + let finalized_number = finalized.as_ref().map(|f| f.0).unwrap_or_else(|| FinalizedBlock::get().0); + if let Some(finalized) = finalized { + FinalizedBlock::put(finalized); + } + + if let Some(prune_end) = prune_end { + let prune_begin = OldestUnprunedBlock::get(); + + for number in prune_begin..prune_end { + let blocks_at_number = HeadersByNumber::take(number); + + // ensure that unfinalized headers we want to prune do not have scheduled changes + if number > finalized_number { + if let Some(ref blocks_at_number) = blocks_at_number { + if blocks_at_number.iter().any(|block| ScheduledChanges::exists(block)) { + HeadersByNumber::insert(number, blocks_at_number); + OldestUnprunedBlock::put(number); + return; + } + } + } + + // physically remove headers and (probably) obsolete validators sets + for hash in blocks_at_number.into_iter().flat_map(|x| x) { + let header = Headers::take(&hash); + ScheduledChanges::remove(hash); + if let Some(header) = header { + ValidatorsSetsRc::mutate( + header.next_validators_set_id, + |rc| match *rc { + Some(rc) if rc > 1 => Some(rc - 1), + _ => None, + }, + ); + } + } + } + + OldestUnprunedBlock::put(prune_end); + } + } +} + +/// Aura engine configuration for Kovan chain. +pub fn kovan_aura_config() -> AuraConfiguration { + AuraConfiguration { + empty_steps_transition: u64::max_value(), + strict_empty_steps_transition: 0, + validate_step_transition: 0x16e360, + validate_score_transition: 0x41a3c4, + two_thirds_majority_transition: u64::max_value(), + min_gas_limit: 0x1388.into(), + max_gas_limit: U256::max_value(), + maximum_extra_data_size: 0x20, + } +} + +/// Validators configuration for Kovan chain. +pub fn kovan_validators_config() -> ValidatorsConfiguration { + ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(vec![ + [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, + 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), + [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, + 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), + [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, + 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), + [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, + 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), + [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, + 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), + [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, + 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), + [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, + 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), + [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, + 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), + [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, + 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + ])), + (10960440, ValidatorsSource::List(vec![ + [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, + 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), + [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, + 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), + [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, + 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + ])), + (10960500, ValidatorsSource::Contract( + [0xaE, 0x71, 0x80, 0x7C, 0x1B, 0x0a, 0x09, 0x3c, 0xB1, 0x54, + 0x7b, 0x68, 0x2D, 0xC7, 0x83, 0x16, 0xD9, 0x45, 0xc9, 0xB8].into(), + vec![ + [0xd0, 0x5f, 0x74, 0x78, 0xc6, 0xaa, 0x10, 0x78, 0x12, 0x58, + 0xc5, 0xcc, 0x8b, 0x4f, 0x38, 0x5f, 0xc8, 0xfa, 0x98, 0x9c].into(), + [0x03, 0x80, 0x1e, 0xfb, 0x0e, 0xfe, 0x2a, 0x25, 0xed, 0xe5, + 0xdd, 0x3a, 0x00, 0x3a, 0xe8, 0x80, 0xc0, 0x29, 0x2e, 0x4d].into(), + [0xa4, 0xdf, 0x25, 0x5e, 0xcf, 0x08, 0xbb, 0xf2, 0xc2, 0x80, + 0x55, 0xc6, 0x52, 0x25, 0xc9, 0xa9, 0x84, 0x7a, 0xbd, 0x94].into(), + [0x59, 0x6e, 0x82, 0x21, 0xa3, 0x0b, 0xfe, 0x6e, 0x7e, 0xff, + 0x67, 0xfe, 0xe6, 0x64, 0xa0, 0x1c, 0x73, 0xba, 0x3c, 0x56].into(), + [0xfa, 0xad, 0xfa, 0xce, 0x3f, 0xbd, 0x81, 0xce, 0x37, 0xb0, + 0xe1, 0x9c, 0x0b, 0x65, 0xff, 0x42, 0x34, 0x14, 0x81, 0x32].into(), + ], + )), + ]) +} + +/// Return iterator of given header ancestors. +pub(crate) fn ancestry<'a, S: Storage>(storage: &'a S, header: &Header) -> impl Iterator + 'a { + let mut parent_hash = header.parent_hash.clone(); + from_fn(move || { + let header = storage.header(&parent_hash); + match header { + Some(header) => { + if header.number == 0 { + return None; + } + + let hash = parent_hash.clone(); + parent_hash = header.parent_hash.clone(); + Some((hash, header)) + }, + None => None + } + }) +} + +#[cfg(test)] +pub(crate) mod tests { + use std::collections::{HashMap, hash_map::Entry}; + use parity_crypto::publickey::{KeyPair, Secret, sign}; + use primitives::{H520, rlp_encode}; + use super::*; + + pub fn genesis() -> Header { + Header { + seal: vec![ + vec![42].into(), + vec![].into(), + ], + ..Default::default() + } + } + + pub fn block_i(storage: &InMemoryStorage, number: u64, validators: &[KeyPair]) -> Header { + custom_block_i(storage, number, validators, |_| {}) + } + + pub fn custom_block_i( + storage: &InMemoryStorage, + number: u64, + validators: &[KeyPair], + customize: impl FnOnce(&mut Header), + ) -> Header { + let validator_index: u8 = (number % (validators.len() as u64)) as _; + let mut header = Header { + number, + parent_hash: storage.headers_by_number[&(number - 1)][0].clone(), + gas_limit: 0x2000.into(), + author: validator(validator_index).address().to_fixed_bytes().into(), + seal: vec![ + vec![number as u8 + 42].into(), + vec![].into(), + ], + difficulty: number.into(), + ..Default::default() + }; + customize(&mut header); + signed_header(validators, header, number + 42) + } + + pub fn signed_header(validators: &[KeyPair], mut header: Header, step: u64) -> Header { + let message = header.seal_hash(false).unwrap(); + let validator_index = (step % validators.len() as u64) as usize; + let signature = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()).unwrap(); + let signature: [u8; 65] = signature.into(); + let signature = H520::from(signature); + header.seal[1] = rlp_encode(&signature); + header + } + + pub fn validator(index: u8) -> KeyPair { + KeyPair::from_secret(Secret::from([index + 1; 32])).unwrap() + } + + pub fn validators_addresses(count: u8) -> Vec
{ + (0..count as usize).map(|i| validator(i as u8).address().as_fixed_bytes().into()).collect() + } + + pub struct InMemoryStorage { + best_block: (u64, H256, U256), + finalized_block: (u64, H256), + oldest_unpruned_block: u64, + headers: HashMap, + headers_by_number: HashMap>, + next_validators_set_id: u64, + validators_sets: HashMap)>, + validators_sets_rc: HashMap, + scheduled_changes: HashMap>, + } + + impl InMemoryStorage { + pub fn new(initial_header: Header, initial_validators: Vec
) -> Self { + let hash = initial_header.hash(); + InMemoryStorage { + best_block: (initial_header.number, hash, 0.into()), + finalized_block: (initial_header.number, hash), + oldest_unpruned_block: initial_header.number, + headers_by_number: vec![(initial_header.number, vec![hash])].into_iter().collect(), + headers: vec![( + hash, + StoredHeader { + header: initial_header, + total_difficulty: 0.into(), + next_validators_set_id: 0, + }, + )].into_iter().collect(), + next_validators_set_id: 1, + validators_sets: vec![(0, (hash, initial_validators))].into_iter().collect(), + validators_sets_rc: vec![(0, 1)].into_iter().collect(), + scheduled_changes: HashMap::new(), + } + } + + pub(crate) fn oldest_unpruned_block(&self) -> u64 { + self.oldest_unpruned_block + } + + pub(crate) fn stored_header(&self, hash: &H256) -> Option<&StoredHeader> { + self.headers.get(hash) + } + } + + impl Storage for InMemoryStorage { + fn best_block(&self) -> (u64, H256, U256) { + self.best_block.clone() + } + + fn finalized_block(&self) -> (u64, H256) { + self.finalized_block.clone() + } + + fn header(&self, hash: &H256) -> Option
{ + self.headers.get(hash).map(|header| header.header.clone()) + } + + fn import_context(&self, parent_hash: &H256) -> Option { + self.headers.get(parent_hash) + .map(|parent_header| { + let (next_validators_set_start, next_validators) = + self.validators_sets.get(&parent_header.next_validators_set_id).unwrap(); + ImportContext { + parent_header: parent_header.header.clone(), + parent_total_difficulty: parent_header.total_difficulty, + next_validators_set_id: parent_header.next_validators_set_id, + next_validators_set: (*next_validators_set_start, next_validators.clone()), + } + }) + } + + fn scheduled_change(&self, hash: &H256) -> Option> { + self.scheduled_changes.get(hash).cloned() + } + + fn insert_header(&mut self, header: HeaderToImport) { + if header.is_best { + self.best_block = (header.header.number, header.hash, header.total_difficulty); + } + if let Some(scheduled_change) = header.scheduled_change { + self.scheduled_changes.insert(header.hash, scheduled_change); + } + let next_validators_set_id = match header.enacted_change { + Some(enacted_change) => { + let next_validators_set_id = self.next_validators_set_id; + self.next_validators_set_id += 1; + self.validators_sets.insert(next_validators_set_id, (header.hash, enacted_change)); + self.validators_sets_rc.insert(next_validators_set_id, 1); + next_validators_set_id + }, + None => { + *self.validators_sets_rc.entry(header.context.next_validators_set_id).or_default() += 1; + header.context.next_validators_set_id + }, + }; + + self.headers_by_number.entry(header.header.number).or_default().push(header.hash); + self.headers.insert(header.hash, StoredHeader { + header: header.header, + total_difficulty: header.total_difficulty, + next_validators_set_id, + }); + } + + fn finalize_headers( + &mut self, + finalized: Option<(u64, H256)>, + prune_end: Option, + ) { + let finalized_number = finalized.as_ref().map(|f| f.0).unwrap_or_else(|| self.finalized_block.0); + if let Some(finalized) = finalized { + self.finalized_block = finalized; + } + + if let Some(prune_end) = prune_end { + let prune_begin = self.oldest_unpruned_block; + + for number in prune_begin..prune_end { + let blocks_at_number = self.headers_by_number.remove(&number); + + // ensure that unfinalized headers we want to prune do not have scheduled changes + if number > finalized_number { + if let Some(ref blocks_at_number) = blocks_at_number { + if blocks_at_number.iter().any(|block| self.scheduled_changes.contains_key(block)) { + self.headers_by_number.insert(number, blocks_at_number.clone()); + self.oldest_unpruned_block = number; + return; + } + } + } + + // physically remove headers and (probably) obsolete validators sets + for hash in blocks_at_number.into_iter().flat_map(|x| x) { + let header = self.headers.remove(&hash); + self.scheduled_changes.remove(&hash); + if let Some(header) = header { + match self.validators_sets_rc.entry(header.next_validators_set_id) { + Entry::Occupied(mut entry) => if *entry.get() == 1 { + entry.remove(); + } else { + *entry.get_mut() -= 1; + }, + Entry::Vacant(_) => unreachable!("there's entry for each header") + }; + } + } + } + + self.oldest_unpruned_block = prune_end; + } + } + } +} diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/validators.rs b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/validators.rs new file mode 100644 index 0000000000000..db1eacd3b3318 --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/validators.rs @@ -0,0 +1,394 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use sp_std::prelude::*; +use primitives::{Address, H256, Header, LogEntry, Receipt, U256}; +use crate::Storage; +use crate::error::Error; + +/// The hash of InitiateChange event of the validators set contract. +const CHANGE_EVENT_HASH: &'static [u8; 32] = &[0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, + 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, 0xd2, 0xc2, 0x28, 0x1d, 0xf8, 0xd6, 0xea, + 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89]; + +/// Where source of validators addresses come from. This covers the chain lifetime. +pub enum ValidatorsConfiguration { + /// There's a single source for the whole chain lifetime. + Single(ValidatorsSource), + /// Validators source changes at given blocks. The blocks are ordered + /// by the block number. + Multi(Vec<(u64, ValidatorsSource)>), +} + +/// Where validators addresses come from. +/// +/// This source is valid within some blocks range. The blocks range could +/// cover multiple epochs - i.e. the validators that are authoring blocks +/// within this range could change, but the source itself can not. +#[cfg_attr(test, derive(Debug, PartialEq))] +pub enum ValidatorsSource { + /// The validators addresses are hardcoded and never change. + List(Vec
), + /// The validators addresses are determined by the validators set contract + /// deployed at given address. The contract must implement the `ValidatorSet` + /// interface. Additionally, the initial validators set must be provided. + Contract(Address, Vec
), +} + +/// Validators manager. +pub struct Validators<'a> { + config: &'a ValidatorsConfiguration, +} + +impl<'a> Validators<'a> { + /// Creates new validators manager using given configuration. + pub fn new(config: &'a ValidatorsConfiguration) -> Self { + Self { config } + } + + /// Returns true if header (probabilistically) signals validators change and + /// the caller needs to provide transactions receipts to import the header. + pub fn maybe_signals_validators_change(&self, header: &Header) -> bool { + let (_, _, source) = self.source_at(header.number); + + // if we are taking validators set from the fixed list, there's always + // single epoch + // => we never require transactions receipts + let contract_address = match source { + ValidatorsSource::List(_) => return false, + ValidatorsSource::Contract(contract_address, _) => contract_address, + }; + + // else we need to check logs bloom and if it has required bits set, it means + // that the contract has (probably) emitted epoch change event + let expected_bloom = LogEntry { + address: *contract_address, + topics: vec![ + CHANGE_EVENT_HASH.into(), + header.parent_hash, + ], + data: Vec::new(), // irrelevant for bloom. + }.bloom(); + + header.log_bloom.contains(&expected_bloom) + } + + /// Extracts validators change signal from the header. + /// + /// Returns tuple where first element is the change scheduled by this header + /// (i.e. this change is only applied starting from the block that has finalized + /// current block). The second element is the immediately applied change. + pub fn extract_validators_change( + &self, + header: &Header, + receipts: Option>, + ) -> Result<(Option>, Option>), Error> { + // let's first check if new source is starting from this header + let (source_index, _, source) = self.source_at(header.number); + let (next_starts_at, next_source) = self.source_at_next_header(source_index, header.number); + if next_starts_at == header.number { + match *next_source { + ValidatorsSource::List(ref new_list) => return Ok((None, Some(new_list.clone()))), + ValidatorsSource::Contract(_, ref new_list) => return Ok((Some(new_list.clone()), None)), + } + } + + // else deal with previous source + // + // if we are taking validators set from the fixed list, there's always + // single epoch + // => we never require transactions receipts + let contract_address = match source { + ValidatorsSource::List(_) => return Ok((None, None)), + ValidatorsSource::Contract(contract_address, _) => contract_address, + }; + + // else we need to check logs bloom and if it has required bits set, it means + // that the contract has (probably) emitted epoch change event + let expected_bloom = LogEntry { + address: *contract_address, + topics: vec![ + CHANGE_EVENT_HASH.into(), + header.parent_hash, + ], + data: Vec::new(), // irrelevant for bloom. + }.bloom(); + + if !header.log_bloom.contains(&expected_bloom) { + return Ok((None, None)); + } + + let receipts = receipts.ok_or(Error::MissingTransactionsReceipts)?; + if !header.check_transactions_receipts(&receipts) { + return Err(Error::TransactionsReceiptsMismatch); + } + + // iterate in reverse because only the _last_ change in a given + // block actually has any effect + Ok((receipts.iter() + .rev() + .filter(|r| r.log_bloom.contains(&expected_bloom)) + .flat_map(|r| r.logs.iter()) + .filter(|l| l.address == *contract_address && + l.topics.len() == 2 && + l.topics[0].as_fixed_bytes() == CHANGE_EVENT_HASH && + l.topics[1] == header.parent_hash + ) + .filter_map(|l| { + let data_len = l.data.len(); + if data_len < 64 { + return None; + } + + let new_validators_len_u256 = U256::from_big_endian(&l.data[32..64]); + let new_validators_len = new_validators_len_u256.low_u64(); + if new_validators_len_u256 != new_validators_len.into() { + return None; + } + + if (data_len - 64) as u64 != new_validators_len.saturating_mul(32) { + return None; + } + + Some(l.data[64..] + .chunks(32) + .map(|chunk| { + let mut new_validator = Address::default(); + new_validator.as_mut().copy_from_slice(&chunk[12..32]); + new_validator + }) + .collect()) + }) + .next(), None)) + } + + /// Finalize changes when blocks are finalized. + pub fn finalize_validators_change( + &self, + storage: &mut S, + finalized_blocks: &[(u64, H256)], + ) -> Option> { + for (_, finalized_hash) in finalized_blocks.iter().rev() { + if let Some(changes) = storage.scheduled_change(finalized_hash) { + return Some(changes); + } + } + None + } + + /// Returns source of validators that should author the header. + fn source_at<'b>(&'b self, header_number: u64) -> (usize, u64, &'b ValidatorsSource) { + match self.config { + ValidatorsConfiguration::Single(ref source) => (0, 0, source), + ValidatorsConfiguration::Multi(ref sources) => sources.iter().rev() + .enumerate() + .find(|(_, &(begin, _))| begin < header_number) + .map(|(i, (begin, source))| (sources.len() - 1 - i, *begin, source)) + .expect("there's always entry for the initial block;\ + we do not touch any headers with number < initial block number; qed"), + } + } + + /// Returns source of validators that should author the next header. + fn source_at_next_header<'b>( + &'b self, + header_source_index: usize, + header_number: u64, + ) -> (u64, &'b ValidatorsSource) { + match self.config { + ValidatorsConfiguration::Single(ref source) => (0, source), + ValidatorsConfiguration::Multi(ref sources) => { + let next_source_index = header_source_index + 1; + if next_source_index < sources.len() { + let next_source = &sources[next_source_index]; + if next_source.0 < header_number + 1 { + return (next_source.0, &next_source.1); + } + } + + let source = &sources[header_source_index]; + (source.0, &source.1) + }, + } + } +} + +impl ValidatorsSource { + /// Returns initial validators set. + pub fn initial_epoch_validators(&self) -> Vec
{ + match self { + ValidatorsSource::List(ref list) => list.clone(), + ValidatorsSource::Contract(_, ref list) => list.clone(), + } + } +} + +/// Get validator that should author the block at given step. +pub fn step_validator(header_validators: &[Address], header_step: u64) -> Address { + header_validators[(header_step % header_validators.len() as u64) as usize] +} + +#[cfg(test)] +pub(crate) mod tests { + use primitives::TransactionOutcome; + use crate::kovan_validators_config; + use super::*; + + pub(crate) fn validators_change_recept(parent_hash: H256) -> Receipt { + Receipt { + gas_used: 0.into(), + log_bloom: (&[0xff; 256]).into(), + outcome: TransactionOutcome::Unknown, + logs: vec![ + LogEntry { + address: [3; 20].into(), + topics: vec![ + CHANGE_EVENT_HASH.into(), + parent_hash, + ], + data: vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + ], + }, + ], + } + } + + #[test] + fn source_at_works() { + let config = ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(vec![[1; 20].into()])), + (100, ValidatorsSource::List(vec![[2; 20].into()])), + (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), + ]); + let validators = Validators::new(&config); + + assert_eq!( + validators.source_at(99), + (0, 0, &ValidatorsSource::List(vec![[1; 20].into()])), + ); + assert_eq!( + validators.source_at_next_header(0, 99), + (0, &ValidatorsSource::List(vec![[1; 20].into()])), + ); + + assert_eq!( + validators.source_at(100), + (0, 0, &ValidatorsSource::List(vec![[1; 20].into()])), + ); + assert_eq!( + validators.source_at_next_header(0, 100), + (100, &ValidatorsSource::List(vec![[2; 20].into()])), + ); + + assert_eq!( + validators.source_at(200), + (1, 100, &ValidatorsSource::List(vec![[2; 20].into()])), + ); + assert_eq!( + validators.source_at_next_header(1, 200), + (200, &ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), + ); + } + + #[test] + fn maybe_signals_validators_change_works() { + // when contract is active, but bloom has no required bits set + let config = kovan_validators_config(); + let validators = Validators::new(&config); + let mut header = Header::default(); + header.number = u64::max_value(); + assert!(!validators.maybe_signals_validators_change(&header)); + + // when contract is active and bloom has required bits set + header.log_bloom = (&[0xff; 256]).into(); + assert!(validators.maybe_signals_validators_change(&header)); + + // when list is active and bloom has required bits set + let config = ValidatorsConfiguration::Single(ValidatorsSource::List(vec![[42; 20].into()])); + let validators = Validators::new(&config); + assert!(!validators.maybe_signals_validators_change(&header)); + } + + #[test] + fn extract_validators_change_works() { + let config = ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(vec![[1; 20].into()])), + (100, ValidatorsSource::List(vec![[2; 20].into()])), + (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), + ]); + let validators = Validators::new(&config); + let mut header = Header::default(); + + // when we're at the block that switches to list source + header.number = 100; + assert_eq!( + validators.extract_validators_change(&header, None), + Ok((None, Some(vec![[2; 20].into()]))), + ); + + // when we're inside list range + header.number = 150; + assert_eq!( + validators.extract_validators_change(&header, None), + Ok((None, None)), + ); + + // when we're at the block that switches to contract source + header.number = 200; + assert_eq!( + validators.extract_validators_change(&header, None), + Ok((Some(vec![[3; 20].into()]), None)), + ); + + // when we're inside contract range and logs bloom signals change + // but we have no receipts + header.number = 250; + header.log_bloom = (&[0xff; 256]).into(); + assert_eq!( + validators.extract_validators_change(&header, None), + Err(Error::MissingTransactionsReceipts), + ); + + // when we're inside contract range and logs bloom signals change + // but there's no change in receipts + header.receipts_root = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(); + assert_eq!( + validators.extract_validators_change(&header, Some(Vec::new())), + Ok((None, None)), + ); + + // when we're inside contract range and logs bloom signals change + // and there's change in receipts + let receipts = vec![validators_change_recept(Default::default())]; + header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45".parse().unwrap(); + assert_eq!( + validators.extract_validators_change(&header, Some(receipts)), + Ok((Some(vec![[7; 20].into()]), None)), + ); + + // when incorrect receipts root passed + assert_eq!( + validators.extract_validators_change(&header, Some(Vec::new())), + Err(Error::TransactionsReceiptsMismatch), + ); + } +} diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/verification.rs b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/verification.rs new file mode 100644 index 0000000000000..10574db327644 --- /dev/null +++ b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/verification.rs @@ -0,0 +1,448 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +use sp_io::crypto::secp256k1_ecdsa_recover; +use primitives::{Address, Header, H256, H520, SealedEmptyStep, U128, U256, public_to_address}; +use crate::{AuraConfiguration, ImportContext, Storage}; +use crate::error::Error; +use crate::validators::step_validator; + +/// Verify header by Aura rules. +pub fn verify_aura_header( + storage: &S, + params: &AuraConfiguration, + header: &Header, +) -> Result { + // let's do the lightest check first + contextless_checks(params, header)?; + + // the rest of checks requires parent + let context = storage.import_context(&header.parent_hash).ok_or(Error::MissingParentBlock)?; + let validators = context.validators(); + let header_step = header.step().ok_or(Error::MissingStep)?; + let parent_step = context.parent_header().step().ok_or(Error::MissingStep)?; + + // Ensure header is from the step after context. + if header_step == parent_step + || (header.number >= params.validate_step_transition && header_step <= parent_step) { + return Err(Error::DoubleVote); + } + + // If empty step messages are enabled we will validate the messages in the seal, missing messages are not + // reported as there's no way to tell whether the empty step message was never sent or simply not included. + let empty_steps_len = match header.number >= params.empty_steps_transition { + true => { + let strict_empty_steps = header.number >= params.strict_empty_steps_transition; + let empty_steps = header.empty_steps().ok_or(Error::MissingEmptySteps)?; + let empty_steps_len = empty_steps.len(); + let mut prev_empty_step = 0; + + for empty_step in empty_steps { + if empty_step.step <= parent_step || empty_step.step >= header_step { + return Err(Error::InsufficientProof); + } + + if !verify_empty_step(&header.parent_hash, &empty_step, validators) { + return Err(Error::InsufficientProof); + } + + if strict_empty_steps { + if empty_step.step <= prev_empty_step { + return Err(Error::InsufficientProof); + } + + prev_empty_step = empty_step.step; + } + } + + empty_steps_len + }, + false => 0, + }; + + // Validate chain score. + if header.number >= params.validate_score_transition { + let expected_difficulty = calculate_score(parent_step, header_step, empty_steps_len as _); + if header.difficulty != expected_difficulty { + return Err(Error::InvalidDifficulty); + } + } + + let expected_validator = step_validator(validators, header_step); + if header.author != expected_validator { + return Err(Error::NotValidator); + } + + let validator_signature = header.signature().ok_or(Error::MissingSignature)?; + let header_seal_hash = header + .seal_hash(header.number >= params.empty_steps_transition) + .ok_or(Error::MissingEmptySteps)?; + let is_invalid_proposer = !verify_signature(&expected_validator, &validator_signature, &header_seal_hash); + if is_invalid_proposer { + return Err(Error::NotValidator); + } + + Ok(context) +} + +/// Perform basic checks that only require header iteself. +fn contextless_checks(config: &AuraConfiguration, header: &Header) -> Result<(), Error> { + let expected_seal_fields = expected_header_seal_fields(config, header); + if header.seal.len() != expected_seal_fields { + return Err(Error::InvalidSealArity); + } + if header.number >= u64::max_value() { + return Err(Error::RidiculousNumber); + } + if header.gas_used > header.gas_limit { + return Err(Error::TooMuchGasUsed); + } + if header.gas_limit < config.min_gas_limit { + return Err(Error::InvalidGasLimit); + } + if header.gas_limit > config.max_gas_limit { + return Err(Error::InvalidGasLimit); + } + if header.number != 0 && header.extra_data.len() as u64 > config.maximum_extra_data_size { + return Err(Error::ExtraDataOutOfBounds); + } + + // we can't detect if block is from future in runtime + // => let's only do an overflow check + if header.timestamp > i32::max_value() as u64 { + return Err(Error::TimestampOverflow); + } + + Ok(()) +} + +/// Returns expected number of seal fields in the header. +fn expected_header_seal_fields(config: &AuraConfiguration, header: &Header) -> usize { + if header.number >= config.empty_steps_transition { + 3 + } else { + 2 + } +} + +/// Verify single sealed empty step. +fn verify_empty_step(parent_hash: &H256, step: &SealedEmptyStep, validators: &[Address]) -> bool { + let expected_validator = step_validator(validators, step.step); + let message = step.message(parent_hash); + verify_signature(&expected_validator, &step.signature, &message) +} + +/// Chain scoring: total weight is sqrt(U256::max_value())*height - step +fn calculate_score(parent_step: u64, current_step: u64, current_empty_steps: usize) -> U256 { + U256::from(U128::max_value()) + U256::from(parent_step) - U256::from(current_step) + U256::from(current_empty_steps) +} + +/// Verify that the signature over message has been produced by given validator. +fn verify_signature(expected_validator: &Address, signature: &H520, message: &H256) -> bool { + secp256k1_ecdsa_recover(signature.as_fixed_bytes(), message.as_fixed_bytes()) + .map(|public| public_to_address(&public)) + .map(|address| *expected_validator == address) + .unwrap_or(false) +} + +#[cfg(test)] +mod tests { + use parity_crypto::publickey::{KeyPair, sign}; + use primitives::{H520, rlp_encode}; + use crate::kovan_aura_config; + use crate::tests::{InMemoryStorage, genesis, signed_header, validator, validators_addresses}; + use super::*; + + fn sealed_empty_step(validators: &[KeyPair], parent_hash: &H256, step: u64) -> SealedEmptyStep { + let mut empty_step = SealedEmptyStep { step, signature: Default::default() }; + let message = empty_step.message(parent_hash); + let validator_index = (step % validators.len() as u64) as usize; + let signature: [u8; 65] = sign( + validators[validator_index].secret(), + &message.as_fixed_bytes().into(), + ).unwrap().into(); + empty_step.signature = signature.into(); + empty_step + } + + fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result { + let storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + verify_aura_header(&storage, &config, header) + } + + fn default_verify(header: &Header) -> Result { + verify_with_config(&kovan_aura_config(), header) + } + + #[test] + fn verifies_seal_count() { + // when there are no seals at all + let mut header = Header::default(); + assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); + + // when there's single seal (we expect 2 or 3 seals) + header.seal = vec![vec![].into()]; + assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); + + // when there's 3 seals (we expect 2 on Kovan) + header.seal = vec![vec![].into(), vec![].into(), vec![].into()]; + assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); + + // when there's 2 seals + header.seal = vec![vec![].into(), vec![].into()]; + assert_ne!(default_verify(&header), Err(Error::InvalidSealArity)); + } + + #[test] + fn verifies_header_number() { + // when number is u64::max_value() + let mut header = Header { + seal: vec![vec![].into(), vec![].into(), vec![].into()], + number: u64::max_value(), + ..Default::default() + }; + assert_eq!(default_verify(&header), Err(Error::RidiculousNumber)); + + // when header is < u64::max_value() + header.seal = vec![vec![].into(), vec![].into()]; + header.number -= 1; + assert_ne!(default_verify(&header), Err(Error::RidiculousNumber)); + } + + #[test] + fn verifies_gas_used() { + // when gas used is larger than gas limit + let mut header = Header { + seal: vec![vec![].into(), vec![].into()], + gas_used: 1.into(), + gas_limit: 0.into(), + ..Default::default() + }; + assert_eq!(default_verify(&header), Err(Error::TooMuchGasUsed)); + + // when gas used is less than gas limit + header.gas_limit = 1.into(); + assert_ne!(default_verify(&header), Err(Error::TooMuchGasUsed)); + } + + #[test] + fn verifies_gas_limit() { + let mut config = kovan_aura_config(); + config.min_gas_limit = 100.into(); + config.max_gas_limit = 200.into(); + + // when limit is lower than expected + let mut header = Header { + seal: vec![vec![].into(), vec![].into()], + gas_limit: 50.into(), + ..Default::default() + }; + assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); + + // when limit is larger than expected + header.gas_limit = 250.into(); + assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); + + // when limit is within expected range + header.gas_limit = 150.into(); + assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); + } + + #[test] + fn verifies_extra_data_len() { + // when extra data is too large + let mut header = Header { + seal: vec![vec![].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + extra_data: std::iter::repeat(42).take(1000).collect::>().into(), + number: 1, + ..Default::default() + }; + assert_eq!(default_verify(&header), Err(Error::ExtraDataOutOfBounds)); + + // when extra data size is OK + header.extra_data = std::iter::repeat(42).take(10).collect::>().into(); + assert_ne!(default_verify(&header), Err(Error::ExtraDataOutOfBounds)); + } + + #[test] + fn verifies_timestamp() { + // when timestamp overflows i32 + let mut header = Header { + seal: vec![vec![].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + timestamp: i32::max_value() as u64 + 1, + ..Default::default() + }; + assert_eq!(default_verify(&header), Err(Error::TimestampOverflow)); + + // when timestamp doesn't overflow i32 + header.timestamp -= 1; + assert_ne!(default_verify(&header), Err(Error::TimestampOverflow)); + } + + #[test] + fn verifies_parent_existence() { + // when there's no parent in the storage + let mut header = Header { + seal: vec![vec![].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + ..Default::default() + }; + assert_eq!(default_verify(&header), Err(Error::MissingParentBlock)); + + // when parent is in the storage + header.parent_hash = genesis().hash(); + assert_ne!(default_verify(&header), Err(Error::MissingParentBlock)); + } + + #[test] + fn verifies_step() { + // when step is missing from seals + let mut header = Header { + seal: vec![vec![].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: genesis().hash(), + ..Default::default() + }; + assert_eq!(default_verify(&header), Err(Error::MissingStep)); + + // when step is the same as for the parent block + header.seal = vec![ + vec![42].into(), + vec![].into(), + ]; + assert_eq!(default_verify(&header), Err(Error::DoubleVote)); + + // when step is OK + header.seal = vec![ + vec![43].into(), + vec![].into(), + ]; + assert_ne!(default_verify(&header), Err(Error::DoubleVote)); + + // now check with validate_step check enabled + let mut config = kovan_aura_config(); + config.validate_step_transition = 0; + + // when step is lesser that for the parent block + header.seal = vec![ + vec![40].into(), + vec![].into(), + ]; + assert_eq!(verify_with_config(&config, &header), Err(Error::DoubleVote)); + + // when step is OK + header.seal = vec![ + vec![44].into(), + vec![].into(), + ]; + assert_ne!(verify_with_config(&config, &header), Err(Error::DoubleVote)); + } + + #[test] + fn verifies_empty_step() { + let validators = vec![validator(0), validator(1), validator(2)]; + let mut config = kovan_aura_config(); + config.empty_steps_transition = 0; + + // when empty step duplicates parent step + let mut header = Header { + seal: vec![ + vec![45].into(), + vec![142].into(), + SealedEmptyStep::rlp_of(&[ + sealed_empty_step(&validators, &genesis().hash(), 42), + ]), + ], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: genesis().hash(), + ..Default::default() + }; + assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); + + // when empty step signature check fails + let mut wrong_sealed_empty_step = sealed_empty_step(&validators, &genesis().hash(), 43); + wrong_sealed_empty_step.signature = Default::default(); + header.seal[2] = SealedEmptyStep::rlp_of(&[wrong_sealed_empty_step]); + assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); + + // when we are accepting strict empty steps and they come not in order + config.strict_empty_steps_transition = 0; + header.seal[2] = SealedEmptyStep::rlp_of(&[ + sealed_empty_step(&validators, &genesis().hash(), 44), + sealed_empty_step(&validators, &genesis().hash(), 43), + ]); + assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); + + // when empty steps are OK + header.seal[2] = SealedEmptyStep::rlp_of(&[ + sealed_empty_step(&validators, &genesis().hash(), 43), + sealed_empty_step(&validators, &genesis().hash(), 44), + ]); + assert_ne!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); + } + + #[test] + fn verifies_chain_score() { + let mut config = kovan_aura_config(); + config.validate_score_transition = 0; + + // when chain score is invalid + let mut header = Header { + seal: vec![ + vec![43].into(), + vec![].into(), + ], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: genesis().hash(), + ..Default::default() + }; + assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); + + // when chain score is accepted + header.difficulty = calculate_score(42, 43, 0); + assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); + } + + #[test] + fn verifies_validator() { + let validators = vec![validator(0), validator(1), validator(2)]; + let good_header = signed_header(&validators, Header { + author: validators[1].address().as_fixed_bytes().into(), + seal: vec![ + vec![43].into(), + vec![].into(), + ], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: genesis().hash(), + ..Default::default() + }, 43); + + // when header author is invalid + let mut header = good_header.clone(); + header.author = Default::default(); + assert_eq!(default_verify(&header), Err(Error::NotValidator)); + + // when header signature is invalid + let mut header = good_header.clone(); + header.seal[1] = rlp_encode(&H520::default()); + assert_eq!(default_verify(&header), Err(Error::NotValidator)); + + // when everything is OK + assert_eq!(default_verify(&good_header).map(|_| ()), Ok(())); + } +} diff --git a/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml b/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml new file mode 100644 index 0000000000000..11c4d46ee26ce --- /dev/null +++ b/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "sp-bridge-eth-poa" +description = "Primitives of Ethereum PoA Bridge module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0", optional = true } +serde-big-array = { version = "0.2", optional = true } +ethbloom = { version = "0.8", default-features = false } +parity-bytes = { version = "0.1", default-features = false } +primitive-types = { version = "0.6", default-features = false, features = ["codec", "rlp"] } +fixed-hash = { version = "0.5", default-features = false } +impl-rlp = { version = "0.2", default-features = false } +impl-serde = { version = "0.2.3", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +rlp = { version = "0.4", default-features = false } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } +sp-api = { version = "2.0.0", path = "../api", default-features = false } +sp-io = { version = "2.0.0", default-features = false, path = "../io" } +hash-db = { version = "0.15.2", default-features = false } +triehash = { version = "0.8.2", default-features = false } +plain_hasher = { version = "0.2.2", default-features = false } + +[features] +default = ["std"] +test-helpers = [] +std = [ + "serde/std", + "serde-big-array", + "ethbloom/std", + "parity-bytes/std", + "primitive-types/std", + "primitive-types/serde", + "fixed-hash/std", + "impl-rlp/std", + "impl-serde", + "codec/std", + "rlp/std", + "sp-std/std", + "sp-runtime/std", + "sp-api/std", + "sp-io/std", + "hash-db/std", + "triehash/std", + "plain_hasher/std", +] diff --git a/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/src/lib.rs b/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/src/lib.rs new file mode 100644 index 0000000000000..f2a7ab7f14f17 --- /dev/null +++ b/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/src/lib.rs @@ -0,0 +1,361 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Parity-Bridge. + +// Parity-Bridge 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-Bridge 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-Bridge. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use parity_bytes::Bytes; +pub use primitive_types::{H160, H256, H512, U128, U256}; + +#[cfg(feature = "test-helpers")] +pub use rlp::encode as rlp_encode; + +use sp_std::prelude::*; +use sp_io::hashing::keccak_256; +use codec::{Decode, Encode}; +use ethbloom::{Bloom as EthBloom, Input as BloomInput}; +use rlp::{Decodable, DecoderError, Rlp, RlpStream}; +use sp_runtime::RuntimeDebug; +use fixed_hash::construct_fixed_hash; + +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +#[cfg(feature = "std")] +use serde_big_array::big_array; +use impl_rlp::impl_fixed_hash_rlp; +#[cfg(feature = "std")] +use impl_serde::impl_fixed_hash_serde; + +construct_fixed_hash! { pub struct H520(65); } +impl_fixed_hash_rlp!(H520, 65); +#[cfg(feature = "std")] +impl_fixed_hash_serde!(H520, 65); + +/// An ethereum address. +pub type Address = H160; + +/// An Aura header. +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Default, Serialize, Deserialize))] +pub struct Header { + /// Parent block hash. + pub parent_hash: H256, + /// Block timestamp. + pub timestamp: u64, + /// Block number. + pub number: u64, + /// Block author. + pub author: Address, + + /// Transactions root. + pub transactions_root: H256, + /// Block uncles hash. + pub uncles_hash: H256, + /// Block extra data. + pub extra_data: Bytes, + + /// State root. + pub state_root: H256, + /// Block receipts root. + pub receipts_root: H256, + /// Block bloom. + pub log_bloom: Bloom, + /// Gas used for contracts execution. + pub gas_used: U256, + /// Block gas limit. + pub gas_limit: U256, + + /// Block difficulty. + pub difficulty: U256, + /// Vector of post-RLP-encoded fields. + pub seal: Vec, +} + +/// Information describing execution of a transaction. +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +pub struct Receipt { + /// The total gas used in the block following execution of the transaction. + pub gas_used: U256, + /// The OR-wide combination of all logs' blooms for this transaction. + pub log_bloom: Bloom, + /// The logs stemming from this transaction. + pub logs: Vec, + /// Transaction outcome. + pub outcome: TransactionOutcome, +} + +/// Transaction outcome store in the receipt. +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +pub enum TransactionOutcome { + /// Status and state root are unknown under EIP-98 rules. + Unknown, + /// State root is known. Pre EIP-98 and EIP-658 rules. + StateRoot(H256), + /// Status code is known. EIP-658 rules. + StatusCode(u8), +} + +/// A record of execution for a `LOG` operation. +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +pub struct LogEntry { + /// The address of the contract executing at the point of the `LOG` operation. + pub address: Address, + /// The topics associated with the `LOG` operation. + pub topics: Vec, + /// The data associated with the `LOG` operation. + pub data: Bytes, +} + +/// Logs bloom. +#[derive(Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Bloom( + #[cfg_attr(feature = "std", serde(with = "BigArray"))] + [u8; 256] +); + +#[cfg(feature = "std")] +big_array! { BigArray; } + +/// An empty step message that is included in a seal, the only difference is that it doesn't include +/// the `parent_hash` in order to save space. The included signature is of the original empty step +/// message, which can be reconstructed by using the parent hash of the block in which this sealed +/// empty message is included. +pub struct SealedEmptyStep { + /// Signature of the original message author. + pub signature: H520, + /// The step this message is generated for. + pub step: u64, +} + +impl Header { + /// Get the hash of this header (keccak of the RLP with seal). + pub fn hash(&self) -> H256 { + keccak_256(&self.rlp(true)).into() + } + + /// Check if passed transactions receipts are matching this header. + pub fn check_transactions_receipts(&self, receipts: &Vec) -> bool { + struct Keccak256Hasher; + + impl hash_db::Hasher for Keccak256Hasher { + type Out = H256; + type StdHasher = plain_hasher::PlainHasher; + const LENGTH: usize = 32; + fn hash(x: &[u8]) -> Self::Out { + keccak_256(x).into() + } + } + + let receipts = receipts.iter().map(|r| r.rlp()); + let actual_root = triehash::ordered_trie_root::(receipts); + let expected_root = self.receipts_root; + actual_root == expected_root + } + + /// Gets the seal hash of this header. + pub fn seal_hash(&self, include_empty_steps: bool) -> Option { + Some(match include_empty_steps { + true => { + let mut message = self.hash().as_bytes().to_vec(); + message.extend_from_slice(self.seal.get(2)?); + keccak_256(&message).into() + }, + false => keccak_256(&self.rlp(false)).into(), + }) + } + + /// Get step this header is generated for. + pub fn step(&self) -> Option { + self.seal.get(0).map(|x| Rlp::new(&x)).and_then(|x| x.as_val().ok()) + } + + /// Get header author' signature. + pub fn signature(&self) -> Option { + self.seal.get(1).and_then(|x| Rlp::new(x).as_val().ok()) + } + + /// Extracts the empty steps from the header seal. + pub fn empty_steps(&self) -> Option> { + self.seal.get(2).and_then(|x| Rlp::new(x).as_list::().ok()) + } + + /// Returns header RLP with or without seals. + fn rlp(&self, with_seal: bool) -> Bytes { + let mut s = RlpStream::new(); + if with_seal { + s.begin_list(13 + self.seal.len()); + } else { + s.begin_list(13); + } + + s.append(&self.parent_hash); + s.append(&self.uncles_hash); + s.append(&self.author); + s.append(&self.state_root); + s.append(&self.transactions_root); + s.append(&self.receipts_root); + s.append(&EthBloom::from(self.log_bloom.0)); + s.append(&self.difficulty); + s.append(&self.number); + s.append(&self.gas_limit); + s.append(&self.gas_used); + s.append(&self.timestamp); + s.append(&self.extra_data); + + if with_seal { + for b in &self.seal { + s.append_raw(b, 1); + } + } + + s.out() + } +} + +impl Receipt { + /// Returns receipt RLP. + fn rlp(&self) -> Bytes { + let mut s = RlpStream::new(); + match self.outcome { + TransactionOutcome::Unknown => { + s.begin_list(3); + }, + TransactionOutcome::StateRoot(ref root) => { + s.begin_list(4); + s.append(root); + }, + TransactionOutcome::StatusCode(ref status_code) => { + s.begin_list(4); + s.append(status_code); + }, + } + s.append(&self.gas_used); + s.append(&EthBloom::from(self.log_bloom.0)); + + s.begin_list(self.logs.len()); + for log in &self.logs { + s.begin_list(3); + s.append(&log.address); + s.begin_list(log.topics.len()); + for topic in &log.topics { + s.append(topic); + } + s.append(&log.data); + } + + s.out() + } +} + +impl SealedEmptyStep { + /// Returns message that has to be signed by the validator. + pub fn message(&self, parent_hash: &H256) -> H256 { + let mut message = RlpStream::new_list(2); + message.append(&self.step); + message.append(parent_hash); + keccak_256(&message.out()).into() + } + + /// Returns rlp for the vector of empty steps (we only do encoding in tests). + #[cfg(feature = "test-helpers")] + pub fn rlp_of(empty_steps: &[SealedEmptyStep]) -> Bytes { + let mut s = RlpStream::new(); + s.begin_list(empty_steps.len()); + for empty_step in empty_steps { + s.begin_list(2) + .append(&empty_step.signature) + .append(&empty_step.step); + } + s.out() + } +} + +impl Decodable for SealedEmptyStep { + fn decode(rlp: &Rlp) -> Result { + let signature: H520 = rlp.val_at(0)?; + let step = rlp.val_at(1)?; + + Ok(SealedEmptyStep { signature, step }) + } +} + +impl LogEntry { + /// Calculates the bloom of this log entry. + pub fn bloom(&self) -> Bloom { + let eth_bloom = self.topics.iter().fold(EthBloom::from(BloomInput::Raw(self.address.as_bytes())), |mut b, t| { + b.accrue(BloomInput::Raw(t.as_bytes())); + b + }); + Bloom(*eth_bloom.data()) + } +} + +impl Bloom { + /// Returns true if this bloom has all bits from the other set. + pub fn contains(&self, other: &Bloom) -> bool { + self.0.iter().zip(other.0.iter()).all(|(l, r)| (l & r) == *r) + } +} + +impl<'a> From<&'a [u8; 256]> for Bloom { + fn from(buffer: &'a [u8; 256]) -> Bloom { + Bloom(*buffer) + } +} + +impl PartialEq for Bloom { + fn eq(&self, other: &Bloom) -> bool { + self.0.iter().zip(other.0.iter()).all(|(l, r)| l == r) + } +} + +#[cfg(feature = "std")] +impl Default for Bloom { + fn default() -> Self { + Bloom([0; 256]) + } +} + +#[cfg(feature = "std")] +impl std::fmt::Debug for Bloom { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("Bloom").finish() + } +} + +/// Convert public key into corresponding ethereum address. +pub fn public_to_address(public: &[u8; 64]) -> Address { + let hash = keccak_256(public); + let mut result = Address::zero(); + result.as_bytes_mut().copy_from_slice(&hash[12..]); + result +} + +sp_api::decl_runtime_apis! { + /// API for headers submitters. + pub trait EthereumHeadersApi { + /// Returns number and hash of the best block known to the bridge module. + /// The caller should only submit `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_block() -> (u64, H256); + + /// Returns true if the import of given block requires transactions receipts. + fn is_import_requires_receipts(header: Header) -> bool; + + /// Returns true if header is known to the runtime. + fn is_known_block(hash: H256) -> bool; + } +} diff --git a/modules/ethereum/bridge-runtime/primitives/core/src/hasher.rs b/modules/ethereum/bridge-runtime/primitives/core/src/hasher.rs new file mode 100644 index 0000000000000..bb0bd665bc7ee --- /dev/null +++ b/modules/ethereum/bridge-runtime/primitives/core/src/hasher.rs @@ -0,0 +1,85 @@ +// Copyright 2018-2020 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 . + +//! Substrate Blake2b Hasher implementation + +use hash_db::Hasher; +use hash256_std_hasher::Hash256StdHasher; +use crate::hash::H256; + +pub mod blake2 { + use super::{Hasher, Hash256StdHasher, H256}; + #[cfg(feature = "std")] + use crate::hashing::blake2_256; + + #[cfg(not(feature = "std"))] + extern "C" { + fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); + } + #[cfg(not(feature = "std"))] + fn blake2_256(data: &[u8]) -> [u8; 32] { + let mut result: [u8; 32] = Default::default(); + unsafe { + ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + } + result + } + + /// Concrete implementation of Hasher using Blake2b 256-bit hashes + #[derive(Debug)] + pub struct Blake2Hasher; + + impl Hasher for Blake2Hasher { + type Out = H256; + type StdHasher = Hash256StdHasher; + const LENGTH: usize = 32; + fn hash(x: &[u8]) -> Self::Out { + blake2_256(x).into() + } + } +} + +pub mod keccak256 { + use super::{Hasher, Hash256StdHasher, H256}; + #[cfg(feature = "std")] + use crate::hashing::keccak_256; + + #[cfg(not(feature = "std"))] + extern "C" { + fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); + } + #[cfg(not(feature = "std"))] + fn keccak_256(data: &[u8]) -> [u8; 32] { + let mut result: [u8; 32] = Default::default(); + unsafe { + ext_keccak_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); + } + result + } + + /// Concrete implementation of Hasher using Keccak 256-bit hashes + #[derive(Debug)] + pub struct Keccak256Hasher; + + impl Hasher for Keccak256Hasher { + type Out = H256; + type StdHasher = Hash256StdHasher; + const LENGTH: usize = 32; + fn hash(x: &[u8]) -> Self::Out { + keccak_256(x).into() + } + } +} diff --git a/modules/ethereum/bridge-runtime/primitives/core/src/lib.rs b/modules/ethereum/bridge-runtime/primitives/core/src/lib.rs new file mode 100644 index 0000000000000..0092f892b79ba --- /dev/null +++ b/modules/ethereum/bridge-runtime/primitives/core/src/lib.rs @@ -0,0 +1,312 @@ +// Copyright 2017-2020 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 . + +//! Shareable Substrate types. + +#![warn(missing_docs)] + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Initialize a key-value collection from array. +/// +/// Creates a vector of given pairs and calls `collect` on the iterator from it. +/// Can be used to create a `HashMap`. +#[macro_export] +macro_rules! map { + ($( $name:expr => $value:expr ),* $(,)? ) => ( + vec![ $( ( $name, $value ) ),* ].into_iter().collect() + ); +} + +use sp_std::prelude::*; +use sp_std::ops::Deref; +#[cfg(feature = "std")] +use std::borrow::Cow; +#[cfg(feature = "std")] +use serde::{Serialize, Deserialize}; +#[cfg(feature = "std")] +pub use serde; +#[doc(hidden)] +pub use codec::{Encode, Decode}; + +pub use sp_debug_derive::RuntimeDebug; + +#[cfg(feature = "std")] +pub use impl_serde::serialize as bytes; + +#[cfg(feature = "full_crypto")] +pub mod hashing; +#[cfg(feature = "full_crypto")] +pub use hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256, keccak_256}; +#[cfg(feature = "std")] +pub mod hexdisplay; +pub mod crypto; + +pub mod u32_trait; + +pub mod ed25519; +pub mod sr25519; +pub mod ecdsa; +pub mod hash; +mod hasher; +pub mod offchain; +pub mod sandbox; +pub mod uint; +mod changes_trie; +#[cfg(feature = "std")] +pub mod traits; +pub mod testing; + +#[cfg(test)] +mod tests; + +pub use self::hash::{H160, H256, H512, convert_hash}; +pub use self::uint::U256; +pub use changes_trie::ChangesTrieConfiguration; +#[cfg(feature = "full_crypto")] +pub use crypto::{DeriveJunction, Pair, Public}; + +pub use hash_db::Hasher; +// Switch back to Blake after PoC-3 is out +// pub use self::hasher::blake::BlakeHasher; +pub use self::hasher::blake2::Blake2Hasher; +pub use self::hasher::keccak256::Keccak256Hasher; + +pub use sp_storage as storage; + +#[doc(hidden)] +pub use sp_std; + +/// Context for executing a call into the runtime. +pub enum ExecutionContext { + /// Context for general importing (including own blocks). + Importing, + /// Context used when syncing the blockchain. + Syncing, + /// Context used for block construction. + BlockConstruction, + /// Context used for offchain calls. + /// + /// This allows passing offchain extension and customizing available capabilities. + OffchainCall(Option<(Box, offchain::Capabilities)>), +} + +impl ExecutionContext { + /// Returns the capabilities of particular context. + pub fn capabilities(&self) -> offchain::Capabilities { + use ExecutionContext::*; + + match self { + Importing | Syncing | BlockConstruction => + offchain::Capabilities::none(), + // Enable keystore by default for offchain calls. CC @bkchr + OffchainCall(None) => [offchain::Capability::Keystore][..].into(), + OffchainCall(Some((_, capabilities))) => *capabilities, + } + } +} + +/// Hex-serialized shim for `Vec`. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))] +pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); + +impl From> for Bytes { + fn from(s: Vec) -> Self { Bytes(s) } +} + +impl From for Bytes { + fn from(s: OpaqueMetadata) -> Self { Bytes(s.0) } +} + +impl Deref for Bytes { + type Target = [u8]; + fn deref(&self) -> &[u8] { &self.0[..] } +} + +/// Stores the encoded `RuntimeMetadata` for the native side as opaque type. +#[derive(Encode, Decode, PartialEq)] +pub struct OpaqueMetadata(Vec); + +impl OpaqueMetadata { + /// Creates a new instance with the given metadata blob. + pub fn new(metadata: Vec) -> Self { + OpaqueMetadata(metadata) + } +} + +impl sp_std::ops::Deref for OpaqueMetadata { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// Something that is either a native or an encoded value. +#[cfg(feature = "std")] +pub enum NativeOrEncoded { + /// The native representation. + Native(R), + /// The encoded representation. + Encoded(Vec) +} + +#[cfg(feature = "std")] +impl sp_std::fmt::Debug for NativeOrEncoded { + fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + hexdisplay::HexDisplay::from(&self.as_encoded().as_ref()).fmt(f) + } +} + +#[cfg(feature = "std")] +impl NativeOrEncoded { + /// Return the value as the encoded format. + pub fn as_encoded(&self) -> Cow<'_, [u8]> { + match self { + NativeOrEncoded::Encoded(e) => Cow::Borrowed(e.as_slice()), + NativeOrEncoded::Native(n) => Cow::Owned(n.encode()), + } + } + + /// Return the value as the encoded format. + pub fn into_encoded(self) -> Vec { + match self { + NativeOrEncoded::Encoded(e) => e, + NativeOrEncoded::Native(n) => n.encode(), + } + } +} + +#[cfg(feature = "std")] +impl PartialEq for NativeOrEncoded { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (NativeOrEncoded::Native(l), NativeOrEncoded::Native(r)) => l == r, + (NativeOrEncoded::Native(n), NativeOrEncoded::Encoded(e)) | + (NativeOrEncoded::Encoded(e), NativeOrEncoded::Native(n)) => + Some(n) == codec::Decode::decode(&mut &e[..]).ok().as_ref(), + (NativeOrEncoded::Encoded(l), NativeOrEncoded::Encoded(r)) => l == r, + } + } +} + +/// A value that is never in a native representation. +/// This is type is useful in conjuction with `NativeOrEncoded`. +#[cfg(feature = "std")] +#[derive(PartialEq)] +pub enum NeverNativeValue {} + +#[cfg(feature = "std")] +impl codec::Encode for NeverNativeValue { + fn encode(&self) -> Vec { + // The enum is not constructable, so this function should never be callable! + unreachable!() + } +} + +#[cfg(feature = "std")] +impl codec::EncodeLike for NeverNativeValue {} + +#[cfg(feature = "std")] +impl codec::Decode for NeverNativeValue { + fn decode(_: &mut I) -> Result { + Err("`NeverNativeValue` should never be decoded".into()) + } +} + +/// Provide a simple 4 byte identifier for a type. +pub trait TypeId { + /// Simple 4 byte identifier. + const TYPE_ID: [u8; 4]; +} + +/// A log level matching the one from `log` crate. +/// +/// Used internally by `sp_io::log` method. +#[derive(Encode, Decode, sp_runtime_interface::pass_by::PassByEnum, Copy, Clone)] +pub enum LogLevel { + /// `Error` log level. + Error = 1, + /// `Warn` log level. + Warn = 2, + /// `Info` log level. + Info = 3, + /// `Debug` log level. + Debug = 4, + /// `Trace` log level. + Trace = 5, +} + +impl From for LogLevel { + fn from(val: u32) -> Self { + match val { + x if x == LogLevel::Warn as u32 => LogLevel::Warn, + x if x == LogLevel::Info as u32 => LogLevel::Info, + x if x == LogLevel::Debug as u32 => LogLevel::Debug, + x if x == LogLevel::Trace as u32 => LogLevel::Trace, + _ => LogLevel::Error, + } + } +} + +impl From for LogLevel { + fn from(l: log::Level) -> Self { + use log::Level::*; + match l { + Error => Self::Error, + Warn => Self::Warn, + Info => Self::Info, + Debug => Self::Debug, + Trace => Self::Trace, + } + } +} + +impl From for log::Level { + fn from(l: LogLevel) -> Self { + use self::LogLevel::*; + match l { + Error => Self::Error, + Warn => Self::Warn, + Info => Self::Info, + Debug => Self::Debug, + Trace => Self::Trace, + } + } +} + +/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`. +/// +/// When Substrate calls into Wasm it expects a fixed signature for functions exported +/// from the Wasm blob. The return value of this signature is always a `u64`. +/// This `u64` stores the pointer to the encoded return value and the length of this encoded value. +/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length. +#[cfg(not(feature = "std"))] +pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 { + let encoded = value.encode(); + + let ptr = encoded.as_ptr() as u64; + let length = encoded.len() as u64; + let res = ptr | (length << 32); + + // Leak the output vector to avoid it being freed. + // This is fine in a WASM context since the heap + // will be discarded after the call. + sp_std::mem::forget(encoded); + + res +} diff --git a/modules/ethereum/bridge-runtime/primitives/io/Cargo.toml b/modules/ethereum/bridge-runtime/primitives/io/Cargo.toml new file mode 100644 index 0000000000000..04350c9479ede --- /dev/null +++ b/modules/ethereum/bridge-runtime/primitives/io/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "sp-io" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false } +hash-db = { version = "0.15.2", default-features = false } +sp-core = { version = "2.0.0", default-features = false, path = "../core" } +sp-std = { version = "2.0.0", default-features = false, path = "../std" } +libsecp256k1 = { version = "0.3.4", optional = true } +sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" } +sp-runtime-interface = { version = "2.0.0", default-features = false, path = "../runtime-interface" } +sp-trie = { version = "2.0.0", optional = true, path = "../../primitives/trie" } +sp-externalities = { version = "2.0.0", optional = true, path = "../externalities" } +log = { version = "0.4.8", optional = true } + +[features] +default = ["std"] +std = [ + "sp-core/std", + "codec/std", + "sp-std/std", + "hash-db/std", + "sp-trie", + "sp-state-machine", + "libsecp256k1", + "sp-runtime-interface/std", + "sp-externalities", + "log", +] + +# These two features are used for `no_std` builds for the environments which already provides +# `#[panic_handler]`, `#[alloc_error_handler]` and `#[global_allocator]`. +# +# For the regular wasm runtime builds those are not used. +disable_panic_handler = [] +disable_oom = [] +disable_allocator = [] diff --git a/modules/ethereum/bridge-runtime/primitives/io/src/lib.rs b/modules/ethereum/bridge-runtime/primitives/io/src/lib.rs new file mode 100644 index 0000000000000..8a87028da6678 --- /dev/null +++ b/modules/ethereum/bridge-runtime/primitives/io/src/lib.rs @@ -0,0 +1,974 @@ +// Copyright 2017-2020 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 . + +//! This is part of the Substrate runtime. + +#![warn(missing_docs)] + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] + +#![cfg_attr(feature = "std", + doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] +#![cfg_attr(not(feature = "std"), + doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] + +use sp_std::vec::Vec; + +#[cfg(feature = "std")] +use sp_std::ops::Deref; + +#[cfg(feature = "std")] +use sp_core::{ + crypto::Pair, + traits::KeystoreExt, + offchain::{OffchainExt, TransactionPoolExt}, + hexdisplay::HexDisplay, + storage::{ChildStorageKey, ChildInfo}, +}; + +use sp_core::{ + crypto::KeyTypeId, ed25519, sr25519, H256, LogLevel, + offchain::{ + Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, + }, +}; + +#[cfg(feature = "std")] +use ::sp_trie::{TrieConfiguration, trie_types::Layout}; + +use sp_runtime_interface::{runtime_interface, Pointer}; + +use codec::{Encode, Decode}; + +#[cfg(feature = "std")] +use sp_externalities::{ExternalitiesExt, Externalities}; + +/// Error verifying ECDSA signature +#[derive(Encode, Decode)] +pub enum EcdsaVerifyError { + /// Incorrect value of R or S + BadRS, + /// Incorrect value of V + BadV, + /// Invalid signature + BadSignature, +} + +/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage +/// key or panics otherwise. +/// +/// Panicking here is aligned with what the `without_std` environment would do +/// in the case of an invalid child storage key. +#[cfg(feature = "std")] +fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { + match ChildStorageKey::from_slice(storage_key) { + Some(storage_key) => storage_key, + None => panic!("child storage key is invalid"), + } +} + +/// Interface for accessing the storage from within the runtime. +#[runtime_interface] +pub trait Storage { + /// Returns the data for `key` in the storage or `None` if the key can not be found. + fn get(&self, key: &[u8]) -> Option> { + self.storage(key).map(|s| s.to_vec()) + } + + /// All Child api uses : + /// - A `child_storage_key` to define the anchor point for the child proof + /// (commonly the location where the child root is stored in its parent trie). + /// - A `child_storage_types` to identify the kind of the child type and how its + /// `child definition` parameter is encoded. + /// - A `child_definition_parameter` which is the additional information required + /// to use the child trie. For instance defaults child tries requires this to + /// contain a collision free unique id. + /// + /// This function specifically returns the data for `key` in the child storage or `None` + /// if the key can not be found. + fn child_get( + &self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) -> Option> { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.child_storage(storage_key, child_info, key).map(|s| s.to_vec()) + } + + /// Get `key` from storage, placing the value into `value_out` and return the number of + /// bytes that the entry in storage has beyond the offset or `None` if the storage entry + /// doesn't exist at all. + /// If `value_out` length is smaller than the returned length, only `value_out` length bytes + /// are copied into `value_out`. + fn read(&self, key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option { + self.storage(key).map(|value| { + let value_offset = value_offset as usize; + let data = &value[value_offset.min(value.len())..]; + let written = std::cmp::min(data.len(), value_out.len()); + value_out[..written].copy_from_slice(&data[..written]); + value.len() as u32 + }) + } + + /// Get `key` from child storage, placing the value into `value_out` and return the number + /// of bytes that the entry in storage has beyond the offset or `None` if the storage entry + /// doesn't exist at all. + /// If `value_out` length is smaller than the returned length, only `value_out` length bytes + /// are copied into `value_out`. + /// + /// See `child_get` for common child api parameters. + fn child_read( + &self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + value_out: &mut [u8], + value_offset: u32, + ) -> Option { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.child_storage(storage_key, child_info, key) + .map(|value| { + let value_offset = value_offset as usize; + let data = &value[value_offset.min(value.len())..]; + let written = std::cmp::min(data.len(), value_out.len()); + value_out[..written].copy_from_slice(&data[..written]); + value.len() as u32 + }) + } + + /// Set `key` to `value` in the storage. + fn set(&mut self, key: &[u8], value: &[u8]) { + self.set_storage(key.to_vec(), value.to_vec()); + } + + /// Set `key` to `value` in the child storage denoted by `child_storage_key`. + /// + /// See `child_get` for common child api parameters. + fn child_set( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + value: &[u8], + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.set_child_storage(storage_key, child_info, key.to_vec(), value.to_vec()); + } + + /// Clear the storage of the given `key` and its value. + fn clear(&mut self, key: &[u8]) { + self.clear_storage(key) + } + + /// Clear the given child storage of the given `key` and its value. + /// + /// See `child_get` for common child api parameters. + fn child_clear( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.clear_child_storage(storage_key, child_info, key); + } + + /// Clear an entire child storage. + /// + /// See `child_get` for common child api parameters. + fn child_storage_kill( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.kill_child_storage(storage_key, child_info); + } + + /// Check whether the given `key` exists in storage. + fn exists(&self, key: &[u8]) -> bool { + self.exists_storage(key) + } + + /// Check whether the given `key` exists in storage. + /// + /// See `child_get` for common child api parameters. + fn child_exists( + &self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) -> bool { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.exists_child_storage(storage_key, child_info, key) + } + + /// Clear the storage of each key-value pair where the key starts with the given `prefix`. + fn clear_prefix(&mut self, prefix: &[u8]) { + Externalities::clear_prefix(*self, prefix) + } + + /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + /// + /// See `child_get` for common child api parameters. + fn child_clear_prefix( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + prefix: &[u8], + ) { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.clear_child_prefix(storage_key, child_info, prefix); + } + + /// "Commit" all existing operations and compute the resulting storage root. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns the SCALE encoded hash. + fn root(&mut self) -> Vec { + self.storage_root() + } + + /// "Commit" all existing operations and compute the resulting child storage root. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns the SCALE encoded hash. + /// + /// See `child_get` for common child api parameters. + fn child_root( + &mut self, + child_storage_key: &[u8], + ) -> Vec { + let storage_key = child_storage_key_or_panic(child_storage_key); + self.child_storage_root(storage_key) + } + + /// "Commit" all existing operations and get the resulting storage change root. + /// `parent_hash` is a SCALE encoded hash. + /// + /// The hashing algorithm is defined by the `Block`. + /// + /// Returns an `Option` that holds the SCALE encoded hash. + fn changes_root(&mut self, parent_hash: &[u8]) -> Option> { + self.storage_changes_root(parent_hash) + .expect("Invalid `parent_hash` given to `changes_root`.") + } + + /// Get the next key in storage after the given one in lexicographic order. + fn next_key(&mut self, key: &[u8]) -> Option> { + self.next_storage_key(&key) + } + + /// Get the next key in storage after the given one in lexicographic order in child storage. + fn child_next_key( + &mut self, + child_storage_key: &[u8], + child_definition: &[u8], + child_type: u32, + key: &[u8], + ) -> Option> { + let storage_key = child_storage_key_or_panic(child_storage_key); + let child_info = ChildInfo::resolve_child_info(child_type, child_definition) + .expect("Invalid child definition"); + self.next_child_storage_key(storage_key, child_info, key) + } +} + +/// Interface that provides trie related functionality. +#[runtime_interface] +pub trait Trie { + /// A trie root formed from the iterated items. + fn blake2_256_root(input: Vec<(Vec, Vec)>) -> H256 { + Layout::::trie_root(input) + } + + /// A trie root formed from the enumerated items. + fn blake2_256_ordered_root(input: Vec>) -> H256 { + Layout::::ordered_trie_root(input) + } + + /// A trie root formed from the enumerated items. + fn keccak_256_ordered_root(input: Vec>) -> H256 { + Layout::::ordered_trie_root(input) + } +} + +/// Interface that provides miscellaneous functions for communicating between the runtime and the node. +#[runtime_interface] +pub trait Misc { + /// The current relay chain identifier. + fn chain_id(&self) -> u64 { + sp_externalities::Externalities::chain_id(*self) + } + + /// Print a number. + fn print_num(val: u64) { + log::debug!(target: "runtime", "{}", val); + } + + /// Print any valid `utf8` buffer. + fn print_utf8(utf8: &[u8]) { + if let Ok(data) = std::str::from_utf8(utf8) { + log::debug!(target: "runtime", "{}", data) + } + } + + /// Print any `u8` slice as hex. + fn print_hex(data: &[u8]) { + log::debug!(target: "runtime", "{}", HexDisplay::from(&data)); + } +} + +/// Interfaces for working with crypto related types from within the runtime. +#[runtime_interface] +pub trait Crypto { + /// Returns all `ed25519` public keys for the given key id from the keystore. + fn ed25519_public_keys(&mut self, id: KeyTypeId) -> Vec { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .ed25519_public_keys(id) + } + + /// Generate an `ed22519` key for the given key type using an optional `seed` and + /// store it in the keystore. + /// + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + fn ed25519_generate(&mut self, id: KeyTypeId, seed: Option>) -> ed25519::Public { + let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); + self.extension::() + .expect("No `keystore` associated for the current context!") + .write() + .ed25519_generate_new(id, seed) + .expect("`ed25519_generate` failed") + } + + /// Sign the given `msg` with the `ed25519` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + fn ed25519_sign( + &mut self, + id: KeyTypeId, + pub_key: &ed25519::Public, + msg: &[u8], + ) -> Option { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .ed25519_key_pair(id, &pub_key) + .map(|k| k.sign(msg)) + } + + /// Verify an `ed25519` signature. + /// + /// Returns `true` when the verification in successful. + fn ed25519_verify( + &self, + sig: &ed25519::Signature, + msg: &[u8], + pub_key: &ed25519::Public, + ) -> bool { + ed25519::Pair::verify(sig, msg, pub_key) + } + + /// Returns all `sr25519` public keys for the given key id from the keystore. + fn sr25519_public_keys(&mut self, id: KeyTypeId) -> Vec { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .sr25519_public_keys(id) + } + + /// Generate an `sr22519` key for the given key type using an optional seed and + /// store it in the keystore. + /// + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + fn sr25519_generate(&mut self, id: KeyTypeId, seed: Option>) -> sr25519::Public { + let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); + self.extension::() + .expect("No `keystore` associated for the current context!") + .write() + .sr25519_generate_new(id, seed) + .expect("`sr25519_generate` failed") + } + + /// Sign the given `msg` with the `sr25519` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + fn sr25519_sign( + &mut self, + id: KeyTypeId, + pub_key: &sr25519::Public, + msg: &[u8], + ) -> Option { + self.extension::() + .expect("No `keystore` associated for the current context!") + .read() + .sr25519_key_pair(id, &pub_key) + .map(|k| k.sign(msg)) + } + + /// Verify an `sr25519` signature. + /// + /// Returns `true` when the verification in successful. + fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { + sr25519::Pair::verify(sig, msg, pubkey) + } + + /// Verify and recover a SECP256k1 ECDSA signature. + /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. + /// Returns `Err` if the signature is bad, otherwise the 64-byte pubkey + /// (doesn't include the 0x04 prefix). + fn secp256k1_ecdsa_recover( + sig: &[u8; 65], + msg: &[u8; 32], + ) -> Result<[u8; 64], EcdsaVerifyError> { + let rs = secp256k1::Signature::parse_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + let mut res = [0u8; 64]; + res.copy_from_slice(&pubkey.serialize()[1..65]); + Ok(res) + } + + /// Verify and recover a SECP256k1 ECDSA signature. + /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. + /// - returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey. + fn secp256k1_ecdsa_recover_compressed( + sig: &[u8; 65], + msg: &[u8; 32], + ) -> Result<[u8; 33], EcdsaVerifyError> { + let rs = secp256k1::Signature::parse_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + Ok(pubkey.serialize_compressed()) + } +} + +/// Interface that provides functions for hashing with different algorithms. +#[runtime_interface] +pub trait Hashing { + /// Conduct a 256-bit Keccak hash. + fn keccak_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::keccak_256(data) + } + + /// Conduct a 256-bit Sha2 hash. + fn sha2_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::sha2_256(data) + } + + /// Conduct a 128-bit Blake2 hash. + fn blake2_128(data: &[u8]) -> [u8; 16] { + sp_core::hashing::blake2_128(data) + } + + /// Conduct a 256-bit Blake2 hash. + fn blake2_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::blake2_256(data) + } + + /// Conduct four XX hashes to give a 256-bit result. + fn twox_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::twox_256(data) + } + + /// Conduct two XX hashes to give a 128-bit result. + fn twox_128(data: &[u8]) -> [u8; 16] { + sp_core::hashing::twox_128(data) + } + + /// Conduct two XX hashes to give a 64-bit result. + fn twox_64(data: &[u8]) -> [u8; 8] { + sp_core::hashing::twox_64(data) + } +} + +/// Interface that provides functions to access the offchain functionality. +#[runtime_interface] +pub trait Offchain { + /// Returns if the local node is a potential validator. + /// + /// Even if this function returns `true`, it does not mean that any keys are configured + /// and that the validator is registered in the chain. + fn is_validator(&mut self) -> bool { + self.extension::() + .expect("is_validator can be called only in the offchain worker context") + .is_validator() + } + + /// Submit an encoded transaction to the pool. + /// + /// The transaction will end up in the pool. + fn submit_transaction(&mut self, data: Vec) -> Result<(), ()> { + self.extension::() + .expect("submit_transaction can be called only in the offchain call context with + TransactionPool capabilities enabled") + .submit_transaction(data) + } + + /// Returns information about the local node's network state. + fn network_state(&mut self) -> Result { + self.extension::() + .expect("network_state can be called only in the offchain worker context") + .network_state() + } + + /// Returns current UNIX timestamp (in millis) + fn timestamp(&mut self) -> Timestamp { + self.extension::() + .expect("timestamp can be called only in the offchain worker context") + .timestamp() + } + + /// Pause the execution until `deadline` is reached. + fn sleep_until(&mut self, deadline: Timestamp) { + self.extension::() + .expect("sleep_until can be called only in the offchain worker context") + .sleep_until(deadline) + } + + /// Returns a random seed. + /// + /// This is a trully random non deterministic seed generated by host environment. + /// Obviously fine in the off-chain worker context. + fn random_seed(&mut self) -> [u8; 32] { + self.extension::() + .expect("random_seed can be called only in the offchain worker context") + .random_seed() + } + + /// Sets a value in the local storage. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { + self.extension::() + .expect("local_storage_set can be called only in the offchain worker context") + .local_storage_set(kind, key, value) + } + + /// Sets a value in the local storage if it matches current value. + /// + /// Since multiple offchain workers may be running concurrently, to prevent + /// data races use CAS to coordinate between them. + /// + /// Returns `true` if the value has been set, `false` otherwise. + /// + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_compare_and_set( + &mut self, + kind: StorageKind, + key: &[u8], + old_value: Option>, + new_value: &[u8], + ) -> bool { + self.extension::() + .expect("local_storage_compare_and_set can be called only in the offchain worker context") + .local_storage_compare_and_set(kind, key, old_value.as_ref().map(|v| v.deref()), new_value) + } + + /// Gets a value from the local storage. + /// + /// If the value does not exist in the storage `None` will be returned. + /// Note this storage is not part of the consensus, it's only accessible by + /// offchain worker tasks running on the same machine. It IS persisted between runs. + fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { + self.extension::() + .expect("local_storage_get can be called only in the offchain worker context") + .local_storage_get(kind, key) + } + + /// Initiates a http request given HTTP verb and the URL. + /// + /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. + /// Returns the id of newly started request. + fn http_request_start( + &mut self, + method: &str, + uri: &str, + meta: &[u8], + ) -> Result { + self.extension::() + .expect("http_request_start can be called only in the offchain worker context") + .http_request_start(method, uri, meta) + } + + /// Append header to the request. + fn http_request_add_header( + &mut self, + request_id: HttpRequestId, + name: &str, + value: &str, + ) -> Result<(), ()> { + self.extension::() + .expect("http_request_add_header can be called only in the offchain worker context") + .http_request_add_header(request_id, name, value) + } + + /// Write a chunk of request body. + /// + /// Writing an empty chunks finalizes the request. + /// Passing `None` as deadline blocks forever. + /// + /// Returns an error in case deadline is reached or the chunk couldn't be written. + fn http_request_write_body( + &mut self, + request_id: HttpRequestId, + chunk: &[u8], + deadline: Option, + ) -> Result<(), HttpError> { + self.extension::() + .expect("http_request_write_body can be called only in the offchain worker context") + .http_request_write_body(request_id, chunk, deadline) + } + + /// Block and wait for the responses for given requests. + /// + /// Returns a vector of request statuses (the len is the same as ids). + /// Note that if deadline is not provided the method will block indefinitely, + /// otherwise unready responses will produce `DeadlineReached` status. + /// + /// Passing `None` as deadline blocks forever. + fn http_response_wait( + &mut self, + ids: &[HttpRequestId], + deadline: Option, + ) -> Vec { + self.extension::() + .expect("http_response_wait can be called only in the offchain worker context") + .http_response_wait(ids, deadline) + } + + /// Read all response headers. + /// + /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. + /// NOTE response headers have to be read before response body. + fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { + self.extension::() + .expect("http_response_headers can be called only in the offchain worker context") + .http_response_headers(request_id) + } + + /// Read a chunk of body response to given buffer. + /// + /// Returns the number of bytes written or an error in case a deadline + /// is reached or server closed the connection. + /// If `0` is returned it means that the response has been fully consumed + /// and the `request_id` is now invalid. + /// NOTE this implies that response headers must be read before draining the body. + /// Passing `None` as a deadline blocks forever. + fn http_response_read_body( + &mut self, + request_id: HttpRequestId, + buffer: &mut [u8], + deadline: Option, + ) -> Result { + self.extension::() + .expect("http_response_read_body can be called only in the offchain worker context") + .http_response_read_body(request_id, buffer, deadline) + .map(|r| r as u32) + } +} + +/// Wasm only interface that provides functions for calling into the allocator. +#[runtime_interface(wasm_only)] +trait Allocator { + /// Malloc the given number of bytes and return the pointer to the allocated memory location. + fn malloc(&mut self, size: u32) -> Pointer { + self.allocate_memory(size).expect("Failed to allocate memory") + } + + /// Free the given pointer. + fn free(&mut self, ptr: Pointer) { + self.deallocate_memory(ptr).expect("Failed to deallocate memory") + } +} + +/// Interface that provides functions for logging from within the runtime. +#[runtime_interface] +pub trait Logging { + /// Request to print a log message on the host. + /// + /// Note that this will be only displayed if the host is enabled to display log messages with + /// given level and target. + /// + /// Instead of using directly, prefer setting up `RuntimeLogger` and using `log` macros. + fn log(level: LogLevel, target: &str, message: &[u8]) { + if let Ok(message) = std::str::from_utf8(message) { + log::log!( + target: target, + log::Level::from(level), + "{}", + message, + ) + } + } +} + +/// Wasm-only interface that provides functions for interacting with the sandbox. +#[runtime_interface(wasm_only)] +pub trait Sandbox { + /// Instantiate a new sandbox instance with the given `wasm_code`. + fn instantiate( + &mut self, + dispatch_thunk: u32, + wasm_code: &[u8], + env_def: &[u8], + state_ptr: Pointer, + ) -> u32 { + self.sandbox() + .instance_new(dispatch_thunk, wasm_code, env_def, state_ptr.into()) + .expect("Failed to instantiate a new sandbox") + } + + /// Invoke `function` in the sandbox with `sandbox_idx`. + fn invoke( + &mut self, + instance_idx: u32, + function: &str, + args: &[u8], + return_val_ptr: Pointer, + return_val_len: u32, + state_ptr: Pointer, + ) -> u32 { + self.sandbox().invoke( + instance_idx, + &function, + &args, + return_val_ptr, + return_val_len, + state_ptr.into(), + ).expect("Failed to invoke function with sandbox") + } + + /// Create a new memory instance with the given `initial` and `maximum` size. + fn memory_new(&mut self, initial: u32, maximum: u32) -> u32 { + self.sandbox() + .memory_new(initial, maximum) + .expect("Failed to create new memory with sandbox") + } + + /// Get the memory starting at `offset` from the instance with `memory_idx` into the buffer. + fn memory_get( + &mut self, + memory_idx: u32, + offset: u32, + buf_ptr: Pointer, + buf_len: u32, + ) -> u32 { + self.sandbox() + .memory_get(memory_idx, offset, buf_ptr, buf_len) + .expect("Failed to get memory with sandbox") + } + + /// Set the memory in the given `memory_idx` to the given value at `offset`. + fn memory_set( + &mut self, + memory_idx: u32, + offset: u32, + val_ptr: Pointer, + val_len: u32, + ) -> u32 { + self.sandbox() + .memory_set(memory_idx, offset, val_ptr, val_len) + .expect("Failed to set memory with sandbox") + } + + /// Teardown the memory instance with the given `memory_idx`. + fn memory_teardown(&mut self, memory_idx: u32) { + self.sandbox().memory_teardown(memory_idx).expect("Failed to teardown memory with sandbox") + } + + /// Teardown the sandbox instance with the given `instance_idx`. + fn instance_teardown(&mut self, instance_idx: u32) { + self.sandbox().instance_teardown(instance_idx).expect("Failed to teardown sandbox instance") + } +} + +/// Allocator used by Substrate when executing the Wasm runtime. +#[cfg(not(feature = "std"))] +struct WasmAllocator; + +#[cfg(all(not(feature = "disable_allocator"), not(feature = "std")))] +#[global_allocator] +static ALLOCATOR: WasmAllocator = WasmAllocator; + +#[cfg(not(feature = "std"))] +mod allocator_impl { + use super::*; + use core::alloc::{GlobalAlloc, Layout}; + + unsafe impl GlobalAlloc for WasmAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + allocator::malloc(layout.size() as u32) + } + + unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { + allocator::free(ptr) + } + } +} + +/// A default panic handler for WASM environment. +#[cfg(all(not(feature = "disable_panic_handler"), not(feature = "std")))] +#[panic_handler] +#[no_mangle] +pub fn panic(info: &core::panic::PanicInfo) -> ! { + unsafe { + let message = sp_std::alloc::format!("{}", info); + logging::log(LogLevel::Error, "runtime", message.as_bytes()); + core::intrinsics::abort() + } +} + +/// A default OOM handler for WASM environment. +#[cfg(all(not(feature = "disable_oom"), not(feature = "std")))] +#[alloc_error_handler] +pub fn oom(_: core::alloc::Layout) -> ! { + unsafe { + logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting"); + core::intrinsics::abort(); + } +} + +/// Type alias for Externalities implementation used in tests. +#[cfg(feature = "std")] +pub type TestExternalities = sp_state_machine::TestExternalities; + +/// The host functions Substrate provides for the Wasm runtime environment. +/// +/// All these host functions will be callable from inside the Wasm environment. +#[cfg(feature = "std")] +pub type SubstrateHostFunctions = ( + storage::HostFunctions, + misc::HostFunctions, + offchain::HostFunctions, + crypto::HostFunctions, + hashing::HostFunctions, + allocator::HostFunctions, + logging::HostFunctions, + sandbox::HostFunctions, + crate::trie::HostFunctions, +); + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::map; + use sp_state_machine::BasicExternalities; + use sp_core::storage::Storage; + + #[test] + fn storage_works() { + let mut t = BasicExternalities::default(); + t.execute_with(|| { + assert_eq!(storage::get(b"hello"), None); + storage::set(b"hello", b"world"); + assert_eq!(storage::get(b"hello"), Some(b"world".to_vec())); + assert_eq!(storage::get(b"foo"), None); + storage::set(b"foo", &[1, 2, 3][..]); + }); + + t = BasicExternalities::new(Storage { + top: map![b"foo".to_vec() => b"bar".to_vec()], + children: map![], + }); + + t.execute_with(|| { + assert_eq!(storage::get(b"hello"), None); + assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec())); + }); + } + + #[test] + fn read_storage_works() { + let mut t = BasicExternalities::new(Storage { + top: map![b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()], + children: map![], + }); + + t.execute_with(|| { + let mut v = [0u8; 4]; + assert!(storage::read(b":test", &mut v[..], 0).unwrap() >= 4); + assert_eq!(v, [11u8, 0, 0, 0]); + let mut w = [0u8; 11]; + assert!(storage::read(b":test", &mut w[..], 4).unwrap() >= 11); + assert_eq!(&w, b"Hello world"); + }); + } + + #[test] + fn clear_prefix_works() { + let mut t = BasicExternalities::new(Storage { + top: map![ + b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), + b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), + b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), + b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() + ], + children: map![], + }); + + t.execute_with(|| { + storage::clear_prefix(b":abc"); + + assert!(storage::get(b":a").is_some()); + assert!(storage::get(b":abdd").is_some()); + assert!(storage::get(b":abcd").is_none()); + assert!(storage::get(b":abc").is_none()); + }); + } +} From 3750b8c2960655b9e5a233d36da7f93bc608f381 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 2 Feb 2020 21:29:06 -0500 Subject: [PATCH 0005/1210] Squashed commit of Rust-ifying the repo: commit e31c1965a2e6b9a21ce68be63b81915b2b090f1d Author: Hernando Castano Date: Sun Feb 2 21:15:42 2020 -0500 Get Ethereum bridge module compiling commit a497fc1640e68682f61b39414ffb15206c6120e2 Author: Hernando Castano Date: Thu Jan 30 12:15:43 2020 -0500 Make the toml file look a bit better commit 898fb7b06cfac7cf866e1a28fed9a4f02bd246a7 Author: Hernando Castano Date: Thu Jan 30 12:06:27 2020 -0500 Get substrate bridge module compiling commit 81e1547e6bec9f590cad9ffba0ee5dfa82cda1c1 Author: Hernando Castano Date: Thu Jan 30 11:40:29 2020 -0500 Create workspace and move more files around --- modules/ethereum/Cargo.toml | 56 + .../frame/bridge-eth-poa/Cargo.toml | 33 - .../bin/node/cli/Cargo.toml | 0 .../bin/node/cli/src/chain_spec.rs | 0 .../bin/node/runtime/Cargo.toml | 0 .../bin/node/runtime/src/lib.rs | 0 .../bin/node/testing/Cargo.toml | 0 .../bin/node/testing/src/genesis.rs | 0 .../primitives/core/src/hasher.rs | 0 .../primitives/core/src/lib.rs | 0 .../primitives/io/Cargo.toml | 0 .../primitives/io/src/lib.rs | 0 .../frame/bridge-eth-poa => }/src/error.rs | 0 .../frame/bridge-eth-poa => }/src/finality.rs | 0 .../frame/bridge-eth-poa => }/src/import.rs | 0 .../frame/bridge-eth-poa => }/src/lib.rs | 10 +- .../bridge-eth-poa => }/src/validators.rs | 0 .../bridge-eth-poa => }/src/verification.rs | 0 modules/substrate/Cargo.toml | 76 + modules/substrate/{ => src}/lib.rs | 2 +- modules/substrate/{ => src}/storage_proof.rs | 0 modules/subtrate | 38 - .../ethereum-poa}/Cargo.toml | 8 +- .../ethereum-poa}/src/lib.rs | 0 relays/ethereum/Cargo.lock | 6274 ----------------- 25 files changed, 142 insertions(+), 6355 deletions(-) create mode 100644 modules/ethereum/Cargo.toml delete mode 100644 modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml rename modules/ethereum/{bridge-runtime => other-runtime-components}/bin/node/cli/Cargo.toml (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/bin/node/cli/src/chain_spec.rs (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/bin/node/runtime/Cargo.toml (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/bin/node/runtime/src/lib.rs (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/bin/node/testing/Cargo.toml (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/bin/node/testing/src/genesis.rs (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/primitives/core/src/hasher.rs (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/primitives/core/src/lib.rs (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/primitives/io/Cargo.toml (100%) rename modules/ethereum/{bridge-runtime => other-runtime-components}/primitives/io/src/lib.rs (100%) rename modules/ethereum/{bridge-runtime/frame/bridge-eth-poa => }/src/error.rs (100%) rename modules/ethereum/{bridge-runtime/frame/bridge-eth-poa => }/src/finality.rs (100%) rename modules/ethereum/{bridge-runtime/frame/bridge-eth-poa => }/src/import.rs (100%) rename modules/ethereum/{bridge-runtime/frame/bridge-eth-poa => }/src/lib.rs (98%) rename modules/ethereum/{bridge-runtime/frame/bridge-eth-poa => }/src/validators.rs (100%) rename modules/ethereum/{bridge-runtime/frame/bridge-eth-poa => }/src/verification.rs (100%) create mode 100644 modules/substrate/Cargo.toml rename modules/substrate/{ => src}/lib.rs (99%) rename modules/substrate/{ => src}/storage_proof.rs (100%) delete mode 100644 modules/subtrate rename {modules/ethereum/bridge-runtime/primitives/bridge-eth-poa => primitives/ethereum-poa}/Cargo.toml (75%) rename {modules/ethereum/bridge-runtime/primitives/bridge-eth-poa => primitives/ethereum-poa}/src/lib.rs (100%) delete mode 100644 relays/ethereum/Cargo.lock diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml new file mode 100644 index 0000000000000..ee4673e589481 --- /dev/null +++ b/modules/ethereum/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-bridge-eth-poa" +description = "A Substrate Runtime module that is able to verify PoA headers and their finality." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", default-features = false } + +# Substrate Based Dependencies +[dependencies.frame-support] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.frame-system] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-std] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-io] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-runtime] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +# Dev Dependencies +[dev-dependencies] +# TODO: Stop renaming this on import +primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", features = ["std", "test-helpers"] } +parity-crypto = { version = "0.4", features = ["publickey"] } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "frame-support/std", + "sp-runtime/std", + "frame-system/std", + "sp-io/std", + "primitives/std", +] diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml b/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml deleted file mode 100644 index b8f195adba5c5..0000000000000 --- a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "pallet-bridge-eth-poa" -description = "A Substrate Runtime module that is able to verify PoA headers and their finality." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } -frame-support = { version = "2.0.0", default-features = false, path = "../support" } # TODO: Rename -sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } -frame-system = { version = "2.0.0", default-features = false, path = "../system" } # TODO: Rename -sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } -primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/bridge-eth-poa", default-features = false } - -[dev-dependencies] -primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/bridge-eth-poa", features = ["std", "test-helpers"] } -parity-crypto = { version = "0.4", features = ["publickey"] } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sp-std/std", - "frame-support/std", - "sp-runtime/std", - "frame-system/std", - "sp-io/std", - "primitives/std", -] diff --git a/modules/ethereum/bridge-runtime/bin/node/cli/Cargo.toml b/modules/ethereum/other-runtime-components/bin/node/cli/Cargo.toml similarity index 100% rename from modules/ethereum/bridge-runtime/bin/node/cli/Cargo.toml rename to modules/ethereum/other-runtime-components/bin/node/cli/Cargo.toml diff --git a/modules/ethereum/bridge-runtime/bin/node/cli/src/chain_spec.rs b/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs similarity index 100% rename from modules/ethereum/bridge-runtime/bin/node/cli/src/chain_spec.rs rename to modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs diff --git a/modules/ethereum/bridge-runtime/bin/node/runtime/Cargo.toml b/modules/ethereum/other-runtime-components/bin/node/runtime/Cargo.toml similarity index 100% rename from modules/ethereum/bridge-runtime/bin/node/runtime/Cargo.toml rename to modules/ethereum/other-runtime-components/bin/node/runtime/Cargo.toml diff --git a/modules/ethereum/bridge-runtime/bin/node/runtime/src/lib.rs b/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs similarity index 100% rename from modules/ethereum/bridge-runtime/bin/node/runtime/src/lib.rs rename to modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs diff --git a/modules/ethereum/bridge-runtime/bin/node/testing/Cargo.toml b/modules/ethereum/other-runtime-components/bin/node/testing/Cargo.toml similarity index 100% rename from modules/ethereum/bridge-runtime/bin/node/testing/Cargo.toml rename to modules/ethereum/other-runtime-components/bin/node/testing/Cargo.toml diff --git a/modules/ethereum/bridge-runtime/bin/node/testing/src/genesis.rs b/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs similarity index 100% rename from modules/ethereum/bridge-runtime/bin/node/testing/src/genesis.rs rename to modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs diff --git a/modules/ethereum/bridge-runtime/primitives/core/src/hasher.rs b/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs similarity index 100% rename from modules/ethereum/bridge-runtime/primitives/core/src/hasher.rs rename to modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs diff --git a/modules/ethereum/bridge-runtime/primitives/core/src/lib.rs b/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs similarity index 100% rename from modules/ethereum/bridge-runtime/primitives/core/src/lib.rs rename to modules/ethereum/other-runtime-components/primitives/core/src/lib.rs diff --git a/modules/ethereum/bridge-runtime/primitives/io/Cargo.toml b/modules/ethereum/other-runtime-components/primitives/io/Cargo.toml similarity index 100% rename from modules/ethereum/bridge-runtime/primitives/io/Cargo.toml rename to modules/ethereum/other-runtime-components/primitives/io/Cargo.toml diff --git a/modules/ethereum/bridge-runtime/primitives/io/src/lib.rs b/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs similarity index 100% rename from modules/ethereum/bridge-runtime/primitives/io/src/lib.rs rename to modules/ethereum/other-runtime-components/primitives/io/src/lib.rs diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/error.rs b/modules/ethereum/src/error.rs similarity index 100% rename from modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/error.rs rename to modules/ethereum/src/error.rs diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/finality.rs b/modules/ethereum/src/finality.rs similarity index 100% rename from modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/finality.rs rename to modules/ethereum/src/finality.rs diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/import.rs b/modules/ethereum/src/import.rs similarity index 100% rename from modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/import.rs rename to modules/ethereum/src/import.rs diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs b/modules/ethereum/src/lib.rs similarity index 98% rename from modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs rename to modules/ethereum/src/lib.rs index 430a950d3c779..e1135fad1386a 100644 --- a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -247,19 +247,19 @@ decl_storage! { /// Oldest unpruned block(s) number. OldestUnprunedBlock: u64; /// Map of imported headers by hash. - Headers: map H256 => Option; + Headers: map hasher(blake2_256) H256 => Option; /// Map of imported header hashes by number. - HeadersByNumber: map u64 => Option>; + HeadersByNumber: map hasher(blake2_256) u64 => Option>; /// The ID of next validator set. NextValidatorsSetId: u64; /// Map of validators sets by their id. - ValidatorsSets: map u64 => Option<(H256, Vec
)>; + ValidatorsSets: map hasher(blake2_256) u64 => Option<(H256, Vec
)>; /// Validators sets reference count. Each header that is authored by this set increases /// the reference count. When we prune this header, we decrease the reference count. /// When it reaches zero, we are free to prune validator set as well. - ValidatorsSetsRc: map u64 => Option; + ValidatorsSetsRc: map hasher(blake2_256) u64 => Option; /// Map of validators set changes scheduled by given header. - ScheduledChanges: map H256 => Option>; + ScheduledChanges: map hasher(blake2_256) H256 => Option>; } add_extra_genesis { config(initial_header): Header; diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/validators.rs b/modules/ethereum/src/validators.rs similarity index 100% rename from modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/validators.rs rename to modules/ethereum/src/validators.rs diff --git a/modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/verification.rs b/modules/ethereum/src/verification.rs similarity index 100% rename from modules/ethereum/bridge-runtime/frame/bridge-eth-poa/src/verification.rs rename to modules/ethereum/src/verification.rs diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml new file mode 100644 index 0000000000000..cd8787a76683e --- /dev/null +++ b/modules/substrate/Cargo.toml @@ -0,0 +1,76 @@ +[package] +name = "pallet-bridge" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +serde = { version = "1.0", optional = true } + +# Substrate Based Dependencies +[dependencies.frame-support] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.frame-system] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.hash-db] +version = "0.15.2" +default-features = false + +[dependencies.pallet-session] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-core] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-finality-grandpa] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-runtime] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dependencies.sp-trie] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +# Dev Dependencies +[dev-dependencies.sp-io] +version = "2.0.0" +git = "https://github.com/paritytech/substrate.git" +default-features = false + +[dev-dependencies.sp-state-machine] +version = "0.8.0" +git = "https://github.com/paritytech/substrate.git" + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-session/std", + "sp-core/std", + "sp-finality-grandpa/std", + "sp-runtime/std", + "sp-trie/std", + "sp-io/std", +] diff --git a/modules/substrate/lib.rs b/modules/substrate/src/lib.rs similarity index 99% rename from modules/substrate/lib.rs rename to modules/substrate/src/lib.rs index 910c38ce7e333..b66e5f610e07f 100644 --- a/modules/substrate/lib.rs +++ b/modules/substrate/src/lib.rs @@ -85,7 +85,7 @@ decl_storage! { /// Maps a bridge id to a bridge struct. Allows a single /// `bridge` module to manage multiple bridges. - pub TrackedBridges get(tracked_bridges): map BridgeId => Option>; + pub TrackedBridges get(tracked_bridges): map hasher(blake2_256) BridgeId => Option>; } } diff --git a/modules/substrate/storage_proof.rs b/modules/substrate/src/storage_proof.rs similarity index 100% rename from modules/substrate/storage_proof.rs rename to modules/substrate/src/storage_proof.rs diff --git a/modules/subtrate b/modules/subtrate deleted file mode 100644 index 335bd1307f84b..0000000000000 --- a/modules/subtrate +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "pallet-bridge" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } -frame-support = { version = "2.0.0", default-features = false, path = "../support" } -frame-system = { version = "2.0.0", default-features = false, path = "../system" } -hash-db = { version = "0.15.2", default-features = false } -pallet-session = { version = "2.0.0", default-features = false, path = "../session" } -serde = { version = "1.0", optional = true } -sp-core = { version = "2.0.0", default-features = false, path = "../../primitives/core" } -sp-finality-grandpa = { version = "2.0.0", default-features = false, path = "../../primitives/finality-grandpa" } -sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } -sp-trie = { version = "2.0.0", default-features = false, path = "../../primitives/trie" } - -[dev-dependencies] -sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } -sp-state-machine = { version = "2.0.0", path = "../../primitives/state-machine" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-session/std", - "sp-core/std", - "sp-finality-grandpa/std", - "sp-runtime/std", - "sp-trie/std", - "sp-io/std", -] diff --git a/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml similarity index 75% rename from modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml rename to primitives/ethereum-poa/Cargo.toml index 11c4d46ee26ce..6b88c8901bfea 100644 --- a/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -16,10 +16,10 @@ impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } rlp = { version = "0.4", default-features = false } -sp-std = { version = "2.0.0", default-features = false, path = "../std" } -sp-runtime = { version = "2.0.0", default-features = false, path = "../runtime" } -sp-api = { version = "2.0.0", path = "../api", default-features = false } -sp-io = { version = "2.0.0", default-features = false, path = "../io" } +sp-std = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } +sp-runtime = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } +sp-api = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } +sp-io = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } diff --git a/modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs similarity index 100% rename from modules/ethereum/bridge-runtime/primitives/bridge-eth-poa/src/lib.rs rename to primitives/ethereum-poa/src/lib.rs diff --git a/relays/ethereum/Cargo.lock b/relays/ethereum/Cargo.lock deleted file mode 100644 index 284a4f341bcef..0000000000000 --- a/relays/ethereum/Cargo.lock +++ /dev/null @@ -1,6274 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "adler32" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "aes" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aes-ctr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aes-soft" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aesni" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ahash" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ansi_term" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "anyhow" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "arc-swap" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "arrayref" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "asn1_der" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "asn1_der_derive" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-bridge" -version = "0.1.0" -dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", - "jsonrpsee-http 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "node-primitives 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "node-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-transaction-payment 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (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)", - "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)", - "sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "web3 0.8.0 (git+https://github.com/svyatonik/rust-web3.git?branch=fix_receipt)", -] - -[[package]] -name = "async-macros" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-macros" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-std" -version = "0.99.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "async-macros 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-std" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "async-stream-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-stream-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "async-task" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "backtrace" -version = "0.3.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base58" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitmask" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitvec" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "blake2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-cipher-trait" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-modes" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bs58" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bstr" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bumpalo" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-slice-cast" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "c_linked_list" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cc" -version = "1.0.41" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "chrono" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clap" -version = "2.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "clear_on_drop" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "const-random" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "const-random-macro" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "core-foundation" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crc32fast" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-channel" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ctr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cuckoofilter" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "curve25519-dalek" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "data-encoding" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "derive_more" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "derive_more" -version = "0.99.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dns-parser" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "elastic-array" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "environmental" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "erased-serde" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "err-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "error-chain" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethabi" -version = "9.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 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)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethbloom" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethereum-transaction" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethereum-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethsign" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-crypto 0.4.2 (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)", - "secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fixed-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -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)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "flate2" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fnv" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "frame-executive" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "frame-metadata" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "frame-support" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "frame-metadata 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-support-procedural 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-arithmetic 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "frame-support-procedural" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support-procedural-tools 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "frame-support-procedural-tools" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support-procedural-tools-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "frame-support-procedural-tools-derive" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "frame-system" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.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-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "frame-system-rpc-runtime-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "frame-utility" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-channel" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-core-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-executor" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-io" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-io-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-join-macro-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-macro" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-select-macro-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-sink" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-task" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-timer" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-timer" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-timer" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-timer" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "futures-util-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-join-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-select-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "get_if_addrs" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "get_if_addrs-sys" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "getrandom" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "globset" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "h2" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "h2" -version = "0.2.0-alpha.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hash-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hash256-std-hasher" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashbrown" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashbrown" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heapsize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hermit-abi" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hex-literal" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex-literal-impl" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac-drbg" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "http-body" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "http-body" -version = "0.2.0-alpha.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "httparse" -version = "1.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper" -version = "0.12.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper" -version = "0.13.0-alpha.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-make 0.3.0-alpha.2a (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hyper-tls" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-codec" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-rlp" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-serde" -version = "0.1.1" -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)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-serde" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "indexmap" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ipnet" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "itoa" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "js-sys" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-core" -version = "14.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 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)", -] - -[[package]] -name = "jsonrpsee-core" -version = "1.0.0" -source = "git+https://github.com/paritytech/jsonrpsee.git#3e4cf9ba52821b113bb5dd14d16cb15d75a1a19c" -dependencies = [ - "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (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)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpsee-http" -version = "1.0.0" -source = "git+https://github.com/paritytech/jsonrpsee.git#3e4cf9ba52821b113bb5dd14d16cb15d75a1a19c" -dependencies = [ - "async-std 0.99.12 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", - "jsonrpsee-server-utils 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (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)", - "tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpsee-server-utils" -version = "1.0.0" -source = "git+https://github.com/paritytech/jsonrpsee.git#3e4cf9ba52821b113bb5dd14d16cb15d75a1a19c" -dependencies = [ - "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "kvdb" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "elastic-array 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libc" -version = "0.2.66" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libp2p" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core-derive 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-deflate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-dns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-floodsub 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-identify 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-kad 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mdns 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-mplex 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-noise 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-ping 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-plaintext 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-secio 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-tcp 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-uds 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-wasm-ext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-websocket 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-yamux 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-core" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "multistream-select 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-core-derive" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-deflate" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-dns" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-floodsub" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-identify" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-kad" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-mdns" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-mplex" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-noise" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "snow 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-ping" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-plaintext" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-secio" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-swarm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-tcp" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnet 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-uds" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-wasm-ext" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-websocket" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libp2p-yamux" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "yamux 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libsecp256k1" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "libz-sys" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lru" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "malloc_size_of_derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memory-db" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", - "parity-util-mem 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "merlin" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz_oxide" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio" -version = "0.6.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio-uds" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "multistream-select" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-tls" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "net2" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "node-primitives" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "node-runtime" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-executive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-utility 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "node-primitives 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-authority-discovery 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-collective 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-contracts 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-contracts-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-democracy 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-elections-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-grandpa 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-im-online 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-indices 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-membership 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-nicks 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-offences 1.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-randomness-collective-flip 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-staking-reward-curve 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-sudo 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-transaction-payment 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-transaction-payment-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-treasury 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (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 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-authority-discovery 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-consensus-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-offchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-transaction-pool-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "substrate-wasm-builder-runner 1.0.4 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nohash-hasher" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nom" -version = "4.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-bigint" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num_cpus" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "once_cell" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "once_cell" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "once_cell" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl" -version = "0.10.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl-sys" -version = "0.9.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pallet-authority-discovery" -version = "0.1.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-authority-discovery 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-authorship" -version = "0.1.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-authorship 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-babe" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-consensus-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-balances" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-bridge-eth-poa" -version = "0.1.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-collective" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-contracts" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-sandbox 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pallet-contracts-rpc-runtime-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.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 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-democracy" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-elections-phragmen" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-finality-tracker" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-grandpa" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-finality-granpda 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-im-online" -version = "0.1.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-indices" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-membership" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-nicks" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-offences" -version = "1.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-randomness-collective-flip" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-session" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-staking" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.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-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-staking-reward-curve" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pallet-sudo" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-timestamp" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-transaction-payment" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-transaction-payment-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-transaction-payment-rpc-runtime-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.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 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "pallet-treasury" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "parity-bytes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "parity-crypto" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-multiaddr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-multihash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-scale-codec" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec-derive 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "parity-util-mem" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "paste" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "paste-impl" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pbkdf2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pin-project" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-project-internal" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pin-project-lite" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pin-utils" -version = "0.1.0-alpha.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pkg-config" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ppv-lite86" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "primitive-types" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-error" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-nested" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "protobuf" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "pwasm-utils" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quick-error" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "remove_dir_all" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ring" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ripemd160" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -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)", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-hex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustls" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rw-stream-sink" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ryu" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "safe-mix" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sc-application-crypto" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sc-block-builder" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sc-client-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (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)", - "kvdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sc-executor 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sc-telemetry 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-transaction-pool-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sc-consensus-slots" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-client-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sc-telemetry 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sc-executor" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-panic-handler 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-serializer 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-wasm-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sc-telemetry" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 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)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)", - "slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "schannel" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "schnorrkel" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scoped-tls" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scrypt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sct" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "secp256k1" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "send_wrapper" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde-big-array" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_json" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha-1" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sha2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha3" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slab" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slab" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "slog" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-async" -version = "2.3.0" -source = "git+https://github.com/paritytech/slog-async#107848e7ded5e80dc43f6296c2b96039eb92c0a5" -dependencies = [ - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-json" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "erased-serde 0.3.9 (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)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "slog-scope" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "smallvec" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "smallvec" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "snow" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "soketto" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (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)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sourcefile" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sp-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-api-proc-macro" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-arithmetic" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-authority-discovery" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-authorship" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-block-builder" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-blockchain" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lru 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-bridge-eth-poa" -version = "0.1.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde-big-array 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-consensus" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libp2p 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-consensus-babe" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sc-consensus-slots 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-core" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", - "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)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core-storage 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-core-storage" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-debug-derive" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-externalities" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core-storage 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-finality-granpda" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-finality-tracker" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-inherents" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-io" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-keyring" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-offchain" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-panic-handler" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-phragmen" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-runtime" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-arithmetic 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-runtime-interface" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime-interface-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-wasm-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-runtime-interface-proc-macro" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-sandbox" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sp-serializer" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "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)", -] - -[[package]] -name = "sp-session" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-staking" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-state-machine" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 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)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-panic-handler 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "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)", -] - -[[package]] -name = "sp-std" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" - -[[package]] -name = "sp-timestamp" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-transaction-pool-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-transaction-pool-runtime-api" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-trie" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "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)", -] - -[[package]] -name = "sp-version" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", - "sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)", -] - -[[package]] -name = "sp-wasm-interface" -version = "2.0.0" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" -dependencies = [ - "impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "stream-cipher" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strum" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "strum_macros" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-bip39" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-wasm-builder-runner" -version = "1.0.4" -source = "git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime#af8a16992efe1026900e212f80d7fead485ba4e8" - -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "subtle" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "take_mut" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (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)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termcolor" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "time" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-bip39" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-keccak" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-buf" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-core" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-dns-unofficial" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-fs" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-fs" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-macros" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-net" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-rustls" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-timer" -version = "0.3.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tls" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-udp" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-uds" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-uds" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tower-make" -version = "0.3.0-alpha.2a" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tower-service" -version = "0.3.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "tracing" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-attributes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tracing-core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tracing-core" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "trie-db" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "elastic-array 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "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)", -] - -[[package]] -name = "trie-root" -version = "0.15.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)", -] - -[[package]] -name = "try-lock" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "twofish" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "twox-hash" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "uint" -version = "0.8.2" -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)", - "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unsigned-varint" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "untrusted" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "vcpkg" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "want" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wasm-bindgen" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wasm-bindgen-webidl" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-timer" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasmi" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasmi-validation" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "web-sys" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", - "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-webidl 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "web3" -version = "0.8.0" -source = "git+https://github.com/svyatonik/rust-web3.git?branch=fix_receipt#0d061ab0642c0def7e32f586ebff8fb145d29cd6" -dependencies = [ - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-transaction 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethsign 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (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)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webpki" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "webpki-roots" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "websocket" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "weedle" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wincolor" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "x25519-dalek" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "yaml-rust" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "yamux" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "nohash-hasher 0.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)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "zeroize" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "zeroize" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "zeroize_derive" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "zeroize_derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" -"checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" -"checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" -"checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" -"checksum aesni 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100" -"checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" -"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" -"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" -"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" -"checksum asn1_der 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6fce6b6a0ffdafebd82c87e79e3f40e8d2c523e5fea5566ff6b90509bf98d638" -"checksum asn1_der_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d0864d84b8e07b145449be9a8537db86bf9de5ce03b913214694643b4743502" -"checksum async-macros 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e421d59b24c1feea2496e409b3e0a8de23e5fc130a2ddc0b012e551f3b272bba" -"checksum async-macros 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "644a5a8de80f2085a1e7e57cd1544a2a7438f6e003c0790999bd43b92a77cdb2" -"checksum async-std 0.99.12 (registry+https://github.com/rust-lang/crates.io-index)" = "44501a9f7961bb539b67be0c428b3694e26557046a52759ca7eaf790030a64cc" -"checksum async-std 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "513ee3c49800679a319912340f5601afda9e72848d7dea3a48bab489e8c1a46f" -"checksum async-stream 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58982858be7540a465c790b95aaea6710e5139bf8956b1d1344d014fa40100b0" -"checksum async-stream-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393356ed99aa7bff0ac486dde592633b83ab02bd254d8c209d5b9f1d0f533480" -"checksum async-task 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de6bd58f7b9cc49032559422595c81cbfcf04db2f2133592f70af19e258a1ced" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" -"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum bitmask 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5da9b3d9f6f585199287a473f4f8dfab6566cf827d15c00c219f53c645687ead" -"checksum bitvec 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a993f74b4c99c1908d156b8d2e0fb6277736b0ecbd833982fd1241d39b2766a6" -"checksum blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "94cb07b0da6a73955f8fb85d24c466778e70cda767a568229b104f0264089330" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" -"checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" -"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -"checksum bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" -"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" -"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" -"checksum byte-slice-cast 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f6209f3b2c1edea170002e016d5ead6903d3bb0a846477f53bbeb614967a52a9" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -"checksum c_linked_list 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4964518bd3b4a8190e832886cdc0da9794f12e8e6c1613a9e90ff331c4c8724b" -"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" -"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" -"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" -"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum ctr 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "022cd691704491df67d25d006fe8eca083098253c4d43516c2206479c58c6736" -"checksum cuckoofilter 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd43f7cfaffe0a386636a10baea2ee05cc50df3b77bea4a456c9572a939bf1f" -"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" -"checksum data-encoding 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f47ca1860a761136924ddd2422ba77b2ea54fe8cc75b9040804a0d9d32ad97" -"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" -"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum dns-parser 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" -"checksum ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)" = "845aaacc16f01178f33349e7c992ecd0cee095aa5e577f0f4dee35971bd36455" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum elastic-array 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "580f3768bd6465780d063f5b8213a2ebd506e139b345e4a81eb301ceae3d61e1" -"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -"checksum environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34f8467a0284de039e6bd0e25c14519538462ba5beb548bb1f03e645097837a8" -"checksum erased-serde 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3beee4bc16478a1b26f2e80ad819a52d24745e292f521a63c16eea5f74b7eb60" -"checksum err-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b41487fadaa500d02a819eefcde5f713599a01dd51626ef25d2d72d87115667b" -"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum ethabi 9.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "965126c64662832991f5a748893577630b558e47fa94e7f35aefcd20d737cef7" -"checksum ethbloom 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cfe1c169414b709cf28aa30c74060bdb830a03a8ba473314d079ac79d80a5f" -"checksum ethereum-transaction 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6689c8377635a1878c1216b8cb5496a36c3009e85425f55e4a562421b35df38d" -"checksum ethereum-types 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba744248e3553a393143d5ebb68939fc3a4ec0c22a269682535f5ffe7fed728c" -"checksum ethsign 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b656fefa0b59f41b39000532c69359e927c0f1850186808ccf1586734ac3365f" -"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fixed-hash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72fe7539e2c5692c6989f2f9c0457e42f1e5768f96b85c87d273574670ae459f" -"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum frame-executive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-metadata 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-support 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-support-procedural 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-support-procedural-tools 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-support-procedural-tools-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-system 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-system-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum frame-utility 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" -"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" -"checksum futures-channel-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" -"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" -"checksum futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" -"checksum futures-executor-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" -"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" -"checksum futures-io-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" -"checksum futures-join-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "59e260e6b48ce7d99936c40a7088d782a499a67bef41da5481d21b439454bcea" -"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" -"checksum futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" -"checksum futures-select-macro-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "df2ae43560eb10b5e50604c53bead6c9c75eade7081390cd3cce66e1582958f7" -"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" -"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" -"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" -"checksum futures-timer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f9eb554aa23143abc64ec4d0016f038caf53bb7cbc3d91490835c54edc96550" -"checksum futures-timer 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "878f1d2fc31355fa02ed2372e741b0c17e58373341e6a122569b4623a14a7d33" -"checksum futures-timer 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7946248e9429ff093345d3e8fdf4eb0f9b2d79091611c9c14f744971a6f8be45" -"checksum futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6" -"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" -"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" -"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum get_if_addrs 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "abddb55a898d32925f3148bd281174a68eeb68bbfd9a5938a57b18f506ee4ef7" -"checksum get_if_addrs-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0d04f9fb746cf36b191c00f3ede8bde9c8e64f9f4b05ae2694a9ccf5e3f5ab48" -"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" -"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" -"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -"checksum h2 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f107db1419ef8271686187b1a5d47c6431af4a7f4d98b495e7b7fc249bb0a78" -"checksum hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" -"checksum hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" -"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" -"checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" -"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" -"checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" -"checksum hex-literal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" -"checksum hex-literal-impl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d4c5c844e2fee0bf673d54c2c177f1713b3d2af2ff6e666b49cb7572e6cf42d" -"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -"checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" -"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -"checksum http-body 0.2.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f3aef6f3de2bd8585f5b366f3f550b5774500b4764d00cf00f903c95749eec3" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum hyper 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -"checksum hyper 0.13.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2d05aa523087ac0b9d8b93dd80d5d482a697308ed3b0dca7b0667511a7fa7cdc" -"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum impl-codec 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1be51a921b067b0eaca2fad532d9400041561aa922221cc65f95a85641c6bf53" -"checksum impl-rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" -"checksum impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5158079de9d4158e0ce1de3ae0bd7be03904efc40b3d7dd8b8c301cbf6b52b56" -"checksum impl-serde 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "58e3cae7e99c7ff5a995da2cf78dd0a5383740eda71d98cf7b1910c301ac69b8" -"checksum impl-trait-for-tuples 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef5550a42e3740a0e71f909d4c861056a284060af885ae7aa6242820f920d9d" -"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" -"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" -"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum ipnet 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f4b06b21db0228860c8dfd17d2106c49c7c6bd07477a4036985347d84def04" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum js-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "1c840fdb2167497b0bd0db43d6dfe61e91637fa72f9d061f8bd17ddc44ba6414" -"checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" -"checksum jsonrpsee-core 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)" = "" -"checksum jsonrpsee-http 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)" = "" -"checksum jsonrpsee-server-utils 1.0.0 (git+https://github.com/paritytech/jsonrpsee.git)" = "" -"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum kv-log-macro 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb" -"checksum kvdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b2f251f01a7224426abdb2563707d856f7de995d821744fd8fa8e2874f69e3" -"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -"checksum libp2p 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fab3090cd3af0f0ff5e6c2cc0f6fe6607e9f9282680cf7cd3bdd4cda38ea722" -"checksum libp2p-core 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3def059145c191b6975e51784d5edc59e77e1ed5b25402fccac704dd7731f3" -"checksum libp2p-core-derive 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1eeb2704ac14c60f31967e351ed928b848526a5fc6db4104520020665012826f" -"checksum libp2p-deflate 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2b0bf5d37692ac90e2bffa436bec26c0b0def6c0cab7ea85ff67a353d58aaa" -"checksum libp2p-dns 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3175fb0fc9016c95c8517a297bbdb5fb6bfbd5665bacd2eb23495d1cbdeb033" -"checksum libp2p-floodsub 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92c11b95281e8cb87eb83c204b3ca4988fa665ed9351199b5bcc323056f49816" -"checksum libp2p-identify 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b4e4b0b4bcf410f77361b08335022d5705df34970dc1744ff58d4bb902309547" -"checksum libp2p-kad 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fd25360fc12b23edb1ed13f73426325a38d32e0927a46fec26ddb6873d7644d" -"checksum libp2p-mdns 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c4c2e225a7dfc571c3ad77a0a5ecccc9537afe42d72289ac9f19768567cd677d" -"checksum libp2p-mplex 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2fe584816d993dc0f893396521a3c93191d78a6f28a892b150baa714a12c3e5" -"checksum libp2p-noise 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a30ec2640262a7ad6b1a8b28f6cd8281e620a6802f700adf9ff26e61487c333a" -"checksum libp2p-ping 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b975ad345eb9bb29ddc64670664a50a8ab3e66e28357abb0f83cfc0a9ca2d78" -"checksum libp2p-plaintext 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4fe82189f5c20e8f0a11deaa04d492703c501cefd2428ad68f4f64aefab76f" -"checksum libp2p-secio 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee09e259ceb7633a52fd17f187bedf94e3545b1746487beedbd3a0a07d99817" -"checksum libp2p-swarm 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd55bc9f5f9eac2bb1ff24ca3c8a655810a566ac38c7a6ee1f30aced5a62905b" -"checksum libp2p-tcp 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "234a7093d05651ab5630db926a4a42ca8978a65bab8c27c2ce2b66b200c76989" -"checksum libp2p-uds 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e2fe0648967da3e56e4a55055c857c8c48326b66be0047d0e04c8ca60d34630" -"checksum libp2p-wasm-ext 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7b8f2bd81fb356e81352d4513856bc21215ecf91502aa1f55b6449642a9acf" -"checksum libp2p-websocket 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d74d4fc229ad7e8d1a973178786bdcd5dadbdd7b9822c4477c8687df6f82f66" -"checksum libp2p-yamux 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1913eb7dd6eb5515957b6f1770296f6921968db87bc9b985f0e974b6657e1003" -"checksum libsecp256k1 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd9a7c16c9487e710536b699c962f022266347c94201174aa0a7eb0546051aa" -"checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" -"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" -"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum lru 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a57ada89b072a15fa9e1b9d1e18d0e161fd25a47e0a3ae4868cf53aada8ba97" -"checksum malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e37c5d4cd9473c5f4c9c111f033f15d4df9bd378fdf615944e360a4f55a05f0b" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"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.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5dabfe0a8c69954ae3bcfc5fc14260a85fb80e1bf9f86a155f668d10a67e93dd" -"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" -"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" -"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multistream-select 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1242e4ecf2060b35fb58002988e4720fbb3a2cbd4c136d369c420fa028f69efe" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum node-primitives 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum node-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e657a6ec97f9a3ba46f6f7034ea6db9fcd5b71d25ef1074b7bc03da49be0e8e" -"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" -"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" -"checksum once_cell 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d584f08c2d717d5c23a6414fc2822b71c651560713e54fa7eace675f758a355e" -"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" -"checksum pallet-authority-discovery 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-authorship 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-balances 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-collective 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-contracts 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-contracts-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-democracy 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-elections-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-grandpa 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-im-online 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-indices 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-membership 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-nicks 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-offences 1.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-randomness-collective-flip 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-staking-reward-curve 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-sudo 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-transaction-payment 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-transaction-payment-rpc-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum pallet-treasury 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c276d76c5333b8c2579e02d49a06733a55b8282d2d9b13e8d53b6406bd7e30a" -"checksum parity-crypto 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a9c2b525c93d717a234eb220c26474f8d97b08ac50d79faeac4cb6c74bf0b9" -"checksum parity-multiaddr 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82afcb7461eae5d122543d8be1c57d306ed89af2d6ff7f8b0f5a3cc8f7e511bc" -"checksum parity-multihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c70cad855872dd51ce6679e823efb6434061a2c1782a1686438aabf506392cdd" -"checksum parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9f9d99dae413590a5f37e43cd99b94d4e62a244160562899126913ea7108673" -"checksum parity-scale-codec-derive 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "492ac3aa93d6caa5d20e4e3e0b75d08e2dcd9dd8a50d19529548b6fe11b3f295" -"checksum parity-send-wrapper 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" -"checksum parity-util-mem 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "570093f39f786beea92dcc09e45d8aae7841516ac19a50431953ac82a0e8f85c" -"checksum parity-wasm 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" -"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" -"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" -"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" -"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" -"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" -"checksum pin-project-lite 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0af6cbca0e6e3ce8692ee19fb8d734b641899e07b68eb73e9bbbd32f1703991" -"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" -"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" -"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum primitive-types 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a0253db64c26d8b4e7896dd2063b516d2a1b9e0a5da26b5b78335f236d1e9522" -"checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -"checksum protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20" -"checksum pwasm-utils 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" -"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac" -"checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" -"checksum rlp 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3a44d5ae8afcb238af8b75640907edc6c931efcfab2c854e81ed35fa080f84cd" -"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_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 rw-stream-sink 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9cbe61c20455d3015b2bb7be39e1872310283b8e5a52f5b242b0ac7581fe78" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" -"checksum sc-application-crypto 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sc-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sc-client-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sc-consensus-slots 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sc-executor 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sc-telemetry 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" -"checksum schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" -"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" -"checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -"checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a" -"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" -"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum send_wrapper 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0eddf2e8f50ced781f288c19f18621fa72a3779e3cb58dbf23b07469b0abeb4" -"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" -"checksum serde-big-array 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "883eee5198ea51720eab8be52a36cf6c0164ac90eea0ed95b649d5e35382404e" -"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" -"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" -"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" -"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" -"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum slog 2.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cc9c640a4adbfbcc11ffb95efe5aa7af7309e002adab54b185507dbf2377b99" -"checksum slog-async 2.3.0 (git+https://github.com/paritytech/slog-async)" = "" -"checksum slog-json 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" -"checksum slog-scope 4.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c44c89dd8b0ae4537d1ae318353eaf7840b4869c536e31c41e963d1ea523ee6" -"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" -"checksum snow 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "afb767eee7d257ba202f0b9b08673bc13b22281632ef45267b19f13100accd2f" -"checksum soketto 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bceb1a3a15232d013d9a3b7cac9e5ce8e2313f348f01d4bc1097e5e53aa07095" -"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" -"checksum sp-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-api-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-arithmetic 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-authority-discovery 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-authorship 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-block-builder 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-blockchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-bridge-eth-poa 0.1.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-consensus 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-consensus-babe 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-core 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-core-storage 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-debug-derive 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-externalities 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-finality-granpda 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-finality-tracker 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-inherents 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-io 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-keyring 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-offchain 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-panic-handler 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-phragmen 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-runtime 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-runtime-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-runtime-interface-proc-macro 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-sandbox 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-serializer 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-session 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-staking 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-state-machine 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-std 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-timestamp 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-transaction-pool-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-transaction-pool-runtime-api 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-trie 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-version 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum sp-wasm-interface 2.0.0 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -"checksum stream-cipher 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" -"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6138f8f88a16d90134763314e3fc76fa3ed6a7db4725d6acf9a3ef95a3188d22" -"checksum strum_macros 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0054a7df764039a6cd8592b9de84be4bec368ff081d203a7d5371cbfa8e65c81" -"checksum substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" -"checksum substrate-wasm-builder-runner 1.0.4 (git+https://github.com/svyatonik/substrate.git?branch=bridge_runtime)" = "" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" -"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" -"checksum tiny-keccak 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2953ca5148619bc99695c1274cb54c5275bbb913c6adad87e72eaf8db9787f69" -"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -"checksum tokio 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f17f5d6ab0f35c1506678b28fb1798bdf74fcb737e9843c7b17b73e426eba38" -"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-codec 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9f5d22fd1e84bd4045d28813491cb7d7caae34d45c80517c2213f09a85e8787a" -"checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" -"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-dns-unofficial 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82c65483db54eb91b4ef3a9389a3364558590faf30ce473141707c0e16fda975" -"checksum tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" -"checksum tokio-executor 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee9ceecf69145923834ea73f32ba40c790fd877b74a7817dd0b089f1eb9c7c8" -"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" -"checksum tokio-fs 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf85e16971e06e680c622e0c1b455be94b086275c5ddcd6d4a83a2bfbb83cda" -"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-io 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "112784d5543df30660b04a72ca423bfbd90e8bb32f94dcf610f15401218b22c5" -"checksum tokio-macros 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "86b616374bcdadd95974e1f0dfca07dc913f1163c53840c0d664aca35114964e" -"checksum tokio-net 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a441682cd32f3559383112c4a7f372f5c9fa1950c5cf8c8dd05274a2ce8c2654" -"checksum tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" -"checksum tokio-rustls 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1df2fa53ac211c136832f530ccb081af9af891af22d685a9493e232c7a359bc2" -"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" -"checksum tokio-sync 0.2.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f1aaeb685540f7407ea0e27f1c9757d258c7c6bf4e3eb19da6fc59b747239d2" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c" -"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" -"checksum tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" -"checksum tokio-timer 0.3.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b97c1587fe71018eb245a4a9daa13a5a3b681bbc1f7fdadfe24720e141472c13" -"checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" -"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" -"checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01d1404644c8b12b16bfcffa4322403a91a451584daaaa7c28d3152e6cbc98cf" -"checksum tower-make 0.3.0-alpha.2a (registry+https://github.com/rust-lang/crates.io-index)" = "316d47dd40cde4ac5d88110eaf9a10a4e2a68612d9c056cd2aa24e37dcb484cd" -"checksum tower-service 0.3.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "63ff37396cd966ce43bea418bfa339f802857495f797dafa00bea5b7221ebdfa" -"checksum tracing 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ff4e4f59e752cb3beb5b61c6d5e11191c7946231ba84faec2902c9efdd8691c5" -"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-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 try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum twofish 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d261e83e727c8e2dbb75dacac67c36e35db36a958ee504f2164fc052434e1" -"checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" -"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum uint 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e75a4cdd7b87b28840dba13c483b9a88ee6bbf16ba5c951ee1ecfcf723078e0d" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum unsigned-varint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f0023a96687fe169081e8adce3f65e3874426b7886e9234d490af2dc077959" -"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" -"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum wasm-bindgen 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "29ae32af33bacd663a9a28241abecf01f2be64e6a185c6139b04f18b6385c5f2" -"checksum wasm-bindgen-backend 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "1845584bd3593442dc0de6e6d9f84454a59a057722f36f005e44665d6ab19d85" -"checksum wasm-bindgen-futures 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "83420b37346c311b9ed822af41ec2e82839bfe99867ec6c54e2da43b7538771c" -"checksum wasm-bindgen-macro 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "87fcc747e6b73c93d22c947a6334644d22cfec5abd8b66238484dc2b0aeb9fe4" -"checksum wasm-bindgen-macro-support 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc4b3f2c4078c8c4a5f363b92fcf62604c5913cbd16c6ff5aaf0f74ec03f570" -"checksum wasm-bindgen-shared 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "ca0b78d6d3be8589b95d1d49cdc0794728ca734adf36d7c9f07e6459508bb53d" -"checksum wasm-bindgen-webidl 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "3126356474ceb717c8fb5549ae387c9fbf4872818454f4d87708bee997214bb5" -"checksum wasm-timer 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aa3e01d234bb71760e685cfafa5e2c96f8ad877c161a721646356651069e26ac" -"checksum wasmi 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bf617d864d25af3587aa745529f7aaa541066c876d57e050c0d0c85c61c92aff" -"checksum wasmi-validation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea78c597064ba73596099281e2f4cfc019075122a65cdda3205af94f0b264d93" -"checksum web-sys 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "98405c0a2e722ed3db341b4c5b70eb9fe0021621f7350bab76df93b09b649bbf" -"checksum web3 0.8.0 (git+https://github.com/svyatonik/rust-web3.git?branch=fix_receipt)" = "" -"checksum webpki 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e664e770ac0110e2384769bcc59ed19e329d81f555916a6e072714957b81b4" -"checksum webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91cd5736df7f12a964a5067a12c62fa38e1bd8080aff1f80bc29be7c80d19ab4" -"checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" -"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee1585dc1484373cbc1cee7aafda26634665cf449436fd6e24bfd1fad230538" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" -"checksum yamux 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2758f29014c1cb7a6e74c1b1160ac8c8203be342d35b73462fc6a13cc6385423" -"checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" -"checksum zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8" -"checksum zeroize_derive 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "080616bd0e31f36095288bb0acdf1f78ef02c2fa15527d7e993f2a6c7591643e" -"checksum zeroize_derive 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" From 01eadd6c04468f95d5b6505cfb1efba2522cb191 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 2 Feb 2020 22:07:35 -0500 Subject: [PATCH 0006/1210] Squashed commit adding admin files: commit 13c9db4a90df62bec88ab0426f1e568aab1ecf8a Author: Hernando Castano Date: Sun Feb 2 22:02:38 2020 -0500 Add README file commit adf214d0506ba10bbeb3bca8578fd1926d818187 Author: Hernando Castano Date: Sun Feb 2 21:52:09 2020 -0500 Add EditorConfig file commit 23b633e9df4bfd72fb10e57a4fd5d7e53755b490 Author: Hernando Castano Date: Sun Feb 2 21:51:58 2020 -0500 Move License to top level and remove .keep files --- relays/ethereum/LICENSE => LICENSE | 0 README.md | 8 ++++++++ modules/.keep | 0 primitives/.keep | 0 relays/.keep | 0 5 files changed, 8 insertions(+) rename relays/ethereum/LICENSE => LICENSE (100%) create mode 100644 README.md delete mode 100644 modules/.keep delete mode 100644 primitives/.keep delete mode 100644 relays/.keep diff --git a/relays/ethereum/LICENSE b/LICENSE similarity index 100% rename from relays/ethereum/LICENSE rename to LICENSE diff --git a/README.md b/README.md new file mode 100644 index 0000000000000..bf84414227822 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# Parity Bridges Common + +This is a collection of components for building bridges. + +The main components that will be constructed here will be bridge modules/runtimes +and bridge relays. + +🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 diff --git a/modules/.keep b/modules/.keep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/primitives/.keep b/primitives/.keep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/relays/.keep b/relays/.keep deleted file mode 100644 index e69de29bb2d1d..0000000000000 From bfe2e6c7e9c2e8b18bf565716e3f0b4a43e44bbf Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Sun, 2 Feb 2020 22:13:28 -0500 Subject: [PATCH 0007/1210] RustFmt the repo (sorry not sorry) --- modules/ethereum/src/finality.rs | 23 +- modules/ethereum/src/import.rs | 107 +++----- modules/ethereum/src/lib.rs | 351 +++++++++++++++---------- modules/ethereum/src/validators.rs | 154 +++++------ modules/ethereum/src/verification.rs | 85 +++--- modules/substrate/src/lib.rs | 71 ++--- modules/substrate/src/storage_proof.rs | 20 +- primitives/ethereum-poa/src/lib.rs | 46 ++-- 8 files changed, 439 insertions(+), 418 deletions(-) diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 74c1660e8c6be..37e16d6ccd438 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -14,16 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use sp_std::prelude::*; +use crate::error::Error; +use crate::{ancestry, Storage}; +use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256}; +use sp_io::crypto::secp256k1_ecdsa_recover; use sp_std::collections::{ btree_map::{BTreeMap, Entry}, btree_set::BTreeSet, vec_deque::VecDeque, }; -use sp_io::crypto::secp256k1_ecdsa_recover; -use primitives::{Address, H256, Header, SealedEmptyStep, public_to_address}; -use crate::{Storage, ancestry}; -use crate::error::Error; +use sp_std::prelude::*; /// Tries to finalize blocks when given block is imported. /// @@ -68,8 +68,8 @@ fn is_finalized( votes: &BTreeMap, requires_two_thirds_majority: bool, ) -> bool { - (!requires_two_thirds_majority && votes.len() * 2 > validators.len()) || - (requires_two_thirds_majority && votes.len() * 3 > validators.len() * 2) + (!requires_two_thirds_majority && votes.len() * 2 > validators.len()) + || (requires_two_thirds_majority && votes.len() * 3 > validators.len() * 2) } /// Prepare 'votes' of header and its ancestors' signers. @@ -157,7 +157,7 @@ fn remove_signers_votes(signers_to_remove: &BTreeSet
, votes: &mut BTree } else { *entry.get_mut() -= 1; } - }, + } Entry::Vacant(_) => unreachable!("we only remove signers that have been added; qed"), } } @@ -165,7 +165,8 @@ fn remove_signers_votes(signers_to_remove: &BTreeSet
, votes: &mut BTree /// Returns unique set of empty steps signers. fn empty_steps_signers(header: &Header) -> BTreeSet
{ - header.empty_steps() + header + .empty_steps() .into_iter() .flat_map(|steps| steps) .filter_map(|step| empty_step_signer(&step, &header.parent_hash)) @@ -182,9 +183,9 @@ fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option #[cfg(test)] mod tests { - use crate::HeaderToImport; - use crate::tests::{InMemoryStorage, genesis, validator, validators_addresses}; use super::*; + use crate::tests::{genesis, validator, validators_addresses, InMemoryStorage}; + use crate::HeaderToImport; #[test] fn verifies_header_author() { diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 318fea1bcc999..c11146526491c 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use sp_std::prelude::*; -use primitives::{H256, Header, Receipt}; -use crate::{AuraConfiguration, Storage}; use crate::error::Error; use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::verify_aura_header; +use crate::{AuraConfiguration, Storage}; +use primitives::{Header, Receipt, H256}; +use sp_std::prelude::*; /// Maximal number of headers behind best blocks that we are aiming to store. When there /// are too many unfinalized headers, it slows down finalization tracking significantly. @@ -50,14 +50,7 @@ pub fn import_headers( let mut useful = 0; let mut useless = 0; for (header, receipts) in headers { - let import_result = import_header( - storage, - aura_config, - validators_config, - prune_depth, - header, - receipts, - ); + let import_result = import_header(storage, aura_config, validators_config, prune_depth, header, receipts); match import_result { Ok(_) => useful += 1, @@ -85,16 +78,11 @@ pub fn import_header( let (hash, prev_finalized_hash) = is_importable_header(storage, &header)?; // verify header - let import_context = verify_aura_header( - storage, - aura_config, - &header, - )?; + let import_context = verify_aura_header(storage, aura_config, &header)?; // check if block schedules new validators let validators = Validators::new(validators_config); - let (scheduled_change, enacted_change) = - validators.extract_validators_change(&header, receipts)?; + let (scheduled_change, enacted_change) = validators.extract_validators_change(&header, receipts)?; // check if block finalizes some other blocks and corresponding scheduled validators let finalized_blocks = finalize_blocks( @@ -105,8 +93,7 @@ pub fn import_header( &header, aura_config.two_thirds_majority_transition, )?; - let enacted_change = enacted_change - .or_else(|| validators.finalize_validators_change(storage, &finalized_blocks)); + let enacted_change = enacted_change.or_else(|| validators.finalize_validators_change(storage, &finalized_blocks)); // NOTE: we can't return Err() from anywhere below this line // (because otherwise we'll have inconsistent storage if transaction will fail) @@ -169,14 +156,12 @@ fn is_importable_header(storage: &S, header: &Header) -> Result<(H25 #[cfg(test)] mod tests { - use crate::{kovan_aura_config, kovan_validators_config}; + use super::*; use crate::tests::{ - InMemoryStorage, - block_i, custom_block_i, signed_header, genesis, - validator, validators_addresses, + block_i, custom_block_i, genesis, signed_header, validator, validators_addresses, InMemoryStorage, }; use crate::validators::ValidatorsSource; - use super::*; + use crate::{kovan_aura_config, kovan_validators_config}; #[test] fn rejects_finalized_block_competitors() { @@ -208,7 +193,8 @@ mod tests { PRUNE_DEPTH, block.clone(), None, - ).map(|_| ()), + ) + .map(|_| ()), Ok(()), ); assert_eq!( @@ -219,7 +205,8 @@ mod tests { PRUNE_DEPTH, block, None, - ).map(|_| ()), + ) + .map(|_| ()), Err(Error::KnownHeader), ); } @@ -235,8 +222,15 @@ mod tests { let header = block_i(&storage, 1, &validators); let hash = header.hash(); assert_eq!( - import_header(&mut storage, &kovan_aura_config(), &validators_config, PRUNE_DEPTH, header, None) - .map(|_| ()), + import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + PRUNE_DEPTH, + header, + None + ) + .map(|_| ()), Ok(()), ); @@ -250,9 +244,8 @@ mod tests { #[test] fn headers_are_pruned() { - let validators_config = ValidatorsConfiguration::Single( - ValidatorsSource::Contract([3; 20].into(), validators_addresses(3)), - ); + let validators_config = + ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), validators_addresses(3))); let validators = vec![validator(0), validator(1), validator(2)]; let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); @@ -261,14 +254,8 @@ mod tests { let mut last_block_hash = Default::default(); for i in 1..11 { let header = block_i(&storage, i, &validators); - last_block_hash = import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - header, - None, - ).unwrap(); + last_block_hash = + import_header(&mut storage, &kovan_aura_config(), &validators_config, 10, header, None).unwrap(); } assert!(storage.header(&genesis().hash()).is_some()); @@ -276,7 +263,9 @@ mod tests { // => we prune header#0 let header = custom_block_i(&storage, 11, &validators, |header| { header.log_bloom = (&[0xff; 256]).into(); - header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951".parse().unwrap(); + header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951" + .parse() + .unwrap(); }); last_block_hash = import_header( &mut storage, @@ -284,8 +273,11 @@ mod tests { &validators_config, 10, header, - Some(vec![crate::validators::tests::validators_change_recept(last_block_hash)]), - ).unwrap(); + Some(vec![crate::validators::tests::validators_change_recept( + last_block_hash, + )]), + ) + .unwrap(); assert!(storage.header(&genesis().hash()).is_none()); // and now let's say validators 1 && 2 went offline @@ -298,22 +290,13 @@ mod tests { parent_hash: last_block_hash, gas_limit: 0x2000.into(), author: validator(2).address().to_fixed_bytes().into(), - seal: vec![ - vec![step].into(), - vec![].into(), - ], + seal: vec![vec![step].into(), vec![].into()], difficulty: i.into(), ..Default::default() }; let header = signed_header(&validators, header, step as _); - last_block_hash = import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - header, - None, - ).unwrap(); + last_block_hash = + import_header(&mut storage, &kovan_aura_config(), &validators_config, 10, header, None).unwrap(); step += 3; } assert_eq!(storage.oldest_unpruned_block(), 11); @@ -326,22 +309,12 @@ mod tests { parent_hash: last_block_hash, gas_limit: 0x2000.into(), author: validator(0).address().to_fixed_bytes().into(), - seal: vec![ - vec![step].into(), - vec![].into(), - ], + seal: vec![vec![step].into(), vec![].into()], difficulty: 25.into(), ..Default::default() }; let header = signed_header(&validators, header, step as _); - import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - header, - None, - ).unwrap(); + import_header(&mut storage, &kovan_aura_config(), &validators_config, 10, header, None).unwrap(); assert_eq!(storage.oldest_unpruned_block(), 15); } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index e1135fad1386a..26e36f8014cc8 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -16,14 +16,14 @@ #![cfg_attr(not(feature = "std"), no_std)] -use sp_std::{prelude::*, iter::from_fn}; use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage}; +use primitives::{Address, Header, Receipt, H256, U256}; use sp_runtime::RuntimeDebug; -use primitives::{Address, U256, H256, Header, Receipt}; -use validators::{ValidatorsSource, ValidatorsConfiguration}; +use sp_std::{iter::from_fn, prelude::*}; +use validators::{ValidatorsConfiguration, ValidatorsSource}; -pub use import::{import_header, header_import_requires_receipts}; +pub use import::{header_import_requires_receipts, import_header}; mod error; mod finality; @@ -180,11 +180,7 @@ pub trait Storage { /// It is the storage duty to ensure that unfinalized headers that have /// scheduled changes won't be pruned until they or their competitors /// are finalized. - fn finalize_headers( - &mut self, - finalized: Option<(u64, H256)>, - prune_end: Option, - ); + fn finalize_headers(&mut self, finalized: Option<(u64, H256)>, prune_end: Option); } /// Decides whether the session should be ended. @@ -304,11 +300,7 @@ impl Module { /// Returns true if the import of given block requires transactions receipts. pub fn is_import_requires_receipts(header: Header) -> bool { - import::header_import_requires_receipts( - &BridgeStorage, - &kovan_validators_config(), - &header, - ) + import::header_import_requires_receipts(&BridgeStorage, &kovan_validators_config(), &header) } /// Returns true if header is known to the runtime. @@ -334,18 +326,17 @@ impl Storage for BridgeStorage { } fn import_context(&self, parent_hash: &H256) -> Option { - Headers::get(parent_hash) - .map(|parent_header| { - let (next_validators_set_start, next_validators) = - ValidatorsSets::get(parent_header.next_validators_set_id) + Headers::get(parent_hash).map(|parent_header| { + let (next_validators_set_start, next_validators) = + ValidatorsSets::get(parent_header.next_validators_set_id) .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); - ImportContext { - parent_header: parent_header.header, - parent_total_difficulty: parent_header.total_difficulty, - next_validators_set_id: parent_header.next_validators_set_id, - next_validators_set: (next_validators_set_start, next_validators), - } - }) + ImportContext { + parent_header: parent_header.header, + parent_total_difficulty: parent_header.total_difficulty, + next_validators_set_id: parent_header.next_validators_set_id, + next_validators_set: (next_validators_set_start, next_validators), + } + }) } fn scheduled_change(&self, hash: &H256) -> Option> { @@ -369,34 +360,33 @@ impl Storage for BridgeStorage { ValidatorsSets::insert(next_validators_set_id, (header.hash, enacted_change)); ValidatorsSetsRc::insert(next_validators_set_id, 1); next_validators_set_id - }, + } None => { - ValidatorsSetsRc::mutate( - header.context.next_validators_set_id, - |rc| { - *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); - *rc - }, - ); + ValidatorsSetsRc::mutate(header.context.next_validators_set_id, |rc| { + *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); + *rc + }); header.context.next_validators_set_id - }, + } }; HeadersByNumber::append_or_insert(header.header.number, vec![header.hash]); - Headers::insert(&header.hash, StoredHeader { - header: header.header, - total_difficulty: header.total_difficulty, - next_validators_set_id, - }); + Headers::insert( + &header.hash, + StoredHeader { + header: header.header, + total_difficulty: header.total_difficulty, + next_validators_set_id, + }, + ); } - fn finalize_headers( - &mut self, - finalized: Option<(u64, H256)>, - prune_end: Option, - ) { + fn finalize_headers(&mut self, finalized: Option<(u64, H256)>, prune_end: Option) { // remember just finalized block - let finalized_number = finalized.as_ref().map(|f| f.0).unwrap_or_else(|| FinalizedBlock::get().0); + let finalized_number = finalized + .as_ref() + .map(|f| f.0) + .unwrap_or_else(|| FinalizedBlock::get().0); if let Some(finalized) = finalized { FinalizedBlock::put(finalized); } @@ -423,13 +413,10 @@ impl Storage for BridgeStorage { let header = Headers::take(&hash); ScheduledChanges::remove(hash); if let Some(header) = header { - ValidatorsSetsRc::mutate( - header.next_validators_set_id, - |rc| match *rc { - Some(rc) if rc > 1 => Some(rc - 1), - _ => None, - }, - ); + ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { + Some(rc) if rc > 1 => Some(rc - 1), + _ => None, + }); } } } @@ -456,50 +443,113 @@ pub fn kovan_aura_config() -> AuraConfiguration { /// Validators configuration for Kovan chain. pub fn kovan_validators_config() -> ValidatorsConfiguration { ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(vec![ - [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, - 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), - [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, - 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), - [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, - 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), - [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, - 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), - [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, - 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), - [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, - 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), - [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, - 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), - [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, - 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), - [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, - 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), - ])), - (10960440, ValidatorsSource::List(vec![ - [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, - 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), - [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, - 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), - [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, - 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), - ])), - (10960500, ValidatorsSource::Contract( - [0xaE, 0x71, 0x80, 0x7C, 0x1B, 0x0a, 0x09, 0x3c, 0xB1, 0x54, - 0x7b, 0x68, 0x2D, 0xC7, 0x83, 0x16, 0xD9, 0x45, 0xc9, 0xB8].into(), - vec![ - [0xd0, 0x5f, 0x74, 0x78, 0xc6, 0xaa, 0x10, 0x78, 0x12, 0x58, - 0xc5, 0xcc, 0x8b, 0x4f, 0x38, 0x5f, 0xc8, 0xfa, 0x98, 0x9c].into(), - [0x03, 0x80, 0x1e, 0xfb, 0x0e, 0xfe, 0x2a, 0x25, 0xed, 0xe5, - 0xdd, 0x3a, 0x00, 0x3a, 0xe8, 0x80, 0xc0, 0x29, 0x2e, 0x4d].into(), - [0xa4, 0xdf, 0x25, 0x5e, 0xcf, 0x08, 0xbb, 0xf2, 0xc2, 0x80, - 0x55, 0xc6, 0x52, 0x25, 0xc9, 0xa9, 0x84, 0x7a, 0xbd, 0x94].into(), - [0x59, 0x6e, 0x82, 0x21, 0xa3, 0x0b, 0xfe, 0x6e, 0x7e, 0xff, - 0x67, 0xfe, 0xe6, 0x64, 0xa0, 0x1c, 0x73, 0xba, 0x3c, 0x56].into(), - [0xfa, 0xad, 0xfa, 0xce, 0x3f, 0xbd, 0x81, 0xce, 0x37, 0xb0, - 0xe1, 0x9c, 0x0b, 0x65, 0xff, 0x42, 0x34, 0x14, 0x81, 0x32].into(), - ], - )), + ( + 0, + ValidatorsSource::List(vec![ + [ + 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, + 0x5B, 0xAd, 0xc0, 0xED, + ] + .into(), + [ + 0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, + 0x65, 0x0a, 0x4d, 0x3d, + ] + .into(), + [ + 0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, + 0x6b, 0x42, 0x4d, 0x6c, + ] + .into(), + [ + 0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, + 0x19, 0xbA, 0x81, 0xA1, + ] + .into(), + [ + 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, + 0x3a, 0xfd, 0x03, 0x2d, + ] + .into(), + [ + 0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, + 0x16, 0x93, 0x38, 0x7A, + ] + .into(), + [ + 0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, + 0x78, 0x89, 0x78, 0x79, + ] + .into(), + [ + 0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, + 0x16, 0xa1, 0x64, 0x5c, + ] + .into(), + [ + 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, + 0x12, 0x31, 0x94, 0xde, + ] + .into(), + ]), + ), + ( + 10960440, + ValidatorsSource::List(vec![ + [ + 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, + 0x5B, 0xAd, 0xc0, 0xED, + ] + .into(), + [ + 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, + 0x3a, 0xfd, 0x03, 0x2d, + ] + .into(), + [ + 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, + 0x12, 0x31, 0x94, 0xde, + ] + .into(), + ]), + ), + ( + 10960500, + ValidatorsSource::Contract( + [ + 0xaE, 0x71, 0x80, 0x7C, 0x1B, 0x0a, 0x09, 0x3c, 0xB1, 0x54, 0x7b, 0x68, 0x2D, 0xC7, 0x83, 0x16, + 0xD9, 0x45, 0xc9, 0xB8, + ] + .into(), + vec![ + [ + 0xd0, 0x5f, 0x74, 0x78, 0xc6, 0xaa, 0x10, 0x78, 0x12, 0x58, 0xc5, 0xcc, 0x8b, 0x4f, 0x38, 0x5f, + 0xc8, 0xfa, 0x98, 0x9c, + ] + .into(), + [ + 0x03, 0x80, 0x1e, 0xfb, 0x0e, 0xfe, 0x2a, 0x25, 0xed, 0xe5, 0xdd, 0x3a, 0x00, 0x3a, 0xe8, 0x80, + 0xc0, 0x29, 0x2e, 0x4d, + ] + .into(), + [ + 0xa4, 0xdf, 0x25, 0x5e, 0xcf, 0x08, 0xbb, 0xf2, 0xc2, 0x80, 0x55, 0xc6, 0x52, 0x25, 0xc9, 0xa9, + 0x84, 0x7a, 0xbd, 0x94, + ] + .into(), + [ + 0x59, 0x6e, 0x82, 0x21, 0xa3, 0x0b, 0xfe, 0x6e, 0x7e, 0xff, 0x67, 0xfe, 0xe6, 0x64, 0xa0, 0x1c, + 0x73, 0xba, 0x3c, 0x56, + ] + .into(), + [ + 0xfa, 0xad, 0xfa, 0xce, 0x3f, 0xbd, 0x81, 0xce, 0x37, 0xb0, 0xe1, 0x9c, 0x0b, 0x65, 0xff, 0x42, + 0x34, 0x14, 0x81, 0x32, + ] + .into(), + ], + ), + ), ]) } @@ -517,25 +567,22 @@ pub(crate) fn ancestry<'a, S: Storage>(storage: &'a S, header: &Header) -> impl let hash = parent_hash.clone(); parent_hash = header.parent_hash.clone(); Some((hash, header)) - }, - None => None + } + None => None, } }) } #[cfg(test)] pub(crate) mod tests { - use std::collections::{HashMap, hash_map::Entry}; - use parity_crypto::publickey::{KeyPair, Secret, sign}; - use primitives::{H520, rlp_encode}; use super::*; + use parity_crypto::publickey::{sign, KeyPair, Secret}; + use primitives::{rlp_encode, H520}; + use std::collections::{hash_map::Entry, HashMap}; pub fn genesis() -> Header { Header { - seal: vec![ - vec![42].into(), - vec![].into(), - ], + seal: vec![vec![42].into(), vec![].into()], ..Default::default() } } @@ -556,10 +603,7 @@ pub(crate) mod tests { parent_hash: storage.headers_by_number[&(number - 1)][0].clone(), gas_limit: 0x2000.into(), author: validator(validator_index).address().to_fixed_bytes().into(), - seal: vec![ - vec![number as u8 + 42].into(), - vec![].into(), - ], + seal: vec![vec![number as u8 + 42].into(), vec![].into()], difficulty: number.into(), ..Default::default() }; @@ -582,7 +626,9 @@ pub(crate) mod tests { } pub fn validators_addresses(count: u8) -> Vec
{ - (0..count as usize).map(|i| validator(i as u8).address().as_fixed_bytes().into()).collect() + (0..count as usize) + .map(|i| validator(i as u8).address().as_fixed_bytes().into()) + .collect() } pub struct InMemoryStorage { @@ -612,7 +658,9 @@ pub(crate) mod tests { total_difficulty: 0.into(), next_validators_set_id: 0, }, - )].into_iter().collect(), + )] + .into_iter() + .collect(), next_validators_set_id: 1, validators_sets: vec![(0, (hash, initial_validators))].into_iter().collect(), validators_sets_rc: vec![(0, 1)].into_iter().collect(), @@ -643,17 +691,16 @@ pub(crate) mod tests { } fn import_context(&self, parent_hash: &H256) -> Option { - self.headers.get(parent_hash) - .map(|parent_header| { - let (next_validators_set_start, next_validators) = - self.validators_sets.get(&parent_header.next_validators_set_id).unwrap(); - ImportContext { - parent_header: parent_header.header.clone(), - parent_total_difficulty: parent_header.total_difficulty, - next_validators_set_id: parent_header.next_validators_set_id, - next_validators_set: (*next_validators_set_start, next_validators.clone()), - } - }) + self.headers.get(parent_hash).map(|parent_header| { + let (next_validators_set_start, next_validators) = + self.validators_sets.get(&parent_header.next_validators_set_id).unwrap(); + ImportContext { + parent_header: parent_header.header.clone(), + parent_total_difficulty: parent_header.total_difficulty, + next_validators_set_id: parent_header.next_validators_set_id, + next_validators_set: (*next_validators_set_start, next_validators.clone()), + } + }) } fn scheduled_change(&self, hash: &H256) -> Option> { @@ -671,30 +718,39 @@ pub(crate) mod tests { Some(enacted_change) => { let next_validators_set_id = self.next_validators_set_id; self.next_validators_set_id += 1; - self.validators_sets.insert(next_validators_set_id, (header.hash, enacted_change)); + self.validators_sets + .insert(next_validators_set_id, (header.hash, enacted_change)); self.validators_sets_rc.insert(next_validators_set_id, 1); next_validators_set_id - }, + } None => { - *self.validators_sets_rc.entry(header.context.next_validators_set_id).or_default() += 1; + *self + .validators_sets_rc + .entry(header.context.next_validators_set_id) + .or_default() += 1; header.context.next_validators_set_id - }, + } }; - self.headers_by_number.entry(header.header.number).or_default().push(header.hash); - self.headers.insert(header.hash, StoredHeader { - header: header.header, - total_difficulty: header.total_difficulty, - next_validators_set_id, - }); + self.headers_by_number + .entry(header.header.number) + .or_default() + .push(header.hash); + self.headers.insert( + header.hash, + StoredHeader { + header: header.header, + total_difficulty: header.total_difficulty, + next_validators_set_id, + }, + ); } - fn finalize_headers( - &mut self, - finalized: Option<(u64, H256)>, - prune_end: Option, - ) { - let finalized_number = finalized.as_ref().map(|f| f.0).unwrap_or_else(|| self.finalized_block.0); + fn finalize_headers(&mut self, finalized: Option<(u64, H256)>, prune_end: Option) { + let finalized_number = finalized + .as_ref() + .map(|f| f.0) + .unwrap_or_else(|| self.finalized_block.0); if let Some(finalized) = finalized { self.finalized_block = finalized; } @@ -708,7 +764,10 @@ pub(crate) mod tests { // ensure that unfinalized headers we want to prune do not have scheduled changes if number > finalized_number { if let Some(ref blocks_at_number) = blocks_at_number { - if blocks_at_number.iter().any(|block| self.scheduled_changes.contains_key(block)) { + if blocks_at_number + .iter() + .any(|block| self.scheduled_changes.contains_key(block)) + { self.headers_by_number.insert(number, blocks_at_number.clone()); self.oldest_unpruned_block = number; return; @@ -722,12 +781,14 @@ pub(crate) mod tests { self.scheduled_changes.remove(&hash); if let Some(header) = header { match self.validators_sets_rc.entry(header.next_validators_set_id) { - Entry::Occupied(mut entry) => if *entry.get() == 1 { - entry.remove(); - } else { - *entry.get_mut() -= 1; - }, - Entry::Vacant(_) => unreachable!("there's entry for each header") + Entry::Occupied(mut entry) => { + if *entry.get() == 1 { + entry.remove(); + } else { + *entry.get_mut() -= 1; + } + } + Entry::Vacant(_) => unreachable!("there's entry for each header"), }; } } diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index db1eacd3b3318..0860f807ffdd5 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -14,15 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use sp_std::prelude::*; -use primitives::{Address, H256, Header, LogEntry, Receipt, U256}; -use crate::Storage; use crate::error::Error; +use crate::Storage; +use primitives::{Address, Header, LogEntry, Receipt, H256, U256}; +use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. -const CHANGE_EVENT_HASH: &'static [u8; 32] = &[0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, - 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, 0xd2, 0xc2, 0x28, 0x1d, 0xf8, 0xd6, 0xea, - 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89]; +const CHANGE_EVENT_HASH: &'static [u8; 32] = &[ + 0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, 0xd2, 0xc2, 0x28, + 0x1d, 0xf8, 0xd6, 0xea, 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89, +]; /// Where source of validators addresses come from. This covers the chain lifetime. pub enum ValidatorsConfiguration { @@ -76,12 +77,10 @@ impl<'a> Validators<'a> { // that the contract has (probably) emitted epoch change event let expected_bloom = LogEntry { address: *contract_address, - topics: vec![ - CHANGE_EVENT_HASH.into(), - header.parent_hash, - ], + topics: vec![CHANGE_EVENT_HASH.into(), header.parent_hash], data: Vec::new(), // irrelevant for bloom. - }.bloom(); + } + .bloom(); header.log_bloom.contains(&expected_bloom) } @@ -120,12 +119,10 @@ impl<'a> Validators<'a> { // that the contract has (probably) emitted epoch change event let expected_bloom = LogEntry { address: *contract_address, - topics: vec![ - CHANGE_EVENT_HASH.into(), - header.parent_hash, - ], + topics: vec![CHANGE_EVENT_HASH.into(), header.parent_hash], data: Vec::new(), // irrelevant for bloom. - }.bloom(); + } + .bloom(); if !header.log_bloom.contains(&expected_bloom) { return Ok((None, None)); @@ -138,41 +135,47 @@ impl<'a> Validators<'a> { // iterate in reverse because only the _last_ change in a given // block actually has any effect - Ok((receipts.iter() - .rev() - .filter(|r| r.log_bloom.contains(&expected_bloom)) - .flat_map(|r| r.logs.iter()) - .filter(|l| l.address == *contract_address && - l.topics.len() == 2 && - l.topics[0].as_fixed_bytes() == CHANGE_EVENT_HASH && - l.topics[1] == header.parent_hash - ) - .filter_map(|l| { - let data_len = l.data.len(); - if data_len < 64 { - return None; - } + Ok(( + receipts + .iter() + .rev() + .filter(|r| r.log_bloom.contains(&expected_bloom)) + .flat_map(|r| r.logs.iter()) + .filter(|l| { + l.address == *contract_address + && l.topics.len() == 2 && l.topics[0].as_fixed_bytes() == CHANGE_EVENT_HASH + && l.topics[1] == header.parent_hash + }) + .filter_map(|l| { + let data_len = l.data.len(); + if data_len < 64 { + return None; + } - let new_validators_len_u256 = U256::from_big_endian(&l.data[32..64]); - let new_validators_len = new_validators_len_u256.low_u64(); - if new_validators_len_u256 != new_validators_len.into() { - return None; - } + let new_validators_len_u256 = U256::from_big_endian(&l.data[32..64]); + let new_validators_len = new_validators_len_u256.low_u64(); + if new_validators_len_u256 != new_validators_len.into() { + return None; + } - if (data_len - 64) as u64 != new_validators_len.saturating_mul(32) { - return None; - } + if (data_len - 64) as u64 != new_validators_len.saturating_mul(32) { + return None; + } - Some(l.data[64..] - .chunks(32) - .map(|chunk| { - let mut new_validator = Address::default(); - new_validator.as_mut().copy_from_slice(&chunk[12..32]); - new_validator - }) - .collect()) - }) - .next(), None)) + Some( + l.data[64..] + .chunks(32) + .map(|chunk| { + let mut new_validator = Address::default(); + new_validator.as_mut().copy_from_slice(&chunk[12..32]); + new_validator + }) + .collect(), + ) + }) + .next(), + None, + )) } /// Finalize changes when blocks are finalized. @@ -193,12 +196,16 @@ impl<'a> Validators<'a> { fn source_at<'b>(&'b self, header_number: u64) -> (usize, u64, &'b ValidatorsSource) { match self.config { ValidatorsConfiguration::Single(ref source) => (0, 0, source), - ValidatorsConfiguration::Multi(ref sources) => sources.iter().rev() + ValidatorsConfiguration::Multi(ref sources) => sources + .iter() + .rev() .enumerate() .find(|(_, &(begin, _))| begin < header_number) .map(|(i, (begin, source))| (sources.len() - 1 - i, *begin, source)) - .expect("there's always entry for the initial block;\ - we do not touch any headers with number < initial block number; qed"), + .expect( + "there's always entry for the initial block;\ + we do not touch any headers with number < initial block number; qed", + ), } } @@ -221,7 +228,7 @@ impl<'a> Validators<'a> { let source = &sources[header_source_index]; (source.0, &source.1) - }, + } } } } @@ -243,32 +250,24 @@ pub fn step_validator(header_validators: &[Address], header_step: u64) -> Addres #[cfg(test)] pub(crate) mod tests { - use primitives::TransactionOutcome; - use crate::kovan_validators_config; use super::*; + use crate::kovan_validators_config; + use primitives::TransactionOutcome; pub(crate) fn validators_change_recept(parent_hash: H256) -> Receipt { Receipt { gas_used: 0.into(), log_bloom: (&[0xff; 256]).into(), outcome: TransactionOutcome::Unknown, - logs: vec![ - LogEntry { - address: [3; 20].into(), - topics: vec![ - CHANGE_EVENT_HASH.into(), - parent_hash, - ], - data: vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - ], - }, - ], + logs: vec![LogEntry { + address: [3; 20].into(), + topics: vec![CHANGE_EVENT_HASH.into(), parent_hash], + data: vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + ], + }], } } @@ -347,10 +346,7 @@ pub(crate) mod tests { // when we're inside list range header.number = 150; - assert_eq!( - validators.extract_validators_change(&header, None), - Ok((None, None)), - ); + assert_eq!(validators.extract_validators_change(&header, None), Ok((None, None)),); // when we're at the block that switches to contract source header.number = 200; @@ -370,7 +366,9 @@ pub(crate) mod tests { // when we're inside contract range and logs bloom signals change // but there's no change in receipts - header.receipts_root = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(); + header.receipts_root = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + .parse() + .unwrap(); assert_eq!( validators.extract_validators_change(&header, Some(Vec::new())), Ok((None, None)), @@ -379,7 +377,9 @@ pub(crate) mod tests { // when we're inside contract range and logs bloom signals change // and there's change in receipts let receipts = vec![validators_change_recept(Default::default())]; - header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45".parse().unwrap(); + header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" + .parse() + .unwrap(); assert_eq!( validators.extract_validators_change(&header, Some(receipts)), Ok((Some(vec![[7; 20].into()]), None)), diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 10574db327644..09de275877cb6 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use sp_io::crypto::secp256k1_ecdsa_recover; -use primitives::{Address, Header, H256, H520, SealedEmptyStep, U128, U256, public_to_address}; -use crate::{AuraConfiguration, ImportContext, Storage}; use crate::error::Error; use crate::validators::step_validator; +use crate::{AuraConfiguration, ImportContext, Storage}; +use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256, H520, U128, U256}; +use sp_io::crypto::secp256k1_ecdsa_recover; /// Verify header by Aura rules. pub fn verify_aura_header( @@ -30,14 +30,15 @@ pub fn verify_aura_header( contextless_checks(params, header)?; // the rest of checks requires parent - let context = storage.import_context(&header.parent_hash).ok_or(Error::MissingParentBlock)?; + let context = storage + .import_context(&header.parent_hash) + .ok_or(Error::MissingParentBlock)?; let validators = context.validators(); let header_step = header.step().ok_or(Error::MissingStep)?; let parent_step = context.parent_header().step().ok_or(Error::MissingStep)?; // Ensure header is from the step after context. - if header_step == parent_step - || (header.number >= params.validate_step_transition && header_step <= parent_step) { + if header_step == parent_step || (header.number >= params.validate_step_transition && header_step <= parent_step) { return Err(Error::DoubleVote); } @@ -69,7 +70,7 @@ pub fn verify_aura_header( } empty_steps_len - }, + } false => 0, }; @@ -160,20 +161,22 @@ fn verify_signature(expected_validator: &Address, signature: &H520, message: &H2 #[cfg(test)] mod tests { - use parity_crypto::publickey::{KeyPair, sign}; - use primitives::{H520, rlp_encode}; - use crate::kovan_aura_config; - use crate::tests::{InMemoryStorage, genesis, signed_header, validator, validators_addresses}; use super::*; + use crate::kovan_aura_config; + use crate::tests::{genesis, signed_header, validator, validators_addresses, InMemoryStorage}; + use parity_crypto::publickey::{sign, KeyPair}; + use primitives::{rlp_encode, H520}; fn sealed_empty_step(validators: &[KeyPair], parent_hash: &H256, step: u64) -> SealedEmptyStep { - let mut empty_step = SealedEmptyStep { step, signature: Default::default() }; + let mut empty_step = SealedEmptyStep { + step, + signature: Default::default(), + }; let message = empty_step.message(parent_hash); let validator_index = (step % validators.len() as u64) as usize; - let signature: [u8; 65] = sign( - validators[validator_index].secret(), - &message.as_fixed_bytes().into(), - ).unwrap().into(); + let signature: [u8; 65] = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()) + .unwrap() + .into(); empty_step.signature = signature.into(); empty_step } @@ -321,17 +324,11 @@ mod tests { assert_eq!(default_verify(&header), Err(Error::MissingStep)); // when step is the same as for the parent block - header.seal = vec![ - vec![42].into(), - vec![].into(), - ]; + header.seal = vec![vec![42].into(), vec![].into()]; assert_eq!(default_verify(&header), Err(Error::DoubleVote)); // when step is OK - header.seal = vec![ - vec![43].into(), - vec![].into(), - ]; + header.seal = vec![vec![43].into(), vec![].into()]; assert_ne!(default_verify(&header), Err(Error::DoubleVote)); // now check with validate_step check enabled @@ -339,17 +336,11 @@ mod tests { config.validate_step_transition = 0; // when step is lesser that for the parent block - header.seal = vec![ - vec![40].into(), - vec![].into(), - ]; + header.seal = vec![vec![40].into(), vec![].into()]; assert_eq!(verify_with_config(&config, &header), Err(Error::DoubleVote)); // when step is OK - header.seal = vec![ - vec![44].into(), - vec![].into(), - ]; + header.seal = vec![vec![44].into(), vec![].into()]; assert_ne!(verify_with_config(&config, &header), Err(Error::DoubleVote)); } @@ -364,9 +355,7 @@ mod tests { seal: vec![ vec![45].into(), vec![142].into(), - SealedEmptyStep::rlp_of(&[ - sealed_empty_step(&validators, &genesis().hash(), 42), - ]), + SealedEmptyStep::rlp_of(&[sealed_empty_step(&validators, &genesis().hash(), 42)]), ], gas_limit: kovan_aura_config().min_gas_limit, parent_hash: genesis().hash(), @@ -403,10 +392,7 @@ mod tests { // when chain score is invalid let mut header = Header { - seal: vec![ - vec![43].into(), - vec![].into(), - ], + seal: vec![vec![43].into(), vec![].into()], gas_limit: kovan_aura_config().min_gas_limit, parent_hash: genesis().hash(), ..Default::default() @@ -421,16 +407,17 @@ mod tests { #[test] fn verifies_validator() { let validators = vec![validator(0), validator(1), validator(2)]; - let good_header = signed_header(&validators, Header { - author: validators[1].address().as_fixed_bytes().into(), - seal: vec![ - vec![43].into(), - vec![].into(), - ], - gas_limit: kovan_aura_config().min_gas_limit, - parent_hash: genesis().hash(), - ..Default::default() - }, 43); + let good_header = signed_header( + &validators, + Header { + author: validators[1].address().as_fixed_bytes().into(), + seal: vec![vec![43].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: genesis().hash(), + ..Default::default() + }, + 43, + ); // when header author is invalid let mut header = good_header.clone(); diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index b66e5f610e07f..ca3fe2839a565 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -37,14 +37,14 @@ mod storage_proof; use crate::storage_proof::{StorageProof, StorageProofChecker}; -use codec::{Encode, Decode}; -use sp_finality_grandpa::{AuthorityId, AuthorityWeight, GRANDPA_AUTHORITIES_KEY}; -use sp_runtime::traits::Header; +use codec::{Decode, Encode}; use frame_support::{ - dispatch::{DispatchResult, DispatchError}, decl_error, decl_module, decl_storage, + dispatch::{DispatchError, DispatchResult}, }; use frame_system::{self as system, ensure_signed}; +use sp_finality_grandpa::{AuthorityId, AuthorityWeight, GRANDPA_AUTHORITIES_KEY}; +use sp_runtime::traits::Header; use storage_proof::Error as StorageError; #[derive(Encode, Decode, Clone, PartialEq)] @@ -58,12 +58,11 @@ pub struct BridgeInfo { impl BridgeInfo { pub fn new( - block_number: &T::BlockNumber, - block_hash: &T::Hash, - state_root: &T::Hash, - validator_set: Vec<(AuthorityId, AuthorityWeight)>, - ) -> Self - { + block_number: &T::BlockNumber, + block_hash: &T::Hash, + state_root: &T::Hash, + validator_set: Vec<(AuthorityId, AuthorityWeight)>, + ) -> Self { // I don't like how this is done, should come back to... BridgeInfo { last_finalized_block_number: *block_number, @@ -140,11 +139,8 @@ impl Module { proof: StorageProof, validator_set: &Vec<(AuthorityId, AuthorityWeight)>, ) -> DispatchResult { - - let checker = ::Hasher>>::new( - *state_root, - proof.clone() - ); + let checker = + ::Hasher>>::new(*state_root, proof.clone()); let checker = checker.map_err(Self::map_storage_err)?; @@ -152,7 +148,9 @@ impl Module { // with the stuff we get out of storage via `read_value` let encoded_validator_set = validator_set.encode(); - let c = checker.read_value(GRANDPA_AUTHORITIES_KEY).map_err(Self::map_storage_err)?; + let c = checker + .read_value(GRANDPA_AUTHORITIES_KEY) + .map_err(Self::map_storage_err)?; let actual_validator_set = c.ok_or(Error::::StorageValueUnavailable)?; if encoded_validator_set == actual_validator_set { @@ -182,7 +180,7 @@ impl Module { parent_hash = header.parent_hash(); if *parent_hash == ancestor_hash { - return Ok(()) + return Ok(()); } } @@ -193,7 +191,8 @@ impl Module { match e { StorageError::StorageRootMismatch => Error::::StorageRootMismatch, StorageError::StorageValueUnavailable => Error::::StorageValueUnavailable, - }.into() + } + .into() } } @@ -201,11 +200,14 @@ impl Module { mod tests { use super::*; - use sp_core::{Blake2Hasher, H256, Public}; + use frame_support::{assert_err, assert_ok, impl_outer_origin, parameter_types}; + use sp_core::{Blake2Hasher, Public, H256}; use sp_runtime::{ - Perbill, traits::{Header as HeaderT, IdentityLookup}, testing::Header, generic::Digest, + generic::Digest, + testing::Header, + traits::{Header as HeaderT, IdentityLookup}, + Perbill, }; - use frame_support::{assert_ok, assert_err, impl_outer_origin, parameter_types}; impl_outer_origin! { pub enum Origin for Test where system = frame_system {} @@ -251,9 +253,7 @@ mod tests { fn new_test_ext() -> sp_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { - num_bridges: 0, - }.assimilate_storage(&mut t).unwrap(); + GenesisConfig { num_bridges: 0 }.assimilate_storage(&mut t).unwrap(); t.into() } @@ -273,14 +273,15 @@ mod tests { } fn create_dummy_validator_proof(validator_set: Vec<(AuthorityId, AuthorityWeight)>) -> (H256, StorageProof) { - use sp_state_machine::{prove_read, backend::Backend, InMemoryBackend}; + use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; let encoded_set = validator_set.encode(); // construct storage proof - let backend = >::from(vec![ - (None, vec![(GRANDPA_AUTHORITIES_KEY.to_vec(), Some(encoded_set))]), - ]); + let backend = >::from(vec![( + None, + vec![(GRANDPA_AUTHORITIES_KEY.to_vec(), Some(encoded_set))], + )]); let root = backend.storage_root(std::iter::empty()).0; // Generates a storage read proof @@ -332,12 +333,11 @@ mod tests { new_test_ext().execute_with(|| { assert_eq!(MockBridge::num_bridges(), 0); dbg!(&test_header); - assert_ok!( - MockBridge::initialize_bridge( - Origin::signed(1), - test_header, - authorities.clone(), - proof, + assert_ok!(MockBridge::initialize_bridge( + Origin::signed(1), + test_header, + authorities.clone(), + proof, )); assert_eq!( @@ -347,7 +347,8 @@ mod tests { last_finalized_block_hash: test_hash, last_finalized_state_root: root, current_validator_set: authorities.clone(), - })); + }) + ); assert_eq!(MockBridge::num_bridges(), 1); }); diff --git a/modules/substrate/src/storage_proof.rs b/modules/substrate/src/storage_proof.rs index cda8311fd03df..68f2c07a20e31 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/modules/substrate/src/storage_proof.rs @@ -16,9 +16,9 @@ //! Logic for checking Substrate storage proofs. -use hash_db::{Hasher, HashDB, EMPTY_PREFIX}; -use sp_trie::{MemoryDB, Trie, trie_types::TrieDB}; +use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; +use sp_trie::{trie_types::TrieDB, MemoryDB, Trie}; pub(crate) type StorageProof = Vec>; @@ -26,14 +26,16 @@ pub(crate) type StorageProof = Vec>; /// 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 +where + H: Hasher, { root: H::Out, db: MemoryDB, } impl StorageProofChecker - where H: Hasher +where + H: Hasher, { /// Constructs a new storage proof checker. /// @@ -43,10 +45,7 @@ impl StorageProofChecker for item in proof { db.insert(EMPTY_PREFIX, &item); } - let checker = StorageProofChecker { - root, - db, - }; + let checker = StorageProofChecker { root, db }; // Return error if trie would be invalid. let _ = checker.trie()?; Ok(checker) @@ -62,8 +61,7 @@ impl StorageProofChecker } fn trie(&self) -> Result, Error> { - TrieDB::new(&self.db, &self.root) - .map_err(|_| Error::StorageRootMismatch) + TrieDB::new(&self.db, &self.root).map_err(|_| Error::StorageRootMismatch) } } @@ -78,7 +76,7 @@ mod tests { use super::*; use sp_core::{Blake2Hasher, H256}; - use sp_state_machine::{prove_read, backend::Backend, InMemoryBackend}; + use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; #[test] fn storage_proof_check() { diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index f2a7ab7f14f17..2cd5d8d2d6838 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -22,21 +22,21 @@ pub use primitive_types::{H160, H256, H512, U128, U256}; #[cfg(feature = "test-helpers")] pub use rlp::encode as rlp_encode; -use sp_std::prelude::*; -use sp_io::hashing::keccak_256; use codec::{Decode, Encode}; use ethbloom::{Bloom as EthBloom, Input as BloomInput}; +use fixed_hash::construct_fixed_hash; use rlp::{Decodable, DecoderError, Rlp, RlpStream}; +use sp_io::hashing::keccak_256; use sp_runtime::RuntimeDebug; -use fixed_hash::construct_fixed_hash; +use sp_std::prelude::*; -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -#[cfg(feature = "std")] -use serde_big_array::big_array; use impl_rlp::impl_fixed_hash_rlp; #[cfg(feature = "std")] use impl_serde::impl_fixed_hash_serde; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +#[cfg(feature = "std")] +use serde_big_array::big_array; construct_fixed_hash! { pub struct H520(65); } impl_fixed_hash_rlp!(H520, 65); @@ -121,10 +121,7 @@ pub struct LogEntry { /// Logs bloom. #[derive(Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Bloom( - #[cfg_attr(feature = "std", serde(with = "BigArray"))] - [u8; 256] -); +pub struct Bloom(#[cfg_attr(feature = "std", serde(with = "BigArray"))] [u8; 256]); #[cfg(feature = "std")] big_array! { BigArray; } @@ -172,7 +169,7 @@ impl Header { let mut message = self.hash().as_bytes().to_vec(); message.extend_from_slice(self.seal.get(2)?); keccak_256(&message).into() - }, + } false => keccak_256(&self.rlp(false)).into(), }) } @@ -189,7 +186,9 @@ impl Header { /// Extracts the empty steps from the header seal. pub fn empty_steps(&self) -> Option> { - self.seal.get(2).and_then(|x| Rlp::new(x).as_list::().ok()) + self.seal + .get(2) + .and_then(|x| Rlp::new(x).as_list::().ok()) } /// Returns header RLP with or without seals. @@ -232,15 +231,15 @@ impl Receipt { match self.outcome { TransactionOutcome::Unknown => { s.begin_list(3); - }, + } TransactionOutcome::StateRoot(ref root) => { s.begin_list(4); s.append(root); - }, + } TransactionOutcome::StatusCode(ref status_code) => { s.begin_list(4); s.append(status_code); - }, + } } s.append(&self.gas_used); s.append(&EthBloom::from(self.log_bloom.0)); @@ -275,9 +274,7 @@ impl SealedEmptyStep { let mut s = RlpStream::new(); s.begin_list(empty_steps.len()); for empty_step in empty_steps { - s.begin_list(2) - .append(&empty_step.signature) - .append(&empty_step.step); + s.begin_list(2).append(&empty_step.signature).append(&empty_step.step); } s.out() } @@ -295,10 +292,13 @@ impl Decodable for SealedEmptyStep { impl LogEntry { /// Calculates the bloom of this log entry. pub fn bloom(&self) -> Bloom { - let eth_bloom = self.topics.iter().fold(EthBloom::from(BloomInput::Raw(self.address.as_bytes())), |mut b, t| { - b.accrue(BloomInput::Raw(t.as_bytes())); - b - }); + let eth_bloom = + self.topics + .iter() + .fold(EthBloom::from(BloomInput::Raw(self.address.as_bytes())), |mut b, t| { + b.accrue(BloomInput::Raw(t.as_bytes())); + b + }); Bloom(*eth_bloom.data()) } } From e82fa55bd11febaf1c410f9c97d027e8339f29b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 10 Feb 2020 16:47:42 +0100 Subject: [PATCH 0008/1210] Add lock file, fix latest substrate. (#3) --- modules/ethereum/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 26e36f8014cc8..2288c205bdac6 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -400,7 +400,7 @@ impl Storage for BridgeStorage { // ensure that unfinalized headers we want to prune do not have scheduled changes if number > finalized_number { if let Some(ref blocks_at_number) = blocks_at_number { - if blocks_at_number.iter().any(|block| ScheduledChanges::exists(block)) { + if blocks_at_number.iter().any(|block| ScheduledChanges::contains_key(block)) { HeadersByNumber::insert(number, blocks_at_number); OldestUnprunedBlock::put(number); return; From 7fda854285bc13b75d1bd542a24c1eb70368a381 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 2 Mar 2020 12:20:23 -0500 Subject: [PATCH 0009/1210] Move `substrate-bridge-relay` into repository (#1) * Initial commit. CLI which parses RPC urls. * Establish ws connections and make simple RPC requests. * Complete bridge setup. * Process subscription events. * Ctrl-C handler. * Write a bare-bones README and copy in design doc. * Modularize code a little bit. * Communicate with each chain in a separate task. * Parse headers from RPC subscription notifications. * Send (fake) extrinsics across bridge channels. And now it's deadlocked. * Fix deadlock. * Clarify in README that this is not-in-progress. * Move everything into a single folder * Move Substrate relay into appropriate folder * Get the Substrate Relay node compiling * Update Cargo.lock * Use new composite accounts from Substrate * Remove specification document It has been moved to the Wiki on the Github repo. * Update author + remove comments * Use latest master for jsonrpsee Required renaming some stuff (e.g Client -> RawClient) Co-authored-by: Jim Posen --- modules/substrate/src/lib.rs | 3 + relays/substrate/Cargo.toml | 20 ++ relays/substrate/README.md | 32 +++ relays/substrate/src/bridge.rs | 391 +++++++++++++++++++++++++++++++++ relays/substrate/src/error.rs | 31 +++ relays/substrate/src/main.rs | 80 +++++++ relays/substrate/src/params.rs | 75 +++++++ relays/substrate/src/rpc.rs | 29 +++ 8 files changed, 661 insertions(+) create mode 100644 relays/substrate/Cargo.toml create mode 100644 relays/substrate/README.md create mode 100644 relays/substrate/src/bridge.rs create mode 100644 relays/substrate/src/error.rs create mode 100644 relays/substrate/src/main.rs create mode 100644 relays/substrate/src/params.rs create mode 100644 relays/substrate/src/rpc.rs diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index ca3fe2839a565..ad27627f62cae 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -247,6 +247,9 @@ mod tests { type MaximumBlockLength = (); type Version = (); type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnReapAccount = (); } impl Trait for Test {} diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml new file mode 100644 index 0000000000000..d3382cedd4625 --- /dev/null +++ b/relays/substrate/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "substrate-bridge" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +async-std = "1.0.1" +clap = "2.3.3" +ctrlc = "3.1.3" +derive_more = "0.99.1" +env_logger = "0.7.1" +futures = "0.3.1" +jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } +log = "0.4.8" +node-primitives = { version = "2.0.0", git = "https://github.com/paritytech/substrate" } +serde_json = "1.0.41" +sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git" } +sp-rpc = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git" } +url = "2.1.0" diff --git a/relays/substrate/README.md b/relays/substrate/README.md new file mode 100644 index 0000000000000..dcbaeaaed5a85 --- /dev/null +++ b/relays/substrate/README.md @@ -0,0 +1,32 @@ +# Substrate-to-Substrate Bridge Relay + +The bridge relay is a process that connects to running Substrate nodes and sends data over the Substrate-to-Substrate bridge. The process communicates with the nodes over the JSON-RPC interface and reads data from the relays information required by the `bridge` pallet using runtime calls and writes data to the modules by constructing and submitting extrinsics. + +For more details, see the [design document](doc/design.md). + +## Status + +This is a not-in-progress prototype. + +## Running in development + +Run two development Substrate chains: + +```bash +> TMPDIR=(mktemp -d) +> cd $TMPDIR +> substrate build-spec --dev > red-spec.json +> cp red-spec.json blue-spec.json +# Modify the chain spec in an editor so that the genesis hashes of the two chains differ. +# For example, double one of the balances in '$.genesis.runtime.balances.balances'. +> substrate --chain red-spec.json --alice --base-path ./red --port 30343 --ws-port 9954 +> substrate --chain blue-spec.json --alice --base-path ./blue --port 30353 --ws-port 9964 +``` + +Now run the bridge relay: + +``` +> target/release/substrate-bridge --base-path ./relay \ + --rpc-url ws://localhost:9954 \ + --rpc-url ws://localhost:9964 +``` diff --git a/relays/substrate/src/bridge.rs b/relays/substrate/src/bridge.rs new file mode 100644 index 0000000000000..7a733c5862e57 --- /dev/null +++ b/relays/substrate/src/bridge.rs @@ -0,0 +1,391 @@ +use crate::error::Error; +use crate::rpc::{self, SubstrateRPC}; +use crate::params::{RPCUrlParam, Params}; + +use futures::{prelude::*, channel::{mpsc, oneshot}, future, select}; +use jsonrpsee::{ + core::client::{RawClientError, RawClientEvent, RawClientRequestId, RawClientSubscription}, + ws::{WsRawClient, WsConnecError, ws_raw_client}, +}; +use node_primitives::{Hash, Header}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::pin::Pin; +use sp_core::Bytes; + +type ChainId = Hash; + +struct BridgeState { + channel: mpsc::Sender, + locally_finalized_head_on_bridged_chain: Header, +} + +struct ChainState { + current_finalized_head: Header, + bridges: HashMap, +} + +enum Event { + SubmitExtrinsic(Bytes), +} + +struct Chain { + url: String, + client: WsRawClient, + sender: mpsc::Sender, + receiver: mpsc::Receiver, + genesis_hash: Hash, + state: ChainState, +} + +async fn init_rpc_connection(url: &RPCUrlParam) -> Result { + let url_str = url.to_string(); + log::debug!("Connecting to {}", url_str); + + // Skip the leading "ws://" and trailing "/". + let url_without_scheme = &url_str[5..(url_str.len() - 1)]; + let mut client = ws_raw_client(url_without_scheme) + .await + .map_err(|err| Error::WsConnectionError(err.to_string()))?; + + let genesis_hash = rpc::genesis_block_hash(&mut client) + .await + .map_err(|e| Error::RPCError(e.to_string()))? + .ok_or_else(|| Error::InvalidChainState(format!( + "chain with RPC URL {} is missing a genesis block hash", + url_str, + )))?; + + let latest_finalized_hash = SubstrateRPC::chain_finalized_head(&mut client) + .await + .map_err(|e| Error::RPCError(e.to_string()))?; + let latest_finalized_header = SubstrateRPC::chain_header( + &mut client, + Some(latest_finalized_hash) + ) + .await + .map_err(|e| Error::RPCError(e.to_string()))? + .ok_or_else(|| Error::InvalidChainState(format!( + "chain {} is missing header for finalized block hash {}", + genesis_hash, latest_finalized_hash + )))?; + + let (sender, receiver) = mpsc::channel(0); + + Ok(Chain { + url: url_str, + client, + sender, + receiver, + genesis_hash, + state: ChainState { + current_finalized_head: latest_finalized_header, + bridges: HashMap::new(), + } + }) +} + +/// Returns IDs of the bridged chains. +async fn read_bridges(chain: &mut Chain, chain_ids: &[Hash]) + -> Result, Error> +{ + // This should make an RPC call to read this information from the bridge pallet state. + // For now, just pretend every chain is bridged to every other chain. + // + // TODO: The correct thing. + Ok( + chain_ids + .iter() + .cloned() + .filter(|&chain_id| chain_id != chain.genesis_hash) + .collect() + ) +} + +pub async fn run_async( + params: Params, + exit: Box + Unpin + Send> +) -> Result<(), Error> +{ + let chains = init_chains(¶ms).await?; + + let (chain_tasks, exit_signals) = chains.into_iter() + .map(|(chain_id, chain_cell)| { + let chain = chain_cell.into_inner(); + let (task_exit_signal, task_exit_receiver) = oneshot::channel(); + let task_exit = Box::new(task_exit_receiver.map(|result| { + result.expect("task_exit_signal is not dropped before send() is called") + })); + let chain_task = async_std::task::spawn(async move { + if let Err(err) = chain_task(chain_id, chain, task_exit).await { + log::error!("Error in task for chain {}: {}", chain_id, err); + } + }); + (chain_task, task_exit_signal) + }) + .unzip::<_, _, Vec<_>, Vec<_>>(); + + async_std::task::spawn(async move { + exit.await; + for exit_signal in exit_signals { + let _ = exit_signal.send(()); + } + }); + + future::join_all(chain_tasks).await; + Ok(()) +} + +fn initial_next_events<'a>(chains: &'a HashMap>) + -> Vec> + 'a>>> +{ + chains.values() + .map(|chain_cell| async move { + let mut chain = chain_cell.borrow_mut(); + let event = chain.client.next_event() + .await + .map_err(|err| Error::RPCError(err.to_string()))?; + Ok((chain.genesis_hash, event)) + }) + .map(|fut| Box::pin(fut) as Pin>>) + .collect() +} + +async fn next_event<'a>( + next_events: Vec> + 'a>>>, + chains: &'a HashMap>, +) + -> ( + Result<(Hash, RawClientEvent), Error>, + Vec> +'a>>> + ) +{ + let (result, _, mut rest) = future::select_all(next_events).await; + + match result { + Ok((chain_id, _)) => { + let fut = async move { + let chain_cell = chains.get(&chain_id) + .expect("chain must be in the map as a function precondition; qed"); + let mut chain = chain_cell.borrow_mut(); + let event = chain.client.next_event() + .await + .map_err(|err| Error::RPCError(err.to_string()))?; + Ok((chain_id, event)) + }; + rest.push(Box::pin(fut)); + } + Err(ref err) => log::warn!("error in RPC connection with a chain: {}", err), + } + + (result, rest) +} + +async fn init_chains(params: &Params) -> Result>, Error> { + let chains = future::join_all(params.rpc_urls.iter().map(init_rpc_connection)) + .await + .into_iter() + .map(|result| result.map(|chain| (chain.genesis_hash, RefCell::new(chain)))) + .collect::, _>>()?; + + // TODO: Remove when read_bridges is implemented correctly. + let chain_ids = chains.keys() + .cloned() + .collect::>(); + // let chain_ids_slice = chain_ids.as_slice(); + + for (&chain_id, chain_cell) in chains.iter() { + let mut chain = chain_cell.borrow_mut(); + for bridged_chain_id in read_bridges(&mut chain, &chain_ids).await? { + if chain_id == bridged_chain_id { + log::warn!("chain {} has a bridge to itself", chain_id); + continue; + } + + if let Some(bridged_chain_cell) = chains.get(&bridged_chain_id) { + let bridged_chain = bridged_chain_cell.borrow_mut(); + + // TODO: Get this from RPC to runtime API. + let genesis_head = SubstrateRPC::chain_header(&mut chain.client, chain_id) + .await + .map_err(|e| Error::RPCError(e.to_string()))? + .ok_or_else(|| Error::InvalidChainState(format!( + "chain {} is missing a genesis block header", chain_id + )))?; + + let channel = chain.sender.clone(); + chain.state.bridges.insert(bridged_chain_id, BridgeState { + channel, + locally_finalized_head_on_bridged_chain: genesis_head, + }); + + // The conditional ensures that we don't log twice per pair of chains. + if chain_id.as_ref() < bridged_chain_id.as_ref() { + log::info!("initialized bridge between {} and {}", chain_id, bridged_chain_id); + } + } + } + } + + Ok(chains) +} + +async fn setup_subscriptions(chain: &mut Chain) + -> Result<(RawClientRequestId, RawClientRequestId), RawClientError> +{ + let new_heads_subscription_id = chain.client + .start_subscription( + "chain_subscribeNewHeads", + jsonrpsee::core::common::Params::None, + ) + .await + .map_err(RawClientError::Inner)?; + + let finalized_heads_subscription_id = chain.client + .start_subscription( + "chain_subscribeFinalizedHeads", + jsonrpsee::core::common::Params::None, + ) + .await + .map_err(RawClientError::Inner)?; + + let new_heads_subscription = + chain.client.subscription_by_id(new_heads_subscription_id) + .expect("subscription_id was returned from start_subscription above; qed"); + let new_heads_subscription = match new_heads_subscription { + RawClientSubscription::Active(_) => {} + RawClientSubscription::Pending(subscription) => { + subscription.wait().await?; + } + }; + + let finalized_heads_subscription = + chain.client.subscription_by_id(finalized_heads_subscription_id) + .expect("subscription_id was returned from start_subscription above; qed"); + let finalized_heads_subscription = match finalized_heads_subscription { + RawClientSubscription::Active(subscription) => {} + RawClientSubscription::Pending(subscription) => { + subscription.wait().await?; + } + }; + + Ok((new_heads_subscription_id, finalized_heads_subscription_id)) +} + +async fn handle_rpc_event( + chain_id: ChainId, + chain: &mut Chain, + event: RawClientEvent, + new_heads_subscription_id: RawClientRequestId, + finalized_heads_subscription_id: RawClientRequestId, +) -> Result<(), Error> +{ + match event { + RawClientEvent::SubscriptionNotif { request_id, result } => + if request_id == new_heads_subscription_id { + let header: Header = serde_json::from_value(result) + .map_err(Error::SerializationError)?; + log::info!("Received new head {:?} on chain {}", header, chain_id); + } else if request_id == finalized_heads_subscription_id { + let header: Header = serde_json::from_value(result) + .map_err(Error::SerializationError)?; + log::info!("Received finalized head {:?} on chain {}", header, chain_id); + + // let old_finalized_head = chain_state.current_finalized_head; + chain.state.current_finalized_head = header; + for (bridged_chain_id, bridged_chain) in chain.state.bridges.iter_mut() { + if bridged_chain.locally_finalized_head_on_bridged_chain.number < + chain.state.current_finalized_head.number { + // Craft and submit an extrinsic over RPC + log::info!("Sending command to submit extrinsic to chain {}", chain_id); + let mut send_event = bridged_chain.channel + .send(Event::SubmitExtrinsic(Bytes(Vec::new()))) + .fuse(); + + // Continue processing events from other chain tasks while waiting to send + // event to other chain task in order to prevent deadlocks. + loop { + select! { + result = send_event => { + result.map_err(Error::ChannelError)?; + break; + } + event = chain.receiver.next().fuse() => { + let event = event + .expect("stream will never close as the chain has an mpsc Sender"); + handle_bridge_event(chain_id, &mut chain.client, event) + .await?; + } + // TODO: exit + } + } + } + } + } else { + return Err(Error::RPCError(format!( + "unexpected subscription response with request ID {:?}", request_id + ))); + }, + _ => return Err(Error::RPCError(format!( + "unexpected RPC event from chain {}: {:?}", chain_id, event + ))), + } + Ok(()) +} + +// Let's say this never sends over a channel (ie. cannot block on another task). +async fn handle_bridge_event( + chain_id: ChainId, + rpc_client: &mut WsRawClient, + event: Event, +) -> Result<(), Error> +{ + match event { + Event::SubmitExtrinsic(data) => { + log::info!("Submitting extrinsic to chain {}", chain_id); + if let Err(err) = SubstrateRPC::author_submit_extrinsic(rpc_client, data).await { + log::error!("failed to submit extrinsic: {}", err); + } + } + } + Ok(()) +} + +async fn chain_task( + chain_id: ChainId, + mut chain: Chain, + exit: impl Future + Unpin + Send +) -> Result<(), Error> +{ + let (new_heads_subscription_id, finalized_heads_subscription_id) = + setup_subscriptions(&mut chain) + .await + .map_err(|e| Error::RPCError(e.to_string()))?; + + let mut exit = exit.fuse(); + loop { + select! { + result = chain.client.next_event().fuse() => { + let event = result.map_err(|e| Error::RPCError(e.to_string()))?; + handle_rpc_event( + chain_id, + &mut chain, + event, + new_heads_subscription_id, + finalized_heads_subscription_id, + ).await?; + } + event = chain.receiver.next().fuse() => { + let event = event + .expect("stream will never close as the chain has an mpsc Sender"); + handle_bridge_event(chain_id, &mut chain.client, event) + .await?; + } + _ = exit => { + log::debug!("Received exit signal, shutting down task for chain {}", chain_id); + break; + } + } + } + Ok(()) +} diff --git a/relays/substrate/src/error.rs b/relays/substrate/src/error.rs new file mode 100644 index 0000000000000..a612c84707d6f --- /dev/null +++ b/relays/substrate/src/error.rs @@ -0,0 +1,31 @@ +use futures::channel::mpsc; + +#[derive(Debug, derive_more::Display)] +pub enum Error { + #[display(fmt = "invalid RPC URL: {}", _0)] + UrlError(String), + #[display(fmt = "RPC response indicates invalid chain state: {}", _0)] + InvalidChainState(String), + #[display(fmt = "could not make RPC call: {}", _0)] + RPCError(String), + #[display(fmt = "could not connect to RPC URL: {}", _0)] + WsConnectionError(String), + #[display(fmt = "unexpected client event from RPC URL {}: {:?}", _0, _1)] + UnexpectedClientEvent(String, String), + #[display(fmt = "serialization error: {}", _0)] + SerializationError(serde_json::error::Error), + #[display(fmt = "invalid event received from bridged chain: {}", _0)] + InvalidBridgeEvent(String), + #[display(fmt = "error sending over MPSC channel: {}", _0)] + ChannelError(mpsc::SendError), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::SerializationError(err) => Some(err), + Error::ChannelError(err) => Some(err), + _ => None, + } + } +} diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs new file mode 100644 index 0000000000000..bfa183cb2e509 --- /dev/null +++ b/relays/substrate/src/main.rs @@ -0,0 +1,80 @@ +mod bridge; +mod error; +mod params; +mod rpc; + +use bridge::run_async; +use params::{Params, RPCUrlParam}; + +use clap::{App, Arg, value_t, values_t}; +use futures::{prelude::*, channel}; +use std::cell::Cell; +use std::process; + +fn main() { + let params = parse_args(); + env_logger::init(); + let exit = setup_exit_handler(); + + let result = async_std::task::block_on(async move { + run_async(params, exit).await + }); + if let Err(err) = result { + log::error!("{}", err); + process::exit(1); + } +} + +fn parse_args() -> Params { + let matches = App::new("substrate-bridge") + .version("1.0") + .author("Parity Technologies") + .about("Bridges Substrates, duh") + .arg( + Arg::with_name("base-path") + .long("base-path") + .value_name("DIRECTORY") + .required(true) + .help("Sets the base path") + .takes_value(true), + ) + .arg( + Arg::with_name("rpc-url") + .long("rpc-url") + .value_name("HOST[:PORT]") + .help("The URL of a bridged Substrate node") + .takes_value(true) + .multiple(true) + ) + .get_matches(); + + let base_path = value_t!(matches, "base-path", String) + .unwrap_or_else(|e| e.exit()); + let rpc_urls = values_t!(matches, "rpc-url", RPCUrlParam) + .unwrap_or_else(|e| e.exit()); + + Params { + base_path, + rpc_urls, + } +} + +fn setup_exit_handler() -> Box + Unpin + Send> { + let (exit_sender, exit_receiver) = channel::oneshot::channel(); + let exit_sender = Cell::new(Some(exit_sender)); + + ctrlc::set_handler(move || { + if let Some(exit_sender) = exit_sender.take() { + if let Err(()) = exit_sender.send(()) { + log::warn!("failed to send exit signal"); + } + } + }) + .expect("must be able to set Ctrl-C handler"); + + Box::new(exit_receiver.map(|result| { + result.expect( + "exit_sender cannot be dropped as it is moved into a globally-referenced closure" + ) + })) +} diff --git a/relays/substrate/src/params.rs b/relays/substrate/src/params.rs new file mode 100644 index 0000000000000..019581eb8c4bf --- /dev/null +++ b/relays/substrate/src/params.rs @@ -0,0 +1,75 @@ +use crate::error::Error; + +use url::Url; +use std::str::FromStr; + +const DEFAULT_WS_PORT: u16 = 9944; + +#[derive(Debug, Clone)] +pub struct Params { + pub base_path: String, + pub rpc_urls: Vec, +} + +#[derive(Debug, Clone)] +pub struct RPCUrlParam { + url: Url, +} + +impl ToString for RPCUrlParam { + fn to_string(&self) -> String { + self.url.to_string() + } +} + +impl FromStr for RPCUrlParam { + type Err = Error; + + fn from_str(url_str: &str) -> Result { + let mut url = Url::parse(url_str) + .map_err(|e| Error::UrlError(format!("could not parse {}: {}", url_str, e)))?; + + if url.scheme() != "ws" { + return Err(Error::UrlError(format!("must have scheme ws, found {}", url.scheme()))); + } + + if url.port().is_none() { + url.set_port(Some(DEFAULT_WS_PORT)) + .expect("the scheme is checked above to be ws; qed"); + } + + if url.path() != "/" { + return Err(Error::UrlError(format!("cannot have a path, found {}", url.path()))); + } + if let Some(query) = url.query() { + return Err(Error::UrlError(format!("cannot have a query, found {}", query))); + } + if let Some(fragment) = url.fragment() { + return Err(Error::UrlError(format!("cannot have a fragment, found {}", fragment))); + } + + Ok(RPCUrlParam { url }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rpc_url_from_str() { + assert_eq!( + RPCUrlParam::from_str("ws://127.0.0.1").unwrap().to_string(), + "ws://127.0.0.1:9944/" + ); + assert_eq!( + RPCUrlParam::from_str("ws://127.0.0.1/").unwrap().to_string(), + "ws://127.0.0.1:9944/" + ); + assert_eq!( + RPCUrlParam::from_str("ws://127.0.0.1:4499").unwrap().to_string(), + "ws://127.0.0.1:4499/" + ); + assert!(RPCUrlParam::from_str("http://127.0.0.1").is_err()); + } +} diff --git a/relays/substrate/src/rpc.rs b/relays/substrate/src/rpc.rs new file mode 100644 index 0000000000000..575419e3c5f0e --- /dev/null +++ b/relays/substrate/src/rpc.rs @@ -0,0 +1,29 @@ +use jsonrpsee::core::client::{RawClient, RawClientError, TransportClient}; +use node_primitives::{BlockNumber, Hash, Header}; +use sp_core::Bytes; +use sp_rpc::number::NumberOrHex; + +jsonrpsee::rpc_api! { + pub SubstrateRPC { + #[rpc(method = "author_submitExtrinsic", positional_params)] + fn author_submit_extrinsic(extrinsic: Bytes) -> Hash; + + #[rpc(method = "chain_getFinalizedHead")] + fn chain_finalized_head() -> Hash; + + #[rpc(method = "chain_getBlockHash", positional_params)] + fn chain_block_hash(id: Option>) -> Option; + + #[rpc(method = "chain_getHeader", positional_params)] + fn chain_header(hash: Option) -> Option
; + + #[rpc(positional_params)] + fn state_call(name: String, bytes: Bytes, hash: Option) -> Bytes; + } +} + +pub async fn genesis_block_hash(client: &mut RawClient) + -> Result, RawClientError> +{ + SubstrateRPC::chain_block_hash(client, Some(NumberOrHex::Number(0))).await +} From 5fb46baf4cb1814475e81f1bb46e0e73fc12f223 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 4 Mar 2020 04:44:21 -0500 Subject: [PATCH 0010/1210] Add a Node (#22) * Copy node-template over from Substrate repo Got the template at rev=6e6d06c33911 * Use dependencies from crates.io + stop renaming on import * Remove template pallet * Stop using crates.io dependencies Instead they're going to be pinned at v2.0.0-alpha.2 at commit `2afecf81ee19b8a6edb364b419190ea47c4a4a31` until something stable comes along. * Remove LICENSE * Change references of `node-template` to `bridge-node` * Remove README * Fix some missed node-template references * Add WASM toolchain to CI * Be more specific about nightly version to use * Maybe don't tie to a specific nightly * Use composite accounts * Update to use lazy reaping * Only use Development chain config --- bin/node/node/Cargo.toml | 108 +++++++++ bin/node/node/build.rs | 9 + bin/node/node/src/chain_spec.rs | 113 +++++++++ bin/node/node/src/cli.rs | 11 + bin/node/node/src/command.rs | 49 ++++ bin/node/node/src/main.rs | 23 ++ bin/node/node/src/service.rs | 225 ++++++++++++++++++ bin/node/runtime/Cargo.toml | 187 +++++++++++++++ bin/node/runtime/build.rs | 10 + bin/node/runtime/src/lib.rs | 353 +++++++++++++++++++++++++++++ bin/node/scripts/init.sh | 12 + modules/ethereum/Cargo.toml | 25 +- modules/substrate/Cargo.toml | 49 ++-- modules/substrate/src/lib.rs | 2 +- primitives/ethereum-poa/Cargo.toml | 10 +- 15 files changed, 1150 insertions(+), 36 deletions(-) create mode 100644 bin/node/node/Cargo.toml create mode 100644 bin/node/node/build.rs create mode 100644 bin/node/node/src/chain_spec.rs create mode 100644 bin/node/node/src/cli.rs create mode 100644 bin/node/node/src/command.rs create mode 100644 bin/node/node/src/main.rs create mode 100644 bin/node/node/src/service.rs create mode 100644 bin/node/runtime/Cargo.toml create mode 100644 bin/node/runtime/build.rs create mode 100644 bin/node/runtime/src/lib.rs create mode 100755 bin/node/scripts/init.sh diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml new file mode 100644 index 0000000000000..4bd5972c3465b --- /dev/null +++ b/bin/node/node/Cargo.toml @@ -0,0 +1,108 @@ +[package] +name = "bridge-node" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" + +[[bin]] +name = "bridge-node" + +[dependencies] +futures = "0.3.1" +log = "0.4.8" +structopt = "0.3.8" +bridge-node-runtime = { version = "0.1.0", path = "../runtime" } + +[dependencies.sc-cli] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-core] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-executor] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-service] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-inherents] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-transaction-pool] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-transaction-pool] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-network] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-consensus-aura] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-consensus-aura] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-consensus] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.grandpa] +package = "sc-finality-grandpa" +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.grandpa-primitives] +package = "sp-finality-grandpa" +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-client] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-runtime] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-basic-authorship] +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[build-dependencies] +vergen = "3.0.4" + +[build-dependencies.build-script-utils] +package = "substrate-build-script-utils" +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" diff --git a/bin/node/node/build.rs b/bin/node/node/build.rs new file mode 100644 index 0000000000000..222cbb409285b --- /dev/null +++ b/bin/node/node/build.rs @@ -0,0 +1,9 @@ +use vergen::{ConstantsFlags, generate_cargo_keys}; + +const ERROR_MSG: &str = "Failed to generate metadata files"; + +fn main() { + generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); + + build_script_utils::rerun_if_git_head_changed(); +} diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs new file mode 100644 index 0000000000000..5693dc21d8a7f --- /dev/null +++ b/bin/node/node/src/chain_spec.rs @@ -0,0 +1,113 @@ +use sp_core::{Pair, Public, sr25519}; +use bridge_node_runtime::{ + AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, + SudoConfig, SystemConfig, WASM_BINARY, Signature +}; +use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; +use grandpa_primitives::{AuthorityId as GrandpaId}; +use sc_service; +use sp_runtime::traits::{Verify, IdentifyAccount}; + +/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. +pub type ChainSpec = sc_service::ChainSpec; + +/// The chain specification option. This is expected to come in from the CLI and +/// is little more than one of a number of alternatives which can easily be converted +/// from a string (`--chain=...`) into a `ChainSpec`. +#[derive(Clone, Debug)] +pub enum Alternative { + /// Whatever the current runtime is, with just Alice as an auth. + Development, +} + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +type AccountPublic = ::Signer; + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId where + AccountPublic: From<::Public> +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate an authority key for Aura +pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { + ( + get_from_seed::(s), + get_from_seed::(s), + ) +} + +impl Alternative { + /// Get an actual chain config from one of the alternatives. + pub(crate) fn load(self) -> Result { + Ok(match self { + Alternative::Development => ChainSpec::from_genesis( + "Development", + "dev", + || testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + ], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ), + vec![], + None, + None, + None, + None + ), + }) + } + + pub(crate) fn from(s: &str) -> Option { + match s { + "" | "dev" => Some(Alternative::Development), + _ => None, + } + } +} + +fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool) -> GenesisConfig { + GenesisConfig { + frame_system: Some(SystemConfig { + code: WASM_BINARY.to_vec(), + changes_trie_config: Default::default(), + }), + pallet_balances: Some(BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), + }), + pallet_aura: Some(AuraConfig { + authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + }), + pallet_grandpa: Some(GrandpaConfig { + authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), + }), + pallet_sudo: Some(SudoConfig { + key: root_key, + }), + } +} + +pub fn load_spec(id: &str) -> Result, String> { + Ok(match Alternative::from(id) { + Some(spec) => Some(spec.load()?), + None => None, + }) +} diff --git a/bin/node/node/src/cli.rs b/bin/node/node/src/cli.rs new file mode 100644 index 0000000000000..0091ef7d75912 --- /dev/null +++ b/bin/node/node/src/cli.rs @@ -0,0 +1,11 @@ +use sc_cli::{RunCmd, Subcommand}; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +pub struct Cli { + #[structopt(subcommand)] + pub subcommand: Option, + + #[structopt(flatten)] + pub run: RunCmd, +} diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs new file mode 100644 index 0000000000000..0f4c301dbff5b --- /dev/null +++ b/bin/node/node/src/command.rs @@ -0,0 +1,49 @@ +// Copyright 2017-2020 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 . + +use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; +use sc_cli::VersionInfo; +use crate::service; +use crate::chain_spec; +use crate::cli::Cli; + +/// Parse and run command line arguments +pub fn run(version: VersionInfo) -> sc_cli::Result<()> { + let opt = sc_cli::from_args::(&version); + + let mut config = sc_service::Configuration::from_version(&version); + + match opt.subcommand { + Some(subcommand) => { + subcommand.init(&version)?; + subcommand.update_config(&mut config, chain_spec::load_spec, &version)?; + subcommand.run( + config, + |config: _| Ok(new_full_start!(config).0), + ) + }, + None => { + opt.run.init(&version)?; + opt.run.update_config(&mut config, chain_spec::load_spec, &version)?; + opt.run.run( + config, + service::new_light, + service::new_full, + &version, + ) + }, + } +} diff --git a/bin/node/node/src/main.rs b/bin/node/node/src/main.rs new file mode 100644 index 0000000000000..7e497cfdfd8fd --- /dev/null +++ b/bin/node/node/src/main.rs @@ -0,0 +1,23 @@ +//! Substrate Node Template CLI library. +#![warn(missing_docs)] + +mod chain_spec; +#[macro_use] +mod service; +mod cli; +mod command; + +fn main() -> sc_cli::Result<()> { + let version = sc_cli::VersionInfo { + name: "Bridge Node", + commit: env!("VERGEN_SHA_SHORT"), + version: env!("CARGO_PKG_VERSION"), + executable_name: "bridge-node", + author: "Parity Technologies", + description: "Bridge Node", + support_url: "https://github.com/paritytech/parity-bridges-common/", + copyright_start_year: 2017, + }; + + command::run(version) +} diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs new file mode 100644 index 0000000000000..9c860e67ca631 --- /dev/null +++ b/bin/node/node/src/service.rs @@ -0,0 +1,225 @@ +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +use std::sync::Arc; +use std::time::Duration; +use sc_client::LongestChain; +use bridge_node_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; +use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; +use sp_inherents::InherentDataProviders; +use sc_executor::native_executor_instance; +pub use sc_executor::NativeExecutor; +use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; + +// Our native executor instance. +native_executor_instance!( + pub Executor, + bridge_node_runtime::api::dispatch, + bridge_node_runtime::native_version, +); + +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +macro_rules! new_full_start { + ($config:expr) => {{ + let mut import_setup = None; + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + + let builder = sc_service::ServiceBuilder::new_full::< + bridge_node_runtime::opaque::Block, bridge_node_runtime::RuntimeApi, crate::service::Executor + >($config)? + .with_select_chain(|_config, backend| { + Ok(sc_client::LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client, _fetcher| { + let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); + Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api))) + })? + .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + let select_chain = select_chain.take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + + let (grandpa_block_import, grandpa_link) = + grandpa::block_import(client.clone(), &*client, select_chain)?; + + let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( + grandpa_block_import.clone(), client.clone(), + ); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client, + inherent_data_providers.clone(), + )?; + + import_setup = Some((grandpa_block_import, grandpa_link)); + + Ok(import_queue) + })?; + + (builder, import_setup, inherent_data_providers) + }} +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) + -> Result +{ + let is_authority = config.roles.is_authority(); + let force_authoring = config.force_authoring; + let name = config.name.clone(); + let disable_grandpa = config.disable_grandpa; + + // sentry nodes announce themselves as authorities to the network + // and should run the same protocols authorities do, but it should + // never actively participate in any consensus process. + let participates_in_consensus = is_authority && !config.sentry_mode; + + let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); + + let (block_import, grandpa_link) = + import_setup.take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + + let service = builder + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .build()?; + + if participates_in_consensus { + let proposer = sc_basic_authorship::ProposerFactory { + client: service.client(), + transaction_pool: service.transaction_pool(), + }; + + let client = service.client(); + let select_chain = service.select_chain() + .ok_or(ServiceError::SelectChainRequired)?; + + let can_author_with = + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + + let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( + sc_consensus_aura::slot_duration(&*client)?, + client, + select_chain, + block_import, + proposer, + service.network(), + inherent_data_providers.clone(), + force_authoring, + service.keystore(), + can_author_with, + )?; + + // the AURA authoring task is considered essential, i.e. if it + // fails we take down the service with it. + service.spawn_essential_task("aura", aura); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if participates_in_consensus { + Some(service.keystore()) + } else { + None + }; + + let grandpa_config = grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: false, + keystore, + is_authority, + }; + + let enable_grandpa = !disable_grandpa; + if enable_grandpa { + // start the full GRANDPA voter + // NOTE: non-authorities could run the GRANDPA observer protocol, but at + // this point the full voter should provide better guarantees of block + // and vote data availability than the observer. The observer has not + // been tested extensively yet and having most nodes in a network run it + // could lead to finality stalls. + let grandpa_config = grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network: service.network(), + inherent_data_providers: inherent_data_providers.clone(), + on_exit: service.on_exit(), + telemetry_on_connect: Some(service.telemetry_on_connect_stream()), + voting_rule: grandpa::VotingRulesBuilder::default().build(), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + service.spawn_essential_task( + "grandpa-voter", + grandpa::run_grandpa_voter(grandpa_config)? + ); + } else { + grandpa::setup_disabled_grandpa( + service.client(), + &inherent_data_providers, + service.network(), + )?; + } + + Ok(service) +} + +/// Builds a new service for a light client. +pub fn new_light(config: Configuration) + -> Result +{ + let inherent_data_providers = InherentDataProviders::new(); + + ServiceBuilder::new_light::(config)? + .with_select_chain(|_config, backend| { + Ok(LongestChain::new(backend.clone())) + })? + .with_transaction_pool(|config, client, fetcher| { + let fetcher = fetcher + .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + + let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); + let pool = sc_transaction_pool::BasicPool::with_revalidation_type( + config, Arc::new(pool_api), sc_transaction_pool::RevalidationType::Light, + ); + Ok(pool) + })? + .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| { + let fetch_checker = fetcher + .map(|fetcher| fetcher.checker().clone()) + .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; + let grandpa_block_import = grandpa::light_block_import( + client.clone(), backend, &*client.clone(), Arc::new(fetch_checker), + )?; + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = + finality_proof_import.create_finality_proof_request_builder(); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( + sc_consensus_aura::slot_duration(&*client)?, + grandpa_block_import, + None, + Some(Box::new(finality_proof_import)), + client, + inherent_data_providers.clone(), + )?; + + Ok((import_queue, finality_proof_request_builder)) + })? + .with_finality_proof_provider(|client, backend| + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) + )? + .build() +} diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml new file mode 100644 index 0000000000000..4b59c813b5653 --- /dev/null +++ b/bin/node/runtime/Cargo.toml @@ -0,0 +1,187 @@ +[package] +name = "bridge-node-runtime" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" + +[dependencies.codec] +package = "parity-scale-codec" +version = "1.0.0" +default-features = false +features = ["derive"] + +[dependencies.serde] +version = "1.0.101" +optional = true +features = ["derive"] + +# Substrate Dependencies +[dependencies.pallet-aura] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-balances] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-support] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-grandpa] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-randomness-collective-flip] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-sudo] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-timestamp] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-transaction-payment] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-executive] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +# Substrate Primitives +[dependencies.sp-api] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-block-builder] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-consensus-aura] +version = "0.8.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-core] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-inherents] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-io] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-offchain] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-session] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-std] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-transaction-pool] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-version] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[build-dependencies.wasm-builder-runner] +version = "1.0.5" +package = "substrate-wasm-builder-runner" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[features] +default = ["std"] +std = [ + "pallet-aura/std", + "pallet-balances/std", + "codec/std", + "frame-executive/std", + "frame-support/std", + "frame-system/std", + "pallet-grandpa/std", + "pallet-randomness-collective-flip/std", + "serde", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment/std", +] diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs new file mode 100644 index 0000000000000..39f7f56feb0b1 --- /dev/null +++ b/bin/node/runtime/build.rs @@ -0,0 +1,10 @@ +use wasm_builder_runner::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .with_wasm_builder_from_crates("1.0.9") + .export_heap_base() + .import_memory() + .build() +} diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs new file mode 100644 index 0000000000000..6036697b47ec5 --- /dev/null +++ b/bin/node/runtime/src/lib.rs @@ -0,0 +1,353 @@ +//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit="256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use sp_std::prelude::*; +use sp_core::OpaqueMetadata; +use sp_runtime::{ + ApplyExtrinsicResult, transaction_validity::TransactionValidity, generic, create_runtime_str, + impl_opaque_keys, MultiSignature, +}; +use sp_runtime::traits::{ + BlakeTwo256, Block as BlockT, IdentityLookup, Verify, ConvertInto, IdentifyAccount +}; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use pallet_grandpa::AuthorityList as GrandpaAuthorityList; +use pallet_grandpa::fg_primitives; +use sp_version::RuntimeVersion; +#[cfg(feature = "std")] +use sp_version::NativeVersion; + +// A few exports that help ease life for downstream crates. +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use pallet_timestamp::Call as TimestampCall; +pub use pallet_balances::Call as BalancesCall; +pub use sp_runtime::{Permill, Perbill}; +pub use frame_support::{ + StorageValue, construct_runtime, parameter_types, + traits::Randomness, + weights::Weight, +}; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// The type for looking up accounts. We don't expect more than 4 billion of them, but you +/// never know... +pub type AccountIndex = u32; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Digest item type. +pub type DigestItem = generic::DigestItem; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; + + impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } + } +} + +/// This runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("bridge-node"), + impl_name: create_runtime_str!("bridge-node"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, +}; + +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// These time units are defined in number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const MaximumBlockWeight: Weight = 1_000_000; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; +} + +impl frame_system::Trait for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = IdentityLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Maximum weight of each block. + type MaximumBlockWeight = MaximumBlockWeight; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type MaximumBlockLength = MaximumBlockLength; + /// Portion of the block weight that is available to all normal transactions. + type AvailableBlockRatio = AvailableBlockRatio; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type ModuleToIndex = ModuleToIndex; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; +} + +impl pallet_aura::Trait for Runtime { + type AuthorityId = AuraId; +} + +impl pallet_grandpa::Trait for Runtime { + type Event = Event; +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Trait for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 500; +} + +impl pallet_balances::Trait for Runtime { + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 0; + pub const TransactionByteFee: Balance = 1; +} + +impl pallet_transaction_payment::Trait for Runtime { + type Currency = pallet_balances::Module; + type OnTransactionPayment = (); + type TransactionBaseFee = TransactionBaseFee; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = ConvertInto; + type FeeMultiplierUpdate = (); +} + +impl pallet_sudo::Trait for Runtime { + type Event = Event; + type Call = Call; +} + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Module, Call, Config, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, + Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, + Aura: pallet_aura::{Module, Config, Inherent(Timestamp)}, + Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, + Balances: pallet_balances::{Module, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Module, Storage}, + Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, + } +); + +/// The address format for describing accounts. +pub type Address = AccountId; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive, Runtime, AllModules>; + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn apply_trusted_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_trusted_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + + fn random_seed() -> ::Hash { + RandomnessCollectiveFlip::random_seed() + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { + Executive::validate_transaction(tx) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { + Aura::slot_duration() + } + + fn authorities() -> Vec { + Aura::authorities() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + opaque::SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, sp_core::crypto::KeyTypeId)>> { + opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + } +} diff --git a/bin/node/scripts/init.sh b/bin/node/scripts/init.sh new file mode 100755 index 0000000000000..1405a41ef333e --- /dev/null +++ b/bin/node/scripts/init.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e + +echo "*** Initializing WASM build environment" + +if [ -z $CI_PROJECT_NAME ] ; then + rustup update nightly + rustup update stable +fi + +rustup target add wasm32-unknown-unknown --toolchain nightly diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index ee4673e589481..2a750ffbf5f6a 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -12,29 +12,34 @@ primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum- # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies] diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index cd8787a76683e..069fed6783209 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -9,56 +9,63 @@ edition = "2018" [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } serde = { version = "1.0", optional = true } +hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" -[dependencies.hash-db] -version = "0.15.2" -default-features = false [dependencies.pallet-session] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0" -git = "https://github.com/paritytech/substrate.git" +version = "2.0.0-alpha.2" default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0" -git = "https://github.com/paritytech/substrate.git" +version = "0.8.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" [features] default = ["std"] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index ad27627f62cae..bcb7f7081bceb 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -249,7 +249,7 @@ mod tests { type ModuleToIndex = (); type AccountData = (); type OnNewAccount = (); - type OnReapAccount = (); + type OnKilledAccount = (); } impl Trait for Test {} diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 6b88c8901bfea..02d144ccb38ef 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -16,10 +16,12 @@ impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } rlp = { version = "0.4", default-features = false } -sp-std = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } -sp-runtime = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } -sp-api = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } -sp-io = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", default-features = false } + +sp-std = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } +sp-runtime = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } +sp-api = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } +sp-io = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } + hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } From a41bffe63249339445264440e2398c071931aea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 7 Mar 2020 04:05:48 +0100 Subject: [PATCH 0011/1210] Add license headers (#27) * Add the scripts. * Add license preamble. * Change existing license headers. --- bin/node/node/build.rs | 16 ++++++++ bin/node/node/src/chain_spec.rs | 16 ++++++++ bin/node/node/src/cli.rs | 16 ++++++++ bin/node/node/src/command.rs | 26 ++++++++++--- bin/node/node/src/main.rs | 18 ++++++++- bin/node/node/src/service.rs | 16 ++++++++ bin/node/runtime/build.rs | 16 ++++++++ bin/node/runtime/src/lib.rs | 16 ++++++++ .../bin/node/cli/src/chain_spec.rs | 28 +++++++++++--- .../bin/node/runtime/src/lib.rs | 26 ++++++++++--- .../bin/node/testing/src/genesis.rs | 24 ++++++++++-- .../primitives/core/src/hasher.rs | 26 ++++++++++--- .../primitives/core/src/lib.rs | 30 +++++++++++---- .../primitives/io/src/lib.rs | 38 +++++++++++++------ modules/ethereum/src/error.rs | 16 ++++++++ modules/ethereum/src/finality.rs | 16 ++++++++ modules/ethereum/src/import.rs | 16 ++++++++ modules/ethereum/src/lib.rs | 16 ++++++++ modules/ethereum/src/validators.rs | 16 ++++++++ modules/ethereum/src/verification.rs | 16 ++++++++ modules/substrate/src/lib.rs | 24 ++++++++++-- modules/substrate/src/storage_proof.rs | 26 ++++++++++--- primitives/ethereum-poa/src/lib.rs | 16 ++++++++ relays/ethereum/src/ethereum_client.rs | 16 ++++++++ relays/ethereum/src/ethereum_headers.rs | 16 ++++++++ relays/ethereum/src/ethereum_sync.rs | 16 ++++++++ relays/ethereum/src/ethereum_sync_loop.rs | 16 ++++++++ relays/ethereum/src/ethereum_types.rs | 16 ++++++++ relays/ethereum/src/main.rs | 16 ++++++++ relays/ethereum/src/substrate_client.rs | 16 ++++++++ relays/ethereum/src/substrate_types.rs | 16 ++++++++ relays/substrate/src/bridge.rs | 16 ++++++++ relays/substrate/src/error.rs | 16 ++++++++ relays/substrate/src/main.rs | 16 ++++++++ relays/substrate/src/params.rs | 16 ++++++++ relays/substrate/src/rpc.rs | 16 ++++++++ 36 files changed, 629 insertions(+), 53 deletions(-) diff --git a/bin/node/node/build.rs b/bin/node/node/build.rs index 222cbb409285b..02322263485cf 100644 --- a/bin/node/node/build.rs +++ b/bin/node/node/build.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use vergen::{ConstantsFlags, generate_cargo_keys}; const ERROR_MSG: &str = "Failed to generate metadata files"; diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 5693dc21d8a7f..a988b96c30108 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use sp_core::{Pair, Public, sr25519}; use bridge_node_runtime::{ AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, diff --git a/bin/node/node/src/cli.rs b/bin/node/node/src/cli.rs index 0091ef7d75912..9be42c8f44cc5 100644 --- a/bin/node/node/src/cli.rs +++ b/bin/node/node/src/cli.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use sc_cli::{RunCmd, Subcommand}; use structopt::StructOpt; diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs index 0f4c301dbff5b..c17ea03dd34f7 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/node/src/command.rs @@ -1,18 +1,34 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . + +// Copyright 2019-2020 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 . use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; use sc_cli::VersionInfo; diff --git a/bin/node/node/src/main.rs b/bin/node/node/src/main.rs index 7e497cfdfd8fd..3a5823d8d7432 100644 --- a/bin/node/node/src/main.rs +++ b/bin/node/node/src/main.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + //! Substrate Node Template CLI library. #![warn(missing_docs)] @@ -16,7 +32,7 @@ fn main() -> sc_cli::Result<()> { author: "Parity Technologies", description: "Bridge Node", support_url: "https://github.com/paritytech/parity-bridges-common/", - copyright_start_year: 2017, + copyright_start_year: 2019, }; command::run(version) diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 9c860e67ca631..f268a5dbbb4ea 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use std::sync::Arc; diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs index 39f7f56feb0b1..81d28a1e92371 100644 --- a/bin/node/runtime/build.rs +++ b/bin/node/runtime/build.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use wasm_builder_runner::WasmBuilder; fn main() { diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 6036697b47ec5..8b5c9876667c2 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + //! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs b/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs index 8a0af961578ac..bb3e566509710 100644 --- a/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs +++ b/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs @@ -1,20 +1,36 @@ +// Copyright 2019-2020 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 . + // Copyright 2018-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . -//! Substrate chain configurations. +//! Parity Bridges Common chain configurations. use sc_chain_spec::ChainSpecExtension; use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519}; @@ -44,7 +60,7 @@ const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; /// Node `ChainSpec` extensions. /// -/// Additional parameters for some Substrate core modules, +/// Additional parameters for some Parity Bridges Common core modules, /// customizable from the chain spec. #[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] #[serde(rename_all = "camelCase")] diff --git a/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs b/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs index 21cfc6d8bc501..d050953a4c53e 100644 --- a/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs +++ b/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs @@ -1,20 +1,36 @@ +// Copyright 2019-2020 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 . + // Copyright 2018-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . -//! The Substrate runtime. This can be compiled with ``#[no_std]`, ready for Wasm. +//! The Parity Bridges Common runtime. This can be compiled with ``#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. diff --git a/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs b/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs index 85dddc808e7cf..cbb1fa0f18ff8 100644 --- a/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs +++ b/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs @@ -1,18 +1,34 @@ // Copyright 2019-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . + +// Copyright 2019-2020 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 . //! Genesis Configuration. diff --git a/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs b/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs index bb0bd665bc7ee..0751f1e824ad7 100644 --- a/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs +++ b/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs @@ -1,20 +1,36 @@ +// Copyright 2019-2020 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 . + // Copyright 2018-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . -//! Substrate Blake2b Hasher implementation +//! Parity Bridges Common Blake2b Hasher implementation use hash_db::Hasher; use hash256_std_hasher::Hash256StdHasher; diff --git a/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs b/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs index 0092f892b79ba..36368f87993ad 100644 --- a/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs +++ b/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs @@ -1,20 +1,36 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . -//! Shareable Substrate types. +// Copyright 2019-2020 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 . + +//! Shareable Parity Bridges Common types. #![warn(missing_docs)] @@ -291,7 +307,7 @@ impl From for log::Level { /// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`. /// -/// When Substrate calls into Wasm it expects a fixed signature for functions exported +/// When Parity Bridges Common calls into Wasm it expects a fixed signature for functions exported /// from the Wasm blob. The return value of this signature is always a `u64`. /// This `u64` stores the pointer to the encoded return value and the length of this encoded value. /// The low `32bits` are reserved for the pointer, followed by `32bit` for the length. diff --git a/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs b/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs index 8a87028da6678..997ab73e58d63 100644 --- a/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs +++ b/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs @@ -1,20 +1,36 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . -//! This is part of the Substrate runtime. +// Copyright 2019-2020 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 . + +//! This is part of the Parity Bridges Common runtime. #![warn(missing_docs)] @@ -23,9 +39,9 @@ #![cfg_attr(not(feature = "std"), feature(core_intrinsics))] #![cfg_attr(feature = "std", - doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")] + doc = "Parity Bridges Common runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), - doc = "Substrate's runtime standard library as compiled without Rust's standard library.")] + doc = "Parity Bridges Common's runtime standard library as compiled without Rust's standard library.")] use sp_std::vec::Vec; @@ -838,7 +854,7 @@ pub trait Sandbox { } } -/// Allocator used by Substrate when executing the Wasm runtime. +/// Allocator used by Parity Bridges Common when executing the Wasm runtime. #[cfg(not(feature = "std"))] struct WasmAllocator; @@ -888,11 +904,11 @@ pub fn oom(_: core::alloc::Layout) -> ! { #[cfg(feature = "std")] pub type TestExternalities = sp_state_machine::TestExternalities; -/// The host functions Substrate provides for the Wasm runtime environment. +/// The host functions Parity Bridges Common provides for the Wasm runtime environment. /// /// All these host functions will be callable from inside the Wasm environment. #[cfg(feature = "std")] -pub type SubstrateHostFunctions = ( +pub type Parity Bridges CommonHostFunctions = ( storage::HostFunctions, misc::HostFunctions, offchain::HostFunctions, diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index f716a7e066185..7fe9b4f802b79 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 37e16d6ccd438..cfa4c77a397e2 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index c11146526491c..bf8d21ea02975 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 2288c205bdac6..f69dbe0592ed5 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 0860f807ffdd5..21f1f0b58b0da 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 09de275877cb6..ea9b37fa528d0 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index bcb7f7081bceb..3a0f9a0db557e 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -1,18 +1,34 @@ +// Copyright 2019-2020 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 . + // Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . //! # Bridge Module //! diff --git a/modules/substrate/src/storage_proof.rs b/modules/substrate/src/storage_proof.rs index 68f2c07a20e31..dfdc0c5787da8 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/modules/substrate/src/storage_proof.rs @@ -1,20 +1,36 @@ +// Copyright 2019-2020 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 . + // Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. +// This file is part of Parity Bridges Common. -// Substrate is free software: you can redistribute it and/or modify +// 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. -// Substrate is distributed in the hope that it will be useful, +// 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 Substrate. If not, see . +// along with Parity Bridges Common. If not, see . -//! Logic for checking Substrate storage proofs. +//! Logic for checking Parity Bridges Common storage proofs. use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 2cd5d8d2d6838..b6b392a2062b7 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index e04a915d46e27..08eaf2475340f 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/ethereum_headers.rs b/relays/ethereum/src/ethereum_headers.rs index 154f9256acb15..1a3c110ad3414 100644 --- a/relays/ethereum/src/ethereum_headers.rs +++ b/relays/ethereum/src/ethereum_headers.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/ethereum_sync.rs b/relays/ethereum/src/ethereum_sync.rs index 93ed761bd01ca..5819c5f0bb893 100644 --- a/relays/ethereum/src/ethereum_sync.rs +++ b/relays/ethereum/src/ethereum_sync.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 59fae12ad3330..1540edd78f445 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index c5aaaf0531785..cd61ac01b3712 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index de9546bfa6fdb..eee802a004cd8 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index f66395b1cd369..7260cb87a254b 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 8cf5d86cb1481..62b28e47358c1 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + // Copyright 2019 Parity Technologies (UK) Ltd. // This file is part of Parity-Bridge. diff --git a/relays/substrate/src/bridge.rs b/relays/substrate/src/bridge.rs index 7a733c5862e57..fb97299bfcbc8 100644 --- a/relays/substrate/src/bridge.rs +++ b/relays/substrate/src/bridge.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use crate::error::Error; use crate::rpc::{self, SubstrateRPC}; use crate::params::{RPCUrlParam, Params}; diff --git a/relays/substrate/src/error.rs b/relays/substrate/src/error.rs index a612c84707d6f..f1b18568b6b3e 100644 --- a/relays/substrate/src/error.rs +++ b/relays/substrate/src/error.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use futures::channel::mpsc; #[derive(Debug, derive_more::Display)] diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index bfa183cb2e509..7443c6bebc932 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + mod bridge; mod error; mod params; diff --git a/relays/substrate/src/params.rs b/relays/substrate/src/params.rs index 019581eb8c4bf..2b2e81321d411 100644 --- a/relays/substrate/src/params.rs +++ b/relays/substrate/src/params.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use crate::error::Error; use url::Url; diff --git a/relays/substrate/src/rpc.rs b/relays/substrate/src/rpc.rs index 575419e3c5f0e..d9376e66de974 100644 --- a/relays/substrate/src/rpc.rs +++ b/relays/substrate/src/rpc.rs @@ -1,3 +1,19 @@ +// Copyright 2019-2020 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 . + use jsonrpsee::core::client::{RawClient, RawClientError, TransportClient}; use node_primitives::{BlockNumber, Hash, Header}; use sp_core::Bytes; From e9aab284eedecd5af0af29011755a455eab7a33a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2020 18:36:04 +0100 Subject: [PATCH 0012/1210] Bump derive_more from 0.99.2 to 0.99.3 (#29) Bumps [derive_more](https://github.com/JelteF/derive_more) from 0.99.2 to 0.99.3. - [Release notes](https://github.com/JelteF/derive_more/releases) - [Changelog](https://github.com/JelteF/derive_more/blob/master/CHANGELOG.md) - [Commits](https://github.com/JelteF/derive_more/compare/v0.99.2...v0.99.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index d3382cedd4625..ed9af042453df 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" async-std = "1.0.1" clap = "2.3.3" ctrlc = "3.1.3" -derive_more = "0.99.1" +derive_more = "0.99.3" env_logger = "0.7.1" futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } From 2a15f765732d4860573f0f8f11c04711c5b7bdd0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2020 15:48:02 +0100 Subject: [PATCH 0013/1210] Bump ctrlc from 3.1.3 to 3.1.4 (#30) Bumps [ctrlc](https://github.com/Detegr/rust-ctrlc) from 3.1.3 to 3.1.4. - [Release notes](https://github.com/Detegr/rust-ctrlc/releases) - [Commits](https://github.com/Detegr/rust-ctrlc/commits/3.1.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index ed9af042453df..5daa9104ba6f9 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] async-std = "1.0.1" clap = "2.3.3" -ctrlc = "3.1.3" +ctrlc = "3.1.4" derive_more = "0.99.3" env_logger = "0.7.1" futures = "0.3.1" From 92ddac9c7e5aabbee456d1ad2dbdfd39fab78fa8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2020 10:01:07 +0100 Subject: [PATCH 0014/1210] Bump jsonrpsee from `de7cbf2` to `a0bea41` (#28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump jsonrpsee from `de7cbf2` to `a0bea41` Bumps [jsonrpsee](https://github.com/paritytech/jsonrpsee) from `de7cbf2` to `a0bea41`. - [Release notes](https://github.com/paritytech/jsonrpsee/releases) - [Commits](https://github.com/paritytech/jsonrpsee/compare/de7cbf2b7528802b6c1079de837db1d4f24561a6...a0bea41c4f37125fa742ec48b12e11cf55c592b5) Signed-off-by: dependabot-preview[bot] * Fix imports. * Update client code. Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Tomasz Drwięga --- relays/substrate/src/bridge.rs | 20 ++++++++++++-------- relays/substrate/src/rpc.rs | 5 ++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/relays/substrate/src/bridge.rs b/relays/substrate/src/bridge.rs index fb97299bfcbc8..044f4606d8917 100644 --- a/relays/substrate/src/bridge.rs +++ b/relays/substrate/src/bridge.rs @@ -20,8 +20,11 @@ use crate::params::{RPCUrlParam, Params}; use futures::{prelude::*, channel::{mpsc, oneshot}, future, select}; use jsonrpsee::{ - core::client::{RawClientError, RawClientEvent, RawClientRequestId, RawClientSubscription}, - ws::{WsRawClient, WsConnecError, ws_raw_client}, + raw::client::{RawClient, RawClientError, RawClientEvent, RawClientRequestId, RawClientSubscription}, + transport::{ + TransportClient, + ws::{WsTransportClient, WsConnecError}, + }, }; use node_primitives::{Hash, Header}; use std::cell::RefCell; @@ -47,7 +50,7 @@ enum Event { struct Chain { url: String, - client: WsRawClient, + client: RawClient, sender: mpsc::Sender, receiver: mpsc::Receiver, genesis_hash: Hash, @@ -60,10 +63,11 @@ async fn init_rpc_connection(url: &RPCUrlParam) -> Result { // Skip the leading "ws://" and trailing "/". let url_without_scheme = &url_str[5..(url_str.len() - 1)]; - let mut client = ws_raw_client(url_without_scheme) + let transport = WsTransportClient::new(url_without_scheme) .await .map_err(|err| Error::WsConnectionError(err.to_string()))?; + let mut client = RawClient::new(transport); let genesis_hash = rpc::genesis_block_hash(&mut client) .await .map_err(|e| Error::RPCError(e.to_string()))? @@ -252,7 +256,7 @@ async fn setup_subscriptions(chain: &mut Chain) let new_heads_subscription_id = chain.client .start_subscription( "chain_subscribeNewHeads", - jsonrpsee::core::common::Params::None, + jsonrpsee::common::Params::None, ) .await .map_err(RawClientError::Inner)?; @@ -260,7 +264,7 @@ async fn setup_subscriptions(chain: &mut Chain) let finalized_heads_subscription_id = chain.client .start_subscription( "chain_subscribeFinalizedHeads", - jsonrpsee::core::common::Params::None, + jsonrpsee::common::Params::None, ) .await .map_err(RawClientError::Inner)?; @@ -350,9 +354,9 @@ async fn handle_rpc_event( } // Let's say this never sends over a channel (ie. cannot block on another task). -async fn handle_bridge_event( +async fn handle_bridge_event( chain_id: ChainId, - rpc_client: &mut WsRawClient, + rpc_client: &mut RawClient, event: Event, ) -> Result<(), Error> { diff --git a/relays/substrate/src/rpc.rs b/relays/substrate/src/rpc.rs index d9376e66de974..38e751ce89a26 100644 --- a/relays/substrate/src/rpc.rs +++ b/relays/substrate/src/rpc.rs @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use jsonrpsee::core::client::{RawClient, RawClientError, TransportClient}; +use jsonrpsee::{ + raw::client::{RawClient, RawClientError}, + transport::TransportClient, +}; use node_primitives::{BlockNumber, Hash, Header}; use sp_core::Bytes; use sp_rpc::number::NumberOrHex; From a891cebc4bb871a7343aa6402e4687786d08b3db Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2020 10:19:59 +0100 Subject: [PATCH 0015/1210] Bump vergen from 3.0.4 to 3.1.0 (#32) Bumps [vergen](https://github.com/rustyhorde/vergen) from 3.0.4 to 3.1.0. - [Release notes](https://github.com/rustyhorde/vergen/releases) - [Commits](https://github.com/rustyhorde/vergen/commits/v3.1.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 4bd5972c3465b..91a13cb7718dd 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -99,7 +99,7 @@ rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate.git" [build-dependencies] -vergen = "3.0.4" +vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" From efddd114f4fa04b8aa4f2d585ae50c07342860d5 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 17 Mar 2020 07:47:21 -0400 Subject: [PATCH 0016/1210] Get Ethereum Relay to Compile (#21) * Update dependencies Upgrades Substrate based dependencies from v2.0.0 -> v2.0.0-alpha.1 and uses the `jsonrpsee`'s new feature flags. The actual code hasn't been updated though, so this won't compile. * Use `RawClient`s from `jsonrpsee` * Update to use jsonrpsee's new API * Hook up Ethereum Bridge Runtime, Relay, and Node Runtime * Bump `parity-crypto` from v0.4 to v0.6 Fixes error when trying to compile tests. This was caused by `parity-crypto` v0.4's use of `parity-secp256k1` over `secp256k1'. Using the Parity fork meant multiple version of the same underlying C library were being pulled in. `parity-crypto` v0.6 moved away from this, only relying on `secp256k1` thus fixing the issue. --- bin/node/node/Cargo.toml | 1 + bin/node/node/src/chain_spec.rs | 51 ++++++++++++++++++++++- bin/node/runtime/Cargo.toml | 12 ++++++ bin/node/runtime/src/lib.rs | 22 ++++++++++ modules/ethereum/Cargo.toml | 2 +- modules/substrate/Cargo.toml | 1 - primitives/ethereum-poa/Cargo.toml | 31 +++++++++++--- relays/ethereum/Cargo.toml | 54 ++++++++++++++++++++----- relays/ethereum/src/ethereum_client.rs | 17 +++++--- relays/ethereum/src/substrate_client.rs | 42 ++++++++++--------- relays/substrate/Cargo.toml | 18 +++++++-- 11 files changed, 203 insertions(+), 48 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 91a13cb7718dd..a0acdab18b9dc 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -15,6 +15,7 @@ futures = "0.3.1" log = "0.4.8" structopt = "0.3.8" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } +sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } [dependencies.sc-cli] version = "0.8.0-alpha.2" diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index a988b96c30108..6301e342ee868 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -16,8 +16,9 @@ use sp_core::{Pair, Public, sr25519}; use bridge_node_runtime::{ - AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, - SudoConfig, SystemConfig, WASM_BINARY, Signature + AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, + GenesisConfig, GrandpaConfig, SudoConfig, SystemConfig, + WASM_BINARY, Signature }; use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; use grandpa_primitives::{AuthorityId as GrandpaId}; @@ -112,6 +113,7 @@ fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, pallet_aura: Some(AuraConfig { authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), }), + pallet_bridge_eth_poa: load_kovan_config(), pallet_grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), }), @@ -127,3 +129,48 @@ pub fn load_spec(id: &str) -> Result, String> { None => None, }) } + +fn load_kovan_config() -> Option { + Some(BridgeEthPoAConfig { + initial_header: sp_bridge_eth_poa::Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), + uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), + extra_data: vec![], + state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), + receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 6000000.into(), + difficulty: 131072.into(), + seal: vec![ + vec![128].into(), + vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), + ], + }, + initial_difficulty: 0.into(), + initial_validators: vec![ + [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, + 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), + [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, + 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), + [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, + 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), + [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, + 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), + [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, + 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), + [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, + 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), + [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, + 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), + [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, + 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), + [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, + 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + ], + }) +} diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 4b59c813b5653..7e0b9392c240c 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -30,6 +30,11 @@ default-features = false rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate/" +[dependencies.pallet-bridge-eth-poa] +version = "0.1.0" +default-features = false +path = "../../../modules/ethereum" + [dependencies.frame-support] version = "2.0.0-alpha.2" default-features = false @@ -91,6 +96,11 @@ default-features = false rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate/" +[dependencies.sp-bridge-eth-poa] +version = "0.1.0" +default-features = false +path = "../../../primitives/ethereum-poa" + [dependencies.sp-consensus-aura] version = "0.8.0-alpha.2" default-features = false @@ -162,6 +172,7 @@ default = ["std"] std = [ "pallet-aura/std", "pallet-balances/std", + "pallet-bridge-eth-poa/std", "codec/std", "frame-executive/std", "frame-support/std", @@ -171,6 +182,7 @@ std = [ "serde", "sp-api/std", "sp-block-builder/std", + "sp-bridge-eth-poa/std", "sp-consensus-aura/std", "sp-core/std", "sp-inherents/std", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 8b5c9876667c2..d5b1c0dd143f0 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -52,6 +52,7 @@ pub use frame_support::{ traits::Randomness, weights::Weight, }; +pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; /// An index to a block. pub type BlockNumber = u32; @@ -186,6 +187,10 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } +impl pallet_bridge_eth_poa::Trait for Runtime { + type OnHeadersSubmitted = (); +} + impl pallet_grandpa::Trait for Runtime { type Event = Event; } @@ -248,6 +253,7 @@ construct_runtime!( Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, + BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage}, } ); @@ -270,6 +276,8 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment ); +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. @@ -327,6 +335,20 @@ impl_runtime_apis! { } } + impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { + fn best_block() -> (u64, sp_bridge_eth_poa::H256) { + BridgeEthPoA::best_block() + } + + fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { + BridgeEthPoA::is_import_requires_receipts(header) + } + + fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { + BridgeEthPoA::is_known_block(hash) + } + } + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { Executive::validate_transaction(tx) diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 2a750ffbf5f6a..3b752212ec9bf 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -45,7 +45,7 @@ git = "https://github.com/paritytech/substrate/" [dev-dependencies] # TODO: Stop renaming this on import primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", features = ["std", "test-helpers"] } -parity-crypto = { version = "0.4", features = ["publickey"] } +parity-crypto = { version = "0.6", features = ["publickey"] } [features] default = ["std"] diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 069fed6783209..2ac2269af44d8 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -24,7 +24,6 @@ default-features = false rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate/" - [dependencies.pallet-session] version = "2.0.0-alpha.2" default-features = false diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 02d144ccb38ef..015cfacb4e0b7 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -16,16 +16,35 @@ impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } rlp = { version = "0.4", default-features = false } - -sp-std = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } -sp-runtime = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } -sp-api = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } -sp-io = { version = "2.0.0-alpha.2", git = "https://github.com/paritytech/substrate.git", default-features = false, rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" } - hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } +# Substrate Based Dependencies +[dependencies.sp-api] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-std] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-runtime] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-io] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + [features] default = ["std"] test-helpers = [] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index f8822fe0a31ed..a58f89e5c2bd6 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "async-bridge" +name = "ethereum-poa-relay" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" @@ -11,22 +11,54 @@ async-stream = "0.2.0" clap = { version = "2.33.0", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" -frame-system = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } futures = "0.3.1" -jsonrpsee-core = { git = "https://github.com/paritytech/jsonrpsee.git" } -jsonrpsee-http = { git = "https://github.com/paritytech/jsonrpsee.git" } +jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } linked-hash-map = "0.5.2" log = "0.4.8" -node-primitives = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } -node-runtime = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } -pallet-transaction-payment = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } parking_lot = "0.9.0" rustc-hex = "2.0.1" serde = { version = "1.0.40", features = ["derive"] } serde_json = "1.0.40" -sp-bridge-eth-poa = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } -sp-core = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } -sp-keyring = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } -sp-runtime = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } +sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.1" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "fix_receipt" } + +# Substrate Based Dependencies +[dependencies.frame-system] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-transaction-payment] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +# I think this is used for sr-io and stuff +[dependencies.node-primitives] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +# Branch used for keccack256 hasher code +# Could probably move the keccack hasher stuff to our own primitives +[dependencies.sp-core] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-keyring] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-runtime] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + +# This should get moved to our `bin` folder +[dependencies.bridge-node-runtime] +version = "0.1.0" +path = "../../bin/node/runtime" +# node-runtime = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 08eaf2475340f..2147922dc79b1 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -30,8 +30,14 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use jsonrpsee_core::{client::ClientError, common::Params}; -use jsonrpsee_http::{HttpClient, RequestError, http_client}; +use jsonrpsee::common::Params; +use jsonrpsee::raw::{ + RawClient, + RawClientError, +}; +use jsonrpsee::transport::http::{ + HttpTransportClient, RequestError +}; use serde::de::DeserializeOwned; use serde_json::{from_value, to_value}; use crate::ethereum_sync_loop::MaybeConnectionError; @@ -45,7 +51,7 @@ const INT_SERIALIZATION_PROOF: &'static str = "integer serialization never fails const BOOL_SERIALIZATION_PROOF: &'static str = "bool serialization never fails; qed"; /// Ethereum client type. -pub type Client = HttpClient; +pub type Client = RawClient; /// All possible errors that can occur during interacting with Ethereum node. #[derive(Debug)] @@ -55,7 +61,7 @@ pub enum Error { /// Request not found (should never occur?). RequestNotFound, /// Failed to receive response. - ResponseRetrievalFailed(ClientError), + ResponseRetrievalFailed(RawClientError), /// Failed to parse response. ResponseParseFailed(serde_json::Error), /// We have received header with missing number and hash fields. @@ -75,7 +81,8 @@ impl MaybeConnectionError for Error { /// Returns client that is able to call RPCs on Ethereum node. pub fn client(uri: &str) -> Client { - http_client(uri) + let transport = HttpTransportClient::new(uri); + RawClient::new(transport) } /// Retrieve best known block number from Ethereum node. diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 7260cb87a254b..232970881a5a4 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -31,8 +31,13 @@ // along with Parity-Bridge. If not, see . use codec::{Encode, Decode}; -use jsonrpsee_core::{client::ClientError, common::Params}; -use jsonrpsee_http::{HttpClient, RequestError, http_client}; +use jsonrpsee::common::Params; +use jsonrpsee::raw::{ + RawClient, RawClientError +}; +use jsonrpsee::transport::http::{ + HttpTransportClient, RequestError +}; use serde_json::{from_value, to_value}; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; @@ -52,7 +57,7 @@ use crate::substrate_types::{ /// Substrate client type. pub struct Client { /// Substrate RPC client. - rpc_client: HttpClient, + rpc_client: RawClient, /// Transactions signer. signer: sp_core::sr25519::Pair, /// Genesis block hash. @@ -67,7 +72,7 @@ pub enum Error { /// Request not found (should never occur?). RequestNotFound, /// Failed to receive response. - ResponseRetrievalFailed(ClientError), + ResponseRetrievalFailed(RawClientError), /// Failed to parse response. ResponseParseFailed, } @@ -83,8 +88,9 @@ impl MaybeConnectionError for Error { /// Returns client that is able to call RPCs on Substrate node. pub fn client(uri: &str, signer: sp_core::sr25519::Pair) -> Client { + let transport = HttpTransportClient::new(uri); Client { - rpc_client: http_client(uri), + rpc_client: RawClient::new(transport), signer, genesis_hash: None, } @@ -283,9 +289,9 @@ fn create_submit_transaction( signer: &sp_core::sr25519::Pair, index: node_primitives::Index, genesis_hash: H256, -) -> node_runtime::UncheckedExtrinsic { - let function = node_runtime::Call::BridgeEthPoa( - node_runtime::BridgeEthPoaCall::import_headers( +) -> bridge_node_runtime::UncheckedExtrinsic { + let function = bridge_node_runtime::Call::BridgeEthPoA( + bridge_node_runtime::BridgeEthPoACall::import_headers( headers .into_iter() .map(|header| { @@ -301,33 +307,31 @@ fn create_submit_transaction( let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( - frame_system::CheckVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), - frame_system::CheckNonce::::from(i), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(f), - Default::default(), + frame_system::CheckVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::::from(i), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(f), ) }; - let raw_payload = node_runtime::SignedPayload::from_raw( + let raw_payload = bridge_node_runtime::SignedPayload::from_raw( function, extra(index, 0), ( - 198, // VERSION.spec_version as u32, + bridge_node_runtime::VERSION.spec_version as u32, genesis_hash, genesis_hash, (), (), (), - (), ), ); let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); let signer: sp_runtime::MultiSigner = signer.public().into(); let (function, extra, _) = raw_payload.deconstruct(); - node_runtime::UncheckedExtrinsic::new_signed( + bridge_node_runtime::UncheckedExtrinsic::new_signed( function, signer.into_account().into(), signature.into(), diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 5daa9104ba6f9..16ea51eb97f40 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -13,8 +13,20 @@ env_logger = "0.7.1" futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" -node-primitives = { version = "2.0.0", git = "https://github.com/paritytech/substrate" } serde_json = "1.0.41" -sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git" } -sp-rpc = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git" } url = "2.1.0" + +[dependencies.sp-core] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-rpc] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + +[dependencies.node-primitives] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" From 736bba0f720b58c97577e1c54f90b0eb6490f2d6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 19 Mar 2020 15:21:02 +0300 Subject: [PATCH 0017/1210] Reward submitters only when submitted block is finalized (#34) * reward submitters on finalization * fix grumble * make submitter part of ImportContext --- modules/ethereum/src/finality.rs | 31 +++--- modules/ethereum/src/import.rs | 135 +++++++++++++++++++----- modules/ethereum/src/lib.rs | 151 ++++++++++++++++++++------- modules/ethereum/src/validators.rs | 4 +- modules/ethereum/src/verification.rs | 16 +-- 5 files changed, 252 insertions(+), 85 deletions(-) diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index cfa4c77a397e2..f41fd712e6771 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -49,9 +49,10 @@ pub fn finalize_blocks( best_finalized_hash: &H256, header_validators: (&H256, &[Address]), hash: &H256, + submitter: Option<&S::Submitter>, header: &Header, two_thirds_majority_transition: u64, -) -> Result, Error> { +) -> Result)>, Error> { // compute count of voters for every unfinalized block in ancestry let validators = header_validators.1.iter().collect(); let (mut votes, mut headers) = prepare_votes( @@ -61,18 +62,19 @@ pub fn finalize_blocks( &validators, hash, header, + submitter, two_thirds_majority_transition, )?; // now let's iterate in reverse order && find just finalized blocks let mut newly_finalized = Vec::new(); - while let Some((oldest_hash, oldest_number, signers)) = headers.pop_front() { + while let Some((oldest_hash, oldest_number, submitter, signers)) = headers.pop_front() { if !is_finalized(&validators, &votes, oldest_number >= two_thirds_majority_transition) { break; } remove_signers_votes(&signers, &mut votes); - newly_finalized.push((oldest_number, oldest_hash)); + newly_finalized.push((oldest_number, oldest_hash, submitter)); } Ok(newly_finalized) @@ -96,8 +98,9 @@ fn prepare_votes( validators: &BTreeSet<&Address>, hash: &H256, header: &Header, + submitter: Option<&S::Submitter>, two_thirds_majority_transition: u64, -) -> Result<(BTreeMap, VecDeque<(H256, u64, BTreeSet
)>), Error> { +) -> Result<(BTreeMap, VecDeque<(H256, u64, Option, BTreeSet
)>), Error> { // this fn can only work with single validators set if !validators.contains(&header.author) { return Err(Error::NotValidator); @@ -108,17 +111,17 @@ fn prepare_votes( // the same set of validators let mut parent_empty_step_signers = empty_steps_signers(header); let ancestry = ancestry(storage, header) - .map(|(hash, header)| { + .map(|(hash, header, submitter)| { let mut signers = BTreeSet::new(); sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); signers.insert(header.author); let empty_step_signers = empty_steps_signers(&header); - let res = (hash, header.number, signers); + let res = (hash, header.number, submitter, signers); parent_empty_step_signers = empty_step_signers; res }) - .take_while(|&(hash, _, _)| hash != *validators_begin && hash != *best_finalized_hash); + .take_while(|&(hash, _, _, _)| hash != *validators_begin && hash != *best_finalized_hash); // now let's iterate built iterator and compute number of validators // 'voted' for each header @@ -126,21 +129,21 @@ fn prepare_votes( // just finalized blocks) let mut votes = BTreeMap::new(); let mut headers = VecDeque::new(); - for (hash, number, signers) in ancestry { + for (hash, number, submitter, signers) in ancestry { add_signers_votes(validators, &signers, &mut votes)?; if is_finalized(validators, &votes, number >= two_thirds_majority_transition) { remove_signers_votes(&signers, &mut votes); break; } - headers.push_front((hash, number, signers)); + headers.push_front((hash, number, submitter, signers)); } // update votes with last header vote let mut header_signers = BTreeSet::new(); header_signers.insert(header.author); *votes.entry(header.author).or_insert(0) += 1; - headers.push_back((*hash, header.number, header_signers)); + headers.push_back((*hash, header.number, submitter.cloned(), header_signers)); Ok((votes, headers)) } @@ -211,6 +214,7 @@ mod tests { &Default::default(), (&Default::default(), &[]), &Default::default(), + None, &Header::default(), 0, ), @@ -233,7 +237,7 @@ mod tests { }; let hash1 = header1.hash(); let mut header_to_import = HeaderToImport { - context: storage.import_context(&genesis().hash()).unwrap(), + context: storage.import_context(None, &genesis().hash()).unwrap(), is_best: true, hash: hash1, header: header1, @@ -247,6 +251,7 @@ mod tests { &Default::default(), (&Default::default(), &validators_addresses(5)), &hash1, + None, &header_to_import.header, u64::max_value(), ), @@ -269,6 +274,7 @@ mod tests { &Default::default(), (&Default::default(), &validators_addresses(5)), &hash2, + None, &header_to_import.header, u64::max_value(), ), @@ -291,10 +297,11 @@ mod tests { &Default::default(), (&Default::default(), &validators_addresses(5)), &hash3, + None, &header_to_import.header, u64::max_value(), ), - Ok(vec![(1, hash1)]), + Ok(vec![(1, hash1, None)]), ); storage.insert_header(header_to_import); } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index bf8d21ea02975..14cb8f26a7fac 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -36,7 +36,10 @@ use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::verify_aura_header; use crate::{AuraConfiguration, Storage}; use primitives::{Header, Receipt, H256}; -use sp_std::prelude::*; +use sp_std::{ + collections::btree_map::BTreeMap, + prelude::*, +}; /// Maximal number of headers behind best blocks that we are aiming to store. When there /// are too many unfinalized headers, it slows down finalization tracking significantly. @@ -61,15 +64,32 @@ pub fn import_headers( aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, prune_depth: u64, + submitter: Option, headers: Vec<(Header, Option>)>, + finalized_headers: &mut BTreeMap, ) -> Result<(u64, u64), Error> { let mut useful = 0; let mut useless = 0; for (header, receipts) in headers { - let import_result = import_header(storage, aura_config, validators_config, prune_depth, header, receipts); + let import_result = import_header( + storage, + aura_config, + validators_config, + prune_depth, + submitter.clone(), + header, + receipts, + ); match import_result { - Ok(_) => useful += 1, + Ok((_, finalized)) => { + for (_, _, submitter) in finalized { + if let Some(submitter) = submitter { + *finalized_headers.entry(submitter).or_default() += 1; + } + } + useful += 1; + }, Err(Error::AncientHeader) | Err(Error::KnownHeader) => useless += 1, Err(error) => return Err(error), } @@ -82,19 +102,22 @@ pub fn import_headers( /// /// Transactions receipts must be provided if `header_import_requires_receipts()` /// has returned true. +/// +/// Returns imported block hash. pub fn import_header( storage: &mut S, aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, prune_depth: u64, + submitter: Option, header: Header, receipts: Option>, -) -> Result { +) -> Result<(H256, Vec<(u64, H256, Option)>), Error> { // first check that we are able to import this header at all let (hash, prev_finalized_hash) = is_importable_header(storage, &header)?; // verify header - let import_context = verify_aura_header(storage, aura_config, &header)?; + let import_context = verify_aura_header(storage, aura_config, submitter, &header)?; // check if block schedules new validators let validators = Validators::new(validators_config); @@ -106,6 +129,7 @@ pub fn import_header( &prev_finalized_hash, (import_context.validators_start(), import_context.validators()), &hash, + import_context.submitter(), &header, aura_config.two_thirds_majority_transition, )?; @@ -119,25 +143,27 @@ pub fn import_header( let total_difficulty = import_context.total_difficulty() + header.difficulty; let is_best = total_difficulty > best_total_difficulty; let header_number = header.number; - storage.insert_header(import_context.into_import_header( - is_best, - hash, - header, - total_difficulty, - enacted_change, - scheduled_change, - )); + storage.insert_header( + import_context.into_import_header( + is_best, + hash, + header, + total_difficulty, + enacted_change, + scheduled_change, + ), + ); // now mark finalized headers && prune old headers storage.finalize_headers( - finalized_blocks.last().cloned(), + finalized_blocks.last().map(|(number, hash, _)| (*number, *hash)), match is_best { true => header_number.checked_sub(prune_depth), false => None, }, ); - Ok(hash) + Ok((hash, finalized_blocks)) } /// Returns true if transactions receipts are required to import given header. @@ -189,6 +215,7 @@ mod tests { &kovan_aura_config(), &kovan_validators_config(), PRUNE_DEPTH, + None, Default::default(), None, ), @@ -207,6 +234,7 @@ mod tests { &kovan_aura_config(), &kovan_validators_config(), PRUNE_DEPTH, + None, block.clone(), None, ) @@ -219,6 +247,7 @@ mod tests { &kovan_aura_config(), &kovan_validators_config(), PRUNE_DEPTH, + None, block, None, ) @@ -243,6 +272,7 @@ mod tests { &kovan_aura_config(), &validators_config, PRUNE_DEPTH, + None, header, None ) @@ -267,43 +297,67 @@ mod tests { // header [0..11] are finalizing blocks [0; 9] // => since we want to keep 10 finalized blocks, we aren't pruning anything - let mut last_block_hash = Default::default(); + let mut latest_block_hash = Default::default(); for i in 1..11 { let header = block_i(&storage, i, &validators); - last_block_hash = - import_header(&mut storage, &kovan_aura_config(), &validators_config, 10, header, None).unwrap(); + let (rolling_last_block_hash, finalized_blocks) = + import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(100), + header, + None, + ).unwrap(); + match i { + 2 ..= 10 => assert_eq!( + finalized_blocks, + vec![(i - 1, block_i(&storage, i - 1, &validators).hash(), Some(100))], + "At {}", + i, + ), + _ => assert_eq!(finalized_blocks, vec![], "At {}", i), + } + latest_block_hash = rolling_last_block_hash; } assert!(storage.header(&genesis().hash()).is_some()); // header 11 finalizes headers [10] AND schedules change // => we prune header#0 - let header = custom_block_i(&storage, 11, &validators, |header| { + let header11 = custom_block_i(&storage, 11, &validators, |header| { header.log_bloom = (&[0xff; 256]).into(); header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951" .parse() .unwrap(); }); - last_block_hash = import_header( + let (rolling_last_block_hash, finalized_blocks) = import_header( &mut storage, &kovan_aura_config(), &validators_config, 10, - header, + Some(101), + header11.clone(), Some(vec![crate::validators::tests::validators_change_recept( - last_block_hash, + latest_block_hash, )]), - ) - .unwrap(); + ).unwrap(); + assert_eq!( + finalized_blocks, + vec![(10, block_i(&storage, 10, &validators).hash(), Some(100))], + ); assert!(storage.header(&genesis().hash()).is_none()); + latest_block_hash = rolling_last_block_hash; // and now let's say validators 1 && 2 went offline // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers // until header#11 is met. we can't prune #11, because it schedules change let mut step = 56; + let mut expected_blocks = vec![(11, header11.hash(), Some(101))]; for i in 12..25 { let header = Header { number: i as _, - parent_hash: last_block_hash, + parent_hash: latest_block_hash, gas_limit: 0x2000.into(), author: validator(2).address().to_fixed_bytes().into(), seal: vec![vec![step].into(), vec![].into()], @@ -311,8 +365,22 @@ mod tests { ..Default::default() }; let header = signed_header(&validators, header, step as _); - last_block_hash = - import_header(&mut storage, &kovan_aura_config(), &validators_config, 10, header, None).unwrap(); + expected_blocks.push((i, header.hash(), Some(102))); + let (rolling_last_block_hash, finalized_blocks) = + import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(102), + header, + None, + ).unwrap(); + assert_eq!( + finalized_blocks, + vec![], + ); + latest_block_hash = rolling_last_block_hash; step += 3; } assert_eq!(storage.oldest_unpruned_block(), 11); @@ -322,7 +390,7 @@ mod tests { step -= 2; let header = Header { number: 25, - parent_hash: last_block_hash, + parent_hash: latest_block_hash, gas_limit: 0x2000.into(), author: validator(0).address().to_fixed_bytes().into(), seal: vec![vec![step].into(), vec![].into()], @@ -330,7 +398,16 @@ mod tests { ..Default::default() }; let header = signed_header(&validators, header, step as _); - import_header(&mut storage, &kovan_aura_config(), &validators_config, 10, header, None).unwrap(); + let (_, finalized_blocks) = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(103), + header, + None, + ).unwrap(); + assert_eq!(finalized_blocks, expected_blocks); assert_eq!(storage.oldest_unpruned_block(), 15); } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index f69dbe0592ed5..5d28bfd074dca 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -36,7 +36,12 @@ use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage}; use primitives::{Address, Header, Receipt, H256, U256}; use sp_runtime::RuntimeDebug; -use sp_std::{iter::from_fn, prelude::*}; +use sp_std::{ + prelude::*, + cmp::Ord, + collections::btree_map::BTreeMap, + iter::from_fn, +}; use validators::{ValidatorsConfiguration, ValidatorsSource}; pub use import::{header_import_requires_receipts, import_header}; @@ -70,7 +75,10 @@ pub struct AuraConfiguration { /// Block header as it is stored in the runtime storage. #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] -pub struct StoredHeader { +pub struct StoredHeader { + /// Submitter of this header. May be `None` if header has been submitted + /// using unsigned transaction. + pub submitter: Option, /// The block header itself. pub header: Header, /// Total difficulty of the chain. @@ -85,9 +93,9 @@ pub struct StoredHeader { /// Header that we're importing. #[derive(RuntimeDebug)] #[cfg_attr(test, derive(Clone, PartialEq))] -pub struct HeaderToImport { +pub struct HeaderToImport { /// Header import context, - pub context: ImportContext, + pub context: ImportContext, /// Should we consider this header as best? pub is_best: bool, /// The hash of the header. @@ -105,22 +113,25 @@ pub struct HeaderToImport { /// Header import context. #[derive(RuntimeDebug)] #[cfg_attr(test, derive(Clone, PartialEq))] -pub struct ImportContext { +pub struct ImportContext { + submitter: Option, parent_header: Header, parent_total_difficulty: U256, next_validators_set_id: u64, next_validators_set: (H256, Vec
), } -impl ImportContext { +impl ImportContext { /// Create import context using passing parameters; pub fn new( + submitter: Option, parent_header: Header, parent_total_difficulty: U256, next_validators_set_id: u64, next_validators_set: (H256, Vec
), ) -> Self { ImportContext { + submitter, parent_header, parent_total_difficulty, next_validators_set_id, @@ -128,6 +139,11 @@ impl ImportContext { } } + /// Returns reference to header submitter (if known). + pub fn submitter(&self) -> Option<&Submitter> { + self.submitter.as_ref() + } + /// Returns reference to parent header. pub fn parent_header(&self) -> &Header { &self.parent_header @@ -162,7 +178,7 @@ impl ImportContext { total_difficulty: U256, enacted_change: Option>, scheduled_change: Option>, - ) -> HeaderToImport { + ) -> HeaderToImport { HeaderToImport { context: self, is_best, @@ -179,18 +195,27 @@ impl ImportContext { /// /// Storage modification must be discarded if block import has failed. pub trait Storage { + /// Header submitter identifier. + type Submitter: Clone + Ord; + /// Get best known block. fn best_block(&self) -> (u64, H256, U256); /// Get last finalized block. fn finalized_block(&self) -> (u64, H256); /// Get imported header by its hash. - fn header(&self, hash: &H256) -> Option
; + /// + /// Returns header and its submitter (if known). + fn header(&self, hash: &H256) -> Option<(Header, Option)>; /// Get header import context by parent header hash. - fn import_context(&self, parent_hash: &H256) -> Option; + fn import_context( + &self, + submitter: Option, + parent_hash: &H256, + ) -> Option>; /// Get new validators that are scheduled by given header. fn scheduled_change(&self, hash: &H256) -> Option>; /// Insert imported header. - fn insert_header(&mut self, header: HeaderToImport); + fn insert_header(&mut self, header: HeaderToImport); /// Finalize given block and prune all headers with number < prune_end. /// The headers in the pruning range could be either finalized, or not. /// It is the storage duty to ensure that unfinalized headers that have @@ -202,14 +227,25 @@ pub trait Storage { /// Decides whether the session should be ended. pub trait OnHeadersSubmitted { /// Called when valid headers have been submitted. + /// + /// The submitter **must not** be rewarded for submitting valid headers, because greedy authority + /// could produce and submit multiple valid headers (without relaying them to other peers) and + /// get rewarded. Instead, the provider could track submitters and stop rewarding if too many + /// headers have been submitted without finalization. fn on_valid_headers_submitted(submitter: AccountId, useful: u64, useless: u64); /// Called when invalid headers have been submitted. fn on_invalid_headers_submitted(submitter: AccountId); + /// Called when earlier submitted headers have been finalized. + /// + /// finalized is the number of headers that submitter has submitted and which + /// have been finalized. + fn on_valid_headers_finalized(submitter: AccountId, finalized: u64); } impl OnHeadersSubmitted for () { fn on_valid_headers_submitted(_submitter: AccountId, _useful: u64, _useless: u64) {} fn on_invalid_headers_submitted(_submitter: AccountId) {} + fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {} } /// The module configuration trait @@ -228,14 +264,27 @@ decl_module! { /// enormous block production/import time. pub fn import_headers(origin, headers_with_receipts: Vec<(Header, Option>)>) { let submitter = frame_system::ensure_signed(origin)?; + let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( - &mut BridgeStorage, + &mut BridgeStorage::::new(), &kovan_aura_config(), &kovan_validators_config(), crate::import::PRUNE_DEPTH, + Some(submitter.clone()), headers_with_receipts, + &mut finalized_headers, ); + // if we have finalized some headers, we will reward their submitters even + // if current submitter has provided some invalid headers + for (f_submitter, f_count) in finalized_headers { + T::OnHeadersSubmitted::on_valid_headers_finalized( + f_submitter, + f_count, + ); + } + + // now track/penalize current submitter for providing new headers match import_result { Ok((useful, useless)) => T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), @@ -259,7 +308,7 @@ decl_storage! { /// Oldest unpruned block(s) number. OldestUnprunedBlock: u64; /// Map of imported headers by hash. - Headers: map hasher(blake2_256) H256 => Option; + Headers: map hasher(blake2_256) H256 => Option>; /// Map of imported header hashes by number. HeadersByNumber: map hasher(blake2_256) u64 => Option>; /// The ID of next validator set. @@ -293,7 +342,8 @@ decl_storage! { FinalizedBlock::put((config.initial_header.number, initial_hash)); OldestUnprunedBlock::put(config.initial_header.number); HeadersByNumber::insert(config.initial_header.number, vec![initial_hash]); - Headers::insert(initial_hash, StoredHeader { + Headers::::insert(initial_hash, StoredHeader { + submitter: None, header: config.initial_header.clone(), total_difficulty: config.initial_difficulty, next_validators_set_id: 0, @@ -310,25 +360,34 @@ impl Module { /// The caller should only submit `import_header` transaction that makes /// (or leads to making) other header the best one. pub fn best_block() -> (u64, H256) { - let (number, hash, _) = BridgeStorage.best_block(); + let (number, hash, _) = BridgeStorage::::new().best_block(); (number, hash) } /// Returns true if the import of given block requires transactions receipts. pub fn is_import_requires_receipts(header: Header) -> bool { - import::header_import_requires_receipts(&BridgeStorage, &kovan_validators_config(), &header) + import::header_import_requires_receipts(&BridgeStorage::::new(), &kovan_validators_config(), &header) } /// Returns true if header is known to the runtime. pub fn is_known_block(hash: H256) -> bool { - BridgeStorage.header(&hash).is_some() + BridgeStorage::::new().header(&hash).is_some() } } /// Runtime bridge storage. -struct BridgeStorage; +#[derive(Default)] +struct BridgeStorage(sp_std::marker::PhantomData); + +impl BridgeStorage { + pub fn new() -> Self { + BridgeStorage(sp_std::marker::PhantomData::::default()) + } +} + +impl Storage for BridgeStorage { + type Submitter = T::AccountId; -impl Storage for BridgeStorage { fn best_block(&self) -> (u64, H256, U256) { BestBlock::get() } @@ -337,16 +396,21 @@ impl Storage for BridgeStorage { FinalizedBlock::get() } - fn header(&self, hash: &H256) -> Option
{ - Headers::get(hash).map(|header| header.header) + fn header(&self, hash: &H256) -> Option<(Header, Option)> { + Headers::::get(hash).map(|header| (header.header, header.submitter)) } - fn import_context(&self, parent_hash: &H256) -> Option { - Headers::get(parent_hash).map(|parent_header| { + fn import_context( + &self, + submitter: Option, + parent_hash: &H256, + ) -> Option> { + Headers::::get(parent_hash).map(|parent_header| { let (next_validators_set_start, next_validators) = ValidatorsSets::get(parent_header.next_validators_set_id) .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); ImportContext { + submitter, parent_header: parent_header.header, parent_total_difficulty: parent_header.total_difficulty, next_validators_set_id: parent_header.next_validators_set_id, @@ -359,7 +423,7 @@ impl Storage for BridgeStorage { ScheduledChanges::get(hash) } - fn insert_header(&mut self, header: HeaderToImport) { + fn insert_header(&mut self, header: HeaderToImport) { if header.is_best { BestBlock::put((header.header.number, header.hash, header.total_difficulty)); } @@ -387,9 +451,10 @@ impl Storage for BridgeStorage { }; HeadersByNumber::append_or_insert(header.header.number, vec![header.hash]); - Headers::insert( + Headers::::insert( &header.hash, StoredHeader { + submitter: header.context.submitter, header: header.header, total_difficulty: header.total_difficulty, next_validators_set_id, @@ -426,7 +491,7 @@ impl Storage for BridgeStorage { // physically remove headers and (probably) obsolete validators sets for hash in blocks_at_number.into_iter().flat_map(|x| x) { - let header = Headers::take(&hash); + let header = Headers::::take(&hash); ScheduledChanges::remove(hash); if let Some(header) = header { ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { @@ -570,19 +635,22 @@ pub fn kovan_validators_config() -> ValidatorsConfiguration { } /// Return iterator of given header ancestors. -pub(crate) fn ancestry<'a, S: Storage>(storage: &'a S, header: &Header) -> impl Iterator + 'a { +pub(crate) fn ancestry<'a, S: Storage>( + storage: &'a S, + header: &Header, +) -> impl Iterator)> + 'a { let mut parent_hash = header.parent_hash.clone(); from_fn(move || { - let header = storage.header(&parent_hash); - match header { - Some(header) => { + let header_and_submitter = storage.header(&parent_hash); + match header_and_submitter { + Some((header, submitter)) => { if header.number == 0 { return None; } let hash = parent_hash.clone(); parent_hash = header.parent_hash.clone(); - Some((hash, header)) + Some((hash, header, submitter)) } None => None, } @@ -596,6 +664,8 @@ pub(crate) mod tests { use primitives::{rlp_encode, H520}; use std::collections::{hash_map::Entry, HashMap}; + pub type AccountId = u64; + pub fn genesis() -> Header { Header { seal: vec![vec![42].into(), vec![].into()], @@ -651,7 +721,7 @@ pub(crate) mod tests { best_block: (u64, H256, U256), finalized_block: (u64, H256), oldest_unpruned_block: u64, - headers: HashMap, + headers: HashMap>, headers_by_number: HashMap>, next_validators_set_id: u64, validators_sets: HashMap)>, @@ -670,6 +740,7 @@ pub(crate) mod tests { headers: vec![( hash, StoredHeader { + submitter: None, header: initial_header, total_difficulty: 0.into(), next_validators_set_id: 0, @@ -688,12 +759,14 @@ pub(crate) mod tests { self.oldest_unpruned_block } - pub(crate) fn stored_header(&self, hash: &H256) -> Option<&StoredHeader> { + pub(crate) fn stored_header(&self, hash: &H256) -> Option<&StoredHeader> { self.headers.get(hash) } } impl Storage for InMemoryStorage { + type Submitter = AccountId; + fn best_block(&self) -> (u64, H256, U256) { self.best_block.clone() } @@ -702,15 +775,20 @@ pub(crate) mod tests { self.finalized_block.clone() } - fn header(&self, hash: &H256) -> Option
{ - self.headers.get(hash).map(|header| header.header.clone()) + fn header(&self, hash: &H256) -> Option<(Header, Option)> { + self.headers.get(hash).map(|header| (header.header.clone(), header.submitter.clone())) } - fn import_context(&self, parent_hash: &H256) -> Option { + fn import_context( + &self, + submitter: Option, + parent_hash: &H256, + ) -> Option> { self.headers.get(parent_hash).map(|parent_header| { let (next_validators_set_start, next_validators) = self.validators_sets.get(&parent_header.next_validators_set_id).unwrap(); ImportContext { + submitter, parent_header: parent_header.header.clone(), parent_total_difficulty: parent_header.total_difficulty, next_validators_set_id: parent_header.next_validators_set_id, @@ -723,7 +801,7 @@ pub(crate) mod tests { self.scheduled_changes.get(hash).cloned() } - fn insert_header(&mut self, header: HeaderToImport) { + fn insert_header(&mut self, header: HeaderToImport) { if header.is_best { self.best_block = (header.header.number, header.hash, header.total_difficulty); } @@ -755,6 +833,7 @@ pub(crate) mod tests { self.headers.insert( header.hash, StoredHeader { + submitter: header.context.submitter, header: header.header, total_difficulty: header.total_difficulty, next_validators_set_id, diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 21f1f0b58b0da..3342f22450b62 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -198,9 +198,9 @@ impl<'a> Validators<'a> { pub fn finalize_validators_change( &self, storage: &mut S, - finalized_blocks: &[(u64, H256)], + finalized_blocks: &[(u64, H256, Option)], ) -> Option> { - for (_, finalized_hash) in finalized_blocks.iter().rev() { + for (_, finalized_hash, _) in finalized_blocks.iter().rev() { if let Some(changes) = storage.scheduled_change(finalized_hash) { return Some(changes); } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index ea9b37fa528d0..c0edd5e56d434 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -40,14 +40,15 @@ use sp_io::crypto::secp256k1_ecdsa_recover; pub fn verify_aura_header( storage: &S, params: &AuraConfiguration, + submitter: Option, header: &Header, -) -> Result { +) -> Result, Error> { // let's do the lightest check first contextless_checks(params, header)?; // the rest of checks requires parent let context = storage - .import_context(&header.parent_hash) + .import_context(submitter, &header.parent_hash) .ok_or(Error::MissingParentBlock)?; let validators = context.validators(); let header_step = header.step().ok_or(Error::MissingStep)?; @@ -179,7 +180,7 @@ fn verify_signature(expected_validator: &Address, signature: &H520, message: &H2 mod tests { use super::*; use crate::kovan_aura_config; - use crate::tests::{genesis, signed_header, validator, validators_addresses, InMemoryStorage}; + use crate::tests::{genesis, signed_header, validator, validators_addresses, AccountId, InMemoryStorage}; use parity_crypto::publickey::{sign, KeyPair}; use primitives::{rlp_encode, H520}; @@ -197,12 +198,15 @@ mod tests { empty_step } - fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result { + fn verify_with_config( + config: &AuraConfiguration, + header: &Header, + ) -> Result, Error> { let storage = InMemoryStorage::new(genesis(), validators_addresses(3)); - verify_aura_header(&storage, &config, header) + verify_aura_header(&storage, &config, None, header) } - fn default_verify(header: &Header) -> Result { + fn default_verify(header: &Header) -> Result, Error> { verify_with_config(&kovan_aura_config(), header) } From 3f4acab110d6f8c75004da443e701800ceea5892 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 19 Mar 2020 13:35:48 -0400 Subject: [PATCH 0018/1210] Run RustFmt as part of the CI (#37) * Run RustFmt as part of the CI * Format repo * Run RustFmt before the default Travis build step Apparently if you override `script` you also need to make sure to `build` and `test` the code yourself. * Format repo --- bin/node/node/build.rs | 2 +- bin/node/node/src/chain_spec.rs | 181 ++++++----- bin/node/node/src/command.rs | 22 +- bin/node/node/src/service.rs | 142 ++++----- bin/node/runtime/src/lib.rs | 41 ++- modules/ethereum/src/finality.rs | 8 +- modules/ethereum/src/import.rs | 78 +++-- modules/ethereum/src/lib.rs | 16 +- modules/ethereum/src/verification.rs | 5 +- relays/ethereum/src/ethereum_client.rs | 67 ++-- relays/ethereum/src/ethereum_headers.rs | 363 +++++++++++++++++----- relays/ethereum/src/ethereum_sync.rs | 26 +- relays/ethereum/src/ethereum_sync_loop.rs | 56 ++-- relays/ethereum/src/ethereum_types.rs | 5 +- relays/ethereum/src/main.rs | 26 +- relays/ethereum/src/substrate_client.rs | 126 +++----- relays/ethereum/src/substrate_types.rs | 50 +-- relays/substrate/src/bridge.rs | 212 ++++++------- relays/substrate/src/main.rs | 35 +-- relays/substrate/src/params.rs | 6 +- relays/substrate/src/rpc.rs | 6 +- 21 files changed, 836 insertions(+), 637 deletions(-) diff --git a/bin/node/node/build.rs b/bin/node/node/build.rs index 02322263485cf..e9a10ff8ad009 100644 --- a/bin/node/node/build.rs +++ b/bin/node/node/build.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use vergen::{ConstantsFlags, generate_cargo_keys}; +use vergen::{generate_cargo_keys, ConstantsFlags}; const ERROR_MSG: &str = "Failed to generate metadata files"; diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 6301e342ee868..0e81f7f167658 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -14,16 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use sp_core::{Pair, Public, sr25519}; use bridge_node_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, - GenesisConfig, GrandpaConfig, SudoConfig, SystemConfig, - WASM_BINARY, Signature + AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, + SystemConfig, WASM_BINARY, }; -use sp_consensus_aura::sr25519::{AuthorityId as AuraId}; -use grandpa_primitives::{AuthorityId as GrandpaId}; +use grandpa_primitives::AuthorityId as GrandpaId; use sc_service; -use sp_runtime::traits::{Verify, IdentifyAccount}; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::ChainSpec; @@ -47,18 +46,16 @@ pub fn get_from_seed(seed: &str) -> ::Pu type AccountPublic = ::Signer; /// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId where - AccountPublic: From<::Public> +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, { AccountPublic::from(get_from_seed::(seed)).into_account() } /// Helper function to generate an authority key for Aura pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - ( - get_from_seed::(s), - get_from_seed::(s), - ) + (get_from_seed::(s), get_from_seed::(s)) } impl Alternative { @@ -68,24 +65,24 @@ impl Alternative { Alternative::Development => ChainSpec::from_genesis( "Development", "dev", - || testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - vec![ + || { + testnet_genesis( + vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - ], - true, - ), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ) + }, vec![], None, None, None, - None + None, ), }) } @@ -98,17 +95,19 @@ impl Alternative { } } -fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, +fn testnet_genesis( + initial_authorities: Vec<(AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, - _enable_println: bool) -> GenesisConfig { + _enable_println: bool, +) -> GenesisConfig { GenesisConfig { frame_system: Some(SystemConfig { code: WASM_BINARY.to_vec(), changes_trie_config: Default::default(), }), pallet_balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }), pallet_aura: Some(AuraConfig { authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), @@ -117,9 +116,7 @@ fn testnet_genesis(initial_authorities: Vec<(AuraId, GrandpaId)>, pallet_grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), }), - pallet_sudo: Some(SudoConfig { - key: root_key, - }), + pallet_sudo: Some(SudoConfig { key: root_key }), } } @@ -132,45 +129,85 @@ pub fn load_spec(id: &str) -> Result, String> { fn load_kovan_config() -> Option { Some(BridgeEthPoAConfig { - initial_header: sp_bridge_eth_poa::Header { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), - extra_data: vec![], - state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), - receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 6000000.into(), - difficulty: 131072.into(), - seal: vec![ - vec![128].into(), - vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), - ], - }, - initial_difficulty: 0.into(), - initial_validators: vec![ - [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, - 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), - [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, - 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), - [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, - 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), - [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, - 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), - [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, - 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), - [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, - 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), - [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, - 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), - [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, - 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), - [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, - 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), + initial_header: sp_bridge_eth_poa::Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + .parse() + .unwrap(), + uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + .parse() + .unwrap(), + extra_data: vec![], + state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2" + .parse() + .unwrap(), + receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + .parse() + .unwrap(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 6000000.into(), + difficulty: 131072.into(), + seal: vec![ + vec![128].into(), + vec![ + 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ] + .into(), ], - }) + }, + initial_difficulty: 0.into(), + initial_validators: vec![ + [ + 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, + 0xAd, 0xc0, 0xED, + ] + .into(), + [ + 0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, + 0x0a, 0x4d, 0x3d, + ] + .into(), + [ + 0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, + 0x42, 0x4d, 0x6c, + ] + .into(), + [ + 0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, + 0xbA, 0x81, 0xA1, + ] + .into(), + [ + 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, + 0xfd, 0x03, 0x2d, + ] + .into(), + [ + 0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, + 0x93, 0x38, 0x7A, + ] + .into(), + [ + 0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, + 0x89, 0x78, 0x79, + ] + .into(), + [ + 0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, + 0xa1, 0x64, 0x5c, + ] + .into(), + [ + 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, + 0x31, 0x94, 0xde, + ] + .into(), + ], + }) } diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs index c17ea03dd34f7..cdae1c8e3aae8 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/node/src/command.rs @@ -30,11 +30,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use sc_cli::VersionInfo; -use crate::service; use crate::chain_spec; use crate::cli::Cli; +use crate::service; +use sc_cli::VersionInfo; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; /// Parse and run command line arguments pub fn run(version: VersionInfo) -> sc_cli::Result<()> { @@ -46,20 +46,12 @@ pub fn run(version: VersionInfo) -> sc_cli::Result<()> { Some(subcommand) => { subcommand.init(&version)?; subcommand.update_config(&mut config, chain_spec::load_spec, &version)?; - subcommand.run( - config, - |config: _| Ok(new_full_start!(config).0), - ) - }, + subcommand.run(config, |config: _| Ok(new_full_start!(config).0)) + } None => { opt.run.init(&version)?; opt.run.update_config(&mut config, chain_spec::load_spec, &version)?; - opt.run.run( - config, - service::new_light, - service::new_full, - &version, - ) - }, + opt.run.run(config, service::new_light, service::new_full, &version) + } } } diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index f268a5dbbb4ea..6d629f5708cfb 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -16,16 +16,16 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -use std::sync::Arc; -use std::time::Duration; +use bridge_node_runtime::{self, opaque::Block, GenesisConfig, RuntimeApi}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use sc_client::LongestChain; -use bridge_node_runtime::{self, GenesisConfig, opaque::Block, RuntimeApi}; -use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder}; -use sp_inherents::InherentDataProviders; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; +use sc_service::{error::Error as ServiceError, AbstractService, Configuration, ServiceBuilder}; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_inherents::InherentDataProviders; +use std::sync::Arc; +use std::time::Duration; // Our native executor instance. native_executor_instance!( @@ -44,48 +44,50 @@ macro_rules! new_full_start { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); let builder = sc_service::ServiceBuilder::new_full::< - bridge_node_runtime::opaque::Block, bridge_node_runtime::RuntimeApi, crate::service::Executor + bridge_node_runtime::opaque::Block, + bridge_node_runtime::RuntimeApi, + crate::service::Executor, >($config)? - .with_select_chain(|_config, backend| { - Ok(sc_client::LongestChain::new(backend.clone())) - })? - .with_transaction_pool(|config, client, _fetcher| { - let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); - Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api))) - })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { - let select_chain = select_chain.take() - .ok_or_else(|| sc_service::Error::SelectChainRequired)?; - - let (grandpa_block_import, grandpa_link) = - grandpa::block_import(client.clone(), &*client, select_chain)?; - - let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( - grandpa_block_import.clone(), client.clone(), - ); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import.clone())), - None, - client, - inherent_data_providers.clone(), - )?; - - import_setup = Some((grandpa_block_import, grandpa_link)); - - Ok(import_queue) - })?; + .with_select_chain(|_config, backend| Ok(sc_client::LongestChain::new(backend.clone())))? + .with_transaction_pool(|config, client, _fetcher| { + let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); + Ok(sc_transaction_pool::BasicPool::new( + config, + std::sync::Arc::new(pool_api), + )) + })? + .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { + let select_chain = select_chain + .take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + + let (grandpa_block_import, grandpa_link) = grandpa::block_import(client.clone(), &*client, select_chain)?; + + let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( + grandpa_block_import.clone(), + client.clone(), + ); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client, + inherent_data_providers.clone(), + )?; + + import_setup = Some((grandpa_block_import, grandpa_link)); + + Ok(import_queue) + })?; (builder, import_setup, inherent_data_providers) - }} + }}; } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) - -> Result -{ +pub fn new_full(config: Configuration) -> Result { let is_authority = config.roles.is_authority(); let force_authoring = config.force_authoring; let name = config.name.clone(); @@ -98,14 +100,14 @@ pub fn new_full(config: Configuration) let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); - let (block_import, grandpa_link) = - import_setup.take() - .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + let (block_import, grandpa_link) = import_setup + .take() + .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); let service = builder - .with_finality_proof_provider(|client, backend| + .with_finality_proof_provider(|client, backend| { Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? + })? .build()?; if participates_in_consensus { @@ -115,11 +117,9 @@ pub fn new_full(config: Configuration) }; let client = service.client(); - let select_chain = service.select_chain() - .ok_or(ServiceError::SelectChainRequired)?; + let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?; - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( sc_consensus_aura::slot_duration(&*client)?, @@ -177,38 +177,28 @@ pub fn new_full(config: Configuration) // the GRANDPA voter task is considered infallible, i.e. // if it fails we take down the service with it. - service.spawn_essential_task( - "grandpa-voter", - grandpa::run_grandpa_voter(grandpa_config)? - ); + service.spawn_essential_task("grandpa-voter", grandpa::run_grandpa_voter(grandpa_config)?); } else { - grandpa::setup_disabled_grandpa( - service.client(), - &inherent_data_providers, - service.network(), - )?; + grandpa::setup_disabled_grandpa(service.client(), &inherent_data_providers, service.network())?; } Ok(service) } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) - -> Result -{ +pub fn new_light(config: Configuration) -> Result { let inherent_data_providers = InherentDataProviders::new(); ServiceBuilder::new_light::(config)? - .with_select_chain(|_config, backend| { - Ok(LongestChain::new(backend.clone())) - })? + .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))? .with_transaction_pool(|config, client, fetcher| { - let fetcher = fetcher - .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + let fetcher = fetcher.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); let pool = sc_transaction_pool::BasicPool::with_revalidation_type( - config, Arc::new(pool_api), sc_transaction_pool::RevalidationType::Light, + config, + Arc::new(pool_api), + sc_transaction_pool::RevalidationType::Light, ); Ok(pool) })? @@ -216,12 +206,10 @@ pub fn new_light(config: Configuration) let fetch_checker = fetcher .map(|fetcher| fetcher.checker().clone()) .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; - let grandpa_block_import = grandpa::light_block_import( - client.clone(), backend, &*client.clone(), Arc::new(fetch_checker), - )?; + let grandpa_block_import = + grandpa::light_block_import(client.clone(), backend, &*client.clone(), Arc::new(fetch_checker))?; let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = - finality_proof_import.create_finality_proof_request_builder(); + let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( sc_consensus_aura::slot_duration(&*client)?, @@ -234,8 +222,8 @@ pub fn new_light(config: Configuration) Ok((import_queue, finality_proof_request_builder)) })? - .with_finality_proof_provider(|client, backend| + .with_finality_proof_provider(|client, backend| { Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) - )? + })? .build() } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d5b1c0dd143f0..dff29f9dff4b7 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -18,41 +18,35 @@ #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit="256"] +#![recursion_limit = "256"] // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use sp_std::prelude::*; +use pallet_grandpa::fg_primitives; +use pallet_grandpa::AuthorityList as GrandpaAuthorityList; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::OpaqueMetadata; +use sp_runtime::traits::{BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, IdentityLookup, Verify}; use sp_runtime::{ - ApplyExtrinsicResult, transaction_validity::TransactionValidity, generic, create_runtime_str, - impl_opaque_keys, MultiSignature, + create_runtime_str, generic, impl_opaque_keys, transaction_validity::TransactionValidity, ApplyExtrinsicResult, + MultiSignature, }; -use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentityLookup, Verify, ConvertInto, IdentifyAccount -}; -use sp_api::impl_runtime_apis; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use pallet_grandpa::AuthorityList as GrandpaAuthorityList; -use pallet_grandpa::fg_primitives; -use sp_version::RuntimeVersion; +use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; +use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use pallet_timestamp::Call as TimestampCall; +pub use frame_support::{construct_runtime, parameter_types, traits::Randomness, weights::Weight, StorageValue}; pub use pallet_balances::Call as BalancesCall; -pub use sp_runtime::{Permill, Perbill}; -pub use frame_support::{ - StorageValue, construct_runtime, parameter_types, - traits::Randomness, - weights::Weight, -}; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use pallet_timestamp::Call as TimestampCall; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; /// An index to a block. pub type BlockNumber = u32; @@ -274,7 +268,7 @@ pub type SignedExtra = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment + pallet_transaction_payment::ChargeTransactionPayment, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; @@ -283,7 +277,8 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive, Runtime, AllModules>; +pub type Executive = + frame_executive::Executive, Runtime, AllModules>; impl_runtime_apis! { impl sp_api::Core for Runtime { diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index f41fd712e6771..e2ea253172179 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -100,7 +100,13 @@ fn prepare_votes( header: &Header, submitter: Option<&S::Submitter>, two_thirds_majority_transition: u64, -) -> Result<(BTreeMap, VecDeque<(H256, u64, Option, BTreeSet
)>), Error> { +) -> Result< + ( + BTreeMap, + VecDeque<(H256, u64, Option, BTreeSet
)>, + ), + Error, +> { // this fn can only work with single validators set if !validators.contains(&header.author) { return Err(Error::NotValidator); diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 14cb8f26a7fac..9b9f3e613cbf1 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -36,10 +36,7 @@ use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::verify_aura_header; use crate::{AuraConfiguration, Storage}; use primitives::{Header, Receipt, H256}; -use sp_std::{ - collections::btree_map::BTreeMap, - prelude::*, -}; +use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// Maximal number of headers behind best blocks that we are aiming to store. When there /// are too many unfinalized headers, it slows down finalization tracking significantly. @@ -89,7 +86,7 @@ pub fn import_headers( } } useful += 1; - }, + } Err(Error::AncientHeader) | Err(Error::KnownHeader) => useless += 1, Err(error) => return Err(error), } @@ -143,16 +140,14 @@ pub fn import_header( let total_difficulty = import_context.total_difficulty() + header.difficulty; let is_best = total_difficulty > best_total_difficulty; let header_number = header.number; - storage.insert_header( - import_context.into_import_header( - is_best, - hash, - header, - total_difficulty, - enacted_change, - scheduled_change, - ), - ); + storage.insert_header(import_context.into_import_header( + is_best, + hash, + header, + total_difficulty, + enacted_change, + scheduled_change, + )); // now mark finalized headers && prune old headers storage.finalize_headers( @@ -300,18 +295,18 @@ mod tests { let mut latest_block_hash = Default::default(); for i in 1..11 { let header = block_i(&storage, i, &validators); - let (rolling_last_block_hash, finalized_blocks) = - import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - Some(100), - header, - None, - ).unwrap(); + let (rolling_last_block_hash, finalized_blocks) = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(100), + header, + None, + ) + .unwrap(); match i { - 2 ..= 10 => assert_eq!( + 2..=10 => assert_eq!( finalized_blocks, vec![(i - 1, block_i(&storage, i - 1, &validators).hash(), Some(100))], "At {}", @@ -341,7 +336,8 @@ mod tests { Some(vec![crate::validators::tests::validators_change_recept( latest_block_hash, )]), - ).unwrap(); + ) + .unwrap(); assert_eq!( finalized_blocks, vec![(10, block_i(&storage, 10, &validators).hash(), Some(100))], @@ -366,20 +362,17 @@ mod tests { }; let header = signed_header(&validators, header, step as _); expected_blocks.push((i, header.hash(), Some(102))); - let (rolling_last_block_hash, finalized_blocks) = - import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - Some(102), - header, - None, - ).unwrap(); - assert_eq!( - finalized_blocks, - vec![], - ); + let (rolling_last_block_hash, finalized_blocks) = import_header( + &mut storage, + &kovan_aura_config(), + &validators_config, + 10, + Some(102), + header, + None, + ) + .unwrap(); + assert_eq!(finalized_blocks, vec![],); latest_block_hash = rolling_last_block_hash; step += 3; } @@ -406,7 +399,8 @@ mod tests { Some(103), header, None, - ).unwrap(); + ) + .unwrap(); assert_eq!(finalized_blocks, expected_blocks); assert_eq!(storage.oldest_unpruned_block(), 15); } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 5d28bfd074dca..9a3317c9731ee 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -36,12 +36,7 @@ use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage}; use primitives::{Address, Header, Receipt, H256, U256}; use sp_runtime::RuntimeDebug; -use sp_std::{ - prelude::*, - cmp::Ord, - collections::btree_map::BTreeMap, - iter::from_fn, -}; +use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, iter::from_fn, prelude::*}; use validators::{ValidatorsConfiguration, ValidatorsSource}; pub use import::{header_import_requires_receipts, import_header}; @@ -481,7 +476,10 @@ impl Storage for BridgeStorage { // ensure that unfinalized headers we want to prune do not have scheduled changes if number > finalized_number { if let Some(ref blocks_at_number) = blocks_at_number { - if blocks_at_number.iter().any(|block| ScheduledChanges::contains_key(block)) { + if blocks_at_number + .iter() + .any(|block| ScheduledChanges::contains_key(block)) + { HeadersByNumber::insert(number, blocks_at_number); OldestUnprunedBlock::put(number); return; @@ -776,7 +774,9 @@ pub(crate) mod tests { } fn header(&self, hash: &H256) -> Option<(Header, Option)> { - self.headers.get(hash).map(|header| (header.header.clone(), header.submitter.clone())) + self.headers + .get(hash) + .map(|header| (header.header.clone(), header.submitter.clone())) } fn import_context( diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index c0edd5e56d434..2104d7f21c687 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -198,10 +198,7 @@ mod tests { empty_step } - fn verify_with_config( - config: &AuraConfiguration, - header: &Header, - ) -> Result, Error> { + fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result, Error> { let storage = InMemoryStorage::new(genesis(), validators_addresses(3)); verify_aura_header(&storage, &config, None, header) } diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 2147922dc79b1..2efa99598c5fb 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -30,18 +30,13 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . +use crate::ethereum_sync_loop::MaybeConnectionError; +use crate::ethereum_types::{Header, HeaderId, Receipt, H256, U64}; use jsonrpsee::common::Params; -use jsonrpsee::raw::{ - RawClient, - RawClientError, -}; -use jsonrpsee::transport::http::{ - HttpTransportClient, RequestError -}; +use jsonrpsee::raw::{RawClient, RawClientError}; +use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; use serde::de::DeserializeOwned; use serde_json::{from_value, to_value}; -use crate::ethereum_sync_loop::MaybeConnectionError; -use crate::ethereum_types::{H256, Header, HeaderId, Receipt, U64}; /// Proof of hash serialization success. const HASH_SERIALIZATION_PROOF: &'static str = "hash serialization never fails; qed"; @@ -87,11 +82,7 @@ pub fn client(uri: &str) -> Client { /// Retrieve best known block number from Ethereum node. pub async fn best_block_number(client: Client) -> (Client, Result) { - let (client, result) = call_rpc::( - client, - "eth_blockNumber", - Params::None, - ).await; + let (client, result) = call_rpc::(client, "eth_blockNumber", Params::None).await; (client, result.map(|x| x.as_u64())) } @@ -104,11 +95,17 @@ pub async fn header_by_number(client: Client, number: u64) -> (Client, Result Ok(header), - false => Err(Error::IncompleteHeader), - })) + ) + .await; + ( + client, + header.and_then( + |header: Header| match header.number.is_some() && header.hash.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + }, + ), + ) } /// Retrieve block header by its hash from Ethereum node. @@ -120,11 +117,17 @@ pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result Ok(header), - false => Err(Error::IncompleteHeader), - })) + ) + .await; + ( + client, + header.and_then( + |header: Header| match header.number.is_none() && header.hash.is_none() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + }, + ), + ) } /// Retrieve transactions receipts for given block. @@ -151,16 +154,16 @@ async fn transaction_receipt(client: Client, hash: H256) -> (Client, Result( client, "eth_getTransactionReceipt", - Params::Array(vec![ - to_value(hash).expect(HASH_SERIALIZATION_PROOF), - ]), - ).await; - (client, receipt.and_then(|receipt| { - match receipt.gas_used.is_some() { + Params::Array(vec![to_value(hash).expect(HASH_SERIALIZATION_PROOF)]), + ) + .await; + ( + client, + receipt.and_then(|receipt| match receipt.gas_used.is_some() { true => Ok(receipt), false => Err(Error::IncompleteReceipt), - } - })) + }), + ) } /// Calls RPC on Ethereum node. diff --git a/relays/ethereum/src/ethereum_headers.rs b/relays/ethereum/src/ethereum_headers.rs index 1a3c110ad3414..0fbc73f83976b 100644 --- a/relays/ethereum/src/ethereum_headers.rs +++ b/relays/ethereum/src/ethereum_headers.rs @@ -30,12 +30,10 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . +use crate::ethereum_types::{Header, HeaderId, HeaderStatus, QueuedHeader, Receipt, H256}; use std::collections::{ - BTreeMap, HashMap, HashSet, - btree_map::Entry as BTreeMapEntry, - hash_map::Entry as HashMapEntry, + btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet, }; -use crate::ethereum_types::{H256, Header, HeaderId, HeaderStatus, QueuedHeader, Receipt}; type HeadersQueue = BTreeMap>; type KnownHeaders = BTreeMap>; @@ -79,9 +77,15 @@ impl QueuedHeaders { pub fn headers_in_status(&self, status: HeaderStatus) -> usize { match status { HeaderStatus::Unknown | HeaderStatus::Synced => return 0, - HeaderStatus::MaybeOrphan => self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeOrphan => self + .maybe_orphan + .values() + .fold(0, |total, headers| total + headers.len()), HeaderStatus::Orphan => self.orphan.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::MaybeReceipts => self.maybe_receipts.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeReceipts => self + .maybe_receipts + .values() + .fold(0, |total, headers| total + headers.len()), HeaderStatus::Receipts => self.receipts.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Ready => self.ready.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Submitted => self.submitted.values().fold(0, |total, headers| total + headers.len()), @@ -90,9 +94,14 @@ impl QueuedHeaders { /// Returns number of headers that are currently in the queue. pub fn total_headers(&self) -> usize { - self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()) + self.maybe_orphan + .values() + .fold(0, |total, headers| total + headers.len()) + self.orphan.values().fold(0, |total, headers| total + headers.len()) - + self.maybe_receipts.values().fold(0, |total, headers| total + headers.len()) + + self + .maybe_receipts + .values() + .fold(0, |total, headers| total + headers.len()) + self.receipts.values().fold(0, |total, headers| total + headers.len()) + self.ready.values().fold(0, |total, headers| total + headers.len()) } @@ -171,16 +180,19 @@ impl QueuedHeaders { HeaderStatus::Unknown | HeaderStatus::MaybeOrphan => { insert_header(&mut self.maybe_orphan, id, header); HeaderStatus::MaybeOrphan - }, + } HeaderStatus::Orphan => { insert_header(&mut self.orphan, id, header); HeaderStatus::Orphan } - HeaderStatus::MaybeReceipts | HeaderStatus::Receipts | HeaderStatus::Ready - | HeaderStatus::Submitted | HeaderStatus::Synced => { + HeaderStatus::MaybeReceipts + | HeaderStatus::Receipts + | HeaderStatus::Ready + | HeaderStatus::Submitted + | HeaderStatus::Synced => { insert_header(&mut self.maybe_receipts, id, header); HeaderStatus::MaybeReceipts - }, + } }; self.known_headers.entry(id.0).or_default().insert(id.1, status); @@ -202,10 +214,12 @@ impl QueuedHeaders { HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), HeaderStatus::Synced => break, - }.expect("header has a given status; given queue has the header; qed"); + } + .expect("header has a given status; given queue has the header; qed"); log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", current, HeaderStatus::Synced); - *self.known_headers + *self + .known_headers .entry(current.0) .or_default() .entry(current.1) @@ -215,7 +229,8 @@ impl QueuedHeaders { // remember that the header is synced log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", id, HeaderStatus::Synced); - *self.known_headers + *self + .known_headers .entry(id.0) .or_default() .entry(id.1) @@ -303,7 +318,7 @@ impl QueuedHeaders { if prune_border <= self.prune_border { return; } - + prune_queue(&mut self.maybe_orphan, prune_border); prune_queue(&mut self.orphan, prune_border); prune_queue(&mut self.maybe_receipts, prune_border); @@ -402,7 +417,10 @@ fn move_header_descendants( if current_parents.contains(&entry.get().header().parent_hash) { let header_to_move = entry.remove(); let header_to_move_id = header_to_move.id(); - known_headers.entry(header_to_move_id.0).or_default().insert(header_to_move_id.1, destination_status); + known_headers + .entry(header_to_move_id.0) + .or_default() + .insert(header_to_move_id.1, destination_status); headers_to_move.push((header_to_move_id, header_to_move)); log::debug!( @@ -438,7 +456,8 @@ fn oldest_header(queue: &HeadersQueue) -> Option<&QueuedHeader> { /// Return oldest headers from the queue until functor will return false. fn oldest_headers(queue: &HeadersQueue, mut f: impl FnMut(&QueuedHeader) -> bool) -> Option> { - let result = queue.values() + let result = queue + .values() .flat_map(|h| h.values()) .take_while(|h| f(h)) .collect::>(); @@ -490,11 +509,27 @@ pub(crate) mod tests { fn total_headers_works() { // total headers just sums up number of headers in every queue let mut queue = QueuedHeaders::default(); - queue.maybe_orphan.entry(1).or_default().insert(hash(1), Default::default()); - queue.maybe_orphan.entry(1).or_default().insert(hash(2), Default::default()); - queue.maybe_orphan.entry(2).or_default().insert(hash(3), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(1), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(2), Default::default()); + queue + .maybe_orphan + .entry(2) + .or_default() + .insert(hash(3), Default::default()); queue.orphan.entry(3).or_default().insert(hash(4), Default::default()); - queue.maybe_receipts.entry(4).or_default().insert(hash(5), Default::default()); + queue + .maybe_receipts + .entry(4) + .or_default() + .insert(hash(5), Default::default()); queue.ready.entry(5).or_default().insert(hash(6), Default::default()); assert_eq!(queue.total_headers(), 6); } @@ -503,21 +538,41 @@ pub(crate) mod tests { fn best_queued_number_works() { // initially there are headers in MaybeOrphan queue only let mut queue = QueuedHeaders::default(); - queue.maybe_orphan.entry(1).or_default().insert(hash(1), Default::default()); - queue.maybe_orphan.entry(1).or_default().insert(hash(2), Default::default()); - queue.maybe_orphan.entry(3).or_default().insert(hash(3), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(1), Default::default()); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(2), Default::default()); + queue + .maybe_orphan + .entry(3) + .or_default() + .insert(hash(3), Default::default()); assert_eq!(queue.best_queued_number(), 3); // and then there's better header in Orphan queue.orphan.entry(10).or_default().insert(hash(10), Default::default()); assert_eq!(queue.best_queued_number(), 10); // and then there's better header in MaybeReceipts - queue.maybe_receipts.entry(20).or_default().insert(hash(20), Default::default()); + queue + .maybe_receipts + .entry(20) + .or_default() + .insert(hash(20), Default::default()); assert_eq!(queue.best_queued_number(), 20); // and then there's better header in Ready queue.ready.entry(30).or_default().insert(hash(30), Default::default()); assert_eq!(queue.best_queued_number(), 30); // and then there's better header in MaybeOrphan again - queue.maybe_orphan.entry(40).or_default().insert(hash(40), Default::default()); + queue + .maybe_orphan + .entry(40) + .or_default() + .insert(hash(40), Default::default()); assert_eq!(queue.best_queued_number(), 40); } @@ -527,7 +582,11 @@ pub(crate) mod tests { let mut queue = QueuedHeaders::default(); assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); // and status is read from the KnownHeaders - queue.known_headers.entry(10).or_default().insert(hash(10), HeaderStatus::Ready); + queue + .known_headers + .entry(10) + .or_default() + .insert(hash(10), HeaderStatus::Ready); assert_eq!(queue.status(&id(10)), HeaderStatus::Ready); } @@ -536,50 +595,83 @@ pub(crate) mod tests { // initially we have oldest header #10 let mut queue = QueuedHeaders::default(); queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(100)); + assert_eq!( + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + hash(100) + ); // inserting #20 changes nothing queue.maybe_orphan.entry(20).or_default().insert(hash(1), header(101)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(100)); + assert_eq!( + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + hash(100) + ); // inserting #5 makes it oldest queue.maybe_orphan.entry(5).or_default().insert(hash(1), header(102)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), hash(102)); + assert_eq!( + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + hash(102) + ); } #[test] fn header_response_works() { // when parent is Synced, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Synced); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Synced); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is Ready, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Ready); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is Receipts, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Receipts); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Receipts); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is MaybeReceipts, we insert to MaybeReceipts let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeReceipts); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); // when parent is Orphan, we insert to Orphan let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Orphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Orphan); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); // when parent is MaybeOrphan, we insert to MaybeOrphan let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); @@ -599,15 +691,39 @@ pub(crate) mod tests { // #97 in Receipts // #96 in Ready let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue.known_headers.entry(99).or_default().insert(hash(99), HeaderStatus::Orphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(100) + .or_default() + .insert(hash(100), header(100)); + queue + .known_headers + .entry(99) + .or_default() + .insert(hash(99), HeaderStatus::Orphan); queue.orphan.entry(99).or_default().insert(hash(99), header(99)); - queue.known_headers.entry(98).or_default().insert(hash(98), HeaderStatus::MaybeReceipts); + queue + .known_headers + .entry(98) + .or_default() + .insert(hash(98), HeaderStatus::MaybeReceipts); queue.maybe_receipts.entry(98).or_default().insert(hash(98), header(98)); - queue.known_headers.entry(97).or_default().insert(hash(97), HeaderStatus::Receipts); + queue + .known_headers + .entry(97) + .or_default() + .insert(hash(97), HeaderStatus::Receipts); queue.receipts.entry(97).or_default().insert(hash(97), header(97)); - queue.known_headers.entry(96).or_default().insert(hash(96), HeaderStatus::Ready); + queue + .known_headers + .entry(96) + .or_default() + .insert(hash(96), HeaderStatus::Ready); queue.ready.entry(96).or_default().insert(hash(96), header(96)); queue.substrate_best_header_response(&id(100)); @@ -618,7 +734,10 @@ pub(crate) mod tests { assert!(queue.receipts.is_empty()); assert!(queue.ready.is_empty()); assert_eq!(queue.known_headers.len(), 5); - assert!(queue.known_headers.values().all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); + assert!(queue + .known_headers + .values() + .all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); } #[test] @@ -629,11 +748,27 @@ pub(crate) mod tests { // #102 in MaybeOrphan // #103 in Orphan let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Orphan); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Orphan); queue.orphan.entry(101).or_default().insert(hash(101), header(101)); - queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); - queue.known_headers.entry(103).or_default().insert(hash(103), HeaderStatus::Orphan); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(102) + .or_default() + .insert(hash(102), header(102)); + queue + .known_headers + .entry(103) + .or_default() + .insert(hash(103), HeaderStatus::Orphan); queue.orphan.entry(103).or_default().insert(hash(103), header(103)); queue.substrate_best_header_response(&id(100)); @@ -655,12 +790,32 @@ pub(crate) mod tests { // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: YES, #99 is known to the Substrate runtime let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Orphan); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(100) + .or_default() + .insert(hash(100), header(100)); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Orphan); queue.orphan.entry(101).or_default().insert(hash(101), header(101)); - queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(102) + .or_default() + .insert(hash(102), header(102)); queue.maybe_orphan_response(&id(99), true); // then all headers (#100..#103) are moved to the MaybeReceipts queue @@ -680,10 +835,26 @@ pub(crate) mod tests { // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: NO, #99 is NOT known to the Substrate runtime let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(101).or_default().insert(hash(101), header(101)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(100) + .or_default() + .insert(hash(100), header(100)); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(101) + .or_default() + .insert(hash(101), header(101)); queue.maybe_orphan_response(&id(99), false); // then all headers (#100..#101) are moved to the Orphan queue @@ -696,8 +867,16 @@ pub(crate) mod tests { #[test] fn positive_maybe_receipts_response_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(100).or_default().insert(hash(100), header(100)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeReceipts); + queue + .maybe_receipts + .entry(100) + .or_default() + .insert(hash(100), header(100)); queue.maybe_receipts_response(&id(100), true); assert!(queue.maybe_receipts.is_empty()); assert_eq!(queue.receipts.len(), 1); @@ -707,8 +886,16 @@ pub(crate) mod tests { #[test] fn negative_maybe_receipts_response_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(100).or_default().insert(hash(100), header(100)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::MaybeReceipts); + queue + .maybe_receipts + .entry(100) + .or_default() + .insert(hash(100), header(100)); queue.maybe_receipts_response(&id(100), false); assert!(queue.maybe_receipts.is_empty()); assert_eq!(queue.ready.len(), 1); @@ -718,7 +905,11 @@ pub(crate) mod tests { #[test] fn receipts_response_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Receipts); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Receipts); queue.receipts.entry(100).or_default().insert(hash(100), header(100)); queue.receipts_response(&id(100), Vec::new()); assert!(queue.receipts.is_empty()); @@ -729,7 +920,11 @@ pub(crate) mod tests { #[test] fn header_submitted_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Ready); queue.ready.entry(100).or_default().insert(hash(100), header(100)); queue.headers_submitted(vec![id(100)]); assert!(queue.ready.is_empty()); @@ -739,15 +934,43 @@ pub(crate) mod tests { #[test] fn prune_works() { let mut queue = QueuedHeaders::default(); - queue.known_headers.entry(104).or_default().insert(hash(104), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(104).or_default().insert(hash(104), header(104)); - queue.known_headers.entry(103).or_default().insert(hash(103), HeaderStatus::Orphan); + queue + .known_headers + .entry(104) + .or_default() + .insert(hash(104), HeaderStatus::MaybeOrphan); + queue + .maybe_orphan + .entry(104) + .or_default() + .insert(hash(104), header(104)); + queue + .known_headers + .entry(103) + .or_default() + .insert(hash(103), HeaderStatus::Orphan); queue.orphan.entry(103).or_default().insert(hash(103), header(103)); - queue.known_headers.entry(102).or_default().insert(hash(102), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(102).or_default().insert(hash(102), header(102)); - queue.known_headers.entry(101).or_default().insert(hash(101), HeaderStatus::Receipts); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::MaybeReceipts); + queue + .maybe_receipts + .entry(102) + .or_default() + .insert(hash(102), header(102)); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Receipts); queue.receipts.entry(101).or_default().insert(hash(101), header(101)); - queue.known_headers.entry(100).or_default().insert(hash(100), HeaderStatus::Ready); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Ready); queue.ready.entry(100).or_default().insert(hash(100), header(100)); queue.prune(102); diff --git a/relays/ethereum/src/ethereum_sync.rs b/relays/ethereum/src/ethereum_sync.rs index 5819c5f0bb893..9c2834c1ae791 100644 --- a/relays/ethereum/src/ethereum_sync.rs +++ b/relays/ethereum/src/ethereum_sync.rs @@ -30,11 +30,11 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use codec::Encode; use crate::ethereum_headers::QueuedHeaders; -use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; use crate::ethereum_sync_loop::EthereumSyncParams; +use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; +use codec::Encode; /// Ethereum headers synchronization context. #[derive(Debug)] @@ -63,7 +63,8 @@ impl HeadersSync { /// Returns true if we have synced almost all known headers. pub fn is_almost_synced(&self) -> bool { match self.target_header_number { - Some(target_header_number) => self.best_header + Some(target_header_number) => self + .best_header .map(|best| target_header_number.saturating_sub(best.0) < 4) .unwrap_or(false), None => true, @@ -100,10 +101,7 @@ impl HeadersSync { } // we assume that there were no reorgs if we have already downloaded best header - let best_downloaded_number = std::cmp::max( - self.headers.best_queued_number(), - best_header.0, - ); + let best_downloaded_number = std::cmp::max(self.headers.best_queued_number(), best_header.0); if best_downloaded_number == target_header_number { return None; } @@ -115,7 +113,9 @@ impl HeadersSync { /// Select headers that need to be submitted to the Substrate node. pub fn select_headers_to_submit(&self) -> Option> { let headers_in_submit_status = self.headers.headers_in_status(HeaderStatus::Submitted); - let headers_to_submit_count = self.params.max_headers_in_submitted_status + let headers_to_submit_count = self + .params + .max_headers_in_submitted_status .checked_sub(headers_in_submit_status)?; let mut total_size = 0; @@ -129,7 +129,8 @@ impl HeadersSync { } let encoded_size = into_substrate_ethereum_header(header.header()).encode().len() - + into_substrate_ethereum_receipts(header.receipts()).map(|receipts| receipts.encode().len()) + + into_substrate_ethereum_receipts(header.receipts()) + .map(|receipts| receipts.encode().len()) .unwrap_or(0); if total_headers != 0 && total_size + encoded_size > self.params.max_headers_size_in_single_submit { return false; @@ -162,7 +163,8 @@ impl HeadersSync { self.headers.substrate_best_header_response(&best_header); // prune ancient headers - self.headers.prune(best_header.0.saturating_sub(self.params.prune_depth)); + self.headers + .prune(best_header.0.saturating_sub(self.params.prune_depth)); // finally remember the best header itself self.best_header = Some(best_header); @@ -180,9 +182,9 @@ impl HeadersSync { #[cfg(test)] mod tests { - use crate::ethereum_headers::tests::{header, id}; - use crate::ethereum_types::{H256, HeaderStatus}; use super::*; + use crate::ethereum_headers::tests::{header, id}; + use crate::ethereum_types::{HeaderStatus, H256}; fn side_hash(number: u64) -> H256 { H256::from_low_u64_le(1000 + number) diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 1540edd78f445..6f61b423d29cb 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -30,10 +30,10 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -use futures::{future::FutureExt, stream::StreamExt}; use crate::ethereum_client; use crate::ethereum_types::HeaderStatus as EthereumHeaderStatus; use crate::substrate_client; +use futures::{future::FutureExt, stream::StreamExt}; // TODO: when SharedClient will be available, switch to Substrate headers subscription // (because we do not need old Substrate headers) @@ -98,7 +98,10 @@ impl std::fmt::Debug for EthereumSyncParams { .field("max_future_headers_to_download", &self.max_future_headers_to_download) .field("max_headers_in_submitted_status", &self.max_headers_in_submitted_status) .field("max_headers_in_single_submit", &self.max_headers_in_single_submit) - .field("max_headers_size_in_single_submit", &self.max_headers_size_in_single_submit) + .field( + "max_headers_size_in_single_submit", + &self.max_headers_size_in_single_submit, + ) .field("prune_depth", &self.prune_depth) .finish() } @@ -136,9 +139,7 @@ pub fn run(params: EthereumSyncParams) { let mut eth_maybe_client = None; let mut eth_best_block_number_required = false; - let eth_best_block_number_future = ethereum_client::best_block_number( - ethereum_client::client(ð_uri) - ).fuse(); + let eth_best_block_number_future = ethereum_client::best_block_number(ethereum_client::client(ð_uri)).fuse(); let eth_new_header_future = futures::future::Fuse::terminated(); let eth_orphan_header_future = futures::future::Fuse::terminated(); let eth_receipts_future = futures::future::Fuse::terminated(); @@ -147,9 +148,8 @@ pub fn run(params: EthereumSyncParams) { let mut sub_maybe_client = None; let mut sub_best_block_required = false; - let sub_best_block_future = substrate_client::best_ethereum_block( - substrate_client::client(&sub_uri, sub_signer), - ).fuse(); + let sub_best_block_future = + substrate_client::best_ethereum_block(substrate_client::client(&sub_uri, sub_signer)).fuse(); let sub_receipts_check_future = futures::future::Fuse::terminated(); let sub_existence_status_future = futures::future::Fuse::terminated(); let sub_submit_header_future = futures::future::Fuse::terminated(); @@ -326,7 +326,7 @@ pub fn run(params: EthereumSyncParams) { // 2) check transactions receipts - it stops us from downloading/submitting new blocks; // 3) check existence - it stops us from submitting new blocks; // 4) submit header - + if sub_best_block_required { log::debug!(target: "bridge", "Asking Substrate about best block"); sub_best_block_future.set(substrate_client::best_ethereum_block(sub_client).fuse()); @@ -338,9 +338,8 @@ pub fn run(params: EthereumSyncParams) { ); let header = header.clone(); - sub_receipts_check_future.set( - substrate_client::ethereum_receipts_required(sub_client, header).fuse() - ); + sub_receipts_check_future + .set(substrate_client::ethereum_receipts_required(sub_client, header).fuse()); } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::MaybeOrphan) { // for MaybeOrphan we actually ask for parent' header existence let parent_id = header.parent_id(); @@ -351,9 +350,8 @@ pub fn run(params: EthereumSyncParams) { parent_id, ); - sub_existence_status_future.set( - substrate_client::ethereum_header_known(sub_client, parent_id).fuse(), - ); + sub_existence_status_future + .set(substrate_client::ethereum_header_known(sub_client, parent_id).fuse()); } else if let Some(headers) = eth_sync.select_headers_to_submit() { let ids = match headers.len() { 1 => format!("{:?}", headers[0].id()), @@ -368,9 +366,7 @@ pub fn run(params: EthereumSyncParams) { ); let headers = headers.into_iter().cloned().collect(); - sub_submit_header_future.set( - substrate_client::submit_ethereum_headers(sub_client, headers).fuse(), - ); + sub_submit_header_future.set(substrate_client::submit_ethereum_headers(sub_client, headers).fuse()); // remember that we have submitted some headers if stall_countdown.is_none() { @@ -400,11 +396,8 @@ pub fn run(params: EthereumSyncParams) { id, ); eth_receipts_future.set( - ethereum_client::transactions_receipts( - eth_client, - id, - header.header().transactions.clone(), - ).fuse() + ethereum_client::transactions_receipts(eth_client, id, header.header().transactions.clone()) + .fuse(), ); } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::Orphan) { // for Orphan we actually ask for parent' header @@ -416,9 +409,7 @@ pub fn run(params: EthereumSyncParams) { parent_id, ); - eth_orphan_header_future.set( - ethereum_client::header_by_hash(eth_client, parent_id.1).fuse(), - ); + eth_orphan_header_future.set(ethereum_client::header_by_hash(eth_client, parent_id.1).fuse()); } else if let Some(id) = eth_sync.select_new_header_to_download() { log::debug!( target: "bridge", @@ -426,9 +417,7 @@ pub fn run(params: EthereumSyncParams) { id, ); - eth_new_header_future.set( - ethereum_client::header_by_number(eth_client, id).fuse(), - ); + eth_new_header_future.set(ethereum_client::header_by_number(eth_client, id).fuse()); } else { eth_maybe_client = Some(eth_client); } @@ -469,7 +458,10 @@ async fn delay(timeout_ms: u64, retval: T) -> T { } fn interval(timeout_ms: u64) -> impl futures::Stream { - futures::stream::unfold((), move |_| async move { delay(timeout_ms, ()).await; Some(((), ())) }) + futures::stream::unfold((), move |_| async move { + delay(timeout_ms, ()).await; + Some(((), ())) + }) } fn process_future_result( @@ -488,7 +480,7 @@ fn process_future_result( Ok(result) => { *maybe_client = Some(client); on_success(result); - }, + } Err(error) => { if error.is_connection_error() { go_offline_future.set(go_offline(client).fuse()); @@ -497,6 +489,6 @@ fn process_future_result( } log::error!(target: "bridge", "{}: {:?}", error_pattern, error); - }, + } } } diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index cd61ac01b3712..a83c4b666bf6d 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -52,7 +52,10 @@ pub struct HeaderId(pub u64, pub H256); impl From<&Header> for HeaderId { fn from(header: &Header) -> HeaderId { - HeaderId(header.number.expect(HEADER_ID_PROOF).as_u64(), header.hash.expect(HEADER_ID_PROOF)) + HeaderId( + header.number.expect(HEADER_ID_PROOF).as_u64(), + header.hash.expect(HEADER_ID_PROOF), + ) } } diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index eee802a004cd8..583faf08c90c8 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -30,7 +30,7 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -#![recursion_limit="1024"] +#![recursion_limit = "1024"] mod ethereum_client; mod ethereum_headers; @@ -40,8 +40,8 @@ mod ethereum_types; mod substrate_client; mod substrate_types; -use std::io::Write; use sp_core::crypto::Pair; +use std::io::Write; fn main() { initialize(); @@ -51,7 +51,7 @@ fn main() { Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); return; - }, + } }); } @@ -66,8 +66,8 @@ fn initialize() { builder.parse_filters(&filters); builder.format(move |buf, record| { writeln!(buf, "{}", { - let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()) - .expect("Time is incorrectly formatted"); + let timestamp = + time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).expect("Time is incorrectly formatted"); if cfg!(windows) { format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) } else { @@ -79,11 +79,13 @@ fn initialize() { log::Level::Debug => Color::Fixed(14).paint(record.level().to_string()), log::Level::Trace => Color::Fixed(12).paint(record.level().to_string()), }; - format!("{} {} {} {}" - , Color::Fixed(8).bold().paint(timestamp) - , log_level - , Color::Fixed(8).paint(record.target()) - , record.args()) + format!( + "{} {} {} {}", + Color::Fixed(8).bold().paint(timestamp), + log_level, + Color::Fixed(8).paint(record.target()), + record.args() + ) } }) }); @@ -110,8 +112,8 @@ fn ethereum_sync_params() -> Result. -use codec::{Encode, Decode}; +use crate::ethereum_sync_loop::MaybeConnectionError; +use crate::ethereum_types::{Bytes, HeaderId as EthereumHeaderId, QueuedHeader as QueuedEthereumHeader, H256}; +use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts, TransactionHash}; +use codec::{Decode, Encode}; use jsonrpsee::common::Params; -use jsonrpsee::raw::{ - RawClient, RawClientError -}; -use jsonrpsee::transport::http::{ - HttpTransportClient, RequestError -}; +use jsonrpsee::raw::{RawClient, RawClientError}; +use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; use serde_json::{from_value, to_value}; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; -use crate::ethereum_sync_loop::MaybeConnectionError; -use crate::ethereum_types::{ - Bytes, - H256, - HeaderId as EthereumHeaderId, - QueuedHeader as QueuedEthereumHeader, -}; -use crate::substrate_types::{ - TransactionHash, - into_substrate_ethereum_header, - into_substrate_ethereum_receipts, -}; /// Substrate client type. pub struct Client { @@ -105,7 +92,8 @@ pub async fn best_ethereum_block(client: Client) -> (Client, Result nonce, Err(err) => return (client, Err(err)), }; - let transaction = create_submit_transaction( - headers, - &client.signer, - nonce, - genesis_hash, - ); + let transaction = create_submit_transaction(headers, &client.signer, nonce, genesis_hash); let encoded_transaction = transaction.encode(); let (client, transaction_hash) = call_rpc( client, "author_submitExtrinsic", - Params::Array(vec![ - to_value(Bytes(encoded_transaction)).unwrap(), - ]), - ).await; + Params::Array(vec![to_value(Bytes(encoded_transaction)).unwrap()]), + ) + .await; (client, transaction_hash.map(|transaction_hash| (transaction_hash, ids))) } @@ -197,10 +184,9 @@ async fn block_hash_by_number(client: Client, number: u64) -> (Client, Result

( - mut client: Client, - method: &'static str, - params: Params, -) -> (Client, Result) { - async fn do_call_rpc( - client: &mut Client, - method: &'static str, - params: Params, - ) -> Result { +async fn call_rpc(mut client: Client, method: &'static str, params: Params) -> (Client, Result) { + async fn do_call_rpc(client: &mut Client, method: &'static str, params: Params) -> Result { let request_id = client .rpc_client .start_request(method, params) @@ -253,16 +230,8 @@ async fn call_rpc( } /// Calls RPC on Substrate node that returns u64. -async fn call_rpc_u64( - mut client: Client, - method: &'static str, - params: Params, -) -> (Client, Result) { - async fn do_call_rpc( - client: &mut Client, - method: &'static str, - params: Params, - ) -> Result { +async fn call_rpc_u64(mut client: Client, method: &'static str, params: Params) -> (Client, Result) { + async fn do_call_rpc(client: &mut Client, method: &'static str, params: Params) -> Result { let request_id = client .rpc_client .start_request(method, params) @@ -290,20 +259,18 @@ fn create_submit_transaction( index: node_primitives::Index, genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { - let function = bridge_node_runtime::Call::BridgeEthPoA( - bridge_node_runtime::BridgeEthPoACall::import_headers( - headers - .into_iter() - .map(|header| { - let (header, receipts) = header.extract(); - ( - into_substrate_ethereum_header(&header), - into_substrate_ethereum_receipts(&receipts), - ) - }) - .collect(), - ), - ); + let function = bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_headers( + headers + .into_iter() + .map(|header| { + let (header, receipts) = header.extract(); + ( + into_substrate_ethereum_header(&header), + into_substrate_ethereum_receipts(&receipts), + ) + }) + .collect(), + )); let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( @@ -331,10 +298,5 @@ fn create_submit_transaction( let signer: sp_runtime::MultiSigner = signer.public().into(); let (function, extra, _) = raw_payload.deconstruct(); - bridge_node_runtime::UncheckedExtrinsic::new_signed( - function, - signer.into_account().into(), - signature.into(), - extra, - ) + bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account().into(), signature.into(), extra) } diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 62b28e47358c1..fd1f07e693282 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -30,17 +30,14 @@ // You should have received a copy of the GNU General Public License // along with Parity-Bridge. If not, see . -pub use sp_bridge_eth_poa::{ - Address, Bloom, Bytes, H256, Header as SubstrateEthereumHeader, - LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, - TransactionOutcome as SubstrateEthereumTransactionOutcome, U256, -}; pub use crate::ethereum_types::H256 as TransactionHash; use crate::ethereum_types::{ - HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, + Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, RECEIPT_GAS_USED_PROOF as ETHEREUM_RECEIPT_GAS_USED_PROOF, - Header as EthereumHeader, - Receipt as EthereumReceipt, +}; +pub use sp_bridge_eth_poa::{ + Address, Bloom, Bytes, Header as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, + Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, }; /// Convert Ethereum header into Ethereum header for Substrate. @@ -67,18 +64,27 @@ pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEther pub fn into_substrate_ethereum_receipts( receipts: &Option>, ) -> Option> { - receipts.as_ref().map(|receipts| receipts.iter().map(|receipt| SubstrateEthereumReceipt { - gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), - log_bloom: receipt.logs_bloom.data().into(), - logs: receipt.logs.iter().map(|log_entry| SubstrateEthereumLogEntry { - address: log_entry.address, - topics: log_entry.topics.clone(), - data: log_entry.data.0.clone(), - }).collect(), - outcome: match (receipt.status, receipt.root) { - (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), - (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), - _ => SubstrateEthereumTransactionOutcome::Unknown, - }, - }).collect()) + receipts.as_ref().map(|receipts| { + receipts + .iter() + .map(|receipt| SubstrateEthereumReceipt { + gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), + log_bloom: receipt.logs_bloom.data().into(), + logs: receipt + .logs + .iter() + .map(|log_entry| SubstrateEthereumLogEntry { + address: log_entry.address, + topics: log_entry.topics.clone(), + data: log_entry.data.0.clone(), + }) + .collect(), + outcome: match (receipt.status, receipt.root) { + (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), + (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), + _ => SubstrateEthereumTransactionOutcome::Unknown, + }, + }) + .collect() + }) } diff --git a/relays/substrate/src/bridge.rs b/relays/substrate/src/bridge.rs index 044f4606d8917..c203e85a2e29e 100644 --- a/relays/substrate/src/bridge.rs +++ b/relays/substrate/src/bridge.rs @@ -15,22 +15,27 @@ // along with Parity Bridges Common. If not, see . use crate::error::Error; +use crate::params::{Params, RPCUrlParam}; use crate::rpc::{self, SubstrateRPC}; -use crate::params::{RPCUrlParam, Params}; -use futures::{prelude::*, channel::{mpsc, oneshot}, future, select}; +use futures::{ + channel::{mpsc, oneshot}, + future, + prelude::*, + select, +}; use jsonrpsee::{ raw::client::{RawClient, RawClientError, RawClientEvent, RawClientRequestId, RawClientSubscription}, transport::{ + ws::{WsConnecError, WsTransportClient}, TransportClient, - ws::{WsTransportClient, WsConnecError}, }, }; use node_primitives::{Hash, Header}; +use sp_core::Bytes; use std::cell::RefCell; use std::collections::HashMap; use std::pin::Pin; -use sp_core::Bytes; type ChainId = Hash; @@ -71,24 +76,25 @@ async fn init_rpc_connection(url: &RPCUrlParam) -> Result { let genesis_hash = rpc::genesis_block_hash(&mut client) .await .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| Error::InvalidChainState(format!( - "chain with RPC URL {} is missing a genesis block hash", - url_str, - )))?; + .ok_or_else(|| { + Error::InvalidChainState(format!( + "chain with RPC URL {} is missing a genesis block hash", + url_str, + )) + })?; let latest_finalized_hash = SubstrateRPC::chain_finalized_head(&mut client) .await .map_err(|e| Error::RPCError(e.to_string()))?; - let latest_finalized_header = SubstrateRPC::chain_header( - &mut client, - Some(latest_finalized_hash) - ) + let latest_finalized_header = SubstrateRPC::chain_header(&mut client, Some(latest_finalized_hash)) .await .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| Error::InvalidChainState(format!( - "chain {} is missing header for finalized block hash {}", - genesis_hash, latest_finalized_hash - )))?; + .ok_or_else(|| { + Error::InvalidChainState(format!( + "chain {} is missing header for finalized block hash {}", + genesis_hash, latest_finalized_hash + )) + })?; let (sender, receiver) = mpsc::channel(0); @@ -101,41 +107,35 @@ async fn init_rpc_connection(url: &RPCUrlParam) -> Result { state: ChainState { current_finalized_head: latest_finalized_header, bridges: HashMap::new(), - } + }, }) } /// Returns IDs of the bridged chains. -async fn read_bridges(chain: &mut Chain, chain_ids: &[Hash]) - -> Result, Error> -{ +async fn read_bridges(chain: &mut Chain, chain_ids: &[Hash]) -> Result, Error> { // This should make an RPC call to read this information from the bridge pallet state. // For now, just pretend every chain is bridged to every other chain. // // TODO: The correct thing. - Ok( - chain_ids - .iter() - .cloned() - .filter(|&chain_id| chain_id != chain.genesis_hash) - .collect() - ) + Ok(chain_ids + .iter() + .cloned() + .filter(|&chain_id| chain_id != chain.genesis_hash) + .collect()) } -pub async fn run_async( - params: Params, - exit: Box + Unpin + Send> -) -> Result<(), Error> -{ +pub async fn run_async(params: Params, exit: Box + Unpin + Send>) -> Result<(), Error> { let chains = init_chains(¶ms).await?; - let (chain_tasks, exit_signals) = chains.into_iter() + let (chain_tasks, exit_signals) = chains + .into_iter() .map(|(chain_id, chain_cell)| { let chain = chain_cell.into_inner(); let (task_exit_signal, task_exit_receiver) = oneshot::channel(); - let task_exit = Box::new(task_exit_receiver.map(|result| { - result.expect("task_exit_signal is not dropped before send() is called") - })); + let task_exit = Box::new( + task_exit_receiver + .map(|result| result.expect("task_exit_signal is not dropped before send() is called")), + ); let chain_task = async_std::task::spawn(async move { if let Err(err) = chain_task(chain_id, chain, task_exit).await { log::error!("Error in task for chain {}: {}", chain_id, err); @@ -156,39 +156,43 @@ pub async fn run_async( Ok(()) } -fn initial_next_events<'a>(chains: &'a HashMap>) - -> Vec> + 'a>>> -{ - chains.values() +fn initial_next_events<'a>( + chains: &'a HashMap>, +) -> Vec> + 'a>>> { + chains + .values() .map(|chain_cell| async move { let mut chain = chain_cell.borrow_mut(); - let event = chain.client.next_event() + let event = chain + .client + .next_event() .await .map_err(|err| Error::RPCError(err.to_string()))?; Ok((chain.genesis_hash, event)) }) - .map(|fut| Box::pin(fut) as Pin>>) + .map(|fut| Box::pin(fut) as Pin>>) .collect() } async fn next_event<'a>( - next_events: Vec> + 'a>>>, + next_events: Vec> + 'a>>>, chains: &'a HashMap>, -) - -> ( - Result<(Hash, RawClientEvent), Error>, - Vec> +'a>>> - ) -{ +) -> ( + Result<(Hash, RawClientEvent), Error>, + Vec> + 'a>>>, +) { let (result, _, mut rest) = future::select_all(next_events).await; match result { Ok((chain_id, _)) => { let fut = async move { - let chain_cell = chains.get(&chain_id) + let chain_cell = chains + .get(&chain_id) .expect("chain must be in the map as a function precondition; qed"); let mut chain = chain_cell.borrow_mut(); - let event = chain.client.next_event() + let event = chain + .client + .next_event() .await .map_err(|err| Error::RPCError(err.to_string()))?; Ok((chain_id, event)) @@ -209,9 +213,7 @@ async fn init_chains(params: &Params) -> Result> .collect::, _>>()?; // TODO: Remove when read_bridges is implemented correctly. - let chain_ids = chains.keys() - .cloned() - .collect::>(); + let chain_ids = chains.keys().cloned().collect::>(); // let chain_ids_slice = chain_ids.as_slice(); for (&chain_id, chain_cell) in chains.iter() { @@ -229,15 +231,18 @@ async fn init_chains(params: &Params) -> Result> let genesis_head = SubstrateRPC::chain_header(&mut chain.client, chain_id) .await .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| Error::InvalidChainState(format!( - "chain {} is missing a genesis block header", chain_id - )))?; + .ok_or_else(|| { + Error::InvalidChainState(format!("chain {} is missing a genesis block header", chain_id)) + })?; let channel = chain.sender.clone(); - chain.state.bridges.insert(bridged_chain_id, BridgeState { - channel, - locally_finalized_head_on_bridged_chain: genesis_head, - }); + chain.state.bridges.insert( + bridged_chain_id, + BridgeState { + channel, + locally_finalized_head_on_bridged_chain: genesis_head, + }, + ); // The conditional ensures that we don't log twice per pair of chains. if chain_id.as_ref() < bridged_chain_id.as_ref() { @@ -250,28 +255,25 @@ async fn init_chains(params: &Params) -> Result> Ok(chains) } -async fn setup_subscriptions(chain: &mut Chain) - -> Result<(RawClientRequestId, RawClientRequestId), RawClientError> -{ - let new_heads_subscription_id = chain.client - .start_subscription( - "chain_subscribeNewHeads", - jsonrpsee::common::Params::None, - ) +async fn setup_subscriptions( + chain: &mut Chain, +) -> Result<(RawClientRequestId, RawClientRequestId), RawClientError> { + let new_heads_subscription_id = chain + .client + .start_subscription("chain_subscribeNewHeads", jsonrpsee::common::Params::None) .await .map_err(RawClientError::Inner)?; - let finalized_heads_subscription_id = chain.client - .start_subscription( - "chain_subscribeFinalizedHeads", - jsonrpsee::common::Params::None, - ) + let finalized_heads_subscription_id = chain + .client + .start_subscription("chain_subscribeFinalizedHeads", jsonrpsee::common::Params::None) .await .map_err(RawClientError::Inner)?; - let new_heads_subscription = - chain.client.subscription_by_id(new_heads_subscription_id) - .expect("subscription_id was returned from start_subscription above; qed"); + let new_heads_subscription = chain + .client + .subscription_by_id(new_heads_subscription_id) + .expect("subscription_id was returned from start_subscription above; qed"); let new_heads_subscription = match new_heads_subscription { RawClientSubscription::Active(_) => {} RawClientSubscription::Pending(subscription) => { @@ -279,9 +281,10 @@ async fn setup_subscriptions(chain: &mut Chain) } }; - let finalized_heads_subscription = - chain.client.subscription_by_id(finalized_heads_subscription_id) - .expect("subscription_id was returned from start_subscription above; qed"); + let finalized_heads_subscription = chain + .client + .subscription_by_id(finalized_heads_subscription_id) + .expect("subscription_id was returned from start_subscription above; qed"); let finalized_heads_subscription = match finalized_heads_subscription { RawClientSubscription::Active(subscription) => {} RawClientSubscription::Pending(subscription) => { @@ -298,27 +301,26 @@ async fn handle_rpc_event( event: RawClientEvent, new_heads_subscription_id: RawClientRequestId, finalized_heads_subscription_id: RawClientRequestId, -) -> Result<(), Error> -{ +) -> Result<(), Error> { match event { - RawClientEvent::SubscriptionNotif { request_id, result } => + RawClientEvent::SubscriptionNotif { request_id, result } => { if request_id == new_heads_subscription_id { - let header: Header = serde_json::from_value(result) - .map_err(Error::SerializationError)?; + let header: Header = serde_json::from_value(result).map_err(Error::SerializationError)?; log::info!("Received new head {:?} on chain {}", header, chain_id); } else if request_id == finalized_heads_subscription_id { - let header: Header = serde_json::from_value(result) - .map_err(Error::SerializationError)?; + let header: Header = serde_json::from_value(result).map_err(Error::SerializationError)?; log::info!("Received finalized head {:?} on chain {}", header, chain_id); // let old_finalized_head = chain_state.current_finalized_head; chain.state.current_finalized_head = header; for (bridged_chain_id, bridged_chain) in chain.state.bridges.iter_mut() { - if bridged_chain.locally_finalized_head_on_bridged_chain.number < - chain.state.current_finalized_head.number { + if bridged_chain.locally_finalized_head_on_bridged_chain.number + < chain.state.current_finalized_head.number + { // Craft and submit an extrinsic over RPC log::info!("Sending command to submit extrinsic to chain {}", chain_id); - let mut send_event = bridged_chain.channel + let mut send_event = bridged_chain + .channel .send(Event::SubmitExtrinsic(Bytes(Vec::new()))) .fuse(); @@ -343,12 +345,17 @@ async fn handle_rpc_event( } } else { return Err(Error::RPCError(format!( - "unexpected subscription response with request ID {:?}", request_id + "unexpected subscription response with request ID {:?}", + request_id ))); - }, - _ => return Err(Error::RPCError(format!( - "unexpected RPC event from chain {}: {:?}", chain_id, event - ))), + } + } + _ => { + return Err(Error::RPCError(format!( + "unexpected RPC event from chain {}: {:?}", + chain_id, event + ))) + } } Ok(()) } @@ -358,8 +365,7 @@ async fn handle_bridge_event( chain_id: ChainId, rpc_client: &mut RawClient, event: Event, -) -> Result<(), Error> -{ +) -> Result<(), Error> { match event { Event::SubmitExtrinsic(data) => { log::info!("Submitting extrinsic to chain {}", chain_id); @@ -374,13 +380,11 @@ async fn handle_bridge_event( async fn chain_task( chain_id: ChainId, mut chain: Chain, - exit: impl Future + Unpin + Send -) -> Result<(), Error> -{ - let (new_heads_subscription_id, finalized_heads_subscription_id) = - setup_subscriptions(&mut chain) - .await - .map_err(|e| Error::RPCError(e.to_string()))?; + exit: impl Future + Unpin + Send, +) -> Result<(), Error> { + let (new_heads_subscription_id, finalized_heads_subscription_id) = setup_subscriptions(&mut chain) + .await + .map_err(|e| Error::RPCError(e.to_string()))?; let mut exit = exit.fuse(); loop { diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 7443c6bebc932..7185313a57114 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -22,8 +22,8 @@ mod rpc; use bridge::run_async; use params::{Params, RPCUrlParam}; -use clap::{App, Arg, value_t, values_t}; -use futures::{prelude::*, channel}; +use clap::{value_t, values_t, App, Arg}; +use futures::{channel, prelude::*}; use std::cell::Cell; use std::process; @@ -32,9 +32,7 @@ fn main() { env_logger::init(); let exit = setup_exit_handler(); - let result = async_std::task::block_on(async move { - run_async(params, exit).await - }); + let result = async_std::task::block_on(async move { run_async(params, exit).await }); if let Err(err) = result { log::error!("{}", err); process::exit(1); @@ -60,22 +58,17 @@ fn parse_args() -> Params { .value_name("HOST[:PORT]") .help("The URL of a bridged Substrate node") .takes_value(true) - .multiple(true) + .multiple(true), ) .get_matches(); - let base_path = value_t!(matches, "base-path", String) - .unwrap_or_else(|e| e.exit()); - let rpc_urls = values_t!(matches, "rpc-url", RPCUrlParam) - .unwrap_or_else(|e| e.exit()); + let base_path = value_t!(matches, "base-path", String).unwrap_or_else(|e| e.exit()); + let rpc_urls = values_t!(matches, "rpc-url", RPCUrlParam).unwrap_or_else(|e| e.exit()); - Params { - base_path, - rpc_urls, - } + Params { base_path, rpc_urls } } -fn setup_exit_handler() -> Box + Unpin + Send> { +fn setup_exit_handler() -> Box + Unpin + Send> { let (exit_sender, exit_receiver) = channel::oneshot::channel(); let exit_sender = Cell::new(Some(exit_sender)); @@ -86,11 +79,11 @@ fn setup_exit_handler() -> Box + Unpin + Send> { } } }) - .expect("must be able to set Ctrl-C handler"); + .expect("must be able to set Ctrl-C handler"); - Box::new(exit_receiver.map(|result| { - result.expect( - "exit_sender cannot be dropped as it is moved into a globally-referenced closure" - ) - })) + Box::new( + exit_receiver.map(|result| { + result.expect("exit_sender cannot be dropped as it is moved into a globally-referenced closure") + }), + ) } diff --git a/relays/substrate/src/params.rs b/relays/substrate/src/params.rs index 2b2e81321d411..3129c920e8140 100644 --- a/relays/substrate/src/params.rs +++ b/relays/substrate/src/params.rs @@ -16,8 +16,8 @@ use crate::error::Error; -use url::Url; use std::str::FromStr; +use url::Url; const DEFAULT_WS_PORT: u16 = 9944; @@ -42,8 +42,8 @@ impl FromStr for RPCUrlParam { type Err = Error; fn from_str(url_str: &str) -> Result { - let mut url = Url::parse(url_str) - .map_err(|e| Error::UrlError(format!("could not parse {}: {}", url_str, e)))?; + let mut url = + Url::parse(url_str).map_err(|e| Error::UrlError(format!("could not parse {}: {}", url_str, e)))?; if url.scheme() != "ws" { return Err(Error::UrlError(format!("must have scheme ws, found {}", url.scheme()))); diff --git a/relays/substrate/src/rpc.rs b/relays/substrate/src/rpc.rs index 38e751ce89a26..10e41907f7654 100644 --- a/relays/substrate/src/rpc.rs +++ b/relays/substrate/src/rpc.rs @@ -41,8 +41,8 @@ jsonrpsee::rpc_api! { } } -pub async fn genesis_block_hash(client: &mut RawClient) - -> Result, RawClientError> -{ +pub async fn genesis_block_hash( + client: &mut RawClient, +) -> Result, RawClientError> { SubstrateRPC::chain_block_hash(client, Some(NumberOrHex::Number(0))).await } From fd28c4f6a4af62425506dac7317377dfeddabbc2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2020 03:05:43 +0000 Subject: [PATCH 0019/1210] Bump parking_lot from 0.9.0 to 0.10.0 (#40) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index a58f89e5c2bd6..df7941e8af518 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } linked-hash-map = "0.5.2" log = "0.4.8" -parking_lot = "0.9.0" +parking_lot = "0.10.0" rustc-hex = "2.0.1" serde = { version = "1.0.40", features = ["derive"] } serde_json = "1.0.40" From 861723aa6b1d5c0569f6c5160703913ff7f79b85 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2020 03:37:00 +0000 Subject: [PATCH 0020/1210] Bump structopt from 0.3.11 to 0.3.12 (#42) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index a0acdab18b9dc..9ed23815195b1 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -13,7 +13,7 @@ name = "bridge-node" [dependencies] futures = "0.3.1" log = "0.4.8" -structopt = "0.3.8" +structopt = "0.3.12" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } From 74aba5d1d63f31086cf6a8dc4b8cf64d34d6ede2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2020 04:34:06 +0000 Subject: [PATCH 0021/1210] Bump ansi_term from 0.9.0 to 0.12.1 (#43) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index df7941e8af518..8970e76150fbe 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -ansi_term = "0.9" +ansi_term = "0.12" async-std = "1.0.1" async-stream = "0.2.0" clap = { version = "2.33.0", features = ["yaml"] } From 08de62b1a1acf36001e6eb0e09361f2c5f0743be Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2020 05:03:43 +0000 Subject: [PATCH 0022/1210] Bump serde from 1.0.104 to 1.0.105 (#41) --- bin/node/runtime/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 7e0b9392c240c..8db68d768e289 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -13,7 +13,7 @@ default-features = false features = ["derive"] [dependencies.serde] -version = "1.0.101" +version = "1.0.105" optional = true features = ["derive"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8970e76150fbe..413f16e9a0958 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -17,7 +17,7 @@ linked-hash-map = "0.5.2" log = "0.4.8" parking_lot = "0.10.0" rustc-hex = "2.0.1" -serde = { version = "1.0.40", features = ["derive"] } +serde = { version = "1.0.105", features = ["derive"] } serde_json = "1.0.40" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.1" From 07d7cd9e609f39ad9a6ac90f82eb7653433d5a62 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2020 11:23:50 +0100 Subject: [PATCH 0023/1210] Bump time from 0.1.42 to 0.2.9 (#44) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump time from 0.1.42 to 0.2.9 Bumps [time](https://github.com/time-rs/time) from 0.1.42 to 0.2.9. - [Release notes](https://github.com/time-rs/time/releases) - [Changelog](https://github.com/time-rs/time/blob/master/CHANGELOG.md) - [Commits](https://github.com/time-rs/time/commits/v0.2.9) Signed-off-by: dependabot-preview[bot] * Update to new API. Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Tomasz Drwięga --- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/main.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 413f16e9a0958..6120710b33775 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -20,7 +20,7 @@ rustc-hex = "2.0.1" serde = { version = "1.0.105", features = ["derive"] } serde_json = "1.0.40" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } -time = "0.1" +time = "0.2" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "fix_receipt" } # Substrate Based Dependencies diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 583faf08c90c8..28ff6d18d9476 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -66,8 +66,7 @@ fn initialize() { builder.parse_filters(&filters); builder.format(move |buf, record| { writeln!(buf, "{}", { - let timestamp = - time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).expect("Time is incorrectly formatted"); + let timestamp = time::OffsetDateTime::now_local().format("%Y-%m-%d %H:%M:%S %Z"); if cfg!(windows) { format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) } else { From 94b4a309ab43db7ff19ddbb8290ebd6bccca460d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 23 Mar 2020 15:22:22 +0300 Subject: [PATCH 0024/1210] remove duplicate licenses (#47) --- modules/ethereum/src/error.rs | 16 ---------------- modules/ethereum/src/finality.rs | 16 ---------------- modules/ethereum/src/import.rs | 16 ---------------- modules/ethereum/src/lib.rs | 16 ---------------- modules/ethereum/src/validators.rs | 16 ---------------- modules/ethereum/src/verification.rs | 16 ---------------- primitives/ethereum-poa/src/lib.rs | 16 ---------------- relays/ethereum/src/ethereum_client.rs | 16 ---------------- relays/ethereum/src/ethereum_headers.rs | 16 ---------------- relays/ethereum/src/ethereum_sync.rs | 16 ---------------- relays/ethereum/src/ethereum_sync_loop.rs | 16 ---------------- relays/ethereum/src/ethereum_types.rs | 16 ---------------- relays/ethereum/src/main.rs | 16 ---------------- relays/ethereum/src/substrate_client.rs | 16 ---------------- relays/ethereum/src/substrate_types.rs | 16 ---------------- 15 files changed, 240 deletions(-) diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index 7fe9b4f802b79..82a2c82736384 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use sp_runtime::RuntimeDebug; /// Header import error. diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index e2ea253172179..62fc3be01629b 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::error::Error; use crate::{ancestry, Storage}; use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256}; diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 9b9f3e613cbf1..82e84f706b439 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::error::Error; use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 9a3317c9731ee..398104fdbff1c 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode}; diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 3342f22450b62..24e34eb1674b9 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::error::Error; use crate::Storage; use primitives::{Address, Header, LogEntry, Receipt, H256, U256}; diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 2104d7f21c687..74bba803fb8ab 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::error::Error; use crate::validators::step_validator; use crate::{AuraConfiguration, ImportContext, Storage}; diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index b6b392a2062b7..ca2afa605db5b 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - #![cfg_attr(not(feature = "std"), no_std)] pub use parity_bytes::Bytes; diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 2efa99598c5fb..30a6bfb28a8c2 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::ethereum_sync_loop::MaybeConnectionError; use crate::ethereum_types::{Header, HeaderId, Receipt, H256, U64}; use jsonrpsee::common::Params; diff --git a/relays/ethereum/src/ethereum_headers.rs b/relays/ethereum/src/ethereum_headers.rs index 0fbc73f83976b..881bc15fee816 100644 --- a/relays/ethereum/src/ethereum_headers.rs +++ b/relays/ethereum/src/ethereum_headers.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::ethereum_types::{Header, HeaderId, HeaderStatus, QueuedHeader, Receipt, H256}; use std::collections::{ btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet, diff --git a/relays/ethereum/src/ethereum_sync.rs b/relays/ethereum/src/ethereum_sync.rs index 9c2834c1ae791..df5698f7e002f 100644 --- a/relays/ethereum/src/ethereum_sync.rs +++ b/relays/ethereum/src/ethereum_sync.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::ethereum_headers::QueuedHeaders; use crate::ethereum_sync_loop::EthereumSyncParams; use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 6f61b423d29cb..5c91b275106c8 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::ethereum_client; use crate::ethereum_types::HeaderStatus as EthereumHeaderStatus; use crate::substrate_client; diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index a83c4b666bf6d..beb6c100fb4d9 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - pub use web3::types::{Bytes, H256, U128, U64}; /// When header is just received from the Ethereum node, we check that it has diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 28ff6d18d9476..9feb34462bb92 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - #![recursion_limit = "1024"] mod ethereum_client; diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 885bf57bec02d..799bf6151ed8b 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - use crate::ethereum_sync_loop::MaybeConnectionError; use crate::ethereum_types::{Bytes, HeaderId as EthereumHeaderId, QueuedHeader as QueuedEthereumHeader, H256}; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts, TransactionHash}; diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index fd1f07e693282..f056b7101149f 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Parity-Bridge. - -// Parity-Bridge 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-Bridge 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-Bridge. If not, see . - pub use crate::ethereum_types::H256 as TransactionHash; use crate::ethereum_types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, From a03277cfbe8f31fa0265533d36247cecb7193ad4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2020 01:56:59 +0000 Subject: [PATCH 0025/1210] Bump serde_json from 1.0.48 to 1.0.50 (#48) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 6120710b33775..8fb7226699b68 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.8" parking_lot = "0.10.0" rustc-hex = "2.0.1" serde = { version = "1.0.105", features = ["derive"] } -serde_json = "1.0.40" +serde_json = "1.0.50" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "fix_receipt" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 16ea51eb97f40..479c450061b90 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -13,7 +13,7 @@ env_logger = "0.7.1" futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" -serde_json = "1.0.41" +serde_json = "1.0.50" url = "2.1.0" [dependencies.sp-core] From c36515781b336f16719aabc001f149df94272496 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2020 02:22:39 +0000 Subject: [PATCH 0026/1210] Bump derive_more from 0.99.3 to 0.99.5 (#49) --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 479c450061b90..cd1408b5997c9 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" async-std = "1.0.1" clap = "2.3.3" ctrlc = "3.1.4" -derive_more = "0.99.3" +derive_more = "0.99.5" env_logger = "0.7.1" futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } From 26916583b3b9739060fdcdcfdbb61bb8e84a70f8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2020 01:58:30 +0000 Subject: [PATCH 0027/1210] Bump serde from 1.0.105 to 1.0.106 (#52) --- bin/node/runtime/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 8db68d768e289..688d55e40baf2 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -13,7 +13,7 @@ default-features = false features = ["derive"] [dependencies.serde] -version = "1.0.105" +version = "1.0.106" optional = true features = ["derive"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8fb7226699b68..d731e2b08d3a3 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -17,7 +17,7 @@ linked-hash-map = "0.5.2" log = "0.4.8" parking_lot = "0.10.0" rustc-hex = "2.0.1" -serde = { version = "1.0.105", features = ["derive"] } +serde = { version = "1.0.106", features = ["derive"] } serde_json = "1.0.50" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" From d9fde29c9ef78de2612d29d8001151ef6cd1cd58 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 6 Apr 2020 03:29:42 +0000 Subject: [PATCH 0028/1210] Bump serde_json from 1.0.50 to 1.0.51 (#53) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d731e2b08d3a3..06b29e7e8effc 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.8" parking_lot = "0.10.0" rustc-hex = "2.0.1" serde = { version = "1.0.106", features = ["derive"] } -serde_json = "1.0.50" +serde_json = "1.0.51" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "fix_receipt" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index cd1408b5997c9..51c197e7f5c1b 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -13,7 +13,7 @@ env_logger = "0.7.1" futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" -serde_json = "1.0.50" +serde_json = "1.0.51" url = "2.1.0" [dependencies.sp-core] From 26ec15cb89be90bef699210294bcaeedab97500e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Apr 2020 11:01:29 +0300 Subject: [PATCH 0029/1210] fixed time format string (#54) --- relays/ethereum/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 9feb34462bb92..bf256d6fad018 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -50,7 +50,7 @@ fn initialize() { builder.parse_filters(&filters); builder.format(move |buf, record| { writeln!(buf, "{}", { - let timestamp = time::OffsetDateTime::now_local().format("%Y-%m-%d %H:%M:%S %Z"); + let timestamp = time::OffsetDateTime::now_local().format("%Y-%m-%d %H:%M:%S %z"); if cfg!(windows) { format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) } else { From 7df1279d5dd382e4cae0e341efd1fcab1594386d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Apr 2020 15:50:02 +0300 Subject: [PATCH 0030/1210] Add missing RPC required for relay (#57) * add missing RPC required for relay * cargo fmt --all --- bin/node/node/Cargo.toml | 11 +++++++++++ bin/node/node/src/service.rs | 10 ++++++++++ bin/node/runtime/Cargo.toml | 7 +++++++ bin/node/runtime/src/lib.rs | 6 ++++++ 4 files changed, 34 insertions(+) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 9ed23815195b1..bff9297112916 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -12,6 +12,7 @@ name = "bridge-node" [dependencies] futures = "0.3.1" +jsonrpc-core = "14.0.3" log = "0.4.8" structopt = "0.3.12" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } @@ -22,6 +23,11 @@ version = "0.8.0-alpha.2" rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate.git" +[dependencies.sc-rpc] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + [dependencies.sp-core] version = "2.0.0-alpha.2" rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" @@ -99,6 +105,11 @@ version = "0.8.0-alpha.2" rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate.git" +[dependencies.substrate-frame-rpc-system] +version = "2.0.0-alpha.2" +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate.git" + [build-dependencies] vergen = "3.1.0" diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 6d629f5708cfb..4ed07fed2b1f5 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -80,6 +80,16 @@ macro_rules! new_full_start { import_setup = Some((grandpa_block_import, grandpa_link)); Ok(import_queue) + })? + .with_rpc_extensions(|builder| -> Result, _> { + use substrate_frame_rpc_system::{FullSystem, SystemApi}; + + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with(SystemApi::to_delegate(FullSystem::new( + builder.client().clone(), + builder.pool(), + ))); + Ok(io) })?; (builder, import_setup, inherent_data_providers) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 688d55e40baf2..06c8d930708db 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -65,6 +65,12 @@ default-features = false rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate/" +[dependencies.frame-system-rpc-runtime-api] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + [dependencies.pallet-timestamp] version = "2.0.0-alpha.2" default-features = false @@ -177,6 +183,7 @@ std = [ "frame-executive/std", "frame-support/std", "frame-system/std", + "frame-system-rpc-runtime-api/std", "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "serde", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index dff29f9dff4b7..7912d7fc8f441 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -330,6 +330,12 @@ impl_runtime_apis! { } } + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { fn best_block() -> (u64, sp_bridge_eth_poa::H256) { BridgeEthPoA::best_block() From 716a28ea07cbfc5759515a51c112d435abb486aa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Apr 2020 15:53:59 +0300 Subject: [PATCH 0031/1210] Sync ethereum headers using unsigned (substrate) transactions (#45) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * reward submitters on finalization * PoA -> Substrate: unsigned_import_header API * fix grumble * make submitter part of ImportContext * verify using next validators set + tests * fix nostd compilation * add sub-tx-mode argument * support sub-tx-mode * impl ValidateUnsigned for Runtime * do not submit too much transactions to the pool * cargo fmt * fix bad merge * revert license fix * Update modules/ethereum/src/lib.rs Co-Authored-By: Hernando Castano * Update modules/ethereum/src/verification.rs Co-Authored-By: Hernando Castano * updated comment * validate receipts before accepting unsigned tx to pool * cargo fmt * fix comment * fix grumbles * Update modules/ethereum/src/verification.rs Co-Authored-By: Hernando Castano * cargo fmt --all * struct ChangeToEnact * updated doc * fix doc * add docs to the code method * simplify fn ancestry * finish incomplete docs * Update modules/ethereum/src/lib.rs Co-Authored-By: Tomasz Drwięga * Update modules/ethereum/src/lib.rs Co-Authored-By: Tomasz Drwięga * return err from unsigned_import_header * get header once * Update relays/ethereum/src/ethereum_sync.rs Co-Authored-By: Tomasz Drwięga * fix * UnsignedTooFarInTheFuture -> Custom(err.code()) * updated ImportContext::last_signal_block * cargo fmt --all * rename runtime calls Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- bin/node/runtime/src/lib.rs | 2 +- modules/ethereum/src/error.rs | 51 +- modules/ethereum/src/finality.rs | 33 +- modules/ethereum/src/import.rs | 32 +- modules/ethereum/src/lib.rs | 370 ++++++++++---- modules/ethereum/src/validators.rs | 9 +- modules/ethereum/src/verification.rs | 558 ++++++++++++++++++++-- relays/ethereum/src/cli.yml | 13 +- relays/ethereum/src/ethereum_sync.rs | 45 +- relays/ethereum/src/ethereum_sync_loop.rs | 35 +- relays/ethereum/src/main.rs | 13 + relays/ethereum/src/substrate_client.rs | 93 +++- 12 files changed, 1043 insertions(+), 211 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7912d7fc8f441..1ec47fde80168 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -247,7 +247,7 @@ construct_runtime!( Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, - BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage}, + BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage, ValidateUnsigned}, } ); diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index 82a2c82736384..4c887a4a493e4 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -17,45 +17,49 @@ use sp_runtime::RuntimeDebug; /// Header import error. -#[derive(RuntimeDebug)] +#[derive(Clone, Copy, RuntimeDebug)] #[cfg_attr(feature = "std", derive(PartialEq))] pub enum Error { - /// The header is beyound last finalized and can not be imported. - AncientHeader, + /// The header is beyond last finalized and can not be imported. + AncientHeader = 0, /// The header is already imported. - KnownHeader, + KnownHeader = 1, /// Seal has an incorrect format. - InvalidSealArity, + InvalidSealArity = 2, /// Block number isn't sensible. - RidiculousNumber, + RidiculousNumber = 3, /// Block has too much gas used. - TooMuchGasUsed, + TooMuchGasUsed = 4, /// Gas limit header field is invalid. - InvalidGasLimit, + InvalidGasLimit = 5, /// Extra data is of an invalid length. - ExtraDataOutOfBounds, + ExtraDataOutOfBounds = 6, /// Timestamp header overflowed. - TimestampOverflow, + TimestampOverflow = 7, /// The parent header is missing from the blockchain. - MissingParentBlock, + MissingParentBlock = 8, /// The header step is missing from the header. - MissingStep, + MissingStep = 9, /// The header signature is missing from the header. - MissingSignature, + MissingSignature = 10, /// Empty steps are missing from the header. - MissingEmptySteps, + MissingEmptySteps = 11, /// The same author issued different votes at the same step. - DoubleVote, + DoubleVote = 12, /// Validation proof insufficient. - InsufficientProof, + InsufficientProof = 13, /// Difficulty header field is invalid. - InvalidDifficulty, + InvalidDifficulty = 14, /// The received block is from an incorrect proposer. - NotValidator, + NotValidator = 15, /// Missing transaction receipts for the operation. - MissingTransactionsReceipts, + MissingTransactionsReceipts = 16, + /// Redundant transaction receipts are provided. + RedundantTransactionsReceipts = 17, /// Provided transactions receipts are not matching the header. - TransactionsReceiptsMismatch, + TransactionsReceiptsMismatch = 18, + /// Can't accept unsigned header from the far future. + UnsignedTooFarInTheFuture = 19, } impl Error { @@ -78,7 +82,14 @@ impl Error { Error::InvalidDifficulty => "Header has invalid difficulty", Error::NotValidator => "Header is sealed by unexpected validator", Error::MissingTransactionsReceipts => "The import operation requires transactions receipts", + Error::RedundantTransactionsReceipts => "Redundant transactions receipts are provided", Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided", + Error::UnsignedTooFarInTheFuture => "The unsigned header is too far in future", } } + + /// Return unique error code. + pub fn code(&self) -> u8 { + *self as u8 + } } diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 62fc3be01629b..1ee9f356028e7 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -15,15 +15,18 @@ // along with Parity Bridges Common. If not, see . use crate::error::Error; -use crate::{ancestry, Storage}; +use crate::Storage; use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256}; use sp_io::crypto::secp256k1_ecdsa_recover; -use sp_std::collections::{ - btree_map::{BTreeMap, Entry}, - btree_set::BTreeSet, - vec_deque::VecDeque, -}; use sp_std::prelude::*; +use sp_std::{ + collections::{ + btree_map::{BTreeMap, Entry}, + btree_set::BTreeSet, + vec_deque::VecDeque, + }, + iter::from_fn, +}; /// Tries to finalize blocks when given block is imported. /// @@ -190,6 +193,24 @@ fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option .map(|public| public_to_address(&public)) } +/// Return iterator of given header ancestors. +pub(crate) fn ancestry<'a, S: Storage>( + storage: &'a S, + header: &Header, +) -> impl Iterator)> + 'a { + let mut parent_hash = header.parent_hash.clone(); + from_fn(move || { + let (header, submitter) = storage.header(&parent_hash)?; + if header.number == 0 { + return None; + } + + let hash = parent_hash.clone(); + parent_hash = header.parent_hash.clone(); + Some((hash, header, submitter)) + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 82e84f706b439..20a5d10e457ec 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -17,8 +17,8 @@ use crate::error::Error; use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; -use crate::verification::verify_aura_header; -use crate::{AuraConfiguration, Storage}; +use crate::verification::{is_importable_header, verify_aura_header}; +use crate::{AuraConfiguration, ChangeToEnact, Storage}; use primitives::{Header, Receipt, H256}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; @@ -105,16 +105,22 @@ pub fn import_header( let (scheduled_change, enacted_change) = validators.extract_validators_change(&header, receipts)?; // check if block finalizes some other blocks and corresponding scheduled validators + let validators_set = import_context.validators_set(); let finalized_blocks = finalize_blocks( storage, &prev_finalized_hash, - (import_context.validators_start(), import_context.validators()), + (&validators_set.enact_block, &validators_set.validators), &hash, import_context.submitter(), &header, aura_config.two_thirds_majority_transition, )?; - let enacted_change = enacted_change.or_else(|| validators.finalize_validators_change(storage, &finalized_blocks)); + let enacted_change = enacted_change + .map(|validators| ChangeToEnact { + signal_block: None, + validators, + }) + .or_else(|| validators.finalize_validators_change(storage, &finalized_blocks)); // NOTE: we can't return Err() from anywhere below this line // (because otherwise we'll have inconsistent storage if transaction will fail) @@ -157,24 +163,6 @@ pub fn header_import_requires_receipts( .unwrap_or(false) } -/// Checks that we are able to ***try to** import this header. -/// Returns error if we should not try to import this block. -/// Returns hash of the header and number of the last finalized block. -fn is_importable_header(storage: &S, header: &Header) -> Result<(H256, H256), Error> { - // we never import any header that competes with finalized header - let (finalized_block_number, finalized_block_hash) = storage.finalized_block(); - if header.number <= finalized_block_number { - return Err(Error::AncientHeader); - } - // we never import any header with known hash - let hash = header.hash(); - if storage.header(&hash).is_some() { - return Err(Error::KnownHeader); - } - - Ok((hash, finalized_block_hash)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 398104fdbff1c..b7bdd066b2567 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -19,8 +19,14 @@ use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage}; use primitives::{Address, Header, Receipt, H256, U256}; -use sp_runtime::RuntimeDebug; -use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, iter::from_fn, prelude::*}; +use sp_runtime::{ + transaction_validity::{ + InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionValidity, UnknownTransaction, + ValidTransaction, + }, + RuntimeDebug, +}; +use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; use validators::{ValidatorsConfiguration, ValidatorsSource}; pub use import::{header_import_requires_receipts, import_header}; @@ -52,6 +58,18 @@ pub struct AuraConfiguration { pub maximum_extra_data_size: u64, } +/// Transaction pool configuration. +/// +/// This is used to limit number of unsigned headers transactions in +/// the pool. We never use it to verify signed transactions. +pub struct PoolConfiguration { + /// Maximal difference between number of header from unsigned transaction + /// and current best block. This must be selected with caution - the more + /// is the difference, the more (potentially invalid) transactions could be + /// accepted to the pool and mined later (filling blocks with spam). + pub max_future_number_difference: u64, +} + /// Block header as it is stored in the runtime storage. #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] pub struct StoredHeader { @@ -67,6 +85,32 @@ pub struct StoredHeader { /// this is the set that has produced the block itself. /// The hash is the hash of block where validators set has been enacted. pub next_validators_set_id: u64, + /// Hash of the last block which has **SCHEDULED** validators set change. + /// Note that signal doesn't mean that the set has been (or ever will be) enacted. + /// Note that the header may already be pruned. + pub last_signal_block: Option, +} + +/// Validators set as it is stored in the runtime storage. +#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[cfg_attr(test, derive(Clone))] +pub struct ValidatorsSet { + /// Validators of this set. + pub validators: Vec
, + /// Hash of the block where this set has been signalled. None if this is the first set. + pub signal_block: Option, + /// Hash of the block where this set has been enacted. + pub enact_block: H256, +} + +/// Validators set change as it is stored in the runtime storage. +#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[cfg_attr(test, derive(Clone))] +pub struct ScheduledChange { + /// Validators of this set. + pub validators: Vec
, + /// Hash of the block which has emitted previous validators change signal. + pub prev_signal_block: Option, } /// Header that we're importing. @@ -83,41 +127,44 @@ pub struct HeaderToImport { pub header: Header, /// Total chain difficulty at the header. pub total_difficulty: U256, - /// Validators set enacted change, if happened at the header. - pub enacted_change: Option>, + /// New validators set and the hash of block where it has been scheduled (if applicable). + /// Some if set is is enacted by this header. + pub enacted_change: Option, /// Validators set scheduled change, if happened at the header. pub scheduled_change: Option>, } +/// Header that we're importing. +#[derive(RuntimeDebug)] +#[cfg_attr(test, derive(Clone, PartialEq))] +pub struct ChangeToEnact { + /// The hash of the header where change has been scheduled. + /// None if it is a first set within current `ValidatorsSource`. + pub signal_block: Option, + /// Validators set that is enacted. + pub validators: Vec
, +} + /// Header import context. +/// +/// The import context contains information needed by the header verification +/// pipeline which is not directly part of the header being imported. This includes +/// information relating to its parent, and the current validator set (which +/// provide _context_ for the current header). #[derive(RuntimeDebug)] #[cfg_attr(test, derive(Clone, PartialEq))] pub struct ImportContext { submitter: Option, + parent_hash: H256, parent_header: Header, parent_total_difficulty: U256, - next_validators_set_id: u64, - next_validators_set: (H256, Vec
), + parent_scheduled_change: Option, + validators_set_id: u64, + validators_set: ValidatorsSet, + last_signal_block: Option, } impl ImportContext { - /// Create import context using passing parameters; - pub fn new( - submitter: Option, - parent_header: Header, - parent_total_difficulty: U256, - next_validators_set_id: u64, - next_validators_set: (H256, Vec
), - ) -> Self { - ImportContext { - submitter, - parent_header, - parent_total_difficulty, - next_validators_set_id, - next_validators_set, - } - } - /// Returns reference to header submitter (if known). pub fn submitter(&self) -> Option<&Submitter> { self.submitter.as_ref() @@ -133,19 +180,28 @@ impl ImportContext { &self.parent_total_difficulty } + /// Returns the validator set change if the parent header has signaled a change. + pub fn parent_scheduled_change(&self) -> Option<&ScheduledChange> { + self.parent_scheduled_change.as_ref() + } + /// Returns id of the set of validators. pub fn validators_set_id(&self) -> u64 { - self.next_validators_set_id + self.validators_set_id } - /// Returns block whenre validators set has been enacted. - pub fn validators_start(&self) -> &H256 { - &self.next_validators_set.0 + /// Returns reference to validators set for the block we're going to import. + pub fn validators_set(&self) -> &ValidatorsSet { + &self.validators_set } - /// Returns reference to the set of validators of the block we're going to import. - pub fn validators(&self) -> &[Address] { - &self.next_validators_set.1 + /// Returns reference to the latest block which has signalled change of validators set. + /// This may point to parent if parent has signalled change. + pub fn last_signal_block(&self) -> Option<&H256> { + match self.parent_scheduled_change { + Some(_) => Some(&self.parent_hash), + None => self.last_signal_block.as_ref(), + } } /// Converts import context into header we're going to import. @@ -155,7 +211,7 @@ impl ImportContext { hash: H256, header: Header, total_difficulty: U256, - enacted_change: Option>, + enacted_change: Option, scheduled_change: Option>, ) -> HeaderToImport { HeaderToImport { @@ -191,8 +247,9 @@ pub trait Storage { submitter: Option, parent_hash: &H256, ) -> Option>; - /// Get new validators that are scheduled by given header. - fn scheduled_change(&self, hash: &H256) -> Option>; + /// Get new validators that are scheduled by given header and hash of the previous + /// block that has scheduled change. + fn scheduled_change(&self, hash: &H256) -> Option; /// Insert imported header. fn insert_header(&mut self, header: HeaderToImport); /// Finalize given block and prune all headers with number < prune_end. @@ -235,13 +292,28 @@ pub trait Trait: frame_system::Trait { decl_module! { pub struct Module for enum Call where origin: T::Origin { - /// Import Aura chain headers. Ignores non-fatal errors (like when known - /// header is provided), rewards for successful headers import and penalizes - /// for fatal errors. + /// Import single Aura header. Requires transaction to be **UNSIGNED**. + pub fn import_unsigned_header(origin, header: Header, receipts: Option>) { + frame_system::ensure_none(origin)?; + + import_header( + &mut BridgeStorage::::new(), + &kovan_aura_config(), + &kovan_validators_config(), + crate::import::PRUNE_DEPTH, + None, + header, + receipts, + ).map_err(|e| e.msg())?; + } + + /// Import Aura chain headers in a single **SIGNED** transaction. + /// Ignores non-fatal errors (like when known header is provided), rewards + /// for successful headers import and penalizes for fatal errors. /// /// This should be used with caution - passing too many headers could lead to /// enormous block production/import time. - pub fn import_headers(origin, headers_with_receipts: Vec<(Header, Option>)>) { + pub fn import_signed_headers(origin, headers_with_receipts: Vec<(Header, Option>)>) { let submitter = frame_system::ensure_signed(origin)?; let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( @@ -293,13 +365,13 @@ decl_storage! { /// The ID of next validator set. NextValidatorsSetId: u64; /// Map of validators sets by their id. - ValidatorsSets: map hasher(blake2_256) u64 => Option<(H256, Vec
)>; + ValidatorsSets: map hasher(blake2_256) u64 => Option; /// Validators sets reference count. Each header that is authored by this set increases /// the reference count. When we prune this header, we decrease the reference count. /// When it reaches zero, we are free to prune validator set as well. ValidatorsSetsRc: map hasher(blake2_256) u64 => Option; /// Map of validators set changes scheduled by given header. - ScheduledChanges: map hasher(blake2_256) H256 => Option>; + ScheduledChanges: map hasher(blake2_256) H256 => Option; } add_extra_genesis { config(initial_header): Header; @@ -326,9 +398,14 @@ decl_storage! { header: config.initial_header.clone(), total_difficulty: config.initial_difficulty, next_validators_set_id: 0, + last_signal_block: None, }); NextValidatorsSetId::put(1); - ValidatorsSets::insert(0, (initial_hash, config.initial_validators.clone())); + ValidatorsSets::insert(0, ValidatorsSet { + validators: config.initial_validators.clone(), + signal_block: None, + enact_block: initial_hash, + }); ValidatorsSetsRc::insert(0, 1); }) } @@ -354,6 +431,43 @@ impl Module { } } +impl frame_support::unsigned::ValidateUnsigned for Module { + type Call = Call; + + fn validate_unsigned(call: &Self::Call) -> TransactionValidity { + match *call { + Self::Call::import_unsigned_header(ref header, ref receipts) => { + let accept_result = verification::accept_aura_header_into_pool( + &BridgeStorage::::new(), + &kovan_aura_config(), + &kovan_validators_config(), + &pool_configuration(), + header, + receipts.as_ref(), + ); + + match accept_result { + Ok((requires, provides)) => Ok(ValidTransaction { + priority: TransactionPriority::max_value(), + requires, + provides, + longevity: TransactionLongevity::max_value(), + propagate: true, + }), + // UnsignedTooFarInTheFuture is the special error code used to limit + // number of transactions in the pool - we do not want to ban transaction + // in this case (see verification.rs for details) + Err(error::Error::UnsignedTooFarInTheFuture) => { + UnknownTransaction::Custom(error::Error::UnsignedTooFarInTheFuture.code()).into() + } + Err(error) => InvalidTransaction::Custom(error.code()).into(), + } + } + _ => InvalidTransaction::Call.into(), + } + } +} + /// Runtime bridge storage. #[derive(Default)] struct BridgeStorage(sp_std::marker::PhantomData); @@ -385,20 +499,23 @@ impl Storage for BridgeStorage { parent_hash: &H256, ) -> Option> { Headers::::get(parent_hash).map(|parent_header| { - let (next_validators_set_start, next_validators) = - ValidatorsSets::get(parent_header.next_validators_set_id) - .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); + let validators_set = ValidatorsSets::get(parent_header.next_validators_set_id) + .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); + let parent_scheduled_change = ScheduledChanges::get(parent_hash); ImportContext { submitter, + parent_hash: *parent_hash, parent_header: parent_header.header, parent_total_difficulty: parent_header.total_difficulty, - next_validators_set_id: parent_header.next_validators_set_id, - next_validators_set: (next_validators_set_start, next_validators), + parent_scheduled_change, + validators_set_id: parent_header.next_validators_set_id, + validators_set, + last_signal_block: parent_header.last_signal_block, } }) } - fn scheduled_change(&self, hash: &H256) -> Option> { + fn scheduled_change(&self, hash: &H256) -> Option { ScheduledChanges::get(hash) } @@ -407,7 +524,13 @@ impl Storage for BridgeStorage { BestBlock::put((header.header.number, header.hash, header.total_difficulty)); } if let Some(scheduled_change) = header.scheduled_change { - ScheduledChanges::insert(&header.hash, scheduled_change); + ScheduledChanges::insert( + &header.hash, + ScheduledChange { + validators: scheduled_change, + prev_signal_block: header.context.last_signal_block, + }, + ); } let next_validators_set_id = match header.enacted_change { Some(enacted_change) => { @@ -416,19 +539,27 @@ impl Storage for BridgeStorage { *set_id += 1; next_set_id }); - ValidatorsSets::insert(next_validators_set_id, (header.hash, enacted_change)); + ValidatorsSets::insert( + next_validators_set_id, + ValidatorsSet { + validators: enacted_change.validators, + enact_block: header.hash, + signal_block: enacted_change.signal_block, + }, + ); ValidatorsSetsRc::insert(next_validators_set_id, 1); next_validators_set_id } None => { - ValidatorsSetsRc::mutate(header.context.next_validators_set_id, |rc| { + ValidatorsSetsRc::mutate(header.context.validators_set_id, |rc| { *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); *rc }); - header.context.next_validators_set_id + header.context.validators_set_id } }; + let last_signal_block = header.context.last_signal_block().cloned(); HeadersByNumber::append_or_insert(header.header.number, vec![header.hash]); Headers::::insert( &header.hash, @@ -437,6 +568,7 @@ impl Storage for BridgeStorage { header: header.header, total_difficulty: header.total_difficulty, next_validators_set_id, + last_signal_block, }, ); } @@ -616,27 +748,11 @@ pub fn kovan_validators_config() -> ValidatorsConfiguration { ]) } -/// Return iterator of given header ancestors. -pub(crate) fn ancestry<'a, S: Storage>( - storage: &'a S, - header: &Header, -) -> impl Iterator)> + 'a { - let mut parent_hash = header.parent_hash.clone(); - from_fn(move || { - let header_and_submitter = storage.header(&parent_hash); - match header_and_submitter { - Some((header, submitter)) => { - if header.number == 0 { - return None; - } - - let hash = parent_hash.clone(); - parent_hash = header.parent_hash.clone(); - Some((hash, header, submitter)) - } - None => None, - } - }) +/// Transaction pool configuration. +fn pool_configuration() -> PoolConfiguration { + PoolConfiguration { + max_future_number_difference: 10, + } } #[cfg(test)] @@ -706,9 +822,9 @@ pub(crate) mod tests { headers: HashMap>, headers_by_number: HashMap>, next_validators_set_id: u64, - validators_sets: HashMap)>, + validators_sets: HashMap, validators_sets_rc: HashMap, - scheduled_changes: HashMap>, + scheduled_changes: HashMap, } impl InMemoryStorage { @@ -726,17 +842,82 @@ pub(crate) mod tests { header: initial_header, total_difficulty: 0.into(), next_validators_set_id: 0, + last_signal_block: None, }, )] .into_iter() .collect(), next_validators_set_id: 1, - validators_sets: vec![(0, (hash, initial_validators))].into_iter().collect(), + validators_sets: vec![( + 0, + ValidatorsSet { + validators: initial_validators, + signal_block: None, + enact_block: hash, + }, + )] + .into_iter() + .collect(), validators_sets_rc: vec![(0, 1)].into_iter().collect(), scheduled_changes: HashMap::new(), } } + pub(crate) fn insert(&mut self, header: Header) { + let hash = header.hash(); + self.headers_by_number.entry(header.number).or_default().push(hash); + self.headers.insert( + hash, + StoredHeader { + submitter: None, + header, + total_difficulty: 0.into(), + next_validators_set_id: 0, + last_signal_block: None, + }, + ); + } + + pub(crate) fn change_validators_set_at( + &mut self, + number: u64, + finalized_set: Vec
, + signalled_set: Option>, + ) { + let set_id = self.next_validators_set_id; + self.next_validators_set_id += 1; + self.validators_sets.insert( + set_id, + ValidatorsSet { + validators: finalized_set, + signal_block: None, + enact_block: self.headers_by_number[&0][0], + }, + ); + + let mut header = self.headers.get_mut(&self.headers_by_number[&number][0]).unwrap(); + header.next_validators_set_id = set_id; + if let Some(signalled_set) = signalled_set { + header.last_signal_block = Some(self.headers_by_number[&(number - 1)][0]); + self.scheduled_changes.insert( + self.headers_by_number[&(number - 1)][0], + ScheduledChange { + validators: signalled_set, + prev_signal_block: None, + }, + ); + } + } + + pub(crate) fn set_best_block(&mut self, best_block: (u64, H256)) { + self.best_block.0 = best_block.0; + self.best_block.1 = best_block.1; + } + + pub(crate) fn set_finalized_block(&mut self, finalized_block: (u64, H256)) { + self.finalized_block = finalized_block; + } + pub(crate) fn oldest_unpruned_block(&self) -> u64 { self.oldest_unpruned_block } @@ -769,19 +950,26 @@ pub(crate) mod tests { parent_hash: &H256, ) -> Option> { self.headers.get(parent_hash).map(|parent_header| { - let (next_validators_set_start, next_validators) = - self.validators_sets.get(&parent_header.next_validators_set_id).unwrap(); + let validators_set = self + .validators_sets + .get(&parent_header.next_validators_set_id) + .unwrap() + .clone(); + let parent_scheduled_change = self.scheduled_changes.get(parent_hash).cloned(); ImportContext { submitter, + parent_hash: *parent_hash, parent_header: parent_header.header.clone(), parent_total_difficulty: parent_header.total_difficulty, - next_validators_set_id: parent_header.next_validators_set_id, - next_validators_set: (*next_validators_set_start, next_validators.clone()), + parent_scheduled_change, + validators_set_id: parent_header.next_validators_set_id, + validators_set, + last_signal_block: parent_header.last_signal_block, } }) } - fn scheduled_change(&self, hash: &H256) -> Option> { + fn scheduled_change(&self, hash: &H256) -> Option { self.scheduled_changes.get(hash).cloned() } @@ -790,26 +978,39 @@ pub(crate) mod tests { self.best_block = (header.header.number, header.hash, header.total_difficulty); } if let Some(scheduled_change) = header.scheduled_change { - self.scheduled_changes.insert(header.hash, scheduled_change); + self.scheduled_changes.insert( + header.hash, + ScheduledChange { + validators: scheduled_change, + prev_signal_block: header.context.last_signal_block, + }, + ); } let next_validators_set_id = match header.enacted_change { Some(enacted_change) => { let next_validators_set_id = self.next_validators_set_id; self.next_validators_set_id += 1; - self.validators_sets - .insert(next_validators_set_id, (header.hash, enacted_change)); + self.validators_sets.insert( + next_validators_set_id, + ValidatorsSet { + validators: enacted_change.validators, + enact_block: header.hash, + signal_block: enacted_change.signal_block, + }, + ); self.validators_sets_rc.insert(next_validators_set_id, 1); next_validators_set_id } None => { *self .validators_sets_rc - .entry(header.context.next_validators_set_id) + .entry(header.context.validators_set_id) .or_default() += 1; - header.context.next_validators_set_id + header.context.validators_set_id } }; + let last_signal_block = header.context.last_signal_block().cloned(); self.headers_by_number .entry(header.header.number) .or_default() @@ -821,6 +1022,7 @@ pub(crate) mod tests { header: header.header, total_difficulty: header.total_difficulty, next_validators_set_id, + last_signal_block, }, ); } diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 24e34eb1674b9..a93c21f8de4e7 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::error::Error; -use crate::Storage; +use crate::{ChangeToEnact, Storage}; use primitives::{Address, Header, LogEntry, Receipt, H256, U256}; use sp_std::prelude::*; @@ -183,10 +183,13 @@ impl<'a> Validators<'a> { &self, storage: &mut S, finalized_blocks: &[(u64, H256, Option)], - ) -> Option> { + ) -> Option { for (_, finalized_hash, _) in finalized_blocks.iter().rev() { if let Some(changes) = storage.scheduled_change(finalized_hash) { - return Some(changes); + return Some(ChangeToEnact { + signal_block: Some(*finalized_hash), + validators: changes.validators, + }); } } None diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 74bba803fb8ab..23f8980b3a0bb 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -15,39 +15,205 @@ // along with Parity Bridges Common. If not, see . use crate::error::Error; -use crate::validators::step_validator; -use crate::{AuraConfiguration, ImportContext, Storage}; -use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256, H520, U128, U256}; +use crate::validators::{step_validator, Validators, ValidatorsConfiguration}; +use crate::{AuraConfiguration, ImportContext, PoolConfiguration, ScheduledChange, Storage}; +use codec::Encode; +use primitives::{public_to_address, Address, Header, Receipt, SealedEmptyStep, H256, H520, U128, U256}; use sp_io::crypto::secp256k1_ecdsa_recover; +use sp_std::{vec, vec::Vec}; + +/// Pre-check to see if should try and import this header. +/// Returns error if we should not try to import this block. +/// Returns hash of the header and number of the last finalized block otherwise. +pub fn is_importable_header(storage: &S, header: &Header) -> Result<(H256, H256), Error> { + // we never import any header that competes with finalized header + let (finalized_block_number, finalized_block_hash) = storage.finalized_block(); + if header.number <= finalized_block_number { + return Err(Error::AncientHeader); + } + // we never import any header with known hash + let hash = header.hash(); + if storage.header(&hash).is_some() { + return Err(Error::KnownHeader); + } + + Ok((hash, finalized_block_hash)) +} + +/// Try accept unsigned aura header into transaction pool. +pub fn accept_aura_header_into_pool( + storage: &S, + config: &AuraConfiguration, + validators_config: &ValidatorsConfiguration, + pool_config: &PoolConfiguration, + header: &Header, + receipts: Option<&Vec>, +) -> Result<(Vec>, Vec>), Error> { + // check if we can verify further + let (hash, _) = is_importable_header(storage, header)?; + + // we can always do contextless checks + contextless_checks(config, header)?; + + // we want to avoid having same headers twice in the pool + // => we're strict about receipts here - if we need them, we require receipts to be Some, + // otherwise we require receipts to be None + let receipts_required = Validators::new(validators_config).maybe_signals_validators_change(header); + match (receipts_required, receipts.is_some()) { + (true, false) => return Err(Error::MissingTransactionsReceipts), + (false, true) => return Err(Error::RedundantTransactionsReceipts), + _ => (), + } + + // we do not want to have all future headers in the pool at once + // => if we see header with number > maximal ever seen header number + LIMIT, + // => we consider this transaction invalid, but only at this moment (we do not want to ban it) + // => let's mark it as Unknown transaction + let (best_number, best_hash, _) = storage.best_block(); + let difference = header.number.saturating_sub(best_number); + if difference > pool_config.max_future_number_difference { + return Err(Error::UnsignedTooFarInTheFuture); + } + + // TODO: only accept new headers when we're at the tip of PoA chain + // https://github.com/paritytech/parity-bridges-common/issues/38 + + // we want to see at most one header with given number from single authority + // => every header is providing tag (block_number + authority) + // => since only one tx in the pool can provide the same tag, they're auto-deduplicated + let provides_number_and_authority_tag = (header.number, header.author).encode(); + + // we want to see several 'future' headers in the pool at once, but we may not have access to + // previous headers here + // => we can at least 'verify' that headers comprise a chain by providing and requiring + // tag (header.number, header.hash) + let provides_header_number_and_hash_tag = (header.number, hash).encode(); + + // depending on whether parent header is available, we either perform full or 'shortened' check + let context = storage.import_context(None, &header.parent_hash); + let tags = match context { + Some(context) => { + let header_step = contextual_checks(config, &context, None, header)?; + validator_checks(config, &context.validators_set().validators, header, header_step)?; + + // since our parent is already in the storage, we do not require it + // to be in the transaction pool + ( + vec![], + vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag], + ) + } + None => { + // we know nothing about parent header + // => the best thing we can do is to believe that there are no forks in + // PoA chain AND that the header is produced either by previous, or next + // scheduled validators set change + let header_step = header.step().ok_or(Error::MissingStep)?; + let best_context = storage.import_context(None, &best_hash).expect( + "import context is None only when header is missing from the storage;\ + best header is always in the storage; qed", + ); + let validators_check_result = + validator_checks(config, &best_context.validators_set().validators, header, header_step); + if let Err(error) = validators_check_result { + find_next_validators_signal(storage, &best_context) + .ok_or_else(|| error) + .and_then(|next_validators| validator_checks(config, &next_validators, header, header_step))?; + } + + // since our parent is missing from the storage, we **DO** require it + // to be in the transaction pool + // (- 1 can't underflow because there's always best block in the header) + let requires_header_number_and_hash_tag = (header.number - 1, header.parent_hash).encode(); + ( + vec![requires_header_number_and_hash_tag], + vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag], + ) + } + }; + + // the heaviest, but rare operation - we do not want invalid receipts in the pool + if let Some(receipts) = receipts { + if !header.check_transactions_receipts(receipts) { + return Err(Error::TransactionsReceiptsMismatch); + } + } + + Ok(tags) +} /// Verify header by Aura rules. pub fn verify_aura_header( storage: &S, - params: &AuraConfiguration, + config: &AuraConfiguration, submitter: Option, header: &Header, ) -> Result, Error> { // let's do the lightest check first - contextless_checks(params, header)?; + contextless_checks(config, header)?; - // the rest of checks requires parent + // the rest of checks requires access to the parent header let context = storage .import_context(submitter, &header.parent_hash) .ok_or(Error::MissingParentBlock)?; - let validators = context.validators(); + let header_step = contextual_checks(config, &context, None, header)?; + validator_checks(config, &context.validators_set().validators, header, header_step)?; + + Ok(context) +} + +/// Perform basic checks that only require header itself. +fn contextless_checks(config: &AuraConfiguration, header: &Header) -> Result<(), Error> { + let expected_seal_fields = expected_header_seal_fields(config, header); + if header.seal.len() != expected_seal_fields { + return Err(Error::InvalidSealArity); + } + if header.number >= u64::max_value() { + return Err(Error::RidiculousNumber); + } + if header.gas_used > header.gas_limit { + return Err(Error::TooMuchGasUsed); + } + if header.gas_limit < config.min_gas_limit { + return Err(Error::InvalidGasLimit); + } + if header.gas_limit > config.max_gas_limit { + return Err(Error::InvalidGasLimit); + } + if header.number != 0 && header.extra_data.len() as u64 > config.maximum_extra_data_size { + return Err(Error::ExtraDataOutOfBounds); + } + + // we can't detect if block is from future in runtime + // => let's only do an overflow check + if header.timestamp > i32::max_value() as u64 { + return Err(Error::TimestampOverflow); + } + + Ok(()) +} + +/// Perform checks that require access to parent header. +fn contextual_checks( + config: &AuraConfiguration, + context: &ImportContext, + validators_override: Option<&[Address]>, + header: &Header, +) -> Result { + let validators = validators_override.unwrap_or_else(|| &context.validators_set().validators); let header_step = header.step().ok_or(Error::MissingStep)?; let parent_step = context.parent_header().step().ok_or(Error::MissingStep)?; // Ensure header is from the step after context. - if header_step == parent_step || (header.number >= params.validate_step_transition && header_step <= parent_step) { + if header_step == parent_step || (header.number >= config.validate_step_transition && header_step <= parent_step) { return Err(Error::DoubleVote); } // If empty step messages are enabled we will validate the messages in the seal, missing messages are not // reported as there's no way to tell whether the empty step message was never sent or simply not included. - let empty_steps_len = match header.number >= params.empty_steps_transition { + let empty_steps_len = match header.number >= config.empty_steps_transition { true => { - let strict_empty_steps = header.number >= params.strict_empty_steps_transition; + let strict_empty_steps = header.number >= config.strict_empty_steps_transition; let empty_steps = header.empty_steps().ok_or(Error::MissingEmptySteps)?; let empty_steps_len = empty_steps.len(); let mut prev_empty_step = 0; @@ -76,13 +242,23 @@ pub fn verify_aura_header( }; // Validate chain score. - if header.number >= params.validate_score_transition { + if header.number >= config.validate_score_transition { let expected_difficulty = calculate_score(parent_step, header_step, empty_steps_len as _); if header.difficulty != expected_difficulty { return Err(Error::InvalidDifficulty); } } + Ok(header_step) +} + +/// Check that block is produced by expected validator. +fn validator_checks( + config: &AuraConfiguration, + validators: &[Address], + header: &Header, + header_step: u64, +) -> Result<(), Error> { let expected_validator = step_validator(validators, header_step); if header.author != expected_validator { return Err(Error::NotValidator); @@ -90,44 +266,13 @@ pub fn verify_aura_header( let validator_signature = header.signature().ok_or(Error::MissingSignature)?; let header_seal_hash = header - .seal_hash(header.number >= params.empty_steps_transition) + .seal_hash(header.number >= config.empty_steps_transition) .ok_or(Error::MissingEmptySteps)?; let is_invalid_proposer = !verify_signature(&expected_validator, &validator_signature, &header_seal_hash); if is_invalid_proposer { return Err(Error::NotValidator); } - Ok(context) -} - -/// Perform basic checks that only require header iteself. -fn contextless_checks(config: &AuraConfiguration, header: &Header) -> Result<(), Error> { - let expected_seal_fields = expected_header_seal_fields(config, header); - if header.seal.len() != expected_seal_fields { - return Err(Error::InvalidSealArity); - } - if header.number >= u64::max_value() { - return Err(Error::RidiculousNumber); - } - if header.gas_used > header.gas_limit { - return Err(Error::TooMuchGasUsed); - } - if header.gas_limit < config.min_gas_limit { - return Err(Error::InvalidGasLimit); - } - if header.gas_limit > config.max_gas_limit { - return Err(Error::InvalidGasLimit); - } - if header.number != 0 && header.extra_data.len() as u64 > config.maximum_extra_data_size { - return Err(Error::ExtraDataOutOfBounds); - } - - // we can't detect if block is from future in runtime - // => let's only do an overflow check - if header.timestamp > i32::max_value() as u64 { - return Err(Error::TimestampOverflow); - } - Ok(()) } @@ -160,13 +305,47 @@ fn verify_signature(expected_validator: &Address, signature: &H520, message: &H2 .unwrap_or(false) } +/// Find next unfinalized validators set change after finalized set. +fn find_next_validators_signal(storage: &S, context: &ImportContext) -> Option> { + // that's the earliest block number we may met in following loop + // it may be None if that's the first set + let best_set_signal_block = context.validators_set().signal_block; + + // if parent schedules validators set change, then it may be our set + // else we'll start with last known change + let mut current_set_signal_block = context.last_signal_block().cloned(); + let mut next_scheduled_set: Option = None; + + loop { + // if we have reached block that signals finalized change, then + // next_current_block_hash points to the block that schedules next + // change + let current_scheduled_set = match current_set_signal_block { + Some(current_set_signal_block) if Some(¤t_set_signal_block) == best_set_signal_block.as_ref() => { + return next_scheduled_set.map(|scheduled_set| scheduled_set.validators) + } + None => return next_scheduled_set.map(|scheduled_set| scheduled_set.validators), + Some(current_set_signal_block) => storage.scheduled_change(¤t_set_signal_block).expect( + "header that is associated with this change is not pruned;\ + scheduled changes are only removed when header is pruned; qed", + ), + }; + + current_set_signal_block = current_scheduled_set.prev_signal_block; + next_scheduled_set = Some(current_scheduled_set); + } +} + #[cfg(test)] mod tests { use super::*; - use crate::kovan_aura_config; - use crate::tests::{genesis, signed_header, validator, validators_addresses, AccountId, InMemoryStorage}; + use crate::tests::{ + block_i, custom_block_i, genesis, signed_header, validator, validators_addresses, AccountId, InMemoryStorage, + }; + use crate::validators::{tests::validators_change_recept, ValidatorsSource}; + use crate::{kovan_aura_config, pool_configuration}; use parity_crypto::publickey::{sign, KeyPair}; - use primitives::{rlp_encode, H520}; + use primitives::{rlp_encode, TransactionOutcome, H520}; fn sealed_empty_step(validators: &[KeyPair], parent_hash: &H256, step: u64) -> SealedEmptyStep { let mut empty_step = SealedEmptyStep { @@ -191,6 +370,35 @@ mod tests { verify_with_config(&kovan_aura_config(), header) } + fn default_accept_into_pool( + mut make_header: impl FnMut(&mut InMemoryStorage, &[KeyPair]) -> (Header, Option>), + ) -> Result<(Vec>, Vec>), Error> { + let validators = vec![validator(0), validator(1), validator(2)]; + let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + let block1 = block_i(&storage, 1, &validators); + storage.insert(block1); + let block2 = block_i(&storage, 2, &validators); + let block2_hash = block2.hash(); + storage.insert(block2); + let block3 = block_i(&storage, 3, &validators); + let block3_hash = block3.hash(); + storage.insert(block3); + storage.set_finalized_block((2, block2_hash)); + storage.set_best_block((3, block3_hash)); + + let validators_config = + ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); + let (header, receipts) = make_header(&mut storage, &validators); + accept_aura_header_into_pool( + &storage, + &kovan_aura_config(), + &validators_config, + &pool_configuration(), + &header, + receipts.as_ref(), + ) + } + #[test] fn verifies_seal_count() { // when there are no seals at all @@ -433,4 +641,262 @@ mod tests { // when everything is OK assert_eq!(default_verify(&good_header).map(|_| ()), Ok(())); } + + #[test] + fn pool_verifies_known_blocks() { + // when header is known + assert_eq!( + default_accept_into_pool(|storage, validators| (block_i(storage, 3, validators), None)), + Err(Error::KnownHeader), + ); + } + + #[test] + fn pool_verifies_ancient_blocks() { + // when header number is less than finalized + assert_eq!( + default_accept_into_pool(|storage, validators| ( + custom_block_i(storage, 2, validators, |header| header.gas_limit += 1.into()), + None, + ),), + Err(Error::AncientHeader), + ); + } + + #[test] + fn pool_rejects_headers_without_required_receipts() { + assert_eq!( + default_accept_into_pool(|_, _| ( + Header { + number: 20_000_000, + seal: vec![vec![].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + log_bloom: (&[0xff; 256]).into(), + ..Default::default() + }, + None, + ),), + Err(Error::MissingTransactionsReceipts), + ); + } + + #[test] + fn pool_rejects_headers_with_redundant_receipts() { + assert_eq!( + default_accept_into_pool(|storage, validators| ( + block_i(storage, 4, validators), + Some(vec![Receipt { + gas_used: 1.into(), + log_bloom: (&[0xff; 256]).into(), + logs: vec![], + outcome: TransactionOutcome::Unknown, + }]), + ),), + Err(Error::RedundantTransactionsReceipts), + ); + } + + #[test] + fn pool_verifies_future_block_number() { + // when header is too far from the future + assert_eq!( + default_accept_into_pool(|storage, validators| ( + custom_block_i(storage, 4, validators, |header| header.number = 100), + None, + ),), + Err(Error::UnsignedTooFarInTheFuture), + ); + } + + #[test] + fn pool_performs_full_verification_when_parent_is_known() { + // if parent is known, then we'll execute contextual_checks, which + // checks for DoubleVote + assert_eq!( + default_accept_into_pool(|storage, validators| ( + custom_block_i(storage, 4, validators, |header| header.seal[0] = + block_i(storage, 3, validators).seal[0].clone()), + None, + ),), + Err(Error::DoubleVote), + ); + } + + #[test] + fn pool_performs_validators_checks_when_parent_is_unknown() { + // if parent is unknown, then we still need to check if header has required signature + // (even if header will be considered invalid/duplicate later, we can use this signature + // as a proof of malicious action by this validator) + assert_eq!( + default_accept_into_pool(|_, validators| ( + signed_header( + validators, + Header { + author: validators[1].address().as_fixed_bytes().into(), + seal: vec![vec![8].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: [42; 32].into(), + number: 8, + ..Default::default() + }, + 43 + ), + None, + )), + Err(Error::NotValidator), + ); + } + + #[test] + fn pool_verifies_header_with_known_parent() { + let mut hash = None; + assert_eq!( + default_accept_into_pool(|storage, validators| { + let header = block_i(&storage, 4, &validators); + hash = Some(header.hash()); + (header, None) + }), + Ok(( + // no tags are required + vec![], + // header provides two tags + vec![ + (4u64, validators_addresses(3)[1]).encode(), + (4u64, hash.unwrap()).encode(), + ], + )), + ); + } + + #[test] + fn pool_verifies_header_with_unknown_parent() { + let mut hash = None; + assert_eq!( + default_accept_into_pool(|_, validators| { + let header = signed_header( + validators, + Header { + author: validators[2].address().as_fixed_bytes().into(), + seal: vec![vec![47].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: [42; 32].into(), + number: 5, + ..Default::default() + }, + 47, + ); + hash = Some(header.hash()); + (header, None) + }), + Ok(( + // parent tag required + vec![(4u64, [42u8; 32]).encode(),], + // header provides two tags + vec![ + (5u64, validators_addresses(3)[2]).encode(), + (5u64, hash.unwrap()).encode(), + ], + )), + ); + } + + #[test] + fn pool_uses_next_validators_set_when_finalized_fails() { + assert_eq!( + default_accept_into_pool(|storage, actual_validators| { + // change finalized set at parent header + storage.change_validators_set_at(3, validators_addresses(1), None); + + // header is signed using wrong set + let header = signed_header( + actual_validators, + Header { + author: actual_validators[2].address().as_fixed_bytes().into(), + seal: vec![vec![47].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: [42; 32].into(), + number: 5, + ..Default::default() + }, + 47, + ); + + (header, None) + }), + Err(Error::NotValidator), + ); + + let mut hash = None; + assert_eq!( + default_accept_into_pool(|storage, actual_validators| { + // change finalized set at parent header + signal valid set at parent block + storage.change_validators_set_at(3, validators_addresses(10), Some(validators_addresses(3))); + + // header is signed using wrong set + let header = signed_header( + actual_validators, + Header { + author: actual_validators[2].address().as_fixed_bytes().into(), + seal: vec![vec![47].into(), vec![].into()], + gas_limit: kovan_aura_config().min_gas_limit, + parent_hash: [42; 32].into(), + number: 5, + ..Default::default() + }, + 47, + ); + hash = Some(header.hash()); + + (header, None) + }), + Ok(( + // parent tag required + vec![(4u64, [42u8; 32]).encode(),], + // header provides two tags + vec![ + (5u64, validators_addresses(3)[2]).encode(), + (5u64, hash.unwrap()).encode(), + ], + )), + ); + } + + #[test] + fn pool_rejects_headers_with_invalid_receipts() { + assert_eq!( + default_accept_into_pool(|storage, validators| { + let header = custom_block_i(&storage, 4, &validators, |header| { + header.log_bloom = (&[0xff; 256]).into(); + }); + (header, Some(vec![validators_change_recept(Default::default())])) + }), + Err(Error::TransactionsReceiptsMismatch), + ); + } + + #[test] + fn pool_accepts_headers_with_valid_receipts() { + let mut hash = None; + assert_eq!( + default_accept_into_pool(|storage, validators| { + let header = custom_block_i(&storage, 4, &validators, |header| { + header.log_bloom = (&[0xff; 256]).into(); + header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" + .parse() + .unwrap(); + }); + hash = Some(header.hash()); + (header, Some(vec![validators_change_recept(Default::default())])) + }), + Ok(( + // no tags are required + vec![], + // header provides two tags + vec![ + (4u64, validators_addresses(3)[1]).encode(), + (4u64, hash.unwrap()).encode(), + ], + )), + ); + } } diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 7a3dcbe2b7ece..750d4f39274ae 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -23,11 +23,22 @@ args: value_name: SUB_PORT help: Connect to Substrate node at given port. takes_value: true + - sub-tx-mode: + long: sub-tx-mode + value_name: MODE + help: Submit headers using signed (default) or unsigned transactions. Third mode - backup - submits signed transactions only when we believe that sync has stalled. + takes_value: true + possible_values: + - signed + - unsigned + - backup - sub-signer: long: sub-signer value_name: SUB_SIGNER help: The SURI of secret key to use when transactions are submitted to the Substrate node. + takes_value: true - sub-signer-password: long: sub-signer-password value_name: SUB_SIGNER_PASSWORD - help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. \ No newline at end of file + help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. + takes_value: true \ No newline at end of file diff --git a/relays/ethereum/src/ethereum_sync.rs b/relays/ethereum/src/ethereum_sync.rs index df5698f7e002f..b174d3819e470 100644 --- a/relays/ethereum/src/ethereum_sync.rs +++ b/relays/ethereum/src/ethereum_sync.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_headers::QueuedHeaders; -use crate::ethereum_sync_loop::EthereumSyncParams; +use crate::ethereum_sync_loop::{EthereumSyncParams, SubstrateTransactionMode}; use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; use codec::Encode; @@ -95,7 +95,12 @@ impl HeadersSync { } /// Select headers that need to be submitted to the Substrate node. - pub fn select_headers_to_submit(&self) -> Option> { + pub fn select_headers_to_submit(&self, stalled: bool) -> Option> { + // if we operate in backup mode, we only submit headers when sync has stalled + if self.params.sub_tx_mode == SubstrateTransactionMode::Backup && !stalled { + return None; + } + let headers_in_submit_status = self.headers.headers_in_status(HeaderStatus::Submitted); let headers_to_submit_count = self .params @@ -224,7 +229,7 @@ mod tests { assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(101))); eth_sync.headers.maybe_receipts_response(&id(101), false); assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(101))); - assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(101)])); + assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); // and header #102 is ready to be downloaded assert_eq!(eth_sync.select_new_header_to_download(), Some(102)); @@ -238,13 +243,13 @@ mod tests { assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(102))); eth_sync.headers.maybe_receipts_response(&id(102), false); assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(102))); - assert_eq!(eth_sync.select_headers_to_submit(), None); + assert_eq!(eth_sync.select_headers_to_submit(false), None); // substrate reports that it has imported block #101 eth_sync.substrate_best_header_response(id(101)); // and we are ready to submit #102 - assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(102)])); + assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(102)])); eth_sync.headers.headers_submitted(vec![id(102)]); // substrate reports that it has imported block #102 @@ -269,7 +274,7 @@ mod tests { eth_sync.headers.header_response(header(101).header().clone()); // we can't submit header #101, because its parent status is unknown - assert_eq!(eth_sync.select_headers_to_submit(), None); + assert_eq!(eth_sync.select_headers_to_submit(false), None); // instead we are trying to determine status of its parent (#100) assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeOrphan), Some(&header(101))); @@ -282,7 +287,7 @@ mod tests { eth_sync.headers.header_response(header(100).header().clone()); // we can't submit header #100, because its parent status is unknown - assert_eq!(eth_sync.select_headers_to_submit(), None); + assert_eq!(eth_sync.select_headers_to_submit(false), None); // instead we are trying to determine status of its parent (#99) assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeOrphan), Some(&header(100))); @@ -293,13 +298,13 @@ mod tests { // and we are ready to submit #100 assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(100))); eth_sync.headers.maybe_receipts_response(&id(100), false); - assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(100)])); + assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(100)])); eth_sync.headers.headers_submitted(vec![id(100)]); // and we are ready to submit #101 assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(101))); eth_sync.headers.maybe_receipts_response(&id(101), false); - assert_eq!(eth_sync.select_headers_to_submit(), Some(vec![&header(101)])); + assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); eth_sync.headers.headers_submitted(vec![id(101)]); } @@ -310,4 +315,26 @@ mod tests { eth_sync.substrate_best_header_response(id(100)); assert_eq!(eth_sync.headers.prune_border(), 50); } + + #[test] + fn only_submitting_headers_in_backup_mode_when_stalled() { + let mut eth_sync = HeadersSync::new(Default::default()); + eth_sync.params.sub_tx_mode = SubstrateTransactionMode::Backup; + + // ethereum reports best header #102 + eth_sync.ethereum_best_header_number_response(102); + + // substrate reports that it is at block #100 + eth_sync.substrate_best_header_response(id(100)); + + // block #101 is downloaded first + eth_sync.headers.header_response(header(101).header().clone()); + eth_sync.headers.maybe_receipts_response(&id(101), false); + + // ensure that headers are not submitted when sync is not stalled + assert_eq!(eth_sync.select_headers_to_submit(false), None); + + // ensure that headers are not submitted when sync is stalled + assert_eq!(eth_sync.select_headers_to_submit(true), Some(vec![&header(101)])); + } } diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 5c91b275106c8..b08d503a5fadd 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -37,6 +37,9 @@ const SUBSTRATE_TICK_INTERVAL_MS: u64 = 5_000; /// the subscriber will receive every best header (2) reorg won't always lead to sync /// stall and restart is a heavy operation (we forget all in-memory headers). const STALL_SYNC_TIMEOUT_MS: u64 = 30_000; +/// Delay (in milliseconds) after we have seen update of best Ethereum header in Substrate, +/// for us to treat sync stalled. ONLY when relay operates in backup mode. +const BACKUP_STALL_SYNC_TIMEOUT_MS: u64 = 5 * 60_000; /// Delay (in milliseconds) after connection-related error happened before we'll try /// reconnection again. const CONNECTION_ERROR_DELAY_MS: u64 = 10_000; @@ -57,6 +60,8 @@ pub struct EthereumSyncParams { pub sub_host: String, /// Substrate RPC port. pub sub_port: u16, + /// Substrate transactions submission mode. + pub sub_tx_mode: SubstrateTransactionMode, /// Substrate transactions signer. pub sub_signer: sp_core::sr25519::Pair, /// Maximal number of ethereum headers to pre-download. @@ -72,6 +77,18 @@ pub struct EthereumSyncParams { pub prune_depth: u64, } +/// Substrate transaction mode. +#[derive(Debug, PartialEq)] +pub enum SubstrateTransactionMode { + /// Submit eth headers using signed substrate transactions. + Signed, + /// Submit eth headers using unsigned substrate transactions. + Unsigned, + /// Submit eth headers using signed substrate transactions, but only when we + /// believe that sync has stalled. + Backup, +} + impl std::fmt::Debug for EthereumSyncParams { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { f.debug_struct("EthereumSyncParams") @@ -79,6 +96,7 @@ impl std::fmt::Debug for EthereumSyncParams { .field("eth_port", &self.eth_port) .field("sub_host", &self.sub_port) .field("sub_port", &self.sub_port) + .field("sub_tx_mode", &self.sub_tx_mode) .field("max_future_headers_to_download", &self.max_future_headers_to_download) .field("max_headers_in_submitted_status", &self.max_headers_in_submitted_status) .field("max_headers_in_single_submit", &self.max_headers_in_single_submit) @@ -98,6 +116,7 @@ impl Default for EthereumSyncParams { eth_port: 8545, sub_host: "localhost".into(), sub_port: 9933, + sub_tx_mode: SubstrateTransactionMode::Signed, sub_signer: sp_keyring::AccountKeyring::Alice.pair(), max_future_headers_to_download: 128, max_headers_in_submitted_status: 128, @@ -112,6 +131,10 @@ impl Default for EthereumSyncParams { pub fn run(params: EthereumSyncParams) { let mut local_pool = futures::executor::LocalPool::new(); let mut progress_context = (std::time::Instant::now(), None, None); + let sign_sub_transactions = match params.sub_tx_mode { + SubstrateTransactionMode::Signed | SubstrateTransactionMode::Backup => true, + SubstrateTransactionMode::Unsigned => false, + }; local_pool.run_until(async move { let eth_uri = format!("http://{}:{}", params.eth_host, params.eth_port); @@ -120,6 +143,7 @@ pub fn run(params: EthereumSyncParams) { let mut eth_sync = crate::ethereum_sync::HeadersSync::new(params); let mut stall_countdown = None; + let mut last_update_time = std::time::Instant::now(); let mut eth_maybe_client = None; let mut eth_best_block_number_required = false; @@ -220,6 +244,9 @@ pub fn run(params: EthereumSyncParams) { sub_best_block, |sub_best_block| { let head_updated = eth_sync.substrate_best_header_response(sub_best_block); + if head_updated { + last_update_time = std::time::Instant::now(); + } match head_updated { // IF head is updated AND there are still our transactions: // => restart stall countdown timer @@ -336,7 +363,9 @@ pub fn run(params: EthereumSyncParams) { sub_existence_status_future .set(substrate_client::ethereum_header_known(sub_client, parent_id).fuse()); - } else if let Some(headers) = eth_sync.select_headers_to_submit() { + } else if let Some(headers) = eth_sync.select_headers_to_submit( + last_update_time.elapsed() > std::time::Duration::from_millis(BACKUP_STALL_SYNC_TIMEOUT_MS), + ) { let ids = match headers.len() { 1 => format!("{:?}", headers[0].id()), 2 => format!("[{:?}, {:?}]", headers[0].id(), headers[1].id()), @@ -350,7 +379,9 @@ pub fn run(params: EthereumSyncParams) { ); let headers = headers.into_iter().cloned().collect(); - sub_submit_header_future.set(substrate_client::submit_ethereum_headers(sub_client, headers).fuse()); + sub_submit_header_future.set( + substrate_client::submit_ethereum_headers(sub_client, headers, sign_sub_transactions).fuse(), + ); // remember that we have submitted some headers if stall_countdown.is_none() { diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index bf256d6fad018..fb276b480cff2 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -99,5 +99,18 @@ fn ethereum_sync_params() -> Result eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Signed, + Some("unsigned") => { + eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Unsigned; + + // tx pool won't accept too much unsigned transactions + eth_sync_params.max_headers_in_submitted_status = 10; + } + Some("backup") => eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Backup, + Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), + None => eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Signed, + } + Ok(eth_sync_params) } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 799bf6151ed8b..51e2b1886e55e 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -132,7 +132,19 @@ pub async fn ethereum_header_known( pub async fn submit_ethereum_headers( client: Client, headers: Vec, -) -> (Client, Result<(TransactionHash, Vec), Error>) { + sign_transactions: bool, +) -> (Client, Result<(Vec, Vec), Error>) { + match sign_transactions { + true => submit_signed_ethereum_headers(client, headers).await, + false => submit_unsigned_ethereum_headers(client, headers).await, + } +} + +/// Submits signed Ethereum header to Substrate runtime. +pub async fn submit_signed_ethereum_headers( + client: Client, + headers: Vec, +) -> (Client, Result<(Vec, Vec), Error>) { let ids = headers.iter().map(|header| header.id()).collect(); let (client, genesis_hash) = match client.genesis_hash { Some(genesis_hash) => (client, genesis_hash), @@ -152,7 +164,9 @@ pub async fn submit_ethereum_headers( Ok(nonce) => nonce, Err(err) => return (client, Err(err)), }; - let transaction = create_submit_transaction(headers, &client.signer, nonce, genesis_hash); + + let transaction = create_signed_submit_transaction(headers, &client.signer, nonce, genesis_hash); + let encoded_transaction = transaction.encode(); let (client, transaction_hash) = call_rpc( client, @@ -160,7 +174,39 @@ pub async fn submit_ethereum_headers( Params::Array(vec![to_value(Bytes(encoded_transaction)).unwrap()]), ) .await; - (client, transaction_hash.map(|transaction_hash| (transaction_hash, ids))) + + ( + client, + transaction_hash.map(|transaction_hash| (vec![transaction_hash], ids)), + ) +} + +/// Submits unsigned Ethereum header to Substrate runtime. +pub async fn submit_unsigned_ethereum_headers( + mut client: Client, + headers: Vec, +) -> (Client, Result<(Vec, Vec), Error>) { + let ids = headers.iter().map(|header| header.id()).collect(); + let mut transactions_hashes = Vec::new(); + for header in headers { + let transaction = create_unsigned_submit_transaction(header); + + let encoded_transaction = transaction.encode(); + let (used_client, transaction_hash) = call_rpc( + client, + "author_submitExtrinsic", + Params::Array(vec![to_value(Bytes(encoded_transaction)).unwrap()]), + ) + .await; + + client = used_client; + transactions_hashes.push(match transaction_hash { + Ok(transaction_hash) => transaction_hash, + Err(error) => return (client, Err(error)), + }); + } + + (client, Ok((transactions_hashes, ids))) } /// Get Substrate block hash by its number. @@ -236,25 +282,26 @@ async fn call_rpc_u64(mut client: Client, method: &'static str, params: Params) (client, result) } -/// Create Substrate transaction for submitting Ethereum header. -fn create_submit_transaction( +/// Create signed Substrate transaction for submitting Ethereum headers. +fn create_signed_submit_transaction( headers: Vec, signer: &sp_core::sr25519::Pair, index: node_primitives::Index, genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { - let function = bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_headers( - headers - .into_iter() - .map(|header| { - let (header, receipts) = header.extract(); - ( - into_substrate_ethereum_header(&header), - into_substrate_ethereum_receipts(&receipts), - ) - }) - .collect(), - )); + let function = + bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + headers + .into_iter() + .map(|header| { + let (header, receipts) = header.extract(); + ( + into_substrate_ethereum_header(&header), + into_substrate_ethereum_receipts(&receipts), + ) + }) + .collect(), + )); let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( @@ -284,3 +331,15 @@ fn create_submit_transaction( bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account().into(), signature.into(), extra) } + +/// Create unsigned Substrate transaction for submitting Ethereum header. +fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { + let (header, receipts) = header.extract(); + let function = + bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + into_substrate_ethereum_header(&header), + into_substrate_ethereum_receipts(&receipts), + )); + + bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) +} From fbc457a0a19df06b2923b96754441ccb973bc905 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 8 Apr 2020 03:48:15 +0300 Subject: [PATCH 0032/1210] Make relay generic over source/target chains (#58) * renamed to-be-generic files * make everything required generic over source/target chains * some more fixes * cargo fmt --all * trait functions -> trait constants * cargo --fmt --all --- relays/ethereum/Cargo.toml | 1 + relays/ethereum/src/cli.yml | 81 +-- relays/ethereum/src/ethereum_client.rs | 8 +- relays/ethereum/src/ethereum_sync_loop.rs | 577 +++++------------- relays/ethereum/src/ethereum_types.rs | 103 +--- .../src/{ethereum_headers.rs => headers.rs} | 553 +++++++++-------- relays/ethereum/src/main.rs | 42 +- relays/ethereum/src/substrate_client.rs | 22 +- .../src/{ethereum_sync.rs => sync.rs} | 219 ++++--- relays/ethereum/src/sync_loop.rs | 464 ++++++++++++++ relays/ethereum/src/sync_types.rs | 130 ++++ 11 files changed, 1294 insertions(+), 906 deletions(-) rename relays/ethereum/src/{ethereum_headers.rs => headers.rs} (60%) rename relays/ethereum/src/{ethereum_sync.rs => sync.rs} (56%) create mode 100644 relays/ethereum/src/sync_loop.rs create mode 100644 relays/ethereum/src/sync_types.rs diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 06b29e7e8effc..93a8d1b0a3eed 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,6 +15,7 @@ futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } linked-hash-map = "0.5.2" log = "0.4.8" +num-traits = "0.2" parking_lot = "0.10.0" rustc-hex = "2.0.1" serde = { version = "1.0.106", features = ["derive"] } diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 750d4f39274ae..fad56da722c5a 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -2,43 +2,44 @@ name: ethsub-bridge version: "0.1.0" author: Parity Technologies about: Parity Ethereum (PoA) <-> Substrate bridge -args: - - eth-host: - long: eth-host - value_name: ETH_HOST - help: Connect to Ethereum node at given host. - takes_value: true - - eth-port: - long: eth-port - value_name: ETH_PORT - help: Connect to Ethereum node at given port. - takes_value: true - - sub-host: - long: sub-host - value_name: SUB_HOST - help: Connect to Substrate node at given host. - takes_value: true - - sub-port: - long: sub-port - value_name: SUB_PORT - help: Connect to Substrate node at given port. - takes_value: true - - sub-tx-mode: - long: sub-tx-mode - value_name: MODE - help: Submit headers using signed (default) or unsigned transactions. Third mode - backup - submits signed transactions only when we believe that sync has stalled. - takes_value: true - possible_values: - - signed - - unsigned - - backup - - sub-signer: - long: sub-signer - value_name: SUB_SIGNER - help: The SURI of secret key to use when transactions are submitted to the Substrate node. - takes_value: true - - sub-signer-password: - long: sub-signer-password - value_name: SUB_SIGNER_PASSWORD - help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. - takes_value: true \ No newline at end of file +subcommands: + - eth-to-sub: + about: Synchronize headers from Ethereum node to Substrate node. + args: + - eth-host: + long: eth-host + value_name: ETH_HOST + help: Connect to Ethereum node at given host. + takes_value: true + - eth-port: + long: eth-port + value_name: ETH_PORT + help: Connect to Ethereum node at given port. + takes_value: true + - sub-host: + long: sub-host + value_name: SUB_HOST + help: Connect to Substrate node at given host. + takes_value: true + - sub-port: + long: sub-port + value_name: SUB_PORT + help: Connect to Substrate node at given port. + takes_value: true + - sub-tx-mode: + long: sub-tx-mode + value_name: MODE + help: Submit headers using signed (default) or unsigned transactions. Third mode - backup - submits signed transactions only when we believe that sync has stalled. + takes_value: true + possible_values: + - signed + - unsigned + - backup + - sub-signer: + long: sub-signer + value_name: SUB_SIGNER + help: The SURI of secret key to use when transactions are submitted to the Substrate node. + - sub-signer-password: + long: sub-signer-password + value_name: SUB_SIGNER_PASSWORD + help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 30a6bfb28a8c2..cddbc8bc148f1 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_sync_loop::MaybeConnectionError; -use crate::ethereum_types::{Header, HeaderId, Receipt, H256, U64}; +use crate::ethereum_types::{EthereumHeaderId, Header, Receipt, H256, U64}; +use crate::sync_types::MaybeConnectionError; use jsonrpsee::common::Params; use jsonrpsee::raw::{RawClient, RawClientError}; use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; @@ -117,9 +117,9 @@ pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result, -) -> (Client, Result<(HeaderId, Vec), Error>) { +) -> (Client, Result<(EthereumHeaderId, Vec), Error>) { let mut transactions_receipts = Vec::with_capacity(transacactions.len()); for transacaction in transacactions { let (next_client, transaction_receipt) = transaction_receipt(client, transacaction).await; diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index b08d503a5fadd..705d78fe9cd4d 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -15,40 +15,18 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_client; -use crate::ethereum_types::HeaderStatus as EthereumHeaderStatus; +use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; use crate::substrate_client; -use futures::{future::FutureExt, stream::StreamExt}; - -// TODO: when SharedClient will be available, switch to Substrate headers subscription -// (because we do not need old Substrate headers) +use crate::sync::{HeadersSyncParams, TargetTransactionMode}; +use crate::sync_loop::{SourceClient, TargetClient}; +use futures::future::FutureExt; +use std::{future::Future, pin::Pin}; +pub use web3::types::H256; /// Interval (in ms) at which we check new Ethereum headers when we are synced/almost synced. const ETHEREUM_TICK_INTERVAL_MS: u64 = 10_000; /// Interval (in ms) at which we check new Substrate blocks. const SUBSTRATE_TICK_INTERVAL_MS: u64 = 5_000; -/// When we submit Ethereum headers to Substrate runtime, but see no updates of best -/// Ethereum block known to Substrate runtime during STALL_SYNC_TIMEOUT_MS milliseconds, -/// we consider that our headers are rejected because there has been reorg in Substrate. -/// This reorg could invalidate our knowledge about sync process (i.e. we have asked if -/// HeaderA is known to Substrate, but then reorg happened and the answer is different -/// now) => we need to reset sync. -/// The other option is to receive **EVERY** best Substrate header and check if it is -/// direct child of previous best header. But: (1) subscription doesn't guarantee that -/// the subscriber will receive every best header (2) reorg won't always lead to sync -/// stall and restart is a heavy operation (we forget all in-memory headers). -const STALL_SYNC_TIMEOUT_MS: u64 = 30_000; -/// Delay (in milliseconds) after we have seen update of best Ethereum header in Substrate, -/// for us to treat sync stalled. ONLY when relay operates in backup mode. -const BACKUP_STALL_SYNC_TIMEOUT_MS: u64 = 5 * 60_000; -/// Delay (in milliseconds) after connection-related error happened before we'll try -/// reconnection again. -const CONNECTION_ERROR_DELAY_MS: u64 = 10_000; - -/// Error type that can signal connection errors. -pub trait MaybeConnectionError { - /// Returns true if error (maybe) represents connection error. - fn is_connection_error(&self) -> bool; -} /// Ethereum synchronization parameters. pub struct EthereumSyncParams { @@ -60,33 +38,10 @@ pub struct EthereumSyncParams { pub sub_host: String, /// Substrate RPC port. pub sub_port: u16, - /// Substrate transactions submission mode. - pub sub_tx_mode: SubstrateTransactionMode, /// Substrate transactions signer. pub sub_signer: sp_core::sr25519::Pair, - /// Maximal number of ethereum headers to pre-download. - pub max_future_headers_to_download: usize, - /// Maximal number of active (we believe) submit header transactions. - pub max_headers_in_submitted_status: usize, - /// Maximal number of headers in single submit request. - pub max_headers_in_single_submit: usize, - /// Maximal total headers size in single submit request. - pub max_headers_size_in_single_submit: usize, - /// We only may store and accept (from Ethereum node) headers that have - /// number >= than best_substrate_header.number - prune_depth. - pub prune_depth: u64, -} - -/// Substrate transaction mode. -#[derive(Debug, PartialEq)] -pub enum SubstrateTransactionMode { - /// Submit eth headers using signed substrate transactions. - Signed, - /// Submit eth headers using unsigned substrate transactions. - Unsigned, - /// Submit eth headers using signed substrate transactions, but only when we - /// believe that sync has stalled. - Backup, + /// Synchronization parameters. + pub sync_params: HeadersSyncParams, } impl std::fmt::Debug for EthereumSyncParams { @@ -96,15 +51,7 @@ impl std::fmt::Debug for EthereumSyncParams { .field("eth_port", &self.eth_port) .field("sub_host", &self.sub_port) .field("sub_port", &self.sub_port) - .field("sub_tx_mode", &self.sub_tx_mode) - .field("max_future_headers_to_download", &self.max_future_headers_to_download) - .field("max_headers_in_submitted_status", &self.max_headers_in_submitted_status) - .field("max_headers_in_single_submit", &self.max_headers_in_single_submit) - .field( - "max_headers_size_in_single_submit", - &self.max_headers_size_in_single_submit, - ) - .field("prune_depth", &self.prune_depth) + .field("sync_params", &self.sync_params) .finish() } } @@ -116,394 +63,158 @@ impl Default for EthereumSyncParams { eth_port: 8545, sub_host: "localhost".into(), sub_port: 9933, - sub_tx_mode: SubstrateTransactionMode::Signed, sub_signer: sp_keyring::AccountKeyring::Alice.pair(), - max_future_headers_to_download: 128, - max_headers_in_submitted_status: 128, - max_headers_in_single_submit: 32, - max_headers_size_in_single_submit: 131_072, - prune_depth: 4096, + sync_params: Default::default(), } } } -/// Run Ethereum headers synchronization. -pub fn run(params: EthereumSyncParams) { - let mut local_pool = futures::executor::LocalPool::new(); - let mut progress_context = (std::time::Instant::now(), None, None); - let sign_sub_transactions = match params.sub_tx_mode { - SubstrateTransactionMode::Signed | SubstrateTransactionMode::Backup => true, - SubstrateTransactionMode::Unsigned => false, - }; - - local_pool.run_until(async move { - let eth_uri = format!("http://{}:{}", params.eth_host, params.eth_port); - let sub_uri = format!("http://{}:{}", params.sub_host, params.sub_port); - let sub_signer = params.sub_signer.clone(); - - let mut eth_sync = crate::ethereum_sync::HeadersSync::new(params); - let mut stall_countdown = None; - let mut last_update_time = std::time::Instant::now(); - - let mut eth_maybe_client = None; - let mut eth_best_block_number_required = false; - let eth_best_block_number_future = ethereum_client::best_block_number(ethereum_client::client(ð_uri)).fuse(); - let eth_new_header_future = futures::future::Fuse::terminated(); - let eth_orphan_header_future = futures::future::Fuse::terminated(); - let eth_receipts_future = futures::future::Fuse::terminated(); - let eth_go_offline_future = futures::future::Fuse::terminated(); - let eth_tick_stream = interval(ETHEREUM_TICK_INTERVAL_MS).fuse(); - - let mut sub_maybe_client = None; - let mut sub_best_block_required = false; - let sub_best_block_future = - substrate_client::best_ethereum_block(substrate_client::client(&sub_uri, sub_signer)).fuse(); - let sub_receipts_check_future = futures::future::Fuse::terminated(); - let sub_existence_status_future = futures::future::Fuse::terminated(); - let sub_submit_header_future = futures::future::Fuse::terminated(); - let sub_go_offline_future = futures::future::Fuse::terminated(); - let sub_tick_stream = interval(SUBSTRATE_TICK_INTERVAL_MS).fuse(); - - futures::pin_mut!( - eth_best_block_number_future, - eth_new_header_future, - eth_orphan_header_future, - eth_receipts_future, - eth_go_offline_future, - eth_tick_stream, - sub_best_block_future, - sub_receipts_check_future, - sub_existence_status_future, - sub_submit_header_future, - sub_go_offline_future, - sub_tick_stream - ); - - loop { - futures::select! { - (eth_client, eth_best_block_number) = eth_best_block_number_future => { - eth_best_block_number_required = false; - - process_future_result( - &mut eth_maybe_client, - eth_client, - eth_best_block_number, - |eth_best_block_number| eth_sync.ethereum_best_header_number_response(eth_best_block_number), - &mut eth_go_offline_future, - |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), - "Error retrieving best header number from Ethereum number", - ); - }, - (eth_client, eth_new_header) = eth_new_header_future => { - process_future_result( - &mut eth_maybe_client, - eth_client, - eth_new_header, - |eth_new_header| eth_sync.headers_mut().header_response(eth_new_header), - &mut eth_go_offline_future, - |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), - "Error retrieving header from Ethereum node", - ); - }, - (eth_client, eth_orphan_header) = eth_orphan_header_future => { - process_future_result( - &mut eth_maybe_client, - eth_client, - eth_orphan_header, - |eth_orphan_header| eth_sync.headers_mut().header_response(eth_orphan_header), - &mut eth_go_offline_future, - |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), - "Error retrieving orphan header from Ethereum node", - ); - }, - (eth_client, eth_receipts) = eth_receipts_future => { - process_future_result( - &mut eth_maybe_client, - eth_client, - eth_receipts, - |(header, receipts)| eth_sync.headers_mut().receipts_response(&header, receipts), - &mut eth_go_offline_future, - |eth_client| delay(CONNECTION_ERROR_DELAY_MS, eth_client), - "Error retrieving transactions receipts from Ethereum node", - ); - }, - eth_client = eth_go_offline_future => { - eth_maybe_client = Some(eth_client); - }, - _ = eth_tick_stream.next() => { - if eth_sync.is_almost_synced() { - eth_best_block_number_required = true; - } - }, - (sub_client, sub_best_block) = sub_best_block_future => { - sub_best_block_required = false; - - process_future_result( - &mut sub_maybe_client, - sub_client, - sub_best_block, - |sub_best_block| { - let head_updated = eth_sync.substrate_best_header_response(sub_best_block); - if head_updated { - last_update_time = std::time::Instant::now(); - } - match head_updated { - // IF head is updated AND there are still our transactions: - // => restart stall countdown timer - true if eth_sync.headers().headers_in_status(EthereumHeaderStatus::Submitted) != 0 => - stall_countdown = Some(std::time::Instant::now()), - // IF head is updated AND there are no our transactions: - // => stop stall countdown timer - true => stall_countdown = None, - // IF head is not updated AND stall countdown is not yet completed - // => do nothing - false if stall_countdown - .map(|stall_countdown| std::time::Instant::now() - stall_countdown < - std::time::Duration::from_millis(STALL_SYNC_TIMEOUT_MS)) - .unwrap_or(true) - => (), - // IF head is not updated AND stall countdown has completed - // => restart sync - false => { - log::info!( - target: "bridge", - "Possible Substrate fork detected. Restarting Ethereum headers synchronization.", - ); - stall_countdown = None; - eth_sync.restart(); - }, - } - }, - &mut sub_go_offline_future, - |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), - "Error retrieving best known header from Substrate node", - ); - }, - (sub_client, sub_existence_status) = sub_existence_status_future => { - process_future_result( - &mut sub_maybe_client, - sub_client, - sub_existence_status, - |(sub_header, sub_existence_status)| eth_sync - .headers_mut() - .maybe_orphan_response(&sub_header, sub_existence_status), - &mut sub_go_offline_future, - |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), - "Error retrieving existence status from Substrate node", - ); - }, - (sub_client, sub_submit_header_result) = sub_submit_header_future => { - process_future_result( - &mut sub_maybe_client, - sub_client, - sub_submit_header_result, - |(_, submitted_headers)| eth_sync.headers_mut().headers_submitted(submitted_headers), - &mut sub_go_offline_future, - |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), - "Error submitting headers to Substrate node", - ); - }, - (sub_client, sub_receipts_check_result) = sub_receipts_check_future => { - // we can minimize number of receipts_check calls by checking header - // logs bloom here, but it may give us false positives (when authorities - // source is contract, we never need any logs) - process_future_result( - &mut sub_maybe_client, - sub_client, - sub_receipts_check_result, - |(header, receipts_check_result)| eth_sync - .headers_mut() - .maybe_receipts_response(&header, receipts_check_result), - &mut sub_go_offline_future, - |sub_client| delay(CONNECTION_ERROR_DELAY_MS, sub_client), - "Error retrieving receipts requirement from Substrate node", - ); - }, - sub_client = sub_go_offline_future => { - sub_maybe_client = Some(sub_client); - }, - _ = sub_tick_stream.next() => { - sub_best_block_required = true; - }, - } - - // print progress - progress_context = print_progress(progress_context, ð_sync); - - // if client is available: wait, or call Substrate RPC methods - if let Some(sub_client) = sub_maybe_client.take() { - // the priority is to: - // 1) get best block - it stops us from downloading/submitting new blocks + we call it rarely; - // 2) check transactions receipts - it stops us from downloading/submitting new blocks; - // 3) check existence - it stops us from submitting new blocks; - // 4) submit header - - if sub_best_block_required { - log::debug!(target: "bridge", "Asking Substrate about best block"); - sub_best_block_future.set(substrate_client::best_ethereum_block(sub_client).fuse()); - } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::MaybeReceipts) { - log::debug!( - target: "bridge", - "Checking if header submission requires receipts: {:?}", - header.id(), - ); - - let header = header.clone(); - sub_receipts_check_future - .set(substrate_client::ethereum_receipts_required(sub_client, header).fuse()); - } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::MaybeOrphan) { - // for MaybeOrphan we actually ask for parent' header existence - let parent_id = header.parent_id(); - - log::debug!( - target: "bridge", - "Asking Substrate node for existence of: {:?}", - parent_id, - ); - - sub_existence_status_future - .set(substrate_client::ethereum_header_known(sub_client, parent_id).fuse()); - } else if let Some(headers) = eth_sync.select_headers_to_submit( - last_update_time.elapsed() > std::time::Duration::from_millis(BACKUP_STALL_SYNC_TIMEOUT_MS), - ) { - let ids = match headers.len() { - 1 => format!("{:?}", headers[0].id()), - 2 => format!("[{:?}, {:?}]", headers[0].id(), headers[1].id()), - len => format!("[{:?} ... {:?}]", headers[0].id(), headers[len - 1].id()), - }; - log::debug!( - target: "bridge", - "Submitting {} header(s) to Substrate node: {:?}", - headers.len(), - ids, - ); - - let headers = headers.into_iter().cloned().collect(); - sub_submit_header_future.set( - substrate_client::submit_ethereum_headers(sub_client, headers, sign_sub_transactions).fuse(), - ); - - // remember that we have submitted some headers - if stall_countdown.is_none() { - stall_countdown = Some(std::time::Instant::now()); - } - } else { - sub_maybe_client = Some(sub_client); - } - } - - // if client is available: wait, or call Ethereum RPC methods - if let Some(eth_client) = eth_maybe_client.take() { - // the priority is to: - // 1) get best block - it stops us from downloading new blocks + we call it rarely; - // 2) check transactions receipts - it stops us from downloading/submitting new blocks; - // 3) check existence - it stops us from submitting new blocks; - // 4) submit header +/// Ethereum client as headers source. +struct EthereumHeadersSource { + /// Ethereum node client. + client: ethereum_client::Client, +} - if eth_best_block_number_required { - log::debug!(target: "bridge", "Asking Ethereum node about best block number"); - eth_best_block_number_future.set(ethereum_client::best_block_number(eth_client).fuse()); - } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::Receipts) { - let id = header.id(); - log::debug!( - target: "bridge", - "Retrieving receipts for header: {:?}", - id, - ); - eth_receipts_future.set( - ethereum_client::transactions_receipts(eth_client, id, header.header().transactions.clone()) - .fuse(), - ); - } else if let Some(header) = eth_sync.headers().header(EthereumHeaderStatus::Orphan) { - // for Orphan we actually ask for parent' header - let parent_id = header.parent_id(); +impl SourceClient for EthereumHeadersSource { + type Error = ethereum_client::Error; + type BestBlockNumberFuture = Pin)>>>; + type HeaderByHashFuture = Pin)>>>; + type HeaderByNumberFuture = Pin)>>>; + type HeaderExtraFuture = + Pin), Self::Error>)>>>; + + fn best_block_number(self) -> Self::BestBlockNumberFuture { + ethereum_client::best_block_number(self.client) + .map(|(client, result)| (EthereumHeadersSource { client }, result)) + .boxed() + } - log::debug!( - target: "bridge", - "Going to download orphan header from Ethereum node: {:?}", - parent_id, - ); + fn header_by_hash(self, hash: H256) -> Self::HeaderByHashFuture { + ethereum_client::header_by_hash(self.client, hash) + .map(|(client, result)| (EthereumHeadersSource { client }, result)) + .boxed() + } - eth_orphan_header_future.set(ethereum_client::header_by_hash(eth_client, parent_id.1).fuse()); - } else if let Some(id) = eth_sync.select_new_header_to_download() { - log::debug!( - target: "bridge", - "Going to download new header from Ethereum node: {:?}", - id, - ); + fn header_by_number(self, number: u64) -> Self::HeaderByNumberFuture { + ethereum_client::header_by_number(self.client, number) + .map(|(client, result)| (EthereumHeadersSource { client }, result)) + .boxed() + } - eth_new_header_future.set(ethereum_client::header_by_number(eth_client, id).fuse()); - } else { - eth_maybe_client = Some(eth_client); - } - } - } - }); + fn header_extra(self, id: EthereumHeaderId, header: &Header) -> Self::HeaderExtraFuture { + ethereum_client::transactions_receipts(self.client, id, header.transactions.clone()) + .map(|(client, result)| (EthereumHeadersSource { client }, result)) + .boxed() + } } -fn print_progress( - progress_context: (std::time::Instant, Option, Option), - eth_sync: &crate::ethereum_sync::HeadersSync, -) -> (std::time::Instant, Option, Option) { - let (prev_time, prev_best_header, prev_target_header) = progress_context; - let now_time = std::time::Instant::now(); - let (now_best_header, now_target_header) = eth_sync.status(); +/// Substrate client as Ethereum headers target. +struct SubstrateHeadersTarget { + /// Substrate node client. + client: substrate_client::Client, + /// Substrate transactions signer. + signer: sp_core::sr25519::Pair, + /// Whether we want to submit signed (true), or unsigned (false) transactions. + sign_transactions: bool, +} - let need_update = now_time - prev_time > std::time::Duration::from_secs(10) - || match (prev_best_header, now_best_header) { - (Some(prev_best_header), Some(now_best_header)) => now_best_header.0.saturating_sub(prev_best_header) > 10, - _ => false, - }; - if !need_update { - return (prev_time, prev_best_header, prev_target_header); +impl TargetClient for SubstrateHeadersTarget { + type Error = substrate_client::Error; + type BestHeaderIdFuture = Pin)>>>; + type IsKnownHeaderFuture = Pin)>>>; + type RequiresExtraFuture = Pin)>>>; + type SubmitHeadersFuture = Pin, Self::Error>)>>>; + + fn best_header_id(self) -> Self::BestHeaderIdFuture { + let (signer, sign_transactions) = (self.signer, self.sign_transactions); + substrate_client::best_ethereum_block(self.client) + .map(move |(client, result)| { + ( + SubstrateHeadersTarget { + client, + signer, + sign_transactions, + }, + result, + ) + }) + .boxed() } - log::info!( - target: "bridge", - "Synced {:?} of {:?} headers", - now_best_header.map(|id| id.0), - now_target_header, - ); - (now_time, now_best_header.clone().map(|id| id.0), *now_target_header) -} + fn is_known_header(self, id: EthereumHeaderId) -> Self::IsKnownHeaderFuture { + let (signer, sign_transactions) = (self.signer, self.sign_transactions); + substrate_client::ethereum_header_known(self.client, id) + .map(move |(client, result)| { + ( + SubstrateHeadersTarget { + client, + signer, + sign_transactions, + }, + result, + ) + }) + .boxed() + } -async fn delay(timeout_ms: u64, retval: T) -> T { - async_std::task::sleep(std::time::Duration::from_millis(timeout_ms)).await; - retval -} + fn requires_extra(self, header: &QueuedEthereumHeader) -> Self::RequiresExtraFuture { + // we can minimize number of receipts_check calls by checking header + // logs bloom here, but it may give us false positives (when authorities + // source is contract, we never need any logs) + let (signer, sign_transactions) = (self.signer, self.sign_transactions); + substrate_client::ethereum_receipts_required(self.client, header.clone()) + .map(move |(client, result)| { + ( + SubstrateHeadersTarget { + client, + signer, + sign_transactions, + }, + result, + ) + }) + .boxed() + } -fn interval(timeout_ms: u64) -> impl futures::Stream { - futures::stream::unfold((), move |_| async move { - delay(timeout_ms, ()).await; - Some(((), ())) - }) + fn submit_headers(self, headers: Vec) -> Self::SubmitHeadersFuture { + let (signer, sign_transactions) = (self.signer, self.sign_transactions); + substrate_client::submit_ethereum_headers(self.client, signer.clone(), headers, sign_transactions) + .map(move |(client, result)| { + ( + SubstrateHeadersTarget { + client, + signer, + sign_transactions, + }, + result.map(|(_, submitted_headers)| submitted_headers), + ) + }) + .boxed() + } } -fn process_future_result( - maybe_client: &mut Option, - client: TClient, - result: Result, - on_success: impl FnOnce(TResult), - go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, - go_offline: impl FnOnce(TClient) -> TGoOfflineFuture, - error_pattern: &'static str, -) where - TError: std::fmt::Debug + MaybeConnectionError, - TGoOfflineFuture: FutureExt, -{ - match result { - Ok(result) => { - *maybe_client = Some(client); - on_success(result); - } - Err(error) => { - if error.is_connection_error() { - go_offline_future.set(go_offline(client).fuse()); - } else { - *maybe_client = Some(client); - } +/// Run Ethereum headers synchronization. +pub fn run(params: EthereumSyncParams) { + let eth_uri = format!("http://{}:{}", params.eth_host, params.eth_port); + let eth_client = ethereum_client::client(ð_uri); + + let sub_uri = format!("http://{}:{}", params.sub_host, params.sub_port); + let sub_client = substrate_client::client(&sub_uri); + let sub_signer = params.sub_signer; + let sign_sub_transactions = match params.sync_params.target_tx_mode { + TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, + TargetTransactionMode::Unsigned => false, + }; - log::error!(target: "bridge", "{}: {:?}", error_pattern, error); - } - } + crate::sync_loop::run( + EthereumHeadersSource { client: eth_client }, + ETHEREUM_TICK_INTERVAL_MS, + SubstrateHeadersTarget { + client: sub_client, + signer: sub_signer, + sign_transactions: sign_sub_transactions, + }, + SUBSTRATE_TICK_INTERVAL_MS, + params.sync_params, + ); } diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index beb6c100fb4d9..93c47da4f7fbe 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; +use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use codec::Encode; + pub use web3::types::{Bytes, H256, U128, U64}; /// When header is just received from the Ethereum node, we check that it has @@ -30,84 +34,43 @@ pub type Header = web3::types::Block; /// Ethereum transaction receipt type. pub type Receipt = web3::types::TransactionReceipt; -/// Ethereum header Id. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct HeaderId(pub u64, pub H256); +/// Ethereum header ID. +pub type EthereumHeaderId = HeaderId; -impl From<&Header> for HeaderId { - fn from(header: &Header) -> HeaderId { - HeaderId( - header.number.expect(HEADER_ID_PROOF).as_u64(), - header.hash.expect(HEADER_ID_PROOF), - ) - } -} +/// Queued ethereum header ID. +pub type QueuedEthereumHeader = QueuedHeader; -/// Ethereum header synchronization status. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum HeaderStatus { - /// Header is unknown. - Unknown, - /// Header is in MaybeOrphan queue. - MaybeOrphan, - /// Header is in Orphan queue. - Orphan, - /// Header is in MaybeReceipts queue. - MaybeReceipts, - /// Header is in Receipts queue. - Receipts, - /// Header is in Ready queue. - Ready, - /// Header has been recently submitted to the Substrate runtime. - Submitted, - /// Header is known to the Substrate runtime. - Synced, -} - -#[derive(Clone, Debug, Default)] +/// Ethereum synchronization pipeline. +#[derive(Clone, Copy, Debug)] #[cfg_attr(test, derive(PartialEq))] -pub struct QueuedHeader { - header: Header, - receipts: Option>, -} - -impl QueuedHeader { - /// Creates new queued header. - pub fn new(header: Header) -> Self { - QueuedHeader { header, receipts: None } - } - - /// Returns ID of header. - pub fn id(&self) -> HeaderId { - (&self.header).into() +pub struct EthereumHeadersSyncPipeline; + +impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { + const SOURCE_NAME: &'static str = "Ethereum"; + const TARGET_NAME: &'static str = "Substrate"; + + type Hash = H256; + type Number = u64; + type Header = Header; + type Extra = Vec; + + fn estimate_size(source: &QueuedHeader) -> usize { + into_substrate_ethereum_header(source.header()).encode().len() + + into_substrate_ethereum_receipts(source.extra()) + .map(|extra| extra.encode().len()) + .unwrap_or(0) } +} - /// Returns ID of parent header. - pub fn parent_id(&self) -> HeaderId { +impl SourceHeader for Header { + fn id(&self) -> EthereumHeaderId { HeaderId( - self.header.number.expect(HEADER_ID_PROOF).as_u64() - 1, - self.header.parent_hash, + self.number.expect(HEADER_ID_PROOF).as_u64(), + self.hash.expect(HEADER_ID_PROOF), ) } - /// Returns reference to header. - pub fn header(&self) -> &Header { - &self.header - } - - /// Returns reference to transactions receipts. - pub fn receipts(&self) -> &Option> { - &self.receipts - } - - /// Extract header and receipts from self. - pub fn extract(self) -> (Header, Option>) { - (self.header, self.receipts) - } - - /// Set associated transaction receipts. - pub fn set_receipts(mut self, receipts: Vec) -> Self { - self.receipts = Some(receipts); - self + fn parent_id(&self) -> EthereumHeaderId { + HeaderId(self.number.expect(HEADER_ID_PROOF).as_u64() - 1, self.parent_hash) } } diff --git a/relays/ethereum/src/ethereum_headers.rs b/relays/ethereum/src/headers.rs similarity index 60% rename from relays/ethereum/src/ethereum_headers.rs rename to relays/ethereum/src/headers.rs index 881bc15fee816..841743ce1d5e5 100644 --- a/relays/ethereum/src/ethereum_headers.rs +++ b/relays/ethereum/src/headers.rs @@ -14,46 +14,63 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{Header, HeaderId, HeaderStatus, QueuedHeader, Receipt, H256}; +use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use num_traits::{One, Zero}; use std::collections::{ btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet, }; -type HeadersQueue = BTreeMap>; -type KnownHeaders = BTreeMap>; +type HeadersQueue

= + BTreeMap<

::Number, HashMap<

::Hash, QueuedHeader

>>; +type KnownHeaders

= + BTreeMap<

::Number, HashMap<

::Hash, HeaderStatus>>; /// Ethereum headers queue. -#[derive(Debug, Default)] -pub struct QueuedHeaders { - /// Headers that are received from Ethereum node, but we (native ethereum sync code) have +#[derive(Debug)] +pub struct QueuedHeaders { + /// Headers that are received from source node, but we (native sync code) have /// never seen their parents. So we need to check if we can/should submit this header. - maybe_orphan: HeadersQueue, - /// Headers that are received from Ethreum node, and we (native ethereum sync code) have + maybe_orphan: HeadersQueue

, + /// Headers that are received from source node, and we (native sync code) have /// checked that Substrate runtime doesn't know their parents. So we need to submit parents /// first. - orphan: HeadersQueue, - /// Headers that are ready to be submitted to Substrate runtime, but we need to check - /// whether submission requires transactions receipts to be provided. - maybe_receipts: HeadersQueue, - /// Headers that are ready to be submitted to Substrate runtime, but we need to retrieve - /// transactions receipts first. - receipts: HeadersQueue, - /// Headers that are ready to be submitted to Substrate runtime. - ready: HeadersQueue, - /// Headers that are (we believe) are currently submitted to Substrate runtime by our, + orphan: HeadersQueue

, + /// Headers that are ready to be submitted to target node, but we need to check + /// whether submission requires extra data to be provided. + maybe_extra: HeadersQueue

, + /// Headers that are ready to be submitted to target node, but we need to retrieve + /// extra data first. + extra: HeadersQueue

, + /// Headers that are ready to be submitted to target node. + ready: HeadersQueue

, + /// Headers that are (we believe) currently submitted to target node by our, /// not-yet mined transactions. - submitted: HeadersQueue, + submitted: HeadersQueue

, /// Pointers to all headers that we ever seen and we believe we can touch in the future. - known_headers: KnownHeaders, + known_headers: KnownHeaders

, /// Pruned blocks border. We do not store or accept any blocks with number less than /// this number. - prune_border: u64, + prune_border: P::Number, } -impl QueuedHeaders { +impl QueuedHeaders

{ + /// Returns new QueuedHeaders. + pub fn new() -> Self { + QueuedHeaders { + maybe_orphan: HeadersQueue::new(), + orphan: HeadersQueue::new(), + maybe_extra: HeadersQueue::new(), + extra: HeadersQueue::new(), + ready: HeadersQueue::new(), + submitted: HeadersQueue::new(), + known_headers: KnownHeaders::

::new(), + prune_border: Zero::zero(), + } + } + /// Returns prune border. #[cfg(test)] - pub fn prune_border(&self) -> u64 { + pub fn prune_border(&self) -> P::Number { self.prune_border } @@ -66,11 +83,11 @@ impl QueuedHeaders { .values() .fold(0, |total, headers| total + headers.len()), HeaderStatus::Orphan => self.orphan.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::MaybeReceipts => self - .maybe_receipts + HeaderStatus::MaybeExtra => self + .maybe_extra .values() .fold(0, |total, headers| total + headers.len()), - HeaderStatus::Receipts => self.receipts.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Extra => self.extra.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Ready => self.ready.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Submitted => self.submitted.values().fold(0, |total, headers| total + headers.len()), } @@ -83,24 +100,24 @@ impl QueuedHeaders { .fold(0, |total, headers| total + headers.len()) + self.orphan.values().fold(0, |total, headers| total + headers.len()) + self - .maybe_receipts + .maybe_extra .values() .fold(0, |total, headers| total + headers.len()) - + self.receipts.values().fold(0, |total, headers| total + headers.len()) + + self.extra.values().fold(0, |total, headers| total + headers.len()) + self.ready.values().fold(0, |total, headers| total + headers.len()) } /// Returns number of best block in the queue. - pub fn best_queued_number(&self) -> u64 { + pub fn best_queued_number(&self) -> P::Number { std::cmp::max( - self.maybe_orphan.keys().next_back().cloned().unwrap_or(0), + self.maybe_orphan.keys().next_back().cloned().unwrap_or_else(Zero::zero), std::cmp::max( - self.orphan.keys().next_back().cloned().unwrap_or(0), + self.orphan.keys().next_back().cloned().unwrap_or_else(Zero::zero), std::cmp::max( - self.maybe_receipts.keys().next_back().cloned().unwrap_or(0), + self.maybe_extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), std::cmp::max( - self.receipts.keys().next_back().cloned().unwrap_or(0), - self.ready.keys().next_back().cloned().unwrap_or(0), + self.extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), + self.ready.keys().next_back().cloned().unwrap_or_else(Zero::zero), ), ), ), @@ -108,7 +125,7 @@ impl QueuedHeaders { } /// Returns synchronization status of the header. - pub fn status(&self, id: &HeaderId) -> HeaderStatus { + pub fn status(&self, id: &HeaderId) -> HeaderStatus { self.known_headers .get(&id.0) .and_then(|x| x.get(&id.1)) @@ -117,46 +134,61 @@ impl QueuedHeaders { } /// Get oldest header from given queue. - pub fn header(&self, status: HeaderStatus) -> Option<&QueuedHeader> { + pub fn header(&self, status: HeaderStatus) -> Option<&QueuedHeader

> { match status { HeaderStatus::Unknown | HeaderStatus::Synced => return None, HeaderStatus::MaybeOrphan => oldest_header(&self.maybe_orphan), HeaderStatus::Orphan => oldest_header(&self.orphan), - HeaderStatus::MaybeReceipts => oldest_header(&self.maybe_receipts), - HeaderStatus::Receipts => oldest_header(&self.receipts), + HeaderStatus::MaybeExtra => oldest_header(&self.maybe_extra), + HeaderStatus::Extra => oldest_header(&self.extra), HeaderStatus::Ready => oldest_header(&self.ready), HeaderStatus::Submitted => oldest_header(&self.submitted), } } /// Get oldest headers from given queue until functor will return false. - pub fn headers(&self, status: HeaderStatus, f: impl FnMut(&QueuedHeader) -> bool) -> Option> { + pub fn headers( + &self, + status: HeaderStatus, + f: impl FnMut(&QueuedHeader

) -> bool, + ) -> Option>> { match status { HeaderStatus::Unknown | HeaderStatus::Synced => return None, HeaderStatus::MaybeOrphan => oldest_headers(&self.maybe_orphan, f), HeaderStatus::Orphan => oldest_headers(&self.orphan, f), - HeaderStatus::MaybeReceipts => oldest_headers(&self.maybe_receipts, f), - HeaderStatus::Receipts => oldest_headers(&self.receipts, f), + HeaderStatus::MaybeExtra => oldest_headers(&self.maybe_extra, f), + HeaderStatus::Extra => oldest_headers(&self.extra, f), HeaderStatus::Ready => oldest_headers(&self.ready, f), HeaderStatus::Submitted => oldest_headers(&self.submitted, f), } } - /// Appends new header to the queue. - pub fn header_response(&mut self, header: Header) { - let id = (&header).into(); + /// Appends new header, received from the source node, to the queue. + pub fn header_response(&mut self, header: P::Header) { + let id = header.id(); let status = self.status(&id); if status != HeaderStatus::Unknown { - log::debug!(target: "bridge", "Ignoring new Ethereum header: {:?}. Status is {:?}.", id, status); + log::debug!( + target: "bridge", + "Ignoring new {} header: {:?}. Status is {:?}.", + P::SOURCE_NAME, + id, + status, + ); return; } if id.0 < self.prune_border { - log::debug!(target: "bridge", "Ignoring ancient new Ethereum header: {:?}.", id); + log::debug!( + target: "bridge", + "Ignoring ancient new {} header: {:?}.", + P::SOURCE_NAME, + id, + ); return; } - let parent_id = HeaderId(id.0 - 1, header.parent_hash); + let parent_id = header.parent_id(); let parent_status = self.status(&parent_id); let header = QueuedHeader::new(header); @@ -169,22 +201,28 @@ impl QueuedHeaders { insert_header(&mut self.orphan, id, header); HeaderStatus::Orphan } - HeaderStatus::MaybeReceipts - | HeaderStatus::Receipts + HeaderStatus::MaybeExtra + | HeaderStatus::Extra | HeaderStatus::Ready | HeaderStatus::Submitted | HeaderStatus::Synced => { - insert_header(&mut self.maybe_receipts, id, header); - HeaderStatus::MaybeReceipts + insert_header(&mut self.maybe_extra, id, header); + HeaderStatus::MaybeExtra } }; self.known_headers.entry(id.0).or_default().insert(id.1, status); - log::debug!(target: "bridge", "Queueing new Ethereum header: {:?}. Queue: {:?}.", id, status); + log::debug!( + target: "bridge", + "Queueing new {} header: {:?}. Queue: {:?}.", + P::SOURCE_NAME, + id, + status, + ); } - /// Receive Substrate best header. - pub fn substrate_best_header_response(&mut self, id: &HeaderId) { + /// Receive best header from the target node. + pub fn target_best_header_response(&mut self, id: &HeaderId) { // all ancestors of this header are now synced => let's remove them from // queues let mut current = *id; @@ -193,15 +231,21 @@ impl QueuedHeaders { HeaderStatus::Unknown => break, HeaderStatus::MaybeOrphan => remove_header(&mut self.maybe_orphan, ¤t), HeaderStatus::Orphan => remove_header(&mut self.orphan, ¤t), - HeaderStatus::MaybeReceipts => remove_header(&mut self.maybe_receipts, ¤t), - HeaderStatus::Receipts => remove_header(&mut self.receipts, ¤t), + HeaderStatus::MaybeExtra => remove_header(&mut self.maybe_extra, ¤t), + HeaderStatus::Extra => remove_header(&mut self.extra, ¤t), HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), HeaderStatus::Synced => break, } .expect("header has a given status; given queue has the header; qed"); - log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", current, HeaderStatus::Synced); + log::debug!( + target: "bridge", + "{} header {:?} is now {:?}", + P::SOURCE_NAME, + current, + HeaderStatus::Synced, + ); *self .known_headers .entry(current.0) @@ -212,7 +256,13 @@ impl QueuedHeaders { } // remember that the header is synced - log::debug!(target: "bridge", "Ethereum header {:?} is now {:?}", id, HeaderStatus::Synced); + log::debug!( + target: "bridge", + "{} header {:?} is now {:?}", + P::SOURCE_NAME, + id, + HeaderStatus::Synced, + ); *self .known_headers .entry(id.0) @@ -221,20 +271,20 @@ impl QueuedHeaders { .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; // now let's move all descendants from maybe_orphan && orphan queues to - // maybe_receipts queue - move_header_descendants( + // maybe_extra queue + move_header_descendants::

( &mut [&mut self.maybe_orphan, &mut self.orphan], - &mut self.maybe_receipts, + &mut self.maybe_extra, &mut self.known_headers, - HeaderStatus::MaybeReceipts, + HeaderStatus::MaybeExtra, id, ); } - /// Receive Substrate response for MaybeOrphan request. - pub fn maybe_orphan_response(&mut self, id: &HeaderId, response: bool) { + /// Receive target node response for MaybeOrphan request. + pub fn maybe_orphan_response(&mut self, id: &HeaderId, response: bool) { if !response { - move_header_descendants( + move_header_descendants::

( &mut [&mut self.maybe_orphan], &mut self.orphan, &mut self.known_headers, @@ -244,25 +294,25 @@ impl QueuedHeaders { return; } - move_header_descendants( + move_header_descendants::

( &mut [&mut self.maybe_orphan, &mut self.orphan], - &mut self.maybe_receipts, + &mut self.maybe_extra, &mut self.known_headers, - HeaderStatus::MaybeReceipts, + HeaderStatus::MaybeExtra, &id, ); } - /// Receive Substrate response for MaybeReceipts request. - pub fn maybe_receipts_response(&mut self, id: &HeaderId, response: bool) { + /// Receive target node response for MaybeExtra request. + pub fn maybe_extra_response(&mut self, id: &HeaderId, response: bool) { let (destination_status, destination_queue) = if response { - (HeaderStatus::Receipts, &mut self.receipts) + (HeaderStatus::Extra, &mut self.extra) } else { (HeaderStatus::Ready, &mut self.ready) }; move_header( - &mut self.maybe_receipts, + &mut self.maybe_extra, destination_queue, &mut self.known_headers, destination_status, @@ -271,20 +321,21 @@ impl QueuedHeaders { ); } - /// Receive transactions receipts from Ethereum node. - pub fn receipts_response(&mut self, id: &HeaderId, receipts: Vec) { + /// Receive extra from source node. + pub fn extra_response(&mut self, id: &HeaderId, extra: P::Extra) { + // move header itself from extra to ready queue move_header( - &mut self.receipts, + &mut self.extra, &mut self.ready, &mut self.known_headers, HeaderStatus::Ready, id, - |header| header.set_receipts(receipts), + |header| header.set_extra(extra), ); } - /// When header is submitted to Substrate node. - pub fn headers_submitted(&mut self, ids: Vec) { + /// When header is submitted to target node. + pub fn headers_submitted(&mut self, ids: Vec>) { for id in ids { move_header( &mut self.ready, @@ -298,18 +349,18 @@ impl QueuedHeaders { } /// Prune and never accep headers before this block. - pub fn prune(&mut self, prune_border: u64) { + pub fn prune(&mut self, prune_border: P::Number) { if prune_border <= self.prune_border { return; } prune_queue(&mut self.maybe_orphan, prune_border); prune_queue(&mut self.orphan, prune_border); - prune_queue(&mut self.maybe_receipts, prune_border); - prune_queue(&mut self.receipts, prune_border); + prune_queue(&mut self.maybe_extra, prune_border); + prune_queue(&mut self.extra, prune_border); prune_queue(&mut self.ready, prune_border); prune_queue(&mut self.submitted, prune_border); - prune_known_headers(&mut self.known_headers, prune_border); + prune_known_headers::

(&mut self.known_headers, prune_border); self.prune_border = prune_border; } @@ -317,22 +368,29 @@ impl QueuedHeaders { pub fn clear(&mut self) { self.maybe_orphan.clear(); self.orphan.clear(); - self.maybe_receipts.clear(); - self.receipts.clear(); + self.maybe_extra.clear(); + self.extra.clear(); self.ready.clear(); self.submitted.clear(); self.known_headers.clear(); - self.prune_border = 0; + self.prune_border = Zero::zero(); } } /// Insert header to the queue. -fn insert_header(queue: &mut HeadersQueue, id: HeaderId, header: QueuedHeader) { +fn insert_header( + queue: &mut HeadersQueue

, + id: HeaderId, + header: QueuedHeader

, +) { queue.entry(id.0).or_default().insert(id.1, header); } /// Remove header from the queue. -fn remove_header(queue: &mut HeadersQueue, id: &HeaderId) -> Option { +fn remove_header( + queue: &mut HeadersQueue

, + id: &HeaderId, +) -> Option> { let mut headers_at = match queue.entry(id.0) { BTreeMapEntry::Occupied(headers_at) => headers_at, BTreeMapEntry::Vacant(_) => return None, @@ -346,39 +404,45 @@ fn remove_header(queue: &mut HeadersQueue, id: &HeaderId) -> Option( + source_queue: &mut HeadersQueue

, + destination_queue: &mut HeadersQueue

, + known_headers: &mut KnownHeaders

, destination_status: HeaderStatus, - id: &HeaderId, - prepare: impl FnOnce(QueuedHeader) -> QueuedHeader, -) { + id: &HeaderId, + prepare: impl FnOnce(QueuedHeader

) -> QueuedHeader

, +) -> Option> { let header = match remove_header(source_queue, id) { Some(header) => prepare(header), - None => return, + None => return None, }; + let parent_id = header.header().parent_id(); known_headers.entry(id.0).or_default().insert(id.1, destination_status); destination_queue.entry(id.0).or_default().insert(id.1, header); log::debug!( target: "bridge", - "Ethereum header {:?} is now {:?}", + "{} header {:?} is now {:?}", + P::SOURCE_NAME, id, destination_status, ); + + Some(parent_id) } /// Move all descendant headers from the source to destination queue. -fn move_header_descendants( - source_queues: &mut [&mut HeadersQueue], - destination_queue: &mut HeadersQueue, - known_headers: &mut KnownHeaders, +fn move_header_descendants( + source_queues: &mut [&mut HeadersQueue

], + destination_queue: &mut HeadersQueue

, + known_headers: &mut KnownHeaders

, destination_status: HeaderStatus, - id: &HeaderId, + id: &HeaderId, ) { - let mut current_number = id.0 + 1; + let mut current_number = id.0 + One::one(); let mut current_parents = HashSet::new(); current_parents.insert(id.1); @@ -398,7 +462,7 @@ fn move_header_descendants( HashMapEntry::Vacant(_) => unreachable!("iterating existing keys; qed"), }; - if current_parents.contains(&entry.get().header().parent_hash) { + if current_parents.contains(&entry.get().header().parent_id().1) { let header_to_move = entry.remove(); let header_to_move_id = header_to_move.id(); known_headers @@ -409,7 +473,8 @@ fn move_header_descendants( log::debug!( target: "bridge", - "Ethereum header {:?} is now {:?}", + "{} header {:?} is now {:?}", + P::SOURCE_NAME, header_to_move_id, destination_status, ); @@ -428,18 +493,21 @@ fn move_header_descendants( .extend(headers_to_move.into_iter().map(|(id, h)| (id.1, h))) } - current_number = current_number + 1; + current_number = current_number + One::one(); std::mem::swap(&mut current_parents, &mut next_parents); } } /// Return oldest header from the queue. -fn oldest_header(queue: &HeadersQueue) -> Option<&QueuedHeader> { +fn oldest_header(queue: &HeadersQueue

) -> Option<&QueuedHeader

> { queue.values().flat_map(|h| h.values()).next() } /// Return oldest headers from the queue until functor will return false. -fn oldest_headers(queue: &HeadersQueue, mut f: impl FnMut(&QueuedHeader) -> bool) -> Option> { +fn oldest_headers( + queue: &HeadersQueue

, + mut f: impl FnMut(&QueuedHeader

) -> bool, +) -> Option>> { let result = queue .values() .flat_map(|h| h.values()) @@ -453,12 +521,12 @@ fn oldest_headers(queue: &HeadersQueue, mut f: impl FnMut(&QueuedHeader) -> bool } /// Forget all headers with number less than given. -fn prune_queue(queue: &mut HeadersQueue, prune_border: u64) { +fn prune_queue(queue: &mut HeadersQueue

, prune_border: P::Number) { *queue = queue.split_off(&prune_border); } /// Forget all known headers with number less than given. -fn prune_known_headers(known_headers: &mut KnownHeaders, prune_border: u64) { +fn prune_known_headers(known_headers: &mut KnownHeaders

, prune_border: P::Number) { let new_known_headers = known_headers.split_off(&prune_border); for (pruned_number, pruned_headers) in &*known_headers { for pruned_hash in pruned_headers.keys() { @@ -471,8 +539,10 @@ fn prune_known_headers(known_headers: &mut KnownHeaders, prune_border: u64) { #[cfg(test)] pub(crate) mod tests { use super::*; + use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, H256}; + use crate::sync_types::{HeaderId, QueuedHeader}; - pub(crate) fn header(number: u64) -> QueuedHeader { + pub(crate) fn header(number: u64) -> QueuedHeader { QueuedHeader::new(Header { number: Some(number.into()), hash: Some(hash(number)), @@ -485,85 +555,88 @@ pub(crate) mod tests { H256::from_low_u64_le(number) } - pub(crate) fn id(number: u64) -> HeaderId { + pub(crate) fn id(number: u64) -> EthereumHeaderId { HeaderId(number, hash(number)) } #[test] fn total_headers_works() { // total headers just sums up number of headers in every queue - let mut queue = QueuedHeaders::default(); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(1), Default::default()); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(2), Default::default()); - queue - .maybe_orphan - .entry(2) - .or_default() - .insert(hash(3), Default::default()); - queue.orphan.entry(3).or_default().insert(hash(4), Default::default()); - queue - .maybe_receipts - .entry(4) - .or_default() - .insert(hash(5), Default::default()); - queue.ready.entry(5).or_default().insert(hash(6), Default::default()); + let mut queue = QueuedHeaders::::new(); + queue.maybe_orphan.entry(1).or_default().insert( + hash(1), + QueuedHeader::::new(Default::default()), + ); + queue.maybe_orphan.entry(1).or_default().insert( + hash(2), + QueuedHeader::::new(Default::default()), + ); + queue.maybe_orphan.entry(2).or_default().insert( + hash(3), + QueuedHeader::::new(Default::default()), + ); + queue.orphan.entry(3).or_default().insert( + hash(4), + QueuedHeader::::new(Default::default()), + ); + queue.maybe_extra.entry(4).or_default().insert( + hash(5), + QueuedHeader::::new(Default::default()), + ); + queue.ready.entry(5).or_default().insert( + hash(6), + QueuedHeader::::new(Default::default()), + ); assert_eq!(queue.total_headers(), 6); } #[test] fn best_queued_number_works() { // initially there are headers in MaybeOrphan queue only - let mut queue = QueuedHeaders::default(); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(1), Default::default()); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(2), Default::default()); - queue - .maybe_orphan - .entry(3) - .or_default() - .insert(hash(3), Default::default()); + let mut queue = QueuedHeaders::::new(); + queue.maybe_orphan.entry(1).or_default().insert( + hash(1), + QueuedHeader::::new(Default::default()), + ); + queue.maybe_orphan.entry(1).or_default().insert( + hash(2), + QueuedHeader::::new(Default::default()), + ); + queue.maybe_orphan.entry(3).or_default().insert( + hash(3), + QueuedHeader::::new(Default::default()), + ); assert_eq!(queue.best_queued_number(), 3); // and then there's better header in Orphan - queue.orphan.entry(10).or_default().insert(hash(10), Default::default()); + queue.orphan.entry(10).or_default().insert( + hash(10), + QueuedHeader::::new(Default::default()), + ); assert_eq!(queue.best_queued_number(), 10); - // and then there's better header in MaybeReceipts - queue - .maybe_receipts - .entry(20) - .or_default() - .insert(hash(20), Default::default()); + // and then there's better header in MaybeExtra + queue.maybe_extra.entry(20).or_default().insert( + hash(20), + QueuedHeader::::new(Default::default()), + ); assert_eq!(queue.best_queued_number(), 20); // and then there's better header in Ready - queue.ready.entry(30).or_default().insert(hash(30), Default::default()); + queue.ready.entry(30).or_default().insert( + hash(30), + QueuedHeader::::new(Default::default()), + ); assert_eq!(queue.best_queued_number(), 30); // and then there's better header in MaybeOrphan again - queue - .maybe_orphan - .entry(40) - .or_default() - .insert(hash(40), Default::default()); + queue.maybe_orphan.entry(40).or_default().insert( + hash(40), + QueuedHeader::::new(Default::default()), + ); assert_eq!(queue.best_queued_number(), 40); } #[test] fn status_works() { // all headers are unknown initially - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); // and status is read from the KnownHeaders queue @@ -577,7 +650,7 @@ pub(crate) mod tests { #[test] fn header_works() { // initially we have oldest header #10 - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); assert_eq!( queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), @@ -599,48 +672,48 @@ pub(crate) mod tests { #[test] fn header_response_works() { - // when parent is Synced, we insert to MaybeReceipts - let mut queue = QueuedHeaders::default(); + // when parent is Synced, we insert to MaybeExtra + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() .insert(hash(100), HeaderStatus::Synced); queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - // when parent is Ready, we insert to MaybeReceipts - let mut queue = QueuedHeaders::default(); + // when parent is Ready, we insert to MaybeExtra + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() .insert(hash(100), HeaderStatus::Ready); queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - // when parent is Receipts, we insert to MaybeReceipts - let mut queue = QueuedHeaders::default(); + // when parent is Receipts, we insert to MaybeExtra + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() - .insert(hash(100), HeaderStatus::Receipts); + .insert(hash(100), HeaderStatus::Extra); queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - // when parent is MaybeReceipts, we insert to MaybeReceipts - let mut queue = QueuedHeaders::default(); + // when parent is MaybeExtra, we insert to MaybeExtra + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() - .insert(hash(100), HeaderStatus::MaybeReceipts); + .insert(hash(100), HeaderStatus::MaybeExtra); queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeReceipts); + assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Orphan, we insert to Orphan - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) @@ -650,7 +723,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); // when parent is MaybeOrphan, we insert to MaybeOrphan - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) @@ -660,7 +733,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); // when parent is unknown, we insert to MaybeOrphan - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); } @@ -671,10 +744,10 @@ pub(crate) mod tests { // its best block to #100. At this time we have: // #100 in MaybeOrphan // #99 in Orphan - // #98 in MaybeReceipts + // #98 in MaybeExtra // #97 in Receipts // #96 in Ready - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) @@ -695,27 +768,27 @@ pub(crate) mod tests { .known_headers .entry(98) .or_default() - .insert(hash(98), HeaderStatus::MaybeReceipts); - queue.maybe_receipts.entry(98).or_default().insert(hash(98), header(98)); + .insert(hash(98), HeaderStatus::MaybeExtra); + queue.maybe_extra.entry(98).or_default().insert(hash(98), header(98)); queue .known_headers .entry(97) .or_default() - .insert(hash(97), HeaderStatus::Receipts); - queue.receipts.entry(97).or_default().insert(hash(97), header(97)); + .insert(hash(97), HeaderStatus::Extra); + queue.extra.entry(97).or_default().insert(hash(97), header(97)); queue .known_headers .entry(96) .or_default() .insert(hash(96), HeaderStatus::Ready); queue.ready.entry(96).or_default().insert(hash(96), header(96)); - queue.substrate_best_header_response(&id(100)); + queue.target_best_header_response(&id(100)); // then the #100 and all ancestors of #100 (#96..#99) are treated as synced assert!(queue.maybe_orphan.is_empty()); assert!(queue.orphan.is_empty()); - assert!(queue.maybe_receipts.is_empty()); - assert!(queue.receipts.is_empty()); + assert!(queue.maybe_extra.is_empty()); + assert!(queue.extra.is_empty()); assert!(queue.ready.is_empty()); assert_eq!(queue.known_headers.len(), 5); assert!(queue @@ -731,7 +804,7 @@ pub(crate) mod tests { // #101 in Orphan // #102 in MaybeOrphan // #103 in Orphan - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(101) @@ -754,15 +827,15 @@ pub(crate) mod tests { .or_default() .insert(hash(103), HeaderStatus::Orphan); queue.orphan.entry(103).or_default().insert(hash(103), header(103)); - queue.substrate_best_header_response(&id(100)); + queue.target_best_header_response(&id(100)); - // all descendants are moved to MaybeReceipts + // all descendants are moved to MaybeExtra assert!(queue.maybe_orphan.is_empty()); assert!(queue.orphan.is_empty()); - assert_eq!(queue.maybe_receipts.len(), 3); - assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeReceipts); - assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeReceipts); - assert_eq!(queue.known_headers[&103][&hash(103)], HeaderStatus::MaybeReceipts); + assert_eq!(queue.maybe_extra.len(), 3); + assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeExtra); + assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeExtra); + assert_eq!(queue.known_headers[&103][&hash(103)], HeaderStatus::MaybeExtra); } #[test] @@ -773,7 +846,7 @@ pub(crate) mod tests { // #102 in MaybeOrphan // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: YES, #99 is known to the Substrate runtime - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) @@ -802,13 +875,13 @@ pub(crate) mod tests { .insert(hash(102), header(102)); queue.maybe_orphan_response(&id(99), true); - // then all headers (#100..#103) are moved to the MaybeReceipts queue + // then all headers (#100..#103) are moved to the MaybeExtra queue assert!(queue.orphan.is_empty()); assert!(queue.maybe_orphan.is_empty()); - assert_eq!(queue.maybe_receipts.len(), 3); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::MaybeReceipts); - assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeReceipts); - assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeReceipts); + assert_eq!(queue.maybe_extra.len(), 3); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::MaybeExtra); + assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeExtra); + assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeExtra); } #[test] @@ -818,7 +891,7 @@ pub(crate) mod tests { // #101 in MaybeOrphan // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: NO, #99 is NOT known to the Substrate runtime - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) @@ -849,61 +922,53 @@ pub(crate) mod tests { } #[test] - fn positive_maybe_receipts_response_works() { - let mut queue = QueuedHeaders::default(); + fn positive_maybe_extra_response_works() { + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() - .insert(hash(100), HeaderStatus::MaybeReceipts); - queue - .maybe_receipts - .entry(100) - .or_default() - .insert(hash(100), header(100)); - queue.maybe_receipts_response(&id(100), true); - assert!(queue.maybe_receipts.is_empty()); - assert_eq!(queue.receipts.len(), 1); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Receipts); + .insert(hash(100), HeaderStatus::MaybeExtra); + queue.maybe_extra.entry(100).or_default().insert(hash(100), header(100)); + queue.maybe_extra_response(&id(100), true); + assert!(queue.maybe_extra.is_empty()); + assert_eq!(queue.extra.len(), 1); + assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Extra); } #[test] - fn negative_maybe_receipts_response_works() { - let mut queue = QueuedHeaders::default(); + fn negative_maybe_extra_response_works() { + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() - .insert(hash(100), HeaderStatus::MaybeReceipts); - queue - .maybe_receipts - .entry(100) - .or_default() - .insert(hash(100), header(100)); - queue.maybe_receipts_response(&id(100), false); - assert!(queue.maybe_receipts.is_empty()); + .insert(hash(100), HeaderStatus::MaybeExtra); + queue.maybe_extra.entry(100).or_default().insert(hash(100), header(100)); + queue.maybe_extra_response(&id(100), false); + assert!(queue.maybe_extra.is_empty()); assert_eq!(queue.ready.len(), 1); assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); } #[test] fn receipts_response_works() { - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) .or_default() - .insert(hash(100), HeaderStatus::Receipts); - queue.receipts.entry(100).or_default().insert(hash(100), header(100)); - queue.receipts_response(&id(100), Vec::new()); - assert!(queue.receipts.is_empty()); + .insert(hash(100), HeaderStatus::Extra); + queue.extra.entry(100).or_default().insert(hash(100), header(100)); + queue.extra_response(&id(100), Vec::new()); + assert!(queue.extra.is_empty()); assert_eq!(queue.ready.len(), 1); assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); } #[test] fn header_submitted_works() { - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(100) @@ -917,7 +982,7 @@ pub(crate) mod tests { #[test] fn prune_works() { - let mut queue = QueuedHeaders::default(); + let mut queue = QueuedHeaders::::new(); queue .known_headers .entry(104) @@ -938,18 +1003,14 @@ pub(crate) mod tests { .known_headers .entry(102) .or_default() - .insert(hash(102), HeaderStatus::MaybeReceipts); - queue - .maybe_receipts - .entry(102) - .or_default() - .insert(hash(102), header(102)); + .insert(hash(102), HeaderStatus::MaybeExtra); + queue.maybe_extra.entry(102).or_default().insert(hash(102), header(102)); queue .known_headers .entry(101) .or_default() - .insert(hash(101), HeaderStatus::Receipts); - queue.receipts.entry(101).or_default().insert(hash(101), header(101)); + .insert(hash(101), HeaderStatus::Extra); + queue.extra.entry(101).or_default().insert(hash(101), header(101)); queue .known_headers .entry(100) @@ -960,8 +1021,8 @@ pub(crate) mod tests { queue.prune(102); assert_eq!(queue.ready.len(), 0); - assert_eq!(queue.receipts.len(), 0); - assert_eq!(queue.maybe_receipts.len(), 1); + assert_eq!(queue.extra.len(), 0); + assert_eq!(queue.maybe_extra.len(), 1); assert_eq!(queue.orphan.len(), 1); assert_eq!(queue.maybe_orphan.len(), 1); assert_eq!(queue.known_headers.len(), 3); @@ -969,8 +1030,8 @@ pub(crate) mod tests { queue.prune(110); assert_eq!(queue.ready.len(), 0); - assert_eq!(queue.receipts.len(), 0); - assert_eq!(queue.maybe_receipts.len(), 0); + assert_eq!(queue.extra.len(), 0); + assert_eq!(queue.maybe_extra.len(), 0); assert_eq!(queue.orphan.len(), 0); assert_eq!(queue.maybe_orphan.len(), 0); assert_eq!(queue.known_headers.len(), 0); diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index fb276b480cff2..8d897d51e42ff 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -17,12 +17,14 @@ #![recursion_limit = "1024"] mod ethereum_client; -mod ethereum_headers; -mod ethereum_sync; mod ethereum_sync_loop; mod ethereum_types; +mod headers; mod substrate_client; mod substrate_types; +mod sync; +mod sync_loop; +mod sync_types; use sp_core::crypto::Pair; use std::io::Write; @@ -30,13 +32,24 @@ use std::io::Write; fn main() { initialize(); - ethereum_sync_loop::run(match ethereum_sync_params() { - Ok(ethereum_sync_params) => ethereum_sync_params, - Err(err) => { - log::error!(target: "bridge", "Error parsing parameters: {}", err); + let yaml = clap::load_yaml!("cli.yml"); + let matches = clap::App::from_yaml(yaml).get_matches(); + match matches.subcommand() { + ("eth-to-sub", Some(eth_to_sub_matches)) => { + ethereum_sync_loop::run(match ethereum_sync_params(ð_to_sub_matches) { + Ok(ethereum_sync_params) => ethereum_sync_params, + Err(err) => { + log::error!(target: "bridge", "Error parsing parameters: {}", err); + return; + } + }); + } + ("", _) => { + log::error!(target: "bridge", "No subcommand specified"); return; } - }); + _ => unreachable!("all possible subcommands are checked above; qed"), + } } fn initialize() { @@ -76,10 +89,7 @@ fn initialize() { builder.init(); } -fn ethereum_sync_params() -> Result { - let yaml = clap::load_yaml!("cli.yml"); - let matches = clap::App::from_yaml(yaml).get_matches(); - +fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result { let mut eth_sync_params = ethereum_sync_loop::EthereumSyncParams::default(); if let Some(eth_host) = matches.value_of("eth-host") { eth_sync_params.eth_host = eth_host.into(); @@ -100,16 +110,16 @@ fn ethereum_sync_params() -> Result eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Signed, + Some("signed") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, Some("unsigned") => { - eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Unsigned; + eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned; // tx pool won't accept too much unsigned transactions - eth_sync_params.max_headers_in_submitted_status = 10; + eth_sync_params.sync_params.max_headers_in_submitted_status = 10; } - Some("backup") => eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Backup, + Some("backup") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Backup, Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), - None => eth_sync_params.sub_tx_mode = ethereum_sync_loop::SubstrateTransactionMode::Signed, + None => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, } Ok(eth_sync_params) diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 51e2b1886e55e..40a9047c5eef4 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_sync_loop::MaybeConnectionError; -use crate::ethereum_types::{Bytes, HeaderId as EthereumHeaderId, QueuedHeader as QueuedEthereumHeader, H256}; +use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256}; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts, TransactionHash}; +use crate::sync_types::{HeaderId, MaybeConnectionError, SourceHeader}; use codec::{Decode, Encode}; use jsonrpsee::common::Params; use jsonrpsee::raw::{RawClient, RawClientError}; @@ -29,8 +29,6 @@ use sp_runtime::traits::IdentifyAccount; pub struct Client { /// Substrate RPC client. rpc_client: RawClient, - /// Transactions signer. - signer: sp_core::sr25519::Pair, /// Genesis block hash. genesis_hash: Option, } @@ -58,11 +56,10 @@ impl MaybeConnectionError for Error { } /// Returns client that is able to call RPCs on Substrate node. -pub fn client(uri: &str, signer: sp_core::sr25519::Pair) -> Client { +pub fn client(uri: &str) -> Client { let transport = HttpTransportClient::new(uri); Client { rpc_client: RawClient::new(transport), - signer, genesis_hash: None, } } @@ -78,7 +75,7 @@ pub async fn best_ethereum_block(client: Client) -> (Client, Result (Client, Result<(EthereumHeaderId, bool), Error>) { - let id = header.id(); + let id = header.header().id(); let header = into_substrate_ethereum_header(header.header()); let encoded_header = header.encode(); let (client, receipts_required) = call_rpc( @@ -131,11 +128,12 @@ pub async fn ethereum_header_known( /// Submits Ethereum header to Substrate runtime. pub async fn submit_ethereum_headers( client: Client, + signer: sp_core::sr25519::Pair, headers: Vec, sign_transactions: bool, ) -> (Client, Result<(Vec, Vec), Error>) { match sign_transactions { - true => submit_signed_ethereum_headers(client, headers).await, + true => submit_signed_ethereum_headers(client, signer, headers).await, false => submit_unsigned_ethereum_headers(client, headers).await, } } @@ -143,6 +141,7 @@ pub async fn submit_ethereum_headers( /// Submits signed Ethereum header to Substrate runtime. pub async fn submit_signed_ethereum_headers( client: Client, + signer: sp_core::sr25519::Pair, headers: Vec, ) -> (Client, Result<(Vec, Vec), Error>) { let ids = headers.iter().map(|header| header.id()).collect(); @@ -158,15 +157,14 @@ pub async fn submit_signed_ethereum_headers( (client, genesis_hash) } }; - let account_id = client.signer.public().as_array_ref().clone().into(); + let account_id = signer.public().as_array_ref().clone().into(); let (client, nonce) = next_account_index(client, account_id).await; let nonce = match nonce { Ok(nonce) => nonce, Err(err) => return (client, Err(err)), }; - let transaction = create_signed_submit_transaction(headers, &client.signer, nonce, genesis_hash); - + let transaction = create_signed_submit_transaction(headers, &signer, nonce, genesis_hash); let encoded_transaction = transaction.encode(); let (client, transaction_hash) = call_rpc( client, diff --git a/relays/ethereum/src/ethereum_sync.rs b/relays/ethereum/src/sync.rs similarity index 56% rename from relays/ethereum/src/ethereum_sync.rs rename to relays/ethereum/src/sync.rs index b174d3819e470..768a7a7932bcd 100644 --- a/relays/ethereum/src/ethereum_sync.rs +++ b/relays/ethereum/src/sync.rs @@ -14,69 +14,97 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_headers::QueuedHeaders; -use crate::ethereum_sync_loop::{EthereumSyncParams, SubstrateTransactionMode}; -use crate::ethereum_types::{HeaderId, HeaderStatus, QueuedHeader}; -use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; -use codec::Encode; +use crate::headers::QueuedHeaders; +use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; +use num_traits::{One, Saturating}; -/// Ethereum headers synchronization context. +/// Common sync params. #[derive(Debug)] -pub struct HeadersSync { +pub struct HeadersSyncParams { + /// Maximal number of ethereum headers to pre-download. + pub max_future_headers_to_download: usize, + /// Maximal number of active (we believe) submit header transactions. + pub max_headers_in_submitted_status: usize, + /// Maximal number of headers in single submit request. + pub max_headers_in_single_submit: usize, + /// Maximal total headers size in single submit request. + pub max_headers_size_in_single_submit: usize, + /// We only may store and accept (from Ethereum node) headers that have + /// number >= than best_substrate_header.number - prune_depth. + pub prune_depth: u32, + /// Target transactions mode. + pub target_tx_mode: TargetTransactionMode, +} + +/// Target transaction mode. +#[derive(Debug, PartialEq)] +pub enum TargetTransactionMode { + /// Submit new headers using signed transactions. + Signed, + /// Submit new headers using unsigned transactions. + Unsigned, + /// Submit new headers using signed transactions, but only when we + /// believe that sync has stalled. + Backup, +} + +/// Headers synchronization context. +#[derive(Debug)] +pub struct HeadersSync { /// Synchronization parameters. - params: EthereumSyncParams, - /// Best header number known to Ethereum node. - target_header_number: Option, - /// Best header known to Substrate node. - best_header: Option, + params: HeadersSyncParams, + /// Best header number known to source node. + source_best_number: Option, + /// Best header known to target node. + target_best_header: Option>, /// Headers queue. - headers: QueuedHeaders, + headers: QueuedHeaders

, } -impl HeadersSync { - /// Creates new Ethereum headers synchronizer. - pub fn new(params: EthereumSyncParams) -> Self { +impl HeadersSync

{ + /// Creates new headers synchronizer. + pub fn new(params: HeadersSyncParams) -> Self { HeadersSync { + headers: QueuedHeaders::new(), params, - target_header_number: None, - best_header: None, - headers: Default::default(), + source_best_number: None, + target_best_header: None, } } /// Returns true if we have synced almost all known headers. pub fn is_almost_synced(&self) -> bool { - match self.target_header_number { - Some(target_header_number) => self - .best_header - .map(|best| target_header_number.saturating_sub(best.0) < 4) + match self.source_best_number { + Some(source_best_number) => self + .target_best_header + .map(|best| source_best_number.saturating_sub(best.0) < 4.into()) .unwrap_or(false), None => true, } } /// Returns synchronization status. - pub fn status(&self) -> (&Option, &Option) { - (&self.best_header, &self.target_header_number) + pub fn status(&self) -> (&Option>, &Option) { + (&self.target_best_header, &self.source_best_number) } /// Returns reference to the headers queue. - pub fn headers(&self) -> &QueuedHeaders { + pub fn headers(&self) -> &QueuedHeaders

{ &self.headers } /// Returns mutable reference to the headers queue. - pub fn headers_mut(&mut self) -> &mut QueuedHeaders { + pub fn headers_mut(&mut self) -> &mut QueuedHeaders

{ &mut self.headers } - /// Select header that needs to be downloaded from the Ethereum node. - pub fn select_new_header_to_download(&self) -> Option { - // if we haven't received best header from Ethereum node yet, there's nothing we can download - let target_header_number = self.target_header_number.clone()?; + /// Select header that needs to be downloaded from the source node. + pub fn select_new_header_to_download(&self) -> Option { + // if we haven't received best header from source node yet, there's nothing we can download + let source_best_number = self.source_best_number.clone()?; - // if we haven't received known best header from Substrate node yet, there's nothing we can download - let best_header = self.best_header.as_ref()?; + // if we haven't received known best header from target node yet, there's nothing we can download + let target_best_header = self.target_best_header.as_ref()?; // if there's too many headers in the queue, stop downloading let in_memory_headers = self.headers.total_headers(); @@ -85,19 +113,19 @@ impl HeadersSync { } // we assume that there were no reorgs if we have already downloaded best header - let best_downloaded_number = std::cmp::max(self.headers.best_queued_number(), best_header.0); - if best_downloaded_number == target_header_number { + let best_downloaded_number = std::cmp::max(self.headers.best_queued_number(), target_best_header.0); + if best_downloaded_number == source_best_number { return None; } // download new header - Some(best_downloaded_number + 1) + Some(best_downloaded_number + One::one()) } - /// Select headers that need to be submitted to the Substrate node. - pub fn select_headers_to_submit(&self, stalled: bool) -> Option> { + /// Select headers that need to be submitted to the target node. + pub fn select_headers_to_submit(&self, stalled: bool) -> Option>> { // if we operate in backup mode, we only submit headers when sync has stalled - if self.params.sub_tx_mode == SubstrateTransactionMode::Backup && !stalled { + if self.params.target_tx_mode == TargetTransactionMode::Backup && !stalled { return None; } @@ -117,10 +145,7 @@ impl HeadersSync { return false; } - let encoded_size = into_substrate_ethereum_header(header.header()).encode().len() - + into_substrate_ethereum_receipts(header.receipts()) - .map(|receipts| receipts.encode().len()) - .unwrap_or(0); + let encoded_size = P::estimate_size(header); if total_headers != 0 && total_size + encoded_size > self.params.max_headers_size_in_single_submit { return false; } @@ -132,48 +157,72 @@ impl HeadersSync { }) } - /// Receive new target header number from the Ethereum node. - pub fn ethereum_best_header_number_response(&mut self, best_header_number: u64) { - log::debug!(target: "bridge", "Received best header number from Ethereum: {}", best_header_number); - self.target_header_number = Some(best_header_number); + /// Receive new target header number from the source node. + pub fn source_best_header_number_response(&mut self, best_header_number: P::Number) { + log::debug!( + target: "bridge", + "Received best header number from {} node: {}", + P::SOURCE_NAME, + best_header_number, + ); + self.source_best_number = Some(best_header_number); } - /// Receive new best header from the Substrate node. + /// Receive new best header from the target node. /// Returns true if it is different from the previous block known to us. - pub fn substrate_best_header_response(&mut self, best_header: HeaderId) -> bool { - log::debug!(target: "bridge", "Received best known header from Substrate: {:?}", best_header); + pub fn target_best_header_response(&mut self, best_header: HeaderId) -> bool { + log::debug!( + target: "bridge", + "Received best known header from {}: {:?}", + P::TARGET_NAME, + best_header, + ); // early return if it is still the same - if self.best_header == Some(best_header) { + if self.target_best_header == Some(best_header) { return false; } // remember that this header is now known to the Substrate runtime - self.headers.substrate_best_header_response(&best_header); + self.headers.target_best_header_response(&best_header); // prune ancient headers self.headers - .prune(best_header.0.saturating_sub(self.params.prune_depth)); + .prune(best_header.0.saturating_sub(self.params.prune_depth.into())); // finally remember the best header itself - self.best_header = Some(best_header); + self.target_best_header = Some(best_header); true } /// Restart synchronization. pub fn restart(&mut self) { - self.target_header_number = None; - self.best_header = None; + self.source_best_number = None; + self.target_best_header = None; self.headers.clear(); } } +impl Default for HeadersSyncParams { + fn default() -> Self { + HeadersSyncParams { + max_future_headers_to_download: 128, + max_headers_in_submitted_status: 128, + max_headers_in_single_submit: 32, + max_headers_size_in_single_submit: 131_072, + prune_depth: 4096, + target_tx_mode: TargetTransactionMode::Signed, + } + } +} + #[cfg(test)] mod tests { use super::*; - use crate::ethereum_headers::tests::{header, id}; - use crate::ethereum_types::{HeaderStatus, H256}; + use crate::ethereum_types::{EthereumHeadersSyncPipeline, H256}; + use crate::headers::tests::{header, id}; + use crate::sync_types::HeaderStatus; fn side_hash(number: u64) -> H256 { H256::from_low_u64_le(1000 + number) @@ -181,26 +230,26 @@ mod tests { #[test] fn select_new_header_to_download_works() { - let mut eth_sync = HeadersSync::new(Default::default()); + let mut eth_sync = HeadersSync::::new(Default::default()); // both best && target headers are unknown assert_eq!(eth_sync.select_new_header_to_download(), None); // best header is known, target header is unknown - eth_sync.best_header = Some(HeaderId(0, Default::default())); + eth_sync.target_best_header = Some(HeaderId(0, Default::default())); assert_eq!(eth_sync.select_new_header_to_download(), None); // target header is known, best header is unknown - eth_sync.best_header = None; - eth_sync.target_header_number = Some(100); + eth_sync.target_best_header = None; + eth_sync.source_best_number = Some(100); assert_eq!(eth_sync.select_new_header_to_download(), None); // when our best block has the same number as the target - eth_sync.best_header = Some(HeaderId(100, Default::default())); + eth_sync.target_best_header = Some(HeaderId(100, Default::default())); assert_eq!(eth_sync.select_new_header_to_download(), None); // when we actually need a new header - eth_sync.target_header_number = Some(101); + eth_sync.source_best_number = Some(101); assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); // when there are too many headers scheduled for submitting @@ -216,18 +265,18 @@ mod tests { eth_sync.params.max_headers_in_submitted_status = 1; // ethereum reports best header #102 - eth_sync.ethereum_best_header_number_response(102); + eth_sync.source_best_header_number_response(102); // substrate reports that it is at block #100 - eth_sync.substrate_best_header_response(id(100)); + eth_sync.target_best_header_response(id(100)); // block #101 is downloaded first assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); eth_sync.headers.header_response(header(101).header().clone()); // now header #101 is ready to be submitted - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(101))); - eth_sync.headers.maybe_receipts_response(&id(101), false); + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(101))); + eth_sync.headers.maybe_extra_response(&id(101), false); assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(101))); assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); @@ -240,20 +289,20 @@ mod tests { // we have nothing to submit because previous header hasn't been confirmed yet // (and we allow max 1 submit transaction in the wild) - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(102))); - eth_sync.headers.maybe_receipts_response(&id(102), false); + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(102))); + eth_sync.headers.maybe_extra_response(&id(102), false); assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(102))); assert_eq!(eth_sync.select_headers_to_submit(false), None); // substrate reports that it has imported block #101 - eth_sync.substrate_best_header_response(id(101)); + eth_sync.target_best_header_response(id(101)); // and we are ready to submit #102 assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(102)])); eth_sync.headers.headers_submitted(vec![id(102)]); // substrate reports that it has imported block #102 - eth_sync.substrate_best_header_response(id(102)); + eth_sync.target_best_header_response(id(102)); // and we have nothing to download assert_eq!(eth_sync.select_new_header_to_download(), None); @@ -264,10 +313,10 @@ mod tests { let mut eth_sync = HeadersSync::new(Default::default()); // ethereum reports best header #102 - eth_sync.ethereum_best_header_number_response(102); + eth_sync.source_best_header_number_response(102); // substrate reports that it is at block #100, but it isn't part of best chain - eth_sync.substrate_best_header_response(HeaderId(100, side_hash(100))); + eth_sync.target_best_header_response(HeaderId(100, side_hash(100))); // block #101 is downloaded first assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); @@ -296,40 +345,40 @@ mod tests { eth_sync.headers.maybe_orphan_response(&id(99), true); // and we are ready to submit #100 - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(100))); - eth_sync.headers.maybe_receipts_response(&id(100), false); + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(100))); + eth_sync.headers.maybe_extra_response(&id(100), false); assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(100)])); eth_sync.headers.headers_submitted(vec![id(100)]); // and we are ready to submit #101 - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeReceipts), Some(&header(101))); - eth_sync.headers.maybe_receipts_response(&id(101), false); + assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(101))); + eth_sync.headers.maybe_extra_response(&id(101), false); assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); eth_sync.headers.headers_submitted(vec![id(101)]); } #[test] - fn pruning_happens_on_substrate_best_header_response() { - let mut eth_sync = HeadersSync::new(Default::default()); + fn pruning_happens_on_target_best_header_response() { + let mut eth_sync = HeadersSync::::new(Default::default()); eth_sync.params.prune_depth = 50; - eth_sync.substrate_best_header_response(id(100)); + eth_sync.target_best_header_response(id(100)); assert_eq!(eth_sync.headers.prune_border(), 50); } #[test] fn only_submitting_headers_in_backup_mode_when_stalled() { let mut eth_sync = HeadersSync::new(Default::default()); - eth_sync.params.sub_tx_mode = SubstrateTransactionMode::Backup; + eth_sync.params.target_tx_mode = TargetTransactionMode::Backup; // ethereum reports best header #102 - eth_sync.ethereum_best_header_number_response(102); + eth_sync.source_best_header_number_response(102); // substrate reports that it is at block #100 - eth_sync.substrate_best_header_response(id(100)); + eth_sync.target_best_header_response(id(100)); // block #101 is downloaded first eth_sync.headers.header_response(header(101).header().clone()); - eth_sync.headers.maybe_receipts_response(&id(101), false); + eth_sync.headers.maybe_extra_response(&id(101), false); // ensure that headers are not submitted when sync is not stalled assert_eq!(eth_sync.select_headers_to_submit(false), None); diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs new file mode 100644 index 0000000000000..803cfaf0c2350 --- /dev/null +++ b/relays/ethereum/src/sync_loop.rs @@ -0,0 +1,464 @@ +// Copyright 2019-2020 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 . + +use crate::sync::HeadersSyncParams; +use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader}; +use futures::{future::FutureExt, stream::StreamExt}; +use num_traits::Saturating; +use std::future::Future; + +/// When we submit headers to target node, but see no updates of best +/// source block known to target node during STALL_SYNC_TIMEOUT_MS milliseconds, +/// we consider that our headers are rejected because there has been reorg in target chain. +/// This reorg could invalidate our knowledge about sync process (i.e. we have asked if +/// HeaderA is known to target, but then reorg happened and the answer is different +/// now) => we need to reset sync. +/// The other option is to receive **EVERY** best target header and check if it is +/// direct child of previous best header. But: (1) subscription doesn't guarantee that +/// the subscriber will receive every best header (2) reorg won't always lead to sync +/// stall and restart is a heavy operation (we forget all in-memory headers). +const STALL_SYNC_TIMEOUT_MS: u64 = 30_000; +/// Delay (in milliseconds) after we have seen update of best source header at target node, +/// for us to treat sync stalled. ONLY when relay operates in backup mode. +const BACKUP_STALL_SYNC_TIMEOUT_MS: u64 = 5 * 60_000; +/// Delay (in milliseconds) after connection-related error happened before we'll try +/// reconnection again. +const CONNECTION_ERROR_DELAY_MS: u64 = 10_000; + +/// Source client trait. +pub trait SourceClient: Sized { + /// Type of error this clients returns. + type Error: std::fmt::Debug + MaybeConnectionError; + /// Future that returns best block number. + type BestBlockNumberFuture: Future)>; + /// Future that returns header by hash. + type HeaderByHashFuture: Future)>; + /// Future that returns header by number. + type HeaderByNumberFuture: Future)>; + /// Future that returns extra data associated with header. + type HeaderExtraFuture: Future, P::Extra), Self::Error>)>; + + /// Get best block number. + fn best_block_number(self) -> Self::BestBlockNumberFuture; + /// Get header by hash. + fn header_by_hash(self, hash: P::Hash) -> Self::HeaderByHashFuture; + /// Get canonical header by number. + fn header_by_number(self, number: P::Number) -> Self::HeaderByNumberFuture; + /// Get extra data by header hash. + fn header_extra(self, id: HeaderId, header: &P::Header) -> Self::HeaderExtraFuture; +} + +/// Target client trait. +pub trait TargetClient: Sized { + /// Type of error this clients returns. + type Error: std::fmt::Debug + MaybeConnectionError; + /// Future that returns best header id. + type BestHeaderIdFuture: Future, Self::Error>)>; + /// Future that returns known header check result. + type IsKnownHeaderFuture: Future, bool), Self::Error>)>; + /// Future that returns extra check result. + type RequiresExtraFuture: Future, bool), Self::Error>)>; + /// Future that returns header submission result. + type SubmitHeadersFuture: Future>, Self::Error>)>; + + /// Returns ID of best header known to the target node. + fn best_header_id(self) -> Self::BestHeaderIdFuture; + /// Returns true if header is known to the target node. + fn is_known_header(self, id: HeaderId) -> Self::IsKnownHeaderFuture; + /// Returns true if header requires extra data to be submitted. + fn requires_extra(self, header: &QueuedHeader

) -> Self::RequiresExtraFuture; + /// Submit headers. + fn submit_headers(self, headers: Vec>) -> Self::SubmitHeadersFuture; +} + +/// Run headers synchronization. +pub fn run( + source_client: impl SourceClient

, + source_tick_ms: u64, + target_client: impl TargetClient

, + target_tick_ms: u64, + sync_params: HeadersSyncParams, +) { + let mut local_pool = futures::executor::LocalPool::new(); + let mut progress_context = (std::time::Instant::now(), None, None); + + local_pool.run_until(async move { + let mut sync = crate::sync::HeadersSync::

::new(sync_params); + let mut stall_countdown = None; + let mut last_update_time = std::time::Instant::now(); + + let mut source_maybe_client = None; + let mut source_best_block_number_required = false; + let source_best_block_number_future = source_client.best_block_number().fuse(); + let source_new_header_future = futures::future::Fuse::terminated(); + let source_orphan_header_future = futures::future::Fuse::terminated(); + let source_extra_future = futures::future::Fuse::terminated(); + let source_go_offline_future = futures::future::Fuse::terminated(); + let source_tick_stream = interval(source_tick_ms).fuse(); + + let mut target_maybe_client = None; + let mut target_best_block_required = false; + let target_best_block_future = target_client.best_header_id().fuse(); + let target_extra_check_future = futures::future::Fuse::terminated(); + let target_existence_status_future = futures::future::Fuse::terminated(); + let target_submit_header_future = futures::future::Fuse::terminated(); + let target_go_offline_future = futures::future::Fuse::terminated(); + let target_tick_stream = interval(target_tick_ms).fuse(); + + futures::pin_mut!( + source_best_block_number_future, + source_new_header_future, + source_orphan_header_future, + source_extra_future, + source_go_offline_future, + source_tick_stream, + target_best_block_future, + target_extra_check_future, + target_existence_status_future, + target_submit_header_future, + target_go_offline_future, + target_tick_stream + ); + + loop { + futures::select! { + (source_client, source_best_block_number) = source_best_block_number_future => { + source_best_block_number_required = false; + + process_future_result( + &mut source_maybe_client, + source_client, + source_best_block_number, + |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), + &mut source_go_offline_future, + |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + || format!("Error retrieving best header number from {}", P::SOURCE_NAME), + ); + }, + (source_client, source_new_header) = source_new_header_future => { + process_future_result( + &mut source_maybe_client, + source_client, + source_new_header, + |source_new_header| sync.headers_mut().header_response(source_new_header), + &mut source_go_offline_future, + |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + || format!("Error retrieving header from {} node", P::SOURCE_NAME), + ); + }, + (source_client, source_orphan_header) = source_orphan_header_future => { + process_future_result( + &mut source_maybe_client, + source_client, + source_orphan_header, + |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), + &mut source_go_offline_future, + |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), + ); + }, + (source_client, source_extra) = source_extra_future => { + process_future_result( + &mut source_maybe_client, + source_client, + source_extra, + |(header, extra)| sync.headers_mut().extra_response(&header, extra), + &mut source_go_offline_future, + |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), + ); + }, + source_client = source_go_offline_future => { + source_maybe_client = Some(source_client); + }, + _ = source_tick_stream.next() => { + if sync.is_almost_synced() { + source_best_block_number_required = true; + } + }, + (target_client, target_best_block) = target_best_block_future => { + target_best_block_required = false; + + process_future_result( + &mut target_maybe_client, + target_client, + target_best_block, + |target_best_block| { + let head_updated = sync.target_best_header_response(target_best_block); + if head_updated { + last_update_time = std::time::Instant::now(); + } + match head_updated { + // IF head is updated AND there are still our transactions: + // => restart stall countdown timer + true if sync.headers().headers_in_status(HeaderStatus::Submitted) != 0 => + stall_countdown = Some(std::time::Instant::now()), + // IF head is updated AND there are no our transactions: + // => stop stall countdown timer + true => stall_countdown = None, + // IF head is not updated AND stall countdown is not yet completed + // => do nothing + false if stall_countdown + .map(|stall_countdown| std::time::Instant::now() - stall_countdown < + std::time::Duration::from_millis(STALL_SYNC_TIMEOUT_MS)) + .unwrap_or(true) + => (), + // IF head is not updated AND stall countdown has completed + // => restart sync + false => { + log::info!( + target: "bridge", + "Possible {} fork detected. Restarting {} headers synchronization.", + P::TARGET_NAME, + P::SOURCE_NAME, + ); + stall_countdown = None; + sync.restart(); + }, + } + }, + &mut target_go_offline_future, + |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + || format!("Error retrieving best known header from {} node", P::TARGET_NAME), + ); + }, + (target_client, target_existence_status) = target_existence_status_future => { + process_future_result( + &mut target_maybe_client, + target_client, + target_existence_status, + |(target_header, target_existence_status)| sync + .headers_mut() + .maybe_orphan_response(&target_header, target_existence_status), + &mut target_go_offline_future, + |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + || format!("Error retrieving existence status from {} node", P::TARGET_NAME), + ); + }, + (target_client, target_submit_header_result) = target_submit_header_future => { + process_future_result( + &mut target_maybe_client, + target_client, + target_submit_header_result, + |submitted_headers| sync.headers_mut().headers_submitted(submitted_headers), + &mut target_go_offline_future, + |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + || format!("Error submitting headers to {} node", P::TARGET_NAME), + ); + }, + (target_client, target_extra_check_result) = target_extra_check_future => { + process_future_result( + &mut target_maybe_client, + target_client, + target_extra_check_result, + |(header, extra_check_result)| sync + .headers_mut() + .maybe_extra_response(&header, extra_check_result), + &mut target_go_offline_future, + |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), + ); + }, + target_client = target_go_offline_future => { + target_maybe_client = Some(target_client); + }, + _ = target_tick_stream.next() => { + target_best_block_required = true; + }, + } + + // print progress + progress_context = print_sync_progress(progress_context, &sync); + + // if target client is available: wait, or call required target methods + if let Some(target_client) = target_maybe_client.take() { + // the priority is to: + // 1) get best block - it stops us from downloading/submitting new blocks + we call it rarely; + // 2) check if we need extra data from source - it stops us from downloading/submitting new blocks; + // 3) check existence - it stops us from submitting new blocks; + // 4) submit header + + if target_best_block_required { + log::debug!(target: "bridge", "Asking {} about best block", P::TARGET_NAME); + target_best_block_future.set(target_client.best_header_id().fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeExtra) { + log::debug!( + target: "bridge", + "Checking if header submission requires extra: {:?}", + header.id(), + ); + + target_extra_check_future.set(target_client.requires_extra(header).fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeOrphan) { + // for MaybeOrphan we actually ask for parent' header existence + let parent_id = header.parent_id(); + + log::debug!( + target: "bridge", + "Asking {} node for existence of: {:?}", + P::TARGET_NAME, + parent_id, + ); + + target_existence_status_future.set(target_client.is_known_header(parent_id).fuse()); + } else if let Some(headers) = sync.select_headers_to_submit( + last_update_time.elapsed() > std::time::Duration::from_millis(BACKUP_STALL_SYNC_TIMEOUT_MS), + ) { + let ids = match headers.len() { + 1 => format!("{:?}", headers[0].id()), + 2 => format!("[{:?}, {:?}]", headers[0].id(), headers[1].id()), + len => format!("[{:?} ... {:?}]", headers[0].id(), headers[len - 1].id()), + }; + log::debug!( + target: "bridge", + "Submitting {} header(s) to {} node: {:?}", + headers.len(), + P::TARGET_NAME, + ids, + ); + + let headers = headers.into_iter().cloned().collect(); + target_submit_header_future.set(target_client.submit_headers(headers).fuse()); + + // remember that we have submitted some headers + if stall_countdown.is_none() { + stall_countdown = Some(std::time::Instant::now()); + } + } else { + target_maybe_client = Some(target_client); + } + } + + // if source client is available: wait, or call required source methods + if let Some(source_client) = source_maybe_client.take() { + // the priority is to: + // 1) get best block - it stops us from downloading new blocks + we call it rarely; + // 2) download extra data - it stops us from submitting new blocks; + // 3) download missing headers - it stops us from downloading/submitting new blocks; + // 4) downloading new headers + + if source_best_block_number_required { + log::debug!(target: "bridge", "Asking {} node about best block number", P::SOURCE_NAME); + source_best_block_number_future.set(source_client.best_block_number().fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::Extra) { + let id = header.id(); + log::debug!( + target: "bridge", + "Retrieving extra data for header: {:?}", + id, + ); + source_extra_future.set(source_client.header_extra(id, header.header()).fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::Orphan) { + // for Orphan we actually ask for parent' header + let parent_id = header.parent_id(); + + log::debug!( + target: "bridge", + "Going to download orphan header from {} node: {:?}", + P::SOURCE_NAME, + parent_id, + ); + + source_orphan_header_future.set(source_client.header_by_hash(parent_id.1).fuse()); + } else if let Some(id) = sync.select_new_header_to_download() { + log::debug!( + target: "bridge", + "Going to download new header from {} node: {:?}", + P::SOURCE_NAME, + id, + ); + + source_new_header_future.set(source_client.header_by_number(id).fuse()); + } else { + source_maybe_client = Some(source_client); + } + } + } + }); +} + +/// Future that resolves into given value after given timeout. +async fn delay(timeout_ms: u64, retval: T) -> T { + async_std::task::sleep(std::time::Duration::from_millis(timeout_ms)).await; + retval +} + +/// Stream that emits item every `timeout_ms` milliseconds. +fn interval(timeout_ms: u64) -> impl futures::Stream { + futures::stream::unfold((), move |_| async move { + delay(timeout_ms, ()).await; + Some(((), ())) + }) +} + +/// Process result of the future that may have been caused by connection failure. +fn process_future_result( + maybe_client: &mut Option, + client: TClient, + result: Result, + on_success: impl FnOnce(TResult), + go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, + go_offline: impl FnOnce(TClient) -> TGoOfflineFuture, + error_pattern: impl FnOnce() -> String, +) where + TError: std::fmt::Debug + MaybeConnectionError, + TGoOfflineFuture: FutureExt, +{ + match result { + Ok(result) => { + *maybe_client = Some(client); + on_success(result); + } + Err(error) => { + if error.is_connection_error() { + go_offline_future.set(go_offline(client).fuse()); + } else { + *maybe_client = Some(client); + } + + log::error!(target: "bridge", "{}: {:?}", error_pattern(), error); + } + } +} + +/// Print synchronization progress. +fn print_sync_progress( + progress_context: (std::time::Instant, Option, Option), + eth_sync: &crate::sync::HeadersSync

, +) -> (std::time::Instant, Option, Option) { + let (prev_time, prev_best_header, prev_target_header) = progress_context; + let now_time = std::time::Instant::now(); + let (now_best_header, now_target_header) = eth_sync.status(); + + let need_update = now_time - prev_time > std::time::Duration::from_secs(10) + || match (prev_best_header, now_best_header) { + (Some(prev_best_header), Some(now_best_header)) => { + now_best_header.0.saturating_sub(prev_best_header) > 10.into() + } + _ => false, + }; + if !need_update { + return (prev_time, prev_best_header, prev_target_header); + } + + log::info!( + target: "bridge", + "Synced {:?} of {:?} headers", + now_best_header.map(|id| id.0), + now_target_header, + ); + (now_time, now_best_header.clone().map(|id| id.0), *now_target_header) +} diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs new file mode 100644 index 0000000000000..9b9712c739e13 --- /dev/null +++ b/relays/ethereum/src/sync_types.rs @@ -0,0 +1,130 @@ +// Copyright 2019-2020 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 . + +/// Ethereum header Id. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct HeaderId(pub Number, pub Hash); + +/// Ethereum header synchronization status. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum HeaderStatus { + /// Header is unknown. + Unknown, + /// Header is in MaybeOrphan queue. + MaybeOrphan, + /// Header is in Orphan queue. + Orphan, + /// Header is in MaybeExtra queue. + MaybeExtra, + /// Header is in Extra queue. + Extra, + /// Header is in Ready queue. + Ready, + /// Header has been recently submitted to the target node. + Submitted, + /// Header is known to the target node. + Synced, +} + +/// Error type that can signal connection errors. +pub trait MaybeConnectionError { + /// Returns true if error (maybe) represents connection error. + fn is_connection_error(&self) -> bool; +} + +/// Headers synchronization pipeline. +pub trait HeadersSyncPipeline: Clone + Copy { + /// Name of the headers source. + const SOURCE_NAME: &'static str; + /// Name of the headers target. + const TARGET_NAME: &'static str; + + /// Headers we're syncing are identified by this hash. + type Hash: Eq + Clone + Copy + std::fmt::Debug + std::fmt::Display + std::hash::Hash; + /// Headers we're syncing are identified by this number. + type Number: From + + Ord + + Clone + + Copy + + std::fmt::Debug + + std::fmt::Display + + std::ops::Add + + std::ops::Sub + + num_traits::Saturating + + num_traits::Zero + + num_traits::One; + /// Type of header that we're syncing. + type Header: Clone + std::fmt::Debug + SourceHeader; + /// Type of extra data for the header that we're receiving from the source node. + type Extra: Clone + std::fmt::Debug; + + /// Function used to convert from queued header to target header. + fn estimate_size(source: &QueuedHeader) -> usize; +} + +/// Header that we're receiving from source node. +pub trait SourceHeader { + /// Returns ID of header. + fn id(&self) -> HeaderId; + /// Returns ID of parent header. + fn parent_id(&self) -> HeaderId; +} + +/// Header how it's stored in the synchronization queue. +#[derive(Clone, Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] +pub struct QueuedHeader { + header: P::Header, + extra: Option, +} + +impl QueuedHeader

{ + /// Creates new queued header. + pub fn new(header: P::Header) -> Self { + QueuedHeader { header, extra: None } + } + + /// Returns ID of header. + pub fn id(&self) -> HeaderId { + self.header.id() + } + + /// Returns ID of parent header. + pub fn parent_id(&self) -> HeaderId { + self.header.parent_id() + } + + /// Returns reference to header. + pub fn header(&self) -> &P::Header { + &self.header + } + + /// Returns reference to associated extra data. + pub fn extra(&self) -> &Option { + &self.extra + } + + /// Extract header and extra from self. + pub fn extract(self) -> (P::Header, Option) { + (self.header, self.extra) + } + + /// Set associated extra data. + pub fn set_extra(mut self, extra: P::Extra) -> Self { + self.extra = Some(extra); + self + } +} From e08aba213973a6869dad9389827e675f17c19b6d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2020 01:58:24 +0000 Subject: [PATCH 0033/1210] Bump parking_lot from 0.10.0 to 0.10.2 (#63) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 93a8d1b0a3eed..4d659365058b0 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -16,7 +16,7 @@ jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-featu linked-hash-map = "0.5.2" log = "0.4.8" num-traits = "0.2" -parking_lot = "0.10.0" +parking_lot = "0.10.2" rustc-hex = "2.0.1" serde = { version = "1.0.106", features = ["derive"] } serde_json = "1.0.51" From 269b3fbd52cce0042809f7314497b82ac0bdb0b3 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2020 02:23:48 +0000 Subject: [PATCH 0034/1210] Bump structopt from 0.3.12 to 0.3.13 (#64) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index bff9297112916..e0a5870936010 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -14,7 +14,7 @@ name = "bridge-node" futures = "0.3.1" jsonrpc-core = "14.0.3" log = "0.4.8" -structopt = "0.3.12" +structopt = "0.3.13" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } From e3bd9ac0dd855bda701ae86d8f13490c30031520 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 03:15:52 +0000 Subject: [PATCH 0035/1210] Bump jsonrpc-core from 14.0.5 to 14.1.0 (#68) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index e0a5870936010..abc7b4cd9e408 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -12,7 +12,7 @@ name = "bridge-node" [dependencies] futures = "0.3.1" -jsonrpc-core = "14.0.3" +jsonrpc-core = "14.1.0" log = "0.4.8" structopt = "0.3.13" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } From b3fd3aba1284e86c4b59fb167631184222fc821f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Apr 2020 13:31:29 +0300 Subject: [PATCH 0036/1210] local testnet for substrate node (#70) --- bin/node/node/src/chain_spec.rs | 67 ++++++++++++++-- bin/node/runtime/Cargo.toml | 12 +++ bin/node/runtime/src/lib.rs | 131 ++++++++++++++++++++++++++++++-- 3 files changed, 195 insertions(+), 15 deletions(-) diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 0e81f7f167658..13bb3f167d369 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -15,8 +15,8 @@ // along with Parity Bridges Common. If not, see . use bridge_node_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, GenesisConfig, GrandpaConfig, Signature, SudoConfig, - SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, GenesisConfig, GrandpaConfig, SessionConfig, + SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use grandpa_primitives::AuthorityId as GrandpaId; use sc_service; @@ -34,6 +34,8 @@ pub type ChainSpec = sc_service::ChainSpec; pub enum Alternative { /// Whatever the current runtime is, with just Alice as an auth. Development, + /// Whatever the current runtime is, with simple Alice/Bob/Charlie/Dave/Eve auths. + LocalTestnet, } /// Helper function to generate a crypto pair from seed @@ -54,8 +56,12 @@ where } /// Helper function to generate an authority key for Aura -pub fn get_authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { - (get_from_seed::(s), get_from_seed::(s)) +pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { + ( + get_account_id_from_seed::(s), + get_from_seed::(s), + get_from_seed::(s), + ) } impl Alternative { @@ -84,19 +90,60 @@ impl Alternative { None, None, ), + Alternative::LocalTestnet => ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + || { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), + get_authority_keys_from_seed("Charlie"), + get_authority_keys_from_seed("Dave"), + get_authority_keys_from_seed("Eve"), + ], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true, + ) + }, + vec![], + None, + None, + None, + None, + ), }) } pub(crate) fn from(s: &str) -> Option { match s { "" | "dev" => Some(Alternative::Development), + "local" => Some(Alternative::LocalTestnet), _ => None, } } } +fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { + SessionKeys { aura, grandpa } +} + fn testnet_genesis( - initial_authorities: Vec<(AuraId, GrandpaId)>, + initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, @@ -110,13 +157,19 @@ fn testnet_genesis( balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }), pallet_aura: Some(AuraConfig { - authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), + authorities: Vec::new(), }), pallet_bridge_eth_poa: load_kovan_config(), pallet_grandpa: Some(GrandpaConfig { - authorities: initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect(), + authorities: Vec::new(), }), pallet_sudo: Some(SudoConfig { key: root_key }), + pallet_session: Some(SessionConfig { + keys: initial_authorities + .iter() + .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) + .collect::>(), + }), } } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 06c8d930708db..394db75e179fd 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -59,6 +59,12 @@ default-features = false rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate/" +[dependencies.pallet-session] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + [dependencies.frame-system] version = "2.0.0-alpha.2" default-features = false @@ -149,6 +155,12 @@ default-features = false rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" git = "https://github.com/paritytech/substrate/" +[dependencies.sp-staking] +version = "2.0.0-alpha.2" +default-features = false +rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +git = "https://github.com/paritytech/substrate/" + [dependencies.sp-std] version = "2.0.0-alpha.2" default-features = false diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 1ec47fde80168..5128ec58e9cf1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -24,12 +24,15 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +use codec::{Decode, Encode}; use pallet_grandpa::fg_primitives; use pallet_grandpa::AuthorityList as GrandpaAuthorityList; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::OpaqueMetadata; -use sp_runtime::traits::{BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, IdentityLookup, Verify}; +use sp_runtime::traits::{ + BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, IdentityLookup, OpaqueKeys, Verify, +}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::TransactionValidity, ApplyExtrinsicResult, MultiSignature, @@ -89,12 +92,12 @@ pub mod opaque { pub type Block = generic::Block; /// Opaque block identifier type. pub type BlockId = generic::BlockId; +} - impl_opaque_keys! { - pub struct SessionKeys { - pub aura: Aura, - pub grandpa: Grandpa, - } +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, } } @@ -233,6 +236,72 @@ impl pallet_sudo::Trait for Runtime { type Call = Call; } +parameter_types! { + pub const Period: BlockNumber = 4; + pub const Offset: BlockNumber = 0; +} + +impl pallet_session::Trait for Runtime { + type Event = Event; + type ValidatorId = ::AccountId; + type ValidatorIdOf = (); + type ShouldEndSession = pallet_session::PeriodicSessions; + type SessionManager = ShiftSessionManager; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; + type DisabledValidatorsThreshold = (); +} + +pub struct ShiftSessionManager; + +impl ShiftSessionManager { + /// Select validators for session. + fn select_validators( + session_index: sp_staking::SessionIndex, + available_validators: &[AccountId], + ) -> Vec { + let available_validators_count = available_validators.len(); + let count = sp_std::cmp::max(1, 2 * available_validators_count / 3); + let offset = session_index as usize % available_validators_count; + let end = offset + count; + let session_validators = match end.overflowing_sub(available_validators_count) { + (wrapped_end, false) if wrapped_end != 0 => available_validators[offset..] + .iter() + .chain(available_validators[..wrapped_end].iter()) + .cloned() + .collect(), + _ => available_validators[offset..end].to_vec(), + }; + + session_validators + } +} + +impl pallet_session::SessionManager for ShiftSessionManager { + fn end_session(_: sp_staking::SessionIndex) {} + fn new_session(session_index: sp_staking::SessionIndex) -> Option> { + // can't access genesis config here :/ + if session_index == 0 || session_index == 1 { + return None; + } + + // the idea that on first call (i.e. when session 1 ends) we're reading current + // set of validators from session module (they are initial validators) and save + // in our 'local storage'. + // then for every session we select (deterministically) 2/3 of these initial + // validators to serve validators of new session + let available_validators = sp_io::storage::get(b":available_validators") + .and_then(|validators| Decode::decode(&mut &validators[..]).ok()) + .unwrap_or_else(|| { + let validators = >::validators(); + sp_io::storage::set(b":available_validators", &validators.encode()); + validators + }); + + Some(Self::select_validators(session_index, &available_validators)) + } +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -247,6 +316,7 @@ construct_runtime!( Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, + Session: pallet_session::{Module, Call, Storage, Event, Config}, BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage, ValidateUnsigned}, } ); @@ -374,13 +444,13 @@ impl_runtime_apis! { impl sp_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { - opaque::SessionKeys::generate(seed) + SessionKeys::generate(seed) } fn decode_session_keys( encoded: Vec, ) -> Option, sp_core::crypto::KeyTypeId)>> { - opaque::SessionKeys::decode_into_raw_public_keys(&encoded) + SessionKeys::decode_into_raw_public_keys(&encoded) } } @@ -390,3 +460,48 @@ impl_runtime_apis! { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn shift_session_manager_works() { + let acc1 = AccountId::from([1u8; 32]); + let acc2 = AccountId::from([2u8; 32]); + let acc3 = AccountId::from([3u8; 32]); + let acc4 = AccountId::from([4u8; 32]); + let acc5 = AccountId::from([5u8; 32]); + let all_accs = vec![acc1.clone(), acc2.clone(), acc3.clone(), acc4.clone(), acc5.clone()]; + + // at least 1 validator is selected + assert_eq!( + ShiftSessionManager::select_validators(0, &[acc1.clone()]), + vec![acc1.clone()], + ); + + // at session#0, shift is also 0 + assert_eq!( + ShiftSessionManager::select_validators(0, &all_accs), + vec![acc1.clone(), acc2.clone(), acc3.clone()], + ); + + // at session#1, shift is also 1 + assert_eq!( + ShiftSessionManager::select_validators(1, &all_accs), + vec![acc2.clone(), acc3.clone(), acc4.clone()], + ); + + // at session#3, we're wrapping + assert_eq!( + ShiftSessionManager::select_validators(3, &all_accs), + vec![acc4, acc5, acc1.clone()], + ); + + // at session#5, we're starting from the beginning again + assert_eq!( + ShiftSessionManager::select_validators(5, &all_accs), + vec![acc1, acc2, acc3], + ); + } +} From 83a793037503bde8069e604479f29d033b747bbc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2020 01:54:18 +0000 Subject: [PATCH 0037/1210] Bump structopt from 0.3.13 to 0.3.14 (#77) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index abc7b4cd9e408..2b5c9775e1948 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -14,7 +14,7 @@ name = "bridge-node" futures = "0.3.1" jsonrpc-core = "14.1.0" log = "0.4.8" -structopt = "0.3.13" +structopt = "0.3.14" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } From a34dc38f27511eed1440a13dca027d8026a8686b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Apr 2020 16:40:23 +0300 Subject: [PATCH 0038/1210] Migrate to new substrate (#79) * new substrate version + actually verify justification * cargo update + fix remaining stuff * add weight=0 comments * cargo fmt --all * fix hash types --- bin/node/node/Cargo.toml | 81 ++++++++++++----------- bin/node/node/src/chain_spec.rs | 19 +----- bin/node/node/src/command.rs | 62 ++++++++++++++---- bin/node/node/src/main.rs | 13 +--- bin/node/node/src/service.rs | 56 ++++++++-------- bin/node/runtime/Cargo.toml | 102 ++++++++++++++--------------- bin/node/runtime/src/lib.rs | 42 ++++++++---- modules/ethereum/Cargo.toml | 20 +++--- modules/ethereum/src/lib.rs | 18 ++--- modules/substrate/Cargo.toml | 36 +++++----- modules/substrate/src/lib.rs | 12 ++-- primitives/ethereum-poa/Cargo.toml | 18 ++--- relays/ethereum/Cargo.toml | 26 ++++---- relays/substrate/Cargo.toml | 12 ++-- 14 files changed, 282 insertions(+), 235 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 2b5c9775e1948..6dfaa6b58e80c 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -19,95 +19,100 @@ bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } [dependencies.sc-cli] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa] package = "sc-finality-grandpa" -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sc-client-api] +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-client] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -115,6 +120,6 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 13bb3f167d369..11a31c7ae1cb5 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -25,7 +25,7 @@ use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::ChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; /// The chain specification option. This is expected to come in from the CLI and /// is little more than one of a number of alternatives which can easily be converted @@ -71,6 +71,7 @@ impl Alternative { Alternative::Development => ChainSpec::from_genesis( "Development", "dev", + sc_service::ChainType::Development, || { testnet_genesis( vec![get_authority_keys_from_seed("Alice")], @@ -93,6 +94,7 @@ impl Alternative { Alternative::LocalTestnet => ChainSpec::from_genesis( "Local Testnet", "local_testnet", + sc_service::ChainType::Local, || { testnet_genesis( vec![ @@ -128,14 +130,6 @@ impl Alternative { ), }) } - - pub(crate) fn from(s: &str) -> Option { - match s { - "" | "dev" => Some(Alternative::Development), - "local" => Some(Alternative::LocalTestnet), - _ => None, - } - } } fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { @@ -173,13 +167,6 @@ fn testnet_genesis( } } -pub fn load_spec(id: &str) -> Result, String> { - Ok(match Alternative::from(id) { - Some(spec) => Some(spec.load()?), - None => None, - }) -} - fn load_kovan_config() -> Option { Some(BridgeEthPoAConfig { initial_header: sp_bridge_eth_poa::Header { diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs index cdae1c8e3aae8..cfe7115239eeb 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/node/src/command.rs @@ -30,28 +30,64 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::chain_spec; use crate::cli::Cli; use crate::service; -use sc_cli::VersionInfo; +use sc_cli::SubstrateCli; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -/// Parse and run command line arguments -pub fn run(version: VersionInfo) -> sc_cli::Result<()> { - let opt = sc_cli::from_args::(&version); +impl SubstrateCli for Cli { + fn impl_name() -> &'static str { + "Bridge Node" + } + + fn impl_version() -> &'static str { + env!("CARGO_PKG_VERSION") + } + + fn description() -> &'static str { + "Bridge Node" + } + + fn author() -> &'static str { + "Parity Technologies" + } + + fn support_url() -> &'static str { + "https://github.com/paritytech/parity-bridges-common/" + } + + fn copyright_start_year() -> i32 { + 2019 + } + + fn executable_name() -> &'static str { + "bridge-node" + } - let mut config = sc_service::Configuration::from_version(&version); + fn load_spec(&self, id: &str) -> Result, String> { + Ok(Box::new( + match id { + "" | "dev" => crate::chain_spec::Alternative::Development, + "local" => crate::chain_spec::Alternative::LocalTestnet, + _ => return Err(format!("Unsupported chain specification: {}", id)), + } + .load()?, + )) + } +} + +/// Parse and run command line arguments +pub fn run() -> sc_cli::Result<()> { + let cli = Cli::from_args(); - match opt.subcommand { + match &cli.subcommand { Some(subcommand) => { - subcommand.init(&version)?; - subcommand.update_config(&mut config, chain_spec::load_spec, &version)?; - subcommand.run(config, |config: _| Ok(new_full_start!(config).0)) + let runner = cli.create_runner(subcommand)?; + runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0)) } None => { - opt.run.init(&version)?; - opt.run.update_config(&mut config, chain_spec::load_spec, &version)?; - opt.run.run(config, service::new_light, service::new_full, &version) + let runner = cli.create_runner(&cli.run)?; + runner.run_node(service::new_light, service::new_full, bridge_node_runtime::VERSION) } } } diff --git a/bin/node/node/src/main.rs b/bin/node/node/src/main.rs index 3a5823d8d7432..30b05d773b0ea 100644 --- a/bin/node/node/src/main.rs +++ b/bin/node/node/src/main.rs @@ -24,16 +24,5 @@ mod cli; mod command; fn main() -> sc_cli::Result<()> { - let version = sc_cli::VersionInfo { - name: "Bridge Node", - commit: env!("VERGEN_SHA_SHORT"), - version: env!("CARGO_PKG_VERSION"), - executable_name: "bridge-node", - author: "Parity Technologies", - description: "Bridge Node", - support_url: "https://github.com/paritytech/parity-bridges-common/", - copyright_start_year: 2019, - }; - - command::run(version) + command::run() } diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 4ed07fed2b1f5..82bd60c11a3cf 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -16,9 +16,10 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -use bridge_node_runtime::{self, opaque::Block, GenesisConfig, RuntimeApi}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; +use bridge_node_runtime::{self, opaque::Block, RuntimeApi}; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider}; use sc_client::LongestChain; +use sc_client_api::ExecutorProvider; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_service::{error::Error as ServiceError, AbstractService, Configuration, ServiceBuilder}; @@ -40,6 +41,8 @@ native_executor_instance!( /// be able to perform chain operations. macro_rules! new_full_start { ($config:expr) => {{ + use std::sync::Arc; + let mut import_setup = None; let inherent_data_providers = sp_inherents::InherentDataProviders::new(); @@ -49,11 +52,12 @@ macro_rules! new_full_start { crate::service::Executor, >($config)? .with_select_chain(|_config, backend| Ok(sc_client::LongestChain::new(backend.clone())))? - .with_transaction_pool(|config, client, _fetcher| { + .with_transaction_pool(|config, client, _fetcher, prometheus_registry| { let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); Ok(sc_transaction_pool::BasicPool::new( config, std::sync::Arc::new(pool_api), + prometheus_registry, )) })? .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { @@ -61,7 +65,8 @@ macro_rules! new_full_start { .take() .ok_or_else(|| sc_service::Error::SelectChainRequired)?; - let (grandpa_block_import, grandpa_link) = grandpa::block_import(client.clone(), &*client, select_chain)?; + let (grandpa_block_import, grandpa_link) = + grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( grandpa_block_import.clone(), @@ -97,17 +102,12 @@ macro_rules! new_full_start { } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { - let is_authority = config.roles.is_authority(); +pub fn new_full(config: Configuration) -> Result { + let role = config.role.clone(); let force_authoring = config.force_authoring; - let name = config.name.clone(); + let name = config.network.node_name.clone(); let disable_grandpa = config.disable_grandpa; - // sentry nodes announce themselves as authorities to the network - // and should run the same protocols authorities do, but it should - // never actively participate in any consensus process. - let participates_in_consensus = is_authority && !config.sentry_mode; - let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); let (block_import, grandpa_link) = import_setup @@ -116,15 +116,13 @@ pub fn new_full(config: Configuration) -> Result>; + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? .build()?; - if participates_in_consensus { - let proposer = sc_basic_authorship::ProposerFactory { - client: service.client(), - transaction_pool: service.transaction_pool(), - }; + if role.is_authority() { + let proposer = sc_basic_authorship::ProposerFactory::new(service.client(), service.transaction_pool()); let client = service.client(); let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?; @@ -151,7 +149,7 @@ pub fn new_full(config: Configuration) -> Result) -> Result) -> Result) -> Result) -> Result { +pub fn new_light(config: Configuration) -> Result { let inherent_data_providers = InherentDataProviders::new(); ServiceBuilder::new_light::(config)? .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))? - .with_transaction_pool(|config, client, fetcher| { + .with_transaction_pool(|config, client, fetcher, prometheus_registry| { let fetcher = fetcher.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); let pool = sc_transaction_pool::BasicPool::with_revalidation_type( config, Arc::new(pool_api), + prometheus_registry, sc_transaction_pool::RevalidationType::Light, ); Ok(pool) @@ -216,8 +215,12 @@ pub fn new_light(config: Configuration) -> Result), + Arc::new(fetch_checker), + )?; let finality_proof_import = grandpa_block_import.clone(); let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); @@ -233,7 +236,8 @@ pub fn new_light(config: Configuration) -> Result>; + Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? .build() } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 394db75e179fd..f39b55625afbb 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -19,15 +19,15 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-bridge-eth-poa] @@ -36,76 +36,76 @@ default-features = false path = "../../../modules/ethereum" [dependencies.frame-support] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-bridge-eth-poa] @@ -114,75 +114,75 @@ default-features = false path = "../../../primitives/ethereum-poa" [dependencies.sp-consensus-aura] -version = "0.8.0-alpha.2" +version = "0.8.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [build-dependencies.wasm-builder-runner] version = "1.0.5" package = "substrate-wasm-builder-runner" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [features] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 5128ec58e9cf1..45db36476e3df 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -34,8 +34,9 @@ use sp_runtime::traits::{ BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, IdentityLookup, OpaqueKeys, Verify, }; use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, transaction_validity::TransactionValidity, ApplyExtrinsicResult, - MultiSignature, + create_runtime_str, generic, impl_opaque_keys, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -43,7 +44,12 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. -pub use frame_support::{construct_runtime, parameter_types, traits::Randomness, weights::Weight, StorageValue}; +pub use frame_support::{ + construct_runtime, parameter_types, + traits::Randomness, + weights::{RuntimeDbWeight, Weight}, + StorageValue, +}; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_timestamp::Call as TimestampCall; @@ -109,6 +115,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_version: 1, impl_version: 1, apis: RUNTIME_API_VERSIONS, + transaction_version: 1, }; pub const MILLISECS_PER_BLOCK: u64 = 6000; @@ -131,10 +138,15 @@ pub fn native_version() -> NativeVersion { parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 1_000_000; + pub const MaximumBlockWeight: Weight = 2_000_000_000_000; + pub const ExtrinsicBaseWeight: Weight = 10_000_000; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 60_000_000, // ~0.06 ms = ~60 µs + write: 200_000_000, // ~0.2 ms = 200 µs + }; } impl frame_system::Trait for Runtime { @@ -162,6 +174,14 @@ impl frame_system::Trait for Runtime { type BlockHashCount = BlockHashCount; /// Maximum weight of each block. type MaximumBlockWeight = MaximumBlockWeight; + /// The weight of database operations that the runtime can invoke. + type DbWeight = DbWeight; + /// The weight of the overhead invoked on the block import process, independent of the + /// extrinsics included in that block. + type BlockExecutionWeight = (); + /// The base weight of any extrinsic processed by the runtime, independent of the + /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. type MaximumBlockLength = MaximumBlockLength; /// Portion of the block weight that is available to all normal transactions. @@ -225,7 +245,6 @@ parameter_types! { impl pallet_transaction_payment::Trait for Runtime { type Currency = pallet_balances::Module; type OnTransactionPayment = (); - type TransactionBaseFee = TransactionBaseFee; type TransactionByteFee = TransactionByteFee; type WeightToFee = ConvertInto; type FeeMultiplierUpdate = (); @@ -246,6 +265,7 @@ impl pallet_session::Trait for Runtime { type ValidatorId = ::AccountId; type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; type SessionManager = ShiftSessionManager; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; @@ -279,6 +299,7 @@ impl ShiftSessionManager { impl pallet_session::SessionManager for ShiftSessionManager { fn end_session(_: sp_staking::SessionIndex) {} + fn start_session(_: sp_staking::SessionIndex) {} fn new_session(session_index: sp_staking::SessionIndex) -> Option> { // can't access genesis config here :/ if session_index == 0 || session_index == 1 { @@ -376,10 +397,6 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } - fn apply_trusted_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { - Executive::apply_trusted_extrinsic(extrinsic) - } - fn finalize_block() -> ::Header { Executive::finalize_block() } @@ -421,8 +438,11 @@ impl_runtime_apis! { } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { - Executive::validate_transaction(tx) + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx) } } diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 3b752212ec9bf..96024f0ac70a0 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -12,33 +12,33 @@ primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum- # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" # Dev Dependencies diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index b7bdd066b2567..9f0b0cbd03171 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -21,8 +21,8 @@ use frame_support::{decl_module, decl_storage}; use primitives::{Address, Header, Receipt, H256, U256}; use sp_runtime::{ transaction_validity::{ - InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionValidity, UnknownTransaction, - ValidTransaction, + InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity, + UnknownTransaction, ValidTransaction, }, RuntimeDebug, }; @@ -293,6 +293,7 @@ pub trait Trait: frame_system::Trait { decl_module! { pub struct Module for enum Call where origin: T::Origin { /// Import single Aura header. Requires transaction to be **UNSIGNED**. + #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_unsigned_header(origin, header: Header, receipts: Option>) { frame_system::ensure_none(origin)?; @@ -313,6 +314,7 @@ decl_module! { /// /// This should be used with caution - passing too many headers could lead to /// enormous block production/import time. + #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_signed_headers(origin, headers_with_receipts: Vec<(Header, Option>)>) { let submitter = frame_system::ensure_signed(origin)?; let mut finalized_headers = BTreeMap::new(); @@ -359,19 +361,19 @@ decl_storage! { /// Oldest unpruned block(s) number. OldestUnprunedBlock: u64; /// Map of imported headers by hash. - Headers: map hasher(blake2_256) H256 => Option>; + Headers: map hasher(identity) H256 => Option>; /// Map of imported header hashes by number. - HeadersByNumber: map hasher(blake2_256) u64 => Option>; + HeadersByNumber: map hasher(blake2_128_concat) u64 => Option>; /// The ID of next validator set. NextValidatorsSetId: u64; /// Map of validators sets by their id. - ValidatorsSets: map hasher(blake2_256) u64 => Option; + ValidatorsSets: map hasher(twox_64_concat) u64 => Option; /// Validators sets reference count. Each header that is authored by this set increases /// the reference count. When we prune this header, we decrease the reference count. /// When it reaches zero, we are free to prune validator set as well. - ValidatorsSetsRc: map hasher(blake2_256) u64 => Option; + ValidatorsSetsRc: map hasher(twox_64_concat) u64 => Option; /// Map of validators set changes scheduled by given header. - ScheduledChanges: map hasher(blake2_256) H256 => Option; + ScheduledChanges: map hasher(identity) H256 => Option; } add_extra_genesis { config(initial_header): Header; @@ -434,7 +436,7 @@ impl Module { impl frame_support::unsigned::ValidateUnsigned for Module { type Call = Call; - fn validate_unsigned(call: &Self::Call) -> TransactionValidity { + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { match *call { Self::Call::import_unsigned_header(ref header, ref receipts) => { let accept_result = verification::accept_aura_header_into_pool( diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 2ac2269af44d8..a62ee1a57ef7f 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -13,57 +13,57 @@ hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "0.8.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 3a0f9a0db557e..efbe0904e6bd8 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -96,11 +96,11 @@ pub trait Trait: system::Trait {} decl_storage! { trait Store for Module as Bridge { /// The number of current bridges managed by the module. - pub NumBridges get(num_bridges) config(): BridgeId; + pub NumBridges get(fn num_bridges) config(): BridgeId; /// Maps a bridge id to a bridge struct. Allows a single /// `bridge` module to manage multiple bridges. - pub TrackedBridges get(tracked_bridges): map hasher(blake2_256) BridgeId => Option>; + pub TrackedBridges get(fn tracked_bridges): map hasher(blake2_128_concat) BridgeId => Option>; } } @@ -108,6 +108,7 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; + #[weight = 0] // TODO: update me fn initialize_bridge( origin, block_header: T::Header, @@ -131,6 +132,7 @@ decl_module! { NumBridges::put(new_bridge_id); } + #[weight = 0] // TODO: update me fn submit_finalized_headers(origin) { let _sender = ensure_signed(origin)?; } @@ -155,8 +157,7 @@ impl Module { proof: StorageProof, validator_set: &Vec<(AuthorityId, AuthorityWeight)>, ) -> DispatchResult { - let checker = - ::Hasher>>::new(*state_root, proof.clone()); + let checker = >::new(*state_root, proof.clone()); let checker = checker.map_err(Self::map_storage_err)?; @@ -259,6 +260,9 @@ mod tests { type Event = (); type BlockHashCount = (); type MaximumBlockWeight = (); + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); type AvailableBlockRatio = (); type MaximumBlockLength = (); type Version = (); diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 015cfacb4e0b7..dca0750b3acde 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -10,7 +10,7 @@ serde = { version = "1.0", optional = true } serde-big-array = { version = "0.2", optional = true } ethbloom = { version = "0.8", default-features = false } parity-bytes = { version = "0.1", default-features = false } -primitive-types = { version = "0.6", default-features = false, features = ["codec", "rlp"] } +primitive-types = { version = "0.7", default-features = false, features = ["codec", "rlp"] } fixed-hash = { version = "0.5", default-features = false } impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } @@ -22,27 +22,27 @@ plain_hasher = { version = "0.2.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-alpha.2" +version = "2.0.0-alpha.6" default-features = false -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [features] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4d659365058b0..02698ef37cdbd 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,40 +22,40 @@ serde = { version = "1.0.106", features = ["derive"] } serde_json = "1.0.51" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" -web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "fix_receipt" } +web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "add-receipt-root" } # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" # I think this is used for sr-io and stuff [dependencies.node-primitives] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" # Branch used for keccack256 hasher code # Could probably move the keccack hasher stuff to our own primitives [dependencies.sp-core] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate.git" # This should get moved to our `bin` folder diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 51c197e7f5c1b..6521ec35f61a3 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -17,16 +17,16 @@ serde_json = "1.0.51" url = "2.1.0" [dependencies.sp-core] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.sp-rpc] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" [dependencies.node-primitives] -version = "2.0.0-alpha.2" -rev = "2afecf81ee19b8a6edb364b419190ea47c4a4a31" +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" git = "https://github.com/paritytech/substrate/" From 1a3094686ae181edd5e4fc26e84119551dfdf792 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 29 Apr 2020 10:09:13 +0300 Subject: [PATCH 0039/1210] Solidity contract that accepts unverified substrate headers (#65) * solidity contract * continue * upd * cargo update * fixes * ehtereum_headers -> headers * extracted some common stuff * ethereum_sync.rs -> sync.rs * make sync generic * continue extracting * continue * add eth-contract argument * continue * some fixes * contract v2 * continue * more fixes * more fixes * deal with duplicated params * removed multiple call_rpc variants * bail_on_error!() * fn submit_ethereum_transaction * more fixes * cargo fmt --all * fix * bail_on_arg_error!() * fix * fix * remove async_extra stuff * substrate-bridge.json -> substrate-bridge-abi.json * get rid of substrate transactions hashes * get rid of ethereum transactions hashes * extracted contract bytecode to separate file * cargo fmt --all * avoid duplicate import in contracts * removed Default::default() * swapped configurations for sub2eth && eth2sub * fix compilation * do not double gas limit when submitting Substrate headers * cargo fmt --all * solidity contract removed * consts * extracted solc compilation details to separate file * removed (obsolete in future Vec justification) * fixed cli option description * fix typos * fix grumble * extracted constants * log decoded header * cargo fmt --all * comment --- modules/ethereum-contract/builtin/Cargo.toml | 20 ++ modules/ethereum-contract/builtin/src/lib.rs | 79 ++++++ relays/ethereum/Cargo.toml | 6 + relays/ethereum/res/substrate-bridge-abi.json | 119 ++++++++ .../res/substrate-bridge-bytecode.hex | 1 + .../res/substrate-bridge-metadata.txt | 5 + relays/ethereum/src/cli.yml | 79 ++++++ relays/ethereum/src/ethereum_client.rs | 260 ++++++++++++++++- .../ethereum/src/ethereum_deploy_contract.rs | 136 +++++++++ relays/ethereum/src/ethereum_sync_loop.rs | 96 ++++--- relays/ethereum/src/ethereum_types.rs | 5 +- relays/ethereum/src/headers.rs | 36 ++- relays/ethereum/src/main.rs | 104 ++++++- relays/ethereum/src/substrate_client.rs | 261 ++++++++++++------ relays/ethereum/src/substrate_sync_loop.rs | 202 ++++++++++++++ relays/ethereum/src/substrate_types.rs | 47 +++- relays/ethereum/src/sync.rs | 34 ++- relays/ethereum/src/sync_loop.rs | 13 +- relays/ethereum/src/utils.rs | 37 +++ 19 files changed, 1347 insertions(+), 193 deletions(-) create mode 100644 modules/ethereum-contract/builtin/Cargo.toml create mode 100644 modules/ethereum-contract/builtin/src/lib.rs create mode 100644 relays/ethereum/res/substrate-bridge-abi.json create mode 100644 relays/ethereum/res/substrate-bridge-bytecode.hex create mode 100644 relays/ethereum/res/substrate-bridge-metadata.txt create mode 100644 relays/ethereum/src/ethereum_deploy_contract.rs create mode 100644 relays/ethereum/src/substrate_sync_loop.rs create mode 100644 relays/ethereum/src/utils.rs diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml new file mode 100644 index 0000000000000..be2b1c7f68363 --- /dev/null +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "ethereum-contract-builtin" +description = "Small crate that helps Solidity contract to verify finality proof." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] + +# General dependencies + +codec = { package = "parity-scale-codec", version = "1.0.0" } +finality-grandpa = { version = "0.11.2", features = ["derive-codec"] } +sp-blockchain = "2.0.0-alpha.5" +sp-finality-grandpa = "2.0.0-alpha.5" +sp-runtime = "2.0.0-alpha.5" + +# Runtime/chain specific dependencies + +bridge-node-runtime = { path = "../../../bin/node/runtime" } diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs new file mode 100644 index 0000000000000..3249307ac9aa3 --- /dev/null +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -0,0 +1,79 @@ +// Copyright 2019-2020 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 . + +use bridge_node_runtime::{BlockNumber, Hash, Header as RuntimeHeader}; +use codec::Decode; +use sp_blockchain::Error as ClientError; + +/// Builtin errors. +#[derive(Debug)] +pub enum Error { + /// Failed to decode Substrate header. + HeaderDecode(codec::Error), + /// Failed to decode best voters set. + BestVotersDecode(codec::Error), + /// Failed to decode finality proof. + FinalityProofDecode(codec::Error), + /// Failed to verify justification. + JustificationVerify(ClientError), +} + +/// Substrate header. +#[derive(Debug)] +pub struct Header { + /// Header hash. + pub hash: Hash, + /// Parent header hash. + pub parent_hash: Hash, + /// Header number. + pub number: BlockNumber, + /// GRANDPA validators change signal. + pub signal: Option, +} + +/// GRANDPA validators set change signal. +#[derive(Debug)] +pub struct ValidatorsSetSignal { + /// Signal delay. + pub delay: BlockNumber, + /// New validators set. + pub validators: Vec, +} + +/// Parse Substrate header. +pub fn parse_substrate_header(raw_header: &[u8]) -> Result { + RuntimeHeader::decode(&mut &raw_header[..]) + .map(|header| Header { + hash: header.hash(), + parent_hash: header.parent_hash, + number: header.number, + signal: None, // TODO: parse me + }) + .map_err(Error::HeaderDecode) +} + +/// Verify GRANDPA finality proof. +pub fn verify_substrate_finality_proof( + _best_set_id: u64, + _raw_best_voters: &[u8], + _raw_best_header: &[u8], + _raw_headers: &[&[u8]], + _raw_finality_proof: &[u8], +) -> Result<(usize, usize), Error> { + Err(Error::JustificationVerify(ClientError::Msg( + "Not yet implemented".into(), + ))) // TODO: implement me +} diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 02698ef37cdbd..d7e337dada792 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -11,11 +11,17 @@ async-stream = "0.2.0" clap = { version = "2.33.0", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" +ethabi = "12.0" +ethabi-contract = "11.0" +ethabi-derive = "11.0" +ethereum-tx-sign = { git = "https://github.com/svyatonik/ethereum-tx-sign.git", branch = "up-ethereum-types" } futures = "0.3.1" +hex = "0.4" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } linked-hash-map = "0.5.2" log = "0.4.8" num-traits = "0.2" +parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" serde = { version = "1.0.106", features = ["derive"] } diff --git a/relays/ethereum/res/substrate-bridge-abi.json b/relays/ethereum/res/substrate-bridge-abi.json new file mode 100644 index 0000000000000..4ff57ab656221 --- /dev/null +++ b/relays/ethereum/res/substrate-bridge-abi.json @@ -0,0 +1,119 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "rawInitialHeader", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "initialValidatorsSetId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "initialValidatorsSet", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "bestKnownHeader", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "finalityTargetNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "finalityTargetHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "rawFinalityProof", + "type": "bytes" + } + ], + "name": "importFinalityProof", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "rawHeader", + "type": "bytes" + } + ], + "name": "importHeader", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "headerHash", + "type": "bytes32" + } + ], + "name": "isFinalityProofRequired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "headerHash", + "type": "bytes32" + } + ], + "name": "isKnownHeader", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/relays/ethereum/res/substrate-bridge-bytecode.hex b/relays/ethereum/res/substrate-bridge-bytecode.hex new file mode 100644 index 0000000000000..54c252b65d685 --- /dev/null +++ b/relays/ethereum/res/substrate-bridge-bytecode.hex @@ -0,0 +1 @@ +60806040523480156200001157600080fd5b5060405162000e6738038062000e67833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d4565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260058352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f92600385019291019062000409565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d19190602085019062000409565b5050505050620004ae565b620002e6620003d4565b600080600080600060608751602089016040516020810160208101602081016020810160a08588886010600019fa6200031e57600080fd5b93519251915190519351929b50909950975090955093505082159050620003a757816001600160401b03811180156200035657600080fd5b506040519080825280601f01601f19166020018201604052801562000382576020820181803683370190505b50905087516020890160208301848184846011600019fa620003a357600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044c57805160ff19168380011785556200047c565b828001600101855582156200047c579182015b828111156200047c5782518255916020019190600101906200045f565b506200048a9291506200048e565b5090565b620004ab91905b808211156200048a576000815560010162000495565b90565b6109a980620004be6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063871ebe181461005c578063a98bfaad1461008d578063d96a2deb146100aa578063e7af0779146100cb578063fae71ae814610173575b600080fd5b6100796004803603602081101561007257600080fd5b5035610225565b604080519115158252519081900360200190f35b610079600480360360208110156100a357600080fd5b503561023a565b6100b2610297565b6040805192835260208301919091528051918290030190f35b610171600480360360208110156100e157600080fd5b8101906020810181356401000000008111156100fc57600080fd5b82018360208201111561010e57600080fd5b8035906020019184600183028401116401000000008311171561013057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506102af945050505050565b005b6101716004803603606081101561018957600080fd5b8135916020810135918101906060810160408201356401000000008111156101b057600080fd5b8201836020820111156101c257600080fd5b803590602001918460018302840111640100000000831117156101e457600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061058e945050505050565b60009081526005602052604090205460ff1690565b6000818152600560205260408120805460ff16801561025e57506001548160020154115b8015610271575080600601548160020154145b80156102905750600354600482015467ffffffffffffffff9081169116145b9392505050565b60008054808252600560205260409091206002015491565b6102b76107a8565b6102c0826106ac565b805160009081526005602052604090205490915060ff1615610329576040805162461bcd60e51b815260206004820152601760248201527f48656164657220697320616c7265616479206b6e6f776e000000000000000000604482015290519081900360640190fd5b6020808201516000908152600590915260409020805460ff168015610358575060018260400151038160020154145b6103935760405162461bcd60e51b81526004018080602001828103825260268152602001806108ee6026913960400191505060405180910390fd5b6006810154158015906103ad575080600201548160060154145b156103f6578160200151600254146103f65760405162461bcd60e51b81526004018080602001828103825260318152602001806109436031913960400191505060405180910390fd5b60068101546080830151511561046b578260400151811061045e576040805162461bcd60e51b815260206004820152601960248201527f4f7665726c617070696e67207369676e616c7320666f756e6400000000000000604482015290519081900360640190fd5b5060608201516040830151015b60048201546005830154600384015467ffffffffffffffff9092169160026000196001831615610100020190911604156104ac575060208401516001909101905b6040805160e0810182526001808252602088810151818401908152898501518486019081526080808c01516060870190815267ffffffffffffffff8a169187019190915260a0860188905260c086018a90528b51600090815260058552969096208551815460ff191690151517815591519382019390935591516002830155925180519293919261054392600385019201906107dd565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c09091015160069091015550509151600055505050565b60008281526005602052604090206002015483146105dd5760405162461bcd60e51b815260040180806020018281038252602f815260200180610914602f913960400191505060405180910390fd5b60025460006105ed85858561079e565b600081815260056020526040902060028281558101546001559091505b8282146106a457506000908152600560205260409020600181015460068201546002830154919291141561069f576005818101546000908152602091909152604090206003805467ffffffffffffffff198116600167ffffffffffffffff9283168101909216178255908201805461069892600492916002610100928216159290920260001901160461085b565b50506106a4565b61060a565b505050505050565b6106b46107a8565b600080600080600060608751602089016040516020810160208101602081016020810160a08588886010600019fa6106eb57600080fd5b93519251915190519351929b50909950975090955093505082159050610771578167ffffffffffffffff8111801561072257600080fd5b506040519080825280601f01601f19166020018201604052801561074d576020820181803683370190505b50905087516020890160208301848184846011600019fa61076d57600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6002549392505050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061081e57805160ff191683800117855561084b565b8280016001018555821561084b579182015b8281111561084b578251825591602001919060010190610830565b506108579291506108d0565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610894578054855561084b565b8280016001018555821561084b57600052602060002091601f016020900482015b8281111561084b5782548255916001019190600101906108b5565b6108ea91905b8082111561085757600081556001016108d6565b9056fe4d697373696e6720706172656e74206865616465722066726f6d207468652073746f726167654d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f726167654d697373696e672072657175697265642066696e616c6974792070726f6f6620666f7220706172656e7420686561646572a26469706673582212206cc35a10288e85e37e14250b2d4af37dc4fbcd59635965d9ac0421cb8db1f66c64736f6c63430006060033 \ No newline at end of file diff --git a/relays/ethereum/res/substrate-bridge-metadata.txt b/relays/ethereum/res/substrate-bridge-metadata.txt new file mode 100644 index 0000000000000..0dc5d853f2046 --- /dev/null +++ b/relays/ethereum/res/substrate-bridge-metadata.txt @@ -0,0 +1,5 @@ +Last Change Date: 2020-04-28 +Solc version: 0.6.6+commit.6c089d02 +Source hash (keccak256): 0xdc46aff04e37129265223e507d17f1407a70cb1ecea3230e1eaa77a17586724d +Source gist: https://gist.github.com/svyatonik/876b388f9507a8de242cb2db9547c4f0 +Compiler flags used (command to produce the file): `docker run -i ethereum/solc:0.6.6 --optimize --bin - < substrate-bridge.sol` \ No newline at end of file diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index fad56da722c5a..4cb33fd7b9cea 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -43,3 +43,82 @@ subcommands: long: sub-signer-password value_name: SUB_SIGNER_PASSWORD help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. + - sub-to-eth: + about: Synchronize headers from Substrate node to Ethereum node. + args: + - eth-host: + long: eth-host + value_name: ETH_HOST + help: Connect to Ethereum node at given host. + takes_value: true + - eth-port: + long: eth-port + value_name: ETH_PORT + help: Connect to Ethereum node at given port. + takes_value: true + - eth-contract: + long: eth-contract + value_name: ETH_CONTRACT + help: Address of deployed bridge contract. + takes_value: true + - eth-signer: + long: eth-signer + value_name: ETH_SIGNER + help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. + - sub-host: + long: sub-host + value_name: SUB_HOST + help: Connect to Substrate node at given host. + takes_value: true + - sub-port: + long: sub-port + value_name: SUB_PORT + help: Connect to Substrate node at given port. + takes_value: true + - eth-deploy-contract: + about: Deploy Bridge contract on Ethereum node. + args: + - eth-host: + long: eth-host + value_name: ETH_HOST + help: Connect to Ethereum node at given host. + takes_value: true + - eth-port: + long: eth-port + value_name: ETH_PORT + help: Connect to Ethereum node at given port. + takes_value: true + - eth-signer: + long: eth-signer + value_name: ETH_SIGNER + help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. + - eth-contract-code: + long: eth-contract-code + value_name: ETH_CONTRACT_CODE + help: Bytecode of bridge contract. + takes_value: true + - sub-host: + long: sub-host + value_name: SUB_HOST + help: Connect to Substrate node at given host. + takes_value: true + - sub-port: + long: sub-port + value_name: SUB_PORT + help: Connect to Substrate node at given port. + takes_value: true + - sub-authorities-set-id: + long: sub-authorities-set-id + value_name: SUB_AUTHORITIES_SET_ID + help: ID of initial GRANDPA authorities set. + takes_value: true + - sub-authorities-set: + long: sub-authorities-set + value_name: SUB_AUTHORITIES_SET + help: Encoded initial GRANDPA authorities set. + takes_value: true + - sub-initial-header: + long: sub-initial-header + value_name: SUB_INITIAL_HEADER + help: Encoded initial Substrate header. + takes_value: true diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index cddbc8bc148f1..8cc6078123fc7 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -14,14 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{EthereumHeaderId, Header, Receipt, H256, U64}; -use crate::sync_types::MaybeConnectionError; +use crate::ethereum_types::{Address, Bytes, EthereumHeaderId, Header, Receipt, TransactionHash, H256, U256, U64}; +use crate::substrate_types::{Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; +use crate::sync_types::{HeaderId, MaybeConnectionError}; +use crate::{bail_on_arg_error, bail_on_error}; +use codec::{Decode, Encode}; +use ethabi::FunctionOutputDecoder; use jsonrpsee::common::Params; use jsonrpsee::raw::{RawClient, RawClientError}; use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; -use serde::de::DeserializeOwned; +use parity_crypto::publickey::KeyPair; +use serde::{de::DeserializeOwned, Serialize}; use serde_json::{from_value, to_value}; +// to encode/decode contract calls +ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json"); + /// Proof of hash serialization success. const HASH_SERIALIZATION_PROOF: &'static str = "hash serialization never fails; qed"; /// Proof of integer serialization success. @@ -29,24 +37,83 @@ const INT_SERIALIZATION_PROOF: &'static str = "integer serialization never fails /// Proof of bool serialization success. const BOOL_SERIALIZATION_PROOF: &'static str = "bool serialization never fails; qed"; +/// Ethereum connection params. +#[derive(Debug)] +pub struct EthereumConnectionParams { + /// Ethereum RPC host. + pub host: String, + /// Ethereum RPC port. + pub port: u16, +} + +impl Default for EthereumConnectionParams { + fn default() -> Self { + EthereumConnectionParams { + host: "localhost".into(), + port: 8545, + } + } +} + +/// Ethereum signing params. +#[derive(Clone, Debug)] +pub struct EthereumSigningParams { + /// Ethereum chain id. + pub chain_id: u64, + /// Ethereum transactions signer. + pub signer: KeyPair, + /// Gas price we agree to pay. + pub gas_price: U256, +} + +impl Default for EthereumSigningParams { + fn default() -> Self { + EthereumSigningParams { + chain_id: 0x11, // Parity dev chain + // account that has a lot of ether when we run instant seal engine + // address: 0x00a329c0648769a73afac7f9381e08fb43dbea72 + // secret: 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 + signer: KeyPair::from_secret_slice( + &hex::decode("4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7") + .expect("secret is hardcoded, thus valid; qed"), + ) + .expect("secret is hardcoded, thus valid; qed"), + gas_price: 8_000_000_000u64.into(), // 8 Gwei + } + } +} + /// Ethereum client type. pub type Client = RawClient; +/// Ethereum contract call request. +#[derive(Debug, Default, PartialEq, Serialize)] +pub struct CallRequest { + /// Contract address. + pub to: Option

, + /// Call data. + pub data: Option, +} + /// All possible errors that can occur during interacting with Ethereum node. #[derive(Debug)] pub enum Error { /// Request start failed. StartRequestFailed(RequestError), + /// Error serializing request. + RequestSerialization(serde_json::Error), /// Request not found (should never occur?). RequestNotFound, /// Failed to receive response. ResponseRetrievalFailed(RawClientError), /// Failed to parse response. - ResponseParseFailed(serde_json::Error), + ResponseParseFailed(String), /// We have received header with missing number and hash fields. IncompleteHeader, /// We have received receipt with missing gas_used field. IncompleteReceipt, + /// Invalid Substrate block number received from Ethereum node. + InvalidSubstrateBlockNumber, } impl MaybeConnectionError for Error { @@ -59,8 +126,9 @@ impl MaybeConnectionError for Error { } /// Returns client that is able to call RPCs on Ethereum node. -pub fn client(uri: &str) -> Client { - let transport = HttpTransportClient::new(uri); +pub fn client(params: EthereumConnectionParams) -> Client { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); RawClient::new(transport) } @@ -118,15 +186,11 @@ pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result, + transactions: Vec, ) -> (Client, Result<(EthereumHeaderId, Vec), Error>) { - let mut transactions_receipts = Vec::with_capacity(transacactions.len()); - for transacaction in transacactions { - let (next_client, transaction_receipt) = transaction_receipt(client, transacaction).await; - let transaction_receipt = match transaction_receipt { - Ok(transaction_receipt) => transaction_receipt, - Err(error) => return (next_client, Err(error)), - }; + let mut transactions_receipts = Vec::with_capacity(transactions.len()); + for transaction in transactions { + let (next_client, transaction_receipt) = bail_on_error!(transaction_receipt(client, transaction).await); transactions_receipts.push(transaction_receipt); client = next_client; } @@ -150,6 +214,172 @@ async fn transaction_receipt(client: Client, hash: H256) -> (Client, Result (Client, Result) { + let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); + let call_request = bail_on_arg_error!( + to_value(CallRequest { + to: Some(contract_address), + data: Some(encoded_call.into()), + }) + .map_err(|e| Error::RequestSerialization(e)), + client + ); + let (client, call_result) = + bail_on_error!(call_rpc::(client, "eth_call", Params::Array(vec![call_request]),).await); + let (number, raw_hash) = match call_decoder.decode(&call_result.0) { + Ok((raw_number, raw_hash)) => (raw_number, raw_hash), + Err(error) => return (client, Err(Error::ResponseParseFailed(format!("{}", error)))), + }; + let hash = match SubstrateHash::decode(&mut &raw_hash[..]) { + Ok(hash) => hash, + Err(error) => return (client, Err(Error::ResponseParseFailed(format!("{}", error)))), + }; + + if number != number.low_u32().into() { + return (client, Err(Error::InvalidSubstrateBlockNumber)); + } + + (client, Ok(HeaderId(number.low_u32(), hash))) +} + +/// Returns true if Substrate header is known to Ethereum node. +pub async fn substrate_header_known( + client: Client, + contract_address: Address, + id: SubstrateHeaderId, +) -> (Client, Result<(SubstrateHeaderId, bool), Error>) { + let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1); + let call_request = bail_on_arg_error!( + to_value(CallRequest { + to: Some(contract_address), + data: Some(encoded_call.into()), + }) + .map_err(|e| Error::RequestSerialization(e)), + client + ); + let (client, call_result) = + bail_on_error!(call_rpc::(client, "eth_call", Params::Array(vec![call_request]),).await); + match call_decoder.decode(&call_result.0) { + Ok(is_known_block) => (client, Ok((id, is_known_block))), + Err(error) => (client, Err(Error::ResponseParseFailed(format!("{}", error)))), + } +} + +/// Submits Substrate headers to Ethereum contract. +pub async fn submit_substrate_headers( + client: Client, + params: EthereumSigningParams, + contract_address: Address, + headers: Vec, +) -> (Client, Result, Error>) { + let (mut client, mut nonce) = + bail_on_error!(account_nonce(client, params.signer.address().as_fixed_bytes().into()).await); + + let ids = headers.iter().map(|header| header.id()).collect(); + for header in headers { + client = bail_on_error!( + submit_ethereum_transaction( + client, + ¶ms, + Some(contract_address), + Some(nonce), + false, + bridge_contract::functions::import_header::encode_input(header.extract().0.encode(),), + ) + .await + ) + .0; + + nonce += 1.into(); + } + + (client, Ok(ids)) +} + +/// Deploy bridge contract. +pub async fn deploy_bridge_contract( + client: Client, + params: &EthereumSigningParams, + contract_code: Vec, + initial_header: Vec, + initial_set_id: u64, + initial_authorities: Vec, +) -> (Client, Result<(), Error>) { + submit_ethereum_transaction( + client, + params, + None, + None, + false, + bridge_contract::constructor(contract_code, initial_header, initial_set_id, initial_authorities), + ) + .await +} + +/// Submit ethereum transaction. +async fn submit_ethereum_transaction( + client: Client, + params: &EthereumSigningParams, + contract_address: Option
, + nonce: Option, + double_gas: bool, + encoded_call: Vec, +) -> (Client, Result<(), Error>) { + let (client, nonce) = match nonce { + Some(nonce) => (client, nonce), + None => bail_on_error!(account_nonce(client, params.signer.address().as_fixed_bytes().into()).await), + }; + let (client, gas) = bail_on_error!( + estimate_gas( + client, + CallRequest { + to: contract_address, + data: Some(encoded_call.clone().into()), + } + ) + .await + ); + let raw_transaction = ethereum_tx_sign::RawTransaction { + nonce, + to: contract_address, + value: U256::zero(), + gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, + gas_price: params.gas_price, + data: encoded_call, + } + .sign(¶ms.signer.secret().as_fixed_bytes().into(), ¶ms.chain_id); + let transaction = bail_on_arg_error!( + to_value(Bytes(raw_transaction)).map_err(|e| Error::RequestSerialization(e)), + client + ); + let (client, _) = bail_on_error!( + call_rpc::(client, "eth_submitTransaction", Params::Array(vec![transaction])).await + ); + (client, Ok(())) +} + +/// Get account nonce. +async fn account_nonce(client: Client, caller_address: Address) -> (Client, Result) { + let caller_address = bail_on_arg_error!( + to_value(caller_address).map_err(|e| Error::RequestSerialization(e)), + client + ); + call_rpc(client, "eth_getTransactionCount", Params::Array(vec![caller_address])).await +} + +/// Estimate gas usage for call. +async fn estimate_gas(client: Client, call_request: CallRequest) -> (Client, Result) { + let call_request = bail_on_arg_error!( + to_value(call_request).map_err(|e| Error::RequestSerialization(e)), + client + ); + call_rpc(client, "eth_estimateGas", Params::Array(vec![call_request])).await +} + /// Calls RPC on Ethereum node. async fn call_rpc( mut client: Client, @@ -172,7 +402,7 @@ async fn call_rpc( .ok_or(Error::RequestNotFound)? .await .map_err(Error::ResponseRetrievalFailed)?; - from_value(response).map_err(Error::ResponseParseFailed) + from_value(response).map_err(|e| Error::ResponseParseFailed(format!("{}", e))) } let result = do_call_rpc(&mut client, method, params).await; diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs new file mode 100644 index 0000000000000..eb9f66be924b0 --- /dev/null +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -0,0 +1,136 @@ +// Copyright 2019-2020 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 . + +use crate::ethereum_client::{self, EthereumConnectionParams, EthereumSigningParams}; +use crate::substrate_client::{self, SubstrateConnectionParams}; +use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader}; +use codec::{Decode, Encode}; +use num_traits::Zero; + +/// Ethereum synchronization parameters. +#[derive(Debug)] +pub struct EthereumDeployContractParams { + /// Ethereum connection params. + pub eth: EthereumConnectionParams, + /// Ethereum signing params. + pub eth_sign: EthereumSigningParams, + /// Ethereum contract bytecode. + pub eth_contract_code: Vec, + /// Substrate connection params. + pub sub: SubstrateConnectionParams, + /// Initial authorities set id. + pub sub_initial_authorities_set_id: Option, + /// Initial authorities set. + pub sub_initial_authorities_set: Option>, + /// Initial header. + pub sub_initial_header: Option>, +} + +impl Default for EthereumDeployContractParams { + fn default() -> Self { + EthereumDeployContractParams { + eth: Default::default(), + eth_sign: Default::default(), + eth_contract_code: hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")) + .expect("code is hardcoded, thus valid; qed"), + sub: Default::default(), + sub_initial_authorities_set_id: None, + sub_initial_authorities_set: None, + sub_initial_header: None, + } + } +} + +/// Deploy Bridge contract on Ethereum chain. +pub fn run(params: EthereumDeployContractParams) { + let mut local_pool = futures::executor::LocalPool::new(); + + let result = local_pool.run_until(async move { + let eth_client = ethereum_client::client(params.eth); + let sub_client = substrate_client::client(params.sub); + + let (sub_client, initial_header) = prepare_initial_header(sub_client, params.sub_initial_header).await; + let (initial_header_hash, initial_header) = initial_header?; + let initial_set_id = params.sub_initial_authorities_set_id.unwrap_or(0); + let (_, initial_set) = prepare_initial_authorities_set( + sub_client, + initial_header_hash, + params.sub_initial_authorities_set, + ).await; + let initial_set = initial_set?; + + log::info!( + target: "bridge", + "Deploying Ethereum contract.\r\n\tInitial header: {:?}\r\n\tInitial header encoded: {}\r\n\tInitial authorities set ID: {}\r\n\tInitial authorities set: {}", + initial_header, + hex::encode(&initial_header), + initial_set_id, + hex::encode(&initial_set), + ); + + ethereum_client::deploy_bridge_contract( + eth_client, + ¶ms.eth_sign, + params.eth_contract_code, + initial_header, + initial_set_id, + initial_set, + ).await.1.map_err(|error| format!("Error deploying contract: {:?}", error)) + }); + + if let Err(error) = result { + log::error!(target: "bridge", "{}", error); + } +} + +/// Prepare initial header. +async fn prepare_initial_header( + sub_client: substrate_client::Client, + sub_initial_header: Option>, +) -> (substrate_client::Client, Result<(SubstrateHash, Vec), String>) { + match sub_initial_header { + Some(raw_initial_header) => match SubstrateHeader::decode(&mut &raw_initial_header[..]) { + Ok(initial_header) => (sub_client, Ok((initial_header.hash(), raw_initial_header))), + Err(error) => (sub_client, Err(format!("Error decoding initial header: {}", error))), + }, + None => { + let (sub_client, initial_header) = substrate_client::header_by_number(sub_client, Zero::zero()).await; + ( + sub_client, + initial_header + .map(|header| (header.hash(), header.encode())) + .map_err(|error| format!("Error reading Substrate genesis header: {:?}", error)), + ) + } + } +} + +/// Prepare initial GRANDPA authorities set. +async fn prepare_initial_authorities_set( + sub_client: substrate_client::Client, + sub_initial_header_hash: SubstrateHash, + sub_initial_authorities_set: Option>, +) -> (substrate_client::Client, Result, String>) { + let (sub_client, initial_authorities_set) = match sub_initial_authorities_set { + Some(initial_authorities_set) => (sub_client, Ok(initial_authorities_set)), + None => substrate_client::grandpa_authorities_set(sub_client, sub_initial_header_hash).await, + }; + + ( + sub_client, + initial_authorities_set.map_err(|error| format!("Error reading GRANDPA authorities set: {:?}", error)), + ) +} diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 705d78fe9cd4d..7c1743a59ede2 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -14,57 +14,58 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_client; +use crate::ethereum_client::{self, EthereumConnectionParams}; use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; -use crate::substrate_client; +use crate::substrate_client::{self, SubstrateConnectionParams, SubstrateSigningParams}; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; use crate::sync_loop::{SourceClient, TargetClient}; use futures::future::FutureExt; use std::{future::Future, pin::Pin}; -pub use web3::types::H256; +use web3::types::H256; /// Interval (in ms) at which we check new Ethereum headers when we are synced/almost synced. const ETHEREUM_TICK_INTERVAL_MS: u64 = 10_000; /// Interval (in ms) at which we check new Substrate blocks. const SUBSTRATE_TICK_INTERVAL_MS: u64 = 5_000; +/// Max number of headers in single submit transaction. +const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; +/// Max total size of headers in single submit transaction. This only affects signed +/// submissions, when several headers are submitted at once. 4096 is the maximal **expected** +/// size of the Ethereum header + transactions receipts (if they're required). +const MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT: usize = MAX_HEADERS_IN_SINGLE_SUBMIT * 4096; +/// Max Ethereum headers we want to have in all 'before-submitted' states. +const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128; +/// Max Ethereum headers count we want to have in 'submitted' state. +const MAX_SUBMITTED_HEADERS: usize = 128; +/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). +const PRUNE_DEPTH: u32 = 4096; /// Ethereum synchronization parameters. pub struct EthereumSyncParams { - /// Ethereum RPC host. - pub eth_host: String, - /// Ethereum RPC port. - pub eth_port: u16, - /// Substrate RPC host. - pub sub_host: String, - /// Substrate RPC port. - pub sub_port: u16, - /// Substrate transactions signer. - pub sub_signer: sp_core::sr25519::Pair, + /// Ethereum connection params. + pub eth: EthereumConnectionParams, + /// Substrate connection params. + pub sub: SubstrateConnectionParams, + /// Substrate signing params. + pub sub_sign: SubstrateSigningParams, /// Synchronization parameters. pub sync_params: HeadersSyncParams, } -impl std::fmt::Debug for EthereumSyncParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("EthereumSyncParams") - .field("eth_host", &self.eth_host) - .field("eth_port", &self.eth_port) - .field("sub_host", &self.sub_port) - .field("sub_port", &self.sub_port) - .field("sync_params", &self.sync_params) - .finish() - } -} - impl Default for EthereumSyncParams { fn default() -> Self { EthereumSyncParams { - eth_host: "localhost".into(), - eth_port: 8545, - sub_host: "localhost".into(), - sub_port: 9933, - sub_signer: sp_keyring::AccountKeyring::Alice.pair(), - sync_params: Default::default(), + eth: Default::default(), + sub: Default::default(), + sub_sign: Default::default(), + sync_params: HeadersSyncParams { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, + max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + }, } } } @@ -112,10 +113,10 @@ impl SourceClient for EthereumHeadersSource { struct SubstrateHeadersTarget { /// Substrate node client. client: substrate_client::Client, - /// Substrate transactions signer. - signer: sp_core::sr25519::Pair, /// Whether we want to submit signed (true), or unsigned (false) transactions. sign_transactions: bool, + /// Substrate signing params. + sign_params: SubstrateSigningParams, } impl TargetClient for SubstrateHeadersTarget { @@ -126,14 +127,14 @@ impl TargetClient for SubstrateHeadersTarget { type SubmitHeadersFuture = Pin, Self::Error>)>>>; fn best_header_id(self) -> Self::BestHeaderIdFuture { - let (signer, sign_transactions) = (self.signer, self.sign_transactions); + let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); substrate_client::best_ethereum_block(self.client) .map(move |(client, result)| { ( SubstrateHeadersTarget { client, - signer, sign_transactions, + sign_params, }, result, ) @@ -142,14 +143,14 @@ impl TargetClient for SubstrateHeadersTarget { } fn is_known_header(self, id: EthereumHeaderId) -> Self::IsKnownHeaderFuture { - let (signer, sign_transactions) = (self.signer, self.sign_transactions); + let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); substrate_client::ethereum_header_known(self.client, id) .map(move |(client, result)| { ( SubstrateHeadersTarget { client, - signer, sign_transactions, + sign_params, }, result, ) @@ -161,14 +162,14 @@ impl TargetClient for SubstrateHeadersTarget { // we can minimize number of receipts_check calls by checking header // logs bloom here, but it may give us false positives (when authorities // source is contract, we never need any logs) - let (signer, sign_transactions) = (self.signer, self.sign_transactions); + let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); substrate_client::ethereum_receipts_required(self.client, header.clone()) .map(move |(client, result)| { ( SubstrateHeadersTarget { client, - signer, sign_transactions, + sign_params, }, result, ) @@ -177,16 +178,16 @@ impl TargetClient for SubstrateHeadersTarget { } fn submit_headers(self, headers: Vec) -> Self::SubmitHeadersFuture { - let (signer, sign_transactions) = (self.signer, self.sign_transactions); - substrate_client::submit_ethereum_headers(self.client, signer.clone(), headers, sign_transactions) + let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); + substrate_client::submit_ethereum_headers(self.client, sign_params.clone(), headers, sign_transactions) .map(move |(client, result)| { ( SubstrateHeadersTarget { client, - signer, sign_transactions, + sign_params, }, - result.map(|(_, submitted_headers)| submitted_headers), + result, ) }) .boxed() @@ -195,12 +196,9 @@ impl TargetClient for SubstrateHeadersTarget { /// Run Ethereum headers synchronization. pub fn run(params: EthereumSyncParams) { - let eth_uri = format!("http://{}:{}", params.eth_host, params.eth_port); - let eth_client = ethereum_client::client(ð_uri); + let eth_client = ethereum_client::client(params.eth); + let sub_client = substrate_client::client(params.sub); - let sub_uri = format!("http://{}:{}", params.sub_host, params.sub_port); - let sub_client = substrate_client::client(&sub_uri); - let sub_signer = params.sub_signer; let sign_sub_transactions = match params.sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, TargetTransactionMode::Unsigned => false, @@ -211,8 +209,8 @@ pub fn run(params: EthereumSyncParams) { ETHEREUM_TICK_INTERVAL_MS, SubstrateHeadersTarget { client: sub_client, - signer: sub_signer, sign_transactions: sign_sub_transactions, + sign_params: params.sub_sign, }, SUBSTRATE_TICK_INTERVAL_MS, params.sync_params, diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index 93c47da4f7fbe..d996ac7c29455 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -18,7 +18,7 @@ use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethe use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; use codec::Encode; -pub use web3::types::{Bytes, H256, U128, U64}; +pub use web3::types::{Address, Bytes, H256, U128, U256, U64}; /// When header is just received from the Ethereum node, we check that it has /// both number and hash fields filled. @@ -28,6 +28,9 @@ pub const HEADER_ID_PROOF: &'static str = "checked on retrieval; qed"; /// gas_used field filled. pub const RECEIPT_GAS_USED_PROOF: &'static str = "checked on retrieval; qed"; +/// Ethereum transaction hash type. +pub type TransactionHash = H256; + /// Ethereum header type. pub type Header = web3::types::Block; diff --git a/relays/ethereum/src/headers.rs b/relays/ethereum/src/headers.rs index 841743ce1d5e5..0e34b9a98f1b7 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/ethereum/src/headers.rs @@ -117,7 +117,10 @@ impl QueuedHeaders

{ self.maybe_extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), std::cmp::max( self.extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), - self.ready.keys().next_back().cloned().unwrap_or_else(Zero::zero), + std::cmp::max( + self.ready.keys().next_back().cloned().unwrap_or_else(Zero::zero), + self.submitted.keys().next_back().cloned().unwrap_or_else(Zero::zero), + ), ), ), ), @@ -226,6 +229,7 @@ impl QueuedHeaders

{ // all ancestors of this header are now synced => let's remove them from // queues let mut current = *id; + let mut id_processed = false; loop { let header = match self.status(¤t) { HeaderStatus::Unknown => break, @@ -253,22 +257,26 @@ impl QueuedHeaders

{ .entry(current.1) .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; current = header.parent_id(); + id_processed = true; } // remember that the header is synced - log::debug!( - target: "bridge", - "{} header {:?} is now {:?}", - P::SOURCE_NAME, - id, - HeaderStatus::Synced, - ); - *self - .known_headers - .entry(id.0) - .or_default() - .entry(id.1) - .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; + if !id_processed { + // to avoid duplicate log message + log::debug!( + target: "bridge", + "{} header {:?} is now {:?}", + P::SOURCE_NAME, + id, + HeaderStatus::Synced, + ); + *self + .known_headers + .entry(id.0) + .or_default() + .entry(id.1) + .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; + } // now let's move all descendants from maybe_orphan && orphan queues to // maybe_extra queue diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 8d897d51e42ff..ae46468f8fa5e 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -17,17 +17,25 @@ #![recursion_limit = "1024"] mod ethereum_client; +mod ethereum_deploy_contract; mod ethereum_sync_loop; mod ethereum_types; mod headers; mod substrate_client; +mod substrate_sync_loop; mod substrate_types; mod sync; mod sync_loop; mod sync_types; +mod utils; +use ethereum_client::{EthereumConnectionParams, EthereumSigningParams}; +use ethereum_sync_loop::EthereumSyncParams; +use parity_crypto::publickey::{KeyPair, Secret}; use sp_core::crypto::Pair; use std::io::Write; +use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams}; +use substrate_sync_loop::SubstrateSyncParams; fn main() { initialize(); @@ -44,6 +52,24 @@ fn main() { } }); } + ("sub-to-eth", Some(sub_to_eth_matches)) => { + substrate_sync_loop::run(match substrate_sync_params(&sub_to_eth_matches) { + Ok(substrate_sync_params) => substrate_sync_params, + Err(err) => { + log::error!(target: "bridge", "Error parsing parameters: {}", err); + return; + } + }); + } + ("eth-deploy-contract", Some(eth_deploy_matches)) => { + ethereum_deploy_contract::run(match ethereum_deploy_contract_params(ð_deploy_matches) { + Ok(ethereum_deploy_matches) => ethereum_deploy_matches, + Err(err) => { + log::error!(target: "bridge", "Error parsing parameters: {}", err); + return; + } + }); + } ("", _) => { log::error!(target: "bridge", "No subcommand specified"); return; @@ -89,25 +115,58 @@ fn initialize() { builder.init(); } -fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result { - let mut eth_sync_params = ethereum_sync_loop::EthereumSyncParams::default(); +fn ethereum_connection_params(matches: &clap::ArgMatches) -> Result { + let mut params = EthereumConnectionParams::default(); if let Some(eth_host) = matches.value_of("eth-host") { - eth_sync_params.eth_host = eth_host.into(); + params.host = eth_host.into(); } if let Some(eth_port) = matches.value_of("eth-port") { - eth_sync_params.eth_port = eth_port.parse().map_err(|e| format!("{}", e))?; + params.port = eth_port + .parse() + .map_err(|e| format!("Failed to parse eth-port: {}", e))?; + } + Ok(params) +} + +fn ethereum_signing_params(matches: &clap::ArgMatches) -> Result { + let mut params = EthereumSigningParams::default(); + if let Some(eth_signer) = matches.value_of("eth-signer") { + params.signer = eth_signer + .parse::() + .map_err(|e| format!("Failed to parse eth-signer: {}", e)) + .and_then(|secret| KeyPair::from_secret(secret).map_err(|e| format!("Invalid eth-signer: {}", e)))?; } + Ok(params) +} + +fn substrate_connection_params(matches: &clap::ArgMatches) -> Result { + let mut params = SubstrateConnectionParams::default(); if let Some(sub_host) = matches.value_of("sub-host") { - eth_sync_params.sub_host = sub_host.into(); + params.host = sub_host.into(); } if let Some(sub_port) = matches.value_of("sub-port") { - eth_sync_params.sub_port = sub_port.parse().map_err(|e| format!("{}", e))?; + params.port = sub_port + .parse() + .map_err(|e| format!("Failed to parse sub-port: {}", e))?; } + Ok(params) +} + +fn substrate_signing_params(matches: &clap::ArgMatches) -> Result { + let mut params = SubstrateSigningParams::default(); if let Some(sub_signer) = matches.value_of("sub-signer") { let sub_signer_password = matches.value_of("sub-signer-password"); - eth_sync_params.sub_signer = - sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password).map_err(|e| format!("{:?}", e))?; + params.signer = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) + .map_err(|e| format!("Failed to parse sub-signer: {:?}", e))?; } + Ok(params) +} + +fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result { + let mut eth_sync_params = EthereumSyncParams::default(); + eth_sync_params.eth = ethereum_connection_params(matches)?; + eth_sync_params.sub = substrate_connection_params(matches)?; + eth_sync_params.sub_sign = substrate_signing_params(matches)?; match matches.value_of("sub-tx-mode") { Some("signed") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, @@ -124,3 +183,32 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result Result { + let mut sub_sync_params = SubstrateSyncParams::default(); + sub_sync_params.eth = ethereum_connection_params(matches)?; + sub_sync_params.eth_sign = ethereum_signing_params(matches)?; + sub_sync_params.sub = substrate_connection_params(matches)?; + + if let Some(eth_contract) = matches.value_of("eth-contract") { + sub_sync_params.eth_contract_address = eth_contract.parse().map_err(|e| format!("{}", e))?; + } + + Ok(sub_sync_params) +} + +fn ethereum_deploy_contract_params( + matches: &clap::ArgMatches, +) -> Result { + let mut eth_deploy_params = ethereum_deploy_contract::EthereumDeployContractParams::default(); + eth_deploy_params.eth = ethereum_connection_params(matches)?; + eth_deploy_params.eth_sign = ethereum_signing_params(matches)?; + eth_deploy_params.sub = substrate_connection_params(matches)?; + + if let Some(eth_contract_code) = matches.value_of("eth-contract-code") { + eth_deploy_params.eth_contract_code = + hex::decode(ð_contract_code).map_err(|e| format!("Failed to parse eth-contract-code: {}", e))?; + } + + Ok(eth_deploy_params) +} diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 40a9047c5eef4..3d74dec250a7b 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -15,16 +15,60 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256}; -use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts, TransactionHash}; +use crate::substrate_types::{ + into_substrate_ethereum_header, into_substrate_ethereum_receipts, Hash, Header as SubstrateHeader, Number, +}; use crate::sync_types::{HeaderId, MaybeConnectionError, SourceHeader}; +use crate::{bail_on_arg_error, bail_on_error}; use codec::{Decode, Encode}; use jsonrpsee::common::Params; use jsonrpsee::raw::{RawClient, RawClientError}; use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; -use serde_json::{from_value, to_value}; +use num_traits::Zero; +use serde::de::DeserializeOwned; +use serde_json::{from_value, to_value, Value}; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; +/// Substrate connection params. +#[derive(Debug)] +pub struct SubstrateConnectionParams { + /// Substrate RPC host. + pub host: String, + /// Substrate RPC port. + pub port: u16, +} + +impl Default for SubstrateConnectionParams { + fn default() -> Self { + SubstrateConnectionParams { + host: "localhost".into(), + port: 9933, + } + } +} + +/// Substrate signing params. +#[derive(Clone)] +pub struct SubstrateSigningParams { + /// Substrate transactions signer. + pub signer: sp_core::sr25519::Pair, +} + +impl std::fmt::Debug for SubstrateSigningParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.signer.public()) + } +} + +impl Default for SubstrateSigningParams { + fn default() -> Self { + SubstrateSigningParams { + signer: sp_keyring::AccountKeyring::Alice.pair(), + } + } +} + /// Substrate client type. pub struct Client { /// Substrate RPC client. @@ -38,6 +82,8 @@ pub struct Client { pub enum Error { /// Request start failed. StartRequestFailed(RequestError), + /// Error serializing request. + RequestSerialization(serde_json::Error), /// Request not found (should never occur?). RequestNotFound, /// Failed to receive response. @@ -56,23 +102,42 @@ impl MaybeConnectionError for Error { } /// Returns client that is able to call RPCs on Substrate node. -pub fn client(uri: &str) -> Client { - let transport = HttpTransportClient::new(uri); +pub fn client(params: SubstrateConnectionParams) -> Client { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); Client { rpc_client: RawClient::new(transport), genesis_hash: None, } } +/// Returns best Substrate header. +pub async fn best_header(client: Client) -> (Client, Result) { + call_rpc(client, "chain_getHeader", Params::None, rpc_returns_value).await +} + +/// Returns Substrate header by hash. +pub async fn header_by_hash(client: Client, hash: Hash) -> (Client, Result) { + let hash = bail_on_arg_error!(to_value(hash).map_err(|e| Error::RequestSerialization(e)), client); + call_rpc(client, "chain_getHeader", Params::Array(vec![hash]), rpc_returns_value).await +} + +/// Returns Substrate header by number. +pub async fn header_by_number(client: Client, number: Number) -> (Client, Result) { + let (client, hash) = bail_on_error!(block_hash_by_number(client, number).await); + header_by_hash(client, hash).await +} + /// Returns best Ethereum block that Substrate runtime knows of. pub async fn best_ethereum_block(client: Client) -> (Client, Result) { - let (client, result) = call_rpc::<(u64, H256)>( + let (client, result) = call_rpc( client, "state_call", Params::Array(vec![ - to_value("EthereumHeadersApi_best_block").unwrap(), - to_value("0x").unwrap(), + serde_json::Value::String("EthereumHeadersApi_best_block".into()), + serde_json::Value::String("0x".into()), ]), + rpc_returns_encoded_value, ) .await; (client, result.map(|(num, hash)| HeaderId(num, hash))) @@ -85,14 +150,18 @@ pub async fn ethereum_receipts_required( ) -> (Client, Result<(EthereumHeaderId, bool), Error>) { let id = header.header().id(); let header = into_substrate_ethereum_header(header.header()); - let encoded_header = header.encode(); + let encoded_header = bail_on_arg_error!( + to_value(Bytes(header.encode())).map_err(|e| Error::RequestSerialization(e)), + client + ); let (client, receipts_required) = call_rpc( client, "state_call", Params::Array(vec![ - to_value("EthereumHeadersApi_is_import_requires_receipts").unwrap(), - to_value(Bytes(encoded_header)).unwrap(), + serde_json::Value::String("EthereumHeadersApi_is_import_requires_receipts".into()), + encoded_header, ]), + rpc_returns_encoded_value, ) .await; ( @@ -112,14 +181,18 @@ pub async fn ethereum_header_known( // But when we'll read best header from Substrate next time, we will know that // there's a better header => this Orphan will either be marked as synced, or // eventually pruned. - let encoded_id = id.1.encode(); + let encoded_id = bail_on_arg_error!( + to_value(Bytes(id.1.encode())).map_err(|e| Error::RequestSerialization(e)), + client + ); let (client, is_known_block) = call_rpc( client, "state_call", Params::Array(vec![ - to_value("EthereumHeadersApi_is_known_block").unwrap(), - to_value(Bytes(encoded_id)).unwrap(), + serde_json::Value::String("EthereumHeadersApi_is_known_block".into()), + encoded_id, ]), + rpc_returns_encoded_value, ) .await; (client, is_known_block.map(|is_known_block| (id, is_known_block))) @@ -128,12 +201,12 @@ pub async fn ethereum_header_known( /// Submits Ethereum header to Substrate runtime. pub async fn submit_ethereum_headers( client: Client, - signer: sp_core::sr25519::Pair, + params: SubstrateSigningParams, headers: Vec, sign_transactions: bool, -) -> (Client, Result<(Vec, Vec), Error>) { +) -> (Client, Result, Error>) { match sign_transactions { - true => submit_signed_ethereum_headers(client, signer, headers).await, + true => submit_signed_ethereum_headers(client, params, headers).await, false => submit_unsigned_ethereum_headers(client, headers).await, } } @@ -141,78 +214,89 @@ pub async fn submit_ethereum_headers( /// Submits signed Ethereum header to Substrate runtime. pub async fn submit_signed_ethereum_headers( client: Client, - signer: sp_core::sr25519::Pair, + params: SubstrateSigningParams, headers: Vec, -) -> (Client, Result<(Vec, Vec), Error>) { +) -> (Client, Result, Error>) { let ids = headers.iter().map(|header| header.id()).collect(); let (client, genesis_hash) = match client.genesis_hash { Some(genesis_hash) => (client, genesis_hash), None => { - let (mut client, genesis_hash) = block_hash_by_number(client, 0).await; - let genesis_hash = match genesis_hash { - Ok(genesis_hash) => genesis_hash, - Err(err) => return (client, Err(err)), - }; + let (mut client, genesis_hash) = bail_on_error!(block_hash_by_number(client, Zero::zero()).await); client.genesis_hash = Some(genesis_hash); (client, genesis_hash) } }; - let account_id = signer.public().as_array_ref().clone().into(); - let (client, nonce) = next_account_index(client, account_id).await; - let nonce = match nonce { - Ok(nonce) => nonce, - Err(err) => return (client, Err(err)), - }; + let account_id = params.signer.public().as_array_ref().clone().into(); + let (client, nonce) = bail_on_error!(next_account_index(client, account_id).await); - let transaction = create_signed_submit_transaction(headers, &signer, nonce, genesis_hash); - let encoded_transaction = transaction.encode(); - let (client, transaction_hash) = call_rpc( + let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, genesis_hash); + let encoded_transaction = bail_on_arg_error!( + to_value(Bytes(transaction.encode())).map_err(|e| Error::RequestSerialization(e)), + client + ); + let (client, _) = call_rpc( client, "author_submitExtrinsic", - Params::Array(vec![to_value(Bytes(encoded_transaction)).unwrap()]), + Params::Array(vec![encoded_transaction]), + |_| Ok(()), ) .await; - ( - client, - transaction_hash.map(|transaction_hash| (vec![transaction_hash], ids)), - ) + (client, Ok(ids)) } /// Submits unsigned Ethereum header to Substrate runtime. pub async fn submit_unsigned_ethereum_headers( mut client: Client, headers: Vec, -) -> (Client, Result<(Vec, Vec), Error>) { +) -> (Client, Result, Error>) { let ids = headers.iter().map(|header| header.id()).collect(); - let mut transactions_hashes = Vec::new(); for header in headers { let transaction = create_unsigned_submit_transaction(header); - let encoded_transaction = transaction.encode(); - let (used_client, transaction_hash) = call_rpc( - client, - "author_submitExtrinsic", - Params::Array(vec![to_value(Bytes(encoded_transaction)).unwrap()]), - ) - .await; + let encoded_transaction = bail_on_arg_error!( + to_value(Bytes(transaction.encode())).map_err(|e| Error::RequestSerialization(e)), + client + ); + let (used_client, _) = bail_on_error!( + call_rpc( + client, + "author_submitExtrinsic", + Params::Array(vec![encoded_transaction]), + |_| Ok(()), + ) + .await + ); client = used_client; - transactions_hashes.push(match transaction_hash { - Ok(transaction_hash) => transaction_hash, - Err(error) => return (client, Err(error)), - }); } - (client, Ok((transactions_hashes, ids))) + (client, Ok(ids)) +} + +/// Get GRANDPA authorities set at given block. +pub async fn grandpa_authorities_set(client: Client, block: Hash) -> (Client, Result, Error>) { + let block = bail_on_arg_error!(to_value(block).map_err(|e| Error::RequestSerialization(e)), client); + call_rpc( + client, + "state_call", + Params::Array(vec![ + serde_json::Value::String("GrandpaApi_grandpa_authorities".into()), + block, + ]), + rpc_returns_bytes, + ) + .await } /// Get Substrate block hash by its number. -async fn block_hash_by_number(client: Client, number: u64) -> (Client, Result) { +async fn block_hash_by_number(client: Client, number: Number) -> (Client, Result) { + let number = bail_on_arg_error!(to_value(number).map_err(|e| Error::RequestSerialization(e)), client); call_rpc( client, "chain_getBlockHash", - Params::Array(vec![to_value(number).unwrap()]), + Params::Array(vec![number]), + rpc_returns_value, ) .await } @@ -224,42 +308,30 @@ async fn next_account_index( ) -> (Client, Result) { use sp_core::crypto::Ss58Codec; - let (client, index) = call_rpc_u64( - client, - "system_accountNextIndex", - Params::Array(vec![to_value(account.to_ss58check()).unwrap()]), - ) + let account = bail_on_arg_error!( + to_value(account.to_ss58check()).map_err(|e| Error::RequestSerialization(e)), + client + ); + let (client, index) = call_rpc(client, "system_accountNextIndex", Params::Array(vec![account]), |v| { + rpc_returns_value::(v) + }) .await; (client, index.map(|index| index as _)) } /// Calls RPC on Substrate node that returns Bytes. -async fn call_rpc(mut client: Client, method: &'static str, params: Params) -> (Client, Result) { - async fn do_call_rpc(client: &mut Client, method: &'static str, params: Params) -> Result { - let request_id = client - .rpc_client - .start_request(method, params) - .await - .map_err(Error::StartRequestFailed)?; - // WARN: if there'll be need for executing >1 request at a time, we should avoid - // calling request_by_id - let response = client - .rpc_client - .request_by_id(request_id) - .ok_or(Error::RequestNotFound)? - .await - .map_err(Error::ResponseRetrievalFailed)?; - let encoded_response: Bytes = from_value(response).map_err(|_| Error::ResponseParseFailed)?; - Decode::decode(&mut &encoded_response.0[..]).map_err(|_| Error::ResponseParseFailed) - } - - let result = do_call_rpc(&mut client, method, params).await; - (client, result) -} - -/// Calls RPC on Substrate node that returns u64. -async fn call_rpc_u64(mut client: Client, method: &'static str, params: Params) -> (Client, Result) { - async fn do_call_rpc(client: &mut Client, method: &'static str, params: Params) -> Result { +async fn call_rpc( + mut client: Client, + method: &'static str, + params: Params, + decode_value: impl Fn(Value) -> Result, +) -> (Client, Result) { + async fn do_call_rpc( + client: &mut Client, + method: &'static str, + params: Params, + decode_value: impl Fn(Value) -> Result, + ) -> Result { let request_id = client .rpc_client .start_request(method, params) @@ -273,10 +345,10 @@ async fn call_rpc_u64(mut client: Client, method: &'static str, params: Params) .ok_or(Error::RequestNotFound)? .await .map_err(Error::ResponseRetrievalFailed)?; - response.as_u64().ok_or(Error::ResponseParseFailed) + decode_value(response) } - let result = do_call_rpc(&mut client, method, params).await; + let result = do_call_rpc(&mut client, method, params, decode_value).await; (client, result) } @@ -341,3 +413,20 @@ fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_no bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) } + +/// When RPC method returns encoded value. +fn rpc_returns_encoded_value(value: Value) -> Result { + let encoded_response: Bytes = from_value(value).map_err(|_| Error::ResponseParseFailed)?; + Decode::decode(&mut &encoded_response.0[..]).map_err(|_| Error::ResponseParseFailed) +} + +/// When RPC method returns value. +fn rpc_returns_value(value: Value) -> Result { + from_value(value).map_err(|_| Error::ResponseParseFailed) +} + +/// When RPC method returns raw bytes. +fn rpc_returns_bytes(value: Value) -> Result, Error> { + let encoded_response: Bytes = from_value(value).map_err(|_| Error::ResponseParseFailed)?; + Ok(encoded_response.0) +} diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs new file mode 100644 index 0000000000000..2c194dac0166c --- /dev/null +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -0,0 +1,202 @@ +// Copyright 2019-2020 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 . + +use crate::ethereum_client::{self, EthereumConnectionParams, EthereumSigningParams}; +use crate::ethereum_types::Address; +use crate::substrate_client::{self, SubstrateConnectionParams}; +use crate::substrate_types::{ + Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, +}; +use crate::sync::{HeadersSyncParams, TargetTransactionMode}; +use crate::sync_loop::{SourceClient, TargetClient}; +use crate::sync_types::SourceHeader; +use futures::future::{ready, FutureExt, Ready}; +use std::{future::Future, pin::Pin}; + +/// Interval (in ms) at which we check new Substrate headers when we are synced/almost synced. +const SUBSTRATE_TICK_INTERVAL_MS: u64 = 10_000; +/// Interval (in ms) at which we check new Ethereum blocks. +const ETHEREUM_TICK_INTERVAL_MS: u64 = 5_000; +/// Max Ethereum headers we want to have in all 'before-submitted' states. +const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; +/// Max Ethereum headers count we want to have in 'submitted' state. +const MAX_SUBMITTED_HEADERS: usize = 4; +/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). +const PRUNE_DEPTH: u32 = 256; + +/// Substrate synchronization parameters. +#[derive(Debug)] +pub struct SubstrateSyncParams { + /// Ethereum connection params. + pub eth: EthereumConnectionParams, + /// Ethereum signing params. + pub eth_sign: EthereumSigningParams, + /// Ethereum bridge contract address. + pub eth_contract_address: Address, + /// Substrate connection params. + pub sub: SubstrateConnectionParams, + /// Synchronization parameters. + pub sync_params: HeadersSyncParams, +} + +impl Default for SubstrateSyncParams { + fn default() -> Self { + SubstrateSyncParams { + eth: Default::default(), + eth_sign: Default::default(), + // the address 0x731a10897d267e19b34503ad902d0a29173ba4b1 is the address + // of the contract that is deployed by default signer and 0 nonce + eth_contract_address: "731a10897d267e19b34503ad902d0a29173ba4b1" + .parse() + .expect("address is hardcoded, thus valid; qed"), + sub: Default::default(), + sync_params: HeadersSyncParams { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + // since we always have single Substrate header in separate Ethereum transaction, + // all max_**_in_single_submit aren't important here + max_headers_in_single_submit: 4, + max_headers_size_in_single_submit: std::usize::MAX, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + }, + } + } +} + +/// Substrate client as headers source. +struct SubstrateHeadersSource { + /// Substrate node client. + client: substrate_client::Client, +} + +impl SourceClient for SubstrateHeadersSource { + type Error = substrate_client::Error; + type BestBlockNumberFuture = Pin)>>>; + type HeaderByHashFuture = Pin)>>>; + type HeaderByNumberFuture = Pin)>>>; + type HeaderExtraFuture = Ready<(Self, Result<(SubstrateHeaderId, ()), Self::Error>)>; + + fn best_block_number(self) -> Self::BestBlockNumberFuture { + substrate_client::best_header(self.client) + .map(|(client, result)| (SubstrateHeadersSource { client }, result.map(|header| header.number))) + .boxed() + } + + fn header_by_hash(self, hash: Hash) -> Self::HeaderByHashFuture { + substrate_client::header_by_hash(self.client, hash) + .map(|(client, result)| (SubstrateHeadersSource { client }, result)) + .boxed() + } + + fn header_by_number(self, number: Number) -> Self::HeaderByNumberFuture { + substrate_client::header_by_number(self.client, number) + .map(|(client, result)| (SubstrateHeadersSource { client }, result)) + .boxed() + } + + fn header_extra(self, id: SubstrateHeaderId, _header: &Header) -> Self::HeaderExtraFuture { + ready((self, Ok((id, ())))) + } +} + +/// Ethereum client as Substrate headers target. +struct EthereumHeadersTarget { + /// Ethereum node client. + client: ethereum_client::Client, + /// Bridge contract address. + contract: Address, + /// Ethereum signing params. + sign_params: EthereumSigningParams, +} + +impl TargetClient for EthereumHeadersTarget { + type Error = ethereum_client::Error; + type BestHeaderIdFuture = Pin)>>>; + type IsKnownHeaderFuture = Pin)>>>; + type RequiresExtraFuture = Ready<(Self, Result<(SubstrateHeaderId, bool), Self::Error>)>; + type SubmitHeadersFuture = Pin, Self::Error>)>>>; + + fn best_header_id(self) -> Self::BestHeaderIdFuture { + let (contract, sign_params) = (self.contract, self.sign_params); + ethereum_client::best_substrate_block(self.client, contract) + .map(move |(client, result)| { + ( + EthereumHeadersTarget { + client, + contract, + sign_params, + }, + result, + ) + }) + .boxed() + } + + fn is_known_header(self, id: SubstrateHeaderId) -> Self::IsKnownHeaderFuture { + let (contract, sign_params) = (self.contract, self.sign_params); + ethereum_client::substrate_header_known(self.client, contract, id) + .map(move |(client, result)| { + ( + EthereumHeadersTarget { + client, + contract, + sign_params, + }, + result, + ) + }) + .boxed() + } + + fn requires_extra(self, header: &QueuedSubstrateHeader) -> Self::RequiresExtraFuture { + ready((self, Ok((header.header().id(), false)))) + } + + fn submit_headers(self, headers: Vec) -> Self::SubmitHeadersFuture { + let (contract, sign_params) = (self.contract, self.sign_params); + ethereum_client::submit_substrate_headers(self.client, sign_params.clone(), contract, headers) + .map(move |(client, result)| { + ( + EthereumHeadersTarget { + client, + contract, + sign_params, + }, + result, + ) + }) + .boxed() + } +} + +/// Run Substrate headers synchronization. +pub fn run(params: SubstrateSyncParams) { + let eth_client = ethereum_client::client(params.eth); + let sub_client = substrate_client::client(params.sub); + + crate::sync_loop::run( + SubstrateHeadersSource { client: sub_client }, + SUBSTRATE_TICK_INTERVAL_MS, + EthereumHeadersTarget { + client: eth_client, + contract: params.eth_contract_address, + sign_params: params.eth_sign, + }, + ETHEREUM_TICK_INTERVAL_MS, + params.sync_params, + ); +} diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index f056b7101149f..d657f0269d838 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -14,16 +14,61 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -pub use crate::ethereum_types::H256 as TransactionHash; use crate::ethereum_types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, RECEIPT_GAS_USED_PROOF as ETHEREUM_RECEIPT_GAS_USED_PROOF, }; +use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use codec::Encode; pub use sp_bridge_eth_poa::{ Address, Bloom, Bytes, Header as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, }; +/// Substrate header hash. +pub type Hash = bridge_node_runtime::Hash; + +/// Substrate header number. +pub type Number = bridge_node_runtime::BlockNumber; + +/// Substrate header type. +pub type Header = bridge_node_runtime::Header; + +/// Substrate header ID. +pub type SubstrateHeaderId = HeaderId; + +/// Queued substrate header ID. +pub type QueuedSubstrateHeader = QueuedHeader; + +/// Substrate synchronization pipeline. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(test, derive(PartialEq))] +pub struct SubstrateHeadersSyncPipeline; + +impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { + const SOURCE_NAME: &'static str = "Substrate"; + const TARGET_NAME: &'static str = "Ethereum"; + + type Hash = bridge_node_runtime::Hash; + type Number = bridge_node_runtime::BlockNumber; + type Header = Header; + type Extra = (); + + fn estimate_size(source: &QueuedHeader) -> usize { + source.header().encode().len() + } +} + +impl SourceHeader for Header { + fn id(&self) -> SubstrateHeaderId { + HeaderId(self.number, self.hash()) + } + + fn parent_id(&self) -> SubstrateHeaderId { + HeaderId(self.number - 1, self.parent_hash) + } +} + /// Convert Ethereum header into Ethereum header for Substrate. pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEthereumHeader { SubstrateEthereumHeader { diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 768a7a7932bcd..e1fc372e148eb 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -204,19 +204,6 @@ impl HeadersSync

{ } } -impl Default for HeadersSyncParams { - fn default() -> Self { - HeadersSyncParams { - max_future_headers_to_download: 128, - max_headers_in_submitted_status: 128, - max_headers_in_single_submit: 32, - max_headers_size_in_single_submit: 131_072, - prune_depth: 4096, - target_tx_mode: TargetTransactionMode::Signed, - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -228,9 +215,20 @@ mod tests { H256::from_low_u64_le(1000 + number) } + fn default_sync_params() -> HeadersSyncParams { + HeadersSyncParams { + max_future_headers_to_download: 128, + max_headers_in_submitted_status: 128, + max_headers_in_single_submit: 32, + max_headers_size_in_single_submit: 131_072, + prune_depth: 4096, + target_tx_mode: TargetTransactionMode::Signed, + } + } + #[test] fn select_new_header_to_download_works() { - let mut eth_sync = HeadersSync::::new(Default::default()); + let mut eth_sync = HeadersSync::::new(default_sync_params()); // both best && target headers are unknown assert_eq!(eth_sync.select_new_header_to_download(), None); @@ -261,7 +259,7 @@ mod tests { #[test] fn sync_without_reorgs_works() { - let mut eth_sync = HeadersSync::new(Default::default()); + let mut eth_sync = HeadersSync::new(default_sync_params()); eth_sync.params.max_headers_in_submitted_status = 1; // ethereum reports best header #102 @@ -310,7 +308,7 @@ mod tests { #[test] fn sync_with_orphan_headers_work() { - let mut eth_sync = HeadersSync::new(Default::default()); + let mut eth_sync = HeadersSync::new(default_sync_params()); // ethereum reports best header #102 eth_sync.source_best_header_number_response(102); @@ -359,7 +357,7 @@ mod tests { #[test] fn pruning_happens_on_target_best_header_response() { - let mut eth_sync = HeadersSync::::new(Default::default()); + let mut eth_sync = HeadersSync::::new(default_sync_params()); eth_sync.params.prune_depth = 50; eth_sync.target_best_header_response(id(100)); assert_eq!(eth_sync.headers.prune_border(), 50); @@ -367,7 +365,7 @@ mod tests { #[test] fn only_submitting_headers_in_backup_mode_when_stalled() { - let mut eth_sync = HeadersSync::new(Default::default()); + let mut eth_sync = HeadersSync::new(default_sync_params()); eth_sync.params.target_tx_mode = TargetTransactionMode::Backup; // ethereum reports best header #102 diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 803cfaf0c2350..b2e97c979408a 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -17,7 +17,7 @@ use crate::sync::HeadersSyncParams; use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader}; use futures::{future::FutureExt, stream::StreamExt}; -use num_traits::Saturating; +use num_traits::{Saturating, Zero}; use std::future::Future; /// When we submit headers to target node, but see no updates of best @@ -365,6 +365,17 @@ pub fn run( // for Orphan we actually ask for parent' header let parent_id = header.parent_id(); + // if we have end up with orphan header#0, then we are misconfigured + if parent_id.0.is_zero() { + log::error!( + target: "bridge", + "Misconfiguration. Genesis {} header is considered orphan by {} node", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + return; + } + log::debug!( target: "bridge", "Going to download orphan header from {} node: {:?}", diff --git a/relays/ethereum/src/utils.rs b/relays/ethereum/src/utils.rs new file mode 100644 index 0000000000000..4f022c80477db --- /dev/null +++ b/relays/ethereum/src/utils.rs @@ -0,0 +1,37 @@ +// Copyright 2019-2020 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 . + +/// Macro that returns (client, Err(error)) tuple from function if result is Err(error). +#[macro_export] +macro_rules! bail_on_error { + ($result: expr) => { + match $result { + (client, Ok(result)) => (client, result), + (client, Err(error)) => return (client, Err(error)), + } + }; +} + +/// Macro that returns (client, Err(error)) tuple from function if result is Err(error). +#[macro_export] +macro_rules! bail_on_arg_error { + ($result: expr, $client: ident) => { + match $result { + Ok(result) => result, + Err(error) => return ($client, Err(error)), + } + }; +} From 19ab491018d7b0737d3c069f586775aa17aad6a7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 4 May 2020 01:56:28 +0000 Subject: [PATCH 0040/1210] Bump ethabi-derive from 11.0.0 to 12.0.0 (#81) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d7e337dada792..8b7ec37068cc7 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -13,7 +13,7 @@ codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" -ethabi-derive = "11.0" +ethabi-derive = "12.0" ethereum-tx-sign = { git = "https://github.com/svyatonik/ethereum-tx-sign.git", branch = "up-ethereum-types" } futures = "0.3.1" hex = "0.4" From 5aa441f943d80fd0f67ed82712598f01fa94cc08 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 4 May 2020 02:57:03 +0000 Subject: [PATCH 0041/1210] Bump finality-grandpa from 0.11.2 to 0.12.1 (#82) --- modules/ethereum-contract/builtin/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index be2b1c7f68363..5ae6a5a1a277e 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" # General dependencies codec = { package = "parity-scale-codec", version = "1.0.0" } -finality-grandpa = { version = "0.11.2", features = ["derive-codec"] } +finality-grandpa = { version = "0.12.1", features = ["derive-codec"] } sp-blockchain = "2.0.0-alpha.5" sp-finality-grandpa = "2.0.0-alpha.5" sp-runtime = "2.0.0-alpha.5" From 80ce84c94560f12e6ce7d6819f4d29903e43d4b9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 May 2020 02:50:51 +0000 Subject: [PATCH 0042/1210] Bump finality-grandpa from 0.12.1 to 0.12.2 (#86) --- modules/ethereum-contract/builtin/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 5ae6a5a1a277e..83fa872865c3e 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" # General dependencies codec = { package = "parity-scale-codec", version = "1.0.0" } -finality-grandpa = { version = "0.12.1", features = ["derive-codec"] } +finality-grandpa = { version = "0.12.2", features = ["derive-codec"] } sp-blockchain = "2.0.0-alpha.5" sp-finality-grandpa = "2.0.0-alpha.5" sp-runtime = "2.0.0-alpha.5" From 8eec0041f98b0c423017738cdf8446fcb6a85203 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 May 2020 03:21:51 +0000 Subject: [PATCH 0043/1210] Bump serde_json from 1.0.52 to 1.0.53 (#87) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8b7ec37068cc7..f1b578131b542 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -25,7 +25,7 @@ parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" serde = { version = "1.0.106", features = ["derive"] } -serde_json = "1.0.51" +serde_json = "1.0.53" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "add-receipt-root" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 6521ec35f61a3..a538e9e46cb81 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -13,7 +13,7 @@ env_logger = "0.7.1" futures = "0.3.1" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" -serde_json = "1.0.51" +serde_json = "1.0.53" url = "2.1.0" [dependencies.sp-core] From b85ce0956e935aec4a7e2cac7c092fcc488bea0d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 May 2020 03:50:29 +0000 Subject: [PATCH 0044/1210] Bump linked-hash-map from 0.5.2 to 0.5.3 (#88) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index f1b578131b542..9c727db5679b1 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -18,7 +18,7 @@ ethereum-tx-sign = { git = "https://github.com/svyatonik/ethereum-tx-sign.git", futures = "0.3.1" hex = "0.4" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } -linked-hash-map = "0.5.2" +linked-hash-map = "0.5.3" log = "0.4.8" num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } From 4a0a835c58e8ffe8d9b39d3bb6e5897b35ae2003 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 May 2020 06:25:34 +0000 Subject: [PATCH 0045/1210] Bump serde from 1.0.106 to 1.0.110 (#90) --- bin/node/runtime/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index f39b55625afbb..65b0484007b65 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -13,7 +13,7 @@ default-features = false features = ["derive"] [dependencies.serde] -version = "1.0.106" +version = "1.0.110" optional = true features = ["derive"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 9c727db5679b1..52a919339dcf7 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -24,7 +24,7 @@ num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" -serde = { version = "1.0.106", features = ["derive"] } +serde = { version = "1.0.110", features = ["derive"] } serde_json = "1.0.53" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" From 584c9523714c01ee58f6abd0d2cc03584f469058 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 May 2020 07:23:30 +0000 Subject: [PATCH 0046/1210] Bump futures from 0.3.4 to 0.3.5 (#89) --- bin/node/node/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 6dfaa6b58e80c..78bd8b6107617 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" name = "bridge-node" [dependencies] -futures = "0.3.1" +futures = "0.3.5" jsonrpc-core = "14.1.0" log = "0.4.8" structopt = "0.3.14" diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 52a919339dcf7..de113a0f9e0b9 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" ethereum-tx-sign = { git = "https://github.com/svyatonik/ethereum-tx-sign.git", branch = "up-ethereum-types" } -futures = "0.3.1" +futures = "0.3.5" hex = "0.4" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } linked-hash-map = "0.5.3" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index a538e9e46cb81..e768660441759 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -10,7 +10,7 @@ clap = "2.3.3" ctrlc = "3.1.4" derive_more = "0.99.5" env_logger = "0.7.1" -futures = "0.3.1" +futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" serde_json = "1.0.53" From a3433aae85bdf3a5df6c3b248277784560efe2ac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 13 May 2020 00:09:26 +0300 Subject: [PATCH 0047/1210] Process finality proofs in solidity PoA -> Substrate contract (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * solidity contract * continue * upd * cargo update * fixes * ehtereum_headers -> headers * extracted some common stuff * ethereum_sync.rs -> sync.rs * make sync generic * continue extracting * continue * add eth-contract argument * continue * some fixes * contract v2 * continue * more fixes * more fixes * deal with duplicated params * removed multiple call_rpc variants * bail_on_error!() * fn submit_ethereum_transaction * more fixes * cargo fmt --all * fix * bail_on_arg_error!() * fix * fix * remove async_extra stuff * start work on finality builtin remove async_extra stuff continue continue local testnet (Alice + Bob) for node * added TODO * substrate-bridge.json -> substrate-bridge-abi.json * get rid of substrate transactions hashes * get rid of ethereum transactions hashes * extracted contract bytecode to separate file * cargo fmt --all * avoid duplicate import in contracts * removed Default::default() * swapped configurations for sub2eth && eth2sub * fix compilation * do not double gas limit when submitting Substrate headers * fix finality storage * at least 1 validator required * shift_session_manager_works * cargo fmt --all * solidity contract removed * consts * extracted solc compilation details to separate file * removed (obsolete in future Vec justification) * fixed cli option description * fix typos * fix grumble * extracted constants * log decoded header * new substrate version + actually verify justification * intermediate cargo fmt --all * comments * disable completion data resubmission * increased timeouts + _MS -> Duration * forget completion data after submission * builtin tests * headers tests * cargo fmt --all * update contract * Update relays/ethereum/src/ethereum_sync_loop.rs Co-authored-by: Tomasz Drwięga * Update relays/ethereum/src/ethereum_sync_loop.rs Co-authored-by: Tomasz Drwięga * added docs * OwnedFutureOutput * more docs fixes * cargo fmt --all * encode headers * consts + docs * aliases again * cargo fmt --all * Update relays/ethereum/src/ethereum_sync_loop.rs Co-authored-by: Tomasz Drwięga * Update relays/ethereum/src/ethereum_sync_loop.rs Co-authored-by: Tomasz Drwięga * Use Duration::from_secs() instead of from_millis() * grumbles * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * incomplete_headers_are_still_incomplete_after_advance * add hex-encoded headers to substrate_header_without_signal_parsed * cargo fmt --all * Update relays/ethereum/src/sync_loop.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/headers.rs Co-authored-by: Hernando Castano * added comments on Extra and Completion Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- modules/ethereum-contract/builtin/Cargo.toml | 33 +- modules/ethereum-contract/builtin/src/lib.rs | 271 +++++++- relays/ethereum/res/substrate-bridge-abi.json | 19 +- .../res/substrate-bridge-bytecode.hex | 2 +- .../res/substrate-bridge-metadata.txt | 6 +- relays/ethereum/src/ethereum_client.rs | 61 +- relays/ethereum/src/ethereum_sync_loop.rs | 56 +- relays/ethereum/src/ethereum_types.rs | 1 + relays/ethereum/src/headers.rs | 633 +++++++++++++++--- relays/ethereum/src/substrate_client.rs | 16 +- relays/ethereum/src/substrate_sync_loop.rs | 82 ++- relays/ethereum/src/substrate_types.rs | 7 + relays/ethereum/src/sync_loop.rs | 194 ++++-- relays/ethereum/src/sync_types.rs | 25 +- 14 files changed, 1191 insertions(+), 215 deletions(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 83fa872865c3e..7a38e4497f1d3 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -10,11 +10,36 @@ edition = "2018" # General dependencies codec = { package = "parity-scale-codec", version = "1.0.0" } -finality-grandpa = { version = "0.12.2", features = ["derive-codec"] } -sp-blockchain = "2.0.0-alpha.5" -sp-finality-grandpa = "2.0.0-alpha.5" -sp-runtime = "2.0.0-alpha.5" +ethereum-types = "0.9.1" # Runtime/chain specific dependencies bridge-node-runtime = { path = "../../../bin/node/runtime" } + +[dependencies.sp-blockchain] +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-finality-grandpa] +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sc-finality-grandpa] +version = "0.8.0-dev" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies] +hex = "0.4" + +[dev-dependencies.sp-core] +version = "2.0.0-alpha.6" +rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs index 3249307ac9aa3..739e14d69efc6 100644 --- a/modules/ethereum-contract/builtin/src/lib.rs +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -14,17 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bridge_node_runtime::{BlockNumber, Hash, Header as RuntimeHeader}; -use codec::Decode; +use bridge_node_runtime::{Block, BlockNumber, Hash, Header as RuntimeHeader}; +use codec::{Decode, Encode}; +use ethereum_types::U256; use sp_blockchain::Error as ClientError; +use sp_finality_grandpa::{AuthorityList, ConsensusLog, GRANDPA_ENGINE_ID}; /// Builtin errors. #[derive(Debug)] pub enum Error { + /// Failed to decode block number. + BlockNumberDecode, /// Failed to decode Substrate header. HeaderDecode(codec::Error), /// Failed to decode best voters set. - BestVotersDecode(codec::Error), + BestSetDecode(codec::Error), /// Failed to decode finality proof. FinalityProofDecode(codec::Error), /// Failed to verify justification. @@ -32,7 +36,7 @@ pub enum Error { } /// Substrate header. -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct Header { /// Header hash. pub hash: Hash, @@ -45,7 +49,7 @@ pub struct Header { } /// GRANDPA validators set change signal. -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct ValidatorsSetSignal { /// Signal delay. pub delay: BlockNumber, @@ -53,6 +57,20 @@ pub struct ValidatorsSetSignal { pub validators: Vec, } +/// Convert from U256 to BlockNumber. Fails if `U256` value isn't fitting within `BlockNumber` +/// limits (the runtime referenced by this module uses u32 as `BlockNumber`). +pub fn to_substrate_block_number(number: U256) -> Result { + match number == number.low_u32().into() { + true => Ok(number.low_u32()), + false => Err(Error::BlockNumberDecode), + } +} + +/// Convert from BlockNumber to U256. +pub fn from_substrate_block_number(number: BlockNumber) -> Result { + Ok(U256::from(number as u64)) +} + /// Parse Substrate header. pub fn parse_substrate_header(raw_header: &[u8]) -> Result { RuntimeHeader::decode(&mut &raw_header[..]) @@ -60,20 +78,243 @@ pub fn parse_substrate_header(raw_header: &[u8]) -> Result { hash: header.hash(), parent_hash: header.parent_hash, number: header.number, - signal: None, // TODO: parse me + signal: sp_runtime::traits::Header::digest(&header) + .log(|log| { + log.as_consensus().and_then(|(engine_id, log)| { + if engine_id == GRANDPA_ENGINE_ID { + Some(log) + } else { + None + } + }) + }) + .and_then(|log| ConsensusLog::decode(&mut &log[..]).ok()) + .and_then(|log| match log { + ConsensusLog::ScheduledChange(scheduled_change) => Some(ValidatorsSetSignal { + delay: scheduled_change.delay, + validators: scheduled_change.next_authorities.encode(), + }), + _ => None, + }), }) .map_err(Error::HeaderDecode) } /// Verify GRANDPA finality proof. pub fn verify_substrate_finality_proof( - _best_set_id: u64, - _raw_best_voters: &[u8], - _raw_best_header: &[u8], - _raw_headers: &[&[u8]], - _raw_finality_proof: &[u8], -) -> Result<(usize, usize), Error> { - Err(Error::JustificationVerify(ClientError::Msg( - "Not yet implemented".into(), - ))) // TODO: implement me + finality_target_number: BlockNumber, + finality_target_hash: Hash, + best_set_id: u64, + raw_best_set: &[u8], + raw_finality_proof: &[u8], +) -> Result<(), Error> { + let best_set = AuthorityList::decode(&mut &raw_best_set[..]).map_err(Error::BestSetDecode)?; + sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( + &raw_finality_proof, + (finality_target_hash, finality_target_number), + best_set_id, + &best_set.into_iter().collect(), + ) + .map_err(Error::JustificationVerify) + .map(|_| ()) +} + +#[cfg(test)] +mod tests { + use super::*; + use bridge_node_runtime::DigestItem; + use sp_core::crypto::Public; + use sp_finality_grandpa::{AuthorityId, ScheduledChange}; + use sp_runtime::generic::Digest; + + #[test] + fn to_substrate_block_number_succeeds() { + assert_eq!(to_substrate_block_number(U256::zero()).unwrap(), 0); + assert_eq!( + to_substrate_block_number(U256::from(std::u32::MAX as u64)).unwrap(), + 0xFFFFFFFF + ); + } + + #[test] + fn to_substrate_block_number_fails() { + assert!(matches!( + to_substrate_block_number(U256::from(std::u32::MAX as u64 + 1)), + Err(Error::BlockNumberDecode) + )); + } + + #[test] + fn from_substrate_block_number_succeeds() { + assert_eq!(from_substrate_block_number(0).unwrap(), U256::zero()); + assert_eq!( + from_substrate_block_number(std::u32::MAX).unwrap(), + U256::from(std::u32::MAX) + ); + } + + #[test] + fn substrate_header_without_signal_parsed() { + let raw_header = RuntimeHeader { + parent_hash: [0u8; 32].into(), + number: 0, + state_root: "b2fc47904df5e355c6ab476d89fbc0733aeddbe302f0b94ba4eea9283f7e89e7" + .parse() + .unwrap(), + extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314" + .parse() + .unwrap(), + digest: Default::default(), + } + .encode(); + assert_eq!( + raw_header, + hex::decode("000000000000000000000000000000000000000000000000000000000000000000b2fc47904df5e355c6ab476d89fbc0733aeddbe302f0b94ba4eea9283f7e89e703170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131400").unwrap(), + ); + + assert_eq!( + parse_substrate_header(&raw_header).unwrap(), + Header { + hash: "afbbeb92bf6ff14f60bdef0aa89f043dd403659ae82665238810ace0d761f6d0" + .parse() + .unwrap(), + parent_hash: Default::default(), + number: 0, + signal: None, + }, + ); + } + + #[test] + fn substrate_header_with_signal_parsed() { + let authorities = vec![ + (AuthorityId::from_slice(&[1; 32]), 101), + (AuthorityId::from_slice(&[3; 32]), 103), + ]; + let mut digest = Digest::default(); + digest.push(DigestItem::Consensus( + GRANDPA_ENGINE_ID, + ConsensusLog::ScheduledChange(ScheduledChange { + next_authorities: authorities.clone(), + delay: 8, + }) + .encode(), + )); + + let raw_header = RuntimeHeader { + parent_hash: "c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b" + .parse() + .unwrap(), + number: 8, + state_root: "822d6b412033aa9ac8e1722918eec5f25633529225754b3d4149982f5cacd4aa" + .parse() + .unwrap(), + extrinsics_root: "e7b07c0ce2799416ce7877b9cefc7f596bea5e8813bb2a0abf760414073ca928" + .parse() + .unwrap(), + digest, + } + .encode(); + assert_eq!( + raw_header, + hex::decode("c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b20822d6b412033aa9ac8e1722918eec5f25633529225754b3d4149982f5cacd4aae7b07c0ce2799416ce7877b9cefc7f596bea5e8813bb2a0abf760414073ca928040446524e4b59010108010101010101010101010101010101010101010101010101010101010101010165000000000000000303030303030303030303030303030303030303030303030303030303030303670000000000000008000000").unwrap(), + ); + + assert_eq!( + parse_substrate_header(&raw_header).unwrap(), + Header { + hash: "3dfebb280bd87a4640f89d7f2adecd62b88148747bff5b63af6e1634ee37a56e" + .parse() + .unwrap(), + parent_hash: "c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b" + .parse() + .unwrap(), + number: 8, + signal: Some(ValidatorsSetSignal { + delay: 8, + validators: authorities.encode(), + }), + }, + ); + } + + /// Number of the example block with justification. + const EXAMPLE_JUSTIFIED_BLOCK_NUMBER: u32 = 8; + /// Hash of the example block with justification. + const EXAMPLE_JUSTIFIED_BLOCK_HASH: &'static str = + "a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775"; + /// Id of authorities set that have generated example justification. Could be computed by tracking + /// every set change in canonized headers. + const EXAMPLE_AUTHORITIES_SET_ID: u64 = 0; + /// Encoded authorities set that has generated example justification. Could be fetched from `ScheduledChange` + /// digest of the block that has scheduled this set OR by calling `GrandpaApi::grandpa_authorities()` at + /// appropriate block. + const EXAMPLE_AUTHORITIES_SET: &'static str = "1488dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f01000000000000005e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d901000000000000001dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b50100000000000000"; + /// Example justification. Could be fetched by calling 'chain_getBlock' RPC. + const EXAMPLE_JUSTIFICATION: &'static str = "2600000000000000a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000010a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000d66b4ceb57ef8bcbc955071b597c8c5d2adcfdbb009c73f8438d342670fdeca9ac60686cbd58105b10f51d0a64a8e73b2e5829b2eab3248a008c472852130b00439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234fa2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000f5730c14d3cd22b7661e2f5fcb3139dd5fef37f946314a441d01b40ce1200ef70d810525f23fd278b588cd67473c200bda83c338c407b479386aa83798e5970b5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000c78d6ec463f476461a695b4791d30e7626d16fdf72d7c252c2cad387495a97e8c2827ed4d5af853d6e05d31cb6fb7438c9481a7e9c6990d60a9bfaf6a6e1930988dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eea2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000052b4fc52d430286b3e2d650aa6e01b6ff4fae8b968893a62be789209eb97ee6e23780d3f5af7042d85bb48f1b202890b22724dfebce138826f66a5e00324320fd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae6900"; + + #[test] + fn substrate_header_parse_fails() { + assert!(matches!(parse_substrate_header(&[]), Err(_))); + } + + #[test] + fn verify_substrate_finality_proof_succeeds() { + verify_substrate_finality_proof( + EXAMPLE_JUSTIFIED_BLOCK_NUMBER, + EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), + EXAMPLE_AUTHORITIES_SET_ID, + &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), + &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), + ) + .unwrap(); + } + + #[test] + fn verify_substrate_finality_proof_fails_when_wrong_block_is_finalized() { + verify_substrate_finality_proof( + 4, + Default::default(), + EXAMPLE_AUTHORITIES_SET_ID, + &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), + &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), + ) + .unwrap_err(); + } + + #[test] + fn verify_substrate_finality_proof_fails_when_wrong_set_is_provided() { + verify_substrate_finality_proof( + EXAMPLE_JUSTIFIED_BLOCK_NUMBER, + EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), + EXAMPLE_AUTHORITIES_SET_ID, + &hex::decode("deadbeef").unwrap(), + &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), + ) + .unwrap_err(); + } + + #[test] + fn verify_substrate_finality_proof_fails_when_wrong_set_id_is_provided() { + verify_substrate_finality_proof( + EXAMPLE_JUSTIFIED_BLOCK_NUMBER, + EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), + 42, + &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), + &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), + ) + .unwrap_err(); + } + + #[test] + fn verify_substrate_finality_proof_fails_when_wrong_proof_is_provided() { + verify_substrate_finality_proof( + EXAMPLE_JUSTIFIED_BLOCK_NUMBER, + EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), + 0, + &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), + &hex::decode("deadbeef").unwrap(), + ) + .unwrap_err(); + } } diff --git a/relays/ethereum/res/substrate-bridge-abi.json b/relays/ethereum/res/substrate-bridge-abi.json index 4ff57ab656221..bd65f6b7921f1 100644 --- a/relays/ethereum/res/substrate-bridge-abi.json +++ b/relays/ethereum/res/substrate-bridge-abi.json @@ -79,19 +79,18 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "bytes32", - "name": "headerHash", - "type": "bytes32" - } - ], - "name": "isFinalityProofRequired", + "inputs": [], + "name": "incompleteHeaders", "outputs": [ { - "internalType": "bool", + "internalType": "uint256[]", "name": "", - "type": "bool" + "type": "uint256[]" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" } ], "stateMutability": "view", diff --git a/relays/ethereum/res/substrate-bridge-bytecode.hex b/relays/ethereum/res/substrate-bridge-bytecode.hex index 54c252b65d685..6b3b74df48b0d 100644 --- a/relays/ethereum/res/substrate-bridge-bytecode.hex +++ b/relays/ethereum/res/substrate-bridge-bytecode.hex @@ -1 +1 @@ -60806040523480156200001157600080fd5b5060405162000e6738038062000e67833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d4565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260058352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f92600385019291019062000409565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d19190602085019062000409565b5050505050620004ae565b620002e6620003d4565b600080600080600060608751602089016040516020810160208101602081016020810160a08588886010600019fa6200031e57600080fd5b93519251915190519351929b50909950975090955093505082159050620003a757816001600160401b03811180156200035657600080fd5b506040519080825280601f01601f19166020018201604052801562000382576020820181803683370190505b50905087516020890160208301848184846011600019fa620003a357600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044c57805160ff19168380011785556200047c565b828001600101855582156200047c579182015b828111156200047c5782518255916020019190600101906200045f565b506200048a9291506200048e565b5090565b620004ab91905b808211156200048a576000815560010162000495565b90565b6109a980620004be6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063871ebe181461005c578063a98bfaad1461008d578063d96a2deb146100aa578063e7af0779146100cb578063fae71ae814610173575b600080fd5b6100796004803603602081101561007257600080fd5b5035610225565b604080519115158252519081900360200190f35b610079600480360360208110156100a357600080fd5b503561023a565b6100b2610297565b6040805192835260208301919091528051918290030190f35b610171600480360360208110156100e157600080fd5b8101906020810181356401000000008111156100fc57600080fd5b82018360208201111561010e57600080fd5b8035906020019184600183028401116401000000008311171561013057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506102af945050505050565b005b6101716004803603606081101561018957600080fd5b8135916020810135918101906060810160408201356401000000008111156101b057600080fd5b8201836020820111156101c257600080fd5b803590602001918460018302840111640100000000831117156101e457600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061058e945050505050565b60009081526005602052604090205460ff1690565b6000818152600560205260408120805460ff16801561025e57506001548160020154115b8015610271575080600601548160020154145b80156102905750600354600482015467ffffffffffffffff9081169116145b9392505050565b60008054808252600560205260409091206002015491565b6102b76107a8565b6102c0826106ac565b805160009081526005602052604090205490915060ff1615610329576040805162461bcd60e51b815260206004820152601760248201527f48656164657220697320616c7265616479206b6e6f776e000000000000000000604482015290519081900360640190fd5b6020808201516000908152600590915260409020805460ff168015610358575060018260400151038160020154145b6103935760405162461bcd60e51b81526004018080602001828103825260268152602001806108ee6026913960400191505060405180910390fd5b6006810154158015906103ad575080600201548160060154145b156103f6578160200151600254146103f65760405162461bcd60e51b81526004018080602001828103825260318152602001806109436031913960400191505060405180910390fd5b60068101546080830151511561046b578260400151811061045e576040805162461bcd60e51b815260206004820152601960248201527f4f7665726c617070696e67207369676e616c7320666f756e6400000000000000604482015290519081900360640190fd5b5060608201516040830151015b60048201546005830154600384015467ffffffffffffffff9092169160026000196001831615610100020190911604156104ac575060208401516001909101905b6040805160e0810182526001808252602088810151818401908152898501518486019081526080808c01516060870190815267ffffffffffffffff8a169187019190915260a0860188905260c086018a90528b51600090815260058552969096208551815460ff191690151517815591519382019390935591516002830155925180519293919261054392600385019201906107dd565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c09091015160069091015550509151600055505050565b60008281526005602052604090206002015483146105dd5760405162461bcd60e51b815260040180806020018281038252602f815260200180610914602f913960400191505060405180910390fd5b60025460006105ed85858561079e565b600081815260056020526040902060028281558101546001559091505b8282146106a457506000908152600560205260409020600181015460068201546002830154919291141561069f576005818101546000908152602091909152604090206003805467ffffffffffffffff198116600167ffffffffffffffff9283168101909216178255908201805461069892600492916002610100928216159290920260001901160461085b565b50506106a4565b61060a565b505050505050565b6106b46107a8565b600080600080600060608751602089016040516020810160208101602081016020810160a08588886010600019fa6106eb57600080fd5b93519251915190519351929b50909950975090955093505082159050610771578167ffffffffffffffff8111801561072257600080fd5b506040519080825280601f01601f19166020018201604052801561074d576020820181803683370190505b50905087516020890160208301848184846011600019fa61076d57600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6002549392505050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061081e57805160ff191683800117855561084b565b8280016001018555821561084b579182015b8281111561084b578251825591602001919060010190610830565b506108579291506108d0565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610894578054855561084b565b8280016001018555821561084b57600052602060002091601f016020900482015b8281111561084b5782548255916001019190600101906108b5565b6108ea91905b8082111561085757600081556001016108d6565b9056fe4d697373696e6720706172656e74206865616465722066726f6d207468652073746f726167654d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f726167654d697373696e672072657175697265642066696e616c6974792070726f6f6620666f7220706172656e7420686561646572a26469706673582212206cc35a10288e85e37e14250b2d4af37dc4fbcd59635965d9ac0421cb8db1f66c64736f6c63430006060033 \ No newline at end of file +60806040523480156200001157600080fd5b506040516200131938038062001319833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d5565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260078352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f9260038501929101906200040a565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d1919060208501906200040a565b5050505050620004af565b620002e6620003d5565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa6200031c57600080fd5b84519b5083519a50825199508151985080519750505050505050506060816001600160401b03811180156200035057600080fd5b506040519080825280601f01601f1916602001820160405280156200037c576020820181803683370190505b5090508115620003a85787516020890160208301848184846011600019fa620003a457600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044d57805160ff19168380011785556200047d565b828001600101855582156200047d579182015b828111156200047d57825182559160200191906001019062000460565b506200048b9291506200048f565b5090565b620004ac91905b808211156200048b576000815560010162000496565b90565b610e5a80620004bf6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063374c2c261461005c578063871ebe18146100fd578063d96a2deb1461012e578063e7af07791461014f578063fae71ae8146101f7575b600080fd5b6100646102a9565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100a8578181015183820152602001610090565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100e75781810151838201526020016100cf565b5050505090500194505050505060405180910390f35b61011a6004803603602081101561011357600080fd5b50356103ae565b604080519115158252519081900360200190f35b6101366103c3565b6040805192835260208301919091528051918290030190f35b6101f56004803603602081101561016557600080fd5b81019060208101813564010000000081111561018057600080fd5b82018360208201111561019257600080fd5b803590602001918460018302840111640100000000831117156101b457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506103db945050505050565b005b6101f56004803603606081101561020d57600080fd5b81359160208101359181019060608101604082013564010000000081111561023457600080fd5b82018360208201111561024657600080fd5b8035906020019184600183028401116401000000008311171561026857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610779945050505050565b6005546060908190818167ffffffffffffffff811180156102c957600080fd5b506040519080825280602002602001820160405280156102f3578160200160208202803683370190505b50905060005b8281101561034e57600760006005838154811061031257fe5b906000526020600020015481526020019081526020016000206002015482828151811061033b57fe5b60209081029190910101526001016102f9565b508060058080548060200260200160405190810160405280929190818152602001828054801561039d57602002820191906000526020600020905b815481526020019060010190808311610389575b505050505090509350935050509091565b60009081526007602052604090205460ff1690565b60008054808252600760205260409091206002015491565b6103e3610c13565b6103ec826109de565b805160009081526007602052604090205490915060ff1615610455576040805162461bcd60e51b815260206004820152601760248201527f48656164657220697320616c7265616479206b6e6f776e000000000000000000604482015290519081900360640190fd5b6001548160400151116104995760405162461bcd60e51b8152600401808060200182810382526025815260200180610d596025913960400191505060405180910390fd5b6020808201516000908152600790915260409020805460ff1680156104c8575060018260400151038160020154145b6105035760405162461bcd60e51b8152600401808060200182810382526026815260200180610d7e6026913960400191505060405180910390fd5b60068101541580159061051d575080600201548160060154145b15610566578160200151600254146105665760405162461bcd60e51b8152600401808060200182810382526031815260200180610df46031913960400191505060405180910390fd5b60048101546005820154600683015460808501515167ffffffffffffffff90931692156106445767ffffffffffffffff83811614156105d65760405162461bcd60e51b8152600401808060200182810382526021815260200180610da46021913960400191505060405180910390fd5b8460400151811061062e576040805162461bcd60e51b815260206004820152601960248201527f4f7665726c617070696e67207369676e616c7320666f756e6400000000000000604482015290519081900360640190fd5b5050825160608401516040850151600190930192015b8460400151811415610697576005805486516001820180845560009384527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0909201558651825260066020526040909120555b6040805160e0810182526001808252602088810151818401908152898501518486019081526080808c01516060870190815267ffffffffffffffff8b169187019190915260a0860189905260c086018890528b51600090815260078552969096208551815460ff191690151517815591519382019390935591516002830155925180519293919261072e9260038501920190610c48565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c09091015160069091015550509151600055505050565b60008281526007602052604090206002015483146107c85760405162461bcd60e51b815260040180806020018281038252602f815260200180610dc5602f913960400191505060405180910390fd5b60028054600354600480546040805160206101006001851615026000190190931696909604601f81018390048302870183019091528086529394600094610879948a948a9467ffffffffffffffff9092169392909183018282801561086e5780601f106108435761010080835404028352916020019161086e565b820191906000526020600020905b81548152906001019060200180831161085157829003601f168201915b505050505087610ad1565b600081815260076020526040902060028281558101546001559091505b8282146109d657506000818152600760209081526040808320600181015460069093529220549092908015610958576005546000199182019181018214610924576000600560018303815481106108e957fe5b90600052602060002001549050806005848154811061090457fe5b600091825260208083209091019290925591825260069052604090208290555b600580548061092f57fe5b600082815260208082208301600019908101839055909201909255848252600690526040812055505b8260060154836002015414156109cf57600583015460009081526007602052604090206003805467ffffffffffffffff198116600167ffffffffffffffff928316810190921617825590820180546109c6926004929160026101009282161592909202600019011604610cc6565b505050506109d6565b5050610896565b505050505050565b6109e6610c13565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa610a1b57600080fd5b84519b5083519a508251995081519850805197505050505050505060608167ffffffffffffffff81118015610a4f57600080fd5b506040519080825280601f01601f191660200182016040528015610a7a576020820181803683370190505b5090508115610aa45787516020890160208301848184846011600019fa610aa057600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b600060608686868686604051602001808681526020018581526020018467ffffffffffffffff1667ffffffffffffffff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610b44578181015183820152602001610b2c565b50505050905090810190601f168015610b715780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610ba4578181015183820152602001610b8c565b50505050905090810190601f168015610bd15780820380516001836020036101000a031916815260200191505b50975050505050505050604051602081830303815290604052905080516020820160008083836012600019fa610c0657600080fd5b5095979650505050505050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c8957805160ff1916838001178555610cb6565b82800160010185558215610cb6579182015b82811115610cb6578251825591602001919060010190610c9b565b50610cc2929150610d3b565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610cff5780548555610cb6565b82800160010185558215610cb657600052602060002091601f016020900482015b82811115610cb6578254825591600101919060010190610d20565b610d5591905b80821115610cc25760008155600101610d41565b9056fe547279696e6720746f20696d706f7274206e6f6e2d63616e6f6e6963616c206865616465724d697373696e6720706172656e74206865616465722066726f6d207468652073746f7261676552656163686564206d6178696d616c2076616c696461746f7273207365742069644d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f726167654d697373696e672072657175697265642066696e616c6974792070726f6f6620666f7220706172656e7420686561646572a26469706673582212206a13d7fad990f5ff64cfe638f258f1cf2a4c72a3161a28ec200db444a3d61c2e64736f6c63430006060033 \ No newline at end of file diff --git a/relays/ethereum/res/substrate-bridge-metadata.txt b/relays/ethereum/res/substrate-bridge-metadata.txt index 0dc5d853f2046..dcf50c5cfa462 100644 --- a/relays/ethereum/res/substrate-bridge-metadata.txt +++ b/relays/ethereum/res/substrate-bridge-metadata.txt @@ -1,5 +1,5 @@ -Last Change Date: 2020-04-28 +Last Change Date: 2020-05-01 Solc version: 0.6.6+commit.6c089d02 -Source hash (keccak256): 0xdc46aff04e37129265223e507d17f1407a70cb1ecea3230e1eaa77a17586724d -Source gist: https://gist.github.com/svyatonik/876b388f9507a8de242cb2db9547c4f0 +Source hash (keccak256): 0x36403636ad41082ca6c937c60ab06446cd9ef7036c178fa2f04d7c8286544d39 +Source gist: https://github.com/svyatonik/substrate-bridge-sol/blob/8b54f5f648f8685fecd52b7af1deb277922b0fc3/substrate-bridge.sol Compiler flags used (command to produce the file): `docker run -i ethereum/solc:0.6.6 --optimize --bin - < substrate-bridge.sol` \ No newline at end of file diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 8cc6078123fc7..ac70c310449d0 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_types::{Address, Bytes, EthereumHeaderId, Header, Receipt, TransactionHash, H256, U256, U64}; -use crate::substrate_types::{Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; +use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; use crate::sync_types::{HeaderId, MaybeConnectionError}; use crate::{bail_on_arg_error, bail_on_error}; use codec::{Decode, Encode}; @@ -26,6 +26,7 @@ use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; use parity_crypto::publickey::KeyPair; use serde::{de::DeserializeOwned, Serialize}; use serde_json::{from_value, to_value}; +use std::collections::HashSet; // to encode/decode contract calls ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json"); @@ -300,6 +301,64 @@ pub async fn submit_substrate_headers( (client, Ok(ids)) } +/// Returns ids of incomplete Substrate headers. +pub async fn incomplete_substrate_headers( + client: Client, + contract_address: Address, +) -> (Client, Result, Error>) { + let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); + let call_request = bail_on_arg_error!( + to_value(CallRequest { + to: Some(contract_address), + data: Some(encoded_call.into()), + }) + .map_err(|e| Error::RequestSerialization(e)), + client + ); + let (client, call_result) = + bail_on_error!(call_rpc::(client, "eth_call", Params::Array(vec![call_request]),).await); + match call_decoder.decode(&call_result.0) { + Ok((incomplete_headers_numbers, incomplete_headers_hashes)) => ( + client, + Ok(incomplete_headers_numbers + .into_iter() + .zip(incomplete_headers_hashes) + .filter_map(|(number, hash)| { + if number != number.low_u32().into() { + return None; + } + + Some(HeaderId(number.low_u32(), hash)) + }) + .collect()), + ), + Err(error) => (client, Err(Error::ResponseParseFailed(format!("{}", error)))), + } +} + +/// Complete Substrate header. +pub async fn complete_substrate_header( + client: Client, + params: EthereumSigningParams, + contract_address: Address, + id: SubstrateHeaderId, + justification: GrandpaJustification, +) -> (Client, Result) { + let (client, _) = bail_on_error!( + submit_ethereum_transaction( + client, + ¶ms, + Some(contract_address), + None, + false, + bridge_contract::functions::import_finality_proof::encode_input(id.0, id.1, justification,), + ) + .await + ); + + (client, Ok(id)) +} + /// Deploy bridge contract. pub async fn deploy_bridge_contract( client: Client, diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 7c1743a59ede2..c9e8a987f0186 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -14,19 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Ethereum PoA -> Substrate synchronization. + use crate::ethereum_client::{self, EthereumConnectionParams}; use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; use crate::substrate_client::{self, SubstrateConnectionParams, SubstrateSigningParams}; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; -use crate::sync_loop::{SourceClient, TargetClient}; -use futures::future::FutureExt; -use std::{future::Future, pin::Pin}; +use crate::sync_loop::{OwnedSourceFutureOutput, OwnedTargetFutureOutput, SourceClient, TargetClient}; +use futures::future::{ready, FutureExt, Ready}; +use std::{collections::HashSet, future::Future, pin::Pin, time::Duration}; use web3::types::H256; -/// Interval (in ms) at which we check new Ethereum headers when we are synced/almost synced. -const ETHEREUM_TICK_INTERVAL_MS: u64 = 10_000; -/// Interval (in ms) at which we check new Substrate blocks. -const SUBSTRATE_TICK_INTERVAL_MS: u64 = 5_000; +/// Interval at which we check new Ethereum headers when we are synced/almost synced. +const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); +/// Interval at which we check new Substrate blocks. +const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max number of headers in single submit transaction. const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; /// Max total size of headers in single submit transaction. This only affects signed @@ -76,13 +78,15 @@ struct EthereumHeadersSource { client: ethereum_client::Client, } +type EthereumFutureOutput = OwnedSourceFutureOutput; + impl SourceClient for EthereumHeadersSource { type Error = ethereum_client::Error; - type BestBlockNumberFuture = Pin)>>>; - type HeaderByHashFuture = Pin)>>>; - type HeaderByNumberFuture = Pin)>>>; - type HeaderExtraFuture = - Pin), Self::Error>)>>>; + type BestBlockNumberFuture = Pin>>>; + type HeaderByHashFuture = Pin>>>; + type HeaderByNumberFuture = Pin>>>; + type HeaderExtraFuture = Pin)>>>>; + type HeaderCompletionFuture = Ready)>>; fn best_block_number(self) -> Self::BestBlockNumberFuture { ethereum_client::best_block_number(self.client) @@ -107,6 +111,10 @@ impl SourceClient for EthereumHeadersSource { .map(|(client, result)| (EthereumHeadersSource { client }, result)) .boxed() } + + fn header_completion(self, id: EthereumHeaderId) -> Self::HeaderCompletionFuture { + ready((self, Ok((id, None)))) + } } /// Substrate client as Ethereum headers target. @@ -119,12 +127,16 @@ struct SubstrateHeadersTarget { sign_params: SubstrateSigningParams, } +type SubstrateFutureOutput = OwnedTargetFutureOutput; + impl TargetClient for SubstrateHeadersTarget { type Error = substrate_client::Error; - type BestHeaderIdFuture = Pin)>>>; - type IsKnownHeaderFuture = Pin)>>>; - type RequiresExtraFuture = Pin)>>>; - type SubmitHeadersFuture = Pin, Self::Error>)>>>; + type BestHeaderIdFuture = Pin>>>; + type IsKnownHeaderFuture = Pin>>>; + type RequiresExtraFuture = Pin>>>; + type SubmitHeadersFuture = Pin>>>>; + type IncompleteHeadersFuture = Ready>>; + type CompleteHeadersFuture = Ready>; fn best_header_id(self) -> Self::BestHeaderIdFuture { let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); @@ -192,6 +204,14 @@ impl TargetClient for SubstrateHeadersTarget { }) .boxed() } + + fn incomplete_headers_ids(self) -> Self::IncompleteHeadersFuture { + ready((self, Ok(HashSet::new()))) + } + + fn complete_header(self, id: EthereumHeaderId, _completion: ()) -> Self::CompleteHeadersFuture { + ready((self, Ok(id))) + } } /// Run Ethereum headers synchronization. @@ -206,13 +226,13 @@ pub fn run(params: EthereumSyncParams) { crate::sync_loop::run( EthereumHeadersSource { client: eth_client }, - ETHEREUM_TICK_INTERVAL_MS, + ETHEREUM_TICK_INTERVAL, SubstrateHeadersTarget { client: sub_client, sign_transactions: sign_sub_transactions, sign_params: params.sub_sign, }, - SUBSTRATE_TICK_INTERVAL_MS, + SUBSTRATE_TICK_INTERVAL, params.sync_params, ); } diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index d996ac7c29455..4731570d4d873 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -56,6 +56,7 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { type Number = u64; type Header = Header; type Extra = Vec; + type Completion = (); fn estimate_size(source: &QueuedHeader) -> usize { into_substrate_ethereum_header(source.header()).encode().len() diff --git a/relays/ethereum/src/headers.rs b/relays/ethereum/src/headers.rs index 0e34b9a98f1b7..a75937da8cfb3 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/ethereum/src/headers.rs @@ -15,9 +15,11 @@ // along with Parity Bridges Common. If not, see . use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use linked_hash_map::LinkedHashMap; use num_traits::{One, Zero}; -use std::collections::{ - btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet, +use std::{ + collections::{btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet}, + time::{Duration, Instant}, }; type HeadersQueue

= @@ -25,6 +27,9 @@ type HeadersQueue

= type KnownHeaders

= BTreeMap<

::Number, HashMap<

::Hash, HeaderStatus>>; +/// We're trying to fetch completion data for single header at this interval. +const RETRY_FETCH_COMPLETION_INTERVAL: Duration = Duration::from_secs(20); + /// Ethereum headers queue. #[derive(Debug)] pub struct QueuedHeaders { @@ -43,16 +48,34 @@ pub struct QueuedHeaders { extra: HeadersQueue

, /// Headers that are ready to be submitted to target node. ready: HeadersQueue

, + /// Headers that are ready to be submitted to target node, but their ancestor is incomplete. + /// Thus we're waiting for these ancestors to be completed first. + /// Note that the incomplete header itself is synced and it isn't in this queue. + incomplete: HeadersQueue

, /// Headers that are (we believe) currently submitted to target node by our, /// not-yet mined transactions. submitted: HeadersQueue

, /// Pointers to all headers that we ever seen and we believe we can touch in the future. known_headers: KnownHeaders

, + /// Headers that are waiting for completion data from source node. Mapped (and auto-sorted + /// by) to the last fetch time. + incomplete_headers: LinkedHashMap, Option>, + /// Headers that are waiting to be completed at target node. Auto-sorted by insertion time. + completion_data: LinkedHashMap, P::Completion>, /// Pruned blocks border. We do not store or accept any blocks with number less than /// this number. prune_border: P::Number, } +/// Header completion data. +#[derive(Debug)] +struct HeaderCompletion { + /// Last time when we tried to upload completion data to target node, if ever. + pub last_upload_time: Option, + /// Completion data. + pub completion: Completion, +} + impl QueuedHeaders

{ /// Returns new QueuedHeaders. pub fn new() -> Self { @@ -62,8 +85,11 @@ impl QueuedHeaders

{ maybe_extra: HeadersQueue::new(), extra: HeadersQueue::new(), ready: HeadersQueue::new(), + incomplete: HeadersQueue::new(), submitted: HeadersQueue::new(), known_headers: KnownHeaders::

::new(), + incomplete_headers: LinkedHashMap::new(), + completion_data: LinkedHashMap::new(), prune_border: Zero::zero(), } } @@ -89,6 +115,7 @@ impl QueuedHeaders

{ .fold(0, |total, headers| total + headers.len()), HeaderStatus::Extra => self.extra.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Ready => self.ready.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Incomplete => self.incomplete.values().fold(0, |total, headers| total + headers.len()), HeaderStatus::Submitted => self.submitted.values().fold(0, |total, headers| total + headers.len()), } } @@ -105,6 +132,7 @@ impl QueuedHeaders

{ .fold(0, |total, headers| total + headers.len()) + self.extra.values().fold(0, |total, headers| total + headers.len()) + self.ready.values().fold(0, |total, headers| total + headers.len()) + + self.incomplete.values().fold(0, |total, headers| total + headers.len()) } /// Returns number of best block in the queue. @@ -119,7 +147,10 @@ impl QueuedHeaders

{ self.extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), std::cmp::max( self.ready.keys().next_back().cloned().unwrap_or_else(Zero::zero), - self.submitted.keys().next_back().cloned().unwrap_or_else(Zero::zero), + std::cmp::max( + self.incomplete.keys().next_back().cloned().unwrap_or_else(Zero::zero), + self.submitted.keys().next_back().cloned().unwrap_or_else(Zero::zero), + ), ), ), ), @@ -145,6 +176,7 @@ impl QueuedHeaders

{ HeaderStatus::MaybeExtra => oldest_header(&self.maybe_extra), HeaderStatus::Extra => oldest_header(&self.extra), HeaderStatus::Ready => oldest_header(&self.ready), + HeaderStatus::Incomplete => oldest_header(&self.incomplete), HeaderStatus::Submitted => oldest_header(&self.submitted), } } @@ -162,6 +194,7 @@ impl QueuedHeaders

{ HeaderStatus::MaybeExtra => oldest_headers(&self.maybe_extra, f), HeaderStatus::Extra => oldest_headers(&self.extra, f), HeaderStatus::Ready => oldest_headers(&self.ready, f), + HeaderStatus::Incomplete => oldest_headers(&self.incomplete, f), HeaderStatus::Submitted => oldest_headers(&self.submitted, f), } } @@ -207,6 +240,7 @@ impl QueuedHeaders

{ HeaderStatus::MaybeExtra | HeaderStatus::Extra | HeaderStatus::Ready + | HeaderStatus::Incomplete | HeaderStatus::Submitted | HeaderStatus::Synced => { insert_header(&mut self.maybe_extra, id, header); @@ -226,67 +260,7 @@ impl QueuedHeaders

{ /// Receive best header from the target node. pub fn target_best_header_response(&mut self, id: &HeaderId) { - // all ancestors of this header are now synced => let's remove them from - // queues - let mut current = *id; - let mut id_processed = false; - loop { - let header = match self.status(¤t) { - HeaderStatus::Unknown => break, - HeaderStatus::MaybeOrphan => remove_header(&mut self.maybe_orphan, ¤t), - HeaderStatus::Orphan => remove_header(&mut self.orphan, ¤t), - HeaderStatus::MaybeExtra => remove_header(&mut self.maybe_extra, ¤t), - HeaderStatus::Extra => remove_header(&mut self.extra, ¤t), - HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), - HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), - HeaderStatus::Synced => break, - } - .expect("header has a given status; given queue has the header; qed"); - - log::debug!( - target: "bridge", - "{} header {:?} is now {:?}", - P::SOURCE_NAME, - current, - HeaderStatus::Synced, - ); - *self - .known_headers - .entry(current.0) - .or_default() - .entry(current.1) - .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; - current = header.parent_id(); - id_processed = true; - } - - // remember that the header is synced - if !id_processed { - // to avoid duplicate log message - log::debug!( - target: "bridge", - "{} header {:?} is now {:?}", - P::SOURCE_NAME, - id, - HeaderStatus::Synced, - ); - *self - .known_headers - .entry(id.0) - .or_default() - .entry(id.1) - .or_insert(HeaderStatus::Synced) = HeaderStatus::Synced; - } - - // now let's move all descendants from maybe_orphan && orphan queues to - // maybe_extra queue - move_header_descendants::

( - &mut [&mut self.maybe_orphan, &mut self.orphan], - &mut self.maybe_extra, - &mut self.known_headers, - HeaderStatus::MaybeExtra, - id, - ); + self.header_synced(id) } /// Receive target node response for MaybeOrphan request. @@ -315,6 +289,8 @@ impl QueuedHeaders

{ pub fn maybe_extra_response(&mut self, id: &HeaderId, response: bool) { let (destination_status, destination_queue) = if response { (HeaderStatus::Extra, &mut self.extra) + } else if self.is_parent_incomplete(id) { + (HeaderStatus::Incomplete, &mut self.incomplete) } else { (HeaderStatus::Ready, &mut self.ready) }; @@ -331,17 +307,42 @@ impl QueuedHeaders

{ /// Receive extra from source node. pub fn extra_response(&mut self, id: &HeaderId, extra: P::Extra) { + let (destination_status, destination_queue) = if self.is_parent_incomplete(id) { + (HeaderStatus::Incomplete, &mut self.incomplete) + } else { + (HeaderStatus::Ready, &mut self.ready) + }; + // move header itself from extra to ready queue move_header( &mut self.extra, - &mut self.ready, + destination_queue, &mut self.known_headers, - HeaderStatus::Ready, + destination_status, id, |header| header.set_extra(extra), ); } + /// Receive completion response from source node. + pub fn completion_response(&mut self, id: &HeaderId, completion: Option) { + let completion = match completion { + Some(completion) => completion, + None => return, // we'll try refetch later + }; + + if self.incomplete_headers.remove(id).is_some() { + log::debug!( + target: "bridge", + "Received completion data from {} for header: {:?}", + P::SOURCE_NAME, + id, + ); + + self.completion_data.insert(id.clone(), completion); + } + } + /// When header is submitted to target node. pub fn headers_submitted(&mut self, ids: Vec>) { for id in ids { @@ -356,7 +357,110 @@ impl QueuedHeaders

{ } } - /// Prune and never accep headers before this block. + /// When header completion data is sent to target node. + pub fn header_completed(&mut self, id: &HeaderId) { + if self.completion_data.remove(id).is_some() { + log::debug!( + target: "bridge", + "Sent completion data to {} for header: {:?}", + P::TARGET_NAME, + id, + ); + + // transaction can be dropped by target chain nodes => it would never be mined + // + // in current implementation the sync loop would wait for some time && if best + // **source** header won't change on **target** node, then the sync will be restarted + // => we'll resubmit the same completion data again (the same is true for submitted + // headers) + // + // the other option would be to track emitted transactions at least on target node, + // but it won't give us 100% guarantee anyway + // + // => we're just dropping completion data just after it has been submitted + } + } + + /// When incomplete headers ids are receved from target node. + pub fn incomplete_headers_response(&mut self, ids: HashSet>) { + // all new incomplete headers are marked Synced and all their descendants + // are moved from Ready/Submitted to Incomplete queue + let new_incomplete_headers = ids + .iter() + .filter(|id| !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id)) + .cloned() + .collect::>(); + for new_incomplete_header in new_incomplete_headers { + self.header_synced(&new_incomplete_header); + move_header_descendants::

( + &mut [&mut self.ready, &mut self.submitted], + &mut self.incomplete, + &mut self.known_headers, + HeaderStatus::Incomplete, + &new_incomplete_header, + ); + + log::debug!( + target: "bridge", + "Scheduling completion data retrieval for header: {:?}", + new_incomplete_header, + ); + + self.incomplete_headers.insert(new_incomplete_header, None); + } + + // for all headers that were incompleted previously, but now are completed, we move + // all descendants from incomplete to ready + let just_completed_headers = self + .incomplete_headers + .keys() + .chain(self.completion_data.keys()) + .filter(|id| !ids.contains(id)) + .cloned() + .collect::>(); + for just_completed_header in just_completed_headers { + move_header_descendants::

( + &mut [&mut self.incomplete], + &mut self.ready, + &mut self.known_headers, + HeaderStatus::Ready, + &just_completed_header, + ); + + log::debug!( + target: "bridge", + "Completion data is no longer required for header: {:?}", + just_completed_header, + ); + + self.incomplete_headers.remove(&just_completed_header); + self.completion_data.remove(&just_completed_header); + } + } + + /// Returns id of the header for which we want to fetch completion data. + pub fn incomplete_header(&mut self) -> Option> { + queued_incomplete_header(&mut self.incomplete_headers, |last_fetch_time| { + let retry = match *last_fetch_time { + Some(last_fetch_time) => last_fetch_time.elapsed() > RETRY_FETCH_COMPLETION_INTERVAL, + None => true, + }; + + if retry { + *last_fetch_time = Some(Instant::now()); + } + + retry + }) + .map(|(id, _)| id) + } + + /// Returns header completion data to upload to target node. + pub fn header_to_complete(&mut self) -> Option<(HeaderId, &P::Completion)> { + queued_incomplete_header(&mut self.completion_data, |_| true) + } + + /// Prune and never accept headers before this block. pub fn prune(&mut self, prune_border: P::Number) { if prune_border <= self.prune_border { return; @@ -368,6 +472,7 @@ impl QueuedHeaders

{ prune_queue(&mut self.extra, prune_border); prune_queue(&mut self.ready, prune_border); prune_queue(&mut self.submitted, prune_border); + prune_queue(&mut self.incomplete, prune_border); prune_known_headers::

(&mut self.known_headers, prune_border); self.prune_border = prune_border; } @@ -379,10 +484,81 @@ impl QueuedHeaders

{ self.maybe_extra.clear(); self.extra.clear(); self.ready.clear(); + self.incomplete.clear(); self.submitted.clear(); self.known_headers.clear(); self.prune_border = Zero::zero(); } + + /// Returns true if parent of this header is either incomplete or waiting for + /// its own incomplete ancestor to be completed. + fn is_parent_incomplete(&self, id: &HeaderId) -> bool { + let status = self.status(id); + let header = match status { + HeaderStatus::MaybeOrphan => header(&self.maybe_orphan, id), + HeaderStatus::Orphan => header(&self.orphan, id), + HeaderStatus::MaybeExtra => header(&self.maybe_extra, id), + HeaderStatus::Extra => header(&self.extra, id), + HeaderStatus::Ready => header(&self.ready, id), + HeaderStatus::Incomplete => header(&self.incomplete, id), + HeaderStatus::Submitted => header(&self.submitted, id), + HeaderStatus::Unknown => return false, + HeaderStatus::Synced => return false, + }; + + match header { + Some(header) => { + let parent_id = header.header().parent_id(); + self.incomplete_headers.contains_key(&parent_id) + || self.completion_data.contains_key(&parent_id) + || self.status(&parent_id) == HeaderStatus::Incomplete + } + None => false, + } + } + + /// When we receive new Synced header from target node. + fn header_synced(&mut self, id: &HeaderId) { + // all ancestors of this header are now synced => let's remove them from + // queues + let mut current = *id; + let mut id_processed = false; + loop { + let header = match self.status(¤t) { + HeaderStatus::Unknown => break, + HeaderStatus::MaybeOrphan => remove_header(&mut self.maybe_orphan, ¤t), + HeaderStatus::Orphan => remove_header(&mut self.orphan, ¤t), + HeaderStatus::MaybeExtra => remove_header(&mut self.maybe_extra, ¤t), + HeaderStatus::Extra => remove_header(&mut self.extra, ¤t), + HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), + HeaderStatus::Incomplete => remove_header(&mut self.incomplete, ¤t), + HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), + HeaderStatus::Synced => break, + } + .expect("header has a given status; given queue has the header; qed"); + + set_header_status::

(&mut self.known_headers, ¤t, HeaderStatus::Synced); + + current = header.parent_id(); + id_processed = true; + } + + // remember that the header itself is synced + // (condition is here to avoid duplicate log messages) + if !id_processed { + set_header_status::

(&mut self.known_headers, &id, HeaderStatus::Synced); + } + + // now let's move all descendants from maybe_orphan && orphan queues to + // maybe_extra queue + move_header_descendants::

( + &mut [&mut self.maybe_orphan, &mut self.orphan], + &mut self.maybe_extra, + &mut self.known_headers, + HeaderStatus::MaybeExtra, + id, + ); + } } /// Insert header to the queue. @@ -411,6 +587,14 @@ fn remove_header( header } +/// Get header from the queue. +fn header<'a, P: HeadersSyncPipeline>( + queue: &'a HeadersQueue

, + id: &HeaderId, +) -> Option<&'a QueuedHeader

> { + queue.get(&id.0).and_then(|by_hash| by_hash.get(&id.1)) +} + /// Move header from source to destination queue. /// /// Returns ID of parent header, if header has been moved, or None otherwise. @@ -428,16 +612,8 @@ fn move_header( }; let parent_id = header.header().parent_id(); - known_headers.entry(id.0).or_default().insert(id.1, destination_status); destination_queue.entry(id.0).or_default().insert(id.1, header); - - log::debug!( - target: "bridge", - "{} header {:?} is now {:?}", - P::SOURCE_NAME, - id, - destination_status, - ); + set_header_status::

(known_headers, id, destination_status); Some(parent_id) } @@ -473,19 +649,8 @@ fn move_header_descendants( if current_parents.contains(&entry.get().header().parent_id().1) { let header_to_move = entry.remove(); let header_to_move_id = header_to_move.id(); - known_headers - .entry(header_to_move_id.0) - .or_default() - .insert(header_to_move_id.1, destination_status); headers_to_move.push((header_to_move_id, header_to_move)); - - log::debug!( - target: "bridge", - "{} header {:?} is now {:?}", - P::SOURCE_NAME, - header_to_move_id, - destination_status, - ); + set_header_status::

(known_headers, &header_to_move_id, destination_status); } } @@ -544,6 +709,44 @@ fn prune_known_headers(known_headers: &mut KnownHeaders< *known_headers = new_known_headers; } +/// Change header status. +fn set_header_status( + known_headers: &mut KnownHeaders

, + id: &HeaderId, + status: HeaderStatus, +) { + log::debug!( + target: "bridge", + "{} header {:?} is now {:?}", + P::SOURCE_NAME, + id, + status, + ); + *known_headers.entry(id.0).or_default().entry(id.1).or_insert(status) = status; +} + +/// Returns queued incomplete header with maximal elapsed time since last update. +fn queued_incomplete_header( + map: &mut LinkedHashMap, + filter: impl FnMut(&mut T) -> bool, +) -> Option<(Id, &T)> { + // TODO (#84): headers that have been just appended to the end of the queue would have to wait until + // all previous headers will be retried + + let retry_old_header = map + .front() + .map(|(key, _)| key.clone()) + .and_then(|key| map.get_mut(&key).map(filter)) + .unwrap_or(false); + if retry_old_header { + let (header_key, header) = map.pop_front().expect("we have checked that front() exists; qed"); + map.insert(header_key, header); + return map.back().map(|(id, data)| (id.clone(), data)); + } + + None +} + #[cfg(test)] pub(crate) mod tests { use super::*; @@ -595,7 +798,11 @@ pub(crate) mod tests { hash(6), QueuedHeader::::new(Default::default()), ); - assert_eq!(queue.total_headers(), 6); + queue.incomplete.entry(6).or_default().insert( + hash(7), + QueuedHeader::::new(Default::default()), + ); + assert_eq!(queue.total_headers(), 7); } #[test] @@ -639,6 +846,12 @@ pub(crate) mod tests { QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 40); + // and then there's some header in Incomplete + queue.incomplete.entry(50).or_default().insert( + hash(50), + QueuedHeader::::new(Default::default()), + ); + assert_eq!(queue.best_queued_number(), 50); } #[test] @@ -946,6 +1159,7 @@ pub(crate) mod tests { #[test] fn negative_maybe_extra_response_works() { + // when parent header is complete let mut queue = QueuedHeaders::::new(); queue .known_headers @@ -957,10 +1171,24 @@ pub(crate) mod tests { assert!(queue.maybe_extra.is_empty()); assert_eq!(queue.ready.len(), 1); assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); + + // when parent header is incomplete + queue.incomplete_headers.insert(id(200), None); + queue + .known_headers + .entry(201) + .or_default() + .insert(hash(201), HeaderStatus::MaybeExtra); + queue.maybe_extra.entry(201).or_default().insert(hash(201), header(201)); + queue.maybe_extra_response(&id(201), false); + assert!(queue.maybe_extra.is_empty()); + assert_eq!(queue.incomplete.len(), 1); + assert_eq!(queue.known_headers[&201][&hash(201)], HeaderStatus::Incomplete); } #[test] fn receipts_response_works() { + // when parent header is complete let mut queue = QueuedHeaders::::new(); queue .known_headers @@ -972,6 +1200,19 @@ pub(crate) mod tests { assert!(queue.extra.is_empty()); assert_eq!(queue.ready.len(), 1); assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); + + // when parent header is incomplete + queue.incomplete_headers.insert(id(200), None); + queue + .known_headers + .entry(201) + .or_default() + .insert(hash(201), HeaderStatus::Extra); + queue.extra.entry(201).or_default().insert(hash(201), header(201)); + queue.extra_response(&id(201), Vec::new()); + assert!(queue.extra.is_empty()); + assert_eq!(queue.incomplete.len(), 1); + assert_eq!(queue.known_headers[&201][&hash(201)], HeaderStatus::Incomplete); } #[test] @@ -988,9 +1229,172 @@ pub(crate) mod tests { assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Submitted); } + #[test] + fn incomplete_header_works() { + let mut queue = QueuedHeaders::::new(); + + // nothing to complete if queue is empty + assert_eq!(queue.incomplete_header(), None); + + // when there's new header to complete => ask for completion data + queue.incomplete_headers.insert(id(100), None); + assert_eq!(queue.incomplete_header(), Some(id(100))); + + // we have just asked for completion data => nothing to request + assert_eq!(queue.incomplete_header(), None); + + // enough time have passed => ask again + queue.incomplete_headers.clear(); + queue.incomplete_headers.insert( + id(100), + Some(Instant::now() - RETRY_FETCH_COMPLETION_INTERVAL - RETRY_FETCH_COMPLETION_INTERVAL), + ); + assert_eq!(queue.incomplete_header(), Some(id(100))); + } + + #[test] + fn completion_response_works() { + let mut queue = QueuedHeaders::::new(); + queue.incomplete_headers.insert(id(100), None); + queue.incomplete_headers.insert(id(200), Some(Instant::now())); + + // when headers isn't incompete, nothing changes + queue.completion_response(&id(300), None); + assert_eq!(queue.incomplete_headers.len(), 2); + assert_eq!(queue.completion_data.len(), 0); + assert_eq!(queue.header_to_complete(), None); + + // when response is None, nothing changes + queue.completion_response(&id(100), None); + assert_eq!(queue.incomplete_headers.len(), 2); + assert_eq!(queue.completion_data.len(), 0); + assert_eq!(queue.header_to_complete(), None); + + // when response is Some, we're scheduling completion + queue.completion_response(&id(200), Some(())); + assert_eq!(queue.incomplete_headers.len(), 1); + assert_eq!(queue.completion_data.len(), 1); + assert!(queue.incomplete_headers.contains_key(&id(100))); + assert!(queue.completion_data.contains_key(&id(200))); + assert_eq!(queue.header_to_complete(), Some((id(200), &()))); + } + + #[test] + fn header_completed_works() { + let mut queue = QueuedHeaders::::new(); + queue.completion_data.insert(id(100), ()); + + // when unknown header is completed + queue.header_completed(&id(200)); + assert_eq!(queue.completion_data.len(), 1); + + // when known header is completed + queue.header_completed(&id(100)); + assert_eq!(queue.completion_data.len(), 0); + } + + #[test] + fn incomplete_headers_response_works() { + let mut queue = QueuedHeaders::::new(); + + // when we have already submitted #101 and #102 is ready + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Submitted); + queue.submitted.entry(101).or_default().insert(hash(101), header(101)); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::Ready); + queue.submitted.entry(102).or_default().insert(hash(102), header(102)); + + // AND now we know that the #100 is incomplete + queue.incomplete_headers_response(vec![id(100)].into_iter().collect()); + + // => #101 and #102 are moved to the Incomplete and #100 is now synced + assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(101)), HeaderStatus::Incomplete); + assert_eq!(queue.status(&id(102)), HeaderStatus::Incomplete); + assert_eq!(queue.submitted.len(), 0); + assert_eq!(queue.ready.len(), 0); + assert!(queue.incomplete.entry(101).or_default().contains_key(&hash(101))); + assert!(queue.incomplete.entry(102).or_default().contains_key(&hash(102))); + assert!(queue.incomplete_headers.contains_key(&id(100))); + assert!(queue.completion_data.is_empty()); + + // and then header #100 is no longer incomplete + queue.incomplete_headers_response(vec![].into_iter().collect()); + + // => #101 and #102 are moved to the Ready queue and #100 if now forgotten + assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(101)), HeaderStatus::Ready); + assert_eq!(queue.status(&id(102)), HeaderStatus::Ready); + assert_eq!(queue.incomplete.len(), 0); + assert_eq!(queue.submitted.len(), 0); + assert!(queue.ready.entry(101).or_default().contains_key(&hash(101))); + assert!(queue.ready.entry(102).or_default().contains_key(&hash(102))); + assert!(queue.incomplete_headers.is_empty()); + assert!(queue.completion_data.is_empty()); + } + + #[test] + fn is_parent_incomplete_works() { + let mut queue = QueuedHeaders::::new(); + + // when we do not know header itself + assert_eq!(queue.is_parent_incomplete(&id(50)), false); + + // when we do not know parent + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Incomplete); + queue.incomplete.entry(100).or_default().insert(hash(100), header(100)); + assert_eq!(queue.is_parent_incomplete(&id(100)), false); + + // when parent is inside incomplete queue (i.e. some other ancestor is actually incomplete) + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Submitted); + queue.submitted.entry(101).or_default().insert(hash(101), header(101)); + assert_eq!(queue.is_parent_incomplete(&id(101)), true); + + // when parent is the incomplete header and we do not have completion data + queue.incomplete_headers.insert(id(199), None); + queue + .known_headers + .entry(200) + .or_default() + .insert(hash(200), HeaderStatus::Submitted); + queue.submitted.entry(200).or_default().insert(hash(200), header(200)); + assert_eq!(queue.is_parent_incomplete(&id(200)), true); + + // when parent is the incomplete header and we have completion data + queue.completion_data.insert(id(299), ()); + queue + .known_headers + .entry(300) + .or_default() + .insert(hash(300), HeaderStatus::Submitted); + queue.submitted.entry(300).or_default().insert(hash(300), header(300)); + assert_eq!(queue.is_parent_incomplete(&id(300)), true); + } + #[test] fn prune_works() { let mut queue = QueuedHeaders::::new(); + queue + .known_headers + .entry(105) + .or_default() + .insert(hash(105), HeaderStatus::Incomplete); + queue.incomplete.entry(105).or_default().insert(hash(105), header(105)); queue .known_headers .entry(104) @@ -1033,7 +1437,8 @@ pub(crate) mod tests { assert_eq!(queue.maybe_extra.len(), 1); assert_eq!(queue.orphan.len(), 1); assert_eq!(queue.maybe_orphan.len(), 1); - assert_eq!(queue.known_headers.len(), 3); + assert_eq!(queue.incomplete.len(), 1); + assert_eq!(queue.known_headers.len(), 4); queue.prune(110); @@ -1042,6 +1447,7 @@ pub(crate) mod tests { assert_eq!(queue.maybe_extra.len(), 0); assert_eq!(queue.orphan.len(), 0); assert_eq!(queue.maybe_orphan.len(), 0); + assert_eq!(queue.incomplete.len(), 0); assert_eq!(queue.known_headers.len(), 0); queue.header_response(header(109).header().clone()); @@ -1050,4 +1456,51 @@ pub(crate) mod tests { queue.header_response(header(110).header().clone()); assert_eq!(queue.known_headers.len(), 1); } + + #[test] + fn incomplete_headers_are_still_incomplete_after_advance() { + let mut queue = QueuedHeaders::::new(); + + // relay#1 knows that header#100 is incomplete && it has headers 101..104 in incomplete queue + queue.incomplete_headers.insert(id(100), None); + queue.incomplete.entry(101).or_default().insert(hash(101), header(101)); + queue.incomplete.entry(102).or_default().insert(hash(102), header(102)); + queue.incomplete.entry(103).or_default().insert(hash(103), header(103)); + queue.incomplete.entry(104).or_default().insert(hash(104), header(104)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Synced); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Incomplete); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::Incomplete); + queue + .known_headers + .entry(103) + .or_default() + .insert(hash(103), HeaderStatus::Incomplete); + queue + .known_headers + .entry(104) + .or_default() + .insert(hash(104), HeaderStatus::Incomplete); + + // let's say relay#2 completes header#100 and then submits header#101+header#102 and it turns + // out that header#102 is also incomplete + queue.incomplete_headers_response(vec![id(102)].into_iter().collect()); + + // then the header#103 and the header#104 must have Incomplete status + assert_eq!(queue.status(&id(101)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(102)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(103)), HeaderStatus::Incomplete); + assert_eq!(queue.status(&id(104)), HeaderStatus::Incomplete); + } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 3d74dec250a7b..e62c12e31b138 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -16,7 +16,8 @@ use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256}; use crate::substrate_types::{ - into_substrate_ethereum_header, into_substrate_ethereum_receipts, Hash, Header as SubstrateHeader, Number, + into_substrate_ethereum_header, into_substrate_ethereum_receipts, GrandpaJustification, Hash, + Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock, SubstrateHeaderId, }; use crate::sync_types::{HeaderId, MaybeConnectionError, SourceHeader}; use crate::{bail_on_arg_error, bail_on_error}; @@ -274,6 +275,19 @@ pub async fn submit_unsigned_ethereum_headers( (client, Ok(ids)) } +/// Get GRANDPA justification for given block. +pub async fn grandpa_justification( + client: Client, + id: SubstrateHeaderId, +) -> (Client, Result<(SubstrateHeaderId, Option), Error>) { + let hash = bail_on_arg_error!(to_value(id.1).map_err(|e| Error::RequestSerialization(e)), client); + let (client, signed_block) = call_rpc(client, "chain_getBlock", Params::Array(vec![hash]), rpc_returns_value).await; + ( + client, + signed_block.map(|signed_block: SignedSubstrateBlock| (id, signed_block.justification)), + ) +} + /// Get GRANDPA authorities set at given block. pub async fn grandpa_authorities_set(client: Client, block: Hash) -> (Client, Result, Error>) { let block = bail_on_arg_error!(to_value(block).map_err(|e| Error::RequestSerialization(e)), client); diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 2c194dac0166c..88dc4b6276a46 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -14,22 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Substrate -> Ethereum synchronization. + use crate::ethereum_client::{self, EthereumConnectionParams, EthereumSigningParams}; use crate::ethereum_types::Address; use crate::substrate_client::{self, SubstrateConnectionParams}; use crate::substrate_types::{ - Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, + GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, }; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; -use crate::sync_loop::{SourceClient, TargetClient}; +use crate::sync_loop::{OwnedSourceFutureOutput, OwnedTargetFutureOutput, SourceClient, TargetClient}; use crate::sync_types::SourceHeader; use futures::future::{ready, FutureExt, Ready}; -use std::{future::Future, pin::Pin}; +use std::{collections::HashSet, future::Future, pin::Pin, time::Duration}; -/// Interval (in ms) at which we check new Substrate headers when we are synced/almost synced. -const SUBSTRATE_TICK_INTERVAL_MS: u64 = 10_000; -/// Interval (in ms) at which we check new Ethereum blocks. -const ETHEREUM_TICK_INTERVAL_MS: u64 = 5_000; +/// Interval at which we check new Substrate headers when we are synced/almost synced. +const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10); +/// Interval at which we check new Ethereum blocks. +const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max Ethereum headers we want to have in all 'before-submitted' states. const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; /// Max Ethereum headers count we want to have in 'submitted' state. @@ -83,12 +85,16 @@ struct SubstrateHeadersSource { client: substrate_client::Client, } +type SubstrateFutureOutput = OwnedSourceFutureOutput; + impl SourceClient for SubstrateHeadersSource { type Error = substrate_client::Error; - type BestBlockNumberFuture = Pin)>>>; - type HeaderByHashFuture = Pin)>>>; - type HeaderByNumberFuture = Pin)>>>; - type HeaderExtraFuture = Ready<(Self, Result<(SubstrateHeaderId, ()), Self::Error>)>; + type BestBlockNumberFuture = Pin>>>; + type HeaderByHashFuture = Pin>>>; + type HeaderByNumberFuture = Pin>>>; + type HeaderExtraFuture = Ready>; + type HeaderCompletionFuture = + Pin)>>>>; fn best_block_number(self) -> Self::BestBlockNumberFuture { substrate_client::best_header(self.client) @@ -111,6 +117,12 @@ impl SourceClient for SubstrateHeadersSource { fn header_extra(self, id: SubstrateHeaderId, _header: &Header) -> Self::HeaderExtraFuture { ready((self, Ok((id, ())))) } + + fn header_completion(self, id: SubstrateHeaderId) -> Self::HeaderCompletionFuture { + substrate_client::grandpa_justification(self.client, id) + .map(|(client, result)| (SubstrateHeadersSource { client }, result)) + .boxed() + } } /// Ethereum client as Substrate headers target. @@ -123,12 +135,16 @@ struct EthereumHeadersTarget { sign_params: EthereumSigningParams, } +type EthereumFutureOutput = OwnedTargetFutureOutput; + impl TargetClient for EthereumHeadersTarget { type Error = ethereum_client::Error; - type BestHeaderIdFuture = Pin)>>>; - type IsKnownHeaderFuture = Pin)>>>; - type RequiresExtraFuture = Ready<(Self, Result<(SubstrateHeaderId, bool), Self::Error>)>; - type SubmitHeadersFuture = Pin, Self::Error>)>>>; + type BestHeaderIdFuture = Pin>>>; + type IsKnownHeaderFuture = Pin>>>; + type RequiresExtraFuture = Ready>; + type SubmitHeadersFuture = Pin>>>>; + type IncompleteHeadersFuture = Pin>>>>; + type CompleteHeadersFuture = Pin>>>; fn best_header_id(self) -> Self::BestHeaderIdFuture { let (contract, sign_params) = (self.contract, self.sign_params); @@ -181,6 +197,38 @@ impl TargetClient for EthereumHeadersTarget { }) .boxed() } + + fn incomplete_headers_ids(self) -> Self::IncompleteHeadersFuture { + let (contract, sign_params) = (self.contract, self.sign_params); + ethereum_client::incomplete_substrate_headers(self.client, contract) + .map(move |(client, result)| { + ( + EthereumHeadersTarget { + client, + contract, + sign_params, + }, + result, + ) + }) + .boxed() + } + + fn complete_header(self, id: SubstrateHeaderId, completion: GrandpaJustification) -> Self::CompleteHeadersFuture { + let (contract, sign_params) = (self.contract, self.sign_params); + ethereum_client::complete_substrate_header(self.client, sign_params.clone(), contract, id, completion) + .map(move |(client, result)| { + ( + EthereumHeadersTarget { + client, + contract, + sign_params, + }, + result, + ) + }) + .boxed() + } } /// Run Substrate headers synchronization. @@ -190,13 +238,13 @@ pub fn run(params: SubstrateSyncParams) { crate::sync_loop::run( SubstrateHeadersSource { client: sub_client }, - SUBSTRATE_TICK_INTERVAL_MS, + SUBSTRATE_TICK_INTERVAL, EthereumHeadersTarget { client: eth_client, contract: params.eth_contract_address, sign_params: params.eth_sign, }, - ETHEREUM_TICK_INTERVAL_MS, + ETHEREUM_TICK_INTERVAL, params.sync_params, ); } diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index d657f0269d838..89e8572ccaaba 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -34,6 +34,12 @@ pub type Number = bridge_node_runtime::BlockNumber; /// Substrate header type. pub type Header = bridge_node_runtime::Header; +/// Substrate signed block type. +pub type SignedBlock = bridge_node_runtime::SignedBlock; + +/// GRANDPA justification. +pub type GrandpaJustification = Vec; + /// Substrate header ID. pub type SubstrateHeaderId = HeaderId; @@ -53,6 +59,7 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { type Number = bridge_node_runtime::BlockNumber; type Header = Header; type Extra = (); + type Completion = GrandpaJustification; fn estimate_size(source: &QueuedHeader) -> usize { source.header().encode().len() diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index b2e97c979408a..ce89a846a0fb4 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -18,10 +18,14 @@ use crate::sync::HeadersSyncParams; use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader}; use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; -use std::future::Future; +use std::{ + collections::HashSet, + future::Future, + time::{Duration, Instant}, +}; /// When we submit headers to target node, but see no updates of best -/// source block known to target node during STALL_SYNC_TIMEOUT_MS milliseconds, +/// source block known to target node during STALL_SYNC_TIMEOUT seconds, /// we consider that our headers are rejected because there has been reorg in target chain. /// This reorg could invalidate our knowledge about sync process (i.e. we have asked if /// HeaderA is known to target, but then reorg happened and the answer is different @@ -30,26 +34,35 @@ use std::future::Future; /// direct child of previous best header. But: (1) subscription doesn't guarantee that /// the subscriber will receive every best header (2) reorg won't always lead to sync /// stall and restart is a heavy operation (we forget all in-memory headers). -const STALL_SYNC_TIMEOUT_MS: u64 = 30_000; -/// Delay (in milliseconds) after we have seen update of best source header at target node, +const STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(5 * 60); +/// Delay after we have seen update of best source header at target node, /// for us to treat sync stalled. ONLY when relay operates in backup mode. -const BACKUP_STALL_SYNC_TIMEOUT_MS: u64 = 5 * 60_000; -/// Delay (in milliseconds) after connection-related error happened before we'll try +const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); +/// Delay after connection-related error happened before we'll try /// reconnection again. -const CONNECTION_ERROR_DELAY_MS: u64 = 10_000; +const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); + +/// Type alias for all SourceClient futures. +pub type OwnedSourceFutureOutput = (Client, Result>::Error>); +/// Type alias for all TargetClient futures. +pub type OwnedTargetFutureOutput = (Client, Result>::Error>); /// Source client trait. pub trait SourceClient: Sized { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; /// Future that returns best block number. - type BestBlockNumberFuture: Future)>; + type BestBlockNumberFuture: Future>; /// Future that returns header by hash. - type HeaderByHashFuture: Future)>; + type HeaderByHashFuture: Future>; /// Future that returns header by number. - type HeaderByNumberFuture: Future)>; + type HeaderByNumberFuture: Future>; /// Future that returns extra data associated with header. - type HeaderExtraFuture: Future, P::Extra), Self::Error>)>; + type HeaderExtraFuture: Future, P::Extra)>>; + /// Future that returns data required to 'complete' header. + type HeaderCompletionFuture: Future< + Output = OwnedSourceFutureOutput, Option)>, + >; /// Get best block number. fn best_block_number(self) -> Self::BestBlockNumberFuture; @@ -59,6 +72,8 @@ pub trait SourceClient: Sized { fn header_by_number(self, number: P::Number) -> Self::HeaderByNumberFuture; /// Get extra data by header hash. fn header_extra(self, id: HeaderId, header: &P::Header) -> Self::HeaderExtraFuture; + /// Get completion data by header hash. + fn header_completion(self, id: HeaderId) -> Self::HeaderCompletionFuture; } /// Target client trait. @@ -66,13 +81,19 @@ pub trait TargetClient: Sized { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; /// Future that returns best header id. - type BestHeaderIdFuture: Future, Self::Error>)>; + type BestHeaderIdFuture: Future>>; /// Future that returns known header check result. - type IsKnownHeaderFuture: Future, bool), Self::Error>)>; + type IsKnownHeaderFuture: Future, bool)>>; /// Future that returns extra check result. - type RequiresExtraFuture: Future, bool), Self::Error>)>; + type RequiresExtraFuture: Future, bool)>>; /// Future that returns header submission result. - type SubmitHeadersFuture: Future>, Self::Error>)>; + type SubmitHeadersFuture: Future>>>; + /// Future that returns incomplete headers ids. + type IncompleteHeadersFuture: Future< + Output = OwnedTargetFutureOutput>>, + >; + /// Future that returns header completion result. + type CompleteHeadersFuture: Future>>; /// Returns ID of best header known to the target node. fn best_header_id(self) -> Self::BestHeaderIdFuture; @@ -82,23 +103,31 @@ pub trait TargetClient: Sized { fn requires_extra(self, header: &QueuedHeader

) -> Self::RequiresExtraFuture; /// Submit headers. fn submit_headers(self, headers: Vec>) -> Self::SubmitHeadersFuture; + /// Returns ID of headers that require to be 'completed' before children can be submitted. + fn incomplete_headers_ids(self) -> Self::IncompleteHeadersFuture; + /// Submit completion data for header. + fn complete_header( + self, + id: HeaderId, + completion: P::Completion, + ) -> Self::CompleteHeadersFuture; } /// Run headers synchronization. pub fn run( source_client: impl SourceClient

, - source_tick_ms: u64, + source_tick: Duration, target_client: impl TargetClient

, - target_tick_ms: u64, + target_tick: Duration, sync_params: HeadersSyncParams, ) { let mut local_pool = futures::executor::LocalPool::new(); - let mut progress_context = (std::time::Instant::now(), None, None); + let mut progress_context = (Instant::now(), None, None); local_pool.run_until(async move { let mut sync = crate::sync::HeadersSync::

::new(sync_params); let mut stall_countdown = None; - let mut last_update_time = std::time::Instant::now(); + let mut last_update_time = Instant::now(); let mut source_maybe_client = None; let mut source_best_block_number_required = false; @@ -106,29 +135,36 @@ pub fn run( let source_new_header_future = futures::future::Fuse::terminated(); let source_orphan_header_future = futures::future::Fuse::terminated(); let source_extra_future = futures::future::Fuse::terminated(); + let source_completion_future = futures::future::Fuse::terminated(); let source_go_offline_future = futures::future::Fuse::terminated(); - let source_tick_stream = interval(source_tick_ms).fuse(); + let source_tick_stream = interval(source_tick).fuse(); let mut target_maybe_client = None; let mut target_best_block_required = false; + let mut target_incomplete_headers_required = true; let target_best_block_future = target_client.best_header_id().fuse(); + let target_incomplete_headers_future = futures::future::Fuse::terminated(); let target_extra_check_future = futures::future::Fuse::terminated(); let target_existence_status_future = futures::future::Fuse::terminated(); let target_submit_header_future = futures::future::Fuse::terminated(); + let target_complete_header_future = futures::future::Fuse::terminated(); let target_go_offline_future = futures::future::Fuse::terminated(); - let target_tick_stream = interval(target_tick_ms).fuse(); + let target_tick_stream = interval(target_tick).fuse(); futures::pin_mut!( source_best_block_number_future, source_new_header_future, source_orphan_header_future, source_extra_future, + source_completion_future, source_go_offline_future, source_tick_stream, target_best_block_future, + target_incomplete_headers_future, target_extra_check_future, target_existence_status_future, target_submit_header_future, + target_complete_header_future, target_go_offline_future, target_tick_stream ); @@ -144,7 +180,7 @@ pub fn run( source_best_block_number, |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + |source_client| delay(CONNECTION_ERROR_DELAY, source_client), || format!("Error retrieving best header number from {}", P::SOURCE_NAME), ); }, @@ -155,7 +191,7 @@ pub fn run( source_new_header, |source_new_header| sync.headers_mut().header_response(source_new_header), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + |source_client| delay(CONNECTION_ERROR_DELAY, source_client), || format!("Error retrieving header from {} node", P::SOURCE_NAME), ); }, @@ -166,7 +202,7 @@ pub fn run( source_orphan_header, |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + |source_client| delay(CONNECTION_ERROR_DELAY, source_client), || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), ); }, @@ -177,10 +213,21 @@ pub fn run( source_extra, |(header, extra)| sync.headers_mut().extra_response(&header, extra), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY_MS, source_client), + |source_client| delay(CONNECTION_ERROR_DELAY, source_client), || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), ); }, + (source_client, source_completion) = source_completion_future => { + process_future_result( + &mut source_maybe_client, + source_client, + source_completion, + |(header, completion)| sync.headers_mut().completion_response(&header, completion), + &mut source_go_offline_future, + |source_client| delay(CONNECTION_ERROR_DELAY, source_client), + || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), + ); + }, source_client = source_go_offline_future => { source_maybe_client = Some(source_client); }, @@ -199,21 +246,20 @@ pub fn run( |target_best_block| { let head_updated = sync.target_best_header_response(target_best_block); if head_updated { - last_update_time = std::time::Instant::now(); + last_update_time = Instant::now(); } match head_updated { // IF head is updated AND there are still our transactions: // => restart stall countdown timer true if sync.headers().headers_in_status(HeaderStatus::Submitted) != 0 => - stall_countdown = Some(std::time::Instant::now()), + stall_countdown = Some(Instant::now()), // IF head is updated AND there are no our transactions: // => stop stall countdown timer true => stall_countdown = None, // IF head is not updated AND stall countdown is not yet completed // => do nothing false if stall_countdown - .map(|stall_countdown| std::time::Instant::now() - stall_countdown < - std::time::Duration::from_millis(STALL_SYNC_TIMEOUT_MS)) + .map(|stall_countdown| stall_countdown.elapsed() < STALL_SYNC_TIMEOUT) .unwrap_or(true) => (), // IF head is not updated AND stall countdown has completed @@ -231,10 +277,23 @@ pub fn run( } }, &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + |target_client| delay(CONNECTION_ERROR_DELAY, target_client), || format!("Error retrieving best known header from {} node", P::TARGET_NAME), ); }, + (target_client, incomplete_headers_ids) = target_incomplete_headers_future => { + target_incomplete_headers_required = false; + + process_future_result( + &mut target_maybe_client, + target_client, + incomplete_headers_ids, + |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), + &mut target_go_offline_future, + |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), + ); + }, (target_client, target_existence_status) = target_existence_status_future => { process_future_result( &mut target_maybe_client, @@ -244,7 +303,7 @@ pub fn run( .headers_mut() .maybe_orphan_response(&target_header, target_existence_status), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + |target_client| delay(CONNECTION_ERROR_DELAY, target_client), || format!("Error retrieving existence status from {} node", P::TARGET_NAME), ); }, @@ -255,10 +314,21 @@ pub fn run( target_submit_header_result, |submitted_headers| sync.headers_mut().headers_submitted(submitted_headers), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + |target_client| delay(CONNECTION_ERROR_DELAY, target_client), || format!("Error submitting headers to {} node", P::TARGET_NAME), ); }, + (target_client, target_complete_header_result) = target_complete_header_future => { + process_future_result( + &mut target_maybe_client, + target_client, + target_complete_header_result, + |completed_header| sync.headers_mut().header_completed(&completed_header), + &mut target_go_offline_future, + |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || format!("Error completing headers at {}", P::TARGET_NAME), + ); + }, (target_client, target_extra_check_result) = target_extra_check_future => { process_future_result( &mut target_maybe_client, @@ -268,7 +338,7 @@ pub fn run( .headers_mut() .maybe_extra_response(&header, extra_check_result), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY_MS, target_client), + |target_client| delay(CONNECTION_ERROR_DELAY, target_client), || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), ); }, @@ -277,6 +347,7 @@ pub fn run( }, _ = target_tick_stream.next() => { target_best_block_required = true; + target_incomplete_headers_required = true; }, } @@ -287,13 +358,26 @@ pub fn run( if let Some(target_client) = target_maybe_client.take() { // the priority is to: // 1) get best block - it stops us from downloading/submitting new blocks + we call it rarely; - // 2) check if we need extra data from source - it stops us from downloading/submitting new blocks; - // 3) check existence - it stops us from submitting new blocks; - // 4) submit header + // 2) get incomplete headers - it stops us from submitting new blocks + we call it rarely; + // 3) complete headers - it stops us from submitting new blocks; + // 4) check if we need extra data from source - it stops us from downloading/submitting new blocks; + // 5) check existence - it stops us from submitting new blocks; + // 6) submit header if target_best_block_required { log::debug!(target: "bridge", "Asking {} about best block", P::TARGET_NAME); target_best_block_future.set(target_client.best_header_id().fuse()); + } else if target_incomplete_headers_required { + log::debug!(target: "bridge", "Asking {} about incomplete headers", P::TARGET_NAME); + target_incomplete_headers_future.set(target_client.incomplete_headers_ids().fuse()); + } else if let Some((id, completion)) = sync.headers_mut().header_to_complete() { + log::debug!( + target: "bridge", + "Going to complete header: {:?}", + id, + ); + + target_complete_header_future.set(target_client.complete_header(id, completion.clone()).fuse()); } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeExtra) { log::debug!( target: "bridge", @@ -314,9 +398,9 @@ pub fn run( ); target_existence_status_future.set(target_client.is_known_header(parent_id).fuse()); - } else if let Some(headers) = sync.select_headers_to_submit( - last_update_time.elapsed() > std::time::Duration::from_millis(BACKUP_STALL_SYNC_TIMEOUT_MS), - ) { + } else if let Some(headers) = + sync.select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) + { let ids = match headers.len() { 1 => format!("{:?}", headers[0].id()), 2 => format!("[{:?}, {:?}]", headers[0].id(), headers[1].id()), @@ -335,7 +419,7 @@ pub fn run( // remember that we have submitted some headers if stall_countdown.is_none() { - stall_countdown = Some(std::time::Instant::now()); + stall_countdown = Some(Instant::now()); } } else { target_maybe_client = Some(target_client); @@ -346,13 +430,21 @@ pub fn run( if let Some(source_client) = source_maybe_client.take() { // the priority is to: // 1) get best block - it stops us from downloading new blocks + we call it rarely; - // 2) download extra data - it stops us from submitting new blocks; - // 3) download missing headers - it stops us from downloading/submitting new blocks; - // 4) downloading new headers + // 2) download completion data - it stops us from submitting new blocks; + // 3) download extra data - it stops us from submitting new blocks; + // 4) download missing headers - it stops us from downloading/submitting new blocks; + // 5) downloading new headers if source_best_block_number_required { log::debug!(target: "bridge", "Asking {} node about best block number", P::SOURCE_NAME); source_best_block_number_future.set(source_client.best_block_number().fuse()); + } else if let Some(id) = sync.headers_mut().incomplete_header() { + log::debug!( + target: "bridge", + "Retrieving completion data for header: {:?}", + id, + ); + source_completion_future.set(source_client.header_completion(id).fuse()); } else if let Some(header) = sync.headers().header(HeaderStatus::Extra) { let id = header.id(); log::debug!( @@ -402,15 +494,15 @@ pub fn run( } /// Future that resolves into given value after given timeout. -async fn delay(timeout_ms: u64, retval: T) -> T { - async_std::task::sleep(std::time::Duration::from_millis(timeout_ms)).await; +async fn delay(timeout: Duration, retval: T) -> T { + async_std::task::sleep(timeout).await; retval } /// Stream that emits item every `timeout_ms` milliseconds. -fn interval(timeout_ms: u64) -> impl futures::Stream { +fn interval(timeout: Duration) -> impl futures::Stream { futures::stream::unfold((), move |_| async move { - delay(timeout_ms, ()).await; + delay(timeout, ()).await; Some(((), ())) }) } @@ -447,14 +539,14 @@ fn process_future_result( /// Print synchronization progress. fn print_sync_progress( - progress_context: (std::time::Instant, Option, Option), + progress_context: (Instant, Option, Option), eth_sync: &crate::sync::HeadersSync

, -) -> (std::time::Instant, Option, Option) { +) -> (Instant, Option, Option) { let (prev_time, prev_best_header, prev_target_header) = progress_context; - let now_time = std::time::Instant::now(); + let now_time = Instant::now(); let (now_best_header, now_target_header) = eth_sync.status(); - let need_update = now_time - prev_time > std::time::Duration::from_secs(10) + let need_update = now_time - prev_time > Duration::from_secs(10) || match (prev_best_header, now_best_header) { (Some(prev_best_header), Some(now_best_header)) => { now_best_header.0.saturating_sub(prev_best_header) > 10.into() diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index 9b9712c739e13..8d68bd8759c31 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . /// Ethereum header Id. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] pub struct HeaderId(pub Number, pub Hash); /// Ethereum header synchronization status. @@ -33,6 +33,8 @@ pub enum HeaderStatus { Extra, /// Header is in Ready queue. Ready, + /// Header is in Incomplete queue. + Incomplete, /// Header has been recently submitted to the target node. Submitted, /// Header is known to the target node. @@ -61,6 +63,7 @@ pub trait HeadersSyncPipeline: Clone + Copy { + Copy + std::fmt::Debug + std::fmt::Display + + std::hash::Hash + std::ops::Add + std::ops::Sub + num_traits::Saturating @@ -68,10 +71,24 @@ pub trait HeadersSyncPipeline: Clone + Copy { + num_traits::One; /// Type of header that we're syncing. type Header: Clone + std::fmt::Debug + SourceHeader; - /// Type of extra data for the header that we're receiving from the source node. + /// Type of extra data for the header that we're receiving from the source node: + /// 1) extra data is required for some headers; + /// 2) target node may answer if it'll require extra data before header is submitted; + /// 3) extra data available since the header creation time; + /// 4) header and extra data are submitted in single transaction. + /// + /// Example: Ethereum transactions receipts. type Extra: Clone + std::fmt::Debug; - - /// Function used to convert from queued header to target header. + /// Type of data required to 'complete' header that we're receiving from the source node: + /// 1) completion data is required for some headers; + /// 2) target node can't answer if it'll require completion data before header is accepted; + /// 3) completion data may be generated after header generation; + /// 4) header and completion data are submitted in separate transactions. + /// + /// Example: Substrate GRANDPA justifications. + type Completion: Clone + std::fmt::Debug; + + /// Function used to estimate size of target-encoded header. fn estimate_size(source: &QueuedHeader) -> usize; } From 77679ee53eef606f866f07d6fb8a7752d907920e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 May 2020 02:26:01 +0000 Subject: [PATCH 0048/1210] Bump derive_more from 0.99.5 to 0.99.7 (#93) --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e768660441759..5065ea83bf78c 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" async-std = "1.0.1" clap = "2.3.3" ctrlc = "3.1.4" -derive_more = "0.99.5" +derive_more = "0.99.7" env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } From 303136c7d5b95872c46dd749e1854cbf49b51fd2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 May 2020 03:21:39 +0000 Subject: [PATCH 0049/1210] Bump ethereum-types from 0.9.1 to 0.9.2 (#95) --- modules/ethereum-contract/builtin/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 7a38e4497f1d3..864d0fbbdea7a 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" # General dependencies codec = { package = "parity-scale-codec", version = "1.0.0" } -ethereum-types = "0.9.1" +ethereum-types = "0.9.2" # Runtime/chain specific dependencies From 35e92436938c4d01db91f65350940ebd27f22157 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 May 2020 04:20:02 +0000 Subject: [PATCH 0050/1210] Bump clap from 2.33.0 to 2.33.1 (#94) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index de113a0f9e0b9..d0bc37073d537 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" ansi_term = "0.12" async-std = "1.0.1" async-stream = "0.2.0" -clap = { version = "2.33.0", features = ["yaml"] } +clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" ethabi = "12.0" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 5065ea83bf78c..f8bac8a06673d 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] async-std = "1.0.1" -clap = "2.3.3" +clap = "2.33.1" ctrlc = "3.1.4" derive_more = "0.99.7" env_logger = "0.7.1" From 19c950aaf4086f75c6b0044bb16fcf199dbd4237 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 18 May 2020 16:10:43 +0300 Subject: [PATCH 0051/1210] fix error processing (#97) --- relays/ethereum/src/substrate_client.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index e62c12e31b138..ec7c36443f075 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -235,13 +235,15 @@ pub async fn submit_signed_ethereum_headers( to_value(Bytes(transaction.encode())).map_err(|e| Error::RequestSerialization(e)), client ); - let (client, _) = call_rpc( - client, - "author_submitExtrinsic", - Params::Array(vec![encoded_transaction]), - |_| Ok(()), - ) - .await; + let (client, _) = bail_on_error!( + call_rpc( + client, + "author_submitExtrinsic", + Params::Array(vec![encoded_transaction]), + |_| Ok(()), + ) + .await + ); (client, Ok(ids)) } From 8de3dfe4863ab6955f71c8f9a3c61dc25c93ded1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 18 May 2020 17:11:46 +0300 Subject: [PATCH 0052/1210] removed unused files (#99) --- .../bin/node/cli/Cargo.toml | 128 --- .../bin/node/cli/src/chain_spec.rs | 465 -------- .../bin/node/runtime/Cargo.toml | 127 --- .../bin/node/runtime/src/lib.rs | 852 --------------- .../bin/node/testing/Cargo.toml | 32 - .../bin/node/testing/src/genesis.rs | 160 --- .../primitives/core/src/hasher.rs | 101 -- .../primitives/core/src/lib.rs | 328 ------ .../primitives/io/Cargo.toml | 40 - .../primitives/io/src/lib.rs | 990 ------------------ 10 files changed, 3223 deletions(-) delete mode 100644 modules/ethereum/other-runtime-components/bin/node/cli/Cargo.toml delete mode 100644 modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs delete mode 100644 modules/ethereum/other-runtime-components/bin/node/runtime/Cargo.toml delete mode 100644 modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs delete mode 100644 modules/ethereum/other-runtime-components/bin/node/testing/Cargo.toml delete mode 100644 modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs delete mode 100644 modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs delete mode 100644 modules/ethereum/other-runtime-components/primitives/core/src/lib.rs delete mode 100644 modules/ethereum/other-runtime-components/primitives/io/Cargo.toml delete mode 100644 modules/ethereum/other-runtime-components/primitives/io/src/lib.rs diff --git a/modules/ethereum/other-runtime-components/bin/node/cli/Cargo.toml b/modules/ethereum/other-runtime-components/bin/node/cli/Cargo.toml deleted file mode 100644 index 4df7401f23b9b..0000000000000 --- a/modules/ethereum/other-runtime-components/bin/node/cli/Cargo.toml +++ /dev/null @@ -1,128 +0,0 @@ -[package] -name = "node-cli" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Substrate node implementation in Rust." -build = "build.rs" -edition = "2018" -default-run = "substrate" - -[badges] -travis-ci = { repository = "paritytech/substrate", branch = "master" } -maintenance = { status = "actively-developed" } -is-it-maintained-issue-resolution = { repository = "paritytech/substrate" } -is-it-maintained-open-issues = { repository = "paritytech/substrate" } - -[[bin]] -name = "substrate" -path = "bin/main.rs" -required-features = ["cli"] - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -# third-party dependencies -codec = { package = "parity-scale-codec", version = "1.0.6" } -serde = { version = "1.0.102", features = ["derive"] } -futures01 = { package = "futures", version = "0.1.29" } -futures = { version = "0.3.1", features = ["compat"] } -hex-literal = "0.2.1" -jsonrpc-core = "14.0.3" -log = "0.4.8" -rand = "0.7.2" -structopt = "=0.3.7" - -# primitives -sp-authority-discovery = { version = "2.0.0", path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { version = "0.8", path = "../../../primitives/consensus/babe" } -grandpa-primitives = { version = "2.0.0", package = "sp-finality-grandpa", path = "../../../primitives/finality-grandpa" } -sp-core = { version = "2.0.0", path = "../../../primitives/core" } -sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } -sp-timestamp = { version = "2.0.0", default-features = false, path = "../../../primitives/timestamp" } -sp-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../primitives/finality-tracker" } -sp-inherents = { version = "2.0.0", path = "../../../primitives/inherents" } -sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } -sp-io = { version = "2.0.0", path = "../../../primitives/io" } -sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" } -sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa" } - -# client dependencies -sc-client-api = { version = "2.0.0", path = "../../../client/api" } -sc-client = { version = "2.0.0", path = "../../../client/" } -sc-chain-spec = { version = "2.0.0", path = "../../../client/chain-spec" } -sc-transaction-pool = { version = "2.0.0", path = "../../../client/transaction-pool" } -sp-transaction-pool = { version = "2.0.0", path = "../../../primitives/transaction-pool" } -sc-network = { version = "0.8", path = "../../../client/network" } -sc-consensus-babe = { version = "0.8", path = "../../../client/consensus/babe" } -grandpa = { version = "2.0.0", package = "sc-finality-grandpa", path = "../../../client/finality-grandpa" } -sc-client-db = { version = "2.0.0", default-features = false, path = "../../../client/db" } -sc-offchain = { version = "2.0.0", path = "../../../client/offchain" } -sc-rpc = { version = "2.0.0", path = "../../../client/rpc" } -sc-basic-authority = { version = "2.0.0", path = "../../../client/basic-authorship" } -sc-service = { version = "2.0.0", default-features = false, path = "../../../client/service" } -sc-telemetry = { version = "2.0.0", path = "../../../client/telemetry" } -sc-authority-discovery = { version = "2.0.0", path = "../../../client/authority-discovery" } - -# frame dependencies -pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } -pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" } -pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } -frame-system = { version = "2.0.0", path = "../../../frame/system" } -pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } -pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } -frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } -pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" } -pallet-authority-discovery = { version = "2.0.0", path = "../../../frame/authority-discovery" } - -# node-specific dependencies -node-runtime = { version = "2.0.0", path = "../runtime" } -node-rpc = { version = "2.0.0", path = "../rpc" } -node-primitives = { version = "2.0.0", path = "../primitives" } -node-executor = { version = "2.0.0", path = "../executor" } - -# CLI-specific dependencies -tokio = { version = "0.1.22", optional = true } -sc-cli = { version = "2.0.0", optional = true, path = "../../../client/cli" } -ctrlc = { version = "3.1.3", features = ["termination"], optional = true } -node-transaction-factory = { version = "2.0.0", optional = true, path = "../transaction-factory" } - -# WASM-specific dependencies -wasm-bindgen = { version = "0.2.57", optional = true } -wasm-bindgen-futures = { version = "0.4.7", optional = true } -browser-utils = { path = "../../../utils/browser", optional = true } - -[dev-dependencies] -sc-keystore = { version = "2.0.0", path = "../../../client/keystore" } -sc-consensus-babe = { version = "0.8", features = ["test-helpers"], path = "../../../client/consensus/babe" } -sc-service-test = { version = "2.0.0", path = "../../../client/service/test" } -futures = "0.3.1" -tempfile = "3.1.0" - -[build-dependencies] -sc-cli = { version = "2.0.0", package = "sc-cli", path = "../../../client/cli" } -build-script-utils = { version = "2.0.0", package = "substrate-build-script-utils", path = "../../../utils/build-script-utils" } -structopt = "=0.3.7" -vergen = "3.0.4" - -[features] -default = ["cli", "wasmtime"] -browser = [ - "browser-utils", - "wasm-bindgen", - "wasm-bindgen-futures", -] -cli = [ - "sc-cli", - "node-transaction-factory", - "tokio", - "ctrlc", - "sc-service/rocksdb", - "node-executor/wasmi-errno", -] -wasmtime = [ - "cli", - "node-executor/wasmtime", - "sc-cli/wasmtime", - "sc-service/wasmtime", -] diff --git a/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs b/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs deleted file mode 100644 index bb3e566509710..0000000000000 --- a/modules/ethereum/other-runtime-components/bin/node/cli/src/chain_spec.rs +++ /dev/null @@ -1,465 +0,0 @@ -// Copyright 2019-2020 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 . - -// Copyright 2018-2020 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 . - -//! Parity Bridges Common chain configurations. - -use sc_chain_spec::ChainSpecExtension; -use sp_core::{Pair, Public, crypto::UncheckedInto, sr25519}; -use serde::{Serialize, Deserialize}; -use node_runtime::{ - AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, ContractsConfig, CouncilConfig, DemocracyConfig, - GrandpaConfig, ImOnlineConfig, IndicesConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, - SystemConfig, TechnicalCommitteeConfig, WASM_BINARY, BridgeEthPoaConfig, -}; -use node_runtime::Block; -use node_runtime::constants::currency::*; -use sc_service; -use hex_literal::hex; -use sc_telemetry::TelemetryEndpoints; -use grandpa_primitives::{AuthorityId as GrandpaId}; -use sp_consensus_babe::{AuthorityId as BabeId}; -use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; -use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_runtime::{Perbill, traits::{Verify, IdentifyAccount}}; - -pub use node_primitives::{AccountId, Balance, Signature}; -pub use node_runtime::GenesisConfig; - -type AccountPublic = ::Signer; - -const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; - -/// Node `ChainSpec` extensions. -/// -/// Additional parameters for some Parity Bridges Common core modules, -/// customizable from the chain spec. -#[derive(Default, Clone, Serialize, Deserialize, ChainSpecExtension)] -#[serde(rename_all = "camelCase")] -pub struct Extensions { - /// Block numbers with known hashes. - pub fork_blocks: sc_client::ForkBlocks, - /// Known bad block hashes. - pub bad_blocks: sc_client::BadBlocks, -} - -/// Specialized `ChainSpec`. -pub type ChainSpec = sc_service::ChainSpec< - GenesisConfig, - Extensions, ->; -/// Flaming Fir testnet generator -pub fn flaming_fir_config() -> Result { - ChainSpec::from_json_bytes(&include_bytes!("../res/flaming-fir.json")[..]) -} - -fn session_keys( - grandpa: GrandpaId, - babe: BabeId, - im_online: ImOnlineId, - authority_discovery: AuthorityDiscoveryId, -) -> SessionKeys { - SessionKeys { grandpa, babe, im_online, authority_discovery } -} - -fn staging_testnet_config_genesis() -> GenesisConfig { - // stash, controller, session-key - // generated with secret: - // for i in 1 2 3 4 ; do for j in stash controller; do subkey inspect "$secret"/fir/$j/$i; done; done - // and - // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 inspect "$secret"//fir//$j//$i; done; done - - let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)> = vec![( - // 5Fbsd6WXDGiLTxunqeK5BATNiocfCqu9bS1yArVjCgeBLkVy - hex!["9c7a2ee14e565db0c69f78c7b4cd839fbf52b607d867e9e9c5a79042898a0d12"].into(), - // 5EnCiV7wSHeNhjW3FSUwiJNkcc2SBkPLn5Nj93FmbLtBjQUq - hex!["781ead1e2fa9ccb74b44c19d29cb2a7a4b5be3972927ae98cd3877523976a276"].into(), - // 5Fb9ayurnxnaXj56CjmyQLBiadfRCqUbL2VWNbbe1nZU6wiC - hex!["9becad03e6dcac03cee07edebca5475314861492cdfc96a2144a67bbe9699332"].unchecked_into(), - // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 - hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), - // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 - hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), - // 5EZaeQ8djPcq9pheJUhgerXQZt9YaHnMJpiHMRhwQeinqUW8 - hex!["6e7e4eb42cbd2e0ab4cae8708ce5509580b8c04d11f6758dbf686d50fe9f9106"].unchecked_into(), - ),( - // 5ERawXCzCWkjVq3xz1W5KGNtVx2VdefvZ62Bw1FEuZW4Vny2 - hex!["68655684472b743e456907b398d3a44c113f189e56d1bbfd55e889e295dfde78"].into(), - // 5Gc4vr42hH1uDZc93Nayk5G7i687bAQdHHc9unLuyeawHipF - hex!["c8dc79e36b29395413399edaec3e20fcca7205fb19776ed8ddb25d6f427ec40e"].into(), - // 5EockCXN6YkiNCDjpqqnbcqd4ad35nU4RmA1ikM4YeRN4WcE - hex!["7932cff431e748892fa48e10c63c17d30f80ca42e4de3921e641249cd7fa3c2f"].unchecked_into(), - // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ - hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), - // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ - hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), - // 5DhLtiaQd1L1LU9jaNeeu9HJkP6eyg3BwXA7iNMzKm7qqruQ - hex!["482dbd7297a39fa145c570552249c2ca9dd47e281f0c500c971b59c9dcdcd82e"].unchecked_into(), - ),( - // 5DyVtKWPidondEu8iHZgi6Ffv9yrJJ1NDNLom3X9cTDi98qp - hex!["547ff0ab649283a7ae01dbc2eb73932eba2fb09075e9485ff369082a2ff38d65"].into(), - // 5FeD54vGVNpFX3PndHPXJ2MDakc462vBCD5mgtWRnWYCpZU9 - hex!["9e42241d7cd91d001773b0b616d523dd80e13c6c2cab860b1234ef1b9ffc1526"].into(), - // 5E1jLYfLdUQKrFrtqoKgFrRvxM3oQPMbf6DfcsrugZZ5Bn8d - hex!["5633b70b80a6c8bb16270f82cca6d56b27ed7b76c8fd5af2986a25a4788ce440"].unchecked_into(), - // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH - hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), - // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH - hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), - // 5DhKqkHRkndJu8vq7pi2Q5S3DfftWJHGxbEUNH43b46qNspH - hex!["482a3389a6cf42d8ed83888cfd920fec738ea30f97e44699ada7323f08c3380a"].unchecked_into(), - ),( - // 5HYZnKWe5FVZQ33ZRJK1rG3WaLMztxWrrNDb1JRwaHHVWyP9 - hex!["f26cdb14b5aec7b2789fd5ca80f979cef3761897ae1f37ffb3e154cbcc1c2663"].into(), - // 5EPQdAQ39WQNLCRjWsCk5jErsCitHiY5ZmjfWzzbXDoAoYbn - hex!["66bc1e5d275da50b72b15de072a2468a5ad414919ca9054d2695767cf650012f"].into(), - // 5DMa31Hd5u1dwoRKgC4uvqyrdK45RHv3CpwvpUC1EzuwDit4 - hex!["3919132b851ef0fd2dae42a7e734fe547af5a6b809006100f48944d7fae8e8ef"].unchecked_into(), - // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x - hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), - // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x - hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), - // 5C4vDQxA8LTck2xJEy4Yg1hM9qjDt4LvTQaMo4Y8ne43aU6x - hex!["00299981a2b92f878baaf5dbeba5c18d4e70f2a1fcd9c61b32ea18daf38f4378"].unchecked_into(), - )]; - - // generated with secret: subkey inspect "$secret"/fir - let root_key: AccountId = hex![ - // 5Ff3iXP75ruzroPWRP2FYBHWnmGGBSb63857BgnzCoXNxfPo - "9ee5e5bdc0ec239eb164f865ecc345ce4c88e76ee002e0f7e318097347471809" - ].into(); - - let endowed_accounts: Vec = vec![root_key.clone()]; - - testnet_genesis( - initial_authorities, - root_key, - Some(endowed_accounts), - false, - ) -} - -/// Staging testnet config. -pub fn staging_testnet_config() -> ChainSpec { - let boot_nodes = vec![]; - ChainSpec::from_genesis( - "Staging Testnet", - "staging_testnet", - staging_testnet_config_genesis, - boot_nodes, - Some(TelemetryEndpoints::new(vec![(STAGING_TELEMETRY_URL.to_string(), 0)])), - None, - None, - Default::default(), - ) -} - -/// Helper function to generate a crypto pair from seed -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() -} - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId where - AccountPublic: From<::Public> -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// Helper function to generate stash, controller and session key from seed -pub fn get_authority_keys_from_seed(seed: &str) -> ( - AccountId, - AccountId, - GrandpaId, - BabeId, - ImOnlineId, - AuthorityDiscoveryId, -) { - ( - get_account_id_from_seed::(&format!("{}//stash", seed)), - get_account_id_from_seed::(seed), - get_from_seed::(seed), - get_from_seed::(seed), - get_from_seed::(seed), - get_from_seed::(seed), - ) -} - -/// Helper function to create GenesisConfig for testing -pub fn testnet_genesis( - initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId, AuthorityDiscoveryId)>, - root_key: AccountId, - endowed_accounts: Option>, - enable_println: bool, -) -> GenesisConfig { - let endowed_accounts: Vec = endowed_accounts.unwrap_or_else(|| { - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - ] - }); - let num_endowed_accounts = endowed_accounts.len(); - - const ENDOWMENT: Balance = 10_000_000 * DOLLARS; - const STASH: Balance = 100 * DOLLARS; - - GenesisConfig { - frame_system: Some(SystemConfig { - code: WASM_BINARY.to_vec(), - changes_trie_config: Default::default(), - }), - pallet_balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned() - .map(|k| (k, ENDOWMENT)) - .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) - .collect(), - vesting: vec![], - }), - pallet_indices: Some(IndicesConfig { - ids: endowed_accounts.iter().cloned() - .chain(initial_authorities.iter().map(|x| x.0.clone())) - .collect::>(), - }), - pallet_session: Some(SessionConfig { - keys: initial_authorities.iter().map(|x| { - (x.0.clone(), session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone())) - }).collect::>(), - }), - pallet_staking: Some(StakingConfig { - current_era: 0, - validator_count: initial_authorities.len() as u32 * 2, - minimum_validator_count: initial_authorities.len() as u32, - stakers: initial_authorities.iter().map(|x| { - (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator) - }).collect(), - invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(), - slash_reward_fraction: Perbill::from_percent(10), - .. Default::default() - }), - pallet_democracy: Some(DemocracyConfig::default()), - pallet_collective_Instance1: Some(CouncilConfig { - members: endowed_accounts.iter().cloned() - .collect::>()[..(num_endowed_accounts + 1) / 2].to_vec(), - phantom: Default::default(), - }), - pallet_collective_Instance2: Some(TechnicalCommitteeConfig { - members: endowed_accounts.iter().cloned() - .collect::>()[..(num_endowed_accounts + 1) / 2].to_vec(), - phantom: Default::default(), - }), - pallet_contracts: Some(ContractsConfig { - current_schedule: pallet_contracts::Schedule { - enable_println, // this should only be enabled on development chains - ..Default::default() - }, - gas_price: 1 * MILLICENTS, - }), - pallet_sudo: Some(SudoConfig { - key: root_key, - }), - pallet_babe: Some(BabeConfig { - authorities: vec![], - }), - pallet_im_online: Some(ImOnlineConfig { - keys: vec![], - }), - pallet_authority_discovery: Some(AuthorityDiscoveryConfig { - keys: vec![], - }), - pallet_grandpa: Some(GrandpaConfig { - authorities: vec![], - }), - pallet_membership_Instance1: Some(Default::default()), - pallet_treasury: Some(Default::default()), - // here comes configuration for Kovan chain - bridge_eth_poa: Some(BridgeEthPoaConfig { - initial_header: sp_bridge_eth_poa::Header { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), - extra_data: vec![], - state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), - receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 6000000.into(), - difficulty: 131072.into(), - seal: vec![ - vec![128].into(), - vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), - ], - }, - initial_difficulty: 0.into(), - initial_validators: vec![ - [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, - 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), - [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, - 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), - [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, - 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), - [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, - 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), - [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, - 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), - [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, - 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), - [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, - 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), - [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, - 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), - [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, - 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), - ], - }), - } -} - -fn development_config_genesis() -> GenesisConfig { - testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - None, - true, - ) -} - -/// Development config (single validator Alice) -pub fn development_config() -> ChainSpec { - ChainSpec::from_genesis( - "Development", - "dev", - development_config_genesis, - vec![], - None, - None, - None, - Default::default(), - ) -} - -fn local_testnet_genesis() -> GenesisConfig { - testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), - ], - get_account_id_from_seed::("Alice"), - None, - false, - ) -} - -/// Local testnet config (multivalidator Alice + Bob) -pub fn local_testnet_config() -> ChainSpec { - ChainSpec::from_genesis( - "Local Testnet", - "local_testnet", - local_testnet_genesis, - vec![], - None, - None, - None, - Default::default(), - ) -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::service::{new_full, new_light}; - use sc_service_test; - - fn local_testnet_genesis_instant_single() -> GenesisConfig { - testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - ], - get_account_id_from_seed::("Alice"), - None, - false, - ) - } - - /// Local testnet config (single validator - Alice) - pub fn integration_test_config_with_single_authority() -> ChainSpec { - ChainSpec::from_genesis( - "Integration Test", - "test", - local_testnet_genesis_instant_single, - vec![], - None, - None, - None, - Default::default(), - ) - } - - /// Local testnet config (multivalidator Alice + Bob) - pub fn integration_test_config_with_two_authorities() -> ChainSpec { - ChainSpec::from_genesis( - "Integration Test", - "test", - local_testnet_genesis, - vec![], - None, - None, - None, - Default::default(), - ) - } - - #[test] - #[ignore] - fn test_connectivity() { - sc_service_test::connectivity( - integration_test_config_with_two_authorities(), - |config| new_full(config), - |config| new_light(config), - ); - } -} diff --git a/modules/ethereum/other-runtime-components/bin/node/runtime/Cargo.toml b/modules/ethereum/other-runtime-components/bin/node/runtime/Cargo.toml deleted file mode 100644 index 7ca943621b28d..0000000000000 --- a/modules/ethereum/other-runtime-components/bin/node/runtime/Cargo.toml +++ /dev/null @@ -1,127 +0,0 @@ -[package] -name = "node-runtime" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" -build = "build.rs" - -[dependencies] -# third-party dependencies -codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false, features = ["derive"] } -integer-sqrt = { version = "0.1.2" } -safe-mix = { version = "1.0", default-features = false } -rustc-hex = { version = "2.0", optional = true } -serde = { version = "1.0.102", optional = true } - -# primitives -sp-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../primitives/authority-discovery" } -sp-consensus-babe = { version = "0.8", default-features = false, path = "../../../primitives/consensus/babe" } -sp-block-builder = { path = "../../../primitives/block-builder", default-features = false} -sp-inherents = { version = "2.0.0", default-features = false, path = "../../../primitives/inherents" } -node-primitives = { version = "2.0.0", default-features = false, path = "../primitives" } -sp-offchain = { version = "2.0.0", default-features = false, path = "../../../primitives/offchain" } -sp-core = { version = "2.0.0", default-features = false, path = "../../../primitives/core" } -sp-std = { version = "2.0.0", default-features = false, path = "../../../primitives/std" } -sp-api = { version = "2.0.0", default-features = false, path = "../../../primitives/api" } -sp-runtime = { version = "2.0.0", default-features = false, path = "../../../primitives/runtime" } -sp-staking = { version = "2.0.0", default-features = false, path = "../../../primitives/staking" } -sp-keyring = { version = "2.0.0", optional = true, path = "../../../primitives/keyring" } -sp-session = { version = "2.0.0", default-features = false, path = "../../../primitives/session" } -sp-transaction-pool = { version = "2.0.0", default-features = false, path = "../../../primitives/transaction-pool" } -sp-version = { version = "2.0.0", default-features = false, path = "../../../primitives/version" } -sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa", default-features = false } - -# frame dependencies -frame-executive = { version = "2.0.0", default-features = false, path = "../../../frame/executive" } -frame-support = { version = "2.0.0", default-features = false, path = "../../../frame/support" } -frame-system = { version = "2.0.0", default-features = false, path = "../../../frame/system" } -frame-system-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } -pallet-authority-discovery = { version = "2.0.0", default-features = false, path = "../../../frame/authority-discovery" } -pallet-authorship = { version = "2.0.0", default-features = false, path = "../../../frame/authorship" } -pallet-babe = { version = "2.0.0", default-features = false, path = "../../../frame/babe" } -pallet-balances = { version = "2.0.0", default-features = false, path = "../../../frame/balances" } -pallet-collective = { version = "2.0.0", default-features = false, path = "../../../frame/collective" } -pallet-contracts = { version = "2.0.0", default-features = false, path = "../../../frame/contracts" } -pallet-contracts-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/contracts/rpc/runtime-api/" } -pallet-democracy = { version = "2.0.0", default-features = false, path = "../../../frame/democracy" } -pallet-elections-phragmen = { version = "2.0.0", default-features = false, path = "../../../frame/elections-phragmen" } -pallet-finality-tracker = { version = "2.0.0", default-features = false, path = "../../../frame/finality-tracker" } -pallet-grandpa = { version = "2.0.0", default-features = false, path = "../../../frame/grandpa" } -pallet-im-online = { version = "2.0.0", default-features = false, path = "../../../frame/im-online" } -pallet-indices = { version = "2.0.0", default-features = false, path = "../../../frame/indices" } -pallet-membership = { version = "2.0.0", default-features = false, path = "../../../frame/membership" } -pallet-nicks = { version = "2.0.0", default-features = false, path = "../../../frame/nicks" } -pallet-offences = { version = "2.0.0", default-features = false, path = "../../../frame/offences" } -pallet-randomness-collective-flip = { version = "2.0.0", default-features = false, path = "../../../frame/randomness-collective-flip" } -pallet-session = { version = "2.0.0", features = ["historical"], path = "../../../frame/session", default-features = false } -pallet-staking = { version = "2.0.0", features = ["migrate"], path = "../../../frame/staking", default-features = false } -pallet-staking-reward-curve = { version = "2.0.0", path = "../../../frame/staking/reward-curve" } -pallet-sudo = { version = "2.0.0", default-features = false, path = "../../../frame/sudo" } -pallet-timestamp = { version = "2.0.0", default-features = false, path = "../../../frame/timestamp" } -pallet-treasury = { version = "2.0.0", default-features = false, path = "../../../frame/treasury" } -pallet-utility = { version = "2.0.0", default-features = false, path = "../../../frame/utility" } -pallet-transaction-payment = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment" } -pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } -# TODO: Update this -bridge-eth-poa = { package = "pallet-bridge-eth-poa", path = "../../../frame/bridge-eth-poa", default-features = false } - -[build-dependencies] -wasm-builder-runner = { version = "1.0.4", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" } - -[dev-dependencies] -sp-io = { version = "2.0.0", path = "../../../primitives/io" } - -[features] -default = ["std"] -std = [ - "sp-authority-discovery/std", - "pallet-authority-discovery/std", - "pallet-authorship/std", - "sp-consensus-babe/std", - "pallet-babe/std", - "pallet-balances/std", - "sp-block-builder/std", - "sp-bridge-eth-poa/std", - "bridge-eth-poa/std", # TODO: Update this - "codec/std", - "pallet-collective/std", - "pallet-contracts-rpc-runtime-api/std", - "pallet-contracts/std", - "pallet-democracy/std", - "pallet-elections-phragmen/std", - "frame-executive/std", - "pallet-finality-tracker/std", - "pallet-grandpa/std", - "pallet-im-online/std", - "pallet-indices/std", - "sp-inherents/std", - "pallet-membership/std", - "pallet-nicks/std", - "node-primitives/std", - "sp-offchain/std", - "pallet-offences/std", - "sp-core/std", - "pallet-randomness-collective-flip/std", - "sp-std/std", - "rustc-hex", - "safe-mix/std", - "serde", - "pallet-session/std", - "sp-api/std", - "sp-runtime/std", - "sp-staking/std", - "pallet-staking/std", - "sp-keyring", - "sp-session/std", - "pallet-sudo/std", - "frame-support/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-treasury/std", - "sp-transaction-pool/std", - "pallet-utility/std", - "sp-version/std", -] diff --git a/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs b/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs deleted file mode 100644 index d050953a4c53e..0000000000000 --- a/modules/ethereum/other-runtime-components/bin/node/runtime/src/lib.rs +++ /dev/null @@ -1,852 +0,0 @@ -// Copyright 2019-2020 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 . - -// Copyright 2018-2020 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 . - -//! The Parity Bridges Common runtime. This can be compiled with ``#[no_std]`, ready for Wasm. - -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit="256"] - -use sp_std::prelude::*; -use frame_support::{ - construct_runtime, parameter_types, debug, - weights::Weight, - traits::{SplitTwoWays, Currency, Randomness}, -}; -use sp_core::u32_trait::{_1, _2, _3, _4}; -use node_primitives::{AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, Moment, Signature}; -use sp_api::impl_runtime_apis; -use sp_runtime::{ - Permill, Perbill, Percent, ApplyExtrinsicResult, impl_opaque_keys, generic, create_runtime_str -}; -use sp_runtime::curve::PiecewiseLinear; -use sp_runtime::transaction_validity::TransactionValidity; -use sp_runtime::traits::{ - self, BlakeTwo256, Block as BlockT, StaticLookup, SaturatedConversion, - OpaqueKeys, -}; -use sp_version::RuntimeVersion; -#[cfg(any(feature = "std", test))] -use sp_version::NativeVersion; -use sp_core::OpaqueMetadata; -use pallet_grandpa::AuthorityList as GrandpaAuthorityList; -use pallet_grandpa::fg_primitives; -use pallet_im_online::sr25519::{AuthorityId as ImOnlineId}; -use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; -use pallet_contracts_rpc_runtime_api::ContractExecResult; -use frame_system::offchain::TransactionSubmitter; -use sp_inherents::{InherentData, CheckInherentsResult}; - -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use pallet_timestamp::Call as TimestampCall; -pub use pallet_balances::Call as BalancesCall; -pub use pallet_contracts::Gas; -pub use frame_support::StorageValue; -pub use pallet_staking::StakerStatus; -pub use bridge_eth_poa::Call as BridgeEthPoaCall; // TODO: Update name - -/// Implementations of some helper traits passed into runtime modules as associated types. -pub mod impls; -use impls::{CurrencyToVoteHandler, Author, LinearWeightToFee, TargetedFeeAdjustment}; - -/// Constant values used within the runtime. -pub mod constants; -use constants::{time::*, currency::*}; - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -/// Runtime version. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node"), - impl_name: create_runtime_str!("substrate-node"), - authoring_version: 10, - // Per convention: if the runtime behavior changes, increment spec_version - // and set impl_version to equal spec_version. If only runtime - // implementation changes and behavior does not, then leave spec_version as - // is and increment impl_version. - spec_version: 202, - impl_version: 202, - apis: RUNTIME_API_VERSIONS, -}; - -/// Native version. -#[cfg(any(feature = "std", test))] -pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } -} - -type NegativeImbalance = >::NegativeImbalance; - -pub type DealWithFees = SplitTwoWays< - Balance, - NegativeImbalance, - _4, Treasury, // 4 parts (80%) goes to the treasury. - _1, Author, // 1 part (20%) goes to the block author. ->; - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 1_000_000_000; - pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; - pub const Version: RuntimeVersion = VERSION; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); -} - -impl frame_system::Trait for Runtime { - type Origin = Origin; - type Call = Call; - type Index = Index; - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = Indices; - type Header = generic::Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = Version; - type ModuleToIndex = ModuleToIndex; -} - -parameter_types! { - // One storage item; value is size 4+4+16+32 bytes = 56 bytes. - pub const MultisigDepositBase: Balance = 30 * CENTS; - // Additional storage item size of 32 bytes. - pub const MultisigDepositFactor: Balance = 5 * CENTS; - pub const MaxSignatories: u16 = 100; -} - -impl pallet_utility::Trait for Runtime { - type Event = Event; - type Call = Call; - type Currency = Balances; - type MultisigDepositBase = MultisigDepositBase; - type MultisigDepositFactor = MultisigDepositFactor; - type MaxSignatories = MaxSignatories; -} - -parameter_types! { - pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS; - pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; -} - -impl pallet_babe::Trait for Runtime { - type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; - type EpochChangeTrigger = pallet_babe::ExternalTrigger; -} - -impl pallet_indices::Trait for Runtime { - type AccountIndex = AccountIndex; - type IsDeadAccount = Balances; - type ResolveHint = pallet_indices::SimpleResolveHint; - type Event = Event; -} - -parameter_types! { - pub const ExistentialDeposit: Balance = 1 * DOLLARS; - pub const TransferFee: Balance = 1 * CENTS; - pub const CreationFee: Balance = 1 * CENTS; -} - -impl pallet_balances::Trait for Runtime { - type Balance = Balance; - type OnFreeBalanceZero = ((Staking, Contracts), Session); - type OnReapAccount = System; - type OnNewAccount = Indices; - type Event = Event; - type DustRemoval = (); - type TransferPayment = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; -} - -parameter_types! { - pub const TransactionBaseFee: Balance = 1 * CENTS; - pub const TransactionByteFee: Balance = 10 * MILLICENTS; - // setting this to zero will disable the weight fee. - pub const WeightFeeCoefficient: Balance = 1_000; - // for a sane configuration, this should always be less than `AvailableBlockRatio`. - pub const TargetBlockFullness: Perbill = Perbill::from_percent(25); -} - -impl pallet_transaction_payment::Trait for Runtime { - type Currency = Balances; - type OnTransactionPayment = DealWithFees; - type TransactionBaseFee = TransactionBaseFee; - type TransactionByteFee = TransactionByteFee; - type WeightToFee = LinearWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -parameter_types! { - pub const MinimumPeriod: Moment = SLOT_DURATION / 2; -} -impl pallet_timestamp::Trait for Runtime { - type Moment = Moment; - type OnTimestampSet = Babe; - type MinimumPeriod = MinimumPeriod; -} - -parameter_types! { - pub const UncleGenerations: BlockNumber = 5; -} - -impl pallet_authorship::Trait for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type UncleGenerations = UncleGenerations; - type FilterUncle = (); - type EventHandler = (Staking, ImOnline); -} - -impl_opaque_keys! { - pub struct SessionKeys { - pub grandpa: Grandpa, - pub babe: Babe, - pub im_online: ImOnline, - pub authority_discovery: AuthorityDiscovery, - } -} - -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); -} - -impl pallet_session::Trait for Runtime { - type OnSessionEnding = Staking; - type SessionHandler = ::KeyTypeIdProviders; - type ShouldEndSession = Babe; - type Event = Event; - type Keys = SessionKeys; - type ValidatorId = ::AccountId; - type ValidatorIdOf = pallet_staking::StashOf; - type SelectInitialValidators = Staking; - type DisabledValidatorsThreshold = DisabledValidatorsThreshold; -} - -impl pallet_session::historical::Trait for Runtime { - type FullIdentification = pallet_staking::Exposure; - type FullIdentificationOf = pallet_staking::ExposureOf; -} - -pallet_staking_reward_curve::build! { - const REWARD_CURVE: PiecewiseLinear<'static> = curve!( - min_inflation: 0_025_000, - max_inflation: 0_100_000, - ideal_stake: 0_500_000, - falloff: 0_050_000, - max_piece_count: 40, - test_precision: 0_005_000, - ); -} - -parameter_types! { - pub const SessionsPerEra: sp_staking::SessionIndex = 6; - pub const BondingDuration: pallet_staking::EraIndex = 24 * 28; - pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. - pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; -} - -impl pallet_staking::Trait for Runtime { - type Currency = Balances; - type Time = Timestamp; - type CurrencyToVote = CurrencyToVoteHandler; - type RewardRemainder = Treasury; - type Event = Event; - type Slash = Treasury; // send the slashed funds to the treasury. - type Reward = (); // rewards are minted from the void - type SessionsPerEra = SessionsPerEra; - type BondingDuration = BondingDuration; - type SlashDeferDuration = SlashDeferDuration; - /// A super-majority of the council can cancel the slash. - type SlashCancelOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; - type SessionInterface = Self; - type RewardCurve = RewardCurve; -} - -parameter_types! { - pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - pub const EmergencyVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; - pub const MinimumDeposit: Balance = 100 * DOLLARS; - pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; - pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; - // One cent: $10,000 / MB - pub const PreimageByteDeposit: Balance = 1 * CENTS; -} - -impl pallet_democracy::Trait for Runtime { - type Proposal = Call; - type Event = Event; - type Currency = Balances; - type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type VotingPeriod = VotingPeriod; - type EmergencyVotingPeriod = EmergencyVotingPeriod; - type MinimumDeposit = MinimumDeposit; - /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>; - /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; - /// A unanimous council can have the next scheduled referendum be a straight default-carries - /// (NTB) vote. - type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast<_1, _1, AccountId, CouncilCollective>; - /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote - /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, TechnicalCollective>; - // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = pallet_collective::EnsureProportionAtLeast<_2, _3, AccountId, CouncilCollective>; - // Any single technical committee member may veto a coming council proposal, however they can - // only do it once and it lasts only for the cooloff period. - type VetoOrigin = pallet_collective::EnsureMember; - type CooloffPeriod = CooloffPeriod; - type PreimageByteDeposit = PreimageByteDeposit; - type Slash = Treasury; -} - -type CouncilCollective = pallet_collective::Instance1; -impl pallet_collective::Trait for Runtime { - type Origin = Origin; - type Proposal = Call; - type Event = Event; -} - -parameter_types! { - pub const CandidacyBond: Balance = 10 * DOLLARS; - pub const VotingBond: Balance = 1 * DOLLARS; - pub const TermDuration: BlockNumber = 7 * DAYS; - pub const DesiredMembers: u32 = 13; - pub const DesiredRunnersUp: u32 = 7; -} - -impl pallet_elections_phragmen::Trait for Runtime { - type Event = Event; - type Currency = Balances; - type CurrencyToVote = CurrencyToVoteHandler; - type CandidacyBond = CandidacyBond; - type VotingBond = VotingBond; - type TermDuration = TermDuration; - type DesiredMembers = DesiredMembers; - type DesiredRunnersUp = DesiredRunnersUp; - type LoserCandidate = (); - type BadReport = (); - type KickedMember = (); - type ChangeMembers = Council; -} - -type TechnicalCollective = pallet_collective::Instance2; -impl pallet_collective::Trait for Runtime { - type Origin = Origin; - type Proposal = Call; - type Event = Event; -} - -impl pallet_membership::Trait for Runtime { - type Event = Event; - type AddOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type RemoveOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type SwapOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type ResetOrigin = pallet_collective::EnsureProportionMoreThan<_1, _2, AccountId, CouncilCollective>; - type MembershipInitialized = TechnicalCommittee; - type MembershipChanged = TechnicalCommittee; -} - -parameter_types! { - pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: Balance = 1 * DOLLARS; - pub const SpendPeriod: BlockNumber = 1 * DAYS; - pub const Burn: Permill = Permill::from_percent(50); - pub const TipCountdown: BlockNumber = 1 * DAYS; - pub const TipFindersFee: Percent = Percent::from_percent(20); - pub const TipReportDepositBase: Balance = 1 * DOLLARS; - pub const TipReportDepositPerByte: Balance = 1 * CENTS; -} - -impl pallet_treasury::Trait for Runtime { - type Currency = Balances; - type ApproveOrigin = pallet_collective::EnsureMembers<_4, AccountId, CouncilCollective>; - type RejectOrigin = pallet_collective::EnsureMembers<_2, AccountId, CouncilCollective>; - type Event = Event; - type ProposalRejection = (); - type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type SpendPeriod = SpendPeriod; - type Burn = Burn; - type Tippers = Elections; - type TipCountdown = TipCountdown; - type TipFindersFee = TipFindersFee; - type TipReportDepositBase = TipReportDepositBase; - type TipReportDepositPerByte = TipReportDepositPerByte; -} - -parameter_types! { - pub const ContractTransferFee: Balance = 1 * CENTS; - pub const ContractCreationFee: Balance = 1 * CENTS; - pub const ContractTransactionBaseFee: Balance = 1 * CENTS; - pub const ContractTransactionByteFee: Balance = 10 * MILLICENTS; - pub const ContractFee: Balance = 1 * CENTS; - pub const TombstoneDeposit: Balance = 1 * DOLLARS; - pub const RentByteFee: Balance = 1 * DOLLARS; - pub const RentDepositOffset: Balance = 1000 * DOLLARS; - pub const SurchargeReward: Balance = 150 * DOLLARS; -} - -impl pallet_contracts::Trait for Runtime { - type Currency = Balances; - type Time = Timestamp; - type Randomness = RandomnessCollectiveFlip; - type Call = Call; - type Event = Event; - type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminator; - type ComputeDispatchFee = pallet_contracts::DefaultDispatchFeeComputor; - type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter; - type GasPayment = (); - type RentPayment = (); - type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap; - type TombstoneDeposit = TombstoneDeposit; - type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset; - type RentByteFee = RentByteFee; - type RentDepositOffset = RentDepositOffset; - type SurchargeReward = SurchargeReward; - type TransferFee = ContractTransferFee; - type CreationFee = ContractCreationFee; - type TransactionBaseFee = ContractTransactionBaseFee; - type TransactionByteFee = ContractTransactionByteFee; - type ContractFee = ContractFee; - type CallBaseFee = pallet_contracts::DefaultCallBaseFee; - type InstantiateBaseFee = pallet_contracts::DefaultInstantiateBaseFee; - type MaxDepth = pallet_contracts::DefaultMaxDepth; - type MaxValueSize = pallet_contracts::DefaultMaxValueSize; - type BlockGasLimit = pallet_contracts::DefaultBlockGasLimit; -} - -impl pallet_sudo::Trait for Runtime { - type Event = Event; - type Proposal = Call; -} - -/// A runtime transaction submitter. -pub type SubmitTransaction = TransactionSubmitter; - -parameter_types! { - pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _; -} - -impl pallet_im_online::Trait for Runtime { - type AuthorityId = ImOnlineId; - type Call = Call; - type Event = Event; - type SubmitTransaction = SubmitTransaction; - type ReportUnresponsiveness = Offences; - type SessionDuration = SessionDuration; -} - -impl pallet_offences::Trait for Runtime { - type Event = Event; - type IdentificationTuple = pallet_session::historical::IdentificationTuple; - type OnOffenceHandler = Staking; -} - -impl pallet_authority_discovery::Trait for Runtime {} - -impl pallet_grandpa::Trait for Runtime { - type Event = Event; -} - -parameter_types! { - pub const WindowSize: BlockNumber = 101; - pub const ReportLatency: BlockNumber = 1000; -} - -impl pallet_finality_tracker::Trait for Runtime { - type OnFinalizationStalled = Grandpa; - type WindowSize = WindowSize; - type ReportLatency = ReportLatency; -} - -parameter_types! { - pub const ReservationFee: Balance = 1 * DOLLARS; - pub const MinLength: usize = 3; - pub const MaxLength: usize = 16; -} - -impl pallet_nicks::Trait for Runtime { - type Event = Event; - type Currency = Balances; - type ReservationFee = ReservationFee; - type Slashed = Treasury; - type ForceOrigin = pallet_collective::EnsureMember; - type MinLength = MinLength; - type MaxLength = MaxLength; -} - -impl frame_system::offchain::CreateTransaction for Runtime { - type Public = ::Signer; - type Signature = Signature; - - fn create_transaction>( - call: Call, - public: Self::Public, - account: AccountId, - index: Index, - ) -> Option<(Call, ::SignaturePayload)> { - // take the biggest period possible. - let period = BlockHashCount::get() - .checked_next_power_of_two() - .map(|c| c / 2) - .unwrap_or(2) as u64; - let current_block = System::block_number() - .saturated_into::() - // The `System::block_number` is initialized with `n+1`, - // so the actual block number is `n`. - .saturating_sub(1); - let tip = 0; - let extra: SignedExtra = ( - frame_system::CheckVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), - frame_system::CheckNonce::::from(index), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(tip), - Default::default(), - ); - let raw_payload = SignedPayload::new(call, extra).map_err(|e| { - debug::warn!("Unable to create signed payload: {:?}", e); - }).ok()?; - let signature = TSigner::sign(public, &raw_payload)?; - let address = Indices::unlookup(account); - let (call, extra, _) = raw_payload.deconstruct(); - Some((call, (address, signature, extra))) - } -} - -impl bridge_eth_poa::Trait for Runtime { - type OnHeadersSubmitted = (); -} - -construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = node_primitives::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: frame_system::{Module, Call, Storage, Config, Event}, - Utility: pallet_utility::{Module, Call, Storage, Event}, - Babe: pallet_babe::{Module, Call, Storage, Config, Inherent(Timestamp)}, - Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Authorship: pallet_authorship::{Module, Call, Storage, Inherent}, - Indices: pallet_indices, - Balances: pallet_balances, - TransactionPayment: pallet_transaction_payment::{Module, Storage}, - Staking: pallet_staking, - Session: pallet_session::{Module, Call, Storage, Event, Config}, - Democracy: pallet_democracy::{Module, Call, Storage, Config, Event}, - Council: pallet_collective::::{Module, Call, Storage, Origin, Event, Config}, - TechnicalCommittee: pallet_collective::::{Module, Call, Storage, Origin, Event, Config}, - Elections: pallet_elections_phragmen::{Module, Call, Storage, Event}, - TechnicalMembership: pallet_membership::::{Module, Call, Storage, Event, Config}, - FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent}, - Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, - Treasury: pallet_treasury::{Module, Call, Storage, Config, Event}, - Contracts: pallet_contracts, - Sudo: pallet_sudo, - ImOnline: pallet_im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, - AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config}, - Offences: pallet_offences::{Module, Call, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, - Nicks: pallet_nicks::{Module, Call, Storage, Event}, - BridgeEthPoa: bridge_eth_poa::{Module, Call, Config}, // TODO: Update this - } -); - -/// The address format for describing accounts. -pub type Address = ::Source; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - frame_system::CheckVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - pallet_contracts::CheckBlockGasLimit, -); -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; -/// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; -/// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; -/// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive, Runtime, AllModules>; - -impl_runtime_apis! { - impl sp_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl sp_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() - } - } - - impl sp_block_builder::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { - Executive::apply_extrinsic(extrinsic) - } - - fn finalize_block() -> ::Header { - Executive::finalize_block() - } - - fn inherent_extrinsics(data: InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult { - data.check_extrinsics(&block) - } - - fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed() - } - } - - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction(tx: ::Extrinsic) -> TransactionValidity { - Executive::validate_transaction(tx) - } - } - - impl sp_offchain::OffchainWorkerApi for Runtime { - fn offchain_worker(header: &::Header) { - Executive::offchain_worker(header) - } - } - - impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_authorities() -> GrandpaAuthorityList { - Grandpa::grandpa_authorities() - } - } - - impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { - // The choice of `c` parameter (where `1 - c` represents the - // probability of a slot being empty), is done in accordance to the - // slot duration and expected target block time, for safely - // resisting network delays of maximum two seconds. - // - sp_consensus_babe::BabeConfiguration { - slot_duration: Babe::slot_duration(), - epoch_length: EpochDuration::get(), - c: PRIMARY_PROBABILITY, - genesis_authorities: Babe::authorities(), - randomness: Babe::randomness(), - secondary_slots: true, - } - } - } - - impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { - fn authorities() -> Vec { - AuthorityDiscovery::authorities() - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Index { - System::account_nonce(account) - } - } - - impl pallet_contracts_rpc_runtime_api::ContractsApi for Runtime { - fn call( - origin: AccountId, - dest: AccountId, - value: Balance, - gas_limit: u64, - input_data: Vec, - ) -> ContractExecResult { - let exec_result = Contracts::bare_call( - origin, - dest.into(), - value, - gas_limit, - input_data, - ); - match exec_result { - Ok(v) => ContractExecResult::Success { - status: v.status, - data: v.data, - }, - Err(_) => ContractExecResult::Error, - } - } - - fn get_storage( - address: AccountId, - key: [u8; 32], - ) -> pallet_contracts_rpc_runtime_api::GetStorageResult { - Contracts::get_storage(address, key).map_err(|rpc_err| { - use pallet_contracts::GetStorageError; - use pallet_contracts_rpc_runtime_api::{GetStorageError as RpcGetStorageError}; - /// Map the contract error into the RPC layer error. - match rpc_err { - GetStorageError::ContractDoesntExist => RpcGetStorageError::ContractDoesntExist, - GetStorageError::IsTombstone => RpcGetStorageError::IsTombstone, - } - }) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< - Block, - Balance, - UncheckedExtrinsic, - > for Runtime { - fn query_info(uxt: UncheckedExtrinsic, len: u32) -> RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - } - - impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - SessionKeys::generate(seed) - } - } - - impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { - fn best_block() -> (u64, sp_bridge_eth_poa::H256) { - BridgeEthPoa::best_block() - } - - fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { - BridgeEthPoa::is_import_requires_receipts(header) - } - - fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { - BridgeEthPoa::is_known_block(hash) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use frame_system::offchain::{SignAndSubmitTransaction, SubmitSignedTransaction}; - - #[test] - fn validate_transaction_submitter_bounds() { - fn is_submit_signed_transaction() where - T: SubmitSignedTransaction< - Runtime, - Call, - >, - {} - - fn is_sign_and_submit_transaction() where - T: SignAndSubmitTransaction< - Runtime, - Call, - Extrinsic=UncheckedExtrinsic, - CreateTransaction=Runtime, - Signer=ImOnlineId, - >, - {} - - is_submit_signed_transaction::(); - is_sign_and_submit_transaction::(); - } - - #[test] - fn block_hooks_weight_should_not_exceed_limits() { - use frame_support::weights::WeighBlock; - let check_for_block = |b| { - let block_hooks_weight = - >::on_initialize(b) + - >::on_finalize(b); - - assert_eq!( - block_hooks_weight, - 0, - "This test might fail simply because the value being compared to has increased to a \ - module declaring a new weight for a hook or call. In this case update the test and \ - happily move on.", - ); - - // Invariant. Always must be like this to have a sane chain. - assert!(block_hooks_weight < MaximumBlockWeight::get()); - - // Warning. - if block_hooks_weight > MaximumBlockWeight::get() / 2 { - println!( - "block hooks weight is consuming more than a block's capacity. You probably want \ - to re-think this. This test will fail now." - ); - assert!(false); - } - }; - - let _ = (0..100_000).for_each(check_for_block); - } -} diff --git a/modules/ethereum/other-runtime-components/bin/node/testing/Cargo.toml b/modules/ethereum/other-runtime-components/bin/node/testing/Cargo.toml deleted file mode 100644 index c0707ad0ee319..0000000000000 --- a/modules/ethereum/other-runtime-components/bin/node/testing/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "node-testing" -version = "2.0.0" -authors = ["Parity Technologies "] -description = "Test utilities for Substrate node." -edition = "2018" - -[dependencies] -pallet-balances = { version = "2.0.0", path = "../../../frame/balances" } -sc-client = { version = "2.0.0", path = "../../../client/" } -codec = { package = "parity-scale-codec", version = "1.0.0" } -pallet-contracts = { version = "2.0.0", path = "../../../frame/contracts" } -pallet-grandpa = { version = "2.0.0", path = "../../../frame/grandpa" } -pallet-indices = { version = "2.0.0", path = "../../../frame/indices" } -sp-keyring = { version = "2.0.0", path = "../../../primitives/keyring" } -node-executor = { version = "2.0.0", path = "../executor" } -node-primitives = { version = "2.0.0", path = "../primitives" } -node-runtime = { version = "2.0.0", path = "../runtime" } -sp-core = { version = "2.0.0", path = "../../../primitives/core" } -sp-io = { version = "2.0.0", path = "../../../primitives/io" } -frame-support = { version = "2.0.0", path = "../../../frame/support" } -pallet-session = { version = "2.0.0", path = "../../../frame/session" } -sp-runtime = { version = "2.0.0", path = "../../../primitives/runtime" } -pallet-staking = { version = "2.0.0", path = "../../../frame/staking" } -sc-executor = { version = "2.0.0", path = "../../../client/executor" } -frame-system = { version = "2.0.0", path = "../../../frame/system" } -substrate-test-client = { version = "2.0.0", path = "../../../test-utils/client" } -pallet-timestamp = { version = "2.0.0", path = "../../../frame/timestamp" } -pallet-transaction-payment = { version = "2.0.0", path = "../../../frame/transaction-payment" } -pallet-treasury = { version = "2.0.0", path = "../../../frame/treasury" } -wabt = "0.9.2" -sp-bridge-eth-poa = { package = "sp-bridge-eth-poa", path = "../../../primitives/bridge-eth-poa" } diff --git a/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs b/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs deleted file mode 100644 index cbb1fa0f18ff8..0000000000000 --- a/modules/ethereum/other-runtime-components/bin/node/testing/src/genesis.rs +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2019-2020 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 . - -// Copyright 2019-2020 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 . - -//! Genesis Configuration. - -use crate::keyring::*; -use sp_keyring::{Ed25519Keyring, Sr25519Keyring}; -use node_runtime::{ - GenesisConfig, BalancesConfig, SessionConfig, StakingConfig, SystemConfig, - GrandpaConfig, IndicesConfig, ContractsConfig, WASM_BINARY, BridgeEthPoaConfig, -}; -use node_runtime::constants::currency::*; -use sp_core::ChangesTrieConfiguration; -use sp_runtime::Perbill; - - -/// Create genesis runtime configuration for tests. -pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig { - GenesisConfig { - frame_system: Some(SystemConfig { - changes_trie_config: if support_changes_trie { Some(ChangesTrieConfiguration { - digest_interval: 2, - digest_levels: 2, - }) } else { None }, - code: code.map(|x| x.to_vec()).unwrap_or_else(|| WASM_BINARY.to_vec()), - }), - pallet_indices: Some(IndicesConfig { - ids: vec![alice(), bob(), charlie(), dave(), eve(), ferdie()], - }), - pallet_balances: Some(BalancesConfig { - balances: vec![ - (alice(), 111 * DOLLARS), - (bob(), 100 * DOLLARS), - (charlie(), 100_000_000 * DOLLARS), - (dave(), 111 * DOLLARS), - (eve(), 101 * DOLLARS), - (ferdie(), 100 * DOLLARS), - ], - vesting: vec![], - }), - pallet_session: Some(SessionConfig { - keys: vec![ - (alice(), to_session_keys( - &Ed25519Keyring::Alice, - &Sr25519Keyring::Alice, - )), - (bob(), to_session_keys( - &Ed25519Keyring::Bob, - &Sr25519Keyring::Bob, - )), - (charlie(), to_session_keys( - &Ed25519Keyring::Charlie, - &Sr25519Keyring::Charlie, - )), - ] - }), - pallet_staking: Some(StakingConfig { - current_era: 0, - stakers: vec![ - (dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator), - (eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator), - (ferdie(), charlie(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator) - ], - validator_count: 3, - minimum_validator_count: 0, - slash_reward_fraction: Perbill::from_percent(10), - invulnerables: vec![alice(), bob(), charlie()], - .. Default::default() - }), - pallet_contracts: Some(ContractsConfig { - current_schedule: Default::default(), - gas_price: 1 * MILLICENTS, - }), - pallet_babe: Some(Default::default()), - pallet_grandpa: Some(GrandpaConfig { - authorities: vec![], - }), - pallet_im_online: Some(Default::default()), - pallet_authority_discovery: Some(Default::default()), - pallet_democracy: Some(Default::default()), - pallet_collective_Instance1: Some(Default::default()), - pallet_collective_Instance2: Some(Default::default()), - pallet_membership_Instance1: Some(Default::default()), - pallet_sudo: Some(Default::default()), - pallet_treasury: Some(Default::default()), - // here comes configuration for Kovan chain - // TODO: Update Name - bridge_eth_poa: Some(BridgeEthPoaConfig { - initial_header: sp_bridge_eth_poa::Header { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".parse().unwrap(), - extra_data: vec![], - state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2".parse().unwrap(), - receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".parse().unwrap(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 6000000.into(), - difficulty: 131072.into(), - seal: vec![ - vec![128].into(), - vec![184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].into(), - ], - }, - initial_difficulty: 0.into(), - initial_validators: vec![ - [0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, - 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, 0xAd, 0xc0, 0xED].into(), - [0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, - 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, 0x0a, 0x4d, 0x3d].into(), - [0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, - 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, 0x42, 0x4d, 0x6c].into(), - [0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, - 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, 0xbA, 0x81, 0xA1].into(), - [0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, - 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, 0xfd, 0x03, 0x2d].into(), - [0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, - 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, 0x93, 0x38, 0x7A].into(), - [0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, - 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, 0x89, 0x78, 0x79].into(), - [0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, - 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, 0xa1, 0x64, 0x5c].into(), - [0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, - 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, 0x31, 0x94, 0xde].into(), - ], - }), - } -} diff --git a/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs b/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs deleted file mode 100644 index 0751f1e824ad7..0000000000000 --- a/modules/ethereum/other-runtime-components/primitives/core/src/hasher.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2019-2020 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 . - -// Copyright 2018-2020 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 . - -//! Parity Bridges Common Blake2b Hasher implementation - -use hash_db::Hasher; -use hash256_std_hasher::Hash256StdHasher; -use crate::hash::H256; - -pub mod blake2 { - use super::{Hasher, Hash256StdHasher, H256}; - #[cfg(feature = "std")] - use crate::hashing::blake2_256; - - #[cfg(not(feature = "std"))] - extern "C" { - fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8); - } - #[cfg(not(feature = "std"))] - fn blake2_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_blake2_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - /// Concrete implementation of Hasher using Blake2b 256-bit hashes - #[derive(Debug)] - pub struct Blake2Hasher; - - impl Hasher for Blake2Hasher { - type Out = H256; - type StdHasher = Hash256StdHasher; - const LENGTH: usize = 32; - fn hash(x: &[u8]) -> Self::Out { - blake2_256(x).into() - } - } -} - -pub mod keccak256 { - use super::{Hasher, Hash256StdHasher, H256}; - #[cfg(feature = "std")] - use crate::hashing::keccak_256; - - #[cfg(not(feature = "std"))] - extern "C" { - fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8); - } - #[cfg(not(feature = "std"))] - fn keccak_256(data: &[u8]) -> [u8; 32] { - let mut result: [u8; 32] = Default::default(); - unsafe { - ext_keccak_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr()); - } - result - } - - /// Concrete implementation of Hasher using Keccak 256-bit hashes - #[derive(Debug)] - pub struct Keccak256Hasher; - - impl Hasher for Keccak256Hasher { - type Out = H256; - type StdHasher = Hash256StdHasher; - const LENGTH: usize = 32; - fn hash(x: &[u8]) -> Self::Out { - keccak_256(x).into() - } - } -} diff --git a/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs b/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs deleted file mode 100644 index 36368f87993ad..0000000000000 --- a/modules/ethereum/other-runtime-components/primitives/core/src/lib.rs +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2019-2020 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 . - -// Copyright 2019-2020 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 . - -//! Shareable Parity Bridges Common types. - -#![warn(missing_docs)] - -#![cfg_attr(not(feature = "std"), no_std)] - -/// Initialize a key-value collection from array. -/// -/// Creates a vector of given pairs and calls `collect` on the iterator from it. -/// Can be used to create a `HashMap`. -#[macro_export] -macro_rules! map { - ($( $name:expr => $value:expr ),* $(,)? ) => ( - vec![ $( ( $name, $value ) ),* ].into_iter().collect() - ); -} - -use sp_std::prelude::*; -use sp_std::ops::Deref; -#[cfg(feature = "std")] -use std::borrow::Cow; -#[cfg(feature = "std")] -use serde::{Serialize, Deserialize}; -#[cfg(feature = "std")] -pub use serde; -#[doc(hidden)] -pub use codec::{Encode, Decode}; - -pub use sp_debug_derive::RuntimeDebug; - -#[cfg(feature = "std")] -pub use impl_serde::serialize as bytes; - -#[cfg(feature = "full_crypto")] -pub mod hashing; -#[cfg(feature = "full_crypto")] -pub use hashing::{blake2_128, blake2_256, twox_64, twox_128, twox_256, keccak_256}; -#[cfg(feature = "std")] -pub mod hexdisplay; -pub mod crypto; - -pub mod u32_trait; - -pub mod ed25519; -pub mod sr25519; -pub mod ecdsa; -pub mod hash; -mod hasher; -pub mod offchain; -pub mod sandbox; -pub mod uint; -mod changes_trie; -#[cfg(feature = "std")] -pub mod traits; -pub mod testing; - -#[cfg(test)] -mod tests; - -pub use self::hash::{H160, H256, H512, convert_hash}; -pub use self::uint::U256; -pub use changes_trie::ChangesTrieConfiguration; -#[cfg(feature = "full_crypto")] -pub use crypto::{DeriveJunction, Pair, Public}; - -pub use hash_db::Hasher; -// Switch back to Blake after PoC-3 is out -// pub use self::hasher::blake::BlakeHasher; -pub use self::hasher::blake2::Blake2Hasher; -pub use self::hasher::keccak256::Keccak256Hasher; - -pub use sp_storage as storage; - -#[doc(hidden)] -pub use sp_std; - -/// Context for executing a call into the runtime. -pub enum ExecutionContext { - /// Context for general importing (including own blocks). - Importing, - /// Context used when syncing the blockchain. - Syncing, - /// Context used for block construction. - BlockConstruction, - /// Context used for offchain calls. - /// - /// This allows passing offchain extension and customizing available capabilities. - OffchainCall(Option<(Box, offchain::Capabilities)>), -} - -impl ExecutionContext { - /// Returns the capabilities of particular context. - pub fn capabilities(&self) -> offchain::Capabilities { - use ExecutionContext::*; - - match self { - Importing | Syncing | BlockConstruction => - offchain::Capabilities::none(), - // Enable keystore by default for offchain calls. CC @bkchr - OffchainCall(None) => [offchain::Capability::Keystore][..].into(), - OffchainCall(Some((_, capabilities))) => *capabilities, - } - } -} - -/// Hex-serialized shim for `Vec`. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord))] -pub struct Bytes(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -impl From> for Bytes { - fn from(s: Vec) -> Self { Bytes(s) } -} - -impl From for Bytes { - fn from(s: OpaqueMetadata) -> Self { Bytes(s.0) } -} - -impl Deref for Bytes { - type Target = [u8]; - fn deref(&self) -> &[u8] { &self.0[..] } -} - -/// Stores the encoded `RuntimeMetadata` for the native side as opaque type. -#[derive(Encode, Decode, PartialEq)] -pub struct OpaqueMetadata(Vec); - -impl OpaqueMetadata { - /// Creates a new instance with the given metadata blob. - pub fn new(metadata: Vec) -> Self { - OpaqueMetadata(metadata) - } -} - -impl sp_std::ops::Deref for OpaqueMetadata { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// Something that is either a native or an encoded value. -#[cfg(feature = "std")] -pub enum NativeOrEncoded { - /// The native representation. - Native(R), - /// The encoded representation. - Encoded(Vec) -} - -#[cfg(feature = "std")] -impl sp_std::fmt::Debug for NativeOrEncoded { - fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - hexdisplay::HexDisplay::from(&self.as_encoded().as_ref()).fmt(f) - } -} - -#[cfg(feature = "std")] -impl NativeOrEncoded { - /// Return the value as the encoded format. - pub fn as_encoded(&self) -> Cow<'_, [u8]> { - match self { - NativeOrEncoded::Encoded(e) => Cow::Borrowed(e.as_slice()), - NativeOrEncoded::Native(n) => Cow::Owned(n.encode()), - } - } - - /// Return the value as the encoded format. - pub fn into_encoded(self) -> Vec { - match self { - NativeOrEncoded::Encoded(e) => e, - NativeOrEncoded::Native(n) => n.encode(), - } - } -} - -#[cfg(feature = "std")] -impl PartialEq for NativeOrEncoded { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (NativeOrEncoded::Native(l), NativeOrEncoded::Native(r)) => l == r, - (NativeOrEncoded::Native(n), NativeOrEncoded::Encoded(e)) | - (NativeOrEncoded::Encoded(e), NativeOrEncoded::Native(n)) => - Some(n) == codec::Decode::decode(&mut &e[..]).ok().as_ref(), - (NativeOrEncoded::Encoded(l), NativeOrEncoded::Encoded(r)) => l == r, - } - } -} - -/// A value that is never in a native representation. -/// This is type is useful in conjuction with `NativeOrEncoded`. -#[cfg(feature = "std")] -#[derive(PartialEq)] -pub enum NeverNativeValue {} - -#[cfg(feature = "std")] -impl codec::Encode for NeverNativeValue { - fn encode(&self) -> Vec { - // The enum is not constructable, so this function should never be callable! - unreachable!() - } -} - -#[cfg(feature = "std")] -impl codec::EncodeLike for NeverNativeValue {} - -#[cfg(feature = "std")] -impl codec::Decode for NeverNativeValue { - fn decode(_: &mut I) -> Result { - Err("`NeverNativeValue` should never be decoded".into()) - } -} - -/// Provide a simple 4 byte identifier for a type. -pub trait TypeId { - /// Simple 4 byte identifier. - const TYPE_ID: [u8; 4]; -} - -/// A log level matching the one from `log` crate. -/// -/// Used internally by `sp_io::log` method. -#[derive(Encode, Decode, sp_runtime_interface::pass_by::PassByEnum, Copy, Clone)] -pub enum LogLevel { - /// `Error` log level. - Error = 1, - /// `Warn` log level. - Warn = 2, - /// `Info` log level. - Info = 3, - /// `Debug` log level. - Debug = 4, - /// `Trace` log level. - Trace = 5, -} - -impl From for LogLevel { - fn from(val: u32) -> Self { - match val { - x if x == LogLevel::Warn as u32 => LogLevel::Warn, - x if x == LogLevel::Info as u32 => LogLevel::Info, - x if x == LogLevel::Debug as u32 => LogLevel::Debug, - x if x == LogLevel::Trace as u32 => LogLevel::Trace, - _ => LogLevel::Error, - } - } -} - -impl From for LogLevel { - fn from(l: log::Level) -> Self { - use log::Level::*; - match l { - Error => Self::Error, - Warn => Self::Warn, - Info => Self::Info, - Debug => Self::Debug, - Trace => Self::Trace, - } - } -} - -impl From for log::Level { - fn from(l: LogLevel) -> Self { - use self::LogLevel::*; - match l { - Error => Self::Error, - Warn => Self::Warn, - Info => Self::Info, - Debug => Self::Debug, - Trace => Self::Trace, - } - } -} - -/// Encodes the given value into a buffer and returns the pointer and the length as a single `u64`. -/// -/// When Parity Bridges Common calls into Wasm it expects a fixed signature for functions exported -/// from the Wasm blob. The return value of this signature is always a `u64`. -/// This `u64` stores the pointer to the encoded return value and the length of this encoded value. -/// The low `32bits` are reserved for the pointer, followed by `32bit` for the length. -#[cfg(not(feature = "std"))] -pub fn to_substrate_wasm_fn_return_value(value: &impl Encode) -> u64 { - let encoded = value.encode(); - - let ptr = encoded.as_ptr() as u64; - let length = encoded.len() as u64; - let res = ptr | (length << 32); - - // Leak the output vector to avoid it being freed. - // This is fine in a WASM context since the heap - // will be discarded after the call. - sp_std::mem::forget(encoded); - - res -} diff --git a/modules/ethereum/other-runtime-components/primitives/io/Cargo.toml b/modules/ethereum/other-runtime-components/primitives/io/Cargo.toml deleted file mode 100644 index 04350c9479ede..0000000000000 --- a/modules/ethereum/other-runtime-components/primitives/io/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "sp-io" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -codec = { package = "parity-scale-codec", version = "1.0.6", default-features = false } -hash-db = { version = "0.15.2", default-features = false } -sp-core = { version = "2.0.0", default-features = false, path = "../core" } -sp-std = { version = "2.0.0", default-features = false, path = "../std" } -libsecp256k1 = { version = "0.3.4", optional = true } -sp-state-machine = { version = "2.0.0", optional = true, path = "../../primitives/state-machine" } -sp-runtime-interface = { version = "2.0.0", default-features = false, path = "../runtime-interface" } -sp-trie = { version = "2.0.0", optional = true, path = "../../primitives/trie" } -sp-externalities = { version = "2.0.0", optional = true, path = "../externalities" } -log = { version = "0.4.8", optional = true } - -[features] -default = ["std"] -std = [ - "sp-core/std", - "codec/std", - "sp-std/std", - "hash-db/std", - "sp-trie", - "sp-state-machine", - "libsecp256k1", - "sp-runtime-interface/std", - "sp-externalities", - "log", -] - -# These two features are used for `no_std` builds for the environments which already provides -# `#[panic_handler]`, `#[alloc_error_handler]` and `#[global_allocator]`. -# -# For the regular wasm runtime builds those are not used. -disable_panic_handler = [] -disable_oom = [] -disable_allocator = [] diff --git a/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs b/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs deleted file mode 100644 index 997ab73e58d63..0000000000000 --- a/modules/ethereum/other-runtime-components/primitives/io/src/lib.rs +++ /dev/null @@ -1,990 +0,0 @@ -// Copyright 2019-2020 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 . - -// Copyright 2019-2020 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 . - -//! This is part of the Parity Bridges Common runtime. - -#![warn(missing_docs)] - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] -#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] - -#![cfg_attr(feature = "std", - doc = "Parity Bridges Common runtime standard library as compiled when linked with Rust's standard library.")] -#![cfg_attr(not(feature = "std"), - doc = "Parity Bridges Common's runtime standard library as compiled without Rust's standard library.")] - -use sp_std::vec::Vec; - -#[cfg(feature = "std")] -use sp_std::ops::Deref; - -#[cfg(feature = "std")] -use sp_core::{ - crypto::Pair, - traits::KeystoreExt, - offchain::{OffchainExt, TransactionPoolExt}, - hexdisplay::HexDisplay, - storage::{ChildStorageKey, ChildInfo}, -}; - -use sp_core::{ - crypto::KeyTypeId, ed25519, sr25519, H256, LogLevel, - offchain::{ - Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, - }, -}; - -#[cfg(feature = "std")] -use ::sp_trie::{TrieConfiguration, trie_types::Layout}; - -use sp_runtime_interface::{runtime_interface, Pointer}; - -use codec::{Encode, Decode}; - -#[cfg(feature = "std")] -use sp_externalities::{ExternalitiesExt, Externalities}; - -/// Error verifying ECDSA signature -#[derive(Encode, Decode)] -pub enum EcdsaVerifyError { - /// Incorrect value of R or S - BadRS, - /// Incorrect value of V - BadV, - /// Invalid signature - BadSignature, -} - -/// Returns a `ChildStorageKey` if the given `storage_key` slice is a valid storage -/// key or panics otherwise. -/// -/// Panicking here is aligned with what the `without_std` environment would do -/// in the case of an invalid child storage key. -#[cfg(feature = "std")] -fn child_storage_key_or_panic(storage_key: &[u8]) -> ChildStorageKey { - match ChildStorageKey::from_slice(storage_key) { - Some(storage_key) => storage_key, - None => panic!("child storage key is invalid"), - } -} - -/// Interface for accessing the storage from within the runtime. -#[runtime_interface] -pub trait Storage { - /// Returns the data for `key` in the storage or `None` if the key can not be found. - fn get(&self, key: &[u8]) -> Option> { - self.storage(key).map(|s| s.to_vec()) - } - - /// All Child api uses : - /// - A `child_storage_key` to define the anchor point for the child proof - /// (commonly the location where the child root is stored in its parent trie). - /// - A `child_storage_types` to identify the kind of the child type and how its - /// `child definition` parameter is encoded. - /// - A `child_definition_parameter` which is the additional information required - /// to use the child trie. For instance defaults child tries requires this to - /// contain a collision free unique id. - /// - /// This function specifically returns the data for `key` in the child storage or `None` - /// if the key can not be found. - fn child_get( - &self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - ) -> Option> { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.child_storage(storage_key, child_info, key).map(|s| s.to_vec()) - } - - /// Get `key` from storage, placing the value into `value_out` and return the number of - /// bytes that the entry in storage has beyond the offset or `None` if the storage entry - /// doesn't exist at all. - /// If `value_out` length is smaller than the returned length, only `value_out` length bytes - /// are copied into `value_out`. - fn read(&self, key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option { - self.storage(key).map(|value| { - let value_offset = value_offset as usize; - let data = &value[value_offset.min(value.len())..]; - let written = std::cmp::min(data.len(), value_out.len()); - value_out[..written].copy_from_slice(&data[..written]); - value.len() as u32 - }) - } - - /// Get `key` from child storage, placing the value into `value_out` and return the number - /// of bytes that the entry in storage has beyond the offset or `None` if the storage entry - /// doesn't exist at all. - /// If `value_out` length is smaller than the returned length, only `value_out` length bytes - /// are copied into `value_out`. - /// - /// See `child_get` for common child api parameters. - fn child_read( - &self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - value_out: &mut [u8], - value_offset: u32, - ) -> Option { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.child_storage(storage_key, child_info, key) - .map(|value| { - let value_offset = value_offset as usize; - let data = &value[value_offset.min(value.len())..]; - let written = std::cmp::min(data.len(), value_out.len()); - value_out[..written].copy_from_slice(&data[..written]); - value.len() as u32 - }) - } - - /// Set `key` to `value` in the storage. - fn set(&mut self, key: &[u8], value: &[u8]) { - self.set_storage(key.to_vec(), value.to_vec()); - } - - /// Set `key` to `value` in the child storage denoted by `child_storage_key`. - /// - /// See `child_get` for common child api parameters. - fn child_set( - &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - value: &[u8], - ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.set_child_storage(storage_key, child_info, key.to_vec(), value.to_vec()); - } - - /// Clear the storage of the given `key` and its value. - fn clear(&mut self, key: &[u8]) { - self.clear_storage(key) - } - - /// Clear the given child storage of the given `key` and its value. - /// - /// See `child_get` for common child api parameters. - fn child_clear( - &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.clear_child_storage(storage_key, child_info, key); - } - - /// Clear an entire child storage. - /// - /// See `child_get` for common child api parameters. - fn child_storage_kill( - &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.kill_child_storage(storage_key, child_info); - } - - /// Check whether the given `key` exists in storage. - fn exists(&self, key: &[u8]) -> bool { - self.exists_storage(key) - } - - /// Check whether the given `key` exists in storage. - /// - /// See `child_get` for common child api parameters. - fn child_exists( - &self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - ) -> bool { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.exists_child_storage(storage_key, child_info, key) - } - - /// Clear the storage of each key-value pair where the key starts with the given `prefix`. - fn clear_prefix(&mut self, prefix: &[u8]) { - Externalities::clear_prefix(*self, prefix) - } - - /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. - /// - /// See `child_get` for common child api parameters. - fn child_clear_prefix( - &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - prefix: &[u8], - ) { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.clear_child_prefix(storage_key, child_info, prefix); - } - - /// "Commit" all existing operations and compute the resulting storage root. - /// - /// The hashing algorithm is defined by the `Block`. - /// - /// Returns the SCALE encoded hash. - fn root(&mut self) -> Vec { - self.storage_root() - } - - /// "Commit" all existing operations and compute the resulting child storage root. - /// - /// The hashing algorithm is defined by the `Block`. - /// - /// Returns the SCALE encoded hash. - /// - /// See `child_get` for common child api parameters. - fn child_root( - &mut self, - child_storage_key: &[u8], - ) -> Vec { - let storage_key = child_storage_key_or_panic(child_storage_key); - self.child_storage_root(storage_key) - } - - /// "Commit" all existing operations and get the resulting storage change root. - /// `parent_hash` is a SCALE encoded hash. - /// - /// The hashing algorithm is defined by the `Block`. - /// - /// Returns an `Option` that holds the SCALE encoded hash. - fn changes_root(&mut self, parent_hash: &[u8]) -> Option> { - self.storage_changes_root(parent_hash) - .expect("Invalid `parent_hash` given to `changes_root`.") - } - - /// Get the next key in storage after the given one in lexicographic order. - fn next_key(&mut self, key: &[u8]) -> Option> { - self.next_storage_key(&key) - } - - /// Get the next key in storage after the given one in lexicographic order in child storage. - fn child_next_key( - &mut self, - child_storage_key: &[u8], - child_definition: &[u8], - child_type: u32, - key: &[u8], - ) -> Option> { - let storage_key = child_storage_key_or_panic(child_storage_key); - let child_info = ChildInfo::resolve_child_info(child_type, child_definition) - .expect("Invalid child definition"); - self.next_child_storage_key(storage_key, child_info, key) - } -} - -/// Interface that provides trie related functionality. -#[runtime_interface] -pub trait Trie { - /// A trie root formed from the iterated items. - fn blake2_256_root(input: Vec<(Vec, Vec)>) -> H256 { - Layout::::trie_root(input) - } - - /// A trie root formed from the enumerated items. - fn blake2_256_ordered_root(input: Vec>) -> H256 { - Layout::::ordered_trie_root(input) - } - - /// A trie root formed from the enumerated items. - fn keccak_256_ordered_root(input: Vec>) -> H256 { - Layout::::ordered_trie_root(input) - } -} - -/// Interface that provides miscellaneous functions for communicating between the runtime and the node. -#[runtime_interface] -pub trait Misc { - /// The current relay chain identifier. - fn chain_id(&self) -> u64 { - sp_externalities::Externalities::chain_id(*self) - } - - /// Print a number. - fn print_num(val: u64) { - log::debug!(target: "runtime", "{}", val); - } - - /// Print any valid `utf8` buffer. - fn print_utf8(utf8: &[u8]) { - if let Ok(data) = std::str::from_utf8(utf8) { - log::debug!(target: "runtime", "{}", data) - } - } - - /// Print any `u8` slice as hex. - fn print_hex(data: &[u8]) { - log::debug!(target: "runtime", "{}", HexDisplay::from(&data)); - } -} - -/// Interfaces for working with crypto related types from within the runtime. -#[runtime_interface] -pub trait Crypto { - /// Returns all `ed25519` public keys for the given key id from the keystore. - fn ed25519_public_keys(&mut self, id: KeyTypeId) -> Vec { - self.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .ed25519_public_keys(id) - } - - /// Generate an `ed22519` key for the given key type using an optional `seed` and - /// store it in the keystore. - /// - /// The `seed` needs to be a valid utf8. - /// - /// Returns the public key. - fn ed25519_generate(&mut self, id: KeyTypeId, seed: Option>) -> ed25519::Public { - let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); - self.extension::() - .expect("No `keystore` associated for the current context!") - .write() - .ed25519_generate_new(id, seed) - .expect("`ed25519_generate` failed") - } - - /// Sign the given `msg` with the `ed25519` key that corresponds to the given public key and - /// key type in the keystore. - /// - /// Returns the signature. - fn ed25519_sign( - &mut self, - id: KeyTypeId, - pub_key: &ed25519::Public, - msg: &[u8], - ) -> Option { - self.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .ed25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg)) - } - - /// Verify an `ed25519` signature. - /// - /// Returns `true` when the verification in successful. - fn ed25519_verify( - &self, - sig: &ed25519::Signature, - msg: &[u8], - pub_key: &ed25519::Public, - ) -> bool { - ed25519::Pair::verify(sig, msg, pub_key) - } - - /// Returns all `sr25519` public keys for the given key id from the keystore. - fn sr25519_public_keys(&mut self, id: KeyTypeId) -> Vec { - self.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .sr25519_public_keys(id) - } - - /// Generate an `sr22519` key for the given key type using an optional seed and - /// store it in the keystore. - /// - /// The `seed` needs to be a valid utf8. - /// - /// Returns the public key. - fn sr25519_generate(&mut self, id: KeyTypeId, seed: Option>) -> sr25519::Public { - let seed = seed.as_ref().map(|s| std::str::from_utf8(&s).expect("Seed is valid utf8!")); - self.extension::() - .expect("No `keystore` associated for the current context!") - .write() - .sr25519_generate_new(id, seed) - .expect("`sr25519_generate` failed") - } - - /// Sign the given `msg` with the `sr25519` key that corresponds to the given public key and - /// key type in the keystore. - /// - /// Returns the signature. - fn sr25519_sign( - &mut self, - id: KeyTypeId, - pub_key: &sr25519::Public, - msg: &[u8], - ) -> Option { - self.extension::() - .expect("No `keystore` associated for the current context!") - .read() - .sr25519_key_pair(id, &pub_key) - .map(|k| k.sign(msg)) - } - - /// Verify an `sr25519` signature. - /// - /// Returns `true` when the verification in successful. - fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool { - sr25519::Pair::verify(sig, msg, pubkey) - } - - /// Verify and recover a SECP256k1 ECDSA signature. - /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. - /// Returns `Err` if the signature is bad, otherwise the 64-byte pubkey - /// (doesn't include the 0x04 prefix). - fn secp256k1_ecdsa_recover( - sig: &[u8; 65], - msg: &[u8; 32], - ) -> Result<[u8; 64], EcdsaVerifyError> { - let rs = secp256k1::Signature::parse_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; - let mut res = [0u8; 64]; - res.copy_from_slice(&pubkey.serialize()[1..65]); - Ok(res) - } - - /// Verify and recover a SECP256k1 ECDSA signature. - /// - `sig` is passed in RSV format. V should be either 0/1 or 27/28. - /// - returns `Err` if the signature is bad, otherwise the 33-byte compressed pubkey. - fn secp256k1_ecdsa_recover_compressed( - sig: &[u8; 65], - msg: &[u8; 32], - ) -> Result<[u8; 33], EcdsaVerifyError> { - let rs = secp256k1::Signature::parse_slice(&sig[0..64]) - .map_err(|_| EcdsaVerifyError::BadRS)?; - let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) - .map_err(|_| EcdsaVerifyError::BadV)?; - let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v) - .map_err(|_| EcdsaVerifyError::BadSignature)?; - Ok(pubkey.serialize_compressed()) - } -} - -/// Interface that provides functions for hashing with different algorithms. -#[runtime_interface] -pub trait Hashing { - /// Conduct a 256-bit Keccak hash. - fn keccak_256(data: &[u8]) -> [u8; 32] { - sp_core::hashing::keccak_256(data) - } - - /// Conduct a 256-bit Sha2 hash. - fn sha2_256(data: &[u8]) -> [u8; 32] { - sp_core::hashing::sha2_256(data) - } - - /// Conduct a 128-bit Blake2 hash. - fn blake2_128(data: &[u8]) -> [u8; 16] { - sp_core::hashing::blake2_128(data) - } - - /// Conduct a 256-bit Blake2 hash. - fn blake2_256(data: &[u8]) -> [u8; 32] { - sp_core::hashing::blake2_256(data) - } - - /// Conduct four XX hashes to give a 256-bit result. - fn twox_256(data: &[u8]) -> [u8; 32] { - sp_core::hashing::twox_256(data) - } - - /// Conduct two XX hashes to give a 128-bit result. - fn twox_128(data: &[u8]) -> [u8; 16] { - sp_core::hashing::twox_128(data) - } - - /// Conduct two XX hashes to give a 64-bit result. - fn twox_64(data: &[u8]) -> [u8; 8] { - sp_core::hashing::twox_64(data) - } -} - -/// Interface that provides functions to access the offchain functionality. -#[runtime_interface] -pub trait Offchain { - /// Returns if the local node is a potential validator. - /// - /// Even if this function returns `true`, it does not mean that any keys are configured - /// and that the validator is registered in the chain. - fn is_validator(&mut self) -> bool { - self.extension::() - .expect("is_validator can be called only in the offchain worker context") - .is_validator() - } - - /// Submit an encoded transaction to the pool. - /// - /// The transaction will end up in the pool. - fn submit_transaction(&mut self, data: Vec) -> Result<(), ()> { - self.extension::() - .expect("submit_transaction can be called only in the offchain call context with - TransactionPool capabilities enabled") - .submit_transaction(data) - } - - /// Returns information about the local node's network state. - fn network_state(&mut self) -> Result { - self.extension::() - .expect("network_state can be called only in the offchain worker context") - .network_state() - } - - /// Returns current UNIX timestamp (in millis) - fn timestamp(&mut self) -> Timestamp { - self.extension::() - .expect("timestamp can be called only in the offchain worker context") - .timestamp() - } - - /// Pause the execution until `deadline` is reached. - fn sleep_until(&mut self, deadline: Timestamp) { - self.extension::() - .expect("sleep_until can be called only in the offchain worker context") - .sleep_until(deadline) - } - - /// Returns a random seed. - /// - /// This is a trully random non deterministic seed generated by host environment. - /// Obviously fine in the off-chain worker context. - fn random_seed(&mut self) -> [u8; 32] { - self.extension::() - .expect("random_seed can be called only in the offchain worker context") - .random_seed() - } - - /// Sets a value in the local storage. - /// - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_set(&mut self, kind: StorageKind, key: &[u8], value: &[u8]) { - self.extension::() - .expect("local_storage_set can be called only in the offchain worker context") - .local_storage_set(kind, key, value) - } - - /// Sets a value in the local storage if it matches current value. - /// - /// Since multiple offchain workers may be running concurrently, to prevent - /// data races use CAS to coordinate between them. - /// - /// Returns `true` if the value has been set, `false` otherwise. - /// - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_compare_and_set( - &mut self, - kind: StorageKind, - key: &[u8], - old_value: Option>, - new_value: &[u8], - ) -> bool { - self.extension::() - .expect("local_storage_compare_and_set can be called only in the offchain worker context") - .local_storage_compare_and_set(kind, key, old_value.as_ref().map(|v| v.deref()), new_value) - } - - /// Gets a value from the local storage. - /// - /// If the value does not exist in the storage `None` will be returned. - /// Note this storage is not part of the consensus, it's only accessible by - /// offchain worker tasks running on the same machine. It IS persisted between runs. - fn local_storage_get(&mut self, kind: StorageKind, key: &[u8]) -> Option> { - self.extension::() - .expect("local_storage_get can be called only in the offchain worker context") - .local_storage_get(kind, key) - } - - /// Initiates a http request given HTTP verb and the URL. - /// - /// Meta is a future-reserved field containing additional, parity-scale-codec encoded parameters. - /// Returns the id of newly started request. - fn http_request_start( - &mut self, - method: &str, - uri: &str, - meta: &[u8], - ) -> Result { - self.extension::() - .expect("http_request_start can be called only in the offchain worker context") - .http_request_start(method, uri, meta) - } - - /// Append header to the request. - fn http_request_add_header( - &mut self, - request_id: HttpRequestId, - name: &str, - value: &str, - ) -> Result<(), ()> { - self.extension::() - .expect("http_request_add_header can be called only in the offchain worker context") - .http_request_add_header(request_id, name, value) - } - - /// Write a chunk of request body. - /// - /// Writing an empty chunks finalizes the request. - /// Passing `None` as deadline blocks forever. - /// - /// Returns an error in case deadline is reached or the chunk couldn't be written. - fn http_request_write_body( - &mut self, - request_id: HttpRequestId, - chunk: &[u8], - deadline: Option, - ) -> Result<(), HttpError> { - self.extension::() - .expect("http_request_write_body can be called only in the offchain worker context") - .http_request_write_body(request_id, chunk, deadline) - } - - /// Block and wait for the responses for given requests. - /// - /// Returns a vector of request statuses (the len is the same as ids). - /// Note that if deadline is not provided the method will block indefinitely, - /// otherwise unready responses will produce `DeadlineReached` status. - /// - /// Passing `None` as deadline blocks forever. - fn http_response_wait( - &mut self, - ids: &[HttpRequestId], - deadline: Option, - ) -> Vec { - self.extension::() - .expect("http_response_wait can be called only in the offchain worker context") - .http_response_wait(ids, deadline) - } - - /// Read all response headers. - /// - /// Returns a vector of pairs `(HeaderKey, HeaderValue)`. - /// NOTE response headers have to be read before response body. - fn http_response_headers(&mut self, request_id: HttpRequestId) -> Vec<(Vec, Vec)> { - self.extension::() - .expect("http_response_headers can be called only in the offchain worker context") - .http_response_headers(request_id) - } - - /// Read a chunk of body response to given buffer. - /// - /// Returns the number of bytes written or an error in case a deadline - /// is reached or server closed the connection. - /// If `0` is returned it means that the response has been fully consumed - /// and the `request_id` is now invalid. - /// NOTE this implies that response headers must be read before draining the body. - /// Passing `None` as a deadline blocks forever. - fn http_response_read_body( - &mut self, - request_id: HttpRequestId, - buffer: &mut [u8], - deadline: Option, - ) -> Result { - self.extension::() - .expect("http_response_read_body can be called only in the offchain worker context") - .http_response_read_body(request_id, buffer, deadline) - .map(|r| r as u32) - } -} - -/// Wasm only interface that provides functions for calling into the allocator. -#[runtime_interface(wasm_only)] -trait Allocator { - /// Malloc the given number of bytes and return the pointer to the allocated memory location. - fn malloc(&mut self, size: u32) -> Pointer { - self.allocate_memory(size).expect("Failed to allocate memory") - } - - /// Free the given pointer. - fn free(&mut self, ptr: Pointer) { - self.deallocate_memory(ptr).expect("Failed to deallocate memory") - } -} - -/// Interface that provides functions for logging from within the runtime. -#[runtime_interface] -pub trait Logging { - /// Request to print a log message on the host. - /// - /// Note that this will be only displayed if the host is enabled to display log messages with - /// given level and target. - /// - /// Instead of using directly, prefer setting up `RuntimeLogger` and using `log` macros. - fn log(level: LogLevel, target: &str, message: &[u8]) { - if let Ok(message) = std::str::from_utf8(message) { - log::log!( - target: target, - log::Level::from(level), - "{}", - message, - ) - } - } -} - -/// Wasm-only interface that provides functions for interacting with the sandbox. -#[runtime_interface(wasm_only)] -pub trait Sandbox { - /// Instantiate a new sandbox instance with the given `wasm_code`. - fn instantiate( - &mut self, - dispatch_thunk: u32, - wasm_code: &[u8], - env_def: &[u8], - state_ptr: Pointer, - ) -> u32 { - self.sandbox() - .instance_new(dispatch_thunk, wasm_code, env_def, state_ptr.into()) - .expect("Failed to instantiate a new sandbox") - } - - /// Invoke `function` in the sandbox with `sandbox_idx`. - fn invoke( - &mut self, - instance_idx: u32, - function: &str, - args: &[u8], - return_val_ptr: Pointer, - return_val_len: u32, - state_ptr: Pointer, - ) -> u32 { - self.sandbox().invoke( - instance_idx, - &function, - &args, - return_val_ptr, - return_val_len, - state_ptr.into(), - ).expect("Failed to invoke function with sandbox") - } - - /// Create a new memory instance with the given `initial` and `maximum` size. - fn memory_new(&mut self, initial: u32, maximum: u32) -> u32 { - self.sandbox() - .memory_new(initial, maximum) - .expect("Failed to create new memory with sandbox") - } - - /// Get the memory starting at `offset` from the instance with `memory_idx` into the buffer. - fn memory_get( - &mut self, - memory_idx: u32, - offset: u32, - buf_ptr: Pointer, - buf_len: u32, - ) -> u32 { - self.sandbox() - .memory_get(memory_idx, offset, buf_ptr, buf_len) - .expect("Failed to get memory with sandbox") - } - - /// Set the memory in the given `memory_idx` to the given value at `offset`. - fn memory_set( - &mut self, - memory_idx: u32, - offset: u32, - val_ptr: Pointer, - val_len: u32, - ) -> u32 { - self.sandbox() - .memory_set(memory_idx, offset, val_ptr, val_len) - .expect("Failed to set memory with sandbox") - } - - /// Teardown the memory instance with the given `memory_idx`. - fn memory_teardown(&mut self, memory_idx: u32) { - self.sandbox().memory_teardown(memory_idx).expect("Failed to teardown memory with sandbox") - } - - /// Teardown the sandbox instance with the given `instance_idx`. - fn instance_teardown(&mut self, instance_idx: u32) { - self.sandbox().instance_teardown(instance_idx).expect("Failed to teardown sandbox instance") - } -} - -/// Allocator used by Parity Bridges Common when executing the Wasm runtime. -#[cfg(not(feature = "std"))] -struct WasmAllocator; - -#[cfg(all(not(feature = "disable_allocator"), not(feature = "std")))] -#[global_allocator] -static ALLOCATOR: WasmAllocator = WasmAllocator; - -#[cfg(not(feature = "std"))] -mod allocator_impl { - use super::*; - use core::alloc::{GlobalAlloc, Layout}; - - unsafe impl GlobalAlloc for WasmAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - allocator::malloc(layout.size() as u32) - } - - unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) { - allocator::free(ptr) - } - } -} - -/// A default panic handler for WASM environment. -#[cfg(all(not(feature = "disable_panic_handler"), not(feature = "std")))] -#[panic_handler] -#[no_mangle] -pub fn panic(info: &core::panic::PanicInfo) -> ! { - unsafe { - let message = sp_std::alloc::format!("{}", info); - logging::log(LogLevel::Error, "runtime", message.as_bytes()); - core::intrinsics::abort() - } -} - -/// A default OOM handler for WASM environment. -#[cfg(all(not(feature = "disable_oom"), not(feature = "std")))] -#[alloc_error_handler] -pub fn oom(_: core::alloc::Layout) -> ! { - unsafe { - logging::log(LogLevel::Error, "runtime", b"Runtime memory exhausted. Aborting"); - core::intrinsics::abort(); - } -} - -/// Type alias for Externalities implementation used in tests. -#[cfg(feature = "std")] -pub type TestExternalities = sp_state_machine::TestExternalities; - -/// The host functions Parity Bridges Common provides for the Wasm runtime environment. -/// -/// All these host functions will be callable from inside the Wasm environment. -#[cfg(feature = "std")] -pub type Parity Bridges CommonHostFunctions = ( - storage::HostFunctions, - misc::HostFunctions, - offchain::HostFunctions, - crypto::HostFunctions, - hashing::HostFunctions, - allocator::HostFunctions, - logging::HostFunctions, - sandbox::HostFunctions, - crate::trie::HostFunctions, -); - -#[cfg(test)] -mod tests { - use super::*; - use sp_core::map; - use sp_state_machine::BasicExternalities; - use sp_core::storage::Storage; - - #[test] - fn storage_works() { - let mut t = BasicExternalities::default(); - t.execute_with(|| { - assert_eq!(storage::get(b"hello"), None); - storage::set(b"hello", b"world"); - assert_eq!(storage::get(b"hello"), Some(b"world".to_vec())); - assert_eq!(storage::get(b"foo"), None); - storage::set(b"foo", &[1, 2, 3][..]); - }); - - t = BasicExternalities::new(Storage { - top: map![b"foo".to_vec() => b"bar".to_vec()], - children: map![], - }); - - t.execute_with(|| { - assert_eq!(storage::get(b"hello"), None); - assert_eq!(storage::get(b"foo"), Some(b"bar".to_vec())); - }); - } - - #[test] - fn read_storage_works() { - let mut t = BasicExternalities::new(Storage { - top: map![b":test".to_vec() => b"\x0b\0\0\0Hello world".to_vec()], - children: map![], - }); - - t.execute_with(|| { - let mut v = [0u8; 4]; - assert!(storage::read(b":test", &mut v[..], 0).unwrap() >= 4); - assert_eq!(v, [11u8, 0, 0, 0]); - let mut w = [0u8; 11]; - assert!(storage::read(b":test", &mut w[..], 4).unwrap() >= 11); - assert_eq!(&w, b"Hello world"); - }); - } - - #[test] - fn clear_prefix_works() { - let mut t = BasicExternalities::new(Storage { - top: map![ - b":a".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), - b":abcd".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), - b":abc".to_vec() => b"\x0b\0\0\0Hello world".to_vec(), - b":abdd".to_vec() => b"\x0b\0\0\0Hello world".to_vec() - ], - children: map![], - }); - - t.execute_with(|| { - storage::clear_prefix(b":abc"); - - assert!(storage::get(b":a").is_some()); - assert!(storage::get(b":abdd").is_some()); - assert!(storage::get(b":abcd").is_none()); - assert!(storage::get(b":abc").is_none()); - }); - } -} From a33e950cf7eae70c4eef5eaffb3d1c5942442049 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 19 May 2020 14:03:08 -0400 Subject: [PATCH 0053/1210] Bump rust-web3 to latest v0.11 (#100) * Bump rust-web3 to latest master * Use tagged release from crates.io * Add check for `logs_bloom` Since this is required by the runtime we want to enforce that an incoming header has this. --- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/ethereum_client.rs | 16 ++++++++-------- relays/ethereum/src/substrate_types.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d0bc37073d537..c41b13d22ed42 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -28,7 +28,7 @@ serde = { version = "1.0.110", features = ["derive"] } serde_json = "1.0.53" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" -web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "add-receipt-root" } +web3 = "0.11" # Substrate Based Dependencies [dependencies.frame-system] diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index ac70c310449d0..974d5ddeff7ba 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -152,12 +152,12 @@ pub async fn header_by_number(client: Client, number: u64) -> (Client, Result Ok(header), false => Err(Error::IncompleteHeader), - }, - ), + } + }), ) } @@ -174,12 +174,12 @@ pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result Ok(header), false => Err(Error::IncompleteHeader), - }, - ), + } + }), ) } diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 89e8572ccaaba..66e5aee67282b 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -88,7 +88,7 @@ pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEther extra_data: header.extra_data.0.clone(), state_root: header.state_root, receipts_root: header.receipts_root, - log_bloom: header.logs_bloom.data().into(), + log_bloom: header.logs_bloom.unwrap_or_default().data().into(), gas_used: header.gas_used, gas_limit: header.gas_limit, difficulty: header.difficulty, From 3cd0aa1078e3d5f1cea6debdc5590312db4e9308 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 20 May 2020 17:54:27 +0300 Subject: [PATCH 0054/1210] Mute warnings from Substrate <-> Substrate runtime module and relay (#104) * mute warnings from sub2sub module+relay * cargo fmt --all --- modules/substrate/src/lib.rs | 2 ++ relays/substrate/src/main.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index efbe0904e6bd8..cb6142e426f84 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -47,6 +47,8 @@ //! || || //!``` +// TODO: when (if) this module will be resurrected, remove this +#![allow(dead_code)] // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 7185313a57114..550ae986b79c9 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +// TODO: when (if) this relay will be resurrected, remove this +#![allow(unused_variables)] +#![allow(dead_code)] + mod bridge; mod error; mod params; From 75b79c84daa5cbdfa85a099bdf1263d9534948e7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 20 May 2020 11:53:41 -0400 Subject: [PATCH 0055/1210] Use `CallRequest` type from rust-web3 crate (#101) * Use `CallRequest` type from rust-web3 crate * Change CallRequest's `to` field to be optional Required due to changes in upstream `rust-web3` crate. --- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/ethereum_client.rs | 19 ++++++++----------- relays/ethereum/src/ethereum_types.rs | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index c41b13d22ed42..4a05cba9420eb 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -28,7 +28,7 @@ serde = { version = "1.0.110", features = ["derive"] } serde_json = "1.0.53" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" -web3 = "0.11" +web3 = { git = "https://github.com/tomusdrw/rust-web3" } # Substrate Based Dependencies [dependencies.frame-system] diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 974d5ddeff7ba..110c8733c03b6 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{Address, Bytes, EthereumHeaderId, Header, Receipt, TransactionHash, H256, U256, U64}; +use crate::ethereum_types::{ + Address, Bytes, CallRequest, EthereumHeaderId, Header, Receipt, TransactionHash, H256, U256, U64, +}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; use crate::sync_types::{HeaderId, MaybeConnectionError}; use crate::{bail_on_arg_error, bail_on_error}; @@ -24,7 +26,7 @@ use jsonrpsee::common::Params; use jsonrpsee::raw::{RawClient, RawClientError}; use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; use parity_crypto::publickey::KeyPair; -use serde::{de::DeserializeOwned, Serialize}; +use serde::de::DeserializeOwned; use serde_json::{from_value, to_value}; use std::collections::HashSet; @@ -87,15 +89,6 @@ impl Default for EthereumSigningParams { /// Ethereum client type. pub type Client = RawClient; -/// Ethereum contract call request. -#[derive(Debug, Default, PartialEq, Serialize)] -pub struct CallRequest { - /// Contract address. - pub to: Option

, - /// Call data. - pub data: Option, -} - /// All possible errors that can occur during interacting with Ethereum node. #[derive(Debug)] pub enum Error { @@ -225,6 +218,7 @@ pub async fn best_substrate_block( to_value(CallRequest { to: Some(contract_address), data: Some(encoded_call.into()), + ..Default::default() }) .map_err(|e| Error::RequestSerialization(e)), client @@ -258,6 +252,7 @@ pub async fn substrate_header_known( to_value(CallRequest { to: Some(contract_address), data: Some(encoded_call.into()), + ..Default::default() }) .map_err(|e| Error::RequestSerialization(e)), client @@ -311,6 +306,7 @@ pub async fn incomplete_substrate_headers( to_value(CallRequest { to: Some(contract_address), data: Some(encoded_call.into()), + ..Default::default() }) .map_err(|e| Error::RequestSerialization(e)), client @@ -398,6 +394,7 @@ async fn submit_ethereum_transaction( CallRequest { to: contract_address, data: Some(encoded_call.clone().into()), + ..Default::default() } ) .await diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index 4731570d4d873..fcd87952e40d5 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -18,7 +18,7 @@ use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethe use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; use codec::Encode; -pub use web3::types::{Address, Bytes, H256, U128, U256, U64}; +pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; /// When header is just received from the Ethereum node, we check that it has /// both number and hash fields filled. From 0992bd43690c9444ec9a4eb1f49e60af1a02e449 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 22 May 2020 14:52:00 -0400 Subject: [PATCH 0056/1210] RPC Module for Relays (#80) * Test defining an RPC API * Add wrapper clients for the RPC API * Implement most Ethereum RPCs Does not include RPCs that require the bridge contract. * Implement a few of the Substrate RPCs Still missing proper error handling, as well as decoding responses from the Substrate node. * Make error handling more ergonomic * Implement Substrate RPCs that use `state_call` * Implement rest of Substrate RPCs * Implement `eth_call` RPC This can be used to implement higher level requests like fetching Substrate headers from an Ethereum node. * Build some of the higher level Ethereum RPCs Uses the new Ethereum RPC interface to do so * Build some of the higher level Substrate RPCs * Remove old Ethereum RPC methods * Remove old Substrate RPC methods * Add some documentation to Substrate RPCs * Fix typo in enum construction * Revert commits `0f0435d` to `ca75502` This range of commits was mainly trying to integrate the new RPC interface into the existing codebase, however this turned out to be a little out of scope for the current PR. Instead this work will be incorporated into a PR which aims to close #72. * Add documentation to RPCs * Rename functions in RPC API to conform to snake_case * Check that header contains a number and hash * Put doc comments on trait instead of impl methods * Remove expect() calls * Replace runtime API enums with consts * Accept Bytes when submitting extrinsic Let's us avoid using a runtime specific Extrinsic. * Add strictly typed arguments to RPC API Missing two methods right now, which require a `serde::Deserialize` implemenation before they can be changed. * Add `chain_getBlock` Substrate RPC * Use typed arguments for `eth_estimateGas` and `eth_call` * Silence dead code warnings * Add check for logs bloom * Remove unused variables * Add documentation to RPC error enums --- relays/ethereum/Cargo.toml | 1 + relays/ethereum/src/ethereum_types.rs | 3 + relays/ethereum/src/main.rs | 2 + relays/ethereum/src/rpc.rs | 301 ++++++++++++++++++++++++++ relays/ethereum/src/rpc_errors.rs | 98 +++++++++ 5 files changed, 405 insertions(+) create mode 100644 relays/ethereum/src/rpc.rs create mode 100644 relays/ethereum/src/rpc_errors.rs diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4a05cba9420eb..ff603639e43cf 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" ansi_term = "0.12" async-std = "1.0.1" async-stream = "0.2.0" +async-trait = "0.1.30" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index fcd87952e40d5..46ba869ac2a59 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -43,6 +43,9 @@ pub type EthereumHeaderId = HeaderId; /// Queued ethereum header ID. pub type QueuedEthereumHeader = QueuedHeader; +/// A raw Ethereum transaction that's been signed. +pub type SignedRawTx = Vec; + /// Ethereum synchronization pipeline. #[derive(Clone, Copy, Debug)] #[cfg_attr(test, derive(PartialEq))] diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index ae46468f8fa5e..c17582e23cb0c 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -21,6 +21,8 @@ mod ethereum_deploy_contract; mod ethereum_sync_loop; mod ethereum_types; mod headers; +mod rpc; +mod rpc_errors; mod substrate_client; mod substrate_sync_loop; mod substrate_types; diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs new file mode 100644 index 0000000000000..70c775a268fbe --- /dev/null +++ b/relays/ethereum/src/rpc.rs @@ -0,0 +1,301 @@ +// Copyright 2019-2020 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 . + +//! RPC Module + +#![allow(dead_code)] +#![allow(unused_variables)] +#[warn(missing_docs)] +use std::result; + +use crate::ethereum_client::EthereumConnectionParams; +use crate::ethereum_types::{ + Address as EthAddress, Bytes, CallRequest, EthereumHeaderId, Header as EthereumHeader, Receipt, SignedRawTx, + TransactionHash as EthereumTxHash, H256, U256, U64, +}; +use crate::rpc_errors::{EthereumNodeError, RpcError}; +use crate::substrate_client::SubstrateConnectionParams; +use crate::substrate_types::{ + Hash as SubstrateHash, Header as SubstrateHeader, Number as SubBlockNumber, SignedBlock as SubstrateBlock, +}; +use crate::sync_types::HeaderId; + +use async_trait::async_trait; +use codec::{Decode, Encode}; +use jsonrpsee::raw::client::RawClient; +use jsonrpsee::transport::http::HttpTransportClient; +use sp_bridge_eth_poa::Header as SubstrateEthereumHeader; + +const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; +const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; +const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; +const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; + +type Result = result::Result; +type GrandpaAuthorityList = Vec; + +jsonrpsee::rpc_api! { + Ethereum { + #[rpc(method = "eth_estimateGas")] + fn estimate_gas(call_request: CallRequest) -> U256; + #[rpc(method = "eth_blockNumber")] + fn block_number() -> U64; + #[rpc(method = "eth_getBlockByNumber")] + fn get_block_by_number(block_number: u64) -> EthereumHeader; + #[rpc(method = "eth_getBlockByHash")] + fn get_block_by_hash(hash: H256) -> EthereumHeader; + #[rpc(method = "eth_getTransactionReceipt")] + fn get_transaction_receipt(transaction_hash: H256) -> Receipt; + #[rpc(method = "eth_getTransactionCount")] + fn get_transaction_count(address: EthAddress) -> U256; + #[rpc(method = "eth_submitTransaction")] + fn submit_transaction(transaction: Bytes) -> EthereumTxHash; + #[rpc(method = "eth_call")] + fn call(transaction_call: CallRequest) -> Bytes; + } + + Substrate { + #[rpc(method = "chain_getHeader")] + fn chain_get_header(block_hash: Option) -> SubstrateHeader; + #[rpc(method = "chain_getBlock")] + fn chain_get_block(block_hash: Option) -> SubstrateBlock; + #[rpc(method = "chain_getBlockHash")] + fn chain_get_block_hash(block_number: Option) -> SubstrateHash; + #[rpc(method = "system_accountNextIndex")] + fn system_account_next_index(account_id: node_primitives::AccountId) -> node_primitives::Index; + #[rpc(method = "author_submitExtrinsic")] + fn author_submit_extrinsic(extrinsic: Bytes) -> SubstrateHash; + #[rpc(method = "state_call")] + fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; + } +} + +/// The API for the supported Ethereum RPC methods. +#[async_trait] +pub trait EthereumRpc { + /// Estimate gas usage for the given call. + async fn estimate_gas(&mut self, call_request: CallRequest) -> Result; + /// Retrieve number of the best known block from the Ethereum node. + async fn best_block_number(&mut self) -> Result; + /// Retrieve block header by its number from Ethereum node. + async fn header_by_number(&mut self, block_number: u64) -> Result; + /// Retrieve block header by its hash from Ethereum node. + async fn header_by_hash(&mut self, hash: H256) -> Result; + /// Retrieve transaction receipt by transaction hash. + async fn transaction_receipt(&mut self, transaction_hash: H256) -> Result; + /// Get the nonce of the given account. + async fn account_nonce(&mut self, address: EthAddress) -> Result; + /// Submit an Ethereum transaction. + /// + /// The transaction must already be signed before sending it through this method. + async fn submit_transaction(&mut self, signed_raw_tx: SignedRawTx) -> Result; + /// Submit a call to an Ethereum smart contract. + async fn eth_call(&mut self, call_transaction: CallRequest) -> Result; +} + +/// The client used to interact with an Ethereum node through RPC. +pub struct EthereumRpcClient { + client: RawClient, +} + +impl EthereumRpcClient { + /// Create a new Ethereum RPC Client. + pub fn new(params: EthereumConnectionParams) -> Self { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); + let client = RawClient::new(transport); + + Self { client } + } +} + +#[async_trait] +impl EthereumRpc for EthereumRpcClient { + async fn estimate_gas(&mut self, call_request: CallRequest) -> Result { + Ok(Ethereum::estimate_gas(&mut self.client, call_request).await?) + } + + async fn best_block_number(&mut self) -> Result { + Ok(Ethereum::block_number(&mut self.client).await?.as_u64()) + } + + async fn header_by_number(&mut self, block_number: u64) -> Result { + let header = Ethereum::get_block_by_number(&mut self.client, block_number).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), + } + } + + async fn header_by_hash(&mut self, hash: H256) -> Result { + let header = Ethereum::get_block_by_hash(&mut self.client, hash).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), + } + } + + async fn transaction_receipt(&mut self, transaction_hash: H256) -> Result { + let receipt = Ethereum::get_transaction_receipt(&mut self.client, transaction_hash).await?; + + match receipt.gas_used { + Some(_) => Ok(receipt), + None => Err(RpcError::Ethereum(EthereumNodeError::IncompleteReceipt)), + } + } + + async fn account_nonce(&mut self, address: EthAddress) -> Result { + Ok(Ethereum::get_transaction_count(&mut self.client, address).await?) + } + + async fn submit_transaction(&mut self, signed_raw_tx: SignedRawTx) -> Result { + let transaction = Bytes(signed_raw_tx); + Ok(Ethereum::submit_transaction(&mut self.client, transaction).await?) + } + + async fn eth_call(&mut self, call_transaction: CallRequest) -> Result { + Ok(Ethereum::call(&mut self.client, call_transaction).await?) + } +} + +/// The API for the supported Substrate RPC methods. +#[async_trait] +pub trait SubstrateRpc { + /// Returns the best Substrate header. + async fn best_header(&mut self) -> Result; + /// Get a Substrate block from its hash. + async fn get_block(&mut self, block_hash: Option) -> Result; + /// Get a Substrate header by its hash. + async fn header_by_hash(&mut self, hash: SubstrateHash) -> Result; + /// Get a Substrate block hash by its number. + async fn block_hash_by_number(&mut self, number: SubBlockNumber) -> Result; + /// Get a Substrate header by its number. + async fn header_by_number(&mut self, block_number: SubBlockNumber) -> Result; + /// Get the nonce of the given Substrate account. + /// + /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. + async fn next_account_index(&mut self, account: node_primitives::AccountId) -> Result; + /// Returns best Ethereum block that Substrate runtime knows of. + async fn best_ethereum_block(&mut self) -> Result; + /// Returns whether or not transactions receipts are required for Ethereum header submission. + async fn ethereum_receipts_required(&mut self, header: SubstrateEthereumHeader) -> Result; + /// Returns whether or not the given Ethereum header is known to the Substrate runtime. + async fn ethereum_header_known(&mut self, header_id: EthereumHeaderId) -> Result; + /// Submit an extrinsic for inclusion in a block. + /// + /// Note: The given transaction does not need be SCALE encoded beforehand. + async fn submit_extrinsic(&mut self, transaction: Bytes) -> Result; + /// Get the GRANDPA authority set at given block. + async fn grandpa_authorities_set(&mut self, block: SubstrateHash) -> Result; +} + +/// The client used to interact with a Substrate node through RPC. +pub struct SubstrateRpcClient { + client: RawClient, +} + +impl SubstrateRpcClient { + /// Create a new Substrate RPC Client. + pub fn new(params: SubstrateConnectionParams) -> Self { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); + let client = RawClient::new(transport); + + Self { client } + } +} + +#[async_trait] +impl SubstrateRpc for SubstrateRpcClient { + async fn best_header(&mut self) -> Result { + Ok(Substrate::chain_get_header(&mut self.client, None).await?) + } + + async fn get_block(&mut self, block_hash: Option) -> Result { + Ok(Substrate::chain_get_block(&mut self.client, block_hash).await?) + } + + async fn header_by_hash(&mut self, block_hash: SubstrateHash) -> Result { + Ok(Substrate::chain_get_header(&mut self.client, block_hash).await?) + } + + async fn block_hash_by_number(&mut self, number: SubBlockNumber) -> Result { + Ok(Substrate::chain_get_block_hash(&mut self.client, number).await?) + } + + async fn header_by_number(&mut self, block_number: SubBlockNumber) -> Result { + let block_hash = Self::block_hash_by_number(self, block_number).await?; + Ok(Self::header_by_hash(self, block_hash).await?) + } + + async fn next_account_index(&mut self, account: node_primitives::AccountId) -> Result { + Ok(Substrate::system_account_next_index(&mut self.client, account).await?) + } + + async fn best_ethereum_block(&mut self) -> Result { + let call = ETH_API_BEST_BLOCK.to_string(); + let data = Bytes("0x".into()); + + let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; + let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + Ok(best_header_id) + } + + async fn ethereum_receipts_required(&mut self, header: SubstrateEthereumHeader) -> Result { + let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); + let data = Bytes(header.encode()); + + let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; + let receipts_required: bool = Decode::decode(&mut &encoded_response.0[..])?; + + // Gonna make it the responsibility of the caller to return (receipts_required, id) + Ok(receipts_required) + } + + // The Substrate module could prune old headers. So this function could return false even + // if header is synced. And we'll mark corresponding Ethereum header as Orphan. + // + // But when we read the best header from Substrate next time, we will know that + // there's a better header. This Orphan will either be marked as synced, or + // eventually pruned. + async fn ethereum_header_known(&mut self, header_id: EthereumHeaderId) -> Result { + let call = ETH_API_IS_KNOWN_BLOCK.to_string(); + let data = Bytes(header_id.1.encode()); + + let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; + let is_known_block: bool = Decode::decode(&mut &encoded_response.0[..])?; + + // Gonna make it the responsibility of the caller to return (is_known_block, id) + Ok(is_known_block) + } + + async fn submit_extrinsic(&mut self, transaction: Bytes) -> Result { + let encoded_transaction = Bytes(transaction.0.encode()); + Ok(Substrate::author_submit_extrinsic(&mut self.client, encoded_transaction).await?) + } + + async fn grandpa_authorities_set(&mut self, block: SubstrateHash) -> Result { + let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); + let data = Bytes(block.as_bytes().to_vec()); + + let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; + let authority_list = encoded_response.0; + + Ok(authority_list) + } +} diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs new file mode 100644 index 0000000000000..86758b559920b --- /dev/null +++ b/relays/ethereum/src/rpc_errors.rs @@ -0,0 +1,98 @@ +// Copyright 2019-2020 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 . + +#![allow(dead_code)] + +use jsonrpsee::raw::client::RawClientError; +use jsonrpsee::transport::http::RequestError; +use serde_json; + +type RpcHttpError = RawClientError; + +/// Contains common errors that can occur when +/// interacting with a Substrate or Ethereum node +/// through RPC. +#[derive(Debug)] +pub enum RpcError { + /// The arguments to the RPC method failed to serialize. + Serialization(serde_json::Error), + /// An error occured when interacting with an Ethereum node. + Ethereum(EthereumNodeError), + /// An error occured when interacting with a Substrate node. + Substrate(SubstrateNodeError), + /// An error that can occur when making an HTTP request to + /// an JSON-RPC client. + Request(RpcHttpError), + /// The response from the client could not be SCALE decoded. + Decoding(codec::Error), +} + +impl From for RpcError { + fn from(err: serde_json::Error) -> Self { + Self::Serialization(err) + } +} + +impl From for RpcError { + fn from(err: EthereumNodeError) -> Self { + Self::Ethereum(err) + } +} + +impl From for RpcError { + fn from(err: SubstrateNodeError) -> Self { + Self::Substrate(err) + } +} + +impl From for RpcError { + fn from(err: RpcHttpError) -> Self { + Self::Request(err) + } +} + +impl From for RpcError { + fn from(err: codec::Error) -> Self { + Self::Decoding(err) + } +} + +/// Errors that can occur only when interacting with +/// an Ethereum node through RPC. +#[derive(Debug)] +pub enum EthereumNodeError { + /// Failed to parse response. + ResponseParseFailed(String), + /// We have received a header with missing fields. + IncompleteHeader, + /// We have received a receipt missing a `gas_used` field. + IncompleteReceipt, + /// An invalid Substrate block number was received from + /// an Ethereum node. + InvalidSubstrateBlockNumber, +} + +/// Errors that can occur only when interacting with +/// a Substrate node through RPC. +#[derive(Debug)] +pub enum SubstrateNodeError { + /// Request start failed. + StartRequestFailed(RequestError), + /// Error serializing request. + RequestSerialization(serde_json::Error), + /// Failed to parse response. + ResponseParseFailed, +} From 8e266946b25bead4237d64aad705376a8b0f986f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 27 May 2020 17:11:11 +0000 Subject: [PATCH 0057/1210] Bump async-trait from 0.1.30 to 0.1.31 (#106) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index ff603639e43cf..08aae247fba21 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" ansi_term = "0.12" async-std = "1.0.1" async-stream = "0.2.0" -async-trait = "0.1.30" +async-trait = "0.1.31" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" From 4eb2bc37f06024ba48117d1659a9ce118a7fb450 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 27 May 2020 18:18:02 +0000 Subject: [PATCH 0058/1210] Bump async-std from 1.5.0 to 1.6.0 (#107) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 08aae247fba21..eea95027a25f5 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] ansi_term = "0.12" -async-std = "1.0.1" +async-std = "1.6.0" async-stream = "0.2.0" async-trait = "0.1.31" clap = { version = "2.33.1", features = ["yaml"] } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index f8bac8a06673d..16f0a3da53b5d 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -async-std = "1.0.1" +async-std = "1.6.0" clap = "2.33.1" ctrlc = "3.1.4" derive_more = "0.99.7" From dcb796f4215b1c7781f005324f1252d0f40897ad Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2020 01:53:06 +0000 Subject: [PATCH 0059/1210] Bump serde from 1.0.110 to 1.0.111 (#114) --- bin/node/runtime/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 65b0484007b65..d0281b1d30f40 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -13,7 +13,7 @@ default-features = false features = ["derive"] [dependencies.serde] -version = "1.0.110" +version = "1.0.111" optional = true features = ["derive"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index eea95027a25f5..50db2c4b6da0a 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -25,7 +25,7 @@ num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" -serde = { version = "1.0.110", features = ["derive"] } +serde = { version = "1.0.111", features = ["derive"] } serde_json = "1.0.53" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" From 91c0df9d1857e91f084a19e7e83075d6f466e91c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 Jun 2020 17:51:12 +0300 Subject: [PATCH 0060/1210] Use runtime storage in PoA -> Substrate module tests (#103) * removeInMemoryStorage + extract Kovan stuff to runtime * removed comment from the future * remove redundant conversions * remove redundant `u8 as usize` * remove redundant `u8 as usize` * Update modules/ethereum/src/mock.rs Co-authored-by: Hernando Castano * use hex-literal in kovan config * cargo fmt --all * extracted insert_header * cargo fmt --all Co-authored-by: Hernando Castano --- bin/node/node/src/chain_spec.rs | 81 +---- bin/node/runtime/Cargo.toml | 3 + bin/node/runtime/src/kovan.rs | 104 ++++++ bin/node/runtime/src/lib.rs | 9 + modules/ethereum/src/finality.rs | 186 ++++++----- modules/ethereum/src/import.rs | 339 ++++++++++--------- modules/ethereum/src/lib.rs | 481 +-------------------------- modules/ethereum/src/mock.rs | 179 ++++++++++ modules/ethereum/src/validators.rs | 3 +- modules/ethereum/src/verification.rs | 180 ++++++---- primitives/ethereum-poa/src/lib.rs | 1 - 11 files changed, 690 insertions(+), 876 deletions(-) create mode 100644 bin/node/runtime/src/kovan.rs create mode 100644 modules/ethereum/src/mock.rs diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 11a31c7ae1cb5..7127ee8d77193 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -169,85 +169,8 @@ fn testnet_genesis( fn load_kovan_config() -> Option { Some(BridgeEthPoAConfig { - initial_header: sp_bridge_eth_poa::Header { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - .parse() - .unwrap(), - uncles_hash: "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - .parse() - .unwrap(), - extra_data: vec![], - state_root: "2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2" - .parse() - .unwrap(), - receipts_root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - .parse() - .unwrap(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 6000000.into(), - difficulty: 131072.into(), - seal: vec![ - vec![128].into(), - vec![ - 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - ] - .into(), - ], - }, + initial_header: bridge_node_runtime::kovan::kovan_genesis_header(), initial_difficulty: 0.into(), - initial_validators: vec![ - [ - 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, 0x5B, - 0xAd, 0xc0, 0xED, - ] - .into(), - [ - 0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, 0x65, - 0x0a, 0x4d, 0x3d, - ] - .into(), - [ - 0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, 0x6b, - 0x42, 0x4d, 0x6c, - ] - .into(), - [ - 0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, 0x19, - 0xbA, 0x81, 0xA1, - ] - .into(), - [ - 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, 0x3a, - 0xfd, 0x03, 0x2d, - ] - .into(), - [ - 0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, 0x16, - 0x93, 0x38, 0x7A, - ] - .into(), - [ - 0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, 0x78, - 0x89, 0x78, 0x79, - ] - .into(), - [ - 0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, 0x16, - 0xa1, 0x64, 0x5c, - ] - .into(), - [ - 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, 0x12, - 0x31, 0x94, 0xde, - ] - .into(), - ], + initial_validators: bridge_node_runtime::kovan::kovan_genesis_validators(), }) } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index d0281b1d30f40..92351e0c44c27 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -6,6 +6,9 @@ edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" +[dependencies] +hex-literal = "0.2" + [dependencies.codec] package = "parity-scale-codec" version = "1.0.0" diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs new file mode 100644 index 0000000000000..2592d8e057b26 --- /dev/null +++ b/bin/node/runtime/src/kovan.rs @@ -0,0 +1,104 @@ +// Copyright 2019-2020 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 . + +use hex_literal::hex; +use pallet_bridge_eth_poa::{AuraConfiguration, ValidatorsConfiguration, ValidatorsSource}; +use sp_bridge_eth_poa::{Address, Header, U256}; +use sp_std::prelude::*; + +/// Aura engine configuration for Kovan chain. +pub fn kovan_aura_configuration() -> AuraConfiguration { + AuraConfiguration { + empty_steps_transition: u64::max_value(), + strict_empty_steps_transition: 0, + validate_step_transition: 0x16e360, + validate_score_transition: 0x41a3c4, + two_thirds_majority_transition: u64::max_value(), + min_gas_limit: 0x1388.into(), + max_gas_limit: U256::max_value(), + maximum_extra_data_size: 0x20, + } +} + +/// Validators configuration for Kovan chain. +pub fn kovan_validators_configuration() -> ValidatorsConfiguration { + ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(kovan_genesis_validators())), + ( + 10960440, + ValidatorsSource::List(vec![ + hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(), + hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(), + hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(), + ]), + ), + ( + 10960500, + ValidatorsSource::Contract( + hex!("aE71807C1B0a093cB1547b682DC78316D945c9B8").into(), + vec![ + hex!("d05f7478c6aa10781258c5cc8b4f385fc8fa989c").into(), + hex!("03801efb0efe2a25ede5dd3a003ae880c0292e4d").into(), + hex!("a4df255ecf08bbf2c28055c65225c9a9847abd94").into(), + hex!("596e8221a30bfe6e7eff67fee664a01c73ba3c56").into(), + hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(), + ], + ), + ), + ]) +} + +/// Genesis validators set of Kovan chain. +pub fn kovan_genesis_validators() -> Vec
{ + vec![ + hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(), + hex!("00427feae2419c15b89d1c21af10d1b6650a4d3d").into(), + hex!("4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c").into(), + hex!("0020ee4Be0e2027d76603cB751eE069519bA81A1").into(), + hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(), + hex!("007733a1FE69CF3f2CF989F81C7b4cAc1693387A").into(), + hex!("00E6d2b931F55a3f1701c7389d592a7778897879").into(), + hex!("00e4a10650e5a6D6001C38ff8E64F97016a1645c").into(), + hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(), + ] +} + +/// Genesis header of the Kovan chain. +pub fn kovan_genesis_header() -> Header { + Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), + extra_data: vec![], + state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(), + receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 6000000.into(), + difficulty: 131072.into(), + seal: vec![ + vec![128].into(), + vec![ + 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ] + .into(), + ], + } +} diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 45db36476e3df..ff4d796cf93a2 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -24,6 +24,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod kovan; + use codec::{Decode, Encode}; use pallet_grandpa::fg_primitives; use pallet_grandpa::AuthorityList as GrandpaAuthorityList; @@ -204,7 +206,14 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } +parameter_types! { + pub const KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); + pub const KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = kovan::kovan_validators_configuration(); +} + impl pallet_bridge_eth_poa::Trait for Runtime { + type AuraConfiguration = KovanAuraConfiguration; + type ValidatorsConfiguration = KovanValidatorsConfiguration; type OnHeadersSubmitted = (); } diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 1ee9f356028e7..676108a30dc68 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -214,106 +214,110 @@ pub(crate) fn ancestry<'a, S: Storage>( #[cfg(test)] mod tests { use super::*; - use crate::tests::{genesis, validator, validators_addresses, InMemoryStorage}; - use crate::HeaderToImport; + use crate::mock::{custom_test_ext, genesis, validator, validators_addresses, TestRuntime}; + use crate::{BridgeStorage, HeaderToImport}; #[test] fn verifies_header_author() { - assert_eq!( - finalize_blocks( - &InMemoryStorage::new(genesis(), validators_addresses(5)), - &Default::default(), - (&Default::default(), &[]), - &Default::default(), - None, - &Header::default(), - 0, - ), - Err(Error::NotValidator), - ); + custom_test_ext(genesis(), validators_addresses(5)).execute_with(|| { + assert_eq!( + finalize_blocks( + &BridgeStorage::::new(), + &Default::default(), + (&Default::default(), &[]), + &Default::default(), + None, + &Header::default(), + 0, + ), + Err(Error::NotValidator), + ); + }); } #[test] fn prepares_votes() { - // let's say we have 5 validators (we need 'votes' from 3 validators to achieve - // finality) - let mut storage = InMemoryStorage::new(genesis(), validators_addresses(5)); + custom_test_ext(genesis(), validators_addresses(5)).execute_with(|| { + // let's say we have 5 validators (we need 'votes' from 3 validators to achieve + // finality) + let mut storage = BridgeStorage::::new(); - // when header#1 is inserted, nothing is finalized (1 vote) - let header1 = Header { - author: validator(0).address().as_fixed_bytes().into(), - parent_hash: genesis().hash(), - number: 1, - ..Default::default() - }; - let hash1 = header1.hash(); - let mut header_to_import = HeaderToImport { - context: storage.import_context(None, &genesis().hash()).unwrap(), - is_best: true, - hash: hash1, - header: header1, - total_difficulty: 0.into(), - enacted_change: None, - scheduled_change: None, - }; - assert_eq!( - finalize_blocks( - &storage, - &Default::default(), - (&Default::default(), &validators_addresses(5)), - &hash1, - None, - &header_to_import.header, - u64::max_value(), - ), - Ok(Vec::new()), - ); - storage.insert_header(header_to_import.clone()); + // when header#1 is inserted, nothing is finalized (1 vote) + let header1 = Header { + author: validator(0).address().as_fixed_bytes().into(), + parent_hash: genesis().hash(), + number: 1, + ..Default::default() + }; + let hash1 = header1.hash(); + let mut header_to_import = HeaderToImport { + context: storage.import_context(None, &genesis().hash()).unwrap(), + is_best: true, + hash: hash1, + header: header1, + total_difficulty: 0.into(), + enacted_change: None, + scheduled_change: None, + }; + assert_eq!( + finalize_blocks( + &storage, + &Default::default(), + (&Default::default(), &validators_addresses(5)), + &hash1, + None, + &header_to_import.header, + u64::max_value(), + ), + Ok(Vec::new()), + ); + storage.insert_header(header_to_import.clone()); - // when header#2 is inserted, nothing is finalized (2 votes) - header_to_import.header = Header { - author: validator(1).address().as_fixed_bytes().into(), - parent_hash: hash1, - number: 2, - ..Default::default() - }; - header_to_import.hash = header_to_import.header.hash(); - let hash2 = header_to_import.header.hash(); - assert_eq!( - finalize_blocks( - &storage, - &Default::default(), - (&Default::default(), &validators_addresses(5)), - &hash2, - None, - &header_to_import.header, - u64::max_value(), - ), - Ok(Vec::new()), - ); - storage.insert_header(header_to_import.clone()); + // when header#2 is inserted, nothing is finalized (2 votes) + header_to_import.header = Header { + author: validator(1).address().as_fixed_bytes().into(), + parent_hash: hash1, + number: 2, + ..Default::default() + }; + header_to_import.hash = header_to_import.header.hash(); + let hash2 = header_to_import.header.hash(); + assert_eq!( + finalize_blocks( + &storage, + &Default::default(), + (&Default::default(), &validators_addresses(5)), + &hash2, + None, + &header_to_import.header, + u64::max_value(), + ), + Ok(Vec::new()), + ); + storage.insert_header(header_to_import.clone()); - // when header#3 is inserted, header#1 is finalized (3 votes) - header_to_import.header = Header { - author: validator(2).address().as_fixed_bytes().into(), - parent_hash: hash2, - number: 3, - ..Default::default() - }; - header_to_import.hash = header_to_import.header.hash(); - let hash3 = header_to_import.header.hash(); - assert_eq!( - finalize_blocks( - &storage, - &Default::default(), - (&Default::default(), &validators_addresses(5)), - &hash3, - None, - &header_to_import.header, - u64::max_value(), - ), - Ok(vec![(1, hash1, None)]), - ); - storage.insert_header(header_to_import); + // when header#3 is inserted, header#1 is finalized (3 votes) + header_to_import.header = Header { + author: validator(2).address().as_fixed_bytes().into(), + parent_hash: hash2, + number: 3, + ..Default::default() + }; + header_to_import.hash = header_to_import.header.hash(); + let hash3 = header_to_import.header.hash(); + assert_eq!( + finalize_blocks( + &storage, + &Default::default(), + (&Default::default(), &validators_addresses(5)), + &hash3, + None, + &header_to_import.header, + u64::max_value(), + ), + Ok(vec![(1, hash1, None)]), + ); + storage.insert_header(header_to_import); + }); } } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 20a5d10e457ec..17c7237fab612 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -166,214 +166,221 @@ pub fn header_import_requires_receipts( #[cfg(test)] mod tests { use super::*; - use crate::tests::{ - block_i, custom_block_i, genesis, signed_header, validator, validators_addresses, InMemoryStorage, + use crate::mock::{ + block_i, custom_block_i, custom_test_ext, genesis, signed_header, test_aura_config, test_validators_config, + validator, validators, validators_addresses, TestRuntime, }; use crate::validators::ValidatorsSource; - use crate::{kovan_aura_config, kovan_validators_config}; + use crate::{BridgeStorage, Headers, OldestUnprunedBlock}; + use frame_support::{StorageMap, StorageValue}; #[test] fn rejects_finalized_block_competitors() { - let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); - storage.finalize_headers(Some((100, Default::default())), None); - assert_eq!( - import_header( - &mut storage, - &kovan_aura_config(), - &kovan_validators_config(), - PRUNE_DEPTH, - None, - Default::default(), - None, - ), - Err(Error::AncientHeader), - ); + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let mut storage = BridgeStorage::::new(); + storage.finalize_headers(Some((100, Default::default())), None); + assert_eq!( + import_header( + &mut storage, + &test_aura_config(), + &test_validators_config(), + PRUNE_DEPTH, + None, + Default::default(), + None, + ), + Err(Error::AncientHeader), + ); + }); } #[test] fn rejects_known_header() { - let validators = (0..3).map(|i| validator(i as u8)).collect::>(); - let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); - let block = block_i(&storage, 1, &validators); - assert_eq!( - import_header( - &mut storage, - &kovan_aura_config(), - &kovan_validators_config(), - PRUNE_DEPTH, - None, - block.clone(), - None, - ) - .map(|_| ()), - Ok(()), - ); - assert_eq!( - import_header( - &mut storage, - &kovan_aura_config(), - &kovan_validators_config(), - PRUNE_DEPTH, - None, - block, - None, - ) - .map(|_| ()), - Err(Error::KnownHeader), - ); + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let validators = validators(3); + let mut storage = BridgeStorage::::new(); + let block = block_i(1, &validators); + assert_eq!( + import_header( + &mut storage, + &test_aura_config(), + &test_validators_config(), + PRUNE_DEPTH, + None, + block.clone(), + None, + ) + .map(|_| ()), + Ok(()), + ); + assert_eq!( + import_header( + &mut storage, + &test_aura_config(), + &test_validators_config(), + PRUNE_DEPTH, + None, + block, + None, + ) + .map(|_| ()), + Err(Error::KnownHeader), + ); + }); } #[test] fn import_header_works() { - let validators_config = ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(validators_addresses(3))), - (1, ValidatorsSource::List(validators_addresses(2))), - ]); - let validators = (0..3).map(|i| validator(i as u8)).collect::>(); - let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); - let header = block_i(&storage, 1, &validators); - let hash = header.hash(); - assert_eq!( - import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - PRUNE_DEPTH, - None, - header, - None - ) - .map(|_| ()), - Ok(()), - ); + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let validators_config = ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(validators_addresses(3))), + (1, ValidatorsSource::List(validators_addresses(2))), + ]); + let validators = validators(3); + let mut storage = BridgeStorage::::new(); + let header = block_i(1, &validators); + let hash = header.hash(); + assert_eq!( + import_header( + &mut storage, + &test_aura_config(), + &validators_config, + PRUNE_DEPTH, + None, + header, + None + ) + .map(|_| ()), + Ok(()), + ); - // check that new validators will be used for next header - let imported_header = storage.stored_header(&hash).unwrap(); - assert_eq!( - imported_header.next_validators_set_id, - 1, // new set is enacted from config - ); + // check that new validators will be used for next header + let imported_header = Headers::::get(&hash).unwrap(); + assert_eq!( + imported_header.next_validators_set_id, + 1, // new set is enacted from config + ); + }); } #[test] fn headers_are_pruned() { - let validators_config = - ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), validators_addresses(3))); - let validators = vec![validator(0), validator(1), validator(2)]; - let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let validators_config = + ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), validators_addresses(3))); + let validators = vec![validator(0), validator(1), validator(2)]; + let mut storage = BridgeStorage::::new(); - // header [0..11] are finalizing blocks [0; 9] - // => since we want to keep 10 finalized blocks, we aren't pruning anything - let mut latest_block_hash = Default::default(); - for i in 1..11 { - let header = block_i(&storage, i, &validators); + // header [0..11] are finalizing blocks [0; 9] + // => since we want to keep 10 finalized blocks, we aren't pruning anything + let mut latest_block_hash = Default::default(); + for i in 1..11 { + let header = block_i(i, &validators); + let (rolling_last_block_hash, finalized_blocks) = import_header( + &mut storage, + &test_aura_config(), + &validators_config, + 10, + Some(100), + header, + None, + ) + .unwrap(); + match i { + 2..=10 => assert_eq!( + finalized_blocks, + vec![(i - 1, block_i(i - 1, &validators).hash(), Some(100))], + "At {}", + i, + ), + _ => assert_eq!(finalized_blocks, vec![], "At {}", i), + } + latest_block_hash = rolling_last_block_hash; + } + assert!(storage.header(&genesis().hash()).is_some()); + + // header 11 finalizes headers [10] AND schedules change + // => we prune header#0 + let header11 = custom_block_i(11, &validators, |header| { + header.log_bloom = (&[0xff; 256]).into(); + header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951" + .parse() + .unwrap(); + }); let (rolling_last_block_hash, finalized_blocks) = import_header( &mut storage, - &kovan_aura_config(), + &test_aura_config(), &validators_config, 10, - Some(100), - header, - None, + Some(101), + header11.clone(), + Some(vec![crate::validators::tests::validators_change_recept( + latest_block_hash, + )]), ) .unwrap(); - match i { - 2..=10 => assert_eq!( - finalized_blocks, - vec![(i - 1, block_i(&storage, i - 1, &validators).hash(), Some(100))], - "At {}", - i, - ), - _ => assert_eq!(finalized_blocks, vec![], "At {}", i), - } + assert_eq!(finalized_blocks, vec![(10, block_i(10, &validators).hash(), Some(100))],); + assert!(storage.header(&genesis().hash()).is_none()); latest_block_hash = rolling_last_block_hash; - } - assert!(storage.header(&genesis().hash()).is_some()); - // header 11 finalizes headers [10] AND schedules change - // => we prune header#0 - let header11 = custom_block_i(&storage, 11, &validators, |header| { - header.log_bloom = (&[0xff; 256]).into(); - header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951" - .parse() + // and now let's say validators 1 && 2 went offline + // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers + // until header#11 is met. we can't prune #11, because it schedules change + let mut step = 56; + let mut expected_blocks = vec![(11, header11.hash(), Some(101))]; + for i in 12..25 { + let header = Header { + number: i as _, + parent_hash: latest_block_hash, + gas_limit: 0x2000.into(), + author: validator(2).address(), + seal: vec![vec![step].into(), vec![].into()], + difficulty: i.into(), + ..Default::default() + }; + let header = signed_header(&validators, header, step as _); + expected_blocks.push((i, header.hash(), Some(102))); + let (rolling_last_block_hash, finalized_blocks) = import_header( + &mut storage, + &test_aura_config(), + &validators_config, + 10, + Some(102), + header, + None, + ) .unwrap(); - }); - let (rolling_last_block_hash, finalized_blocks) = import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - Some(101), - header11.clone(), - Some(vec![crate::validators::tests::validators_change_recept( - latest_block_hash, - )]), - ) - .unwrap(); - assert_eq!( - finalized_blocks, - vec![(10, block_i(&storage, 10, &validators).hash(), Some(100))], - ); - assert!(storage.header(&genesis().hash()).is_none()); - latest_block_hash = rolling_last_block_hash; + assert_eq!(finalized_blocks, vec![],); + latest_block_hash = rolling_last_block_hash; + step += 3; + } + assert_eq!(OldestUnprunedBlock::get(), 11); - // and now let's say validators 1 && 2 went offline - // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers - // until header#11 is met. we can't prune #11, because it schedules change - let mut step = 56; - let mut expected_blocks = vec![(11, header11.hash(), Some(101))]; - for i in 12..25 { + // now let's insert block signed by validator 1 + // => blocks 11..24 are finalized and blocks 11..14 are pruned + step -= 2; let header = Header { - number: i as _, + number: 25, parent_hash: latest_block_hash, gas_limit: 0x2000.into(), - author: validator(2).address().to_fixed_bytes().into(), + author: validator(0).address(), seal: vec![vec![step].into(), vec![].into()], - difficulty: i.into(), + difficulty: 25.into(), ..Default::default() }; let header = signed_header(&validators, header, step as _); - expected_blocks.push((i, header.hash(), Some(102))); - let (rolling_last_block_hash, finalized_blocks) = import_header( + let (_, finalized_blocks) = import_header( &mut storage, - &kovan_aura_config(), + &test_aura_config(), &validators_config, 10, - Some(102), + Some(103), header, None, ) .unwrap(); - assert_eq!(finalized_blocks, vec![],); - latest_block_hash = rolling_last_block_hash; - step += 3; - } - assert_eq!(storage.oldest_unpruned_block(), 11); - - // now let's insert block signed by validator 1 - // => blocks 11..24 are finalized and blocks 11..14 are pruned - step -= 2; - let header = Header { - number: 25, - parent_hash: latest_block_hash, - gas_limit: 0x2000.into(), - author: validator(0).address().to_fixed_bytes().into(), - seal: vec![vec![step].into(), vec![].into()], - difficulty: 25.into(), - ..Default::default() - }; - let header = signed_header(&validators, header, step as _); - let (_, finalized_blocks) = import_header( - &mut storage, - &kovan_aura_config(), - &validators_config, - 10, - Some(103), - header, - None, - ) - .unwrap(); - assert_eq!(finalized_blocks, expected_blocks); - assert_eq!(storage.oldest_unpruned_block(), 15); + assert_eq!(finalized_blocks, expected_blocks); + assert_eq!(OldestUnprunedBlock::get(), 15); + }); } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 9f0b0cbd03171..376d800d34dba 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode}; -use frame_support::{decl_module, decl_storage}; +use frame_support::{decl_module, decl_storage, traits::Get}; use primitives::{Address, Header, Receipt, H256, U256}; use sp_runtime::{ transaction_validity::{ @@ -27,9 +27,8 @@ use sp_runtime::{ RuntimeDebug, }; use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; -use validators::{ValidatorsConfiguration, ValidatorsSource}; -pub use import::{header_import_requires_receipts, import_header}; +pub use validators::{ValidatorsConfiguration, ValidatorsSource}; mod error; mod finality; @@ -37,6 +36,9 @@ mod import; mod validators; mod verification; +#[cfg(test)] +mod mock; + /// Authority round engine configuration parameters. #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] pub struct AuraConfiguration { @@ -286,6 +288,10 @@ impl OnHeadersSubmitted for () { /// The module configuration trait pub trait Trait: frame_system::Trait { + /// Aura configuration. + type AuraConfiguration: Get; + /// Validators configuration. + type ValidatorsConfiguration: Get; /// Handler for headers submission result. type OnHeadersSubmitted: OnHeadersSubmitted; } @@ -297,10 +303,10 @@ decl_module! { pub fn import_unsigned_header(origin, header: Header, receipts: Option>) { frame_system::ensure_none(origin)?; - import_header( + import::import_header( &mut BridgeStorage::::new(), - &kovan_aura_config(), - &kovan_validators_config(), + &T::AuraConfiguration::get(), + &T::ValidatorsConfiguration::get(), crate::import::PRUNE_DEPTH, None, header, @@ -320,8 +326,8 @@ decl_module! { let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( &mut BridgeStorage::::new(), - &kovan_aura_config(), - &kovan_validators_config(), + &T::AuraConfiguration::get(), + &T::ValidatorsConfiguration::get(), crate::import::PRUNE_DEPTH, Some(submitter.clone()), headers_with_receipts, @@ -424,7 +430,7 @@ impl Module { /// Returns true if the import of given block requires transactions receipts. pub fn is_import_requires_receipts(header: Header) -> bool { - import::header_import_requires_receipts(&BridgeStorage::::new(), &kovan_validators_config(), &header) + import::header_import_requires_receipts(&BridgeStorage::::new(), &T::ValidatorsConfiguration::get(), &header) } /// Returns true if header is known to the runtime. @@ -441,8 +447,8 @@ impl frame_support::unsigned::ValidateUnsigned for Module { Self::Call::import_unsigned_header(ref header, ref receipts) => { let accept_result = verification::accept_aura_header_into_pool( &BridgeStorage::::new(), - &kovan_aura_config(), - &kovan_validators_config(), + &T::AuraConfiguration::get(), + &T::ValidatorsConfiguration::get(), &pool_configuration(), header, receipts.as_ref(), @@ -623,462 +629,9 @@ impl Storage for BridgeStorage { } } -/// Aura engine configuration for Kovan chain. -pub fn kovan_aura_config() -> AuraConfiguration { - AuraConfiguration { - empty_steps_transition: u64::max_value(), - strict_empty_steps_transition: 0, - validate_step_transition: 0x16e360, - validate_score_transition: 0x41a3c4, - two_thirds_majority_transition: u64::max_value(), - min_gas_limit: 0x1388.into(), - max_gas_limit: U256::max_value(), - maximum_extra_data_size: 0x20, - } -} - -/// Validators configuration for Kovan chain. -pub fn kovan_validators_config() -> ValidatorsConfiguration { - ValidatorsConfiguration::Multi(vec![ - ( - 0, - ValidatorsSource::List(vec![ - [ - 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, - 0x5B, 0xAd, 0xc0, 0xED, - ] - .into(), - [ - 0x00, 0x42, 0x7f, 0xea, 0xe2, 0x41, 0x9c, 0x15, 0xb8, 0x9d, 0x1c, 0x21, 0xaf, 0x10, 0xd1, 0xb6, - 0x65, 0x0a, 0x4d, 0x3d, - ] - .into(), - [ - 0x4E, 0xd9, 0xB0, 0x8e, 0x63, 0x54, 0xC7, 0x0f, 0xE6, 0xF8, 0xCB, 0x04, 0x11, 0xb0, 0xd3, 0x24, - 0x6b, 0x42, 0x4d, 0x6c, - ] - .into(), - [ - 0x00, 0x20, 0xee, 0x4B, 0xe0, 0xe2, 0x02, 0x7d, 0x76, 0x60, 0x3c, 0xB7, 0x51, 0xeE, 0x06, 0x95, - 0x19, 0xbA, 0x81, 0xA1, - ] - .into(), - [ - 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, - 0x3a, 0xfd, 0x03, 0x2d, - ] - .into(), - [ - 0x00, 0x77, 0x33, 0xa1, 0xFE, 0x69, 0xCF, 0x3f, 0x2C, 0xF9, 0x89, 0xF8, 0x1C, 0x7b, 0x4c, 0xAc, - 0x16, 0x93, 0x38, 0x7A, - ] - .into(), - [ - 0x00, 0xE6, 0xd2, 0xb9, 0x31, 0xF5, 0x5a, 0x3f, 0x17, 0x01, 0xc7, 0x38, 0x9d, 0x59, 0x2a, 0x77, - 0x78, 0x89, 0x78, 0x79, - ] - .into(), - [ - 0x00, 0xe4, 0xa1, 0x06, 0x50, 0xe5, 0xa6, 0xD6, 0x00, 0x1C, 0x38, 0xff, 0x8E, 0x64, 0xF9, 0x70, - 0x16, 0xa1, 0x64, 0x5c, - ] - .into(), - [ - 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, - 0x12, 0x31, 0x94, 0xde, - ] - .into(), - ]), - ), - ( - 10960440, - ValidatorsSource::List(vec![ - [ - 0x00, 0xD6, 0xCc, 0x1B, 0xA9, 0xcf, 0x89, 0xBD, 0x2e, 0x58, 0x00, 0x97, 0x41, 0xf4, 0xF7, 0x32, - 0x5B, 0xAd, 0xc0, 0xED, - ] - .into(), - [ - 0x00, 0x10, 0xf9, 0x4b, 0x29, 0x6a, 0x85, 0x2a, 0xaa, 0xc5, 0x2e, 0xa6, 0xc5, 0xac, 0x72, 0xe0, - 0x3a, 0xfd, 0x03, 0x2d, - ] - .into(), - [ - 0x00, 0xa0, 0xa2, 0x4b, 0x9f, 0x0e, 0x5e, 0xc7, 0xaa, 0x4c, 0x73, 0x89, 0xb8, 0x30, 0x2f, 0xd0, - 0x12, 0x31, 0x94, 0xde, - ] - .into(), - ]), - ), - ( - 10960500, - ValidatorsSource::Contract( - [ - 0xaE, 0x71, 0x80, 0x7C, 0x1B, 0x0a, 0x09, 0x3c, 0xB1, 0x54, 0x7b, 0x68, 0x2D, 0xC7, 0x83, 0x16, - 0xD9, 0x45, 0xc9, 0xB8, - ] - .into(), - vec![ - [ - 0xd0, 0x5f, 0x74, 0x78, 0xc6, 0xaa, 0x10, 0x78, 0x12, 0x58, 0xc5, 0xcc, 0x8b, 0x4f, 0x38, 0x5f, - 0xc8, 0xfa, 0x98, 0x9c, - ] - .into(), - [ - 0x03, 0x80, 0x1e, 0xfb, 0x0e, 0xfe, 0x2a, 0x25, 0xed, 0xe5, 0xdd, 0x3a, 0x00, 0x3a, 0xe8, 0x80, - 0xc0, 0x29, 0x2e, 0x4d, - ] - .into(), - [ - 0xa4, 0xdf, 0x25, 0x5e, 0xcf, 0x08, 0xbb, 0xf2, 0xc2, 0x80, 0x55, 0xc6, 0x52, 0x25, 0xc9, 0xa9, - 0x84, 0x7a, 0xbd, 0x94, - ] - .into(), - [ - 0x59, 0x6e, 0x82, 0x21, 0xa3, 0x0b, 0xfe, 0x6e, 0x7e, 0xff, 0x67, 0xfe, 0xe6, 0x64, 0xa0, 0x1c, - 0x73, 0xba, 0x3c, 0x56, - ] - .into(), - [ - 0xfa, 0xad, 0xfa, 0xce, 0x3f, 0xbd, 0x81, 0xce, 0x37, 0xb0, 0xe1, 0x9c, 0x0b, 0x65, 0xff, 0x42, - 0x34, 0x14, 0x81, 0x32, - ] - .into(), - ], - ), - ), - ]) -} - /// Transaction pool configuration. fn pool_configuration() -> PoolConfiguration { PoolConfiguration { max_future_number_difference: 10, } } - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use parity_crypto::publickey::{sign, KeyPair, Secret}; - use primitives::{rlp_encode, H520}; - use std::collections::{hash_map::Entry, HashMap}; - - pub type AccountId = u64; - - pub fn genesis() -> Header { - Header { - seal: vec![vec![42].into(), vec![].into()], - ..Default::default() - } - } - - pub fn block_i(storage: &InMemoryStorage, number: u64, validators: &[KeyPair]) -> Header { - custom_block_i(storage, number, validators, |_| {}) - } - - pub fn custom_block_i( - storage: &InMemoryStorage, - number: u64, - validators: &[KeyPair], - customize: impl FnOnce(&mut Header), - ) -> Header { - let validator_index: u8 = (number % (validators.len() as u64)) as _; - let mut header = Header { - number, - parent_hash: storage.headers_by_number[&(number - 1)][0].clone(), - gas_limit: 0x2000.into(), - author: validator(validator_index).address().to_fixed_bytes().into(), - seal: vec![vec![number as u8 + 42].into(), vec![].into()], - difficulty: number.into(), - ..Default::default() - }; - customize(&mut header); - signed_header(validators, header, number + 42) - } - - pub fn signed_header(validators: &[KeyPair], mut header: Header, step: u64) -> Header { - let message = header.seal_hash(false).unwrap(); - let validator_index = (step % validators.len() as u64) as usize; - let signature = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()).unwrap(); - let signature: [u8; 65] = signature.into(); - let signature = H520::from(signature); - header.seal[1] = rlp_encode(&signature); - header - } - - pub fn validator(index: u8) -> KeyPair { - KeyPair::from_secret(Secret::from([index + 1; 32])).unwrap() - } - - pub fn validators_addresses(count: u8) -> Vec
{ - (0..count as usize) - .map(|i| validator(i as u8).address().as_fixed_bytes().into()) - .collect() - } - - pub struct InMemoryStorage { - best_block: (u64, H256, U256), - finalized_block: (u64, H256), - oldest_unpruned_block: u64, - headers: HashMap>, - headers_by_number: HashMap>, - next_validators_set_id: u64, - validators_sets: HashMap, - validators_sets_rc: HashMap, - scheduled_changes: HashMap, - } - - impl InMemoryStorage { - pub fn new(initial_header: Header, initial_validators: Vec
) -> Self { - let hash = initial_header.hash(); - InMemoryStorage { - best_block: (initial_header.number, hash, 0.into()), - finalized_block: (initial_header.number, hash), - oldest_unpruned_block: initial_header.number, - headers_by_number: vec![(initial_header.number, vec![hash])].into_iter().collect(), - headers: vec![( - hash, - StoredHeader { - submitter: None, - header: initial_header, - total_difficulty: 0.into(), - next_validators_set_id: 0, - last_signal_block: None, - }, - )] - .into_iter() - .collect(), - next_validators_set_id: 1, - validators_sets: vec![( - 0, - ValidatorsSet { - validators: initial_validators, - signal_block: None, - enact_block: hash, - }, - )] - .into_iter() - .collect(), - validators_sets_rc: vec![(0, 1)].into_iter().collect(), - scheduled_changes: HashMap::new(), - } - } - - pub(crate) fn insert(&mut self, header: Header) { - let hash = header.hash(); - self.headers_by_number.entry(header.number).or_default().push(hash); - self.headers.insert( - hash, - StoredHeader { - submitter: None, - header, - total_difficulty: 0.into(), - next_validators_set_id: 0, - last_signal_block: None, - }, - ); - } - - pub(crate) fn change_validators_set_at( - &mut self, - number: u64, - finalized_set: Vec
, - signalled_set: Option>, - ) { - let set_id = self.next_validators_set_id; - self.next_validators_set_id += 1; - self.validators_sets.insert( - set_id, - ValidatorsSet { - validators: finalized_set, - signal_block: None, - enact_block: self.headers_by_number[&0][0], - }, - ); - - let mut header = self.headers.get_mut(&self.headers_by_number[&number][0]).unwrap(); - header.next_validators_set_id = set_id; - if let Some(signalled_set) = signalled_set { - header.last_signal_block = Some(self.headers_by_number[&(number - 1)][0]); - self.scheduled_changes.insert( - self.headers_by_number[&(number - 1)][0], - ScheduledChange { - validators: signalled_set, - prev_signal_block: None, - }, - ); - } - } - - pub(crate) fn set_best_block(&mut self, best_block: (u64, H256)) { - self.best_block.0 = best_block.0; - self.best_block.1 = best_block.1; - } - - pub(crate) fn set_finalized_block(&mut self, finalized_block: (u64, H256)) { - self.finalized_block = finalized_block; - } - - pub(crate) fn oldest_unpruned_block(&self) -> u64 { - self.oldest_unpruned_block - } - - pub(crate) fn stored_header(&self, hash: &H256) -> Option<&StoredHeader> { - self.headers.get(hash) - } - } - - impl Storage for InMemoryStorage { - type Submitter = AccountId; - - fn best_block(&self) -> (u64, H256, U256) { - self.best_block.clone() - } - - fn finalized_block(&self) -> (u64, H256) { - self.finalized_block.clone() - } - - fn header(&self, hash: &H256) -> Option<(Header, Option)> { - self.headers - .get(hash) - .map(|header| (header.header.clone(), header.submitter.clone())) - } - - fn import_context( - &self, - submitter: Option, - parent_hash: &H256, - ) -> Option> { - self.headers.get(parent_hash).map(|parent_header| { - let validators_set = self - .validators_sets - .get(&parent_header.next_validators_set_id) - .unwrap() - .clone(); - let parent_scheduled_change = self.scheduled_changes.get(parent_hash).cloned(); - ImportContext { - submitter, - parent_hash: *parent_hash, - parent_header: parent_header.header.clone(), - parent_total_difficulty: parent_header.total_difficulty, - parent_scheduled_change, - validators_set_id: parent_header.next_validators_set_id, - validators_set, - last_signal_block: parent_header.last_signal_block, - } - }) - } - - fn scheduled_change(&self, hash: &H256) -> Option { - self.scheduled_changes.get(hash).cloned() - } - - fn insert_header(&mut self, header: HeaderToImport) { - if header.is_best { - self.best_block = (header.header.number, header.hash, header.total_difficulty); - } - if let Some(scheduled_change) = header.scheduled_change { - self.scheduled_changes.insert( - header.hash, - ScheduledChange { - validators: scheduled_change, - prev_signal_block: header.context.last_signal_block, - }, - ); - } - let next_validators_set_id = match header.enacted_change { - Some(enacted_change) => { - let next_validators_set_id = self.next_validators_set_id; - self.next_validators_set_id += 1; - self.validators_sets.insert( - next_validators_set_id, - ValidatorsSet { - validators: enacted_change.validators, - enact_block: header.hash, - signal_block: enacted_change.signal_block, - }, - ); - self.validators_sets_rc.insert(next_validators_set_id, 1); - next_validators_set_id - } - None => { - *self - .validators_sets_rc - .entry(header.context.validators_set_id) - .or_default() += 1; - header.context.validators_set_id - } - }; - - let last_signal_block = header.context.last_signal_block().cloned(); - self.headers_by_number - .entry(header.header.number) - .or_default() - .push(header.hash); - self.headers.insert( - header.hash, - StoredHeader { - submitter: header.context.submitter, - header: header.header, - total_difficulty: header.total_difficulty, - next_validators_set_id, - last_signal_block, - }, - ); - } - - fn finalize_headers(&mut self, finalized: Option<(u64, H256)>, prune_end: Option) { - let finalized_number = finalized - .as_ref() - .map(|f| f.0) - .unwrap_or_else(|| self.finalized_block.0); - if let Some(finalized) = finalized { - self.finalized_block = finalized; - } - - if let Some(prune_end) = prune_end { - let prune_begin = self.oldest_unpruned_block; - - for number in prune_begin..prune_end { - let blocks_at_number = self.headers_by_number.remove(&number); - - // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number { - if let Some(ref blocks_at_number) = blocks_at_number { - if blocks_at_number - .iter() - .any(|block| self.scheduled_changes.contains_key(block)) - { - self.headers_by_number.insert(number, blocks_at_number.clone()); - self.oldest_unpruned_block = number; - return; - } - } - } - - // physically remove headers and (probably) obsolete validators sets - for hash in blocks_at_number.into_iter().flat_map(|x| x) { - let header = self.headers.remove(&hash); - self.scheduled_changes.remove(&hash); - if let Some(header) = header { - match self.validators_sets_rc.entry(header.next_validators_set_id) { - Entry::Occupied(mut entry) => { - if *entry.get() == 1 { - entry.remove(); - } else { - *entry.get_mut() -= 1; - } - } - Entry::Vacant(_) => unreachable!("there's entry for each header"), - }; - } - } - } - - self.oldest_unpruned_block = prune_end; - } - } - } -} diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs new file mode 100644 index 0000000000000..6624b149a9045 --- /dev/null +++ b/modules/ethereum/src/mock.rs @@ -0,0 +1,179 @@ +// Copyright 2019-2020 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 . + +use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; +use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, HeadersByNumber, Storage, Trait}; +use frame_support::StorageMap; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use parity_crypto::publickey::{sign, KeyPair, Secret}; +use primitives::{rlp_encode, H520}; +use primitives::{Address, Header, H256, U256}; +use sp_runtime::{ + testing::Header as SubstrateHeader, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +pub type AccountId = u64; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct TestRuntime; + +impl_outer_origin! { + pub enum Origin for TestRuntime where system = frame_system {} +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = SubstrateHeader; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); +} + +parameter_types! { + pub const TestAuraConfiguration: AuraConfiguration = test_aura_config(); + pub const TestValidatorsConfiguration: ValidatorsConfiguration = test_validators_config(); +} + +impl Trait for TestRuntime { + type AuraConfiguration = TestAuraConfiguration; + type ValidatorsConfiguration = TestValidatorsConfiguration; + type OnHeadersSubmitted = (); +} + +/// Aura configuration that is used in tests by default. +pub fn test_aura_config() -> AuraConfiguration { + AuraConfiguration { + empty_steps_transition: u64::max_value(), + strict_empty_steps_transition: 0, + validate_step_transition: 0x16e360, + validate_score_transition: 0x41a3c4, + two_thirds_majority_transition: u64::max_value(), + min_gas_limit: 0x1388.into(), + max_gas_limit: U256::max_value(), + maximum_extra_data_size: 0x20, + } +} + +/// Validators configuration that is used in tests by default. +pub fn test_validators_config() -> ValidatorsConfiguration { + ValidatorsConfiguration::Single(ValidatorsSource::List(validators_addresses(3))) +} + +/// Genesis header that is used in tests by default. +pub fn genesis() -> Header { + Header { + seal: vec![vec![42].into(), vec![].into()], + ..Default::default() + } +} + +/// Build default i-th block, using data from runtime storage. +pub fn block_i(number: u64, validators: &[KeyPair]) -> Header { + custom_block_i(number, validators, |_| {}) +} + +/// Build custom i-th block, using data from runtime storage. +pub fn custom_block_i(number: u64, validators: &[KeyPair], customize: impl FnOnce(&mut Header)) -> Header { + let validator_index: u8 = (number % (validators.len() as u64)) as _; + let mut header = Header { + number, + parent_hash: HeadersByNumber::get(number - 1).unwrap()[0].clone(), + gas_limit: 0x2000.into(), + author: validator(validator_index).address(), + seal: vec![vec![number as u8 + 42].into(), vec![].into()], + difficulty: number.into(), + ..Default::default() + }; + customize(&mut header); + signed_header(validators, header, number + 42) +} + +/// Build signed header from given header. +pub fn signed_header(validators: &[KeyPair], mut header: Header, step: u64) -> Header { + let message = header.seal_hash(false).unwrap(); + let validator_index = (step % validators.len() as u64) as usize; + let signature = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()).unwrap(); + let signature: [u8; 65] = signature.into(); + let signature = H520::from(signature); + header.seal[1] = rlp_encode(&signature); + header +} + +/// Return key pair of given test validator. +pub fn validator(index: u8) -> KeyPair { + KeyPair::from_secret(Secret::from([index + 1; 32])).unwrap() +} + +/// Return key pairs of all test validators. +pub fn validators(count: u8) -> Vec { + (0..count).map(validator).collect() +} + +/// Return addresses of all test validators. +pub fn validators_addresses(count: u8) -> Vec
{ + (0..count).map(|i| validator(i).address()).collect() +} + +/// Prepare externalities to start with custom initial header. +pub fn custom_test_ext(initial_header: Header, initial_validators: Vec
) -> sp_io::TestExternalities { + let t = GenesisConfig { + initial_header, + initial_difficulty: 0.into(), + initial_validators, + } + .build_storage::() + .unwrap(); + sp_io::TestExternalities::new(t) +} + +/// Insert header into storage. +pub fn insert_header(storage: &mut S, header: Header) { + storage.insert_header(HeaderToImport { + context: storage.import_context(None, &header.parent_hash).unwrap(), + is_best: true, + hash: header.hash(), + header, + total_difficulty: 0.into(), + enacted_change: None, + scheduled_change: None, + }); +} diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index a93c21f8de4e7..7a1fbb52f036b 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -254,7 +254,6 @@ pub fn step_validator(header_validators: &[Address], header_step: u64) -> Addres #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::kovan_validators_config; use primitives::TransactionOutcome; pub(crate) fn validators_change_recept(parent_hash: H256) -> Receipt { @@ -314,7 +313,7 @@ pub(crate) mod tests { #[test] fn maybe_signals_validators_change_works() { // when contract is active, but bloom has no required bits set - let config = kovan_validators_config(); + let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); let validators = Validators::new(&config); let mut header = Header::default(); header.number = u64::max_value(); diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 23f8980b3a0bb..567d14f3b54a4 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -339,11 +339,16 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< #[cfg(test)] mod tests { use super::*; - use crate::tests::{ - block_i, custom_block_i, genesis, signed_header, validator, validators_addresses, AccountId, InMemoryStorage, + use crate::mock::{ + block_i, custom_block_i, custom_test_ext, genesis, insert_header, signed_header, test_aura_config, validator, + validators_addresses, AccountId, TestRuntime, }; use crate::validators::{tests::validators_change_recept, ValidatorsSource}; - use crate::{kovan_aura_config, pool_configuration}; + use crate::{ + pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, + ScheduledChanges, ValidatorsSet, ValidatorsSets, + }; + use frame_support::{StorageMap, StorageValue}; use parity_crypto::publickey::{sign, KeyPair}; use primitives::{rlp_encode, TransactionOutcome, H520}; @@ -362,41 +367,73 @@ mod tests { } fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result, Error> { - let storage = InMemoryStorage::new(genesis(), validators_addresses(3)); - verify_aura_header(&storage, &config, None, header) + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let storage = BridgeStorage::::new(); + verify_aura_header(&storage, &config, None, header) + }) } fn default_verify(header: &Header) -> Result, Error> { - verify_with_config(&kovan_aura_config(), header) + verify_with_config(&test_aura_config(), header) } fn default_accept_into_pool( - mut make_header: impl FnMut(&mut InMemoryStorage, &[KeyPair]) -> (Header, Option>), + mut make_header: impl FnMut(&[KeyPair]) -> (Header, Option>), ) -> Result<(Vec>, Vec>), Error> { - let validators = vec![validator(0), validator(1), validator(2)]; - let mut storage = InMemoryStorage::new(genesis(), validators_addresses(3)); - let block1 = block_i(&storage, 1, &validators); - storage.insert(block1); - let block2 = block_i(&storage, 2, &validators); - let block2_hash = block2.hash(); - storage.insert(block2); - let block3 = block_i(&storage, 3, &validators); - let block3_hash = block3.hash(); - storage.insert(block3); - storage.set_finalized_block((2, block2_hash)); - storage.set_best_block((3, block3_hash)); - - let validators_config = - ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); - let (header, receipts) = make_header(&mut storage, &validators); - accept_aura_header_into_pool( - &storage, - &kovan_aura_config(), - &validators_config, - &pool_configuration(), - &header, - receipts.as_ref(), - ) + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let validators = vec![validator(0), validator(1), validator(2)]; + let mut storage = BridgeStorage::::new(); + let block1 = block_i(1, &validators); + insert_header(&mut storage, block1); + let block2 = block_i(2, &validators); + let block2_hash = block2.hash(); + insert_header(&mut storage, block2); + let block3 = block_i(3, &validators); + insert_header(&mut storage, block3); + + FinalizedBlock::put((2, block2_hash)); + + let validators_config = + ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); + let (header, receipts) = make_header(&validators); + accept_aura_header_into_pool( + &storage, + &test_aura_config(), + &validators_config, + &pool_configuration(), + &header, + receipts.as_ref(), + ) + }) + } + + fn change_validators_set_at(number: u64, finalized_set: Vec
, signalled_set: Option>) { + let set_id = NextValidatorsSetId::get(); + NextValidatorsSetId::put(set_id + 1); + ValidatorsSets::insert( + set_id, + ValidatorsSet { + validators: finalized_set, + signal_block: None, + enact_block: HeadersByNumber::get(&0).unwrap()[0].clone(), + }, + ); + + let header_hash = HeadersByNumber::get(&number).unwrap()[0].clone(); + let mut header = Headers::::get(&header_hash).unwrap(); + header.next_validators_set_id = set_id; + if let Some(signalled_set) = signalled_set { + header.last_signal_block = Some(header.header.parent_hash); + ScheduledChanges::insert( + header.header.parent_hash, + ScheduledChange { + validators: signalled_set, + prev_signal_block: None, + }, + ); + } + + Headers::::insert(header_hash, header); } #[test] @@ -409,7 +446,7 @@ mod tests { header.seal = vec![vec![].into()]; assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); - // when there's 3 seals (we expect 2 on Kovan) + // when there's 3 seals (we expect 2 by default) header.seal = vec![vec![].into(), vec![].into(), vec![].into()]; assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); @@ -452,7 +489,7 @@ mod tests { #[test] fn verifies_gas_limit() { - let mut config = kovan_aura_config(); + let mut config = test_aura_config(); config.min_gas_limit = 100.into(); config.max_gas_limit = 200.into(); @@ -478,7 +515,7 @@ mod tests { // when extra data is too large let mut header = Header { seal: vec![vec![].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, extra_data: std::iter::repeat(42).take(1000).collect::>().into(), number: 1, ..Default::default() @@ -495,7 +532,7 @@ mod tests { // when timestamp overflows i32 let mut header = Header { seal: vec![vec![].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, timestamp: i32::max_value() as u64 + 1, ..Default::default() }; @@ -511,7 +548,7 @@ mod tests { // when there's no parent in the storage let mut header = Header { seal: vec![vec![].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, ..Default::default() }; assert_eq!(default_verify(&header), Err(Error::MissingParentBlock)); @@ -526,7 +563,7 @@ mod tests { // when step is missing from seals let mut header = Header { seal: vec![vec![].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: genesis().hash(), ..Default::default() }; @@ -541,7 +578,7 @@ mod tests { assert_ne!(default_verify(&header), Err(Error::DoubleVote)); // now check with validate_step check enabled - let mut config = kovan_aura_config(); + let mut config = test_aura_config(); config.validate_step_transition = 0; // when step is lesser that for the parent block @@ -556,7 +593,7 @@ mod tests { #[test] fn verifies_empty_step() { let validators = vec![validator(0), validator(1), validator(2)]; - let mut config = kovan_aura_config(); + let mut config = test_aura_config(); config.empty_steps_transition = 0; // when empty step duplicates parent step @@ -566,7 +603,7 @@ mod tests { vec![142].into(), SealedEmptyStep::rlp_of(&[sealed_empty_step(&validators, &genesis().hash(), 42)]), ], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: genesis().hash(), ..Default::default() }; @@ -596,13 +633,13 @@ mod tests { #[test] fn verifies_chain_score() { - let mut config = kovan_aura_config(); + let mut config = test_aura_config(); config.validate_score_transition = 0; // when chain score is invalid let mut header = Header { seal: vec![vec![43].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: genesis().hash(), ..Default::default() }; @@ -621,7 +658,7 @@ mod tests { Header { author: validators[1].address().as_fixed_bytes().into(), seal: vec![vec![43].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: genesis().hash(), ..Default::default() }, @@ -646,7 +683,7 @@ mod tests { fn pool_verifies_known_blocks() { // when header is known assert_eq!( - default_accept_into_pool(|storage, validators| (block_i(storage, 3, validators), None)), + default_accept_into_pool(|validators| (block_i(3, validators), None)), Err(Error::KnownHeader), ); } @@ -655,8 +692,8 @@ mod tests { fn pool_verifies_ancient_blocks() { // when header number is less than finalized assert_eq!( - default_accept_into_pool(|storage, validators| ( - custom_block_i(storage, 2, validators, |header| header.gas_limit += 1.into()), + default_accept_into_pool(|validators| ( + custom_block_i(2, validators, |header| header.gas_limit += 1.into()), None, ),), Err(Error::AncientHeader), @@ -666,11 +703,11 @@ mod tests { #[test] fn pool_rejects_headers_without_required_receipts() { assert_eq!( - default_accept_into_pool(|_, _| ( + default_accept_into_pool(|_| ( Header { number: 20_000_000, seal: vec![vec![].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, log_bloom: (&[0xff; 256]).into(), ..Default::default() }, @@ -683,8 +720,8 @@ mod tests { #[test] fn pool_rejects_headers_with_redundant_receipts() { assert_eq!( - default_accept_into_pool(|storage, validators| ( - block_i(storage, 4, validators), + default_accept_into_pool(|validators| ( + block_i(4, validators), Some(vec![Receipt { gas_used: 1.into(), log_bloom: (&[0xff; 256]).into(), @@ -700,10 +737,7 @@ mod tests { fn pool_verifies_future_block_number() { // when header is too far from the future assert_eq!( - default_accept_into_pool(|storage, validators| ( - custom_block_i(storage, 4, validators, |header| header.number = 100), - None, - ),), + default_accept_into_pool(|validators| (custom_block_i(4, validators, |header| header.number = 100), None,),), Err(Error::UnsignedTooFarInTheFuture), ); } @@ -713,9 +747,9 @@ mod tests { // if parent is known, then we'll execute contextual_checks, which // checks for DoubleVote assert_eq!( - default_accept_into_pool(|storage, validators| ( - custom_block_i(storage, 4, validators, |header| header.seal[0] = - block_i(storage, 3, validators).seal[0].clone()), + default_accept_into_pool(|validators| ( + custom_block_i(4, validators, |header| header.seal[0] = + block_i(3, validators).seal[0].clone()), None, ),), Err(Error::DoubleVote), @@ -728,13 +762,13 @@ mod tests { // (even if header will be considered invalid/duplicate later, we can use this signature // as a proof of malicious action by this validator) assert_eq!( - default_accept_into_pool(|_, validators| ( + default_accept_into_pool(|validators| ( signed_header( validators, Header { author: validators[1].address().as_fixed_bytes().into(), seal: vec![vec![8].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: [42; 32].into(), number: 8, ..Default::default() @@ -751,8 +785,8 @@ mod tests { fn pool_verifies_header_with_known_parent() { let mut hash = None; assert_eq!( - default_accept_into_pool(|storage, validators| { - let header = block_i(&storage, 4, &validators); + default_accept_into_pool(|validators| { + let header = block_i(4, &validators); hash = Some(header.hash()); (header, None) }), @@ -772,13 +806,13 @@ mod tests { fn pool_verifies_header_with_unknown_parent() { let mut hash = None; assert_eq!( - default_accept_into_pool(|_, validators| { + default_accept_into_pool(|validators| { let header = signed_header( validators, Header { author: validators[2].address().as_fixed_bytes().into(), seal: vec![vec![47].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: [42; 32].into(), number: 5, ..Default::default() @@ -803,9 +837,9 @@ mod tests { #[test] fn pool_uses_next_validators_set_when_finalized_fails() { assert_eq!( - default_accept_into_pool(|storage, actual_validators| { + default_accept_into_pool(|actual_validators| { // change finalized set at parent header - storage.change_validators_set_at(3, validators_addresses(1), None); + change_validators_set_at(3, validators_addresses(1), None); // header is signed using wrong set let header = signed_header( @@ -813,7 +847,7 @@ mod tests { Header { author: actual_validators[2].address().as_fixed_bytes().into(), seal: vec![vec![47].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: [42; 32].into(), number: 5, ..Default::default() @@ -828,9 +862,9 @@ mod tests { let mut hash = None; assert_eq!( - default_accept_into_pool(|storage, actual_validators| { + default_accept_into_pool(|actual_validators| { // change finalized set at parent header + signal valid set at parent block - storage.change_validators_set_at(3, validators_addresses(10), Some(validators_addresses(3))); + change_validators_set_at(3, validators_addresses(10), Some(validators_addresses(3))); // header is signed using wrong set let header = signed_header( @@ -838,7 +872,7 @@ mod tests { Header { author: actual_validators[2].address().as_fixed_bytes().into(), seal: vec![vec![47].into(), vec![].into()], - gas_limit: kovan_aura_config().min_gas_limit, + gas_limit: test_aura_config().min_gas_limit, parent_hash: [42; 32].into(), number: 5, ..Default::default() @@ -864,8 +898,8 @@ mod tests { #[test] fn pool_rejects_headers_with_invalid_receipts() { assert_eq!( - default_accept_into_pool(|storage, validators| { - let header = custom_block_i(&storage, 4, &validators, |header| { + default_accept_into_pool(|validators| { + let header = custom_block_i(4, &validators, |header| { header.log_bloom = (&[0xff; 256]).into(); }); (header, Some(vec![validators_change_recept(Default::default())])) @@ -878,8 +912,8 @@ mod tests { fn pool_accepts_headers_with_valid_receipts() { let mut hash = None; assert_eq!( - default_accept_into_pool(|storage, validators| { - let header = custom_block_i(&storage, 4, &validators, |header| { + default_accept_into_pool(|validators| { + let header = custom_block_i(4, &validators, |header| { header.log_bloom = (&[0xff; 256]).into(); header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" .parse() diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index ca2afa605db5b..662079c301f4a 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -322,7 +322,6 @@ impl PartialEq for Bloom { } } -#[cfg(feature = "std")] impl Default for Bloom { fn default() -> Self { Bloom([0; 256]) From d3dd71293fbc2d3fb43c789fb7b3f5040797adf6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 2 Jun 2020 13:40:39 +0300 Subject: [PATCH 0061/1210] downgrade async-std to 1.5.0 (#119) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 50db2c4b6da0a..05553d8bb5389 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] ansi_term = "0.12" -async-std = "1.6.0" +async-std = "=1.5.0" async-stream = "0.2.0" async-trait = "0.1.31" clap = { version = "2.33.1", features = ["yaml"] } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 16f0a3da53b5d..7f151e55a446e 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -async-std = "1.6.0" +async-std = "=1.5.0" clap = "2.33.1" ctrlc = "3.1.4" derive_more = "0.99.7" From e6bd936b94bd2592cf273baec71383e017330487 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 3 Jun 2020 01:17:16 +0300 Subject: [PATCH 0062/1210] Limit number of headers that are pruned within single import Call (#105) * removeInMemoryStorage + extract Kovan stuff to runtime * removed comment from the future * limit number of headers that are pruned within single import Call * verify that pruning range upper bottom is always-increasing * Fix typo Co-authored-by: Hernando Castano --- modules/ethereum/src/import.rs | 20 ++- modules/ethereum/src/lib.rs | 318 +++++++++++++++++++++++++++++---- 2 files changed, 295 insertions(+), 43 deletions(-) diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 17c7237fab612..87025e543fa97 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -171,7 +171,7 @@ mod tests { validator, validators, validators_addresses, TestRuntime, }; use crate::validators::ValidatorsSource; - use crate::{BridgeStorage, Headers, OldestUnprunedBlock}; + use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; use frame_support::{StorageMap, StorageValue}; #[test] @@ -264,7 +264,7 @@ mod tests { } #[test] - fn headers_are_pruned() { + fn headers_are_pruned_during_import() { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), validators_addresses(3))); @@ -354,7 +354,13 @@ mod tests { latest_block_hash = rolling_last_block_hash; step += 3; } - assert_eq!(OldestUnprunedBlock::get(), 11); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 11, + oldest_block_to_keep: 14, + }, + ); // now let's insert block signed by validator 1 // => blocks 11..24 are finalized and blocks 11..14 are pruned @@ -380,7 +386,13 @@ mod tests { ) .unwrap(); assert_eq!(finalized_blocks, expected_blocks); - assert_eq!(OldestUnprunedBlock::get(), 15); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 15, + oldest_block_to_keep: 15, + }, + ); }); } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 376d800d34dba..ba6c02c7d5f85 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -39,6 +39,9 @@ mod verification; #[cfg(test)] mod mock; +/// Maximal number of blocks we're pruning in single import call. +const MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT: u64 = 8; + /// Authority round engine configuration parameters. #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] pub struct AuraConfiguration { @@ -147,6 +150,19 @@ pub struct ChangeToEnact { pub validators: Vec
, } +/// Blocks range that we want to prune. +#[derive(Encode, Decode, Default, RuntimeDebug, Clone, PartialEq)] +struct PruningRange { + /// Number of the oldest unpruned block(s). This might be the block that we do not + /// want to prune now (then it is equal to `oldest_block_to_keep`), or block that we + /// were unable to prune for whatever reason (i.e. if it isn't finalized yet and has + /// scheduled validators set change). + pub oldest_unpruned_block: u64, + /// Number of oldest block(s) that we want to keep. We want to prune blocks in range + /// [`oldest_unpruned_block`; `oldest_block_to_keep`). + pub oldest_block_to_keep: u64, +} + /// Header import context. /// /// The import context contains information needed by the header verification @@ -364,8 +380,8 @@ decl_storage! { BestBlock: (u64, H256, U256); /// Best finalized block. FinalizedBlock: (u64, H256); - /// Oldest unpruned block(s) number. - OldestUnprunedBlock: u64; + /// Range of blocks that we want to prune. + BlocksToPrune: PruningRange; /// Map of imported headers by hash. Headers: map hasher(identity) H256 => Option>; /// Map of imported header hashes by number. @@ -399,7 +415,10 @@ decl_storage! { let initial_hash = config.initial_header.hash(); BestBlock::put((config.initial_header.number, initial_hash, config.initial_difficulty)); FinalizedBlock::put((config.initial_header.number, initial_hash)); - OldestUnprunedBlock::put(config.initial_header.number); + BlocksToPrune::put(PruningRange { + oldest_unpruned_block: config.initial_header.number, + oldest_block_to_keep: config.initial_header.number, + }); HeadersByNumber::insert(config.initial_header.number, vec![initial_hash]); Headers::::insert(initial_hash, StoredHeader { submitter: None, @@ -480,10 +499,96 @@ impl frame_support::unsigned::ValidateUnsigned for Module { #[derive(Default)] struct BridgeStorage(sp_std::marker::PhantomData); -impl BridgeStorage { +impl BridgeStorage { + /// Create new BridgeStorage. pub fn new() -> Self { BridgeStorage(sp_std::marker::PhantomData::::default()) } + + /// Prune old blocks. + fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: Option) { + let pruning_range = BlocksToPrune::get(); + let mut new_pruning_range = pruning_range.clone(); + + // update oldest block we want to keep + if let Some(prune_end) = prune_end { + if prune_end > new_pruning_range.oldest_block_to_keep { + new_pruning_range.oldest_block_to_keep = prune_end; + } + } + + // start pruning blocks + let begin = new_pruning_range.oldest_unpruned_block; + let end = new_pruning_range.oldest_block_to_keep; + for number in begin..end { + // if we can't prune anything => break + if max_blocks_to_prune == 0 { + break; + } + + // read hashes of blocks with given number and try to prune these blocks + let blocks_at_number = HeadersByNumber::take(number); + if let Some(mut blocks_at_number) = blocks_at_number { + self.prune_blocks_by_hashes( + &mut max_blocks_to_prune, + finalized_number, + number, + &mut blocks_at_number, + ); + + // if we haven't pruned all blocks, remember unpruned + if !blocks_at_number.is_empty() { + HeadersByNumber::insert(number, blocks_at_number); + break; + } + } + + // we have pruned all headers at number + new_pruning_range.oldest_unpruned_block = number + 1; + } + + // update pruning range in storage + if pruning_range != new_pruning_range { + BlocksToPrune::put(new_pruning_range); + } + } + + /// Prune old blocks with given hashes. + fn prune_blocks_by_hashes( + &self, + max_blocks_to_prune: &mut u64, + finalized_number: u64, + number: u64, + blocks_at_number: &mut Vec, + ) { + // ensure that unfinalized headers we want to prune do not have scheduled changes + if number > finalized_number { + if blocks_at_number + .iter() + .any(|block| ScheduledChanges::contains_key(block)) + { + return; + } + } + + // physically remove headers and (probably) obsolete validators sets + while let Some(hash) = blocks_at_number.pop() { + let header = Headers::::take(&hash); + ScheduledChanges::remove(hash); + if let Some(header) = header { + ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { + Some(rc) if rc > 1 => Some(rc - 1), + _ => None, + }); + } + + // check if we have already pruned too much headers in this call + *max_blocks_to_prune -= 1; + if *max_blocks_to_prune == 0 { + return; + } + } + } } impl Storage for BridgeStorage { @@ -591,41 +696,8 @@ impl Storage for BridgeStorage { FinalizedBlock::put(finalized); } - if let Some(prune_end) = prune_end { - let prune_begin = OldestUnprunedBlock::get(); - - for number in prune_begin..prune_end { - let blocks_at_number = HeadersByNumber::take(number); - - // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number { - if let Some(ref blocks_at_number) = blocks_at_number { - if blocks_at_number - .iter() - .any(|block| ScheduledChanges::contains_key(block)) - { - HeadersByNumber::insert(number, blocks_at_number); - OldestUnprunedBlock::put(number); - return; - } - } - } - - // physically remove headers and (probably) obsolete validators sets - for hash in blocks_at_number.into_iter().flat_map(|x| x) { - let header = Headers::::take(&hash); - ScheduledChanges::remove(hash); - if let Some(header) = header { - ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { - Some(rc) if rc > 1 => Some(rc - 1), - _ => None, - }); - } - } - } - - OldestUnprunedBlock::put(prune_end); - } + // and now prune headers if we need to + self.prune_blocks(MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT, finalized_number, prune_end); } } @@ -635,3 +707,171 @@ fn pool_configuration() -> PoolConfiguration { max_future_number_difference: 10, } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{custom_block_i, custom_test_ext, genesis, validators, validators_addresses, TestRuntime}; + + fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let validators = validators(3); + for i in 1..10 { + let mut headers_by_number = Vec::with_capacity(5); + for j in 0..5 { + let header = custom_block_i(i, &validators, |header| { + header.gas_limit = header.gas_limit + U256::from(j); + }); + let hash = header.hash(); + headers_by_number.push(hash); + Headers::::insert( + hash, + StoredHeader { + submitter: None, + header: header, + total_difficulty: 0.into(), + next_validators_set_id: 0, + last_signal_block: None, + }, + ); + + if i == 7 && j == 1 { + ScheduledChanges::insert( + hash, + ScheduledChange { + validators: validators_addresses(5), + prev_signal_block: None, + }, + ); + } + } + HeadersByNumber::insert(i, headers_by_number); + } + + f(BridgeStorage::new()) + }) + } + + #[test] + fn blocks_are_not_pruned_if_range_is_empty() { + with_headers_to_prune(|storage| { + BlocksToPrune::put(PruningRange { + oldest_unpruned_block: 5, + oldest_block_to_keep: 5, + }); + + // try to prune blocks [5; 10) + storage.prune_blocks(0xFFFF, 10, Some(5)); + assert_eq!(HeadersByNumber::get(&5).unwrap().len(), 5); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 5, + oldest_block_to_keep: 5, + }, + ); + }); + } + + #[test] + fn blocks_to_prune_never_shrinks_from_the_end() { + with_headers_to_prune(|storage| { + BlocksToPrune::put(PruningRange { + oldest_unpruned_block: 0, + oldest_block_to_keep: 5, + }); + + // try to prune blocks [5; 10) + storage.prune_blocks(0xFFFF, 10, Some(3)); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 5, + oldest_block_to_keep: 5, + }, + ); + }); + } + + #[test] + fn blocks_are_not_pruned_if_limit_is_zero() { + with_headers_to_prune(|storage| { + // try to prune blocks [0; 10) + storage.prune_blocks(0, 10, Some(10)); + assert!(HeadersByNumber::get(&0).is_some()); + assert!(HeadersByNumber::get(&1).is_some()); + assert!(HeadersByNumber::get(&2).is_some()); + assert!(HeadersByNumber::get(&3).is_some()); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 0, + oldest_block_to_keep: 10, + }, + ); + }); + } + + #[test] + fn blocks_are_pruned_if_limit_is_non_zero() { + with_headers_to_prune(|storage| { + // try to prune blocks [0; 10) + storage.prune_blocks(7, 10, Some(10)); + // 1 headers with number = 0 is pruned (1 total) + assert!(HeadersByNumber::get(&0).is_none()); + // 5 headers with number = 1 are pruned (6 total) + assert!(HeadersByNumber::get(&1).is_none()); + // 1 header with number = 2 are pruned (7 total) + assert_eq!(HeadersByNumber::get(&2).unwrap().len(), 4); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 2, + oldest_block_to_keep: 10, + }, + ); + + // try to prune blocks [2; 10) + storage.prune_blocks(11, 10, Some(10)); + // 4 headers with number = 2 are pruned (4 total) + assert!(HeadersByNumber::get(&2).is_none()); + // 5 headers with number = 3 are pruned (9 total) + assert!(HeadersByNumber::get(&3).is_none()); + // 2 headers with number = 4 are pruned (11 total) + assert_eq!(HeadersByNumber::get(&4).unwrap().len(), 3); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 4, + oldest_block_to_keep: 10, + }, + ); + }); + } + + #[test] + fn pruning_stops_on_unfainalized_block_with_scheduled_change() { + with_headers_to_prune(|storage| { + // try to prune blocks [0; 10) + // last finalized block is 5 + // and one of blocks#7 has scheduled change + // => we won't prune any block#7 at all + storage.prune_blocks(0xFFFF, 5, Some(10)); + assert!(HeadersByNumber::get(&0).is_none()); + assert!(HeadersByNumber::get(&1).is_none()); + assert!(HeadersByNumber::get(&2).is_none()); + assert!(HeadersByNumber::get(&3).is_none()); + assert!(HeadersByNumber::get(&4).is_none()); + assert!(HeadersByNumber::get(&5).is_none()); + assert!(HeadersByNumber::get(&6).is_none()); + assert_eq!(HeadersByNumber::get(&7).unwrap().len(), 5); + assert_eq!( + BlocksToPrune::get(), + PruningRange { + oldest_unpruned_block: 7, + oldest_block_to_keep: 10, + }, + ); + }); + } +} From 5088b31888afcb80a7a3b63b1d630b988bb2556c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 3 Jun 2020 06:23:32 +0300 Subject: [PATCH 0063/1210] Bump substrate version (#120) * bump substrate * cargo fmt --all --- bin/node/node/Cargo.toml | 84 ++++++------- bin/node/node/src/service.rs | 121 ++++++++++--------- bin/node/runtime/Cargo.toml | 102 ++++++++-------- bin/node/runtime/src/lib.rs | 53 ++++++-- modules/ethereum-contract/builtin/Cargo.toml | 19 +-- modules/ethereum-contract/builtin/src/lib.rs | 9 +- modules/ethereum/Cargo.toml | 20 +-- modules/ethereum/src/lib.rs | 2 +- modules/ethereum/src/mock.rs | 1 + modules/substrate/Cargo.toml | 36 +++--- modules/substrate/src/lib.rs | 1 + primitives/ethereum-poa/Cargo.toml | 16 +-- relays/ethereum/Cargo.toml | 24 ++-- relays/ethereum/src/substrate_client.rs | 6 +- relays/substrate/Cargo.toml | 12 +- 15 files changed, 283 insertions(+), 223 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 78bd8b6107617..a593d5ce9c167 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -19,100 +19,100 @@ bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } [dependencies.sc-cli] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa] package = "sc-finality-grandpa" -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" -[dependencies.sc-client-api] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +[dependencies.sc-consensus] +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" -[dependencies.sc-client] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +[dependencies.sc-client-api] +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -120,6 +120,6 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 82bd60c11a3cf..736cab5198989 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -17,9 +17,9 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use bridge_node_runtime::{self, opaque::Block, RuntimeApi}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider}; -use sc_client::LongestChain; +use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState, StorageAndProofProvider}; use sc_client_api::ExecutorProvider; +use sc_consensus::LongestChain; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_service::{error::Error as ServiceError, AbstractService, Configuration, ServiceBuilder}; @@ -51,7 +51,7 @@ macro_rules! new_full_start { bridge_node_runtime::RuntimeApi, crate::service::Executor, >($config)? - .with_select_chain(|_config, backend| Ok(sc_client::LongestChain::new(backend.clone())))? + .with_select_chain(|_config, backend| Ok(sc_consensus::LongestChain::new(backend.clone())))? .with_transaction_pool(|config, client, _fetcher, prometheus_registry| { let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); Ok(sc_transaction_pool::BasicPool::new( @@ -60,32 +60,36 @@ macro_rules! new_full_start { prometheus_registry, )) })? - .with_import_queue(|_config, client, mut select_chain, _transaction_pool| { - let select_chain = select_chain - .take() - .ok_or_else(|| sc_service::Error::SelectChainRequired)?; - - let (grandpa_block_import, grandpa_link) = - grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; - - let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( - grandpa_block_import.clone(), - client.clone(), - ); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import.clone())), - None, - client, - inherent_data_providers.clone(), - )?; - - import_setup = Some((grandpa_block_import, grandpa_link)); - - Ok(import_queue) - })? + .with_import_queue( + |_config, client, mut select_chain, _transaction_pool, spawn_task_handle, registry| { + let select_chain = select_chain + .take() + .ok_or_else(|| sc_service::Error::SelectChainRequired)?; + + let (grandpa_block_import, grandpa_link) = + grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; + + let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( + grandpa_block_import.clone(), + client.clone(), + ); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client, + inherent_data_providers.clone(), + spawn_task_handle, + registry, + )?; + + import_setup = Some((grandpa_block_import, grandpa_link)); + + Ok(import_queue) + }, + )? .with_rpc_extensions(|builder| -> Result, _> { use substrate_frame_rpc_system::{FullSystem, SystemApi}; @@ -122,7 +126,11 @@ pub fn new_full(config: Configuration) -> Result Result Result), - Arc::new(fetch_checker), - )?; - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>( - sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import, - None, - Some(Box::new(finality_proof_import)), - client, - inherent_data_providers.clone(), - )?; - - Ok((import_queue, finality_proof_request_builder)) - })? + .with_import_queue_and_fprb( + |_config, client, backend, fetcher, _select_chain, _tx_pool, spawn_task_handle, prometheus_registry| { + let fetch_checker = fetcher + .map(|fetcher| fetcher.checker().clone()) + .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; + let grandpa_block_import = grandpa::light_block_import( + client.clone(), + backend, + &(client.clone() as Arc<_>), + Arc::new(fetch_checker), + )?; + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + sc_consensus_aura::slot_duration(&*client)?, + grandpa_block_import, + None, + Some(Box::new(finality_proof_import)), + client, + inherent_data_providers.clone(), + spawn_task_handle, + prometheus_registry, + )?; + + Ok((import_queue, finality_proof_request_builder)) + }, + )? .with_finality_proof_provider(|client, backend| { let provider = client as Arc>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 92351e0c44c27..d8e5a8a92a21d 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -22,15 +22,15 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-bridge-eth-poa] @@ -39,76 +39,76 @@ default-features = false path = "../../../modules/ethereum" [dependencies.frame-support] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-bridge-eth-poa] @@ -117,75 +117,75 @@ default-features = false path = "../../../primitives/ethereum-poa" [dependencies.sp-consensus-aura] -version = "0.8.0-alpha.6" +version = "0.8.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [build-dependencies.wasm-builder-runner] version = "1.0.5" package = "substrate-wasm-builder-runner" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [features] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index ff4d796cf93a2..d02d108d514a1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -27,13 +27,12 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod kovan; use codec::{Decode, Encode}; -use pallet_grandpa::fg_primitives; -use pallet_grandpa::AuthorityList as GrandpaAuthorityList; +use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_core::OpaqueMetadata; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, IdentityLookup, OpaqueKeys, Verify, + BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify, }; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -48,8 +47,8 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::Randomness, - weights::{RuntimeDbWeight, Weight}, + traits::{KeyOwnerProofSystem, Randomness}, + weights::{IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; pub use pallet_balances::Call as BalancesCall; @@ -143,6 +142,9 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 2_000_000_000_000; pub const ExtrinsicBaseWeight: Weight = 10_000_000; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub const MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() + .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { @@ -184,6 +186,10 @@ impl frame_system::Trait for Runtime { /// The base weight of any extrinsic processed by the runtime, independent of the /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, + /// idependent of the logic of that extrinsics. (Roughly max block weight - average on + /// initialize cost). + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. type MaximumBlockLength = MaximumBlockLength; /// Portion of the block weight that is available to all normal transactions. @@ -219,6 +225,16 @@ impl pallet_bridge_eth_poa::Trait for Runtime { impl pallet_grandpa::Trait for Runtime { type Event = Event; + type Call = Call; + + type KeyOwnerProofSystem = (); + + type KeyOwnerProof = >::Proof; + + type KeyOwnerIdentification = + >::IdentificationTuple; + + type HandleEquivocation = (); } parameter_types! { @@ -255,7 +271,7 @@ impl pallet_transaction_payment::Trait for Runtime { type Currency = pallet_balances::Module; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; - type WeightToFee = ConvertInto; + type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -363,7 +379,8 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( - frame_system::CheckVersion, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, frame_system::CheckGenesis, frame_system::CheckEra, frame_system::CheckNonce, @@ -487,6 +504,26 @@ impl_runtime_apis! { fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } + + fn submit_report_equivocation_extrinsic( + _equivocation_proof: fg_primitives::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: fg_primitives::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } } } diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 864d0fbbdea7a..4d36fa98fb27c 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -11,35 +11,36 @@ edition = "2018" codec = { package = "parity-scale-codec", version = "1.0.0" } ethereum-types = "0.9.2" +finality-grandpa = "0.12.3" # Runtime/chain specific dependencies bridge-node-runtime = { path = "../../../bin/node/runtime" } [dependencies.sp-blockchain] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sc-finality-grandpa] version = "0.8.0-dev" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dev-dependencies] hex = "0.4" [dev-dependencies.sp-core] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs index 739e14d69efc6..2f4200f3442f7 100644 --- a/modules/ethereum-contract/builtin/src/lib.rs +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -17,6 +17,7 @@ use bridge_node_runtime::{Block, BlockNumber, Hash, Header as RuntimeHeader}; use codec::{Decode, Encode}; use ethereum_types::U256; +use finality_grandpa::voter_set::VoterSet; use sp_blockchain::Error as ClientError; use sp_finality_grandpa::{AuthorityList, ConsensusLog, GRANDPA_ENGINE_ID}; @@ -29,6 +30,8 @@ pub enum Error { HeaderDecode(codec::Error), /// Failed to decode best voters set. BestSetDecode(codec::Error), + /// Best voters set is invalid. + InvalidBestSet, /// Failed to decode finality proof. FinalityProofDecode(codec::Error), /// Failed to verify justification. @@ -108,12 +111,14 @@ pub fn verify_substrate_finality_proof( raw_best_set: &[u8], raw_finality_proof: &[u8], ) -> Result<(), Error> { - let best_set = AuthorityList::decode(&mut &raw_best_set[..]).map_err(Error::BestSetDecode)?; + let best_set = AuthorityList::decode(&mut &raw_best_set[..]) + .map_err(Error::BestSetDecode) + .and_then(|authorities| VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet))?; sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( &raw_finality_proof, (finality_target_hash, finality_target_number), best_set_id, - &best_set.into_iter().collect(), + &best_set, ) .map_err(Error::JustificationVerify) .map(|_| ()) diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 96024f0ac70a0..667abe8d97846 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -12,33 +12,33 @@ primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum- # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" # Dev Dependencies diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ba6c02c7d5f85..232f89d9c3361 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -673,7 +673,7 @@ impl Storage for BridgeStorage { }; let last_signal_block = header.context.last_signal_block().cloned(); - HeadersByNumber::append_or_insert(header.header.number, vec![header.hash]); + HeadersByNumber::append(header.header.number, header.hash); Headers::::insert( &header.hash, StoredHeader { diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 6624b149a9045..44213813fe3ce 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -59,6 +59,7 @@ impl frame_system::Trait for TestRuntime { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index a62ee1a57ef7f..4f5f91c05b0d8 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -13,57 +13,57 @@ hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "0.8.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index cb6142e426f84..148ebd5ef9866 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -265,6 +265,7 @@ mod tests { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); type AvailableBlockRatio = (); type MaximumBlockLength = (); type Version = (); diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index dca0750b3acde..32ac689bb9b8e 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -22,27 +22,27 @@ plain_hasher = { version = "0.2.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-alpha.6" +version = "2.0.0-rc1" default-features = false -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [features] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 05553d8bb5389..d3e6770fc5ca9 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -33,36 +33,36 @@ web3 = { git = "https://github.com/tomusdrw/rust-web3" } # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" # I think this is used for sr-io and stuff [dependencies.node-primitives] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" # Branch used for keccack256 hasher code # Could probably move the keccack hasher stuff to our own primitives [dependencies.sp-core] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate.git" # This should get moved to our `bin` folder diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index ec7c36443f075..0319c0b5ac828 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -391,7 +391,8 @@ fn create_signed_submit_transaction( let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( - frame_system::CheckVersion::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), frame_system::CheckNonce::::from(i), @@ -403,7 +404,8 @@ fn create_signed_submit_transaction( function, extra(index, 0), ( - bridge_node_runtime::VERSION.spec_version as u32, + bridge_node_runtime::VERSION.spec_version, + bridge_node_runtime::VERSION.transaction_version, genesis_hash, genesis_hash, (), diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 7f151e55a446e..9cfeec36131e3 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -17,16 +17,16 @@ serde_json = "1.0.53" url = "2.1.0" [dependencies.sp-core] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.sp-rpc] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" [dependencies.node-primitives] -version = "2.0.0-alpha.6" -rev = "c13ad41634d0bd7cf07897c2aa062b917d520520" +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" git = "https://github.com/paritytech/substrate/" From 0a09b8698985735841bc155cdded1969d156ed9b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 5 Jun 2020 04:12:31 +0300 Subject: [PATCH 0064/1210] Claim funds on Substrate chain by providing proof of funds locking on PoA chain (#91) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ethereum exchange module * continue * continue * added tests for exchange module * moved * remove println * move again * fixes * removed redundant deps * cargo fmt * fund_locks_transaction_decode_works * cargo fmt --all * fix error processing * added some tracing to bridge modules * more tests * more tests * cargo fmt --all * kovan.rs -> exchange.rs * Update bin/node/runtime/src/exchange.rs Co-authored-by: Tomasz Drwięga * added assumption doc * Airdrop -> DepositInto * AsIs -> Identity * OnTransactionSubmitted * Transfers::Key = Id * typo * Update bin/node/runtime/src/exchange.rs Co-authored-by: Tomasz Drwięga * block+tx+proof -> proof { block, tx, proof } * cargo fmt --all * docs * check <-> verify * parse hex * extracted exchange primitives to separate crate * added docs to runtime::exchange module * Update bin/node/runtime/src/exchange.rs Co-authored-by: Hernando Castano * typo * Update modules/currency-exchange/Cargo.toml Co-authored-by: Hernando Castano * add docs to currency-exchange module * change tests names * cargo fmt --all * Update bin/node/runtime/src/exchange.rs Co-authored-by: Hernando Castano * Update bin/node/runtime/src/exchange.rs Co-authored-by: Hernando Castano * Update bin/node/runtime/src/exchange.rs Co-authored-by: Hernando Castano * Update bin/node/runtime/src/exchange.rs Co-authored-by: Hernando Castano * Update bin/node/runtime/src/exchange.rs Co-authored-by: Hernando Castano * fixed verify_transaction_finalized for siblings of finalized blocks * cargo fmt --all * added double spend note * cargo fmt --all Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- bin/node/runtime/Cargo.toml | 15 + bin/node/runtime/src/exchange.rs | 229 +++++++++++++ bin/node/runtime/src/lib.rs | 46 ++- modules/currency-exchange/Cargo.toml | 58 ++++ modules/currency-exchange/src/lib.rs | 418 ++++++++++++++++++++++++ modules/ethereum/src/finality.rs | 5 +- modules/ethereum/src/lib.rs | 195 ++++++++++- modules/ethereum/src/validators.rs | 2 +- modules/ethereum/src/verification.rs | 2 +- primitives/currency-exchange/Cargo.toml | 31 ++ primitives/currency-exchange/src/lib.rs | 127 +++++++ primitives/ethereum-poa/Cargo.toml | 3 + primitives/ethereum-poa/src/lib.rs | 193 ++++++++++- relays/ethereum/Cargo.toml | 2 +- 14 files changed, 1300 insertions(+), 26 deletions(-) create mode 100644 bin/node/runtime/src/exchange.rs create mode 100644 modules/currency-exchange/Cargo.toml create mode 100644 modules/currency-exchange/src/lib.rs create mode 100644 primitives/currency-exchange/Cargo.toml create mode 100644 primitives/currency-exchange/src/lib.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index d8e5a8a92a21d..e3cc405ee94d5 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -9,6 +9,9 @@ repository = "https://github.com/paritytech/parity-bridges-common/" [dependencies] hex-literal = "0.2" +[dev-dependencies] +ethereum-tx-sign = "3.0" + [dependencies.codec] package = "parity-scale-codec" version = "1.0.0" @@ -38,6 +41,11 @@ version = "0.1.0" default-features = false path = "../../../modules/ethereum" +[dependencies.pallet-bridge-currency-exchange] +version = "0.1.0" +default-features = false +path = "../../../modules/currency-exchange" + [dependencies.frame-support] version = "2.0.0-rc1" default-features = false @@ -116,6 +124,11 @@ version = "0.1.0" default-features = false path = "../../../primitives/ethereum-poa" +[dependencies.sp-currency-exchange] +version = "0.1.0" +default-features = false +path = "../../../primitives/currency-exchange" + [dependencies.sp-consensus-aura] version = "0.8.0-rc1" default-features = false @@ -194,6 +207,7 @@ std = [ "pallet-aura/std", "pallet-balances/std", "pallet-bridge-eth-poa/std", + "pallet-bridge-currency-exchange/std", "codec/std", "frame-executive/std", "frame-support/std", @@ -205,6 +219,7 @@ std = [ "sp-api/std", "sp-block-builder/std", "sp-bridge-eth-poa/std", + "sp-currency-exchange/std", "sp-consensus-aura/std", "sp-core/std", "sp-inherents/std", diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs new file mode 100644 index 0000000000000..e269882a50d4d --- /dev/null +++ b/bin/node/runtime/src/exchange.rs @@ -0,0 +1,229 @@ +// Copyright 2019-2020 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 . + +//! Support for PoA -> Substrate native tokens exchange. +//! +//! If you want to exchange native PoA tokens for native Substrate +//! chain tokens, you need to: +//! 1) send some PoA tokens to `LOCK_FUNDS_ADDRESS` address on PoA chain. Data field of +//! the transaction must be SCALE-encoded id of Substrate account that will receive +//! funds on Substrate chain; +//! 2) wait until the 'lock funds' transaction is mined on PoA chain; +//! 3) wait until the block containing the 'lock funds' transaction is finalized on PoA chain; +//! 4) wait until the required PoA header and its finality are provided +//! to the PoA -> Substrate bridge module (it can be provided by you); +//! 5) receive tokens by providing proof-of-inclusion of PoA transaction. + +use codec::{Decode, Encode}; +use frame_support::RuntimeDebug; +use hex_literal::hex; +use pallet_bridge_currency_exchange::Blockchain; +use sp_bridge_eth_poa::transaction_decode; +use sp_currency_exchange::{ + Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, +}; +use sp_std::vec::Vec; + +/// Ethereum address where locked PoA funds must be sent to. +const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); + +/// Ethereum transaction inclusion proof. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +pub struct EthereumTransactionInclusionProof { + /// Hash of the block with transaction. + pub block: sp_core::H256, + /// Index of the transaction within the block. + pub index: u64, + /// The proof itself (right now it is all RLP-encoded transactions of the block). + pub proof: Vec>, +} + +/// We uniquely identify transfer by the pair (sender, nonce). +/// +/// The assumption is that this pair will never appear more than once in +/// transactions included into finalized blocks. This is obviously true +/// for any existing eth-like chain (that keep current tx format), because +/// otherwise transaction can be replayed over and over. +#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +pub struct EthereumTransactionTag { + /// Account that has locked funds. + pub account: [u8; 20], + /// Lock transaction nonce. + pub nonce: sp_core::U256, +} + +/// Eth blockchain from runtime perspective. +pub struct EthBlockchain; + +impl Blockchain for EthBlockchain { + type Transaction = Vec; + type TransactionInclusionProof = EthereumTransactionInclusionProof; + + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + let is_transaction_finalized = + crate::BridgeEthPoA::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + + if !is_transaction_finalized { + return None; + } + + proof.proof.get(proof.index as usize).cloned() + } +} + +/// Eth transaction from runtime perspective. +pub struct EthTransaction; + +impl MaybeLockFundsTransaction for EthTransaction { + type Transaction = Vec; + type Id = EthereumTransactionTag; + type Recipient = crate::AccountId; + type Amount = crate::Balance; + + fn parse( + raw_tx: &Self::Transaction, + ) -> ExchangeResult> { + let tx = transaction_decode(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?; + + // we only accept transactions sending funds directly to the pre-configured address + if tx.to != Some(LOCK_FUNDS_ADDRESS.into()) { + frame_support::debug::error!( + target: "runtime", + "Failed to parse fund locks transaction. Invalid peer recipient: {:?}", + tx.to, + ); + + return Err(ExchangeError::InvalidTransaction); + } + + let mut recipient_raw = sp_core::H256::default(); + match tx.payload.len() { + 32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.payload), + len => { + frame_support::debug::error!( + target: "runtime", + "Failed to parse fund locks transaction. Invalid recipient length: {}", + len, + ); + + return Err(ExchangeError::InvalidRecipient); + } + } + let amount = tx.value.low_u128(); + + if tx.value != amount.into() { + frame_support::debug::error!( + target: "runtime", + "Failed to parse fund locks transaction. Invalid amount: {}", + tx.value, + ); + + return Err(ExchangeError::InvalidAmount); + } + + Ok(LockFundsTransaction { + id: EthereumTransactionTag { + account: *tx.sender.as_fixed_bytes(), + nonce: tx.nonce, + }, + recipient: crate::AccountId::from(*recipient_raw.as_fixed_bytes()), + amount, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + fn ferdie() -> crate::AccountId { + hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into() + } + + fn prepare_ethereum_transaction(editor: impl Fn(&mut ethereum_tx_sign::RawTransaction)) -> Vec { + // prepare tx for OpenEthereum private dev chain: + // chain id is 0x11 + // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 + let chain_id = 0x11_u64; + let signer = hex!("4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7"); + let ferdie_id = ferdie(); + let ferdie_raw: &[u8; 32] = ferdie_id.as_ref(); + let mut eth_tx = ethereum_tx_sign::RawTransaction { + nonce: 0.into(), + to: Some(LOCK_FUNDS_ADDRESS.into()), + value: 100.into(), + gas: 100_000.into(), + gas_price: 100_000.into(), + data: ferdie_raw.to_vec(), + }; + editor(&mut eth_tx); + eth_tx.sign(&signer.into(), &chain_id) + } + + #[test] + fn valid_transaction_accepted() { + assert_eq!( + EthTransaction::parse(&prepare_ethereum_transaction(|_| {})), + Ok(LockFundsTransaction { + id: EthereumTransactionTag { + account: hex!("00a329c0648769a73afac7f9381e08fb43dbea72"), + nonce: 0.into(), + }, + recipient: ferdie(), + amount: 100, + }), + ); + } + + #[test] + fn invalid_transaction_rejected() { + assert_eq!( + EthTransaction::parse(&Vec::new()), + Err(ExchangeError::InvalidTransaction), + ); + } + + #[test] + fn transaction_with_invalid_peer_recipient_rejected() { + assert_eq!( + EthTransaction::parse(&prepare_ethereum_transaction(|tx| { + tx.to = None; + })), + Err(ExchangeError::InvalidTransaction), + ); + } + + #[test] + fn transaction_with_invalid_recipient_rejected() { + assert_eq!( + EthTransaction::parse(&prepare_ethereum_transaction(|tx| { + tx.data.clear(); + })), + Err(ExchangeError::InvalidRecipient), + ); + } + + #[test] + fn transaction_with_invalid_amount_rejected() { + assert_eq!( + EthTransaction::parse(&prepare_ethereum_transaction(|tx| { + tx.value = sp_core::U256::from(u128::max_value()) + sp_core::U256::from(1); + })), + Err(ExchangeError::InvalidAmount), + ); + } +} diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d02d108d514a1..eef870a3f58c3 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -24,6 +24,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +mod exchange; + pub mod kovan; use codec::{Decode, Encode}; @@ -47,11 +49,12 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::{KeyOwnerProofSystem, Randomness}, + traits::{Currency, ExistenceRequirement, KeyOwnerProofSystem, Randomness}, weights::{IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; pub use pallet_balances::Call as BalancesCall; +pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] @@ -223,6 +226,46 @@ impl pallet_bridge_eth_poa::Trait for Runtime { type OnHeadersSubmitted = (); } +impl pallet_bridge_currency_exchange::Trait for Runtime { + type OnTransactionSubmitted = (); + type PeerBlockchain = exchange::EthBlockchain; + type PeerMaybeLockFundsTransaction = exchange::EthTransaction; + type RecipientsMap = sp_currency_exchange::IdentityRecipients; + type Amount = Balance; + type CurrencyConverter = sp_currency_exchange::IdentityCurrencyConverter; + type DepositInto = DepositInto; +} + +pub struct DepositInto; + +impl sp_currency_exchange::DepositInto for DepositInto { + type Recipient = AccountId; + type Amount = Balance; + + fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { + as Currency>::deposit_into_existing(&recipient, amount) + .map(|_| { + frame_support::debug::trace!( + target: "runtime", + "Deposited {} to {:?}", + amount, + recipient, + ); + }) + .map_err(|e| { + frame_support::debug::error!( + target: "runtime", + "Deposit of {} to {:?} has failed with: {:?}", + amount, + recipient, + e + ); + + sp_currency_exchange::Error::DepositFailed + }) + } +} + impl pallet_grandpa::Trait for Runtime { type Event = Event; type Call = Call; @@ -364,6 +407,7 @@ construct_runtime!( Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, Session: pallet_session::{Module, Call, Storage, Event, Config}, BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage, ValidateUnsigned}, + BridgeCurrencyExchange: pallet_bridge_currency_exchange::{Module, Call}, } ); diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml new file mode 100644 index 0000000000000..cd3d11211985c --- /dev/null +++ b/modules/currency-exchange/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "pallet-bridge-currency-exchange" +description = "A Substrate Runtime module that accepts 'lock funds' transactions from a peer chain and grants an equivalent amount to a the appropriate Substrate account." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +sp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } + +# Substrate Based Dependencies +[dependencies.frame-support] +version = "2.0.0-rc1" +default-features = false +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system] +version = "2.0.0-rc1" +default-features = false +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-std] +version = "2.0.0-rc1" +default-features = false +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-rc1" +default-features = false +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies.sp-core] +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies.sp-io] +version = "2.0.0-rc1" +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate/" + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-currency-exchange/std", +] diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs new file mode 100644 index 0000000000000..a4ef7360f9ed6 --- /dev/null +++ b/modules/currency-exchange/src/lib.rs @@ -0,0 +1,418 @@ +// Copyright 2019-2020 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 . + +//! Runtime module that allows tokens exchange between two bridged chains. + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{decl_error, decl_module, decl_storage, ensure, Parameter}; +use sp_currency_exchange::{ + CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, +}; +use sp_runtime::DispatchResult; + +/// Called when transaction is submitted to the exchange module. +pub trait OnTransactionSubmitted { + /// Called when valid transaction is submitted and accepted by the module. + fn on_valid_transaction_submitted(submitter: AccountId); +} + +/// Peer blockhain interface. +pub trait Blockchain { + /// Transaction type. + type Transaction: Parameter; + /// Transaction inclusion proof type. + type TransactionInclusionProof: Parameter; + + /// Verify that transaction is a part of given block. + /// + /// Returns Some(transaction) if proof is valid and None otherwise. + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option; +} + +/// The module configuration trait +pub trait Trait: frame_system::Trait { + /// Handler for transaction submission result. + type OnTransactionSubmitted: OnTransactionSubmitted; + /// Peer blockchain type. + type PeerBlockchain: Blockchain; + /// Peer blockchain transaction parser. + type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< + Transaction = ::Transaction, + >; + /// Map between blockchains recipients. + type RecipientsMap: RecipientsMap< + PeerRecipient = ::Recipient, + Recipient = Self::AccountId, + >; + /// This blockchain currency amount type. + type Amount; + /// Converter from peer blockchain currency type into current blockchain currency type. + type CurrencyConverter: CurrencyConverter< + SourceAmount = ::Amount, + TargetAmount = Self::Amount, + >; + /// Something that could grant money. + type DepositInto: DepositInto; +} + +decl_error! { + pub enum Error for Module { + /// Invalid peer blockchain transaction provided. + InvalidTransaction, + /// Peer transaction has invalid amount. + InvalidAmount, + /// Peer transaction has invalid recipient. + InvalidRecipient, + /// Cannot map from peer recipient to this blockchain recipient. + FailedToMapRecipients, + /// Failed to convert from peer blockchain currency to this blockhain currency. + FailedToConvertCurrency, + /// Deposit has failed. + DepositFailed, + /// Transaction is not finalized. + UnfinalizedTransaction, + /// Transaction funds are already claimed. + AlreadyClaimed, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + /// Imports lock fund transaction of the peer blockchain. + #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + pub fn import_peer_transaction( + origin, + proof: <::PeerBlockchain as Blockchain>::TransactionInclusionProof, + ) -> DispatchResult { + let submitter = frame_system::ensure_signed(origin)?; + + // ensure that transaction is included in finalized block that we know of + let transaction = ::PeerBlockchain::verify_transaction_inclusion_proof( + &proof, + ).ok_or_else(|| Error::::UnfinalizedTransaction)?; + + // parse transaction + let transaction = ::PeerMaybeLockFundsTransaction::parse(&transaction) + .map_err(Error::::from)?; + let transfer_id = transaction.id; + ensure!( + !Transfers::::contains_key(&transfer_id), + Error::::AlreadyClaimed + ); + + // grant recipient + let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; + let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; + + // make sure to update the mapping if we deposit successfully to avoid double spending, + // i.e. whenever `deposit_into` is successful we MUST update `Transfers`. + { + T::DepositInto::deposit_into(recipient, amount).map_err(Error::::from)?; + Transfers::::insert(transfer_id, ()) + } + + // reward submitter for providing valid message + T::OnTransactionSubmitted::on_valid_transaction_submitted(submitter); + + Ok(()) + } + } +} + +decl_storage! { + trait Store for Module as Bridge { + /// All transfers that have already been claimed. + Transfers: map hasher(blake2_128_concat) ::Id => (); + } +} + +impl From for Error { + fn from(error: ExchangeError) -> Self { + match error { + ExchangeError::InvalidTransaction => Error::InvalidTransaction, + ExchangeError::InvalidAmount => Error::InvalidAmount, + ExchangeError::InvalidRecipient => Error::InvalidRecipient, + ExchangeError::FailedToMapRecipients => Error::FailedToMapRecipients, + ExchangeError::FailedToConvertCurrency => Error::FailedToConvertCurrency, + ExchangeError::DepositFailed => Error::DepositFailed, + } + } +} + +impl OnTransactionSubmitted for () { + fn on_valid_transaction_submitted(_: AccountId) {} +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types, weights::Weight}; + use sp_core::H256; + use sp_currency_exchange::LockFundsTransaction; + use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, + }; + + type AccountId = u64; + + const INVALID_TRANSACTION_ID: u64 = 100; + const ALREADY_CLAIMED_TRANSACTION_ID: u64 = 101; + const UNKNOWN_RECIPIENT_ID: u64 = 0; + const INVALID_AMOUNT: u64 = 0; + const MAX_DEPOSIT_AMOUNT: u64 = 1000; + const SUBMITTER: u64 = 2000; + + type RawTransaction = LockFundsTransaction; + + pub struct DummyTransactionSubmissionHandler; + + impl OnTransactionSubmitted for DummyTransactionSubmissionHandler { + fn on_valid_transaction_submitted(submitter: AccountId) { + Transfers::::insert(submitter, ()); + } + } + + pub struct DummyBlockchain; + + impl Blockchain for DummyBlockchain { + type Transaction = RawTransaction; + type TransactionInclusionProof = (bool, RawTransaction); + + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + if proof.0 { + Some(proof.1.clone()) + } else { + None + } + } + } + + pub struct DummyTransaction; + + impl MaybeLockFundsTransaction for DummyTransaction { + type Transaction = RawTransaction; + type Id = u64; + type Recipient = AccountId; + type Amount = u64; + + fn parse(tx: &Self::Transaction) -> sp_currency_exchange::Result { + match tx.id { + INVALID_TRANSACTION_ID => Err(sp_currency_exchange::Error::InvalidTransaction), + _ => Ok(tx.clone()), + } + } + } + + pub struct DummyRecipientsMap; + + impl RecipientsMap for DummyRecipientsMap { + type PeerRecipient = AccountId; + type Recipient = AccountId; + + fn map(peer_recipient: Self::PeerRecipient) -> sp_currency_exchange::Result { + match peer_recipient { + UNKNOWN_RECIPIENT_ID => Err(sp_currency_exchange::Error::FailedToMapRecipients), + _ => Ok(peer_recipient * 10), + } + } + } + + pub struct DummyCurrencyConverter; + + impl CurrencyConverter for DummyCurrencyConverter { + type SourceAmount = u64; + type TargetAmount = u64; + + fn convert(amount: Self::SourceAmount) -> sp_currency_exchange::Result { + match amount { + INVALID_AMOUNT => Err(sp_currency_exchange::Error::FailedToConvertCurrency), + _ => Ok(amount * 10), + } + } + } + + pub struct DummyDepositInto; + + impl DepositInto for DummyDepositInto { + type Recipient = AccountId; + type Amount = u64; + + fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { + match amount > MAX_DEPOSIT_AMOUNT { + true => Err(sp_currency_exchange::Error::DepositFailed), + _ => Ok(()), + } + } + } + + #[derive(Clone, Eq, PartialEq)] + pub struct TestRuntime; + + impl_outer_origin! { + pub enum Origin for TestRuntime where system = frame_system {} + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + } + + impl Trait for TestRuntime { + type OnTransactionSubmitted = DummyTransactionSubmissionHandler; + type PeerBlockchain = DummyBlockchain; + type PeerMaybeLockFundsTransaction = DummyTransaction; + type RecipientsMap = DummyRecipientsMap; + type Amount = u64; + type CurrencyConverter = DummyCurrencyConverter; + type DepositInto = DummyDepositInto; + } + + type Exchange = Module; + + fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + sp_io::TestExternalities::new(t) + } + + fn transaction(id: u64) -> RawTransaction { + RawTransaction { + id, + recipient: 1, + amount: 2, + } + } + + #[test] + fn unfinalized_transaction_rejected() { + new_test_ext().execute_with(|| { + assert_noop!( + Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (false, transaction(0))), + Error::::UnfinalizedTransaction, + ); + }); + } + + #[test] + fn invalid_transaction_rejected() { + new_test_ext().execute_with(|| { + assert_noop!( + Exchange::import_peer_transaction( + Origin::signed(SUBMITTER), + (true, transaction(INVALID_TRANSACTION_ID)), + ), + Error::::InvalidTransaction, + ); + }); + } + + #[test] + fn claimed_transaction_rejected() { + new_test_ext().execute_with(|| { + ::Transfers::insert(ALREADY_CLAIMED_TRANSACTION_ID, ()); + assert_noop!( + Exchange::import_peer_transaction( + Origin::signed(SUBMITTER), + (true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)), + ), + Error::::AlreadyClaimed, + ); + }); + } + + #[test] + fn transaction_with_unknown_recipient_rejected() { + new_test_ext().execute_with(|| { + let mut transaction = transaction(0); + transaction.recipient = UNKNOWN_RECIPIENT_ID; + assert_noop!( + Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), + Error::::FailedToMapRecipients, + ); + }); + } + + #[test] + fn transaction_with_invalid_amount_rejected() { + new_test_ext().execute_with(|| { + let mut transaction = transaction(0); + transaction.amount = INVALID_AMOUNT; + assert_noop!( + Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), + Error::::FailedToConvertCurrency, + ); + }); + } + + #[test] + fn transaction_with_invalid_deposit_rejected() { + new_test_ext().execute_with(|| { + let mut transaction = transaction(0); + transaction.amount = MAX_DEPOSIT_AMOUNT; + assert_noop!( + Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), + Error::::DepositFailed, + ); + }); + } + + #[test] + fn valid_transaction_accepted() { + new_test_ext().execute_with(|| { + assert_ok!(Exchange::import_peer_transaction( + Origin::signed(SUBMITTER), + (true, transaction(0)), + ),); + + // ensure that the transfer has been marked as completed + assert!(::Transfers::contains_key(0u64)); + // ensure that submitter has been rewarded + assert!(::Transfers::contains_key(SUBMITTER)); + }); + } +} diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 676108a30dc68..70d79fb20d08e 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -103,7 +103,7 @@ fn prepare_votes( // we only take ancestors that are not yet pruned and those signed by // the same set of validators let mut parent_empty_step_signers = empty_steps_signers(header); - let ancestry = ancestry(storage, header) + let ancestry = ancestry(storage, header.parent_hash) .map(|(hash, header, submitter)| { let mut signers = BTreeSet::new(); sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); @@ -196,9 +196,8 @@ fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option /// Return iterator of given header ancestors. pub(crate) fn ancestry<'a, S: Storage>( storage: &'a S, - header: &Header, + mut parent_hash: H256, ) -> impl Iterator)> + 'a { - let mut parent_hash = header.parent_hash.clone(); from_fn(move || { let (header, submitter) = storage.header(&parent_hash)?; if header.number == 0 { diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 232f89d9c3361..3f662547d19db 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -18,7 +18,7 @@ use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage, traits::Get}; -use primitives::{Address, Header, Receipt, H256, U256}; +use primitives::{Address, Header, RawTransaction, Receipt, H256, U256}; use sp_runtime::{ transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity, @@ -456,6 +456,11 @@ impl Module { pub fn is_known_block(hash: H256) -> bool { BridgeStorage::::new().header(&hash).is_some() } + + /// Verify that transaction is included into given finalized block. + pub fn verify_transaction_finalized(block: H256, tx_index: u64, proof: &Vec) -> bool { + crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) + } } impl frame_support::unsigned::ValidateUnsigned for Module { @@ -672,6 +677,13 @@ impl Storage for BridgeStorage { } }; + frame_support::debug::trace!( + target: "runtime", + "Inserting PoA header: ({}, {})", + header.header.number, + header.hash, + ); + let last_signal_block = header.context.last_signal_block().cloned(); HeadersByNumber::append(header.header.number, header.hash); Headers::::insert( @@ -693,6 +705,13 @@ impl Storage for BridgeStorage { .map(|f| f.0) .unwrap_or_else(|| FinalizedBlock::get().0); if let Some(finalized) = finalized { + frame_support::debug::trace!( + target: "runtime", + "Finalizing PoA header: ({}, {})", + finalized.0, + finalized.1, + ); + FinalizedBlock::put(finalized); } @@ -701,6 +720,44 @@ impl Storage for BridgeStorage { } } +/// Verify that transaction is included into given finalized block. +pub fn verify_transaction_finalized( + storage: &S, + block: H256, + tx_index: u64, + proof: &Vec, +) -> bool { + if tx_index >= proof.len() as _ { + return false; + } + + let header = match storage.header(&block) { + Some((header, _)) => header, + None => return false, + }; + let (finalized_number, finalized_hash) = storage.finalized_block(); + + // if header is not yet finalized => return + if header.number > finalized_number { + return false; + } + + // check if header is actually finalized + let is_finalized = match header.number < finalized_number { + true => finality::ancestry(storage, finalized_hash) + .skip_while(|(_, ancestor, _)| ancestor.number > header.number) + .filter(|&(ancestor_hash, _, _)| ancestor_hash == block) + .next() + .is_some(), + false => block == finalized_hash, + }; + if !is_finalized { + return false; + } + + header.verify_transactions_root(proof) +} + /// Transaction pool configuration. fn pool_configuration() -> PoolConfiguration { PoolConfiguration { @@ -709,9 +766,12 @@ fn pool_configuration() -> PoolConfiguration { } #[cfg(test)] -mod tests { +pub(crate) mod tests { use super::*; - use crate::mock::{custom_block_i, custom_test_ext, genesis, validators, validators_addresses, TestRuntime}; + use crate::mock::{ + custom_block_i, custom_test_ext, genesis, insert_header, validators, validators_addresses, TestRuntime, + }; + use primitives::compute_merkle_root; fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { @@ -874,4 +934,133 @@ mod tests { ); }); } + + fn example_tx() -> Vec { + vec![42] + } + + fn example_header() -> Header { + let mut header = Header::default(); + header.number = 2; + header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.parent_hash = example_header_parent().hash(); + header + } + + fn example_header_parent() -> Header { + let mut header = Header::default(); + header.number = 1; + header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.parent_hash = genesis().hash(); + header + } + + #[test] + fn verify_transaction_finalized_works_for_best_finalized_header() { + custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { + let storage = BridgeStorage::::new(); + assert_eq!( + verify_transaction_finalized(&storage, example_header().hash(), 0, &vec![example_tx()],), + true, + ); + }); + } + + #[test] + fn verify_transaction_finalized_works_for_best_finalized_header_ancestor() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let mut storage = BridgeStorage::::new(); + insert_header(&mut storage, example_header_parent()); + insert_header(&mut storage, example_header()); + storage.finalize_headers(Some((example_header().number, example_header().hash())), None); + assert_eq!( + verify_transaction_finalized(&storage, example_header_parent().hash(), 0, &vec![example_tx()],), + true, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_proof_with_missing_tx() { + custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { + let storage = BridgeStorage::::new(); + assert_eq!( + verify_transaction_finalized(&storage, example_header().hash(), 1, &vec![],), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_unknown_header() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let storage = BridgeStorage::::new(); + assert_eq!( + verify_transaction_finalized(&storage, example_header().hash(), 1, &vec![],), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_unfinalized_header() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let mut storage = BridgeStorage::::new(); + insert_header(&mut storage, example_header_parent()); + insert_header(&mut storage, example_header()); + assert_eq!( + verify_transaction_finalized(&storage, example_header().hash(), 0, &vec![example_tx()],), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_finalized_header_sibling() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let mut finalized_header_sibling = example_header(); + finalized_header_sibling.timestamp = 1; + let finalized_header_sibling_hash = finalized_header_sibling.hash(); + + let mut storage = BridgeStorage::::new(); + insert_header(&mut storage, example_header_parent()); + insert_header(&mut storage, example_header()); + insert_header(&mut storage, finalized_header_sibling); + storage.finalize_headers(Some((example_header().number, example_header().hash())), None); + assert_eq!( + verify_transaction_finalized(&storage, finalized_header_sibling_hash, 0, &vec![example_tx()],), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_finalized_header_uncle() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let mut finalized_header_uncle = example_header_parent(); + finalized_header_uncle.timestamp = 1; + let finalized_header_uncle_hash = finalized_header_uncle.hash(); + + let mut storage = BridgeStorage::::new(); + insert_header(&mut storage, example_header_parent()); + insert_header(&mut storage, finalized_header_uncle); + insert_header(&mut storage, example_header()); + storage.finalize_headers(Some((example_header().number, example_header().hash())), None); + assert_eq!( + verify_transaction_finalized(&storage, finalized_header_uncle_hash, 0, &vec![example_tx()],), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_invalid_proof() { + custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { + let storage = BridgeStorage::::new(); + assert_eq!( + verify_transaction_finalized(&storage, example_header().hash(), 0, &vec![example_tx(), example_tx(),],), + false, + ); + }); + } } diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 7a1fbb52f036b..8b1c5698fc742 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -129,7 +129,7 @@ impl<'a> Validators<'a> { } let receipts = receipts.ok_or(Error::MissingTransactionsReceipts)?; - if !header.check_transactions_receipts(&receipts) { + if !header.verify_receipts_root(&receipts) { return Err(Error::TransactionsReceiptsMismatch); } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 567d14f3b54a4..ca8d9af6d17f7 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -134,7 +134,7 @@ pub fn accept_aura_header_into_pool( // the heaviest, but rare operation - we do not want invalid receipts in the pool if let Some(receipts) = receipts { - if !header.check_transactions_receipts(receipts) { + if !header.verify_receipts_root(receipts) { return Err(Error::TransactionsReceiptsMismatch); } } diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml new file mode 100644 index 0000000000000..eec26b3797afc --- /dev/null +++ b/primitives/currency-exchange/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "sp-currency-exchange" +description = "Primitives of currency exchange module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } + +# Substrate Based Dependencies + +[dependencies.sp-std] +version = "2.0.0-rc1" +default-features = false +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.frame-support] +version = "2.0.0-rc1" +default-features = false +rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +git = "https://github.com/paritytech/substrate.git" + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-std/std", + "frame-support/std", +] diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs new file mode 100644 index 0000000000000..59e411c1bcfbb --- /dev/null +++ b/primitives/currency-exchange/src/lib.rs @@ -0,0 +1,127 @@ +// Copyright 2019-2020 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 . + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, EncodeLike}; +use frame_support::RuntimeDebug; +use sp_std::marker::PhantomData; + +/// All errors that may happen during exchange. +#[derive(RuntimeDebug, PartialEq)] +pub enum Error { + /// Invalid peer blockchain transaction provided. + InvalidTransaction, + /// Peer transaction has invalid amount. + InvalidAmount, + /// Peer transaction has invalid recipient. + InvalidRecipient, + /// Cannot map from peer recipient to this blockchain recipient. + FailedToMapRecipients, + /// Failed to convert from peer blockchain currency to this blockhain currency. + FailedToConvertCurrency, + /// Deposit has failed. + DepositFailed, +} + +/// Result of all exchange operations. +pub type Result = sp_std::result::Result; + +/// Peer blockchain lock funds transaction. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct LockFundsTransaction { + /// Something that uniquely identifies this transfer. + pub id: TransferId, + /// Funds recipient on the peer chain. + pub recipient: Recipient, + /// Amount of the locked funds. + pub amount: Amount, +} + +/// Peer blockchain transaction that may represent lock funds transaction. +pub trait MaybeLockFundsTransaction { + /// Transaction type. + type Transaction; + /// Identifier that uniquely identifies this transfer. + type Id: Decode + Encode + EncodeLike; + /// Peer recipient type. + type Recipient; + /// Peer currency amount type. + type Amount; + + /// Parse lock funds transaction of the peer blockchain. Returns None if + /// transaction format is unknown, or it isn't a lock funds transaction. + fn parse(tx: &Self::Transaction) -> Result>; +} + +/// Map that maps recipients from peer blockchain to this blockchain recipients. +pub trait RecipientsMap { + /// Peer blockchain recipient type. + type PeerRecipient; + /// Current blockchain recipient type. + type Recipient; + + /// Lookup current blockchain recipient by peer blockchain recipient. + fn map(peer_recipient: Self::PeerRecipient) -> Result; +} + +/// Conversion between two currencies. +pub trait CurrencyConverter { + /// Type of the source currency amount. + type SourceAmount; + /// Type of the target currency amount. + type TargetAmount; + + /// Covert from source to target currency. + fn convert(amount: Self::SourceAmount) -> Result; +} + +/// Currency deposit. +pub trait DepositInto { + /// Recipient type. + type Recipient; + /// Currency amount type. + type Amount; + + /// Grant some money to given account. + fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> Result<()>; +} + +/// Recipients map which is used when accounts ids are the same on both chains. +#[derive(Debug)] +pub struct IdentityRecipients(PhantomData); + +impl RecipientsMap for IdentityRecipients { + type PeerRecipient = AccountId; + type Recipient = AccountId; + + fn map(peer_recipient: Self::PeerRecipient) -> Result { + Ok(peer_recipient) + } +} + +/// Currency converter which is used when currency is the same on both chains. +#[derive(Debug)] +pub struct IdentityCurrencyConverter(PhantomData); + +impl CurrencyConverter for IdentityCurrencyConverter { + type SourceAmount = Amount; + type TargetAmount = Amount; + + fn convert(currency: Self::SourceAmount) -> Result { + Ok(currency) + } +} diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 32ac689bb9b8e..e6c3c6c04aa15 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -20,6 +20,9 @@ hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } +[dev-dependencies] +hex-literal = "0.2" + # Substrate Based Dependencies [dependencies.sp-api] version = "2.0.0-rc1" diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 662079c301f4a..969af63e1556f 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -43,6 +43,9 @@ impl_fixed_hash_rlp!(H520, 65); #[cfg(feature = "std")] impl_fixed_hash_serde!(H520, 65); +/// Raw (RLP-encoded) ethereum transaction. +pub type RawTransaction = Vec; + /// An ethereum address. pub type Address = H160; @@ -83,6 +86,21 @@ pub struct Header { pub seal: Vec, } +/// Parsed ethereum transaction. +#[derive(Debug, PartialEq)] +pub struct Transaction { + /// Sender address. + pub sender: Address, + /// Sender nonce. + pub nonce: U256, + /// Transaction destination address. None if it is contract creation transaction. + pub to: Option
, + /// Transaction value. + pub value: U256, + /// Transaction payload. + pub payload: Bytes, +} + /// Information describing execution of a transaction. #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] pub struct Receipt { @@ -143,23 +161,14 @@ impl Header { keccak_256(&self.rlp(true)).into() } - /// Check if passed transactions receipts are matching this header. - pub fn check_transactions_receipts(&self, receipts: &Vec) -> bool { - struct Keccak256Hasher; - - impl hash_db::Hasher for Keccak256Hasher { - type Out = H256; - type StdHasher = plain_hasher::PlainHasher; - const LENGTH: usize = 32; - fn hash(x: &[u8]) -> Self::Out { - keccak_256(x).into() - } - } + /// Check if passed transactions receipts are matching receipts root in this header. + pub fn verify_receipts_root(&self, receipts: &[Receipt]) -> bool { + verify_merkle_proof(self.receipts_root, receipts.iter().map(|r| r.rlp())) + } - let receipts = receipts.iter().map(|r| r.rlp()); - let actual_root = triehash::ordered_trie_root::(receipts); - let expected_root = self.receipts_root; - actual_root == expected_root + /// Check if passed transactions are matching transactions root in this header. + pub fn verify_transactions_root(&self, transactions: &[RawTransaction]) -> bool { + verify_merkle_proof(self.transactions_root, transactions.into_iter()) } /// Gets the seal hash of this header. @@ -335,6 +344,65 @@ impl std::fmt::Debug for Bloom { } } +/// Decode Ethereum transaction. +pub fn transaction_decode(raw_tx: &[u8]) -> Result { + // parse transaction fields + let tx_rlp = Rlp::new(raw_tx); + let nonce: U256 = tx_rlp.val_at(0)?; + let gas_price = tx_rlp.at(1)?; + let gas = tx_rlp.at(2)?; + let action = tx_rlp.at(3)?; + let to = match action.is_empty() { + false => Some(action.as_val()?), + true => None, + }; + let value: U256 = tx_rlp.val_at(4)?; + let payload: Bytes = tx_rlp.val_at(5)?; + let v: u64 = tx_rlp.val_at(6)?; + let r: U256 = tx_rlp.val_at(7)?; + let s: U256 = tx_rlp.val_at(8)?; + + // reconstruct signature + let mut signature = [0u8; 65]; + let (chain_id, v) = match v { + v if v == 27u64 => (None, 0), + v if v == 28u64 => (None, 1), + v if v >= 35u64 => (Some((v - 35) / 2), ((v - 1) % 2) as u8), + _ => (None, 4), + }; + r.to_big_endian(&mut signature[0..32]); + s.to_big_endian(&mut signature[32..64]); + signature[64] = v; + + // reconstruct message that has been signed + let mut message = RlpStream::new_list(if chain_id.is_some() { 9 } else { 6 }); + message.append(&nonce); + message.append_raw(gas_price.as_raw(), 1); + message.append_raw(gas.as_raw(), 1); + message.append_raw(action.as_raw(), 1); + message.append(&value); + message.append(&payload); + if let Some(chain_id) = chain_id { + message.append(&chain_id); + message.append(&0u8); + message.append(&0u8); + } + let message = keccak_256(&message.out()); + + // recover tx sender + let sender_public = sp_io::crypto::secp256k1_ecdsa_recover(&signature, &message) + .map_err(|_| rlp::DecoderError::Custom("Failed to recover transaction sender"))?; + let sender_address = public_to_address(&sender_public); + + Ok(Transaction { + sender: sender_address, + nonce, + to, + value, + payload, + }) +} + /// Convert public key into corresponding ethereum address. pub fn public_to_address(public: &[u8; 64]) -> Address { let hash = keccak_256(public); @@ -343,6 +411,27 @@ pub fn public_to_address(public: &[u8; 64]) -> Address { result } +/// Verify ethereum merkle proof. +fn verify_merkle_proof>(expected_root: H256, items: impl Iterator) -> bool { + compute_merkle_root(items) == expected_root +} + +/// Compute ethereum merkle root. +pub fn compute_merkle_root>(items: impl Iterator) -> H256 { + struct Keccak256Hasher; + + impl hash_db::Hasher for Keccak256Hasher { + type Out = H256; + type StdHasher = plain_hasher::PlainHasher; + const LENGTH: usize = 32; + fn hash(x: &[u8]) -> Self::Out { + keccak_256(x).into() + } + } + + triehash::ordered_trie_root::(items) +} + sp_api::decl_runtime_apis! { /// API for headers submitters. pub trait EthereumHeadersApi { @@ -358,3 +447,75 @@ sp_api::decl_runtime_apis! { fn is_known_block(hash: H256) -> bool; } } + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn transfer_transaction_decode_works() { + // value transfer transaction + // https://etherscan.io/tx/0xb9d4ad5408f53eac8627f9ccd840ba8fb3469d55cd9cc2a11c6e049f1eef4edd + // https://etherscan.io/getRawTx?tx=0xb9d4ad5408f53eac8627f9ccd840ba8fb3469d55cd9cc2a11c6e049f1eef4edd + let raw_tx = hex!("f86c0a85046c7cfe0083016dea94d1310c1e038bc12865d3d3997275b3e4737c6302880b503be34d9fe80080269fc7eaaa9c21f59adf8ad43ed66cf5ef9ee1c317bd4d32cd65401e7aaca47cfaa0387d79c65b90be6260d09dcfb780f29dd8133b9b1ceb20b83b7e442b4bfc30cb"); + assert_eq!( + transaction_decode(&raw_tx), + Ok(Transaction { + sender: hex!("67835910d32600471f388a137bbff3eb07993c04").into(), + nonce: 10.into(), + to: Some(hex!("d1310c1e038bc12865d3d3997275b3e4737c6302").into()), + value: 815217380000000000_u64.into(), + payload: Default::default(), + }), + ); + + // Kovan value transfer transaction + // https://kovan.etherscan.io/tx/0x3b4b7bd41c1178045ccb4753aa84c1ef9864b4d712fa308b228917cd837915da + // https://kovan.etherscan.io/getRawTx?tx=0x3b4b7bd41c1178045ccb4753aa84c1ef9864b4d712fa308b228917cd837915da + let raw_tx = hex!("f86a822816808252089470c1ccde719d6f477084f07e4137ab0e55f8369f8930cf46e92063afd8008078a00e4d1f4d8aa992bda3c105ff3d6e9b9acbfd99facea00985e2131029290adbdca028ea29a46a4b66ec65b454f0706228e3768cb0ecf755f67c50ddd472f11d5994"); + assert_eq!( + transaction_decode(&raw_tx), + Ok(Transaction { + sender: hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(), + nonce: 10262.into(), + to: Some(hex!("70c1ccde719d6f477084f07e4137ab0e55f8369f").into()), + value: 900379597077600000000_u128.into(), + payload: Default::default(), + }), + ); + } + + #[test] + fn payload_transaction_decode_works() { + // contract call transaction + // https://etherscan.io/tx/0xdc2b996b4d1d6922bf6dba063bfd70913279cb6170967c9bb80252aeb061cf65 + // https://etherscan.io/getRawTx?tx=0xdc2b996b4d1d6922bf6dba063bfd70913279cb6170967c9bb80252aeb061cf65 + let raw_tx = hex!("f8aa76850430e234008301500094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b4025a0964e023999621dc3d4d831c43c71f7555beb6d1192dee81a3674b3f57e310f21a00f229edd86f841d1ee4dc48cc16667e2283817b1d39bae16ced10cd206ae4fd4"); + assert_eq!( + transaction_decode(&raw_tx), + Ok(Transaction { + sender: hex!("2b9a4d37bdeecdf994c4c9ad7f3cf8dc632f7d70").into(), + nonce: 118.into(), + to: Some(hex!("dac17f958d2ee523a2206206994597c13d831ec7").into()), + value: 0.into(), + payload: hex!("a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b40").to_vec().into(), + }), + ); + + // Kovan contract call transaction + // https://kovan.etherscan.io/tx/0x2904b4451d23665492239016b78da052d40d55fdebc7304b38e53cf6a37322cf + // https://kovan.etherscan.io/getRawTx?tx=0x2904b4451d23665492239016b78da052d40d55fdebc7304b38e53cf6a37322cf + let raw_tx = hex!("f8ac8302200b843b9aca00830271009484dd11eb2a29615303d18149c0dbfa24167f896680b844a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b600000000000000000000000000000000000000000000000000000000000027101ba0ce126d2cca81f5e245f292ff84a0d915c0a4ac52af5c51219db1e5d36aa8da35a0045298b79dac631907403888f9b04c2ab5509fe0cc31785276d30a40b915fcf9"); + assert_eq!( + transaction_decode(&raw_tx), + Ok(Transaction { + sender: hex!("617da121abf03d4c1af572f5a4e313e26bef7bdc").into(), + nonce: 139275.into(), + to: Some(hex!("84dd11eb2a29615303d18149c0dbfa24167f8966").into()), + value: 0.into(), + payload: hex!("a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b60000000000000000000000000000000000000000000000000000000000002710").to_vec().into(), + }), + ); + } +} diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d3e6770fc5ca9..d1918fe8d7bd1 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" -ethereum-tx-sign = { git = "https://github.com/svyatonik/ethereum-tx-sign.git", branch = "up-ethereum-types" } +ethereum-tx-sign = "3.0" futures = "0.3.5" hex = "0.4" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } From 0cf3bf8da7427b2a49d907a8f6ecca72db91b95c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 5 Jun 2020 11:05:58 -0400 Subject: [PATCH 0065/1210] Provide overview about project components (#121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add descriptions for folder structure + node * Beef up descriptions of project components * Fix list formatting * Add note about nightly Rust * Update README.md Co-authored-by: Tomasz Drwięga * Update README.md Co-authored-by: Tomasz Drwięga * Reword Tomek's currency-exchange suggestion * Add link to Substrate's installation guide Co-authored-by: Tomasz Drwięga --- README.md | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf84414227822..2547ca8a4453d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,157 @@ This is a collection of components for building bridges. -The main components that will be constructed here will be bridge modules/runtimes -and bridge relays. +These components include runtime modules to help you construct your bridge's runtime, as well as +bridge relays for cross-chain communication. + +A bridge node is also available. The node can be used to run a test network which has support for bridging Ethereum +PoA chains to Substrate. We're working on expanding this functionality in the future. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 + +## Contents +- [Installation](#installation) +- [Project Layout](#project-layout) +- [Bridge Node Runtime](#bridge-node-runtime) +- [Ethereum Node](#ethereum-node) +- [Bridge Relay](#bridge-relay) +- [Running the Bridge](#running-the-bridge) + +## Installation +To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web +Assembly (WASM) runtime for the node. You can configure the WASM support as so: + +``` +rustup install nightly +rustup target add wasm32-unknown-unknown --toolchain nightly +``` + +Once this is configured you can build and test the repo as follows: + +``` +git clone https://github.com/paritytech/parity-bridges-common.git +cd parity-bridges-common +cargo build --all +cargo test --all +``` + +If you need more information about setting up your development environment Substrate's +[Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good +resource. + +## Project Layout +Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual +"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and +the `relays` which are used to pass messages between chains. + +``` +├── bin +│ └── node // Bridge ready chain implementation +├── modules // Runtime Modules +│ ├── ethereum // Manage Ethereum PoA chain info +│ ├── ethereum-contract // Ethereum built-in for validating Substrate block info +│ ├── currency-exchange // Cross-chain fund transfers +│ └── substrate // Manage Substrate chain info +├── primitives // Shared runtime and node code +│ └── ethereum-poa // Helpers for Ethereum PoA +├── relays // Cross-chain communication +│ ├── ethereum // Sync and communicate between Ethereum PoA + Substrate chains +│ └── substrate // 🚧 WIP 🚧 +``` + +## Bridge Node Runtime +The node runtime consists of several runtime modules, however not all of them are used at the same +time. When running an Ethereum PoA to Substrate bridge the modules required are the Ethereum module +and the currency exchange module. When running a Substrate to Substrate bridge the Substrate and +currency exchange modules are required. + +Below is a brief description of each of the runtime modules. + +### Ethereum Bridge Runtime Module +The main job of this runtime module is to keep track of useful information an Ethereum PoA chain +which has been submitted by a bridge relayer. This includes: + + - Ethereum headers and their status (e.g are they the best header, are they finalized, etc.) + - Current validator set, and upcoming validator sets + +This runtime module has more responsibilties than simply storing headers and validator sets. It is +able to perform checks on the incoming headers to verify their general integrity, as well as whether +or not they've been finalized by the authorities on the PoA chain. + +This module is laid out as so: + +``` +├── ethereum +│ └── src +│ ├── error.rs // Runtime error handling +│ ├── finality.rs // Manage finality operations +│ ├── import.rs // Import new Ethereum headers +│ ├── lib.rs // Store headers and validator set info +│ ├── validators.rs // Track current and future PoA validator sets +│ └── verification.rs // Verify validity of incoming Ethereum headers +``` + +### Currency Exchange Runtime Module +The currency exchange module is used to faciliate cross-chain funds transfers. It works by accepting +a transaction which proves that funds were locked on one chain, and releases a corresponding amount +of funds on the recieving chain. + +For example: Alice would like to send funds from chain A to chain B. What she would do is send a +transaction to chain A indicating that she would like to send funds to an address on chain B. This +transaction would contain the amount of funds she would like to send, as well as the address of the +recipient on chain B. These funds would now be locked on chain A. Once the block containing this +"locked-funds" transaction is finalized it can be relayed to chain B. Chain B will verify that this +transaction was included in a finalized block on chain A, and if successful deposit funds into the +recipient account on chain B. + +Chain B would need a way to convert from a foreign currency to its local currency. How this is done +is left to the runtime developer for chain B. + +This module is one example of how an on-chain light client can be used to prove a particular action +was taken on a foreign chain. In particular it enables transfers of the foreign chain's native +currency, but more sophisticated modules such as ERC20 token transfers or arbitrary message transfers +are being worked on as well. + +### Substrate Bridge Runtime Module +👷 Under Construction 👷‍♀️ + +## Ethereum Node +On the Ethereum side of things, we require two things. First, a Solidity smart contract to track the +Substrate headers which have been submitted to the bridge (by the relay), and a built-in contract to +be able to verify that headers have been finalized by the Grandpa finality gadget. Together this +allows the Ethereum PoA chain to verify the integrity and finality of incoming Substrate headers. + +The Solidity smart contract is not part of this repo, but can be found +[here](https://github.com/svyatonik/substrate-bridge-sol/blob/master/substrate-bridge.sol) if you're +curious. We have the contract ABI in the `ethereum/relays/res` directory. + +## Bridge Relay +The bridge relay is responsible for syncing the chains which are being bridged, and passing messages +between them. The current implementation of the relay supportings syncing and interacting with +Ethereum PoA and Substrate chains. + +The folder structure of the bridge relay is as follows: + +``` +├── relays +│ ├── ethereum +│ │ ├── res +│ │ │ └── ... +│ │ └── src +│ │ ├── ethereum_client.rs // Interface for Ethereum RPC +│ │ ├── ethereum_deploy_contract.rs // Utility for deploying bridge contract to Ethereum +│ │ ├── ethereum_sync_loop.rs // Sync headers from Ethereum, submit to Substrate +│ │ ├── ethereum_types.rs // Useful Ethereum types +│ │ ├── headers.rs // Track synced and incoming block headers +│ │ ├── main.rs // Entry point to binary +│ │ ├── substrate_client.rs // Interface for Substrate RPC +│ │ ├── substrate_sync_loop.rs // Sync headers from Substrate, submit to Ethereum +│ │ ├── substrate_types.rs // Useful Ethereum types +│ │ ├── sync.rs // Sync configuration and helpers +│ │ ├── sync_loop.rs // Header synchronization between source and target chains +│ │ ├── sync_types.rs // Useful sync types +│ │ └── utils.rs // General utilities +``` + +## Running the Bridge +👷 Under Construction 👷‍♀️ From 4debc85da78caff49db3bc5d82ec684b662f806a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2020 01:52:45 +0000 Subject: [PATCH 0066/1210] Bump jsonrpc-core from 14.1.0 to 14.2.0 (#124) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index a593d5ce9c167..2a9ff917aad27 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -12,7 +12,7 @@ name = "bridge-node" [dependencies] futures = "0.3.5" -jsonrpc-core = "14.1.0" +jsonrpc-core = "14.2.0" log = "0.4.8" structopt = "0.3.14" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } From f6e80c05bdb37c9e6da3cb51ce8a1b31ff953158 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2020 03:29:32 +0000 Subject: [PATCH 0067/1210] Bump async-trait from 0.1.31 to 0.1.33 (#125) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d1918fe8d7bd1..d5c97583bb7f2 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" ansi_term = "0.12" async-std = "=1.5.0" async-stream = "0.2.0" -async-trait = "0.1.31" +async-trait = "0.1.33" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" From 23744b31c01b8514eb88da76cb4640bf065e326f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 8 Jun 2020 04:29:23 +0000 Subject: [PATCH 0068/1210] Bump async-std from 1.5.0 to 1.6.0 (#126) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d5c97583bb7f2..6f2b60d497cb7 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] ansi_term = "0.12" -async-std = "=1.5.0" +async-std = "=1.6.0" async-stream = "0.2.0" async-trait = "0.1.33" clap = { version = "2.33.1", features = ["yaml"] } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 9cfeec36131e3..5a15daa4346f4 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -async-std = "=1.5.0" +async-std = "=1.6.0" clap = "2.33.1" ctrlc = "3.1.4" derive_more = "0.99.7" From 29595e7d7d7da571b6eee15a98504353c25b262c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 8 Jun 2020 11:40:57 +0200 Subject: [PATCH 0069/1210] Revert "Bump async-std from 1.5.0 to 1.6.0" (#127) * Revert "Bump async-std from 1.5.0 to 1.6.0 (#126)" This reverts commit 23744b31c01b8514eb88da76cb4640bf065e326f. * Add async-std=1.6 to ignore. --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 6f2b60d497cb7..d5c97583bb7f2 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] ansi_term = "0.12" -async-std = "=1.6.0" +async-std = "=1.5.0" async-stream = "0.2.0" async-trait = "0.1.33" clap = { version = "2.33.1", features = ["yaml"] } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 5a15daa4346f4..9cfeec36131e3 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -async-std = "=1.6.0" +async-std = "=1.5.0" clap = "2.33.1" ctrlc = "3.1.4" derive_more = "0.99.7" From 16d7240609903f2ec92dc86d545ea36201c3c963 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 10 Jun 2020 10:56:47 +0300 Subject: [PATCH 0070/1210] Finality votes cache (#116) * removeInMemoryStorage + extract Kovan stuff to runtime * removed comment from the future * remove redundant conversions * remove redundant `u8 as usize` * remove redundant `u8 as usize` * Update modules/ethereum/src/mock.rs Co-authored-by: Hernando Castano * use hex-literal in kovan config * cargo fmt --all * extracted insert_header * cargo fmt --all * finality cache * cargo fmt --all * cargo fmt --all * impl Default for FinalityVotes Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/node/runtime/src/lib.rs | 5 +- modules/ethereum/src/finality.rs | 445 ++++++++++++++++++++------- modules/ethereum/src/import.rs | 72 +++-- modules/ethereum/src/lib.rs | 341 +++++++++++++++----- modules/ethereum/src/mock.rs | 6 +- modules/ethereum/src/validators.rs | 124 +++++++- modules/ethereum/src/verification.rs | 80 ++--- primitives/ethereum-poa/src/lib.rs | 23 +- 8 files changed, 819 insertions(+), 277 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index eef870a3f58c3..2330e5c29f37d 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -216,12 +216,14 @@ impl pallet_aura::Trait for Runtime { } parameter_types! { + pub const FinalityVotesCachingInterval: Option = Some(16); pub const KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); pub const KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = kovan::kovan_validators_configuration(); } impl pallet_bridge_eth_poa::Trait for Runtime { type AuraConfiguration = KovanAuraConfiguration; + type FinalityVotesCachingInterval = FinalityVotesCachingInterval; type ValidatorsConfiguration = KovanValidatorsConfiguration; type OnHeadersSubmitted = (); } @@ -495,7 +497,8 @@ impl_runtime_apis! { impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { fn best_block() -> (u64, sp_bridge_eth_poa::H256) { - BridgeEthPoA::best_block() + let best_block = BridgeEthPoA::best_block(); + (best_block.number, best_block.hash) } fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 70d79fb20d08e..0fb5f1f777413 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -16,55 +16,108 @@ use crate::error::Error; use crate::Storage; -use primitives::{public_to_address, Address, Header, SealedEmptyStep, H256}; +use codec::{Decode, Encode}; +use primitives::{public_to_address, Address, Header, HeaderId, SealedEmptyStep, H256}; use sp_io::crypto::secp256k1_ecdsa_recover; -use sp_std::prelude::*; -use sp_std::{ - collections::{ - btree_map::{BTreeMap, Entry}, - btree_set::BTreeSet, - vec_deque::VecDeque, - }, - iter::from_fn, +use sp_runtime::RuntimeDebug; +use sp_std::collections::{ + btree_map::{BTreeMap, Entry}, + btree_set::BTreeSet, + vec_deque::VecDeque, }; +use sp_std::prelude::*; + +/// Cached finality votes for given block. +#[derive(RuntimeDebug, Default)] +#[cfg_attr(test, derive(PartialEq))] +pub struct CachedFinalityVotes { + /// Header ancestors that were read while we have been searching for + /// cached votes entry. Newest header has index 0. + pub unaccounted_ancestry: VecDeque<(HeaderId, Option, Header)>, + /// Cached finality votes, if they have been found. The associated + /// header is not included into `unaccounted_ancestry`. + pub votes: Option>, +} + +/// Finality effects. +#[derive(RuntimeDebug)] +#[cfg_attr(test, derive(PartialEq))] +pub struct FinalityEffects { + /// Finalized headers. + pub finalized_headers: Vec<(HeaderId, Option)>, + /// Finality votes used in computation. + pub votes: FinalityVotes, +} + +/// Finality votes for given block. +#[derive(RuntimeDebug, Decode, Encode)] +#[cfg_attr(test, derive(Clone, PartialEq))] +pub struct FinalityVotes { + /// Number of votes per each validator. + pub votes: BTreeMap, + /// Ancestry blocks with oldest ancestors at the beginning and newest at the + /// end of the queue. + pub ancestry: VecDeque>, +} + +/// Information about block ancestor that is used in computations. +#[derive(RuntimeDebug, Decode, Encode)] +#[cfg_attr(test, derive(Clone, Default, PartialEq))] +pub struct FinalityAncestor { + /// Bock id. + pub id: HeaderId, + /// Block submitter. + pub submitter: Option, + /// Validators that have signed this block and empty steps on top + /// of this block. + pub signers: BTreeSet
, +} /// Tries to finalize blocks when given block is imported. /// /// Returns numbers and hashes of finalized blocks in ascending order. pub fn finalize_blocks( storage: &S, - best_finalized_hash: &H256, - header_validators: (&H256, &[Address]), - hash: &H256, + best_finalized: HeaderId, + header_validators: (HeaderId, &[Address]), + id: HeaderId, submitter: Option<&S::Submitter>, header: &Header, two_thirds_majority_transition: u64, -) -> Result)>, Error> { +) -> Result, Error> { // compute count of voters for every unfinalized block in ancestry let validators = header_validators.1.iter().collect(); - let (mut votes, mut headers) = prepare_votes( - storage, - best_finalized_hash, - &header_validators.0, + let votes = prepare_votes( + storage.cached_finality_votes(&header.parent_hash, |hash| { + *hash == header_validators.0.hash || *hash == best_finalized.hash + }), + best_finalized.number, &validators, - hash, + id, header, - submitter, - two_thirds_majority_transition, + submitter.cloned(), )?; // now let's iterate in reverse order && find just finalized blocks - let mut newly_finalized = Vec::new(); - while let Some((oldest_hash, oldest_number, submitter, signers)) = headers.pop_front() { - if !is_finalized(&validators, &votes, oldest_number >= two_thirds_majority_transition) { + let mut finalized_headers = Vec::new(); + let mut current_votes = votes.votes.clone(); + for ancestor in &votes.ancestry { + if !is_finalized( + &validators, + ¤t_votes, + ancestor.id.number >= two_thirds_majority_transition, + ) { break; } - remove_signers_votes(&signers, &mut votes); - newly_finalized.push((oldest_number, oldest_hash, submitter)); + remove_signers_votes(&ancestor.signers, &mut current_votes); + finalized_headers.push((ancestor.id, ancestor.submitter.clone())); } - Ok(newly_finalized) + Ok(FinalityEffects { + finalized_headers, + votes, + }) } /// Returns true if there are enough votes to treat this header as finalized. @@ -78,67 +131,66 @@ fn is_finalized( } /// Prepare 'votes' of header and its ancestors' signers. -fn prepare_votes( - storage: &S, - best_finalized_hash: &H256, - validators_begin: &H256, +fn prepare_votes( + mut cached_votes: CachedFinalityVotes, + best_finalized_number: u64, validators: &BTreeSet<&Address>, - hash: &H256, + id: HeaderId, header: &Header, - submitter: Option<&S::Submitter>, - two_thirds_majority_transition: u64, -) -> Result< - ( - BTreeMap, - VecDeque<(H256, u64, Option, BTreeSet
)>, - ), - Error, -> { + submitter: Option, +) -> Result, Error> { // this fn can only work with single validators set if !validators.contains(&header.author) { return Err(Error::NotValidator); } - // prepare iterator of signers of all ancestors of the header - // we only take ancestors that are not yet pruned and those signed by - // the same set of validators - let mut parent_empty_step_signers = empty_steps_signers(header); - let ancestry = ancestry(storage, header.parent_hash) - .map(|(hash, header, submitter)| { - let mut signers = BTreeSet::new(); - sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); - signers.insert(header.author); - - let empty_step_signers = empty_steps_signers(&header); - let res = (hash, header.number, submitter, signers); - parent_empty_step_signers = empty_step_signers; - res - }) - .take_while(|&(hash, _, _, _)| hash != *validators_begin && hash != *best_finalized_hash); - - // now let's iterate built iterator and compute number of validators - // 'voted' for each header - // we stop when finalized block is met (because we only interested in - // just finalized blocks) - let mut votes = BTreeMap::new(); - let mut headers = VecDeque::new(); - for (hash, number, submitter, signers) in ancestry { - add_signers_votes(validators, &signers, &mut votes)?; - if is_finalized(validators, &votes, number >= two_thirds_majority_transition) { - remove_signers_votes(&signers, &mut votes); + // now we have votes that were valid when some block B has been inserted + // things may have changed a bit, but we do not need to read anything else + // from the db, because we have ancestry + // so the only thing we need to do is: + // 1) remove votes from blocks that have been finalized after B has been inserted; + // 2) add votes from B descendants + let mut votes = cached_votes.votes.unwrap_or_default(); + + // remove votes from finalized blocks + while let Some(old_ancestor) = votes.ancestry.pop_front() { + if old_ancestor.id.number > best_finalized_number { + votes.ancestry.push_front(old_ancestor); break; } - headers.push_front((hash, number, submitter, signers)); + remove_signers_votes(&old_ancestor.signers, &mut votes.votes); + } + + // add votes from new blocks + let mut parent_empty_step_signers = empty_steps_signers(header); + let mut unaccounted_ancestry = VecDeque::new(); + while let Some((ancestor_id, ancestor_submitter, ancestor)) = cached_votes.unaccounted_ancestry.pop_front() { + let mut signers = empty_steps_signers(&ancestor); + sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); + signers.insert(ancestor.author); + + add_signers_votes(validators, &signers, &mut votes.votes)?; + + unaccounted_ancestry.push_front(FinalityAncestor { + id: ancestor_id, + submitter: ancestor_submitter, + signers, + }); } + votes.ancestry.extend(unaccounted_ancestry); - // update votes with last header vote + // add votes from block itself let mut header_signers = BTreeSet::new(); header_signers.insert(header.author); - *votes.entry(header.author).or_insert(0) += 1; - headers.push_back((*hash, header.number, submitter.cloned(), header_signers)); + *votes.votes.entry(header.author).or_insert(0) += 1; + votes.ancestry.push_back(FinalityAncestor { + id, + submitter, + signers: header_signers, + }); - Ok((votes, headers)) + Ok(votes) } /// Increase count of 'votes' for every passed signer. @@ -193,28 +245,21 @@ fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option .map(|public| public_to_address(&public)) } -/// Return iterator of given header ancestors. -pub(crate) fn ancestry<'a, S: Storage>( - storage: &'a S, - mut parent_hash: H256, -) -> impl Iterator)> + 'a { - from_fn(move || { - let (header, submitter) = storage.header(&parent_hash)?; - if header.number == 0 { - return None; +impl Default for FinalityVotes { + fn default() -> Self { + FinalityVotes { + votes: BTreeMap::new(), + ancestry: VecDeque::new(), } - - let hash = parent_hash.clone(); - parent_hash = header.parent_hash.clone(); - Some((hash, header, submitter)) - }) + } } #[cfg(test)] mod tests { use super::*; - use crate::mock::{custom_test_ext, genesis, validator, validators_addresses, TestRuntime}; - use crate::{BridgeStorage, HeaderToImport}; + use crate::mock::{custom_test_ext, genesis, insert_header, validator, validators_addresses, TestRuntime}; + use crate::{BridgeStorage, FinalityCache, HeaderToImport}; + use frame_support::StorageMap; #[test] fn verifies_header_author() { @@ -222,9 +267,9 @@ mod tests { assert_eq!( finalize_blocks( &BridgeStorage::::new(), - &Default::default(), - (&Default::default(), &[]), - &Default::default(), + Default::default(), + (Default::default(), &[]), + Default::default(), None, &Header::default(), 0, @@ -235,7 +280,7 @@ mod tests { } #[test] - fn prepares_votes() { + fn finalize_blocks_works() { custom_test_ext(genesis(), validators_addresses(5)).execute_with(|| { // let's say we have 5 validators (we need 'votes' from 3 validators to achieve // finality) @@ -244,30 +289,32 @@ mod tests { // when header#1 is inserted, nothing is finalized (1 vote) let header1 = Header { author: validator(0).address().as_fixed_bytes().into(), - parent_hash: genesis().hash(), + parent_hash: genesis().compute_hash(), number: 1, ..Default::default() }; - let hash1 = header1.hash(); + let id1 = header1.compute_id(); let mut header_to_import = HeaderToImport { - context: storage.import_context(None, &genesis().hash()).unwrap(), + context: storage.import_context(None, &genesis().compute_hash()).unwrap(), is_best: true, - hash: hash1, + id: id1, header: header1, total_difficulty: 0.into(), enacted_change: None, scheduled_change: None, + finality_votes: Default::default(), }; assert_eq!( finalize_blocks( &storage, - &Default::default(), - (&Default::default(), &validators_addresses(5)), - &hash1, + Default::default(), + (Default::default(), &validators_addresses(5)), + id1, None, &header_to_import.header, u64::max_value(), - ), + ) + .map(|eff| eff.finalized_headers), Ok(Vec::new()), ); storage.insert_header(header_to_import.clone()); @@ -275,22 +322,23 @@ mod tests { // when header#2 is inserted, nothing is finalized (2 votes) header_to_import.header = Header { author: validator(1).address().as_fixed_bytes().into(), - parent_hash: hash1, + parent_hash: id1.hash, number: 2, ..Default::default() }; - header_to_import.hash = header_to_import.header.hash(); - let hash2 = header_to_import.header.hash(); + header_to_import.id = header_to_import.header.compute_id(); + let id2 = header_to_import.header.compute_id(); assert_eq!( finalize_blocks( &storage, - &Default::default(), - (&Default::default(), &validators_addresses(5)), - &hash2, + Default::default(), + (Default::default(), &validators_addresses(5)), + id2, None, &header_to_import.header, u64::max_value(), - ), + ) + .map(|eff| eff.finalized_headers), Ok(Vec::new()), ); storage.insert_header(header_to_import.clone()); @@ -298,25 +346,192 @@ mod tests { // when header#3 is inserted, header#1 is finalized (3 votes) header_to_import.header = Header { author: validator(2).address().as_fixed_bytes().into(), - parent_hash: hash2, + parent_hash: id2.hash, number: 3, ..Default::default() }; - header_to_import.hash = header_to_import.header.hash(); - let hash3 = header_to_import.header.hash(); + header_to_import.id = header_to_import.header.compute_id(); + let id3 = header_to_import.header.compute_id(); assert_eq!( finalize_blocks( &storage, - &Default::default(), - (&Default::default(), &validators_addresses(5)), - &hash3, + Default::default(), + (Default::default(), &validators_addresses(5)), + id3, None, &header_to_import.header, u64::max_value(), - ), - Ok(vec![(1, hash1, None)]), + ) + .map(|eff| eff.finalized_headers), + Ok(vec![(id1, None)]), ); storage.insert_header(header_to_import); }); } + + #[test] + fn cached_votes_are_updated_with_ancestry() { + // we're inserting header#5 + // cached votes are from header#3 + // header#4 has finalized header#1 and header#2 + // => when inserting header#5, we need to: + // 1) remove votes from header#1 and header#2 + // 2) add votes from header#4 and header#5 + let validators = validators_addresses(5); + let headers = (1..6) + .map(|number| Header { + number: number, + author: validators[number as usize - 1], + ..Default::default() + }) + .collect::>(); + let ancestry = headers + .iter() + .map(|header| FinalityAncestor { + id: header.compute_id(), + signers: vec![header.author].into_iter().collect(), + ..Default::default() + }) + .collect::>(); + let header5 = headers[4].clone(); + assert_eq!( + prepare_votes::<()>( + CachedFinalityVotes { + unaccounted_ancestry: vec![(headers[3].compute_id(), None, headers[3].clone()),] + .into_iter() + .collect(), + votes: Some(FinalityVotes { + votes: vec![(validators[0], 1), (validators[1], 1), (validators[2], 1),] + .into_iter() + .collect(), + ancestry: ancestry[..3].iter().cloned().collect(), + }), + }, + 2, + &validators.iter().collect(), + header5.compute_id(), + &header5, + None, + ) + .unwrap(), + FinalityVotes { + votes: vec![(validators[2], 1), (validators[3], 1), (validators[4], 1),] + .into_iter() + .collect(), + ancestry: ancestry[2..].iter().cloned().collect(), + }, + ); + } + + #[test] + fn prepare_votes_respects_finality_cache() { + let validators_addresses = validators_addresses(5); + custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { + // we need signatures of 3 validators to finalize block + let mut storage = BridgeStorage::::new(); + + // headers 1..3 are signed by validator#0 + // headers 4..6 are signed by validator#1 + // headers 7..9 are signed by validator#2 + let mut hashes = Vec::new(); + let mut headers = Vec::new(); + let mut ancestry = Vec::new(); + let mut parent_hash = genesis().compute_hash(); + for i in 1..10 { + let header = Header { + author: validator((i - 1) / 3).address().as_fixed_bytes().into(), + parent_hash, + number: i as _, + ..Default::default() + }; + let id = header.compute_id(); + insert_header(&mut storage, header.clone()); + hashes.push(id.hash); + ancestry.push(FinalityAncestor { + id: header.compute_id(), + submitter: None, + signers: vec![header.author].into_iter().collect(), + }); + headers.push(header); + parent_hash = id.hash; + } + + // when we're inserting header#7 and last finalized header is 0: + // check that votes at #7 are computed correctly without cache + let expected_votes_at_7 = FinalityVotes { + votes: vec![ + (validators_addresses[0].clone(), 3), + (validators_addresses[1].clone(), 3), + (validators_addresses[2].clone(), 1), + ] + .into_iter() + .collect(), + ancestry: ancestry[..7].iter().cloned().collect(), + }; + let id7 = headers[6].compute_id(); + assert_eq!( + prepare_votes( + storage.cached_finality_votes(&hashes.get(5).unwrap(), |_| false,), + 0, + &validators_addresses.iter().collect(), + id7, + headers.get(6).unwrap(), + None, + ) + .unwrap(), + expected_votes_at_7, + ); + + // cached votes at #5 + let expected_votes_at_5 = FinalityVotes { + votes: vec![ + (validators_addresses[0].clone(), 3), + (validators_addresses[1].clone(), 2), + ] + .into_iter() + .collect(), + ancestry: ancestry[..5].iter().cloned().collect(), + }; + FinalityCache::::insert(hashes[4], expected_votes_at_5); + + // when we're inserting header#7 and last finalized header is 0: + // check that votes at #7 are computed correctly with cache + assert_eq!( + prepare_votes( + storage.cached_finality_votes(&hashes.get(5).unwrap(), |_| false,), + 0, + &validators_addresses.iter().collect(), + id7, + headers.get(6).unwrap(), + None, + ) + .unwrap(), + expected_votes_at_7, + ); + + // when we're inserting header#7 and last finalized header is 3: + // check that votes at #7 are computed correctly with cache + let expected_votes_at_7 = FinalityVotes { + votes: vec![ + (validators_addresses[1].clone(), 3), + (validators_addresses[2].clone(), 1), + ] + .into_iter() + .collect(), + ancestry: ancestry[3..7].iter().cloned().collect(), + }; + assert_eq!( + prepare_votes( + storage.cached_finality_votes(&hashes.get(5).unwrap(), |hash| *hash == hashes[2],), + 3, + &validators_addresses.iter().collect(), + id7, + headers.get(6).unwrap(), + None, + ) + .unwrap(), + expected_votes_at_7, + ); + }); + } } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 87025e543fa97..a59bfc750b4a8 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -19,7 +19,7 @@ use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::{is_importable_header, verify_aura_header}; use crate::{AuraConfiguration, ChangeToEnact, Storage}; -use primitives::{Header, Receipt, H256}; +use primitives::{Header, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// Maximal number of headers behind best blocks that we are aiming to store. When there @@ -64,7 +64,7 @@ pub fn import_headers( match import_result { Ok((_, finalized)) => { - for (_, _, submitter) in finalized { + for (_, submitter) in finalized { if let Some(submitter) = submitter { *finalized_headers.entry(submitter).or_default() += 1; } @@ -84,7 +84,7 @@ pub fn import_headers( /// Transactions receipts must be provided if `header_import_requires_receipts()` /// has returned true. /// -/// Returns imported block hash. +/// Returns imported block id and list of all finalized headers. pub fn import_header( storage: &mut S, aura_config: &AuraConfiguration, @@ -93,9 +93,9 @@ pub fn import_header( submitter: Option, header: Header, receipts: Option>, -) -> Result<(H256, Vec<(u64, H256, Option)>), Error> { +) -> Result<(HeaderId, Vec<(HeaderId, Option)>), Error> { // first check that we are able to import this header at all - let (hash, prev_finalized_hash) = is_importable_header(storage, &header)?; + let (header_id, finalized_id) = is_importable_header(storage, &header)?; // verify header let import_context = verify_aura_header(storage, aura_config, submitter, &header)?; @@ -108,9 +108,9 @@ pub fn import_header( let validators_set = import_context.validators_set(); let finalized_blocks = finalize_blocks( storage, - &prev_finalized_hash, - (&validators_set.enact_block, &validators_set.validators), - &hash, + finalized_id, + (validators_set.enact_block, &validators_set.validators), + header_id, import_context.submitter(), &header, aura_config.two_thirds_majority_transition, @@ -120,35 +120,36 @@ pub fn import_header( signal_block: None, validators, }) - .or_else(|| validators.finalize_validators_change(storage, &finalized_blocks)); + .or_else(|| validators.finalize_validators_change(storage, &finalized_blocks.finalized_headers)); // NOTE: we can't return Err() from anywhere below this line // (because otherwise we'll have inconsistent storage if transaction will fail) // and finally insert the block - let (_, _, best_total_difficulty) = storage.best_block(); + let (_, best_total_difficulty) = storage.best_block(); let total_difficulty = import_context.total_difficulty() + header.difficulty; let is_best = total_difficulty > best_total_difficulty; let header_number = header.number; storage.insert_header(import_context.into_import_header( is_best, - hash, + header_id, header, total_difficulty, enacted_change, scheduled_change, + finalized_blocks.votes, )); // now mark finalized headers && prune old headers storage.finalize_headers( - finalized_blocks.last().map(|(number, hash, _)| (*number, *hash)), + finalized_blocks.finalized_headers.last().map(|(id, _)| *id), match is_best { true => header_number.checked_sub(prune_depth), false => None, }, ); - Ok((hash, finalized_blocks)) + Ok((header_id, finalized_blocks.finalized_headers)) } /// Returns true if transactions receipts are required to import given header. @@ -178,7 +179,13 @@ mod tests { fn rejects_finalized_block_competitors() { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let mut storage = BridgeStorage::::new(); - storage.finalize_headers(Some((100, Default::default())), None); + storage.finalize_headers( + Some(HeaderId { + number: 100, + ..Default::default() + }), + None, + ); assert_eq!( import_header( &mut storage, @@ -239,7 +246,7 @@ mod tests { let validators = validators(3); let mut storage = BridgeStorage::::new(); let header = block_i(1, &validators); - let hash = header.hash(); + let hash = header.compute_hash(); assert_eq!( import_header( &mut storage, @@ -273,10 +280,10 @@ mod tests { // header [0..11] are finalizing blocks [0; 9] // => since we want to keep 10 finalized blocks, we aren't pruning anything - let mut latest_block_hash = Default::default(); + let mut latest_block_id = Default::default(); for i in 1..11 { let header = block_i(i, &validators); - let (rolling_last_block_hash, finalized_blocks) = import_header( + let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, &test_aura_config(), &validators_config, @@ -289,15 +296,15 @@ mod tests { match i { 2..=10 => assert_eq!( finalized_blocks, - vec![(i - 1, block_i(i - 1, &validators).hash(), Some(100))], + vec![(block_i(i - 1, &validators).compute_id(), Some(100))], "At {}", i, ), _ => assert_eq!(finalized_blocks, vec![], "At {}", i), } - latest_block_hash = rolling_last_block_hash; + latest_block_id = rolling_last_block_id; } - assert!(storage.header(&genesis().hash()).is_some()); + assert!(storage.header(&genesis().compute_hash()).is_some()); // header 11 finalizes headers [10] AND schedules change // => we prune header#0 @@ -307,7 +314,7 @@ mod tests { .parse() .unwrap(); }); - let (rolling_last_block_hash, finalized_blocks) = import_header( + let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, &test_aura_config(), &validators_config, @@ -315,23 +322,26 @@ mod tests { Some(101), header11.clone(), Some(vec![crate::validators::tests::validators_change_recept( - latest_block_hash, + latest_block_id.hash, )]), ) .unwrap(); - assert_eq!(finalized_blocks, vec![(10, block_i(10, &validators).hash(), Some(100))],); - assert!(storage.header(&genesis().hash()).is_none()); - latest_block_hash = rolling_last_block_hash; + assert_eq!( + finalized_blocks, + vec![(block_i(10, &validators).compute_id(), Some(100))], + ); + assert!(storage.header(&genesis().compute_hash()).is_none()); + latest_block_id = rolling_last_block_id; // and now let's say validators 1 && 2 went offline // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers // until header#11 is met. we can't prune #11, because it schedules change let mut step = 56; - let mut expected_blocks = vec![(11, header11.hash(), Some(101))]; + let mut expected_blocks = vec![(header11.compute_id(), Some(101))]; for i in 12..25 { let header = Header { number: i as _, - parent_hash: latest_block_hash, + parent_hash: latest_block_id.hash, gas_limit: 0x2000.into(), author: validator(2).address(), seal: vec![vec![step].into(), vec![].into()], @@ -339,8 +349,8 @@ mod tests { ..Default::default() }; let header = signed_header(&validators, header, step as _); - expected_blocks.push((i, header.hash(), Some(102))); - let (rolling_last_block_hash, finalized_blocks) = import_header( + expected_blocks.push((header.compute_id(), Some(102))); + let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, &test_aura_config(), &validators_config, @@ -351,7 +361,7 @@ mod tests { ) .unwrap(); assert_eq!(finalized_blocks, vec![],); - latest_block_hash = rolling_last_block_hash; + latest_block_id = rolling_last_block_id; step += 3; } assert_eq!( @@ -367,7 +377,7 @@ mod tests { step -= 2; let header = Header { number: 25, - parent_hash: latest_block_hash, + parent_hash: latest_block_id.hash, gas_limit: 0x2000.into(), author: validator(0).address(), seal: vec![vec![step].into(), vec![].into()], diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 3f662547d19db..8b927bd54ef29 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -16,9 +16,10 @@ #![cfg_attr(not(feature = "std"), no_std)] +use crate::finality::{CachedFinalityVotes, FinalityVotes}; use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage, traits::Get}; -use primitives::{Address, Header, RawTransaction, Receipt, H256, U256}; +use primitives::{Address, Header, HeaderId, RawTransaction, Receipt, H256, U256}; use sp_runtime::{ transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity, @@ -93,7 +94,7 @@ pub struct StoredHeader { /// Hash of the last block which has **SCHEDULED** validators set change. /// Note that signal doesn't mean that the set has been (or ever will be) enacted. /// Note that the header may already be pruned. - pub last_signal_block: Option, + pub last_signal_block: Option, } /// Validators set as it is stored in the runtime storage. @@ -103,9 +104,9 @@ pub struct ValidatorsSet { /// Validators of this set. pub validators: Vec
, /// Hash of the block where this set has been signalled. None if this is the first set. - pub signal_block: Option, + pub signal_block: Option, /// Hash of the block where this set has been enacted. - pub enact_block: H256, + pub enact_block: HeaderId, } /// Validators set change as it is stored in the runtime storage. @@ -115,7 +116,7 @@ pub struct ScheduledChange { /// Validators of this set. pub validators: Vec
, /// Hash of the block which has emitted previous validators change signal. - pub prev_signal_block: Option, + pub prev_signal_block: Option, } /// Header that we're importing. @@ -126,8 +127,8 @@ pub struct HeaderToImport { pub context: ImportContext, /// Should we consider this header as best? pub is_best: bool, - /// The hash of the header. - pub hash: H256, + /// The id of the header. + pub id: HeaderId, /// The header itself. pub header: Header, /// Total chain difficulty at the header. @@ -137,15 +138,17 @@ pub struct HeaderToImport { pub enacted_change: Option, /// Validators set scheduled change, if happened at the header. pub scheduled_change: Option>, + /// Finality votes at this header. + pub finality_votes: FinalityVotes, } /// Header that we're importing. #[derive(RuntimeDebug)] #[cfg_attr(test, derive(Clone, PartialEq))] pub struct ChangeToEnact { - /// The hash of the header where change has been scheduled. + /// The id of the header where change has been scheduled. /// None if it is a first set within current `ValidatorsSource`. - pub signal_block: Option, + pub signal_block: Option, /// Validators set that is enacted. pub validators: Vec
, } @@ -179,7 +182,7 @@ pub struct ImportContext { parent_scheduled_change: Option, validators_set_id: u64, validators_set: ValidatorsSet, - last_signal_block: Option, + last_signal_block: Option, } impl ImportContext { @@ -215,10 +218,13 @@ impl ImportContext { /// Returns reference to the latest block which has signalled change of validators set. /// This may point to parent if parent has signalled change. - pub fn last_signal_block(&self) -> Option<&H256> { + pub fn last_signal_block(&self) -> Option { match self.parent_scheduled_change { - Some(_) => Some(&self.parent_hash), - None => self.last_signal_block.as_ref(), + Some(_) => Some(HeaderId { + number: self.parent_header.number, + hash: self.parent_hash, + }), + None => self.last_signal_block, } } @@ -226,20 +232,22 @@ impl ImportContext { pub fn into_import_header( self, is_best: bool, - hash: H256, + id: HeaderId, header: Header, total_difficulty: U256, enacted_change: Option, scheduled_change: Option>, + finality_votes: FinalityVotes, ) -> HeaderToImport { HeaderToImport { context: self, is_best, - hash, + id, header, total_difficulty, enacted_change, scheduled_change, + finality_votes, } } } @@ -251,14 +259,22 @@ pub trait Storage { /// Header submitter identifier. type Submitter: Clone + Ord; - /// Get best known block. - fn best_block(&self) -> (u64, H256, U256); + /// Get best known block and total chain difficulty. + fn best_block(&self) -> (HeaderId, U256); /// Get last finalized block. - fn finalized_block(&self) -> (u64, H256); + fn finalized_block(&self) -> HeaderId; /// Get imported header by its hash. /// /// Returns header and its submitter (if known). fn header(&self, hash: &H256) -> Option<(Header, Option)>; + /// Returns latest cached finality votes (if any) for block ancestors, starting + /// from `parent_hash` block and stopping at genesis block, or block where `stop_at` + /// returns true. + fn cached_finality_votes( + &self, + parent_hash: &H256, + stop_at: impl Fn(&H256) -> bool, + ) -> CachedFinalityVotes; /// Get header import context by parent header hash. fn import_context( &self, @@ -275,7 +291,7 @@ pub trait Storage { /// It is the storage duty to ensure that unfinalized headers that have /// scheduled changes won't be pruned until they or their competitors /// are finalized. - fn finalize_headers(&mut self, finalized: Option<(u64, H256)>, prune_end: Option); + fn finalize_headers(&mut self, finalized: Option, prune_end: Option); } /// Decides whether the session should be ended. @@ -302,10 +318,17 @@ impl OnHeadersSubmitted for () { fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {} } -/// The module configuration trait +/// The module configuration trait. pub trait Trait: frame_system::Trait { /// Aura configuration. type AuraConfiguration: Get; + /// Interval (in blocks) for for finality votes caching. + /// If None, cache is disabled. + /// + /// Ideally, this should either be None (when we are sure that there won't + /// be any significant finalization delays), or something that is bit larger + /// than average finalization delay. + type FinalityVotesCachingInterval: Get>; /// Validators configuration. type ValidatorsConfiguration: Get; /// Handler for headers submission result. @@ -377,15 +400,17 @@ decl_module! { decl_storage! { trait Store for Module as Bridge { /// Best known block. - BestBlock: (u64, H256, U256); + BestBlock: (HeaderId, U256); /// Best finalized block. - FinalizedBlock: (u64, H256); + FinalizedBlock: HeaderId; /// Range of blocks that we want to prune. BlocksToPrune: PruningRange; /// Map of imported headers by hash. Headers: map hasher(identity) H256 => Option>; /// Map of imported header hashes by number. HeadersByNumber: map hasher(blake2_128_concat) u64 => Option>; + /// Map of cached finality data by header hash. + FinalityCache: map hasher(identity) H256 => Option>; /// The ID of next validator set. NextValidatorsSetId: u64; /// Map of validators sets by their id. @@ -412,9 +437,13 @@ decl_storage! { "Initial validators set can't be empty", ); - let initial_hash = config.initial_header.hash(); - BestBlock::put((config.initial_header.number, initial_hash, config.initial_difficulty)); - FinalizedBlock::put((config.initial_header.number, initial_hash)); + let initial_hash = config.initial_header.compute_hash(); + let initial_id = HeaderId { + number: config.initial_header.number, + hash: initial_hash, + }; + BestBlock::put((initial_id, config.initial_difficulty)); + FinalizedBlock::put(initial_id); BlocksToPrune::put(PruningRange { oldest_unpruned_block: config.initial_header.number, oldest_block_to_keep: config.initial_header.number, @@ -431,7 +460,7 @@ decl_storage! { ValidatorsSets::insert(0, ValidatorsSet { validators: config.initial_validators.clone(), signal_block: None, - enact_block: initial_hash, + enact_block: initial_id, }); ValidatorsSetsRc::insert(0, 1); }) @@ -442,9 +471,8 @@ impl Module { /// Returns number and hash of the best block known to the bridge module. /// The caller should only submit `import_header` transaction that makes /// (or leads to making) other header the best one. - pub fn best_block() -> (u64, H256) { - let (number, hash, _) = BridgeStorage::::new().best_block(); - (number, hash) + pub fn best_block() -> HeaderId { + BridgeStorage::::new().best_block().0 } /// Returns true if the import of given block requires transactions receipts. @@ -580,6 +608,7 @@ impl BridgeStorage { while let Some(hash) = blocks_at_number.pop() { let header = Headers::::take(&hash); ScheduledChanges::remove(hash); + FinalityCache::::remove(hash); if let Some(header) = header { ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { Some(rc) if rc > 1 => Some(rc - 1), @@ -599,11 +628,11 @@ impl BridgeStorage { impl Storage for BridgeStorage { type Submitter = T::AccountId; - fn best_block(&self) -> (u64, H256, U256) { + fn best_block(&self) -> (HeaderId, U256) { BestBlock::get() } - fn finalized_block(&self) -> (u64, H256) { + fn finalized_block(&self) -> HeaderId { FinalizedBlock::get() } @@ -611,6 +640,41 @@ impl Storage for BridgeStorage { Headers::::get(hash).map(|header| (header.header, header.submitter)) } + fn cached_finality_votes( + &self, + parent_hash: &H256, + stop_at: impl Fn(&H256) -> bool, + ) -> CachedFinalityVotes { + let mut votes = CachedFinalityVotes::default(); + let mut current_hash = *parent_hash; + loop { + if stop_at(¤t_hash) { + return votes; + } + + let cached_votes = FinalityCache::::get(¤t_hash); + if let Some(cached_votes) = cached_votes { + votes.votes = Some(cached_votes); + return votes; + } + + let header = match Headers::::get(¤t_hash) { + Some(header) if header.header.number != 0 => header, + _ => return votes, + }; + let parent_hash = header.header.parent_hash; + let current_id = HeaderId { + number: header.header.number, + hash: current_hash, + }; + votes + .unaccounted_ancestry + .push_back((current_id, header.submitter, header.header)); + + current_hash = parent_hash; + } + } + fn import_context( &self, submitter: Option, @@ -639,11 +703,11 @@ impl Storage for BridgeStorage { fn insert_header(&mut self, header: HeaderToImport) { if header.is_best { - BestBlock::put((header.header.number, header.hash, header.total_difficulty)); + BestBlock::put((header.id, header.total_difficulty)); } if let Some(scheduled_change) = header.scheduled_change { ScheduledChanges::insert( - &header.hash, + &header.id.hash, ScheduledChange { validators: scheduled_change, prev_signal_block: header.context.last_signal_block, @@ -661,7 +725,7 @@ impl Storage for BridgeStorage { next_validators_set_id, ValidatorsSet { validators: enacted_change.validators, - enact_block: header.hash, + enact_block: header.id, signal_block: enacted_change.signal_block, }, ); @@ -677,17 +741,25 @@ impl Storage for BridgeStorage { } }; + let finality_votes_caching_interval = T::FinalityVotesCachingInterval::get(); + if let Some(finality_votes_caching_interval) = finality_votes_caching_interval { + let cache_entry_required = header.id.number != 0 && header.id.number % finality_votes_caching_interval == 0; + if cache_entry_required { + FinalityCache::::insert(header.id.hash, header.finality_votes); + } + } + frame_support::debug::trace!( target: "runtime", "Inserting PoA header: ({}, {})", header.header.number, - header.hash, + header.id.hash, ); - let last_signal_block = header.context.last_signal_block().cloned(); - HeadersByNumber::append(header.header.number, header.hash); + let last_signal_block = header.context.last_signal_block(); + HeadersByNumber::append(header.id.number, header.id.hash); Headers::::insert( - &header.hash, + &header.id.hash, StoredHeader { submitter: header.context.submitter, header: header.header, @@ -698,18 +770,18 @@ impl Storage for BridgeStorage { ); } - fn finalize_headers(&mut self, finalized: Option<(u64, H256)>, prune_end: Option) { + fn finalize_headers(&mut self, finalized: Option, prune_end: Option) { // remember just finalized block let finalized_number = finalized .as_ref() - .map(|f| f.0) - .unwrap_or_else(|| FinalizedBlock::get().0); + .map(|f| f.number) + .unwrap_or_else(|| FinalizedBlock::get().number); if let Some(finalized) = finalized { frame_support::debug::trace!( target: "runtime", "Finalizing PoA header: ({}, {})", - finalized.0, - finalized.1, + finalized.number, + finalized.hash, ); FinalizedBlock::put(finalized); @@ -735,21 +807,21 @@ pub fn verify_transaction_finalized( Some((header, _)) => header, None => return false, }; - let (finalized_number, finalized_hash) = storage.finalized_block(); + let finalized = storage.finalized_block(); // if header is not yet finalized => return - if header.number > finalized_number { + if header.number > finalized.number { return false; } // check if header is actually finalized - let is_finalized = match header.number < finalized_number { - true => finality::ancestry(storage, finalized_hash) - .skip_while(|(_, ancestor, _)| ancestor.number > header.number) - .filter(|&(ancestor_hash, _, _)| ancestor_hash == block) + let is_finalized = match header.number < finalized.number { + true => ancestry(storage, finalized.hash) + .skip_while(|(_, ancestor)| ancestor.number > header.number) + .filter(|&(ancestor_hash, _)| ancestor_hash == block) .next() .is_some(), - false => block == finalized_hash, + false => block == finalized.hash, }; if !is_finalized { return false; @@ -765,14 +837,49 @@ fn pool_configuration() -> PoolConfiguration { } } +/// Return iterator of given header ancestors. +fn ancestry<'a, S: Storage>(storage: &'a S, mut parent_hash: H256) -> impl Iterator + 'a { + sp_std::iter::from_fn(move || { + let (header, _) = storage.header(&parent_hash)?; + if header.number == 0 { + return None; + } + + let hash = parent_hash; + parent_hash = header.parent_hash; + Some((hash, header)) + }) +} + #[cfg(test)] pub(crate) mod tests { use super::*; + use crate::finality::FinalityAncestor; use crate::mock::{ - custom_block_i, custom_test_ext, genesis, insert_header, validators, validators_addresses, TestRuntime, + block_i, custom_block_i, custom_test_ext, genesis, insert_header, validators, validators_addresses, TestRuntime, }; use primitives::compute_merkle_root; + fn example_tx() -> Vec { + vec![42] + } + + fn example_header() -> Header { + let mut header = Header::default(); + header.number = 2; + header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.parent_hash = example_header_parent().compute_hash(); + header + } + + fn example_header_parent() -> Header { + let mut header = Header::default(); + header.number = 1; + header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.parent_hash = genesis().compute_hash(); + header + } + fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let validators = validators(3); @@ -782,7 +889,7 @@ pub(crate) mod tests { let header = custom_block_i(i, &validators, |header| { header.gas_limit = header.gas_limit + U256::from(j); }); - let hash = header.hash(); + let hash = header.compute_hash(); headers_by_number.push(hash); Headers::::insert( hash, @@ -935,24 +1042,97 @@ pub(crate) mod tests { }); } - fn example_tx() -> Vec { - vec![42] - } + #[test] + fn finality_votes_are_cached() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let mut storage = BridgeStorage::::new(); + let interval = ::FinalityVotesCachingInterval::get().unwrap(); - fn example_header() -> Header { - let mut header = Header::default(); - header.number = 2; - header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); - header.parent_hash = example_header_parent().hash(); - header + // for all headers with number < interval, cache entry is not created + let validators = validators(3); + for i in 1..interval { + let header = block_i(i, &validators); + let id = header.compute_id(); + insert_header(&mut storage, header); + assert_eq!(FinalityCache::::get(&id.hash), None); + } + + // for header with number = interval, cache entry is created + let header_with_entry = block_i(interval, &validators); + let header_with_entry_hash = header_with_entry.compute_hash(); + insert_header(&mut storage, header_with_entry); + assert_eq!( + FinalityCache::::get(&header_with_entry_hash), + Some(Default::default()), + ); + + // when we later prune this header, cache entry is removed + BlocksToPrune::put(PruningRange { + oldest_unpruned_block: interval - 1, + oldest_block_to_keep: interval - 1, + }); + storage.finalize_headers(None, Some(interval + 1)); + assert_eq!(FinalityCache::::get(&header_with_entry_hash), None); + }); } - fn example_header_parent() -> Header { - let mut header = Header::default(); - header.number = 1; - header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); - header.parent_hash = genesis().hash(); - header + #[test] + fn cached_finality_votes_finds_entry() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + // insert 5 headers + let validators = validators(3); + let mut storage = BridgeStorage::::new(); + let mut headers = Vec::new(); + for i in 1..5 { + let header = block_i(i, &validators); + headers.push(header.clone()); + insert_header(&mut storage, header); + } + + // when inserting header#6, entry isn't found + let hash5 = headers.last().unwrap().compute_hash(); + assert_eq!( + storage.cached_finality_votes(&hash5, |_| false), + CachedFinalityVotes { + unaccounted_ancestry: headers + .iter() + .map(|header| (header.compute_id(), None, header.clone(),)) + .rev() + .collect(), + votes: None, + }, + ); + + // let's now create entry at #3 + let hash3 = headers[2].compute_hash(); + let votes_at_3 = FinalityVotes { + votes: vec![([42; 20].into(), 21)].into_iter().collect(), + ancestry: vec![FinalityAncestor { + id: HeaderId { + number: 100, + hash: Default::default(), + }, + ..Default::default() + }] + .into_iter() + .collect(), + }; + FinalityCache::::insert(hash3, votes_at_3.clone()); + + // searching at #6 again => entry is found + assert_eq!( + storage.cached_finality_votes(&hash5, |_| false), + CachedFinalityVotes { + unaccounted_ancestry: headers + .iter() + .skip(3) + .map(|header| (header.compute_id(), None, header.clone(),)) + .rev() + .collect(), + votes: Some(votes_at_3), + }, + ); + }); } #[test] @@ -960,7 +1140,7 @@ pub(crate) mod tests { custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().hash(), 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &vec![example_tx()],), true, ); }); @@ -972,9 +1152,9 @@ pub(crate) mod tests { let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); - storage.finalize_headers(Some((example_header().number, example_header().hash())), None); + storage.finalize_headers(Some(example_header().compute_id()), None); assert_eq!( - verify_transaction_finalized(&storage, example_header_parent().hash(), 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, example_header_parent().compute_hash(), 0, &vec![example_tx()],), true, ); }); @@ -985,7 +1165,7 @@ pub(crate) mod tests { custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().hash(), 1, &vec![],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &vec![],), false, ); }); @@ -996,7 +1176,7 @@ pub(crate) mod tests { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().hash(), 1, &vec![],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &vec![],), false, ); }); @@ -1009,7 +1189,7 @@ pub(crate) mod tests { insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); assert_eq!( - verify_transaction_finalized(&storage, example_header().hash(), 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &vec![example_tx()],), false, ); }); @@ -1020,13 +1200,13 @@ pub(crate) mod tests { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let mut finalized_header_sibling = example_header(); finalized_header_sibling.timestamp = 1; - let finalized_header_sibling_hash = finalized_header_sibling.hash(); + let finalized_header_sibling_hash = finalized_header_sibling.compute_hash(); let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); insert_header(&mut storage, finalized_header_sibling); - storage.finalize_headers(Some((example_header().number, example_header().hash())), None); + storage.finalize_headers(Some(example_header().compute_id()), None); assert_eq!( verify_transaction_finalized(&storage, finalized_header_sibling_hash, 0, &vec![example_tx()],), false, @@ -1039,13 +1219,13 @@ pub(crate) mod tests { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let mut finalized_header_uncle = example_header_parent(); finalized_header_uncle.timestamp = 1; - let finalized_header_uncle_hash = finalized_header_uncle.hash(); + let finalized_header_uncle_hash = finalized_header_uncle.compute_hash(); let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, finalized_header_uncle); insert_header(&mut storage, example_header()); - storage.finalize_headers(Some((example_header().number, example_header().hash())), None); + storage.finalize_headers(Some(example_header().compute_id()), None); assert_eq!( verify_transaction_finalized(&storage, finalized_header_uncle_hash, 0, &vec![example_tx()],), false, @@ -1058,7 +1238,12 @@ pub(crate) mod tests { custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().hash(), 0, &vec![example_tx(), example_tx(),],), + verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &vec![example_tx(), example_tx(),], + ), false, ); }); diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 44213813fe3ce..a4f9e0fe4bbfc 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::finality::FinalityVotes; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, HeadersByNumber, Storage, Trait}; use frame_support::StorageMap; @@ -70,12 +71,14 @@ impl frame_system::Trait for TestRuntime { } parameter_types! { + pub const TestFinalityVotesCachingInterval: Option = Some(16); pub const TestAuraConfiguration: AuraConfiguration = test_aura_config(); pub const TestValidatorsConfiguration: ValidatorsConfiguration = test_validators_config(); } impl Trait for TestRuntime { type AuraConfiguration = TestAuraConfiguration; + type FinalityVotesCachingInterval = TestFinalityVotesCachingInterval; type ValidatorsConfiguration = TestValidatorsConfiguration; type OnHeadersSubmitted = (); } @@ -171,10 +174,11 @@ pub fn insert_header(storage: &mut S, header: Header) { storage.insert_header(HeaderToImport { context: storage.import_context(None, &header.parent_hash).unwrap(), is_best: true, - hash: header.hash(), + id: header.compute_id(), header, total_difficulty: 0.into(), enacted_change: None, scheduled_change: None, + finality_votes: FinalityVotes::default(), }); } diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 8b1c5698fc742..70aa246c90e56 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -16,7 +16,7 @@ use crate::error::Error; use crate::{ChangeToEnact, Storage}; -use primitives::{Address, Header, LogEntry, Receipt, H256, U256}; +use primitives::{Address, Header, HeaderId, LogEntry, Receipt, U256}; use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. @@ -181,18 +181,45 @@ impl<'a> Validators<'a> { /// Finalize changes when blocks are finalized. pub fn finalize_validators_change( &self, - storage: &mut S, - finalized_blocks: &[(u64, H256, Option)], + storage: &S, + finalized_blocks: &[(HeaderId, Option)], ) -> Option { - for (_, finalized_hash, _) in finalized_blocks.iter().rev() { - if let Some(changes) = storage.scheduled_change(finalized_hash) { - return Some(ChangeToEnact { - signal_block: Some(*finalized_hash), - validators: changes.validators, - }); - } - } - None + // if we haven't finalized any blocks, no changes may be finalized + let newest_finalized_id = match finalized_blocks.last().map(|(id, _)| id) { + Some(last_finalized_id) => last_finalized_id, + None => return None, + }; + let oldest_finalized_id = finalized_blocks + .first() + .map(|(id, _)| id) + .expect("finalized_blocks is not empty; qed"); + + // try to directly go to the header that has scheduled last change + // + // if we're unable to create import context for some block, it means + // that the header has already been pruned => it and its ancestors had + // no scheduled changes + // + // if we're unable to find scheduled changes for some block, it means + // that these changes have been finalized already + storage + .import_context(None, &newest_finalized_id.hash) + .and_then(|context| context.last_signal_block()) + .and_then(|signal_block| { + if signal_block.number >= oldest_finalized_id.number { + Some(signal_block) + } else { + None + } + }) + .and_then(|signal_block| { + storage + .scheduled_change(&signal_block.hash) + .map(|change| ChangeToEnact { + signal_block: Some(signal_block), + validators: change.validators, + }) + }) } /// Returns source of validators that should author the header. @@ -254,7 +281,10 @@ pub fn step_validator(header_validators: &[Address], header_step: u64) -> Addres #[cfg(test)] pub(crate) mod tests { use super::*; - use primitives::TransactionOutcome; + use crate::mock::{custom_test_ext, genesis, validators_addresses, TestRuntime}; + use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader}; + use frame_support::StorageMap; + use primitives::{TransactionOutcome, H256}; pub(crate) fn validators_change_recept(parent_hash: H256) -> Receipt { Receipt { @@ -393,4 +423,72 @@ pub(crate) mod tests { Err(Error::TransactionsReceiptsMismatch), ); } + + fn try_finalize_with_scheduled_change(scheduled_at: Option) -> Option { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); + let validators = Validators::new(&config); + let storage = BridgeStorage::::new(); + + // when we're finailizing blocks 10...100 + let id10 = HeaderId { + number: 10, + hash: [10; 32].into(), + }; + let id100 = HeaderId { + number: 100, + hash: [100; 32].into(), + }; + let finalized_blocks = vec![(id10, None), (id100, None)]; + let header100 = StoredHeader:: { + submitter: None, + header: Header { + number: 100, + ..Default::default() + }, + total_difficulty: 0.into(), + next_validators_set_id: 0, + last_signal_block: scheduled_at, + }; + let scheduled_change = ScheduledChange { + validators: validators_addresses(1), + prev_signal_block: None, + }; + Headers::::insert(id100.hash, header100); + if let Some(scheduled_at) = scheduled_at { + ScheduledChanges::insert(scheduled_at.hash, scheduled_change); + } + + validators.finalize_validators_change(&storage, &finalized_blocks) + }) + } + + #[test] + fn finalize_validators_change_finalizes_scheduled_change() { + let id50 = HeaderId { + number: 50, + ..Default::default() + }; + assert_eq!( + try_finalize_with_scheduled_change(Some(id50)), + Some(ChangeToEnact { + signal_block: Some(id50), + validators: validators_addresses(1), + }), + ); + } + + #[test] + fn finalize_validators_change_does_not_finalize_when_changes_are_not_scheduled() { + assert_eq!(try_finalize_with_scheduled_change(None), None,); + } + + #[test] + fn finalize_validators_change_does_not_finalize_changes_when_they_are_outside_of_range() { + let id5 = HeaderId { + number: 5, + ..Default::default() + }; + assert_eq!(try_finalize_with_scheduled_change(Some(id5)), None,); + } } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index ca8d9af6d17f7..dee912e26a157 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -18,26 +18,26 @@ use crate::error::Error; use crate::validators::{step_validator, Validators, ValidatorsConfiguration}; use crate::{AuraConfiguration, ImportContext, PoolConfiguration, ScheduledChange, Storage}; use codec::Encode; -use primitives::{public_to_address, Address, Header, Receipt, SealedEmptyStep, H256, H520, U128, U256}; +use primitives::{public_to_address, Address, Header, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256}; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_std::{vec, vec::Vec}; /// Pre-check to see if should try and import this header. /// Returns error if we should not try to import this block. -/// Returns hash of the header and number of the last finalized block otherwise. -pub fn is_importable_header(storage: &S, header: &Header) -> Result<(H256, H256), Error> { +/// Returns ID of passed header and best finalized header. +pub fn is_importable_header(storage: &S, header: &Header) -> Result<(HeaderId, HeaderId), Error> { // we never import any header that competes with finalized header - let (finalized_block_number, finalized_block_hash) = storage.finalized_block(); - if header.number <= finalized_block_number { + let finalized_id = storage.finalized_block(); + if header.number <= finalized_id.number { return Err(Error::AncientHeader); } // we never import any header with known hash - let hash = header.hash(); - if storage.header(&hash).is_some() { + let id = header.compute_id(); + if storage.header(&id.hash).is_some() { return Err(Error::KnownHeader); } - Ok((hash, finalized_block_hash)) + Ok((id, finalized_id)) } /// Try accept unsigned aura header into transaction pool. @@ -50,7 +50,7 @@ pub fn accept_aura_header_into_pool( receipts: Option<&Vec>, ) -> Result<(Vec>, Vec>), Error> { // check if we can verify further - let (hash, _) = is_importable_header(storage, header)?; + let (header_id, _) = is_importable_header(storage, header)?; // we can always do contextless checks contextless_checks(config, header)?; @@ -69,8 +69,8 @@ pub fn accept_aura_header_into_pool( // => if we see header with number > maximal ever seen header number + LIMIT, // => we consider this transaction invalid, but only at this moment (we do not want to ban it) // => let's mark it as Unknown transaction - let (best_number, best_hash, _) = storage.best_block(); - let difference = header.number.saturating_sub(best_number); + let (best_id, _) = storage.best_block(); + let difference = header.number.saturating_sub(best_id.number); if difference > pool_config.max_future_number_difference { return Err(Error::UnsignedTooFarInTheFuture); } @@ -87,7 +87,7 @@ pub fn accept_aura_header_into_pool( // previous headers here // => we can at least 'verify' that headers comprise a chain by providing and requiring // tag (header.number, header.hash) - let provides_header_number_and_hash_tag = (header.number, hash).encode(); + let provides_header_number_and_hash_tag = header_id.encode(); // depending on whether parent header is available, we either perform full or 'shortened' check let context = storage.import_context(None, &header.parent_hash); @@ -109,7 +109,7 @@ pub fn accept_aura_header_into_pool( // PoA chain AND that the header is produced either by previous, or next // scheduled validators set change let header_step = header.step().ok_or(Error::MissingStep)?; - let best_context = storage.import_context(None, &best_hash).expect( + let best_context = storage.import_context(None, &best_id.hash).expect( "import context is None only when header is missing from the storage;\ best header is always in the storage; qed", ); @@ -124,7 +124,11 @@ pub fn accept_aura_header_into_pool( // since our parent is missing from the storage, we **DO** require it // to be in the transaction pool // (- 1 can't underflow because there's always best block in the header) - let requires_header_number_and_hash_tag = (header.number - 1, header.parent_hash).encode(); + let requires_header_number_and_hash_tag = HeaderId { + number: header.number - 1, + hash: header.parent_hash, + } + .encode(); ( vec![requires_header_number_and_hash_tag], vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag], @@ -313,7 +317,7 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< // if parent schedules validators set change, then it may be our set // else we'll start with last known change - let mut current_set_signal_block = context.last_signal_block().cloned(); + let mut current_set_signal_block = context.last_signal_block(); let mut next_scheduled_set: Option = None; loop { @@ -325,7 +329,7 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< return next_scheduled_set.map(|scheduled_set| scheduled_set.validators) } None => return next_scheduled_set.map(|scheduled_set| scheduled_set.validators), - Some(current_set_signal_block) => storage.scheduled_change(¤t_set_signal_block).expect( + Some(current_set_signal_block) => storage.scheduled_change(¤t_set_signal_block.hash).expect( "header that is associated with this change is not pruned;\ scheduled changes are only removed when header is pruned; qed", ), @@ -386,12 +390,12 @@ mod tests { let block1 = block_i(1, &validators); insert_header(&mut storage, block1); let block2 = block_i(2, &validators); - let block2_hash = block2.hash(); + let block2_id = block2.compute_id(); insert_header(&mut storage, block2); let block3 = block_i(3, &validators); insert_header(&mut storage, block3); - FinalizedBlock::put((2, block2_hash)); + FinalizedBlock::put(block2_id); let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); @@ -415,7 +419,10 @@ mod tests { ValidatorsSet { validators: finalized_set, signal_block: None, - enact_block: HeadersByNumber::get(&0).unwrap()[0].clone(), + enact_block: HeaderId { + number: 0, + hash: HeadersByNumber::get(&0).unwrap()[0], + }, }, ); @@ -423,7 +430,10 @@ mod tests { let mut header = Headers::::get(&header_hash).unwrap(); header.next_validators_set_id = set_id; if let Some(signalled_set) = signalled_set { - header.last_signal_block = Some(header.header.parent_hash); + header.last_signal_block = Some(HeaderId { + number: header.header.number - 1, + hash: header.header.parent_hash, + }); ScheduledChanges::insert( header.header.parent_hash, ScheduledChange { @@ -554,7 +564,7 @@ mod tests { assert_eq!(default_verify(&header), Err(Error::MissingParentBlock)); // when parent is in the storage - header.parent_hash = genesis().hash(); + header.parent_hash = genesis().compute_hash(); assert_ne!(default_verify(&header), Err(Error::MissingParentBlock)); } @@ -564,7 +574,7 @@ mod tests { let mut header = Header { seal: vec![vec![].into(), vec![].into()], gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().hash(), + parent_hash: genesis().compute_hash(), ..Default::default() }; assert_eq!(default_verify(&header), Err(Error::MissingStep)); @@ -601,16 +611,16 @@ mod tests { seal: vec![ vec![45].into(), vec![142].into(), - SealedEmptyStep::rlp_of(&[sealed_empty_step(&validators, &genesis().hash(), 42)]), + SealedEmptyStep::rlp_of(&[sealed_empty_step(&validators, &genesis().compute_hash(), 42)]), ], gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().hash(), + parent_hash: genesis().compute_hash(), ..Default::default() }; assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); // when empty step signature check fails - let mut wrong_sealed_empty_step = sealed_empty_step(&validators, &genesis().hash(), 43); + let mut wrong_sealed_empty_step = sealed_empty_step(&validators, &genesis().compute_hash(), 43); wrong_sealed_empty_step.signature = Default::default(); header.seal[2] = SealedEmptyStep::rlp_of(&[wrong_sealed_empty_step]); assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); @@ -618,15 +628,15 @@ mod tests { // when we are accepting strict empty steps and they come not in order config.strict_empty_steps_transition = 0; header.seal[2] = SealedEmptyStep::rlp_of(&[ - sealed_empty_step(&validators, &genesis().hash(), 44), - sealed_empty_step(&validators, &genesis().hash(), 43), + sealed_empty_step(&validators, &genesis().compute_hash(), 44), + sealed_empty_step(&validators, &genesis().compute_hash(), 43), ]); assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); // when empty steps are OK header.seal[2] = SealedEmptyStep::rlp_of(&[ - sealed_empty_step(&validators, &genesis().hash(), 43), - sealed_empty_step(&validators, &genesis().hash(), 44), + sealed_empty_step(&validators, &genesis().compute_hash(), 43), + sealed_empty_step(&validators, &genesis().compute_hash(), 44), ]); assert_ne!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); } @@ -640,7 +650,7 @@ mod tests { let mut header = Header { seal: vec![vec![43].into(), vec![].into()], gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().hash(), + parent_hash: genesis().compute_hash(), ..Default::default() }; assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); @@ -659,7 +669,7 @@ mod tests { author: validators[1].address().as_fixed_bytes().into(), seal: vec![vec![43].into(), vec![].into()], gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().hash(), + parent_hash: genesis().compute_hash(), ..Default::default() }, 43, @@ -787,7 +797,7 @@ mod tests { assert_eq!( default_accept_into_pool(|validators| { let header = block_i(4, &validators); - hash = Some(header.hash()); + hash = Some(header.compute_hash()); (header, None) }), Ok(( @@ -819,7 +829,7 @@ mod tests { }, 47, ); - hash = Some(header.hash()); + hash = Some(header.compute_hash()); (header, None) }), Ok(( @@ -879,7 +889,7 @@ mod tests { }, 47, ); - hash = Some(header.hash()); + hash = Some(header.compute_hash()); (header, None) }), @@ -919,7 +929,7 @@ mod tests { .parse() .unwrap(); }); - hash = Some(header.hash()); + hash = Some(header.compute_hash()); (header, Some(vec![validators_change_recept(Default::default())])) }), Ok(( diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 969af63e1556f..da04c13faa77c 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -49,6 +49,15 @@ pub type RawTransaction = Vec; /// An ethereum address. pub type Address = H160; +/// Complete header id. +#[derive(Encode, Decode, Default, RuntimeDebug, PartialEq, Clone, Copy)] +pub struct HeaderId { + /// Header number. + pub number: u64, + /// Header hash. + pub hash: H256, +} + /// An Aura header. #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Default, Serialize, Deserialize))] @@ -156,8 +165,16 @@ pub struct SealedEmptyStep { } impl Header { - /// Get the hash of this header (keccak of the RLP with seal). - pub fn hash(&self) -> H256 { + /// Compute id of this header. + pub fn compute_id(&self) -> HeaderId { + HeaderId { + number: self.number, + hash: self.compute_hash(), + } + } + + /// Compute hash of this header (keccak of the RLP with seal). + pub fn compute_hash(&self) -> H256 { keccak_256(&self.rlp(true)).into() } @@ -175,7 +192,7 @@ impl Header { pub fn seal_hash(&self, include_empty_steps: bool) -> Option { Some(match include_empty_steps { true => { - let mut message = self.hash().as_bytes().to_vec(); + let mut message = self.compute_hash().as_bytes().to_vec(); message.extend_from_slice(self.seal.get(2)?); keccak_256(&message).into() } From 9cb2c06ee3be91679828ba652b724752d2b7e96c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 11 Jun 2020 17:44:54 +0300 Subject: [PATCH 0071/1210] Update Substrate to latest master (rc3) (#129) * Substrate 606c56d2e2f69f68f3947551224be6a3515dff60 * update jsonrpsee --- bin/node/node/Cargo.toml | 80 +++++++-------- bin/node/node/src/service.rs | 22 ++-- bin/node/runtime/Cargo.toml | 102 +++++++++---------- bin/node/runtime/src/lib.rs | 6 +- modules/currency-exchange/Cargo.toml | 24 ++--- modules/ethereum-contract/builtin/Cargo.toml | 18 ++-- modules/ethereum/Cargo.toml | 20 ++-- modules/ethereum/src/mock.rs | 4 +- modules/substrate/Cargo.toml | 36 +++---- primitives/currency-exchange/Cargo.toml | 8 +- primitives/ethereum-poa/Cargo.toml | 16 +-- relays/ethereum/Cargo.toml | 24 ++--- relays/substrate/Cargo.toml | 12 +-- relays/substrate/src/rpc.rs | 4 +- 14 files changed, 189 insertions(+), 187 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 2a9ff917aad27..f209961e083f8 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -19,100 +19,100 @@ bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } [dependencies.sc-cli] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa] package = "sc-finality-grandpa" -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-client-api] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -120,6 +120,6 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 736cab5198989..6e09a2c902b28 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -52,12 +52,12 @@ macro_rules! new_full_start { crate::service::Executor, >($config)? .with_select_chain(|_config, backend| Ok(sc_consensus::LongestChain::new(backend.clone())))? - .with_transaction_pool(|config, client, _fetcher, prometheus_registry| { - let pool_api = sc_transaction_pool::FullChainApi::new(client.clone()); + .with_transaction_pool(|builder| { + let pool_api = sc_transaction_pool::FullChainApi::new(builder.client().clone()); Ok(sc_transaction_pool::BasicPool::new( - config, + builder.config().transaction_pool.clone(), std::sync::Arc::new(pool_api), - prometheus_registry, + builder.prometheus_registry(), )) })? .with_import_queue( @@ -158,7 +158,7 @@ pub fn new_full(config: Configuration) -> Result Result(config)? .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))? - .with_transaction_pool(|config, client, fetcher, prometheus_registry| { - let fetcher = fetcher.ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; + .with_transaction_pool(|builder| { + let fetcher = builder + .fetcher() + .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; - let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone()); + let pool_api = sc_transaction_pool::LightChainApi::new(builder.client().clone(), fetcher.clone()); let pool = sc_transaction_pool::BasicPool::with_revalidation_type( - config, + builder.config().transaction_pool.clone(), Arc::new(pool_api), - prometheus_registry, + builder.prometheus_registry(), sc_transaction_pool::RevalidationType::Light, ); Ok(pool) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index e3cc405ee94d5..17c801e02e28d 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -25,15 +25,15 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-bridge-eth-poa] @@ -47,76 +47,76 @@ default-features = false path = "../../../modules/currency-exchange" [dependencies.frame-support] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-bridge-eth-poa] @@ -130,75 +130,75 @@ default-features = false path = "../../../primitives/currency-exchange" [dependencies.sp-consensus-aura] -version = "0.8.0-rc1" +version = "0.8.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [build-dependencies.wasm-builder-runner] version = "1.0.5" package = "substrate-wasm-builder-runner" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [features] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 2330e5c29f37d..f92a3a11b7929 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -146,7 +146,7 @@ parameter_types! { pub const ExtrinsicBaseWeight: Weight = 10_000_000; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); /// Assume 10% of weight for average on_initialize calls. - pub const MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() + pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; @@ -217,8 +217,8 @@ impl pallet_aura::Trait for Runtime { parameter_types! { pub const FinalityVotesCachingInterval: Option = Some(16); - pub const KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); - pub const KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = kovan::kovan_validators_configuration(); + pub KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); + pub KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = kovan::kovan_validators_configuration(); } impl pallet_bridge_eth_poa::Trait for Runtime { diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index cd3d11211985c..1a69a41f25167 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -12,37 +12,37 @@ sp-currency-exchange = { path = "../../primitives/currency-exchange", default-fe # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-io] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 4d36fa98fb27c..e9b938ccf86e0 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -18,29 +18,29 @@ finality-grandpa = "0.12.3" bridge-node-runtime = { path = "../../../bin/node/runtime" } [dependencies.sp-blockchain] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sc-finality-grandpa] version = "0.8.0-dev" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies] hex = "0.4" [dev-dependencies.sp-core] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 667abe8d97846..818ef12d40263 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -12,33 +12,33 @@ primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum- # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" # Dev Dependencies diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index a4f9e0fe4bbfc..2a004f5a25c70 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -72,8 +72,8 @@ impl frame_system::Trait for TestRuntime { parameter_types! { pub const TestFinalityVotesCachingInterval: Option = Some(16); - pub const TestAuraConfiguration: AuraConfiguration = test_aura_config(); - pub const TestValidatorsConfiguration: ValidatorsConfiguration = test_validators_config(); + pub TestAuraConfiguration: AuraConfiguration = test_aura_config(); + pub TestValidatorsConfiguration: ValidatorsConfiguration = test_validators_config(); } impl Trait for TestRuntime { diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 4f5f91c05b0d8..e55b0ac4b216d 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -13,57 +13,57 @@ hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "0.8.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [features] diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index eec26b3797afc..91fddf25480a9 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -11,15 +11,15 @@ codec = { package = "parity-scale-codec", version = "1.0.0", default-features = # Substrate Based Dependencies [dependencies.sp-std] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.frame-support] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [features] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index e6c3c6c04aa15..96c60c3efc6f7 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -25,27 +25,27 @@ hex-literal = "0.2" # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-rc1" +version = "2.0.0-rc3" default-features = false -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [features] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d5c97583bb7f2..9e31838b7e6a7 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -33,36 +33,36 @@ web3 = { git = "https://github.com/tomusdrw/rust-web3" } # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" # I think this is used for sr-io and stuff [dependencies.node-primitives] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" # Branch used for keccack256 hasher code # Could probably move the keccack hasher stuff to our own primitives [dependencies.sp-core] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" # This should get moved to our `bin` folder diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 9cfeec36131e3..a60194fb5cdb2 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -17,16 +17,16 @@ serde_json = "1.0.53" url = "2.1.0" [dependencies.sp-core] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-rpc] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.node-primitives] -version = "2.0.0-rc1" -rev = "599ba75bc2b5acd238c21c5c7efe8e2ad8d401ee" +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" diff --git a/relays/substrate/src/rpc.rs b/relays/substrate/src/rpc.rs index 10e41907f7654..5dfd1eb16c5ee 100644 --- a/relays/substrate/src/rpc.rs +++ b/relays/substrate/src/rpc.rs @@ -18,7 +18,7 @@ use jsonrpsee::{ raw::client::{RawClient, RawClientError}, transport::TransportClient, }; -use node_primitives::{BlockNumber, Hash, Header}; +use node_primitives::{Hash, Header}; use sp_core::Bytes; use sp_rpc::number::NumberOrHex; @@ -31,7 +31,7 @@ jsonrpsee::rpc_api! { fn chain_finalized_head() -> Hash; #[rpc(method = "chain_getBlockHash", positional_params)] - fn chain_block_hash(id: Option>) -> Option; + fn chain_block_hash(id: Option) -> Option; #[rpc(method = "chain_getHeader", positional_params)] fn chain_header(hash: Option) -> Option
; From c0b3d8aa576cd03d04be032baa091d5bec105a14 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 11 Jun 2020 12:25:48 -0400 Subject: [PATCH 0072/1210] Add async_trait to SourceClient and TargetClient (#123) * Use async_trait for SourceClient * Use aync_trait for TargetClient * Revert async_trait usage for Source/Target client This reverts commit f636ffaffd60197e90e887362b4a0c35a0dc5a6c. This reverts commit 2c15755e8c93318f8e0a605852efe87d72edb769. I'm having a very hard time finding out what is causing compilation issues, and I think it's best to start over again. * Use async_trait for TargetClient * Use async_trait for SourceClient * Move where non-async methods are * RustFmt * QueuedHeader holds Arc to actual data * Clean up async return type Co-authored-by: Svyatoslav Nikolsky * Clean up async return type Co-authored-by: Svyatoslav Nikolsky * Clean up async return type Co-authored-by: Svyatoslav Nikolsky * Remove unused import Co-authored-by: Svyatoslav Nikolsky --- relays/ethereum/src/ethereum_client.rs | 2 +- relays/ethereum/src/ethereum_sync_loop.rs | 91 +++++++++++----------- relays/ethereum/src/substrate_client.rs | 10 +-- relays/ethereum/src/substrate_sync_loop.rs | 87 +++++++++++---------- relays/ethereum/src/sync_loop.rs | 88 +++++++++++---------- relays/ethereum/src/sync_types.rs | 54 ++++++++----- 6 files changed, 174 insertions(+), 158 deletions(-) diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 110c8733c03b6..5dba31344b0a3 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -284,7 +284,7 @@ pub async fn submit_substrate_headers( Some(contract_address), Some(nonce), false, - bridge_contract::functions::import_header::encode_input(header.extract().0.encode(),), + bridge_contract::functions::import_header::encode_input(header.header().encode(),), ) .await ) diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index c9e8a987f0186..95f415a753228 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -21,8 +21,10 @@ use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Heade use crate::substrate_client::{self, SubstrateConnectionParams, SubstrateSigningParams}; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; use crate::sync_loop::{OwnedSourceFutureOutput, OwnedTargetFutureOutput, SourceClient, TargetClient}; -use futures::future::{ready, FutureExt, Ready}; -use std::{collections::HashSet, future::Future, pin::Pin, time::Duration}; + +use async_trait::async_trait; +use futures::future::FutureExt; +use std::{collections::HashSet, time::Duration}; use web3::types::H256; /// Interval at which we check new Ethereum headers when we are synced/almost synced. @@ -80,40 +82,40 @@ struct EthereumHeadersSource { type EthereumFutureOutput = OwnedSourceFutureOutput; +#[async_trait] impl SourceClient for EthereumHeadersSource { type Error = ethereum_client::Error; - type BestBlockNumberFuture = Pin>>>; - type HeaderByHashFuture = Pin>>>; - type HeaderByNumberFuture = Pin>>>; - type HeaderExtraFuture = Pin)>>>>; - type HeaderCompletionFuture = Ready)>>; - fn best_block_number(self) -> Self::BestBlockNumberFuture { + async fn best_block_number(self) -> EthereumFutureOutput { ethereum_client::best_block_number(self.client) .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .boxed() + .await } - fn header_by_hash(self, hash: H256) -> Self::HeaderByHashFuture { + async fn header_by_hash(self, hash: H256) -> EthereumFutureOutput
{ ethereum_client::header_by_hash(self.client, hash) .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .boxed() + .await } - fn header_by_number(self, number: u64) -> Self::HeaderByNumberFuture { + async fn header_by_number(self, number: u64) -> EthereumFutureOutput
{ ethereum_client::header_by_number(self.client, number) .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .boxed() + .await } - fn header_extra(self, id: EthereumHeaderId, header: &Header) -> Self::HeaderExtraFuture { - ethereum_client::transactions_receipts(self.client, id, header.transactions.clone()) - .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .boxed() + async fn header_completion(self, id: EthereumHeaderId) -> EthereumFutureOutput<(EthereumHeaderId, Option<()>)> { + (self, Ok((id, None))) } - fn header_completion(self, id: EthereumHeaderId) -> Self::HeaderCompletionFuture { - ready((self, Ok((id, None)))) + async fn header_extra( + self, + id: EthereumHeaderId, + header: QueuedEthereumHeader, + ) -> EthereumFutureOutput<(EthereumHeaderId, Vec)> { + ethereum_client::transactions_receipts(self.client, id, header.header().transactions.clone()) + .map(|(client, result)| (EthereumHeadersSource { client }, result)) + .await } } @@ -129,16 +131,11 @@ struct SubstrateHeadersTarget { type SubstrateFutureOutput = OwnedTargetFutureOutput; +#[async_trait] impl TargetClient for SubstrateHeadersTarget { type Error = substrate_client::Error; - type BestHeaderIdFuture = Pin>>>; - type IsKnownHeaderFuture = Pin>>>; - type RequiresExtraFuture = Pin>>>; - type SubmitHeadersFuture = Pin>>>>; - type IncompleteHeadersFuture = Ready>>; - type CompleteHeadersFuture = Ready>; - - fn best_header_id(self) -> Self::BestHeaderIdFuture { + + async fn best_header_id(self) -> SubstrateFutureOutput { let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); substrate_client::best_ethereum_block(self.client) .map(move |(client, result)| { @@ -151,10 +148,10 @@ impl TargetClient for SubstrateHeadersTarget { result, ) }) - .boxed() + .await } - fn is_known_header(self, id: EthereumHeaderId) -> Self::IsKnownHeaderFuture { + async fn is_known_header(self, id: EthereumHeaderId) -> SubstrateFutureOutput<(EthereumHeaderId, bool)> { let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); substrate_client::ethereum_header_known(self.client, id) .map(move |(client, result)| { @@ -167,15 +164,12 @@ impl TargetClient for SubstrateHeadersTarget { result, ) }) - .boxed() + .await } - fn requires_extra(self, header: &QueuedEthereumHeader) -> Self::RequiresExtraFuture { - // we can minimize number of receipts_check calls by checking header - // logs bloom here, but it may give us false positives (when authorities - // source is contract, we never need any logs) + async fn submit_headers(self, headers: Vec) -> SubstrateFutureOutput> { let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); - substrate_client::ethereum_receipts_required(self.client, header.clone()) + substrate_client::submit_ethereum_headers(self.client, sign_params.clone(), headers, sign_transactions) .map(move |(client, result)| { ( SubstrateHeadersTarget { @@ -186,12 +180,23 @@ impl TargetClient for SubstrateHeadersTarget { result, ) }) - .boxed() + .await + } + + async fn incomplete_headers_ids(self) -> SubstrateFutureOutput> { + (self, Ok(HashSet::new())) } - fn submit_headers(self, headers: Vec) -> Self::SubmitHeadersFuture { + async fn complete_header(self, id: EthereumHeaderId, _completion: ()) -> SubstrateFutureOutput { + (self, Ok(id)) + } + + async fn requires_extra(self, header: QueuedEthereumHeader) -> SubstrateFutureOutput<(EthereumHeaderId, bool)> { + // we can minimize number of receipts_check calls by checking header + // logs bloom here, but it may give us false positives (when authorities + // source is contract, we never need any logs) let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); - substrate_client::submit_ethereum_headers(self.client, sign_params.clone(), headers, sign_transactions) + substrate_client::ethereum_receipts_required(self.client, header) .map(move |(client, result)| { ( SubstrateHeadersTarget { @@ -202,15 +207,7 @@ impl TargetClient for SubstrateHeadersTarget { result, ) }) - .boxed() - } - - fn incomplete_headers_ids(self) -> Self::IncompleteHeadersFuture { - ready((self, Ok(HashSet::new()))) - } - - fn complete_header(self, id: EthereumHeaderId, _completion: ()) -> Self::CompleteHeadersFuture { - ready((self, Ok(id))) + .await } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 0319c0b5ac828..e7067cbda3a0d 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -380,10 +380,9 @@ fn create_signed_submit_transaction( headers .into_iter() .map(|header| { - let (header, receipts) = header.extract(); ( - into_substrate_ethereum_header(&header), - into_substrate_ethereum_receipts(&receipts), + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), ) }) .collect(), @@ -422,11 +421,10 @@ fn create_signed_submit_transaction( /// Create unsigned Substrate transaction for submitting Ethereum header. fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { - let (header, receipts) = header.extract(); let function = bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(&header), - into_substrate_ethereum_receipts(&receipts), + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), )); bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 88dc4b6276a46..7ca80f9672ad9 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -25,8 +25,10 @@ use crate::substrate_types::{ use crate::sync::{HeadersSyncParams, TargetTransactionMode}; use crate::sync_loop::{OwnedSourceFutureOutput, OwnedTargetFutureOutput, SourceClient, TargetClient}; use crate::sync_types::SourceHeader; -use futures::future::{ready, FutureExt, Ready}; -use std::{collections::HashSet, future::Future, pin::Pin, time::Duration}; + +use async_trait::async_trait; +use futures::future::FutureExt; +use std::{collections::HashSet, time::Duration}; /// Interval at which we check new Substrate headers when we are synced/almost synced. const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10); @@ -87,41 +89,43 @@ struct SubstrateHeadersSource { type SubstrateFutureOutput = OwnedSourceFutureOutput; +#[async_trait] impl SourceClient for SubstrateHeadersSource { type Error = substrate_client::Error; - type BestBlockNumberFuture = Pin>>>; - type HeaderByHashFuture = Pin>>>; - type HeaderByNumberFuture = Pin>>>; - type HeaderExtraFuture = Ready>; - type HeaderCompletionFuture = - Pin)>>>>; - - fn best_block_number(self) -> Self::BestBlockNumberFuture { + + async fn best_block_number(self) -> SubstrateFutureOutput { substrate_client::best_header(self.client) .map(|(client, result)| (SubstrateHeadersSource { client }, result.map(|header| header.number))) - .boxed() + .await } - fn header_by_hash(self, hash: Hash) -> Self::HeaderByHashFuture { + async fn header_by_hash(self, hash: Hash) -> SubstrateFutureOutput
{ substrate_client::header_by_hash(self.client, hash) .map(|(client, result)| (SubstrateHeadersSource { client }, result)) - .boxed() + .await } - fn header_by_number(self, number: Number) -> Self::HeaderByNumberFuture { + async fn header_by_number(self, number: Number) -> SubstrateFutureOutput
{ substrate_client::header_by_number(self.client, number) .map(|(client, result)| (SubstrateHeadersSource { client }, result)) - .boxed() - } - - fn header_extra(self, id: SubstrateHeaderId, _header: &Header) -> Self::HeaderExtraFuture { - ready((self, Ok((id, ())))) + .await } - fn header_completion(self, id: SubstrateHeaderId) -> Self::HeaderCompletionFuture { + async fn header_completion( + self, + id: SubstrateHeaderId, + ) -> SubstrateFutureOutput<(SubstrateHeaderId, Option)> { substrate_client::grandpa_justification(self.client, id) .map(|(client, result)| (SubstrateHeadersSource { client }, result)) - .boxed() + .await + } + + async fn header_extra( + self, + id: SubstrateHeaderId, + _header: QueuedSubstrateHeader, + ) -> SubstrateFutureOutput<(SubstrateHeaderId, ())> { + (self, Ok((id, ()))) } } @@ -137,16 +141,11 @@ struct EthereumHeadersTarget { type EthereumFutureOutput = OwnedTargetFutureOutput; +#[async_trait] impl TargetClient for EthereumHeadersTarget { type Error = ethereum_client::Error; - type BestHeaderIdFuture = Pin>>>; - type IsKnownHeaderFuture = Pin>>>; - type RequiresExtraFuture = Ready>; - type SubmitHeadersFuture = Pin>>>>; - type IncompleteHeadersFuture = Pin>>>>; - type CompleteHeadersFuture = Pin>>>; - - fn best_header_id(self) -> Self::BestHeaderIdFuture { + + async fn best_header_id(self) -> EthereumFutureOutput { let (contract, sign_params) = (self.contract, self.sign_params); ethereum_client::best_substrate_block(self.client, contract) .map(move |(client, result)| { @@ -159,10 +158,10 @@ impl TargetClient for EthereumHeadersTarget { result, ) }) - .boxed() + .await } - fn is_known_header(self, id: SubstrateHeaderId) -> Self::IsKnownHeaderFuture { + async fn is_known_header(self, id: SubstrateHeaderId) -> EthereumFutureOutput<(SubstrateHeaderId, bool)> { let (contract, sign_params) = (self.contract, self.sign_params); ethereum_client::substrate_header_known(self.client, contract, id) .map(move |(client, result)| { @@ -175,14 +174,10 @@ impl TargetClient for EthereumHeadersTarget { result, ) }) - .boxed() - } - - fn requires_extra(self, header: &QueuedSubstrateHeader) -> Self::RequiresExtraFuture { - ready((self, Ok((header.header().id(), false)))) + .await } - fn submit_headers(self, headers: Vec) -> Self::SubmitHeadersFuture { + async fn submit_headers(self, headers: Vec) -> EthereumFutureOutput> { let (contract, sign_params) = (self.contract, self.sign_params); ethereum_client::submit_substrate_headers(self.client, sign_params.clone(), contract, headers) .map(move |(client, result)| { @@ -195,10 +190,10 @@ impl TargetClient for EthereumHeadersTarget { result, ) }) - .boxed() + .await } - fn incomplete_headers_ids(self) -> Self::IncompleteHeadersFuture { + async fn incomplete_headers_ids(self) -> EthereumFutureOutput> { let (contract, sign_params) = (self.contract, self.sign_params); ethereum_client::incomplete_substrate_headers(self.client, contract) .map(move |(client, result)| { @@ -211,10 +206,14 @@ impl TargetClient for EthereumHeadersTarget { result, ) }) - .boxed() + .await } - fn complete_header(self, id: SubstrateHeaderId, completion: GrandpaJustification) -> Self::CompleteHeadersFuture { + async fn complete_header( + self, + id: SubstrateHeaderId, + completion: GrandpaJustification, + ) -> EthereumFutureOutput { let (contract, sign_params) = (self.contract, self.sign_params); ethereum_client::complete_substrate_header(self.client, sign_params.clone(), contract, id, completion) .map(move |(client, result)| { @@ -227,7 +226,11 @@ impl TargetClient for EthereumHeadersTarget { result, ) }) - .boxed() + .await + } + + async fn requires_extra(self, header: QueuedSubstrateHeader) -> EthereumFutureOutput<(SubstrateHeaderId, bool)> { + (self, Ok((header.header().id(), false))) } } diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index ce89a846a0fb4..978db603591db 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -16,11 +16,12 @@ use crate::sync::HeadersSyncParams; use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader}; + +use async_trait::async_trait; use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; use std::{ collections::HashSet, - future::Future, time::{Duration, Instant}, }; @@ -48,69 +49,70 @@ pub type OwnedSourceFutureOutput = (Client, Result = (Client, Result>::Error>); /// Source client trait. +#[async_trait] pub trait SourceClient: Sized { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; - /// Future that returns best block number. - type BestBlockNumberFuture: Future>; - /// Future that returns header by hash. - type HeaderByHashFuture: Future>; - /// Future that returns header by number. - type HeaderByNumberFuture: Future>; - /// Future that returns extra data associated with header. - type HeaderExtraFuture: Future, P::Extra)>>; - /// Future that returns data required to 'complete' header. - type HeaderCompletionFuture: Future< - Output = OwnedSourceFutureOutput, Option)>, - >; /// Get best block number. - fn best_block_number(self) -> Self::BestBlockNumberFuture; + async fn best_block_number(self) -> OwnedSourceFutureOutput; + /// Get header by hash. - fn header_by_hash(self, hash: P::Hash) -> Self::HeaderByHashFuture; + async fn header_by_hash(self, hash: P::Hash) -> OwnedSourceFutureOutput; + /// Get canonical header by number. - fn header_by_number(self, number: P::Number) -> Self::HeaderByNumberFuture; - /// Get extra data by header hash. - fn header_extra(self, id: HeaderId, header: &P::Header) -> Self::HeaderExtraFuture; + async fn header_by_number(self, number: P::Number) -> OwnedSourceFutureOutput; + /// Get completion data by header hash. - fn header_completion(self, id: HeaderId) -> Self::HeaderCompletionFuture; + async fn header_completion( + self, + id: HeaderId, + ) -> OwnedSourceFutureOutput, Option)>; + + /// Get extra data by header hash. + async fn header_extra( + self, + id: HeaderId, + header: QueuedHeader

, + ) -> OwnedSourceFutureOutput, P::Extra)>; } /// Target client trait. +#[async_trait] pub trait TargetClient: Sized { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; - /// Future that returns best header id. - type BestHeaderIdFuture: Future>>; - /// Future that returns known header check result. - type IsKnownHeaderFuture: Future, bool)>>; - /// Future that returns extra check result. - type RequiresExtraFuture: Future, bool)>>; - /// Future that returns header submission result. - type SubmitHeadersFuture: Future>>>; - /// Future that returns incomplete headers ids. - type IncompleteHeadersFuture: Future< - Output = OwnedTargetFutureOutput>>, - >; - /// Future that returns header completion result. - type CompleteHeadersFuture: Future>>; /// Returns ID of best header known to the target node. - fn best_header_id(self) -> Self::BestHeaderIdFuture; + async fn best_header_id(self) -> OwnedTargetFutureOutput>; + /// Returns true if header is known to the target node. - fn is_known_header(self, id: HeaderId) -> Self::IsKnownHeaderFuture; - /// Returns true if header requires extra data to be submitted. - fn requires_extra(self, header: &QueuedHeader

) -> Self::RequiresExtraFuture; + async fn is_known_header( + self, + id: HeaderId, + ) -> OwnedTargetFutureOutput, bool)>; + /// Submit headers. - fn submit_headers(self, headers: Vec>) -> Self::SubmitHeadersFuture; + async fn submit_headers( + self, + headers: Vec>, + ) -> OwnedTargetFutureOutput>>; + /// Returns ID of headers that require to be 'completed' before children can be submitted. - fn incomplete_headers_ids(self) -> Self::IncompleteHeadersFuture; + async fn incomplete_headers_ids(self) -> OwnedTargetFutureOutput>>; + /// Submit completion data for header. - fn complete_header( + async fn complete_header( self, id: HeaderId, completion: P::Completion, - ) -> Self::CompleteHeadersFuture; + ) -> OwnedTargetFutureOutput>; + + /// Returns true if header requires extra data to be submitted. + async fn requires_extra( + self, + header: QueuedHeader

, + ) -> OwnedTargetFutureOutput, bool)>; } /// Run headers synchronization. @@ -385,7 +387,7 @@ pub fn run( header.id(), ); - target_extra_check_future.set(target_client.requires_extra(header).fuse()); + target_extra_check_future.set(target_client.requires_extra(header.clone()).fuse()); } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeOrphan) { // for MaybeOrphan we actually ask for parent' header existence let parent_id = header.parent_id(); @@ -452,7 +454,7 @@ pub fn run( "Retrieving extra data for header: {:?}", id, ); - source_extra_future.set(source_client.header_extra(id, header.header()).fuse()); + source_extra_future.set(source_client.header_extra(id, header.clone()).fuse()); } else if let Some(header) = sync.headers().header(HeaderStatus::Orphan) { // for Orphan we actually ask for parent' header let parent_id = header.parent_id(); diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index 8d68bd8759c31..391d18afab390 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use std::{ops::Deref, sync::Arc}; + /// Ethereum header Id. #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] pub struct HeaderId(pub Number, pub Hash); @@ -70,7 +72,7 @@ pub trait HeadersSyncPipeline: Clone + Copy { + num_traits::Zero + num_traits::One; /// Type of header that we're syncing. - type Header: Clone + std::fmt::Debug + SourceHeader; + type Header: Clone + std::fmt::Debug + PartialEq + SourceHeader; /// Type of extra data for the header that we're receiving from the source node: /// 1) extra data is required for some headers; /// 2) target node may answer if it'll require extra data before header is submitted; @@ -78,7 +80,7 @@ pub trait HeadersSyncPipeline: Clone + Copy { /// 4) header and extra data are submitted in single transaction. /// /// Example: Ethereum transactions receipts. - type Extra: Clone + std::fmt::Debug; + type Extra: Clone + PartialEq + std::fmt::Debug; /// Type of data required to 'complete' header that we're receiving from the source node: /// 1) completion data is required for some headers; /// 2) target node can't answer if it'll require completion data before header is accepted; @@ -101,19 +103,44 @@ pub trait SourceHeader { } /// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] #[cfg_attr(test, derive(PartialEq))] -pub struct QueuedHeader { - header: P::Header, - extra: Option, -} +pub struct QueuedHeader(Arc>); impl QueuedHeader

{ /// Creates new queued header. pub fn new(header: P::Header) -> Self { - QueuedHeader { header, extra: None } + QueuedHeader(Arc::new(QueuedHeaderData { header, extra: None })) } + /// Set associated extra data. + pub fn set_extra(self, extra: P::Extra) -> Self { + QueuedHeader(Arc::new(QueuedHeaderData { + header: Arc::try_unwrap(self.0) + .map(|data| data.header) + .unwrap_or_else(|data| data.header.clone()), + extra: Some(extra), + })) + } +} + +impl Deref for QueuedHeader

{ + type Target = QueuedHeaderData

; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// Header how it's stored in the synchronization queue. +#[derive(Clone, Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] +pub struct QueuedHeaderData { + header: P::Header, + extra: Option, +} + +impl QueuedHeader

{ /// Returns ID of header. pub fn id(&self) -> HeaderId { self.header.id() @@ -133,15 +160,4 @@ impl QueuedHeader

{ pub fn extra(&self) -> &Option { &self.extra } - - /// Extract header and extra from self. - pub fn extract(self) -> (P::Header, Option) { - (self.header, self.extra) - } - - /// Set associated extra data. - pub fn set_extra(mut self, extra: P::Extra) -> Self { - self.extra = Some(extra); - self - } } From f89a0d0cbf9a81878381de095112d74327d2366e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2020 02:57:54 +0000 Subject: [PATCH 0073/1210] Bump serde_json from 1.0.53 to 1.0.55 (#134) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 9e31838b7e6a7..143a5fa052712 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -26,7 +26,7 @@ parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" serde = { version = "1.0.111", features = ["derive"] } -serde_json = "1.0.53" +serde_json = "1.0.55" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = { git = "https://github.com/tomusdrw/rust-web3" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index a60194fb5cdb2..ad223ff96bb58 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -13,7 +13,7 @@ env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" -serde_json = "1.0.53" +serde_json = "1.0.55" url = "2.1.0" [dependencies.sp-core] From 3ab254ba8b2aed62818418bcfd55120ad8c9dd2b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2020 03:27:09 +0000 Subject: [PATCH 0074/1210] Bump async-trait from 0.1.33 to 0.1.35 (#135) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 143a5fa052712..33d7c922d39ac 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" ansi_term = "0.12" async-std = "=1.5.0" async-stream = "0.2.0" -async-trait = "0.1.33" +async-trait = "0.1.35" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" From 87ddf8a5fb8963752f05a1b632c238a11d4b5c31 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2020 04:27:31 +0000 Subject: [PATCH 0075/1210] Bump serde from 1.0.111 to 1.0.112 (#133) --- bin/node/runtime/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 17c801e02e28d..244c1e34e0663 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -19,7 +19,7 @@ default-features = false features = ["derive"] [dependencies.serde] -version = "1.0.111" +version = "1.0.112" optional = true features = ["derive"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 33d7c922d39ac..dcb0c7f3707f8 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -25,7 +25,7 @@ num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" -serde = { version = "1.0.111", features = ["derive"] } +serde = { version = "1.0.112", features = ["derive"] } serde_json = "1.0.55" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" From 2f58c597ae219c3c9522fa5710fbbb7ea39dede4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 16 Jun 2020 16:46:30 +0300 Subject: [PATCH 0076/1210] Move pruning strategy to runtime level (#128) * move pruning strategy to runtim level * cargo fmt --all * Update modules/ethereum/src/lib.rs Co-authored-by: Hernando Castano * finalize_headers -> finalize_and_prune_headers * PruningStrategy::default() * fn import_of_non_best_block_may_finalize_blocks() Co-authored-by: Hernando Castano --- bin/node/runtime/src/kovan.rs | 49 +++++++++++- bin/node/runtime/src/lib.rs | 1 + modules/ethereum/src/import.rs | 136 ++++++++++++++++++++++++--------- modules/ethereum/src/lib.rs | 64 ++++++++++------ modules/ethereum/src/mock.rs | 29 +++++-- 5 files changed, 215 insertions(+), 64 deletions(-) diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index 2592d8e057b26..09fb309c70e4c 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -14,11 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use frame_support::RuntimeDebug; use hex_literal::hex; -use pallet_bridge_eth_poa::{AuraConfiguration, ValidatorsConfiguration, ValidatorsSource}; +use pallet_bridge_eth_poa::{AuraConfiguration, PruningStrategy, ValidatorsConfiguration, ValidatorsSource}; use sp_bridge_eth_poa::{Address, Header, U256}; use sp_std::prelude::*; +/// Max number of finalized headers to keep. It is equivalent of ~24 hours of +/// finalized blocks on current Kovan chain. +const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000; + /// Aura engine configuration for Kovan chain. pub fn kovan_aura_configuration() -> AuraConfiguration { AuraConfiguration { @@ -102,3 +107,45 @@ pub fn kovan_genesis_header() -> Header { ], } } + +/// Kovan headers pruning strategy. +/// +/// We do not prune unfinalized headers because exchange module only accepts +/// claims from finalized headers. And if we're pruning unfinalized headers, then +/// some claims may never be accepted. +#[derive(Default, RuntimeDebug)] +pub struct KovanPruningStrategy; + +impl PruningStrategy for KovanPruningStrategy { + fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { + best_finalized_number + .checked_sub(FINALIZED_HEADERS_TO_KEEP) + .unwrap_or(0) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn pruning_strategy_keeps_enough_headers() { + assert_eq!( + KovanPruningStrategy::default().pruning_upper_bound(100_000, 10_000), + 0, + "10_000 <= 20_000 => nothing should be pruned yet", + ); + + assert_eq!( + KovanPruningStrategy::default().pruning_upper_bound(100_000, 20_000), + 0, + "20_000 <= 20_000 => nothing should be pruned yet", + ); + + assert_eq!( + KovanPruningStrategy::default().pruning_upper_bound(100_000, 30_000), + 10_000, + "20_000 <= 30_000 => we're ready to prune first 10_000 headers", + ); + } +} diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index f92a3a11b7929..fe1fc8c905872 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -225,6 +225,7 @@ impl pallet_bridge_eth_poa::Trait for Runtime { type AuraConfiguration = KovanAuraConfiguration; type FinalityVotesCachingInterval = FinalityVotesCachingInterval; type ValidatorsConfiguration = KovanValidatorsConfiguration; + type PruningStrategy = kovan::KovanPruningStrategy; type OnHeadersSubmitted = (); } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index a59bfc750b4a8..9f8d146f881bc 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -18,19 +18,10 @@ use crate::error::Error; use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::{is_importable_header, verify_aura_header}; -use crate::{AuraConfiguration, ChangeToEnact, Storage}; +use crate::{AuraConfiguration, ChangeToEnact, PruningStrategy, Storage}; use primitives::{Header, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; -/// Maximal number of headers behind best blocks that we are aiming to store. When there -/// are too many unfinalized headers, it slows down finalization tracking significantly. -/// That's why we won't consider imports/reorganizations to blocks of PRUNE_DEPTH age. -/// If there's more headers than that, we prune the oldest. The only exception is -/// when unfinalized header schedules validators set change. We can't compute finality -/// for pruned headers => we won't know when to enact validators set change. That's -/// why we never prune headers with scheduled changes. -pub(crate) const PRUNE_DEPTH: u64 = 4096; - /// Imports bunch of headers and updates blocks finality. /// /// Transactions receipts must be provided if `header_import_requires_receipts()` @@ -40,11 +31,11 @@ pub(crate) const PRUNE_DEPTH: u64 = 4096; /// we have NOT imported. /// Returns error if fatal error has occured during import. Some valid headers may be /// imported in this case. -pub fn import_headers( +pub fn import_headers( storage: &mut S, + pruning_strategy: &mut PS, aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, - prune_depth: u64, submitter: Option, headers: Vec<(Header, Option>)>, finalized_headers: &mut BTreeMap, @@ -54,9 +45,9 @@ pub fn import_headers( for (header, receipts) in headers { let import_result = import_header( storage, + pruning_strategy, aura_config, validators_config, - prune_depth, submitter.clone(), header, receipts, @@ -85,11 +76,11 @@ pub fn import_headers( /// has returned true. /// /// Returns imported block id and list of all finalized headers. -pub fn import_header( +pub fn import_header( storage: &mut S, + pruning_strategy: &mut PS, aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, - prune_depth: u64, submitter: Option, header: Header, receipts: Option>, @@ -126,10 +117,9 @@ pub fn import_header( // (because otherwise we'll have inconsistent storage if transaction will fail) // and finally insert the block - let (_, best_total_difficulty) = storage.best_block(); + let (best_id, best_total_difficulty) = storage.best_block(); let total_difficulty = import_context.total_difficulty() + header.difficulty; let is_best = total_difficulty > best_total_difficulty; - let header_number = header.number; storage.insert_header(import_context.into_import_header( is_best, header_id, @@ -140,15 +130,19 @@ pub fn import_header( finalized_blocks.votes, )); - // now mark finalized headers && prune old headers - storage.finalize_headers( - finalized_blocks.finalized_headers.last().map(|(id, _)| *id), - match is_best { - true => header_number.checked_sub(prune_depth), - false => None, - }, + // compute upper border of updated pruning range + let new_best_block_id = if is_best { header_id } else { best_id }; + let new_best_finalized_block_id = finalized_blocks.finalized_headers.last().map(|(id, _)| *id); + let pruning_upper_bound = pruning_strategy.pruning_upper_bound( + new_best_block_id.number, + new_best_finalized_block_id + .map(|id| id.number) + .unwrap_or(finalized_id.number), ); + // now mark finalized headers && prune old headers + storage.finalize_and_prune_headers(new_best_finalized_block_id, pruning_upper_bound); + Ok((header_id, finalized_blocks.finalized_headers)) } @@ -169,7 +163,7 @@ mod tests { use super::*; use crate::mock::{ block_i, custom_block_i, custom_test_ext, genesis, signed_header, test_aura_config, test_validators_config, - validator, validators, validators_addresses, TestRuntime, + validator, validators, validators_addresses, KeepSomeHeadersBehindBest, TestRuntime, GENESIS_STEP, }; use crate::validators::ValidatorsSource; use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; @@ -179,19 +173,19 @@ mod tests { fn rejects_finalized_block_competitors() { custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { let mut storage = BridgeStorage::::new(); - storage.finalize_headers( + storage.finalize_and_prune_headers( Some(HeaderId { number: 100, ..Default::default() }), - None, + 0, ); assert_eq!( import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &test_validators_config(), - PRUNE_DEPTH, None, Default::default(), None, @@ -210,9 +204,9 @@ mod tests { assert_eq!( import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &test_validators_config(), - PRUNE_DEPTH, None, block.clone(), None, @@ -223,9 +217,9 @@ mod tests { assert_eq!( import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &test_validators_config(), - PRUNE_DEPTH, None, block, None, @@ -250,9 +244,9 @@ mod tests { assert_eq!( import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &validators_config, - PRUNE_DEPTH, None, header, None @@ -285,9 +279,9 @@ mod tests { let header = block_i(i, &validators); let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &validators_config, - 10, Some(100), header, None, @@ -316,9 +310,9 @@ mod tests { }); let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &validators_config, - 10, Some(101), header11.clone(), Some(vec![crate::validators::tests::validators_change_recept( @@ -352,9 +346,9 @@ mod tests { expected_blocks.push((header.compute_id(), Some(102))); let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &validators_config, - 10, Some(102), header, None, @@ -387,9 +381,9 @@ mod tests { let header = signed_header(&validators, header, step as _); let (_, finalized_blocks) = import_header( &mut storage, + &mut KeepSomeHeadersBehindBest::default(), &test_aura_config(), &validators_config, - 10, Some(103), header, None, @@ -405,4 +399,76 @@ mod tests { ); }); } + + #[test] + fn import_of_non_best_block_may_finalize_blocks() { + const TOTAL_VALIDATORS: u8 = 3; + let validators_addresses = validators_addresses(TOTAL_VALIDATORS); + custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { + let validators = validators(TOTAL_VALIDATORS); + let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( + [0; 20].into(), + validators_addresses.clone(), + )); + let mut storage = BridgeStorage::::new(); + let mut pruning_strategy = KeepSomeHeadersBehindBest::default(); + + // insert headers (H1, validator1), (H2, validator1), (H3, validator1) + // making H3 the best header, without finalizing anything (we need 2 signatures) + let mut expected_best_block = Default::default(); + for i in 1..4 { + let step = GENESIS_STEP + i * TOTAL_VALIDATORS as u64; + let header = custom_block_i(i, &validators, |header| { + header.author = validators_addresses[0]; + header.seal[0][0] = step as u8; + }); + let header = signed_header(&validators, header, step); + expected_best_block = header.compute_id(); + import_header( + &mut storage, + &mut pruning_strategy, + &test_aura_config(), + &validators_config, + None, + header, + None, + ) + .unwrap(); + } + let (best_block, best_difficulty) = storage.best_block(); + assert_eq!(best_block, expected_best_block); + assert_eq!(storage.finalized_block(), genesis().compute_id()); + + // insert headers (H1', validator1), (H2', validator2), finalizing H2, even though H3 + // has better difficulty than H2' (because there are more steps involved) + let mut expected_finalized_block = Default::default(); + let mut parent_hash = genesis().compute_hash(); + for i in 1..3 { + let header = custom_block_i(i, &validators, |header| { + header.gas_limit += 1.into(); + header.parent_hash = parent_hash; + }); + let header = signed_header(&validators, header, GENESIS_STEP + i); + parent_hash = header.compute_hash(); + if i == 1 { + expected_finalized_block = header.compute_id(); + } + + import_header( + &mut storage, + &mut pruning_strategy, + &test_aura_config(), + &validators_config, + None, + header, + None, + ) + .unwrap(); + } + let (new_best_block, new_best_difficulty) = storage.best_block(); + assert_eq!(new_best_block, expected_best_block); + assert_eq!(new_best_difficulty, best_difficulty); + assert_eq!(storage.finalized_block(), expected_finalized_block); + }); + } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 8b927bd54ef29..ef7f7b95d514e 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -286,15 +286,31 @@ pub trait Storage { fn scheduled_change(&self, hash: &H256) -> Option; /// Insert imported header. fn insert_header(&mut self, header: HeaderToImport); - /// Finalize given block and prune all headers with number < prune_end. + /// Finalize given block and schedules pruning of all headers + /// with number < prune_end. + /// /// The headers in the pruning range could be either finalized, or not. /// It is the storage duty to ensure that unfinalized headers that have /// scheduled changes won't be pruned until they or their competitors /// are finalized. - fn finalize_headers(&mut self, finalized: Option, prune_end: Option); + fn finalize_and_prune_headers(&mut self, finalized: Option, prune_end: u64); +} + +/// Headers pruning strategy. +pub trait PruningStrategy: Default { + /// Return upper bound (exclusive) of headers pruning range. + /// + /// Every value that is returned from this function, must be greater or equal to the + /// previous value. Otherwise it will be ignored (we can't revert pruning). + /// + /// Module may prune both finalized and unfinalized blocks. But it can't give any + /// guarantees on when it will happen. Example: if some unfinalized block at height N + /// has scheduled validators set change, then the module won't prune any blocks with + /// number >= N even if strategy allows that. + fn pruning_upper_bound(&mut self, best_number: u64, best_finalized_number: u64) -> u64; } -/// Decides whether the session should be ended. +/// Callbacks for header submission rewards/penalties. pub trait OnHeadersSubmitted { /// Called when valid headers have been submitted. /// @@ -322,6 +338,9 @@ impl OnHeadersSubmitted for () { pub trait Trait: frame_system::Trait { /// Aura configuration. type AuraConfiguration: Get; + /// Validators configuration. + type ValidatorsConfiguration: Get; + /// Interval (in blocks) for for finality votes caching. /// If None, cache is disabled. /// @@ -329,8 +348,9 @@ pub trait Trait: frame_system::Trait { /// be any significant finalization delays), or something that is bit larger /// than average finalization delay. type FinalityVotesCachingInterval: Get>; - /// Validators configuration. - type ValidatorsConfiguration: Get; + /// Headers pruning strategy. + type PruningStrategy: PruningStrategy; + /// Handler for headers submission result. type OnHeadersSubmitted: OnHeadersSubmitted; } @@ -344,9 +364,9 @@ decl_module! { import::import_header( &mut BridgeStorage::::new(), + &mut T::PruningStrategy::default(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), - crate::import::PRUNE_DEPTH, None, header, receipts, @@ -365,9 +385,9 @@ decl_module! { let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( &mut BridgeStorage::::new(), + &mut T::PruningStrategy::default(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), - crate::import::PRUNE_DEPTH, Some(submitter.clone()), headers_with_receipts, &mut finalized_headers, @@ -539,15 +559,13 @@ impl BridgeStorage { } /// Prune old blocks. - fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: Option) { + fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) { let pruning_range = BlocksToPrune::get(); let mut new_pruning_range = pruning_range.clone(); // update oldest block we want to keep - if let Some(prune_end) = prune_end { - if prune_end > new_pruning_range.oldest_block_to_keep { - new_pruning_range.oldest_block_to_keep = prune_end; - } + if prune_end > new_pruning_range.oldest_block_to_keep { + new_pruning_range.oldest_block_to_keep = prune_end; } // start pruning blocks @@ -770,7 +788,7 @@ impl Storage for BridgeStorage { ); } - fn finalize_headers(&mut self, finalized: Option, prune_end: Option) { + fn finalize_and_prune_headers(&mut self, finalized: Option, prune_end: u64) { // remember just finalized block let finalized_number = finalized .as_ref() @@ -928,7 +946,7 @@ pub(crate) mod tests { }); // try to prune blocks [5; 10) - storage.prune_blocks(0xFFFF, 10, Some(5)); + storage.prune_blocks(0xFFFF, 10, 5); assert_eq!(HeadersByNumber::get(&5).unwrap().len(), 5); assert_eq!( BlocksToPrune::get(), @@ -949,7 +967,7 @@ pub(crate) mod tests { }); // try to prune blocks [5; 10) - storage.prune_blocks(0xFFFF, 10, Some(3)); + storage.prune_blocks(0xFFFF, 10, 3); assert_eq!( BlocksToPrune::get(), PruningRange { @@ -964,7 +982,7 @@ pub(crate) mod tests { fn blocks_are_not_pruned_if_limit_is_zero() { with_headers_to_prune(|storage| { // try to prune blocks [0; 10) - storage.prune_blocks(0, 10, Some(10)); + storage.prune_blocks(0, 10, 10); assert!(HeadersByNumber::get(&0).is_some()); assert!(HeadersByNumber::get(&1).is_some()); assert!(HeadersByNumber::get(&2).is_some()); @@ -983,7 +1001,7 @@ pub(crate) mod tests { fn blocks_are_pruned_if_limit_is_non_zero() { with_headers_to_prune(|storage| { // try to prune blocks [0; 10) - storage.prune_blocks(7, 10, Some(10)); + storage.prune_blocks(7, 10, 10); // 1 headers with number = 0 is pruned (1 total) assert!(HeadersByNumber::get(&0).is_none()); // 5 headers with number = 1 are pruned (6 total) @@ -999,7 +1017,7 @@ pub(crate) mod tests { ); // try to prune blocks [2; 10) - storage.prune_blocks(11, 10, Some(10)); + storage.prune_blocks(11, 10, 10); // 4 headers with number = 2 are pruned (4 total) assert!(HeadersByNumber::get(&2).is_none()); // 5 headers with number = 3 are pruned (9 total) @@ -1023,7 +1041,7 @@ pub(crate) mod tests { // last finalized block is 5 // and one of blocks#7 has scheduled change // => we won't prune any block#7 at all - storage.prune_blocks(0xFFFF, 5, Some(10)); + storage.prune_blocks(0xFFFF, 5, 10); assert!(HeadersByNumber::get(&0).is_none()); assert!(HeadersByNumber::get(&1).is_none()); assert!(HeadersByNumber::get(&2).is_none()); @@ -1071,7 +1089,7 @@ pub(crate) mod tests { oldest_unpruned_block: interval - 1, oldest_block_to_keep: interval - 1, }); - storage.finalize_headers(None, Some(interval + 1)); + storage.finalize_and_prune_headers(None, interval + 1); assert_eq!(FinalityCache::::get(&header_with_entry_hash), None); }); } @@ -1152,7 +1170,7 @@ pub(crate) mod tests { let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); - storage.finalize_headers(Some(example_header().compute_id()), None); + storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( verify_transaction_finalized(&storage, example_header_parent().compute_hash(), 0, &vec![example_tx()],), true, @@ -1206,7 +1224,7 @@ pub(crate) mod tests { insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); insert_header(&mut storage, finalized_header_sibling); - storage.finalize_headers(Some(example_header().compute_id()), None); + storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( verify_transaction_finalized(&storage, finalized_header_sibling_hash, 0, &vec![example_tx()],), false, @@ -1225,7 +1243,7 @@ pub(crate) mod tests { insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, finalized_header_uncle); insert_header(&mut storage, example_header()); - storage.finalize_headers(Some(example_header().compute_id()), None); + storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( verify_transaction_finalized(&storage, finalized_header_uncle_hash, 0, &vec![example_tx()],), false, diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 2a004f5a25c70..1575f6cf405d4 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -16,7 +16,7 @@ use crate::finality::FinalityVotes; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, HeadersByNumber, Storage, Trait}; +use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, HeadersByNumber, PruningStrategy, Storage, Trait}; use frame_support::StorageMap; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use parity_crypto::publickey::{sign, KeyPair, Secret}; @@ -78,11 +78,15 @@ parameter_types! { impl Trait for TestRuntime { type AuraConfiguration = TestAuraConfiguration; - type FinalityVotesCachingInterval = TestFinalityVotesCachingInterval; type ValidatorsConfiguration = TestValidatorsConfiguration; + type FinalityVotesCachingInterval = TestFinalityVotesCachingInterval; + type PruningStrategy = KeepSomeHeadersBehindBest; type OnHeadersSubmitted = (); } +/// Step of genesis header. +pub const GENESIS_STEP: u64 = 42; + /// Aura configuration that is used in tests by default. pub fn test_aura_config() -> AuraConfiguration { AuraConfiguration { @@ -105,7 +109,7 @@ pub fn test_validators_config() -> ValidatorsConfiguration { /// Genesis header that is used in tests by default. pub fn genesis() -> Header { Header { - seal: vec![vec![42].into(), vec![].into()], + seal: vec![vec![GENESIS_STEP as _].into(), vec![].into()], ..Default::default() } } @@ -123,12 +127,12 @@ pub fn custom_block_i(number: u64, validators: &[KeyPair], customize: impl FnOnc parent_hash: HeadersByNumber::get(number - 1).unwrap()[0].clone(), gas_limit: 0x2000.into(), author: validator(validator_index).address(), - seal: vec![vec![number as u8 + 42].into(), vec![].into()], + seal: vec![vec![(number + GENESIS_STEP) as u8].into(), vec![].into()], difficulty: number.into(), ..Default::default() }; customize(&mut header); - signed_header(validators, header, number + 42) + signed_header(validators, header, number + GENESIS_STEP) } /// Build signed header from given header. @@ -182,3 +186,18 @@ pub fn insert_header(storage: &mut S, header: Header) { finality_votes: FinalityVotes::default(), }); } + +/// Pruning strategy that keeps 10 headers behind best block. +pub struct KeepSomeHeadersBehindBest(pub u64); + +impl Default for KeepSomeHeadersBehindBest { + fn default() -> KeepSomeHeadersBehindBest { + KeepSomeHeadersBehindBest(10) + } +} + +impl PruningStrategy for KeepSomeHeadersBehindBest { + fn pruning_upper_bound(&mut self, best_number: u64, _: u64) -> u64 { + best_number.checked_sub(self.0).unwrap_or(0) + } +} From b9d690b127ca42ea4d55ec3fcdd505d571782d4e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 18 Jun 2020 10:45:16 +0300 Subject: [PATCH 0077/1210] Forbid appending blocks to forks that are competing with finalized chain (#138) * Error::TryingToFinalizeSibling * cargo fmt --all * updated PruningStrategy comment --- modules/ethereum/src/error.rs | 3 + modules/ethereum/src/finality.rs | 90 ++++++++++++--- modules/ethereum/src/import.rs | 170 +++++++++++++++++++++++------ modules/ethereum/src/lib.rs | 93 +++++++++++++--- primitives/ethereum-poa/src/lib.rs | 8 ++ 5 files changed, 296 insertions(+), 68 deletions(-) diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index 4c887a4a493e4..0a9ca57f8c135 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -60,6 +60,8 @@ pub enum Error { TransactionsReceiptsMismatch = 18, /// Can't accept unsigned header from the far future. UnsignedTooFarInTheFuture = 19, + /// Trying to finalize sibling of finalized block. + TryingToFinalizeSibling = 20, } impl Error { @@ -85,6 +87,7 @@ impl Error { Error::RedundantTransactionsReceipts => "Redundant transactions receipts are provided", Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided", Error::UnsignedTooFarInTheFuture => "The unsigned header is too far in future", + Error::TryingToFinalizeSibling => "Trying to finalize sibling of finalized block", } } diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 0fb5f1f777413..c7bfe67d640bc 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -28,9 +28,13 @@ use sp_std::collections::{ use sp_std::prelude::*; /// Cached finality votes for given block. -#[derive(RuntimeDebug, Default)] +#[derive(RuntimeDebug)] #[cfg_attr(test, derive(PartialEq))] pub struct CachedFinalityVotes { + /// True if we have stopped at best finalized block' sibling. This means + /// that we are trying to finalize block from fork that has forked before + /// best finalized. + pub stopped_at_finalized_sibling: bool, /// Header ancestors that were read while we have been searching for /// cached votes entry. Newest header has index 0. pub unaccounted_ancestry: VecDeque<(HeaderId, Option, Header)>, @@ -88,10 +92,15 @@ pub fn finalize_blocks( // compute count of voters for every unfinalized block in ancestry let validators = header_validators.1.iter().collect(); let votes = prepare_votes( - storage.cached_finality_votes(&header.parent_hash, |hash| { - *hash == header_validators.0.hash || *hash == best_finalized.hash - }), - best_finalized.number, + header + .parent_id() + .map(|parent_id| { + storage.cached_finality_votes(&parent_id, &best_finalized, |hash| { + *hash == header_validators.0.hash || *hash == best_finalized.hash + }) + }) + .unwrap_or_else(|| CachedFinalityVotes::default()), + best_finalized, &validators, id, header, @@ -133,12 +142,18 @@ fn is_finalized( /// Prepare 'votes' of header and its ancestors' signers. fn prepare_votes( mut cached_votes: CachedFinalityVotes, - best_finalized_number: u64, + best_finalized: HeaderId, validators: &BTreeSet<&Address>, id: HeaderId, header: &Header, submitter: Option, ) -> Result, Error> { + // if we have reached finalized block sibling, then we're trying + // to switch finalized blocks + if cached_votes.stopped_at_finalized_sibling { + return Err(Error::TryingToFinalizeSibling); + } + // this fn can only work with single validators set if !validators.contains(&header.author) { return Err(Error::NotValidator); @@ -154,7 +169,7 @@ fn prepare_votes( // remove votes from finalized blocks while let Some(old_ancestor) = votes.ancestry.pop_front() { - if old_ancestor.id.number > best_finalized_number { + if old_ancestor.id.number > best_finalized.number { votes.ancestry.push_front(old_ancestor); break; } @@ -245,6 +260,16 @@ fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option .map(|public| public_to_address(&public)) } +impl Default for CachedFinalityVotes { + fn default() -> Self { + CachedFinalityVotes { + stopped_at_finalized_sibling: false, + unaccounted_ancestry: VecDeque::new(), + votes: None, + } + } +} + impl Default for FinalityVotes { fn default() -> Self { FinalityVotes { @@ -307,7 +332,7 @@ mod tests { assert_eq!( finalize_blocks( &storage, - Default::default(), + genesis().compute_id(), (Default::default(), &validators_addresses(5)), id1, None, @@ -331,7 +356,7 @@ mod tests { assert_eq!( finalize_blocks( &storage, - Default::default(), + genesis().compute_id(), (Default::default(), &validators_addresses(5)), id2, None, @@ -355,7 +380,7 @@ mod tests { assert_eq!( finalize_blocks( &storage, - Default::default(), + genesis().compute_id(), (Default::default(), &validators_addresses(5)), id3, None, @@ -397,6 +422,7 @@ mod tests { assert_eq!( prepare_votes::<()>( CachedFinalityVotes { + stopped_at_finalized_sibling: false, unaccounted_ancestry: vec![(headers[3].compute_id(), None, headers[3].clone()),] .into_iter() .collect(), @@ -407,7 +433,7 @@ mod tests { ancestry: ancestry[..3].iter().cloned().collect(), }), }, - 2, + headers[1].compute_id(), &validators.iter().collect(), header5.compute_id(), &header5, @@ -471,8 +497,12 @@ mod tests { let id7 = headers[6].compute_id(); assert_eq!( prepare_votes( - storage.cached_finality_votes(&hashes.get(5).unwrap(), |_| false,), - 0, + storage.cached_finality_votes( + &headers.get(5).unwrap().compute_id(), + &genesis().compute_id(), + |_| false, + ), + Default::default(), &validators_addresses.iter().collect(), id7, headers.get(6).unwrap(), @@ -498,8 +528,12 @@ mod tests { // check that votes at #7 are computed correctly with cache assert_eq!( prepare_votes( - storage.cached_finality_votes(&hashes.get(5).unwrap(), |_| false,), - 0, + storage.cached_finality_votes( + &headers.get(5).unwrap().compute_id(), + &genesis().compute_id(), + |_| false, + ), + Default::default(), &validators_addresses.iter().collect(), id7, headers.get(6).unwrap(), @@ -522,8 +556,12 @@ mod tests { }; assert_eq!( prepare_votes( - storage.cached_finality_votes(&hashes.get(5).unwrap(), |hash| *hash == hashes[2],), - 3, + storage.cached_finality_votes( + &headers.get(5).unwrap().compute_id(), + &headers.get(2).unwrap().compute_id(), + |hash| *hash == hashes[2], + ), + headers[2].compute_id(), &validators_addresses.iter().collect(), id7, headers.get(6).unwrap(), @@ -534,4 +572,22 @@ mod tests { ); }); } + + #[test] + fn prepare_votes_fails_when_finalized_sibling_is_in_ancestry() { + assert_eq!( + prepare_votes::<()>( + CachedFinalityVotes { + stopped_at_finalized_sibling: true, + ..Default::default() + }, + Default::default(), + &validators_addresses(3).iter().collect(), + Default::default(), + &Default::default(), + None, + ), + Err(Error::TryingToFinalizeSibling), + ); + } } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 9f8d146f881bc..4ae91bb70c707 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -168,6 +168,7 @@ mod tests { use crate::validators::ValidatorsSource; use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; use frame_support::{StorageMap, StorageValue}; + use parity_crypto::publickey::KeyPair; #[test] fn rejects_finalized_block_competitors() { @@ -400,39 +401,53 @@ mod tests { }); } + fn import_custom_block( + storage: &mut S, + validators: &[KeyPair], + number: u64, + step: u64, + customize: impl FnOnce(&mut Header), + ) -> Result { + let header = custom_block_i(number, validators, |header| { + header.seal[0][0] = step as _; + header.author = + crate::validators::step_validator(&validators.iter().map(|kp| kp.address()).collect::>(), step); + customize(header); + }); + let header = signed_header(validators, header, step); + let id = header.compute_id(); + import_header( + storage, + &mut KeepSomeHeadersBehindBest::default(), + &test_aura_config(), + &ValidatorsConfiguration::Single(ValidatorsSource::Contract( + [0; 20].into(), + validators.iter().map(|kp| kp.address()).collect(), + )), + None, + header, + None, + ) + .map(|_| id) + } + #[test] fn import_of_non_best_block_may_finalize_blocks() { const TOTAL_VALIDATORS: u8 = 3; let validators_addresses = validators_addresses(TOTAL_VALIDATORS); custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { let validators = validators(TOTAL_VALIDATORS); - let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( - [0; 20].into(), - validators_addresses.clone(), - )); let mut storage = BridgeStorage::::new(); - let mut pruning_strategy = KeepSomeHeadersBehindBest::default(); // insert headers (H1, validator1), (H2, validator1), (H3, validator1) // making H3 the best header, without finalizing anything (we need 2 signatures) let mut expected_best_block = Default::default(); for i in 1..4 { let step = GENESIS_STEP + i * TOTAL_VALIDATORS as u64; - let header = custom_block_i(i, &validators, |header| { + expected_best_block = import_custom_block(&mut storage, &validators, i, step, |header| { header.author = validators_addresses[0]; header.seal[0][0] = step as u8; - }); - let header = signed_header(&validators, header, step); - expected_best_block = header.compute_id(); - import_header( - &mut storage, - &mut pruning_strategy, - &test_aura_config(), - &validators_config, - None, - header, - None, - ) + }) .unwrap(); } let (best_block, best_difficulty) = storage.best_block(); @@ -444,26 +459,16 @@ mod tests { let mut expected_finalized_block = Default::default(); let mut parent_hash = genesis().compute_hash(); for i in 1..3 { - let header = custom_block_i(i, &validators, |header| { + let step = GENESIS_STEP + i; + let id = import_custom_block(&mut storage, &validators, i, step, |header| { header.gas_limit += 1.into(); header.parent_hash = parent_hash; - }); - let header = signed_header(&validators, header, GENESIS_STEP + i); - parent_hash = header.compute_hash(); + }) + .unwrap(); + parent_hash = id.hash; if i == 1 { - expected_finalized_block = header.compute_id(); + expected_finalized_block = id; } - - import_header( - &mut storage, - &mut pruning_strategy, - &test_aura_config(), - &validators_config, - None, - header, - None, - ) - .unwrap(); } let (new_best_block, new_best_difficulty) = storage.best_block(); assert_eq!(new_best_block, expected_best_block); @@ -471,4 +476,101 @@ mod tests { assert_eq!(storage.finalized_block(), expected_finalized_block); }); } + + #[test] + fn append_to_unfinalized_fork_fails() { + const TOTAL_VALIDATORS: u64 = 5; + let validators_addresses = validators_addresses(TOTAL_VALIDATORS as _); + custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { + let validators = validators(TOTAL_VALIDATORS as _); + let mut storage = BridgeStorage::::new(); + + // header1, authored by validator[2] is best common block between two competing forks + let header1 = import_custom_block(&mut storage, &validators, 1, GENESIS_STEP + 1, |_| ()).unwrap(); + assert_eq!(storage.best_block().0, header1); + assert_eq!(storage.finalized_block().number, 0); + + // validator[3] has authored header2 (nothing is finalized yet) + let header2 = import_custom_block(&mut storage, &validators, 2, GENESIS_STEP + 2, |_| ()).unwrap(); + assert_eq!(storage.best_block().0, header2); + assert_eq!(storage.finalized_block().number, 0); + + // validator[4] has authored header3 (header1 is finalized) + let header3 = import_custom_block(&mut storage, &validators, 3, GENESIS_STEP + 3, |_| ()).unwrap(); + assert_eq!(storage.best_block().0, header3); + assert_eq!(storage.finalized_block(), header1); + + // validator[4] has authored 4 blocks: header2'...header5' (header1 is still finalized) + let header2_1 = import_custom_block(&mut storage, &validators, 2, GENESIS_STEP + 3, |header| { + header.gas_limit += 1.into(); + }) + .unwrap(); + let header3_1 = import_custom_block( + &mut storage, + &validators, + 3, + GENESIS_STEP + 3 + TOTAL_VALIDATORS, + |header| { + header.parent_hash = header2_1.hash; + }, + ) + .unwrap(); + let header4_1 = import_custom_block( + &mut storage, + &validators, + 4, + GENESIS_STEP + 3 + TOTAL_VALIDATORS * 2, + |header| { + header.parent_hash = header3_1.hash; + }, + ) + .unwrap(); + let header5_1 = import_custom_block( + &mut storage, + &validators, + 5, + GENESIS_STEP + 3 + TOTAL_VALIDATORS * 3, + |header| { + header.parent_hash = header4_1.hash; + }, + ) + .unwrap(); + assert_eq!(storage.best_block().0, header5_1); + assert_eq!(storage.finalized_block(), header1); + + // when we import header4 { parent = header3 }, authored by validator[0], header2 is finalized + let header4 = import_custom_block(&mut storage, &validators, 4, GENESIS_STEP + 4, |_| ()).unwrap(); + assert_eq!(storage.best_block().0, header5_1); + assert_eq!(storage.finalized_block(), header2); + + // when we import header5 { parent = header4 }, authored by validator[1], header3 is finalized + let _ = import_custom_block(&mut storage, &validators, 5, GENESIS_STEP + 5, |header| { + header.parent_hash = header4.hash; + }) + .unwrap(); + assert_eq!(storage.best_block().0, header5_1); + assert_eq!(storage.finalized_block(), header3); + + // import of header2'' { parent = header1 } fails, because it has number < best_finalized + assert_eq!( + import_custom_block(&mut storage, &validators, 2, GENESIS_STEP + 3, |header| { + header.gas_limit += 2.into(); + }), + Err(Error::AncientHeader), + ); + + // import of header6' should also fail because we're trying to append to fork thas + // has forked before finalized block + assert_eq!( + import_custom_block( + &mut storage, + &validators, + 6, + GENESIS_STEP + 3 + TOTAL_VALIDATORS * 4, + |_| () + ), + Err(Error::TryingToFinalizeSibling), + ); + }); + } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ef7f7b95d514e..4c495a8c1489c 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -268,11 +268,12 @@ pub trait Storage { /// Returns header and its submitter (if known). fn header(&self, hash: &H256) -> Option<(Header, Option)>; /// Returns latest cached finality votes (if any) for block ancestors, starting - /// from `parent_hash` block and stopping at genesis block, or block where `stop_at` - /// returns true. + /// from `parent_hash` block and stopping at genesis block, best finalized block + /// or block where `stop_at` returns true. fn cached_finality_votes( &self, - parent_hash: &H256, + parent: &HeaderId, + best_finalized: &HeaderId, stop_at: impl Fn(&H256) -> bool, ) -> CachedFinalityVotes; /// Get header import context by parent header hash. @@ -307,6 +308,12 @@ pub trait PruningStrategy: Default { /// guarantees on when it will happen. Example: if some unfinalized block at height N /// has scheduled validators set change, then the module won't prune any blocks with /// number >= N even if strategy allows that. + /// + /// If your strategy allows pruning unfinalized blocks, this could lead to switch + /// between finalized forks (only if authorities are misbehaving). But since 50%+1 (or 2/3) + /// authorities are able to do whatever they want with the chain, this isn't considered + /// fatal. If your strategy only prunes finalized blocks, we'll never be able to finalize + /// header that isn't descendant of current best finalized block. fn pruning_upper_bound(&mut self, best_number: u64, best_finalized_number: u64) -> u64; } @@ -660,36 +667,49 @@ impl Storage for BridgeStorage { fn cached_finality_votes( &self, - parent_hash: &H256, + parent: &HeaderId, + best_finalized: &HeaderId, stop_at: impl Fn(&H256) -> bool, ) -> CachedFinalityVotes { let mut votes = CachedFinalityVotes::default(); - let mut current_hash = *parent_hash; + let mut current_id = *parent; loop { - if stop_at(¤t_hash) { + // if we have reached finalized block' sibling => stop with special signal + if current_id.number == best_finalized.number { + if current_id.hash != best_finalized.hash { + votes.stopped_at_finalized_sibling = true; + return votes; + } + } + + // if we have reached target header => stop + if stop_at(¤t_id.hash) { return votes; } - let cached_votes = FinalityCache::::get(¤t_hash); + // if we have found cached votes => stop + let cached_votes = FinalityCache::::get(¤t_id.hash); if let Some(cached_votes) = cached_votes { votes.votes = Some(cached_votes); return votes; } - let header = match Headers::::get(¤t_hash) { + // read next parent header id + let header = match Headers::::get(¤t_id.hash) { Some(header) if header.header.number != 0 => header, _ => return votes, }; - let parent_hash = header.header.parent_hash; - let current_id = HeaderId { - number: header.header.number, - hash: current_hash, - }; + let parent_id = header.header.parent_id().expect( + "only returns None at genesis header;\ + the header is proved to have number > 0;\ + qed", + ); + votes .unaccounted_ancestry .push_back((current_id, header.submitter, header.header)); - current_hash = parent_hash; + current_id = parent_id; } } @@ -1108,10 +1128,11 @@ pub(crate) mod tests { } // when inserting header#6, entry isn't found - let hash5 = headers.last().unwrap().compute_hash(); + let id5 = headers.last().unwrap().compute_id(); assert_eq!( - storage.cached_finality_votes(&hash5, |_| false), + storage.cached_finality_votes(&id5, &genesis().compute_id(), |_| false), CachedFinalityVotes { + stopped_at_finalized_sibling: false, unaccounted_ancestry: headers .iter() .map(|header| (header.compute_id(), None, header.clone(),)) @@ -1139,8 +1160,9 @@ pub(crate) mod tests { // searching at #6 again => entry is found assert_eq!( - storage.cached_finality_votes(&hash5, |_| false), + storage.cached_finality_votes(&id5, &genesis().compute_id(), |_| false), CachedFinalityVotes { + stopped_at_finalized_sibling: false, unaccounted_ancestry: headers .iter() .skip(3) @@ -1153,6 +1175,43 @@ pub(crate) mod tests { }); } + #[test] + fn cached_finality_votes_stops_at_finalized_sibling() { + custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + let validators = validators(3); + let mut storage = BridgeStorage::::new(); + + // insert header1 + let header1 = block_i(1, &validators); + let header1_id = header1.compute_id(); + insert_header(&mut storage, header1); + + // insert header1' - sibling of header1 + let header1s = custom_block_i(1, &validators, |header| { + header.gas_limit += 1.into(); + }); + let header1s_id = header1s.compute_id(); + insert_header(&mut storage, header1s); + + // header1 is finalized + FinalizedBlock::put(header1_id); + + // trying to get finality votes when importing header2 -> header1 succeeds + assert!( + !storage + .cached_finality_votes(&header1_id, &genesis().compute_id(), |_| false) + .stopped_at_finalized_sibling + ); + + // trying to get finality votes when importing header2s -> header1s fails + assert!( + storage + .cached_finality_votes(&header1s_id, &header1_id, |_| false) + .stopped_at_finalized_sibling + ); + }); + } + #[test] fn verify_transaction_finalized_works_for_best_finalized_header() { custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index da04c13faa77c..12ee571315358 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -178,6 +178,14 @@ impl Header { keccak_256(&self.rlp(true)).into() } + /// Get id of this header' parent. Returns None if this is genesis header. + pub fn parent_id(&self) -> Option { + self.number.checked_sub(1).map(|parent_number| HeaderId { + number: parent_number, + hash: self.parent_hash, + }) + } + /// Check if passed transactions receipts are matching receipts root in this header. pub fn verify_receipts_root(&self, receipts: &[Receipt]) -> bool { verify_merkle_proof(self.receipts_root, receipts.iter().map(|r| r.rlp())) From 0062ea871f359d706793987b3f9a10dca53668c6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2020 10:52:33 +0200 Subject: [PATCH 0078/1210] Bump serde from 1.0.112 to 1.0.114 (#144) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.112 to 1.0.114. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.112...v1.0.114) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- bin/node/runtime/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 244c1e34e0663..2bc3e25144b96 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -19,7 +19,7 @@ default-features = false features = ["derive"] [dependencies.serde] -version = "1.0.112" +version = "1.0.114" optional = true features = ["derive"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index dcb0c7f3707f8..d2e720ce0cf6f 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -25,7 +25,7 @@ num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.10.2" rustc-hex = "2.0.1" -serde = { version = "1.0.112", features = ["derive"] } +serde = { version = "1.0.114", features = ["derive"] } serde_json = "1.0.55" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" From 98bfec787deb1ab6b43331b377427ff78cc7b0f8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2020 10:52:43 +0200 Subject: [PATCH 0079/1210] Bump async-trait from 0.1.35 to 0.1.36 (#145) Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.35 to 0.1.36. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.35...0.1.36) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d2e720ce0cf6f..01cfbf704c021 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" ansi_term = "0.12" async-std = "=1.5.0" async-stream = "0.2.0" -async-trait = "0.1.35" +async-trait = "0.1.36" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" From ff7969de293f6c7fe58960e1220881836833eeff Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2020 10:52:53 +0200 Subject: [PATCH 0080/1210] Bump derive_more from 0.99.7 to 0.99.8 (#146) Bumps [derive_more](https://github.com/JelteF/derive_more) from 0.99.7 to 0.99.8. - [Release notes](https://github.com/JelteF/derive_more/releases) - [Changelog](https://github.com/JelteF/derive_more/blob/master/CHANGELOG.md) - [Commits](https://github.com/JelteF/derive_more/compare/v0.99.7...v0.99.8) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index ad223ff96bb58..c40d287824038 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" async-std = "=1.5.0" clap = "2.33.1" ctrlc = "3.1.4" -derive_more = "0.99.7" +derive_more = "0.99.8" env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } From 1e7249396916aff623e62fcd8abd1ef0e4db6d3c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2020 10:53:04 +0200 Subject: [PATCH 0081/1210] Bump structopt from 0.3.14 to 0.3.15 (#148) Bumps [structopt](https://github.com/TeXitoi/structopt) from 0.3.14 to 0.3.15. - [Release notes](https://github.com/TeXitoi/structopt/releases) - [Changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md) - [Commits](https://github.com/TeXitoi/structopt/compare/v0.3.14...v0.3.15) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index f209961e083f8..229c3ff637e22 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -14,7 +14,7 @@ name = "bridge-node" futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.8" -structopt = "0.3.14" +structopt = "0.3.15" bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } From 77ff3714cfb0c37ad5135b16f663a3c9f017c929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 23 Jun 2020 03:36:32 +0200 Subject: [PATCH 0082/1210] Update web3 dependency. (#140) * Update web3 dependency. * Switch to crates.io. --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 01cfbf704c021..4bdcf930c1c4e 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -29,7 +29,7 @@ serde = { version = "1.0.114", features = ["derive"] } serde_json = "1.0.55" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" -web3 = { git = "https://github.com/tomusdrw/rust-web3" } +web3 = { version = "0.12.0", default-features = false } # Substrate Based Dependencies [dependencies.frame-system] From 9a842beb4c66fc6fa91590dc130249dd4649495a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 23 Jun 2020 16:55:51 -0400 Subject: [PATCH 0083/1210] Switch to new RPC interface (#131) * Move EthereumRpc implementation to Eth client * Move SubstrateRpc implementation to SubstrateClient * Update deploy_contract to use new RPC interface * Fix some types in the Substrate client * Swap out method bodies in Eth sync loop * Swap out method bodies in Substrate sync loop * Remove Client from SourceClient trait return types * Remove Client from TargetClient trait return types * Remove client from Source select! arms * Remove client from Target select! arms * Add missing mutable refs in Substrate client * Use mutable references in Source/Target Client traits * Try and use mutable references in Source/Client trait implementations * Handle errors more gracefully * Remove unused imports * Remove dead_code and unused_variables lints * Remove usage of `jsonrpsee::RawClient` By using a `jsonrpsee::Client` we are able to remove all the shared mutable references required when interacting with the RPC server. This is convenient as trying to sharing mutable references in code that uses async/await is a bit of a pain. However, using a `Client` instead of a `RawClient` is not yet supported by the `jsonrpsee::rpc_api` macro, so a fork must be used for the moment. * Clean up dead code and warnings * Clean up higher level RPCs Some of the RPCs that were "high level" didn't necessarily belong as part of the trait, so they were removed. * Use positional parameters for RPCs Both Substrate and Ethereum's RPCs use positional (array) parameters, so in order to be compatible with both we need to make sure that our API is defined with positional paramters in mind. * Rename argument for eth_getBlockByNumber * Remove some unecessary Ok-wraps * Process client requests synchonously Before the refactoring the sync loop would wait until a client finished handling a request before issuing another one. This behaviour was inadvertently changed during the refactoring leading to race conditions. This commit makes sure that the previous behaviour is respected. * Reduce the errors that are considered a connection error * Only decode bridge contract once * Set genesis_config at RPC client startup * Fetch genesis hash in SubstrateRpcClient::new() * Move Decode error into SubstrateNodeError * Suppress warnings caused by `rpc_api!` * Implement From RpcError for String * Handle Substrate client initalization errors more gracefully * Remove match in favour of ? Co-authored-by: Svyatoslav Nikolsky --- relays/ethereum/Cargo.toml | 7 +- relays/ethereum/src/ethereum_client.rs | 595 ++++++++---------- .../ethereum/src/ethereum_deploy_contract.rs | 83 ++- relays/ethereum/src/ethereum_sync_loop.rs | 170 +++-- relays/ethereum/src/main.rs | 20 +- relays/ethereum/src/rpc.rs | 253 ++------ relays/ethereum/src/rpc_errors.rs | 71 ++- relays/ethereum/src/substrate_client.rs | 443 +++++-------- relays/ethereum/src/substrate_sync_loop.rs | 183 +++--- relays/ethereum/src/sync.rs | 4 +- relays/ethereum/src/sync_loop.rs | 243 +++---- 11 files changed, 840 insertions(+), 1232 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4bdcf930c1c4e..0505ff8bc1855 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -18,7 +18,6 @@ ethabi-derive = "12.0" ethereum-tx-sign = "3.0" futures = "0.3.5" hex = "0.4" -jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee.git", default-features = false, features = ["http"] } linked-hash-map = "0.5.3" log = "0.4.8" num-traits = "0.2" @@ -31,6 +30,12 @@ sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = { version = "0.12.0", default-features = false } +[dependencies.jsonrpsee] +git = "https://github.com/svyatonik/jsonrpsee.git" +branch = "shared-client-in-rpc-api" +default-features = false +features = ["http"] + # Substrate Based Dependencies [dependencies.frame-system] version = "2.0.0-rc3" diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 5dba31344b0a3..fcd627549a076 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -15,33 +15,30 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_types::{ - Address, Bytes, CallRequest, EthereumHeaderId, Header, Receipt, TransactionHash, H256, U256, U64, + Address, Bytes, CallRequest, EthereumHeaderId, Header, Receipt, SignedRawTx, TransactionHash, H256, U256, }; +use crate::rpc::{Ethereum, EthereumRpc}; +use crate::rpc_errors::{EthereumNodeError, RpcError}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::{HeaderId, MaybeConnectionError}; -use crate::{bail_on_arg_error, bail_on_error}; +use crate::sync_types::HeaderId; + +use async_trait::async_trait; use codec::{Decode, Encode}; use ethabi::FunctionOutputDecoder; -use jsonrpsee::common::Params; -use jsonrpsee::raw::{RawClient, RawClientError}; -use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; +use jsonrpsee::raw::RawClient; +use jsonrpsee::transport::http::HttpTransportClient; +use jsonrpsee::Client; use parity_crypto::publickey::KeyPair; -use serde::de::DeserializeOwned; -use serde_json::{from_value, to_value}; + use std::collections::HashSet; // to encode/decode contract calls ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json"); -/// Proof of hash serialization success. -const HASH_SERIALIZATION_PROOF: &'static str = "hash serialization never fails; qed"; -/// Proof of integer serialization success. -const INT_SERIALIZATION_PROOF: &'static str = "integer serialization never fails; qed"; -/// Proof of bool serialization success. -const BOOL_SERIALIZATION_PROOF: &'static str = "bool serialization never fails; qed"; +type Result = std::result::Result; /// Ethereum connection params. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct EthereumConnectionParams { /// Ethereum RPC host. pub host: String, @@ -86,381 +83,283 @@ impl Default for EthereumSigningParams { } } -/// Ethereum client type. -pub type Client = RawClient; - -/// All possible errors that can occur during interacting with Ethereum node. -#[derive(Debug)] -pub enum Error { - /// Request start failed. - StartRequestFailed(RequestError), - /// Error serializing request. - RequestSerialization(serde_json::Error), - /// Request not found (should never occur?). - RequestNotFound, - /// Failed to receive response. - ResponseRetrievalFailed(RawClientError), - /// Failed to parse response. - ResponseParseFailed(String), - /// We have received header with missing number and hash fields. - IncompleteHeader, - /// We have received receipt with missing gas_used field. - IncompleteReceipt, - /// Invalid Substrate block number received from Ethereum node. - InvalidSubstrateBlockNumber, +/// The client used to interact with an Ethereum node through RPC. +pub struct EthereumRpcClient { + client: Client, } -impl MaybeConnectionError for Error { - fn is_connection_error(&self) -> bool { - match *self { - Error::StartRequestFailed(_) | Error::ResponseRetrievalFailed(_) => true, - _ => false, - } +impl EthereumRpcClient { + /// Create a new Ethereum RPC Client. + pub fn new(params: EthereumConnectionParams) -> Self { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); + let raw_client = RawClient::new(transport); + let client: Client = raw_client.into(); + + Self { client } } } -/// Returns client that is able to call RPCs on Ethereum node. -pub fn client(params: EthereumConnectionParams) -> Client { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - RawClient::new(transport) -} +#[async_trait] +impl EthereumRpc for EthereumRpcClient { + async fn estimate_gas(&self, call_request: CallRequest) -> Result { + Ok(Ethereum::estimate_gas(&self.client, call_request).await?) + } -/// Retrieve best known block number from Ethereum node. -pub async fn best_block_number(client: Client) -> (Client, Result) { - let (client, result) = call_rpc::(client, "eth_blockNumber", Params::None).await; - (client, result.map(|x| x.as_u64())) -} + async fn best_block_number(&self) -> Result { + Ok(Ethereum::block_number(&self.client).await?.as_u64()) + } -/// Retrieve block header by its number from Ethereum node. -pub async fn header_by_number(client: Client, number: u64) -> (Client, Result) { - let (client, header) = call_rpc( - client, - "eth_getBlockByNumber", - Params::Array(vec![ - to_value(U64::from(number)).expect(INT_SERIALIZATION_PROOF), - to_value(false).expect(BOOL_SERIALIZATION_PROOF), - ]), - ) - .await; - ( - client, - header.and_then(|header: Header| { - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(Error::IncompleteHeader), - } - }), - ) -} + async fn header_by_number(&self, block_number: u64) -> Result

{ + let get_full_tx_objects = false; + let header = Ethereum::get_block_by_number(&self.client, block_number, get_full_tx_objects).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), + } + } -/// Retrieve block header by its hash from Ethereum node. -pub async fn header_by_hash(client: Client, hash: H256) -> (Client, Result) { - let (client, header) = call_rpc( - client, - "eth_getBlockByHash", - Params::Array(vec![ - to_value(hash).expect(HASH_SERIALIZATION_PROOF), - to_value(false).expect(BOOL_SERIALIZATION_PROOF), - ]), - ) - .await; - ( - client, - header.and_then(|header: Header| { - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(Error::IncompleteHeader), - } - }), - ) -} + async fn header_by_hash(&self, hash: H256) -> Result
{ + let header = Ethereum::get_block_by_hash(&self.client, hash).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), + } + } + + async fn transaction_receipt(&self, transaction_hash: H256) -> Result { + let receipt = Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?; -/// Retrieve transactions receipts for given block. -pub async fn transactions_receipts( - mut client: Client, - id: EthereumHeaderId, - transactions: Vec, -) -> (Client, Result<(EthereumHeaderId, Vec), Error>) { - let mut transactions_receipts = Vec::with_capacity(transactions.len()); - for transaction in transactions { - let (next_client, transaction_receipt) = bail_on_error!(transaction_receipt(client, transaction).await); - transactions_receipts.push(transaction_receipt); - client = next_client; + match receipt.gas_used { + Some(_) => Ok(receipt), + None => Err(RpcError::Ethereum(EthereumNodeError::IncompleteReceipt)), + } + } + + async fn account_nonce(&self, address: Address) -> Result { + Ok(Ethereum::get_transaction_count(&self.client, address).await?) + } + + async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result { + let transaction = Bytes(signed_raw_tx); + Ok(Ethereum::submit_transaction(&self.client, transaction).await?) + } + + async fn eth_call(&self, call_transaction: CallRequest) -> Result { + Ok(Ethereum::call(&self.client, call_transaction).await?) } - (client, Ok((id, transactions_receipts))) } -/// Retrieve transaction receipt by transaction hash. -async fn transaction_receipt(client: Client, hash: H256) -> (Client, Result) { - let (client, receipt) = call_rpc::( - client, - "eth_getTransactionReceipt", - Params::Array(vec![to_value(hash).expect(HASH_SERIALIZATION_PROOF)]), - ) - .await; - ( - client, - receipt.and_then(|receipt| match receipt.gas_used.is_some() { - true => Ok(receipt), - false => Err(Error::IncompleteReceipt), - }), - ) +/// A trait which contains methods that work by using multiple low-level RPCs, or more complicated +/// interactions involving, for example, an Ethereum contract. +#[async_trait] +pub trait EthereumHighLevelRpc: EthereumRpc { + /// Returns best Substrate block that PoA chain knows of. + async fn best_substrate_block(&self, contract_address: Address) -> Result; + + /// Returns true if Substrate header is known to Ethereum node. + async fn substrate_header_known( + &self, + contract_address: Address, + id: SubstrateHeaderId, + ) -> Result<(SubstrateHeaderId, bool)>; + + /// Submits Substrate headers to Ethereum contract. + async fn submit_substrate_headers( + &self, + params: EthereumSigningParams, + contract_address: Address, + headers: Vec, + ) -> Result>; + + /// Returns ids of incomplete Substrate headers. + async fn incomplete_substrate_headers(&self, contract_address: Address) -> Result>; + + /// Complete Substrate header. + async fn complete_substrate_header( + &self, + params: EthereumSigningParams, + contract_address: Address, + id: SubstrateHeaderId, + justification: GrandpaJustification, + ) -> Result; + + /// Submit ethereum transaction. + async fn submit_ethereum_transaction( + &self, + params: &EthereumSigningParams, + contract_address: Option
, + nonce: Option, + double_gas: bool, + encoded_call: Vec, + ) -> Result<()>; + + /// Retrieve transactions receipts for given block. + async fn transaction_receipts( + &self, + id: EthereumHeaderId, + transactions: Vec, + ) -> Result<(EthereumHeaderId, Vec)>; } -/// Returns best Substrate block that PoA chain knows of. -pub async fn best_substrate_block( - client: Client, - contract_address: Address, -) -> (Client, Result) { - let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); - let call_request = bail_on_arg_error!( - to_value(CallRequest { +#[async_trait] +impl EthereumHighLevelRpc for EthereumRpcClient { + async fn best_substrate_block(&self, contract_address: Address) -> Result { + let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); + let call_request = CallRequest { to: Some(contract_address), data: Some(encoded_call.into()), ..Default::default() - }) - .map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, call_result) = - bail_on_error!(call_rpc::(client, "eth_call", Params::Array(vec![call_request]),).await); - let (number, raw_hash) = match call_decoder.decode(&call_result.0) { - Ok((raw_number, raw_hash)) => (raw_number, raw_hash), - Err(error) => return (client, Err(Error::ResponseParseFailed(format!("{}", error)))), - }; - let hash = match SubstrateHash::decode(&mut &raw_hash[..]) { - Ok(hash) => hash, - Err(error) => return (client, Err(Error::ResponseParseFailed(format!("{}", error)))), - }; - - if number != number.low_u32().into() { - return (client, Err(Error::InvalidSubstrateBlockNumber)); - } + }; - (client, Ok(HeaderId(number.low_u32(), hash))) -} + let call_result = self.eth_call(call_request).await?; + let (number, raw_hash) = call_decoder.decode(&call_result.0)?; + let hash = SubstrateHash::decode(&mut &raw_hash[..])?; -/// Returns true if Substrate header is known to Ethereum node. -pub async fn substrate_header_known( - client: Client, - contract_address: Address, - id: SubstrateHeaderId, -) -> (Client, Result<(SubstrateHeaderId, bool), Error>) { - let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1); - let call_request = bail_on_arg_error!( - to_value(CallRequest { + if number != number.low_u32().into() { + return Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)); + } + + Ok(HeaderId(number.low_u32(), hash)) + } + + async fn substrate_header_known( + &self, + contract_address: Address, + id: SubstrateHeaderId, + ) -> Result<(SubstrateHeaderId, bool)> { + let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1); + let call_request = CallRequest { to: Some(contract_address), data: Some(encoded_call.into()), ..Default::default() - }) - .map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, call_result) = - bail_on_error!(call_rpc::(client, "eth_call", Params::Array(vec![call_request]),).await); - match call_decoder.decode(&call_result.0) { - Ok(is_known_block) => (client, Ok((id, is_known_block))), - Err(error) => (client, Err(Error::ResponseParseFailed(format!("{}", error)))), + }; + + let call_result = self.eth_call(call_request).await?; + let is_known_block = call_decoder.decode(&call_result.0)?; + + Ok((id, is_known_block)) } -} -/// Submits Substrate headers to Ethereum contract. -pub async fn submit_substrate_headers( - client: Client, - params: EthereumSigningParams, - contract_address: Address, - headers: Vec, -) -> (Client, Result, Error>) { - let (mut client, mut nonce) = - bail_on_error!(account_nonce(client, params.signer.address().as_fixed_bytes().into()).await); - - let ids = headers.iter().map(|header| header.id()).collect(); - for header in headers { - client = bail_on_error!( - submit_ethereum_transaction( - client, + async fn submit_substrate_headers( + &self, + params: EthereumSigningParams, + contract_address: Address, + headers: Vec, + ) -> Result> { + let address: Address = params.signer.address().as_fixed_bytes().into(); + let mut nonce = self.account_nonce(address).await?; + + let ids = headers.iter().map(|header| header.id()).collect(); + for header in headers { + self.submit_ethereum_transaction( ¶ms, Some(contract_address), Some(nonce), false, - bridge_contract::functions::import_header::encode_input(header.header().encode(),), + bridge_contract::functions::import_header::encode_input(header.header().encode()), ) - .await - ) - .0; + .await?; - nonce += 1.into(); - } + nonce += 1.into(); + } - (client, Ok(ids)) -} + Ok(ids) + } -/// Returns ids of incomplete Substrate headers. -pub async fn incomplete_substrate_headers( - client: Client, - contract_address: Address, -) -> (Client, Result, Error>) { - let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); - let call_request = bail_on_arg_error!( - to_value(CallRequest { + async fn incomplete_substrate_headers(&self, contract_address: Address) -> Result> { + let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); + let call_request = CallRequest { to: Some(contract_address), data: Some(encoded_call.into()), ..Default::default() - }) - .map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, call_result) = - bail_on_error!(call_rpc::(client, "eth_call", Params::Array(vec![call_request]),).await); - match call_decoder.decode(&call_result.0) { - Ok((incomplete_headers_numbers, incomplete_headers_hashes)) => ( - client, - Ok(incomplete_headers_numbers - .into_iter() - .zip(incomplete_headers_hashes) - .filter_map(|(number, hash)| { - if number != number.low_u32().into() { - return None; - } - - Some(HeaderId(number.low_u32(), hash)) - }) - .collect()), - ), - Err(error) => (client, Err(Error::ResponseParseFailed(format!("{}", error)))), - } -} + }; -/// Complete Substrate header. -pub async fn complete_substrate_header( - client: Client, - params: EthereumSigningParams, - contract_address: Address, - id: SubstrateHeaderId, - justification: GrandpaJustification, -) -> (Client, Result) { - let (client, _) = bail_on_error!( - submit_ethereum_transaction( - client, - ¶ms, - Some(contract_address), - None, - false, - bridge_contract::functions::import_finality_proof::encode_input(id.0, id.1, justification,), - ) - .await - ); - - (client, Ok(id)) -} + let call_result = self.eth_call(call_request).await?; -/// Deploy bridge contract. -pub async fn deploy_bridge_contract( - client: Client, - params: &EthereumSigningParams, - contract_code: Vec, - initial_header: Vec, - initial_set_id: u64, - initial_authorities: Vec, -) -> (Client, Result<(), Error>) { - submit_ethereum_transaction( - client, - params, - None, - None, - false, - bridge_contract::constructor(contract_code, initial_header, initial_set_id, initial_authorities), - ) - .await -} + // Q: Is is correct to call these "incomplete_ids"? + let (incomplete_headers_numbers, incomplete_headers_hashes) = call_decoder.decode(&call_result.0)?; + let incomplete_ids = incomplete_headers_numbers + .into_iter() + .zip(incomplete_headers_hashes) + .filter_map(|(number, hash)| { + if number != number.low_u32().into() { + return None; + } -/// Submit ethereum transaction. -async fn submit_ethereum_transaction( - client: Client, - params: &EthereumSigningParams, - contract_address: Option
, - nonce: Option, - double_gas: bool, - encoded_call: Vec, -) -> (Client, Result<(), Error>) { - let (client, nonce) = match nonce { - Some(nonce) => (client, nonce), - None => bail_on_error!(account_nonce(client, params.signer.address().as_fixed_bytes().into()).await), - }; - let (client, gas) = bail_on_error!( - estimate_gas( - client, - CallRequest { - to: contract_address, - data: Some(encoded_call.clone().into()), - ..Default::default() - } - ) - .await - ); - let raw_transaction = ethereum_tx_sign::RawTransaction { - nonce, - to: contract_address, - value: U256::zero(), - gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, - gas_price: params.gas_price, - data: encoded_call, + Some(HeaderId(number.low_u32(), hash)) + }) + .collect(); + + Ok(incomplete_ids) } - .sign(¶ms.signer.secret().as_fixed_bytes().into(), ¶ms.chain_id); - let transaction = bail_on_arg_error!( - to_value(Bytes(raw_transaction)).map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, _) = bail_on_error!( - call_rpc::(client, "eth_submitTransaction", Params::Array(vec![transaction])).await - ); - (client, Ok(())) -} -/// Get account nonce. -async fn account_nonce(client: Client, caller_address: Address) -> (Client, Result) { - let caller_address = bail_on_arg_error!( - to_value(caller_address).map_err(|e| Error::RequestSerialization(e)), - client - ); - call_rpc(client, "eth_getTransactionCount", Params::Array(vec![caller_address])).await -} + async fn complete_substrate_header( + &self, + params: EthereumSigningParams, + contract_address: Address, + id: SubstrateHeaderId, + justification: GrandpaJustification, + ) -> Result { + let _ = self + .submit_ethereum_transaction( + ¶ms, + Some(contract_address), + None, + false, + bridge_contract::functions::import_finality_proof::encode_input(id.0, id.1, justification), + ) + .await?; -/// Estimate gas usage for call. -async fn estimate_gas(client: Client, call_request: CallRequest) -> (Client, Result) { - let call_request = bail_on_arg_error!( - to_value(call_request).map_err(|e| Error::RequestSerialization(e)), - client - ); - call_rpc(client, "eth_estimateGas", Params::Array(vec![call_request])).await -} + Ok(id) + } -/// Calls RPC on Ethereum node. -async fn call_rpc( - mut client: Client, - method: &'static str, - params: Params, -) -> (Client, Result) { - async fn do_call_rpc( - client: &mut Client, - method: &'static str, - params: Params, - ) -> Result { - let request_id = client - .start_request(method, params) - .await - .map_err(Error::StartRequestFailed)?; - // WARN: if there'll be need for executing >1 request at a time, we should avoid - // calling request_by_id - let response = client - .request_by_id(request_id) - .ok_or(Error::RequestNotFound)? - .await - .map_err(Error::ResponseRetrievalFailed)?; - from_value(response).map_err(|e| Error::ResponseParseFailed(format!("{}", e))) + async fn submit_ethereum_transaction( + &self, + params: &EthereumSigningParams, + contract_address: Option
, + nonce: Option, + double_gas: bool, + encoded_call: Vec, + ) -> Result<()> { + let nonce = if let Some(n) = nonce { + n + } else { + let address: Address = params.signer.address().as_fixed_bytes().into(); + self.account_nonce(address).await? + }; + + let call_request = CallRequest { + to: contract_address, + data: Some(encoded_call.clone().into()), + ..Default::default() + }; + let gas = self.estimate_gas(call_request).await?; + + let raw_transaction = ethereum_tx_sign::RawTransaction { + nonce, + to: contract_address, + value: U256::zero(), + gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, + gas_price: params.gas_price, + data: encoded_call, + } + .sign(¶ms.signer.secret().as_fixed_bytes().into(), ¶ms.chain_id); + + let _ = self.submit_transaction(raw_transaction).await?; + Ok(()) } - let result = do_call_rpc(&mut client, method, params).await; - (client, result) + async fn transaction_receipts( + &self, + id: EthereumHeaderId, + transactions: Vec, + ) -> Result<(EthereumHeaderId, Vec)> { + let mut transaction_receipts = Vec::with_capacity(transactions.len()); + for transaction in transactions { + let transaction_receipt = self.transaction_receipt(transaction).await?; + transaction_receipts.push(transaction_receipt); + } + Ok((id, transaction_receipts)) + } } diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index eb9f66be924b0..0e573bda0634f 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -14,9 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_client::{self, EthereumConnectionParams, EthereumSigningParams}; -use crate::substrate_client::{self, SubstrateConnectionParams}; +use crate::ethereum_client::{ + bridge_contract, EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, +}; +use crate::rpc::SubstrateRpc; +use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader}; + use codec::{Decode, Encode}; use num_traits::Zero; @@ -59,18 +63,16 @@ pub fn run(params: EthereumDeployContractParams) { let mut local_pool = futures::executor::LocalPool::new(); let result = local_pool.run_until(async move { - let eth_client = ethereum_client::client(params.eth); - let sub_client = substrate_client::client(params.sub); + let eth_client = EthereumRpcClient::new(params.eth); + let sub_client = SubstrateRpcClient::new(params.sub).await?; - let (sub_client, initial_header) = prepare_initial_header(sub_client, params.sub_initial_header).await; - let (initial_header_hash, initial_header) = initial_header?; + let (initial_header_hash, initial_header) = prepare_initial_header(&sub_client, params.sub_initial_header).await?; let initial_set_id = params.sub_initial_authorities_set_id.unwrap_or(0); - let (_, initial_set) = prepare_initial_authorities_set( - sub_client, + let initial_set = prepare_initial_authorities_set( + &sub_client, initial_header_hash, params.sub_initial_authorities_set, - ).await; - let initial_set = initial_set?; + ).await?; log::info!( target: "bridge", @@ -81,14 +83,14 @@ pub fn run(params: EthereumDeployContractParams) { hex::encode(&initial_set), ); - ethereum_client::deploy_bridge_contract( - eth_client, + deploy_bridge_contract( + ð_client, ¶ms.eth_sign, params.eth_contract_code, initial_header, initial_set_id, initial_set, - ).await.1.map_err(|error| format!("Error deploying contract: {:?}", error)) + ).await }); if let Err(error) = result { @@ -98,39 +100,54 @@ pub fn run(params: EthereumDeployContractParams) { /// Prepare initial header. async fn prepare_initial_header( - sub_client: substrate_client::Client, + sub_client: &SubstrateRpcClient, sub_initial_header: Option>, -) -> (substrate_client::Client, Result<(SubstrateHash, Vec), String>) { +) -> Result<(SubstrateHash, Vec), String> { match sub_initial_header { Some(raw_initial_header) => match SubstrateHeader::decode(&mut &raw_initial_header[..]) { - Ok(initial_header) => (sub_client, Ok((initial_header.hash(), raw_initial_header))), - Err(error) => (sub_client, Err(format!("Error decoding initial header: {}", error))), + Ok(initial_header) => Ok((initial_header.hash(), raw_initial_header)), + Err(error) => Err(format!("Error decoding initial header: {}", error)), }, None => { - let (sub_client, initial_header) = substrate_client::header_by_number(sub_client, Zero::zero()).await; - ( - sub_client, - initial_header - .map(|header| (header.hash(), header.encode())) - .map_err(|error| format!("Error reading Substrate genesis header: {:?}", error)), - ) + let initial_header = sub_client.header_by_number(Zero::zero()).await; + initial_header + .map(|header| (header.hash(), header.encode())) + .map_err(|error| format!("Error reading Substrate genesis header: {:?}", error)) } } } /// Prepare initial GRANDPA authorities set. async fn prepare_initial_authorities_set( - sub_client: substrate_client::Client, + sub_client: &SubstrateRpcClient, sub_initial_header_hash: SubstrateHash, sub_initial_authorities_set: Option>, -) -> (substrate_client::Client, Result, String>) { - let (sub_client, initial_authorities_set) = match sub_initial_authorities_set { - Some(initial_authorities_set) => (sub_client, Ok(initial_authorities_set)), - None => substrate_client::grandpa_authorities_set(sub_client, sub_initial_header_hash).await, +) -> Result, String> { + let initial_authorities_set = match sub_initial_authorities_set { + Some(initial_authorities_set) => Ok(initial_authorities_set), + None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await, }; - ( - sub_client, - initial_authorities_set.map_err(|error| format!("Error reading GRANDPA authorities set: {:?}", error)), - ) + initial_authorities_set.map_err(|error| format!("Error reading GRANDPA authorities set: {:?}", error)) +} + +/// Deploy bridge contract to Ethereum chain. +async fn deploy_bridge_contract( + eth_client: &EthereumRpcClient, + params: &EthereumSigningParams, + contract_code: Vec, + initial_header: Vec, + initial_set_id: u64, + initial_authorities: Vec, +) -> Result<(), String> { + eth_client + .submit_ethereum_transaction( + params, + None, + None, + false, + bridge_contract::constructor(contract_code, initial_header, initial_set_id, initial_authorities), + ) + .await + .map_err(|error| format!("Error deploying contract: {:?}", error)) } diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 95f415a753228..26804d4de0cb7 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -16,17 +16,23 @@ //! Ethereum PoA -> Substrate synchronization. -use crate::ethereum_client::{self, EthereumConnectionParams}; +use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient}; use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; -use crate::substrate_client::{self, SubstrateConnectionParams, SubstrateSigningParams}; +use crate::rpc::{EthereumRpc, SubstrateRpc}; +use crate::rpc_errors::RpcError; +use crate::substrate_client::{ + SubmitEthereumHeaders, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, +}; +use crate::substrate_types::into_substrate_ethereum_header; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; -use crate::sync_loop::{OwnedSourceFutureOutput, OwnedTargetFutureOutput, SourceClient, TargetClient}; +use crate::sync_loop::{SourceClient, TargetClient}; +use crate::sync_types::SourceHeader; use async_trait::async_trait; -use futures::future::FutureExt; -use std::{collections::HashSet, time::Duration}; use web3::types::H256; +use std::{collections::HashSet, time::Duration}; + /// Interval at which we check new Ethereum headers when we are synced/almost synced. const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); /// Interval at which we check new Substrate blocks. @@ -45,6 +51,7 @@ const MAX_SUBMITTED_HEADERS: usize = 128; const PRUNE_DEPTH: u32 = 4096; /// Ethereum synchronization parameters. +#[derive(Clone)] pub struct EthereumSyncParams { /// Ethereum connection params. pub eth: EthereumConnectionParams, @@ -77,159 +84,124 @@ impl Default for EthereumSyncParams { /// Ethereum client as headers source. struct EthereumHeadersSource { /// Ethereum node client. - client: ethereum_client::Client, + client: EthereumRpcClient, } -type EthereumFutureOutput = OwnedSourceFutureOutput; +impl EthereumHeadersSource { + fn new(client: EthereumRpcClient) -> Self { + Self { client } + } +} #[async_trait] impl SourceClient for EthereumHeadersSource { - type Error = ethereum_client::Error; + type Error = RpcError; - async fn best_block_number(self) -> EthereumFutureOutput { - ethereum_client::best_block_number(self.client) - .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .await + async fn best_block_number(&self) -> Result { + self.client.best_block_number().await } - async fn header_by_hash(self, hash: H256) -> EthereumFutureOutput
{ - ethereum_client::header_by_hash(self.client, hash) - .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .await + async fn header_by_hash(&self, hash: H256) -> Result { + self.client.header_by_hash(hash).await } - async fn header_by_number(self, number: u64) -> EthereumFutureOutput
{ - ethereum_client::header_by_number(self.client, number) - .map(|(client, result)| (EthereumHeadersSource { client }, result)) - .await + async fn header_by_number(&self, number: u64) -> Result { + self.client.header_by_number(number).await } - async fn header_completion(self, id: EthereumHeaderId) -> EthereumFutureOutput<(EthereumHeaderId, Option<()>)> { - (self, Ok((id, None))) + async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), Self::Error> { + Ok((id, None)) } async fn header_extra( - self, + &self, id: EthereumHeaderId, header: QueuedEthereumHeader, - ) -> EthereumFutureOutput<(EthereumHeaderId, Vec)> { - ethereum_client::transactions_receipts(self.client, id, header.header().transactions.clone()) - .map(|(client, result)| (EthereumHeadersSource { client }, result)) + ) -> Result<(EthereumHeaderId, Vec), Self::Error> { + self.client + .transaction_receipts(id, header.header().transactions.clone()) .await } } -/// Substrate client as Ethereum headers target. struct SubstrateHeadersTarget { /// Substrate node client. - client: substrate_client::Client, + client: SubstrateRpcClient, /// Whether we want to submit signed (true), or unsigned (false) transactions. sign_transactions: bool, /// Substrate signing params. sign_params: SubstrateSigningParams, } -type SubstrateFutureOutput = OwnedTargetFutureOutput; +impl SubstrateHeadersTarget { + fn new(client: SubstrateRpcClient, sign_transactions: bool, sign_params: SubstrateSigningParams) -> Self { + Self { + client, + sign_transactions, + sign_params, + } + } +} #[async_trait] impl TargetClient for SubstrateHeadersTarget { - type Error = substrate_client::Error; - - async fn best_header_id(self) -> SubstrateFutureOutput { - let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); - substrate_client::best_ethereum_block(self.client) - .map(move |(client, result)| { - ( - SubstrateHeadersTarget { - client, - sign_transactions, - sign_params, - }, - result, - ) - }) - .await + type Error = RpcError; + + async fn best_header_id(&self) -> Result { + self.client.best_ethereum_block().await } - async fn is_known_header(self, id: EthereumHeaderId) -> SubstrateFutureOutput<(EthereumHeaderId, bool)> { - let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); - substrate_client::ethereum_header_known(self.client, id) - .map(move |(client, result)| { - ( - SubstrateHeadersTarget { - client, - sign_transactions, - sign_params, - }, - result, - ) - }) - .await + async fn is_known_header(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, bool), Self::Error> { + Ok((id, self.client.ethereum_header_known(id).await?)) } - async fn submit_headers(self, headers: Vec) -> SubstrateFutureOutput> { - let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); - substrate_client::submit_ethereum_headers(self.client, sign_params.clone(), headers, sign_transactions) - .map(move |(client, result)| { - ( - SubstrateHeadersTarget { - client, - sign_transactions, - sign_params, - }, - result, - ) - }) + async fn submit_headers(&self, headers: Vec) -> Result, Self::Error> { + let (sign_params, sign_transactions) = (self.sign_params.clone(), self.sign_transactions.clone()); + self.client + .submit_ethereum_headers(sign_params, headers, sign_transactions) .await } - async fn incomplete_headers_ids(self) -> SubstrateFutureOutput> { - (self, Ok(HashSet::new())) + async fn incomplete_headers_ids(&self) -> Result, Self::Error> { + Ok(HashSet::new()) } - async fn complete_header(self, id: EthereumHeaderId, _completion: ()) -> SubstrateFutureOutput { - (self, Ok(id)) + async fn complete_header(&self, id: EthereumHeaderId, _completion: ()) -> Result { + Ok(id) } - async fn requires_extra(self, header: QueuedEthereumHeader) -> SubstrateFutureOutput<(EthereumHeaderId, bool)> { + async fn requires_extra(&self, header: QueuedEthereumHeader) -> Result<(EthereumHeaderId, bool), Self::Error> { // we can minimize number of receipts_check calls by checking header // logs bloom here, but it may give us false positives (when authorities // source is contract, we never need any logs) - let (sign_transactions, sign_params) = (self.sign_transactions, self.sign_params); - substrate_client::ethereum_receipts_required(self.client, header) - .map(move |(client, result)| { - ( - SubstrateHeadersTarget { - client, - sign_transactions, - sign_params, - }, - result, - ) - }) - .await + let id = header.header().id(); + let sub_eth_header = into_substrate_ethereum_header(header.header()); + Ok((id, self.client.ethereum_receipts_required(sub_eth_header).await?)) } } /// Run Ethereum headers synchronization. -pub fn run(params: EthereumSyncParams) { - let eth_client = ethereum_client::client(params.eth); - let sub_client = substrate_client::client(params.sub); +pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { + let sub_params = params.clone(); + + let eth_client = EthereumRpcClient::new(params.eth); + let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params.sub).await })?; let sign_sub_transactions = match params.sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, TargetTransactionMode::Unsigned => false, }; + let source = EthereumHeadersSource::new(eth_client); + let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, params.sub_sign); + crate::sync_loop::run( - EthereumHeadersSource { client: eth_client }, + source, ETHEREUM_TICK_INTERVAL, - SubstrateHeadersTarget { - client: sub_client, - sign_transactions: sign_sub_transactions, - sign_params: params.sub_sign, - }, + target, SUBSTRATE_TICK_INTERVAL, params.sync_params, ); + + Ok(()) } diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index c17582e23cb0c..5786ff23dbfce 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -46,28 +46,38 @@ fn main() { let matches = clap::App::from_yaml(yaml).get_matches(); match matches.subcommand() { ("eth-to-sub", Some(eth_to_sub_matches)) => { - ethereum_sync_loop::run(match ethereum_sync_params(ð_to_sub_matches) { + if ethereum_sync_loop::run(match ethereum_sync_params(ð_to_sub_matches) { Ok(ethereum_sync_params) => ethereum_sync_params, Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); return; } - }); + }) + .is_err() + { + log::error!(target: "bridge", "Unable to get Substrate genesis block for Ethereum sync."); + return; + }; } ("sub-to-eth", Some(sub_to_eth_matches)) => { - substrate_sync_loop::run(match substrate_sync_params(&sub_to_eth_matches) { + if substrate_sync_loop::run(match substrate_sync_params(&sub_to_eth_matches) { Ok(substrate_sync_params) => substrate_sync_params, Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); return; } - }); + }) + .is_err() + { + log::error!(target: "bridge", "Unable to get Substrate genesis block for Substrate sync."); + return; + }; } ("eth-deploy-contract", Some(eth_deploy_matches)) => { ethereum_deploy_contract::run(match ethereum_deploy_contract_params(ð_deploy_matches) { Ok(ethereum_deploy_matches) => ethereum_deploy_matches, Err(err) => { - log::error!(target: "bridge", "Error parsing parameters: {}", err); + log::error!(target: "bridge", "Error during contract deployment: {}", err); return; } }); diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs index 70c775a268fbe..1dc253406c080 100644 --- a/relays/ethereum/src/rpc.rs +++ b/relays/ethereum/src/rpc.rs @@ -16,69 +16,61 @@ //! RPC Module +#![warn(missing_docs)] + +// The compiler doesn't think we're using the +// code from rpc_api! #![allow(dead_code)] #![allow(unused_variables)] -#[warn(missing_docs)] use std::result; -use crate::ethereum_client::EthereumConnectionParams; use crate::ethereum_types::{ Address as EthAddress, Bytes, CallRequest, EthereumHeaderId, Header as EthereumHeader, Receipt, SignedRawTx, TransactionHash as EthereumTxHash, H256, U256, U64, }; -use crate::rpc_errors::{EthereumNodeError, RpcError}; -use crate::substrate_client::SubstrateConnectionParams; +use crate::rpc_errors::RpcError; use crate::substrate_types::{ Hash as SubstrateHash, Header as SubstrateHeader, Number as SubBlockNumber, SignedBlock as SubstrateBlock, }; -use crate::sync_types::HeaderId; use async_trait::async_trait; -use codec::{Decode, Encode}; -use jsonrpsee::raw::client::RawClient; -use jsonrpsee::transport::http::HttpTransportClient; use sp_bridge_eth_poa::Header as SubstrateEthereumHeader; -const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; -const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; -const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; -const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; - type Result = result::Result; type GrandpaAuthorityList = Vec; jsonrpsee::rpc_api! { - Ethereum { - #[rpc(method = "eth_estimateGas")] + pub(crate) Ethereum { + #[rpc(method = "eth_estimateGas", positional_params)] fn estimate_gas(call_request: CallRequest) -> U256; - #[rpc(method = "eth_blockNumber")] + #[rpc(method = "eth_blockNumber", positional_params)] fn block_number() -> U64; - #[rpc(method = "eth_getBlockByNumber")] - fn get_block_by_number(block_number: u64) -> EthereumHeader; - #[rpc(method = "eth_getBlockByHash")] + #[rpc(method = "eth_getBlockByNumber", positional_params)] + fn get_block_by_number(block_number: U64, full_tx_objs: bool) -> EthereumHeader; + #[rpc(method = "eth_getBlockByHash", positional_params)] fn get_block_by_hash(hash: H256) -> EthereumHeader; - #[rpc(method = "eth_getTransactionReceipt")] + #[rpc(method = "eth_getTransactionReceipt", positional_params)] fn get_transaction_receipt(transaction_hash: H256) -> Receipt; - #[rpc(method = "eth_getTransactionCount")] + #[rpc(method = "eth_getTransactionCount", positional_params)] fn get_transaction_count(address: EthAddress) -> U256; - #[rpc(method = "eth_submitTransaction")] + #[rpc(method = "eth_submitTransaction", positional_params)] fn submit_transaction(transaction: Bytes) -> EthereumTxHash; - #[rpc(method = "eth_call")] + #[rpc(method = "eth_call", positional_params)] fn call(transaction_call: CallRequest) -> Bytes; } - Substrate { - #[rpc(method = "chain_getHeader")] + pub(crate) Substrate { + #[rpc(method = "chain_getHeader", positional_params)] fn chain_get_header(block_hash: Option) -> SubstrateHeader; - #[rpc(method = "chain_getBlock")] + #[rpc(method = "chain_getBlock", positional_params)] fn chain_get_block(block_hash: Option) -> SubstrateBlock; - #[rpc(method = "chain_getBlockHash")] + #[rpc(method = "chain_getBlockHash", positional_params)] fn chain_get_block_hash(block_number: Option) -> SubstrateHash; - #[rpc(method = "system_accountNextIndex")] + #[rpc(method = "system_accountNextIndex", positional_params)] fn system_account_next_index(account_id: node_primitives::AccountId) -> node_primitives::Index; - #[rpc(method = "author_submitExtrinsic")] + #[rpc(method = "author_submitExtrinsic", positional_params)] fn author_submit_extrinsic(extrinsic: Bytes) -> SubstrateHash; - #[rpc(method = "state_call")] + #[rpc(method = "state_call", positional_params)] fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; } } @@ -87,215 +79,52 @@ jsonrpsee::rpc_api! { #[async_trait] pub trait EthereumRpc { /// Estimate gas usage for the given call. - async fn estimate_gas(&mut self, call_request: CallRequest) -> Result; + async fn estimate_gas(&self, call_request: CallRequest) -> Result; /// Retrieve number of the best known block from the Ethereum node. - async fn best_block_number(&mut self) -> Result; + async fn best_block_number(&self) -> Result; /// Retrieve block header by its number from Ethereum node. - async fn header_by_number(&mut self, block_number: u64) -> Result; + async fn header_by_number(&self, block_number: u64) -> Result; /// Retrieve block header by its hash from Ethereum node. - async fn header_by_hash(&mut self, hash: H256) -> Result; + async fn header_by_hash(&self, hash: H256) -> Result; /// Retrieve transaction receipt by transaction hash. - async fn transaction_receipt(&mut self, transaction_hash: H256) -> Result; + async fn transaction_receipt(&self, transaction_hash: H256) -> Result; /// Get the nonce of the given account. - async fn account_nonce(&mut self, address: EthAddress) -> Result; + async fn account_nonce(&self, address: EthAddress) -> Result; /// Submit an Ethereum transaction. /// /// The transaction must already be signed before sending it through this method. - async fn submit_transaction(&mut self, signed_raw_tx: SignedRawTx) -> Result; + async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result; /// Submit a call to an Ethereum smart contract. - async fn eth_call(&mut self, call_transaction: CallRequest) -> Result; -} - -/// The client used to interact with an Ethereum node through RPC. -pub struct EthereumRpcClient { - client: RawClient, -} - -impl EthereumRpcClient { - /// Create a new Ethereum RPC Client. - pub fn new(params: EthereumConnectionParams) -> Self { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - let client = RawClient::new(transport); - - Self { client } - } -} - -#[async_trait] -impl EthereumRpc for EthereumRpcClient { - async fn estimate_gas(&mut self, call_request: CallRequest) -> Result { - Ok(Ethereum::estimate_gas(&mut self.client, call_request).await?) - } - - async fn best_block_number(&mut self) -> Result { - Ok(Ethereum::block_number(&mut self.client).await?.as_u64()) - } - - async fn header_by_number(&mut self, block_number: u64) -> Result { - let header = Ethereum::get_block_by_number(&mut self.client, block_number).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), - } - } - - async fn header_by_hash(&mut self, hash: H256) -> Result { - let header = Ethereum::get_block_by_hash(&mut self.client, hash).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), - } - } - - async fn transaction_receipt(&mut self, transaction_hash: H256) -> Result { - let receipt = Ethereum::get_transaction_receipt(&mut self.client, transaction_hash).await?; - - match receipt.gas_used { - Some(_) => Ok(receipt), - None => Err(RpcError::Ethereum(EthereumNodeError::IncompleteReceipt)), - } - } - - async fn account_nonce(&mut self, address: EthAddress) -> Result { - Ok(Ethereum::get_transaction_count(&mut self.client, address).await?) - } - - async fn submit_transaction(&mut self, signed_raw_tx: SignedRawTx) -> Result { - let transaction = Bytes(signed_raw_tx); - Ok(Ethereum::submit_transaction(&mut self.client, transaction).await?) - } - - async fn eth_call(&mut self, call_transaction: CallRequest) -> Result { - Ok(Ethereum::call(&mut self.client, call_transaction).await?) - } + async fn eth_call(&self, call_transaction: CallRequest) -> Result; } /// The API for the supported Substrate RPC methods. #[async_trait] pub trait SubstrateRpc { /// Returns the best Substrate header. - async fn best_header(&mut self) -> Result; + async fn best_header(&self) -> Result; /// Get a Substrate block from its hash. - async fn get_block(&mut self, block_hash: Option) -> Result; + async fn get_block(&self, block_hash: Option) -> Result; /// Get a Substrate header by its hash. - async fn header_by_hash(&mut self, hash: SubstrateHash) -> Result; + async fn header_by_hash(&self, hash: SubstrateHash) -> Result; /// Get a Substrate block hash by its number. - async fn block_hash_by_number(&mut self, number: SubBlockNumber) -> Result; + async fn block_hash_by_number(&self, number: SubBlockNumber) -> Result; /// Get a Substrate header by its number. - async fn header_by_number(&mut self, block_number: SubBlockNumber) -> Result; + async fn header_by_number(&self, block_number: SubBlockNumber) -> Result; /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. - async fn next_account_index(&mut self, account: node_primitives::AccountId) -> Result; + async fn next_account_index(&self, account: node_primitives::AccountId) -> Result; /// Returns best Ethereum block that Substrate runtime knows of. - async fn best_ethereum_block(&mut self) -> Result; + async fn best_ethereum_block(&self) -> Result; /// Returns whether or not transactions receipts are required for Ethereum header submission. - async fn ethereum_receipts_required(&mut self, header: SubstrateEthereumHeader) -> Result; + async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> Result; /// Returns whether or not the given Ethereum header is known to the Substrate runtime. - async fn ethereum_header_known(&mut self, header_id: EthereumHeaderId) -> Result; + async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> Result; /// Submit an extrinsic for inclusion in a block. /// /// Note: The given transaction does not need be SCALE encoded beforehand. - async fn submit_extrinsic(&mut self, transaction: Bytes) -> Result; + async fn submit_extrinsic(&self, transaction: Bytes) -> Result; /// Get the GRANDPA authority set at given block. - async fn grandpa_authorities_set(&mut self, block: SubstrateHash) -> Result; -} - -/// The client used to interact with a Substrate node through RPC. -pub struct SubstrateRpcClient { - client: RawClient, -} - -impl SubstrateRpcClient { - /// Create a new Substrate RPC Client. - pub fn new(params: SubstrateConnectionParams) -> Self { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - let client = RawClient::new(transport); - - Self { client } - } -} - -#[async_trait] -impl SubstrateRpc for SubstrateRpcClient { - async fn best_header(&mut self) -> Result { - Ok(Substrate::chain_get_header(&mut self.client, None).await?) - } - - async fn get_block(&mut self, block_hash: Option) -> Result { - Ok(Substrate::chain_get_block(&mut self.client, block_hash).await?) - } - - async fn header_by_hash(&mut self, block_hash: SubstrateHash) -> Result { - Ok(Substrate::chain_get_header(&mut self.client, block_hash).await?) - } - - async fn block_hash_by_number(&mut self, number: SubBlockNumber) -> Result { - Ok(Substrate::chain_get_block_hash(&mut self.client, number).await?) - } - - async fn header_by_number(&mut self, block_number: SubBlockNumber) -> Result { - let block_hash = Self::block_hash_by_number(self, block_number).await?; - Ok(Self::header_by_hash(self, block_hash).await?) - } - - async fn next_account_index(&mut self, account: node_primitives::AccountId) -> Result { - Ok(Substrate::system_account_next_index(&mut self.client, account).await?) - } - - async fn best_ethereum_block(&mut self) -> Result { - let call = ETH_API_BEST_BLOCK.to_string(); - let data = Bytes("0x".into()); - - let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; - let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; - - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); - Ok(best_header_id) - } - - async fn ethereum_receipts_required(&mut self, header: SubstrateEthereumHeader) -> Result { - let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); - let data = Bytes(header.encode()); - - let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; - let receipts_required: bool = Decode::decode(&mut &encoded_response.0[..])?; - - // Gonna make it the responsibility of the caller to return (receipts_required, id) - Ok(receipts_required) - } - - // The Substrate module could prune old headers. So this function could return false even - // if header is synced. And we'll mark corresponding Ethereum header as Orphan. - // - // But when we read the best header from Substrate next time, we will know that - // there's a better header. This Orphan will either be marked as synced, or - // eventually pruned. - async fn ethereum_header_known(&mut self, header_id: EthereumHeaderId) -> Result { - let call = ETH_API_IS_KNOWN_BLOCK.to_string(); - let data = Bytes(header_id.1.encode()); - - let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; - let is_known_block: bool = Decode::decode(&mut &encoded_response.0[..])?; - - // Gonna make it the responsibility of the caller to return (is_known_block, id) - Ok(is_known_block) - } - - async fn submit_extrinsic(&mut self, transaction: Bytes) -> Result { - let encoded_transaction = Bytes(transaction.0.encode()); - Ok(Substrate::author_submit_extrinsic(&mut self.client, encoded_transaction).await?) - } - - async fn grandpa_authorities_set(&mut self, block: SubstrateHash) -> Result { - let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); - let data = Bytes(block.as_bytes().to_vec()); - - let encoded_response = Substrate::state_call(&mut self.client, call, data, None).await?; - let authority_list = encoded_response.0; - - Ok(authority_list) - } + async fn grandpa_authorities_set(&self, block: SubstrateHash) -> Result; } diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 86758b559920b..34295df756d6d 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -14,14 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -#![allow(dead_code)] +use crate::sync_types::MaybeConnectionError; -use jsonrpsee::raw::client::RawClientError; -use jsonrpsee::transport::http::RequestError; +use jsonrpsee::client::RequestError; use serde_json; -type RpcHttpError = RawClientError; - /// Contains common errors that can occur when /// interacting with a Substrate or Ethereum node /// through RPC. @@ -35,9 +32,18 @@ pub enum RpcError { Substrate(SubstrateNodeError), /// An error that can occur when making an HTTP request to /// an JSON-RPC client. - Request(RpcHttpError), - /// The response from the client could not be SCALE decoded. - Decoding(codec::Error), + Request(RequestError), +} + +impl From for String { + fn from(err: RpcError) -> Self { + match err { + RpcError::Serialization(e) => e.to_string(), + RpcError::Ethereum(e) => e.to_string(), + RpcError::Substrate(e) => e.to_string(), + RpcError::Request(e) => e.to_string(), + } + } } impl From for RpcError { @@ -58,15 +64,30 @@ impl From for RpcError { } } -impl From for RpcError { - fn from(err: RpcHttpError) -> Self { +impl From for RpcError { + fn from(err: RequestError) -> Self { Self::Request(err) } } +impl From for RpcError { + fn from(err: ethabi::Error) -> Self { + Self::Ethereum(EthereumNodeError::ResponseParseFailed(format!("{}", err))) + } +} + +impl MaybeConnectionError for RpcError { + fn is_connection_error(&self) -> bool { + match *self { + RpcError::Request(RequestError::TransportError(_)) => true, + _ => false, + } + } +} + impl From for RpcError { fn from(err: codec::Error) -> Self { - Self::Decoding(err) + Self::Substrate(SubstrateNodeError::Decoding(err)) } } @@ -85,14 +106,30 @@ pub enum EthereumNodeError { InvalidSubstrateBlockNumber, } +impl ToString for EthereumNodeError { + fn to_string(&self) -> String { + match self { + Self::ResponseParseFailed(e) => e, + Self::IncompleteHeader => "Incomplete Ethereum Header Received", + Self::IncompleteReceipt => "Incomplete Ethereum Receipt Recieved", + Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node", + } + .to_string() + } +} + /// Errors that can occur only when interacting with /// a Substrate node through RPC. #[derive(Debug)] pub enum SubstrateNodeError { - /// Request start failed. - StartRequestFailed(RequestError), - /// Error serializing request. - RequestSerialization(serde_json::Error), - /// Failed to parse response. - ResponseParseFailed, + /// The response from the client could not be SCALE decoded. + Decoding(codec::Error), +} + +impl ToString for SubstrateNodeError { + fn to_string(&self) -> String { + match self { + Self::Decoding(e) => e.what().to_string(), + } + } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index e7067cbda3a0d..cd77545b266bd 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -15,24 +15,34 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256}; +use crate::rpc::{Substrate, SubstrateRpc}; +use crate::rpc_errors::RpcError; use crate::substrate_types::{ - into_substrate_ethereum_header, into_substrate_ethereum_receipts, GrandpaJustification, Hash, - Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock, SubstrateHeaderId, + into_substrate_ethereum_header, into_substrate_ethereum_receipts, Hash, Header as SubstrateHeader, Number, + SignedBlock as SignedSubstrateBlock, }; -use crate::sync_types::{HeaderId, MaybeConnectionError, SourceHeader}; -use crate::{bail_on_arg_error, bail_on_error}; +use crate::sync_types::HeaderId; + +use async_trait::async_trait; use codec::{Decode, Encode}; -use jsonrpsee::common::Params; -use jsonrpsee::raw::{RawClient, RawClientError}; -use jsonrpsee::transport::http::{HttpTransportClient, RequestError}; +use jsonrpsee::raw::RawClient; +use jsonrpsee::transport::http::HttpTransportClient; +use jsonrpsee::Client; use num_traits::Zero; -use serde::de::DeserializeOwned; -use serde_json::{from_value, to_value, Value}; +use sp_bridge_eth_poa::Header as SubstrateEthereumHeader; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; +const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; +const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; +const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; +const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; + +type Result = std::result::Result; +type GrandpaAuthorityList = Vec; + /// Substrate connection params. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SubstrateConnectionParams { /// Substrate RPC host. pub host: String, @@ -71,301 +81,177 @@ impl Default for SubstrateSigningParams { } /// Substrate client type. -pub struct Client { +pub struct SubstrateRpcClient { /// Substrate RPC client. - rpc_client: RawClient, + client: Client, /// Genesis block hash. - genesis_hash: Option, + genesis_hash: H256, } -/// All possible errors that can occur during interacting with Ethereum node. -#[derive(Debug)] -pub enum Error { - /// Request start failed. - StartRequestFailed(RequestError), - /// Error serializing request. - RequestSerialization(serde_json::Error), - /// Request not found (should never occur?). - RequestNotFound, - /// Failed to receive response. - ResponseRetrievalFailed(RawClientError), - /// Failed to parse response. - ResponseParseFailed, -} +impl SubstrateRpcClient { + /// Returns client that is able to call RPCs on Substrate node. + pub async fn new(params: SubstrateConnectionParams) -> Result { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); + let raw_client = RawClient::new(transport); + let client: Client = raw_client.into(); -impl MaybeConnectionError for Error { - fn is_connection_error(&self) -> bool { - match *self { - Error::StartRequestFailed(_) | Error::ResponseRetrievalFailed(_) => true, - _ => false, - } + let number: Number = Zero::zero(); + let genesis_hash = Substrate::chain_get_block_hash(&client, number).await?; + + Ok(Self { client, genesis_hash }) } } -/// Returns client that is able to call RPCs on Substrate node. -pub fn client(params: SubstrateConnectionParams) -> Client { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - Client { - rpc_client: RawClient::new(transport), - genesis_hash: None, +#[async_trait] +impl SubstrateRpc for SubstrateRpcClient { + async fn best_header(&self) -> Result { + Ok(Substrate::chain_get_header(&self.client, None).await?) } -} -/// Returns best Substrate header. -pub async fn best_header(client: Client) -> (Client, Result) { - call_rpc(client, "chain_getHeader", Params::None, rpc_returns_value).await -} + async fn get_block(&self, block_hash: Option) -> Result { + Ok(Substrate::chain_get_block(&self.client, block_hash).await?) + } -/// Returns Substrate header by hash. -pub async fn header_by_hash(client: Client, hash: Hash) -> (Client, Result) { - let hash = bail_on_arg_error!(to_value(hash).map_err(|e| Error::RequestSerialization(e)), client); - call_rpc(client, "chain_getHeader", Params::Array(vec![hash]), rpc_returns_value).await -} + async fn header_by_hash(&self, block_hash: Hash) -> Result { + Ok(Substrate::chain_get_header(&self.client, block_hash).await?) + } -/// Returns Substrate header by number. -pub async fn header_by_number(client: Client, number: Number) -> (Client, Result) { - let (client, hash) = bail_on_error!(block_hash_by_number(client, number).await); - header_by_hash(client, hash).await -} + async fn block_hash_by_number(&self, number: Number) -> Result { + Ok(Substrate::chain_get_block_hash(&self.client, number).await?) + } -/// Returns best Ethereum block that Substrate runtime knows of. -pub async fn best_ethereum_block(client: Client) -> (Client, Result) { - let (client, result) = call_rpc( - client, - "state_call", - Params::Array(vec![ - serde_json::Value::String("EthereumHeadersApi_best_block".into()), - serde_json::Value::String("0x".into()), - ]), - rpc_returns_encoded_value, - ) - .await; - (client, result.map(|(num, hash)| HeaderId(num, hash))) -} + async fn header_by_number(&self, block_number: Number) -> Result { + let block_hash = Self::block_hash_by_number(self, block_number).await?; + Ok(Self::header_by_hash(self, block_hash).await?) + } -/// Returns true if transactions receipts are required for Ethereum header submission. -pub async fn ethereum_receipts_required( - client: Client, - header: QueuedEthereumHeader, -) -> (Client, Result<(EthereumHeaderId, bool), Error>) { - let id = header.header().id(); - let header = into_substrate_ethereum_header(header.header()); - let encoded_header = bail_on_arg_error!( - to_value(Bytes(header.encode())).map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, receipts_required) = call_rpc( - client, - "state_call", - Params::Array(vec![ - serde_json::Value::String("EthereumHeadersApi_is_import_requires_receipts".into()), - encoded_header, - ]), - rpc_returns_encoded_value, - ) - .await; - ( - client, - receipts_required.map(|receipts_required| (id, receipts_required)), - ) -} + async fn next_account_index(&self, account: node_primitives::AccountId) -> Result { + Ok(Substrate::system_account_next_index(&self.client, account).await?) + } -/// Returns true if Ethereum header is known to Substrate runtime. -pub async fn ethereum_header_known( - client: Client, - id: EthereumHeaderId, -) -> (Client, Result<(EthereumHeaderId, bool), Error>) { - // Substrate module could prune old headers. So this fn could return false even + async fn best_ethereum_block(&self) -> Result { + let call = ETH_API_BEST_BLOCK.to_string(); + let data = Bytes("0x".into()); + + let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + Ok(best_header_id) + } + + async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> Result { + let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); + let data = Bytes(header.encode()); + + let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let receipts_required: bool = Decode::decode(&mut &encoded_response.0[..])?; + + Ok(receipts_required) + } + + // The Substrate module could prune old headers. So this function could return false even // if header is synced. And we'll mark corresponding Ethereum header as Orphan. // - // But when we'll read best header from Substrate next time, we will know that - // there's a better header => this Orphan will either be marked as synced, or + // But when we read the best header from Substrate next time, we will know that + // there's a better header. This Orphan will either be marked as synced, or // eventually pruned. - let encoded_id = bail_on_arg_error!( - to_value(Bytes(id.1.encode())).map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, is_known_block) = call_rpc( - client, - "state_call", - Params::Array(vec![ - serde_json::Value::String("EthereumHeadersApi_is_known_block".into()), - encoded_id, - ]), - rpc_returns_encoded_value, - ) - .await; - (client, is_known_block.map(|is_known_block| (id, is_known_block))) -} + async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> Result { + let call = ETH_API_IS_KNOWN_BLOCK.to_string(); + let data = Bytes(header_id.1.encode()); -/// Submits Ethereum header to Substrate runtime. -pub async fn submit_ethereum_headers( - client: Client, - params: SubstrateSigningParams, - headers: Vec, - sign_transactions: bool, -) -> (Client, Result, Error>) { - match sign_transactions { - true => submit_signed_ethereum_headers(client, params, headers).await, - false => submit_unsigned_ethereum_headers(client, headers).await, + let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let is_known_block: bool = Decode::decode(&mut &encoded_response.0[..])?; + + Ok(is_known_block) } -} -/// Submits signed Ethereum header to Substrate runtime. -pub async fn submit_signed_ethereum_headers( - client: Client, - params: SubstrateSigningParams, - headers: Vec, -) -> (Client, Result, Error>) { - let ids = headers.iter().map(|header| header.id()).collect(); - let (client, genesis_hash) = match client.genesis_hash { - Some(genesis_hash) => (client, genesis_hash), - None => { - let (mut client, genesis_hash) = bail_on_error!(block_hash_by_number(client, Zero::zero()).await); - client.genesis_hash = Some(genesis_hash); - (client, genesis_hash) - } - }; - let account_id = params.signer.public().as_array_ref().clone().into(); - let (client, nonce) = bail_on_error!(next_account_index(client, account_id).await); + async fn submit_extrinsic(&self, transaction: Bytes) -> Result { + Ok(Substrate::author_submit_extrinsic(&self.client, transaction).await?) + } - let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, genesis_hash); - let encoded_transaction = bail_on_arg_error!( - to_value(Bytes(transaction.encode())).map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, _) = bail_on_error!( - call_rpc( - client, - "author_submitExtrinsic", - Params::Array(vec![encoded_transaction]), - |_| Ok(()), - ) - .await - ); + async fn grandpa_authorities_set(&self, block: Hash) -> Result { + let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); + let data = Bytes(block.as_bytes().to_vec()); - (client, Ok(ids)) -} + let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let authority_list = encoded_response.0; -/// Submits unsigned Ethereum header to Substrate runtime. -pub async fn submit_unsigned_ethereum_headers( - mut client: Client, - headers: Vec, -) -> (Client, Result, Error>) { - let ids = headers.iter().map(|header| header.id()).collect(); - for header in headers { - let transaction = create_unsigned_submit_transaction(header); - - let encoded_transaction = bail_on_arg_error!( - to_value(Bytes(transaction.encode())).map_err(|e| Error::RequestSerialization(e)), - client - ); - let (used_client, _) = bail_on_error!( - call_rpc( - client, - "author_submitExtrinsic", - Params::Array(vec![encoded_transaction]), - |_| Ok(()), - ) - .await - ); - - client = used_client; + Ok(authority_list) } - - (client, Ok(ids)) } -/// Get GRANDPA justification for given block. -pub async fn grandpa_justification( - client: Client, - id: SubstrateHeaderId, -) -> (Client, Result<(SubstrateHeaderId, Option), Error>) { - let hash = bail_on_arg_error!(to_value(id.1).map_err(|e| Error::RequestSerialization(e)), client); - let (client, signed_block) = call_rpc(client, "chain_getBlock", Params::Array(vec![hash]), rpc_returns_value).await; - ( - client, - signed_block.map(|signed_block: SignedSubstrateBlock| (id, signed_block.justification)), - ) +/// A trait for RPC calls which are used to submit Ethereum headers to a Substrate +/// runtime. These are typically calls which use a combination of other low-level RPC +/// calls. +#[async_trait] +pub trait SubmitEthereumHeaders: SubstrateRpc { + /// Submits Ethereum header to Substrate runtime. + async fn submit_ethereum_headers( + &self, + params: SubstrateSigningParams, + headers: Vec, + sign_transactions: bool, + ) -> Result>; + + /// Submits signed Ethereum header to Substrate runtime. + async fn submit_signed_ethereum_headers( + &self, + params: SubstrateSigningParams, + headers: Vec, + ) -> Result>; + + /// Submits unsigned Ethereum header to Substrate runtime. + async fn submit_unsigned_ethereum_headers( + &self, + headers: Vec, + ) -> Result>; } -/// Get GRANDPA authorities set at given block. -pub async fn grandpa_authorities_set(client: Client, block: Hash) -> (Client, Result, Error>) { - let block = bail_on_arg_error!(to_value(block).map_err(|e| Error::RequestSerialization(e)), client); - call_rpc( - client, - "state_call", - Params::Array(vec![ - serde_json::Value::String("GrandpaApi_grandpa_authorities".into()), - block, - ]), - rpc_returns_bytes, - ) - .await -} +#[async_trait] +impl SubmitEthereumHeaders for SubstrateRpcClient { + async fn submit_ethereum_headers( + &self, + params: SubstrateSigningParams, + headers: Vec, + sign_transactions: bool, + ) -> Result> { + if sign_transactions { + self.submit_signed_ethereum_headers(params, headers).await + } else { + self.submit_unsigned_ethereum_headers(headers).await + } + } -/// Get Substrate block hash by its number. -async fn block_hash_by_number(client: Client, number: Number) -> (Client, Result) { - let number = bail_on_arg_error!(to_value(number).map_err(|e| Error::RequestSerialization(e)), client); - call_rpc( - client, - "chain_getBlockHash", - Params::Array(vec![number]), - rpc_returns_value, - ) - .await -} + async fn submit_signed_ethereum_headers( + &self, + params: SubstrateSigningParams, + headers: Vec, + ) -> Result> { + let ids = headers.iter().map(|header| header.id()).collect(); -/// Get substrate account nonce. -async fn next_account_index( - client: Client, - account: node_primitives::AccountId, -) -> (Client, Result) { - use sp_core::crypto::Ss58Codec; + let account_id = params.signer.public().as_array_ref().clone().into(); + let nonce = self.next_account_index(account_id).await?; - let account = bail_on_arg_error!( - to_value(account.to_ss58check()).map_err(|e| Error::RequestSerialization(e)), - client - ); - let (client, index) = call_rpc(client, "system_accountNextIndex", Params::Array(vec![account]), |v| { - rpc_returns_value::(v) - }) - .await; - (client, index.map(|index| index as _)) -} + let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, self.genesis_hash); + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; -/// Calls RPC on Substrate node that returns Bytes. -async fn call_rpc( - mut client: Client, - method: &'static str, - params: Params, - decode_value: impl Fn(Value) -> Result, -) -> (Client, Result) { - async fn do_call_rpc( - client: &mut Client, - method: &'static str, - params: Params, - decode_value: impl Fn(Value) -> Result, - ) -> Result { - let request_id = client - .rpc_client - .start_request(method, params) - .await - .map_err(Error::StartRequestFailed)?; - // WARN: if there'll be need for executing >1 request at a time, we should avoid - // calling request_by_id - let response = client - .rpc_client - .request_by_id(request_id) - .ok_or(Error::RequestNotFound)? - .await - .map_err(Error::ResponseRetrievalFailed)?; - decode_value(response) + Ok(ids) } - let result = do_call_rpc(&mut client, method, params, decode_value).await; - (client, result) + async fn submit_unsigned_ethereum_headers( + &self, + headers: Vec, + ) -> Result> { + let ids = headers.iter().map(|header| header.id()).collect(); + for header in headers { + let transaction = create_unsigned_submit_transaction(header); + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + } + + Ok(ids) + } } /// Create signed Substrate transaction for submitting Ethereum headers. @@ -429,20 +315,3 @@ fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_no bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) } - -/// When RPC method returns encoded value. -fn rpc_returns_encoded_value(value: Value) -> Result { - let encoded_response: Bytes = from_value(value).map_err(|_| Error::ResponseParseFailed)?; - Decode::decode(&mut &encoded_response.0[..]).map_err(|_| Error::ResponseParseFailed) -} - -/// When RPC method returns value. -fn rpc_returns_value(value: Value) -> Result { - from_value(value).map_err(|_| Error::ResponseParseFailed) -} - -/// When RPC method returns raw bytes. -fn rpc_returns_bytes(value: Value) -> Result, Error> { - let encoded_response: Bytes = from_value(value).map_err(|_| Error::ResponseParseFailed)?; - Ok(encoded_response.0) -} diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 7ca80f9672ad9..ede547a9b5d5f 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -16,18 +16,22 @@ //! Substrate -> Ethereum synchronization. -use crate::ethereum_client::{self, EthereumConnectionParams, EthereumSigningParams}; +use crate::ethereum_client::{ + EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, +}; use crate::ethereum_types::Address; -use crate::substrate_client::{self, SubstrateConnectionParams}; +use crate::rpc::SubstrateRpc; +use crate::rpc_errors::RpcError; +use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{ GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, }; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; -use crate::sync_loop::{OwnedSourceFutureOutput, OwnedTargetFutureOutput, SourceClient, TargetClient}; +use crate::sync_loop::{SourceClient, TargetClient}; use crate::sync_types::SourceHeader; use async_trait::async_trait; -use futures::future::FutureExt; + use std::{collections::HashSet, time::Duration}; /// Interval at which we check new Substrate headers when we are synced/almost synced. @@ -42,7 +46,7 @@ const MAX_SUBMITTED_HEADERS: usize = 4; const PRUNE_DEPTH: u32 = 256; /// Substrate synchronization parameters. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SubstrateSyncParams { /// Ethereum connection params. pub eth: EthereumConnectionParams, @@ -84,170 +88,125 @@ impl Default for SubstrateSyncParams { /// Substrate client as headers source. struct SubstrateHeadersSource { /// Substrate node client. - client: substrate_client::Client, + client: SubstrateRpcClient, } -type SubstrateFutureOutput = OwnedSourceFutureOutput; +impl SubstrateHeadersSource { + fn new(client: SubstrateRpcClient) -> Self { + Self { client } + } +} #[async_trait] impl SourceClient for SubstrateHeadersSource { - type Error = substrate_client::Error; + type Error = RpcError; - async fn best_block_number(self) -> SubstrateFutureOutput { - substrate_client::best_header(self.client) - .map(|(client, result)| (SubstrateHeadersSource { client }, result.map(|header| header.number))) - .await + async fn best_block_number(&self) -> Result { + Ok(self.client.best_header().await?.number) } - async fn header_by_hash(self, hash: Hash) -> SubstrateFutureOutput
{ - substrate_client::header_by_hash(self.client, hash) - .map(|(client, result)| (SubstrateHeadersSource { client }, result)) - .await + async fn header_by_hash(&self, hash: Hash) -> Result { + self.client.header_by_hash(hash).await } - async fn header_by_number(self, number: Number) -> SubstrateFutureOutput
{ - substrate_client::header_by_number(self.client, number) - .map(|(client, result)| (SubstrateHeadersSource { client }, result)) - .await + async fn header_by_number(&self, number: Number) -> Result { + self.client.header_by_number(number).await } async fn header_completion( - self, + &self, id: SubstrateHeaderId, - ) -> SubstrateFutureOutput<(SubstrateHeaderId, Option)> { - substrate_client::grandpa_justification(self.client, id) - .map(|(client, result)| (SubstrateHeadersSource { client }, result)) - .await + ) -> Result<(SubstrateHeaderId, Option), Self::Error> { + let hash = id.1; + let signed_block = self.client.get_block(Some(hash)).await?; + let grandpa_justification = signed_block.justification; + + Ok((id, grandpa_justification)) } async fn header_extra( - self, + &self, id: SubstrateHeaderId, _header: QueuedSubstrateHeader, - ) -> SubstrateFutureOutput<(SubstrateHeaderId, ())> { - (self, Ok((id, ()))) + ) -> Result<(SubstrateHeaderId, ()), Self::Error> { + Ok((id, ())) } } /// Ethereum client as Substrate headers target. struct EthereumHeadersTarget { /// Ethereum node client. - client: ethereum_client::Client, + client: EthereumRpcClient, /// Bridge contract address. contract: Address, /// Ethereum signing params. sign_params: EthereumSigningParams, } -type EthereumFutureOutput = OwnedTargetFutureOutput; +impl EthereumHeadersTarget { + fn new(client: EthereumRpcClient, contract: Address, sign_params: EthereumSigningParams) -> Self { + Self { + client, + contract, + sign_params, + } + } +} #[async_trait] impl TargetClient for EthereumHeadersTarget { - type Error = ethereum_client::Error; - - async fn best_header_id(self) -> EthereumFutureOutput { - let (contract, sign_params) = (self.contract, self.sign_params); - ethereum_client::best_substrate_block(self.client, contract) - .map(move |(client, result)| { - ( - EthereumHeadersTarget { - client, - contract, - sign_params, - }, - result, - ) - }) - .await + type Error = RpcError; + + async fn best_header_id(&self) -> Result { + self.client.best_substrate_block(self.contract).await } - async fn is_known_header(self, id: SubstrateHeaderId) -> EthereumFutureOutput<(SubstrateHeaderId, bool)> { - let (contract, sign_params) = (self.contract, self.sign_params); - ethereum_client::substrate_header_known(self.client, contract, id) - .map(move |(client, result)| { - ( - EthereumHeadersTarget { - client, - contract, - sign_params, - }, - result, - ) - }) - .await + async fn is_known_header(&self, id: SubstrateHeaderId) -> Result<(SubstrateHeaderId, bool), Self::Error> { + self.client.substrate_header_known(self.contract, id).await } - async fn submit_headers(self, headers: Vec) -> EthereumFutureOutput> { - let (contract, sign_params) = (self.contract, self.sign_params); - ethereum_client::submit_substrate_headers(self.client, sign_params.clone(), contract, headers) - .map(move |(client, result)| { - ( - EthereumHeadersTarget { - client, - contract, - sign_params, - }, - result, - ) - }) + async fn submit_headers(&self, headers: Vec) -> Result, Self::Error> { + self.client + .submit_substrate_headers(self.sign_params.clone(), self.contract, headers) .await } - async fn incomplete_headers_ids(self) -> EthereumFutureOutput> { - let (contract, sign_params) = (self.contract, self.sign_params); - ethereum_client::incomplete_substrate_headers(self.client, contract) - .map(move |(client, result)| { - ( - EthereumHeadersTarget { - client, - contract, - sign_params, - }, - result, - ) - }) - .await + async fn incomplete_headers_ids(&self) -> Result, Self::Error> { + self.client.incomplete_substrate_headers(self.contract).await } async fn complete_header( - self, + &self, id: SubstrateHeaderId, completion: GrandpaJustification, - ) -> EthereumFutureOutput { - let (contract, sign_params) = (self.contract, self.sign_params); - ethereum_client::complete_substrate_header(self.client, sign_params.clone(), contract, id, completion) - .map(move |(client, result)| { - ( - EthereumHeadersTarget { - client, - contract, - sign_params, - }, - result, - ) - }) + ) -> Result { + self.client + .complete_substrate_header(self.sign_params.clone(), self.contract, id, completion) .await } - async fn requires_extra(self, header: QueuedSubstrateHeader) -> EthereumFutureOutput<(SubstrateHeaderId, bool)> { - (self, Ok((header.header().id(), false))) + async fn requires_extra(&self, header: QueuedSubstrateHeader) -> Result<(SubstrateHeaderId, bool), Self::Error> { + Ok((header.header().id(), false)) } } /// Run Substrate headers synchronization. -pub fn run(params: SubstrateSyncParams) { - let eth_client = ethereum_client::client(params.eth); - let sub_client = substrate_client::client(params.sub); +pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { + let sub_params = params.clone(); + + let eth_client = EthereumRpcClient::new(params.eth); + let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params.sub).await })?; + + let target = EthereumHeadersTarget::new(eth_client, params.eth_contract_address, params.eth_sign); + let source = SubstrateHeadersSource::new(sub_client); crate::sync_loop::run( - SubstrateHeadersSource { client: sub_client }, + source, SUBSTRATE_TICK_INTERVAL, - EthereumHeadersTarget { - client: eth_client, - contract: params.eth_contract_address, - sign_params: params.eth_sign, - }, + target, ETHEREUM_TICK_INTERVAL, params.sync_params, ); + + Ok(()) } diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index e1fc372e148eb..7f15865cc5049 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -19,7 +19,7 @@ use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeade use num_traits::{One, Saturating}; /// Common sync params. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct HeadersSyncParams { /// Maximal number of ethereum headers to pre-download. pub max_future_headers_to_download: usize, @@ -37,7 +37,7 @@ pub struct HeadersSyncParams { } /// Target transaction mode. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum TargetTransactionMode { /// Submit new headers using signed transactions. Signed, diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 978db603591db..28ee40650f32a 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -43,11 +43,6 @@ const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); /// reconnection again. const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); -/// Type alias for all SourceClient futures. -pub type OwnedSourceFutureOutput = (Client, Result>::Error>); -/// Type alias for all TargetClient futures. -pub type OwnedTargetFutureOutput = (Client, Result>::Error>); - /// Source client trait. #[async_trait] pub trait SourceClient: Sized { @@ -55,26 +50,26 @@ pub trait SourceClient: Sized { type Error: std::fmt::Debug + MaybeConnectionError; /// Get best block number. - async fn best_block_number(self) -> OwnedSourceFutureOutput; + async fn best_block_number(&self) -> Result; /// Get header by hash. - async fn header_by_hash(self, hash: P::Hash) -> OwnedSourceFutureOutput; + async fn header_by_hash(&self, hash: P::Hash) -> Result; /// Get canonical header by number. - async fn header_by_number(self, number: P::Number) -> OwnedSourceFutureOutput; + async fn header_by_number(&self, number: P::Number) -> Result; /// Get completion data by header hash. async fn header_completion( - self, + &self, id: HeaderId, - ) -> OwnedSourceFutureOutput, Option)>; + ) -> Result<(HeaderId, Option), Self::Error>; /// Get extra data by header hash. async fn header_extra( - self, + &self, id: HeaderId, header: QueuedHeader

, - ) -> OwnedSourceFutureOutput, P::Extra)>; + ) -> Result<(HeaderId, P::Extra), Self::Error>; } /// Target client trait. @@ -84,35 +79,35 @@ pub trait TargetClient: Sized { type Error: std::fmt::Debug + MaybeConnectionError; /// Returns ID of best header known to the target node. - async fn best_header_id(self) -> OwnedTargetFutureOutput>; + async fn best_header_id(&self) -> Result, Self::Error>; /// Returns true if header is known to the target node. async fn is_known_header( - self, + &self, id: HeaderId, - ) -> OwnedTargetFutureOutput, bool)>; + ) -> Result<(HeaderId, bool), Self::Error>; /// Submit headers. async fn submit_headers( - self, + &self, headers: Vec>, - ) -> OwnedTargetFutureOutput>>; + ) -> Result>, Self::Error>; /// Returns ID of headers that require to be 'completed' before children can be submitted. - async fn incomplete_headers_ids(self) -> OwnedTargetFutureOutput>>; + async fn incomplete_headers_ids(&self) -> Result>, Self::Error>; /// Submit completion data for header. async fn complete_header( - self, + &self, id: HeaderId, completion: P::Completion, - ) -> OwnedTargetFutureOutput>; + ) -> Result, Self::Error>; /// Returns true if header requires extra data to be submitted. async fn requires_extra( - self, + &self, header: QueuedHeader

, - ) -> OwnedTargetFutureOutput, bool)>; + ) -> Result<(HeaderId, bool), Self::Error>; } /// Run headers synchronization. @@ -131,7 +126,7 @@ pub fn run( let mut stall_countdown = None; let mut last_update_time = Instant::now(); - let mut source_maybe_client = None; + let mut source_client_is_online = false; let mut source_best_block_number_required = false; let source_best_block_number_future = source_client.best_block_number().fuse(); let source_new_header_future = futures::future::Fuse::terminated(); @@ -141,7 +136,7 @@ pub fn run( let source_go_offline_future = futures::future::Fuse::terminated(); let source_tick_stream = interval(source_tick).fuse(); - let mut target_maybe_client = None; + let mut target_client_is_online = false; let mut target_best_block_required = false; let mut target_incomplete_headers_required = true; let target_best_block_future = target_client.best_header_id().fuse(); @@ -173,77 +168,65 @@ pub fn run( loop { futures::select! { - (source_client, source_best_block_number) = source_best_block_number_future => { + source_best_block_number = source_best_block_number_future => { source_best_block_number_required = false; - process_future_result( - &mut source_maybe_client, - source_client, + source_client_is_online = process_future_result( source_best_block_number, |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY, source_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving best header number from {}", P::SOURCE_NAME), ); }, - (source_client, source_new_header) = source_new_header_future => { - process_future_result( - &mut source_maybe_client, - source_client, + source_new_header = source_new_header_future => { + source_client_is_online = process_future_result( source_new_header, |source_new_header| sync.headers_mut().header_response(source_new_header), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY, source_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving header from {} node", P::SOURCE_NAME), ); }, - (source_client, source_orphan_header) = source_orphan_header_future => { - process_future_result( - &mut source_maybe_client, - source_client, + source_orphan_header = source_orphan_header_future => { + source_client_is_online = process_future_result( source_orphan_header, |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY, source_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), ); }, - (source_client, source_extra) = source_extra_future => { - process_future_result( - &mut source_maybe_client, - source_client, + source_extra = source_extra_future => { + source_client_is_online = process_future_result( source_extra, |(header, extra)| sync.headers_mut().extra_response(&header, extra), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY, source_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), ); }, - (source_client, source_completion) = source_completion_future => { - process_future_result( - &mut source_maybe_client, - source_client, + source_completion = source_completion_future => { + source_client_is_online = process_future_result( source_completion, |(header, completion)| sync.headers_mut().completion_response(&header, completion), &mut source_go_offline_future, - |source_client| delay(CONNECTION_ERROR_DELAY, source_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), ); }, source_client = source_go_offline_future => { - source_maybe_client = Some(source_client); + source_client_is_online = true; }, _ = source_tick_stream.next() => { if sync.is_almost_synced() { source_best_block_number_required = true; } }, - (target_client, target_best_block) = target_best_block_future => { + target_best_block = target_best_block_future => { target_best_block_required = false; - process_future_result( - &mut target_maybe_client, - target_client, + target_client_is_online = process_future_result( target_best_block, |target_best_block| { let head_updated = sync.target_best_header_response(target_best_block); @@ -279,73 +262,63 @@ pub fn run( } }, &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving best known header from {} node", P::TARGET_NAME), ); }, - (target_client, incomplete_headers_ids) = target_incomplete_headers_future => { + incomplete_headers_ids = target_incomplete_headers_future => { target_incomplete_headers_required = false; - process_future_result( - &mut target_maybe_client, - target_client, + target_client_is_online = process_future_result( incomplete_headers_ids, |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), ); }, - (target_client, target_existence_status) = target_existence_status_future => { - process_future_result( - &mut target_maybe_client, - target_client, + target_existence_status = target_existence_status_future => { + target_client_is_online = process_future_result( target_existence_status, |(target_header, target_existence_status)| sync .headers_mut() .maybe_orphan_response(&target_header, target_existence_status), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving existence status from {} node", P::TARGET_NAME), ); }, - (target_client, target_submit_header_result) = target_submit_header_future => { - process_future_result( - &mut target_maybe_client, - target_client, + target_submit_header_result = target_submit_header_future => { + target_client_is_online = process_future_result( target_submit_header_result, |submitted_headers| sync.headers_mut().headers_submitted(submitted_headers), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error submitting headers to {} node", P::TARGET_NAME), ); }, - (target_client, target_complete_header_result) = target_complete_header_future => { - process_future_result( - &mut target_maybe_client, - target_client, + target_complete_header_result = target_complete_header_future => { + target_client_is_online = process_future_result( target_complete_header_result, |completed_header| sync.headers_mut().header_completed(&completed_header), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error completing headers at {}", P::TARGET_NAME), ); }, - (target_client, target_extra_check_result) = target_extra_check_future => { - process_future_result( - &mut target_maybe_client, - target_client, + target_extra_check_result = target_extra_check_future => { + target_client_is_online = process_future_result( target_extra_check_result, |(header, extra_check_result)| sync .headers_mut() .maybe_extra_response(&header, extra_check_result), &mut target_go_offline_future, - |target_client| delay(CONNECTION_ERROR_DELAY, target_client), + || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), ); }, target_client = target_go_offline_future => { - target_maybe_client = Some(target_client); + target_client_is_online = true; }, _ = target_tick_stream.next() => { target_best_block_required = true; @@ -356,15 +329,35 @@ pub fn run( // print progress progress_context = print_sync_progress(progress_context, &sync); - // if target client is available: wait, or call required target methods - if let Some(target_client) = target_maybe_client.take() { - // the priority is to: - // 1) get best block - it stops us from downloading/submitting new blocks + we call it rarely; - // 2) get incomplete headers - it stops us from submitting new blocks + we call it rarely; - // 3) complete headers - it stops us from submitting new blocks; - // 4) check if we need extra data from source - it stops us from downloading/submitting new blocks; - // 5) check existence - it stops us from submitting new blocks; - // 6) submit header + // If the target client is accepting requests we update the requests that + // we want it to run + if target_client_is_online { + // NOTE: Is is important to reset this so that we only have one + // request being processed by the client at a time. This prevents + // race conditions like receiving two transactions with the same + // nonce from the client. + target_client_is_online = false; + + // The following is how we prioritize requests: + // + // 1. Get best block + // - Stops us from downloading or submitting new blocks + // - Only called rarely + // + // 2. Get incomplete headers + // - Stops us from submitting new blocks + // - Only called rarely + // + // 3. Get complete headers + // - Stops us from submitting new blocks + // + // 4. Check if we need extra data from source + // - Stops us from downloading or submitting new blocks + // + // 5. Check existence of header + // - Stops us from submitting new blocks + // + // 6. Submit header if target_best_block_required { log::debug!(target: "bridge", "Asking {} about best block", P::TARGET_NAME); @@ -424,18 +417,35 @@ pub fn run( stall_countdown = Some(Instant::now()); } } else { - target_maybe_client = Some(target_client); + target_client_is_online = true; } } - // if source client is available: wait, or call required source methods - if let Some(source_client) = source_maybe_client.take() { - // the priority is to: - // 1) get best block - it stops us from downloading new blocks + we call it rarely; - // 2) download completion data - it stops us from submitting new blocks; - // 3) download extra data - it stops us from submitting new blocks; - // 4) download missing headers - it stops us from downloading/submitting new blocks; - // 5) downloading new headers + // If the source client is accepting requests we update the requests that + // we want it to run + if source_client_is_online { + // NOTE: Is is important to reset this so that we only have one + // request being processed by the client at a time. This prevents + // race conditions like receiving two transactions with the same + // nonce from the client. + source_client_is_online = false; + + // The following is how we prioritize requests: + // + // 1. Get best block + // - Stops us from downloading or submitting new blocks + // - Only called rarely + // + // 2. Download completion data + // - Stops us from submitting new blocks + // + // 3. Download extra data + // - Stops us from submitting new blocks + // + // 4. Download missing headers + // - Stops us from downloading or submitting new blocks + // + // 5. Downloading new headers if source_best_block_number_required { log::debug!(target: "bridge", "Asking {} node about best block number", P::SOURCE_NAME); @@ -488,55 +498,56 @@ pub fn run( source_new_header_future.set(source_client.header_by_number(id).fuse()); } else { - source_maybe_client = Some(source_client); + source_client_is_online = true; } } } }); } -/// Future that resolves into given value after given timeout. -async fn delay(timeout: Duration, retval: T) -> T { - async_std::task::sleep(timeout).await; - retval -} - /// Stream that emits item every `timeout_ms` milliseconds. fn interval(timeout: Duration) -> impl futures::Stream { futures::stream::unfold((), move |_| async move { - delay(timeout, ()).await; + async_std::task::sleep(timeout).await; Some(((), ())) }) } -/// Process result of the future that may have been caused by connection failure. -fn process_future_result( - maybe_client: &mut Option, - client: TClient, +/// Process result of the future from a client. +/// +/// Returns whether or not the client we're interacting with is online. In this context +/// what online means is that the client is currently not handling any other requests +/// that we've previously sent. +fn process_future_result( result: Result, on_success: impl FnOnce(TResult), go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, - go_offline: impl FnOnce(TClient) -> TGoOfflineFuture, + go_offline: impl FnOnce() -> TGoOfflineFuture, error_pattern: impl FnOnce() -> String, -) where +) -> bool +where TError: std::fmt::Debug + MaybeConnectionError, TGoOfflineFuture: FutureExt, { + let mut client_is_online = false; + match result { Ok(result) => { - *maybe_client = Some(client); on_success(result); + client_is_online = true } Err(error) => { if error.is_connection_error() { - go_offline_future.set(go_offline(client).fuse()); + go_offline_future.set(go_offline().fuse()); } else { - *maybe_client = Some(client); + client_is_online = true } log::error!(target: "bridge", "{}: {:?}", error_pattern(), error); } } + + client_is_online } /// Print synchronization progress. From e32cdb6083eddd795d87e2203300b3bd6b1d7beb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 24 Jun 2020 23:25:21 +0300 Subject: [PATCH 0084/1210] Runtime benchmarks: start (#136) * runtime benchmarks: start * merge tests + benchmarks infrastructure * fix compilation * Fix compilation issues with runtime-benchmark feature flag Mainly involved pulling in correct dependencies and adding some functions which were called but didn't yet exist. * Fix broken compilation for tests * Move header signing methods into trait * Move signing related test helpers to own module * Remove comment about feature flag * Add constants to tests * Add top level comment for testing utilities Co-authored-by: Hernando Castano --- bin/node/node/Cargo.toml | 21 ++ bin/node/node/src/cli.rs | 14 +- bin/node/node/src/command.rs | 18 +- bin/node/node/src/service.rs | 1 + bin/node/runtime/Cargo.toml | 16 ++ bin/node/runtime/build.rs | 2 +- bin/node/runtime/src/lib.rs | 21 ++ modules/currency-exchange/Cargo.toml | 15 +- modules/ethereum/Cargo.toml | 30 +- modules/ethereum/src/benchmarking.rs | 60 ++++ modules/ethereum/src/finality.rs | 95 +++---- modules/ethereum/src/import.rs | 261 +++++++++-------- modules/ethereum/src/lib.rs | 144 ++++++---- modules/ethereum/src/mock.rs | 120 ++++---- modules/ethereum/src/test_utils.rs | 233 +++++++++++++++ modules/ethereum/src/validators.rs | 11 +- modules/ethereum/src/verification.rs | 328 +++++++++------------- primitives/ethereum-poa/Cargo.toml | 14 +- primitives/ethereum-poa/src/lib.rs | 14 +- primitives/ethereum-poa/src/signatures.rs | 66 +++++ 20 files changed, 950 insertions(+), 534 deletions(-) create mode 100644 modules/ethereum/src/benchmarking.rs create mode 100644 modules/ethereum/src/test_utils.rs create mode 100644 primitives/ethereum-poa/src/signatures.rs diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 229c3ff637e22..10122e07a1ad3 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -115,6 +115,16 @@ version = "2.0.0-rc3" rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" +[dependencies.frame-benchmarking] +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +git = "https://github.com/paritytech/substrate.git" + +[dependencies.frame-benchmarking-cli] +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +git = "https://github.com/paritytech/substrate.git" + [build-dependencies] vergen = "3.1.0" @@ -123,3 +133,14 @@ package = "substrate-build-script-utils" version = "2.0.0-rc3" rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" + +[build-dependencies.frame-benchmarking-cli] +version = "2.0.0-rc3" +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +git = "https://github.com/paritytech/substrate.git" + +[features] +default = [] +runtime-benchmarks = [ + "bridge-node-runtime/runtime-benchmarks", +] diff --git a/bin/node/node/src/cli.rs b/bin/node/node/src/cli.rs index 9be42c8f44cc5..a7399fa716dff 100644 --- a/bin/node/node/src/cli.rs +++ b/bin/node/node/src/cli.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use sc_cli::{RunCmd, Subcommand}; +use sc_cli::RunCmd; use structopt::StructOpt; #[derive(Debug, StructOpt)] @@ -25,3 +25,15 @@ pub struct Cli { #[structopt(flatten)] pub run: RunCmd, } + +/// Possible subcommands of the main binary. +#[derive(Debug, StructOpt)] +pub enum Subcommand { + /// A set of base subcommands handled by `sc_cli`. + #[structopt(flatten)] + Base(sc_cli::Subcommand), + + /// The custom benchmark subcommmand benchmarking runtime pallets. + #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), +} diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs index cfe7115239eeb..9a23704decd72 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/node/src/command.rs @@ -30,8 +30,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::Cli; +use crate::cli::{Cli, Subcommand}; use crate::service; +use bridge_node_runtime::Block; use sc_cli::SubstrateCli; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; @@ -81,7 +82,20 @@ pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); match &cli.subcommand { - Some(subcommand) => { + Some(Subcommand::Benchmark(cmd)) => { + if cfg!(feature = "runtime-benchmarks") { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| cmd.run::(config)) + } else { + println!( + "Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + ); + Ok(()) + } + } + Some(Subcommand::Base(subcommand)) => { let runner = cli.create_runner(subcommand)?; runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0)) } diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 6e09a2c902b28..96728beb81bcd 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -33,6 +33,7 @@ native_executor_instance!( pub Executor, bridge_node_runtime::api::dispatch, bridge_node_runtime::native_version, + frame_benchmarking::benchmarking::HostFunctions, ); /// Starts a `ServiceBuilder` for a full service. diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 2bc3e25144b96..ddee4842a9293 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -195,6 +195,13 @@ default-features = false rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" +[dependencies.frame-benchmarking] +optional = true +version = "2.0.0-rc3" +default-features = false +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +git = "https://github.com/paritytech/substrate/" + [build-dependencies.wasm-builder-runner] version = "1.0.5" package = "substrate-wasm-builder-runner" @@ -209,6 +216,7 @@ std = [ "pallet-bridge-eth-poa/std", "pallet-bridge-currency-exchange/std", "codec/std", + "frame-benchmarking/std", "frame-executive/std", "frame-support/std", "frame-system/std", @@ -234,3 +242,11 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment/std", ] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-bridge-currency-exchange/runtime-benchmarks", + "pallet-bridge-eth-poa/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/bin/node/runtime/build.rs b/bin/node/runtime/build.rs index 81d28a1e92371..4fda040c9bd14 100644 --- a/bin/node/runtime/build.rs +++ b/bin/node/runtime/build.rs @@ -19,7 +19,7 @@ use wasm_builder_runner::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates("1.0.9") + .with_wasm_builder_from_crates("1.0.11") .export_heap_base() .import_memory() .build() diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index fe1fc8c905872..450bd4d8791d1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -573,6 +573,27 @@ impl_runtime_apis! { None } } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn dispatch_benchmark( + pallet: Vec, + benchmark: Vec, + lowest_range_values: Vec, + highest_range_values: Vec, + steps: Vec, + repeat: u32, + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark}; + let mut batches = Vec::::new(); + let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat); + + add_benchmark!(params, batches, b"bridge-eth-poa", BridgeEthPoA); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } } #[cfg(test)] diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 1a69a41f25167..7847483bc8b75 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -35,6 +35,13 @@ default-features = false rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" +[dependencies.frame-benchmarking] +optional = true +version = "2.0.0-rc3" +default-features = false +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +git = "https://github.com/paritytech/substrate/" + [dev-dependencies.sp-core] version = "2.0.0-rc3" rev = "606c56d2e2f69f68f3947551224be6a3515dff60" @@ -48,11 +55,13 @@ git = "https://github.com/paritytech/substrate/" [features] default = ["std"] std = [ - "serde", "codec/std", - "sp-std/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "sp-runtime/std", + "serde", "sp-currency-exchange/std", + "sp-std/std", + "sp-runtime/std", ] +runtime-benchmarks = ["frame-benchmarking"] diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 818ef12d40263..bb022397f394b 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] serde = { version = "1.0", optional = true } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +hex-literal = "0.2" primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", default-features = false } # Substrate Based Dependencies @@ -41,21 +42,40 @@ default-features = false rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" +[dependencies.frame-benchmarking] +optional = true +version = "2.0.0-rc3" +default-features = false +rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +git = "https://github.com/paritytech/substrate/" + +[dependencies.libsecp256k1] +optional = true +version = "0.3.4" +default-features = false +features = ["hmac"] + # Dev Dependencies [dev-dependencies] # TODO: Stop renaming this on import primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", features = ["std", "test-helpers"] } -parity-crypto = { version = "0.6", features = ["publickey"] } +libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [features] default = ["std"] std = [ - "serde", "codec/std", - "sp-std/std", + "frame-benchmarking/std", "frame-support/std", - "sp-runtime/std", "frame-system/std", - "sp-io/std", "primitives/std", + "serde", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "libsecp256k1", + "primitives/test-helpers", ] diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs new file mode 100644 index 0000000000000..10136c1e5f42b --- /dev/null +++ b/modules/ethereum/src/benchmarking.rs @@ -0,0 +1,60 @@ +// Copyright 2019-2020 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 . + +use super::*; + +use crate::test_utils::{build_custom_header, build_genesis_header, validator_utils::*}; + +use frame_benchmarking::benchmarks; +use frame_system::RawOrigin; +use primitives::U256; + +benchmarks! { + _ { } + + // Benchmark `import_unsigned_header` extrinsic with the best possible conditions: + // * Parent header is finalized. + // * New header doesn't require receipts. + // * Nothing is finalized by new header. + // * Nothing is pruned by new header. + import_unsigned_header_best_case { + let n in 1..1000; + + // initialize storage with some initial header + let initial_header = build_genesis_header(&validator(0)); + let initial_header_hash = initial_header.compute_hash(); + let initial_difficulty = initial_header.difficulty; + initialize_storage::( + &initial_header, + initial_difficulty, + &validators_addresses(2), + ); + + // prepare header to be inserted + let header = build_custom_header( + &validator(1), + &initial_header, + |mut header| { + header.gas_limit = header.gas_limit + U256::from(n); + header + }, + ); + + }: import_unsigned_header(RawOrigin::None, header, None) + verify { + assert_eq!(BridgeStorage::::new().best_block().0.number, 1); + } +} diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index c7bfe67d640bc..e113f66831a8f 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -282,13 +282,15 @@ impl Default for FinalityVotes { #[cfg(test)] mod tests { use super::*; - use crate::mock::{custom_test_ext, genesis, insert_header, validator, validators_addresses, TestRuntime}; + use crate::mock::{insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime}; use crate::{BridgeStorage, FinalityCache, HeaderToImport}; use frame_support::StorageMap; + const TOTAL_VALIDATORS: usize = 5; + #[test] fn verifies_header_author() { - custom_test_ext(genesis(), validators_addresses(5)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { assert_eq!( finalize_blocks( &BridgeStorage::::new(), @@ -306,21 +308,16 @@ mod tests { #[test] fn finalize_blocks_works() { - custom_test_ext(genesis(), validators_addresses(5)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |ctx| { // let's say we have 5 validators (we need 'votes' from 3 validators to achieve // finality) let mut storage = BridgeStorage::::new(); // when header#1 is inserted, nothing is finalized (1 vote) - let header1 = Header { - author: validator(0).address().as_fixed_bytes().into(), - parent_hash: genesis().compute_hash(), - number: 1, - ..Default::default() - }; + let header1 = HeaderBuilder::with_parent(&ctx.genesis).sign_by(&validator(0)); let id1 = header1.compute_id(); let mut header_to_import = HeaderToImport { - context: storage.import_context(None, &genesis().compute_hash()).unwrap(), + context: storage.import_context(None, &header1.parent_hash).unwrap(), is_best: true, id: id1, header: header1, @@ -332,8 +329,8 @@ mod tests { assert_eq!( finalize_blocks( &storage, - genesis().compute_id(), - (Default::default(), &validators_addresses(5)), + ctx.genesis.compute_id(), + (Default::default(), &ctx.addresses), id1, None, &header_to_import.header, @@ -345,19 +342,14 @@ mod tests { storage.insert_header(header_to_import.clone()); // when header#2 is inserted, nothing is finalized (2 votes) - header_to_import.header = Header { - author: validator(1).address().as_fixed_bytes().into(), - parent_hash: id1.hash, - number: 2, - ..Default::default() - }; + header_to_import.header = HeaderBuilder::with_parent_hash(id1.hash).sign_by(&validator(1)); header_to_import.id = header_to_import.header.compute_id(); let id2 = header_to_import.header.compute_id(); assert_eq!( finalize_blocks( &storage, - genesis().compute_id(), - (Default::default(), &validators_addresses(5)), + ctx.genesis.compute_id(), + (Default::default(), &ctx.addresses), id2, None, &header_to_import.header, @@ -369,19 +361,14 @@ mod tests { storage.insert_header(header_to_import.clone()); // when header#3 is inserted, header#1 is finalized (3 votes) - header_to_import.header = Header { - author: validator(2).address().as_fixed_bytes().into(), - parent_hash: id2.hash, - number: 3, - ..Default::default() - }; + header_to_import.header = HeaderBuilder::with_parent_hash(id2.hash).sign_by(&validator(2)); header_to_import.id = header_to_import.header.compute_id(); let id3 = header_to_import.header.compute_id(); assert_eq!( finalize_blocks( &storage, - genesis().compute_id(), - (Default::default(), &validators_addresses(5)), + ctx.genesis.compute_id(), + (Default::default(), &ctx.addresses), id3, None, &header_to_import.header, @@ -404,11 +391,7 @@ mod tests { // 2) add votes from header#4 and header#5 let validators = validators_addresses(5); let headers = (1..6) - .map(|number| Header { - number: number, - author: validators[number as usize - 1], - ..Default::default() - }) + .map(|number| HeaderBuilder::with_number(number).sign_by(&validator(number as usize - 1))) .collect::>(); let ancestry = headers .iter() @@ -451,8 +434,7 @@ mod tests { #[test] fn prepare_votes_respects_finality_cache() { - let validators_addresses = validators_addresses(5); - custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { + run_test(TOTAL_VALIDATORS, |ctx| { // we need signatures of 3 validators to finalize block let mut storage = BridgeStorage::::new(); @@ -462,14 +444,9 @@ mod tests { let mut hashes = Vec::new(); let mut headers = Vec::new(); let mut ancestry = Vec::new(); - let mut parent_hash = genesis().compute_hash(); + let mut parent_hash = ctx.genesis.compute_hash(); for i in 1..10 { - let header = Header { - author: validator((i - 1) / 3).address().as_fixed_bytes().into(), - parent_hash, - number: i as _, - ..Default::default() - }; + let header = HeaderBuilder::with_parent_hash(parent_hash).sign_by(&validator((i - 1) / 3)); let id = header.compute_id(); insert_header(&mut storage, header.clone()); hashes.push(id.hash); @@ -486,9 +463,9 @@ mod tests { // check that votes at #7 are computed correctly without cache let expected_votes_at_7 = FinalityVotes { votes: vec![ - (validators_addresses[0].clone(), 3), - (validators_addresses[1].clone(), 3), - (validators_addresses[2].clone(), 1), + (ctx.addresses[0].clone(), 3), + (ctx.addresses[1].clone(), 3), + (ctx.addresses[2].clone(), 1), ] .into_iter() .collect(), @@ -499,11 +476,11 @@ mod tests { prepare_votes( storage.cached_finality_votes( &headers.get(5).unwrap().compute_id(), - &genesis().compute_id(), + &ctx.genesis.compute_id(), |_| false, ), Default::default(), - &validators_addresses.iter().collect(), + &ctx.addresses.iter().collect(), id7, headers.get(6).unwrap(), None, @@ -514,12 +491,9 @@ mod tests { // cached votes at #5 let expected_votes_at_5 = FinalityVotes { - votes: vec![ - (validators_addresses[0].clone(), 3), - (validators_addresses[1].clone(), 2), - ] - .into_iter() - .collect(), + votes: vec![(ctx.addresses[0].clone(), 3), (ctx.addresses[1].clone(), 2)] + .into_iter() + .collect(), ancestry: ancestry[..5].iter().cloned().collect(), }; FinalityCache::::insert(hashes[4], expected_votes_at_5); @@ -530,11 +504,11 @@ mod tests { prepare_votes( storage.cached_finality_votes( &headers.get(5).unwrap().compute_id(), - &genesis().compute_id(), + &ctx.genesis.compute_id(), |_| false, ), Default::default(), - &validators_addresses.iter().collect(), + &ctx.addresses.iter().collect(), id7, headers.get(6).unwrap(), None, @@ -546,12 +520,9 @@ mod tests { // when we're inserting header#7 and last finalized header is 3: // check that votes at #7 are computed correctly with cache let expected_votes_at_7 = FinalityVotes { - votes: vec![ - (validators_addresses[1].clone(), 3), - (validators_addresses[2].clone(), 1), - ] - .into_iter() - .collect(), + votes: vec![(ctx.addresses[1].clone(), 3), (ctx.addresses[2].clone(), 1)] + .into_iter() + .collect(), ancestry: ancestry[3..7].iter().cloned().collect(), }; assert_eq!( @@ -562,7 +533,7 @@ mod tests { |hash| *hash == hashes[2], ), headers[2].compute_id(), - &validators_addresses.iter().collect(), + &ctx.addresses.iter().collect(), id7, headers.get(6).unwrap(), None, diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 4ae91bb70c707..ab375d256b8e0 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -162,17 +162,19 @@ pub fn header_import_requires_receipts( mod tests { use super::*; use crate::mock::{ - block_i, custom_block_i, custom_test_ext, genesis, signed_header, test_aura_config, test_validators_config, - validator, validators, validators_addresses, KeepSomeHeadersBehindBest, TestRuntime, GENESIS_STEP, + run_test, secret_to_address, test_aura_config, test_validators_config, validator, validators_addresses, + HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; use frame_support::{StorageMap, StorageValue}; - use parity_crypto::publickey::KeyPair; + use secp256k1::SecretKey; + + const TOTAL_VALIDATORS: usize = 3; #[test] fn rejects_finalized_block_competitors() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let mut storage = BridgeStorage::::new(); storage.finalize_and_prune_headers( Some(HeaderId { @@ -198,10 +200,9 @@ mod tests { #[test] fn rejects_known_header() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { - let validators = validators(3); + run_test(TOTAL_VALIDATORS, |ctx| { let mut storage = BridgeStorage::::new(); - let block = block_i(1, &validators); + let header = HeaderBuilder::with_parent(&ctx.genesis).sign_by(&validator(1)); assert_eq!( import_header( &mut storage, @@ -209,7 +210,7 @@ mod tests { &test_aura_config(), &test_validators_config(), None, - block.clone(), + header.clone(), None, ) .map(|_| ()), @@ -222,7 +223,7 @@ mod tests { &test_aura_config(), &test_validators_config(), None, - block, + header, None, ) .map(|_| ()), @@ -233,14 +234,13 @@ mod tests { #[test] fn import_header_works() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |ctx| { let validators_config = ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(validators_addresses(3))), + (0, ValidatorsSource::List(ctx.addresses.clone())), (1, ValidatorsSource::List(validators_addresses(2))), ]); - let validators = validators(3); let mut storage = BridgeStorage::::new(); - let header = block_i(1, &validators); + let header = HeaderBuilder::with_parent(&ctx.genesis).sign_by(&validator(1)); let hash = header.compute_hash(); assert_eq!( import_header( @@ -267,9 +267,9 @@ mod tests { #[test] fn headers_are_pruned_during_import() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |ctx| { let validators_config = - ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), validators_addresses(3))); + ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), ctx.addresses.clone())); let validators = vec![validator(0), validator(1), validator(2)]; let mut storage = BridgeStorage::::new(); @@ -277,7 +277,9 @@ mod tests { // => since we want to keep 10 finalized blocks, we aren't pruning anything let mut latest_block_id = Default::default(); for i in 1..11 { - let header = block_i(i, &validators); + let header = HeaderBuilder::with_parent_number(i - 1).sign_by_set(&validators); + let parent_id = header.parent_id().unwrap(); + let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, &mut KeepSomeHeadersBehindBest::default(), @@ -289,26 +291,24 @@ mod tests { ) .unwrap(); match i { - 2..=10 => assert_eq!( - finalized_blocks, - vec![(block_i(i - 1, &validators).compute_id(), Some(100))], - "At {}", - i, - ), + 2..=10 => assert_eq!(finalized_blocks, vec![(parent_id, Some(100))], "At {}", i,), _ => assert_eq!(finalized_blocks, vec![], "At {}", i), } latest_block_id = rolling_last_block_id; } - assert!(storage.header(&genesis().compute_hash()).is_some()); + assert!(storage.header(&ctx.genesis.compute_hash()).is_some()); // header 11 finalizes headers [10] AND schedules change // => we prune header#0 - let header11 = custom_block_i(11, &validators, |header| { - header.log_bloom = (&[0xff; 256]).into(); - header.receipts_root = "2e60346495092587026484e868a5b3063749032b2ea3843844509a6320d7f951" - .parse() - .unwrap(); - }); + let header11 = HeaderBuilder::with_parent_number(10) + .log_bloom((&[0xff; 256]).into()) + .receipts_root( + "ead6c772ba0083bbff497ba0f4efe47c199a2655401096c21ab7450b6c466d97" + .parse() + .unwrap(), + ) + .sign_by_set(&validators); + let parent_id = header11.parent_id().unwrap(); let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, &mut KeepSomeHeadersBehindBest::default(), @@ -321,29 +321,20 @@ mod tests { )]), ) .unwrap(); - assert_eq!( - finalized_blocks, - vec![(block_i(10, &validators).compute_id(), Some(100))], - ); - assert!(storage.header(&genesis().compute_hash()).is_none()); + assert_eq!(finalized_blocks, vec![(parent_id, Some(100))],); + assert!(storage.header(&ctx.genesis.compute_hash()).is_none()); latest_block_id = rolling_last_block_id; // and now let's say validators 1 && 2 went offline // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers // until header#11 is met. we can't prune #11, because it schedules change - let mut step = 56; + let mut step = 56u64; let mut expected_blocks = vec![(header11.compute_id(), Some(101))]; for i in 12..25 { - let header = Header { - number: i as _, - parent_hash: latest_block_id.hash, - gas_limit: 0x2000.into(), - author: validator(2).address(), - seal: vec![vec![step].into(), vec![].into()], - difficulty: i.into(), - ..Default::default() - }; - let header = signed_header(&validators, header, step as _); + let header = HeaderBuilder::with_parent_hash(latest_block_id.hash) + .difficulty(i.into()) + .step(step) + .sign_by_set(&validators); expected_blocks.push((header.compute_id(), Some(102))); let (rolling_last_block_id, finalized_blocks) = import_header( &mut storage, @@ -370,16 +361,10 @@ mod tests { // now let's insert block signed by validator 1 // => blocks 11..24 are finalized and blocks 11..14 are pruned step -= 2; - let header = Header { - number: 25, - parent_hash: latest_block_id.hash, - gas_limit: 0x2000.into(), - author: validator(0).address(), - seal: vec![vec![step].into(), vec![].into()], - difficulty: 25.into(), - ..Default::default() - }; - let header = signed_header(&validators, header, step as _); + let header = HeaderBuilder::with_parent_hash(latest_block_id.hash) + .difficulty(25.into()) + .step(step) + .sign_by_set(&validators); let (_, finalized_blocks) = import_header( &mut storage, &mut KeepSomeHeadersBehindBest::default(), @@ -403,18 +388,9 @@ mod tests { fn import_custom_block( storage: &mut S, - validators: &[KeyPair], - number: u64, - step: u64, - customize: impl FnOnce(&mut Header), + validators: &[SecretKey], + header: Header, ) -> Result { - let header = custom_block_i(number, validators, |header| { - header.seal[0][0] = step as _; - header.author = - crate::validators::step_validator(&validators.iter().map(|kp| kp.address()).collect::>(), step); - customize(header); - }); - let header = signed_header(validators, header, step); let id = header.compute_id(); import_header( storage, @@ -422,7 +398,7 @@ mod tests { &test_aura_config(), &ValidatorsConfiguration::Single(ValidatorsSource::Contract( [0; 20].into(), - validators.iter().map(|kp| kp.address()).collect(), + validators.iter().map(secret_to_address).collect(), )), None, header, @@ -433,37 +409,41 @@ mod tests { #[test] fn import_of_non_best_block_may_finalize_blocks() { - const TOTAL_VALIDATORS: u8 = 3; - let validators_addresses = validators_addresses(TOTAL_VALIDATORS); - custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { - let validators = validators(TOTAL_VALIDATORS); + run_test(TOTAL_VALIDATORS, |ctx| { let mut storage = BridgeStorage::::new(); // insert headers (H1, validator1), (H2, validator1), (H3, validator1) // making H3 the best header, without finalizing anything (we need 2 signatures) let mut expected_best_block = Default::default(); for i in 1..4 { - let step = GENESIS_STEP + i * TOTAL_VALIDATORS as u64; - expected_best_block = import_custom_block(&mut storage, &validators, i, step, |header| { - header.author = validators_addresses[0]; - header.seal[0][0] = step as u8; - }) + let step = 1 + i * TOTAL_VALIDATORS as u64; + expected_best_block = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(i - 1) + .step(step) + .sign_by_set(&ctx.validators), + ) .unwrap(); } let (best_block, best_difficulty) = storage.best_block(); assert_eq!(best_block, expected_best_block); - assert_eq!(storage.finalized_block(), genesis().compute_id()); + assert_eq!(storage.finalized_block(), ctx.genesis.compute_id()); // insert headers (H1', validator1), (H2', validator2), finalizing H2, even though H3 // has better difficulty than H2' (because there are more steps involved) let mut expected_finalized_block = Default::default(); - let mut parent_hash = genesis().compute_hash(); + let mut parent_hash = ctx.genesis.compute_hash(); for i in 1..3 { - let step = GENESIS_STEP + i; - let id = import_custom_block(&mut storage, &validators, i, step, |header| { - header.gas_limit += 1.into(); - header.parent_hash = parent_hash; - }) + let step = i; + let id = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_hash(parent_hash) + .step(step) + .gas_limit((GAS_LIMIT + 1).into()) + .sign_by_set(&ctx.validators), + ) .unwrap(); parent_hash = id.hash; if i == 1 { @@ -479,83 +459,117 @@ mod tests { #[test] fn append_to_unfinalized_fork_fails() { - const TOTAL_VALIDATORS: u64 = 5; - let validators_addresses = validators_addresses(TOTAL_VALIDATORS as _); - custom_test_ext(genesis(), validators_addresses.clone()).execute_with(move || { - let validators = validators(TOTAL_VALIDATORS as _); + const VALIDATORS: u64 = 5; + run_test(VALIDATORS as usize, |ctx| { let mut storage = BridgeStorage::::new(); // header1, authored by validator[2] is best common block between two competing forks - let header1 = import_custom_block(&mut storage, &validators, 1, GENESIS_STEP + 1, |_| ()).unwrap(); + let header1 = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(0) + .step(2) + .sign_by_set(&ctx.validators), + ) + .unwrap(); assert_eq!(storage.best_block().0, header1); assert_eq!(storage.finalized_block().number, 0); // validator[3] has authored header2 (nothing is finalized yet) - let header2 = import_custom_block(&mut storage, &validators, 2, GENESIS_STEP + 2, |_| ()).unwrap(); + let header2 = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(1) + .step(3) + .sign_by_set(&ctx.validators), + ) + .unwrap(); assert_eq!(storage.best_block().0, header2); assert_eq!(storage.finalized_block().number, 0); // validator[4] has authored header3 (header1 is finalized) - let header3 = import_custom_block(&mut storage, &validators, 3, GENESIS_STEP + 3, |_| ()).unwrap(); + let header3 = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(2) + .step(4) + .sign_by_set(&ctx.validators), + ) + .unwrap(); assert_eq!(storage.best_block().0, header3); assert_eq!(storage.finalized_block(), header1); // validator[4] has authored 4 blocks: header2'...header5' (header1 is still finalized) - let header2_1 = import_custom_block(&mut storage, &validators, 2, GENESIS_STEP + 3, |header| { - header.gas_limit += 1.into(); - }) + let header2_1 = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(1) + .gas_limit((GAS_LIMIT + 1).into()) + .step(4) + .sign_by_set(&ctx.validators), + ) .unwrap(); let header3_1 = import_custom_block( &mut storage, - &validators, - 3, - GENESIS_STEP + 3 + TOTAL_VALIDATORS, - |header| { - header.parent_hash = header2_1.hash; - }, + &ctx.validators, + HeaderBuilder::with_parent_hash(header2_1.hash) + .step(4 + VALIDATORS) + .sign_by_set(&ctx.validators), ) .unwrap(); let header4_1 = import_custom_block( &mut storage, - &validators, - 4, - GENESIS_STEP + 3 + TOTAL_VALIDATORS * 2, - |header| { - header.parent_hash = header3_1.hash; - }, + &ctx.validators, + HeaderBuilder::with_parent_hash(header3_1.hash) + .step(4 + VALIDATORS * 2) + .sign_by_set(&ctx.validators), ) .unwrap(); let header5_1 = import_custom_block( &mut storage, - &validators, - 5, - GENESIS_STEP + 3 + TOTAL_VALIDATORS * 3, - |header| { - header.parent_hash = header4_1.hash; - }, + &ctx.validators, + HeaderBuilder::with_parent_hash(header4_1.hash) + .step(4 + VALIDATORS * 3) + .sign_by_set(&ctx.validators), ) .unwrap(); assert_eq!(storage.best_block().0, header5_1); assert_eq!(storage.finalized_block(), header1); // when we import header4 { parent = header3 }, authored by validator[0], header2 is finalized - let header4 = import_custom_block(&mut storage, &validators, 4, GENESIS_STEP + 4, |_| ()).unwrap(); + let header4 = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(3) + .step(5) + .sign_by_set(&ctx.validators), + ) + .unwrap(); assert_eq!(storage.best_block().0, header5_1); assert_eq!(storage.finalized_block(), header2); // when we import header5 { parent = header4 }, authored by validator[1], header3 is finalized - let _ = import_custom_block(&mut storage, &validators, 5, GENESIS_STEP + 5, |header| { - header.parent_hash = header4.hash; - }) + let header5 = import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_hash(header4.hash) + .step(6) + .sign_by_set(&ctx.validators), + ) .unwrap(); - assert_eq!(storage.best_block().0, header5_1); + assert_eq!(storage.best_block().0, header5); assert_eq!(storage.finalized_block(), header3); // import of header2'' { parent = header1 } fails, because it has number < best_finalized assert_eq!( - import_custom_block(&mut storage, &validators, 2, GENESIS_STEP + 3, |header| { - header.gas_limit += 2.into(); - }), + import_custom_block( + &mut storage, + &ctx.validators, + HeaderBuilder::with_parent_number(1) + .gas_limit((GAS_LIMIT + 1).into()) + .step(3) + .sign_by_set(&ctx.validators) + ), Err(Error::AncientHeader), ); @@ -564,10 +578,11 @@ mod tests { assert_eq!( import_custom_block( &mut storage, - &validators, - 6, - GENESIS_STEP + 3 + TOTAL_VALIDATORS * 4, - |_| () + &ctx.validators, + HeaderBuilder::with_parent_number(5) + .gas_limit((GAS_LIMIT + 1).into()) + .step(5 + VALIDATORS * 4) + .sign_by_set(&ctx.validators), ), Err(Error::TryingToFinalizeSibling), ); diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 4c495a8c1489c..1ff2c2a8ae0b4 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -37,9 +37,15 @@ mod import; mod validators; mod verification; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + #[cfg(test)] mod mock; +#[cfg(any(feature = "runtime-benchmarks", test))] +mod test_utils; + /// Maximal number of blocks we're pruning in single import call. const MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT: u64 = 8; @@ -464,32 +470,11 @@ decl_storage! { "Initial validators set can't be empty", ); - let initial_hash = config.initial_header.compute_hash(); - let initial_id = HeaderId { - number: config.initial_header.number, - hash: initial_hash, - }; - BestBlock::put((initial_id, config.initial_difficulty)); - FinalizedBlock::put(initial_id); - BlocksToPrune::put(PruningRange { - oldest_unpruned_block: config.initial_header.number, - oldest_block_to_keep: config.initial_header.number, - }); - HeadersByNumber::insert(config.initial_header.number, vec![initial_hash]); - Headers::::insert(initial_hash, StoredHeader { - submitter: None, - header: config.initial_header.clone(), - total_difficulty: config.initial_difficulty, - next_validators_set_id: 0, - last_signal_block: None, - }); - NextValidatorsSetId::put(1); - ValidatorsSets::insert(0, ValidatorsSet { - validators: config.initial_validators.clone(), - signal_block: None, - enact_block: initial_id, - }); - ValidatorsSetsRc::insert(0, 1); + initialize_storage::( + &config.initial_header, + config.initial_difficulty, + &config.initial_validators, + ); }) } } @@ -632,6 +617,13 @@ impl BridgeStorage { // physically remove headers and (probably) obsolete validators sets while let Some(hash) = blocks_at_number.pop() { let header = Headers::::take(&hash); + frame_support::debug::trace!( + target: "runtime", + "Pruning PoA header: ({}, {})", + number, + hash, + ); + ScheduledChanges::remove(hash); FinalityCache::::remove(hash); if let Some(header) = header { @@ -830,6 +822,53 @@ impl Storage for BridgeStorage { } } +/// Initialize storage. +pub(crate) fn initialize_storage( + initial_header: &Header, + initial_difficulty: U256, + initial_validators: &[Address], +) { + let initial_hash = initial_header.compute_hash(); + frame_support::debug::trace!( + target: "runtime", + "Initializing bridge with PoA header: ({}, {})", + initial_header.number, + initial_hash, + ); + + let initial_id = HeaderId { + number: initial_header.number, + hash: initial_hash, + }; + BestBlock::put((initial_id, initial_difficulty)); + FinalizedBlock::put(initial_id); + BlocksToPrune::put(PruningRange { + oldest_unpruned_block: initial_header.number, + oldest_block_to_keep: initial_header.number, + }); + HeadersByNumber::insert(initial_header.number, vec![initial_hash]); + Headers::::insert( + initial_hash, + StoredHeader { + submitter: None, + header: initial_header.clone(), + total_difficulty: initial_difficulty, + next_validators_set_id: 0, + last_signal_block: None, + }, + ); + NextValidatorsSetId::put(1); + ValidatorsSets::insert( + 0, + ValidatorsSet { + validators: initial_validators.to_vec(), + signal_block: None, + enact_block: initial_id, + }, + ); + ValidatorsSetsRc::insert(0, 1); +} + /// Verify that transaction is included into given finalized block. pub fn verify_transaction_finalized( storage: &S, @@ -894,10 +933,13 @@ pub(crate) mod tests { use super::*; use crate::finality::FinalityAncestor; use crate::mock::{ - block_i, custom_block_i, custom_test_ext, genesis, insert_header, validators, validators_addresses, TestRuntime, + genesis, insert_header, run_test, run_test_with_genesis, validators_addresses, HeaderBuilder, TestRuntime, + GAS_LIMIT, }; use primitives::compute_merkle_root; + const TOTAL_VALIDATORS: usize = 3; + fn example_tx() -> Vec { vec![42] } @@ -919,14 +961,13 @@ pub(crate) mod tests { } fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { - let validators = validators(3); + run_test(TOTAL_VALIDATORS, |ctx| { for i in 1..10 { let mut headers_by_number = Vec::with_capacity(5); for j in 0..5 { - let header = custom_block_i(i, &validators, |header| { - header.gas_limit = header.gas_limit + U256::from(j); - }); + let header = HeaderBuilder::with_parent_number(i - 1) + .gas_limit((GAS_LIMIT + j).into()) + .sign_by_set(&ctx.validators); let hash = header.compute_hash(); headers_by_number.push(hash); Headers::::insert( @@ -1082,21 +1123,20 @@ pub(crate) mod tests { #[test] fn finality_votes_are_cached() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |ctx| { let mut storage = BridgeStorage::::new(); let interval = ::FinalityVotesCachingInterval::get().unwrap(); // for all headers with number < interval, cache entry is not created - let validators = validators(3); for i in 1..interval { - let header = block_i(i, &validators); + let header = HeaderBuilder::with_parent_number(i - 1).sign_by_set(&ctx.validators); let id = header.compute_id(); insert_header(&mut storage, header); assert_eq!(FinalityCache::::get(&id.hash), None); } // for header with number = interval, cache entry is created - let header_with_entry = block_i(interval, &validators); + let header_with_entry = HeaderBuilder::with_parent_number(interval - 1).sign_by_set(&ctx.validators); let header_with_entry_hash = header_with_entry.compute_hash(); insert_header(&mut storage, header_with_entry); assert_eq!( @@ -1116,13 +1156,12 @@ pub(crate) mod tests { #[test] fn cached_finality_votes_finds_entry() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |ctx| { // insert 5 headers - let validators = validators(3); let mut storage = BridgeStorage::::new(); let mut headers = Vec::new(); for i in 1..5 { - let header = block_i(i, &validators); + let header = HeaderBuilder::with_parent_number(i - 1).sign_by_set(&ctx.validators); headers.push(header.clone()); insert_header(&mut storage, header); } @@ -1177,19 +1216,18 @@ pub(crate) mod tests { #[test] fn cached_finality_votes_stops_at_finalized_sibling() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { - let validators = validators(3); + run_test(TOTAL_VALIDATORS, |ctx| { let mut storage = BridgeStorage::::new(); // insert header1 - let header1 = block_i(1, &validators); + let header1 = HeaderBuilder::with_parent_number(0).sign_by_set(&ctx.validators); let header1_id = header1.compute_id(); insert_header(&mut storage, header1); // insert header1' - sibling of header1 - let header1s = custom_block_i(1, &validators, |header| { - header.gas_limit += 1.into(); - }); + let header1s = HeaderBuilder::with_parent_number(0) + .gas_limit((GAS_LIMIT + 1).into()) + .sign_by_set(&ctx.validators); let header1s_id = header1s.compute_id(); insert_header(&mut storage, header1s); @@ -1214,7 +1252,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_works_for_best_finalized_header() { - custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { + run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &vec![example_tx()],), @@ -1225,7 +1263,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_works_for_best_finalized_header_ancestor() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); @@ -1239,7 +1277,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_rejects_proof_with_missing_tx() { - custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { + run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &vec![],), @@ -1250,7 +1288,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_rejects_unknown_header() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &vec![],), @@ -1261,7 +1299,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_rejects_unfinalized_header() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); @@ -1274,7 +1312,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_rejects_finalized_header_sibling() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let mut finalized_header_sibling = example_header(); finalized_header_sibling.timestamp = 1; let finalized_header_sibling_hash = finalized_header_sibling.compute_hash(); @@ -1293,7 +1331,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_rejects_finalized_header_uncle() { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let mut finalized_header_uncle = example_header_parent(); finalized_header_uncle.timestamp = 1; let finalized_header_uncle_hash = finalized_header_uncle.compute_hash(); @@ -1312,7 +1350,7 @@ pub(crate) mod tests { #[test] fn verify_transaction_finalized_rejects_invalid_proof() { - custom_test_ext(example_header(), validators_addresses(3)).execute_with(|| { + run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( verify_transaction_finalized( diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 1575f6cf405d4..c169eaec3c87f 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -14,14 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +pub use crate::test_utils::{validator_utils::*, HeaderBuilder, GAS_LIMIT}; +pub use primitives::signatures::secret_to_address; + use crate::finality::FinalityVotes; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, HeadersByNumber, PruningStrategy, Storage, Trait}; -use frame_support::StorageMap; +use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, PruningStrategy, Storage, Trait}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; -use parity_crypto::publickey::{sign, KeyPair, Secret}; -use primitives::{rlp_encode, H520}; use primitives::{Address, Header, H256, U256}; +use secp256k1::SecretKey; use sp_runtime::{ testing::Header as SubstrateHeader, traits::{BlakeTwo256, IdentityLookup}, @@ -84,8 +85,17 @@ impl Trait for TestRuntime { type OnHeadersSubmitted = (); } -/// Step of genesis header. -pub const GENESIS_STEP: u64 = 42; +/// Test context. +pub struct TestContext { + /// Initial (genesis) header. + pub genesis: Header, + /// Number of initial validators. + pub total_validators: usize, + /// Secret keys of validators, ordered by validator index. + pub validators: Vec, + /// Addresses of validators, ordered by validator index. + pub addresses: Vec

, +} /// Aura configuration that is used in tests by default. pub fn test_aura_config() -> AuraConfiguration { @@ -108,72 +118,38 @@ pub fn test_validators_config() -> ValidatorsConfiguration { /// Genesis header that is used in tests by default. pub fn genesis() -> Header { - Header { - seal: vec![vec![GENESIS_STEP as _].into(), vec![].into()], - ..Default::default() - } -} - -/// Build default i-th block, using data from runtime storage. -pub fn block_i(number: u64, validators: &[KeyPair]) -> Header { - custom_block_i(number, validators, |_| {}) -} - -/// Build custom i-th block, using data from runtime storage. -pub fn custom_block_i(number: u64, validators: &[KeyPair], customize: impl FnOnce(&mut Header)) -> Header { - let validator_index: u8 = (number % (validators.len() as u64)) as _; - let mut header = Header { - number, - parent_hash: HeadersByNumber::get(number - 1).unwrap()[0].clone(), - gas_limit: 0x2000.into(), - author: validator(validator_index).address(), - seal: vec![vec![(number + GENESIS_STEP) as u8].into(), vec![].into()], - difficulty: number.into(), - ..Default::default() - }; - customize(&mut header); - signed_header(validators, header, number + GENESIS_STEP) -} - -/// Build signed header from given header. -pub fn signed_header(validators: &[KeyPair], mut header: Header, step: u64) -> Header { - let message = header.seal_hash(false).unwrap(); - let validator_index = (step % validators.len() as u64) as usize; - let signature = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()).unwrap(); - let signature: [u8; 65] = signature.into(); - let signature = H520::from(signature); - header.seal[1] = rlp_encode(&signature); - header -} - -/// Return key pair of given test validator. -pub fn validator(index: u8) -> KeyPair { - KeyPair::from_secret(Secret::from([index + 1; 32])).unwrap() -} - -/// Return key pairs of all test validators. -pub fn validators(count: u8) -> Vec { - (0..count).map(validator).collect() -} - -/// Return addresses of all test validators. -pub fn validators_addresses(count: u8) -> Vec
{ - (0..count).map(|i| validator(i).address()).collect() -} - -/// Prepare externalities to start with custom initial header. -pub fn custom_test_ext(initial_header: Header, initial_validators: Vec
) -> sp_io::TestExternalities { - let t = GenesisConfig { - initial_header, - initial_difficulty: 0.into(), - initial_validators, - } - .build_storage::() - .unwrap(); - sp_io::TestExternalities::new(t) -} - -/// Insert header into storage. + HeaderBuilder::genesis().sign_by(&validator(0)) +} + +/// Run test with default genesis header. +pub fn run_test(total_validators: usize, test: impl FnOnce(TestContext) -> T) -> T { + run_test_with_genesis(genesis(), total_validators, test) +} + +/// Run test with default genesis header. +pub fn run_test_with_genesis(genesis: Header, total_validators: usize, test: impl FnOnce(TestContext) -> T) -> T { + let validators = validators(total_validators); + let addresses = validators_addresses(total_validators); + sp_io::TestExternalities::new( + GenesisConfig { + initial_header: genesis.clone(), + initial_difficulty: 0.into(), + initial_validators: addresses.clone(), + } + .build_storage::() + .unwrap(), + ) + .execute_with(|| { + test(TestContext { + genesis, + total_validators, + validators, + addresses, + }) + }) +} + +/// Insert unverified header into storage. pub fn insert_header(storage: &mut S, header: Header) { storage.insert_header(HeaderToImport { context: storage.import_context(None, &header.parent_hash).unwrap(), diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs new file mode 100644 index 0000000000000..2a424542d76c8 --- /dev/null +++ b/modules/ethereum/src/test_utils.rs @@ -0,0 +1,233 @@ +// Copyright 2019-2020 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 . + +//! Utilities for testing and benchmarking the Ethereum Bridge Pallet. +//! +//! Although the name implies that it is used by tests, it shouldn't be be used _directly_ by tests. +//! Instead these utilities should be used by the Mock runtime, which in turn is used by tests. +//! +//! On the other hand, they may be used directly by the bechmarking module. + +use crate::verification::calculate_score; + +use primitives::{ + rlp_encode, + signatures::{secret_to_address, sign, SignHeader}, + Address, Bloom, Header, SealedEmptyStep, H256, U256, +}; +use secp256k1::SecretKey; +use sp_std::prelude::*; + +/// Gas limit valid in test environment. +pub const GAS_LIMIT: u64 = 0x2000; + +/// Test header builder. +pub struct HeaderBuilder { + header: Header, + parent_header: Header, +} + +impl HeaderBuilder { + /// Creates default genesis header. + pub fn genesis() -> Self { + let current_step = 0u64; + Self { + header: Header { + gas_limit: GAS_LIMIT.into(), + seal: vec![primitives::rlp_encode(¤t_step), vec![]], + ..Default::default() + }, + parent_header: Default::default(), + } + } + + /// Creates default header on top of parent with given hash. + #[cfg(test)] + pub fn with_parent_hash(parent_hash: H256) -> Self { + use crate::mock::TestRuntime; + use crate::Headers; + use frame_support::StorageMap; + + let parent_header = Headers::::get(&parent_hash).unwrap().header; + Self::with_parent(&parent_header) + } + + /// Creates default header on top of parent with given number. First parent is selected. + #[cfg(test)] + pub fn with_parent_number(parent_number: u64) -> Self { + use crate::HeadersByNumber; + use frame_support::StorageMap; + + let parent_hash = HeadersByNumber::get(parent_number).unwrap()[0].clone(); + Self::with_parent_hash(parent_hash) + } + + /// Creates default header on top of non-existent parent. + #[cfg(test)] + pub fn with_number(number: u64) -> Self { + Self::with_parent(&Header { + number: number - 1, + seal: vec![primitives::rlp_encode(&(number - 1)), vec![]], + ..Default::default() + }) + } + + /// Creates default header on top of given parent. + pub fn with_parent(parent_header: &Header) -> Self { + let parent_step = parent_header.step().unwrap(); + let current_step = parent_step + 1; + Self { + header: Header { + parent_hash: parent_header.compute_hash(), + number: parent_header.number + 1, + gas_limit: GAS_LIMIT.into(), + seal: vec![primitives::rlp_encode(¤t_step), vec![]], + difficulty: calculate_score(parent_step, current_step, 0), + ..Default::default() + }, + parent_header: parent_header.clone(), + } + } + + /// Update step of this header. + pub fn step(mut self, step: u64) -> Self { + let parent_step = self.parent_header.step(); + self.header.seal[0] = rlp_encode(&step); + self.header.difficulty = parent_step + .map(|parent_step| calculate_score(parent_step, step, 0)) + .unwrap_or_default(); + self + } + + /// Adds empty steps to this header. + pub fn empty_steps(mut self, empty_steps: &[(&SecretKey, u64)]) -> Self { + let sealed_empty_steps = empty_steps + .into_iter() + .map(|(author, step)| { + let mut empty_step = SealedEmptyStep { + step: *step, + signature: Default::default(), + }; + let message = empty_step.message(&self.header.parent_hash); + let signature: [u8; 65] = sign(author, message).into(); + empty_step.signature = signature.into(); + empty_step + }) + .collect::>(); + + // by default in test configuration headers are generated without empty steps seal + if self.header.seal.len() < 3 { + self.header.seal.push(Vec::new()); + } + + self.header.seal[2] = SealedEmptyStep::rlp_of(&sealed_empty_steps); + self + } + + /// Update difficulty field of this header. + pub fn difficulty(mut self, difficulty: U256) -> Self { + self.header.difficulty = difficulty; + self + } + + /// Update extra data field of this header. + pub fn extra_data(mut self, extra_data: Vec) -> Self { + self.header.extra_data = extra_data; + self + } + + /// Update gas limit field of this header. + pub fn gas_limit(mut self, gas_limit: U256) -> Self { + self.header.gas_limit = gas_limit; + self + } + + /// Update gas used field of this header. + pub fn gas_used(mut self, gas_used: U256) -> Self { + self.header.gas_used = gas_used; + self + } + + /// Update log bloom field of this header. + pub fn log_bloom(mut self, log_bloom: Bloom) -> Self { + self.header.log_bloom = log_bloom; + self + } + + /// Update receipts root field of this header. + pub fn receipts_root(mut self, receipts_root: H256) -> Self { + self.header.receipts_root = receipts_root; + self + } + + /// Update timestamp field of this header. + pub fn timestamp(mut self, timestamp: u64) -> Self { + self.header.timestamp = timestamp; + self + } + + /// Signs header by given author. + pub fn sign_by(self, author: &SecretKey) -> Header { + self.header.sign_by(author) + } + + /// Signs header by given authors set. + pub fn sign_by_set(self, authors: &[SecretKey]) -> Header { + self.header.sign_by_set(authors) + } +} + +/// Helper function for getting a genesis header which has been signed by an authority. +pub fn build_genesis_header(author: &SecretKey) -> Header { + let genesis = HeaderBuilder::genesis(); + genesis.header.sign_by(&author) +} + +/// Helper function for building a custom child header which has been signed by an authority. +pub fn build_custom_header(author: &SecretKey, previous: &Header, customize_header: F) -> Header +where + F: FnOnce(Header) -> Header, +{ + let new_header = HeaderBuilder::with_parent(&previous); + let custom_header = customize_header(new_header.header); + custom_header.sign_by(author) +} + +pub mod validator_utils { + use super::*; + + /// Return key pair of given test validator. + pub fn validator(index: usize) -> SecretKey { + let mut raw_secret = [0u8; 32]; + raw_secret[..8].copy_from_slice(&(index + 1).to_le_bytes()); + SecretKey::parse(&raw_secret).unwrap() + } + + /// Return key pairs of all test validators. + pub fn validators(count: usize) -> Vec { + (0..count).map(validator).collect() + } + + /// Return address of test validator. + pub fn validator_address(index: usize) -> Address { + secret_to_address(&validator(index)) + } + + /// Return addresses of all test validators. + pub fn validators_addresses(count: usize) -> Vec
{ + (0..count).map(validator_address).collect() + } +} diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 70aa246c90e56..e6a454cc63772 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -273,19 +273,16 @@ impl ValidatorsSource { } } -/// Get validator that should author the block at given step. -pub fn step_validator(header_validators: &[Address], header_step: u64) -> Address { - header_validators[(header_step % header_validators.len() as u64) as usize] -} - #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::mock::{custom_test_ext, genesis, validators_addresses, TestRuntime}; + use crate::mock::{run_test, validators_addresses, TestRuntime}; use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader}; use frame_support::StorageMap; use primitives::{TransactionOutcome, H256}; + const TOTAL_VALIDATORS: usize = 3; + pub(crate) fn validators_change_recept(parent_hash: H256) -> Receipt { Receipt { gas_used: 0.into(), @@ -425,7 +422,7 @@ pub(crate) mod tests { } fn try_finalize_with_scheduled_change(scheduled_at: Option) -> Option { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test(TOTAL_VALIDATORS, |_| { let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); let validators = Validators::new(&config); let storage = BridgeStorage::::new(); diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index dee912e26a157..031b85ab4aba7 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -15,10 +15,12 @@ // along with Parity Bridges Common. If not, see . use crate::error::Error; -use crate::validators::{step_validator, Validators, ValidatorsConfiguration}; +use crate::validators::{Validators, ValidatorsConfiguration}; use crate::{AuraConfiguration, ImportContext, PoolConfiguration, ScheduledChange, Storage}; use codec::Encode; -use primitives::{public_to_address, Address, Header, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256}; +use primitives::{ + public_to_address, step_validator, Address, Header, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, +}; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_std::{vec, vec::Vec}; @@ -157,9 +159,16 @@ pub fn verify_aura_header( contextless_checks(config, header)?; // the rest of checks requires access to the parent header - let context = storage - .import_context(submitter, &header.parent_hash) - .ok_or(Error::MissingParentBlock)?; + let context = storage.import_context(submitter, &header.parent_hash).ok_or_else(|| { + frame_support::debug::warn!( + target: "runtime", + "Missing parent PoA block: ({:?}, {})", + header.number.checked_sub(1), + header.parent_hash, + ); + + Error::MissingParentBlock + })?; let header_step = contextual_checks(config, &context, None, header)?; validator_checks(config, &context.validators_set().validators, header, header_step)?; @@ -263,7 +272,7 @@ fn validator_checks( header: &Header, header_step: u64, ) -> Result<(), Error> { - let expected_validator = step_validator(validators, header_step); + let expected_validator = *step_validator(validators, header_step); if header.author != expected_validator { return Err(Error::NotValidator); } @@ -282,7 +291,7 @@ fn validator_checks( /// Returns expected number of seal fields in the header. fn expected_header_seal_fields(config: &AuraConfiguration, header: &Header) -> usize { - if header.number >= config.empty_steps_transition { + if header.number != u64::max_value() && header.number >= config.empty_steps_transition { 3 } else { 2 @@ -291,13 +300,13 @@ fn expected_header_seal_fields(config: &AuraConfiguration, header: &Header) -> u /// Verify single sealed empty step. fn verify_empty_step(parent_hash: &H256, step: &SealedEmptyStep, validators: &[Address]) -> bool { - let expected_validator = step_validator(validators, step.step); + let expected_validator = *step_validator(validators, step.step); let message = step.message(parent_hash); verify_signature(&expected_validator, &step.signature, &message) } /// Chain scoring: total weight is sqrt(U256::max_value())*height - step -fn calculate_score(parent_step: u64, current_step: u64, current_empty_steps: usize) -> U256 { +pub(crate) fn calculate_score(parent_step: u64, current_step: u64, current_empty_steps: usize) -> U256 { U256::from(U128::max_value()) + U256::from(parent_step) - U256::from(current_step) + U256::from(current_empty_steps) } @@ -344,8 +353,8 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< mod tests { use super::*; use crate::mock::{ - block_i, custom_block_i, custom_test_ext, genesis, insert_header, signed_header, test_aura_config, validator, - validators_addresses, AccountId, TestRuntime, + insert_header, run_test_with_genesis, test_aura_config, validator, validator_address, validators_addresses, + AccountId, HeaderBuilder, TestRuntime, GAS_LIMIT, }; use crate::validators::{tests::validators_change_recept, ValidatorsSource}; use crate::{ @@ -353,25 +362,18 @@ mod tests { ScheduledChanges, ValidatorsSet, ValidatorsSets, }; use frame_support::{StorageMap, StorageValue}; - use parity_crypto::publickey::{sign, KeyPair}; use primitives::{rlp_encode, TransactionOutcome, H520}; + use secp256k1::SecretKey; - fn sealed_empty_step(validators: &[KeyPair], parent_hash: &H256, step: u64) -> SealedEmptyStep { - let mut empty_step = SealedEmptyStep { - step, - signature: Default::default(), - }; - let message = empty_step.message(parent_hash); - let validator_index = (step % validators.len() as u64) as usize; - let signature: [u8; 65] = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()) - .unwrap() - .into(); - empty_step.signature = signature.into(); - empty_step + const GENESIS_STEP: u64 = 42; + const TOTAL_VALIDATORS: usize = 3; + + fn genesis() -> Header { + HeaderBuilder::genesis().step(GENESIS_STEP).sign_by(&validator(0)) } fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result, Error> { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); verify_aura_header(&storage, &config, None, header) }) @@ -382,17 +384,17 @@ mod tests { } fn default_accept_into_pool( - mut make_header: impl FnMut(&[KeyPair]) -> (Header, Option>), + mut make_header: impl FnMut(&[SecretKey]) -> (Header, Option>), ) -> Result<(Vec>, Vec>), Error> { - custom_test_ext(genesis(), validators_addresses(3)).execute_with(|| { + run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let validators = vec![validator(0), validator(1), validator(2)]; let mut storage = BridgeStorage::::new(); - let block1 = block_i(1, &validators); + let block1 = HeaderBuilder::with_parent_number(0).sign_by_set(&validators); insert_header(&mut storage, block1); - let block2 = block_i(2, &validators); + let block2 = HeaderBuilder::with_parent_number(1).sign_by_set(&validators); let block2_id = block2.compute_id(); insert_header(&mut storage, block2); - let block3 = block_i(3, &validators); + let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators); insert_header(&mut storage, block3); FinalizedBlock::put(block2_id); @@ -468,32 +470,26 @@ mod tests { #[test] fn verifies_header_number() { // when number is u64::max_value() - let mut header = Header { - seal: vec![vec![].into(), vec![].into(), vec![].into()], - number: u64::max_value(), - ..Default::default() - }; + let header = HeaderBuilder::with_number(u64::max_value()).sign_by(&validator(0)); assert_eq!(default_verify(&header), Err(Error::RidiculousNumber)); // when header is < u64::max_value() - header.seal = vec![vec![].into(), vec![].into()]; - header.number -= 1; + let header = HeaderBuilder::with_number(u64::max_value() - 1).sign_by(&validator(0)); assert_ne!(default_verify(&header), Err(Error::RidiculousNumber)); } #[test] fn verifies_gas_used() { // when gas used is larger than gas limit - let mut header = Header { - seal: vec![vec![].into(), vec![].into()], - gas_used: 1.into(), - gas_limit: 0.into(), - ..Default::default() - }; + let header = HeaderBuilder::with_number(1) + .gas_used((GAS_LIMIT + 1).into()) + .sign_by(&validator(0)); assert_eq!(default_verify(&header), Err(Error::TooMuchGasUsed)); // when gas used is less than gas limit - header.gas_limit = 1.into(); + let header = HeaderBuilder::with_number(1) + .gas_used((GAS_LIMIT - 1).into()) + .sign_by(&validator(0)); assert_ne!(default_verify(&header), Err(Error::TooMuchGasUsed)); } @@ -504,67 +500,62 @@ mod tests { config.max_gas_limit = 200.into(); // when limit is lower than expected - let mut header = Header { - seal: vec![vec![].into(), vec![].into()], - gas_limit: 50.into(), - ..Default::default() - }; + let header = HeaderBuilder::with_number(1) + .gas_limit(50.into()) + .sign_by(&validator(0)); assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); // when limit is larger than expected - header.gas_limit = 250.into(); + let header = HeaderBuilder::with_number(1) + .gas_limit(250.into()) + .sign_by(&validator(0)); assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); // when limit is within expected range - header.gas_limit = 150.into(); + let header = HeaderBuilder::with_number(1) + .gas_limit(150.into()) + .sign_by(&validator(0)); assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); } #[test] fn verifies_extra_data_len() { // when extra data is too large - let mut header = Header { - seal: vec![vec![].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - extra_data: std::iter::repeat(42).take(1000).collect::>().into(), - number: 1, - ..Default::default() - }; + let header = HeaderBuilder::with_number(1) + .extra_data(std::iter::repeat(42).take(1000).collect::>()) + .sign_by(&validator(0)); assert_eq!(default_verify(&header), Err(Error::ExtraDataOutOfBounds)); // when extra data size is OK - header.extra_data = std::iter::repeat(42).take(10).collect::>().into(); + let header = HeaderBuilder::with_number(1) + .extra_data(std::iter::repeat(42).take(10).collect::>()) + .sign_by(&validator(0)); assert_ne!(default_verify(&header), Err(Error::ExtraDataOutOfBounds)); } #[test] fn verifies_timestamp() { // when timestamp overflows i32 - let mut header = Header { - seal: vec![vec![].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - timestamp: i32::max_value() as u64 + 1, - ..Default::default() - }; + let header = HeaderBuilder::with_number(1) + .timestamp(i32::max_value() as u64 + 1) + .sign_by(&validator(0)); assert_eq!(default_verify(&header), Err(Error::TimestampOverflow)); // when timestamp doesn't overflow i32 - header.timestamp -= 1; + let header = HeaderBuilder::with_number(1) + .timestamp(i32::max_value() as u64) + .sign_by(&validator(0)); assert_ne!(default_verify(&header), Err(Error::TimestampOverflow)); } #[test] fn verifies_parent_existence() { // when there's no parent in the storage - let mut header = Header { - seal: vec![vec![].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - ..Default::default() - }; + let header = HeaderBuilder::with_number(1).sign_by(&validator(0)); assert_eq!(default_verify(&header), Err(Error::MissingParentBlock)); // when parent is in the storage - header.parent_hash = genesis().compute_hash(); + let header = HeaderBuilder::with_parent(&genesis()).sign_by(&validator(0)); assert_ne!(default_verify(&header), Err(Error::MissingParentBlock)); } @@ -580,11 +571,11 @@ mod tests { assert_eq!(default_verify(&header), Err(Error::MissingStep)); // when step is the same as for the parent block - header.seal = vec![vec![42].into(), vec![].into()]; + header.seal[0] = rlp_encode(&42u64); assert_eq!(default_verify(&header), Err(Error::DoubleVote)); // when step is OK - header.seal = vec![vec![43].into(), vec![].into()]; + header.seal[0] = rlp_encode(&43u64); assert_ne!(default_verify(&header), Err(Error::DoubleVote)); // now check with validate_step check enabled @@ -592,52 +583,47 @@ mod tests { config.validate_step_transition = 0; // when step is lesser that for the parent block + header.seal[0] = rlp_encode(&40u64); header.seal = vec![vec![40].into(), vec![].into()]; assert_eq!(verify_with_config(&config, &header), Err(Error::DoubleVote)); // when step is OK - header.seal = vec![vec![44].into(), vec![].into()]; + header.seal[0] = rlp_encode(&44u64); assert_ne!(verify_with_config(&config, &header), Err(Error::DoubleVote)); } #[test] fn verifies_empty_step() { - let validators = vec![validator(0), validator(1), validator(2)]; let mut config = test_aura_config(); config.empty_steps_transition = 0; // when empty step duplicates parent step - let mut header = Header { - seal: vec![ - vec![45].into(), - vec![142].into(), - SealedEmptyStep::rlp_of(&[sealed_empty_step(&validators, &genesis().compute_hash(), 42)]), - ], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().compute_hash(), - ..Default::default() - }; + let header = HeaderBuilder::with_parent(&genesis()) + .empty_steps(&[(&validator(0), GENESIS_STEP)]) + .step(GENESIS_STEP + 3) + .sign_by(&validator(3)); assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); // when empty step signature check fails - let mut wrong_sealed_empty_step = sealed_empty_step(&validators, &genesis().compute_hash(), 43); - wrong_sealed_empty_step.signature = Default::default(); - header.seal[2] = SealedEmptyStep::rlp_of(&[wrong_sealed_empty_step]); + let header = HeaderBuilder::with_parent(&genesis()) + .empty_steps(&[(&validator(100), GENESIS_STEP + 1)]) + .step(GENESIS_STEP + 3) + .sign_by(&validator(3)); assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); // when we are accepting strict empty steps and they come not in order config.strict_empty_steps_transition = 0; - header.seal[2] = SealedEmptyStep::rlp_of(&[ - sealed_empty_step(&validators, &genesis().compute_hash(), 44), - sealed_empty_step(&validators, &genesis().compute_hash(), 43), - ]); + let header = HeaderBuilder::with_parent(&genesis()) + .empty_steps(&[(&validator(2), GENESIS_STEP + 2), (&validator(1), GENESIS_STEP + 1)]) + .step(GENESIS_STEP + 3) + .sign_by(&validator(3)); assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); // when empty steps are OK - header.seal[2] = SealedEmptyStep::rlp_of(&[ - sealed_empty_step(&validators, &genesis().compute_hash(), 43), - sealed_empty_step(&validators, &genesis().compute_hash(), 44), - ]); + let header = HeaderBuilder::with_parent(&genesis()) + .empty_steps(&[(&validator(1), GENESIS_STEP + 1), (&validator(2), GENESIS_STEP + 2)]) + .step(GENESIS_STEP + 3) + .sign_by(&validator(3)); assert_ne!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); } @@ -647,33 +633,19 @@ mod tests { config.validate_score_transition = 0; // when chain score is invalid - let mut header = Header { - seal: vec![vec![43].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().compute_hash(), - ..Default::default() - }; + let header = HeaderBuilder::with_parent(&genesis()) + .difficulty(100.into()) + .sign_by(&validator(0)); assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); // when chain score is accepted - header.difficulty = calculate_score(42, 43, 0); + let header = HeaderBuilder::with_parent(&genesis()).sign_by(&validator(0)); assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); } #[test] fn verifies_validator() { - let validators = vec![validator(0), validator(1), validator(2)]; - let good_header = signed_header( - &validators, - Header { - author: validators[1].address().as_fixed_bytes().into(), - seal: vec![vec![43].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().compute_hash(), - ..Default::default() - }, - 43, - ); + let good_header = HeaderBuilder::with_parent(&genesis()).sign_by(&validator(1)); // when header author is invalid let mut header = good_header.clone(); @@ -693,7 +665,7 @@ mod tests { fn pool_verifies_known_blocks() { // when header is known assert_eq!( - default_accept_into_pool(|validators| (block_i(3, validators), None)), + default_accept_into_pool(|validators| (HeaderBuilder::with_parent_number(2).sign_by_set(validators), None)), Err(Error::KnownHeader), ); } @@ -703,7 +675,9 @@ mod tests { // when header number is less than finalized assert_eq!( default_accept_into_pool(|validators| ( - custom_block_i(2, validators, |header| header.gas_limit += 1.into()), + HeaderBuilder::with_parent_number(1) + .gas_limit((GAS_LIMIT + 1).into()) + .sign_by_set(validators), None, ),), Err(Error::AncientHeader), @@ -731,7 +705,7 @@ mod tests { fn pool_rejects_headers_with_redundant_receipts() { assert_eq!( default_accept_into_pool(|validators| ( - block_i(4, validators), + HeaderBuilder::with_parent_number(3).sign_by_set(validators), Some(vec![Receipt { gas_used: 1.into(), log_bloom: (&[0xff; 256]).into(), @@ -747,7 +721,7 @@ mod tests { fn pool_verifies_future_block_number() { // when header is too far from the future assert_eq!( - default_accept_into_pool(|validators| (custom_block_i(4, validators, |header| header.number = 100), None,),), + default_accept_into_pool(|validators| (HeaderBuilder::with_number(100).sign_by_set(&validators), None),), Err(Error::UnsignedTooFarInTheFuture), ); } @@ -758,8 +732,9 @@ mod tests { // checks for DoubleVote assert_eq!( default_accept_into_pool(|validators| ( - custom_block_i(4, validators, |header| header.seal[0] = - block_i(3, validators).seal[0].clone()), + HeaderBuilder::with_parent_number(3) + .step(GENESIS_STEP + 3) + .sign_by_set(&validators), None, ),), Err(Error::DoubleVote), @@ -772,21 +747,7 @@ mod tests { // (even if header will be considered invalid/duplicate later, we can use this signature // as a proof of malicious action by this validator) assert_eq!( - default_accept_into_pool(|validators| ( - signed_header( - validators, - Header { - author: validators[1].address().as_fixed_bytes().into(), - seal: vec![vec![8].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: [42; 32].into(), - number: 8, - ..Default::default() - }, - 43 - ), - None, - )), + default_accept_into_pool(|_| (HeaderBuilder::with_number(8).step(8).sign_by(&validator(1)), None,)), Err(Error::NotValidator), ); } @@ -796,7 +757,7 @@ mod tests { let mut hash = None; assert_eq!( default_accept_into_pool(|validators| { - let header = block_i(4, &validators); + let header = HeaderBuilder::with_parent_number(3).sign_by_set(validators); hash = Some(header.compute_hash()); (header, None) }), @@ -814,32 +775,22 @@ mod tests { #[test] fn pool_verifies_header_with_unknown_parent() { - let mut hash = None; + let mut id = None; + let mut parent_id = None; assert_eq!( default_accept_into_pool(|validators| { - let header = signed_header( - validators, - Header { - author: validators[2].address().as_fixed_bytes().into(), - seal: vec![vec![47].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: [42; 32].into(), - number: 5, - ..Default::default() - }, - 47, - ); - hash = Some(header.compute_hash()); + let header = HeaderBuilder::with_number(5) + .step(GENESIS_STEP + 5) + .sign_by_set(validators); + id = Some(header.compute_id()); + parent_id = header.parent_id(); (header, None) }), Ok(( // parent tag required - vec![(4u64, [42u8; 32]).encode(),], + vec![parent_id.unwrap().encode()], // header provides two tags - vec![ - (5u64, validators_addresses(3)[2]).encode(), - (5u64, hash.unwrap()).encode(), - ], + vec![(5u64, validator_address(2)).encode(), id.unwrap().encode(),], )), ); } @@ -852,55 +803,36 @@ mod tests { change_validators_set_at(3, validators_addresses(1), None); // header is signed using wrong set - let header = signed_header( - actual_validators, - Header { - author: actual_validators[2].address().as_fixed_bytes().into(), - seal: vec![vec![47].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: [42; 32].into(), - number: 5, - ..Default::default() - }, - 47, - ); + let header = HeaderBuilder::with_number(5) + .step(GENESIS_STEP + 2) + .sign_by_set(actual_validators); (header, None) }), Err(Error::NotValidator), ); - let mut hash = None; + let mut id = None; + let mut parent_id = None; assert_eq!( default_accept_into_pool(|actual_validators| { // change finalized set at parent header + signal valid set at parent block change_validators_set_at(3, validators_addresses(10), Some(validators_addresses(3))); // header is signed using wrong set - let header = signed_header( - actual_validators, - Header { - author: actual_validators[2].address().as_fixed_bytes().into(), - seal: vec![vec![47].into(), vec![].into()], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: [42; 32].into(), - number: 5, - ..Default::default() - }, - 47, - ); - hash = Some(header.compute_hash()); + let header = HeaderBuilder::with_number(5) + .step(GENESIS_STEP + 2) + .sign_by_set(actual_validators); + id = Some(header.compute_id()); + parent_id = header.parent_id(); (header, None) }), Ok(( // parent tag required - vec![(4u64, [42u8; 32]).encode(),], + vec![parent_id.unwrap().encode(),], // header provides two tags - vec![ - (5u64, validators_addresses(3)[2]).encode(), - (5u64, hash.unwrap()).encode(), - ], + vec![(5u64, validator_address(2)).encode(), id.unwrap().encode(),], )), ); } @@ -909,9 +841,9 @@ mod tests { fn pool_rejects_headers_with_invalid_receipts() { assert_eq!( default_accept_into_pool(|validators| { - let header = custom_block_i(4, &validators, |header| { - header.log_bloom = (&[0xff; 256]).into(); - }); + let header = HeaderBuilder::with_parent_number(3) + .log_bloom((&[0xff; 256]).into()) + .sign_by_set(validators); (header, Some(vec![validators_change_recept(Default::default())])) }), Err(Error::TransactionsReceiptsMismatch), @@ -923,12 +855,14 @@ mod tests { let mut hash = None; assert_eq!( default_accept_into_pool(|validators| { - let header = custom_block_i(4, &validators, |header| { - header.log_bloom = (&[0xff; 256]).into(); - header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" - .parse() - .unwrap(); - }); + let header = HeaderBuilder::with_parent_number(3) + .log_bloom((&[0xff; 256]).into()) + .receipts_root( + "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" + .parse() + .unwrap(), + ) + .sign_by_set(validators); hash = Some(header.compute_hash()); (header, Some(vec![validators_change_recept(Default::default())])) }), diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 96c60c3efc6f7..a444d659bceec 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -20,9 +20,6 @@ hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } -[dev-dependencies] -hex-literal = "0.2" - # Substrate Based Dependencies [dependencies.sp-api] version = "2.0.0-rc3" @@ -48,9 +45,18 @@ default-features = false rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" +[dependencies.libsecp256k1] +optional = true +version = "0.3.4" +default-features = false +features = ["hmac"] + +[dev-dependencies] +hex-literal = "0.2" + [features] default = ["std"] -test-helpers = [] +test-helpers = ["libsecp256k1"] std = [ "serde/std", "serde-big-array", diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 12ee571315358..ca804b32bda99 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -18,8 +18,6 @@ pub use parity_bytes::Bytes; pub use primitive_types::{H160, H256, H512, U128, U256}; - -#[cfg(feature = "test-helpers")] pub use rlp::encode as rlp_encode; use codec::{Decode, Encode}; @@ -49,6 +47,9 @@ pub type RawTransaction = Vec; /// An ethereum address. pub type Address = H160; +#[cfg(any(feature = "test-helpers", test))] +pub mod signatures; + /// Complete header id. #[derive(Encode, Decode, Default, RuntimeDebug, PartialEq, Clone, Copy)] pub struct HeaderId { @@ -59,8 +60,8 @@ pub struct HeaderId { } /// An Aura header. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Default, Serialize, Deserialize))] +#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Header { /// Parent block hash. pub parent_hash: H256, @@ -457,6 +458,11 @@ pub fn compute_merkle_root>(items: impl Iterator) -> H2 triehash::ordered_trie_root::(items) } +/// Get validator that should author the block at given step. +pub fn step_validator(header_validators: &[T], header_step: u64) -> &T { + &header_validators[(header_step % header_validators.len() as u64) as usize] +} + sp_api::decl_runtime_apis! { /// API for headers submitters. pub trait EthereumHeadersApi { diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs new file mode 100644 index 0000000000000..4eae9d16b1339 --- /dev/null +++ b/primitives/ethereum-poa/src/signatures.rs @@ -0,0 +1,66 @@ +// Copyright 2020 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 . +// + +//! Helpers related to signatures. +//! +//! Used for testing and benchmarking. + +use crate::{public_to_address, rlp_encode, step_validator, Address, Header, H256, H520}; + +use secp256k1::{Message, PublicKey, SecretKey}; + +/// Utilities for signing headers. +pub trait SignHeader { + /// Signs header by given author. + fn sign_by(self, author: &SecretKey) -> Header; + /// Signs header by given authors set. + fn sign_by_set(self, authors: &[SecretKey]) -> Header; +} + +impl SignHeader for Header { + fn sign_by(mut self, author: &SecretKey) -> Self { + self.author = secret_to_address(author); + + let message = self.seal_hash(false).unwrap(); + let signature = sign(author, message); + self.seal[1] = rlp_encode(&signature); + self + } + + fn sign_by_set(self, authors: &[SecretKey]) -> Self { + let step = self.step().unwrap(); + let author = step_validator(authors, step); + self.sign_by(author) + } +} + +/// Return author's signature over given message. +pub fn sign(author: &SecretKey, message: H256) -> H520 { + let (signature, recovery_id) = secp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); + let mut raw_signature = [0u8; 65]; + raw_signature[..64].copy_from_slice(&signature.serialize()); + raw_signature[64] = recovery_id.serialize(); + raw_signature.into() +} + +/// Returns address corresponding to given secret key. +pub fn secret_to_address(secret: &SecretKey) -> Address { + let public = PublicKey::from_secret_key(secret); + let mut raw_public = [0u8; 64]; + raw_public.copy_from_slice(&public.serialize()[1..]); + public_to_address(&raw_public) +} From 7129d500705e2c977553e9847dae2117626618db Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2020 01:56:04 +0000 Subject: [PATCH 0085/1210] Bump parking_lot from 0.10.2 to 0.11.0 (#151) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 0505ff8bc1855..6d50e0d857979 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ linked-hash-map = "0.5.3" log = "0.4.8" num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } -parking_lot = "0.10.2" +parking_lot = "0.11.0" rustc-hex = "2.0.1" serde = { version = "1.0.114", features = ["derive"] } serde_json = "1.0.55" From b3003a20c493e8dc1aca6be681b4273a26f221ab Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 29 Jun 2020 02:26:30 +0000 Subject: [PATCH 0086/1210] Bump derive_more from 0.99.8 to 0.99.9 (#152) --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index c40d287824038..2b8e26f6286ab 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" async-std = "=1.5.0" clap = "2.33.1" ctrlc = "3.1.4" -derive_more = "0.99.8" +derive_more = "0.99.9" env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } From 5962276e0c0bcf197de97cf21c92913578179aa4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Jul 2020 10:40:01 +0300 Subject: [PATCH 0087/1210] Create accounts from DepositInto::deposit_into() (#157) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use deposit_creating in DepositInto * Update modules/currency-exchange/src/lib.rs Co-authored-by: Tomasz Drwięga * Update primitives/currency-exchange/src/lib.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- bin/node/runtime/src/lib.rs | 119 ++++++++++++++++++++++-- modules/currency-exchange/src/lib.rs | 40 +++++++- primitives/currency-exchange/src/lib.rs | 2 + 3 files changed, 147 insertions(+), 14 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 450bd4d8791d1..b967cf07f760d 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -49,7 +49,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::{Currency, ExistenceRequirement, KeyOwnerProofSystem, Randomness}, + traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, Randomness}, weights::{IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -246,26 +246,53 @@ impl sp_currency_exchange::DepositInto for DepositInto { type Amount = Balance; fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { - as Currency>::deposit_into_existing(&recipient, amount) - .map(|_| { + // let balances module make all checks for us (it won't allow depositing lower than existential + // deposit, balance overflow, ...) + let deposited = as Currency>::deposit_creating(&recipient, amount); + + // I'm dropping deposited here explicitly to illustrate the fact that it'll update `TotalIssuance` + // on drop + let deposited_amount = deposited.peek(); + drop(deposited); + + // we have 3 cases here: + // - deposited == amount: success + // - deposited == 0: deposit has failed and no changes to storage were made + // - deposited != 0: (should never happen in practice) deposit has been partially completed + match deposited_amount { + _ if deposited_amount == amount => { frame_support::debug::trace!( target: "runtime", "Deposited {} to {:?}", amount, recipient, ); - }) - .map_err(|e| { + + Ok(()) + } + _ if deposited_amount == 0 => { + frame_support::debug::error!( + target: "runtime", + "Deposit of {} to {:?} has failed", + amount, + recipient, + ); + + Err(sp_currency_exchange::Error::DepositFailed) + } + _ => { frame_support::debug::error!( target: "runtime", - "Deposit of {} to {:?} has failed with: {:?}", + "Deposit of {} to {:?} has partially competed. {} has been deposited", amount, recipient, - e + deposited_amount, ); - sp_currency_exchange::Error::DepositFailed - }) + // we can't return DepositFailed error here, because storage changes were made + Err(sp_currency_exchange::Error::DepositPartiallyFailed) + } + } } } @@ -599,6 +626,7 @@ impl_runtime_apis! { #[cfg(test)] mod tests { use super::*; + use sp_currency_exchange::DepositInto; #[test] fn shift_session_manager_works() { @@ -639,4 +667,77 @@ mod tests { vec![acc1, acc2, acc3], ); } + + fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) { + let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::().unwrap().into(); + ext.execute_with(|| { + // initially issuance is zero + assert_eq!( + as Currency>::total_issuance(), + 0, + ); + + // create account + let account: AccountId = [1u8; 32].into(); + let initial_amount = ExistentialDeposit::get(); + let deposited = + as Currency>::deposit_creating(&account, initial_amount); + drop(deposited); + assert_eq!( + as Currency>::total_issuance(), + initial_amount, + ); + assert_eq!( + as Currency>::free_balance(&account), + initial_amount, + ); + + // run test + let total_issuance_change = test(account); + + // check that total issuance has changed by `run_deposit_into_test` + assert_eq!( + as Currency>::total_issuance(), + initial_amount + total_issuance_change, + ); + }); + } + + #[test] + fn deposit_into_existing_account_works() { + run_deposit_into_test(|existing_account| { + let initial_amount = + as Currency>::free_balance(&existing_account); + let additional_amount = 10_000; + ::DepositInto::deposit_into( + existing_account.clone(), + additional_amount, + ) + .unwrap(); + assert_eq!( + as Currency>::free_balance(&existing_account), + initial_amount + additional_amount, + ); + additional_amount + }); + } + + #[test] + fn deposit_into_new_account_works() { + run_deposit_into_test(|_| { + let initial_amount = 0; + let additional_amount = ExistentialDeposit::get() + 10_000; + let new_account: AccountId = [42u8; 32].into(); + ::DepositInto::deposit_into( + new_account.clone(), + additional_amount, + ) + .unwrap(); + assert_eq!( + as Currency>::free_balance(&new_account), + initial_amount + additional_amount, + ); + additional_amount + }); + } } diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index a4ef7360f9ed6..cfefd5b4adb37 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -83,6 +83,8 @@ decl_error! { FailedToConvertCurrency, /// Deposit has failed. DepositFailed, + /// Deposit has partially failed (changes to recipient account were made). + DepositPartiallyFailed, /// Transaction is not finalized. UnfinalizedTransaction, /// Transaction funds are already claimed. @@ -121,7 +123,14 @@ decl_module! { // make sure to update the mapping if we deposit successfully to avoid double spending, // i.e. whenever `deposit_into` is successful we MUST update `Transfers`. { - T::DepositInto::deposit_into(recipient, amount).map_err(Error::::from)?; + // if any changes were made to the storage, we can't just return error here, because + // otherwise the same proof may be imported again + let deposit_result = T::DepositInto::deposit_into(recipient, amount); + match deposit_result { + Ok(_) => (), + Err(ExchangeError::DepositPartiallyFailed) => (), + Err(error) => Err(Error::::from(error))?, + } Transfers::::insert(transfer_id, ()) } @@ -149,6 +158,7 @@ impl From for Error { ExchangeError::FailedToMapRecipients => Error::FailedToMapRecipients, ExchangeError::FailedToConvertCurrency => Error::FailedToConvertCurrency, ExchangeError::DepositFailed => Error::DepositFailed, + ExchangeError::DepositPartiallyFailed => Error::DepositPartiallyFailed, } } } @@ -254,9 +264,12 @@ mod tests { type Amount = u64; fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { - match amount > MAX_DEPOSIT_AMOUNT { - true => Err(sp_currency_exchange::Error::DepositFailed), - _ => Ok(()), + if amount < MAX_DEPOSIT_AMOUNT * 10 { + Ok(()) + } else if amount == MAX_DEPOSIT_AMOUNT * 10 { + Err(ExchangeError::DepositPartiallyFailed) + } else { + Err(ExchangeError::DepositFailed) } } } @@ -393,7 +406,7 @@ mod tests { fn transaction_with_invalid_deposit_rejected() { new_test_ext().execute_with(|| { let mut transaction = transaction(0); - transaction.amount = MAX_DEPOSIT_AMOUNT; + transaction.amount = MAX_DEPOSIT_AMOUNT + 1; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), Error::::DepositFailed, @@ -401,6 +414,23 @@ mod tests { }); } + #[test] + fn valid_transaction_accepted_even_if_deposit_partially_fails() { + new_test_ext().execute_with(|| { + let mut transaction = transaction(0); + transaction.amount = MAX_DEPOSIT_AMOUNT; + assert_ok!(Exchange::import_peer_transaction( + Origin::signed(SUBMITTER), + (true, transaction), + ),); + + // ensure that the transfer has been marked as completed + assert!(::Transfers::contains_key(0u64)); + // ensure that submitter has been rewarded + assert!(::Transfers::contains_key(SUBMITTER)); + }); + } + #[test] fn valid_transaction_accepted() { new_test_ext().execute_with(|| { diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index 59e411c1bcfbb..f864d4b733a90 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -35,6 +35,8 @@ pub enum Error { FailedToConvertCurrency, /// Deposit has failed. DepositFailed, + /// Deposit has partially failed (changes to recipient account were made). + DepositPartiallyFailed, } /// Result of all exchange operations. From e2440d06814a45bf42095000e1c125d9ca1762dc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 2 Jul 2020 23:41:53 +0300 Subject: [PATCH 0088/1210] Sign PoA transactions from wasm env (#155) * sign PoA transactions from wasm env * cargo fmt --all --- bin/node/runtime/Cargo.toml | 9 +- bin/node/runtime/src/exchange.rs | 43 ++++--- primitives/ethereum-poa/src/lib.rs | 143 +++++++++++++++------- primitives/ethereum-poa/src/signatures.rs | 81 +++++++++++- 4 files changed, 208 insertions(+), 68 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index ddee4842a9293..3e473687334e5 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -9,9 +9,6 @@ repository = "https://github.com/paritytech/parity-bridges-common/" [dependencies] hex-literal = "0.2" -[dev-dependencies] -ethereum-tx-sign = "3.0" - [dependencies.codec] package = "parity-scale-codec" version = "1.0.0" @@ -202,6 +199,12 @@ default-features = false rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" +[dev-dependencies.sp-bridge-eth-poa] +version = "0.1.0" +default-features = false +features = ["test-helpers"] +path = "../../../primitives/ethereum-poa" + [build-dependencies.wasm-builder-runner] version = "1.0.5" package = "substrate-wasm-builder-runner" diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index e269882a50d4d..8a627e8a2c868 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -31,7 +31,7 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_currency_exchange::Blockchain; -use sp_bridge_eth_poa::transaction_decode; +use sp_bridge_eth_poa::{transaction_decode, RawTransaction}; use sp_currency_exchange::{ Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, }; @@ -48,7 +48,7 @@ pub struct EthereumTransactionInclusionProof { /// Index of the transaction within the block. pub index: u64, /// The proof itself (right now it is all RLP-encoded transactions of the block). - pub proof: Vec>, + pub proof: Vec, } /// We uniquely identify transfer by the pair (sender, nonce). @@ -69,7 +69,7 @@ pub struct EthereumTransactionTag { pub struct EthBlockchain; impl Blockchain for EthBlockchain { - type Transaction = Vec; + type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { @@ -88,7 +88,7 @@ impl Blockchain for EthBlockchain { pub struct EthTransaction; impl MaybeLockFundsTransaction for EthTransaction { - type Transaction = Vec; + type Transaction = RawTransaction; type Id = EthereumTransactionTag; type Recipient = crate::AccountId; type Amount = crate::Balance; @@ -99,19 +99,19 @@ impl MaybeLockFundsTransaction for EthTransaction { let tx = transaction_decode(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?; // we only accept transactions sending funds directly to the pre-configured address - if tx.to != Some(LOCK_FUNDS_ADDRESS.into()) { + if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) { frame_support::debug::error!( target: "runtime", "Failed to parse fund locks transaction. Invalid peer recipient: {:?}", - tx.to, + tx.unsigned.to, ); return Err(ExchangeError::InvalidTransaction); } let mut recipient_raw = sp_core::H256::default(); - match tx.payload.len() { - 32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.payload), + match tx.unsigned.payload.len() { + 32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.unsigned.payload), len => { frame_support::debug::error!( target: "runtime", @@ -122,13 +122,13 @@ impl MaybeLockFundsTransaction for EthTransaction { return Err(ExchangeError::InvalidRecipient); } } - let amount = tx.value.low_u128(); + let amount = tx.unsigned.value.low_u128(); - if tx.value != amount.into() { + if tx.unsigned.value != amount.into() { frame_support::debug::error!( target: "runtime", "Failed to parse fund locks transaction. Invalid amount: {}", - tx.value, + tx.unsigned.value, ); return Err(ExchangeError::InvalidAmount); @@ -137,7 +137,7 @@ impl MaybeLockFundsTransaction for EthTransaction { Ok(LockFundsTransaction { id: EthereumTransactionTag { account: *tx.sender.as_fixed_bytes(), - nonce: tx.nonce, + nonce: tx.unsigned.nonce, }, recipient: crate::AccountId::from(*recipient_raw.as_fixed_bytes()), amount, @@ -149,29 +149,36 @@ impl MaybeLockFundsTransaction for EthTransaction { mod tests { use super::*; use hex_literal::hex; + use sp_bridge_eth_poa::{ + signatures::{SecretKey, SignTransaction}, + UnsignedTransaction, + }; fn ferdie() -> crate::AccountId { hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into() } - fn prepare_ethereum_transaction(editor: impl Fn(&mut ethereum_tx_sign::RawTransaction)) -> Vec { + fn prepare_ethereum_transaction(editor: impl Fn(&mut UnsignedTransaction)) -> Vec { // prepare tx for OpenEthereum private dev chain: // chain id is 0x11 // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 let chain_id = 0x11_u64; - let signer = hex!("4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7"); + let signer = SecretKey::parse(&hex!( + "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" + )) + .unwrap(); let ferdie_id = ferdie(); let ferdie_raw: &[u8; 32] = ferdie_id.as_ref(); - let mut eth_tx = ethereum_tx_sign::RawTransaction { + let mut eth_tx = UnsignedTransaction { nonce: 0.into(), to: Some(LOCK_FUNDS_ADDRESS.into()), value: 100.into(), gas: 100_000.into(), gas_price: 100_000.into(), - data: ferdie_raw.to_vec(), + payload: ferdie_raw.to_vec(), }; editor(&mut eth_tx); - eth_tx.sign(&signer.into(), &chain_id) + eth_tx.sign_by(&signer, Some(chain_id)) } #[test] @@ -211,7 +218,7 @@ mod tests { fn transaction_with_invalid_recipient_rejected() { assert_eq!( EthTransaction::parse(&prepare_ethereum_transaction(|tx| { - tx.data.clear(); + tx.payload.clear(); })), Err(ExchangeError::InvalidRecipient), ); diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index ca804b32bda99..a4fac244bf792 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -97,12 +97,24 @@ pub struct Header { } /// Parsed ethereum transaction. -#[derive(Debug, PartialEq)] +#[derive(PartialEq, RuntimeDebug)] pub struct Transaction { /// Sender address. pub sender: Address, + /// Unsigned portion of ethereum transaction. + pub unsigned: UnsignedTransaction, +} + +/// Unsigned portion of ethereum transaction. +#[derive(PartialEq, RuntimeDebug)] +#[cfg_attr(test, derive(Clone))] +pub struct UnsignedTransaction { /// Sender nonce. pub nonce: U256, + /// Gas price. + pub gas_price: U256, + /// Gas limit. + pub gas: U256, /// Transaction destination address. None if it is contract creation transaction. pub to: Option
, /// Transaction value. @@ -259,6 +271,55 @@ impl Header { } } +impl UnsignedTransaction { + /// Decode unsigned portion of raw transaction RLP. + pub fn decode(raw_tx: &[u8]) -> Result { + let tx_rlp = Rlp::new(raw_tx); + let to = tx_rlp.at(3)?; + Ok(UnsignedTransaction { + nonce: tx_rlp.val_at(0)?, + gas_price: tx_rlp.val_at(1)?, + gas: tx_rlp.val_at(2)?, + to: match to.is_empty() { + false => Some(to.as_val()?), + true => None, + }, + value: tx_rlp.val_at(4)?, + payload: tx_rlp.val_at(5)?, + }) + } + + /// Returns message that has to be signed to sign this transaction. + pub fn message(&self, chain_id: Option) -> H256 { + keccak_256(&self.rlp(chain_id)).into() + } + + /// Returns unsigned transaction RLP. + pub fn rlp(&self, chain_id: Option) -> Bytes { + let mut stream = RlpStream::new_list(if chain_id.is_some() { 9 } else { 6 }); + self.rlp_to(chain_id, &mut stream); + stream.out() + } + + /// Encode to given rlp stream. + pub fn rlp_to(&self, chain_id: Option, stream: &mut RlpStream) { + stream.append(&self.nonce); + stream.append(&self.gas_price); + stream.append(&self.gas); + match self.to { + Some(to) => stream.append(&to), + None => stream.append(&""), + }; + stream.append(&self.value); + stream.append(&self.payload); + if let Some(chain_id) = chain_id { + stream.append(&chain_id); + stream.append(&0u8); + stream.append(&0u8); + } + } +} + impl Receipt { /// Returns receipt RLP. fn rlp(&self) -> Bytes { @@ -373,17 +434,8 @@ impl std::fmt::Debug for Bloom { /// Decode Ethereum transaction. pub fn transaction_decode(raw_tx: &[u8]) -> Result { // parse transaction fields + let unsigned = UnsignedTransaction::decode(raw_tx)?; let tx_rlp = Rlp::new(raw_tx); - let nonce: U256 = tx_rlp.val_at(0)?; - let gas_price = tx_rlp.at(1)?; - let gas = tx_rlp.at(2)?; - let action = tx_rlp.at(3)?; - let to = match action.is_empty() { - false => Some(action.as_val()?), - true => None, - }; - let value: U256 = tx_rlp.val_at(4)?; - let payload: Bytes = tx_rlp.val_at(5)?; let v: u64 = tx_rlp.val_at(6)?; let r: U256 = tx_rlp.val_at(7)?; let s: U256 = tx_rlp.val_at(8)?; @@ -401,31 +453,16 @@ pub fn transaction_decode(raw_tx: &[u8]) -> Result Header; } +/// Utilities for signing transactions. +pub trait SignTransaction { + /// Sign transaction by given author. + fn sign_by(self, author: &SecretKey, chain_id: Option) -> RawTransaction; +} + impl SignHeader for Header { fn sign_by(mut self, author: &SecretKey) -> Self { self.author = secret_to_address(author); @@ -48,6 +60,24 @@ impl SignHeader for Header { } } +impl SignTransaction for UnsignedTransaction { + fn sign_by(self, author: &SecretKey, chain_id: Option) -> RawTransaction { + let message = self.message(chain_id); + let signature = sign(author, message); + let signature_r = U256::from_big_endian(&signature.as_fixed_bytes()[..32][..]); + let signature_s = U256::from_big_endian(&signature.as_fixed_bytes()[32..64][..]); + let signature_v = signature.as_fixed_bytes()[64] as u64; + let signature_v = signature_v + if let Some(n) = chain_id { 35 + n * 2 } else { 27 }; + + let mut stream = rlp::RlpStream::new_list(9); + self.rlp_to(None, &mut stream); + stream.append(&signature_v); + stream.append(&signature_r); + stream.append(&signature_s); + stream.out() + } +} + /// Return author's signature over given message. pub fn sign(author: &SecretKey, message: H256) -> H520 { let (signature, recovery_id) = secp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); @@ -64,3 +94,50 @@ pub fn secret_to_address(secret: &SecretKey) -> Address { raw_public.copy_from_slice(&public.serialize()[1..]); public_to_address(&raw_public) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{transaction_decode, Transaction}; + + #[test] + fn transaction_signed_properly() { + // case1: with chain_id replay protection + to + let signer = SecretKey::parse(&[1u8; 32]).unwrap(); + let signer_address = secret_to_address(&signer); + let unsigned = UnsignedTransaction { + nonce: 100.into(), + gas_price: 200.into(), + gas: 300.into(), + to: Some([42u8; 20].into()), + value: 400.into(), + payload: vec![1, 2, 3], + }; + let raw_tx = unsigned.clone().sign_by(&signer, Some(42)); + assert_eq!( + transaction_decode(&raw_tx), + Ok(Transaction { + sender: signer_address, + unsigned, + }), + ); + + // case2: without chain_id replay protection + contract creation + let unsigned = UnsignedTransaction { + nonce: 100.into(), + gas_price: 200.into(), + gas: 300.into(), + to: None, + value: 400.into(), + payload: vec![1, 2, 3], + }; + let raw_tx = unsigned.clone().sign_by(&signer, None); + assert_eq!( + transaction_decode(&raw_tx), + Ok(Transaction { + sender: signer_address, + unsigned, + }), + ); + } +} From 13c9736a15cb418c5cef04b797ecf19b64398f11 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Jul 2020 10:49:31 +0300 Subject: [PATCH 0089/1210] Fix sub2eth synchronization (#172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ease serde version requirements (to build OE with builtin) * trace + fix completion notifications * check incompletion on submit * fix compilation * do not ask for synced blocks when queue is empty * cargo fmt --all * Update relays/ethereum/src/ethereum_client.rs Co-authored-by: Tomasz Drwięga * remove closure * fn submit_substrate_header() -> Option Co-authored-by: Tomasz Drwięga --- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/res/substrate-bridge-abi.json | 19 ++ .../res/substrate-bridge-bytecode.hex | 2 +- .../res/substrate-bridge-metadata.txt | 6 +- relays/ethereum/src/ethereum_client.rs | 251 ++++++++++++++++-- relays/ethereum/src/ethereum_sync_loop.rs | 7 +- relays/ethereum/src/headers.rs | 55 +++- relays/ethereum/src/substrate_client.rs | 61 +++-- relays/ethereum/src/substrate_sync_loop.rs | 7 +- relays/ethereum/src/sync.rs | 25 +- relays/ethereum/src/sync_loop.rs | 23 +- relays/ethereum/src/sync_types.rs | 27 ++ 12 files changed, 419 insertions(+), 66 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 6d50e0d857979..fd7c69429bdff 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -24,7 +24,7 @@ num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.11.0" rustc-hex = "2.0.1" -serde = { version = "1.0.114", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.55" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" diff --git a/relays/ethereum/res/substrate-bridge-abi.json b/relays/ethereum/res/substrate-bridge-abi.json index bd65f6b7921f1..169b000680218 100644 --- a/relays/ethereum/res/substrate-bridge-abi.json +++ b/relays/ethereum/res/substrate-bridge-abi.json @@ -96,6 +96,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "rawHeader", + "type": "bytes" + } + ], + "name": "isIncompleteHeader", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/relays/ethereum/res/substrate-bridge-bytecode.hex b/relays/ethereum/res/substrate-bridge-bytecode.hex index 6b3b74df48b0d..0a0973699d463 100644 --- a/relays/ethereum/res/substrate-bridge-bytecode.hex +++ b/relays/ethereum/res/substrate-bridge-bytecode.hex @@ -1 +1 @@ -60806040523480156200001157600080fd5b506040516200131938038062001319833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d5565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260078352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f9260038501929101906200040a565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d1919060208501906200040a565b5050505050620004af565b620002e6620003d5565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa6200031c57600080fd5b84519b5083519a50825199508151985080519750505050505050506060816001600160401b03811180156200035057600080fd5b506040519080825280601f01601f1916602001820160405280156200037c576020820181803683370190505b5090508115620003a85787516020890160208301848184846011600019fa620003a457600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044d57805160ff19168380011785556200047d565b828001600101855582156200047d579182015b828111156200047d57825182559160200191906001019062000460565b506200048b9291506200048f565b5090565b620004ac91905b808211156200048b576000815560010162000496565b90565b610e5a80620004bf6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063374c2c261461005c578063871ebe18146100fd578063d96a2deb1461012e578063e7af07791461014f578063fae71ae8146101f7575b600080fd5b6100646102a9565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100a8578181015183820152602001610090565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100e75781810151838201526020016100cf565b5050505090500194505050505060405180910390f35b61011a6004803603602081101561011357600080fd5b50356103ae565b604080519115158252519081900360200190f35b6101366103c3565b6040805192835260208301919091528051918290030190f35b6101f56004803603602081101561016557600080fd5b81019060208101813564010000000081111561018057600080fd5b82018360208201111561019257600080fd5b803590602001918460018302840111640100000000831117156101b457600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506103db945050505050565b005b6101f56004803603606081101561020d57600080fd5b81359160208101359181019060608101604082013564010000000081111561023457600080fd5b82018360208201111561024657600080fd5b8035906020019184600183028401116401000000008311171561026857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610779945050505050565b6005546060908190818167ffffffffffffffff811180156102c957600080fd5b506040519080825280602002602001820160405280156102f3578160200160208202803683370190505b50905060005b8281101561034e57600760006005838154811061031257fe5b906000526020600020015481526020019081526020016000206002015482828151811061033b57fe5b60209081029190910101526001016102f9565b508060058080548060200260200160405190810160405280929190818152602001828054801561039d57602002820191906000526020600020905b815481526020019060010190808311610389575b505050505090509350935050509091565b60009081526007602052604090205460ff1690565b60008054808252600760205260409091206002015491565b6103e3610c13565b6103ec826109de565b805160009081526007602052604090205490915060ff1615610455576040805162461bcd60e51b815260206004820152601760248201527f48656164657220697320616c7265616479206b6e6f776e000000000000000000604482015290519081900360640190fd5b6001548160400151116104995760405162461bcd60e51b8152600401808060200182810382526025815260200180610d596025913960400191505060405180910390fd5b6020808201516000908152600790915260409020805460ff1680156104c8575060018260400151038160020154145b6105035760405162461bcd60e51b8152600401808060200182810382526026815260200180610d7e6026913960400191505060405180910390fd5b60068101541580159061051d575080600201548160060154145b15610566578160200151600254146105665760405162461bcd60e51b8152600401808060200182810382526031815260200180610df46031913960400191505060405180910390fd5b60048101546005820154600683015460808501515167ffffffffffffffff90931692156106445767ffffffffffffffff83811614156105d65760405162461bcd60e51b8152600401808060200182810382526021815260200180610da46021913960400191505060405180910390fd5b8460400151811061062e576040805162461bcd60e51b815260206004820152601960248201527f4f7665726c617070696e67207369676e616c7320666f756e6400000000000000604482015290519081900360640190fd5b5050825160608401516040850151600190930192015b8460400151811415610697576005805486516001820180845560009384527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0909201558651825260066020526040909120555b6040805160e0810182526001808252602088810151818401908152898501518486019081526080808c01516060870190815267ffffffffffffffff8b169187019190915260a0860189905260c086018890528b51600090815260078552969096208551815460ff191690151517815591519382019390935591516002830155925180519293919261072e9260038501920190610c48565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c09091015160069091015550509151600055505050565b60008281526007602052604090206002015483146107c85760405162461bcd60e51b815260040180806020018281038252602f815260200180610dc5602f913960400191505060405180910390fd5b60028054600354600480546040805160206101006001851615026000190190931696909604601f81018390048302870183019091528086529394600094610879948a948a9467ffffffffffffffff9092169392909183018282801561086e5780601f106108435761010080835404028352916020019161086e565b820191906000526020600020905b81548152906001019060200180831161085157829003601f168201915b505050505087610ad1565b600081815260076020526040902060028281558101546001559091505b8282146109d657506000818152600760209081526040808320600181015460069093529220549092908015610958576005546000199182019181018214610924576000600560018303815481106108e957fe5b90600052602060002001549050806005848154811061090457fe5b600091825260208083209091019290925591825260069052604090208290555b600580548061092f57fe5b600082815260208082208301600019908101839055909201909255848252600690526040812055505b8260060154836002015414156109cf57600583015460009081526007602052604090206003805467ffffffffffffffff198116600167ffffffffffffffff928316810190921617825590820180546109c6926004929160026101009282161592909202600019011604610cc6565b505050506109d6565b5050610896565b505050505050565b6109e6610c13565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa610a1b57600080fd5b84519b5083519a508251995081519850805197505050505050505060608167ffffffffffffffff81118015610a4f57600080fd5b506040519080825280601f01601f191660200182016040528015610a7a576020820181803683370190505b5090508115610aa45787516020890160208301848184846011600019fa610aa057600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b600060608686868686604051602001808681526020018581526020018467ffffffffffffffff1667ffffffffffffffff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610b44578181015183820152602001610b2c565b50505050905090810190601f168015610b715780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610ba4578181015183820152602001610b8c565b50505050905090810190601f168015610bd15780820380516001836020036101000a031916815260200191505b50975050505050505050604051602081830303815290604052905080516020820160008083836012600019fa610c0657600080fd5b5095979650505050505050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c8957805160ff1916838001178555610cb6565b82800160010185558215610cb6579182015b82811115610cb6578251825591602001919060010190610c9b565b50610cc2929150610d3b565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610cff5780548555610cb6565b82800160010185558215610cb657600052602060002091601f016020900482015b82811115610cb6578254825591600101919060010190610d20565b610d5591905b80821115610cc25760008155600101610d41565b9056fe547279696e6720746f20696d706f7274206e6f6e2d63616e6f6e6963616c206865616465724d697373696e6720706172656e74206865616465722066726f6d207468652073746f7261676552656163686564206d6178696d616c2076616c696461746f7273207365742069644d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f726167654d697373696e672072657175697265642066696e616c6974792070726f6f6620666f7220706172656e7420686561646572a26469706673582212206a13d7fad990f5ff64cfe638f258f1cf2a4c72a3161a28ec200db444a3d61c2e64736f6c63430006060033 \ No newline at end of file +60806040523480156200001157600080fd5b506040516200142e3803806200142e833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d5565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260078352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f9260038501929101906200040a565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d1919060208501906200040a565b5050505050620004af565b620002e6620003d5565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa6200031c57600080fd5b84519b5083519a50825199508151985080519750505050505050506060816001600160401b03811180156200035057600080fd5b506040519080825280601f01601f1916602001820160405280156200037c576020820181803683370190505b5090508115620003a85787516020890160208301848184846011600019fa620003a457600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044d57805160ff19168380011785556200047d565b828001600101855582156200047d579182015b828111156200047d57825182559160200191906001019062000460565b506200048b9291506200048f565b5090565b620004ac91905b808211156200048b576000815560010162000496565b90565b610f6f80620004bf6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063374c2c2614610067578063871ebe18146101085780638dc1f05c14610139578063d96a2deb146101df578063e7af077914610200578063fae71ae8146102a8575b600080fd5b61006f61035a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b357818101518382015260200161009b565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f25781810151838201526020016100da565b5050505090500194505050505060405180910390f35b6101256004803603602081101561011e57600080fd5b503561045f565b604080519115158252519081900360200190f35b6101256004803603602081101561014f57600080fd5b81019060208101813564010000000081111561016a57600080fd5b82018360208201111561017c57600080fd5b8035906020019184600183028401116401000000008311171561019e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610474945050505050565b6101e761049d565b6040805192835260208301919091528051918290030190f35b6102a66004803603602081101561021657600080fd5b81019060208101813564010000000081111561023157600080fd5b82018360208201111561024357600080fd5b8035906020019184600183028401116401000000008311171561026557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506104b5945050505050565b005b6102a6600480360360608110156102be57600080fd5b8135916020810135918101906060810160408201356401000000008111156102e557600080fd5b8201836020820111156102f757600080fd5b8035906020019184600183028401116401000000008311171561031957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610607945050505050565b6005546060908190818167ffffffffffffffff8111801561037a57600080fd5b506040519080825280602002602001820160405280156103a4578160200160208202803683370190505b50905060005b828110156103ff5760076000600583815481106103c357fe5b90600052602060002001548152602001908152602001600020600201548282815181106103ec57fe5b60209081029190910101526001016103aa565b508060058080548060200260200160405190810160405280929190818152602001828054801561044e57602002820191906000526020600020905b81548152602001906001019080831161043a575b505050505090509350935050509091565b60009081526007602052604090205460ff1690565b600061047e610d28565b60006104898461086c565b604090930151909214945050505050919050565b60008054808252600760205260409091206002015491565b6104bd610d28565b60008060006104cb8561086c565b93509350935093508360400151811415610526576005805485516001820180845560009384527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0909201558551825260066020526040909120555b6040805160e0810182526001808252602087810151818401908152888501518486019081526080808b01516060870190815267ffffffffffffffff8b169187019190915260a0860189905260c086018890528a51600090815260078552969096208551815460ff19169015151781559151938201939093559151600283015592518051929391926105bd9260038501920190610d5d565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c090910151600690910155505090516000555050565b60008281526007602052604090206002015483146106565760405162461bcd60e51b815260040180806020018281038252602f815260200180610eda602f913960400191505060405180910390fd5b60028054600354600480546040805160206101006001851615026000190190931696909604601f81018390048302870183019091528086529394600094610707948a948a9467ffffffffffffffff909216939290918301828280156106fc5780601f106106d1576101008083540402835291602001916106fc565b820191906000526020600020905b8154815290600101906020018083116106df57829003601f168201915b505050505087610af3565b600081815260076020526040902060028281558101546001559091505b828214610864575060008181526007602090815260408083206001810154600690935292205490929080156107e65760055460001991820191810182146107b25760006005600183038154811061077757fe5b90600052602060002001549050806005848154811061079257fe5b600091825260208083209091019290925591825260069052604090208290555b60058054806107bd57fe5b600082815260208082208301600019908101839055909201909255848252600690526040812055505b82600601548360020154141561085d57600583015460009081526007602052604090206003805467ffffffffffffffff198116600167ffffffffffffffff92831681019092161782559082018054610854926004929160026101009282161592909202600019011604610ddb565b50505050610864565b5050610724565b505050505050565b610874610d28565b6000806000610881610d28565b61088a86610c35565b805160009081526007602052604090205490915060ff16156108f3576040805162461bcd60e51b815260206004820152601760248201527f48656164657220697320616c7265616479206b6e6f776e000000000000000000604482015290519081900360640190fd5b6001548160400151116109375760405162461bcd60e51b8152600401808060200182810382526025815260200180610e6e6025913960400191505060405180910390fd5b6020808201516000908152600790915260409020805460ff168015610966575060018260400151038160020154145b6109a15760405162461bcd60e51b8152600401808060200182810382526026815260200180610e936026913960400191505060405180910390fd5b6006810154158015906109bb575080600201548160060154145b15610a0457816020015160025414610a045760405162461bcd60e51b8152600401808060200182810382526031815260200180610f096031913960400191505060405180910390fd5b60048101546005820154600683015460808501515167ffffffffffffffff9093169215610ae25767ffffffffffffffff8381161415610a745760405162461bcd60e51b8152600401808060200182810382526021815260200180610eb96021913960400191505060405180910390fd5b84604001518110610acc576040805162461bcd60e51b815260206004820152601960248201527f4f7665726c617070696e67207369676e616c7320666f756e6400000000000000604482015290519081900360640190fd5b5050825160608401516040850151600190930192015b939991985096509194509092505050565b600060608686868686604051602001808681526020018581526020018467ffffffffffffffff1667ffffffffffffffff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610b66578181015183820152602001610b4e565b50505050905090810190601f168015610b935780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610bc6578181015183820152602001610bae565b50505050905090810190601f168015610bf35780820380516001836020036101000a031916815260200191505b50975050505050505050604051602081830303815290604052905080516020820160008083836012600019fa610c2857600080fd5b5095979650505050505050565b610c3d610d28565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa610c7257600080fd5b84519b5083519a508251995081519850805197505050505050505060608167ffffffffffffffff81118015610ca657600080fd5b506040519080825280601f01601f191660200182016040528015610cd1576020820181803683370190505b5090508115610cfb5787516020890160208301848184846011600019fa610cf757600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610d9e57805160ff1916838001178555610dcb565b82800160010185558215610dcb579182015b82811115610dcb578251825591602001919060010190610db0565b50610dd7929150610e50565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e145780548555610dcb565b82800160010185558215610dcb57600052602060002091601f016020900482015b82811115610dcb578254825591600101919060010190610e35565b610e6a91905b80821115610dd75760008155600101610e56565b9056fe547279696e6720746f20696d706f7274206e6f6e2d63616e6f6e6963616c206865616465724d697373696e6720706172656e74206865616465722066726f6d207468652073746f7261676552656163686564206d6178696d616c2076616c696461746f7273207365742069644d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f726167654d697373696e672072657175697265642066696e616c6974792070726f6f6620666f7220706172656e7420686561646572a2646970667358221220430a1b51f4ade85190a1817f6d8dfc5ffc46019627c95d768106e998f360e8be64736f6c63430006060033 \ No newline at end of file diff --git a/relays/ethereum/res/substrate-bridge-metadata.txt b/relays/ethereum/res/substrate-bridge-metadata.txt index dcf50c5cfa462..60b8d022fc4b4 100644 --- a/relays/ethereum/res/substrate-bridge-metadata.txt +++ b/relays/ethereum/res/substrate-bridge-metadata.txt @@ -1,5 +1,5 @@ -Last Change Date: 2020-05-01 +Last Change Date: 2020-07-03 Solc version: 0.6.6+commit.6c089d02 -Source hash (keccak256): 0x36403636ad41082ca6c937c60ab06446cd9ef7036c178fa2f04d7c8286544d39 -Source gist: https://github.com/svyatonik/substrate-bridge-sol/blob/8b54f5f648f8685fecd52b7af1deb277922b0fc3/substrate-bridge.sol +Source hash (keccak256): 0x3e6339beefe6786f4f26b408d4f727e03c6fd9630d692af9a7f6b46143fa308f +Source gist: https://github.com/svyatonik/substrate-bridge-sol/blob/1d0fa475a2ba3a70a47ed2dd870568c42ec16c8c/substrate-bridge.sol Compiler flags used (command to produce the file): `docker run -i ethereum/solc:0.6.6 --optimize --bin - < substrate-bridge.sol` \ No newline at end of file diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index fcd627549a076..ffc14f77584e4 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -20,7 +20,7 @@ use crate::ethereum_types::{ use crate::rpc::{Ethereum, EthereumRpc}; use crate::rpc_errors::{EthereumNodeError, RpcError}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::HeaderId; +use crate::sync_types::{HeaderId, MaybeConnectionError, SubmittedHeaders}; use async_trait::async_trait; use codec::{Decode, Encode}; @@ -30,7 +30,7 @@ use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use parity_crypto::publickey::KeyPair; -use std::collections::HashSet; +use std::collections::{HashSet, VecDeque}; // to encode/decode contract calls ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json"); @@ -170,7 +170,7 @@ pub trait EthereumHighLevelRpc: EthereumRpc { params: EthereumSigningParams, contract_address: Address, headers: Vec, - ) -> Result>; + ) -> SubmittedHeaders; /// Returns ids of incomplete Substrate headers. async fn incomplete_substrate_headers(&self, contract_address: Address) -> Result>; @@ -246,25 +246,35 @@ impl EthereumHighLevelRpc for EthereumRpcClient { params: EthereumSigningParams, contract_address: Address, headers: Vec, - ) -> Result> { + ) -> SubmittedHeaders { + // read nonce of signer let address: Address = params.signer.address().as_fixed_bytes().into(); - let mut nonce = self.account_nonce(address).await?; - - let ids = headers.iter().map(|header| header.id()).collect(); - for header in headers { - self.submit_ethereum_transaction( - ¶ms, - Some(contract_address), - Some(nonce), - false, - bridge_contract::functions::import_header::encode_input(header.header().encode()), - ) - .await?; - - nonce += 1.into(); - } + let nonce = match self.account_nonce(address).await { + Ok(nonce) => nonce, + Err(error) => { + return SubmittedHeaders { + submitted: Vec::new(), + incomplete: Vec::new(), + rejected: headers.iter().rev().map(|header| header.id()).collect(), + fatal_error: Some(error), + } + } + }; - Ok(ids) + // submit headers. Note that we're cloning self here. It is ok, because + // cloning `jsonrpsee::Client` only clones reference to background threads + submit_substrate_headers( + EthereumHeadersSubmitter { + client: EthereumRpcClient { + client: self.client.clone(), + }, + params, + contract_address, + nonce, + }, + headers, + ) + .await } async fn incomplete_substrate_headers(&self, contract_address: Address) -> Result> { @@ -363,3 +373,204 @@ impl EthereumHighLevelRpc for EthereumRpcClient { Ok((id, transaction_receipts)) } } + +/// Substrate headers submitter API. +#[async_trait] +trait HeadersSubmitter { + /// Returns Ok(true) if not-yet-imported header is incomplete. + /// Returns Ok(false) if not-yet-imported header is complete. + /// + /// Returns Err(()) if contract has rejected header. This probably means + /// that the header is already imported by the contract. + async fn is_header_incomplete(&self, header: &QueuedSubstrateHeader) -> Result; + + /// Submit given header to Ethereum node. + async fn submit_header(&mut self, header: QueuedSubstrateHeader) -> Result<()>; +} + +/// Implementation of Substrate headers submitter that sends headers to running Ethereum node. +struct EthereumHeadersSubmitter { + client: EthereumRpcClient, + params: EthereumSigningParams, + contract_address: Address, + nonce: U256, +} + +#[async_trait] +impl HeadersSubmitter for EthereumHeadersSubmitter { + async fn is_header_incomplete(&self, header: &QueuedSubstrateHeader) -> Result { + let (encoded_call, call_decoder) = + bridge_contract::functions::is_incomplete_header::call(header.header().encode()); + let call_request = CallRequest { + to: Some(self.contract_address), + data: Some(encoded_call.into()), + ..Default::default() + }; + + let call_result = self.client.eth_call(call_request).await?; + let is_incomplete = call_decoder.decode(&call_result.0)?; + + Ok(is_incomplete) + } + + async fn submit_header(&mut self, header: QueuedSubstrateHeader) -> Result<()> { + let result = self + .client + .submit_ethereum_transaction( + &self.params, + Some(self.contract_address), + Some(self.nonce), + false, + bridge_contract::functions::import_header::encode_input(header.header().encode()), + ) + .await; + + if result.is_ok() { + self.nonce += U256::one(); + } + + result + } +} + +/// Submit multiple Substrate headers. +async fn submit_substrate_headers( + mut header_submitter: impl HeadersSubmitter, + headers: Vec, +) -> SubmittedHeaders { + let mut ids = headers.iter().map(|header| header.id()).collect::>(); + let mut submitted_headers = SubmittedHeaders::default(); + for header in headers { + let id = ids.pop_front().expect("both collections have same size; qed"); + submitted_headers.fatal_error = + submit_substrate_header(&mut header_submitter, &mut submitted_headers, id, header).await; + + if submitted_headers.fatal_error.is_some() { + submitted_headers.rejected.extend(ids); + break; + } + } + + submitted_headers +} + +/// Submit single Substrate header. +async fn submit_substrate_header( + header_submitter: &mut impl HeadersSubmitter, + submitted_headers: &mut SubmittedHeaders, + id: SubstrateHeaderId, + header: QueuedSubstrateHeader, +) -> Option { + // if parent of this header is either incomplete, or rejected, we assume that contract + // will reject this header as well + let parent_id = header.parent_id(); + if submitted_headers.rejected.contains(&parent_id) || submitted_headers.incomplete.contains(&parent_id) { + submitted_headers.rejected.push(id); + return None; + } + + // check if this header is incomplete + let is_header_incomplete = match header_submitter.is_header_incomplete(&header).await { + Ok(true) => true, + Ok(false) => false, + Err(error) => { + // contract has rejected this header => we do not want to submit it + submitted_headers.rejected.push(id); + if error.is_connection_error() { + return Some(error); + } else { + return None; + } + } + }; + + // submit header and update submitted headers + match header_submitter.submit_header(header).await { + Ok(_) => { + submitted_headers.submitted.push(id); + if is_header_incomplete { + submitted_headers.incomplete.push(id); + } + None + } + Err(error) => { + submitted_headers.rejected.push(id); + Some(error) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::substrate_types::{Header as SubstrateHeader, Number as SubstrateBlockNumber}; + use sp_runtime::traits::Header; + + struct TestHeadersSubmitter { + incomplete: Vec, + failed: Vec, + } + + #[async_trait] + impl HeadersSubmitter for TestHeadersSubmitter { + async fn is_header_incomplete(&self, header: &QueuedSubstrateHeader) -> Result { + if self.incomplete.iter().any(|i| i.0 == header.id().0) { + Ok(true) + } else { + Ok(false) + } + } + + async fn submit_header(&mut self, header: QueuedSubstrateHeader) -> Result<()> { + if self.failed.iter().any(|i| i.0 == header.id().0) { + Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)) + } else { + Ok(()) + } + } + } + + fn header(number: SubstrateBlockNumber) -> QueuedSubstrateHeader { + QueuedSubstrateHeader::new(SubstrateHeader::new( + number, + Default::default(), + Default::default(), + if number == 0 { + Default::default() + } else { + header(number - 1).id().1 + }, + Default::default(), + )) + } + + #[test] + fn descendants_of_incomplete_headers_are_not_submitted() { + let submitted_headers = async_std::task::block_on(submit_substrate_headers( + TestHeadersSubmitter { + incomplete: vec![header(5).id()], + failed: vec![], + }, + vec![header(5), header(6)], + )); + assert_eq!(submitted_headers.submitted, vec![header(5).id()]); + assert_eq!(submitted_headers.incomplete, vec![header(5).id()]); + assert_eq!(submitted_headers.rejected, vec![header(6).id()]); + assert!(submitted_headers.fatal_error.is_none()); + } + + #[test] + fn headers_after_fatal_error_are_not_submitted() { + let submitted_headers = async_std::task::block_on(submit_substrate_headers( + TestHeadersSubmitter { + incomplete: vec![], + failed: vec![header(6).id()], + }, + vec![header(5), header(6), header(7)], + )); + assert_eq!(submitted_headers.submitted, vec![header(5).id()]); + assert_eq!(submitted_headers.incomplete, vec![]); + assert_eq!(submitted_headers.rejected, vec![header(6).id(), header(7).id()]); + assert!(submitted_headers.fatal_error.is_some()); + } +} diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 26804d4de0cb7..65d53946ebbe3 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -26,7 +26,7 @@ use crate::substrate_client::{ use crate::substrate_types::into_substrate_ethereum_header; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; use crate::sync_loop::{SourceClient, TargetClient}; -use crate::sync_types::SourceHeader; +use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; use web3::types::H256; @@ -155,7 +155,10 @@ impl TargetClient for SubstrateHeadersTarget { Ok((id, self.client.ethereum_header_known(id).await?)) } - async fn submit_headers(&self, headers: Vec) -> Result, Self::Error> { + async fn submit_headers( + &self, + headers: Vec, + ) -> SubmittedHeaders { let (sign_params, sign_transactions) = (self.sign_params.clone(), self.sign_transactions.clone()); self.client .submit_ethereum_headers(sign_params, headers, sign_transactions) diff --git a/relays/ethereum/src/headers.rs b/relays/ethereum/src/headers.rs index a75937da8cfb3..c1dcc86444d67 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/ethereum/src/headers.rs @@ -62,6 +62,8 @@ pub struct QueuedHeaders { incomplete_headers: LinkedHashMap, Option>, /// Headers that are waiting to be completed at target node. Auto-sorted by insertion time. completion_data: LinkedHashMap, P::Completion>, + /// Best synced block number. + best_synced_number: P::Number, /// Pruned blocks border. We do not store or accept any blocks with number less than /// this number. prune_border: P::Number, @@ -90,6 +92,7 @@ impl QueuedHeaders

{ known_headers: KnownHeaders::

::new(), incomplete_headers: LinkedHashMap::new(), completion_data: LinkedHashMap::new(), + best_synced_number: Zero::zero(), prune_border: Zero::zero(), } } @@ -158,6 +161,12 @@ impl QueuedHeaders

{ ) } + /// Returns number of best synced block we have ever seen. It is either less + /// than `best_queued_number()`, or points to last synced block if queue is empty. + pub fn best_synced_number(&self) -> P::Number { + self.best_synced_number + } + /// Returns synchronization status of the header. pub fn status(&self, id: &HeaderId) -> HeaderStatus { self.known_headers @@ -328,10 +337,23 @@ impl QueuedHeaders

{ pub fn completion_response(&mut self, id: &HeaderId, completion: Option) { let completion = match completion { Some(completion) => completion, - None => return, // we'll try refetch later + None => { + log::debug!( + target: "bridge", + "{} Node is still missing completion data for header: {:?}. Will retry later.", + P::SOURCE_NAME, + id, + ); + + return; + } }; - if self.incomplete_headers.remove(id).is_some() { + // do not remove from `incomplete_headers` here, because otherwise we'll miss + // completion 'notification' + // this could lead to duplicate completion retrieval (if completion transaction isn't mined + // for too long) + if self.incomplete_headers.get(id).is_some() { log::debug!( target: "bridge", "Received completion data from {} for header: {:?}", @@ -381,15 +403,8 @@ impl QueuedHeaders

{ } } - /// When incomplete headers ids are receved from target node. - pub fn incomplete_headers_response(&mut self, ids: HashSet>) { - // all new incomplete headers are marked Synced and all their descendants - // are moved from Ready/Submitted to Incomplete queue - let new_incomplete_headers = ids - .iter() - .filter(|id| !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id)) - .cloned() - .collect::>(); + /// Marks given headers incomplete. + pub fn add_incomplete_headers(&mut self, new_incomplete_headers: Vec>) { for new_incomplete_header in new_incomplete_headers { self.header_synced(&new_incomplete_header); move_header_descendants::

( @@ -408,6 +423,18 @@ impl QueuedHeaders

{ self.incomplete_headers.insert(new_incomplete_header, None); } + } + + /// When incomplete headers ids are receved from target node. + pub fn incomplete_headers_response(&mut self, ids: HashSet>) { + // all new incomplete headers are marked Synced and all their descendants + // are moved from Ready/Submitted to Incomplete queue + let new_incomplete_headers = ids + .iter() + .filter(|id| !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id)) + .cloned() + .collect::>(); + self.add_incomplete_headers(new_incomplete_headers); // for all headers that were incompleted previously, but now are completed, we move // all descendants from incomplete to ready @@ -487,6 +514,7 @@ impl QueuedHeaders

{ self.incomplete.clear(); self.submitted.clear(); self.known_headers.clear(); + self.best_synced_number = Zero::zero(); self.prune_border = Zero::zero(); } @@ -519,6 +547,9 @@ impl QueuedHeaders

{ /// When we receive new Synced header from target node. fn header_synced(&mut self, id: &HeaderId) { + // update best synced block number + self.best_synced_number = std::cmp::max(self.best_synced_number, id.0); + // all ancestors of this header are now synced => let's remove them from // queues let mut current = *id; @@ -1272,7 +1303,7 @@ pub(crate) mod tests { // when response is Some, we're scheduling completion queue.completion_response(&id(200), Some(())); - assert_eq!(queue.incomplete_headers.len(), 1); + assert_eq!(queue.incomplete_headers.len(), 2); assert_eq!(queue.completion_data.len(), 1); assert!(queue.incomplete_headers.contains_key(&id(100))); assert!(queue.completion_data.contains_key(&id(200))); diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index cd77545b266bd..43549292cef6d 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -21,7 +21,7 @@ use crate::substrate_types::{ into_substrate_ethereum_header, into_substrate_ethereum_receipts, Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock, }; -use crate::sync_types::HeaderId; +use crate::sync_types::{HeaderId, SubmittedHeaders}; use async_trait::async_trait; use codec::{Decode, Encode}; @@ -32,6 +32,7 @@ use num_traits::Zero; use sp_bridge_eth_poa::Header as SubstrateEthereumHeader; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; +use std::collections::VecDeque; const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; @@ -193,20 +194,20 @@ pub trait SubmitEthereumHeaders: SubstrateRpc { params: SubstrateSigningParams, headers: Vec, sign_transactions: bool, - ) -> Result>; + ) -> SubmittedHeaders; /// Submits signed Ethereum header to Substrate runtime. async fn submit_signed_ethereum_headers( &self, params: SubstrateSigningParams, headers: Vec, - ) -> Result>; + ) -> SubmittedHeaders; /// Submits unsigned Ethereum header to Substrate runtime. async fn submit_unsigned_ethereum_headers( &self, headers: Vec, - ) -> Result>; + ) -> SubmittedHeaders; } #[async_trait] @@ -216,7 +217,7 @@ impl SubmitEthereumHeaders for SubstrateRpcClient { params: SubstrateSigningParams, headers: Vec, sign_transactions: bool, - ) -> Result> { + ) -> SubmittedHeaders { if sign_transactions { self.submit_signed_ethereum_headers(params, headers).await } else { @@ -228,29 +229,55 @@ impl SubmitEthereumHeaders for SubstrateRpcClient { &self, params: SubstrateSigningParams, headers: Vec, - ) -> Result> { + ) -> SubmittedHeaders { let ids = headers.iter().map(|header| header.id()).collect(); + let submission_result = async { + let account_id = params.signer.public().as_array_ref().clone().into(); + let nonce = self.next_account_index(account_id).await?; - let account_id = params.signer.public().as_array_ref().clone().into(); - let nonce = self.next_account_index(account_id).await?; - - let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, self.genesis_hash); - let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; - - Ok(ids) + let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, self.genesis_hash); + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + Ok(()) + } + .await; + + match submission_result { + Ok(_) => SubmittedHeaders { + submitted: ids, + incomplete: Vec::new(), + rejected: Vec::new(), + fatal_error: None, + }, + Err(error) => SubmittedHeaders { + submitted: Vec::new(), + incomplete: Vec::new(), + rejected: ids, + fatal_error: Some(error), + }, + } } async fn submit_unsigned_ethereum_headers( &self, headers: Vec, - ) -> Result> { - let ids = headers.iter().map(|header| header.id()).collect(); + ) -> SubmittedHeaders { + let mut ids = headers.iter().map(|header| header.id()).collect::>(); + let mut submitted_headers = SubmittedHeaders::default(); for header in headers { + let id = ids.pop_front().expect("both collections have same size; qed"); let transaction = create_unsigned_submit_transaction(header); - let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + match self.submit_extrinsic(Bytes(transaction.encode())).await { + Ok(_) => submitted_headers.submitted.push(id), + Err(error) => { + submitted_headers.rejected.push(id); + submitted_headers.rejected.extend(ids); + submitted_headers.fatal_error = Some(error); + break; + } + } } - Ok(ids) + submitted_headers } } diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index ede547a9b5d5f..4da5fcb1290af 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -28,7 +28,7 @@ use crate::substrate_types::{ }; use crate::sync::{HeadersSyncParams, TargetTransactionMode}; use crate::sync_loop::{SourceClient, TargetClient}; -use crate::sync_types::SourceHeader; +use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; @@ -165,7 +165,10 @@ impl TargetClient for EthereumHeadersTarget { self.client.substrate_header_known(self.contract, id).await } - async fn submit_headers(&self, headers: Vec) -> Result, Self::Error> { + async fn submit_headers( + &self, + headers: Vec, + ) -> SubmittedHeaders { self.client .submit_substrate_headers(self.sign_params.clone(), self.contract, headers) .await diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 7f15865cc5049..4cfd3b4ab92f4 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -113,7 +113,10 @@ impl HeadersSync

{ } // we assume that there were no reorgs if we have already downloaded best header - let best_downloaded_number = std::cmp::max(self.headers.best_queued_number(), target_best_header.0); + let best_downloaded_number = std::cmp::max( + std::cmp::max(self.headers.best_queued_number(), self.headers.best_synced_number()), + target_best_header.0, + ); if best_downloaded_number == source_best_number { return None; } @@ -257,6 +260,26 @@ mod tests { assert_eq!(eth_sync.select_new_header_to_download(), None); } + #[test] + fn select_new_header_to_download_works_with_empty_queue() { + let mut eth_sync = HeadersSync::::new(default_sync_params()); + eth_sync.source_best_header_number_response(100); + + // when queue is not empty => everything goes as usually + eth_sync.target_best_header_response(header(10).id()); + eth_sync.headers_mut().header_response(header(11).header().clone()); + eth_sync.headers_mut().maybe_extra_response(&header(11).id(), false); + assert_eq!(eth_sync.select_new_header_to_download(), Some(12)); + + // but then queue is drained + eth_sync.headers_mut().target_best_header_response(&header(11).id()); + + // even though it's empty, we know that header#11 is synced + assert_eq!(eth_sync.headers().best_queued_number(), 0); + assert_eq!(eth_sync.headers().best_synced_number(), 11); + assert_eq!(eth_sync.select_new_header_to_download(), Some(12)); + } + #[test] fn sync_without_reorgs_works() { let mut eth_sync = HeadersSync::new(default_sync_params()); diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 28ee40650f32a..e13b52469dfef 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -15,7 +15,9 @@ // along with Parity Bridges Common. If not, see . use crate::sync::HeadersSyncParams; -use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader}; +use crate::sync_types::{ + HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SubmittedHeaders, +}; use async_trait::async_trait; use futures::{future::FutureExt, stream::StreamExt}; @@ -91,7 +93,7 @@ pub trait TargetClient: Sized { async fn submit_headers( &self, headers: Vec>, - ) -> Result>, Self::Error>; + ) -> SubmittedHeaders, Self::Error>; /// Returns ID of headers that require to be 'completed' before children can be submitted. async fn incomplete_headers_ids(&self) -> Result>, Self::Error>; @@ -111,10 +113,10 @@ pub trait TargetClient: Sized { } /// Run headers synchronization. -pub fn run( +pub fn run>( source_client: impl SourceClient

, source_tick: Duration, - target_client: impl TargetClient

, + target_client: TC, target_tick: Duration, sync_params: HeadersSyncParams, ) { @@ -288,14 +290,21 @@ pub fn run( || format!("Error retrieving existence status from {} node", P::TARGET_NAME), ); }, - target_submit_header_result = target_submit_header_future => { + submitted_headers = target_submit_header_future => { + // following line helps Rust understand the type of `submitted_headers` :/ + let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; + let maybe_fatal_error = submitted_headers.fatal_error.map(Err).unwrap_or(Ok(())); + target_client_is_online = process_future_result( - target_submit_header_result, - |submitted_headers| sync.headers_mut().headers_submitted(submitted_headers), + maybe_fatal_error, + |_| {}, &mut target_go_offline_future, || async_std::task::sleep(CONNECTION_ERROR_DELAY), || format!("Error submitting headers to {} node", P::TARGET_NAME), ); + + sync.headers_mut().headers_submitted(submitted_headers.submitted); + sync.headers_mut().add_incomplete_headers(submitted_headers.incomplete); }, target_complete_header_result = target_complete_header_future => { target_client_is_online = process_future_result( diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index 391d18afab390..c300d25e84bbd 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -161,3 +161,30 @@ impl QueuedHeader

{ &self.extra } } + +/// Headers submission result. +#[derive(Debug)] +#[cfg_attr(test, derive(PartialEq))] +pub struct SubmittedHeaders { + /// IDs of headers that have been submitted to target node. + pub submitted: Vec, + /// IDs of incomplete headers. These headers were submitted (so this id is also in `submitted` vec), + /// but all descendants are not. + pub incomplete: Vec, + /// IDs of ignored headers that we have decided not to submit (they're either rejected by + /// target node immediately, or they're descendants of incomplete headers). + pub rejected: Vec, + /// Fatal target node error, if it has occured during submission. + pub fatal_error: Option, +} + +impl Default for SubmittedHeaders { + fn default() -> Self { + SubmittedHeaders { + submitted: Vec::new(), + incomplete: Vec::new(), + rejected: Vec::new(), + fatal_error: None, + } + } +} From b039a441c8e67af00095f533a63900303d617e3c Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Mon, 6 Jul 2020 13:44:30 +0300 Subject: [PATCH 0090/1210] Add cargo deny (#166) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add cargo deny * deny - master * Copy deny.toml to . * cargo deny check * upload artifacts * install cargo deny * typo * up install cargo deny * update archive * typo * path's * allow failure cargo deny * allew failure log * cargo deny init * add deny.toml and compare with embark actions * fix options * Fix cargo deny. * Remove cargo audit (same as deny) Co-authored-by: Tomasz Drwięga --- bin/node/node/Cargo.toml | 1 + bin/node/runtime/Cargo.toml | 1 + modules/currency-exchange/Cargo.toml | 1 + modules/ethereum-contract/builtin/Cargo.toml | 1 + modules/ethereum/Cargo.toml | 1 + modules/substrate/Cargo.toml | 1 + primitives/currency-exchange/Cargo.toml | 1 + primitives/ethereum-poa/Cargo.toml | 1 + relays/ethereum/Cargo.toml | 1 + relays/substrate/Cargo.toml | 1 + 10 files changed, 10 insertions(+) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 10122e07a1ad3..0b7b5ab6ab449 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" build = "build.rs" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [[bin]] name = "bridge-node" diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 3e473687334e5..1d75dc3fecb7d 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Parity Technologies "] edition = "2018" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.2" diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 7847483bc8b75..b9a71150a18ea 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -4,6 +4,7 @@ description = "A Substrate Runtime module that accepts 'lock funds' transactions version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] serde = { version = "1.0", optional = true } diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index e9b938ccf86e0..d8f4cf8fb9f4d 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -4,6 +4,7 @@ description = "Small crate that helps Solidity contract to verify finality proof version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index bb022397f394b..32a5b997d1194 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -4,6 +4,7 @@ description = "A Substrate Runtime module that is able to verify PoA headers and version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] serde = { version = "1.0", optional = true } diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index e55b0ac4b216d..605d70231f7c6 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -3,6 +3,7 @@ name = "pallet-bridge" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 91fddf25480a9..1bbfac6a61344 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -4,6 +4,7 @@ description = "Primitives of currency exchange module." version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index a444d659bceec..0ccabfaa592b4 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -4,6 +4,7 @@ description = "Primitives of Ethereum PoA Bridge module." version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] serde = { version = "1.0", optional = true } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index fd7c69429bdff..d2e5758fe8884 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -3,6 +3,7 @@ name = "ethereum-poa-relay" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 2b8e26f6286ab..e8052b5b1d919 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -3,6 +3,7 @@ name = "substrate-bridge" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "=1.5.0" From ed4cc919ad8833a10be59bbed01a127c0b17935a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2020 11:36:49 +0000 Subject: [PATCH 0091/1210] Bump serde_json from 1.0.55 to 1.0.56 (#173) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d2e5758fe8884..742c1e3bc802e 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -26,7 +26,7 @@ parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.11.0" rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.55" +serde_json = "1.0.56" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = { version = "0.12.0", default-features = false } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e8052b5b1d919..e391a18901b36 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -14,7 +14,7 @@ env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.8" -serde_json = "1.0.55" +serde_json = "1.0.56" url = "2.1.0" [dependencies.sp-core] From 20eaa7b12032a1ca92ca124c215cec326d76ce2a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 8 Jul 2020 21:53:21 +0300 Subject: [PATCH 0092/1210] Backoff on connection-unrelated errors (#178) * backoff on connection-unrelated errors * cargo fmt --all * Fix some typos Co-authored-by: Hernando Castano --- relays/ethereum/Cargo.toml | 1 + relays/ethereum/src/sync_loop.rs | 132 ++++++++++++++++++++++++++----- 2 files changed, 115 insertions(+), 18 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 742c1e3bc802e..6619a3ca7ea75 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -10,6 +10,7 @@ ansi_term = "0.12" async-std = "=1.5.0" async-stream = "0.2.0" async-trait = "0.1.36" +backoff = "0.1" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.0.0" } env_logger = "0.7.0" diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index e13b52469dfef..e1437ccdc57ee 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -20,6 +20,7 @@ use crate::sync_types::{ }; use async_trait::async_trait; +use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; use std::{ @@ -44,6 +45,9 @@ const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); /// Delay after connection-related error happened before we'll try /// reconnection again. const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); +/// Max delay after connection-unrelated error happened before we'll try the +/// same request again. +const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); /// Source client trait. #[async_trait] @@ -128,6 +132,7 @@ pub fn run>( let mut stall_countdown = None; let mut last_update_time = Instant::now(); + let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = false; let mut source_best_block_number_required = false; let source_best_block_number_future = source_client.best_block_number().fuse(); @@ -138,6 +143,7 @@ pub fn run>( let source_go_offline_future = futures::future::Fuse::terminated(); let source_tick_stream = interval(source_tick).fuse(); + let mut target_retry_backoff = retry_backoff(); let mut target_client_is_online = false; let mut target_best_block_required = false; let mut target_incomplete_headers_required = true; @@ -175,45 +181,50 @@ pub fn run>( source_client_is_online = process_future_result( source_best_block_number, + &mut source_retry_backoff, |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), &mut source_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving best header number from {}", P::SOURCE_NAME), ); }, source_new_header = source_new_header_future => { source_client_is_online = process_future_result( source_new_header, + &mut source_retry_backoff, |source_new_header| sync.headers_mut().header_response(source_new_header), &mut source_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving header from {} node", P::SOURCE_NAME), ); }, source_orphan_header = source_orphan_header_future => { source_client_is_online = process_future_result( source_orphan_header, + &mut source_retry_backoff, |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), &mut source_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), ); }, source_extra = source_extra_future => { source_client_is_online = process_future_result( source_extra, + &mut source_retry_backoff, |(header, extra)| sync.headers_mut().extra_response(&header, extra), &mut source_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), ); }, source_completion = source_completion_future => { source_client_is_online = process_future_result( source_completion, + &mut source_retry_backoff, |(header, completion)| sync.headers_mut().completion_response(&header, completion), &mut source_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), ); }, @@ -230,6 +241,7 @@ pub fn run>( target_client_is_online = process_future_result( target_best_block, + &mut target_retry_backoff, |target_best_block| { let head_updated = sync.target_best_header_response(target_best_block); if head_updated { @@ -264,7 +276,7 @@ pub fn run>( } }, &mut target_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving best known header from {} node", P::TARGET_NAME), ); }, @@ -273,20 +285,22 @@ pub fn run>( target_client_is_online = process_future_result( incomplete_headers_ids, + &mut target_retry_backoff, |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), &mut target_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), ); }, target_existence_status = target_existence_status_future => { target_client_is_online = process_future_result( target_existence_status, + &mut target_retry_backoff, |(target_header, target_existence_status)| sync .headers_mut() .maybe_orphan_response(&target_header, target_existence_status), &mut target_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving existence status from {} node", P::TARGET_NAME), ); }, @@ -297,9 +311,10 @@ pub fn run>( target_client_is_online = process_future_result( maybe_fatal_error, + &mut target_retry_backoff, |_| {}, &mut target_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error submitting headers to {} node", P::TARGET_NAME), ); @@ -309,20 +324,22 @@ pub fn run>( target_complete_header_result = target_complete_header_future => { target_client_is_online = process_future_result( target_complete_header_result, + &mut target_retry_backoff, |completed_header| sync.headers_mut().header_completed(&completed_header), &mut target_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error completing headers at {}", P::TARGET_NAME), ); }, target_extra_check_result = target_extra_check_future => { target_client_is_online = process_future_result( target_extra_check_result, + &mut target_retry_backoff, |(header, extra_check_result)| sync .headers_mut() .maybe_extra_response(&header, extra_check_result), &mut target_go_offline_future, - || async_std::task::sleep(CONNECTION_ERROR_DELAY), + |delay| async_std::task::sleep(delay), || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), ); }, @@ -522,6 +539,15 @@ fn interval(timeout: Duration) -> impl futures::Stream { }) } +/// Exponential backoff for connection-unrelated errors retries. +fn retry_backoff() -> ExponentialBackoff { + let mut backoff = ExponentialBackoff::default(); + // we do not want relayer to stop + backoff.max_elapsed_time = None; + backoff.max_interval = MAX_BACKOFF_INTERVAL; + backoff +} + /// Process result of the future from a client. /// /// Returns whether or not the client we're interacting with is online. In this context @@ -529,9 +555,10 @@ fn interval(timeout: Duration) -> impl futures::Stream { /// that we've previously sent. fn process_future_result( result: Result, + retry_backoff: &mut ExponentialBackoff, on_success: impl FnOnce(TResult), go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, - go_offline: impl FnOnce() -> TGoOfflineFuture, + go_offline: impl FnOnce(Duration) -> TGoOfflineFuture, error_pattern: impl FnOnce() -> String, ) -> bool where @@ -543,16 +570,26 @@ where match result { Ok(result) => { on_success(result); + retry_backoff.reset(); client_is_online = true } Err(error) => { - if error.is_connection_error() { - go_offline_future.set(go_offline().fuse()); + let is_connection_error = error.is_connection_error(); + let retry_delay = if is_connection_error { + retry_backoff.reset(); + CONNECTION_ERROR_DELAY } else { - client_is_online = true - } - - log::error!(target: "bridge", "{}: {:?}", error_pattern(), error); + retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY) + }; + go_offline_future.set(go_offline(retry_delay).fuse()); + + log::error!( + target: "bridge", + "{}: {:?}. Retrying in {}s", + error_pattern(), + error, + retry_delay.as_secs_f64(), + ); } } @@ -587,3 +624,62 @@ fn print_sync_progress( ); (now_time, now_best_header.clone().map(|id| id.0), *now_target_header) } + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug)] + struct TestError(bool); + + impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + self.0 + } + } + + fn run_backoff_test(result: Result<(), TestError>) -> (Duration, Duration) { + let mut backoff = retry_backoff(); + + // no randomness in tests (otherwise intervals may overlap => asserts are failing) + backoff.randomization_factor = 0f64; + + // increase backoff's current interval + let interval1 = backoff.next_backoff().unwrap(); + let interval2 = backoff.next_backoff().unwrap(); + assert!(interval2 > interval1); + + // successful future result leads to backoff's reset + let go_offline_future = futures::future::Fuse::terminated(); + futures::pin_mut!(go_offline_future); + + process_future_result( + result, + &mut backoff, + |_| {}, + &mut go_offline_future, + |delay| async_std::task::sleep(delay), + || unreachable!(), + ); + + (interval2, backoff.next_backoff().unwrap()) + } + + #[test] + fn process_future_result_resets_backoff_on_success() { + let (interval2, interval_after_reset) = run_backoff_test(Ok(())); + assert!(interval2 > interval_after_reset); + } + + #[test] + fn process_future_result_resets_backoff_on_connection_error() { + let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(true))); + assert!(interval2 > interval_after_reset); + } + + #[test] + fn process_future_result_does_not_reset_backoff_on_non_connection_error() { + let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(false))); + assert!(interval2 < interval_after_reset); + } +} From df9e1ec7de7945c10a1f1012d4b0fcd4fb77174c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 10 Jul 2020 05:10:53 -0400 Subject: [PATCH 0093/1210] Benchmark Ethereum Pallet (#149) * Add skeleton for worst case import_unsigned_header * Fix a typo * Add benchmark test for best case unsigned header import * Add finality verification to worst case bench * Move `insert_header()` from mock to test_utils Allows the benchmarking code to use this without having to pull it in from the mock. * Add a rough bench to test a finalizing a "long" chain * Try to use complexity parameter for finality bench * Improve long finality bench * Remove stray dot file * Remove old "worst" case bench * Scribble some ideas down for pruning bench * Prune headers during benchmarking * Clean up some comments * Make finality bench work for entire range of complexity parameter * Place initialization code into a function * Add bench for block finalization with caching * First attempt at bench with receipts * Try and trigger validator set change * Perform a validator set change during benchmarking * Move `validators_change_receipt()` to shared location Allows unit tests and benchmarks to access the same helper function and const * Extract a test receipt root into a constant * Clean up description of pruning bench * Fix cache and pruning tests * Remove unecessary `build_custom_header` usage * Get rid of warnings * Remove code duplication comment I don't think its entirely worth it to split out so few lines of code. The benches aren't particularly hard to read anyways. * Increase the range of the complexity parameter * Use dynamic number of receipts while benchmarking As part of this change we have removed the hardcoded TEST_RECEIPT_ROOT and instead chose to calculate the receipt root on the fly. This will make tests and benches less fragile. * Prune a dynamic number of headers --- bin/node/runtime/src/lib.rs | 22 +++ modules/ethereum/src/benchmarking.rs | 237 +++++++++++++++++++++++++-- modules/ethereum/src/import.rs | 6 +- modules/ethereum/src/lib.rs | 8 +- modules/ethereum/src/mock.rs | 19 +-- modules/ethereum/src/test_utils.rs | 41 ++++- modules/ethereum/src/validators.rs | 31 +--- modules/ethereum/src/verification.rs | 20 +-- primitives/ethereum-poa/src/lib.rs | 2 +- 9 files changed, 315 insertions(+), 71 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index b967cf07f760d..a68ec33fa0e5b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -215,6 +215,28 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } +// We want to use a different validator configuration for benchmarking than what's used in Kovan, +// but we can't configure a new validator set on the fly which means we need to wire the runtime +// together like this +#[cfg(feature = "runtime-benchmarks")] +use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource}; + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub const FinalityVotesCachingInterval: Option = Some(16); + pub KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); + pub KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = bench_validator_config(); +} + +#[cfg(feature = "runtime-benchmarks")] +fn bench_validator_config() -> ValidatorsConfiguration { + ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(vec![[1; 20].into()])), + (1, ValidatorsSource::Contract([3; 20].into(), vec![[1; 20].into()])), + ]) +} + +#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { pub const FinalityVotesCachingInterval: Option = Some(16); pub KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 10136c1e5f42b..d31d410391220 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -16,11 +16,14 @@ use super::*; -use crate::test_utils::{build_custom_header, build_genesis_header, validator_utils::*}; +use crate::test_utils::{ + build_custom_header, build_genesis_header, insert_header, validator_utils::*, validators_change_receipt, + HeaderBuilder, +}; use frame_benchmarking::benchmarks; use frame_system::RawOrigin; -use primitives::U256; +use primitives::{compute_merkle_root, U256}; benchmarks! { _ { } @@ -33,15 +36,8 @@ benchmarks! { import_unsigned_header_best_case { let n in 1..1000; - // initialize storage with some initial header - let initial_header = build_genesis_header(&validator(0)); - let initial_header_hash = initial_header.compute_hash(); - let initial_difficulty = initial_header.difficulty; - initialize_storage::( - &initial_header, - initial_difficulty, - &validators_addresses(2), - ); + let num_validators = 2; + let initial_header = initialize_bench::(num_validators); // prepare header to be inserted let header = build_custom_header( @@ -55,6 +51,223 @@ benchmarks! { }: import_unsigned_header(RawOrigin::None, header, None) verify { - assert_eq!(BridgeStorage::::new().best_block().0.number, 1); + let storage = BridgeStorage::::new(); + assert_eq!(storage.best_block().0.number, 1); + assert_eq!(storage.finalized_block().number, 0); + } + + // Our goal with this bench is to try and see the effect that finalizing difference ranges of + // blocks has on our import time. As such we need to make sure that we keep the number of + // validators fixed while changing the number blocks finalized (the complexity parameter) by + // importing the last header. + // + // One important thing to keep in mind is that the runtime provides a finality cache in order to + // reduce the overhead of header finalization. However, this is only triggered every 16 blocks. + import_unsigned_finality { + // Our complexity parameter, n, will represent the number of blocks imported before + // finalization. + let n in 1..7; + + let mut storage = BridgeStorage::::new(); + let num_validators: u32 = 2; + let initial_header = initialize_bench::(num_validators as usize); + + // Since we only have two validators we need to make sure the number of blocks is even to + // make sure the right validator signs the final block + let num_blocks = 2 * n; + let mut headers = Vec::new(); + let mut parent = initial_header.clone(); + + // Import a bunch of headers without any verification, will ensure that they're not + // finalized prematurely + for i in 1..=num_blocks { + let header = HeaderBuilder::with_parent(&parent).sign_by(&validator(0)); + let id = header.compute_id(); + insert_header(&mut storage, header.clone()); + headers.push(header.clone()); + parent = header; + } + + let last_header = headers.last().unwrap().clone(); + let last_authority = validator(1); + + // Need to make sure that the header we're going to import hasn't been inserted + // into storage already + let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); + }: import_unsigned_header(RawOrigin::None, header, None) + verify { + let storage = BridgeStorage::::new(); + assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); + assert_eq!(storage.finalized_block().number, num_blocks as u64); + } + + // Basically the exact same as `import_unsigned_finality` but with a different range for the + // complexity parameter. In this bench we use a larger range of blocks to see how performance + // changes when the finality cache kicks in (>16 blocks). + import_unsigned_finality_with_cache { + // Our complexity parameter, n, will represent the number of blocks imported before + // finalization. + let n in 7..100; + + let mut storage = BridgeStorage::::new(); + let num_validators: u32 = 2; + let initial_header = initialize_bench::(num_validators as usize); + + // Since we only have two validators we need to make sure the number of blocks is even to + // make sure the right validator signs the final block + let num_blocks = 2 * n; + let mut headers = Vec::new(); + let mut parent = initial_header.clone(); + + // Import a bunch of headers without any verification, will ensure that they're not + // finalized prematurely + for i in 1..=num_blocks { + let header = HeaderBuilder::with_parent(&parent).sign_by(&validator(0)); + let id = header.compute_id(); + insert_header(&mut storage, header.clone()); + headers.push(header.clone()); + parent = header; + } + + let last_header = headers.last().unwrap().clone(); + let last_authority = validator(1); + + // Need to make sure that the header we're going to import hasn't been inserted + // into storage already + let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); + }: import_unsigned_header(RawOrigin::None, header, None) + verify { + let storage = BridgeStorage::::new(); + assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); + assert_eq!(storage.finalized_block().number, num_blocks as u64); + } + + // A block import may trigger a pruning event, which adds extra work to the import progress. + // In this bench we trigger a pruning event in order to see how much extra time is spent by the + // runtime dealing with it. In the Ethereum Pallet, we're limited pruning to eight blocks in a + // single import, as dictated by MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT. + import_unsigned_pruning { + let n in 1..MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT as u32; + + let mut storage = BridgeStorage::::new(); + + let num_validators = 3; + let initial_header = initialize_bench::(num_validators as usize); + let validators = validators(num_validators); + + // Want to prune eligible blocks between [0, n) + BlocksToPrune::put(PruningRange { + oldest_unpruned_block: 0, + oldest_block_to_keep: n as u64, + }); + + let mut parent = initial_header; + for i in 1..=n { + let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators); + let id = header.compute_id(); + insert_header(&mut storage, header.clone()); + parent = header; + } + + let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators); + }: import_unsigned_header(RawOrigin::None, header, None) + verify { + let storage = BridgeStorage::::new(); + let max_pruned: u64 = (n - 1) as _; + assert_eq!(storage.best_block().0.number, (n + 1) as u64); + assert!(HeadersByNumber::get(&0).is_none()); + assert!(HeadersByNumber::get(&max_pruned).is_none()); + } + + // The goal of this bench is to import a block which contains a transaction receipt. The receipt + // will contain a validator set change. Verifying the receipt root is an expensive operation to + // do, which is why we're interested in benchmarking it. + import_unsigned_with_receipts { + let n in 1..100; + + let mut storage = BridgeStorage::::new(); + + let num_validators = 1; + let initial_header = initialize_bench::(num_validators as usize); + + let mut receipts = vec![]; + for i in 1..=n { + let receipt = validators_change_receipt(Default::default()); + receipts.push(receipt) + } + let encoded_receipts = receipts.iter().map(|r| r.rlp()); + + // We need this extra header since this is what signals a validator set transition. This + // will ensure that the next header is within the "Contract" window + let header1 = HeaderBuilder::with_parent(&initial_header).sign_by(&validator(0)); + insert_header(&mut storage, header1.clone()); + + let header = build_custom_header( + &validator(0), + &header1, + |mut header| { + // Logs Bloom signals a change in validator set + header.log_bloom = (&[0xff; 256]).into(); + header.receipts_root = compute_merkle_root(encoded_receipts); + header + }, + ); + }: import_unsigned_header(RawOrigin::None, header, Some(receipts)) + verify { + let storage = BridgeStorage::::new(); + assert_eq!(storage.best_block().0.number, 2); + } +} + +fn initialize_bench(num_validators: usize) -> Header { + // Initialize storage with some initial header + let initial_header = build_genesis_header(&validator(0)); + let initial_difficulty = initial_header.difficulty; + let initial_validators = validators_addresses(num_validators as usize); + + initialize_storage::(&initial_header, initial_difficulty, &initial_validators); + + initial_header +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{run_test, TestRuntime}; + use frame_support::assert_ok; + + #[test] + fn insert_unsigned_header_best_case() { + run_test(1, |_| { + assert_ok!(test_benchmark_import_unsigned_header_best_case::()); + }); + } + + #[test] + fn insert_unsigned_header_finality() { + run_test(1, |_| { + assert_ok!(test_benchmark_import_unsigned_finality::()); + }); + } + + #[test] + fn insert_unsigned_header_finality_with_cache() { + run_test(1, |_| { + assert_ok!(test_benchmark_import_unsigned_finality_with_cache::()); + }); + } + + #[test] + fn insert_unsigned_header_pruning() { + run_test(1, |_| { + assert_ok!(test_benchmark_import_unsigned_pruning::()); + }); + } + + #[test] + fn insert_unsigned_header_receipts() { + run_test(1, |_| { + assert_ok!(test_benchmark_import_unsigned_with_receipts::()); + }); } } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index ab375d256b8e0..588b4dfdbf2cd 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -163,7 +163,7 @@ mod tests { use super::*; use crate::mock::{ run_test, secret_to_address, test_aura_config, test_validators_config, validator, validators_addresses, - HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, + validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; @@ -316,9 +316,7 @@ mod tests { &validators_config, Some(101), header11.clone(), - Some(vec![crate::validators::tests::validators_change_recept( - latest_block_id.hash, - )]), + Some(vec![validators_change_receipt(latest_block_id.hash)]), ) .unwrap(); assert_eq!(finalized_blocks, vec![(parent_id, Some(100))],); diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 1ff2c2a8ae0b4..1a87111e57df7 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -463,7 +463,7 @@ decl_storage! { // the initial blocks should be selected so that: // 1) it doesn't signal validators changes; // 2) there are no scheduled validators changes from previous blocks; - // 3) (implied) all direct children of initial block are authred by the same validators set. + // 3) (implied) all direct children of initial block are authored by the same validators set. assert!( !config.initial_validators.is_empty(), @@ -563,6 +563,7 @@ impl BridgeStorage { // start pruning blocks let begin = new_pruning_range.oldest_unpruned_block; let end = new_pruning_range.oldest_block_to_keep; + frame_support::debug::trace!(target: "runtime", "Pruning blocks in range [{}..{})", begin, end); for number in begin..end { // if we can't prune anything => break if max_blocks_to_prune == 0 { @@ -588,6 +589,11 @@ impl BridgeStorage { // we have pruned all headers at number new_pruning_range.oldest_unpruned_block = number + 1; + frame_support::debug::trace!( + target: "runtime", + "Oldest unpruned PoA header is now: {}", + new_pruning_range.oldest_unpruned_block, + ); } // update pruning range in storage diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index c169eaec3c87f..94986d3d5815d 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -14,12 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -pub use crate::test_utils::{validator_utils::*, HeaderBuilder, GAS_LIMIT}; +pub use crate::test_utils::{insert_header, validator_utils::*, validators_change_receipt, HeaderBuilder, GAS_LIMIT}; pub use primitives::signatures::secret_to_address; -use crate::finality::FinalityVotes; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, PruningStrategy, Storage, Trait}; +use crate::{AuraConfiguration, GenesisConfig, PruningStrategy, Trait}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use primitives::{Address, Header, H256, U256}; use secp256k1::SecretKey; @@ -149,20 +148,6 @@ pub fn run_test_with_genesis(genesis: Header, total_validators: usize, test: }) } -/// Insert unverified header into storage. -pub fn insert_header(storage: &mut S, header: Header) { - storage.insert_header(HeaderToImport { - context: storage.import_context(None, &header.parent_hash).unwrap(), - is_best: true, - id: header.compute_id(), - header, - total_difficulty: 0.into(), - enacted_change: None, - scheduled_change: None, - finality_votes: FinalityVotes::default(), - }); -} - /// Pruning strategy that keeps 10 headers behind best block. pub struct KeepSomeHeadersBehindBest(pub u64); diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 2a424542d76c8..a4c51e4ac6866 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -21,12 +21,18 @@ //! //! On the other hand, they may be used directly by the bechmarking module. +// Since this is test code it's fine that not everything is used +#![allow(dead_code)] + +use crate::finality::FinalityVotes; +use crate::validators::CHANGE_EVENT_HASH; use crate::verification::calculate_score; +use crate::{HeaderToImport, Storage}; use primitives::{ rlp_encode, signatures::{secret_to_address, sign, SignHeader}, - Address, Bloom, Header, SealedEmptyStep, H256, U256, + Address, Bloom, Header, Receipt, SealedEmptyStep, H256, U256, }; use secp256k1::SecretKey; use sp_std::prelude::*; @@ -206,6 +212,39 @@ where custom_header.sign_by(author) } +/// Insert unverified header into storage. +pub fn insert_header(storage: &mut S, header: Header) { + storage.insert_header(HeaderToImport { + context: storage.import_context(None, &header.parent_hash).unwrap(), + is_best: true, + id: header.compute_id(), + header, + total_difficulty: 0.into(), + enacted_change: None, + scheduled_change: None, + finality_votes: FinalityVotes::default(), + }); +} + +pub fn validators_change_receipt(parent_hash: H256) -> Receipt { + use primitives::{LogEntry, TransactionOutcome}; + + Receipt { + gas_used: 0.into(), + log_bloom: (&[0xff; 256]).into(), + outcome: TransactionOutcome::Unknown, + logs: vec![LogEntry { + address: [3; 20].into(), + topics: vec![CHANGE_EVENT_HASH.into(), parent_hash], + data: vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + ], + }], + } +} + pub mod validator_utils { use super::*; diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index e6a454cc63772..5620bcb86c0a8 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -20,7 +20,7 @@ use primitives::{Address, Header, HeaderId, LogEntry, Receipt, U256}; use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. -const CHANGE_EVENT_HASH: &'static [u8; 32] = &[ +pub(crate) const CHANGE_EVENT_HASH: &'static [u8; 32] = &[ 0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, 0xd2, 0xc2, 0x28, 0x1d, 0xf8, 0xd6, 0xea, 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89, ]; @@ -39,7 +39,7 @@ pub enum ValidatorsConfiguration { /// This source is valid within some blocks range. The blocks range could /// cover multiple epochs - i.e. the validators that are authoring blocks /// within this range could change, but the source itself can not. -#[cfg_attr(test, derive(Debug, PartialEq))] +#[cfg_attr(any(test, feature = "runtime-benchmarks"), derive(Debug, PartialEq))] pub enum ValidatorsSource { /// The validators addresses are hardcoded and never change. List(Vec

), @@ -276,30 +276,13 @@ impl ValidatorsSource { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::mock::{run_test, validators_addresses, TestRuntime}; + use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}; use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader}; use frame_support::StorageMap; - use primitives::{TransactionOutcome, H256}; + use primitives::compute_merkle_root; const TOTAL_VALIDATORS: usize = 3; - pub(crate) fn validators_change_recept(parent_hash: H256) -> Receipt { - Receipt { - gas_used: 0.into(), - log_bloom: (&[0xff; 256]).into(), - outcome: TransactionOutcome::Unknown, - logs: vec![LogEntry { - address: [3; 20].into(), - topics: vec![CHANGE_EVENT_HASH.into(), parent_hash], - data: vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - ], - }], - } - } - #[test] fn source_at_works() { let config = ValidatorsConfiguration::Multi(vec![ @@ -405,10 +388,8 @@ pub(crate) mod tests { // when we're inside contract range and logs bloom signals change // and there's change in receipts - let receipts = vec![validators_change_recept(Default::default())]; - header.receipts_root = "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" - .parse() - .unwrap(); + let receipts = vec![validators_change_receipt(Default::default())]; + header.receipts_root = compute_merkle_root(receipts.iter().map(|r| r.rlp())); assert_eq!( validators.extract_validators_change(&header, Some(receipts)), Ok((Some(vec![[7; 20].into()]), None)), diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 031b85ab4aba7..3c49e81eac1c4 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -140,6 +140,7 @@ pub fn accept_aura_header_into_pool( // the heaviest, but rare operation - we do not want invalid receipts in the pool if let Some(receipts) = receipts { + frame_support::debug::trace!(target: "runtime", "Got receipts! {:?}", receipts); if !header.verify_receipts_root(receipts) { return Err(Error::TransactionsReceiptsMismatch); } @@ -354,15 +355,15 @@ mod tests { use super::*; use crate::mock::{ insert_header, run_test_with_genesis, test_aura_config, validator, validator_address, validators_addresses, - AccountId, HeaderBuilder, TestRuntime, GAS_LIMIT, + validators_change_receipt, AccountId, HeaderBuilder, TestRuntime, GAS_LIMIT, }; - use crate::validators::{tests::validators_change_recept, ValidatorsSource}; + use crate::validators::ValidatorsSource; use crate::{ pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, ScheduledChanges, ValidatorsSet, ValidatorsSets, }; use frame_support::{StorageMap, StorageValue}; - use primitives::{rlp_encode, TransactionOutcome, H520}; + use primitives::{compute_merkle_root, rlp_encode, TransactionOutcome, H520}; use secp256k1::SecretKey; const GENESIS_STEP: u64 = 42; @@ -844,7 +845,7 @@ mod tests { let header = HeaderBuilder::with_parent_number(3) .log_bloom((&[0xff; 256]).into()) .sign_by_set(validators); - (header, Some(vec![validators_change_recept(Default::default())])) + (header, Some(vec![validators_change_receipt(Default::default())])) }), Err(Error::TransactionsReceiptsMismatch), ); @@ -853,18 +854,17 @@ mod tests { #[test] fn pool_accepts_headers_with_valid_receipts() { let mut hash = None; + let receipts = vec![validators_change_receipt(Default::default())]; + let receipts_root = compute_merkle_root(receipts.iter().map(|r| r.rlp())); + assert_eq!( default_accept_into_pool(|validators| { let header = HeaderBuilder::with_parent_number(3) .log_bloom((&[0xff; 256]).into()) - .receipts_root( - "81ce88dc524403b796222046bf3daf543978329b87ffd50228f1d3987031dc45" - .parse() - .unwrap(), - ) + .receipts_root(receipts_root) .sign_by_set(validators); hash = Some(header.compute_hash()); - (header, Some(vec![validators_change_recept(Default::default())])) + (header, Some(receipts.clone())) }), Ok(( // no tags are required diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index a4fac244bf792..95e69f62c5133 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -322,7 +322,7 @@ impl UnsignedTransaction { impl Receipt { /// Returns receipt RLP. - fn rlp(&self) -> Bytes { + pub fn rlp(&self) -> Bytes { let mut s = RlpStream::new(); match self.outcome { TransactionOutcome::Unknown => { From a57ffd947b8c287a698fb69b0f48490f87db3ae2 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 10 Jul 2020 05:40:46 -0400 Subject: [PATCH 0094/1210] Update Substrate to rc4 (#175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump Substrate to rc4 * Add BaseCallFilter type * Add DenyUnsafe to SystemApi extension * Use new ServiceBuilder build functions * Add BaseCallFilter to test runtimes * Remove old comments * Add `rev` and `git` fields back Turns out that if you don't have these future release candidates will be used if available. For instance, once `rc5` is released a fresh pull would use that instead of `rc4` which is what we want. * Use tag release instead of specific commit Will make scripted updates easier in the future * Add short script to update between `rc` versions * Update scripts/update_rc.sh Co-authored-by: Tomasz Drwięga --- bin/node/node/Cargo.toml | 92 ++++++++-------- bin/node/node/src/service.rs | 12 ++- bin/node/runtime/Cargo.toml | 105 +++++++++---------- bin/node/runtime/src/lib.rs | 2 + modules/currency-exchange/Cargo.toml | 28 ++--- modules/currency-exchange/src/lib.rs | 1 + modules/ethereum-contract/builtin/Cargo.toml | 20 ++-- modules/ethereum/Cargo.toml | 24 ++--- modules/ethereum/src/mock.rs | 1 + modules/substrate/Cargo.toml | 36 +++---- modules/substrate/src/lib.rs | 1 + primitives/currency-exchange/Cargo.toml | 8 +- primitives/ethereum-poa/Cargo.toml | 16 +-- relays/ethereum/Cargo.toml | 29 +++-- relays/substrate/Cargo.toml | 12 +-- 15 files changed, 195 insertions(+), 192 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 0b7b5ab6ab449..c0a2f936cd17d 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -20,110 +20,110 @@ bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } [dependencies.sc-cli] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa] package = "sc-finality-grandpa" -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-client-api] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking-cli] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -131,13 +131,13 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [build-dependencies.frame-benchmarking-cli] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [features] diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 96728beb81bcd..b033ff5327da3 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -92,12 +92,14 @@ macro_rules! new_full_start { }, )? .with_rpc_extensions(|builder| -> Result, _> { + use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( builder.client().clone(), builder.pool(), + DenyUnsafe::No, ))); Ok(io) })?; @@ -124,7 +126,7 @@ pub fn new_full(config: Configuration) -> Result>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? - .build()?; + .build_full()?; if role.is_authority() { let proposer = sc_basic_authorship::ProposerFactory::new( @@ -153,7 +155,7 @@ pub fn new_full(config: Configuration) -> Result Result Result>; Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) })? - .build() + .build_light() } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 1d75dc3fecb7d..99b4389ce17c4 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -23,15 +23,15 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-bridge-eth-poa] @@ -45,76 +45,76 @@ default-features = false path = "../../../modules/currency-exchange" [dependencies.frame-support] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-bridge-eth-poa] @@ -128,76 +128,76 @@ default-features = false path = "../../../primitives/currency-exchange" [dependencies.sp-consensus-aura] -version = "0.8.0-rc3" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-bridge-eth-poa] @@ -209,7 +209,6 @@ path = "../../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] version = "1.0.5" package = "substrate-wasm-builder-runner" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [features] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a68ec33fa0e5b..7e0d2a10d1274 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -157,6 +157,8 @@ parameter_types! { } impl frame_system::Trait for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = (); /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index b9a71150a18ea..ac45876a6b2a1 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -13,44 +13,44 @@ sp-currency-exchange = { path = "../../primitives/currency-exchange", default-fe # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-io] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index cfefd5b4adb37..6970fa18f4658 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -312,6 +312,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type BaseCallFilter = (); } impl Trait for TestRuntime { diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index d8f4cf8fb9f4d..5867e1176c9f9 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -19,29 +19,29 @@ finality-grandpa = "0.12.3" bridge-node-runtime = { path = "../../../bin/node/runtime" } [dependencies.sp-blockchain] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dependencies.sc-finality-grandpa] -version = "0.8.0-dev" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dev-dependencies] hex = "0.4" [dev-dependencies.sp-core] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 32a5b997d1194..c22adb8490676 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -14,40 +14,40 @@ primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum- # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.libsecp256k1] diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 94986d3d5815d..6c68d927586be 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -68,6 +68,7 @@ impl frame_system::Trait for TestRuntime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type BaseCallFilter = (); } parameter_types! { diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 605d70231f7c6..fefacdd458d0e 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -14,57 +14,57 @@ hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 148ebd5ef9866..61d50d6fdd556 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -273,6 +273,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); + type BaseCallFilter = (); } impl Trait for Test {} diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 1bbfac6a61344..432a1ae9e82a8 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -12,15 +12,15 @@ codec = { package = "parity-scale-codec", version = "1.0.0", default-features = # Substrate Based Dependencies [dependencies.sp-std] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.frame-support] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [features] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 0ccabfaa592b4..945752bc348aa 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -23,27 +23,27 @@ plain_hasher = { version = "0.2.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-rc3" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' default-features = false -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" git = "https://github.com/paritytech/substrate.git" [dependencies.libsecp256k1] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 6619a3ca7ea75..743f2793c0342 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -40,40 +40,35 @@ features = ["http"] # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" -# I think this is used for sr-io and stuff [dependencies.node-primitives] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" -# Branch used for keccack256 hasher code -# Could probably move the keccack hasher stuff to our own primitives [dependencies.sp-core] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" -# This should get moved to our `bin` folder [dependencies.bridge-node-runtime] version = "0.1.0" path = "../../bin/node/runtime" -# node-runtime = { git = "https://github.com/svyatonik/substrate.git", branch = "bridge_runtime" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e391a18901b36..7d51a35cff6cc 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -18,16 +18,16 @@ serde_json = "1.0.56" url = "2.1.0" [dependencies.sp-core] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dependencies.sp-rpc] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" [dependencies.node-primitives] -version = "2.0.0-rc3" -rev = "606c56d2e2f69f68f3947551224be6a3515dff60" +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate/" From 85ef49fac524fb68e993663b4b73f909d5b7df81 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 10 Jul 2020 13:23:16 +0300 Subject: [PATCH 0095/1210] do not panic when logging is enalbed (#180) --- relays/ethereum/src/sync_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index e1437ccdc57ee..73ccc49b9803a 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -659,7 +659,7 @@ mod tests { |_| {}, &mut go_offline_future, |delay| async_std::task::sleep(delay), - || unreachable!(), + || "Test error".into(), ); (interval2, backoff.next_backoff().unwrap()) From 91ebae77bcdf6e32940132201c854f5b95dc8d17 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2020 13:09:21 +0000 Subject: [PATCH 0096/1210] Bump ctrlc from 3.1.4 to 3.1.5 (#184) --- relays/substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 7d51a35cff6cc..f80fc087e9f13 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "=1.5.0" clap = "2.33.1" -ctrlc = "3.1.4" +ctrlc = "3.1.5" derive_more = "0.99.9" env_logger = "0.7.1" futures = "0.3.5" From c01831178d9fe41fbea5f69e66daf113b05f8e65 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Jul 2020 12:06:17 +0300 Subject: [PATCH 0097/1210] Basic tests for sync loop (#182) * basic sync loop tests * cargo ftm --all * SyncLoopTestParams * move sync loop tests to sync_loop_tests.rs * cargo fmt --all --- relays/ethereum/src/ethereum_sync_loop.rs | 1 + relays/ethereum/src/main.rs | 1 + relays/ethereum/src/substrate_sync_loop.rs | 1 + relays/ethereum/src/sync.rs | 42 +- relays/ethereum/src/sync_loop.rs | 76 +-- relays/ethereum/src/sync_loop_tests.rs | 573 +++++++++++++++++++++ 6 files changed, 626 insertions(+), 68 deletions(-) create mode 100644 relays/ethereum/src/sync_loop_tests.rs diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 65d53946ebbe3..a270386ccb887 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -204,6 +204,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { target, SUBSTRATE_TICK_INTERVAL, params.sync_params, + futures::future::pending(), ); Ok(()) diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 5786ff23dbfce..0ca3c95a28b40 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -28,6 +28,7 @@ mod substrate_sync_loop; mod substrate_types; mod sync; mod sync_loop; +mod sync_loop_tests; mod sync_types; mod utils; diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 4da5fcb1290af..7e77c2392a5f8 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -209,6 +209,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { target, ETHEREUM_TICK_INTERVAL, params.sync_params, + futures::future::pending(), ); Ok(()) diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 4cfd3b4ab92f4..3e16f9630f372 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -16,7 +16,7 @@ use crate::headers::QueuedHeaders; use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; -use num_traits::{One, Saturating}; +use num_traits::{One, Saturating, Zero}; /// Common sync params. #[derive(Debug, Clone)] @@ -112,12 +112,19 @@ impl HeadersSync

{ return None; } + // if queue is empty and best header on target is > than best header on source, + // then we shoud reorg + let best_queued_number = self.headers.best_queued_number(); + if best_queued_number.is_zero() && source_best_number < target_best_header.0 { + return Some(source_best_number); + } + // we assume that there were no reorgs if we have already downloaded best header let best_downloaded_number = std::cmp::max( - std::cmp::max(self.headers.best_queued_number(), self.headers.best_synced_number()), + std::cmp::max(best_queued_number, self.headers.best_synced_number()), target_best_header.0, ); - if best_downloaded_number == source_best_number { + if best_downloaded_number >= source_best_number { return None; } @@ -125,6 +132,21 @@ impl HeadersSync

{ Some(best_downloaded_number + One::one()) } + /// Selech orphan header to downoload. + pub fn select_orphan_header_to_download(&self) -> Option<&QueuedHeader

> { + let orphan_header = self.headers.header(HeaderStatus::Orphan)?; + + // we consider header orphan until we'll find it ancestor that is known to the target node + // => we may get orphan header while we ask target node whether it knows its parent + // => let's avoid fetching duplicate headers + let parent_id = orphan_header.parent_id(); + if self.headers.status(&parent_id) != HeaderStatus::Unknown { + return None; + } + + Some(orphan_header) + } + /// Select headers that need to be submitted to the target node. pub fn select_headers_to_submit(&self, stalled: bool) -> Option>> { // if we operate in backup mode, we only submit headers when sync has stalled @@ -208,7 +230,7 @@ impl HeadersSync

{ } #[cfg(test)] -mod tests { +pub mod tests { use super::*; use crate::ethereum_types::{EthereumHeadersSyncPipeline, H256}; use crate::headers::tests::{header, id}; @@ -218,7 +240,7 @@ mod tests { H256::from_low_u64_le(1000 + number) } - fn default_sync_params() -> HeadersSyncParams { + pub fn default_sync_params() -> HeadersSyncParams { HeadersSyncParams { max_future_headers_to_download: 128, max_headers_in_submitted_status: 128, @@ -253,6 +275,11 @@ mod tests { eth_sync.source_best_number = Some(101); assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); + // when we have to reorganize to longer fork + eth_sync.source_best_number = Some(100); + eth_sync.target_best_header = Some(HeaderId(200, Default::default())); + assert_eq!(eth_sync.select_new_header_to_download(), Some(100)); + // when there are too many headers scheduled for submitting for i in 1..1000 { eth_sync.headers.header_response(header(i).header().clone()); @@ -356,6 +383,11 @@ mod tests { assert_eq!(eth_sync.headers.header(HeaderStatus::Orphan), Some(&header(101))); eth_sync.headers.header_response(header(100).header().clone()); + // #101 is now Orphan and #100 is MaybeOrphan => we do not want to retrieve + // header #100 again + assert_eq!(eth_sync.headers.header(HeaderStatus::Orphan), Some(&header(101))); + assert_eq!(eth_sync.select_orphan_header_to_download(), None); + // we can't submit header #100, because its parent status is unknown assert_eq!(eth_sync.select_headers_to_submit(false), None); diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 73ccc49b9803a..200c4a38f3f1f 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -25,6 +25,7 @@ use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; use std::{ collections::HashSet, + future::Future, time::{Duration, Instant}, }; @@ -123,6 +124,7 @@ pub fn run>( target_client: TC, target_tick: Duration, sync_params: HeadersSyncParams, + exit_signal: impl Future, ) { let mut local_pool = futures::executor::LocalPool::new(); let mut progress_context = (Instant::now(), None, None); @@ -156,6 +158,8 @@ pub fn run>( let target_go_offline_future = futures::future::Fuse::terminated(); let target_tick_stream = interval(target_tick).fuse(); + let exit_signal = exit_signal.fuse(); + futures::pin_mut!( source_best_block_number_future, source_new_header_future, @@ -171,7 +175,8 @@ pub fn run>( target_submit_header_future, target_complete_header_future, target_go_offline_future, - target_tick_stream + target_tick_stream, + exit_signal ); loop { @@ -350,6 +355,10 @@ pub fn run>( target_best_block_required = true; target_incomplete_headers_required = true; }, + + _ = exit_signal => { + return; + } } // print progress @@ -491,7 +500,7 @@ pub fn run>( id, ); source_extra_future.set(source_client.header_extra(id, header.clone()).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::Orphan) { + } else if let Some(header) = sync.select_orphan_header_to_download() { // for Orphan we actually ask for parent' header let parent_id = header.parent_id(); @@ -540,7 +549,7 @@ fn interval(timeout: Duration) -> impl futures::Stream { } /// Exponential backoff for connection-unrelated errors retries. -fn retry_backoff() -> ExponentialBackoff { +pub(crate) fn retry_backoff() -> ExponentialBackoff { let mut backoff = ExponentialBackoff::default(); // we do not want relayer to stop backoff.max_elapsed_time = None; @@ -553,7 +562,7 @@ fn retry_backoff() -> ExponentialBackoff { /// Returns whether or not the client we're interacting with is online. In this context /// what online means is that the client is currently not handling any other requests /// that we've previously sent. -fn process_future_result( +pub(crate) fn process_future_result( result: Result, retry_backoff: &mut ExponentialBackoff, on_success: impl FnOnce(TResult), @@ -624,62 +633,3 @@ fn print_sync_progress( ); (now_time, now_best_header.clone().map(|id| id.0), *now_target_header) } - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Debug)] - struct TestError(bool); - - impl MaybeConnectionError for TestError { - fn is_connection_error(&self) -> bool { - self.0 - } - } - - fn run_backoff_test(result: Result<(), TestError>) -> (Duration, Duration) { - let mut backoff = retry_backoff(); - - // no randomness in tests (otherwise intervals may overlap => asserts are failing) - backoff.randomization_factor = 0f64; - - // increase backoff's current interval - let interval1 = backoff.next_backoff().unwrap(); - let interval2 = backoff.next_backoff().unwrap(); - assert!(interval2 > interval1); - - // successful future result leads to backoff's reset - let go_offline_future = futures::future::Fuse::terminated(); - futures::pin_mut!(go_offline_future); - - process_future_result( - result, - &mut backoff, - |_| {}, - &mut go_offline_future, - |delay| async_std::task::sleep(delay), - || "Test error".into(), - ); - - (interval2, backoff.next_backoff().unwrap()) - } - - #[test] - fn process_future_result_resets_backoff_on_success() { - let (interval2, interval_after_reset) = run_backoff_test(Ok(())); - assert!(interval2 > interval_after_reset); - } - - #[test] - fn process_future_result_resets_backoff_on_connection_error() { - let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(true))); - assert!(interval2 > interval_after_reset); - } - - #[test] - fn process_future_result_does_not_reset_backoff_on_non_connection_error() { - let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(false))); - assert!(interval2 < interval_after_reset); - } -} diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/ethereum/src/sync_loop_tests.rs new file mode 100644 index 0000000000000..cf62c67f6e9ba --- /dev/null +++ b/relays/ethereum/src/sync_loop_tests.rs @@ -0,0 +1,573 @@ +// Copyright 2019-2020 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 . + +#![cfg(test)] + +use crate::sync_loop::{process_future_result, retry_backoff, run, SourceClient, TargetClient}; +use crate::sync_types::{ + HeaderId, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SourceHeader, SubmittedHeaders, +}; + +use async_trait::async_trait; +use backoff::backoff::Backoff; +use futures::{future::FutureExt, stream::StreamExt}; +use parking_lot::Mutex; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::Duration, +}; + +type TestNumber = u64; +type TestHash = u64; +type TestExtra = u64; +type TestCompletion = u64; +type TestHeaderId = HeaderId; +type TestQueuedHeader = QueuedHeader; + +#[derive(Debug, Clone, PartialEq)] +struct TestHeader { + hash: TestHash, + number: TestNumber, + parent_hash: TestHash, +} + +impl SourceHeader for TestHeader { + fn id(&self) -> TestHeaderId { + HeaderId(self.number, self.hash) + } + + fn parent_id(&self) -> TestHeaderId { + HeaderId(self.number - 1, self.parent_hash) + } +} + +#[derive(Debug, Clone)] +struct TestError(bool); + +impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + self.0 + } +} + +#[derive(Debug, Clone, Copy)] +struct TestHeadersSyncPipeline; + +impl HeadersSyncPipeline for TestHeadersSyncPipeline { + const SOURCE_NAME: &'static str = "Source"; + const TARGET_NAME: &'static str = "Target"; + + type Hash = TestHash; + type Number = TestNumber; + type Header = TestHeader; + type Extra = TestExtra; + type Completion = TestCompletion; + + fn estimate_size(_: &TestQueuedHeader) -> usize { + 0 + } +} + +enum SourceMethod { + BestBlockNumber, + HeaderByHash(TestHash), + HeaderByNumber(TestNumber), + HeaderCompletion(TestHeaderId), + HeaderExtra(TestHeaderId, TestQueuedHeader), +} + +struct Source { + data: Mutex, + on_method_call: Arc, +} + +struct SourceData { + best_block_number: Result, + header_by_hash: HashMap, + header_by_number: HashMap, + provides_completion: bool, + provides_extra: bool, +} + +impl Source { + pub fn new( + best_block_id: TestHeaderId, + headers: Vec<(bool, TestHeader)>, + on_method_call: impl Fn(SourceMethod, &mut SourceData) + Send + Sync + 'static, + ) -> Self { + Source { + data: Mutex::new(SourceData { + best_block_number: Ok(best_block_id.0), + header_by_hash: headers + .iter() + .map(|(_, header)| (header.hash, header.clone())) + .collect(), + header_by_number: headers + .iter() + .filter_map(|(is_canonical, header)| { + if *is_canonical { + Some((header.hash, header.clone())) + } else { + None + } + }) + .collect(), + provides_completion: true, + provides_extra: true, + }), + on_method_call: Arc::new(on_method_call), + } + } +} + +#[async_trait] +impl SourceClient for Source { + type Error = TestError; + + async fn best_block_number(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(SourceMethod::BestBlockNumber, &mut *data); + data.best_block_number.clone() + } + + async fn header_by_hash(&self, hash: TestHash) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(SourceMethod::HeaderByHash(hash), &mut *data); + data.header_by_hash.get(&hash).cloned().ok_or(TestError(false)) + } + + async fn header_by_number(&self, number: TestNumber) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(SourceMethod::HeaderByNumber(number), &mut *data); + data.header_by_number.get(&number).cloned().ok_or(TestError(false)) + } + + async fn header_completion(&self, id: TestHeaderId) -> Result<(TestHeaderId, Option), Self::Error> { + let mut data = self.data.lock(); + (self.on_method_call)(SourceMethod::HeaderCompletion(id), &mut *data); + if data.provides_completion { + Ok((id, Some(test_completion(id)))) + } else { + Ok((id, None)) + } + } + + async fn header_extra( + &self, + id: TestHeaderId, + header: TestQueuedHeader, + ) -> Result<(TestHeaderId, TestExtra), Self::Error> { + let mut data = self.data.lock(); + (self.on_method_call)(SourceMethod::HeaderExtra(id, header), &mut *data); + if data.provides_extra { + Ok((id, test_extra(id))) + } else { + Err(TestError(false)) + } + } +} + +enum TargetMethod { + BestHeaderId, + IsKnownHeader(TestHeaderId), + SubmitHeaders(Vec), + IncompleteHeadersIds, + CompleteHeader(TestHeaderId, TestCompletion), + RequiresExtra(TestQueuedHeader), +} + +struct Target { + data: Mutex, + on_method_call: Arc, +} + +struct TargetData { + best_header_id: Result, + is_known_header_by_hash: HashMap, + submitted_headers: HashMap, + submit_headers_result: Option>, + completed_headers: HashMap, + requires_completion: bool, + requires_extra: bool, +} + +impl Target { + pub fn new( + best_header_id: TestHeaderId, + headers: Vec, + on_method_call: impl Fn(TargetMethod, &mut TargetData) + Send + Sync + 'static, + ) -> Self { + Target { + data: Mutex::new(TargetData { + best_header_id: Ok(best_header_id), + is_known_header_by_hash: headers.iter().map(|header| (header.1, true)).collect(), + submitted_headers: HashMap::new(), + submit_headers_result: None, + completed_headers: HashMap::new(), + requires_completion: false, + requires_extra: false, + }), + on_method_call: Arc::new(on_method_call), + } + } +} + +#[async_trait] +impl TargetClient for Target { + type Error = TestError; + + async fn best_header_id(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(TargetMethod::BestHeaderId, &mut *data); + data.best_header_id.clone() + } + + async fn is_known_header(&self, id: TestHeaderId) -> Result<(TestHeaderId, bool), TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(TargetMethod::IsKnownHeader(id), &mut *data); + data.is_known_header_by_hash + .get(&id.1) + .cloned() + .map(|is_known_header| Ok((id, is_known_header))) + .unwrap_or(Ok((id, false))) + } + + async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { + let mut data = self.data.lock(); + (self.on_method_call)(TargetMethod::SubmitHeaders(headers.clone()), &mut *data); + data.submitted_headers + .extend(headers.iter().map(|header| (header.id().1, header.clone()))); + data.submit_headers_result.take().expect("test must accept headers") + } + + async fn incomplete_headers_ids(&self) -> Result, TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(TargetMethod::IncompleteHeadersIds, &mut *data); + if data.requires_completion { + Ok(data + .submitted_headers + .iter() + .filter(|(hash, _)| !data.completed_headers.contains_key(hash)) + .map(|(_, header)| header.id()) + .collect()) + } else { + Ok(HashSet::new()) + } + } + + async fn complete_header(&self, id: TestHeaderId, completion: TestCompletion) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(TargetMethod::CompleteHeader(id, completion), &mut *data); + data.completed_headers.insert(id.1, completion); + Ok(id) + } + + async fn requires_extra(&self, header: TestQueuedHeader) -> Result<(TestHeaderId, bool), TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(TargetMethod::RequiresExtra(header.clone()), &mut *data); + if data.requires_extra { + Ok((header.id(), true)) + } else { + Ok((header.id(), false)) + } + } +} + +fn test_tick() -> Duration { + // in ideal world that should have been Duration::from_millis(0), because we do not want + // to sleep in tests at all, but that could lead to `select! {}` always waking on tick + // => not doing actual job + Duration::from_millis(10) +} + +fn test_id(number: TestNumber) -> TestHeaderId { + HeaderId(number, number) +} + +fn test_header(number: TestNumber) -> TestHeader { + let id = test_id(number); + TestHeader { + hash: id.1, + number: id.0, + parent_hash: if number == 0 { + TestHash::default() + } else { + test_id(number - 1).1 + }, + } +} + +fn test_forked_id(number: TestNumber, forked_from: TestNumber) -> TestHeaderId { + const FORK_OFFSET: TestNumber = 1000; + + if number == forked_from { + HeaderId(number, number) + } else { + HeaderId(number, FORK_OFFSET + number) + } +} + +fn test_forked_header(number: TestNumber, forked_from: TestNumber) -> TestHeader { + let id = test_forked_id(number, forked_from); + TestHeader { + hash: id.1, + number: id.0, + parent_hash: if number == 0 { + TestHash::default() + } else { + test_forked_id(number - 1, forked_from).1 + }, + } +} + +fn test_completion(id: TestHeaderId) -> TestCompletion { + id.0 +} + +fn test_extra(id: TestHeaderId) -> TestExtra { + id.0 +} + +fn source_reject_completion(method: &SourceMethod) { + if let SourceMethod::HeaderCompletion(_) = method { + unreachable!("HeaderCompletion request is not expected") + } +} + +fn source_reject_extra(method: &SourceMethod) { + if let SourceMethod::HeaderExtra(_, _) = method { + unreachable!("HeaderExtra request is not expected") + } +} + +fn target_accept_all_headers(method: &TargetMethod, data: &mut TargetData, requires_extra: bool) { + if let TargetMethod::SubmitHeaders(ref submitted) = method { + assert_eq!(submitted.iter().all(|header| header.extra().is_some()), requires_extra,); + + let mut submitted_headers = SubmittedHeaders::default(); + submitted_headers.submitted = submitted.iter().map(|header| header.id()).collect(); + data.submit_headers_result = Some(submitted_headers); + } +} + +fn target_signal_exit_when_header_submitted( + method: &TargetMethod, + header_id: TestHeaderId, + exit_signal: &futures::channel::mpsc::UnboundedSender<()>, +) { + if let TargetMethod::SubmitHeaders(ref submitted) = method { + if submitted.iter().any(|header| header.id() == header_id) { + exit_signal.unbounded_send(()).unwrap(); + } + } +} + +fn target_signal_exit_when_header_completed( + method: &TargetMethod, + header_id: TestHeaderId, + exit_signal: &futures::channel::mpsc::UnboundedSender<()>, +) { + if let TargetMethod::CompleteHeader(completed_id, _) = method { + if *completed_id == header_id { + exit_signal.unbounded_send(()).unwrap(); + } + } +} + +fn run_backoff_test(result: Result<(), TestError>) -> (Duration, Duration) { + let mut backoff = retry_backoff(); + + // no randomness in tests (otherwise intervals may overlap => asserts are failing) + backoff.randomization_factor = 0f64; + + // increase backoff's current interval + let interval1 = backoff.next_backoff().unwrap(); + let interval2 = backoff.next_backoff().unwrap(); + assert!(interval2 > interval1); + + // successful future result leads to backoff's reset + let go_offline_future = futures::future::Fuse::terminated(); + futures::pin_mut!(go_offline_future); + + process_future_result( + result, + &mut backoff, + |_| {}, + &mut go_offline_future, + |delay| async_std::task::sleep(delay), + || "Test error".into(), + ); + + (interval2, backoff.next_backoff().unwrap()) +} + +#[test] +fn process_future_result_resets_backoff_on_success() { + let (interval2, interval_after_reset) = run_backoff_test(Ok(())); + assert!(interval2 > interval_after_reset); +} + +#[test] +fn process_future_result_resets_backoff_on_connection_error() { + let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(true))); + assert!(interval2 > interval_after_reset); +} + +#[test] +fn process_future_result_does_not_reset_backoff_on_non_connection_error() { + let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(false))); + assert!(interval2 < interval_after_reset); +} + +struct SyncLoopTestParams { + best_source_header: TestHeader, + headers_on_source: Vec<(bool, TestHeader)>, + best_target_header: TestHeader, + headers_on_target: Vec, + target_requires_extra: bool, + target_requires_completion: bool, + stop_at: TestHeaderId, +} + +fn run_sync_loop_test(params: SyncLoopTestParams) { + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + let target_requires_extra = params.target_requires_extra; + let target_requires_completion = params.target_requires_completion; + let stop_at = params.stop_at; + let source = Source::new( + params.best_source_header.id(), + params.headers_on_source, + move |method, _| { + if !target_requires_extra { + source_reject_extra(&method); + } + if !target_requires_completion { + source_reject_completion(&method); + } + }, + ); + let target = Target::new( + params.best_target_header.id(), + params.headers_on_target.into_iter().map(|header| header.id()).collect(), + move |method, data| { + target_accept_all_headers(&method, data, target_requires_extra); + if target_requires_completion { + target_signal_exit_when_header_completed(&method, stop_at, &exit_sender); + } else { + target_signal_exit_when_header_submitted(&method, stop_at, &exit_sender); + } + }, + ); + target.data.lock().requires_extra = target_requires_extra; + target.data.lock().requires_completion = target_requires_completion; + + run( + source, + test_tick(), + target, + test_tick(), + crate::sync::tests::default_sync_params(), + exit_receiver.into_future().map(|(_, _)| ()), + ); +} + +#[test] +fn sync_loop_is_able_to_synchronize_single_header() { + run_sync_loop_test(SyncLoopTestParams { + best_source_header: test_header(1), + headers_on_source: vec![(true, test_header(1))], + best_target_header: test_header(0), + headers_on_target: vec![test_header(0)], + target_requires_extra: false, + target_requires_completion: false, + stop_at: test_id(1), + }); +} + +#[test] +fn sync_loop_is_able_to_synchronize_single_header_with_extra() { + run_sync_loop_test(SyncLoopTestParams { + best_source_header: test_header(1), + headers_on_source: vec![(true, test_header(1))], + best_target_header: test_header(0), + headers_on_target: vec![test_header(0)], + target_requires_extra: true, + target_requires_completion: false, + stop_at: test_id(1), + }); +} + +#[test] +fn sync_loop_is_able_to_synchronize_single_header_with_completion() { + run_sync_loop_test(SyncLoopTestParams { + best_source_header: test_header(1), + headers_on_source: vec![(true, test_header(1))], + best_target_header: test_header(0), + headers_on_target: vec![test_header(0)], + target_requires_extra: false, + target_requires_completion: true, + stop_at: test_id(1), + }); +} + +#[test] +fn sync_loop_is_able_to_reorganize_from_shorter_fork() { + run_sync_loop_test(SyncLoopTestParams { + best_source_header: test_header(3), + headers_on_source: vec![ + (true, test_header(1)), + (true, test_header(2)), + (true, test_header(3)), + (false, test_forked_header(1, 0)), + (false, test_forked_header(2, 0)), + ], + best_target_header: test_forked_header(2, 0), + headers_on_target: vec![test_header(0), test_forked_header(1, 0), test_forked_header(2, 0)], + target_requires_extra: false, + target_requires_completion: false, + stop_at: test_id(3), + }); +} + +#[test] +fn sync_loop_is_able_to_reorganize_from_longer_fork() { + run_sync_loop_test(SyncLoopTestParams { + best_source_header: test_header(3), + headers_on_source: vec![ + (true, test_header(1)), + (true, test_header(2)), + (true, test_header(3)), + (false, test_forked_header(1, 0)), + (false, test_forked_header(2, 0)), + (false, test_forked_header(3, 0)), + (false, test_forked_header(4, 0)), + (false, test_forked_header(5, 0)), + ], + best_target_header: test_forked_header(5, 0), + headers_on_target: vec![ + test_header(0), + test_forked_header(1, 0), + test_forked_header(2, 0), + test_forked_header(3, 0), + test_forked_header(4, 0), + test_forked_header(5, 0), + ], + target_requires_extra: false, + target_requires_completion: false, + stop_at: test_id(3), + }); +} From 61bc0d594a0ff90f7580f84d1e6f72f611d9eb3d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Jul 2020 12:07:03 +0300 Subject: [PATCH 0098/1210] Relay PoA lock-funds transactions proofs (#177) * relay exchange transaction(s) * fixed Ethereum::get_block_by_hash * added exchange trace * fixed method name * update for new web3 * svyatonik/rust-web3 -> tomusdrw/rust-web3 * if let Some() -> .expect() * extracted loops in separate functions * use yaml references (TIL) * get eth header with transactions * cargo fmt --all * Update primitives/ethereum-poa/src/lib.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/ethereum_exchange.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/rpc_errors.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/exchange.rs Co-authored-by: Hernando Castano * removed comment * Update relays/ethereum/src/ethereum_exchange.rs Co-authored-by: Hernando Castano * Update relays/ethereum/src/ethereum_exchange.rs Co-authored-by: Hernando Castano * module-level comments * updated readme * use web3 from crates.io * added missing fields info in error description * cargo fmt --all Co-authored-by: Hernando Castano --- README.md | 2 + bin/node/runtime/src/lib.rs | 8 +- modules/currency-exchange/src/lib.rs | 8 +- modules/ethereum/src/lib.rs | 5 + primitives/currency-exchange/src/lib.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 3 + relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/cli.yml | 82 ++-- relays/ethereum/src/ethereum_client.rs | 27 +- relays/ethereum/src/ethereum_exchange.rs | 214 ++++++++++ relays/ethereum/src/ethereum_types.rs | 6 + relays/ethereum/src/exchange.rs | 494 +++++++++++++++++++++++ relays/ethereum/src/main.rs | 26 ++ relays/ethereum/src/rpc.rs | 15 +- relays/ethereum/src/rpc_errors.rs | 30 +- relays/ethereum/src/substrate_client.rs | 84 +++- 16 files changed, 931 insertions(+), 77 deletions(-) create mode 100644 relays/ethereum/src/ethereum_exchange.rs create mode 100644 relays/ethereum/src/exchange.rs diff --git a/README.md b/README.md index 2547ca8a4453d..7204e2f0fe895 100644 --- a/README.md +++ b/README.md @@ -141,8 +141,10 @@ The folder structure of the bridge relay is as follows: │ │ └── src │ │ ├── ethereum_client.rs // Interface for Ethereum RPC │ │ ├── ethereum_deploy_contract.rs // Utility for deploying bridge contract to Ethereum +│ │ ├── ethereum_exchange.rs // Relay proof of PoA -> Substrate exchange transactions │ │ ├── ethereum_sync_loop.rs // Sync headers from Ethereum, submit to Substrate │ │ ├── ethereum_types.rs // Useful Ethereum types +│ │ ├── exchange.rs // Relay proof of exchange transactions │ │ ├── headers.rs // Track synced and incoming block headers │ │ ├── main.rs // Entry point to binary │ │ ├── substrate_client.rs // Interface for Substrate RPC diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7e0d2a10d1274..8ed1e5fbef40f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -24,8 +24,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod exchange; - +pub mod exchange; pub mod kovan; use codec::{Decode, Encode}; @@ -553,6 +552,11 @@ impl_runtime_apis! { (best_block.number, best_block.hash) } + fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { + let finalized_block = BridgeEthPoA::finalized_block(); + (finalized_block.number, finalized_block.hash) + } + fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { BridgeEthPoA::is_import_requires_receipts(header) } diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 6970fa18f4658..959538b7465f7 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -131,12 +131,18 @@ decl_module! { Err(ExchangeError::DepositPartiallyFailed) => (), Err(error) => Err(Error::::from(error))?, } - Transfers::::insert(transfer_id, ()) + Transfers::::insert(&transfer_id, ()) } // reward submitter for providing valid message T::OnTransactionSubmitted::on_valid_transaction_submitted(submitter); + frame_support::debug::trace!( + target: "runtime", + "Completed currency exchange: {:?}", + transfer_id, + ); + Ok(()) } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 1a87111e57df7..db54613b8e768 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -487,6 +487,11 @@ impl Module { BridgeStorage::::new().best_block().0 } + /// Returns number and hash of the best finalized block known to the bridge module. + pub fn finalized_block() -> HeaderId { + BridgeStorage::::new().finalized_block() + } + /// Returns true if the import of given block requires transactions receipts. pub fn is_import_requires_receipts(header: Header) -> bool { import::header_import_requires_receipts(&BridgeStorage::::new(), &T::ValidatorsConfiguration::get(), &header) diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index f864d4b733a90..00836dee23bf5 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -58,7 +58,7 @@ pub trait MaybeLockFundsTransaction { /// Transaction type. type Transaction; /// Identifier that uniquely identifies this transfer. - type Id: Decode + Encode + EncodeLike; + type Id: Decode + Encode + EncodeLike + sp_std::fmt::Debug; /// Peer recipient type. type Recipient; /// Peer currency amount type. diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 95e69f62c5133..c0cf4da9d599a 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -508,6 +508,9 @@ sp_api::decl_runtime_apis! { /// (or leads to making) other header the best one. fn best_block() -> (u64, H256); + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (u64, H256); + /// Returns true if the import of given block requires transactions receipts. fn is_import_requires_receipts(header: Header) -> bool; diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 743f2793c0342..35f88282b0967 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -30,7 +30,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.56" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" -web3 = { version = "0.12.0", default-features = false } +web3 = "0.13" [dependencies.jsonrpsee] git = "https://github.com/svyatonik/jsonrpsee.git" diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 4cb33fd7b9cea..7425584c485ba 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -6,22 +6,22 @@ subcommands: - eth-to-sub: about: Synchronize headers from Ethereum node to Substrate node. args: - - eth-host: + - eth-host: ð-host long: eth-host value_name: ETH_HOST help: Connect to Ethereum node at given host. takes_value: true - - eth-port: + - eth-port: ð-port long: eth-port value_name: ETH_PORT help: Connect to Ethereum node at given port. takes_value: true - - sub-host: + - sub-host: &sub-host long: sub-host value_name: SUB_HOST help: Connect to Substrate node at given host. takes_value: true - - sub-port: + - sub-port: &sub-port long: sub-port value_name: SUB_PORT help: Connect to Substrate node at given port. @@ -35,78 +35,43 @@ subcommands: - signed - unsigned - backup - - sub-signer: + - sub-signer: &sub-signer long: sub-signer value_name: SUB_SIGNER help: The SURI of secret key to use when transactions are submitted to the Substrate node. - - sub-signer-password: + - sub-signer-password: &sub-signer-password long: sub-signer-password value_name: SUB_SIGNER_PASSWORD help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. - sub-to-eth: about: Synchronize headers from Substrate node to Ethereum node. args: - - eth-host: - long: eth-host - value_name: ETH_HOST - help: Connect to Ethereum node at given host. - takes_value: true - - eth-port: - long: eth-port - value_name: ETH_PORT - help: Connect to Ethereum node at given port. - takes_value: true + - eth-host: *eth-host + - eth-port: *eth-port - eth-contract: long: eth-contract value_name: ETH_CONTRACT help: Address of deployed bridge contract. takes_value: true - - eth-signer: + - eth-signer: ð-signer long: eth-signer value_name: ETH_SIGNER help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. - - sub-host: - long: sub-host - value_name: SUB_HOST - help: Connect to Substrate node at given host. - takes_value: true - - sub-port: - long: sub-port - value_name: SUB_PORT - help: Connect to Substrate node at given port. - takes_value: true + - sub-host: *sub-host + - sub-port: *sub-port - eth-deploy-contract: about: Deploy Bridge contract on Ethereum node. args: - - eth-host: - long: eth-host - value_name: ETH_HOST - help: Connect to Ethereum node at given host. - takes_value: true - - eth-port: - long: eth-port - value_name: ETH_PORT - help: Connect to Ethereum node at given port. - takes_value: true - - eth-signer: - long: eth-signer - value_name: ETH_SIGNER - help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. + - eth-host: *eth-host + - eth-port: *eth-port + - eth-signer: *eth-signer - eth-contract-code: long: eth-contract-code value_name: ETH_CONTRACT_CODE help: Bytecode of bridge contract. takes_value: true - - sub-host: - long: sub-host - value_name: SUB_HOST - help: Connect to Substrate node at given host. - takes_value: true - - sub-port: - long: sub-port - value_name: SUB_PORT - help: Connect to Substrate node at given port. - takes_value: true + - sub-host: *sub-host + - sub-port: *sub-port - sub-authorities-set-id: long: sub-authorities-set-id value_name: SUB_AUTHORITIES_SET_ID @@ -122,3 +87,18 @@ subcommands: value_name: SUB_INITIAL_HEADER help: Encoded initial Substrate header. takes_value: true + - eth-exchange-sub: + about: Submit proof of PoA lock funds transaction to Substrate node. + args: + - eth-host: *eth-host + - eth-port: *eth-port + - eth-tx-hash: + long: eth-tx-hash + value_name: ETH_TX_HASH + help: Hash of the lock funds transaction. + takes_value: true + required: true + - sub-host: *sub-host + - sub-port: *sub-port + - sub-signer: *sub-signer + - sub-signer-password: *sub-signer-password diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index ffc14f77584e4..e23f1e5c5a8ef 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -15,7 +15,8 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_types::{ - Address, Bytes, CallRequest, EthereumHeaderId, Header, Receipt, SignedRawTx, TransactionHash, H256, U256, + Address, Bytes, CallRequest, EthereumHeaderId, Header, HeaderWithTransactions, Receipt, SignedRawTx, Transaction, + TransactionHash, H256, U256, }; use crate::rpc::{Ethereum, EthereumRpc}; use crate::rpc_errors::{EthereumNodeError, RpcError}; @@ -120,13 +121,35 @@ impl EthereumRpc for EthereumRpcClient { } async fn header_by_hash(&self, hash: H256) -> Result

{ - let header = Ethereum::get_block_by_hash(&self.client, hash).await?; + let get_full_tx_objects = false; + let header = Ethereum::get_block_by_hash(&self.client, hash, get_full_tx_objects).await?; match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { true => Ok(header), false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), } } + async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { + let get_full_tx_objects = true; + let header = Ethereum::get_block_by_hash_with_transactions(&self.client, hash, get_full_tx_objects).await?; + + let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + if !is_complete_header { + return Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)); + } + + let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); + if !is_complete_transactions { + return Err(RpcError::Ethereum(EthereumNodeError::IncompleteTransaction)); + } + + Ok(header) + } + + async fn transaction_by_hash(&self, hash: H256) -> Result> { + Ok(Ethereum::transaction_by_hash(&self.client, hash).await?) + } + async fn transaction_receipt(&self, transaction_hash: H256) -> Result { let receipt = Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?; diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs new file mode 100644 index 0000000000000..385c68a3fef7d --- /dev/null +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -0,0 +1,214 @@ +// Copyright 2019-2020 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 . + +//! Relaying proofs of PoA -> Substrate exchange transactions. + +use crate::ethereum_client::{EthereumConnectionParams, EthereumRpcClient}; +use crate::ethereum_types::{ + EthereumHeaderId, Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, +}; +use crate::exchange::{relay_single_transaction_proof, SourceClient, TargetClient, TransactionProofPipeline}; +use crate::rpc::{EthereumRpc, SubstrateRpc}; +use crate::rpc_errors::{EthereumNodeError, RpcError}; +use crate::substrate_client::{ + SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, +}; +use crate::sync_types::HeaderId; + +use async_trait::async_trait; +use bridge_node_runtime::exchange::EthereumTransactionInclusionProof; +use std::time::Duration; + +/// Interval at which we ask Ethereum node for updates. +const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); +/// Interval at which we ask Substrate node for updates. +const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); + +/// PoA exchange transaction relay params. +#[derive(Debug, Default)] +pub struct EthereumExchangeParams { + /// Ethereum connection params. + pub eth: EthereumConnectionParams, + /// Hash of the Ethereum transaction to relay. + pub eth_tx_hash: EthereumTransactionHash, + /// Substrate connection params. + pub sub: SubstrateConnectionParams, + /// Substrate signing params. + pub sub_sign: SubstrateSigningParams, +} + +/// Ethereum to Substrate exchange pipeline. +struct EthereumToSubstrateExchange; + +impl TransactionProofPipeline for EthereumToSubstrateExchange { + const SOURCE_NAME: &'static str = "Ethereum"; + const TARGET_NAME: &'static str = "Substrate"; + + type BlockHash = H256; + type BlockNumber = u64; + type TransactionHash = EthereumTransactionHash; + type Transaction = EthereumTransaction; + type TransactionProof = EthereumTransactionInclusionProof; +} + +/// Ethereum node as transactions proof source. +struct EthereumTransactionsSource { + client: EthereumRpcClient, +} + +#[async_trait] +impl SourceClient for EthereumTransactionsSource { + type Error = RpcError; + + async fn tick(&self) { + async_std::task::sleep(ETHEREUM_TICK_INTERVAL).await; + } + + async fn transaction( + &self, + hash: &EthereumTransactionHash, + ) -> Result, Self::Error> { + let eth_tx = match self.client.transaction_by_hash(*hash).await? { + Some(eth_tx) => eth_tx, + None => return Ok(None), + }; + + // we need transaction to be mined => check if it is included in the block + let eth_header_id = match (eth_tx.block_number, eth_tx.block_hash) { + (Some(block_number), Some(block_hash)) => HeaderId(block_number.as_u64(), block_hash), + _ => return Ok(None), + }; + + Ok(Some((eth_header_id, eth_tx))) + } + + async fn transaction_proof( + &self, + eth_header_id: &EthereumHeaderId, + eth_tx: EthereumTransaction, + ) -> Result { + const TRANSACTION_HAS_RAW_FIELD_PROOF: &'static str = "RPC level checks that transactions from Ethereum\ + node are having `raw` field; qed"; + + let eth_header = self.client.header_by_hash_with_transactions(eth_header_id.1).await?; + let eth_relay_tx_hash = eth_tx.hash; + let mut eth_relay_tx = Some(eth_tx); + let mut eth_relay_tx_index = None; + let mut transaction_proof = Vec::with_capacity(eth_header.transactions.len()); + for (index, eth_tx) in eth_header.transactions.into_iter().enumerate() { + if eth_tx.hash != eth_relay_tx_hash { + let eth_raw_tx = eth_tx.raw.expect(TRANSACTION_HAS_RAW_FIELD_PROOF); + transaction_proof.push(eth_raw_tx.0); + } else { + let eth_raw_relay_tx = match eth_relay_tx.take() { + Some(eth_relay_tx) => eth_relay_tx.raw.expect(TRANSACTION_HAS_RAW_FIELD_PROOF), + None => { + return Err( + EthereumNodeError::DuplicateBlockTransaction(*eth_header_id, eth_relay_tx_hash).into(), + ) + } + }; + eth_relay_tx_index = Some(index as u64); + transaction_proof.push(eth_raw_relay_tx.0); + } + } + + Ok(EthereumTransactionInclusionProof { + block: eth_header_id.1, + index: eth_relay_tx_index.ok_or_else(|| { + RpcError::from(EthereumNodeError::BlockMissingTransaction( + *eth_header_id, + eth_relay_tx_hash, + )) + })?, + proof: transaction_proof, + }) + } +} + +/// Substrate node as transactions proof target. +struct SubstrateTransactionsTarget { + client: SubstrateRpcClient, + sign_params: SubstrateSigningParams, +} + +#[async_trait] +impl TargetClient for SubstrateTransactionsTarget { + type Error = RpcError; + + async fn tick(&self) { + async_std::task::sleep(SUBSTRATE_TICK_INTERVAL).await; + } + + async fn is_header_known(&self, id: &EthereumHeaderId) -> Result { + self.client.ethereum_header_known(*id).await + } + + async fn is_header_finalized(&self, id: &EthereumHeaderId) -> Result { + // we check if header is finalized by simple comparison of the header number and + // number of best finalized PoA header known to Substrate node. + // + // this may lead to failure in tx proof import if PoA reorganization has happened + // after we have checked that our tx has been included into given block + // + // the fix is easy, but since this code is mostly developed for demonstration purposes, + // I'm leaving this KISS-based design here + let best_finalized_ethereum_block = self.client.best_ethereum_finalized_block().await?; + Ok(id.0 <= best_finalized_ethereum_block.0) + } + + async fn submit_transaction_proof(&self, proof: EthereumTransactionInclusionProof) -> Result<(), Self::Error> { + let sign_params = self.sign_params.clone(); + self.client.submit_exchange_transaction_proof(sign_params, proof).await + } +} + +/// Relay exchange transaction proof to Substrate node. +pub fn run(params: EthereumExchangeParams) { + let eth_tx_hash = params.eth_tx_hash; + let mut local_pool = futures::executor::LocalPool::new(); + + let result = local_pool.run_until(async move { + let eth_client = EthereumRpcClient::new(params.eth); + let sub_client = SubstrateRpcClient::new(params.sub).await?; + + let source = EthereumTransactionsSource { client: eth_client }; + let target = SubstrateTransactionsTarget { + client: sub_client, + sign_params: params.sub_sign, + }; + + relay_single_transaction_proof(&source, &target, eth_tx_hash).await + }); + + match result { + Ok(_) => { + log::info!( + target: "bridge", + "Ethereum transaction {} proof has been successfully submitted to Substrate node", + eth_tx_hash, + ); + } + Err(err) => { + log::error!( + target: "bridge", + "Error submitting Ethereum transaction {} proof to Substrate node: {}", + eth_tx_hash, + err, + ); + } + } +} diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index 46ba869ac2a59..6e118e3ad986a 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -31,9 +31,15 @@ pub const RECEIPT_GAS_USED_PROOF: &'static str = "checked on retrieval; qed"; /// Ethereum transaction hash type. pub type TransactionHash = H256; +/// Ethereum transaction type. +pub type Transaction = web3::types::Transaction; + /// Ethereum header type. pub type Header = web3::types::Block; +/// Ethereum header with transactions type. +pub type HeaderWithTransactions = web3::types::Block; + /// Ethereum transaction receipt type. pub type Receipt = web3::types::TransactionReceipt; diff --git a/relays/ethereum/src/exchange.rs b/relays/ethereum/src/exchange.rs new file mode 100644 index 0000000000000..d465e8a214949 --- /dev/null +++ b/relays/ethereum/src/exchange.rs @@ -0,0 +1,494 @@ +// Copyright 2019-2020 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 . + +//! Relaying proofs of exchange transactions. + +use async_trait::async_trait; +use std::fmt::{Debug, Display}; + +/// Transaction proof pipeline. +pub trait TransactionProofPipeline { + /// Name of the transaction proof source. + const SOURCE_NAME: &'static str; + /// Name of the transaction proof target. + const TARGET_NAME: &'static str; + + /// Block hash type. + type BlockHash: Display; + /// Block number type. + type BlockNumber: Display; + /// Transaction hash type. + type TransactionHash: Display; + /// Transaction type. + type Transaction; + /// Transaction inclusion proof type. + type TransactionProof; +} + +/// Header id. +pub type HeaderId

= crate::sync_types::HeaderId< +

::BlockHash, +

::BlockNumber, +>; + +/// Source client API. +#[async_trait] +pub trait SourceClient { + /// Error type. + type Error: Debug; + + /// Sleep until exchange-related data is (probably) updated. + async fn tick(&self); + /// Return **mined** transaction by its hash. May return `Ok(None)` if transaction is unknown to the source node. + async fn transaction( + &self, + hash: &P::TransactionHash, + ) -> Result, P::Transaction)>, Self::Error>; + /// Prepare transaction proof. + async fn transaction_proof( + &self, + header: &HeaderId

, + transaction: P::Transaction, + ) -> Result; +} + +/// Target client API. +#[async_trait] +pub trait TargetClient { + /// Error type. + type Error: Debug; + + /// Sleep until exchange-related data is (probably) updated. + async fn tick(&self); + /// Returns `Ok(true)` if header is known to the target node. + async fn is_header_known(&self, id: &HeaderId

) -> Result; + /// Returns `Ok(true)` if header is finalized by the target node. + async fn is_header_finalized(&self, id: &HeaderId

) -> Result; + /// Submits transaction proof to the target node. + async fn submit_transaction_proof(&self, proof: P::TransactionProof) -> Result<(), Self::Error>; +} + +/// Relay single transaction proof. +pub async fn relay_single_transaction_proof( + source_client: &impl SourceClient

, + target_client: &impl TargetClient

, + source_tx_hash: P::TransactionHash, +) -> Result<(), String> { + // wait for transaction and header on source node + let (source_header_id, source_tx) = wait_transaction_mined(source_client, &source_tx_hash).await?; + let transaction_proof = source_client + .transaction_proof(&source_header_id, source_tx) + .await + .map_err(|err| { + format!( + "Error building transaction {} proof on {} node: {:?}", + source_tx_hash, + P::SOURCE_NAME, + err, + ) + })?; + + // wait for transaction and header on target node + wait_header_imported(target_client, &source_header_id).await?; + wait_header_finalized(target_client, &source_header_id).await?; + + // and finally - submit transaction proof to target node + target_client + .submit_transaction_proof(transaction_proof) + .await + .map_err(|err| { + format!( + "Error submitting transaction {} proof to {} node: {:?}", + source_tx_hash, + P::TARGET_NAME, + err, + ) + }) +} + +/// Wait until transaction is mined by source node. +async fn wait_transaction_mined( + source_client: &impl SourceClient

, + source_tx_hash: &P::TransactionHash, +) -> Result<(HeaderId

, P::Transaction), String> { + loop { + let source_header_and_tx = source_client.transaction(&source_tx_hash).await.map_err(|err| { + format!( + "Error retrieving transaction {} from {} node: {:?}", + source_tx_hash, + P::SOURCE_NAME, + err, + ) + })?; + match source_header_and_tx { + Some((source_header_id, source_tx)) => { + log::info!( + target: "bridge", + "Transaction {} is retrieved from {} node. Continuing...", + source_tx_hash, + P::SOURCE_NAME, + ); + + return Ok((source_header_id, source_tx)); + } + None => { + log::info!( + target: "bridge", + "Waiting for transaction {} to be mined by {} node...", + source_tx_hash, + P::SOURCE_NAME, + ); + + source_client.tick().await; + } + } + } +} + +/// Wait until target node imports required header. +async fn wait_header_imported( + target_client: &impl TargetClient

, + source_header_id: &HeaderId

, +) -> Result<(), String> { + loop { + let is_header_known = target_client.is_header_known(&source_header_id).await.map_err(|err| { + format!( + "Failed to check existence of header {}/{} on {} node: {:?}", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + err, + ) + })?; + match is_header_known { + true => { + log::info!( + target: "bridge", + "Header {}/{} is known to {} node. Continuing.", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + ); + + return Ok(()); + } + false => { + log::info!( + target: "bridge", + "Waiting for header {}/{} to be imported by {} node...", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + ); + + target_client.tick().await; + } + } + } +} + +/// Wait until target node finalizes required header. +async fn wait_header_finalized( + target_client: &impl TargetClient

, + source_header_id: &HeaderId

, +) -> Result<(), String> { + loop { + let is_header_finalized = target_client + .is_header_finalized(&source_header_id) + .await + .map_err(|err| { + format!( + "Failed to check finality of header {}/{} on {} node: {:?}", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + err, + ) + })?; + match is_header_finalized { + true => { + log::info!( + target: "bridge", + "Header {}/{} is finalizd by {} node. Continuing.", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + ); + + return Ok(()); + } + false => { + log::info!( + target: "bridge", + "Waiting for header {}/{} to be finalized by {} node...", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + ); + + target_client.tick().await; + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::sync_types::HeaderId; + + use parking_lot::Mutex; + + fn test_header_id() -> TestHeaderId { + HeaderId(100, 100) + } + + fn test_transaction_hash() -> TestTransactionHash { + 200 + } + + fn test_transaction() -> TestTransaction { + 300 + } + + fn test_transaction_proof() -> TestTransactionProof { + 400 + } + + type TestError = u64; + type TestBlockNumber = u64; + type TestBlockHash = u64; + type TestTransactionHash = u64; + type TestTransaction = u64; + type TestTransactionProof = u64; + type TestHeaderId = HeaderId; + + struct TestTransactionProofPipeline; + + impl TransactionProofPipeline for TestTransactionProofPipeline { + const SOURCE_NAME: &'static str = "TestSource"; + const TARGET_NAME: &'static str = "TestTarget"; + + type BlockHash = TestBlockHash; + type BlockNumber = TestBlockNumber; + type TransactionHash = TestTransactionHash; + type Transaction = TestTransaction; + type TransactionProof = TestTransactionProof; + } + + struct TestTransactionsSource { + on_tick: Box, + data: Mutex, + } + + struct TestTransactionsSourceData { + transaction: Result, TestError>, + transaction_proof: Result, + } + + impl TestTransactionsSource { + fn new(on_tick: Box) -> Self { + Self { + on_tick, + data: Mutex::new(TestTransactionsSourceData { + transaction: Ok(Some((test_header_id(), test_transaction()))), + transaction_proof: Ok(test_transaction_proof()), + }), + } + } + } + + #[async_trait] + impl SourceClient for TestTransactionsSource { + type Error = TestError; + + async fn tick(&self) { + (self.on_tick)(&mut *self.data.lock()) + } + + async fn transaction( + &self, + _: &TestTransactionHash, + ) -> Result, TestError> { + self.data.lock().transaction.clone() + } + + async fn transaction_proof( + &self, + _: &TestHeaderId, + _: TestTransaction, + ) -> Result { + self.data.lock().transaction_proof.clone() + } + } + + struct TestTransactionsTarget { + on_tick: Box, + data: Mutex, + } + + struct TestTransactionsTargetData { + is_header_known: Result, + is_header_finalized: Result, + submitted_proofs: Vec, + } + + impl TestTransactionsTarget { + fn new(on_tick: Box) -> Self { + Self { + on_tick, + data: Mutex::new(TestTransactionsTargetData { + is_header_known: Ok(true), + is_header_finalized: Ok(true), + submitted_proofs: Vec::new(), + }), + } + } + } + + #[async_trait] + impl TargetClient for TestTransactionsTarget { + type Error = TestError; + + async fn tick(&self) { + (self.on_tick)(&mut *self.data.lock()) + } + + async fn is_header_known(&self, _: &TestHeaderId) -> Result { + self.data.lock().is_header_known.clone() + } + + async fn is_header_finalized(&self, _: &TestHeaderId) -> Result { + self.data.lock().is_header_finalized.clone() + } + + async fn submit_transaction_proof(&self, proof: TestTransactionProof) -> Result<(), TestError> { + self.data.lock().submitted_proofs.push(proof); + Ok(()) + } + } + + fn ensure_success(source: TestTransactionsSource, target: TestTransactionsTarget) { + assert_eq!( + async_std::task::block_on(relay_single_transaction_proof( + &source, + &target, + test_transaction_hash(), + )), + Ok(()), + ); + assert_eq!(target.data.lock().submitted_proofs, vec![test_transaction_proof()],); + } + + fn ensure_failure(source: TestTransactionsSource, target: TestTransactionsTarget) { + assert!(async_std::task::block_on(relay_single_transaction_proof( + &source, + &target, + test_transaction_hash(), + )) + .is_err(),); + assert!(target.data.lock().submitted_proofs.is_empty()); + } + + #[test] + fn ready_transaction_proof_relayed_immediately() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + ensure_success(source, target) + } + + #[test] + fn relay_transaction_proof_waits_for_transaction_to_be_mined() { + let source = TestTransactionsSource::new(Box::new(|source_data| { + assert_eq!(source_data.transaction, Ok(None)); + source_data.transaction = Ok(Some((test_header_id(), test_transaction()))); + })); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + // transaction is not yet mined, but will be available after first wait (tick) + source.data.lock().transaction = Ok(None); + + ensure_success(source, target) + } + + #[test] + fn relay_transaction_fails_when_transaction_retrieval_fails() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + source.data.lock().transaction = Err(0); + + ensure_failure(source, target) + } + + #[test] + fn relay_transaction_fails_when_proof_retrieval_fails() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + source.data.lock().transaction_proof = Err(0); + + ensure_failure(source, target) + } + + #[test] + fn relay_transaction_proof_waits_for_header_to_be_imported() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|target_data| { + assert_eq!(target_data.is_header_known, Ok(false)); + target_data.is_header_known = Ok(true); + })); + + // header is not yet imported, but will be available after first wait (tick) + target.data.lock().is_header_known = Ok(false); + + ensure_success(source, target) + } + + #[test] + fn relay_transaction_proof_fails_when_is_header_known_fails() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + target.data.lock().is_header_known = Err(0); + + ensure_failure(source, target) + } + + #[test] + fn relay_transaction_proof_waits_for_header_to_be_finalized() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|target_data| { + assert_eq!(target_data.is_header_finalized, Ok(false)); + target_data.is_header_finalized = Ok(true); + })); + + // header is not yet finalized, but will be available after first wait (tick) + target.data.lock().is_header_finalized = Ok(false); + + ensure_success(source, target) + } + + #[test] + fn relay_transaction_proof_fails_when_is_header_finalized_fails() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + target.data.lock().is_header_finalized = Err(0); + + ensure_failure(source, target) + } +} diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 0ca3c95a28b40..2c6a5457512ef 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -18,8 +18,10 @@ mod ethereum_client; mod ethereum_deploy_contract; +mod ethereum_exchange; mod ethereum_sync_loop; mod ethereum_types; +mod exchange; mod headers; mod rpc; mod rpc_errors; @@ -83,6 +85,15 @@ fn main() { } }); } + ("eth-exchange-sub", Some(eth_exchange_matches)) => { + ethereum_exchange::run(match ethereum_exchange_params(ð_exchange_matches) { + Ok(eth_exchange_params) => eth_exchange_params, + Err(err) => { + log::error!(target: "bridge", "Error relaying Ethereum transactions proofs: {}", err); + return; + } + }); + } ("", _) => { log::error!(target: "bridge", "No subcommand specified"); return; @@ -225,3 +236,18 @@ fn ethereum_deploy_contract_params( Ok(eth_deploy_params) } + +fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result { + let mut params = ethereum_exchange::EthereumExchangeParams::default(); + params.eth = ethereum_connection_params(matches)?; + params.sub = substrate_connection_params(matches)?; + params.sub_sign = substrate_signing_params(matches)?; + + params.eth_tx_hash = matches + .value_of("eth-tx-hash") + .expect("eth-tx-hash is a required parameter; clap verifies that required parameters have matches; qed") + .parse() + .map_err(|e| format!("Failed to parse eth-tx-hash: {}", e))?; + + Ok(params) +} diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs index 1dc253406c080..412add5f8efde 100644 --- a/relays/ethereum/src/rpc.rs +++ b/relays/ethereum/src/rpc.rs @@ -25,7 +25,8 @@ use std::result; use crate::ethereum_types::{ - Address as EthAddress, Bytes, CallRequest, EthereumHeaderId, Header as EthereumHeader, Receipt, SignedRawTx, + Address as EthAddress, Bytes, CallRequest, EthereumHeaderId, Header as EthereumHeader, + HeaderWithTransactions as EthereumHeaderWithTransactions, Receipt, SignedRawTx, Transaction as EthereumTransaction, TransactionHash as EthereumTxHash, H256, U256, U64, }; use crate::rpc_errors::RpcError; @@ -48,7 +49,11 @@ jsonrpsee::rpc_api! { #[rpc(method = "eth_getBlockByNumber", positional_params)] fn get_block_by_number(block_number: U64, full_tx_objs: bool) -> EthereumHeader; #[rpc(method = "eth_getBlockByHash", positional_params)] - fn get_block_by_hash(hash: H256) -> EthereumHeader; + fn get_block_by_hash(hash: H256, full_tx_objs: bool) -> EthereumHeader; + #[rpc(method = "eth_getBlockByHash", positional_params)] + fn get_block_by_hash_with_transactions(hash: H256, full_tx_objs: bool) -> EthereumHeaderWithTransactions; + #[rpc(method = "eth_getTransactionByHash", positional_params)] + fn transaction_by_hash(hash: H256) -> Option; #[rpc(method = "eth_getTransactionReceipt", positional_params)] fn get_transaction_receipt(transaction_hash: H256) -> Receipt; #[rpc(method = "eth_getTransactionCount", positional_params)] @@ -86,6 +91,10 @@ pub trait EthereumRpc { async fn header_by_number(&self, block_number: u64) -> Result; /// Retrieve block header by its hash from Ethereum node. async fn header_by_hash(&self, hash: H256) -> Result; + /// Retrieve block header and its transactions by its hash from Ethereum node. + async fn header_by_hash_with_transactions(&self, hash: H256) -> Result; + /// Retrieve transaction by its hash from Ethereum node. + async fn transaction_by_hash(&self, hash: H256) -> Result>; /// Retrieve transaction receipt by transaction hash. async fn transaction_receipt(&self, transaction_hash: H256) -> Result; /// Get the nonce of the given account. @@ -117,6 +126,8 @@ pub trait SubstrateRpc { async fn next_account_index(&self, account: node_primitives::AccountId) -> Result; /// Returns best Ethereum block that Substrate runtime knows of. async fn best_ethereum_block(&self) -> Result; + /// Returns best finalized Ethereum block that Substrate runtime knows of. + async fn best_ethereum_finalized_block(&self) -> Result; /// Returns whether or not transactions receipts are required for Ethereum header submission. async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> Result; /// Returns whether or not the given Ethereum header is known to the Substrate runtime. diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 34295df756d6d..65f757a0e01d7 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::ethereum_types::{EthereumHeaderId, TransactionHash as EthereumTransactionHash}; use crate::sync_types::MaybeConnectionError; use jsonrpsee::client::RequestError; @@ -101,20 +102,39 @@ pub enum EthereumNodeError { IncompleteHeader, /// We have received a receipt missing a `gas_used` field. IncompleteReceipt, + /// We have received a transaction missing a `raw` field. + IncompleteTransaction, /// An invalid Substrate block number was received from /// an Ethereum node. InvalidSubstrateBlockNumber, + /// Block includes the same transaction more than once. + DuplicateBlockTransaction(EthereumHeaderId, EthereumTransactionHash), + /// Block is missing transaction we believe is a part of this block. + BlockMissingTransaction(EthereumHeaderId, EthereumTransactionHash), } impl ToString for EthereumNodeError { fn to_string(&self) -> String { match self { - Self::ResponseParseFailed(e) => e, - Self::IncompleteHeader => "Incomplete Ethereum Header Received", - Self::IncompleteReceipt => "Incomplete Ethereum Receipt Recieved", - Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node", + Self::ResponseParseFailed(e) => e.to_string(), + Self::IncompleteHeader => { + "Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom)" + .to_string() + } + Self::IncompleteReceipt => { + "Incomplete Ethereum Receipt Recieved (missing required field - gas_used)".to_string() + } + Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), + Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), + Self::DuplicateBlockTransaction(header_id, tx_hash) => format!( + "Ethereum block {}/{} includes Ethereum transaction {} more than once", + header_id.0, header_id.1, tx_hash, + ), + Self::BlockMissingTransaction(header_id, tx_hash) => format!( + "Ethereum block {}/{} is missing Ethereum transaction {} which we believe is a part of this block", + header_id.0, header_id.1, tx_hash, + ), } - .to_string() } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 43549292cef6d..82e1081b85240 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -37,6 +37,7 @@ use std::collections::VecDeque; const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; +const ETH_API_BEST_FINALIZED_BLOCK: &str = "EthereumHeadersApi_finalized_block"; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; type Result = std::result::Result; @@ -142,6 +143,17 @@ impl SubstrateRpc for SubstrateRpcClient { Ok(best_header_id) } + async fn best_ethereum_finalized_block(&self) -> Result { + let call = ETH_API_BEST_FINALIZED_BLOCK.to_string(); + let data = Bytes("0x".into()); + + let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + Ok(best_header_id) + } + async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> Result { let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); let data = Bytes(header.encode()); @@ -281,6 +293,42 @@ impl SubmitEthereumHeaders for SubstrateRpcClient { } } +/// A trait for RPC calls which are used to submit proof of Ethereum exchange transaction to a +/// Substrate runtime. These are typically calls which use a combination of other low-level RPC +/// calls. +#[async_trait] +pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { + /// Submits Ethereum exchange transaction proof to Substrate runtime. + async fn submit_exchange_transaction_proof( + &self, + params: SubstrateSigningParams, + proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + ) -> Result<()>; +} + +#[async_trait] +impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { + async fn submit_exchange_transaction_proof( + &self, + params: SubstrateSigningParams, + proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + ) -> Result<()> { + let account_id = params.signer.public().as_array_ref().clone().into(); + let nonce = self.next_account_index(account_id).await?; + + let transaction = create_signed_transaction( + bridge_node_runtime::Call::BridgeCurrencyExchange( + bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof), + ), + ¶ms.signer, + nonce, + self.genesis_hash, + ); + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + Ok(()) + } +} + /// Create signed Substrate transaction for submitting Ethereum headers. fn create_signed_submit_transaction( headers: Vec, @@ -288,7 +336,7 @@ fn create_signed_submit_transaction( index: node_primitives::Index, genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { - let function = + create_signed_transaction( bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( headers .into_iter() @@ -299,8 +347,31 @@ fn create_signed_submit_transaction( ) }) .collect(), + )), + signer, + index, + genesis_hash, + ) +} + +/// Create unsigned Substrate transaction for submitting Ethereum header. +fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { + let function = + bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), )); + bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) +} + +/// Create signed Substrate transaction. +fn create_signed_transaction( + function: bridge_node_runtime::Call, + signer: &sp_core::sr25519::Pair, + index: node_primitives::Index, + genesis_hash: H256, +) -> bridge_node_runtime::UncheckedExtrinsic { let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( frame_system::CheckSpecVersion::::new(), @@ -331,14 +402,3 @@ fn create_signed_submit_transaction( bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account().into(), signature.into(), extra) } - -/// Create unsigned Substrate transaction for submitting Ethereum header. -fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { - let function = - bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(header.header()), - into_substrate_ethereum_receipts(header.extra()), - )); - - bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) -} From 0b6d8ed1ff8a8e48f57b3c7ea4615e330afae0c2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Jul 2020 13:07:34 +0300 Subject: [PATCH 0099/1210] Fixed best_ethereum_block() call parameters encoding (#188) * fixed best_ethereum_block() params encoding * updated versions --- bin/node/runtime/Cargo.toml | 3 ++- modules/currency-exchange/Cargo.toml | 2 +- modules/ethereum-contract/builtin/Cargo.toml | 2 +- modules/ethereum/Cargo.toml | 2 +- modules/substrate/Cargo.toml | 2 +- primitives/currency-exchange/Cargo.toml | 2 +- primitives/ethereum-poa/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/substrate_client.rs | 2 +- 9 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 99b4389ce17c4..7d6d6f009ce6c 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -12,7 +12,7 @@ hex-literal = "0.2" [dependencies.codec] package = "parity-scale-codec" -version = "1.0.0" +version = "1.3.1" default-features = false features = ["derive"] @@ -208,6 +208,7 @@ path = "../../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] version = "1.0.5" +tag = 'v2.0.0-rc4' package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index ac45876a6b2a1..23865b32bfff6 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] serde = { version = "1.0", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } sp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } # Substrate Based Dependencies diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 5867e1176c9f9..cfee003f19176 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # General dependencies -codec = { package = "parity-scale-codec", version = "1.0.0" } +codec = { package = "parity-scale-codec", version = "1.3.1" } ethereum-types = "0.9.2" finality-grandpa = "0.12.3" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index c22adb8490676..8beafb6448381 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] serde = { version = "1.0", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } hex-literal = "0.2" primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", default-features = false } diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index fefacdd458d0e..ec5ec2a0e84b2 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } serde = { version = "1.0", optional = true } hash-db = { version = "0.15.2", default-features = false } diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 432a1ae9e82a8..4cdba7ec1398f 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } # Substrate Based Dependencies diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 945752bc348aa..bf1d835197fe6 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -15,7 +15,7 @@ primitive-types = { version = "0.7", default-features = false, features = ["code fixed-hash = { version = "0.5", default-features = false } impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } rlp = { version = "0.4", default-features = false } hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 35f88282b0967..23c37156e58bc 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -12,7 +12,7 @@ async-stream = "0.2.0" async-trait = "0.1.36" backoff = "0.1" clap = { version = "2.33.1", features = ["yaml"] } -codec = { package = "parity-scale-codec", version = "1.0.0" } +codec = { package = "parity-scale-codec", version = "1.3.1" } env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 82e1081b85240..e349213dfc74c 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -134,7 +134,7 @@ impl SubstrateRpc for SubstrateRpcClient { async fn best_ethereum_block(&self) -> Result { let call = ETH_API_BEST_BLOCK.to_string(); - let data = Bytes("0x".into()); + let data = Bytes(Vec::new()); let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; From fda64c803950438b3c2954e44500fb7cc48906a8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 16 Jul 2020 12:58:46 +0300 Subject: [PATCH 0100/1210] Exchange pallet benchmarks (#158) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * exchange benchmarks: framework * updated comment about tx size Co-authored-by: Tomasz Drwięga --- bin/node/runtime/Cargo.toml | 15 +- bin/node/runtime/src/exchange.rs | 82 +++++++---- bin/node/runtime/src/lib.rs | 45 +++++- modules/currency-exchange/src/benchmarking.rs | 134 ++++++++++++++++++ modules/currency-exchange/src/lib.rs | 9 +- modules/ethereum/src/benchmarking.rs | 1 - modules/ethereum/src/lib.rs | 4 +- modules/ethereum/src/test_utils.rs | 29 +++- primitives/ethereum-poa/Cargo.toml | 1 + primitives/ethereum-poa/src/lib.rs | 6 +- 10 files changed, 281 insertions(+), 45 deletions(-) create mode 100644 modules/currency-exchange/src/benchmarking.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 7d6d6f009ce6c..fbb9099d5ab97 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -16,6 +16,12 @@ version = "1.3.1" default-features = false features = ["derive"] +[dependencies.libsecp256k1] +optional = true +version = "0.3.4" +default-features = false +features = ["hmac"] + [dependencies.serde] version = "1.0.114" optional = true @@ -200,10 +206,15 @@ tag = 'v2.0.0-rc4' default-features = false git = "https://github.com/paritytech/substrate/" +[dev-dependencies.libsecp256k1] +version = "0.3.4" +default-features = false +features = ["hmac"] + [dev-dependencies.sp-bridge-eth-poa] version = "0.1.0" default-features = false -features = ["test-helpers"] +features = ["std", "test-helpers"] path = "../../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] @@ -250,7 +261,9 @@ runtime-benchmarks = [ "frame-benchmarking", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "libsecp256k1", "pallet-bridge-currency-exchange/runtime-benchmarks", "pallet-bridge-eth-poa/runtime-benchmarks", + "sp-bridge-eth-poa/test-helpers", "sp-runtime/runtime-benchmarks", ] diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index 8a627e8a2c868..3e9ab8a609dc7 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -145,6 +145,57 @@ impl MaybeLockFundsTransaction for EthTransaction { } } +/// Prepares everything required to bench claim of funds locked by given transaction. +#[cfg(feature = "runtime-benchmarks")] +pub(crate) fn prepare_environment_for_claim( + transactions: &[RawTransaction], +) -> sp_bridge_eth_poa::H256 { + use pallet_bridge_eth_poa::{ + test_utils::{insert_header, validator_utils::validator, HeaderBuilder}, + BridgeStorage, Storage, + }; + use sp_bridge_eth_poa::compute_merkle_root; + + let mut storage = BridgeStorage::::new(); + let header = HeaderBuilder::with_parent_number_on_runtime::(0) + .with_transactions_root(compute_merkle_root(transactions.iter())) + .sign_by(&validator(0)); + let header_id = header.compute_id(); + insert_header(&mut storage, header); + storage.finalize_and_prune_headers(Some(header_id), 0); + + header_id.hash +} + +/// Prepare signed ethereum lock-funds transaction. +#[cfg(any(feature = "runtime-benchmarks", test))] +pub(crate) fn prepare_ethereum_transaction( + recipient: &crate::AccountId, + editor: impl Fn(&mut sp_bridge_eth_poa::UnsignedTransaction), +) -> Vec { + use sp_bridge_eth_poa::signatures::SignTransaction; + + // prepare tx for OpenEthereum private dev chain: + // chain id is 0x11 + // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 + let chain_id = 0x11; + let signer = secp256k1::SecretKey::parse(&hex!( + "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" + )) + .unwrap(); + let recipient_raw: &[u8; 32] = recipient.as_ref(); + let mut eth_tx = sp_bridge_eth_poa::UnsignedTransaction { + nonce: 0.into(), + to: Some(LOCK_FUNDS_ADDRESS.into()), + value: 100.into(), + gas: 100_000.into(), + gas_price: 100_000.into(), + payload: recipient_raw.to_vec(), + }; + editor(&mut eth_tx); + eth_tx.sign_by(&signer.into(), Some(chain_id)) +} + #[cfg(test)] mod tests { use super::*; @@ -158,33 +209,10 @@ mod tests { hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into() } - fn prepare_ethereum_transaction(editor: impl Fn(&mut UnsignedTransaction)) -> Vec { - // prepare tx for OpenEthereum private dev chain: - // chain id is 0x11 - // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 - let chain_id = 0x11_u64; - let signer = SecretKey::parse(&hex!( - "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" - )) - .unwrap(); - let ferdie_id = ferdie(); - let ferdie_raw: &[u8; 32] = ferdie_id.as_ref(); - let mut eth_tx = UnsignedTransaction { - nonce: 0.into(), - to: Some(LOCK_FUNDS_ADDRESS.into()), - value: 100.into(), - gas: 100_000.into(), - gas_price: 100_000.into(), - payload: ferdie_raw.to_vec(), - }; - editor(&mut eth_tx); - eth_tx.sign_by(&signer, Some(chain_id)) - } - #[test] fn valid_transaction_accepted() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(|_| {})), + EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |_| {})), Ok(LockFundsTransaction { id: EthereumTransactionTag { account: hex!("00a329c0648769a73afac7f9381e08fb43dbea72"), @@ -207,7 +235,7 @@ mod tests { #[test] fn transaction_with_invalid_peer_recipient_rejected() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(|tx| { + EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |tx| { tx.to = None; })), Err(ExchangeError::InvalidTransaction), @@ -217,7 +245,7 @@ mod tests { #[test] fn transaction_with_invalid_recipient_rejected() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(|tx| { + EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |tx| { tx.payload.clear(); })), Err(ExchangeError::InvalidRecipient), @@ -227,7 +255,7 @@ mod tests { #[test] fn transaction_with_invalid_amount_rejected() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(|tx| { + EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |tx| { tx.value = sp_core::U256::from(u128::max_value()) + sp_core::U256::from(1); })), Err(ExchangeError::InvalidAmount), diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 8ed1e5fbef40f..6d2c5eb7869ef 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -641,9 +641,52 @@ impl_runtime_apis! { ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark}; let mut batches = Vec::::new(); - let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat); + + let whitelist: Vec> = vec![]; + let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist); + + use pallet_bridge_currency_exchange::benchmarking::{ + Module as BridgeCurrencyExchangeBench, + Trait as BridgeCurrencyExchangeTrait, + ProofParams as BridgeCurrencyExchangeProofParams, + }; + + impl BridgeCurrencyExchangeTrait for Runtime { + fn make_proof( + proof_params: BridgeCurrencyExchangeProofParams, + ) -> crate::exchange::EthereumTransactionInclusionProof { + use sp_currency_exchange::DepositInto; + + if proof_params.recipient_exists { + ::DepositInto::deposit_into( + proof_params.recipient.clone(), + ExistentialDeposit::get(), + ).unwrap(); + } + + let transaction = crate::exchange::prepare_ethereum_transaction( + &proof_params.recipient, + |tx| { + // our runtime only supports transactions where data is exactly 32 bytes long + // (receiver key) + // => we are ignoring `transaction_size_factor` here + tx.value = (ExistentialDeposit::get() * 10).into(); + }, + ); + let transactions = sp_std::iter::repeat(transaction.clone()) + .take(1 + proof_params.proof_size_factor as usize) + .collect::>(); + let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); + crate::exchange::EthereumTransactionInclusionProof { + block: block_hash, + index: 0, + proof: transactions, + } + } + } add_benchmark!(params, batches, b"bridge-eth-poa", BridgeEthPoA); + add_benchmark!(params, batches, b"bridge-currency-exchange", BridgeCurrencyExchangeBench::); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs new file mode 100644 index 0000000000000..dc032720ce3c0 --- /dev/null +++ b/modules/currency-exchange/src/benchmarking.rs @@ -0,0 +1,134 @@ +// Copyright 2019-2020 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 . + +//! Exchange module complexity is mostly determined by callbacks, defined by runtime. +//! So we are giving runtime opportunity to prepare environment and construct proof +//! before invoking module calls. + +use super::{Blockchain, Call, Module as CurrencyExchangeModule, Trait as CurrencyExchangeTrait}; +use sp_std::prelude::*; + +use frame_benchmarking::{account, benchmarks}; +use frame_system::RawOrigin; + +const SEED: u32 = 0; +const WORST_TX_SIZE_FACTOR: u32 = 1000; +const WORST_PROOF_SIZE_FACTOR: u32 = 1000; + +/// Module we're benchmarking here. +pub struct Module(CurrencyExchangeModule); + +/// Proof benchmarking parameters. +pub struct ProofParams { + /// Funds recipient. + pub recipient: Recipient, + /// When true, recipient must exists before import. + pub recipient_exists: bool, + /// When 0, transaction should have minimal possible size. When this value has non-zero value n, + /// transaction size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. + pub transaction_size_factor: u32, + /// When 0, proof should have minimal possible size. When this value has non-zero value n, + /// proof size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. + pub proof_size_factor: u32, +} + +/// Trait that must be implemented by runtime. +pub trait Trait: CurrencyExchangeTrait { + /// Prepare proof for importing exchange transaction. + fn make_proof( + proof_params: ProofParams, + ) -> <::PeerBlockchain as Blockchain>::TransactionInclusionProof; +} + +benchmarks! { + _ { } + + // Benchmark `import_peer_transaction` extrinsic with the best possible conditions: + // * Proof is the transaction itself. + // * Transaction has minimal size. + // * Recipient account exists. + import_peer_transaction_best_case { + let i in 1..100; + + let recipient: T::AccountId = account("recipient", i, SEED); + let proof = T::make_proof(ProofParams { + recipient: recipient.clone(), + recipient_exists: true, + transaction_size_factor: 0, + proof_size_factor: 0, + }); + }: import_peer_transaction(RawOrigin::Signed(recipient), proof) + + // Benchmark `import_peer_transaction` extrinsic when recipient account does not exists. + import_peer_transaction_when_recipient_does_not_exists { + let i in 1..100; + + let recipient: T::AccountId = account("recipient", i, SEED); + let proof = T::make_proof(ProofParams { + recipient: recipient.clone(), + recipient_exists: false, + transaction_size_factor: 0, + proof_size_factor: 0, + }); + }: import_peer_transaction(RawOrigin::Signed(recipient), proof) + + // Benchmark `import_peer_transaction` when transaction size increases. + import_peer_transaction_when_transaction_size_increases { + let i in 1..100; + let n in 1..WORST_TX_SIZE_FACTOR; + + let recipient: T::AccountId = account("recipient", i, SEED); + let proof = T::make_proof(ProofParams { + recipient: recipient.clone(), + recipient_exists: true, + transaction_size_factor: n, + proof_size_factor: 0, + }); + }: import_peer_transaction(RawOrigin::Signed(recipient), proof) + + // Benchmark `import_peer_transaction` when proof size increases. + import_peer_transaction_when_proof_size_increases { + let i in 1..100; + let n in 1..WORST_PROOF_SIZE_FACTOR; + + let recipient: T::AccountId = account("recipient", i, SEED); + let proof = T::make_proof(ProofParams { + recipient: recipient.clone(), + recipient_exists: true, + transaction_size_factor: 0, + proof_size_factor: n, + }); + }: import_peer_transaction(RawOrigin::Signed(recipient), proof) + + // Benchmark `import_peer_transaction` extrinsic with the worst possible conditions: + // * Proof is large. + // * Transaction has large size. + // * Recipient account does not exists. + import_peer_transaction_worst_case { + let i in 1..100; + let m in WORST_TX_SIZE_FACTOR..WORST_TX_SIZE_FACTOR+1; + let n in WORST_PROOF_SIZE_FACTOR..WORST_PROOF_SIZE_FACTOR+1; + + let recipient: T::AccountId = account("recipient", i, SEED); + let proof = T::make_proof(ProofParams { + recipient: recipient.clone(), + recipient_exists: false, + transaction_size_factor: m, + proof_size_factor: n, + }); + }: import_peer_transaction(RawOrigin::Signed(recipient), proof) + +} diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 959538b7465f7..c6ca356e00ffb 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -24,6 +24,9 @@ use sp_currency_exchange::{ }; use sp_runtime::DispatchResult; +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + /// Called when transaction is submitted to the exchange module. pub trait OnTransactionSubmitted { /// Called when valid transaction is submitted and accepted by the module. @@ -229,7 +232,7 @@ mod tests { fn parse(tx: &Self::Transaction) -> sp_currency_exchange::Result { match tx.id { - INVALID_TRANSACTION_ID => Err(sp_currency_exchange::Error::InvalidTransaction), + INVALID_TRANSACTION_ID => Err(ExchangeError::InvalidTransaction), _ => Ok(tx.clone()), } } @@ -243,7 +246,7 @@ mod tests { fn map(peer_recipient: Self::PeerRecipient) -> sp_currency_exchange::Result { match peer_recipient { - UNKNOWN_RECIPIENT_ID => Err(sp_currency_exchange::Error::FailedToMapRecipients), + UNKNOWN_RECIPIENT_ID => Err(ExchangeError::FailedToMapRecipients), _ => Ok(peer_recipient * 10), } } @@ -257,7 +260,7 @@ mod tests { fn convert(amount: Self::SourceAmount) -> sp_currency_exchange::Result { match amount { - INVALID_AMOUNT => Err(sp_currency_exchange::Error::FailedToConvertCurrency), + INVALID_AMOUNT => Err(ExchangeError::FailedToConvertCurrency), _ => Ok(amount * 10), } } diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index d31d410391220..1f0a7fbe96f20 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -48,7 +48,6 @@ benchmarks! { header }, ); - }: import_unsigned_header(RawOrigin::None, header, None) verify { let storage = BridgeStorage::::new(); diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index db54613b8e768..b77f436301d67 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -44,7 +44,7 @@ mod benchmarking; mod mock; #[cfg(any(feature = "runtime-benchmarks", test))] -mod test_utils; +pub mod test_utils; /// Maximal number of blocks we're pruning in single import call. const MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT: u64 = 8; @@ -547,7 +547,7 @@ impl frame_support::unsigned::ValidateUnsigned for Module { /// Runtime bridge storage. #[derive(Default)] -struct BridgeStorage(sp_std::marker::PhantomData); +pub struct BridgeStorage(sp_std::marker::PhantomData); impl BridgeStorage { /// Create new BridgeStorage. diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index a4c51e4ac6866..9084783d6802d 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -27,7 +27,7 @@ use crate::finality::FinalityVotes; use crate::validators::CHANGE_EVENT_HASH; use crate::verification::calculate_score; -use crate::{HeaderToImport, Storage}; +use crate::{HeaderToImport, Storage, Trait}; use primitives::{ rlp_encode, @@ -60,25 +60,34 @@ impl HeaderBuilder { } } - /// Creates default header on top of parent with given hash. + /// Creates default header on top of test parent with given hash. #[cfg(test)] pub fn with_parent_hash(parent_hash: H256) -> Self { - use crate::mock::TestRuntime; + Self::with_parent_hash_on_runtime::(parent_hash) + } + + /// Creates default header on top of test parent with given number. First parent is selected. + #[cfg(test)] + pub fn with_parent_number(parent_number: u64) -> Self { + Self::with_parent_number_on_runtime::(parent_number) + } + + /// Creates default header on top of parent with given hash. + pub fn with_parent_hash_on_runtime(parent_hash: H256) -> Self { use crate::Headers; use frame_support::StorageMap; - let parent_header = Headers::::get(&parent_hash).unwrap().header; + let parent_header = Headers::::get(&parent_hash).unwrap().header; Self::with_parent(&parent_header) } /// Creates default header on top of parent with given number. First parent is selected. - #[cfg(test)] - pub fn with_parent_number(parent_number: u64) -> Self { + pub fn with_parent_number_on_runtime(parent_number: u64) -> Self { use crate::HeadersByNumber; use frame_support::StorageMap; let parent_hash = HeadersByNumber::get(parent_number).unwrap()[0].clone(); - Self::with_parent_hash(parent_hash) + Self::with_parent_hash_on_runtime::(parent_hash) } /// Creates default header on top of non-existent parent. @@ -185,6 +194,12 @@ impl HeaderBuilder { self } + /// Update transactions root field of this header. + pub fn with_transactions_root(mut self, transactions_root: H256) -> Self { + self.header.transactions_root = transactions_root; + self + } + /// Signs header by given author. pub fn sign_by(self, author: &SecretKey) -> Header { self.header.sign_by(author) diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index bf1d835197fe6..232bdf21bf64e 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -54,6 +54,7 @@ features = ["hmac"] [dev-dependencies] hex-literal = "0.2" +libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } [features] default = ["std"] diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index c0cf4da9d599a..fa47912f39f0b 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -117,9 +117,9 @@ pub struct UnsignedTransaction { pub gas: U256, /// Transaction destination address. None if it is contract creation transaction. pub to: Option

, - /// Transaction value. + /// Value. pub value: U256, - /// Transaction payload. + /// Associated data. pub payload: Bytes, } @@ -432,7 +432,7 @@ impl std::fmt::Debug for Bloom { } /// Decode Ethereum transaction. -pub fn transaction_decode(raw_tx: &[u8]) -> Result { +pub fn transaction_decode(raw_tx: &[u8]) -> Result { // parse transaction fields let unsigned = UnsignedTransaction::decode(raw_tx)?; let tx_rlp = Rlp::new(raw_tx); From cb9c060822cc5cf953765998c79d633fd82a7837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 17 Jul 2020 16:39:32 +0200 Subject: [PATCH 0101/1210] Rialto test network setup (#163) * Dockerfile for OpenEth. * Add relayer dockerfile. * Add docker-compose. * Working on the relay. * Bump a bunch of deps. * Change relay branch. * Running a 3-validators poa network. * Add bridge nodes. * Conditional compilation of bridge configs. * Fix genesis hash. * Disable features build. * Disable empty steps. * Work on sub2eth * Add some logs. * More logs. * Fix compilation. * Add chain-id parameter to relay. * Unify bridge-hash. * Update the hash. * Ditch sub2eth for now. * Add some docs & proxy configuration. * Fixes. * Fix remaining issues. * Increase health timeout. * Make sure to install curl for health monitoring. * Fix kovan. * Fix build. * Create if does not exist. * Fix benches. * Revert CLI params requirements. * cargo fmt --all * Apply suggestions from code review Co-authored-by: Hernando Castano * Add some docs. * Update BRIDGE_HASH to master * Duplicate compose file. * Rename testpoa to Rialto. * Fix borked merge. * Fix entrypoints to take arguments. Co-authored-by: Hernando Castano --- README.md | 38 +++++- bin/node/node/Cargo.toml | 11 +- bin/node/node/src/chain_spec.rs | 8 +- bin/node/runtime/Cargo.toml | 5 +- bin/node/runtime/src/benches.rs | 37 ++++++ bin/node/runtime/src/kovan.rs | 28 +++-- bin/node/runtime/src/lib.rs | 63 +++++----- bin/node/runtime/src/rialto.rs | 141 ++++++++++++++++++++++ relays/ethereum/src/cli.yml | 5 + relays/ethereum/src/ethereum_sync_loop.rs | 2 +- relays/ethereum/src/main.rs | 14 +++ 11 files changed, 300 insertions(+), 52 deletions(-) create mode 100644 bin/node/runtime/src/benches.rs create mode 100644 bin/node/runtime/src/rialto.rs diff --git a/README.md b/README.md index 7204e2f0fe895..8d1d313b15302 100644 --- a/README.md +++ b/README.md @@ -157,4 +157,40 @@ The folder structure of the bridge relay is as follows: ``` ## Running the Bridge -👷 Under Construction 👷‍♀️ + +To run the Bridge you need to be able to connect to the RPC interface of nodes on each side of the +bridge (home & foreign chain). + +You can build the relayer using [./Dockerfile](Dockerfile), which will use all the local source +files, +or you can use an image that is designed to build from Github repo sources (`master` branch by +default, configurable via `build-arg`): +```bash +docker build \ + https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ + -t poa-relay +docker run -it poa-relay +``` + +By default the relayer is configured to connect to OpenEthereum `--dev` chain node and Substrate +`bridge-node` running in a `--dev` mode. +To build the `bridge-node`: +```bash +docker build \ + https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ + -t bridge-node \ + --build-arg PROJECT=bridge-node +docker run -it bridge-node +``` + +And to build `OpenEthereum` with bridge support: +``` +docker build \ + https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/OpenEthereum.Dockerfile + -t openethereum +docker run it openethereum +``` + +See [./deployments/README.md](Deployments README) to learn more about how to run +a more sophisticated test network using `docker-compose` setup. + diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index c0a2f936cd17d..c2d7dbd3cb79a 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -16,9 +16,14 @@ futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.8" structopt = "0.3.15" -bridge-node-runtime = { version = "0.1.0", path = "../runtime" } sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } +[dependencies.bridge-node-runtime] +version = "0.1.0" +path = "../runtime" +default-features = false +features = ["std"] + [dependencies.sc-cli] version = "0.8.0-rc4" tag = 'v2.0.0-rc4' @@ -141,7 +146,9 @@ tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [features] -default = [] +default = ["bridge-rialto"] +bridge-kovan = ["bridge-node-runtime/bridge-kovan"] +bridge-rialto = ["bridge-node-runtime/bridge-rialto"] runtime-benchmarks = [ "bridge-node-runtime/runtime-benchmarks", ] diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 7127ee8d77193..436e82eaed79c 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -153,7 +153,7 @@ fn testnet_genesis( pallet_aura: Some(AuraConfig { authorities: Vec::new(), }), - pallet_bridge_eth_poa: load_kovan_config(), + pallet_bridge_eth_poa: load_bridge_config(), pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), @@ -167,10 +167,10 @@ fn testnet_genesis( } } -fn load_kovan_config() -> Option { +fn load_bridge_config() -> Option { Some(BridgeEthPoAConfig { - initial_header: bridge_node_runtime::kovan::kovan_genesis_header(), + initial_header: bridge_node_runtime::bridge::genesis_header(), initial_difficulty: 0.into(), - initial_validators: bridge_node_runtime::kovan::kovan_genesis_validators(), + initial_validators: bridge_node_runtime::bridge::genesis_validators(), }) } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index fbb9099d5ab97..b5ec9139b9939 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -224,7 +224,9 @@ package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" [features] -default = ["std"] +default = ["std", "bridge-rialto"] +bridge-kovan = [] +bridge-rialto = [] std = [ "pallet-aura/std", "pallet-balances/std", @@ -266,4 +268,5 @@ runtime-benchmarks = [ "pallet-bridge-eth-poa/runtime-benchmarks", "sp-bridge-eth-poa/test-helpers", "sp-runtime/runtime-benchmarks", + "bridge-kovan", ] diff --git a/bin/node/runtime/src/benches.rs b/bin/node/runtime/src/benches.rs new file mode 100644 index 0000000000000..4ca476e5f3ca6 --- /dev/null +++ b/bin/node/runtime/src/benches.rs @@ -0,0 +1,37 @@ +// Copyright 2020 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 . + +//! We want to use a different validator configuration for benchmarking than what's used in Kovan +//! or in our Rialto test network. However, we can't configure a new validator set on the fly which +//! means we need to wire the runtime together like this + +use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource}; +use sp_std::vec; + +pub use crate::kovan::{ + genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, PruningStrategy, +}; + +frame_support::parameter_types! { + pub BridgeValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = bench_validator_config(); +} + +fn bench_validator_config() -> ValidatorsConfiguration { + ValidatorsConfiguration::Multi(vec![ + (0, ValidatorsSource::List(vec![[1; 20].into()])), + (1, ValidatorsSource::Contract([3; 20].into(), vec![[1; 20].into()])), + ]) +} diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index 09fb309c70e4c..44532e1d5816f 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -16,10 +16,20 @@ use frame_support::RuntimeDebug; use hex_literal::hex; -use pallet_bridge_eth_poa::{AuraConfiguration, PruningStrategy, ValidatorsConfiguration, ValidatorsSource}; +use pallet_bridge_eth_poa::{ + AuraConfiguration, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, ValidatorsSource, +}; use sp_bridge_eth_poa::{Address, Header, U256}; use sp_std::prelude::*; +frame_support::parameter_types! { + pub const FinalityVotesCachingInterval: Option = Some(16); + pub BridgeAuraConfiguration: AuraConfiguration = + kovan_aura_configuration(); + pub BridgeValidatorsConfiguration: ValidatorsConfiguration = + kovan_validators_configuration(); +} + /// Max number of finalized headers to keep. It is equivalent of ~24 hours of /// finalized blocks on current Kovan chain. const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000; @@ -41,7 +51,7 @@ pub fn kovan_aura_configuration() -> AuraConfiguration { /// Validators configuration for Kovan chain. pub fn kovan_validators_configuration() -> ValidatorsConfiguration { ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(kovan_genesis_validators())), + (0, ValidatorsSource::List(genesis_validators())), ( 10960440, ValidatorsSource::List(vec![ @@ -67,7 +77,7 @@ pub fn kovan_validators_configuration() -> ValidatorsConfiguration { } /// Genesis validators set of Kovan chain. -pub fn kovan_genesis_validators() -> Vec
{ +pub fn genesis_validators() -> Vec
{ vec![ hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(), hex!("00427feae2419c15b89d1c21af10d1b6650a4d3d").into(), @@ -82,7 +92,7 @@ pub fn kovan_genesis_validators() -> Vec
{ } /// Genesis header of the Kovan chain. -pub fn kovan_genesis_header() -> Header { +pub fn genesis_header() -> Header { Header { parent_hash: Default::default(), timestamp: 0, @@ -114,9 +124,9 @@ pub fn kovan_genesis_header() -> Header { /// claims from finalized headers. And if we're pruning unfinalized headers, then /// some claims may never be accepted. #[derive(Default, RuntimeDebug)] -pub struct KovanPruningStrategy; +pub struct PruningStrategy; -impl PruningStrategy for KovanPruningStrategy { +impl BridgePruningStrategy for PruningStrategy { fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { best_finalized_number .checked_sub(FINALIZED_HEADERS_TO_KEEP) @@ -131,19 +141,19 @@ mod tests { #[test] fn pruning_strategy_keeps_enough_headers() { assert_eq!( - KovanPruningStrategy::default().pruning_upper_bound(100_000, 10_000), + PruningStrategy::default().pruning_upper_bound(100_000, 10_000), 0, "10_000 <= 20_000 => nothing should be pruned yet", ); assert_eq!( - KovanPruningStrategy::default().pruning_upper_bound(100_000, 20_000), + PruningStrategy::default().pruning_upper_bound(100_000, 20_000), 0, "20_000 <= 20_000 => nothing should be pruned yet", ); assert_eq!( - KovanPruningStrategy::default().pruning_upper_bound(100_000, 30_000), + PruningStrategy::default().pruning_upper_bound(100_000, 30_000), 10_000, "20_000 <= 30_000 => we're ready to prune first 10_000 headers", ); diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 6d2c5eb7869ef..e61d924ba1281 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -25,7 +25,20 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod exchange; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benches; +#[cfg(feature = "bridge-kovan")] pub mod kovan; +#[cfg(feature = "bridge-rialto")] +pub mod rialto; + +#[cfg(feature = "runtime-benchmarks")] +pub use benches as bridge; +#[cfg(all(feature = "bridge-kovan", not(feature = "runtime-benchmarks")))] +pub use kovan as bridge; +#[cfg(all(feature = "bridge-rialto", not(feature = "runtime-benchmarks")))] +pub use rialto as bridge; use codec::{Decode, Encode}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; @@ -216,39 +229,11 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } -// We want to use a different validator configuration for benchmarking than what's used in Kovan, -// but we can't configure a new validator set on the fly which means we need to wire the runtime -// together like this -#[cfg(feature = "runtime-benchmarks")] -use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource}; - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub const FinalityVotesCachingInterval: Option = Some(16); - pub KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); - pub KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = bench_validator_config(); -} - -#[cfg(feature = "runtime-benchmarks")] -fn bench_validator_config() -> ValidatorsConfiguration { - ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(vec![[1; 20].into()])), - (1, ValidatorsSource::Contract([3; 20].into(), vec![[1; 20].into()])), - ]) -} - -#[cfg(not(feature = "runtime-benchmarks"))] -parameter_types! { - pub const FinalityVotesCachingInterval: Option = Some(16); - pub KovanAuraConfiguration: pallet_bridge_eth_poa::AuraConfiguration = kovan::kovan_aura_configuration(); - pub KovanValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = kovan::kovan_validators_configuration(); -} - impl pallet_bridge_eth_poa::Trait for Runtime { - type AuraConfiguration = KovanAuraConfiguration; - type FinalityVotesCachingInterval = FinalityVotesCachingInterval; - type ValidatorsConfiguration = KovanValidatorsConfiguration; - type PruningStrategy = kovan::KovanPruningStrategy; + type AuraConfiguration = bridge::BridgeAuraConfiguration; + type FinalityVotesCachingInterval = bridge::FinalityVotesCachingInterval; + type ValidatorsConfiguration = bridge::BridgeValidatorsConfiguration; + type PruningStrategy = bridge::PruningStrategy; type OnHeadersSubmitted = (); } @@ -641,8 +626,18 @@ impl_runtime_apis! { ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark}; let mut batches = Vec::::new(); - - let whitelist: Vec> = vec![]; + let whitelist: Vec> = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec(), + // Caller 0 Account + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec(), + ]; let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist); use pallet_bridge_currency_exchange::benchmarking::{ diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs new file mode 100644 index 0000000000000..fa272fe8af8b8 --- /dev/null +++ b/bin/node/runtime/src/rialto.rs @@ -0,0 +1,141 @@ +// Copyright 2020 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 . + +use frame_support::RuntimeDebug; +use hex_literal::hex; +use pallet_bridge_eth_poa::{ + AuraConfiguration, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, ValidatorsSource, +}; +use sp_bridge_eth_poa::{Address, Header, U256}; +use sp_std::prelude::*; + +frame_support::parameter_types! { + pub const FinalityVotesCachingInterval: Option = Some(8); + pub BridgeAuraConfiguration: AuraConfiguration = + aura_configuration(); + pub BridgeValidatorsConfiguration: ValidatorsConfiguration = + validators_configuration(); +} + +/// Max number of finalized headers to keep. +const FINALIZED_HEADERS_TO_KEEP: u64 = 5_000; + +/// Aura engine configuration for Rialto chain. +pub fn aura_configuration() -> AuraConfiguration { + AuraConfiguration { + empty_steps_transition: 0xfffffffff, + strict_empty_steps_transition: 0, + validate_step_transition: 0, + validate_score_transition: 0, + two_thirds_majority_transition: u64::max_value(), + min_gas_limit: 0x1388.into(), + max_gas_limit: U256::max_value(), + maximum_extra_data_size: 0x20, + } +} + +/// Validators configuration for Rialto chain. +pub fn validators_configuration() -> ValidatorsConfiguration { + ValidatorsConfiguration::Single(ValidatorsSource::List(genesis_validators())) +} + +/// Genesis validators set of Rialto chain. +pub fn genesis_validators() -> Vec
{ + vec![ + hex!("005e714f896a8b7cede9d38688c1a81de72a58e4").into(), + hex!("007594304039c2937a12220338aab821d819f5a4").into(), + hex!("004e7a39907f090e19b0b80a277e77b72b22e269").into(), + ] +} + +/// Genesis header of the Rialto chain. +/// +/// To obtain genesis header from a running node, invoke: +/// ```bash +/// $ http localhost:8545 jsonrpc=2.0 id=1 method=eth_getBlockByNumber params:='["earliest", false]' -v +/// ``` +pub fn genesis_header() -> Header { + Header { + parent_hash: Default::default(), + timestamp: 0, + number: 0, + author: Default::default(), + transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), + extra_data: vec![], + state_root: hex!("d6368925ffd9acad81f411ce45891d3722e14355af2790391839488e23d74b0d").into(), + receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + log_bloom: Default::default(), + gas_used: Default::default(), + gas_limit: 0x222222.into(), + difficulty: 0x20000.into(), + seal: vec![vec![0x80].into(), { + let mut vec = vec![0xb8, 0x41]; + vec.resize(67, 0); + vec.into() + }], + } +} + +/// Rialto headers pruning strategy. +/// +/// We do not prune unfinalized headers because exchange module only accepts +/// claims from finalized headers. And if we're pruning unfinalized headers, then +/// some claims may never be accepted. +#[derive(Default, RuntimeDebug)] +pub struct PruningStrategy; + +impl TPruningStrategy for PruningStrategy { + fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { + best_finalized_number + .checked_sub(FINALIZED_HEADERS_TO_KEEP) + .unwrap_or(0) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn genesis_hash_matches() { + assert_eq!( + genesis_header().compute_hash(), + hex!("bc936e808b668546250ad43de5c0a95fe2a9644a850a2ff69b57f874e3e35644").into(), + ); + } + + #[test] + fn pruning_strategy_keeps_enough_headers() { + assert_eq!( + PruningStrategy::default().pruning_upper_bound(100_000, 1_000), + 0, + "1_000 <= 5_000 => nothing should be pruned yet", + ); + + assert_eq!( + PruningStrategy::default().pruning_upper_bound(100_000, 5_000), + 0, + "5_000 <= 5_000 => nothing should be pruned yet", + ); + + assert_eq!( + PruningStrategy::default().pruning_upper_bound(100_000, 10_000), + 5_000, + "5_000 <= 10_000 => we're ready to prune first 5_000 headers", + ); + } +} diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 7425584c485ba..1731f2ef83d83 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -53,6 +53,10 @@ subcommands: value_name: ETH_CONTRACT help: Address of deployed bridge contract. takes_value: true + - eth-chain-id: ð-chain-id + long: eth-chain-id + value_name: ETH_CHAIN_ID + help: Chain ID to use for signing. - eth-signer: ð-signer long: eth-signer value_name: ETH_SIGNER @@ -65,6 +69,7 @@ subcommands: - eth-host: *eth-host - eth-port: *eth-port - eth-signer: *eth-signer + - eth-chain-id: *eth-chain-id - eth-contract-code: long: eth-contract-code value_name: ETH_CONTRACT_CODE diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index a270386ccb887..8980e7539e40f 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -51,7 +51,7 @@ const MAX_SUBMITTED_HEADERS: usize = 128; const PRUNE_DEPTH: u32 = 4096; /// Ethereum synchronization parameters. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct EthereumSyncParams { /// Ethereum connection params. pub eth: EthereumConnectionParams, diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 2c6a5457512ef..5424f941b27f2 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -49,6 +49,7 @@ fn main() { let matches = clap::App::from_yaml(yaml).get_matches(); match matches.subcommand() { ("eth-to-sub", Some(eth_to_sub_matches)) => { + log::info!(target: "bridge", "Starting ETH ➡ SUB relay."); if ethereum_sync_loop::run(match ethereum_sync_params(ð_to_sub_matches) { Ok(ethereum_sync_params) => ethereum_sync_params, Err(err) => { @@ -63,6 +64,7 @@ fn main() { }; } ("sub-to-eth", Some(sub_to_eth_matches)) => { + log::info!(target: "bridge", "Starting SUB ➡ ETH relay."); if substrate_sync_loop::run(match substrate_sync_params(&sub_to_eth_matches) { Ok(substrate_sync_params) => substrate_sync_params, Err(err) => { @@ -77,6 +79,7 @@ fn main() { }; } ("eth-deploy-contract", Some(eth_deploy_matches)) => { + log::info!(target: "bridge", "Deploying ETH contracts."); ethereum_deploy_contract::run(match ethereum_deploy_contract_params(ð_deploy_matches) { Ok(ethereum_deploy_matches) => ethereum_deploy_matches, Err(err) => { @@ -160,6 +163,11 @@ fn ethereum_signing_params(matches: &clap::ArgMatches) -> Result() + .map_err(|e| format!("Failed to parse eth-chain-id: {}", e))?; + } Ok(params) } @@ -205,6 +213,8 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, } + log::debug!(target: "bridge", "Ethereum sync params: {:?}", eth_sync_params); + Ok(eth_sync_params) } @@ -218,6 +228,8 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result Date: Fri, 17 Jul 2020 21:48:59 +0300 Subject: [PATCH 0102/1210] Relay dashboard (#191) * expose metrics for Prometheus * added preconfigured configs for Prometheus and Grafana * metrics-related cli args * fix compilation --- relays/ethereum/Cargo.toml | 6 + .../ethereum/dashboard/grafana-dashboard.json | 410 ++++++++++++++++++ .../ethereum/dashboard/grafana-dashboard.yaml | 6 + .../dashboard/grafana-datasource.yaml | 9 + relays/ethereum/dashboard/prometheus.yml | 9 + relays/ethereum/src/cli.yml | 14 + relays/ethereum/src/ethereum_sync_loop.rs | 5 + relays/ethereum/src/main.rs | 23 + relays/ethereum/src/metrics.rs | 119 +++++ relays/ethereum/src/substrate_sync_loop.rs | 5 + relays/ethereum/src/sync.rs | 10 + relays/ethereum/src/sync_loop.rs | 35 ++ relays/ethereum/src/sync_loop_metrics.rs | 90 ++++ relays/ethereum/src/sync_loop_tests.rs | 1 + relays/ethereum/src/sync_types.rs | 3 +- 15 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 relays/ethereum/dashboard/grafana-dashboard.json create mode 100644 relays/ethereum/dashboard/grafana-dashboard.yaml create mode 100644 relays/ethereum/dashboard/grafana-datasource.yaml create mode 100644 relays/ethereum/dashboard/prometheus.yml create mode 100644 relays/ethereum/src/metrics.rs create mode 100644 relays/ethereum/src/sync_loop_metrics.rs diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 23c37156e58bc..4a7af04c443bb 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -28,6 +28,7 @@ parking_lot = "0.11.0" rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.56" +sysinfo = "0.13" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = "0.13" @@ -69,6 +70,11 @@ version = "2.0.0-rc4" tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" +[dependencies.substrate-prometheus-endpoint] +version = "0.8.0-rc4" +tag = 'v2.0.0-rc4' +git = "https://github.com/paritytech/substrate.git" + [dependencies.bridge-node-runtime] version = "0.1.0" path = "../../bin/node/runtime" diff --git a/relays/ethereum/dashboard/grafana-dashboard.json b/relays/ethereum/dashboard/grafana-dashboard.json new file mode 100644 index 0000000000000..f15fa60ba22a7 --- /dev/null +++ b/relays/ethereum/dashboard/grafana-dashboard.json @@ -0,0 +1,410 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": { + "align": null + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 2, + "interval": "5s", + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "expr": "best_block_numbers", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Best known block on {{node}} node", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Best blocks relay knows of", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "system_average_load", + "interval": "", + "legendFormat": "Average system load in last {{over}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "System load average", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 0 + }, + "id": 12, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "expr": "process_cpu_usage_percentage", + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Relay process CPU usage (1 CPU = 100)", + "type": "gauge" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 4, + "options": { + "displayMode": "gradient", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showUnfilled": true + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "expr": "blocks_in_state", + "instant": true, + "interval": "", + "legendFormat": "{{state}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Blocks in state on relay", + "type": "bargauge" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "process_memory_usage_bytes / 1024 / 1024", + "interval": "", + "legendFormat": "Process memory, MB", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory used by relay process", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5s", + "schemaVersion": 25, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "RelayDashboard", + "uid": "oj3y7vnGz", + "version": 1 +} \ No newline at end of file diff --git a/relays/ethereum/dashboard/grafana-dashboard.yaml b/relays/ethereum/dashboard/grafana-dashboard.yaml new file mode 100644 index 0000000000000..f66dff441311b --- /dev/null +++ b/relays/ethereum/dashboard/grafana-dashboard.yaml @@ -0,0 +1,6 @@ +- name: 'default' + orgId: 1 + folder: '' + type: file + options: + path: '/etc/grafana/provisioning/dashboards/grafana-dashboard.json' \ No newline at end of file diff --git a/relays/ethereum/dashboard/grafana-datasource.yaml b/relays/ethereum/dashboard/grafana-datasource.yaml new file mode 100644 index 0000000000000..ed77109fdb8e6 --- /dev/null +++ b/relays/ethereum/dashboard/grafana-datasource.yaml @@ -0,0 +1,9 @@ +datasources: + - name: Prometheus + type: prometheus + access: proxy + orgId: 1 + url: http://localhost:9090 + editable: false + is_default: true + version: 1 \ No newline at end of file diff --git a/relays/ethereum/dashboard/prometheus.yml b/relays/ethereum/dashboard/prometheus.yml new file mode 100644 index 0000000000000..572b62d1ac553 --- /dev/null +++ b/relays/ethereum/dashboard/prometheus.yml @@ -0,0 +1,9 @@ +scrape_configs: + # The job name is added as a label `job=` to any timeseries scraped from this config. + - job_name: 'relay_node' + + # Override the global default and scrape targets from this job every 5 seconds. + scrape_interval: 5s + + static_configs: + - targets: ['127.0.0.1:9616'] diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 1731f2ef83d83..988af146a7c53 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -43,6 +43,17 @@ subcommands: long: sub-signer-password value_name: SUB_SIGNER_PASSWORD help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. + - no-prometheus: &no-prometheus + long: no-prometheus + help: Do not expose a Prometheus metric endpoint. + - prometheus-host: &prometheus-host + long: prometheus-host + value_name: PROMETHEUS_HOST + help: Expose Prometheus endpoint at given interface. + - prometheus-port: &prometheus-port + long: prometheus-port + value_name: PROMETHEUS_PORT + help: Expose Prometheus endpoint at given port. - sub-to-eth: about: Synchronize headers from Substrate node to Ethereum node. args: @@ -63,6 +74,9 @@ subcommands: help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. - sub-host: *sub-host - sub-port: *sub-port + - no-prometheus: *no-prometheus + - prometheus-host: *prometheus-host + - prometheus-port: *prometheus-port - eth-deploy-contract: about: Deploy Bridge contract on Ethereum node. args: diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 8980e7539e40f..162f93c63143c 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -18,6 +18,7 @@ use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient}; use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; +use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_client::{ @@ -61,6 +62,8 @@ pub struct EthereumSyncParams { pub sub_sign: SubstrateSigningParams, /// Synchronization parameters. pub sync_params: HeadersSyncParams, + /// Metrics parameters. + pub metrics_params: Option, } impl Default for EthereumSyncParams { @@ -77,6 +80,7 @@ impl Default for EthereumSyncParams { prune_depth: PRUNE_DEPTH, target_tx_mode: TargetTransactionMode::Signed, }, + metrics_params: Some(Default::default()), } } } @@ -204,6 +208,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { target, SUBSTRATE_TICK_INTERVAL, params.sync_params, + params.metrics_params, futures::future::pending(), ); diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 5424f941b27f2..a574e64775809 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -23,6 +23,7 @@ mod ethereum_sync_loop; mod ethereum_types; mod exchange; mod headers; +mod metrics; mod rpc; mod rpc_errors; mod substrate_client; @@ -30,6 +31,7 @@ mod substrate_sync_loop; mod substrate_types; mod sync; mod sync_loop; +mod sync_loop_metrics; mod sync_loop_tests; mod sync_types; mod utils; @@ -199,6 +201,7 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, @@ -223,6 +226,7 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result Result Result, String> { + if matches.is_present("no-prometheus") { + return Ok(None); + } + + let mut metrics_params = metrics::MetricsParams::default(); + + if let Some(prometheus_host) = matches.value_of("prometheus-host") { + metrics_params.host = prometheus_host.into(); + } + if let Some(prometheus_port) = matches.value_of("prometheus-port") { + metrics_params.port = prometheus_port + .parse() + .map_err(|e| format!("Failed to parse prometheus-port: {}", e))?; + } + + Ok(Some(metrics_params)) +} diff --git a/relays/ethereum/src/metrics.rs b/relays/ethereum/src/metrics.rs new file mode 100644 index 0000000000000..95e84fc6473f8 --- /dev/null +++ b/relays/ethereum/src/metrics.rs @@ -0,0 +1,119 @@ +// Copyright 2019-2020 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 . + +pub use substrate_prometheus_endpoint::{register, Gauge, GaugeVec, Opts, Registry, F64, U64}; + +use std::net::SocketAddr; +use substrate_prometheus_endpoint::init_prometheus; +use sysinfo::{ProcessExt, System, SystemExt}; + +/// Prometheus endpoint MetricsParams. +#[derive(Debug, Clone)] +pub struct MetricsParams { + /// Serve HTTP requests at given host. + pub host: String, + /// Serve HTTP requests at given port. + pub port: u16, +} + +/// Global Prometheus metrics. +#[derive(Debug)] +pub struct GlobalMetrics { + system: System, + system_average_load: GaugeVec, + process_cpu_usage_percentage: Gauge, + process_memory_usage_bytes: Gauge, +} + +/// Start Prometheus endpoint with given metrics registry. +pub async fn start(params: MetricsParams, registry: Registry) -> Result<(), String> { + init_prometheus( + SocketAddr::new( + params + .host + .parse() + .map_err(|err| format!("Invalid Prometheus host {}: {}", params.host, err))?, + params.port, + ), + registry, + ) + .await + .map_err(|err| format!("Error starting Prometheus endpoint: {}", err)) +} + +impl Default for MetricsParams { + fn default() -> Self { + MetricsParams { + host: "127.0.0.1".into(), + port: 9616, + } + } +} + +impl GlobalMetrics { + /// Creates global metrics. + pub fn new() -> Self { + GlobalMetrics { + system: System::new(), + system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) + .expect("metric is static and thus valid; qed"), + process_cpu_usage_percentage: Gauge::new("process_cpu_usage_percentage", "Process CPU usage") + .expect("metric is static and thus valid; qed"), + process_memory_usage_bytes: Gauge::new( + "process_memory_usage_bytes", + "Process memory (resident set size) usage", + ) + .expect("metric is static and thus valid; qed"), + } + } + + /// Registers global metrics in the metrics registry. + pub fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.system_average_load.clone(), registry).map_err(|e| e.to_string())?; + register(self.process_cpu_usage_percentage.clone(), registry).map_err(|e| e.to_string())?; + register(self.process_memory_usage_bytes.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } + + /// Update metrics. + pub fn update(&mut self) { + // update system-wide metrics + let load = self.system.get_load_average(); + self.system_average_load.with_label_values(&["1min"]).set(load.one); + self.system_average_load.with_label_values(&["5min"]).set(load.five); + self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); + + // update process-related metrics + let pid = sysinfo::get_current_pid().expect( + "only fails where pid is unavailable (os=unknown || arch=wasm32);\ + relay is not supposed to run in such MetricsParamss;\ + qed", + ); + let is_process_refreshed = self.system.refresh_process(pid); + match (is_process_refreshed, self.system.get_process(pid)) { + (true, Some(process_info)) => { + self.process_cpu_usage_percentage.set(process_info.cpu_usage() as f64); + self.process_memory_usage_bytes.set(process_info.memory() * 1024); + } + _ => { + log::warn!( + target: "bridge", + "Failed to refresh process information. Metrics may show obsolete values", + ); + } + } + } +} diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 7e77c2392a5f8..1d81e2e6bf303 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -20,6 +20,7 @@ use crate::ethereum_client::{ EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, }; use crate::ethereum_types::Address; +use crate::metrics::MetricsParams; use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; @@ -58,6 +59,8 @@ pub struct SubstrateSyncParams { pub sub: SubstrateConnectionParams, /// Synchronization parameters. pub sync_params: HeadersSyncParams, + /// Metrics parameters. + pub metrics_params: Option, } impl Default for SubstrateSyncParams { @@ -81,6 +84,7 @@ impl Default for SubstrateSyncParams { prune_depth: PRUNE_DEPTH, target_tx_mode: TargetTransactionMode::Signed, }, + metrics_params: Some(Default::default()), } } } @@ -209,6 +213,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { target, ETHEREUM_TICK_INTERVAL, params.sync_params, + params.metrics_params, futures::future::pending(), ); diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 3e16f9630f372..481311f20f371 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -72,6 +72,16 @@ impl HeadersSync

{ } } + /// Return best header number known to source node. + pub fn source_best_number(&self) -> Option { + self.source_best_number + } + + /// Best header known to target node. + pub fn target_best_header(&self) -> Option> { + self.target_best_header + } + /// Returns true if we have synced almost all known headers. pub fn is_almost_synced(&self) -> bool { match self.source_best_number { diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 200c4a38f3f1f..9128374e9ff10 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams, Registry as MetricsRegistry}; use crate::sync::HeadersSyncParams; +use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{ HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SubmittedHeaders, }; @@ -124,6 +126,7 @@ pub fn run>( target_client: TC, target_tick: Duration, sync_params: HeadersSyncParams, + metrics_params: Option, exit_signal: impl Future, ) { let mut local_pool = futures::executor::LocalPool::new(); @@ -134,6 +137,19 @@ pub fn run>( let mut stall_countdown = None; let mut last_update_time = Instant::now(); + let mut metrics_global = GlobalMetrics::new(); + let mut metrics_sync = SyncLoopMetrics::new(); + let metrics_enabled = metrics_params.is_some(); + if let Some(metrics_params) = metrics_params { + if let Err(err) = expose_metrics(metrics_params, &metrics_global, &metrics_sync).await { + log::warn!( + target: "bridge", + "Failed to expose metrics: {}", + err, + ); + } + } + let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = false; let mut source_best_block_number_required = false; @@ -361,6 +377,12 @@ pub fn run>( } } + // update metrics + if metrics_enabled { + metrics_global.update(); + metrics_sync.update(&mut sync); + } + // print progress progress_context = print_sync_progress(progress_context, &sync); @@ -540,6 +562,19 @@ pub fn run>( }); } +/// Expose sync loop metrics. +async fn expose_metrics( + metrics_params: MetricsParams, + metrics_global: &GlobalMetrics, + metrics_sync: &SyncLoopMetrics, +) -> Result<(), String> { + let metrics_registry = MetricsRegistry::new(); + metrics_global.register(&metrics_registry)?; + metrics_sync.register(&metrics_registry)?; + async_std::task::spawn(metrics_start(metrics_params, metrics_registry)); + Ok(()) +} + /// Stream that emits item every `timeout_ms` milliseconds. fn interval(timeout: Duration) -> impl futures::Stream { futures::stream::unfold((), move |_| async move { diff --git a/relays/ethereum/src/sync_loop_metrics.rs b/relays/ethereum/src/sync_loop_metrics.rs new file mode 100644 index 0000000000000..657630ad408c6 --- /dev/null +++ b/relays/ethereum/src/sync_loop_metrics.rs @@ -0,0 +1,90 @@ +// Copyright 2019-2020 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 . + +use crate::metrics::{register, GaugeVec, Opts, Registry, U64}; +use crate::sync::HeadersSync; +use crate::sync_types::{HeaderStatus, HeadersSyncPipeline}; + +use num_traits::Zero; + +/// Headers sync metrics. +pub struct SyncLoopMetrics { + /// Best syncing headers at "source" and "target" nodes. + best_block_numbers: GaugeVec, + /// Number of headers in given states (see `HeaderStatus`). + blocks_in_state: GaugeVec, +} + +impl SyncLoopMetrics { + /// Creates sync loop metrics. + pub fn new() -> Self { + SyncLoopMetrics { + best_block_numbers: GaugeVec::new( + Opts::new("best_block_numbers", "Best block numbers on source and target nodes"), + &["node"], + ) + .expect("metric is static and thus valid; qed"), + blocks_in_state: GaugeVec::new( + Opts::new("blocks_in_state", "Number of blocks in given state"), + &["state"], + ) + .expect("metric is static and thus valid; qed"), + } + } + + /// Registers sync loop metrics in the metrics registry. + pub fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; + register(self.blocks_in_state.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } + + /// Update metrics. + pub fn update(&mut self, sync: &HeadersSync

) { + let headers = sync.headers(); + let source_best_number = sync.source_best_number().unwrap_or(Zero::zero()); + let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or(Zero::zero()); + + self.best_block_numbers + .with_label_values(&["source"]) + .set(source_best_number.into()); + self.best_block_numbers + .with_label_values(&["target"]) + .set(target_best_number.into()); + + self.blocks_in_state + .with_label_values(&["maybe_orphan"]) + .set(headers.headers_in_status(HeaderStatus::MaybeOrphan) as _); + self.blocks_in_state + .with_label_values(&["orphan"]) + .set(headers.headers_in_status(HeaderStatus::Orphan) as _); + self.blocks_in_state + .with_label_values(&["maybe_extra"]) + .set(headers.headers_in_status(HeaderStatus::MaybeExtra) as _); + self.blocks_in_state + .with_label_values(&["extra"]) + .set(headers.headers_in_status(HeaderStatus::Extra) as _); + self.blocks_in_state + .with_label_values(&["ready"]) + .set(headers.headers_in_status(HeaderStatus::Ready) as _); + self.blocks_in_state + .with_label_values(&["incomplete"]) + .set(headers.headers_in_status(HeaderStatus::Incomplete) as _); + self.blocks_in_state + .with_label_values(&["submitted"]) + .set(headers.headers_in_status(HeaderStatus::Submitted) as _); + } +} diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/ethereum/src/sync_loop_tests.rs index cf62c67f6e9ba..83fadce6199c7 100644 --- a/relays/ethereum/src/sync_loop_tests.rs +++ b/relays/ethereum/src/sync_loop_tests.rs @@ -481,6 +481,7 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { target, test_tick(), crate::sync::tests::default_sync_params(), + None, exit_receiver.into_future().map(|(_, _)| ()), ); } diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index c300d25e84bbd..e1ea9023ea75b 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -70,7 +70,8 @@ pub trait HeadersSyncPipeline: Clone + Copy { + std::ops::Sub + num_traits::Saturating + num_traits::Zero - + num_traits::One; + + num_traits::One + + Into; /// Type of header that we're syncing. type Header: Clone + std::fmt::Debug + PartialEq + SourceHeader; /// Type of extra data for the header that we're receiving from the source node: From dc13aa28c9fe5527f8f6c7b547db950ffc87ee9f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2020 02:30:55 +0000 Subject: [PATCH 0103/1210] Bump backoff from 0.1.6 to 0.2.1 (#222) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4a7af04c443bb..53cfb22fbec9d 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -10,7 +10,7 @@ ansi_term = "0.12" async-std = "=1.5.0" async-stream = "0.2.0" async-trait = "0.1.36" -backoff = "0.1" +backoff = "0.2" clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.1" } env_logger = "0.7.0" From e297863b3917eb5800e24123702ca57922f634ba Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2020 02:31:27 +0000 Subject: [PATCH 0104/1210] Bump hex-literal from 0.2.1 to 0.3.0 (#223) --- bin/node/runtime/Cargo.toml | 2 +- modules/ethereum/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index b5ec9139b9939..c1437ae4d511a 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -hex-literal = "0.2" +hex-literal = "0.3" [dependencies.codec] package = "parity-scale-codec" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 8beafb6448381..3b14060ab72eb 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] serde = { version = "1.0", optional = true } codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -hex-literal = "0.2" +hex-literal = "0.3" primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", default-features = false } # Substrate Based Dependencies From 7a046bcae2f20247cbccd95ce5a5eb71d340814c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2020 03:38:59 +0000 Subject: [PATCH 0105/1210] Bump sysinfo from 0.13.4 to 0.14.13 (#225) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 53cfb22fbec9d..ab05ed54f647e 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -28,7 +28,7 @@ parking_lot = "0.11.0" rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.56" -sysinfo = "0.13" +sysinfo = "0.14" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = "0.13" From 447c341525711abfe39bbfe060d8aa00ab5b09fa Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2020 03:44:53 +0000 Subject: [PATCH 0106/1210] Bump log from 0.4.8 to 0.4.11 (#224) --- bin/node/node/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index c2d7dbd3cb79a..84edf0183e35a 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -14,7 +14,7 @@ name = "bridge-node" [dependencies] futures = "0.3.5" jsonrpc-core = "14.2.0" -log = "0.4.8" +log = "0.4.11" structopt = "0.3.15" sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index ab05ed54f647e..39a9c038aed40 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -21,7 +21,7 @@ ethereum-tx-sign = "3.0" futures = "0.3.5" hex = "0.4" linked-hash-map = "0.5.3" -log = "0.4.8" +log = "0.4.11" num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.11.0" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index f80fc087e9f13..83f191af1e678 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -13,7 +13,7 @@ derive_more = "0.99.9" env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } -log = "0.4.8" +log = "0.4.11" serde_json = "1.0.56" url = "2.1.0" From 22bf4b96165a820212a85965c94e9f593bca5d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jul 2020 19:17:32 +0200 Subject: [PATCH 0107/1210] Fix clippy suggestions. (#179) * Fix clippy errors. * Cargo fmt. * Enable clippy checks. * Create if does not exist. * Fix warnings and enable sccache for clippy. * chmod +x * Revert and ignore errors. * Update cancel-workflow-action. * Fixes. * Clippy fixes. * Fix compilation. * Fix new clippy warnings. * fmt --all * Fix the rest. * fmt --all * Conditional. * Bump smallvec. * Use separate cache dir for clippy to prevent races. * Remove unused imports in tests * Remove "useless conversion" * Move clippy to main worfklow to avoid clashes. * Fix clippy error. * Fix remaning clippy errors. * cargo fmt --all Co-authored-by: Hernando Castano --- bin/node/node/src/chain_spec.rs | 1 - bin/node/node/src/service.rs | 4 +- bin/node/runtime/src/exchange.rs | 6 +- bin/node/runtime/src/kovan.rs | 9 +-- bin/node/runtime/src/lib.rs | 4 ++ bin/node/runtime/src/rialto.rs | 8 +-- modules/currency-exchange/src/lib.rs | 12 ++-- modules/ethereum-contract/builtin/src/lib.rs | 10 +-- modules/ethereum/src/finality.rs | 22 +++---- modules/ethereum/src/import.rs | 5 +- modules/ethereum/src/lib.rs | 47 +++++++------- modules/ethereum/src/mock.rs | 2 +- modules/ethereum/src/test_utils.rs | 4 +- modules/ethereum/src/validators.rs | 15 +++-- modules/ethereum/src/verification.rs | 22 ++++--- modules/substrate/src/lib.rs | 4 +- primitives/ethereum-poa/src/lib.rs | 10 ++- relays/ethereum/src/ethereum_exchange.rs | 2 +- relays/ethereum/src/ethereum_sync_loop.rs | 3 +- relays/ethereum/src/ethereum_types.rs | 4 +- relays/ethereum/src/exchange.rs | 8 +-- relays/ethereum/src/headers.rs | 66 +++++++++----------- relays/ethereum/src/main.rs | 1 - relays/ethereum/src/rpc_errors.rs | 6 +- relays/ethereum/src/substrate_client.rs | 2 +- relays/ethereum/src/sync.rs | 14 ++--- relays/ethereum/src/sync_loop.rs | 42 +++++-------- relays/ethereum/src/sync_loop_metrics.rs | 4 +- relays/ethereum/src/sync_loop_tests.rs | 2 +- relays/ethereum/src/sync_types.rs | 3 + relays/substrate/src/bridge.rs | 14 ++--- 31 files changed, 159 insertions(+), 197 deletions(-) diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 436e82eaed79c..425448b921c2d 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -19,7 +19,6 @@ use bridge_node_runtime::{ SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use grandpa_primitives::AuthorityId as GrandpaId; -use sc_service; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index b033ff5327da3..c32ecc3220e7c 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -188,7 +188,7 @@ pub fn new_full(config: Configuration) -> Result Result crate::AccountId { hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into() diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index 44532e1d5816f..fe62fce163b12 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -108,12 +108,11 @@ pub fn genesis_header() -> Header { gas_limit: 6000000.into(), difficulty: 131072.into(), seal: vec![ - vec![128].into(), + vec![128], vec![ 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ] - .into(), + ], ], } } @@ -128,9 +127,7 @@ pub struct PruningStrategy; impl BridgePruningStrategy for PruningStrategy { fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { - best_finalized_number - .checked_sub(FINALIZED_HEADERS_TO_KEEP) - .unwrap_or(0) + best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP) } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e61d924ba1281..d77b54764438a 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -19,6 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] +// Runtime-generated enums +#![allow(clippy::large_enum_variant)] +// Runtime-generated DecodeLimit::decode_all_With_depth_limit +#![allow(clippy::unnecessary_mut_passed)] // Make the WASM binary available. #[cfg(feature = "std")] diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs index fa272fe8af8b8..cdc314fb480cc 100644 --- a/bin/node/runtime/src/rialto.rs +++ b/bin/node/runtime/src/rialto.rs @@ -82,10 +82,10 @@ pub fn genesis_header() -> Header { gas_used: Default::default(), gas_limit: 0x222222.into(), difficulty: 0x20000.into(), - seal: vec![vec![0x80].into(), { + seal: vec![vec![0x80], { let mut vec = vec![0xb8, 0x41]; vec.resize(67, 0); - vec.into() + vec }], } } @@ -100,9 +100,7 @@ pub struct PruningStrategy; impl TPruningStrategy for PruningStrategy { fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { - best_finalized_number - .checked_sub(FINALIZED_HEADERS_TO_KEEP) - .unwrap_or(0) + best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP) } } diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index c6ca356e00ffb..12d8657cab2fb 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -132,7 +132,7 @@ decl_module! { match deposit_result { Ok(_) => (), Err(ExchangeError::DepositPartiallyFailed) => (), - Err(error) => Err(Error::::from(error))?, + Err(error) => return Err(Error::::from(error).into()), } Transfers::::insert(&transfer_id, ()) } @@ -273,12 +273,10 @@ mod tests { type Amount = u64; fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { - if amount < MAX_DEPOSIT_AMOUNT * 10 { - Ok(()) - } else if amount == MAX_DEPOSIT_AMOUNT * 10 { - Err(ExchangeError::DepositPartiallyFailed) - } else { - Err(ExchangeError::DepositFailed) + match amount { + amount if amount < MAX_DEPOSIT_AMOUNT * 10 => Ok(()), + amount if amount == MAX_DEPOSIT_AMOUNT * 10 => Err(ExchangeError::DepositPartiallyFailed), + _ => Err(ExchangeError::DepositFailed), } } } diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs index 2f4200f3442f7..5f284231a7259 100644 --- a/modules/ethereum-contract/builtin/src/lib.rs +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -35,7 +35,7 @@ pub enum Error { /// Failed to decode finality proof. FinalityProofDecode(codec::Error), /// Failed to verify justification. - JustificationVerify(ClientError), + JustificationVerify(Box), } /// Substrate header. @@ -120,6 +120,7 @@ pub fn verify_substrate_finality_proof( best_set_id, &best_set, ) + .map_err(Box::new) .map_err(Error::JustificationVerify) .map(|_| ()) } @@ -246,17 +247,16 @@ mod tests { /// Number of the example block with justification. const EXAMPLE_JUSTIFIED_BLOCK_NUMBER: u32 = 8; /// Hash of the example block with justification. - const EXAMPLE_JUSTIFIED_BLOCK_HASH: &'static str = - "a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775"; + const EXAMPLE_JUSTIFIED_BLOCK_HASH: &str = "a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775"; /// Id of authorities set that have generated example justification. Could be computed by tracking /// every set change in canonized headers. const EXAMPLE_AUTHORITIES_SET_ID: u64 = 0; /// Encoded authorities set that has generated example justification. Could be fetched from `ScheduledChange` /// digest of the block that has scheduled this set OR by calling `GrandpaApi::grandpa_authorities()` at /// appropriate block. - const EXAMPLE_AUTHORITIES_SET: &'static str = "1488dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f01000000000000005e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d901000000000000001dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b50100000000000000"; + const EXAMPLE_AUTHORITIES_SET: &str = "1488dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f01000000000000005e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d901000000000000001dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b50100000000000000"; /// Example justification. Could be fetched by calling 'chain_getBlock' RPC. - const EXAMPLE_JUSTIFICATION: &'static str = "2600000000000000a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000010a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000d66b4ceb57ef8bcbc955071b597c8c5d2adcfdbb009c73f8438d342670fdeca9ac60686cbd58105b10f51d0a64a8e73b2e5829b2eab3248a008c472852130b00439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234fa2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000f5730c14d3cd22b7661e2f5fcb3139dd5fef37f946314a441d01b40ce1200ef70d810525f23fd278b588cd67473c200bda83c338c407b479386aa83798e5970b5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000c78d6ec463f476461a695b4791d30e7626d16fdf72d7c252c2cad387495a97e8c2827ed4d5af853d6e05d31cb6fb7438c9481a7e9c6990d60a9bfaf6a6e1930988dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eea2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000052b4fc52d430286b3e2d650aa6e01b6ff4fae8b968893a62be789209eb97ee6e23780d3f5af7042d85bb48f1b202890b22724dfebce138826f66a5e00324320fd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae6900"; + const EXAMPLE_JUSTIFICATION: &str = "2600000000000000a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000010a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000d66b4ceb57ef8bcbc955071b597c8c5d2adcfdbb009c73f8438d342670fdeca9ac60686cbd58105b10f51d0a64a8e73b2e5829b2eab3248a008c472852130b00439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234fa2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000f5730c14d3cd22b7661e2f5fcb3139dd5fef37f946314a441d01b40ce1200ef70d810525f23fd278b588cd67473c200bda83c338c407b479386aa83798e5970b5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000c78d6ec463f476461a695b4791d30e7626d16fdf72d7c252c2cad387495a97e8c2827ed4d5af853d6e05d31cb6fb7438c9481a7e9c6990d60a9bfaf6a6e1930988dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eea2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000052b4fc52d430286b3e2d650aa6e01b6ff4fae8b968893a62be789209eb97ee6e23780d3f5af7042d85bb48f1b202890b22724dfebce138826f66a5e00324320fd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae6900"; #[test] fn substrate_header_parse_fails() { diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index e113f66831a8f..c847e77704799 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -99,7 +99,7 @@ pub fn finalize_blocks( *hash == header_validators.0.hash || *hash == best_finalized.hash }) }) - .unwrap_or_else(|| CachedFinalityVotes::default()), + .unwrap_or_default(), best_finalized, &validators, id, @@ -247,7 +247,7 @@ fn empty_steps_signers(header: &Header) -> BTreeSet

{ header .empty_steps() .into_iter() - .flat_map(|steps| steps) + .flatten() .filter_map(|step| empty_step_signer(&step, &header.parent_hash)) .collect::>() } @@ -462,13 +462,9 @@ mod tests { // when we're inserting header#7 and last finalized header is 0: // check that votes at #7 are computed correctly without cache let expected_votes_at_7 = FinalityVotes { - votes: vec![ - (ctx.addresses[0].clone(), 3), - (ctx.addresses[1].clone(), 3), - (ctx.addresses[2].clone(), 1), - ] - .into_iter() - .collect(), + votes: vec![(ctx.addresses[0], 3), (ctx.addresses[1], 3), (ctx.addresses[2], 1)] + .into_iter() + .collect(), ancestry: ancestry[..7].iter().cloned().collect(), }; let id7 = headers[6].compute_id(); @@ -491,9 +487,7 @@ mod tests { // cached votes at #5 let expected_votes_at_5 = FinalityVotes { - votes: vec![(ctx.addresses[0].clone(), 3), (ctx.addresses[1].clone(), 2)] - .into_iter() - .collect(), + votes: vec![(ctx.addresses[0], 3), (ctx.addresses[1], 2)].into_iter().collect(), ancestry: ancestry[..5].iter().cloned().collect(), }; FinalityCache::::insert(hashes[4], expected_votes_at_5); @@ -520,9 +514,7 @@ mod tests { // when we're inserting header#7 and last finalized header is 3: // check that votes at #7 are computed correctly with cache let expected_votes_at_7 = FinalityVotes { - votes: vec![(ctx.addresses[1].clone(), 3), (ctx.addresses[2].clone(), 1)] - .into_iter() - .collect(), + votes: vec![(ctx.addresses[1], 3), (ctx.addresses[2], 1)].into_iter().collect(), ancestry: ancestry[3..7].iter().cloned().collect(), }; assert_eq!( diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 588b4dfdbf2cd..490c164e47b58 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -70,6 +70,9 @@ pub fn import_headers( Ok((useful, useless)) } +/// A vector of finalized headers and their submitters. +pub type FinalizedHeaders = Vec<(HeaderId, Option<::Submitter>)>; + /// Imports given header and updates blocks finality (if required). /// /// Transactions receipts must be provided if `header_import_requires_receipts()` @@ -84,7 +87,7 @@ pub fn import_header( submitter: Option, header: Header, receipts: Option>, -) -> Result<(HeaderId, Vec<(HeaderId, Option)>), Error> { +) -> Result<(HeaderId, FinalizedHeaders), Error> { // first check that we are able to import this header at all let (header_id, finalized_id) = is_importable_header(storage, &header)?; diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index b77f436301d67..bfae5d4b260c4 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -15,6 +15,8 @@ // along with Parity Bridges Common. If not, see . #![cfg_attr(not(feature = "std"), no_std)] +// Runtime-generated enums +#![allow(clippy::large_enum_variant)] use crate::finality::{CachedFinalityVotes, FinalityVotes}; use codec::{Decode, Encode}; @@ -235,6 +237,7 @@ impl ImportContext { } /// Converts import context into header we're going to import. + #[allow(clippy::too_many_arguments)] pub fn into_import_header( self, is_best: bool, @@ -503,7 +506,7 @@ impl Module { } /// Verify that transaction is included into given finalized block. - pub fn verify_transaction_finalized(block: H256, tx_index: u64, proof: &Vec) -> bool { + pub fn verify_transaction_finalized(block: H256, tx_index: u64, proof: &[RawTransaction]) -> bool { crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) } } @@ -616,13 +619,8 @@ impl BridgeStorage { blocks_at_number: &mut Vec, ) { // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number { - if blocks_at_number - .iter() - .any(|block| ScheduledChanges::contains_key(block)) - { - return; - } + if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::contains_key) { + return; } // physically remove headers and (probably) obsolete validators sets @@ -678,11 +676,9 @@ impl Storage for BridgeStorage { let mut current_id = *parent; loop { // if we have reached finalized block' sibling => stop with special signal - if current_id.number == best_finalized.number { - if current_id.hash != best_finalized.hash { - votes.stopped_at_finalized_sibling = true; - return votes; - } + if current_id.number == best_finalized.number && current_id.hash != best_finalized.hash { + votes.stopped_at_finalized_sibling = true; + return votes; } // if we have reached target header => stop @@ -834,6 +830,7 @@ impl Storage for BridgeStorage { } /// Initialize storage. +#[cfg(any(feature = "std", feature = "runtime-benchmarks"))] pub(crate) fn initialize_storage( initial_header: &Header, initial_difficulty: U256, @@ -885,7 +882,7 @@ pub fn verify_transaction_finalized( storage: &S, block: H256, tx_index: u64, - proof: &Vec, + proof: &[RawTransaction], ) -> bool { if tx_index >= proof.len() as _ { return false; @@ -906,9 +903,7 @@ pub fn verify_transaction_finalized( let is_finalized = match header.number < finalized.number { true => ancestry(storage, finalized.hash) .skip_while(|(_, ancestor)| ancestor.number > header.number) - .filter(|&(ancestor_hash, _)| ancestor_hash == block) - .next() - .is_some(), + .any(|(ancestor_hash, _)| ancestor_hash == block), false => block == finalized.hash, }; if !is_finalized { @@ -985,7 +980,7 @@ pub(crate) mod tests { hash, StoredHeader { submitter: None, - header: header, + header, total_difficulty: 0.into(), next_validators_set_id: 0, last_signal_block: None, @@ -1266,7 +1261,7 @@ pub(crate) mod tests { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &[example_tx()],), true, ); }); @@ -1280,7 +1275,7 @@ pub(crate) mod tests { insert_header(&mut storage, example_header()); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( - verify_transaction_finalized(&storage, example_header_parent().compute_hash(), 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, example_header_parent().compute_hash(), 0, &[example_tx()],), true, ); }); @@ -1291,7 +1286,7 @@ pub(crate) mod tests { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &vec![],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &[],), false, ); }); @@ -1302,7 +1297,7 @@ pub(crate) mod tests { run_test(TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &vec![],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &[],), false, ); }); @@ -1315,7 +1310,7 @@ pub(crate) mod tests { insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &[example_tx()],), false, ); }); @@ -1334,7 +1329,7 @@ pub(crate) mod tests { insert_header(&mut storage, finalized_header_sibling); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( - verify_transaction_finalized(&storage, finalized_header_sibling_hash, 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, finalized_header_sibling_hash, 0, &[example_tx()],), false, ); }); @@ -1353,7 +1348,7 @@ pub(crate) mod tests { insert_header(&mut storage, example_header()); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( - verify_transaction_finalized(&storage, finalized_header_uncle_hash, 0, &vec![example_tx()],), + verify_transaction_finalized(&storage, finalized_header_uncle_hash, 0, &[example_tx()],), false, ); }); @@ -1368,7 +1363,7 @@ pub(crate) mod tests { &storage, example_header().compute_hash(), 0, - &vec![example_tx(), example_tx(),], + &[example_tx(), example_tx()], ), false, ); diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 6c68d927586be..0dde85bd93c5f 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -160,6 +160,6 @@ impl Default for KeepSomeHeadersBehindBest { impl PruningStrategy for KeepSomeHeadersBehindBest { fn pruning_upper_bound(&mut self, best_number: u64, _: u64) -> u64 { - best_number.checked_sub(self.0).unwrap_or(0) + best_number.saturating_sub(self.0) } } diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 9084783d6802d..eacdb680e0ba1 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -86,7 +86,7 @@ impl HeaderBuilder { use crate::HeadersByNumber; use frame_support::StorageMap; - let parent_hash = HeadersByNumber::get(parent_number).unwrap()[0].clone(); + let parent_hash = HeadersByNumber::get(parent_number).unwrap()[0]; Self::with_parent_hash_on_runtime::(parent_hash) } @@ -130,7 +130,7 @@ impl HeaderBuilder { /// Adds empty steps to this header. pub fn empty_steps(mut self, empty_steps: &[(&SecretKey, u64)]) -> Self { let sealed_empty_steps = empty_steps - .into_iter() + .iter() .map(|(author, step)| { let mut empty_step = SealedEmptyStep { step: *step, diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 5620bcb86c0a8..7aa2dd8cb1ee9 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -20,7 +20,7 @@ use primitives::{Address, Header, HeaderId, LogEntry, Receipt, U256}; use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. -pub(crate) const CHANGE_EVENT_HASH: &'static [u8; 32] = &[ +pub(crate) const CHANGE_EVENT_HASH: &[u8; 32] = &[ 0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, 0xd2, 0xc2, 0x28, 0x1d, 0xf8, 0xd6, 0xea, 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89, ]; @@ -49,6 +49,9 @@ pub enum ValidatorsSource { Contract(Address, Vec
), } +/// A short hand for optional validators change. +pub type ValidatorsChange = Option>; + /// Validators manager. pub struct Validators<'a> { config: &'a ValidatorsConfiguration, @@ -94,7 +97,7 @@ impl<'a> Validators<'a> { &self, header: &Header, receipts: Option>, - ) -> Result<(Option>, Option>), Error> { + ) -> Result<(ValidatorsChange, ValidatorsChange), Error> { // let's first check if new source is starting from this header let (source_index, _, source) = self.source_at(header.number); let (next_starts_at, next_source) = self.source_at_next_header(source_index, header.number); @@ -223,7 +226,7 @@ impl<'a> Validators<'a> { } /// Returns source of validators that should author the header. - fn source_at<'b>(&'b self, header_number: u64) -> (usize, u64, &'b ValidatorsSource) { + fn source_at(&self, header_number: u64) -> (usize, u64, &ValidatorsSource) { match self.config { ValidatorsConfiguration::Single(ref source) => (0, 0, source), ValidatorsConfiguration::Multi(ref sources) => sources @@ -240,11 +243,7 @@ impl<'a> Validators<'a> { } /// Returns source of validators that should author the next header. - fn source_at_next_header<'b>( - &'b self, - header_source_index: usize, - header_number: u64, - ) -> (u64, &'b ValidatorsSource) { + fn source_at_next_header(&self, header_source_index: usize, header_number: u64) -> (u64, &ValidatorsSource) { match self.config { ValidatorsConfiguration::Single(ref source) => (0, source), ValidatorsConfiguration::Multi(ref sources) => { diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 3c49e81eac1c4..3b1c1865929ef 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -22,6 +22,7 @@ use primitives::{ public_to_address, step_validator, Address, Header, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, }; use sp_io::crypto::secp256k1_ecdsa_recover; +use sp_runtime::transaction_validity::TransactionTag; use sp_std::{vec, vec::Vec}; /// Pre-check to see if should try and import this header. @@ -43,6 +44,8 @@ pub fn is_importable_header(storage: &S, header: &Header) -> Result< } /// Try accept unsigned aura header into transaction pool. +/// +/// Returns required and provided tags. pub fn accept_aura_header_into_pool( storage: &S, config: &AuraConfiguration, @@ -50,7 +53,7 @@ pub fn accept_aura_header_into_pool( pool_config: &PoolConfiguration, header: &Header, receipts: Option<&Vec>, -) -> Result<(Vec>, Vec>), Error> { +) -> Result<(Vec, Vec), Error> { // check if we can verify further let (header_id, _) = is_importable_header(storage, header)?; @@ -365,6 +368,7 @@ mod tests { use frame_support::{StorageMap, StorageValue}; use primitives::{compute_merkle_root, rlp_encode, TransactionOutcome, H520}; use secp256k1::SecretKey; + use sp_runtime::transaction_validity::TransactionTag; const GENESIS_STEP: u64 = 42; const TOTAL_VALIDATORS: usize = 3; @@ -386,7 +390,7 @@ mod tests { fn default_accept_into_pool( mut make_header: impl FnMut(&[SecretKey]) -> (Header, Option>), - ) -> Result<(Vec>, Vec>), Error> { + ) -> Result<(Vec, Vec), Error> { run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let validators = vec![validator(0), validator(1), validator(2)]; let mut storage = BridgeStorage::::new(); @@ -429,7 +433,7 @@ mod tests { }, ); - let header_hash = HeadersByNumber::get(&number).unwrap()[0].clone(); + let header_hash = HeadersByNumber::get(&number).unwrap()[0]; let mut header = Headers::::get(&header_hash).unwrap(); header.next_validators_set_id = set_id; if let Some(signalled_set) = signalled_set { @@ -456,15 +460,15 @@ mod tests { assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); // when there's single seal (we expect 2 or 3 seals) - header.seal = vec![vec![].into()]; + header.seal = vec![vec![]]; assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); // when there's 3 seals (we expect 2 by default) - header.seal = vec![vec![].into(), vec![].into(), vec![].into()]; + header.seal = vec![vec![], vec![], vec![]]; assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); // when there's 2 seals - header.seal = vec![vec![].into(), vec![].into()]; + header.seal = vec![vec![], vec![]]; assert_ne!(default_verify(&header), Err(Error::InvalidSealArity)); } @@ -564,7 +568,7 @@ mod tests { fn verifies_step() { // when step is missing from seals let mut header = Header { - seal: vec![vec![].into(), vec![].into()], + seal: vec![vec![], vec![]], gas_limit: test_aura_config().min_gas_limit, parent_hash: genesis().compute_hash(), ..Default::default() @@ -585,7 +589,7 @@ mod tests { // when step is lesser that for the parent block header.seal[0] = rlp_encode(&40u64); - header.seal = vec![vec![40].into(), vec![].into()]; + header.seal = vec![vec![40], vec![]]; assert_eq!(verify_with_config(&config, &header), Err(Error::DoubleVote)); // when step is OK @@ -691,7 +695,7 @@ mod tests { default_accept_into_pool(|_| ( Header { number: 20_000_000, - seal: vec![vec![].into(), vec![].into()], + seal: vec![vec![], vec![]], gas_limit: test_aura_config().min_gas_limit, log_bloom: (&[0xff; 256]).into(), ..Default::default() diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 61d50d6fdd556..9afa0872a57b9 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -157,9 +157,9 @@ impl Module { fn check_validator_set_proof( state_root: &T::Hash, proof: StorageProof, - validator_set: &Vec<(AuthorityId, AuthorityWeight)>, + validator_set: &[(AuthorityId, AuthorityWeight)], ) -> DispatchResult { - let checker = >::new(*state_root, proof.clone()); + let checker = >::new(*state_root, proof); let checker = checker.map_err(Self::map_storage_err)?; diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index fa47912f39f0b..6515f901feffd 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -15,6 +15,10 @@ // along with Parity Bridges Common. If not, see . #![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Generated by `DecodeLimit::decode_with_depth_limit` +#![allow(clippy::unnecessary_mut_passed)] pub use parity_bytes::Bytes; pub use primitive_types::{H160, H256, H512, U128, U256}; @@ -206,7 +210,7 @@ impl Header { /// Check if passed transactions are matching transactions root in this header. pub fn verify_transactions_root(&self, transactions: &[RawTransaction]) -> bool { - verify_merkle_proof(self.transactions_root, transactions.into_iter()) + verify_merkle_proof(self.transactions_root, transactions.iter()) } /// Gets the seal hash of this header. @@ -581,7 +585,7 @@ mod tests { gas: 86016.into(), to: Some(hex!("dac17f958d2ee523a2206206994597c13d831ec7").into()), value: 0.into(), - payload: hex!("a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b40").to_vec().into(), + payload: hex!("a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b40").to_vec(), }, }), ); @@ -600,7 +604,7 @@ mod tests { gas: 160000.into(), to: Some(hex!("84dd11eb2a29615303d18149c0dbfa24167f8966").into()), value: 0.into(), - payload: hex!("a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b60000000000000000000000000000000000000000000000000000000000002710").to_vec().into(), + payload: hex!("a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b60000000000000000000000000000000000000000000000000000000000002710").to_vec(), }, }), ); diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 385c68a3fef7d..95ded39f60cd5 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -100,7 +100,7 @@ impl SourceClient for EthereumTransactionsSource { eth_header_id: &EthereumHeaderId, eth_tx: EthereumTransaction, ) -> Result { - const TRANSACTION_HAS_RAW_FIELD_PROOF: &'static str = "RPC level checks that transactions from Ethereum\ + const TRANSACTION_HAS_RAW_FIELD_PROOF: &str = "RPC level checks that transactions from Ethereum\ node are having `raw` field; qed"; let eth_header = self.client.header_by_hash_with_transactions(eth_header_id.1).await?; diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 162f93c63143c..4a13fa6a1dcf8 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -163,7 +163,7 @@ impl TargetClient for SubstrateHeadersTarget { &self, headers: Vec, ) -> SubmittedHeaders { - let (sign_params, sign_transactions) = (self.sign_params.clone(), self.sign_transactions.clone()); + let (sign_params, sign_transactions) = (self.sign_params.clone(), self.sign_transactions); self.client .submit_ethereum_headers(sign_params, headers, sign_transactions) .await @@ -173,6 +173,7 @@ impl TargetClient for SubstrateHeadersTarget { Ok(HashSet::new()) } + #[allow(clippy::unit_arg)] async fn complete_header(&self, id: EthereumHeaderId, _completion: ()) -> Result { Ok(id) } diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index 6e118e3ad986a..58aa3497014fd 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -22,11 +22,11 @@ pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; /// When header is just received from the Ethereum node, we check that it has /// both number and hash fields filled. -pub const HEADER_ID_PROOF: &'static str = "checked on retrieval; qed"; +pub const HEADER_ID_PROOF: &str = "checked on retrieval; qed"; /// When receipt is just received from the Ethereum node, we check that it has /// gas_used field filled. -pub const RECEIPT_GAS_USED_PROOF: &'static str = "checked on retrieval; qed"; +pub const RECEIPT_GAS_USED_PROOF: &str = "checked on retrieval; qed"; /// Ethereum transaction hash type. pub type TransactionHash = H256; diff --git a/relays/ethereum/src/exchange.rs b/relays/ethereum/src/exchange.rs index d465e8a214949..352e53fe6cb3a 100644 --- a/relays/ethereum/src/exchange.rs +++ b/relays/ethereum/src/exchange.rs @@ -323,7 +323,7 @@ mod tests { &self, _: &TestTransactionHash, ) -> Result, TestError> { - self.data.lock().transaction.clone() + self.data.lock().transaction } async fn transaction_proof( @@ -331,7 +331,7 @@ mod tests { _: &TestHeaderId, _: TestTransaction, ) -> Result { - self.data.lock().transaction_proof.clone() + self.data.lock().transaction_proof } } @@ -368,11 +368,11 @@ mod tests { } async fn is_header_known(&self, _: &TestHeaderId) -> Result { - self.data.lock().is_header_known.clone() + self.data.lock().is_header_known } async fn is_header_finalized(&self, _: &TestHeaderId) -> Result { - self.data.lock().is_header_finalized.clone() + self.data.lock().is_header_finalized } async fn submit_transaction_proof(&self, proof: TestTransactionProof) -> Result<(), TestError> { diff --git a/relays/ethereum/src/headers.rs b/relays/ethereum/src/headers.rs index c1dcc86444d67..8980bcccf3e8a 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/ethereum/src/headers.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::sync_types::{HeaderId, HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; use linked_hash_map::LinkedHashMap; use num_traits::{One, Zero}; use std::{ @@ -59,9 +59,9 @@ pub struct QueuedHeaders { known_headers: KnownHeaders

, /// Headers that are waiting for completion data from source node. Mapped (and auto-sorted /// by) to the last fetch time. - incomplete_headers: LinkedHashMap, Option>, + incomplete_headers: LinkedHashMap, Option>, /// Headers that are waiting to be completed at target node. Auto-sorted by insertion time. - completion_data: LinkedHashMap, P::Completion>, + completion_data: LinkedHashMap, P::Completion>, /// Best synced block number. best_synced_number: P::Number, /// Pruned blocks border. We do not store or accept any blocks with number less than @@ -106,7 +106,7 @@ impl QueuedHeaders

{ /// Returns number of headers that are currently in given queue. pub fn headers_in_status(&self, status: HeaderStatus) -> usize { match status { - HeaderStatus::Unknown | HeaderStatus::Synced => return 0, + HeaderStatus::Unknown | HeaderStatus::Synced => 0, HeaderStatus::MaybeOrphan => self .maybe_orphan .values() @@ -168,7 +168,7 @@ impl QueuedHeaders

{ } /// Returns synchronization status of the header. - pub fn status(&self, id: &HeaderId) -> HeaderStatus { + pub fn status(&self, id: &HeaderIdOf

) -> HeaderStatus { self.known_headers .get(&id.0) .and_then(|x| x.get(&id.1)) @@ -179,7 +179,7 @@ impl QueuedHeaders

{ /// Get oldest header from given queue. pub fn header(&self, status: HeaderStatus) -> Option<&QueuedHeader

> { match status { - HeaderStatus::Unknown | HeaderStatus::Synced => return None, + HeaderStatus::Unknown | HeaderStatus::Synced => None, HeaderStatus::MaybeOrphan => oldest_header(&self.maybe_orphan), HeaderStatus::Orphan => oldest_header(&self.orphan), HeaderStatus::MaybeExtra => oldest_header(&self.maybe_extra), @@ -197,7 +197,7 @@ impl QueuedHeaders

{ f: impl FnMut(&QueuedHeader

) -> bool, ) -> Option>> { match status { - HeaderStatus::Unknown | HeaderStatus::Synced => return None, + HeaderStatus::Unknown | HeaderStatus::Synced => None, HeaderStatus::MaybeOrphan => oldest_headers(&self.maybe_orphan, f), HeaderStatus::Orphan => oldest_headers(&self.orphan, f), HeaderStatus::MaybeExtra => oldest_headers(&self.maybe_extra, f), @@ -268,12 +268,12 @@ impl QueuedHeaders

{ } /// Receive best header from the target node. - pub fn target_best_header_response(&mut self, id: &HeaderId) { + pub fn target_best_header_response(&mut self, id: &HeaderIdOf

) { self.header_synced(id) } /// Receive target node response for MaybeOrphan request. - pub fn maybe_orphan_response(&mut self, id: &HeaderId, response: bool) { + pub fn maybe_orphan_response(&mut self, id: &HeaderIdOf

, response: bool) { if !response { move_header_descendants::

( &mut [&mut self.maybe_orphan], @@ -295,7 +295,7 @@ impl QueuedHeaders

{ } /// Receive target node response for MaybeExtra request. - pub fn maybe_extra_response(&mut self, id: &HeaderId, response: bool) { + pub fn maybe_extra_response(&mut self, id: &HeaderIdOf

, response: bool) { let (destination_status, destination_queue) = if response { (HeaderStatus::Extra, &mut self.extra) } else if self.is_parent_incomplete(id) { @@ -315,7 +315,7 @@ impl QueuedHeaders

{ } /// Receive extra from source node. - pub fn extra_response(&mut self, id: &HeaderId, extra: P::Extra) { + pub fn extra_response(&mut self, id: &HeaderIdOf

, extra: P::Extra) { let (destination_status, destination_queue) = if self.is_parent_incomplete(id) { (HeaderStatus::Incomplete, &mut self.incomplete) } else { @@ -334,7 +334,7 @@ impl QueuedHeaders

{ } /// Receive completion response from source node. - pub fn completion_response(&mut self, id: &HeaderId, completion: Option) { + pub fn completion_response(&mut self, id: &HeaderIdOf

, completion: Option) { let completion = match completion { Some(completion) => completion, None => { @@ -361,12 +361,12 @@ impl QueuedHeaders

{ id, ); - self.completion_data.insert(id.clone(), completion); + self.completion_data.insert(*id, completion); } } /// When header is submitted to target node. - pub fn headers_submitted(&mut self, ids: Vec>) { + pub fn headers_submitted(&mut self, ids: Vec>) { for id in ids { move_header( &mut self.ready, @@ -380,7 +380,7 @@ impl QueuedHeaders

{ } /// When header completion data is sent to target node. - pub fn header_completed(&mut self, id: &HeaderId) { + pub fn header_completed(&mut self, id: &HeaderIdOf

) { if self.completion_data.remove(id).is_some() { log::debug!( target: "bridge", @@ -404,7 +404,7 @@ impl QueuedHeaders

{ } /// Marks given headers incomplete. - pub fn add_incomplete_headers(&mut self, new_incomplete_headers: Vec>) { + pub fn add_incomplete_headers(&mut self, new_incomplete_headers: Vec>) { for new_incomplete_header in new_incomplete_headers { self.header_synced(&new_incomplete_header); move_header_descendants::

( @@ -426,7 +426,7 @@ impl QueuedHeaders

{ } /// When incomplete headers ids are receved from target node. - pub fn incomplete_headers_response(&mut self, ids: HashSet>) { + pub fn incomplete_headers_response(&mut self, ids: HashSet>) { // all new incomplete headers are marked Synced and all their descendants // are moved from Ready/Submitted to Incomplete queue let new_incomplete_headers = ids @@ -466,7 +466,7 @@ impl QueuedHeaders

{ } /// Returns id of the header for which we want to fetch completion data. - pub fn incomplete_header(&mut self) -> Option> { + pub fn incomplete_header(&mut self) -> Option> { queued_incomplete_header(&mut self.incomplete_headers, |last_fetch_time| { let retry = match *last_fetch_time { Some(last_fetch_time) => last_fetch_time.elapsed() > RETRY_FETCH_COMPLETION_INTERVAL, @@ -483,7 +483,7 @@ impl QueuedHeaders

{ } /// Returns header completion data to upload to target node. - pub fn header_to_complete(&mut self) -> Option<(HeaderId, &P::Completion)> { + pub fn header_to_complete(&mut self) -> Option<(HeaderIdOf

, &P::Completion)> { queued_incomplete_header(&mut self.completion_data, |_| true) } @@ -520,7 +520,7 @@ impl QueuedHeaders

{ /// Returns true if parent of this header is either incomplete or waiting for /// its own incomplete ancestor to be completed. - fn is_parent_incomplete(&self, id: &HeaderId) -> bool { + fn is_parent_incomplete(&self, id: &HeaderIdOf

) -> bool { let status = self.status(id); let header = match status { HeaderStatus::MaybeOrphan => header(&self.maybe_orphan, id), @@ -546,7 +546,7 @@ impl QueuedHeaders

{ } /// When we receive new Synced header from target node. - fn header_synced(&mut self, id: &HeaderId) { + fn header_synced(&mut self, id: &HeaderIdOf

) { // update best synced block number self.best_synced_number = std::cmp::max(self.best_synced_number, id.0); @@ -593,19 +593,12 @@ impl QueuedHeaders

{ } /// Insert header to the queue. -fn insert_header( - queue: &mut HeadersQueue

, - id: HeaderId, - header: QueuedHeader

, -) { +fn insert_header(queue: &mut HeadersQueue

, id: HeaderIdOf

, header: QueuedHeader

) { queue.entry(id.0).or_default().insert(id.1, header); } /// Remove header from the queue. -fn remove_header( - queue: &mut HeadersQueue

, - id: &HeaderId, -) -> Option> { +fn remove_header(queue: &mut HeadersQueue

, id: &HeaderIdOf

) -> Option> { let mut headers_at = match queue.entry(id.0) { BTreeMapEntry::Occupied(headers_at) => headers_at, BTreeMapEntry::Vacant(_) => return None, @@ -619,10 +612,7 @@ fn remove_header( } /// Get header from the queue. -fn header<'a, P: HeadersSyncPipeline>( - queue: &'a HeadersQueue

, - id: &HeaderId, -) -> Option<&'a QueuedHeader

> { +fn header<'a, P: HeadersSyncPipeline>(queue: &'a HeadersQueue

, id: &HeaderIdOf

) -> Option<&'a QueuedHeader

> { queue.get(&id.0).and_then(|by_hash| by_hash.get(&id.1)) } @@ -634,9 +624,9 @@ fn move_header( destination_queue: &mut HeadersQueue

, known_headers: &mut KnownHeaders

, destination_status: HeaderStatus, - id: &HeaderId, + id: &HeaderIdOf

, prepare: impl FnOnce(QueuedHeader

) -> QueuedHeader

, -) -> Option> { +) -> Option> { let header = match remove_header(source_queue, id) { Some(header) => prepare(header), None => return None, @@ -655,7 +645,7 @@ fn move_header_descendants( destination_queue: &mut HeadersQueue

, known_headers: &mut KnownHeaders

, destination_status: HeaderStatus, - id: &HeaderId, + id: &HeaderIdOf

, ) { let mut current_number = id.0 + One::one(); let mut current_parents = HashSet::new(); @@ -743,7 +733,7 @@ fn prune_known_headers(known_headers: &mut KnownHeaders< /// Change header status. fn set_header_status( known_headers: &mut KnownHeaders

, - id: &HeaderId, + id: &HeaderIdOf

, status: HeaderStatus, ) { log::debug!( diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index a574e64775809..4894c7efb27e8 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -101,7 +101,6 @@ fn main() { } ("", _) => { log::error!(target: "bridge", "No subcommand specified"); - return; } _ => unreachable!("all possible subcommands are checked above; qed"), } diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 65f757a0e01d7..4645d4e4dcf85 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -18,7 +18,6 @@ use crate::ethereum_types::{EthereumHeaderId, TransactionHash as EthereumTransac use crate::sync_types::MaybeConnectionError; use jsonrpsee::client::RequestError; -use serde_json; /// Contains common errors that can occur when /// interacting with a Substrate or Ethereum node @@ -79,10 +78,7 @@ impl From for RpcError { impl MaybeConnectionError for RpcError { fn is_connection_error(&self) -> bool { - match *self { - RpcError::Request(RequestError::TransportError(_)) => true, - _ => false, - } + matches!(*self, RpcError::Request(RequestError::TransportError(_))) } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index e349213dfc74c..e0c59457b0125 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -400,5 +400,5 @@ fn create_signed_transaction( let signer: sp_runtime::MultiSigner = signer.public().into(); let (function, extra, _) = raw_payload.deconstruct(); - bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account().into(), signature.into(), extra) + bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account(), signature.into(), extra) } diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 481311f20f371..b1799bf2d2950 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::headers::QueuedHeaders; -use crate::sync_types::{HeaderId, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; +use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; use num_traits::{One, Saturating, Zero}; /// Common sync params. @@ -56,7 +56,7 @@ pub struct HeadersSync { /// Best header number known to source node. source_best_number: Option, /// Best header known to target node. - target_best_header: Option>, + target_best_header: Option>, /// Headers queue. headers: QueuedHeaders

, } @@ -78,7 +78,7 @@ impl HeadersSync

{ } /// Best header known to target node. - pub fn target_best_header(&self) -> Option> { + pub fn target_best_header(&self) -> Option> { self.target_best_header } @@ -94,7 +94,7 @@ impl HeadersSync

{ } /// Returns synchronization status. - pub fn status(&self) -> (&Option>, &Option) { + pub fn status(&self) -> (&Option>, &Option) { (&self.target_best_header, &self.source_best_number) } @@ -111,7 +111,7 @@ impl HeadersSync

{ /// Select header that needs to be downloaded from the source node. pub fn select_new_header_to_download(&self) -> Option { // if we haven't received best header from source node yet, there's nothing we can download - let source_best_number = self.source_best_number.clone()?; + let source_best_number = self.source_best_number?; // if we haven't received known best header from target node yet, there's nothing we can download let target_best_header = self.target_best_header.as_ref()?; @@ -205,7 +205,7 @@ impl HeadersSync

{ /// Receive new best header from the target node. /// Returns true if it is different from the previous block known to us. - pub fn target_best_header_response(&mut self, best_header: HeaderId) -> bool { + pub fn target_best_header_response(&mut self, best_header: HeaderIdOf

) -> bool { log::debug!( target: "bridge", "Received best known header from {}: {:?}", @@ -244,7 +244,7 @@ pub mod tests { use super::*; use crate::ethereum_types::{EthereumHeadersSyncPipeline, H256}; use crate::headers::tests::{header, id}; - use crate::sync_types::HeaderStatus; + use crate::sync_types::{HeaderId, HeaderStatus}; fn side_hash(number: u64) -> H256 { H256::from_low_u64_le(1000 + number) diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 9128374e9ff10..be64e9fa504d5 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -18,7 +18,7 @@ use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams, Regis use crate::sync::HeadersSyncParams; use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{ - HeaderId, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SubmittedHeaders, + HeaderIdOf, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SubmittedHeaders, }; use async_trait::async_trait; @@ -68,17 +68,15 @@ pub trait SourceClient: Sized { async fn header_by_number(&self, number: P::Number) -> Result; /// Get completion data by header hash. - async fn header_completion( - &self, - id: HeaderId, - ) -> Result<(HeaderId, Option), Self::Error>; + async fn header_completion(&self, id: HeaderIdOf

) + -> Result<(HeaderIdOf

, Option), Self::Error>; /// Get extra data by header hash. async fn header_extra( &self, - id: HeaderId, + id: HeaderIdOf

, header: QueuedHeader

, - ) -> Result<(HeaderId, P::Extra), Self::Error>; + ) -> Result<(HeaderIdOf

, P::Extra), Self::Error>; } /// Target client trait. @@ -88,35 +86,23 @@ pub trait TargetClient: Sized { type Error: std::fmt::Debug + MaybeConnectionError; /// Returns ID of best header known to the target node. - async fn best_header_id(&self) -> Result, Self::Error>; + async fn best_header_id(&self) -> Result, Self::Error>; /// Returns true if header is known to the target node. - async fn is_known_header( - &self, - id: HeaderId, - ) -> Result<(HeaderId, bool), Self::Error>; + async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), Self::Error>; /// Submit headers. - async fn submit_headers( - &self, - headers: Vec>, - ) -> SubmittedHeaders, Self::Error>; + async fn submit_headers(&self, headers: Vec>) -> SubmittedHeaders, Self::Error>; /// Returns ID of headers that require to be 'completed' before children can be submitted. - async fn incomplete_headers_ids(&self) -> Result>, Self::Error>; + async fn incomplete_headers_ids(&self) -> Result>, Self::Error>; /// Submit completion data for header. - async fn complete_header( - &self, - id: HeaderId, - completion: P::Completion, - ) -> Result, Self::Error>; + async fn complete_header(&self, id: HeaderIdOf

, completion: P::Completion) + -> Result, Self::Error>; /// Returns true if header requires extra data to be submitted. - async fn requires_extra( - &self, - header: QueuedHeader

, - ) -> Result<(HeaderId, bool), Self::Error>; + async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), Self::Error>; } /// Run headers synchronization. @@ -327,7 +313,7 @@ pub fn run>( }, submitted_headers = target_submit_header_future => { // following line helps Rust understand the type of `submitted_headers` :/ - let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; + let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; let maybe_fatal_error = submitted_headers.fatal_error.map(Err).unwrap_or(Ok(())); target_client_is_online = process_future_result( @@ -380,7 +366,7 @@ pub fn run>( // update metrics if metrics_enabled { metrics_global.update(); - metrics_sync.update(&mut sync); + metrics_sync.update(&sync); } // print progress diff --git a/relays/ethereum/src/sync_loop_metrics.rs b/relays/ethereum/src/sync_loop_metrics.rs index 657630ad408c6..fa34c8b511d65 100644 --- a/relays/ethereum/src/sync_loop_metrics.rs +++ b/relays/ethereum/src/sync_loop_metrics.rs @@ -55,8 +55,8 @@ impl SyncLoopMetrics { /// Update metrics. pub fn update(&mut self, sync: &HeadersSync

) { let headers = sync.headers(); - let source_best_number = sync.source_best_number().unwrap_or(Zero::zero()); - let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or(Zero::zero()); + let source_best_number = sync.source_best_number().unwrap_or_else(Zero::zero); + let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); self.best_block_numbers .with_label_values(&["source"]) diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/ethereum/src/sync_loop_tests.rs index 83fadce6199c7..b49d4ce5e530e 100644 --- a/relays/ethereum/src/sync_loop_tests.rs +++ b/relays/ethereum/src/sync_loop_tests.rs @@ -408,7 +408,7 @@ fn run_backoff_test(result: Result<(), TestError>) -> (Duration, Duration) { &mut backoff, |_| {}, &mut go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || "Test error".into(), ); diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index e1ea9023ea75b..1e2aca16f7d82 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -95,6 +95,9 @@ pub trait HeadersSyncPipeline: Clone + Copy { fn estimate_size(source: &QueuedHeader) -> usize; } +/// A HeaderId for `HeaderSyncPipeline`. +pub type HeaderIdOf

= HeaderId<

::Hash,

::Number>; + /// Header that we're receiving from source node. pub trait SourceHeader { /// Returns ID of header. diff --git a/relays/substrate/src/bridge.rs b/relays/substrate/src/bridge.rs index c203e85a2e29e..b797005210284 100644 --- a/relays/substrate/src/bridge.rs +++ b/relays/substrate/src/bridge.rs @@ -156,9 +156,10 @@ pub async fn run_async(params: Params, exit: Box + Unpin Ok(()) } -fn initial_next_events<'a>( - chains: &'a HashMap>, -) -> Vec> + 'a>>> { +type EventsResult = Result<(ChainId, RawClientEvent), Error>; +type EventsFuture<'a> = Pin + 'a>>; + +fn initial_next_events<'a>(chains: &'a HashMap>) -> Vec> { chains .values() .map(|chain_cell| async move { @@ -175,12 +176,9 @@ fn initial_next_events<'a>( } async fn next_event<'a>( - next_events: Vec> + 'a>>>, + next_events: Vec>, chains: &'a HashMap>, -) -> ( - Result<(Hash, RawClientEvent), Error>, - Vec> + 'a>>>, -) { +) -> (Result<(Hash, RawClientEvent), Error>, Vec>) { let (result, _, mut rest) = future::select_all(next_events).await; match result { From 03af74aac7c1e1de9936e736b490c20415f0b0be Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 21 Jul 2020 06:16:53 -0400 Subject: [PATCH 0108/1210] Add Prometheus and Grafana to Docker Compose (#221) * Add Prometheus and Grafana to Docker Compose * Expose relay's Prometheus metrics port * Use Docker network references intead of localhost When you have containers on the same network they don't communicate over localhost, they instead refer to their container names * Move dashboard components into deployment folder * Update folder structure for Grafana and Prometheus config files The new folder structure more closely matches the expected defaults by Grafana and Prometheus, which allows us to clean up the paths in our docker-compose file a bit. * Add documentation about Prometheus and Grafana * Refer to Prometheus server instead of node --- README.md | 14 +- .../ethereum/dashboard/grafana-dashboard.json | 410 ------------------ .../ethereum/dashboard/grafana-dashboard.yaml | 6 - .../dashboard/grafana-datasource.yaml | 9 - relays/ethereum/dashboard/prometheus.yml | 9 - 5 files changed, 7 insertions(+), 441 deletions(-) delete mode 100644 relays/ethereum/dashboard/grafana-dashboard.json delete mode 100644 relays/ethereum/dashboard/grafana-dashboard.yaml delete mode 100644 relays/ethereum/dashboard/grafana-datasource.yaml delete mode 100644 relays/ethereum/dashboard/prometheus.yml diff --git a/README.md b/README.md index 8d1d313b15302..381ea37a7d603 100644 --- a/README.md +++ b/README.md @@ -161,10 +161,10 @@ The folder structure of the bridge relay is as follows: To run the Bridge you need to be able to connect to the RPC interface of nodes on each side of the bridge (home & foreign chain). -You can build the relayer using [./Dockerfile](Dockerfile), which will use all the local source -files, +You can build the relayer using [./Dockerfile](Dockerfile), which will use all the local source files, or you can use an image that is designed to build from Github repo sources (`master` branch by default, configurable via `build-arg`): + ```bash docker build \ https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ @@ -173,7 +173,8 @@ docker run -it poa-relay ``` By default the relayer is configured to connect to OpenEthereum `--dev` chain node and Substrate -`bridge-node` running in a `--dev` mode. +`bridge-node` running in `--dev` mode. + To build the `bridge-node`: ```bash docker build \ @@ -184,13 +185,12 @@ docker run -it bridge-node ``` And to build `OpenEthereum` with bridge support: -``` +```bash docker build \ https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/OpenEthereum.Dockerfile -t openethereum -docker run it openethereum +docker run -it openethereum ``` -See [./deployments/README.md](Deployments README) to learn more about how to run +See [Deployments README](./deployments/README.md) to learn more about how to run a more sophisticated test network using `docker-compose` setup. - diff --git a/relays/ethereum/dashboard/grafana-dashboard.json b/relays/ethereum/dashboard/grafana-dashboard.json deleted file mode 100644 index f15fa60ba22a7..0000000000000 --- a/relays/ethereum/dashboard/grafana-dashboard.json +++ /dev/null @@ -1,410 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "links": [], - "panels": [ - { - "datasource": "Prometheus", - "fieldConfig": { - "defaults": { - "custom": { - "align": null - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 2, - "interval": "5s", - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - } - }, - "pluginVersion": "7.0.6", - "targets": [ - { - "expr": "best_block_numbers", - "format": "time_series", - "instant": true, - "interval": "", - "intervalFactor": 1, - "legendFormat": "Best known block on {{node}} node", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Best blocks relay knows of", - "type": "stat" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "Prometheus", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 9, - "w": 6, - "x": 12, - "y": 0 - }, - "hiddenSeries": false, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "system_average_load", - "interval": "", - "legendFormat": "Average system load in last {{over}}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "System load average", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "datasource": "Prometheus", - "fieldConfig": { - "defaults": { - "custom": {}, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 6, - "x": 18, - "y": 0 - }, - "id": 12, - "options": { - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true - }, - "pluginVersion": "7.0.6", - "targets": [ - { - "expr": "process_cpu_usage_percentage", - "interval": "", - "legendFormat": "", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Relay process CPU usage (1 CPU = 100)", - "type": "gauge" - }, - { - "datasource": "Prometheus", - "fieldConfig": { - "defaults": { - "custom": {}, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 11, - "w": 12, - "x": 0, - "y": 6 - }, - "id": 4, - "options": { - "displayMode": "gradient", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "mean" - ], - "fields": "", - "values": false - }, - "showUnfilled": true - }, - "pluginVersion": "7.0.6", - "targets": [ - { - "expr": "blocks_in_state", - "instant": true, - "interval": "", - "legendFormat": "{{state}}", - "refId": "A" - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Blocks in state on relay", - "type": "bargauge" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "Prometheus", - "fieldConfig": { - "defaults": { - "custom": {} - }, - "overrides": [] - }, - "fill": 1, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 9 - }, - "hiddenSeries": false, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "process_memory_usage_bytes / 1024 / 1024", - "interval": "", - "legendFormat": "Process memory, MB", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Memory used by relay process", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": "5s", - "schemaVersion": 25, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-5m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "RelayDashboard", - "uid": "oj3y7vnGz", - "version": 1 -} \ No newline at end of file diff --git a/relays/ethereum/dashboard/grafana-dashboard.yaml b/relays/ethereum/dashboard/grafana-dashboard.yaml deleted file mode 100644 index f66dff441311b..0000000000000 --- a/relays/ethereum/dashboard/grafana-dashboard.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- name: 'default' - orgId: 1 - folder: '' - type: file - options: - path: '/etc/grafana/provisioning/dashboards/grafana-dashboard.json' \ No newline at end of file diff --git a/relays/ethereum/dashboard/grafana-datasource.yaml b/relays/ethereum/dashboard/grafana-datasource.yaml deleted file mode 100644 index ed77109fdb8e6..0000000000000 --- a/relays/ethereum/dashboard/grafana-datasource.yaml +++ /dev/null @@ -1,9 +0,0 @@ -datasources: - - name: Prometheus - type: prometheus - access: proxy - orgId: 1 - url: http://localhost:9090 - editable: false - is_default: true - version: 1 \ No newline at end of file diff --git a/relays/ethereum/dashboard/prometheus.yml b/relays/ethereum/dashboard/prometheus.yml deleted file mode 100644 index 572b62d1ac553..0000000000000 --- a/relays/ethereum/dashboard/prometheus.yml +++ /dev/null @@ -1,9 +0,0 @@ -scrape_configs: - # The job name is added as a label `job=` to any timeseries scraped from this config. - - job_name: 'relay_node' - - # Override the global default and scrape targets from this job every 5 seconds. - scrape_interval: 5s - - static_configs: - - targets: ['127.0.0.1:9616'] From 8a53561637a2754c1e270d7d1e96dbce79b0859d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2020 02:34:15 +0000 Subject: [PATCH 0109/1210] Bump sysinfo from 0.14.13 to 0.15.0 (#234) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 39a9c038aed40..8b467e0c6fe5a 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -28,7 +28,7 @@ parking_lot = "0.11.0" rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.56" -sysinfo = "0.14" +sysinfo = "0.15" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = "0.13" From c9c162190c811c7eb9eaf9c59360f5b1b758a619 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2020 03:21:44 +0000 Subject: [PATCH 0110/1210] Bump serde_json from 1.0.56 to 1.0.57 (#235) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8b467e0c6fe5a..027d471e69e22 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -27,7 +27,7 @@ parity-crypto = { version = "0.6", features = ["publickey"] } parking_lot = "0.11.0" rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.56" +serde_json = "1.0.57" sysinfo = "0.15" sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 83f191af1e678..8ee475be613f3 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -14,7 +14,7 @@ env_logger = "0.7.1" futures = "0.3.5" jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } log = "0.4.11" -serde_json = "1.0.56" +serde_json = "1.0.57" url = "2.1.0" [dependencies.sp-core] From 91f681cd39dde481eabab4f601038623d775c192 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Jul 2020 14:58:14 +0300 Subject: [PATCH 0111/1210] Auto relay exchange transactions (#227) * auto relay exchange transactions * docker + auto-relay-tx * clippy * jsonrpsee in Cargo.lock ??? * fix tests compilation * Show sccache * mute clippy * move * Update relays/ethereum/src/exchange.rs Co-authored-by: Hernando Castano * finish comment * (bool, String) -> StringifiedMaybeConnectionError * Update deployments/rialto/docker-compose.yml Co-authored-by: Hernando Castano Co-authored-by: Denis S. Soldatov aka General-Beck Co-authored-by: Hernando Castano --- bin/node/runtime/src/lib.rs | 6 + modules/currency-exchange/src/lib.rs | 72 ++- primitives/currency-exchange/Cargo.toml | 7 + primitives/currency-exchange/src/lib.rs | 16 +- relays/ethereum/Cargo.toml | 1 + relays/ethereum/src/cli.yml | 8 +- relays/ethereum/src/ethereum_client.rs | 17 + relays/ethereum/src/ethereum_exchange.rs | 220 ++++++-- relays/ethereum/src/exchange.rs | 687 ++++++++++++++++++----- relays/ethereum/src/exchange_loop.rs | 267 +++++++++ relays/ethereum/src/main.rs | 21 +- relays/ethereum/src/rpc.rs | 4 + relays/ethereum/src/rpc_errors.rs | 13 - relays/ethereum/src/substrate_client.rs | 21 +- relays/ethereum/src/sync_loop.rs | 13 +- relays/ethereum/src/sync_loop_tests.rs | 3 +- relays/ethereum/src/utils.rs | 16 + 17 files changed, 1163 insertions(+), 229 deletions(-) create mode 100644 relays/ethereum/src/exchange_loop.rs diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d77b54764438a..9f473fee9d8ba 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -555,6 +555,12 @@ impl_runtime_apis! { } } + impl sp_currency_exchange::CurrencyExchangeApi for Runtime { + fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { + BridgeCurrencyExchange::filter_transaction_proof(&proof) + } + } + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( source: TransactionSource, diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 12d8657cab2fb..1c39e1aea9323 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -105,36 +105,21 @@ decl_module! { ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; - // ensure that transaction is included in finalized block that we know of - let transaction = ::PeerBlockchain::verify_transaction_inclusion_proof( - &proof, - ).ok_or_else(|| Error::::UnfinalizedTransaction)?; - - // parse transaction - let transaction = ::PeerMaybeLockFundsTransaction::parse(&transaction) - .map_err(Error::::from)?; - let transfer_id = transaction.id; - ensure!( - !Transfers::::contains_key(&transfer_id), - Error::::AlreadyClaimed - ); - - // grant recipient - let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; - let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; + // verify and parse transaction proof + let deposit = prepare_deposit_details::(&proof)?; // make sure to update the mapping if we deposit successfully to avoid double spending, // i.e. whenever `deposit_into` is successful we MUST update `Transfers`. { // if any changes were made to the storage, we can't just return error here, because // otherwise the same proof may be imported again - let deposit_result = T::DepositInto::deposit_into(recipient, amount); + let deposit_result = T::DepositInto::deposit_into(deposit.recipient, deposit.amount); match deposit_result { Ok(_) => (), Err(ExchangeError::DepositPartiallyFailed) => (), Err(error) => return Err(Error::::from(error).into()), } - Transfers::::insert(&transfer_id, ()) + Transfers::::insert(&deposit.transfer_id, ()) } // reward submitter for providing valid message @@ -143,7 +128,7 @@ decl_module! { frame_support::debug::trace!( target: "runtime", "Completed currency exchange: {:?}", - transfer_id, + deposit.transfer_id, ); Ok(()) @@ -158,6 +143,18 @@ decl_storage! { } } +impl Module { + /// Returns true if currency exchange module is able to import given transaction proof in + /// its current state. + pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { + if prepare_deposit_details::(proof).is_err() { + return false; + } + + true + } +} + impl From for Error { fn from(error: ExchangeError) -> Self { match error { @@ -176,6 +173,41 @@ impl OnTransactionSubmitted for () { fn on_valid_transaction_submitted(_: AccountId) {} } +/// Exchange deposit details. +struct DepositDetails { + /// Transfer id. + pub transfer_id: ::Id, + /// Transfer recipient. + pub recipient: ::Recipient, + /// Transfer amount. + pub amount: ::TargetAmount, +} + +/// Verify and parse transaction proof, preparing everything required for importing +/// this transaction proof. +fn prepare_deposit_details( + proof: &<::PeerBlockchain as Blockchain>::TransactionInclusionProof, +) -> Result, Error> { + // ensure that transaction is included in finalized block that we know of + let transaction = ::PeerBlockchain::verify_transaction_inclusion_proof(proof) + .ok_or_else(|| Error::::UnfinalizedTransaction)?; + + // parse transaction + let transaction = ::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; + let transfer_id = transaction.id; + ensure!(!Transfers::::contains_key(&transfer_id), Error::::AlreadyClaimed); + + // grant recipient + let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; + let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; + + Ok(DepositDetails { + transfer_id, + recipient, + amount, + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 4cdba7ec1398f..198d4ad531ed4 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -11,6 +11,12 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies +[dependencies.sp-api] +version = "2.0.0-rc4" +tag = 'v2.0.0-rc4' +default-features = false +git = "https://github.com/paritytech/substrate.git" + [dependencies.sp-std] version = "2.0.0-rc4" tag = 'v2.0.0-rc4' @@ -27,6 +33,7 @@ git = "https://github.com/paritytech/substrate.git" default = ["std"] std = [ "codec/std", + "sp-api/std", "sp-std/std", "frame-support/std", ] diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index 00836dee23bf5..28a3afd080803 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -15,9 +15,14 @@ // along with Parity Bridges Common. If not, see . #![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Generated by `DecodeLimit::decode_with_depth_limit` +#![allow(clippy::unnecessary_mut_passed)] use codec::{Decode, Encode, EncodeLike}; -use frame_support::RuntimeDebug; +use frame_support::{Parameter, RuntimeDebug}; +use sp_api::decl_runtime_apis; use sp_std::marker::PhantomData; /// All errors that may happen during exchange. @@ -127,3 +132,12 @@ impl CurrencyConverter for IdentityCurrencyConverter { Ok(currency) } } + +decl_runtime_apis! { + /// API for exchange transactions submitters. + pub trait CurrencyExchangeApi { + /// Returns true if currency exchange module is able to import transaction proof in + /// its current state. + fn filter_transaction_proof(proof: Proof) -> bool; + } +} diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 027d471e69e22..cd39d6ea44531 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -29,6 +29,7 @@ rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" sysinfo = "0.15" +sp-currency-exchange = { path = "../../primitives/currency-exchange" } sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = "0.13" diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 988af146a7c53..2026da39ef465 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -111,12 +111,18 @@ subcommands: args: - eth-host: *eth-host - eth-port: *eth-port + - eth-start-with-block: + long: eth-start-with-block + value_name: ETH_START_WITH_BLOCK + help: Auto-relay transactions starting with given block number. If not specified, starts with best finalized Ethereum block (known to Substrate node) transactions. + takes_value: true + conflicts_with: + - eth-tx-hash - eth-tx-hash: long: eth-tx-hash value_name: ETH_TX_HASH help: Hash of the lock funds transaction. takes_value: true - required: true - sub-host: *sub-host - sub-port: *sub-port - sub-signer: *sub-signer diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index e23f1e5c5a8ef..aba5d1ca74318 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -129,6 +129,23 @@ impl EthereumRpc for EthereumRpcClient { } } + async fn header_by_number_with_transactions(&self, number: u64) -> Result { + let get_full_tx_objects = true; + let header = Ethereum::get_block_by_number_with_transactions(&self.client, number, get_full_tx_objects).await?; + + let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + if !is_complete_header { + return Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)); + } + + let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); + if !is_complete_transactions { + return Err(RpcError::Ethereum(EthereumNodeError::IncompleteTransaction)); + } + + Ok(header) + } + async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { let get_full_tx_objects = true; let header = Ethereum::get_block_by_hash_with_transactions(&self.client, hash, get_full_tx_objects).await?; diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 95ded39f60cd5..d27f3345e8a6a 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -18,11 +18,16 @@ use crate::ethereum_client::{EthereumConnectionParams, EthereumRpcClient}; use crate::ethereum_types::{ - EthereumHeaderId, Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, + EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, Transaction as EthereumTransaction, + TransactionHash as EthereumTransactionHash, H256, }; -use crate::exchange::{relay_single_transaction_proof, SourceClient, TargetClient, TransactionProofPipeline}; +use crate::exchange::{ + relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, + TransactionProofPipeline, +}; +use crate::exchange_loop::{run as run_loop, InMemoryStorage}; use crate::rpc::{EthereumRpc, SubstrateRpc}; -use crate::rpc_errors::{EthereumNodeError, RpcError}; +use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; @@ -30,6 +35,7 @@ use crate::sync_types::HeaderId; use async_trait::async_trait; use bridge_node_runtime::exchange::EthereumTransactionInclusionProof; +use sp_currency_exchange::MaybeLockFundsTransaction; use std::time::Duration; /// Interval at which we ask Ethereum node for updates. @@ -37,17 +43,26 @@ const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); /// Interval at which we ask Substrate node for updates. const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); +/// Exchange relay mode. +#[derive(Debug)] +pub enum ExchangeRelayMode { + /// Relay single transaction and quit. + Single(EthereumTransactionHash), + /// Auto-relay transactions starting with given block. + Auto(Option), +} + /// PoA exchange transaction relay params. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct EthereumExchangeParams { /// Ethereum connection params. pub eth: EthereumConnectionParams, - /// Hash of the Ethereum transaction to relay. - pub eth_tx_hash: EthereumTransactionHash, /// Substrate connection params. pub sub: SubstrateConnectionParams, /// Substrate signing params. pub sub_sign: SubstrateSigningParams, + /// Relay working mode. + pub mode: ExchangeRelayMode, } /// Ethereum to Substrate exchange pipeline. @@ -57,13 +72,46 @@ impl TransactionProofPipeline for EthereumToSubstrateExchange { const SOURCE_NAME: &'static str = "Ethereum"; const TARGET_NAME: &'static str = "Substrate"; - type BlockHash = H256; - type BlockNumber = u64; - type TransactionHash = EthereumTransactionHash; - type Transaction = EthereumTransaction; + type Block = EthereumSourceBlock; type TransactionProof = EthereumTransactionInclusionProof; } +/// Ethereum source block. +struct EthereumSourceBlock(EthereumHeaderWithTransactions); + +impl SourceBlock for EthereumSourceBlock { + type Hash = H256; + type Number = u64; + type Transaction = EthereumSourceTransaction; + + fn id(&self) -> EthereumHeaderId { + HeaderId( + self.0.number.expect(crate::ethereum_types::HEADER_ID_PROOF).as_u64(), + self.0.hash.expect(crate::ethereum_types::HEADER_ID_PROOF), + ) + } + + fn transactions(&self) -> Vec { + self.0 + .transactions + .iter() + .cloned() + .map(EthereumSourceTransaction) + .collect() + } +} + +/// Ethereum source transaction. +struct EthereumSourceTransaction(EthereumTransaction); + +impl SourceTransaction for EthereumSourceTransaction { + type Hash = EthereumTransactionHash; + + fn hash(&self) -> Self::Hash { + self.0.hash + } +} + /// Ethereum node as transactions proof source. struct EthereumTransactionsSource { client: EthereumRpcClient, @@ -77,63 +125,60 @@ impl SourceClient for EthereumTransactionsSource { async_std::task::sleep(ETHEREUM_TICK_INTERVAL).await; } - async fn transaction( + async fn block_by_hash(&self, hash: H256) -> Result { + self.client + .header_by_hash_with_transactions(hash) + .await + .map(EthereumSourceBlock) + } + + async fn block_by_number(&self, number: u64) -> Result { + self.client + .header_by_number_with_transactions(number) + .await + .map(EthereumSourceBlock) + } + + async fn transaction_block( &self, hash: &EthereumTransactionHash, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let eth_tx = match self.client.transaction_by_hash(*hash).await? { Some(eth_tx) => eth_tx, None => return Ok(None), }; // we need transaction to be mined => check if it is included in the block - let eth_header_id = match (eth_tx.block_number, eth_tx.block_hash) { - (Some(block_number), Some(block_hash)) => HeaderId(block_number.as_u64(), block_hash), + let (eth_header_id, eth_tx_index) = match (eth_tx.block_number, eth_tx.block_hash, eth_tx.transaction_index) { + (Some(block_number), Some(block_hash), Some(transaction_index)) => ( + HeaderId(block_number.as_u64(), block_hash), + transaction_index.as_u64() as _, + ), _ => return Ok(None), }; - Ok(Some((eth_header_id, eth_tx))) + Ok(Some((eth_header_id, eth_tx_index))) } async fn transaction_proof( &self, - eth_header_id: &EthereumHeaderId, - eth_tx: EthereumTransaction, + block: &EthereumSourceBlock, + tx_index: usize, ) -> Result { const TRANSACTION_HAS_RAW_FIELD_PROOF: &str = "RPC level checks that transactions from Ethereum\ node are having `raw` field; qed"; + const BLOCK_HAS_HASH_FIELD_PROOF: &str = "RPC level checks that block has `hash` field; qed"; - let eth_header = self.client.header_by_hash_with_transactions(eth_header_id.1).await?; - let eth_relay_tx_hash = eth_tx.hash; - let mut eth_relay_tx = Some(eth_tx); - let mut eth_relay_tx_index = None; - let mut transaction_proof = Vec::with_capacity(eth_header.transactions.len()); - for (index, eth_tx) in eth_header.transactions.into_iter().enumerate() { - if eth_tx.hash != eth_relay_tx_hash { - let eth_raw_tx = eth_tx.raw.expect(TRANSACTION_HAS_RAW_FIELD_PROOF); - transaction_proof.push(eth_raw_tx.0); - } else { - let eth_raw_relay_tx = match eth_relay_tx.take() { - Some(eth_relay_tx) => eth_relay_tx.raw.expect(TRANSACTION_HAS_RAW_FIELD_PROOF), - None => { - return Err( - EthereumNodeError::DuplicateBlockTransaction(*eth_header_id, eth_relay_tx_hash).into(), - ) - } - }; - eth_relay_tx_index = Some(index as u64); - transaction_proof.push(eth_raw_relay_tx.0); - } - } + let transaction_proof = block + .0 + .transactions + .iter() + .map(|tx| tx.raw.clone().expect(TRANSACTION_HAS_RAW_FIELD_PROOF).0) + .collect(); Ok(EthereumTransactionInclusionProof { - block: eth_header_id.1, - index: eth_relay_tx_index.ok_or_else(|| { - RpcError::from(EthereumNodeError::BlockMissingTransaction( - *eth_header_id, - eth_relay_tx_hash, - )) - })?, + block: block.0.hash.expect(BLOCK_HAS_HASH_FIELD_PROOF), + index: tx_index as _, proof: transaction_proof, }) } @@ -170,15 +215,51 @@ impl TargetClient for SubstrateTransactionsTarget { Ok(id.0 <= best_finalized_ethereum_block.0) } + async fn best_finalized_header_id(&self) -> Result { + self.client.best_ethereum_finalized_block().await + } + + async fn filter_transaction_proof(&self, proof: &EthereumTransactionInclusionProof) -> Result { + // let's try to parse transaction locally + let parse_result = bridge_node_runtime::exchange::EthTransaction::parse(&proof.proof[proof.index as usize]); + if parse_result.is_err() { + return Ok(false); + } + + // seems that transaction is relayable - let's check if runtime is able to import it + // (we can't if e.g. header is pruned or there's some issue with tx data) + self.client.verify_exchange_transaction_proof(proof.clone()).await + } + async fn submit_transaction_proof(&self, proof: EthereumTransactionInclusionProof) -> Result<(), Self::Error> { let sign_params = self.sign_params.clone(); self.client.submit_exchange_transaction_proof(sign_params, proof).await } } -/// Relay exchange transaction proof to Substrate node. +impl Default for EthereumExchangeParams { + fn default() -> Self { + EthereumExchangeParams { + eth: Default::default(), + sub: Default::default(), + sub_sign: Default::default(), + mode: ExchangeRelayMode::Auto(None), + } + } +} + +/// Relay exchange transaction proof(s) to Substrate node. pub fn run(params: EthereumExchangeParams) { - let eth_tx_hash = params.eth_tx_hash; + match params.mode { + ExchangeRelayMode::Single(eth_tx_hash) => run_single_transaction_relay(params, eth_tx_hash), + ExchangeRelayMode::Auto(eth_start_with_block_number) => { + run_auto_transactions_relay_loop(params, eth_start_with_block_number) + } + }; +} + +/// Run single transaction proof relay and stop. +fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) { let mut local_pool = futures::executor::LocalPool::new(); let result = local_pool.run_until(async move { @@ -212,3 +293,46 @@ pub fn run(params: EthereumExchangeParams) { } } } + +/// Run auto-relay loop. +fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_with_block_number: Option) { + let do_run_loop = move || -> Result<(), String> { + let eth_client = EthereumRpcClient::new(params.eth); + let sub_client = async_std::task::block_on(SubstrateRpcClient::new(params.sub)) + .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; + + let eth_start_with_block_number = match eth_start_with_block_number { + Some(eth_start_with_block_number) => eth_start_with_block_number, + None => { + async_std::task::block_on(sub_client.best_ethereum_finalized_block()) + .map_err(|err| { + format!( + "Error retrieving best finalized Ethereum block from Substrate node: {:?}", + err + ) + })? + .0 + } + }; + + run_loop( + InMemoryStorage::new(eth_start_with_block_number), + EthereumTransactionsSource { client: eth_client }, + SubstrateTransactionsTarget { + client: sub_client, + sign_params: params.sub_sign, + }, + futures::future::pending(), + ); + + Ok(()) + }; + + if let Err(err) = do_run_loop() { + log::error!( + target: "bridge", + "Error auto-relaying Ethereum transactions proofs to Substrate node: {}", + err, + ); + } +} diff --git a/relays/ethereum/src/exchange.rs b/relays/ethereum/src/exchange.rs index 352e53fe6cb3a..4de47e5975053 100644 --- a/relays/ethereum/src/exchange.rs +++ b/relays/ethereum/src/exchange.rs @@ -14,10 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Relaying proofs of exchange transactions. +//! Relaying proofs of exchange transaction. + +use crate::sync_types::MaybeConnectionError; use async_trait::async_trait; -use std::fmt::{Debug, Display}; +use std::{ + fmt::{Debug, Display}, + string::ToString, +}; /// Transaction proof pipeline. pub trait TransactionProofPipeline { @@ -26,50 +31,76 @@ pub trait TransactionProofPipeline { /// Name of the transaction proof target. const TARGET_NAME: &'static str; + /// Block type. + type Block: SourceBlock; + /// Transaction inclusion proof type. + type TransactionProof; +} + +/// Block that is participating in exchange. +pub trait SourceBlock { /// Block hash type. - type BlockHash: Display; + type Hash: Clone + Debug + Display; /// Block number type. - type BlockNumber: Display; + type Number: Debug + Display + Clone + Copy + std::cmp::Ord + std::ops::Add + num_traits::One; + /// Block transaction. + type Transaction: SourceTransaction; + + /// Return hash of the block. + fn id(&self) -> crate::sync_types::HeaderId; + /// Return block transactions iterator. + fn transactions(&self) -> Vec; +} + +/// Transaction that is participating in exchange. +pub trait SourceTransaction { /// Transaction hash type. - type TransactionHash: Display; - /// Transaction type. - type Transaction; - /// Transaction inclusion proof type. - type TransactionProof; + type Hash: Debug + Display; + + /// Return transaction hash. + fn hash(&self) -> Self::Hash; } +/// Block hash for given pipeline. +pub type BlockHashOf

= <

::Block as SourceBlock>::Hash; + +/// Block number for given pipeline. +pub type BlockNumberOf

= <

::Block as SourceBlock>::Number; + +/// Transaction hash for given pipeline. +pub type TransactionOf

= <

::Block as SourceBlock>::Transaction; + +/// Transaction hash for given pipeline. +pub type TransactionHashOf

= as SourceTransaction>::Hash; + /// Header id. -pub type HeaderId

= crate::sync_types::HeaderId< -

::BlockHash, -

::BlockNumber, ->; +pub type HeaderId

= crate::sync_types::HeaderId, BlockNumberOf

>; /// Source client API. #[async_trait] pub trait SourceClient { /// Error type. - type Error: Debug; + type Error: Debug + MaybeConnectionError; /// Sleep until exchange-related data is (probably) updated. async fn tick(&self); - /// Return **mined** transaction by its hash. May return `Ok(None)` if transaction is unknown to the source node. - async fn transaction( - &self, - hash: &P::TransactionHash, - ) -> Result, P::Transaction)>, Self::Error>; + /// Get block by hash. + async fn block_by_hash(&self, hash: BlockHashOf

) -> Result; + /// Get canonical block by number. + async fn block_by_number(&self, number: BlockNumberOf

) -> Result; + /// Return block + index where transaction has been **mined**. May return `Ok(None)` if transaction + /// is unknown to the source node. + async fn transaction_block(&self, hash: &TransactionHashOf

) + -> Result, usize)>, Self::Error>; /// Prepare transaction proof. - async fn transaction_proof( - &self, - header: &HeaderId

, - transaction: P::Transaction, - ) -> Result; + async fn transaction_proof(&self, block: &P::Block, tx_index: usize) -> Result; } /// Target client API. #[async_trait] pub trait TargetClient { /// Error type. - type Error: Debug; + type Error: Debug + MaybeConnectionError; /// Sleep until exchange-related data is (probably) updated. async fn tick(&self); @@ -77,44 +108,209 @@ pub trait TargetClient { async fn is_header_known(&self, id: &HeaderId

) -> Result; /// Returns `Ok(true)` if header is finalized by the target node. async fn is_header_finalized(&self, id: &HeaderId

) -> Result; + /// Returns best finalized header id. + async fn best_finalized_header_id(&self) -> Result, Self::Error>; + /// Returns `Ok(true)` if transaction proof is need to be relayed. + async fn filter_transaction_proof(&self, proof: &P::TransactionProof) -> Result; /// Submits transaction proof to the target node. async fn submit_transaction_proof(&self, proof: P::TransactionProof) -> Result<(), Self::Error>; } +/// Block transaction statistics. +#[derive(Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] +pub struct RelayedBlockTransactions { + /// Total number of transactions processed (either relayed or ignored) so far. + pub processed: usize, + /// Total number of transactions successfully relayed so far. + pub relayed: usize, + /// Total number of transactions that we have failed to relay so far. + pub failed: usize, +} + +/// Stringified error that may be either connection-related or not. +enum StringifiedMaybeConnectionError { + /// The error is connection-related error. + Connection(String), + /// The error is connection-unrelated error. + NonConnection(String), +} + +/// Relay all suitable transactions from single block. +/// +/// If connection error occurs, returns Err with number of successfully processed transactions. +/// If some other error occurs, it is ignored and other transactions are processed. +/// +/// All transaction-level traces are written by this function. This function is not tracing +/// any information about block. +pub async fn relay_block_transactions( + source_client: &impl SourceClient

, + target_client: &impl TargetClient

, + source_block: &P::Block, + mut relayed_transactions: RelayedBlockTransactions, +) -> Result { + let transactions_to_process = source_block + .transactions() + .into_iter() + .enumerate() + .skip(relayed_transactions.processed); + for (source_tx_index, source_tx) in transactions_to_process { + let result = async { + let source_tx_id = format!("{}/{}", source_block.id().1, source_tx_index); + let source_tx_proof = + prepare_transaction_proof(source_client, &source_tx_id, source_block, source_tx_index).await?; + + let needs_to_be_relayed = + target_client + .filter_transaction_proof(&source_tx_proof) + .await + .map_err(|err| { + StringifiedMaybeConnectionError::new( + err.is_connection_error(), + format!("Transaction filtering has failed with {:?}", err), + ) + })?; + + if !needs_to_be_relayed { + return Ok(false); + } + + relay_ready_transaction_proof(target_client, &source_tx_id, source_tx_proof) + .await + .map(|_| true) + } + .await; + + // We have two options here: + // 1) retry with the same transaction later; + // 2) report error and proceed with next transaction. + // + // Option#1 may seems better, but: + // 1) we do not track if transaction is mined (without an error) by the target node; + // 2) error could be irrecoverable (e.g. when block is already pruned by bridge module or tx + // has invalid format) && we'll end up in infinite loop of retrying the same transaction proof. + // + // So we're going with option#2 here (the only exception are connection errors). + match result { + Ok(false) => { + relayed_transactions.processed += 1; + } + Ok(true) => { + log::info!( + target: "bridge", + "{} transaction {} proof has been successfully submitted to {} node", + P::SOURCE_NAME, + source_tx.hash(), + P::TARGET_NAME, + ); + + relayed_transactions.processed += 1; + relayed_transactions.relayed += 1; + } + Err(err) => { + log::error!( + target: "bridge", + "Error relaying {} transaction {} proof to {} node: {}. {}", + P::SOURCE_NAME, + source_tx.hash(), + P::TARGET_NAME, + err.to_string(), + if err.is_connection_error() { + "Going to retry after delay..." + } else { + "You may need to submit proof of this transaction manually" + }, + ); + + if err.is_connection_error() { + return Err(relayed_transactions); + } + + relayed_transactions.processed += 1; + relayed_transactions.failed += 1; + } + } + } + + Ok(relayed_transactions) +} + /// Relay single transaction proof. pub async fn relay_single_transaction_proof( source_client: &impl SourceClient

, target_client: &impl TargetClient

, - source_tx_hash: P::TransactionHash, + source_tx_hash: TransactionHashOf

, ) -> Result<(), String> { // wait for transaction and header on source node - let (source_header_id, source_tx) = wait_transaction_mined(source_client, &source_tx_hash).await?; - let transaction_proof = source_client - .transaction_proof(&source_header_id, source_tx) - .await - .map_err(|err| { - format!( - "Error building transaction {} proof on {} node: {:?}", - source_tx_hash, - P::SOURCE_NAME, - err, - ) - })?; + let (source_header_id, source_tx_index) = wait_transaction_mined(source_client, &source_tx_hash).await?; + let source_block = source_client.block_by_hash(source_header_id.1.clone()).await; + let source_block = source_block.map_err(|err| { + format!( + "Error retrieving block {} from {} node: {:?}", + source_header_id.1, + P::SOURCE_NAME, + err, + ) + })?; // wait for transaction and header on target node wait_header_imported(target_client, &source_header_id).await?; wait_header_finalized(target_client, &source_header_id).await?; - // and finally - submit transaction proof to target node + // and finally - prepare and submit transaction proof to target node + let source_tx_id = format!("{}", source_tx_hash); + relay_ready_transaction_proof( + target_client, + &source_tx_id, + prepare_transaction_proof(source_client, &source_tx_id, &source_block, source_tx_index) + .await + .map_err(|err| err.to_string())?, + ) + .await + .map_err(|err| err.to_string()) +} + +/// Prepare transaction proof. +async fn prepare_transaction_proof( + source_client: &impl SourceClient

, + source_tx_id: &str, + source_block: &P::Block, + source_tx_index: usize, +) -> Result { + source_client + .transaction_proof(source_block, source_tx_index) + .await + .map_err(|err| { + StringifiedMaybeConnectionError::new( + err.is_connection_error(), + format!( + "Error building transaction {} proof on {} node: {:?}", + source_tx_id, + P::SOURCE_NAME, + err, + ), + ) + }) +} + +/// Relay prepared proof of transaction. +async fn relay_ready_transaction_proof( + target_client: &impl TargetClient

, + source_tx_id: &str, + source_tx_proof: P::TransactionProof, +) -> Result<(), StringifiedMaybeConnectionError> { target_client - .submit_transaction_proof(transaction_proof) + .submit_transaction_proof(source_tx_proof) .await .map_err(|err| { - format!( - "Error submitting transaction {} proof to {} node: {:?}", - source_tx_hash, - P::TARGET_NAME, - err, + StringifiedMaybeConnectionError::new( + err.is_connection_error(), + format!( + "Error submitting transaction {} proof to {} node: {:?}", + source_tx_id, + P::TARGET_NAME, + err, + ), ) }) } @@ -122,10 +318,10 @@ pub async fn relay_single_transaction_proof( /// Wait until transaction is mined by source node. async fn wait_transaction_mined( source_client: &impl SourceClient

, - source_tx_hash: &P::TransactionHash, -) -> Result<(HeaderId

, P::Transaction), String> { + source_tx_hash: &TransactionHashOf

, +) -> Result<(HeaderId

, usize), String> { loop { - let source_header_and_tx = source_client.transaction(&source_tx_hash).await.map_err(|err| { + let source_header_and_tx = source_client.transaction_block(&source_tx_hash).await.map_err(|err| { format!( "Error retrieving transaction {} from {} node: {:?}", source_tx_hash, @@ -245,68 +441,144 @@ async fn wait_header_finalized( } } +impl StringifiedMaybeConnectionError { + fn new(is_connection_error: bool, error: String) -> Self { + if is_connection_error { + StringifiedMaybeConnectionError::Connection(error) + } else { + StringifiedMaybeConnectionError::NonConnection(error) + } + } +} + +impl MaybeConnectionError for StringifiedMaybeConnectionError { + fn is_connection_error(&self) -> bool { + match *self { + StringifiedMaybeConnectionError::Connection(_) => true, + StringifiedMaybeConnectionError::NonConnection(_) => false, + } + } +} + +impl ToString for StringifiedMaybeConnectionError { + fn to_string(&self) -> String { + match *self { + StringifiedMaybeConnectionError::Connection(ref err) => err.clone(), + StringifiedMaybeConnectionError::NonConnection(ref err) => err.clone(), + } + } +} + #[cfg(test)] -mod tests { +pub(crate) mod tests { use super::*; use crate::sync_types::HeaderId; use parking_lot::Mutex; + use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + }; + + pub fn test_block_id() -> TestHeaderId { + HeaderId(1, 1) + } - fn test_header_id() -> TestHeaderId { - HeaderId(100, 100) + pub fn test_next_block_id() -> TestHeaderId { + HeaderId(2, 2) } - fn test_transaction_hash() -> TestTransactionHash { - 200 + pub fn test_transaction_hash(tx_index: u64) -> TestTransactionHash { + 200 + tx_index } - fn test_transaction() -> TestTransaction { - 300 + pub fn test_transaction(tx_index: u64) -> TestTransaction { + TestTransaction(test_transaction_hash(tx_index)) } - fn test_transaction_proof() -> TestTransactionProof { - 400 + pub fn test_block() -> TestBlock { + TestBlock(test_block_id(), vec![test_transaction(0)]) } - type TestError = u64; - type TestBlockNumber = u64; - type TestBlockHash = u64; - type TestTransactionHash = u64; - type TestTransaction = u64; - type TestTransactionProof = u64; - type TestHeaderId = HeaderId; + pub fn test_next_block() -> TestBlock { + TestBlock(test_next_block_id(), vec![test_transaction(1)]) + } + + pub type TestBlockNumber = u64; + pub type TestBlockHash = u64; + pub type TestTransactionHash = u64; + pub type TestHeaderId = HeaderId; - struct TestTransactionProofPipeline; + #[derive(Debug, Clone, PartialEq)] + pub struct TestError(pub bool); + + impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + self.0 + } + } + + pub struct TestTransactionProofPipeline; impl TransactionProofPipeline for TestTransactionProofPipeline { const SOURCE_NAME: &'static str = "TestSource"; const TARGET_NAME: &'static str = "TestTarget"; - type BlockHash = TestBlockHash; - type BlockNumber = TestBlockNumber; - type TransactionHash = TestTransactionHash; - type Transaction = TestTransaction; + type Block = TestBlock; type TransactionProof = TestTransactionProof; } - struct TestTransactionsSource { - on_tick: Box, - data: Mutex, + #[derive(Debug, Clone)] + pub struct TestBlock(pub TestHeaderId, pub Vec); + + impl SourceBlock for TestBlock { + type Hash = TestBlockHash; + type Number = TestBlockNumber; + type Transaction = TestTransaction; + + fn id(&self) -> TestHeaderId { + self.0 + } + + fn transactions(&self) -> Vec { + self.1.clone() + } } - struct TestTransactionsSourceData { - transaction: Result, TestError>, - transaction_proof: Result, + #[derive(Debug, Clone)] + pub struct TestTransaction(pub TestTransactionHash); + + impl SourceTransaction for TestTransaction { + type Hash = TestTransactionHash; + + fn hash(&self) -> Self::Hash { + self.0 + } + } + + #[derive(Debug, Clone, PartialEq)] + pub struct TestTransactionProof(pub TestTransactionHash); + + pub struct TestTransactionsSource { + pub on_tick: Box, + pub data: Arc>, + } + + pub struct TestTransactionsSourceData { + pub block: Result, + pub transaction_block: Result, TestError>, + pub proofs_to_fail: HashMap, } impl TestTransactionsSource { - fn new(on_tick: Box) -> Self { + pub fn new(on_tick: Box) -> Self { Self { on_tick, - data: Mutex::new(TestTransactionsSourceData { - transaction: Ok(Some((test_header_id(), test_transaction()))), - transaction_proof: Ok(test_transaction_proof()), - }), + data: Arc::new(Mutex::new(TestTransactionsSourceData { + block: Ok(test_block()), + transaction_block: Ok(Some((test_block_id(), 0))), + proofs_to_fail: HashMap::new(), + })), } } } @@ -319,42 +591,53 @@ mod tests { (self.on_tick)(&mut *self.data.lock()) } - async fn transaction( - &self, - _: &TestTransactionHash, - ) -> Result, TestError> { - self.data.lock().transaction + async fn block_by_hash(&self, _: TestBlockHash) -> Result { + self.data.lock().block.clone() + } + + async fn block_by_number(&self, _: TestBlockNumber) -> Result { + self.data.lock().block.clone() } - async fn transaction_proof( - &self, - _: &TestHeaderId, - _: TestTransaction, - ) -> Result { - self.data.lock().transaction_proof + async fn transaction_block(&self, _: &TestTransactionHash) -> Result, TestError> { + self.data.lock().transaction_block.clone() + } + + async fn transaction_proof(&self, block: &TestBlock, index: usize) -> Result { + let tx_hash = block.1[index].hash(); + let proof_error = self.data.lock().proofs_to_fail.get(&tx_hash).cloned(); + if let Some(err) = proof_error { + return Err(err); + } + + Ok(TestTransactionProof(tx_hash)) } } - struct TestTransactionsTarget { - on_tick: Box, - data: Mutex, + pub struct TestTransactionsTarget { + pub on_tick: Box, + pub data: Arc>, } - struct TestTransactionsTargetData { - is_header_known: Result, - is_header_finalized: Result, - submitted_proofs: Vec, + pub struct TestTransactionsTargetData { + pub is_header_known: Result, + pub is_header_finalized: Result, + pub best_finalized_header_id: Result, + pub transactions_to_accept: HashSet, + pub submitted_proofs: Vec, } impl TestTransactionsTarget { - fn new(on_tick: Box) -> Self { + pub fn new(on_tick: Box) -> Self { Self { on_tick, - data: Mutex::new(TestTransactionsTargetData { + data: Arc::new(Mutex::new(TestTransactionsTargetData { is_header_known: Ok(true), is_header_finalized: Ok(true), + best_finalized_header_id: Ok(test_block_id()), + transactions_to_accept: vec![test_transaction_hash(0)].into_iter().collect(), submitted_proofs: Vec::new(), - }), + })), } } } @@ -368,11 +651,19 @@ mod tests { } async fn is_header_known(&self, _: &TestHeaderId) -> Result { - self.data.lock().is_header_known + self.data.lock().is_header_known.clone() } async fn is_header_finalized(&self, _: &TestHeaderId) -> Result { - self.data.lock().is_header_finalized + self.data.lock().is_header_finalized.clone() + } + + async fn best_finalized_header_id(&self) -> Result { + self.data.lock().best_finalized_header_id.clone() + } + + async fn filter_transaction_proof(&self, proof: &TestTransactionProof) -> Result { + Ok(self.data.lock().transactions_to_accept.contains(&proof.0)) } async fn submit_transaction_proof(&self, proof: TestTransactionProof) -> Result<(), TestError> { @@ -381,23 +672,22 @@ mod tests { } } - fn ensure_success(source: TestTransactionsSource, target: TestTransactionsTarget) { + fn ensure_relay_single_success(source: &TestTransactionsSource, target: &TestTransactionsTarget) { assert_eq!( - async_std::task::block_on(relay_single_transaction_proof( - &source, - &target, - test_transaction_hash(), - )), + async_std::task::block_on(relay_single_transaction_proof(source, target, test_transaction_hash(0),)), Ok(()), ); - assert_eq!(target.data.lock().submitted_proofs, vec![test_transaction_proof()],); + assert_eq!( + target.data.lock().submitted_proofs, + vec![TestTransactionProof(test_transaction_hash(0))], + ); } - fn ensure_failure(source: TestTransactionsSource, target: TestTransactionsTarget) { + fn ensure_relay_single_failure(source: TestTransactionsSource, target: TestTransactionsTarget) { assert!(async_std::task::block_on(relay_single_transaction_proof( &source, &target, - test_transaction_hash(), + test_transaction_hash(0), )) .is_err(),); assert!(target.data.lock().submitted_proofs.is_empty()); @@ -407,21 +697,21 @@ mod tests { fn ready_transaction_proof_relayed_immediately() { let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - ensure_success(source, target) + ensure_relay_single_success(&source, &target) } #[test] fn relay_transaction_proof_waits_for_transaction_to_be_mined() { let source = TestTransactionsSource::new(Box::new(|source_data| { - assert_eq!(source_data.transaction, Ok(None)); - source_data.transaction = Ok(Some((test_header_id(), test_transaction()))); + assert_eq!(source_data.transaction_block, Ok(None)); + source_data.transaction_block = Ok(Some((test_block_id(), 0))); })); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); // transaction is not yet mined, but will be available after first wait (tick) - source.data.lock().transaction = Ok(None); + source.data.lock().transaction_block = Ok(None); - ensure_success(source, target) + ensure_relay_single_success(&source, &target) } #[test] @@ -429,9 +719,9 @@ mod tests { let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - source.data.lock().transaction = Err(0); + source.data.lock().transaction_block = Err(TestError(false)); - ensure_failure(source, target) + ensure_relay_single_failure(source, target) } #[test] @@ -439,9 +729,13 @@ mod tests { let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - source.data.lock().transaction_proof = Err(0); + source + .data + .lock() + .proofs_to_fail + .insert(test_transaction_hash(0), TestError(false)); - ensure_failure(source, target) + ensure_relay_single_failure(source, target) } #[test] @@ -455,7 +749,7 @@ mod tests { // header is not yet imported, but will be available after first wait (tick) target.data.lock().is_header_known = Ok(false); - ensure_success(source, target) + ensure_relay_single_success(&source, &target) } #[test] @@ -463,9 +757,9 @@ mod tests { let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - target.data.lock().is_header_known = Err(0); + target.data.lock().is_header_known = Err(TestError(false)); - ensure_failure(source, target) + ensure_relay_single_failure(source, target) } #[test] @@ -479,7 +773,7 @@ mod tests { // header is not yet finalized, but will be available after first wait (tick) target.data.lock().is_header_finalized = Ok(false); - ensure_success(source, target) + ensure_relay_single_success(&source, &target) } #[test] @@ -487,8 +781,147 @@ mod tests { let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - target.data.lock().is_header_finalized = Err(0); + target.data.lock().is_header_finalized = Err(TestError(false)); + + ensure_relay_single_failure(source, target) + } + + #[test] + fn relay_transaction_proof_fails_when_target_node_rejects_proof() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + target + .data + .lock() + .transactions_to_accept + .remove(&test_transaction_hash(0)); + + ensure_relay_single_success(&source, &target) + } + + fn test_relay_block_transactions( + source: &TestTransactionsSource, + target: &TestTransactionsTarget, + pre_relayed: RelayedBlockTransactions, + ) -> Result { + async_std::task::block_on(relay_block_transactions( + source, + target, + &TestBlock( + test_block_id(), + vec![test_transaction(0), test_transaction(1), test_transaction(2)], + ), + pre_relayed, + )) + } + + #[test] + fn relay_block_transactions_process_all_transactions() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + // let's only accept tx#1 + target + .data + .lock() + .transactions_to_accept + .remove(&test_transaction_hash(0)); + target + .data + .lock() + .transactions_to_accept + .insert(test_transaction_hash(1)); + + let relayed_transactions = test_relay_block_transactions(&source, &target, Default::default()); + assert_eq!( + relayed_transactions, + Ok(RelayedBlockTransactions { + processed: 3, + relayed: 1, + failed: 0, + }), + ); + assert_eq!( + target.data.lock().submitted_proofs, + vec![TestTransactionProof(test_transaction_hash(1))], + ); + } + + #[test] + fn relay_block_transactions_ignores_transaction_failure() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - ensure_failure(source, target) + // let's reject proof for tx#0 + source + .data + .lock() + .proofs_to_fail + .insert(test_transaction_hash(0), TestError(false)); + + let relayed_transactions = test_relay_block_transactions(&source, &target, Default::default()); + assert_eq!( + relayed_transactions, + Ok(RelayedBlockTransactions { + processed: 3, + relayed: 0, + failed: 1, + }), + ); + assert_eq!(target.data.lock().submitted_proofs, vec![],); + } + + #[test] + fn relay_block_transactions_fails_on_connection_error() { + let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); + + // fail with connection error when preparing proof for tx#1 + source + .data + .lock() + .proofs_to_fail + .insert(test_transaction_hash(1), TestError(true)); + + let relayed_transactions = test_relay_block_transactions(&source, &target, Default::default()); + assert_eq!( + relayed_transactions, + Err(RelayedBlockTransactions { + processed: 1, + relayed: 1, + failed: 0, + }), + ); + assert_eq!( + target.data.lock().submitted_proofs, + vec![TestTransactionProof(test_transaction_hash(0))], + ); + + // now do not fail on tx#2 + source.data.lock().proofs_to_fail.clear(); + // and also relay tx#3 + target + .data + .lock() + .transactions_to_accept + .insert(test_transaction_hash(2)); + + let relayed_transactions = test_relay_block_transactions(&source, &target, relayed_transactions.unwrap_err()); + assert_eq!( + relayed_transactions, + Ok(RelayedBlockTransactions { + processed: 3, + relayed: 2, + failed: 0, + }), + ); + assert_eq!( + target.data.lock().submitted_proofs, + vec![ + TestTransactionProof(test_transaction_hash(0)), + TestTransactionProof(test_transaction_hash(2)) + ], + ); } } diff --git a/relays/ethereum/src/exchange_loop.rs b/relays/ethereum/src/exchange_loop.rs new file mode 100644 index 0000000000000..678211d7c139f --- /dev/null +++ b/relays/ethereum/src/exchange_loop.rs @@ -0,0 +1,267 @@ +// Copyright 2019-2020 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 . + +//! Relaying proofs of exchange transactions. + +use crate::exchange::{ + relay_block_transactions, BlockNumberOf, RelayedBlockTransactions, SourceClient, TargetClient, + TransactionProofPipeline, +}; +use crate::utils::retry_backoff; + +use backoff::backoff::Backoff; +use futures::{future::FutureExt, select}; +use num_traits::One; +use std::{future::Future, time::Duration}; + +/// Delay after connection-related error happened before we'll try +/// reconnection again. +const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); + +/// Transactions proofs relay state. +#[derive(Debug)] +pub struct TransactionProofsRelayState { + /// Number of last header we have processed so far. + pub best_processed_header_number: BlockNumber, +} + +/// Transactions proofs relay storage. +pub trait TransactionProofsRelayStorage { + /// Associated block number. + type BlockNumber; + + /// Get relay state. + fn state(&self) -> TransactionProofsRelayState; + /// Update relay state. + fn set_state(&mut self, state: &TransactionProofsRelayState); +} + +/// In-memory storage for auto-relay loop. +#[derive(Debug)] +pub struct InMemoryStorage { + best_processed_header_number: BlockNumber, +} + +impl InMemoryStorage { + /// Created new in-memory storage with given best processed block number. + pub fn new(best_processed_header_number: BlockNumber) -> Self { + InMemoryStorage { + best_processed_header_number, + } + } +} + +impl TransactionProofsRelayStorage for InMemoryStorage { + type BlockNumber = BlockNumber; + + fn state(&self) -> TransactionProofsRelayState { + TransactionProofsRelayState { + best_processed_header_number: self.best_processed_header_number, + } + } + + fn set_state(&mut self, state: &TransactionProofsRelayState) { + self.best_processed_header_number = state.best_processed_header_number; + } +} + +/// Run proofs synchronization. +pub fn run( + mut storage: impl TransactionProofsRelayStorage>, + source_client: impl SourceClient

, + target_client: impl TargetClient

, + exit_signal: impl Future, +) { + let mut local_pool = futures::executor::LocalPool::new(); + + local_pool.run_until(async move { + let mut retry_backoff = retry_backoff(); + let mut state = storage.state(); + let mut current_finalized_block = None; + + let exit_signal = exit_signal.fuse(); + + futures::pin_mut!(exit_signal); + + loop { + let iteration_result = run_loop_iteration( + &mut storage, + &source_client, + &target_client, + &mut state, + &mut current_finalized_block, + ) + .await; + + match iteration_result { + Ok(_) => { + retry_backoff.reset(); + + select! { + _ = source_client.tick().fuse() => {}, + _ = exit_signal => return, + } + } + Err(_) => { + let retry_timeout = retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY); + + select! { + _ = async_std::task::sleep(retry_timeout).fuse() => {}, + _ = exit_signal => return, + } + } + } + } + }); +} + +/// Run exchange loop until we need to break. +async fn run_loop_iteration( + storage: &mut impl TransactionProofsRelayStorage>, + source_client: &impl SourceClient

, + target_client: &impl TargetClient

, + state: &mut TransactionProofsRelayState>, + current_finalized_block: &mut Option<(P::Block, RelayedBlockTransactions)>, +) -> Result<(), ()> { + let best_finalized_header_id = match target_client.best_finalized_header_id().await { + Ok(best_finalized_header_id) => { + log::trace!( + target: "bridge", + "Got best finalized {} block from {} node: {:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + best_finalized_header_id, + ); + + best_finalized_header_id + } + Err(err) => { + log::error!( + target: "bridge", + "Failed to retrieve best {} header id from {} node: {:?}. Going to retry...", + P::SOURCE_NAME, + P::TARGET_NAME, + err, + ); + + return Err(()); + } + }; + + loop { + // if we already have some finalized block body, try to relay its transactions + if let Some((block, relayed_transactions)) = current_finalized_block.take() { + let result = relay_block_transactions(source_client, target_client, &block, relayed_transactions).await; + + match result { + Ok(relayed_transactions) => { + log::info!( + target: "bridge", + "Relay has processed {} block #{}. Total/Relayed/Failed transactions: {}/{}/{}", + P::SOURCE_NAME, + state.best_processed_header_number, + relayed_transactions.processed, + relayed_transactions.relayed, + relayed_transactions.failed, + ); + + state.best_processed_header_number = state.best_processed_header_number + One::one(); + storage.set_state(state); + + // we have just updated state => proceed to next block retrieval + } + Err(relayed_transactions) => { + *current_finalized_block = Some((block, relayed_transactions)); + return Err(()); + } + } + } + + // we may need to retrieve finalized block body from source node + if best_finalized_header_id.0 > state.best_processed_header_number { + let next_block_number = state.best_processed_header_number + One::one(); + let result = source_client.block_by_number(next_block_number).await; + + match result { + Ok(block) => { + *current_finalized_block = Some((block, RelayedBlockTransactions::default())); + + // we have received new finalized block => go back to relay its transactions + continue; + } + Err(err) => { + log::error!( + target: "bridge", + "Failed to retrieve canonical block #{} from {} node: {:?}. Going to retry...", + next_block_number, + P::SOURCE_NAME, + err, + ); + + return Err(()); + } + } + } + + // there are no any transactions we need to relay => wait for new data + return Ok(()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::exchange::tests::{ + test_next_block, test_next_block_id, test_transaction_hash, TestTransactionProof, TestTransactionsSource, + TestTransactionsTarget, + }; + use futures::{future::FutureExt, stream::StreamExt}; + + #[test] + fn exchange_loop_is_able_to_relay_proofs() { + let storage = InMemoryStorage { + best_processed_header_number: 0, + }; + let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no target ticks allowed"))); + let target_data = target.data.clone(); + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + + let source = TestTransactionsSource::new(Box::new(move |data| { + let transaction1_relayed = target_data + .lock() + .submitted_proofs + .contains(&TestTransactionProof(test_transaction_hash(0))); + let transaction2_relayed = target_data + .lock() + .submitted_proofs + .contains(&TestTransactionProof(test_transaction_hash(1))); + match (transaction1_relayed, transaction2_relayed) { + (true, true) => exit_sender.unbounded_send(()).unwrap(), + (true, false) => { + data.block = Ok(test_next_block()); + target_data.lock().best_finalized_header_id = Ok(test_next_block_id()); + target_data + .lock() + .transactions_to_accept + .insert(test_transaction_hash(1)); + } + _ => (), + } + })); + + run(storage, source, target, exit_receiver.into_future().map(|(_, _)| ())); + } +} diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 4894c7efb27e8..403ff101f8639 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -22,6 +22,7 @@ mod ethereum_exchange; mod ethereum_sync_loop; mod ethereum_types; mod exchange; +mod exchange_loop; mod headers; mod metrics; mod rpc; @@ -260,11 +261,21 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result ethereum_exchange::ExchangeRelayMode::Single( + eth_tx_hash + .parse() + .map_err(|e| format!("Failed to parse eth-tx-hash: {}", e))?, + ), + None => ethereum_exchange::ExchangeRelayMode::Auto(match matches.value_of("eth-start-with-block") { + Some(eth_start_with_block) => Some( + eth_start_with_block + .parse() + .map_err(|e| format!("Failed to parse eth-start-with-block: {}", e))?, + ), + None => None, + }), + }; Ok(params) } diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs index 412add5f8efde..5fc73ed02eaeb 100644 --- a/relays/ethereum/src/rpc.rs +++ b/relays/ethereum/src/rpc.rs @@ -50,6 +50,8 @@ jsonrpsee::rpc_api! { fn get_block_by_number(block_number: U64, full_tx_objs: bool) -> EthereumHeader; #[rpc(method = "eth_getBlockByHash", positional_params)] fn get_block_by_hash(hash: H256, full_tx_objs: bool) -> EthereumHeader; + #[rpc(method = "eth_getBlockByNumber", positional_params)] + fn get_block_by_number_with_transactions(number: U64, full_tx_objs: bool) -> EthereumHeaderWithTransactions; #[rpc(method = "eth_getBlockByHash", positional_params)] fn get_block_by_hash_with_transactions(hash: H256, full_tx_objs: bool) -> EthereumHeaderWithTransactions; #[rpc(method = "eth_getTransactionByHash", positional_params)] @@ -91,6 +93,8 @@ pub trait EthereumRpc { async fn header_by_number(&self, block_number: u64) -> Result; /// Retrieve block header by its hash from Ethereum node. async fn header_by_hash(&self, hash: H256) -> Result; + /// Retrieve block header and its transactions by its number from Ethereum node. + async fn header_by_number_with_transactions(&self, block_number: u64) -> Result; /// Retrieve block header and its transactions by its hash from Ethereum node. async fn header_by_hash_with_transactions(&self, hash: H256) -> Result; /// Retrieve transaction by its hash from Ethereum node. diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 4645d4e4dcf85..9739237520b05 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{EthereumHeaderId, TransactionHash as EthereumTransactionHash}; use crate::sync_types::MaybeConnectionError; use jsonrpsee::client::RequestError; @@ -103,10 +102,6 @@ pub enum EthereumNodeError { /// An invalid Substrate block number was received from /// an Ethereum node. InvalidSubstrateBlockNumber, - /// Block includes the same transaction more than once. - DuplicateBlockTransaction(EthereumHeaderId, EthereumTransactionHash), - /// Block is missing transaction we believe is a part of this block. - BlockMissingTransaction(EthereumHeaderId, EthereumTransactionHash), } impl ToString for EthereumNodeError { @@ -122,14 +117,6 @@ impl ToString for EthereumNodeError { } Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), - Self::DuplicateBlockTransaction(header_id, tx_hash) => format!( - "Ethereum block {}/{} includes Ethereum transaction {} more than once", - header_id.0, header_id.1, tx_hash, - ), - Self::BlockMissingTransaction(header_id, tx_hash) => format!( - "Ethereum block {}/{} is missing Ethereum transaction {} which we believe is a part of this block", - header_id.0, header_id.1, tx_hash, - ), } } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index e0c59457b0125..32f219d4ea332 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -38,6 +38,7 @@ const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_req const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; const ETH_API_BEST_FINALIZED_BLOCK: &str = "EthereumHeadersApi_finalized_block"; +const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "CurrencyExchangeApi_filter_transaction_proof"; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; type Result = std::result::Result; @@ -145,7 +146,7 @@ impl SubstrateRpc for SubstrateRpcClient { async fn best_ethereum_finalized_block(&self) -> Result { let call = ETH_API_BEST_FINALIZED_BLOCK.to_string(); - let data = Bytes("0x".into()); + let data = Bytes(Vec::new()); let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; @@ -298,6 +299,11 @@ impl SubmitEthereumHeaders for SubstrateRpcClient { /// calls. #[async_trait] pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { + /// Pre-verify Ethereum exchange transaction proof. + async fn verify_exchange_transaction_proof( + &self, + proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + ) -> Result; /// Submits Ethereum exchange transaction proof to Substrate runtime. async fn submit_exchange_transaction_proof( &self, @@ -308,6 +314,19 @@ pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { #[async_trait] impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { + async fn verify_exchange_transaction_proof( + &self, + proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + ) -> Result { + let call = EXCH_API_FILTER_TRANSACTION_PROOF.to_string(); + let data = Bytes(proof.encode()); + + let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let is_allowed: bool = Decode::decode(&mut &encoded_response.0[..])?; + + Ok(is_allowed) + } + async fn submit_exchange_transaction_proof( &self, params: SubstrateSigningParams, diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index be64e9fa504d5..b2c5d2a5ee39e 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -20,6 +20,7 @@ use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{ HeaderIdOf, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SubmittedHeaders, }; +use crate::utils::retry_backoff; use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; @@ -48,9 +49,6 @@ const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); /// Delay after connection-related error happened before we'll try /// reconnection again. const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); -/// Max delay after connection-unrelated error happened before we'll try the -/// same request again. -const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); /// Source client trait. #[async_trait] @@ -569,15 +567,6 @@ fn interval(timeout: Duration) -> impl futures::Stream { }) } -/// Exponential backoff for connection-unrelated errors retries. -pub(crate) fn retry_backoff() -> ExponentialBackoff { - let mut backoff = ExponentialBackoff::default(); - // we do not want relayer to stop - backoff.max_elapsed_time = None; - backoff.max_interval = MAX_BACKOFF_INTERVAL; - backoff -} - /// Process result of the future from a client. /// /// Returns whether or not the client we're interacting with is online. In this context diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/ethereum/src/sync_loop_tests.rs index b49d4ce5e530e..7b65f3d54a8d4 100644 --- a/relays/ethereum/src/sync_loop_tests.rs +++ b/relays/ethereum/src/sync_loop_tests.rs @@ -16,10 +16,11 @@ #![cfg(test)] -use crate::sync_loop::{process_future_result, retry_backoff, run, SourceClient, TargetClient}; +use crate::sync_loop::{process_future_result, run, SourceClient, TargetClient}; use crate::sync_types::{ HeaderId, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SourceHeader, SubmittedHeaders, }; +use crate::utils::retry_backoff; use async_trait::async_trait; use backoff::backoff::Backoff; diff --git a/relays/ethereum/src/utils.rs b/relays/ethereum/src/utils.rs index 4f022c80477db..e769e10782777 100644 --- a/relays/ethereum/src/utils.rs +++ b/relays/ethereum/src/utils.rs @@ -14,6 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use backoff::ExponentialBackoff; +use std::time::Duration; + +/// Max delay after connection-unrelated error happened before we'll try the +/// same request again. +const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); + /// Macro that returns (client, Err(error)) tuple from function if result is Err(error). #[macro_export] macro_rules! bail_on_error { @@ -35,3 +42,12 @@ macro_rules! bail_on_arg_error { } }; } + +/// Exponential backoff for connection-unrelated errors retries. +pub fn retry_backoff() -> ExponentialBackoff { + let mut backoff = ExponentialBackoff::default(); + // we do not want relayer to stop + backoff.max_elapsed_time = None; + backoff.max_interval = MAX_BACKOFF_INTERVAL; + backoff +} From 6d7a4eb7bd496b2a04c1eeb63d4b6bb97ec0bbb7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 27 Jul 2020 13:14:36 -0400 Subject: [PATCH 0112/1210] Allow Multiple Bridge Pallet Instances (#226) * Add Instance type parameter to pallet * Sketch out what the runtime could look like * Allow runtime to compile with multiple bridge pallets * Cargo Fmt * Allow an instance of a PoA chain to be used with currency-exchange I specify that it's only _an instance_ instead of _instances_ since the currency-exchange pallet does not support multiple instances itself. What this commit does is make it so that the different instances of the PoA chains we currently have are compatible with the currency-exchange pallet through the implementation of the PeerBlockchain trait. * Add Instance type parameter to Currency Exchange pallet * Wire up currency exchange intances in runtime * Rust Fmt * Show sccache * Allow Eth pallet to use a default instance * Use a default instance in Eth pallet tests * Remove Rialto and Kovan feature flags Through some discussions it has been decided that the `bridge-node` should, like Substrate's `node-template`, be a showcase of the different pallets available in a project. Because of this I've removed the feature flags for the Rialto and Kovan networks in favour of having both of them included in the runtime. * Update the chain_spec to use both Rialto and Kovan configs * Update pallet level calls used by Substrate client Allows the project to compile. However, it should be noted that in reality we shouldn't be hardcoding the pallet we're calling. * Allow currency-exchange pallet to use a default instance * Support benchmarking an instance of the Eth pallet * Update currency exchange benchmarks to work with instances * Fix test helpers which now need a PoA instance * Remove Actions for checking Rialto and Kovan features * Add missing comments * Update Runtime API string constants * Add issue number for generic chain support in relay * Add Runtime APIs for instances of the currency-exchange pallet * Rust Fmt Co-authored-by: Denis S. Soldatov aka General-Beck --- bin/node/node/Cargo.toml | 4 +- bin/node/node/src/chain_spec.rs | 23 ++- bin/node/runtime/Cargo.toml | 5 +- bin/node/runtime/src/exchange.rs | 26 +-- bin/node/runtime/src/kovan.rs | 24 ++- bin/node/runtime/src/lib.rs | 105 +++++++--- bin/node/runtime/src/rialto.rs | 24 ++- modules/currency-exchange/src/benchmarking.rs | 12 +- modules/currency-exchange/src/lib.rs | 74 +++---- modules/ethereum/src/benchmarking.rs | 42 ++-- modules/ethereum/src/import.rs | 5 +- modules/ethereum/src/lib.rs | 182 +++++++++--------- modules/ethereum/src/mock.rs | 2 +- modules/ethereum/src/test_utils.rs | 14 +- modules/ethereum/src/validators.rs | 3 +- modules/ethereum/src/verification.rs | 15 +- primitives/currency-exchange/src/lib.rs | 11 +- primitives/ethereum-poa/src/lib.rs | 23 ++- relays/ethereum/src/substrate_client.rs | 17 +- 19 files changed, 360 insertions(+), 251 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 84edf0183e35a..f60ad3ac0c826 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -146,9 +146,7 @@ tag = 'v2.0.0-rc4' git = "https://github.com/paritytech/substrate.git" [features] -default = ["bridge-rialto"] -bridge-kovan = ["bridge-node-runtime/bridge-kovan"] -bridge-rialto = ["bridge-node-runtime/bridge-rialto"] +default = [] runtime-benchmarks = [ "bridge-node-runtime/runtime-benchmarks", ] diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/node/src/chain_spec.rs index 425448b921c2d..12c97f140e9d2 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/node/src/chain_spec.rs @@ -15,8 +15,8 @@ // along with Parity Bridges Common. If not, see . use bridge_node_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeEthPoAConfig, GenesisConfig, GrandpaConfig, SessionConfig, - SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, + SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use grandpa_primitives::AuthorityId as GrandpaId; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -152,7 +152,8 @@ fn testnet_genesis( pallet_aura: Some(AuraConfig { authorities: Vec::new(), }), - pallet_bridge_eth_poa: load_bridge_config(), + pallet_bridge_eth_poa_Instance1: load_rialto_bridge_config(), + pallet_bridge_eth_poa_Instance2: load_kovan_bridge_config(), pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), @@ -166,10 +167,18 @@ fn testnet_genesis( } } -fn load_bridge_config() -> Option { - Some(BridgeEthPoAConfig { - initial_header: bridge_node_runtime::bridge::genesis_header(), +fn load_rialto_bridge_config() -> Option { + Some(BridgeRialtoConfig { + initial_header: bridge_node_runtime::rialto::genesis_header(), initial_difficulty: 0.into(), - initial_validators: bridge_node_runtime::bridge::genesis_validators(), + initial_validators: bridge_node_runtime::rialto::genesis_validators(), + }) +} + +fn load_kovan_bridge_config() -> Option { + Some(BridgeKovanConfig { + initial_header: bridge_node_runtime::kovan::genesis_header(), + initial_difficulty: 0.into(), + initial_validators: bridge_node_runtime::kovan::genesis_validators(), }) } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index c1437ae4d511a..755dc99b343fe 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -224,9 +224,7 @@ package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" [features] -default = ["std", "bridge-rialto"] -bridge-kovan = [] -bridge-rialto = [] +default = ["std"] std = [ "pallet-aura/std", "pallet-balances/std", @@ -268,5 +266,4 @@ runtime-benchmarks = [ "pallet-bridge-eth-poa/runtime-benchmarks", "sp-bridge-eth-poa/test-helpers", "sp-runtime/runtime-benchmarks", - "bridge-kovan", ] diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index 75b2007bff286..e41ec9ac40498 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -30,7 +30,6 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use hex_literal::hex; -use pallet_bridge_currency_exchange::Blockchain; use sp_bridge_eth_poa::{transaction_decode, RawTransaction}; use sp_currency_exchange::{ Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, @@ -65,25 +64,6 @@ pub struct EthereumTransactionTag { pub nonce: sp_core::U256, } -/// Eth blockchain from runtime perspective. -pub struct EthBlockchain; - -impl Blockchain for EthBlockchain { - type Transaction = RawTransaction; - type TransactionInclusionProof = EthereumTransactionInclusionProof; - - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { - let is_transaction_finalized = - crate::BridgeEthPoA::verify_transaction_finalized(proof.block, proof.index, &proof.proof); - - if !is_transaction_finalized { - return None; - } - - proof.proof.get(proof.index as usize).cloned() - } -} - /// Eth transaction from runtime perspective. pub struct EthTransaction; @@ -147,7 +127,7 @@ impl MaybeLockFundsTransaction for EthTransaction { /// Prepares everything required to bench claim of funds locked by given transaction. #[cfg(feature = "runtime-benchmarks")] -pub(crate) fn prepare_environment_for_claim( +pub(crate) fn prepare_environment_for_claim, I: pallet_bridge_eth_poa::Instance>( transactions: &[RawTransaction], ) -> sp_bridge_eth_poa::H256 { use pallet_bridge_eth_poa::{ @@ -156,8 +136,8 @@ pub(crate) fn prepare_environment_for_claim( }; use sp_bridge_eth_poa::compute_merkle_root; - let mut storage = BridgeStorage::::new(); - let header = HeaderBuilder::with_parent_number_on_runtime::(0) + let mut storage = BridgeStorage::::new(); + let header = HeaderBuilder::with_parent_number_on_runtime::(0) .with_transactions_root(compute_merkle_root(transactions.iter())) .sign_by(&validator(0)); let header_id = header.compute_id(); diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index fe62fce163b12..ad641aa728a6d 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -14,12 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::exchange::EthereumTransactionInclusionProof; + use frame_support::RuntimeDebug; use hex_literal::hex; +use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; -use sp_bridge_eth_poa::{Address, Header, U256}; +use sp_bridge_eth_poa::{Address, Header, RawTransaction, U256}; use sp_std::prelude::*; frame_support::parameter_types! { @@ -131,6 +134,25 @@ impl BridgePruningStrategy for PruningStrategy { } } +/// The Kovan Blockchain as seen by the runtime. +pub struct KovanBlockchain; + +impl PeerBlockchain for KovanBlockchain { + type Transaction = RawTransaction; + type TransactionInclusionProof = EthereumTransactionInclusionProof; + + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + let is_transaction_finalized = + crate::BridgeKovan::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + + if !is_transaction_finalized { + return None; + } + + proof.proof.get(proof.index as usize).cloned() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9f473fee9d8ba..6c4ad00692e4b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -32,17 +32,11 @@ pub mod exchange; #[cfg(feature = "runtime-benchmarks")] pub mod benches; -#[cfg(feature = "bridge-kovan")] pub mod kovan; -#[cfg(feature = "bridge-rialto")] pub mod rialto; #[cfg(feature = "runtime-benchmarks")] pub use benches as bridge; -#[cfg(all(feature = "bridge-kovan", not(feature = "runtime-benchmarks")))] -pub use kovan as bridge; -#[cfg(all(feature = "bridge-rialto", not(feature = "runtime-benchmarks")))] -pub use rialto as bridge; use codec::{Decode, Encode}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; @@ -69,10 +63,12 @@ pub use frame_support::{ weights::{IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; + pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_timestamp::Call as TimestampCall; + #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; @@ -233,17 +229,39 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } -impl pallet_bridge_eth_poa::Trait for Runtime { - type AuraConfiguration = bridge::BridgeAuraConfiguration; - type FinalityVotesCachingInterval = bridge::FinalityVotesCachingInterval; - type ValidatorsConfiguration = bridge::BridgeValidatorsConfiguration; - type PruningStrategy = bridge::PruningStrategy; +type Rialto = pallet_bridge_eth_poa::Instance1; +impl pallet_bridge_eth_poa::Trait for Runtime { + type AuraConfiguration = rialto::BridgeAuraConfiguration; + type FinalityVotesCachingInterval = rialto::FinalityVotesCachingInterval; + type ValidatorsConfiguration = rialto::BridgeValidatorsConfiguration; + type PruningStrategy = rialto::PruningStrategy; + type OnHeadersSubmitted = (); +} + +type Kovan = pallet_bridge_eth_poa::Instance2; +impl pallet_bridge_eth_poa::Trait for Runtime { + type AuraConfiguration = kovan::BridgeAuraConfiguration; + type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval; + type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration; + type PruningStrategy = kovan::PruningStrategy; type OnHeadersSubmitted = (); } -impl pallet_bridge_currency_exchange::Trait for Runtime { +type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1; +impl pallet_bridge_currency_exchange::Trait for Runtime { type OnTransactionSubmitted = (); - type PeerBlockchain = exchange::EthBlockchain; + type PeerBlockchain = rialto::RialtoBlockchain; + type PeerMaybeLockFundsTransaction = exchange::EthTransaction; + type RecipientsMap = sp_currency_exchange::IdentityRecipients; + type Amount = Balance; + type CurrencyConverter = sp_currency_exchange::IdentityCurrencyConverter; + type DepositInto = DepositInto; +} + +type KovanCurrencyExchange = pallet_bridge_currency_exchange::Instance2; +impl pallet_bridge_currency_exchange::Trait for Runtime { + type OnTransactionSubmitted = (); + type PeerBlockchain = kovan::KovanBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; type RecipientsMap = sp_currency_exchange::IdentityRecipients; type Amount = Balance; @@ -439,6 +457,10 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { + BridgeRialto: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, + BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, + BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, + BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, @@ -448,8 +470,6 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Module, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, Session: pallet_session::{Module, Call, Storage, Event, Config}, - BridgeEthPoA: pallet_bridge_eth_poa::{Module, Call, Config, Storage, ValidateUnsigned}, - BridgeCurrencyExchange: pallet_bridge_currency_exchange::{Module, Call}, } ); @@ -535,32 +555,59 @@ impl_runtime_apis! { } } - impl sp_bridge_eth_poa::EthereumHeadersApi for Runtime { + impl sp_bridge_eth_poa::RialtoHeaderApi for Runtime { fn best_block() -> (u64, sp_bridge_eth_poa::H256) { - let best_block = BridgeEthPoA::best_block(); + let best_block = BridgeRialto::best_block(); (best_block.number, best_block.hash) } fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { - let finalized_block = BridgeEthPoA::finalized_block(); + let finalized_block = BridgeRialto::finalized_block(); (finalized_block.number, finalized_block.hash) } fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { - BridgeEthPoA::is_import_requires_receipts(header) + BridgeRialto::is_import_requires_receipts(header) } fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { - BridgeEthPoA::is_known_block(hash) + BridgeRialto::is_known_block(hash) } } - impl sp_currency_exchange::CurrencyExchangeApi for Runtime { + impl sp_bridge_eth_poa::KovanHeaderApi for Runtime { + fn best_block() -> (u64, sp_bridge_eth_poa::H256) { + let best_block = BridgeKovan::best_block(); + (best_block.number, best_block.hash) + } + + fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { + let finalized_block = BridgeKovan::finalized_block(); + (finalized_block.number, finalized_block.hash) + } + + fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { + BridgeKovan::is_import_requires_receipts(header) + } + + fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { + BridgeKovan::is_known_block(hash) + } + } + + impl sp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { + fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { + BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) + } + } + + impl sp_currency_exchange::KovanCurrencyExchangeApi for Runtime { fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { - BridgeCurrencyExchange::filter_transaction_proof(&proof) + BridgeKovanCurrencyExchange::filter_transaction_proof(&proof) } } + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( source: TransactionSource, @@ -656,14 +703,14 @@ impl_runtime_apis! { ProofParams as BridgeCurrencyExchangeProofParams, }; - impl BridgeCurrencyExchangeTrait for Runtime { + impl BridgeCurrencyExchangeTrait for Runtime { fn make_proof( proof_params: BridgeCurrencyExchangeProofParams, ) -> crate::exchange::EthereumTransactionInclusionProof { use sp_currency_exchange::DepositInto; if proof_params.recipient_exists { - ::DepositInto::deposit_into( + >::DepositInto::deposit_into( proof_params.recipient.clone(), ExistentialDeposit::get(), ).unwrap(); @@ -681,7 +728,7 @@ impl_runtime_apis! { let transactions = sp_std::iter::repeat(transaction.clone()) .take(1 + proof_params.proof_size_factor as usize) .collect::>(); - let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); + let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); crate::exchange::EthereumTransactionInclusionProof { block: block_hash, index: 0, @@ -690,8 +737,8 @@ impl_runtime_apis! { } } - add_benchmark!(params, batches, b"bridge-eth-poa", BridgeEthPoA); - add_benchmark!(params, batches, b"bridge-currency-exchange", BridgeCurrencyExchangeBench::); + add_benchmark!(params, batches, b"bridge-eth-poa", BridgeKovan); + add_benchmark!(params, batches, b"bridge-currency-exchange", BridgeCurrencyExchangeBench::); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) @@ -785,7 +832,7 @@ mod tests { let initial_amount = as Currency>::free_balance(&existing_account); let additional_amount = 10_000; - ::DepositInto::deposit_into( + >::DepositInto::deposit_into( existing_account.clone(), additional_amount, ) @@ -804,7 +851,7 @@ mod tests { let initial_amount = 0; let additional_amount = ExistentialDeposit::get() + 10_000; let new_account: AccountId = [42u8; 32].into(); - ::DepositInto::deposit_into( + >::DepositInto::deposit_into( new_account.clone(), additional_amount, ) diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs index cdc314fb480cc..6560dbb398097 100644 --- a/bin/node/runtime/src/rialto.rs +++ b/bin/node/runtime/src/rialto.rs @@ -14,12 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::exchange::EthereumTransactionInclusionProof; + use frame_support::RuntimeDebug; use hex_literal::hex; +use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; -use sp_bridge_eth_poa::{Address, Header, U256}; +use sp_bridge_eth_poa::{Address, Header, RawTransaction, U256}; use sp_std::prelude::*; frame_support::parameter_types! { @@ -104,6 +107,25 @@ impl TPruningStrategy for PruningStrategy { } } +/// The Rialto Blockchain as seen by the runtime. +pub struct RialtoBlockchain; + +impl PeerBlockchain for RialtoBlockchain { + type Transaction = RawTransaction; + type TransactionInclusionProof = EthereumTransactionInclusionProof; + + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + let is_transaction_finalized = + crate::BridgeRialto::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + + if !is_transaction_finalized { + return None; + } + + proof.proof.get(proof.index as usize).cloned() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index dc032720ce3c0..30fb7e63f0075 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -18,10 +18,10 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{Blockchain, Call, Module as CurrencyExchangeModule, Trait as CurrencyExchangeTrait}; +use super::{Call, Instance, Module as CurrencyExchangeModule, PeerBlockchain, Trait as CurrencyExchangeTrait}; use sp_std::prelude::*; -use frame_benchmarking::{account, benchmarks}; +use frame_benchmarking::{account, benchmarks_instance}; use frame_system::RawOrigin; const SEED: u32 = 0; @@ -29,7 +29,7 @@ const WORST_TX_SIZE_FACTOR: u32 = 1000; const WORST_PROOF_SIZE_FACTOR: u32 = 1000; /// Module we're benchmarking here. -pub struct Module(CurrencyExchangeModule); +pub struct Module, I: Instance>(CurrencyExchangeModule); /// Proof benchmarking parameters. pub struct ProofParams { @@ -46,14 +46,14 @@ pub struct ProofParams { } /// Trait that must be implemented by runtime. -pub trait Trait: CurrencyExchangeTrait { +pub trait Trait: CurrencyExchangeTrait { /// Prepare proof for importing exchange transaction. fn make_proof( proof_params: ProofParams, - ) -> <::PeerBlockchain as Blockchain>::TransactionInclusionProof; + ) -> <>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof; } -benchmarks! { +benchmarks_instance! { _ { } // Benchmark `import_peer_transaction` extrinsic with the best possible conditions: diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 1c39e1aea9323..cf03239c8a664 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -33,8 +33,8 @@ pub trait OnTransactionSubmitted { fn on_valid_transaction_submitted(submitter: AccountId); } -/// Peer blockhain interface. -pub trait Blockchain { +/// Peer blockchain interface. +pub trait PeerBlockchain { /// Transaction type. type Transaction: Parameter; /// Transaction inclusion proof type. @@ -47,14 +47,14 @@ pub trait Blockchain { } /// The module configuration trait -pub trait Trait: frame_system::Trait { +pub trait Trait: frame_system::Trait { /// Handler for transaction submission result. type OnTransactionSubmitted: OnTransactionSubmitted; - /// Peer blockchain type. - type PeerBlockchain: Blockchain; + /// Represents the blockchain that we'll be exchanging currency with. + type PeerBlockchain: PeerBlockchain; /// Peer blockchain transaction parser. type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< - Transaction = ::Transaction, + Transaction = ::Transaction, >; /// Map between blockchains recipients. type RecipientsMap: RecipientsMap< @@ -73,7 +73,7 @@ pub trait Trait: frame_system::Trait { } decl_error! { - pub enum Error for Module { + pub enum Error for Module, I: Instance> { /// Invalid peer blockchain transaction provided. InvalidTransaction, /// Peer transaction has invalid amount. @@ -96,17 +96,17 @@ decl_error! { } decl_module! { - pub struct Module for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Imports lock fund transaction of the peer blockchain. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_peer_transaction( origin, - proof: <::PeerBlockchain as Blockchain>::TransactionInclusionProof, + proof: <>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof, ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; // verify and parse transaction proof - let deposit = prepare_deposit_details::(&proof)?; + let deposit = prepare_deposit_details::(&proof)?; // make sure to update the mapping if we deposit successfully to avoid double spending, // i.e. whenever `deposit_into` is successful we MUST update `Transfers`. @@ -117,9 +117,9 @@ decl_module! { match deposit_result { Ok(_) => (), Err(ExchangeError::DepositPartiallyFailed) => (), - Err(error) => return Err(Error::::from(error).into()), + Err(error) => return Err(Error::::from(error).into()), } - Transfers::::insert(&deposit.transfer_id, ()) + Transfers::::insert(&deposit.transfer_id, ()) } // reward submitter for providing valid message @@ -137,17 +137,17 @@ decl_module! { } decl_storage! { - trait Store for Module as Bridge { + trait Store for Module, I: Instance = DefaultInstance> as Bridge { /// All transfers that have already been claimed. Transfers: map hasher(blake2_128_concat) ::Id => (); } } -impl Module { +impl, I: Instance> Module { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. - pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { - if prepare_deposit_details::(proof).is_err() { + pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { + if prepare_deposit_details::(proof).is_err() { return false; } @@ -155,7 +155,7 @@ impl Module { } } -impl From for Error { +impl, I: Instance> From for Error { fn from(error: ExchangeError) -> Self { match error { ExchangeError::InvalidTransaction => Error::InvalidTransaction, @@ -174,7 +174,7 @@ impl OnTransactionSubmitted for () { } /// Exchange deposit details. -struct DepositDetails { +struct DepositDetails, I: Instance> { /// Transfer id. pub transfer_id: ::Id, /// Transfer recipient. @@ -185,21 +185,25 @@ struct DepositDetails { /// Verify and parse transaction proof, preparing everything required for importing /// this transaction proof. -fn prepare_deposit_details( - proof: &<::PeerBlockchain as Blockchain>::TransactionInclusionProof, -) -> Result, Error> { +fn prepare_deposit_details, I: Instance>( + proof: &<>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof, +) -> Result, Error> { // ensure that transaction is included in finalized block that we know of - let transaction = ::PeerBlockchain::verify_transaction_inclusion_proof(proof) - .ok_or_else(|| Error::::UnfinalizedTransaction)?; + let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) + .ok_or_else(|| Error::::UnfinalizedTransaction)?; // parse transaction - let transaction = ::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; + let transaction = + >::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; let transfer_id = transaction.id; - ensure!(!Transfers::::contains_key(&transfer_id), Error::::AlreadyClaimed); + ensure!( + !Transfers::::contains_key(&transfer_id), + Error::::AlreadyClaimed + ); // grant recipient - let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; - let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; + let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; + let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; Ok(DepositDetails { transfer_id, @@ -235,13 +239,13 @@ mod tests { impl OnTransactionSubmitted for DummyTransactionSubmissionHandler { fn on_valid_transaction_submitted(submitter: AccountId) { - Transfers::::insert(submitter, ()); + Transfers::::insert(submitter, ()); } } pub struct DummyBlockchain; - impl Blockchain for DummyBlockchain { + impl PeerBlockchain for DummyBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = (bool, RawTransaction); @@ -386,7 +390,7 @@ mod tests { new_test_ext().execute_with(|| { assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (false, transaction(0))), - Error::::UnfinalizedTransaction, + Error::::UnfinalizedTransaction, ); }); } @@ -399,7 +403,7 @@ mod tests { Origin::signed(SUBMITTER), (true, transaction(INVALID_TRANSACTION_ID)), ), - Error::::InvalidTransaction, + Error::::InvalidTransaction, ); }); } @@ -413,7 +417,7 @@ mod tests { Origin::signed(SUBMITTER), (true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)), ), - Error::::AlreadyClaimed, + Error::::AlreadyClaimed, ); }); } @@ -425,7 +429,7 @@ mod tests { transaction.recipient = UNKNOWN_RECIPIENT_ID; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToMapRecipients, + Error::::FailedToMapRecipients, ); }); } @@ -437,7 +441,7 @@ mod tests { transaction.amount = INVALID_AMOUNT; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToConvertCurrency, + Error::::FailedToConvertCurrency, ); }); } @@ -449,7 +453,7 @@ mod tests { transaction.amount = MAX_DEPOSIT_AMOUNT + 1; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::DepositFailed, + Error::::DepositFailed, ); }); } diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 1f0a7fbe96f20..1da7019c6408f 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -21,11 +21,11 @@ use crate::test_utils::{ HeaderBuilder, }; -use frame_benchmarking::benchmarks; +use frame_benchmarking::benchmarks_instance; use frame_system::RawOrigin; use primitives::{compute_merkle_root, U256}; -benchmarks! { +benchmarks_instance! { _ { } // Benchmark `import_unsigned_header` extrinsic with the best possible conditions: @@ -37,7 +37,7 @@ benchmarks! { let n in 1..1000; let num_validators = 2; - let initial_header = initialize_bench::(num_validators); + let initial_header = initialize_bench::(num_validators); // prepare header to be inserted let header = build_custom_header( @@ -50,7 +50,7 @@ benchmarks! { ); }: import_unsigned_header(RawOrigin::None, header, None) verify { - let storage = BridgeStorage::::new(); + let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, 1); assert_eq!(storage.finalized_block().number, 0); } @@ -67,9 +67,9 @@ benchmarks! { // finalization. let n in 1..7; - let mut storage = BridgeStorage::::new(); + let mut storage = BridgeStorage::::new(); let num_validators: u32 = 2; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(num_validators as usize); // Since we only have two validators we need to make sure the number of blocks is even to // make sure the right validator signs the final block @@ -95,7 +95,7 @@ benchmarks! { let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); }: import_unsigned_header(RawOrigin::None, header, None) verify { - let storage = BridgeStorage::::new(); + let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); assert_eq!(storage.finalized_block().number, num_blocks as u64); } @@ -108,9 +108,9 @@ benchmarks! { // finalization. let n in 7..100; - let mut storage = BridgeStorage::::new(); + let mut storage = BridgeStorage::::new(); let num_validators: u32 = 2; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(num_validators as usize); // Since we only have two validators we need to make sure the number of blocks is even to // make sure the right validator signs the final block @@ -136,7 +136,7 @@ benchmarks! { let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); }: import_unsigned_header(RawOrigin::None, header, None) verify { - let storage = BridgeStorage::::new(); + let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); assert_eq!(storage.finalized_block().number, num_blocks as u64); } @@ -148,14 +148,14 @@ benchmarks! { import_unsigned_pruning { let n in 1..MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT as u32; - let mut storage = BridgeStorage::::new(); + let mut storage = BridgeStorage::::new(); let num_validators = 3; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(num_validators as usize); let validators = validators(num_validators); // Want to prune eligible blocks between [0, n) - BlocksToPrune::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: n as u64, }); @@ -171,11 +171,11 @@ benchmarks! { let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators); }: import_unsigned_header(RawOrigin::None, header, None) verify { - let storage = BridgeStorage::::new(); + let storage = BridgeStorage::::new(); let max_pruned: u64 = (n - 1) as _; assert_eq!(storage.best_block().0.number, (n + 1) as u64); - assert!(HeadersByNumber::get(&0).is_none()); - assert!(HeadersByNumber::get(&max_pruned).is_none()); + assert!(HeadersByNumber::::get(&0).is_none()); + assert!(HeadersByNumber::::get(&max_pruned).is_none()); } // The goal of this bench is to import a block which contains a transaction receipt. The receipt @@ -184,10 +184,10 @@ benchmarks! { import_unsigned_with_receipts { let n in 1..100; - let mut storage = BridgeStorage::::new(); + let mut storage = BridgeStorage::::new(); let num_validators = 1; - let initial_header = initialize_bench::(num_validators as usize); + let initial_header = initialize_bench::(num_validators as usize); let mut receipts = vec![]; for i in 1..=n { @@ -213,18 +213,18 @@ benchmarks! { ); }: import_unsigned_header(RawOrigin::None, header, Some(receipts)) verify { - let storage = BridgeStorage::::new(); + let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, 2); } } -fn initialize_bench(num_validators: usize) -> Header { +fn initialize_bench, I: Instance>(num_validators: usize) -> Header { // Initialize storage with some initial header let initial_header = build_genesis_header(&validator(0)); let initial_difficulty = initial_header.difficulty; let initial_validators = validators_addresses(num_validators as usize); - initialize_storage::(&initial_header, initial_difficulty, &initial_validators); + initialize_storage::(&initial_header, initial_difficulty, &initial_validators); initial_header } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 490c164e47b58..20c86cf6eb8b1 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -169,6 +169,7 @@ mod tests { validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; + use crate::DefaultInstance; use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; use frame_support::{StorageMap, StorageValue}; use secp256k1::SecretKey; @@ -352,7 +353,7 @@ mod tests { step += 3; } assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 11, oldest_block_to_keep: 14, @@ -378,7 +379,7 @@ mod tests { .unwrap(); assert_eq!(finalized_blocks, expected_blocks); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 15, oldest_block_to_keep: 15, diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index bfae5d4b260c4..de25c5aaa218b 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -351,7 +351,7 @@ impl OnHeadersSubmitted for () { } /// The module configuration trait. -pub trait Trait: frame_system::Trait { +pub trait Trait: frame_system::Trait { /// Aura configuration. type AuraConfiguration: Get; /// Validators configuration. @@ -372,14 +372,14 @@ pub trait Trait: frame_system::Trait { } decl_module! { - pub struct Module for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Import single Aura header. Requires transaction to be **UNSIGNED**. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_unsigned_header(origin, header: Header, receipts: Option>) { frame_system::ensure_none(origin)?; import::import_header( - &mut BridgeStorage::::new(), + &mut BridgeStorage::::new(), &mut T::PruningStrategy::default(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), @@ -400,7 +400,7 @@ decl_module! { let submitter = frame_system::ensure_signed(origin)?; let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( - &mut BridgeStorage::::new(), + &mut BridgeStorage::::new(), &mut T::PruningStrategy::default(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), @@ -434,7 +434,7 @@ decl_module! { } decl_storage! { - trait Store for Module as Bridge { + trait Store for Module, I: Instance = DefaultInstance> as Bridge { /// Best known block. BestBlock: (HeaderId, U256); /// Best finalized block. @@ -473,7 +473,7 @@ decl_storage! { "Initial validators set can't be empty", ); - initialize_storage::( + initialize_storage::( &config.initial_header, config.initial_difficulty, &config.initial_validators, @@ -482,43 +482,47 @@ decl_storage! { } } -impl Module { +impl, I: Instance> Module { /// Returns number and hash of the best block known to the bridge module. /// The caller should only submit `import_header` transaction that makes /// (or leads to making) other header the best one. pub fn best_block() -> HeaderId { - BridgeStorage::::new().best_block().0 + BridgeStorage::::new().best_block().0 } /// Returns number and hash of the best finalized block known to the bridge module. pub fn finalized_block() -> HeaderId { - BridgeStorage::::new().finalized_block() + BridgeStorage::::new().finalized_block() } /// Returns true if the import of given block requires transactions receipts. pub fn is_import_requires_receipts(header: Header) -> bool { - import::header_import_requires_receipts(&BridgeStorage::::new(), &T::ValidatorsConfiguration::get(), &header) + import::header_import_requires_receipts( + &BridgeStorage::::new(), + &T::ValidatorsConfiguration::get(), + &header, + ) } /// Returns true if header is known to the runtime. pub fn is_known_block(hash: H256) -> bool { - BridgeStorage::::new().header(&hash).is_some() + BridgeStorage::::new().header(&hash).is_some() } /// Verify that transaction is included into given finalized block. pub fn verify_transaction_finalized(block: H256, tx_index: u64, proof: &[RawTransaction]) -> bool { - crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) + crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) } } -impl frame_support::unsigned::ValidateUnsigned for Module { - type Call = Call; +impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Module { + type Call = Call; fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { match *call { Self::Call::import_unsigned_header(ref header, ref receipts) => { let accept_result = verification::accept_aura_header_into_pool( - &BridgeStorage::::new(), + &BridgeStorage::::new(), &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), &pool_configuration(), @@ -550,17 +554,17 @@ impl frame_support::unsigned::ValidateUnsigned for Module { /// Runtime bridge storage. #[derive(Default)] -pub struct BridgeStorage(sp_std::marker::PhantomData); +pub struct BridgeStorage(sp_std::marker::PhantomData<(T, I)>); -impl BridgeStorage { +impl, I: Instance> BridgeStorage { /// Create new BridgeStorage. pub fn new() -> Self { - BridgeStorage(sp_std::marker::PhantomData::::default()) + BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default()) } /// Prune old blocks. fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) { - let pruning_range = BlocksToPrune::get(); + let pruning_range = BlocksToPrune::::get(); let mut new_pruning_range = pruning_range.clone(); // update oldest block we want to keep @@ -579,7 +583,7 @@ impl BridgeStorage { } // read hashes of blocks with given number and try to prune these blocks - let blocks_at_number = HeadersByNumber::take(number); + let blocks_at_number = HeadersByNumber::::take(number); if let Some(mut blocks_at_number) = blocks_at_number { self.prune_blocks_by_hashes( &mut max_blocks_to_prune, @@ -590,7 +594,7 @@ impl BridgeStorage { // if we haven't pruned all blocks, remember unpruned if !blocks_at_number.is_empty() { - HeadersByNumber::insert(number, blocks_at_number); + HeadersByNumber::::insert(number, blocks_at_number); break; } } @@ -606,7 +610,7 @@ impl BridgeStorage { // update pruning range in storage if pruning_range != new_pruning_range { - BlocksToPrune::put(new_pruning_range); + BlocksToPrune::::put(new_pruning_range); } } @@ -619,13 +623,13 @@ impl BridgeStorage { blocks_at_number: &mut Vec, ) { // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::contains_key) { + if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::::contains_key) { return; } // physically remove headers and (probably) obsolete validators sets while let Some(hash) = blocks_at_number.pop() { - let header = Headers::::take(&hash); + let header = Headers::::take(&hash); frame_support::debug::trace!( target: "runtime", "Pruning PoA header: ({}, {})", @@ -633,10 +637,10 @@ impl BridgeStorage { hash, ); - ScheduledChanges::remove(hash); - FinalityCache::::remove(hash); + ScheduledChanges::::remove(hash); + FinalityCache::::remove(hash); if let Some(header) = header { - ValidatorsSetsRc::mutate(header.next_validators_set_id, |rc| match *rc { + ValidatorsSetsRc::::mutate(header.next_validators_set_id, |rc| match *rc { Some(rc) if rc > 1 => Some(rc - 1), _ => None, }); @@ -651,19 +655,19 @@ impl BridgeStorage { } } -impl Storage for BridgeStorage { +impl, I: Instance> Storage for BridgeStorage { type Submitter = T::AccountId; fn best_block(&self) -> (HeaderId, U256) { - BestBlock::get() + BestBlock::::get() } fn finalized_block(&self) -> HeaderId { - FinalizedBlock::get() + FinalizedBlock::::get() } fn header(&self, hash: &H256) -> Option<(Header, Option)> { - Headers::::get(hash).map(|header| (header.header, header.submitter)) + Headers::::get(hash).map(|header| (header.header, header.submitter)) } fn cached_finality_votes( @@ -675,7 +679,7 @@ impl Storage for BridgeStorage { let mut votes = CachedFinalityVotes::default(); let mut current_id = *parent; loop { - // if we have reached finalized block' sibling => stop with special signal + // if we have reached finalized block's sibling => stop with special signal if current_id.number == best_finalized.number && current_id.hash != best_finalized.hash { votes.stopped_at_finalized_sibling = true; return votes; @@ -687,14 +691,14 @@ impl Storage for BridgeStorage { } // if we have found cached votes => stop - let cached_votes = FinalityCache::::get(¤t_id.hash); + let cached_votes = FinalityCache::::get(¤t_id.hash); if let Some(cached_votes) = cached_votes { votes.votes = Some(cached_votes); return votes; } // read next parent header id - let header = match Headers::::get(¤t_id.hash) { + let header = match Headers::::get(¤t_id.hash) { Some(header) if header.header.number != 0 => header, _ => return votes, }; @@ -717,10 +721,10 @@ impl Storage for BridgeStorage { submitter: Option, parent_hash: &H256, ) -> Option> { - Headers::::get(parent_hash).map(|parent_header| { - let validators_set = ValidatorsSets::get(parent_header.next_validators_set_id) + Headers::::get(parent_hash).map(|parent_header| { + let validators_set = ValidatorsSets::::get(parent_header.next_validators_set_id) .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); - let parent_scheduled_change = ScheduledChanges::get(parent_hash); + let parent_scheduled_change = ScheduledChanges::::get(parent_hash); ImportContext { submitter, parent_hash: *parent_hash, @@ -735,15 +739,15 @@ impl Storage for BridgeStorage { } fn scheduled_change(&self, hash: &H256) -> Option { - ScheduledChanges::get(hash) + ScheduledChanges::::get(hash) } fn insert_header(&mut self, header: HeaderToImport) { if header.is_best { - BestBlock::put((header.id, header.total_difficulty)); + BestBlock::::put((header.id, header.total_difficulty)); } if let Some(scheduled_change) = header.scheduled_change { - ScheduledChanges::insert( + ScheduledChanges::::insert( &header.id.hash, ScheduledChange { validators: scheduled_change, @@ -753,12 +757,12 @@ impl Storage for BridgeStorage { } let next_validators_set_id = match header.enacted_change { Some(enacted_change) => { - let next_validators_set_id = NextValidatorsSetId::mutate(|set_id| { + let next_validators_set_id = NextValidatorsSetId::::mutate(|set_id| { let next_set_id = *set_id; *set_id += 1; next_set_id }); - ValidatorsSets::insert( + ValidatorsSets::::insert( next_validators_set_id, ValidatorsSet { validators: enacted_change.validators, @@ -766,11 +770,11 @@ impl Storage for BridgeStorage { signal_block: enacted_change.signal_block, }, ); - ValidatorsSetsRc::insert(next_validators_set_id, 1); + ValidatorsSetsRc::::insert(next_validators_set_id, 1); next_validators_set_id } None => { - ValidatorsSetsRc::mutate(header.context.validators_set_id, |rc| { + ValidatorsSetsRc::::mutate(header.context.validators_set_id, |rc| { *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); *rc }); @@ -782,7 +786,7 @@ impl Storage for BridgeStorage { if let Some(finality_votes_caching_interval) = finality_votes_caching_interval { let cache_entry_required = header.id.number != 0 && header.id.number % finality_votes_caching_interval == 0; if cache_entry_required { - FinalityCache::::insert(header.id.hash, header.finality_votes); + FinalityCache::::insert(header.id.hash, header.finality_votes); } } @@ -794,8 +798,8 @@ impl Storage for BridgeStorage { ); let last_signal_block = header.context.last_signal_block(); - HeadersByNumber::append(header.id.number, header.id.hash); - Headers::::insert( + HeadersByNumber::::append(header.id.number, header.id.hash); + Headers::::insert( &header.id.hash, StoredHeader { submitter: header.context.submitter, @@ -812,7 +816,7 @@ impl Storage for BridgeStorage { let finalized_number = finalized .as_ref() .map(|f| f.number) - .unwrap_or_else(|| FinalizedBlock::get().number); + .unwrap_or_else(|| FinalizedBlock::::get().number); if let Some(finalized) = finalized { frame_support::debug::trace!( target: "runtime", @@ -821,7 +825,7 @@ impl Storage for BridgeStorage { finalized.hash, ); - FinalizedBlock::put(finalized); + FinalizedBlock::::put(finalized); } // and now prune headers if we need to @@ -831,7 +835,7 @@ impl Storage for BridgeStorage { /// Initialize storage. #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] -pub(crate) fn initialize_storage( +pub(crate) fn initialize_storage, I: Instance>( initial_header: &Header, initial_difficulty: U256, initial_validators: &[Address], @@ -848,14 +852,14 @@ pub(crate) fn initialize_storage( number: initial_header.number, hash: initial_hash, }; - BestBlock::put((initial_id, initial_difficulty)); - FinalizedBlock::put(initial_id); - BlocksToPrune::put(PruningRange { + BestBlock::::put((initial_id, initial_difficulty)); + FinalizedBlock::::put(initial_id); + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: initial_header.number, oldest_block_to_keep: initial_header.number, }); - HeadersByNumber::insert(initial_header.number, vec![initial_hash]); - Headers::::insert( + HeadersByNumber::::insert(initial_header.number, vec![initial_hash]); + Headers::::insert( initial_hash, StoredHeader { submitter: None, @@ -865,8 +869,8 @@ pub(crate) fn initialize_storage( last_signal_block: None, }, ); - NextValidatorsSetId::put(1); - ValidatorsSets::insert( + NextValidatorsSetId::::put(1); + ValidatorsSets::::insert( 0, ValidatorsSet { validators: initial_validators.to_vec(), @@ -874,7 +878,7 @@ pub(crate) fn initialize_storage( enact_block: initial_id, }, ); - ValidatorsSetsRc::insert(0, 1); + ValidatorsSetsRc::::insert(0, 1); } /// Verify that transaction is included into given finalized block. @@ -988,7 +992,7 @@ pub(crate) mod tests { ); if i == 7 && j == 1 { - ScheduledChanges::insert( + ScheduledChanges::::insert( hash, ScheduledChange { validators: validators_addresses(5), @@ -997,7 +1001,7 @@ pub(crate) mod tests { ); } } - HeadersByNumber::insert(i, headers_by_number); + HeadersByNumber::::insert(i, headers_by_number); } f(BridgeStorage::new()) @@ -1007,16 +1011,16 @@ pub(crate) mod tests { #[test] fn blocks_are_not_pruned_if_range_is_empty() { with_headers_to_prune(|storage| { - BlocksToPrune::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5, }); // try to prune blocks [5; 10) storage.prune_blocks(0xFFFF, 10, 5); - assert_eq!(HeadersByNumber::get(&5).unwrap().len(), 5); + assert_eq!(HeadersByNumber::::get(&5).unwrap().len(), 5); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5, @@ -1028,7 +1032,7 @@ pub(crate) mod tests { #[test] fn blocks_to_prune_never_shrinks_from_the_end() { with_headers_to_prune(|storage| { - BlocksToPrune::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: 5, }); @@ -1036,7 +1040,7 @@ pub(crate) mod tests { // try to prune blocks [5; 10) storage.prune_blocks(0xFFFF, 10, 3); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5, @@ -1050,12 +1054,12 @@ pub(crate) mod tests { with_headers_to_prune(|storage| { // try to prune blocks [0; 10) storage.prune_blocks(0, 10, 10); - assert!(HeadersByNumber::get(&0).is_some()); - assert!(HeadersByNumber::get(&1).is_some()); - assert!(HeadersByNumber::get(&2).is_some()); - assert!(HeadersByNumber::get(&3).is_some()); + assert!(HeadersByNumber::::get(&0).is_some()); + assert!(HeadersByNumber::::get(&1).is_some()); + assert!(HeadersByNumber::::get(&2).is_some()); + assert!(HeadersByNumber::::get(&3).is_some()); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: 10, @@ -1070,13 +1074,13 @@ pub(crate) mod tests { // try to prune blocks [0; 10) storage.prune_blocks(7, 10, 10); // 1 headers with number = 0 is pruned (1 total) - assert!(HeadersByNumber::get(&0).is_none()); + assert!(HeadersByNumber::::get(&0).is_none()); // 5 headers with number = 1 are pruned (6 total) - assert!(HeadersByNumber::get(&1).is_none()); + assert!(HeadersByNumber::::get(&1).is_none()); // 1 header with number = 2 are pruned (7 total) - assert_eq!(HeadersByNumber::get(&2).unwrap().len(), 4); + assert_eq!(HeadersByNumber::::get(&2).unwrap().len(), 4); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 2, oldest_block_to_keep: 10, @@ -1086,13 +1090,13 @@ pub(crate) mod tests { // try to prune blocks [2; 10) storage.prune_blocks(11, 10, 10); // 4 headers with number = 2 are pruned (4 total) - assert!(HeadersByNumber::get(&2).is_none()); + assert!(HeadersByNumber::::get(&2).is_none()); // 5 headers with number = 3 are pruned (9 total) - assert!(HeadersByNumber::get(&3).is_none()); + assert!(HeadersByNumber::::get(&3).is_none()); // 2 headers with number = 4 are pruned (11 total) - assert_eq!(HeadersByNumber::get(&4).unwrap().len(), 3); + assert_eq!(HeadersByNumber::::get(&4).unwrap().len(), 3); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 4, oldest_block_to_keep: 10, @@ -1109,16 +1113,16 @@ pub(crate) mod tests { // and one of blocks#7 has scheduled change // => we won't prune any block#7 at all storage.prune_blocks(0xFFFF, 5, 10); - assert!(HeadersByNumber::get(&0).is_none()); - assert!(HeadersByNumber::get(&1).is_none()); - assert!(HeadersByNumber::get(&2).is_none()); - assert!(HeadersByNumber::get(&3).is_none()); - assert!(HeadersByNumber::get(&4).is_none()); - assert!(HeadersByNumber::get(&5).is_none()); - assert!(HeadersByNumber::get(&6).is_none()); - assert_eq!(HeadersByNumber::get(&7).unwrap().len(), 5); + assert!(HeadersByNumber::::get(&0).is_none()); + assert!(HeadersByNumber::::get(&1).is_none()); + assert!(HeadersByNumber::::get(&2).is_none()); + assert!(HeadersByNumber::::get(&3).is_none()); + assert!(HeadersByNumber::::get(&4).is_none()); + assert!(HeadersByNumber::::get(&5).is_none()); + assert!(HeadersByNumber::::get(&6).is_none()); + assert_eq!(HeadersByNumber::::get(&7).unwrap().len(), 5); assert_eq!( - BlocksToPrune::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 7, oldest_block_to_keep: 10, @@ -1151,7 +1155,7 @@ pub(crate) mod tests { ); // when we later prune this header, cache entry is removed - BlocksToPrune::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: interval - 1, oldest_block_to_keep: interval - 1, }); @@ -1238,7 +1242,7 @@ pub(crate) mod tests { insert_header(&mut storage, header1s); // header1 is finalized - FinalizedBlock::put(header1_id); + FinalizedBlock::::put(header1_id); // trying to get finality votes when importing header2 -> header1 succeeds assert!( diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 0dde85bd93c5f..31717d53cc44e 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -136,7 +136,7 @@ pub fn run_test_with_genesis(genesis: Header, total_validators: usize, test: initial_difficulty: 0.into(), initial_validators: addresses.clone(), } - .build_storage::() + .build_storage::() .unwrap(), ) .execute_with(|| { diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index eacdb680e0ba1..e6e3ac4681c22 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -63,31 +63,31 @@ impl HeaderBuilder { /// Creates default header on top of test parent with given hash. #[cfg(test)] pub fn with_parent_hash(parent_hash: H256) -> Self { - Self::with_parent_hash_on_runtime::(parent_hash) + Self::with_parent_hash_on_runtime::(parent_hash) } /// Creates default header on top of test parent with given number. First parent is selected. #[cfg(test)] pub fn with_parent_number(parent_number: u64) -> Self { - Self::with_parent_number_on_runtime::(parent_number) + Self::with_parent_number_on_runtime::(parent_number) } /// Creates default header on top of parent with given hash. - pub fn with_parent_hash_on_runtime(parent_hash: H256) -> Self { + pub fn with_parent_hash_on_runtime, I: crate::Instance>(parent_hash: H256) -> Self { use crate::Headers; use frame_support::StorageMap; - let parent_header = Headers::::get(&parent_hash).unwrap().header; + let parent_header = Headers::::get(&parent_hash).unwrap().header; Self::with_parent(&parent_header) } /// Creates default header on top of parent with given number. First parent is selected. - pub fn with_parent_number_on_runtime(parent_number: u64) -> Self { + pub fn with_parent_number_on_runtime, I: crate::Instance>(parent_number: u64) -> Self { use crate::HeadersByNumber; use frame_support::StorageMap; - let parent_hash = HeadersByNumber::get(parent_number).unwrap()[0]; - Self::with_parent_hash_on_runtime::(parent_hash) + let parent_hash = HeadersByNumber::::get(parent_number).unwrap()[0]; + Self::with_parent_hash_on_runtime::(parent_hash) } /// Creates default header on top of non-existent parent. diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 7aa2dd8cb1ee9..9695e9a11be6d 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -276,6 +276,7 @@ impl ValidatorsSource { pub(crate) mod tests { use super::*; use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}; + use crate::DefaultInstance; use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader}; use frame_support::StorageMap; use primitives::compute_merkle_root; @@ -433,7 +434,7 @@ pub(crate) mod tests { }; Headers::::insert(id100.hash, header100); if let Some(scheduled_at) = scheduled_at { - ScheduledChanges::insert(scheduled_at.hash, scheduled_change); + ScheduledChanges::::insert(scheduled_at.hash, scheduled_change); } validators.finalize_validators_change(&storage, &finalized_blocks) diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 3b1c1865929ef..31f9c2e5531d2 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -361,6 +361,7 @@ mod tests { validators_change_receipt, AccountId, HeaderBuilder, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; + use crate::DefaultInstance; use crate::{ pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, ScheduledChanges, ValidatorsSet, ValidatorsSets, @@ -402,7 +403,7 @@ mod tests { let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators); insert_header(&mut storage, block3); - FinalizedBlock::put(block2_id); + FinalizedBlock::::put(block2_id); let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); @@ -419,21 +420,21 @@ mod tests { } fn change_validators_set_at(number: u64, finalized_set: Vec

, signalled_set: Option>) { - let set_id = NextValidatorsSetId::get(); - NextValidatorsSetId::put(set_id + 1); - ValidatorsSets::insert( + let set_id = NextValidatorsSetId::::get(); + NextValidatorsSetId::::put(set_id + 1); + ValidatorsSets::::insert( set_id, ValidatorsSet { validators: finalized_set, signal_block: None, enact_block: HeaderId { number: 0, - hash: HeadersByNumber::get(&0).unwrap()[0], + hash: HeadersByNumber::::get(&0).unwrap()[0], }, }, ); - let header_hash = HeadersByNumber::get(&number).unwrap()[0]; + let header_hash = HeadersByNumber::::get(&number).unwrap()[0]; let mut header = Headers::::get(&header_hash).unwrap(); header.next_validators_set_id = set_id; if let Some(signalled_set) = signalled_set { @@ -441,7 +442,7 @@ mod tests { number: header.header.number - 1, hash: header.header.parent_hash, }); - ScheduledChanges::insert( + ScheduledChanges::::insert( header.header.parent_hash, ScheduledChange { validators: signalled_set, diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index 28a3afd080803..131daf66eda51 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -134,8 +134,15 @@ impl CurrencyConverter for IdentityCurrencyConverter { } decl_runtime_apis! { - /// API for exchange transactions submitters. - pub trait CurrencyExchangeApi { + /// API for Rialto exchange transactions submitters. + pub trait RialtoCurrencyExchangeApi { + /// Returns true if currency exchange module is able to import transaction proof in + /// its current state. + fn filter_transaction_proof(proof: Proof) -> bool; + } + + /// API for Kovan exchange transactions submitters. + pub trait KovanCurrencyExchangeApi { /// Returns true if currency exchange module is able to import transaction proof in /// its current state. fn filter_transaction_proof(proof: Proof) -> bool; diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 6515f901feffd..444af8cfa3638 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -505,19 +505,32 @@ pub fn step_validator(header_validators: &[T], header_step: u64) -> &T { } sp_api::decl_runtime_apis! { - /// API for headers submitters. - pub trait EthereumHeadersApi { + /// API for querying information about headers from the Rialto Bridge Pallet + pub trait RialtoHeaderApi { /// Returns number and hash of the best block known to the bridge module. - /// The caller should only submit `import_header` transaction that makes + /// + /// The caller should only submit an `import_header` transaction that makes /// (or leads to making) other header the best one. fn best_block() -> (u64, H256); - /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (u64, H256); - /// Returns true if the import of given block requires transactions receipts. fn is_import_requires_receipts(header: Header) -> bool; + /// Returns true if header is known to the runtime. + fn is_known_block(hash: H256) -> bool; + } + /// API for querying information about headers from the Kovan Bridge Pallet + pub trait KovanHeaderApi { + /// Returns number and hash of the best block known to the bridge module. + /// + /// The caller should only submit an `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_block() -> (u64, H256); + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (u64, H256); + /// Returns true if the import of given block requires transactions receipts. + fn is_import_requires_receipts(header: Header) -> bool; /// Returns true if header is known to the runtime. fn is_known_block(hash: H256) -> bool; } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 32f219d4ea332..3865566d9183c 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -34,10 +34,10 @@ use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; use std::collections::VecDeque; -const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "EthereumHeadersApi_is_import_requires_receipts"; -const ETH_API_IS_KNOWN_BLOCK: &str = "EthereumHeadersApi_is_known_block"; -const ETH_API_BEST_BLOCK: &str = "EthereumHeadersApi_best_block"; -const ETH_API_BEST_FINALIZED_BLOCK: &str = "EthereumHeadersApi_finalized_block"; +const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoHeaderApi_is_import_requires_receipts"; +const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoHeaderApi_is_known_block"; +const ETH_API_BEST_BLOCK: &str = "RialtoHeaderApi_best_block"; +const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoHeaderApi_finalized_block"; const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "CurrencyExchangeApi_filter_transaction_proof"; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; @@ -336,7 +336,8 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { let nonce = self.next_account_index(account_id).await?; let transaction = create_signed_transaction( - bridge_node_runtime::Call::BridgeCurrencyExchange( + // TODO [#209]: Change so that that it's dynamic + bridge_node_runtime::Call::BridgeRialtoCurrencyExchange( bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof), ), ¶ms.signer, @@ -356,7 +357,8 @@ fn create_signed_submit_transaction( genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { create_signed_transaction( - bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + // TODO [#209]: Change so that that it's dynamic + bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( headers .into_iter() .map(|header| { @@ -376,7 +378,8 @@ fn create_signed_submit_transaction( /// Create unsigned Substrate transaction for submitting Ethereum header. fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { let function = - bridge_node_runtime::Call::BridgeEthPoA(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + // TODO [#209]: Change so that that it's dynamic + bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( into_substrate_ethereum_header(header.header()), into_substrate_ethereum_receipts(header.extra()), )); From c3a1da5e5897ef764a776cae130fd602365fbf67 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 28 Jul 2020 01:47:54 -0400 Subject: [PATCH 0113/1210] Fix Local Dockerfile Entrypoint (#233) * Correctly resolve project in Dockerfile entrypoint * Improve instruction for running local Docker containers * Rename bridge entrypoint script --- README.md | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 381ea37a7d603..3906389c51448 100644 --- a/README.md +++ b/README.md @@ -158,12 +158,39 @@ The folder structure of the bridge relay is as follows: ## Running the Bridge -To run the Bridge you need to be able to connect to the RPC interface of nodes on each side of the -bridge (home & foreign chain). +To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes +on each side of the bridge (home & foreign chain). An easy way to build all the required nodes is +through Docker. -You can build the relayer using [./Dockerfile](Dockerfile), which will use all the local source files, -or you can use an image that is designed to build from Github repo sources (`master` branch by -default, configurable via `build-arg`): +### Local Docker Build +If you want to make a Docker container using your local source files you can run the following +command at the top level of the repository: + +```bash +docker build . -t bridge-relay-dev +``` + +You can also build and run the Substrate based node as follows: + +```bash +docker build . -t bridge-node-dev --build-arg PROJECT=bridge-node +``` + +To run the Substrate node you can do the following: + +```bash +docker run -it bridge-node-dev --dev --tmp +``` + +Notice that the `docker run` command will accept all the normal Substrate flags. For local +development you should at minimum run with the `--dev` flag or else no blocks will be produced. + +### GitHub Docker Build +If you don't want to run using the local source files you can also use images which pull the latest +`master`, or some other commit or branch of your choosing (configured with the `BRIDGE_HASH` build +argument). + +These images live in the [Rialto deployments](./deployments/rialto) folder. ```bash docker build \ @@ -181,7 +208,7 @@ docker build \ https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ -t bridge-node \ --build-arg PROJECT=bridge-node -docker run -it bridge-node +docker run -it bridge-node --dev ``` And to build `OpenEthereum` with bridge support: @@ -192,5 +219,6 @@ docker build \ docker run -it openethereum ``` +### Full Network Docker Setup See [Deployments README](./deployments/README.md) to learn more about how to run a more sophisticated test network using `docker-compose` setup. From cfb6b8d043a6c23fa2cdd03a63c743aee28fc909 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Jul 2020 13:57:25 +0300 Subject: [PATCH 0114/1210] Make transactions receipts part of transaction inclusion proof (#236) * make receipts part of tx proof * is_successful_raw_receipt_with_empty_data * cargo fmt --all * clippy * fix everything --- bin/node/runtime/src/exchange.rs | 58 ++++++---- bin/node/runtime/src/kovan.rs | 2 +- bin/node/runtime/src/lib.rs | 4 +- bin/node/runtime/src/rialto.rs | 2 +- modules/ethereum/src/lib.rs | 122 ++++++++++++++++++++-- modules/ethereum/src/test_utils.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 111 ++++++++++++++++++-- primitives/ethereum-poa/src/signatures.rs | 6 +- relays/ethereum/src/ethereum_exchange.rs | 27 +++-- relays/ethereum/src/substrate_types.rs | 44 ++++---- 10 files changed, 303 insertions(+), 75 deletions(-) diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index e41ec9ac40498..8754bec0893ff 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -30,7 +30,7 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use hex_literal::hex; -use sp_bridge_eth_poa::{transaction_decode, RawTransaction}; +use sp_bridge_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; use sp_currency_exchange::{ Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, }; @@ -46,8 +46,9 @@ pub struct EthereumTransactionInclusionProof { pub block: sp_core::H256, /// Index of the transaction within the block. pub index: u64, - /// The proof itself (right now it is all RLP-encoded transactions of the block). - pub proof: Vec, + /// The proof itself (right now it is all RLP-encoded transactions of the block + + /// RLP-encoded receipts of all transactions of the block). + pub proof: Vec<(RawTransaction, RawTransactionReceipt)>, } /// We uniquely identify transfer by the pair (sender, nonce). @@ -76,7 +77,7 @@ impl MaybeLockFundsTransaction for EthTransaction { fn parse( raw_tx: &Self::Transaction, ) -> ExchangeResult> { - let tx = transaction_decode(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?; + let tx = transaction_decode_rlp(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?; // we only accept transactions sending funds directly to the pre-configured address if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) { @@ -128,7 +129,7 @@ impl MaybeLockFundsTransaction for EthTransaction { /// Prepares everything required to bench claim of funds locked by given transaction. #[cfg(feature = "runtime-benchmarks")] pub(crate) fn prepare_environment_for_claim, I: pallet_bridge_eth_poa::Instance>( - transactions: &[RawTransaction], + transactions: &[(RawTransaction, RawTransactionReceipt)], ) -> sp_bridge_eth_poa::H256 { use pallet_bridge_eth_poa::{ test_utils::{insert_header, validator_utils::validator, HeaderBuilder}, @@ -138,7 +139,8 @@ pub(crate) fn prepare_environment_for_claim, let mut storage = BridgeStorage::::new(); let header = HeaderBuilder::with_parent_number_on_runtime::(0) - .with_transactions_root(compute_merkle_root(transactions.iter())) + .transactions_root(compute_merkle_root(transactions.iter().map(|(tx, _)| tx))) + .receipts_root(compute_merkle_root(transactions.iter().map(|(_, receipt)| receipt))) .sign_by(&validator(0)); let header_id = header.compute_id(); insert_header(&mut storage, header); @@ -152,8 +154,8 @@ pub(crate) fn prepare_environment_for_claim, pub(crate) fn prepare_ethereum_transaction( recipient: &crate::AccountId, editor: impl Fn(&mut sp_bridge_eth_poa::UnsignedTransaction), -) -> Vec { - use sp_bridge_eth_poa::signatures::SignTransaction; +) -> (RawTransaction, RawTransactionReceipt) { + use sp_bridge_eth_poa::{signatures::SignTransaction, Receipt, TransactionOutcome}; // prepare tx for OpenEthereum private dev chain: // chain id is 0x11 @@ -173,7 +175,16 @@ pub(crate) fn prepare_ethereum_transaction( payload: recipient_raw.to_vec(), }; editor(&mut eth_tx); - eth_tx.sign_by(&signer, Some(chain_id)) + ( + eth_tx.sign_by(&signer, Some(chain_id)), + Receipt { + outcome: TransactionOutcome::StatusCode(1), + gas_used: Default::default(), + log_bloom: Default::default(), + logs: Vec::new(), + } + .rlp(), + ) } #[cfg(test)] @@ -188,7 +199,7 @@ mod tests { #[test] fn valid_transaction_accepted() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |_| {})), + EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |_| {}).0), Ok(LockFundsTransaction { id: EthereumTransactionTag { account: hex!("00a329c0648769a73afac7f9381e08fb43dbea72"), @@ -211,9 +222,12 @@ mod tests { #[test] fn transaction_with_invalid_peer_recipient_rejected() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |tx| { - tx.to = None; - })), + EthTransaction::parse( + &prepare_ethereum_transaction(&ferdie(), |tx| { + tx.to = None; + }) + .0 + ), Err(ExchangeError::InvalidTransaction), ); } @@ -221,9 +235,12 @@ mod tests { #[test] fn transaction_with_invalid_recipient_rejected() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |tx| { - tx.payload.clear(); - })), + EthTransaction::parse( + &prepare_ethereum_transaction(&ferdie(), |tx| { + tx.payload.clear(); + }) + .0 + ), Err(ExchangeError::InvalidRecipient), ); } @@ -231,9 +248,12 @@ mod tests { #[test] fn transaction_with_invalid_amount_rejected() { assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |tx| { - tx.value = sp_core::U256::from(u128::max_value()) + sp_core::U256::from(1); - })), + EthTransaction::parse( + &prepare_ethereum_transaction(&ferdie(), |tx| { + tx.value = sp_core::U256::from(u128::max_value()) + sp_core::U256::from(1); + }) + .0 + ), Err(ExchangeError::InvalidAmount), ); } diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index ad641aa728a6d..005aaa8f7b961 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -149,7 +149,7 @@ impl PeerBlockchain for KovanBlockchain { return None; } - proof.proof.get(proof.index as usize).cloned() + proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 6c4ad00692e4b..113f32f09138c 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -716,7 +716,7 @@ impl_runtime_apis! { ).unwrap(); } - let transaction = crate::exchange::prepare_ethereum_transaction( + let (transaction, receipt) = crate::exchange::prepare_ethereum_transaction( &proof_params.recipient, |tx| { // our runtime only supports transactions where data is exactly 32 bytes long @@ -725,7 +725,7 @@ impl_runtime_apis! { tx.value = (ExistentialDeposit::get() * 10).into(); }, ); - let transactions = sp_std::iter::repeat(transaction.clone()) + let transactions = sp_std::iter::repeat((transaction, receipt)) .take(1 + proof_params.proof_size_factor as usize) .collect::>(); let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs index 6560dbb398097..195fed1693fdb 100644 --- a/bin/node/runtime/src/rialto.rs +++ b/bin/node/runtime/src/rialto.rs @@ -122,7 +122,7 @@ impl PeerBlockchain for RialtoBlockchain { return None; } - proof.proof.get(proof.index as usize).cloned() + proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index de25c5aaa218b..ae6399f002fc1 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -21,7 +21,7 @@ use crate::finality::{CachedFinalityVotes, FinalityVotes}; use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage, traits::Get}; -use primitives::{Address, Header, HeaderId, RawTransaction, Receipt, H256, U256}; +use primitives::{Address, Header, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; use sp_runtime::{ transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity, @@ -510,7 +510,11 @@ impl, I: Instance> Module { } /// Verify that transaction is included into given finalized block. - pub fn verify_transaction_finalized(block: H256, tx_index: u64, proof: &[RawTransaction]) -> bool { + pub fn verify_transaction_finalized( + block: H256, + tx_index: u64, + proof: &[(RawTransaction, RawTransactionReceipt)], + ) -> bool { crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) } } @@ -886,7 +890,7 @@ pub fn verify_transaction_finalized( storage: &S, block: H256, tx_index: u64, - proof: &[RawTransaction], + proof: &[(RawTransaction, RawTransactionReceipt)], ) -> bool { if tx_index >= proof.len() as _ { return false; @@ -914,7 +918,21 @@ pub fn verify_transaction_finalized( return false; } - header.verify_transactions_root(proof) + // verify that transaction is included in the block + if !header.verify_transactions_root(proof.iter().map(|(tx, _)| tx)) { + return false; + } + + // verify that transaction receipt is included in the block + if !header.verify_raw_receipts_root(proof.iter().map(|(_, r)| r)) { + return false; + } + + // check that transaction has completed successfully + matches!( + Receipt::is_successful_raw_receipt(&proof[tx_index as usize].1), + Ok(true) + ) } /// Transaction pool configuration. @@ -954,10 +972,31 @@ pub(crate) mod tests { vec![42] } + fn example_tx_receipt(success: bool) -> Vec { + Receipt { + // the only thing that we care of: + outcome: primitives::TransactionOutcome::StatusCode(if success { 1 } else { 0 }), + gas_used: Default::default(), + log_bloom: Default::default(), + logs: Vec::new(), + } + .rlp() + } + + fn example_header_with_failed_receipt() -> Header { + let mut header = Header::default(); + header.number = 3; + header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.receipts_root = compute_merkle_root(vec![example_tx_receipt(false)].into_iter()); + header.parent_hash = example_header().compute_hash(); + header + } + fn example_header() -> Header { let mut header = Header::default(); header.number = 2; header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.receipts_root = compute_merkle_root(vec![example_tx_receipt(true)].into_iter()); header.parent_hash = example_header_parent().compute_hash(); header } @@ -966,6 +1005,7 @@ pub(crate) mod tests { let mut header = Header::default(); header.number = 1; header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); + header.receipts_root = compute_merkle_root(vec![example_tx_receipt(true)].into_iter()); header.parent_hash = genesis().compute_hash(); header } @@ -1265,7 +1305,12 @@ pub(crate) mod tests { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &[example_tx()],), + verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(true))], + ), true, ); }); @@ -1279,7 +1324,12 @@ pub(crate) mod tests { insert_header(&mut storage, example_header()); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( - verify_transaction_finalized(&storage, example_header_parent().compute_hash(), 0, &[example_tx()],), + verify_transaction_finalized( + &storage, + example_header_parent().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(true))], + ), true, ); }); @@ -1314,7 +1364,12 @@ pub(crate) mod tests { insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 0, &[example_tx()],), + verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(true))], + ), false, ); }); @@ -1333,7 +1388,12 @@ pub(crate) mod tests { insert_header(&mut storage, finalized_header_sibling); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( - verify_transaction_finalized(&storage, finalized_header_sibling_hash, 0, &[example_tx()],), + verify_transaction_finalized( + &storage, + finalized_header_sibling_hash, + 0, + &[(example_tx(), example_tx_receipt(true))], + ), false, ); }); @@ -1352,14 +1412,19 @@ pub(crate) mod tests { insert_header(&mut storage, example_header()); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); assert_eq!( - verify_transaction_finalized(&storage, finalized_header_uncle_hash, 0, &[example_tx()],), + verify_transaction_finalized( + &storage, + finalized_header_uncle_hash, + 0, + &[(example_tx(), example_tx_receipt(true))], + ), false, ); }); } #[test] - fn verify_transaction_finalized_rejects_invalid_proof() { + fn verify_transaction_finalized_rejects_invalid_transactions_in_proof() { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); assert_eq!( @@ -1367,7 +1432,42 @@ pub(crate) mod tests { &storage, example_header().compute_hash(), 0, - &[example_tx(), example_tx()], + &[ + (example_tx(), example_tx_receipt(true)), + (example_tx(), example_tx_receipt(true)) + ], + ), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_invalid_receipts_in_proof() { + run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { + let storage = BridgeStorage::::new(); + assert_eq!( + verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[(example_tx(), vec![42])], + ), + false, + ); + }); + } + + #[test] + fn verify_transaction_finalized_rejects_failed_transaction() { + run_test_with_genesis(example_header_with_failed_receipt(), TOTAL_VALIDATORS, |_| { + let storage = BridgeStorage::::new(); + assert_eq!( + verify_transaction_finalized( + &storage, + example_header_with_failed_receipt().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(false))], ), false, ); diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index e6e3ac4681c22..035882450fbb5 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -195,7 +195,7 @@ impl HeaderBuilder { } /// Update transactions root field of this header. - pub fn with_transactions_root(mut self, transactions_root: H256) -> Self { + pub fn transactions_root(mut self, transactions_root: H256) -> Self { self.header.transactions_root = transactions_root; self } diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 444af8cfa3638..f418a8e325b80 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -48,6 +48,9 @@ impl_fixed_hash_serde!(H520, 65); /// Raw (RLP-encoded) ethereum transaction. pub type RawTransaction = Vec; +/// Raw (RLP-encoded) ethereum transaction receipt. +pub type RawTransactionReceipt = Vec; + /// An ethereum address. pub type Address = H160; @@ -208,9 +211,14 @@ impl Header { verify_merkle_proof(self.receipts_root, receipts.iter().map(|r| r.rlp())) } + /// Check if passed raw transactions receipts are matching receipts root in this header. + pub fn verify_raw_receipts_root<'a>(&self, receipts: impl IntoIterator) -> bool { + verify_merkle_proof(self.receipts_root, receipts.into_iter()) + } + /// Check if passed transactions are matching transactions root in this header. - pub fn verify_transactions_root(&self, transactions: &[RawTransaction]) -> bool { - verify_merkle_proof(self.transactions_root, transactions.iter()) + pub fn verify_transactions_root<'a>(&self, transactions: impl IntoIterator) -> bool { + verify_merkle_proof(self.transactions_root, transactions.into_iter()) } /// Gets the seal hash of this header. @@ -277,7 +285,7 @@ impl Header { impl UnsignedTransaction { /// Decode unsigned portion of raw transaction RLP. - pub fn decode(raw_tx: &[u8]) -> Result { + pub fn decode_rlp(raw_tx: &[u8]) -> Result { let tx_rlp = Rlp::new(raw_tx); let to = tx_rlp.at(3)?; Ok(UnsignedTransaction { @@ -325,6 +333,25 @@ impl UnsignedTransaction { } impl Receipt { + /// Decode status from raw transaction receipt RLP. + pub fn is_successful_raw_receipt(raw_receipt: &[u8]) -> Result { + let rlp = Rlp::new(raw_receipt); + if rlp.item_count()? == 3 { + // no outcome - invalid tx? + Ok(false) + } else { + let first = rlp.at(0)?; + if first.is_data() && first.data()?.len() <= 1 { + // EIP-658 transaction - status of successful transaction is 1 + let status: u8 = first.as_val()?; + Ok(status == 1) + } else { + // pre-EIP-658 transaction - we do not support this kind of transactions + Ok(false) + } + } + } + /// Returns receipt RLP. pub fn rlp(&self) -> Bytes { let mut s = RlpStream::new(); @@ -436,9 +463,9 @@ impl std::fmt::Debug for Bloom { } /// Decode Ethereum transaction. -pub fn transaction_decode(raw_tx: &[u8]) -> Result { +pub fn transaction_decode_rlp(raw_tx: &[u8]) -> Result { // parse transaction fields - let unsigned = UnsignedTransaction::decode(raw_tx)?; + let unsigned = UnsignedTransaction::decode_rlp(raw_tx)?; let tx_rlp = Rlp::new(raw_tx); let v: u64 = tx_rlp.val_at(6)?; let r: U256 = tx_rlp.val_at(7)?; @@ -548,7 +575,7 @@ mod tests { // https://etherscan.io/getRawTx?tx=0xb9d4ad5408f53eac8627f9ccd840ba8fb3469d55cd9cc2a11c6e049f1eef4edd let raw_tx = hex!("f86c0a85046c7cfe0083016dea94d1310c1e038bc12865d3d3997275b3e4737c6302880b503be34d9fe80080269fc7eaaa9c21f59adf8ad43ed66cf5ef9ee1c317bd4d32cd65401e7aaca47cfaa0387d79c65b90be6260d09dcfb780f29dd8133b9b1ceb20b83b7e442b4bfc30cb"); assert_eq!( - transaction_decode(&raw_tx), + transaction_decode_rlp(&raw_tx), Ok(Transaction { sender: hex!("67835910d32600471f388a137bbff3eb07993c04").into(), unsigned: UnsignedTransaction { @@ -567,7 +594,7 @@ mod tests { // https://kovan.etherscan.io/getRawTx?tx=0x3b4b7bd41c1178045ccb4753aa84c1ef9864b4d712fa308b228917cd837915da let raw_tx = hex!("f86a822816808252089470c1ccde719d6f477084f07e4137ab0e55f8369f8930cf46e92063afd8008078a00e4d1f4d8aa992bda3c105ff3d6e9b9acbfd99facea00985e2131029290adbdca028ea29a46a4b66ec65b454f0706228e3768cb0ecf755f67c50ddd472f11d5994"); assert_eq!( - transaction_decode(&raw_tx), + transaction_decode_rlp(&raw_tx), Ok(Transaction { sender: hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(), unsigned: UnsignedTransaction { @@ -589,7 +616,7 @@ mod tests { // https://etherscan.io/getRawTx?tx=0xdc2b996b4d1d6922bf6dba063bfd70913279cb6170967c9bb80252aeb061cf65 let raw_tx = hex!("f8aa76850430e234008301500094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b4025a0964e023999621dc3d4d831c43c71f7555beb6d1192dee81a3674b3f57e310f21a00f229edd86f841d1ee4dc48cc16667e2283817b1d39bae16ced10cd206ae4fd4"); assert_eq!( - transaction_decode(&raw_tx), + transaction_decode_rlp(&raw_tx), Ok(Transaction { sender: hex!("2b9a4d37bdeecdf994c4c9ad7f3cf8dc632f7d70").into(), unsigned: UnsignedTransaction { @@ -608,7 +635,7 @@ mod tests { // https://kovan.etherscan.io/getRawTx?tx=0x2904b4451d23665492239016b78da052d40d55fdebc7304b38e53cf6a37322cf let raw_tx = hex!("f8ac8302200b843b9aca00830271009484dd11eb2a29615303d18149c0dbfa24167f896680b844a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b600000000000000000000000000000000000000000000000000000000000027101ba0ce126d2cca81f5e245f292ff84a0d915c0a4ac52af5c51219db1e5d36aa8da35a0045298b79dac631907403888f9b04c2ab5509fe0cc31785276d30a40b915fcf9"); assert_eq!( - transaction_decode(&raw_tx), + transaction_decode_rlp(&raw_tx), Ok(Transaction { sender: hex!("617da121abf03d4c1af572f5a4e313e26bef7bdc").into(), unsigned: UnsignedTransaction { @@ -622,4 +649,70 @@ mod tests { }), ); } + + #[test] + fn is_successful_raw_receipt_works() { + assert!(Receipt::is_successful_raw_receipt(&[]).is_err()); + + assert_eq!( + Receipt::is_successful_raw_receipt( + &Receipt { + outcome: TransactionOutcome::Unknown, + gas_used: Default::default(), + log_bloom: Default::default(), + logs: Vec::new(), + } + .rlp() + ), + Ok(false), + ); + assert_eq!( + Receipt::is_successful_raw_receipt( + &Receipt { + outcome: TransactionOutcome::StateRoot(Default::default()), + gas_used: Default::default(), + log_bloom: Default::default(), + logs: Vec::new(), + } + .rlp() + ), + Ok(false), + ); + assert_eq!( + Receipt::is_successful_raw_receipt( + &Receipt { + outcome: TransactionOutcome::StatusCode(0), + gas_used: Default::default(), + log_bloom: Default::default(), + logs: Vec::new(), + } + .rlp() + ), + Ok(false), + ); + assert_eq!( + Receipt::is_successful_raw_receipt( + &Receipt { + outcome: TransactionOutcome::StatusCode(1), + gas_used: Default::default(), + log_bloom: Default::default(), + logs: Vec::new(), + } + .rlp() + ), + Ok(true), + ); + } + + #[test] + fn is_successful_raw_receipt_with_empty_data() { + let mut stream = RlpStream::new(); + stream.begin_list(4); + stream.append_empty_data(); + stream.append(&1u64); + stream.append(&2u64); + stream.append(&3u64); + + assert_eq!(Receipt::is_successful_raw_receipt(&stream.out()), Ok(false),); + } } diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs index 309297e1ccbc5..4d97fbcbfbd1a 100644 --- a/primitives/ethereum-poa/src/signatures.rs +++ b/primitives/ethereum-poa/src/signatures.rs @@ -98,7 +98,7 @@ pub fn secret_to_address(secret: &SecretKey) -> Address { #[cfg(test)] mod tests { use super::*; - use crate::{transaction_decode, Transaction}; + use crate::{transaction_decode_rlp, Transaction}; #[test] fn transaction_signed_properly() { @@ -115,7 +115,7 @@ mod tests { }; let raw_tx = unsigned.clone().sign_by(&signer, Some(42)); assert_eq!( - transaction_decode(&raw_tx), + transaction_decode_rlp(&raw_tx), Ok(Transaction { sender: signer_address, unsigned, @@ -133,7 +133,7 @@ mod tests { }; let raw_tx = unsigned.clone().sign_by(&signer, None); assert_eq!( - transaction_decode(&raw_tx), + transaction_decode_rlp(&raw_tx), Ok(Transaction { sender: signer_address, unsigned, diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index d27f3345e8a6a..62e2d3eefb6c5 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -31,6 +31,7 @@ use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; +use crate::substrate_types::into_substrate_ethereum_receipt; use crate::sync_types::HeaderId; use async_trait::async_trait; @@ -169,12 +170,17 @@ impl SourceClient for EthereumTransactionsSource { node are having `raw` field; qed"; const BLOCK_HAS_HASH_FIELD_PROOF: &str = "RPC level checks that block has `hash` field; qed"; - let transaction_proof = block - .0 - .transactions - .iter() - .map(|tx| tx.raw.clone().expect(TRANSACTION_HAS_RAW_FIELD_PROOF).0) - .collect(); + let mut transaction_proof = Vec::with_capacity(block.0.transactions.len()); + for tx in &block.0.transactions { + let raw_tx_receipt = self + .client + .transaction_receipt(tx.hash) + .await + .map(|receipt| into_substrate_ethereum_receipt(&receipt)) + .map(|receipt| receipt.rlp())?; + let raw_tx = tx.raw.clone().expect(TRANSACTION_HAS_RAW_FIELD_PROOF).0; + transaction_proof.push((raw_tx, raw_tx_receipt)); + } Ok(EthereumTransactionInclusionProof { block: block.0.hash.expect(BLOCK_HAS_HASH_FIELD_PROOF), @@ -221,11 +227,18 @@ impl TargetClient for SubstrateTransactionsTarget { async fn filter_transaction_proof(&self, proof: &EthereumTransactionInclusionProof) -> Result { // let's try to parse transaction locally - let parse_result = bridge_node_runtime::exchange::EthTransaction::parse(&proof.proof[proof.index as usize]); + let (raw_tx, raw_tx_receipt) = &proof.proof[proof.index as usize]; + let parse_result = bridge_node_runtime::exchange::EthTransaction::parse(raw_tx); if parse_result.is_err() { return Ok(false); } + // now let's check if transaction is successful + match sp_bridge_eth_poa::Receipt::is_successful_raw_receipt(raw_tx_receipt) { + Ok(true) => (), + _ => return Ok(false), + } + // seems that transaction is relayable - let's check if runtime is able to import it // (we can't if e.g. header is pruned or there's some issue with tx data) self.client.verify_exchange_transaction_proof(proof.clone()).await diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 66e5aee67282b..7d761a627e66a 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -100,27 +100,29 @@ pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEther pub fn into_substrate_ethereum_receipts( receipts: &Option>, ) -> Option> { - receipts.as_ref().map(|receipts| { - receipts + receipts + .as_ref() + .map(|receipts| receipts.iter().map(into_substrate_ethereum_receipt).collect()) +} + +/// Convert Ethereum transactions receipt into Ethereum transactions receipt for Substrate. +pub fn into_substrate_ethereum_receipt(receipt: &EthereumReceipt) -> SubstrateEthereumReceipt { + SubstrateEthereumReceipt { + gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), + log_bloom: receipt.logs_bloom.data().into(), + logs: receipt + .logs .iter() - .map(|receipt| SubstrateEthereumReceipt { - gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), - log_bloom: receipt.logs_bloom.data().into(), - logs: receipt - .logs - .iter() - .map(|log_entry| SubstrateEthereumLogEntry { - address: log_entry.address, - topics: log_entry.topics.clone(), - data: log_entry.data.0.clone(), - }) - .collect(), - outcome: match (receipt.status, receipt.root) { - (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), - (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), - _ => SubstrateEthereumTransactionOutcome::Unknown, - }, + .map(|log_entry| SubstrateEthereumLogEntry { + address: log_entry.address, + topics: log_entry.topics.clone(), + data: log_entry.data.0.clone(), }) - .collect() - }) + .collect(), + outcome: match (receipt.status, receipt.root) { + (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), + (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), + _ => SubstrateEthereumTransactionOutcome::Unknown, + }, + } } From 7d9fee18609aef2e40227316926a9ab167196f21 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Jul 2020 14:08:20 +0300 Subject: [PATCH 0115/1210] Auto exchange transactions relay metrics (#237) * auto exchange tx relay dashboard * cargo fmt --all * single metrics startup fn --- relays/ethereum/src/cli.yml | 3 + relays/ethereum/src/ethereum_exchange.rs | 5 ++ relays/ethereum/src/exchange.rs | 9 ++- relays/ethereum/src/exchange_loop.rs | 30 ++++++- relays/ethereum/src/exchange_loop_metrics.rs | 84 ++++++++++++++++++++ relays/ethereum/src/main.rs | 2 + relays/ethereum/src/metrics.rs | 62 +++++++++++---- relays/ethereum/src/sync_loop.rs | 25 +----- relays/ethereum/src/sync_loop_metrics.rs | 17 ++-- 9 files changed, 187 insertions(+), 50 deletions(-) create mode 100644 relays/ethereum/src/exchange_loop_metrics.rs diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 2026da39ef465..6e11c70ada3a5 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -127,3 +127,6 @@ subcommands: - sub-port: *sub-port - sub-signer: *sub-signer - sub-signer-password: *sub-signer-password + - no-prometheus: *no-prometheus + - prometheus-host: *prometheus-host + - prometheus-port: *prometheus-port diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 62e2d3eefb6c5..9661f28f195ed 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -26,6 +26,7 @@ use crate::exchange::{ TransactionProofPipeline, }; use crate::exchange_loop::{run as run_loop, InMemoryStorage}; +use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_client::{ @@ -64,6 +65,8 @@ pub struct EthereumExchangeParams { pub sub_sign: SubstrateSigningParams, /// Relay working mode. pub mode: ExchangeRelayMode, + /// Metrics parameters. + pub metrics_params: Option, } /// Ethereum to Substrate exchange pipeline. @@ -257,6 +260,7 @@ impl Default for EthereumExchangeParams { sub: Default::default(), sub_sign: Default::default(), mode: ExchangeRelayMode::Auto(None), + metrics_params: Some(Default::default()), } } } @@ -335,6 +339,7 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi client: sub_client, sign_params: params.sub_sign, }, + params.metrics_params, futures::future::pending(), ); diff --git a/relays/ethereum/src/exchange.rs b/relays/ethereum/src/exchange.rs index 4de47e5975053..58ddcf6b66647 100644 --- a/relays/ethereum/src/exchange.rs +++ b/relays/ethereum/src/exchange.rs @@ -42,7 +42,14 @@ pub trait SourceBlock { /// Block hash type. type Hash: Clone + Debug + Display; /// Block number type. - type Number: Debug + Display + Clone + Copy + std::cmp::Ord + std::ops::Add + num_traits::One; + type Number: Debug + + Display + + Clone + + Copy + + Into + + std::cmp::Ord + + std::ops::Add + + num_traits::One; /// Block transaction. type Transaction: SourceTransaction; diff --git a/relays/ethereum/src/exchange_loop.rs b/relays/ethereum/src/exchange_loop.rs index 678211d7c139f..b089e70328003 100644 --- a/relays/ethereum/src/exchange_loop.rs +++ b/relays/ethereum/src/exchange_loop.rs @@ -20,6 +20,8 @@ use crate::exchange::{ relay_block_transactions, BlockNumberOf, RelayedBlockTransactions, SourceClient, TargetClient, TransactionProofPipeline, }; +use crate::exchange_loop_metrics::ExchangeLoopMetrics; +use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; use crate::utils::retry_backoff; use backoff::backoff::Backoff; @@ -83,6 +85,7 @@ pub fn run( mut storage: impl TransactionProofsRelayStorage>, source_client: impl SourceClient

, target_client: impl TargetClient

, + metrics_params: Option, exit_signal: impl Future, ) { let mut local_pool = futures::executor::LocalPool::new(); @@ -92,6 +95,11 @@ pub fn run( let mut state = storage.state(); let mut current_finalized_block = None; + let mut metrics_global = GlobalMetrics::new(); + let mut metrics_exch = ExchangeLoopMetrics::new(); + let metrics_enabled = metrics_params.is_some(); + metrics_start(metrics_params, &metrics_global, &metrics_exch); + let exit_signal = exit_signal.fuse(); futures::pin_mut!(exit_signal); @@ -103,9 +111,14 @@ pub fn run( &target_client, &mut state, &mut current_finalized_block, + if metrics_enabled { Some(&mut metrics_exch) } else { None }, ) .await; + if metrics_enabled { + metrics_global.update(); + } + match iteration_result { Ok(_) => { retry_backoff.reset(); @@ -135,6 +148,7 @@ async fn run_loop_iteration( target_client: &impl TargetClient

, state: &mut TransactionProofsRelayState>, current_finalized_block: &mut Option<(P::Block, RelayedBlockTransactions)>, + mut exchange_loop_metrics: Option<&mut ExchangeLoopMetrics>, ) -> Result<(), ()> { let best_finalized_header_id = match target_client.best_finalized_header_id().await { Ok(best_finalized_header_id) => { @@ -181,6 +195,14 @@ async fn run_loop_iteration( state.best_processed_header_number = state.best_processed_header_number + One::one(); storage.set_state(state); + if let Some(exchange_loop_metrics) = exchange_loop_metrics.as_mut() { + exchange_loop_metrics.update::

( + state.best_processed_header_number, + best_finalized_header_id.0, + relayed_transactions, + ); + } + // we have just updated state => proceed to next block retrieval } Err(relayed_transactions) => { @@ -262,6 +284,12 @@ mod tests { } })); - run(storage, source, target, exit_receiver.into_future().map(|(_, _)| ())); + run( + storage, + source, + target, + None, + exit_receiver.into_future().map(|(_, _)| ()), + ); } } diff --git a/relays/ethereum/src/exchange_loop_metrics.rs b/relays/ethereum/src/exchange_loop_metrics.rs new file mode 100644 index 0000000000000..438360e22435b --- /dev/null +++ b/relays/ethereum/src/exchange_loop_metrics.rs @@ -0,0 +1,84 @@ +// Copyright 2019-2020 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 . + +use crate::exchange::{BlockNumberOf, RelayedBlockTransactions, TransactionProofPipeline}; +use crate::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; + +/// Exchange transactions relay metrics. +pub struct ExchangeLoopMetrics { + /// Best finalized block numbers - "processed" and "known". + best_block_numbers: GaugeVec, + /// Number of processed blocks ("total"). + processed_blocks: Counter, + /// Number of processed transactions ("total", "relayed" and "failed"). + processed_transactions: CounterVec, +} + +impl Metrics for ExchangeLoopMetrics { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; + register(self.processed_blocks.clone(), registry).map_err(|e| e.to_string())?; + register(self.processed_transactions.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + +impl ExchangeLoopMetrics { + /// Creates sync loop metrics. + pub fn new() -> Self { + ExchangeLoopMetrics { + best_block_numbers: GaugeVec::new( + Opts::new("best_block_numbers", "Best finalized block numbers"), + &["type"], + ) + .expect("metric is static and thus valid; qed"), + processed_blocks: Counter::new("processed_blocks", "Total number of processed blocks") + .expect("metric is static and thus valid; qed"), + processed_transactions: CounterVec::new( + Opts::new("processed_transactions", "Total number of processed transactions"), + &["type"], + ) + .expect("metric is static and thus valid; qed"), + } + } + + /// Update metrics when single block is relayed. + pub fn update( + &mut self, + best_processed_block_number: BlockNumberOf

, + best_known_block_number: BlockNumberOf

, + relayed_transactions: RelayedBlockTransactions, + ) { + self.best_block_numbers + .with_label_values(&["processed"]) + .set(best_processed_block_number.into()); + self.best_block_numbers + .with_label_values(&["known"]) + .set(best_known_block_number.into()); + + self.processed_blocks.inc(); + + self.processed_transactions + .with_label_values(&["total"]) + .inc_by(relayed_transactions.processed as _); + self.processed_transactions + .with_label_values(&["relayed"]) + .inc_by(relayed_transactions.relayed as _); + self.processed_transactions + .with_label_values(&["failed"]) + .inc_by(relayed_transactions.failed as _); + } +} diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 403ff101f8639..caddcfb9ca496 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -23,6 +23,7 @@ mod ethereum_sync_loop; mod ethereum_types; mod exchange; mod exchange_loop; +mod exchange_loop_metrics; mod headers; mod metrics; mod rpc; @@ -260,6 +261,7 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result ethereum_exchange::ExchangeRelayMode::Single( diff --git a/relays/ethereum/src/metrics.rs b/relays/ethereum/src/metrics.rs index 95e84fc6473f8..084b5ae10fa08 100644 --- a/relays/ethereum/src/metrics.rs +++ b/relays/ethereum/src/metrics.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -pub use substrate_prometheus_endpoint::{register, Gauge, GaugeVec, Opts, Registry, F64, U64}; +pub use substrate_prometheus_endpoint::{register, Counter, CounterVec, Gauge, GaugeVec, Opts, Registry, F64, U64}; use std::net::SocketAddr; use substrate_prometheus_endpoint::init_prometheus; @@ -29,6 +29,12 @@ pub struct MetricsParams { pub port: u16, } +/// Metrics API. +pub trait Metrics { + /// Register metrics in the registry. + fn register(&self, registry: &Registry) -> Result<(), String>; +} + /// Global Prometheus metrics. #[derive(Debug)] pub struct GlobalMetrics { @@ -39,19 +45,40 @@ pub struct GlobalMetrics { } /// Start Prometheus endpoint with given metrics registry. -pub async fn start(params: MetricsParams, registry: Registry) -> Result<(), String> { - init_prometheus( - SocketAddr::new( +pub fn start(params: Option, global_metrics: &GlobalMetrics, extra_metrics: &impl Metrics) { + let params = match params { + Some(params) => params, + None => return, + }; + + let do_start = move || { + let prometheus_socket_addr = SocketAddr::new( params .host .parse() .map_err(|err| format!("Invalid Prometheus host {}: {}", params.host, err))?, params.port, - ), - registry, - ) - .await - .map_err(|err| format!("Error starting Prometheus endpoint: {}", err)) + ); + let metrics_registry = Registry::new(); + global_metrics.register(&metrics_registry)?; + extra_metrics.register(&metrics_registry)?; + async_std::task::spawn(async move { + init_prometheus(prometheus_socket_addr, metrics_registry) + .await + .map_err(|err| format!("Error starting Prometheus endpoint: {}", err)) + }); + + Ok(()) + }; + + let result: Result<(), String> = do_start(); + if let Err(err) = result { + log::warn!( + target: "bridge", + "Failed to expose metrics: {}", + err, + ); + } } impl Default for MetricsParams { @@ -63,6 +90,15 @@ impl Default for MetricsParams { } } +impl Metrics for GlobalMetrics { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.system_average_load.clone(), registry).map_err(|e| e.to_string())?; + register(self.process_cpu_usage_percentage.clone(), registry).map_err(|e| e.to_string())?; + register(self.process_memory_usage_bytes.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + impl GlobalMetrics { /// Creates global metrics. pub fn new() -> Self { @@ -80,14 +116,6 @@ impl GlobalMetrics { } } - /// Registers global metrics in the metrics registry. - pub fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.system_average_load.clone(), registry).map_err(|e| e.to_string())?; - register(self.process_cpu_usage_percentage.clone(), registry).map_err(|e| e.to_string())?; - register(self.process_memory_usage_bytes.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } - /// Update metrics. pub fn update(&mut self) { // update system-wide metrics diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index b2c5d2a5ee39e..95a617154499f 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams, Registry as MetricsRegistry}; +use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; use crate::sync::HeadersSyncParams; use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{ @@ -124,15 +124,7 @@ pub fn run>( let mut metrics_global = GlobalMetrics::new(); let mut metrics_sync = SyncLoopMetrics::new(); let metrics_enabled = metrics_params.is_some(); - if let Some(metrics_params) = metrics_params { - if let Err(err) = expose_metrics(metrics_params, &metrics_global, &metrics_sync).await { - log::warn!( - target: "bridge", - "Failed to expose metrics: {}", - err, - ); - } - } + metrics_start(metrics_params, &metrics_global, &metrics_sync); let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = false; @@ -546,19 +538,6 @@ pub fn run>( }); } -/// Expose sync loop metrics. -async fn expose_metrics( - metrics_params: MetricsParams, - metrics_global: &GlobalMetrics, - metrics_sync: &SyncLoopMetrics, -) -> Result<(), String> { - let metrics_registry = MetricsRegistry::new(); - metrics_global.register(&metrics_registry)?; - metrics_sync.register(&metrics_registry)?; - async_std::task::spawn(metrics_start(metrics_params, metrics_registry)); - Ok(()) -} - /// Stream that emits item every `timeout_ms` milliseconds. fn interval(timeout: Duration) -> impl futures::Stream { futures::stream::unfold((), move |_| async move { diff --git a/relays/ethereum/src/sync_loop_metrics.rs b/relays/ethereum/src/sync_loop_metrics.rs index fa34c8b511d65..dc512a46e48f6 100644 --- a/relays/ethereum/src/sync_loop_metrics.rs +++ b/relays/ethereum/src/sync_loop_metrics.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{register, GaugeVec, Opts, Registry, U64}; +use crate::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; use crate::sync::HeadersSync; use crate::sync_types::{HeaderStatus, HeadersSyncPipeline}; @@ -28,6 +28,14 @@ pub struct SyncLoopMetrics { blocks_in_state: GaugeVec, } +impl Metrics for SyncLoopMetrics { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; + register(self.blocks_in_state.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + impl SyncLoopMetrics { /// Creates sync loop metrics. pub fn new() -> Self { @@ -45,13 +53,6 @@ impl SyncLoopMetrics { } } - /// Registers sync loop metrics in the metrics registry. - pub fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; - register(self.blocks_in_state.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } - /// Update metrics. pub fn update(&mut self, sync: &HeadersSync

) { let headers = sync.headers(); From b4fa09dd8f768678b66d76e689f7642f84bc3fc1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Jul 2020 14:20:50 +0300 Subject: [PATCH 0116/1210] fixed method name (#239) --- relays/ethereum/src/substrate_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 3865566d9183c..c6e19cf110b8b 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -38,7 +38,7 @@ const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoHeaderApi_is_import_requir const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoHeaderApi_is_known_block"; const ETH_API_BEST_BLOCK: &str = "RialtoHeaderApi_best_block"; const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoHeaderApi_finalized_block"; -const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "CurrencyExchangeApi_filter_transaction_proof"; +const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "RialtoCurrencyExchangeApi_filter_transaction_proof"; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; type Result = std::result::Result; From bff740966c73a3f6a43366ce513ebf88d39fdfed Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Jul 2020 18:19:16 +0300 Subject: [PATCH 0117/1210] Exchange transactions relay dashboard (#241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update dashboards * cargo fmt --all * Update deployments/rialto/dashboard/prometheus/prometheus.yml Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- relays/ethereum/src/exchange_loop.rs | 7 ++++++- relays/ethereum/src/metrics.rs | 12 ++++++++++-- relays/ethereum/src/sync_loop.rs | 7 ++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/relays/ethereum/src/exchange_loop.rs b/relays/ethereum/src/exchange_loop.rs index b089e70328003..4d9a031ec9f52 100644 --- a/relays/ethereum/src/exchange_loop.rs +++ b/relays/ethereum/src/exchange_loop.rs @@ -98,7 +98,12 @@ pub fn run( let mut metrics_global = GlobalMetrics::new(); let mut metrics_exch = ExchangeLoopMetrics::new(); let metrics_enabled = metrics_params.is_some(); - metrics_start(metrics_params, &metrics_global, &metrics_exch); + metrics_start( + format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), + metrics_params, + &metrics_global, + &metrics_exch, + ); let exit_signal = exit_signal.fuse(); diff --git a/relays/ethereum/src/metrics.rs b/relays/ethereum/src/metrics.rs index 084b5ae10fa08..c65fdac5ad833 100644 --- a/relays/ethereum/src/metrics.rs +++ b/relays/ethereum/src/metrics.rs @@ -45,12 +45,19 @@ pub struct GlobalMetrics { } /// Start Prometheus endpoint with given metrics registry. -pub fn start(params: Option, global_metrics: &GlobalMetrics, extra_metrics: &impl Metrics) { +pub fn start( + prefix: String, + params: Option, + global_metrics: &GlobalMetrics, + extra_metrics: &impl Metrics, +) { let params = match params { Some(params) => params, None => return, }; + assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); + let do_start = move || { let prometheus_socket_addr = SocketAddr::new( params @@ -59,7 +66,8 @@ pub fn start(params: Option, global_metrics: &GlobalMetrics, extr .map_err(|err| format!("Invalid Prometheus host {}: {}", params.host, err))?, params.port, ); - let metrics_registry = Registry::new(); + let metrics_registry = + Registry::new_custom(Some(prefix), None).expect("only fails if prefix is empty; prefix is not empty; qed"); global_metrics.register(&metrics_registry)?; extra_metrics.register(&metrics_registry)?; async_std::task::spawn(async move { diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 95a617154499f..9e5535f5c471c 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -124,7 +124,12 @@ pub fn run>( let mut metrics_global = GlobalMetrics::new(); let mut metrics_sync = SyncLoopMetrics::new(); let metrics_enabled = metrics_params.is_some(); - metrics_start(metrics_params, &metrics_global, &metrics_sync); + metrics_start( + format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), + metrics_params, + &metrics_global, + &metrics_sync, + ); let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = false; From 7299e92be5074aee426bc133b88275dbcfb2512d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 29 Jul 2020 11:00:16 +0200 Subject: [PATCH 0118/1210] Remove substrate relay. (#244) --- relays/substrate/Cargo.toml | 33 --- relays/substrate/README.md | 32 --- relays/substrate/src/bridge.rs | 413 --------------------------------- relays/substrate/src/error.rs | 47 ---- relays/substrate/src/main.rs | 93 -------- relays/substrate/src/params.rs | 91 -------- relays/substrate/src/rpc.rs | 48 ---- 7 files changed, 757 deletions(-) delete mode 100644 relays/substrate/Cargo.toml delete mode 100644 relays/substrate/README.md delete mode 100644 relays/substrate/src/bridge.rs delete mode 100644 relays/substrate/src/error.rs delete mode 100644 relays/substrate/src/main.rs delete mode 100644 relays/substrate/src/params.rs delete mode 100644 relays/substrate/src/rpc.rs diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml deleted file mode 100644 index 8ee475be613f3..0000000000000 --- a/relays/substrate/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "substrate-bridge" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -async-std = "=1.5.0" -clap = "2.33.1" -ctrlc = "3.1.5" -derive_more = "0.99.9" -env_logger = "0.7.1" -futures = "0.3.5" -jsonrpsee = { git = "https://github.com/paritytech/jsonrpsee", features = ["ws"] } -log = "0.4.11" -serde_json = "1.0.57" -url = "2.1.0" - -[dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-rpc] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' -git = "https://github.com/paritytech/substrate/" - -[dependencies.node-primitives] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' -git = "https://github.com/paritytech/substrate/" diff --git a/relays/substrate/README.md b/relays/substrate/README.md deleted file mode 100644 index dcbaeaaed5a85..0000000000000 --- a/relays/substrate/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Substrate-to-Substrate Bridge Relay - -The bridge relay is a process that connects to running Substrate nodes and sends data over the Substrate-to-Substrate bridge. The process communicates with the nodes over the JSON-RPC interface and reads data from the relays information required by the `bridge` pallet using runtime calls and writes data to the modules by constructing and submitting extrinsics. - -For more details, see the [design document](doc/design.md). - -## Status - -This is a not-in-progress prototype. - -## Running in development - -Run two development Substrate chains: - -```bash -> TMPDIR=(mktemp -d) -> cd $TMPDIR -> substrate build-spec --dev > red-spec.json -> cp red-spec.json blue-spec.json -# Modify the chain spec in an editor so that the genesis hashes of the two chains differ. -# For example, double one of the balances in '$.genesis.runtime.balances.balances'. -> substrate --chain red-spec.json --alice --base-path ./red --port 30343 --ws-port 9954 -> substrate --chain blue-spec.json --alice --base-path ./blue --port 30353 --ws-port 9964 -``` - -Now run the bridge relay: - -``` -> target/release/substrate-bridge --base-path ./relay \ - --rpc-url ws://localhost:9954 \ - --rpc-url ws://localhost:9964 -``` diff --git a/relays/substrate/src/bridge.rs b/relays/substrate/src/bridge.rs deleted file mode 100644 index b797005210284..0000000000000 --- a/relays/substrate/src/bridge.rs +++ /dev/null @@ -1,413 +0,0 @@ -// Copyright 2019-2020 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 . - -use crate::error::Error; -use crate::params::{Params, RPCUrlParam}; -use crate::rpc::{self, SubstrateRPC}; - -use futures::{ - channel::{mpsc, oneshot}, - future, - prelude::*, - select, -}; -use jsonrpsee::{ - raw::client::{RawClient, RawClientError, RawClientEvent, RawClientRequestId, RawClientSubscription}, - transport::{ - ws::{WsConnecError, WsTransportClient}, - TransportClient, - }, -}; -use node_primitives::{Hash, Header}; -use sp_core::Bytes; -use std::cell::RefCell; -use std::collections::HashMap; -use std::pin::Pin; - -type ChainId = Hash; - -struct BridgeState { - channel: mpsc::Sender, - locally_finalized_head_on_bridged_chain: Header, -} - -struct ChainState { - current_finalized_head: Header, - bridges: HashMap, -} - -enum Event { - SubmitExtrinsic(Bytes), -} - -struct Chain { - url: String, - client: RawClient, - sender: mpsc::Sender, - receiver: mpsc::Receiver, - genesis_hash: Hash, - state: ChainState, -} - -async fn init_rpc_connection(url: &RPCUrlParam) -> Result { - let url_str = url.to_string(); - log::debug!("Connecting to {}", url_str); - - // Skip the leading "ws://" and trailing "/". - let url_without_scheme = &url_str[5..(url_str.len() - 1)]; - let transport = WsTransportClient::new(url_without_scheme) - .await - .map_err(|err| Error::WsConnectionError(err.to_string()))?; - - let mut client = RawClient::new(transport); - let genesis_hash = rpc::genesis_block_hash(&mut client) - .await - .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| { - Error::InvalidChainState(format!( - "chain with RPC URL {} is missing a genesis block hash", - url_str, - )) - })?; - - let latest_finalized_hash = SubstrateRPC::chain_finalized_head(&mut client) - .await - .map_err(|e| Error::RPCError(e.to_string()))?; - let latest_finalized_header = SubstrateRPC::chain_header(&mut client, Some(latest_finalized_hash)) - .await - .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| { - Error::InvalidChainState(format!( - "chain {} is missing header for finalized block hash {}", - genesis_hash, latest_finalized_hash - )) - })?; - - let (sender, receiver) = mpsc::channel(0); - - Ok(Chain { - url: url_str, - client, - sender, - receiver, - genesis_hash, - state: ChainState { - current_finalized_head: latest_finalized_header, - bridges: HashMap::new(), - }, - }) -} - -/// Returns IDs of the bridged chains. -async fn read_bridges(chain: &mut Chain, chain_ids: &[Hash]) -> Result, Error> { - // This should make an RPC call to read this information from the bridge pallet state. - // For now, just pretend every chain is bridged to every other chain. - // - // TODO: The correct thing. - Ok(chain_ids - .iter() - .cloned() - .filter(|&chain_id| chain_id != chain.genesis_hash) - .collect()) -} - -pub async fn run_async(params: Params, exit: Box + Unpin + Send>) -> Result<(), Error> { - let chains = init_chains(¶ms).await?; - - let (chain_tasks, exit_signals) = chains - .into_iter() - .map(|(chain_id, chain_cell)| { - let chain = chain_cell.into_inner(); - let (task_exit_signal, task_exit_receiver) = oneshot::channel(); - let task_exit = Box::new( - task_exit_receiver - .map(|result| result.expect("task_exit_signal is not dropped before send() is called")), - ); - let chain_task = async_std::task::spawn(async move { - if let Err(err) = chain_task(chain_id, chain, task_exit).await { - log::error!("Error in task for chain {}: {}", chain_id, err); - } - }); - (chain_task, task_exit_signal) - }) - .unzip::<_, _, Vec<_>, Vec<_>>(); - - async_std::task::spawn(async move { - exit.await; - for exit_signal in exit_signals { - let _ = exit_signal.send(()); - } - }); - - future::join_all(chain_tasks).await; - Ok(()) -} - -type EventsResult = Result<(ChainId, RawClientEvent), Error>; -type EventsFuture<'a> = Pin + 'a>>; - -fn initial_next_events<'a>(chains: &'a HashMap>) -> Vec> { - chains - .values() - .map(|chain_cell| async move { - let mut chain = chain_cell.borrow_mut(); - let event = chain - .client - .next_event() - .await - .map_err(|err| Error::RPCError(err.to_string()))?; - Ok((chain.genesis_hash, event)) - }) - .map(|fut| Box::pin(fut) as Pin>>) - .collect() -} - -async fn next_event<'a>( - next_events: Vec>, - chains: &'a HashMap>, -) -> (Result<(Hash, RawClientEvent), Error>, Vec>) { - let (result, _, mut rest) = future::select_all(next_events).await; - - match result { - Ok((chain_id, _)) => { - let fut = async move { - let chain_cell = chains - .get(&chain_id) - .expect("chain must be in the map as a function precondition; qed"); - let mut chain = chain_cell.borrow_mut(); - let event = chain - .client - .next_event() - .await - .map_err(|err| Error::RPCError(err.to_string()))?; - Ok((chain_id, event)) - }; - rest.push(Box::pin(fut)); - } - Err(ref err) => log::warn!("error in RPC connection with a chain: {}", err), - } - - (result, rest) -} - -async fn init_chains(params: &Params) -> Result>, Error> { - let chains = future::join_all(params.rpc_urls.iter().map(init_rpc_connection)) - .await - .into_iter() - .map(|result| result.map(|chain| (chain.genesis_hash, RefCell::new(chain)))) - .collect::, _>>()?; - - // TODO: Remove when read_bridges is implemented correctly. - let chain_ids = chains.keys().cloned().collect::>(); - // let chain_ids_slice = chain_ids.as_slice(); - - for (&chain_id, chain_cell) in chains.iter() { - let mut chain = chain_cell.borrow_mut(); - for bridged_chain_id in read_bridges(&mut chain, &chain_ids).await? { - if chain_id == bridged_chain_id { - log::warn!("chain {} has a bridge to itself", chain_id); - continue; - } - - if let Some(bridged_chain_cell) = chains.get(&bridged_chain_id) { - let bridged_chain = bridged_chain_cell.borrow_mut(); - - // TODO: Get this from RPC to runtime API. - let genesis_head = SubstrateRPC::chain_header(&mut chain.client, chain_id) - .await - .map_err(|e| Error::RPCError(e.to_string()))? - .ok_or_else(|| { - Error::InvalidChainState(format!("chain {} is missing a genesis block header", chain_id)) - })?; - - let channel = chain.sender.clone(); - chain.state.bridges.insert( - bridged_chain_id, - BridgeState { - channel, - locally_finalized_head_on_bridged_chain: genesis_head, - }, - ); - - // The conditional ensures that we don't log twice per pair of chains. - if chain_id.as_ref() < bridged_chain_id.as_ref() { - log::info!("initialized bridge between {} and {}", chain_id, bridged_chain_id); - } - } - } - } - - Ok(chains) -} - -async fn setup_subscriptions( - chain: &mut Chain, -) -> Result<(RawClientRequestId, RawClientRequestId), RawClientError> { - let new_heads_subscription_id = chain - .client - .start_subscription("chain_subscribeNewHeads", jsonrpsee::common::Params::None) - .await - .map_err(RawClientError::Inner)?; - - let finalized_heads_subscription_id = chain - .client - .start_subscription("chain_subscribeFinalizedHeads", jsonrpsee::common::Params::None) - .await - .map_err(RawClientError::Inner)?; - - let new_heads_subscription = chain - .client - .subscription_by_id(new_heads_subscription_id) - .expect("subscription_id was returned from start_subscription above; qed"); - let new_heads_subscription = match new_heads_subscription { - RawClientSubscription::Active(_) => {} - RawClientSubscription::Pending(subscription) => { - subscription.wait().await?; - } - }; - - let finalized_heads_subscription = chain - .client - .subscription_by_id(finalized_heads_subscription_id) - .expect("subscription_id was returned from start_subscription above; qed"); - let finalized_heads_subscription = match finalized_heads_subscription { - RawClientSubscription::Active(subscription) => {} - RawClientSubscription::Pending(subscription) => { - subscription.wait().await?; - } - }; - - Ok((new_heads_subscription_id, finalized_heads_subscription_id)) -} - -async fn handle_rpc_event( - chain_id: ChainId, - chain: &mut Chain, - event: RawClientEvent, - new_heads_subscription_id: RawClientRequestId, - finalized_heads_subscription_id: RawClientRequestId, -) -> Result<(), Error> { - match event { - RawClientEvent::SubscriptionNotif { request_id, result } => { - if request_id == new_heads_subscription_id { - let header: Header = serde_json::from_value(result).map_err(Error::SerializationError)?; - log::info!("Received new head {:?} on chain {}", header, chain_id); - } else if request_id == finalized_heads_subscription_id { - let header: Header = serde_json::from_value(result).map_err(Error::SerializationError)?; - log::info!("Received finalized head {:?} on chain {}", header, chain_id); - - // let old_finalized_head = chain_state.current_finalized_head; - chain.state.current_finalized_head = header; - for (bridged_chain_id, bridged_chain) in chain.state.bridges.iter_mut() { - if bridged_chain.locally_finalized_head_on_bridged_chain.number - < chain.state.current_finalized_head.number - { - // Craft and submit an extrinsic over RPC - log::info!("Sending command to submit extrinsic to chain {}", chain_id); - let mut send_event = bridged_chain - .channel - .send(Event::SubmitExtrinsic(Bytes(Vec::new()))) - .fuse(); - - // Continue processing events from other chain tasks while waiting to send - // event to other chain task in order to prevent deadlocks. - loop { - select! { - result = send_event => { - result.map_err(Error::ChannelError)?; - break; - } - event = chain.receiver.next().fuse() => { - let event = event - .expect("stream will never close as the chain has an mpsc Sender"); - handle_bridge_event(chain_id, &mut chain.client, event) - .await?; - } - // TODO: exit - } - } - } - } - } else { - return Err(Error::RPCError(format!( - "unexpected subscription response with request ID {:?}", - request_id - ))); - } - } - _ => { - return Err(Error::RPCError(format!( - "unexpected RPC event from chain {}: {:?}", - chain_id, event - ))) - } - } - Ok(()) -} - -// Let's say this never sends over a channel (ie. cannot block on another task). -async fn handle_bridge_event( - chain_id: ChainId, - rpc_client: &mut RawClient, - event: Event, -) -> Result<(), Error> { - match event { - Event::SubmitExtrinsic(data) => { - log::info!("Submitting extrinsic to chain {}", chain_id); - if let Err(err) = SubstrateRPC::author_submit_extrinsic(rpc_client, data).await { - log::error!("failed to submit extrinsic: {}", err); - } - } - } - Ok(()) -} - -async fn chain_task( - chain_id: ChainId, - mut chain: Chain, - exit: impl Future + Unpin + Send, -) -> Result<(), Error> { - let (new_heads_subscription_id, finalized_heads_subscription_id) = setup_subscriptions(&mut chain) - .await - .map_err(|e| Error::RPCError(e.to_string()))?; - - let mut exit = exit.fuse(); - loop { - select! { - result = chain.client.next_event().fuse() => { - let event = result.map_err(|e| Error::RPCError(e.to_string()))?; - handle_rpc_event( - chain_id, - &mut chain, - event, - new_heads_subscription_id, - finalized_heads_subscription_id, - ).await?; - } - event = chain.receiver.next().fuse() => { - let event = event - .expect("stream will never close as the chain has an mpsc Sender"); - handle_bridge_event(chain_id, &mut chain.client, event) - .await?; - } - _ = exit => { - log::debug!("Received exit signal, shutting down task for chain {}", chain_id); - break; - } - } - } - Ok(()) -} diff --git a/relays/substrate/src/error.rs b/relays/substrate/src/error.rs deleted file mode 100644 index f1b18568b6b3e..0000000000000 --- a/relays/substrate/src/error.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019-2020 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 . - -use futures::channel::mpsc; - -#[derive(Debug, derive_more::Display)] -pub enum Error { - #[display(fmt = "invalid RPC URL: {}", _0)] - UrlError(String), - #[display(fmt = "RPC response indicates invalid chain state: {}", _0)] - InvalidChainState(String), - #[display(fmt = "could not make RPC call: {}", _0)] - RPCError(String), - #[display(fmt = "could not connect to RPC URL: {}", _0)] - WsConnectionError(String), - #[display(fmt = "unexpected client event from RPC URL {}: {:?}", _0, _1)] - UnexpectedClientEvent(String, String), - #[display(fmt = "serialization error: {}", _0)] - SerializationError(serde_json::error::Error), - #[display(fmt = "invalid event received from bridged chain: {}", _0)] - InvalidBridgeEvent(String), - #[display(fmt = "error sending over MPSC channel: {}", _0)] - ChannelError(mpsc::SendError), -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::SerializationError(err) => Some(err), - Error::ChannelError(err) => Some(err), - _ => None, - } - } -} diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs deleted file mode 100644 index 550ae986b79c9..0000000000000 --- a/relays/substrate/src/main.rs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2019-2020 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 . - -// TODO: when (if) this relay will be resurrected, remove this -#![allow(unused_variables)] -#![allow(dead_code)] - -mod bridge; -mod error; -mod params; -mod rpc; - -use bridge::run_async; -use params::{Params, RPCUrlParam}; - -use clap::{value_t, values_t, App, Arg}; -use futures::{channel, prelude::*}; -use std::cell::Cell; -use std::process; - -fn main() { - let params = parse_args(); - env_logger::init(); - let exit = setup_exit_handler(); - - let result = async_std::task::block_on(async move { run_async(params, exit).await }); - if let Err(err) = result { - log::error!("{}", err); - process::exit(1); - } -} - -fn parse_args() -> Params { - let matches = App::new("substrate-bridge") - .version("1.0") - .author("Parity Technologies") - .about("Bridges Substrates, duh") - .arg( - Arg::with_name("base-path") - .long("base-path") - .value_name("DIRECTORY") - .required(true) - .help("Sets the base path") - .takes_value(true), - ) - .arg( - Arg::with_name("rpc-url") - .long("rpc-url") - .value_name("HOST[:PORT]") - .help("The URL of a bridged Substrate node") - .takes_value(true) - .multiple(true), - ) - .get_matches(); - - let base_path = value_t!(matches, "base-path", String).unwrap_or_else(|e| e.exit()); - let rpc_urls = values_t!(matches, "rpc-url", RPCUrlParam).unwrap_or_else(|e| e.exit()); - - Params { base_path, rpc_urls } -} - -fn setup_exit_handler() -> Box + Unpin + Send> { - let (exit_sender, exit_receiver) = channel::oneshot::channel(); - let exit_sender = Cell::new(Some(exit_sender)); - - ctrlc::set_handler(move || { - if let Some(exit_sender) = exit_sender.take() { - if let Err(()) = exit_sender.send(()) { - log::warn!("failed to send exit signal"); - } - } - }) - .expect("must be able to set Ctrl-C handler"); - - Box::new( - exit_receiver.map(|result| { - result.expect("exit_sender cannot be dropped as it is moved into a globally-referenced closure") - }), - ) -} diff --git a/relays/substrate/src/params.rs b/relays/substrate/src/params.rs deleted file mode 100644 index 3129c920e8140..0000000000000 --- a/relays/substrate/src/params.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2019-2020 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 . - -use crate::error::Error; - -use std::str::FromStr; -use url::Url; - -const DEFAULT_WS_PORT: u16 = 9944; - -#[derive(Debug, Clone)] -pub struct Params { - pub base_path: String, - pub rpc_urls: Vec, -} - -#[derive(Debug, Clone)] -pub struct RPCUrlParam { - url: Url, -} - -impl ToString for RPCUrlParam { - fn to_string(&self) -> String { - self.url.to_string() - } -} - -impl FromStr for RPCUrlParam { - type Err = Error; - - fn from_str(url_str: &str) -> Result { - let mut url = - Url::parse(url_str).map_err(|e| Error::UrlError(format!("could not parse {}: {}", url_str, e)))?; - - if url.scheme() != "ws" { - return Err(Error::UrlError(format!("must have scheme ws, found {}", url.scheme()))); - } - - if url.port().is_none() { - url.set_port(Some(DEFAULT_WS_PORT)) - .expect("the scheme is checked above to be ws; qed"); - } - - if url.path() != "/" { - return Err(Error::UrlError(format!("cannot have a path, found {}", url.path()))); - } - if let Some(query) = url.query() { - return Err(Error::UrlError(format!("cannot have a query, found {}", query))); - } - if let Some(fragment) = url.fragment() { - return Err(Error::UrlError(format!("cannot have a fragment, found {}", fragment))); - } - - Ok(RPCUrlParam { url }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn rpc_url_from_str() { - assert_eq!( - RPCUrlParam::from_str("ws://127.0.0.1").unwrap().to_string(), - "ws://127.0.0.1:9944/" - ); - assert_eq!( - RPCUrlParam::from_str("ws://127.0.0.1/").unwrap().to_string(), - "ws://127.0.0.1:9944/" - ); - assert_eq!( - RPCUrlParam::from_str("ws://127.0.0.1:4499").unwrap().to_string(), - "ws://127.0.0.1:4499/" - ); - assert!(RPCUrlParam::from_str("http://127.0.0.1").is_err()); - } -} diff --git a/relays/substrate/src/rpc.rs b/relays/substrate/src/rpc.rs deleted file mode 100644 index 5dfd1eb16c5ee..0000000000000 --- a/relays/substrate/src/rpc.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019-2020 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 . - -use jsonrpsee::{ - raw::client::{RawClient, RawClientError}, - transport::TransportClient, -}; -use node_primitives::{Hash, Header}; -use sp_core::Bytes; -use sp_rpc::number::NumberOrHex; - -jsonrpsee::rpc_api! { - pub SubstrateRPC { - #[rpc(method = "author_submitExtrinsic", positional_params)] - fn author_submit_extrinsic(extrinsic: Bytes) -> Hash; - - #[rpc(method = "chain_getFinalizedHead")] - fn chain_finalized_head() -> Hash; - - #[rpc(method = "chain_getBlockHash", positional_params)] - fn chain_block_hash(id: Option) -> Option; - - #[rpc(method = "chain_getHeader", positional_params)] - fn chain_header(hash: Option) -> Option

; - - #[rpc(positional_params)] - fn state_call(name: String, bytes: Bytes, hash: Option) -> Bytes; - } -} - -pub async fn genesis_block_hash( - client: &mut RawClient, -) -> Result, RawClientError> { - SubstrateRPC::chain_block_hash(client, Some(NumberOrHex::Number(0))).await -} From 686ab29fec9ff62dba3ef1fa3ca7f3e10bc3230f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 29 Jul 2020 22:04:33 +0300 Subject: [PATCH 0119/1210] Submit exchange transactions to PoA node (#229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * submit Eth exchange transactions * submit ethereum in docker-compose * submit Eth exchange transactions * fix duplicate message * fix relay script * lost file * cargo fmt --all * cargo +nightly clippy * Show sccache * remove test-helpers remains * what's going on with jsonrpsee + Cargo.lock? * relay-eth-submit-exchange-tx -> poa-exchange-tx-generator * Update relays/ethereum/src/main.rs Co-authored-by: Tomasz Drwięga * configuring exchange-gen loop using env variables * fixed signer account from dev chain to Arthur * improve debug prints * parse nonce from relay output * --eth-nonce= * fix compilation * cargo fmt --all * fix typo * duplicate relay output to tty * allow using from bash scripts tests * fix: U256::parse() expects hex string :/ * cargo fmt --all * BRIDGE_HASH: ${BRIDGE_HASH:-master} * script comment * generate exchange PoA transactions by Bertha * Bertha address Co-authored-by: Denis S. Soldatov aka General-Beck Co-authored-by: Tomasz Drwięga --- bin/node/runtime/Cargo.toml | 3 +- bin/node/runtime/src/exchange.rs | 2 +- modules/ethereum/Cargo.toml | 3 +- primitives/ethereum-poa/Cargo.toml | 3 - primitives/ethereum-poa/src/lib.rs | 5 +- relays/ethereum/Cargo.toml | 1 + relays/ethereum/src/cli.yml | 22 ++++ .../ethereum/src/ethereum_exchange_submit.rs | 120 ++++++++++++++++++ relays/ethereum/src/main.rs | 54 +++++++- 9 files changed, 200 insertions(+), 13 deletions(-) create mode 100644 relays/ethereum/src/ethereum_exchange_submit.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 755dc99b343fe..11f3a8f457758 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -214,7 +214,7 @@ features = ["hmac"] [dev-dependencies.sp-bridge-eth-poa] version = "0.1.0" default-features = false -features = ["std", "test-helpers"] +features = ["std"] path = "../../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] @@ -264,6 +264,5 @@ runtime-benchmarks = [ "libsecp256k1", "pallet-bridge-currency-exchange/runtime-benchmarks", "pallet-bridge-eth-poa/runtime-benchmarks", - "sp-bridge-eth-poa/test-helpers", "sp-runtime/runtime-benchmarks", ] diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index 8754bec0893ff..1048c661894d0 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -37,7 +37,7 @@ use sp_currency_exchange::{ use sp_std::vec::Vec; /// Ethereum address where locked PoA funds must be sent to. -const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); +pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); /// Ethereum transaction inclusion proof. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 3b14060ab72eb..dbe32d617794d 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -59,7 +59,7 @@ features = ["hmac"] # Dev Dependencies [dev-dependencies] # TODO: Stop renaming this on import -primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", features = ["std", "test-helpers"] } +primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", features = ["std"] } libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [features] @@ -78,5 +78,4 @@ std = [ runtime-benchmarks = [ "frame-benchmarking", "libsecp256k1", - "primitives/test-helpers", ] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 232bdf21bf64e..f52fb42f1d1b7 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -47,18 +47,15 @@ default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.libsecp256k1] -optional = true version = "0.3.4" default-features = false features = ["hmac"] [dev-dependencies] hex-literal = "0.2" -libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } [features] default = ["std"] -test-helpers = ["libsecp256k1"] std = [ "serde/std", "serde-big-array", diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index f418a8e325b80..ada3fe9a1a327 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -54,7 +54,6 @@ pub type RawTransactionReceipt = Vec; /// An ethereum address. pub type Address = H160; -#[cfg(any(feature = "test-helpers", test))] pub mod signatures; /// Complete header id. @@ -113,8 +112,7 @@ pub struct Transaction { } /// Unsigned portion of ethereum transaction. -#[derive(PartialEq, RuntimeDebug)] -#[cfg_attr(test, derive(Clone))] +#[derive(Clone, PartialEq, RuntimeDebug)] pub struct UnsignedTransaction { /// Sender nonce. pub nonce: U256, @@ -396,7 +394,6 @@ impl SealedEmptyStep { } /// Returns rlp for the vector of empty steps (we only do encoding in tests). - #[cfg(feature = "test-helpers")] pub fn rlp_of(empty_steps: &[SealedEmptyStep]) -> Bytes { let mut s = RlpStream::new(); s.begin_list(empty_steps.len()); diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index cd39d6ea44531..972d9be945dd1 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -20,6 +20,7 @@ ethabi-derive = "12.0" ethereum-tx-sign = "3.0" futures = "0.3.5" hex = "0.4" +hex-literal = "0.3" linked-hash-map = "0.5.3" log = "0.4.11" num-traits = "0.2" diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 6e11c70ada3a5..135e8da29a986 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -106,6 +106,28 @@ subcommands: value_name: SUB_INITIAL_HEADER help: Encoded initial Substrate header. takes_value: true + - eth-submit-exchange-tx: + about: Submit lock funds transaction to Ethereum node. + args: + - eth-host: *eth-host + - eth-port: *eth-port + - eth-nonce: + long: eth-nonce + value_name: ETH_NONCE + help: Nonce that have to be used when building transaction. If not specified, read from PoA node. + takes_value: true + - eth-signer: *eth-signer + - eth-chain-id: *eth-chain-id + - eth-amount: + long: eth-amount + value_name: ETH_AMOUNT + help: Amount of ETH to lock (in wei). + takes_value: true + - sub-recipient: + long: sub-recipient + value_name: SUB_RECIPIENT + help: Hex-encoded Public key of funds recipient in Substrate chain. + takes_value: true - eth-exchange-sub: about: Submit proof of PoA lock funds transaction to Substrate node. args: diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs new file mode 100644 index 0000000000000..201b251db2ed3 --- /dev/null +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -0,0 +1,120 @@ +// Copyright 2019-2020 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 . + +//! Submitting Ethereum -> Substrate exchange transactions. + +use crate::ethereum_client::{EthereumConnectionParams, EthereumRpcClient, EthereumSigningParams}; +use crate::ethereum_types::{CallRequest, U256}; +use crate::rpc::EthereumRpc; + +use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS; +use hex_literal::hex; +use sp_bridge_eth_poa::{ + signatures::{SecretKey, SignTransaction}, + UnsignedTransaction, +}; + +/// Ethereum exchange transaction params. +#[derive(Debug)] +pub struct EthereumExchangeSubmitParams { + /// Ethereum connection params. + pub eth: EthereumConnectionParams, + /// Ethereum signing params. + pub eth_sign: EthereumSigningParams, + /// Ethereum signer nonce. + pub eth_nonce: Option, + /// Amount of Ethereum tokens to lock. + pub eth_amount: U256, + /// Funds recipient on Substrate side. + pub sub_recipient: [u8; 32], +} + +impl Default for EthereumExchangeSubmitParams { + fn default() -> Self { + EthereumExchangeSubmitParams { + eth: Default::default(), + eth_sign: Default::default(), + eth_nonce: None, + eth_amount: 1_000_000_000_000_000_000_u64.into(), // 1 ETH + sub_recipient: hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"), // ferdie + } + } +} + +/// Submit single Ethereum -> Substrate exchange transaction. +pub fn run(params: EthereumExchangeSubmitParams) { + let mut local_pool = futures::executor::LocalPool::new(); + + let result: Result<_, String> = local_pool.run_until(async move { + let eth_client = EthereumRpcClient::new(params.eth); + + let eth_signer_address = params.eth_sign.signer.address(); + let sub_recipient_encoded = params.sub_recipient; + let nonce = match params.eth_nonce { + Some(eth_nonce) => eth_nonce, + None => eth_client + .account_nonce(eth_signer_address) + .await + .map_err(|err| format!("error fetching acount nonce: {:?}", err))?, + }; + let gas = eth_client + .estimate_gas(CallRequest { + from: Some(eth_signer_address), + to: Some(LOCK_FUNDS_ADDRESS.into()), + value: Some(params.eth_amount), + data: Some(sub_recipient_encoded.to_vec().into()), + ..Default::default() + }) + .await + .map_err(|err| format!("error estimating gas requirements: {:?}", err))?; + let eth_tx_unsigned = UnsignedTransaction { + nonce, + gas_price: params.eth_sign.gas_price, + gas, + to: Some(LOCK_FUNDS_ADDRESS.into()), + value: params.eth_amount, + payload: sub_recipient_encoded.to_vec(), + }; + let eth_tx_signed = eth_tx_unsigned.clone().sign_by( + &SecretKey::parse(params.eth_sign.signer.secret().as_fixed_bytes()) + .expect("key is accepted by secp256k1::KeyPair and thus is valid; qed"), + Some(params.eth_sign.chain_id), + ); + eth_client + .submit_transaction(eth_tx_signed) + .await + .map_err(|err| format!("error submitting transaction: {:?}", err))?; + + Ok(eth_tx_unsigned) + }); + + match result { + Ok(eth_tx_unsigned) => { + log::info!( + target: "bridge", + "Exchange transaction has been submitted to Ethereum node: {:?}", + eth_tx_unsigned, + ); + } + Err(err) => { + log::error!( + target: "bridge", + "Error submitting exchange transaction to Ethereum node: {}", + err, + ); + } + } +} diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index caddcfb9ca496..94d88f6e93911 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -19,6 +19,7 @@ mod ethereum_client; mod ethereum_deploy_contract; mod ethereum_exchange; +mod ethereum_exchange_submit; mod ethereum_sync_loop; mod ethereum_types; mod exchange; @@ -85,14 +86,25 @@ fn main() { ("eth-deploy-contract", Some(eth_deploy_matches)) => { log::info!(target: "bridge", "Deploying ETH contracts."); ethereum_deploy_contract::run(match ethereum_deploy_contract_params(ð_deploy_matches) { - Ok(ethereum_deploy_matches) => ethereum_deploy_matches, + Ok(ethereum_deploy_params) => ethereum_deploy_params, Err(err) => { log::error!(target: "bridge", "Error during contract deployment: {}", err); return; } }); } + ("eth-submit-exchange-tx", Some(eth_exchange_submit_matches)) => { + log::info!(target: "bridge", "Submitting ETH ➡ SUB exchange transaction."); + ethereum_exchange_submit::run(match ethereum_exchange_submit_params(ð_exchange_submit_matches) { + Ok(eth_exchange_submit_params) => eth_exchange_submit_params, + Err(err) => { + log::error!(target: "bridge", "Error submitting Eethereum exchange transaction: {}", err); + return; + } + }); + } ("eth-exchange-sub", Some(eth_exchange_matches)) => { + log::info!(target: "bridge", "Starting ETH ➡ SUB exchange transactions relay."); ethereum_exchange::run(match ethereum_exchange_params(ð_exchange_matches) { Ok(eth_exchange_params) => eth_exchange_params, Err(err) => { @@ -256,6 +268,44 @@ fn ethereum_deploy_contract_params( Ok(eth_deploy_params) } +fn ethereum_exchange_submit_params( + matches: &clap::ArgMatches, +) -> Result { + let mut params = ethereum_exchange_submit::EthereumExchangeSubmitParams::default(); + params.eth = ethereum_connection_params(matches)?; + params.eth_sign = ethereum_signing_params(matches)?; + + if let Some(eth_nonce) = matches.value_of("eth-nonce") { + params.eth_nonce = Some( + ethereum_types::U256::from_dec_str(ð_nonce).map_err(|e| format!("Failed to parse eth-nonce: {}", e))?, + ); + } + if let Some(eth_amount) = matches.value_of("eth-amount") { + params.eth_amount = eth_amount + .parse() + .map_err(|e| format!("Failed to parse eth-amount: {}", e))?; + } + if let Some(sub_recipient) = matches.value_of("sub-recipient") { + params.sub_recipient = hex::decode(&sub_recipient) + .map_err(|err| err.to_string()) + .and_then(|vsub_recipient| { + let expected_len = params.sub_recipient.len(); + if expected_len != vsub_recipient.len() { + Err(format!("invalid length. Expected {} bytes", expected_len)) + } else { + let mut sub_recipient = params.sub_recipient; + sub_recipient.copy_from_slice(&vsub_recipient[..expected_len]); + Ok(sub_recipient) + } + }) + .map_err(|e| format!("Failed to parse sub-recipient: {}", e))?; + } + + log::debug!(target: "bridge", "Submit Ethereum exchange tx params: {:?}", params); + + Ok(params) +} + fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result { let mut params = ethereum_exchange::EthereumExchangeParams::default(); params.eth = ethereum_connection_params(matches)?; @@ -279,6 +329,8 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result Date: Thu, 30 Jul 2020 18:05:50 +0300 Subject: [PATCH 0120/1210] Prepare for sub to eth relay (#248) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed PoA contract deploy (granda_authorities call) * pause if all submitted headers were rejected * give funds to Bertha and Carlos * max 1 active PoA transaction in headers sync :( * display initial header id when deploying PoA contract * cargo fmt + clipy * fix compilation * Update relays/ethereum/src/sync_types.rs Co-authored-by: Tomasz Drwięga * Update relays/ethereum/src/utils.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- bin/node/runtime/src/rialto.rs | 4 +- relays/ethereum/src/ethereum_client.rs | 3 +- .../ethereum/src/ethereum_deploy_contract.rs | 19 +++--- relays/ethereum/src/exchange.rs | 38 +---------- relays/ethereum/src/rpc_errors.rs | 2 +- relays/ethereum/src/substrate_client.rs | 4 +- relays/ethereum/src/substrate_sync_loop.rs | 2 +- relays/ethereum/src/sync_loop.rs | 26 ++++---- relays/ethereum/src/sync_loop_tests.rs | 6 +- relays/ethereum/src/sync_types.rs | 22 +++++-- relays/ethereum/src/utils.rs | 63 +++++++++++++++++++ 11 files changed, 117 insertions(+), 72 deletions(-) diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs index 195fed1693fdb..1a46fae0b5303 100644 --- a/bin/node/runtime/src/rialto.rs +++ b/bin/node/runtime/src/rialto.rs @@ -79,7 +79,7 @@ pub fn genesis_header() -> Header { transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), extra_data: vec![], - state_root: hex!("d6368925ffd9acad81f411ce45891d3722e14355af2790391839488e23d74b0d").into(), + state_root: hex!("eccf6b74c2bcbe115c71116a23fe963c54406010c244d9650526028ad3e32cce").into(), receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), log_bloom: Default::default(), gas_used: Default::default(), @@ -134,7 +134,7 @@ mod tests { fn genesis_hash_matches() { assert_eq!( genesis_header().compute_hash(), - hex!("bc936e808b668546250ad43de5c0a95fe2a9644a850a2ff69b57f874e3e35644").into(), + hex!("9ff57c7fa155853586382022f0982b71c51fa313a0942f8c456300896643e890").into(), ); } diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index aba5d1ca74318..df4945afcaf7d 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -21,7 +21,8 @@ use crate::ethereum_types::{ use crate::rpc::{Ethereum, EthereumRpc}; use crate::rpc_errors::{EthereumNodeError, RpcError}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::{HeaderId, MaybeConnectionError, SubmittedHeaders}; +use crate::sync_types::{HeaderId, SubmittedHeaders}; +use crate::utils::MaybeConnectionError; use async_trait::async_trait; use codec::{Decode, Encode}; diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index 0e573bda0634f..d46bd879448d9 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -19,7 +19,8 @@ use crate::ethereum_client::{ }; use crate::rpc::SubstrateRpc; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; -use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader}; +use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId}; +use crate::sync_types::HeaderId; use codec::{Decode, Encode}; use num_traits::Zero; @@ -66,18 +67,19 @@ pub fn run(params: EthereumDeployContractParams) { let eth_client = EthereumRpcClient::new(params.eth); let sub_client = SubstrateRpcClient::new(params.sub).await?; - let (initial_header_hash, initial_header) = prepare_initial_header(&sub_client, params.sub_initial_header).await?; + let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, params.sub_initial_header).await?; let initial_set_id = params.sub_initial_authorities_set_id.unwrap_or(0); let initial_set = prepare_initial_authorities_set( &sub_client, - initial_header_hash, + initial_header_id.1, params.sub_initial_authorities_set, ).await?; log::info!( target: "bridge", - "Deploying Ethereum contract.\r\n\tInitial header: {:?}\r\n\tInitial header encoded: {}\r\n\tInitial authorities set ID: {}\r\n\tInitial authorities set: {}", + "Deploying Ethereum contract.\r\n\tInitial header: {:?}\r\n\tInitial header id: {:?}\r\n\tInitial header encoded: {}\r\n\tInitial authorities set ID: {}\r\n\tInitial authorities set: {}", initial_header, + initial_header_id, hex::encode(&initial_header), initial_set_id, hex::encode(&initial_set), @@ -102,16 +104,19 @@ pub fn run(params: EthereumDeployContractParams) { async fn prepare_initial_header( sub_client: &SubstrateRpcClient, sub_initial_header: Option>, -) -> Result<(SubstrateHash, Vec), String> { +) -> Result<(SubstrateHeaderId, Vec), String> { match sub_initial_header { Some(raw_initial_header) => match SubstrateHeader::decode(&mut &raw_initial_header[..]) { - Ok(initial_header) => Ok((initial_header.hash(), raw_initial_header)), + Ok(initial_header) => Ok(( + HeaderId(initial_header.number, initial_header.hash()), + raw_initial_header, + )), Err(error) => Err(format!("Error decoding initial header: {}", error)), }, None => { let initial_header = sub_client.header_by_number(Zero::zero()).await; initial_header - .map(|header| (header.hash(), header.encode())) + .map(|header| (HeaderId(Zero::zero(), header.hash()), header.encode())) .map_err(|error| format!("Error reading Substrate genesis header: {:?}", error)) } } diff --git a/relays/ethereum/src/exchange.rs b/relays/ethereum/src/exchange.rs index 58ddcf6b66647..89f30a2dae549 100644 --- a/relays/ethereum/src/exchange.rs +++ b/relays/ethereum/src/exchange.rs @@ -16,7 +16,7 @@ //! Relaying proofs of exchange transaction. -use crate::sync_types::MaybeConnectionError; +use crate::utils::{MaybeConnectionError, StringifiedMaybeConnectionError}; use async_trait::async_trait; use std::{ @@ -135,14 +135,6 @@ pub struct RelayedBlockTransactions { pub failed: usize, } -/// Stringified error that may be either connection-related or not. -enum StringifiedMaybeConnectionError { - /// The error is connection-related error. - Connection(String), - /// The error is connection-unrelated error. - NonConnection(String), -} - /// Relay all suitable transactions from single block. /// /// If connection error occurs, returns Err with number of successfully processed transactions. @@ -448,34 +440,6 @@ async fn wait_header_finalized( } } -impl StringifiedMaybeConnectionError { - fn new(is_connection_error: bool, error: String) -> Self { - if is_connection_error { - StringifiedMaybeConnectionError::Connection(error) - } else { - StringifiedMaybeConnectionError::NonConnection(error) - } - } -} - -impl MaybeConnectionError for StringifiedMaybeConnectionError { - fn is_connection_error(&self) -> bool { - match *self { - StringifiedMaybeConnectionError::Connection(_) => true, - StringifiedMaybeConnectionError::NonConnection(_) => false, - } - } -} - -impl ToString for StringifiedMaybeConnectionError { - fn to_string(&self) -> String { - match *self { - StringifiedMaybeConnectionError::Connection(ref err) => err.clone(), - StringifiedMaybeConnectionError::NonConnection(ref err) => err.clone(), - } - } -} - #[cfg(test)] pub(crate) mod tests { use super::*; diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 9739237520b05..dfc84192db0f4 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::sync_types::MaybeConnectionError; +use crate::utils::MaybeConnectionError; use jsonrpsee::client::RequestError; diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index c6e19cf110b8b..bfb6c3c2793b0 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -187,9 +187,9 @@ impl SubstrateRpc for SubstrateRpcClient { async fn grandpa_authorities_set(&self, block: Hash) -> Result { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); - let data = Bytes(block.as_bytes().to_vec()); + let data = Bytes(Vec::new()); - let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; + let encoded_response = Substrate::state_call(&self.client, call, data, Some(block)).await?; let authority_list = encoded_response.0; Ok(authority_list) diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 1d81e2e6bf303..16afb163d41a2 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -42,7 +42,7 @@ const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max Ethereum headers we want to have in all 'before-submitted' states. const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; /// Max Ethereum headers count we want to have in 'submitted' state. -const MAX_SUBMITTED_HEADERS: usize = 4; +const MAX_SUBMITTED_HEADERS: usize = 1; /// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). const PRUNE_DEPTH: u32 = 256; diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 9e5535f5c471c..a62c712f22000 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -17,10 +17,8 @@ use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; use crate::sync::HeadersSyncParams; use crate::sync_loop_metrics::SyncLoopMetrics; -use crate::sync_types::{ - HeaderIdOf, HeaderStatus, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SubmittedHeaders, -}; -use crate::utils::retry_backoff; +use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}; +use crate::utils::{format_ids, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError}; use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; @@ -309,7 +307,16 @@ pub fn run>( submitted_headers = target_submit_header_future => { // following line helps Rust understand the type of `submitted_headers` :/ let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; - let maybe_fatal_error = submitted_headers.fatal_error.map(Err).unwrap_or(Ok(())); + let submitted_headers_str = format!("{}", submitted_headers); + let maybe_fatal_error = match submitted_headers.fatal_error { + Some(fatal_error) => Err(StringifiedMaybeConnectionError::new( + fatal_error.is_connection_error(), + format!("{:?}", fatal_error), + )), + None if submitted_headers.submitted.is_empty() && submitted_headers.incomplete.is_empty() => + Err(StringifiedMaybeConnectionError::new(false, "All headers were rejected".into())), + None => Ok(()), + }; target_client_is_online = process_future_result( maybe_fatal_error, @@ -320,6 +327,8 @@ pub fn run>( || format!("Error submitting headers to {} node", P::TARGET_NAME), ); + log::debug!(target: "bridge", "Header submit result: {}", submitted_headers_str); + sync.headers_mut().headers_submitted(submitted_headers.submitted); sync.headers_mut().add_incomplete_headers(submitted_headers.incomplete); }, @@ -434,17 +443,12 @@ pub fn run>( } else if let Some(headers) = sync.select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) { - let ids = match headers.len() { - 1 => format!("{:?}", headers[0].id()), - 2 => format!("[{:?}, {:?}]", headers[0].id(), headers[1].id()), - len => format!("[{:?} ... {:?}]", headers[0].id(), headers[len - 1].id()), - }; log::debug!( target: "bridge", "Submitting {} header(s) to {} node: {:?}", headers.len(), P::TARGET_NAME, - ids, + format_ids(headers.iter().map(|header| header.id())), ); let headers = headers.into_iter().cloned().collect(); diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/ethereum/src/sync_loop_tests.rs index 7b65f3d54a8d4..13206f4ad21db 100644 --- a/relays/ethereum/src/sync_loop_tests.rs +++ b/relays/ethereum/src/sync_loop_tests.rs @@ -17,10 +17,8 @@ #![cfg(test)] use crate::sync_loop::{process_future_result, run, SourceClient, TargetClient}; -use crate::sync_types::{ - HeaderId, HeadersSyncPipeline, MaybeConnectionError, QueuedHeader, SourceHeader, SubmittedHeaders, -}; -use crate::utils::retry_backoff; +use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}; +use crate::utils::{retry_backoff, MaybeConnectionError}; use async_trait::async_trait; use backoff::backoff::Backoff; diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index 1e2aca16f7d82..4f9dbb3e6b26f 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::utils::format_ids; + use std::{ops::Deref, sync::Arc}; /// Ethereum header Id. @@ -43,12 +45,6 @@ pub enum HeaderStatus { Synced, } -/// Error type that can signal connection errors. -pub trait MaybeConnectionError { - /// Returns true if error (maybe) represents connection error. - fn is_connection_error(&self) -> bool; -} - /// Headers synchronization pipeline. pub trait HeadersSyncPipeline: Clone + Copy { /// Name of the headers source. @@ -192,3 +188,17 @@ impl Default for SubmittedHeaders { } } } + +impl std::fmt::Display for SubmittedHeaders { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let submitted = format_ids(self.submitted.iter()); + let incomplete = format_ids(self.incomplete.iter()); + let rejected = format_ids(self.rejected.iter()); + + write!( + f, + "Submitted: {}, Incomplete: {}, Rejected: {}", + submitted, incomplete, rejected + ) + } +} diff --git a/relays/ethereum/src/utils.rs b/relays/ethereum/src/utils.rs index e769e10782777..dfe3b3966fc9d 100644 --- a/relays/ethereum/src/utils.rs +++ b/relays/ethereum/src/utils.rs @@ -43,6 +43,50 @@ macro_rules! bail_on_arg_error { }; } +/// Error type that can signal connection errors. +pub trait MaybeConnectionError { + /// Returns true if error (maybe) represents connection error. + fn is_connection_error(&self) -> bool; +} + +/// Stringified error that may be either connection-related or not. +#[derive(Debug)] +pub enum StringifiedMaybeConnectionError { + /// The error is connection-related error. + Connection(String), + /// The error is connection-unrelated error. + NonConnection(String), +} + +impl StringifiedMaybeConnectionError { + /// Create new stringified connection error. + pub fn new(is_connection_error: bool, error: String) -> Self { + if is_connection_error { + StringifiedMaybeConnectionError::Connection(error) + } else { + StringifiedMaybeConnectionError::NonConnection(error) + } + } +} + +impl MaybeConnectionError for StringifiedMaybeConnectionError { + fn is_connection_error(&self) -> bool { + match *self { + StringifiedMaybeConnectionError::Connection(_) => true, + StringifiedMaybeConnectionError::NonConnection(_) => false, + } + } +} + +impl ToString for StringifiedMaybeConnectionError { + fn to_string(&self) -> String { + match *self { + StringifiedMaybeConnectionError::Connection(ref err) => err.clone(), + StringifiedMaybeConnectionError::NonConnection(ref err) => err.clone(), + } + } +} + /// Exponential backoff for connection-unrelated errors retries. pub fn retry_backoff() -> ExponentialBackoff { let mut backoff = ExponentialBackoff::default(); @@ -51,3 +95,22 @@ pub fn retry_backoff() -> ExponentialBackoff { backoff.max_interval = MAX_BACKOFF_INTERVAL; backoff } + +/// Compact format of IDs vector. +pub fn format_ids(mut ids: impl ExactSizeIterator) -> String { + const NTH_PROOF: &str = "we have checked len; qed"; + match ids.len() { + 0 => "".into(), + 1 => format!("{:?}", ids.next().expect(NTH_PROOF)), + 2 => { + let id0 = ids.next().expect(NTH_PROOF); + let id1 = ids.next().expect(NTH_PROOF); + format!("[{:?}, {:?}]", id0, id1) + } + len => { + let id0 = ids.next().expect(NTH_PROOF); + let id_last = ids.last().expect(NTH_PROOF); + format!("{}:[{:?} ... {:?}]", len, id0, id_last) + } + } +} From ffe913c821d6c2b41fdad569026e7592f6abcfe7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 31 Jul 2020 01:00:02 +0300 Subject: [PATCH 0121/1210] Add traces to PoA builtin (#258) * replace debug printlns with traces * cargo fmt --all * fixed traces * update RUST_LOG in docker-compose * only print hex data if error has occured * updated OE hash --- modules/ethereum-contract/builtin/Cargo.toml | 2 + modules/ethereum-contract/builtin/src/lib.rs | 63 +++++++++++++++++--- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index cfee003f19176..73d7cd45a6695 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -13,6 +13,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1" } ethereum-types = "0.9.2" finality-grandpa = "0.12.3" +hex = "0.4" +log = "0.4.11" # Runtime/chain specific dependencies diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs index 5f284231a7259..f99704b45a11f 100644 --- a/modules/ethereum-contract/builtin/src/lib.rs +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -63,10 +63,19 @@ pub struct ValidatorsSetSignal { /// Convert from U256 to BlockNumber. Fails if `U256` value isn't fitting within `BlockNumber` /// limits (the runtime referenced by this module uses u32 as `BlockNumber`). pub fn to_substrate_block_number(number: U256) -> Result { - match number == number.low_u32().into() { + let substrate_block_number = match number == number.low_u32().into() { true => Ok(number.low_u32()), false => Err(Error::BlockNumberDecode), - } + }; + + log::trace!( + target: "bridge-builtin", + "Parsed Substrate block number from {}: {:?}", + number, + substrate_block_number, + ); + + substrate_block_number } /// Convert from BlockNumber to U256. @@ -76,7 +85,7 @@ pub fn from_substrate_block_number(number: BlockNumber) -> Result { /// Parse Substrate header. pub fn parse_substrate_header(raw_header: &[u8]) -> Result { - RuntimeHeader::decode(&mut &raw_header[..]) + let substrate_header = RuntimeHeader::decode(&mut &raw_header[..]) .map(|header| Header { hash: header.hash(), parent_hash: header.parent_hash, @@ -100,7 +109,20 @@ pub fn parse_substrate_header(raw_header: &[u8]) -> Result { _ => None, }), }) - .map_err(Error::HeaderDecode) + .map_err(Error::HeaderDecode); + + log::debug!( + target: "bridge-builtin", + "Parsed Substrate header {}: {:?}", + if substrate_header.is_ok() { + format!("<{}-bytes-blob>", raw_header.len()) + } else { + hex::encode(raw_header) + }, + substrate_header, + ); + + substrate_header } /// Verify GRANDPA finality proof. @@ -113,8 +135,22 @@ pub fn verify_substrate_finality_proof( ) -> Result<(), Error> { let best_set = AuthorityList::decode(&mut &raw_best_set[..]) .map_err(Error::BestSetDecode) - .and_then(|authorities| VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet))?; - sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( + .and_then(|authorities| VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet)); + + log::debug!( + target: "bridge-builtin", + "Parsed Substrate authorities set {}: {:?}", + if best_set.is_ok() { + format!("<{}-bytes-blob>", raw_best_set.len()) + } else { + hex::encode(raw_best_set) + }, + best_set, + ); + + let best_set = best_set?; + + let verify_result = sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( &raw_finality_proof, (finality_target_hash, finality_target_number), best_set_id, @@ -122,7 +158,20 @@ pub fn verify_substrate_finality_proof( ) .map_err(Box::new) .map_err(Error::JustificationVerify) - .map(|_| ()) + .map(|_| ()); + + log::debug!( + target: "bridge-builtin", + "Verified Substrate finality proof {}: {:?}", + if verify_result.is_ok() { + format!("<{}-bytes-blob>", raw_finality_proof.len()) + } else { + hex::encode(raw_finality_proof) + }, + verify_result, + ); + + verify_result } #[cfg(test)] From a25d7e13341aba97421333a70e95917e7fa3903f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 31 Jul 2020 16:32:22 +0300 Subject: [PATCH 0122/1210] Fix gas_used fields in receipts (#261) * gas_used should be cumulative_gas_used!!! * more runtime traces * improve logs --- modules/currency-exchange/src/lib.rs | 8 ++- modules/ethereum/src/lib.rs | 75 +++++++++++++++++++++++--- modules/ethereum/src/validators.rs | 2 +- modules/ethereum/src/verification.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 37 +++++++++---- relays/ethereum/src/ethereum_client.rs | 7 +-- relays/ethereum/src/ethereum_types.rs | 4 -- relays/ethereum/src/rpc_errors.rs | 5 -- relays/ethereum/src/substrate_types.rs | 3 +- 9 files changed, 107 insertions(+), 36 deletions(-) diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index cf03239c8a664..967fbb66cb484 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -147,7 +147,13 @@ impl, I: Instance> Module { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { - if prepare_deposit_details::(proof).is_err() { + if let Err(err) = prepare_deposit_details::(proof) { + frame_support::debug::trace!( + target: "runtime", + "Can't accept exchange transaction: {:?}", + err, + ); + return false; } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ae6399f002fc1..cb8305543d6be 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -893,17 +893,40 @@ pub fn verify_transaction_finalized( proof: &[(RawTransaction, RawTransactionReceipt)], ) -> bool { if tx_index >= proof.len() as _ { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: transaction index ({}) is larger than number of transactions ({})", + tx_index, + proof.len(), + ); + return false; } let header = match storage.header(&block) { Some((header, _)) => header, - None => return false, + None => { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: can't find header in the storage: {}", + block, + ); + + return false; + } }; let finalized = storage.finalized_block(); // if header is not yet finalized => return if header.number > finalized.number { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: header {}/{} is not finalized. Best finalized: {}", + header.number, + block, + finalized.number, + ); + return false; } @@ -915,24 +938,62 @@ pub fn verify_transaction_finalized( false => block == finalized.hash, }; if !is_finalized { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: header {} is not finalized: no canonical path to best finalized block {}", + block, + finalized.hash, + ); + return false; } // verify that transaction is included in the block - if !header.verify_transactions_root(proof.iter().map(|(tx, _)| tx)) { + if let Err(computed_root) = header.check_transactions_root(proof.iter().map(|(tx, _)| tx)) { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: transactions root mismatch. Expected: {}, computed: {}", + header.transactions_root, + computed_root, + ); + return false; } // verify that transaction receipt is included in the block - if !header.verify_raw_receipts_root(proof.iter().map(|(_, r)| r)) { + if let Err(computed_root) = header.check_raw_receipts_root(proof.iter().map(|(_, r)| r)) { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: receipts root mismatch. Expected: {}, computed: {}", + header.receipts_root, + computed_root, + ); + return false; } // check that transaction has completed successfully - matches!( - Receipt::is_successful_raw_receipt(&proof[tx_index as usize].1), - Ok(true) - ) + let is_successful_raw_receipt = Receipt::is_successful_raw_receipt(&proof[tx_index as usize].1); + match is_successful_raw_receipt { + Ok(true) => true, + Ok(false) => { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: receipt shows that transaction has failed", + ); + + false + } + Err(err) => { + frame_support::debug::trace!( + target: "runtime", + "Tx finality check failed: receipt check has failed: {}", + err, + ); + + false + } + } } /// Transaction pool configuration. diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 9695e9a11be6d..8253ab2def693 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -132,7 +132,7 @@ impl<'a> Validators<'a> { } let receipts = receipts.ok_or(Error::MissingTransactionsReceipts)?; - if !header.verify_receipts_root(&receipts) { + if header.check_receipts_root(&receipts).is_err() { return Err(Error::TransactionsReceiptsMismatch); } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 31f9c2e5531d2..8e028edbbc86f 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -144,7 +144,7 @@ pub fn accept_aura_header_into_pool( // the heaviest, but rare operation - we do not want invalid receipts in the pool if let Some(receipts) = receipts { frame_support::debug::trace!(target: "runtime", "Got receipts! {:?}", receipts); - if !header.verify_receipts_root(receipts) { + if header.check_receipts_root(receipts).is_err() { return Err(Error::TransactionsReceiptsMismatch); } } diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index ada3fe9a1a327..a2a2b9366b6e7 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -205,18 +205,30 @@ impl Header { } /// Check if passed transactions receipts are matching receipts root in this header. - pub fn verify_receipts_root(&self, receipts: &[Receipt]) -> bool { - verify_merkle_proof(self.receipts_root, receipts.iter().map(|r| r.rlp())) + /// Returns Ok(computed-root) if check succeeds. + /// Returns Err(computed-root) if check fails. + pub fn check_receipts_root(&self, receipts: &[Receipt]) -> Result { + check_merkle_proof(self.receipts_root, receipts.iter().map(|r| r.rlp())) } /// Check if passed raw transactions receipts are matching receipts root in this header. - pub fn verify_raw_receipts_root<'a>(&self, receipts: impl IntoIterator) -> bool { - verify_merkle_proof(self.receipts_root, receipts.into_iter()) + /// Returns Ok(computed-root) if check succeeds. + /// Returns Err(computed-root) if check fails. + pub fn check_raw_receipts_root<'a>( + &self, + receipts: impl IntoIterator, + ) -> Result { + check_merkle_proof(self.receipts_root, receipts.into_iter()) } /// Check if passed transactions are matching transactions root in this header. - pub fn verify_transactions_root<'a>(&self, transactions: impl IntoIterator) -> bool { - verify_merkle_proof(self.transactions_root, transactions.into_iter()) + /// Returns Ok(computed-root) if check succeeds. + /// Returns Err(computed-root) if check fails. + pub fn check_transactions_root<'a>( + &self, + transactions: impl IntoIterator, + ) -> Result { + check_merkle_proof(self.transactions_root, transactions.into_iter()) } /// Gets the seal hash of this header. @@ -502,9 +514,16 @@ pub fn public_to_address(public: &[u8; 64]) -> Address { result } -/// Verify ethereum merkle proof. -fn verify_merkle_proof>(expected_root: H256, items: impl Iterator) -> bool { - compute_merkle_root(items) == expected_root +/// Check ethereum merkle proof. +/// Returns Ok(computed-root) if check succeeds. +/// Returns Err(computed-root) if check fails. +fn check_merkle_proof>(expected_root: H256, items: impl Iterator) -> Result { + let computed_root = compute_merkle_root(items); + if computed_root == expected_root { + Ok(computed_root) + } else { + Err(computed_root) + } } /// Compute ethereum merkle root. diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index df4945afcaf7d..b489cab522359 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -169,12 +169,7 @@ impl EthereumRpc for EthereumRpcClient { } async fn transaction_receipt(&self, transaction_hash: H256) -> Result { - let receipt = Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?; - - match receipt.gas_used { - Some(_) => Ok(receipt), - None => Err(RpcError::Ethereum(EthereumNodeError::IncompleteReceipt)), - } + Ok(Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?) } async fn account_nonce(&self, address: Address) -> Result { diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index 58aa3497014fd..8dcfb00fc94c7 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -24,10 +24,6 @@ pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; /// both number and hash fields filled. pub const HEADER_ID_PROOF: &str = "checked on retrieval; qed"; -/// When receipt is just received from the Ethereum node, we check that it has -/// gas_used field filled. -pub const RECEIPT_GAS_USED_PROOF: &str = "checked on retrieval; qed"; - /// Ethereum transaction hash type. pub type TransactionHash = H256; diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index dfc84192db0f4..aa3bcbde09dba 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -95,8 +95,6 @@ pub enum EthereumNodeError { ResponseParseFailed(String), /// We have received a header with missing fields. IncompleteHeader, - /// We have received a receipt missing a `gas_used` field. - IncompleteReceipt, /// We have received a transaction missing a `raw` field. IncompleteTransaction, /// An invalid Substrate block number was received from @@ -112,9 +110,6 @@ impl ToString for EthereumNodeError { "Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom)" .to_string() } - Self::IncompleteReceipt => { - "Incomplete Ethereum Receipt Recieved (missing required field - gas_used)".to_string() - } Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), } diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 7d761a627e66a..9e5ce6b732c73 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -16,7 +16,6 @@ use crate::ethereum_types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, - RECEIPT_GAS_USED_PROOF as ETHEREUM_RECEIPT_GAS_USED_PROOF, }; use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; use codec::Encode; @@ -108,7 +107,7 @@ pub fn into_substrate_ethereum_receipts( /// Convert Ethereum transactions receipt into Ethereum transactions receipt for Substrate. pub fn into_substrate_ethereum_receipt(receipt: &EthereumReceipt) -> SubstrateEthereumReceipt { SubstrateEthereumReceipt { - gas_used: receipt.gas_used.expect(ETHEREUM_RECEIPT_GAS_USED_PROOF), + gas_used: receipt.cumulative_gas_used, log_bloom: receipt.logs_bloom.data().into(), logs: receipt .logs From d492e55883e29705ece478cc593fa7f65a4d9592 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 3 Aug 2020 06:55:30 -0400 Subject: [PATCH 0123/1210] Bump Substrate to RC5 (#243) * Bump Substrate to rc5 * Bump async-std to v1.6.2 There was a bug in v.1.6.0 which kept us locked to v1.5 releases. I think that's fixed now so I'm bumping this. * Update bridge node runtime * Update node service * Update CLI * Add SystemWeightInfo type to test runtimes * Add RPC extension builder to service * Directly return rpc_extensions_builder * Allow complex types in service This comes from Substrate, so I'd rather just keep the code as is * Update benchmarking code for new CLI --- bin/node/node/Cargo.toml | 94 ++--- bin/node/node/src/command.rs | 52 ++- bin/node/node/src/service.rs | 366 +++++++++++-------- bin/node/runtime/Cargo.toml | 106 +++--- bin/node/runtime/src/lib.rs | 32 +- modules/currency-exchange/Cargo.toml | 28 +- modules/currency-exchange/src/lib.rs | 1 + modules/ethereum-contract/builtin/Cargo.toml | 20 +- modules/ethereum/Cargo.toml | 24 +- modules/ethereum/src/mock.rs | 1 + modules/substrate/Cargo.toml | 36 +- modules/substrate/src/lib.rs | 1 + primitives/currency-exchange/Cargo.toml | 12 +- primitives/ethereum-poa/Cargo.toml | 16 +- relays/ethereum/Cargo.toml | 30 +- 15 files changed, 448 insertions(+), 371 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index f60ad3ac0c826..cea3b6915274c 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -25,110 +25,110 @@ default-features = false features = ["std"] [dependencies.sc-cli] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" -[dependencies.grandpa] +[dependencies.sc-finality-grandpa] package = "sc-finality-grandpa" -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-client-api] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking-cli] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -136,13 +136,13 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [build-dependencies.frame-benchmarking-cli] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [features] diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs index 9a23704decd72..8a50ab1ad40e1 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/node/src/command.rs @@ -32,37 +32,42 @@ use crate::cli::{Cli, Subcommand}; use crate::service; +use crate::service::new_full_params; use bridge_node_runtime::Block; -use sc_cli::SubstrateCli; -use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; +use sc_service::ServiceParams; impl SubstrateCli for Cli { - fn impl_name() -> &'static str { - "Bridge Node" + fn impl_name() -> String { + "Bridge Node".into() } - fn impl_version() -> &'static str { - env!("CARGO_PKG_VERSION") + fn impl_version() -> String { + env!("CARGO_PKG_VERSION").into() } - fn description() -> &'static str { - "Bridge Node" + fn description() -> String { + "Bridge Node".into() } - fn author() -> &'static str { - "Parity Technologies" + fn author() -> String { + "Parity Technologies".into() } - fn support_url() -> &'static str { - "https://github.com/paritytech/parity-bridges-common/" + fn support_url() -> String { + "https://github.com/paritytech/parity-bridges-common/".into() } fn copyright_start_year() -> i32 { 2019 } - fn executable_name() -> &'static str { - "bridge-node" + fn executable_name() -> String { + "bridge-node".into() + } + + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &bridge_node_runtime::VERSION } fn load_spec(&self, id: &str) -> Result, String> { @@ -97,11 +102,26 @@ pub fn run() -> sc_cli::Result<()> { } Some(Subcommand::Base(subcommand)) => { let runner = cli.create_runner(subcommand)?; - runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0)) + runner.run_subcommand(subcommand, |config| { + let ( + ServiceParams { + client, + backend, + task_manager, + import_queue, + .. + }, + .., + ) = new_full_params(config)?; + Ok((client, backend, import_queue, task_manager)) + }) } None => { let runner = cli.create_runner(&cli.run)?; - runner.run_node(service::new_light, service::new_full, bridge_node_runtime::VERSION) + runner.run_node_until_exit(|config| match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + }) } } } diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index c32ecc3220e7c..4607c51b50b88 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -17,12 +17,13 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use bridge_node_runtime::{self, opaque::Block, RuntimeApi}; -use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState, StorageAndProofProvider}; -use sc_client_api::ExecutorProvider; -use sc_consensus::LongestChain; +use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sc_service::{error::Error as ServiceError, AbstractService, Configuration, ServiceBuilder}; +use sc_finality_grandpa::{ + FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState, StorageAndProofProvider, +}; +use sc_service::{error::Error as ServiceError, Configuration, ServiceComponents, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -36,137 +37,175 @@ native_executor_instance!( frame_benchmarking::benchmarking::HostFunctions, ); -/// Starts a `ServiceBuilder` for a full service. -/// -/// Use this macro if you don't actually need the full service, but just the builder in order to -/// be able to perform chain operations. -macro_rules! new_full_start { - ($config:expr) => {{ - use std::sync::Arc; - - let mut import_setup = None; - let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - - let builder = sc_service::ServiceBuilder::new_full::< - bridge_node_runtime::opaque::Block, - bridge_node_runtime::RuntimeApi, - crate::service::Executor, - >($config)? - .with_select_chain(|_config, backend| Ok(sc_consensus::LongestChain::new(backend.clone())))? - .with_transaction_pool(|builder| { - let pool_api = sc_transaction_pool::FullChainApi::new(builder.client().clone()); - Ok(sc_transaction_pool::BasicPool::new( - builder.config().transaction_pool.clone(), - std::sync::Arc::new(pool_api), - builder.prometheus_registry(), - )) - })? - .with_import_queue( - |_config, client, mut select_chain, _transaction_pool, spawn_task_handle, registry| { - let select_chain = select_chain - .take() - .ok_or_else(|| sc_service::Error::SelectChainRequired)?; - - let (grandpa_block_import, grandpa_link) = - grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; - - let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new( - grandpa_block_import.clone(), - client.clone(), - ); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import.clone())), - None, - client, - inherent_data_providers.clone(), - spawn_task_handle, - registry, - )?; - - import_setup = Some((grandpa_block_import, grandpa_link)); - - Ok(import_queue) - }, - )? - .with_rpc_extensions(|builder| -> Result, _> { - use sc_rpc::DenyUnsafe; - use substrate_frame_rpc_system::{FullSystem, SystemApi}; - +type FullClient = sc_service::TFullClient; +type FullBackend = sc_service::TFullBackend; +type FullSelectChain = sc_consensus::LongestChain; + +#[allow(clippy::type_complexity)] +pub fn new_full_params( + config: Configuration, +) -> Result< + ( + sc_service::ServiceParams< + Block, + FullClient, + sc_consensus_aura::AuraImportQueue, + sc_transaction_pool::FullPool, + jsonrpc_core::IoHandler, + FullBackend, + >, + FullSelectChain, + sp_inherents::InherentDataProviders, + sc_finality_grandpa::GrandpaBlockImport, + sc_finality_grandpa::LinkHalf, + ), + ServiceError, +> { + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + + let (client, backend, keystore, task_manager) = sc_service::new_full_parts::(&config)?; + let client = Arc::new(client); + + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + + let pool_api = sc_transaction_pool::FullChainApi::new(client.clone(), config.prometheus_registry()); + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + std::sync::Arc::new(pool_api), + config.prometheus_registry(), + task_manager.spawn_handle(), + client.clone(), + ); + + let (grandpa_block_import, grandpa_link) = + sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; + + let aura_block_import = + sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client.clone(), + inherent_data_providers.clone(), + &task_manager.spawn_handle(), + config.prometheus_registry(), + )?; + + let rpc_extensions_builder = { + use sc_rpc::DenyUnsafe; + use substrate_frame_rpc_system::{FullSystem, SystemApi}; + + let client = client.clone(); + let pool = transaction_pool.clone(); + + Box::new(move |_| { let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( - builder.client().clone(), - builder.pool(), + client.clone(), + pool.clone(), DenyUnsafe::No, ))); - Ok(io) - })?; - (builder, import_setup, inherent_data_providers) - }}; + io + }) + }; + + let provider = client.clone() as Arc>; + let finality_proof_provider = Arc::new(GrandpaFinalityProofProvider::new(backend.clone(), provider)); + + let params = sc_service::ServiceParams { + backend, + client, + import_queue, + keystore, + task_manager, + transaction_pool, + config, + block_announce_validator_builder: None, + finality_proof_request_builder: None, + finality_proof_provider: Some(finality_proof_provider), + on_demand: None, + remote_blockchain: None, + rpc_extensions_builder, + }; + + Ok(( + params, + select_chain, + inherent_data_providers, + grandpa_block_import, + grandpa_link, + )) } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { - let role = config.role.clone(); - let force_authoring = config.force_authoring; - let name = config.network.node_name.clone(); - let disable_grandpa = config.disable_grandpa; +pub fn new_full(config: Configuration) -> Result { + let (params, select_chain, inherent_data_providers, block_import, grandpa_link) = new_full_params(config)?; - let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); - - let (block_import, grandpa_link) = import_setup - .take() - .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); + let (role, force_authoring, name, enable_grandpa, prometheus_registry, client, transaction_pool, keystore) = { + let sc_service::ServiceParams { + config, + client, + transaction_pool, + keystore, + .. + } = ¶ms; + + ( + config.role.clone(), + config.force_authoring, + config.network.node_name.clone(), + !config.disable_grandpa, + config.prometheus_registry().cloned(), + client.clone(), + transaction_pool.clone(), + keystore.clone(), + ) + }; - let service = builder - .with_finality_proof_provider(|client, backend| { - let provider = client as Arc>; - Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) - })? - .build_full()?; + let ServiceComponents { + task_manager, + network, + telemetry_on_connect_sinks, + .. + } = sc_service::build(params)?; if role.is_authority() { - let proposer = sc_basic_authorship::ProposerFactory::new( - service.client(), - service.transaction_pool(), - service.prometheus_registry().as_ref(), - ); - - let client = service.client(); - let select_chain = service.select_chain().ok_or(ServiceError::SelectChainRequired)?; + let proposer = + sc_basic_authorship::ProposerFactory::new(client.clone(), transaction_pool, prometheus_registry.as_ref()); let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( sc_consensus_aura::slot_duration(&*client)?, - client, + client.clone(), select_chain, block_import, proposer, - service.network(), + network.clone(), inherent_data_providers.clone(), force_authoring, - service.keystore(), + keystore.clone(), can_author_with, )?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. - service.spawn_essential_task_handle().spawn_blocking("aura", aura); + task_manager.spawn_essential_handle().spawn_blocking("aura", aura); } // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. let keystore = if role.is_authority() { - Some(service.keystore() as sp_core::traits::BareCryptoStorePtr) + Some(keystore as sp_core::traits::BareCryptoStorePtr) } else { None }; - let grandpa_config = grandpa::Config { + let grandpa_config = sc_finality_grandpa::Config { // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), justification_period: 512, @@ -176,7 +215,6 @@ pub fn new_full(config: Configuration) -> Result Result Result { - let inherent_data_providers = InherentDataProviders::new(); - - ServiceBuilder::new_light::(config)? - .with_select_chain(|_config, backend| Ok(LongestChain::new(backend.clone())))? - .with_transaction_pool(|builder| { - let fetcher = builder - .fetcher() - .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?; - - let pool_api = sc_transaction_pool::LightChainApi::new(builder.client().clone(), fetcher); - let pool = sc_transaction_pool::BasicPool::with_revalidation_type( - builder.config().transaction_pool.clone(), - Arc::new(pool_api), - builder.prometheus_registry(), - sc_transaction_pool::RevalidationType::Light, - ); - Ok(pool) - })? - .with_import_queue_and_fprb( - |_config, client, backend, fetcher, _select_chain, _tx_pool, spawn_task_handle, prometheus_registry| { - let fetch_checker = fetcher - .map(|fetcher| fetcher.checker().clone()) - .ok_or_else(|| "Trying to start light import queue without active fetch checker")?; - let grandpa_block_import = grandpa::light_block_import( - client.clone(), - backend, - &(client.clone() as Arc<_>), - Arc::new(fetch_checker), - )?; - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); - - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( - sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import, - None, - Some(Box::new(finality_proof_import)), - client, - inherent_data_providers.clone(), - spawn_task_handle, - prometheus_registry, - )?; - - Ok((import_queue, finality_proof_request_builder)) - }, - )? - .with_finality_proof_provider(|client, backend| { - let provider = client as Arc>; - Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _) - })? - .build_light() +pub fn new_light(config: Configuration) -> Result { + let (client, backend, keystore, task_manager, on_demand) = + sc_service::new_light_parts::(&config)?; + + let transaction_pool_api = Arc::new(sc_transaction_pool::LightChainApi::new( + client.clone(), + on_demand.clone(), + )); + let transaction_pool = sc_transaction_pool::BasicPool::new_light( + config.transaction_pool.clone(), + transaction_pool_api, + config.prometheus_registry(), + task_manager.spawn_handle(), + ); + + let grandpa_block_import = sc_finality_grandpa::light_block_import( + client.clone(), + backend.clone(), + &(client.clone() as Arc<_>), + Arc::new(on_demand.checker().clone()) as Arc<_>, + )?; + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + sc_consensus_aura::slot_duration(&*client)?, + grandpa_block_import, + None, + Some(Box::new(finality_proof_import)), + client.clone(), + InherentDataProviders::new(), + &task_manager.spawn_handle(), + config.prometheus_registry(), + )?; + + let finality_proof_provider = Arc::new(GrandpaFinalityProofProvider::new( + backend.clone(), + client.clone() as Arc<_>, + )); + + sc_service::build(sc_service::ServiceParams { + block_announce_validator_builder: None, + finality_proof_request_builder: Some(finality_proof_request_builder), + finality_proof_provider: Some(finality_proof_provider), + on_demand: Some(on_demand), + remote_blockchain: Some(backend.remote_blockchain()), + rpc_extensions_builder: Box::new(|_| ()), + transaction_pool: Arc::new(transaction_pool), + config, + client, + import_queue, + keystore, + backend, + task_manager, + }) + .map(|ServiceComponents { task_manager, .. }| task_manager) } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 11f3a8f457758..205932ca04485 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -29,14 +29,14 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" @@ -51,75 +51,75 @@ default-features = false path = "../../../modules/currency-exchange" [dependencies.frame-support] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" @@ -134,75 +134,75 @@ default-features = false path = "../../../primitives/currency-exchange" [dependencies.sp-consensus-aura] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" @@ -219,7 +219,7 @@ path = "../../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] version = "1.0.5" -tag = 'v2.0.0-rc4' +tag = 'v2.0.0-rc5' package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 113f32f09138c..22abc50b6d298 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -35,9 +35,6 @@ pub mod benches; pub mod kovan; pub mod rialto; -#[cfg(feature = "runtime-benchmarks")] -pub use benches as bridge; - use codec::{Decode, Encode}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; @@ -223,6 +220,8 @@ impl frame_system::Trait for Runtime { type OnKilledAccount = (); /// The data to be stored in an account. type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); } impl pallet_aura::Trait for Runtime { @@ -349,6 +348,7 @@ impl pallet_timestamp::Trait for Runtime { type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); } parameter_types! { @@ -363,6 +363,7 @@ impl pallet_balances::Trait for Runtime { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = (); } parameter_types! { @@ -398,6 +399,7 @@ impl pallet_session::Trait for Runtime { type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = (); + type WeightInfo = (); } pub struct ShiftSessionManager; @@ -464,7 +466,7 @@ construct_runtime!( System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Aura: pallet_aura::{Module, Config, Inherent(Timestamp)}, + Aura: pallet_aura::{Module, Config, Inherent}, Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, @@ -650,14 +652,19 @@ impl_runtime_apis! { Grandpa::grandpa_authorities() } - fn submit_report_equivocation_extrinsic( - _equivocation_proof: fg_primitives::EquivocationProof< + fn submit_report_equivocation_unsigned_extrinsic( + equivocation_proof: fg_primitives::EquivocationProof< ::Hash, NumberFor, >, - _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, ) -> Option<()> { - None + let key_owner_proof = key_owner_proof.decode()?; + + Grandpa::submit_unsigned_equivocation_report( + equivocation_proof, + key_owner_proof, + ) } fn generate_key_ownership_proof( @@ -737,8 +744,13 @@ impl_runtime_apis! { } } - add_benchmark!(params, batches, b"bridge-eth-poa", BridgeKovan); - add_benchmark!(params, batches, b"bridge-currency-exchange", BridgeCurrencyExchangeBench::); + add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeKovan); + add_benchmark!( + params, + batches, + pallet_bridge_currency_exchange, + BridgeCurrencyExchangeBench:: + ); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 23865b32bfff6..4c8116aca895f 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -13,44 +13,44 @@ sp-currency-exchange = { path = "../../primitives/currency-exchange", default-fe # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-io] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 967fbb66cb484..29ba94631e564 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -362,6 +362,7 @@ mod tests { type OnNewAccount = (); type OnKilledAccount = (); type BaseCallFilter = (); + type SystemWeightInfo = (); } impl Trait for TestRuntime { diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 73d7cd45a6695..97b497f5ee786 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -21,29 +21,29 @@ log = "0.4.11" bridge-node-runtime = { path = "../../../bin/node/runtime" } [dependencies.sp-blockchain] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [dependencies.sc-finality-grandpa] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [dev-dependencies] hex = "0.4" [dev-dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index dbe32d617794d..d2b17e0f63291 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -14,39 +14,39 @@ primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum- # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 31717d53cc44e..be173512a723f 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -69,6 +69,7 @@ impl frame_system::Trait for TestRuntime { type OnNewAccount = (); type OnKilledAccount = (); type BaseCallFilter = (); + type SystemWeightInfo = (); } parameter_types! { diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index ec5ec2a0e84b2..cec9e837eba4b 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -14,57 +14,57 @@ hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 9afa0872a57b9..3403d91a5b3d1 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -274,6 +274,7 @@ mod tests { type OnNewAccount = (); type OnKilledAccount = (); type BaseCallFilter = (); + type SystemWeightInfo = (); } impl Trait for Test {} diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 198d4ad531ed4..91052ca850975 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -12,20 +12,20 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.frame-support] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index f52fb42f1d1b7..d77efda8a3d31 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -23,26 +23,26 @@ plain_hasher = { version = "0.2.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 972d9be945dd1..e57a885d9d4fc 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" -async-std = "=1.5.0" +async-std = "1.6.2" async-stream = "0.2.0" async-trait = "0.1.36" backoff = "0.2" @@ -43,38 +43,38 @@ features = ["http"] # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.node-primitives] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc4" -tag = 'v2.0.0-rc4' +version = "2.0.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-prometheus-endpoint] -version = "0.8.0-rc4" -tag = 'v2.0.0-rc4' +version = "0.8.0-rc5" +tag = 'v2.0.0-rc5' git = "https://github.com/paritytech/substrate.git" [dependencies.bridge-node-runtime] From 605ff7e6992283e3743999f340abfaa187f2b696 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 4 Aug 2020 12:03:21 -0400 Subject: [PATCH 0124/1210] Support Pallet Instances in Relay (#238) * Sketch out how to support different bridge pallet instances * Create a common interface for using pallet instances * Start introducing generic instance parameter Attemps to make the compiler happy, but I'm having second thoughts about this approach. Commiting now as a way to have a checkpoint, but I think I'm going to need to re-consider my approach here. Ideally I want a change which introduces minimal changes, but this seems to be propagating around the codebase in ways I don't want. * Use trait objects instead of generics * Implement traits for Boxed trait objects This is done in order to statisfy trait bounds by types which use these new trait objects * Remove Clone usage for sync parameters * Remove implementation of Default for sync params * Require that BridgeInstance implements Debug * Ensure that BridgeInstance trait implements Send/Sync * Add documentation related to instances * Rust Fmt * Remove needless format * Make instance CLI option case insensitive * Replace `with_*` constructors with `new` * Clean up usage of instance structs * Enforce a default instance in the CLI params * Build sync params as we process input from CLI * Remove case insensitivity from sub-tx-mode I think this should happen, but maybe as part of a different PR * Process default Eth contract deployment config in CLI * Build EthereumExchangeParams in CLI * Process EthereumExchangeSubmitParams params in CLI --- relays/ethereum/src/cli.yml | 11 + .../ethereum/src/ethereum_deploy_contract.rs | 47 +++-- relays/ethereum/src/ethereum_exchange.rs | 50 +++-- .../ethereum/src/ethereum_exchange_submit.rs | 41 ++-- relays/ethereum/src/ethereum_sync_loop.rs | 94 +++++---- relays/ethereum/src/instances.rs | 115 +++++++++++ relays/ethereum/src/main.rs | 191 +++++++++++------- relays/ethereum/src/substrate_client.rs | 68 +++---- relays/ethereum/src/substrate_sync_loop.rs | 92 ++++----- relays/ethereum/src/sync.rs | 32 +++ 10 files changed, 461 insertions(+), 280 deletions(-) create mode 100644 relays/ethereum/src/instances.rs diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 135e8da29a986..0fbf866166d55 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -43,6 +43,17 @@ subcommands: long: sub-signer-password value_name: SUB_SIGNER_PASSWORD help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. + - sub-pallet-instance: &sub-pallet-instance + long: instance + short: i + value_name: PALLET_INSTANCE + help: The instance of the bridge pallet the relay should follow. + takes_value: true + case_insensitive: true + possible_values: + - Rialto + - Kovan + default_value: Rialto - no-prometheus: &no-prometheus long: no-prometheus help: Do not expose a Prometheus metric endpoint. diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index d46bd879448d9..cce91a5519b8d 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -17,6 +17,7 @@ use crate::ethereum_client::{ bridge_contract, EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, }; +use crate::instances::BridgeInstance; use crate::rpc::SubstrateRpc; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId}; @@ -29,50 +30,48 @@ use num_traits::Zero; #[derive(Debug)] pub struct EthereumDeployContractParams { /// Ethereum connection params. - pub eth: EthereumConnectionParams, + pub eth_params: EthereumConnectionParams, /// Ethereum signing params. pub eth_sign: EthereumSigningParams, /// Ethereum contract bytecode. pub eth_contract_code: Vec, /// Substrate connection params. - pub sub: SubstrateConnectionParams, + pub sub_params: SubstrateConnectionParams, /// Initial authorities set id. pub sub_initial_authorities_set_id: Option, /// Initial authorities set. pub sub_initial_authorities_set: Option>, /// Initial header. pub sub_initial_header: Option>, -} - -impl Default for EthereumDeployContractParams { - fn default() -> Self { - EthereumDeployContractParams { - eth: Default::default(), - eth_sign: Default::default(), - eth_contract_code: hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")) - .expect("code is hardcoded, thus valid; qed"), - sub: Default::default(), - sub_initial_authorities_set_id: None, - sub_initial_authorities_set: None, - sub_initial_header: None, - } - } + /// Instance of the bridge pallet being synchronized. + pub instance: Box, } /// Deploy Bridge contract on Ethereum chain. pub fn run(params: EthereumDeployContractParams) { let mut local_pool = futures::executor::LocalPool::new(); + let EthereumDeployContractParams { + eth_params, + eth_sign, + sub_params, + instance, + sub_initial_authorities_set_id, + sub_initial_authorities_set, + sub_initial_header, + eth_contract_code, + } = params; + let result = local_pool.run_until(async move { - let eth_client = EthereumRpcClient::new(params.eth); - let sub_client = SubstrateRpcClient::new(params.sub).await?; + let eth_client = EthereumRpcClient::new(eth_params); + let sub_client = SubstrateRpcClient::new(sub_params, instance).await?; - let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, params.sub_initial_header).await?; - let initial_set_id = params.sub_initial_authorities_set_id.unwrap_or(0); + let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; + let initial_set_id = sub_initial_authorities_set_id.unwrap_or(0); let initial_set = prepare_initial_authorities_set( &sub_client, initial_header_id.1, - params.sub_initial_authorities_set, + sub_initial_authorities_set, ).await?; log::info!( @@ -87,8 +86,8 @@ pub fn run(params: EthereumDeployContractParams) { deploy_bridge_contract( ð_client, - ¶ms.eth_sign, - params.eth_contract_code, + ð_sign, + eth_contract_code, initial_header, initial_set_id, initial_set, diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 9661f28f195ed..d094d9bae39c3 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -26,6 +26,7 @@ use crate::exchange::{ TransactionProofPipeline, }; use crate::exchange_loop::{run as run_loop, InMemoryStorage}; +use crate::instances::BridgeInstance; use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; @@ -58,15 +59,17 @@ pub enum ExchangeRelayMode { #[derive(Debug)] pub struct EthereumExchangeParams { /// Ethereum connection params. - pub eth: EthereumConnectionParams, + pub eth_params: EthereumConnectionParams, /// Substrate connection params. - pub sub: SubstrateConnectionParams, + pub sub_params: SubstrateConnectionParams, /// Substrate signing params. pub sub_sign: SubstrateSigningParams, /// Relay working mode. pub mode: ExchangeRelayMode, /// Metrics parameters. pub metrics_params: Option, + /// Instance of the bridge pallet being synchronized. + pub instance: Box, } /// Ethereum to Substrate exchange pipeline. @@ -253,18 +256,6 @@ impl TargetClient for SubstrateTransactionsTarget { } } -impl Default for EthereumExchangeParams { - fn default() -> Self { - EthereumExchangeParams { - eth: Default::default(), - sub: Default::default(), - sub_sign: Default::default(), - mode: ExchangeRelayMode::Auto(None), - metrics_params: Some(Default::default()), - } - } -} - /// Relay exchange transaction proof(s) to Substrate node. pub fn run(params: EthereumExchangeParams) { match params.mode { @@ -279,14 +270,22 @@ pub fn run(params: EthereumExchangeParams) { fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) { let mut local_pool = futures::executor::LocalPool::new(); + let EthereumExchangeParams { + eth_params, + sub_params, + sub_sign, + instance, + .. + } = params; + let result = local_pool.run_until(async move { - let eth_client = EthereumRpcClient::new(params.eth); - let sub_client = SubstrateRpcClient::new(params.sub).await?; + let eth_client = EthereumRpcClient::new(eth_params); + let sub_client = SubstrateRpcClient::new(sub_params, instance).await?; let source = EthereumTransactionsSource { client: eth_client }; let target = SubstrateTransactionsTarget { client: sub_client, - sign_params: params.sub_sign, + sign_params: sub_sign, }; relay_single_transaction_proof(&source, &target, eth_tx_hash).await @@ -313,9 +312,18 @@ fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H25 /// Run auto-relay loop. fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_with_block_number: Option) { + let EthereumExchangeParams { + eth_params, + sub_params, + sub_sign, + metrics_params, + instance, + .. + } = params; + let do_run_loop = move || -> Result<(), String> { - let eth_client = EthereumRpcClient::new(params.eth); - let sub_client = async_std::task::block_on(SubstrateRpcClient::new(params.sub)) + let eth_client = EthereumRpcClient::new(eth_params); + let sub_client = async_std::task::block_on(SubstrateRpcClient::new(sub_params, instance)) .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; let eth_start_with_block_number = match eth_start_with_block_number { @@ -337,9 +345,9 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi EthereumTransactionsSource { client: eth_client }, SubstrateTransactionsTarget { client: sub_client, - sign_params: params.sub_sign, + sign_params: sub_sign, }, - params.metrics_params, + metrics_params, futures::future::pending(), ); diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index 201b251db2ed3..96a0fc68d0f64 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -21,7 +21,6 @@ use crate::ethereum_types::{CallRequest, U256}; use crate::rpc::EthereumRpc; use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS; -use hex_literal::hex; use sp_bridge_eth_poa::{ signatures::{SecretKey, SignTransaction}, UnsignedTransaction, @@ -31,7 +30,7 @@ use sp_bridge_eth_poa::{ #[derive(Debug)] pub struct EthereumExchangeSubmitParams { /// Ethereum connection params. - pub eth: EthereumConnectionParams, + pub eth_params: EthereumConnectionParams, /// Ethereum signing params. pub eth_sign: EthereumSigningParams, /// Ethereum signer nonce. @@ -42,28 +41,24 @@ pub struct EthereumExchangeSubmitParams { pub sub_recipient: [u8; 32], } -impl Default for EthereumExchangeSubmitParams { - fn default() -> Self { - EthereumExchangeSubmitParams { - eth: Default::default(), - eth_sign: Default::default(), - eth_nonce: None, - eth_amount: 1_000_000_000_000_000_000_u64.into(), // 1 ETH - sub_recipient: hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"), // ferdie - } - } -} - /// Submit single Ethereum -> Substrate exchange transaction. pub fn run(params: EthereumExchangeSubmitParams) { let mut local_pool = futures::executor::LocalPool::new(); + let EthereumExchangeSubmitParams { + eth_params, + eth_sign, + eth_nonce, + eth_amount, + sub_recipient, + } = params; + let result: Result<_, String> = local_pool.run_until(async move { - let eth_client = EthereumRpcClient::new(params.eth); + let eth_client = EthereumRpcClient::new(eth_params); - let eth_signer_address = params.eth_sign.signer.address(); - let sub_recipient_encoded = params.sub_recipient; - let nonce = match params.eth_nonce { + let eth_signer_address = eth_sign.signer.address(); + let sub_recipient_encoded = sub_recipient; + let nonce = match eth_nonce { Some(eth_nonce) => eth_nonce, None => eth_client .account_nonce(eth_signer_address) @@ -74,7 +69,7 @@ pub fn run(params: EthereumExchangeSubmitParams) { .estimate_gas(CallRequest { from: Some(eth_signer_address), to: Some(LOCK_FUNDS_ADDRESS.into()), - value: Some(params.eth_amount), + value: Some(eth_amount), data: Some(sub_recipient_encoded.to_vec().into()), ..Default::default() }) @@ -82,16 +77,16 @@ pub fn run(params: EthereumExchangeSubmitParams) { .map_err(|err| format!("error estimating gas requirements: {:?}", err))?; let eth_tx_unsigned = UnsignedTransaction { nonce, - gas_price: params.eth_sign.gas_price, + gas_price: eth_sign.gas_price, gas, to: Some(LOCK_FUNDS_ADDRESS.into()), - value: params.eth_amount, + value: eth_amount, payload: sub_recipient_encoded.to_vec(), }; let eth_tx_signed = eth_tx_unsigned.clone().sign_by( - &SecretKey::parse(params.eth_sign.signer.secret().as_fixed_bytes()) + &SecretKey::parse(eth_sign.signer.secret().as_fixed_bytes()) .expect("key is accepted by secp256k1::KeyPair and thus is valid; qed"), - Some(params.eth_sign.chain_id), + Some(eth_sign.chain_id), ); eth_client .submit_transaction(eth_tx_signed) diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 4a13fa6a1dcf8..939cad5666da2 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -18,6 +18,7 @@ use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient}; use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; +use crate::instances::BridgeInstance; use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; @@ -32,57 +33,45 @@ use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; use web3::types::H256; +use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; -/// Interval at which we check new Ethereum headers when we are synced/almost synced. -const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); -/// Interval at which we check new Substrate blocks. -const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); -/// Max number of headers in single submit transaction. -const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; -/// Max total size of headers in single submit transaction. This only affects signed -/// submissions, when several headers are submitted at once. 4096 is the maximal **expected** -/// size of the Ethereum header + transactions receipts (if they're required). -const MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT: usize = MAX_HEADERS_IN_SINGLE_SUBMIT * 4096; -/// Max Ethereum headers we want to have in all 'before-submitted' states. -const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128; -/// Max Ethereum headers count we want to have in 'submitted' state. -const MAX_SUBMITTED_HEADERS: usize = 128; -/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). -const PRUNE_DEPTH: u32 = 4096; +pub mod consts { + use super::*; + + /// Interval at which we check new Ethereum headers when we are synced/almost synced. + pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); + /// Interval at which we check new Substrate blocks. + pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); + /// Max number of headers in single submit transaction. + pub const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; + /// Max total size of headers in single submit transaction. This only affects signed + /// submissions, when several headers are submitted at once. 4096 is the maximal **expected** + /// size of the Ethereum header + transactions receipts (if they're required). + pub const MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT: usize = MAX_HEADERS_IN_SINGLE_SUBMIT * 4096; + /// Max Ethereum headers we want to have in all 'before-submitted' states. + pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128; + /// Max Ethereum headers count we want to have in 'submitted' state. + pub const MAX_SUBMITTED_HEADERS: usize = 128; + /// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). + pub const PRUNE_DEPTH: u32 = 4096; +} /// Ethereum synchronization parameters. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct EthereumSyncParams { /// Ethereum connection params. - pub eth: EthereumConnectionParams, + pub eth_params: EthereumConnectionParams, /// Substrate connection params. - pub sub: SubstrateConnectionParams, + pub sub_params: SubstrateConnectionParams, /// Substrate signing params. pub sub_sign: SubstrateSigningParams, /// Synchronization parameters. pub sync_params: HeadersSyncParams, /// Metrics parameters. pub metrics_params: Option, -} - -impl Default for EthereumSyncParams { - fn default() -> Self { - EthereumSyncParams { - eth: Default::default(), - sub: Default::default(), - sub_sign: Default::default(), - sync_params: HeadersSyncParams { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, - max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - }, - metrics_params: Some(Default::default()), - } - } + /// Instance of the bridge pallet being synchronized. + pub instance: Box, } /// Ethereum client as headers source. @@ -190,26 +179,33 @@ impl TargetClient for SubstrateHeadersTarget { /// Run Ethereum headers synchronization. pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { - let sub_params = params.clone(); - - let eth_client = EthereumRpcClient::new(params.eth); - let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params.sub).await })?; - - let sign_sub_transactions = match params.sync_params.target_tx_mode { + let EthereumSyncParams { + eth_params, + sub_params, + sub_sign, + sync_params, + metrics_params, + instance, + } = params; + + let eth_client = EthereumRpcClient::new(eth_params); + let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?; + + let sign_sub_transactions = match sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, TargetTransactionMode::Unsigned => false, }; let source = EthereumHeadersSource::new(eth_client); - let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, params.sub_sign); + let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign); crate::sync_loop::run( source, - ETHEREUM_TICK_INTERVAL, + consts::ETHEREUM_TICK_INTERVAL, target, - SUBSTRATE_TICK_INTERVAL, - params.sync_params, - params.metrics_params, + consts::SUBSTRATE_TICK_INTERVAL, + sync_params, + metrics_params, futures::future::pending(), ); diff --git a/relays/ethereum/src/instances.rs b/relays/ethereum/src/instances.rs new file mode 100644 index 0000000000000..fa6963430b1d6 --- /dev/null +++ b/relays/ethereum/src/instances.rs @@ -0,0 +1,115 @@ +// Copyright 2020 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 . + +//! The PoA Bridge Pallet provides a way to include multiple instances of itself in a runtime. When +//! synchronizing a Substrate chain which can include multiple instances of the bridge pallet we +//! must somehow decide which of the instances to sync. +//! +//! Note that each instance of the bridge pallet is coupled with an instance of the currency exchange +//! pallet. We must also have a way to create `Call`s for the correct currency exchange instance. +//! +//! This module helps by preparing the correct `Call`s for each of the different pallet instances. + +use crate::ethereum_types::QueuedEthereumHeader; +use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; + +use bridge_node_runtime::exchange::EthereumTransactionInclusionProof as Proof; +use bridge_node_runtime::Call; + +/// Interface for `Calls` which are needed to correctly sync the bridge. +/// +/// Each instance of the bridge and currency exchange pallets in the bridge runtime requires similar +/// but slightly different `Call` in order to be synchronized. +pub trait BridgeInstance: Send + Sync + std::fmt::Debug { + /// Used to build a `Call` for importing signed headers to a Substrate runtime. + fn build_signed_header_call(&self, headers: Vec) -> Call; + /// Used to build a `Call` for importing an unsigned header to a Substrate runtime. + fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call; + /// Used to build a `Call` for importing peer transactions to a Substrate runtime. + fn build_currency_exchange_call(&self, proof: Proof) -> Call; +} + +/// Corresponds to the Rialto instance used in the bridge runtime. +#[derive(Default, Clone, Debug)] +pub struct Rialto; + +impl BridgeInstance for Rialto { + fn build_signed_header_call(&self, headers: Vec) -> Call { + let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + headers + .into_iter() + .map(|header| { + ( + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), + ) + }) + .collect(), + ); + + bridge_node_runtime::Call::BridgeRialto(pallet_call) + } + + fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { + let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), + ); + + bridge_node_runtime::Call::BridgeRialto(pallet_call) + } + + fn build_currency_exchange_call(&self, proof: Proof) -> Call { + let pallet_call = bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + bridge_node_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call) + } +} + +/// Corresponds to the Kovan instance used in the bridge runtime. +#[derive(Default, Clone, Debug)] +pub struct Kovan; + +impl BridgeInstance for Kovan { + fn build_signed_header_call(&self, headers: Vec) -> Call { + let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + headers + .into_iter() + .map(|header| { + ( + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), + ) + }) + .collect(), + ); + + bridge_node_runtime::Call::BridgeKovan(pallet_call) + } + + fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { + let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_receipts(header.extra()), + ); + + bridge_node_runtime::Call::BridgeKovan(pallet_call) + } + + fn build_currency_exchange_call(&self, proof: Proof) -> Call { + let pallet_call = bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + bridge_node_runtime::Call::BridgeKovanCurrencyExchange(pallet_call) + } +} diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 94d88f6e93911..5a1cf23ab1461 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -26,6 +26,7 @@ mod exchange; mod exchange_loop; mod exchange_loop_metrics; mod headers; +mod instances; mod metrics; mod rpc; mod rpc_errors; @@ -40,12 +41,19 @@ mod sync_types; mod utils; use ethereum_client::{EthereumConnectionParams, EthereumSigningParams}; +use ethereum_deploy_contract::EthereumDeployContractParams; +use ethereum_exchange::EthereumExchangeParams; +use ethereum_exchange_submit::EthereumExchangeSubmitParams; use ethereum_sync_loop::EthereumSyncParams; +use hex_literal::hex; +use instances::{BridgeInstance, Kovan, Rialto}; use parity_crypto::publickey::{KeyPair, Secret}; use sp_core::crypto::Pair; -use std::io::Write; use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams}; use substrate_sync_loop::SubstrateSyncParams; +use sync::HeadersSyncParams; + +use std::io::Write; fn main() { initialize(); @@ -210,110 +218,134 @@ fn substrate_signing_params(matches: &clap::ArgMatches) -> Result Result { - let mut eth_sync_params = EthereumSyncParams::default(); - eth_sync_params.eth = ethereum_connection_params(matches)?; - eth_sync_params.sub = substrate_connection_params(matches)?; - eth_sync_params.sub_sign = substrate_signing_params(matches)?; - eth_sync_params.metrics_params = metrics_params(matches)?; + let mut sync_params = HeadersSyncParams::ethereum_sync_default(); match matches.value_of("sub-tx-mode") { - Some("signed") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, + Some("signed") => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, Some("unsigned") => { - eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned; + sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned; // tx pool won't accept too much unsigned transactions - eth_sync_params.sync_params.max_headers_in_submitted_status = 10; + sync_params.max_headers_in_submitted_status = 10; } - Some("backup") => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Backup, + Some("backup") => sync_params.target_tx_mode = sync::TargetTransactionMode::Backup, Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), - None => eth_sync_params.sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, + None => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, } - log::debug!(target: "bridge", "Ethereum sync params: {:?}", eth_sync_params); + let params = EthereumSyncParams { + eth_params: ethereum_connection_params(matches)?, + sub_params: substrate_connection_params(matches)?, + sub_sign: substrate_signing_params(matches)?, + metrics_params: metrics_params(matches)?, + instance: instance_params(matches)?, + sync_params, + }; + + log::debug!(target: "bridge", "Ethereum sync params: {:?}", params); - Ok(eth_sync_params) + Ok(params) } fn substrate_sync_params(matches: &clap::ArgMatches) -> Result { - let mut sub_sync_params = SubstrateSyncParams::default(); - sub_sync_params.eth = ethereum_connection_params(matches)?; - sub_sync_params.eth_sign = ethereum_signing_params(matches)?; - sub_sync_params.sub = substrate_connection_params(matches)?; - sub_sync_params.metrics_params = metrics_params(matches)?; - - if let Some(eth_contract) = matches.value_of("eth-contract") { - sub_sync_params.eth_contract_address = eth_contract.parse().map_err(|e| format!("{}", e))?; - } + let eth_contract_address: ethereum_types::Address = if let Some(eth_contract) = matches.value_of("eth-contract") { + eth_contract.parse().map_err(|e| format!("{}", e))? + } else { + "731a10897d267e19b34503ad902d0a29173ba4b1" + .parse() + .expect("address is hardcoded, thus valid; qed") + }; - log::debug!(target: "bridge", "Substrate sync params: {:?}", sub_sync_params); + let params = SubstrateSyncParams { + sub_params: substrate_connection_params(matches)?, + eth_params: ethereum_connection_params(matches)?, + eth_sign: ethereum_signing_params(matches)?, + metrics_params: metrics_params(matches)?, + instance: instance_params(matches)?, + sync_params: HeadersSyncParams::substrate_sync_default(), + eth_contract_address, + }; + + log::debug!(target: "bridge", "Substrate sync params: {:?}", params); - Ok(sub_sync_params) + Ok(params) } -fn ethereum_deploy_contract_params( - matches: &clap::ArgMatches, -) -> Result { - let mut eth_deploy_params = ethereum_deploy_contract::EthereumDeployContractParams::default(); - eth_deploy_params.eth = ethereum_connection_params(matches)?; - eth_deploy_params.eth_sign = ethereum_signing_params(matches)?; - eth_deploy_params.sub = substrate_connection_params(matches)?; - - if let Some(eth_contract_code) = matches.value_of("eth-contract-code") { - eth_deploy_params.eth_contract_code = - hex::decode(ð_contract_code).map_err(|e| format!("Failed to parse eth-contract-code: {}", e))?; - } +fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result { + let eth_contract_code = if let Some(eth_contract_code) = matches.value_of("eth-contract-code") { + hex::decode(ð_contract_code).map_err(|e| format!("Failed to parse eth-contract-code: {}", e))? + } else { + hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")).expect("code is hardcoded, thus valid; qed") + }; - log::debug!(target: "bridge", "Deploy params: {:?}", eth_deploy_params); + let params = EthereumDeployContractParams { + eth_params: ethereum_connection_params(matches)?, + eth_sign: ethereum_signing_params(matches)?, + sub_params: substrate_connection_params(matches)?, + instance: instance_params(matches)?, + sub_initial_authorities_set_id: None, + sub_initial_authorities_set: None, + sub_initial_header: None, + eth_contract_code, + }; + + log::debug!(target: "bridge", "Deploy params: {:?}", params); - Ok(eth_deploy_params) + Ok(params) } -fn ethereum_exchange_submit_params( - matches: &clap::ArgMatches, -) -> Result { - let mut params = ethereum_exchange_submit::EthereumExchangeSubmitParams::default(); - params.eth = ethereum_connection_params(matches)?; - params.eth_sign = ethereum_signing_params(matches)?; - - if let Some(eth_nonce) = matches.value_of("eth-nonce") { - params.eth_nonce = Some( - ethereum_types::U256::from_dec_str(ð_nonce).map_err(|e| format!("Failed to parse eth-nonce: {}", e))?, - ); - } - if let Some(eth_amount) = matches.value_of("eth-amount") { - params.eth_amount = eth_amount +fn ethereum_exchange_submit_params(matches: &clap::ArgMatches) -> Result { + let eth_nonce = if let Some(eth_nonce) = matches.value_of("eth-nonce") { + Some(ethereum_types::U256::from_dec_str(ð_nonce).map_err(|e| format!("Failed to parse eth-nonce: {}", e))?) + } else { + None + }; + + let eth_amount = if let Some(eth_amount) = matches.value_of("eth-amount") { + eth_amount .parse() - .map_err(|e| format!("Failed to parse eth-amount: {}", e))?; - } - if let Some(sub_recipient) = matches.value_of("sub-recipient") { - params.sub_recipient = hex::decode(&sub_recipient) + .map_err(|e| format!("Failed to parse eth-amount: {}", e))? + } else { + // This is in Wei, represents 1 ETH + 1_000_000_000_000_000_000_u64.into() + }; + + // This is the well-known Substrate account of Ferdie + let default_recepient = hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"); + + let sub_recipient = if let Some(sub_recipient) = matches.value_of("sub-recipient") { + hex::decode(&sub_recipient) .map_err(|err| err.to_string()) .and_then(|vsub_recipient| { - let expected_len = params.sub_recipient.len(); + let expected_len = default_recepient.len(); if expected_len != vsub_recipient.len() { Err(format!("invalid length. Expected {} bytes", expected_len)) } else { - let mut sub_recipient = params.sub_recipient; + let mut sub_recipient = default_recepient; sub_recipient.copy_from_slice(&vsub_recipient[..expected_len]); Ok(sub_recipient) } }) - .map_err(|e| format!("Failed to parse sub-recipient: {}", e))?; - } + .map_err(|e| format!("Failed to parse sub-recipient: {}", e))? + } else { + default_recepient + }; + + let params = EthereumExchangeSubmitParams { + eth_params: ethereum_connection_params(matches)?, + eth_sign: ethereum_signing_params(matches)?, + eth_nonce, + eth_amount, + sub_recipient, + }; log::debug!(target: "bridge", "Submit Ethereum exchange tx params: {:?}", params); Ok(params) } -fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result { - let mut params = ethereum_exchange::EthereumExchangeParams::default(); - params.eth = ethereum_connection_params(matches)?; - params.sub = substrate_connection_params(matches)?; - params.sub_sign = substrate_signing_params(matches)?; - params.metrics_params = metrics_params(matches)?; - - params.mode = match matches.value_of("eth-tx-hash") { +fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result { + let mode = match matches.value_of("eth-tx-hash") { Some(eth_tx_hash) => ethereum_exchange::ExchangeRelayMode::Single( eth_tx_hash .parse() @@ -329,6 +361,15 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result Result Result, String> { + let instance: Box = if let Some(instance) = matches.value_of("sub-pallet-instance") { + match instance.to_lowercase().as_str() { + "rialto" => Box::new(Rialto::default()), + "kovan" => Box::new(Kovan::default()), + _ => return Err("Unsupported bridge pallet instance".to_string()), + } + } else { + unreachable!("CLI config enforces a default instance, can never be None") + }; + + Ok(instance) +} diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index bfb6c3c2793b0..f40d3a547254e 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -15,12 +15,10 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256}; +use crate::instances::BridgeInstance; use crate::rpc::{Substrate, SubstrateRpc}; use crate::rpc_errors::RpcError; -use crate::substrate_types::{ - into_substrate_ethereum_header, into_substrate_ethereum_receipts, Hash, Header as SubstrateHeader, Number, - SignedBlock as SignedSubstrateBlock, -}; +use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock}; use crate::sync_types::{HeaderId, SubmittedHeaders}; use async_trait::async_trait; @@ -89,11 +87,13 @@ pub struct SubstrateRpcClient { client: Client, /// Genesis block hash. genesis_hash: H256, + /// Instance of the bridge pallet being synchronized. + instance: Box, } impl SubstrateRpcClient { /// Returns client that is able to call RPCs on Substrate node. - pub async fn new(params: SubstrateConnectionParams) -> Result { + pub async fn new(params: SubstrateConnectionParams, instance: Box) -> Result { let uri = format!("http://{}:{}", params.host, params.port); let transport = HttpTransportClient::new(&uri); let raw_client = RawClient::new(transport); @@ -102,7 +102,11 @@ impl SubstrateRpcClient { let number: Number = Zero::zero(); let genesis_hash = Substrate::chain_get_block_hash(&client, number).await?; - Ok(Self { client, genesis_hash }) + Ok(Self { + client, + genesis_hash, + instance, + }) } } @@ -248,7 +252,8 @@ impl SubmitEthereumHeaders for SubstrateRpcClient { let account_id = params.signer.public().as_array_ref().clone().into(); let nonce = self.next_account_index(account_id).await?; - let transaction = create_signed_submit_transaction(headers, ¶ms.signer, nonce, self.genesis_hash); + let call = self.instance.build_signed_header_call(headers); + let transaction = create_signed_submit_transaction(call, ¶ms.signer, nonce, self.genesis_hash); let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; Ok(()) } @@ -276,9 +281,13 @@ impl SubmitEthereumHeaders for SubstrateRpcClient { ) -> SubmittedHeaders { let mut ids = headers.iter().map(|header| header.id()).collect::>(); let mut submitted_headers = SubmittedHeaders::default(); + for header in headers { let id = ids.pop_front().expect("both collections have same size; qed"); - let transaction = create_unsigned_submit_transaction(header); + + let call = self.instance.build_unsigned_header_call(header); + let transaction = create_unsigned_submit_transaction(call); + match self.submit_extrinsic(Bytes(transaction.encode())).await { Ok(_) => submitted_headers.submitted.push(id), Err(error) => { @@ -335,15 +344,9 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { let account_id = params.signer.public().as_array_ref().clone().into(); let nonce = self.next_account_index(account_id).await?; - let transaction = create_signed_transaction( - // TODO [#209]: Change so that that it's dynamic - bridge_node_runtime::Call::BridgeRialtoCurrencyExchange( - bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof), - ), - ¶ms.signer, - nonce, - self.genesis_hash, - ); + let call = self.instance.build_currency_exchange_call(proof); + let transaction = create_signed_transaction(call, ¶ms.signer, nonce, self.genesis_hash); + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; Ok(()) } @@ -351,40 +354,17 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { /// Create signed Substrate transaction for submitting Ethereum headers. fn create_signed_submit_transaction( - headers: Vec, + signed_call: bridge_node_runtime::Call, signer: &sp_core::sr25519::Pair, index: node_primitives::Index, genesis_hash: H256, ) -> bridge_node_runtime::UncheckedExtrinsic { - create_signed_transaction( - // TODO [#209]: Change so that that it's dynamic - bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_signed_headers( - headers - .into_iter() - .map(|header| { - ( - into_substrate_ethereum_header(header.header()), - into_substrate_ethereum_receipts(header.extra()), - ) - }) - .collect(), - )), - signer, - index, - genesis_hash, - ) + create_signed_transaction(signed_call, signer, index, genesis_hash) } /// Create unsigned Substrate transaction for submitting Ethereum header. -fn create_unsigned_submit_transaction(header: QueuedEthereumHeader) -> bridge_node_runtime::UncheckedExtrinsic { - let function = - // TODO [#209]: Change so that that it's dynamic - bridge_node_runtime::Call::BridgeRialto(bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(header.header()), - into_substrate_ethereum_receipts(header.extra()), - )); - - bridge_node_runtime::UncheckedExtrinsic::new_unsigned(function) +fn create_unsigned_submit_transaction(call: bridge_node_runtime::Call) -> bridge_node_runtime::UncheckedExtrinsic { + bridge_node_runtime::UncheckedExtrinsic::new_unsigned(call) } /// Create signed Substrate transaction. diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 16afb163d41a2..0ed7913327234 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -20,6 +20,7 @@ use crate::ethereum_client::{ EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, }; use crate::ethereum_types::Address; +use crate::instances::BridgeInstance; use crate::metrics::MetricsParams; use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; @@ -27,66 +28,47 @@ use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{ GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, }; -use crate::sync::{HeadersSyncParams, TargetTransactionMode}; +use crate::sync::HeadersSyncParams; use crate::sync_loop::{SourceClient, TargetClient}; use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; +use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; -/// Interval at which we check new Substrate headers when we are synced/almost synced. -const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10); -/// Interval at which we check new Ethereum blocks. -const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); -/// Max Ethereum headers we want to have in all 'before-submitted' states. -const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; -/// Max Ethereum headers count we want to have in 'submitted' state. -const MAX_SUBMITTED_HEADERS: usize = 1; -/// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). -const PRUNE_DEPTH: u32 = 256; +pub mod consts { + use super::*; + + /// Interval at which we check new Substrate headers when we are synced/almost synced. + pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10); + /// Interval at which we check new Ethereum blocks. + pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); + /// Max Ethereum headers we want to have in all 'before-submitted' states. + pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; + /// Max Ethereum headers count we want to have in 'submitted' state. + pub const MAX_SUBMITTED_HEADERS: usize = 1; + /// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). + pub const PRUNE_DEPTH: u32 = 256; +} /// Substrate synchronization parameters. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct SubstrateSyncParams { + /// Substrate connection params. + pub sub_params: SubstrateConnectionParams, /// Ethereum connection params. - pub eth: EthereumConnectionParams, + pub eth_params: EthereumConnectionParams, /// Ethereum signing params. pub eth_sign: EthereumSigningParams, /// Ethereum bridge contract address. pub eth_contract_address: Address, - /// Substrate connection params. - pub sub: SubstrateConnectionParams, /// Synchronization parameters. pub sync_params: HeadersSyncParams, /// Metrics parameters. pub metrics_params: Option, -} - -impl Default for SubstrateSyncParams { - fn default() -> Self { - SubstrateSyncParams { - eth: Default::default(), - eth_sign: Default::default(), - // the address 0x731a10897d267e19b34503ad902d0a29173ba4b1 is the address - // of the contract that is deployed by default signer and 0 nonce - eth_contract_address: "731a10897d267e19b34503ad902d0a29173ba4b1" - .parse() - .expect("address is hardcoded, thus valid; qed"), - sub: Default::default(), - sync_params: HeadersSyncParams { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - // since we always have single Substrate header in separate Ethereum transaction, - // all max_**_in_single_submit aren't important here - max_headers_in_single_submit: 4, - max_headers_size_in_single_submit: std::usize::MAX, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - }, - metrics_params: Some(Default::default()), - } - } + /// Instance of the bridge pallet being synchronized. + pub instance: Box, } /// Substrate client as headers source. @@ -199,21 +181,29 @@ impl TargetClient for EthereumHeadersTarget { /// Run Substrate headers synchronization. pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { - let sub_params = params.clone(); - - let eth_client = EthereumRpcClient::new(params.eth); - let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params.sub).await })?; - - let target = EthereumHeadersTarget::new(eth_client, params.eth_contract_address, params.eth_sign); + let SubstrateSyncParams { + sub_params, + eth_params, + eth_sign, + eth_contract_address, + sync_params, + metrics_params, + instance, + } = params; + + let eth_client = EthereumRpcClient::new(eth_params); + let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?; + + let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); crate::sync_loop::run( source, - SUBSTRATE_TICK_INTERVAL, + consts::SUBSTRATE_TICK_INTERVAL, target, - ETHEREUM_TICK_INTERVAL, - params.sync_params, - params.metrics_params, + consts::ETHEREUM_TICK_INTERVAL, + sync_params, + metrics_params, futures::future::pending(), ); diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index b1799bf2d2950..9ff7a0733f84b 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -36,6 +36,38 @@ pub struct HeadersSyncParams { pub target_tx_mode: TargetTransactionMode, } +impl HeadersSyncParams { + /// Default parameters for syncing Ethereum headers. + pub fn ethereum_sync_default() -> Self { + use crate::ethereum_sync_loop::consts::*; + + Self { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, + max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + } + } + + /// Default parameters for syncing Substrate headers. + pub fn substrate_sync_default() -> Self { + use crate::substrate_sync_loop::consts::*; + + Self { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + // since we always have single Substrate header in separate Ethereum transaction, + // all max_**_in_single_submit aren't important here + max_headers_in_single_submit: 4, + max_headers_size_in_single_submit: std::usize::MAX, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + } + } +} + /// Target transaction mode. #[derive(Debug, PartialEq, Clone)] pub enum TargetTransactionMode { From 6e507640b28ca61ec2d20352b87f3d9995fce78c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 5 Aug 2020 17:41:46 +0300 Subject: [PATCH 0125/1210] Prepare for sub to eth relay - part2 (#253) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed PoA contract deploy (granda_authorities call) * pause if all submitted headers were rejected * give funds to Bertha and Carlos * max 1 active PoA transaction in headers sync :( * display initial header id when deploying PoA contract * cargo fmt + clipy * update PoA contract to accept <= 4 Substrate headers at once * pause submitting headers when contract rejects all new headers + we have active transactions * fix compilation * cargo fmt --all * does_not_select_new_headers_to_submit_when_submit_is_paused * updated bridge contract * Update relays/ethereum/src/sync.rs Co-authored-by: Hernando Castano * WiP. * Submit first incomplete header. * Finish up test. * cargo fmt --all * Remove redundant clone. * Address review comments. * cargo fmt --all * Fix clippy. Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- relays/ethereum/res/substrate-bridge-abi.json | 42 +- .../res/substrate-bridge-bytecode.hex | 2 +- .../res/substrate-bridge-metadata.txt | 8 +- relays/ethereum/src/ethereum_client.rs | 363 ++++++++++++++---- relays/ethereum/src/exchange_loop.rs | 2 +- relays/ethereum/src/rpc_errors.rs | 3 + relays/ethereum/src/substrate_client.rs | 40 +- relays/ethereum/src/sync.rs | 65 ++++ relays/ethereum/src/sync_loop.rs | 16 +- 9 files changed, 433 insertions(+), 108 deletions(-) diff --git a/relays/ethereum/res/substrate-bridge-abi.json b/relays/ethereum/res/substrate-bridge-abi.json index 169b000680218..b7d7b4b9152cd 100644 --- a/relays/ethereum/res/substrate-bridge-abi.json +++ b/relays/ethereum/res/substrate-bridge-abi.json @@ -69,11 +69,26 @@ "inputs": [ { "internalType": "bytes", - "name": "rawHeader", + "name": "rawHeader1", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawHeader2", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawHeader3", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawHeader4", "type": "bytes" } ], - "name": "importHeader", + "name": "importHeaders", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -100,16 +115,31 @@ "inputs": [ { "internalType": "bytes", - "name": "rawHeader", + "name": "rawHeader1", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawHeader2", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawHeader3", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawHeader4", "type": "bytes" } ], - "name": "isIncompleteHeader", + "name": "isIncompleteHeaders", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", diff --git a/relays/ethereum/res/substrate-bridge-bytecode.hex b/relays/ethereum/res/substrate-bridge-bytecode.hex index 0a0973699d463..6dd6a33046f6c 100644 --- a/relays/ethereum/res/substrate-bridge-bytecode.hex +++ b/relays/ethereum/res/substrate-bridge-bytecode.hex @@ -1 +1 @@ -60806040523480156200001157600080fd5b506040516200142e3803806200142e833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d5565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260078352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f9260038501929101906200040a565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d1919060208501906200040a565b5050505050620004af565b620002e6620003d5565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa6200031c57600080fd5b84519b5083519a50825199508151985080519750505050505050506060816001600160401b03811180156200035057600080fd5b506040519080825280601f01601f1916602001820160405280156200037c576020820181803683370190505b5090508115620003a85787516020890160208301848184846011600019fa620003a457600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044d57805160ff19168380011785556200047d565b828001600101855582156200047d579182015b828111156200047d57825182559160200191906001019062000460565b506200048b9291506200048f565b5090565b620004ac91905b808211156200048b576000815560010162000496565b90565b610f6f80620004bf6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063374c2c2614610067578063871ebe18146101085780638dc1f05c14610139578063d96a2deb146101df578063e7af077914610200578063fae71ae8146102a8575b600080fd5b61006f61035a565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b357818101518382015260200161009b565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f25781810151838201526020016100da565b5050505090500194505050505060405180910390f35b6101256004803603602081101561011e57600080fd5b503561045f565b604080519115158252519081900360200190f35b6101256004803603602081101561014f57600080fd5b81019060208101813564010000000081111561016a57600080fd5b82018360208201111561017c57600080fd5b8035906020019184600183028401116401000000008311171561019e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610474945050505050565b6101e761049d565b6040805192835260208301919091528051918290030190f35b6102a66004803603602081101561021657600080fd5b81019060208101813564010000000081111561023157600080fd5b82018360208201111561024357600080fd5b8035906020019184600183028401116401000000008311171561026557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506104b5945050505050565b005b6102a6600480360360608110156102be57600080fd5b8135916020810135918101906060810160408201356401000000008111156102e557600080fd5b8201836020820111156102f757600080fd5b8035906020019184600183028401116401000000008311171561031957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610607945050505050565b6005546060908190818167ffffffffffffffff8111801561037a57600080fd5b506040519080825280602002602001820160405280156103a4578160200160208202803683370190505b50905060005b828110156103ff5760076000600583815481106103c357fe5b90600052602060002001548152602001908152602001600020600201548282815181106103ec57fe5b60209081029190910101526001016103aa565b508060058080548060200260200160405190810160405280929190818152602001828054801561044e57602002820191906000526020600020905b81548152602001906001019080831161043a575b505050505090509350935050509091565b60009081526007602052604090205460ff1690565b600061047e610d28565b60006104898461086c565b604090930151909214945050505050919050565b60008054808252600760205260409091206002015491565b6104bd610d28565b60008060006104cb8561086c565b93509350935093508360400151811415610526576005805485516001820180845560009384527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0909201558551825260066020526040909120555b6040805160e0810182526001808252602087810151818401908152888501518486019081526080808b01516060870190815267ffffffffffffffff8b169187019190915260a0860189905260c086018890528a51600090815260078552969096208551815460ff19169015151781559151938201939093559151600283015592518051929391926105bd9260038501920190610d5d565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c090910151600690910155505090516000555050565b60008281526007602052604090206002015483146106565760405162461bcd60e51b815260040180806020018281038252602f815260200180610eda602f913960400191505060405180910390fd5b60028054600354600480546040805160206101006001851615026000190190931696909604601f81018390048302870183019091528086529394600094610707948a948a9467ffffffffffffffff909216939290918301828280156106fc5780601f106106d1576101008083540402835291602001916106fc565b820191906000526020600020905b8154815290600101906020018083116106df57829003601f168201915b505050505087610af3565b600081815260076020526040902060028281558101546001559091505b828214610864575060008181526007602090815260408083206001810154600690935292205490929080156107e65760055460001991820191810182146107b25760006005600183038154811061077757fe5b90600052602060002001549050806005848154811061079257fe5b600091825260208083209091019290925591825260069052604090208290555b60058054806107bd57fe5b600082815260208082208301600019908101839055909201909255848252600690526040812055505b82600601548360020154141561085d57600583015460009081526007602052604090206003805467ffffffffffffffff198116600167ffffffffffffffff92831681019092161782559082018054610854926004929160026101009282161592909202600019011604610ddb565b50505050610864565b5050610724565b505050505050565b610874610d28565b6000806000610881610d28565b61088a86610c35565b805160009081526007602052604090205490915060ff16156108f3576040805162461bcd60e51b815260206004820152601760248201527f48656164657220697320616c7265616479206b6e6f776e000000000000000000604482015290519081900360640190fd5b6001548160400151116109375760405162461bcd60e51b8152600401808060200182810382526025815260200180610e6e6025913960400191505060405180910390fd5b6020808201516000908152600790915260409020805460ff168015610966575060018260400151038160020154145b6109a15760405162461bcd60e51b8152600401808060200182810382526026815260200180610e936026913960400191505060405180910390fd5b6006810154158015906109bb575080600201548160060154145b15610a0457816020015160025414610a045760405162461bcd60e51b8152600401808060200182810382526031815260200180610f096031913960400191505060405180910390fd5b60048101546005820154600683015460808501515167ffffffffffffffff9093169215610ae25767ffffffffffffffff8381161415610a745760405162461bcd60e51b8152600401808060200182810382526021815260200180610eb96021913960400191505060405180910390fd5b84604001518110610acc576040805162461bcd60e51b815260206004820152601960248201527f4f7665726c617070696e67207369676e616c7320666f756e6400000000000000604482015290519081900360640190fd5b5050825160608401516040850151600190930192015b939991985096509194509092505050565b600060608686868686604051602001808681526020018581526020018467ffffffffffffffff1667ffffffffffffffff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015610b66578181015183820152602001610b4e565b50505050905090810190601f168015610b935780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610bc6578181015183820152602001610bae565b50505050905090810190601f168015610bf35780820380516001836020036101000a031916815260200191505b50975050505050505050604051602081830303815290604052905080516020820160008083836012600019fa610c2857600080fd5b5095979650505050505050565b610c3d610d28565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa610c7257600080fd5b84519b5083519a508251995081519850805197505050505050505060608167ffffffffffffffff81118015610ca657600080fd5b506040519080825280601f01601f191660200182016040528015610cd1576020820181803683370190505b5090508115610cfb5787516020890160208301848184846011600019fa610cf757600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610d9e57805160ff1916838001178555610dcb565b82800160010185558215610dcb579182015b82811115610dcb578251825591602001919060010190610db0565b50610dd7929150610e50565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e145780548555610dcb565b82800160010185558215610dcb57600052602060002091601f016020900482015b82811115610dcb578254825591600101919060010190610e35565b610e6a91905b80821115610dd75760008155600101610e56565b9056fe547279696e6720746f20696d706f7274206e6f6e2d63616e6f6e6963616c206865616465724d697373696e6720706172656e74206865616465722066726f6d207468652073746f7261676552656163686564206d6178696d616c2076616c696461746f7273207365742069644d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f726167654d697373696e672072657175697265642066696e616c6974792070726f6f6620666f7220706172656e7420686561646572a2646970667358221220430a1b51f4ade85190a1817f6d8dfc5ffc46019627c95d768106e998f360e8be64736f6c63430006060033 \ No newline at end of file +60806040523480156200001157600080fd5b5060405162001af838038062001af8833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d5565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260078352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f9260038501929101906200040a565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d1919060208501906200040a565b5050505050620004af565b620002e6620003d5565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa6200031c57600080fd5b84519b5083519a50825199508151985080519750505050505050506060816001600160401b03811180156200035057600080fd5b506040519080825280601f01601f1916602001820160405280156200037c576020820181803683370190505b5090508115620003a85787516020890160208301848184846011600019fa620003a457600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044d57805160ff19168380011785556200047d565b828001600101855582156200047d579182015b828111156200047d57825182559160200191906001019062000460565b506200048b9291506200048f565b5090565b620004ac91905b808211156200048b576000815560010162000496565b90565b61163980620004bf6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063374c2c26146100675780636a742c0914610108578063871ebe181461033d578063d96a2deb1461036e578063e8ffbe841461038f578063fae71ae8146105d4575b600080fd5b61006f610684565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b357818101518382015260200161009b565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f25781810151838201526020016100da565b5050505090500194505050505060405180910390f35b61033b6004803603608081101561011e57600080fd5b810190602081018135600160201b81111561013857600080fd5b82018360208201111561014a57600080fd5b803590602001918460018302840111600160201b8311171561016b57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156101bd57600080fd5b8201836020820111156101cf57600080fd5b803590602001918460018302840111600160201b831117156101f057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561024257600080fd5b82018360208201111561025457600080fd5b803590602001918460018302840111600160201b8311171561027557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156102c757600080fd5b8201836020820111156102d957600080fd5b803590602001918460018302840111600160201b831117156102fa57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610789945050505050565b005b61035a6004803603602081101561035357600080fd5b50356107e5565b604080519115158252519081900360200190f35b6103766107fd565b6040805192835260208301919091528051918290030190f35b6105c2600480360360808110156103a557600080fd5b810190602081018135600160201b8111156103bf57600080fd5b8201836020820111156103d157600080fd5b803590602001918460018302840111600160201b831117156103f257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561044457600080fd5b82018360208201111561045657600080fd5b803590602001918460018302840111600160201b8311171561047757600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156104c957600080fd5b8201836020820111156104db57600080fd5b803590602001918460018302840111600160201b831117156104fc57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561054e57600080fd5b82018360208201111561056057600080fd5b803590602001918460018302840111600160201b8311171561058157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610815945050505050565b60408051918252519081900360200190f35b61033b600480360360608110156105ea57600080fd5b813591602081013591810190606081016040820135600160201b81111561061057600080fd5b82018360208201111561062257600080fd5b803590602001918460018302840111600160201b8311171561064357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610b28945050505050565b6005546060908190818167ffffffffffffffff811180156106a457600080fd5b506040519080825280602002602001820160405280156106ce578160200160208202803683370190505b50905060005b828110156107295760076000600583815481106106ed57fe5b906000526020600020015481526020019081526020016000206002015482828151811061071657fe5b60209081029190910101526001016106d4565b508060058080548060200260200160405190810160405280929190818152602001828054801561077857602002820191906000526020600020905b815481526020019060010190808311610764575b505050505090509350935050509091565b61079284610d8d565b61079b576107df565b8251156107b4576107ab83610d8d565b6107b4576107df565b8151156107cd576107c482610d8d565b6107cd576107df565b8051156107df576107dd81610d8d565b505b50505050565b60008181526007602052604090205460ff165b919050565b60008054808252600760205260409091206002015491565b600061081f611454565b61082886610f0e565b9050610832611489565b602082810151600090815260078252604090819020815160e081018352815460ff1615158152600180830154828601526002808401548386015260038401805486516101009482161594909402600019011691909104601f81018790048702830187019095528482529194929360608601939192918301828280156108f85780601f106108cd576101008083540402835291602001916108f8565b820191906000526020600020905b8154815290600101906020018083116108db57829003601f168201915b5050509183525050600482015467ffffffffffffffff1660208201526005820154604082015260069091015460609091015290506000806109398484611001565b945050505091506000600681111561094d57fe5b82600681111561095957fe5b146109ab576040805162461bcd60e51b815260206004820152601860248201527f43616e277420696d706f727420616e7920686561646572730000000000000000604482015290519081900360640190fd5b83604001518114156109c4576001945050505050610b20565b87516109d7576000945050505050610b20565b6109df611489565b6109e98585611171565b90506109f3611454565b6109fc8a610f0e565b90506000610a0a8284611001565b9450505050508160400151811415610a2c576002975050505050505050610b20565b8951610a42576000975050505050505050610b20565b610a4a611489565b610a548388611171565b9050610a5e611454565b610a678c610f0e565b90506000610a758284611001565b9450505050508160400151811415610a9a5760039a5050505050505050505050610b20565b8b51610ab35760009a5050505050505050505050610b20565b610abb611489565b610ac5838b611171565b9050610acf611454565b610ad88e610f0e565b90506000610ae68284611001565b9450505050508160400151811415610b0e5760049d5050505050505050505050505050610b20565b60009d50505050505050505050505050505b949350505050565b6000828152600760205260409020600201548314610b775760405162461bcd60e51b815260040180806020018281038252602f8152602001806115d5602f913960400191505060405180910390fd5b60028054600354600480546040805160206101006001851615026000190190931696909604601f81018390048302870183019091528086529394600094610c28948a948a9467ffffffffffffffff90921693929091830182828015610c1d5780601f10610bf257610100808354040283529160200191610c1d565b820191906000526020600020905b815481529060010190602001808311610c0057829003601f168201915b5050505050876111d0565b600081815260076020526040902060028281558101546001559091505b828214610d8557506000818152600760209081526040808320600181015460069093529220549092908015610d07576005546000199182019181018214610cd357600060056001830381548110610c9857fe5b906000526020600020015490508060058481548110610cb357fe5b600091825260208083209091019290925591825260069052604090208290555b6005805480610cde57fe5b600082815260208082208301600019908101839055909201909255848252600690526040812055505b826006015483600201541415610d7e57600583015460009081526007602052604090206003805467ffffffffffffffff198116600167ffffffffffffffff92831681019092161782559082018054610d759260049291600261010092821615929092026000190116046114c4565b50505050610d85565b5050610c45565b505050505050565b600080610d98611454565b6000806000610da687611312565b9398509196509450925090506000856006811115610dc057fe5b14610dd3576000955050505050506107f8565b604084015181148015610e27576005805486516001820180845560009384527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0909201558651825260066020526040909120555b6040805160e0810182526001808252602088810151818401908152898501518486019081526080808c01516060870190815267ffffffffffffffff8c169187019190915260a086018a905260c086018990528b51600090815260078552969096208551815460ff1916901515178155915193820193909355915160028301559251805192939192610ebe9260038501920190611549565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c090910151600690910155935160005550509015949350505050565b610f16611454565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa610f4b57600080fd5b84519b5083519a508251995081519850805197505050505050505060608167ffffffffffffffff81118015610f7f57600080fd5b506040519080825280601f01601f191660200182016040528015610faa576020820181803683370190505b5090508115610fd45787516020890160208301848184846011600019fa610fd057600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b600061100b611454565b83516000908152600760205260408120548190819060ff161561103d5750600193508592506000915081905080611167565b60015487604001511161105f5750600293508592506000915081905080611167565b8551158061107857506001876040015103866040015114155b156110925750600393508592506000915081905080611167565b60c0860151158015906110ac575085604001518660c00151145b156110d3578660200151600254146110d35750600493508592506000915081905080611167565b60808087015160a088015160c0890151928a01515191929091156111585767ffffffffffffffff838116141561111d57506005965088955060009450849350839250611167915050565b8960400151811061114257506006965088955060009450849350839250611167915050565b50508751606089015160408a0151600190930192015b60009750899650919450925090505b9295509295909350565b611179611489565b506040805160e08101825260018082528451602083015293820151909301908301526060818101519083015260808082015167ffffffffffffffff169083015260a0808201519083015260c0908101519082015290565b600060608686868686604051602001808681526020018581526020018467ffffffffffffffff1667ffffffffffffffff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561124357818101518382015260200161122b565b50505050905090810190601f1680156112705780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156112a357818101518382015260200161128b565b50505050905090810190601f1680156112d05780820380516001836020036101000a031916815260200191505b50975050505050505050604051602081830303815290604052905080516020820160008083836012600019fa61130557600080fd5b5095979650505050505050565b600061131c611454565b6000806000611329611454565b61133287610f0e565b905061133c611489565b602082810151600090815260078252604090819020815160e081018352815460ff1615158152600180830154828601526002808401548386015260038401805486516101009482161594909402600019011691909104601f81018790048702830187019095528482529194929360608601939192918301828280156114025780601f106113d757610100808354040283529160200191611402565b820191906000526020600020905b8154815290600101906020018083116113e557829003601f168201915b5050509183525050600482015467ffffffffffffffff1660208201526005820154604082015260069091015460609091015290506114408282611001565b939c929b5090995097509095509350505050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b6040805160e0810182526000808252602082018190529181018290526060808201526080810182905260a0810182905260c081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114fd5780548555611539565b8280016001018555821561153957600052602060002091601f016020900482015b8281111561153957825482559160010191906001019061151e565b506115459291506115b7565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061158a57805160ff1916838001178555611539565b82800160010185558215611539579182015b8281111561153957825182559160200191906001019061159c565b6115d191905b8082111561154557600081556001016115bd565b9056fe4d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f72616765a2646970667358221220edcaec08f93f74ce5be00b81da5d6b2276138571a33f1cfdca50e5047f854e6e64736f6c63430006060033 \ No newline at end of file diff --git a/relays/ethereum/res/substrate-bridge-metadata.txt b/relays/ethereum/res/substrate-bridge-metadata.txt index 60b8d022fc4b4..13b7daa9a8b8b 100644 --- a/relays/ethereum/res/substrate-bridge-metadata.txt +++ b/relays/ethereum/res/substrate-bridge-metadata.txt @@ -1,5 +1,5 @@ -Last Change Date: 2020-07-03 -Solc version: 0.6.6+commit.6c089d02 -Source hash (keccak256): 0x3e6339beefe6786f4f26b408d4f727e03c6fd9630d692af9a7f6b46143fa308f -Source gist: https://github.com/svyatonik/substrate-bridge-sol/blob/1d0fa475a2ba3a70a47ed2dd870568c42ec16c8c/substrate-bridge.sol +Last Change Date: 2020-07-30 +Solc version: 0.6.6+commit.6c089d02.Linux.g++ +Source hash (keccak256): 0xea5d6d744f69157adc2857166792aca139c0b5b186ba89c1011358fbcad90d7e +Source gist: https://github.com/svyatonik/substrate-bridge-sol/blob/6456d3e016c95cd5e6d5e817c23e9e69e739aa78/substrate-bridge.sol Compiler flags used (command to produce the file): `docker run -i ethereum/solc:0.6.6 --optimize --bin - < substrate-bridge.sol` \ No newline at end of file diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index b489cab522359..ae7e630c33553 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -32,12 +32,12 @@ use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use parity_crypto::publickey::KeyPair; -use std::collections::{HashSet, VecDeque}; +use std::collections::HashSet; // to encode/decode contract calls ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json"); -type Result = std::result::Result; +type RpcResult = std::result::Result; /// Ethereum connection params. #[derive(Debug, Clone)] @@ -104,15 +104,15 @@ impl EthereumRpcClient { #[async_trait] impl EthereumRpc for EthereumRpcClient { - async fn estimate_gas(&self, call_request: CallRequest) -> Result { + async fn estimate_gas(&self, call_request: CallRequest) -> RpcResult { Ok(Ethereum::estimate_gas(&self.client, call_request).await?) } - async fn best_block_number(&self) -> Result { + async fn best_block_number(&self) -> RpcResult { Ok(Ethereum::block_number(&self.client).await?.as_u64()) } - async fn header_by_number(&self, block_number: u64) -> Result
{ + async fn header_by_number(&self, block_number: u64) -> RpcResult
{ let get_full_tx_objects = false; let header = Ethereum::get_block_by_number(&self.client, block_number, get_full_tx_objects).await?; match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { @@ -121,7 +121,7 @@ impl EthereumRpc for EthereumRpcClient { } } - async fn header_by_hash(&self, hash: H256) -> Result
{ + async fn header_by_hash(&self, hash: H256) -> RpcResult
{ let get_full_tx_objects = false; let header = Ethereum::get_block_by_hash(&self.client, hash, get_full_tx_objects).await?; match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { @@ -130,7 +130,7 @@ impl EthereumRpc for EthereumRpcClient { } } - async fn header_by_number_with_transactions(&self, number: u64) -> Result { + async fn header_by_number_with_transactions(&self, number: u64) -> RpcResult { let get_full_tx_objects = true; let header = Ethereum::get_block_by_number_with_transactions(&self.client, number, get_full_tx_objects).await?; @@ -147,7 +147,7 @@ impl EthereumRpc for EthereumRpcClient { Ok(header) } - async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { + async fn header_by_hash_with_transactions(&self, hash: H256) -> RpcResult { let get_full_tx_objects = true; let header = Ethereum::get_block_by_hash_with_transactions(&self.client, hash, get_full_tx_objects).await?; @@ -164,24 +164,26 @@ impl EthereumRpc for EthereumRpcClient { Ok(header) } - async fn transaction_by_hash(&self, hash: H256) -> Result> { + async fn transaction_by_hash(&self, hash: H256) -> RpcResult> { Ok(Ethereum::transaction_by_hash(&self.client, hash).await?) } - async fn transaction_receipt(&self, transaction_hash: H256) -> Result { + async fn transaction_receipt(&self, transaction_hash: H256) -> RpcResult { Ok(Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?) } - async fn account_nonce(&self, address: Address) -> Result { + async fn account_nonce(&self, address: Address) -> RpcResult { Ok(Ethereum::get_transaction_count(&self.client, address).await?) } - async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result { + async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> RpcResult { let transaction = Bytes(signed_raw_tx); - Ok(Ethereum::submit_transaction(&self.client, transaction).await?) + let tx_hash = Ethereum::submit_transaction(&self.client, transaction).await?; + log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); + Ok(tx_hash) } - async fn eth_call(&self, call_transaction: CallRequest) -> Result { + async fn eth_call(&self, call_transaction: CallRequest) -> RpcResult { Ok(Ethereum::call(&self.client, call_transaction).await?) } } @@ -191,14 +193,14 @@ impl EthereumRpc for EthereumRpcClient { #[async_trait] pub trait EthereumHighLevelRpc: EthereumRpc { /// Returns best Substrate block that PoA chain knows of. - async fn best_substrate_block(&self, contract_address: Address) -> Result; + async fn best_substrate_block(&self, contract_address: Address) -> RpcResult; /// Returns true if Substrate header is known to Ethereum node. async fn substrate_header_known( &self, contract_address: Address, id: SubstrateHeaderId, - ) -> Result<(SubstrateHeaderId, bool)>; + ) -> RpcResult<(SubstrateHeaderId, bool)>; /// Submits Substrate headers to Ethereum contract. async fn submit_substrate_headers( @@ -209,7 +211,7 @@ pub trait EthereumHighLevelRpc: EthereumRpc { ) -> SubmittedHeaders; /// Returns ids of incomplete Substrate headers. - async fn incomplete_substrate_headers(&self, contract_address: Address) -> Result>; + async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult>; /// Complete Substrate header. async fn complete_substrate_header( @@ -218,7 +220,7 @@ pub trait EthereumHighLevelRpc: EthereumRpc { contract_address: Address, id: SubstrateHeaderId, justification: GrandpaJustification, - ) -> Result; + ) -> RpcResult; /// Submit ethereum transaction. async fn submit_ethereum_transaction( @@ -228,19 +230,19 @@ pub trait EthereumHighLevelRpc: EthereumRpc { nonce: Option, double_gas: bool, encoded_call: Vec, - ) -> Result<()>; + ) -> RpcResult<()>; /// Retrieve transactions receipts for given block. async fn transaction_receipts( &self, id: EthereumHeaderId, transactions: Vec, - ) -> Result<(EthereumHeaderId, Vec)>; + ) -> RpcResult<(EthereumHeaderId, Vec)>; } #[async_trait] impl EthereumHighLevelRpc for EthereumRpcClient { - async fn best_substrate_block(&self, contract_address: Address) -> Result { + async fn best_substrate_block(&self, contract_address: Address) -> RpcResult { let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); let call_request = CallRequest { to: Some(contract_address), @@ -263,7 +265,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { &self, contract_address: Address, id: SubstrateHeaderId, - ) -> Result<(SubstrateHeaderId, bool)> { + ) -> RpcResult<(SubstrateHeaderId, bool)> { let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1); let call_request = CallRequest { to: Some(contract_address), @@ -313,7 +315,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { .await } - async fn incomplete_substrate_headers(&self, contract_address: Address) -> Result> { + async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult> { let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); let call_request = CallRequest { to: Some(contract_address), @@ -346,7 +348,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { contract_address: Address, id: SubstrateHeaderId, justification: GrandpaJustification, - ) -> Result { + ) -> RpcResult { let _ = self .submit_ethereum_transaction( ¶ms, @@ -367,7 +369,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { nonce: Option, double_gas: bool, encoded_call: Vec, - ) -> Result<()> { + ) -> RpcResult<()> { let nonce = if let Some(n) = nonce { n } else { @@ -400,7 +402,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { &self, id: EthereumHeaderId, transactions: Vec, - ) -> Result<(EthereumHeaderId, Vec)> { + ) -> RpcResult<(EthereumHeaderId, Vec)> { let mut transaction_receipts = Vec::with_capacity(transactions.len()); for transaction in transactions { let transaction_receipt = self.transaction_receipt(transaction).await?; @@ -410,18 +412,115 @@ impl EthereumHighLevelRpc for EthereumRpcClient { } } +/// Max number of headers which can be sent to Solidity contract. +pub const HEADERS_BATCH: usize = 4; + +/// Substrate headers to send to the Ethereum light client. +/// +/// The Solidity contract can only accept a fixed number of headers in one go. +/// This struct is meant to encapsulate this limitation. +#[derive(Debug)] +#[cfg_attr(test, derive(Clone))] +pub struct HeadersBatch { + pub header1: QueuedSubstrateHeader, + pub header2: Option, + pub header3: Option, + pub header4: Option, +} + +impl HeadersBatch { + /// Create new headers from given header & ids collections. + /// + /// This method will pop `HEADERS_BATCH` items from both collections + /// and construct `Headers` object and a vector of `SubstrateheaderId`s. + pub fn pop_from( + headers: &mut Vec, + ids: &mut Vec, + ) -> Result<(Self, Vec), ()> { + if headers.len() != ids.len() { + log::error!(target: "bridge", "Collection size mismatch ({} vs {})", headers.len(), ids.len()); + return Err(()); + } + + let header1 = headers.pop().ok_or(())?; + let header2 = headers.pop(); + let header3 = headers.pop(); + let header4 = headers.pop(); + + let mut submitting_ids = Vec::with_capacity(HEADERS_BATCH); + for _ in 0..HEADERS_BATCH { + submitting_ids.extend(ids.pop().iter()); + } + + Ok(( + Self { + header1, + header2, + header3, + header4, + }, + submitting_ids, + )) + } + + /// Returns unified array of headers. + /// + /// The first element is always `Some`. + fn headers(&self) -> [Option<&QueuedSubstrateHeader>; HEADERS_BATCH] { + [ + Some(&self.header1), + self.header2.as_ref(), + self.header3.as_ref(), + self.header4.as_ref(), + ] + } + + /// Encodes all headers. If header is not present an empty vector will be returned. + pub fn encode(&self) -> [Vec; HEADERS_BATCH] { + let encode = |h: &QueuedSubstrateHeader| h.header().encode(); + let headers = self.headers(); + [ + headers[0].map(encode).unwrap_or_default(), + headers[1].map(encode).unwrap_or_default(), + headers[2].map(encode).unwrap_or_default(), + headers[3].map(encode).unwrap_or_default(), + ] + } + /// Returns number of contained headers. + pub fn len(&self) -> usize { + let is_set = |h: &Option<&QueuedSubstrateHeader>| if h.is_some() { 1 } else { 0 }; + self.headers().iter().map(is_set).sum() + } + + /// Remove headers starting from `idx` (0-based) from this collection. + /// + /// The collection will be left with `[0, idx)` headers. + /// Returns `Err` when `idx == 0`, since `Headers` must contain at least one header, + /// or when `idx > HEADERS_BATCH`. + pub fn split_off(&mut self, idx: usize) -> Result<(), ()> { + if idx == 0 || idx > HEADERS_BATCH { + return Err(()); + } + let mut vals: [_; HEADERS_BATCH] = [&mut None, &mut self.header2, &mut self.header3, &mut self.header4]; + for val in vals.iter_mut().skip(idx) { + **val = None; + } + Ok(()) + } +} + /// Substrate headers submitter API. #[async_trait] trait HeadersSubmitter { - /// Returns Ok(true) if not-yet-imported header is incomplete. - /// Returns Ok(false) if not-yet-imported header is complete. + /// Returns Ok(0) if all given not-yet-imported headers are complete. + /// Returns Ok(index != 0) where index is 1-based index of first header that is incomplete. /// - /// Returns Err(()) if contract has rejected header. This probably means - /// that the header is already imported by the contract. - async fn is_header_incomplete(&self, header: &QueuedSubstrateHeader) -> Result; + /// Returns Err(()) if contract has rejected headers. This means that the contract is + /// unable to import first header (e.g. it may already be imported). + async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult; - /// Submit given header to Ethereum node. - async fn submit_header(&mut self, header: QueuedSubstrateHeader) -> Result<()>; + /// Submit given headers to Ethereum node. + async fn submit_headers(&mut self, headers: HeadersBatch) -> RpcResult<()>; } /// Implementation of Substrate headers submitter that sends headers to running Ethereum node. @@ -434,9 +533,9 @@ struct EthereumHeadersSubmitter { #[async_trait] impl HeadersSubmitter for EthereumHeadersSubmitter { - async fn is_header_incomplete(&self, header: &QueuedSubstrateHeader) -> Result { - let (encoded_call, call_decoder) = - bridge_contract::functions::is_incomplete_header::call(header.header().encode()); + async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult { + let [h1, h2, h3, h4] = headers.encode(); + let (encoded_call, call_decoder) = bridge_contract::functions::is_incomplete_headers::call(h1, h2, h3, h4); let call_request = CallRequest { to: Some(self.contract_address), data: Some(encoded_call.into()), @@ -444,12 +543,16 @@ impl HeadersSubmitter for EthereumHeadersSubmitter { }; let call_result = self.client.eth_call(call_request).await?; - let is_incomplete = call_decoder.decode(&call_result.0)?; + let incomplete_index: U256 = call_decoder.decode(&call_result.0)?; + if incomplete_index > HEADERS_BATCH.into() { + return Err(RpcError::Ethereum(EthereumNodeError::InvalidIncompleteIndex)); + } - Ok(is_incomplete) + Ok(incomplete_index.low_u32() as _) } - async fn submit_header(&mut self, header: QueuedSubstrateHeader) -> Result<()> { + async fn submit_headers(&mut self, headers: HeadersBatch) -> RpcResult<()> { + let [h1, h2, h3, h4] = headers.encode(); let result = self .client .submit_ethereum_transaction( @@ -457,7 +560,7 @@ impl HeadersSubmitter for EthereumHeadersSubmitter { Some(self.contract_address), Some(self.nonce), false, - bridge_contract::functions::import_header::encode_input(header.header().encode()), + bridge_contract::functions::import_headers::encode_input(h1, h2, h3, h4), ) .await; @@ -472,16 +575,23 @@ impl HeadersSubmitter for EthereumHeadersSubmitter { /// Submit multiple Substrate headers. async fn submit_substrate_headers( mut header_submitter: impl HeadersSubmitter, - headers: Vec, + mut headers: Vec, ) -> SubmittedHeaders { - let mut ids = headers.iter().map(|header| header.id()).collect::>(); let mut submitted_headers = SubmittedHeaders::default(); - for header in headers { - let id = ids.pop_front().expect("both collections have same size; qed"); + + let mut ids = headers.iter().map(|header| header.id()).rev().collect::>(); + headers.reverse(); + + while !headers.is_empty() { + let (headers, submitting_ids) = + HeadersBatch::pop_from(&mut headers, &mut ids).expect("Headers and ids are not empty; qed"); + submitted_headers.fatal_error = - submit_substrate_header(&mut header_submitter, &mut submitted_headers, id, header).await; + submit_substrate_headers_batch(&mut header_submitter, &mut submitted_headers, submitting_ids, headers) + .await; if submitted_headers.fatal_error.is_some() { + ids.reverse(); submitted_headers.rejected.extend(ids); break; } @@ -490,28 +600,31 @@ async fn submit_substrate_headers( submitted_headers } -/// Submit single Substrate header. -async fn submit_substrate_header( +/// Submit 4 Substrate headers in single PoA transaction. +async fn submit_substrate_headers_batch( header_submitter: &mut impl HeadersSubmitter, submitted_headers: &mut SubmittedHeaders, - id: SubstrateHeaderId, - header: QueuedSubstrateHeader, + mut ids: Vec, + mut headers: HeadersBatch, ) -> Option { - // if parent of this header is either incomplete, or rejected, we assume that contract + debug_assert_eq!(ids.len(), headers.len(),); + + // if parent of first header is either incomplete, or rejected, we assume that contract // will reject this header as well - let parent_id = header.parent_id(); + let parent_id = headers.header1.parent_id(); if submitted_headers.rejected.contains(&parent_id) || submitted_headers.incomplete.contains(&parent_id) { - submitted_headers.rejected.push(id); + submitted_headers.rejected.extend(ids); return None; } - // check if this header is incomplete - let is_header_incomplete = match header_submitter.is_header_incomplete(&header).await { - Ok(true) => true, - Ok(false) => false, + // check if headers are incomplete + let incomplete_header_index = match header_submitter.is_headers_incomplete(&headers).await { + // All headers valid + Ok(0) => None, + Ok(incomplete_header_index) => Some(incomplete_header_index), Err(error) => { - // contract has rejected this header => we do not want to submit it - submitted_headers.rejected.push(id); + // contract has rejected all headers => we do not want to submit it + submitted_headers.rejected.extend(ids); if error.is_connection_error() { return Some(error); } else { @@ -520,17 +633,30 @@ async fn submit_substrate_header( } }; - // submit header and update submitted headers - match header_submitter.submit_header(header).await { + // Modify `ids` and `headers` to only contain values that are going to be accepted. + let rejected = if let Some(idx) = incomplete_header_index { + let len = std::cmp::min(idx, ids.len()); + headers + .split_off(len) + .expect("len > 0, the case where all headers are valid is converted to None; qed"); + ids.split_off(len) + } else { + Vec::new() + }; + let submitted = ids; + let submit_result = header_submitter.submit_headers(headers).await; + match submit_result { Ok(_) => { - submitted_headers.submitted.push(id); - if is_header_incomplete { - submitted_headers.incomplete.push(id); + if incomplete_header_index.is_some() { + submitted_headers.incomplete.extend(submitted.iter().last().cloned()); } + submitted_headers.submitted.extend(submitted); + submitted_headers.rejected.extend(rejected); None } Err(error) => { - submitted_headers.rejected.push(id); + submitted_headers.rejected.extend(submitted); + submitted_headers.rejected.extend(rejected); Some(error) } } @@ -549,16 +675,16 @@ mod tests { #[async_trait] impl HeadersSubmitter for TestHeadersSubmitter { - async fn is_header_incomplete(&self, header: &QueuedSubstrateHeader) -> Result { - if self.incomplete.iter().any(|i| i.0 == header.id().0) { - Ok(true) + async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult { + if self.incomplete.iter().any(|i| i.0 == headers.header1.id().0) { + Ok(1) } else { - Ok(false) + Ok(0) } } - async fn submit_header(&mut self, header: QueuedSubstrateHeader) -> Result<()> { - if self.failed.iter().any(|i| i.0 == header.id().0) { + async fn submit_headers(&mut self, headers: HeadersBatch) -> RpcResult<()> { + if self.failed.iter().any(|i| i.0 == headers.header1.id().0) { Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)) } else { Ok(()) @@ -600,13 +726,102 @@ mod tests { let submitted_headers = async_std::task::block_on(submit_substrate_headers( TestHeadersSubmitter { incomplete: vec![], - failed: vec![header(6).id()], + failed: vec![header(9).id()], }, - vec![header(5), header(6), header(7)], + vec![ + header(5), + header(6), + header(7), + header(8), + header(9), + header(10), + header(11), + ], )); - assert_eq!(submitted_headers.submitted, vec![header(5).id()]); + assert_eq!( + submitted_headers.submitted, + vec![header(5).id(), header(6).id(), header(7).id(), header(8).id()] + ); assert_eq!(submitted_headers.incomplete, vec![]); - assert_eq!(submitted_headers.rejected, vec![header(6).id(), header(7).id()]); + assert_eq!( + submitted_headers.rejected, + vec![header(9).id(), header(10).id(), header(11).id(),] + ); assert!(submitted_headers.fatal_error.is_some()); } + + fn headers_batch() -> HeadersBatch { + let mut init_headers = vec![header(1), header(2), header(3), header(4), header(5)]; + init_headers.reverse(); + let mut init_ids = init_headers.iter().map(|h| h.id()).collect(); + let (headers, ids) = HeadersBatch::pop_from(&mut init_headers, &mut init_ids).unwrap(); + assert_eq!(init_headers, vec![header(5)]); + assert_eq!(init_ids, vec![header(5).id()]); + assert_eq!( + ids, + vec![header(1).id(), header(2).id(), header(3).id(), header(4).id()] + ); + headers + } + + #[test] + fn headers_batch_len() { + let headers = headers_batch(); + assert_eq!(headers.len(), 4); + } + + #[test] + fn headers_batch_encode() { + let headers = headers_batch(); + assert_eq!( + headers.encode(), + [ + header(1).header().encode(), + header(2).header().encode(), + header(3).header().encode(), + header(4).header().encode(), + ] + ); + } + + #[test] + fn headers_batch_split_off() { + // given + let mut headers = headers_batch(); + + // when + assert!(headers.split_off(0).is_err()); + assert_eq!(headers.header1, header(1)); + assert!(headers.header2.is_some()); + assert!(headers.header3.is_some()); + assert!(headers.header4.is_some()); + + // when + let mut h = headers.clone(); + h.split_off(1).unwrap(); + assert!(h.header2.is_none()); + assert!(h.header3.is_none()); + assert!(h.header4.is_none()); + + // when + let mut h = headers.clone(); + h.split_off(2).unwrap(); + assert!(h.header2.is_some()); + assert!(h.header3.is_none()); + assert!(h.header4.is_none()); + + // when + let mut h = headers.clone(); + h.split_off(3).unwrap(); + assert!(h.header2.is_some()); + assert!(h.header3.is_some()); + assert!(h.header4.is_none()); + + // when + let mut h = headers; + h.split_off(4).unwrap(); + assert!(h.header2.is_some()); + assert!(h.header3.is_some()); + assert!(h.header4.is_some()); + } } diff --git a/relays/ethereum/src/exchange_loop.rs b/relays/ethereum/src/exchange_loop.rs index 4d9a031ec9f52..0da29d2324ed4 100644 --- a/relays/ethereum/src/exchange_loop.rs +++ b/relays/ethereum/src/exchange_loop.rs @@ -157,7 +157,7 @@ async fn run_loop_iteration( ) -> Result<(), ()> { let best_finalized_header_id = match target_client.best_finalized_header_id().await { Ok(best_finalized_header_id) => { - log::trace!( + log::debug!( target: "bridge", "Got best finalized {} block from {} node: {:?}", P::SOURCE_NAME, diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index aa3bcbde09dba..26206bdc1d6dc 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -100,6 +100,8 @@ pub enum EthereumNodeError { /// An invalid Substrate block number was received from /// an Ethereum node. InvalidSubstrateBlockNumber, + /// An invalid index has been received from an Ethereum node. + InvalidIncompleteIndex, } impl ToString for EthereumNodeError { @@ -112,6 +114,7 @@ impl ToString for EthereumNodeError { } Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), + Self::InvalidIncompleteIndex => "Received an invalid incomplete index from Ethereum Node".to_string(), } } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index f40d3a547254e..4970587d34fbc 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -39,7 +39,7 @@ const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoHeaderApi_finalized_block"; const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "RialtoCurrencyExchangeApi_filter_transaction_proof"; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; -type Result = std::result::Result; +type RpcResult = std::result::Result; type GrandpaAuthorityList = Vec; /// Substrate connection params. @@ -93,7 +93,7 @@ pub struct SubstrateRpcClient { impl SubstrateRpcClient { /// Returns client that is able to call RPCs on Substrate node. - pub async fn new(params: SubstrateConnectionParams, instance: Box) -> Result { + pub async fn new(params: SubstrateConnectionParams, instance: Box) -> RpcResult { let uri = format!("http://{}:{}", params.host, params.port); let transport = HttpTransportClient::new(&uri); let raw_client = RawClient::new(transport); @@ -112,32 +112,32 @@ impl SubstrateRpcClient { #[async_trait] impl SubstrateRpc for SubstrateRpcClient { - async fn best_header(&self) -> Result { + async fn best_header(&self) -> RpcResult { Ok(Substrate::chain_get_header(&self.client, None).await?) } - async fn get_block(&self, block_hash: Option) -> Result { + async fn get_block(&self, block_hash: Option) -> RpcResult { Ok(Substrate::chain_get_block(&self.client, block_hash).await?) } - async fn header_by_hash(&self, block_hash: Hash) -> Result { + async fn header_by_hash(&self, block_hash: Hash) -> RpcResult { Ok(Substrate::chain_get_header(&self.client, block_hash).await?) } - async fn block_hash_by_number(&self, number: Number) -> Result { + async fn block_hash_by_number(&self, number: Number) -> RpcResult { Ok(Substrate::chain_get_block_hash(&self.client, number).await?) } - async fn header_by_number(&self, block_number: Number) -> Result { + async fn header_by_number(&self, block_number: Number) -> RpcResult { let block_hash = Self::block_hash_by_number(self, block_number).await?; Ok(Self::header_by_hash(self, block_hash).await?) } - async fn next_account_index(&self, account: node_primitives::AccountId) -> Result { + async fn next_account_index(&self, account: node_primitives::AccountId) -> RpcResult { Ok(Substrate::system_account_next_index(&self.client, account).await?) } - async fn best_ethereum_block(&self) -> Result { + async fn best_ethereum_block(&self) -> RpcResult { let call = ETH_API_BEST_BLOCK.to_string(); let data = Bytes(Vec::new()); @@ -148,7 +148,7 @@ impl SubstrateRpc for SubstrateRpcClient { Ok(best_header_id) } - async fn best_ethereum_finalized_block(&self) -> Result { + async fn best_ethereum_finalized_block(&self) -> RpcResult { let call = ETH_API_BEST_FINALIZED_BLOCK.to_string(); let data = Bytes(Vec::new()); @@ -159,7 +159,7 @@ impl SubstrateRpc for SubstrateRpcClient { Ok(best_header_id) } - async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> Result { + async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult { let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); let data = Bytes(header.encode()); @@ -175,7 +175,7 @@ impl SubstrateRpc for SubstrateRpcClient { // But when we read the best header from Substrate next time, we will know that // there's a better header. This Orphan will either be marked as synced, or // eventually pruned. - async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> Result { + async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult { let call = ETH_API_IS_KNOWN_BLOCK.to_string(); let data = Bytes(header_id.1.encode()); @@ -185,11 +185,13 @@ impl SubstrateRpc for SubstrateRpcClient { Ok(is_known_block) } - async fn submit_extrinsic(&self, transaction: Bytes) -> Result { - Ok(Substrate::author_submit_extrinsic(&self.client, transaction).await?) + async fn submit_extrinsic(&self, transaction: Bytes) -> RpcResult { + let tx_hash = Substrate::author_submit_extrinsic(&self.client, transaction).await?; + log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); + Ok(tx_hash) } - async fn grandpa_authorities_set(&self, block: Hash) -> Result { + async fn grandpa_authorities_set(&self, block: Hash) -> RpcResult { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); @@ -312,13 +314,13 @@ pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { async fn verify_exchange_transaction_proof( &self, proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, - ) -> Result; + ) -> RpcResult; /// Submits Ethereum exchange transaction proof to Substrate runtime. async fn submit_exchange_transaction_proof( &self, params: SubstrateSigningParams, proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, - ) -> Result<()>; + ) -> RpcResult<()>; } #[async_trait] @@ -326,7 +328,7 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { async fn verify_exchange_transaction_proof( &self, proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, - ) -> Result { + ) -> RpcResult { let call = EXCH_API_FILTER_TRANSACTION_PROOF.to_string(); let data = Bytes(proof.encode()); @@ -340,7 +342,7 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { &self, params: SubstrateSigningParams, proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, - ) -> Result<()> { + ) -> RpcResult<()> { let account_id = params.signer.public().as_array_ref().clone().into(); let nonce = self.next_account_index(account_id).await?; diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 9ff7a0733f84b..2538b04c32bfc 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -91,6 +91,8 @@ pub struct HeadersSync { target_best_header: Option>, /// Headers queue. headers: QueuedHeaders

, + /// Pause headers submission. + pause_submit: bool, } impl HeadersSync

{ @@ -101,6 +103,7 @@ impl HeadersSync

{ params, source_best_number: None, target_best_header: None, + pause_submit: false, } } @@ -191,6 +194,11 @@ impl HeadersSync

{ /// Select headers that need to be submitted to the target node. pub fn select_headers_to_submit(&self, stalled: bool) -> Option>> { + // maybe we have paused new headers submit? + if self.pause_submit { + return None; + } + // if we operate in backup mode, we only submit headers when sync has stalled if self.params.target_tx_mode == TargetTransactionMode::Backup && !stalled { return None; @@ -260,14 +268,40 @@ impl HeadersSync

{ // finally remember the best header itself self.target_best_header = Some(best_header); + // we are ready to submit headers again + if self.pause_submit { + log::debug!( + target: "bridge", + "Ready to submit {} headers to {} node again!", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + + self.pause_submit = false; + } + true } + /// Pause headers submit until best header will be updated on target node. + pub fn pause_submit(&mut self) { + log::debug!( + target: "bridge", + "Stopping submitting {} headers to {} node. Waiting for {} submitted headers to be accepted", + P::SOURCE_NAME, + P::TARGET_NAME, + self.headers.headers_in_status(HeaderStatus::Submitted), + ); + + self.pause_submit = true; + } + /// Restart synchronization. pub fn restart(&mut self) { self.source_best_number = None; self.target_best_header = None; self.headers.clear(); + self.pause_submit = false; } } @@ -481,4 +515,35 @@ pub mod tests { // ensure that headers are not submitted when sync is stalled assert_eq!(eth_sync.select_headers_to_submit(true), Some(vec![&header(101)])); } + + #[test] + fn does_not_select_new_headers_to_submit_when_submit_is_paused() { + let mut eth_sync = HeadersSync::new(default_sync_params()); + eth_sync.params.max_headers_in_submitted_status = 1; + + // ethereum reports best header #102 and substrate is at #100 + eth_sync.source_best_header_number_response(102); + eth_sync.target_best_header_response(id(100)); + + // let's prepare #101 and #102 for submitting + eth_sync.headers.header_response(header(101).header().clone()); + eth_sync.headers.maybe_extra_response(&id(101), false); + eth_sync.headers.header_response(header(102).header().clone()); + eth_sync.headers.maybe_extra_response(&id(102), false); + + // when submit is not paused, we're ready to submit #101 + assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); + + // when submit is paused, we're not ready to submit anything + eth_sync.pause_submit(); + assert_eq!(eth_sync.select_headers_to_submit(false), None); + + // if best header on substrate node isn't updated, we still not submitting anything + eth_sync.target_best_header_response(id(100)); + assert_eq!(eth_sync.select_headers_to_submit(false), None); + + // but after it is actually updated, we are ready to submit + eth_sync.target_best_header_response(id(101)); + assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(102)])); + } } diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index a62c712f22000..12fdf0d01b5bf 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -266,8 +266,7 @@ pub fn run>( false => { log::info!( target: "bridge", - "Possible {} fork detected. Restarting {} headers synchronization.", - P::TARGET_NAME, + "Sync has stalled. Restarting {} headers synchronization.", P::SOURCE_NAME, ); stall_countdown = None; @@ -308,16 +307,21 @@ pub fn run>( // following line helps Rust understand the type of `submitted_headers` :/ let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; let submitted_headers_str = format!("{}", submitted_headers); + let all_headers_rejected = submitted_headers.submitted.is_empty() + && submitted_headers.incomplete.is_empty(); + let has_submitted_headers = sync.headers().headers_in_status(HeaderStatus::Submitted) != 0; + let maybe_fatal_error = match submitted_headers.fatal_error { Some(fatal_error) => Err(StringifiedMaybeConnectionError::new( fatal_error.is_connection_error(), format!("{:?}", fatal_error), )), - None if submitted_headers.submitted.is_empty() && submitted_headers.incomplete.is_empty() => + None if all_headers_rejected && !has_submitted_headers => Err(StringifiedMaybeConnectionError::new(false, "All headers were rejected".into())), None => Ok(()), }; + let no_fatal_error = maybe_fatal_error.is_ok(); target_client_is_online = process_future_result( maybe_fatal_error, &mut target_retry_backoff, @@ -331,6 +335,12 @@ pub fn run>( sync.headers_mut().headers_submitted(submitted_headers.submitted); sync.headers_mut().add_incomplete_headers(submitted_headers.incomplete); + + // when there's no fatal error, but node has rejected all our headers we may + // want to pause until our submitted headers will be accepted + if no_fatal_error && all_headers_rejected && has_submitted_headers { + sync.pause_submit(); + } }, target_complete_header_result = target_complete_header_future => { target_client_is_online = process_future_result( From 8e6dc045e51f38a85a16185bc6ba8f8f9d09b872 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 7 Aug 2020 10:23:40 -0400 Subject: [PATCH 0126/1210] Rename Primitive Crates (#271) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename Ethereum PoA primitives crate The "sp" prefix comes from Substrate primitives, since this crate originated in that repo. However, it is not part of Substrate anymore and its name should be updated to reflect that. * Rename currency exchange primitives * Rust Fmt * Update import in benchmarking module * Rust Fmt * Split pub and no-pub * Sort toml files. Co-authored-by: Tomasz Drwięga --- bin/node/node/Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 44 ++++++++++--------- bin/node/runtime/src/exchange.rs | 18 ++++---- bin/node/runtime/src/kovan.rs | 2 +- bin/node/runtime/src/lib.rs | 44 +++++++++---------- bin/node/runtime/src/rialto.rs | 2 +- modules/currency-exchange/Cargo.toml | 8 ++-- modules/currency-exchange/src/lib.rs | 14 +++--- modules/ethereum/Cargo.toml | 9 ++-- modules/ethereum/src/benchmarking.rs | 2 +- modules/ethereum/src/finality.rs | 2 +- modules/ethereum/src/import.rs | 2 +- modules/ethereum/src/lib.rs | 6 +-- modules/ethereum/src/mock.rs | 4 +- modules/ethereum/src/test_utils.rs | 10 ++--- modules/ethereum/src/validators.rs | 4 +- modules/ethereum/src/verification.rs | 6 +-- primitives/currency-exchange/Cargo.toml | 2 +- primitives/ethereum-poa/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 4 +- relays/ethereum/src/ethereum_exchange.rs | 4 +- .../ethereum/src/ethereum_exchange_submit.rs | 4 +- relays/ethereum/src/rpc.rs | 2 +- relays/ethereum/src/substrate_client.rs | 6 +-- relays/ethereum/src/substrate_types.rs | 3 +- 25 files changed, 104 insertions(+), 102 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index cea3b6915274c..3dbae3a36b05f 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -12,11 +12,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" name = "bridge-node" [dependencies] +bp-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.11" structopt = "0.3.15" -sp-bridge-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } [dependencies.bridge-node-runtime] version = "0.1.0" diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 205932ca04485..2e46acecaca49 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -123,16 +123,6 @@ tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" -[dependencies.sp-bridge-eth-poa] -version = "0.1.0" -default-features = false -path = "../../../primitives/ethereum-poa" - -[dependencies.sp-currency-exchange] -version = "0.1.0" -default-features = false -path = "../../../primitives/currency-exchange" - [dependencies.sp-consensus-aura] version = "0.8.0-rc5" tag = 'v2.0.0-rc5' @@ -206,12 +196,24 @@ tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" +[dependencies.bp-currency-exchange] +version = "0.1.0" +default-features = false +path = "../../../primitives/currency-exchange" + +[dependencies.bp-eth-poa] +version = "0.1.0" +default-features = false +path = "../../../primitives/ethereum-poa" + +# Dev Dependencies + [dev-dependencies.libsecp256k1] version = "0.3.4" default-features = false features = ["hmac"] -[dev-dependencies.sp-bridge-eth-poa] +[dev-dependencies.bp-eth-poa] version = "0.1.0" default-features = false features = ["std"] @@ -226,23 +228,26 @@ git = "https://github.com/paritytech/substrate/" [features] default = ["std"] std = [ - "pallet-aura/std", - "pallet-balances/std", - "pallet-bridge-eth-poa/std", - "pallet-bridge-currency-exchange/std", + "bp-currency-exchange/std", + "bp-eth-poa/std", "codec/std", "frame-benchmarking/std", "frame-executive/std", "frame-support/std", - "frame-system/std", "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-aura/std", + "pallet-balances/std", + "pallet-bridge-currency-exchange/std", + "pallet-bridge-eth-poa/std", "pallet-grandpa/std", "pallet-randomness-collective-flip/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment/std", "serde", "sp-api/std", "sp-block-builder/std", - "sp-bridge-eth-poa/std", - "sp-currency-exchange/std", "sp-consensus-aura/std", "sp-core/std", "sp-inherents/std", @@ -253,9 +258,6 @@ std = [ "sp-std/std", "sp-transaction-pool/std", "sp-version/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-transaction-payment/std", ] runtime-benchmarks = [ "frame-benchmarking", diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index 1048c661894d0..0812006ebd66a 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -27,13 +27,13 @@ //! to the PoA -> Substrate bridge module (it can be provided by you); //! 5) receive tokens by providing proof-of-inclusion of PoA transaction. +use bp_currency_exchange::{ + Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, +}; +use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use hex_literal::hex; -use sp_bridge_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; -use sp_currency_exchange::{ - Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, -}; use sp_std::vec::Vec; /// Ethereum address where locked PoA funds must be sent to. @@ -130,12 +130,12 @@ impl MaybeLockFundsTransaction for EthTransaction { #[cfg(feature = "runtime-benchmarks")] pub(crate) fn prepare_environment_for_claim, I: pallet_bridge_eth_poa::Instance>( transactions: &[(RawTransaction, RawTransactionReceipt)], -) -> sp_bridge_eth_poa::H256 { +) -> bp_eth_poa::H256 { + use bp_eth_poa::compute_merkle_root; use pallet_bridge_eth_poa::{ test_utils::{insert_header, validator_utils::validator, HeaderBuilder}, BridgeStorage, Storage, }; - use sp_bridge_eth_poa::compute_merkle_root; let mut storage = BridgeStorage::::new(); let header = HeaderBuilder::with_parent_number_on_runtime::(0) @@ -153,9 +153,9 @@ pub(crate) fn prepare_environment_for_claim, #[cfg(any(feature = "runtime-benchmarks", test))] pub(crate) fn prepare_ethereum_transaction( recipient: &crate::AccountId, - editor: impl Fn(&mut sp_bridge_eth_poa::UnsignedTransaction), + editor: impl Fn(&mut bp_eth_poa::UnsignedTransaction), ) -> (RawTransaction, RawTransactionReceipt) { - use sp_bridge_eth_poa::{signatures::SignTransaction, Receipt, TransactionOutcome}; + use bp_eth_poa::{signatures::SignTransaction, Receipt, TransactionOutcome}; // prepare tx for OpenEthereum private dev chain: // chain id is 0x11 @@ -166,7 +166,7 @@ pub(crate) fn prepare_ethereum_transaction( )) .unwrap(); let recipient_raw: &[u8; 32] = recipient.as_ref(); - let mut eth_tx = sp_bridge_eth_poa::UnsignedTransaction { + let mut eth_tx = bp_eth_poa::UnsignedTransaction { nonce: 0.into(), to: Some(LOCK_FUNDS_ADDRESS.into()), value: 100.into(), diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index 005aaa8f7b961..1855aa9dd3ea5 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -16,13 +16,13 @@ use crate::exchange::EthereumTransactionInclusionProof; +use bp_eth_poa::{Address, Header, RawTransaction, U256}; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; -use sp_bridge_eth_poa::{Address, Header, RawTransaction, U256}; use sp_std::prelude::*; frame_support::parameter_types! { diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 22abc50b6d298..2ea311289196f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -251,9 +251,9 @@ impl pallet_bridge_currency_exchange::Trait for Runtime type OnTransactionSubmitted = (); type PeerBlockchain = rialto::RialtoBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; - type RecipientsMap = sp_currency_exchange::IdentityRecipients; + type RecipientsMap = bp_currency_exchange::IdentityRecipients; type Amount = Balance; - type CurrencyConverter = sp_currency_exchange::IdentityCurrencyConverter; + type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter; type DepositInto = DepositInto; } @@ -262,19 +262,19 @@ impl pallet_bridge_currency_exchange::Trait for Runtime { type OnTransactionSubmitted = (); type PeerBlockchain = kovan::KovanBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; - type RecipientsMap = sp_currency_exchange::IdentityRecipients; + type RecipientsMap = bp_currency_exchange::IdentityRecipients; type Amount = Balance; - type CurrencyConverter = sp_currency_exchange::IdentityCurrencyConverter; + type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter; type DepositInto = DepositInto; } pub struct DepositInto; -impl sp_currency_exchange::DepositInto for DepositInto { +impl bp_currency_exchange::DepositInto for DepositInto { type Recipient = AccountId; type Amount = Balance; - fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { + fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> bp_currency_exchange::Result<()> { // let balances module make all checks for us (it won't allow depositing lower than existential // deposit, balance overflow, ...) let deposited = as Currency>::deposit_creating(&recipient, amount); @@ -307,7 +307,7 @@ impl sp_currency_exchange::DepositInto for DepositInto { recipient, ); - Err(sp_currency_exchange::Error::DepositFailed) + Err(bp_currency_exchange::Error::DepositFailed) } _ => { frame_support::debug::error!( @@ -319,7 +319,7 @@ impl sp_currency_exchange::DepositInto for DepositInto { ); // we can't return DepositFailed error here, because storage changes were made - Err(sp_currency_exchange::Error::DepositPartiallyFailed) + Err(bp_currency_exchange::Error::DepositPartiallyFailed) } } } @@ -557,53 +557,53 @@ impl_runtime_apis! { } } - impl sp_bridge_eth_poa::RialtoHeaderApi for Runtime { - fn best_block() -> (u64, sp_bridge_eth_poa::H256) { + impl bp_eth_poa::RialtoHeaderApi for Runtime { + fn best_block() -> (u64, bp_eth_poa::H256) { let best_block = BridgeRialto::best_block(); (best_block.number, best_block.hash) } - fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { + fn finalized_block() -> (u64, bp_eth_poa::H256) { let finalized_block = BridgeRialto::finalized_block(); (finalized_block.number, finalized_block.hash) } - fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { + fn is_import_requires_receipts(header: bp_eth_poa::Header) -> bool { BridgeRialto::is_import_requires_receipts(header) } - fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { + fn is_known_block(hash: bp_eth_poa::H256) -> bool { BridgeRialto::is_known_block(hash) } } - impl sp_bridge_eth_poa::KovanHeaderApi for Runtime { - fn best_block() -> (u64, sp_bridge_eth_poa::H256) { + impl bp_eth_poa::KovanHeaderApi for Runtime { + fn best_block() -> (u64, bp_eth_poa::H256) { let best_block = BridgeKovan::best_block(); (best_block.number, best_block.hash) } - fn finalized_block() -> (u64, sp_bridge_eth_poa::H256) { + fn finalized_block() -> (u64, bp_eth_poa::H256) { let finalized_block = BridgeKovan::finalized_block(); (finalized_block.number, finalized_block.hash) } - fn is_import_requires_receipts(header: sp_bridge_eth_poa::Header) -> bool { + fn is_import_requires_receipts(header: bp_eth_poa::Header) -> bool { BridgeKovan::is_import_requires_receipts(header) } - fn is_known_block(hash: sp_bridge_eth_poa::H256) -> bool { + fn is_known_block(hash: bp_eth_poa::H256) -> bool { BridgeKovan::is_known_block(hash) } } - impl sp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { + impl bp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) } } - impl sp_currency_exchange::KovanCurrencyExchangeApi for Runtime { + impl bp_currency_exchange::KovanCurrencyExchangeApi for Runtime { fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { BridgeKovanCurrencyExchange::filter_transaction_proof(&proof) } @@ -714,7 +714,7 @@ impl_runtime_apis! { fn make_proof( proof_params: BridgeCurrencyExchangeProofParams, ) -> crate::exchange::EthereumTransactionInclusionProof { - use sp_currency_exchange::DepositInto; + use bp_currency_exchange::DepositInto; if proof_params.recipient_exists { >::DepositInto::deposit_into( @@ -761,7 +761,7 @@ impl_runtime_apis! { #[cfg(test)] mod tests { use super::*; - use sp_currency_exchange::DepositInto; + use bp_currency_exchange::DepositInto; #[test] fn shift_session_manager_works() { diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs index 1a46fae0b5303..800b0ab1c86c8 100644 --- a/bin/node/runtime/src/rialto.rs +++ b/bin/node/runtime/src/rialto.rs @@ -16,13 +16,13 @@ use crate::exchange::EthereumTransactionInclusionProof; +use bp_eth_poa::{Address, Header, RawTransaction, U256}; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; -use sp_bridge_eth_poa::{Address, Header, RawTransaction, U256}; use sp_std::prelude::*; frame_support::parameter_types! { diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 4c8116aca895f..03b3d692a3fac 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -serde = { version = "1.0", optional = true } +bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -sp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } +serde = { version = "1.0", optional = true } # Substrate Based Dependencies [dependencies.frame-support] @@ -56,13 +56,13 @@ git = "https://github.com/paritytech/substrate/" [features] default = ["std"] std = [ + "bp-currency-exchange/std", "codec/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", "serde", - "sp-currency-exchange/std", - "sp-std/std", "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = ["frame-benchmarking"] diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 29ba94631e564..a7c3c5026a2e8 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -18,10 +18,10 @@ #![cfg_attr(not(feature = "std"), no_std)] -use frame_support::{decl_error, decl_module, decl_storage, ensure, Parameter}; -use sp_currency_exchange::{ +use bp_currency_exchange::{ CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, }; +use frame_support::{decl_error, decl_module, decl_storage, ensure, Parameter}; use sp_runtime::DispatchResult; #[cfg(feature = "runtime-benchmarks")] @@ -221,9 +221,9 @@ fn prepare_deposit_details, I: Instance>( #[cfg(test)] mod tests { use super::*; + use bp_currency_exchange::LockFundsTransaction; use frame_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types, weights::Weight}; use sp_core::H256; - use sp_currency_exchange::LockFundsTransaction; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, @@ -272,7 +272,7 @@ mod tests { type Recipient = AccountId; type Amount = u64; - fn parse(tx: &Self::Transaction) -> sp_currency_exchange::Result { + fn parse(tx: &Self::Transaction) -> bp_currency_exchange::Result { match tx.id { INVALID_TRANSACTION_ID => Err(ExchangeError::InvalidTransaction), _ => Ok(tx.clone()), @@ -286,7 +286,7 @@ mod tests { type PeerRecipient = AccountId; type Recipient = AccountId; - fn map(peer_recipient: Self::PeerRecipient) -> sp_currency_exchange::Result { + fn map(peer_recipient: Self::PeerRecipient) -> bp_currency_exchange::Result { match peer_recipient { UNKNOWN_RECIPIENT_ID => Err(ExchangeError::FailedToMapRecipients), _ => Ok(peer_recipient * 10), @@ -300,7 +300,7 @@ mod tests { type SourceAmount = u64; type TargetAmount = u64; - fn convert(amount: Self::SourceAmount) -> sp_currency_exchange::Result { + fn convert(amount: Self::SourceAmount) -> bp_currency_exchange::Result { match amount { INVALID_AMOUNT => Err(ExchangeError::FailedToConvertCurrency), _ => Ok(amount * 10), @@ -314,7 +314,7 @@ mod tests { type Recipient = AccountId; type Amount = u64; - fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> sp_currency_exchange::Result<()> { + fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> bp_currency_exchange::Result<()> { match amount { amount if amount < MAX_DEPOSIT_AMOUNT * 10 => Ok(()), amount if amount == MAX_DEPOSIT_AMOUNT * 10 => Err(ExchangeError::DepositPartiallyFailed), diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index d2b17e0f63291..bde8f95456d94 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -7,10 +7,10 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -serde = { version = "1.0", optional = true } +bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } hex-literal = "0.3" -primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", default-features = false } +serde = { version = "1.0", optional = true } # Substrate Based Dependencies [dependencies.frame-support] @@ -58,18 +58,17 @@ features = ["hmac"] # Dev Dependencies [dev-dependencies] -# TODO: Stop renaming this on import -primitives = { package = "sp-bridge-eth-poa", path = "../../primitives/ethereum-poa", features = ["std"] } +bp-eth-poa = { path = "../../primitives/ethereum-poa", features = ["std"] } libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [features] default = ["std"] std = [ + "bp-eth-poa/std", "codec/std", "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "primitives/std", "serde", "sp-io/std", "sp-runtime/std", diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 1da7019c6408f..b088c49bec812 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -21,9 +21,9 @@ use crate::test_utils::{ HeaderBuilder, }; +use bp_eth_poa::{compute_merkle_root, U256}; use frame_benchmarking::benchmarks_instance; use frame_system::RawOrigin; -use primitives::{compute_merkle_root, U256}; benchmarks_instance! { _ { } diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index c847e77704799..4d836cd8a5224 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -16,8 +16,8 @@ use crate::error::Error; use crate::Storage; +use bp_eth_poa::{public_to_address, Address, Header, HeaderId, SealedEmptyStep, H256}; use codec::{Decode, Encode}; -use primitives::{public_to_address, Address, Header, HeaderId, SealedEmptyStep, H256}; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_runtime::RuntimeDebug; use sp_std::collections::{ diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 20c86cf6eb8b1..97f423b2d9296 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -19,7 +19,7 @@ use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::{is_importable_header, verify_aura_header}; use crate::{AuraConfiguration, ChangeToEnact, PruningStrategy, Storage}; -use primitives::{Header, HeaderId, Receipt}; +use bp_eth_poa::{Header, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// Imports bunch of headers and updates blocks finality. diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index cb8305543d6be..bbb2ba2956197 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -19,9 +19,9 @@ #![allow(clippy::large_enum_variant)] use crate::finality::{CachedFinalityVotes, FinalityVotes}; +use bp_eth_poa::{Address, Header, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage, traits::Get}; -use primitives::{Address, Header, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; use sp_runtime::{ transaction_validity::{ InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity, @@ -1025,7 +1025,7 @@ pub(crate) mod tests { genesis, insert_header, run_test, run_test_with_genesis, validators_addresses, HeaderBuilder, TestRuntime, GAS_LIMIT, }; - use primitives::compute_merkle_root; + use bp_eth_poa::compute_merkle_root; const TOTAL_VALIDATORS: usize = 3; @@ -1036,7 +1036,7 @@ pub(crate) mod tests { fn example_tx_receipt(success: bool) -> Vec { Receipt { // the only thing that we care of: - outcome: primitives::TransactionOutcome::StatusCode(if success { 1 } else { 0 }), + outcome: bp_eth_poa::TransactionOutcome::StatusCode(if success { 1 } else { 0 }), gas_used: Default::default(), log_bloom: Default::default(), logs: Vec::new(), diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index be173512a723f..66d63d28d0911 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -15,12 +15,12 @@ // along with Parity Bridges Common. If not, see . pub use crate::test_utils::{insert_header, validator_utils::*, validators_change_receipt, HeaderBuilder, GAS_LIMIT}; -pub use primitives::signatures::secret_to_address; +pub use bp_eth_poa::signatures::secret_to_address; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; use crate::{AuraConfiguration, GenesisConfig, PruningStrategy, Trait}; +use bp_eth_poa::{Address, Header, H256, U256}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; -use primitives::{Address, Header, H256, U256}; use secp256k1::SecretKey; use sp_runtime::{ testing::Header as SubstrateHeader, diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 035882450fbb5..37f7a7a0298b5 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -29,7 +29,7 @@ use crate::validators::CHANGE_EVENT_HASH; use crate::verification::calculate_score; use crate::{HeaderToImport, Storage, Trait}; -use primitives::{ +use bp_eth_poa::{ rlp_encode, signatures::{secret_to_address, sign, SignHeader}, Address, Bloom, Header, Receipt, SealedEmptyStep, H256, U256, @@ -53,7 +53,7 @@ impl HeaderBuilder { Self { header: Header { gas_limit: GAS_LIMIT.into(), - seal: vec![primitives::rlp_encode(¤t_step), vec![]], + seal: vec![bp_eth_poa::rlp_encode(¤t_step), vec![]], ..Default::default() }, parent_header: Default::default(), @@ -95,7 +95,7 @@ impl HeaderBuilder { pub fn with_number(number: u64) -> Self { Self::with_parent(&Header { number: number - 1, - seal: vec![primitives::rlp_encode(&(number - 1)), vec![]], + seal: vec![bp_eth_poa::rlp_encode(&(number - 1)), vec![]], ..Default::default() }) } @@ -109,7 +109,7 @@ impl HeaderBuilder { parent_hash: parent_header.compute_hash(), number: parent_header.number + 1, gas_limit: GAS_LIMIT.into(), - seal: vec![primitives::rlp_encode(¤t_step), vec![]], + seal: vec![bp_eth_poa::rlp_encode(¤t_step), vec![]], difficulty: calculate_score(parent_step, current_step, 0), ..Default::default() }, @@ -242,7 +242,7 @@ pub fn insert_header(storage: &mut S, header: Header) { } pub fn validators_change_receipt(parent_hash: H256) -> Receipt { - use primitives::{LogEntry, TransactionOutcome}; + use bp_eth_poa::{LogEntry, TransactionOutcome}; Receipt { gas_used: 0.into(), diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 8253ab2def693..e0b747fc3f029 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -16,7 +16,7 @@ use crate::error::Error; use crate::{ChangeToEnact, Storage}; -use primitives::{Address, Header, HeaderId, LogEntry, Receipt, U256}; +use bp_eth_poa::{Address, Header, HeaderId, LogEntry, Receipt, U256}; use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. @@ -278,8 +278,8 @@ pub(crate) mod tests { use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}; use crate::DefaultInstance; use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader}; + use bp_eth_poa::compute_merkle_root; use frame_support::StorageMap; - use primitives::compute_merkle_root; const TOTAL_VALIDATORS: usize = 3; diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 8e028edbbc86f..ea5a208b40906 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -17,10 +17,10 @@ use crate::error::Error; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::{AuraConfiguration, ImportContext, PoolConfiguration, ScheduledChange, Storage}; -use codec::Encode; -use primitives::{ +use bp_eth_poa::{ public_to_address, step_validator, Address, Header, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, }; +use codec::Encode; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_runtime::transaction_validity::TransactionTag; use sp_std::{vec, vec::Vec}; @@ -366,8 +366,8 @@ mod tests { pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, ScheduledChanges, ValidatorsSet, ValidatorsSets, }; + use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520}; use frame_support::{StorageMap, StorageValue}; - use primitives::{compute_merkle_root, rlp_encode, TransactionOutcome, H520}; use secp256k1::SecretKey; use sp_runtime::transaction_validity::TransactionTag; diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 91052ca850975..ff2c98c11870d 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sp-currency-exchange" +name = "bp-currency-exchange" description = "Primitives of currency exchange module." version = "0.1.0" authors = ["Parity Technologies "] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index d77efda8a3d31..9beb08892e95c 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "sp-bridge-eth-poa" +name = "bp-eth-poa" description = "Primitives of Ethereum PoA Bridge module." version = "0.1.0" authors = ["Parity Technologies "] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index e57a885d9d4fc..922d6a2f85896 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -11,6 +11,8 @@ async-std = "1.6.2" async-stream = "0.2.0" async-trait = "0.1.36" backoff = "0.2" +bp-currency-exchange = { path = "../../primitives/currency-exchange" } +bp-eth-poa = { path = "../../primitives/ethereum-poa" } clap = { version = "2.33.1", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.1" } env_logger = "0.7.0" @@ -30,8 +32,6 @@ rustc-hex = "2.0.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" sysinfo = "0.15" -sp-currency-exchange = { path = "../../primitives/currency-exchange" } -sp-bridge-eth-poa = { path = "../../primitives/ethereum-poa" } time = "0.2" web3 = "0.13" diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index d094d9bae39c3..bcaebdd9c5179 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -37,8 +37,8 @@ use crate::substrate_types::into_substrate_ethereum_receipt; use crate::sync_types::HeaderId; use async_trait::async_trait; +use bp_currency_exchange::MaybeLockFundsTransaction; use bridge_node_runtime::exchange::EthereumTransactionInclusionProof; -use sp_currency_exchange::MaybeLockFundsTransaction; use std::time::Duration; /// Interval at which we ask Ethereum node for updates. @@ -240,7 +240,7 @@ impl TargetClient for SubstrateTransactionsTarget { } // now let's check if transaction is successful - match sp_bridge_eth_poa::Receipt::is_successful_raw_receipt(raw_tx_receipt) { + match bp_eth_poa::Receipt::is_successful_raw_receipt(raw_tx_receipt) { Ok(true) => (), _ => return Ok(false), } diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index 96a0fc68d0f64..69a4d7a39b7f2 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -20,11 +20,11 @@ use crate::ethereum_client::{EthereumConnectionParams, EthereumRpcClient, Ethere use crate::ethereum_types::{CallRequest, U256}; use crate::rpc::EthereumRpc; -use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS; -use sp_bridge_eth_poa::{ +use bp_eth_poa::{ signatures::{SecretKey, SignTransaction}, UnsignedTransaction, }; +use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS; /// Ethereum exchange transaction params. #[derive(Debug)] diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs index 5fc73ed02eaeb..fd108f8963fef 100644 --- a/relays/ethereum/src/rpc.rs +++ b/relays/ethereum/src/rpc.rs @@ -35,7 +35,7 @@ use crate::substrate_types::{ }; use async_trait::async_trait; -use sp_bridge_eth_poa::Header as SubstrateEthereumHeader; +use bp_eth_poa::Header as SubstrateEthereumHeader; type Result = result::Result; type GrandpaAuthorityList = Vec; diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 4970587d34fbc..c2bc56ac26992 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -22,12 +22,12 @@ use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBloc use crate::sync_types::{HeaderId, SubmittedHeaders}; use async_trait::async_trait; +use bp_eth_poa::Header as SubstrateEthereumHeader; use codec::{Decode, Encode}; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use num_traits::Zero; -use sp_bridge_eth_poa::Header as SubstrateEthereumHeader; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; use std::collections::VecDeque; @@ -142,7 +142,7 @@ impl SubstrateRpc for SubstrateRpcClient { let data = Bytes(Vec::new()); let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; let best_header_id = HeaderId(decoded_response.0, decoded_response.1); Ok(best_header_id) @@ -153,7 +153,7 @@ impl SubstrateRpc for SubstrateRpcClient { let data = Bytes(Vec::new()); let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let decoded_response: (u64, sp_bridge_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; let best_header_id = HeaderId(decoded_response.0, decoded_response.1); Ok(best_header_id) diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 9e5ce6b732c73..d03e8a86fdafa 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -19,7 +19,8 @@ use crate::ethereum_types::{ }; use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; use codec::Encode; -pub use sp_bridge_eth_poa::{ + +pub use bp_eth_poa::{ Address, Bloom, Bytes, Header as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, }; From cb247ed679f3903e5f7c1381d3722db750bc2d85 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 7 Aug 2020 17:52:56 -0400 Subject: [PATCH 0127/1210] Fix panic when no instance is passed to certain CLI options (#275) --- relays/ethereum/src/cli.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 0fbf866166d55..35c8c2e6eb3f9 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -85,6 +85,7 @@ subcommands: help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. - sub-host: *sub-host - sub-port: *sub-port + - sub-pallet-instance: *sub-pallet-instance - no-prometheus: *no-prometheus - prometheus-host: *prometheus-host - prometheus-port: *prometheus-port @@ -102,6 +103,7 @@ subcommands: takes_value: true - sub-host: *sub-host - sub-port: *sub-port + - sub-pallet-instance: *sub-pallet-instance - sub-authorities-set-id: long: sub-authorities-set-id value_name: SUB_AUTHORITIES_SET_ID @@ -160,6 +162,7 @@ subcommands: - sub-port: *sub-port - sub-signer: *sub-signer - sub-signer-password: *sub-signer-password + - sub-pallet-instance: *sub-pallet-instance - no-prometheus: *no-prometheus - prometheus-host: *prometheus-host - prometheus-port: *prometheus-port From 0854274d02f6256e71c3fac20ec28edac27d5e9d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2020 02:22:32 +0000 Subject: [PATCH 0128/1210] Bump structopt from 0.3.15 to 0.3.16 (#277) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 3dbae3a36b05f..ab7db6f9d01ed 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -16,7 +16,7 @@ bp-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.11" -structopt = "0.3.15" +structopt = "0.3.16" [dependencies.bridge-node-runtime] version = "0.1.0" From 5fd93dc86f2e0c5d3c7e580e11faf65c30bac3f0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2020 02:23:55 +0000 Subject: [PATCH 0129/1210] Bump async-stream from 0.2.1 to 0.3.0 (#278) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 922d6a2f85896..eee8701af46f3 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" async-std = "1.6.2" -async-stream = "0.2.0" +async-stream = "0.3.0" async-trait = "0.1.36" backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } From 1dc492190df6d117c1c8da6ea015d4b510ad8d94 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2020 03:27:59 +0000 Subject: [PATCH 0130/1210] Bump clap from 2.33.1 to 2.33.2 (#279) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index eee8701af46f3..7712ca5ea407e 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1.36" backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } -clap = { version = "2.33.1", features = ["yaml"] } +clap = { version = "2.33.2", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.1" } env_logger = "0.7.0" ethabi = "12.0" From 93d18187cd2e5a341206556f75287a2dbb23d616 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 10 Aug 2020 17:54:43 -0400 Subject: [PATCH 0131/1210] Add instructions and scripts for local development (#280) * Add dev deployment profile with Ethereum PoA config * Add scripts for running local components * Use `openethereum` folder * Add local development instructions in README * Add note about clone location * Point to right folder for scripts * Add some missing back-ticks * Remove Bertha and Carlos as authorities * Fix a line length issue --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/README.md b/README.md index 3906389c51448..d46332dacb518 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,54 @@ To run the Bridge you need to be able to connect the bridge relay node to the RP on each side of the bridge (home & foreign chain). An easy way to build all the required nodes is through Docker. +### Local Development Build + +#### Building + +First you'll need to build the bridge node and relay. This can be done as follows: + +```bash +# In `parity-bridges-common` folder +cargo build -p bridge-node +cargo build -p ethereum-poa-relay +``` + +Next you'll need to clone the following [fork of OpenEthereum](https://github.com/HCastano/parity-ethereum). +If you're doing development which only involves the Ethereum to Substrate side of the bridge you may +use the `master` branch. Otherwise you'll need to checkout the `substrate-builtins-stubs` branch. + +```bash +# Should be at the same level as `parity-bridges-common` folder +git clone https://github.com/HCastano/parity-ethereum.git openethereum +git fetch +git checkout substrate-builtins-stubs +``` + +If you've checked out the `substrate-builtins-stubs` branch make sure you've cloned the OpenEthereum +repo at the same level as `parity-bridges-common` since it references the repo. + +Next you'll need to build the Ethereum node: + +```bash +# In `openethereum` folder +cargo build +``` + +#### Running + +To run a simple dev network you'll can use the scripts located in +[the `scripts` folder](./scripts). Since the relay connects to both the Substrate and Ethereum +chains it must be run last. + +```bash +# In `parity-bridges-common` folder +./scripts/run-openethereum-node.sh +./scripts/run-bridge-node.sh +./scripts/run-eth2sub-relay.sh +``` +At this point you should see the relayer submitting blocks from the Ethereum chain +to the Substrate chain. + ### Local Docker Build If you want to make a Docker container using your local source files you can run the following command at the top level of the repository: From 89c99fd6f5e9b8971a4ac6f61a3965a07a2cfbae Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2020 02:24:36 +0000 Subject: [PATCH 0132/1210] Bump async-trait from 0.1.36 to 0.1.37 (#283) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 7712ca5ea407e..8655d8735214e 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" ansi_term = "0.12" async-std = "1.6.2" async-stream = "0.3.0" -async-trait = "0.1.36" +async-trait = "0.1.37" backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } From 5c0b3722eba6d55efe06809673e3d237b8e5e76d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2020 02:24:50 +0000 Subject: [PATCH 0133/1210] Bump serde from 1.0.114 to 1.0.115 (#282) --- bin/node/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 2e46acecaca49..09e58047bd3f9 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -23,7 +23,7 @@ default-features = false features = ["hmac"] [dependencies.serde] -version = "1.0.114" +version = "1.0.115" optional = true features = ["derive"] From 5281adb86080c12b14f8cc398f074c3f41dbdeee Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 17 Aug 2020 03:18:29 +0000 Subject: [PATCH 0134/1210] Bump clap from 2.33.2 to 2.33.3 (#284) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8655d8735214e..856c10788b2ab 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1.37" backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } -clap = { version = "2.33.2", features = ["yaml"] } +clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.1" } env_logger = "0.7.0" ethabi = "12.0" From 7ef64a60c8c21de220c46b37fd868a2f65866010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 18 Aug 2020 18:34:31 +0200 Subject: [PATCH 0135/1210] Update open ethereum. (#290) * Update open ethereum. * Remove extra line break. * Remove branch comment. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d46332dacb518..1f426a860716a 100644 --- a/README.md +++ b/README.md @@ -174,13 +174,13 @@ cargo build -p bridge-node cargo build -p ethereum-poa-relay ``` -Next you'll need to clone the following [fork of OpenEthereum](https://github.com/HCastano/parity-ethereum). +Next you'll need to clone the following [fork of OpenEthereum](https://github.com/paritytech/openethereum). If you're doing development which only involves the Ethereum to Substrate side of the bridge you may use the `master` branch. Otherwise you'll need to checkout the `substrate-builtins-stubs` branch. ```bash # Should be at the same level as `parity-bridges-common` folder -git clone https://github.com/HCastano/parity-ethereum.git openethereum +git clone https://github.com/paritytech/openethereum.git openethereum git fetch git checkout substrate-builtins-stubs ``` From af88c243710c4333e72e62cfd2d9572e37b2cedf Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 18 Aug 2020 19:39:18 +0300 Subject: [PATCH 0136/1210] Parse all deploy contract arguments (#289) * parse all deploy contract arguments * cargo fmt --all --- relays/ethereum/src/main.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 5a1cf23ab1461..a842c2b559b4f 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -272,20 +272,28 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result Result { - let eth_contract_code = if let Some(eth_contract_code) = matches.value_of("eth-contract-code") { - hex::decode(ð_contract_code).map_err(|e| format!("Failed to parse eth-contract-code: {}", e))? - } else { + let eth_contract_code = parse_hex_argument(matches, "eth-contract-code")?.unwrap_or_else(|| { hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")).expect("code is hardcoded, thus valid; qed") + }); + let sub_initial_authorities_set_id = match matches.value_of("sub-authorities-set-id") { + Some(sub_initial_authorities_set_id) => Some( + sub_initial_authorities_set_id + .parse() + .map_err(|e| format!("Failed to parse sub-authorities-set-id: {}", e))?, + ), + None => None, }; + let sub_initial_authorities_set = parse_hex_argument(matches, "sub-authorities-set")?; + let sub_initial_header = parse_hex_argument(matches, "sub-initial-header")?; let params = EthereumDeployContractParams { eth_params: ethereum_connection_params(matches)?, eth_sign: ethereum_signing_params(matches)?, sub_params: substrate_connection_params(matches)?, instance: instance_params(matches)?, - sub_initial_authorities_set_id: None, - sub_initial_authorities_set: None, - sub_initial_header: None, + sub_initial_authorities_set_id, + sub_initial_authorities_set, + sub_initial_header, eth_contract_code, }; @@ -407,3 +415,12 @@ fn instance_params(matches: &clap::ArgMatches) -> Result Ok(instance) } + +fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> Result>, String> { + match matches.value_of(arg) { + Some(value) => Ok(Some( + hex::decode(value).map_err(|e| format!("Failed to parse {}: {}", arg, e))?, + )), + None => Ok(None), + } +} From 51893c468d5bd67cedf7d6fe3a0786cb88ed3b54 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 18 Aug 2020 16:17:14 -0400 Subject: [PATCH 0137/1210] Introduce Minimal Header Chain: Proving Interface (#287) * Add header-chain primitive crate * Make MinimalHeaderChain functionaly the same as PeerBlockchain * Use a better doc comment for MinimalHeaderChain * Fix benchmark compilation * Rust Fmt * Remove Substrate based dependencies * Rename MinimalHeaderChain to BaseHeaderChain --- bin/node/runtime/Cargo.toml | 5 +++ bin/node/runtime/src/kovan.rs | 4 +- bin/node/runtime/src/rialto.rs | 4 +- modules/currency-exchange/Cargo.toml | 1 + modules/currency-exchange/src/benchmarking.rs | 4 +- modules/currency-exchange/src/lib.rs | 28 ++++-------- primitives/header-chain/Cargo.toml | 18 ++++++++ primitives/header-chain/src/lib.rs | 44 +++++++++++++++++++ 8 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 primitives/header-chain/Cargo.toml create mode 100644 primitives/header-chain/src/lib.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 09e58047bd3f9..bedb7a9a0c9d0 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -206,6 +206,11 @@ version = "0.1.0" default-features = false path = "../../../primitives/ethereum-poa" +[dependencies.bp-header-chain] +version = "0.1.0" +default-features = false +path = "../../../primitives/header-chain" + # Dev Dependencies [dev-dependencies.libsecp256k1] diff --git a/bin/node/runtime/src/kovan.rs b/bin/node/runtime/src/kovan.rs index 1855aa9dd3ea5..189333a83c590 100644 --- a/bin/node/runtime/src/kovan.rs +++ b/bin/node/runtime/src/kovan.rs @@ -17,9 +17,9 @@ use crate::exchange::EthereumTransactionInclusionProof; use bp_eth_poa::{Address, Header, RawTransaction, U256}; +use bp_header_chain::BaseHeaderChain; use frame_support::RuntimeDebug; use hex_literal::hex; -use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; @@ -137,7 +137,7 @@ impl BridgePruningStrategy for PruningStrategy { /// The Kovan Blockchain as seen by the runtime. pub struct KovanBlockchain; -impl PeerBlockchain for KovanBlockchain { +impl BaseHeaderChain for KovanBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; diff --git a/bin/node/runtime/src/rialto.rs b/bin/node/runtime/src/rialto.rs index 800b0ab1c86c8..17e84a5e1a07a 100644 --- a/bin/node/runtime/src/rialto.rs +++ b/bin/node/runtime/src/rialto.rs @@ -17,9 +17,9 @@ use crate::exchange::EthereumTransactionInclusionProof; use bp_eth_poa::{Address, Header, RawTransaction, U256}; +use bp_header_chain::BaseHeaderChain; use frame_support::RuntimeDebug; use hex_literal::hex; -use pallet_bridge_currency_exchange::PeerBlockchain; use pallet_bridge_eth_poa::{ AuraConfiguration, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, ValidatorsSource, }; @@ -110,7 +110,7 @@ impl TPruningStrategy for PruningStrategy { /// The Rialto Blockchain as seen by the runtime. pub struct RialtoBlockchain; -impl PeerBlockchain for RialtoBlockchain { +impl BaseHeaderChain for RialtoBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 03b3d692a3fac..4b0f0fd068a04 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } serde = { version = "1.0", optional = true } diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index 30fb7e63f0075..189dac8407b9d 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -18,7 +18,7 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{Call, Instance, Module as CurrencyExchangeModule, PeerBlockchain, Trait as CurrencyExchangeTrait}; +use super::{BaseHeaderChain, Call, Instance, Module as CurrencyExchangeModule, Trait as CurrencyExchangeTrait}; use sp_std::prelude::*; use frame_benchmarking::{account, benchmarks_instance}; @@ -50,7 +50,7 @@ pub trait Trait: CurrencyExchangeTrait { /// Prepare proof for importing exchange transaction. fn make_proof( proof_params: ProofParams, - ) -> <>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof; + ) -> <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof; } benchmarks_instance! { diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index a7c3c5026a2e8..28a53d287b51c 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -21,7 +21,8 @@ use bp_currency_exchange::{ CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, }; -use frame_support::{decl_error, decl_module, decl_storage, ensure, Parameter}; +use bp_header_chain::BaseHeaderChain; +use frame_support::{decl_error, decl_module, decl_storage, ensure}; use sp_runtime::DispatchResult; #[cfg(feature = "runtime-benchmarks")] @@ -33,28 +34,15 @@ pub trait OnTransactionSubmitted { fn on_valid_transaction_submitted(submitter: AccountId); } -/// Peer blockchain interface. -pub trait PeerBlockchain { - /// Transaction type. - type Transaction: Parameter; - /// Transaction inclusion proof type. - type TransactionInclusionProof: Parameter; - - /// Verify that transaction is a part of given block. - /// - /// Returns Some(transaction) if proof is valid and None otherwise. - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option; -} - /// The module configuration trait pub trait Trait: frame_system::Trait { /// Handler for transaction submission result. type OnTransactionSubmitted: OnTransactionSubmitted; /// Represents the blockchain that we'll be exchanging currency with. - type PeerBlockchain: PeerBlockchain; + type PeerBlockchain: BaseHeaderChain; /// Peer blockchain transaction parser. type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< - Transaction = ::Transaction, + Transaction = ::Transaction, >; /// Map between blockchains recipients. type RecipientsMap: RecipientsMap< @@ -101,7 +89,7 @@ decl_module! { #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_peer_transaction( origin, - proof: <>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof, + proof: <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; @@ -146,7 +134,7 @@ decl_storage! { impl, I: Instance> Module { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. - pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { + pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { if let Err(err) = prepare_deposit_details::(proof) { frame_support::debug::trace!( target: "runtime", @@ -192,7 +180,7 @@ struct DepositDetails, I: Instance> { /// Verify and parse transaction proof, preparing everything required for importing /// this transaction proof. fn prepare_deposit_details, I: Instance>( - proof: &<>::PeerBlockchain as PeerBlockchain>::TransactionInclusionProof, + proof: &<>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, ) -> Result, Error> { // ensure that transaction is included in finalized block that we know of let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) @@ -251,7 +239,7 @@ mod tests { pub struct DummyBlockchain; - impl PeerBlockchain for DummyBlockchain { + impl BaseHeaderChain for DummyBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = (bool, RawTransaction); diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml new file mode 100644 index 0000000000000..034f801001530 --- /dev/null +++ b/primitives/header-chain/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "bp-header-chain" +description = "A common interface for describing what a bridge pallet should be able to do." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies.parity-scale-codec] +version = "1.3.1" +default-features = false +features = ["derive"] + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", +] diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs new file mode 100644 index 0000000000000..7e5fa058cfe8c --- /dev/null +++ b/primitives/header-chain/src/lib.rs @@ -0,0 +1,44 @@ +// Copyright 2019-2020 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 . + +//! Defines traits which represent a common interface for Substrate pallets which want to +//! incorporate bridge functionality. + +#![cfg_attr(not(feature = "std"), no_std)] + +use core::clone::Clone; +use core::cmp::Eq; +use core::fmt::Debug; +use parity_scale_codec::{Codec, EncodeLike}; + +/// A type that can be used as a parameter in a dispatchable function. +/// +/// When using `decl_module` all arguments for call functions must implement this trait. +pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug {} +impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug {} + +/// A base trait for pallets which want to keep track of a full set of headers from a bridged chain. +pub trait BaseHeaderChain { + /// Transaction type. + type Transaction: Parameter; + /// Transaction inclusion proof type. + type TransactionInclusionProof: Parameter; + + /// Verify that transaction is a part of given block. + /// + /// Returns Some(transaction) if proof is valid and None otherwise. + fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option; +} From 7113b4341997b11e0799c0bc3ebfe2c6efa3fc51 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 19 Aug 2020 03:51:02 -0400 Subject: [PATCH 0138/1210] Remove old Substrate pallet (#292) --- modules/substrate/Cargo.toml | 52 +--- modules/substrate/src/lib.rs | 469 +---------------------------------- 2 files changed, 2 insertions(+), 519 deletions(-) diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index cec9e837eba4b..0abae27618c32 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-bridge" +name = "pallet-substrate-bridge" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" @@ -8,41 +8,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } serde = { version = "1.0", optional = true } hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies -[dependencies.frame-support] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-session] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-finality-grandpa] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - [dependencies.sp-runtime] version = "2.0.0-rc5" tag = 'v2.0.0-rc5' @@ -55,29 +24,10 @@ tag = 'v2.0.0-rc5' default-features = false git = "https://github.com/paritytech/substrate/" -# Dev Dependencies -[dev-dependencies.sp-io] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dev-dependencies.sp-state-machine] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' -git = "https://github.com/paritytech/substrate/" - [features] default = ["std"] std = [ "serde", - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-session/std", - "sp-core/std", - "sp-finality-grandpa/std", "sp-runtime/std", "sp-trie/std", - "sp-io/std", ] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 3403d91a5b3d1..84fde5c57db2c 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// Copyright 2020 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 @@ -13,470 +13,3 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . - -// Copyright 2017-2019 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 . - -//! # Bridge Module -//! -//! This will eventually have some useful documentation. -//! For now though, enjoy this cow's wisdom. -//! -//!```ignore -//!________________________________________ -//! / You are only young once, but you can \ -//! \ stay immature indefinitely. / -//! ---------------------------------------- -//! \ ^__^ -//! \ (oo)\_______ -//! (__)\ )\/\ -//! ||----w | -//! || || -//!``` - -// TODO: when (if) this module will be resurrected, remove this -#![allow(dead_code)] -// Ensure we're `no_std` when compiling for Wasm. -#![cfg_attr(not(feature = "std"), no_std)] - -mod storage_proof; - -use crate::storage_proof::{StorageProof, StorageProofChecker}; -use codec::{Decode, Encode}; -use frame_support::{ - decl_error, decl_module, decl_storage, - dispatch::{DispatchError, DispatchResult}, -}; -use frame_system::{self as system, ensure_signed}; -use sp_finality_grandpa::{AuthorityId, AuthorityWeight, GRANDPA_AUTHORITIES_KEY}; -use sp_runtime::traits::Header; -use storage_proof::Error as StorageError; - -#[derive(Encode, Decode, Clone, PartialEq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct BridgeInfo { - last_finalized_block_number: T::BlockNumber, - last_finalized_block_hash: T::Hash, - last_finalized_state_root: T::Hash, - current_validator_set: Vec<(AuthorityId, AuthorityWeight)>, -} - -impl BridgeInfo { - pub fn new( - block_number: &T::BlockNumber, - block_hash: &T::Hash, - state_root: &T::Hash, - validator_set: Vec<(AuthorityId, AuthorityWeight)>, - ) -> Self { - // I don't like how this is done, should come back to... - BridgeInfo { - last_finalized_block_number: *block_number, - last_finalized_block_hash: *block_hash, - last_finalized_state_root: *state_root, - current_validator_set: validator_set, - } - } -} - -type BridgeId = u64; - -pub trait Trait: system::Trait {} - -decl_storage! { - trait Store for Module as Bridge { - /// The number of current bridges managed by the module. - pub NumBridges get(fn num_bridges) config(): BridgeId; - - /// Maps a bridge id to a bridge struct. Allows a single - /// `bridge` module to manage multiple bridges. - pub TrackedBridges get(fn tracked_bridges): map hasher(blake2_128_concat) BridgeId => Option>; - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - - #[weight = 0] // TODO: update me - fn initialize_bridge( - origin, - block_header: T::Header, - validator_set: Vec<(AuthorityId, AuthorityWeight)>, - validator_set_proof: StorageProof, - ) { - // NOTE: Will want to make this a governance issued call - let _sender = ensure_signed(origin)?; - - let block_number = block_header.number(); - let block_hash = block_header.hash(); - let state_root = block_header.state_root(); - - Self::check_validator_set_proof(state_root, validator_set_proof, &validator_set)?; - - let bridge_info = BridgeInfo::new(block_number, &block_hash, state_root, validator_set); - - let new_bridge_id = NumBridges::get() + 1; - >::insert(new_bridge_id, bridge_info); - - NumBridges::put(new_bridge_id); - } - - #[weight = 0] // TODO: update me - fn submit_finalized_headers(origin) { - let _sender = ensure_signed(origin)?; - } - } -} - -decl_error! { - // Error for the Bridge module - pub enum Error for Module { - InvalidStorageProof, - StorageRootMismatch, - StorageValueUnavailable, - InvalidValidatorSetProof, - ValidatorSetMismatch, - InvalidAncestryProof, - } -} - -impl Module { - fn check_validator_set_proof( - state_root: &T::Hash, - proof: StorageProof, - validator_set: &[(AuthorityId, AuthorityWeight)], - ) -> DispatchResult { - let checker = >::new(*state_root, proof); - - let checker = checker.map_err(Self::map_storage_err)?; - - // By encoding the given set we should have an easy way to compare - // with the stuff we get out of storage via `read_value` - let encoded_validator_set = validator_set.encode(); - - let c = checker - .read_value(GRANDPA_AUTHORITIES_KEY) - .map_err(Self::map_storage_err)?; - let actual_validator_set = c.ok_or(Error::::StorageValueUnavailable)?; - - if encoded_validator_set == actual_validator_set { - Ok(()) - } else { - Err(Error::::ValidatorSetMismatch.into()) - } - } - - // A naive way to check whether a `child` header is a decendent - // of an `ancestor` header. For this it requires a proof which - // is a chain of headers between (but not including) the `child` - // and `ancestor`. This could be updated to use something like - // Log2 Ancestors (#2053) in the future. - fn verify_ancestry(proof: Vec, ancestor_hash: H::Hash, child: H) -> DispatchResult - where - H: Header, - { - let mut parent_hash = child.parent_hash(); - - // If we find that the header's parent hash matches our ancestor's hash we're done - for header in proof.iter() { - // Need to check that blocks are actually related - if header.hash() != *parent_hash { - break; - } - - parent_hash = header.parent_hash(); - if *parent_hash == ancestor_hash { - return Ok(()); - } - } - - Err(Error::::InvalidAncestryProof.into()) - } - - fn map_storage_err(e: StorageError) -> DispatchError { - match e { - StorageError::StorageRootMismatch => Error::::StorageRootMismatch, - StorageError::StorageValueUnavailable => Error::::StorageValueUnavailable, - } - .into() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use frame_support::{assert_err, assert_ok, impl_outer_origin, parameter_types}; - use sp_core::{Blake2Hasher, Public, H256}; - use sp_runtime::{ - generic::Digest, - testing::Header, - traits::{Header as HeaderT, IdentityLookup}, - Perbill, - }; - - impl_outer_origin! { - pub enum Origin for Test where system = frame_system {} - } - - #[derive(Clone, PartialEq, Eq, Debug)] - pub struct Test; - - type _System = system::Module; - type MockBridge = Module; - - // TODO: Figure out what I actually need from here - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: u32 = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const MinimumPeriod: u64 = 5; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - type DummyAuthorityId = u64; - - impl system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Call = (); - type Hash = H256; - type Hashing = sp_runtime::traits::BlakeTwo256; - type AccountId = DummyAuthorityId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = (); - type MaximumBlockWeight = (); - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = (); - type MaximumBlockLength = (); - type Version = (); - type ModuleToIndex = (); - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = (); - type SystemWeightInfo = (); - } - - impl Trait for Test {} - - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { num_bridges: 0 }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn it_works_for_default_value() { - new_test_ext().execute_with(|| { - assert_eq!(MockBridge::num_bridges(), 0); - }); - } - - fn get_dummy_authorities() -> Vec<(AuthorityId, AuthorityWeight)> { - let authority1 = (AuthorityId::from_slice(&[1; 32]), 1); - let authority2 = (AuthorityId::from_slice(&[2; 32]), 1); - let authority3 = (AuthorityId::from_slice(&[3; 32]), 1); - - vec![authority1, authority2, authority3] - } - - fn create_dummy_validator_proof(validator_set: Vec<(AuthorityId, AuthorityWeight)>) -> (H256, StorageProof) { - use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; - - let encoded_set = validator_set.encode(); - - // construct storage proof - let backend = >::from(vec![( - None, - vec![(GRANDPA_AUTHORITIES_KEY.to_vec(), Some(encoded_set))], - )]); - let root = backend.storage_root(std::iter::empty()).0; - - // Generates a storage read proof - let proof: StorageProof = prove_read(backend, &[&GRANDPA_AUTHORITIES_KEY[..]]) - .unwrap() - .iter_nodes() - .collect(); - - (root, proof) - } - - #[test] - fn it_can_validate_validator_sets() { - let authorities = get_dummy_authorities(); - let (root, proof) = create_dummy_validator_proof(authorities.clone()); - - assert_ok!(MockBridge::check_validator_set_proof(&root, proof, &authorities)); - } - - #[test] - fn it_rejects_invalid_validator_sets() { - let mut authorities = get_dummy_authorities(); - let (root, proof) = create_dummy_validator_proof(authorities.clone()); - - // Do something to make the authority set invalid - authorities.reverse(); - let invalid_authorities = authorities; - - assert_err!( - MockBridge::check_validator_set_proof(&root, proof, &invalid_authorities), - Error::::ValidatorSetMismatch - ); - } - - #[test] - fn it_creates_a_new_bridge() { - let authorities = get_dummy_authorities(); - let (root, proof) = create_dummy_validator_proof(authorities.clone()); - - let test_header = Header { - parent_hash: H256::default(), - number: 42, - state_root: root, - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - let test_hash = test_header.hash(); - - new_test_ext().execute_with(|| { - assert_eq!(MockBridge::num_bridges(), 0); - dbg!(&test_header); - assert_ok!(MockBridge::initialize_bridge( - Origin::signed(1), - test_header, - authorities.clone(), - proof, - )); - - assert_eq!( - MockBridge::tracked_bridges(1), - Some(BridgeInfo { - last_finalized_block_number: 42, - last_finalized_block_hash: test_hash, - last_finalized_state_root: root, - current_validator_set: authorities.clone(), - }) - ); - - assert_eq!(MockBridge::num_bridges(), 1); - }); - } - - fn build_header_chain(root_header: Header, len: usize) -> Vec

{ - let mut header_chain = vec![root_header]; - for i in 1..len { - let parent = &header_chain[i - 1]; - - let h = Header { - parent_hash: parent.hash(), - number: parent.number() + 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - header_chain.push(h); - } - - // We want our proofs to go from newest to older headers - header_chain.reverse(); - // We don't actually need the oldest header in the proof - header_chain.pop(); - header_chain - } - - #[test] - fn check_that_child_is_ancestor_of_grandparent() { - let ancestor = Header { - parent_hash: H256::default(), - number: 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - // A valid proof doesn't include the child header, so remove it - let mut proof = build_header_chain(ancestor.clone(), 10); - let child = proof.remove(0); - - assert_ok!(MockBridge::verify_ancestry(proof, ancestor.hash(), child)); - } - - #[test] - fn fake_ancestor_is_not_found_in_child_ancestry() { - let ancestor = Header { - parent_hash: H256::default(), - number: 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - // A valid proof doesn't include the child header, so remove it - let mut proof = build_header_chain(ancestor, 10); - let child = proof.remove(0); - - let fake_ancestor = Header { - parent_hash: H256::from_slice(&[1u8; 32]), - number: 42, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - assert_err!( - MockBridge::verify_ancestry(proof, fake_ancestor.hash(), child), - Error::::InvalidAncestryProof - ); - } - - #[test] - fn checker_fails_if_given_an_unrelated_header() { - let ancestor = Header { - parent_hash: H256::default(), - number: 1, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - // A valid proof doesn't include the child header, so remove it - let mut invalid_proof = build_header_chain(ancestor.clone(), 10); - let child = invalid_proof.remove(0); - - let fake_ancestor = Header { - parent_hash: H256::from_slice(&[1u8; 32]), - number: 42, - state_root: H256::default(), - extrinsics_root: H256::default(), - digest: Digest::default(), - }; - - invalid_proof.insert(5, fake_ancestor); - - assert_err!( - MockBridge::verify_ancestry(invalid_proof, ancestor.hash(), child), - Error::::InvalidAncestryProof - ); - } -} From 53809e85568dbeb7a94a6de8d6812774bf61fa76 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 19 Aug 2020 13:32:12 +0300 Subject: [PATCH 0139/1210] MAX_SUBMITTED_HEADERS = 4 (#293) --- relays/ethereum/src/substrate_sync_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 0ed7913327234..4f796029a83ad 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -47,7 +47,7 @@ pub mod consts { /// Max Ethereum headers we want to have in all 'before-submitted' states. pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; /// Max Ethereum headers count we want to have in 'submitted' state. - pub const MAX_SUBMITTED_HEADERS: usize = 1; + pub const MAX_SUBMITTED_HEADERS: usize = 4; /// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). pub const PRUNE_DEPTH: u32 = 256; } From 037ca88e19eff8a6a05d58d29a1a6eb228ec976d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 19 Aug 2020 13:32:54 +0300 Subject: [PATCH 0140/1210] Remove errors from log (#294) * changed log level from error to trace * incomplete during submit != synced --- bin/node/runtime/src/exchange.rs | 6 +++--- relays/ethereum/src/headers.rs | 23 ++++++++++++++--------- relays/ethereum/src/sync_loop.rs | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index 0812006ebd66a..7296fc41e1c2e 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -81,7 +81,7 @@ impl MaybeLockFundsTransaction for EthTransaction { // we only accept transactions sending funds directly to the pre-configured address if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) { - frame_support::debug::error!( + frame_support::debug::trace!( target: "runtime", "Failed to parse fund locks transaction. Invalid peer recipient: {:?}", tx.unsigned.to, @@ -94,7 +94,7 @@ impl MaybeLockFundsTransaction for EthTransaction { match tx.unsigned.payload.len() { 32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.unsigned.payload), len => { - frame_support::debug::error!( + frame_support::debug::trace!( target: "runtime", "Failed to parse fund locks transaction. Invalid recipient length: {}", len, @@ -106,7 +106,7 @@ impl MaybeLockFundsTransaction for EthTransaction { let amount = tx.unsigned.value.low_u128(); if tx.unsigned.value != amount.into() { - frame_support::debug::error!( + frame_support::debug::trace!( target: "runtime", "Failed to parse fund locks transaction. Invalid amount: {}", tx.unsigned.value, diff --git a/relays/ethereum/src/headers.rs b/relays/ethereum/src/headers.rs index 8980bcccf3e8a..63c8e07351f8a 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/ethereum/src/headers.rs @@ -404,9 +404,12 @@ impl QueuedHeaders

{ } /// Marks given headers incomplete. - pub fn add_incomplete_headers(&mut self, new_incomplete_headers: Vec>) { + pub fn add_incomplete_headers(&mut self, make_header_incomplete: bool, new_incomplete_headers: Vec>) { for new_incomplete_header in new_incomplete_headers { - self.header_synced(&new_incomplete_header); + if make_header_incomplete { + self.header_synced(&new_incomplete_header); + } + move_header_descendants::

( &mut [&mut self.ready, &mut self.submitted], &mut self.incomplete, @@ -415,13 +418,15 @@ impl QueuedHeaders

{ &new_incomplete_header, ); - log::debug!( - target: "bridge", - "Scheduling completion data retrieval for header: {:?}", - new_incomplete_header, - ); + if make_header_incomplete { + log::debug!( + target: "bridge", + "Scheduling completion data retrieval for header: {:?}", + new_incomplete_header, + ); - self.incomplete_headers.insert(new_incomplete_header, None); + self.incomplete_headers.insert(new_incomplete_header, None); + } } } @@ -434,7 +439,7 @@ impl QueuedHeaders

{ .filter(|id| !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id)) .cloned() .collect::>(); - self.add_incomplete_headers(new_incomplete_headers); + self.add_incomplete_headers(true, new_incomplete_headers); // for all headers that were incompleted previously, but now are completed, we move // all descendants from incomplete to ready diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 12fdf0d01b5bf..4b82bfdf12113 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -334,7 +334,7 @@ pub fn run>( log::debug!(target: "bridge", "Header submit result: {}", submitted_headers_str); sync.headers_mut().headers_submitted(submitted_headers.submitted); - sync.headers_mut().add_incomplete_headers(submitted_headers.incomplete); + sync.headers_mut().add_incomplete_headers(false, submitted_headers.incomplete); // when there's no fatal error, but node has rejected all our headers we may // want to pause until our submitted headers will be accepted From b418cbd6a8badcb61ac8b7f4db5be81cfe492b9c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 20 Aug 2020 11:47:33 +0300 Subject: [PATCH 0141/1210] Fix (workaround) for "cannot read property 'toFixed' of null" (#297) * fix (workaround) for NaN CPU usage * cargo fmt --all --- relays/ethereum/src/metrics.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/relays/ethereum/src/metrics.rs b/relays/ethereum/src/metrics.rs index c65fdac5ad833..c94ecf6f02c85 100644 --- a/relays/ethereum/src/metrics.rs +++ b/relays/ethereum/src/metrics.rs @@ -18,7 +18,7 @@ pub use substrate_prometheus_endpoint::{register, Counter, CounterVec, Gauge, Ga use std::net::SocketAddr; use substrate_prometheus_endpoint::init_prometheus; -use sysinfo::{ProcessExt, System, SystemExt}; +use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; /// Prometheus endpoint MetricsParams. #[derive(Debug, Clone)] @@ -111,7 +111,7 @@ impl GlobalMetrics { /// Creates global metrics. pub fn new() -> Self { GlobalMetrics { - system: System::new(), + system: System::new_with_specifics(RefreshKind::everything()), system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) .expect("metric is static and thus valid; qed"), process_cpu_usage_percentage: Gauge::new("process_cpu_usage_percentage", "Process CPU usage") @@ -141,8 +141,18 @@ impl GlobalMetrics { let is_process_refreshed = self.system.refresh_process(pid); match (is_process_refreshed, self.system.get_process(pid)) { (true, Some(process_info)) => { - self.process_cpu_usage_percentage.set(process_info.cpu_usage() as f64); - self.process_memory_usage_bytes.set(process_info.memory() * 1024); + let cpu_usage = process_info.cpu_usage() as f64; + let memory_usage = process_info.memory() * 1024; + log::trace!( + target: "bridge-metrics", + "Refreshed process metrics: CPU={}, memory={}", + cpu_usage, + memory_usage, + ); + + self.process_cpu_usage_percentage + .set(if cpu_usage.is_finite() { cpu_usage } else { 0f64 }); + self.process_memory_usage_bytes.set(memory_usage); } _ => { log::warn!( From dc9f643887483a90edfa37e9dab9a4a44266d542 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 28 Aug 2020 09:47:44 +0300 Subject: [PATCH 0142/1210] Update substrate reference to rc6 (#321) * update substrate to rc6 * clippy * fixed benchmarks compilation * Update bin/node/node/src/service.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/node/node/Cargo.toml | 92 +++---- bin/node/node/src/command.rs | 21 +- bin/node/node/src/service.rs | 253 +++++++++++-------- bin/node/runtime/Cargo.toml | 106 ++++---- bin/node/runtime/src/exchange.rs | 2 +- bin/node/runtime/src/lib.rs | 17 +- modules/currency-exchange/Cargo.toml | 30 +-- modules/ethereum-contract/builtin/Cargo.toml | 22 +- modules/ethereum/Cargo.toml | 26 +- modules/substrate/Cargo.toml | 8 +- primitives/currency-exchange/Cargo.toml | 14 +- primitives/ethereum-poa/Cargo.toml | 18 +- relays/ethereum/Cargo.toml | 30 +-- 13 files changed, 340 insertions(+), 299 deletions(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index ab7db6f9d01ed..df2d53052f36f 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -25,110 +25,110 @@ default-features = false features = ["std"] [dependencies.sc-cli] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-finality-grandpa] package = "sc-finality-grandpa" -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-client-api] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking-cli] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -136,13 +136,13 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [build-dependencies.frame-benchmarking-cli] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [features] diff --git a/bin/node/node/src/command.rs b/bin/node/node/src/command.rs index 8a50ab1ad40e1..9951e9af47f6c 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/node/src/command.rs @@ -32,10 +32,10 @@ use crate::cli::{Cli, Subcommand}; use crate::service; -use crate::service::new_full_params; +use crate::service::new_partial; use bridge_node_runtime::Block; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; -use sc_service::ServiceParams; +use sc_service::PartialComponents; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -103,16 +103,13 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::Base(subcommand)) => { let runner = cli.create_runner(subcommand)?; runner.run_subcommand(subcommand, |config| { - let ( - ServiceParams { - client, - backend, - task_manager, - import_queue, - .. - }, - .., - ) = new_full_params(config)?; + let PartialComponents { + client, + backend, + task_manager, + import_queue, + .. + } = new_partial(&config)?; Ok((client, backend, import_queue, task_manager)) }) } diff --git a/bin/node/node/src/service.rs b/bin/node/node/src/service.rs index 4607c51b50b88..e1a1919b97343 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/node/src/service.rs @@ -16,14 +16,24 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. +// ===================================================================================== +// ===================================================================================== +// ===================================================================================== +// UPDATE GUIDE: +// 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); +// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom RPCs; +// 3) fix compilation errors; +// 4) test :) +// ===================================================================================== +// ===================================================================================== +// ===================================================================================== + use bridge_node_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sc_finality_grandpa::{ - FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState, StorageAndProofProvider, -}; -use sc_service::{error::Error as ServiceError, Configuration, ServiceComponents, TaskManager}; +use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -42,23 +52,20 @@ type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; #[allow(clippy::type_complexity)] -pub fn new_full_params( - config: Configuration, +pub fn new_partial( + config: &Configuration, ) -> Result< - ( - sc_service::ServiceParams< - Block, - FullClient, - sc_consensus_aura::AuraImportQueue, - sc_transaction_pool::FullPool, - jsonrpc_core::IoHandler, - FullBackend, - >, + sc_service::PartialComponents< + FullClient, + FullBackend, FullSelectChain, - sp_inherents::InherentDataProviders, - sc_finality_grandpa::GrandpaBlockImport, - sc_finality_grandpa::LinkHalf, - ), + sp_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, + ( + sc_finality_grandpa::GrandpaBlockImport, + sc_finality_grandpa::LinkHalf, + ), + >, ServiceError, > { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); @@ -68,10 +75,8 @@ pub fn new_full_params( let select_chain = sc_consensus::LongestChain::new(backend.clone()); - let pool_api = sc_transaction_pool::FullChainApi::new(client.clone(), config.prometheus_registry()); let transaction_pool = sc_transaction_pool::BasicPool::new_full( config.transaction_pool.clone(), - std::sync::Arc::new(pool_api), config.prometheus_registry(), task_manager.spawn_handle(), client.clone(), @@ -83,7 +88,7 @@ pub fn new_full_params( let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, aura_block_import, Some(Box::new(grandpa_block_import.clone())), @@ -92,8 +97,68 @@ pub fn new_full_params( inherent_data_providers.clone(), &task_manager.spawn_handle(), config.prometheus_registry(), + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), )?; + Ok(sc_service::PartialComponents { + client, + backend, + task_manager, + import_queue, + keystore, + select_chain, + transaction_pool, + inherent_data_providers, + other: (grandpa_block_import, grandpa_link), + }) +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) -> Result { + let sc_service::PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore, + select_chain, + transaction_pool, + inherent_data_providers, + other: (block_import, grandpa_link), + } = new_partial(&config)?; + + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + + let (network, network_status_sinks, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + finality_proof_request_builder: None, + finality_proof_provider: Some(finality_proof_provider), + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + backend.clone(), + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + } + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let name = config.network.node_name.clone(); + let enable_grandpa = !config.disable_grandpa; + let prometheus_registry = config.prometheus_registry().cloned(); + let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); + let rpc_extensions_builder = { use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; @@ -101,7 +166,7 @@ pub fn new_full_params( let client = client.clone(); let pool = transaction_pool.clone(); - Box::new(move |_| { + Box::new(move |_, _| { let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( client.clone(), @@ -113,65 +178,21 @@ pub fn new_full_params( }) }; - let provider = client.clone() as Arc>; - let finality_proof_provider = Arc::new(GrandpaFinalityProofProvider::new(backend.clone(), provider)); - - let params = sc_service::ServiceParams { - backend, - client, - import_queue, - keystore, - task_manager, - transaction_pool, - config, - block_announce_validator_builder: None, - finality_proof_request_builder: None, - finality_proof_provider: Some(finality_proof_provider), + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore.clone(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + telemetry_connection_sinks: telemetry_connection_sinks.clone(), + rpc_extensions_builder, on_demand: None, remote_blockchain: None, - rpc_extensions_builder, - }; - - Ok(( - params, - select_chain, - inherent_data_providers, - grandpa_block_import, - grandpa_link, - )) -} - -/// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { - let (params, select_chain, inherent_data_providers, block_import, grandpa_link) = new_full_params(config)?; - - let (role, force_authoring, name, enable_grandpa, prometheus_registry, client, transaction_pool, keystore) = { - let sc_service::ServiceParams { - config, - client, - transaction_pool, - keystore, - .. - } = ¶ms; - - ( - config.role.clone(), - config.force_authoring, - config.network.node_name.clone(), - !config.disable_grandpa, - config.prometheus_registry().cloned(), - client.clone(), - transaction_pool.clone(), - keystore.clone(), - ) - }; - - let ServiceComponents { - task_manager, - network, - telemetry_on_connect_sinks, - .. - } = sc_service::build(params)?; + backend, + network_status_sinks, + system_rpc_tx, + config, + })?; if role.is_authority() { let proposer = @@ -227,7 +248,7 @@ pub fn new_full(config: Configuration) -> Result { link: grandpa_link, network, inherent_data_providers, - telemetry_on_connect: Some(telemetry_on_connect_sinks.on_connect_stream()), + telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), @@ -242,24 +263,22 @@ pub fn new_full(config: Configuration) -> Result { sc_finality_grandpa::setup_disabled_grandpa(client, &inherent_data_providers, network)?; } + network_starter.start_network(); Ok(task_manager) } /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - let (client, backend, keystore, task_manager, on_demand) = + let (client, backend, keystore, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; - let transaction_pool_api = Arc::new(sc_transaction_pool::LightChainApi::new( - client.clone(), - on_demand.clone(), - )); - let transaction_pool = sc_transaction_pool::BasicPool::new_light( + let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( config.transaction_pool.clone(), - transaction_pool_api, config.prometheus_registry(), task_manager.spawn_handle(), - ); + client.clone(), + on_demand.clone(), + )); let grandpa_block_import = sc_finality_grandpa::light_block_import( client.clone(), @@ -270,7 +289,7 @@ pub fn new_light(config: Configuration) -> Result { let finality_proof_import = grandpa_block_import.clone(); let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _>( + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, grandpa_block_import, None, @@ -279,27 +298,51 @@ pub fn new_light(config: Configuration) -> Result { InherentDataProviders::new(), &task_manager.spawn_handle(), config.prometheus_registry(), + sp_consensus::NeverCanAuthor, )?; - let finality_proof_provider = Arc::new(GrandpaFinalityProofProvider::new( - backend.clone(), - client.clone() as Arc<_>, - )); + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + + let (network, network_status_sinks, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: Some(on_demand.clone()), + block_announce_validator_builder: None, + finality_proof_request_builder: Some(finality_proof_request_builder), + finality_proof_provider: Some(finality_proof_provider), + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + backend.clone(), + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + } - sc_service::build(sc_service::ServiceParams { - block_announce_validator_builder: None, - finality_proof_request_builder: Some(finality_proof_request_builder), - finality_proof_provider: Some(finality_proof_provider), - on_demand: Some(on_demand), + sc_service::spawn_tasks(sc_service::SpawnTasksParams { remote_blockchain: Some(backend.remote_blockchain()), - rpc_extensions_builder: Box::new(|_| ()), - transaction_pool: Arc::new(transaction_pool), + transaction_pool, + task_manager: &mut task_manager, + on_demand: Some(on_demand), + rpc_extensions_builder: Box::new(|_, _| ()), + telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), config, client, - import_queue, keystore, backend, - task_manager, - }) - .map(|ServiceComponents { task_manager, .. }| task_manager) + network, + network_status_sinks, + system_rpc_tx, + })?; + + network_starter.start_network(); + + Ok(task_manager) } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index bedb7a9a0c9d0..62a8e6baee411 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -29,14 +29,14 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" @@ -51,148 +51,148 @@ default-features = false path = "../../../modules/currency-exchange" [dependencies.frame-support] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-consensus-aura] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" @@ -226,7 +226,7 @@ path = "../../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] version = "1.0.5" -tag = 'v2.0.0-rc5' +tag = 'v2.0.0-rc6' package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" diff --git a/bin/node/runtime/src/exchange.rs b/bin/node/runtime/src/exchange.rs index 7296fc41e1c2e..1e68ce83f71fe 100644 --- a/bin/node/runtime/src/exchange.rs +++ b/bin/node/runtime/src/exchange.rs @@ -128,7 +128,7 @@ impl MaybeLockFundsTransaction for EthTransaction { /// Prepares everything required to bench claim of funds locked by given transaction. #[cfg(feature = "runtime-benchmarks")] -pub(crate) fn prepare_environment_for_claim, I: pallet_bridge_eth_poa::Instance>( +pub(crate) fn prepare_environment_for_claim, I: frame_support::traits::Instance>( transactions: &[(RawTransaction, RawTransactionReceipt)], ) -> bp_eth_poa::H256 { use bp_eth_poa::compute_merkle_root; diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 2ea311289196f..7fedc3e35469a 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -687,22 +687,23 @@ impl_runtime_apis! { highest_range_values: Vec, steps: Vec, repeat: u32, + extra: bool, ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; let mut batches = Vec::::new(); - let whitelist: Vec> = vec![ + let whitelist: Vec = vec![ // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec(), + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec(), + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec(), + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec(), + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), // Caller 0 Account - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec(), + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), ]; - let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist); + let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist, extra); use pallet_bridge_currency_exchange::benchmarking::{ Module as BridgeCurrencyExchangeBench, diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 4b0f0fd068a04..09bb1c25cba9f 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -9,49 +9,49 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } bp-header-chain = { path = "../../primitives/header-chain", default-features = false } -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } serde = { version = "1.0", optional = true } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-io] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 97b497f5ee786..ac7b7b80b7856 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # General dependencies -codec = { package = "parity-scale-codec", version = "1.3.1" } +codec = { package = "parity-scale-codec", version = "1.3.4" } ethereum-types = "0.9.2" finality-grandpa = "0.12.3" hex = "0.4" @@ -21,29 +21,29 @@ log = "0.4.11" bridge-node-runtime = { path = "../../../bin/node/runtime" } [dependencies.sp-blockchain] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [dependencies.sc-finality-grandpa] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [dev-dependencies] hex = "0.4" [dev-dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index bde8f95456d94..affabfe7976fa 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -8,45 +8,45 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } hex-literal = "0.3" serde = { version = "1.0", optional = true } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 0abae27618c32..d5ffb159d2222 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -13,14 +13,14 @@ hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index ff2c98c11870d..a958f83c4372c 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -7,25 +7,25 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.frame-support] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 9beb08892e95c..95b6fa2132190 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -15,7 +15,7 @@ primitive-types = { version = "0.7", default-features = false, features = ["code fixed-hash = { version = "0.5", default-features = false } impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } rlp = { version = "0.4", default-features = false } hash-db = { version = "0.15.2", default-features = false } triehash = { version = "0.8.2", default-features = false } @@ -23,26 +23,26 @@ plain_hasher = { version = "0.2.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 856c10788b2ab..e06e31b45c2e6 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -14,7 +14,7 @@ backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } clap = { version = "2.33.3", features = ["yaml"] } -codec = { package = "parity-scale-codec", version = "1.3.1" } +codec = { package = "parity-scale-codec", version = "1.3.4" } env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" @@ -43,38 +43,38 @@ features = ["http"] # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.node-primitives] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc5" -tag = 'v2.0.0-rc5' +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-prometheus-endpoint] -version = "0.8.0-rc5" -tag = 'v2.0.0-rc5' +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" [dependencies.bridge-node-runtime] From 5ae6a85743b17c71e28255e5f739fb0751e7b3b6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 28 Aug 2020 12:12:33 +0300 Subject: [PATCH 0143/1210] Bump async-trait from 0.1.37 to 0.1.38 (#306) Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.37 to 0.1.38. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.37...0.1.38) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Svyatoslav Nikolsky --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index e06e31b45c2e6..69fe4265051fe 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" ansi_term = "0.12" async-std = "1.6.2" async-stream = "0.3.0" -async-trait = "0.1.37" +async-trait = "0.1.38" backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } From f6a0f319cbee8a4e296bcb60c05807bbce2d2580 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2020 02:29:00 +0000 Subject: [PATCH 0144/1210] Bump async-trait from 0.1.38 to 0.1.40 (#329) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 69fe4265051fe..0842bb206d15f 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" ansi_term = "0.12" async-std = "1.6.2" async-stream = "0.3.0" -async-trait = "0.1.38" +async-trait = "0.1.40" backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } From dd60775c09be3efc324ba0d63ec2cd1978e5c4af Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2020 02:29:22 +0000 Subject: [PATCH 0145/1210] Bump structopt from 0.3.16 to 0.3.17 (#330) --- bin/node/node/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index df2d53052f36f..4834c783c8570 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -16,7 +16,7 @@ bp-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.11" -structopt = "0.3.16" +structopt = "0.3.17" [dependencies.bridge-node-runtime] version = "0.1.0" From f3846b5183a817179ad6b885b961e9347201be0f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 31 Aug 2020 11:14:12 +0300 Subject: [PATCH 0146/1210] Initial version of DummyOrdered pallet (#299) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * initial commit of DummyOrdered (aka message-lane) pallet * API for relay * cargo fmt --all * some clippy + no_std * more clippy + no_std * inbound lane tests * outbound lane tests * cargo fmt --all * prune old messages whenever outbound lane is updated * do not care about MessageNonce overflow * cargo fmt --all * update crate docs * MaxHeadersToPruneAtOnce -> MaxMessagesToPruneAtOnce * MessageAction -> MessageResult * cargo fmt --all * fire MessageAccepted + MessagesDelivered * confirm message processing * cargo fmt --all * clippy * cargo fmt again * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano * use crate::* * cargo fmt --all * Storage -> S * Update modules/message-lane/src/outbound_lane.rs Co-authored-by: Hernando Castano * add method doc * Update modules/message-lane/src/inbound_lane.rs Co-authored-by: Hernando Castano * added detailed module docs * Update modules/message-lane/src/lib.rs Co-authored-by: Tomasz Drwięga * updated OnMessageReceived docs * prune only when new message is sent * removed #![warn(missing_docs)] * fixed merge with overlapped PR Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- bin/node/runtime/Cargo.toml | 5 + modules/message-lane/Cargo.toml | 56 +++++ modules/message-lane/src/inbound_lane.rs | 236 ++++++++++++++++++ modules/message-lane/src/lib.rs | 281 ++++++++++++++++++++++ modules/message-lane/src/mock.rs | 121 ++++++++++ modules/message-lane/src/outbound_lane.rs | 271 +++++++++++++++++++++ primitives/message-lane/Cargo.toml | 25 ++ primitives/message-lane/src/lib.rs | 135 +++++++++++ 8 files changed, 1130 insertions(+) create mode 100644 modules/message-lane/Cargo.toml create mode 100644 modules/message-lane/src/inbound_lane.rs create mode 100644 modules/message-lane/src/lib.rs create mode 100644 modules/message-lane/src/mock.rs create mode 100644 modules/message-lane/src/outbound_lane.rs create mode 100644 primitives/message-lane/Cargo.toml create mode 100644 primitives/message-lane/src/lib.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 62a8e6baee411..5deeff830845f 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -50,6 +50,11 @@ version = "0.1.0" default-features = false path = "../../../modules/currency-exchange" +[dependencies.pallet-message-lane] +version = "0.1.0" +default-features = false +path = "../../../modules/message-lane" + [dependencies.frame-support] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml new file mode 100644 index 0000000000000..71bb86f689f08 --- /dev/null +++ b/modules/message-lane/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-message-lane" +description = "Module that allows bridged chains to exchange messages using lane concept." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } + +# Substrate Based Dependencies + +[dependencies.frame-support] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-std] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies.sp-core] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies.sp-io] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies.sp-runtime] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-std/std" +] diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs new file mode 100644 index 0000000000000..abf6ffb346760 --- /dev/null +++ b/modules/message-lane/src/inbound_lane.rs @@ -0,0 +1,236 @@ +// Copyright 2019-2020 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 . + +//! Everything about incoming messages receival. + +use bp_message_lane::{InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessageResult, OnMessageReceived}; + +/// Inbound lane storage. +pub trait InboundLaneStorage { + /// Message payload. + type Payload; + + /// Lane id. + fn id(&self) -> LaneId; + /// Get lane data from the storage. + fn data(&self) -> InboundLaneData; + /// Update lane data in the storage. + fn set_data(&mut self, data: InboundLaneData); + /// Returns saved inbound message payload. + fn message(&self, nonce: &MessageNonce) -> Option; + /// Save inbound message in the storage. + fn save_message(&mut self, nonce: MessageNonce, payload: Self::Payload); + /// Remove inbound message from the storage. + fn remove_message(&mut self, nonce: &MessageNonce); +} + +/// Inbound messages lane. +pub struct InboundLane { + storage: S, +} + +impl InboundLane { + /// Create new inbound lane backed by given storage. + pub fn new(storage: S) -> Self { + InboundLane { storage } + } + + /// Receive new message. + pub fn receive_message( + &mut self, + nonce: MessageNonce, + payload: S::Payload, + processor: &mut impl OnMessageReceived, + ) -> bool { + let mut data = self.storage.data(); + let is_correct_message = nonce == data.latest_received_nonce + 1; + if !is_correct_message { + return false; + } + + let is_process_required = is_correct_message && data.oldest_unprocessed_nonce == nonce; + data.latest_received_nonce = nonce; + self.storage.set_data(data); + + let payload_to_save = match is_process_required { + true => { + let message = Message { + key: MessageKey { + lane_id: self.storage.id(), + nonce, + }, + payload, + }; + match processor.on_message_received(message) { + MessageResult::Processed => None, + MessageResult::NotProcessed(message) => Some(message.payload), + } + } + false => Some(payload), + }; + + if let Some(payload_to_save) = payload_to_save { + self.storage.save_message(nonce, payload_to_save); + } + + true + } + + /// Process stored lane messages. + /// + /// Stops processing either when all messages are processed, or when processor returns + /// MessageResult::NotProcessed. + pub fn process_messages(&mut self, processor: &mut impl OnMessageReceived) { + let mut anything_processed = false; + let mut data = self.storage.data(); + while data.oldest_unprocessed_nonce <= data.latest_received_nonce { + let nonce = data.oldest_unprocessed_nonce; + let payload = self + .storage + .message(&nonce) + .expect("message is referenced by lane; referenced message is not pruned; qed"); + let message = Message { + key: MessageKey { + lane_id: self.storage.id(), + nonce, + }, + payload, + }; + + let process_result = processor.on_message_received(message); + if let MessageResult::NotProcessed(_) = process_result { + break; + } + + self.storage.remove_message(&nonce); + + anything_processed = true; + data.oldest_unprocessed_nonce += 1; + } + + if anything_processed { + self.storage.set_data(data); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + inbound_lane, + mock::{ + run_test, TestMessageProcessor, TestPayload, TestRuntime, PAYLOAD_TO_QUEUE, REGULAR_PAYLOAD, TEST_LANE_ID, + }, + }; + + #[test] + fn fails_to_receive_message_with_incorrect_nonce() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(!lane.receive_message(10, REGULAR_PAYLOAD, &mut TestMessageProcessor)); + assert!(lane.storage.message(&10).is_none()); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + }); + } + + #[test] + fn correct_message_is_queued_if_some_other_messages_are_queued() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(lane.receive_message(1, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); + assert!(lane.storage.message(&1).is_some()); + assert!(lane.receive_message(2, REGULAR_PAYLOAD, &mut TestMessageProcessor)); + assert!(lane.storage.message(&2).is_some()); + assert_eq!(lane.storage.data().latest_received_nonce, 2); + }); + } + + #[test] + fn correct_message_is_queued_if_processor_wants_to_queue() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(lane.receive_message(1, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); + assert!(lane.storage.message(&1).is_some()); + assert_eq!(lane.storage.data().latest_received_nonce, 1); + }); + } + + #[test] + fn correct_message_is_not_queued_if_processed_instantly() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(lane.receive_message(1, REGULAR_PAYLOAD, &mut TestMessageProcessor)); + assert!(lane.storage.message(&1).is_none()); + assert_eq!(lane.storage.data().latest_received_nonce, 1); + }); + } + + #[test] + fn process_message_does_nothing_when_lane_is_empty() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 1); + lane.process_messages(&mut TestMessageProcessor); + assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 1); + }); + } + + #[test] + fn process_message_works() { + run_test(|| { + pub struct QueueByNonce(MessageNonce); + + impl OnMessageReceived for QueueByNonce { + fn on_message_received(&mut self, message: Message) -> MessageResult { + if message.key.nonce == self.0 { + MessageResult::NotProcessed(message) + } else { + MessageResult::Processed + } + } + } + + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(lane.receive_message(1, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); + assert!(lane.receive_message(2, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); + assert!(lane.receive_message(3, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); + assert!(lane.receive_message(4, REGULAR_PAYLOAD, &mut TestMessageProcessor)); + + assert!(lane.storage.message(&1).is_some()); + assert!(lane.storage.message(&2).is_some()); + assert!(lane.storage.message(&3).is_some()); + assert!(lane.storage.message(&4).is_some()); + assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 1); + + lane.process_messages(&mut QueueByNonce(3)); + + assert!(lane.storage.message(&1).is_none()); + assert!(lane.storage.message(&2).is_none()); + assert!(lane.storage.message(&3).is_some()); + assert!(lane.storage.message(&4).is_some()); + assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 3); + + lane.process_messages(&mut QueueByNonce(10)); + + assert!(lane.storage.message(&1).is_none()); + assert!(lane.storage.message(&2).is_none()); + assert!(lane.storage.message(&3).is_none()); + assert!(lane.storage.message(&4).is_none()); + assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 5); + }); + } +} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs new file mode 100644 index 0000000000000..40517887e1579 --- /dev/null +++ b/modules/message-lane/src/lib.rs @@ -0,0 +1,281 @@ +// Copyright 2019-2020 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 . + +//! Runtime module that allows sending and receiving messages using lane concept: +//! +//! 1) the message is sent using `send_message()` call; +//! 2) every outbound message is assigned nonce; +//! 3) the messages are stored in the storage; +//! 4) external component (relay) delivers messages to bridged chain; +//! 5) messages are processed in order (ordered by assigned nonce); +//! 6) relay may send proof-of-receiving and proof-of-processing back to this chain. +//! +//! Once message is sent, its progress can be tracked by looking at module events. +//! The assigned nonce is reported using `MessageAccepted` event. When message is +//! accepted by the bridged chain, `MessagesDelivered` is fired. When message is +//! processedby the bridged chain, `MessagesProcessed` by the bridged chain. + +#![cfg_attr(not(feature = "std"), no_std)] + +use crate::inbound_lane::{InboundLane, InboundLaneStorage}; +use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; + +use bp_message_lane::{ + InboundLaneData, LaneId, Message, MessageKey, MessageNonce, OnMessageReceived, OutboundLaneData, +}; +use frame_support::{decl_event, decl_module, decl_storage, traits::Get, Parameter, StorageMap}; +use frame_system::ensure_signed; +use sp_std::{marker::PhantomData, prelude::*}; + +mod inbound_lane; +mod outbound_lane; + +#[cfg(test)] +mod mock; + +/// The module configuration trait +pub trait Trait: frame_system::Trait { + /// They overarching event type. + type Event: From + Into<::Event>; + /// Message payload. + type Payload: Parameter; + /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs + /// whenever outbound lane is updated - i.e. when new message is sent, or receival is + /// confirmed. The reason is that if you want to use lane, you should be ready to pay + /// for it. + type MaxMessagesToPruneAtOnce: Get; + /// Called when message has been received. + type OnMessageReceived: Default + OnMessageReceived; +} + +decl_storage! { + trait Store for Module, I: Instance = DefaultInstance> as MessageLane { + /// Map of lane id => inbound lane data. + InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; + /// All stored (unprocessed) inbound messages. + InboundMessages: map hasher(blake2_128_concat) MessageKey => Option; + /// Map of lane id => outbound lane data. + OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; + /// All queued outbound messages. + OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option; + } +} + +decl_event!( + pub enum Event { + /// Message has been accepted and is waiting to be delivered. + MessageAccepted(LaneId, MessageNonce), + /// Messages in the inclusive range have been delivered to the bridged chain. + MessagesDelivered(LaneId, MessageNonce, MessageNonce), + /// Messages in the inclusive range have been processed by the bridged chain. + MessagesProcessed(LaneId, MessageNonce, MessageNonce), + } +); + +decl_module! { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + /// Deposit one of this module's events by using the default implementation. + fn deposit_event() = default; + + /// Send message over lane. + #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + pub fn send_message( + origin, + lane_id: LaneId, + payload: T::Payload, + ) { + let _ = ensure_signed(origin)?; + let mut lane = outbound_lane::(lane_id); + let nonce = lane.send_message(payload); + lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); + + Self::deposit_event(Event::MessageAccepted(lane_id, nonce)); + } + } +} + +impl, I: Instance> Module { + // ========================================================================================= + // === Exposed mutables ==================================================================== + // ========================================================================================= + + /// Receive new TRUSTED lane messages. + /// + /// Trusted here means that the function itself doesn't check whether message has actually + /// been sent through the other end of the channel. We only check that we are receiving + /// and processing messages in order here. + /// + /// Messages vector is required to be sorted by nonce within each lane. Otherise messages + /// will be rejected. + pub fn receive_messages(messages: Vec>) -> MessageNonce { + let mut correct_messages = 0; + let mut processor = T::OnMessageReceived::default(); + for message in messages { + let mut lane = inbound_lane::(message.key.lane_id); + if lane.receive_message(message.key.nonce, message.payload, &mut processor) { + correct_messages += 1; + } + } + + correct_messages + } + + /// Process stored lane messages. + /// + /// Stops processing either when all messages are processed, or when processor returns + /// MessageResult::NotProcessed. + pub fn process_lane_messages(lane_id: &LaneId, processor: &mut impl OnMessageReceived) { + inbound_lane::(*lane_id).process_messages(processor); + } + + /// Receive TRUSTED proof of message receival. + /// + /// Trusted here means that the function itself doesn't check whether the bridged chain has + /// actually received these messages. + /// + /// The caller may break the channel by providing `latest_received_nonce` that is larger + /// than actual one. Not-yet-sent messages may be pruned in this case. + pub fn confirm_receival(lane_id: &LaneId, latest_received_nonce: MessageNonce) { + let mut lane = outbound_lane::(*lane_id); + let received_range = lane.confirm_receival(latest_received_nonce); + + if let Some(received_range) = received_range { + Self::deposit_event(Event::MessagesDelivered(*lane_id, received_range.0, received_range.1)); + } + } + + /// Receive TRUSTED proof of message processing. + /// + /// Trusted here means that the function itself doesn't check whether the bridged chain has + /// actually processed these messages. + pub fn confirm_processing(lane_id: &LaneId, latest_processed_nonce: MessageNonce) { + let mut lane = outbound_lane::(*lane_id); + let processed_range = lane.confirm_processing(latest_processed_nonce); + + if let Some(processed_range) = processed_range { + Self::deposit_event(Event::MessagesProcessed(*lane_id, processed_range.0, processed_range.1)); + } + } +} + +/// Creates new inbound lane object, backed by runtime storage. +fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { + InboundLane::new(RuntimeInboundLaneStorage { + lane_id, + _phantom: Default::default(), + }) +} + +/// Creates new outbound lane object, backed by runtime storage. +fn outbound_lane, I: Instance>(lane_id: LaneId) -> OutboundLane> { + OutboundLane::new(RuntimeOutboundLaneStorage { + lane_id, + _phantom: Default::default(), + }) +} + +/// Runtime inbound lane storage. +struct RuntimeInboundLaneStorage { + lane_id: LaneId, + _phantom: PhantomData<(T, I)>, +} + +impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { + type Payload = T::Payload; + + fn id(&self) -> LaneId { + self.lane_id + } + + fn data(&self) -> InboundLaneData { + InboundLanes::::get(&self.lane_id) + } + + fn set_data(&mut self, data: InboundLaneData) { + InboundLanes::::insert(&self.lane_id, data) + } + + fn message(&self, nonce: &MessageNonce) -> Option { + InboundMessages::::get(MessageKey { + lane_id: self.lane_id, + nonce: *nonce, + }) + } + + fn save_message(&mut self, nonce: MessageNonce, payload: T::Payload) { + InboundMessages::::insert( + MessageKey { + lane_id: self.lane_id, + nonce, + }, + payload, + ); + } + + fn remove_message(&mut self, nonce: &MessageNonce) { + InboundMessages::::remove(MessageKey { + lane_id: self.lane_id, + nonce: *nonce, + }); + } +} + +/// Runtime outbound lane storage. +struct RuntimeOutboundLaneStorage { + lane_id: LaneId, + _phantom: PhantomData<(T, I)>, +} + +impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorage { + type Payload = T::Payload; + + fn id(&self) -> LaneId { + self.lane_id + } + + fn data(&self) -> OutboundLaneData { + OutboundLanes::::get(&self.lane_id) + } + + fn set_data(&mut self, data: OutboundLaneData) { + OutboundLanes::::insert(&self.lane_id, data) + } + + #[cfg(test)] + fn message(&self, nonce: &MessageNonce) -> Option { + OutboundMessages::::get(MessageKey { + lane_id: self.lane_id, + nonce: *nonce, + }) + } + + fn save_message(&mut self, nonce: MessageNonce, payload: T::Payload) { + OutboundMessages::::insert( + MessageKey { + lane_id: self.lane_id, + nonce, + }, + payload, + ); + } + + fn remove_message(&mut self, nonce: &MessageNonce) { + OutboundMessages::::remove(MessageKey { + lane_id: self.lane_id, + nonce: *nonce, + }); + } +} diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs new file mode 100644 index 0000000000000..5512490751906 --- /dev/null +++ b/modules/message-lane/src/mock.rs @@ -0,0 +1,121 @@ +// Copyright 2019-2020 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 . + +use bp_message_lane::{LaneId, Message, MessageResult, OnMessageReceived}; +use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; +use sp_core::H256; +use sp_runtime::{ + testing::Header as SubstrateHeader, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +use crate::Trait; + +pub type AccountId = u64; +pub type TestPayload = u64; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct TestRuntime; + +mod message_lane { + pub use crate::Event; +} + +impl_outer_event! { + pub enum TestEvent for TestRuntime { + frame_system, + message_lane, + } +} + +impl_outer_origin! { + pub enum Origin for TestRuntime where system = frame_system {} +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = SubstrateHeader; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = (); + type SystemWeightInfo = (); +} + +parameter_types! { + pub const MaxMessagesToPruneAtOnce: u64 = 10; +} + +impl Trait for TestRuntime { + type Event = TestEvent; + type Payload = TestPayload; + type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type OnMessageReceived = TestMessageProcessor; +} + +/// Lane that we're using in tests. +pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; + +/// Regular message payload that is not PAYLOAD_TO_QUEUE. +pub const REGULAR_PAYLOAD: TestPayload = 0; + +/// All messages with this payload are queued by TestMessageProcessor. +pub const PAYLOAD_TO_QUEUE: TestPayload = 42; + +/// Message processor that immediately handles all messages except messages with PAYLOAD_TO_QUEUE payload. +#[derive(Debug, Default)] +pub struct TestMessageProcessor; + +impl OnMessageReceived for TestMessageProcessor { + fn on_message_received(&mut self, message: Message) -> MessageResult { + if message.payload == PAYLOAD_TO_QUEUE { + MessageResult::NotProcessed(message) + } else { + MessageResult::Processed + } + } +} + +/// Run message lane test. +pub fn run_test(test: impl FnOnce() -> T) -> T { + sp_io::TestExternalities::new(Default::default()).execute_with(test) +} diff --git a/modules/message-lane/src/outbound_lane.rs b/modules/message-lane/src/outbound_lane.rs new file mode 100644 index 0000000000000..7357dbd410830 --- /dev/null +++ b/modules/message-lane/src/outbound_lane.rs @@ -0,0 +1,271 @@ +// Copyright 2019-2020 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 . + +//! Everything about outgoing messages sending. + +use bp_message_lane::{LaneId, MessageNonce, OutboundLaneData}; + +/// Outbound lane storage. +pub trait OutboundLaneStorage { + /// Message payload. + type Payload; + + /// Lane id. + fn id(&self) -> LaneId; + /// Get lane data from the storage. + fn data(&self) -> OutboundLaneData; + /// Update lane data in the storage. + fn set_data(&mut self, data: OutboundLaneData); + /// Returns saved outbound message payload. + #[cfg(test)] + fn message(&self, nonce: &MessageNonce) -> Option; + /// Save outbound message in the storage. + fn save_message(&mut self, nonce: MessageNonce, payload: Self::Payload); + /// Remove outbound message from the storage. + fn remove_message(&mut self, nonce: &MessageNonce); +} + +/// Outbound messages lane. +pub struct OutboundLane { + storage: S, +} + +impl OutboundLane { + /// Create new inbound lane backed by given storage. + pub fn new(storage: S) -> Self { + OutboundLane { storage } + } + + /// Send message over lane. + /// + /// Returns new message nonce. + pub fn send_message(&mut self, payload: S::Payload) -> MessageNonce { + let mut data = self.storage.data(); + let nonce = data.latest_generated_nonce + 1; + data.latest_generated_nonce = nonce; + + self.storage.save_message(nonce, payload); + self.storage.set_data(data); + + nonce + } + + /// Confirm message receival. + /// + /// Returns `None` if confirmation is wrong/duplicate. + /// Returns `Some` with inclusive ranges of message nonces that have been received. + pub fn confirm_receival(&mut self, latest_received_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> { + let mut data = self.storage.data(); + if latest_received_nonce <= data.latest_received_nonce || latest_received_nonce > data.latest_generated_nonce { + return None; + } + + let prev_latest_received_nonce = data.latest_received_nonce; + data.latest_received_nonce = latest_received_nonce; + self.storage.set_data(data); + + Some((prev_latest_received_nonce + 1, latest_received_nonce)) + } + + /// Confirm message processing. + /// + /// Returns `None` if confirmation is wrong/duplicate. + /// Returns `Some` with inclusive ranges of message nonces that have been processed. + pub fn confirm_processing(&mut self, latest_processed_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> { + let mut data = self.storage.data(); + // wait for recieval confirmation first + if latest_processed_nonce <= data.latest_processed_nonce || latest_processed_nonce > data.latest_received_nonce + { + return None; + } + + let prev_latest_processed_nonce = data.latest_processed_nonce; + data.latest_processed_nonce = latest_processed_nonce; + self.storage.set_data(data); + + Some((prev_latest_processed_nonce + 1, latest_processed_nonce)) + } + + /// Prune at most `max_messages_to_prune` already received messages. + /// + /// Returns number of pruned messages. + pub fn prune_messages(&mut self, max_messages_to_prune: MessageNonce) -> MessageNonce { + let mut pruned_messages = 0; + let mut anything_changed = false; + let mut data = self.storage.data(); + while pruned_messages < max_messages_to_prune && data.oldest_unpruned_nonce <= data.latest_received_nonce { + self.storage.remove_message(&data.oldest_unpruned_nonce); + + anything_changed = true; + pruned_messages += 1; + data.oldest_unpruned_nonce += 1; + } + + if anything_changed { + self.storage.set_data(data); + } + + pruned_messages + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + mock::{run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, + outbound_lane, + }; + + #[test] + fn send_message_works() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + assert_eq!(lane.storage.data().latest_generated_nonce, 0); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 1); + assert!(lane.storage.message(&1).is_some()); + assert_eq!(lane.storage.data().latest_generated_nonce, 1); + }); + } + + #[test] + fn confirm_receival_works() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 1); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 2); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 3); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + assert_eq!(lane.confirm_receival(3), Some((1, 3))); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 3); + }); + } + + #[test] + fn confirm_receival_rejects_nonce_lesser_than_latest_received() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + assert_eq!(lane.confirm_receival(3), Some((1, 3))); + assert_eq!(lane.confirm_receival(3), None); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 3); + + assert_eq!(lane.confirm_receival(2), None); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 3); + }); + } + + #[test] + fn confirm_receival_rejects_nonce_larger_than_last_generated() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + assert_eq!(lane.confirm_receival(10), None); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + }); + } + + #[test] + fn confirm_processing_works() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 1); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 2); + assert_eq!(lane.send_message(REGULAR_PAYLOAD), 3); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 0); + assert_eq!(lane.confirm_receival(3), Some((1, 3))); + assert_eq!(lane.confirm_processing(2), Some((1, 2))); + assert_eq!(lane.storage.data().latest_processed_nonce, 2); + assert_eq!(lane.confirm_processing(3), Some((3, 3))); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 3); + }); + } + + #[test] + fn confirm_processing_rejects_nonce_lesser_than_latest_processed() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 0); + assert_eq!(lane.confirm_receival(3), Some((1, 3))); + assert_eq!(lane.confirm_processing(3), Some((1, 3))); + assert_eq!(lane.confirm_processing(3), None); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 3); + + assert_eq!(lane.confirm_processing(2), None); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 3); + }); + } + + #[test] + fn confirm_processing_rejects_nonce_larger_than_last_received() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 0); + assert_eq!(lane.confirm_processing(2), None); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_processed_nonce, 0); + }); + } + + #[test] + fn prune_messages_works() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + // when lane is empty, nothing is pruned + assert_eq!(lane.prune_messages(100), 0); + assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); + // when nothing is confirmed, nothing is pruned + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + lane.send_message(REGULAR_PAYLOAD); + assert_eq!(lane.prune_messages(100), 0); + assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); + // after confirmation, some messages are received + assert_eq!(lane.confirm_receival(2), Some((1, 2))); + assert_eq!(lane.prune_messages(100), 2); + assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3); + // after last message is confirmed, everything is pruned + assert_eq!(lane.confirm_receival(3), Some((3, 3))); + assert_eq!(lane.prune_messages(100), 1); + assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4); + }); + } +} diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml new file mode 100644 index 0000000000000..b937e452ac72f --- /dev/null +++ b/primitives/message-lane/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "bp-message-lane" +description = "Primitives of message lane module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } + +# Substrate Based Dependencies + +[dependencies.sp-api] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate.git" + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-api/std" +] diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs new file mode 100644 index 0000000000000..fce49679469db --- /dev/null +++ b/primitives/message-lane/src/lib.rs @@ -0,0 +1,135 @@ +// Copyright 2019-2020 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 . + +//! Primitives for sending and receiving Substrate <-> Substrate messages. + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Generated by `DecodeLimit::decode_with_depth_limit` +#![allow(clippy::unnecessary_mut_passed)] + +use codec::{Decode, Encode}; +use sp_api::decl_runtime_apis; + +/// Lane identifier. +pub type LaneId = [u8; 4]; + +/// Message nonce. Valid messages will never have 0 nonce. +pub type MessageNonce = u64; + +/// Message key (unique message identifier) as it is stored in the storage. +#[derive(Encode, Decode, Clone)] +pub struct MessageKey { + /// ID of the message lane. + pub lane_id: LaneId, + /// Message nonce. + pub nonce: MessageNonce, +} + +/// Message as it is stored in the storage. +#[derive(Encode, Decode, Clone)] +pub struct Message { + /// Message key. + pub key: MessageKey, + /// Message payload. + pub payload: Payload, +} + +/// Message processing result. +pub enum MessageResult { + /// Message has been processed and should not be queued. + Processed, + /// Message has NOT been processed and should be queued for processing later. + NotProcessed(Message), +} + +/// Called when inbound message is received. +pub trait OnMessageReceived { + /// Called when inbound message is received. + /// + /// It is up to the implementers of this trait to determine whether the message + /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. And, + /// if message is invalid, then it should be dropped immediately (by returning + /// `MessageResult::Processed`), or it'll block the lane forever. + fn on_message_received(&mut self, message: Message) -> MessageResult; +} + +/// Inbound lane data. +#[derive(Encode, Decode, Clone)] +pub struct InboundLaneData { + /// Nonce of oldest message that we haven't processed yet. May point to not-yet-received message if + /// lane is currently empty. + pub oldest_unprocessed_nonce: MessageNonce, + /// Nonce of latest message that we have received from bridged chain. + pub latest_received_nonce: MessageNonce, +} + +impl Default for InboundLaneData { + fn default() -> Self { + InboundLaneData { + // it is 1 because we're processing everything in [oldest_unprocessed_nonce; latest_received_nonce] + oldest_unprocessed_nonce: 1, + latest_received_nonce: 0, + } + } +} + +/// Outbound lane data. +#[derive(Encode, Decode, Clone)] +pub struct OutboundLaneData { + /// Nonce of oldest message that we haven't yet pruned. May point to not-yet-generated message if + /// all sent messages are already pruned. + pub oldest_unpruned_nonce: MessageNonce, + /// Nonce of latest message, received by bridged chain. + pub latest_received_nonce: MessageNonce, + /// Nonce of latest message, processed by bridged chain. + pub latest_processed_nonce: MessageNonce, + /// Nonce of latest message, generated by us. + pub latest_generated_nonce: MessageNonce, +} + +impl Default for OutboundLaneData { + fn default() -> Self { + OutboundLaneData { + // it is 1 because we're pruning everything in [oldest_unpruned_nonce; latest_received_nonce] + oldest_unpruned_nonce: 1, + latest_received_nonce: 0, + latest_processed_nonce: 0, + latest_generated_nonce: 0, + } + } +} + +decl_runtime_apis! { + /// Outbound message lane API. + pub trait OutboundLaneApi { + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, processed by bridged chain. + fn latest_processed_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API. + pub trait InboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, processed by given lane. + fn latest_processed_nonce(lane: LaneId) -> MessageNonce; + } +} From 17aa01081655e0a7316aa395f774e3c26d675d6a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 3 Sep 2020 00:49:51 +0300 Subject: [PATCH 0147/1210] Custom RPC methods for DummyOrdered pallet (#317) * RPC for DummyOrdered * add test for RPC * proof returned by RPC is Vec<>>.encode() * retrieval -> receiving * bp-runtime crate * bp-runtime supports no_std * cargo fmt --all * jsonrpc_core::BoxFuture * Update modules/message-lane/rpc/Cargo.toml Co-authored-by: Hernando Castano * Update modules/message-lane/rpc/src/lib.rs Co-authored-by: Hernando Castano * messageLane_ prefix for RPC methods * Update primitives/runtime/Cargo.toml Co-authored-by: Hernando Castano * Update primitives/runtime/src/lib.rs Co-authored-by: Hernando Castano * Update modules/message-lane/rpc/src/lib.rs Co-authored-by: Hernando Castano * Update modules/message-lane/rpc/src/lib.rs Co-authored-by: Hernando Castano * Update modules/message-lane/rpc/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/node/node/Cargo.toml | 1 + modules/message-lane/rpc/Cargo.toml | 56 +++++ modules/message-lane/rpc/src/error.rs | 59 ++++++ modules/message-lane/rpc/src/lib.rs | 281 ++++++++++++++++++++++++++ primitives/runtime/Cargo.toml | 11 + primitives/runtime/src/lib.rs | 25 +++ 6 files changed, 433 insertions(+) create mode 100644 modules/message-lane/rpc/Cargo.toml create mode 100644 modules/message-lane/rpc/src/error.rs create mode 100644 modules/message-lane/rpc/src/lib.rs create mode 100644 primitives/runtime/Cargo.toml create mode 100644 primitives/runtime/src/lib.rs diff --git a/bin/node/node/Cargo.toml b/bin/node/node/Cargo.toml index 4834c783c8570..c163f8e89b77f 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/node/Cargo.toml @@ -16,6 +16,7 @@ bp-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.11" +pallet-message-lane-rpc = { version = "0.1.0", path = "../../../modules/message-lane/rpc" } structopt = "0.3.17" [dependencies.bridge-node-runtime] diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml new file mode 100644 index 0000000000000..83c41604ad1ec --- /dev/null +++ b/modules/message-lane/rpc/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "pallet-message-lane-rpc" +description = "Module that provides RPC methods specific to message-lane pallet." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +bp-runtime = { path = "../../../primitives/runtime" } +bp-message-lane = { path = "../../../primitives/message-lane" } +derive_more = "0.99.2" +futures = { version = "0.3.5", features = ["compat"] } +jsonrpc-core = "14.2.0" +jsonrpc-core-client = "14.2.0" +jsonrpc-derive = "14.2.1" + +# Substrate Based Dependencies + +[dependencies.sc-client-api] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-blockchain] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-core] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-state-machine] +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-trie] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies] +async-std = "1.6.2" + +[dev-dependencies.substrate-test-runtime-client] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" diff --git a/modules/message-lane/rpc/src/error.rs b/modules/message-lane/rpc/src/error.rs new file mode 100644 index 0000000000000..74fd829fcdb3b --- /dev/null +++ b/modules/message-lane/rpc/src/error.rs @@ -0,0 +1,59 @@ +// Copyright 2019-2020 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 . + +//! Possible errors and results of message-lane RPC calls. + +/// Future Result type. +pub type FutureResult = jsonrpc_core::BoxFuture; + +/// State RPC errors. +#[derive(Debug, derive_more::Display, derive_more::From)] +pub enum Error { + /// When unknown instance id is passed. + #[display(fmt = "Message lane instance is unknown")] + UnknownInstance, + /// Client error. + #[display(fmt = "Client error: {}", _0)] + Client(Box), +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::UnknownInstance => None, + Error::Client(ref err) => Some(&**err), + } + } +} + +impl From for jsonrpc_core::Error { + fn from(e: Error) -> Self { + const UNKNOW_INSTANCE_CODE: i64 = 1; + + match e { + Error::UnknownInstance => jsonrpc_core::Error { + code: jsonrpc_core::ErrorCode::ServerError(UNKNOW_INSTANCE_CODE), + message: "Unknown instance passed".into(), + data: None, + }, + Error::Client(e) => jsonrpc_core::Error { + code: jsonrpc_core::ErrorCode::InternalError, + message: format!("Unknown error occured: {}", e), + data: Some(format!("{:?}", e).into()), + }, + } + } +} diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs new file mode 100644 index 0000000000000..3d0a0f484a1fd --- /dev/null +++ b/modules/message-lane/rpc/src/lib.rs @@ -0,0 +1,281 @@ +// Copyright 2019-2020 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 . + +//! Module that provides RPC methods specific to message-lane pallet. + +use crate::error::{Error, FutureResult}; + +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::InstanceId; +use futures::{FutureExt, TryFutureExt}; +use jsonrpc_core::futures::Future as _; +use jsonrpc_derive::rpc; +use sc_client_api::Backend as BackendT; +use sp_blockchain::{Error as BlockchainError, HeaderBackend}; +use sp_core::{storage::StorageKey, Bytes}; +use sp_runtime::{codec::Encode, generic::BlockId, traits::Block as BlockT}; +use sp_state_machine::prove_read; +use sp_trie::StorageProof; +use std::sync::Arc; + +mod error; + +/// Trie-based storage proof that the message(s) with given key(s) have been sent by the bridged chain. +/// SCALE-encoded trie nodes array `Vec>`. +pub type MessagesProof = Bytes; + +/// Trie-based storage proof that the message(s) with given key(s) have been received by the bridged chain. +/// SCALE-encoded trie nodes array `Vec>`. +pub type MessagesReceivingProof = Bytes; + +/// Trie-based storage proof that the message(s) with given key(s) have been processed by the bridged chain. +/// SCALE-encoded trie nodes array `Vec>`. +pub type MessagesProcessingProof = Bytes; + +/// Runtime adapter. +pub trait Runtime: Send + Sync + 'static { + /// Return runtime storage key for given message. May return None if instance is unknown. + fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option; + /// Return runtime storage key for inbound lane state. May return None if instance is unknown. + fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option; +} + +/// Provides RPC methods for interacting with message-lane pallet. +#[rpc] +pub trait MessageLaneApi { + /// Returns proof-of-message(s) in given inclusive range. + #[rpc(name = "messageLane_proveMessages")] + fn prove_messages( + &self, + instance: InstanceId, + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + block: Option, + ) -> FutureResult; + + /// Returns proof-of-message(s) receiving. + #[rpc(name = "messageLane_proveMessagesReceiving")] + fn prove_messages_receiving( + &self, + instance: InstanceId, + lane: LaneId, + block: Option, + ) -> FutureResult; + + /// Returns proof-of-message(s) processing. + #[rpc(name = "messageLane_proveMessagesProcessing")] + fn prove_messages_processing( + &self, + instance: InstanceId, + lane: LaneId, + block: Option, + ) -> FutureResult; +} + +/// Implements the MessageLaneApi trait for interacting with message lanes. +pub struct MessageLaneRpcHandler { + backend: Arc, + runtime: Arc, + _phantom: std::marker::PhantomData, +} + +impl MessageLaneRpcHandler { + /// Creates new mesage lane RPC handler. + pub fn new(backend: Arc, runtime: Arc) -> Self { + Self { + backend, + runtime, + _phantom: Default::default(), + } + } +} + +impl MessageLaneApi for MessageLaneRpcHandler +where + Block: BlockT, + Backend: BackendT + 'static, + R: Runtime, +{ + fn prove_messages( + &self, + instance: InstanceId, + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + block: Option, + ) -> FutureResult { + let runtime = self.runtime.clone(); + Box::new( + prove_keys_read( + self.backend.clone(), + block, + (begin..=end).map(move |nonce| runtime.message_key(&instance, &lane, nonce)), + ) + .boxed() + .compat() + .map(serialize_storage_proof) + .map_err(Into::into), + ) + } + + fn prove_messages_receiving( + &self, + instance: InstanceId, + lane: LaneId, + block: Option, + ) -> FutureResult { + Box::new( + prove_keys_read( + self.backend.clone(), + block, + vec![self.runtime.inbound_lane_data_key(&instance, &lane)], + ) + .boxed() + .compat() + .map(serialize_storage_proof) + .map_err(Into::into), + ) + } + + fn prove_messages_processing( + &self, + instance: InstanceId, + lane: LaneId, + block: Option, + ) -> FutureResult { + Box::new( + prove_keys_read( + self.backend.clone(), + block, + vec![self.runtime.inbound_lane_data_key(&instance, &lane)], + ) + .boxed() + .compat() + .map(serialize_storage_proof) + .map_err(Into::into), + ) + } +} + +async fn prove_keys_read( + backend: Arc, + block: Option, + keys: impl IntoIterator>, +) -> Result +where + Block: BlockT, + Backend: BackendT + 'static, +{ + let block = unwrap_or_best(&*backend, block); + let state = backend.state_at(BlockId::Hash(block)).map_err(blockchain_err)?; + let keys = keys + .into_iter() + .map(|key| key.ok_or(Error::UnknownInstance).map(|key| key.0)) + .collect::, _>>()?; + let storage_proof = prove_read(state, keys) + .map_err(BlockchainError::Execution) + .map_err(blockchain_err)?; + Ok(storage_proof) +} + +fn serialize_storage_proof(proof: StorageProof) -> Bytes { + let raw_nodes: Vec> = proof.iter_nodes().map(Into::into).collect(); + raw_nodes.encode().into() +} + +fn unwrap_or_best(backend: &impl BackendT, block: Option) -> Block::Hash { + match block { + Some(block) => block, + None => backend.blockchain().info().best_hash, + } +} + +fn blockchain_err(err: BlockchainError) -> Error { + Error::Client(Box::new(err)) +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::Blake2Hasher; + use sp_runtime::{codec::Decode, traits::Header as HeaderT}; + use substrate_test_runtime_client::{ + runtime::Block, Backend, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, + }; + + const TEST_INSTANCE: InstanceId = [0, 0, 0, 1]; + const TEST_LANE: LaneId = [0, 0, 0, 1]; + + fn test_key() -> StorageKey { + StorageKey(sp_core::storage::well_known_keys::CODE.to_vec()) + } + + struct TestRuntimeAdapter; + + impl Runtime for TestRuntimeAdapter { + fn message_key(&self, instance: &InstanceId, _lane: &LaneId, _nonce: MessageNonce) -> Option { + if *instance == TEST_INSTANCE { + Some(test_key()) + } else { + None + } + } + + fn inbound_lane_data_key(&self, instance: &InstanceId, _lane: &LaneId) -> Option { + if *instance == TEST_INSTANCE { + Some(test_key()) + } else { + None + } + } + } + + fn test_handler() -> MessageLaneRpcHandler { + let builder = TestClientBuilder::new(); + let (_, backend) = builder.build_with_backend(); + + MessageLaneRpcHandler::new(backend, Arc::new(TestRuntimeAdapter)) + } + + #[test] + fn storage_proof_is_actually_generated() { + // the only thing we actually care here is that RPC actually generates storage proof + // that can be verified from runtime + + // proof is generated by RPC + let handler = test_handler(); + let proof = handler + .prove_messages(TEST_INSTANCE, TEST_LANE, 1, 3, None) + .wait() + .unwrap(); + + // proof is then relayed + checked by runtime (sp_trie supports no_std) + // (storage root is known to underlying bridge pallet) + let root = *handler + .backend + .blockchain() + .header(BlockId::Number(0)) + .unwrap() + .unwrap() + .state_root(); + let proof = StorageProof::new(Decode::decode(&mut &proof[..]).unwrap()); + let trie_db = proof.into_memory_db::(); + let checked_storage_value = + sp_trie::read_trie_value::, _>(&trie_db, &root, &test_key().0).unwrap(); + assert!(checked_storage_value.is_some()); + } +} diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml new file mode 100644 index 0000000000000..84dd53e4d380c --- /dev/null +++ b/primitives/runtime/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "bp-runtime" +description = "Primitives that may be used at (bridges) runtime level." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[features] +default = ["std"] +std = [] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs new file mode 100644 index 0000000000000..fa41b2126a43d --- /dev/null +++ b/primitives/runtime/src/lib.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2020 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 . + +//! Primitives that may be used at (bridges) runtime level. + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Id of deployed module instance. We have a bunch of pallets that may be used in +/// different bridges. E.g. message-lane 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]; From c30854a3bb2b38da7818d8fa9adfd3c8749b06d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 4 Sep 2020 13:09:49 +0200 Subject: [PATCH 0148/1210] Initial version of `Call::decode` dispatch. (#300) * Initial version of call dispatch. * cargo fmt --all * Remove unused stuff. * cargo fmt --all * weight is part of msg + events * should_fail_on_weight_mismatch * plug into runtime * cargo fmt --all * fix benchmarks compilation? * expected/actual values in events * return actual weight from MessageDispatch::dispatch() * MessageOrigin -> InstanceId + move bridge_account_id to bp-runtime * fix benchmarks again * cargo fmt --all * clippy Co-authored-by: Svyatoslav Nikolsky --- bin/node/runtime/Cargo.toml | 12 + bin/node/runtime/src/lib.rs | 7 + modules/call-dispatch/Cargo.toml | 62 +++++ modules/call-dispatch/src/lib.rs | 348 +++++++++++++++++++++++++ primitives/message-dispatch/Cargo.toml | 18 ++ primitives/message-dispatch/src/lib.rs | 40 +++ primitives/runtime/Cargo.toml | 16 +- primitives/runtime/src/lib.rs | 21 ++ 8 files changed, 523 insertions(+), 1 deletion(-) create mode 100644 modules/call-dispatch/Cargo.toml create mode 100644 modules/call-dispatch/src/lib.rs create mode 100644 primitives/message-dispatch/Cargo.toml create mode 100644 primitives/message-dispatch/src/lib.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 5deeff830845f..7713c621dc012 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -45,6 +45,11 @@ version = "0.1.0" default-features = false path = "../../../modules/ethereum" +[dependencies.pallet-bridge-call-dispatch] +version = "0.1.0" +default-features = false +path = "../../../modules/call-dispatch" + [dependencies.pallet-bridge-currency-exchange] version = "0.1.0" default-features = false @@ -216,6 +221,11 @@ version = "0.1.0" default-features = false path = "../../../primitives/header-chain" +[dependencies.bp-message-lane] +version = "0.1.0" +default-features = false +path = "../../../primitives/message-lane" + # Dev Dependencies [dev-dependencies.libsecp256k1] @@ -240,6 +250,7 @@ default = ["std"] std = [ "bp-currency-exchange/std", "bp-eth-poa/std", + "bp-message-lane/std", "codec/std", "frame-benchmarking/std", "frame-executive/std", @@ -248,6 +259,7 @@ std = [ "frame-system/std", "pallet-aura/std", "pallet-balances/std", + "pallet-bridge-call-dispatch/std", "pallet-bridge-currency-exchange/std", "pallet-bridge-eth-poa/std", "pallet-grandpa/std", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7fedc3e35469a..3bd039e3a52f6 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -268,6 +268,12 @@ impl pallet_bridge_currency_exchange::Trait for Runtime { type DepositInto = DepositInto; } +impl pallet_bridge_call_dispatch::Trait for Runtime { + type Event = Event; + type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); + type Call = Call; +} + pub struct DepositInto; impl bp_currency_exchange::DepositInto for DepositInto { @@ -463,6 +469,7 @@ construct_runtime!( BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, + BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml new file mode 100644 index 0000000000000..838f0aa6a9b25 --- /dev/null +++ b/modules/call-dispatch/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "pallet-bridge-call-dispatch" +description = "A Substrate Runtime module that dispatches a bridge message, treating it simply as encoded Call" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } + +# Substrate Based Dependencies +[dependencies.frame-support] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-std] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-core] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-io] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[features] +default = ["std"] +std = [ + "bp-message-dispatch/std", + "bp-runtime/std", + "frame-support/std", + "frame-system/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs new file mode 100644 index 0000000000000..03da86ec0e4e2 --- /dev/null +++ b/modules/call-dispatch/src/lib.rs @@ -0,0 +1,348 @@ +// Copyright 2019-2020 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 . + +//! Runtime module which takes care of dispatching messages received over the bridge. +//! +//! The messages are interpreted directly as runtime `Call`s, we attempt to decode +//! them and then dispatch as usualy. +//! To prevent compatibility issues, the calls have to include `spec_version` as well +//! which is being checked before dispatch. +//! +//! In case of succesful dispatch event is emitted. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +use bp_message_dispatch::{MessageDispatch, Weight}; +use bp_runtime::{bridge_account_id, InstanceId, CALL_DISPATCH_MODULE_PREFIX}; +use frame_support::{ + decl_event, decl_module, + dispatch::{Dispatchable, Parameter}, + traits::Get, + weights::{extract_actual_weight, GetDispatchInfo}, +}; +use sp_runtime::DispatchResult; + +/// Spec version type. +pub type SpecVersion = u32; + +// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) +/// Weight of single deposit_event() call. +const DEPOSIT_EVENT_WEIGHT: Weight = 0; + +/// The module configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + /// Id of the message. Whenever message is passed to the dispatch module, it emits + /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if + /// it comes from message-lane module. + type MessageId: Parameter; + /// The overarching dispatch call type. + type Call: Parameter + + GetDispatchInfo + + Dispatchable< + Origin = ::Origin, + PostInfo = frame_support::dispatch::PostDispatchInfo, + >; +} + +decl_event!( + pub enum Event where + ::MessageId, + { + /// Message has been rejected by dispatcher because of spec version mismatch. + /// Last two arguments are: expected and passed spec version. + MessageVersionSpecMismatch(InstanceId, MessageId, SpecVersion, SpecVersion), + /// Message has been rejected by dispatcher because of weight mismatch. + /// Last two arguments are: expected and passed call weight. + MessageWeightMismatch(InstanceId, MessageId, Weight, Weight), + /// Message has been dispatched with given result. + MessageDispatched(InstanceId, MessageId, DispatchResult), + } +); + +decl_module! { + /// Call Dispatch FRAME Pallet. + pub struct Module for enum Call where origin: T::Origin { + /// Deposit one of this module's events by using the default implementation. + fn deposit_event() = default; + } +} + +impl MessageDispatch for Module { + type Message = (SpecVersion, Weight, ::Call); + + fn dispatch(bridge: InstanceId, id: T::MessageId, message: Self::Message) -> Weight { + let (spec_version, weight, call) = message; + + // verify spec version + // (we want it to be the same, because otherwise we may decode Call improperly) + let expected_version = ::Version::get().spec_version; + if spec_version != expected_version { + frame_support::debug::trace!( + "Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}", + bridge, + id, + expected_version, + spec_version, + ); + Self::deposit_event(Event::::MessageVersionSpecMismatch( + bridge, + id, + expected_version, + spec_version, + )); + return DEPOSIT_EVENT_WEIGHT; + } + + // verify weight + // (we want passed weight to be at least equal to pre-dispatch weight of the call + // because otherwise Calls may be dispatched at lower price) + let dispatch_info = call.get_dispatch_info(); + let expected_weight = dispatch_info.weight; + if weight < expected_weight { + frame_support::debug::trace!( + "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", + bridge, + id, + expected_weight, + weight, + ); + Self::deposit_event(Event::::MessageWeightMismatch(bridge, id, expected_weight, weight)); + return DEPOSIT_EVENT_WEIGHT; + } + + // finally dispatch message + let origin_account = bridge_account_id(bridge, CALL_DISPATCH_MODULE_PREFIX); + let dispatch_result = call.dispatch(frame_system::RawOrigin::Signed(origin_account).into()); + let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); + frame_support::debug::trace!( + "Message {:?}/{:?} has been dispatched. Result: {:?}", + bridge, + id, + dispatch_result, + ); + + Self::deposit_event(Event::::MessageDispatched( + bridge, + id, + dispatch_result.map(drop).map_err(|e| e.error), + )); + + actual_call_weight + DEPOSIT_EVENT_WEIGHT + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::{impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; + use frame_system::{EventRecord, Phase}; + use sp_core::H256; + use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + DispatchError, Perbill, + }; + + type AccountId = u64; + type CallDispatch = Module; + type System = frame_system::Module; + + type MessageId = [u8; 4]; + + #[derive(Clone, Eq, PartialEq)] + pub struct TestRuntime; + + mod call_dispatch { + pub use crate::Event; + } + + impl_outer_event! { + pub enum TestEvent for TestRuntime { + frame_system, + call_dispatch, + } + } + + impl_outer_origin! { + pub enum Origin for TestRuntime where system = frame_system {} + } + + impl_outer_dispatch! { + pub enum Call for TestRuntime where origin: Origin { + frame_system::System, + call_dispatch::CallDispatch, + } + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = Call; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = TestEvent; + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = (); + type SystemWeightInfo = (); + } + + impl Trait for TestRuntime { + type Event = TestEvent; + type MessageId = MessageId; + type Call = Call; + } + + fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + sp_io::TestExternalities::new(t) + } + + #[test] + fn should_succesfuly_dispatch_remark() { + new_test_ext().execute_with(|| { + let origin = b"ethb".to_owned(); + let id = [0; 4]; + let message = ( + 0, + 1_000_000_000, + Call::System(>::remark(vec![1, 2, 3])), + ); + + System::set_block_number(1); + CallDispatch::dispatch(origin, id, message); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageDispatched(origin, id, Ok(()))), + topics: vec![], + }], + ); + }); + } + + #[test] + fn should_fail_on_spec_version_mismatch() { + new_test_ext().execute_with(|| { + let origin = b"ethb".to_owned(); + let id = [0; 4]; + let message = ( + 69, + 1_000_000, + Call::System(>::remark(vec![1, 2, 3])), + ); + + System::set_block_number(1); + CallDispatch::dispatch(origin, id, message); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageVersionSpecMismatch( + origin, id, 0, 69, + )), + topics: vec![], + }], + ); + }); + } + + #[test] + fn should_fail_on_weight_mismatch() { + new_test_ext().execute_with(|| { + let origin = b"ethb".to_owned(); + let id = [0; 4]; + let message = ( + 0, + 0, + Call::System(>::remark(vec![1, 2, 3])), + ); + + System::set_block_number(1); + CallDispatch::dispatch(origin, id, message); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( + origin, id, 1305000, 0, + )), + topics: vec![], + }], + ); + }); + } + + #[test] + fn should_dispatch_from_non_root_origin() { + new_test_ext().execute_with(|| { + let origin = b"ethb".to_owned(); + let id = [0; 4]; + let message = ( + 0, + 1_000_000, + Call::System(>::fill_block(Perbill::from_percent(10))), + ); + + System::set_block_number(1); + CallDispatch::dispatch(origin, id, message); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageDispatched( + origin, + id, + Err(DispatchError::BadOrigin) + )), + topics: vec![], + }], + ); + }); + } +} diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml new file mode 100644 index 0000000000000..a6bf4b7cc57dc --- /dev/null +++ b/primitives/message-dispatch/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "bp-message-dispatch" +description = "Primitives of bridge messages dispatch modules." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +bp-runtime = { path = "../runtime", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-runtime/std", + "codec/std", +] diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs new file mode 100644 index 0000000000000..04b40e597268f --- /dev/null +++ b/primitives/message-dispatch/src/lib.rs @@ -0,0 +1,40 @@ +// Copyright 2019-2020 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 . + +//! A common interface for all Bridge Message Dispatch modules. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +use bp_runtime::InstanceId; + +/// Message dispatch weight. +pub type Weight = u64; + +/// A generic trait to dispatch arbitrary messages delivered over the bridge. +pub trait MessageDispatch { + /// A type of the message to be dispatched. + type Message: codec::Decode; + + /// Dispatches the message internally. + /// + /// `bridge` indicates instance of deployed bridge where the message came from. + /// + /// `id` is a short unique if of the message. + /// + /// Returns post-dispatch (actual) message weight. + fn dispatch(bridge: InstanceId, id: MessageId, message: Self::Message) -> Weight; +} diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 84dd53e4d380c..a0c8cb035cac2 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -6,6 +6,20 @@ authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } + +# Substrate Based Dependencies + +[dependencies.sp-io] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + [features] default = ["std"] -std = [] +std = [ + "codec/std", + "sp-io/std", +] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index fa41b2126a43d..45097ea1b6756 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -18,8 +18,29 @@ #![cfg_attr(not(feature = "std"), no_std)] +use codec::{Decode, Encode}; +use sp_io::hashing::blake2_256; + +/// Call-dispatch module prefix. +pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; + /// Id of deployed module instance. We have a bunch of pallets that may be used in /// different bridges. E.g. message-lane 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]; + +/// Returns id of account that acts as "system" account of given bridge instance. +/// The `module_prefix` (arbitrary slice) may be used to generate module-level +/// "system" account, so you could have separate "system" accounts for currency +/// exchange, message dispatch and other modules. +/// +/// The account is not supposed to actually exists on the chain, or to have any funds. +/// It is only used to +pub fn bridge_account_id(bridge: InstanceId, module_prefix: &[u8]) -> AccountId +where + AccountId: Decode + Default, +{ + let entropy = (module_prefix, bridge).using_encoded(blake2_256); + AccountId::decode(&mut &entropy[..]).unwrap_or_default() +} From 2e2fc43d3f72fdbee308533694d8d4ec62b5e01b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Sep 2020 12:06:26 +0300 Subject: [PATCH 0149/1210] extract ShiftSessionManager into separate pallet (#342) --- bin/node/runtime/Cargo.toml | 6 + bin/node/runtime/src/lib.rs | 95 +--------- modules/shift-session-manager/Cargo.toml | 67 +++++++ modules/shift-session-manager/src/lib.rs | 213 +++++++++++++++++++++++ 4 files changed, 289 insertions(+), 92 deletions(-) create mode 100644 modules/shift-session-manager/Cargo.toml create mode 100644 modules/shift-session-manager/src/lib.rs diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 7713c621dc012..143c41a7a67a0 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -78,6 +78,11 @@ tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" +[dependencies.pallet-shift-session-manager] +version = "0.1.0" +default-features = false +path = "../../../modules/shift-session-manager" + [dependencies.pallet-sudo] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' @@ -264,6 +269,7 @@ std = [ "pallet-bridge-eth-poa/std", "pallet-grandpa/std", "pallet-randomness-collective-flip/std", + "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment/std", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 3bd039e3a52f6..92ee820f7cd15 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -35,7 +35,6 @@ pub mod benches; pub mod kovan; pub mod rialto; -use codec::{Decode, Encode}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -401,63 +400,14 @@ impl pallet_session::Trait for Runtime { type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = ShiftSessionManager; + type SessionManager = pallet_shift_session_manager::Module; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = (); type WeightInfo = (); } -pub struct ShiftSessionManager; - -impl ShiftSessionManager { - /// Select validators for session. - fn select_validators( - session_index: sp_staking::SessionIndex, - available_validators: &[AccountId], - ) -> Vec { - let available_validators_count = available_validators.len(); - let count = sp_std::cmp::max(1, 2 * available_validators_count / 3); - let offset = session_index as usize % available_validators_count; - let end = offset + count; - let session_validators = match end.overflowing_sub(available_validators_count) { - (wrapped_end, false) if wrapped_end != 0 => available_validators[offset..] - .iter() - .chain(available_validators[..wrapped_end].iter()) - .cloned() - .collect(), - _ => available_validators[offset..end].to_vec(), - }; - - session_validators - } -} - -impl pallet_session::SessionManager for ShiftSessionManager { - fn end_session(_: sp_staking::SessionIndex) {} - fn start_session(_: sp_staking::SessionIndex) {} - fn new_session(session_index: sp_staking::SessionIndex) -> Option> { - // can't access genesis config here :/ - if session_index == 0 || session_index == 1 { - return None; - } - - // the idea that on first call (i.e. when session 1 ends) we're reading current - // set of validators from session module (they are initial validators) and save - // in our 'local storage'. - // then for every session we select (deterministically) 2/3 of these initial - // validators to serve validators of new session - let available_validators = sp_io::storage::get(b":available_validators") - .and_then(|validators| Decode::decode(&mut &validators[..]).ok()) - .unwrap_or_else(|| { - let validators = >::validators(); - sp_io::storage::set(b":available_validators", &validators.encode()); - validators - }); - - Some(Self::select_validators(session_index, &available_validators)) - } -} +impl pallet_shift_session_manager::Trait for Runtime {} construct_runtime!( pub enum Runtime where @@ -479,6 +429,7 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Module, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, Session: pallet_session::{Module, Call, Storage, Event, Config}, + ShiftSessionManager: pallet_shift_session_manager::{Module}, } ); @@ -771,46 +722,6 @@ mod tests { use super::*; use bp_currency_exchange::DepositInto; - #[test] - fn shift_session_manager_works() { - let acc1 = AccountId::from([1u8; 32]); - let acc2 = AccountId::from([2u8; 32]); - let acc3 = AccountId::from([3u8; 32]); - let acc4 = AccountId::from([4u8; 32]); - let acc5 = AccountId::from([5u8; 32]); - let all_accs = vec![acc1.clone(), acc2.clone(), acc3.clone(), acc4.clone(), acc5.clone()]; - - // at least 1 validator is selected - assert_eq!( - ShiftSessionManager::select_validators(0, &[acc1.clone()]), - vec![acc1.clone()], - ); - - // at session#0, shift is also 0 - assert_eq!( - ShiftSessionManager::select_validators(0, &all_accs), - vec![acc1.clone(), acc2.clone(), acc3.clone()], - ); - - // at session#1, shift is also 1 - assert_eq!( - ShiftSessionManager::select_validators(1, &all_accs), - vec![acc2.clone(), acc3.clone(), acc4.clone()], - ); - - // at session#3, we're wrapping - assert_eq!( - ShiftSessionManager::select_validators(3, &all_accs), - vec![acc4, acc5, acc1.clone()], - ); - - // at session#5, we're starting from the beginning again - assert_eq!( - ShiftSessionManager::select_validators(5, &all_accs), - vec![acc1, acc2, acc3], - ); - } - fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) { let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::().unwrap().into(); ext.execute_with(|| { diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml new file mode 100644 index 0000000000000..706733e73fee3 --- /dev/null +++ b/modules/shift-session-manager/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = "pallet-shift-session-manager" +description = "A Substrate Runtime module that selects 2/3 of initial validators for every session" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } + +# Substrate Based Dependencies + +[dependencies.frame-support] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-session] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-core] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-staking] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-std] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-session/std", + "sp-core/std", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", +] diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs new file mode 100644 index 0000000000000..d2ca15d215999 --- /dev/null +++ b/modules/shift-session-manager/src/lib.rs @@ -0,0 +1,213 @@ +// Copyright 2019-2020 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 . + +//! Substrate session manager that selects 2/3 validators from initial set, +//! starting from session 2. + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{decl_module, decl_storage}; +use sp_std::prelude::*; + +/// The module configuration trait. +pub trait Trait: pallet_session::Trait {} + +decl_module! { + /// Shift session manager pallet. + pub struct Module for enum Call where origin: T::Origin {} +} + +decl_storage! { + trait Store for Module as ShiftSessionManager { + /// Validators of first two sessions. + InitialValidators: Option>; + } +} + +impl pallet_session::SessionManager for Module { + fn end_session(_: sp_staking::SessionIndex) {} + fn start_session(_: sp_staking::SessionIndex) {} + fn new_session(session_index: sp_staking::SessionIndex) -> Option> { + // we don't want to add even more fields to genesis config => just return None + if session_index == 0 || session_index == 1 { + return None; + } + + // the idea that on first call (i.e. when session 1 ends) we're reading current + // set of validators from session module (they are initial validators) and save + // in our 'local storage'. + // then for every session we select (deterministically) 2/3 of these initial + // validators to serve validators of new session + let available_validators = InitialValidators::::get().unwrap_or_else(|| { + let validators = >::validators(); + InitialValidators::::put(validators.clone()); + validators + }); + + Some(Self::select_validators(session_index, &available_validators)) + } +} + +impl Module { + /// Select validators for session. + fn select_validators( + session_index: sp_staking::SessionIndex, + available_validators: &[T::ValidatorId], + ) -> Vec { + let available_validators_count = available_validators.len(); + let count = sp_std::cmp::max(1, 2 * available_validators_count / 3); + let offset = session_index as usize % available_validators_count; + let end = offset + count; + let session_validators = match end.overflowing_sub(available_validators_count) { + (wrapped_end, false) if wrapped_end != 0 => available_validators[offset..] + .iter() + .chain(available_validators[..wrapped_end].iter()) + .cloned() + .collect(), + _ => available_validators[offset..end].to_vec(), + }; + + session_validators + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::sp_io::TestExternalities; + use frame_support::sp_runtime::{ + testing::{Header, UintAuthorityId}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, + Perbill, RuntimeAppPublic, + }; + use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; + use sp_core::H256; + + type AccountId = u64; + + #[derive(Clone, Eq, PartialEq)] + pub struct TestRuntime; + + impl_outer_origin! { + pub enum Origin for TestRuntime {} + } + + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Trait for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = (); + type SystemWeightInfo = (); + } + + parameter_types! { + pub const Period: u64 = 1; + pub const Offset: u64 = 0; + } + + impl pallet_session::Trait for TestRuntime { + type Event = (); + type ValidatorId = ::AccountId; + type ValidatorIdOf = ConvertInto; + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionManager = (); + type SessionHandler = TestSessionHandler; + type Keys = UintAuthorityId; + type DisabledValidatorsThreshold = (); + type WeightInfo = (); + } + + impl Trait for TestRuntime {} + + pub struct TestSessionHandler; + impl pallet_session::SessionHandler for TestSessionHandler { + const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; + + fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + + fn on_new_session(_: bool, _: &[(AccountId, Ks)], _: &[(AccountId, Ks)]) {} + + fn on_disabled(_: usize) {} + } + + fn new_test_ext() -> TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + pallet_session::GenesisConfig:: { + keys: vec![ + (1, 1, UintAuthorityId(1)), + (2, 2, UintAuthorityId(2)), + (3, 3, UintAuthorityId(3)), + (4, 4, UintAuthorityId(4)), + (5, 5, UintAuthorityId(5)), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + TestExternalities::new(t) + } + + #[test] + fn shift_session_manager_works() { + new_test_ext().execute_with(|| { + let all_accs = vec![1, 2, 3, 4, 5]; + + // at least 1 validator is selected + assert_eq!(Module::::select_validators(0, &[1]), vec![1],); + + // at session#0, shift is also 0 + assert_eq!(Module::::select_validators(0, &all_accs), vec![1, 2, 3],); + + // at session#1, shift is also 1 + assert_eq!(Module::::select_validators(1, &all_accs), vec![2, 3, 4],); + + // at session#3, we're wrapping + assert_eq!(Module::::select_validators(3, &all_accs), vec![4, 5, 1],); + + // at session#5, we're starting from the beginning again + assert_eq!(Module::::select_validators(5, &all_accs), vec![1, 2, 3],); + }); + } +} From 00bf8d51a0b450b089530c400cddd97a80d32275 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Sep 2020 12:08:00 +0300 Subject: [PATCH 0150/1210] resurrect substrate StorageProofChecker (#343) --- modules/substrate/Cargo.toml | 12 ++++++ modules/substrate/src/lib.rs | 2 + modules/substrate/src/storage_proof.rs | 51 ++++++++------------------ 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index d5ffb159d2222..40b7b0b894d59 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -24,6 +24,18 @@ tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" +[dev-dependencies.sp-core] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dev-dependencies.sp-state-machine] +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + [features] default = ["std"] std = [ diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 84fde5c57db2c..034c56a8a46ca 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -13,3 +13,5 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . + +mod storage_proof; diff --git a/modules/substrate/src/storage_proof.rs b/modules/substrate/src/storage_proof.rs index dfdc0c5787da8..40a1399695448 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/modules/substrate/src/storage_proof.rs @@ -14,29 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2017-2019 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. +// TODO: remove on actual use +#![allow(dead_code)] -// 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 . - -//! Logic for checking Parity Bridges Common storage proofs. +//! Logic for checking Substrate storage proofs. use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; -use sp_trie::{trie_types::TrieDB, MemoryDB, Trie}; - -pub(crate) type StorageProof = 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 @@ -57,27 +42,19 @@ where /// /// 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 { - let mut db = MemoryDB::default(); - for item in proof { - db.insert(EMPTY_PREFIX, &item); + let db = proof.into_memory_db(); + if !db.contains(&root, EMPTY_PREFIX) { + return Err(Error::StorageRootMismatch); } + 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>, Error> { - self.trie()? - .get(key) - .map(|value| value.map(|value| value.to_vec())) - .map_err(|_| Error::StorageValueUnavailable) - } - - fn trie(&self) -> Result, Error> { - TrieDB::new(&self.db, &self.root).map_err(|_| Error::StorageRootMismatch) + read_trie_value::, _>(&self.db, &self.root, key).map_err(|_| Error::StorageValueUnavailable) } } @@ -105,10 +82,12 @@ mod tests { (None, vec![(b"key11".to_vec(), Some(vec![0u8; 32]))]), ]); let root = backend.storage_root(std::iter::empty()).0; - let proof: StorageProof = prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) - .unwrap() - .iter_nodes() - .collect(); + let proof = StorageProof::new( + prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) + .unwrap() + .iter_nodes() + .collect(), + ); // check proof in runtime let checker = >::new(root, proof.clone()).unwrap(); From c05273923e1c170ce2ed1f93b8bb6a18ae60db26 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 11 Sep 2020 23:09:47 +0300 Subject: [PATCH 0151/1210] Make message-lane Event generic (#345) * make message-lane Event generic * cargo fmt --all * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- modules/message-lane/src/lib.rs | 22 +++++++++++++++++----- modules/message-lane/src/mock.rs | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 40517887e1579..0f581d0c659c3 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -49,7 +49,7 @@ mod mock; /// The module configuration trait pub trait Trait: frame_system::Trait { /// They overarching event type. - type Event: From + Into<::Event>; + type Event: From> + Into<::Event>; /// Message payload. type Payload: Parameter; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs @@ -75,13 +75,17 @@ decl_storage! { } decl_event!( - pub enum Event { + pub enum Event where + ::AccountId, + { /// Message has been accepted and is waiting to be delivered. MessageAccepted(LaneId, MessageNonce), /// Messages in the inclusive range have been delivered to the bridged chain. MessagesDelivered(LaneId, MessageNonce, MessageNonce), /// Messages in the inclusive range have been processed by the bridged chain. MessagesProcessed(LaneId, MessageNonce, MessageNonce), + /// Phantom member, never used. + Dummy(PhantomData<(AccountId, I)>), } ); @@ -102,7 +106,7 @@ decl_module! { let nonce = lane.send_message(payload); lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); - Self::deposit_event(Event::MessageAccepted(lane_id, nonce)); + Self::deposit_event(RawEvent::MessageAccepted(lane_id, nonce)); } } } @@ -153,7 +157,11 @@ impl, I: Instance> Module { let received_range = lane.confirm_receival(latest_received_nonce); if let Some(received_range) = received_range { - Self::deposit_event(Event::MessagesDelivered(*lane_id, received_range.0, received_range.1)); + Self::deposit_event(RawEvent::MessagesDelivered( + *lane_id, + received_range.0, + received_range.1, + )); } } @@ -166,7 +174,11 @@ impl, I: Instance> Module { let processed_range = lane.confirm_processing(latest_processed_nonce); if let Some(processed_range) = processed_range { - Self::deposit_event(Event::MessagesProcessed(*lane_id, processed_range.0, processed_range.1)); + Self::deposit_event(RawEvent::MessagesProcessed( + *lane_id, + processed_range.0, + processed_range.1, + )); } } } diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 5512490751906..b56489c96a280 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -38,7 +38,7 @@ mod message_lane { impl_outer_event! { pub enum TestEvent for TestRuntime { frame_system, - message_lane, + message_lane, } } From aec6f024405e1ded13a891f1d8a76ad6cc742d39 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2020 02:28:18 +0000 Subject: [PATCH 0152/1210] Bump serde from 1.0.115 to 1.0.116 (#348) --- bin/node/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 143c41a7a67a0..b613c857b4863 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -23,7 +23,7 @@ default-features = false features = ["hmac"] [dependencies.serde] -version = "1.0.115" +version = "1.0.116" optional = true features = ["derive"] From 4d4956f4ad5cc6047867e2a61fb1bda4205ebb60 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Sep 2020 12:12:19 +0300 Subject: [PATCH 0153/1210] Relay DummyOrdered messages (#318) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * DummyOrdered relay: initial commit * 1 ML file -> 3 files * extracted generic message race loop * uncommented race error procesing * lane loop tests * cargo fmt * moved HeaderId to utils.rs * restart lane loop on stall * message delivery strategy tests * removed obsolete code * clippy * Update relays/ethereum/src/message_lane_loop.rs Co-authored-by: Tomasz Drwięga * Update relays/ethereum/src/message_lane_loop.rs Co-authored-by: Tomasz Drwięga * added more races docs * Update relays/ethereum/src/message_race_delivery.rs Co-authored-by: Tomasz Drwięga * update docs * Update relays/ethereum/src/message_race_loop.rs Co-authored-by: Tomasz Drwięga * deal with TODOs * removed docs * docs * cargo fmt --all * Update relays/ethereum/src/message_race_loop.rs Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- relays/ethereum/src/ethereum_client.rs | 4 +- .../ethereum/src/ethereum_deploy_contract.rs | 2 +- relays/ethereum/src/ethereum_exchange.rs | 2 +- relays/ethereum/src/ethereum_types.rs | 3 +- relays/ethereum/src/exchange.rs | 6 +- relays/ethereum/src/headers.rs | 6 +- relays/ethereum/src/main.rs | 4 + relays/ethereum/src/message_lane.rs | 55 ++ relays/ethereum/src/message_lane_loop.rs | 591 ++++++++++++++++++ relays/ethereum/src/message_race_delivery.rs | 385 ++++++++++++ relays/ethereum/src/message_race_loop.rs | 359 +++++++++++ relays/ethereum/src/substrate_client.rs | 3 +- relays/ethereum/src/substrate_types.rs | 4 +- relays/ethereum/src/sync.rs | 3 +- relays/ethereum/src/sync_loop.rs | 86 +-- relays/ethereum/src/sync_loop_tests.rs | 6 +- relays/ethereum/src/sync_types.rs | 6 +- relays/ethereum/src/utils.rs | 109 +++- 18 files changed, 1540 insertions(+), 94 deletions(-) create mode 100644 relays/ethereum/src/message_lane.rs create mode 100644 relays/ethereum/src/message_lane_loop.rs create mode 100644 relays/ethereum/src/message_race_delivery.rs create mode 100644 relays/ethereum/src/message_race_loop.rs diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index ae7e630c33553..bfcb7d9cb2c9e 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -21,8 +21,8 @@ use crate::ethereum_types::{ use crate::rpc::{Ethereum, EthereumRpc}; use crate::rpc_errors::{EthereumNodeError, RpcError}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::{HeaderId, SubmittedHeaders}; -use crate::utils::MaybeConnectionError; +use crate::sync_types::SubmittedHeaders; +use crate::utils::{HeaderId, MaybeConnectionError}; use async_trait::async_trait; use codec::{Decode, Encode}; diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index cce91a5519b8d..94ce80706773f 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -21,7 +21,7 @@ use crate::instances::BridgeInstance; use crate::rpc::SubstrateRpc; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::HeaderId; +use crate::utils::HeaderId; use codec::{Decode, Encode}; use num_traits::Zero; diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index bcaebdd9c5179..b045b36356ff1 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -34,7 +34,7 @@ use crate::substrate_client::{ SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; use crate::substrate_types::into_substrate_ethereum_receipt; -use crate::sync_types::HeaderId; +use crate::utils::HeaderId; use async_trait::async_trait; use bp_currency_exchange::MaybeLockFundsTransaction; diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index 8dcfb00fc94c7..bdb960c8cd816 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -15,7 +15,8 @@ // along with Parity Bridges Common. If not, see . use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; -use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::utils::HeaderId; use codec::Encode; pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; diff --git a/relays/ethereum/src/exchange.rs b/relays/ethereum/src/exchange.rs index 89f30a2dae549..e236b9d3cf56e 100644 --- a/relays/ethereum/src/exchange.rs +++ b/relays/ethereum/src/exchange.rs @@ -54,7 +54,7 @@ pub trait SourceBlock { type Transaction: SourceTransaction; /// Return hash of the block. - fn id(&self) -> crate::sync_types::HeaderId; + fn id(&self) -> crate::utils::HeaderId; /// Return block transactions iterator. fn transactions(&self) -> Vec; } @@ -81,7 +81,7 @@ pub type TransactionOf

= <

::Block as SourceBlo pub type TransactionHashOf

= as SourceTransaction>::Hash; /// Header id. -pub type HeaderId

= crate::sync_types::HeaderId, BlockNumberOf

>; +pub type HeaderId

= crate::utils::HeaderId, BlockNumberOf

>; /// Source client API. #[async_trait] @@ -443,7 +443,7 @@ async fn wait_header_finalized( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::sync_types::HeaderId; + use crate::utils::HeaderId; use parking_lot::Mutex; use std::{ diff --git a/relays/ethereum/src/headers.rs b/relays/ethereum/src/headers.rs index 63c8e07351f8a..991d935548adf 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/ethereum/src/headers.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::sync_types::{HeaderId, HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::utils::HeaderId; + use linked_hash_map::LinkedHashMap; use num_traits::{One, Zero}; use std::{ @@ -777,7 +779,7 @@ fn queued_incomplete_header( pub(crate) mod tests { use super::*; use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, H256}; - use crate::sync_types::{HeaderId, QueuedHeader}; + use crate::sync_types::QueuedHeader; pub(crate) fn header(number: u64) -> QueuedHeader { QueuedHeader::new(Header { diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index a842c2b559b4f..82dfb08209c2e 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -27,6 +27,10 @@ mod exchange_loop; mod exchange_loop_metrics; mod headers; mod instances; +mod message_lane; +mod message_lane_loop; +mod message_race_delivery; +mod message_race_loop; mod metrics; mod rpc; mod rpc_errors; diff --git a/relays/ethereum/src/message_lane.rs b/relays/ethereum/src/message_lane.rs new file mode 100644 index 0000000000000..7ca8d2e9fb980 --- /dev/null +++ b/relays/ethereum/src/message_lane.rs @@ -0,0 +1,55 @@ +// Copyright 2019-2020 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 . + +//! One-way message lane types. Within single one-way lane we have three 'races' where we try to: +//! +//! 1) relay new messages from source to target node; +//! 2) relay proof-of-receiving from target to source node; +//! 3) relay proof-of-processing from target no source node. + +use crate::utils::HeaderId; + +use std::fmt::Debug; + +/// One-way message lane. +pub trait MessageLane { + /// Name of the messages source. + const SOURCE_NAME: &'static str; + /// Name of the messages target. + const TARGET_NAME: &'static str; + + /// Message nonce type. + type MessageNonce: Clone + Copy + Debug + Default + From + Ord + std::ops::Add; + + /// Messages proof. + type MessagesProof: Clone; + + /// Number of the source header. + type SourceHeaderNumber: Clone + Debug + Default + Ord + PartialEq; + /// Hash of the source header. + type SourceHeaderHash: Clone + Debug + Default + PartialEq; + + /// Number of the target header. + type TargetHeaderNumber: Clone + Debug + Default + Ord + PartialEq; + /// Hash of the target header. + type TargetHeaderHash: Clone + Debug + Default + PartialEq; +} + +/// Source header id within given one-way message lane. +pub type SourceHeaderIdOf

= HeaderId<

::SourceHeaderHash,

::SourceHeaderNumber>; + +/// Target header id within given one-way message lane. +pub type TargetHeaderIdOf

= HeaderId<

::TargetHeaderHash,

::TargetHeaderNumber>; diff --git a/relays/ethereum/src/message_lane_loop.rs b/relays/ethereum/src/message_lane_loop.rs new file mode 100644 index 0000000000000..03cc2929b3a70 --- /dev/null +++ b/relays/ethereum/src/message_lane_loop.rs @@ -0,0 +1,591 @@ +// Copyright 2019-2020 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 . + +//! Message delivery loop. Designed to work with message-lane pallet. +//! +//! Single relay instance delivers messages of single lane in single direction. +//! To serve two-way lane, you would need two instances of relay. +//! To serve N two-way lanes, you would need N*2 instances of relay. +//! +//! Please keep in mind that the best header in this file is actually best +//! finalized header. I.e. when talking about headers in lane context, we +//! only care about finalized headers. + +// Until there'll be actual message-lane in the runtime. +#![allow(dead_code)] + +use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; +use crate::message_race_delivery::run as run_message_delivery_race; +use crate::utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; + +use async_trait::async_trait; +use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; +use std::{fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; + +/// Source client trait. +#[async_trait(?Send)] +pub trait SourceClient: Clone { + /// Type of error this clients returns. + type Error: std::fmt::Debug + MaybeConnectionError; + + /// Try to reconnect to source node. + fn reconnect(self) -> Self; + + /// Returns state of the client. + async fn state(&self) -> Result, Self::Error>; + + /// Get nonce of instance of latest generated message. + async fn latest_generated_nonce( + &self, + id: SourceHeaderIdOf

, + ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error>; + + /// Prove messages in inclusive range [begin; end]. + async fn prove_messages( + &self, + id: SourceHeaderIdOf

, + nonces: RangeInclusive, + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error>; +} + +/// Target client trait. +#[async_trait(?Send)] +pub trait TargetClient: Clone { + /// Type of error this clients returns. + type Error: std::fmt::Debug + MaybeConnectionError; + + /// Try to reconnect to source node. + fn reconnect(self) -> Self; + + /// Returns state of the client. + async fn state(&self) -> Result, Self::Error>; + + /// Get nonce of latest message, which receival has been confirmed. + async fn latest_received_nonce( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error>; + + /// Submit messages proof. + async fn submit_messages_proof( + &self, + generated_at_header: SourceHeaderIdOf

, + nonces: RangeInclusive, + proof: P::MessagesProof, + ) -> Result, Self::Error>; +} + +/// State of the client. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct ClientState { + /// Best header id of this chain. + pub best_self: SelfHeaderId, + /// Best header id of the peer chain. + pub best_peer: PeerHeaderId, +} + +/// State of source client in one-way message lane. +pub type SourceClientState

= ClientState, TargetHeaderIdOf

>; + +/// State of target client in one-way message lane. +pub type TargetClientState

= ClientState, SourceHeaderIdOf

>; + +/// Both clients state. +#[derive(Debug, Default)] +pub struct ClientsState { + /// Source client state. + pub source: Option>, + /// Target client state. + pub target: Option>, +} + +/// Run message lane service loop. +pub fn run( + mut source_client: impl SourceClient

, + source_tick: Duration, + mut target_client: impl TargetClient

, + target_tick: Duration, + reconnect_delay: Duration, + stall_timeout: Duration, + exit_signal: impl Future, +) { + let mut local_pool = futures::executor::LocalPool::new(); + let exit_signal = exit_signal.shared(); + + local_pool.run_until(async move { + loop { + let result = run_until_connection_lost( + source_client.clone(), + source_tick, + target_client.clone(), + target_tick, + stall_timeout, + exit_signal.clone(), + ) + .await; + + match result { + Ok(()) => break, + Err(failed_client) => { + async_std::task::sleep(reconnect_delay).await; + if failed_client == FailedClient::Both || failed_client == FailedClient::Source { + source_client = source_client.reconnect(); + } + if failed_client == FailedClient::Both || failed_client == FailedClient::Target { + target_client = target_client.reconnect(); + } + } + } + + log::debug!( + target: "bridge", + "Restarting lane {} -> {}", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + } + }); +} + +/// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. +async fn run_until_connection_lost, TC: TargetClient

>( + source_client: SC, + source_tick: Duration, + target_client: TC, + target_tick: Duration, + stall_timeout: Duration, + exit_signal: impl Future, +) -> Result<(), FailedClient> { + let mut source_retry_backoff = retry_backoff(); + let mut source_client_is_online = false; + let mut source_state_required = true; + let source_state = source_client.state().fuse(); + let source_go_offline_future = futures::future::Fuse::terminated(); + let source_tick_stream = interval(source_tick).fuse(); + + let mut target_retry_backoff = retry_backoff(); + let mut target_client_is_online = false; + let mut target_state_required = true; + let target_state = target_client.state().fuse(); + let target_go_offline_future = futures::future::Fuse::terminated(); + let target_tick_stream = interval(target_tick).fuse(); + + let ( + (delivery_source_state_sender, delivery_source_state_receiver), + (delivery_target_state_sender, delivery_target_state_receiver), + ) = (unbounded(), unbounded()); + let delivery_race_loop = run_message_delivery_race( + source_client.clone(), + delivery_source_state_receiver, + target_client.clone(), + delivery_target_state_receiver, + stall_timeout, + ) + .fuse(); + + let exit_signal = exit_signal.fuse(); + + futures::pin_mut!( + source_state, + source_go_offline_future, + source_tick_stream, + target_state, + target_go_offline_future, + target_tick_stream, + delivery_race_loop, + exit_signal + ); + + loop { + futures::select! { + new_source_state = source_state => { + source_state_required = false; + + source_client_is_online = process_future_result( + new_source_state, + &mut source_retry_backoff, + |new_source_state| { + log::debug!( + target: "bridge", + "Received state from {} node: {:?}", + P::SOURCE_NAME, + new_source_state, + ); + let _ = delivery_source_state_sender.unbounded_send(new_source_state); + }, + &mut source_go_offline_future, + |delay| async_std::task::sleep(delay), + || format!("Error retrieving state from {} node", P::SOURCE_NAME), + ).fail_if_connection_error(FailedClient::Source)?; + }, + _ = source_go_offline_future => { + source_client_is_online = true; + }, + _ = source_tick_stream.next() => { + source_state_required = true; + }, + new_target_state = target_state => { + target_state_required = false; + + target_client_is_online = process_future_result( + new_target_state, + &mut target_retry_backoff, + |new_target_state| { + log::debug!( + target: "bridge", + "Received state from {} node: {:?}", + P::TARGET_NAME, + new_target_state, + ); + let _ = delivery_target_state_sender.unbounded_send(new_target_state); + }, + &mut target_go_offline_future, + |delay| async_std::task::sleep(delay), + || format!("Error retrieving state from {} node", P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + }, + _ = target_go_offline_future => { + target_client_is_online = true; + }, + _ = target_tick_stream.next() => { + target_state_required = true; + }, + + delivery_error = delivery_race_loop => { + match delivery_error { + Ok(_) => unreachable!("only ends with error; qed"), + Err(err) => return Err(err), + } + }, + + () = exit_signal => { + return Ok(()); + } + } + + if source_client_is_online && source_state_required { + log::debug!(target: "bridge", "Asking {} node about its state", P::SOURCE_NAME); + source_state.set(source_client.state().fuse()); + source_client_is_online = false; + } + + if target_client_is_online && target_state_required { + log::debug!(target: "bridge", "Asking {} node about its state", P::TARGET_NAME); + target_state.set(target_client.state().fuse()); + target_client_is_online = false; + } + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + use crate::utils::HeaderId; + use futures::stream::StreamExt; + use parking_lot::Mutex; + use std::sync::Arc; + + pub fn header_id(number: TestSourceHeaderNumber) -> HeaderId { + HeaderId(number, number) + } + + pub type TestMessageNonce = u64; + pub type TestMessagesProof = RangeInclusive; + + pub type TestSourceHeaderNumber = u64; + pub type TestSourceHeaderHash = u64; + + pub type TestTargetHeaderNumber = u64; + pub type TestTargetHeaderHash = u64; + + #[derive(Debug)] + pub enum TestError { + Logic, + Connection, + } + + impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + match *self { + TestError::Logic => false, + TestError::Connection => true, + } + } + } + + pub struct TestMessageLane; + + impl MessageLane for TestMessageLane { + const SOURCE_NAME: &'static str = "TestSource"; + const TARGET_NAME: &'static str = "TestTarget"; + + type MessageNonce = TestMessageNonce; + type MessagesProof = TestMessagesProof; + + type SourceHeaderNumber = TestSourceHeaderNumber; + type SourceHeaderHash = TestSourceHeaderHash; + + type TargetHeaderNumber = TestTargetHeaderNumber; + type TargetHeaderHash = TestTargetHeaderHash; + } + + #[derive(Debug, Default, Clone)] + pub struct TestClientData { + is_source_fails: bool, + is_source_reconnected: bool, + source_state: SourceClientState, + source_latest_generated_nonce: TestMessageNonce, + is_target_fails: bool, + is_target_reconnected: bool, + target_state: SourceClientState, + target_latest_received_nonce: TestMessageNonce, + submitted_messages_proofs: Vec, + } + + #[derive(Clone)] + pub struct TestSourceClient { + data: Arc>, + tick: Arc, + } + + #[async_trait(?Send)] + impl SourceClient for TestSourceClient { + type Error = TestError; + + fn reconnect(self) -> Self { + { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + data.is_source_reconnected = true; + } + self + } + + async fn state(&self) -> Result, Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + if data.is_source_fails { + return Err(TestError::Connection); + } + Ok(data.source_state.clone()) + } + + /// Get nonce of instance of latest generated message. + async fn latest_generated_nonce( + &self, + id: SourceHeaderIdOf, + ) -> Result<(SourceHeaderIdOf, TestMessageNonce), Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + if data.is_source_fails { + return Err(TestError::Connection); + } + Ok((id, data.source_latest_generated_nonce)) + } + + async fn prove_messages( + &self, + id: SourceHeaderIdOf, + nonces: RangeInclusive, + ) -> Result< + ( + SourceHeaderIdOf, + RangeInclusive, + TestMessagesProof, + ), + Self::Error, + > { + Ok((id, nonces.clone(), nonces)) + } + } + + #[derive(Clone)] + pub struct TestTargetClient { + data: Arc>, + tick: Arc, + } + + #[async_trait(?Send)] + impl TargetClient for TestTargetClient { + type Error = TestError; + + fn reconnect(self) -> Self { + { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + data.is_target_reconnected = true; + } + self + } + + async fn state(&self) -> Result, Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + if data.is_target_fails { + return Err(TestError::Connection); + } + Ok(data.target_state.clone()) + } + + async fn latest_received_nonce( + &self, + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, TestMessageNonce), Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + if data.is_target_fails { + return Err(TestError::Connection); + } + Ok((id, data.target_latest_received_nonce)) + } + + /// Submit messages proof. + async fn submit_messages_proof( + &self, + _generated_at_header: SourceHeaderIdOf, + nonces: RangeInclusive, + proof: TestMessagesProof, + ) -> Result, Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + if data.is_target_fails { + return Err(TestError::Connection); + } + data.target_state.best_self = + HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); + data.target_latest_received_nonce = *proof.end(); + data.submitted_messages_proofs.push(proof); + Ok(nonces) + } + } + + fn run_loop_test( + data: TestClientData, + source_tick: Arc, + target_tick: Arc, + exit_signal: impl Future, + ) -> TestClientData { + async_std::task::block_on(async { + let data = Arc::new(Mutex::new(data)); + + let source_client = TestSourceClient { + data: data.clone(), + tick: source_tick, + }; + let target_client = TestTargetClient { + data: data.clone(), + tick: target_tick, + }; + run( + source_client, + Duration::from_millis(100), + target_client, + Duration::from_millis(100), + Duration::from_millis(0), + Duration::from_secs(60), + exit_signal, + ); + + let result = data.lock().clone(); + result + }) + } + + #[test] + fn message_lane_loop_is_able_to_recover_from_connection_errors() { + // with this configuration, source client will return Err, making source client + // reconnect. Then the target client will fail with Err + reconnect. Then we finally + // able to deliver messages. + let (exit_sender, exit_receiver) = unbounded(); + let result = run_loop_test( + TestClientData { + is_source_fails: true, + source_state: ClientState { + best_self: HeaderId(0, 0), + best_peer: HeaderId(0, 0), + }, + source_latest_generated_nonce: 1, + target_state: ClientState { + best_self: HeaderId(0, 0), + best_peer: HeaderId(0, 0), + }, + target_latest_received_nonce: 0, + ..Default::default() + }, + Arc::new(|data: &mut TestClientData| { + if data.is_source_reconnected { + data.is_source_fails = false; + data.is_target_fails = true; + } + }), + Arc::new(move |data: &mut TestClientData| { + if data.is_target_reconnected { + data.is_target_fails = false; + } + if data.target_state.best_peer.0 < 10 { + data.target_state.best_peer = + HeaderId(data.target_state.best_peer.0 + 1, data.target_state.best_peer.0 + 1); + } + if !data.submitted_messages_proofs.is_empty() { + exit_sender.unbounded_send(()).unwrap(); + } + }), + exit_receiver.into_future().map(|(_, _)| ()), + ); + + assert_eq!(result.submitted_messages_proofs, vec![1..=1],); + } + + #[test] + fn message_lane_loop_works() { + // with this configuration, target client must first sync headers [1; 10] and + // then submit proof-of-messages [0; 10] at once + let (exit_sender, exit_receiver) = unbounded(); + let result = run_loop_test( + TestClientData { + source_state: ClientState { + best_self: HeaderId(10, 10), + best_peer: HeaderId(0, 0), + }, + source_latest_generated_nonce: 10, + target_state: ClientState { + best_self: HeaderId(0, 0), + best_peer: HeaderId(0, 0), + }, + target_latest_received_nonce: 0, + ..Default::default() + }, + Arc::new(|_: &mut TestClientData| {}), + Arc::new(move |data: &mut TestClientData| { + if data.target_state.best_peer.0 < 10 { + data.target_state.best_peer = + HeaderId(data.target_state.best_peer.0 + 1, data.target_state.best_peer.0 + 1); + } + if data + .submitted_messages_proofs + .last() + .map(|last| *last.end() == 10) + .unwrap_or(false) + { + exit_sender.unbounded_send(()).unwrap(); + } + }), + exit_receiver.into_future().map(|(_, _)| ()), + ); + + assert_eq!(result.submitted_messages_proofs, vec![1..=4, 5..=8, 9..=10],); + } +} diff --git a/relays/ethereum/src/message_race_delivery.rs b/relays/ethereum/src/message_race_delivery.rs new file mode 100644 index 0000000000000..a0039909789f9 --- /dev/null +++ b/relays/ethereum/src/message_race_delivery.rs @@ -0,0 +1,385 @@ +// Copyright 2019-2020 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. + +//! Message delivery race delivers proof-of-messages from lane.source to lane.target. + +use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; +use crate::message_lane_loop::{ + SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, + TargetClientState, +}; +use crate::message_race_loop::{MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; +use crate::utils::FailedClient; + +use async_trait::async_trait; +use futures::stream::FusedStream; +use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; + +/// Maximal number of messages to relay in single transaction. +const MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX: u32 = 4; + +/// Run message delivery race. +pub async fn run( + source_client: impl MessageLaneSourceClient

, + source_state_updates: impl FusedStream>, + target_client: impl MessageLaneTargetClient

, + target_state_updates: impl FusedStream>, + stall_timeout: Duration, +) -> Result<(), FailedClient> { + crate::message_race_loop::run( + MessageDeliveryRaceSource { + client: source_client, + _phantom: Default::default(), + }, + source_state_updates, + MessageDeliveryRaceTarget { + client: target_client, + _phantom: Default::default(), + }, + target_state_updates, + stall_timeout, + MessageDeliveryStrategy::

::default(), + ) + .await +} + +/// Message delivery race. +struct MessageDeliveryRace

(std::marker::PhantomData

); + +impl MessageRace for MessageDeliveryRace

{ + type SourceHeaderId = SourceHeaderIdOf

; + type TargetHeaderId = TargetHeaderIdOf

; + + type MessageNonce = P::MessageNonce; + type Proof = P::MessagesProof; + + fn source_name() -> String { + format!("{}::MessagesDelivery", P::SOURCE_NAME) + } + + fn target_name() -> String { + format!("{}::MessagesDelivery", P::TARGET_NAME) + } +} + +/// Message delivery race source, which is a source of the lane. +struct MessageDeliveryRaceSource { + client: C, + _phantom: PhantomData

, +} + +#[async_trait(?Send)] +impl SourceClient> for MessageDeliveryRaceSource +where + P: MessageLane, + C: MessageLaneSourceClient

, +{ + type Error = C::Error; + + async fn latest_nonce( + &self, + at_block: SourceHeaderIdOf

, + ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { + self.client.latest_generated_nonce(at_block).await + } + + async fn generate_proof( + &self, + at_block: SourceHeaderIdOf

, + nonces: RangeInclusive, + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { + self.client.prove_messages(at_block, nonces).await + } +} + +/// Message delivery race target, which is a target of the lane. +struct MessageDeliveryRaceTarget { + client: C, + _phantom: PhantomData

, +} + +#[async_trait(?Send)] +impl TargetClient> for MessageDeliveryRaceTarget +where + P: MessageLane, + C: MessageLaneTargetClient

, +{ + type Error = C::Error; + + async fn latest_nonce( + &self, + at_block: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { + self.client.latest_received_nonce(at_block).await + } + + async fn submit_proof( + &self, + generated_at_block: SourceHeaderIdOf

, + nonces: RangeInclusive, + proof: P::MessagesProof, + ) -> Result, Self::Error> { + self.client + .submit_messages_proof(generated_at_block, nonces, proof) + .await + } +} + +/// Message delivery strategy. +struct MessageDeliveryStrategy { + /// All queued nonces. + source_queue: VecDeque<(SourceHeaderIdOf

, P::MessageNonce)>, + /// Best nonce known to target node. + target_nonce: P::MessageNonce, + /// Unused generic types dump. + _phantom: PhantomData

, +} + +impl Default for MessageDeliveryStrategy

{ + fn default() -> Self { + MessageDeliveryStrategy { + source_queue: VecDeque::new(), + target_nonce: Default::default(), + _phantom: Default::default(), + } + } +} + +impl RaceStrategy, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof> + for MessageDeliveryStrategy

+{ + fn is_empty(&self) -> bool { + self.source_queue.is_empty() + } + + fn source_nonce_updated(&mut self, at_block: SourceHeaderIdOf

, nonce: P::MessageNonce) { + if nonce <= self.target_nonce { + return; + } + + match self.source_queue.back() { + Some((_, prev_nonce)) if *prev_nonce < nonce => (), + Some(_) => return, + None => (), + } + + self.source_queue.push_back((at_block, nonce)) + } + + fn target_nonce_updated( + &mut self, + nonce: P::MessageNonce, + race_state: &mut RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, + ) { + if nonce < self.target_nonce { + return; + } + + while let Some(true) = self + .source_queue + .front() + .map(|(_, source_nonce)| *source_nonce <= nonce) + { + self.source_queue.pop_front(); + } + + let need_to_select_new_nonces = race_state + .nonces_to_submit + .as_ref() + .map(|(_, nonces, _)| *nonces.end() <= nonce) + .unwrap_or(false); + if need_to_select_new_nonces { + race_state.nonces_to_submit = None; + } + + let need_new_nonces_to_submit = race_state + .nonces_submitted + .as_ref() + .map(|nonces| *nonces.end() <= nonce) + .unwrap_or(false); + if need_new_nonces_to_submit { + race_state.nonces_submitted = None; + } + + self.target_nonce = nonce; + } + + fn select_nonces_to_deliver( + &mut self, + race_state: &RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, + ) -> Option> { + // if we have already selected nonces that we want to submit, do nothing + if race_state.nonces_to_submit.is_some() { + return None; + } + + // if we already submitted some nonces, do nothing + if race_state.nonces_submitted.is_some() { + return None; + } + + // 1) we want to deliver all nonces, starting from `target_nonce + 1` + // 2) we want to deliver at most `MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX` nonces in this batch + // 3) we can't deliver new nonce until header, that has emitted this nonce, is finalized + // by target client + let nonces_begin = self.target_nonce + 1.into(); + let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; + let mut nonces_end = None; + for i in 0..MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX { + let nonce = nonces_begin + i.into(); + + // if queue is empty, we don't need to prove anything + let (first_queued_at, first_queued_nonce) = match self.source_queue.front() { + Some((first_queued_at, first_queued_nonce)) => (first_queued_at.clone(), *first_queued_nonce), + None => break, + }; + + // if header that has queued the message is not yet finalized at bridged chain, + // we can't prove anything + if first_queued_at.0 > best_header_at_target.0 { + break; + } + + // ok, we may deliver this nonce + nonces_end = Some(nonce); + + // probably remove it from the queue? + if nonce == first_queued_nonce { + self.source_queue.pop_front(); + } + } + + nonces_end.map(|nonces_end| RangeInclusive::new(nonces_begin, nonces_end)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::message_lane_loop::{ + tests::{header_id, TestMessageLane, TestMessageNonce, TestMessagesProof}, + ClientState, + }; + + #[test] + fn strategy_is_empty_works() { + let mut strategy = MessageDeliveryStrategy::::default(); + assert_eq!(strategy.is_empty(), true); + strategy.source_nonce_updated(header_id(1), 1); + assert_eq!(strategy.is_empty(), false); + } + + #[test] + fn source_nonce_is_never_lower_than_known_target_nonce() { + let mut strategy = MessageDeliveryStrategy::::default(); + strategy.target_nonce_updated(10, &mut Default::default()); + strategy.source_nonce_updated(header_id(1), 5); + assert_eq!(strategy.source_queue, vec![]); + } + + #[test] + fn source_nonce_is_never_lower_than_latest_known_source_nonce() { + let mut strategy = MessageDeliveryStrategy::::default(); + strategy.source_nonce_updated(header_id(1), 5); + strategy.source_nonce_updated(header_id(2), 3); + strategy.source_nonce_updated(header_id(2), 5); + assert_eq!(strategy.source_queue, vec![(header_id(1), 5)]); + } + + #[test] + fn target_nonce_is_never_lower_than_latest_known_target_nonce() { + let mut strategy = MessageDeliveryStrategy::::default(); + strategy.target_nonce_updated(10, &mut Default::default()); + strategy.target_nonce_updated(5, &mut Default::default()); + assert_eq!(strategy.target_nonce, 10); + } + + #[test] + fn updated_target_nonce_removes_queued_entries() { + let mut strategy = MessageDeliveryStrategy::::default(); + strategy.source_nonce_updated(header_id(1), 5); + strategy.source_nonce_updated(header_id(2), 10); + strategy.source_nonce_updated(header_id(3), 15); + strategy.source_nonce_updated(header_id(4), 20); + strategy.target_nonce_updated(15, &mut Default::default()); + assert_eq!(strategy.source_queue, vec![(header_id(4), 20)]); + } + + #[test] + fn selected_nonces_are_dropped_on_target_nonce_update() { + let mut state = RaceState::default(); + let mut strategy = MessageDeliveryStrategy::::default(); + state.nonces_to_submit = Some((header_id(1), 5..=10, 5..=10)); + strategy.target_nonce_updated(7, &mut state); + assert!(state.nonces_to_submit.is_some()); + strategy.target_nonce_updated(10, &mut state); + assert!(state.nonces_to_submit.is_none()); + } + + #[test] + fn submitted_nonces_are_dropped_on_target_nonce_update() { + let mut state = RaceState::default(); + let mut strategy = MessageDeliveryStrategy::::default(); + state.nonces_submitted = Some(5..=10); + strategy.target_nonce_updated(7, &mut state); + assert!(state.nonces_submitted.is_some()); + strategy.target_nonce_updated(10, &mut state); + assert!(state.nonces_submitted.is_none()); + } + + #[test] + fn nothing_is_selected_if_something_is_already_selected() { + let mut state = RaceState::default(); + let mut strategy = MessageDeliveryStrategy::::default(); + state.nonces_to_submit = Some((header_id(1), 1..=10, 1..=10)); + strategy.source_nonce_updated(header_id(1), 10); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn nothing_is_selected_if_something_is_already_submitted() { + let mut state = RaceState::default(); + let mut strategy = MessageDeliveryStrategy::::default(); + state.nonces_submitted = Some(1..=10); + strategy.source_nonce_updated(header_id(1), 10); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn select_nonces_to_deliver_works() { + let mut state = RaceState::<_, _, TestMessageNonce, TestMessagesProof>::default(); + let mut strategy = MessageDeliveryStrategy::::default(); + strategy.source_nonce_updated(header_id(1), 1); + strategy.source_nonce_updated(header_id(2), 2); + strategy.source_nonce_updated(header_id(3), 6); + strategy.source_nonce_updated(header_id(5), 8); + + state.target_state = Some(ClientState { + best_self: header_id(0), + best_peer: header_id(4), + }); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some(1..=4)); + strategy.target_nonce_updated(4, &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some(5..=6)); + strategy.target_nonce_updated(6, &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + + state.target_state = Some(ClientState { + best_self: header_id(0), + best_peer: header_id(5), + }); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some(7..=8)); + strategy.target_nonce_updated(8, &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } +} diff --git a/relays/ethereum/src/message_race_loop.rs b/relays/ethereum/src/message_race_loop.rs new file mode 100644 index 0000000000000..9d1657edb451e --- /dev/null +++ b/relays/ethereum/src/message_race_loop.rs @@ -0,0 +1,359 @@ +// Copyright 2019-2020 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. + +//! Loop that is serving single race within message lane. This could be +//! message delivery race, receiving confirmations race or processing +//! confirmations race. +//! +//! The idea of the race is simple - we have `nonce`-s on source and target +//! nodes. We're trying to prove that the source node has this nonce (and +//! associated data - like messages, lane state, etc) to the target node by +//! generating and submitting proof. + +// Until there'll be actual message-lane in the runtime. +#![allow(dead_code)] + +use crate::message_lane_loop::ClientState; +use crate::utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; + +use async_trait::async_trait; +use futures::{ + future::FutureExt, + stream::{FusedStream, StreamExt}, +}; +use std::{ + fmt::Debug, + ops::RangeInclusive, + time::{Duration, Instant}, +}; + +/// One of races within lane. +pub trait MessageRace { + /// Header id of the race source. + type SourceHeaderId: Debug + Clone + PartialEq; + /// Header id of the race source. + type TargetHeaderId: Debug + Clone + PartialEq; + + /// Message nonce used in the race. + type MessageNonce: Debug + Clone; + /// Proof that is generated and delivered in this race. + type Proof: Clone; + + /// Name of the race source. + fn source_name() -> String; + /// Name of the race target. + fn target_name() -> String; +} + +/// State of race source client. +type SourceClientState

= ClientState<

::SourceHeaderId,

::TargetHeaderId>; + +/// State of race target client. +type TargetClientState

= ClientState<

::TargetHeaderId,

::SourceHeaderId>; + +/// One of message lane clients, which is source client for the race. +#[async_trait(?Send)] +pub trait SourceClient { + /// Type of error this clients returns. + type Error: std::fmt::Debug + MaybeConnectionError; + + /// Return latest nonce that is known to the source client. + async fn latest_nonce( + &self, + at_block: P::SourceHeaderId, + ) -> Result<(P::SourceHeaderId, P::MessageNonce), Self::Error>; + /// Generate proof for delivering to the target client. + async fn generate_proof( + &self, + at_block: P::SourceHeaderId, + nonces: RangeInclusive, + ) -> Result<(P::SourceHeaderId, RangeInclusive, P::Proof), Self::Error>; +} + +/// One of message lane clients, which is target client for the race. +#[async_trait(?Send)] +pub trait TargetClient { + /// Type of error this clients returns. + type Error: std::fmt::Debug + MaybeConnectionError; + + /// Return latest nonce that is known to the target client. + async fn latest_nonce( + &self, + at_block: P::TargetHeaderId, + ) -> Result<(P::TargetHeaderId, P::MessageNonce), Self::Error>; + /// Submit proof to the target client. + async fn submit_proof( + &self, + generated_at_block: P::SourceHeaderId, + nonces: RangeInclusive, + proof: P::Proof, + ) -> Result, Self::Error>; +} + +/// Race strategy. +pub trait RaceStrategy { + /// Should return true if nothing has to be synced. + fn is_empty(&self) -> bool; + /// Called when latest nonce is updated at source node of the race. + fn source_nonce_updated(&mut self, at_block: SourceHeaderId, nonce: MessageNonce); + /// Called when latest nonce is updated at target node of the race. + fn target_nonce_updated( + &mut self, + nonce: MessageNonce, + race_state: &mut RaceState, + ); + /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated + /// data) from source to target node. + fn select_nonces_to_deliver( + &mut self, + race_state: &RaceState, + ) -> Option>; +} + +/// State of the race. +pub struct RaceState { + /// Source state, if known. + pub source_state: Option>, + /// Target state, if known. + pub target_state: Option>, + /// Range of nonces that we have selected to submit. + pub nonces_to_submit: Option<(SourceHeaderId, RangeInclusive, Proof)>, + /// Range of nonces that is currently submitted. + pub nonces_submitted: Option>, +} + +/// Run race loop until connection with target or source node is lost. +pub async fn run( + race_source: impl SourceClient

, + race_source_updated: impl FusedStream>, + race_target: impl TargetClient

, + race_target_updated: impl FusedStream>, + stall_timeout: Duration, + mut strategy: impl RaceStrategy, +) -> Result<(), FailedClient> { + let mut race_state = RaceState::default(); + let mut stall_countdown = Instant::now(); + + let mut source_retry_backoff = retry_backoff(); + let mut source_client_is_online = true; + let mut source_latest_nonce_required = false; + let source_latest_nonce = futures::future::Fuse::terminated(); + let source_generate_proof = futures::future::Fuse::terminated(); + let source_go_offline_future = futures::future::Fuse::terminated(); + + let mut target_retry_backoff = retry_backoff(); + let mut target_client_is_online = true; + let mut target_latest_nonce_required = false; + let target_latest_nonce = futures::future::Fuse::terminated(); + let target_submit_proof = futures::future::Fuse::terminated(); + let target_go_offline_future = futures::future::Fuse::terminated(); + + futures::pin_mut!( + race_source_updated, + source_latest_nonce, + source_generate_proof, + source_go_offline_future, + race_target_updated, + target_latest_nonce, + target_submit_proof, + target_go_offline_future, + ); + + loop { + futures::select! { + // when headers ids are updated + source_state = race_source_updated.next() => { + if let Some(source_state) = source_state { + if race_state.source_state.as_ref() != Some(&source_state) { + source_latest_nonce_required = true; + race_state.source_state = Some(source_state); + } + } + }, + target_state = race_target_updated.next() => { + if let Some(target_state) = target_state { + if race_state.target_state.as_ref() != Some(&target_state) { + target_latest_nonce_required = true; + race_state.target_state = Some(target_state); + } + } + }, + + // when nonces are updated + latest_nonce = source_latest_nonce => { + source_latest_nonce_required = false; + + source_client_is_online = process_future_result( + latest_nonce, + &mut source_retry_backoff, + |(at_block, latest_nonce)| { + log::debug!( + target: "bridge", + "Received latest nonce from {}: {:?}", + P::source_name(), + latest_nonce, + ); + + strategy.source_nonce_updated(at_block, latest_nonce); + }, + &mut source_go_offline_future, + |delay| async_std::task::sleep(delay), + || format!("Error retrieving latest nonce from {}", P::source_name()), + ).fail_if_connection_error(FailedClient::Source)?; + }, + latest_nonce = target_latest_nonce => { + target_latest_nonce_required = false; + + target_client_is_online = process_future_result( + latest_nonce, + &mut target_retry_backoff, + |(_, latest_nonce)| { + log::debug!( + target: "bridge", + "Received latest nonce from {}: {:?}", + P::target_name(), + latest_nonce, + ); + + strategy.target_nonce_updated(latest_nonce, &mut race_state); + }, + &mut target_go_offline_future, + |delay| async_std::task::sleep(delay), + || format!("Error retrieving latest nonce from {}", P::target_name()), + ).fail_if_connection_error(FailedClient::Target)?; + }, + + // proof generation and submission + proof = source_generate_proof => { + source_client_is_online = process_future_result( + proof, + &mut source_retry_backoff, + |(at_block, nonces_range, proof)| { + log::debug!( + target: "bridge", + "Received proof for nonces in range {:?} from {}", + nonces_range, + P::source_name(), + ); + + race_state.nonces_to_submit = Some((at_block, nonces_range, proof)); + }, + &mut source_go_offline_future, + |delay| async_std::task::sleep(delay), + || format!("Error generating proof at {}", P::source_name()), + ).fail_if_connection_error(FailedClient::Source)?; + }, + proof_submit_result = target_submit_proof => { + target_client_is_online = process_future_result( + proof_submit_result, + &mut target_retry_backoff, + |nonces_range| { + log::debug!( + target: "bridge", + "Successfully submitted proof of nonces {:?} to {}", + nonces_range, + P::target_name(), + ); + + race_state.nonces_to_submit = None; + race_state.nonces_submitted = Some(nonces_range); + }, + &mut target_go_offline_future, + |delay| async_std::task::sleep(delay), + || format!("Error submitting proof {}", P::target_name()), + ).fail_if_connection_error(FailedClient::Target)?; + } + } + + if stall_countdown.elapsed() > stall_timeout { + return Err(FailedClient::Both); + } else if race_state.nonces_to_submit.is_none() && race_state.nonces_submitted.is_none() && strategy.is_empty() + { + stall_countdown = Instant::now(); + } + + if source_client_is_online { + source_client_is_online = false; + + let nonces_to_deliver = race_state.source_state.as_ref().and_then(|source_state| { + strategy + .select_nonces_to_deliver(&race_state) + .map(|nonces_range| (source_state.best_self.clone(), nonces_range)) + }); + + if let Some((at_block, nonces_range)) = nonces_to_deliver { + log::debug!( + target: "bridge", + "Asking {} to prove nonces in range {:?}", + P::source_name(), + nonces_range, + ); + source_generate_proof.set(race_source.generate_proof(at_block, nonces_range).fuse()); + } else if source_latest_nonce_required { + log::debug!(target: "bridge", "Asking {} about latest generated message nonce", P::source_name()); + let at_block = race_state + .source_state + .as_ref() + .expect("source_latest_nonce_required is only true when source_state is Some; qed") + .best_self + .clone(); + source_latest_nonce.set(race_source.latest_nonce(at_block).fuse()); + } else { + source_client_is_online = true; + } + } + + if target_client_is_online { + target_client_is_online = false; + + if let Some((at_block, nonces_range, proof)) = race_state.nonces_to_submit.as_ref() { + log::debug!( + target: "bridge", + "Going to submit proof of messages in range {:?} to {} node", + nonces_range, + P::target_name(), + ); + target_submit_proof.set( + race_target + .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) + .fuse(), + ); + } + if target_latest_nonce_required { + log::debug!(target: "bridge", "Asking {} about latest nonce", P::target_name()); + let at_block = race_state + .target_state + .as_ref() + .expect("target_latest_nonce_required is only true when target_state is Some; qed") + .best_self + .clone(); + target_latest_nonce.set(race_target.latest_nonce(at_block).fuse()); + } else { + target_client_is_online = true; + } + } + } +} + +impl Default + for RaceState +{ + fn default() -> Self { + RaceState { + source_state: None, + target_state: None, + nonces_to_submit: None, + nonces_submitted: None, + } + } +} diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index c2bc56ac26992..7004dd8b14b97 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -19,7 +19,8 @@ use crate::instances::BridgeInstance; use crate::rpc::{Substrate, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock}; -use crate::sync_types::{HeaderId, SubmittedHeaders}; +use crate::sync_types::SubmittedHeaders; +use crate::utils::HeaderId; use async_trait::async_trait; use bp_eth_poa::Header as SubstrateEthereumHeader; diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index d03e8a86fdafa..fdd2880230ab1 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -17,7 +17,9 @@ use crate::ethereum_types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, }; -use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::utils::HeaderId; + use codec::Encode; pub use bp_eth_poa::{ diff --git a/relays/ethereum/src/sync.rs b/relays/ethereum/src/sync.rs index 2538b04c32bfc..e86e9be4ae339 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/ethereum/src/sync.rs @@ -310,7 +310,8 @@ pub mod tests { use super::*; use crate::ethereum_types::{EthereumHeadersSyncPipeline, H256}; use crate::headers::tests::{header, id}; - use crate::sync_types::{HeaderId, HeaderStatus}; + use crate::sync_types::HeaderStatus; + use crate::utils::HeaderId; fn side_hash(number: u64) -> H256 { H256::from_low_u64_le(1000 + number) diff --git a/relays/ethereum/src/sync_loop.rs b/relays/ethereum/src/sync_loop.rs index 4b82bfdf12113..62a9b06a83de4 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/ethereum/src/sync_loop.rs @@ -18,10 +18,11 @@ use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; use crate::sync::HeadersSyncParams; use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}; -use crate::utils::{format_ids, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError}; +use crate::utils::{ + format_ids, interval, process_future_result, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError, +}; use async_trait::async_trait; -use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; use std::{ @@ -44,9 +45,6 @@ const STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(5 * 60); /// Delay after we have seen update of best source header at target node, /// for us to treat sync stalled. ONLY when relay operates in backup mode. const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); -/// Delay after connection-related error happened before we'll try -/// reconnection again. -const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); /// Source client trait. #[async_trait] @@ -186,7 +184,7 @@ pub fn run>( &mut source_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving best header number from {}", P::SOURCE_NAME), - ); + ).is_ok(); }, source_new_header = source_new_header_future => { source_client_is_online = process_future_result( @@ -196,7 +194,7 @@ pub fn run>( &mut source_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving header from {} node", P::SOURCE_NAME), - ); + ).is_ok(); }, source_orphan_header = source_orphan_header_future => { source_client_is_online = process_future_result( @@ -206,7 +204,7 @@ pub fn run>( &mut source_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), - ); + ).is_ok(); }, source_extra = source_extra_future => { source_client_is_online = process_future_result( @@ -216,7 +214,7 @@ pub fn run>( &mut source_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), - ); + ).is_ok(); }, source_completion = source_completion_future => { source_client_is_online = process_future_result( @@ -226,7 +224,7 @@ pub fn run>( &mut source_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), - ); + ).is_ok(); }, source_client = source_go_offline_future => { source_client_is_online = true; @@ -277,7 +275,7 @@ pub fn run>( &mut target_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving best known header from {} node", P::TARGET_NAME), - ); + ).is_ok(); }, incomplete_headers_ids = target_incomplete_headers_future => { target_incomplete_headers_required = false; @@ -289,7 +287,7 @@ pub fn run>( &mut target_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), - ); + ).is_ok(); }, target_existence_status = target_existence_status_future => { target_client_is_online = process_future_result( @@ -301,7 +299,7 @@ pub fn run>( &mut target_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving existence status from {} node", P::TARGET_NAME), - ); + ).is_ok(); }, submitted_headers = target_submit_header_future => { // following line helps Rust understand the type of `submitted_headers` :/ @@ -329,7 +327,7 @@ pub fn run>( &mut target_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error submitting headers to {} node", P::TARGET_NAME), - ); + ).is_ok(); log::debug!(target: "bridge", "Header submit result: {}", submitted_headers_str); @@ -350,7 +348,7 @@ pub fn run>( &mut target_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error completing headers at {}", P::TARGET_NAME), - ); + ).is_ok(); }, target_extra_check_result = target_extra_check_future => { target_client_is_online = process_future_result( @@ -362,7 +360,7 @@ pub fn run>( &mut target_go_offline_future, |delay| async_std::task::sleep(delay), || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), - ); + ).is_ok(); }, target_client = target_go_offline_future => { target_client_is_online = true; @@ -557,62 +555,6 @@ pub fn run>( }); } -/// Stream that emits item every `timeout_ms` milliseconds. -fn interval(timeout: Duration) -> impl futures::Stream { - futures::stream::unfold((), move |_| async move { - async_std::task::sleep(timeout).await; - Some(((), ())) - }) -} - -/// Process result of the future from a client. -/// -/// Returns whether or not the client we're interacting with is online. In this context -/// what online means is that the client is currently not handling any other requests -/// that we've previously sent. -pub(crate) fn process_future_result( - result: Result, - retry_backoff: &mut ExponentialBackoff, - on_success: impl FnOnce(TResult), - go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, - go_offline: impl FnOnce(Duration) -> TGoOfflineFuture, - error_pattern: impl FnOnce() -> String, -) -> bool -where - TError: std::fmt::Debug + MaybeConnectionError, - TGoOfflineFuture: FutureExt, -{ - let mut client_is_online = false; - - match result { - Ok(result) => { - on_success(result); - retry_backoff.reset(); - client_is_online = true - } - Err(error) => { - let is_connection_error = error.is_connection_error(); - let retry_delay = if is_connection_error { - retry_backoff.reset(); - CONNECTION_ERROR_DELAY - } else { - retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY) - }; - go_offline_future.set(go_offline(retry_delay).fuse()); - - log::error!( - target: "bridge", - "{}: {:?}. Retrying in {}s", - error_pattern(), - error, - retry_delay.as_secs_f64(), - ); - } - } - - client_is_online -} - /// Print synchronization progress. fn print_sync_progress( progress_context: (Instant, Option, Option), diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/ethereum/src/sync_loop_tests.rs index 13206f4ad21db..8e2a4380ebbf7 100644 --- a/relays/ethereum/src/sync_loop_tests.rs +++ b/relays/ethereum/src/sync_loop_tests.rs @@ -16,9 +16,9 @@ #![cfg(test)] -use crate::sync_loop::{process_future_result, run, SourceClient, TargetClient}; -use crate::sync_types::{HeaderId, HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}; -use crate::utils::{retry_backoff, MaybeConnectionError}; +use crate::sync_loop::{run, SourceClient, TargetClient}; +use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}; +use crate::utils::{process_future_result, retry_backoff, HeaderId, MaybeConnectionError}; use async_trait::async_trait; use backoff::backoff::Backoff; diff --git a/relays/ethereum/src/sync_types.rs b/relays/ethereum/src/sync_types.rs index 4f9dbb3e6b26f..3970fb56291db 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/ethereum/src/sync_types.rs @@ -14,14 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::utils::format_ids; +use crate::utils::{format_ids, HeaderId}; use std::{ops::Deref, sync::Arc}; -/// Ethereum header Id. -#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] -pub struct HeaderId(pub Number, pub Hash); - /// Ethereum header synchronization status. #[derive(Debug, Clone, Copy, PartialEq)] pub enum HeaderStatus { diff --git a/relays/ethereum/src/utils.rs b/relays/ethereum/src/utils.rs index dfe3b3966fc9d..e149f1884b229 100644 --- a/relays/ethereum/src/utils.rs +++ b/relays/ethereum/src/utils.rs @@ -14,12 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use backoff::ExponentialBackoff; +use backoff::{backoff::Backoff, ExponentialBackoff}; +use futures::future::FutureExt; use std::time::Duration; /// Max delay after connection-unrelated error happened before we'll try the /// same request again. const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); +/// Delay after connection-related error happened before we'll try +/// reconnection again. +const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); /// Macro that returns (client, Err(error)) tuple from function if result is Err(error). #[macro_export] @@ -43,6 +47,10 @@ macro_rules! bail_on_arg_error { }; } +/// Ethereum header Id. +#[derive(Debug, Default, Clone, Copy, Eq, Hash, PartialEq)] +pub struct HeaderId(pub Number, pub Hash); + /// Error type that can signal connection errors. pub trait MaybeConnectionError { /// Returns true if error (maybe) represents connection error. @@ -114,3 +122,102 @@ pub fn format_ids(mut ids: impl ExactSizeIterator impl futures::Stream { + futures::stream::unfold((), move |_| async move { + async_std::task::sleep(timeout).await; + Some(((), ())) + }) +} + +/// Which client has caused error. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum FailedClient { + /// It is the source client who has caused error. + Source, + /// It is the target client who has caused error. + Target, + /// Both clients are failing, or we just encountered some other error that + /// should be treated like that. + Both, +} + +/// Future process result. +#[derive(Debug, Clone, Copy)] +pub enum ProcessFutureResult { + /// Future has been processed successfully. + Success, + /// Future has failed with non-connection error. + Failed, + /// Future has failed with connection error. + ConnectionFailed, +} + +impl ProcessFutureResult { + /// Returns true if result is Success. + pub fn is_ok(self) -> bool { + match self { + ProcessFutureResult::Success => true, + ProcessFutureResult::Failed | ProcessFutureResult::ConnectionFailed => false, + } + } + + /// Returns Ok(true) if future has succeeded. + /// Returns Ok(false) if future has failed with non-connection error. + /// Returns Err if future is `ConnectionFailed`. + pub fn fail_if_connection_error(self, failed_client: FailedClient) -> Result { + match self { + ProcessFutureResult::Success => Ok(true), + ProcessFutureResult::Failed => Ok(false), + ProcessFutureResult::ConnectionFailed => Err(failed_client), + } + } +} + +/// Process result of the future from a client. +pub(crate) fn process_future_result( + result: Result, + retry_backoff: &mut ExponentialBackoff, + on_success: impl FnOnce(TResult), + go_offline_future: &mut std::pin::Pin<&mut futures::future::Fuse>, + go_offline: impl FnOnce(Duration) -> TGoOfflineFuture, + error_pattern: impl FnOnce() -> String, +) -> ProcessFutureResult +where + TError: std::fmt::Debug + MaybeConnectionError, + TGoOfflineFuture: FutureExt, +{ + match result { + Ok(result) => { + on_success(result); + retry_backoff.reset(); + ProcessFutureResult::Success + } + Err(error) if error.is_connection_error() => { + log::error!( + target: "bridge", + "{}: {:?}. Going to restart", + error_pattern(), + error, + ); + + retry_backoff.reset(); + go_offline_future.set(go_offline(CONNECTION_ERROR_DELAY).fuse()); + ProcessFutureResult::ConnectionFailed + } + Err(error) => { + let retry_delay = retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY); + log::error!( + target: "bridge", + "{}: {:?}. Retrying in {}", + error_pattern(), + error, + retry_delay.as_secs_f64(), + ); + + go_offline_future.set(go_offline(retry_delay).fuse()); + ProcessFutureResult::Failed + } + } +} From cc6661d26b33a82517e4f62139700a38d1dbc7f8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Sep 2020 12:13:03 +0300 Subject: [PATCH 0154/1210] Prepare separate runtime for testing sub2sub bridge (#341) * renamed bin/node/runtime to bin/node/rialto-runtime * replaced bridge-node-runtime references with rialto-runtime references * separate folders for millau/rialto nodes+runtimes * extracted pallet-shift-session-manager * bridge-node -> bridge-node-runtime * uninstall previous rust (temp solution???) * fix dockerfile * cargo fmt * fix benchmarks check * fix benchmarks again * update LAST_RUST_UPDATE to clear the cache * changed runtime comments * move bin/node/* to bin/ * REVERT ME * Revert "REVERT ME" This reverts commit 7c335f946308ed11d9ed6ffec7c1c13dbe2743ed. * specify container name * REVERT ME * container_name -> hostname * fix typo * aliases * Revert "REVERT ME" This reverts commit 0e74af5f8430f1975a3fc924d8b52079f266bda1. * removed prefixes --- README.md | 20 +- bin/millau-node/Cargo.toml | 10 + bin/millau-node/src/main.rs | 24 + bin/millau-runtime/Cargo.toml | 254 ++++++++++ bin/{node/runtime => millau-runtime}/build.rs | 0 bin/millau-runtime/src/lib.rs | 475 ++++++++++++++++++ bin/node/{node => }/Cargo.toml | 26 +- bin/node/{node => }/build.rs | 0 bin/node/{node => }/src/chain_spec.rs | 12 +- bin/node/{node => }/src/cli.rs | 0 bin/node/{node => }/src/command.rs | 4 +- bin/node/{node/src/main.rs => src/lib.rs} | 6 +- bin/node/{node => }/src/service.rs | 6 +- bin/rialto-node/Cargo.toml | 16 + bin/rialto-node/src/main.rs | 24 + .../runtime => rialto-runtime}/Cargo.toml | 22 +- bin/rialto-runtime/build.rs | 26 + .../runtime => rialto-runtime}/src/benches.rs | 0 .../src/exchange.rs | 0 .../runtime => rialto-runtime}/src/kovan.rs | 0 .../runtime => rialto-runtime}/src/lib.rs | 6 +- .../runtime => rialto-runtime}/src/rialto.rs | 0 bin/{node => }/scripts/init.sh | 0 modules/ethereum-contract/builtin/Cargo.toml | 2 +- modules/ethereum-contract/builtin/src/lib.rs | 4 +- relays/ethereum/Cargo.toml | 4 +- relays/ethereum/src/ethereum_exchange.rs | 4 +- .../ethereum/src/ethereum_exchange_submit.rs | 2 +- relays/ethereum/src/instances.rs | 28 +- relays/ethereum/src/substrate_client.rs | 42 +- relays/ethereum/src/substrate_types.rs | 16 +- 31 files changed, 938 insertions(+), 95 deletions(-) create mode 100644 bin/millau-node/Cargo.toml create mode 100644 bin/millau-node/src/main.rs create mode 100644 bin/millau-runtime/Cargo.toml rename bin/{node/runtime => millau-runtime}/build.rs (100%) create mode 100644 bin/millau-runtime/src/lib.rs rename bin/node/{node => }/Cargo.toml (89%) rename bin/node/{node => }/build.rs (100%) rename bin/node/{node => }/src/chain_spec.rs (95%) rename bin/node/{node => }/src/cli.rs (100%) rename bin/node/{node => }/src/command.rs (98%) rename bin/node/{node/src/main.rs => src/lib.rs} (90%) rename bin/node/{node => }/src/service.rs (98%) create mode 100644 bin/rialto-node/Cargo.toml create mode 100644 bin/rialto-node/src/main.rs rename bin/{node/runtime => rialto-runtime}/Cargo.toml (93%) create mode 100644 bin/rialto-runtime/build.rs rename bin/{node/runtime => rialto-runtime}/src/benches.rs (100%) rename bin/{node/runtime => rialto-runtime}/src/exchange.rs (100%) rename bin/{node/runtime => rialto-runtime}/src/kovan.rs (100%) rename bin/{node/runtime => rialto-runtime}/src/lib.rs (99%) rename bin/{node/runtime => rialto-runtime}/src/rialto.rs (100%) rename bin/{node => }/scripts/init.sh (100%) diff --git a/README.md b/README.md index 1f426a860716a..744056faa1350 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ PoA chains to Substrate. We're working on expanding this functionality in the fu ## Contents - [Installation](#installation) - [Project Layout](#project-layout) -- [Bridge Node Runtime](#bridge-node-runtime) +- [Rialto Runtime](#rialto-runtime) - [Ethereum Node](#ethereum-node) - [Bridge Relay](#bridge-relay) - [Running the Bridge](#running-the-bridge) @@ -60,7 +60,7 @@ the `relays` which are used to pass messages between chains. │ └── substrate // 🚧 WIP 🚧 ``` -## Bridge Node Runtime +## Rialto Runtime The node runtime consists of several runtime modules, however not all of them are used at the same time. When running an Ethereum PoA to Substrate bridge the modules required are the Ethereum module and the currency exchange module. When running a Substrate to Substrate bridge the Substrate and @@ -170,7 +170,7 @@ First you'll need to build the bridge node and relay. This can be done as follow ```bash # In `parity-bridges-common` folder -cargo build -p bridge-node +cargo build -p rialto-bridge-node cargo build -p ethereum-poa-relay ``` @@ -204,7 +204,7 @@ chains it must be run last. ```bash # In `parity-bridges-common` folder ./scripts/run-openethereum-node.sh -./scripts/run-bridge-node.sh +./scripts/run-rialto-bridge-node.sh ./scripts/run-eth2sub-relay.sh ``` At this point you should see the relayer submitting blocks from the Ethereum chain @@ -221,7 +221,7 @@ docker build . -t bridge-relay-dev You can also build and run the Substrate based node as follows: ```bash -docker build . -t bridge-node-dev --build-arg PROJECT=bridge-node +docker build . -t bridge-node-dev --build-arg PROJECT=rialto-bridge-node ``` To run the Substrate node you can do the following: @@ -248,15 +248,15 @@ docker run -it poa-relay ``` By default the relayer is configured to connect to OpenEthereum `--dev` chain node and Substrate -`bridge-node` running in `--dev` mode. +`rialto-bridge-node` running in `--dev` mode. -To build the `bridge-node`: +To build the `rialto-bridge-node`: ```bash docker build \ https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ - -t bridge-node \ - --build-arg PROJECT=bridge-node -docker run -it bridge-node --dev + -t rialto-bridge-node \ + --build-arg PROJECT=rialto-bridge-node +docker run -it rialto-bridge-node --dev ``` And to build `OpenEthereum` with bridge support: diff --git a/bin/millau-node/Cargo.toml b/bin/millau-node/Cargo.toml new file mode 100644 index 0000000000000..646841abdc5de --- /dev/null +++ b/bin/millau-node/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "millau-bridge-node" +description = "Substrate node compatible with Millau runtime" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +bridge-node = { path = "../node", default-features = false, features = ["millau"] } diff --git a/bin/millau-node/src/main.rs b/bin/millau-node/src/main.rs new file mode 100644 index 0000000000000..6ce72ef75c823 --- /dev/null +++ b/bin/millau-node/src/main.rs @@ -0,0 +1,24 @@ +// Copyright 2019-2020 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 . + +//! Millau bridge node. + +#![warn(missing_docs)] + +/// Run node. +fn main() -> bridge_node::Result { + bridge_node::run() +} diff --git a/bin/millau-runtime/Cargo.toml b/bin/millau-runtime/Cargo.toml new file mode 100644 index 0000000000000..a6b2cb3f1d326 --- /dev/null +++ b/bin/millau-runtime/Cargo.toml @@ -0,0 +1,254 @@ +[package] +name = "millau-runtime" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +hex-literal = "0.3" + +[dependencies.codec] +package = "parity-scale-codec" +version = "1.3.1" +default-features = false +features = ["derive"] + +[dependencies.serde] +version = "1.0.115" +optional = true +features = ["derive"] + +# Substrate Dependencies +[dependencies.pallet-aura] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-balances] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-bridge-call-dispatch] +version = "0.1.0" +default-features = false +path = "../../modules/call-dispatch" + +[dependencies.pallet-message-lane] +version = "0.1.0" +default-features = false +path = "../../modules/message-lane" + +[dependencies.frame-support] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-grandpa] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-randomness-collective-flip] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-sudo] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-shift-session-manager] +version = "0.1.0" +default-features = false +path = "../../modules/shift-session-manager" + +[dependencies.pallet-session] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-system-rpc-runtime-api] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-timestamp] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.pallet-transaction-payment] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-executive] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +# Substrate Primitives +[dependencies.sp-api] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-block-builder] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-consensus-aura] +version = "0.8.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-core] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-inherents] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-io] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-offchain] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-runtime] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-session] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-staking] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-std] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-transaction-pool] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-version] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.frame-benchmarking] +optional = true +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.bp-header-chain] +version = "0.1.0" +default-features = false +path = "../../primitives/header-chain" + +[dependencies.bp-message-lane] +version = "0.1.0" +default-features = false +path = "../../primitives/message-lane" + +# Dev Dependencies + +[build-dependencies.wasm-builder-runner] +version = "1.0.5" +tag = 'v2.0.0-rc6' +package = "substrate-wasm-builder-runner" +git = "https://github.com/paritytech/substrate/" + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "codec/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-aura/std", + "pallet-balances/std", + "pallet-bridge-call-dispatch/std", + "pallet-grandpa/std", + "pallet-randomness-collective-flip/std", + "pallet-shift-session-manager/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment/std", + "serde", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", +] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/bin/node/runtime/build.rs b/bin/millau-runtime/build.rs similarity index 100% rename from bin/node/runtime/build.rs rename to bin/millau-runtime/build.rs diff --git a/bin/millau-runtime/src/lib.rs b/bin/millau-runtime/src/lib.rs new file mode 100644 index 0000000000000..864fb8256c00e --- /dev/null +++ b/bin/millau-runtime/src/lib.rs @@ -0,0 +1,475 @@ +// Copyright 2019-2020 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 . + +//! The Millau runtime. This can be compiled with `#[no_std]`, ready for Wasm. + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] +// Runtime-generated enums +#![allow(clippy::large_enum_variant)] +// Runtime-generated DecodeLimit::decode_all_With_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_runtime::traits::{ + BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify, +}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, +}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +// A few exports that help ease life for downstream crates. +pub use frame_support::{ + construct_runtime, parameter_types, + traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, Randomness}, + weights::{IdentityFee, RuntimeDbWeight, Weight}, + StorageValue, +}; + +pub use pallet_balances::Call as BalancesCall; +pub use pallet_timestamp::Call as TimestampCall; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; + +/// An index to a block. +pub type BlockNumber = u32; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// The type for looking up accounts. We don't expect more than 4 billion of them, but you +/// never know... +pub type AccountIndex = u32; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Digest item type. +pub type DigestItem = generic::DigestItem; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } +} + +/// This runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("millau-runtime"), + impl_name: create_runtime_str!("millau-runtime"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, +}; + +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// These time units are defined in number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const MaximumBlockWeight: Weight = 2_000_000_000_000; + pub const ExtrinsicBaseWeight: Weight = 10_000_000; + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); + /// Assume 10% of weight for average on_initialize calls. + pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() + .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); + pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const Version: RuntimeVersion = VERSION; + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 60_000_000, // ~0.06 ms = ~60 µs + write: 200_000_000, // ~0.2 ms = 200 µs + }; +} + +impl frame_system::Trait for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = (); + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = IdentityLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Maximum weight of each block. + type MaximumBlockWeight = MaximumBlockWeight; + /// The weight of database operations that the runtime can invoke. + type DbWeight = DbWeight; + /// The weight of the overhead invoked on the block import process, independent of the + /// extrinsics included in that block. + type BlockExecutionWeight = (); + /// The base weight of any extrinsic processed by the runtime, independent of the + /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) + type ExtrinsicBaseWeight = ExtrinsicBaseWeight; + /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, + /// idependent of the logic of that extrinsics. (Roughly max block weight - average on + /// initialize cost). + type MaximumExtrinsicWeight = MaximumExtrinsicWeight; + /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. + type MaximumBlockLength = MaximumBlockLength; + /// Portion of the block weight that is available to all normal transactions. + type AvailableBlockRatio = AvailableBlockRatio; + /// Version of the runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type ModuleToIndex = ModuleToIndex; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); +} + +impl pallet_aura::Trait for Runtime { + type AuthorityId = AuraId; +} + +impl pallet_bridge_call_dispatch::Trait for Runtime { + type Event = Event; + type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); + type Call = Call; +} + +impl pallet_grandpa::Trait for Runtime { + type Event = Event; + type Call = Call; + + type KeyOwnerProofSystem = (); + + type KeyOwnerProof = >::Proof; + + type KeyOwnerIdentification = + >::IdentificationTuple; + + type HandleEquivocation = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Trait for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 500; +} + +impl pallet_balances::Trait for Runtime { + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +parameter_types! { + pub const TransactionBaseFee: Balance = 0; + pub const TransactionByteFee: Balance = 1; +} + +impl pallet_transaction_payment::Trait for Runtime { + type Currency = pallet_balances::Module; + type OnTransactionPayment = (); + type TransactionByteFee = TransactionByteFee; + type WeightToFee = IdentityFee; + type FeeMultiplierUpdate = (); +} + +impl pallet_sudo::Trait for Runtime { + type Event = Event; + type Call = Call; +} + +parameter_types! { + pub const Period: BlockNumber = 4; + pub const Offset: BlockNumber = 0; +} + +impl pallet_session::Trait for Runtime { + type Event = Event; + type ValidatorId = ::AccountId; + type ValidatorIdOf = (); + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionManager = pallet_shift_session_manager::Module; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; + type DisabledValidatorsThreshold = (); + type WeightInfo = (); +} + +impl pallet_shift_session_manager::Trait for Runtime {} + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, + System: frame_system::{Module, Call, Config, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, + Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, + Aura: pallet_aura::{Module, Config, Inherent}, + Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, + Balances: pallet_balances::{Module, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Module, Storage}, + Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, + Session: pallet_session::{Module, Call, Storage, Event, Config}, + ShiftSessionManager: pallet_shift_session_manager::{Module}, + } +); + +/// The address format for describing accounts. +pub type Address = AccountId; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = + frame_executive::Executive, Runtime, AllModules>; + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + + fn random_seed() -> ::Hash { + RandomnessCollectiveFlip::random_seed() + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> u64 { + Aura::slot_duration() + } + + fn authorities() -> Vec { + Aura::authorities() + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, sp_core::crypto::KeyTypeId)>> { + SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + + fn submit_report_equivocation_unsigned_extrinsic( + equivocation_proof: fg_primitives::EquivocationProof< + ::Hash, + NumberFor, + >, + key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + ) -> Option<()> { + let key_owner_proof = key_owner_proof.decode()?; + + Grandpa::submit_unsigned_equivocation_report( + equivocation_proof, + key_owner_proof, + ) + } + + fn generate_key_ownership_proof( + _set_id: fg_primitives::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } + } +} diff --git a/bin/node/node/Cargo.toml b/bin/node/Cargo.toml similarity index 89% rename from bin/node/node/Cargo.toml rename to bin/node/Cargo.toml index c163f8e89b77f..7f6015d639c9e 100644 --- a/bin/node/node/Cargo.toml +++ b/bin/node/Cargo.toml @@ -8,20 +8,24 @@ homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -[[bin]] -name = "bridge-node" - [dependencies] -bp-eth-poa = { version = "0.1.0", path = "../../../primitives/ethereum-poa" } futures = "0.3.5" jsonrpc-core = "14.2.0" log = "0.4.11" -pallet-message-lane-rpc = { version = "0.1.0", path = "../../../modules/message-lane/rpc" } +pallet-message-lane-rpc = { version = "0.1.0", path = "../../modules/message-lane/rpc" } structopt = "0.3.17" -[dependencies.bridge-node-runtime] +[dependencies.millau-runtime] +optional = true +version = "0.1.0" +path = "../millau-runtime" +default-features = false +features = ["std"] + +[dependencies.rialto-runtime] +optional = true version = "0.1.0" -path = "../runtime" +path = "../rialto-runtime" default-features = false features = ["std"] @@ -148,6 +152,12 @@ git = "https://github.com/paritytech/substrate.git" [features] default = [] +millau = [ + "millau-runtime", +] +rialto = [ + "rialto-runtime", +] runtime-benchmarks = [ - "bridge-node-runtime/runtime-benchmarks", + "rialto-runtime/runtime-benchmarks", ] diff --git a/bin/node/node/build.rs b/bin/node/build.rs similarity index 100% rename from bin/node/node/build.rs rename to bin/node/build.rs diff --git a/bin/node/node/src/chain_spec.rs b/bin/node/src/chain_spec.rs similarity index 95% rename from bin/node/node/src/chain_spec.rs rename to bin/node/src/chain_spec.rs index 12c97f140e9d2..2aac990331903 100644 --- a/bin/node/node/src/chain_spec.rs +++ b/bin/node/src/chain_spec.rs @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bridge_node_runtime::{ +use grandpa_primitives::AuthorityId as GrandpaId; +use rialto_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; -use grandpa_primitives::AuthorityId as GrandpaId; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -169,16 +169,16 @@ fn testnet_genesis( fn load_rialto_bridge_config() -> Option { Some(BridgeRialtoConfig { - initial_header: bridge_node_runtime::rialto::genesis_header(), + initial_header: rialto_runtime::rialto::genesis_header(), initial_difficulty: 0.into(), - initial_validators: bridge_node_runtime::rialto::genesis_validators(), + initial_validators: rialto_runtime::rialto::genesis_validators(), }) } fn load_kovan_bridge_config() -> Option { Some(BridgeKovanConfig { - initial_header: bridge_node_runtime::kovan::genesis_header(), + initial_header: rialto_runtime::kovan::genesis_header(), initial_difficulty: 0.into(), - initial_validators: bridge_node_runtime::kovan::genesis_validators(), + initial_validators: rialto_runtime::kovan::genesis_validators(), }) } diff --git a/bin/node/node/src/cli.rs b/bin/node/src/cli.rs similarity index 100% rename from bin/node/node/src/cli.rs rename to bin/node/src/cli.rs diff --git a/bin/node/node/src/command.rs b/bin/node/src/command.rs similarity index 98% rename from bin/node/node/src/command.rs rename to bin/node/src/command.rs index 9951e9af47f6c..f216c3c42d1c7 100644 --- a/bin/node/node/src/command.rs +++ b/bin/node/src/command.rs @@ -33,7 +33,7 @@ use crate::cli::{Cli, Subcommand}; use crate::service; use crate::service::new_partial; -use bridge_node_runtime::Block; +use rialto_runtime::Block; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; @@ -67,7 +67,7 @@ impl SubstrateCli for Cli { } fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - &bridge_node_runtime::VERSION + &rialto_runtime::VERSION } fn load_spec(&self, id: &str) -> Result, String> { diff --git a/bin/node/node/src/main.rs b/bin/node/src/lib.rs similarity index 90% rename from bin/node/node/src/main.rs rename to bin/node/src/lib.rs index 30b05d773b0ea..fdecc0b45f0ea 100644 --- a/bin/node/node/src/main.rs +++ b/bin/node/src/lib.rs @@ -23,6 +23,10 @@ mod service; mod cli; mod command; -fn main() -> sc_cli::Result<()> { +/// Node run result. +pub type Result = sc_cli::Result<()>; + +/// Run node. +pub fn run() -> Result { command::run() } diff --git a/bin/node/node/src/service.rs b/bin/node/src/service.rs similarity index 98% rename from bin/node/node/src/service.rs rename to bin/node/src/service.rs index e1a1919b97343..4b89ae4782560 100644 --- a/bin/node/node/src/service.rs +++ b/bin/node/src/service.rs @@ -28,7 +28,7 @@ // ===================================================================================== // ===================================================================================== -use bridge_node_runtime::{self, opaque::Block, RuntimeApi}; +use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; @@ -42,8 +42,8 @@ use std::time::Duration; // Our native executor instance. native_executor_instance!( pub Executor, - bridge_node_runtime::api::dispatch, - bridge_node_runtime::native_version, + rialto_runtime::api::dispatch, + rialto_runtime::native_version, frame_benchmarking::benchmarking::HostFunctions, ); diff --git a/bin/rialto-node/Cargo.toml b/bin/rialto-node/Cargo.toml new file mode 100644 index 0000000000000..215cf60faa28e --- /dev/null +++ b/bin/rialto-node/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rialto-bridge-node" +description = "Substrate node compatible with Rialto runtime" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +bridge-node = { path = "../node", default-features = false, features = ["rialto"] } + +[features] +default = [] +runtime-benchmarks = [ + "bridge-node/runtime-benchmarks", +] diff --git a/bin/rialto-node/src/main.rs b/bin/rialto-node/src/main.rs new file mode 100644 index 0000000000000..7e101de175159 --- /dev/null +++ b/bin/rialto-node/src/main.rs @@ -0,0 +1,24 @@ +// Copyright 2019-2020 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 . + +//! Rialto bridge node. + +#![warn(missing_docs)] + +/// Run node. +fn main() -> bridge_node::Result { + bridge_node::run() +} diff --git a/bin/node/runtime/Cargo.toml b/bin/rialto-runtime/Cargo.toml similarity index 93% rename from bin/node/runtime/Cargo.toml rename to bin/rialto-runtime/Cargo.toml index b613c857b4863..101477915342a 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/rialto-runtime/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "bridge-node-runtime" +name = "rialto-runtime" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" @@ -43,22 +43,22 @@ git = "https://github.com/paritytech/substrate/" [dependencies.pallet-bridge-eth-poa] version = "0.1.0" default-features = false -path = "../../../modules/ethereum" +path = "../../modules/ethereum" [dependencies.pallet-bridge-call-dispatch] version = "0.1.0" default-features = false -path = "../../../modules/call-dispatch" +path = "../../modules/call-dispatch" [dependencies.pallet-bridge-currency-exchange] version = "0.1.0" default-features = false -path = "../../../modules/currency-exchange" +path = "../../modules/currency-exchange" [dependencies.pallet-message-lane] version = "0.1.0" default-features = false -path = "../../../modules/message-lane" +path = "../../modules/message-lane" [dependencies.frame-support] version = "2.0.0-rc6" @@ -81,7 +81,7 @@ git = "https://github.com/paritytech/substrate/" [dependencies.pallet-shift-session-manager] version = "0.1.0" default-features = false -path = "../../../modules/shift-session-manager" +path = "../../modules/shift-session-manager" [dependencies.pallet-sudo] version = "2.0.0-rc6" @@ -214,22 +214,22 @@ git = "https://github.com/paritytech/substrate/" [dependencies.bp-currency-exchange] version = "0.1.0" default-features = false -path = "../../../primitives/currency-exchange" +path = "../../primitives/currency-exchange" [dependencies.bp-eth-poa] version = "0.1.0" default-features = false -path = "../../../primitives/ethereum-poa" +path = "../../primitives/ethereum-poa" [dependencies.bp-header-chain] version = "0.1.0" default-features = false -path = "../../../primitives/header-chain" +path = "../../primitives/header-chain" [dependencies.bp-message-lane] version = "0.1.0" default-features = false -path = "../../../primitives/message-lane" +path = "../../primitives/message-lane" # Dev Dependencies @@ -242,7 +242,7 @@ features = ["hmac"] version = "0.1.0" default-features = false features = ["std"] -path = "../../../primitives/ethereum-poa" +path = "../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] version = "1.0.5" diff --git a/bin/rialto-runtime/build.rs b/bin/rialto-runtime/build.rs new file mode 100644 index 0000000000000..4fda040c9bd14 --- /dev/null +++ b/bin/rialto-runtime/build.rs @@ -0,0 +1,26 @@ +// Copyright 2019-2020 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 . + +use wasm_builder_runner::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .with_wasm_builder_from_crates("1.0.11") + .export_heap_base() + .import_memory() + .build() +} diff --git a/bin/node/runtime/src/benches.rs b/bin/rialto-runtime/src/benches.rs similarity index 100% rename from bin/node/runtime/src/benches.rs rename to bin/rialto-runtime/src/benches.rs diff --git a/bin/node/runtime/src/exchange.rs b/bin/rialto-runtime/src/exchange.rs similarity index 100% rename from bin/node/runtime/src/exchange.rs rename to bin/rialto-runtime/src/exchange.rs diff --git a/bin/node/runtime/src/kovan.rs b/bin/rialto-runtime/src/kovan.rs similarity index 100% rename from bin/node/runtime/src/kovan.rs rename to bin/rialto-runtime/src/kovan.rs diff --git a/bin/node/runtime/src/lib.rs b/bin/rialto-runtime/src/lib.rs similarity index 99% rename from bin/node/runtime/src/lib.rs rename to bin/rialto-runtime/src/lib.rs index 92ee820f7cd15..a00733ae74fa6 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/rialto-runtime/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm. +//! The Rialto runtime. This can be compiled with `#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. @@ -121,8 +121,8 @@ impl_opaque_keys! { /// This runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("bridge-node"), - impl_name: create_runtime_str!("bridge-node"), + spec_name: create_runtime_str!("rialto-runtime"), + impl_name: create_runtime_str!("rialto-runtime"), authoring_version: 1, spec_version: 1, impl_version: 1, diff --git a/bin/node/runtime/src/rialto.rs b/bin/rialto-runtime/src/rialto.rs similarity index 100% rename from bin/node/runtime/src/rialto.rs rename to bin/rialto-runtime/src/rialto.rs diff --git a/bin/node/scripts/init.sh b/bin/scripts/init.sh similarity index 100% rename from bin/node/scripts/init.sh rename to bin/scripts/init.sh diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index ac7b7b80b7856..3911c2cd10675 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.11" # Runtime/chain specific dependencies -bridge-node-runtime = { path = "../../../bin/node/runtime" } +rialto-runtime = { path = "../../../bin/rialto-runtime" } [dependencies.sp-blockchain] version = "2.0.0-rc6" diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs index f99704b45a11f..abb7375103dff 100644 --- a/modules/ethereum-contract/builtin/src/lib.rs +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bridge_node_runtime::{Block, BlockNumber, Hash, Header as RuntimeHeader}; use codec::{Decode, Encode}; use ethereum_types::U256; use finality_grandpa::voter_set::VoterSet; +use rialto_runtime::{Block, BlockNumber, Hash, Header as RuntimeHeader}; use sp_blockchain::Error as ClientError; use sp_finality_grandpa::{AuthorityList, ConsensusLog, GRANDPA_ENGINE_ID}; @@ -177,7 +177,7 @@ pub fn verify_substrate_finality_proof( #[cfg(test)] mod tests { use super::*; - use bridge_node_runtime::DigestItem; + use rialto_runtime::DigestItem; use sp_core::crypto::Public; use sp_finality_grandpa::{AuthorityId, ScheduledChange}; use sp_runtime::generic::Digest; diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 0842bb206d15f..16deabd717951 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -77,6 +77,6 @@ version = "0.8.0-rc6" tag = 'v2.0.0-rc6' git = "https://github.com/paritytech/substrate.git" -[dependencies.bridge-node-runtime] +[dependencies.rialto-runtime] version = "0.1.0" -path = "../../bin/node/runtime" +path = "../../bin/rialto-runtime" diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index b045b36356ff1..666b71fa3b4e7 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -38,7 +38,7 @@ use crate::utils::HeaderId; use async_trait::async_trait; use bp_currency_exchange::MaybeLockFundsTransaction; -use bridge_node_runtime::exchange::EthereumTransactionInclusionProof; +use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::time::Duration; /// Interval at which we ask Ethereum node for updates. @@ -234,7 +234,7 @@ impl TargetClient for SubstrateTransactionsTarget { async fn filter_transaction_proof(&self, proof: &EthereumTransactionInclusionProof) -> Result { // let's try to parse transaction locally let (raw_tx, raw_tx_receipt) = &proof.proof[proof.index as usize]; - let parse_result = bridge_node_runtime::exchange::EthTransaction::parse(raw_tx); + let parse_result = rialto_runtime::exchange::EthTransaction::parse(raw_tx); if parse_result.is_err() { return Ok(false); } diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index 69a4d7a39b7f2..4309b6e894d24 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -24,7 +24,7 @@ use bp_eth_poa::{ signatures::{SecretKey, SignTransaction}, UnsignedTransaction, }; -use bridge_node_runtime::exchange::LOCK_FUNDS_ADDRESS; +use rialto_runtime::exchange::LOCK_FUNDS_ADDRESS; /// Ethereum exchange transaction params. #[derive(Debug)] diff --git a/relays/ethereum/src/instances.rs b/relays/ethereum/src/instances.rs index fa6963430b1d6..4d17bcbec9b8d 100644 --- a/relays/ethereum/src/instances.rs +++ b/relays/ethereum/src/instances.rs @@ -26,8 +26,8 @@ use crate::ethereum_types::QueuedEthereumHeader; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; -use bridge_node_runtime::exchange::EthereumTransactionInclusionProof as Proof; -use bridge_node_runtime::Call; +use rialto_runtime::exchange::EthereumTransactionInclusionProof as Proof; +use rialto_runtime::Call; /// Interface for `Calls` which are needed to correctly sync the bridge. /// @@ -48,7 +48,7 @@ pub struct Rialto; impl BridgeInstance for Rialto { fn build_signed_header_call(&self, headers: Vec) -> Call { - let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers( headers .into_iter() .map(|header| { @@ -60,21 +60,21 @@ impl BridgeInstance for Rialto { .collect(), ); - bridge_node_runtime::Call::BridgeRialto(pallet_call) + rialto_runtime::Call::BridgeRialto(pallet_call) } fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { - let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( into_substrate_ethereum_header(header.header()), into_substrate_ethereum_receipts(header.extra()), ); - bridge_node_runtime::Call::BridgeRialto(pallet_call) + rialto_runtime::Call::BridgeRialto(pallet_call) } fn build_currency_exchange_call(&self, proof: Proof) -> Call { - let pallet_call = bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); - bridge_node_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call) + let pallet_call = rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + rialto_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call) } } @@ -84,7 +84,7 @@ pub struct Kovan; impl BridgeInstance for Kovan { fn build_signed_header_call(&self, headers: Vec) -> Call { - let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_signed_headers( + let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers( headers .into_iter() .map(|header| { @@ -96,20 +96,20 @@ impl BridgeInstance for Kovan { .collect(), ); - bridge_node_runtime::Call::BridgeKovan(pallet_call) + rialto_runtime::Call::BridgeKovan(pallet_call) } fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { - let pallet_call = bridge_node_runtime::BridgeEthPoACall::import_unsigned_header( + let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( into_substrate_ethereum_header(header.header()), into_substrate_ethereum_receipts(header.extra()), ); - bridge_node_runtime::Call::BridgeKovan(pallet_call) + rialto_runtime::Call::BridgeKovan(pallet_call) } fn build_currency_exchange_call(&self, proof: Proof) -> Call { - let pallet_call = bridge_node_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); - bridge_node_runtime::Call::BridgeKovanCurrencyExchange(pallet_call) + let pallet_call = rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + rialto_runtime::Call::BridgeKovanCurrencyExchange(pallet_call) } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 7004dd8b14b97..1d3e5d03199fd 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -314,13 +314,13 @@ pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { /// Pre-verify Ethereum exchange transaction proof. async fn verify_exchange_transaction_proof( &self, - proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult; /// Submits Ethereum exchange transaction proof to Substrate runtime. async fn submit_exchange_transaction_proof( &self, params: SubstrateSigningParams, - proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()>; } @@ -328,7 +328,7 @@ pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { async fn verify_exchange_transaction_proof( &self, - proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult { let call = EXCH_API_FILTER_TRANSACTION_PROOF.to_string(); let data = Bytes(proof.encode()); @@ -342,7 +342,7 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { async fn submit_exchange_transaction_proof( &self, params: SubstrateSigningParams, - proof: bridge_node_runtime::exchange::EthereumTransactionInclusionProof, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { let account_id = params.signer.public().as_array_ref().clone().into(); let nonce = self.next_account_index(account_id).await?; @@ -357,43 +357,43 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { /// Create signed Substrate transaction for submitting Ethereum headers. fn create_signed_submit_transaction( - signed_call: bridge_node_runtime::Call, + signed_call: rialto_runtime::Call, signer: &sp_core::sr25519::Pair, index: node_primitives::Index, genesis_hash: H256, -) -> bridge_node_runtime::UncheckedExtrinsic { +) -> rialto_runtime::UncheckedExtrinsic { create_signed_transaction(signed_call, signer, index, genesis_hash) } /// Create unsigned Substrate transaction for submitting Ethereum header. -fn create_unsigned_submit_transaction(call: bridge_node_runtime::Call) -> bridge_node_runtime::UncheckedExtrinsic { - bridge_node_runtime::UncheckedExtrinsic::new_unsigned(call) +fn create_unsigned_submit_transaction(call: rialto_runtime::Call) -> rialto_runtime::UncheckedExtrinsic { + rialto_runtime::UncheckedExtrinsic::new_unsigned(call) } /// Create signed Substrate transaction. fn create_signed_transaction( - function: bridge_node_runtime::Call, + function: rialto_runtime::Call, signer: &sp_core::sr25519::Pair, index: node_primitives::Index, genesis_hash: H256, -) -> bridge_node_runtime::UncheckedExtrinsic { +) -> rialto_runtime::UncheckedExtrinsic { let extra = |i: node_primitives::Index, f: node_primitives::Balance| { ( - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), - frame_system::CheckNonce::::from(i), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(f), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::::from(i), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(f), ) }; - let raw_payload = bridge_node_runtime::SignedPayload::from_raw( + let raw_payload = rialto_runtime::SignedPayload::from_raw( function, extra(index, 0), ( - bridge_node_runtime::VERSION.spec_version, - bridge_node_runtime::VERSION.transaction_version, + rialto_runtime::VERSION.spec_version, + rialto_runtime::VERSION.transaction_version, genesis_hash, genesis_hash, (), @@ -405,5 +405,5 @@ fn create_signed_transaction( let signer: sp_runtime::MultiSigner = signer.public().into(); let (function, extra, _) = raw_payload.deconstruct(); - bridge_node_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account(), signature.into(), extra) + rialto_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account(), signature.into(), extra) } diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index fdd2880230ab1..87931957ad3b2 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -28,22 +28,22 @@ pub use bp_eth_poa::{ }; /// Substrate header hash. -pub type Hash = bridge_node_runtime::Hash; +pub type Hash = rialto_runtime::Hash; /// Substrate header number. -pub type Number = bridge_node_runtime::BlockNumber; +pub type Number = rialto_runtime::BlockNumber; /// Substrate header type. -pub type Header = bridge_node_runtime::Header; +pub type Header = rialto_runtime::Header; /// Substrate signed block type. -pub type SignedBlock = bridge_node_runtime::SignedBlock; +pub type SignedBlock = rialto_runtime::SignedBlock; /// GRANDPA justification. pub type GrandpaJustification = Vec; /// Substrate header ID. -pub type SubstrateHeaderId = HeaderId; +pub type SubstrateHeaderId = HeaderId; /// Queued substrate header ID. pub type QueuedSubstrateHeader = QueuedHeader; @@ -57,8 +57,8 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { const SOURCE_NAME: &'static str = "Substrate"; const TARGET_NAME: &'static str = "Ethereum"; - type Hash = bridge_node_runtime::Hash; - type Number = bridge_node_runtime::BlockNumber; + type Hash = rialto_runtime::Hash; + type Number = rialto_runtime::BlockNumber; type Header = Header; type Extra = (); type Completion = GrandpaJustification; @@ -68,7 +68,7 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { } } -impl SourceHeader for Header { +impl SourceHeader for Header { fn id(&self) -> SubstrateHeaderId { HeaderId(self.number, self.hash()) } From 74c90d46c6116b704dec66b7fc2bbe2bfffc13a0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Sep 2020 21:39:56 +0300 Subject: [PATCH 0155/1210] Fix Rialto test-poa genesis state root (#350) * fix test-poa genesis state root * fix test --- bin/rialto-runtime/src/rialto.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/rialto-runtime/src/rialto.rs b/bin/rialto-runtime/src/rialto.rs index 17e84a5e1a07a..03f8c40650885 100644 --- a/bin/rialto-runtime/src/rialto.rs +++ b/bin/rialto-runtime/src/rialto.rs @@ -79,7 +79,7 @@ pub fn genesis_header() -> Header { transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), extra_data: vec![], - state_root: hex!("eccf6b74c2bcbe115c71116a23fe963c54406010c244d9650526028ad3e32cce").into(), + state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(), receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), log_bloom: Default::default(), gas_used: Default::default(), @@ -134,7 +134,7 @@ mod tests { fn genesis_hash_matches() { assert_eq!( genesis_header().compute_hash(), - hex!("9ff57c7fa155853586382022f0982b71c51fa313a0942f8c456300896643e890").into(), + hex!("1468e1a0fa20d30025a5a0f87e1cced4fdc393b84b7d2850b11ca5863db482cb").into(), ); } From b8a8403182c672c69ef9554baa57ace0f07b67aa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 15 Sep 2020 15:14:52 +0300 Subject: [PATCH 0156/1210] Remove queueing from message-lane (#352) * remove queueing from message-lane * also remove queueing from RPCs * another trace * new clippy --- modules/currency-exchange/src/lib.rs | 2 +- modules/ethereum/src/verification.rs | 2 +- modules/message-lane/rpc/src/lib.rs | 32 ----- modules/message-lane/src/inbound_lane.rs | 165 ++-------------------- modules/message-lane/src/lib.rs | 60 +------- modules/message-lane/src/mock.rs | 23 +-- modules/message-lane/src/outbound_lane.rs | 73 ---------- primitives/message-lane/src/lib.rs | 42 ++---- 8 files changed, 29 insertions(+), 370 deletions(-) diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 28a53d287b51c..aace287eb5834 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -184,7 +184,7 @@ fn prepare_deposit_details, I: Instance>( ) -> Result, Error> { // ensure that transaction is included in finalized block that we know of let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) - .ok_or_else(|| Error::::UnfinalizedTransaction)?; + .ok_or(Error::::UnfinalizedTransaction)?; // parse transaction let transaction = diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index ea5a208b40906..115867d284e24 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -122,7 +122,7 @@ pub fn accept_aura_header_into_pool( validator_checks(config, &best_context.validators_set().validators, header, header_step); if let Err(error) = validators_check_result { find_next_validators_signal(storage, &best_context) - .ok_or_else(|| error) + .ok_or(error) .and_then(|next_validators| validator_checks(config, &next_validators, header, header_step))?; } diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index 3d0a0f484a1fd..799de23dab9d7 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -41,10 +41,6 @@ pub type MessagesProof = Bytes; /// SCALE-encoded trie nodes array `Vec>`. pub type MessagesReceivingProof = Bytes; -/// Trie-based storage proof that the message(s) with given key(s) have been processed by the bridged chain. -/// SCALE-encoded trie nodes array `Vec>`. -pub type MessagesProcessingProof = Bytes; - /// Runtime adapter. pub trait Runtime: Send + Sync + 'static { /// Return runtime storage key for given message. May return None if instance is unknown. @@ -75,15 +71,6 @@ pub trait MessageLaneApi { lane: LaneId, block: Option, ) -> FutureResult; - - /// Returns proof-of-message(s) processing. - #[rpc(name = "messageLane_proveMessagesProcessing")] - fn prove_messages_processing( - &self, - instance: InstanceId, - lane: LaneId, - block: Option, - ) -> FutureResult; } /// Implements the MessageLaneApi trait for interacting with message lanes. @@ -150,25 +137,6 @@ where .map_err(Into::into), ) } - - fn prove_messages_processing( - &self, - instance: InstanceId, - lane: LaneId, - block: Option, - ) -> FutureResult { - Box::new( - prove_keys_read( - self.backend.clone(), - block, - vec![self.runtime.inbound_lane_data_key(&instance, &lane)], - ) - .boxed() - .compat() - .map(serialize_storage_proof) - .map_err(Into::into), - ) - } } async fn prove_keys_read( diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index abf6ffb346760..f8bf478ecb29a 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -16,7 +16,7 @@ //! Everything about incoming messages receival. -use bp_message_lane::{InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessageResult, OnMessageReceived}; +use bp_message_lane::{InboundLaneData, LaneId, Message, MessageKey, MessageNonce, OnMessageReceived}; /// Inbound lane storage. pub trait InboundLaneStorage { @@ -29,12 +29,6 @@ pub trait InboundLaneStorage { fn data(&self) -> InboundLaneData; /// Update lane data in the storage. fn set_data(&mut self, data: InboundLaneData); - /// Returns saved inbound message payload. - fn message(&self, nonce: &MessageNonce) -> Option; - /// Save inbound message in the storage. - fn save_message(&mut self, nonce: MessageNonce, payload: Self::Payload); - /// Remove inbound message from the storage. - fn remove_message(&mut self, nonce: &MessageNonce); } /// Inbound messages lane. @@ -49,11 +43,10 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message( + pub fn receive_message>( &mut self, nonce: MessageNonce, payload: S::Payload, - processor: &mut impl OnMessageReceived, ) -> bool { let mut data = self.storage.data(); let is_correct_message = nonce == data.latest_received_nonce + 1; @@ -61,70 +54,19 @@ impl InboundLane { return false; } - let is_process_required = is_correct_message && data.oldest_unprocessed_nonce == nonce; data.latest_received_nonce = nonce; self.storage.set_data(data); - let payload_to_save = match is_process_required { - true => { - let message = Message { - key: MessageKey { - lane_id: self.storage.id(), - nonce, - }, - payload, - }; - match processor.on_message_received(message) { - MessageResult::Processed => None, - MessageResult::NotProcessed(message) => Some(message.payload), - } - } - false => Some(payload), - }; - - if let Some(payload_to_save) = payload_to_save { - self.storage.save_message(nonce, payload_to_save); - } + P::on_message_received(Message { + key: MessageKey { + lane_id: self.storage.id(), + nonce, + }, + payload, + }); true } - - /// Process stored lane messages. - /// - /// Stops processing either when all messages are processed, or when processor returns - /// MessageResult::NotProcessed. - pub fn process_messages(&mut self, processor: &mut impl OnMessageReceived) { - let mut anything_processed = false; - let mut data = self.storage.data(); - while data.oldest_unprocessed_nonce <= data.latest_received_nonce { - let nonce = data.oldest_unprocessed_nonce; - let payload = self - .storage - .message(&nonce) - .expect("message is referenced by lane; referenced message is not pruned; qed"); - let message = Message { - key: MessageKey { - lane_id: self.storage.id(), - nonce, - }, - payload, - }; - - let process_result = processor.on_message_received(message); - if let MessageResult::NotProcessed(_) = process_result { - break; - } - - self.storage.remove_message(&nonce); - - anything_processed = true; - data.oldest_unprocessed_nonce += 1; - } - - if anything_processed { - self.storage.set_data(data); - } - } } #[cfg(test)] @@ -132,105 +74,24 @@ mod tests { use super::*; use crate::{ inbound_lane, - mock::{ - run_test, TestMessageProcessor, TestPayload, TestRuntime, PAYLOAD_TO_QUEUE, REGULAR_PAYLOAD, TEST_LANE_ID, - }, + mock::{run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, }; #[test] fn fails_to_receive_message_with_incorrect_nonce() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(!lane.receive_message(10, REGULAR_PAYLOAD, &mut TestMessageProcessor)); - assert!(lane.storage.message(&10).is_none()); + assert!(!lane.receive_message::<()>(10, REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_received_nonce, 0); }); } #[test] - fn correct_message_is_queued_if_some_other_messages_are_queued() { - run_test(|| { - let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message(1, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); - assert!(lane.storage.message(&1).is_some()); - assert!(lane.receive_message(2, REGULAR_PAYLOAD, &mut TestMessageProcessor)); - assert!(lane.storage.message(&2).is_some()); - assert_eq!(lane.storage.data().latest_received_nonce, 2); - }); - } - - #[test] - fn correct_message_is_queued_if_processor_wants_to_queue() { - run_test(|| { - let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message(1, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); - assert!(lane.storage.message(&1).is_some()); - assert_eq!(lane.storage.data().latest_received_nonce, 1); - }); - } - - #[test] - fn correct_message_is_not_queued_if_processed_instantly() { + fn correct_message_is_processed_instantly() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message(1, REGULAR_PAYLOAD, &mut TestMessageProcessor)); - assert!(lane.storage.message(&1).is_none()); + assert!(lane.receive_message::<()>(1, REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_received_nonce, 1); }); } - - #[test] - fn process_message_does_nothing_when_lane_is_empty() { - run_test(|| { - let mut lane = inbound_lane::(TEST_LANE_ID); - assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 1); - lane.process_messages(&mut TestMessageProcessor); - assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 1); - }); - } - - #[test] - fn process_message_works() { - run_test(|| { - pub struct QueueByNonce(MessageNonce); - - impl OnMessageReceived for QueueByNonce { - fn on_message_received(&mut self, message: Message) -> MessageResult { - if message.key.nonce == self.0 { - MessageResult::NotProcessed(message) - } else { - MessageResult::Processed - } - } - } - - let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message(1, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); - assert!(lane.receive_message(2, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); - assert!(lane.receive_message(3, PAYLOAD_TO_QUEUE, &mut TestMessageProcessor)); - assert!(lane.receive_message(4, REGULAR_PAYLOAD, &mut TestMessageProcessor)); - - assert!(lane.storage.message(&1).is_some()); - assert!(lane.storage.message(&2).is_some()); - assert!(lane.storage.message(&3).is_some()); - assert!(lane.storage.message(&4).is_some()); - assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 1); - - lane.process_messages(&mut QueueByNonce(3)); - - assert!(lane.storage.message(&1).is_none()); - assert!(lane.storage.message(&2).is_none()); - assert!(lane.storage.message(&3).is_some()); - assert!(lane.storage.message(&4).is_some()); - assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 3); - - lane.process_messages(&mut QueueByNonce(10)); - - assert!(lane.storage.message(&1).is_none()); - assert!(lane.storage.message(&2).is_none()); - assert!(lane.storage.message(&3).is_none()); - assert!(lane.storage.message(&4).is_none()); - assert_eq!(lane.storage.data().oldest_unprocessed_nonce, 5); - }); - } } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 0f581d0c659c3..f8c9b9d4f8e72 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -58,15 +58,13 @@ pub trait Trait: frame_system::Trait { /// for it. type MaxMessagesToPruneAtOnce: Get; /// Called when message has been received. - type OnMessageReceived: Default + OnMessageReceived; + type OnMessageReceived: OnMessageReceived; } decl_storage! { trait Store for Module, I: Instance = DefaultInstance> as MessageLane { /// Map of lane id => inbound lane data. InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; - /// All stored (unprocessed) inbound messages. - InboundMessages: map hasher(blake2_128_concat) MessageKey => Option; /// Map of lane id => outbound lane data. OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; /// All queued outbound messages. @@ -80,10 +78,8 @@ decl_event!( { /// Message has been accepted and is waiting to be delivered. MessageAccepted(LaneId, MessageNonce), - /// Messages in the inclusive range have been delivered to the bridged chain. + /// Messages in the inclusive range have been delivered and processed by the bridged chain. MessagesDelivered(LaneId, MessageNonce, MessageNonce), - /// Messages in the inclusive range have been processed by the bridged chain. - MessagesProcessed(LaneId, MessageNonce, MessageNonce), /// Phantom member, never used. Dummy(PhantomData<(AccountId, I)>), } @@ -126,10 +122,9 @@ impl, I: Instance> Module { /// will be rejected. pub fn receive_messages(messages: Vec>) -> MessageNonce { let mut correct_messages = 0; - let mut processor = T::OnMessageReceived::default(); for message in messages { let mut lane = inbound_lane::(message.key.lane_id); - if lane.receive_message(message.key.nonce, message.payload, &mut processor) { + if lane.receive_message::(message.key.nonce, message.payload) { correct_messages += 1; } } @@ -137,14 +132,6 @@ impl, I: Instance> Module { correct_messages } - /// Process stored lane messages. - /// - /// Stops processing either when all messages are processed, or when processor returns - /// MessageResult::NotProcessed. - pub fn process_lane_messages(lane_id: &LaneId, processor: &mut impl OnMessageReceived) { - inbound_lane::(*lane_id).process_messages(processor); - } - /// Receive TRUSTED proof of message receival. /// /// Trusted here means that the function itself doesn't check whether the bridged chain has @@ -164,23 +151,6 @@ impl, I: Instance> Module { )); } } - - /// Receive TRUSTED proof of message processing. - /// - /// Trusted here means that the function itself doesn't check whether the bridged chain has - /// actually processed these messages. - pub fn confirm_processing(lane_id: &LaneId, latest_processed_nonce: MessageNonce) { - let mut lane = outbound_lane::(*lane_id); - let processed_range = lane.confirm_processing(latest_processed_nonce); - - if let Some(processed_range) = processed_range { - Self::deposit_event(RawEvent::MessagesProcessed( - *lane_id, - processed_range.0, - processed_range.1, - )); - } - } } /// Creates new inbound lane object, backed by runtime storage. @@ -219,30 +189,6 @@ impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage< fn set_data(&mut self, data: InboundLaneData) { InboundLanes::::insert(&self.lane_id, data) } - - fn message(&self, nonce: &MessageNonce) -> Option { - InboundMessages::::get(MessageKey { - lane_id: self.lane_id, - nonce: *nonce, - }) - } - - fn save_message(&mut self, nonce: MessageNonce, payload: T::Payload) { - InboundMessages::::insert( - MessageKey { - lane_id: self.lane_id, - nonce, - }, - payload, - ); - } - - fn remove_message(&mut self, nonce: &MessageNonce) { - InboundMessages::::remove(MessageKey { - lane_id: self.lane_id, - nonce: *nonce, - }); - } } /// Runtime outbound lane storage. diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index b56489c96a280..c0d27e389aa3b 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bp_message_lane::{LaneId, Message, MessageResult, OnMessageReceived}; +use bp_message_lane::LaneId; use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; use sp_core::H256; use sp_runtime::{ @@ -89,32 +89,15 @@ impl Trait for TestRuntime { type Event = TestEvent; type Payload = TestPayload; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; - type OnMessageReceived = TestMessageProcessor; + type OnMessageReceived = (); } /// Lane that we're using in tests. pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; -/// Regular message payload that is not PAYLOAD_TO_QUEUE. +/// Regular message payload. pub const REGULAR_PAYLOAD: TestPayload = 0; -/// All messages with this payload are queued by TestMessageProcessor. -pub const PAYLOAD_TO_QUEUE: TestPayload = 42; - -/// Message processor that immediately handles all messages except messages with PAYLOAD_TO_QUEUE payload. -#[derive(Debug, Default)] -pub struct TestMessageProcessor; - -impl OnMessageReceived for TestMessageProcessor { - fn on_message_received(&mut self, message: Message) -> MessageResult { - if message.payload == PAYLOAD_TO_QUEUE { - MessageResult::NotProcessed(message) - } else { - MessageResult::Processed - } - } -} - /// Run message lane test. pub fn run_test(test: impl FnOnce() -> T) -> T { sp_io::TestExternalities::new(Default::default()).execute_with(test) diff --git a/modules/message-lane/src/outbound_lane.rs b/modules/message-lane/src/outbound_lane.rs index 7357dbd410830..52a1404ba7a76 100644 --- a/modules/message-lane/src/outbound_lane.rs +++ b/modules/message-lane/src/outbound_lane.rs @@ -80,25 +80,6 @@ impl OutboundLane { Some((prev_latest_received_nonce + 1, latest_received_nonce)) } - /// Confirm message processing. - /// - /// Returns `None` if confirmation is wrong/duplicate. - /// Returns `Some` with inclusive ranges of message nonces that have been processed. - pub fn confirm_processing(&mut self, latest_processed_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> { - let mut data = self.storage.data(); - // wait for recieval confirmation first - if latest_processed_nonce <= data.latest_processed_nonce || latest_processed_nonce > data.latest_received_nonce - { - return None; - } - - let prev_latest_processed_nonce = data.latest_processed_nonce; - data.latest_processed_nonce = latest_processed_nonce; - self.storage.set_data(data); - - Some((prev_latest_processed_nonce + 1, latest_processed_nonce)) - } - /// Prune at most `max_messages_to_prune` already received messages. /// /// Returns number of pruned messages. @@ -191,60 +172,6 @@ mod tests { }); } - #[test] - fn confirm_processing_works() { - run_test(|| { - let mut lane = outbound_lane::(TEST_LANE_ID); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 1); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 2); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 3); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 0); - assert_eq!(lane.confirm_receival(3), Some((1, 3))); - assert_eq!(lane.confirm_processing(2), Some((1, 2))); - assert_eq!(lane.storage.data().latest_processed_nonce, 2); - assert_eq!(lane.confirm_processing(3), Some((3, 3))); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 3); - }); - } - - #[test] - fn confirm_processing_rejects_nonce_lesser_than_latest_processed() { - run_test(|| { - let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 0); - assert_eq!(lane.confirm_receival(3), Some((1, 3))); - assert_eq!(lane.confirm_processing(3), Some((1, 3))); - assert_eq!(lane.confirm_processing(3), None); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 3); - - assert_eq!(lane.confirm_processing(2), None); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 3); - }); - } - - #[test] - fn confirm_processing_rejects_nonce_larger_than_last_received() { - run_test(|| { - let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 0); - assert_eq!(lane.confirm_processing(2), None); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_processed_nonce, 0); - }); - } - #[test] fn prune_messages_works() { run_test(|| { diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index fce49679469db..a4bfac459b8b9 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -49,45 +49,26 @@ pub struct Message { pub payload: Payload, } -/// Message processing result. -pub enum MessageResult { - /// Message has been processed and should not be queued. - Processed, - /// Message has NOT been processed and should be queued for processing later. - NotProcessed(Message), -} - /// Called when inbound message is received. pub trait OnMessageReceived { /// Called when inbound message is received. /// /// It is up to the implementers of this trait to determine whether the message - /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. And, - /// if message is invalid, then it should be dropped immediately (by returning - /// `MessageResult::Processed`), or it'll block the lane forever. - fn on_message_received(&mut self, message: Message) -> MessageResult; + /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. + fn on_message_received(message: Message); +} + +impl OnMessageReceived for () { + fn on_message_received(_message: Message) {} } /// Inbound lane data. -#[derive(Encode, Decode, Clone)] +#[derive(Default, Encode, Decode, Clone)] pub struct InboundLaneData { - /// Nonce of oldest message that we haven't processed yet. May point to not-yet-received message if - /// lane is currently empty. - pub oldest_unprocessed_nonce: MessageNonce, /// Nonce of latest message that we have received from bridged chain. pub latest_received_nonce: MessageNonce, } -impl Default for InboundLaneData { - fn default() -> Self { - InboundLaneData { - // it is 1 because we're processing everything in [oldest_unprocessed_nonce; latest_received_nonce] - oldest_unprocessed_nonce: 1, - latest_received_nonce: 0, - } - } -} - /// Outbound lane data. #[derive(Encode, Decode, Clone)] pub struct OutboundLaneData { @@ -96,8 +77,6 @@ pub struct OutboundLaneData { pub oldest_unpruned_nonce: MessageNonce, /// Nonce of latest message, received by bridged chain. pub latest_received_nonce: MessageNonce, - /// Nonce of latest message, processed by bridged chain. - pub latest_processed_nonce: MessageNonce, /// Nonce of latest message, generated by us. pub latest_generated_nonce: MessageNonce, } @@ -108,7 +87,6 @@ impl Default for OutboundLaneData { // it is 1 because we're pruning everything in [oldest_unpruned_nonce; latest_received_nonce] oldest_unpruned_nonce: 1, latest_received_nonce: 0, - latest_processed_nonce: 0, latest_generated_nonce: 0, } } @@ -116,11 +94,9 @@ impl Default for OutboundLaneData { decl_runtime_apis! { /// Outbound message lane API. - pub trait OutboundLaneApi { + pub trait OutboundLaneApi { /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, processed by bridged chain. - fn latest_processed_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } @@ -129,7 +105,5 @@ decl_runtime_apis! { pub trait InboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, processed by given lane. - fn latest_processed_nonce(lane: LaneId) -> MessageNonce; } } From ad9bf083a19312b9d58a44579aea41dce428d57a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 16 Sep 2020 21:52:42 +0300 Subject: [PATCH 0157/1210] Verify GRANDPA justifications from runtime (#353) * verify justifications from runtime * unreachable --- modules/substrate/Cargo.toml | 33 ++- modules/substrate/src/justification.rs | 329 +++++++++++++++++++++++++ modules/substrate/src/lib.rs | 1 + 3 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 modules/substrate/src/justification.rs diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 40b7b0b894d59..365ce68993539 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -8,16 +8,35 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version = "1.0", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +finality-grandpa = { version = "0.12.3", default-features = false } hash-db = { version = "0.15.2", default-features = false } # Substrate Based Dependencies +[dependencies.frame-support] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.sp-finality-grandpa] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + [dependencies.sp-runtime] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" +[dependencies.sp-std] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + [dependencies.sp-trie] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' @@ -30,6 +49,12 @@ tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" +[dev-dependencies.sp-keyring] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + [dev-dependencies.sp-state-machine] version = "0.8.0-rc6" tag = 'v2.0.0-rc6' @@ -39,7 +64,11 @@ git = "https://github.com/paritytech/substrate/" [features] default = ["std"] std = [ - "serde", + "codec/std", + "finality-grandpa/std", + "frame-support/std", + "sp-finality-grandpa/std", "sp-runtime/std", + "sp-std/std", "sp-trie/std", ] diff --git a/modules/substrate/src/justification.rs b/modules/substrate/src/justification.rs new file mode 100644 index 0000000000000..0457278197aa2 --- /dev/null +++ b/modules/substrate/src/justification.rs @@ -0,0 +1,329 @@ +// Copyright 2019-2020 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 . + +//! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin +//! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. + +// TODO: remove on actual use +#![allow(dead_code)] + +use codec::Decode; +use finality_grandpa::{voter_set::VoterSet, Chain, Error as GrandpaError}; +use frame_support::RuntimeDebug; +use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; + +/// Justification verification error. +#[derive(RuntimeDebug, PartialEq)] +pub enum Error { + /// Failed to decode justification. + JustificationDecode, + /// Justification is finalizing unexpected header. + InvalidJustificationTarget, + /// Invalid commit in justification. + InvalidJustificationCommit, + /// Justification has invalid authority singature. + InvalidAuthoritySignature, + /// The justification has precommit for the header that has no route from the target header. + InvalidPrecommitAncestryProof, + /// The justification has 'unused' headers in its precommit ancestries. + InvalidPrecommitAncestries, +} + +/// Verify that justification, that is generated by given authority set, finalizes given header. +pub fn verify_justification( + finalized_target: (Header::Hash, Header::Number), + authorities_set_id: SetId, + authorities_set: VoterSet, + raw_justification: &[u8], +) -> Result<(), Error> +where + Header::Number: finality_grandpa::BlockNumberOps, +{ + // decode justification first + let justification = + GrandpaJustification::

::decode(&mut &raw_justification[..]).map_err(|_| Error::JustificationDecode)?; + + // ensure that it is justification for the expected header + if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { + return Err(Error::InvalidJustificationTarget); + } + + // validate commit of the justification (it just assumes all signatures are valid) + let ancestry_chain = AncestryChain::new(&justification.votes_ancestries); + match finality_grandpa::validate_commit(&justification.commit, &authorities_set, &ancestry_chain) { + Ok(ref result) if result.ghost().is_some() => {} + _ => return Err(Error::InvalidJustificationCommit), + } + + // now that we know that the commit is correct, check authorities signatures + let mut buf = Vec::new(); + let mut visited_hashes = BTreeSet::new(); + for signed in &justification.commit.precommits { + if !sp_finality_grandpa::check_message_signature_with_buffer( + &finality_grandpa::Message::Precommit(signed.precommit.clone()), + &signed.id, + &signed.signature, + justification.round, + authorities_set_id, + &mut buf, + ) { + return Err(Error::InvalidAuthoritySignature); + } + + if justification.commit.target_hash == signed.precommit.target_hash { + continue; + } + + match ancestry_chain.ancestry(justification.commit.target_hash, signed.precommit.target_hash) { + Ok(route) => { + // ancestry starts from parent hash but the precommit target hash has been visited + visited_hashes.insert(signed.precommit.target_hash); + visited_hashes.extend(route); + } + _ => { + // could this happen in practice? I don't think so, but original code has this check + return Err(Error::InvalidPrecommitAncestryProof); + } + } + } + + let ancestry_hashes = justification + .votes_ancestries + .iter() + .map(|h: &Header| h.hash()) + .collect(); + if visited_hashes != ancestry_hashes { + return Err(Error::InvalidPrecommitAncestries); + } + + Ok(()) +} + +/// GRANDPA justification of the bridged chain +#[derive(Decode, RuntimeDebug)] +#[cfg_attr(test, derive(codec::Encode))] +struct GrandpaJustification { + round: u64, + commit: finality_grandpa::Commit, + votes_ancestries: Vec
, +} + +/// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. +struct AncestryChain { + ancestry: BTreeMap, +} + +impl AncestryChain
{ + fn new(ancestry: &[Header]) -> AncestryChain
{ + AncestryChain { + ancestry: ancestry + .iter() + .map(|header| (header.hash(), *header.parent_hash())) + .collect(), + } + } +} + +impl finality_grandpa::Chain for AncestryChain
+where + Header::Number: finality_grandpa::BlockNumberOps, +{ + fn ancestry(&self, base: Header::Hash, block: Header::Hash) -> Result, GrandpaError> { + let mut route = Vec::new(); + let mut current_hash = block; + loop { + if current_hash == base { + break; + } + match self.ancestry.get(¤t_hash).cloned() { + Some(parent_hash) => { + current_hash = parent_hash; + route.push(current_hash); + } + _ => return Err(GrandpaError::NotDescendent), + } + } + route.pop(); // remove the base + + Ok(route) + } + + fn best_chain_containing(&self, _block: Header::Hash) -> Option<(Header::Hash, Header::Number)> { + unreachable!("is only used during voting; qed") + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use sp_core::H256; + use sp_keyring::Ed25519Keyring; + use sp_runtime::traits::BlakeTwo256; + + const TEST_GRANDPA_ROUND: u64 = 1; + const TEST_GRANDPA_SET_ID: SetId = 1; + + type TestHeader = sp_runtime::generic::Header; + + fn header(index: u8) -> TestHeader { + TestHeader::new( + index as _, + Default::default(), + Default::default(), + if index == 0 { + Default::default() + } else { + header(index - 1).hash() + }, + Default::default(), + ) + } + + fn header_id(index: u8) -> (H256, u64) { + (header(index).hash(), index as _) + } + + fn authorities_set() -> VoterSet { + VoterSet::new(vec![ + (Ed25519Keyring::Alice.public().into(), 1), + (Ed25519Keyring::Bob.public().into(), 1), + (Ed25519Keyring::Charlie.public().into(), 1), + ]) + .unwrap() + } + + fn signed_precommit( + signer: Ed25519Keyring, + target: (H256, u64), + ) -> finality_grandpa::SignedPrecommit { + let precommit = finality_grandpa::Precommit { + target_hash: target.0, + target_number: target.1, + }; + let encoded = sp_finality_grandpa::localized_payload( + TEST_GRANDPA_ROUND, + TEST_GRANDPA_SET_ID, + &finality_grandpa::Message::Precommit(precommit.clone()), + ); + let signature = signer.sign(&encoded[..]).into(); + finality_grandpa::SignedPrecommit { + precommit, + signature, + id: signer.public().into(), + } + } + + fn make_justification_for_header_1() -> GrandpaJustification { + GrandpaJustification { + round: TEST_GRANDPA_ROUND, + commit: finality_grandpa::Commit { + target_hash: header_id(1).0, + target_number: header_id(1).1, + precommits: vec![ + signed_precommit(Ed25519Keyring::Alice, header_id(2)), + signed_precommit(Ed25519Keyring::Bob, header_id(3)), + signed_precommit(Ed25519Keyring::Charlie, header_id(4)), + ], + }, + votes_ancestries: vec![header(2), header(3), header(4)], + } + } + + #[test] + fn justification_with_invalid_encoding_rejected() { + assert_eq!( + verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, authorities_set(), &[],), + Err(Error::JustificationDecode), + ); + } + + #[test] + fn justification_with_invalid_target_rejected() { + assert_eq!( + verify_justification::( + header_id(2), + TEST_GRANDPA_SET_ID, + authorities_set(), + &make_justification_for_header_1().encode(), + ), + Err(Error::InvalidJustificationTarget), + ); + } + + #[test] + fn justification_with_invalid_commit_rejected() { + let mut justification = make_justification_for_header_1(); + justification.commit.precommits.clear(); + + assert_eq!( + verify_justification::( + header_id(1), + TEST_GRANDPA_SET_ID, + authorities_set(), + &justification.encode(), + ), + Err(Error::InvalidJustificationCommit), + ); + } + + #[test] + fn justification_with_invalid_authority_signature_rejected() { + let mut justification = make_justification_for_header_1(); + justification.commit.precommits[0].signature = Default::default(); + + assert_eq!( + verify_justification::( + header_id(1), + TEST_GRANDPA_SET_ID, + authorities_set(), + &justification.encode(), + ), + Err(Error::InvalidAuthoritySignature), + ); + } + + #[test] + fn justification_with_invalid_precommit_ancestry() { + let mut justification = make_justification_for_header_1(); + justification.votes_ancestries.push(header(10)); + + assert_eq!( + verify_justification::( + header_id(1), + TEST_GRANDPA_SET_ID, + authorities_set(), + &justification.encode(), + ), + Err(Error::InvalidPrecommitAncestries), + ); + } + + #[test] + fn valid_justification_accepted() { + assert_eq!( + verify_justification::( + header_id(1), + TEST_GRANDPA_SET_ID, + authorities_set(), + &make_justification_for_header_1().encode(), + ), + Ok(()), + ); + } +} diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 034c56a8a46ca..ec00311e6eabe 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -14,4 +14,5 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +mod justification; mod storage_proof; From 5d249d4005fc17cb65ef275abf3579c0af38eb8c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 17 Sep 2020 07:31:22 -0400 Subject: [PATCH 0158/1210] Rename Ethereum Headers to AuraHeader (#354) * Rename Header to AuraHeader This prevents some type conflicts with the PolkadotJS Apps types. * Fix test and benchmark builds * Update AuraHeader in types.json --- bin/rialto-runtime/src/kovan.rs | 6 ++-- bin/rialto-runtime/src/lib.rs | 4 +-- bin/rialto-runtime/src/rialto.rs | 6 ++-- modules/ethereum/src/benchmarking.rs | 2 +- modules/ethereum/src/finality.rs | 12 +++---- modules/ethereum/src/import.rs | 10 +++--- modules/ethereum/src/lib.rs | 40 +++++++++++------------ modules/ethereum/src/mock.rs | 12 ++++--- modules/ethereum/src/test_utils.rs | 26 +++++++-------- modules/ethereum/src/validators.rs | 12 +++---- modules/ethereum/src/verification.rs | 30 ++++++++--------- primitives/ethereum-poa/src/lib.rs | 8 ++--- primitives/ethereum-poa/src/signatures.rs | 10 +++--- relays/ethereum/src/rpc.rs | 3 +- relays/ethereum/src/substrate_client.rs | 2 +- relays/ethereum/src/substrate_types.rs | 2 +- 16 files changed, 94 insertions(+), 91 deletions(-) diff --git a/bin/rialto-runtime/src/kovan.rs b/bin/rialto-runtime/src/kovan.rs index 189333a83c590..d0b59478d22ea 100644 --- a/bin/rialto-runtime/src/kovan.rs +++ b/bin/rialto-runtime/src/kovan.rs @@ -16,7 +16,7 @@ use crate::exchange::EthereumTransactionInclusionProof; -use bp_eth_poa::{Address, Header, RawTransaction, U256}; +use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; use bp_header_chain::BaseHeaderChain; use frame_support::RuntimeDebug; use hex_literal::hex; @@ -95,8 +95,8 @@ pub fn genesis_validators() -> Vec
{ } /// Genesis header of the Kovan chain. -pub fn genesis_header() -> Header { - Header { +pub fn genesis_header() -> AuraHeader { + AuraHeader { parent_hash: Default::default(), timestamp: 0, number: 0, diff --git a/bin/rialto-runtime/src/lib.rs b/bin/rialto-runtime/src/lib.rs index a00733ae74fa6..8ae3faebebb44 100644 --- a/bin/rialto-runtime/src/lib.rs +++ b/bin/rialto-runtime/src/lib.rs @@ -526,7 +526,7 @@ impl_runtime_apis! { (finalized_block.number, finalized_block.hash) } - fn is_import_requires_receipts(header: bp_eth_poa::Header) -> bool { + fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool { BridgeRialto::is_import_requires_receipts(header) } @@ -546,7 +546,7 @@ impl_runtime_apis! { (finalized_block.number, finalized_block.hash) } - fn is_import_requires_receipts(header: bp_eth_poa::Header) -> bool { + fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool { BridgeKovan::is_import_requires_receipts(header) } diff --git a/bin/rialto-runtime/src/rialto.rs b/bin/rialto-runtime/src/rialto.rs index 03f8c40650885..4e92e800eccdc 100644 --- a/bin/rialto-runtime/src/rialto.rs +++ b/bin/rialto-runtime/src/rialto.rs @@ -16,7 +16,7 @@ use crate::exchange::EthereumTransactionInclusionProof; -use bp_eth_poa::{Address, Header, RawTransaction, U256}; +use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; use bp_header_chain::BaseHeaderChain; use frame_support::RuntimeDebug; use hex_literal::hex; @@ -70,8 +70,8 @@ pub fn genesis_validators() -> Vec
{ /// ```bash /// $ http localhost:8545 jsonrpc=2.0 id=1 method=eth_getBlockByNumber params:='["earliest", false]' -v /// ``` -pub fn genesis_header() -> Header { - Header { +pub fn genesis_header() -> AuraHeader { + AuraHeader { parent_hash: Default::default(), timestamp: 0, number: 0, diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index b088c49bec812..2dd58d664822f 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -218,7 +218,7 @@ benchmarks_instance! { } } -fn initialize_bench, I: Instance>(num_validators: usize) -> Header { +fn initialize_bench, I: Instance>(num_validators: usize) -> AuraHeader { // Initialize storage with some initial header let initial_header = build_genesis_header(&validator(0)); let initial_difficulty = initial_header.difficulty; diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 4d836cd8a5224..e53ce91ed3cf9 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -16,7 +16,7 @@ use crate::error::Error; use crate::Storage; -use bp_eth_poa::{public_to_address, Address, Header, HeaderId, SealedEmptyStep, H256}; +use bp_eth_poa::{public_to_address, Address, AuraHeader, HeaderId, SealedEmptyStep, H256}; use codec::{Decode, Encode}; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_runtime::RuntimeDebug; @@ -37,7 +37,7 @@ pub struct CachedFinalityVotes { pub stopped_at_finalized_sibling: bool, /// Header ancestors that were read while we have been searching for /// cached votes entry. Newest header has index 0. - pub unaccounted_ancestry: VecDeque<(HeaderId, Option, Header)>, + pub unaccounted_ancestry: VecDeque<(HeaderId, Option, AuraHeader)>, /// Cached finality votes, if they have been found. The associated /// header is not included into `unaccounted_ancestry`. pub votes: Option>, @@ -86,7 +86,7 @@ pub fn finalize_blocks( header_validators: (HeaderId, &[Address]), id: HeaderId, submitter: Option<&S::Submitter>, - header: &Header, + header: &AuraHeader, two_thirds_majority_transition: u64, ) -> Result, Error> { // compute count of voters for every unfinalized block in ancestry @@ -145,7 +145,7 @@ fn prepare_votes( best_finalized: HeaderId, validators: &BTreeSet<&Address>, id: HeaderId, - header: &Header, + header: &AuraHeader, submitter: Option, ) -> Result, Error> { // if we have reached finalized block sibling, then we're trying @@ -243,7 +243,7 @@ fn remove_signers_votes(signers_to_remove: &BTreeSet
, votes: &mut BTree } /// Returns unique set of empty steps signers. -fn empty_steps_signers(header: &Header) -> BTreeSet
{ +fn empty_steps_signers(header: &AuraHeader) -> BTreeSet
{ header .empty_steps() .into_iter() @@ -298,7 +298,7 @@ mod tests { (Default::default(), &[]), Default::default(), None, - &Header::default(), + &AuraHeader::default(), 0, ), Err(Error::NotValidator), diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 97f423b2d9296..977ffd6718159 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -19,7 +19,7 @@ use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::{is_importable_header, verify_aura_header}; use crate::{AuraConfiguration, ChangeToEnact, PruningStrategy, Storage}; -use bp_eth_poa::{Header, HeaderId, Receipt}; +use bp_eth_poa::{AuraHeader, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// Imports bunch of headers and updates blocks finality. @@ -37,7 +37,7 @@ pub fn import_headers( aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, submitter: Option, - headers: Vec<(Header, Option>)>, + headers: Vec<(AuraHeader, Option>)>, finalized_headers: &mut BTreeMap, ) -> Result<(u64, u64), Error> { let mut useful = 0; @@ -85,7 +85,7 @@ pub fn import_header( aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, submitter: Option, - header: Header, + header: AuraHeader, receipts: Option>, ) -> Result<(HeaderId, FinalizedHeaders), Error> { // first check that we are able to import this header at all @@ -153,7 +153,7 @@ pub fn import_header( pub fn header_import_requires_receipts( storage: &S, validators_config: &ValidatorsConfiguration, - header: &Header, + header: &AuraHeader, ) -> bool { is_importable_header(storage, header) .map(|_| Validators::new(validators_config)) @@ -391,7 +391,7 @@ mod tests { fn import_custom_block( storage: &mut S, validators: &[SecretKey], - header: Header, + header: AuraHeader, ) -> Result { let id = header.compute_id(); import_header( diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index bbb2ba2956197..afc5c681a39a4 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -19,7 +19,7 @@ #![allow(clippy::large_enum_variant)] use crate::finality::{CachedFinalityVotes, FinalityVotes}; -use bp_eth_poa::{Address, Header, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; +use bp_eth_poa::{Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; use codec::{Decode, Encode}; use frame_support::{decl_module, decl_storage, traits::Get}; use sp_runtime::{ @@ -91,7 +91,7 @@ pub struct StoredHeader { /// using unsigned transaction. pub submitter: Option, /// The block header itself. - pub header: Header, + pub header: AuraHeader, /// Total difficulty of the chain. pub total_difficulty: U256, /// The ID of set of validators that is expected to produce direct descendants of @@ -138,7 +138,7 @@ pub struct HeaderToImport { /// The id of the header. pub id: HeaderId, /// The header itself. - pub header: Header, + pub header: AuraHeader, /// Total chain difficulty at the header. pub total_difficulty: U256, /// New validators set and the hash of block where it has been scheduled (if applicable). @@ -185,7 +185,7 @@ struct PruningRange { pub struct ImportContext { submitter: Option, parent_hash: H256, - parent_header: Header, + parent_header: AuraHeader, parent_total_difficulty: U256, parent_scheduled_change: Option, validators_set_id: u64, @@ -200,7 +200,7 @@ impl ImportContext { } /// Returns reference to parent header. - pub fn parent_header(&self) -> &Header { + pub fn parent_header(&self) -> &AuraHeader { &self.parent_header } @@ -242,7 +242,7 @@ impl ImportContext { self, is_best: bool, id: HeaderId, - header: Header, + header: AuraHeader, total_difficulty: U256, enacted_change: Option, scheduled_change: Option>, @@ -275,7 +275,7 @@ pub trait Storage { /// Get imported header by its hash. /// /// Returns header and its submitter (if known). - fn header(&self, hash: &H256) -> Option<(Header, Option)>; + fn header(&self, hash: &H256) -> Option<(AuraHeader, Option)>; /// Returns latest cached finality votes (if any) for block ancestors, starting /// from `parent_hash` block and stopping at genesis block, best finalized block /// or block where `stop_at` returns true. @@ -375,7 +375,7 @@ decl_module! { pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Import single Aura header. Requires transaction to be **UNSIGNED**. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_unsigned_header(origin, header: Header, receipts: Option>) { + pub fn import_unsigned_header(origin, header: AuraHeader, receipts: Option>) { frame_system::ensure_none(origin)?; import::import_header( @@ -396,7 +396,7 @@ decl_module! { /// This should be used with caution - passing too many headers could lead to /// enormous block production/import time. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_signed_headers(origin, headers_with_receipts: Vec<(Header, Option>)>) { + pub fn import_signed_headers(origin, headers_with_receipts: Vec<(AuraHeader, Option>)>) { let submitter = frame_system::ensure_signed(origin)?; let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( @@ -459,7 +459,7 @@ decl_storage! { ScheduledChanges: map hasher(identity) H256 => Option; } add_extra_genesis { - config(initial_header): Header; + config(initial_header): AuraHeader; config(initial_difficulty): U256; config(initial_validators): Vec
; build(|config| { @@ -496,7 +496,7 @@ impl, I: Instance> Module { } /// Returns true if the import of given block requires transactions receipts. - pub fn is_import_requires_receipts(header: Header) -> bool { + pub fn is_import_requires_receipts(header: AuraHeader) -> bool { import::header_import_requires_receipts( &BridgeStorage::::new(), &T::ValidatorsConfiguration::get(), @@ -670,7 +670,7 @@ impl, I: Instance> Storage for BridgeStorage { FinalizedBlock::::get() } - fn header(&self, hash: &H256) -> Option<(Header, Option)> { + fn header(&self, hash: &H256) -> Option<(AuraHeader, Option)> { Headers::::get(hash).map(|header| (header.header, header.submitter)) } @@ -840,7 +840,7 @@ impl, I: Instance> Storage for BridgeStorage { /// Initialize storage. #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] pub(crate) fn initialize_storage, I: Instance>( - initial_header: &Header, + initial_header: &AuraHeader, initial_difficulty: U256, initial_validators: &[Address], ) { @@ -1004,7 +1004,7 @@ fn pool_configuration() -> PoolConfiguration { } /// Return iterator of given header ancestors. -fn ancestry<'a, S: Storage>(storage: &'a S, mut parent_hash: H256) -> impl Iterator + 'a { +fn ancestry<'a, S: Storage>(storage: &'a S, mut parent_hash: H256) -> impl Iterator + 'a { sp_std::iter::from_fn(move || { let (header, _) = storage.header(&parent_hash)?; if header.number == 0 { @@ -1044,8 +1044,8 @@ pub(crate) mod tests { .rlp() } - fn example_header_with_failed_receipt() -> Header { - let mut header = Header::default(); + fn example_header_with_failed_receipt() -> AuraHeader { + let mut header = AuraHeader::default(); header.number = 3; header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); header.receipts_root = compute_merkle_root(vec![example_tx_receipt(false)].into_iter()); @@ -1053,8 +1053,8 @@ pub(crate) mod tests { header } - fn example_header() -> Header { - let mut header = Header::default(); + fn example_header() -> AuraHeader { + let mut header = AuraHeader::default(); header.number = 2; header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); header.receipts_root = compute_merkle_root(vec![example_tx_receipt(true)].into_iter()); @@ -1062,8 +1062,8 @@ pub(crate) mod tests { header } - fn example_header_parent() -> Header { - let mut header = Header::default(); + fn example_header_parent() -> AuraHeader { + let mut header = AuraHeader::default(); header.number = 1; header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); header.receipts_root = compute_merkle_root(vec![example_tx_receipt(true)].into_iter()); diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 66d63d28d0911..db84afacc4960 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -19,7 +19,7 @@ pub use bp_eth_poa::signatures::secret_to_address; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; use crate::{AuraConfiguration, GenesisConfig, PruningStrategy, Trait}; -use bp_eth_poa::{Address, Header, H256, U256}; +use bp_eth_poa::{Address, AuraHeader, H256, U256}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use secp256k1::SecretKey; use sp_runtime::{ @@ -89,7 +89,7 @@ impl Trait for TestRuntime { /// Test context. pub struct TestContext { /// Initial (genesis) header. - pub genesis: Header, + pub genesis: AuraHeader, /// Number of initial validators. pub total_validators: usize, /// Secret keys of validators, ordered by validator index. @@ -118,7 +118,7 @@ pub fn test_validators_config() -> ValidatorsConfiguration { } /// Genesis header that is used in tests by default. -pub fn genesis() -> Header { +pub fn genesis() -> AuraHeader { HeaderBuilder::genesis().sign_by(&validator(0)) } @@ -128,7 +128,11 @@ pub fn run_test(total_validators: usize, test: impl FnOnce(TestContext) -> T) } /// Run test with default genesis header. -pub fn run_test_with_genesis(genesis: Header, total_validators: usize, test: impl FnOnce(TestContext) -> T) -> T { +pub fn run_test_with_genesis( + genesis: AuraHeader, + total_validators: usize, + test: impl FnOnce(TestContext) -> T, +) -> T { let validators = validators(total_validators); let addresses = validators_addresses(total_validators); sp_io::TestExternalities::new( diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 37f7a7a0298b5..b669856fdb445 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -32,7 +32,7 @@ use crate::{HeaderToImport, Storage, Trait}; use bp_eth_poa::{ rlp_encode, signatures::{secret_to_address, sign, SignHeader}, - Address, Bloom, Header, Receipt, SealedEmptyStep, H256, U256, + Address, AuraHeader, Bloom, Receipt, SealedEmptyStep, H256, U256, }; use secp256k1::SecretKey; use sp_std::prelude::*; @@ -42,8 +42,8 @@ pub const GAS_LIMIT: u64 = 0x2000; /// Test header builder. pub struct HeaderBuilder { - header: Header, - parent_header: Header, + header: AuraHeader, + parent_header: AuraHeader, } impl HeaderBuilder { @@ -51,7 +51,7 @@ impl HeaderBuilder { pub fn genesis() -> Self { let current_step = 0u64; Self { - header: Header { + header: AuraHeader { gas_limit: GAS_LIMIT.into(), seal: vec![bp_eth_poa::rlp_encode(¤t_step), vec![]], ..Default::default() @@ -93,7 +93,7 @@ impl HeaderBuilder { /// Creates default header on top of non-existent parent. #[cfg(test)] pub fn with_number(number: u64) -> Self { - Self::with_parent(&Header { + Self::with_parent(&AuraHeader { number: number - 1, seal: vec![bp_eth_poa::rlp_encode(&(number - 1)), vec![]], ..Default::default() @@ -101,11 +101,11 @@ impl HeaderBuilder { } /// Creates default header on top of given parent. - pub fn with_parent(parent_header: &Header) -> Self { + pub fn with_parent(parent_header: &AuraHeader) -> Self { let parent_step = parent_header.step().unwrap(); let current_step = parent_step + 1; Self { - header: Header { + header: AuraHeader { parent_hash: parent_header.compute_hash(), number: parent_header.number + 1, gas_limit: GAS_LIMIT.into(), @@ -201,26 +201,26 @@ impl HeaderBuilder { } /// Signs header by given author. - pub fn sign_by(self, author: &SecretKey) -> Header { + pub fn sign_by(self, author: &SecretKey) -> AuraHeader { self.header.sign_by(author) } /// Signs header by given authors set. - pub fn sign_by_set(self, authors: &[SecretKey]) -> Header { + pub fn sign_by_set(self, authors: &[SecretKey]) -> AuraHeader { self.header.sign_by_set(authors) } } /// Helper function for getting a genesis header which has been signed by an authority. -pub fn build_genesis_header(author: &SecretKey) -> Header { +pub fn build_genesis_header(author: &SecretKey) -> AuraHeader { let genesis = HeaderBuilder::genesis(); genesis.header.sign_by(&author) } /// Helper function for building a custom child header which has been signed by an authority. -pub fn build_custom_header(author: &SecretKey, previous: &Header, customize_header: F) -> Header +pub fn build_custom_header(author: &SecretKey, previous: &AuraHeader, customize_header: F) -> AuraHeader where - F: FnOnce(Header) -> Header, + F: FnOnce(AuraHeader) -> AuraHeader, { let new_header = HeaderBuilder::with_parent(&previous); let custom_header = customize_header(new_header.header); @@ -228,7 +228,7 @@ where } /// Insert unverified header into storage. -pub fn insert_header(storage: &mut S, header: Header) { +pub fn insert_header(storage: &mut S, header: AuraHeader) { storage.insert_header(HeaderToImport { context: storage.import_context(None, &header.parent_hash).unwrap(), is_best: true, diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index e0b747fc3f029..ede479fd37881 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -16,7 +16,7 @@ use crate::error::Error; use crate::{ChangeToEnact, Storage}; -use bp_eth_poa::{Address, Header, HeaderId, LogEntry, Receipt, U256}; +use bp_eth_poa::{Address, AuraHeader, HeaderId, LogEntry, Receipt, U256}; use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. @@ -65,7 +65,7 @@ impl<'a> Validators<'a> { /// Returns true if header (probabilistically) signals validators change and /// the caller needs to provide transactions receipts to import the header. - pub fn maybe_signals_validators_change(&self, header: &Header) -> bool { + pub fn maybe_signals_validators_change(&self, header: &AuraHeader) -> bool { let (_, _, source) = self.source_at(header.number); // if we are taking validators set from the fixed list, there's always @@ -95,7 +95,7 @@ impl<'a> Validators<'a> { /// current block). The second element is the immediately applied change. pub fn extract_validators_change( &self, - header: &Header, + header: &AuraHeader, receipts: Option>, ) -> Result<(ValidatorsChange, ValidatorsChange), Error> { // let's first check if new source is starting from this header @@ -325,7 +325,7 @@ pub(crate) mod tests { // when contract is active, but bloom has no required bits set let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); let validators = Validators::new(&config); - let mut header = Header::default(); + let mut header = AuraHeader::default(); header.number = u64::max_value(); assert!(!validators.maybe_signals_validators_change(&header)); @@ -347,7 +347,7 @@ pub(crate) mod tests { (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), ]); let validators = Validators::new(&config); - let mut header = Header::default(); + let mut header = AuraHeader::default(); // when we're at the block that switches to list source header.number = 100; @@ -420,7 +420,7 @@ pub(crate) mod tests { let finalized_blocks = vec![(id10, None), (id100, None)]; let header100 = StoredHeader:: { submitter: None, - header: Header { + header: AuraHeader { number: 100, ..Default::default() }, diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 115867d284e24..c9592c567efe9 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -18,7 +18,7 @@ use crate::error::Error; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::{AuraConfiguration, ImportContext, PoolConfiguration, ScheduledChange, Storage}; use bp_eth_poa::{ - public_to_address, step_validator, Address, Header, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, + public_to_address, step_validator, Address, AuraHeader, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, }; use codec::Encode; use sp_io::crypto::secp256k1_ecdsa_recover; @@ -28,7 +28,7 @@ use sp_std::{vec, vec::Vec}; /// Pre-check to see if should try and import this header. /// Returns error if we should not try to import this block. /// Returns ID of passed header and best finalized header. -pub fn is_importable_header(storage: &S, header: &Header) -> Result<(HeaderId, HeaderId), Error> { +pub fn is_importable_header(storage: &S, header: &AuraHeader) -> Result<(HeaderId, HeaderId), Error> { // we never import any header that competes with finalized header let finalized_id = storage.finalized_block(); if header.number <= finalized_id.number { @@ -51,7 +51,7 @@ pub fn accept_aura_header_into_pool( config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, pool_config: &PoolConfiguration, - header: &Header, + header: &AuraHeader, receipts: Option<&Vec>, ) -> Result<(Vec, Vec), Error> { // check if we can verify further @@ -157,7 +157,7 @@ pub fn verify_aura_header( storage: &S, config: &AuraConfiguration, submitter: Option, - header: &Header, + header: &AuraHeader, ) -> Result, Error> { // let's do the lightest check first contextless_checks(config, header)?; @@ -180,7 +180,7 @@ pub fn verify_aura_header( } /// Perform basic checks that only require header itself. -fn contextless_checks(config: &AuraConfiguration, header: &Header) -> Result<(), Error> { +fn contextless_checks(config: &AuraConfiguration, header: &AuraHeader) -> Result<(), Error> { let expected_seal_fields = expected_header_seal_fields(config, header); if header.seal.len() != expected_seal_fields { return Err(Error::InvalidSealArity); @@ -215,7 +215,7 @@ fn contextual_checks( config: &AuraConfiguration, context: &ImportContext, validators_override: Option<&[Address]>, - header: &Header, + header: &AuraHeader, ) -> Result { let validators = validators_override.unwrap_or_else(|| &context.validators_set().validators); let header_step = header.step().ok_or(Error::MissingStep)?; @@ -273,7 +273,7 @@ fn contextual_checks( fn validator_checks( config: &AuraConfiguration, validators: &[Address], - header: &Header, + header: &AuraHeader, header_step: u64, ) -> Result<(), Error> { let expected_validator = *step_validator(validators, header_step); @@ -294,7 +294,7 @@ fn validator_checks( } /// Returns expected number of seal fields in the header. -fn expected_header_seal_fields(config: &AuraConfiguration, header: &Header) -> usize { +fn expected_header_seal_fields(config: &AuraConfiguration, header: &AuraHeader) -> usize { if header.number != u64::max_value() && header.number >= config.empty_steps_transition { 3 } else { @@ -374,23 +374,23 @@ mod tests { const GENESIS_STEP: u64 = 42; const TOTAL_VALIDATORS: usize = 3; - fn genesis() -> Header { + fn genesis() -> AuraHeader { HeaderBuilder::genesis().step(GENESIS_STEP).sign_by(&validator(0)) } - fn verify_with_config(config: &AuraConfiguration, header: &Header) -> Result, Error> { + fn verify_with_config(config: &AuraConfiguration, header: &AuraHeader) -> Result, Error> { run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); verify_aura_header(&storage, &config, None, header) }) } - fn default_verify(header: &Header) -> Result, Error> { + fn default_verify(header: &AuraHeader) -> Result, Error> { verify_with_config(&test_aura_config(), header) } fn default_accept_into_pool( - mut make_header: impl FnMut(&[SecretKey]) -> (Header, Option>), + mut make_header: impl FnMut(&[SecretKey]) -> (AuraHeader, Option>), ) -> Result<(Vec, Vec), Error> { run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let validators = vec![validator(0), validator(1), validator(2)]; @@ -457,7 +457,7 @@ mod tests { #[test] fn verifies_seal_count() { // when there are no seals at all - let mut header = Header::default(); + let mut header = AuraHeader::default(); assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); // when there's single seal (we expect 2 or 3 seals) @@ -568,7 +568,7 @@ mod tests { #[test] fn verifies_step() { // when step is missing from seals - let mut header = Header { + let mut header = AuraHeader { seal: vec![vec![], vec![]], gas_limit: test_aura_config().min_gas_limit, parent_hash: genesis().compute_hash(), @@ -694,7 +694,7 @@ mod tests { fn pool_rejects_headers_without_required_receipts() { assert_eq!( default_accept_into_pool(|_| ( - Header { + AuraHeader { number: 20_000_000, seal: vec![vec![], vec![]], gas_limit: test_aura_config().min_gas_limit, diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index a2a2b9366b6e7..5229522b02123 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -68,7 +68,7 @@ pub struct HeaderId { /// An Aura header. #[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Header { +pub struct AuraHeader { /// Parent block hash. pub parent_hash: H256, /// Block timestamp. @@ -182,7 +182,7 @@ pub struct SealedEmptyStep { pub step: u64, } -impl Header { +impl AuraHeader { /// Compute id of this header. pub fn compute_id(&self) -> HeaderId { HeaderId { @@ -558,7 +558,7 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (u64, H256); /// Returns true if the import of given block requires transactions receipts. - fn is_import_requires_receipts(header: Header) -> bool; + fn is_import_requires_receipts(header: AuraHeader) -> bool; /// Returns true if header is known to the runtime. fn is_known_block(hash: H256) -> bool; } @@ -573,7 +573,7 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (u64, H256); /// Returns true if the import of given block requires transactions receipts. - fn is_import_requires_receipts(header: Header) -> bool; + fn is_import_requires_receipts(header: AuraHeader) -> bool; /// Returns true if header is known to the runtime. fn is_known_block(hash: H256) -> bool; } diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs index 4d97fbcbfbd1a..cab8fdfa2f435 100644 --- a/primitives/ethereum-poa/src/signatures.rs +++ b/primitives/ethereum-poa/src/signatures.rs @@ -23,8 +23,8 @@ pub use secp256k1::SecretKey; use crate::{ - public_to_address, rlp_encode, step_validator, Address, Header, RawTransaction, UnsignedTransaction, H256, H520, - U256, + public_to_address, rlp_encode, step_validator, Address, AuraHeader, RawTransaction, UnsignedTransaction, H256, + H520, U256, }; use secp256k1::{Message, PublicKey}; @@ -32,9 +32,9 @@ use secp256k1::{Message, PublicKey}; /// Utilities for signing headers. pub trait SignHeader { /// Signs header by given author. - fn sign_by(self, author: &SecretKey) -> Header; + fn sign_by(self, author: &SecretKey) -> AuraHeader; /// Signs header by given authors set. - fn sign_by_set(self, authors: &[SecretKey]) -> Header; + fn sign_by_set(self, authors: &[SecretKey]) -> AuraHeader; } /// Utilities for signing transactions. @@ -43,7 +43,7 @@ pub trait SignTransaction { fn sign_by(self, author: &SecretKey, chain_id: Option) -> RawTransaction; } -impl SignHeader for Header { +impl SignHeader for AuraHeader { fn sign_by(mut self, author: &SecretKey) -> Self { self.author = secret_to_address(author); diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs index fd108f8963fef..64b70093f12d4 100644 --- a/relays/ethereum/src/rpc.rs +++ b/relays/ethereum/src/rpc.rs @@ -17,7 +17,6 @@ //! RPC Module #![warn(missing_docs)] - // The compiler doesn't think we're using the // code from rpc_api! #![allow(dead_code)] @@ -35,7 +34,7 @@ use crate::substrate_types::{ }; use async_trait::async_trait; -use bp_eth_poa::Header as SubstrateEthereumHeader; +use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; type Result = result::Result; type GrandpaAuthorityList = Vec; diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index 1d3e5d03199fd..e6004be1f7e77 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -23,7 +23,7 @@ use crate::sync_types::SubmittedHeaders; use crate::utils::HeaderId; use async_trait::async_trait; -use bp_eth_poa::Header as SubstrateEthereumHeader; +use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; use codec::{Decode, Encode}; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 87931957ad3b2..05b96c037ff1e 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -23,7 +23,7 @@ use crate::utils::HeaderId; use codec::Encode; pub use bp_eth_poa::{ - Address, Bloom, Bytes, Header as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, + Address, AuraHeader as SubstrateEthereumHeader, Bloom, Bytes, LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, }; From 56c0ed406e8915c50bbc55e7d24711b44699b32b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 17 Sep 2020 15:51:33 +0300 Subject: [PATCH 0159/1210] Relay receiving + processing confirmations (#351) * relay receiving + processing confirmations * fmt && clippy * removed message processing race * remove more traces * generic args names --- relays/ethereum/src/main.rs | 1 + relays/ethereum/src/message_lane.rs | 16 +- relays/ethereum/src/message_lane_loop.rs | 103 ++++++++++-- relays/ethereum/src/message_race_delivery.rs | 102 ++++++++---- relays/ethereum/src/message_race_receiving.rs | 152 ++++++++++++++++++ 5 files changed, 328 insertions(+), 46 deletions(-) create mode 100644 relays/ethereum/src/message_race_receiving.rs diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 82dfb08209c2e..16f9d3e79c2f0 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -31,6 +31,7 @@ mod message_lane; mod message_lane_loop; mod message_race_delivery; mod message_race_loop; +mod message_race_receiving; mod metrics; mod rpc; mod rpc_errors; diff --git a/relays/ethereum/src/message_lane.rs b/relays/ethereum/src/message_lane.rs index 7ca8d2e9fb980..0635456c40641 100644 --- a/relays/ethereum/src/message_lane.rs +++ b/relays/ethereum/src/message_lane.rs @@ -17,11 +17,11 @@ //! One-way message lane types. Within single one-way lane we have three 'races' where we try to: //! //! 1) relay new messages from source to target node; -//! 2) relay proof-of-receiving from target to source node; -//! 3) relay proof-of-processing from target no source node. +//! 2) relay proof-of-receiving from target to source node. use crate::utils::HeaderId; +use num_traits::{One, Zero}; use std::fmt::Debug; /// One-way message lane. @@ -32,10 +32,20 @@ pub trait MessageLane { const TARGET_NAME: &'static str; /// Message nonce type. - type MessageNonce: Clone + Copy + Debug + Default + From + Ord + std::ops::Add; + type MessageNonce: Clone + + Copy + + Debug + + Default + + From + + Ord + + std::ops::Add + + One + + Zero; /// Messages proof. type MessagesProof: Clone; + /// Messages receiving proof. + type MessagesReceivingProof: Clone; /// Number of the source header. type SourceHeaderNumber: Clone + Debug + Default + Ord + PartialEq; diff --git a/relays/ethereum/src/message_lane_loop.rs b/relays/ethereum/src/message_lane_loop.rs index 03cc2929b3a70..0618382b83954 100644 --- a/relays/ethereum/src/message_lane_loop.rs +++ b/relays/ethereum/src/message_lane_loop.rs @@ -29,6 +29,7 @@ use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_race_delivery::run as run_message_delivery_race; +use crate::message_race_receiving::run as run_message_receiving_race; use crate::utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use async_trait::async_trait; @@ -52,6 +53,11 @@ pub trait SourceClient: Clone { &self, id: SourceHeaderIdOf

, ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error>; + /// Get nonce of the latest message, which receiving has been confirmed by the target chain. + async fn latest_confirmed_received_nonce( + &self, + id: SourceHeaderIdOf

, + ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error>; /// Prove messages in inclusive range [begin; end]. async fn prove_messages( @@ -59,6 +65,13 @@ pub trait SourceClient: Clone { id: SourceHeaderIdOf

, nonces: RangeInclusive, ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error>; + + /// Submit messages receiving proof. + async fn submit_messages_receiving_proof( + &self, + generated_at_block: TargetHeaderIdOf

, + proof: P::MessagesReceivingProof, + ) -> Result, Self::Error>; } /// Target client trait. @@ -73,12 +86,18 @@ pub trait TargetClient: Clone { /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; - /// Get nonce of latest message, which receival has been confirmed. + /// Get nonce of latest received message. async fn latest_received_nonce( &self, id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error>; + /// Prove messages receiving at given block. + async fn prove_messages_receiving( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error>; + /// Submit messages proof. async fn submit_messages_proof( &self, @@ -196,6 +215,19 @@ async fn run_until_connection_lost, TC: Targ ) .fuse(); + let ( + (receiving_source_state_sender, receiving_source_state_receiver), + (receiving_target_state_sender, receiving_target_state_receiver), + ) = (unbounded(), unbounded()); + let receiving_race_loop = run_message_receiving_race( + source_client.clone(), + receiving_source_state_receiver, + target_client.clone(), + receiving_target_state_receiver, + stall_timeout, + ) + .fuse(); + let exit_signal = exit_signal.fuse(); futures::pin_mut!( @@ -206,6 +238,7 @@ async fn run_until_connection_lost, TC: Targ target_go_offline_future, target_tick_stream, delivery_race_loop, + receiving_race_loop, exit_signal ); @@ -224,7 +257,8 @@ async fn run_until_connection_lost, TC: Targ P::SOURCE_NAME, new_source_state, ); - let _ = delivery_source_state_sender.unbounded_send(new_source_state); + let _ = delivery_source_state_sender.unbounded_send(new_source_state.clone()); + let _ = receiving_source_state_sender.unbounded_send(new_source_state.clone()); }, &mut source_go_offline_future, |delay| async_std::task::sleep(delay), @@ -250,7 +284,8 @@ async fn run_until_connection_lost, TC: Targ P::TARGET_NAME, new_target_state, ); - let _ = delivery_target_state_sender.unbounded_send(new_target_state); + let _ = delivery_target_state_sender.unbounded_send(new_target_state.clone()); + let _ = receiving_target_state_sender.unbounded_send(new_target_state.clone()); }, &mut target_go_offline_future, |delay| async_std::task::sleep(delay), @@ -270,6 +305,12 @@ async fn run_until_connection_lost, TC: Targ Err(err) => return Err(err), } }, + receiving_error = receiving_race_loop => { + match receiving_error { + Ok(_) => unreachable!("only ends with error; qed"), + Err(err) => return Err(err), + } + }, () = exit_signal => { return Ok(()); @@ -304,6 +345,7 @@ pub(crate) mod tests { pub type TestMessageNonce = u64; pub type TestMessagesProof = RangeInclusive; + pub type TestMessagesReceivingProof = TestMessageNonce; pub type TestSourceHeaderNumber = u64; pub type TestSourceHeaderHash = u64; @@ -333,7 +375,9 @@ pub(crate) mod tests { const TARGET_NAME: &'static str = "TestTarget"; type MessageNonce = TestMessageNonce; + type MessagesProof = TestMessagesProof; + type MessagesReceivingProof = TestMessagesReceivingProof; type SourceHeaderNumber = TestSourceHeaderNumber; type SourceHeaderHash = TestSourceHeaderHash; @@ -348,6 +392,8 @@ pub(crate) mod tests { is_source_reconnected: bool, source_state: SourceClientState, source_latest_generated_nonce: TestMessageNonce, + source_latest_confirmed_received_nonce: TestMessageNonce, + submitted_messages_receiving_proofs: Vec, is_target_fails: bool, is_target_reconnected: bool, target_state: SourceClientState, @@ -383,7 +429,6 @@ pub(crate) mod tests { Ok(data.source_state.clone()) } - /// Get nonce of instance of latest generated message. async fn latest_generated_nonce( &self, id: SourceHeaderIdOf, @@ -396,6 +441,15 @@ pub(crate) mod tests { Ok((id, data.source_latest_generated_nonce)) } + async fn latest_confirmed_received_nonce( + &self, + id: SourceHeaderIdOf, + ) -> Result<(SourceHeaderIdOf, TestMessageNonce), Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + Ok((id, data.source_latest_confirmed_received_nonce)) + } + async fn prove_messages( &self, id: SourceHeaderIdOf, @@ -410,6 +464,18 @@ pub(crate) mod tests { > { Ok((id, nonces.clone(), nonces)) } + + async fn submit_messages_receiving_proof( + &self, + _generated_at_block: TargetHeaderIdOf, + proof: TestMessagesReceivingProof, + ) -> Result, Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + data.submitted_messages_receiving_proofs.push(proof); + data.source_latest_confirmed_received_nonce = proof; + Ok(proof..=proof) + } } #[derive(Clone)] @@ -452,7 +518,13 @@ pub(crate) mod tests { Ok((id, data.target_latest_received_nonce)) } - /// Submit messages proof. + async fn prove_messages_receiving( + &self, + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, TestMessagesReceivingProof), Self::Error> { + Ok((id, self.data.lock().target_latest_received_nonce)) + } + async fn submit_messages_proof( &self, _generated_at_header: SourceHeaderIdOf, @@ -570,16 +642,22 @@ pub(crate) mod tests { }, Arc::new(|_: &mut TestClientData| {}), Arc::new(move |data: &mut TestClientData| { - if data.target_state.best_peer.0 < 10 { + // syncing source headers -> target chain (by one) + if data.target_state.best_peer.0 < data.source_state.best_self.0 { data.target_state.best_peer = HeaderId(data.target_state.best_peer.0 + 1, data.target_state.best_peer.0 + 1); } - if data - .submitted_messages_proofs - .last() - .map(|last| *last.end() == 10) - .unwrap_or(false) - { + // syncing source headers -> target chain (all at once) + if data.source_state.best_peer.0 < data.target_state.best_self.0 { + data.source_state.best_peer = data.target_state.best_self; + } + // if target has received all messages => increase target block so that confirmations may be sent + if data.target_latest_received_nonce == 10 { + data.target_state.best_self = + HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.0 + 1); + } + // if source has received all messages receiving confirmations => increase source block so that confirmations may be sent + if data.source_latest_confirmed_received_nonce == 10 { exit_sender.unbounded_send(()).unwrap(); } }), @@ -587,5 +665,6 @@ pub(crate) mod tests { ); assert_eq!(result.submitted_messages_proofs, vec![1..=4, 5..=8, 9..=10],); + assert!(!result.submitted_messages_receiving_proofs.is_empty()); } } diff --git a/relays/ethereum/src/message_race_delivery.rs b/relays/ethereum/src/message_race_delivery.rs index a0039909789f9..d55b8353ee4dc 100644 --- a/relays/ethereum/src/message_race_delivery.rs +++ b/relays/ethereum/src/message_race_delivery.rs @@ -19,10 +19,11 @@ use crate::message_lane_loop::{ TargetClientState, }; use crate::message_race_loop::{MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; -use crate::utils::FailedClient; +use crate::utils::{FailedClient, HeaderId}; use async_trait::async_trait; use futures::stream::FusedStream; +use num_traits::{One, Zero}; use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Maximal number of messages to relay in single transaction. @@ -48,7 +49,7 @@ pub async fn run( }, target_state_updates, stall_timeout, - MessageDeliveryStrategy::

::default(), + MessageDeliveryStrategy::

::new(MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX.into()), ) .await } @@ -135,34 +136,60 @@ where } } -/// Message delivery strategy. -struct MessageDeliveryStrategy { +/// Messages delivery strategy. +type MessageDeliveryStrategy

= DeliveryStrategy< +

::SourceHeaderNumber, +

::SourceHeaderHash, +

::TargetHeaderNumber, +

::TargetHeaderHash, +

::MessageNonce, +

::MessagesProof, +>; + +/// Nonces delivery strategy. +#[derive(Debug)] +pub struct DeliveryStrategy { /// All queued nonces. - source_queue: VecDeque<(SourceHeaderIdOf

, P::MessageNonce)>, + source_queue: VecDeque<(HeaderId, Nonce)>, /// Best nonce known to target node. - target_nonce: P::MessageNonce, + target_nonce: Nonce, + /// Max nonces to relay in single transaction. + max_nonces_to_relay_in_single_tx: Nonce, /// Unused generic types dump. - _phantom: PhantomData

, + _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, } -impl Default for MessageDeliveryStrategy

{ - fn default() -> Self { - MessageDeliveryStrategy { +impl + DeliveryStrategy +{ + /// Create new delivery strategy. + pub fn new(max_nonces_to_relay_in_single_tx: Nonce) -> Self { + DeliveryStrategy { source_queue: VecDeque::new(), target_nonce: Default::default(), + max_nonces_to_relay_in_single_tx, _phantom: Default::default(), } } } -impl RaceStrategy, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof> - for MessageDeliveryStrategy

+impl + RaceStrategy< + HeaderId, + HeaderId, + Nonce, + Proof, + > for DeliveryStrategy +where + SourceHeaderHash: Clone, + SourceHeaderNumber: Clone + Ord, + Nonce: Clone + Copy + From + Ord + std::ops::Add + One + Zero, { fn is_empty(&self) -> bool { self.source_queue.is_empty() } - fn source_nonce_updated(&mut self, at_block: SourceHeaderIdOf

, nonce: P::MessageNonce) { + fn source_nonce_updated(&mut self, at_block: HeaderId, nonce: Nonce) { if nonce <= self.target_nonce { return; } @@ -178,8 +205,13 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M fn target_nonce_updated( &mut self, - nonce: P::MessageNonce, - race_state: &mut RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, + nonce: Nonce, + race_state: &mut RaceState< + HeaderId, + HeaderId, + Nonce, + Proof, + >, ) { if nonce < self.target_nonce { return; @@ -216,8 +248,13 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M fn select_nonces_to_deliver( &mut self, - race_state: &RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, - ) -> Option> { + race_state: &RaceState< + HeaderId, + HeaderId, + Nonce, + Proof, + >, + ) -> Option> { // if we have already selected nonces that we want to submit, do nothing if race_state.nonces_to_submit.is_some() { return None; @@ -229,18 +266,19 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M } // 1) we want to deliver all nonces, starting from `target_nonce + 1` - // 2) we want to deliver at most `MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX` nonces in this batch + // 2) we want to deliver at most `self.max_nonces_to_relay_in_single_tx` nonces in this batch // 3) we can't deliver new nonce until header, that has emitted this nonce, is finalized // by target client let nonces_begin = self.target_nonce + 1.into(); let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; let mut nonces_end = None; - for i in 0..MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX { - let nonce = nonces_begin + i.into(); + let mut i = Zero::zero(); + while i < self.max_nonces_to_relay_in_single_tx { + let nonce = nonces_begin + i; // if queue is empty, we don't need to prove anything let (first_queued_at, first_queued_nonce) = match self.source_queue.front() { - Some((first_queued_at, first_queued_nonce)) => (first_queued_at.clone(), *first_queued_nonce), + Some((first_queued_at, first_queued_nonce)) => ((*first_queued_at).clone(), *first_queued_nonce), None => break, }; @@ -257,6 +295,8 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M if nonce == first_queued_nonce { self.source_queue.pop_front(); } + + i = i + One::one(); } nonces_end.map(|nonces_end| RangeInclusive::new(nonces_begin, nonces_end)) @@ -273,7 +313,7 @@ mod tests { #[test] fn strategy_is_empty_works() { - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); assert_eq!(strategy.is_empty(), true); strategy.source_nonce_updated(header_id(1), 1); assert_eq!(strategy.is_empty(), false); @@ -281,7 +321,7 @@ mod tests { #[test] fn source_nonce_is_never_lower_than_known_target_nonce() { - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); strategy.target_nonce_updated(10, &mut Default::default()); strategy.source_nonce_updated(header_id(1), 5); assert_eq!(strategy.source_queue, vec![]); @@ -289,7 +329,7 @@ mod tests { #[test] fn source_nonce_is_never_lower_than_latest_known_source_nonce() { - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); strategy.source_nonce_updated(header_id(1), 5); strategy.source_nonce_updated(header_id(2), 3); strategy.source_nonce_updated(header_id(2), 5); @@ -298,7 +338,7 @@ mod tests { #[test] fn target_nonce_is_never_lower_than_latest_known_target_nonce() { - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); strategy.target_nonce_updated(10, &mut Default::default()); strategy.target_nonce_updated(5, &mut Default::default()); assert_eq!(strategy.target_nonce, 10); @@ -306,7 +346,7 @@ mod tests { #[test] fn updated_target_nonce_removes_queued_entries() { - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); strategy.source_nonce_updated(header_id(1), 5); strategy.source_nonce_updated(header_id(2), 10); strategy.source_nonce_updated(header_id(3), 15); @@ -318,7 +358,7 @@ mod tests { #[test] fn selected_nonces_are_dropped_on_target_nonce_update() { let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); state.nonces_to_submit = Some((header_id(1), 5..=10, 5..=10)); strategy.target_nonce_updated(7, &mut state); assert!(state.nonces_to_submit.is_some()); @@ -329,7 +369,7 @@ mod tests { #[test] fn submitted_nonces_are_dropped_on_target_nonce_update() { let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); state.nonces_submitted = Some(5..=10); strategy.target_nonce_updated(7, &mut state); assert!(state.nonces_submitted.is_some()); @@ -340,7 +380,7 @@ mod tests { #[test] fn nothing_is_selected_if_something_is_already_selected() { let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); state.nonces_to_submit = Some((header_id(1), 1..=10, 1..=10)); strategy.source_nonce_updated(header_id(1), 10); assert_eq!(strategy.select_nonces_to_deliver(&state), None); @@ -349,7 +389,7 @@ mod tests { #[test] fn nothing_is_selected_if_something_is_already_submitted() { let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); state.nonces_submitted = Some(1..=10); strategy.source_nonce_updated(header_id(1), 10); assert_eq!(strategy.select_nonces_to_deliver(&state), None); @@ -358,7 +398,7 @@ mod tests { #[test] fn select_nonces_to_deliver_works() { let mut state = RaceState::<_, _, TestMessageNonce, TestMessagesProof>::default(); - let mut strategy = MessageDeliveryStrategy::::default(); + let mut strategy = MessageDeliveryStrategy::::new(4); strategy.source_nonce_updated(header_id(1), 1); strategy.source_nonce_updated(header_id(2), 2); strategy.source_nonce_updated(header_id(3), 6); diff --git a/relays/ethereum/src/message_race_receiving.rs b/relays/ethereum/src/message_race_receiving.rs new file mode 100644 index 0000000000000..a50b713f0bd7c --- /dev/null +++ b/relays/ethereum/src/message_race_receiving.rs @@ -0,0 +1,152 @@ +// Copyright 2019-2020 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. + +use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; +use crate::message_lane_loop::{ + SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, + TargetClientState, +}; +use crate::message_race_delivery::DeliveryStrategy; +use crate::message_race_loop::{MessageRace, SourceClient, TargetClient}; +use crate::utils::FailedClient; + +use async_trait::async_trait; +use futures::stream::FusedStream; +use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; + +/// Message receiving confirmations delivery strategy. +type ReceivingConfirmationsDeliveryStrategy

= DeliveryStrategy< +

::TargetHeaderNumber, +

::TargetHeaderHash, +

::SourceHeaderNumber, +

::SourceHeaderHash, +

::MessageNonce, +

::MessagesReceivingProof, +>; + +/// Run receiving confirmations race. +pub async fn run( + source_client: impl MessageLaneSourceClient

, + source_state_updates: impl FusedStream>, + target_client: impl MessageLaneTargetClient

, + target_state_updates: impl FusedStream>, + stall_timeout: Duration, +) -> Result<(), FailedClient> { + crate::message_race_loop::run( + ReceivingConfirmationsRaceSource { + client: target_client, + _phantom: Default::default(), + }, + target_state_updates, + ReceivingConfirmationsRaceTarget { + client: source_client, + _phantom: Default::default(), + }, + source_state_updates, + stall_timeout, + ReceivingConfirmationsDeliveryStrategy::

::new(std::u32::MAX.into()), + ) + .await +} + +/// Messages receiving confirmations race. +struct ReceivingConfirmationsRace

(std::marker::PhantomData

); + +impl MessageRace for ReceivingConfirmationsRace

{ + type SourceHeaderId = TargetHeaderIdOf

; + type TargetHeaderId = SourceHeaderIdOf

; + + type MessageNonce = P::MessageNonce; + type Proof = P::MessagesReceivingProof; + + fn source_name() -> String { + format!("{}::ReceivingConfirmationsDelivery", P::SOURCE_NAME) + } + + fn target_name() -> String { + format!("{}::ReceivingConfirmationsDelivery", P::TARGET_NAME) + } +} + +/// Message receiving confirmations race source, which is a target of the lane. +struct ReceivingConfirmationsRaceSource { + client: C, + _phantom: PhantomData

, +} + +#[async_trait(?Send)] +impl SourceClient> for ReceivingConfirmationsRaceSource +where + P: MessageLane, + C: MessageLaneTargetClient

, +{ + type Error = C::Error; + + async fn latest_nonce( + &self, + at_block: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { + self.client.latest_received_nonce(at_block).await + } + + async fn generate_proof( + &self, + at_block: TargetHeaderIdOf

, + nonces: RangeInclusive, + ) -> Result< + ( + TargetHeaderIdOf

, + RangeInclusive, + P::MessagesReceivingProof, + ), + Self::Error, + > { + self.client + .prove_messages_receiving(at_block) + .await + .map(|(at_block, proof)| (at_block, nonces, proof)) + } +} + +/// Message receiving confirmations race target, which is a source of the lane. +struct ReceivingConfirmationsRaceTarget { + client: C, + _phantom: PhantomData

, +} + +#[async_trait(?Send)] +impl TargetClient> for ReceivingConfirmationsRaceTarget +where + P: MessageLane, + C: MessageLaneSourceClient

, +{ + type Error = C::Error; + + async fn latest_nonce( + &self, + at_block: SourceHeaderIdOf

, + ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { + self.client.latest_confirmed_received_nonce(at_block).await + } + + async fn submit_proof( + &self, + generated_at_block: TargetHeaderIdOf

, + _nonces: RangeInclusive, + proof: P::MessagesReceivingProof, + ) -> Result, Self::Error> { + self.client + .submit_messages_receiving_proof(generated_at_block, proof) + .await + } +} From 5fd363cb58ea0425b4930a628a04aca6fdba4f94 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 17 Sep 2020 20:18:47 +0300 Subject: [PATCH 0160/1210] Support user-provided origins in Call-dispatch module (#355) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * call dispatch origin * Update modules/call-dispatch/src/lib.rs Co-authored-by: Tomasz Drwięga * cargo fmt --all Co-authored-by: Tomasz Drwięga --- bin/millau-runtime/src/lib.rs | 5 +- bin/rialto-runtime/src/lib.rs | 5 +- modules/call-dispatch/src/lib.rs | 342 +++++++++++++++++++++++++++---- 3 files changed, 305 insertions(+), 47 deletions(-) diff --git a/bin/millau-runtime/src/lib.rs b/bin/millau-runtime/src/lib.rs index 864fb8256c00e..93ae91ea9c04c 100644 --- a/bin/millau-runtime/src/lib.rs +++ b/bin/millau-runtime/src/lib.rs @@ -38,7 +38,7 @@ use sp_runtime::traits::{ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, + ApplyExtrinsicResult, MultiSignature, MultiSigner, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -222,6 +222,9 @@ impl pallet_bridge_call_dispatch::Trait for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; + type SourceChainAccountPublic = MultiSigner; + type TargetChainAccountPublic = MultiSigner; + type TargetChainSignature = MultiSignature; } impl pallet_grandpa::Trait for Runtime { diff --git a/bin/rialto-runtime/src/lib.rs b/bin/rialto-runtime/src/lib.rs index 8ae3faebebb44..2ef00bf9e1603 100644 --- a/bin/rialto-runtime/src/lib.rs +++ b/bin/rialto-runtime/src/lib.rs @@ -45,7 +45,7 @@ use sp_runtime::traits::{ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, + ApplyExtrinsicResult, MultiSignature, MultiSigner, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -271,6 +271,9 @@ impl pallet_bridge_call_dispatch::Trait for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; + type SourceChainAccountPublic = MultiSigner; + type TargetChainAccountPublic = MultiSigner; + type TargetChainSignature = MultiSignature; } pub struct DepositInto; diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 03da86ec0e4e2..205c0cbfc00d8 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -28,13 +28,20 @@ use bp_message_dispatch::{MessageDispatch, Weight}; use bp_runtime::{bridge_account_id, InstanceId, CALL_DISPATCH_MODULE_PREFIX}; +use codec::{Decode, Encode}; use frame_support::{ - decl_event, decl_module, + decl_event, decl_module, decl_storage, dispatch::{Dispatchable, Parameter}, traits::Get, weights::{extract_actual_weight, GetDispatchInfo}, + RuntimeDebug, }; -use sp_runtime::DispatchResult; +use frame_system::{ensure_root, ensure_signed, RawOrigin}; +use sp_runtime::{ + traits::{BadOrigin, IdentifyAccount, Verify}, + DispatchResult, +}; +use sp_std::{marker::PhantomData, prelude::*}; /// Spec version type. pub type SpecVersion = u32; @@ -43,14 +50,56 @@ pub type SpecVersion = u32; /// Weight of single deposit_event() call. const DEPOSIT_EVENT_WEIGHT: Weight = 0; +/// Origin of the call on the target chain. +#[derive(RuntimeDebug, Encode, Decode, Clone)] +pub enum CallOrigin { + /// Call is originated from bridge account, which is (designed to be) specific to + /// the single deployed instance of the messages bridge (message-lane, ...) module. + /// It is assumed that this account is not controlled by anyone and has zero balance + /// (unless someone would make transfer by mistake?). + /// If we trust the source chain to allow sending calls with that origin in case they originate + /// from source chain `root` account (default implementation), `BridgeAccount` represents the + /// source-chain-root origin on the target chain and can be used to send and authorize + /// "control plane" messages between the two runtimes. + BridgeAccount, + /// Call is originated from account, identified by `TargetChainAccountPublic`. The proof + /// that the `SourceChainAccountPublic` controls `TargetChainAccountPublic` is the + /// `TargetChainSignature` over `(Call, SourceChainAccountPublic).encode()`. + /// The source chain must ensure that the message is sent by the owner of + /// `SourceChainAccountPublic` account (use the `fn verify_sending_message()`). + RealAccount(SourceChainAccountPublic, TargetChainAccountPublic, TargetChainSignature), +} + +/// Message payload type used by call-dispatch module. +#[derive(RuntimeDebug, Encode, Decode, Clone)] +pub struct MessagePayload { + /// Runtime specification version. We only dispatch messages that have the same + /// runtime version. Otherwise we risk to misinterpret encoded calls. + pub spec_version: SpecVersion, + /// Weight of the call, declared by the message sender. If it is less than actual + /// static weight, the call is not dispatched. + pub weight: Weight, + /// Call origin to be used during dispatch. + pub origin: CallOrigin, + /// The call itself. + pub call: Call, +} + /// The module configuration trait. -pub trait Trait: frame_system::Trait { +pub trait Trait: frame_system::Trait { /// The overarching event type. - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; /// Id of the message. Whenever message is passed to the dispatch module, it emits /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if /// it comes from message-lane module. type MessageId: Parameter; + /// Type of account public key on source chain. + type SourceChainAccountPublic: Parameter; + /// Type of account public key on target chain. + type TargetChainAccountPublic: Parameter + IdentifyAccount; + /// Type of signature that may prove that the message has been signed by + /// owner of `TargetChainAccountPublic`. + type TargetChainSignature: Parameter + Verify; /// The overarching dispatch call type. type Call: Parameter + GetDispatchInfo @@ -60,9 +109,14 @@ pub trait Trait: frame_system::Trait { >; } +decl_storage! { + trait Store for Module, I: Instance = DefaultInstance> as CallDispatch { + } +} + decl_event!( - pub enum Event where - ::MessageId, + pub enum Event where + >::MessageId { /// Message has been rejected by dispatcher because of spec version mismatch. /// Last two arguments are: expected and passed spec version. @@ -70,41 +124,48 @@ decl_event!( /// Message has been rejected by dispatcher because of weight mismatch. /// Last two arguments are: expected and passed call weight. MessageWeightMismatch(InstanceId, MessageId, Weight, Weight), + /// Message signature mismatch. + MessageSignatureMismatch(InstanceId, MessageId), /// Message has been dispatched with given result. MessageDispatched(InstanceId, MessageId, DispatchResult), + /// Phantom member, never used. + Dummy(PhantomData), } ); decl_module! { /// Call Dispatch FRAME Pallet. - pub struct Module for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; } } -impl MessageDispatch for Module { - type Message = (SpecVersion, Weight, ::Call); +impl, I: Instance> MessageDispatch for Module { + type Message = MessagePayload< + T::SourceChainAccountPublic, + T::TargetChainAccountPublic, + T::TargetChainSignature, + >::Call, + >; fn dispatch(bridge: InstanceId, id: T::MessageId, message: Self::Message) -> Weight { - let (spec_version, weight, call) = message; - // verify spec version // (we want it to be the same, because otherwise we may decode Call improperly) let expected_version = ::Version::get().spec_version; - if spec_version != expected_version { + if message.spec_version != expected_version { frame_support::debug::trace!( "Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}", bridge, id, expected_version, - spec_version, + message.spec_version, ); - Self::deposit_event(Event::::MessageVersionSpecMismatch( + Self::deposit_event(RawEvent::MessageVersionSpecMismatch( bridge, id, expected_version, - spec_version, + message.spec_version, )); return DEPOSIT_EVENT_WEIGHT; } @@ -112,23 +173,53 @@ impl MessageDispatch for Module { // verify weight // (we want passed weight to be at least equal to pre-dispatch weight of the call // because otherwise Calls may be dispatched at lower price) - let dispatch_info = call.get_dispatch_info(); + let dispatch_info = message.call.get_dispatch_info(); let expected_weight = dispatch_info.weight; - if weight < expected_weight { + if message.weight < expected_weight { frame_support::debug::trace!( "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", bridge, id, expected_weight, - weight, + message.weight, ); - Self::deposit_event(Event::::MessageWeightMismatch(bridge, id, expected_weight, weight)); + Self::deposit_event(RawEvent::MessageWeightMismatch( + bridge, + id, + expected_weight, + message.weight, + )); return DEPOSIT_EVENT_WEIGHT; } + // prepare dispatch origin + let origin_account = match message.origin { + CallOrigin::BridgeAccount => bridge_account_id(bridge, CALL_DISPATCH_MODULE_PREFIX), + CallOrigin::RealAccount(source_public, target_public, target_signature) => { + let mut signed_message = Vec::new(); + message.call.encode_to(&mut signed_message); + source_public.encode_to(&mut signed_message); + + let target_account = target_public.into_account(); + if !target_signature.verify(&signed_message[..], &target_account) { + frame_support::debug::trace!( + "Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}", + bridge, + id, + target_account, + target_signature, + ); + Self::deposit_event(RawEvent::MessageSignatureMismatch(bridge, id)); + return DEPOSIT_EVENT_WEIGHT; + } + + target_account + } + }; + // finally dispatch message - let origin_account = bridge_account_id(bridge, CALL_DISPATCH_MODULE_PREFIX); - let dispatch_result = call.dispatch(frame_system::RawOrigin::Signed(origin_account).into()); + let origin = RawOrigin::Signed(origin_account).into(); + let dispatch_result = message.call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); frame_support::debug::trace!( "Message {:?}/{:?} has been dispatched. Result: {:?}", @@ -137,7 +228,7 @@ impl MessageDispatch for Module { dispatch_result, ); - Self::deposit_event(Event::::MessageDispatched( + Self::deposit_event(RawEvent::MessageDispatched( bridge, id, dispatch_result.map(drop).map_err(|e| e.error), @@ -147,6 +238,39 @@ impl MessageDispatch for Module { } } +/// Verify payload of the message at the sending side. +pub fn verify_sending_message< + ThisChainOuterOrigin, + ThisChainAccountId, + SourceChainAccountPublic, + TargetChainAccountPublic, + TargetChainSignature, + Call, +>( + sender_origin: ThisChainOuterOrigin, + message: &MessagePayload, +) -> Result, BadOrigin> +where + ThisChainOuterOrigin: Into, ThisChainOuterOrigin>>, + TargetChainAccountPublic: Clone + IdentifyAccount, + ThisChainAccountId: PartialEq, +{ + match message.origin { + CallOrigin::BridgeAccount => { + ensure_root(sender_origin)?; + Ok(None) + } + CallOrigin::RealAccount(ref this_account_public, _, _) => { + let this_chain_account_id = ensure_signed(sender_origin)?; + if this_chain_account_id != this_account_public.clone().into_account() { + return Err(BadOrigin); + } + + Ok(Some(this_chain_account_id)) + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -165,6 +289,28 @@ mod tests { type MessageId = [u8; 4]; + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] + pub struct TestAccountPublic(AccountId); + + impl IdentifyAccount for TestAccountPublic { + type AccountId = AccountId; + + fn into_account(self) -> AccountId { + self.0 + } + } + + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] + pub struct TestSignature(AccountId); + + impl Verify for TestSignature { + type Signer = TestAccountPublic; + + fn verify>(&self, _msg: L, signer: &AccountId) -> bool { + self.0 == *signer + } + } + #[derive(Clone, Eq, PartialEq)] pub struct TestRuntime; @@ -228,9 +374,15 @@ mod tests { impl Trait for TestRuntime { type Event = TestEvent; type MessageId = MessageId; + type SourceChainAccountPublic = TestAccountPublic; + type TargetChainAccountPublic = TestAccountPublic; + type TargetChainSignature = TestSignature; type Call = Call; } + const TEST_SPEC_VERSION: SpecVersion = 0; + const TEST_WEIGHT: Weight = 1_000_000_000; + fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::default() .build_storage::() @@ -238,16 +390,24 @@ mod tests { sp_io::TestExternalities::new(t) } + fn prepare_bridge_message( + call: Call, + ) -> as MessageDispatch<::MessageId>>::Message { + MessagePayload { + spec_version: TEST_SPEC_VERSION, + weight: TEST_WEIGHT, + origin: CallOrigin::BridgeAccount, + call, + } + } + #[test] fn should_succesfuly_dispatch_remark() { new_test_ext().execute_with(|| { let origin = b"ethb".to_owned(); let id = [0; 4]; - let message = ( - 0, - 1_000_000_000, - Call::System(>::remark(vec![1, 2, 3])), - ); + let message = + prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); System::set_block_number(1); CallDispatch::dispatch(origin, id, message); @@ -268,11 +428,9 @@ mod tests { new_test_ext().execute_with(|| { let origin = b"ethb".to_owned(); let id = [0; 4]; - let message = ( - 69, - 1_000_000, - Call::System(>::remark(vec![1, 2, 3])), - ); + let mut message = + prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); + message.origin = CallOrigin::RealAccount(TestAccountPublic(2), TestAccountPublic(2), TestSignature(1)); System::set_block_number(1); CallDispatch::dispatch(origin, id, message); @@ -281,9 +439,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageVersionSpecMismatch( - origin, id, 0, 69, - )), + event: TestEvent::call_dispatch(Event::::MessageSignatureMismatch(origin, id,)), topics: vec![], }], ); @@ -295,11 +451,9 @@ mod tests { new_test_ext().execute_with(|| { let origin = b"ethb".to_owned(); let id = [0; 4]; - let message = ( - 0, - 0, - Call::System(>::remark(vec![1, 2, 3])), - ); + let mut message = + prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); + message.weight = 0; System::set_block_number(1); CallDispatch::dispatch(origin, id, message); @@ -318,15 +472,38 @@ mod tests { } #[test] - fn should_dispatch_from_non_root_origin() { + fn should_fail_on_signature_mismatch() { new_test_ext().execute_with(|| { let origin = b"ethb".to_owned(); let id = [0; 4]; - let message = ( - 0, - 1_000_000, - Call::System(>::fill_block(Perbill::from_percent(10))), + let mut message = + prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); + message.weight = 0; + + System::set_block_number(1); + CallDispatch::dispatch(origin, id, message); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( + origin, id, 1305000, 0, + )), + topics: vec![], + }], ); + }); + } + + #[test] + fn should_dispatch_bridge_message_from_non_root_origin() { + new_test_ext().execute_with(|| { + let origin = b"ethb".to_owned(); + let id = [0; 4]; + let message = prepare_bridge_message(Call::System(>::fill_block( + Perbill::from_percent(10), + ))); System::set_block_number(1); CallDispatch::dispatch(origin, id, message); @@ -345,4 +522,79 @@ mod tests { ); }); } + + #[test] + fn dispatch_supports_different_accounts() { + fn dispatch_suicide(call_origin: CallOrigin) { + let origin = b"ethb".to_owned(); + let id = [0; 4]; + let mut message = prepare_bridge_message(Call::System(>::suicide())); + message.origin = call_origin; + + System::set_block_number(1); + CallDispatch::dispatch(origin, id, message); + } + + new_test_ext().execute_with(|| { + // 'create' real account + let real_account_id = 1; + System::inc_account_nonce(real_account_id); + // 'create' bridge account + let bridge_account_id: AccountId = bridge_account_id(*b"ethb", CALL_DISPATCH_MODULE_PREFIX); + System::inc_account_nonce(bridge_account_id); + + assert_eq!(System::account_nonce(real_account_id), 1); + assert_eq!(System::account_nonce(bridge_account_id), 1); + + // kill real account + dispatch_suicide(CallOrigin::RealAccount( + TestAccountPublic(real_account_id), + TestAccountPublic(real_account_id), + TestSignature(real_account_id), + )); + assert_eq!(System::account_nonce(real_account_id), 0); + assert_eq!(System::account_nonce(bridge_account_id), 1); + + // kill bridge account + dispatch_suicide(CallOrigin::BridgeAccount); + assert_eq!(System::account_nonce(real_account_id), 0); + assert_eq!(System::account_nonce(bridge_account_id), 0); + }); + } + + #[test] + fn origin_is_checked_when_verify_sending_message() { + let mut message = prepare_bridge_message(Call::System(>::suicide())); + + // when message is sent by root, CallOrigin::BridgeAccount is allowed + assert!(matches!( + verify_sending_message(Origin::from(RawOrigin::Root), &message), + Ok(None) + )); + + // when message is sent by some real account, CallOrigin::BridgeAccount is not allowed + assert!(matches!( + verify_sending_message(Origin::from(RawOrigin::Signed(1)), &message), + Err(BadOrigin) + )); + + // when message is sent by root, CallOrigin::RealAccount is not allowed + message.origin = CallOrigin::RealAccount(TestAccountPublic(2), TestAccountPublic(2), TestSignature(2)); + assert!(matches!( + verify_sending_message(Origin::from(RawOrigin::Root), &message), + Err(BadOrigin) + )); + + // when message is sent by some other account, it is rejected + assert!(matches!( + verify_sending_message(Origin::from(RawOrigin::Signed(1)), &message), + Err(BadOrigin) + )); + + // when message is sent real account, it is allowed to have origin CallOrigin::RealAccount + assert!(matches!( + verify_sending_message(Origin::from(RawOrigin::Signed(2)), &message), + Ok(Some(2)) + )); + } } From 7d7ea19f343c8a1d25afc530528b43e681283aaa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 18 Sep 2020 10:34:08 +0300 Subject: [PATCH 0161/1210] Extract (headers, exchange, messages) relay loops into separate crates (#357) * extracted relay crates * moved metrics to utils * exchange-relay compilation * fix compilation of headers-relay * fixed messages-relay compilation * fixed ethereum-poa-relay compilation * cargo lock * cargo fmt --all * clippy * cargo fmt --all * fix tests compilation * clippy * eof * module level docs * removed obsolete comment * #![warn(missing_docs)] * .0 -> Deref * post-merge fix * cargo fmt * Update relays/headers-relay/src/headers.rs Co-authored-by: Hernando Castano * Update relays/headers-relay/src/headers.rs Co-authored-by: Hernando Castano * Update relays/headers-relay/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- relays/ethereum/Cargo.toml | 10 +- relays/ethereum/src/ethereum_client.rs | 30 ++-- .../ethereum/src/ethereum_deploy_contract.rs | 2 +- relays/ethereum/src/ethereum_exchange.rs | 13 +- relays/ethereum/src/ethereum_sync_loop.rs | 20 +-- relays/ethereum/src/ethereum_types.rs | 26 +++- relays/ethereum/src/instances.rs | 4 +- relays/ethereum/src/main.rs | 54 +++---- relays/ethereum/src/rpc_errors.rs | 3 +- relays/ethereum/src/substrate_client.rs | 4 +- relays/ethereum/src/substrate_sync_loop.rs | 19 +-- relays/ethereum/src/substrate_types.rs | 25 +++- relays/exchange-relay/Cargo.toml | 16 +++ .../src/exchange.rs | 9 +- .../src/exchange_loop.rs | 10 +- .../src/exchange_loop_metrics.rs | 11 +- relays/exchange-relay/src/lib.rs | 26 ++++ relays/headers-relay/Cargo.toml | 17 +++ .../src/headers.rs | 134 +++++++++--------- relays/headers-relay/src/lib.rs | 33 +++++ .../{ethereum => headers-relay}/src/sync.rs | 53 ++----- .../src/sync_loop.rs | 15 +- .../src/sync_loop_metrics.rs | 11 +- .../src/sync_loop_tests.rs | 28 ++-- .../src/sync_types.rs | 9 +- relays/messages-relay/Cargo.toml | 15 ++ relays/messages-relay/src/lib.rs | 32 +++++ .../src/message_lane.rs | 2 +- .../src/message_lane_loop.rs | 4 +- .../src/message_race_delivery.rs | 2 +- .../src/message_race_loop.rs | 2 +- .../src/message_race_receiving.rs | 4 +- relays/utils/Cargo.toml | 16 +++ .../src/utils.rs => utils/src/lib.rs} | 10 +- relays/{ethereum => utils}/src/metrics.rs | 7 +- 35 files changed, 435 insertions(+), 241 deletions(-) create mode 100644 relays/exchange-relay/Cargo.toml rename relays/{ethereum => exchange-relay}/src/exchange.rs (99%) rename relays/{ethereum => exchange-relay}/src/exchange_loop.rs (97%) rename relays/{ethereum => exchange-relay}/src/exchange_loop_metrics.rs (93%) create mode 100644 relays/exchange-relay/src/lib.rs create mode 100644 relays/headers-relay/Cargo.toml rename relays/{ethereum => headers-relay}/src/headers.rs (92%) create mode 100644 relays/headers-relay/src/lib.rs rename relays/{ethereum => headers-relay}/src/sync.rs (91%) rename relays/{ethereum => headers-relay}/src/sync_loop.rs (98%) rename relays/{ethereum => headers-relay}/src/sync_loop_metrics.rs (94%) rename relays/{ethereum => headers-relay}/src/sync_loop_tests.rs (96%) rename relays/{ethereum => headers-relay}/src/sync_types.rs (97%) create mode 100644 relays/messages-relay/Cargo.toml create mode 100644 relays/messages-relay/src/lib.rs rename relays/{ethereum => messages-relay}/src/message_lane.rs (98%) rename relays/{ethereum => messages-relay}/src/message_lane_loop.rs (99%) rename relays/{ethereum => messages-relay}/src/message_race_delivery.rs (99%) rename relays/{ethereum => messages-relay}/src/message_race_loop.rs (99%) rename relays/{ethereum => messages-relay}/src/message_race_receiving.rs (97%) create mode 100644 relays/utils/Cargo.toml rename relays/{ethereum/src/utils.rs => utils/src/lib.rs} (96%) rename relays/{ethereum => utils}/src/metrics.rs (98%) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 16deabd717951..1bedea7aedaa0 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,9 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" async-std = "1.6.2" -async-stream = "0.3.0" async-trait = "0.1.40" -backoff = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } clap = { version = "2.33.3", features = ["yaml"] } @@ -20,18 +18,18 @@ ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" ethereum-tx-sign = "3.0" +exchange-relay = { path = "../exchange-relay" } futures = "0.3.5" +headers-relay = { path = "../headers-relay" } hex = "0.4" hex-literal = "0.3" -linked-hash-map = "0.5.3" log = "0.4.11" +messages-relay = { path = "../messages-relay" } num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } -parking_lot = "0.11.0" -rustc-hex = "2.0.1" +relay-utils = { path = "../utils" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" -sysinfo = "0.15" time = "0.2" web3 = "0.13" diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index bfcb7d9cb2c9e..5635197d6404a 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -21,17 +21,16 @@ use crate::ethereum_types::{ use crate::rpc::{Ethereum, EthereumRpc}; use crate::rpc_errors::{EthereumNodeError, RpcError}; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; -use crate::sync_types::SubmittedHeaders; -use crate::utils::{HeaderId, MaybeConnectionError}; use async_trait::async_trait; use codec::{Decode, Encode}; use ethabi::FunctionOutputDecoder; +use headers_relay::sync_types::SubmittedHeaders; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use parity_crypto::publickey::KeyPair; - +use relay_utils::{HeaderId, MaybeConnectionError}; use std::collections::HashSet; // to encode/decode contract calls @@ -693,17 +692,20 @@ mod tests { } fn header(number: SubstrateBlockNumber) -> QueuedSubstrateHeader { - QueuedSubstrateHeader::new(SubstrateHeader::new( - number, - Default::default(), - Default::default(), - if number == 0 { - Default::default() - } else { - header(number - 1).id().1 - }, - Default::default(), - )) + QueuedSubstrateHeader::new( + SubstrateHeader::new( + number, + Default::default(), + Default::default(), + if number == 0 { + Default::default() + } else { + header(number - 1).id().1 + }, + Default::default(), + ) + .into(), + ) } #[test] diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index 94ce80706773f..b04632fc7eae0 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -21,10 +21,10 @@ use crate::instances::BridgeInstance; use crate::rpc::SubstrateRpc; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId}; -use crate::utils::HeaderId; use codec::{Decode, Encode}; use num_traits::Zero; +use relay_utils::HeaderId; /// Ethereum synchronization parameters. #[derive(Debug)] diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 666b71fa3b4e7..e5a821bf3a098 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -21,23 +21,22 @@ use crate::ethereum_types::{ EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, }; -use crate::exchange::{ - relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, - TransactionProofPipeline, -}; -use crate::exchange_loop::{run as run_loop, InMemoryStorage}; use crate::instances::BridgeInstance; -use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; use crate::substrate_types::into_substrate_ethereum_receipt; -use crate::utils::HeaderId; use async_trait::async_trait; use bp_currency_exchange::MaybeLockFundsTransaction; +use exchange_relay::exchange::{ + relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, + TransactionProofPipeline, +}; +use exchange_relay::exchange_loop::{run as run_loop, InMemoryStorage}; +use relay_utils::{metrics::MetricsParams, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::time::Duration; diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 939cad5666da2..10779845cbf24 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -17,20 +17,24 @@ //! Ethereum PoA -> Substrate synchronization. use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient}; -use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, QueuedEthereumHeader, Receipt}; +use crate::ethereum_types::{ + EthereumHeaderId, EthereumHeadersSyncPipeline, EthereumSyncHeader as Header, QueuedEthereumHeader, Receipt, +}; use crate::instances::BridgeInstance; -use crate::metrics::MetricsParams; use crate::rpc::{EthereumRpc, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumHeaders, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; use crate::substrate_types::into_substrate_ethereum_header; -use crate::sync::{HeadersSyncParams, TargetTransactionMode}; -use crate::sync_loop::{SourceClient, TargetClient}; -use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; +use headers_relay::{ + sync::{HeadersSyncParams, TargetTransactionMode}, + sync_loop::{SourceClient, TargetClient}, + sync_types::{SourceHeader, SubmittedHeaders}, +}; +use relay_utils::metrics::MetricsParams; use web3::types::H256; use std::fmt::Debug; @@ -95,11 +99,11 @@ impl SourceClient for EthereumHeadersSource { } async fn header_by_hash(&self, hash: H256) -> Result { - self.client.header_by_hash(hash).await + self.client.header_by_hash(hash).await.map(Into::into) } async fn header_by_number(&self, number: u64) -> Result { - self.client.header_by_number(number).await + self.client.header_by_number(number).await.map(Into::into) } async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), Self::Error> { @@ -199,7 +203,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { let source = EthereumHeadersSource::new(eth_client); let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign); - crate::sync_loop::run( + headers_relay::sync_loop::run( source, consts::ETHEREUM_TICK_INTERVAL, target, diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum/src/ethereum_types.rs index bdb960c8cd816..bb780d6968019 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum/src/ethereum_types.rs @@ -15,9 +15,10 @@ // along with Parity Bridges Common. If not, see . use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; -use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use crate::utils::HeaderId; + use codec::Encode; +use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use relay_utils::HeaderId; pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; @@ -34,6 +35,17 @@ pub type Transaction = web3::types::Transaction; /// Ethereum header type. pub type Header = web3::types::Block; +/// Ethereum header type used in headers sync. +#[derive(Clone, Debug, PartialEq)] +pub struct EthereumSyncHeader(Header); + +impl std::ops::Deref for EthereumSyncHeader { + type Target = Header; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + /// Ethereum header with transactions type. pub type HeaderWithTransactions = web3::types::Block; @@ -60,7 +72,7 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { type Hash = H256; type Number = u64; - type Header = Header; + type Header = EthereumSyncHeader; type Extra = Vec; type Completion = (); @@ -72,7 +84,13 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { } } -impl SourceHeader for Header { +impl From

for EthereumSyncHeader { + fn from(header: Header) -> Self { + Self(header) + } +} + +impl SourceHeader for EthereumSyncHeader { fn id(&self) -> EthereumHeaderId { HeaderId( self.number.expect(HEADER_ID_PROOF).as_u64(), diff --git a/relays/ethereum/src/instances.rs b/relays/ethereum/src/instances.rs index 4d17bcbec9b8d..6fa44740e89c7 100644 --- a/relays/ethereum/src/instances.rs +++ b/relays/ethereum/src/instances.rs @@ -53,7 +53,7 @@ impl BridgeInstance for Rialto { .into_iter() .map(|header| { ( - into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_header(&header.header()), into_substrate_ethereum_receipts(header.extra()), ) }) @@ -65,7 +65,7 @@ impl BridgeInstance for Rialto { fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(header.header()), + into_substrate_ethereum_header(&header.header()), into_substrate_ethereum_receipts(header.extra()), ); diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 16f9d3e79c2f0..85deab4f1ad4b 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -22,42 +22,28 @@ mod ethereum_exchange; mod ethereum_exchange_submit; mod ethereum_sync_loop; mod ethereum_types; -mod exchange; -mod exchange_loop; -mod exchange_loop_metrics; -mod headers; mod instances; -mod message_lane; -mod message_lane_loop; -mod message_race_delivery; -mod message_race_loop; -mod message_race_receiving; -mod metrics; mod rpc; mod rpc_errors; mod substrate_client; mod substrate_sync_loop; mod substrate_types; -mod sync; -mod sync_loop; -mod sync_loop_metrics; -mod sync_loop_tests; -mod sync_types; -mod utils; use ethereum_client::{EthereumConnectionParams, EthereumSigningParams}; use ethereum_deploy_contract::EthereumDeployContractParams; use ethereum_exchange::EthereumExchangeParams; use ethereum_exchange_submit::EthereumExchangeSubmitParams; use ethereum_sync_loop::EthereumSyncParams; +use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; use instances::{BridgeInstance, Kovan, Rialto}; use parity_crypto::publickey::{KeyPair, Secret}; +use relay_utils::metrics::MetricsParams; use sp_core::crypto::Pair; use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams}; use substrate_sync_loop::SubstrateSyncParams; -use sync::HeadersSyncParams; +use headers_relay::sync::HeadersSyncParams; use std::io::Write; fn main() { @@ -223,19 +209,28 @@ fn substrate_signing_params(matches: &clap::ArgMatches) -> Result Result { - let mut sync_params = HeadersSyncParams::ethereum_sync_default(); + use crate::ethereum_sync_loop::consts::*; + + let mut sync_params = HeadersSyncParams { + max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, + max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, + max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, + max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, + prune_depth: PRUNE_DEPTH, + target_tx_mode: TargetTransactionMode::Signed, + }; match matches.value_of("sub-tx-mode") { - Some("signed") => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, + Some("signed") => sync_params.target_tx_mode = TargetTransactionMode::Signed, Some("unsigned") => { - sync_params.target_tx_mode = sync::TargetTransactionMode::Unsigned; + sync_params.target_tx_mode = TargetTransactionMode::Unsigned; // tx pool won't accept too much unsigned transactions sync_params.max_headers_in_submitted_status = 10; } - Some("backup") => sync_params.target_tx_mode = sync::TargetTransactionMode::Backup, + Some("backup") => sync_params.target_tx_mode = TargetTransactionMode::Backup, Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), - None => sync_params.target_tx_mode = sync::TargetTransactionMode::Signed, + None => sync_params.target_tx_mode = TargetTransactionMode::Signed, } let params = EthereumSyncParams { @@ -253,6 +248,8 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result Result { + use crate::substrate_sync_loop::consts::*; + let eth_contract_address: ethereum_types::Address = if let Some(eth_contract) = matches.value_of("eth-contract") { eth_contract.parse().map_err(|e| format!("{}", e))? } else { @@ -267,7 +264,14 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result Result Result, String> { +fn metrics_params(matches: &clap::ArgMatches) -> Result, String> { if matches.is_present("no-prometheus") { return Ok(None); } - let mut metrics_params = metrics::MetricsParams::default(); + let mut metrics_params = MetricsParams::default(); if let Some(prometheus_host) = matches.value_of("prometheus-host") { metrics_params.host = prometheus_host.into(); diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 26206bdc1d6dc..747ec151f1e43 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -14,9 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::utils::MaybeConnectionError; - use jsonrpsee::client::RequestError; +use relay_utils::MaybeConnectionError; /// Contains common errors that can occur when /// interacting with a Substrate or Ethereum node diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index e6004be1f7e77..aadde0ec14f20 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -19,16 +19,16 @@ use crate::instances::BridgeInstance; use crate::rpc::{Substrate, SubstrateRpc}; use crate::rpc_errors::RpcError; use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock}; -use crate::sync_types::SubmittedHeaders; -use crate::utils::HeaderId; use async_trait::async_trait; use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; use codec::{Decode, Encode}; +use headers_relay::sync_types::SubmittedHeaders; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use num_traits::Zero; +use relay_utils::HeaderId; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; use std::collections::VecDeque; diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 4f796029a83ad..ce3a5ae4d3141 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -21,18 +21,21 @@ use crate::ethereum_client::{ }; use crate::ethereum_types::Address; use crate::instances::BridgeInstance; -use crate::metrics::MetricsParams; use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; use crate::substrate_types::{ - GrandpaJustification, Hash, Header, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, + GrandpaJustification, Hash, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, + SubstrateSyncHeader as Header, }; -use crate::sync::HeadersSyncParams; -use crate::sync_loop::{SourceClient, TargetClient}; -use crate::sync_types::{SourceHeader, SubmittedHeaders}; use async_trait::async_trait; +use headers_relay::{ + sync::HeadersSyncParams, + sync_loop::{SourceClient, TargetClient}, + sync_types::{SourceHeader, SubmittedHeaders}, +}; +use relay_utils::metrics::MetricsParams; use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; @@ -92,11 +95,11 @@ impl SourceClient for SubstrateHeadersSource { } async fn header_by_hash(&self, hash: Hash) -> Result { - self.client.header_by_hash(hash).await + self.client.header_by_hash(hash).await.map(Into::into) } async fn header_by_number(&self, number: Number) -> Result { - self.client.header_by_number(number).await + self.client.header_by_number(number).await.map(Into::into) } async fn header_completion( @@ -197,7 +200,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); - crate::sync_loop::run( + headers_relay::sync_loop::run( source, consts::SUBSTRATE_TICK_INTERVAL, target, diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 05b96c037ff1e..4f5328b778763 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -17,10 +17,10 @@ use crate::ethereum_types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, }; -use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use crate::utils::HeaderId; use codec::Encode; +use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use relay_utils::HeaderId; pub use bp_eth_poa::{ Address, AuraHeader as SubstrateEthereumHeader, Bloom, Bytes, LogEntry as SubstrateEthereumLogEntry, @@ -36,6 +36,17 @@ pub type Number = rialto_runtime::BlockNumber; /// Substrate header type. pub type Header = rialto_runtime::Header; +/// Substrate header type used in headers sync. +#[derive(Clone, Debug, PartialEq)] +pub struct SubstrateSyncHeader(Header); + +impl std::ops::Deref for SubstrateSyncHeader { + type Target = Header; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + /// Substrate signed block type. pub type SignedBlock = rialto_runtime::SignedBlock; @@ -59,7 +70,7 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { type Hash = rialto_runtime::Hash; type Number = rialto_runtime::BlockNumber; - type Header = Header; + type Header = SubstrateSyncHeader; type Extra = (); type Completion = GrandpaJustification; @@ -68,7 +79,13 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { } } -impl SourceHeader for Header { +impl From
for SubstrateSyncHeader { + fn from(header: Header) -> Self { + Self(header) + } +} + +impl SourceHeader for SubstrateSyncHeader { fn id(&self) -> SubstrateHeaderId { HeaderId(self.number, self.hash()) } diff --git a/relays/exchange-relay/Cargo.toml b/relays/exchange-relay/Cargo.toml new file mode 100644 index 0000000000000..87502fe6a6e5f --- /dev/null +++ b/relays/exchange-relay/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "exchange-relay" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +backoff = "0.2" +futures = "0.3.5" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } diff --git a/relays/ethereum/src/exchange.rs b/relays/exchange-relay/src/exchange.rs similarity index 99% rename from relays/ethereum/src/exchange.rs rename to relays/exchange-relay/src/exchange.rs index e236b9d3cf56e..0df2927d56c6e 100644 --- a/relays/ethereum/src/exchange.rs +++ b/relays/exchange-relay/src/exchange.rs @@ -16,9 +16,8 @@ //! Relaying proofs of exchange transaction. -use crate::utils::{MaybeConnectionError, StringifiedMaybeConnectionError}; - use async_trait::async_trait; +use relay_utils::{MaybeConnectionError, StringifiedMaybeConnectionError}; use std::{ fmt::{Debug, Display}, string::ToString, @@ -54,7 +53,7 @@ pub trait SourceBlock { type Transaction: SourceTransaction; /// Return hash of the block. - fn id(&self) -> crate::utils::HeaderId; + fn id(&self) -> relay_utils::HeaderId; /// Return block transactions iterator. fn transactions(&self) -> Vec; } @@ -81,7 +80,7 @@ pub type TransactionOf

= <

::Block as SourceBlo pub type TransactionHashOf

= as SourceTransaction>::Hash; /// Header id. -pub type HeaderId

= crate::utils::HeaderId, BlockNumberOf

>; +pub type HeaderId

= relay_utils::HeaderId, BlockNumberOf

>; /// Source client API. #[async_trait] @@ -443,9 +442,9 @@ async fn wait_header_finalized( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::utils::HeaderId; use parking_lot::Mutex; + use relay_utils::HeaderId; use std::{ collections::{HashMap, HashSet}, sync::Arc, diff --git a/relays/ethereum/src/exchange_loop.rs b/relays/exchange-relay/src/exchange_loop.rs similarity index 97% rename from relays/ethereum/src/exchange_loop.rs rename to relays/exchange-relay/src/exchange_loop.rs index 0da29d2324ed4..645672ba3f403 100644 --- a/relays/ethereum/src/exchange_loop.rs +++ b/relays/exchange-relay/src/exchange_loop.rs @@ -21,12 +21,14 @@ use crate::exchange::{ TransactionProofPipeline, }; use crate::exchange_loop_metrics::ExchangeLoopMetrics; -use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; -use crate::utils::retry_backoff; use backoff::backoff::Backoff; use futures::{future::FutureExt, select}; use num_traits::One; +use relay_utils::{ + metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + retry_backoff, +}; use std::{future::Future, time::Duration}; /// Delay after connection-related error happened before we'll try @@ -95,8 +97,8 @@ pub fn run( let mut state = storage.state(); let mut current_finalized_block = None; - let mut metrics_global = GlobalMetrics::new(); - let mut metrics_exch = ExchangeLoopMetrics::new(); + let mut metrics_global = GlobalMetrics::default(); + let mut metrics_exch = ExchangeLoopMetrics::default(); let metrics_enabled = metrics_params.is_some(); metrics_start( format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), diff --git a/relays/ethereum/src/exchange_loop_metrics.rs b/relays/exchange-relay/src/exchange_loop_metrics.rs similarity index 93% rename from relays/ethereum/src/exchange_loop_metrics.rs rename to relays/exchange-relay/src/exchange_loop_metrics.rs index 438360e22435b..325bfd2c9dfcd 100644 --- a/relays/ethereum/src/exchange_loop_metrics.rs +++ b/relays/exchange-relay/src/exchange_loop_metrics.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Metrics for currency-exchange relay loop. + use crate::exchange::{BlockNumberOf, RelayedBlockTransactions, TransactionProofPipeline}; -use crate::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; +use relay_utils::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; /// Exchange transactions relay metrics. pub struct ExchangeLoopMetrics { @@ -36,9 +38,8 @@ impl Metrics for ExchangeLoopMetrics { } } -impl ExchangeLoopMetrics { - /// Creates sync loop metrics. - pub fn new() -> Self { +impl Default for ExchangeLoopMetrics { + fn default() -> Self { ExchangeLoopMetrics { best_block_numbers: GaugeVec::new( Opts::new("best_block_numbers", "Best finalized block numbers"), @@ -54,7 +55,9 @@ impl ExchangeLoopMetrics { .expect("metric is static and thus valid; qed"), } } +} +impl ExchangeLoopMetrics { /// Update metrics when single block is relayed. pub fn update( &mut self, diff --git a/relays/exchange-relay/src/lib.rs b/relays/exchange-relay/src/lib.rs new file mode 100644 index 0000000000000..f975ef2aa0ff4 --- /dev/null +++ b/relays/exchange-relay/src/lib.rs @@ -0,0 +1,26 @@ +// Copyright 2019-2020 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 . + +//! Relaying [`currency-exchange`](../pallet_bridge_currency_exchange/index.html) application +//! specific data. Currency exchange application allows exchanging tokens between bridged chains. +//! This module provides entrypoints for crafting and submitting (single and multiple) +//! proof-of-exchange-at-source-chain transaction(s) to target chain. + +#![warn(missing_docs)] + +pub mod exchange; +pub mod exchange_loop; +pub mod exchange_loop_metrics; diff --git a/relays/headers-relay/Cargo.toml b/relays/headers-relay/Cargo.toml new file mode 100644 index 0000000000000..e289ac984fb86 --- /dev/null +++ b/relays/headers-relay/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "headers-relay" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +backoff = "0.2" +futures = "0.3.5" +linked-hash-map = "0.5.3" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } diff --git a/relays/ethereum/src/headers.rs b/relays/headers-relay/src/headers.rs similarity index 92% rename from relays/ethereum/src/headers.rs rename to relays/headers-relay/src/headers.rs index 991d935548adf..5800d370fba0a 100644 --- a/relays/ethereum/src/headers.rs +++ b/relays/headers-relay/src/headers.rs @@ -14,11 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Headers queue - the intermediate buffer that is filled when headers are read +//! from the source chain. Headers are removed from the queue once they become +//! known to the target chain. Inside, there are several sub-queues, where headers +//! may stay until source/target chain state isn't updated. When a header reaches the +//! `ready` sub-queue, it may be submitted to the target chain. + use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use crate::utils::HeaderId; use linked_hash_map::LinkedHashMap; use num_traits::{One, Zero}; +use relay_utils::HeaderId; use std::{ collections::{btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet}, time::{Duration, Instant}, @@ -32,7 +38,7 @@ type KnownHeaders

= /// We're trying to fetch completion data for single header at this interval. const RETRY_FETCH_COMPLETION_INTERVAL: Duration = Duration::from_secs(20); -/// Ethereum headers queue. +/// Headers queue. #[derive(Debug)] pub struct QueuedHeaders { /// Headers that are received from source node, but we (native sync code) have @@ -80,9 +86,8 @@ struct HeaderCompletion { pub completion: Completion, } -impl QueuedHeaders

{ - /// Returns new QueuedHeaders. - pub fn new() -> Self { +impl Default for QueuedHeaders

{ + fn default() -> Self { QueuedHeaders { maybe_orphan: HeadersQueue::new(), orphan: HeadersQueue::new(), @@ -98,7 +103,9 @@ impl QueuedHeaders

{ prune_border: Zero::zero(), } } +} +impl QueuedHeaders

{ /// Returns prune border. #[cfg(test)] pub fn prune_border(&self) -> P::Number { @@ -778,57 +785,56 @@ fn queued_incomplete_header( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::ethereum_types::{EthereumHeaderId, EthereumHeadersSyncPipeline, Header, H256}; + use crate::sync_loop_tests::{TestHash, TestHeader, TestHeaderId, TestHeadersSyncPipeline, TestNumber}; use crate::sync_types::QueuedHeader; - pub(crate) fn header(number: u64) -> QueuedHeader { - QueuedHeader::new(Header { - number: Some(number.into()), - hash: Some(hash(number)), + pub(crate) fn header(number: TestNumber) -> QueuedHeader { + QueuedHeader::new(TestHeader { + number, + hash: hash(number), parent_hash: hash(number - 1), - ..Default::default() }) } - pub(crate) fn hash(number: u64) -> H256 { - H256::from_low_u64_le(number) + pub(crate) fn hash(number: TestNumber) -> TestHash { + number } - pub(crate) fn id(number: u64) -> EthereumHeaderId { + pub(crate) fn id(number: TestNumber) -> TestHeaderId { HeaderId(number, hash(number)) } #[test] fn total_headers_works() { // total headers just sums up number of headers in every queue - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue.maybe_orphan.entry(1).or_default().insert( hash(1), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.maybe_orphan.entry(1).or_default().insert( hash(2), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.maybe_orphan.entry(2).or_default().insert( hash(3), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.orphan.entry(3).or_default().insert( hash(4), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.maybe_extra.entry(4).or_default().insert( hash(5), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.ready.entry(5).or_default().insert( hash(6), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.incomplete.entry(6).or_default().insert( hash(7), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.total_headers(), 7); } @@ -836,48 +842,48 @@ pub(crate) mod tests { #[test] fn best_queued_number_works() { // initially there are headers in MaybeOrphan queue only - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue.maybe_orphan.entry(1).or_default().insert( hash(1), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.maybe_orphan.entry(1).or_default().insert( hash(2), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); queue.maybe_orphan.entry(3).or_default().insert( hash(3), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 3); // and then there's better header in Orphan queue.orphan.entry(10).or_default().insert( hash(10), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 10); // and then there's better header in MaybeExtra queue.maybe_extra.entry(20).or_default().insert( hash(20), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 20); // and then there's better header in Ready queue.ready.entry(30).or_default().insert( hash(30), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 30); // and then there's better header in MaybeOrphan again queue.maybe_orphan.entry(40).or_default().insert( hash(40), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 40); // and then there's some header in Incomplete queue.incomplete.entry(50).or_default().insert( hash(50), - QueuedHeader::::new(Default::default()), + QueuedHeader::::new(Default::default()), ); assert_eq!(queue.best_queued_number(), 50); } @@ -885,7 +891,7 @@ pub(crate) mod tests { #[test] fn status_works() { // all headers are unknown initially - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); // and status is read from the KnownHeaders queue @@ -899,22 +905,22 @@ pub(crate) mod tests { #[test] fn header_works() { // initially we have oldest header #10 - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(100) ); // inserting #20 changes nothing queue.maybe_orphan.entry(20).or_default().insert(hash(1), header(101)); assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(100) ); // inserting #5 makes it oldest queue.maybe_orphan.entry(5).or_default().insert(hash(1), header(102)); assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash.unwrap(), + queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(102) ); } @@ -922,7 +928,7 @@ pub(crate) mod tests { #[test] fn header_response_works() { // when parent is Synced, we insert to MaybeExtra - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -932,7 +938,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Ready, we insert to MaybeExtra - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -942,7 +948,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Receipts, we insert to MaybeExtra - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -952,7 +958,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is MaybeExtra, we insert to MaybeExtra - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -962,7 +968,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); // when parent is Orphan, we insert to Orphan - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -972,7 +978,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); // when parent is MaybeOrphan, we insert to MaybeOrphan - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -982,7 +988,7 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); // when parent is unknown, we insert to MaybeOrphan - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue.header_response(header(101).header().clone()); assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); } @@ -996,7 +1002,7 @@ pub(crate) mod tests { // #98 in MaybeExtra // #97 in Receipts // #96 in Ready - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -1053,7 +1059,7 @@ pub(crate) mod tests { // #101 in Orphan // #102 in MaybeOrphan // #103 in Orphan - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(101) @@ -1095,7 +1101,7 @@ pub(crate) mod tests { // #102 in MaybeOrphan // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: YES, #99 is known to the Substrate runtime - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -1140,7 +1146,7 @@ pub(crate) mod tests { // #101 in MaybeOrphan // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) // and the response is: NO, #99 is NOT known to the Substrate runtime - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -1172,7 +1178,7 @@ pub(crate) mod tests { #[test] fn positive_maybe_extra_response_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -1188,7 +1194,7 @@ pub(crate) mod tests { #[test] fn negative_maybe_extra_response_works() { // when parent header is complete - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -1217,14 +1223,14 @@ pub(crate) mod tests { #[test] fn receipts_response_works() { // when parent header is complete - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) .or_default() .insert(hash(100), HeaderStatus::Extra); queue.extra.entry(100).or_default().insert(hash(100), header(100)); - queue.extra_response(&id(100), Vec::new()); + queue.extra_response(&id(100), 100_100); assert!(queue.extra.is_empty()); assert_eq!(queue.ready.len(), 1); assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); @@ -1237,7 +1243,7 @@ pub(crate) mod tests { .or_default() .insert(hash(201), HeaderStatus::Extra); queue.extra.entry(201).or_default().insert(hash(201), header(201)); - queue.extra_response(&id(201), Vec::new()); + queue.extra_response(&id(201), 201_201); assert!(queue.extra.is_empty()); assert_eq!(queue.incomplete.len(), 1); assert_eq!(queue.known_headers[&201][&hash(201)], HeaderStatus::Incomplete); @@ -1245,7 +1251,7 @@ pub(crate) mod tests { #[test] fn header_submitted_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(100) @@ -1259,7 +1265,7 @@ pub(crate) mod tests { #[test] fn incomplete_header_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); // nothing to complete if queue is empty assert_eq!(queue.incomplete_header(), None); @@ -1282,7 +1288,7 @@ pub(crate) mod tests { #[test] fn completion_response_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue.incomplete_headers.insert(id(100), None); queue.incomplete_headers.insert(id(200), Some(Instant::now())); @@ -1299,18 +1305,18 @@ pub(crate) mod tests { assert_eq!(queue.header_to_complete(), None); // when response is Some, we're scheduling completion - queue.completion_response(&id(200), Some(())); + queue.completion_response(&id(200), Some(200_200)); assert_eq!(queue.incomplete_headers.len(), 2); assert_eq!(queue.completion_data.len(), 1); assert!(queue.incomplete_headers.contains_key(&id(100))); assert!(queue.completion_data.contains_key(&id(200))); - assert_eq!(queue.header_to_complete(), Some((id(200), &()))); + assert_eq!(queue.header_to_complete(), Some((id(200), &200_200))); } #[test] fn header_completed_works() { - let mut queue = QueuedHeaders::::new(); - queue.completion_data.insert(id(100), ()); + let mut queue = QueuedHeaders::::default(); + queue.completion_data.insert(id(100), 100_100); // when unknown header is completed queue.header_completed(&id(200)); @@ -1323,7 +1329,7 @@ pub(crate) mod tests { #[test] fn incomplete_headers_response_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); // when we have already submitted #101 and #102 is ready queue @@ -1370,7 +1376,7 @@ pub(crate) mod tests { #[test] fn is_parent_incomplete_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); // when we do not know header itself assert_eq!(queue.is_parent_incomplete(&id(50)), false); @@ -1404,7 +1410,7 @@ pub(crate) mod tests { assert_eq!(queue.is_parent_incomplete(&id(200)), true); // when parent is the incomplete header and we have completion data - queue.completion_data.insert(id(299), ()); + queue.completion_data.insert(id(299), 299_299); queue .known_headers .entry(300) @@ -1416,7 +1422,7 @@ pub(crate) mod tests { #[test] fn prune_works() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); queue .known_headers .entry(105) @@ -1487,7 +1493,7 @@ pub(crate) mod tests { #[test] fn incomplete_headers_are_still_incomplete_after_advance() { - let mut queue = QueuedHeaders::::new(); + let mut queue = QueuedHeaders::::default(); // relay#1 knows that header#100 is incomplete && it has headers 101..104 in incomplete queue queue.incomplete_headers.insert(id(100), None); diff --git a/relays/headers-relay/src/lib.rs b/relays/headers-relay/src/lib.rs new file mode 100644 index 0000000000000..d91fe94d9d50b --- /dev/null +++ b/relays/headers-relay/src/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2019-2020 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 . + +//! Relaying source chain headers to target chain. This module provides entrypoint +//! that starts reading new headers from source chain and submit these headers as +//! module/contract transactions to the target chain. Module/contract on the target +//! chain is a light-client of the source chain. All other trustless bridge +//! applications are built using this light-client, so running headers-relay is +//! essential for running all other bridge applications. + +// required for futures::select! +#![recursion_limit = "1024"] +#![warn(missing_docs)] + +pub mod headers; +pub mod sync; +pub mod sync_loop; +pub mod sync_loop_metrics; +pub mod sync_loop_tests; +pub mod sync_types; diff --git a/relays/ethereum/src/sync.rs b/relays/headers-relay/src/sync.rs similarity index 91% rename from relays/ethereum/src/sync.rs rename to relays/headers-relay/src/sync.rs index e86e9be4ae339..8e4c671dbaa9e 100644 --- a/relays/ethereum/src/sync.rs +++ b/relays/headers-relay/src/sync.rs @@ -14,6 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Headers synchronization context. This structure wraps headers queue and is +//! able to choose: which headers to read from the source chain? Which headers +//! to submit to the target chain? The context makes decisions basing on parameters +//! passed using `HeadersSyncParams` structure. + use crate::headers::QueuedHeaders; use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; use num_traits::{One, Saturating, Zero}; @@ -36,38 +41,6 @@ pub struct HeadersSyncParams { pub target_tx_mode: TargetTransactionMode, } -impl HeadersSyncParams { - /// Default parameters for syncing Ethereum headers. - pub fn ethereum_sync_default() -> Self { - use crate::ethereum_sync_loop::consts::*; - - Self { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, - max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - } - } - - /// Default parameters for syncing Substrate headers. - pub fn substrate_sync_default() -> Self { - use crate::substrate_sync_loop::consts::*; - - Self { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - // since we always have single Substrate header in separate Ethereum transaction, - // all max_**_in_single_submit aren't important here - max_headers_in_single_submit: 4, - max_headers_size_in_single_submit: std::usize::MAX, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - } - } -} - /// Target transaction mode. #[derive(Debug, PartialEq, Clone)] pub enum TargetTransactionMode { @@ -99,7 +72,7 @@ impl HeadersSync

{ /// Creates new headers synchronizer. pub fn new(params: HeadersSyncParams) -> Self { HeadersSync { - headers: QueuedHeaders::new(), + headers: QueuedHeaders::default(), params, source_best_number: None, target_best_header: None, @@ -308,13 +281,13 @@ impl HeadersSync

{ #[cfg(test)] pub mod tests { use super::*; - use crate::ethereum_types::{EthereumHeadersSyncPipeline, H256}; use crate::headers::tests::{header, id}; + use crate::sync_loop_tests::{TestHash, TestHeadersSyncPipeline, TestNumber}; use crate::sync_types::HeaderStatus; - use crate::utils::HeaderId; + use relay_utils::HeaderId; - fn side_hash(number: u64) -> H256 { - H256::from_low_u64_le(1000 + number) + fn side_hash(number: TestNumber) -> TestHash { + 1000 + number } pub fn default_sync_params() -> HeadersSyncParams { @@ -330,7 +303,7 @@ pub mod tests { #[test] fn select_new_header_to_download_works() { - let mut eth_sync = HeadersSync::::new(default_sync_params()); + let mut eth_sync = HeadersSync::::new(default_sync_params()); // both best && target headers are unknown assert_eq!(eth_sync.select_new_header_to_download(), None); @@ -366,7 +339,7 @@ pub mod tests { #[test] fn select_new_header_to_download_works_with_empty_queue() { - let mut eth_sync = HeadersSync::::new(default_sync_params()); + let mut eth_sync = HeadersSync::::new(default_sync_params()); eth_sync.source_best_header_number_response(100); // when queue is not empty => everything goes as usually @@ -489,7 +462,7 @@ pub mod tests { #[test] fn pruning_happens_on_target_best_header_response() { - let mut eth_sync = HeadersSync::::new(default_sync_params()); + let mut eth_sync = HeadersSync::::new(default_sync_params()); eth_sync.params.prune_depth = 50; eth_sync.target_best_header_response(id(100)); assert_eq!(eth_sync.headers.prune_border(), 50); diff --git a/relays/ethereum/src/sync_loop.rs b/relays/headers-relay/src/sync_loop.rs similarity index 98% rename from relays/ethereum/src/sync_loop.rs rename to relays/headers-relay/src/sync_loop.rs index 62a9b06a83de4..14eb7e2a4140e 100644 --- a/relays/ethereum/src/sync_loop.rs +++ b/relays/headers-relay/src/sync_loop.rs @@ -14,17 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{start as metrics_start, GlobalMetrics, MetricsParams}; +//! Entrypoint for running headers synchronization loop. + use crate::sync::HeadersSyncParams; use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}; -use crate::utils::{ - format_ids, interval, process_future_result, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError, -}; use async_trait::async_trait; use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; +use relay_utils::{ + format_ids, interval, + metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + process_future_result, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError, +}; use std::{ collections::HashSet, future::Future, @@ -117,8 +120,8 @@ pub fn run>( let mut stall_countdown = None; let mut last_update_time = Instant::now(); - let mut metrics_global = GlobalMetrics::new(); - let mut metrics_sync = SyncLoopMetrics::new(); + let mut metrics_global = GlobalMetrics::default(); + let mut metrics_sync = SyncLoopMetrics::default(); let metrics_enabled = metrics_params.is_some(); metrics_start( format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), diff --git a/relays/ethereum/src/sync_loop_metrics.rs b/relays/headers-relay/src/sync_loop_metrics.rs similarity index 94% rename from relays/ethereum/src/sync_loop_metrics.rs rename to relays/headers-relay/src/sync_loop_metrics.rs index dc512a46e48f6..26939ee372cb7 100644 --- a/relays/ethereum/src/sync_loop_metrics.rs +++ b/relays/headers-relay/src/sync_loop_metrics.rs @@ -14,11 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; +//! Metrics for headers synchronization relay loop. + use crate::sync::HeadersSync; use crate::sync_types::{HeaderStatus, HeadersSyncPipeline}; use num_traits::Zero; +use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; /// Headers sync metrics. pub struct SyncLoopMetrics { @@ -36,9 +38,8 @@ impl Metrics for SyncLoopMetrics { } } -impl SyncLoopMetrics { - /// Creates sync loop metrics. - pub fn new() -> Self { +impl Default for SyncLoopMetrics { + fn default() -> Self { SyncLoopMetrics { best_block_numbers: GaugeVec::new( Opts::new("best_block_numbers", "Best block numbers on source and target nodes"), @@ -52,7 +53,9 @@ impl SyncLoopMetrics { .expect("metric is static and thus valid; qed"), } } +} +impl SyncLoopMetrics { /// Update metrics. pub fn update(&mut self, sync: &HeadersSync

) { let headers = sync.headers(); diff --git a/relays/ethereum/src/sync_loop_tests.rs b/relays/headers-relay/src/sync_loop_tests.rs similarity index 96% rename from relays/ethereum/src/sync_loop_tests.rs rename to relays/headers-relay/src/sync_loop_tests.rs index 8e2a4380ebbf7..84b2082ce91d4 100644 --- a/relays/ethereum/src/sync_loop_tests.rs +++ b/relays/headers-relay/src/sync_loop_tests.rs @@ -18,30 +18,30 @@ use crate::sync_loop::{run, SourceClient, TargetClient}; use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}; -use crate::utils::{process_future_result, retry_backoff, HeaderId, MaybeConnectionError}; use async_trait::async_trait; use backoff::backoff::Backoff; use futures::{future::FutureExt, stream::StreamExt}; use parking_lot::Mutex; +use relay_utils::{process_future_result, retry_backoff, HeaderId, MaybeConnectionError}; use std::{ collections::{HashMap, HashSet}, sync::Arc, time::Duration, }; -type TestNumber = u64; -type TestHash = u64; -type TestExtra = u64; -type TestCompletion = u64; -type TestHeaderId = HeaderId; -type TestQueuedHeader = QueuedHeader; +pub type TestNumber = u64; +pub type TestHash = u64; +pub type TestHeaderId = HeaderId; +pub type TestExtra = u64; +pub type TestCompletion = u64; +pub type TestQueuedHeader = QueuedHeader; -#[derive(Debug, Clone, PartialEq)] -struct TestHeader { - hash: TestHash, - number: TestNumber, - parent_hash: TestHash, +#[derive(Default, Debug, Clone, PartialEq)] +pub struct TestHeader { + pub hash: TestHash, + pub number: TestNumber, + pub parent_hash: TestHash, } impl SourceHeader for TestHeader { @@ -63,8 +63,8 @@ impl MaybeConnectionError for TestError { } } -#[derive(Debug, Clone, Copy)] -struct TestHeadersSyncPipeline; +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct TestHeadersSyncPipeline; impl HeadersSyncPipeline for TestHeadersSyncPipeline { const SOURCE_NAME: &'static str = "Source"; diff --git a/relays/ethereum/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs similarity index 97% rename from relays/ethereum/src/sync_types.rs rename to relays/headers-relay/src/sync_types.rs index 3970fb56291db..21eec10c1e0d3 100644 --- a/relays/ethereum/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::utils::{format_ids, HeaderId}; +//! Types that are used by headers synchronization components. +use relay_utils::{format_ids, HeaderId}; use std::{ops::Deref, sync::Arc}; /// Ethereum header synchronization status. @@ -99,8 +100,7 @@ pub trait SourceHeader { } /// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug)] -#[cfg_attr(test, derive(PartialEq))] +#[derive(Clone, Debug, PartialEq)] pub struct QueuedHeader(Arc>); impl QueuedHeader

{ @@ -129,8 +129,7 @@ impl Deref for QueuedHeader

{ } /// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug, Default)] -#[cfg_attr(test, derive(PartialEq))] +#[derive(Clone, Debug, Default, PartialEq)] pub struct QueuedHeaderData { header: P::Header, extra: Option, diff --git a/relays/messages-relay/Cargo.toml b/relays/messages-relay/Cargo.toml new file mode 100644 index 0000000000000..0af7eddc551fc --- /dev/null +++ b/relays/messages-relay/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "messages-relay" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +futures = "0.3.5" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } diff --git a/relays/messages-relay/src/lib.rs b/relays/messages-relay/src/lib.rs new file mode 100644 index 0000000000000..fe764071cfb6f --- /dev/null +++ b/relays/messages-relay/src/lib.rs @@ -0,0 +1,32 @@ +// Copyright 2019-2020 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 . + +//! Relaying [`message-lane`](../pallet_message_lane/index.html) application specific +//! data. Message lane allows sending arbitrary messages between bridged chains. This +//! module provides entrypoint that starts reading messages from given message lane +//! of source chain and submits proof-of-message-at-source-chain transactions to the +//! target chain. Additionaly, proofs-of-messages-delivery are sent back from the +//! target chain to the source chain. + +// required for futures::select! +#![recursion_limit = "1024"] +#![warn(missing_docs)] + +pub mod message_lane; +pub mod message_lane_loop; +pub mod message_race_delivery; +pub mod message_race_loop; +pub mod message_race_receiving; diff --git a/relays/ethereum/src/message_lane.rs b/relays/messages-relay/src/message_lane.rs similarity index 98% rename from relays/ethereum/src/message_lane.rs rename to relays/messages-relay/src/message_lane.rs index 0635456c40641..8671451394eb1 100644 --- a/relays/ethereum/src/message_lane.rs +++ b/relays/messages-relay/src/message_lane.rs @@ -19,7 +19,7 @@ //! 1) relay new messages from source to target node; //! 2) relay proof-of-receiving from target to source node. -use crate::utils::HeaderId; +use relay_utils::HeaderId; use num_traits::{One, Zero}; use std::fmt::Debug; diff --git a/relays/ethereum/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs similarity index 99% rename from relays/ethereum/src/message_lane_loop.rs rename to relays/messages-relay/src/message_lane_loop.rs index 0618382b83954..91d3017e93eae 100644 --- a/relays/ethereum/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -30,10 +30,10 @@ use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_race_delivery::run as run_message_delivery_race; use crate::message_race_receiving::run as run_message_receiving_race; -use crate::utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use async_trait::async_trait; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; +use relay_utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use std::{fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; /// Source client trait. @@ -334,9 +334,9 @@ async fn run_until_connection_lost, TC: Targ #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::utils::HeaderId; use futures::stream::StreamExt; use parking_lot::Mutex; + use relay_utils::HeaderId; use std::sync::Arc; pub fn header_id(number: TestSourceHeaderNumber) -> HeaderId { diff --git a/relays/ethereum/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs similarity index 99% rename from relays/ethereum/src/message_race_delivery.rs rename to relays/messages-relay/src/message_race_delivery.rs index d55b8353ee4dc..7cac96c01b488 100644 --- a/relays/ethereum/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -19,11 +19,11 @@ use crate::message_lane_loop::{ TargetClientState, }; use crate::message_race_loop::{MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; -use crate::utils::{FailedClient, HeaderId}; use async_trait::async_trait; use futures::stream::FusedStream; use num_traits::{One, Zero}; +use relay_utils::{FailedClient, HeaderId}; use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Maximal number of messages to relay in single transaction. diff --git a/relays/ethereum/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs similarity index 99% rename from relays/ethereum/src/message_race_loop.rs rename to relays/messages-relay/src/message_race_loop.rs index 9d1657edb451e..30401cd0baaa9 100644 --- a/relays/ethereum/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -24,13 +24,13 @@ #![allow(dead_code)] use crate::message_lane_loop::ClientState; -use crate::utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use async_trait::async_trait; use futures::{ future::FutureExt, stream::{FusedStream, StreamExt}, }; +use relay_utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; use std::{ fmt::Debug, ops::RangeInclusive, diff --git a/relays/ethereum/src/message_race_receiving.rs b/relays/messages-relay/src/message_race_receiving.rs similarity index 97% rename from relays/ethereum/src/message_race_receiving.rs rename to relays/messages-relay/src/message_race_receiving.rs index a50b713f0bd7c..4eeea7adbd374 100644 --- a/relays/ethereum/src/message_race_receiving.rs +++ b/relays/messages-relay/src/message_race_receiving.rs @@ -11,6 +11,8 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. +//! Message receiving race delivers proof-of-messages-delivery from lane.target to lane.source. + use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_lane_loop::{ SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, @@ -18,10 +20,10 @@ use crate::message_lane_loop::{ }; use crate::message_race_delivery::DeliveryStrategy; use crate::message_race_loop::{MessageRace, SourceClient, TargetClient}; -use crate::utils::FailedClient; use async_trait::async_trait; use futures::stream::FusedStream; +use relay_utils::FailedClient; use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Message receiving confirmations delivery strategy. diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml new file mode 100644 index 0000000000000..ffebd82a51aee --- /dev/null +++ b/relays/utils/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "relay-utils" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +backoff = "0.2" +futures = "0.3.5" +log = "0.4.11" +sysinfo = "0.15" + +# Substrate dependencies +substrate-prometheus-endpoint = { version = "0.8.0-rc6", git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0-rc6" } diff --git a/relays/ethereum/src/utils.rs b/relays/utils/src/lib.rs similarity index 96% rename from relays/ethereum/src/utils.rs rename to relays/utils/src/lib.rs index e149f1884b229..0b4d682c1cd41 100644 --- a/relays/ethereum/src/utils.rs +++ b/relays/utils/src/lib.rs @@ -14,16 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Utilities used by different relays. + use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::future::FutureExt; use std::time::Duration; /// Max delay after connection-unrelated error happened before we'll try the /// same request again. -const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); +pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); /// Delay after connection-related error happened before we'll try /// reconnection again. -const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); +pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); + +pub mod metrics; /// Macro that returns (client, Err(error)) tuple from function if result is Err(error). #[macro_export] @@ -176,7 +180,7 @@ impl ProcessFutureResult { } /// Process result of the future from a client. -pub(crate) fn process_future_result( +pub fn process_future_result( result: Result, retry_backoff: &mut ExponentialBackoff, on_success: impl FnOnce(TResult), diff --git a/relays/ethereum/src/metrics.rs b/relays/utils/src/metrics.rs similarity index 98% rename from relays/ethereum/src/metrics.rs rename to relays/utils/src/metrics.rs index c94ecf6f02c85..0667bdb922a00 100644 --- a/relays/ethereum/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -107,9 +107,8 @@ impl Metrics for GlobalMetrics { } } -impl GlobalMetrics { - /// Creates global metrics. - pub fn new() -> Self { +impl Default for GlobalMetrics { + fn default() -> Self { GlobalMetrics { system: System::new_with_specifics(RefreshKind::everything()), system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) @@ -123,7 +122,9 @@ impl GlobalMetrics { .expect("metric is static and thus valid; qed"), } } +} +impl GlobalMetrics { /// Update metrics. pub fn update(&mut self) { // update system-wide metrics From b50e9672c924a815bee9c1884ff9b6c48d30838b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Sep 2020 11:43:04 +0300 Subject: [PATCH 0162/1210] Extract minimal ethereum client (#359) * relay-ethereum-client * use relay-ethereum-client from ethereum-poa-relay * cargo fmt --all * #![warn(missing_docs)] * EthereumRpcClient -> EthereumClient * make EthereumHeadersSyncPipeline private * return concrete type from crate::new * cleanup dependencies * *self -> self * remove trait Client * sort deps --- relays/ethereum-client/Cargo.toml | 17 ++ relays/ethereum-client/src/client.rs | 142 ++++++++++++ relays/ethereum-client/src/error.rs | 71 ++++++ relays/ethereum-client/src/lib.rs | 48 ++++ relays/ethereum-client/src/rpc.rs | 53 +++++ relays/ethereum-client/src/sign.rs | 85 ++++++++ .../src/types.rs} | 54 ++--- relays/ethereum/Cargo.toml | 3 +- relays/ethereum/src/ethereum_client.rs | 206 ++---------------- .../ethereum/src/ethereum_deploy_contract.rs | 11 +- relays/ethereum/src/ethereum_exchange.rs | 26 ++- .../ethereum/src/ethereum_exchange_submit.rs | 10 +- relays/ethereum/src/ethereum_sync_loop.rs | 65 ++++-- relays/ethereum/src/instances.rs | 2 +- relays/ethereum/src/main.rs | 23 +- relays/ethereum/src/rpc.rs | 60 +---- relays/ethereum/src/rpc_errors.rs | 39 +--- relays/ethereum/src/substrate_client.rs | 3 +- relays/ethereum/src/substrate_sync_loop.rs | 15 +- relays/ethereum/src/substrate_types.rs | 7 +- 20 files changed, 556 insertions(+), 384 deletions(-) create mode 100644 relays/ethereum-client/Cargo.toml create mode 100644 relays/ethereum-client/src/client.rs create mode 100644 relays/ethereum-client/src/error.rs create mode 100644 relays/ethereum-client/src/lib.rs create mode 100644 relays/ethereum-client/src/rpc.rs create mode 100644 relays/ethereum-client/src/sign.rs rename relays/{ethereum/src/ethereum_types.rs => ethereum-client/src/types.rs} (57%) diff --git a/relays/ethereum-client/Cargo.toml b/relays/ethereum-client/Cargo.toml new file mode 100644 index 0000000000000..4923b8a111fbc --- /dev/null +++ b/relays/ethereum-client/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "relay-ethereum-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.4" } +ethereum-tx-sign = "3.0" +headers-relay = { path = "../headers-relay" } +hex = "0.4" +jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } +log = "0.4.11" +parity-crypto = { version = "0.6", features = ["publickey"] } +relay-utils = { path = "../utils" } +web3 = "0.13" diff --git a/relays/ethereum-client/src/client.rs b/relays/ethereum-client/src/client.rs new file mode 100644 index 0000000000000..0042b13c6ef18 --- /dev/null +++ b/relays/ethereum-client/src/client.rs @@ -0,0 +1,142 @@ +// Copyright 2019-2020 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 . + +use crate::rpc::Ethereum; +use crate::types::{ + Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, Transaction, TransactionHash, + H256, U256, +}; +use crate::{ConnectionParams, Error, Result}; + +use jsonrpsee::raw::RawClient; +use jsonrpsee::transport::http::HttpTransportClient; +use jsonrpsee::Client as RpcClient; + +/// The client used to interact with an Ethereum node through RPC. +#[derive(Clone)] +pub struct Client { + client: RpcClient, +} + +impl Client { + /// Create a new Ethereum RPC Client. + pub fn new(params: ConnectionParams) -> Self { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); + let raw_client = RawClient::new(transport); + let client: RpcClient = raw_client.into(); + + Self { client } + } +} + +impl Client { + /// Estimate gas usage for the given call. + pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { + Ok(Ethereum::estimate_gas(&self.client, call_request).await?) + } + + /// Retrieve number of the best known block from the Ethereum node. + pub async fn best_block_number(&self) -> Result { + Ok(Ethereum::block_number(&self.client).await?.as_u64()) + } + + /// Retrieve number of the best known block from the Ethereum node. + pub async fn header_by_number(&self, block_number: u64) -> Result

{ + let get_full_tx_objects = false; + let header = Ethereum::get_block_by_number(&self.client, block_number, get_full_tx_objects).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + } + } + + /// Retrieve block header by its hash from Ethereum node. + pub async fn header_by_hash(&self, hash: H256) -> Result
{ + let get_full_tx_objects = false; + let header = Ethereum::get_block_by_hash(&self.client, hash, get_full_tx_objects).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + } + } + + /// Retrieve block header and its transactions by its number from Ethereum node. + pub async fn header_by_number_with_transactions(&self, number: u64) -> Result { + let get_full_tx_objects = true; + let header = Ethereum::get_block_by_number_with_transactions(&self.client, number, get_full_tx_objects).await?; + + let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + if !is_complete_header { + return Err(Error::IncompleteHeader); + } + + let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); + if !is_complete_transactions { + return Err(Error::IncompleteTransaction); + } + + Ok(header) + } + + /// Retrieve block header and its transactions by its hash from Ethereum node. + pub async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { + let get_full_tx_objects = true; + let header = Ethereum::get_block_by_hash_with_transactions(&self.client, hash, get_full_tx_objects).await?; + + let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + if !is_complete_header { + return Err(Error::IncompleteHeader); + } + + let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); + if !is_complete_transactions { + return Err(Error::IncompleteTransaction); + } + + Ok(header) + } + + /// Retrieve transaction by its hash from Ethereum node. + pub async fn transaction_by_hash(&self, hash: H256) -> Result> { + Ok(Ethereum::transaction_by_hash(&self.client, hash).await?) + } + + /// Retrieve transaction receipt by transaction hash. + pub async fn transaction_receipt(&self, transaction_hash: H256) -> Result { + Ok(Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?) + } + + /// Get the nonce of the given account. + pub async fn account_nonce(&self, address: Address) -> Result { + Ok(Ethereum::get_transaction_count(&self.client, address).await?) + } + + /// Submit an Ethereum transaction. + /// + /// The transaction must already be signed before sending it through this method. + pub async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result { + let transaction = Bytes(signed_raw_tx); + let tx_hash = Ethereum::submit_transaction(&self.client, transaction).await?; + log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); + Ok(tx_hash) + } + + /// Call Ethereum smart contract. + pub async fn eth_call(&self, call_transaction: CallRequest) -> Result { + Ok(Ethereum::call(&self.client, call_transaction).await?) + } +} diff --git a/relays/ethereum-client/src/error.rs b/relays/ethereum-client/src/error.rs new file mode 100644 index 0000000000000..b02e5fecf5842 --- /dev/null +++ b/relays/ethereum-client/src/error.rs @@ -0,0 +1,71 @@ +// Copyright 2019-2020 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 . + +//! Ethereum node RPC errors. + +use jsonrpsee::client::RequestError; +use relay_utils::MaybeConnectionError; + +/// Result type used by Ethereum client. +pub type Result = std::result::Result; + +/// Errors that can occur only when interacting with +/// an Ethereum node through RPC. +#[derive(Debug)] +pub enum Error { + /// An error that can occur when making an HTTP request to + /// an JSON-RPC client. + Request(RequestError), + /// Failed to parse response. + ResponseParseFailed(String), + /// We have received a header with missing fields. + IncompleteHeader, + /// We have received a transaction missing a `raw` field. + IncompleteTransaction, + /// An invalid Substrate block number was received from + /// an Ethereum node. + InvalidSubstrateBlockNumber, + /// An invalid index has been received from an Ethereum node. + InvalidIncompleteIndex, +} + +impl From for Error { + fn from(error: RequestError) -> Self { + Error::Request(error) + } +} + +impl MaybeConnectionError for Error { + fn is_connection_error(&self) -> bool { + matches!(*self, Error::Request(RequestError::TransportError(_))) + } +} + +impl ToString for Error { + fn to_string(&self) -> String { + match self { + Self::Request(e) => e.to_string(), + Self::ResponseParseFailed(e) => e.to_string(), + Self::IncompleteHeader => { + "Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom)" + .to_string() + } + Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), + Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), + Self::InvalidIncompleteIndex => "Received an invalid incomplete index from Ethereum Node".to_string(), + } + } +} diff --git a/relays/ethereum-client/src/lib.rs b/relays/ethereum-client/src/lib.rs new file mode 100644 index 0000000000000..8c5a00e01b4d7 --- /dev/null +++ b/relays/ethereum-client/src/lib.rs @@ -0,0 +1,48 @@ +// Copyright 2019-2020 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 . + +//! Tools to interact with (Open) Ethereum node using RPC methods. + +#![warn(missing_docs)] + +mod client; +mod error; +mod rpc; +mod sign; + +pub use crate::client::Client; +pub use crate::error::{Error, Result}; +pub use crate::sign::{sign_and_submit_transaction, SigningParams}; + +pub mod types; + +/// Ethereum connection params. +#[derive(Debug, Clone)] +pub struct ConnectionParams { + /// Ethereum RPC host. + pub host: String, + /// Ethereum RPC port. + pub port: u16, +} + +impl Default for ConnectionParams { + fn default() -> Self { + ConnectionParams { + host: "localhost".into(), + port: 8545, + } + } +} diff --git a/relays/ethereum-client/src/rpc.rs b/relays/ethereum-client/src/rpc.rs new file mode 100644 index 0000000000000..9739d3edbe280 --- /dev/null +++ b/relays/ethereum-client/src/rpc.rs @@ -0,0 +1,53 @@ +// Copyright 2019-2020 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 . + +//! Ethereum node RPC interface. + +// The compiler doesn't think we're using the +// code from rpc_api! +#![allow(dead_code)] +#![allow(unused_variables)] + +use crate::types::{ + Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, Transaction, TransactionHash, H256, U256, U64, +}; + +jsonrpsee::rpc_api! { + pub(crate) Ethereum { + #[rpc(method = "eth_estimateGas", positional_params)] + fn estimate_gas(call_request: CallRequest) -> U256; + #[rpc(method = "eth_blockNumber", positional_params)] + fn block_number() -> U64; + #[rpc(method = "eth_getBlockByNumber", positional_params)] + fn get_block_by_number(block_number: U64, full_tx_objs: bool) -> Header; + #[rpc(method = "eth_getBlockByHash", positional_params)] + fn get_block_by_hash(hash: H256, full_tx_objs: bool) -> Header; + #[rpc(method = "eth_getBlockByNumber", positional_params)] + fn get_block_by_number_with_transactions(number: U64, full_tx_objs: bool) -> HeaderWithTransactions; + #[rpc(method = "eth_getBlockByHash", positional_params)] + fn get_block_by_hash_with_transactions(hash: H256, full_tx_objs: bool) -> HeaderWithTransactions; + #[rpc(method = "eth_getTransactionByHash", positional_params)] + fn transaction_by_hash(hash: H256) -> Option; + #[rpc(method = "eth_getTransactionReceipt", positional_params)] + fn get_transaction_receipt(transaction_hash: H256) -> Receipt; + #[rpc(method = "eth_getTransactionCount", positional_params)] + fn get_transaction_count(address: Address) -> U256; + #[rpc(method = "eth_submitTransaction", positional_params)] + fn submit_transaction(transaction: Bytes) -> TransactionHash; + #[rpc(method = "eth_call", positional_params)] + fn call(transaction_call: CallRequest) -> Bytes; + } +} diff --git a/relays/ethereum-client/src/sign.rs b/relays/ethereum-client/src/sign.rs new file mode 100644 index 0000000000000..f5b80a34e5a7b --- /dev/null +++ b/relays/ethereum-client/src/sign.rs @@ -0,0 +1,85 @@ +// Copyright 2019-2020 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 . + +use crate::types::{Address, CallRequest, U256}; +use crate::{Client, Result}; + +use parity_crypto::publickey::KeyPair; + +/// Ethereum signing params. +#[derive(Clone, Debug)] +pub struct SigningParams { + /// Ethereum chain id. + pub chain_id: u64, + /// Ethereum transactions signer. + pub signer: KeyPair, + /// Gas price we agree to pay. + pub gas_price: U256, +} + +impl Default for SigningParams { + fn default() -> Self { + SigningParams { + chain_id: 0x11, // Parity dev chain + // account that has a lot of ether when we run instant seal engine + // address: 0x00a329c0648769a73afac7f9381e08fb43dbea72 + // secret: 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 + signer: KeyPair::from_secret_slice( + &hex::decode("4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7") + .expect("secret is hardcoded, thus valid; qed"), + ) + .expect("secret is hardcoded, thus valid; qed"), + gas_price: 8_000_000_000u64.into(), // 8 Gwei + } + } +} + +/// Sign and submit tranaction using given Ethereum client. +pub async fn sign_and_submit_transaction( + client: &Client, + params: &SigningParams, + contract_address: Option
, + nonce: Option, + double_gas: bool, + encoded_call: Vec, +) -> Result<()> { + let nonce = if let Some(n) = nonce { + n + } else { + let address: Address = params.signer.address().as_fixed_bytes().into(); + client.account_nonce(address).await? + }; + + let call_request = CallRequest { + to: contract_address, + data: Some(encoded_call.clone().into()), + ..Default::default() + }; + let gas = client.estimate_gas(call_request).await?; + + let raw_transaction = ethereum_tx_sign::RawTransaction { + nonce, + to: contract_address, + value: U256::zero(), + gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, + gas_price: params.gas_price, + data: encoded_call, + } + .sign(¶ms.signer.secret().as_fixed_bytes().into(), ¶ms.chain_id); + + let _ = client.submit_transaction(raw_transaction).await?; + Ok(()) +} diff --git a/relays/ethereum/src/ethereum_types.rs b/relays/ethereum-client/src/types.rs similarity index 57% rename from relays/ethereum/src/ethereum_types.rs rename to relays/ethereum-client/src/types.rs index bb780d6968019..f64362ade0e88 100644 --- a/relays/ethereum/src/ethereum_types.rs +++ b/relays/ethereum-client/src/types.rs @@ -14,11 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; +//! Common types that are used in relay <-> Ethereum node communications. -use codec::Encode; -use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use relay_utils::HeaderId; +use headers_relay::sync_types::SourceHeader; pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; @@ -26,6 +24,9 @@ pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; /// both number and hash fields filled. pub const HEADER_ID_PROOF: &str = "checked on retrieval; qed"; +/// Ethereum transaction hash type. +pub type HeaderHash = H256; + /// Ethereum transaction hash type. pub type TransactionHash = H256; @@ -37,10 +38,11 @@ pub type Header = web3::types::Block; /// Ethereum header type used in headers sync. #[derive(Clone, Debug, PartialEq)] -pub struct EthereumSyncHeader(Header); +pub struct SyncHeader(Header); -impl std::ops::Deref for EthereumSyncHeader { +impl std::ops::Deref for SyncHeader { type Target = Header; + fn deref(&self) -> &Self::Target { &self.0 } @@ -53,52 +55,26 @@ pub type HeaderWithTransactions = web3::types::Block; pub type Receipt = web3::types::TransactionReceipt; /// Ethereum header ID. -pub type EthereumHeaderId = HeaderId; - -/// Queued ethereum header ID. -pub type QueuedEthereumHeader = QueuedHeader; +pub type HeaderId = relay_utils::HeaderId; /// A raw Ethereum transaction that's been signed. pub type SignedRawTx = Vec; -/// Ethereum synchronization pipeline. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct EthereumHeadersSyncPipeline; - -impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { - const SOURCE_NAME: &'static str = "Ethereum"; - const TARGET_NAME: &'static str = "Substrate"; - - type Hash = H256; - type Number = u64; - type Header = EthereumSyncHeader; - type Extra = Vec; - type Completion = (); - - fn estimate_size(source: &QueuedHeader) -> usize { - into_substrate_ethereum_header(source.header()).encode().len() - + into_substrate_ethereum_receipts(source.extra()) - .map(|extra| extra.encode().len()) - .unwrap_or(0) - } -} - -impl From
for EthereumSyncHeader { +impl From
for SyncHeader { fn from(header: Header) -> Self { Self(header) } } -impl SourceHeader for EthereumSyncHeader { - fn id(&self) -> EthereumHeaderId { - HeaderId( +impl SourceHeader for SyncHeader { + fn id(&self) -> HeaderId { + relay_utils::HeaderId( self.number.expect(HEADER_ID_PROOF).as_u64(), self.hash.expect(HEADER_ID_PROOF), ) } - fn parent_id(&self) -> EthereumHeaderId { - HeaderId(self.number.expect(HEADER_ID_PROOF).as_u64() - 1, self.parent_hash) + fn parent_id(&self) -> HeaderId { + relay_utils::HeaderId(self.number.expect(HEADER_ID_PROOF).as_u64() - 1, self.parent_hash) } } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 1bedea7aedaa0..ab6872dabf206 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -17,7 +17,6 @@ env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" -ethereum-tx-sign = "3.0" exchange-relay = { path = "../exchange-relay" } futures = "0.3.5" headers-relay = { path = "../headers-relay" } @@ -27,11 +26,11 @@ log = "0.4.11" messages-relay = { path = "../messages-relay" } num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } +relay-ethereum-client = { path = "../ethereum-client" } relay-utils = { path = "../utils" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" time = "0.2" -web3 = "0.13" [dependencies.jsonrpsee] git = "https://github.com/svyatonik/jsonrpsee.git" diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 5635197d6404a..d9357c560b08d 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -14,22 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{ - Address, Bytes, CallRequest, EthereumHeaderId, Header, HeaderWithTransactions, Receipt, SignedRawTx, Transaction, - TransactionHash, H256, U256, -}; -use crate::rpc::{Ethereum, EthereumRpc}; -use crate::rpc_errors::{EthereumNodeError, RpcError}; +use crate::rpc_errors::RpcError; use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; use async_trait::async_trait; use codec::{Decode, Encode}; use ethabi::FunctionOutputDecoder; use headers_relay::sync_types::SubmittedHeaders; -use jsonrpsee::raw::RawClient; -use jsonrpsee::transport::http::HttpTransportClient; -use jsonrpsee::Client; -use parity_crypto::publickey::KeyPair; +use relay_ethereum_client::{ + sign_and_submit_transaction, + types::{Address, CallRequest, HeaderId as EthereumHeaderId, Receipt, H256, U256}, + Client as EthereumClient, Error as EthereumNodeError, SigningParams as EthereumSigningParams, +}; use relay_utils::{HeaderId, MaybeConnectionError}; use std::collections::HashSet; @@ -38,159 +34,10 @@ ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json") type RpcResult = std::result::Result; -/// Ethereum connection params. -#[derive(Debug, Clone)] -pub struct EthereumConnectionParams { - /// Ethereum RPC host. - pub host: String, - /// Ethereum RPC port. - pub port: u16, -} - -impl Default for EthereumConnectionParams { - fn default() -> Self { - EthereumConnectionParams { - host: "localhost".into(), - port: 8545, - } - } -} - -/// Ethereum signing params. -#[derive(Clone, Debug)] -pub struct EthereumSigningParams { - /// Ethereum chain id. - pub chain_id: u64, - /// Ethereum transactions signer. - pub signer: KeyPair, - /// Gas price we agree to pay. - pub gas_price: U256, -} - -impl Default for EthereumSigningParams { - fn default() -> Self { - EthereumSigningParams { - chain_id: 0x11, // Parity dev chain - // account that has a lot of ether when we run instant seal engine - // address: 0x00a329c0648769a73afac7f9381e08fb43dbea72 - // secret: 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 - signer: KeyPair::from_secret_slice( - &hex::decode("4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7") - .expect("secret is hardcoded, thus valid; qed"), - ) - .expect("secret is hardcoded, thus valid; qed"), - gas_price: 8_000_000_000u64.into(), // 8 Gwei - } - } -} - -/// The client used to interact with an Ethereum node through RPC. -pub struct EthereumRpcClient { - client: Client, -} - -impl EthereumRpcClient { - /// Create a new Ethereum RPC Client. - pub fn new(params: EthereumConnectionParams) -> Self { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - let raw_client = RawClient::new(transport); - let client: Client = raw_client.into(); - - Self { client } - } -} - -#[async_trait] -impl EthereumRpc for EthereumRpcClient { - async fn estimate_gas(&self, call_request: CallRequest) -> RpcResult { - Ok(Ethereum::estimate_gas(&self.client, call_request).await?) - } - - async fn best_block_number(&self) -> RpcResult { - Ok(Ethereum::block_number(&self.client).await?.as_u64()) - } - - async fn header_by_number(&self, block_number: u64) -> RpcResult
{ - let get_full_tx_objects = false; - let header = Ethereum::get_block_by_number(&self.client, block_number, get_full_tx_objects).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), - } - } - - async fn header_by_hash(&self, hash: H256) -> RpcResult
{ - let get_full_tx_objects = false; - let header = Ethereum::get_block_by_hash(&self.client, hash, get_full_tx_objects).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)), - } - } - - async fn header_by_number_with_transactions(&self, number: u64) -> RpcResult { - let get_full_tx_objects = true; - let header = Ethereum::get_block_by_number_with_transactions(&self.client, number, get_full_tx_objects).await?; - - let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); - if !is_complete_header { - return Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)); - } - - let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); - if !is_complete_transactions { - return Err(RpcError::Ethereum(EthereumNodeError::IncompleteTransaction)); - } - - Ok(header) - } - - async fn header_by_hash_with_transactions(&self, hash: H256) -> RpcResult { - let get_full_tx_objects = true; - let header = Ethereum::get_block_by_hash_with_transactions(&self.client, hash, get_full_tx_objects).await?; - - let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); - if !is_complete_header { - return Err(RpcError::Ethereum(EthereumNodeError::IncompleteHeader)); - } - - let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); - if !is_complete_transactions { - return Err(RpcError::Ethereum(EthereumNodeError::IncompleteTransaction)); - } - - Ok(header) - } - - async fn transaction_by_hash(&self, hash: H256) -> RpcResult> { - Ok(Ethereum::transaction_by_hash(&self.client, hash).await?) - } - - async fn transaction_receipt(&self, transaction_hash: H256) -> RpcResult { - Ok(Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?) - } - - async fn account_nonce(&self, address: Address) -> RpcResult { - Ok(Ethereum::get_transaction_count(&self.client, address).await?) - } - - async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> RpcResult { - let transaction = Bytes(signed_raw_tx); - let tx_hash = Ethereum::submit_transaction(&self.client, transaction).await?; - log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); - Ok(tx_hash) - } - - async fn eth_call(&self, call_transaction: CallRequest) -> RpcResult { - Ok(Ethereum::call(&self.client, call_transaction).await?) - } -} - /// A trait which contains methods that work by using multiple low-level RPCs, or more complicated /// interactions involving, for example, an Ethereum contract. #[async_trait] -pub trait EthereumHighLevelRpc: EthereumRpc { +pub trait EthereumHighLevelRpc { /// Returns best Substrate block that PoA chain knows of. async fn best_substrate_block(&self, contract_address: Address) -> RpcResult; @@ -240,7 +87,7 @@ pub trait EthereumHighLevelRpc: EthereumRpc { } #[async_trait] -impl EthereumHighLevelRpc for EthereumRpcClient { +impl EthereumHighLevelRpc for EthereumClient { async fn best_substrate_block(&self, contract_address: Address) -> RpcResult { let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); let call_request = CallRequest { @@ -293,7 +140,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { submitted: Vec::new(), incomplete: Vec::new(), rejected: headers.iter().rev().map(|header| header.id()).collect(), - fatal_error: Some(error), + fatal_error: Some(error.into()), } } }; @@ -302,9 +149,7 @@ impl EthereumHighLevelRpc for EthereumRpcClient { // cloning `jsonrpsee::Client` only clones reference to background threads submit_substrate_headers( EthereumHeadersSubmitter { - client: EthereumRpcClient { - client: self.client.clone(), - }, + client: self.clone(), params, contract_address, nonce, @@ -369,32 +214,9 @@ impl EthereumHighLevelRpc for EthereumRpcClient { double_gas: bool, encoded_call: Vec, ) -> RpcResult<()> { - let nonce = if let Some(n) = nonce { - n - } else { - let address: Address = params.signer.address().as_fixed_bytes().into(); - self.account_nonce(address).await? - }; - - let call_request = CallRequest { - to: contract_address, - data: Some(encoded_call.clone().into()), - ..Default::default() - }; - let gas = self.estimate_gas(call_request).await?; - - let raw_transaction = ethereum_tx_sign::RawTransaction { - nonce, - to: contract_address, - value: U256::zero(), - gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, - gas_price: params.gas_price, - data: encoded_call, - } - .sign(¶ms.signer.secret().as_fixed_bytes().into(), ¶ms.chain_id); - - let _ = self.submit_transaction(raw_transaction).await?; - Ok(()) + sign_and_submit_transaction(self, params, contract_address, nonce, double_gas, encoded_call) + .await + .map_err(Into::into) } async fn transaction_receipts( @@ -524,7 +346,7 @@ trait HeadersSubmitter { /// Implementation of Substrate headers submitter that sends headers to running Ethereum node. struct EthereumHeadersSubmitter { - client: EthereumRpcClient, + client: EthereumClient, params: EthereumSigningParams, contract_address: Address, nonce: U256, diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index b04632fc7eae0..17f12ba45eb1b 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -14,9 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_client::{ - bridge_contract, EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, -}; +use crate::ethereum_client::{bridge_contract, EthereumHighLevelRpc}; use crate::instances::BridgeInstance; use crate::rpc::SubstrateRpc; use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; @@ -24,6 +22,9 @@ use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, S use codec::{Decode, Encode}; use num_traits::Zero; +use relay_ethereum_client::{ + Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, +}; use relay_utils::HeaderId; /// Ethereum synchronization parameters. @@ -63,7 +64,7 @@ pub fn run(params: EthereumDeployContractParams) { } = params; let result = local_pool.run_until(async move { - let eth_client = EthereumRpcClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params); let sub_client = SubstrateRpcClient::new(sub_params, instance).await?; let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; @@ -137,7 +138,7 @@ async fn prepare_initial_authorities_set( /// Deploy bridge contract to Ethereum chain. async fn deploy_bridge_contract( - eth_client: &EthereumRpcClient, + eth_client: &EthereumClient, params: &EthereumSigningParams, contract_code: Vec, initial_header: Vec, diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index e5a821bf3a098..59c9a42ca68c4 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -16,13 +16,8 @@ //! Relaying proofs of PoA -> Substrate exchange transactions. -use crate::ethereum_client::{EthereumConnectionParams, EthereumRpcClient}; -use crate::ethereum_types::{ - EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, Transaction as EthereumTransaction, - TransactionHash as EthereumTransactionHash, H256, -}; use crate::instances::BridgeInstance; -use crate::rpc::{EthereumRpc, SubstrateRpc}; +use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, @@ -36,6 +31,13 @@ use exchange_relay::exchange::{ TransactionProofPipeline, }; use exchange_relay::exchange_loop::{run as run_loop, InMemoryStorage}; +use relay_ethereum_client::{ + types::{ + HeaderId as EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, + Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, HEADER_ID_PROOF, + }, + Client as EthereumClient, ConnectionParams as EthereumConnectionParams, +}; use relay_utils::{metrics::MetricsParams, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::time::Duration; @@ -92,8 +94,8 @@ impl SourceBlock for EthereumSourceBlock { fn id(&self) -> EthereumHeaderId { HeaderId( - self.0.number.expect(crate::ethereum_types::HEADER_ID_PROOF).as_u64(), - self.0.hash.expect(crate::ethereum_types::HEADER_ID_PROOF), + self.0.number.expect(HEADER_ID_PROOF).as_u64(), + self.0.hash.expect(HEADER_ID_PROOF), ) } @@ -120,7 +122,7 @@ impl SourceTransaction for EthereumSourceTransaction { /// Ethereum node as transactions proof source. struct EthereumTransactionsSource { - client: EthereumRpcClient, + client: EthereumClient, } #[async_trait] @@ -136,6 +138,7 @@ impl SourceClient for EthereumTransactionsSource { .header_by_hash_with_transactions(hash) .await .map(EthereumSourceBlock) + .map_err(Into::into) } async fn block_by_number(&self, number: u64) -> Result { @@ -143,6 +146,7 @@ impl SourceClient for EthereumTransactionsSource { .header_by_number_with_transactions(number) .await .map(EthereumSourceBlock) + .map_err(Into::into) } async fn transaction_block( @@ -278,7 +282,7 @@ fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H25 } = params; let result = local_pool.run_until(async move { - let eth_client = EthereumRpcClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params); let sub_client = SubstrateRpcClient::new(sub_params, instance).await?; let source = EthereumTransactionsSource { client: eth_client }; @@ -321,7 +325,7 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi } = params; let do_run_loop = move || -> Result<(), String> { - let eth_client = EthereumRpcClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params); let sub_client = async_std::task::block_on(SubstrateRpcClient::new(sub_params, instance)) .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index 4309b6e894d24..519fdba8cb99a 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -16,14 +16,14 @@ //! Submitting Ethereum -> Substrate exchange transactions. -use crate::ethereum_client::{EthereumConnectionParams, EthereumRpcClient, EthereumSigningParams}; -use crate::ethereum_types::{CallRequest, U256}; -use crate::rpc::EthereumRpc; - use bp_eth_poa::{ signatures::{SecretKey, SignTransaction}, UnsignedTransaction, }; +use relay_ethereum_client::{ + types::{CallRequest, U256}, + Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, +}; use rialto_runtime::exchange::LOCK_FUNDS_ADDRESS; /// Ethereum exchange transaction params. @@ -54,7 +54,7 @@ pub fn run(params: EthereumExchangeSubmitParams) { } = params; let result: Result<_, String> = local_pool.run_until(async move { - let eth_client = EthereumRpcClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params); let eth_signer_address = eth_sign.signer.address(); let sub_recipient_encoded = sub_recipient; diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 10779845cbf24..d5a4ec9b8e103 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -16,26 +16,27 @@ //! Ethereum PoA -> Substrate synchronization. -use crate::ethereum_client::{EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient}; -use crate::ethereum_types::{ - EthereumHeaderId, EthereumHeadersSyncPipeline, EthereumSyncHeader as Header, QueuedEthereumHeader, Receipt, -}; +use crate::ethereum_client::EthereumHighLevelRpc; use crate::instances::BridgeInstance; -use crate::rpc::{EthereumRpc, SubstrateRpc}; +use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; use crate::substrate_client::{ SubmitEthereumHeaders, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, }; -use crate::substrate_types::into_substrate_ethereum_header; +use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; use async_trait::async_trait; +use codec::Encode; use headers_relay::{ sync::{HeadersSyncParams, TargetTransactionMode}, sync_loop::{SourceClient, TargetClient}, - sync_types::{SourceHeader, SubmittedHeaders}, + sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, +}; +use relay_ethereum_client::{ + types::{HeaderHash, HeaderId as EthereumHeaderId, Receipt, SyncHeader as Header}, + Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; use relay_utils::metrics::MetricsParams; -use web3::types::H256; use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; @@ -78,14 +79,40 @@ pub struct EthereumSyncParams { pub instance: Box, } +/// Ethereum synchronization pipeline. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(test, derive(PartialEq))] +pub struct EthereumHeadersSyncPipeline; + +impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { + const SOURCE_NAME: &'static str = "Ethereum"; + const TARGET_NAME: &'static str = "Substrate"; + + type Hash = HeaderHash; + type Number = u64; + type Header = Header; + type Extra = Vec; + type Completion = (); + + fn estimate_size(source: &QueuedHeader) -> usize { + into_substrate_ethereum_header(source.header()).encode().len() + + into_substrate_ethereum_receipts(source.extra()) + .map(|extra| extra.encode().len()) + .unwrap_or(0) + } +} + +/// Queued ethereum header ID. +pub type QueuedEthereumHeader = QueuedHeader; + /// Ethereum client as headers source. struct EthereumHeadersSource { /// Ethereum node client. - client: EthereumRpcClient, + client: EthereumClient, } impl EthereumHeadersSource { - fn new(client: EthereumRpcClient) -> Self { + fn new(client: EthereumClient) -> Self { Self { client } } } @@ -95,15 +122,23 @@ impl SourceClient for EthereumHeadersSource { type Error = RpcError; async fn best_block_number(&self) -> Result { - self.client.best_block_number().await + self.client.best_block_number().await.map_err(Into::into) } - async fn header_by_hash(&self, hash: H256) -> Result { - self.client.header_by_hash(hash).await.map(Into::into) + async fn header_by_hash(&self, hash: HeaderHash) -> Result { + self.client + .header_by_hash(hash) + .await + .map(Into::into) + .map_err(Into::into) } async fn header_by_number(&self, number: u64) -> Result { - self.client.header_by_number(number).await.map(Into::into) + self.client + .header_by_number(number) + .await + .map(Into::into) + .map_err(Into::into) } async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), Self::Error> { @@ -192,7 +227,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { instance, } = params; - let eth_client = EthereumRpcClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params); let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?; let sign_sub_transactions = match sync_params.target_tx_mode { diff --git a/relays/ethereum/src/instances.rs b/relays/ethereum/src/instances.rs index 6fa44740e89c7..d2f06c2504342 100644 --- a/relays/ethereum/src/instances.rs +++ b/relays/ethereum/src/instances.rs @@ -23,7 +23,7 @@ //! //! This module helps by preparing the correct `Call`s for each of the different pallet instances. -use crate::ethereum_types::QueuedEthereumHeader; +use crate::ethereum_sync_loop::QueuedEthereumHeader; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; use rialto_runtime::exchange::EthereumTransactionInclusionProof as Proof; diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 85deab4f1ad4b..14400c630f9e5 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -21,7 +21,6 @@ mod ethereum_deploy_contract; mod ethereum_exchange; mod ethereum_exchange_submit; mod ethereum_sync_loop; -mod ethereum_types; mod instances; mod rpc; mod rpc_errors; @@ -29,7 +28,6 @@ mod substrate_client; mod substrate_sync_loop; mod substrate_types; -use ethereum_client::{EthereumConnectionParams, EthereumSigningParams}; use ethereum_deploy_contract::EthereumDeployContractParams; use ethereum_exchange::EthereumExchangeParams; use ethereum_exchange_submit::EthereumExchangeSubmitParams; @@ -44,6 +42,7 @@ use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams}; use substrate_sync_loop::SubstrateSyncParams; use headers_relay::sync::HeadersSyncParams; +use relay_ethereum_client::{ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams}; use std::io::Write; fn main() { @@ -250,13 +249,14 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result Result { use crate::substrate_sync_loop::consts::*; - let eth_contract_address: ethereum_types::Address = if let Some(eth_contract) = matches.value_of("eth-contract") { - eth_contract.parse().map_err(|e| format!("{}", e))? - } else { - "731a10897d267e19b34503ad902d0a29173ba4b1" - .parse() - .expect("address is hardcoded, thus valid; qed") - }; + let eth_contract_address: relay_ethereum_client::types::Address = + if let Some(eth_contract) = matches.value_of("eth-contract") { + eth_contract.parse().map_err(|e| format!("{}", e))? + } else { + "731a10897d267e19b34503ad902d0a29173ba4b1" + .parse() + .expect("address is hardcoded, thus valid; qed") + }; let params = SubstrateSyncParams { sub_params: substrate_connection_params(matches)?, @@ -313,7 +313,10 @@ fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result Result { let eth_nonce = if let Some(eth_nonce) = matches.value_of("eth-nonce") { - Some(ethereum_types::U256::from_dec_str(ð_nonce).map_err(|e| format!("Failed to parse eth-nonce: {}", e))?) + Some( + relay_ethereum_client::types::U256::from_dec_str(ð_nonce) + .map_err(|e| format!("Failed to parse eth-nonce: {}", e))?, + ) } else { None }; diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs index 64b70093f12d4..ee463e38cecf5 100644 --- a/relays/ethereum/src/rpc.rs +++ b/relays/ethereum/src/rpc.rs @@ -23,11 +23,6 @@ #![allow(unused_variables)] use std::result; -use crate::ethereum_types::{ - Address as EthAddress, Bytes, CallRequest, EthereumHeaderId, Header as EthereumHeader, - HeaderWithTransactions as EthereumHeaderWithTransactions, Receipt, SignedRawTx, Transaction as EthereumTransaction, - TransactionHash as EthereumTxHash, H256, U256, U64, -}; use crate::rpc_errors::RpcError; use crate::substrate_types::{ Hash as SubstrateHash, Header as SubstrateHeader, Number as SubBlockNumber, SignedBlock as SubstrateBlock, @@ -35,36 +30,12 @@ use crate::substrate_types::{ use async_trait::async_trait; use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; +use relay_ethereum_client::types::{Bytes, HeaderId as EthereumHeaderId}; type Result = result::Result; type GrandpaAuthorityList = Vec; jsonrpsee::rpc_api! { - pub(crate) Ethereum { - #[rpc(method = "eth_estimateGas", positional_params)] - fn estimate_gas(call_request: CallRequest) -> U256; - #[rpc(method = "eth_blockNumber", positional_params)] - fn block_number() -> U64; - #[rpc(method = "eth_getBlockByNumber", positional_params)] - fn get_block_by_number(block_number: U64, full_tx_objs: bool) -> EthereumHeader; - #[rpc(method = "eth_getBlockByHash", positional_params)] - fn get_block_by_hash(hash: H256, full_tx_objs: bool) -> EthereumHeader; - #[rpc(method = "eth_getBlockByNumber", positional_params)] - fn get_block_by_number_with_transactions(number: U64, full_tx_objs: bool) -> EthereumHeaderWithTransactions; - #[rpc(method = "eth_getBlockByHash", positional_params)] - fn get_block_by_hash_with_transactions(hash: H256, full_tx_objs: bool) -> EthereumHeaderWithTransactions; - #[rpc(method = "eth_getTransactionByHash", positional_params)] - fn transaction_by_hash(hash: H256) -> Option; - #[rpc(method = "eth_getTransactionReceipt", positional_params)] - fn get_transaction_receipt(transaction_hash: H256) -> Receipt; - #[rpc(method = "eth_getTransactionCount", positional_params)] - fn get_transaction_count(address: EthAddress) -> U256; - #[rpc(method = "eth_submitTransaction", positional_params)] - fn submit_transaction(transaction: Bytes) -> EthereumTxHash; - #[rpc(method = "eth_call", positional_params)] - fn call(transaction_call: CallRequest) -> Bytes; - } - pub(crate) Substrate { #[rpc(method = "chain_getHeader", positional_params)] fn chain_get_header(block_hash: Option) -> SubstrateHeader; @@ -81,35 +52,6 @@ jsonrpsee::rpc_api! { } } -/// The API for the supported Ethereum RPC methods. -#[async_trait] -pub trait EthereumRpc { - /// Estimate gas usage for the given call. - async fn estimate_gas(&self, call_request: CallRequest) -> Result; - /// Retrieve number of the best known block from the Ethereum node. - async fn best_block_number(&self) -> Result; - /// Retrieve block header by its number from Ethereum node. - async fn header_by_number(&self, block_number: u64) -> Result; - /// Retrieve block header by its hash from Ethereum node. - async fn header_by_hash(&self, hash: H256) -> Result; - /// Retrieve block header and its transactions by its number from Ethereum node. - async fn header_by_number_with_transactions(&self, block_number: u64) -> Result; - /// Retrieve block header and its transactions by its hash from Ethereum node. - async fn header_by_hash_with_transactions(&self, hash: H256) -> Result; - /// Retrieve transaction by its hash from Ethereum node. - async fn transaction_by_hash(&self, hash: H256) -> Result>; - /// Retrieve transaction receipt by transaction hash. - async fn transaction_receipt(&self, transaction_hash: H256) -> Result; - /// Get the nonce of the given account. - async fn account_nonce(&self, address: EthAddress) -> Result; - /// Submit an Ethereum transaction. - /// - /// The transaction must already be signed before sending it through this method. - async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result; - /// Submit a call to an Ethereum smart contract. - async fn eth_call(&self, call_transaction: CallRequest) -> Result; -} - /// The API for the supported Substrate RPC methods. #[async_trait] pub trait SubstrateRpc { diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 747ec151f1e43..5e01031968fc7 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use jsonrpsee::client::RequestError; +use relay_ethereum_client::Error as EthereumNodeError; use relay_utils::MaybeConnectionError; /// Contains common errors that can occur when @@ -76,7 +77,11 @@ impl From for RpcError { impl MaybeConnectionError for RpcError { fn is_connection_error(&self) -> bool { - matches!(*self, RpcError::Request(RequestError::TransportError(_))) + match self { + RpcError::Request(RequestError::TransportError(_)) => true, + RpcError::Ethereum(ref error) => error.is_connection_error(), + _ => false, + } } } @@ -86,38 +91,6 @@ impl From for RpcError { } } -/// Errors that can occur only when interacting with -/// an Ethereum node through RPC. -#[derive(Debug)] -pub enum EthereumNodeError { - /// Failed to parse response. - ResponseParseFailed(String), - /// We have received a header with missing fields. - IncompleteHeader, - /// We have received a transaction missing a `raw` field. - IncompleteTransaction, - /// An invalid Substrate block number was received from - /// an Ethereum node. - InvalidSubstrateBlockNumber, - /// An invalid index has been received from an Ethereum node. - InvalidIncompleteIndex, -} - -impl ToString for EthereumNodeError { - fn to_string(&self) -> String { - match self { - Self::ResponseParseFailed(e) => e.to_string(), - Self::IncompleteHeader => { - "Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom)" - .to_string() - } - Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), - Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), - Self::InvalidIncompleteIndex => "Received an invalid incomplete index from Ethereum Node".to_string(), - } - } -} - /// Errors that can occur only when interacting with /// a Substrate node through RPC. #[derive(Debug)] diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs index aadde0ec14f20..4b1765aa2be05 100644 --- a/relays/ethereum/src/substrate_client.rs +++ b/relays/ethereum/src/substrate_client.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{Bytes, EthereumHeaderId, QueuedEthereumHeader, H256}; +use crate::ethereum_sync_loop::QueuedEthereumHeader; use crate::instances::BridgeInstance; use crate::rpc::{Substrate, SubstrateRpc}; use crate::rpc_errors::RpcError; @@ -28,6 +28,7 @@ use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client; use num_traits::Zero; +use relay_ethereum_client::types::{Bytes, HeaderId as EthereumHeaderId, H256}; use relay_utils::HeaderId; use sp_core::crypto::Pair; use sp_runtime::traits::IdentifyAccount; diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index ce3a5ae4d3141..8c3e0fb91d193 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -16,10 +16,7 @@ //! Substrate -> Ethereum synchronization. -use crate::ethereum_client::{ - EthereumConnectionParams, EthereumHighLevelRpc, EthereumRpcClient, EthereumSigningParams, -}; -use crate::ethereum_types::Address; +use crate::ethereum_client::EthereumHighLevelRpc; use crate::instances::BridgeInstance; use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; @@ -35,6 +32,10 @@ use headers_relay::{ sync_loop::{SourceClient, TargetClient}, sync_types::{SourceHeader, SubmittedHeaders}, }; +use relay_ethereum_client::{ + types::Address, Client as EthereumClient, ConnectionParams as EthereumConnectionParams, + SigningParams as EthereumSigningParams, +}; use relay_utils::metrics::MetricsParams; use std::fmt::Debug; @@ -125,7 +126,7 @@ impl SourceClient for SubstrateHeadersSource { /// Ethereum client as Substrate headers target. struct EthereumHeadersTarget { /// Ethereum node client. - client: EthereumRpcClient, + client: EthereumClient, /// Bridge contract address. contract: Address, /// Ethereum signing params. @@ -133,7 +134,7 @@ struct EthereumHeadersTarget { } impl EthereumHeadersTarget { - fn new(client: EthereumRpcClient, contract: Address, sign_params: EthereumSigningParams) -> Self { + fn new(client: EthereumClient, contract: Address, sign_params: EthereumSigningParams) -> Self { Self { client, contract, @@ -194,7 +195,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { instance, } = params; - let eth_client = EthereumRpcClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params); let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?; let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 4f5328b778763..793358be03a47 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -14,10 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_types::{ - Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, -}; - use codec::Encode; use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; use relay_utils::HeaderId; @@ -26,6 +22,9 @@ pub use bp_eth_poa::{ Address, AuraHeader as SubstrateEthereumHeader, Bloom, Bytes, LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, }; +use relay_ethereum_client::types::{ + Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, +}; /// Substrate header hash. pub type Hash = rialto_runtime::Hash; From 37000d172cc763eba9799481f7f8032faa346b58 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 23 Sep 2020 11:17:06 -0400 Subject: [PATCH 0163/1210] Initial Substrate Header Chain Implementation (#296) * Add pallet template from Substrate Dev Hub * Clean up un-needed stuff from template * Sketch out dispatchable interface * Introduce notion of finality chain * Add dependencies which were removed during a rebase * Sketch out idea for finality header-chain pallet * Sketch out ChainVerifier trait * Add storage parameter to verifier * Write out some things I think I need for finality verification * Add some pseudocode for marking finalized headers * Remove parity_scale_codec duplicate * Move verification logic into pallet I've been struggling with getting the generic types between the storage and verifier traits to play nice with each other. As a way to continue making progress I'm moving everything to the pallet. This way I hope to make progress towards a functional pallet. * Start doing verification around authority set changes * Remove commented BridgeStorage and ChainVerifier traits * Create Substrate bridge primitives crate * Add logic for updating scheduled authority sets * Introduce notion of imported headers * Implement basic header ancestry checker * Add mock runtime for tests * Add testing boilerplate * Add some storage read/write sanity tests * Add some basic header import tests * Add tests for ancestry proofs * Create helper for changing authority sets * Fix authority set test Fixes a problem with how the scheduled change was counted as well as a SCALE encoding issue * Correctly check for scheduled change digests There's no guarantee that the consensus digest item will be the last one in a header, which is how it was previously being checked. Thanks to Andre for pointing me to the Grandpa code that does this. * Mark imported headers as finalized when appropriate When a header that finalizes a chain of headers is succesfully imported we also want to mark its ancestors as finalized. * Add helper for writing test headers * Add test helper for scheduling authority set changes * Bump Substrate pallet and primitives to rc6 * Remove Millau verifier implementation * Add some doc comments * Remove some needless returns * Make Clippy happy * Split block import from finalization * Make tests compile again * Add test for finalizing header after importing children * Create a test stub for importing future justifications * Start adding genesis config * Reject justifications from future We should only be accepting justifications for the header which enacted the current authority set. Any ancestors of that header which require a justification can be imported but they must not be finalized. * Add explanation to some `expect()` calls * Start adding GenesisConfig * Plug genesis config into runtime * Remove tests module * Check for overflow when updating authority sets * Make verifier take ownership of headers during import * Only store best finalized header hash Removed the need to store the whole header, since we store it was part of the ImportedHeaders structure anyways * Add some helpers to ImportedHeader * Update ancestry checker to work with ImportedHeaders * Update ancestry tests to use ImportedHeaders * Update import tests to use ImportedHeaders * Clean up some of the test helpers * Remove stray dbg! * Add doc comments throughout * Remove runtime related code * Fix Clippy warnings * Remove trait bound on ImportedHeader struct * Simplify checks in GenesisConfig * Rename `get_header_by_hash()` * Alias `parity_scale_codec` to `codec` * Reword Verifier documentation * Missed codec rename in tests * Split ImportError into FinalizationError * Remove ChainVerifier trait This trait was a remenant of the original design, and it is not required at the moment. Something like it should be added back in the future to ensure that other chains which conform to this interface can be used by higher-level bridge applications. * Fix the verifier tests so they compile * Implement Deref for ImportedHeader * Get rid of `new` methods for some Substrate primitives * Ensure that a child header's number follows its parent's * Prevent ancestry checker from aimlessly traversing to genesis If an ancestor which was newer than the child header we were checking we would walk all the way to genesis before realizing that we weren't related. This commit fixes that. * Remove redundant clones * Ensure that old headers are not finalized Prevents a panic where if the header being imported and `best_finalized` were the same header the ancestry checker would return an empty list. We had made an assumption that the list would always be populated, and if this didn't hold we would end up panicking. * Disallow imports at same height as `best_finalized` * Fix Clippy warnings * Make NextScheduledChange optional * Rework how scheduled authority set changes are enacted We now require a justification for headers which _enact_ changes instead of those which _schedule_ changes. A few changes had to be made to accomodate this, such as changing when we check for scheduled change logs in incoming headers. * Update documentation for Substrate Primitives * Clarify why we skip header in requires_justification check * Add description to assert! call * Fix formatting within macros * Remove unused dependencies from runtime * Remove expect call in GenesisConfig * Turn FinalityProof into a struct * Add some inline TODOs for follow up PRs * Remove test which enacted multiple changes This should be added back at some later point in time, but right now the code doesn't allow for this behaviour. * Use `contains_key` when checking for header This is better than using `get().is_some()` since we skip decoding the storage value * Use initial hash when updating best_finalized * Add better checks around enacting scheduled changes * Rename finality related functions * Appease Clippy --- modules/substrate/Cargo.toml | 26 +- modules/substrate/src/justification.rs | 1 + modules/substrate/src/lib.rs | 258 ++++++++++ modules/substrate/src/mock.rs | 75 +++ modules/substrate/src/storage_proof.rs | 1 + modules/substrate/src/verifier.rs | 680 +++++++++++++++++++++++++ primitives/substrate/Cargo.toml | 36 ++ primitives/substrate/src/lib.rs | 82 +++ 8 files changed, 1158 insertions(+), 1 deletion(-) create mode 100644 modules/substrate/src/mock.rs create mode 100644 modules/substrate/src/verifier.rs create mode 100644 primitives/substrate/Cargo.toml create mode 100644 primitives/substrate/src/lib.rs diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 365ce68993539..6fb935e548310 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -8,17 +8,32 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-substrate = { path = "../../primitives/substrate", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } hash-db = { version = "0.15.2", default-features = false } +serde = { version = "1.0", optional = true } + +[dependencies.codec] +package = "parity-scale-codec" +version = "1.3.1" +default-features = false +features = ["derive"] # Substrate Based Dependencies + [dependencies.frame-support] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" +[dependencies.frame-system] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + [dependencies.sp-finality-grandpa] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' @@ -43,6 +58,12 @@ tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate/" +# Dev Dependencies +[dev-dependencies.sp-io] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +git = "https://github.com/paritytech/substrate/" + [dev-dependencies.sp-core] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' @@ -67,8 +88,11 @@ std = [ "codec/std", "finality-grandpa/std", "frame-support/std", + "frame-system/std", + "serde", "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", + "sp-io/std", ] diff --git a/modules/substrate/src/justification.rs b/modules/substrate/src/justification.rs index 0457278197aa2..4887e180896bd 100644 --- a/modules/substrate/src/justification.rs +++ b/modules/substrate/src/justification.rs @@ -26,6 +26,7 @@ use frame_support::RuntimeDebug; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::traits::Header as HeaderT; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; +use sp_std::prelude::Vec; /// Justification verification error. #[derive(RuntimeDebug, PartialEq)] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index ec00311e6eabe..4fb9dbd3d5f1d 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -14,5 +14,263 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Substrate Bridge Pallet +//! +//! This pallet is an on-chain light client for chains which have a notion of finality. +//! +//! It has a simple interface for achieving this. First it can import headers to the runtime +//! storage. During this it will check the validity of the headers and ensure they don't conflict +//! with any existing headers (e.g they're on a different finalized chain). Secondly it can finalize +//! an already imported header (and its ancestors) given a valid Grandpa justification. +//! +//! With these two functions the pallet is able to form a "source of truth" for what headers have +//! been finalized on a given Substrate chain. This can be a useful source of info for other +//! higher-level applications. + +#![cfg_attr(not(feature = "std"), no_std)] +// Runtime-generated enums +#![allow(clippy::large_enum_variant)] + +use bp_substrate::{AuthoritySet, ImportedHeader, ScheduledChange}; +use frame_support::{decl_error, decl_module, decl_storage, dispatch}; +use frame_system::ensure_signed; +use sp_runtime::traits::Header as HeaderT; +use sp_std::{marker::PhantomData, prelude::*}; + mod justification; mod storage_proof; +mod verifier; + +#[cfg(test)] +mod mock; + +type Hash = ::Hash; +type Number = ::Number; + +pub trait Trait: frame_system::Trait {} + +decl_storage! { + trait Store for Module as SubstrateBridge { + /// Hash of the best finalized header. + BestFinalized: T::Hash; + /// Headers which have been imported into the pallet. + ImportedHeaders: map hasher(identity) T::Hash => Option>; + /// The current Grandpa Authority set. + CurrentAuthoritySet: AuthoritySet; + /// The next scheduled authority set change. + /// + // Grandpa doesn't require there to always be a pending change. In fact, most of the time + // there will be no pending change available. + NextScheduledChange: Option>>; + } + add_extra_genesis { + config(initial_header): Option; + config(initial_authority_list): sp_finality_grandpa::AuthorityList; + config(initial_set_id): sp_finality_grandpa::SetId; + config(first_scheduled_change): Option>>; + build(|config| { + assert!( + !config.initial_authority_list.is_empty(), + "An initial authority list is needed." + ); + + let initial_header = config + .initial_header + .clone() + .expect("An initial header is needed"); + + >::put(initial_header.hash()); + >::insert( + initial_header.hash(), + ImportedHeader { + header: initial_header, + requires_justification: false, + is_finalized: true, + }, + ); + + let authority_set = + AuthoritySet::new(config.initial_authority_list.clone(), config.initial_set_id); + CurrentAuthoritySet::put(authority_set); + + if let Some(ref change) = config.first_scheduled_change { + >::put(change); + }; + }) + } +} + +decl_error! { + pub enum Error for Module { + /// This header has failed basic verification. + InvalidHeader, + /// This header has not been finalized. + UnfinalizedHeader, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + /// Import a signed Substrate header into the runtime. + /// + /// This will perform some basic checks to make sure it is fine to + /// import into the runtime. However, it does not perform any checks + /// related to finality. + // TODO: Update weights [#78] + #[weight = 0] + pub fn import_signed_header( + origin, + header: T::Header, + ) -> dispatch::DispatchResult { + let _ = ensure_signed(origin)?; + frame_support::debug::trace!(target: "sub-bridge", "Got header {:?}", header); + + let mut verifier = verifier::Verifier { + storage: PalletStorage::::new(), + }; + + let _ = verifier + .import_header(header) + .map_err(|_| >::InvalidHeader)?; + + Ok(()) + } + + /// Import a finalty proof for a particular header. + /// + /// This will take care of finalizing any already imported headers + /// which get finalized when importing this particular proof, as well + /// as updating the current and next validator sets. + // TODO: Update weights [#78] + #[weight = 0] + pub fn finalize_header( + origin, + hash: Hash, + finality_proof: Vec, + ) -> dispatch::DispatchResult { + let _ = ensure_signed(origin)?; + frame_support::debug::trace!(target: "sub-bridge", "Got header hash {:?}", hash); + + let mut verifier = verifier::Verifier { + storage: PalletStorage::::new(), + }; + + let _ = verifier + .import_finality_proof(hash, finality_proof.into()) + .map_err(|_| >::UnfinalizedHeader)?; + + Ok(()) + } + } +} + +/// Expected interface for interacting with bridge pallet storage. +// TODO: This should be split into its own less-Substrate-dependent crate +pub trait BridgeStorage { + /// The header type being used by the pallet. + type Header: HeaderT; + + /// Write a header to storage. + fn write_header(&mut self, header: &ImportedHeader); + + /// Get the best finalized header the pallet knows of. + fn best_finalized_header(&self) -> ImportedHeader; + + /// Update the best finalized header the pallet knows of. + fn update_best_finalized(&self, hash: ::Hash); + + /// Check if a particular header is known to the pallet. + fn header_exists(&self, hash: ::Hash) -> bool; + + /// Get a specific header by its hash. + /// + /// Returns None if it is not known to the pallet. + fn header_by_hash(&self, hash: ::Hash) -> Option>; + + /// Get the current Grandpa authority set. + fn current_authority_set(&self) -> AuthoritySet; + + /// Update the current Grandpa authority set. + /// + /// Should only be updated when a scheduled change has been triggered. + fn update_current_authority_set(&self, new_set: AuthoritySet); + + /// Replace the current authority set with the next scheduled set. + /// + /// Returns an error if there is no scheduled authority set to enact. + fn enact_authority_set(&mut self) -> Result<(), ()>; + + /// Get the next scheduled Grandpa authority set change. + fn scheduled_set_change(&self) -> Option::Number>>; + + /// Schedule a Grandpa authority set change in the future. + fn schedule_next_set_change(&self, next_change: ScheduledChange<::Number>); +} + +/// Used to interact with the pallet storage in a more abstract way. +#[derive(Default, Clone)] +pub struct PalletStorage(PhantomData); + +impl PalletStorage { + fn new() -> Self { + Self(PhantomData::::default()) + } +} + +impl BridgeStorage for PalletStorage { + type Header = T::Header; + + fn write_header(&mut self, header: &ImportedHeader) { + let hash = header.header.hash(); + >::insert(hash, header); + } + + fn best_finalized_header(&self) -> ImportedHeader { + let hash = >::get(); + self.header_by_hash(hash) + .expect("A finalized header was added at genesis, therefore this must always exist") + } + + fn update_best_finalized(&self, hash: Hash) { + >::put(hash) + } + + fn header_exists(&self, hash: Hash) -> bool { + >::contains_key(hash) + } + + fn header_by_hash(&self, hash: Hash) -> Option> { + >::get(hash) + } + + fn current_authority_set(&self) -> AuthoritySet { + CurrentAuthoritySet::get() + } + + fn update_current_authority_set(&self, new_set: AuthoritySet) { + CurrentAuthoritySet::put(new_set) + } + + fn enact_authority_set(&mut self) -> Result<(), ()> { + if >::exists() { + let new_set = >::take() + .expect("Ensured that entry existed in storage") + .authority_set; + self.update_current_authority_set(new_set); + + Ok(()) + } else { + Err(()) + } + } + + fn scheduled_set_change(&self) -> Option>> { + >::get() + } + + fn schedule_next_set_change(&self, next_change: ScheduledChange>) { + >::put(next_change) + } +} diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs new file mode 100644 index 0000000000000..303f1ad61db5f --- /dev/null +++ b/modules/substrate/src/mock.rs @@ -0,0 +1,75 @@ +// Copyright 2020 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 . + +#![cfg(test)] + +use crate::Trait; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use sp_runtime::{ + testing::{Header, H256}, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +pub type AccountId = u64; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct TestRuntime; + +impl_outer_origin! { + pub enum Origin for TestRuntime where system = frame_system {} +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Trait for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = (); + type AvailableBlockRatio = AvailableBlockRatio; + type MaximumBlockLength = MaximumBlockLength; + type Version = (); + type ModuleToIndex = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = (); + type SystemWeightInfo = (); +} + +impl Trait for TestRuntime {} + +pub fn run_test(test: impl FnOnce() -> T) -> T { + sp_io::TestExternalities::new(Default::default()).execute_with(test) +} diff --git a/modules/substrate/src/storage_proof.rs b/modules/substrate/src/storage_proof.rs index 40a1399695448..97ec09e132891 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/modules/substrate/src/storage_proof.rs @@ -21,6 +21,7 @@ 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" diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs new file mode 100644 index 0000000000000..aa0924508a961 --- /dev/null +++ b/modules/substrate/src/verifier.rs @@ -0,0 +1,680 @@ +// Copyright 2020 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 . + +//! The verifier's role is to check the validity of headers being imported, and also determine if +//! they can be finalized. +//! +//! When importing headers it performs checks to ensure that no invariants are broken (like +//! importing the same header twice). When it imports finality proofs it will ensure that the proof +//! has been signed off by the correct Grandpa authorities, and also enact any authority set changes +//! if required. + +use crate::BridgeStorage; +use bp_substrate::{check_finality_proof, AuthoritySet, ImportedHeader, ScheduledChange}; +use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; +use sp_runtime::generic::OpaqueDigestItemId; +use sp_runtime::traits::{CheckedAdd, Header as HeaderT, One}; +use sp_std::{prelude::Vec, vec}; + +/// The finality proof used by the pallet. +/// +/// For a Substrate based chain using Grandpa this will +/// be an encoded Grandpa Justification. +pub struct FinalityProof(Vec); + +impl From<&[u8]> for FinalityProof { + fn from(proof: &[u8]) -> Self { + Self(proof.to_vec()) + } +} + +impl From> for FinalityProof { + fn from(proof: Vec) -> Self { + Self(proof) + } +} + +/// Errors which can happen while importing a header. +#[derive(Debug, PartialEq)] +pub enum ImportError { + /// This header is older than our latest finalized block, thus not useful. + OldHeader, + /// This header has already been imported by the pallet. + HeaderAlreadyExists, + /// We're missing a parent for this header. + MissingParent, + /// The number of the header does not follow its parent's number. + InvalidChildNumber, + /// The height of the next authority set change overflowed. + ScheduledHeightOverflow, +} + +/// Errors which can happen while verifying a headers finality. +#[derive(Debug, PartialEq)] +pub enum FinalizationError { + /// This header has never been imported by the pallet. + UnknownHeader, + /// We were unable to prove finality for this header. + UnfinalizedHeader, + /// Trying to prematurely import a justification + PrematureJustification, + /// We failed to verify this header's ancestry. + AncestryCheckFailed, + /// This header is older than our latest finalized block, thus not useful. + OldHeader, +} + +/// Used to verify imported headers and their finality status. +#[derive(Debug)] +pub struct Verifier { + pub storage: S, +} + +impl Verifier +where + S: BridgeStorage
, + H: HeaderT, +{ + /// Import a header to the pallet. + /// + /// Will perform some basic checks to make sure that this header doesn't break any assumptions + /// such as being on a different finalized fork. + pub fn import_header(&mut self, header: H) -> Result<(), ImportError> { + let best_finalized = self.storage.best_finalized_header(); + + if header.number() <= best_finalized.number() { + return Err(ImportError::OldHeader); + } + + if self.storage.header_exists(header.hash()) { + return Err(ImportError::HeaderAlreadyExists); + } + + let parent_header = self + .storage + .header_by_hash(*header.parent_hash()) + .ok_or(ImportError::MissingParent)?; + + let parent_number = *parent_header.number(); + if parent_number + One::one() != *header.number() { + return Err(ImportError::InvalidChildNumber); + } + + // This header requires a justification since it enacts an authority set change. We don't + // need to act on it right away (we'll update the set once this header gets finalized), but + // we need to make a note of it. + // + // TODO: This assumes that we can only have one authority set change pending at a time. + // This is not strictly true as Grandpa may schedule multiple changes on a given chain + // if the "next next" change is scheduled after the "delay" period of the "next" change + let requires_justification = if let Some(change) = self.storage.scheduled_set_change() { + change.height == *header.number() + } else { + // Since we don't currently have a pending authority set change let's check if the header + // contains a log indicating when the next change should be. + if let Some(change) = find_scheduled_change(&header) { + let next_set = AuthoritySet { + authorities: change.next_authorities, + set_id: self.storage.current_authority_set().set_id + 1, + }; + + let height = (*header.number()) + .checked_add(&change.delay) + .ok_or(ImportError::ScheduledHeightOverflow)?; + let scheduled_change = ScheduledChange { + authority_set: next_set, + height, + }; + + self.storage.schedule_next_set_change(scheduled_change); + + // If the delay is 0 this header will enact the change it signaled + height == *header.number() + } else { + false + } + }; + + let is_finalized = false; + self.storage.write_header(&ImportedHeader { + header, + requires_justification, + is_finalized, + }); + + Ok(()) + } + + /// Verify that a previously imported header can be finalized with the given Grandpa finality + /// proof. If the header enacts an authority set change the change will be applied once the + /// header has been finalized. + pub fn import_finality_proof(&mut self, hash: H::Hash, proof: FinalityProof) -> Result<(), FinalizationError> { + // Make sure that we've previously imported this header + let header = self + .storage + .header_by_hash(hash) + .ok_or(FinalizationError::UnknownHeader)?; + + // We don't want to finalize an ancestor of an already finalized + // header, this would be inconsistent + let last_finalized = self.storage.best_finalized_header(); + if header.number() <= last_finalized.number() { + return Err(FinalizationError::OldHeader); + } + + let current_authority_set = self.storage.current_authority_set(); + let is_finalized = check_finality_proof(&header, ¤t_authority_set, &proof.0); + if !is_finalized { + return Err(FinalizationError::UnfinalizedHeader); + } + + frame_support::debug::trace!(target: "sub-bridge", "Checking ancestry for headers between {:?} and {:?}", last_finalized, header); + let mut finalized_headers = + if let Some(ancestors) = headers_between(&self.storage, last_finalized, header.clone()) { + // Since we only try and finalize headers with a height strictly greater + // than `best_finalized` if `headers_between` returns Some we must have + // at least one element. If we don't something's gone wrong, so best + // to die before we write to storage. + assert_eq!( + ancestors.is_empty(), + false, + "Empty ancestry list returned from `headers_between()`", + ); + + // Check if any of our ancestors `requires_justification` a.k.a schedule authority + // set changes. If they're still waiting to be finalized we must reject this + // justification. We don't include our current header in this check. + // + // We do this because it is important to to import justifications _in order_, + // otherwise we risk finalizing headers on competing chains. + let requires_justification = ancestors.iter().skip(1).find(|h| h.requires_justification); + if requires_justification.is_some() { + return Err(FinalizationError::PrematureJustification); + } + + ancestors + } else { + return Err(FinalizationError::AncestryCheckFailed); + }; + + // If the current header was marked as `requires_justification` it means that it enacts a + // new authority set change. When we finalize the header we need to update the current + // authority set. + if header.requires_justification { + // If we are unable to enact an authority set it means our storage entry for scheduled + // changes is missing. Best to crash since this is likely a bug. + let _ = self.storage.enact_authority_set().expect( + "Headers must only be marked as `requires_justification` if there's a scheduled change in storage.", + ); + } + + for header in finalized_headers.iter_mut() { + header.is_finalized = true; + header.requires_justification = false; + self.storage.write_header(header); + } + + self.storage.update_best_finalized(hash); + + Ok(()) + } +} + +/// Returns the lineage of headers between [child, ancestor) +fn headers_between( + storage: &S, + ancestor: ImportedHeader, + child: ImportedHeader, +) -> Option>> +where + S: BridgeStorage
, + H: HeaderT, +{ + let mut ancestors = vec![]; + let mut current_header = child; + + while ancestor.hash() != current_header.hash() { + // We've gotten to the same height and we're not related + if ancestor.number() >= current_header.number() { + return None; + } + + let parent = storage.header_by_hash(*current_header.parent_hash()); + ancestors.push(current_header); + current_header = match parent { + Some(h) => h, + None => return None, + } + } + + Some(ancestors) +} + +fn find_scheduled_change(header: &H) -> Option> { + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + + let filter_log = |log: ConsensusLog| match log { + ConsensusLog::ScheduledChange(change) => Some(change), + _ => None, + }; + + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use crate::{BestFinalized, ImportedHeaders, PalletStorage}; + use frame_support::{assert_err, assert_ok}; + use frame_support::{StorageMap, StorageValue}; + use sp_finality_grandpa::{AuthorityId, AuthorityList}; + use sp_runtime::testing::UintAuthorityId; + + type TestHeader = ::Header; + type TestNumber = ::Number; + + fn unfinalized_header(num: u64) -> ImportedHeader { + ImportedHeader { + header: TestHeader::new_from_number(num), + requires_justification: false, + is_finalized: false, + } + } + + fn get_authorities(authorities: Vec<(u64, u64)>) -> AuthorityList { + authorities + .iter() + .map(|(id, weight)| (UintAuthorityId(*id).to_public_key::(), *weight)) + .collect() + } + + fn schedule_next_change( + authorities: Vec<(u64, u64)>, + set_id: u64, + height: TestNumber, + ) -> ScheduledChange { + let authorities = get_authorities(authorities); + let authority_set = AuthoritySet::new(authorities, set_id); + ScheduledChange { authority_set, height } + } + + // Useful for quickly writing a chain of headers to storage + fn write_headers>( + storage: &mut S, + headers: Vec<(u64, bool, bool)>, + ) -> Vec> { + let mut imported_headers = vec![]; + let genesis = ImportedHeader { + header: TestHeader::new_from_number(0), + requires_justification: false, + is_finalized: true, + }; + + >::put(genesis.hash()); + storage.write_header(&genesis); + imported_headers.push(genesis); + + for (num, requires_justification, is_finalized) in headers { + let mut h = TestHeader::new_from_number(num); + h.parent_hash = imported_headers.last().unwrap().hash(); + + let header = ImportedHeader { + header: h, + requires_justification, + is_finalized, + }; + + storage.write_header(&header); + imported_headers.push(header); + } + + imported_headers + } + + #[test] + fn fails_to_import_old_header() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let parent = unfinalized_header(5); + storage.write_header(&parent); + storage.update_best_finalized(parent.hash()); + + let header = TestHeader::new_from_number(1); + let mut verifier = Verifier { storage }; + assert_err!(verifier.import_header(header), ImportError::OldHeader); + }) + } + + #[test] + fn fails_to_import_header_without_parent() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let parent = unfinalized_header(1); + storage.write_header(&parent); + storage.update_best_finalized(parent.hash()); + + // By default the parent is `0x00` + let header = TestHeader::new_from_number(2); + + let mut verifier = Verifier { storage }; + assert_err!(verifier.import_header(header), ImportError::MissingParent); + }) + } + + #[test] + fn fails_to_import_header_twice() { + run_test(|| { + let storage = PalletStorage::::new(); + let header = TestHeader::new_from_number(1); + >::put(header.hash()); + + let imported_header = ImportedHeader { + header: header.clone(), + requires_justification: false, + is_finalized: false, + }; + >::insert(header.hash(), &imported_header); + + let mut verifier = Verifier { storage }; + assert_err!(verifier.import_header(header), ImportError::OldHeader); + }) + } + + #[test] + fn succesfully_imports_valid_but_unfinalized_header() { + run_test(|| { + let storage = PalletStorage::::new(); + let parent = TestHeader::new_from_number(1); + let parent_hash = parent.hash(); + >::put(parent.hash()); + + let imported_header = ImportedHeader { + header: parent, + requires_justification: false, + is_finalized: true, + }; + >::insert(parent_hash, &imported_header); + + let mut header = TestHeader::new_from_number(2); + header.parent_hash = parent_hash; + let mut verifier = Verifier { + storage: storage.clone(), + }; + assert_ok!(verifier.import_header(header.clone())); + + let stored_header = storage.header_by_hash(header.hash()); + assert!(stored_header.is_some()); + assert_eq!(stored_header.unwrap().is_finalized, false); + }) + } + + #[test] + fn related_headers_are_ancestors() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let headers = vec![(1, false, false), (2, false, false), (3, false, false)]; + let mut imported_headers = write_headers(&mut storage, headers); + + for header in imported_headers.iter() { + assert!(storage.header_exists(header.hash())); + } + + let ancestor = imported_headers.remove(0); + let child = imported_headers.pop().unwrap(); + let ancestors = headers_between(&storage, ancestor, child); + + assert!(ancestors.is_some()); + assert_eq!(ancestors.unwrap().len(), 3); + }) + } + + #[test] + fn unrelated_headers_are_not_ancestors() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let headers = vec![(1, false, false), (2, false, false), (3, false, false)]; + let mut imported_headers = write_headers(&mut storage, headers); + for header in imported_headers.iter() { + assert!(storage.header_exists(header.hash())); + } + + // Need to give it a different parent_hash or else it'll be + // related to our test genesis header + let mut bad_ancestor = TestHeader::new_from_number(0); + bad_ancestor.parent_hash = [1u8; 32].into(); + let bad_ancestor = ImportedHeader { + header: bad_ancestor, + requires_justification: false, + is_finalized: false, + }; + + let child = imported_headers.pop().unwrap(); + let ancestors = headers_between(&storage, bad_ancestor, child); + assert!(ancestors.is_none()); + }) + } + + #[test] + fn ancestor_newer_than_child_is_not_related() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let headers = vec![(1, false, false), (2, false, false), (3, false, false)]; + let mut imported_headers = write_headers(&mut storage, headers); + for header in imported_headers.iter() { + assert!(storage.header_exists(header.hash())); + } + + // What if we have an "ancestor" that's newer than child? + let new_ancestor = TestHeader::new_from_number(5); + let new_ancestor = ImportedHeader { + header: new_ancestor, + requires_justification: false, + is_finalized: false, + }; + + let child = imported_headers.pop().unwrap(); + let ancestors = headers_between(&storage, new_ancestor, child); + assert!(ancestors.is_none()); + }) + } + + #[test] + fn finalizes_header_which_doesnt_enact_or_schedule_a_new_authority_set() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let headers = vec![(1, false, false)]; + let imported_headers = write_headers(&mut storage, headers); + + // Nothing special about this header, yet Grandpa may have created a justification + // for it since it does that periodically + let mut header = TestHeader::new_from_number(2); + header.parent_hash = imported_headers[1].hash(); + + let mut verifier = Verifier { + storage: storage.clone(), + }; + + assert_ok!(verifier.import_header(header.clone())); + assert_ok!(verifier.import_finality_proof(header.hash(), vec![4, 2].into())); + assert_eq!(storage.best_finalized_header().header, header); + }) + } + + #[test] + fn correctly_verifies_and_finalizes_chain_of_headers() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let headers = vec![(1, false, false), (2, false, false)]; + let imported_headers = write_headers(&mut storage, headers); + + let mut header = TestHeader::new_from_number(3); + header.parent_hash = imported_headers[2].hash(); + + let mut verifier = Verifier { + storage: storage.clone(), + }; + assert!(verifier.import_header(header.clone()).is_ok()); + assert!(verifier.import_finality_proof(header.hash(), vec![4, 2].into()).is_ok()); + + // Make sure we marked the our headers as finalized + assert!(storage.header_by_hash(imported_headers[1].hash()).unwrap().is_finalized); + assert!(storage.header_by_hash(imported_headers[2].hash()).unwrap().is_finalized); + assert!(storage.header_by_hash(header.hash()).unwrap().is_finalized); + + // Make sure the header at the highest height is the best finalized + assert_eq!(storage.best_finalized_header().header, header); + }); + } + + #[test] + fn updates_authority_set_upon_finalizing_header_which_enacts_change() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let headers = vec![(1, false, false)]; + let imported_headers = write_headers(&mut storage, headers); + + let set_id = 0; + let authorities = get_authorities(vec![(1, 1)]); + let initial_authority_set = AuthoritySet::new(authorities, set_id); + storage.update_current_authority_set(initial_authority_set); + + // This header enacts an authority set change upon finalization + let mut header = TestHeader::new_from_number(2); + header.parent_hash = imported_headers[1].hash(); + + // Schedule a change at the height of our header + let set_id = 1; + let height = *header.number(); + let authorities = vec![(2, 1)]; + let change = schedule_next_change(authorities, set_id, height); + storage.schedule_next_set_change(change.clone()); + + let mut verifier = Verifier { + storage: storage.clone(), + }; + + assert_ok!(verifier.import_header(header.clone())); + assert_ok!(verifier.import_finality_proof(header.hash(), vec![4, 2].into())); + assert_eq!(storage.best_finalized_header().header, header); + + // Make sure that we have updated the set now that we've finalized our header + assert_eq!(storage.current_authority_set(), change.authority_set); + }) + } + + #[test] + fn importing_finality_proof_for_already_finalized_header_doesnt_work() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let genesis = TestHeader::new_from_number(0); + + let genesis = ImportedHeader { + header: genesis, + requires_justification: false, + is_finalized: true, + }; + + // Make sure that genesis is the best finalized header + >::put(genesis.hash()); + storage.write_header(&genesis); + + let mut verifier = Verifier { storage }; + + // Now we want to try and import it again to see what happens + assert_eq!( + verifier + .import_finality_proof(genesis.hash(), vec![4, 2].into()) + .unwrap_err(), + FinalizationError::OldHeader + ); + }); + } + + // We're supposed to enact a set change at header N. This means that when we import it we must + // remember that it requires a justification. We can continue importing headers past N but must + // not finalize any childen. At a later point in time we should be able to import the + // justification for N. + // + // Since N enacts a new authority set, when we finalize it we should see this change reflected + // correctly. + // + // [G] <- [N-1] <- [N] <- [N+1] <- [N+2] + // | |- Import justification for N here + // |- Enacts change, needs justification + #[test] + fn allows_importing_justification_at_block_past_scheduled_change() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let headers = vec![(1, false, false)]; + let imported_headers = write_headers(&mut storage, headers); + + // This is header N + let mut header = TestHeader::new_from_number(2); + header.parent_hash = imported_headers[1].hash(); + + // Schedule a change at height N + let set_id = 1; + let height = *header.number(); + let authorities = vec![(1, 1)]; + let change = schedule_next_change(authorities, set_id, height); + storage.schedule_next_set_change(change.clone()); + + // Import header N + let mut verifier = Verifier { + storage: storage.clone(), + }; + assert!(verifier.import_header(header.clone()).is_ok()); + + // Header N should be marked as needing a justification + assert_eq!( + storage.header_by_hash(header.hash()).unwrap().requires_justification, + true + ); + + // Now we want to import some headers which are past N + let mut child = TestHeader::new_from_number(*header.number() + 1); + child.parent_hash = header.hash(); + assert!(verifier.import_header(child.clone()).is_ok()); + + let mut grandchild = TestHeader::new_from_number(*child.number() + 1); + grandchild.parent_hash = child.hash(); + assert!(verifier.import_header(grandchild).is_ok()); + + // Even though we're a few headers ahead we should still be able to import + // a justification for header N + assert!(verifier.import_finality_proof(header.hash(), vec![4, 2].into()).is_ok()); + + // Some checks to make sure that our header has been correctly finalized + let finalized_header = storage.header_by_hash(header.hash()).unwrap(); + assert!(finalized_header.is_finalized); + assert_eq!(finalized_header.requires_justification, false); + assert_eq!(storage.best_finalized_header().header, header); + + // Make sure we marked the parent of the header at N as finalized + assert!(storage.header_by_hash(imported_headers[1].hash()).unwrap().is_finalized); + + // Since our header was supposed to enact a new authority set change when it got + // finalized let's make sure that the authority set actually changed + assert_eq!(storage.current_authority_set(), change.authority_set); + }) + } +} diff --git a/primitives/substrate/Cargo.toml b/primitives/substrate/Cargo.toml new file mode 100644 index 0000000000000..c452b767a8ab1 --- /dev/null +++ b/primitives/substrate/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "bp-substrate" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0", optional = true } + +[dependencies.sp-finality-grandpa] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate.git" + +[dependencies.sp-runtime] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate/" + +[dependencies.parity-scale-codec] +version = "1.3.1" +default-features = false +features = ["derive"] + +[features] +default = ["std"] +std = [ + "serde/std", + "sp-runtime/std", + "sp-finality-grandpa/std", +] diff --git a/primitives/substrate/src/lib.rs b/primitives/substrate/src/lib.rs new file mode 100644 index 0000000000000..0b63f0deefbda --- /dev/null +++ b/primitives/substrate/src/lib.rs @@ -0,0 +1,82 @@ +// Copyright 2019-2020 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 . + +//! Primitives for the Substrate light client (a.k.a bridge) pallet. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +use core::default::Default; +use parity_scale_codec::{Decode, Encode}; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_finality_grandpa::{AuthorityList, SetId}; +use sp_runtime::RuntimeDebug; + +/// A Grandpa Authority List and ID. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct AuthoritySet { + /// List of Grandpa authorities for the current round. + pub authorities: AuthorityList, + /// Monotonic identifier of the current Grandpa authority set. + pub set_id: SetId, +} + +impl AuthoritySet { + /// Create a new Grandpa Authority Set. + pub fn new(authorities: AuthorityList, set_id: SetId) -> Self { + Self { authorities, set_id } + } +} + +/// Keeps track of when the next Grandpa authority set change will occur. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ScheduledChange { + /// The authority set that will be used once this change is enacted. + pub authority_set: AuthoritySet, + /// The block height at which the authority set should be enacted. + /// + /// Note: It will only be enacted once a header at this height is finalized. + pub height: N, +} + +/// A more useful representation of a header for storage purposes. +#[derive(Default, Encode, Decode, Clone, RuntimeDebug, PartialEq)] +pub struct ImportedHeader { + /// A plain Substrate header. + pub header: H, + /// Does this header enact a new authority set change. If it does + /// then it will require a justification. + pub requires_justification: bool, + /// Has this header been finalized, either explicitly via a justification, + /// or implicitly via one of its children getting finalized. + pub is_finalized: bool, +} + +impl core::ops::Deref for ImportedHeader { + type Target = H; + + fn deref(&self) -> &H { + &self.header + } +} + +/// Prove that the given header was finalized by the given authority set. +pub fn check_finality_proof(_header: &H, _set: &AuthoritySet, _justification: &[u8]) -> bool { + true +} From 242b6a0d4ade8e50ec119a71907974825f26944c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Sep 2020 22:22:44 +0300 Subject: [PATCH 0164/1210] Fees, weights, message delivery and dispatch (#339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * introduce BridgedHeaderChain trait * LaneMessageVerifier + tests * fixed tests * do not expose intenal functions * cargo fmt --all + fix no_std compilation * ByWeightDispatcher * process queued messages from message-lane::on_initialize * scheduled_messages_are_processed_from_on_initialize * flush * deal with fees + weights * drop heavy messages on dispatch * cargo fmt * clippy * fix comment * Update primitives/message-lane/src/source_chain.rs Co-authored-by: Tomasz Drwięga * removed messages_processed * Update primitives/message-lane/src/source_chain.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano * remove queueing from message-lane * also remove queueing from RPCs * remove by-weight traces * dispatch fee * receiving -> delivery * receival -> delivery * remove extra line * Update primitives/message-lane/src/source_chain.rs Co-authored-by: Hernando Castano * cargo fmt --all * clippy * let dispatch_weight to be larger than actual_dispatch_weight * post-merge fix Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- modules/call-dispatch/src/lib.rs | 22 +- modules/message-lane/Cargo.toml | 6 +- modules/message-lane/rpc/src/lib.rs | 14 +- modules/message-lane/src/inbound_lane.rs | 20 +- modules/message-lane/src/lib.rs | 452 +++++++++++++++++--- modules/message-lane/src/mock.rs | 145 ++++++- modules/message-lane/src/outbound_lane.rs | 64 +-- primitives/message-dispatch/src/lib.rs | 8 +- primitives/message-lane/Cargo.toml | 16 +- primitives/message-lane/src/lib.rs | 44 +- primitives/message-lane/src/source_chain.rs | 97 +++++ primitives/message-lane/src/target_chain.rs | 56 +++ relays/messages-relay/src/message_lane.rs | 2 +- 13 files changed, 802 insertions(+), 144 deletions(-) create mode 100644 primitives/message-lane/src/source_chain.rs create mode 100644 primitives/message-lane/src/target_chain.rs diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 205c0cbfc00d8..1524c0d223802 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -46,10 +46,6 @@ use sp_std::{marker::PhantomData, prelude::*}; /// Spec version type. pub type SpecVersion = u32; -// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) -/// Weight of single deposit_event() call. -const DEPOSIT_EVENT_WEIGHT: Weight = 0; - /// Origin of the call on the target chain. #[derive(RuntimeDebug, Encode, Decode, Clone)] pub enum CallOrigin { @@ -149,7 +145,11 @@ impl, I: Instance> MessageDispatch for Module { >::Call, >; - fn dispatch(bridge: InstanceId, id: T::MessageId, message: Self::Message) -> Weight { + fn dispatch_weight(message: &Self::Message) -> Weight { + message.weight + } + + fn dispatch(bridge: InstanceId, id: T::MessageId, message: Self::Message) { // verify spec version // (we want it to be the same, because otherwise we may decode Call improperly) let expected_version = ::Version::get().spec_version; @@ -167,7 +167,7 @@ impl, I: Instance> MessageDispatch for Module { expected_version, message.spec_version, )); - return DEPOSIT_EVENT_WEIGHT; + return; } // verify weight @@ -189,7 +189,7 @@ impl, I: Instance> MessageDispatch for Module { expected_weight, message.weight, )); - return DEPOSIT_EVENT_WEIGHT; + return; } // prepare dispatch origin @@ -210,7 +210,7 @@ impl, I: Instance> MessageDispatch for Module { target_signature, ); Self::deposit_event(RawEvent::MessageSignatureMismatch(bridge, id)); - return DEPOSIT_EVENT_WEIGHT; + return; } target_account @@ -222,9 +222,11 @@ impl, I: Instance> MessageDispatch for Module { let dispatch_result = message.call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); frame_support::debug::trace!( - "Message {:?}/{:?} has been dispatched. Result: {:?}", + "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", bridge, id, + actual_call_weight, + message.weight, dispatch_result, ); @@ -233,8 +235,6 @@ impl, I: Instance> MessageDispatch for Module { id, dispatch_result.map(drop).map_err(|e| e.error), )); - - actual_call_weight + DEPOSIT_EVENT_WEIGHT } } diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 71bb86f689f08..d9a2c3c46bfab 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -7,7 +7,9 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } # Substrate Based Dependencies @@ -48,9 +50,11 @@ git = "https://github.com/paritytech/substrate/" [features] default = ["std"] std = [ + "bp-message-dispatch/std", "bp-message-lane/std", + "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", - "sp-std/std" + "sp-std/std", ] diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index 799de23dab9d7..ff3ab1507ad8a 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -39,7 +39,7 @@ pub type MessagesProof = Bytes; /// Trie-based storage proof that the message(s) with given key(s) have been received by the bridged chain. /// SCALE-encoded trie nodes array `Vec>`. -pub type MessagesReceivingProof = Bytes; +pub type MessagesDeliveryProof = Bytes; /// Runtime adapter. pub trait Runtime: Send + Sync + 'static { @@ -63,14 +63,14 @@ pub trait MessageLaneApi { block: Option, ) -> FutureResult; - /// Returns proof-of-message(s) receiving. - #[rpc(name = "messageLane_proveMessagesReceiving")] - fn prove_messages_receiving( + /// Returns proof-of-message(s) delivery. + #[rpc(name = "messageLane_proveMessagesDelivery")] + fn prove_messages_delivery( &self, instance: InstanceId, lane: LaneId, block: Option, - ) -> FutureResult; + ) -> FutureResult; } /// Implements the MessageLaneApi trait for interacting with message lanes. @@ -119,12 +119,12 @@ where ) } - fn prove_messages_receiving( + fn prove_messages_delivery( &self, instance: InstanceId, lane: LaneId, block: Option, - ) -> FutureResult { + ) -> FutureResult { Box::new( prove_keys_read( self.backend.clone(), diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index f8bf478ecb29a..9fedf043194da 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -16,12 +16,16 @@ //! Everything about incoming messages receival. -use bp_message_lane::{InboundLaneData, LaneId, Message, MessageKey, MessageNonce, OnMessageReceived}; +use bp_message_lane::{ + target_chain::MessageDispatch, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, +}; /// Inbound lane storage. pub trait InboundLaneStorage { /// Message payload. type Payload; + /// Delivery and dispatch fee type on source chain. + type MessageFee; /// Lane id. fn id(&self) -> LaneId; @@ -43,10 +47,10 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message>( + pub fn receive_message>( &mut self, nonce: MessageNonce, - payload: S::Payload, + message_data: MessageData, ) -> bool { let mut data = self.storage.data(); let is_correct_message = nonce == data.latest_received_nonce + 1; @@ -57,12 +61,12 @@ impl InboundLane { data.latest_received_nonce = nonce; self.storage.set_data(data); - P::on_message_received(Message { + P::dispatch(Message { key: MessageKey { lane_id: self.storage.id(), nonce, }, - payload, + data: message_data, }); true @@ -74,14 +78,14 @@ mod tests { use super::*; use crate::{ inbound_lane, - mock::{run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, + mock::{message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, }; #[test] fn fails_to_receive_message_with_incorrect_nonce() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(!lane.receive_message::<()>(10, REGULAR_PAYLOAD)); + assert!(!lane.receive_message::(10, message_data(REGULAR_PAYLOAD))); assert_eq!(lane.storage.data().latest_received_nonce, 0); }); } @@ -90,7 +94,7 @@ mod tests { fn correct_message_is_processed_instantly() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message::<()>(1, REGULAR_PAYLOAD)); + assert!(lane.receive_message::(1, message_data(REGULAR_PAYLOAD))); assert_eq!(lane.storage.data().latest_received_nonce, 1); }); } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index f8c9b9d4f8e72..5f99eee756b63 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -21,12 +21,11 @@ //! 3) the messages are stored in the storage; //! 4) external component (relay) delivers messages to bridged chain; //! 5) messages are processed in order (ordered by assigned nonce); -//! 6) relay may send proof-of-receiving and proof-of-processing back to this chain. +//! 6) relay may send proof-of-delivery back to this chain. //! //! Once message is sent, its progress can be tracked by looking at module events. //! The assigned nonce is reported using `MessageAccepted` event. When message is -//! accepted by the bridged chain, `MessagesDelivered` is fired. When message is -//! processedby the bridged chain, `MessagesProcessed` by the bridged chain. +//! delivered to the the bridged chain, it is reported using `MessagesDelivered` event. #![cfg_attr(not(feature = "std"), no_std)] @@ -34,9 +33,14 @@ use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use bp_message_lane::{ - InboundLaneData, LaneId, Message, MessageKey, MessageNonce, OnMessageReceived, OutboundLaneData, + source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, + target_chain::{MessageDispatch, SourceHeaderChain}, + InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, +}; +use frame_support::{ + decl_error, decl_event, decl_module, decl_storage, sp_runtime::DispatchResult, traits::Get, weights::Weight, + Parameter, StorageMap, }; -use frame_support::{decl_event, decl_module, decl_storage, traits::Get, Parameter, StorageMap}; use frame_system::ensure_signed; use sp_std::{marker::PhantomData, prelude::*}; @@ -46,8 +50,14 @@ mod outbound_lane; #[cfg(test)] mod mock; +// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) +/// Upper bound of delivery transaction weight. +const DELIVERY_BASE_WEIGHT: Weight = 0; + /// The module configuration trait pub trait Trait: frame_system::Trait { + // General types + /// They overarching event type. type Event: From> + Into<::Event>; /// Message payload. @@ -57,8 +67,50 @@ pub trait Trait: frame_system::Trait { /// confirmed. The reason is that if you want to use lane, you should be ready to pay /// for it. type MaxMessagesToPruneAtOnce: Get; - /// Called when message has been received. - type OnMessageReceived: OnMessageReceived; + + // Types that are used by outbound_lane (on source chain). + + /// Type of delivery_and_dispatch_fee on source chain. + type MessageFee: Parameter; + /// Target header chain. + type TargetHeaderChain: TargetHeaderChain; + /// Message payload verifier. + type LaneMessageVerifier: LaneMessageVerifier; + /// Message delivery payment. + type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment; + + // Types that are used by inbound_lane (on target chain). + + /// Source header chain, as it is represented on target chain. + type SourceHeaderChain: SourceHeaderChain; + /// Message dispatch. + type MessageDispatch: MessageDispatch; +} + +/// Shortcut to messages proof type for Trait. +type MessagesProofOf = <>::SourceHeaderChain as SourceHeaderChain< + >::Payload, + >::MessageFee, +>>::MessagesProof; +/// Shortcut to messages delivery proof type for Trait. +type MessagesDeliveryProofOf = + <>::TargetHeaderChain as TargetHeaderChain<>::Payload>>::MessagesDeliveryProof; + +decl_error! { + pub enum Error for Module, I: Instance> { + /// Message has been treated as invalid by chain verifier. + MessageRejectedByChainVerifier, + /// Message has been treated as invalid by lane verifier. + MessageRejectedByLaneVerifier, + /// Submitter has failed to pay fee for delivering and dispatching messages. + FailedToWithdrawMessageFee, + /// Invalid messages has been submitted. + InvalidMessagesProof, + /// Invalid messages dispatch weight has been declared by the relayer. + InvalidMessagesDispatchWeight, + /// Invalid messages delivery proof has been submitted. + InvalidMessagesDeliveryProof, + } } decl_storage! { @@ -68,7 +120,7 @@ decl_storage! { /// Map of lane id => outbound lane data. OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; /// All queued outbound messages. - OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option; + OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; } } @@ -96,59 +148,160 @@ decl_module! { origin, lane_id: LaneId, payload: T::Payload, - ) { - let _ = ensure_signed(origin)?; + delivery_and_dispatch_fee: T::MessageFee, + ) -> DispatchResult { + let submitter = ensure_signed(origin)?; + + // let's first check if message can be delivered to target chain + T::TargetHeaderChain::verify_message(&payload).map_err(|err| { + frame_support::debug::trace!( + target: "runtime", + "Message to lane {:?} is rejected by target chain: {:?}", + lane_id, + err, + ); + + Error::::MessageRejectedByChainVerifier + })?; + + // now let's enforce any additional lane rules + T::LaneMessageVerifier::verify_message( + &submitter, + &delivery_and_dispatch_fee, + &lane_id, + &payload, + ).map_err(|err| { + frame_support::debug::trace!( + target: "runtime", + "Message to lane {:?} is rejected by lane verifier: {:?}", + lane_id, + err, + ); + + Error::::MessageRejectedByLaneVerifier + })?; + + // let's withdraw delivery and dispatch fee from submitter + T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( + &submitter, + &delivery_and_dispatch_fee, + ).map_err(|err| { + frame_support::debug::trace!( + target: "runtime", + "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", + lane_id, + submitter, + delivery_and_dispatch_fee, + err, + ); + + Error::::FailedToWithdrawMessageFee + })?; + + // finally, save message in outbound storage and emit event let mut lane = outbound_lane::(lane_id); - let nonce = lane.send_message(payload); + let nonce = lane.send_message(MessageData { + payload, + fee: delivery_and_dispatch_fee, + }); lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); + frame_support::debug::trace!( + target: "runtime", + "Accepted message {} to lane {:?}", + nonce, + lane_id, + ); + Self::deposit_event(RawEvent::MessageAccepted(lane_id, nonce)); + + Ok(()) } - } -} -impl, I: Instance> Module { - // ========================================================================================= - // === Exposed mutables ==================================================================== - // ========================================================================================= - - /// Receive new TRUSTED lane messages. - /// - /// Trusted here means that the function itself doesn't check whether message has actually - /// been sent through the other end of the channel. We only check that we are receiving - /// and processing messages in order here. - /// - /// Messages vector is required to be sorted by nonce within each lane. Otherise messages - /// will be rejected. - pub fn receive_messages(messages: Vec>) -> MessageNonce { - let mut correct_messages = 0; - for message in messages { - let mut lane = inbound_lane::(message.key.lane_id); - if lane.receive_message::(message.key.nonce, message.payload) { - correct_messages += 1; + /// Receive messages proof from bridged chain. + #[weight = DELIVERY_BASE_WEIGHT + dispatch_weight] + pub fn receive_messages_proof( + origin, + proof: MessagesProofOf, + dispatch_weight: Weight, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + + // verify messages proof && convert proof into messages + let messages = T::SourceHeaderChain::verify_messages_proof(proof).map_err(|err| { + frame_support::debug::trace!( + target: "runtime", + "Rejecting invalid messages proof: {:?}", + err, + ); + + Error::::InvalidMessagesProof + })?; + + // verify that relayer is paying actual dispatch weight + let actual_dispatch_weight: Weight = messages + .iter() + .map(T::MessageDispatch::dispatch_weight) + .sum(); + if dispatch_weight < actual_dispatch_weight { + frame_support::debug::trace!( + target: "runtime", + "Rejecting messages proof because of dispatch weight mismatch: declared={}, expected={}", + dispatch_weight, + actual_dispatch_weight, + ); + + return Err(Error::::InvalidMessagesDispatchWeight.into()); + } + + // dispatch messages + let total_messages = messages.len(); + let mut valid_messages = 0; + for message in messages { + let mut lane = inbound_lane::(message.key.lane_id); + if lane.receive_message::(message.key.nonce, message.data) { + valid_messages += 1; + } } + + frame_support::debug::trace!( + target: "runtime", + "Received messages: total={}, valid={}", + total_messages, + valid_messages, + ); + + Ok(()) } - correct_messages - } - - /// Receive TRUSTED proof of message receival. - /// - /// Trusted here means that the function itself doesn't check whether the bridged chain has - /// actually received these messages. - /// - /// The caller may break the channel by providing `latest_received_nonce` that is larger - /// than actual one. Not-yet-sent messages may be pruned in this case. - pub fn confirm_receival(lane_id: &LaneId, latest_received_nonce: MessageNonce) { - let mut lane = outbound_lane::(*lane_id); - let received_range = lane.confirm_receival(latest_received_nonce); - - if let Some(received_range) = received_range { - Self::deposit_event(RawEvent::MessagesDelivered( - *lane_id, - received_range.0, - received_range.1, - )); + /// Receive messages delivery proof from bridged chain. + #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + pub fn receive_messages_delivery_proof(origin, proof: MessagesDeliveryProofOf) -> DispatchResult { + let _ = ensure_signed(origin)?; + let (lane_id, nonce) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { + frame_support::debug::trace!( + target: "runtime", + "Rejecting invalid messages delivery proof: {:?}", + err, + ); + + Error::::InvalidMessagesDeliveryProof + })?; + + let mut lane = outbound_lane::(lane_id); + let received_range = lane.confirm_delivery(nonce); + if let Some(received_range) = received_range { + Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); + } + + frame_support::debug::trace!( + target: "runtime", + "Received messages delivery proof up to (and including) {} at lane {:?}", + nonce, + lane_id, + ); + + Ok(()) } } } @@ -177,6 +330,7 @@ struct RuntimeInboundLaneStorage { impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { type Payload = T::Payload; + type MessageFee = T::MessageFee; fn id(&self) -> LaneId { self.lane_id @@ -199,6 +353,7 @@ struct RuntimeOutboundLaneStorage { impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorage { type Payload = T::Payload; + type MessageFee = T::MessageFee; fn id(&self) -> LaneId { self.lane_id @@ -213,20 +368,20 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorag } #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option { + fn message(&self, nonce: &MessageNonce) -> Option> { OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce, }) } - fn save_message(&mut self, nonce: MessageNonce, payload: T::Payload) { + fn save_message(&mut self, nonce: MessageNonce, mesage_data: MessageData) { OutboundMessages::::insert( MessageKey { lane_id: self.lane_id, nonce, }, - payload, + mesage_data, ); } @@ -237,3 +392,190 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorag }); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{ + run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestRuntime, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, + }; + use bp_message_lane::Message; + use frame_support::{assert_noop, assert_ok}; + use frame_system::{EventRecord, Module as System, Phase}; + + fn send_regular_message() { + System::::set_block_number(1); + System::::reset_events(); + + assert_ok!(Module::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + REGULAR_PAYLOAD.1, + )); + + // check event with assigned nonce + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::message_lane(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), + topics: vec![], + }], + ); + + // check that fee has been withdrawn from submitter + assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, REGULAR_PAYLOAD.1)); + } + + fn receive_messages_delivery_proof() { + System::::set_block_number(1); + System::::reset_events(); + + assert_ok!(Module::::receive_messages_delivery_proof( + Origin::signed(1), + Ok((TEST_LANE_ID, 1)), + )); + + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::message_lane(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), + topics: vec![], + }], + ); + } + + #[test] + fn send_message_works() { + run_test(|| { + send_regular_message(); + }); + } + + #[test] + fn chain_verifier_rejects_invalid_message_in_send_message() { + run_test(|| { + // messages with this payload are rejected by target chain verifier + assert_noop!( + Module::::send_message( + Origin::signed(1), + TEST_LANE_ID, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, + PAYLOAD_REJECTED_BY_TARGET_CHAIN.1 + ), + Error::::MessageRejectedByChainVerifier, + ); + }); + } + + #[test] + fn lane_verifier_rejects_invalid_message_in_send_message() { + run_test(|| { + // messages with zero fee are rejected by lane verifier + assert_noop!( + Module::::send_message(Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 0), + Error::::MessageRejectedByLaneVerifier, + ); + }); + } + + #[test] + fn message_send_fails_if_submitter_cant_pay_message_fee() { + run_test(|| { + TestMessageDeliveryAndDispatchPayment::reject_payments(); + assert_noop!( + Module::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + REGULAR_PAYLOAD.1 + ), + Error::::FailedToWithdrawMessageFee, + ); + }); + } + + #[test] + fn receive_messages_proof_works() { + run_test(|| { + assert_ok!(Module::::receive_messages_proof( + Origin::signed(1), + Ok(vec![Message { + key: MessageKey { + lane_id: TEST_LANE_ID, + nonce: 1, + }, + data: MessageData { + payload: REGULAR_PAYLOAD, + fee: 0, + }, + }]), + REGULAR_PAYLOAD.1, + )); + + assert_eq!( + InboundLanes::::get(TEST_LANE_ID).latest_received_nonce, + 1 + ); + }); + } + + #[test] + fn receive_messages_proof_rejects_invalid_dispatch_weight() { + run_test(|| { + assert_noop!( + Module::::receive_messages_proof( + Origin::signed(1), + Ok(vec![Message { + key: MessageKey { + lane_id: TEST_LANE_ID, + nonce: 1, + }, + data: MessageData { + payload: REGULAR_PAYLOAD, + fee: 0, + }, + }]), + REGULAR_PAYLOAD.1 - 1, + ), + Error::::InvalidMessagesDispatchWeight, + ); + }); + } + + #[test] + fn receive_messages_proof_rejects_invalid_proof() { + run_test(|| { + assert_noop!( + Module::::receive_messages_proof(Origin::signed(1), Err(()), 0), + Error::::InvalidMessagesProof, + ); + }); + } + + #[test] + fn receive_messages_delivery_proof_works() { + run_test(|| { + send_regular_message(); + receive_messages_delivery_proof(); + + assert_eq!( + OutboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, + 1, + ); + }); + } + + #[test] + fn receive_messages_delivery_proof_rejects_invalid_proof() { + run_test(|| { + assert_noop!( + Module::::receive_messages_delivery_proof(Origin::signed(1), Err(()),), + Error::::InvalidMessagesDeliveryProof, + ); + }); + } +} diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index c0d27e389aa3b..a682d6705b55b 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -14,7 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bp_message_lane::LaneId; +use crate::Trait; + +use bp_message_lane::{ + source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, + target_chain::{MessageDispatch, SourceHeaderChain}, + LaneId, Message, MessageData, MessageNonce, +}; use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; use sp_core::H256; use sp_runtime::{ @@ -23,10 +29,9 @@ use sp_runtime::{ Perbill, }; -use crate::Trait; - pub type AccountId = u64; -pub type TestPayload = u64; +pub type TestPayload = (u64, Weight); +pub type TestMessageFee = u64; #[derive(Clone, Eq, PartialEq, Debug)] pub struct TestRuntime; @@ -69,7 +74,7 @@ impl frame_system::Trait for TestRuntime { type DbWeight = (); type BlockExecutionWeight = (); type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); @@ -89,16 +94,140 @@ impl Trait for TestRuntime { type Event = TestEvent; type Payload = TestPayload; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; - type OnMessageReceived = (); + + type MessageFee = TestMessageFee; + type TargetHeaderChain = TestTargetHeaderChain; + type LaneMessageVerifier = TestLaneMessageVerifier; + type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; + + type SourceHeaderChain = TestSourceHeaderChain; + type MessageDispatch = TestMessageDispatch; } +/// Error that is returned by all test implementations. +pub const TEST_ERROR: &str = "Test error"; + /// Lane that we're using in tests. pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; /// Regular message payload. -pub const REGULAR_PAYLOAD: TestPayload = 0; +pub const REGULAR_PAYLOAD: TestPayload = (0, 50); + +/// Payload that is rejected by `TestTargetHeaderChain`. +pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = (1, 50); + +/// Target header chain that is used in tests. +#[derive(Debug, Default)] +pub struct TestTargetHeaderChain; + +impl TargetHeaderChain for TestTargetHeaderChain { + type Error = &'static str; + + type MessagesDeliveryProof = Result<(LaneId, MessageNonce), ()>; + + fn verify_message(payload: &TestPayload) -> Result<(), Self::Error> { + if *payload == PAYLOAD_REJECTED_BY_TARGET_CHAIN { + Err(TEST_ERROR) + } else { + Ok(()) + } + } + + fn verify_messages_delivery_proof( + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, MessageNonce), Self::Error> { + proof.map_err(|_| TEST_ERROR) + } +} + +/// Lane message verifier that is used in tests. +#[derive(Debug, Default)] +pub struct TestLaneMessageVerifier; + +impl LaneMessageVerifier for TestLaneMessageVerifier { + type Error = &'static str; + + fn verify_message( + _submitter: &AccountId, + delivery_and_dispatch_fee: &TestMessageFee, + _lane: &LaneId, + _payload: &TestPayload, + ) -> Result<(), Self::Error> { + if *delivery_and_dispatch_fee != 0 { + Ok(()) + } else { + Err(TEST_ERROR) + } + } +} + +/// Message fee payment system that is used in tests. +#[derive(Debug, Default)] +pub struct TestMessageDeliveryAndDispatchPayment; + +impl TestMessageDeliveryAndDispatchPayment { + /// Reject all payments. + pub fn reject_payments() { + frame_support::storage::unhashed::put(b":reject-message-fee:", &true); + } + + /// Returns true if given fee has been paid by given relayer. + pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { + frame_support::storage::unhashed::get(b":message-fee:") == Some((submitter, fee)) + } +} + +impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { + type Error = &'static str; + + fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &TestMessageFee) -> Result<(), Self::Error> { + if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) { + return Err(TEST_ERROR); + } + + frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee)); + Ok(()) + } +} + +/// Source header chain that is used in tests. +#[derive(Debug)] +pub struct TestSourceHeaderChain; + +impl SourceHeaderChain for TestSourceHeaderChain { + type Error = &'static str; + + type MessagesProof = Result>, ()>; + + fn verify_messages_proof( + proof: Self::MessagesProof, + ) -> Result>, Self::Error> { + proof.map_err(|_| TEST_ERROR) + } +} + +/// Source header chain that is used in tests. +#[derive(Debug)] +pub struct TestMessageDispatch; + +impl MessageDispatch for TestMessageDispatch { + fn dispatch_weight(message: &Message) -> Weight { + message.data.payload.1 + } + + fn dispatch(_message: Message) {} +} + +/// Return message data with valid fee for given payload. +pub fn message_data(payload: TestPayload) -> MessageData { + MessageData { payload, fee: 1 } +} /// Run message lane test. pub fn run_test(test: impl FnOnce() -> T) -> T { - sp_io::TestExternalities::new(Default::default()).execute_with(test) + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(test) } diff --git a/modules/message-lane/src/outbound_lane.rs b/modules/message-lane/src/outbound_lane.rs index 52a1404ba7a76..8afcd0702869b 100644 --- a/modules/message-lane/src/outbound_lane.rs +++ b/modules/message-lane/src/outbound_lane.rs @@ -16,12 +16,14 @@ //! Everything about outgoing messages sending. -use bp_message_lane::{LaneId, MessageNonce, OutboundLaneData}; +use bp_message_lane::{LaneId, MessageData, MessageNonce, OutboundLaneData}; /// Outbound lane storage. pub trait OutboundLaneStorage { /// Message payload. type Payload; + /// Delivery and dispatch fee type on source chain. + type MessageFee; /// Lane id. fn id(&self) -> LaneId; @@ -31,9 +33,9 @@ pub trait OutboundLaneStorage { fn set_data(&mut self, data: OutboundLaneData); /// Returns saved outbound message payload. #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option; + fn message(&self, nonce: &MessageNonce) -> Option>; /// Save outbound message in the storage. - fn save_message(&mut self, nonce: MessageNonce, payload: Self::Payload); + fn save_message(&mut self, nonce: MessageNonce, message_data: MessageData); /// Remove outbound message from the storage. fn remove_message(&mut self, nonce: &MessageNonce); } @@ -52,22 +54,22 @@ impl OutboundLane { /// Send message over lane. /// /// Returns new message nonce. - pub fn send_message(&mut self, payload: S::Payload) -> MessageNonce { + pub fn send_message(&mut self, message_data: MessageData) -> MessageNonce { let mut data = self.storage.data(); let nonce = data.latest_generated_nonce + 1; data.latest_generated_nonce = nonce; - self.storage.save_message(nonce, payload); + self.storage.save_message(nonce, message_data); self.storage.set_data(data); nonce } - /// Confirm message receival. + /// Confirm messages delivery. /// /// Returns `None` if confirmation is wrong/duplicate. /// Returns `Some` with inclusive ranges of message nonces that have been received. - pub fn confirm_receival(&mut self, latest_received_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> { + pub fn confirm_delivery(&mut self, latest_received_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> { let mut data = self.storage.data(); if latest_received_nonce <= data.latest_received_nonce || latest_received_nonce > data.latest_generated_nonce { return None; @@ -107,7 +109,7 @@ impl OutboundLane { mod tests { use super::*; use crate::{ - mock::{run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, + mock::{message_data, run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, outbound_lane, }; @@ -116,57 +118,57 @@ mod tests { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); assert_eq!(lane.storage.data().latest_generated_nonce, 0); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 1); + assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 1); assert!(lane.storage.message(&1).is_some()); assert_eq!(lane.storage.data().latest_generated_nonce, 1); }); } #[test] - fn confirm_receival_works() { + fn confirm_delivery_works() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 1); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 2); - assert_eq!(lane.send_message(REGULAR_PAYLOAD), 3); + assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 1); + assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 2); + assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 3); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); - assert_eq!(lane.confirm_receival(3), Some((1, 3))); + assert_eq!(lane.confirm_delivery(3), Some((1, 3))); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); }); } #[test] - fn confirm_receival_rejects_nonce_lesser_than_latest_received() { + fn confirm_delivery_rejects_nonce_lesser_than_latest_received() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); - assert_eq!(lane.confirm_receival(3), Some((1, 3))); - assert_eq!(lane.confirm_receival(3), None); + assert_eq!(lane.confirm_delivery(3), Some((1, 3))); + assert_eq!(lane.confirm_delivery(3), None); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); - assert_eq!(lane.confirm_receival(2), None); + assert_eq!(lane.confirm_delivery(2), None); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); }); } #[test] - fn confirm_receival_rejects_nonce_larger_than_last_generated() { + fn confirm_delivery_rejects_nonce_larger_than_last_generated() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); - assert_eq!(lane.confirm_receival(10), None); + assert_eq!(lane.confirm_delivery(10), None); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); }); @@ -180,17 +182,17 @@ mod tests { assert_eq!(lane.prune_messages(100), 0); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // when nothing is confirmed, nothing is pruned - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); - lane.send_message(REGULAR_PAYLOAD); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); assert_eq!(lane.prune_messages(100), 0); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // after confirmation, some messages are received - assert_eq!(lane.confirm_receival(2), Some((1, 2))); + assert_eq!(lane.confirm_delivery(2), Some((1, 2))); assert_eq!(lane.prune_messages(100), 2); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3); // after last message is confirmed, everything is pruned - assert_eq!(lane.confirm_receival(3), Some((3, 3))); + assert_eq!(lane.confirm_delivery(3), Some((3, 3))); assert_eq!(lane.prune_messages(100), 1); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4); }); diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 04b40e597268f..1877df90bcb37 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -29,6 +29,12 @@ pub trait MessageDispatch { /// A type of the message to be dispatched. type Message: codec::Decode; + /// Estimate dispatch weight. + /// + /// This function must: (1) be instant and (2) return correct upper bound + /// of dispatch weight. + fn dispatch_weight(message: &Self::Message) -> Weight; + /// Dispatches the message internally. /// /// `bridge` indicates instance of deployed bridge where the message came from. @@ -36,5 +42,5 @@ pub trait MessageDispatch { /// `id` is a short unique if of the message. /// /// Returns post-dispatch (actual) message weight. - fn dispatch(bridge: InstanceId, id: MessageId, message: Self::Message) -> Weight; + fn dispatch(bridge: InstanceId, id: MessageId, message: Self::Message); } diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index b937e452ac72f..538a5d6fb72ac 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -11,15 +11,29 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies +[dependencies.frame-support] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate.git" + [dependencies.sp-api] version = "2.0.0-rc6" tag = 'v2.0.0-rc6' default-features = false git = "https://github.com/paritytech/substrate.git" +[dependencies.sp-std] +version = "2.0.0-rc6" +tag = 'v2.0.0-rc6' +default-features = false +git = "https://github.com/paritytech/substrate.git" + [features] default = ["std"] std = [ "codec/std", - "sp-api/std" + "frame-support/std", + "sp-api/std", + "sp-std/std" ] diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index a4bfac459b8b9..a2e3e41cfd40c 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Primitives for sending and receiving Substrate <-> Substrate messages. +//! Primitives of message lane module. #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions @@ -23,7 +23,12 @@ #![allow(clippy::unnecessary_mut_passed)] use codec::{Decode, Encode}; +use frame_support::RuntimeDebug; use sp_api::decl_runtime_apis; +use sp_std::prelude::*; + +pub mod source_chain; +pub mod target_chain; /// Lane identifier. pub type LaneId = [u8; 4]; @@ -31,8 +36,11 @@ pub type LaneId = [u8; 4]; /// Message nonce. Valid messages will never have 0 nonce. pub type MessageNonce = u64; +/// Message id as a tuple. +pub type MessageId = (LaneId, MessageNonce); + /// Message key (unique message identifier) as it is stored in the storage. -#[derive(Encode, Decode, Clone)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct MessageKey { /// ID of the message lane. pub lane_id: LaneId, @@ -40,37 +48,33 @@ pub struct MessageKey { pub nonce: MessageNonce, } -/// Message as it is stored in the storage. -#[derive(Encode, Decode, Clone)] -pub struct Message { - /// Message key. - pub key: MessageKey, +/// Message data as it is stored in the storage. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct MessageData { /// Message payload. pub payload: Payload, + /// Message delivery and dispatch fee, paid by the submitter. + pub fee: Fee, } -/// Called when inbound message is received. -pub trait OnMessageReceived { - /// Called when inbound message is received. - /// - /// It is up to the implementers of this trait to determine whether the message - /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. - fn on_message_received(message: Message); -} - -impl OnMessageReceived for () { - fn on_message_received(_message: Message) {} +/// Message as it is stored in the storage. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +pub struct Message { + /// Message key. + pub key: MessageKey, + /// Message data. + pub data: MessageData, } /// Inbound lane data. -#[derive(Default, Encode, Decode, Clone)] +#[derive(Default, Encode, Decode, Clone, RuntimeDebug, PartialEq)] pub struct InboundLaneData { /// Nonce of latest message that we have received from bridged chain. pub latest_received_nonce: MessageNonce, } /// Outbound lane data. -#[derive(Encode, Decode, Clone)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq)] pub struct OutboundLaneData { /// Nonce of oldest message that we haven't yet pruned. May point to not-yet-generated message if /// all sent messages are already pruned. diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs new file mode 100644 index 0000000000000..cce5e0d5bfbce --- /dev/null +++ b/primitives/message-lane/src/source_chain.rs @@ -0,0 +1,97 @@ +// Copyright 2019-2020 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 . + +//! Primitives of message lane module, that are used on the source chain. + +use crate::{LaneId, MessageNonce}; + +use frame_support::Parameter; +use sp_std::fmt::Debug; + +/// Target chain API. Used by source chain to verify target chain proofs. +/// +/// All implementations of this trait should only work with finalized data that +/// can't change. Wrong implementation may lead to invalid lane states (i.e. lane +/// that's stuck) and/or processing messages without paying fees. +pub trait TargetHeaderChain { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Proof that messages have been received by target chain. + type MessagesDeliveryProof: Parameter; + + /// Verify message payload before we accept it. + /// + /// **CAUTION**: this is very important function. Incorrect implementation may lead + /// to stuck lanes and/or relayers loses. + /// + /// The proper implementation must ensure that the delivery-transaction with this + /// payload would (at least) be accepted into target chain transaction pool AND + /// eventually will be successfully 'mined'. The most obvious incorrect implementation + /// example would be implementation for BTC chain that accepts payloads larger than + /// 1MB. BTC nodes aren't accepting transactions that are larger than 1MB, so relayer + /// will be unable to craft valid transaction => this (and all subsequent) messages will + /// never be delivered. + fn verify_message(payload: &Payload) -> Result<(), Self::Error>; + + /// Verify messages delivery proof and return lane && nonce of the latest recevied message. + fn verify_messages_delivery_proof( + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, MessageNonce), Self::Error>; +} + +/// Lane message verifier. +/// +/// Runtime developer may implement any additional validation logic over message-lane mechanism. +/// E.g. if lanes should have some security (e.g. you can only accept Lane1 messages from +/// Submitter1, Lane2 messages for those who has submitted first message to this lane, disable +/// Lane3 until some block, ...), then it may be built using this verifier. +/// +/// Any fee requirements should also be enforced here. +pub trait LaneMessageVerifier { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the lane. + fn verify_message( + submitter: &Submitter, + delivery_and_dispatch_fee: &Fee, + lane: &LaneId, + payload: &Payload, + ) -> Result<(), Self::Error>; +} + +/// Message delivery payment. It is called as a part of submit-message transaction. Transaction +/// submitter is paying (in source chain tokens/assets) for: +/// +/// 1) submit-message-transaction-fee itself. This fee is not included in the +/// `delivery_and_dispatch_fee` and is witheld by the regular transaction payment mechanism; +/// 2) message-delivery-transaction-fee. It is submitted to the target node by relayer; +/// 3) message-dispatch fee. It is paid by relayer for processing message by target chain; +/// 4) message-receiving-delivery-transaction-fee. It is submitted to the source node +/// by relayer. +/// +/// So to be sure that any non-altruist relayer would agree to deliver message, submitter +/// should set `delivery_and_dispatch_fee` to at least (equialent of): sum of fees from (2) +/// to (4) above, plus some interest for the relayer. +pub trait MessageDeliveryAndDispatchPayment { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Withhold/write-off delivery_and_dispatch_fee from submitter account to + /// some relayers-fund account. + fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &Balance) -> Result<(), Self::Error>; +} diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs new file mode 100644 index 0000000000000..7287b26ae5713 --- /dev/null +++ b/primitives/message-lane/src/target_chain.rs @@ -0,0 +1,56 @@ +// Copyright 2019-2020 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 . + +//! Primitives of message lane module, that are used on the target chain. + +use crate::Message; + +use frame_support::{weights::Weight, Parameter}; +use sp_std::{fmt::Debug, prelude::*}; + +/// Source chain API. Used by target chain, to verify source chain proofs. +/// +/// All implementations of this trait should only work with finalized data that +/// can't change. Wrong implementation may lead to invalid lane states (i.e. lane +/// that's stuck) and/or processing messages without paying fees. +pub trait SourceHeaderChain { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Proof that messages are sent from source chain. + type MessagesProof: Parameter; + + /// Verify messages proof and return proved messages. + /// + /// Messages vector is required to be sorted by nonce within each lane. Out-of-order + /// messages will be rejected. + fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error>; +} + +/// Called when inbound message is received. +pub trait MessageDispatch { + /// Estimate dispatch weight. + /// + /// This function must: (1) be instant and (2) return correct upper bound + /// of dispatch weight. + fn dispatch_weight(message: &Message) -> Weight; + + /// Called when inbound message is received. + /// + /// It is up to the implementers of this trait to determine whether the message + /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. + fn dispatch(message: Message); +} diff --git a/relays/messages-relay/src/message_lane.rs b/relays/messages-relay/src/message_lane.rs index 8671451394eb1..9db30926a0ede 100644 --- a/relays/messages-relay/src/message_lane.rs +++ b/relays/messages-relay/src/message_lane.rs @@ -17,7 +17,7 @@ //! One-way message lane types. Within single one-way lane we have three 'races' where we try to: //! //! 1) relay new messages from source to target node; -//! 2) relay proof-of-receiving from target to source node. +//! 2) relay proof-of-delivery from target to source node. use relay_utils::HeaderId; From 0b911d43b5ddbe788f2b76b2d00b8ba656956a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 28 Sep 2020 20:23:08 +0200 Subject: [PATCH 0165/1210] Bump Substrate to v2.0.0 (#382) * Change script to update versions. * Bump versions. * Address remainders. * cargo fmt --all * Fix tests. * Whitelist BlueOak license * Fix benchmarks? --- bin/millau-runtime/Cargo.toml | 106 +++++++++---------- bin/millau-runtime/src/lib.rs | 20 ++-- bin/node/Cargo.toml | 94 ++++++++-------- bin/node/src/cli.rs | 34 +++++- bin/node/src/command.rs | 63 ++++++++++- bin/rialto-runtime/Cargo.toml | 106 +++++++++---------- bin/rialto-runtime/src/lib.rs | 33 +++--- modules/call-dispatch/Cargo.toml | 24 ++--- modules/call-dispatch/src/lib.rs | 2 +- modules/currency-exchange/Cargo.toml | 28 ++--- modules/currency-exchange/src/lib.rs | 2 +- modules/ethereum-contract/builtin/Cargo.toml | 20 ++-- modules/ethereum/Cargo.toml | 24 ++--- modules/ethereum/src/mock.rs | 2 +- modules/message-lane/Cargo.toml | 24 ++--- modules/message-lane/rpc/Cargo.toml | 34 +++--- modules/message-lane/src/mock.rs | 2 +- modules/shift-session-manager/Cargo.toml | 28 ++--- modules/shift-session-manager/src/lib.rs | 2 +- modules/substrate/Cargo.toml | 40 +++---- modules/substrate/src/mock.rs | 2 +- primitives/currency-exchange/Cargo.toml | 12 +-- primitives/ethereum-poa/Cargo.toml | 16 +-- primitives/message-lane/Cargo.toml | 12 +-- primitives/runtime/Cargo.toml | 4 +- primitives/substrate/Cargo.toml | 8 +- relays/ethereum/Cargo.toml | 28 ++--- relays/utils/Cargo.toml | 2 +- 28 files changed, 428 insertions(+), 344 deletions(-) diff --git a/bin/millau-runtime/Cargo.toml b/bin/millau-runtime/Cargo.toml index a6b2cb3f1d326..e766a58d790fd 100644 --- a/bin/millau-runtime/Cargo.toml +++ b/bin/millau-runtime/Cargo.toml @@ -23,14 +23,14 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" @@ -45,26 +45,26 @@ default-features = false path = "../../modules/message-lane" [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-sudo] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" @@ -74,124 +74,124 @@ default-features = false path = "../../modules/shift-session-manager" [dependencies.pallet-session] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-consensus-aura] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" @@ -209,7 +209,7 @@ path = "../../primitives/message-lane" [build-dependencies.wasm-builder-runner] version = "1.0.5" -tag = 'v2.0.0-rc6' +tag = 'v2.0.0' package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" diff --git a/bin/millau-runtime/src/lib.rs b/bin/millau-runtime/src/lib.rs index 93ae91ea9c04c..394cb0d1c82b0 100644 --- a/bin/millau-runtime/src/lib.rs +++ b/bin/millau-runtime/src/lib.rs @@ -200,16 +200,15 @@ impl frame_system::Trait for Runtime { type AvailableBlockRatio = AvailableBlockRatio; /// Version of the runtime. type Version = Version; - /// Converts a module to the index of the module in `construct_runtime!`. - /// - /// This type is being generated by `construct_runtime!`. - type ModuleToIndex = ModuleToIndex; + /// Provides information about the pallet setup in the runtime. + type PalletInfo = PalletInfo; /// What to do if a new account is created. type OnNewAccount = (); /// What to do if an account is fully reaped from the system. type OnKilledAccount = (); /// The data to be stored in an account. type AccountData = pallet_balances::AccountData; + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); } @@ -230,15 +229,13 @@ impl pallet_bridge_call_dispatch::Trait for Runtime { impl pallet_grandpa::Trait for Runtime { type Event = Event; type Call = Call; - type KeyOwnerProofSystem = (); - type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type HandleEquivocation = (); + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + type WeightInfo = (); } parameter_types! { @@ -250,11 +247,15 @@ impl pallet_timestamp::Trait for Runtime { type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u128 = 500; + // For weight estimation, we assume that the most locks on an individual account will be 50. + // This number may need to be adjusted in the future if this assumption no longer holds true. + pub const MaxLocks: u32 = 50; } impl pallet_balances::Trait for Runtime { @@ -265,7 +266,9 @@ impl pallet_balances::Trait for Runtime { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); + type MaxLocks = MaxLocks; } parameter_types! { @@ -301,6 +304,7 @@ impl pallet_session::Trait for Runtime { type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = (); + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); } diff --git a/bin/node/Cargo.toml b/bin/node/Cargo.toml index 7f6015d639c9e..72770e0db7c32 100644 --- a/bin/node/Cargo.toml +++ b/bin/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] futures = "0.3.5" -jsonrpc-core = "14.2.0" +jsonrpc-core = "15.0.0" log = "0.4.11" pallet-message-lane-rpc = { version = "0.1.0", path = "../../modules/message-lane/rpc" } structopt = "0.3.17" @@ -30,110 +30,110 @@ default-features = false features = ["std"] [dependencies.sc-cli] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-rpc] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-executor] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-service] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-inherents] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-transaction-pool] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-transaction-pool] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-network] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus-aura] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus-aura] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-consensus] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-finality-grandpa] package = "sc-finality-grandpa" -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.grandpa-primitives] package = "sp-finality-grandpa" -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-consensus] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-client-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sc-basic-authorship] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-frame-rpc-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.frame-benchmarking-cli] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [build-dependencies] @@ -141,13 +141,13 @@ vergen = "3.1.0" [build-dependencies.build-script-utils] package = "substrate-build-script-utils" -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [build-dependencies.frame-benchmarking-cli] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [features] diff --git a/bin/node/src/cli.rs b/bin/node/src/cli.rs index a7399fa716dff..1149c4f910c8d 100644 --- a/bin/node/src/cli.rs +++ b/bin/node/src/cli.rs @@ -29,9 +29,37 @@ pub struct Cli { /// Possible subcommands of the main binary. #[derive(Debug, StructOpt)] pub enum Subcommand { - /// A set of base subcommands handled by `sc_cli`. - #[structopt(flatten)] - Base(sc_cli::Subcommand), + /// Key management cli utilities + Key(sc_cli::KeySubcommand), + /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. + Verify(sc_cli::VerifyCmd), + + /// Generate a seed that provides a vanity address. + Vanity(sc_cli::VanityCmd), + + /// Sign a message, with a given (secret) key. + Sign(sc_cli::SignCmd), + + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), + + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), + + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), + + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), + + /// Remove the whole chain. + PurgeChain(sc_cli::PurgeChainCmd), + + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), /// The custom benchmark subcommmand benchmarking runtime pallets. #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] diff --git a/bin/node/src/command.rs b/bin/node/src/command.rs index f216c3c42d1c7..7a7417c9a5f1d 100644 --- a/bin/node/src/command.rs +++ b/bin/node/src/command.rs @@ -100,17 +100,70 @@ pub fn run() -> sc_cli::Result<()> { Ok(()) } } - Some(Subcommand::Base(subcommand)) => { - let runner = cli.create_runner(subcommand)?; - runner.run_subcommand(subcommand, |config| { + Some(Subcommand::Key(cmd)) => cmd.run(), + Some(Subcommand::Sign(cmd)) => cmd.run(), + Some(Subcommand::Verify(cmd)) => cmd.run(), + Some(Subcommand::Vanity(cmd)) => cmd.run(), + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + } + Some(Subcommand::CheckBlock(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { let PartialComponents { client, - backend, task_manager, import_queue, .. } = new_partial(&config)?; - Ok((client, backend, import_queue, task_manager)) + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::ExportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, task_manager, .. + } = new_partial(&config)?; + Ok((cmd.run(client, config.database), task_manager)) + }) + } + Some(Subcommand::ExportState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, task_manager, .. + } = new_partial(&config)?; + Ok((cmd.run(client, config.chain_spec), task_manager)) + }) + } + Some(Subcommand::ImportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.database)) + } + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + backend, + .. + } = new_partial(&config)?; + Ok((cmd.run(client, backend), task_manager)) }) } None => { diff --git a/bin/rialto-runtime/Cargo.toml b/bin/rialto-runtime/Cargo.toml index 101477915342a..5ea4c9fc90238 100644 --- a/bin/rialto-runtime/Cargo.toml +++ b/bin/rialto-runtime/Cargo.toml @@ -29,14 +29,14 @@ features = ["derive"] # Substrate Dependencies [dependencies.pallet-aura] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-balances] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" @@ -61,20 +61,20 @@ default-features = false path = "../../modules/message-lane" [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-grandpa] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-randomness-collective-flip] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" @@ -84,130 +84,130 @@ default-features = false path = "../../modules/shift-session-manager" [dependencies.pallet-sudo] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system-rpc-runtime-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-timestamp] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-executive] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" # Substrate Primitives [dependencies.sp-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-block-builder] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-consensus-aura] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-inherents] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-offchain] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-session] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-transaction-pool] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-version] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" @@ -246,7 +246,7 @@ path = "../../primitives/ethereum-poa" [build-dependencies.wasm-builder-runner] version = "1.0.5" -tag = 'v2.0.0-rc6' +tag = 'v2.0.0' package = "substrate-wasm-builder-runner" git = "https://github.com/paritytech/substrate/" diff --git a/bin/rialto-runtime/src/lib.rs b/bin/rialto-runtime/src/lib.rs index 2ef00bf9e1603..6b207dbdb0951 100644 --- a/bin/rialto-runtime/src/lib.rs +++ b/bin/rialto-runtime/src/lib.rs @@ -209,16 +209,15 @@ impl frame_system::Trait for Runtime { type AvailableBlockRatio = AvailableBlockRatio; /// Version of the runtime. type Version = Version; - /// Converts a module to the index of the module in `construct_runtime!`. - /// - /// This type is being generated by `construct_runtime!`. - type ModuleToIndex = ModuleToIndex; + /// Provides information about the pallet setup in the runtime. + type PalletInfo = PalletInfo; /// What to do if a new account is created. type OnNewAccount = (); /// What to do if an account is fully reaped from the system. type OnKilledAccount = (); /// The data to be stored in an account. type AccountData = pallet_balances::AccountData; + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); } @@ -336,15 +335,13 @@ impl bp_currency_exchange::DepositInto for DepositInto { impl pallet_grandpa::Trait for Runtime { type Event = Event; type Call = Call; - type KeyOwnerProofSystem = (); - type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type HandleEquivocation = (); + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + type WeightInfo = (); } parameter_types! { @@ -356,11 +353,15 @@ impl pallet_timestamp::Trait for Runtime { type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); } parameter_types! { pub const ExistentialDeposit: u128 = 500; + // For weight estimation, we assume that the most locks on an individual account will be 50. + // This number may need to be adjusted in the future if this assumption no longer holds true. + pub const MaxLocks: u32 = 50; } impl pallet_balances::Trait for Runtime { @@ -371,7 +372,9 @@ impl pallet_balances::Trait for Runtime { type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); + type MaxLocks = MaxLocks; } parameter_types! { @@ -407,6 +410,7 @@ impl pallet_session::Trait for Runtime { type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = (); + // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); } @@ -642,16 +646,9 @@ impl_runtime_apis! { #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn dispatch_benchmark( - pallet: Vec, - benchmark: Vec, - lowest_range_values: Vec, - highest_range_values: Vec, - steps: Vec, - repeat: u32, - extra: bool, + config: frame_benchmarking::BenchmarkConfig, ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; - let mut batches = Vec::::new(); let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -664,7 +661,9 @@ impl_runtime_apis! { // Caller 0 Account hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), ]; - let params = (&pallet, &benchmark, &lowest_range_values, &highest_range_values, &steps, repeat, &whitelist, extra); + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); use pallet_bridge_currency_exchange::benchmarking::{ Module as BridgeCurrencyExchangeBench, diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index 838f0aa6a9b25..83e86ba0e0b67 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -13,38 +13,38 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 1524c0d223802..6adac937e5cd1 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -363,7 +363,7 @@ mod tests { type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); - type ModuleToIndex = (); + type PalletInfo = (); type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 09bb1c25cba9f..5e3c980447c96 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -14,44 +14,44 @@ serde = { version = "1.0", optional = true } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index aace287eb5834..036f3b564c10d 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -345,7 +345,7 @@ mod tests { type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); - type ModuleToIndex = (); + type PalletInfo = (); type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 3911c2cd10675..5ade9e6deb157 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -21,29 +21,29 @@ log = "0.4.11" rialto-runtime = { path = "../../../bin/rialto-runtime" } [dependencies.sp-blockchain] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sc-finality-grandpa] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies] hex = "0.4" [dev-dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index affabfe7976fa..7c66ad26f74c6 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -14,39 +14,39 @@ serde = { version = "1.0", optional = true } # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-benchmarking] optional = true -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index db84afacc4960..2c46c7c5407d9 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -64,7 +64,7 @@ impl frame_system::Trait for TestRuntime { type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); - type ModuleToIndex = (); + type PalletInfo = (); type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index d9a2c3c46bfab..c983b6cd99a55 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -15,36 +15,36 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [features] diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index 83c41604ad1ec..843cfe6e24fe3 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -11,46 +11,46 @@ bp-runtime = { path = "../../../primitives/runtime" } bp-message-lane = { path = "../../../primitives/message-lane" } derive_more = "0.99.2" futures = { version = "0.3.5", features = ["compat"] } -jsonrpc-core = "14.2.0" -jsonrpc-core-client = "14.2.0" -jsonrpc-derive = "14.2.1" +jsonrpc-core = "15.0.0" +jsonrpc-core-client = "15.0.0" +jsonrpc-derive = "15.0.0" # Substrate Based Dependencies [dependencies.sc-client-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-blockchain] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-state-machine] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies] async-std = "1.6.2" [dev-dependencies.substrate-test-runtime-client] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index a682d6705b55b..b8b71c5db19b4 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -78,7 +78,7 @@ impl frame_system::Trait for TestRuntime { type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); - type ModuleToIndex = (); + type PalletInfo = (); type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 706733e73fee3..7684157380b6c 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -12,44 +12,44 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.pallet-session] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-staking] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index d2ca15d215999..918c2513f41bc 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -132,7 +132,7 @@ mod tests { type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); - type ModuleToIndex = (); + type PalletInfo = (); type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 6fb935e548310..2d16493a360e5 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -23,62 +23,62 @@ features = ["derive"] # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-finality-grandpa] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dependencies.sp-trie] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" # Dev Dependencies [dev-dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-keyring] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" [dev-dependencies.sp-state-machine] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index 303f1ad61db5f..8cedca4ac4290 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -60,7 +60,7 @@ impl frame_system::Trait for TestRuntime { type AvailableBlockRatio = AvailableBlockRatio; type MaximumBlockLength = MaximumBlockLength; type Version = (); - type ModuleToIndex = (); + type PalletInfo = (); type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index a958f83c4372c..6f70280f16dc1 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -12,20 +12,20 @@ codec = { package = "parity-scale-codec", version = "1.3.4", default-features = # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 95b6fa2132190..6ff4c0481a3ca 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -23,26 +23,26 @@ plain_hasher = { version = "0.2.2", default-features = false } # Substrate Based Dependencies [dependencies.sp-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index 538a5d6fb72ac..c551a11627cbc 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -12,20 +12,20 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies [dependencies.frame-support] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-api] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-std] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index a0c8cb035cac2..249e49f151e9b 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -12,8 +12,8 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Based Dependencies [dependencies.sp-io] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/primitives/substrate/Cargo.toml b/primitives/substrate/Cargo.toml index c452b767a8ab1..3756bd7bf8048 100644 --- a/primitives/substrate/Cargo.toml +++ b/primitives/substrate/Cargo.toml @@ -11,14 +11,14 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" serde = { version = "1.0", optional = true } [dependencies.sp-finality-grandpa] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' default-features = false git = "https://github.com/paritytech/substrate/" diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index ab6872dabf206..08f1b147aae6f 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -40,38 +40,38 @@ features = ["http"] # Substrate Based Dependencies [dependencies.frame-system] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dependencies.pallet-transaction-payment] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.node-primitives] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-core] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-keyring] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.sp-runtime] -version = "2.0.0-rc6" -tag = 'v2.0.0-rc6' +version = "2.0.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.substrate-prometheus-endpoint] -version = "0.8.0-rc6" -tag = 'v2.0.0-rc6' +version = "0.8.0" +tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" [dependencies.rialto-runtime] diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ffebd82a51aee..029fdd4547d07 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -13,4 +13,4 @@ log = "0.4.11" sysinfo = "0.15" # Substrate dependencies -substrate-prometheus-endpoint = { version = "0.8.0-rc6", git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0-rc6" } +substrate-prometheus-endpoint = { version = "0.8.0", git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0" } From aec955c4ccc6627178d74a873d79385b8176d4ea Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 28 Sep 2020 23:48:58 +0300 Subject: [PATCH 0166/1210] Split payload types (#383) * split payloads (inbound/outbound/opaque/dispatch) + fees (inbound/outbound) * added tests Co-authored-by: Hernando Castano --- modules/message-lane/src/inbound_lane.rs | 15 ++- modules/message-lane/src/lib.rs | 121 ++++++++++++-------- modules/message-lane/src/mock.rs | 52 ++++++--- modules/message-lane/src/outbound_lane.rs | 8 +- primitives/message-lane/src/lib.rs | 11 +- primitives/message-lane/src/target_chain.rs | 56 +++++++-- 6 files changed, 178 insertions(+), 85 deletions(-) diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index 9fedf043194da..0c88b7796998d 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -17,13 +17,12 @@ //! Everything about incoming messages receival. use bp_message_lane::{ - target_chain::MessageDispatch, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, + target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, + InboundLaneData, LaneId, MessageKey, MessageNonce, }; /// Inbound lane storage. pub trait InboundLaneStorage { - /// Message payload. - type Payload; /// Delivery and dispatch fee type on source chain. type MessageFee; @@ -47,10 +46,10 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message>( + pub fn receive_message>( &mut self, nonce: MessageNonce, - message_data: MessageData, + message_data: DispatchMessageData, ) -> bool { let mut data = self.storage.data(); let is_correct_message = nonce == data.latest_received_nonce + 1; @@ -61,7 +60,7 @@ impl InboundLane { data.latest_received_nonce = nonce; self.storage.set_data(data); - P::dispatch(Message { + P::dispatch(DispatchMessage { key: MessageKey { lane_id: self.storage.id(), nonce, @@ -85,7 +84,7 @@ mod tests { fn fails_to_receive_message_with_incorrect_nonce() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(!lane.receive_message::(10, message_data(REGULAR_PAYLOAD))); + assert!(!lane.receive_message::(10, message_data(REGULAR_PAYLOAD).into())); assert_eq!(lane.storage.data().latest_received_nonce, 0); }); } @@ -94,7 +93,7 @@ mod tests { fn correct_message_is_processed_instantly() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message::(1, message_data(REGULAR_PAYLOAD))); + assert!(lane.receive_message::(1, message_data(REGULAR_PAYLOAD).into())); assert_eq!(lane.storage.data().latest_received_nonce, 1); }); } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 5f99eee756b63..e79ccb6d483a3 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -37,6 +37,7 @@ use bp_message_lane::{ target_chain::{MessageDispatch, SourceHeaderChain}, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; +use codec::{Decode, Encode}; use frame_support::{ decl_error, decl_event, decl_module, decl_storage, sp_runtime::DispatchResult, traits::Get, weights::Weight, Parameter, StorageMap, @@ -60,41 +61,45 @@ pub trait Trait: frame_system::Trait { /// They overarching event type. type Event: From> + Into<::Event>; - /// Message payload. - type Payload: Parameter; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever outbound lane is updated - i.e. when new message is sent, or receival is /// confirmed. The reason is that if you want to use lane, you should be ready to pay /// for it. type MaxMessagesToPruneAtOnce: Get; + /// Payload type of outbound messages. This payload is dispatched on the bridged chain. + type OutboundPayload: Parameter; + /// Message fee type of outbound messages. This fee is paid on this chain. + type OutboundMessageFee: Parameter; + + /// Payload type of inbound messages. This payload is dispatched on this chain. + type InboundPayload: Decode; + /// Message fee type of inbound messages. This fee is paid on the bridged chain. + type InboundMessageFee: Decode; + // Types that are used by outbound_lane (on source chain). - /// Type of delivery_and_dispatch_fee on source chain. - type MessageFee: Parameter; /// Target header chain. - type TargetHeaderChain: TargetHeaderChain; + type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. - type LaneMessageVerifier: LaneMessageVerifier; + type LaneMessageVerifier: LaneMessageVerifier; /// Message delivery payment. - type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment; + type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment; // Types that are used by inbound_lane (on target chain). /// Source header chain, as it is represented on target chain. - type SourceHeaderChain: SourceHeaderChain; + type SourceHeaderChain: SourceHeaderChain; /// Message dispatch. - type MessageDispatch: MessageDispatch; + type MessageDispatch: MessageDispatch; } /// Shortcut to messages proof type for Trait. -type MessagesProofOf = <>::SourceHeaderChain as SourceHeaderChain< - >::Payload, - >::MessageFee, ->>::MessagesProof; +type MessagesProofOf = + <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; /// Shortcut to messages delivery proof type for Trait. type MessagesDeliveryProofOf = - <>::TargetHeaderChain as TargetHeaderChain<>::Payload>>::MessagesDeliveryProof; + <>::TargetHeaderChain as TargetHeaderChain<>::OutboundPayload>>::MessagesDeliveryProof; decl_error! { pub enum Error for Module, I: Instance> { @@ -120,7 +125,7 @@ decl_storage! { /// Map of lane id => outbound lane data. OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; /// All queued outbound messages. - OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; + OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; } } @@ -147,8 +152,8 @@ decl_module! { pub fn send_message( origin, lane_id: LaneId, - payload: T::Payload, - delivery_and_dispatch_fee: T::MessageFee, + payload: T::OutboundPayload, + delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResult { let submitter = ensure_signed(origin)?; @@ -201,7 +206,7 @@ decl_module! { // finally, save message in outbound storage and emit event let mut lane = outbound_lane::(lane_id); let nonce = lane.send_message(MessageData { - payload, + payload: payload.encode(), fee: delivery_and_dispatch_fee, }); lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); @@ -238,6 +243,9 @@ decl_module! { Error::::InvalidMessagesProof })?; + // try to decode message payloads + let messages: Vec<_> = messages.into_iter().map(Into::into).collect(); + // verify that relayer is paying actual dispatch weight let actual_dispatch_weight: Weight = messages .iter() @@ -329,8 +337,7 @@ struct RuntimeInboundLaneStorage { } impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { - type Payload = T::Payload; - type MessageFee = T::MessageFee; + type MessageFee = T::InboundMessageFee; fn id(&self) -> LaneId { self.lane_id @@ -352,8 +359,7 @@ struct RuntimeOutboundLaneStorage { } impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorage { - type Payload = T::Payload; - type MessageFee = T::MessageFee; + type MessageFee = T::OutboundMessageFee; fn id(&self) -> LaneId { self.lane_id @@ -368,14 +374,14 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorag } #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option> { + fn message(&self, nonce: &MessageNonce) -> Option> { OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce, }) } - fn save_message(&mut self, nonce: MessageNonce, mesage_data: MessageData) { + fn save_message(&mut self, nonce: MessageNonce, mesage_data: MessageData) { OutboundMessages::::insert( MessageKey { lane_id: self.lane_id, @@ -397,10 +403,9 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorag mod tests { use super::*; use crate::mock::{ - run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestRuntime, + message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, }; - use bp_message_lane::Message; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Module as System, Phase}; @@ -503,16 +508,7 @@ mod tests { run_test(|| { assert_ok!(Module::::receive_messages_proof( Origin::signed(1), - Ok(vec![Message { - key: MessageKey { - lane_id: TEST_LANE_ID, - nonce: 1, - }, - data: MessageData { - payload: REGULAR_PAYLOAD, - fee: 0, - }, - }]), + Ok(vec![message(1, REGULAR_PAYLOAD)]), REGULAR_PAYLOAD.1, )); @@ -529,16 +525,7 @@ mod tests { assert_noop!( Module::::receive_messages_proof( Origin::signed(1), - Ok(vec![Message { - key: MessageKey { - lane_id: TEST_LANE_ID, - nonce: 1, - }, - data: MessageData { - payload: REGULAR_PAYLOAD, - fee: 0, - }, - }]), + Ok(vec![message(1, REGULAR_PAYLOAD)]), REGULAR_PAYLOAD.1 - 1, ), Error::::InvalidMessagesDispatchWeight, @@ -578,4 +565,46 @@ mod tests { ); }); } + + #[test] + fn receive_messages_accepts_single_message_with_invalid_payload() { + run_test(|| { + let mut invalid_message = message(1, REGULAR_PAYLOAD); + invalid_message.data.payload = Vec::new(); + + assert_ok!(Module::::receive_messages_proof( + Origin::signed(1), + Ok(vec![invalid_message]), + 0, // weight may be zero in this case (all messages are improperly encoded) + ),); + + assert_eq!( + InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, + 1, + ); + }); + } + + #[test] + fn receive_messages_accepts_batch_with_message_with_invalid_payload() { + run_test(|| { + let mut invalid_message = message(2, REGULAR_PAYLOAD); + invalid_message.data.payload = Vec::new(); + + assert_ok!(Module::::receive_messages_proof( + Origin::signed(1), + Ok(vec![ + message(1, REGULAR_PAYLOAD), + invalid_message, + message(3, REGULAR_PAYLOAD), + ]), + REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1, + ),); + + assert_eq!( + InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, + 3, + ); + }); + } } diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index b8b71c5db19b4..69faeb7cdcc87 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -18,9 +18,10 @@ use crate::Trait; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, - target_chain::{MessageDispatch, SourceHeaderChain}, - LaneId, Message, MessageData, MessageNonce, + target_chain::{DispatchMessage, MessageDispatch, SourceHeaderChain}, + LaneId, Message, MessageData, MessageKey, MessageNonce, }; +use codec::Encode; use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; use sp_core::H256; use sp_runtime::{ @@ -92,10 +93,14 @@ parameter_types! { impl Trait for TestRuntime { type Event = TestEvent; - type Payload = TestPayload; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; - type MessageFee = TestMessageFee; + type OutboundPayload = TestPayload; + type OutboundMessageFee = TestMessageFee; + + type InboundPayload = TestPayload; + type InboundMessageFee = TestMessageFee; + type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; @@ -194,14 +199,12 @@ impl MessageDeliveryAndDispatchPayment for TestMessag #[derive(Debug)] pub struct TestSourceHeaderChain; -impl SourceHeaderChain for TestSourceHeaderChain { +impl SourceHeaderChain for TestSourceHeaderChain { type Error = &'static str; - type MessagesProof = Result>, ()>; + type MessagesProof = Result>, ()>; - fn verify_messages_proof( - proof: Self::MessagesProof, - ) -> Result>, Self::Error> { + fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error> { proof.map_err(|_| TEST_ERROR) } } @@ -210,17 +213,36 @@ impl SourceHeaderChain for TestSourceHeaderChain { #[derive(Debug)] pub struct TestMessageDispatch; -impl MessageDispatch for TestMessageDispatch { - fn dispatch_weight(message: &Message) -> Weight { - message.data.payload.1 +impl MessageDispatch for TestMessageDispatch { + type DispatchPayload = TestPayload; + + fn dispatch_weight(message: &DispatchMessage) -> Weight { + match message.data.payload.as_ref() { + Ok(payload) => payload.1, + Err(_) => 0, + } } - fn dispatch(_message: Message) {} + fn dispatch(_message: DispatchMessage) {} +} + +/// Return test lane message with given nonce and payload. +pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message { + Message { + key: MessageKey { + lane_id: TEST_LANE_ID, + nonce, + }, + data: message_data(payload), + } } /// Return message data with valid fee for given payload. -pub fn message_data(payload: TestPayload) -> MessageData { - MessageData { payload, fee: 1 } +pub fn message_data(payload: TestPayload) -> MessageData { + MessageData { + payload: payload.encode(), + fee: 1, + } } /// Run message lane test. diff --git a/modules/message-lane/src/outbound_lane.rs b/modules/message-lane/src/outbound_lane.rs index 8afcd0702869b..dc1ec413012d0 100644 --- a/modules/message-lane/src/outbound_lane.rs +++ b/modules/message-lane/src/outbound_lane.rs @@ -20,8 +20,6 @@ use bp_message_lane::{LaneId, MessageData, MessageNonce, OutboundLaneData}; /// Outbound lane storage. pub trait OutboundLaneStorage { - /// Message payload. - type Payload; /// Delivery and dispatch fee type on source chain. type MessageFee; @@ -33,9 +31,9 @@ pub trait OutboundLaneStorage { fn set_data(&mut self, data: OutboundLaneData); /// Returns saved outbound message payload. #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option>; + fn message(&self, nonce: &MessageNonce) -> Option>; /// Save outbound message in the storage. - fn save_message(&mut self, nonce: MessageNonce, message_data: MessageData); + fn save_message(&mut self, nonce: MessageNonce, message_data: MessageData); /// Remove outbound message from the storage. fn remove_message(&mut self, nonce: &MessageNonce); } @@ -54,7 +52,7 @@ impl OutboundLane { /// Send message over lane. /// /// Returns new message nonce. - pub fn send_message(&mut self, message_data: MessageData) -> MessageNonce { + pub fn send_message(&mut self, message_data: MessageData) -> MessageNonce { let mut data = self.storage.data(); let nonce = data.latest_generated_nonce + 1; data.latest_generated_nonce = nonce; diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index a2e3e41cfd40c..a3216439958b1 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -39,6 +39,9 @@ pub type MessageNonce = u64; /// Message id as a tuple. pub type MessageId = (LaneId, MessageNonce); +/// Opaque message payload. We only decode this payload when it is dispatched. +pub type MessagePayload = Vec; + /// Message key (unique message identifier) as it is stored in the storage. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct MessageKey { @@ -50,20 +53,20 @@ pub struct MessageKey { /// Message data as it is stored in the storage. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct MessageData { +pub struct MessageData { /// Message payload. - pub payload: Payload, + pub payload: MessagePayload, /// Message delivery and dispatch fee, paid by the submitter. pub fee: Fee, } /// Message as it is stored in the storage. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] -pub struct Message { +pub struct Message { /// Message key. pub key: MessageKey, /// Message data. - pub data: MessageData, + pub data: MessageData, } /// Inbound lane data. diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index 7287b26ae5713..8bc71ee830066 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -16,17 +16,36 @@ //! Primitives of message lane module, that are used on the target chain. -use crate::Message; +use crate::{Message, MessageData, MessageKey}; -use frame_support::{weights::Weight, Parameter}; +use codec::{Decode, Error as CodecError}; +use frame_support::{weights::Weight, Parameter, RuntimeDebug}; use sp_std::{fmt::Debug, prelude::*}; +/// Message data with decoded dispatch payload. +#[derive(RuntimeDebug)] +pub struct DispatchMessageData { + /// Result of dispatch payload decoding. + pub payload: Result, + /// Message delivery and dispatch fee, paid by the submitter. + pub fee: Fee, +} + +/// Message with decoded dispatch payload. +#[derive(RuntimeDebug)] +pub struct DispatchMessage { + /// Message key. + pub key: MessageKey, + /// Message data with decoded dispatch payload. + pub data: DispatchMessageData, +} + /// Source chain API. Used by target chain, to verify source chain proofs. /// /// All implementations of this trait should only work with finalized data that /// can't change. Wrong implementation may lead to invalid lane states (i.e. lane /// that's stuck) and/or processing messages without paying fees. -pub trait SourceHeaderChain { +pub trait SourceHeaderChain { /// Error type. type Error: Debug + Into<&'static str>; @@ -37,20 +56,43 @@ pub trait SourceHeaderChain { /// /// Messages vector is required to be sorted by nonce within each lane. Out-of-order /// messages will be rejected. - fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error>; + fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error>; } /// Called when inbound message is received. -pub trait MessageDispatch { +pub trait MessageDispatch { + /// Decoded message payload type. Valid message may contain invalid payload. In this case + /// message is delivered, but dispatch fails. Therefore, two separate types of payload + /// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch). + type DispatchPayload: Decode; + /// Estimate dispatch weight. /// /// This function must: (1) be instant and (2) return correct upper bound /// of dispatch weight. - fn dispatch_weight(message: &Message) -> Weight; + fn dispatch_weight(message: &DispatchMessage) -> Weight; /// Called when inbound message is received. /// /// It is up to the implementers of this trait to determine whether the message /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. - fn dispatch(message: Message); + fn dispatch(message: DispatchMessage); +} + +impl From> for DispatchMessage { + fn from(message: Message) -> Self { + DispatchMessage { + key: message.key, + data: message.data.into(), + } + } +} + +impl From> for DispatchMessageData { + fn from(data: MessageData) -> Self { + DispatchMessageData { + payload: DispatchPayload::decode(&mut &data.payload[..]), + fee: data.fee, + } + } } From 362e31bf169dba4f2434ab9d78d853834f846d28 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 28 Sep 2020 23:49:15 +0300 Subject: [PATCH 0167/1210] Extract minimal Rialto-Sub and Millau-Sub clients (#365) * extracting sub clients * fmt + lost docs * revert enum BridgeInstance * apply suggestions from review * explicite debug impl * remove unused imports from Millau * fix typo * fix instance + API name * Update relays/ethereum/src/ethereum_sync_loop.rs Co-authored-by: Hernando Castano * separate crates for millau and rialto client * cargo fmt * fix * fmt * remove no_std support * fix compilation again * Update relays/substrate-client/Cargo.toml * Update relay clients to Substrate 2.0 Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/rialto-runtime/src/lib.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 2 +- relays/ethereum/Cargo.toml | 13 +- relays/ethereum/src/cli.yml | 2 - relays/ethereum/src/ethereum_client.rs | 83 ++-- .../ethereum/src/ethereum_deploy_contract.rs | 26 +- relays/ethereum/src/ethereum_exchange.rs | 32 +- relays/ethereum/src/ethereum_sync_loop.rs | 41 +- relays/ethereum/src/instances.rs | 4 +- relays/ethereum/src/main.rs | 30 +- relays/ethereum/src/rialto_client.rs | 269 ++++++++++++ relays/ethereum/src/rpc.rs | 86 ---- relays/ethereum/src/rpc_errors.rs | 32 +- relays/ethereum/src/substrate_client.rs | 410 ------------------ relays/ethereum/src/substrate_sync_loop.rs | 94 ++-- relays/ethereum/src/substrate_types.rs | 80 +--- relays/millau-client/Cargo.toml | 10 + relays/millau-client/src/lib.rs | 33 ++ relays/rialto-client/Cargo.toml | 24 + relays/rialto-client/src/lib.rs | 132 ++++++ relays/substrate-client/Cargo.toml | 22 + relays/substrate-client/src/chain.rs | 87 ++++ relays/substrate-client/src/client.rs | 135 ++++++ relays/substrate-client/src/error.rs | 55 +++ relays/substrate-client/src/lib.rs | 46 ++ relays/substrate-client/src/rpc.rs | 43 ++ 26 files changed, 1042 insertions(+), 751 deletions(-) create mode 100644 relays/ethereum/src/rialto_client.rs delete mode 100644 relays/ethereum/src/rpc.rs delete mode 100644 relays/ethereum/src/substrate_client.rs create mode 100644 relays/millau-client/Cargo.toml create mode 100644 relays/millau-client/src/lib.rs create mode 100644 relays/rialto-client/Cargo.toml create mode 100644 relays/rialto-client/src/lib.rs create mode 100644 relays/substrate-client/Cargo.toml create mode 100644 relays/substrate-client/src/chain.rs create mode 100644 relays/substrate-client/src/client.rs create mode 100644 relays/substrate-client/src/error.rs create mode 100644 relays/substrate-client/src/lib.rs create mode 100644 relays/substrate-client/src/rpc.rs diff --git a/bin/rialto-runtime/src/lib.rs b/bin/rialto-runtime/src/lib.rs index 6b207dbdb0951..f0e1e77154b7d 100644 --- a/bin/rialto-runtime/src/lib.rs +++ b/bin/rialto-runtime/src/lib.rs @@ -522,7 +522,7 @@ impl_runtime_apis! { } } - impl bp_eth_poa::RialtoHeaderApi for Runtime { + impl bp_eth_poa::RialtoPoAHeaderApi for Runtime { fn best_block() -> (u64, bp_eth_poa::H256) { let best_block = BridgeRialto::best_block(); (best_block.number, best_block.hash) diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 5229522b02123..63d2dda207e83 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -549,7 +549,7 @@ pub fn step_validator(header_validators: &[T], header_step: u64) -> &T { sp_api::decl_runtime_apis! { /// API for querying information about headers from the Rialto Bridge Pallet - pub trait RialtoHeaderApi { + pub trait RialtoPoAHeaderApi { /// Returns number and hash of the best block known to the bridge module. /// /// The caller should only submit an `import_header` transaction that makes diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 08f1b147aae6f..15feebd70fd2b 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -27,17 +27,14 @@ messages-relay = { path = "../messages-relay" } num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } relay-ethereum-client = { path = "../ethereum-client" } +relay-rialto-client = { path = "../rialto-client" } +relay-substrate-client = { path = "../substrate-client" } +rialto-runtime = { path = "../../bin/rialto-runtime" } relay-utils = { path = "../utils" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" time = "0.2" -[dependencies.jsonrpsee] -git = "https://github.com/svyatonik/jsonrpsee.git" -branch = "shared-client-in-rpc-api" -default-features = false -features = ["http"] - # Substrate Based Dependencies [dependencies.frame-system] version = "2.0.0" @@ -73,7 +70,3 @@ git = "https://github.com/paritytech/substrate.git" version = "0.8.0" tag = 'v2.0.0' git = "https://github.com/paritytech/substrate.git" - -[dependencies.rialto-runtime] -version = "0.1.0" -path = "../../bin/rialto-runtime" diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index 35c8c2e6eb3f9..a665e76776967 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -85,7 +85,6 @@ subcommands: help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. - sub-host: *sub-host - sub-port: *sub-port - - sub-pallet-instance: *sub-pallet-instance - no-prometheus: *no-prometheus - prometheus-host: *prometheus-host - prometheus-port: *prometheus-port @@ -103,7 +102,6 @@ subcommands: takes_value: true - sub-host: *sub-host - sub-port: *sub-port - - sub-pallet-instance: *sub-pallet-instance - sub-authorities-set-id: long: sub-authorities-set-id value_name: SUB_AUTHORITIES_SET_ID diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index d9357c560b08d..19d88199853b2 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::rpc_errors::RpcError; -use crate::substrate_types::{GrandpaJustification, Hash as SubstrateHash, QueuedSubstrateHeader, SubstrateHeaderId}; +use crate::substrate_sync_loop::QueuedRialtoHeader; use async_trait::async_trait; use codec::{Decode, Encode}; @@ -26,7 +26,9 @@ use relay_ethereum_client::{ types::{Address, CallRequest, HeaderId as EthereumHeaderId, Receipt, H256, U256}, Client as EthereumClient, Error as EthereumNodeError, SigningParams as EthereumSigningParams, }; +use relay_rialto_client::HeaderId as RialtoHeaderId; use relay_utils::{HeaderId, MaybeConnectionError}; +use sp_runtime::Justification; use std::collections::HashSet; // to encode/decode contract calls @@ -39,34 +41,34 @@ type RpcResult = std::result::Result; #[async_trait] pub trait EthereumHighLevelRpc { /// Returns best Substrate block that PoA chain knows of. - async fn best_substrate_block(&self, contract_address: Address) -> RpcResult; + async fn best_substrate_block(&self, contract_address: Address) -> RpcResult; /// Returns true if Substrate header is known to Ethereum node. async fn substrate_header_known( &self, contract_address: Address, - id: SubstrateHeaderId, - ) -> RpcResult<(SubstrateHeaderId, bool)>; + id: RialtoHeaderId, + ) -> RpcResult<(RialtoHeaderId, bool)>; /// Submits Substrate headers to Ethereum contract. async fn submit_substrate_headers( &self, params: EthereumSigningParams, contract_address: Address, - headers: Vec, - ) -> SubmittedHeaders; + headers: Vec, + ) -> SubmittedHeaders; /// Returns ids of incomplete Substrate headers. - async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult>; + async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult>; /// Complete Substrate header. async fn complete_substrate_header( &self, params: EthereumSigningParams, contract_address: Address, - id: SubstrateHeaderId, - justification: GrandpaJustification, - ) -> RpcResult; + id: RialtoHeaderId, + justification: Justification, + ) -> RpcResult; /// Submit ethereum transaction. async fn submit_ethereum_transaction( @@ -88,7 +90,7 @@ pub trait EthereumHighLevelRpc { #[async_trait] impl EthereumHighLevelRpc for EthereumClient { - async fn best_substrate_block(&self, contract_address: Address) -> RpcResult { + async fn best_substrate_block(&self, contract_address: Address) -> RpcResult { let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); let call_request = CallRequest { to: Some(contract_address), @@ -98,7 +100,7 @@ impl EthereumHighLevelRpc for EthereumClient { let call_result = self.eth_call(call_request).await?; let (number, raw_hash) = call_decoder.decode(&call_result.0)?; - let hash = SubstrateHash::decode(&mut &raw_hash[..])?; + let hash = rialto_runtime::Hash::decode(&mut &raw_hash[..])?; if number != number.low_u32().into() { return Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)); @@ -110,8 +112,8 @@ impl EthereumHighLevelRpc for EthereumClient { async fn substrate_header_known( &self, contract_address: Address, - id: SubstrateHeaderId, - ) -> RpcResult<(SubstrateHeaderId, bool)> { + id: RialtoHeaderId, + ) -> RpcResult<(RialtoHeaderId, bool)> { let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1); let call_request = CallRequest { to: Some(contract_address), @@ -129,8 +131,8 @@ impl EthereumHighLevelRpc for EthereumClient { &self, params: EthereumSigningParams, contract_address: Address, - headers: Vec, - ) -> SubmittedHeaders { + headers: Vec, + ) -> SubmittedHeaders { // read nonce of signer let address: Address = params.signer.address().as_fixed_bytes().into(); let nonce = match self.account_nonce(address).await { @@ -159,7 +161,7 @@ impl EthereumHighLevelRpc for EthereumClient { .await } - async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult> { + async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult> { let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); let call_request = CallRequest { to: Some(contract_address), @@ -190,9 +192,9 @@ impl EthereumHighLevelRpc for EthereumClient { &self, params: EthereumSigningParams, contract_address: Address, - id: SubstrateHeaderId, - justification: GrandpaJustification, - ) -> RpcResult { + id: RialtoHeaderId, + justification: Justification, + ) -> RpcResult { let _ = self .submit_ethereum_transaction( ¶ms, @@ -243,21 +245,21 @@ pub const HEADERS_BATCH: usize = 4; #[derive(Debug)] #[cfg_attr(test, derive(Clone))] pub struct HeadersBatch { - pub header1: QueuedSubstrateHeader, - pub header2: Option, - pub header3: Option, - pub header4: Option, + pub header1: QueuedRialtoHeader, + pub header2: Option, + pub header3: Option, + pub header4: Option, } impl HeadersBatch { /// Create new headers from given header & ids collections. /// /// This method will pop `HEADERS_BATCH` items from both collections - /// and construct `Headers` object and a vector of `SubstrateheaderId`s. + /// and construct `Headers` object and a vector of `RialtoHeaderId`s. pub fn pop_from( - headers: &mut Vec, - ids: &mut Vec, - ) -> Result<(Self, Vec), ()> { + headers: &mut Vec, + ids: &mut Vec, + ) -> Result<(Self, Vec), ()> { if headers.len() != ids.len() { log::error!(target: "bridge", "Collection size mismatch ({} vs {})", headers.len(), ids.len()); return Err(()); @@ -287,7 +289,7 @@ impl HeadersBatch { /// Returns unified array of headers. /// /// The first element is always `Some`. - fn headers(&self) -> [Option<&QueuedSubstrateHeader>; HEADERS_BATCH] { + fn headers(&self) -> [Option<&QueuedRialtoHeader>; HEADERS_BATCH] { [ Some(&self.header1), self.header2.as_ref(), @@ -298,7 +300,7 @@ impl HeadersBatch { /// Encodes all headers. If header is not present an empty vector will be returned. pub fn encode(&self) -> [Vec; HEADERS_BATCH] { - let encode = |h: &QueuedSubstrateHeader| h.header().encode(); + let encode = |h: &QueuedRialtoHeader| h.header().encode(); let headers = self.headers(); [ headers[0].map(encode).unwrap_or_default(), @@ -309,7 +311,7 @@ impl HeadersBatch { } /// Returns number of contained headers. pub fn len(&self) -> usize { - let is_set = |h: &Option<&QueuedSubstrateHeader>| if h.is_some() { 1 } else { 0 }; + let is_set = |h: &Option<&QueuedRialtoHeader>| if h.is_some() { 1 } else { 0 }; self.headers().iter().map(is_set).sum() } @@ -396,8 +398,8 @@ impl HeadersSubmitter for EthereumHeadersSubmitter { /// Submit multiple Substrate headers. async fn submit_substrate_headers( mut header_submitter: impl HeadersSubmitter, - mut headers: Vec, -) -> SubmittedHeaders { + mut headers: Vec, +) -> SubmittedHeaders { let mut submitted_headers = SubmittedHeaders::default(); let mut ids = headers.iter().map(|header| header.id()).rev().collect::>(); @@ -424,8 +426,8 @@ async fn submit_substrate_headers( /// Submit 4 Substrate headers in single PoA transaction. async fn submit_substrate_headers_batch( header_submitter: &mut impl HeadersSubmitter, - submitted_headers: &mut SubmittedHeaders, - mut ids: Vec, + submitted_headers: &mut SubmittedHeaders, + mut ids: Vec, mut headers: HeadersBatch, ) -> Option { debug_assert_eq!(ids.len(), headers.len(),); @@ -486,12 +488,11 @@ async fn submit_substrate_headers_batch( #[cfg(test)] mod tests { use super::*; - use crate::substrate_types::{Header as SubstrateHeader, Number as SubstrateBlockNumber}; use sp_runtime::traits::Header; struct TestHeadersSubmitter { - incomplete: Vec, - failed: Vec, + incomplete: Vec, + failed: Vec, } #[async_trait] @@ -513,9 +514,9 @@ mod tests { } } - fn header(number: SubstrateBlockNumber) -> QueuedSubstrateHeader { - QueuedSubstrateHeader::new( - SubstrateHeader::new( + fn header(number: rialto_runtime::BlockNumber) -> QueuedRialtoHeader { + QueuedRialtoHeader::new( + rialto_runtime::Header::new( number, Default::default(), Default::default(), diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index 17f12ba45eb1b..25f8c873e5903 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -15,16 +15,17 @@ // along with Parity Bridges Common. If not, see . use crate::ethereum_client::{bridge_contract, EthereumHighLevelRpc}; -use crate::instances::BridgeInstance; -use crate::rpc::SubstrateRpc; -use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; -use crate::substrate_types::{Hash as SubstrateHash, Header as SubstrateHeader, SubstrateHeaderId}; +use crate::rpc_errors::RpcError; use codec::{Decode, Encode}; use num_traits::Zero; use relay_ethereum_client::{ Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, }; +use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto}; +use relay_substrate_client::{ + Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, OpaqueGrandpaAuthoritiesSet, +}; use relay_utils::HeaderId; /// Ethereum synchronization parameters. @@ -44,8 +45,6 @@ pub struct EthereumDeployContractParams { pub sub_initial_authorities_set: Option>, /// Initial header. pub sub_initial_header: Option>, - /// Instance of the bridge pallet being synchronized. - pub instance: Box, } /// Deploy Bridge contract on Ethereum chain. @@ -56,7 +55,6 @@ pub fn run(params: EthereumDeployContractParams) { eth_params, eth_sign, sub_params, - instance, sub_initial_authorities_set_id, sub_initial_authorities_set, sub_initial_header, @@ -65,7 +63,7 @@ pub fn run(params: EthereumDeployContractParams) { let result = local_pool.run_until(async move { let eth_client = EthereumClient::new(eth_params); - let sub_client = SubstrateRpcClient::new(sub_params, instance).await?; + let sub_client = SubstrateClient::::new(sub_params).await.map_err(RpcError::Substrate)?; let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; let initial_set_id = sub_initial_authorities_set_id.unwrap_or(0); @@ -102,11 +100,11 @@ pub fn run(params: EthereumDeployContractParams) { /// Prepare initial header. async fn prepare_initial_header( - sub_client: &SubstrateRpcClient, + sub_client: &SubstrateClient, sub_initial_header: Option>, -) -> Result<(SubstrateHeaderId, Vec), String> { +) -> Result<(RialtoHeaderId, Vec), String> { match sub_initial_header { - Some(raw_initial_header) => match SubstrateHeader::decode(&mut &raw_initial_header[..]) { + Some(raw_initial_header) => match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) { Ok(initial_header) => Ok(( HeaderId(initial_header.number, initial_header.hash()), raw_initial_header, @@ -124,10 +122,10 @@ async fn prepare_initial_header( /// Prepare initial GRANDPA authorities set. async fn prepare_initial_authorities_set( - sub_client: &SubstrateRpcClient, - sub_initial_header_hash: SubstrateHash, + sub_client: &SubstrateClient, + sub_initial_header_hash: rialto_runtime::Hash, sub_initial_authorities_set: Option>, -) -> Result, String> { +) -> Result { let initial_authorities_set = match sub_initial_authorities_set { Some(initial_authorities_set) => Ok(initial_authorities_set), None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await, diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 59c9a42ca68c4..c8b8a7a7e8ebf 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -17,11 +17,8 @@ //! Relaying proofs of PoA -> Substrate exchange transactions. use crate::instances::BridgeInstance; -use crate::rpc::SubstrateRpc; +use crate::rialto_client::{SubmitEthereumExchangeTransactionProof, SubstrateHighLevelRpc}; use crate::rpc_errors::RpcError; -use crate::substrate_client::{ - SubmitEthereumExchangeTransactionProof, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, -}; use crate::substrate_types::into_substrate_ethereum_receipt; use async_trait::async_trait; @@ -38,9 +35,11 @@ use relay_ethereum_client::{ }, Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; +use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; use relay_utils::{metrics::MetricsParams, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; -use std::time::Duration; +use std::{sync::Arc, time::Duration}; /// Interval at which we ask Ethereum node for updates. const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); @@ -64,13 +63,13 @@ pub struct EthereumExchangeParams { /// Substrate connection params. pub sub_params: SubstrateConnectionParams, /// Substrate signing params. - pub sub_sign: SubstrateSigningParams, + pub sub_sign: RialtoSigningParams, /// Relay working mode. pub mode: ExchangeRelayMode, /// Metrics parameters. pub metrics_params: Option, /// Instance of the bridge pallet being synchronized. - pub instance: Box, + pub instance: Arc, } /// Ethereum to Substrate exchange pipeline. @@ -201,8 +200,9 @@ impl SourceClient for EthereumTransactionsSource { /// Substrate node as transactions proof target. struct SubstrateTransactionsTarget { - client: SubstrateRpcClient, - sign_params: SubstrateSigningParams, + client: SubstrateClient, + sign_params: RialtoSigningParams, + bridge_instance: Arc, } #[async_trait] @@ -254,8 +254,10 @@ impl TargetClient for SubstrateTransactionsTarget { } async fn submit_transaction_proof(&self, proof: EthereumTransactionInclusionProof) -> Result<(), Self::Error> { - let sign_params = self.sign_params.clone(); - self.client.submit_exchange_transaction_proof(sign_params, proof).await + let (sign_params, bridge_instance) = (self.sign_params.clone(), self.bridge_instance.clone()); + self.client + .submit_exchange_transaction_proof(sign_params, bridge_instance, proof) + .await } } @@ -283,12 +285,15 @@ fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H25 let result = local_pool.run_until(async move { let eth_client = EthereumClient::new(eth_params); - let sub_client = SubstrateRpcClient::new(sub_params, instance).await?; + let sub_client = SubstrateClient::::new(sub_params) + .await + .map_err(RpcError::Substrate)?; let source = EthereumTransactionsSource { client: eth_client }; let target = SubstrateTransactionsTarget { client: sub_client, sign_params: sub_sign, + bridge_instance: instance, }; relay_single_transaction_proof(&source, &target, eth_tx_hash).await @@ -326,7 +331,7 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi let do_run_loop = move || -> Result<(), String> { let eth_client = EthereumClient::new(eth_params); - let sub_client = async_std::task::block_on(SubstrateRpcClient::new(sub_params, instance)) + let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params)) .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; let eth_start_with_block_number = match eth_start_with_block_number { @@ -349,6 +354,7 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi SubstrateTransactionsTarget { client: sub_client, sign_params: sub_sign, + bridge_instance: instance, }, metrics_params, futures::future::pending(), diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index d5a4ec9b8e103..c9045c6974dcc 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -14,15 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Ethereum PoA -> Substrate synchronization. +//! Ethereum PoA -> Rialto-Substrate synchronization. use crate::ethereum_client::EthereumHighLevelRpc; use crate::instances::BridgeInstance; -use crate::rpc::SubstrateRpc; +use crate::rialto_client::{SubmitEthereumHeaders, SubstrateHighLevelRpc}; use crate::rpc_errors::RpcError; -use crate::substrate_client::{ - SubmitEthereumHeaders, SubstrateConnectionParams, SubstrateRpcClient, SubstrateSigningParams, -}; use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; use async_trait::async_trait; @@ -36,10 +33,12 @@ use relay_ethereum_client::{ types::{HeaderHash, HeaderId as EthereumHeaderId, Receipt, SyncHeader as Header}, Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; +use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; use relay_utils::metrics::MetricsParams; use std::fmt::Debug; -use std::{collections::HashSet, time::Duration}; +use std::{collections::HashSet, sync::Arc, time::Duration}; pub mod consts { use super::*; @@ -70,13 +69,13 @@ pub struct EthereumSyncParams { /// Substrate connection params. pub sub_params: SubstrateConnectionParams, /// Substrate signing params. - pub sub_sign: SubstrateSigningParams, + pub sub_sign: RialtoSigningParams, /// Synchronization parameters. pub sync_params: HeadersSyncParams, /// Metrics parameters. pub metrics_params: Option, /// Instance of the bridge pallet being synchronized. - pub instance: Box, + pub instance: Arc, } /// Ethereum synchronization pipeline. @@ -158,19 +157,27 @@ impl SourceClient for EthereumHeadersSource { struct SubstrateHeadersTarget { /// Substrate node client. - client: SubstrateRpcClient, + client: SubstrateClient, /// Whether we want to submit signed (true), or unsigned (false) transactions. sign_transactions: bool, /// Substrate signing params. - sign_params: SubstrateSigningParams, + sign_params: RialtoSigningParams, + /// Bridge instance used in Ethereum to Substrate sync. + bridge_instance: Arc, } impl SubstrateHeadersTarget { - fn new(client: SubstrateRpcClient, sign_transactions: bool, sign_params: SubstrateSigningParams) -> Self { + fn new( + client: SubstrateClient, + sign_transactions: bool, + sign_params: RialtoSigningParams, + bridge_instance: Arc, + ) -> Self { Self { client, sign_transactions, sign_params, + bridge_instance, } } } @@ -191,9 +198,13 @@ impl TargetClient for SubstrateHeadersTarget { &self, headers: Vec, ) -> SubmittedHeaders { - let (sign_params, sign_transactions) = (self.sign_params.clone(), self.sign_transactions); + let (sign_params, bridge_instance, sign_transactions) = ( + self.sign_params.clone(), + self.bridge_instance.clone(), + self.sign_transactions, + ); self.client - .submit_ethereum_headers(sign_params, headers, sign_transactions) + .submit_ethereum_headers(sign_params, bridge_instance, headers, sign_transactions) .await } @@ -228,7 +239,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { } = params; let eth_client = EthereumClient::new(eth_params); - let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?; + let sub_client = async_std::task::block_on(async { SubstrateClient::::new(sub_params).await })?; let sign_sub_transactions = match sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, @@ -236,7 +247,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { }; let source = EthereumHeadersSource::new(eth_client); - let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign); + let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign, instance); headers_relay::sync_loop::run( source, diff --git a/relays/ethereum/src/instances.rs b/relays/ethereum/src/instances.rs index d2f06c2504342..bfdccd0ba34df 100644 --- a/relays/ethereum/src/instances.rs +++ b/relays/ethereum/src/instances.rs @@ -44,9 +44,9 @@ pub trait BridgeInstance: Send + Sync + std::fmt::Debug { /// Corresponds to the Rialto instance used in the bridge runtime. #[derive(Default, Clone, Debug)] -pub struct Rialto; +pub struct RialtoPoA; -impl BridgeInstance for Rialto { +impl BridgeInstance for RialtoPoA { fn build_signed_header_call(&self, headers: Vec) -> Call { let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers( headers diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 14400c630f9e5..9b290df43c45d 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -22,9 +22,8 @@ mod ethereum_exchange; mod ethereum_exchange_submit; mod ethereum_sync_loop; mod instances; -mod rpc; +mod rialto_client; mod rpc_errors; -mod substrate_client; mod substrate_sync_loop; mod substrate_types; @@ -34,16 +33,17 @@ use ethereum_exchange_submit::EthereumExchangeSubmitParams; use ethereum_sync_loop::EthereumSyncParams; use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; -use instances::{BridgeInstance, Kovan, Rialto}; +use instances::{BridgeInstance, Kovan, RialtoPoA}; use parity_crypto::publickey::{KeyPair, Secret}; use relay_utils::metrics::MetricsParams; use sp_core::crypto::Pair; -use substrate_client::{SubstrateConnectionParams, SubstrateSigningParams}; use substrate_sync_loop::SubstrateSyncParams; use headers_relay::sync::HeadersSyncParams; use relay_ethereum_client::{ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams}; -use std::io::Write; +use relay_rialto_client::SigningParams as RialtoSigningParams; +use relay_substrate_client::ConnectionParams as SubstrateConnectionParams; +use std::{io::Write, sync::Arc}; fn main() { initialize(); @@ -197,8 +197,8 @@ fn substrate_connection_params(matches: &clap::ArgMatches) -> Result Result { - let mut params = SubstrateSigningParams::default(); +fn rialto_signing_params(matches: &clap::ArgMatches) -> Result { + let mut params = RialtoSigningParams::default(); if let Some(sub_signer) = matches.value_of("sub-signer") { let sub_signer_password = matches.value_of("sub-signer-password"); params.signer = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) @@ -235,7 +235,7 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result Result Result Result Result, S Ok(Some(metrics_params)) } -fn instance_params(matches: &clap::ArgMatches) -> Result, String> { - let instance: Box = if let Some(instance) = matches.value_of("sub-pallet-instance") { +fn instance_params(matches: &clap::ArgMatches) -> Result, String> { + let instance = if let Some(instance) = matches.value_of("sub-pallet-instance") { match instance.to_lowercase().as_str() { - "rialto" => Box::new(Rialto::default()), - "kovan" => Box::new(Kovan::default()), + "rialto" => Arc::new(RialtoPoA) as Arc, + "kovan" => Arc::new(Kovan), _ => return Err("Unsupported bridge pallet instance".to_string()), } } else { diff --git a/relays/ethereum/src/rialto_client.rs b/relays/ethereum/src/rialto_client.rs new file mode 100644 index 0000000000000..861ef8efeb970 --- /dev/null +++ b/relays/ethereum/src/rialto_client.rs @@ -0,0 +1,269 @@ +// Copyright 2019-2020 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 . + +use crate::ethereum_sync_loop::QueuedEthereumHeader; +use crate::instances::BridgeInstance; +use crate::rpc_errors::RpcError; + +use async_trait::async_trait; +use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; +use codec::{Decode, Encode}; +use headers_relay::sync_types::SubmittedHeaders; +use relay_ethereum_client::types::HeaderId as EthereumHeaderId; +use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{Client as SubstrateClient, TransactionSignScheme}; +use relay_utils::HeaderId; +use sp_core::{crypto::Pair, Bytes}; +use std::{collections::VecDeque, sync::Arc}; + +const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoPoAHeaderApi_is_import_requires_receipts"; +const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoPoAHeaderApi_is_known_block"; +const ETH_API_BEST_BLOCK: &str = "RialtoPoAHeaderApi_best_block"; +const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoPoAHeaderApi_finalized_block"; +const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "RialtoCurrencyExchangeApi_filter_transaction_proof"; + +type RpcResult = std::result::Result; + +/// A trait which contains methods that work by using multiple low-level RPCs, or more complicated +/// interactions involving, for example, an Ethereum bridge module. +#[async_trait] +pub trait SubstrateHighLevelRpc { + /// Returns best Ethereum block that Substrate runtime knows of. + async fn best_ethereum_block(&self) -> RpcResult; + /// Returns best finalized Ethereum block that Substrate runtime knows of. + async fn best_ethereum_finalized_block(&self) -> RpcResult; + /// Returns whether or not transactions receipts are required for Ethereum header submission. + async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult; + /// Returns whether or not the given Ethereum header is known to the Substrate runtime. + async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult; +} + +#[async_trait] +impl SubstrateHighLevelRpc for SubstrateClient { + async fn best_ethereum_block(&self) -> RpcResult { + let call = ETH_API_BEST_BLOCK.to_string(); + let data = Bytes(Vec::new()); + + let encoded_response = self.state_call(call, data, None).await?; + let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + Ok(best_header_id) + } + + async fn best_ethereum_finalized_block(&self) -> RpcResult { + let call = ETH_API_BEST_FINALIZED_BLOCK.to_string(); + let data = Bytes(Vec::new()); + + let encoded_response = self.state_call(call, data, None).await?; + let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + Ok(best_header_id) + } + + async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult { + let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); + let data = Bytes(header.encode()); + + let encoded_response = self.state_call(call, data, None).await?; + let receipts_required: bool = Decode::decode(&mut &encoded_response.0[..])?; + + Ok(receipts_required) + } + + // The Substrate module could prune old headers. So this function could return false even + // if header is synced. And we'll mark corresponding Ethereum header as Orphan. + // + // But when we read the best header from Substrate next time, we will know that + // there's a better header. This Orphan will either be marked as synced, or + // eventually pruned. + async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult { + let call = ETH_API_IS_KNOWN_BLOCK.to_string(); + let data = Bytes(header_id.1.encode()); + + let encoded_response = self.state_call(call, data, None).await?; + let is_known_block: bool = Decode::decode(&mut &encoded_response.0[..])?; + + Ok(is_known_block) + } +} + +/// A trait for RPC calls which are used to submit Ethereum headers to a Substrate +/// runtime. These are typically calls which use a combination of other low-level RPC +/// calls. +#[async_trait] +pub trait SubmitEthereumHeaders { + /// Submits Ethereum header to Substrate runtime. + async fn submit_ethereum_headers( + &self, + params: RialtoSigningParams, + instance: Arc, + headers: Vec, + sign_transactions: bool, + ) -> SubmittedHeaders; + + /// Submits signed Ethereum header to Substrate runtime. + async fn submit_signed_ethereum_headers( + &self, + params: RialtoSigningParams, + instance: Arc, + headers: Vec, + ) -> SubmittedHeaders; + + /// Submits unsigned Ethereum header to Substrate runtime. + async fn submit_unsigned_ethereum_headers( + &self, + instance: Arc, + headers: Vec, + ) -> SubmittedHeaders; +} + +#[async_trait] +impl SubmitEthereumHeaders for SubstrateClient { + async fn submit_ethereum_headers( + &self, + params: RialtoSigningParams, + instance: Arc, + headers: Vec, + sign_transactions: bool, + ) -> SubmittedHeaders { + if sign_transactions { + self.submit_signed_ethereum_headers(params, instance, headers).await + } else { + self.submit_unsigned_ethereum_headers(instance, headers).await + } + } + + async fn submit_signed_ethereum_headers( + &self, + params: RialtoSigningParams, + instance: Arc, + headers: Vec, + ) -> SubmittedHeaders { + let ids = headers.iter().map(|header| header.id()).collect(); + let submission_result = async { + let account_id = params.signer.public().as_array_ref().clone().into(); + let nonce = self.next_account_index(account_id).await?; + + let call = instance.build_signed_header_call(headers); + let transaction = Rialto::sign_transaction(self, ¶ms.signer, nonce, call); + + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + Ok(()) + } + .await; + + match submission_result { + Ok(_) => SubmittedHeaders { + submitted: ids, + incomplete: Vec::new(), + rejected: Vec::new(), + fatal_error: None, + }, + Err(error) => SubmittedHeaders { + submitted: Vec::new(), + incomplete: Vec::new(), + rejected: ids, + fatal_error: Some(error), + }, + } + } + + async fn submit_unsigned_ethereum_headers( + &self, + instance: Arc, + headers: Vec, + ) -> SubmittedHeaders { + let mut ids = headers.iter().map(|header| header.id()).collect::>(); + let mut submitted_headers = SubmittedHeaders::default(); + + for header in headers { + let id = ids.pop_front().expect("both collections have same size; qed"); + + let call = instance.build_unsigned_header_call(header); + let transaction = create_unsigned_submit_transaction(call); + + match self.submit_extrinsic(Bytes(transaction.encode())).await { + Ok(_) => submitted_headers.submitted.push(id), + Err(error) => { + submitted_headers.rejected.push(id); + submitted_headers.rejected.extend(ids); + submitted_headers.fatal_error = Some(error.into()); + break; + } + } + } + + submitted_headers + } +} + +/// A trait for RPC calls which are used to submit proof of Ethereum exchange transaction to a +/// Substrate runtime. These are typically calls which use a combination of other low-level RPC +/// calls. +#[async_trait] +pub trait SubmitEthereumExchangeTransactionProof { + /// Pre-verify Ethereum exchange transaction proof. + async fn verify_exchange_transaction_proof( + &self, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, + ) -> RpcResult; + /// Submits Ethereum exchange transaction proof to Substrate runtime. + async fn submit_exchange_transaction_proof( + &self, + params: RialtoSigningParams, + instance: Arc, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, + ) -> RpcResult<()>; +} + +#[async_trait] +impl SubmitEthereumExchangeTransactionProof for SubstrateClient { + async fn verify_exchange_transaction_proof( + &self, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, + ) -> RpcResult { + let call = EXCH_API_FILTER_TRANSACTION_PROOF.to_string(); + let data = Bytes(proof.encode()); + + let encoded_response = self.state_call(call, data, None).await?; + let is_allowed: bool = Decode::decode(&mut &encoded_response.0[..])?; + + Ok(is_allowed) + } + + async fn submit_exchange_transaction_proof( + &self, + params: RialtoSigningParams, + instance: Arc, + proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, + ) -> RpcResult<()> { + let account_id = params.signer.public().as_array_ref().clone().into(); + let nonce = self.next_account_index(account_id).await?; + + let call = instance.build_currency_exchange_call(proof); + let transaction = Rialto::sign_transaction(self, ¶ms.signer, nonce, call); + + let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + Ok(()) + } +} + +/// Create unsigned Substrate transaction for submitting Ethereum header. +fn create_unsigned_submit_transaction(call: rialto_runtime::Call) -> rialto_runtime::UncheckedExtrinsic { + rialto_runtime::UncheckedExtrinsic::new_unsigned(call) +} diff --git a/relays/ethereum/src/rpc.rs b/relays/ethereum/src/rpc.rs deleted file mode 100644 index ee463e38cecf5..0000000000000 --- a/relays/ethereum/src/rpc.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019-2020 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 . - -//! RPC Module - -#![warn(missing_docs)] -// The compiler doesn't think we're using the -// code from rpc_api! -#![allow(dead_code)] -#![allow(unused_variables)] -use std::result; - -use crate::rpc_errors::RpcError; -use crate::substrate_types::{ - Hash as SubstrateHash, Header as SubstrateHeader, Number as SubBlockNumber, SignedBlock as SubstrateBlock, -}; - -use async_trait::async_trait; -use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; -use relay_ethereum_client::types::{Bytes, HeaderId as EthereumHeaderId}; - -type Result = result::Result; -type GrandpaAuthorityList = Vec; - -jsonrpsee::rpc_api! { - pub(crate) Substrate { - #[rpc(method = "chain_getHeader", positional_params)] - fn chain_get_header(block_hash: Option) -> SubstrateHeader; - #[rpc(method = "chain_getBlock", positional_params)] - fn chain_get_block(block_hash: Option) -> SubstrateBlock; - #[rpc(method = "chain_getBlockHash", positional_params)] - fn chain_get_block_hash(block_number: Option) -> SubstrateHash; - #[rpc(method = "system_accountNextIndex", positional_params)] - fn system_account_next_index(account_id: node_primitives::AccountId) -> node_primitives::Index; - #[rpc(method = "author_submitExtrinsic", positional_params)] - fn author_submit_extrinsic(extrinsic: Bytes) -> SubstrateHash; - #[rpc(method = "state_call", positional_params)] - fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; - } -} - -/// The API for the supported Substrate RPC methods. -#[async_trait] -pub trait SubstrateRpc { - /// Returns the best Substrate header. - async fn best_header(&self) -> Result; - /// Get a Substrate block from its hash. - async fn get_block(&self, block_hash: Option) -> Result; - /// Get a Substrate header by its hash. - async fn header_by_hash(&self, hash: SubstrateHash) -> Result; - /// Get a Substrate block hash by its number. - async fn block_hash_by_number(&self, number: SubBlockNumber) -> Result; - /// Get a Substrate header by its number. - async fn header_by_number(&self, block_number: SubBlockNumber) -> Result; - /// Get the nonce of the given Substrate account. - /// - /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. - async fn next_account_index(&self, account: node_primitives::AccountId) -> Result; - /// Returns best Ethereum block that Substrate runtime knows of. - async fn best_ethereum_block(&self) -> Result; - /// Returns best finalized Ethereum block that Substrate runtime knows of. - async fn best_ethereum_finalized_block(&self) -> Result; - /// Returns whether or not transactions receipts are required for Ethereum header submission. - async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> Result; - /// Returns whether or not the given Ethereum header is known to the Substrate runtime. - async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> Result; - /// Submit an extrinsic for inclusion in a block. - /// - /// Note: The given transaction does not need be SCALE encoded beforehand. - async fn submit_extrinsic(&self, transaction: Bytes) -> Result; - /// Get the GRANDPA authority set at given block. - async fn grandpa_authorities_set(&self, block: SubstrateHash) -> Result; -} diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/ethereum/src/rpc_errors.rs index 5e01031968fc7..9f7f14cf9a1f5 100644 --- a/relays/ethereum/src/rpc_errors.rs +++ b/relays/ethereum/src/rpc_errors.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use jsonrpsee::client::RequestError; use relay_ethereum_client::Error as EthereumNodeError; +use relay_substrate_client::Error as SubstrateNodeError; use relay_utils::MaybeConnectionError; /// Contains common errors that can occur when @@ -29,9 +29,6 @@ pub enum RpcError { Ethereum(EthereumNodeError), /// An error occured when interacting with a Substrate node. Substrate(SubstrateNodeError), - /// An error that can occur when making an HTTP request to - /// an JSON-RPC client. - Request(RequestError), } impl From for String { @@ -40,7 +37,6 @@ impl From for String { RpcError::Serialization(e) => e.to_string(), RpcError::Ethereum(e) => e.to_string(), RpcError::Substrate(e) => e.to_string(), - RpcError::Request(e) => e.to_string(), } } } @@ -63,12 +59,6 @@ impl From for RpcError { } } -impl From for RpcError { - fn from(err: RequestError) -> Self { - Self::Request(err) - } -} - impl From for RpcError { fn from(err: ethabi::Error) -> Self { Self::Ethereum(EthereumNodeError::ResponseParseFailed(format!("{}", err))) @@ -78,8 +68,8 @@ impl From for RpcError { impl MaybeConnectionError for RpcError { fn is_connection_error(&self) -> bool { match self { - RpcError::Request(RequestError::TransportError(_)) => true, RpcError::Ethereum(ref error) => error.is_connection_error(), + RpcError::Substrate(ref error) => error.is_connection_error(), _ => false, } } @@ -87,22 +77,6 @@ impl MaybeConnectionError for RpcError { impl From for RpcError { fn from(err: codec::Error) -> Self { - Self::Substrate(SubstrateNodeError::Decoding(err)) - } -} - -/// Errors that can occur only when interacting with -/// a Substrate node through RPC. -#[derive(Debug)] -pub enum SubstrateNodeError { - /// The response from the client could not be SCALE decoded. - Decoding(codec::Error), -} - -impl ToString for SubstrateNodeError { - fn to_string(&self) -> String { - match self { - Self::Decoding(e) => e.what().to_string(), - } + Self::Substrate(SubstrateNodeError::ResponseParseFailed(err)) } } diff --git a/relays/ethereum/src/substrate_client.rs b/relays/ethereum/src/substrate_client.rs deleted file mode 100644 index 4b1765aa2be05..0000000000000 --- a/relays/ethereum/src/substrate_client.rs +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2019-2020 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 . - -use crate::ethereum_sync_loop::QueuedEthereumHeader; -use crate::instances::BridgeInstance; -use crate::rpc::{Substrate, SubstrateRpc}; -use crate::rpc_errors::RpcError; -use crate::substrate_types::{Hash, Header as SubstrateHeader, Number, SignedBlock as SignedSubstrateBlock}; - -use async_trait::async_trait; -use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; -use codec::{Decode, Encode}; -use headers_relay::sync_types::SubmittedHeaders; -use jsonrpsee::raw::RawClient; -use jsonrpsee::transport::http::HttpTransportClient; -use jsonrpsee::Client; -use num_traits::Zero; -use relay_ethereum_client::types::{Bytes, HeaderId as EthereumHeaderId, H256}; -use relay_utils::HeaderId; -use sp_core::crypto::Pair; -use sp_runtime::traits::IdentifyAccount; -use std::collections::VecDeque; - -const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoHeaderApi_is_import_requires_receipts"; -const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoHeaderApi_is_known_block"; -const ETH_API_BEST_BLOCK: &str = "RialtoHeaderApi_best_block"; -const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoHeaderApi_finalized_block"; -const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "RialtoCurrencyExchangeApi_filter_transaction_proof"; -const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; - -type RpcResult = std::result::Result; -type GrandpaAuthorityList = Vec; - -/// Substrate connection params. -#[derive(Debug, Clone)] -pub struct SubstrateConnectionParams { - /// Substrate RPC host. - pub host: String, - /// Substrate RPC port. - pub port: u16, -} - -impl Default for SubstrateConnectionParams { - fn default() -> Self { - SubstrateConnectionParams { - host: "localhost".into(), - port: 9933, - } - } -} - -/// Substrate signing params. -#[derive(Clone)] -pub struct SubstrateSigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl std::fmt::Debug for SubstrateSigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} - -impl Default for SubstrateSigningParams { - fn default() -> Self { - SubstrateSigningParams { - signer: sp_keyring::AccountKeyring::Alice.pair(), - } - } -} - -/// Substrate client type. -pub struct SubstrateRpcClient { - /// Substrate RPC client. - client: Client, - /// Genesis block hash. - genesis_hash: H256, - /// Instance of the bridge pallet being synchronized. - instance: Box, -} - -impl SubstrateRpcClient { - /// Returns client that is able to call RPCs on Substrate node. - pub async fn new(params: SubstrateConnectionParams, instance: Box) -> RpcResult { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - let raw_client = RawClient::new(transport); - let client: Client = raw_client.into(); - - let number: Number = Zero::zero(); - let genesis_hash = Substrate::chain_get_block_hash(&client, number).await?; - - Ok(Self { - client, - genesis_hash, - instance, - }) - } -} - -#[async_trait] -impl SubstrateRpc for SubstrateRpcClient { - async fn best_header(&self) -> RpcResult { - Ok(Substrate::chain_get_header(&self.client, None).await?) - } - - async fn get_block(&self, block_hash: Option) -> RpcResult { - Ok(Substrate::chain_get_block(&self.client, block_hash).await?) - } - - async fn header_by_hash(&self, block_hash: Hash) -> RpcResult { - Ok(Substrate::chain_get_header(&self.client, block_hash).await?) - } - - async fn block_hash_by_number(&self, number: Number) -> RpcResult { - Ok(Substrate::chain_get_block_hash(&self.client, number).await?) - } - - async fn header_by_number(&self, block_number: Number) -> RpcResult { - let block_hash = Self::block_hash_by_number(self, block_number).await?; - Ok(Self::header_by_hash(self, block_hash).await?) - } - - async fn next_account_index(&self, account: node_primitives::AccountId) -> RpcResult { - Ok(Substrate::system_account_next_index(&self.client, account).await?) - } - - async fn best_ethereum_block(&self) -> RpcResult { - let call = ETH_API_BEST_BLOCK.to_string(); - let data = Bytes(Vec::new()); - - let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; - - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); - Ok(best_header_id) - } - - async fn best_ethereum_finalized_block(&self) -> RpcResult { - let call = ETH_API_BEST_FINALIZED_BLOCK.to_string(); - let data = Bytes(Vec::new()); - - let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; - - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); - Ok(best_header_id) - } - - async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult { - let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); - let data = Bytes(header.encode()); - - let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let receipts_required: bool = Decode::decode(&mut &encoded_response.0[..])?; - - Ok(receipts_required) - } - - // The Substrate module could prune old headers. So this function could return false even - // if header is synced. And we'll mark corresponding Ethereum header as Orphan. - // - // But when we read the best header from Substrate next time, we will know that - // there's a better header. This Orphan will either be marked as synced, or - // eventually pruned. - async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult { - let call = ETH_API_IS_KNOWN_BLOCK.to_string(); - let data = Bytes(header_id.1.encode()); - - let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let is_known_block: bool = Decode::decode(&mut &encoded_response.0[..])?; - - Ok(is_known_block) - } - - async fn submit_extrinsic(&self, transaction: Bytes) -> RpcResult { - let tx_hash = Substrate::author_submit_extrinsic(&self.client, transaction).await?; - log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); - Ok(tx_hash) - } - - async fn grandpa_authorities_set(&self, block: Hash) -> RpcResult { - let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); - let data = Bytes(Vec::new()); - - let encoded_response = Substrate::state_call(&self.client, call, data, Some(block)).await?; - let authority_list = encoded_response.0; - - Ok(authority_list) - } -} - -/// A trait for RPC calls which are used to submit Ethereum headers to a Substrate -/// runtime. These are typically calls which use a combination of other low-level RPC -/// calls. -#[async_trait] -pub trait SubmitEthereumHeaders: SubstrateRpc { - /// Submits Ethereum header to Substrate runtime. - async fn submit_ethereum_headers( - &self, - params: SubstrateSigningParams, - headers: Vec, - sign_transactions: bool, - ) -> SubmittedHeaders; - - /// Submits signed Ethereum header to Substrate runtime. - async fn submit_signed_ethereum_headers( - &self, - params: SubstrateSigningParams, - headers: Vec, - ) -> SubmittedHeaders; - - /// Submits unsigned Ethereum header to Substrate runtime. - async fn submit_unsigned_ethereum_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders; -} - -#[async_trait] -impl SubmitEthereumHeaders for SubstrateRpcClient { - async fn submit_ethereum_headers( - &self, - params: SubstrateSigningParams, - headers: Vec, - sign_transactions: bool, - ) -> SubmittedHeaders { - if sign_transactions { - self.submit_signed_ethereum_headers(params, headers).await - } else { - self.submit_unsigned_ethereum_headers(headers).await - } - } - - async fn submit_signed_ethereum_headers( - &self, - params: SubstrateSigningParams, - headers: Vec, - ) -> SubmittedHeaders { - let ids = headers.iter().map(|header| header.id()).collect(); - let submission_result = async { - let account_id = params.signer.public().as_array_ref().clone().into(); - let nonce = self.next_account_index(account_id).await?; - - let call = self.instance.build_signed_header_call(headers); - let transaction = create_signed_submit_transaction(call, ¶ms.signer, nonce, self.genesis_hash); - let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; - Ok(()) - } - .await; - - match submission_result { - Ok(_) => SubmittedHeaders { - submitted: ids, - incomplete: Vec::new(), - rejected: Vec::new(), - fatal_error: None, - }, - Err(error) => SubmittedHeaders { - submitted: Vec::new(), - incomplete: Vec::new(), - rejected: ids, - fatal_error: Some(error), - }, - } - } - - async fn submit_unsigned_ethereum_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders { - let mut ids = headers.iter().map(|header| header.id()).collect::>(); - let mut submitted_headers = SubmittedHeaders::default(); - - for header in headers { - let id = ids.pop_front().expect("both collections have same size; qed"); - - let call = self.instance.build_unsigned_header_call(header); - let transaction = create_unsigned_submit_transaction(call); - - match self.submit_extrinsic(Bytes(transaction.encode())).await { - Ok(_) => submitted_headers.submitted.push(id), - Err(error) => { - submitted_headers.rejected.push(id); - submitted_headers.rejected.extend(ids); - submitted_headers.fatal_error = Some(error); - break; - } - } - } - - submitted_headers - } -} - -/// A trait for RPC calls which are used to submit proof of Ethereum exchange transaction to a -/// Substrate runtime. These are typically calls which use a combination of other low-level RPC -/// calls. -#[async_trait] -pub trait SubmitEthereumExchangeTransactionProof: SubstrateRpc { - /// Pre-verify Ethereum exchange transaction proof. - async fn verify_exchange_transaction_proof( - &self, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult; - /// Submits Ethereum exchange transaction proof to Substrate runtime. - async fn submit_exchange_transaction_proof( - &self, - params: SubstrateSigningParams, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult<()>; -} - -#[async_trait] -impl SubmitEthereumExchangeTransactionProof for SubstrateRpcClient { - async fn verify_exchange_transaction_proof( - &self, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult { - let call = EXCH_API_FILTER_TRANSACTION_PROOF.to_string(); - let data = Bytes(proof.encode()); - - let encoded_response = Substrate::state_call(&self.client, call, data, None).await?; - let is_allowed: bool = Decode::decode(&mut &encoded_response.0[..])?; - - Ok(is_allowed) - } - - async fn submit_exchange_transaction_proof( - &self, - params: SubstrateSigningParams, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult<()> { - let account_id = params.signer.public().as_array_ref().clone().into(); - let nonce = self.next_account_index(account_id).await?; - - let call = self.instance.build_currency_exchange_call(proof); - let transaction = create_signed_transaction(call, ¶ms.signer, nonce, self.genesis_hash); - - let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; - Ok(()) - } -} - -/// Create signed Substrate transaction for submitting Ethereum headers. -fn create_signed_submit_transaction( - signed_call: rialto_runtime::Call, - signer: &sp_core::sr25519::Pair, - index: node_primitives::Index, - genesis_hash: H256, -) -> rialto_runtime::UncheckedExtrinsic { - create_signed_transaction(signed_call, signer, index, genesis_hash) -} - -/// Create unsigned Substrate transaction for submitting Ethereum header. -fn create_unsigned_submit_transaction(call: rialto_runtime::Call) -> rialto_runtime::UncheckedExtrinsic { - rialto_runtime::UncheckedExtrinsic::new_unsigned(call) -} - -/// Create signed Substrate transaction. -fn create_signed_transaction( - function: rialto_runtime::Call, - signer: &sp_core::sr25519::Pair, - index: node_primitives::Index, - genesis_hash: H256, -) -> rialto_runtime::UncheckedExtrinsic { - let extra = |i: node_primitives::Index, f: node_primitives::Balance| { - ( - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), - frame_system::CheckNonce::::from(i), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(f), - ) - }; - let raw_payload = rialto_runtime::SignedPayload::from_raw( - function, - extra(index, 0), - ( - rialto_runtime::VERSION.spec_version, - rialto_runtime::VERSION.transaction_version, - genesis_hash, - genesis_hash, - (), - (), - (), - ), - ); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); - let (function, extra, _) = raw_payload.deconstruct(); - - rialto_runtime::UncheckedExtrinsic::new_signed(function, signer.into_account(), signature.into(), extra) -} diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 8c3e0fb91d193..a3f525f11100e 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -14,29 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Substrate -> Ethereum synchronization. +//! Rialto-Substrate -> Ethereum PoA synchronization. use crate::ethereum_client::EthereumHighLevelRpc; -use crate::instances::BridgeInstance; -use crate::rpc::SubstrateRpc; use crate::rpc_errors::RpcError; -use crate::substrate_client::{SubstrateConnectionParams, SubstrateRpcClient}; -use crate::substrate_types::{ - GrandpaJustification, Hash, Number, QueuedSubstrateHeader, SubstrateHeaderId, SubstrateHeadersSyncPipeline, - SubstrateSyncHeader as Header, -}; use async_trait::async_trait; +use codec::Encode; use headers_relay::{ sync::HeadersSyncParams, sync_loop::{SourceClient, TargetClient}, - sync_types::{SourceHeader, SubmittedHeaders}, + sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, }; use relay_ethereum_client::{ types::Address, Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, }; +use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; +use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; use relay_utils::metrics::MetricsParams; +use sp_runtime::Justification; use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; @@ -71,18 +68,39 @@ pub struct SubstrateSyncParams { pub sync_params: HeadersSyncParams, /// Metrics parameters. pub metrics_params: Option, - /// Instance of the bridge pallet being synchronized. - pub instance: Box, } +/// Substrate synchronization pipeline. +#[derive(Clone, Copy, Debug)] +#[cfg_attr(test, derive(PartialEq))] +pub struct SubstrateHeadersSyncPipeline; + +impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { + const SOURCE_NAME: &'static str = "Substrate"; + const TARGET_NAME: &'static str = "Ethereum"; + + type Hash = rialto_runtime::Hash; + type Number = rialto_runtime::BlockNumber; + type Header = RialtoSyncHeader; + type Extra = (); + type Completion = Justification; + + fn estimate_size(source: &QueuedHeader) -> usize { + source.header().encode().len() + } +} + +/// Queued substrate header ID. +pub type QueuedRialtoHeader = QueuedHeader; + /// Substrate client as headers source. struct SubstrateHeadersSource { /// Substrate node client. - client: SubstrateRpcClient, + client: SubstrateClient, } impl SubstrateHeadersSource { - fn new(client: SubstrateRpcClient) -> Self { + fn new(client: SubstrateClient) -> Self { Self { client } } } @@ -91,22 +109,30 @@ impl SubstrateHeadersSource { impl SourceClient for SubstrateHeadersSource { type Error = RpcError; - async fn best_block_number(&self) -> Result { + async fn best_block_number(&self) -> Result { Ok(self.client.best_header().await?.number) } - async fn header_by_hash(&self, hash: Hash) -> Result { - self.client.header_by_hash(hash).await.map(Into::into) + async fn header_by_hash(&self, hash: rialto_runtime::Hash) -> Result { + self.client + .header_by_hash(hash) + .await + .map(Into::into) + .map_err(Into::into) } - async fn header_by_number(&self, number: Number) -> Result { - self.client.header_by_number(number).await.map(Into::into) + async fn header_by_number(&self, number: rialto_runtime::BlockNumber) -> Result { + self.client + .header_by_number(number) + .await + .map(Into::into) + .map_err(Into::into) } async fn header_completion( &self, - id: SubstrateHeaderId, - ) -> Result<(SubstrateHeaderId, Option), Self::Error> { + id: RialtoHeaderId, + ) -> Result<(RialtoHeaderId, Option), Self::Error> { let hash = id.1; let signed_block = self.client.get_block(Some(hash)).await?; let grandpa_justification = signed_block.justification; @@ -116,9 +142,9 @@ impl SourceClient for SubstrateHeadersSource { async fn header_extra( &self, - id: SubstrateHeaderId, - _header: QueuedSubstrateHeader, - ) -> Result<(SubstrateHeaderId, ()), Self::Error> { + id: RialtoHeaderId, + _header: QueuedRialtoHeader, + ) -> Result<(RialtoHeaderId, ()), Self::Error> { Ok((id, ())) } } @@ -147,38 +173,35 @@ impl EthereumHeadersTarget { impl TargetClient for EthereumHeadersTarget { type Error = RpcError; - async fn best_header_id(&self) -> Result { + async fn best_header_id(&self) -> Result { self.client.best_substrate_block(self.contract).await } - async fn is_known_header(&self, id: SubstrateHeaderId) -> Result<(SubstrateHeaderId, bool), Self::Error> { + async fn is_known_header(&self, id: RialtoHeaderId) -> Result<(RialtoHeaderId, bool), Self::Error> { self.client.substrate_header_known(self.contract, id).await } - async fn submit_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders { + async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { self.client .submit_substrate_headers(self.sign_params.clone(), self.contract, headers) .await } - async fn incomplete_headers_ids(&self) -> Result, Self::Error> { + async fn incomplete_headers_ids(&self) -> Result, Self::Error> { self.client.incomplete_substrate_headers(self.contract).await } async fn complete_header( &self, - id: SubstrateHeaderId, - completion: GrandpaJustification, - ) -> Result { + id: RialtoHeaderId, + completion: Justification, + ) -> Result { self.client .complete_substrate_header(self.sign_params.clone(), self.contract, id, completion) .await } - async fn requires_extra(&self, header: QueuedSubstrateHeader) -> Result<(SubstrateHeaderId, bool), Self::Error> { + async fn requires_extra(&self, header: QueuedRialtoHeader) -> Result<(RialtoHeaderId, bool), Self::Error> { Ok((header.header().id(), false)) } } @@ -192,11 +215,10 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { eth_contract_address, sync_params, metrics_params, - instance, } = params; let eth_client = EthereumClient::new(eth_params); - let sub_client = async_std::task::block_on(async { SubstrateRpcClient::new(sub_params, instance).await })?; + let sub_client = async_std::task::block_on(async { SubstrateClient::::new(sub_params).await })?; let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); diff --git a/relays/ethereum/src/substrate_types.rs b/relays/ethereum/src/substrate_types.rs index 793358be03a47..b88f383139385 100644 --- a/relays/ethereum/src/substrate_types.rs +++ b/relays/ethereum/src/substrate_types.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// Copyright 2020 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 @@ -14,86 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use codec::Encode; -use headers_relay::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}; -use relay_utils::HeaderId; +//! Converting between Ethereum headers and bridge module types. -pub use bp_eth_poa::{ - Address, AuraHeader as SubstrateEthereumHeader, Bloom, Bytes, LogEntry as SubstrateEthereumLogEntry, - Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, H256, U256, +use bp_eth_poa::{ + AuraHeader as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, + TransactionOutcome as SubstrateEthereumTransactionOutcome, }; use relay_ethereum_client::types::{ Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, }; -/// Substrate header hash. -pub type Hash = rialto_runtime::Hash; - -/// Substrate header number. -pub type Number = rialto_runtime::BlockNumber; - -/// Substrate header type. -pub type Header = rialto_runtime::Header; - -/// Substrate header type used in headers sync. -#[derive(Clone, Debug, PartialEq)] -pub struct SubstrateSyncHeader(Header); - -impl std::ops::Deref for SubstrateSyncHeader { - type Target = Header; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// Substrate signed block type. -pub type SignedBlock = rialto_runtime::SignedBlock; - -/// GRANDPA justification. -pub type GrandpaJustification = Vec; - -/// Substrate header ID. -pub type SubstrateHeaderId = HeaderId; - -/// Queued substrate header ID. -pub type QueuedSubstrateHeader = QueuedHeader; - -/// Substrate synchronization pipeline. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct SubstrateHeadersSyncPipeline; - -impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { - const SOURCE_NAME: &'static str = "Substrate"; - const TARGET_NAME: &'static str = "Ethereum"; - - type Hash = rialto_runtime::Hash; - type Number = rialto_runtime::BlockNumber; - type Header = SubstrateSyncHeader; - type Extra = (); - type Completion = GrandpaJustification; - - fn estimate_size(source: &QueuedHeader) -> usize { - source.header().encode().len() - } -} - -impl From
for SubstrateSyncHeader { - fn from(header: Header) -> Self { - Self(header) - } -} - -impl SourceHeader for SubstrateSyncHeader { - fn id(&self) -> SubstrateHeaderId { - HeaderId(self.number, self.hash()) - } - - fn parent_id(&self) -> SubstrateHeaderId { - HeaderId(self.number - 1, self.parent_hash) - } -} - /// Convert Ethereum header into Ethereum header for Substrate. pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEthereumHeader { SubstrateEthereumHeader { diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml new file mode 100644 index 0000000000000..cd142200a0913 --- /dev/null +++ b/relays/millau-client/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "relay-millau-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +millau-runtime = { path = "../../bin/millau-runtime" } +substrate-client = { path = "../substrate-client" } diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs new file mode 100644 index 0000000000000..c05fad91ac0de --- /dev/null +++ b/relays/millau-client/src/lib.rs @@ -0,0 +1,33 @@ +// Copyright 2019-2020 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 . + +//! Types used to connect to the Millau-Substrate chain. + +use relay_substrate_client::Chain; + +/// Millau chain definition. +#[derive(Debug, Clone, Copy)] +pub struct Millau; + +impl Chain for Millau { + type BlockNumber = millau_runtime::BlockNumber; + type Hash = millau_runtime::Hash; + type Header = millau_runtime::Header; + type AccountId = millau_runtime::AccountId; + type Index = millau_runtime::Index; + type SignedBlock = millau_runtime::SignedBlock; + type Call = rialto_runtime::Call; +} diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml new file mode 100644 index 0000000000000..5f5fef38c36e9 --- /dev/null +++ b/relays/rialto-client/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "relay-rialto-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.4" } +headers-relay = { path = "../headers-relay" } +relay-substrate-client = { path = "../substrate-client" } +relay-utils = { path = "../utils" } + +# Supported Chains + +rialto-runtime = { path = "../../bin/rialto-runtime" } + +# Substrate Dependencies + +frame-system = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +pallet-transaction-payment = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-core = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-keyring = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs new file mode 100644 index 0000000000000..4db86ae9e3c55 --- /dev/null +++ b/relays/rialto-client/src/lib.rs @@ -0,0 +1,132 @@ +// Copyright 2019-2020 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 . + +//! Types used to connect to the Rialto-Substrate chain. + +use codec::Encode; +use headers_relay::sync_types::SourceHeader; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use sp_core::Pair; +use sp_runtime::{ + generic::SignedPayload, + traits::{Header as HeaderT, IdentifyAccount}, +}; + +/// Rialto header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Rialto chain definition +#[derive(Debug, Clone, Copy)] +pub struct Rialto; + +impl Chain for Rialto { + type BlockNumber = rialto_runtime::BlockNumber; + type Hash = rialto_runtime::Hash; + type Header = rialto_runtime::Header; + type AccountId = rialto_runtime::AccountId; + type Index = rialto_runtime::Index; + type SignedBlock = rialto_runtime::SignedBlock; + type Call = rialto_runtime::Call; +} + +impl TransactionSignScheme for Rialto { + type Chain = Rialto; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = rialto_runtime::UncheckedExtrinsic; + + fn sign_transaction( + client: &Client, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::from_raw( + call, + ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::::from(signer_nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ), + ( + rialto_runtime::VERSION.spec_version, + rialto_runtime::VERSION.transaction_version, + *client.genesis_hash(), + *client.genesis_hash(), + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + rialto_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + } +} + +/// Rialto signing params. +#[derive(Clone)] +pub struct SigningParams { + /// Substrate transactions signer. + pub signer: sp_core::sr25519::Pair, +} + +impl std::fmt::Debug for SigningParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.signer.public()) + } +} + +impl Default for SigningParams { + fn default() -> Self { + SigningParams { + signer: sp_keyring::AccountKeyring::Alice.pair(), + } + } +} + +/// Rialto header type used in headers sync. +#[derive(Clone, Debug, PartialEq)] +pub struct SyncHeader(rialto_runtime::Header); + +impl std::ops::Deref for SyncHeader { + type Target = rialto_runtime::Header; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for SyncHeader { + fn from(header: rialto_runtime::Header) -> Self { + Self(header) + } +} + +impl SourceHeader for SyncHeader { + fn id(&self) -> HeaderId { + relay_utils::HeaderId(*self.number(), self.hash()) + } + + fn parent_id(&self) -> HeaderId { + relay_utils::HeaderId(*self.number() - 1, *self.parent_hash()) + } +} diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml new file mode 100644 index 0000000000000..fc92f568fcb57 --- /dev/null +++ b/relays/substrate-client/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "relay-substrate-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.4" } +headers-relay = { path = "../headers-relay" } +jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } +log = "0.4.11" +num-traits = "0.2" +relay-utils = { path = "../utils" } + +# Substrate Dependencies + +frame-support = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +frame-system = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-core = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-std = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs new file mode 100644 index 0000000000000..94126d811bc9c --- /dev/null +++ b/relays/substrate-client/src/chain.rs @@ -0,0 +1,87 @@ +// Copyright 2019-2020 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 . + +use crate::client::Client; + +use frame_support::Parameter; +use jsonrpsee::common::{DeserializeOwned, Serialize}; +use sp_core::Pair; +use sp_runtime::traits::{ + AtLeast32Bit, AtLeast32BitUnsigned, Bounded, CheckEqual, Dispatchable, Header as HeaderT, MaybeDisplay, + MaybeMallocSizeOf, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, +}; +use sp_std::fmt::Debug; + +/// Substrate-based chain from minimal relay-client point of view. +pub trait Chain { + /// The block number type used by the runtime. + type BlockNumber: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + MaybeDisplay + + AtLeast32BitUnsigned + + Default + + Bounded + + Copy + + sp_std::hash::Hash + + sp_std::str::FromStr + + MaybeMallocSizeOf; + /// The output of the `Hashing` function. + type Hash: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + MaybeDisplay + + SimpleBitOps + + Ord + + Default + + Copy + + CheckEqual + + sp_std::hash::Hash + + AsRef<[u8]> + + AsMut<[u8]> + + MaybeMallocSizeOf; + /// The block header. + type Header: Parameter + HeaderT; + /// The user account identifier type for the runtime. + type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; + /// Account index (aka nonce) type. This stores the number of previous transactions associated + /// with a sender account. + type Index: Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + AtLeast32Bit + Copy; + /// Block type. + type SignedBlock: Member + Serialize + DeserializeOwned; + /// The aggregated `Call` type. + type Call: Dispatchable + Debug; +} + +/// Substrate-based chain transactions signing scheme. +pub trait TransactionSignScheme { + /// Chain that this scheme is to be used. + type Chain: Chain; + /// Type of key pairs used to sign transactions. + type AccountKeyPair: Pair; + /// Signed transaction. + type SignedTransaction; + + /// Create transaction for given runtime call, signed by given account. + fn sign_transaction( + client: &Client, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction; +} diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs new file mode 100644 index 0000000000000..5d744a8920a3f --- /dev/null +++ b/relays/substrate-client/src/client.rs @@ -0,0 +1,135 @@ +// Copyright 2019-2020 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 . + +//! Substrate node client. + +use crate::chain::Chain; +use crate::rpc::Substrate; +use crate::{ConnectionParams, Result}; + +use jsonrpsee::common::DeserializeOwned; +use jsonrpsee::raw::RawClient; +use jsonrpsee::transport::http::HttpTransportClient; +use jsonrpsee::Client as RpcClient; +use num_traits::Zero; +use sp_core::Bytes; + +const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; + +/// Opaque GRANDPA authorities set. +pub type OpaqueGrandpaAuthoritiesSet = Vec; + +/// Substrate client type. +pub struct Client { + /// Substrate RPC client. + client: RpcClient, + /// Genesis block hash. + genesis_hash: C::Hash, +} + +impl std::fmt::Debug for Client { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("Client") + .field("genesis_hash", &self.genesis_hash) + .finish() + } +} + +impl Client { + /// Returns client that is able to call RPCs on Substrate node. + pub async fn new(params: ConnectionParams) -> Result { + let uri = format!("http://{}:{}", params.host, params.port); + let transport = HttpTransportClient::new(&uri); + let raw_client = RawClient::new(transport); + let client: RpcClient = raw_client.into(); + + let number: C::BlockNumber = Zero::zero(); + let genesis_hash = Substrate::::chain_get_block_hash(&client, number).await?; + + Ok(Self { client, genesis_hash }) + } +} + +impl Client +where + C::Header: DeserializeOwned, + C::Index: DeserializeOwned, +{ + /// Return hash of the genesis block. + pub fn genesis_hash(&self) -> &C::Hash { + &self.genesis_hash + } + + /// Returns the best Substrate header. + pub async fn best_header(&self) -> Result { + Ok(Substrate::::chain_get_header(&self.client, None).await?) + } + + /// Get a Substrate block from its hash. + pub async fn get_block(&self, block_hash: Option) -> Result { + Ok(Substrate::::chain_get_block(&self.client, block_hash).await?) + } + + /// Get a Substrate header by its hash. + pub async fn header_by_hash(&self, block_hash: C::Hash) -> Result { + Ok(Substrate::::chain_get_header(&self.client, block_hash).await?) + } + + /// Get a Substrate block hash by its number. + pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { + Ok(Substrate::::chain_get_block_hash(&self.client, number).await?) + } + + /// Get a Substrate header by its number. + pub async fn header_by_number(&self, block_number: C::BlockNumber) -> Result { + let block_hash = Self::block_hash_by_number(self, block_number).await?; + Ok(Self::header_by_hash(self, block_hash).await?) + } + + /// Get the nonce of the given Substrate account. + /// + /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. + pub async fn next_account_index(&self, account: C::AccountId) -> Result { + Ok(Substrate::::system_account_next_index(&self.client, account).await?) + } + + /// Submit an extrinsic for inclusion in a block. + /// + /// Note: The given transaction does not need be SCALE encoded beforehand. + pub async fn submit_extrinsic(&self, transaction: Bytes) -> Result { + let tx_hash = Substrate::::author_submit_extrinsic(&self.client, transaction).await?; + log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); + Ok(tx_hash) + } + + /// Get the GRANDPA authority set at given block. + pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result { + let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); + let data = Bytes(Vec::new()); + + let encoded_response = Substrate::::state_call(&self.client, call, data, Some(block)).await?; + let authority_list = encoded_response.0; + + Ok(authority_list) + } + + /// Execute runtime call at given block. + pub async fn state_call(&self, method: String, data: Bytes, at_block: Option) -> Result { + Substrate::::state_call(&self.client, method, data, at_block) + .await + .map_err(Into::into) + } +} diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs new file mode 100644 index 0000000000000..78b519c7b0ad0 --- /dev/null +++ b/relays/substrate-client/src/error.rs @@ -0,0 +1,55 @@ +// Copyright 2019-2020 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 . + +//! Substrate node RPC errors. + +use jsonrpsee::client::RequestError; +use relay_utils::MaybeConnectionError; + +/// Result type used by Substrate client. +pub type Result = std::result::Result; + +/// Errors that can occur only when interacting with +/// a Substrate node through RPC. +#[derive(Debug)] +pub enum Error { + /// An error that can occur when making an HTTP request to + /// an JSON-RPC client. + Request(RequestError), + /// The response from the client could not be SCALE decoded. + ResponseParseFailed(codec::Error), +} + +impl From for Error { + fn from(error: RequestError) -> Self { + Error::Request(error) + } +} + +impl MaybeConnectionError for Error { + fn is_connection_error(&self) -> bool { + matches!(*self, Error::Request(RequestError::TransportError(_))) + } +} + +impl ToString for Error { + fn to_string(&self) -> String { + match self { + Self::Request(e) => e.to_string(), + Self::ResponseParseFailed(e) => e.what().to_string(), + } + } +} diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs new file mode 100644 index 0000000000000..6bf38afdb8d3c --- /dev/null +++ b/relays/substrate-client/src/lib.rs @@ -0,0 +1,46 @@ +// Copyright 2019-2020 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 . + +//! Tools to interact with (Open) Ethereum node using RPC methods. + +#![warn(missing_docs)] + +mod chain; +mod client; +mod error; +mod rpc; + +pub use crate::chain::{Chain, TransactionSignScheme}; +pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet}; +pub use crate::error::{Error, Result}; + +/// Substrate connection params. +#[derive(Debug, Clone)] +pub struct ConnectionParams { + /// Substrate RPC host. + pub host: String, + /// Substrate RPC port. + pub port: u16, +} + +impl Default for ConnectionParams { + fn default() -> Self { + ConnectionParams { + host: "localhost".into(), + port: 9933, + } + } +} diff --git a/relays/substrate-client/src/rpc.rs b/relays/substrate-client/src/rpc.rs new file mode 100644 index 0000000000000..60141e0df660a --- /dev/null +++ b/relays/substrate-client/src/rpc.rs @@ -0,0 +1,43 @@ +// Copyright 2019-2020 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 . + +//! The most generic Substrate node RPC interface. + +// The compiler doesn't think we're using the +// code from rpc_api! +#![allow(dead_code)] +#![allow(unused_variables)] + +use crate::chain::Chain; + +use sp_core::Bytes; + +jsonrpsee::rpc_api! { + pub(crate) Substrate { + #[rpc(method = "chain_getHeader", positional_params)] + fn chain_get_header(block_hash: Option) -> C::Header; + #[rpc(method = "chain_getBlock", positional_params)] + fn chain_get_block(block_hash: Option) -> C::SignedBlock; + #[rpc(method = "chain_getBlockHash", positional_params)] + fn chain_get_block_hash(block_number: Option) -> C::Hash; + #[rpc(method = "system_accountNextIndex", positional_params)] + fn system_account_next_index(account_id: C::AccountId) -> C::Index; + #[rpc(method = "author_submitExtrinsic", positional_params)] + fn author_submit_extrinsic(extrinsic: Bytes) -> C::Hash; + #[rpc(method = "state_call", positional_params)] + fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; + } +} From d53fdff0dae6dde10cae4fef3c2a70b8f1caea66 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 30 Sep 2020 04:58:28 -0400 Subject: [PATCH 0168/1210] Integrate Grandpa Proof Checker into Substrate Pallet (#375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove the Substrate primitives crate The types here were only used in one place, the pallet itself. If other components start using these types we can considering moving them back into a standalone crate. * Start trying to integrate justification module * Make Substrate blocks configurable in Pallet * WIP: Try and generalize justification test helpers * Fix tests which use "real" justifications * Put common test helpers alongside mock code * Use common helper for creating headers * Remove usage of UintAuthorityId This change favours the use of the Ed25519Keyring authorities in order to keep things consistent with the tests. * Add documentation around config trait types * Make test header, hash, and number types consistent * Update modules/substrate/src/verifier.rs Co-authored-by: Svyatoslav Nikolsky * Update modules/substrate/src/lib.rs Co-authored-by: Tomasz Drwięga * Update modules/substrate/Cargo.toml Co-authored-by: Svyatoslav Nikolsky * Derive `RuntimeDebug` instead of `Debug` * Add `Paramter` as a trait constraint on config types Since we use these types as part of the dispatchable functions we should explicitly require this. * Enforce that hasher output matches expected hash type * Accept headers over indexes when making test justifications * Check that authority sets are valid * Make Clippy happy * Apply correct Clippy fix * Move justification code into primitives module * Use new module in verifier code * Add primitives module for Substrate test helpers * WIP * Move justification generation into test_helpers * Revert commits which move `justification` into primitives This reverts commit 03a381f0bc4a8dbe4785c30d42ab252a06ba876c. Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Tomasz Drwięga --- modules/substrate/Cargo.toml | 3 +- modules/substrate/src/justification.rs | 140 ++++++------ modules/substrate/src/lib.rs | 109 ++++++--- modules/substrate/src/mock.rs | 64 +++++- .../substrate/src/storage.rs | 12 +- modules/substrate/src/verifier.rs | 212 ++++++++++++------ 6 files changed, 366 insertions(+), 174 deletions(-) rename primitives/substrate/src/lib.rs => modules/substrate/src/storage.rs (87%) diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 2d16493a360e5..ae70b54af409c 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -9,10 +9,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../../primitives/header-chain", default-features = false } -bp-substrate = { path = "../../primitives/substrate", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } hash-db = { version = "0.15.2", default-features = false } serde = { version = "1.0", optional = true } +num-traits = { version = "0.2", default-features = false } [dependencies.codec] package = "parity-scale-codec" @@ -89,6 +89,7 @@ std = [ "finality-grandpa/std", "frame-support/std", "frame-system/std", + "num-traits/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/modules/substrate/src/justification.rs b/modules/substrate/src/justification.rs index 4887e180896bd..100049f810ef0 100644 --- a/modules/substrate/src/justification.rs +++ b/modules/substrate/src/justification.rs @@ -14,12 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Module for checking Grandpa Finality Proofs. +//! //! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin //! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. -// TODO: remove on actual use -#![allow(dead_code)] - use codec::Decode; use finality_grandpa::{voter_set::VoterSet, Chain, Error as GrandpaError}; use frame_support::RuntimeDebug; @@ -115,16 +114,21 @@ where Ok(()) } -/// GRANDPA justification of the bridged chain +/// A Grandpa Justification is a proof that a given header was finalized +/// at a certain height and with a certain set of authorities. +/// +/// This particular proof is used to prove that headers on a bridged chain +/// (so not our chain) have been finalized correctly. #[derive(Decode, RuntimeDebug)] #[cfg_attr(test, derive(codec::Encode))] -struct GrandpaJustification { +pub(crate) struct GrandpaJustification { round: u64, commit: finality_grandpa::Commit, votes_ancestries: Vec
, } /// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. +#[derive(RuntimeDebug)] struct AncestryChain { ancestry: BTreeMap, } @@ -170,56 +174,30 @@ where } #[cfg(test)] -mod tests { +pub(crate) mod tests { use super::*; + use crate::mock::helpers::*; use codec::Encode; use sp_core::H256; + use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; use sp_keyring::Ed25519Keyring; - use sp_runtime::traits::BlakeTwo256; const TEST_GRANDPA_ROUND: u64 = 1; const TEST_GRANDPA_SET_ID: SetId = 1; - type TestHeader = sp_runtime::generic::Header; - - fn header(index: u8) -> TestHeader { - TestHeader::new( - index as _, - Default::default(), - Default::default(), - if index == 0 { - Default::default() - } else { - header(index - 1).hash() - }, - Default::default(), - ) - } - - fn header_id(index: u8) -> (H256, u64) { - (header(index).hash(), index as _) - } - - fn authorities_set() -> VoterSet { - VoterSet::new(vec![ - (Ed25519Keyring::Alice.public().into(), 1), - (Ed25519Keyring::Bob.public().into(), 1), - (Ed25519Keyring::Charlie.public().into(), 1), - ]) - .unwrap() - } - - fn signed_precommit( + pub(crate) fn signed_precommit( signer: Ed25519Keyring, - target: (H256, u64), + target: HeaderId, + round: u64, + set_id: SetId, ) -> finality_grandpa::SignedPrecommit { let precommit = finality_grandpa::Precommit { target_hash: target.0, target_number: target.1, }; let encoded = sp_finality_grandpa::localized_payload( - TEST_GRANDPA_ROUND, - TEST_GRANDPA_SET_ID, + round, + set_id, &finality_grandpa::Message::Precommit(precommit.clone()), ); let signature = signer.sign(&encoded[..]).into(); @@ -230,26 +208,59 @@ mod tests { } } - fn make_justification_for_header_1() -> GrandpaJustification { + pub(crate) fn make_justification_for_header( + header: &TestHeader, + round: u64, + set_id: SetId, + authorities: &[(AuthorityId, AuthorityWeight)], + ) -> GrandpaJustification { + let (target_hash, target_number) = (header.hash(), *header.number()); + let mut precommits = vec![]; + let mut votes_ancestries = vec![]; + + // We want to make sure that the header included in the vote ancestries + // is actually related to our target header + let mut precommit_header = test_header(target_number + 1); + precommit_header.parent_hash = target_hash; + + // I'm using the same header for all the voters since it doesn't matter as long + // as they all vote on blocks _ahead_ of the one we're interested in finalizing + for (id, _weight) in authorities.iter() { + let signer = extract_keyring(&id); + let precommit = signed_precommit( + signer, + (precommit_header.hash(), *precommit_header.number()), + round, + set_id, + ); + precommits.push(precommit); + votes_ancestries.push(precommit_header.clone()); + } + GrandpaJustification { - round: TEST_GRANDPA_ROUND, + round, commit: finality_grandpa::Commit { - target_hash: header_id(1).0, - target_number: header_id(1).1, - precommits: vec![ - signed_precommit(Ed25519Keyring::Alice, header_id(2)), - signed_precommit(Ed25519Keyring::Bob, header_id(3)), - signed_precommit(Ed25519Keyring::Charlie, header_id(4)), - ], + target_hash, + target_number, + precommits, }, - votes_ancestries: vec![header(2), header(3), header(4)], + votes_ancestries, } } + pub(crate) fn make_justification_for_header_1() -> GrandpaJustification { + make_justification_for_header( + &test_header(1), + TEST_GRANDPA_ROUND, + TEST_GRANDPA_SET_ID, + &authority_list(), + ) + } + #[test] fn justification_with_invalid_encoding_rejected() { assert_eq!( - verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, authorities_set(), &[],), + verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &[],), Err(Error::JustificationDecode), ); } @@ -260,7 +271,7 @@ mod tests { verify_justification::( header_id(2), TEST_GRANDPA_SET_ID, - authorities_set(), + voter_set(), &make_justification_for_header_1().encode(), ), Err(Error::InvalidJustificationTarget), @@ -273,12 +284,7 @@ mod tests { justification.commit.precommits.clear(); assert_eq!( - verify_justification::( - header_id(1), - TEST_GRANDPA_SET_ID, - authorities_set(), - &justification.encode(), - ), + verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &justification.encode(),), Err(Error::InvalidJustificationCommit), ); } @@ -289,12 +295,7 @@ mod tests { justification.commit.precommits[0].signature = Default::default(); assert_eq!( - verify_justification::( - header_id(1), - TEST_GRANDPA_SET_ID, - authorities_set(), - &justification.encode(), - ), + verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &justification.encode(),), Err(Error::InvalidAuthoritySignature), ); } @@ -302,15 +303,10 @@ mod tests { #[test] fn justification_with_invalid_precommit_ancestry() { let mut justification = make_justification_for_header_1(); - justification.votes_ancestries.push(header(10)); + justification.votes_ancestries.push(test_header(10)); assert_eq!( - verify_justification::( - header_id(1), - TEST_GRANDPA_SET_ID, - authorities_set(), - &justification.encode(), - ), + verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &justification.encode(),), Err(Error::InvalidPrecommitAncestries), ); } @@ -321,7 +317,7 @@ mod tests { verify_justification::( header_id(1), TEST_GRANDPA_SET_ID, - authorities_set(), + voter_set(), &make_justification_for_header_1().encode(), ), Ok(()), diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 4fb9dbd3d5f1d..dfc3cb181156e 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -31,43 +31,100 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] -use bp_substrate::{AuthoritySet, ImportedHeader, ScheduledChange}; -use frame_support::{decl_error, decl_module, decl_storage, dispatch}; +use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; +use codec::{Codec, EncodeLike}; +use frame_support::{ + decl_error, decl_module, decl_storage, + dispatch::{DispatchResult, Parameter}, +}; use frame_system::ensure_signed; -use sp_runtime::traits::Header as HeaderT; -use sp_std::{marker::PhantomData, prelude::*}; +use num_traits::AsPrimitive; +use sp_runtime::traits::{ + AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, MaybeMallocSizeOf, MaybeSerializeDeserialize, + Member, SimpleBitOps, +}; +use sp_std::{fmt::Debug, marker::PhantomData, prelude::*, str::FromStr}; mod justification; +mod storage; mod storage_proof; mod verifier; #[cfg(test)] mod mock; -type Hash = ::Hash; -type Number = ::Number; - -pub trait Trait: frame_system::Trait {} +pub trait Trait: frame_system::Trait { + /// 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 BridgedHeader: Parameter + HeaderT; + + /// 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` trait is required by the Grandpa justification + // verifier, and is not usually part of a Substrate Header's Number type. + type BridgedBlockNumber: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + sp_std::hash::Hash + + Copy + + MaybeDisplay + + AtLeast32BitUnsigned + + Codec + + FromStr + + MaybeMallocSizeOf + + AsPrimitive; + + /// 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 BridgedBlockHash: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + sp_std::hash::Hash + + Ord + + Copy + + MaybeDisplay + + Default + + SimpleBitOps + + Codec + + AsRef<[u8]> + + AsMut<[u8]> + + MaybeMallocSizeOf + + EncodeLike; + + /// 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 BridgedBlockHasher: HashT; +} decl_storage! { trait Store for Module as SubstrateBridge { /// Hash of the best finalized header. - BestFinalized: T::Hash; + BestFinalized: T::BridgedBlockHash; /// Headers which have been imported into the pallet. - ImportedHeaders: map hasher(identity) T::Hash => Option>; + ImportedHeaders: map hasher(identity) T::BridgedBlockHash => Option>; /// The current Grandpa Authority set. CurrentAuthoritySet: AuthoritySet; /// The next scheduled authority set change. - /// // Grandpa doesn't require there to always be a pending change. In fact, most of the time // there will be no pending change available. - NextScheduledChange: Option>>; + NextScheduledChange: Option>; } add_extra_genesis { - config(initial_header): Option; + config(initial_header): Option; config(initial_authority_list): sp_finality_grandpa::AuthorityList; config(initial_set_id): sp_finality_grandpa::SetId; - config(first_scheduled_change): Option>>; + config(first_scheduled_change): Option>; build(|config| { assert!( !config.initial_authority_list.is_empty(), @@ -122,8 +179,8 @@ decl_module! { #[weight = 0] pub fn import_signed_header( origin, - header: T::Header, - ) -> dispatch::DispatchResult { + header: T::BridgedHeader, + ) -> DispatchResult { let _ = ensure_signed(origin)?; frame_support::debug::trace!(target: "sub-bridge", "Got header {:?}", header); @@ -147,9 +204,9 @@ decl_module! { #[weight = 0] pub fn finalize_header( origin, - hash: Hash, + hash: T::BridgedBlockHash, finality_proof: Vec, - ) -> dispatch::DispatchResult { + ) -> DispatchResult { let _ = ensure_signed(origin)?; frame_support::debug::trace!(target: "sub-bridge", "Got header hash {:?}", hash); @@ -220,28 +277,28 @@ impl PalletStorage { } impl BridgeStorage for PalletStorage { - type Header = T::Header; + type Header = T::BridgedHeader; - fn write_header(&mut self, header: &ImportedHeader) { + fn write_header(&mut self, header: &ImportedHeader) { let hash = header.header.hash(); >::insert(hash, header); } - fn best_finalized_header(&self) -> ImportedHeader { + fn best_finalized_header(&self) -> ImportedHeader { let hash = >::get(); self.header_by_hash(hash) .expect("A finalized header was added at genesis, therefore this must always exist") } - fn update_best_finalized(&self, hash: Hash) { + fn update_best_finalized(&self, hash: T::BridgedBlockHash) { >::put(hash) } - fn header_exists(&self, hash: Hash) -> bool { + fn header_exists(&self, hash: T::BridgedBlockHash) -> bool { >::contains_key(hash) } - fn header_by_hash(&self, hash: Hash) -> Option> { + fn header_by_hash(&self, hash: T::BridgedBlockHash) -> Option> { >::get(hash) } @@ -266,11 +323,11 @@ impl BridgeStorage for PalletStorage { } } - fn scheduled_set_change(&self) -> Option>> { + fn scheduled_set_change(&self) -> Option> { >::get() } - fn schedule_next_set_change(&self, next_change: ScheduledChange>) { + fn schedule_next_set_change(&self, next_change: ScheduledChange) { >::put(next_change) } } diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index 8cedca4ac4290..b6cc8bd31c1c8 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Mock Runtime for Substrate Pallet Testing. +//! +//! Includes some useful testing utilities in the `helpers` module. + #![cfg(test)] use crate::Trait; @@ -68,8 +72,66 @@ impl frame_system::Trait for TestRuntime { type SystemWeightInfo = (); } -impl Trait for TestRuntime {} +impl Trait for TestRuntime { + type BridgedHeader = ::Header; + type BridgedBlockNumber = ::BlockNumber; + type BridgedBlockHash = ::Hash; + type BridgedBlockHasher = ::Hashing; +} pub fn run_test(test: impl FnOnce() -> T) -> T { sp_io::TestExternalities::new(Default::default()).execute_with(test) } + +pub mod helpers { + use super::*; + use finality_grandpa::voter_set::VoterSet; + use sp_finality_grandpa::{AuthorityId, AuthorityList}; + use sp_keyring::Ed25519Keyring; + + pub type TestHeader = ::BridgedHeader; + pub type TestNumber = ::BridgedBlockNumber; + pub type TestHash = ::BridgedBlockHash; + pub type HeaderId = (TestHash, TestNumber); + + pub fn test_header(num: TestNumber) -> TestHeader { + let mut header = TestHeader::new_from_number(num); + header.parent_hash = if num == 0 { + Default::default() + } else { + test_header(num - 1).hash() + }; + + header + } + + pub fn header_id(index: u8) -> HeaderId { + (test_header(index.into()).hash(), index as _) + } + + pub fn extract_keyring(id: &AuthorityId) -> Ed25519Keyring { + let mut raw_public = [0; 32]; + raw_public.copy_from_slice(id.as_ref()); + Ed25519Keyring::from_raw_public(raw_public).unwrap() + } + + pub fn voter_set() -> VoterSet { + VoterSet::new(authority_list()).unwrap() + } + + pub fn authority_list() -> AuthorityList { + vec![(alice(), 1), (bob(), 1), (charlie(), 1)] + } + + pub fn alice() -> AuthorityId { + Ed25519Keyring::Alice.public().into() + } + + pub fn bob() -> AuthorityId { + Ed25519Keyring::Bob.public().into() + } + + pub fn charlie() -> AuthorityId { + Ed25519Keyring::Charlie.public().into() + } +} diff --git a/primitives/substrate/src/lib.rs b/modules/substrate/src/storage.rs similarity index 87% rename from primitives/substrate/src/lib.rs rename to modules/substrate/src/storage.rs index 0b63f0deefbda..e27c781e178a8 100644 --- a/primitives/substrate/src/lib.rs +++ b/modules/substrate/src/storage.rs @@ -14,13 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Primitives for the Substrate light client (a.k.a bridge) pallet. - -#![warn(missing_docs)] -#![cfg_attr(not(feature = "std"), no_std)] +//! Storage primitives for the Substrate light client (a.k.a bridge) pallet. +use codec::{Decode, Encode}; use core::default::Default; -use parity_scale_codec::{Decode, Encode}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, SetId}; @@ -75,8 +72,3 @@ impl core::ops::Deref for ImportedHeader { &self.header } } - -/// Prove that the given header was finalized by the given authority set. -pub fn check_finality_proof(_header: &H, _set: &AuthoritySet, _justification: &[u8]) -> bool { - true -} diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index aa0924508a961..3bf99df5a21f2 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -22,17 +22,21 @@ //! has been signed off by the correct Grandpa authorities, and also enact any authority set changes //! if required. +use crate::justification::verify_justification; +use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; use crate::BridgeStorage; -use bp_substrate::{check_finality_proof, AuthoritySet, ImportedHeader, ScheduledChange}; +use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::generic::OpaqueDigestItemId; use sp_runtime::traits::{CheckedAdd, Header as HeaderT, One}; +use sp_runtime::RuntimeDebug; use sp_std::{prelude::Vec, vec}; /// The finality proof used by the pallet. /// /// For a Substrate based chain using Grandpa this will /// be an encoded Grandpa Justification. +#[derive(RuntimeDebug)] pub struct FinalityProof(Vec); impl From<&[u8]> for FinalityProof { @@ -48,7 +52,7 @@ impl From> for FinalityProof { } /// Errors which can happen while importing a header. -#[derive(Debug, PartialEq)] +#[derive(RuntimeDebug, PartialEq)] pub enum ImportError { /// This header is older than our latest finalized block, thus not useful. OldHeader, @@ -60,25 +64,33 @@ pub enum ImportError { InvalidChildNumber, /// The height of the next authority set change overflowed. ScheduledHeightOverflow, + /// Received an authority set which was invalid in some way, such as + /// the authority weights being empty or overflowing the `AuthorityWeight` + /// type. + InvalidAuthoritySet, } /// Errors which can happen while verifying a headers finality. -#[derive(Debug, PartialEq)] +#[derive(RuntimeDebug, PartialEq)] pub enum FinalizationError { /// This header has never been imported by the pallet. UnknownHeader, - /// We were unable to prove finality for this header. - UnfinalizedHeader, /// Trying to prematurely import a justification PrematureJustification, /// We failed to verify this header's ancestry. AncestryCheckFailed, /// This header is older than our latest finalized block, thus not useful. OldHeader, + /// The given justification was not able to finalize the given header. + /// + /// There are several reasons why this might happen, such as the justification being + /// signed by the wrong authority set, being given alongside an unexpected header, + /// or failing ancestry checks. + InvalidJustification, } /// Used to verify imported headers and their finality status. -#[derive(Debug)] +#[derive(RuntimeDebug)] pub struct Verifier { pub storage: S, } @@ -87,6 +99,7 @@ impl Verifier where S: BridgeStorage
, H: HeaderT, + H::Number: finality_grandpa::BlockNumberOps, { /// Import a header to the pallet. /// @@ -126,6 +139,21 @@ where // Since we don't currently have a pending authority set change let's check if the header // contains a log indicating when the next change should be. if let Some(change) = find_scheduled_change(&header) { + let mut total_weight = 0u64; + + // We need to make sure that we don't overflow the `AuthorityWeight` type. + for (_id, weight) in &change.next_authorities { + total_weight = total_weight + .checked_add(*weight) + .ok_or(ImportError::InvalidAuthoritySet)?; + } + + // If none of the authorities have a weight associated with them the + // set is essentially empty. We don't want that. + if total_weight == 0 { + return Err(ImportError::InvalidAuthoritySet); + } + let next_set = AuthoritySet { authorities: change.next_authorities, set_id: self.storage.current_authority_set().set_id + 1, @@ -176,10 +204,18 @@ where } let current_authority_set = self.storage.current_authority_set(); - let is_finalized = check_finality_proof(&header, ¤t_authority_set, &proof.0); - if !is_finalized { - return Err(FinalizationError::UnfinalizedHeader); - } + let voter_set = VoterSet::new(current_authority_set.authorities).expect( + "This only fails if we have an invalid list of authorities. Since we + got this from storage it should always be valid, otherwise we have a bug.", + ); + verify_justification::( + (hash, *header.number()), + current_authority_set.set_id, + voter_set, + &proof.0, + ) + .map_err(|_| FinalizationError::InvalidJustification)?; + frame_support::debug::trace!(target: "sub-bridge", "Received valid justification for {:?}", header); frame_support::debug::trace!(target: "sub-bridge", "Checking ancestry for headers between {:?} and {:?}", last_finalized, header); let mut finalized_headers = @@ -279,37 +315,29 @@ fn find_scheduled_change(header: &H) -> Option::Header; - type TestNumber = ::Number; + use sp_finality_grandpa::{AuthorityId, SetId}; fn unfinalized_header(num: u64) -> ImportedHeader { ImportedHeader { - header: TestHeader::new_from_number(num), + header: test_header(num), requires_justification: false, is_finalized: false, } } - fn get_authorities(authorities: Vec<(u64, u64)>) -> AuthorityList { - authorities - .iter() - .map(|(id, weight)| (UintAuthorityId(*id).to_public_key::(), *weight)) - .collect() - } - fn schedule_next_change( - authorities: Vec<(u64, u64)>, - set_id: u64, + authorities: Vec, + set_id: SetId, height: TestNumber, ) -> ScheduledChange { - let authorities = get_authorities(authorities); + let authorities = authorities.into_iter().map(|id| (id, 1u64)).collect(); let authority_set = AuthoritySet::new(authorities, set_id); ScheduledChange { authority_set, height } } @@ -321,7 +349,7 @@ mod tests { ) -> Vec> { let mut imported_headers = vec![]; let genesis = ImportedHeader { - header: TestHeader::new_from_number(0), + header: test_header(0), requires_justification: false, is_finalized: true, }; @@ -331,11 +359,8 @@ mod tests { imported_headers.push(genesis); for (num, requires_justification, is_finalized) in headers { - let mut h = TestHeader::new_from_number(num); - h.parent_hash = imported_headers.last().unwrap().hash(); - let header = ImportedHeader { - header: h, + header: test_header(num), requires_justification, is_finalized, }; @@ -355,7 +380,7 @@ mod tests { storage.write_header(&parent); storage.update_best_finalized(parent.hash()); - let header = TestHeader::new_from_number(1); + let header = test_header(1); let mut verifier = Verifier { storage }; assert_err!(verifier.import_header(header), ImportError::OldHeader); }) @@ -381,7 +406,7 @@ mod tests { fn fails_to_import_header_twice() { run_test(|| { let storage = PalletStorage::::new(); - let header = TestHeader::new_from_number(1); + let header = test_header(1); >::put(header.hash()); let imported_header = ImportedHeader { @@ -400,7 +425,7 @@ mod tests { fn succesfully_imports_valid_but_unfinalized_header() { run_test(|| { let storage = PalletStorage::::new(); - let parent = TestHeader::new_from_number(1); + let parent = test_header(1); let parent_hash = parent.hash(); >::put(parent.hash()); @@ -411,8 +436,7 @@ mod tests { }; >::insert(parent_hash, &imported_header); - let mut header = TestHeader::new_from_number(2); - header.parent_hash = parent_hash; + let header = test_header(2); let mut verifier = Verifier { storage: storage.clone(), }; @@ -458,7 +482,7 @@ mod tests { // Need to give it a different parent_hash or else it'll be // related to our test genesis header - let mut bad_ancestor = TestHeader::new_from_number(0); + let mut bad_ancestor = test_header(0); bad_ancestor.parent_hash = [1u8; 32].into(); let bad_ancestor = ImportedHeader { header: bad_ancestor, @@ -484,7 +508,7 @@ mod tests { } // What if we have an "ancestor" that's newer than child? - let new_ancestor = TestHeader::new_from_number(5); + let new_ancestor = test_header(5); let new_ancestor = ImportedHeader { header: new_ancestor, requires_justification: false, @@ -497,24 +521,62 @@ mod tests { }) } + #[test] + fn doesnt_import_header_which_schedules_change_with_invalid_authority_set() { + use sp_runtime::{Digest, DigestItem}; + + run_test(|| { + let mut storage = PalletStorage::::new(); + let headers = vec![(1, false, false)]; + let _imported_headers = write_headers(&mut storage, headers); + let mut header = test_header(2); + + // This is an *invalid* authority set because the combined weight of the + // authorities is greater than `u64::MAX` + let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + next_authorities: vec![(alice(), u64::MAX), (bob(), u64::MAX)], + delay: 0, + }); + + header.digest = Digest:: { + logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], + }; + + let mut verifier = Verifier { storage }; + + assert_eq!( + verifier.import_header(header).unwrap_err(), + ImportError::InvalidAuthoritySet + ); + }) + } + #[test] fn finalizes_header_which_doesnt_enact_or_schedule_a_new_authority_set() { run_test(|| { let mut storage = PalletStorage::::new(); let headers = vec![(1, false, false)]; - let imported_headers = write_headers(&mut storage, headers); + let _imported_headers = write_headers(&mut storage, headers); // Nothing special about this header, yet Grandpa may have created a justification // for it since it does that periodically - let mut header = TestHeader::new_from_number(2); - header.parent_hash = imported_headers[1].hash(); + let header = test_header(2); + + let set_id = 1; + let authorities = authority_list(); + let authority_set = AuthoritySet::new(authorities.clone(), set_id); + storage.update_current_authority_set(authority_set); + + // We'll need this justification to finalize the header + let grandpa_round = 1; + let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); let mut verifier = Verifier { storage: storage.clone(), }; assert_ok!(verifier.import_header(header.clone())); - assert_ok!(verifier.import_finality_proof(header.hash(), vec![4, 2].into())); + assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); assert_eq!(storage.best_finalized_header().header, header); }) } @@ -525,15 +587,26 @@ mod tests { let mut storage = PalletStorage::::new(); let headers = vec![(1, false, false), (2, false, false)]; let imported_headers = write_headers(&mut storage, headers); + let header = test_header(3); + + let set_id = 1; + let authorities = authority_list(); + let authority_set = AuthoritySet { + authorities: authorities.clone(), + set_id, + }; + storage.update_current_authority_set(authority_set); - let mut header = TestHeader::new_from_number(3); - header.parent_hash = imported_headers[2].hash(); + let grandpa_round = 1; + let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); let mut verifier = Verifier { storage: storage.clone(), }; assert!(verifier.import_header(header.clone()).is_ok()); - assert!(verifier.import_finality_proof(header.hash(), vec![4, 2].into()).is_ok()); + assert!(verifier + .import_finality_proof(header.hash(), justification.into()) + .is_ok()); // Make sure we marked the our headers as finalized assert!(storage.header_by_hash(imported_headers[1].hash()).unwrap().is_finalized); @@ -550,21 +623,23 @@ mod tests { run_test(|| { let mut storage = PalletStorage::::new(); let headers = vec![(1, false, false)]; - let imported_headers = write_headers(&mut storage, headers); + let _imported_headers = write_headers(&mut storage, headers); - let set_id = 0; - let authorities = get_authorities(vec![(1, 1)]); - let initial_authority_set = AuthoritySet::new(authorities, set_id); + let set_id = 1; + let authorities = authority_list(); + let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id); storage.update_current_authority_set(initial_authority_set); // This header enacts an authority set change upon finalization - let mut header = TestHeader::new_from_number(2); - header.parent_hash = imported_headers[1].hash(); + let header = test_header(2); + + let grandpa_round = 1; + let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); // Schedule a change at the height of our header - let set_id = 1; + let set_id = 2; let height = *header.number(); - let authorities = vec![(2, 1)]; + let authorities = vec![alice()]; let change = schedule_next_change(authorities, set_id, height); storage.schedule_next_set_change(change.clone()); @@ -573,7 +648,7 @@ mod tests { }; assert_ok!(verifier.import_header(header.clone())); - assert_ok!(verifier.import_finality_proof(header.hash(), vec![4, 2].into())); + assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); assert_eq!(storage.best_finalized_header().header, header); // Make sure that we have updated the set now that we've finalized our header @@ -585,7 +660,7 @@ mod tests { fn importing_finality_proof_for_already_finalized_header_doesnt_work() { run_test(|| { let mut storage = PalletStorage::::new(); - let genesis = TestHeader::new_from_number(0); + let genesis = test_header(0); let genesis = ImportedHeader { header: genesis, @@ -627,14 +702,23 @@ mod tests { let headers = vec![(1, false, false)]; let imported_headers = write_headers(&mut storage, headers); + // Set up our initial authority set + let set_id = 1; + let authorities = authority_list(); + let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id); + storage.update_current_authority_set(initial_authority_set); + // This is header N - let mut header = TestHeader::new_from_number(2); - header.parent_hash = imported_headers[1].hash(); + let header = test_header(2); + + // Since we want to finalize N we need a justification for it + let grandpa_round = 1; + let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); // Schedule a change at height N - let set_id = 1; + let set_id = 2; let height = *header.number(); - let authorities = vec![(1, 1)]; + let authorities = vec![alice()]; let change = schedule_next_change(authorities, set_id, height); storage.schedule_next_set_change(change.clone()); @@ -651,17 +735,17 @@ mod tests { ); // Now we want to import some headers which are past N - let mut child = TestHeader::new_from_number(*header.number() + 1); - child.parent_hash = header.hash(); + let child = test_header(*header.number() + 1); assert!(verifier.import_header(child.clone()).is_ok()); - let mut grandchild = TestHeader::new_from_number(*child.number() + 1); - grandchild.parent_hash = child.hash(); + let grandchild = test_header(*child.number() + 1); assert!(verifier.import_header(grandchild).is_ok()); // Even though we're a few headers ahead we should still be able to import // a justification for header N - assert!(verifier.import_finality_proof(header.hash(), vec![4, 2].into()).is_ok()); + assert!(verifier + .import_finality_proof(header.hash(), justification.into()) + .is_ok()); // Some checks to make sure that our header has been correctly finalized let finalized_header = storage.header_by_hash(header.hash()).unwrap(); From 7395939b16fb2609ba46e25343d80a38acb05f55 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 30 Sep 2020 14:03:57 +0300 Subject: [PATCH 0169/1210] Substrate relay stub (#376) * substrate-relay: initial commit * MillauHeaderApi and RialtoHeaderApi * post-merge fixes + TODOs + compilation --- bin/millau-runtime/Cargo.toml | 2 + bin/millau-runtime/src/lib.rs | 4 +- bin/rialto-runtime/Cargo.toml | 4 + bin/rialto-runtime/src/lib.rs | 21 ++- primitives/millau/Cargo.toml | 22 +++ primitives/millau/src/lib.rs | 49 +++++++ primitives/rialto/Cargo.toml | 22 +++ primitives/rialto/src/lib.rs | 49 +++++++ relays/ethereum/src/substrate_sync_loop.rs | 63 +-------- relays/headers-relay/src/sync_types.rs | 8 +- relays/millau-client/Cargo.toml | 13 +- relays/millau-client/src/lib.rs | 36 ++++- relays/rialto-client/src/lib.rs | 9 ++ relays/substrate-client/Cargo.toml | 1 + relays/substrate-client/src/chain.rs | 33 ++++- relays/substrate-client/src/error.rs | 6 + relays/substrate-client/src/headers_source.rs | 99 ++++++++++++++ relays/substrate-client/src/lib.rs | 4 +- relays/substrate/Cargo.toml | 22 +++ relays/substrate/src/cli.rs | 65 +++++++++ relays/substrate/src/main.rs | 66 +++++++++ .../substrate/src/millau_headers_to_rialto.rs | 125 ++++++++++++++++++ 22 files changed, 652 insertions(+), 71 deletions(-) create mode 100644 primitives/millau/Cargo.toml create mode 100644 primitives/millau/src/lib.rs create mode 100644 primitives/rialto/Cargo.toml create mode 100644 primitives/rialto/src/lib.rs create mode 100644 relays/substrate-client/src/headers_source.rs create mode 100644 relays/substrate/Cargo.toml create mode 100644 relays/substrate/src/cli.rs create mode 100644 relays/substrate/src/main.rs create mode 100644 relays/substrate/src/millau_headers_to_rialto.rs diff --git a/bin/millau-runtime/Cargo.toml b/bin/millau-runtime/Cargo.toml index e766a58d790fd..fd24613039d84 100644 --- a/bin/millau-runtime/Cargo.toml +++ b/bin/millau-runtime/Cargo.toml @@ -8,6 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bp-millau = { path = "../../primitives/millau", default-features = false } hex-literal = "0.3" [dependencies.codec] @@ -217,6 +218,7 @@ git = "https://github.com/paritytech/substrate/" default = ["std"] std = [ "bp-message-lane/std", + "bp-millau/std", "codec/std", "frame-benchmarking/std", "frame-executive/std", diff --git a/bin/millau-runtime/src/lib.rs b/bin/millau-runtime/src/lib.rs index 394cb0d1c82b0..1adab7e6a2ec4 100644 --- a/bin/millau-runtime/src/lib.rs +++ b/bin/millau-runtime/src/lib.rs @@ -61,7 +61,7 @@ pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; /// An index to a block. -pub type BlockNumber = u32; +pub type BlockNumber = bp_millau::BlockNumber; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -81,7 +81,7 @@ pub type Balance = u128; pub type Index = u32; /// A hash of some data used by the chain. -pub type Hash = sp_core::H256; +pub type Hash = bp_millau::Hash; /// Digest item type. pub type DigestItem = generic::DigestItem; diff --git a/bin/rialto-runtime/Cargo.toml b/bin/rialto-runtime/Cargo.toml index 5ea4c9fc90238..495948486cbe2 100644 --- a/bin/rialto-runtime/Cargo.toml +++ b/bin/rialto-runtime/Cargo.toml @@ -8,6 +8,8 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bp-millau = { path = "../../primitives/millau", default-features = false } +bp-rialto = { path = "../../primitives/rialto", default-features = false } hex-literal = "0.3" [dependencies.codec] @@ -256,6 +258,8 @@ std = [ "bp-currency-exchange/std", "bp-eth-poa/std", "bp-message-lane/std", + "bp-millau/std", + "bp-rialto/std", "codec/std", "frame-benchmarking/std", "frame-executive/std", diff --git a/bin/rialto-runtime/src/lib.rs b/bin/rialto-runtime/src/lib.rs index f0e1e77154b7d..2d0c6fbb0c663 100644 --- a/bin/rialto-runtime/src/lib.rs +++ b/bin/rialto-runtime/src/lib.rs @@ -70,7 +70,7 @@ pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; /// An index to a block. -pub type BlockNumber = u32; +pub type BlockNumber = bp_rialto::BlockNumber; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -90,7 +90,7 @@ pub type Balance = u128; pub type Index = u32; /// A hash of some data used by the chain. -pub type Hash = sp_core::H256; +pub type Hash = bp_rialto::Hash; /// Digest item type. pub type DigestItem = generic::DigestItem; @@ -574,6 +574,23 @@ impl_runtime_apis! { } } + impl bp_millau::MillauHeaderApi for Runtime { + fn best_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + } + + fn finalized_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + } + + fn incomplete_headers() -> Vec<(bp_millau::BlockNumber, bp_millau::Hash)> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + } + + fn is_known_block(_hash: bp_millau::Hash) -> bool { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + } + } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml new file mode 100644 index 0000000000000..8e787996f501a --- /dev/null +++ b/primitives/millau/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "bp-millau" +description = "Primitives of Millau runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Substrate Based Dependencies +sp-api = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } +sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } +sp-std = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } + +[features] +default = ["std"] +std = [ + "sp-api/std", + "sp-core/std", + "sp-std/std", +] diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs new file mode 100644 index 0000000000000..214497d1e8580 --- /dev/null +++ b/primitives/millau/src/lib.rs @@ -0,0 +1,49 @@ +// Copyright 2019-2020 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_With_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use sp_std::prelude::*; + +/// Block number type used in Millau. +pub type BlockNumber = u32; + +/// Hash type used in Millau. +pub type Hash = sp_core::H256; + +sp_api::decl_runtime_apis! { + /// API for querying information about Millau headers from the Bridge Pallet instance. + /// + /// This API is implemented by runtimes that are bridging with Millau chain, not the + /// Millau runtime itself. + pub trait MillauHeaderApi { + /// Returns number and hash of the best block known to the bridge module. + /// + /// The caller should only submit an `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_block() -> (BlockNumber, Hash); + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (BlockNumber, Hash); + /// Returns numbers and hashes of headers that require finality proofs. + fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; + /// Returns true if header is known to the runtime. + fn is_known_block(hash: Hash) -> bool; + } +} diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml new file mode 100644 index 0000000000000..42f56fdae00d8 --- /dev/null +++ b/primitives/rialto/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "bp-rialto" +description = "Primitives of Rialto runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Substrate Based Dependencies +sp-api = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } +sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } +sp-std = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } + +[features] +default = ["std"] +std = [ + "sp-api/std", + "sp-core/std", + "sp-std/std", +] diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs new file mode 100644 index 0000000000000..f23e09c511499 --- /dev/null +++ b/primitives/rialto/src/lib.rs @@ -0,0 +1,49 @@ +// Copyright 2019-2020 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_With_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use sp_std::prelude::*; + +/// Block number type used in Rialto. +pub type BlockNumber = u32; + +/// Hash type used in Rialto. +pub type Hash = sp_core::H256; + +sp_api::decl_runtime_apis! { + /// API for querying information about Rialto headers from the Bridge Pallet instance. + /// + /// This API is implemented by runtimes that are bridging with Rialto chain, not the + /// Rialto runtime itself. + pub trait RialtoHeaderApi { + /// Returns number and hash of the best block known to the bridge module. + /// + /// The caller should only submit an `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_block() -> (BlockNumber, Hash); + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (BlockNumber, Hash); + /// Returns numbers and hashes of headers that require finality proofs. + fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; + /// Returns true if header is known to the runtime. + fn is_known_block(hash: Hash) -> bool; + } +} diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index a3f525f11100e..80d611a89c4fc 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -23,7 +23,7 @@ use async_trait::async_trait; use codec::Encode; use headers_relay::{ sync::HeadersSyncParams, - sync_loop::{SourceClient, TargetClient}, + sync_loop::TargetClient, sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, }; use relay_ethereum_client::{ @@ -31,7 +31,9 @@ use relay_ethereum_client::{ SigningParams as EthereumSigningParams, }; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; +use relay_substrate_client::{ + headers_source::HeadersSource, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, +}; use relay_utils::metrics::MetricsParams; use sp_runtime::Justification; @@ -93,61 +95,8 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { /// Queued substrate header ID. pub type QueuedRialtoHeader = QueuedHeader; -/// Substrate client as headers source. -struct SubstrateHeadersSource { - /// Substrate node client. - client: SubstrateClient, -} - -impl SubstrateHeadersSource { - fn new(client: SubstrateClient) -> Self { - Self { client } - } -} - -#[async_trait] -impl SourceClient for SubstrateHeadersSource { - type Error = RpcError; - - async fn best_block_number(&self) -> Result { - Ok(self.client.best_header().await?.number) - } - - async fn header_by_hash(&self, hash: rialto_runtime::Hash) -> Result { - self.client - .header_by_hash(hash) - .await - .map(Into::into) - .map_err(Into::into) - } - - async fn header_by_number(&self, number: rialto_runtime::BlockNumber) -> Result { - self.client - .header_by_number(number) - .await - .map(Into::into) - .map_err(Into::into) - } - - async fn header_completion( - &self, - id: RialtoHeaderId, - ) -> Result<(RialtoHeaderId, Option), Self::Error> { - let hash = id.1; - let signed_block = self.client.get_block(Some(hash)).await?; - let grandpa_justification = signed_block.justification; - - Ok((id, grandpa_justification)) - } - - async fn header_extra( - &self, - id: RialtoHeaderId, - _header: QueuedRialtoHeader, - ) -> Result<(RialtoHeaderId, ()), Self::Error> { - Ok((id, ())) - } -} +/// Rialto node as headers source. +type SubstrateHeadersSource = HeadersSource; /// Ethereum client as Substrate headers target. struct EthereumHeadersTarget { diff --git a/relays/headers-relay/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs index 21eec10c1e0d3..0dcb712c91800 100644 --- a/relays/headers-relay/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -43,19 +43,21 @@ pub enum HeaderStatus { } /// Headers synchronization pipeline. -pub trait HeadersSyncPipeline: Clone + Copy { +pub trait HeadersSyncPipeline: Clone + Copy + Send + Sync { /// Name of the headers source. const SOURCE_NAME: &'static str; /// Name of the headers target. const TARGET_NAME: &'static str; /// Headers we're syncing are identified by this hash. - type Hash: Eq + Clone + Copy + std::fmt::Debug + std::fmt::Display + std::hash::Hash; + type Hash: Eq + Clone + Copy + Send + Sync + std::fmt::Debug + std::fmt::Display + std::hash::Hash; /// Headers we're syncing are identified by this number. type Number: From + Ord + Clone + Copy + + Send + + Sync + std::fmt::Debug + std::fmt::Display + std::hash::Hash @@ -66,7 +68,7 @@ pub trait HeadersSyncPipeline: Clone + Copy { + num_traits::One + Into; /// Type of header that we're syncing. - type Header: Clone + std::fmt::Debug + PartialEq + SourceHeader; + type Header: Clone + std::fmt::Debug + PartialEq + SourceHeader + Send + Sync; /// Type of extra data for the header that we're receiving from the source node: /// 1) extra data is required for some headers; /// 2) target node may answer if it'll require extra data before header is submitted; diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index cd142200a0913..35b029ed3b7c8 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -6,5 +6,16 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +codec = { package = "parity-scale-codec", version = "1.3.4" } +headers-relay = { path = "../headers-relay" } +relay-substrate-client = { path = "../substrate-client" } +relay-utils = { path = "../utils" } + +# Supported Chains + millau-runtime = { path = "../../bin/millau-runtime" } -substrate-client = { path = "../substrate-client" } + +# Substrate Dependencies + +frame-system = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index c05fad91ac0de..a901be18eedb4 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -18,6 +18,12 @@ use relay_substrate_client::Chain; +use headers_relay::sync_types::SourceHeader; +use sp_runtime::traits::Header as HeaderT; + +/// Millau header id. +pub type HeaderId = relay_utils::HeaderId; + /// Millau chain definition. #[derive(Debug, Clone, Copy)] pub struct Millau; @@ -29,5 +35,33 @@ impl Chain for Millau { type AccountId = millau_runtime::AccountId; type Index = millau_runtime::Index; type SignedBlock = millau_runtime::SignedBlock; - type Call = rialto_runtime::Call; + type Call = millau_runtime::Call; +} + +/// Millau header type used in headers sync. +#[derive(Clone, Debug, PartialEq)] +pub struct SyncHeader(millau_runtime::Header); + +impl std::ops::Deref for SyncHeader { + type Target = millau_runtime::Header; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for SyncHeader { + fn from(header: millau_runtime::Header) -> Self { + Self(header) + } +} + +impl SourceHeader for SyncHeader { + fn id(&self) -> HeaderId { + relay_utils::HeaderId(*self.number(), self.hash()) + } + + fn parent_id(&self) -> HeaderId { + relay_utils::HeaderId(*self.number(), *self.parent_hash()) + } } diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs index 4db86ae9e3c55..2ad3526995ae3 100644 --- a/relays/rialto-client/src/lib.rs +++ b/relays/rialto-client/src/lib.rs @@ -89,6 +89,15 @@ pub struct SigningParams { pub signer: sp_core::sr25519::Pair, } +impl SigningParams { + /// Create signing params from SURI and password. + pub fn from_suri(suri: &str, password: Option<&str>) -> Result { + Ok(SigningParams { + signer: sp_core::sr25519::Pair::from_string(suri, password)?, + }) + } +} + impl std::fmt::Debug for SigningParams { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.signer.public()) diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index fc92f568fcb57..ae04b9dbeae70 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "1.3.4" } headers-relay = { path = "../headers-relay" } jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index 94126d811bc9c..174bbcb33d625 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -19,9 +19,13 @@ use crate::client::Client; use frame_support::Parameter; use jsonrpsee::common::{DeserializeOwned, Serialize}; use sp_core::Pair; -use sp_runtime::traits::{ - AtLeast32Bit, AtLeast32BitUnsigned, Bounded, CheckEqual, Dispatchable, Header as HeaderT, MaybeDisplay, - MaybeMallocSizeOf, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, +use sp_runtime::{ + generic::SignedBlock, + traits::{ + AtLeast32Bit, AtLeast32BitUnsigned, Bounded, CheckEqual, Dispatchable, Header as HeaderT, MaybeDisplay, + MaybeMallocSizeOf, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, + }, + Justification, }; use sp_std::fmt::Debug; @@ -63,11 +67,17 @@ pub trait Chain { /// with a sender account. type Index: Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + AtLeast32Bit + Copy; /// Block type. - type SignedBlock: Member + Serialize + DeserializeOwned; + type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. type Call: Dispatchable + Debug; } +/// Block with justification. +pub trait BlockWithJustification { + /// Return block justification, if known. + fn justification(&self) -> Option<&Justification>; +} + /// Substrate-based chain transactions signing scheme. pub trait TransactionSignScheme { /// Chain that this scheme is to be used. @@ -85,3 +95,18 @@ pub trait TransactionSignScheme { call: ::Call, ) -> Self::SignedTransaction; } + +/// Header type used by the chain. +pub type HeaderOf = ::Header; + +/// Hash type used by the chain. +pub type HashOf = ::Hash; + +/// Block number used by the chain. +pub type BlockNumberOf = ::BlockNumber; + +impl BlockWithJustification for SignedBlock { + fn justification(&self) -> Option<&Justification> { + self.justification.as_ref() + } +} diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index 78b519c7b0ad0..6f8c206d7dac3 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -45,6 +45,12 @@ impl MaybeConnectionError for Error { } } +impl From for String { + fn from(error: Error) -> String { + error.to_string() + } +} + impl ToString for Error { fn to_string(&self) -> String { match self { diff --git a/relays/substrate-client/src/headers_source.rs b/relays/substrate-client/src/headers_source.rs new file mode 100644 index 0000000000000..14be6e0e65cbb --- /dev/null +++ b/relays/substrate-client/src/headers_source.rs @@ -0,0 +1,99 @@ +// Copyright 2019-2020 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 . + +//! Default generic implementation of headers source for basic Substrate client. + +use crate::chain::{BlockWithJustification, Chain}; +use crate::client::Client; +use crate::error::Error; + +use async_trait::async_trait; +use headers_relay::{ + sync_loop::SourceClient, + sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, +}; +use jsonrpsee::common::DeserializeOwned; +use num_traits::Saturating; +use sp_runtime::{traits::Header as HeaderT, Justification}; +use std::marker::PhantomData; + +/// Substrate node as headers source. +pub struct HeadersSource { + client: Client, + _phantom: PhantomData

, +} + +impl HeadersSource { + /// Create new headers source using given client. + pub fn new(client: Client) -> Self { + HeadersSource { + client, + _phantom: Default::default(), + } + } +} + +#[async_trait] +impl SourceClient

for HeadersSource +where + C: Chain, + C::BlockNumber: Into + Saturating, + C::Header: DeserializeOwned + Into, + C::Index: DeserializeOwned, + P: HeadersSyncPipeline, + P::Header: SourceHeader, +{ + type Error = Error; + + async fn best_block_number(&self) -> Result { + Ok(*self.client.best_header().await?.number()) + } + + async fn header_by_hash(&self, hash: P::Hash) -> Result { + self.client + .header_by_hash(hash) + .await + .map(Into::into) + .map_err(Into::into) + } + + async fn header_by_number(&self, number: P::Number) -> Result { + self.client + .header_by_number(number) + .await + .map(Into::into) + .map_err(Into::into) + } + + async fn header_completion( + &self, + id: HeaderIdOf

, + ) -> Result<(HeaderIdOf

, Option), Self::Error> { + let hash = id.1; + let signed_block = self.client.get_block(Some(hash)).await?; + let grandpa_justification = signed_block.justification().cloned(); + + Ok((id, grandpa_justification)) + } + + async fn header_extra( + &self, + id: HeaderIdOf

, + _header: QueuedHeader

, + ) -> Result<(HeaderIdOf

, ()), Self::Error> { + Ok((id, ())) + } +} diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index 6bf38afdb8d3c..7e44653db8add 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -23,7 +23,9 @@ mod client; mod error; mod rpc; -pub use crate::chain::{Chain, TransactionSignScheme}; +pub mod headers_source; + +pub use crate::chain::{BlockNumberOf, BlockWithJustification, Chain, HashOf, HeaderOf, TransactionSignScheme}; pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml new file mode 100644 index 0000000000000..22809fc3c7ba4 --- /dev/null +++ b/relays/substrate/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "substrate-relay" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.2" +async-trait = "0.1.40" +bp-rialto = { path = "../../primitives/rialto" } +codec = { package = "parity-scale-codec", version = "1.3.4" } +futures = "0.3.5" +headers-relay = { path = "../headers-relay" } +log = "0.4.11" +messages-relay = { path = "../messages-relay" } +paste = "1.0" +relay-millau-client = { path = "../millau-client" } +relay-rialto-client = { path = "../rialto-client" } +relay-substrate-client = { path = "../substrate-client" } +sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +structopt = "0.3" diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs new file mode 100644 index 0000000000000..939863b5ca0a2 --- /dev/null +++ b/relays/substrate/src/cli.rs @@ -0,0 +1,65 @@ +// Copyright 2019-2020 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 . + +//! Deal with CLI args of substrate-to-substrate relay. + +use structopt::StructOpt; + +/// Parse relay CLI args. +pub fn parse_args() -> Command { + Command::from_args() +} + +/// Substrate-to-Substrate relay CLI args. +#[derive(StructOpt)] +#[structopt(about = "Substrate-to-Substrate relay")] +pub enum Command { + MillauHeadersToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + }, +} + +macro_rules! declare_chain_options { + ($chain:ident, $chain_prefix:ident) => { + paste::item! { + #[doc = $chain " connection params."] + #[derive(StructOpt)] + pub struct [<$chain ConnectionParams>] { + #[doc = "Connect to " $chain " node at given host."] + pub [<$chain_prefix _host>]: String, + #[doc = "Connect to " $chain " node at given port."] + pub [<$chain_prefix _port>]: u16, + } + + #[doc = $chain " signing params."] + #[derive(StructOpt)] + pub struct [<$chain SigningParams>] { + #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + pub [<$chain_prefix _signer>]: String, + #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + pub [<$chain_prefix _signer_password>]: Option, + } + } + }; +} + +declare_chain_options!(Rialto, rialto); +declare_chain_options!(Millau, millau); diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs new file mode 100644 index 0000000000000..a42d721759221 --- /dev/null +++ b/relays/substrate/src/main.rs @@ -0,0 +1,66 @@ +// Copyright 2019-2020 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 . + +//! Substrate-to-substrate relay entrypoint. + +#![warn(missing_docs)] + +use relay_rialto_client::SigningParams as RialtoSigningParams; +use relay_substrate_client::ConnectionParams; + +/// Millau node client. +pub type MillauClient = relay_substrate_client::Client; +/// Rialto node client. +pub type RialtoClient = relay_substrate_client::Client; + +mod cli; +mod millau_headers_to_rialto; + +fn main() { + let result = async_std::task::block_on(run_command(cli::parse_args())); + if let Err(error) = result { + log::error!(target: "bridge", "Failed to start relay: {}", error); + } +} + +async fn run_command(command: cli::Command) -> Result<(), String> { + match command { + cli::Command::MillauHeadersToRialto { + millau, + rialto, + rialto_sign, + } => { + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let rialto_sign = RialtoSigningParams::from_suri( + &rialto_sign.rialto_signer, + rialto_sign.rialto_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign) + } + } + + Ok(()) +} diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs new file mode 100644 index 0000000000000..d927a9e133f42 --- /dev/null +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -0,0 +1,125 @@ +// Copyright 2019-2020 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 . + +//! Millau-to-Rialto headers sync entrypoint. + +use crate::{MillauClient, RialtoClient}; + +use async_trait::async_trait; +use codec::Encode; +use headers_relay::{ + sync::{HeadersSyncParams, TargetTransactionMode}, + sync_loop::TargetClient, + sync_types::{HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, +}; +use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SyncHeader as MillauSyncHeader}; +use relay_rialto_client::SigningParams as RialtoSigningParams; +use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Error as SubstrateError, HashOf}; +use sp_runtime::Justification; +use std::{collections::HashSet, time::Duration}; + +/// Millau-to-Rialto headers pipeline. +#[derive(Debug, Clone, Copy)] +struct MillauHeadersToRialto; + +impl HeadersSyncPipeline for MillauHeadersToRialto { + const SOURCE_NAME: &'static str = "Millau"; + const TARGET_NAME: &'static str = "Rialto"; + + type Hash = HashOf; + type Number = BlockNumberOf; + type Header = MillauSyncHeader; + type Extra = (); + type Completion = Justification; + + fn estimate_size(source: &QueuedHeader) -> usize { + source.header().encode().len() + } +} + +/// Millau header in-the-queue. +type QueuedMillauHeader = QueuedHeader; + +/// Millau node as headers source. +type MillauSourceClient = HeadersSource; + +/// Rialto node as headers target. +struct RialtoTargetClient { + _client: RialtoClient, + _sign: RialtoSigningParams, +} + +#[async_trait] +impl TargetClient for RialtoTargetClient { + type Error = SubstrateError; + + async fn best_header_id(&self) -> Result { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + } + + async fn is_known_header(&self, _id: MillauHeaderId) -> Result<(MillauHeaderId, bool), Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + } + + async fn submit_headers(&self, _headers: Vec) -> SubmittedHeaders { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + } + + async fn incomplete_headers_ids(&self) -> Result, Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + } + + #[allow(clippy::unit_arg)] + async fn complete_header( + &self, + _id: MillauHeaderId, + _completion: Justification, + ) -> Result { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + } + + async fn requires_extra(&self, _header: QueuedMillauHeader) -> Result<(MillauHeaderId, bool), Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + } +} + +/// Run Millau-to-Rialto headers sync. +pub fn run(millau_client: MillauClient, rialto_client: RialtoClient, rialto_sign: RialtoSigningParams) { + let millau_tick = Duration::from_secs(5); + let rialto_tick = Duration::from_secs(5); + let sync_params = HeadersSyncParams { + max_future_headers_to_download: 32, + max_headers_in_submitted_status: 1024, + max_headers_in_single_submit: 8, + max_headers_size_in_single_submit: 1024 * 1024, + prune_depth: 256, + target_tx_mode: TargetTransactionMode::Signed, + }; + let metrics_params = None; + + headers_relay::sync_loop::run( + MillauSourceClient::new(millau_client), + millau_tick, + RialtoTargetClient { + _client: rialto_client, + _sign: rialto_sign, + }, + rialto_tick, + sync_params, + metrics_params, + futures::future::pending(), + ); +} From 6aefc979c33c024589e17047e6ea5f13b2c5ce68 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 30 Sep 2020 14:21:03 +0300 Subject: [PATCH 0170/1210] update async-std (#388) --- modules/message-lane/rpc/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/main.rs | 13 +++++++++++++ relays/exchange-relay/Cargo.toml | 2 +- relays/headers-relay/Cargo.toml | 2 +- relays/messages-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-) diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index 843cfe6e24fe3..2a374fd79363e 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -48,7 +48,7 @@ tag = 'v2.0.0' git = "https://github.com/paritytech/substrate/" [dev-dependencies] -async-std = "1.6.2" +async-std = "1.6.5" [dev-dependencies.substrate-test-runtime-client] version = "2.0.0" diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 15feebd70fd2b..9a22379fa3f2e 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" -async-std = "1.6.2" +async-std = "1.6.5" async-trait = "0.1.40" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 9b290df43c45d..20f18c3310c61 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -434,3 +434,16 @@ fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> Result Ok(None), } } + +#[cfg(test)] +mod tests { + + // Details: https://github.com/paritytech/parity-bridges-common/issues/118 + #[test] + fn async_std_sleep_works() { + let mut local_pool = futures::executor::LocalPool::new(); + local_pool.run_until(async move { + async_std::task::sleep(std::time::Duration::from_secs(1)).await; + }); + } +} diff --git a/relays/exchange-relay/Cargo.toml b/relays/exchange-relay/Cargo.toml index 87502fe6a6e5f..62e7a029bbb2c 100644 --- a/relays/exchange-relay/Cargo.toml +++ b/relays/exchange-relay/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.2" +async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" futures = "0.3.5" diff --git a/relays/headers-relay/Cargo.toml b/relays/headers-relay/Cargo.toml index e289ac984fb86..31d3166a99781 100644 --- a/relays/headers-relay/Cargo.toml +++ b/relays/headers-relay/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.2" +async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" futures = "0.3.5" diff --git a/relays/messages-relay/Cargo.toml b/relays/messages-relay/Cargo.toml index 0af7eddc551fc..f876b387424fb 100644 --- a/relays/messages-relay/Cargo.toml +++ b/relays/messages-relay/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.2" +async-std = "1.6.5" async-trait = "0.1.40" futures = "0.3.5" log = "0.4.11" diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 029fdd4547d07..c456e5cc62319 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.2" +async-std = "1.6.5" backoff = "0.2" futures = "0.3.5" log = "0.4.11" From d19b35aa7e643c8bc60193fe48574c9b7c04140e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 30 Sep 2020 15:26:13 +0300 Subject: [PATCH 0171/1210] Get substrate dependencies from crates io (#387) * get Substrate dependencies from crates.io * removing unused dependencies * cargo fmt --all * remove commented dependencies * remove commented dependencies again * try to fix compilation --- bin/millau-runtime/Cargo.toml | 246 +++------------- bin/node/Cargo.toml | 163 ++--------- bin/node/src/chain_spec.rs | 2 +- bin/rialto-runtime/Cargo.toml | 287 ++++--------------- modules/call-dispatch/Cargo.toml | 47 +-- modules/currency-exchange/Cargo.toml | 57 ++-- modules/ethereum-contract/builtin/Cargo.toml | 33 +-- modules/ethereum/Cargo.toml | 54 +--- modules/message-lane/Cargo.toml | 46 +-- modules/message-lane/rpc/Cargo.toml | 48 +--- modules/message-lane/rpc/src/lib.rs | 72 ----- modules/shift-session-manager/Cargo.toml | 52 +--- modules/substrate/Cargo.toml | 83 +----- primitives/currency-exchange/Cargo.toml | 24 +- primitives/ethereum-poa/Cargo.toml | 69 ++--- primitives/message-lane/Cargo.toml | 22 +- primitives/millau/Cargo.toml | 6 +- primitives/rialto/Cargo.toml | 6 +- primitives/runtime/Cargo.toml | 8 +- primitives/substrate/Cargo.toml | 36 --- relays/ethereum/Cargo.toml | 60 ++-- relays/millau-client/Cargo.toml | 4 +- relays/rialto-client/Cargo.toml | 12 +- relays/substrate-client/Cargo.toml | 15 +- relays/substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 3 +- 26 files changed, 284 insertions(+), 1173 deletions(-) delete mode 100644 primitives/substrate/Cargo.toml diff --git a/bin/millau-runtime/Cargo.toml b/bin/millau-runtime/Cargo.toml index fd24613039d84..85db10f4dcb0e 100644 --- a/bin/millau-runtime/Cargo.toml +++ b/bin/millau-runtime/Cargo.toml @@ -8,211 +8,45 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-millau = { path = "../../primitives/millau", default-features = false } -hex-literal = "0.3" +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +serde = { version = "1.0.115", optional = true, features = ["derive"] } -[dependencies.codec] -package = "parity-scale-codec" -version = "1.3.1" -default-features = false -features = ["derive"] +# Bridge dependencies -[dependencies.serde] -version = "1.0.115" -optional = true -features = ["derive"] +bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-millau = { path = "../../primitives/millau", default-features = false } +pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } +pallet-message-lane = { path = "../../modules/message-lane", default-features = false } +pallet-shift-session-manager = { path = "../../modules/shift-session-manager", default-features = false } # Substrate Dependencies -[dependencies.pallet-aura] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-balances] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-bridge-call-dispatch] -version = "0.1.0" -default-features = false -path = "../../modules/call-dispatch" - -[dependencies.pallet-message-lane] -version = "0.1.0" -default-features = false -path = "../../modules/message-lane" - -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-grandpa] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-randomness-collective-flip] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-sudo] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-shift-session-manager] -version = "0.1.0" -default-features = false -path = "../../modules/shift-session-manager" - -[dependencies.pallet-session] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system-rpc-runtime-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-timestamp] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-transaction-payment] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-executive] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -# Substrate Primitives -[dependencies.sp-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-block-builder] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" -[dependencies.sp-consensus-aura] -version = "0.8.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-inherents] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-offchain] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-session] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-staking] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-transaction-pool] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-version] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-benchmarking] -optional = true -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.bp-header-chain] -version = "0.1.0" -default-features = false -path = "../../primitives/header-chain" - -[dependencies.bp-message-lane] -version = "0.1.0" -default-features = false -path = "../../primitives/message-lane" - -# Dev Dependencies - -[build-dependencies.wasm-builder-runner] -version = "1.0.5" -tag = 'v2.0.0' -package = "substrate-wasm-builder-runner" -git = "https://github.com/paritytech/substrate/" +frame-executive = { version = "2.0", default-features = false } +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +frame-system-rpc-runtime-api = { version = "2.0", default-features = false } +pallet-aura = { version = "2.0", default-features = false } +pallet-balances = { version = "2.0", default-features = false } +pallet-grandpa = { version = "2.0", default-features = false } +pallet-randomness-collective-flip = { version = "2.0", default-features = false } +pallet-session = { version = "2.0", default-features = false } +pallet-sudo = { version = "2.0", default-features = false } +pallet-timestamp = { version = "2.0", default-features = false } +pallet-transaction-payment = { version = "2.0", default-features = false } +sp-api = { version = "2.0", default-features = false } +sp-block-builder = { version = "2.0", default-features = false } +sp-consensus-aura = { version = "0.8", default-features = false } +sp-core = { version = "2.0", default-features = false } +sp-inherents = { version = "2.0", default-features = false } +sp-offchain = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-session = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } +sp-transaction-pool = { version = "2.0", default-features = false } +sp-version = { version = "2.0", default-features = false } + +[build-dependencies] +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.5" } [features] default = ["std"] @@ -220,17 +54,18 @@ std = [ "bp-message-lane/std", "bp-millau/std", "codec/std", - "frame-benchmarking/std", "frame-executive/std", "frame-support/std", - "frame-system-rpc-runtime-api/std", "frame-system/std", + "frame-system-rpc-runtime-api/std", "pallet-aura/std", "pallet-balances/std", "pallet-bridge-call-dispatch/std", "pallet-grandpa/std", + "pallet-message-lane/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", + "pallet-session/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment/std", @@ -240,7 +75,6 @@ std = [ "sp-consensus-aura/std", "sp-core/std", "sp-inherents/std", - "sp-io/std", "sp-offchain/std", "sp-runtime/std", "sp-session/std", @@ -248,9 +82,3 @@ std = [ "sp-transaction-pool/std", "sp-version/std", ] -runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] diff --git a/bin/node/Cargo.toml b/bin/node/Cargo.toml index 72770e0db7c32..628ba7552568d 100644 --- a/bin/node/Cargo.toml +++ b/bin/node/Cargo.toml @@ -9,147 +9,42 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -futures = "0.3.5" jsonrpc-core = "15.0.0" -log = "0.4.11" -pallet-message-lane-rpc = { version = "0.1.0", path = "../../modules/message-lane/rpc" } structopt = "0.3.17" -[dependencies.millau-runtime] -optional = true -version = "0.1.0" -path = "../millau-runtime" -default-features = false -features = ["std"] - -[dependencies.rialto-runtime] -optional = true -version = "0.1.0" -path = "../rialto-runtime" -default-features = false -features = ["std"] - -[dependencies.sc-cli] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-rpc] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-executor] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-service] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-inherents] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-transaction-pool] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-transaction-pool] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-network] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-consensus-aura] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-consensus-aura] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-consensus] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-finality-grandpa] -package = "sc-finality-grandpa" -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.grandpa-primitives] -package = "sp-finality-grandpa" -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-consensus] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-client-api] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sc-basic-authorship] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.substrate-frame-rpc-system] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.frame-benchmarking] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.frame-benchmarking-cli] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" +# Bridge dependencies + +millau-runtime = { path = "../millau-runtime", optional = true } +pallet-message-lane-rpc = { path = "../../modules/message-lane/rpc" } +rialto-runtime = { path = "../rialto-runtime", optional = true } + +# Substrate Dependencies + +frame-benchmarking = "2.0" +frame-benchmarking-cli = "2.0" +sc-basic-authorship = "0.8" +sc-cli = "0.8" +sc-client-api = "2.0" +sc-consensus = "0.8" +sc-consensus-aura = "0.8" +sc-executor = "0.8" +sc-finality-grandpa = "0.8" +sc-service = "0.8" +sc-rpc = "2.0" +sc-transaction-pool = "2.0" +sp-consensus = "0.8" +sp-consensus-aura = "0.8" +sp-core = "2.0" +sp-inherents = "2.0" +sp-finality-grandpa = "2.0" +sp-runtime = "2.0" +substrate-frame-rpc-system = "2.0" [build-dependencies] +build-script-utils = { package = "substrate-build-script-utils", version = "2.0" } +frame-benchmarking-cli = "2.0" vergen = "3.1.0" -[build-dependencies.build-script-utils] -package = "substrate-build-script-utils" -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[build-dependencies.frame-benchmarking-cli] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - [features] default = [] millau = [ diff --git a/bin/node/src/chain_spec.rs b/bin/node/src/chain_spec.rs index 2aac990331903..62f28fb49a885 100644 --- a/bin/node/src/chain_spec.rs +++ b/bin/node/src/chain_spec.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use grandpa_primitives::AuthorityId as GrandpaId; use rialto_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; +use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. diff --git a/bin/rialto-runtime/Cargo.toml b/bin/rialto-runtime/Cargo.toml index 495948486cbe2..878dfc01b873e 100644 --- a/bin/rialto-runtime/Cargo.toml +++ b/bin/rialto-runtime/Cargo.toml @@ -8,255 +8,65 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-millau = { path = "../../primitives/millau", default-features = false } -bp-rialto = { path = "../../primitives/rialto", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" +libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } +serde = { version = "1.0.115", optional = true, features = ["derive"] } -[dependencies.codec] -package = "parity-scale-codec" -version = "1.3.1" -default-features = false -features = ["derive"] +# Bridge dependencies -[dependencies.libsecp256k1] -optional = true -version = "0.3.4" -default-features = false -features = ["hmac"] - -[dependencies.serde] -version = "1.0.116" -optional = true -features = ["derive"] +bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } +bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-millau = { path = "../../primitives/millau", default-features = false } +bp-rialto = { path = "../../primitives/rialto", default-features = false } +pallet-bridge-eth-poa = { path = "../../modules/ethereum", default-features = false } +pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } +pallet-bridge-currency-exchange = { path = "../../modules/currency-exchange", default-features = false } +pallet-message-lane = { path = "../../modules/message-lane", default-features = false } +pallet-shift-session-manager = { path = "../../modules/shift-session-manager", default-features = false } # Substrate Dependencies -[dependencies.pallet-aura] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-balances] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-bridge-eth-poa] -version = "0.1.0" -default-features = false -path = "../../modules/ethereum" - -[dependencies.pallet-bridge-call-dispatch] -version = "0.1.0" -default-features = false -path = "../../modules/call-dispatch" - -[dependencies.pallet-bridge-currency-exchange] -version = "0.1.0" -default-features = false -path = "../../modules/currency-exchange" - -[dependencies.pallet-message-lane] -version = "0.1.0" -default-features = false -path = "../../modules/message-lane" - -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-grandpa] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-randomness-collective-flip] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-shift-session-manager] -version = "0.1.0" -default-features = false -path = "../../modules/shift-session-manager" - -[dependencies.pallet-sudo] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-session] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system-rpc-runtime-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-timestamp] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-transaction-payment] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-executive] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -# Substrate Primitives -[dependencies.sp-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" -[dependencies.sp-block-builder] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-consensus-aura] -version = "0.8.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-inherents] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-offchain] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-session] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-staking] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-transaction-pool] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-version] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-benchmarking] -optional = true -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.bp-currency-exchange] -version = "0.1.0" -default-features = false -path = "../../primitives/currency-exchange" - -[dependencies.bp-eth-poa] -version = "0.1.0" -default-features = false -path = "../../primitives/ethereum-poa" - -[dependencies.bp-header-chain] -version = "0.1.0" -default-features = false -path = "../../primitives/header-chain" - -[dependencies.bp-message-lane] -version = "0.1.0" -default-features = false -path = "../../primitives/message-lane" - -# Dev Dependencies - -[dev-dependencies.libsecp256k1] -version = "0.3.4" -default-features = false -features = ["hmac"] - -[dev-dependencies.bp-eth-poa] -version = "0.1.0" -default-features = false -features = ["std"] -path = "../../primitives/ethereum-poa" - -[build-dependencies.wasm-builder-runner] -version = "1.0.5" -tag = 'v2.0.0' -package = "substrate-wasm-builder-runner" -git = "https://github.com/paritytech/substrate/" +frame-benchmarking = { version = "2.0", default-features = false, optional = true } +frame-executive = { version = "2.0", default-features = false } +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +frame-system-rpc-runtime-api = { version = "2.0", default-features = false } +pallet-aura = { version = "2.0", default-features = false } +pallet-balances = { version = "2.0", default-features = false } +pallet-grandpa = { version = "2.0", default-features = false } +pallet-randomness-collective-flip = { version = "2.0", default-features = false } +pallet-session = { version = "2.0", default-features = false } +pallet-sudo = { version = "2.0", default-features = false } +pallet-timestamp = { version = "2.0", default-features = false } +pallet-transaction-payment = { version = "2.0", default-features = false } +sp-api = { version = "2.0", default-features = false } +sp-block-builder = { version = "2.0", default-features = false } +sp-consensus-aura = { version = "0.8", default-features = false } +sp-core = { version = "2.0", default-features = false } +sp-inherents = { version = "2.0", default-features = false } +sp-io = { version = "2.0", default-features = false } +sp-offchain = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-session = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } +sp-transaction-pool = { version = "2.0", default-features = false } +sp-version = { version = "2.0", default-features = false } + +[dev-dependencies] +libsecp256k1 = { version = "0.3.4", features = ["hmac"] } + +[build-dependencies] +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.5" } [features] default = ["std"] std = [ "bp-currency-exchange/std", "bp-eth-poa/std", + "bp-header-chain/std", "bp-message-lane/std", "bp-millau/std", "bp-rialto/std", @@ -268,10 +78,11 @@ std = [ "frame-system/std", "pallet-aura/std", "pallet-balances/std", + "pallet-bridge-eth-poa/std", "pallet-bridge-call-dispatch/std", "pallet-bridge-currency-exchange/std", - "pallet-bridge-eth-poa/std", "pallet-grandpa/std", + "pallet-message-lane/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", "pallet-sudo/std", diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index 83e86ba0e0b67..b60cf14d79229 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -8,45 +8,22 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } - -# Substrate Based Dependencies -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Bridge dependencies -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Substrate Dependencies -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } -[dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +[dev-dependencies] +sp-core = "2.0" +sp-io = "2.0" [features] default = ["std"] @@ -55,8 +32,6 @@ std = [ "bp-runtime/std", "frame-support/std", "frame-system/std", - "sp-core/std", - "sp-io/std", "sp-runtime/std", "sp-std/std", ] diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 5e3c980447c96..8d400e07bb215 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -7,57 +7,31 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } -bp-header-chain = { path = "../../primitives/header-chain", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } serde = { version = "1.0", optional = true } -# Substrate Based Dependencies -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Bridge dependencies -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } -[dependencies.frame-benchmarking] -optional = true -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Substrate Dependencies -[dev-dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +frame-benchmarking = { version = "2.0", default-features = false, optional = true } +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false, optional = true } -[dev-dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +[dev-dependencies] +sp-core = "2.0" +sp-io = "2.0" [features] default = ["std"] std = [ "bp-currency-exchange/std", + "bp-header-chain/std", "codec/std", "frame-benchmarking/std", "frame-support/std", @@ -66,4 +40,7 @@ std = [ "sp-runtime/std", "sp-std/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = [ + "frame-benchmarking", + "sp-std", +] diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 5ade9e6deb157..b2adcfbf49ecb 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -7,9 +7,6 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] - -# General dependencies - codec = { package = "parity-scale-codec", version = "1.3.4" } ethereum-types = "0.9.2" finality-grandpa = "0.12.3" @@ -20,30 +17,12 @@ log = "0.4.11" rialto-runtime = { path = "../../../bin/rialto-runtime" } -[dependencies.sp-blockchain] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-finality-grandpa] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +# Substrate Dependencies -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sc-finality-grandpa] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +sc-finality-grandpa = "0.8" +sp-blockchain = "2.0" +sp-finality-grandpa = "2.0" +sp-runtime = "2.0" [dev-dependencies] -hex = "0.4" - -[dev-dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +sp-core = "2.0" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 7c66ad26f74c6..eb8393f4905ae 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -7,58 +7,24 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } -hex-literal = "0.3" +libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"], optional = true } serde = { version = "1.0", optional = true } -# Substrate Based Dependencies -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Bridge dependencies -[dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } -[dependencies.frame-benchmarking] -optional = true -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Substrate Dependencies -[dependencies.libsecp256k1] -optional = true -version = "0.3.4" -default-features = false -features = ["hmac"] +frame-benchmarking = { version = "2.0", default-features = false, optional = true } +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +sp-io = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } -# Dev Dependencies [dev-dependencies] -bp-eth-poa = { path = "../../primitives/ethereum-poa", features = ["std"] } libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [features] diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index c983b6cd99a55..0240d22250594 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -7,54 +7,30 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } -bp-message-lane = { path = "../../primitives/message-lane", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -# Substrate Based Dependencies - -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Bridge dependencies -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +bp-message-lane = { path = "../../primitives/message-lane", default-features = false } -[dev-dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +# Substrate Dependencies -[dev-dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } -[dev-dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +[dev-dependencies] +sp-core = "2.0" +sp-io = "2.0" [features] default = ["std"] std = [ - "bp-message-dispatch/std", "bp-message-lane/std", - "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index 2a374fd79363e..e9ef6c1cc6b2a 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -7,50 +7,22 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-runtime = { path = "../../../primitives/runtime" } -bp-message-lane = { path = "../../../primitives/message-lane" } derive_more = "0.99.2" futures = { version = "0.3.5", features = ["compat"] } jsonrpc-core = "15.0.0" jsonrpc-core-client = "15.0.0" jsonrpc-derive = "15.0.0" -# Substrate Based Dependencies - -[dependencies.sc-client-api] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-blockchain] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +# Bridge dependencies -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-state-machine] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-trie] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +bp-runtime = { path = "../../../primitives/runtime" } +bp-message-lane = { path = "../../../primitives/message-lane" } -[dev-dependencies] -async-std = "1.6.5" +# Substrate Dependencies -[dev-dependencies.substrate-test-runtime-client] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" +sc-client-api = "2.0" +sp-blockchain = "2.0" +sp-core = "2.0" +sp-runtime = "2.0" +sp-state-machine = "0.8" +sp-trie = "2.0" diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index ff3ab1507ad8a..28aeb66ab15e5 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -175,75 +175,3 @@ fn unwrap_or_best(backend: &impl BackendT, block: Option Error { Error::Client(Box::new(err)) } - -#[cfg(test)] -mod tests { - use super::*; - use sp_core::Blake2Hasher; - use sp_runtime::{codec::Decode, traits::Header as HeaderT}; - use substrate_test_runtime_client::{ - runtime::Block, Backend, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt, - }; - - const TEST_INSTANCE: InstanceId = [0, 0, 0, 1]; - const TEST_LANE: LaneId = [0, 0, 0, 1]; - - fn test_key() -> StorageKey { - StorageKey(sp_core::storage::well_known_keys::CODE.to_vec()) - } - - struct TestRuntimeAdapter; - - impl Runtime for TestRuntimeAdapter { - fn message_key(&self, instance: &InstanceId, _lane: &LaneId, _nonce: MessageNonce) -> Option { - if *instance == TEST_INSTANCE { - Some(test_key()) - } else { - None - } - } - - fn inbound_lane_data_key(&self, instance: &InstanceId, _lane: &LaneId) -> Option { - if *instance == TEST_INSTANCE { - Some(test_key()) - } else { - None - } - } - } - - fn test_handler() -> MessageLaneRpcHandler { - let builder = TestClientBuilder::new(); - let (_, backend) = builder.build_with_backend(); - - MessageLaneRpcHandler::new(backend, Arc::new(TestRuntimeAdapter)) - } - - #[test] - fn storage_proof_is_actually_generated() { - // the only thing we actually care here is that RPC actually generates storage proof - // that can be verified from runtime - - // proof is generated by RPC - let handler = test_handler(); - let proof = handler - .prove_messages(TEST_INSTANCE, TEST_LANE, 1, 3, None) - .wait() - .unwrap(); - - // proof is then relayed + checked by runtime (sp_trie supports no_std) - // (storage root is known to underlying bridge pallet) - let root = *handler - .backend - .blockchain() - .header(BlockId::Number(0)) - .unwrap() - .unwrap() - .state_root(); - let proof = StorageProof::new(Decode::decode(&mut &proof[..]).unwrap()); - let trie_db = proof.into_memory_db::(); - let checked_storage_value = - sp_trie::read_trie_value::, _>(&trie_db, &root, &test_key().0).unwrap(); - assert!(checked_storage_value.is_some()); - } -} diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 7684157380b6c..3f54df20dfe00 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -9,49 +9,17 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -# Substrate Based Dependencies +# Substrate Dependencies -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +pallet-session = { version = "2.0", default-features = false } +sp-staking = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-session] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-staking] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +[dev-dependencies] +sp-core = "2.0" +sp-runtime = "2.0" [features] default = ["std"] @@ -60,8 +28,6 @@ std = [ "frame-support/std", "frame-system/std", "pallet-session/std", - "sp-core/std", - "sp-runtime/std", "sp-staking/std", "sp-std/std", ] diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index ae70b54af409c..3b474e643fc75 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -8,79 +8,26 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } hash-db = { version = "0.15.2", default-features = false } -serde = { version = "1.0", optional = true } num-traits = { version = "0.2", default-features = false } +serde = { version = "1.0", optional = true } -[dependencies.codec] -package = "parity-scale-codec" -version = "1.3.1" -default-features = false -features = ["derive"] - -# Substrate Based Dependencies - -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-finality-grandpa] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.sp-trie] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -# Dev Dependencies -[dev-dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dev-dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +# Substrate Dependencies -[dev-dependencies.sp-keyring] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +frame-support = { version = "2.0", default-features = false } +frame-system = { version = "2.0", default-features = false } +sp-finality-grandpa = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } +sp-trie = { version = "2.0", default-features = false } -[dev-dependencies.sp-state-machine] -version = "0.8.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +[dev-dependencies] +sp-core = "2.0" +sp-io = "2.0" +sp-keyring = "2.0" +sp-state-machine = "0.8" [features] default = ["std"] @@ -89,11 +36,11 @@ std = [ "finality-grandpa/std", "frame-support/std", "frame-system/std", + "hash-db/std", "num-traits/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", - "sp-io/std", ] diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 6f70280f16dc1..aebde40e902f6 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -9,31 +9,17 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } -# Substrate Based Dependencies +# Substrate Dependencies -[dependencies.sp-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" +frame-support = { version = "2.0", default-features = false } +sp-api = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } [features] default = ["std"] std = [ "codec/std", + "frame-support/std", "sp-api/std", "sp-std/std", - "frame-support/std", ] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 6ff4c0481a3ca..49eab4f084362 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -7,49 +7,27 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -serde = { version = "1.0", optional = true } -serde-big-array = { version = "0.2", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } ethbloom = { version = "0.8", default-features = false } -parity-bytes = { version = "0.1", default-features = false } -primitive-types = { version = "0.7", default-features = false, features = ["codec", "rlp"] } fixed-hash = { version = "0.5", default-features = false } +hash-db = { version = "0.15.2", default-features = false } impl-rlp = { version = "0.2", default-features = false } impl-serde = { version = "0.2.3", optional = true } -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } +parity-bytes = { version = "0.1", default-features = false } +plain_hasher = { version = "0.2.2", default-features = false } +primitive-types = { version = "0.7", default-features = false, features = ["codec", "rlp"] } rlp = { version = "0.4", default-features = false } -hash-db = { version = "0.15.2", default-features = false } +serde = { version = "1.0", optional = true } +serde-big-array = { version = "0.2", optional = true } triehash = { version = "0.8.2", default-features = false } -plain_hasher = { version = "0.2.2", default-features = false } - -# Substrate Based Dependencies -[dependencies.sp-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" +# Substrate Dependencies -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.libsecp256k1] -version = "0.3.4" -default-features = false -features = ["hmac"] +sp-api = { version = "2.0", default-features = false } +sp-io = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } [dev-dependencies] hex-literal = "0.2" @@ -57,22 +35,23 @@ hex-literal = "0.2" [features] default = ["std"] std = [ - "serde/std", - "serde-big-array", + "codec/std", "ethbloom/std", - "parity-bytes/std", - "primitive-types/std", - "primitive-types/serde", "fixed-hash/std", + "hash-db/std", "impl-rlp/std", "impl-serde", - "codec/std", + "libsecp256k1/std", + "parity-bytes/std", + "plain_hasher/std", + "primitive-types/std", + "primitive-types/serde", "rlp/std", - "sp-std/std", - "sp-runtime/std", + "serde/std", + "serde-big-array", "sp-api/std", "sp-io/std", - "hash-db/std", + "sp-runtime/std", + "sp-std/std", "triehash/std", - "plain_hasher/std", ] diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index c551a11627cbc..d705c119fe5d0 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -9,25 +9,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } -# Substrate Based Dependencies +# Substrate Dependencies -[dependencies.frame-support] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-api] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-std] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" +frame-support = { version = "2.0", default-features = false } +sp-api = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } [features] default = ["std"] diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index 8e787996f501a..831a33b0403ef 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Substrate Based Dependencies -sp-api = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } -sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } -sp-std = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } +sp-api = { version = "2.0", default-features = false } +sp-core = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } [features] default = ["std"] diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index 42f56fdae00d8..e8a04907b8c37 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Substrate Based Dependencies -sp-api = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } -sp-core = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } -sp-std = { version = "2.0.0", git = "https://github.com/paritytech/substrate.git", tag = 'v2.0.0', default-features = false } +sp-api = { version = "2.0.0", default-features = false } +sp-core = { version = "2.0.0", default-features = false } +sp-std = { version = "2.0.0", default-features = false } [features] default = ["std"] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 249e49f151e9b..b182f4e4e406a 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -9,13 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -# Substrate Based Dependencies +# Substrate Dependencies -[dependencies.sp-io] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" +sp-io = { version = "2.0", default-features = false } [features] default = ["std"] diff --git a/primitives/substrate/Cargo.toml b/primitives/substrate/Cargo.toml deleted file mode 100644 index 3756bd7bf8048..0000000000000 --- a/primitives/substrate/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "bp-substrate" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -serde = { version = "1.0", optional = true } - -[dependencies.sp-finality-grandpa] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -default-features = false -git = "https://github.com/paritytech/substrate/" - -[dependencies.parity-scale-codec] -version = "1.3.1" -default-features = false -features = ["derive"] - -[features] -default = ["std"] -std = [ - "serde/std", - "sp-runtime/std", - "sp-finality-grandpa/std", -] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 9a22379fa3f2e..4c840758fcbc9 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -9,64 +9,40 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" ansi_term = "0.12" async-std = "1.6.5" async-trait = "0.1.40" -bp-currency-exchange = { path = "../../primitives/currency-exchange" } -bp-eth-poa = { path = "../../primitives/ethereum-poa" } clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" -exchange-relay = { path = "../exchange-relay" } futures = "0.3.5" -headers-relay = { path = "../headers-relay" } hex = "0.4" hex-literal = "0.3" log = "0.4.11" -messages-relay = { path = "../messages-relay" } num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } -relay-ethereum-client = { path = "../ethereum-client" } -relay-rialto-client = { path = "../rialto-client" } -relay-substrate-client = { path = "../substrate-client" } -rialto-runtime = { path = "../../bin/rialto-runtime" } -relay-utils = { path = "../utils" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.57" time = "0.2" -# Substrate Based Dependencies -[dependencies.frame-system] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate/" - -[dependencies.pallet-transaction-payment] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.node-primitives] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" +# Bridge dependencies -[dependencies.sp-core] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" - -[dependencies.sp-keyring] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" +bp-currency-exchange = { path = "../../primitives/currency-exchange" } +bp-eth-poa = { path = "../../primitives/ethereum-poa" } +exchange-relay = { path = "../exchange-relay" } +headers-relay = { path = "../headers-relay" } +messages-relay = { path = "../messages-relay" } +relay-ethereum-client = { path = "../ethereum-client" } +relay-rialto-client = { path = "../rialto-client" } +relay-substrate-client = { path = "../substrate-client" } +relay-utils = { path = "../utils" } +rialto-runtime = { path = "../../bin/rialto-runtime" } -[dependencies.sp-runtime] -version = "2.0.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" +# Substrate Dependencies -[dependencies.substrate-prometheus-endpoint] -version = "0.8.0" -tag = 'v2.0.0' -git = "https://github.com/paritytech/substrate.git" +frame-system = "2.0" +pallet-transaction-payment = "2.0" +sp-core = "2.0" +sp-keyring = "2.0" +sp-runtime = "2.0" +substrate-prometheus-endpoint = "0.8" diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index 35b029ed3b7c8..cb98370d845a8 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -17,5 +17,5 @@ millau-runtime = { path = "../../bin/millau-runtime" } # Substrate Dependencies -frame-system = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +frame-system = "2.0" +sp-runtime = "2.0" diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml index 5f5fef38c36e9..aec1262a00ec1 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/rialto-client/Cargo.toml @@ -11,14 +11,14 @@ headers-relay = { path = "../headers-relay" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } -# Supported Chains +# Bridge dependencies rialto-runtime = { path = "../../bin/rialto-runtime" } # Substrate Dependencies -frame-system = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -pallet-transaction-payment = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-core = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-keyring = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +frame-system = "2.0" +pallet-transaction-payment = "2.0" +sp-core = "2.0" +sp-keyring = "2.0" +sp-runtime = "2.0" diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index ae04b9dbeae70..0ffd702da6dbf 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -8,16 +8,19 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "1.3.4" } -headers-relay = { path = "../headers-relay" } jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } log = "0.4.11" num-traits = "0.2" + +# Bridge dependencies + +headers-relay = { path = "../headers-relay" } relay-utils = { path = "../utils" } # Substrate Dependencies -frame-support = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -frame-system = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-core = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } -sp-std = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +frame-support = "2.0" +frame-system = "2.0" +sp-core = "2.0" +sp-runtime = "2.0" +sp-std = "2.0" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 22809fc3c7ba4..8a740daa0e113 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -18,5 +18,5 @@ paste = "1.0" relay-millau-client = { path = "../millau-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } -sp-runtime = { version = "2.0.0", tag = 'v2.0.0', git = "https://github.com/paritytech/substrate.git" } +sp-runtime = "2.0" structopt = "0.3" diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index c456e5cc62319..04113bfdd1b85 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -13,4 +13,5 @@ log = "0.4.11" sysinfo = "0.15" # Substrate dependencies -substrate-prometheus-endpoint = { version = "0.8.0", git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0" } + +substrate-prometheus-endpoint = "0.8" From 95186371dde657c576c443896332e88c3aec5c93 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Sat, 3 Oct 2020 00:35:23 +0300 Subject: [PATCH 0172/1210] Support non-positional params (#393) --- relays/substrate/src/cli.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 939863b5ca0a2..ca97aa00249ea 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -44,8 +44,10 @@ macro_rules! declare_chain_options { #[derive(StructOpt)] pub struct [<$chain ConnectionParams>] { #[doc = "Connect to " $chain " node at given host."] + #[structopt(long)] pub [<$chain_prefix _host>]: String, #[doc = "Connect to " $chain " node at given port."] + #[structopt(long)] pub [<$chain_prefix _port>]: u16, } @@ -53,8 +55,10 @@ macro_rules! declare_chain_options { #[derive(StructOpt)] pub struct [<$chain SigningParams>] { #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] pub [<$chain_prefix _signer>]: String, #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] pub [<$chain_prefix _signer_password>]: Option, } } From 60d998541a2dbc86998860e970b35e5bed91e28e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2020 02:23:49 +0000 Subject: [PATCH 0173/1210] Bump async-trait from 0.1.40 to 0.1.41 (#395) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4c840758fcbc9..8656ed6996ae2 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" async-std = "1.6.5" -async-trait = "0.1.40" +async-trait = "0.1.41" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } env_logger = "0.7.0" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 8a740daa0e113..3351a3fb43534 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.2" -async-trait = "0.1.40" +async-trait = "0.1.41" bp-rialto = { path = "../../primitives/rialto" } codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.5" From a733636891a2e9f72066a062c4efcbe772111ca4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2020 02:41:00 +0000 Subject: [PATCH 0174/1210] Bump serde_json from 1.0.57 to 1.0.58 (#396) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8656ed6996ae2..d496aeff67566 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.11" num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.57" +serde_json = "1.0.58" time = "0.2" # Bridge dependencies From 7b7626269f78f5a09d6acbe3190bed298d0f3989 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 5 Oct 2020 10:01:19 +0300 Subject: [PATCH 0175/1210] extract common relay initialization func (#392) --- relays/ethereum/src/main.rs | 43 ++----------------------- relays/substrate/Cargo.toml | 14 ++++++--- relays/substrate/src/main.rs | 5 ++- relays/utils/Cargo.toml | 3 ++ relays/utils/src/initialize.rs | 57 ++++++++++++++++++++++++++++++++++ relays/utils/src/lib.rs | 1 + 6 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 relays/utils/src/initialize.rs diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 20f18c3310c61..fd46847c6d9de 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -35,7 +35,7 @@ use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; use instances::{BridgeInstance, Kovan, RialtoPoA}; use parity_crypto::publickey::{KeyPair, Secret}; -use relay_utils::metrics::MetricsParams; +use relay_utils::{initialize::initialize_relay, metrics::MetricsParams}; use sp_core::crypto::Pair; use substrate_sync_loop::SubstrateSyncParams; @@ -43,10 +43,10 @@ use headers_relay::sync::HeadersSyncParams; use relay_ethereum_client::{ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams}; use relay_rialto_client::SigningParams as RialtoSigningParams; use relay_substrate_client::ConnectionParams as SubstrateConnectionParams; -use std::{io::Write, sync::Arc}; +use std::sync::Arc; fn main() { - initialize(); + initialize_relay(); let yaml = clap::load_yaml!("cli.yml"); let matches = clap::App::from_yaml(yaml).get_matches(); @@ -118,43 +118,6 @@ fn main() { } } -fn initialize() { - let mut builder = env_logger::Builder::new(); - - let filters = match std::env::var("RUST_LOG") { - Ok(env_filters) => format!("bridge=info,{}", env_filters), - Err(_) => "bridge=info".into(), - }; - - builder.parse_filters(&filters); - builder.format(move |buf, record| { - writeln!(buf, "{}", { - let timestamp = time::OffsetDateTime::now_local().format("%Y-%m-%d %H:%M:%S %z"); - if cfg!(windows) { - format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) - } else { - use ansi_term::Colour as Color; - let log_level = match record.level() { - log::Level::Error => Color::Fixed(9).bold().paint(record.level().to_string()), - log::Level::Warn => Color::Fixed(11).bold().paint(record.level().to_string()), - log::Level::Info => Color::Fixed(10).paint(record.level().to_string()), - log::Level::Debug => Color::Fixed(14).paint(record.level().to_string()), - log::Level::Trace => Color::Fixed(12).paint(record.level().to_string()), - }; - format!( - "{} {} {} {}", - Color::Fixed(8).bold().paint(timestamp), - log_level, - Color::Fixed(8).paint(record.target()), - record.args() - ) - } - }) - }); - - builder.init(); -} - fn ethereum_connection_params(matches: &clap::ArgMatches) -> Result { let mut params = EthereumConnectionParams::default(); if let Some(eth_host) = matches.value_of("eth-host") { diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 3351a3fb43534..bd52598ff596b 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,15 +8,19 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.2" async-trait = "0.1.41" -bp-rialto = { path = "../../primitives/rialto" } codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.5" -headers-relay = { path = "../headers-relay" } log = "0.4.11" -messages-relay = { path = "../messages-relay" } paste = "1.0" +sp-runtime = "2.0" +structopt = "0.3" + +# Bridge dependencies + +bp-rialto = { path = "../../primitives/rialto" } +headers-relay = { path = "../headers-relay" } +messages-relay = { path = "../messages-relay" } relay-millau-client = { path = "../millau-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } -sp-runtime = "2.0" -structopt = "0.3" +relay-utils = { path = "../utils" } diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index a42d721759221..09728ef6941c7 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -20,6 +20,7 @@ use relay_rialto_client::SigningParams as RialtoSigningParams; use relay_substrate_client::ConnectionParams; +use relay_utils::initialize::initialize_relay; /// Millau node client. pub type MillauClient = relay_substrate_client::Client; @@ -30,6 +31,8 @@ mod cli; mod millau_headers_to_rialto; fn main() { + initialize_relay(); + let result = async_std::task::block_on(run_command(cli::parse_args())); if let Err(error) = result { log::error!(target: "bridge", "Failed to start relay: {}", error); @@ -58,7 +61,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { rialto_sign.rialto_signer_password.as_deref(), ) .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign) + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign); } } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 04113bfdd1b85..eeb49369f9295 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -6,11 +6,14 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +ansi_term = "0.12" async-std = "1.6.5" backoff = "0.2" +env_logger = "0.7.0" futures = "0.3.5" log = "0.4.11" sysinfo = "0.15" +time = "0.2" # Substrate dependencies diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs new file mode 100644 index 0000000000000..c6c395d18e02a --- /dev/null +++ b/relays/utils/src/initialize.rs @@ -0,0 +1,57 @@ +// Copyright 2019-2020 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 . + +//! Relayer initialization functions. + +use std::io::Write; + +/// Initialize relay environment. +pub fn initialize_relay() { + let mut builder = env_logger::Builder::new(); + + let filters = match std::env::var("RUST_LOG") { + Ok(env_filters) => format!("bridge=info,{}", env_filters), + Err(_) => "bridge=info".into(), + }; + + builder.parse_filters(&filters); + builder.format(move |buf, record| { + writeln!(buf, "{}", { + let timestamp = time::OffsetDateTime::now_local().format("%Y-%m-%d %H:%M:%S %z"); + if cfg!(windows) { + format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) + } else { + use ansi_term::Colour as Color; + let log_level = match record.level() { + log::Level::Error => Color::Fixed(9).bold().paint(record.level().to_string()), + log::Level::Warn => Color::Fixed(11).bold().paint(record.level().to_string()), + log::Level::Info => Color::Fixed(10).paint(record.level().to_string()), + log::Level::Debug => Color::Fixed(14).paint(record.level().to_string()), + log::Level::Trace => Color::Fixed(12).paint(record.level().to_string()), + }; + format!( + "{} {} {} {}", + Color::Fixed(8).bold().paint(timestamp), + log_level, + Color::Fixed(8).paint(record.target()), + record.args() + ) + } + }) + }); + + builder.init(); +} diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 0b4d682c1cd41..49f2ae996598e 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -27,6 +27,7 @@ pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); /// reconnection again. pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); +pub mod initialize; pub mod metrics; /// Macro that returns (client, Err(error)) tuple from function if result is Err(error). From 12e4864847681112100537628cb077cfc1d8235c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Oct 2020 04:36:59 -0400 Subject: [PATCH 0176/1210] Split Rialto and Millau Nodes (#372) * Split the Rialto Node into a standalone crate * Split the Millau Node into a standalone crate * Remove `bridge-node` crate * Add benchmarking feature to nodes * Check that benchmarks compile in CI * Remove nodes from CI matrix * Update Rialto node to Substrate 2.0 * Get Millau node compiling with Substrate 2.0 * Remove extra license text * Remove comments in TOML files * Move nodes and runtimes into Rialto and Millau folders * Fix dependency paths * Remove unused script * Add issue to benchmarking TODO * Fix benchmark manifest paths --- bin/millau-node/Cargo.toml | 10 - bin/millau/node/Cargo.toml | 54 +++ bin/{ => millau}/node/build.rs | 0 bin/millau/node/src/chain_spec.rs | 166 +++++++++ bin/{ => millau}/node/src/cli.rs | 0 bin/millau/node/src/command.rs | 161 ++++++++ bin/{ => millau}/node/src/lib.rs | 0 bin/{millau-node => millau/node}/src/main.rs | 12 +- bin/millau/node/src/service.rs | 348 ++++++++++++++++++ .../runtime}/Cargo.toml | 10 +- .../runtime}/build.rs | 0 .../runtime}/src/lib.rs | 0 bin/rialto-node/Cargo.toml | 16 - bin/{ => rialto}/node/Cargo.toml | 14 +- bin/rialto/node/build.rs | 25 ++ bin/{ => rialto}/node/src/chain_spec.rs | 0 bin/rialto/node/src/cli.rs | 67 ++++ bin/{ => rialto}/node/src/command.rs | 22 +- bin/{rialto-node => rialto/node}/src/main.rs | 12 +- bin/{ => rialto}/node/src/service.rs | 0 .../runtime}/Cargo.toml | 22 +- .../runtime}/build.rs | 0 .../runtime}/src/benches.rs | 0 .../runtime}/src/exchange.rs | 0 .../runtime}/src/kovan.rs | 0 .../runtime}/src/lib.rs | 0 .../runtime}/src/rialto.rs | 0 bin/scripts/init.sh | 12 - modules/ethereum-contract/builtin/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/millau-client/Cargo.toml | 2 +- relays/rialto-client/Cargo.toml | 2 +- 32 files changed, 866 insertions(+), 93 deletions(-) delete mode 100644 bin/millau-node/Cargo.toml create mode 100644 bin/millau/node/Cargo.toml rename bin/{ => millau}/node/build.rs (100%) create mode 100644 bin/millau/node/src/chain_spec.rs rename bin/{ => millau}/node/src/cli.rs (100%) create mode 100644 bin/millau/node/src/command.rs rename bin/{ => millau}/node/src/lib.rs (100%) rename bin/{millau-node => millau/node}/src/main.rs (85%) create mode 100644 bin/millau/node/src/service.rs rename bin/{millau-runtime => millau/runtime}/Cargo.toml (85%) rename bin/{millau-runtime => millau/runtime}/build.rs (100%) rename bin/{millau-runtime => millau/runtime}/src/lib.rs (100%) delete mode 100644 bin/rialto-node/Cargo.toml rename bin/{ => rialto}/node/Cargo.toml (79%) create mode 100644 bin/rialto/node/build.rs rename bin/{ => rialto}/node/src/chain_spec.rs (100%) create mode 100644 bin/rialto/node/src/cli.rs rename bin/{ => rialto}/node/src/command.rs (84%) rename bin/{rialto-node => rialto/node}/src/main.rs (85%) rename bin/{ => rialto}/node/src/service.rs (100%) rename bin/{rialto-runtime => rialto/runtime}/Cargo.toml (78%) rename bin/{rialto-runtime => rialto/runtime}/build.rs (100%) rename bin/{rialto-runtime => rialto/runtime}/src/benches.rs (100%) rename bin/{rialto-runtime => rialto/runtime}/src/exchange.rs (100%) rename bin/{rialto-runtime => rialto/runtime}/src/kovan.rs (100%) rename bin/{rialto-runtime => rialto/runtime}/src/lib.rs (100%) rename bin/{rialto-runtime => rialto/runtime}/src/rialto.rs (100%) delete mode 100755 bin/scripts/init.sh diff --git a/bin/millau-node/Cargo.toml b/bin/millau-node/Cargo.toml deleted file mode 100644 index 646841abdc5de..0000000000000 --- a/bin/millau-node/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "millau-bridge-node" -description = "Substrate node compatible with Millau runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -bridge-node = { path = "../node", default-features = false, features = ["millau"] } diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml new file mode 100644 index 0000000000000..a6dc223e84cab --- /dev/null +++ b/bin/millau/node/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "millau-bridge-node" +description = "Substrate node compatible with Millau runtime" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +build = "build.rs" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +jsonrpc-core = "15.0.0" +structopt = "0.3.17" + +# Bridge dependencies + +millau-runtime = { path = "../runtime" } + +# Substrate Dependencies + +frame-benchmarking = "2.0" +frame-benchmarking-cli = "2.0" +sc-basic-authorship = "0.8" +sc-cli = "0.8" +sc-client-api = "2.0" +sc-consensus = "0.8" +sc-consensus-aura = "0.8" +sc-executor = "0.8" +sc-finality-grandpa = "0.8" +sc-service = "0.8" +sc-rpc = "2.0" +sc-transaction-pool = "2.0" +sp-consensus = "0.8" +sp-consensus-aura = "0.8" +sp-core = "2.0" +sp-inherents = "2.0" +sp-finality-grandpa = "2.0" +sp-runtime = "2.0" +substrate-frame-rpc-system = "2.0" + +[build-dependencies] +build-script-utils = { package = "substrate-build-script-utils", version = "2.0" } +frame-benchmarking-cli = "2.0" +vergen = "3.1.0" + +[features] +default = [] + +# TODO: https://github.com/paritytech/parity-bridges-common/issues/390 +# I've left the feature flag here to test our CI configuration +runtime-benchmarks = [ + # "millau-runtime/runtime-benchmarks", +] diff --git a/bin/node/build.rs b/bin/millau/node/build.rs similarity index 100% rename from bin/node/build.rs rename to bin/millau/node/build.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs new file mode 100644 index 0000000000000..df66c3318e5b8 --- /dev/null +++ b/bin/millau/node/src/chain_spec.rs @@ -0,0 +1,166 @@ +// Copyright 2019-2020 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 . + +use millau_runtime::{ + AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, + SudoConfig, SystemConfig, WASM_BINARY, +}; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{sr25519, Pair, Public}; +use sp_finality_grandpa::AuthorityId as GrandpaId; +use sp_runtime::traits::{IdentifyAccount, Verify}; + +/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. +pub type ChainSpec = sc_service::GenericChainSpec; + +/// The chain specification option. This is expected to come in from the CLI and +/// is little more than one of a number of alternatives which can easily be converted +/// from a string (`--chain=...`) into a `ChainSpec`. +#[derive(Clone, Debug)] +pub enum Alternative { + /// Whatever the current runtime is, with just Alice as an auth. + Development, + /// Whatever the current runtime is, with simple Alice/Bob/Charlie/Dave/Eve auths. + LocalTestnet, +} + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +type AccountPublic = ::Signer; + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Helper function to generate an authority key for Aura +pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { + ( + get_account_id_from_seed::(s), + get_from_seed::(s), + get_from_seed::(s), + ) +} + +impl Alternative { + /// Get an actual chain config from one of the alternatives. + pub(crate) fn load(self) -> Result { + Ok(match self { + Alternative::Development => ChainSpec::from_genesis( + "Development", + "dev", + sc_service::ChainType::Development, + || { + testnet_genesis( + vec![get_authority_keys_from_seed("Alice")], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + true, + ) + }, + vec![], + None, + None, + None, + None, + ), + Alternative::LocalTestnet => ChainSpec::from_genesis( + "Local Testnet", + "local_testnet", + sc_service::ChainType::Local, + || { + testnet_genesis( + vec![ + get_authority_keys_from_seed("Alice"), + get_authority_keys_from_seed("Bob"), + get_authority_keys_from_seed("Charlie"), + get_authority_keys_from_seed("Dave"), + get_authority_keys_from_seed("Eve"), + ], + get_account_id_from_seed::("Alice"), + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + true, + ) + }, + vec![], + None, + None, + None, + None, + ), + }) + } +} + +fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { + SessionKeys { aura, grandpa } +} + +fn testnet_genesis( + initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, + root_key: AccountId, + endowed_accounts: Vec, + _enable_println: bool, +) -> GenesisConfig { + GenesisConfig { + frame_system: Some(SystemConfig { + code: WASM_BINARY.to_vec(), + changes_trie_config: Default::default(), + }), + pallet_balances: Some(BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + }), + pallet_aura: Some(AuraConfig { + authorities: Vec::new(), + }), + pallet_grandpa: Some(GrandpaConfig { + authorities: Vec::new(), + }), + pallet_sudo: Some(SudoConfig { key: root_key }), + pallet_session: Some(SessionConfig { + keys: initial_authorities + .iter() + .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) + .collect::>(), + }), + } +} diff --git a/bin/node/src/cli.rs b/bin/millau/node/src/cli.rs similarity index 100% rename from bin/node/src/cli.rs rename to bin/millau/node/src/cli.rs diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs new file mode 100644 index 0000000000000..fcd107d1ee009 --- /dev/null +++ b/bin/millau/node/src/command.rs @@ -0,0 +1,161 @@ +// Copyright 2019-2020 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 . + +use crate::cli::{Cli, Subcommand}; +use crate::service; +use crate::service::new_partial; +use millau_runtime::Block; +use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; +use sc_service::PartialComponents; + +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Millau Bridge Node".into() + } + + fn impl_version() -> String { + env!("CARGO_PKG_VERSION").into() + } + + fn description() -> String { + "Millau Bridge Node".into() + } + + fn author() -> String { + "Parity Technologies".into() + } + + fn support_url() -> String { + "https://github.com/paritytech/parity-bridges-common/".into() + } + + fn copyright_start_year() -> i32 { + 2019 + } + + fn executable_name() -> String { + "millau-bridge-node".into() + } + + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &millau_runtime::VERSION + } + + fn load_spec(&self, id: &str) -> Result, String> { + Ok(Box::new( + match id { + "" | "dev" => crate::chain_spec::Alternative::Development, + "local" => crate::chain_spec::Alternative::LocalTestnet, + _ => return Err(format!("Unsupported chain specification: {}", id)), + } + .load()?, + )) + } +} + +/// Parse and run command line arguments +pub fn run() -> sc_cli::Result<()> { + let cli = Cli::from_args(); + + match &cli.subcommand { + Some(Subcommand::Benchmark(cmd)) => { + if cfg!(feature = "runtime-benchmarks") { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| cmd.run::(config)) + } else { + println!( + "Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + ); + Ok(()) + } + } + Some(Subcommand::Key(cmd)) => cmd.run(), + Some(Subcommand::Sign(cmd)) => cmd.run(), + Some(Subcommand::Verify(cmd)) => cmd.run(), + Some(Subcommand::Vanity(cmd)) => cmd.run(), + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + } + Some(Subcommand::CheckBlock(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::ExportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, task_manager, .. + } = new_partial(&config)?; + Ok((cmd.run(client, config.database), task_manager)) + }) + } + Some(Subcommand::ExportState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, task_manager, .. + } = new_partial(&config)?; + Ok((cmd.run(client, config.chain_spec), task_manager)) + }) + } + Some(Subcommand::ImportBlocks(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = new_partial(&config)?; + Ok((cmd.run(client, import_queue), task_manager)) + }) + } + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.database)) + } + Some(Subcommand::Revert(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.async_run(|config| { + let PartialComponents { + client, + task_manager, + backend, + .. + } = new_partial(&config)?; + Ok((cmd.run(client, backend), task_manager)) + }) + } + None => { + let runner = cli.create_runner(&cli.run)?; + runner.run_node_until_exit(|config| match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + }) + } + } +} diff --git a/bin/node/src/lib.rs b/bin/millau/node/src/lib.rs similarity index 100% rename from bin/node/src/lib.rs rename to bin/millau/node/src/lib.rs diff --git a/bin/millau-node/src/main.rs b/bin/millau/node/src/main.rs similarity index 85% rename from bin/millau-node/src/main.rs rename to bin/millau/node/src/main.rs index 6ce72ef75c823..07ec88727df5f 100644 --- a/bin/millau-node/src/main.rs +++ b/bin/millau/node/src/main.rs @@ -18,7 +18,13 @@ #![warn(missing_docs)] -/// Run node. -fn main() -> bridge_node::Result { - bridge_node::run() +mod chain_spec; +#[macro_use] +mod service; +mod cli; +mod command; + +/// Run the Millau Node +fn main() -> sc_cli::Result<()> { + command::run() } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs new file mode 100644 index 0000000000000..e2e83d5a721ea --- /dev/null +++ b/bin/millau/node/src/service.rs @@ -0,0 +1,348 @@ +// Copyright 2019-2020 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 . + +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +// ===================================================================================== +// ===================================================================================== +// ===================================================================================== +// UPDATE GUIDE: +// 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); +// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom RPCs; +// 3) fix compilation errors; +// 4) test :) +// ===================================================================================== +// ===================================================================================== +// ===================================================================================== + +use millau_runtime::{self, opaque::Block, RuntimeApi}; +use sc_client_api::{ExecutorProvider, RemoteBackend}; +use sc_executor::native_executor_instance; +pub use sc_executor::NativeExecutor; +use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; +use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_inherents::InherentDataProviders; +use std::sync::Arc; +use std::time::Duration; + +// Our native executor instance. +native_executor_instance!( + pub Executor, + millau_runtime::api::dispatch, + millau_runtime::native_version, + frame_benchmarking::benchmarking::HostFunctions, +); + +type FullClient = sc_service::TFullClient; +type FullBackend = sc_service::TFullBackend; +type FullSelectChain = sc_consensus::LongestChain; + +#[allow(clippy::type_complexity)] +pub fn new_partial( + config: &Configuration, +) -> Result< + sc_service::PartialComponents< + FullClient, + FullBackend, + FullSelectChain, + sp_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, + ( + sc_finality_grandpa::GrandpaBlockImport, + sc_finality_grandpa::LinkHalf, + ), + >, + ServiceError, +> { + let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + + let (client, backend, keystore, task_manager) = sc_service::new_full_parts::(&config)?; + let client = Arc::new(client); + + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.prometheus_registry(), + task_manager.spawn_handle(), + client.clone(), + ); + + let (grandpa_block_import, grandpa_link) = + sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; + + let aura_block_import = + sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( + sc_consensus_aura::slot_duration(&*client)?, + aura_block_import, + Some(Box::new(grandpa_block_import.clone())), + None, + client.clone(), + inherent_data_providers.clone(), + &task_manager.spawn_handle(), + config.prometheus_registry(), + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + )?; + + Ok(sc_service::PartialComponents { + client, + backend, + task_manager, + import_queue, + keystore, + select_chain, + transaction_pool, + inherent_data_providers, + other: (grandpa_block_import, grandpa_link), + }) +} + +/// Builds a new service for a full client. +pub fn new_full(config: Configuration) -> Result { + let sc_service::PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore, + select_chain, + transaction_pool, + inherent_data_providers, + other: (block_import, grandpa_link), + } = new_partial(&config)?; + + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + + let (network, network_status_sinks, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + finality_proof_request_builder: None, + finality_proof_provider: Some(finality_proof_provider), + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + backend.clone(), + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + } + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let name = config.network.node_name.clone(); + let enable_grandpa = !config.disable_grandpa; + let prometheus_registry = config.prometheus_registry().cloned(); + let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); + + let rpc_extensions_builder = { + use sc_rpc::DenyUnsafe; + use substrate_frame_rpc_system::{FullSystem, SystemApi}; + + let client = client.clone(); + let pool = transaction_pool.clone(); + + Box::new(move |_, _| { + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with(SystemApi::to_delegate(FullSystem::new( + client.clone(), + pool.clone(), + DenyUnsafe::No, + ))); + + io + }) + }; + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network: network.clone(), + client: client.clone(), + keystore: keystore.clone(), + task_manager: &mut task_manager, + transaction_pool: transaction_pool.clone(), + telemetry_connection_sinks: telemetry_connection_sinks.clone(), + rpc_extensions_builder, + on_demand: None, + remote_blockchain: None, + backend, + network_status_sinks, + system_rpc_tx, + config, + })?; + + if role.is_authority() { + let proposer = + sc_basic_authorship::ProposerFactory::new(client.clone(), transaction_pool, prometheus_registry.as_ref()); + + let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + + let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( + sc_consensus_aura::slot_duration(&*client)?, + client.clone(), + select_chain, + block_import, + proposer, + network.clone(), + inherent_data_providers.clone(), + force_authoring, + keystore.clone(), + can_author_with, + )?; + + // the AURA authoring task is considered essential, i.e. if it + // fails we take down the service with it. + task_manager.spawn_essential_handle().spawn_blocking("aura", aura); + } + + // if the node isn't actively participating in consensus then it doesn't + // need a keystore, regardless of which protocol we use below. + let keystore = if role.is_authority() { + Some(keystore as sp_core::traits::BareCryptoStorePtr) + } else { + None + }; + + let grandpa_config = sc_finality_grandpa::Config { + // FIXME #1578 make this available through chainspec + gossip_duration: Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: false, + keystore, + is_authority: role.is_network_authority(), + }; + + if enable_grandpa { + // start the full GRANDPA voter + // NOTE: non-authorities could run the GRANDPA observer protocol, but at + // this point the full voter should provide better guarantees of block + // and vote data availability than the observer. The observer has not + // been tested extensively yet and having most nodes in a network run it + // could lead to finality stalls. + let grandpa_config = sc_finality_grandpa::GrandpaParams { + config: grandpa_config, + link: grandpa_link, + network, + inherent_data_providers, + telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), + voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), + prometheus_registry, + shared_voter_state: SharedVoterState::empty(), + }; + + // the GRANDPA voter task is considered infallible, i.e. + // if it fails we take down the service with it. + task_manager + .spawn_essential_handle() + .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); + } else { + sc_finality_grandpa::setup_disabled_grandpa(client, &inherent_data_providers, network)?; + } + + network_starter.start_network(); + Ok(task_manager) +} + +/// Builds a new service for a light client. +pub fn new_light(config: Configuration) -> Result { + let (client, backend, keystore, mut task_manager, on_demand) = + sc_service::new_light_parts::(&config)?; + + let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( + config.transaction_pool.clone(), + config.prometheus_registry(), + task_manager.spawn_handle(), + client.clone(), + on_demand.clone(), + )); + + let grandpa_block_import = sc_finality_grandpa::light_block_import( + client.clone(), + backend.clone(), + &(client.clone() as Arc<_>), + Arc::new(on_demand.checker().clone()) as Arc<_>, + )?; + let finality_proof_import = grandpa_block_import.clone(); + let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); + + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( + sc_consensus_aura::slot_duration(&*client)?, + grandpa_block_import, + None, + Some(Box::new(finality_proof_import)), + client.clone(), + InherentDataProviders::new(), + &task_manager.spawn_handle(), + config.prometheus_registry(), + sp_consensus::NeverCanAuthor, + )?; + + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + + let (network, network_status_sinks, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: Some(on_demand.clone()), + block_announce_validator_builder: None, + finality_proof_request_builder: Some(finality_proof_request_builder), + finality_proof_provider: Some(finality_proof_provider), + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + backend.clone(), + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + } + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + remote_blockchain: Some(backend.remote_blockchain()), + transaction_pool, + task_manager: &mut task_manager, + on_demand: Some(on_demand), + rpc_extensions_builder: Box::new(|_, _| ()), + telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), + config, + client, + keystore, + backend, + network, + network_status_sinks, + system_rpc_tx, + })?; + + network_starter.start_network(); + + Ok(task_manager) +} diff --git a/bin/millau-runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml similarity index 85% rename from bin/millau-runtime/Cargo.toml rename to bin/millau/runtime/Cargo.toml index 85db10f4dcb0e..039444b1e55b0 100644 --- a/bin/millau-runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -13,11 +13,11 @@ serde = { version = "1.0.115", optional = true, features = ["derive"] } # Bridge dependencies -bp-message-lane = { path = "../../primitives/message-lane", default-features = false } -bp-millau = { path = "../../primitives/millau", default-features = false } -pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } -pallet-message-lane = { path = "../../modules/message-lane", default-features = false } -pallet-shift-session-manager = { path = "../../modules/shift-session-manager", default-features = false } +bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } +bp-millau = { path = "../../../primitives/millau", default-features = false } +pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } +pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } +pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies diff --git a/bin/millau-runtime/build.rs b/bin/millau/runtime/build.rs similarity index 100% rename from bin/millau-runtime/build.rs rename to bin/millau/runtime/build.rs diff --git a/bin/millau-runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs similarity index 100% rename from bin/millau-runtime/src/lib.rs rename to bin/millau/runtime/src/lib.rs diff --git a/bin/rialto-node/Cargo.toml b/bin/rialto-node/Cargo.toml deleted file mode 100644 index 215cf60faa28e..0000000000000 --- a/bin/rialto-node/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "rialto-bridge-node" -description = "Substrate node compatible with Rialto runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -bridge-node = { path = "../node", default-features = false, features = ["rialto"] } - -[features] -default = [] -runtime-benchmarks = [ - "bridge-node/runtime-benchmarks", -] diff --git a/bin/node/Cargo.toml b/bin/rialto/node/Cargo.toml similarity index 79% rename from bin/node/Cargo.toml rename to bin/rialto/node/Cargo.toml index 628ba7552568d..db4f2a093f543 100644 --- a/bin/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -1,5 +1,6 @@ [package] -name = "bridge-node" +name = "rialto-bridge-node" +description = "Substrate node compatible with Rialto runtime" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" @@ -14,9 +15,8 @@ structopt = "0.3.17" # Bridge dependencies -millau-runtime = { path = "../millau-runtime", optional = true } -pallet-message-lane-rpc = { path = "../../modules/message-lane/rpc" } -rialto-runtime = { path = "../rialto-runtime", optional = true } +pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } +rialto-runtime = { path = "../runtime" } # Substrate Dependencies @@ -47,12 +47,6 @@ vergen = "3.1.0" [features] default = [] -millau = [ - "millau-runtime", -] -rialto = [ - "rialto-runtime", -] runtime-benchmarks = [ "rialto-runtime/runtime-benchmarks", ] diff --git a/bin/rialto/node/build.rs b/bin/rialto/node/build.rs new file mode 100644 index 0000000000000..e9a10ff8ad009 --- /dev/null +++ b/bin/rialto/node/build.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2020 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 . + +use vergen::{generate_cargo_keys, ConstantsFlags}; + +const ERROR_MSG: &str = "Failed to generate metadata files"; + +fn main() { + generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); + + build_script_utils::rerun_if_git_head_changed(); +} diff --git a/bin/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs similarity index 100% rename from bin/node/src/chain_spec.rs rename to bin/rialto/node/src/chain_spec.rs diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs new file mode 100644 index 0000000000000..1149c4f910c8d --- /dev/null +++ b/bin/rialto/node/src/cli.rs @@ -0,0 +1,67 @@ +// Copyright 2019-2020 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 . + +use sc_cli::RunCmd; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +pub struct Cli { + #[structopt(subcommand)] + pub subcommand: Option, + + #[structopt(flatten)] + pub run: RunCmd, +} + +/// Possible subcommands of the main binary. +#[derive(Debug, StructOpt)] +pub enum Subcommand { + /// Key management cli utilities + Key(sc_cli::KeySubcommand), + /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. + Verify(sc_cli::VerifyCmd), + + /// Generate a seed that provides a vanity address. + Vanity(sc_cli::VanityCmd), + + /// Sign a message, with a given (secret) key. + Sign(sc_cli::SignCmd), + + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), + + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), + + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), + + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), + + /// Remove the whole chain. + PurgeChain(sc_cli::PurgeChainCmd), + + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + + /// The custom benchmark subcommmand benchmarking runtime pallets. + #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), +} diff --git a/bin/node/src/command.rs b/bin/rialto/node/src/command.rs similarity index 84% rename from bin/node/src/command.rs rename to bin/rialto/node/src/command.rs index 7a7417c9a5f1d..fb07b77cb0f71 100644 --- a/bin/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// Copyright 2019-2020 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 . - use crate::cli::{Cli, Subcommand}; use crate::service; use crate::service::new_partial; @@ -39,7 +23,7 @@ use sc_service::PartialComponents; impl SubstrateCli for Cli { fn impl_name() -> String { - "Bridge Node".into() + "Rialto Bridge Node".into() } fn impl_version() -> String { @@ -47,7 +31,7 @@ impl SubstrateCli for Cli { } fn description() -> String { - "Bridge Node".into() + "Rialto Bridge Node".into() } fn author() -> String { @@ -63,7 +47,7 @@ impl SubstrateCli for Cli { } fn executable_name() -> String { - "bridge-node".into() + "rialto-bridge-node".into() } fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { diff --git a/bin/rialto-node/src/main.rs b/bin/rialto/node/src/main.rs similarity index 85% rename from bin/rialto-node/src/main.rs rename to bin/rialto/node/src/main.rs index 7e101de175159..164afae2bb90d 100644 --- a/bin/rialto-node/src/main.rs +++ b/bin/rialto/node/src/main.rs @@ -18,7 +18,13 @@ #![warn(missing_docs)] -/// Run node. -fn main() -> bridge_node::Result { - bridge_node::run() +mod chain_spec; +#[macro_use] +mod service; +mod cli; +mod command; + +/// Run the Rialto Node +fn main() -> sc_cli::Result<()> { + command::run() } diff --git a/bin/node/src/service.rs b/bin/rialto/node/src/service.rs similarity index 100% rename from bin/node/src/service.rs rename to bin/rialto/node/src/service.rs diff --git a/bin/rialto-runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml similarity index 78% rename from bin/rialto-runtime/Cargo.toml rename to bin/rialto/runtime/Cargo.toml index 878dfc01b873e..41dd0e9d672e9 100644 --- a/bin/rialto-runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -15,17 +15,17 @@ serde = { version = "1.0.115", optional = true, features = ["derive"] } # Bridge dependencies -bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } -bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } -bp-header-chain = { path = "../../primitives/header-chain", default-features = false } -bp-message-lane = { path = "../../primitives/message-lane", default-features = false } -bp-millau = { path = "../../primitives/millau", default-features = false } -bp-rialto = { path = "../../primitives/rialto", default-features = false } -pallet-bridge-eth-poa = { path = "../../modules/ethereum", default-features = false } -pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } -pallet-bridge-currency-exchange = { path = "../../modules/currency-exchange", default-features = false } -pallet-message-lane = { path = "../../modules/message-lane", default-features = false } -pallet-shift-session-manager = { path = "../../modules/shift-session-manager", default-features = false } +bp-currency-exchange = { path = "../../../primitives/currency-exchange", default-features = false } +bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = false } +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } +bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } +bp-millau = { path = "../../../primitives/millau", default-features = false } +bp-rialto = { path = "../../../primitives/rialto", default-features = false } +pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } +pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } +pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } +pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } +pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies diff --git a/bin/rialto-runtime/build.rs b/bin/rialto/runtime/build.rs similarity index 100% rename from bin/rialto-runtime/build.rs rename to bin/rialto/runtime/build.rs diff --git a/bin/rialto-runtime/src/benches.rs b/bin/rialto/runtime/src/benches.rs similarity index 100% rename from bin/rialto-runtime/src/benches.rs rename to bin/rialto/runtime/src/benches.rs diff --git a/bin/rialto-runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs similarity index 100% rename from bin/rialto-runtime/src/exchange.rs rename to bin/rialto/runtime/src/exchange.rs diff --git a/bin/rialto-runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs similarity index 100% rename from bin/rialto-runtime/src/kovan.rs rename to bin/rialto/runtime/src/kovan.rs diff --git a/bin/rialto-runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs similarity index 100% rename from bin/rialto-runtime/src/lib.rs rename to bin/rialto/runtime/src/lib.rs diff --git a/bin/rialto-runtime/src/rialto.rs b/bin/rialto/runtime/src/rialto.rs similarity index 100% rename from bin/rialto-runtime/src/rialto.rs rename to bin/rialto/runtime/src/rialto.rs diff --git a/bin/scripts/init.sh b/bin/scripts/init.sh deleted file mode 100755 index 1405a41ef333e..0000000000000 --- a/bin/scripts/init.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo "*** Initializing WASM build environment" - -if [ -z $CI_PROJECT_NAME ] ; then - rustup update nightly - rustup update stable -fi - -rustup target add wasm32-unknown-unknown --toolchain nightly diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index b2adcfbf49ecb..631bc24c44a3f 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.11" # Runtime/chain specific dependencies -rialto-runtime = { path = "../../../bin/rialto-runtime" } +rialto-runtime = { path = "../../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index d496aeff67566..bc60e41b818fa 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -36,7 +36,7 @@ relay-ethereum-client = { path = "../ethereum-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } -rialto-runtime = { path = "../../bin/rialto-runtime" } +rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index cb98370d845a8..3bf0dc426f05f 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -13,7 +13,7 @@ relay-utils = { path = "../utils" } # Supported Chains -millau-runtime = { path = "../../bin/millau-runtime" } +millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml index aec1262a00ec1..2f4be18a66ee4 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/rialto-client/Cargo.toml @@ -13,7 +13,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies -rialto-runtime = { path = "../../bin/rialto-runtime" } +rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies From 1ef0eb40a17b20a96fdd11201a654c9c48bb866b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Oct 2020 18:17:24 +0300 Subject: [PATCH 0177/1210] Message lane loop metrics (#400) * message lane metrics * fmt and clippy --- relays/messages-relay/Cargo.toml | 5 + relays/messages-relay/src/lib.rs | 2 + relays/messages-relay/src/message_lane.rs | 5 +- .../messages-relay/src/message_lane_loop.rs | 55 ++++++++- .../src/message_race_delivery.rs | 22 +++- .../src/message_race_receiving.rs | 22 +++- relays/messages-relay/src/metrics.rs | 106 ++++++++++++++++++ 7 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 relays/messages-relay/src/metrics.rs diff --git a/relays/messages-relay/Cargo.toml b/relays/messages-relay/Cargo.toml index f876b387424fb..aa76679351514 100644 --- a/relays/messages-relay/Cargo.toml +++ b/relays/messages-relay/Cargo.toml @@ -9,7 +9,12 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" futures = "0.3.5" +hex = "0.4" log = "0.4.11" num-traits = "0.2" parking_lot = "0.11.0" + +# Bridge Dependencies + +bp-message-lane = { path = "../../primitives/message-lane" } relay-utils = { path = "../utils" } diff --git a/relays/messages-relay/src/lib.rs b/relays/messages-relay/src/lib.rs index fe764071cfb6f..d1820140d8368 100644 --- a/relays/messages-relay/src/lib.rs +++ b/relays/messages-relay/src/lib.rs @@ -25,6 +25,8 @@ #![recursion_limit = "1024"] #![warn(missing_docs)] +mod metrics; + pub mod message_lane; pub mod message_lane_loop; pub mod message_race_delivery; diff --git a/relays/messages-relay/src/message_lane.rs b/relays/messages-relay/src/message_lane.rs index 9db30926a0ede..3869e6f24d6d2 100644 --- a/relays/messages-relay/src/message_lane.rs +++ b/relays/messages-relay/src/message_lane.rs @@ -37,6 +37,7 @@ pub trait MessageLane { + Debug + Default + From + + Into + Ord + std::ops::Add + One @@ -48,12 +49,12 @@ pub trait MessageLane { type MessagesReceivingProof: Clone; /// Number of the source header. - type SourceHeaderNumber: Clone + Debug + Default + Ord + PartialEq; + type SourceHeaderNumber: Clone + Debug + Default + Ord + PartialEq + Into; /// Hash of the source header. type SourceHeaderHash: Clone + Debug + Default + PartialEq; /// Number of the target header. - type TargetHeaderNumber: Clone + Debug + Default + Ord + PartialEq; + type TargetHeaderNumber: Clone + Debug + Default + Ord + PartialEq + Into; /// Hash of the target header. type TargetHeaderHash: Clone + Debug + Default + PartialEq; } diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index 91d3017e93eae..b2eb7d2820bf9 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -30,10 +30,16 @@ use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_race_delivery::run as run_message_delivery_race; use crate::message_race_receiving::run as run_message_receiving_race; +use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; +use bp_message_lane::LaneId; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; -use relay_utils::{interval, process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; +use relay_utils::{ + interval, + metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + process_future_result, retry_backoff, FailedClient, MaybeConnectionError, +}; use std::{fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; /// Source client trait. @@ -132,19 +138,37 @@ pub struct ClientsState { } /// Run message lane service loop. +#[allow(clippy::too_many_arguments)] pub fn run( + lane: LaneId, mut source_client: impl SourceClient

, source_tick: Duration, mut target_client: impl TargetClient

, target_tick: Duration, reconnect_delay: Duration, stall_timeout: Duration, + metrics_params: Option, exit_signal: impl Future, ) { let mut local_pool = futures::executor::LocalPool::new(); let exit_signal = exit_signal.shared(); local_pool.run_until(async move { + let mut metrics_global = GlobalMetrics::default(); + let metrics_msg = MessageLaneLoopMetrics::default(); + let metrics_enabled = metrics_params.is_some(); + metrics_start( + format!( + "{}_to_{}_MessageLoop/{}", + P::SOURCE_NAME, + P::TARGET_NAME, + hex::encode(lane) + ), + metrics_params, + &metrics_global, + &metrics_msg, + ); + loop { let result = run_until_connection_lost( source_client.clone(), @@ -152,6 +176,16 @@ pub fn run( target_client.clone(), target_tick, stall_timeout, + if metrics_enabled { + Some(&mut metrics_global) + } else { + None + }, + if metrics_enabled { + Some(metrics_msg.clone()) + } else { + None + }, exit_signal.clone(), ) .await; @@ -180,12 +214,15 @@ pub fn run( } /// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. +#[allow(clippy::too_many_arguments)] async fn run_until_connection_lost, TC: TargetClient

>( source_client: SC, source_tick: Duration, target_client: TC, target_tick: Duration, stall_timeout: Duration, + mut metrics_global: Option<&mut GlobalMetrics>, + metrics_msg: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { let mut source_retry_backoff = retry_backoff(); @@ -212,6 +249,7 @@ async fn run_until_connection_lost, TC: Targ target_client.clone(), delivery_target_state_receiver, stall_timeout, + metrics_msg.clone(), ) .fuse(); @@ -225,6 +263,7 @@ async fn run_until_connection_lost, TC: Targ target_client.clone(), receiving_target_state_receiver, stall_timeout, + metrics_msg.clone(), ) .fuse(); @@ -259,6 +298,10 @@ async fn run_until_connection_lost, TC: Targ ); let _ = delivery_source_state_sender.unbounded_send(new_source_state.clone()); let _ = receiving_source_state_sender.unbounded_send(new_source_state.clone()); + + if let Some(metrics_msg) = metrics_msg.as_ref() { + metrics_msg.update_source_state::

(new_source_state); + } }, &mut source_go_offline_future, |delay| async_std::task::sleep(delay), @@ -286,6 +329,10 @@ async fn run_until_connection_lost, TC: Targ ); let _ = delivery_target_state_sender.unbounded_send(new_target_state.clone()); let _ = receiving_target_state_sender.unbounded_send(new_target_state.clone()); + + if let Some(metrics_msg) = metrics_msg.as_ref() { + metrics_msg.update_target_state::

(new_target_state); + } }, &mut target_go_offline_future, |delay| async_std::task::sleep(delay), @@ -317,6 +364,10 @@ async fn run_until_connection_lost, TC: Targ } } + if let Some(metrics_global) = metrics_global.as_mut() { + metrics_global.update(); + } + if source_client_is_online && source_state_required { log::debug!(target: "bridge", "Asking {} node about its state", P::SOURCE_NAME); source_state.set(source_client.state().fuse()); @@ -562,12 +613,14 @@ pub(crate) mod tests { tick: target_tick, }; run( + [0, 0, 0, 0], source_client, Duration::from_millis(100), target_client, Duration::from_millis(100), Duration::from_millis(0), Duration::from_secs(60), + None, exit_signal, ); diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 7cac96c01b488..d725f256878f7 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -19,6 +19,7 @@ use crate::message_lane_loop::{ TargetClientState, }; use crate::message_race_loop::{MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; +use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use futures::stream::FusedStream; @@ -36,15 +37,18 @@ pub async fn run( target_client: impl MessageLaneTargetClient

, target_state_updates: impl FusedStream>, stall_timeout: Duration, + metrics_msg: Option, ) -> Result<(), FailedClient> { crate::message_race_loop::run( MessageDeliveryRaceSource { client: source_client, + metrics_msg: metrics_msg.clone(), _phantom: Default::default(), }, source_state_updates, MessageDeliveryRaceTarget { client: target_client, + metrics_msg, _phantom: Default::default(), }, target_state_updates, @@ -76,6 +80,7 @@ impl MessageRace for MessageDeliveryRace

{ /// Message delivery race source, which is a source of the lane. struct MessageDeliveryRaceSource { client: C, + metrics_msg: Option, _phantom: PhantomData

, } @@ -91,7 +96,13 @@ where &self, at_block: SourceHeaderIdOf

, ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { - self.client.latest_generated_nonce(at_block).await + let result = self.client.latest_generated_nonce(at_block).await; + if let Some(metrics_msg) = self.metrics_msg.as_ref() { + if let Ok((_, source_latest_generated_nonce)) = result.as_ref() { + metrics_msg.update_target_latest_received_nonce::

(*source_latest_generated_nonce); + } + } + result } async fn generate_proof( @@ -106,6 +117,7 @@ where /// Message delivery race target, which is a target of the lane. struct MessageDeliveryRaceTarget { client: C, + metrics_msg: Option, _phantom: PhantomData

, } @@ -121,7 +133,13 @@ where &self, at_block: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { - self.client.latest_received_nonce(at_block).await + let result = self.client.latest_received_nonce(at_block).await; + if let Some(metrics_msg) = self.metrics_msg.as_ref() { + if let Ok((_, target_latest_received_nonce)) = result.as_ref() { + metrics_msg.update_target_latest_received_nonce::

(*target_latest_received_nonce); + } + } + result } async fn submit_proof( diff --git a/relays/messages-relay/src/message_race_receiving.rs b/relays/messages-relay/src/message_race_receiving.rs index 4eeea7adbd374..d985020fddda1 100644 --- a/relays/messages-relay/src/message_race_receiving.rs +++ b/relays/messages-relay/src/message_race_receiving.rs @@ -20,6 +20,7 @@ use crate::message_lane_loop::{ }; use crate::message_race_delivery::DeliveryStrategy; use crate::message_race_loop::{MessageRace, SourceClient, TargetClient}; +use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use futures::stream::FusedStream; @@ -43,15 +44,18 @@ pub async fn run( target_client: impl MessageLaneTargetClient

, target_state_updates: impl FusedStream>, stall_timeout: Duration, + metrics_msg: Option, ) -> Result<(), FailedClient> { crate::message_race_loop::run( ReceivingConfirmationsRaceSource { client: target_client, + metrics_msg: metrics_msg.clone(), _phantom: Default::default(), }, target_state_updates, ReceivingConfirmationsRaceTarget { client: source_client, + metrics_msg, _phantom: Default::default(), }, source_state_updates, @@ -83,6 +87,7 @@ impl MessageRace for ReceivingConfirmationsRace

{ /// Message receiving confirmations race source, which is a target of the lane. struct ReceivingConfirmationsRaceSource { client: C, + metrics_msg: Option, _phantom: PhantomData

, } @@ -98,7 +103,13 @@ where &self, at_block: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { - self.client.latest_received_nonce(at_block).await + let result = self.client.latest_received_nonce(at_block).await; + if let Some(metrics_msg) = self.metrics_msg.as_ref() { + if let Ok((_, target_latest_received_nonce)) = result.as_ref() { + metrics_msg.update_target_latest_received_nonce::

(*target_latest_received_nonce); + } + } + result } async fn generate_proof( @@ -123,6 +134,7 @@ where /// Message receiving confirmations race target, which is a source of the lane. struct ReceivingConfirmationsRaceTarget { client: C, + metrics_msg: Option, _phantom: PhantomData

, } @@ -138,7 +150,13 @@ where &self, at_block: SourceHeaderIdOf

, ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { - self.client.latest_confirmed_received_nonce(at_block).await + let result = self.client.latest_confirmed_received_nonce(at_block).await; + if let Some(metrics_msg) = self.metrics_msg.as_ref() { + if let Ok((_, source_latest_confirmed_nonce)) = result.as_ref() { + metrics_msg.update_source_latest_confirmed_nonce::

(*source_latest_confirmed_nonce); + } + } + result } async fn submit_proof( diff --git a/relays/messages-relay/src/metrics.rs b/relays/messages-relay/src/metrics.rs new file mode 100644 index 0000000000000..93f4259c106ea --- /dev/null +++ b/relays/messages-relay/src/metrics.rs @@ -0,0 +1,106 @@ +// Copyright 2019-2020 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 . + +//! Metrics for message lane relay loop. + +use crate::message_lane::MessageLane; +use crate::message_lane_loop::{SourceClientState, TargetClientState}; + +use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; + +/// Message lane relay metrics. +/// +/// Cloning only clones references. +#[derive(Clone)] +pub struct MessageLaneLoopMetrics { + /// Best finalized block numbers - "source", "target", "source_at_target", "target_at_source". + best_block_numbers: GaugeVec, + /// Lane state nonces: "source_latest_generated", "source_latest_confirmed", + /// "target_latest_received", "target_latest_confirmed". + lane_state_nonces: GaugeVec, +} + +impl Metrics for MessageLaneLoopMetrics { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; + register(self.lane_state_nonces.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + +impl Default for MessageLaneLoopMetrics { + fn default() -> Self { + MessageLaneLoopMetrics { + best_block_numbers: GaugeVec::new( + Opts::new("best_block_numbers", "Best finalized block numbers"), + &["type"], + ) + .expect("metric is static and thus valid; qed"), + lane_state_nonces: GaugeVec::new(Opts::new("lane_state_nonces", "Nonces of the lane state"), &["type"]) + .expect("metric is static and thus valid; qed"), + } + } +} + +impl MessageLaneLoopMetrics { + /// Update source client state metrics. + pub fn update_source_state(&self, source_client_state: SourceClientState

) { + self.best_block_numbers + .with_label_values(&["source"]) + .set(source_client_state.best_self.0.into()); + self.best_block_numbers + .with_label_values(&["target_at_source"]) + .set(source_client_state.best_peer.0.into()); + } + + /// Update target client state metrics. + pub fn update_target_state(&self, target_client_state: TargetClientState

) { + self.best_block_numbers + .with_label_values(&["target"]) + .set(target_client_state.best_self.0.into()); + self.best_block_numbers + .with_label_values(&["source_at_target"]) + .set(target_client_state.best_peer.0.into()); + } + + /// Update latest generated nonce at source. + pub fn update_source_latest_generated_nonce(&self, source_latest_generated_nonce: P::MessageNonce) { + self.lane_state_nonces + .with_label_values(&["source_latest_generated"]) + .set(source_latest_generated_nonce.into()); + } + + /// Update latest confirmed nonce at source. + pub fn update_source_latest_confirmed_nonce(&self, source_latest_confirmed_nonce: P::MessageNonce) { + self.lane_state_nonces + .with_label_values(&["source_latest_confirmed"]) + .set(source_latest_confirmed_nonce.into()); + } + + /// Update latest received nonce at target. + pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: P::MessageNonce) { + self.lane_state_nonces + .with_label_values(&["target_latest_received"]) + .set(target_latest_generated_nonce.into()); + } + + /// Update latest confirmed nonce at target. + pub fn update_target_latest_confirmed_nonce(&self, target_latest_confirmed_nonce: P::MessageNonce) { + self.lane_state_nonces + .with_label_values(&["target_latest_confirmed"]) + .set(target_latest_confirmed_nonce.into()); + } +} From 61da0d15e9657f6bb263a32cb18d23539326bcd7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Oct 2020 15:53:25 -0400 Subject: [PATCH 0178/1210] Implement Substrate Pallet Runtime APIs (#389) * Implement public helpers for querying header info * Update `best_header` when importing headers * Add BestHeader to GenesisConfig * Define extra types for Millau primitives * Start implementing runtime APIs in Millau runtime * Add helper for getting headers which require a justification * Add runtime API for getting headers requiring a justification * Reword `expect()` proof for valid authority sets * Fix typo * Clean up Hasher comment * Add the Call Dispatch Pallet back to the Millau runtime * Use types from Rialto in bridge pallet config * Use the Rialto runtime APIS in the Millau runtime * Include Millau bridge instance in Rialto runtime * Add missing doc comment * Use one storage function for setting and clearing `RequiresJustification` * Remove TODO comments --- bin/millau/runtime/Cargo.toml | 4 ++ bin/millau/runtime/src/lib.rs | 40 ++++++++++++- bin/rialto/runtime/Cargo.toml | 4 +- bin/rialto/runtime/src/lib.rs | 54 +++++++++++------ modules/substrate/src/lib.rs | 97 +++++++++++++++++++++++++++++++ modules/substrate/src/verifier.rs | 32 +++++++--- primitives/millau/Cargo.toml | 2 + primitives/millau/src/lib.rs | 17 +++++- primitives/rialto/Cargo.toml | 2 + primitives/rialto/src/lib.rs | 17 +++++- 10 files changed, 238 insertions(+), 31 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 039444b1e55b0..e961ccf8c8d74 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -15,9 +15,11 @@ serde = { version = "1.0.115", optional = true, features = ["derive"] } bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } bp-millau = { path = "../../../primitives/millau", default-features = false } +bp-rialto = { path = "../../../primitives/rialto", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } +pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } # Substrate Dependencies @@ -53,6 +55,7 @@ default = ["std"] std = [ "bp-message-lane/std", "bp-millau/std", + "bp-rialto/std", "codec/std", "frame-executive/std", "frame-support/std", @@ -66,6 +69,7 @@ std = [ "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", "pallet-session/std", + "pallet-substrate-bridge/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1adab7e6a2ec4..656b0c292b48a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -54,6 +54,7 @@ pub use frame_support::{ }; pub use pallet_balances::Call as BalancesCall; +pub use pallet_substrate_bridge::Call as BridgeSubstrateCall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] @@ -216,7 +217,6 @@ impl frame_system::Trait for Runtime { impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } - impl pallet_bridge_call_dispatch::Trait for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); @@ -308,6 +308,13 @@ impl pallet_session::Trait for Runtime { type WeightInfo = (); } +impl pallet_substrate_bridge::Trait for Runtime { + type BridgedHeader = bp_rialto::Header; + type BridgedBlockNumber = bp_rialto::BlockNumber; + type BridgedBlockHash = bp_rialto::Hash; + type BridgedBlockHasher = bp_rialto::Hasher; +} + impl pallet_shift_session_manager::Trait for Runtime {} construct_runtime!( @@ -316,6 +323,7 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { + BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, @@ -479,4 +487,34 @@ impl_runtime_apis! { None } } + + impl bp_rialto::RialtoHeaderApi for Runtime { + fn best_block() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { + let header = BridgeRialto::best_header(); + (header.number, header.hash()) + } + + fn finalized_block() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { + let header = BridgeRialto::best_finalized(); + (header.number, header.hash()) + } + + fn incomplete_headers() -> Vec<(bp_rialto::BlockNumber, bp_rialto::Hash)> { + // Since the pallet doesn't accept multiple scheduled changes right now + // we can only have one header requiring a justification at any time. + if let Some(header) = BridgeRialto::requires_justification() { + vec![(header.number, header.hash())] + } else { + vec![] + } + } + + fn is_known_block(hash: bp_rialto::Hash) -> bool { + BridgeRialto::is_known_header(hash) + } + + fn is_finalized_block(hash: bp_rialto::Hash) -> bool { + BridgeRialto::is_finalized_header(hash) + } + } } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 41dd0e9d672e9..60de3e70b448b 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -24,6 +24,7 @@ bp-rialto = { path = "../../../primitives/rialto", default-features = false } pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } +pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } @@ -68,8 +69,8 @@ std = [ "bp-eth-poa/std", "bp-header-chain/std", "bp-message-lane/std", - "bp-millau/std", "bp-rialto/std", + "bp-millau/std", "codec/std", "frame-benchmarking/std", "frame-executive/std", @@ -85,6 +86,7 @@ std = [ "pallet-message-lane/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", + "pallet-substrate-bridge/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 2d0c6fbb0c663..5ee7ff92460f0 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -414,6 +414,13 @@ impl pallet_session::Trait for Runtime { type WeightInfo = (); } +impl pallet_substrate_bridge::Trait for Runtime { + type BridgedHeader = bp_millau::Header; + type BridgedBlockNumber = bp_millau::BlockNumber; + type BridgedBlockHash = bp_millau::Hash; + type BridgedBlockHasher = bp_millau::Hasher; +} + impl pallet_shift_session_manager::Trait for Runtime {} construct_runtime!( @@ -426,6 +433,7 @@ construct_runtime!( BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, + BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, @@ -562,33 +570,45 @@ impl_runtime_apis! { } } - impl bp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { - fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { - BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) - } - } - - impl bp_currency_exchange::KovanCurrencyExchangeApi for Runtime { - fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { - BridgeKovanCurrencyExchange::filter_transaction_proof(&proof) - } - } - impl bp_millau::MillauHeaderApi for Runtime { fn best_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + let header = BridgeMillau::best_header(); + (header.number, header.hash()) } fn finalized_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + let header = BridgeMillau::best_finalized(); + (header.number, header.hash()) } fn incomplete_headers() -> Vec<(bp_millau::BlockNumber, bp_millau::Hash)> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + // Since the pallet doesn't accept multiple scheduled changes right now + // we can only have one header requiring a justification at any time. + if let Some(header) = BridgeMillau::requires_justification() { + vec![(header.number, header.hash())] + } else { + vec![] + } } - fn is_known_block(_hash: bp_millau::Hash) -> bool { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/368") + fn is_known_block(hash: bp_millau::Hash) -> bool { + BridgeMillau::is_known_header(hash) + } + + fn is_finalized_block(hash: bp_millau::Hash) -> bool { + BridgeMillau::is_finalized_header(hash) + } + } + + impl bp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { + fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { + BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) + } + } + + impl bp_currency_exchange::KovanCurrencyExchangeApi for Runtime { + fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { + BridgeKovanCurrencyExchange::filter_transaction_proof(&proof) } } diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index dfc3cb181156e..4b55bd41d75ab 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -109,8 +109,15 @@ pub trait Trait: frame_system::Trait { decl_storage! { trait Store for Module as SubstrateBridge { + /// Hash of the header at the highest known height. + BestHeader: T::BridgedBlockHash; /// Hash of the best finalized header. BestFinalized: T::BridgedBlockHash; + /// A header which enacts an authority set change and therefore + /// requires a Grandpa justification. + // Since we won't always have an authority set change scheduled we + // won't always have a header which needs a justification. + RequiresJustification: Option; /// Headers which have been imported into the pallet. ImportedHeaders: map hasher(identity) T::BridgedBlockHash => Option>; /// The current Grandpa Authority set. @@ -136,6 +143,7 @@ decl_storage! { .clone() .expect("An initial header is needed"); + >::put(initial_header.hash()); >::put(initial_header.hash()); >::insert( initial_header.hash(), @@ -223,6 +231,58 @@ decl_module! { } } +impl Module { + /// Get the highest header that the pallet knows of. + // In a future where we support forks this could be a Vec of headers + // since we may have multiple headers at the same height. + pub fn best_header() -> T::BridgedHeader { + PalletStorage::::new().best_header().header + } + + /// Get the best finalized header the pallet knows of. + /// + /// Since this has been finalized correctly a user of the bridge + /// pallet should be confident that any transactions that were + /// included in this or any previous header will not be reverted. + pub fn best_finalized() -> T::BridgedHeader { + PalletStorage::::new().best_finalized_header().header + } + + /// Check if a particular header is known to the bridge pallet. + pub fn is_known_header(hash: T::BridgedBlockHash) -> bool { + PalletStorage::::new().header_exists(hash) + } + + /// Check if a particular header is finalized. + /// + /// Will return false if the header is not known to the pallet. + // One thing worth noting here is that this approach won't work well + // once we track forks since there could be an older header on a + // different fork which isn't an ancestor of our best finalized header. + pub fn is_finalized_header(hash: T::BridgedBlockHash) -> bool { + let storage = PalletStorage::::new(); + if let Some(header) = storage.header_by_hash(hash) { + header.number() <= storage.best_finalized_header().number() + } else { + false + } + } + + /// Return the latest header which enacts an authority set change + /// and still needs a finality proof. + /// + /// Will return None if there are no headers which are missing finality proofs. + pub fn requires_justification() -> Option { + let storage = PalletStorage::::new(); + let hash = storage.unfinalized_header()?; + let imported_header = storage.header_by_hash(hash).expect( + "We write a header to storage before marking it as unfinalized, therefore + this must always exist if we got an unfinalized header hash.", + ); + Some(imported_header.header) + } +} + /// Expected interface for interacting with bridge pallet storage. // TODO: This should be split into its own less-Substrate-dependent crate pub trait BridgeStorage { @@ -232,6 +292,12 @@ pub trait BridgeStorage { /// Write a header to storage. fn write_header(&mut self, header: &ImportedHeader); + /// Get the header at the highest known height. + fn best_header(&self) -> ImportedHeader; + + /// Update the header at the highest height. + fn update_best_header(&mut self, hash: ::Hash); + /// Get the best finalized header the pallet knows of. fn best_finalized_header(&self) -> ImportedHeader; @@ -241,6 +307,15 @@ pub trait BridgeStorage { /// Check if a particular header is known to the pallet. fn header_exists(&self, hash: ::Hash) -> bool; + /// Return a header which requires a justification. A header will require + /// a justification when it enacts an new authority set. + fn unfinalized_header(&self) -> Option<::Hash>; + + /// Mark a header as eventually requiring a justification. + /// + /// If None is passed the storage item is cleared. + fn update_unfinalized_header(&mut self, hash: Option<::Hash>); + /// Get a specific header by its hash. /// /// Returns None if it is not known to the pallet. @@ -284,6 +359,16 @@ impl BridgeStorage for PalletStorage { >::insert(hash, header); } + fn best_header(&self) -> ImportedHeader { + let hash = >::get(); + self.header_by_hash(hash) + .expect("A header must have been written at genesis, therefore this must always exist") + } + + fn update_best_header(&mut self, hash: T::BridgedBlockHash) { + >::put(hash) + } + fn best_finalized_header(&self) -> ImportedHeader { let hash = >::get(); self.header_by_hash(hash) @@ -302,6 +387,18 @@ impl BridgeStorage for PalletStorage { >::get(hash) } + fn unfinalized_header(&self) -> Option { + >::get() + } + + fn update_unfinalized_header(&mut self, hash: Option<::Hash>) { + if let Some(hash) = hash { + >::put(hash); + } else { + >::kill(); + } + } + fn current_authority_set(&self) -> AuthoritySet { CurrentAuthoritySet::get() } diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 3bf99df5a21f2..edde9d220d712 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -106,13 +106,14 @@ where /// Will perform some basic checks to make sure that this header doesn't break any assumptions /// such as being on a different finalized fork. pub fn import_header(&mut self, header: H) -> Result<(), ImportError> { + let hash = header.hash(); let best_finalized = self.storage.best_finalized_header(); if header.number() <= best_finalized.number() { return Err(ImportError::OldHeader); } - if self.storage.header_exists(header.hash()) { + if self.storage.header_exists(hash) { return Err(ImportError::HeaderAlreadyExists); } @@ -176,13 +177,20 @@ where } }; - let is_finalized = false; self.storage.write_header(&ImportedHeader { header, requires_justification, - is_finalized, + is_finalized: false, }); + if requires_justification { + self.storage.update_unfinalized_header(Some(hash)); + } + + // Since we're not dealing with forks at the moment we know that + // the header we just got will be the one at the best height + self.storage.update_best_header(hash); + Ok(()) } @@ -205,8 +213,8 @@ where let current_authority_set = self.storage.current_authority_set(); let voter_set = VoterSet::new(current_authority_set.authorities).expect( - "This only fails if we have an invalid list of authorities. Since we - got this from storage it should always be valid, otherwise we have a bug.", + "We verified the correctness of the authority list during header import, + before writing them to storage. This must always be valid.", ); verify_justification::( (hash, *header.number()), @@ -255,6 +263,9 @@ where let _ = self.storage.enact_authority_set().expect( "Headers must only be marked as `requires_justification` if there's a scheduled change in storage.", ); + + // Clear the storage entry since we got a justification + self.storage.update_unfinalized_header(None); } for header in finalized_headers.iter_mut() { @@ -442,9 +453,11 @@ mod tests { }; assert_ok!(verifier.import_header(header.clone())); - let stored_header = storage.header_by_hash(header.hash()); - assert!(stored_header.is_some()); - assert_eq!(stored_header.unwrap().is_finalized, false); + let stored_header = storage + .header_by_hash(header.hash()) + .expect("Should have been imported successfully"); + assert_eq!(stored_header.is_finalized, false); + assert_eq!(stored_header, storage.best_header()); }) } @@ -648,11 +661,14 @@ mod tests { }; assert_ok!(verifier.import_header(header.clone())); + assert_eq!(storage.unfinalized_header(), Some(header.hash())); + assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); assert_eq!(storage.best_finalized_header().header, header); // Make sure that we have updated the set now that we've finalized our header assert_eq!(storage.current_authority_set(), change.authority_set); + assert_eq!(storage.unfinalized_header(), None); }) } diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index 831a33b0403ef..2125fa8205b3b 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Substrate Based Dependencies sp-api = { version = "2.0", default-features = false } sp-core = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } [features] @@ -18,5 +19,6 @@ default = ["std"] std = [ "sp-api/std", "sp-core/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 214497d1e8580..dc233caab4ce1 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -20,13 +20,21 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +use sp_core::Hasher as HasherT; +use sp_runtime::traits::BlakeTwo256; use sp_std::prelude::*; /// Block number type used in Millau. pub type BlockNumber = u32; /// Hash type used in Millau. -pub type Hash = sp_core::H256; +pub type Hash = ::Out; + +/// The type of an object that can produce hashes on Millau. +pub type Hasher = BlakeTwo256; + +/// The header type used by Millau. +pub type Header = sp_runtime::generic::Header; sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. @@ -42,8 +50,13 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (BlockNumber, Hash); /// Returns numbers and hashes of headers that require finality proofs. + /// + /// An empty response means that there are no headers which currently require a + /// finality proof. fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; - /// Returns true if header is known to the runtime. + /// Returns true if the header is known to the runtime. fn is_known_block(hash: Hash) -> bool; + /// Returns true if the header is considered finalized by the runtime. + fn is_finalized_block(hash: Hash) -> bool; } } diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index e8a04907b8c37..80616f3863d3d 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Substrate Based Dependencies sp-api = { version = "2.0.0", default-features = false } sp-core = { version = "2.0.0", default-features = false } +sp-runtime = { version = "2.0.0", default-features = false } sp-std = { version = "2.0.0", default-features = false } [features] @@ -18,5 +19,6 @@ default = ["std"] std = [ "sp-api/std", "sp-core/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index f23e09c511499..0a3fddbc0b74f 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -20,13 +20,21 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +use sp_core::Hasher as HasherT; +use sp_runtime::traits::BlakeTwo256; use sp_std::prelude::*; /// Block number type used in Rialto. pub type BlockNumber = u32; /// Hash type used in Rialto. -pub type Hash = sp_core::H256; +pub type Hash = ::Out; + +/// The type of an object that can produce hashes on Rialto. +pub type Hasher = BlakeTwo256; + +/// The header type used by Rialto. +pub type Header = sp_runtime::generic::Header; sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. @@ -42,8 +50,13 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (BlockNumber, Hash); /// Returns numbers and hashes of headers that require finality proofs. + /// + /// An empty response means that there are no headers which currently require a + /// finality proof. fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; - /// Returns true if header is known to the runtime. + /// Returns true if the header is known to the runtime. fn is_known_block(hash: Hash) -> bool; + /// Returns true if the header is considered finalized by the runtime. + fn is_finalized_block(hash: Hash) -> bool; } } From 824c40b1db6b11be7850c26be199271bd567f03f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 7 Oct 2020 21:39:07 +0300 Subject: [PATCH 0179/1210] Prometheus options in Substrate relay (#402) --- relays/substrate/Cargo.toml | 5 +++- relays/substrate/src/cli.rs | 30 +++++++++++++++++++ relays/substrate/src/main.rs | 3 +- .../substrate/src/millau_headers_to_rialto.rs | 8 +++-- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index bd52598ff596b..ea7f37c02ea55 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -12,7 +12,6 @@ codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.5" log = "0.4.11" paste = "1.0" -sp-runtime = "2.0" structopt = "0.3" # Bridge dependencies @@ -24,3 +23,7 @@ relay-millau-client = { path = "../millau-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } + +# Substrate dependencies + +sp-runtime = "2.0" diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index ca97aa00249ea..3dfda38e8a505 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -27,6 +27,7 @@ pub fn parse_args() -> Command { #[derive(StructOpt)] #[structopt(about = "Substrate-to-Substrate relay")] pub enum Command { + /// Relay Millau headers to Rialto. MillauHeadersToRialto { #[structopt(flatten)] millau: MillauConnectionParams, @@ -34,9 +35,38 @@ pub enum Command { rialto: RialtoConnectionParams, #[structopt(flatten)] rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, }, } +/// Prometheus metrics params. +#[derive(StructOpt)] +pub struct PrometheusParams { + /// Do not expose a Prometheus metric endpoint. + #[structopt(long)] + pub no_prometheus: bool, + /// Expose Prometheus endpoint at given interface. + #[structopt(long, default_value = "127.0.0.1")] + pub prometheus_host: String, + /// Expose Prometheus endpoint at given port. + #[structopt(long, default_value = "9616")] + pub prometheus_port: u16, +} + +impl From for Option { + fn from(cli_params: PrometheusParams) -> Option { + if !cli_params.no_prometheus { + Some(relay_utils::metrics::MetricsParams { + host: cli_params.prometheus_host, + port: cli_params.prometheus_port, + }) + } else { + None + } + } +} + macro_rules! declare_chain_options { ($chain:ident, $chain_prefix:ident) => { paste::item! { diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 09728ef6941c7..743827ab8d871 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -45,6 +45,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { millau, rialto, rialto_sign, + prometheus_params, } => { let millau_client = MillauClient::new(ConnectionParams { host: millau.millau_host, @@ -61,7 +62,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { rialto_sign.rialto_signer_password.as_deref(), ) .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign); + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()); } } diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index d927a9e133f42..f7064c51bf111 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -97,7 +97,12 @@ impl TargetClient for RialtoTargetClient { } /// Run Millau-to-Rialto headers sync. -pub fn run(millau_client: MillauClient, rialto_client: RialtoClient, rialto_sign: RialtoSigningParams) { +pub fn run( + millau_client: MillauClient, + rialto_client: RialtoClient, + rialto_sign: RialtoSigningParams, + metrics_params: Option, +) { let millau_tick = Duration::from_secs(5); let rialto_tick = Duration::from_secs(5); let sync_params = HeadersSyncParams { @@ -108,7 +113,6 @@ pub fn run(millau_client: MillauClient, rialto_client: RialtoClient, rialto_sign prune_depth: 256, target_tx_mode: TargetTransactionMode::Signed, }; - let metrics_params = None; headers_relay::sync_loop::run( MillauSourceClient::new(millau_client), From a2f470d89839440bc668eadd7d6d9931dff169ea Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 7 Oct 2020 22:50:43 +0300 Subject: [PATCH 0180/1210] Move Chain trait to runtime primitives (#403) * extract ChainBase to bp-runtime * post-merge fixes * cargo fmt --all * compilation fixes * reexport BlockNumberOf, HashOf, HeaderOf --- bin/millau/runtime/src/lib.rs | 20 ++--- bin/rialto/runtime/src/lib.rs | 20 ++--- modules/substrate/Cargo.toml | 7 +- modules/substrate/src/lib.rs | 125 ++++++++------------------- modules/substrate/src/mock.rs | 23 +++-- primitives/millau/Cargo.toml | 8 ++ primitives/millau/src/lib.rs | 13 +++ primitives/rialto/Cargo.toml | 16 +++- primitives/rialto/src/lib.rs | 13 +++ primitives/runtime/Cargo.toml | 8 ++ primitives/runtime/src/chain.rs | 85 ++++++++++++++++++ primitives/runtime/src/lib.rs | 4 + relays/millau-client/src/lib.rs | 8 +- relays/rialto-client/src/lib.rs | 8 +- relays/substrate-client/Cargo.toml | 1 + relays/substrate-client/src/chain.rs | 47 +--------- relays/substrate-client/src/lib.rs | 3 +- 17 files changed, 238 insertions(+), 171 deletions(-) create mode 100644 primitives/runtime/src/chain.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 656b0c292b48a..b9d0f638a84fe 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -32,9 +32,7 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as G use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify, -}; +use sp_runtime::traits::{Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, @@ -84,6 +82,9 @@ pub type Index = u32; /// A hash of some data used by the chain. pub type Hash = bp_millau::Hash; +/// Hashing algorithm used by the chain. +pub type Hashing = bp_millau::Hasher; + /// Digest item type. pub type DigestItem = generic::DigestItem; @@ -97,7 +98,7 @@ pub mod opaque { pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; /// Opaque block header type. - pub type Header = generic::Header; + pub type Header = generic::Header; /// Opaque block type. pub type Block = generic::Block; /// Opaque block identifier type. @@ -172,9 +173,9 @@ impl frame_system::Trait for Runtime { /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. - type Hashing = BlakeTwo256; + type Hashing = Hashing; /// The header type. - type Header = generic::Header; + type Header = generic::Header; /// The ubiquitous event type. type Event = Event; /// The ubiquitous origin type. @@ -309,10 +310,7 @@ impl pallet_session::Trait for Runtime { } impl pallet_substrate_bridge::Trait for Runtime { - type BridgedHeader = bp_rialto::Header; - type BridgedBlockNumber = bp_rialto::BlockNumber; - type BridgedBlockHash = bp_rialto::Hash; - type BridgedBlockHasher = bp_rialto::Hasher; + type BridgedChain = bp_rialto::Rialto; } impl pallet_shift_session_manager::Trait for Runtime {} @@ -341,7 +339,7 @@ construct_runtime!( /// The address format for describing accounts. pub type Address = AccountId; /// Block header type as expected by this runtime. -pub type Header = generic::Header; +pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; /// A Block signed with a Justification diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5ee7ff92460f0..6259e99a02855 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -39,9 +39,7 @@ use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as G use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{ - BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify, -}; +use sp_runtime::traits::{Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, @@ -92,6 +90,9 @@ pub type Index = u32; /// A hash of some data used by the chain. pub type Hash = bp_rialto::Hash; +/// Hashing algorithm used by the chain. +pub type Hashing = bp_rialto::Hasher; + /// Digest item type. pub type DigestItem = generic::DigestItem; @@ -105,7 +106,7 @@ pub mod opaque { pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; /// Opaque block header type. - pub type Header = generic::Header; + pub type Header = generic::Header; /// Opaque block type. pub type Block = generic::Block; /// Opaque block identifier type. @@ -180,9 +181,9 @@ impl frame_system::Trait for Runtime { /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. - type Hashing = BlakeTwo256; + type Hashing = Hashing; /// The header type. - type Header = generic::Header; + type Header = generic::Header; /// The ubiquitous event type. type Event = Event; /// The ubiquitous origin type. @@ -415,10 +416,7 @@ impl pallet_session::Trait for Runtime { } impl pallet_substrate_bridge::Trait for Runtime { - type BridgedHeader = bp_millau::Header; - type BridgedBlockNumber = bp_millau::BlockNumber; - type BridgedBlockHash = bp_millau::Hash; - type BridgedBlockHasher = bp_millau::Hasher; + type BridgedChain = bp_millau::Millau; } impl pallet_shift_session_manager::Trait for Runtime {} @@ -451,7 +449,7 @@ construct_runtime!( /// The address format for describing accounts. pub type Address = AccountId; /// Block header type as expected by this runtime. -pub type Header = generic::Header; +pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; /// A Block signed with a Justification diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 3b474e643fc75..82740fc1b4fc2 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -11,9 +11,12 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } hash-db = { version = "0.15.2", default-features = false } -num-traits = { version = "0.2", default-features = false } serde = { version = "1.0", optional = true } +# Bridge Dependencies + +bp-runtime = { path = "../../primitives/runtime", default-features = false } + # Substrate Dependencies frame-support = { version = "2.0", default-features = false } @@ -32,12 +35,12 @@ sp-state-machine = "0.8" [features] default = ["std"] std = [ + "bp-runtime/std", "codec/std", "finality-grandpa/std", "frame-support/std", "frame-system/std", "hash-db/std", - "num-traits/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 4b55bd41d75ab..25276ace09133 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -32,18 +32,11 @@ #![allow(clippy::large_enum_variant)] use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; -use codec::{Codec, EncodeLike}; -use frame_support::{ - decl_error, decl_module, decl_storage, - dispatch::{DispatchResult, Parameter}, -}; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderOf}; +use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult}; use frame_system::ensure_signed; -use num_traits::AsPrimitive; -use sp_runtime::traits::{ - AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, MaybeMallocSizeOf, MaybeSerializeDeserialize, - Member, SimpleBitOps, -}; -use sp_std::{fmt::Debug, marker::PhantomData, prelude::*, str::FromStr}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::{marker::PhantomData, prelude::*}; mod justification; mod storage; @@ -54,84 +47,42 @@ mod verifier; mod mock; pub trait Trait: frame_system::Trait { - /// 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 BridgedHeader: Parameter + HeaderT; - - /// 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` trait is required by the Grandpa justification - // verifier, and is not usually part of a Substrate Header's Number type. - type BridgedBlockNumber: Parameter - + Member - + MaybeSerializeDeserialize - + Debug - + sp_std::hash::Hash - + Copy - + MaybeDisplay - + AtLeast32BitUnsigned - + Codec - + FromStr - + MaybeMallocSizeOf - + AsPrimitive; - - /// 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 BridgedBlockHash: Parameter - + Member - + MaybeSerializeDeserialize - + Debug - + sp_std::hash::Hash - + Ord - + Copy - + MaybeDisplay - + Default - + SimpleBitOps - + Codec - + AsRef<[u8]> - + AsMut<[u8]> - + MaybeMallocSizeOf - + EncodeLike; - - /// 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 BridgedBlockHasher: HashT; + /// Chain that we are bridging here. + type BridgedChain: Chain; } +/// Block number of the bridged chain. +pub(crate) type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; +/// Block hash of the bridged chain. +pub(crate) type BridgedBlockHash = HashOf<::BridgedChain>; +/// Header of the bridged chain. +pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; + decl_storage! { trait Store for Module as SubstrateBridge { /// Hash of the header at the highest known height. - BestHeader: T::BridgedBlockHash; + BestHeader: BridgedBlockHash; /// Hash of the best finalized header. - BestFinalized: T::BridgedBlockHash; + BestFinalized: BridgedBlockHash; /// A header which enacts an authority set change and therefore /// requires a Grandpa justification. // Since we won't always have an authority set change scheduled we // won't always have a header which needs a justification. - RequiresJustification: Option; + RequiresJustification: Option>; /// Headers which have been imported into the pallet. - ImportedHeaders: map hasher(identity) T::BridgedBlockHash => Option>; + ImportedHeaders: map hasher(identity) BridgedBlockHash => Option>>; /// The current Grandpa Authority set. CurrentAuthoritySet: AuthoritySet; /// The next scheduled authority set change. // Grandpa doesn't require there to always be a pending change. In fact, most of the time // there will be no pending change available. - NextScheduledChange: Option>; + NextScheduledChange: Option>>; } add_extra_genesis { - config(initial_header): Option; + config(initial_header): Option>; config(initial_authority_list): sp_finality_grandpa::AuthorityList; config(initial_set_id): sp_finality_grandpa::SetId; - config(first_scheduled_change): Option>; + config(first_scheduled_change): Option>>; build(|config| { assert!( !config.initial_authority_list.is_empty(), @@ -187,7 +138,7 @@ decl_module! { #[weight = 0] pub fn import_signed_header( origin, - header: T::BridgedHeader, + header: BridgedHeader, ) -> DispatchResult { let _ = ensure_signed(origin)?; frame_support::debug::trace!(target: "sub-bridge", "Got header {:?}", header); @@ -212,7 +163,7 @@ decl_module! { #[weight = 0] pub fn finalize_header( origin, - hash: T::BridgedBlockHash, + hash: BridgedBlockHash, finality_proof: Vec, ) -> DispatchResult { let _ = ensure_signed(origin)?; @@ -235,7 +186,7 @@ impl Module { /// Get the highest header that the pallet knows of. // In a future where we support forks this could be a Vec of headers // since we may have multiple headers at the same height. - pub fn best_header() -> T::BridgedHeader { + pub fn best_header() -> BridgedHeader { PalletStorage::::new().best_header().header } @@ -244,12 +195,12 @@ impl Module { /// Since this has been finalized correctly a user of the bridge /// pallet should be confident that any transactions that were /// included in this or any previous header will not be reverted. - pub fn best_finalized() -> T::BridgedHeader { + pub fn best_finalized() -> BridgedHeader { PalletStorage::::new().best_finalized_header().header } /// Check if a particular header is known to the bridge pallet. - pub fn is_known_header(hash: T::BridgedBlockHash) -> bool { + pub fn is_known_header(hash: BridgedBlockHash) -> bool { PalletStorage::::new().header_exists(hash) } @@ -259,7 +210,7 @@ impl Module { // One thing worth noting here is that this approach won't work well // once we track forks since there could be an older header on a // different fork which isn't an ancestor of our best finalized header. - pub fn is_finalized_header(hash: T::BridgedBlockHash) -> bool { + pub fn is_finalized_header(hash: BridgedBlockHash) -> bool { let storage = PalletStorage::::new(); if let Some(header) = storage.header_by_hash(hash) { header.number() <= storage.best_finalized_header().number() @@ -272,7 +223,7 @@ impl Module { /// and still needs a finality proof. /// /// Will return None if there are no headers which are missing finality proofs. - pub fn requires_justification() -> Option { + pub fn requires_justification() -> Option> { let storage = PalletStorage::::new(); let hash = storage.unfinalized_header()?; let imported_header = storage.header_by_hash(hash).expect( @@ -352,42 +303,42 @@ impl PalletStorage { } impl BridgeStorage for PalletStorage { - type Header = T::BridgedHeader; + type Header = BridgedHeader; - fn write_header(&mut self, header: &ImportedHeader) { + fn write_header(&mut self, header: &ImportedHeader>) { let hash = header.header.hash(); >::insert(hash, header); } - fn best_header(&self) -> ImportedHeader { + fn best_header(&self) -> ImportedHeader> { let hash = >::get(); self.header_by_hash(hash) .expect("A header must have been written at genesis, therefore this must always exist") } - fn update_best_header(&mut self, hash: T::BridgedBlockHash) { + fn update_best_header(&mut self, hash: BridgedBlockHash) { >::put(hash) } - fn best_finalized_header(&self) -> ImportedHeader { + fn best_finalized_header(&self) -> ImportedHeader> { let hash = >::get(); self.header_by_hash(hash) .expect("A finalized header was added at genesis, therefore this must always exist") } - fn update_best_finalized(&self, hash: T::BridgedBlockHash) { + fn update_best_finalized(&self, hash: BridgedBlockHash) { >::put(hash) } - fn header_exists(&self, hash: T::BridgedBlockHash) -> bool { + fn header_exists(&self, hash: BridgedBlockHash) -> bool { >::contains_key(hash) } - fn header_by_hash(&self, hash: T::BridgedBlockHash) -> Option> { + fn header_by_hash(&self, hash: BridgedBlockHash) -> Option>> { >::get(hash) } - fn unfinalized_header(&self) -> Option { + fn unfinalized_header(&self) -> Option> { >::get() } @@ -420,11 +371,11 @@ impl BridgeStorage for PalletStorage { } } - fn scheduled_set_change(&self) -> Option> { + fn scheduled_set_change(&self) -> Option>> { >::get() } - fn schedule_next_set_change(&self, next_change: ScheduledChange) { + fn schedule_next_set_change(&self, next_change: ScheduledChange>) { >::put(next_change) } } diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index b6cc8bd31c1c8..f16ea476bb913 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -21,6 +21,7 @@ #![cfg(test)] use crate::Trait; +use bp_runtime::Chain; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, @@ -73,10 +74,17 @@ impl frame_system::Trait for TestRuntime { } impl Trait for TestRuntime { - type BridgedHeader = ::Header; - type BridgedBlockNumber = ::BlockNumber; - type BridgedBlockHash = ::Hash; - type BridgedBlockHasher = ::Hashing; + type BridgedChain = TestBridgedChain; +} + +#[derive(Debug)] +pub struct TestBridgedChain; + +impl Chain for TestBridgedChain { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hashing; + type Header = ::Header; } pub fn run_test(test: impl FnOnce() -> T) -> T { @@ -85,13 +93,14 @@ pub fn run_test(test: impl FnOnce() -> T) -> T { pub mod helpers { use super::*; + use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader}; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{AuthorityId, AuthorityList}; use sp_keyring::Ed25519Keyring; - pub type TestHeader = ::BridgedHeader; - pub type TestNumber = ::BridgedBlockNumber; - pub type TestHash = ::BridgedBlockHash; + pub type TestHeader = BridgedHeader; + pub type TestNumber = BridgedBlockNumber; + pub type TestHash = BridgedBlockHash; pub type HeaderId = (TestHash, TestNumber); pub fn test_header(num: TestNumber) -> TestHeader { diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index 2125fa8205b3b..47b7474184c10 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -8,7 +8,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +# Bridge Dependencies + +bp-runtime = { path = "../runtime", default-features = false } + # Substrate Based Dependencies + +frame-support = { version = "2.0", default-features = false } sp-api = { version = "2.0", default-features = false } sp-core = { version = "2.0", default-features = false } sp-runtime = { version = "2.0", default-features = false } @@ -17,6 +23,8 @@ sp-std = { version = "2.0", default-features = false } [features] default = ["std"] std = [ + "bp-runtime/std", + "frame-support/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index dc233caab4ce1..99bb0207f50db 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -20,6 +20,8 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +use bp_runtime::Chain; +use frame_support::RuntimeDebug; use sp_core::Hasher as HasherT; use sp_runtime::traits::BlakeTwo256; use sp_std::prelude::*; @@ -36,6 +38,17 @@ pub type Hasher = BlakeTwo256; /// The header type used by Millau. pub type Header = sp_runtime::generic::Header; +/// Millau chain. +#[derive(RuntimeDebug)] +pub struct Millau; + +impl Chain for Millau { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; +} + sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index 80616f3863d3d..b03806905167d 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -8,15 +8,23 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +# Bridge Dependencies + +bp-runtime = { path = "../runtime", default-features = false } + # Substrate Based Dependencies -sp-api = { version = "2.0.0", default-features = false } -sp-core = { version = "2.0.0", default-features = false } -sp-runtime = { version = "2.0.0", default-features = false } -sp-std = { version = "2.0.0", default-features = false } + +frame-support = { version = "2.0", default-features = false } +sp-api = { version = "2.0", default-features = false } +sp-core = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } [features] default = ["std"] std = [ + "bp-runtime/std", + "frame-support/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 0a3fddbc0b74f..ea20d72ab022e 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -20,6 +20,8 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +use bp_runtime::Chain; +use frame_support::RuntimeDebug; use sp_core::Hasher as HasherT; use sp_runtime::traits::BlakeTwo256; use sp_std::prelude::*; @@ -36,6 +38,17 @@ pub type Hasher = BlakeTwo256; /// The header type used by Rialto. pub type Header = sp_runtime::generic::Header; +/// Rialto chain. +#[derive(RuntimeDebug)] +pub struct Rialto; + +impl Chain for Rialto { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; +} + sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index b182f4e4e406a..b42fa4bf3ecdd 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -8,14 +8,22 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +num-traits = { version = "0.2", default-features = false } # Substrate Dependencies +frame-support = { version = "2.0", default-features = false } sp-io = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } [features] default = ["std"] std = [ "codec/std", + "frame-support/std", + "num-traits/std", "sp-io/std", + "sp-runtime/std", + "sp-std/std", ] diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs new file mode 100644 index 0000000000000..096db8397b81f --- /dev/null +++ b/primitives/runtime/src/chain.rs @@ -0,0 +1,85 @@ +// Copyright 2019-2020 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 . + +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 { + /// 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` 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 + + MaybeDisplay + + AtLeast32BitUnsigned + + FromStr + + MaybeMallocSizeOf + + AsPrimitive; + + /// 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; + + /// 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; +} + +/// Block number used by the chain. +pub type BlockNumberOf = ::BlockNumber; + +/// Hash type used by the chain. +pub type HashOf = ::Hash; + +/// Hasher type used by the chain. +pub type HasherOf = ::Header; + +/// Header type used by the chain. +pub type HeaderOf = ::Header; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 45097ea1b6756..6a826da3af74f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -21,6 +21,10 @@ use codec::{Decode, Encode}; use sp_io::hashing::blake2_256; +pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; + +mod chain; + /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index a901be18eedb4..291954cbea9e8 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the Millau-Substrate chain. -use relay_substrate_client::Chain; +use relay_substrate_client::{Chain, ChainBase}; use headers_relay::sync_types::SourceHeader; use sp_runtime::traits::Header as HeaderT; @@ -28,10 +28,14 @@ pub type HeaderId = relay_utils::HeaderId - + AsMut<[u8]> - + MaybeMallocSizeOf; - /// The block header. - type Header: Parameter + HeaderT; +pub trait Chain: ChainBase { /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; /// Account index (aka nonce) type. This stores the number of previous transactions associated @@ -96,15 +64,6 @@ pub trait TransactionSignScheme { ) -> Self::SignedTransaction; } -/// Header type used by the chain. -pub type HeaderOf = ::Header; - -/// Hash type used by the chain. -pub type HashOf = ::Hash; - -/// Block number used by the chain. -pub type BlockNumberOf = ::BlockNumber; - impl BlockWithJustification for SignedBlock { fn justification(&self) -> Option<&Justification> { self.justification.as_ref() diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index 7e44653db8add..6c978f4652222 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -25,9 +25,10 @@ mod rpc; pub mod headers_source; -pub use crate::chain::{BlockNumberOf, BlockWithJustification, Chain, HashOf, HeaderOf, TransactionSignScheme}; +pub use crate::chain::{BlockWithJustification, Chain, TransactionSignScheme}; pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; +pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; /// Substrate connection params. #[derive(Debug, Clone)] From fd6f1a6adf67f90aa0dbbb19b527dd1c49d824be Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 9 Oct 2020 02:09:06 -0400 Subject: [PATCH 0181/1210] Add GenesisConfig for Millau and Rialto Runtimes (#401) * Add Rialto as a target for the Millau node * Rename Rialto module to Rialto-PoA This will reduce confusion as the Millau runtime has a Rialto module as well which refers to the Substrate chain. * Add Millau as a target for the Rialto node * Be more explicit about Rialto PoA related code * Missed some name changes in the Ethereum PoA relay * Re-export Substrate pallet structs used by node * Remove `first_scheduled_change` of Millau in Rialto node * Make Millau's genesis config for Rialto bridge more accurate * Set initial header for Millau config * Update initial Millau authorities Co-authored-by: Svyatoslav Nikolsky * RustFmt Millau authorities Co-authored-by: Svyatoslav Nikolsky --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/chain_spec.rs | 14 ++- bin/millau/runtime/Cargo.toml | 3 + bin/millau/runtime/src/lib.rs | 4 +- bin/millau/runtime/src/rialto.rs | 56 ++++++++++++ bin/rialto/node/src/chain_spec.rs | 24 +++-- bin/rialto/runtime/Cargo.toml | 2 + bin/rialto/runtime/src/lib.rs | 29 ++++--- bin/rialto/runtime/src/millau.rs | 87 +++++++++++++++++++ .../runtime/src/{rialto.rs => rialto_poa.rs} | 14 +-- modules/substrate/src/lib.rs | 5 +- primitives/rialto/Cargo.toml | 1 - relays/ethereum/src/instances.rs | 4 +- 13 files changed, 210 insertions(+), 35 deletions(-) create mode 100644 bin/millau/runtime/src/rialto.rs create mode 100644 bin/rialto/runtime/src/millau.rs rename bin/rialto/runtime/src/{rialto.rs => rialto_poa.rs} (92%) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index a6dc223e84cab..5051d0dba7ce9 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -14,7 +14,7 @@ jsonrpc-core = "15.0.0" structopt = "0.3.17" # Bridge dependencies - +bp-rialto = { path = "../../../primitives/rialto" } millau-runtime = { path = "../runtime" } # Substrate Dependencies diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index df66c3318e5b8..a3e95398fda96 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -15,8 +15,8 @@ // along with Parity Bridges Common. If not, see . use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, - SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, SessionConfig, + SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -155,6 +155,7 @@ fn testnet_genesis( pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), + pallet_substrate_bridge: load_rialto_bridge_config(), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { keys: initial_authorities @@ -164,3 +165,12 @@ fn testnet_genesis( }), } } + +fn load_rialto_bridge_config() -> Option { + Some(BridgeRialtoConfig { + initial_header: Some(millau_runtime::rialto::initial_header()), + initial_authority_list: millau_runtime::rialto::initial_authority_set().authorities, + initial_set_id: millau_runtime::rialto::initial_authority_set().set_id, + first_scheduled_change: None, + }) +} diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index e961ccf8c8d74..eb37ea473f36d 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +hex-literal = "0.3" serde = { version = "1.0.115", optional = true, features = ["derive"] } # Bridge dependencies @@ -40,6 +41,7 @@ sp-block-builder = { version = "2.0", default-features = false } sp-consensus-aura = { version = "0.8", default-features = false } sp-core = { version = "2.0", default-features = false } sp-inherents = { version = "2.0", default-features = false } +sp-finality-grandpa = { version = "2.0", default-features = false } sp-offchain = { version = "2.0", default-features = false } sp-runtime = { version = "2.0", default-features = false } sp-session = { version = "2.0", default-features = false } @@ -79,6 +81,7 @@ std = [ "sp-consensus-aura/std", "sp-core/std", "sp-inherents/std", + "sp-finality-grandpa/std", "sp-offchain/std", "sp-runtime/std", "sp-session/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b9d0f638a84fe..340639e367333 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -28,6 +28,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod rialto; + use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -321,7 +323,7 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage}, + BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, diff --git a/bin/millau/runtime/src/rialto.rs b/bin/millau/runtime/src/rialto.rs new file mode 100644 index 0000000000000..0c25d93e93ddb --- /dev/null +++ b/bin/millau/runtime/src/rialto.rs @@ -0,0 +1,56 @@ +// Copyright 2020 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 . + +//! Configuration parameters for the Rialto Substrate chain. + +use bp_rialto::Header; +use pallet_substrate_bridge::AuthoritySet; +use sp_core::crypto::Public; +use sp_finality_grandpa::AuthorityId; +use sp_std::vec; + +/// The first header known to the pallet. +/// +/// Note that this does not need to be the genesis header of the Rialto +/// chain since the pallet may start at any arbitrary header. +// To get this we first need to call the `chain_getBlockHash` RPC method, and then +// we can use the result from that and call the `chain_getBlock` RPC method to get +// the rest of the info. +// +// In this case we've grabbed the genesis block of the Rialto Substrate chain. +pub fn initial_header() -> Header { + Header { + parent_hash: Default::default(), + number: Default::default(), + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), + } +} + +/// The first set of Grandpa authorities known to the pallet. +/// +/// Note that this doesn't have to be the "genesis" authority set, as the +/// pallet can be configured to start from any height. +pub fn initial_authority_set() -> AuthoritySet { + let set_id = 0; + let authorities = vec![ + (AuthorityId::from_slice(&[1; 32]), 1), + (AuthorityId::from_slice(&[2; 32]), 1), + (AuthorityId::from_slice(&[3; 32]), 1), + ]; + AuthoritySet::new(authorities, set_id) +} diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 62f28fb49a885..4b66d656f8394 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -15,8 +15,8 @@ // along with Parity Bridges Common. If not, see . use rialto_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, - SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauConfig, BridgeRialtoPoAConfig, GenesisConfig, + GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -152,11 +152,12 @@ fn testnet_genesis( pallet_aura: Some(AuraConfig { authorities: Vec::new(), }), - pallet_bridge_eth_poa_Instance1: load_rialto_bridge_config(), + pallet_bridge_eth_poa_Instance1: load_rialto_poa_bridge_config(), pallet_bridge_eth_poa_Instance2: load_kovan_bridge_config(), pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), + pallet_substrate_bridge: load_millau_bridge_config(), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { keys: initial_authorities @@ -167,11 +168,11 @@ fn testnet_genesis( } } -fn load_rialto_bridge_config() -> Option { - Some(BridgeRialtoConfig { - initial_header: rialto_runtime::rialto::genesis_header(), +fn load_rialto_poa_bridge_config() -> Option { + Some(BridgeRialtoPoAConfig { + initial_header: rialto_runtime::rialto_poa::genesis_header(), initial_difficulty: 0.into(), - initial_validators: rialto_runtime::rialto::genesis_validators(), + initial_validators: rialto_runtime::rialto_poa::genesis_validators(), }) } @@ -182,3 +183,12 @@ fn load_kovan_bridge_config() -> Option { initial_validators: rialto_runtime::kovan::genesis_validators(), }) } + +fn load_millau_bridge_config() -> Option { + Some(BridgeMillauConfig { + initial_header: Some(rialto_runtime::millau::initial_header()), + initial_authority_list: rialto_runtime::millau::initial_authority_set().authorities, + initial_set_id: rialto_runtime::millau::initial_authority_set().set_id, + first_scheduled_change: None, + }) +} diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 60de3e70b448b..fc7058f010cf3 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -47,6 +47,7 @@ sp-api = { version = "2.0", default-features = false } sp-block-builder = { version = "2.0", default-features = false } sp-consensus-aura = { version = "0.8", default-features = false } sp-core = { version = "2.0", default-features = false } +sp-finality-grandpa = { version = "2.0", default-features = false } sp-inherents = { version = "2.0", default-features = false } sp-io = { version = "2.0", default-features = false } sp-offchain = { version = "2.0", default-features = false } @@ -95,6 +96,7 @@ std = [ "sp-block-builder/std", "sp-consensus-aura/std", "sp-core/std", + "sp-finality-grandpa/std", "sp-inherents/std", "sp-io/std", "sp-offchain/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6259e99a02855..a693e8897397a 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -33,7 +33,8 @@ pub mod exchange; #[cfg(feature = "runtime-benchmarks")] pub mod benches; pub mod kovan; -pub mod rialto; +pub mod millau; +pub mod rialto_poa; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; @@ -227,12 +228,12 @@ impl pallet_aura::Trait for Runtime { type AuthorityId = AuraId; } -type Rialto = pallet_bridge_eth_poa::Instance1; -impl pallet_bridge_eth_poa::Trait for Runtime { - type AuraConfiguration = rialto::BridgeAuraConfiguration; - type FinalityVotesCachingInterval = rialto::FinalityVotesCachingInterval; - type ValidatorsConfiguration = rialto::BridgeValidatorsConfiguration; - type PruningStrategy = rialto::PruningStrategy; +type RialtoPoA = pallet_bridge_eth_poa::Instance1; +impl pallet_bridge_eth_poa::Trait for Runtime { + type AuraConfiguration = rialto_poa::BridgeAuraConfiguration; + type FinalityVotesCachingInterval = rialto_poa::FinalityVotesCachingInterval; + type ValidatorsConfiguration = rialto_poa::BridgeValidatorsConfiguration; + type PruningStrategy = rialto_poa::PruningStrategy; type OnHeadersSubmitted = (); } @@ -248,7 +249,7 @@ impl pallet_bridge_eth_poa::Trait for Runtime { type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1; impl pallet_bridge_currency_exchange::Trait for Runtime { type OnTransactionSubmitted = (); - type PeerBlockchain = rialto::RialtoBlockchain; + type PeerBlockchain = rialto_poa::RialtoBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; type RecipientsMap = bp_currency_exchange::IdentityRecipients; type Amount = Balance; @@ -427,11 +428,11 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialto: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, + BridgeRialtoPoA: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, - BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage}, + BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, @@ -530,21 +531,21 @@ impl_runtime_apis! { impl bp_eth_poa::RialtoPoAHeaderApi for Runtime { fn best_block() -> (u64, bp_eth_poa::H256) { - let best_block = BridgeRialto::best_block(); + let best_block = BridgeRialtoPoA::best_block(); (best_block.number, best_block.hash) } fn finalized_block() -> (u64, bp_eth_poa::H256) { - let finalized_block = BridgeRialto::finalized_block(); + let finalized_block = BridgeRialtoPoA::finalized_block(); (finalized_block.number, finalized_block.hash) } fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool { - BridgeRialto::is_import_requires_receipts(header) + BridgeRialtoPoA::is_import_requires_receipts(header) } fn is_known_block(hash: bp_eth_poa::H256) -> bool { - BridgeRialto::is_known_block(hash) + BridgeRialtoPoA::is_known_block(hash) } } diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs new file mode 100644 index 0000000000000..47568f41742af --- /dev/null +++ b/bin/rialto/runtime/src/millau.rs @@ -0,0 +1,87 @@ +// Copyright 2020 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 . + +//! Configuration parameters for the Millau Substrate chain. + +use bp_rialto::Header; +use hex_literal::hex; +use pallet_substrate_bridge::AuthoritySet; +use sp_core::crypto::Public; +use sp_finality_grandpa::AuthorityId; +use sp_std::vec; + +/// The first header known to the pallet. +/// +/// Note that this does not need to be the genesis header of the Millau +/// chain since the pallet may start at any arbitrary header. +// To get this we first need to call the `chain_getBlockHash` RPC method, and then +// we can use the result from that and call the `chain_getBlock` RPC method to get +// the rest of the info. +// +// In this case we've grabbed the genesis block of the Millau Substrate chain. +pub fn initial_header() -> Header { + Header { + parent_hash: Default::default(), + number: Default::default(), + state_root: hex!("bb65e8ba99408ebfefea9d28f74403d41da6858fa075c51fcc71dc383455c530").into(), + extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), + digest: Default::default(), + } +} + +/// The first set of Grandpa authorities known to the pallet. +/// +/// Note that this doesn't have to be the "genesis" authority set, as the +/// pallet can be configured to start from any height. +pub fn initial_authority_set() -> AuthoritySet { + let set_id = 0; + + // These authorities are: Alice, Bob, Charlie, Dave, and Eve. + let authorities = vec![ + ( + AuthorityId::from_slice(&hex!( + "88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee" + )), + 1, + ), + ( + AuthorityId::from_slice(&hex!( + "d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae69" + )), + 1, + ), + ( + AuthorityId::from_slice(&hex!( + "439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f" + )), + 1, + ), + ( + AuthorityId::from_slice(&hex!( + "5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9" + )), + 1, + ), + ( + AuthorityId::from_slice(&hex!( + "1dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b5" + )), + 1, + ), + ]; + + AuthoritySet::new(authorities, set_id) +} diff --git a/bin/rialto/runtime/src/rialto.rs b/bin/rialto/runtime/src/rialto_poa.rs similarity index 92% rename from bin/rialto/runtime/src/rialto.rs rename to bin/rialto/runtime/src/rialto_poa.rs index 4e92e800eccdc..4839579b04e05 100644 --- a/bin/rialto/runtime/src/rialto.rs +++ b/bin/rialto/runtime/src/rialto_poa.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Configuration parameters for the Rialto PoA chain. + use crate::exchange::EthereumTransactionInclusionProof; use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; @@ -50,12 +52,12 @@ pub fn aura_configuration() -> AuraConfiguration { } } -/// Validators configuration for Rialto chain. +/// Validators configuration for Rialto PoA chain. pub fn validators_configuration() -> ValidatorsConfiguration { ValidatorsConfiguration::Single(ValidatorsSource::List(genesis_validators())) } -/// Genesis validators set of Rialto chain. +/// Genesis validators set of Rialto PoA chain. pub fn genesis_validators() -> Vec

{ vec![ hex!("005e714f896a8b7cede9d38688c1a81de72a58e4").into(), @@ -64,7 +66,7 @@ pub fn genesis_validators() -> Vec
{ ] } -/// Genesis header of the Rialto chain. +/// Genesis header of the Rialto PoA chain. /// /// To obtain genesis header from a running node, invoke: /// ```bash @@ -93,7 +95,7 @@ pub fn genesis_header() -> AuraHeader { } } -/// Rialto headers pruning strategy. +/// Rialto PoA headers pruning strategy. /// /// We do not prune unfinalized headers because exchange module only accepts /// claims from finalized headers. And if we're pruning unfinalized headers, then @@ -107,7 +109,7 @@ impl TPruningStrategy for PruningStrategy { } } -/// The Rialto Blockchain as seen by the runtime. +/// The Rialto PoA Blockchain as seen by the runtime. pub struct RialtoBlockchain; impl BaseHeaderChain for RialtoBlockchain { @@ -116,7 +118,7 @@ impl BaseHeaderChain for RialtoBlockchain { fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { let is_transaction_finalized = - crate::BridgeRialto::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + crate::BridgeRialtoPoA::verify_transaction_finalized(proof.block, proof.index, &proof.proof); if !is_transaction_finalized { return None; diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 25276ace09133..c4406b6a3ccb1 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -31,13 +31,16 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] -use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; +use crate::storage::ImportedHeader; use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderOf}; use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult}; use frame_system::ensure_signed; use sp_runtime::traits::Header as HeaderT; use sp_std::{marker::PhantomData, prelude::*}; +// Re-export since the node uses these when configuring genesis +pub use storage::{AuthoritySet, ScheduledChange}; + mod justification; mod storage; mod storage_proof; diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index b03806905167d..9c9cb4bc8160b 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -13,7 +13,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies - frame-support = { version = "2.0", default-features = false } sp-api = { version = "2.0", default-features = false } sp-core = { version = "2.0", default-features = false } diff --git a/relays/ethereum/src/instances.rs b/relays/ethereum/src/instances.rs index bfdccd0ba34df..7f29c26d8c362 100644 --- a/relays/ethereum/src/instances.rs +++ b/relays/ethereum/src/instances.rs @@ -60,7 +60,7 @@ impl BridgeInstance for RialtoPoA { .collect(), ); - rialto_runtime::Call::BridgeRialto(pallet_call) + rialto_runtime::Call::BridgeRialtoPoA(pallet_call) } fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { @@ -69,7 +69,7 @@ impl BridgeInstance for RialtoPoA { into_substrate_ethereum_receipts(header.extra()), ); - rialto_runtime::Call::BridgeRialto(pallet_call) + rialto_runtime::Call::BridgeRialtoPoA(pallet_call) } fn build_currency_exchange_call(&self, proof: Proof) -> Call { From c4f9ad8128523fade248d3dc87f1dd63c417dd6c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Oct 2020 22:23:47 +0300 Subject: [PATCH 0182/1210] Expose GRANDPA RPC API from Millau node (#408) * expose GRANDPA RPC API from Millau node * fmt --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/service.rs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 5051d0dba7ce9..551c19b32c221 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -28,6 +28,7 @@ sc-consensus = "0.8" sc-consensus-aura = "0.8" sc-executor = "0.8" sc-finality-grandpa = "0.8" +sc-finality-grandpa-rpc = "0.8" sc-service = "0.8" sc-rpc = "2.0" sc-transaction-pool = "2.0" diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index e2e83d5a721ea..fe1686fdda965 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -33,6 +33,7 @@ use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; +use sc_finality_grandpa_rpc::GrandpaRpcHandler; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; @@ -160,19 +161,33 @@ pub fn new_full(config: Configuration) -> Result { let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { + use sc_finality_grandpa_rpc::GrandpaApi; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; let client = client.clone(); let pool = transaction_pool.clone(); - Box::new(move |_, _| { + let justification_stream = grandpa_link.justification_stream(); + let shared_authority_set = grandpa_link.shared_authority_set().clone(); + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + + Box::new(move |_, subscription_executor| { + let shared_voter_state = SharedVoterState::empty(); + let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( client.clone(), pool.clone(), DenyUnsafe::No, ))); + io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( + shared_authority_set.clone(), + shared_voter_state, + justification_stream.clone(), + subscription_executor, + finality_proof_provider.clone(), + ))); io }) From d5211061be9b4219534fef6563523f6fd24356b8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 11:13:24 +0000 Subject: [PATCH 0183/1210] Bump futures from 0.3.5 to 0.3.6 (#413) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index bc60e41b818fa..b1a45acbae0c3 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ env_logger = "0.7.0" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" -futures = "0.3.5" +futures = "0.3.6" hex = "0.4" hex-literal = "0.3" log = "0.4.11" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index ea7f37c02ea55..c10923dff9ff2 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.2" async-trait = "0.1.41" codec = { package = "parity-scale-codec", version = "1.3.4" } -futures = "0.3.5" +futures = "0.3.6" log = "0.4.11" paste = "1.0" structopt = "0.3" From 6be363af85ef435491c209fb1c404fa48a6c682c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 13:02:19 +0000 Subject: [PATCH 0184/1210] Bump structopt from 0.3.18 to 0.3.19 (#411) --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 551c19b32c221..be78518d494f0 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.0.0" -structopt = "0.3.17" +structopt = "0.3.19" # Bridge dependencies bp-rialto = { path = "../../../primitives/rialto" } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index db4f2a093f543..66e3afaa2ba68 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.0.0" -structopt = "0.3.17" +structopt = "0.3.19" # Bridge dependencies From 9c4e3f513f6482ffe9f4177645a486f94fea9b9f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 20:57:07 +0000 Subject: [PATCH 0185/1210] Bump jsonrpc-core from 15.0.0 to 15.1.0 (#412) --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index be78518d494f0..527507c16a1d5 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -jsonrpc-core = "15.0.0" +jsonrpc-core = "15.1.0" structopt = "0.3.19" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 66e3afaa2ba68..bb1a86480aa1a 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -jsonrpc-core = "15.0.0" +jsonrpc-core = "15.1.0" structopt = "0.3.19" # Bridge dependencies From abe3cb951e5a63bff90d4302f1702ecdad8fc553 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Tue, 13 Oct 2020 12:23:58 +0200 Subject: [PATCH 0186/1210] Add ChainTime associated type (#410) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add HeaderTimestamp associated type * use Header Timestamp * rename HeaderTimestamp to ChainTime * add unit test * deal with clippy * Apply suggestions from code review Commit review suggestions Co-authored-by: Tomasz Drwięga * code review * cargo fmt * get rid of additional test runtime * unit test asserts against concrete import context Co-authored-by: Tomasz Drwięga --- bin/rialto/runtime/src/kovan.rs | 14 +++++- bin/rialto/runtime/src/lib.rs | 2 + bin/rialto/runtime/src/rialto_poa.rs | 14 +++++- modules/ethereum/Cargo.toml | 1 + modules/ethereum/src/error.rs | 3 ++ modules/ethereum/src/import.rs | 24 +++++++-- modules/ethereum/src/lib.rs | 24 +++++++++ modules/ethereum/src/mock.rs | 14 +++++- modules/ethereum/src/verification.rs | 74 ++++++++++++++++++++++++---- 9 files changed, 154 insertions(+), 16 deletions(-) diff --git a/bin/rialto/runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs index d0b59478d22ea..bc2252bbb9594 100644 --- a/bin/rialto/runtime/src/kovan.rs +++ b/bin/rialto/runtime/src/kovan.rs @@ -21,7 +21,8 @@ use bp_header_chain::BaseHeaderChain; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_eth_poa::{ - AuraConfiguration, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, ValidatorsSource, + AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, + ValidatorsSource, }; use sp_std::prelude::*; @@ -134,6 +135,17 @@ impl BridgePruningStrategy for PruningStrategy { } } +/// PoA Header timestamp verification against `Timestamp` pallet. +#[derive(Default, RuntimeDebug)] +pub struct ChainTime; + +impl TChainTime for ChainTime { + fn is_timestamp_ahead(&self, timestamp: u64) -> bool { + let now = super::Timestamp::now(); + timestamp > now + } +} + /// The Kovan Blockchain as seen by the runtime. pub struct KovanBlockchain; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a693e8897397a..77a23cbf8f4ad 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -234,6 +234,7 @@ impl pallet_bridge_eth_poa::Trait for Runtime { type FinalityVotesCachingInterval = rialto_poa::FinalityVotesCachingInterval; type ValidatorsConfiguration = rialto_poa::BridgeValidatorsConfiguration; type PruningStrategy = rialto_poa::PruningStrategy; + type ChainTime = rialto_poa::ChainTime; type OnHeadersSubmitted = (); } @@ -243,6 +244,7 @@ impl pallet_bridge_eth_poa::Trait for Runtime { type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval; type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration; type PruningStrategy = kovan::PruningStrategy; + type ChainTime = kovan::ChainTime; type OnHeadersSubmitted = (); } diff --git a/bin/rialto/runtime/src/rialto_poa.rs b/bin/rialto/runtime/src/rialto_poa.rs index 4839579b04e05..324179b55d88c 100644 --- a/bin/rialto/runtime/src/rialto_poa.rs +++ b/bin/rialto/runtime/src/rialto_poa.rs @@ -23,7 +23,8 @@ use bp_header_chain::BaseHeaderChain; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_eth_poa::{ - AuraConfiguration, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, ValidatorsSource, + AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, + ValidatorsSource, }; use sp_std::prelude::*; @@ -109,6 +110,17 @@ impl TPruningStrategy for PruningStrategy { } } +/// ChainTime provider +#[derive(Default)] +pub struct ChainTime; + +impl TChainTime for ChainTime { + fn is_timestamp_ahead(&self, timestamp: u64) -> bool { + let now = super::Timestamp::now(); + timestamp > now + } +} + /// The Rialto PoA Blockchain as seen by the runtime. pub struct RialtoBlockchain; diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index eb8393f4905ae..83be6d79639a4 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -26,6 +26,7 @@ sp-std = { version = "2.0", default-features = false } [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } +hex-literal = "0.3" [features] default = ["std"] diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index 0a9ca57f8c135..50dccd6ea2ced 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -62,6 +62,8 @@ pub enum Error { UnsignedTooFarInTheFuture = 19, /// Trying to finalize sibling of finalized block. TryingToFinalizeSibling = 20, + /// Header timestamp is ahead of on-chain timestamp + HeaderTimestampIsAhead = 21, } impl Error { @@ -88,6 +90,7 @@ impl Error { Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided", Error::UnsignedTooFarInTheFuture => "The unsigned header is too far in future", Error::TryingToFinalizeSibling => "Trying to finalize sibling of finalized block", + Error::HeaderTimestampIsAhead => "Header timestamp is ahead of on-chain timestamp", } } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 977ffd6718159..1b41c3a8b20ad 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -18,7 +18,7 @@ use crate::error::Error; use crate::finality::finalize_blocks; use crate::validators::{Validators, ValidatorsConfiguration}; use crate::verification::{is_importable_header, verify_aura_header}; -use crate::{AuraConfiguration, ChangeToEnact, PruningStrategy, Storage}; +use crate::{AuraConfiguration, ChainTime, ChangeToEnact, PruningStrategy, Storage}; use bp_eth_poa::{AuraHeader, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; @@ -31,13 +31,16 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// we have NOT imported. /// Returns error if fatal error has occured during import. Some valid headers may be /// imported in this case. -pub fn import_headers( +/// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/415) +#[allow(clippy::too_many_arguments)] +pub fn import_headers( storage: &mut S, pruning_strategy: &mut PS, aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, submitter: Option, headers: Vec<(AuraHeader, Option>)>, + chain_time: &CT, finalized_headers: &mut BTreeMap, ) -> Result<(u64, u64), Error> { let mut useful = 0; @@ -50,6 +53,7 @@ pub fn import_headers( validators_config, submitter.clone(), header, + chain_time, receipts, ); @@ -79,20 +83,23 @@ pub type FinalizedHeaders = Vec<(HeaderId, Option<::Submitter>) /// has returned true. /// /// Returns imported block id and list of all finalized headers. -pub fn import_header( +/// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/415) +#[allow(clippy::too_many_arguments)] +pub fn import_header( storage: &mut S, pruning_strategy: &mut PS, aura_config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, submitter: Option, header: AuraHeader, + chain_time: &CT, receipts: Option>, ) -> Result<(HeaderId, FinalizedHeaders), Error> { // first check that we are able to import this header at all let (header_id, finalized_id) = is_importable_header(storage, &header)?; // verify header - let import_context = verify_aura_header(storage, aura_config, submitter, &header)?; + let import_context = verify_aura_header(storage, aura_config, submitter, &header, chain_time)?; // check if block schedules new validators let validators = Validators::new(validators_config); @@ -195,6 +202,7 @@ mod tests { &test_validators_config(), None, Default::default(), + &(), None, ), Err(Error::AncientHeader), @@ -215,6 +223,7 @@ mod tests { &test_validators_config(), None, header.clone(), + &(), None, ) .map(|_| ()), @@ -228,6 +237,7 @@ mod tests { &test_validators_config(), None, header, + &(), None, ) .map(|_| ()), @@ -254,6 +264,7 @@ mod tests { &validators_config, None, header, + &(), None ) .map(|_| ()), @@ -291,6 +302,7 @@ mod tests { &validators_config, Some(100), header, + &(), None, ) .unwrap(); @@ -320,6 +332,7 @@ mod tests { &validators_config, Some(101), header11.clone(), + &(), Some(vec![validators_change_receipt(latest_block_id.hash)]), ) .unwrap(); @@ -345,6 +358,7 @@ mod tests { &validators_config, Some(102), header, + &(), None, ) .unwrap(); @@ -374,6 +388,7 @@ mod tests { &validators_config, Some(103), header, + &(), None, ) .unwrap(); @@ -404,6 +419,7 @@ mod tests { )), None, header, + &(), None, ) .map(|_| id) diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index afc5c681a39a4..2328864957ad0 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -326,6 +326,25 @@ pub trait PruningStrategy: Default { fn pruning_upper_bound(&mut self, best_number: u64, best_finalized_number: u64) -> u64; } +/// ChainTime represents the runtime on-chain time +pub trait ChainTime: Default { + /// Is a header timestamp ahead of the current on-chain time. + /// + /// Check whether `timestamp` is ahead (i.e greater than) the current on-chain + /// time. If so, return `true`, `false` otherwise. + fn is_timestamp_ahead(&self, timestamp: u64) -> bool; +} + +/// ChainTime implementation for the empty type. +/// +/// This implementation will allow a runtime without the timestamp pallet to use +/// the empty type as its ChainTime associated type. +impl ChainTime for () { + fn is_timestamp_ahead(&self, _: u64) -> bool { + false + } +} + /// Callbacks for header submission rewards/penalties. pub trait OnHeadersSubmitted { /// Called when valid headers have been submitted. @@ -366,6 +385,8 @@ pub trait Trait: frame_system::Trait { type FinalityVotesCachingInterval: Get>; /// Headers pruning strategy. type PruningStrategy: PruningStrategy; + /// Header timestamp verification against current on-chain time. + type ChainTime: ChainTime; /// Handler for headers submission result. type OnHeadersSubmitted: OnHeadersSubmitted; @@ -385,6 +406,7 @@ decl_module! { &T::ValidatorsConfiguration::get(), None, header, + &T::ChainTime::default(), receipts, ).map_err(|e| e.msg())?; } @@ -406,6 +428,7 @@ decl_module! { &T::ValidatorsConfiguration::get(), Some(submitter.clone()), headers_with_receipts, + &T::ChainTime::default(), &mut finalized_headers, ); @@ -531,6 +554,7 @@ impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Mod &T::ValidatorsConfiguration::get(), &pool_configuration(), header, + &T::ChainTime::default(), receipts.as_ref(), ); diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 2c46c7c5407d9..1255cc671962b 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -18,7 +18,7 @@ pub use crate::test_utils::{insert_header, validator_utils::*, validators_change pub use bp_eth_poa::signatures::secret_to_address; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, GenesisConfig, PruningStrategy, Trait}; +use crate::{AuraConfiguration, ChainTime, GenesisConfig, PruningStrategy, Trait}; use bp_eth_poa::{Address, AuraHeader, H256, U256}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use secp256k1::SecretKey; @@ -83,6 +83,7 @@ impl Trait for TestRuntime { type ValidatorsConfiguration = TestValidatorsConfiguration; type FinalityVotesCachingInterval = TestFinalityVotesCachingInterval; type PruningStrategy = KeepSomeHeadersBehindBest; + type ChainTime = ConstChainTime; type OnHeadersSubmitted = (); } @@ -168,3 +169,14 @@ impl PruningStrategy for KeepSomeHeadersBehindBest { best_number.saturating_sub(self.0) } } + +/// Constant chain time +#[derive(Default)] +pub struct ConstChainTime; + +impl ChainTime for ConstChainTime { + fn is_timestamp_ahead(&self, timestamp: u64) -> bool { + let now = i32::max_value() as u64 / 2; + timestamp > now + } +} diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index c9592c567efe9..90d3f2a4748b6 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -16,7 +16,7 @@ use crate::error::Error; use crate::validators::{Validators, ValidatorsConfiguration}; -use crate::{AuraConfiguration, ImportContext, PoolConfiguration, ScheduledChange, Storage}; +use crate::{AuraConfiguration, ChainTime, ImportContext, PoolConfiguration, ScheduledChange, Storage}; use bp_eth_poa::{ public_to_address, step_validator, Address, AuraHeader, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, }; @@ -46,19 +46,20 @@ pub fn is_importable_header(storage: &S, header: &AuraHeader) -> Res /// Try accept unsigned aura header into transaction pool. /// /// Returns required and provided tags. -pub fn accept_aura_header_into_pool( +pub fn accept_aura_header_into_pool( storage: &S, config: &AuraConfiguration, validators_config: &ValidatorsConfiguration, pool_config: &PoolConfiguration, header: &AuraHeader, + chain_time: &CT, receipts: Option<&Vec>, ) -> Result<(Vec, Vec), Error> { // check if we can verify further let (header_id, _) = is_importable_header(storage, header)?; // we can always do contextless checks - contextless_checks(config, header)?; + contextless_checks(config, header, chain_time)?; // we want to avoid having same headers twice in the pool // => we're strict about receipts here - if we need them, we require receipts to be Some, @@ -153,14 +154,15 @@ pub fn accept_aura_header_into_pool( } /// Verify header by Aura rules. -pub fn verify_aura_header( +pub fn verify_aura_header( storage: &S, config: &AuraConfiguration, submitter: Option, header: &AuraHeader, + chain_time: &CT, ) -> Result, Error> { // let's do the lightest check first - contextless_checks(config, header)?; + contextless_checks(config, header, chain_time)?; // the rest of checks requires access to the parent header let context = storage.import_context(submitter, &header.parent_hash).ok_or_else(|| { @@ -180,7 +182,11 @@ pub fn verify_aura_header( } /// Perform basic checks that only require header itself. -fn contextless_checks(config: &AuraConfiguration, header: &AuraHeader) -> Result<(), Error> { +fn contextless_checks( + config: &AuraConfiguration, + header: &AuraHeader, + chain_time: &CT, +) -> Result<(), Error> { let expected_seal_fields = expected_header_seal_fields(config, header); if header.seal.len() != expected_seal_fields { return Err(Error::InvalidSealArity); @@ -207,6 +213,10 @@ fn contextless_checks(config: &AuraConfiguration, header: &AuraHeader) -> Result return Err(Error::TimestampOverflow); } + if chain_time.is_timestamp_ahead(header.timestamp) { + return Err(Error::HeaderTimestampIsAhead); + } + Ok(()) } @@ -358,7 +368,7 @@ mod tests { use super::*; use crate::mock::{ insert_header, run_test_with_genesis, test_aura_config, validator, validator_address, validators_addresses, - validators_change_receipt, AccountId, HeaderBuilder, TestRuntime, GAS_LIMIT, + validators_change_receipt, AccountId, ConstChainTime, HeaderBuilder, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; use crate::DefaultInstance; @@ -366,8 +376,9 @@ mod tests { pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, ScheduledChanges, ValidatorsSet, ValidatorsSets, }; - use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520}; + use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256}; use frame_support::{StorageMap, StorageValue}; + use hex_literal::hex; use secp256k1::SecretKey; use sp_runtime::transaction_validity::TransactionTag; @@ -381,7 +392,7 @@ mod tests { fn verify_with_config(config: &AuraConfiguration, header: &AuraHeader) -> Result, Error> { run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - verify_aura_header(&storage, &config, None, header) + verify_aura_header(&storage, &config, None, header, &ConstChainTime::default()) }) } @@ -414,6 +425,7 @@ mod tests { &validators_config, &pool_configuration(), &header, + &(), receipts.as_ref(), ) }) @@ -554,6 +566,50 @@ mod tests { assert_ne!(default_verify(&header), Err(Error::TimestampOverflow)); } + #[test] + fn verifies_chain_time() { + // expected import context after verification + let expect = ImportContext:: { + submitter: None, + parent_hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3").into(), + parent_header: genesis(), + parent_total_difficulty: U256::zero(), + parent_scheduled_change: None, + validators_set_id: 0, + validators_set: ValidatorsSet { + validators: vec![ + hex!("dc5b20847f43d67928f49cd4f85d696b5a7617b5").into(), + hex!("897df33a7b3c62ade01e22c13d48f98124b4480f").into(), + hex!("05c987b34c6ef74e0c7e69c6e641120c24164c2d").into(), + ], + signal_block: None, + enact_block: HeaderId { + number: 0, + hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3").into(), + }, + }, + last_signal_block: None, + }; + + // header is behind + let header = HeaderBuilder::with_parent(&genesis()) + .timestamp(i32::max_value() as u64 / 2 - 100) + .sign_by(&validator(1)); + assert_eq!(default_verify(&header).unwrap(), expect); + + // header is ahead + let header = HeaderBuilder::with_parent(&genesis()) + .timestamp(i32::max_value() as u64 / 2 + 100) + .sign_by(&validator(1)); + assert_eq!(default_verify(&header), Err(Error::HeaderTimestampIsAhead)); + + // header has same timestamp as ConstChainTime + let header = HeaderBuilder::with_parent(&genesis()) + .timestamp(i32::max_value() as u64 / 2) + .sign_by(&validator(1)); + assert_eq!(default_verify(&header).unwrap(), expect); + } + #[test] fn verifies_parent_existence() { // when there's no parent in the storage From b16e9f26a0eae4f8c429816a9cd3a761432b79b4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 14 Oct 2020 08:19:39 +0300 Subject: [PATCH 0187/1210] connect to substrate using ws (#417) --- relays/ethereum/src/cli.yml | 2 +- relays/substrate-client/Cargo.toml | 2 +- relays/substrate-client/src/client.rs | 8 ++++---- relays/substrate-client/src/error.rs | 14 ++++++++++++-- relays/substrate-client/src/lib.rs | 8 ++++---- relays/substrate/src/cli.rs | 2 +- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index a665e76776967..c6a5b08e1bb04 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -24,7 +24,7 @@ subcommands: - sub-port: &sub-port long: sub-port value_name: SUB_PORT - help: Connect to Substrate node at given port. + help: Connect to Substrate node websocket server at given port. takes_value: true - sub-tx-mode: long: sub-tx-mode diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 3bf7ae9fafabd..4655ca3db918a 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "1.3.4" } -jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } +jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["ws"] } log = "0.4.11" num-traits = "0.2" diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 5d744a8920a3f..ad6dad1a2a475 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -22,7 +22,7 @@ use crate::{ConnectionParams, Result}; use jsonrpsee::common::DeserializeOwned; use jsonrpsee::raw::RawClient; -use jsonrpsee::transport::http::HttpTransportClient; +use jsonrpsee::transport::ws::WsTransportClient; use jsonrpsee::Client as RpcClient; use num_traits::Zero; use sp_core::Bytes; @@ -49,10 +49,10 @@ impl std::fmt::Debug for Client { } impl Client { - /// Returns client that is able to call RPCs on Substrate node. + /// Returns client that is able to call RPCs on Substrate node over websocket connection. pub async fn new(params: ConnectionParams) -> Result { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); + let uri = format!("ws://{}:{}", params.host, params.port); + let transport = WsTransportClient::new(&uri).await?; let raw_client = RawClient::new(transport); let client: RpcClient = raw_client.into(); diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index 6f8c206d7dac3..9dff9e02d2f64 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -17,6 +17,7 @@ //! Substrate node RPC errors. use jsonrpsee::client::RequestError; +use jsonrpsee::transport::ws::WsNewDnsError; use relay_utils::MaybeConnectionError; /// Result type used by Substrate client. @@ -26,13 +27,21 @@ pub type Result = std::result::Result; /// a Substrate node through RPC. #[derive(Debug)] pub enum Error { + /// Web socket connection error. + WsConnectionError(WsNewDnsError), /// An error that can occur when making an HTTP request to - /// an JSON-RPC client. + /// an JSON-RPC server. Request(RequestError), - /// The response from the client could not be SCALE decoded. + /// The response from the server could not be SCALE decoded. ResponseParseFailed(codec::Error), } +impl From for Error { + fn from(error: WsNewDnsError) -> Self { + Error::WsConnectionError(error) + } +} + impl From for Error { fn from(error: RequestError) -> Self { Error::Request(error) @@ -54,6 +63,7 @@ impl From for String { impl ToString for Error { fn to_string(&self) -> String { match self { + Self::WsConnectionError(e) => e.to_string(), Self::Request(e) => e.to_string(), Self::ResponseParseFailed(e) => e.what().to_string(), } diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index 6c978f4652222..9bc1cf164245a 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -30,12 +30,12 @@ pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; -/// Substrate connection params. +/// Substrate-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { - /// Substrate RPC host. + /// Websocket server hostname. pub host: String, - /// Substrate RPC port. + /// Websocket server TCP port. pub port: u16, } @@ -43,7 +43,7 @@ impl Default for ConnectionParams { fn default() -> Self { ConnectionParams { host: "localhost".into(), - port: 9933, + port: 9944, } } } diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 3dfda38e8a505..e13eccf6016dd 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -76,7 +76,7 @@ macro_rules! declare_chain_options { #[doc = "Connect to " $chain " node at given host."] #[structopt(long)] pub [<$chain_prefix _host>]: String, - #[doc = "Connect to " $chain " node at given port."] + #[doc = "Connect to " $chain " node websocket server at given port."] #[structopt(long)] pub [<$chain_prefix _port>]: u16, } From 0cd3add1c0d76d1e013163a7889692c1e8ac4bfe Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 14 Oct 2020 08:19:56 +0300 Subject: [PATCH 0188/1210] Millau -> Rialto headers relay (#398) * working-millau-to-rialto-relay * fix Millau state root * properly fix synced+incomplete headers for sub2sub * removed wrong TODO * fmt + clippy * Update relays/headers-relay/src/headers.rs Co-authored-by: Hernando Castano * moved SubstrateTransactionMaker definition * removed M from phantomdata * removed prune_synced_children * methods names as consts Co-authored-by: Hernando Castano --- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/millau.rs | 2 +- primitives/millau/src/lib.rs | 7 + relays/headers-relay/src/headers.rs | 197 ++++++++++++++++-- relays/headers-relay/src/sync_loop.rs | 2 +- relays/headers-relay/src/sync_types.rs | 2 +- relays/millau-client/src/lib.rs | 8 +- relays/rialto-client/src/lib.rs | 2 + relays/substrate-client/src/client.rs | 3 + relays/substrate/Cargo.toml | 4 +- relays/substrate/src/headers_target.rs | 168 +++++++++++++++ relays/substrate/src/main.rs | 1 + .../substrate/src/millau_headers_to_rialto.rs | 107 +++++----- 13 files changed, 435 insertions(+), 69 deletions(-) create mode 100644 relays/substrate/src/headers_target.rs diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 77a23cbf8f4ad..cdb09c6cb009f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -62,6 +62,7 @@ pub use frame_support::{ pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use pallet_substrate_bridge::Call as BridgeMillauCall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs index 47568f41742af..57ca750e2406d 100644 --- a/bin/rialto/runtime/src/millau.rs +++ b/bin/rialto/runtime/src/millau.rs @@ -36,7 +36,7 @@ pub fn initial_header() -> Header { Header { parent_hash: Default::default(), number: Default::default(), - state_root: hex!("bb65e8ba99408ebfefea9d28f74403d41da6858fa075c51fcc71dc383455c530").into(), + state_root: hex!("e901070e3bb061a6ae9ea8e4ba5417bf4c4642f9e75af9d372861c170ba7a9a3").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Default::default(), } diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 99bb0207f50db..844e4667c6036 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -49,6 +49,13 @@ impl Chain for Millau { type Header = Header; } +/// Name of the `MillauHeaderApi::best_block` runtime method. +pub const BEST_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_best_block"; +/// Name of the `MillauHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; +/// Name of the `MillauHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; + sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// diff --git a/relays/headers-relay/src/headers.rs b/relays/headers-relay/src/headers.rs index 5800d370fba0a..b8c51eec1b492 100644 --- a/relays/headers-relay/src/headers.rs +++ b/relays/headers-relay/src/headers.rs @@ -32,6 +32,8 @@ use std::{ type HeadersQueue

= BTreeMap<

::Number, HashMap<

::Hash, QueuedHeader

>>; +type SyncedChildren

= + BTreeMap<

::Number, HashMap<

::Hash, HashSet>>>; type KnownHeaders

= BTreeMap<

::Number, HashMap<

::Hash, HeaderStatus>>; @@ -63,6 +65,9 @@ pub struct QueuedHeaders { /// Headers that are (we believe) currently submitted to target node by our, /// not-yet mined transactions. submitted: HeadersQueue

, + /// Synced headers childrens. We need it to support case when header is synced, but some of + /// its parents are incomplete. + synced_children: SyncedChildren

, /// Pointers to all headers that we ever seen and we believe we can touch in the future. known_headers: KnownHeaders

, /// Headers that are waiting for completion data from source node. Mapped (and auto-sorted @@ -96,6 +101,7 @@ impl Default for QueuedHeaders

{ ready: HeadersQueue::new(), incomplete: HeadersQueue::new(), submitted: HeadersQueue::new(), + synced_children: SyncedChildren::

::new(), known_headers: KnownHeaders::

::new(), incomplete_headers: LinkedHashMap::new(), completion_data: LinkedHashMap::new(), @@ -419,13 +425,17 @@ impl QueuedHeaders

{ self.header_synced(&new_incomplete_header); } - move_header_descendants::

( - &mut [&mut self.ready, &mut self.submitted], - &mut self.incomplete, - &mut self.known_headers, - HeaderStatus::Incomplete, - &new_incomplete_header, - ); + let move_origins = select_synced_children::

(&self.synced_children, &new_incomplete_header); + let move_origins = move_origins.into_iter().chain(std::iter::once(new_incomplete_header)); + for move_origin in move_origins { + move_header_descendants::

( + &mut [&mut self.ready, &mut self.submitted], + &mut self.incomplete, + &mut self.known_headers, + HeaderStatus::Incomplete, + &move_origin, + ); + } if make_header_incomplete { log::debug!( @@ -460,13 +470,20 @@ impl QueuedHeaders

{ .cloned() .collect::>(); for just_completed_header in just_completed_headers { - move_header_descendants::

( - &mut [&mut self.incomplete], - &mut self.ready, - &mut self.known_headers, - HeaderStatus::Ready, - &just_completed_header, - ); + // sub2eth rejects H if H.Parent is incomplete + // sub2sub allows 'syncing' headers like that + // => let's check if there are some synced children of just completed header + let move_origins = select_synced_children::

(&self.synced_children, &just_completed_header); + let move_origins = move_origins.into_iter().chain(std::iter::once(just_completed_header)); + for move_origin in move_origins { + move_header_descendants::

( + &mut [&mut self.incomplete], + &mut self.ready, + &mut self.known_headers, + HeaderStatus::Ready, + &move_origin, + ); + } log::debug!( target: "bridge", @@ -514,6 +531,7 @@ impl QueuedHeaders

{ prune_queue(&mut self.ready, prune_border); prune_queue(&mut self.submitted, prune_border); prune_queue(&mut self.incomplete, prune_border); + self.synced_children = self.synced_children.split_off(&prune_border); prune_known_headers::

(&mut self.known_headers, prune_border); self.prune_border = prune_border; } @@ -527,6 +545,7 @@ impl QueuedHeaders

{ self.ready.clear(); self.incomplete.clear(); self.submitted.clear(); + self.synced_children.clear(); self.known_headers.clear(); self.best_synced_number = Zero::zero(); self.prune_border = Zero::zero(); @@ -568,6 +587,7 @@ impl QueuedHeaders

{ // queues let mut current = *id; let mut id_processed = false; + let mut previous_current = None; loop { let header = match self.status(¤t) { HeaderStatus::Unknown => break, @@ -582,8 +602,42 @@ impl QueuedHeaders

{ } .expect("header has a given status; given queue has the header; qed"); + // remember ids of all the children of the current header + let synced_children_entry = self + .synced_children + .entry(current.0) + .or_default() + .entry(current.1) + .or_default(); + let all_queues = [ + &self.maybe_orphan, + &self.orphan, + &self.maybe_extra, + &self.extra, + &self.ready, + &self.incomplete, + &self.submitted, + ]; + for queue in &all_queues { + let children_from_queue = queue + .get(&(current.0 + One::one())) + .map(|potential_children| { + potential_children + .values() + .filter(|potential_child| potential_child.header().parent_id() == current) + .map(|child| child.id()) + .collect::>() + }) + .unwrap_or_default(); + synced_children_entry.extend(children_from_queue); + } + if let Some(previous_current) = previous_current { + synced_children_entry.insert(previous_current); + } + set_header_status::

(&mut self.known_headers, ¤t, HeaderStatus::Synced); + previous_current = Some(current); current = header.parent_id(); id_processed = true; } @@ -706,6 +760,35 @@ fn move_header_descendants( } } +/// Selects (recursive) all synced children of given header. +fn select_synced_children( + synced_children: &SyncedChildren

, + id: &HeaderIdOf

, +) -> Vec> { + let mut result = Vec::new(); + let mut current_parents = HashSet::new(); + current_parents.insert(*id); + + while !current_parents.is_empty() { + let mut next_parents = HashSet::new(); + for current_parent in ¤t_parents { + let current_parent_synced_children = synced_children + .get(¤t_parent.0) + .and_then(|by_number_entry| by_number_entry.get(¤t_parent.1)); + if let Some(current_parent_synced_children) = current_parent_synced_children { + for current_parent_synced_child in current_parent_synced_children { + result.push(*current_parent_synced_child); + next_parents.insert(*current_parent_synced_child); + } + } + } + + let _ = std::mem::replace(&mut current_parents, next_parents); + } + + result +} + /// Return oldest header from the queue. fn oldest_header(queue: &HeadersQueue

) -> Option<&QueuedHeader

> { queue.values().flat_map(|h| h.values()).next() @@ -1050,6 +1133,37 @@ pub(crate) mod tests { .known_headers .values() .all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); + + // children of synced headers are stored + assert_eq!( + vec![id(97)], + queue.synced_children[&96][&hash(96)] + .iter() + .cloned() + .collect::>() + ); + assert_eq!( + vec![id(98)], + queue.synced_children[&97][&hash(97)] + .iter() + .cloned() + .collect::>() + ); + assert_eq!( + vec![id(99)], + queue.synced_children[&98][&hash(98)] + .iter() + .cloned() + .collect::>() + ); + assert_eq!( + vec![id(100)], + queue.synced_children[&99][&hash(99)] + .iter() + .cloned() + .collect::>() + ); + assert_eq!(0, queue.synced_children[&100][&hash(100)].len()); } #[test] @@ -1463,6 +1577,16 @@ pub(crate) mod tests { .or_default() .insert(hash(100), HeaderStatus::Ready); queue.ready.entry(100).or_default().insert(hash(100), header(100)); + queue + .synced_children + .entry(100) + .or_default() + .insert(hash(100), vec![id(101)].into_iter().collect()); + queue + .synced_children + .entry(102) + .or_default() + .insert(hash(102), vec![id(102)].into_iter().collect()); queue.prune(102); @@ -1472,6 +1596,7 @@ pub(crate) mod tests { assert_eq!(queue.orphan.len(), 1); assert_eq!(queue.maybe_orphan.len(), 1); assert_eq!(queue.incomplete.len(), 1); + assert_eq!(queue.synced_children.len(), 1); assert_eq!(queue.known_headers.len(), 4); queue.prune(110); @@ -1482,6 +1607,7 @@ pub(crate) mod tests { assert_eq!(queue.orphan.len(), 0); assert_eq!(queue.maybe_orphan.len(), 0); assert_eq!(queue.incomplete.len(), 0); + assert_eq!(queue.synced_children.len(), 0); assert_eq!(queue.known_headers.len(), 0); queue.header_response(header(109).header().clone()); @@ -1537,4 +1663,47 @@ pub(crate) mod tests { assert_eq!(queue.status(&id(103)), HeaderStatus::Incomplete); assert_eq!(queue.status(&id(104)), HeaderStatus::Incomplete); } + + #[test] + fn incomplete_headers_response_moves_synced_headers() { + let mut queue = QueuedHeaders::::default(); + + // we have submitted two headers - 100 and 101. 102 is ready + queue.submitted.entry(100).or_default().insert(hash(100), header(100)); + queue.submitted.entry(101).or_default().insert(hash(101), header(101)); + queue.ready.entry(102).or_default().insert(hash(102), header(102)); + queue + .known_headers + .entry(100) + .or_default() + .insert(hash(100), HeaderStatus::Submitted); + queue + .known_headers + .entry(101) + .or_default() + .insert(hash(101), HeaderStatus::Submitted); + queue + .known_headers + .entry(102) + .or_default() + .insert(hash(102), HeaderStatus::Ready); + + // both headers are accepted + queue.target_best_header_response(&id(101)); + + // but header 100 is incomplete + queue.incomplete_headers_response(vec![id(100)].into_iter().collect()); + assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(101)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(102)), HeaderStatus::Incomplete); + assert!(queue.incomplete_headers.contains_key(&id(100))); + assert!(queue.incomplete[&102].contains_key(&hash(102))); + + // when header 100 is completed, 101 is synced and 102 is ready + queue.incomplete_headers_response(HashSet::new()); + assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(101)), HeaderStatus::Synced); + assert_eq!(queue.status(&id(102)), HeaderStatus::Ready); + assert!(queue.ready[&102].contains_key(&hash(102))); + } } diff --git a/relays/headers-relay/src/sync_loop.rs b/relays/headers-relay/src/sync_loop.rs index 14eb7e2a4140e..c53a1ab0f082f 100644 --- a/relays/headers-relay/src/sync_loop.rs +++ b/relays/headers-relay/src/sync_loop.rs @@ -277,7 +277,7 @@ pub fn run>( }, &mut target_go_offline_future, |delay| async_std::task::sleep(delay), - || format!("Error retrieving best known header from {} node", P::TARGET_NAME), + || format!("Error retrieving best known {} header from {} node", P::SOURCE_NAME, P::TARGET_NAME), ).is_ok(); }, incomplete_headers_ids = target_incomplete_headers_future => { diff --git a/relays/headers-relay/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs index 0dcb712c91800..a910ce581c7e0 100644 --- a/relays/headers-relay/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -43,7 +43,7 @@ pub enum HeaderStatus { } /// Headers synchronization pipeline. -pub trait HeadersSyncPipeline: Clone + Copy + Send + Sync { +pub trait HeadersSyncPipeline: Clone + Send + Sync { /// Name of the headers source. const SOURCE_NAME: &'static str; /// Name of the headers target. diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index 291954cbea9e8..c1fadba024da1 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -60,12 +60,18 @@ impl From for SyncHeader { } } +impl From for millau_runtime::Header { + fn from(header: SyncHeader) -> Self { + header.0 + } +} + impl SourceHeader for SyncHeader { fn id(&self) -> HeaderId { relay_utils::HeaderId(*self.number(), self.hash()) } fn parent_id(&self) -> HeaderId { - relay_utils::HeaderId(*self.number(), *self.parent_hash()) + relay_utils::HeaderId(*self.number() - 1, *self.parent_hash()) } } diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs index b8601c3ccd0f7..95382cf591d9a 100644 --- a/relays/rialto-client/src/lib.rs +++ b/relays/rialto-client/src/lib.rs @@ -25,6 +25,8 @@ use sp_runtime::{ traits::{Header as HeaderT, IdentifyAccount}, }; +pub use rialto_runtime::BridgeMillauCall; + /// Rialto header id. pub type HeaderId = relay_utils::HeaderId; diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index ad6dad1a2a475..896b01477590c 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -33,6 +33,9 @@ const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; pub type OpaqueGrandpaAuthoritiesSet = Vec; /// Substrate client type. +/// +/// Cloning Client is a cheap operation. +#[derive(Clone)] pub struct Client { /// Substrate RPC client. client: RpcClient, diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index c10923dff9ff2..2e61699b7d933 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -16,6 +16,7 @@ structopt = "0.3" # Bridge dependencies +bp-millau = { path = "../../primitives/millau" } bp-rialto = { path = "../../primitives/rialto" } headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } @@ -24,6 +25,7 @@ relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } -# Substrate dependencies +# Substrate Dependencies +sp-core = "2.0" sp-runtime = "2.0" diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs new file mode 100644 index 0000000000000..92bc017a72eb2 --- /dev/null +++ b/relays/substrate/src/headers_target.rs @@ -0,0 +1,168 @@ +// Copyright 2019-2020 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 . + +//! Substrate client as Substrate headers target. The chain we connect to should have +//! runtime that implements `HeaderApi` to allow bridging with +//! chain. + +use async_trait::async_trait; +use codec::{Decode, Encode}; +use futures::TryFutureExt; +use headers_relay::{ + sync_loop::TargetClient, + sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, +}; +use relay_substrate_client::{Chain, Client, Error as SubstrateError}; +use relay_utils::HeaderId; +use sp_core::Bytes; +use sp_runtime::{DeserializeOwned, Justification}; +use std::collections::HashSet; + +/// Headers sync pipeline for Substrate <-> Substrate relays. +#[async_trait] +pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { + /// Name of the `best_block` runtime method. + const BEST_BLOCK_METHOD: &'static str; + /// Name of the `is_known_block` runtime method. + const IS_KNOWN_BLOCK_METHOD: &'static str; + /// Name of the `incomplete_headers` runtime method. + const INCOMPLETE_HEADERS_METHOD: &'static str; + + /// Signed transaction type. + type SignedTransaction: Send + Sync + Encode; + + /// Make submit header transaction. + async fn make_submit_header_transaction( + &self, + header: QueuedHeader, + ) -> Result; + + /// Make completion transaction for the header. + async fn make_complete_header_transaction( + &self, + id: HeaderIdOf, + completion: Justification, + ) -> Result; +} + +/// Substrate client as Substrate headers target. +pub struct SubstrateHeadersTarget { + client: Client, + pipeline: P, +} + +impl SubstrateHeadersTarget { + /// Create new Substrate headers target. + pub fn new(client: Client, pipeline: P) -> Self { + SubstrateHeadersTarget { client, pipeline } + } +} + +#[async_trait] +impl TargetClient

for SubstrateHeadersTarget +where + C: Chain, + C::Header: DeserializeOwned, + C::Index: DeserializeOwned, + P::Number: Decode, + P::Hash: Decode + Encode, + P: SubstrateHeadersSyncPipeline, +{ + type Error = SubstrateError; + + async fn best_header_id(&self) -> Result, Self::Error> { + let call = P::BEST_BLOCK_METHOD.into(); + let data = Bytes(Vec::new()); + + let encoded_response = self.client.state_call(call, data, None).await?; + let decoded_response: (P::Number, P::Hash) = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + Ok(best_header_id) + } + + async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), Self::Error> { + let call = P::IS_KNOWN_BLOCK_METHOD.into(); + let data = Bytes(id.1.encode()); + + let encoded_response = self.client.state_call(call, data, None).await?; + let is_known_block: bool = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + + Ok((id, is_known_block)) + } + + async fn submit_headers(&self, mut headers: Vec>) -> SubmittedHeaders, Self::Error> { + debug_assert_eq!( + headers.len(), + 1, + "Substrate pallet only supports single header / transaction" + ); + + let header = headers.remove(0); + let id = header.id(); + let submit_transaction_result = self + .pipeline + .make_submit_header_transaction(header) + .and_then(|tx| self.client.submit_extrinsic(Bytes(tx.encode()))) + .await; + + match submit_transaction_result { + Ok(_) => SubmittedHeaders { + submitted: vec![id], + incomplete: Vec::new(), + rejected: Vec::new(), + fatal_error: None, + }, + Err(error) => SubmittedHeaders { + submitted: Vec::new(), + incomplete: Vec::new(), + rejected: vec![id], + fatal_error: Some(error), + }, + } + } + + async fn incomplete_headers_ids(&self) -> Result>, Self::Error> { + let call = P::INCOMPLETE_HEADERS_METHOD.into(); + let data = Bytes(Vec::new()); + + let encoded_response = self.client.state_call(call, data, None).await?; + let decoded_response: Vec<(P::Number, P::Hash)> = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + + let incomplete_headers = decoded_response + .into_iter() + .map(|(number, hash)| HeaderId(number, hash)) + .collect(); + Ok(incomplete_headers) + } + + async fn complete_header( + &self, + id: HeaderIdOf

, + completion: Justification, + ) -> Result, Self::Error> { + let tx = self.pipeline.make_complete_header_transaction(id, completion).await?; + self.client.submit_extrinsic(Bytes(tx.encode())).await?; + Ok(id) + } + + async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), Self::Error> { + Ok((header.id(), false)) + } +} diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 743827ab8d871..ad77a13eea9bf 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -28,6 +28,7 @@ pub type MillauClient = relay_substrate_client::Client; mod cli; +mod headers_target; mod millau_headers_to_rialto; fn main() { diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index f7064c51bf111..67ac6d6b94e7a 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -16,24 +16,33 @@ //! Millau-to-Rialto headers sync entrypoint. -use crate::{MillauClient, RialtoClient}; +use crate::{ + headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, + MillauClient, RialtoClient, +}; use async_trait::async_trait; +use bp_millau::{BEST_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, IS_KNOWN_MILLAU_BLOCK_METHOD}; use codec::Encode; use headers_relay::{ sync::{HeadersSyncParams, TargetTransactionMode}, - sync_loop::TargetClient, - sync_types::{HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, + sync_types::{HeadersSyncPipeline, QueuedHeader}, }; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SyncHeader as MillauSyncHeader}; -use relay_rialto_client::SigningParams as RialtoSigningParams; -use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Error as SubstrateError, HashOf}; +use relay_rialto_client::{BridgeMillauCall, Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{ + headers_source::HeadersSource, BlockNumberOf, Error as SubstrateError, HashOf, TransactionSignScheme, +}; +use sp_core::Pair; use sp_runtime::Justification; -use std::{collections::HashSet, time::Duration}; +use std::time::Duration; /// Millau-to-Rialto headers pipeline. -#[derive(Debug, Clone, Copy)] -struct MillauHeadersToRialto; +#[derive(Debug, Clone)] +struct MillauHeadersToRialto { + client: RialtoClient, + sign: RialtoSigningParams, +} impl HeadersSyncPipeline for MillauHeadersToRialto { const SOURCE_NAME: &'static str = "Millau"; @@ -50,51 +59,46 @@ impl HeadersSyncPipeline for MillauHeadersToRialto { } } -/// Millau header in-the-queue. -type QueuedMillauHeader = QueuedHeader; - -/// Millau node as headers source. -type MillauSourceClient = HeadersSource; - -/// Rialto node as headers target. -struct RialtoTargetClient { - _client: RialtoClient, - _sign: RialtoSigningParams, -} - #[async_trait] -impl TargetClient for RialtoTargetClient { - type Error = SubstrateError; +impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { + const BEST_BLOCK_METHOD: &'static str = BEST_MILLAU_BLOCK_METHOD; + const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_MILLAU_BLOCK_METHOD; + const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_MILLAU_HEADERS_METHOD; - async fn best_header_id(&self) -> Result { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") - } + type SignedTransaction = ::SignedTransaction; - async fn is_known_header(&self, _id: MillauHeaderId) -> Result<(MillauHeaderId, bool), Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + async fn make_submit_header_transaction( + &self, + header: QueuedMillauHeader, + ) -> Result { + let account_id = self.sign.signer.public().as_array_ref().clone().into(); + let nonce = self.client.next_account_index(account_id).await?; + let call = BridgeMillauCall::import_signed_header(header.header().clone().into()).into(); + let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + Ok(transaction) } - async fn submit_headers(&self, _headers: Vec) -> SubmittedHeaders { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") + async fn make_complete_header_transaction( + &self, + id: MillauHeaderId, + completion: Justification, + ) -> Result { + let account_id = self.sign.signer.public().as_array_ref().clone().into(); + let nonce = self.client.next_account_index(account_id).await?; + let call = BridgeMillauCall::finalize_header(id.1, completion).into(); + let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + Ok(transaction) } +} - async fn incomplete_headers_ids(&self) -> Result, Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") - } +/// Millau header in-the-queue. +type QueuedMillauHeader = QueuedHeader; - #[allow(clippy::unit_arg)] - async fn complete_header( - &self, - _id: MillauHeaderId, - _completion: Justification, - ) -> Result { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") - } +/// Millau node as headers source. +type MillauSourceClient = HeadersSource; - async fn requires_extra(&self, _header: QueuedMillauHeader) -> Result<(MillauHeaderId, bool), Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/209") - } -} +/// Rialto node as headers target. +type RialtoTargetClient = SubstrateHeadersTarget; /// Run Millau-to-Rialto headers sync. pub fn run( @@ -107,8 +111,8 @@ pub fn run( let rialto_tick = Duration::from_secs(5); let sync_params = HeadersSyncParams { max_future_headers_to_download: 32, - max_headers_in_submitted_status: 1024, - max_headers_in_single_submit: 8, + max_headers_in_submitted_status: 8, + max_headers_in_single_submit: 1, max_headers_size_in_single_submit: 1024 * 1024, prune_depth: 256, target_tx_mode: TargetTransactionMode::Signed, @@ -117,10 +121,13 @@ pub fn run( headers_relay::sync_loop::run( MillauSourceClient::new(millau_client), millau_tick, - RialtoTargetClient { - _client: rialto_client, - _sign: rialto_sign, - }, + RialtoTargetClient::new( + rialto_client.clone(), + MillauHeadersToRialto { + client: rialto_client, + sign: rialto_sign, + }, + ), rialto_tick, sync_params, metrics_params, From 352533ebcfb340939d2cd4fdec659d3a51a9a2cb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 11:24:44 +0000 Subject: [PATCH 0189/1210] Bump serde from 1.0.116 to 1.0.117 (#427) --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index eb37ea473f36d..65ea06963c37d 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" -serde = { version = "1.0.115", optional = true, features = ["derive"] } +serde = { version = "1.0.117", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index fc7058f010cf3..1cda71cf9ef8d 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } -serde = { version = "1.0.115", optional = true, features = ["derive"] } +serde = { version = "1.0.117", optional = true, features = ["derive"] } # Bridge dependencies From fa2007ea94436f33137811bc92f8a77c249883da Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 18:41:23 +0000 Subject: [PATCH 0190/1210] Bump serde_json from 1.0.58 to 1.0.59 (#426) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index b1a45acbae0c3..f7d1cdd2041ca 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.11" num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.58" +serde_json = "1.0.59" time = "0.2" # Bridge dependencies From e18f587149b3389a2c495b1695ce8190660df9c1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 18:49:15 +0000 Subject: [PATCH 0191/1210] Bump structopt from 0.3.19 to 0.3.20 (#425) --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 527507c16a1d5..3485c8d487c5b 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.1.0" -structopt = "0.3.19" +structopt = "0.3.20" # Bridge dependencies bp-rialto = { path = "../../../primitives/rialto" } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index bb1a86480aa1a..be700d9353fc8 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.1.0" -structopt = "0.3.19" +structopt = "0.3.20" # Bridge dependencies From 5b4b3ada5cdd6fcb22220f8cd9563ff4e26f1d6e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2020 20:30:18 +0000 Subject: [PATCH 0192/1210] Bump env_logger from 0.7.1 to 0.8.1 (#424) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index f7d1cdd2041ca..66f38dff1db60 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1.41" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } -env_logger = "0.7.0" +env_logger = "0.8.1" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" From a0fa8349d6008161bc52abd453d799c5cbad2d75 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 20 Oct 2020 13:12:35 +0300 Subject: [PATCH 0193/1210] Reward relayers for dispatching messages (#385) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * reward relayers for dispatching messages * clippy * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano * added comment * Update modules/message-lane/src/inbound_lane.rs Co-authored-by: Tomasz Drwięga * Update modules/message-lane/src/inbound_lane.rs Co-authored-by: Tomasz Drwięga * SubmitterId + RelayerId -> AccountId * add confirmation_relayer arg to pay_relayer_reward * cargo fmt --all * removed verify_and_decode_messages_proof from SourceHeaderChain * &mut self -> RefCell * Optimize max messages at inbound lane (#418) * Add tests for checking messages above max limit Signed-off-by: MaciejBaj * Extend the relayers entry of inbound lane by additional msg nonce Signed-off-by: MaciejBaj * Support additional message nonce from inbound relayers Signed-off-by: MaciejBaj * Code format Signed-off-by: MaciejBaj * Merge messages range for highest relayers * Change unwrap() to ensure() while accessing relayers * Edit rustdocs for relayers deque at inbound lane data Co-authored-by: Hernando Castano * Declare additional relayers A & B and use across tests consistently Signed-off-by: MaciejBaj * Remove duplicates and improve naming for inbound lane tests * Fix test checking max limit per inbound lane * Correct relayers rewards loop after a proof is received * Remove redundant check for messages ahead of received range * Correct grammar at inbound lane tests rustdocs Co-authored-by: Hernando Castano * Improve code quality of relayers updates :nail_care: Co-authored-by: Tomasz Drwięga * Test dispatches above max limit from same relayer Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga * Fix typo. Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga Co-authored-by: Maciej Baj Co-authored-by: Tomasz Drwięga --- modules/message-lane/src/inbound_lane.rs | 268 ++++++++++++++++- modules/message-lane/src/lib.rs | 310 ++++++++++++++++---- modules/message-lane/src/mock.rs | 79 ++++- primitives/message-lane/src/lib.rs | 32 +- primitives/message-lane/src/source_chain.rs | 9 +- primitives/message-lane/src/target_chain.rs | 32 +- 6 files changed, 649 insertions(+), 81 deletions(-) diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index 0c88b7796998d..1d63b5675cf06 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -18,20 +18,25 @@ use bp_message_lane::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - InboundLaneData, LaneId, MessageKey, MessageNonce, + InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, }; +use sp_std::prelude::PartialEq; /// Inbound lane storage. pub trait InboundLaneStorage { /// Delivery and dispatch fee type on source chain. type MessageFee; + /// Id of relayer on source chain. + type Relayer: PartialEq; /// Lane id. fn id(&self) -> LaneId; + /// Return maximal number of unconfirmed messages in inbound lane. + fn max_unconfirmed_messages(&self) -> MessageNonce; /// Get lane data from the storage. - fn data(&self) -> InboundLaneData; + fn data(&self) -> InboundLaneData; /// Update lane data in the storage. - fn set_data(&mut self, data: InboundLaneData); + fn set_data(&mut self, data: InboundLaneData); } /// Inbound messages lane. @@ -45,9 +50,44 @@ impl InboundLane { InboundLane { storage } } + /// Receive state of the corresponding outbound lane. + pub fn receive_state_update(&mut self, outbound_lane_data: OutboundLaneData) -> Option { + let mut data = self.storage.data(); + if outbound_lane_data.latest_received_nonce > data.latest_received_nonce { + // this is something that should never happen if proofs are correct + return None; + } + if outbound_lane_data.latest_received_nonce <= data.latest_confirmed_nonce { + return None; + } + + data.latest_confirmed_nonce = outbound_lane_data.latest_received_nonce; + // Firstly, remove all of the records where higher nonce <= new confirmed nonce + while data + .relayers + .front() + .map(|(_, nonce_high, _)| *nonce_high <= data.latest_confirmed_nonce) + .unwrap_or(false) + { + data.relayers.pop_front(); + } + // Secondly, update the next record with lower nonce equal to new confirmed nonce if needed. + // Note: There will be max. 1 record to update as we don't allow messages from relayers to overlap. + match data.relayers.front_mut() { + Some((nonce_low, _, _)) if *nonce_low < data.latest_confirmed_nonce => { + *nonce_low = data.latest_confirmed_nonce + 1; + } + _ => {} + } + + self.storage.set_data(data); + Some(outbound_lane_data.latest_received_nonce) + } + /// Receive new message. pub fn receive_message>( &mut self, + relayer: S::Relayer, nonce: MessageNonce, message_data: DispatchMessageData, ) -> bool { @@ -57,7 +97,24 @@ impl InboundLane { return false; } + // if there are more unconfirmed messages than we may accept, reject this message + if self.storage.max_unconfirmed_messages() <= data.relayers.len() as MessageNonce { + return false; + } + data.latest_received_nonce = nonce; + + let push_new = match data.relayers.back_mut() { + Some((_, nonce_high, last_relayer)) if last_relayer == &relayer => { + *nonce_high = nonce; + false + } + _ => true, + }; + if push_new { + data.relayers.push_back((nonce, nonce, relayer)); + } + self.storage.set_data(data); P::dispatch(DispatchMessage { @@ -77,23 +134,222 @@ mod tests { use super::*; use crate::{ inbound_lane, - mock::{message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, + mock::{ + message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, + TEST_RELAYER_B, TEST_RELAYER_C, + }, + DefaultInstance, RuntimeInboundLaneStorage, }; + fn receive_regular_message( + lane: &mut InboundLane>, + nonce: MessageNonce, + ) { + assert!(lane.receive_message::( + TEST_RELAYER_A, + nonce, + message_data(REGULAR_PAYLOAD).into() + )); + } + + #[test] + fn receive_status_update_ignores_status_from_the_future() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + receive_regular_message(&mut lane, 1); + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 10, + ..Default::default() + }), + None, + ); + + assert_eq!(lane.storage.data().latest_confirmed_nonce, 0); + }); + } + + #[test] + fn receive_status_update_ignores_obsolete_status() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + receive_regular_message(&mut lane, 1); + receive_regular_message(&mut lane, 2); + receive_regular_message(&mut lane, 3); + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 3, + ..Default::default() + }), + Some(3), + ); + assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 3, + ..Default::default() + }), + None, + ); + assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + }); + } + + #[test] + fn receive_status_update_works() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + receive_regular_message(&mut lane, 1); + receive_regular_message(&mut lane, 2); + receive_regular_message(&mut lane, 3); + assert_eq!(lane.storage.data().latest_confirmed_nonce, 0); + assert_eq!(lane.storage.data().relayers, vec![(1, 3, TEST_RELAYER_A)]); + + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 2, + ..Default::default() + }), + Some(2), + ); + assert_eq!(lane.storage.data().latest_confirmed_nonce, 2); + assert_eq!(lane.storage.data().relayers, vec![(3, 3, TEST_RELAYER_A)]); + + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 3, + ..Default::default() + }), + Some(3), + ); + assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().relayers, vec![]); + }); + } + + #[test] + fn receive_status_update_works_with_batches_from_relayers() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + let mut seed_storage_data = lane.storage.data(); + // Prepare data + seed_storage_data.latest_confirmed_nonce = 0; + seed_storage_data.latest_received_nonce = 5; + seed_storage_data.relayers.push_back((1, 1, TEST_RELAYER_A)); + // Simulate messages batch (2, 3, 4) from relayer #2 + seed_storage_data.relayers.push_back((2, 4, TEST_RELAYER_B)); + seed_storage_data.relayers.push_back((5, 5, TEST_RELAYER_C)); + lane.storage.set_data(seed_storage_data); + // Check + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 3, + ..Default::default() + }), + Some(3), + ); + assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!( + lane.storage.data().relayers, + vec![(4, 4, TEST_RELAYER_B), (5, 5, TEST_RELAYER_C)] + ); + }); + } + #[test] fn fails_to_receive_message_with_incorrect_nonce() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(!lane.receive_message::(10, message_data(REGULAR_PAYLOAD).into())); + assert!(!lane.receive_message::( + TEST_RELAYER_A, + 10, + message_data(REGULAR_PAYLOAD).into() + )); assert_eq!(lane.storage.data().latest_received_nonce, 0); }); } + #[test] + fn fails_to_receive_messages_above_max_limit_per_lane() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); + for current_nonce in 1..max_nonce + 1 { + assert!(lane.receive_message::( + TEST_RELAYER_A + current_nonce, + current_nonce, + message_data(REGULAR_PAYLOAD).into() + )); + } + // Fails to dispatch new message from different than latest relayer. + assert_eq!( + false, + lane.receive_message::( + TEST_RELAYER_A + max_nonce + 1, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ) + ); + // Fails to dispatch new messages from latest relayer. Prevents griefing attacks. + assert_eq!( + false, + lane.receive_message::( + TEST_RELAYER_A + max_nonce, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ) + ); + }); + } + + #[test] + fn correctly_receives_following_messages_from_two_relayers_alternately() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(lane.receive_message::( + TEST_RELAYER_A, + 1, + message_data(REGULAR_PAYLOAD).into() + )); + assert!(lane.receive_message::( + TEST_RELAYER_B, + 2, + message_data(REGULAR_PAYLOAD).into() + )); + assert!(lane.receive_message::( + TEST_RELAYER_A, + 3, + message_data(REGULAR_PAYLOAD).into() + )); + assert_eq!( + lane.storage.data().relayers, + vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B), (3, 3, TEST_RELAYER_A)] + ); + }); + } + + #[test] + fn rejects_same_message_from_two_different_relayers() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + assert!(lane.receive_message::( + TEST_RELAYER_A, + 1, + message_data(REGULAR_PAYLOAD).into() + )); + assert_eq!( + false, + lane.receive_message::(TEST_RELAYER_B, 1, message_data(REGULAR_PAYLOAD).into()) + ); + }); + } + #[test] fn correct_message_is_processed_instantly() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message::(1, message_data(REGULAR_PAYLOAD).into())); + receive_regular_message(&mut lane, 1); assert_eq!(lane.storage.data().latest_received_nonce, 1); }); } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index e79ccb6d483a3..8fcc1ce5aef05 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -34,7 +34,7 @@ use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, - target_chain::{MessageDispatch, SourceHeaderChain}, + target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use codec::{Decode, Encode}; @@ -43,7 +43,7 @@ use frame_support::{ Parameter, StorageMap, }; use frame_system::ensure_signed; -use sp_std::{marker::PhantomData, prelude::*}; +use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; @@ -66,6 +66,11 @@ pub trait Trait: frame_system::Trait { /// confirmed. The reason is that if you want to use lane, you should be ready to pay /// for it. type MaxMessagesToPruneAtOnce: Get; + /// Maximal number of messages in the 'unconfirmed' state at inbound lane. Unconfirmed + /// message at inbound lane is the message that has been: sent, delivered and dispatched. + /// Its delivery confirmation is still pending. This limit is introduced to bound maximal + /// number of relayers-ids in the inbound lane state. + type MaxUnconfirmedMessagesAtInboundLane: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter; @@ -76,11 +81,13 @@ pub trait Trait: frame_system::Trait { type InboundPayload: Decode; /// Message fee type of inbound messages. This fee is paid on the bridged chain. type InboundMessageFee: Decode; + /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the bridged chain. + type InboundRelayer: Parameter; // Types that are used by outbound_lane (on source chain). /// Target header chain. - type TargetHeaderChain: TargetHeaderChain; + type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier; /// Message delivery payment. @@ -98,8 +105,10 @@ pub trait Trait: frame_system::Trait { type MessagesProofOf = <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; /// Shortcut to messages delivery proof type for Trait. -type MessagesDeliveryProofOf = - <>::TargetHeaderChain as TargetHeaderChain<>::OutboundPayload>>::MessagesDeliveryProof; +type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< + >::OutboundPayload, + ::AccountId, +>>::MessagesDeliveryProof; decl_error! { pub enum Error for Module, I: Instance> { @@ -121,7 +130,7 @@ decl_error! { decl_storage! { trait Store for Module, I: Instance = DefaultInstance> as MessageLane { /// Map of lane id => inbound lane data. - InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; + InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; /// Map of lane id => outbound lane data. OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; /// All queued outbound messages. @@ -227,29 +236,33 @@ decl_module! { #[weight = DELIVERY_BASE_WEIGHT + dispatch_weight] pub fn receive_messages_proof( origin, + relayer_id: T::InboundRelayer, proof: MessagesProofOf, dispatch_weight: Weight, ) -> DispatchResult { let _ = ensure_signed(origin)?; // verify messages proof && convert proof into messages - let messages = T::SourceHeaderChain::verify_messages_proof(proof).map_err(|err| { - frame_support::debug::trace!( - target: "runtime", - "Rejecting invalid messages proof: {:?}", - err, - ); + let messages = verify_and_decode_messages_proof::(proof) + .map_err(|err| { + frame_support::debug::trace!( + target: "runtime", + "Rejecting invalid messages proof: {:?}", + err, + ); - Error::::InvalidMessagesProof - })?; - - // try to decode message payloads - let messages: Vec<_> = messages.into_iter().map(Into::into).collect(); + Error::::InvalidMessagesProof + })?; // verify that relayer is paying actual dispatch weight let actual_dispatch_weight: Weight = messages - .iter() - .map(T::MessageDispatch::dispatch_weight) + .values() + .map(|lane_messages| lane_messages + .messages + .iter() + .map(T::MessageDispatch::dispatch_weight) + .sum::() + ) .sum(); if dispatch_weight < actual_dispatch_weight { frame_support::debug::trace!( @@ -262,13 +275,31 @@ decl_module! { return Err(Error::::InvalidMessagesDispatchWeight.into()); } - // dispatch messages - let total_messages = messages.len(); + // dispatch messages and (optionally) update lane(s) state(s) + let mut total_messages = 0; let mut valid_messages = 0; - for message in messages { - let mut lane = inbound_lane::(message.key.lane_id); - if lane.receive_message::(message.key.nonce, message.data) { - valid_messages += 1; + for (lane_id, lane_data) in messages { + let mut lane = inbound_lane::(lane_id); + + if let Some(lane_state) = lane_data.lane_state { + let updated_latest_confirmed_nonce = lane.receive_state_update(lane_state); + if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { + frame_support::debug::trace!( + target: "runtime", + "Received lane {:?} state update: latest_confirmed_nonce={}", + lane_id, + updated_latest_confirmed_nonce, + ); + } + } + + for message in lane_data.messages { + debug_assert_eq!(message.key.lane_id, lane_id); + + total_messages += 1; + if lane.receive_message::(relayer_id.clone(), message.key.nonce, message.data) { + valid_messages += 1; + } } } @@ -285,8 +316,8 @@ decl_module! { /// Receive messages delivery proof from bridged chain. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn receive_messages_delivery_proof(origin, proof: MessagesDeliveryProofOf) -> DispatchResult { - let _ = ensure_signed(origin)?; - let (lane_id, nonce) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { + let confirmation_relayer = ensure_signed(origin)?; + let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { frame_support::debug::trace!( target: "runtime", "Rejecting invalid messages delivery proof: {:?}", @@ -296,16 +327,37 @@ decl_module! { Error::::InvalidMessagesDeliveryProof })?; + // mark messages as delivered let mut lane = outbound_lane::(lane_id); - let received_range = lane.confirm_delivery(nonce); + let received_range = lane.confirm_delivery(lane_data.latest_received_nonce); if let Some(received_range) = received_range { Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); + + // reward relayers that have delivered messages + // this loop is bounded by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + for (nonce_low, nonce_high, relayer) in lane_data.relayers { + let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0); + let nonce_end = sp_std::cmp::min(nonce_high, received_range.1); + // loop won't proceed if current entry is ahead of received range (begin > end). + for nonce in nonce_begin..nonce_end + 1 { + let message_data = OutboundMessages::::get(MessageKey { + lane_id, + nonce, + }).expect("message was just confirmed; we never prune unconfirmed messages; qed"); + + >::MessageDeliveryAndDispatchPayment::pay_relayer_reward( + &confirmation_relayer, + &relayer, + &message_data.fee, + ); + } + } } frame_support::debug::trace!( target: "runtime", "Received messages delivery proof up to (and including) {} at lane {:?}", - nonce, + lane_data.latest_received_nonce, lane_id, ); @@ -318,6 +370,7 @@ decl_module! { fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { InboundLane::new(RuntimeInboundLaneStorage { lane_id, + cached_data: RefCell::new(None), _phantom: Default::default(), }) } @@ -331,24 +384,44 @@ fn outbound_lane, I: Instance>(lane_id: LaneId) -> OutboundLane { +struct RuntimeInboundLaneStorage, I = DefaultInstance> { lane_id: LaneId, - _phantom: PhantomData<(T, I)>, + cached_data: RefCell>>, + _phantom: PhantomData, } impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { type MessageFee = T::InboundMessageFee; + type Relayer = T::InboundRelayer; fn id(&self) -> LaneId { self.lane_id } - fn data(&self) -> InboundLaneData { - InboundLanes::::get(&self.lane_id) + fn max_unconfirmed_messages(&self) -> MessageNonce { + T::MaxUnconfirmedMessagesAtInboundLane::get() + } + + fn data(&self) -> InboundLaneData { + match self.cached_data.clone().into_inner() { + Some(data) => data, + None => { + let data = InboundLanes::::get(&self.lane_id); + *self.cached_data.try_borrow_mut().expect( + "we're in the single-threaded environment;\ + we have no recursive borrows; qed", + ) = Some(data.clone()); + data + } + } } - fn set_data(&mut self, data: InboundLaneData) { - InboundLanes::::insert(&self.lane_id, data) + fn set_data(&mut self, data: InboundLaneData) { + *self.cached_data.try_borrow_mut().expect( + "we're in the single-threaded environment;\ + we have no recursive borrows; qed", + ) = Some(data.clone()); + InboundLanes::::insert(&self.lane_id, data) } } @@ -399,12 +472,32 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorag } } +/// Verify messages proof and return proved messages with decoded payload. +fn verify_and_decode_messages_proof, Fee, DispatchPayload: Decode>( + proof: Chain::MessagesProof, +) -> Result>, Chain::Error> { + Chain::verify_messages_proof(proof).map(|messages_by_lane| { + messages_by_lane + .into_iter() + .map(|(lane, lane_data)| { + ( + lane, + ProvedLaneMessages { + lane_state: lane_data.lane_state, + messages: lane_data.messages.into_iter().map(Into::into).collect(), + }, + ) + }) + .collect() + }) +} + #[cfg(test)] mod tests { use super::*; use crate::mock::{ - message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestRuntime, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, + message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesProof, TestRuntime, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Module as System, Phase}; @@ -440,7 +533,13 @@ mod tests { assert_ok!(Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok((TEST_LANE_ID, 1)), + Ok(( + TEST_LANE_ID, + InboundLaneData { + latest_received_nonce: 1, + ..Default::default() + } + )), )); assert_eq!( @@ -508,13 +607,53 @@ mod tests { run_test(|| { assert_ok!(Module::::receive_messages_proof( Origin::signed(1), - Ok(vec![message(1, REGULAR_PAYLOAD)]), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + REGULAR_PAYLOAD.1, + )); + + assert_eq!(InboundLanes::::get(TEST_LANE_ID).latest_received_nonce, 1); + }); + } + + #[test] + fn receive_messages_proof_updates_confirmed_message_nonce() { + run_test(|| { + // say we have received 10 messages && last confirmed message is 8 + InboundLanes::::insert( + TEST_LANE_ID, + InboundLaneData { + latest_confirmed_nonce: 8, + latest_received_nonce: 10, + relayers: vec![(9, 9, TEST_RELAYER_A), (10, 10, TEST_RELAYER_B)] + .into_iter() + .collect(), + }, + ); + + // message proof includes outbound lane state with latest confirmed message updated to 9 + let mut message_proof: TestMessagesProof = Ok(vec![message(11, REGULAR_PAYLOAD)]).into(); + message_proof.result.as_mut().unwrap()[0].1.lane_state = Some(OutboundLaneData { + latest_received_nonce: 9, + ..Default::default() + }); + + assert_ok!(Module::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + message_proof, REGULAR_PAYLOAD.1, )); assert_eq!( - InboundLanes::::get(TEST_LANE_ID).latest_received_nonce, - 1 + InboundLanes::::get(TEST_LANE_ID), + InboundLaneData { + relayers: vec![(10, 10, TEST_RELAYER_B), (11, 11, TEST_RELAYER_A)] + .into_iter() + .collect(), + latest_received_nonce: 11, + latest_confirmed_nonce: 9, + }, ); }); } @@ -525,7 +664,8 @@ mod tests { assert_noop!( Module::::receive_messages_proof( Origin::signed(1), - Ok(vec![message(1, REGULAR_PAYLOAD)]), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), REGULAR_PAYLOAD.1 - 1, ), Error::::InvalidMessagesDispatchWeight, @@ -537,7 +677,12 @@ mod tests { fn receive_messages_proof_rejects_invalid_proof() { run_test(|| { assert_noop!( - Module::::receive_messages_proof(Origin::signed(1), Err(()), 0), + Module::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + Err(()).into(), + 0, + ), Error::::InvalidMessagesProof, ); }); @@ -556,6 +701,68 @@ mod tests { }); } + #[test] + fn receive_messages_delivery_proof_rewards_relayers() { + run_test(|| { + assert_ok!(Module::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + 1000, + )); + assert_ok!(Module::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + 2000, + )); + + // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A + assert_ok!(Module::::receive_messages_delivery_proof( + Origin::signed(1), + Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![(1, 1, TEST_RELAYER_A)].into_iter().collect(), + latest_received_nonce: 1, + ..Default::default() + } + )), + )); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( + TEST_RELAYER_A, + 1000 + )); + assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid( + TEST_RELAYER_B, + 2000 + )); + + // this reports delivery of both message 1 and message 2 => reward is paid only to TEST_RELAYER_B + assert_ok!(Module::::receive_messages_delivery_proof( + Origin::signed(1), + Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] + .into_iter() + .collect(), + latest_received_nonce: 2, + ..Default::default() + } + )), + )); + assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid( + TEST_RELAYER_A, + 1000 + )); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( + TEST_RELAYER_B, + 2000 + )); + }); + } + #[test] fn receive_messages_delivery_proof_rejects_invalid_proof() { run_test(|| { @@ -574,14 +781,12 @@ mod tests { assert_ok!(Module::::receive_messages_proof( Origin::signed(1), - Ok(vec![invalid_message]), + TEST_RELAYER_A, + Ok(vec![invalid_message]).into(), 0, // weight may be zero in this case (all messages are improperly encoded) ),); - assert_eq!( - InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, - 1, - ); + assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 1,); }); } @@ -593,18 +798,17 @@ mod tests { assert_ok!(Module::::receive_messages_proof( Origin::signed(1), + TEST_RELAYER_A, Ok(vec![ message(1, REGULAR_PAYLOAD), invalid_message, message(3, REGULAR_PAYLOAD), - ]), + ]) + .into(), REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1, ),); - assert_eq!( - InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, - 3, - ); + assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 3,); }); } } diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 69faeb7cdcc87..398f85f655ffd 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -18,10 +18,10 @@ use crate::Trait; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, - target_chain::{DispatchMessage, MessageDispatch, SourceHeaderChain}, - LaneId, Message, MessageData, MessageKey, MessageNonce, + target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, + InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, }; -use codec::Encode; +use codec::{Decode, Encode}; use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; use sp_core::H256; use sp_runtime::{ @@ -29,10 +29,12 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, Perbill, }; +use std::collections::BTreeMap; pub type AccountId = u64; pub type TestPayload = (u64, Weight); pub type TestMessageFee = u64; +pub type TestRelayer = u64; #[derive(Clone, Eq, PartialEq, Debug)] pub struct TestRuntime; @@ -89,17 +91,20 @@ impl frame_system::Trait for TestRuntime { parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; + pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 16; } impl Trait for TestRuntime { type Event = TestEvent; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type OutboundPayload = TestPayload; type OutboundMessageFee = TestMessageFee; type InboundPayload = TestPayload; type InboundMessageFee = TestMessageFee; + type InboundRelayer = TestRelayer; type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; @@ -109,6 +114,15 @@ impl Trait for TestRuntime { type MessageDispatch = TestMessageDispatch; } +/// Account id of test relayer. +pub const TEST_RELAYER_A: AccountId = 100; + +/// Account id of additional test relayer - B. +pub const TEST_RELAYER_B: AccountId = 101; + +/// Account id of additional test relayer - C. +pub const TEST_RELAYER_C: AccountId = 102; + /// Error that is returned by all test implementations. pub const TEST_ERROR: &str = "Test error"; @@ -121,14 +135,42 @@ pub const REGULAR_PAYLOAD: TestPayload = (0, 50); /// Payload that is rejected by `TestTargetHeaderChain`. pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = (1, 50); +/// Vec of proved messages, grouped by lane. +pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages>)>; + +/// Test messages proof. +#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] +pub struct TestMessagesProof { + pub result: Result, +} + +impl From>, ()>> for TestMessagesProof { + fn from(result: Result>, ()>) -> Self { + Self { + result: result.map(|messages| { + let mut messages_by_lane: BTreeMap>> = + BTreeMap::new(); + for message in messages { + messages_by_lane + .entry(message.key.lane_id) + .or_default() + .messages + .push(message); + } + messages_by_lane.into_iter().collect() + }), + } + } +} + /// Target header chain that is used in tests. #[derive(Debug, Default)] pub struct TestTargetHeaderChain; -impl TargetHeaderChain for TestTargetHeaderChain { +impl TargetHeaderChain for TestTargetHeaderChain { type Error = &'static str; - type MessagesDeliveryProof = Result<(LaneId, MessageNonce), ()>; + type MessagesDeliveryProof = Result<(LaneId, InboundLaneData), ()>; fn verify_message(payload: &TestPayload) -> Result<(), Self::Error> { if *payload == PAYLOAD_REJECTED_BY_TARGET_CHAIN { @@ -140,7 +182,7 @@ impl TargetHeaderChain for TestTargetHeaderChain { fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, MessageNonce), Self::Error> { + ) -> Result<(LaneId, InboundLaneData), Self::Error> { proof.map_err(|_| TEST_ERROR) } } @@ -176,10 +218,17 @@ impl TestMessageDeliveryAndDispatchPayment { frame_support::storage::unhashed::put(b":reject-message-fee:", &true); } - /// Returns true if given fee has been paid by given relayer. + /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { frame_support::storage::unhashed::get(b":message-fee:") == Some((submitter, fee)) } + + /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is + /// cleared after the call. + pub fn is_reward_paid(relayer: AccountId, fee: TestMessageFee) -> bool { + let key = (b":relayer-reward:", relayer, fee).encode(); + frame_support::storage::unhashed::take::(&key).is_some() + } } impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { @@ -193,6 +242,11 @@ impl MessageDeliveryAndDispatchPayment for TestMessag frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee)); Ok(()) } + + fn pay_relayer_reward(_confirmation_relayer: &AccountId, relayer: &AccountId, fee: &TestMessageFee) { + let key = (b":relayer-reward:", relayer, fee).encode(); + frame_support::storage::unhashed::put(&key, &true); + } } /// Source header chain that is used in tests. @@ -202,10 +256,15 @@ pub struct TestSourceHeaderChain; impl SourceHeaderChain for TestSourceHeaderChain { type Error = &'static str; - type MessagesProof = Result>, ()>; + type MessagesProof = TestMessagesProof; - fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error> { - proof.map_err(|_| TEST_ERROR) + fn verify_messages_proof( + proof: Self::MessagesProof, + ) -> Result>, Self::Error> { + proof + .result + .map(|proof| proof.into_iter().collect()) + .map_err(|_| TEST_ERROR) } } diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index a3216439958b1..75c627e9e5ffa 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -25,7 +25,7 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_api::decl_runtime_apis; -use sp_std::prelude::*; +use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; pub mod target_chain; @@ -70,14 +70,38 @@ pub struct Message { } /// Inbound lane data. -#[derive(Default, Encode, Decode, Clone, RuntimeDebug, PartialEq)] -pub struct InboundLaneData { +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct InboundLaneData { + /// Identifiers of relayers and messages that they have delivered (ordered by message nonce). + /// It is guaranteed to have at most N entries, where N is configured at module level. If + /// there are N entries in this vec, then: + /// 1) all incoming messages are rejected if they're missing corresponding `proof-of(outbound-lane.state)`; + /// 2) all incoming messages are rejected if `proof-of(outbound-lane.state).latest_received_nonce` is + /// equal to `this.latest_confirmed_nonce`. + /// Given what is said above, all nonces in this queue are in range (latest_confirmed_nonce; latest_received_nonce]. + /// + /// When a relayer sends a single message, both of MessageNonces are the same. + /// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce. + /// Multiple dispatches from the same relayer one are allowed. + pub relayers: VecDeque<(MessageNonce, MessageNonce, RelayerId)>, /// Nonce of latest message that we have received from bridged chain. pub latest_received_nonce: MessageNonce, + /// Nonce of latest message that has been confirmed to the bridged chain. + pub latest_confirmed_nonce: MessageNonce, +} + +impl Default for InboundLaneData { + fn default() -> Self { + InboundLaneData { + relayers: VecDeque::new(), + latest_received_nonce: 0, + latest_confirmed_nonce: 0, + } + } } /// Outbound lane data. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct OutboundLaneData { /// Nonce of oldest message that we haven't yet pruned. May point to not-yet-generated message if /// all sent messages are already pruned. diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index cce5e0d5bfbce..fd188e56b7c91 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -16,7 +16,7 @@ //! Primitives of message lane module, that are used on the source chain. -use crate::{LaneId, MessageNonce}; +use crate::{InboundLaneData, LaneId}; use frame_support::Parameter; use sp_std::fmt::Debug; @@ -26,7 +26,7 @@ use sp_std::fmt::Debug; /// All implementations of this trait should only work with finalized data that /// can't change. Wrong implementation may lead to invalid lane states (i.e. lane /// that's stuck) and/or processing messages without paying fees. -pub trait TargetHeaderChain { +pub trait TargetHeaderChain { /// Error type. type Error: Debug + Into<&'static str>; @@ -50,7 +50,7 @@ pub trait TargetHeaderChain { /// Verify messages delivery proof and return lane && nonce of the latest recevied message. fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, MessageNonce), Self::Error>; + ) -> Result<(LaneId, InboundLaneData), Self::Error>; } /// Lane message verifier. @@ -94,4 +94,7 @@ pub trait MessageDeliveryAndDispatchPayment { /// Withhold/write-off delivery_and_dispatch_fee from submitter account to /// some relayers-fund account. fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &Balance) -> Result<(), Self::Error>; + + /// Pay reward for delivering message to the given relayer account. + fn pay_relayer_reward(confirmation_relayer: &AccountId, relayer: &AccountId, reward: &Balance); } diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index 8bc71ee830066..7b6514f26ef8f 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -16,11 +16,23 @@ //! Primitives of message lane module, that are used on the target chain. -use crate::{Message, MessageData, MessageKey}; +use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; -use codec::{Decode, Error as CodecError}; +use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; -use sp_std::{fmt::Debug, prelude::*}; +use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*}; + +/// Proved messages from the source chain. +pub type ProvedMessages = BTreeMap>; + +/// Proved messages from single lane of the source chain. +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +pub struct ProvedLaneMessages { + /// Optional outbound lane state. + pub lane_state: Option, + /// Messages sent through this lane. + pub messages: Vec, +} /// Message data with decoded dispatch payload. #[derive(RuntimeDebug)] @@ -49,14 +61,15 @@ pub trait SourceHeaderChain { /// Error type. type Error: Debug + Into<&'static str>; - /// Proof that messages are sent from source chain. + /// Proof that messages are sent from source chain. This may also include proof + /// of corresponding outbound lane states. type MessagesProof: Parameter; /// Verify messages proof and return proved messages. /// /// Messages vector is required to be sorted by nonce within each lane. Out-of-order /// messages will be rejected. - fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error>; + fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error>; } /// Called when inbound message is received. @@ -79,6 +92,15 @@ pub trait MessageDispatch { fn dispatch(message: DispatchMessage); } +impl Default for ProvedLaneMessages { + fn default() -> Self { + ProvedLaneMessages { + lane_state: None, + messages: Vec::new(), + } + } +} + impl From> for DispatchMessage { fn from(message: Message) -> Self { DispatchMessage { From 1ce913b78e5b868613522d780baab2f3e560ae1f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Oct 2020 17:03:32 +0300 Subject: [PATCH 0194/1210] (optionally) include outbound lane data into messages proof (#428) --- modules/message-lane/rpc/src/lib.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index 28aeb66ab15e5..61a82eae7f2c6 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -45,6 +45,8 @@ pub type MessagesDeliveryProof = Bytes; pub trait Runtime: Send + Sync + 'static { /// Return runtime storage key for given message. May return None if instance is unknown. fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option; + /// Return runtime storage key for outbound lane state. May return None if instance is unknown. + fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option; /// Return runtime storage key for inbound lane state. May return None if instance is unknown. fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option; } @@ -60,6 +62,7 @@ pub trait MessageLaneApi { lane: LaneId, begin: MessageNonce, end: MessageNonce, + include_outbound_lane_state: bool, block: Option, ) -> FutureResult; @@ -103,14 +106,22 @@ where lane: LaneId, begin: MessageNonce, end: MessageNonce, + include_outbound_lane_state: bool, block: Option, ) -> FutureResult { let runtime = self.runtime.clone(); + let outbound_lane_data_key = if include_outbound_lane_state { + Some(runtime.inbound_lane_data_key(&instance, &lane)) + } else { + None + }; Box::new( prove_keys_read( self.backend.clone(), block, - (begin..=end).map(move |nonce| runtime.message_key(&instance, &lane, nonce)), + (begin..=end) + .map(move |nonce| runtime.message_key(&instance, &lane, nonce)) + .chain(outbound_lane_data_key.into_iter()), ) .boxed() .compat() From aaa8e5e78d7a158a17e256d6da2dbf12703b74c8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Oct 2020 19:19:57 +0300 Subject: [PATCH 0195/1210] InboundLaneApi::latest_confirmed_nonce (#429) * InboundLaneApi::latest_confirmed_nonce * Fix wording and typo Co-authored-by: Hernando Castano --- modules/message-lane/src/lib.rs | 14 ++++++++++---- primitives/message-lane/src/lib.rs | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 8fcc1ce5aef05..0404fecd5cfa1 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -66,10 +66,16 @@ pub trait Trait: frame_system::Trait { /// confirmed. The reason is that if you want to use lane, you should be ready to pay /// for it. type MaxMessagesToPruneAtOnce: Get; - /// Maximal number of messages in the 'unconfirmed' state at inbound lane. Unconfirmed - /// message at inbound lane is the message that has been: sent, delivered and dispatched. - /// Its delivery confirmation is still pending. This limit is introduced to bound maximal - /// number of relayers-ids in the inbound lane state. + /// Maximal number of "messages" (see note below) in the 'unconfirmed' state at inbound lane. + /// Unconfirmed message at inbound lane is the message that has been: sent, delivered and + /// dispatched. Its delivery confirmation is still pending. This limit is introduced to bound + /// maximal number of relayers-ids in the inbound lane state. + /// + /// "Message" in this context does not necessarily mean an individual message, but instead + /// continuous range of individual messages, that are delivered by single relayer. So if relayer#1 + /// has submitted delivery transaction#1 with individual messages [1; 2] and then delivery + /// transaction#2 with individual messages [3; 4], this would be treated as single "Message" and + /// would occupy single unit of `MaxUnconfirmedMessagesAtInboundLane` limit. type MaxUnconfirmedMessagesAtInboundLane: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 75c627e9e5ffa..672ba719b97de 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -136,5 +136,7 @@ decl_runtime_apis! { pub trait InboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; } } From 7d4f0910a86e6a89db4beefc78a4265ffe7bc60c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 26 Oct 2020 03:43:09 +0000 Subject: [PATCH 0196/1210] Bump futures from 0.3.6 to 0.3.7 (#456) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 66f38dff1db60..1682e3f3ae808 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ env_logger = "0.8.1" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" -futures = "0.3.6" +futures = "0.3.7" hex = "0.4" hex-literal = "0.3" log = "0.4.11" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 2e61699b7d933..d58b9d6f37e98 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.2" async-trait = "0.1.41" codec = { package = "parity-scale-codec", version = "1.3.4" } -futures = "0.3.6" +futures = "0.3.7" log = "0.4.11" paste = "1.0" structopt = "0.3" From c41b0feff23d6b71a6496b267bfae67d0b35b430 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 26 Oct 2020 10:03:47 +0300 Subject: [PATCH 0197/1210] Integrate Rialto <-> Millau message lanes into Millau/Rialto runtimes (#386) * millau -> rialto lanes integration * extrace common message-lane integration types into bridge-runtime-common * rialto_messages.rs in Millau runtime * tests * Update bin/rialto/runtime/src/millau_messages.rs Co-authored-by: Hernando Castano * RELAYER_INTEREST_PERCENT -> RELAYER_FEE_PERCENT * Update bin/runtime-common/src/messages.rs Co-authored-by: Hernando Castano * estimate_message_dispatch_and_delivery_fee returns Result * Update bin/rialto/runtime/src/millau_messages.rs Co-authored-by: Hernando Castano * Update bin/rialto/runtime/src/millau_messages.rs Co-authored-by: Hernando Castano * Update bin/rialto/runtime/src/millau_messages.rs Co-authored-by: Hernando Castano * fmt * mowed weight formula to primitives Co-authored-by: Hernando Castano --- bin/millau/runtime/Cargo.toml | 6 + bin/millau/runtime/src/lib.rs | 44 +- bin/millau/runtime/src/rialto_messages.rs | 157 ++++++ bin/rialto/runtime/Cargo.toml | 10 +- bin/rialto/runtime/src/lib.rs | 44 +- bin/rialto/runtime/src/millau_messages.rs | 157 ++++++ bin/runtime-common/Cargo.toml | 39 ++ bin/runtime-common/src/lib.rs | 21 + bin/runtime-common/src/messages.rs | 539 +++++++++++++++++++ modules/call-dispatch/src/lib.rs | 4 +- modules/message-lane/Cargo.toml | 2 + modules/message-lane/src/instant_payments.rs | 75 +++ modules/message-lane/src/lib.rs | 2 + primitives/millau/src/lib.rs | 28 +- primitives/rialto/Cargo.toml | 1 + primitives/rialto/src/lib.rs | 28 +- primitives/runtime/src/lib.rs | 6 + 17 files changed, 1138 insertions(+), 25 deletions(-) create mode 100644 bin/millau/runtime/src/rialto_messages.rs create mode 100644 bin/rialto/runtime/src/millau_messages.rs create mode 100644 bin/runtime-common/Cargo.toml create mode 100644 bin/runtime-common/src/lib.rs create mode 100644 bin/runtime-common/src/messages.rs create mode 100644 modules/message-lane/src/instant_payments.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 65ea06963c37d..59a28d19413fe 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -17,6 +17,8 @@ serde = { version = "1.0.117", optional = true, features = ["derive"] } bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } bp-millau = { path = "../../../primitives/millau", default-features = false } bp-rialto = { path = "../../../primitives/rialto", default-features = false } +bp-runtime = { path = "../../../primitives/runtime", default-features = false } +bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } @@ -47,6 +49,7 @@ sp-runtime = { version = "2.0", default-features = false } sp-session = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } sp-transaction-pool = { version = "2.0", default-features = false } +sp-trie = { version = "2.0", default-features = false } sp-version = { version = "2.0", default-features = false } [build-dependencies] @@ -58,6 +61,8 @@ std = [ "bp-message-lane/std", "bp-millau/std", "bp-rialto/std", + "bp-runtime/std", + "bridge-runtime-common/std", "codec/std", "frame-executive/std", "frame-support/std", @@ -87,5 +92,6 @@ std = [ "sp-session/std", "sp-std/std", "sp-transaction-pool/std", + "sp-trie/std", "sp-version/std", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 340639e367333..dd8b0aa795286 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -29,12 +29,13 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto; +pub mod rialto_messages; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify}; +use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, @@ -65,18 +66,18 @@ pub use sp_runtime::{Perbill, Permill}; pub type BlockNumber = bp_millau::BlockNumber; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; +pub type Signature = bp_millau::Signature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type AccountId = bp_millau::AccountId; /// The type for looking up accounts. We don't expect more than 4 billion of them, but you /// never know... pub type AccountIndex = u32; /// Balance of an account. -pub type Balance = u128; +pub type Balance = bp_millau::Balance; /// Index of a transaction in the chain. pub type Index = u32; @@ -145,12 +146,10 @@ pub fn native_version() -> NativeVersion { parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 2_000_000_000_000; + pub const MaximumBlockWeight: Weight = bp_millau::MAXIMUM_BLOCK_WEIGHT; pub const ExtrinsicBaseWeight: Weight = 10_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - /// Assume 10% of weight for average on_initialize calls. - pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() - .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_millau::AVAILABLE_BLOCK_RATIO); + pub MaximumExtrinsicWeight: Weight = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT; pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { @@ -317,6 +316,32 @@ impl pallet_substrate_bridge::Trait for Runtime { impl pallet_shift_session_manager::Trait for Runtime {} +parameter_types! { + pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = 128; +} + +impl pallet_message_lane::Trait for Runtime { + type Event = Event; + type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + + type OutboundPayload = crate::rialto_messages::ToRialtoMessagePayload; + type OutboundMessageFee = Balance; + + type InboundPayload = crate::rialto_messages::FromRialtoMessagePayload; + type InboundMessageFee = bp_rialto::Balance; + type InboundRelayer = bp_rialto::AccountId; + + type TargetHeaderChain = crate::rialto_messages::Rialto; + type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; + type MessageDeliveryAndDispatchPayment = + pallet_message_lane::instant_payments::InstantCurrencyPayments>; + + type SourceHeaderChain = crate::rialto_messages::Rialto; + type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -324,6 +349,7 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, + BridgeRialtoMessageLane: pallet_message_lane::{Module, Call, Event}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs new file mode 100644 index 0000000000000..e2a41e88f9cdc --- /dev/null +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -0,0 +1,157 @@ +// Copyright 2019-2020 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 . + +//! Everything required to serve Millau <-> Rialto message lanes. + +use bridge_runtime_common::messages; + +use bp_message_lane::{ + source_chain::TargetHeaderChain, + target_chain::{ProvedMessages, SourceHeaderChain}, + InboundLaneData, LaneId, Message, MessageNonce, +}; +use bp_runtime::InstanceId; +use bridge_runtime_common::messages::MessageBridge; +use frame_support::{ + weights::{Weight, WeightToFeePolynomial}, + RuntimeDebug, +}; +use sp_trie::StorageProof; + +/// Message payload for Millau -> Rialto messages. +pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload; + +/// Message verifier for Millau -> Rialto messages. +pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier; + +/// Message payload for Rialto -> Millau messages. +pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; + +/// Call-dispatch based message dispatch for Rialto -> Millau messages. +pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< + WithRialtoMessageBridge, + crate::Runtime, + pallet_bridge_call_dispatch::DefaultInstance, +>; + +/// Millau <-> Rialto message bridge. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct WithRialtoMessageBridge; + +impl MessageBridge for WithRialtoMessageBridge { + const INSTANCE: InstanceId = *b"rlto"; + + const RELAYER_FEE_PERCENT: u32 = 10; + + type ThisChain = Millau; + type BridgedChain = Rialto; + + fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + // we don't want to relay too large messages + keep reserve for future upgrades + bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2 + } + + fn weight_of_delivery_transaction() -> Weight { + 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + } + + fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { + 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + } + + fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { + 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + } + + fn this_weight_to_balance(weight: Weight) -> bp_rialto::Balance { + ::WeightToFee::calc(&weight) + } + + fn bridged_weight_to_balance(weight: Weight) -> bp_millau::Balance { + // we're using the same weights in both chains now + ::WeightToFee::calc(&weight) + } + + fn this_chain_balance_to_bridged_chain_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { + // 1:1 conversion that will probably change in the future + this_balance + } +} + +/// Millau chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Millau; + +impl messages::ChainWithMessageLanes for Millau { + type AccountId = bp_millau::AccountId; + type Signer = bp_millau::AccountSigner; + type Signature = bp_millau::Signature; + type Call = crate::Call; + type Weight = Weight; + type Balance = bp_millau::Balance; +} + +/// Rialto chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Rialto; + +impl messages::ChainWithMessageLanes for Rialto { + type AccountId = bp_rialto::AccountId; + type Signer = bp_rialto::AccountSigner; + type Signature = bp_rialto::Signature; + type Call = (); // unknown to us + type Weight = Weight; + type Balance = bp_rialto::Balance; +} + +impl TargetHeaderChain for Rialto { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof or one or several keys; + // - id of the lane we prove state of. + type MessagesDeliveryProof = (bp_rialto::Hash, StorageProof, LaneId); + + fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { + if payload.weight > WithRialtoMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { + return Err("Too large weight declared"); + } + + Ok(()) + } + + fn verify_messages_delivery_proof( + _proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + } +} + +impl SourceHeaderChain for Rialto { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof or one or several keys; + // - id of the lane we prove messages for; + // - inclusive range of messages nonces that are proved. + type MessagesProof = (bp_rialto::Hash, StorageProof, LaneId, MessageNonce, MessageNonce); + + fn verify_messages_proof( + _proof: Self::MessagesProof, + ) -> Result>, Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + } +} diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 1cda71cf9ef8d..67e8ab8eee556 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -18,9 +18,12 @@ serde = { version = "1.0.117", optional = true, features = ["derive"] } bp-currency-exchange = { path = "../../../primitives/currency-exchange", default-features = false } bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = false } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } +bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } bp-millau = { path = "../../../primitives/millau", default-features = false } bp-rialto = { path = "../../../primitives/rialto", default-features = false } +bp-runtime = { path = "../../../primitives/runtime", default-features = false } +bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } @@ -55,6 +58,7 @@ sp-runtime = { version = "2.0", default-features = false } sp-session = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } sp-transaction-pool = { version = "2.0", default-features = false } +sp-trie = { version = "2.0", default-features = false } sp-version = { version = "2.0", default-features = false } [dev-dependencies] @@ -69,9 +73,12 @@ std = [ "bp-currency-exchange/std", "bp-eth-poa/std", "bp-header-chain/std", + "bp-message-dispatch/std", "bp-message-lane/std", - "bp-rialto/std", "bp-millau/std", + "bp-rialto/std", + "bp-runtime/std", + "bridge-runtime-common/std", "codec/std", "frame-benchmarking/std", "frame-executive/std", @@ -104,6 +111,7 @@ std = [ "sp-session/std", "sp-std/std", "sp-transaction-pool/std", + "sp-trie/std", "sp-version/std", ] runtime-benchmarks = [ diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index cdb09c6cb009f..c4815ea9bc7b5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -34,13 +34,14 @@ pub mod exchange; pub mod benches; pub mod kovan; pub mod millau; +pub mod millau_messages; pub mod rialto_poa; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, OpaqueKeys, Saturating, Verify}; +use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, @@ -73,18 +74,18 @@ pub use sp_runtime::{Perbill, Permill}; pub type BlockNumber = bp_rialto::BlockNumber; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; +pub type Signature = bp_rialto::Signature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +pub type AccountId = bp_rialto::AccountId; /// The type for looking up accounts. We don't expect more than 4 billion of them, but you /// never know... pub type AccountIndex = u32; /// Balance of an account. -pub type Balance = u128; +pub type Balance = bp_rialto::Balance; /// Index of a transaction in the chain. pub type Index = u32; @@ -153,12 +154,10 @@ pub fn native_version() -> NativeVersion { parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = 2_000_000_000_000; + pub const MaximumBlockWeight: Weight = bp_rialto::MAXIMUM_BLOCK_WEIGHT; pub const ExtrinsicBaseWeight: Weight = 10_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); - /// Assume 10% of weight for average on_initialize calls. - pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get() - .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get(); + pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_rialto::AVAILABLE_BLOCK_RATIO); + pub MaximumExtrinsicWeight: Weight = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT; pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { @@ -425,6 +424,32 @@ impl pallet_substrate_bridge::Trait for Runtime { impl pallet_shift_session_manager::Trait for Runtime {} +parameter_types! { + pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = 128; +} + +impl pallet_message_lane::Trait for Runtime { + type Event = Event; + type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + + type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; + type OutboundMessageFee = Balance; + + type InboundPayload = crate::millau_messages::FromMillauMessagePayload; + type InboundMessageFee = bp_millau::Balance; + type InboundRelayer = bp_millau::AccountId; + + type TargetHeaderChain = crate::millau_messages::Millau; + type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; + type MessageDeliveryAndDispatchPayment = + pallet_message_lane::instant_payments::InstantCurrencyPayments>; + + type SourceHeaderChain = crate::millau_messages::Millau; + type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -437,6 +462,7 @@ construct_runtime!( BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, + BridgeMillauMessageLane: pallet_message_lane::{Module, Call, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs new file mode 100644 index 0000000000000..920c3b39eb486 --- /dev/null +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -0,0 +1,157 @@ +// Copyright 2019-2020 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 . + +//! Everything required to serve Millau <-> Rialto message lanes. + +use bridge_runtime_common::messages; + +use bp_message_lane::{ + source_chain::TargetHeaderChain, + target_chain::{ProvedMessages, SourceHeaderChain}, + InboundLaneData, LaneId, Message, MessageNonce, +}; +use bp_runtime::InstanceId; +use bridge_runtime_common::messages::MessageBridge; +use frame_support::{ + weights::{Weight, WeightToFeePolynomial}, + RuntimeDebug, +}; +use sp_trie::StorageProof; + +/// Message payload for Rialto -> Millau messages. +pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; + +/// Message verifier for Rialto -> Millau messages. +pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; + +/// Message payload for Millau -> Rialto messages. +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; + +/// Call-dispatch based message dispatch for Millau -> Rialto messages. +pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< + WithMillauMessageBridge, + crate::Runtime, + pallet_bridge_call_dispatch::DefaultInstance, +>; + +/// Millau <-> Rialto message bridge. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct WithMillauMessageBridge; + +impl MessageBridge for WithMillauMessageBridge { + const INSTANCE: InstanceId = *b"mlau"; + + const RELAYER_FEE_PERCENT: u32 = 10; + + type ThisChain = Rialto; + type BridgedChain = Millau; + + fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + // we don't want to relay too large messages + keep reserve for future upgrades + bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2 + } + + fn weight_of_delivery_transaction() -> Weight { + 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + } + + fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { + 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + } + + fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { + 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + } + + fn this_weight_to_balance(weight: Weight) -> bp_rialto::Balance { + ::WeightToFee::calc(&weight) + } + + fn bridged_weight_to_balance(weight: Weight) -> bp_millau::Balance { + // we're using the same weights in both chains now + ::WeightToFee::calc(&weight) + } + + fn this_chain_balance_to_bridged_chain_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { + // 1:1 conversion that will probably change in the future + this_balance + } +} + +/// Rialto chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Rialto; + +impl messages::ChainWithMessageLanes for Rialto { + type AccountId = bp_rialto::AccountId; + type Signer = bp_rialto::AccountSigner; + type Signature = bp_rialto::Signature; + type Call = crate::Call; + type Weight = Weight; + type Balance = bp_rialto::Balance; +} + +/// Millau chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Millau; + +impl messages::ChainWithMessageLanes for Millau { + type AccountId = bp_millau::AccountId; + type Signer = bp_millau::AccountSigner; + type Signature = bp_millau::Signature; + type Call = (); // unknown to us + type Weight = Weight; + type Balance = bp_millau::Balance; +} + +impl TargetHeaderChain for Millau { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof of one or several keys; + // - id of the lane we prove state of. + type MessagesDeliveryProof = (bp_millau::Hash, StorageProof, LaneId); + + fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { + if payload.weight > WithMillauMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { + return Err("Payload has weight larger than maximum allowed weight"); + } + + Ok(()) + } + + fn verify_messages_delivery_proof( + _proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + } +} + +impl SourceHeaderChain for Millau { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof of one or several keys; + // - id of the lane we prove messages for; + // - inclusive range of messages nonces that are proved. + type MessagesProof = (bp_millau::Hash, StorageProof, LaneId, MessageNonce, MessageNonce); + + fn verify_messages_proof( + _proof: Self::MessagesProof, + ) -> Result>, Self::Error> { + unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + } +} diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml new file mode 100644 index 0000000000000..960fbc580caf8 --- /dev/null +++ b/bin/runtime-common/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "bridge-runtime-common" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } + +# Bridge dependencies + +bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } +bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } + +# Substrate dependencies + +frame-support = { version = "2.0", default-features = false } +sp-runtime = { version = "2.0", default-features = false } +sp-std = { version = "2.0", default-features = false } +sp-trie = { version = "2.0", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-dispatch/std", + "bp-message-lane/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "pallet-bridge-call-dispatch/std", + "sp-runtime/std", + "sp-std/std", + "sp-trie/std", +] diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs new file mode 100644 index 0000000000000..3168383f5eb8f --- /dev/null +++ b/bin/runtime-common/src/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2019-2020 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 . + +//! Common types/functions that may be used by runtimes of all bridged chains. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod messages; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs new file mode 100644 index 0000000000000..9e534c6d782ad --- /dev/null +++ b/bin/runtime-common/src/messages.rs @@ -0,0 +1,539 @@ +// Copyright 2019-2020 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 . + +//! Types that allow runtime to act as a source/target endpoint of message lanes. +//! +//! Messages are assumed to be encoded `Call`s of the target chain. Call-dispatch +//! pallet is used to dispatch incoming messages. Message identified by a tuple +//! of to elements - message lane id and message nonce. + +use bp_message_dispatch::MessageDispatch as _; +use bp_message_lane::{ + source_chain::LaneMessageVerifier, + target_chain::{DispatchMessage, MessageDispatch}, + LaneId, MessageNonce, +}; +use bp_runtime::InstanceId; +use codec::{Compact, Decode, Input}; +use frame_support::RuntimeDebug; +use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; +use sp_std::{cmp::PartialOrd, marker::PhantomData, vec::Vec}; + +/// Bidirectional message bridge. +pub trait MessageBridge { + /// Instance id of this bridge. + const INSTANCE: InstanceId; + + /// Relayer interest (in percents). + const RELAYER_FEE_PERCENT: u32; + + /// This chain in context of message bridge. + type ThisChain: ChainWithMessageLanes; + /// Bridged chain in context of message bridge. + type BridgedChain: ChainWithMessageLanes; + + /// Maximal (dispatch) weight of the message that we are able to send to Bridged chain. + fn maximal_dispatch_weight_of_message_on_bridged_chain() -> WeightOf>; + + /// Maximal weight of single message delivery transaction on Bridged chain. + fn weight_of_delivery_transaction() -> WeightOf>; + + /// Maximal weight of single message delivery confirmation transaction on This chain. + fn weight_of_delivery_confirmation_transaction_on_this_chain() -> WeightOf>; + + /// Weight of single message reward confirmation on the Bridged chain. This confirmation + /// is a part of delivery transaction, so this weight is added to the delivery + /// transaction weight. + fn weight_of_reward_confirmation_transaction_on_target_chain() -> WeightOf>; + + /// Convert weight of This chain to the fee (paid in Balance) of This chain. + fn this_weight_to_balance(weight: WeightOf>) -> BalanceOf>; + + /// Convert weight of the Bridged chain to the fee (paid in Balance) of the Bridged chain. + fn bridged_weight_to_balance(weight: WeightOf>) -> BalanceOf>; + + /// Convert This chain Balance into Bridged chain Balance. + fn this_chain_balance_to_bridged_chain_balance( + this_balance: BalanceOf>, + ) -> BalanceOf>; +} + +/// Chain that has `message-lane` and `call-dispatch` modules. +pub trait ChainWithMessageLanes { + /// Accound id on the chain. + type AccountId; + /// Public key of the chain account that may be used to verify signatures. + type Signer: Decode; + /// Signature type used on the chain. + type Signature: Decode; + /// Call type on the chain. + type Call: Decode; + /// Type of weight that is used on the chain. This would almost always be a regular + /// `frame_support::weight::Weight`. But since the meaning of weight on different chains + /// may be different, the `WeightOf<>` construct is used to avoid confusion between + /// different weights. + type Weight: From; + /// Type of balances that is used on the chain. + type Balance: CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; +} + +pub(crate) type ThisChain = ::ThisChain; +pub(crate) type BridgedChain = ::BridgedChain; +pub(crate) type AccountIdOf = ::AccountId; +pub(crate) type SignerOf = ::Signer; +pub(crate) type SignatureOf = ::Signature; +pub(crate) type WeightOf = ::Weight; +pub(crate) type BalanceOf = ::Balance; +pub(crate) type CallOf = ::Call; + +/// Sub-module that is declaring types required for processing This -> Bridged chain messages. +pub mod source { + use super::*; + + /// Encoded Call of the Bridged chain. We never try to decode it on This chain. + pub type BridgedChainOpaqueCall = Vec; + + /// Message payload for This -> Bridged chain messages. + pub type FromThisChainMessagePayload = pallet_bridge_call_dispatch::MessagePayload< + SignerOf>, + SignerOf>, + SignatureOf>, + BridgedChainOpaqueCall, + >; + + /// Message verifier that requires submitter to pay minimal delivery and dispatch fee. + #[derive(RuntimeDebug)] + pub struct FromThisChainMessageVerifier(PhantomData); + + impl + LaneMessageVerifier>, FromThisChainMessagePayload, BalanceOf>> + for FromThisChainMessageVerifier + { + type Error = &'static str; + + fn verify_message( + _submitter: &AccountIdOf>, + delivery_and_dispatch_fee: &BalanceOf>, + _lane: &LaneId, + payload: &FromThisChainMessagePayload, + ) -> Result<(), Self::Error> { + let minimal_fee_in_bridged_tokens = + estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; + + // compare with actual fee paid + let actual_fee_in_bridged_tokens = + B::this_chain_balance_to_bridged_chain_balance(*delivery_and_dispatch_fee); + if actual_fee_in_bridged_tokens < minimal_fee_in_bridged_tokens { + return Err("Too low fee paid"); + } + + Ok(()) + } + } + + /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged chain. + /// + /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional conversions. + /// Returns `None` if overflow has happened. + pub fn estimate_message_dispatch_and_delivery_fee( + payload: &FromThisChainMessagePayload, + relayer_fee_percent: u32, + ) -> Result>, &'static str> { + // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain + let delivery_fee = B::bridged_weight_to_balance(B::weight_of_delivery_transaction()); + let dispatch_fee = B::bridged_weight_to_balance(payload.weight.into()); + let reward_confirmation_fee = + B::bridged_weight_to_balance(B::weight_of_reward_confirmation_transaction_on_target_chain()); + + // the fee (in Bridged tokens) of all transactions that are made on This chain + let delivery_confirmation_fee = B::this_chain_balance_to_bridged_chain_balance(B::this_weight_to_balance( + B::weight_of_delivery_confirmation_transaction_on_this_chain(), + )); + + // minimal fee (in Bridged tokens) is a sum of all required fees + let minimal_fee = delivery_fee + .checked_add(&dispatch_fee) + .and_then(|fee| fee.checked_add(&reward_confirmation_fee)) + .and_then(|fee| fee.checked_add(&delivery_confirmation_fee)); + + // before returning, add extra fee that is paid to the relayer (relayer interest) + minimal_fee + .and_then(|fee| + // having message with fee that is near the `Balance::MAX_VALUE` of the chain is + // unlikely and should be treated as an error + // => let's do multiplication first + fee + .checked_mul(&relayer_fee_percent.into()) + .and_then(|interest| interest.checked_div(&100u32.into())) + .and_then(|interest| fee.checked_add(&interest))) + .ok_or("Overflow when computing minimal required message delivery and dispatch fee") + } +} + +/// Sub-module that is declaring types required for processing Bridged -> This chain messages. +pub mod target { + use super::*; + + /// Call origin for Bridged -> This chain messages. + pub type FromBridgedChainMessageCallOrigin = pallet_bridge_call_dispatch::CallOrigin< + SignerOf>, + SignerOf>, + SignatureOf>, + >; + + /// Decoded Bridged -> This message payload. + pub type FromBridgedChainDecodedMessagePayload = pallet_bridge_call_dispatch::MessagePayload< + SignerOf>, + SignerOf>, + SignatureOf>, + CallOf>, + >; + + /// Message payload for Bridged -> This messages. + pub struct FromBridgedChainMessagePayload(pub(crate) FromBridgedChainDecodedMessagePayload); + + impl Decode for FromBridgedChainMessagePayload { + fn decode(input: &mut I) -> Result { + // for bridged chain our Calls are opaque - they're encoded to Vec by submitter + // => skip encoded vec length here before decoding Call + let spec_version = pallet_bridge_call_dispatch::SpecVersion::decode(input)?; + let weight = frame_support::weights::Weight::decode(input)?; + let origin = FromBridgedChainMessageCallOrigin::::decode(input)?; + let _skipped_length = Compact::::decode(input)?; + let call = CallOf::>::decode(input)?; + + Ok(FromBridgedChainMessagePayload( + pallet_bridge_call_dispatch::MessagePayload { + spec_version, + weight, + origin, + call, + }, + )) + } + } + + /// Dispatching Bridged -> This chain messages. + #[derive(RuntimeDebug, Clone, Copy)] + pub struct FromBridgedChainMessageDispatch { + _marker: PhantomData<(B, ThisRuntime, ThisCallDispatchInstance)>, + } + + impl + MessageDispatch< as ChainWithMessageLanes>::Balance> + for FromBridgedChainMessageDispatch + where + ThisCallDispatchInstance: frame_support::traits::Instance, + ThisRuntime: pallet_bridge_call_dispatch::Trait, + pallet_bridge_call_dispatch::Module: + bp_message_dispatch::MessageDispatch< + (LaneId, MessageNonce), + Message = FromBridgedChainDecodedMessagePayload, + >, + { + type DispatchPayload = FromBridgedChainMessagePayload; + + fn dispatch_weight( + message: &DispatchMessage>>, + ) -> frame_support::weights::Weight { + message + .data + .payload + .as_ref() + .map(|payload| payload.0.weight) + .unwrap_or(0) + } + + fn dispatch(message: DispatchMessage>>) { + if let Ok(payload) = message.data.payload { + pallet_bridge_call_dispatch::Module::::dispatch( + B::INSTANCE, + (message.key.lane_id, message.key.nonce), + payload.0, + ); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Decode, Encode}; + use frame_support::weights::Weight; + + const DELIVERY_TRANSACTION_WEIGHT: Weight = 100; + const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; + const REWARD_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; + const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; + const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; + const THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE: u32 = 6; + + /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain; + struct OnThisChainBridge; + + impl MessageBridge for OnThisChainBridge { + const INSTANCE: InstanceId = *b"this"; + const RELAYER_FEE_PERCENT: u32 = 10; + + type ThisChain = ThisChain; + type BridgedChain = BridgedChain; + + fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + unreachable!() + } + + fn weight_of_delivery_transaction() -> Weight { + DELIVERY_TRANSACTION_WEIGHT + } + + fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { + DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT + } + + fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { + REWARD_CONFIRMATION_TRANSACTION_WEIGHT + } + + fn this_weight_to_balance(weight: Weight) -> ThisChainBalance { + ThisChainBalance(weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) + } + + fn bridged_weight_to_balance(weight: Weight) -> BridgedChainBalance { + BridgedChainBalance(weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) + } + + fn this_chain_balance_to_bridged_chain_balance(this_balance: ThisChainBalance) -> BridgedChainBalance { + BridgedChainBalance(this_balance.0 * THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE as u32) + } + } + + /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from ThisChain; + struct OnBridgedChainBridge; + + impl MessageBridge for OnBridgedChainBridge { + const INSTANCE: InstanceId = *b"brdg"; + const RELAYER_FEE_PERCENT: u32 = 20; + + type ThisChain = BridgedChain; + type BridgedChain = ThisChain; + + fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + unreachable!() + } + + fn weight_of_delivery_transaction() -> Weight { + unreachable!() + } + + fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { + unreachable!() + } + + fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { + unreachable!() + } + + fn this_weight_to_balance(_weight: Weight) -> BridgedChainBalance { + unreachable!() + } + + fn bridged_weight_to_balance(_weight: Weight) -> ThisChainBalance { + unreachable!() + } + + fn this_chain_balance_to_bridged_chain_balance(_this_balance: BridgedChainBalance) -> ThisChainBalance { + unreachable!() + } + } + + #[derive(Debug, PartialEq, Decode, Encode)] + struct ThisChainAccountId(u32); + #[derive(Debug, PartialEq, Decode, Encode)] + struct ThisChainSigner(u32); + #[derive(Debug, PartialEq, Decode, Encode)] + struct ThisChainSignature(u32); + #[derive(Debug, PartialEq, Decode, Encode)] + enum ThisChainCall { + #[codec(index = 42)] + Transfer, + #[codec(index = 84)] + Mint, + } + + #[derive(Debug, PartialEq, Decode, Encode)] + struct BridgedChainAccountId(u32); + #[derive(Debug, PartialEq, Decode, Encode)] + struct BridgedChainSigner(u32); + #[derive(Debug, PartialEq, Decode, Encode)] + struct BridgedChainSignature(u32); + #[derive(Debug, PartialEq, Decode, Encode)] + enum BridgedChainCall {} + + macro_rules! impl_wrapped_balance { + ($name:ident) => { + #[derive(Debug, PartialEq, Decode, Encode, Clone, Copy)] + struct $name(u32); + + impl From for $name { + fn from(balance: u32) -> Self { + Self(balance) + } + } + + impl sp_std::ops::Add for $name { + type Output = $name; + + fn add(self, other: Self) -> Self { + Self(self.0 + other.0) + } + } + + impl sp_std::ops::Div for $name { + type Output = $name; + + fn div(self, other: Self) -> Self { + Self(self.0 / other.0) + } + } + + impl sp_std::ops::Mul for $name { + type Output = $name; + + fn mul(self, other: Self) -> Self { + Self(self.0 * other.0) + } + } + + impl sp_std::cmp::PartialOrd for $name { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } + } + + impl CheckedAdd for $name { + fn checked_add(&self, other: &Self) -> Option { + self.0.checked_add(other.0).map(Self) + } + } + + impl CheckedDiv for $name { + fn checked_div(&self, other: &Self) -> Option { + self.0.checked_div(other.0).map(Self) + } + } + + impl CheckedMul for $name { + fn checked_mul(&self, other: &Self) -> Option { + self.0.checked_mul(other.0).map(Self) + } + } + }; + } + + impl_wrapped_balance!(ThisChainBalance); + impl_wrapped_balance!(BridgedChainBalance); + + struct ThisChain; + + impl ChainWithMessageLanes for ThisChain { + type AccountId = ThisChainAccountId; + type Signer = ThisChainSigner; + type Signature = ThisChainSignature; + type Call = ThisChainCall; + type Weight = frame_support::weights::Weight; + type Balance = ThisChainBalance; + } + + struct BridgedChain; + + impl ChainWithMessageLanes for BridgedChain { + type AccountId = BridgedChainAccountId; + type Signer = BridgedChainSigner; + type Signature = BridgedChainSignature; + type Call = BridgedChainCall; + type Weight = frame_support::weights::Weight; + type Balance = BridgedChainBalance; + } + + #[test] + fn message_from_bridged_chain_is_decoded() { + // the message is encoded on the bridged chain + let message_on_bridged_chain = source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: 100, + origin: pallet_bridge_call_dispatch::CallOrigin::BridgeAccount, + call: ThisChainCall::Transfer.encode(), + } + .encode(); + + // and sent to this chain where it is decoded + let message_on_this_chain = + target::FromBridgedChainMessagePayload::::decode(&mut &message_on_bridged_chain[..]) + .unwrap(); + assert_eq!( + message_on_this_chain.0, + target::FromBridgedChainDecodedMessagePayload:: { + spec_version: 1, + weight: 100, + origin: pallet_bridge_call_dispatch::CallOrigin::BridgeAccount, + call: ThisChainCall::Transfer, + } + ); + } + + #[test] + fn message_fee_is_checked_by_verifier() { + const EXPECTED_MINIMAL_FEE: u32 = 2640; + + // payload of the This -> Bridged chain message + let payload = source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: 100, + origin: pallet_bridge_call_dispatch::CallOrigin::BridgeAccount, + call: vec![42], + }; + + // let's check if estimation matching hardcoded value + assert_eq!( + source::estimate_message_dispatch_and_delivery_fee::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + ), + Ok(BridgedChainBalance(EXPECTED_MINIMAL_FEE)), + ); + + // and now check that the verifier checks the fee + assert!( + source::FromThisChainMessageVerifier::::verify_message( + &ThisChainAccountId(0), + &ThisChainBalance(1), + &*b"test", + &payload, + ) + .is_err(), + ); + assert!( + source::FromThisChainMessageVerifier::::verify_message( + &ThisChainAccountId(0), + &ThisChainBalance(1_000_000), + &*b"test", + &payload, + ) + .is_ok(), + ); + } +} diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 6adac937e5cd1..f6fda67fbae47 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -47,7 +47,7 @@ use sp_std::{marker::PhantomData, prelude::*}; pub type SpecVersion = u32; /// Origin of the call on the target chain. -#[derive(RuntimeDebug, Encode, Decode, Clone)] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] pub enum CallOrigin { /// Call is originated from bridge account, which is (designed to be) specific to /// the single deployed instance of the messages bridge (message-lane, ...) module. @@ -67,7 +67,7 @@ pub enum CallOrigin { /// Runtime specification version. We only dispatch messages that have the same /// runtime version. Otherwise we risk to misinterpret encoded calls. diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 0240d22250594..e9313a4d70d5e 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Bridge dependencies bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies @@ -28,6 +29,7 @@ sp-io = "2.0" default = ["std"] std = [ "bp-message-lane/std", + "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs new file mode 100644 index 0000000000000..3c11d263cebb4 --- /dev/null +++ b/modules/message-lane/src/instant_payments.rs @@ -0,0 +1,75 @@ +// Copyright 2019-2020 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 . + +//! Implementation of `MessageDeliveryAndDispatchPayment` trait on top of `Currency` trait. +//! All payments are instant. + +use bp_message_lane::source_chain::MessageDeliveryAndDispatchPayment; +use bp_runtime::{bridge_account_id, MESSAGE_LANE_MODULE_PREFIX, NO_INSTANCE_ID}; +use codec::Decode; +use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement}; +use sp_std::fmt::Debug; + +/// Instant message payments made in given currency. Until claimed, fee is stored in special +/// 'relayers-fund' account. +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(AccountId, Currency)>, +} + +impl MessageDeliveryAndDispatchPayment + for InstantCurrencyPayments +where + Currency: CurrencyT, + AccountId: Debug + Default + Decode, +{ + type Error = &'static str; + + fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &Currency::Balance) -> Result<(), Self::Error> { + Currency::transfer( + submitter, + &relayers_fund_account(), + *fee, + ExistenceRequirement::AllowDeath, + ) + .map_err(Into::into) + } + + fn pay_relayer_reward(_confirmation_relayer: &AccountId, relayer: &AccountId, reward: &Currency::Balance) { + let pay_result = Currency::transfer( + &relayers_fund_account(), + relayer, + *reward, + ExistenceRequirement::AllowDeath, + ); + + // we can't actually do anything here, because rewards are paid as a part of unrelated transaction + if let Err(error) = pay_result { + frame_support::debug::trace!( + target: "runtime", + "Failed to pay relayer {:?} reward {:?}: {:?}", + relayer, + reward, + error, + ); + } + } +} + +/// Return account id of shared relayers-fund account that is storing all fees +/// paid by submitters, until they're claimed by relayers. +fn relayers_fund_account() -> AccountId { + bridge_account_id(NO_INSTANCE_ID, MESSAGE_LANE_MODULE_PREFIX) +} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 0404fecd5cfa1..6e7a6add2fcce 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -48,6 +48,8 @@ use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; +pub mod instant_payments; + #[cfg(test)] mod mock; diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 844e4667c6036..8571ba9499f97 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -21,11 +21,22 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_runtime::Chain; -use frame_support::RuntimeDebug; +use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; -use sp_runtime::traits::BlakeTwo256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, MultiSigner, +}; use sp_std::prelude::*; +/// Maximal weight of single Millau block. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2_000_000_000_000; +/// Portion of block reserved for regular transactions. +pub const AVAILABLE_BLOCK_RATIO: u32 = 75; +/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular +/// transactions minus 10% for initialization). +pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); + /// Block number type used in Millau. pub type BlockNumber = u32; @@ -56,6 +67,19 @@ pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; /// Name of the `MillauHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// Balance of an account. +pub type Balance = u128; + sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index 9c9cb4bc8160b..b03806905167d 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -13,6 +13,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies + frame-support = { version = "2.0", default-features = false } sp-api = { version = "2.0", default-features = false } sp-core = { version = "2.0", default-features = false } diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index ea20d72ab022e..7e761a72031d0 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -21,11 +21,22 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_runtime::Chain; -use frame_support::RuntimeDebug; +use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; -use sp_runtime::traits::BlakeTwo256; +use sp_runtime::{ + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, MultiSigner, +}; use sp_std::prelude::*; +/// Maximal weight of single Millau block. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2_000_000_000_000; +/// Portion of block reserved for regular transactions. +pub const AVAILABLE_BLOCK_RATIO: u32 = 75; +/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular +/// transactions minus 10% for initialization). +pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); + /// Block number type used in Rialto. pub type BlockNumber = u32; @@ -49,6 +60,19 @@ impl Chain for Rialto { type Header = Header; } +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// Balance of an account. +pub type Balance = u128; + sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 6a826da3af74f..a7894554c359c 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -25,9 +25,15 @@ pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; mod chain; +/// Use this when something must be shared among all instances. +pub const NO_INSTANCE_ID: InstanceId = [0, 0, 0, 0]; + /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; +/// Message-lane module prefix. +pub const MESSAGE_LANE_MODULE_PREFIX: &[u8] = b"pallet-bridge/message-lane"; + /// Id of deployed module instance. We have a bunch of pallets that may be used in /// different bridges. E.g. message-lane pallet may be deployed twice in the same /// runtime to bridge ThisChain with Chain1 and Chain2. Sometimes we need to be able From b61511fe12f1282a2189193372309ca67b85ce9e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 26 Oct 2020 19:36:29 +0300 Subject: [PATCH 0198/1210] Subscribe to justifications in Millau->Rialto headers sync (#394) * maintain MillauHeadersToRialto sync by subscribing to Millau justifications * more tracing in maintain * Update relays/substrate/src/headers_maintain.rs Co-authored-by: Hernando Castano * Update relays/substrate/src/headers_maintain.rs Co-authored-by: Hernando Castano * -Please * -TODO * revert raise recursion limit * updated comment Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/millau.rs | 2 +- modules/substrate/src/justification.rs | 9 + modules/substrate/src/lib.rs | 2 + primitives/millau/src/lib.rs | 2 + relays/ethereum/src/ethereum_sync_loop.rs | 1 + relays/ethereum/src/substrate_sync_loop.rs | 1 + relays/headers-relay/src/headers.rs | 5 + relays/headers-relay/src/sync_loop.rs | 42 +- relays/headers-relay/src/sync_loop_tests.rs | 1 + relays/headers-relay/src/sync_types.rs | 4 +- relays/substrate-client/src/client.rs | 17 +- relays/substrate-client/src/error.rs | 2 +- relays/substrate-client/src/lib.rs | 2 +- relays/substrate/Cargo.toml | 1 + relays/substrate/src/headers_maintain.rs | 382 ++++++++++++++++++ relays/substrate/src/headers_target.rs | 2 + relays/substrate/src/main.rs | 3 +- .../substrate/src/millau_headers_to_rialto.rs | 60 ++- 19 files changed, 508 insertions(+), 33 deletions(-) create mode 100644 relays/substrate/src/headers_maintain.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dd8b0aa795286..9b5692647b42e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -292,7 +292,8 @@ impl pallet_sudo::Trait for Runtime { } parameter_types! { - pub const Period: BlockNumber = 4; + /// Authorities are changing every 5 minutes. + pub const Period: BlockNumber = 5 * MINUTES; pub const Offset: BlockNumber = 0; } diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs index 57ca750e2406d..2c0e9dfc87b01 100644 --- a/bin/rialto/runtime/src/millau.rs +++ b/bin/rialto/runtime/src/millau.rs @@ -36,7 +36,7 @@ pub fn initial_header() -> Header { Header { parent_hash: Default::default(), number: Default::default(), - state_root: hex!("e901070e3bb061a6ae9ea8e4ba5417bf4c4642f9e75af9d372861c170ba7a9a3").into(), + state_root: hex!("234a17bbd3fbaff8f0a799a6c8f0bdba1979e242fb2ed66d15945acb84947cbd").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Default::default(), } diff --git a/modules/substrate/src/justification.rs b/modules/substrate/src/justification.rs index 100049f810ef0..911ebf3f2c8c4 100644 --- a/modules/substrate/src/justification.rs +++ b/modules/substrate/src/justification.rs @@ -44,6 +44,15 @@ pub enum Error { InvalidPrecommitAncestries, } +/// Decode justification target. +pub fn decode_justification_target( + raw_justification: &[u8], +) -> Result<(Header::Hash, Header::Number), Error> { + GrandpaJustification::

::decode(&mut &raw_justification[..]) + .map(|justification| (justification.commit.target_hash, justification.commit.target_number)) + .map_err(|_| Error::JustificationDecode) +} + /// Verify that justification, that is generated by given authority set, finalizes given header. pub fn verify_justification( finalized_target: (Header::Hash, Header::Number), diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index c4406b6a3ccb1..6dfe27f2c1aba 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -41,6 +41,8 @@ use sp_std::{marker::PhantomData, prelude::*}; // Re-export since the node uses these when configuring genesis pub use storage::{AuthoritySet, ScheduledChange}; +pub use justification::decode_justification_target; + mod justification; mod storage; mod storage_proof; diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 8571ba9499f97..6276b8db3a17a 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -62,6 +62,8 @@ impl Chain for Millau { /// Name of the `MillauHeaderApi::best_block` runtime method. pub const BEST_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_best_block"; +/// Name of the `MillauHeaderApi::finalized_block` runtime method. +pub const FINALIZED_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_finalized_block"; /// Name of the `MillauHeaderApi::is_known_block` runtime method. pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; /// Name of the `MillauHeaderApi::incomplete_headers` runtime method. diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index c9045c6974dcc..c2dd0b2d1e19d 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -254,6 +254,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { consts::ETHEREUM_TICK_INTERVAL, target, consts::SUBSTRATE_TICK_INTERVAL, + (), sync_params, metrics_params, futures::future::pending(), diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 80d611a89c4fc..fcc6e2786b563 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -177,6 +177,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { consts::SUBSTRATE_TICK_INTERVAL, target, consts::ETHEREUM_TICK_INTERVAL, + (), sync_params, metrics_params, futures::future::pending(), diff --git a/relays/headers-relay/src/headers.rs b/relays/headers-relay/src/headers.rs index b8c51eec1b492..6081cb1c18d73 100644 --- a/relays/headers-relay/src/headers.rs +++ b/relays/headers-relay/src/headers.rs @@ -496,6 +496,11 @@ impl QueuedHeaders

{ } } + /// Returns true if given header requires completion data. + pub fn requires_completion_data(&self, id: &HeaderIdOf

) -> bool { + self.incomplete_headers.contains_key(id) + } + /// Returns id of the header for which we want to fetch completion data. pub fn incomplete_header(&mut self) -> Option> { queued_incomplete_header(&mut self.incomplete_headers, |last_fetch_time| { diff --git a/relays/headers-relay/src/sync_loop.rs b/relays/headers-relay/src/sync_loop.rs index c53a1ab0f082f..4a09e3518df96 100644 --- a/relays/headers-relay/src/sync_loop.rs +++ b/relays/headers-relay/src/sync_loop.rs @@ -16,7 +16,7 @@ //! Entrypoint for running headers synchronization loop. -use crate::sync::HeadersSyncParams; +use crate::sync::{HeadersSync, HeadersSyncParams}; use crate::sync_loop_metrics::SyncLoopMetrics; use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}; @@ -48,10 +48,12 @@ const STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(5 * 60); /// Delay after we have seen update of best source header at target node, /// for us to treat sync stalled. ONLY when relay operates in backup mode. const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); +/// Interval between calling sync maintain procedure. +const MAINTAIN_INTERVAL: Duration = Duration::from_secs(30); /// Source client trait. #[async_trait] -pub trait SourceClient: Sized { +pub trait SourceClient { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; @@ -78,7 +80,7 @@ pub trait SourceClient: Sized { /// Target client trait. #[async_trait] -pub trait TargetClient: Sized { +pub trait TargetClient { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; @@ -102,12 +104,24 @@ pub trait TargetClient: Sized { async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), Self::Error>; } +/// Synchronization maintain procedure. +#[async_trait] +pub trait SyncMaintain: Send + Sync { + /// Run custom maintain procedures. This is guaranteed to be called when both source and target + /// clients are unoccupied. + async fn maintain(&self, _sync: &mut HeadersSync

) {} +} + +impl SyncMaintain

for () {} + /// Run headers synchronization. +#[allow(clippy::too_many_arguments)] pub fn run>( source_client: impl SourceClient

, source_tick: Duration, target_client: TC, target_tick: Duration, + sync_maintain: impl SyncMaintain

, sync_params: HeadersSyncParams, metrics_params: Option, exit_signal: impl Future, @@ -116,7 +130,7 @@ pub fn run>( let mut progress_context = (Instant::now(), None, None); local_pool.run_until(async move { - let mut sync = crate::sync::HeadersSync::

::new(sync_params); + let mut sync = HeadersSync::

::new(sync_params); let mut stall_countdown = None; let mut last_update_time = Instant::now(); @@ -154,6 +168,9 @@ pub fn run>( let target_go_offline_future = futures::future::Fuse::terminated(); let target_tick_stream = interval(target_tick).fuse(); + let mut maintain_required = false; + let maintain_stream = interval(MAINTAIN_INTERVAL).fuse(); + let exit_signal = exit_signal.fuse(); futures::pin_mut!( @@ -172,6 +189,7 @@ pub fn run>( target_complete_header_future, target_go_offline_future, target_tick_stream, + maintain_stream, exit_signal ); @@ -373,6 +391,9 @@ pub fn run>( target_incomplete_headers_required = true; }, + _ = maintain_stream.next() => { + maintain_required = true; + }, _ = exit_signal => { return; } @@ -387,9 +408,16 @@ pub fn run>( // print progress progress_context = print_sync_progress(progress_context, &sync); + // run maintain procedures + if maintain_required && source_client_is_online && target_client_is_online { + log::debug!(target: "bridge", "Maintaining headers sync loop"); + maintain_required = false; + sync_maintain.maintain(&mut sync).await; + } + // If the target client is accepting requests we update the requests that // we want it to run - if target_client_is_online { + if !maintain_required && target_client_is_online { // NOTE: Is is important to reset this so that we only have one // request being processed by the client at a time. This prevents // race conditions like receiving two transactions with the same @@ -476,7 +504,7 @@ pub fn run>( // If the source client is accepting requests we update the requests that // we want it to run - if source_client_is_online { + if !maintain_required && source_client_is_online { // NOTE: Is is important to reset this so that we only have one // request being processed by the client at a time. This prevents // race conditions like receiving two transactions with the same @@ -561,7 +589,7 @@ pub fn run>( /// Print synchronization progress. fn print_sync_progress( progress_context: (Instant, Option, Option), - eth_sync: &crate::sync::HeadersSync

, + eth_sync: &HeadersSync

, ) -> (Instant, Option, Option) { let (prev_time, prev_best_header, prev_target_header) = progress_context; let now_time = Instant::now(); diff --git a/relays/headers-relay/src/sync_loop_tests.rs b/relays/headers-relay/src/sync_loop_tests.rs index 84b2082ce91d4..f41d9708cd61c 100644 --- a/relays/headers-relay/src/sync_loop_tests.rs +++ b/relays/headers-relay/src/sync_loop_tests.rs @@ -479,6 +479,7 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { test_tick(), target, test_tick(), + (), crate::sync::tests::default_sync_params(), None, exit_receiver.into_future().map(|(_, _)| ()), diff --git a/relays/headers-relay/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs index a910ce581c7e0..54a41a8aaa571 100644 --- a/relays/headers-relay/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -76,7 +76,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { /// 4) header and extra data are submitted in single transaction. /// /// Example: Ethereum transactions receipts. - type Extra: Clone + PartialEq + std::fmt::Debug; + type Extra: Clone + Send + Sync + PartialEq + std::fmt::Debug; /// Type of data required to 'complete' header that we're receiving from the source node: /// 1) completion data is required for some headers; /// 2) target node can't answer if it'll require completion data before header is accepted; @@ -84,7 +84,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { /// 4) header and completion data are submitted in separate transactions. /// /// Example: Substrate GRANDPA justifications. - type Completion: Clone + std::fmt::Debug; + type Completion: Clone + Send + Sync + std::fmt::Debug; /// Function used to estimate size of target-encoded header. fn estimate_size(source: &QueuedHeader) -> usize; diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 896b01477590c..64994505ab073 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -23,12 +23,15 @@ use crate::{ConnectionParams, Result}; use jsonrpsee::common::DeserializeOwned; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::ws::WsTransportClient; -use jsonrpsee::Client as RpcClient; +use jsonrpsee::{client::Subscription, Client as RpcClient}; use num_traits::Zero; use sp_core::Bytes; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; +/// Opaque justifications subscription type. +pub type JustificationsSubscription = Subscription; + /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; @@ -135,4 +138,16 @@ where .await .map_err(Into::into) } + + /// Return new justifications stream. + pub async fn subscribe_justifications(self) -> Result { + Ok(self + .client + .subscribe( + "grandpa_subscribeJustifications", + jsonrpsee::common::Params::None, + "grandpa_unsubscribeJustifications", + ) + .await?) + } } diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index 9dff9e02d2f64..319027440b180 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -29,7 +29,7 @@ pub type Result = std::result::Result; pub enum Error { /// Web socket connection error. WsConnectionError(WsNewDnsError), - /// An error that can occur when making an HTTP request to + /// An error that can occur when making a request to /// an JSON-RPC server. Request(RequestError), /// The response from the server could not be SCALE decoded. diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index 9bc1cf164245a..adee027d51e51 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -26,7 +26,7 @@ mod rpc; pub mod headers_source; pub use crate::chain::{BlockWithJustification, Chain, TransactionSignScheme}; -pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet}; +pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index d58b9d6f37e98..a3f6ca6e435c4 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -20,6 +20,7 @@ bp-millau = { path = "../../primitives/millau" } bp-rialto = { path = "../../primitives/rialto" } headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } +pallet-substrate-bridge = { path = "../../modules/substrate" } relay-millau-client = { path = "../millau-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs new file mode 100644 index 0000000000000..e5e7c7023cda1 --- /dev/null +++ b/relays/substrate/src/headers_maintain.rs @@ -0,0 +1,382 @@ +// Copyright 2019-2020 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 . + +//! Substrate-to-Substrate headers synchronization maintain procedure. +//! +//! Regular headers synchronization only depends on persistent justifications +//! that are generated when authorities set changes. This happens rarely on +//! real-word chains. So some other way to finalize headers is required. +//! +//! Full nodes are listening to GRANDPA messages, so they may have track authorities +//! votes on their own. They're returning both persistent and ephemeral justifications +//! (justifications that are not stored in the database and not broadcasted over network) +//! throught `grandpa_subscribeJustifications` RPC subscription. +//! +//! The idea of this maintain procedure is that when we see justification that 'improves' +//! best finalized header on the target chain, we submit this justification to the target +//! node. + +use crate::headers_target::SubstrateHeadersSyncPipeline; + +use async_std::sync::{Arc, Mutex}; +use async_trait::async_trait; +use codec::{Decode, Encode}; +use futures::future::{poll_fn, FutureExt, TryFutureExt}; +use headers_relay::{ + sync::HeadersSync, + sync_loop::SyncMaintain, + sync_types::{HeaderIdOf, HeaderStatus}, +}; +use relay_substrate_client::{Chain, Client, Error as SubstrateError, JustificationsSubscription}; +use relay_utils::HeaderId; +use sp_core::Bytes; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, Justification}; +use std::{collections::VecDeque, task::Poll}; + +/// Substrate-to-Substrate headers synchronization maintain procedure. +pub struct SubstrateHeadersToSubstrateMaintain { + pipeline: P, + target_client: Client, + justifications: Arc>>, +} + +/// Future and already received justifications from the source chain. +struct Justifications { + /// Justifications stream. + stream: JustificationsSubscription, + /// Justifications that we have read from the stream but have not sent to the + /// target node, because their targets were still not synced. + queue: VecDeque<(HeaderIdOf

, Justification)>, +} + +impl SubstrateHeadersToSubstrateMaintain { + /// Create new maintain procedure. + pub fn new(pipeline: P, target_client: Client, justifications: JustificationsSubscription) -> Self { + SubstrateHeadersToSubstrateMaintain { + pipeline, + target_client, + justifications: Arc::new(Mutex::new(Justifications { + stream: justifications, + queue: VecDeque::new(), + })), + } + } +} + +#[async_trait] +impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain +where + C: Chain, + C::Header: DeserializeOwned, + C::Index: DeserializeOwned, + P::Number: Decode + From, + P::Hash: Decode + From, + P: SubstrateHeadersSyncPipeline, +{ + async fn maintain(&self, sync: &mut HeadersSync

) { + // lock justifications before doing anything else + let mut justifications = match self.justifications.try_lock() { + Some(justifications) => justifications, + None => { + // this should never happen, as we use single-thread executor + log::warn!(target: "bridge", "Failed to acquire {} justifications lock", P::SOURCE_NAME); + return; + } + }; + + // we need to read best finalized header from the target node to be able to + // choose justification to submit + let best_finalized = match best_finalized_header_id::(&self.target_client).await { + Ok(best_finalized) => best_finalized, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to read best finalized {} block from maintain: {:?}", + P::SOURCE_NAME, + error, + ); + return; + } + }; + + log::debug!( + target: "bridge", + "Read best finalized {} block from {}: {:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + best_finalized, + ); + + // Select justification to submit to the target node. We're submitting at most one justification + // on every maintain call. So maintain rate directly affects finalization rate. + let justification_to_submit = poll_fn(|context| { + // read justifications from the stream and push to the queue + justifications.read_from_stream::(context); + + // remove all obsolete justifications from the queue + remove_obsolete::

(&mut justifications.queue, best_finalized); + + // select justification to submit + Poll::Ready(select_justification(&mut justifications.queue, sync)) + }) + .await; + + // finally - submit selected justification + if let Some((target, justification)) = justification_to_submit { + let submit_result = self + .pipeline + .make_complete_header_transaction(target, justification) + .and_then(|tx| self.target_client.submit_extrinsic(Bytes(tx.encode()))) + .await; + + match submit_result { + Ok(_) => log::debug!( + target: "bridge", + "Submitted justification received over {} subscription. Target: {:?}", + P::SOURCE_NAME, + target, + ), + Err(error) => log::warn!( + target: "bridge", + "Failed to submit justification received over {} subscription for {:?}: {:?}", + P::SOURCE_NAME, + target, + error, + ), + } + } + } +} + +impl

Justifications

+where + P::Number: Decode, + P::Hash: Decode, + P: SubstrateHeadersSyncPipeline, +{ + /// Read justifications from the subscription stream without blocking. + fn read_from_stream<'a, Header>(&mut self, context: &mut std::task::Context<'a>) + where + Header: HeaderT, + Header::Number: Into, + Header::Hash: Into, + { + loop { + let maybe_next_justification = self.stream.next(); + futures::pin_mut!(maybe_next_justification); + + let maybe_next_justification = maybe_next_justification.poll_unpin(context); + let justification = match maybe_next_justification { + Poll::Ready(justification) => justification, + Poll::Pending => return, + }; + + // decode justification target + let target = pallet_substrate_bridge::decode_justification_target::

(&justification); + let target = match target { + Ok((target_hash, target_number)) => HeaderId(target_number.into(), target_hash.into()), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to decode justification from {} subscription: {:?}", + P::SOURCE_NAME, + error, + ); + continue; + } + }; + + log::debug!( + target: "bridge", + "Received {} justification over subscription. Target: {:?}", + P::SOURCE_NAME, + target, + ); + + self.queue.push_back((target, justification.0)); + } + } +} + +/// Clean queue of all justifications that are justifying already finalized blocks. +fn remove_obsolete( + queue: &mut VecDeque<(HeaderIdOf

, Justification)>, + best_finalized: HeaderIdOf

, +) { + while queue + .front() + .map(|(target, _)| target.0 <= best_finalized.0) + .unwrap_or(false) + { + queue.pop_front(); + } +} + +/// Select appropriate justification that would improve best finalized block on target node. +/// +/// It is assumed that the selected justification will be submitted to the target node. The +/// justification itself and all preceeding justifications are removed from the queue. +fn select_justification

( + queue: &mut VecDeque<(HeaderIdOf

, Justification)>, + sync: &mut HeadersSync

, +) -> Option<(HeaderIdOf

, Justification)> +where + P: SubstrateHeadersSyncPipeline, +{ + let mut selected_justification = None; + while let Some((target, justification)) = queue.pop_front() { + // if we're waiting for this justification, report it + if sync.headers().requires_completion_data(&target) { + sync.headers_mut().completion_response(&target, Some(justification)); + // we won't submit previous justifications as we going to submit justification for + // next header + selected_justification = None; + // we won't submit next justifications as we need to submit previous justifications + // first + break; + } + + // if we know that the header is already synced (it is known to the target node), let's + // select it for submission. We still may select better justification on the next iteration. + if sync.headers().status(&target) == HeaderStatus::Synced { + selected_justification = Some((target, justification)); + continue; + } + + // finally - return justification back to the queue + queue.push_back((target, justification)); + break; + } + + selected_justification +} + +/// Returns best finalized source header on the target chain. +async fn best_finalized_header_id(client: &Client) -> Result, SubstrateError> +where + P: SubstrateHeadersSyncPipeline, + P::Number: Decode + From, + P::Hash: Decode + From, + C: Chain, + C::Header: DeserializeOwned, + C::Index: DeserializeOwned, +{ + let call = P::FINALIZED_BLOCK_METHOD.into(); + let data = Bytes(Vec::new()); + + let encoded_response = client.state_call(call, data, None).await?; + let decoded_response: (C::BlockNumber, C::Hash) = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + + let best_header_id = HeaderId(decoded_response.0.into(), decoded_response.1.into()); + Ok(best_header_id) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::millau_headers_to_rialto::{sync_params, MillauHeadersToRialto}; + + fn parent_hash(index: u8) -> bp_millau::Hash { + if index == 1 { + Default::default() + } else { + header(index - 1).hash() + } + } + + fn header_hash(index: u8) -> bp_millau::Hash { + header(index).hash() + } + + fn header(index: u8) -> bp_millau::Header { + bp_millau::Header::new( + index as _, + Default::default(), + Default::default(), + parent_hash(index), + Default::default(), + ) + } + + #[test] + fn obsolete_justifications_are_removed() { + let mut queue = vec![ + (HeaderId(1, header_hash(1)), vec![1]), + (HeaderId(2, header_hash(2)), vec![2]), + (HeaderId(3, header_hash(3)), vec![3]), + ] + .into_iter() + .collect(); + + remove_obsolete::(&mut queue, HeaderId(2, header_hash(2))); + + assert_eq!( + queue, + vec![(HeaderId(3, header_hash(3)), vec![3])] + .into_iter() + .collect::>(), + ); + } + + #[test] + fn latest_justification_is_selected() { + let mut queue = vec![ + (HeaderId(1, header_hash(1)), vec![1]), + (HeaderId(2, header_hash(2)), vec![2]), + (HeaderId(3, header_hash(3)), vec![3]), + ] + .into_iter() + .collect(); + let mut sync = HeadersSync::::new(sync_params()); + sync.headers_mut().header_response(header(1).into()); + sync.headers_mut().header_response(header(2).into()); + sync.headers_mut().header_response(header(3).into()); + sync.target_best_header_response(HeaderId(2, header_hash(2))); + + assert_eq!( + select_justification(&mut queue, &mut sync), + Some((HeaderId(2, header_hash(2)), vec![2])), + ); + } + + #[test] + fn required_justification_is_reported() { + let mut queue = vec![ + (HeaderId(1, header_hash(1)), vec![1]), + (HeaderId(2, header_hash(2)), vec![2]), + (HeaderId(3, header_hash(3)), vec![3]), + ] + .into_iter() + .collect(); + let mut sync = HeadersSync::::new(sync_params()); + sync.headers_mut().header_response(header(1).into()); + sync.headers_mut().header_response(header(2).into()); + sync.headers_mut().header_response(header(3).into()); + sync.headers_mut() + .incomplete_headers_response(vec![HeaderId(2, header_hash(2))].into_iter().collect()); + sync.target_best_header_response(HeaderId(2, header_hash(2))); + + assert_eq!(sync.headers_mut().header_to_complete(), None,); + + assert_eq!(select_justification(&mut queue, &mut sync), None,); + + assert_eq!( + sync.headers_mut().header_to_complete(), + Some((HeaderId(2, header_hash(2)), &vec![2])), + ); + } +} diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index 92bc017a72eb2..546fb805eb632 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -36,6 +36,8 @@ use std::collections::HashSet; pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { /// Name of the `best_block` runtime method. const BEST_BLOCK_METHOD: &'static str; + /// Name of the `finalized_block` runtime method. + const FINALIZED_BLOCK_METHOD: &'static str; /// Name of the `is_known_block` runtime method. const IS_KNOWN_BLOCK_METHOD: &'static str; /// Name of the `incomplete_headers` runtime method. diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index ad77a13eea9bf..53f10dab86d6b 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -28,6 +28,7 @@ pub type MillauClient = relay_substrate_client::Client; mod cli; +mod headers_maintain; mod headers_target; mod millau_headers_to_rialto; @@ -63,7 +64,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { rialto_sign.rialto_signer_password.as_deref(), ) .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()); + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; } } diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 67ac6d6b94e7a..9f63614cde374 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -17,12 +17,16 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::{ + headers_maintain::SubstrateHeadersToSubstrateMaintain, headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, MillauClient, RialtoClient, }; use async_trait::async_trait; -use bp_millau::{BEST_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, IS_KNOWN_MILLAU_BLOCK_METHOD}; +use bp_millau::{ + BEST_MILLAU_BLOCK_METHOD, FINALIZED_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, + IS_KNOWN_MILLAU_BLOCK_METHOD, +}; use codec::Encode; use headers_relay::{ sync::{HeadersSyncParams, TargetTransactionMode}, @@ -39,7 +43,7 @@ use std::time::Duration; /// Millau-to-Rialto headers pipeline. #[derive(Debug, Clone)] -struct MillauHeadersToRialto { +pub struct MillauHeadersToRialto { client: RialtoClient, sign: RialtoSigningParams, } @@ -62,6 +66,7 @@ impl HeadersSyncPipeline for MillauHeadersToRialto { #[async_trait] impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { const BEST_BLOCK_METHOD: &'static str = BEST_MILLAU_BLOCK_METHOD; + const FINALIZED_BLOCK_METHOD: &'static str = FINALIZED_MILLAU_BLOCK_METHOD; const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_MILLAU_BLOCK_METHOD; const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_MILLAU_HEADERS_METHOD; @@ -100,8 +105,20 @@ type MillauSourceClient = HeadersSource; /// Rialto node as headers target. type RialtoTargetClient = SubstrateHeadersTarget; +/// Return sync parameters for Millau-to-Rialto headers sync. +pub fn sync_params() -> HeadersSyncParams { + HeadersSyncParams { + max_future_headers_to_download: 32, + max_headers_in_submitted_status: 8, + max_headers_in_single_submit: 1, + max_headers_size_in_single_submit: 1024 * 1024, + prune_depth: 256, + target_tx_mode: TargetTransactionMode::Signed, + } +} + /// Run Millau-to-Rialto headers sync. -pub fn run( +pub async fn run( millau_client: MillauClient, rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, @@ -109,27 +126,34 @@ pub fn run( ) { let millau_tick = Duration::from_secs(5); let rialto_tick = Duration::from_secs(5); - let sync_params = HeadersSyncParams { - max_future_headers_to_download: 32, - max_headers_in_submitted_status: 8, - max_headers_in_single_submit: 1, - max_headers_size_in_single_submit: 1024 * 1024, - prune_depth: 256, - target_tx_mode: TargetTransactionMode::Signed, + + let millau_justifications = match millau_client.clone().subscribe_justifications().await { + Ok(millau_justifications) => millau_justifications, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to subscribe to Millau justifications: {:?}", + error, + ); + + return; + } + }; + + let pipeline = MillauHeadersToRialto { + client: rialto_client.clone(), + sign: rialto_sign, }; + let sync_maintain = + SubstrateHeadersToSubstrateMaintain::new(pipeline.clone(), rialto_client.clone(), millau_justifications); headers_relay::sync_loop::run( MillauSourceClient::new(millau_client), millau_tick, - RialtoTargetClient::new( - rialto_client.clone(), - MillauHeadersToRialto { - client: rialto_client, - sign: rialto_sign, - }, - ), + RialtoTargetClient::new(rialto_client, pipeline), rialto_tick, - sync_params, + sync_maintain, + sync_params(), metrics_params, futures::future::pending(), ); From 8343bcbef0c4242f97a78a25f4d265fd76de7ba2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 27 Oct 2020 13:31:22 +0300 Subject: [PATCH 0199/1210] Actually use pinned nightly version when building runtimes (#465) * try to fix build * use pinned nightly for in stable --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 59a28d19413fe..0689bc4fbae44 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -53,7 +53,7 @@ sp-trie = { version = "2.0", default-features = false } sp-version = { version = "2.0", default-features = false } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.5" } +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2.0.0" } [features] default = ["std"] diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 67e8ab8eee556..0b68971c8a379 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -65,7 +65,7 @@ sp-version = { version = "2.0", default-features = false } libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.5" } +wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2.0.0" } [features] default = ["std"] From 57a6fb96ab43202f10b08d1837e484e8db7ecee8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 27 Oct 2020 15:49:41 +0300 Subject: [PATCH 0200/1210] Integrate message-lane module RPCs into Rialto/Millau nodes (#458) * integrate message-lane RPCs into Millau and Rialto runtime * fmt * use instance in InboundLanes * moved RialtoMessageLaneKeys/MillauMessageLaneKeys inside rpc_extensions_builder to ease Substrate refs update --- bin/millau/node/Cargo.toml | 4 +++ bin/millau/node/src/service.rs | 37 ++++++++++++++++++++++ bin/millau/runtime/src/rialto_messages.rs | 26 ++++++++++++++-- bin/rialto/node/Cargo.toml | 2 ++ bin/rialto/node/src/service.rs | 38 ++++++++++++++++++++++- bin/rialto/runtime/src/millau_messages.rs | 26 ++++++++++++++-- modules/message-lane/src/lib.rs | 6 ++-- primitives/runtime/src/lib.rs | 6 ++++ 8 files changed, 135 insertions(+), 10 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3485c8d487c5b..7af2f6febda85 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -14,8 +14,12 @@ jsonrpc-core = "15.1.0" structopt = "0.3.20" # Bridge dependencies + +bp-message-lane = { path = "../../../primitives/message-lane" } bp-rialto = { path = "../../../primitives/rialto" } +bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } +pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } # Substrate Dependencies diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index fe1686fdda965..3e3917d7bd8dd 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -28,6 +28,8 @@ // ===================================================================================== // ===================================================================================== +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; @@ -36,6 +38,7 @@ use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, use sc_finality_grandpa_rpc::GrandpaRpcHandler; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_core::storage::StorageKey; use sp_inherents::InherentDataProviders; use std::sync::Arc; use std::time::Duration; @@ -161,10 +164,40 @@ pub fn new_full(config: Configuration) -> Result { let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { + // This struct is here to ease update process. + + /// Millau runtime from message-lane RPC point of view. + struct MillauMessageLaneKeys; + + impl pallet_message_lane_rpc::Runtime for MillauMessageLaneKeys { + fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option { + match *instance { + RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::message_key(lane, nonce)), + _ => None, + } + } + + fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { + match *instance { + RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::outbound_lane_data_key(lane)), + _ => None, + } + } + + fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { + match *instance { + RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::inbound_lane_data_key(lane)), + _ => None, + } + } + } + + use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; use sc_finality_grandpa_rpc::GrandpaApi; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; + let backend = backend.clone(); let client = client.clone(); let pool = transaction_pool.clone(); @@ -188,6 +221,10 @@ pub fn new_full(config: Configuration) -> Result { subscription_executor, finality_proof_provider.clone(), ))); + io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + backend.clone(), + Arc::new(MillauMessageLaneKeys), + ))); io }) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index e2a41e88f9cdc..a947d796cd778 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,21 +16,41 @@ //! Everything required to serve Millau <-> Rialto message lanes. -use bridge_runtime_common::messages; +use crate::Runtime; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, + InboundLaneData, LaneId, Message, MessageKey, MessageNonce, }; use bp_runtime::InstanceId; -use bridge_runtime_common::messages::MessageBridge; +use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{ + storage::generator::StorageMap, weights::{Weight, WeightToFeePolynomial}, RuntimeDebug, }; +use pallet_message_lane::{DefaultInstance, InboundLanes, OutboundLanes, OutboundMessages}; +use sp_core::storage::StorageKey; use sp_trie::StorageProof; +/// Storage key of the Millau -> Rialto message in the runtime storage. +pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { + let message_key = MessageKey { lane_id: *lane, nonce }; + let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); + StorageKey(raw_storage_key) +} + +/// Storage key of the Millau -> Rialto message lane state in the runtime storage. +pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { + StorageKey(OutboundLanes::::storage_map_final_key(*lane)) +} + +/// Storage key of the Rialto -> Millau message lane state in the runtime storage. +pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { + StorageKey(InboundLanes::::storage_map_final_key(*lane)) +} + /// Message payload for Millau -> Rialto messages. pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload; diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index be700d9353fc8..a0394f34af06b 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -15,6 +15,8 @@ structopt = "0.3.20" # Bridge dependencies +bp-message-lane = { path = "../../../primitives/message-lane" } +bp-runtime = { path = "../../../primitives/runtime" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } rialto-runtime = { path = "../runtime" } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 4b89ae4782560..21b2bf0bce7d5 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -28,6 +28,8 @@ // ===================================================================================== // ===================================================================================== +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; @@ -35,6 +37,7 @@ pub use sc_executor::NativeExecutor; use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; +use sp_core::storage::StorageKey; use sp_inherents::InherentDataProviders; use std::sync::Arc; use std::time::Duration; @@ -160,9 +163,38 @@ pub fn new_full(config: Configuration) -> Result { let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { + // This struct is here to ease update process. + + /// Rialto runtime from message-lane RPC point of view. + struct RialtoMessageLaneKeys; + + impl pallet_message_lane_rpc::Runtime for RialtoMessageLaneKeys { + fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option { + match *instance { + MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::message_key(lane, nonce)), + _ => None, + } + } + + fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { + match *instance { + MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::outbound_lane_data_key(lane)), + _ => None, + } + } + + fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { + match *instance { + MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::inbound_lane_data_key(lane)), + _ => None, + } + } + } + + use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; - + let backend = backend.clone(); let client = client.clone(); let pool = transaction_pool.clone(); @@ -173,6 +205,10 @@ pub fn new_full(config: Configuration) -> Result { pool.clone(), DenyUnsafe::No, ))); + io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + backend.clone(), + Arc::new(RialtoMessageLaneKeys), + ))); io }) diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 920c3b39eb486..6d38398eab6a4 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,21 +16,41 @@ //! Everything required to serve Millau <-> Rialto message lanes. -use bridge_runtime_common::messages; +use crate::Runtime; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, + InboundLaneData, LaneId, Message, MessageKey, MessageNonce, }; use bp_runtime::InstanceId; -use bridge_runtime_common::messages::MessageBridge; +use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{ + storage::generator::StorageMap, weights::{Weight, WeightToFeePolynomial}, RuntimeDebug, }; +use pallet_message_lane::{DefaultInstance, InboundLanes, OutboundLanes, OutboundMessages}; +use sp_core::storage::StorageKey; use sp_trie::StorageProof; +/// Storage key of the Rialto -> Millau message in the runtime storage. +pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { + let message_key = MessageKey { lane_id: *lane, nonce }; + let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); + StorageKey(raw_storage_key) +} + +/// Storage key of the Rialto -> Millau message lane state in the runtime storage. +pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { + StorageKey(OutboundLanes::::storage_map_final_key(*lane)) +} + +/// Storage key of the Millau -> Rialto message lane state in the runtime storage. +pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { + StorageKey(InboundLanes::::storage_map_final_key(*lane)) +} + /// Message payload for Rialto -> Millau messages. pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 6e7a6add2fcce..696340c6ff50b 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -138,11 +138,11 @@ decl_error! { decl_storage! { trait Store for Module, I: Instance = DefaultInstance> as MessageLane { /// Map of lane id => inbound lane data. - InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; + pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; /// Map of lane id => outbound lane data. - OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; + pub OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; /// All queued outbound messages. - OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; + pub OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a7894554c359c..df0975f9815ef 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -28,6 +28,12 @@ mod chain; /// 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"; + /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; From 8b262897406ca9dc54ff2c9322e8a6f14cb9d767 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 27 Oct 2020 15:31:10 -0400 Subject: [PATCH 0201/1210] Support Tracking Forks in Substrate Pallet (#409) * Support multiple "best headers" from different forks * Update the name of a test * Add note about multiple scheduled changes * Disallow multiple scheduled authority set changes * Return multiple best headers from Runtime APIs * Remove invalid test write-up * Add some sketch-ups of test scenarios * Clean up test scenarios * Add module for testing forks * Write headers to storage * Add way to check expected outcome for header imports * Add support for importing finality proofs * Support importing headers which schedule changes * Write out test scenario using new framework * Map authority set changes across forks Gets all the tests in the `forks` module passing * Remove basic tests These were used when working on the initial test helper * Prevent multiple pending set changes on the same fork * Remove old test which allowed imports past unfinalized header * Ignore failing test (for now) * Rewrite `if` comparison using `match` and `cmp` Fixes Clippy warning: `comparison_chain` * Add helper for writing test headers with default characteristics * Fix test that checked authority set updates * Make note about importing headers on different unfinalized fork * Perform some cleanup on the fork module * Fix Clippy complaints * Provide list of unfinalized headers to Runtime APIs * Add proofs to expect() calls * Make tests the focus of the forks module * Allow specific errors to be checked in fork tests * Remove unused method * Replace unreachable() statement with expect() * Rename storage `unfinalized_headers() `to make its purpose more clear * Update Runtime API name in relayer to match pallet * Commit `unfinalized_headers` changes I forgot to add * Rename ChainTipHeight to BestHeight * Make schedule_next_set_change require a mutable reference * Remove check for key when enacting authority set We only expect to take the happy-path in the pallet anyways, so this check to save ourselves the time spent decoding the entry isn't really used. * Clear justification set when writing headers to storage * Clarify why we only allow one set change per fork * Change best_headers() to return HeaderIDs Prevents us from returning full headers (which are more expensive to get from storage) since we only care about header IDs (number, hash) anyways. * Fix Clippy complaint * Make note about equivocations * Use HeaderIds when returning incomplete headers This change stops returning full headers which are more expensive to get from storage than header Ids (number, hash) are. Clients likely don't need the full header anyways which is why this change is fine. * Introduce HeaderId type to reduce type complexity * Add signal hash to storage during genesis config * Return error instead of expect()-ing * Fix Clippy lint about `ok_or` fn call * Rename `forks` module to indicate that it's for testing * Use `const` for `expect()` proofs * Remove check that key exists before `kill`-ing value Co-authored-by: Svyatoslav Nikolsky --- bin/millau/runtime/src/lib.rs | 13 +- bin/rialto/runtime/src/lib.rs | 13 +- modules/substrate/src/fork_tests.rs | 511 ++++++++++++++++++ modules/substrate/src/lib.rs | 223 +++++--- modules/substrate/src/storage.rs | 8 +- modules/substrate/src/verifier.rs | 301 ++++++----- primitives/millau/src/lib.rs | 8 +- primitives/rialto/src/lib.rs | 6 +- primitives/runtime/src/chain.rs | 3 +- relays/substrate/src/headers_target.rs | 9 +- .../substrate/src/millau_headers_to_rialto.rs | 4 +- 11 files changed, 854 insertions(+), 245 deletions(-) create mode 100644 modules/substrate/src/fork_tests.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 9b5692647b42e..7f78bc58213dd 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -516,9 +516,8 @@ impl_runtime_apis! { } impl bp_rialto::RialtoHeaderApi for Runtime { - fn best_block() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { - let header = BridgeRialto::best_header(); - (header.number, header.hash()) + fn best_blocks() -> Vec<(bp_rialto::BlockNumber, bp_rialto::Hash)> { + BridgeRialto::best_headers() } fn finalized_block() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { @@ -527,13 +526,7 @@ impl_runtime_apis! { } fn incomplete_headers() -> Vec<(bp_rialto::BlockNumber, bp_rialto::Hash)> { - // Since the pallet doesn't accept multiple scheduled changes right now - // we can only have one header requiring a justification at any time. - if let Some(header) = BridgeRialto::requires_justification() { - vec![(header.number, header.hash())] - } else { - vec![] - } + BridgeRialto::require_justifications() } fn is_known_block(hash: bp_rialto::Hash) -> bool { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index c4815ea9bc7b5..008e473731698 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -599,9 +599,8 @@ impl_runtime_apis! { } impl bp_millau::MillauHeaderApi for Runtime { - fn best_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { - let header = BridgeMillau::best_header(); - (header.number, header.hash()) + fn best_blocks() -> Vec<(bp_millau::BlockNumber, bp_millau::Hash)> { + BridgeMillau::best_headers() } fn finalized_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { @@ -610,13 +609,7 @@ impl_runtime_apis! { } fn incomplete_headers() -> Vec<(bp_millau::BlockNumber, bp_millau::Hash)> { - // Since the pallet doesn't accept multiple scheduled changes right now - // we can only have one header requiring a justification at any time. - if let Some(header) = BridgeMillau::requires_justification() { - vec![(header.number, header.hash())] - } else { - vec![] - } + BridgeMillau::require_justifications() } fn is_known_block(hash: bp_millau::Hash) -> bool { diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs new file mode 100644 index 0000000000000..cd146cd1ec8d8 --- /dev/null +++ b/modules/substrate/src/fork_tests.rs @@ -0,0 +1,511 @@ +// Copyright 2020 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 . + +//! Tests for checking that behaviour of importing headers and finality proofs works correctly. +//! +//! The tests are built around the idea that we will be importing headers on different forks and we +//! should be able to check that we're correctly importing headers, scheduling changes, and +//! finalizing headers across different forks. +//! +//! Each test is depicted using beautiful ASCII art. The symbols used in the tests are the +//! following: +//! +//! - S|N: Schedules change in N blocks +//! - E: Enacts change +//! - F: Finalized +//! - FN: Finality proof imported for header N +//! +//! Each diagram also comes with an import order. This is important since we expect things to fail +//! when headers or proofs are imported in a certain order. +//! +//! Tests can be read as follows: +//! +//! ## Example Import 1 +//! +//! (Type::Header(2, 1, None, None), Ok(())) +//! +//! Import header 2 on fork 1. This does not create a fork, or schedule an authority set change. We +//! expect this header import to be succesful. +//! +//! ## Example Import 2 +//! +//! (Type::Header(4, 2, Some((3, 1)), Some(0)), Ok(())) +//! +//! Import header 4 on fork 2. This header starts a new fork from header 3 on fork 1. It also +//! schedules a change with a delay of 0 blocks. It should be succesfully imported. +//! +//! ## Example Import 3 +//! +//! (Type::Finality(2, 1), Err(FinalizationError::OldHeader.into())) +//! +//! Import a finality proof for header 2 on fork 1. This finalty proof should fail to be imported +//! because the header is an old header. + +use crate::justification::tests::*; +use crate::mock::{helpers::*, *}; +use crate::storage::{AuthoritySet, ImportedHeader}; +use crate::verifier::*; +use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; +use codec::Encode; +use frame_support::{IterableStorageMap, StorageValue}; +use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; +use sp_runtime::{Digest, DigestItem}; +use std::collections::BTreeMap; + +type ForkId = u64; +type Delay = u64; + +// Indicates when to start a new fork. The first item in the tuple +// will be the parent header of the header starting this fork. +type ForksAt = Option<(TestNumber, ForkId)>; +type ScheduledChangeAt = Option; + +#[derive(Debug)] +enum Type { + Header(TestNumber, ForkId, ForksAt, ScheduledChangeAt), + Finality(TestNumber, ForkId), +} + +// Order: 1, 2, 2', 3, 3'' +// +// / [3''] +// / [2'] +// [1] <- [2] <- [3] +#[test] +fn fork_can_import_headers_on_different_forks() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, None), Ok(())), + (Type::Header(2, 2, Some((1, 1)), None), Ok(())), + (Type::Header(3, 1, None, None), Ok(())), + (Type::Header(3, 3, Some((2, 2)), None), Ok(())), + ]; + + create_chain(&mut storage, &mut chain); + + let best_headers = storage.best_headers(); + assert_eq!(best_headers.len(), 2); + assert_eq!(>::get(), 3); + }) +} + +// Order: 1, 2, 2', F2, F2' +// +// [1] <- [2: F] +// \ [2'] +// +// Not allowed to finalize 2' +#[test] +fn fork_does_not_allow_competing_finality_proofs() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, None), Ok(())), + (Type::Header(2, 2, Some((1, 1)), None), Ok(())), + (Type::Finality(2, 1), Ok(())), + (Type::Finality(2, 2), Err(FinalizationError::OldHeader.into())), + ]; + + create_chain(&mut storage, &mut chain); + }) +} + +// Order: 1, 2, 3, F2, 3 +// +// [1] <- [2: S|0] <- [3] +// +// Not allowed to import 3 until we get F2 +// +// Note: Grandpa would technically allow 3 to be imported as long as it didn't try and enact an +// authority set change. However, since we expect finality proofs to be imported quickly we've +// decided to simplify our import process and disallow header imports until we get a finality proof. +#[test] +fn fork_waits_for_finality_proof_before_importing_header_past_one_which_enacts_a_change() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(0)), Ok(())), + ( + Type::Header(3, 1, None, None), + Err(ImportError::AwaitingFinalityProof.into()), + ), + (Type::Finality(2, 1), Ok(())), + (Type::Header(3, 1, None, None), Ok(())), + ]; + + create_chain(&mut storage, &mut chain); + }) +} + +// Order: 1, 2, F2, 3 +// +// [1] <- [2: S|1] <- [3: S|0] +// +// Grandpa can have multiple authority set changes pending on the same fork. However, we've decided +// to introduce a limit of _one_ pending authority set change per fork in order to simplify pallet +// logic and to prevent DoS attacks if Grandpa finality were to temporarily stall for a long time +// (we'd have to perform a lot of expensive ancestry checks to catch back up). +#[test] +fn fork_does_not_allow_multiple_scheduled_changes_on_the_same_fork() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(1)), Ok(())), + ( + Type::Header(3, 1, None, Some(0)), + Err(ImportError::PendingAuthoritySetChange.into()), + ), + (Type::Finality(2, 1), Ok(())), + (Type::Header(3, 1, None, Some(0)), Ok(())), + ]; + + create_chain(&mut storage, &mut chain); + }) +} + +// Order: 1, 2, 2' +// +// / [2': S|0] +// [1] <- [2: S|0] +// +// Both 2 and 2' should be marked as needing justifications since they enact changes. +#[test] +fn fork_correctly_tracks_which_headers_require_finality_proofs() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(0)), Ok(())), + (Type::Header(2, 2, Some((1, 1)), Some(0)), Ok(())), + ]; + + create_chain(&mut storage, &mut chain); + + let header_ids = storage.missing_justifications(); + assert_eq!(header_ids.len(), 2); + assert!(header_ids[0].hash != header_ids[1].hash); + assert_eq!(header_ids[0].number, 2); + assert_eq!(header_ids[1].number, 2); + }) +} + +// Order: 1, 2, 2', 3', F2, 3, 4' +// +// / [2': S|1] <- [3'] <- [4'] +// [1] <- [2: S|0] <- [3] +// +// +// Not allowed to import 3 or 4' +// Can only import 3 after we get the finality proof for 2 +#[test] +fn fork_does_not_allow_importing_past_header_that_enacts_changes_on_forks() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(0)), Ok(())), + (Type::Header(2, 2, Some((1, 1)), Some(1)), Ok(())), + ( + Type::Header(3, 1, None, None), + Err(ImportError::AwaitingFinalityProof.into()), + ), + (Type::Header(3, 2, None, None), Ok(())), + (Type::Finality(2, 1), Ok(())), + (Type::Header(3, 1, None, None), Ok(())), + ( + Type::Header(4, 2, None, None), + Err(ImportError::AwaitingFinalityProof.into()), + ), + ]; + + create_chain(&mut storage, &mut chain); + + // Since we can't query the map directly to check if we applied the right authority set + // change (we don't know the header hash of 2) we need to get a little clever. + let mut next_change = >::iter(); + let (_, scheduled_change_on_fork) = next_change.next().unwrap(); + assert_eq!(scheduled_change_on_fork.height, 3); + + // Sanity check to make sure we enacted the change on the canonical change + assert_eq!(next_change.next(), None); + }) +} + +// Order: 1, 2, 3, 2', 3' +// +// / [2'] <- [3'] +// [1] <- [2: S|0] <- [3] +// +// Not allowed to import 3 +// Fine to import 2' and 3' +#[test] +fn fork_allows_importing_on_different_fork_while_waiting_for_finality_proof() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(0)), Ok(())), + ( + Type::Header(3, 1, None, None), + Err(ImportError::AwaitingFinalityProof.into()), + ), + (Type::Header(2, 2, Some((1, 1)), None), Ok(())), + (Type::Header(3, 2, None, None), Ok(())), + ]; + + create_chain(&mut storage, &mut chain); + }) +} + +// Order: 1, 2, 2', F2, 3, 3' +// +// / [2'] <- [3'] +// [1] <- [2: F] <- [3] +// +// In our current implementation we're allowed to keep building on fork 2 for as long as our hearts' +// content. However, we'll never be able to finalize anything on that fork. We'd have to check for +// ancestry with `best_finalized` on every import which will get expensive. +// +// I think this is fine as long as we run pruning every so often to clean up these dead forks. +#[test] +fn fork_allows_importing_on_different_fork_past_finalized_header() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(0)), Ok(())), + (Type::Header(2, 2, Some((1, 1)), None), Ok(())), + (Type::Finality(2, 1), Ok(())), + (Type::Header(3, 1, None, None), Ok(())), + (Type::Header(3, 2, None, None), Ok(())), + ]; + + create_chain(&mut storage, &mut chain); + }) +} + +// Order: 1, 2, 3, 4, 3', 4' +// +// / [3': E] <- [4'] +// [1] <- [2: S|1] <- [3: E] <- [4] +// +// Not allowed to import {4|4'} +#[test] +fn fork_can_track_scheduled_changes_across_forks() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + let mut chain = vec![ + (Type::Header(1, 1, None, None), Ok(())), + (Type::Header(2, 1, None, Some(1)), Ok(())), + (Type::Header(3, 1, None, None), Ok(())), + ( + Type::Header(4, 1, None, None), + Err(ImportError::AwaitingFinalityProof.into()), + ), + (Type::Header(3, 2, Some((2, 1)), None), Ok(())), + ( + Type::Header(4, 2, None, None), + Err(ImportError::AwaitingFinalityProof.into()), + ), + ]; + + create_chain(&mut storage, &mut chain); + }) +} + +#[derive(Debug, PartialEq)] +enum TestError { + Import(ImportError), + Finality(FinalizationError), +} + +impl From for TestError { + fn from(e: ImportError) -> Self { + TestError::Import(e) + } +} + +impl From for TestError { + fn from(e: FinalizationError) -> Self { + TestError::Finality(e) + } +} + +// Builds a fork-aware representation of a blockchain given a list of headers. +// +// Takes a list of headers and finality proof operations which will be applied in order. The +// expected outcome for each operation is also required. +// +// The first header in the list will be used as the genesis header and will be manually imported +// into storage. +fn create_chain(storage: &mut S, chain: &mut Vec<(Type, Result<(), TestError>)>) +where + S: BridgeStorage

+ Clone, +{ + let mut map = BTreeMap::new(); + let mut verifier = Verifier { + storage: storage.clone(), + }; + initialize_genesis(storage, &mut map, chain.remove(0).0); + + for h in chain { + match h { + (Type::Header(num, fork_id, does_fork, schedules_change), expected_result) => { + // If we've never seen this fork before + if !map.contains_key(&fork_id) { + // Let's get the info about where to start the fork + if let Some((parent_num, forked_from_id)) = does_fork { + let fork = &*map.get(&forked_from_id).unwrap(); + let parent = fork + .iter() + .find(|h| h.number == *parent_num) + .expect("Trying to fork on a parent which doesn't exist"); + + let mut header = test_header(*num); + header.parent_hash = parent.hash(); + header.state_root = [*fork_id as u8; 32].into(); + + if let Some(delay) = schedules_change { + header.digest = change_log(*delay); + } + + // Try and import into storage + let res = verifier.import_header(header.clone()).map_err(TestError::Import); + assert_eq!( + res, *expected_result, + "Expected {:?} while importing header ({}, {}), got {:?}", + *expected_result, *num, *fork_id, res, + ); + + // Let's mark the header down in a new fork + if res.is_ok() { + map.insert(*fork_id, vec![header]); + } + } + } else { + // We've seen this fork before so let's append our new header to it + let parent_hash = { + let fork = &*map.get(&fork_id).unwrap(); + fork.last().unwrap().hash() + }; + + let mut header = test_header(*num); + header.parent_hash = parent_hash; + + // Doing this to make sure headers at the same height but on + // different forks have different hashes + header.state_root = [*fork_id as u8; 32].into(); + + if let Some(delay) = schedules_change { + header.digest = change_log(*delay); + } + + let res = verifier.import_header(header.clone()).map_err(TestError::Import); + assert_eq!( + res, *expected_result, + "Expected {:?} while importing header ({}, {}), got {:?}", + *expected_result, *num, *fork_id, res, + ); + + if res.is_ok() { + map.get_mut(&fork_id).unwrap().push(header); + } + } + } + (Type::Finality(num, fork_id), expected_result) => { + let header = map[fork_id] + .iter() + .find(|h| h.number == *num) + .expect("Trying to finalize block that doesn't exist"); + + // This is technically equivocating (accepting the same justification on the same + // `grandpa_round`). + // + // See for more: https://github.com/paritytech/parity-bridges-common/issues/430 + let grandpa_round = 1; + let set_id = 1; + let authorities = authority_list(); + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + + let res = verifier + .import_finality_proof(header.hash(), justification.into()) + .map_err(TestError::Finality); + assert_eq!( + res, *expected_result, + "Expected {:?} while importing finality proof for header ({}, {}), got {:?}", + *expected_result, *num, *fork_id, res, + ); + } + } + } + + for (key, value) in map.iter() { + println!("{}: {:#?}", key, value); + } +} + +fn initialize_genesis(storage: &mut S, map: &mut BTreeMap>, genesis: Type) +where + S: BridgeStorage
, +{ + if let Type::Header(num, fork_id, None, None) = genesis { + let genesis = test_header(num); + map.insert(fork_id, vec![genesis.clone()]); + + let genesis = ImportedHeader { + header: genesis, + requires_justification: false, + is_finalized: true, + signal_hash: None, + }; + + >::put(genesis.hash()); + storage.write_header(&genesis); + } else { + panic!("Unexpected genesis block format {:#?}", genesis) + } + + let set_id = 1; + let authorities = authority_list(); + let authority_set = AuthoritySet::new(authorities, set_id); + storage.update_current_authority_set(authority_set); +} + +fn change_log(delay: u64) -> Digest { + let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + next_authorities: vec![(alice(), 1), (bob(), 1)], + delay, + }); + + Digest:: { + logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], + } +} diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 6dfe27f2c1aba..62a44e0a62c3f 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -36,6 +36,7 @@ use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderOf}; use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult}; use frame_system::ensure_signed; use sp_runtime::traits::Header as HeaderT; +use sp_runtime::RuntimeDebug; use sp_std::{marker::PhantomData, prelude::*}; // Re-export since the node uses these when configuring genesis @@ -51,10 +52,8 @@ mod verifier; #[cfg(test)] mod mock; -pub trait Trait: frame_system::Trait { - /// Chain that we are bridging here. - type BridgedChain: Chain; -} +#[cfg(test)] +mod fork_tests; /// Block number of the bridged chain. pub(crate) type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; @@ -63,25 +62,45 @@ pub(crate) type BridgedBlockHash = HashOf<::BridgedChain>; /// Header of the bridged chain. pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; +/// A convenience type identifying headers. +#[derive(RuntimeDebug, PartialEq)] +pub struct HeaderId { + /// The block number of the header. + pub number: H::Number, + /// The hash of the header. + pub hash: H::Hash, +} + +pub trait Trait: frame_system::Trait { + /// Chain that we are bridging here. + type BridgedChain: Chain; +} + decl_storage! { trait Store for Module as SubstrateBridge { + /// The number of the highest block(s) we know of. + BestHeight: BridgedBlockNumber; /// Hash of the header at the highest known height. - BestHeader: BridgedBlockHash; + /// + /// If there are multiple headers at the same "best" height + /// this will contain all of their hashes. + BestHeaders: Vec>; /// Hash of the best finalized header. BestFinalized: BridgedBlockHash; - /// A header which enacts an authority set change and therefore - /// requires a Grandpa justification. - // Since we won't always have an authority set change scheduled we - // won't always have a header which needs a justification. - RequiresJustification: Option>; + /// The set of header IDs (number, hash) which enact an authority set change and therefore + /// require a Grandpa justification. + RequiresJustification: map hasher(identity) BridgedBlockHash => BridgedBlockNumber; /// Headers which have been imported into the pallet. ImportedHeaders: map hasher(identity) BridgedBlockHash => Option>>; /// The current Grandpa Authority set. CurrentAuthoritySet: AuthoritySet; - /// The next scheduled authority set change. + /// The next scheduled authority set change for a given fork. + /// + /// The fork is indicated by the header which _signals_ the change (key in the mapping). + /// Note that this is different than a header which _enacts_ a change. // Grandpa doesn't require there to always be a pending change. In fact, most of the time // there will be no pending change available. - NextScheduledChange: Option>>; + NextScheduledChange: map hasher(identity) BridgedBlockHash => Option>>; } add_extra_genesis { config(initial_header): Option>; @@ -98,25 +117,37 @@ decl_storage! { .initial_header .clone() .expect("An initial header is needed"); + let initial_hash = initial_header.hash(); + + >::put(initial_header.number()); + >::put(vec![initial_hash]); + >::put(initial_hash); + + let authority_set = + AuthoritySet::new(config.initial_authority_list.clone(), config.initial_set_id); + CurrentAuthoritySet::put(authority_set); + + let mut signal_hash = None; + if let Some(ref change) = config.first_scheduled_change { + assert!( + change.height > *initial_header.number(), + "Changes must be scheduled past initial header." + ); + + signal_hash = Some(initial_hash); + >::insert(initial_hash, change); + }; - >::put(initial_header.hash()); - >::put(initial_header.hash()); >::insert( - initial_header.hash(), + initial_hash, ImportedHeader { header: initial_header, requires_justification: false, is_finalized: true, + signal_hash, }, ); - let authority_set = - AuthoritySet::new(config.initial_authority_list.clone(), config.initial_set_id); - CurrentAuthoritySet::put(authority_set); - - if let Some(ref change) = config.first_scheduled_change { - >::put(change); - }; }) } } @@ -188,11 +219,13 @@ decl_module! { } impl Module { - /// Get the highest header that the pallet knows of. - // In a future where we support forks this could be a Vec of headers - // since we may have multiple headers at the same height. - pub fn best_header() -> BridgedHeader { - PalletStorage::::new().best_header().header + /// Get the highest header(s) that the pallet knows of. + pub fn best_headers() -> Vec<(BridgedBlockNumber, BridgedBlockHash)> { + PalletStorage::::new() + .best_headers() + .iter() + .map(|id| (id.number, id.hash)) + .collect() } /// Get the best finalized header the pallet knows of. @@ -224,18 +257,15 @@ impl Module { } } - /// Return the latest header which enacts an authority set change - /// and still needs a finality proof. + /// Returns a list of headers which require finality proofs. /// - /// Will return None if there are no headers which are missing finality proofs. - pub fn requires_justification() -> Option> { - let storage = PalletStorage::::new(); - let hash = storage.unfinalized_header()?; - let imported_header = storage.header_by_hash(hash).expect( - "We write a header to storage before marking it as unfinalized, therefore - this must always exist if we got an unfinalized header hash.", - ); - Some(imported_header.header) + /// These headers require proofs because they enact authority set changes. + pub fn require_justifications() -> Vec<(BridgedBlockNumber, BridgedBlockHash)> { + PalletStorage::::new() + .missing_justifications() + .iter() + .map(|id| (id.number, id.hash)) + .collect() } } @@ -248,11 +278,8 @@ pub trait BridgeStorage { /// Write a header to storage. fn write_header(&mut self, header: &ImportedHeader); - /// Get the header at the highest known height. - fn best_header(&self) -> ImportedHeader; - - /// Update the header at the highest height. - fn update_best_header(&mut self, hash: ::Hash); + /// Get the header(s) at the highest known height. + fn best_headers(&self) -> Vec>; /// Get the best finalized header the pallet knows of. fn best_finalized_header(&self) -> ImportedHeader; @@ -263,14 +290,10 @@ pub trait BridgeStorage { /// Check if a particular header is known to the pallet. fn header_exists(&self, hash: ::Hash) -> bool; - /// Return a header which requires a justification. A header will require - /// a justification when it enacts an new authority set. - fn unfinalized_header(&self) -> Option<::Hash>; - - /// Mark a header as eventually requiring a justification. + /// Returns a list of headers which require justifications. /// - /// If None is passed the storage item is cleared. - fn update_unfinalized_header(&mut self, hash: Option<::Hash>); + /// A header will require a justification if it enacts a new authority set. + fn missing_justifications(&self) -> Vec>; /// Get a specific header by its hash. /// @@ -288,13 +311,22 @@ pub trait BridgeStorage { /// Replace the current authority set with the next scheduled set. /// /// Returns an error if there is no scheduled authority set to enact. - fn enact_authority_set(&mut self) -> Result<(), ()>; + fn enact_authority_set(&mut self, signal_hash: ::Hash) -> Result<(), ()>; /// Get the next scheduled Grandpa authority set change. - fn scheduled_set_change(&self) -> Option::Number>>; + fn scheduled_set_change( + &self, + signal_hash: ::Hash, + ) -> Option::Number>>; /// Schedule a Grandpa authority set change in the future. - fn schedule_next_set_change(&self, next_change: ScheduledChange<::Number>); + /// + /// Takes the hash of the header which scheduled this particular change. + fn schedule_next_set_change( + &mut self, + signal_hash: ::Hash, + next_change: ScheduledChange<::Number>, + ); } /// Used to interact with the pallet storage in a more abstract way. @@ -311,18 +343,43 @@ impl BridgeStorage for PalletStorage { type Header = BridgedHeader; fn write_header(&mut self, header: &ImportedHeader>) { - let hash = header.header.hash(); - >::insert(hash, header); - } + use core::cmp::Ordering; + + let hash = header.hash(); + let current_height = header.number(); + let best_height = >::get(); + + match current_height.cmp(&best_height) { + Ordering::Equal => { + >::append(hash); + } + Ordering::Greater => { + >::kill(); + >::append(hash); + >::put(current_height); + } + Ordering::Less => { + // This is fine. We can still have a valid header, but it might just be on a + // different fork and at a lower height than the "best" overall header. + } + } - fn best_header(&self) -> ImportedHeader> { - let hash = >::get(); - self.header_by_hash(hash) - .expect("A header must have been written at genesis, therefore this must always exist") + if header.requires_justification { + >::insert(hash, current_height); + } else { + // If the key doesn't exist this is a no-op, so it's fine to call it often + >::remove(hash); + } + + >::insert(hash, header); } - fn update_best_header(&mut self, hash: BridgedBlockHash) { - >::put(hash) + fn best_headers(&self) -> Vec>> { + let number = >::get(); + >::get() + .iter() + .map(|hash| HeaderId { number, hash: *hash }) + .collect() } fn best_finalized_header(&self) -> ImportedHeader> { @@ -332,7 +389,7 @@ impl BridgeStorage for PalletStorage { } fn update_best_finalized(&self, hash: BridgedBlockHash) { - >::put(hash) + >::put(hash); } fn header_exists(&self, hash: BridgedBlockHash) -> bool { @@ -343,16 +400,10 @@ impl BridgeStorage for PalletStorage { >::get(hash) } - fn unfinalized_header(&self) -> Option> { - >::get() - } - - fn update_unfinalized_header(&mut self, hash: Option<::Hash>) { - if let Some(hash) = hash { - >::put(hash); - } else { - >::kill(); - } + fn missing_justifications(&self) -> Vec>> { + >::iter() + .map(|(hash, number)| HeaderId { number, hash }) + .collect() } fn current_authority_set(&self) -> AuthoritySet { @@ -363,24 +414,22 @@ impl BridgeStorage for PalletStorage { CurrentAuthoritySet::put(new_set) } - fn enact_authority_set(&mut self) -> Result<(), ()> { - if >::exists() { - let new_set = >::take() - .expect("Ensured that entry existed in storage") - .authority_set; - self.update_current_authority_set(new_set); + fn enact_authority_set(&mut self, signal_hash: BridgedBlockHash) -> Result<(), ()> { + let new_set = >::take(signal_hash).ok_or(())?.authority_set; + self.update_current_authority_set(new_set); - Ok(()) - } else { - Err(()) - } + Ok(()) } - fn scheduled_set_change(&self) -> Option>> { - >::get() + fn scheduled_set_change(&self, signal_hash: BridgedBlockHash) -> Option>> { + >::get(signal_hash) } - fn schedule_next_set_change(&self, next_change: ScheduledChange>) { - >::put(next_change) + fn schedule_next_set_change( + &mut self, + signal_hash: BridgedBlockHash, + next_change: ScheduledChange>, + ) { + >::insert(signal_hash, next_change) } } diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs index e27c781e178a8..fb98228c6a6a6 100644 --- a/modules/substrate/src/storage.rs +++ b/modules/substrate/src/storage.rs @@ -21,6 +21,7 @@ use core::default::Default; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, SetId}; +use sp_runtime::traits::Header as HeaderT; use sp_runtime::RuntimeDebug; /// A Grandpa Authority List and ID. @@ -54,7 +55,7 @@ pub struct ScheduledChange { /// A more useful representation of a header for storage purposes. #[derive(Default, Encode, Decode, Clone, RuntimeDebug, PartialEq)] -pub struct ImportedHeader { +pub struct ImportedHeader { /// A plain Substrate header. pub header: H, /// Does this header enact a new authority set change. If it does @@ -63,9 +64,12 @@ pub struct ImportedHeader { /// Has this header been finalized, either explicitly via a justification, /// or implicitly via one of its children getting finalized. pub is_finalized: bool, + /// The hash of the header which scheduled a change on this fork. If there are currently + /// not pending changes on this fork this will be empty. + pub signal_hash: Option, } -impl core::ops::Deref for ImportedHeader { +impl core::ops::Deref for ImportedHeader { type Target = H; fn deref(&self) -> &H { diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index edde9d220d712..3535834014961 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -54,7 +54,7 @@ impl From> for FinalityProof { /// Errors which can happen while importing a header. #[derive(RuntimeDebug, PartialEq)] pub enum ImportError { - /// This header is older than our latest finalized block, thus not useful. + /// This header is at the same height or older than our latest finalized block, thus not useful. OldHeader, /// This header has already been imported by the pallet. HeaderAlreadyExists, @@ -68,6 +68,13 @@ pub enum ImportError { /// the authority weights being empty or overflowing the `AuthorityWeight` /// type. InvalidAuthoritySet, + /// This header is not allowed to be imported since an ancestor requires a finality proof. + /// + /// This can happen if an ancestor is supposed to enact an authority set change. + AwaitingFinalityProof, + /// This header schedules an authority set change even though we're still waiting + /// for an old authority set change to be enacted on this fork. + PendingAuthoritySetChange, } /// Errors which can happen while verifying a headers finality. @@ -79,7 +86,7 @@ pub enum FinalizationError { PrematureJustification, /// We failed to verify this header's ancestry. AncestryCheckFailed, - /// This header is older than our latest finalized block, thus not useful. + /// This header is at the same height or older than our latest finalized block, thus not useful. OldHeader, /// The given justification was not able to finalize the given header. /// @@ -127,22 +134,37 @@ where return Err(ImportError::InvalidChildNumber); } - // This header requires a justification since it enacts an authority set change. We don't - // need to act on it right away (we'll update the set once this header gets finalized), but + // A header requires a justification if it enacts an authority set change. We don't + // need to act on it right away (we'll update the set once the header gets finalized), but // we need to make a note of it. // - // TODO: This assumes that we can only have one authority set change pending at a time. - // This is not strictly true as Grandpa may schedule multiple changes on a given chain - // if the "next next" change is scheduled after the "delay" period of the "next" change - let requires_justification = if let Some(change) = self.storage.scheduled_set_change() { - change.height == *header.number() + // Note: This assumes that we can only have one authority set change pending per fork at a + // time. While this is not strictly true of Grandpa (it can have multiple pending changes, + // even across forks), this assumption simplifies our tracking of authority set changes. + let mut signal_hash = parent_header.signal_hash; + let scheduled_change = find_scheduled_change(&header); + + // Check if our fork is expecting an authority set change + let requires_justification = if let Some(hash) = signal_hash { + const PROOF: &str = "If the header has a signal hash it means there's an accompanying set + change in storage, therefore this must always be valid."; + let pending_change = self.storage.scheduled_set_change(hash).expect(PROOF); + + if scheduled_change.is_some() { + return Err(ImportError::PendingAuthoritySetChange); + } + + if *header.number() > pending_change.height { + return Err(ImportError::AwaitingFinalityProof); + } + + pending_change.height == *header.number() } else { // Since we don't currently have a pending authority set change let's check if the header // contains a log indicating when the next change should be. - if let Some(change) = find_scheduled_change(&header) { + if let Some(change) = scheduled_change { let mut total_weight = 0u64; - // We need to make sure that we don't overflow the `AuthorityWeight` type. for (_id, weight) in &change.next_authorities { total_weight = total_weight .checked_add(*weight) @@ -163,12 +185,16 @@ where let height = (*header.number()) .checked_add(&change.delay) .ok_or(ImportError::ScheduledHeightOverflow)?; + let scheduled_change = ScheduledChange { authority_set: next_set, height, }; - self.storage.schedule_next_set_change(scheduled_change); + // Note: It's important that the signal hash is updated if a header schedules a + // change or else we end up with inconsistencies in other places. + signal_hash = Some(hash); + self.storage.schedule_next_set_change(hash, scheduled_change); // If the delay is 0 this header will enact the change it signaled height == *header.number() @@ -181,16 +207,9 @@ where header, requires_justification, is_finalized: false, + signal_hash, }); - if requires_justification { - self.storage.update_unfinalized_header(Some(hash)); - } - - // Since we're not dealing with forks at the moment we know that - // the header we just got will be the one at the best height - self.storage.update_best_header(hash); - Ok(()) } @@ -258,19 +277,25 @@ where // new authority set change. When we finalize the header we need to update the current // authority set. if header.requires_justification { + const SIGNAL_HASH_PROOF: &str = "When we import a header we only mark it as + `requires_justification` if we have checked that it contains a signal hash. Therefore + this must always be valid."; + + const ENACT_SET_PROOF: &str = + "Headers must only be marked as `requires_justification` if there's a scheduled change in storage."; + // If we are unable to enact an authority set it means our storage entry for scheduled // changes is missing. Best to crash since this is likely a bug. - let _ = self.storage.enact_authority_set().expect( - "Headers must only be marked as `requires_justification` if there's a scheduled change in storage.", - ); - - // Clear the storage entry since we got a justification - self.storage.update_unfinalized_header(None); + let _ = self + .storage + .enact_authority_set(header.signal_hash.expect(SIGNAL_HASH_PROOF)) + .expect(ENACT_SET_PROOF); } for header in finalized_headers.iter_mut() { header.is_finalized = true; header.requires_justification = false; + header.signal_hash = None; self.storage.write_header(header); } @@ -329,17 +354,19 @@ mod tests { use crate::justification::tests::*; use crate::mock::helpers::*; use crate::mock::*; - use crate::{BestFinalized, ImportedHeaders, PalletStorage}; + use crate::{BestFinalized, BestHeight, HeaderId, ImportedHeaders, PalletStorage}; use codec::Encode; use frame_support::{assert_err, assert_ok}; use frame_support::{StorageMap, StorageValue}; use sp_finality_grandpa::{AuthorityId, SetId}; + use sp_runtime::{Digest, DigestItem}; fn unfinalized_header(num: u64) -> ImportedHeader { ImportedHeader { header: test_header(num), requires_justification: false, is_finalized: false, + signal_hash: None, } } @@ -354,6 +381,7 @@ mod tests { } // Useful for quickly writing a chain of headers to storage + // Input is expected in the form: vec![(num, requires_justification, is_finalized)] fn write_headers>( storage: &mut S, headers: Vec<(u64, bool, bool)>, @@ -363,6 +391,7 @@ mod tests { header: test_header(0), requires_justification: false, is_finalized: true, + signal_hash: None, }; >::put(genesis.hash()); @@ -374,6 +403,7 @@ mod tests { header: test_header(num), requires_justification, is_finalized, + signal_hash: None, }; storage.write_header(&header); @@ -383,6 +413,16 @@ mod tests { imported_headers } + // Given a block number will generate a chain of headers which don't require justification and + // are not considered to be finalized. + fn write_default_headers>( + storage: &mut S, + headers: Vec, + ) -> Vec> { + let headers = headers.iter().map(|num| (*num, false, false)).collect(); + write_headers(storage, headers) + } + #[test] fn fails_to_import_old_header() { run_test(|| { @@ -424,6 +464,7 @@ mod tests { header: header.clone(), requires_justification: false, is_finalized: false, + signal_hash: None, }; >::insert(header.hash(), &imported_header); @@ -444,6 +485,7 @@ mod tests { header: parent, requires_justification: false, is_finalized: true, + signal_hash: None, }; >::insert(parent_hash, &imported_header); @@ -457,17 +499,97 @@ mod tests { .header_by_hash(header.hash()) .expect("Should have been imported successfully"); assert_eq!(stored_header.is_finalized, false); - assert_eq!(stored_header, storage.best_header()); + assert_eq!(stored_header.hash(), storage.best_headers()[0].hash); }) } #[test] - fn related_headers_are_ancestors() { + fn successfully_imports_two_different_headers_at_same_height() { + run_test(|| { + let mut storage = PalletStorage::::new(); + + // We want to write the genesis header to storage + let _ = write_headers(&mut storage, vec![]); + + // Both of these headers have the genesis header as their parent + let header_on_fork1 = test_header(1); + let mut header_on_fork2 = test_header(1); + + // We need to change _something_ to make it a different header + header_on_fork2.state_root = [1; 32].into(); + + let mut verifier = Verifier { + storage: storage.clone(), + }; + + // It should be fine to import both + assert_ok!(verifier.import_header(header_on_fork1.clone())); + assert_ok!(verifier.import_header(header_on_fork2.clone())); + + // We should have two headers marked as being the best since they're + // both at the same height + let best_headers = storage.best_headers(); + assert_eq!(best_headers.len(), 2); + assert_eq!( + best_headers[0], + HeaderId { + number: *header_on_fork1.number(), + hash: header_on_fork1.hash() + } + ); + assert_eq!( + best_headers[1], + HeaderId { + number: *header_on_fork2.number(), + hash: header_on_fork2.hash() + } + ); + assert_eq!(>::get(), 1); + }) + } + + #[test] + fn correctly_updates_the_best_header_given_a_better_header() { run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false), (2, false, false), (3, false, false)]; - let mut imported_headers = write_headers(&mut storage, headers); + // Write two headers at the same height to storage. + let imported_headers = write_default_headers(&mut storage, vec![1, 1]); + + // The headers we manually imported should have been marked as the best + // upon writing to storage. Let's confirm that. + assert_eq!(storage.best_headers().len(), 2); + assert_eq!(>::get(), 1); + + // Now let's build something at a better height. + let mut better_header = test_header(2); + better_header.parent_hash = imported_headers[1].hash(); + + let mut verifier = Verifier { + storage: storage.clone(), + }; + assert_ok!(verifier.import_header(better_header.clone())); + + // Since `better_header` is the only one at height = 2 we should only have + // a single "best header" now. + let best_headers = storage.best_headers(); + assert_eq!(best_headers.len(), 1); + assert_eq!( + best_headers[0], + HeaderId { + number: *better_header.number(), + hash: better_header.hash() + } + ); + assert_eq!(>::get(), 2); + }) + } + + #[test] + fn related_headers_are_ancestors() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let mut imported_headers = write_default_headers(&mut storage, vec![1, 2, 3]); for header in imported_headers.iter() { assert!(storage.header_exists(header.hash())); @@ -487,8 +609,7 @@ mod tests { run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false), (2, false, false), (3, false, false)]; - let mut imported_headers = write_headers(&mut storage, headers); + let mut imported_headers = write_default_headers(&mut storage, vec![1, 2, 3]); for header in imported_headers.iter() { assert!(storage.header_exists(header.hash())); } @@ -501,6 +622,7 @@ mod tests { header: bad_ancestor, requires_justification: false, is_finalized: false, + signal_hash: None, }; let child = imported_headers.pop().unwrap(); @@ -514,8 +636,7 @@ mod tests { run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false), (2, false, false), (3, false, false)]; - let mut imported_headers = write_headers(&mut storage, headers); + let mut imported_headers = write_default_headers(&mut storage, vec![1, 2, 3]); for header in imported_headers.iter() { assert!(storage.header_exists(header.hash())); } @@ -526,6 +647,7 @@ mod tests { header: new_ancestor, requires_justification: false, is_finalized: false, + signal_hash: None, }; let child = imported_headers.pop().unwrap(); @@ -536,12 +658,9 @@ mod tests { #[test] fn doesnt_import_header_which_schedules_change_with_invalid_authority_set() { - use sp_runtime::{Digest, DigestItem}; - run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false)]; - let _imported_headers = write_headers(&mut storage, headers); + let _imported_headers = write_default_headers(&mut storage, vec![1]); let mut header = test_header(2); // This is an *invalid* authority set because the combined weight of the @@ -568,8 +687,7 @@ mod tests { fn finalizes_header_which_doesnt_enact_or_schedule_a_new_authority_set() { run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false)]; - let _imported_headers = write_headers(&mut storage, headers); + let _imported_headers = write_default_headers(&mut storage, vec![1]); // Nothing special about this header, yet Grandpa may have created a justification // for it since it does that periodically @@ -598,8 +716,7 @@ mod tests { fn correctly_verifies_and_finalizes_chain_of_headers() { run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false), (2, false, false)]; - let imported_headers = write_headers(&mut storage, headers); + let imported_headers = write_default_headers(&mut storage, vec![1, 2]); let header = test_header(3); let set_id = 1; @@ -635,8 +752,16 @@ mod tests { fn updates_authority_set_upon_finalizing_header_which_enacts_change() { run_test(|| { let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false)]; - let _imported_headers = write_headers(&mut storage, headers); + let genesis_hash = write_headers(&mut storage, vec![])[0].hash(); + + // We want this header to indicate that there's an upcoming set change on this fork + let parent = ImportedHeader { + header: test_header(1), + requires_justification: false, + is_finalized: false, + signal_hash: Some(genesis_hash), + }; + storage.write_header(&parent); let set_id = 1; let authorities = authority_list(); @@ -654,21 +779,22 @@ mod tests { let height = *header.number(); let authorities = vec![alice()]; let change = schedule_next_change(authorities, set_id, height); - storage.schedule_next_set_change(change.clone()); + storage.schedule_next_set_change(genesis_hash, change.clone()); let mut verifier = Verifier { storage: storage.clone(), }; assert_ok!(verifier.import_header(header.clone())); - assert_eq!(storage.unfinalized_header(), Some(header.hash())); + assert_eq!(storage.missing_justifications().len(), 1); + assert_eq!(storage.missing_justifications()[0].hash, header.hash()); assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); assert_eq!(storage.best_finalized_header().header, header); // Make sure that we have updated the set now that we've finalized our header assert_eq!(storage.current_authority_set(), change.authority_set); - assert_eq!(storage.unfinalized_header(), None); + assert!(storage.missing_justifications().is_empty()); }) } @@ -682,6 +808,7 @@ mod tests { header: genesis, requires_justification: false, is_finalized: true, + signal_hash: None, }; // Make sure that genesis is the best finalized header @@ -699,82 +826,4 @@ mod tests { ); }); } - - // We're supposed to enact a set change at header N. This means that when we import it we must - // remember that it requires a justification. We can continue importing headers past N but must - // not finalize any childen. At a later point in time we should be able to import the - // justification for N. - // - // Since N enacts a new authority set, when we finalize it we should see this change reflected - // correctly. - // - // [G] <- [N-1] <- [N] <- [N+1] <- [N+2] - // | |- Import justification for N here - // |- Enacts change, needs justification - #[test] - fn allows_importing_justification_at_block_past_scheduled_change() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let headers = vec![(1, false, false)]; - let imported_headers = write_headers(&mut storage, headers); - - // Set up our initial authority set - let set_id = 1; - let authorities = authority_list(); - let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id); - storage.update_current_authority_set(initial_authority_set); - - // This is header N - let header = test_header(2); - - // Since we want to finalize N we need a justification for it - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); - - // Schedule a change at height N - let set_id = 2; - let height = *header.number(); - let authorities = vec![alice()]; - let change = schedule_next_change(authorities, set_id, height); - storage.schedule_next_set_change(change.clone()); - - // Import header N - let mut verifier = Verifier { - storage: storage.clone(), - }; - assert!(verifier.import_header(header.clone()).is_ok()); - - // Header N should be marked as needing a justification - assert_eq!( - storage.header_by_hash(header.hash()).unwrap().requires_justification, - true - ); - - // Now we want to import some headers which are past N - let child = test_header(*header.number() + 1); - assert!(verifier.import_header(child.clone()).is_ok()); - - let grandchild = test_header(*child.number() + 1); - assert!(verifier.import_header(grandchild).is_ok()); - - // Even though we're a few headers ahead we should still be able to import - // a justification for header N - assert!(verifier - .import_finality_proof(header.hash(), justification.into()) - .is_ok()); - - // Some checks to make sure that our header has been correctly finalized - let finalized_header = storage.header_by_hash(header.hash()).unwrap(); - assert!(finalized_header.is_finalized); - assert_eq!(finalized_header.requires_justification, false); - assert_eq!(storage.best_finalized_header().header, header); - - // Make sure we marked the parent of the header at N as finalized - assert!(storage.header_by_hash(imported_headers[1].hash()).unwrap().is_finalized); - - // Since our header was supposed to enact a new authority set change when it got - // finalized let's make sure that the authority set actually changed - assert_eq!(storage.current_authority_set(), change.authority_set); - }) - } } diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 6276b8db3a17a..dcdbf37dbd783 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -61,7 +61,7 @@ impl Chain for Millau { } /// Name of the `MillauHeaderApi::best_block` runtime method. -pub const BEST_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_best_block"; +pub const BEST_MILLAU_BLOCKS_METHOD: &str = "MillauHeaderApi_best_blocks"; /// Name of the `MillauHeaderApi::finalized_block` runtime method. pub const FINALIZED_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_finalized_block"; /// Name of the `MillauHeaderApi::is_known_block` runtime method. @@ -88,11 +88,13 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are bridging with Millau chain, not the /// Millau runtime itself. pub trait MillauHeaderApi { - /// Returns number and hash of the best block known to the bridge module. + /// Returns number and hash of the best blocks known to the bridge module. + /// + /// Will return multiple headers if there are many headers at the same "best" height. /// /// The caller should only submit an `import_header` transaction that makes /// (or leads to making) other header the best one. - fn best_block() -> (BlockNumber, Hash); + fn best_blocks() -> Vec<(BlockNumber, Hash)>; /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (BlockNumber, Hash); /// Returns numbers and hashes of headers that require finality proofs. diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 7e761a72031d0..426c5c4f1f893 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -79,11 +79,13 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are bridging with Rialto chain, not the /// Rialto runtime itself. pub trait RialtoHeaderApi { - /// Returns number and hash of the best block known to the bridge module. + /// Returns number and hash of the best blocks known to the bridge module. + /// + /// Will return multiple headers if there are many headers at the same "best" height. /// /// The caller should only submit an `import_header` transaction that makes /// (or leads to making) other header the best one. - fn best_block() -> (BlockNumber, Hash); + fn best_blocks() -> Vec<(BlockNumber, Hash)>; /// Returns number and hash of the best finalized block known to the bridge module. fn finalized_block() -> (BlockNumber, Hash); /// Returns numbers and hashes of headers that require finality proofs. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 096db8397b81f..2754a8aa7d436 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -40,7 +40,8 @@ pub trait Chain { + AtLeast32BitUnsigned + FromStr + MaybeMallocSizeOf - + AsPrimitive; + + AsPrimitive + + 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` diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index 546fb805eb632..a6502f407fa4b 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -90,10 +90,15 @@ where let data = Bytes(Vec::new()); let encoded_response = self.client.state_call(call, data, None).await?; - let decoded_response: (P::Number, P::Hash) = + let decoded_response: Vec<(P::Number, P::Hash)> = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); + let best_header = decoded_response.last().ok_or_else(|| { + SubstrateError::ResponseParseFailed( + "Parsed an empty list of headers, we should always have at least one.".into(), + ) + })?; + let best_header_id = HeaderId(best_header.0, best_header.1); Ok(best_header_id) } diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 9f63614cde374..7bf504bcfe968 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -24,7 +24,7 @@ use crate::{ use async_trait::async_trait; use bp_millau::{ - BEST_MILLAU_BLOCK_METHOD, FINALIZED_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, + BEST_MILLAU_BLOCKS_METHOD, FINALIZED_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, IS_KNOWN_MILLAU_BLOCK_METHOD, }; use codec::Encode; @@ -65,7 +65,7 @@ impl HeadersSyncPipeline for MillauHeadersToRialto { #[async_trait] impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { - const BEST_BLOCK_METHOD: &'static str = BEST_MILLAU_BLOCK_METHOD; + const BEST_BLOCK_METHOD: &'static str = BEST_MILLAU_BLOCKS_METHOD; const FINALIZED_BLOCK_METHOD: &'static str = FINALIZED_MILLAU_BLOCK_METHOD; const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_MILLAU_BLOCK_METHOD; const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_MILLAU_HEADERS_METHOD; From e4e6e7f6fb0a7e5cb0e4bb5d8c37df60e6a4e275 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Oct 2020 10:04:06 +0300 Subject: [PATCH 0202/1210] SubmitMillauToRialtoMessage subcommand in substrate-relay (#460) * substrate-relay::SubmitMillauToRialtoMessage * typo * Update relays/substrate/src/cli.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + relays/millau-client/Cargo.toml | 2 + relays/millau-client/src/lib.rs | 72 +++++++++++++++++++++++++-- relays/substrate/Cargo.toml | 6 +++ relays/substrate/src/cli.rs | 49 ++++++++++++++++++- relays/substrate/src/main.rs | 87 +++++++++++++++++++++++++++++++-- 7 files changed, 210 insertions(+), 8 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7f78bc58213dd..22df99bbb3711 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -55,6 +55,7 @@ pub use frame_support::{ }; pub use pallet_balances::Call as BalancesCall; +pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeSubstrateCall; pub use pallet_timestamp::Call as TimestampCall; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 008e473731698..778b2afd18e95 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -60,6 +60,7 @@ pub use frame_support::{ StorageValue, }; +pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index 3bf0dc426f05f..bf6569d7eed3e 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -18,4 +18,6 @@ millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies frame-system = "2.0" +pallet-transaction-payment = "2.0" +sp-core = "2.0" sp-runtime = "2.0" diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index c1fadba024da1..129602cf7a468 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -16,10 +16,14 @@ //! Types used to connect to the Millau-Substrate chain. -use relay_substrate_client::{Chain, ChainBase}; - +use codec::Encode; use headers_relay::sync_types::SourceHeader; -use sp_runtime::traits::Header as HeaderT; +use relay_substrate_client::{Chain, ChainBase, Client, TransactionSignScheme}; +use sp_core::Pair; +use sp_runtime::{ + generic::SignedPayload, + traits::{Header as HeaderT, IdentifyAccount}, +}; /// Millau header id. pub type HeaderId = relay_utils::HeaderId; @@ -42,6 +46,68 @@ impl Chain for Millau { type Call = millau_runtime::Call; } +impl TransactionSignScheme for Millau { + type Chain = Millau; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = millau_runtime::UncheckedExtrinsic; + + fn sign_transaction( + client: &Client, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::from_raw( + call, + ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckNonce::::from(signer_nonce), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ), + ( + millau_runtime::VERSION.spec_version, + millau_runtime::VERSION.transaction_version, + *client.genesis_hash(), + *client.genesis_hash(), + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + millau_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + } +} + +/// Millau signing params. +#[derive(Clone)] +pub struct SigningParams { + /// Substrate transactions signer. + pub signer: sp_core::sr25519::Pair, +} + +impl SigningParams { + /// Create signing params from SURI and password. + pub fn from_suri(suri: &str, password: Option<&str>) -> Result { + Ok(SigningParams { + signer: sp_core::sr25519::Pair::from_string(suri, password)?, + }) + } +} + +impl std::fmt::Debug for SigningParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.signer.public()) + } +} + /// Millau header type used in headers sync. #[derive(Clone, Debug, PartialEq)] pub struct SyncHeader(millau_runtime::Header); diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index a3f6ca6e435c4..3a760ffde86bf 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -10,23 +10,29 @@ async-std = "1.6.2" async-trait = "0.1.41" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.7" +hex = "0.4" log = "0.4.11" paste = "1.0" structopt = "0.3" # Bridge dependencies +bp-message-lane = { path = "../../primitives/message-lane" } bp-millau = { path = "../../primitives/millau" } bp-rialto = { path = "../../primitives/rialto" } headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } +millau-runtime = { path = "../../bin/millau/runtime" } +pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } pallet-substrate-bridge = { path = "../../modules/substrate" } relay-millau-client = { path = "../millau-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } +rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies +frame-support = "2.0" sp-core = "2.0" sp-runtime = "2.0" diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index e13eccf6016dd..ec081cd1d2780 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -16,7 +16,8 @@ //! Deal with CLI args of substrate-to-substrate relay. -use structopt::StructOpt; +use bp_message_lane::LaneId; +use structopt::{clap::arg_enum, StructOpt}; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -38,6 +39,52 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, + /// Submit message to given Rialto -> Millau lane. + SubmitMillauToRialtoMessage { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + /// Hex-encoded lane id. + #[structopt(long)] + lane: HexLaneId, + /// Message type. + #[structopt(long, possible_values = &ToRialtoMessage::variants())] + message: ToRialtoMessage, + /// Delivery and dispatch fee. + #[structopt(long)] + fee: bp_millau::Balance, + }, +} + +arg_enum! { + #[derive(Debug)] + /// All possible messages that may be delivered to the Rialto chain. + pub enum ToRialtoMessage { + Remark, + } +} + +/// Lane id. +#[derive(Debug)] +pub struct HexLaneId(LaneId); + +impl From for LaneId { + fn from(lane_id: HexLaneId) -> LaneId { + lane_id.0 + } +} + +impl std::str::FromStr for HexLaneId { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + let mut lane_id = LaneId::default(); + hex::decode_to_slice(s, &mut lane_id)?; + Ok(HexLaneId(lane_id)) + } } /// Prometheus metrics params. diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 53f10dab86d6b..76b2aa9189dde 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -18,14 +18,19 @@ #![warn(missing_docs)] -use relay_rialto_client::SigningParams as RialtoSigningParams; -use relay_substrate_client::ConnectionParams; +use codec::Encode; +use frame_support::weights::GetDispatchInfo; +use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; +use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{ConnectionParams, TransactionSignScheme}; use relay_utils::initialize::initialize_relay; +use sp_core::{Bytes, Pair}; /// Millau node client. -pub type MillauClient = relay_substrate_client::Client; +pub type MillauClient = relay_substrate_client::Client; /// Rialto node client. -pub type RialtoClient = relay_substrate_client::Client; +pub type RialtoClient = relay_substrate_client::Client; mod cli; mod headers_maintain; @@ -66,6 +71,80 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; } + cli::Command::SubmitMillauToRialtoMessage { + millau, + millau_sign, + rialto_sign, + lane, + message, + fee, + } => { + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + let rialto_sign = RialtoSigningParams::from_suri( + &rialto_sign.rialto_signer, + rialto_sign.rialto_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + + let rialto_call = match message { + cli::ToRialtoMessage::Remark => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( + format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec(), + )), + }; + let rialto_call_weight = rialto_call.get_dispatch_info().weight; + + let millau_sender_public = millau_sign.signer.public(); + let rialto_origin_public = rialto_sign.signer.public(); + + let mut rialto_origin_signature_message = Vec::new(); + rialto_call.encode_to(&mut rialto_origin_signature_message); + millau_sender_public.encode_to(&mut rialto_origin_signature_message); + let rialto_origin_signature = rialto_sign.signer.sign(&rialto_origin_signature_message); + + let millau_call = + millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( + lane.into(), + MessagePayload { + spec_version: millau_runtime::VERSION.spec_version, + weight: rialto_call_weight, + origin: CallOrigin::RealAccount( + millau_sender_public.into(), + rialto_origin_public.into(), + rialto_origin_signature.into(), + ), + call: rialto_call.encode(), + }, + fee, + )); + + let signed_millau_call = Millau::sign_transaction( + &millau_client, + &millau_sign.signer, + millau_client.next_account_index(millau_sender_public.into()).await?, + millau_call, + ); + + millau_client + .submit_extrinsic(Bytes(signed_millau_call.encode())) + .await?; + } } Ok(()) From e9b34934752f3c165d9782bf8935527b8e69c215 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Oct 2020 12:26:12 +0300 Subject: [PATCH 0203/1210] Update jsonrpsee reference (#467) * update Millau state_root * update jsonrpsee reference --- bin/rialto/runtime/src/millau.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs index 2c0e9dfc87b01..1ca819331906e 100644 --- a/bin/rialto/runtime/src/millau.rs +++ b/bin/rialto/runtime/src/millau.rs @@ -36,7 +36,7 @@ pub fn initial_header() -> Header { Header { parent_hash: Default::default(), number: Default::default(), - state_root: hex!("234a17bbd3fbaff8f0a799a6c8f0bdba1979e242fb2ed66d15945acb84947cbd").into(), + state_root: hex!("dc7567715330c666eca349a4612e82ec3b3c4f306ef941dce192a37fb3131cfa").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Default::default(), } From 2a06c645896d17cb1f54cbb3f3767744701a30cc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Oct 2020 21:35:29 +0300 Subject: [PATCH 0204/1210] Return cumulative dispatch weight of messages from the `messageLane_proveMessages` (#469) * implement OutboundLaneApi and InboundLaneApi for Millau /Rialto runtimes * fixed typo --- bin/millau/node/src/service.rs | 1 + bin/millau/runtime/src/lib.rs | 31 +++++++++++++++++++++ bin/rialto/node/src/service.rs | 1 + bin/rialto/runtime/src/lib.rs | 31 +++++++++++++++++++++ modules/message-lane/rpc/Cargo.toml | 2 ++ modules/message-lane/rpc/src/lib.rs | 42 ++++++++++++++++++++++------- modules/message-lane/src/lib.rs | 29 +++++++++++++++++++- primitives/message-lane/src/lib.rs | 4 ++- 8 files changed, 129 insertions(+), 12 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 3e3917d7bd8dd..0a6b5d8b849e6 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -222,6 +222,7 @@ pub fn new_full(config: Configuration) -> Result { finality_proof_provider.clone(), ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + client.clone(), backend.clone(), Arc::new(MillauMessageLaneKeys), ))); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 22df99bbb3711..1e5a8feddeaf0 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -31,6 +31,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto; pub mod rialto_messages; +use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -538,4 +539,34 @@ impl_runtime_apis! { BridgeRialto::is_finalized_header(hash) } } + + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::OutboundLaneApi for Runtime { + fn messages_dispatch_weight(lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce) -> Weight { + (begin..=end) + .filter_map(|nonce| BridgeRialtoMessageLane::outbound_message_payload(lane, nonce)) + .filter_map(|encoded_payload| rialto_messages::ToRialtoMessagePayload::decode(&mut &encoded_payload[..]).ok()) + .map(|decoded_payload| decoded_payload.weight) + .fold(0, |sum, weight| sum.saturating_add(weight)) + } + + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::outbound_latest_received_nonce(lane) + } + + fn latest_generated_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::outbound_latest_generated_nonce(lane) + } + } + + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::InboundLaneApi for Runtime { + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::inbound_latest_received_nonce(lane) + } + + fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeRialtoMessageLane::inbound_latest_confirmed_nonce(lane) + } + } } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 21b2bf0bce7d5..07a49a26858ac 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -206,6 +206,7 @@ pub fn new_full(config: Configuration) -> Result { DenyUnsafe::No, ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + client.clone(), backend.clone(), Arc::new(RialtoMessageLaneKeys), ))); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 778b2afd18e95..1ab9984bec722 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -37,6 +37,7 @@ pub mod millau; pub mod millau_messages; pub mod rialto_poa; +use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -702,6 +703,36 @@ impl_runtime_apis! { } } + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::OutboundLaneApi for Runtime { + fn messages_dispatch_weight(lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce) -> Weight { + (begin..=end) + .filter_map(|nonce| BridgeMillauMessageLane::outbound_message_payload(lane, nonce)) + .filter_map(|encoded_payload| millau_messages::ToMillauMessagePayload::decode(&mut &encoded_payload[..]).ok()) + .map(|decoded_payload| decoded_payload.weight) + .fold(0, |sum, weight| sum.saturating_add(weight)) + } + + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::outbound_latest_received_nonce(lane) + } + + fn latest_generated_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::outbound_latest_generated_nonce(lane) + } + } + + // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) + impl bp_message_lane::InboundLaneApi for Runtime { + fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::inbound_latest_received_nonce(lane) + } + + fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { + BridgeMillauMessageLane::inbound_latest_confirmed_nonce(lane) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn dispatch_benchmark( diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index e9ef6c1cc6b2a..cc179f5d366c7 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -20,7 +20,9 @@ bp-message-lane = { path = "../../../primitives/message-lane" } # Substrate Dependencies +frame-support = "2.0" sc-client-api = "2.0" +sp-api = "2.0" sp-blockchain = "2.0" sp-core = "2.0" sp-runtime = "2.0" diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index 61a82eae7f2c6..bcc786f3866fc 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -18,12 +18,14 @@ use crate::error::{Error, FutureResult}; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_message_lane::{LaneId, MessageNonce, OutboundLaneApi}; use bp_runtime::InstanceId; +use frame_support::weights::Weight; use futures::{FutureExt, TryFutureExt}; use jsonrpc_core::futures::Future as _; use jsonrpc_derive::rpc; use sc_client_api::Backend as BackendT; +use sp_api::ProvideRuntimeApi; use sp_blockchain::{Error as BlockchainError, HeaderBackend}; use sp_core::{storage::StorageKey, Bytes}; use sp_runtime::{codec::Encode, generic::BlockId, traits::Block as BlockT}; @@ -54,7 +56,8 @@ pub trait Runtime: Send + Sync + 'static { /// Provides RPC methods for interacting with message-lane pallet. #[rpc] pub trait MessageLaneApi { - /// Returns proof-of-message(s) in given inclusive range. + /// Returns cumulative dispatch weight of messages in given inclusive range and their storage proof. + /// The state of outbound lane is included in the proof if `include_outbound_lane_state` is true. #[rpc(name = "messageLane_proveMessages")] fn prove_messages( &self, @@ -64,7 +67,7 @@ pub trait MessageLaneApi { end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> FutureResult; + ) -> FutureResult<(Weight, MessagesProof)>; /// Returns proof-of-message(s) delivery. #[rpc(name = "messageLane_proveMessagesDelivery")] @@ -77,16 +80,18 @@ pub trait MessageLaneApi { } /// Implements the MessageLaneApi trait for interacting with message lanes. -pub struct MessageLaneRpcHandler { +pub struct MessageLaneRpcHandler { + client: Arc, backend: Arc, runtime: Arc, _phantom: std::marker::PhantomData, } -impl MessageLaneRpcHandler { +impl MessageLaneRpcHandler { /// Creates new mesage lane RPC handler. - pub fn new(backend: Arc, runtime: Arc) -> Self { + pub fn new(client: Arc, backend: Arc, runtime: Arc) -> Self { Self { + client, backend, runtime, _phantom: Default::default(), @@ -94,9 +99,11 @@ impl MessageLaneRpcHandler { } } -impl MessageLaneApi for MessageLaneRpcHandler +impl MessageLaneApi for MessageLaneRpcHandler where Block: BlockT, + Client: ProvideRuntimeApi + Send + Sync + 'static, + Client::Api: OutboundLaneApi, Backend: BackendT + 'static, R: Runtime, { @@ -108,7 +115,22 @@ where end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> FutureResult { + ) -> FutureResult<(Weight, MessagesProof)> { + let block = unwrap_or_best(&*self.backend, block); + + let messages_dispatch_weight_result = + self.client + .runtime_api() + .messages_dispatch_weight(&BlockId::Hash(block), lane, begin, end); + let messages_dispatch_weight = match messages_dispatch_weight_result { + Ok(messages_dispatch_weight) => messages_dispatch_weight, + Err(error) => { + return Box::new(jsonrpc_core::futures::future::err( + blockchain_err(BlockchainError::Execution(Box::new(format!("{:?}", error)))).into(), + )) + } + }; + let runtime = self.runtime.clone(); let outbound_lane_data_key = if include_outbound_lane_state { Some(runtime.inbound_lane_data_key(&instance, &lane)) @@ -118,14 +140,14 @@ where Box::new( prove_keys_read( self.backend.clone(), - block, + Some(block), (begin..=end) .map(move |nonce| runtime.message_key(&instance, &lane, nonce)) .chain(outbound_lane_data_key.into_iter()), ) .boxed() .compat() - .map(serialize_storage_proof) + .map(move |proof| (messages_dispatch_weight, serialize_storage_proof(proof))) .map_err(Into::into), ) } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 696340c6ff50b..169270efe0b21 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -35,7 +35,7 @@ use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, + InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; use codec::{Decode, Encode}; use frame_support::{ @@ -374,6 +374,33 @@ decl_module! { } } +impl, I: Instance> Module { + /// Get payload of given outbound message. + pub fn outbound_message_payload(lane: LaneId, nonce: MessageNonce) -> Option { + OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(|message_data| message_data.payload) + } + + /// Get nonce of latest generated message at given outbound lane. + pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { + OutboundLanes::::get(&lane).latest_generated_nonce + } + + /// Get nonce of latest confirmed message at given outbound lane. + pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { + OutboundLanes::::get(&lane).latest_received_nonce + } + + /// Get nonce of latest received message at given inbound lane. + pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { + InboundLanes::::get(&lane).latest_received_nonce + } + + /// Get nonce of latest confirmed message at given inbound lane. + pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { + InboundLanes::::get(&lane).latest_confirmed_nonce + } +} + /// Creates new inbound lane object, backed by runtime storage. fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { InboundLane::new(RuntimeInboundLaneStorage { diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 672ba719b97de..e7ae16135b6ed 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -23,7 +23,7 @@ #![allow(clippy::unnecessary_mut_passed)] use codec::{Decode, Encode}; -use frame_support::RuntimeDebug; +use frame_support::{weights::Weight, RuntimeDebug}; use sp_api::decl_runtime_apis; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; @@ -126,6 +126,8 @@ impl Default for OutboundLaneData { decl_runtime_apis! { /// Outbound message lane API. pub trait OutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + fn messages_dispatch_weight(lane: LaneId, begin: MessageNonce, end: MessageNonce) -> Weight; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. From 318fa0e87332b639bc8372e0fde11a92b6756a41 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 2 Nov 2020 08:13:29 +0300 Subject: [PATCH 0205/1210] Ability to halt/resume message-lane pallet (#472) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * halt/resume message-lane pallet * fmt * Update modules/message-lane/src/lib.rs Co-authored-by: Tomasz Drwięga * include weights in halt/resume operations * remove trailing space * set_owner * Shorten doc comment length Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- modules/message-lane/Cargo.toml | 2 + modules/message-lane/src/lib.rs | 176 +++++++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index e9313a4d70d5e..41f844fc9f841 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -33,6 +34,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "serde", "sp-runtime/std", "sp-std/std", ] diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 169270efe0b21..9f6c1d6d706ad 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -39,10 +39,13 @@ use bp_message_lane::{ }; use codec::{Decode, Encode}; use frame_support::{ - decl_error, decl_event, decl_module, decl_storage, sp_runtime::DispatchResult, traits::Get, weights::Weight, + decl_error, decl_event, decl_module, decl_storage, + traits::Get, + weights::{DispatchClass, Weight}, Parameter, StorageMap, }; -use frame_system::ensure_signed; +use frame_system::{ensure_signed, RawOrigin}; +use sp_runtime::{traits::BadOrigin, DispatchResult}; use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; @@ -120,6 +123,8 @@ type MessagesDeliveryProofOf = <>::TargetHeaderChain as Targ decl_error! { pub enum Error for Module, I: Instance> { + /// All pallet operations are halted. + Halted, /// Message has been treated as invalid by chain verifier. MessageRejectedByChainVerifier, /// Message has been treated as invalid by lane verifier. @@ -137,6 +142,15 @@ decl_error! { decl_storage! { trait Store for Module, I: Instance = DefaultInstance> as MessageLane { + /// Optional pallet owner. + /// + /// Pallet owner has a right to halt all pallet operations and then resume it. If it is + /// `None`, then there are no direct ways to halt/resume pallet operations, but other + /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt + /// flag directly or call the `halt_operations`). + pub ModuleOwner get(fn module_owner) config(): Option; + /// If true, all pallet transactions are failed immediately. + pub IsHalted get(fn is_halted) config(): bool; /// Map of lane id => inbound lane data. pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; /// Map of lane id => outbound lane data. @@ -144,6 +158,9 @@ decl_storage! { /// All queued outbound messages. pub OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; } + add_extra_genesis { + config(phantom): sp_std::marker::PhantomData; + } } decl_event!( @@ -164,6 +181,36 @@ decl_module! { /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; + /// Change `ModuleOwner`. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] + pub fn set_owner(origin, new_owner: Option) { + ensure_owner_or_root::(origin)?; + match new_owner { + Some(new_owner) => ModuleOwner::::put(new_owner), + None => ModuleOwner::::kill(), + } + } + + /// Halt all pallet operations. Operations may be resumed using `resume_operations` call. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] + pub fn halt_operations(origin) { + ensure_owner_or_root::(origin)?; + IsHalted::::put(true); + } + + /// Resume all pallet operations. May be called even if pallet is halted. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] + pub fn resume_operations(origin) { + ensure_owner_or_root::(origin)?; + IsHalted::::put(false); + } + /// Send message over lane. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn send_message( @@ -172,6 +219,7 @@ decl_module! { payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResult { + ensure_operational::()?; let submitter = ensure_signed(origin)?; // let's first check if message can be delivered to target chain @@ -248,6 +296,7 @@ decl_module! { proof: MessagesProofOf, dispatch_weight: Weight, ) -> DispatchResult { + ensure_operational::()?; let _ = ensure_signed(origin)?; // verify messages proof && convert proof into messages @@ -324,6 +373,8 @@ decl_module! { /// Receive messages delivery proof from bridged chain. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn receive_messages_delivery_proof(origin, proof: MessagesDeliveryProofOf) -> DispatchResult { + ensure_operational::()?; + let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { frame_support::debug::trace!( @@ -401,6 +452,24 @@ impl, I: Instance> Module { } } +/// Ensure that the origin is either root, or `ModuleOwner`. +fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<(), BadOrigin> { + match origin.into() { + Ok(RawOrigin::Root) => Ok(()), + Ok(RawOrigin::Signed(ref signer)) if Some(signer) == Module::::module_owner().as_ref() => Ok(()), + _ => Err(BadOrigin), + } +} + +/// Ensure that the pallet is in operational mode (not halted). +fn ensure_operational, I: Instance>() -> Result<(), Error> { + if IsHalted::::get() { + Err(Error::::Halted) + } else { + Ok(()) + } +} + /// Creates new inbound lane object, backed by runtime storage. fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { InboundLane::new(RuntimeInboundLaneStorage { @@ -536,6 +605,7 @@ mod tests { }; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Module as System, Phase}; + use sp_runtime::DispatchError; fn send_regular_message() { System::::set_block_number(1); @@ -587,6 +657,108 @@ mod tests { ); } + #[test] + fn pallet_owner_may_change_owner() { + run_test(|| { + ModuleOwner::::put(2); + + assert_ok!(Module::::set_owner(Origin::root(), Some(1))); + assert_noop!( + Module::::halt_operations(Origin::signed(2)), + DispatchError::BadOrigin, + ); + assert_ok!(Module::::halt_operations(Origin::root())); + + assert_ok!(Module::::set_owner(Origin::signed(1), None)); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + assert_noop!( + Module::::resume_operations(Origin::signed(2)), + DispatchError::BadOrigin, + ); + assert_ok!(Module::::resume_operations(Origin::root())); + }); + } + + #[test] + fn pallet_may_be_halted_by_root() { + run_test(|| { + assert_ok!(Module::::halt_operations(Origin::root())); + assert_ok!(Module::::resume_operations(Origin::root())); + }); + } + + #[test] + fn pallet_may_be_halted_by_owner() { + run_test(|| { + ModuleOwner::::put(2); + + assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_ok!(Module::::resume_operations(Origin::signed(2))); + + assert_noop!( + Module::::halt_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + + assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + }); + } + + #[test] + fn pallet_rejects_transactions_if_halted() { + run_test(|| { + // send message first to be able to check that delivery_proof fails later + send_regular_message(); + + IsHalted::::put(true); + + assert_noop!( + Module::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + REGULAR_PAYLOAD.1, + ), + Error::::Halted, + ); + + assert_noop!( + Module::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + Ok(vec![message(2, REGULAR_PAYLOAD)]).into(), + REGULAR_PAYLOAD.1, + ), + Error::::Halted, + ); + + assert_noop!( + Module::::receive_messages_delivery_proof( + Origin::signed(1), + Ok(( + TEST_LANE_ID, + InboundLaneData { + latest_received_nonce: 1, + ..Default::default() + } + )), + ), + Error::::Halted, + ); + }); + } + #[test] fn send_message_works() { run_test(|| { From 4507b4f5ee08c262e4cf9540d5256f26f1a380c8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 2 Nov 2020 15:01:59 +0300 Subject: [PATCH 0206/1210] Substrate relay guards (#470) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * substrate relay guards * checked time condition * ChainWithBalances * removed obsolete comment * Update relays/substrate-client/src/chain.rs Co-authored-by: Tomasz Drwięga * trailing space Co-authored-by: Tomasz Drwięga --- primitives/runtime/src/chain.rs | 2 +- relays/millau-client/Cargo.toml | 1 + relays/millau-client/src/lib.rs | 19 +- relays/rialto-client/Cargo.toml | 1 + relays/rialto-client/src/lib.rs | 19 +- relays/substrate-client/Cargo.toml | 8 +- relays/substrate-client/src/chain.rs | 28 +- relays/substrate-client/src/client.rs | 53 +++- relays/substrate-client/src/error.rs | 3 + relays/substrate-client/src/guard.rs | 371 ++++++++++++++++++++++++++ relays/substrate-client/src/lib.rs | 3 +- relays/substrate-client/src/rpc.rs | 10 +- 12 files changed, 498 insertions(+), 20 deletions(-) create mode 100644 relays/substrate-client/src/guard.rs diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 2754a8aa7d436..a63d5688d9052 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -23,7 +23,7 @@ use sp_runtime::traits::{ use sp_std::str::FromStr; /// Minimal Substrate-based chain representation that may be used from no_std environment. -pub trait Chain { +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: diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index bf6569d7eed3e..25a27f754fd9e 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -17,6 +17,7 @@ millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies +frame-support = "2.0" frame-system = "2.0" pallet-transaction-payment = "2.0" sp-core = "2.0" diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index 129602cf7a468..e2ab00e4b7b82 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -18,12 +18,13 @@ use codec::Encode; use headers_relay::sync_types::SourceHeader; -use relay_substrate_client::{Chain, ChainBase, Client, TransactionSignScheme}; -use sp_core::Pair; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, Client, TransactionSignScheme}; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedPayload, traits::{Header as HeaderT, IdentifyAccount}, }; +use std::time::Duration; /// Millau header id. pub type HeaderId = relay_utils::HeaderId; @@ -40,12 +41,26 @@ impl ChainBase for Millau { } impl Chain for Millau { + const NAME: &'static str = "Millau"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); + type AccountId = millau_runtime::AccountId; type Index = millau_runtime::Index; type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::Call; } +impl ChainWithBalances for Millau { + type NativeBalance = millau_runtime::Balance; + + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + use frame_support::storage::generator::StorageMap; + StorageKey(frame_system::Account::::storage_map_final_key( + account_id, + )) + } +} + impl TransactionSignScheme for Millau { type Chain = Millau; type AccountKeyPair = sp_core::sr25519::Pair; diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml index 2f4be18a66ee4..7f9b6e9be5f89 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/rialto-client/Cargo.toml @@ -18,6 +18,7 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies frame-system = "2.0" +frame-support = "2.0" pallet-transaction-payment = "2.0" sp-core = "2.0" sp-keyring = "2.0" diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs index 95382cf591d9a..8ab5426803950 100644 --- a/relays/rialto-client/src/lib.rs +++ b/relays/rialto-client/src/lib.rs @@ -18,12 +18,13 @@ use codec::Encode; use headers_relay::sync_types::SourceHeader; -use relay_substrate_client::{Chain, ChainBase, Client, TransactionSignScheme}; -use sp_core::Pair; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, Client, TransactionSignScheme}; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedPayload, traits::{Header as HeaderT, IdentifyAccount}, }; +use std::time::Duration; pub use rialto_runtime::BridgeMillauCall; @@ -42,12 +43,26 @@ impl ChainBase for Rialto { } impl Chain for Rialto { + const NAME: &'static str = "Rialto"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); + type AccountId = rialto_runtime::AccountId; type Index = rialto_runtime::Index; type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::Call; } +impl ChainWithBalances for Rialto { + type NativeBalance = rialto_runtime::Balance; + + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + use frame_support::storage::generator::StorageMap; + StorageKey(frame_system::Account::::storage_map_final_key( + account_id, + )) + } +} + impl TransactionSignScheme for Rialto { type Chain = Rialto; type AccountKeyPair = sp_core::sr25519::Pair; diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 4655ca3db918a..a1de85ec39fbb 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -6,11 +6,13 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "1.3.4" } jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["ws"] } log = "0.4.11" num-traits = "0.2" +rand = "0.7" # Bridge dependencies @@ -22,6 +24,10 @@ relay-utils = { path = "../utils" } frame-support = "2.0" frame-system = "2.0" +pallet-balances = "2.0" sp-core = "2.0" sp-runtime = "2.0" -sp-std = "2.0" +sp-version = "2.0" + +#[dev-dependencies] +futures = "0.3.7" diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index 4418e87d5cc2a..d82845b25e416 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -19,16 +19,24 @@ use crate::client::Client; use bp_runtime::Chain as ChainBase; use frame_support::Parameter; use jsonrpsee::common::{DeserializeOwned, Serialize}; -use sp_core::Pair; +use num_traits::{CheckedSub, Zero}; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, traits::{AtLeast32Bit, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member}, Justification, }; -use sp_std::fmt::Debug; +use std::{fmt::Debug, time::Duration}; /// Substrate-based chain from minimal relay-client point of view. pub trait Chain: ChainBase { + /// Chain name. + const NAME: &'static str; + /// Average block interval. + /// + /// How often blocks are produced on that chain. It's suggested to set this value to match the block time of the chain. + const AVERAGE_BLOCK_INTERVAL: Duration; + /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; /// Account index (aka nonce) type. This stores the number of previous transactions associated @@ -40,6 +48,16 @@ pub trait Chain: ChainBase { type Call: Dispatchable + Debug; } +/// Substrate-based chain with `frame_system::Trait::AccountData` set to +/// the `pallet_balances::AccountData`. +pub trait ChainWithBalances: Chain { + /// Balance of an account in native tokens. + type NativeBalance: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + Zero; + + /// Return runtime storage key for getting `frame_system::AccountInfo` of given account. + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey; +} + /// Block with justification. pub trait BlockWithJustification { /// Return block justification, if known. @@ -64,6 +82,12 @@ pub trait TransactionSignScheme { ) -> Self::SignedTransaction; } +impl BlockWithJustification for () { + fn justification(&self) -> Option<&Justification> { + None + } +} + impl BlockWithJustification for SignedBlock { fn justification(&self) -> Option<&Justification> { self.justification.as_ref() diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 64994505ab073..05a0da47ebe88 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -16,16 +16,21 @@ //! Substrate node client. -use crate::chain::Chain; +use crate::chain::{Chain, ChainWithBalances}; +use crate::error::Error; use crate::rpc::Substrate; use crate::{ConnectionParams, Result}; +use codec::Decode; +use frame_system::AccountInfo; use jsonrpsee::common::DeserializeOwned; use jsonrpsee::raw::RawClient; use jsonrpsee::transport::ws::WsTransportClient; use jsonrpsee::{client::Subscription, Client as RpcClient}; use num_traits::Zero; +use pallet_balances::AccountData; use sp_core::Bytes; +use sp_version::RuntimeVersion; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; @@ -69,18 +74,17 @@ impl Client { } } -impl Client -where - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, -{ +impl Client { /// Return hash of the genesis block. pub fn genesis_hash(&self) -> &C::Hash { &self.genesis_hash } /// Returns the best Substrate header. - pub async fn best_header(&self) -> Result { + pub async fn best_header(&self) -> Result + where + C::Header: DeserializeOwned, + { Ok(Substrate::::chain_get_header(&self.client, None).await?) } @@ -90,7 +94,10 @@ where } /// Get a Substrate header by its hash. - pub async fn header_by_hash(&self, block_hash: C::Hash) -> Result { + pub async fn header_by_hash(&self, block_hash: C::Hash) -> Result + where + C::Header: DeserializeOwned, + { Ok(Substrate::::chain_get_header(&self.client, block_hash).await?) } @@ -100,15 +107,41 @@ where } /// Get a Substrate header by its number. - pub async fn header_by_number(&self, block_number: C::BlockNumber) -> Result { + pub async fn header_by_number(&self, block_number: C::BlockNumber) -> Result + where + C::Header: DeserializeOwned, + { let block_hash = Self::block_hash_by_number(self, block_number).await?; Ok(Self::header_by_hash(self, block_hash).await?) } + /// Return runtime version. + pub async fn runtime_version(&self) -> Result { + Ok(Substrate::::runtime_version(&self.client).await?) + } + + /// Return native tokens balance of the account. + pub async fn free_native_balance(&self, account: C::AccountId) -> Result + where + C: ChainWithBalances, + { + let storage_key = C::account_info_storage_key(&account); + let encoded_account_data = Substrate::::get_storage(&self.client, storage_key) + .await? + .ok_or(Error::AccountDoesNotExist)?; + let decoded_account_data = + AccountInfo::>::decode(&mut &encoded_account_data.0[..]) + .map_err(Error::ResponseParseFailed)?; + Ok(decoded_account_data.data.free) + } + /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. - pub async fn next_account_index(&self, account: C::AccountId) -> Result { + pub async fn next_account_index(&self, account: C::AccountId) -> Result + where + C::Index: DeserializeOwned, + { Ok(Substrate::::system_account_next_index(&self.client, account).await?) } diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index 319027440b180..5f41af9aacc33 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -34,6 +34,8 @@ pub enum Error { Request(RequestError), /// The response from the server could not be SCALE decoded. ResponseParseFailed(codec::Error), + /// Account does not exist on the chain. + AccountDoesNotExist, } impl From for Error { @@ -66,6 +68,7 @@ impl ToString for Error { Self::WsConnectionError(e) => e.to_string(), Self::Request(e) => e.to_string(), Self::ResponseParseFailed(e) => e.what().to_string(), + Self::AccountDoesNotExist => "Account does not exist on the chain".into(), } } } diff --git a/relays/substrate-client/src/guard.rs b/relays/substrate-client/src/guard.rs new file mode 100644 index 0000000000000..d439ec890763d --- /dev/null +++ b/relays/substrate-client/src/guard.rs @@ -0,0 +1,371 @@ +// Copyright 2019-2020 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 . + +//! Module provides a set of guard functions that are running in background threads +//! and are aborting process if some condition fails. + +use crate::{Chain, ChainWithBalances, Client}; + +use async_trait::async_trait; +use num_traits::CheckedSub; +use sp_version::RuntimeVersion; +use std::{ + collections::VecDeque, + time::{Duration, Instant}, +}; + +/// Guards environment. +#[async_trait] +pub trait Environment: Send + Sync + 'static { + /// Return current runtime version. + async fn runtime_version(&mut self) -> Result; + /// Return free native balance of the account on the chain. + async fn free_native_balance(&mut self, account: C::AccountId) -> Result; + + /// Return current time. + fn now(&self) -> Instant { + Instant::now() + } + /// Sleep given amount of time. + async fn sleep(&mut self, duration: Duration) { + async_std::task::sleep(duration).await + } + /// Abort current process. Called when guard condition check fails. + async fn abort(&mut self) { + std::process::abort(); + } +} + +/// Abort when runtime spec version is different from specified. +pub fn abort_on_spec_version_change(mut env: impl Environment, expected_spec_version: u32) { + async_std::task::spawn(async move { + loop { + let actual_spec_version = env.runtime_version().await; + match actual_spec_version { + Ok(version) if version.spec_version == expected_spec_version => (), + Ok(version) => { + log::error!( + target: "bridge-guard", + "{} runtime spec version has changed from {} to {}. Aborting relay", + C::NAME, + expected_spec_version, + version.spec_version, + ); + + env.abort().await; + } + Err(error) => log::warn!( + target: "bridge-guard", + "Failed to read {} runtime version: {:?}. Relay may need to be stopped manually", + C::NAME, + error, + ), + } + + env.sleep(conditions_check_delay::()).await; + } + }); +} + +/// Abort if, during a 24 hours, free balance of given account is decreased at least by given value. +/// Other components may increase (or decrease) balance of account and it WILL affect logic of the guard. +pub fn abort_when_account_balance_decreased( + mut env: impl Environment, + account_id: C::AccountId, + maximal_decrease: C::NativeBalance, +) { + const DAY: Duration = Duration::from_secs(60 * 60 * 24); + + async_std::task::spawn(async move { + let mut balances = VecDeque::new(); + + loop { + let current_time = env.now(); + + // remember balances that are beyound 24h border + let time_border = current_time - DAY; + while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) { + balances.pop_front(); + } + + // read balance of the account + let current_balance = env.free_native_balance(account_id.clone()).await; + + // remember balance and check difference + match current_balance { + Ok(current_balance) => { + // remember balance + balances.push_back((current_time, current_balance)); + + // check if difference between current and oldest balance is too large + let (oldest_time, oldest_balance) = + balances.front().expect("pushed to queue couple of lines above; qed"); + let balances_difference = oldest_balance.checked_sub(¤t_balance); + if balances_difference > Some(maximal_decrease) { + log::error!( + target: "bridge-guard", + "Balance of {} account {:?} has decreased from {:?} to {:?} in {} minutes. Aborting relay", + C::NAME, + account_id, + oldest_balance, + current_balance, + current_time.duration_since(*oldest_time).as_secs() / 60, + ); + + env.abort().await; + } + } + Err(error) => { + log::warn!( + target: "bridge-guard", + "Failed to read {} account {:?} balance: {:?}. Relay may need to be stopped manually", + C::NAME, + account_id, + error, + ); + } + }; + + env.sleep(conditions_check_delay::()).await; + } + }); +} + +/// Delay between conditions check. +fn conditions_check_delay() -> Duration { + C::AVERAGE_BLOCK_INTERVAL * (10 + rand::random::() % 10) +} + +#[async_trait] +impl Environment for Client { + async fn runtime_version(&mut self) -> Result { + Client::::runtime_version(self).await.map_err(|e| e.to_string()) + } + + async fn free_native_balance(&mut self, account: C::AccountId) -> Result { + Client::::free_native_balance(self, account) + .await + .map_err(|e| e.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::{ + channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, + future::FutureExt, + stream::StreamExt, + SinkExt, + }; + + struct TestChain; + + impl bp_runtime::Chain for TestChain { + type BlockNumber = u32; + type Hash = sp_core::H256; + type Hasher = sp_runtime::traits::BlakeTwo256; + type Header = sp_runtime::generic::Header; + } + + impl Chain for TestChain { + const NAME: &'static str = "Test"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); + + type AccountId = u32; + type Index = u32; + type SignedBlock = (); + type Call = (); + } + + impl ChainWithBalances for TestChain { + type NativeBalance = u32; + + fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey { + unreachable!() + } + } + + struct TestEnvironment { + runtime_version_rx: UnboundedReceiver, + free_native_balance_rx: UnboundedReceiver, + slept_tx: UnboundedSender<()>, + aborted_tx: UnboundedSender<()>, + } + + #[async_trait] + impl Environment for TestEnvironment { + async fn runtime_version(&mut self) -> Result { + Ok(self.runtime_version_rx.next().await.unwrap_or_default()) + } + + async fn free_native_balance(&mut self, _account: u32) -> Result { + Ok(self.free_native_balance_rx.next().await.unwrap_or_default()) + } + + async fn sleep(&mut self, _duration: Duration) { + let _ = self.slept_tx.send(()).await; + } + + async fn abort(&mut self) { + let _ = self.aborted_tx.send(()).await; + // simulate process abort :) + async_std::task::sleep(Duration::from_secs(60)).await; + } + } + + #[test] + fn aborts_when_spec_version_is_changed() { + async_std::task::block_on(async { + let ( + (mut runtime_version_tx, runtime_version_rx), + (_free_native_balance_tx, free_native_balance_rx), + (slept_tx, mut slept_rx), + (aborted_tx, mut aborted_rx), + ) = (unbounded(), unbounded(), unbounded(), unbounded()); + abort_on_spec_version_change( + TestEnvironment { + runtime_version_rx, + free_native_balance_rx, + slept_tx, + aborted_tx, + }, + 0, + ); + + // client responds with wrong version + runtime_version_tx + .send(RuntimeVersion { + spec_version: 42, + ..Default::default() + }) + .await + .unwrap(); + + // then the `abort` function is called + aborted_rx.next().await; + // and we do not reach the `sleep` function call + assert!(slept_rx.next().now_or_never().is_none()); + }); + } + + #[test] + fn does_not_aborts_when_spec_version_is_unchanged() { + async_std::task::block_on(async { + let ( + (mut runtime_version_tx, runtime_version_rx), + (_free_native_balance_tx, free_native_balance_rx), + (slept_tx, mut slept_rx), + (aborted_tx, mut aborted_rx), + ) = (unbounded(), unbounded(), unbounded(), unbounded()); + abort_on_spec_version_change( + TestEnvironment { + runtime_version_rx, + free_native_balance_rx, + slept_tx, + aborted_tx, + }, + 42, + ); + + // client responds with the same version + runtime_version_tx + .send(RuntimeVersion { + spec_version: 42, + ..Default::default() + }) + .await + .unwrap(); + + // then the `sleep` function is called + slept_rx.next().await; + // and the `abort` function is not called + assert!(aborted_rx.next().now_or_never().is_none()); + }); + } + + #[test] + fn aborts_when_balance_is_too_low() { + async_std::task::block_on(async { + let ( + (_runtime_version_tx, runtime_version_rx), + (mut free_native_balance_tx, free_native_balance_rx), + (slept_tx, mut slept_rx), + (aborted_tx, mut aborted_rx), + ) = (unbounded(), unbounded(), unbounded(), unbounded()); + abort_when_account_balance_decreased( + TestEnvironment { + runtime_version_rx, + free_native_balance_rx, + slept_tx, + aborted_tx, + }, + 0, + 100, + ); + + // client responds with initial balance + free_native_balance_tx.send(1000).await.unwrap(); + + // then the guard sleeps + slept_rx.next().await; + + // and then client responds with updated balance, which is too low + free_native_balance_tx.send(899).await.unwrap(); + + // then the `abort` function is called + aborted_rx.next().await; + // and we do not reach next `sleep` function call + assert!(slept_rx.next().now_or_never().is_none()); + }); + } + + #[test] + fn does_not_aborts_when_balance_is_enough() { + async_std::task::block_on(async { + let ( + (_runtime_version_tx, runtime_version_rx), + (mut free_native_balance_tx, free_native_balance_rx), + (slept_tx, mut slept_rx), + (aborted_tx, mut aborted_rx), + ) = (unbounded(), unbounded(), unbounded(), unbounded()); + abort_when_account_balance_decreased( + TestEnvironment { + runtime_version_rx, + free_native_balance_rx, + slept_tx, + aborted_tx, + }, + 0, + 100, + ); + + // client responds with initial balance + free_native_balance_tx.send(1000).await.unwrap(); + + // then the guard sleeps + slept_rx.next().await; + + // and then client responds with updated balance, which is enough + free_native_balance_tx.send(950).await.unwrap(); + + // then the `sleep` function is called + slept_rx.next().await; + // and `abort` is not called + assert!(aborted_rx.next().now_or_never().is_none()); + }); + } +} diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index adee027d51e51..b92e6d02885ec 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -23,9 +23,10 @@ mod client; mod error; mod rpc; +pub mod guard; pub mod headers_source; -pub use crate::chain::{BlockWithJustification, Chain, TransactionSignScheme}; +pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme}; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; diff --git a/relays/substrate-client/src/rpc.rs b/relays/substrate-client/src/rpc.rs index 60141e0df660a..552b20de622b5 100644 --- a/relays/substrate-client/src/rpc.rs +++ b/relays/substrate-client/src/rpc.rs @@ -23,7 +23,11 @@ use crate::chain::Chain; -use sp_core::Bytes; +use sp_core::{ + storage::{StorageData, StorageKey}, + Bytes, +}; +use sp_version::RuntimeVersion; jsonrpsee::rpc_api! { pub(crate) Substrate { @@ -39,5 +43,9 @@ jsonrpsee::rpc_api! { fn author_submit_extrinsic(extrinsic: Bytes) -> C::Hash; #[rpc(method = "state_call", positional_params)] fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; + #[rpc(method = "state_getStorage", positional_params)] + fn get_storage(key: StorageKey) -> Option; + #[rpc(method = "state_getRuntimeVersion", positional_params)] + fn runtime_version() -> RuntimeVersion; } } From ab90d92630f76604a6d6dbbe4aea187a12dd4e11 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 3 Nov 2020 11:15:17 +0300 Subject: [PATCH 0207/1210] Rialto -> Millau headers relay (#477) * Rialto -> Millau headers relay * removed more constraints * removed file from other PR * Update primitives/rialto/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 2 +- primitives/rialto/src/lib.rs | 13 +- primitives/runtime/src/chain.rs | 2 +- relays/ethereum/src/ethereum_exchange.rs | 8 +- relays/ethereum/src/ethereum_sync_loop.rs | 8 +- relays/ethereum/src/substrate_sync_loop.rs | 7 +- relays/headers-relay/src/sync_types.rs | 4 +- relays/millau-client/src/lib.rs | 2 + relays/rialto-client/src/lib.rs | 6 + relays/substrate-client/src/chain.rs | 13 +- relays/substrate-client/src/client.rs | 5 +- relays/substrate-client/src/headers_source.rs | 4 +- relays/substrate/Cargo.toml | 1 + relays/substrate/src/cli.rs | 11 ++ relays/substrate/src/headers_maintain.rs | 9 +- relays/substrate/src/headers_pipeline.rs | 140 ++++++++++++++++++ relays/substrate/src/headers_target.rs | 4 +- relays/substrate/src/main.rs | 25 ++++ .../substrate/src/millau_headers_to_rialto.rs | 113 +++----------- .../substrate/src/rialto_headers_to_millau.rs | 88 +++++++++++ 20 files changed, 337 insertions(+), 128 deletions(-) create mode 100644 relays/substrate/src/headers_pipeline.rs create mode 100644 relays/substrate/src/rialto_headers_to_millau.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1e5a8feddeaf0..faad5153d8223 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -57,7 +57,7 @@ pub use frame_support::{ pub use pallet_balances::Call as BalancesCall; pub use pallet_message_lane::Call as MessageLaneCall; -pub use pallet_substrate_bridge::Call as BridgeSubstrateCall; +pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 426c5c4f1f893..b024dc66c3a97 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -29,11 +29,11 @@ use sp_runtime::{ }; use sp_std::prelude::*; -/// Maximal weight of single Millau block. +/// Maximal weight of single Rialto block. pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2_000_000_000_000; /// Portion of block reserved for regular transactions. pub const AVAILABLE_BLOCK_RATIO: u32 = 75; -/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular +/// Maximal weight of single Rialto extrinsic (65% of maximum block weight = 75% for regular /// transactions minus 10% for initialization). pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); @@ -60,6 +60,15 @@ impl Chain for Rialto { type Header = Header; } +/// Name of the `RialtoHeaderApi::best_blocks` runtime method. +pub const BEST_RIALTO_BLOCKS_METHOD: &str = "RialtoHeaderApi_best_blocks"; +/// Name of the `RialtoHeaderApi::finalized_block` runtime method. +pub const FINALIZED_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_finalized_block"; +/// Name of the `RialtoHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; +/// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; + /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index a63d5688d9052..706e56f667ecd 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -70,7 +70,7 @@ 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; + type Header: Parameter + HeaderT + MaybeSerializeDeserialize; } /// Block number used by the chain. diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index c8b8a7a7e8ebf..870de74f7835a 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -36,15 +36,15 @@ use relay_ethereum_client::{ Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; +use relay_substrate_client::{ + Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, +}; use relay_utils::{metrics::MetricsParams, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::{sync::Arc, time::Duration}; /// Interval at which we ask Ethereum node for updates. const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); -/// Interval at which we ask Substrate node for updates. -const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Exchange relay mode. #[derive(Debug)] @@ -210,7 +210,7 @@ impl TargetClient for SubstrateTransactionsTarget { type Error = RpcError; async fn tick(&self) { - async_std::task::sleep(SUBSTRATE_TICK_INTERVAL).await; + async_std::task::sleep(Rialto::AVERAGE_BLOCK_INTERVAL).await; } async fn is_header_known(&self, id: &EthereumHeaderId) -> Result { diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index c2dd0b2d1e19d..ec0c95c70ca72 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -34,7 +34,9 @@ use relay_ethereum_client::{ Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams}; +use relay_substrate_client::{ + Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, +}; use relay_utils::metrics::MetricsParams; use std::fmt::Debug; @@ -45,8 +47,6 @@ pub mod consts { /// Interval at which we check new Ethereum headers when we are synced/almost synced. pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); - /// Interval at which we check new Substrate blocks. - pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max number of headers in single submit transaction. pub const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; /// Max total size of headers in single submit transaction. This only affects signed @@ -253,7 +253,7 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { source, consts::ETHEREUM_TICK_INTERVAL, target, - consts::SUBSTRATE_TICK_INTERVAL, + Rialto::AVERAGE_BLOCK_INTERVAL, (), sync_params, metrics_params, diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index fcc6e2786b563..7ca9d797dfe55 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -32,7 +32,8 @@ use relay_ethereum_client::{ }; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; use relay_substrate_client::{ - headers_source::HeadersSource, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, + headers_source::HeadersSource, Chain as SubstrateChain, Client as SubstrateClient, + ConnectionParams as SubstrateConnectionParams, }; use relay_utils::metrics::MetricsParams; use sp_runtime::Justification; @@ -43,8 +44,6 @@ use std::{collections::HashSet, time::Duration}; pub mod consts { use super::*; - /// Interval at which we check new Substrate headers when we are synced/almost synced. - pub const SUBSTRATE_TICK_INTERVAL: Duration = Duration::from_secs(10); /// Interval at which we check new Ethereum blocks. pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); /// Max Ethereum headers we want to have in all 'before-submitted' states. @@ -174,7 +173,7 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { headers_relay::sync_loop::run( source, - consts::SUBSTRATE_TICK_INTERVAL, + Rialto::AVERAGE_BLOCK_INTERVAL, target, consts::ETHEREUM_TICK_INTERVAL, (), diff --git a/relays/headers-relay/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs index 54a41a8aaa571..958c81dd911ed 100644 --- a/relays/headers-relay/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -68,7 +68,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { + num_traits::One + Into; /// Type of header that we're syncing. - type Header: Clone + std::fmt::Debug + PartialEq + SourceHeader + Send + Sync; + type Header: SourceHeader; /// Type of extra data for the header that we're receiving from the source node: /// 1) extra data is required for some headers; /// 2) target node may answer if it'll require extra data before header is submitted; @@ -94,7 +94,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { pub type HeaderIdOf

= HeaderId<

::Hash,

::Number>; /// Header that we're receiving from source node. -pub trait SourceHeader { +pub trait SourceHeader: Clone + std::fmt::Debug + PartialEq + Send + Sync { /// Returns ID of header. fn id(&self) -> HeaderId; /// Returns ID of parent header. diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index e2ab00e4b7b82..9c018a8419a41 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -26,6 +26,8 @@ use sp_runtime::{ }; use std::time::Duration; +pub use millau_runtime::BridgeRialtoCall; + /// Millau header id. pub type HeaderId = relay_utils::HeaderId; diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs index 8ab5426803950..f45408d1538a4 100644 --- a/relays/rialto-client/src/lib.rs +++ b/relays/rialto-client/src/lib.rs @@ -151,6 +151,12 @@ impl From for SyncHeader { } } +impl From for rialto_runtime::Header { + fn from(header: SyncHeader) -> Self { + header.0 + } +} + impl SourceHeader for SyncHeader { fn id(&self) -> HeaderId { relay_utils::HeaderId(*self.number(), self.hash()) diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index d82845b25e416..1de2bf401f13b 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -34,14 +34,23 @@ pub trait Chain: ChainBase { const NAME: &'static str; /// Average block interval. /// - /// How often blocks are produced on that chain. It's suggested to set this value to match the block time of the chain. + /// How often blocks are produced on that chain. It's suggested to set this value + /// to match the block time of the chain. const AVERAGE_BLOCK_INTERVAL: Duration; /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; /// Account index (aka nonce) type. This stores the number of previous transactions associated /// with a sender account. - type Index: Parameter + Member + MaybeSerialize + Debug + Default + MaybeDisplay + AtLeast32Bit + Copy; + type Index: Parameter + + Member + + MaybeSerialize + + Debug + + Default + + MaybeDisplay + + DeserializeOwned + + AtLeast32Bit + + Copy; /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 05a0da47ebe88..9ff54c4b3ab2c 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -138,10 +138,7 @@ impl Client { /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. - pub async fn next_account_index(&self, account: C::AccountId) -> Result - where - C::Index: DeserializeOwned, - { + pub async fn next_account_index(&self, account: C::AccountId) -> Result { Ok(Substrate::::system_account_next_index(&self.client, account).await?) } diff --git a/relays/substrate-client/src/headers_source.rs b/relays/substrate-client/src/headers_source.rs index 14be6e0e65cbb..b9b46774ce588 100644 --- a/relays/substrate-client/src/headers_source.rs +++ b/relays/substrate-client/src/headers_source.rs @@ -25,7 +25,6 @@ use headers_relay::{ sync_loop::SourceClient, sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; -use jsonrpsee::common::DeserializeOwned; use num_traits::Saturating; use sp_runtime::{traits::Header as HeaderT, Justification}; use std::marker::PhantomData; @@ -51,8 +50,7 @@ impl SourceClient

for HeadersSource where C: Chain, C::BlockNumber: Into + Saturating, - C::Header: DeserializeOwned + Into, - C::Index: DeserializeOwned, + C::Header: Into, P: HeadersSyncPipeline, P::Header: SourceHeader, { diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 3a760ffde86bf..c5dca17c9fab2 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.7" hex = "0.4" log = "0.4.11" +num-traits = "0.2" paste = "1.0" structopt = "0.3" diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index ec081cd1d2780..cff2d36211108 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -39,6 +39,17 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, + /// Relay Rialto headers to Millau. + RialtoHeadersToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + }, /// Submit message to given Rialto -> Millau lane. SubmitMillauToRialtoMessage { #[structopt(flatten)] diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index e5e7c7023cda1..af3196b375b27 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -43,7 +43,7 @@ use headers_relay::{ use relay_substrate_client::{Chain, Client, Error as SubstrateError, JustificationsSubscription}; use relay_utils::HeaderId; use sp_core::Bytes; -use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, Justification}; +use sp_runtime::{traits::Header as HeaderT, Justification}; use std::{collections::VecDeque, task::Poll}; /// Substrate-to-Substrate headers synchronization maintain procedure. @@ -80,8 +80,6 @@ impl SubstrateHeadersToSubstrateMaint impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain where C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, P::Number: Decode + From, P::Hash: Decode + From, P: SubstrateHeadersSyncPipeline, @@ -271,8 +269,6 @@ where P::Number: Decode + From, P::Hash: Decode + From, C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, { let call = P::FINALIZED_BLOCK_METHOD.into(); let data = Bytes(Vec::new()); @@ -288,7 +284,8 @@ where #[cfg(test)] mod tests { use super::*; - use crate::millau_headers_to_rialto::{sync_params, MillauHeadersToRialto}; + use crate::headers_pipeline::sync_params; + use crate::millau_headers_to_rialto::MillauHeadersToRialto; fn parent_hash(index: u8) -> bp_millau::Hash { if index == 1 { diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs new file mode 100644 index 0000000000000..3a6348961fb71 --- /dev/null +++ b/relays/substrate/src/headers_pipeline.rs @@ -0,0 +1,140 @@ +// Copyright 2019-2020 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 . + +//! Substrate-to-Substrate headers sync entrypoint. + +use crate::{ + headers_maintain::SubstrateHeadersToSubstrateMaintain, + headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, +}; + +use codec::Encode; +use headers_relay::{ + sync::{HeadersSyncParams, TargetTransactionMode}, + sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}, +}; +use num_traits::Saturating; +use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, HashOf}; +use sp_runtime::Justification; +use std::marker::PhantomData; + +/// Substrate-to-Substrate headers pipeline. +#[derive(Debug, Clone)] +pub struct SubstrateHeadersToSubstrate { + /// Client for the target chain. + pub(crate) target_client: Client, + /// Data required to sign target chain transactions. + pub(crate) target_sign: TargetSign, + /// Unused generic arguments dump. + _marker: PhantomData<(SourceChain, SourceSyncHeader)>, +} + +impl + SubstrateHeadersToSubstrate +{ + /// Create new Substrate-to-Substrate headers pipeline. + pub fn new(target_client: Client, target_sign: TargetSign) -> Self { + SubstrateHeadersToSubstrate { + target_client, + target_sign, + _marker: Default::default(), + } + } +} + +impl HeadersSyncPipeline + for SubstrateHeadersToSubstrate +where + SourceChain: Clone + Chain, + BlockNumberOf: Saturating + Into, + SourceSyncHeader: + SourceHeader, BlockNumberOf> + std::ops::Deref, + TargetChain: Clone + Chain, + TargetSign: Clone + Send + Sync, +{ + const SOURCE_NAME: &'static str = SourceChain::NAME; + const TARGET_NAME: &'static str = TargetChain::NAME; + + type Hash = HashOf; + type Number = BlockNumberOf; + type Header = SourceSyncHeader; + type Extra = (); + type Completion = Justification; + + fn estimate_size(source: &QueuedHeader) -> usize { + source.header().encode().len() + } +} + +/// Return sync parameters for Substrate-to-Substrate headers sync. +pub fn sync_params() -> HeadersSyncParams { + HeadersSyncParams { + max_future_headers_to_download: 32, + max_headers_in_submitted_status: 8, + max_headers_in_single_submit: 1, + max_headers_size_in_single_submit: 1024 * 1024, + prune_depth: 256, + target_tx_mode: TargetTransactionMode::Signed, + } +} + +/// Run Substrate-to-Substrate headers sync. +pub async fn run( + pipeline: P, + source_client: Client, + target_client: Client, + metrics_params: Option, +) where + P: SubstrateHeadersSyncPipeline< + Hash = HashOf, + Number = BlockNumberOf, + Completion = Justification, + Extra = (), + >, + P::Header: SourceHeader, BlockNumberOf>, + SourceChain: Clone + Chain, + SourceChain::Header: Into, + BlockNumberOf: Into + Saturating, + TargetChain: Clone + Chain, +{ + let source_justifications = match source_client.clone().subscribe_justifications().await { + Ok(source_justifications) => source_justifications, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to subscribe to {} justifications: {:?}", + SourceChain::NAME, + error, + ); + + return; + } + }; + + let sync_maintain = + SubstrateHeadersToSubstrateMaintain::new(pipeline.clone(), source_client.clone(), source_justifications); + + headers_relay::sync_loop::run( + HeadersSource::new(source_client), + SourceChain::AVERAGE_BLOCK_INTERVAL, + SubstrateHeadersTarget::new(target_client, pipeline), + TargetChain::AVERAGE_BLOCK_INTERVAL, + sync_maintain, + sync_params(), + metrics_params, + futures::future::pending(), + ); +} diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index a6502f407fa4b..6f23706d171cb 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -28,7 +28,7 @@ use headers_relay::{ use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_utils::HeaderId; use sp_core::Bytes; -use sp_runtime::{DeserializeOwned, Justification}; +use sp_runtime::Justification; use std::collections::HashSet; /// Headers sync pipeline for Substrate <-> Substrate relays. @@ -77,8 +77,6 @@ impl SubstrateHeadersTarget { impl TargetClient

for SubstrateHeadersTarget where C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, P::Number: Decode, P::Hash: Decode + Encode, P: SubstrateHeadersSyncPipeline, diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 76b2aa9189dde..6d36e7606159e 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -34,8 +34,10 @@ pub type RialtoClient = relay_substrate_client::Client; mod cli; mod headers_maintain; +mod headers_pipeline; mod headers_target; mod millau_headers_to_rialto; +mod rialto_headers_to_millau; fn main() { initialize_relay(); @@ -71,6 +73,29 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; } + cli::Command::RialtoHeadersToMillau { + rialto, + millau, + millau_sign, + prometheus_params, + } => { + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; + } cli::Command::SubmitMillauToRialtoMessage { millau, millau_sign, diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 7bf504bcfe968..a07138e019367 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -17,9 +17,8 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::{ - headers_maintain::SubstrateHeadersToSubstrateMaintain, - headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, - MillauClient, RialtoClient, + headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, + RialtoClient, }; use async_trait::async_trait; @@ -27,41 +26,18 @@ use bp_millau::{ BEST_MILLAU_BLOCKS_METHOD, FINALIZED_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, IS_KNOWN_MILLAU_BLOCK_METHOD, }; -use codec::Encode; -use headers_relay::{ - sync::{HeadersSyncParams, TargetTransactionMode}, - sync_types::{HeadersSyncPipeline, QueuedHeader}, -}; +use headers_relay::sync_types::QueuedHeader; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{BridgeMillauCall, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - headers_source::HeadersSource, BlockNumberOf, Error as SubstrateError, HashOf, TransactionSignScheme, -}; +use relay_substrate_client::{Error as SubstrateError, TransactionSignScheme}; use sp_core::Pair; use sp_runtime::Justification; -use std::time::Duration; - -/// Millau-to-Rialto headers pipeline. -#[derive(Debug, Clone)] -pub struct MillauHeadersToRialto { - client: RialtoClient, - sign: RialtoSigningParams, -} - -impl HeadersSyncPipeline for MillauHeadersToRialto { - const SOURCE_NAME: &'static str = "Millau"; - const TARGET_NAME: &'static str = "Rialto"; - - type Hash = HashOf; - type Number = BlockNumberOf; - type Header = MillauSyncHeader; - type Extra = (); - type Completion = Justification; - fn estimate_size(source: &QueuedHeader) -> usize { - source.header().encode().len() - } -} +/// Millau-to-Rialto headers sync pipeline. +pub(crate) type MillauHeadersToRialto = + SubstrateHeadersToSubstrate; +/// Millau header in-the-queue. +type QueuedMillauHeader = QueuedHeader; #[async_trait] impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { @@ -76,10 +52,10 @@ impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { &self, header: QueuedMillauHeader, ) -> Result { - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; let call = BridgeMillauCall::import_signed_header(header.header().clone().into()).into(); - let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } @@ -88,35 +64,14 @@ impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { id: MillauHeaderId, completion: Justification, ) -> Result { - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; let call = BridgeMillauCall::finalize_header(id.1, completion).into(); - let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } } -/// Millau header in-the-queue. -type QueuedMillauHeader = QueuedHeader; - -/// Millau node as headers source. -type MillauSourceClient = HeadersSource; - -/// Rialto node as headers target. -type RialtoTargetClient = SubstrateHeadersTarget; - -/// Return sync parameters for Millau-to-Rialto headers sync. -pub fn sync_params() -> HeadersSyncParams { - HeadersSyncParams { - max_future_headers_to_download: 32, - max_headers_in_submitted_status: 8, - max_headers_in_single_submit: 1, - max_headers_size_in_single_submit: 1024 * 1024, - prune_depth: 256, - target_tx_mode: TargetTransactionMode::Signed, - } -} - /// Run Millau-to-Rialto headers sync. pub async fn run( millau_client: MillauClient, @@ -124,37 +79,11 @@ pub async fn run( rialto_sign: RialtoSigningParams, metrics_params: Option, ) { - let millau_tick = Duration::from_secs(5); - let rialto_tick = Duration::from_secs(5); - - let millau_justifications = match millau_client.clone().subscribe_justifications().await { - Ok(millau_justifications) => millau_justifications, - Err(error) => { - log::warn!( - target: "bridge", - "Failed to subscribe to Millau justifications: {:?}", - error, - ); - - return; - } - }; - - let pipeline = MillauHeadersToRialto { - client: rialto_client.clone(), - sign: rialto_sign, - }; - let sync_maintain = - SubstrateHeadersToSubstrateMaintain::new(pipeline.clone(), rialto_client.clone(), millau_justifications); - - headers_relay::sync_loop::run( - MillauSourceClient::new(millau_client), - millau_tick, - RialtoTargetClient::new(rialto_client, pipeline), - rialto_tick, - sync_maintain, - sync_params(), + crate::headers_pipeline::run( + MillauHeadersToRialto::new(rialto_client.clone(), rialto_sign), + millau_client, + rialto_client, metrics_params, - futures::future::pending(), - ); + ) + .await; } diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs new file mode 100644 index 0000000000000..f458e291244d4 --- /dev/null +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -0,0 +1,88 @@ +// Copyright 2019-2020 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 . + +//! Rialto-to-Millau headers sync entrypoint. + +use crate::{ + headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, + RialtoClient, +}; + +use async_trait::async_trait; +use bp_rialto::{ + BEST_RIALTO_BLOCKS_METHOD, FINALIZED_RIALTO_BLOCK_METHOD, INCOMPLETE_RIALTO_HEADERS_METHOD, + IS_KNOWN_RIALTO_BLOCK_METHOD, +}; +use headers_relay::sync_types::QueuedHeader; +use relay_millau_client::{BridgeRialtoCall, Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; +use relay_substrate_client::{Error as SubstrateError, TransactionSignScheme}; +use sp_core::Pair; +use sp_runtime::Justification; + +/// Rialto-to-Millau headers sync pipeline. +type RialtoHeadersToMillau = SubstrateHeadersToSubstrate; +/// Rialto header in-the-queue. +type QueuedRialtoHeader = QueuedHeader; + +#[async_trait] +impl SubstrateHeadersSyncPipeline for RialtoHeadersToMillau { + const BEST_BLOCK_METHOD: &'static str = BEST_RIALTO_BLOCKS_METHOD; + const FINALIZED_BLOCK_METHOD: &'static str = FINALIZED_RIALTO_BLOCK_METHOD; + const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_RIALTO_BLOCK_METHOD; + const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_RIALTO_HEADERS_METHOD; + + type SignedTransaction = ::SignedTransaction; + + async fn make_submit_header_transaction( + &self, + header: QueuedRialtoHeader, + ) -> Result { + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + let call = BridgeRialtoCall::import_signed_header(header.header().clone().into()).into(); + let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + Ok(transaction) + } + + async fn make_complete_header_transaction( + &self, + id: RialtoHeaderId, + completion: Justification, + ) -> Result { + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + let call = BridgeRialtoCall::finalize_header(id.1, completion).into(); + let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + Ok(transaction) + } +} + +/// Run Rialto-to-Millau headers sync. +pub async fn run( + rialto_client: RialtoClient, + millau_client: MillauClient, + millau_sign: MillauSigningParams, + metrics_params: Option, +) { + crate::headers_pipeline::run( + RialtoHeadersToMillau::new(millau_client.clone(), millau_sign), + rialto_client, + millau_client, + metrics_params, + ) + .await; +} From c85ddde9c09eac28b5b8ab198d9140960d55f6c4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 3 Nov 2020 13:45:39 +0300 Subject: [PATCH 0208/1210] is_finalized_header - use is_finalized flag (#476) --- modules/substrate/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 62a44e0a62c3f..0daed1db3e23e 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -251,7 +251,7 @@ impl Module { pub fn is_finalized_header(hash: BridgedBlockHash) -> bool { let storage = PalletStorage::::new(); if let Some(header) = storage.header_by_hash(hash) { - header.number() <= storage.best_finalized_header().number() + header.is_finalized } else { false } From 7b5a0824b224816925dc5168a265a8b22cdedf80 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 5 Nov 2020 11:18:15 +0300 Subject: [PATCH 0209/1210] Parse substrate message proof (#479) * parse substrate message proof * unfinalized_header --- modules/substrate/src/lib.rs | 89 +++++++++++++++++++++++++- modules/substrate/src/mock.rs | 10 +++ modules/substrate/src/storage_proof.rs | 22 ++++++- modules/substrate/src/verifier.rs | 9 --- primitives/runtime/src/chain.rs | 2 +- 5 files changed, 118 insertions(+), 14 deletions(-) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 0daed1db3e23e..0bd3423e92189 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -32,17 +32,19 @@ #![allow(clippy::large_enum_variant)] use crate::storage::ImportedHeader; -use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderOf}; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult}; use frame_system::ensure_signed; use sp_runtime::traits::Header as HeaderT; use sp_runtime::RuntimeDebug; use sp_std::{marker::PhantomData, prelude::*}; +use sp_trie::StorageProof; // Re-export since the node uses these when configuring genesis pub use storage::{AuthoritySet, ScheduledChange}; pub use justification::decode_justification_target; +pub use storage_proof::StorageProofChecker; mod justification; mod storage; @@ -59,6 +61,8 @@ mod fork_tests; pub(crate) type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; /// Block hash of the bridged chain. pub(crate) type BridgedBlockHash = HashOf<::BridgedChain>; +/// Hasher of the bridged chain. +pub(crate) type BridgedBlockHasher = HasherOf<::BridgedChain>; /// Header of the bridged chain. pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; @@ -158,6 +162,12 @@ decl_error! { InvalidHeader, /// This header has not been finalized. UnfinalizedHeader, + /// The header is unknown. + UnknownHeader, + /// The storage proof doesn't contains storage root. So it is invalid for given header. + StorageRootMismatch, + /// Error when trying to fetch storage value from the proof. + StorageValueUnavailable, } } @@ -267,6 +277,27 @@ impl Module { .map(|id| (id.number, id.hash)) .collect() } + + /// Verify that the passed storage proof is valid, given it is crafted using + /// known finalized header. If the proof is valid, then the `parse` callback + /// is called and the function returns its result. + pub fn parse_finalized_storage_proof( + finalized_header_hash: BridgedBlockHash, + storage_proof: StorageProof, + parse: impl FnOnce(StorageProofChecker>) -> R, + ) -> Result { + let storage = PalletStorage::::new(); + let header = storage + .header_by_hash(finalized_header_hash) + .ok_or(Error::::UnknownHeader)?; + if !header.is_finalized { + return Err(Error::::UnfinalizedHeader.into()); + } + + let storage_proof_checker = + StorageProofChecker::new(*header.state_root(), storage_proof).map_err(Error::::from)?; + Ok(parse(storage_proof_checker)) + } } /// Expected interface for interacting with bridge pallet storage. @@ -433,3 +464,59 @@ impl BridgeStorage for PalletStorage { >::insert(signal_hash, next_change) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{helpers::unfinalized_header, run_test, TestRuntime}; + use frame_support::{assert_noop, assert_ok}; + + #[test] + fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { + run_test(|| { + assert_noop!( + Module::::parse_finalized_storage_proof( + Default::default(), + StorageProof::new(vec![]), + |_| (), + ), + Error::::UnknownHeader, + ); + }); + } + + #[test] + fn parse_finalized_storage_proof_rejects_proof_on_unfinalized_header() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let header = unfinalized_header(1); + storage.write_header(&header); + + assert_noop!( + Module::::parse_finalized_storage_proof( + header.header.hash(), + StorageProof::new(vec![]), + |_| (), + ), + Error::::UnfinalizedHeader, + ); + }); + } + + #[test] + fn parse_finalized_storage_accepts_valid_proof() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let (state_root, storage_proof) = storage_proof::tests::craft_valid_storage_proof(); + let mut header = unfinalized_header(1); + header.is_finalized = true; + header.header.set_state_root(state_root); + storage.write_header(&header); + + assert_ok!( + Module::::parse_finalized_storage_proof(header.header.hash(), storage_proof, |_| (),), + (), + ); + }); + } +} diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index f16ea476bb913..88ed2ed469816 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -93,6 +93,7 @@ pub fn run_test(test: impl FnOnce() -> T) -> T { pub mod helpers { use super::*; + use crate::storage::ImportedHeader; use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader}; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{AuthorityId, AuthorityList}; @@ -114,6 +115,15 @@ pub mod helpers { header } + pub fn unfinalized_header(num: u64) -> ImportedHeader { + ImportedHeader { + header: test_header(num), + requires_justification: false, + is_finalized: false, + signal_hash: None, + } + } + pub fn header_id(index: u8) -> HeaderId { (test_header(index.into()).hash(), index as _) } diff --git a/modules/substrate/src/storage_proof.rs b/modules/substrate/src/storage_proof.rs index 97ec09e132891..820a84737f175 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/modules/substrate/src/storage_proof.rs @@ -65,15 +65,24 @@ pub enum Error { StorageValueUnavailable, } +impl From for crate::Error { + fn from(error: Error) -> Self { + match error { + Error::StorageRootMismatch => crate::Error::StorageRootMismatch, + Error::StorageValueUnavailable => crate::Error::StorageValueUnavailable, + } + } +} + #[cfg(test)] -mod tests { +pub mod tests { use super::*; use sp_core::{Blake2Hasher, H256}; use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; - #[test] - fn storage_proof_check() { + /// Return valid storage proof and state root. + pub fn craft_valid_storage_proof() -> (H256, StorageProof) { // construct storage proof let backend = >::from(vec![ (None, vec![(b"key1".to_vec(), Some(b"value1".to_vec()))]), @@ -90,6 +99,13 @@ mod tests { .collect(), ); + (root, proof) + } + + #[test] + fn storage_proof_check() { + let (root, proof) = craft_valid_storage_proof(); + // check proof in runtime let checker = >::new(root, proof.clone()).unwrap(); assert_eq!(checker.read_value(b"key1"), Ok(Some(b"value1".to_vec()))); diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 3535834014961..1b58df03f85e0 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -361,15 +361,6 @@ mod tests { use sp_finality_grandpa::{AuthorityId, SetId}; use sp_runtime::{Digest, DigestItem}; - fn unfinalized_header(num: u64) -> ImportedHeader { - ImportedHeader { - header: test_header(num), - requires_justification: false, - is_finalized: false, - signal_hash: None, - } - } - fn schedule_next_change( authorities: Vec, set_id: SetId, diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 706e56f667ecd..5f180cf398138 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -80,7 +80,7 @@ pub type BlockNumberOf = ::BlockNumber; pub type HashOf = ::Hash; /// Hasher type used by the chain. -pub type HasherOf = ::Header; +pub type HasherOf = ::Hasher; /// Header type used by the chain. pub type HeaderOf = ::Header; From d0bf938a0cf15fd4087090bd7f73df9ccf199292 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 5 Nov 2020 11:18:38 +0300 Subject: [PATCH 0210/1210] Move storage keys computation to the message-lane pallet (#478) * compute required storage keys in the message-lane pallet * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/runtime/src/rialto_messages.rs | 27 ++++++--- bin/rialto/runtime/src/millau_messages.rs | 32 +++++++---- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages.rs | 29 +++++++++- modules/message-lane/Cargo.toml | 4 +- modules/message-lane/src/lib.rs | 67 +++++++++++++++++++++++ 6 files changed, 140 insertions(+), 21 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index a947d796cd778..0aed3d4bae89b 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -21,34 +21,37 @@ use crate::Runtime; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageKey, MessageNonce, + InboundLaneData, LaneId, Message, MessageNonce, }; use bp_runtime::InstanceId; -use bridge_runtime_common::messages::{self, MessageBridge}; +use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ - storage::generator::StorageMap, weights::{Weight, WeightToFeePolynomial}, RuntimeDebug, }; -use pallet_message_lane::{DefaultInstance, InboundLanes, OutboundLanes, OutboundMessages}; use sp_core::storage::StorageKey; use sp_trie::StorageProof; /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - let message_key = MessageKey { lane_id: *lane, nonce }; - let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); - StorageKey(raw_storage_key) + pallet_message_lane::storage_keys::message_key::::MessageLaneInstance>( + lane, nonce, + ) } /// Storage key of the Millau -> Rialto message lane state in the runtime storage. pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - StorageKey(OutboundLanes::::storage_map_final_key(*lane)) + pallet_message_lane::storage_keys::outbound_lane_data_key::<::MessageLaneInstance>( + lane, + ) } /// Storage key of the Rialto -> Millau message lane state in the runtime storage. pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - StorageKey(InboundLanes::::storage_map_final_key(*lane)) + pallet_message_lane::storage_keys::inbound_lane_data_key::< + Runtime, + ::MessageLaneInstance, + >(lane) } /// Message payload for Millau -> Rialto messages. @@ -116,12 +119,15 @@ impl MessageBridge for WithRialtoMessageBridge { pub struct Millau; impl messages::ChainWithMessageLanes for Millau { + type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; type Call = crate::Call; type Weight = Weight; type Balance = bp_millau::Balance; + + type MessageLaneInstance = pallet_message_lane::DefaultInstance; } /// Rialto chain from message lane point of view. @@ -129,12 +135,15 @@ impl messages::ChainWithMessageLanes for Millau { pub struct Rialto; impl messages::ChainWithMessageLanes for Rialto { + type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; type Call = (); // unknown to us type Weight = Weight; type Balance = bp_rialto::Balance; + + type MessageLaneInstance = pallet_message_lane::DefaultInstance; } impl TargetHeaderChain for Rialto { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 6d38398eab6a4..45e3984a24a51 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -21,34 +21,37 @@ use crate::Runtime; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageKey, MessageNonce, + InboundLaneData, LaneId, Message, MessageNonce, }; use bp_runtime::InstanceId; -use bridge_runtime_common::messages::{self, MessageBridge}; +use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ - storage::generator::StorageMap, weights::{Weight, WeightToFeePolynomial}, RuntimeDebug, }; -use pallet_message_lane::{DefaultInstance, InboundLanes, OutboundLanes, OutboundMessages}; use sp_core::storage::StorageKey; use sp_trie::StorageProof; /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - let message_key = MessageKey { lane_id: *lane, nonce }; - let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); - StorageKey(raw_storage_key) + pallet_message_lane::storage_keys::message_key::::MessageLaneInstance>( + lane, nonce, + ) } /// Storage key of the Rialto -> Millau message lane state in the runtime storage. pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - StorageKey(OutboundLanes::::storage_map_final_key(*lane)) + pallet_message_lane::storage_keys::outbound_lane_data_key::<::MessageLaneInstance>( + lane, + ) } /// Storage key of the Millau -> Rialto message lane state in the runtime storage. pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - StorageKey(InboundLanes::::storage_map_final_key(*lane)) + pallet_message_lane::storage_keys::inbound_lane_data_key::< + Runtime, + ::MessageLaneInstance, + >(lane) } /// Message payload for Rialto -> Millau messages. @@ -67,6 +70,9 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi pallet_bridge_call_dispatch::DefaultInstance, >; +/// Messages proof for Millau -> Rialto messages. +type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; + /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithMillauMessageBridge; @@ -116,12 +122,15 @@ impl MessageBridge for WithMillauMessageBridge { pub struct Rialto; impl messages::ChainWithMessageLanes for Rialto { + type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; type Call = crate::Call; type Weight = Weight; type Balance = bp_rialto::Balance; + + type MessageLaneInstance = pallet_message_lane::DefaultInstance; } /// Millau chain from message lane point of view. @@ -129,12 +138,15 @@ impl messages::ChainWithMessageLanes for Rialto { pub struct Millau; impl messages::ChainWithMessageLanes for Millau { + type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; type Call = (); // unknown to us type Weight = Weight; type Balance = bp_millau::Balance; + + type MessageLaneInstance = pallet_message_lane::DefaultInstance; } impl TargetHeaderChain for Millau { @@ -167,7 +179,7 @@ impl SourceHeaderChain for Millau { // - the storage proof of one or several keys; // - id of the lane we prove messages for; // - inclusive range of messages nonces that are proved. - type MessagesProof = (bp_millau::Hash, StorageProof, LaneId, MessageNonce, MessageNonce); + type MessagesProof = FromMillauMessagesProof; fn verify_messages_proof( _proof: Self::MessagesProof, diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 960fbc580caf8..61d4928da3278 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -16,6 +16,7 @@ bp-message-dispatch = { path = "../../primitives/message-dispatch", default-feat bp-message-lane = { path = "../../primitives/message-lane", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } +pallet-message-lane = { path = "../../modules/message-lane", default-features = false } # Substrate dependencies @@ -33,6 +34,7 @@ std = [ "codec/std", "frame-support/std", "pallet-bridge-call-dispatch/std", + "pallet-message-lane/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 9e534c6d782ad..9ac6ced189d7d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -28,9 +28,10 @@ use bp_message_lane::{ }; use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; -use frame_support::RuntimeDebug; +use frame_support::{traits::Instance, RuntimeDebug}; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; use sp_std::{cmp::PartialOrd, marker::PhantomData, vec::Vec}; +use sp_trie::StorageProof; /// Bidirectional message bridge. pub trait MessageBridge { @@ -73,6 +74,8 @@ pub trait MessageBridge { /// Chain that has `message-lane` and `call-dispatch` modules. pub trait ChainWithMessageLanes { + /// Hash used in the chain. + type Hash: Decode; /// Accound id on the chain. type AccountId; /// Public key of the chain account that may be used to verify signatures. @@ -88,10 +91,14 @@ pub trait ChainWithMessageLanes { type Weight: From; /// Type of balances that is used on the chain. type Balance: CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; + + /// Instance of the message-lane pallet. + type MessageLaneInstance: Instance; } pub(crate) type ThisChain = ::ThisChain; pub(crate) type BridgedChain = ::BridgedChain; +pub(crate) type HashOf = ::Hash; pub(crate) type AccountIdOf = ::AccountId; pub(crate) type SignerOf = ::Signer; pub(crate) type SignatureOf = ::Signature; @@ -202,6 +209,20 @@ pub mod target { CallOf>, >; + /// Messages proof from bridged chain: + /// + /// - hash of finalized header; + /// - storage proof of messages and (optionally) outbound lane state; + /// - lane id; + /// - nonces (inclusive range) of messages which are included in this proof. + pub type FromBridgedChainMessagesProof = ( + HashOf>, + StorageProof, + LaneId, + MessageNonce, + MessageNonce, + ); + /// Message payload for Bridged -> This messages. pub struct FromBridgedChainMessagePayload(pub(crate) FromBridgedChainDecodedMessagePayload); @@ -450,23 +471,29 @@ mod tests { struct ThisChain; impl ChainWithMessageLanes for ThisChain { + type Hash = (); type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; type Signature = ThisChainSignature; type Call = ThisChainCall; type Weight = frame_support::weights::Weight; type Balance = ThisChainBalance; + + type MessageLaneInstance = pallet_message_lane::DefaultInstance; } struct BridgedChain; impl ChainWithMessageLanes for BridgedChain { + type Hash = (); type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; type Signature = BridgedChainSignature; type Call = BridgedChainCall; type Weight = frame_support::weights::Weight; type Balance = BridgedChainBalance; + + type MessageLaneInstance = pallet_message_lane::DefaultInstance; } #[test] diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 41f844fc9f841..480306d2b21bf 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -19,11 +19,12 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } frame-support = { version = "2.0", default-features = false } frame-system = { version = "2.0", default-features = false } +sp-core = { version = "2.0", default-features = false } sp-runtime = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } [dev-dependencies] -sp-core = "2.0" +hex-literal = "0.3" sp-io = "2.0" [features] @@ -35,6 +36,7 @@ std = [ "frame-support/std", "frame-system/std", "serde", + "sp-core/std", "sp-runtime/std", "sp-std/std", ] diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 9f6c1d6d706ad..30f575ab6884e 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -452,6 +452,42 @@ impl, I: Instance> Module { } } +/// Getting storage keys for messages and lanes states. These keys are normally used when building +/// messages and lanes states proofs. +/// +/// Keep in mind that all functions in this module are **NOT** using passed `T` argument, so any +/// runtime can be passed. E.g. if you're verifying proof from Runtime1 in Runtime2, you only have +/// access to Runtime2 and you may pass it to the functions, where required. This is because our +/// maps are not using any Runtime-specific data in the keys. +/// +/// On the other side, passing correct instance is required. So if proof has been crafted by the +/// Instance1, you should verify it using Instance1. This is inconvenient if you're using different +/// instances on different sides of the bridge. I.e. in Runtime1 it is Instance2, but on Runtime2 +/// it is Instance42. But there's no other way, but to craft this key manually (which is what I'm +/// trying to avoid here) - by using strings like "Instance2", "OutboundMessages", etc. +pub mod storage_keys { + use super::*; + use frame_support::storage::generator::StorageMap; + use sp_core::storage::StorageKey; + + /// Storage key of the outbound message in the runtime storage. + pub fn message_key, I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey { + let message_key = MessageKey { lane_id: *lane, nonce }; + let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); + StorageKey(raw_storage_key) + } + + /// Storage key of the outbound message lane state in the runtime storage. + pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { + StorageKey(OutboundLanes::::storage_map_final_key(*lane)) + } + + /// Storage key of the inbound message lane state in the runtime storage. + pub fn inbound_lane_data_key, I: Instance>(lane: &LaneId) -> StorageKey { + StorageKey(InboundLanes::::storage_map_final_key(*lane)) + } +} + /// Ensure that the origin is either root, or `ModuleOwner`. fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { @@ -605,6 +641,7 @@ mod tests { }; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Module as System, Phase}; + use hex_literal::hex; use sp_runtime::DispatchError; fn send_regular_message() { @@ -1018,4 +1055,34 @@ mod tests { assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 3,); }); } + + #[test] + fn storage_message_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking all + // previously crafted messages proofs. + assert_eq!( + storage_keys::message_key::(&*b"test", 42).0, + hex!("87f1ffe31b52878f09495ca7482df1a48a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), + ); + } + + #[test] + fn outbound_lane_data_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking all + // previously crafted outbound lane state proofs. + assert_eq!( + storage_keys::outbound_lane_data_key::(&*b"test").0, + hex!("87f1ffe31b52878f09495ca7482df1a496c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), + ); + } + + #[test] + fn inbound_lane_data_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking all + // previously crafted inbound lane state proofs. + assert_eq!( + storage_keys::inbound_lane_data_key::(&*b"test").0, + hex!("87f1ffe31b52878f09495ca7482df1a4e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), + ); + } } From f406afe752d416910d949f5b1baa10e2af1fda4a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 5 Nov 2020 13:12:31 +0300 Subject: [PATCH 0211/1210] Millau -> Rialto messages relay (#399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Millau messages -> Rialto relay * prepare for custom race strategy of delivery race * custom strategy for delivery race * update TODOs * add reference to issue 457 * impl reconnect * clippy * fix check in test * fmt * removed obsolete TODO * fixed another TODOs * fmt * use MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE const from primitives * Update relays/messages-relay/src/message_lane_loop.rs Co-authored-by: Hernando Castano * added SubstrateMessagesProof typedef * fix test * removed comment * additional_proof_required -> ProofParameters * typo * multiline literal * clippy * fix typo * and_then -> await * update_source_latest_confirmed_nonce * Update relays/messages-relay/src/message_race_delivery.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 4 +- bin/rialto/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/millau_messages.rs | 4 +- primitives/millau/Cargo.toml | 2 + primitives/millau/src/lib.rs | 4 + primitives/rialto/Cargo.toml | 2 + primitives/rialto/src/lib.rs | 4 + primitives/runtime/src/chain.rs | 1 + relays/messages-relay/src/lib.rs | 8 +- relays/messages-relay/src/message_lane.rs | 19 +- .../messages-relay/src/message_lane_loop.rs | 211 ++++++--- .../src/message_race_delivery.rs | 413 ++++++------------ .../messages-relay/src/message_race_loop.rs | 136 +++--- .../src/message_race_receiving.rs | 56 ++- .../src/message_race_strategy.rs | 334 ++++++++++++++ relays/millau-client/Cargo.toml | 1 + relays/substrate-client/Cargo.toml | 3 + relays/substrate-client/src/client.rs | 99 ++++- relays/substrate-client/src/lib.rs | 3 + relays/substrate-client/src/rpc.rs | 24 + relays/substrate/Cargo.toml | 2 + relays/substrate/src/cli.rs | 16 + relays/substrate/src/main.rs | 42 ++ relays/substrate/src/messages_source.rs | 225 ++++++++++ relays/substrate/src/messages_target.rs | 176 ++++++++ .../src/millau_messages_to_rialto.rs | 171 ++++++++ 27 files changed, 1510 insertions(+), 455 deletions(-) create mode 100644 relays/messages-relay/src/message_race_strategy.rs create mode 100644 relays/substrate/src/messages_source.rs create mode 100644 relays/substrate/src/messages_target.rs create mode 100644 relays/substrate/src/millau_messages_to_rialto.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index faad5153d8223..42251b94b01b3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -321,7 +321,7 @@ impl pallet_shift_session_manager::Trait for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = 128; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; } impl pallet_message_lane::Trait for Runtime { diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 0aed3d4bae89b..450d38b6d00fb 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -23,7 +23,7 @@ use bp_message_lane::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, }; -use bp_runtime::InstanceId; +use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ weights::{Weight, WeightToFeePolynomial}, @@ -75,7 +75,7 @@ pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDi pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { - const INSTANCE: InstanceId = *b"rlto"; + const INSTANCE: InstanceId = RIALTO_BRIDGE_INSTANCE; const RELAYER_FEE_PERCENT: u32 = 10; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 1ab9984bec722..ea73fd2d1f520 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -65,6 +65,7 @@ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeMillauCall; pub use pallet_timestamp::Call as TimestampCall; @@ -428,7 +429,7 @@ impl pallet_shift_session_manager::Trait for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = 128; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; } impl pallet_message_lane::Trait for Runtime { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 45e3984a24a51..97067078e34b5 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -23,7 +23,7 @@ use bp_message_lane::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, }; -use bp_runtime::InstanceId; +use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ weights::{Weight, WeightToFeePolynomial}, @@ -78,7 +78,7 @@ type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof + Into + Ord + + CheckedSub + std::ops::Add + One + Zero; /// Messages proof. - type MessagesProof: Clone; + type MessagesProof: Clone + Send + Sync; /// Messages receiving proof. - type MessagesReceivingProof: Clone; + type MessagesReceivingProof: Clone + Send + Sync; /// Number of the source header. - type SourceHeaderNumber: Clone + Debug + Default + Ord + PartialEq + Into; + type SourceHeaderNumber: Clone + Debug + Ord + PartialEq + Into + Send + Sync; /// Hash of the source header. - type SourceHeaderHash: Clone + Debug + Default + PartialEq; + type SourceHeaderHash: Clone + Debug + Default + PartialEq + Send + Sync; /// Number of the target header. - type TargetHeaderNumber: Clone + Debug + Default + Ord + PartialEq + Into; + type TargetHeaderNumber: Clone + Debug + Ord + PartialEq + Into + Send + Sync; /// Hash of the target header. - type TargetHeaderHash: Clone + Debug + Default + PartialEq; + type TargetHeaderHash: Clone + Debug + Default + PartialEq + Send + Sync; } /// Source header id within given one-way message lane. diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index b2eb7d2820bf9..a9333509500e6 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -24,9 +24,6 @@ //! finalized header. I.e. when talking about headers in lane context, we //! only care about finalized headers. -// Until there'll be actual message-lane in the runtime. -#![allow(dead_code)] - use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_race_delivery::run as run_message_delivery_race; use crate::message_race_receiving::run as run_message_receiving_race; @@ -42,14 +39,33 @@ use relay_utils::{ }; use std::{fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; +/// Message lane loop configuration params. +#[derive(Debug, Clone)] +pub struct Params { + /// Id of lane this loop is servicing. + pub lane: LaneId, + /// Interval at which we ask target node about its updates. + pub source_tick: Duration, + /// Interval at which we ask target node about its updates. + pub target_tick: Duration, + /// Delay between moments when connection error happens and our reconnect attempt. + pub reconnect_delay: Duration, + /// The loop will auto-restart if there has been no updates during this period. + pub stall_timeout: Duration, + /// Message delivery race will stop delivering messages if there are `max_unconfirmed_nonces_at_target` + /// unconfirmed nonces on the target node. The race would continue once they're confirmed by the + /// receiving race. + pub max_unconfirmed_nonces_at_target: MessageNonce, +} + /// Source client trait. -#[async_trait(?Send)] -pub trait SourceClient: Clone { +#[async_trait] +pub trait SourceClient: Clone + Send + Sync { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; /// Try to reconnect to source node. - fn reconnect(self) -> Self; + async fn reconnect(self) -> Result; /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -70,6 +86,7 @@ pub trait SourceClient: Clone { &self, id: SourceHeaderIdOf

, nonces: RangeInclusive, + include_outbound_lane_state: bool, ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error>; /// Submit messages receiving proof. @@ -77,17 +94,17 @@ pub trait SourceClient: Clone { &self, generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, - ) -> Result, Self::Error>; + ) -> Result<(), Self::Error>; } /// Target client trait. -#[async_trait(?Send)] -pub trait TargetClient: Clone { +#[async_trait] +pub trait TargetClient: Clone + Send + Sync { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; /// Try to reconnect to source node. - fn reconnect(self) -> Self; + async fn reconnect(self) -> Result; /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -98,6 +115,12 @@ pub trait TargetClient: Clone { id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error>; + /// Get nonce of latest confirmed message. + async fn latest_confirmed_received_nonce( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error>; + /// Prove messages receiving at given block. async fn prove_messages_receiving( &self, @@ -138,15 +161,10 @@ pub struct ClientsState { } /// Run message lane service loop. -#[allow(clippy::too_many_arguments)] pub fn run( - lane: LaneId, + params: Params, mut source_client: impl SourceClient

, - source_tick: Duration, mut target_client: impl TargetClient

, - target_tick: Duration, - reconnect_delay: Duration, - stall_timeout: Duration, metrics_params: Option, exit_signal: impl Future, ) { @@ -162,7 +180,7 @@ pub fn run( "{}_to_{}_MessageLoop/{}", P::SOURCE_NAME, P::TARGET_NAME, - hex::encode(lane) + hex::encode(params.lane) ), metrics_params, &metrics_global, @@ -171,11 +189,9 @@ pub fn run( loop { let result = run_until_connection_lost( + params.clone(), source_client.clone(), - source_tick, target_client.clone(), - target_tick, - stall_timeout, if metrics_enabled { Some(&mut metrics_global) } else { @@ -192,15 +208,41 @@ pub fn run( match result { Ok(()) => break, - Err(failed_client) => { - async_std::task::sleep(reconnect_delay).await; + Err(failed_client) => loop { + async_std::task::sleep(params.reconnect_delay).await; if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - source_client = source_client.reconnect(); + source_client = match source_client.clone().reconnect().await { + Ok(source_client) => source_client, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect {}. Going to retry in {}s: {:?}", + P::SOURCE_NAME, + params.reconnect_delay.as_secs(), + error, + ); + continue; + } + } } if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - target_client = target_client.reconnect(); + target_client = match target_client.clone().reconnect().await { + Ok(target_client) => target_client, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect {}. Going to retry in {}s: {:?}", + P::TARGET_NAME, + params.reconnect_delay.as_secs(), + error, + ); + continue; + } + } } - } + + break; + }, } log::debug!( @@ -214,13 +256,10 @@ pub fn run( } /// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. -#[allow(clippy::too_many_arguments)] async fn run_until_connection_lost, TC: TargetClient

>( + params: Params, source_client: SC, - source_tick: Duration, target_client: TC, - target_tick: Duration, - stall_timeout: Duration, mut metrics_global: Option<&mut GlobalMetrics>, metrics_msg: Option, exit_signal: impl Future, @@ -230,14 +269,14 @@ async fn run_until_connection_lost, TC: Targ let mut source_state_required = true; let source_state = source_client.state().fuse(); let source_go_offline_future = futures::future::Fuse::terminated(); - let source_tick_stream = interval(source_tick).fuse(); + let source_tick_stream = interval(params.source_tick).fuse(); let mut target_retry_backoff = retry_backoff(); let mut target_client_is_online = false; let mut target_state_required = true; let target_state = target_client.state().fuse(); let target_go_offline_future = futures::future::Fuse::terminated(); - let target_tick_stream = interval(target_tick).fuse(); + let target_tick_stream = interval(params.target_tick).fuse(); let ( (delivery_source_state_sender, delivery_source_state_receiver), @@ -248,8 +287,9 @@ async fn run_until_connection_lost, TC: Targ delivery_source_state_receiver, target_client.clone(), delivery_target_state_receiver, - stall_timeout, + params.stall_timeout, metrics_msg.clone(), + params.max_unconfirmed_nonces_at_target, ) .fuse(); @@ -262,7 +302,7 @@ async fn run_until_connection_lost, TC: Targ receiving_source_state_receiver, target_client.clone(), receiving_target_state_receiver, - stall_timeout, + params.stall_timeout, metrics_msg.clone(), ) .fuse(); @@ -395,7 +435,7 @@ pub(crate) mod tests { } pub type TestMessageNonce = u64; - pub type TestMessagesProof = RangeInclusive; + pub type TestMessagesProof = (RangeInclusive, Option); pub type TestMessagesReceivingProof = TestMessageNonce; pub type TestSourceHeaderNumber = u64; @@ -405,20 +445,15 @@ pub(crate) mod tests { pub type TestTargetHeaderHash = u64; #[derive(Debug)] - pub enum TestError { - Logic, - Connection, - } + pub struct TestError; impl MaybeConnectionError for TestError { fn is_connection_error(&self) -> bool { - match *self { - TestError::Logic => false, - TestError::Connection => true, - } + true } } + #[derive(Clone)] pub struct TestMessageLane; impl MessageLane for TestMessageLane { @@ -449,33 +484,34 @@ pub(crate) mod tests { is_target_reconnected: bool, target_state: SourceClientState, target_latest_received_nonce: TestMessageNonce, + target_latest_confirmed_received_nonce: TestMessageNonce, submitted_messages_proofs: Vec, } #[derive(Clone)] pub struct TestSourceClient { data: Arc>, - tick: Arc, + tick: Arc, } - #[async_trait(?Send)] + #[async_trait] impl SourceClient for TestSourceClient { type Error = TestError; - fn reconnect(self) -> Self { + async fn reconnect(self) -> Result { { let mut data = self.data.lock(); (self.tick)(&mut *data); data.is_source_reconnected = true; } - self + Ok(self) } async fn state(&self) -> Result, Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { - return Err(TestError::Connection); + return Err(TestError); } Ok(data.source_state.clone()) } @@ -487,7 +523,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { - return Err(TestError::Connection); + return Err(TestError); } Ok((id, data.source_latest_generated_nonce)) } @@ -505,6 +541,7 @@ pub(crate) mod tests { &self, id: SourceHeaderIdOf, nonces: RangeInclusive, + include_outbound_lane_state: bool, ) -> Result< ( SourceHeaderIdOf, @@ -513,46 +550,59 @@ pub(crate) mod tests { ), Self::Error, > { - Ok((id, nonces.clone(), nonces)) + let mut data = self.data.lock(); + (self.tick)(&mut *data); + Ok(( + id, + nonces.clone(), + ( + nonces, + if include_outbound_lane_state { + Some(data.source_latest_confirmed_received_nonce) + } else { + None + }, + ), + )) } async fn submit_messages_receiving_proof( &self, _generated_at_block: TargetHeaderIdOf, proof: TestMessagesReceivingProof, - ) -> Result, Self::Error> { + ) -> Result<(), Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); data.submitted_messages_receiving_proofs.push(proof); data.source_latest_confirmed_received_nonce = proof; - Ok(proof..=proof) + Ok(()) } } #[derive(Clone)] pub struct TestTargetClient { data: Arc>, - tick: Arc, + tick: Arc, } - #[async_trait(?Send)] + #[async_trait] impl TargetClient for TestTargetClient { type Error = TestError; - fn reconnect(self) -> Self { + async fn reconnect(self) -> Result { { let mut data = self.data.lock(); (self.tick)(&mut *data); data.is_target_reconnected = true; } - self + Ok(self) } async fn state(&self) -> Result, Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError::Connection); + return Err(TestError); } Ok(data.target_state.clone()) } @@ -564,11 +614,23 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError::Connection); + return Err(TestError); } Ok((id, data.target_latest_received_nonce)) } + async fn latest_confirmed_received_nonce( + &self, + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, TestMessageNonce), Self::Error> { + let mut data = self.data.lock(); + (self.tick)(&mut *data); + if data.is_target_fails { + return Err(TestError); + } + Ok((id, data.target_latest_confirmed_received_nonce)) + } + async fn prove_messages_receiving( &self, id: TargetHeaderIdOf, @@ -585,11 +647,14 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError::Connection); + return Err(TestError); } data.target_state.best_self = HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); - data.target_latest_received_nonce = *proof.end(); + data.target_latest_received_nonce = *proof.0.end(); + if let Some(target_latest_confirmed_received_nonce) = proof.1 { + data.target_latest_confirmed_received_nonce = target_latest_confirmed_received_nonce; + } data.submitted_messages_proofs.push(proof); Ok(nonces) } @@ -597,8 +662,8 @@ pub(crate) mod tests { fn run_loop_test( data: TestClientData, - source_tick: Arc, - target_tick: Arc, + source_tick: Arc, + target_tick: Arc, exit_signal: impl Future, ) -> TestClientData { async_std::task::block_on(async { @@ -613,17 +678,19 @@ pub(crate) mod tests { tick: target_tick, }; run( - [0, 0, 0, 0], + Params { + lane: [0, 0, 0, 0], + source_tick: Duration::from_millis(100), + target_tick: Duration::from_millis(100), + reconnect_delay: Duration::from_millis(0), + stall_timeout: Duration::from_millis(60), + max_unconfirmed_nonces_at_target: 100, + }, source_client, - Duration::from_millis(100), target_client, - Duration::from_millis(100), - Duration::from_millis(0), - Duration::from_secs(60), None, exit_signal, ); - let result = data.lock().clone(); result }) @@ -671,7 +738,7 @@ pub(crate) mod tests { exit_receiver.into_future().map(|(_, _)| ()), ); - assert_eq!(result.submitted_messages_proofs, vec![1..=1],); + assert_eq!(result.submitted_messages_proofs, vec![(1..=1, None)],); } #[test] @@ -717,7 +784,13 @@ pub(crate) mod tests { exit_receiver.into_future().map(|(_, _)| ()), ); - assert_eq!(result.submitted_messages_proofs, vec![1..=4, 5..=8, 9..=10],); + // there are no strict restrictions on when reward confirmation should come + // (because `max_unconfirmed_nonces_at_target` is `100` in tests and this confirmation + // depends on the state of both clients) + // => we do not check it here + assert_eq!(result.submitted_messages_proofs[0].0, 1..=4); + assert_eq!(result.submitted_messages_proofs[1].0, 5..=8); + assert_eq!(result.submitted_messages_proofs[2].0, 9..=10); assert!(!result.submitted_messages_receiving_proofs.is_empty()); } } diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index d725f256878f7..a5d096b7710b1 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -18,14 +18,15 @@ use crate::message_lane_loop::{ SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }; -use crate::message_race_loop::{MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; +use crate::message_race_loop::{ClientNonces, MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; +use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use futures::stream::FusedStream; -use num_traits::{One, Zero}; -use relay_utils::{FailedClient, HeaderId}; -use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; +use num_traits::CheckedSub; +use relay_utils::FailedClient; +use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Maximal number of messages to relay in single transaction. const MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX: u32 = 4; @@ -38,6 +39,7 @@ pub async fn run( target_state_updates: impl FusedStream>, stall_timeout: Duration, metrics_msg: Option, + max_unconfirmed_nonces_at_target: P::MessageNonce, ) -> Result<(), FailedClient> { crate::message_race_loop::run( MessageDeliveryRaceSource { @@ -53,7 +55,12 @@ pub async fn run( }, target_state_updates, stall_timeout, - MessageDeliveryStrategy::

::new(MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX.into()), + MessageDeliveryStrategy::

{ + max_unconfirmed_nonces_at_target, + source_nonces: None, + target_nonces: None, + strategy: BasicStrategy::new(MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX.into()), + }, ) .await } @@ -84,33 +91,46 @@ struct MessageDeliveryRaceSource { _phantom: PhantomData

, } -#[async_trait(?Send)] +#[async_trait] impl SourceClient> for MessageDeliveryRaceSource where P: MessageLane, C: MessageLaneSourceClient

, { type Error = C::Error; + type ProofParameters = bool; - async fn latest_nonce( + async fn nonces( &self, at_block: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { - let result = self.client.latest_generated_nonce(at_block).await; + ) -> Result<(SourceHeaderIdOf

, ClientNonces), Self::Error> { + let (at_block, latest_generated_nonce) = self.client.latest_generated_nonce(at_block).await?; + let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; + if let Some(metrics_msg) = self.metrics_msg.as_ref() { - if let Ok((_, source_latest_generated_nonce)) = result.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(*source_latest_generated_nonce); - } + metrics_msg.update_source_latest_generated_nonce::

(latest_generated_nonce); + metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); } - result + + Ok(( + at_block, + ClientNonces { + latest_nonce: latest_generated_nonce, + confirmed_nonce: Some(latest_confirmed_nonce), + }, + )) } async fn generate_proof( &self, at_block: SourceHeaderIdOf

, nonces: RangeInclusive, + proof_parameters: Self::ProofParameters, ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { - self.client.prove_messages(at_block, nonces).await + let outbound_state_proof_required = proof_parameters; + self.client + .prove_messages(at_block, nonces, outbound_state_proof_required) + .await } } @@ -121,7 +141,7 @@ struct MessageDeliveryRaceTarget { _phantom: PhantomData

, } -#[async_trait(?Send)] +#[async_trait] impl TargetClient> for MessageDeliveryRaceTarget where P: MessageLane, @@ -129,17 +149,25 @@ where { type Error = C::Error; - async fn latest_nonce( + async fn nonces( &self, at_block: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { - let result = self.client.latest_received_nonce(at_block).await; + ) -> Result<(TargetHeaderIdOf

, ClientNonces), Self::Error> { + let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; + let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; + if let Some(metrics_msg) = self.metrics_msg.as_ref() { - if let Ok((_, target_latest_received_nonce)) = result.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(*target_latest_received_nonce); - } + metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); + metrics_msg.update_target_latest_confirmed_nonce::

(latest_confirmed_nonce); } - result + + Ok(( + at_block, + ClientNonces { + latest_nonce: latest_received_nonce, + confirmed_nonce: Some(latest_confirmed_nonce), + }, + )) } async fn submit_proof( @@ -155,7 +183,18 @@ where } /// Messages delivery strategy. -type MessageDeliveryStrategy

= DeliveryStrategy< +struct MessageDeliveryStrategy { + /// Maximal unconfirmed nonces at target client. + max_unconfirmed_nonces_at_target: P::MessageNonce, + /// Latest nonces from the source client. + source_nonces: Option>, + /// Target nonces from the source client. + target_nonces: Option>, + /// Basic delivery strategy. + strategy: MessageDeliveryStrategyBase

, +} + +type MessageDeliveryStrategyBase

= BasicStrategy<

::SourceHeaderNumber,

::SourceHeaderHash,

::TargetHeaderNumber, @@ -164,280 +203,90 @@ type MessageDeliveryStrategy

= DeliveryStrategy<

::MessagesProof, >; -/// Nonces delivery strategy. -#[derive(Debug)] -pub struct DeliveryStrategy { - /// All queued nonces. - source_queue: VecDeque<(HeaderId, Nonce)>, - /// Best nonce known to target node. - target_nonce: Nonce, - /// Max nonces to relay in single transaction. - max_nonces_to_relay_in_single_tx: Nonce, - /// Unused generic types dump. - _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, -} - -impl - DeliveryStrategy +impl RaceStrategy, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof> + for MessageDeliveryStrategy

{ - /// Create new delivery strategy. - pub fn new(max_nonces_to_relay_in_single_tx: Nonce) -> Self { - DeliveryStrategy { - source_queue: VecDeque::new(), - target_nonce: Default::default(), - max_nonces_to_relay_in_single_tx, - _phantom: Default::default(), - } - } -} + type ProofParameters = bool; -impl - RaceStrategy< - HeaderId, - HeaderId, - Nonce, - Proof, - > for DeliveryStrategy -where - SourceHeaderHash: Clone, - SourceHeaderNumber: Clone + Ord, - Nonce: Clone + Copy + From + Ord + std::ops::Add + One + Zero, -{ fn is_empty(&self) -> bool { - self.source_queue.is_empty() + self.strategy.is_empty() } - fn source_nonce_updated(&mut self, at_block: HeaderId, nonce: Nonce) { - if nonce <= self.target_nonce { - return; - } - - match self.source_queue.back() { - Some((_, prev_nonce)) if *prev_nonce < nonce => (), - Some(_) => return, - None => (), - } - - self.source_queue.push_back((at_block, nonce)) + fn source_nonces_updated(&mut self, at_block: SourceHeaderIdOf

, nonces: ClientNonces) { + self.source_nonces = Some(nonces.clone()); + self.strategy.source_nonces_updated(at_block, nonces) } - fn target_nonce_updated( + fn target_nonces_updated( &mut self, - nonce: Nonce, - race_state: &mut RaceState< - HeaderId, - HeaderId, - Nonce, - Proof, - >, + nonces: ClientNonces, + race_state: &mut RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, ) { - if nonce < self.target_nonce { - return; - } - - while let Some(true) = self - .source_queue - .front() - .map(|(_, source_nonce)| *source_nonce <= nonce) - { - self.source_queue.pop_front(); - } - - let need_to_select_new_nonces = race_state - .nonces_to_submit - .as_ref() - .map(|(_, nonces, _)| *nonces.end() <= nonce) - .unwrap_or(false); - if need_to_select_new_nonces { - race_state.nonces_to_submit = None; - } - - let need_new_nonces_to_submit = race_state - .nonces_submitted - .as_ref() - .map(|nonces| *nonces.end() <= nonce) - .unwrap_or(false); - if need_new_nonces_to_submit { - race_state.nonces_submitted = None; - } - - self.target_nonce = nonce; + self.target_nonces = Some(nonces.clone()); + self.strategy.target_nonces_updated(nonces, race_state) } fn select_nonces_to_deliver( &mut self, - race_state: &RaceState< - HeaderId, - HeaderId, - Nonce, - Proof, - >, - ) -> Option> { - // if we have already selected nonces that we want to submit, do nothing - if race_state.nonces_to_submit.is_some() { - return None; - } - - // if we already submitted some nonces, do nothing - if race_state.nonces_submitted.is_some() { - return None; - } - - // 1) we want to deliver all nonces, starting from `target_nonce + 1` - // 2) we want to deliver at most `self.max_nonces_to_relay_in_single_tx` nonces in this batch - // 3) we can't deliver new nonce until header, that has emitted this nonce, is finalized - // by target client - let nonces_begin = self.target_nonce + 1.into(); - let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; - let mut nonces_end = None; - let mut i = Zero::zero(); - while i < self.max_nonces_to_relay_in_single_tx { - let nonce = nonces_begin + i; - - // if queue is empty, we don't need to prove anything - let (first_queued_at, first_queued_nonce) = match self.source_queue.front() { - Some((first_queued_at, first_queued_nonce)) => ((*first_queued_at).clone(), *first_queued_nonce), - None => break, - }; - - // if header that has queued the message is not yet finalized at bridged chain, - // we can't prove anything - if first_queued_at.0 > best_header_at_target.0 { - break; - } - - // ok, we may deliver this nonce - nonces_end = Some(nonce); - - // probably remove it from the queue? - if nonce == first_queued_nonce { - self.source_queue.pop_front(); + race_state: &RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, + ) -> Option<(RangeInclusive, Self::ProofParameters)> { + const CONFIRMED_NONCE_PROOF: &str = "\ + ClientNonces are crafted by MessageDeliveryRace(Source|Target);\ + MessageDeliveryRace(Source|Target) always fills confirmed_nonce field;\ + qed"; + + let source_nonces = self.source_nonces.as_ref()?; + let target_nonces = self.target_nonces.as_ref()?; + + // There's additional condition in the message delivery race: target would reject messages + // if there are too much unconfirmed messages at the inbound lane. + + // https://github.com/paritytech/parity-bridges-common/issues/432 + // TODO: message lane loop works with finalized blocks only, but we're submitting transactions that + // are updating best block (which may not be finalized yet). So all decisions that are made below + // may be outdated. This needs to be changed - all logic here must be built on top of best blocks. + + // The receiving race is responsible to deliver confirmations back to the source chain. So if + // there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. + let latest_received_nonce_at_target = target_nonces.latest_nonce; + let latest_confirmed_nonce_at_source = source_nonces.confirmed_nonce.expect(CONFIRMED_NONCE_PROOF); + let confirmations_missing = latest_received_nonce_at_target.checked_sub(&latest_confirmed_nonce_at_source); + match confirmations_missing { + Some(confirmations_missing) if confirmations_missing > self.max_unconfirmed_nonces_at_target => { + log::debug!( + target: "bridge", + "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ + at target: target.latest_received={:?}, source.latest_confirmed={:?}, max={:?}", + MessageDeliveryRace::

::source_name(), + MessageDeliveryRace::

::target_name(), + latest_received_nonce_at_target, + latest_confirmed_nonce_at_source, + self.max_unconfirmed_nonces_at_target, + ); + + return None; } - - i = i + One::one(); + _ => (), } - nonces_end.map(|nonces_end| RangeInclusive::new(nonces_begin, nonces_end)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::message_lane_loop::{ - tests::{header_id, TestMessageLane, TestMessageNonce, TestMessagesProof}, - ClientState, - }; - - #[test] - fn strategy_is_empty_works() { - let mut strategy = MessageDeliveryStrategy::::new(4); - assert_eq!(strategy.is_empty(), true); - strategy.source_nonce_updated(header_id(1), 1); - assert_eq!(strategy.is_empty(), false); - } - - #[test] - fn source_nonce_is_never_lower_than_known_target_nonce() { - let mut strategy = MessageDeliveryStrategy::::new(4); - strategy.target_nonce_updated(10, &mut Default::default()); - strategy.source_nonce_updated(header_id(1), 5); - assert_eq!(strategy.source_queue, vec![]); - } - - #[test] - fn source_nonce_is_never_lower_than_latest_known_source_nonce() { - let mut strategy = MessageDeliveryStrategy::::new(4); - strategy.source_nonce_updated(header_id(1), 5); - strategy.source_nonce_updated(header_id(2), 3); - strategy.source_nonce_updated(header_id(2), 5); - assert_eq!(strategy.source_queue, vec![(header_id(1), 5)]); - } - - #[test] - fn target_nonce_is_never_lower_than_latest_known_target_nonce() { - let mut strategy = MessageDeliveryStrategy::::new(4); - strategy.target_nonce_updated(10, &mut Default::default()); - strategy.target_nonce_updated(5, &mut Default::default()); - assert_eq!(strategy.target_nonce, 10); - } - - #[test] - fn updated_target_nonce_removes_queued_entries() { - let mut strategy = MessageDeliveryStrategy::::new(4); - strategy.source_nonce_updated(header_id(1), 5); - strategy.source_nonce_updated(header_id(2), 10); - strategy.source_nonce_updated(header_id(3), 15); - strategy.source_nonce_updated(header_id(4), 20); - strategy.target_nonce_updated(15, &mut Default::default()); - assert_eq!(strategy.source_queue, vec![(header_id(4), 20)]); - } - - #[test] - fn selected_nonces_are_dropped_on_target_nonce_update() { - let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::new(4); - state.nonces_to_submit = Some((header_id(1), 5..=10, 5..=10)); - strategy.target_nonce_updated(7, &mut state); - assert!(state.nonces_to_submit.is_some()); - strategy.target_nonce_updated(10, &mut state); - assert!(state.nonces_to_submit.is_none()); - } - - #[test] - fn submitted_nonces_are_dropped_on_target_nonce_update() { - let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::new(4); - state.nonces_submitted = Some(5..=10); - strategy.target_nonce_updated(7, &mut state); - assert!(state.nonces_submitted.is_some()); - strategy.target_nonce_updated(10, &mut state); - assert!(state.nonces_submitted.is_none()); - } - - #[test] - fn nothing_is_selected_if_something_is_already_selected() { - let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::new(4); - state.nonces_to_submit = Some((header_id(1), 1..=10, 1..=10)); - strategy.source_nonce_updated(header_id(1), 10); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); - } - - #[test] - fn nothing_is_selected_if_something_is_already_submitted() { - let mut state = RaceState::default(); - let mut strategy = MessageDeliveryStrategy::::new(4); - state.nonces_submitted = Some(1..=10); - strategy.source_nonce_updated(header_id(1), 10); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); - } - - #[test] - fn select_nonces_to_deliver_works() { - let mut state = RaceState::<_, _, TestMessageNonce, TestMessagesProof>::default(); - let mut strategy = MessageDeliveryStrategy::::new(4); - strategy.source_nonce_updated(header_id(1), 1); - strategy.source_nonce_updated(header_id(2), 2); - strategy.source_nonce_updated(header_id(3), 6); - strategy.source_nonce_updated(header_id(5), 8); - - state.target_state = Some(ClientState { - best_self: header_id(0), - best_peer: header_id(4), - }); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some(1..=4)); - strategy.target_nonce_updated(4, &mut state); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some(5..=6)); - strategy.target_nonce_updated(6, &mut state); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); - - state.target_state = Some(ClientState { - best_self: header_id(0), - best_peer: header_id(5), - }); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some(7..=8)); - strategy.target_nonce_updated(8, &mut state); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + // If we're here, then the confirmations race did it job && sending side now knows that messages + // have been delivered. Now let's select nonces that we want to deliver. + let selected_nonces = self.strategy.select_nonces_to_deliver(race_state)?.0; + + // Ok - we have new nonces to deliver. But target may still reject new messages, because we haven't + // notified it that (some) messages have been confirmed. So we may want to include updated + // `source.latest_confirmed` in the proof. + // + // Important note: we're including outbound state lane proof whenever there are unconfirmed nonces + // on the target chain. Other strategy is to include it only if it's absolutely necessary. + let latest_confirmed_nonce_at_target = target_nonces.confirmed_nonce.expect(CONFIRMED_NONCE_PROOF); + let outbound_state_proof_required = latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; + + // https://github.com/paritytech/parity-bridges-common/issues/432 + // https://github.com/paritytech/parity-bridges-common/issues/433 + // TODO: number of messages must be no larger than: + // `max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_target)` + + Some((selected_nonces, outbound_state_proof_required)) } } diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 30401cd0baaa9..4b2a9eef04540 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -20,9 +20,6 @@ //! associated data - like messages, lane state, etc) to the target node by //! generating and submitting proof. -// Until there'll be actual message-lane in the runtime. -#![allow(dead_code)] - use crate::message_lane_loop::ClientState; use async_trait::async_trait; @@ -61,36 +58,49 @@ type SourceClientState

= ClientState<

::SourceHeaderId,

= ClientState<

::TargetHeaderId,

::SourceHeaderId>; +/// Nonces on the race client. +#[derive(Debug, Clone)] +pub struct ClientNonces { + /// Latest nonce that is known to the client. + pub latest_nonce: MessageNonce, + /// Latest nonce that is confirmed to the bridged client. This nonce only makes + /// sense in some races. In other races it is `None`. + pub confirmed_nonce: Option, +} + /// One of message lane clients, which is source client for the race. -#[async_trait(?Send)] +#[async_trait] pub trait SourceClient { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; + /// Additional proof parameters required to generate proof. + type ProofParameters; - /// Return latest nonce that is known to the source client. - async fn latest_nonce( + /// Return nonces that are known to the source client. + async fn nonces( &self, at_block: P::SourceHeaderId, - ) -> Result<(P::SourceHeaderId, P::MessageNonce), Self::Error>; + ) -> Result<(P::SourceHeaderId, ClientNonces), Self::Error>; /// Generate proof for delivering to the target client. async fn generate_proof( &self, at_block: P::SourceHeaderId, nonces: RangeInclusive, + proof_parameters: Self::ProofParameters, ) -> Result<(P::SourceHeaderId, RangeInclusive, P::Proof), Self::Error>; } /// One of message lane clients, which is target client for the race. -#[async_trait(?Send)] +#[async_trait] pub trait TargetClient { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; - /// Return latest nonce that is known to the target client. - async fn latest_nonce( + /// Return nonces that are known to the target client. + async fn nonces( &self, at_block: P::TargetHeaderId, - ) -> Result<(P::TargetHeaderId, P::MessageNonce), Self::Error>; + ) -> Result<(P::TargetHeaderId, ClientNonces), Self::Error>; /// Submit proof to the target client. async fn submit_proof( &self, @@ -102,22 +112,26 @@ pub trait TargetClient { /// Race strategy. pub trait RaceStrategy { + /// Additional proof parameters required to generate proof. + type ProofParameters; + /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; - /// Called when latest nonce is updated at source node of the race. - fn source_nonce_updated(&mut self, at_block: SourceHeaderId, nonce: MessageNonce); - /// Called when latest nonce is updated at target node of the race. - fn target_nonce_updated( + /// Called when nonces are updated at source node of the race. + fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonce: ClientNonces); + /// Called when nonces are updated at target node of the race. + fn target_nonces_updated( &mut self, - nonce: MessageNonce, + nonces: ClientNonces, race_state: &mut RaceState, ); /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated /// data) from source to target node. + /// Additionally, parameters required to generate proof are returned. fn select_nonces_to_deliver( &mut self, race_state: &RaceState, - ) -> Option>; + ) -> Option<(RangeInclusive, Self::ProofParameters)>; } /// State of the race. @@ -133,38 +147,44 @@ pub struct RaceState { } /// Run race loop until connection with target or source node is lost. -pub async fn run( - race_source: impl SourceClient

, +pub async fn run>( + race_source: SC, race_source_updated: impl FusedStream>, race_target: impl TargetClient

, race_target_updated: impl FusedStream>, stall_timeout: Duration, - mut strategy: impl RaceStrategy, + mut strategy: impl RaceStrategy< + P::SourceHeaderId, + P::TargetHeaderId, + P::MessageNonce, + P::Proof, + ProofParameters = SC::ProofParameters, + >, ) -> Result<(), FailedClient> { let mut race_state = RaceState::default(); let mut stall_countdown = Instant::now(); let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = true; - let mut source_latest_nonce_required = false; - let source_latest_nonce = futures::future::Fuse::terminated(); + let mut source_nonces_required = false; + let source_nonces = futures::future::Fuse::terminated(); let source_generate_proof = futures::future::Fuse::terminated(); let source_go_offline_future = futures::future::Fuse::terminated(); let mut target_retry_backoff = retry_backoff(); let mut target_client_is_online = true; - let mut target_latest_nonce_required = false; - let target_latest_nonce = futures::future::Fuse::terminated(); + let mut target_nonces_required = false; + let target_nonces = futures::future::Fuse::terminated(); let target_submit_proof = futures::future::Fuse::terminated(); let target_go_offline_future = futures::future::Fuse::terminated(); futures::pin_mut!( race_source_updated, - source_latest_nonce, + source_nonces, source_generate_proof, source_go_offline_future, race_target_updated, - target_latest_nonce, + target_nonces, target_submit_proof, target_go_offline_future, ); @@ -175,7 +195,7 @@ pub async fn run( source_state = race_source_updated.next() => { if let Some(source_state) = source_state { if race_state.source_state.as_ref() != Some(&source_state) { - source_latest_nonce_required = true; + source_nonces_required = true; race_state.source_state = Some(source_state); } } @@ -183,53 +203,53 @@ pub async fn run( target_state = race_target_updated.next() => { if let Some(target_state) = target_state { if race_state.target_state.as_ref() != Some(&target_state) { - target_latest_nonce_required = true; + target_nonces_required = true; race_state.target_state = Some(target_state); } } }, // when nonces are updated - latest_nonce = source_latest_nonce => { - source_latest_nonce_required = false; + nonces = source_nonces => { + source_nonces_required = false; source_client_is_online = process_future_result( - latest_nonce, + nonces, &mut source_retry_backoff, - |(at_block, latest_nonce)| { + |(at_block, nonces)| { log::debug!( target: "bridge", - "Received latest nonce from {}: {:?}", + "Received nonces from {}: {:?}", P::source_name(), - latest_nonce, + nonces, ); - strategy.source_nonce_updated(at_block, latest_nonce); + strategy.source_nonces_updated(at_block, nonces); }, &mut source_go_offline_future, |delay| async_std::task::sleep(delay), - || format!("Error retrieving latest nonce from {}", P::source_name()), + || format!("Error retrieving nonces from {}", P::source_name()), ).fail_if_connection_error(FailedClient::Source)?; }, - latest_nonce = target_latest_nonce => { - target_latest_nonce_required = false; + nonces = target_nonces => { + target_nonces_required = false; target_client_is_online = process_future_result( - latest_nonce, + nonces, &mut target_retry_backoff, - |(_, latest_nonce)| { + |(_, nonces)| { log::debug!( target: "bridge", - "Received latest nonce from {}: {:?}", + "Received nonces from {}: {:?}", P::target_name(), - latest_nonce, + nonces, ); - strategy.target_nonce_updated(latest_nonce, &mut race_state); + strategy.target_nonces_updated(nonces, &mut race_state); }, &mut target_go_offline_future, |delay| async_std::task::sleep(delay), - || format!("Error retrieving latest nonce from {}", P::target_name()), + || format!("Error retrieving nonces from {}", P::target_name()), ).fail_if_connection_error(FailedClient::Target)?; }, @@ -288,26 +308,32 @@ pub async fn run( let nonces_to_deliver = race_state.source_state.as_ref().and_then(|source_state| { strategy .select_nonces_to_deliver(&race_state) - .map(|nonces_range| (source_state.best_self.clone(), nonces_range)) + .map(|(nonces_range, proof_parameters)| { + (source_state.best_self.clone(), nonces_range, proof_parameters) + }) }); - if let Some((at_block, nonces_range)) = nonces_to_deliver { + if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { log::debug!( target: "bridge", "Asking {} to prove nonces in range {:?}", P::source_name(), nonces_range, ); - source_generate_proof.set(race_source.generate_proof(at_block, nonces_range).fuse()); - } else if source_latest_nonce_required { - log::debug!(target: "bridge", "Asking {} about latest generated message nonce", P::source_name()); + source_generate_proof.set( + race_source + .generate_proof(at_block, nonces_range, proof_parameters) + .fuse(), + ); + } else if source_nonces_required { + log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); let at_block = race_state .source_state .as_ref() - .expect("source_latest_nonce_required is only true when source_state is Some; qed") + .expect("source_nonces_required is only true when source_state is Some; qed") .best_self .clone(); - source_latest_nonce.set(race_source.latest_nonce(at_block).fuse()); + source_nonces.set(race_source.nonces(at_block).fuse()); } else { source_client_is_online = true; } @@ -329,15 +355,15 @@ pub async fn run( .fuse(), ); } - if target_latest_nonce_required { - log::debug!(target: "bridge", "Asking {} about latest nonce", P::target_name()); + if target_nonces_required { + log::debug!(target: "bridge", "Asking {} about message nonces", P::target_name()); let at_block = race_state .target_state .as_ref() - .expect("target_latest_nonce_required is only true when target_state is Some; qed") + .expect("target_nonces_required is only true when target_state is Some; qed") .best_self .clone(); - target_latest_nonce.set(race_target.latest_nonce(at_block).fuse()); + target_nonces.set(race_target.nonces(at_block).fuse()); } else { target_client_is_online = true; } diff --git a/relays/messages-relay/src/message_race_receiving.rs b/relays/messages-relay/src/message_race_receiving.rs index d985020fddda1..bf9975717c319 100644 --- a/relays/messages-relay/src/message_race_receiving.rs +++ b/relays/messages-relay/src/message_race_receiving.rs @@ -18,8 +18,8 @@ use crate::message_lane_loop::{ SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }; -use crate::message_race_delivery::DeliveryStrategy; -use crate::message_race_loop::{MessageRace, SourceClient, TargetClient}; +use crate::message_race_loop::{ClientNonces, MessageRace, SourceClient, TargetClient}; +use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; @@ -28,7 +28,7 @@ use relay_utils::FailedClient; use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Message receiving confirmations delivery strategy. -type ReceivingConfirmationsDeliveryStrategy

= DeliveryStrategy< +type ReceivingConfirmationsBasicStrategy

= BasicStrategy<

::TargetHeaderNumber,

::TargetHeaderHash,

::SourceHeaderNumber, @@ -60,7 +60,7 @@ pub async fn run( }, source_state_updates, stall_timeout, - ReceivingConfirmationsDeliveryStrategy::

::new(std::u32::MAX.into()), + ReceivingConfirmationsBasicStrategy::

::new(std::u32::MAX.into()), ) .await } @@ -91,31 +91,38 @@ struct ReceivingConfirmationsRaceSource { _phantom: PhantomData

, } -#[async_trait(?Send)] +#[async_trait] impl SourceClient> for ReceivingConfirmationsRaceSource where P: MessageLane, C: MessageLaneTargetClient

, { type Error = C::Error; + type ProofParameters = (); - async fn latest_nonce( + async fn nonces( &self, at_block: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { - let result = self.client.latest_received_nonce(at_block).await; + ) -> Result<(TargetHeaderIdOf

, ClientNonces), Self::Error> { + let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { - if let Ok((_, target_latest_received_nonce)) = result.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(*target_latest_received_nonce); - } + metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); } - result + Ok(( + at_block, + ClientNonces { + latest_nonce: latest_received_nonce, + confirmed_nonce: None, + }, + )) } + #[allow(clippy::unit_arg)] async fn generate_proof( &self, at_block: TargetHeaderIdOf

, nonces: RangeInclusive, + _proof_parameters: Self::ProofParameters, ) -> Result< ( TargetHeaderIdOf

, @@ -138,7 +145,7 @@ struct ReceivingConfirmationsRaceTarget { _phantom: PhantomData

, } -#[async_trait(?Send)] +#[async_trait] impl TargetClient> for ReceivingConfirmationsRaceTarget where P: MessageLane, @@ -146,27 +153,32 @@ where { type Error = C::Error; - async fn latest_nonce( + async fn nonces( &self, at_block: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { - let result = self.client.latest_confirmed_received_nonce(at_block).await; + ) -> Result<(SourceHeaderIdOf

, ClientNonces), Self::Error> { + let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { - if let Ok((_, source_latest_confirmed_nonce)) = result.as_ref() { - metrics_msg.update_source_latest_confirmed_nonce::

(*source_latest_confirmed_nonce); - } + metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); } - result + Ok(( + at_block, + ClientNonces { + latest_nonce: latest_confirmed_nonce, + confirmed_nonce: None, + }, + )) } async fn submit_proof( &self, generated_at_block: TargetHeaderIdOf

, - _nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::MessagesReceivingProof, ) -> Result, Self::Error> { self.client .submit_messages_receiving_proof(generated_at_block, proof) - .await + .await?; + Ok(nonces) } } diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs new file mode 100644 index 0000000000000..a22331fe07d13 --- /dev/null +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -0,0 +1,334 @@ +// Copyright 2019-2020 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. + +//! Basic delivery strategy. The strategy selects nonces if: +//! +//! 1) there are more nonces on the source side than on the target side; +//! 2) new nonces may be proved to target node (i.e. they have appeared at the +//! block, which is known to the target node). + +use crate::message_race_loop::{ClientNonces, RaceState, RaceStrategy}; + +use num_traits::{One, Zero}; +use relay_utils::HeaderId; +use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive}; + +/// Nonces delivery strategy. +#[derive(Debug)] +pub struct BasicStrategy { + /// All queued nonces. + source_queue: VecDeque<(HeaderId, Nonce)>, + /// Best nonce known to target node. + target_nonce: Nonce, + /// Max nonces to relay in single transaction. + max_nonces_to_relay_in_single_tx: Nonce, + /// Unused generic types dump. + _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, +} + +impl + BasicStrategy +{ + /// Create new delivery strategy. + pub fn new(max_nonces_to_relay_in_single_tx: Nonce) -> Self { + BasicStrategy { + source_queue: VecDeque::new(), + target_nonce: Default::default(), + max_nonces_to_relay_in_single_tx, + _phantom: Default::default(), + } + } +} + +impl + RaceStrategy< + HeaderId, + HeaderId, + Nonce, + Proof, + > for BasicStrategy +where + SourceHeaderHash: Clone, + SourceHeaderNumber: Clone + Ord, + Nonce: Clone + Copy + From + Ord + std::ops::Add + One + Zero, +{ + type ProofParameters = (); + + fn is_empty(&self) -> bool { + self.source_queue.is_empty() + } + + fn source_nonces_updated( + &mut self, + at_block: HeaderId, + nonces: ClientNonces, + ) { + let nonce = nonces.latest_nonce; + + if nonce <= self.target_nonce { + return; + } + + match self.source_queue.back() { + Some((_, prev_nonce)) if *prev_nonce < nonce => (), + Some(_) => return, + None => (), + } + + self.source_queue.push_back((at_block, nonce)) + } + + fn target_nonces_updated( + &mut self, + nonces: ClientNonces, + race_state: &mut RaceState< + HeaderId, + HeaderId, + Nonce, + Proof, + >, + ) { + let nonce = nonces.latest_nonce; + + if nonce < self.target_nonce { + return; + } + + while let Some(true) = self + .source_queue + .front() + .map(|(_, source_nonce)| *source_nonce <= nonce) + { + self.source_queue.pop_front(); + } + + let need_to_select_new_nonces = race_state + .nonces_to_submit + .as_ref() + .map(|(_, nonces, _)| *nonces.end() <= nonce) + .unwrap_or(false); + if need_to_select_new_nonces { + race_state.nonces_to_submit = None; + } + + let need_new_nonces_to_submit = race_state + .nonces_submitted + .as_ref() + .map(|nonces| *nonces.end() <= nonce) + .unwrap_or(false); + if need_new_nonces_to_submit { + race_state.nonces_submitted = None; + } + + self.target_nonce = nonce; + } + + fn select_nonces_to_deliver( + &mut self, + race_state: &RaceState< + HeaderId, + HeaderId, + Nonce, + Proof, + >, + ) -> Option<(RangeInclusive, Self::ProofParameters)> { + // if we have already selected nonces that we want to submit, do nothing + if race_state.nonces_to_submit.is_some() { + return None; + } + + // if we already submitted some nonces, do nothing + if race_state.nonces_submitted.is_some() { + return None; + } + + // 1) we want to deliver all nonces, starting from `target_nonce + 1` + // 2) we want to deliver at most `self.max_nonces_to_relay_in_single_tx` nonces in this batch + // 3) we can't deliver new nonce until header, that has emitted this nonce, is finalized + // by target client + let nonces_begin = self.target_nonce + 1.into(); + let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; + let mut nonces_end = None; + let mut i = Zero::zero(); + + // https://github.com/paritytech/parity-bridges-common/issues/433 + // TODO: instead of limiting number of messages by number, provide custom limit callback here. + // In delivery race it'll be weight-based callback. In receiving race it'll be unlimited callback. + + while i < self.max_nonces_to_relay_in_single_tx { + let nonce = nonces_begin + i; + + // if queue is empty, we don't need to prove anything + let (first_queued_at, first_queued_nonce) = match self.source_queue.front() { + Some((first_queued_at, first_queued_nonce)) => ((*first_queued_at).clone(), *first_queued_nonce), + None => break, + }; + + // if header that has queued the message is not yet finalized at bridged chain, + // we can't prove anything + if first_queued_at.0 > best_header_at_target.0 { + break; + } + + // ok, we may deliver this nonce + nonces_end = Some(nonce); + + // probably remove it from the queue? + if nonce == first_queued_nonce { + self.source_queue.pop_front(); + } + + i = i + One::one(); + } + + nonces_end.map(|nonces_end| (RangeInclusive::new(nonces_begin, nonces_end), ())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::message_lane::MessageLane; + use crate::message_lane_loop::{ + tests::{header_id, TestMessageLane, TestMessageNonce, TestMessagesProof}, + ClientState, + }; + + type BasicStrategy

= super::BasicStrategy< +

::SourceHeaderNumber, +

::SourceHeaderHash, +

::TargetHeaderNumber, +

::TargetHeaderHash, +

::MessageNonce, +

::MessagesProof, + >; + + fn nonces(latest_nonce: TestMessageNonce) -> ClientNonces { + ClientNonces { + latest_nonce, + confirmed_nonce: None, + } + } + + #[test] + fn strategy_is_empty_works() { + let mut strategy = BasicStrategy::::new(4); + assert_eq!(strategy.is_empty(), true); + strategy.source_nonces_updated(header_id(1), nonces(1)); + assert_eq!(strategy.is_empty(), false); + } + + #[test] + fn source_nonce_is_never_lower_than_known_target_nonce() { + let mut strategy = BasicStrategy::::new(4); + strategy.target_nonces_updated(nonces(10), &mut Default::default()); + strategy.source_nonces_updated(header_id(1), nonces(5)); + assert_eq!(strategy.source_queue, vec![]); + } + + #[test] + fn source_nonce_is_never_lower_than_latest_known_source_nonce() { + let mut strategy = BasicStrategy::::new(4); + strategy.source_nonces_updated(header_id(1), nonces(5)); + strategy.source_nonces_updated(header_id(2), nonces(3)); + strategy.source_nonces_updated(header_id(2), nonces(5)); + assert_eq!(strategy.source_queue, vec![(header_id(1), 5)]); + } + + #[test] + fn target_nonce_is_never_lower_than_latest_known_target_nonce() { + let mut strategy = BasicStrategy::::new(4); + strategy.target_nonces_updated(nonces(10), &mut Default::default()); + strategy.target_nonces_updated(nonces(5), &mut Default::default()); + assert_eq!(strategy.target_nonce, 10); + } + + #[test] + fn updated_target_nonce_removes_queued_entries() { + let mut strategy = BasicStrategy::::new(4); + strategy.source_nonces_updated(header_id(1), nonces(5)); + strategy.source_nonces_updated(header_id(2), nonces(10)); + strategy.source_nonces_updated(header_id(3), nonces(15)); + strategy.source_nonces_updated(header_id(4), nonces(20)); + strategy.target_nonces_updated(nonces(15), &mut Default::default()); + assert_eq!(strategy.source_queue, vec![(header_id(4), 20)]); + } + + #[test] + fn selected_nonces_are_dropped_on_target_nonce_update() { + let mut state = RaceState::default(); + let mut strategy = BasicStrategy::::new(4); + state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); + strategy.target_nonces_updated(nonces(7), &mut state); + assert!(state.nonces_to_submit.is_some()); + strategy.target_nonces_updated(nonces(10), &mut state); + assert!(state.nonces_to_submit.is_none()); + } + + #[test] + fn submitted_nonces_are_dropped_on_target_nonce_update() { + let mut state = RaceState::default(); + let mut strategy = BasicStrategy::::new(4); + state.nonces_submitted = Some(5..=10); + strategy.target_nonces_updated(nonces(7), &mut state); + assert!(state.nonces_submitted.is_some()); + strategy.target_nonces_updated(nonces(10), &mut state); + assert!(state.nonces_submitted.is_none()); + } + + #[test] + fn nothing_is_selected_if_something_is_already_selected() { + let mut state = RaceState::default(); + let mut strategy = BasicStrategy::::new(4); + state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); + strategy.source_nonces_updated(header_id(1), nonces(10)); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn nothing_is_selected_if_something_is_already_submitted() { + let mut state = RaceState::default(); + let mut strategy = BasicStrategy::::new(4); + state.nonces_submitted = Some(1..=10); + strategy.source_nonces_updated(header_id(1), nonces(10)); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn select_nonces_to_deliver_works() { + let mut state = RaceState::<_, _, TestMessageNonce, TestMessagesProof>::default(); + let mut strategy = BasicStrategy::::new(4); + strategy.source_nonces_updated(header_id(1), nonces(1)); + strategy.source_nonces_updated(header_id(2), nonces(2)); + strategy.source_nonces_updated(header_id(3), nonces(6)); + strategy.source_nonces_updated(header_id(5), nonces(8)); + + state.target_state = Some(ClientState { + best_self: header_id(0), + best_peer: header_id(4), + }); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some((1..=4, ()))); + strategy.target_nonces_updated(nonces(4), &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some((5..=6, ()))); + strategy.target_nonces_updated(nonces(6), &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + + state.target_state = Some(ClientState { + best_self: header_id(0), + best_peer: header_id(5), + }); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some((7..=8, ()))); + strategy.target_nonces_updated(nonces(8), &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } +} diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index 25a27f754fd9e..487e4bb6347f6 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -21,4 +21,5 @@ frame-support = "2.0" frame-system = "2.0" pallet-transaction-payment = "2.0" sp-core = "2.0" +sp-keyring = "2.0" sp-runtime = "2.0" diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index a1de85ec39fbb..d8f9232b25e0f 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -16,6 +16,7 @@ rand = "0.7" # Bridge dependencies +bp-message-lane = { path = "../../primitives/message-lane" } bp-runtime = { path = "../../primitives/runtime" } headers-relay = { path = "../headers-relay" } relay-utils = { path = "../utils" } @@ -27,6 +28,8 @@ frame-system = "2.0" pallet-balances = "2.0" sp-core = "2.0" sp-runtime = "2.0" +sp-std = "2.0" +sp-trie = "2.0" sp-version = "2.0" #[dev-dependencies] diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 9ff54c4b3ab2c..1e0075f228c43 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -17,11 +17,13 @@ //! Substrate node client. use crate::chain::{Chain, ChainWithBalances}; -use crate::error::Error; -use crate::rpc::Substrate; -use crate::{ConnectionParams, Result}; +use crate::rpc::{Substrate, SubstrateMessageLane}; +use crate::{ConnectionParams, Error, Result}; +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::InstanceId; use codec::Decode; +use frame_support::weights::Weight; use frame_system::AccountInfo; use jsonrpsee::common::DeserializeOwned; use jsonrpsee::raw::RawClient; @@ -30,7 +32,9 @@ use jsonrpsee::{client::Subscription, Client as RpcClient}; use num_traits::Zero; use pallet_balances::AccountData; use sp_core::Bytes; +use sp_trie::StorageProof; use sp_version::RuntimeVersion; +use std::ops::RangeInclusive; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; @@ -42,15 +46,26 @@ pub type OpaqueGrandpaAuthoritiesSet = Vec; /// Substrate client type. /// -/// Cloning Client is a cheap operation. -#[derive(Clone)] +/// Cloning `Client` is a cheap operation. pub struct Client { + /// Client connection params. + params: ConnectionParams, /// Substrate RPC client. client: RpcClient, /// Genesis block hash. genesis_hash: C::Hash, } +impl Clone for Client { + fn clone(&self) -> Self { + Client { + params: self.params.clone(), + client: self.client.clone(), + genesis_hash: self.genesis_hash, + } + } +} + impl std::fmt::Debug for Client { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { fmt.debug_struct("Client") @@ -62,15 +77,33 @@ impl std::fmt::Debug for Client { impl Client { /// Returns client that is able to call RPCs on Substrate node over websocket connection. pub async fn new(params: ConnectionParams) -> Result { - let uri = format!("ws://{}:{}", params.host, params.port); - let transport = WsTransportClient::new(&uri).await?; - let raw_client = RawClient::new(transport); - let client: RpcClient = raw_client.into(); + let client = Self::build_client(params.clone()).await?; let number: C::BlockNumber = Zero::zero(); let genesis_hash = Substrate::::chain_get_block_hash(&client, number).await?; - Ok(Self { client, genesis_hash }) + Ok(Self { + params, + client, + genesis_hash, + }) + } + + /// Reopen client connection. + pub async fn reconnect(self) -> Result { + Ok(Self { + params: self.params.clone(), + client: Self::build_client(self.params).await?, + genesis_hash: self.genesis_hash, + }) + } + + /// Build client to use in connection. + async fn build_client(params: ConnectionParams) -> Result { + let uri = format!("ws://{}:{}", params.host, params.port); + let transport = WsTransportClient::new(&uri).await?; + let raw_client = RawClient::new(transport); + Ok(raw_client.into()) } } @@ -80,6 +113,11 @@ impl Client { &self.genesis_hash } + /// Return hash of the best finalized block. + pub async fn best_finalized_header_hash(&self) -> Result { + Ok(Substrate::::chain_get_finalized_head(&self.client).await?) + } + /// Returns the best Substrate header. pub async fn best_header(&self) -> Result where @@ -169,6 +207,47 @@ impl Client { .map_err(Into::into) } + /// Returns proof-of-message(s) in given inclusive range. + pub async fn prove_messages( + &self, + instance: InstanceId, + lane: LaneId, + range: RangeInclusive, + include_outbound_lane_state: bool, + at_block: C::Hash, + ) -> Result<(Weight, StorageProof)> { + let (dispatch_weight, encoded_trie_nodes) = SubstrateMessageLane::::prove_messages( + &self.client, + instance, + lane, + *range.start(), + *range.end(), + include_outbound_lane_state, + Some(at_block), + ) + .await + .map_err(Error::Request)?; + let decoded_trie_nodes: Vec> = + Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; + Ok((dispatch_weight, StorageProof::new(decoded_trie_nodes))) + } + + /// Returns proof-of-message(s) delivery. + pub async fn prove_messages_delivery( + &self, + instance: InstanceId, + lane: LaneId, + at_block: C::Hash, + ) -> Result { + let encoded_trie_nodes = + SubstrateMessageLane::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) + .await + .map_err(Error::Request)?; + let decoded_trie_nodes: Vec> = + Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; + Ok(StorageProof::new(decoded_trie_nodes)) + } + /// Return new justifications stream. pub async fn subscribe_justifications(self) -> Result { Ok(self diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index b92e6d02885ec..567fc4a61984e 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -31,6 +31,9 @@ pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthori pub use crate::error::{Error, Result}; pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; +/// Header id used by the chain. +pub type HeaderIdOf = relay_utils::HeaderId, BlockNumberOf>; + /// Substrate-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { diff --git a/relays/substrate-client/src/rpc.rs b/relays/substrate-client/src/rpc.rs index 552b20de622b5..89ed36695abcc 100644 --- a/relays/substrate-client/src/rpc.rs +++ b/relays/substrate-client/src/rpc.rs @@ -23,6 +23,9 @@ use crate::chain::Chain; +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::InstanceId; +use frame_support::weights::Weight; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, @@ -33,6 +36,8 @@ jsonrpsee::rpc_api! { pub(crate) Substrate { #[rpc(method = "chain_getHeader", positional_params)] fn chain_get_header(block_hash: Option) -> C::Header; + #[rpc(method = "chain_getFinalizedHead", positional_params)] + fn chain_get_finalized_head() -> C::Hash; #[rpc(method = "chain_getBlock", positional_params)] fn chain_get_block(block_hash: Option) -> C::SignedBlock; #[rpc(method = "chain_getBlockHash", positional_params)] @@ -48,4 +53,23 @@ jsonrpsee::rpc_api! { #[rpc(method = "state_getRuntimeVersion", positional_params)] fn runtime_version() -> RuntimeVersion; } + + pub(crate) SubstrateMessageLane { + #[rpc(method = "messageLane_proveMessages", positional_params)] + fn prove_messages( + instance: InstanceId, + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + include_outbound_lane_state: bool, + block: Option, + ) -> (Weight, Bytes); + + #[rpc(method = "messageLane_proveMessagesDelivery", positional_params)] + fn prove_messages_delivery( + instance: InstanceId, + lane: LaneId, + block: Option, + ) -> Bytes; + } } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index c5dca17c9fab2..2489ebcf95bec 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -20,6 +20,7 @@ structopt = "0.3" bp-message-lane = { path = "../../primitives/message-lane" } bp-millau = { path = "../../primitives/millau" } +bp-runtime = { path = "../../primitives/runtime" } bp-rialto = { path = "../../primitives/rialto" } headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } @@ -37,3 +38,4 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } frame-support = "2.0" sp-core = "2.0" sp-runtime = "2.0" +sp-trie = "2.0" diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index cff2d36211108..d3ad78c3a1a0e 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -50,6 +50,22 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, + /// Serve given lane of Millau -> Rialto messages. + MillauMessagesToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + /// Hex-encoded id of lane that should be served by relay. + #[structopt(long)] + lane: HexLaneId, + }, /// Submit message to given Rialto -> Millau lane. SubmitMillauToRialtoMessage { #[structopt(flatten)] diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 6d36e7606159e..98c30ff0be58a 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -36,7 +36,10 @@ mod cli; mod headers_maintain; mod headers_pipeline; mod headers_target; +mod messages_source; +mod messages_target; mod millau_headers_to_rialto; +mod millau_messages_to_rialto; mod rialto_headers_to_millau; fn main() { @@ -94,8 +97,47 @@ async fn run_command(command: cli::Command) -> Result<(), String> { millau_sign.millau_signer_password.as_deref(), ) .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; } + cli::Command::MillauMessagesToRialto { + millau, + millau_sign, + rialto, + rialto_sign, + prometheus_params, + lane, + } => { + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let rialto_sign = RialtoSigningParams::from_suri( + &rialto_sign.rialto_signer, + rialto_sign.rialto_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + + millau_messages_to_rialto::run( + millau_client, + millau_sign, + rialto_client, + rialto_sign, + lane.into(), + prometheus_params.into(), + ); + } cli::Command::SubmitMillauToRialtoMessage { millau, millau_sign, diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs new file mode 100644 index 0000000000000..46e990e101682 --- /dev/null +++ b/relays/substrate/src/messages_source.rs @@ -0,0 +1,225 @@ +// Copyright 2019-2020 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 . + +//! Substrate client as Substrate messages source. The chain we connect to should have +//! runtime that implements `HeaderApi` to allow bridging with +//! chain. + +use async_trait::async_trait; +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::InstanceId; +use codec::{Decode, Encode}; +use frame_support::weights::Weight; +use messages_relay::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane_loop::{ClientState, SourceClient, SourceClientState}, +}; +use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; +use relay_utils::HeaderId; +use sp_core::Bytes; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; +use sp_trie::StorageProof; +use std::{marker::PhantomData, ops::RangeInclusive}; + +/// Intermediate message proof returned by the source Substrate node. Includes everything +/// required to submit to the target node: cumulative dispatch weight of bundled messages and +/// the proof itself. +pub type SubstrateMessagesProof = (Weight, (HashOf, StorageProof, LaneId, MessageNonce, MessageNonce)); + +/// Substrate client as Substrate messages source. +pub struct SubstrateMessagesSource { + client: Client, + tx_maker: M, + lane: LaneId, + instance: InstanceId, + _marker: PhantomData

, +} + +/// Substrate transactions maker. +#[async_trait] +pub trait SubstrateTransactionMaker: Clone + Send + Sync { + /// Signed transaction type. + type SignedTransaction: Send + Sync + Encode; + + /// Make messages receiving proof transaction. + async fn make_messages_receiving_proof_transaction( + &self, + generated_at_block: TargetHeaderIdOf

, + proof: P::MessagesReceivingProof, + ) -> Result; +} + +impl SubstrateMessagesSource { + /// Create new Substrate headers source. + pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self { + SubstrateMessagesSource { + client, + tx_maker, + lane, + instance, + _marker: Default::default(), + } + } +} + +impl Clone for SubstrateMessagesSource { + fn clone(&self) -> Self { + Self { + client: self.client.clone(), + tx_maker: self.tx_maker.clone(), + lane: self.lane, + instance: self.instance, + _marker: Default::default(), + } + } +} + +#[async_trait] +impl SourceClient

for SubstrateMessagesSource +where + C: Chain, + C::Header: DeserializeOwned, + C::Index: DeserializeOwned, + ::Number: Into, + P: MessageLane< + MessageNonce = MessageNonce, + MessagesProof = SubstrateMessagesProof, + SourceHeaderNumber = ::Number, + SourceHeaderHash = ::Hash, + >, + P::TargetHeaderNumber: Decode, + P::TargetHeaderHash: Decode, + M: SubstrateTransactionMaker, +{ + type Error = SubstrateError; + + async fn reconnect(mut self) -> Result { + let new_client = self.client.clone().reconnect().await?; + self.client = new_client; + Ok(self) + } + + async fn state(&self) -> Result, Self::Error> { + read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>(&self.client, P::TARGET_NAME).await + } + + async fn latest_generated_nonce( + &self, + id: SourceHeaderIdOf

, + ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { + let encoded_response = self + .client + .state_call( + // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 + "OutboundLaneApi_latest_generated_nonce".into(), + Bytes(self.lane.encode()), + Some(id.1), + ) + .await?; + let latest_generated_nonce: P::MessageNonce = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + Ok((id, latest_generated_nonce)) + } + + async fn latest_confirmed_received_nonce( + &self, + id: SourceHeaderIdOf

, + ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { + let encoded_response = self + .client + .state_call( + // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 + "OutboundLaneApi_latest_received_nonce".into(), + Bytes(self.lane.encode()), + Some(id.1), + ) + .await?; + let latest_received_nonce: P::MessageNonce = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + Ok((id, latest_received_nonce)) + } + + async fn prove_messages( + &self, + id: SourceHeaderIdOf

, + nonces: RangeInclusive, + include_outbound_lane_state: bool, + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { + let (weight, proof) = self + .client + .prove_messages( + self.instance, + self.lane, + nonces.clone(), + include_outbound_lane_state, + id.1, + ) + .await?; + let proof = (id.1, proof, self.lane, *nonces.start(), *nonces.end()); + Ok((id, nonces, (weight, proof))) + } + + async fn submit_messages_receiving_proof( + &self, + generated_at_block: TargetHeaderIdOf

, + proof: P::MessagesReceivingProof, + ) -> Result<(), Self::Error> { + let tx = self + .tx_maker + .make_messages_receiving_proof_transaction(generated_at_block, proof) + .await?; + self.client.submit_extrinsic(Bytes(tx.encode())).await?; + Ok(()) + } +} + +pub async fn read_client_state( + self_client: &Client, + bridged_chain_name: &str, +) -> Result, HeaderId>, SubstrateError> +where + SelfChain: Chain, + SelfChain::Header: DeserializeOwned, + SelfChain::Index: DeserializeOwned, + BridgedHeaderHash: Decode, + BridgedHeaderNumber: Decode, +{ + // let's read our state first: we need best finalized header hash on **this** chain + let self_best_finalized_header_hash = self_client.best_finalized_header_hash().await?; + let self_best_finalized_header = self_client.header_by_hash(self_best_finalized_header_hash).await?; + let self_best_finalized_id = HeaderId(*self_best_finalized_header.number(), self_best_finalized_header_hash); + + // now let's read id of best finalized peer header at our best finalized block + let best_finalized_peer_on_self_method = format!("{}HeaderApi_finalized_block", bridged_chain_name); + let encoded_best_finalized_peer_on_self = self_client + .state_call( + best_finalized_peer_on_self_method, + Bytes(Vec::new()), + Some(self_best_finalized_header_hash), + ) + .await?; + let decoded_best_finalized_peer_on_self: (BridgedHeaderNumber, BridgedHeaderHash) = + Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + let peer_on_self_best_finalized_id = HeaderId( + decoded_best_finalized_peer_on_self.0, + decoded_best_finalized_peer_on_self.1, + ); + + Ok(ClientState { + best_self: self_best_finalized_id, + best_peer: peer_on_self_best_finalized_id, + }) +} diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs new file mode 100644 index 0000000000000..541b4dc0f2d85 --- /dev/null +++ b/relays/substrate/src/messages_target.rs @@ -0,0 +1,176 @@ +// Copyright 2019-2020 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 . + +//! Substrate client as Substrate messages target. The chain we connect to should have +//! runtime that implements `HeaderApi` to allow bridging with +//! chain. + +use crate::messages_source::read_client_state; + +use async_trait::async_trait; +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::InstanceId; +use codec::{Decode, Encode}; +use messages_relay::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane_loop::{TargetClient, TargetClientState}, +}; +use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; +use sp_core::Bytes; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; +use sp_trie::StorageProof; +use std::{marker::PhantomData, ops::RangeInclusive}; + +/// Substrate client as Substrate messages target. +pub struct SubstrateMessagesTarget { + client: Client, + tx_maker: M, + lane: LaneId, + instance: InstanceId, + _marker: PhantomData

, +} + +/// Substrate transactions maker. +#[async_trait] +pub trait SubstrateTransactionMaker: Clone + Send + Sync { + /// Signed transaction type. + type SignedTransaction: Send + Sync + Encode; + + /// Make messages delivery transaction. + async fn make_messages_delivery_transaction( + &self, + generated_at_header: SourceHeaderIdOf

, + nonces: RangeInclusive, + proof: P::MessagesProof, + ) -> Result; +} + +impl SubstrateMessagesTarget { + /// Create new Substrate headers target. + pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self { + SubstrateMessagesTarget { + client, + tx_maker, + lane, + instance, + _marker: Default::default(), + } + } +} + +impl Clone for SubstrateMessagesTarget { + fn clone(&self) -> Self { + Self { + client: self.client.clone(), + tx_maker: self.tx_maker.clone(), + lane: self.lane, + instance: self.instance, + _marker: Default::default(), + } + } +} + +#[async_trait] +impl TargetClient

for SubstrateMessagesTarget +where + C: Chain, + C::Header: DeserializeOwned, + C::Index: DeserializeOwned, + ::Number: Into, + P: MessageLane< + MessageNonce = MessageNonce, + MessagesReceivingProof = (HashOf, StorageProof, LaneId), + TargetHeaderNumber = ::Number, + TargetHeaderHash = ::Hash, + >, + P::SourceHeaderNumber: Decode, + P::SourceHeaderHash: Decode, + M: SubstrateTransactionMaker, +{ + type Error = SubstrateError; + + async fn reconnect(mut self) -> Result { + let new_client = self.client.clone().reconnect().await?; + self.client = new_client; + Ok(self) + } + + async fn state(&self) -> Result, Self::Error> { + read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>(&self.client, P::SOURCE_NAME).await + } + + async fn latest_received_nonce( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { + let encoded_response = self + .client + .state_call( + // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 + "InboundLaneApi_latest_received_nonce".into(), + Bytes(self.lane.encode()), + Some(id.1), + ) + .await?; + let latest_received_nonce: P::MessageNonce = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + Ok((id, latest_received_nonce)) + } + + async fn latest_confirmed_received_nonce( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { + let encoded_response = self + .client + .state_call( + // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 + "OutboundLaneApi_latest_received_nonce".into(), + Bytes(self.lane.encode()), + Some(id.1), + ) + .await?; + let latest_received_nonce: P::MessageNonce = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + Ok((id, latest_received_nonce)) + } + + async fn prove_messages_receiving( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error> { + let proof = self + .client + .prove_messages_delivery(self.instance, self.lane, id.1) + .await?; + let proof = (id.1, proof, self.lane); + Ok((id, proof)) + } + + async fn submit_messages_proof( + &self, + generated_at_header: SourceHeaderIdOf

, + nonces: RangeInclusive, + proof: P::MessagesProof, + ) -> Result, Self::Error> { + let tx = self + .tx_maker + .make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof) + .await?; + self.client.submit_extrinsic(Bytes(tx.encode())).await?; + Ok(nonces) + } +} diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs new file mode 100644 index 0000000000000..47a5158b552ef --- /dev/null +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -0,0 +1,171 @@ +// Copyright 2019-2020 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 . + +//! Millau-to-Rialto messages sync entrypoint. + +use crate::messages_source::{SubstrateMessagesSource, SubstrateTransactionMaker as SubstrateSourceTransactionMaker}; +use crate::messages_target::{SubstrateMessagesTarget, SubstrateTransactionMaker as SubstrateTargetTransactionMaker}; +use crate::{MillauClient, RialtoClient}; + +use async_trait::async_trait; +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; +use frame_support::weights::Weight; +use messages_relay::message_lane::MessageLane; +use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{BlockNumberOf, Error as SubstrateError, HashOf, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; +use sp_trie::StorageProof; +use std::{ops::RangeInclusive, time::Duration}; + +/// Millau -> Rialto messages proof: +/// +/// - cumulative dispatch-weight of messages in the batch; +/// - proof that we'll actually submit to the Rialto node. +type FromMillauMessagesProof = ( + Weight, + (HashOf, StorageProof, LaneId, MessageNonce, MessageNonce), +); +/// Rialto -> Millau messages receiving proof. +type FromRialtoMessagesReceivingProof = (HashOf, StorageProof, LaneId); + +/// Millau-to-Rialto messages pipeline. +#[derive(Debug, Clone, Copy)] +struct MillauMessagesToRialto; + +impl MessageLane for MillauMessagesToRialto { + const SOURCE_NAME: &'static str = "Millau"; + const TARGET_NAME: &'static str = "Rialto"; + + type MessageNonce = MessageNonce; + type MessagesProof = FromMillauMessagesProof; + type MessagesReceivingProof = FromRialtoMessagesReceivingProof; + + type SourceHeaderNumber = BlockNumberOf; + type SourceHeaderHash = HashOf; + + type TargetHeaderNumber = BlockNumberOf; + type TargetHeaderHash = HashOf; +} + +/// Millau node as messages source. +type MillauSourceClient = SubstrateMessagesSource; + +/// Millau transaction maker. +#[derive(Clone)] +struct MillauTransactionMaker { + client: MillauClient, + sign: MillauSigningParams, +} + +#[async_trait] +impl SubstrateSourceTransactionMaker for MillauTransactionMaker { + type SignedTransaction = ::SignedTransaction; + + async fn make_messages_receiving_proof_transaction( + &self, + _generated_at_block: RialtoHeaderId, + proof: FromRialtoMessagesReceivingProof, + ) -> Result { + let account_id = self.sign.signer.public().as_array_ref().clone().into(); + let nonce = self.client.next_account_index(account_id).await?; + let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); + let transaction = Millau::sign_transaction(&self.client, &self.sign.signer, nonce, call); + Ok(transaction) + } +} + +/// Rialto node as messages target. +type RialtoTargetClient = SubstrateMessagesTarget; + +/// Rialto transaction maker. +#[derive(Clone)] +struct RialtoTransactionMaker { + client: RialtoClient, + relayer_id: bp_millau::AccountId, + sign: RialtoSigningParams, +} + +#[async_trait] +impl SubstrateTargetTransactionMaker for RialtoTransactionMaker { + type SignedTransaction = ::SignedTransaction; + + async fn make_messages_delivery_transaction( + &self, + _generated_at_header: MillauHeaderId, + _nonces: RangeInclusive, + proof: FromMillauMessagesProof, + ) -> Result { + let (dispatch_weight, proof) = proof; + let account_id = self.sign.signer.public().as_array_ref().clone().into(); + let nonce = self.client.next_account_index(account_id).await?; + let call = + rialto_runtime::MessageLaneCall::receive_messages_proof(self.relayer_id.clone(), proof, dispatch_weight) + .into(); + let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + Ok(transaction) + } +} + +/// Run Millau-to-Rialto messages sync. +pub fn run( + millau_client: MillauClient, + millau_sign: MillauSigningParams, + rialto_client: RialtoClient, + rialto_sign: RialtoSigningParams, + lane: LaneId, + metrics_params: Option, +) { + let millau_tick = Duration::from_secs(5); + let rialto_tick = Duration::from_secs(5); + let reconnect_delay = Duration::from_secs(10); + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id = millau_sign.signer.public().as_array_ref().clone().into(); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane, + source_tick: millau_tick, + target_tick: rialto_tick, + reconnect_delay, + stall_timeout, + max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + }, + MillauSourceClient::new( + millau_client.clone(), + MillauTransactionMaker { + client: millau_client, + sign: millau_sign, + }, + lane, + RIALTO_BRIDGE_INSTANCE, + ), + RialtoTargetClient::new( + rialto_client.clone(), + RialtoTransactionMaker { + client: rialto_client, + relayer_id, + sign: rialto_sign, + }, + lane, + MILLAU_BRIDGE_INSTANCE, + ), + metrics_params, + futures::future::pending(), + ); +} From afe983fbc5f7cfa9aec616f27a1e4b65897efcc1 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 5 Nov 2020 14:19:20 -0500 Subject: [PATCH 0212/1210] Allow Substrate Pallet to be Initialized via Dipatchable (#481) * Add dispatchable for intializing pallet * Add Polkadot JS types for Substrate bridge pallet * Ensure Root is the only one that can initialize the pallet * Add some tests * Pack initialization data into struct * Only allow pallet to be initialized once * Use new initialization config in nodes * Rename ScheduledChange in Ethereum pallet We're renaming it to prevent clashes with Substrate bridge pallet type of the same name. This is relevant when importing types to Polkadot JS Apps. * Move all Polkadot JS types into one file * Appease Clippy --- bin/millau/node/src/chain_spec.rs | 14 +- bin/rialto/node/src/chain_spec.rs | 5 +- bin/rialto/runtime/src/millau.rs | 14 +- modules/ethereum/src/lib.rs | 16 +-- modules/ethereum/src/validators.rs | 4 +- modules/ethereum/src/verification.rs | 6 +- modules/substrate/src/lib.rs | 194 ++++++++++++++++++++------- modules/substrate/src/storage.rs | 16 +++ 8 files changed, 193 insertions(+), 76 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index a3e95398fda96..9d29d8ca7b469 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -155,7 +155,10 @@ fn testnet_genesis( pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), - pallet_substrate_bridge: load_rialto_bridge_config(), + pallet_substrate_bridge: Some(BridgeRialtoConfig { + // We'll initialize the pallet with a dispatchable instead. + init_data: None, + }), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { keys: initial_authorities @@ -165,12 +168,3 @@ fn testnet_genesis( }), } } - -fn load_rialto_bridge_config() -> Option { - Some(BridgeRialtoConfig { - initial_header: Some(millau_runtime::rialto::initial_header()), - initial_authority_list: millau_runtime::rialto::initial_authority_set().authorities, - initial_set_id: millau_runtime::rialto::initial_authority_set().set_id, - first_scheduled_change: None, - }) -} diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 4b66d656f8394..b55a758544334 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -186,9 +186,6 @@ fn load_kovan_bridge_config() -> Option { fn load_millau_bridge_config() -> Option { Some(BridgeMillauConfig { - initial_header: Some(rialto_runtime::millau::initial_header()), - initial_authority_list: rialto_runtime::millau::initial_authority_set().authorities, - initial_set_id: rialto_runtime::millau::initial_authority_set().set_id, - first_scheduled_change: None, + init_data: Some(rialto_runtime::millau::init_data()), }) } diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs index 1ca819331906e..8da062ec59b20 100644 --- a/bin/rialto/runtime/src/millau.rs +++ b/bin/rialto/runtime/src/millau.rs @@ -18,11 +18,23 @@ use bp_rialto::Header; use hex_literal::hex; -use pallet_substrate_bridge::AuthoritySet; +use pallet_substrate_bridge::{AuthoritySet, InitializationData}; use sp_core::crypto::Public; use sp_finality_grandpa::AuthorityId; use sp_std::vec; +/// Information about where the bridge palelt should start syncing from. This includes things like +/// the initial header and the initial authorities of the briged chain. +pub fn init_data() -> InitializationData

{ + let authority_set = initial_authority_set(); + InitializationData { + header: initial_header(), + authority_list: authority_set.authorities, + set_id: authority_set.set_id, + scheduled_change: None, + } +} + /// The first header known to the pallet. /// /// Note that this does not need to be the genesis header of the Millau diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 2328864957ad0..ace34f38edb81 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -120,7 +120,7 @@ pub struct ValidatorsSet { /// Validators set change as it is stored in the runtime storage. #[derive(Encode, Decode, PartialEq, RuntimeDebug)] #[cfg_attr(test, derive(Clone))] -pub struct ScheduledChange { +pub struct AuraScheduledChange { /// Validators of this set. pub validators: Vec
, /// Hash of the block which has emitted previous validators change signal. @@ -187,7 +187,7 @@ pub struct ImportContext { parent_hash: H256, parent_header: AuraHeader, parent_total_difficulty: U256, - parent_scheduled_change: Option, + parent_scheduled_change: Option, validators_set_id: u64, validators_set: ValidatorsSet, last_signal_block: Option, @@ -210,7 +210,7 @@ impl ImportContext { } /// Returns the validator set change if the parent header has signaled a change. - pub fn parent_scheduled_change(&self) -> Option<&ScheduledChange> { + pub fn parent_scheduled_change(&self) -> Option<&AuraScheduledChange> { self.parent_scheduled_change.as_ref() } @@ -293,7 +293,7 @@ pub trait Storage { ) -> Option>; /// Get new validators that are scheduled by given header and hash of the previous /// block that has scheduled change. - fn scheduled_change(&self, hash: &H256) -> Option; + fn scheduled_change(&self, hash: &H256) -> Option; /// Insert imported header. fn insert_header(&mut self, header: HeaderToImport); /// Finalize given block and schedules pruning of all headers @@ -479,7 +479,7 @@ decl_storage! { /// When it reaches zero, we are free to prune validator set as well. ValidatorsSetsRc: map hasher(twox_64_concat) u64 => Option; /// Map of validators set changes scheduled by given header. - ScheduledChanges: map hasher(identity) H256 => Option; + ScheduledChanges: map hasher(identity) H256 => Option; } add_extra_genesis { config(initial_header): AuraHeader; @@ -766,7 +766,7 @@ impl, I: Instance> Storage for BridgeStorage { }) } - fn scheduled_change(&self, hash: &H256) -> Option { + fn scheduled_change(&self, hash: &H256) -> Option { ScheduledChanges::::get(hash) } @@ -777,7 +777,7 @@ impl, I: Instance> Storage for BridgeStorage { if let Some(scheduled_change) = header.scheduled_change { ScheduledChanges::::insert( &header.id.hash, - ScheduledChange { + AuraScheduledChange { validators: scheduled_change, prev_signal_block: header.context.last_signal_block, }, @@ -1119,7 +1119,7 @@ pub(crate) mod tests { if i == 7 && j == 1 { ScheduledChanges::::insert( hash, - ScheduledChange { + AuraScheduledChange { validators: validators_addresses(5), prev_signal_block: None, }, diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index ede479fd37881..dc09b48d55062 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -277,7 +277,7 @@ pub(crate) mod tests { use super::*; use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}; use crate::DefaultInstance; - use crate::{BridgeStorage, Headers, ScheduledChange, ScheduledChanges, StoredHeader}; + use crate::{AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader}; use bp_eth_poa::compute_merkle_root; use frame_support::StorageMap; @@ -428,7 +428,7 @@ pub(crate) mod tests { next_validators_set_id: 0, last_signal_block: scheduled_at, }; - let scheduled_change = ScheduledChange { + let scheduled_change = AuraScheduledChange { validators: validators_addresses(1), prev_signal_block: None, }; diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 90d3f2a4748b6..b762a280f5848 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -16,7 +16,7 @@ use crate::error::Error; use crate::validators::{Validators, ValidatorsConfiguration}; -use crate::{AuraConfiguration, ChainTime, ImportContext, PoolConfiguration, ScheduledChange, Storage}; +use crate::{AuraConfiguration, AuraScheduledChange, ChainTime, ImportContext, PoolConfiguration, Storage}; use bp_eth_poa::{ public_to_address, step_validator, Address, AuraHeader, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, }; @@ -341,7 +341,7 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< // if parent schedules validators set change, then it may be our set // else we'll start with last known change let mut current_set_signal_block = context.last_signal_block(); - let mut next_scheduled_set: Option = None; + let mut next_scheduled_set: Option = None; loop { // if we have reached block that signals finalized change, then @@ -456,7 +456,7 @@ mod tests { }); ScheduledChanges::::insert( header.header.parent_hash, - ScheduledChange { + AuraScheduledChange { validators: signalled_set, prev_signal_block: None, }, diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 0bd3423e92189..cf7d4fbc6ffef 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -33,15 +33,15 @@ use crate::storage::ImportedHeader; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; -use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult}; -use frame_system::ensure_signed; +use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure}; +use frame_system::{ensure_root, ensure_signed}; use sp_runtime::traits::Header as HeaderT; use sp_runtime::RuntimeDebug; use sp_std::{marker::PhantomData, prelude::*}; use sp_trie::StorageProof; // Re-export since the node uses these when configuring genesis -pub use storage::{AuthoritySet, ScheduledChange}; +pub use storage::{AuthoritySet, InitializationData, ScheduledChange}; pub use justification::decode_justification_target; pub use storage_proof::StorageProofChecker; @@ -105,53 +105,18 @@ decl_storage! { // Grandpa doesn't require there to always be a pending change. In fact, most of the time // there will be no pending change available. NextScheduledChange: map hasher(identity) BridgedBlockHash => Option>>; + /// Whether or not the bridge has been initialized. + /// + /// This is important to know to ensure that we don't try and initialize the bridge twice + /// and create an inconsistent genesis state. + IsInitialized: bool; } add_extra_genesis { - config(initial_header): Option>; - config(initial_authority_list): sp_finality_grandpa::AuthorityList; - config(initial_set_id): sp_finality_grandpa::SetId; - config(first_scheduled_change): Option>>; + config(init_data): Option>>; build(|config| { - assert!( - !config.initial_authority_list.is_empty(), - "An initial authority list is needed." - ); - - let initial_header = config - .initial_header - .clone() - .expect("An initial header is needed"); - let initial_hash = initial_header.hash(); - - >::put(initial_header.number()); - >::put(vec![initial_hash]); - >::put(initial_hash); - - let authority_set = - AuthoritySet::new(config.initial_authority_list.clone(), config.initial_set_id); - CurrentAuthoritySet::put(authority_set); - - let mut signal_hash = None; - if let Some(ref change) = config.first_scheduled_change { - assert!( - change.height > *initial_header.number(), - "Changes must be scheduled past initial header." - ); - - signal_hash = Some(initial_hash); - >::insert(initial_hash, change); - }; - - >::insert( - initial_hash, - ImportedHeader { - header: initial_header, - requires_justification: false, - is_finalized: true, - signal_hash, - }, - ); - + if let Some(init_data) = config.init_data.clone() { + initialize_bridge::(init_data); + } }) } } @@ -164,6 +129,8 @@ decl_error! { UnfinalizedHeader, /// The header is unknown. UnknownHeader, + /// The pallet has already been initialized. + AlreadyInitialized, /// The storage proof doesn't contains storage root. So it is invalid for given header. StorageRootMismatch, /// Error when trying to fetch storage value from the proof. @@ -225,6 +192,27 @@ decl_module! { Ok(()) } + + /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. + /// + /// The initial configuration provided does not need to be the genesis header of the bridged + /// chain, it can be any arbirary header. You can also provide the next scheduled set change + /// if it is already know. + /// + /// This function is only allowed to be called from a trusted origin and writes to storage + /// with practically no checks in terms of the validity of the data. It is important that + /// you ensure that valid data is being passed in. + //TODO: Update weights [#78] + #[weight = 0] + pub fn initialize( + origin, + init_data: InitializationData>, + ) { + let _ = ensure_root(origin)?; + let init_allowed = !IsInitialized::get(); + ensure!(init_allowed, >::AlreadyInitialized); + initialize_bridge::(init_data); + } } } @@ -300,6 +288,49 @@ impl Module { } } +// Since this writes to storage with no real checks this should only be used in functions that were +// called by a trusted origin. +fn initialize_bridge(init_params: InitializationData>) { + let InitializationData { + header, + authority_list, + set_id, + scheduled_change, + } = init_params; + + let initial_hash = header.hash(); + + let mut signal_hash = None; + if let Some(ref change) = scheduled_change { + assert!( + change.height > *header.number(), + "Changes must be scheduled past initial header." + ); + + signal_hash = Some(initial_hash); + >::insert(initial_hash, change); + }; + + >::put(header.number()); + >::put(vec![initial_hash]); + >::put(initial_hash); + + let authority_set = AuthoritySet::new(authority_list, set_id); + CurrentAuthoritySet::put(authority_set); + + >::insert( + initial_hash, + ImportedHeader { + header, + requires_justification: false, + is_finalized: true, + signal_hash, + }, + ); + + IsInitialized::put(true); +} + /// Expected interface for interacting with bridge pallet storage. // TODO: This should be split into its own less-Substrate-dependent crate pub trait BridgeStorage { @@ -468,8 +499,75 @@ impl BridgeStorage for PalletStorage { #[cfg(test)] mod tests { use super::*; - use crate::mock::{helpers::unfinalized_header, run_test, TestRuntime}; + use crate::mock::helpers::{authority_list, test_header, unfinalized_header}; + use crate::mock::{run_test, Origin, TestRuntime}; use frame_support::{assert_noop, assert_ok}; + use sp_runtime::DispatchError; + + #[test] + fn only_root_origin_can_initialize_pallet() { + run_test(|| { + let init_data = InitializationData { + header: test_header(1), + authority_list: authority_list(), + set_id: 1, + scheduled_change: None, + }; + + assert_noop!( + Module::::initialize(Origin::signed(1), init_data.clone()), + DispatchError::BadOrigin, + ); + + assert_ok!(Module::::initialize(Origin::root(), init_data)); + }) + } + + #[test] + fn can_only_initialize_pallet_once() { + run_test(|| { + let init_data = InitializationData { + header: test_header(1), + authority_list: authority_list(), + set_id: 1, + scheduled_change: None, + }; + + assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + assert_noop!( + Module::::initialize(Origin::root(), init_data,), + >::AlreadyInitialized, + ); + }) + } + + #[test] + fn storage_entries_are_correctly_initialized() { + run_test(|| { + let init_data = InitializationData { + header: test_header(1), + authority_list: authority_list(), + set_id: 1, + scheduled_change: None, + }; + + assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + + let storage = PalletStorage::::new(); + + assert!(IsInitialized::get()); + assert!(storage.header_exists(init_data.header.hash())); + assert_eq!( + storage.best_headers()[0], + crate::HeaderId { + number: *init_data.header.number(), + hash: init_data.header.hash() + } + ); + assert_eq!(storage.best_finalized_header().hash(), init_data.header.hash()); + assert_eq!(storage.current_authority_set().authorities, init_data.authority_list); + }) + } #[test] fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs index fb98228c6a6a6..24c42482955ce 100644 --- a/modules/substrate/src/storage.rs +++ b/modules/substrate/src/storage.rs @@ -24,6 +24,22 @@ use sp_finality_grandpa::{AuthorityList, SetId}; use sp_runtime::traits::Header as HeaderT; use sp_runtime::RuntimeDebug; +/// Data required for initializing the bridge pallet. +/// +/// The bridge needs to know where to start its sync from, and this provides that initial context. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct InitializationData { + /// The header from which we should start syncing. + pub header: H, + /// The initial authorities of the pallet. + pub authority_list: AuthorityList, + /// The ID of the initial authority set. + pub set_id: SetId, + /// The first scheduled authority set change of the pallet. + pub scheduled_change: Option>, +} + /// A Grandpa Authority List and ID. #[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] From 9387d3c40edeeef9e5017b98d76c0bf15d3af459 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 07:05:05 +0300 Subject: [PATCH 0213/1210] verify messages delivery proofs (#482) --- bin/millau/runtime/src/rialto_messages.rs | 17 +++++--- bin/rialto/runtime/src/millau_messages.rs | 12 +++--- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages.rs | 49 ++++++++++++++++++++++- 4 files changed, 67 insertions(+), 13 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 450d38b6d00fb..fc20cf7b5628b 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -30,7 +30,6 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; -use sp_trie::StorageProof; /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -63,6 +62,12 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifie /// Message payload for Rialto -> Millau messages. pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +/// Messages proof for Rialto -> Millau messages. +type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; + +/// Messages delivery proof for Millau -> Rialto messages. +type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; + /// Call-dispatch based message dispatch for Rialto -> Millau messages. pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithRialtoMessageBridge, @@ -152,7 +157,7 @@ impl TargetHeaderChain for Rialto // - hash of the header this proof has been created with; // - the storage proof or one or several keys; // - id of the lane we prove state of. - type MessagesDeliveryProof = (bp_rialto::Hash, StorageProof, LaneId); + type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof; fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { if payload.weight > WithRialtoMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { @@ -163,9 +168,9 @@ impl TargetHeaderChain for Rialto } fn verify_messages_delivery_proof( - _proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + messages::source::verify_messages_delivery_proof::(proof) } } @@ -176,7 +181,7 @@ impl SourceHeaderChain for Rialto { // - the storage proof or one or several keys; // - id of the lane we prove messages for; // - inclusive range of messages nonces that are proved. - type MessagesProof = (bp_rialto::Hash, StorageProof, LaneId, MessageNonce, MessageNonce); + type MessagesProof = FromRialtoMessagesProof; fn verify_messages_proof( _proof: Self::MessagesProof, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 97067078e34b5..79b03ba935579 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -30,7 +30,6 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; -use sp_trie::StorageProof; /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -73,6 +72,9 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi /// Messages proof for Millau -> Rialto messages. type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; +/// Messages delivery proof for Rialto -> Millau messages. +type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; + /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithMillauMessageBridge; @@ -155,7 +157,7 @@ impl TargetHeaderChain for Millau // - hash of the header this proof has been created with; // - the storage proof of one or several keys; // - id of the lane we prove state of. - type MessagesDeliveryProof = (bp_millau::Hash, StorageProof, LaneId); + type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { if payload.weight > WithMillauMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { @@ -166,9 +168,9 @@ impl TargetHeaderChain for Millau } fn verify_messages_delivery_proof( - _proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + messages::source::verify_messages_delivery_proof::(proof) } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 61d4928da3278..93e0bf6a2bf32 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -17,6 +17,7 @@ bp-message-lane = { path = "../../primitives/message-lane", default-features = f bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } pallet-message-lane = { path = "../../modules/message-lane", default-features = false } +pallet-substrate-bridge = { path = "../../modules/substrate", default-features = false } # Substrate dependencies @@ -35,6 +36,7 @@ std = [ "frame-support/std", "pallet-bridge-call-dispatch/std", "pallet-message-lane/std", + "pallet-substrate-bridge/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 9ac6ced189d7d..384b17e44a2fb 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -24,7 +24,7 @@ use bp_message_dispatch::MessageDispatch as _; use bp_message_lane::{ source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch}, - LaneId, MessageNonce, + InboundLaneData, LaneId, MessageNonce, }; use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; @@ -77,7 +77,7 @@ pub trait ChainWithMessageLanes { /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. - type AccountId; + type AccountId: Decode; /// Public key of the chain account that may be used to verify signatures. type Signer: Decode; /// Signature type used on the chain. @@ -105,6 +105,7 @@ pub(crate) type SignatureOf = ::Signature; pub(crate) type WeightOf = ::Weight; pub(crate) type BalanceOf = ::Balance; pub(crate) type CallOf = ::Call; +pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { @@ -121,6 +122,16 @@ pub mod source { BridgedChainOpaqueCall, >; + /// Messages delivery proof from bridged chain: + /// + /// - hash of finalized header; + /// - storage proof of inbound lane state; + /// - lane id. + pub type FromBridgedChainMessagesDeliveryProof = (HashOf>, StorageProof, LaneId); + + /// 'Parsed' message delivery proof - inbound lane id and its state. + pub type ParsedMessagesDeliveryProofFromBridgedChain = (LaneId, InboundLaneData>>); + /// Message verifier that requires submitter to pay minimal delivery and dispatch fee. #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); @@ -188,6 +199,40 @@ pub mod source { .and_then(|interest| fee.checked_add(&interest))) .ok_or("Overflow when computing minimal required message delivery and dispatch fee") } + + /// Verify proof of This -> Bridged chain messages delivery. + pub fn verify_messages_delivery_proof( + proof: FromBridgedChainMessagesDeliveryProof, + ) -> Result, &'static str> + where + ThisRuntime: pallet_substrate_bridge::Trait, + ThisRuntime: pallet_message_lane::Trait>>, + HashOf>: + Into::BridgedChain>>, + { + let (bridged_header_hash, bridged_storage_proof, lane) = proof; + pallet_substrate_bridge::Module::::parse_finalized_storage_proof( + bridged_header_hash.into(), + bridged_storage_proof, + |storage| { + // Messages delivery proof is just proof of single storage key read => any error + // is fatal. + let storage_inbound_lane_data_key = pallet_message_lane::storage_keys::inbound_lane_data_key::< + ThisRuntime, + MessageLaneInstanceOf>, + >(&lane); + let raw_inbound_lane_data = storage + .read_value(storage_inbound_lane_data_key.0.as_ref()) + .map_err(|_| "Failed to read inbound lane state from storage proof")? + .ok_or("Inbound lane state is missing from the messages proof")?; + let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) + .map_err(|_| "Failed to decode inbound lane state from the proof")?; + + Ok((lane, inbound_lane_data)) + }, + ) + .map_err(<&'static str>::from)? + } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages. From 0d564d12826f3533f025ea4582f5f2a7b9954c6d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 11:15:14 +0300 Subject: [PATCH 0214/1210] Verify messages proofs (#480) * verify messages proofs * fmt * clippy * grumbles --- bin/millau/runtime/src/rialto_messages.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 4 +- bin/runtime-common/src/messages.rs | 76 ++++++++++++++++++++++- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index fc20cf7b5628b..b810aa1522100 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -184,8 +184,8 @@ impl SourceHeaderChain for Rialto { type MessagesProof = FromRialtoMessagesProof; fn verify_messages_proof( - _proof: Self::MessagesProof, + proof: Self::MessagesProof, ) -> Result>, Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + messages::target::verify_messages_proof::(proof) } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 79b03ba935579..65797322bca52 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -184,8 +184,8 @@ impl SourceHeaderChain for Millau { type MessagesProof = FromMillauMessagesProof; fn verify_messages_proof( - _proof: Self::MessagesProof, + proof: Self::MessagesProof, ) -> Result>, Self::Error> { - unimplemented!("https://github.com/paritytech/parity-bridges-common/issues/397") + messages::target::verify_messages_proof::(proof) } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 384b17e44a2fb..264efd409c208 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -23,8 +23,8 @@ use bp_message_dispatch::MessageDispatch as _; use bp_message_lane::{ source_chain::LaneMessageVerifier, - target_chain::{DispatchMessage, MessageDispatch}, - InboundLaneData, LaneId, MessageNonce, + target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, + InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; @@ -90,7 +90,7 @@ pub trait ChainWithMessageLanes { /// different weights. type Weight: From; /// Type of balances that is used on the chain. - type Balance: CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; + type Balance: Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; /// Instance of the message-lane pallet. type MessageLaneInstance: Instance; @@ -333,6 +333,76 @@ pub mod target { } } } + + /// Verify proof of Bridged -> This chain messages. + pub fn verify_messages_proof( + proof: FromBridgedChainMessagesProof, + ) -> Result>>>, &'static str> + where + ThisRuntime: pallet_substrate_bridge::Trait, + ThisRuntime: pallet_message_lane::Trait>>, + HashOf>: + Into::BridgedChain>>, + { + let (bridged_header_hash, bridged_storage_proof, lane_id, begin, end) = proof; + pallet_substrate_bridge::Module::::parse_finalized_storage_proof( + bridged_header_hash.into(), + bridged_storage_proof, + |storage| { + // Read messages first. All messages that are claimed to be in the proof must + // be in the proof. So any error in `read_value`, or even missing value is fatal. + // + // Mind that we allow proofs with no messages if outbound lane state is proved. + let mut messages = Vec::with_capacity(end.saturating_sub(begin) as _); + for nonce in begin..=end { + let message_key = MessageKey { lane_id, nonce }; + let storage_message_key = pallet_message_lane::storage_keys::message_key::< + ThisRuntime, + MessageLaneInstanceOf>, + >(&lane_id, nonce); + let raw_message_data = storage + .read_value(storage_message_key.0.as_ref()) + .map_err(|_| "Failed to read message from storage proof")? + .ok_or("Message is missing from the messages proof")?; + let message_data = MessageData::>>::decode(&mut &raw_message_data[..]) + .map_err(|_| "Failed to decode message from the proof")?; + messages.push(Message { + key: message_key, + data: message_data, + }); + } + + // Now let's check if proof contains outbound lane state proof. It is optional, so we + // simply ignore `read_value` errors and missing value. + let mut proved_lane_messages = ProvedLaneMessages { + lane_state: None, + messages, + }; + let storage_outbound_lane_data_key = pallet_message_lane::storage_keys::outbound_lane_data_key::< + MessageLaneInstanceOf>, + >(&lane_id); + let raw_outbound_lane_data = storage.read_value(storage_outbound_lane_data_key.0.as_ref()); + if let Ok(Some(raw_outbound_lane_data)) = raw_outbound_lane_data { + proved_lane_messages.lane_state = Some( + OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) + .map_err(|_| "Failed to decode outbound lane data from the proof")?, + ); + } + + // Now we may actually check if the proof is empty or not. + if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { + return Err("Messages proof is empty"); + } + + // We only support single lane messages in this schema + let mut proved_messages = ProvedMessages::new(); + proved_messages.insert(lane_id, proved_lane_messages); + + Ok(proved_messages) + }, + ) + .map_err(<&'static str>::from)? + } } #[cfg(test)] From 0f173d1fe3d1b34734c4e2ebc60f73b10193e043 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 12:19:31 +0300 Subject: [PATCH 0215/1210] enable GrandpaRpcApi for Rialto (#486) --- bin/millau/node/src/service.rs | 3 +-- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/service.rs | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 0a6b5d8b849e6..086ef7609cc1e 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -35,7 +35,6 @@ use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; -use sc_finality_grandpa_rpc::GrandpaRpcHandler; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_core::storage::StorageKey; @@ -193,7 +192,7 @@ pub fn new_full(config: Configuration) -> Result { } use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; - use sc_finality_grandpa_rpc::GrandpaApi; + use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index a0394f34af06b..dd905a53a9c27 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -31,6 +31,7 @@ sc-consensus = "0.8" sc-consensus-aura = "0.8" sc-executor = "0.8" sc-finality-grandpa = "0.8" +sc-finality-grandpa-rpc = "0.8" sc-service = "0.8" sc-rpc = "2.0" sc-transaction-pool = "2.0" diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 07a49a26858ac..1d7dfdffefbd3 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -192,19 +192,33 @@ pub fn new_full(config: Configuration) -> Result { } use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; + use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; let backend = backend.clone(); let client = client.clone(); let pool = transaction_pool.clone(); - Box::new(move |_, _| { + let justification_stream = grandpa_link.justification_stream(); + let shared_authority_set = grandpa_link.shared_authority_set().clone(); + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + + Box::new(move |_, subscription_executor| { + let shared_voter_state = SharedVoterState::empty(); + let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( client.clone(), pool.clone(), DenyUnsafe::No, ))); + io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( + shared_authority_set.clone(), + shared_voter_state, + justification_stream.clone(), + subscription_executor, + finality_proof_provider.clone(), + ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( client.clone(), backend.clone(), From d89afed6264d53710098ed948ee4bd59dfb530a6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 12:19:39 +0300 Subject: [PATCH 0216/1210] Fixed client used in headers maintain (#487) * fixed client used in headers maintain * fmt --- relays/substrate/src/headers_maintain.rs | 45 ++++++++++++++---------- relays/substrate/src/headers_pipeline.rs | 7 ++-- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index af3196b375b27..fc91494c7b725 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -44,13 +44,14 @@ use relay_substrate_client::{Chain, Client, Error as SubstrateError, Justificati use relay_utils::HeaderId; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, Justification}; -use std::{collections::VecDeque, task::Poll}; +use std::{collections::VecDeque, marker::PhantomData, task::Poll}; /// Substrate-to-Substrate headers synchronization maintain procedure. -pub struct SubstrateHeadersToSubstrateMaintain { +pub struct SubstrateHeadersToSubstrateMaintain { pipeline: P, - target_client: Client, + target_client: Client, justifications: Arc>>, + _marker: PhantomData, } /// Future and already received justifications from the source chain. @@ -62,9 +63,11 @@ struct Justifications { queue: VecDeque<(HeaderIdOf

, Justification)>, } -impl SubstrateHeadersToSubstrateMaintain { +impl + SubstrateHeadersToSubstrateMaintain +{ /// Create new maintain procedure. - pub fn new(pipeline: P, target_client: Client, justifications: JustificationsSubscription) -> Self { + pub fn new(pipeline: P, target_client: Client, justifications: JustificationsSubscription) -> Self { SubstrateHeadersToSubstrateMaintain { pipeline, target_client, @@ -72,16 +75,20 @@ impl SubstrateHeadersToSubstrateMaint stream: justifications, queue: VecDeque::new(), })), + _marker: Default::default(), } } } #[async_trait] -impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain +impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain where - C: Chain, - P::Number: Decode + From, - P::Hash: Decode + From, + SourceChain: Chain, + ::Number: Into, + ::Hash: Into, + TargetChain: Chain, + P::Number: Decode, + P::Hash: Decode, P: SubstrateHeadersSyncPipeline, { async fn maintain(&self, sync: &mut HeadersSync

) { @@ -122,7 +129,7 @@ where // on every maintain call. So maintain rate directly affects finalization rate. let justification_to_submit = poll_fn(|context| { // read justifications from the stream and push to the queue - justifications.read_from_stream::(context); + justifications.read_from_stream::(context); // remove all obsolete justifications from the queue remove_obsolete::

(&mut justifications.queue, best_finalized); @@ -166,11 +173,11 @@ where P: SubstrateHeadersSyncPipeline, { /// Read justifications from the subscription stream without blocking. - fn read_from_stream<'a, Header>(&mut self, context: &mut std::task::Context<'a>) + fn read_from_stream<'a, SourceHeader>(&mut self, context: &mut std::task::Context<'a>) where - Header: HeaderT, - Header::Number: Into, - Header::Hash: Into, + SourceHeader: HeaderT, + SourceHeader::Number: Into, + SourceHeader::Hash: Into, { loop { let maybe_next_justification = self.stream.next(); @@ -183,7 +190,7 @@ where }; // decode justification target - let target = pallet_substrate_bridge::decode_justification_target::

(&justification); + let target = pallet_substrate_bridge::decode_justification_target::(&justification); let target = match target { Ok((target_hash, target_number)) => HeaderId(target_number.into(), target_hash.into()), Err(error) => { @@ -266,18 +273,18 @@ where async fn best_finalized_header_id(client: &Client) -> Result, SubstrateError> where P: SubstrateHeadersSyncPipeline, - P::Number: Decode + From, - P::Hash: Decode + From, + P::Number: Decode, + P::Hash: Decode, C: Chain, { let call = P::FINALIZED_BLOCK_METHOD.into(); let data = Bytes(Vec::new()); let encoded_response = client.state_call(call, data, None).await?; - let decoded_response: (C::BlockNumber, C::Hash) = + let decoded_response: (P::Number, P::Hash) = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - let best_header_id = HeaderId(decoded_response.0.into(), decoded_response.1.into()); + let best_header_id = HeaderId(decoded_response.0, decoded_response.1); Ok(best_header_id) } diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index 3a6348961fb71..b00417da39d0e 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -124,8 +124,11 @@ pub async fn run( } }; - let sync_maintain = - SubstrateHeadersToSubstrateMaintain::new(pipeline.clone(), source_client.clone(), source_justifications); + let sync_maintain = SubstrateHeadersToSubstrateMaintain::<_, SourceChain, _>::new( + pipeline.clone(), + target_client.clone(), + source_justifications, + ); headers_relay::sync_loop::run( HeadersSource::new(source_client), From 284d989c2d19ca56849ee023c225cfc60ce500d2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 16:43:20 +0300 Subject: [PATCH 0217/1210] Fixed block where proof is generated (#488) * fixed block where proof is generated * proof_is_generated_at_best_block_known_to_target_node --- .../messages-relay/src/message_race_loop.rs | 78 +++++++++++++++++-- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 4b2a9eef04540..c3239f7115376 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -305,20 +305,15 @@ pub async fn run>( if source_client_is_online { source_client_is_online = false; - let nonces_to_deliver = race_state.source_state.as_ref().and_then(|source_state| { - strategy - .select_nonces_to_deliver(&race_state) - .map(|(nonces_range, proof_parameters)| { - (source_state.best_self.clone(), nonces_range, proof_parameters) - }) - }); + let nonces_to_deliver = select_nonces_to_deliver(&race_state, &mut strategy); if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { log::debug!( target: "bridge", - "Asking {} to prove nonces in range {:?}", + "Asking {} to prove nonces in range {:?} at block {:?}", P::source_name(), nonces_range, + at_block, ); source_generate_proof.set( race_source @@ -383,3 +378,70 @@ impl Default } } } + +fn select_nonces_to_deliver( + race_state: &RaceState, + strategy: &mut Strategy, +) -> Option<(SourceHeaderId, RangeInclusive, Strategy::ProofParameters)> +where + SourceHeaderId: Clone, + Strategy: RaceStrategy, +{ + race_state.target_state.as_ref().and_then(|target_state| { + strategy + .select_nonces_to_deliver(&race_state) + .map(|(nonces_range, proof_parameters)| (target_state.best_peer.clone(), nonces_range, proof_parameters)) + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::message_race_strategy::BasicStrategy; + use relay_utils::HeaderId; + + #[test] + fn proof_is_generated_at_best_block_known_to_target_node() { + const GENERATED_AT: u64 = 6; + const BEST_AT_SOURCE: u64 = 10; + const BEST_AT_TARGET: u64 = 8; + + // target node only knows about source' BEST_AT_TARGET block + // source node has BEST_AT_SOURCE > BEST_AT_SOURCE block + let mut race_state = RaceState::<_, _, _, ()> { + source_state: Some(ClientState { + best_self: HeaderId(BEST_AT_SOURCE, BEST_AT_SOURCE), + best_peer: HeaderId(0, 0), + }), + target_state: Some(ClientState { + best_self: HeaderId(0, 0), + best_peer: HeaderId(BEST_AT_TARGET, BEST_AT_TARGET), + }), + nonces_to_submit: None, + nonces_submitted: None, + }; + + // we have some nonces to deliver and they're generated at GENERATED_AT < BEST_AT_SOURCE + let mut strategy = BasicStrategy::new(100); + strategy.source_nonces_updated( + HeaderId(GENERATED_AT, GENERATED_AT), + ClientNonces { + latest_nonce: 10u64, + confirmed_nonce: None, + }, + ); + strategy.target_nonces_updated( + ClientNonces { + latest_nonce: 5u64, + confirmed_nonce: None, + }, + &mut race_state, + ); + + // the proof will be generated on source, but using BEST_AT_TARGET block + assert_eq!( + select_nonces_to_deliver(&race_state, &mut strategy), + Some((HeaderId(BEST_AT_TARGET, BEST_AT_TARGET), 6..=10, (),)) + ); + } +} From ff7fbfcde2085e1bbee95094f32292f1476f09c3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Nov 2020 18:42:53 +0300 Subject: [PATCH 0218/1210] Print progress of message races (#489) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * print message race progress * fmt * Update relays/messages-relay/src/message_race_loop.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- .../src/message_race_delivery.rs | 8 +++++ .../messages-relay/src/message_race_loop.rs | 35 +++++++++++++++++++ .../src/message_race_strategy.rs | 11 ++++++ 3 files changed, 54 insertions(+) diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index a5d096b7710b1..90345f8c61571 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -212,6 +212,14 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M self.strategy.is_empty() } + fn best_at_source(&self) -> P::MessageNonce { + self.strategy.best_at_source() + } + + fn best_at_target(&self) -> P::MessageNonce { + self.strategy.best_at_target() + } + fn source_nonces_updated(&mut self, at_block: SourceHeaderIdOf

, nonces: ClientNonces) { self.source_nonces = Some(nonces.clone()); self.strategy.source_nonces_updated(at_block, nonces) diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index c3239f7115376..43a2cd9ad275b 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -117,6 +117,11 @@ pub trait RaceStrategy { /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; + /// Return best nonce at source node. + fn best_at_source(&self) -> MessageNonce; + /// Return best nonce at target node. + fn best_at_target(&self) -> MessageNonce; + /// Called when nonces are updated at source node of the race. fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonce: ClientNonces); /// Called when nonces are updated at target node of the race. @@ -135,6 +140,7 @@ pub trait RaceStrategy { } /// State of the race. +#[derive(Debug)] pub struct RaceState { /// Source state, if known. pub source_state: Option>, @@ -161,6 +167,7 @@ pub async fn run>( ProofParameters = SC::ProofParameters, >, ) -> Result<(), FailedClient> { + let mut progress_context = Instant::now(); let mut race_state = RaceState::default(); let mut stall_countdown = Instant::now(); @@ -295,6 +302,8 @@ pub async fn run>( } } + progress_context = print_race_progress::(progress_context, &strategy); + if stall_countdown.elapsed() > stall_timeout { return Err(FailedClient::Both); } else if race_state.nonces_to_submit.is_none() && race_state.nonces_submitted.is_none() && strategy.is_empty() @@ -379,6 +388,32 @@ impl Default } } +/// Print race progress. +fn print_race_progress(prev_time: Instant, strategy: &S) -> Instant +where + P: MessageRace, + S: RaceStrategy, +{ + let now_time = Instant::now(); + + let need_update = now_time.saturating_duration_since(prev_time) > Duration::from_secs(10); + if !need_update { + return prev_time; + } + + let now_best_nonce_at_source = strategy.best_at_source(); + let now_best_nonce_at_target = strategy.best_at_target(); + log::info!( + target: "bridge", + "Synced {:?} of {:?} nonces in {} -> {} race", + now_best_nonce_at_target, + now_best_nonce_at_source, + P::source_name(), + P::target_name(), + ); + now_time +} + fn select_nonces_to_deliver( race_state: &RaceState, strategy: &mut Strategy, diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index a22331fe07d13..4aabf6c200afd 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -68,6 +68,17 @@ where self.source_queue.is_empty() } + fn best_at_source(&self) -> Nonce { + self.source_queue + .back() + .map(|(_, nonce)| *nonce) + .unwrap_or_else(Zero::zero) + } + + fn best_at_target(&self) -> Nonce { + self.target_nonce + } + fn source_nonces_updated( &mut self, at_block: HeaderId, From c451bc943521bf59fc22fb5077640f0ae874a3d4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 6 Nov 2020 11:29:17 -0500 Subject: [PATCH 0219/1210] Rework Compose Setup for Millau Deployment (#464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename `rialto` deployment to `eth-sub-bridge` * Add base Compose configs for Rialto and Eth-PoA nodes * Add new compose file for eth-sub deployment * Rename bridge-nodes to rialto-nodes * Update bootnode entries for Rialto nodes * Remove new compose file since it was used for quick test * Rename bridge nodes in entrypoint scripts * Remove all nodes from Eth-Sub Compose file The nodes should be getting pulled in from the new compose files. * Remove TODO comment * Rename nodes to networks Reflects the fact that a set of nodes makes up a network. * Add Compose file for Millau network nodes * Enable logging for all Millau nodes * Delete Rialto reserved peers file * Rename `bridge-config` to `scripts` * Add Compose file for Rialto-Millau bridge * Move bridge deployments into `bridges` folder * Drop `bridges` prefix from bridge deployments * Rename folder that had scripts for working with binaries * Move proxy configuration to common top level folder * Make a top level `monitoring` folder * Start updating deployment README * More updates in the README * Remove usage of Git overrides * Remove scripts to run Eth<->Sub I don't think these are used anymore * Remove Github Docker build instructions from main README * Add note about monitoring * Update Millau state root * Add script for running and updating Compose deployments * Remove old update script * Explain usage of `run` script * Update Millau state_root again * Remove repeated Prom image from Rialto-Millau bridge * Quick fix to stop containers in `run` script * Pin GrafanaMatrix Dockerfile to old commit The latest master has some changes in how the application is run. We don't want to update just yet so we're pinning to an old commit. * Make Compose files use a project directory The main consequence of this change is that all paths have to be specified from the root of the `deployments` folder. However, this makes it so that we can reuse components in different deployments, like the GranfaMatrix Dockerfile which is shared by all bridges. * Use `project-directory` when stopping and updating network If we don't use the full Compose command which includes `project-directory` not all the containers get cleaned up correctly. * Update path in Bridge Dockerfile * Correctly ignore `target` folders in Docker builds * Wait for Rialto nodes before running relay * Make `run` script a little less sketchy * Clean up deployment README * Remove stray line * Have run script automatically change into correct directory * Use PoA-to-Rialto instead of Eth-to-Sub in names * Rename `eth-poa-sub` bridge deployment to `poa-rialto` * Use /entrypoints volume for entrypoint scripts * Be more consistent with relay service names * Remove `docker-compose` prefix from network Compose files * Add comment explaning Grafana Matrix commit * Fix wording in README Co-authored-by: Tomasz Drwięga * Cleanup unused line in README * Add link to Slava's test scripts * Remove uneccessary piping when `cd`-ing in `run.sh` Co-authored-by: Tomasz Drwięga --- README.md | 34 -------------------------------- bin/rialto/runtime/src/millau.rs | 2 +- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/README.md b/README.md index 744056faa1350..8c086d0b6df1b 100644 --- a/README.md +++ b/README.md @@ -233,40 +233,6 @@ docker run -it bridge-node-dev --dev --tmp Notice that the `docker run` command will accept all the normal Substrate flags. For local development you should at minimum run with the `--dev` flag or else no blocks will be produced. -### GitHub Docker Build -If you don't want to run using the local source files you can also use images which pull the latest -`master`, or some other commit or branch of your choosing (configured with the `BRIDGE_HASH` build -argument). - -These images live in the [Rialto deployments](./deployments/rialto) folder. - -```bash -docker build \ - https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ - -t poa-relay -docker run -it poa-relay -``` - -By default the relayer is configured to connect to OpenEthereum `--dev` chain node and Substrate -`rialto-bridge-node` running in `--dev` mode. - -To build the `rialto-bridge-node`: -```bash -docker build \ - https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/Bridge.Dockerfile \ - -t rialto-bridge-node \ - --build-arg PROJECT=rialto-bridge-node -docker run -it rialto-bridge-node --dev -``` - -And to build `OpenEthereum` with bridge support: -```bash -docker build \ - https://raw.githubusercontent.com/paritytech/parity-bridges-common/master/deployments/rialto/OpenEthereum.Dockerfile - -t openethereum -docker run -it openethereum -``` - ### Full Network Docker Setup See [Deployments README](./deployments/README.md) to learn more about how to run a more sophisticated test network using `docker-compose` setup. diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs index 8da062ec59b20..d49ed9856df24 100644 --- a/bin/rialto/runtime/src/millau.rs +++ b/bin/rialto/runtime/src/millau.rs @@ -48,7 +48,7 @@ pub fn initial_header() -> Header { Header { parent_hash: Default::default(), number: Default::default(), - state_root: hex!("dc7567715330c666eca349a4612e82ec3b3c4f306ef941dce192a37fb3131cfa").into(), + state_root: hex!("0f2ca6dde08378ef81958bf087a3c40391079d0dbf434ea3fa0f73d54200839b").into(), extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), digest: Default::default(), } From 0957cc7281d87c3ffade1d72afe05cf2db6b017b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 03:05:30 +0000 Subject: [PATCH 0220/1210] Bump async-std from 1.6.5 to 1.7.0 (#491) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 1682e3f3ae808..69af77a8fa319 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" -async-std = "1.6.5" +async-std = "1.7.0" async-trait = "0.1.41" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 2489ebcf95bec..a147eb2bc223a 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.2" +async-std = "1.7.0" async-trait = "0.1.41" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.7" From 35c814f2fd2859566ce8ea9a3832b1e8070f121a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 9 Nov 2020 16:43:22 -0500 Subject: [PATCH 0221/1210] Allow Substrate Pallet to be Halted (#485) * Copy-Pasta owner and freezing code from `message-lane` * Halt pallet if bridge hasn't been initialized * Make owner optional in `message-lane` pallet * Add `is_halted` to `InitializationData` * Fix initialization tests * Only allow pallet to be initialized once * Add some logging around halting and ownership changes * Remove `target` in debugging calls --- bin/millau/node/src/chain_spec.rs | 1 + bin/rialto/node/src/chain_spec.rs | 1 + bin/rialto/runtime/src/millau.rs | 1 + modules/message-lane/src/lib.rs | 30 ++-- modules/substrate/src/lib.rs | 232 +++++++++++++++++++++++++----- modules/substrate/src/storage.rs | 2 + 6 files changed, 219 insertions(+), 48 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 9d29d8ca7b469..541d240b6a1ac 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -158,6 +158,7 @@ fn testnet_genesis( pallet_substrate_bridge: Some(BridgeRialtoConfig { // We'll initialize the pallet with a dispatchable instead. init_data: None, + owner: None, }), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index b55a758544334..b562e646a62e8 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -187,5 +187,6 @@ fn load_kovan_bridge_config() -> Option { fn load_millau_bridge_config() -> Option { Some(BridgeMillauConfig { init_data: Some(rialto_runtime::millau::init_data()), + owner: Some([0; 32].into()), }) } diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs index d49ed9856df24..3549360b111b9 100644 --- a/bin/rialto/runtime/src/millau.rs +++ b/bin/rialto/runtime/src/millau.rs @@ -32,6 +32,7 @@ pub fn init_data() -> InitializationData

{ authority_list: authority_set.authorities, set_id: authority_set.set_id, scheduled_change: None, + is_halted: false, } } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 30f575ab6884e..936d590f64108 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -148,7 +148,7 @@ decl_storage! { /// `None`, then there are no direct ways to halt/resume pallet operations, but other /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). - pub ModuleOwner get(fn module_owner) config(): Option; + pub ModuleOwner get(fn module_owner): Option; /// If true, all pallet transactions are failed immediately. pub IsHalted get(fn is_halted) config(): bool; /// Map of lane id => inbound lane data. @@ -160,6 +160,12 @@ decl_storage! { } add_extra_genesis { config(phantom): sp_std::marker::PhantomData; + config(owner): Option; + build(|config| { + if let Some(ref owner) = config.owner { + >::put(owner); + } + }) } } @@ -188,8 +194,14 @@ decl_module! { pub fn set_owner(origin, new_owner: Option) { ensure_owner_or_root::(origin)?; match new_owner { - Some(new_owner) => ModuleOwner::::put(new_owner), - None => ModuleOwner::::kill(), + Some(new_owner) => { + ModuleOwner::::put(&new_owner); + frame_support::debug::info!("Setting pallet Owner to: {:?}", new_owner); + }, + None => { + ModuleOwner::::kill(); + frame_support::debug::info!("Removed Owner of pallet."); + }, } } @@ -200,6 +212,7 @@ decl_module! { pub fn halt_operations(origin) { ensure_owner_or_root::(origin)?; IsHalted::::put(true); + frame_support::debug::warn!("Stopping pallet operations."); } /// Resume all pallet operations. May be called even if pallet is halted. @@ -209,6 +222,7 @@ decl_module! { pub fn resume_operations(origin) { ensure_owner_or_root::(origin)?; IsHalted::::put(false); + frame_support::debug::info!("Resuming pallet operations."); } /// Send message over lane. @@ -225,7 +239,6 @@ decl_module! { // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload).map_err(|err| { frame_support::debug::trace!( - target: "runtime", "Message to lane {:?} is rejected by target chain: {:?}", lane_id, err, @@ -242,7 +255,6 @@ decl_module! { &payload, ).map_err(|err| { frame_support::debug::trace!( - target: "runtime", "Message to lane {:?} is rejected by lane verifier: {:?}", lane_id, err, @@ -257,7 +269,6 @@ decl_module! { &delivery_and_dispatch_fee, ).map_err(|err| { frame_support::debug::trace!( - target: "runtime", "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", lane_id, submitter, @@ -277,7 +288,6 @@ decl_module! { lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); frame_support::debug::trace!( - target: "runtime", "Accepted message {} to lane {:?}", nonce, lane_id, @@ -303,7 +313,6 @@ decl_module! { let messages = verify_and_decode_messages_proof::(proof) .map_err(|err| { frame_support::debug::trace!( - target: "runtime", "Rejecting invalid messages proof: {:?}", err, ); @@ -323,7 +332,6 @@ decl_module! { .sum(); if dispatch_weight < actual_dispatch_weight { frame_support::debug::trace!( - target: "runtime", "Rejecting messages proof because of dispatch weight mismatch: declared={}, expected={}", dispatch_weight, actual_dispatch_weight, @@ -342,7 +350,6 @@ decl_module! { let updated_latest_confirmed_nonce = lane.receive_state_update(lane_state); if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { frame_support::debug::trace!( - target: "runtime", "Received lane {:?} state update: latest_confirmed_nonce={}", lane_id, updated_latest_confirmed_nonce, @@ -361,7 +368,6 @@ decl_module! { } frame_support::debug::trace!( - target: "runtime", "Received messages: total={}, valid={}", total_messages, valid_messages, @@ -378,7 +384,6 @@ decl_module! { let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { frame_support::debug::trace!( - target: "runtime", "Rejecting invalid messages delivery proof: {:?}", err, ); @@ -414,7 +419,6 @@ decl_module! { } frame_support::debug::trace!( - target: "runtime", "Received messages delivery proof up to (and including) {} at lane {:?}", lane_data.latest_received_nonce, lane_id, diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index cf7d4fbc6ffef..1515c46ca897a 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -33,10 +33,12 @@ use crate::storage::ImportedHeader; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; -use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure}; -use frame_system::{ensure_root, ensure_signed}; +use frame_support::{ + decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, weights::DispatchClass, +}; +use frame_system::{ensure_signed, RawOrigin}; use sp_runtime::traits::Header as HeaderT; -use sp_runtime::RuntimeDebug; +use sp_runtime::{traits::BadOrigin, RuntimeDebug}; use sp_std::{marker::PhantomData, prelude::*}; use sp_trie::StorageProof; @@ -105,17 +107,30 @@ decl_storage! { // Grandpa doesn't require there to always be a pending change. In fact, most of the time // there will be no pending change available. NextScheduledChange: map hasher(identity) BridgedBlockHash => Option>>; - /// Whether or not the bridge has been initialized. + /// Optional pallet owner. /// - /// This is important to know to ensure that we don't try and initialize the bridge twice - /// and create an inconsistent genesis state. - IsInitialized: bool; + /// Pallet owner has a right to halt all pallet operations and then resume it. If it is + /// `None`, then there are no direct ways to halt/resume pallet operations, but other + /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt + /// flag directly or call the `halt_operations`). + ModuleOwner get(fn module_owner): Option; + /// If true, all pallet transactions are failed immediately. + IsHalted get(fn is_halted): bool; } add_extra_genesis { + config(owner): Option; config(init_data): Option>>; build(|config| { + if let Some(ref owner) = config.owner { + >::put(owner); + } + if let Some(init_data) = config.init_data.clone() { initialize_bridge::(init_data); + } else { + // Since the bridge hasn't been initialized we shouldn't allow anyone to perform + // transactions. + IsHalted::put(true); } }) } @@ -129,12 +144,14 @@ decl_error! { UnfinalizedHeader, /// The header is unknown. UnknownHeader, - /// The pallet has already been initialized. - AlreadyInitialized, /// The storage proof doesn't contains storage root. So it is invalid for given header. StorageRootMismatch, /// Error when trying to fetch storage value from the proof. StorageValueUnavailable, + /// All pallet operations are halted. + Halted, + /// The pallet has already been initialized. + AlreadyInitialized, } } @@ -153,8 +170,9 @@ decl_module! { origin, header: BridgedHeader, ) -> DispatchResult { + ensure_operational::()?; let _ = ensure_signed(origin)?; - frame_support::debug::trace!(target: "sub-bridge", "Got header {:?}", header); + frame_support::debug::trace!("Got header {:?}", header); let mut verifier = verifier::Verifier { storage: PalletStorage::::new(), @@ -179,8 +197,9 @@ decl_module! { hash: BridgedBlockHash, finality_proof: Vec, ) -> DispatchResult { + ensure_operational::()?; let _ = ensure_signed(origin)?; - frame_support::debug::trace!(target: "sub-bridge", "Got header hash {:?}", hash); + frame_support::debug::trace!("Got header hash {:?}", hash); let mut verifier = verifier::Verifier { storage: PalletStorage::::new(), @@ -208,10 +227,52 @@ decl_module! { origin, init_data: InitializationData>, ) { - let _ = ensure_root(origin)?; - let init_allowed = !IsInitialized::get(); + ensure_owner_or_root::(origin)?; + let init_allowed = !>::exists(); ensure!(init_allowed, >::AlreadyInitialized); - initialize_bridge::(init_data); + initialize_bridge::(init_data.clone()); + + frame_support::debug::info!( + "Pallet has been initialized with the following parameters: {:?}", init_data + ); + } + + /// Change `ModuleOwner`. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] + pub fn set_owner(origin, new_owner: Option) { + ensure_owner_or_root::(origin)?; + match new_owner { + Some(new_owner) => { + ModuleOwner::::put(&new_owner); + frame_support::debug::info!("Setting pallet Owner to: {:?}", new_owner); + }, + None => { + ModuleOwner::::kill(); + frame_support::debug::info!("Removed Owner of pallet."); + }, + } + } + + /// Halt all pallet operations. Operations may be resumed using `resume_operations` call. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] + pub fn halt_operations(origin) { + ensure_owner_or_root::(origin)?; + IsHalted::put(true); + frame_support::debug::warn!("Stopping pallet operations."); + } + + /// Resume all pallet operations. May be called even if pallet is halted. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] + pub fn resume_operations(origin) { + ensure_owner_or_root::(origin)?; + IsHalted::put(false); + frame_support::debug::info!("Resuming pallet operations."); } } } @@ -288,14 +349,33 @@ impl Module { } } -// Since this writes to storage with no real checks this should only be used in functions that were -// called by a trusted origin. +/// Ensure that the origin is either root, or `ModuleOwner`. +fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { + match origin.into() { + Ok(RawOrigin::Root) => Ok(()), + Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::module_owner().as_ref() => Ok(()), + _ => Err(BadOrigin), + } +} + +/// Ensure that the pallet is in operational mode (not halted). +fn ensure_operational() -> Result<(), Error> { + if IsHalted::get() { + Err(>::Halted) + } else { + Ok(()) + } +} + +/// Since this writes to storage with no real checks this should only be used in functions that were +/// called by a trusted origin. fn initialize_bridge(init_params: InitializationData>) { let InitializationData { header, authority_list, set_id, scheduled_change, + is_halted, } = init_params; let initial_hash = header.hash(); @@ -328,7 +408,7 @@ fn initialize_bridge(init_params: InitializationData> }, ); - IsInitialized::put(true); + IsHalted::put(is_halted); } /// Expected interface for interacting with bridge pallet storage. @@ -505,13 +585,14 @@ mod tests { use sp_runtime::DispatchError; #[test] - fn only_root_origin_can_initialize_pallet() { + fn init_root_or_owner_origin_can_initialize_pallet() { run_test(|| { let init_data = InitializationData { header: test_header(1), authority_list: authority_list(), set_id: 1, scheduled_change: None, + is_halted: false, }; assert_noop!( @@ -519,53 +600,134 @@ mod tests { DispatchError::BadOrigin, ); - assert_ok!(Module::::initialize(Origin::root(), init_data)); + assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + + // Reset storage so we can initialize the pallet again + BestFinalized::::kill(); + ModuleOwner::::put(2); + assert_ok!(Module::::initialize(Origin::signed(2), init_data)); }) } #[test] - fn can_only_initialize_pallet_once() { + fn init_storage_entries_are_correctly_initialized() { run_test(|| { let init_data = InitializationData { header: test_header(1), authority_list: authority_list(), set_id: 1, scheduled_change: None, + is_halted: false, }; assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); - assert_noop!( - Module::::initialize(Origin::root(), init_data,), - >::AlreadyInitialized, + + let storage = PalletStorage::::new(); + assert!(storage.header_exists(init_data.header.hash())); + assert_eq!( + storage.best_headers()[0], + crate::HeaderId { + number: *init_data.header.number(), + hash: init_data.header.hash() + } ); + assert_eq!(storage.best_finalized_header().hash(), init_data.header.hash()); + assert_eq!(storage.current_authority_set().authorities, init_data.authority_list); + assert_eq!(IsHalted::get(), false); }) } #[test] - fn storage_entries_are_correctly_initialized() { + fn init_can_only_initialize_pallet_once() { run_test(|| { let init_data = InitializationData { header: test_header(1), authority_list: authority_list(), set_id: 1, scheduled_change: None, + is_halted: false, }; assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + assert_noop!( + Module::::initialize(Origin::root(), init_data), + >::AlreadyInitialized + ); + }) + } - let storage = PalletStorage::::new(); + #[test] + fn pallet_owner_may_change_owner() { + run_test(|| { + ModuleOwner::::put(2); - assert!(IsInitialized::get()); - assert!(storage.header_exists(init_data.header.hash())); - assert_eq!( - storage.best_headers()[0], - crate::HeaderId { - number: *init_data.header.number(), - hash: init_data.header.hash() - } + assert_ok!(Module::::set_owner(Origin::root(), Some(1))); + assert_noop!( + Module::::halt_operations(Origin::signed(2)), + DispatchError::BadOrigin, + ); + assert_ok!(Module::::halt_operations(Origin::root())); + + assert_ok!(Module::::set_owner(Origin::signed(1), None)); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + assert_noop!( + Module::::resume_operations(Origin::signed(2)), + DispatchError::BadOrigin, + ); + assert_ok!(Module::::resume_operations(Origin::root())); + }); + } + + #[test] + fn pallet_may_be_halted_by_root() { + run_test(|| { + assert_ok!(Module::::halt_operations(Origin::root())); + assert_ok!(Module::::resume_operations(Origin::root())); + }); + } + + #[test] + fn pallet_may_be_halted_by_owner() { + run_test(|| { + ModuleOwner::::put(2); + + assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_ok!(Module::::resume_operations(Origin::signed(2))); + + assert_noop!( + Module::::halt_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + + assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + }); + } + + #[test] + fn pallet_rejects_transactions_if_halted() { + run_test(|| { + IsHalted::put(true); + + assert_noop!( + Module::::import_signed_header(Origin::signed(1), test_header(1)), + Error::::Halted, + ); + + assert_noop!( + Module::::finalize_header(Origin::signed(1), test_header(1).hash(), vec![]), + Error::::Halted, ); - assert_eq!(storage.best_finalized_header().hash(), init_data.header.hash()); - assert_eq!(storage.current_authority_set().authorities, init_data.authority_list); }) } diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs index 24c42482955ce..86677f67c54f8 100644 --- a/modules/substrate/src/storage.rs +++ b/modules/substrate/src/storage.rs @@ -38,6 +38,8 @@ pub struct InitializationData { pub set_id: SetId, /// The first scheduled authority set change of the pallet. pub scheduled_change: Option>, + /// Should the pallet block transaction immediately after initialization. + pub is_halted: bool, } /// A Grandpa Authority List and ID. From 521cdbf826779bf82e1e55b003f76fa0756981a1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 10 Nov 2020 20:15:36 +0300 Subject: [PATCH 0222/1210] Relay subcommands to initialize substrate bridge pallet (#483) * initialize substrate bridge from relay * is_halted: false * initialize using su instead of owner * Fix wording in comments Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + relays/substrate/Cargo.toml | 1 + relays/substrate/src/cli.rs | 38 ++++++ relays/substrate/src/headers_initialize.rs | 141 +++++++++++++++++++++ relays/substrate/src/main.rs | 97 ++++++++++++++ 6 files changed, 279 insertions(+) create mode 100644 relays/substrate/src/headers_initialize.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 42251b94b01b3..70134602dad34 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -58,6 +58,7 @@ pub use frame_support::{ pub use pallet_balances::Call as BalancesCall; pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeRialtoCall; +pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index ea73fd2d1f520..020be14458350 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -67,6 +67,7 @@ pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeMillauCall; +pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; #[cfg(any(feature = "std", test))] diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index a147eb2bc223a..f0d6c1e2183a6 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -37,5 +37,6 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } frame-support = "2.0" sp-core = "2.0" +sp-finality-grandpa = "2.0" sp-runtime = "2.0" sp-trie = "2.0" diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index d3ad78c3a1a0e..334ebd0d5c696 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -17,6 +17,8 @@ //! Deal with CLI args of substrate-to-substrate relay. use bp_message_lane::LaneId; +use sp_core::Bytes; +use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId; use structopt::{clap::arg_enum, StructOpt}; /// Parse relay CLI args. @@ -28,6 +30,17 @@ pub fn parse_args() -> Command { #[derive(StructOpt)] #[structopt(about = "Substrate-to-Substrate relay")] pub enum Command { + /// Initialize Millau headers bridge in Rialto. + InitializeMillauHeadersBridgeInRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau_bridge_params: MillauBridgeInitializationParams, + }, /// Relay Millau headers to Rialto. MillauHeadersToRialto { #[structopt(flatten)] @@ -39,6 +52,17 @@ pub enum Command { #[structopt(flatten)] prometheus_params: PrometheusParams, }, + /// Initialize Rialto headers bridge in Millau. + InitializeRialtoHeadersBridgeInMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto_bridge_params: RialtoBridgeInitializationParams, + }, /// Relay Rialto headers to Millau. RialtoHeadersToMillau { #[structopt(flatten)] @@ -165,6 +189,20 @@ macro_rules! declare_chain_options { #[structopt(long)] pub [<$chain_prefix _signer_password>]: Option, } + + #[doc = $chain " headers bridge initialization params."] + #[derive(StructOpt)] + pub struct [<$chain BridgeInitializationParams>] { + #[doc = "Hex-encoded " $chain " header to initialize bridge with. If not specified, genesis header is used."] + #[structopt(long)] + pub [<$chain_prefix _initial_header>]: Option, + #[doc = "Hex-encoded " $chain " GRANDPA authorities set to initialize bridge with. If not specified, set from genesis block is used."] + #[structopt(long)] + pub [<$chain_prefix _initial_authorities>]: Option, + #[doc = "Id of the " $chain " GRANDPA authorities set to initialize bridge with. If not specified, zero is used."] + #[structopt(long)] + pub [<$chain_prefix _initial_authorities_set_id>]: Option, + } } }; } diff --git a/relays/substrate/src/headers_initialize.rs b/relays/substrate/src/headers_initialize.rs new file mode 100644 index 0000000000000..6b66a2e9bd7fb --- /dev/null +++ b/relays/substrate/src/headers_initialize.rs @@ -0,0 +1,141 @@ +// Copyright 2019-2020 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 . + +//! Initialize Substrate -> Substrate headers bridge. +//! +//! Initialization is a transaction that calls `initialize()` function of the +//! `pallet-substrate-bridge` pallet. This transaction brings initial header +//! and authorities set from source to target chain. The headers sync starts +//! with this header. + +use codec::Decode; +use pallet_substrate_bridge::InitializationData; +use relay_substrate_client::{Chain, Client}; +use sp_core::Bytes; +use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, SetId as GrandpaAuthoritiesSetId}; + +/// Submit headers-bridge initialization transaction. +pub async fn initialize( + source_client: Client, + target_client: Client, + raw_initial_header: Option, + raw_initial_authorities_set: Option, + initial_authorities_set_id: Option, + prepare_initialize_transaction: impl FnOnce(InitializationData) -> Result, +) { + let result = do_initialize( + source_client, + target_client, + raw_initial_header, + raw_initial_authorities_set, + initial_authorities_set_id, + prepare_initialize_transaction, + ) + .await; + + match result { + Ok(tx_hash) => log::info!( + target: "bridge", + "Successfully submitted {}-headers bridge initialization transaction to {}: {:?}", + SourceChain::NAME, + TargetChain::NAME, + tx_hash, + ), + Err(err) => log::error!( + target: "bridge", + "Failed to submit {}-headers bridge initialization transaction to {}: {:?}", + SourceChain::NAME, + TargetChain::NAME, + err, + ), + } +} + +/// Craft and submit initialization transaction, returning any error that may occur. +async fn do_initialize( + source_client: Client, + target_client: Client, + raw_initial_header: Option, + raw_initial_authorities_set: Option, + initial_authorities_set_id: Option, + prepare_initialize_transaction: impl FnOnce(InitializationData) -> Result, +) -> Result { + let initialization_data = prepare_initialization_data( + source_client, + raw_initial_header, + raw_initial_authorities_set, + initial_authorities_set_id, + ) + .await?; + let initialization_tx = prepare_initialize_transaction(initialization_data)?; + let initialization_tx_hash = target_client + .submit_extrinsic(initialization_tx) + .await + .map_err(|err| format!("Failed to submit {} transaction: {:?}", TargetChain::NAME, err))?; + Ok(initialization_tx_hash) +} + +/// Prepare initialization data for the headers-bridge pallet. +async fn prepare_initialization_data( + source_client: Client, + raw_initial_header: Option, + raw_initial_authorities_set: Option, + initial_authorities_set_id: Option, +) -> Result, String> { + let source_genesis_hash = *source_client.genesis_hash(); + + let initial_header = match raw_initial_header { + Some(raw_initial_header) => SourceChain::Header::decode(&mut &raw_initial_header.0[..]) + .map_err(|err| format!("Failed to decode {} initial header: {:?}", SourceChain::NAME, err))?, + None => source_client + .header_by_hash(source_genesis_hash) + .await + .map_err(|err| format!("Failed to retrive {} genesis header: {:?}", SourceChain::NAME, err))?, + }; + + let raw_initial_authorities_set = match raw_initial_authorities_set { + Some(raw_initial_authorities_set) => raw_initial_authorities_set.0, + None => source_client + .grandpa_authorities_set(source_genesis_hash) + .await + .map_err(|err| { + format!( + "Failed to retrive {} authorities set at genesis header: {:?}", + SourceChain::NAME, + err + ) + })?, + }; + let initial_authorities_set = + GrandpaAuthoritiesSet::decode(&mut &raw_initial_authorities_set[..]).map_err(|err| { + format!( + "Failed to decode {} initial authorities set: {:?}", + SourceChain::NAME, + err + ) + })?; + + Ok(InitializationData { + header: initial_header, + authority_list: initial_authorities_set, + set_id: initial_authorities_set_id.unwrap_or(0), + // There may be multiple scheduled changes, so on real chains we should select proper + // moment, when there's nothing scheduled. On ephemeral (temporary) chains, it is ok to + // start with genesis. + scheduled_change: None, + is_halted: false, + }) +} diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 98c30ff0be58a..727e4eb24300c 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -33,6 +33,7 @@ pub type MillauClient = relay_substrate_client::Client; pub type RialtoClient = relay_substrate_client::Client; mod cli; +mod headers_initialize; mod headers_maintain; mod headers_pipeline; mod headers_target; @@ -53,6 +54,54 @@ fn main() { async fn run_command(command: cli::Command) -> Result<(), String> { match command { + cli::Command::InitializeMillauHeadersBridgeInRialto { + millau, + rialto, + rialto_sign, + millau_bridge_params, + } => { + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let rialto_sign = RialtoSigningParams::from_suri( + &rialto_sign.rialto_signer, + rialto_sign.rialto_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let rialto_signer_next_index = rialto_client + .next_account_index(rialto_sign.signer.public().into()) + .await?; + + headers_initialize::initialize( + millau_client, + rialto_client.clone(), + millau_bridge_params.millau_initial_header, + millau_bridge_params.millau_initial_authorities, + millau_bridge_params.millau_initial_authorities_set_id, + move |initialization_data| { + Ok(Bytes( + Rialto::sign_transaction( + &rialto_client, + &rialto_sign.signer, + rialto_signer_next_index, + millau_runtime::SudoCall::sudo(Box::new( + rialto_runtime::BridgeMillauCall::initialize(initialization_data).into(), + )) + .into(), + ) + .encode(), + )) + }, + ) + .await; + } cli::Command::MillauHeadersToRialto { millau, rialto, @@ -76,6 +125,54 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; } + cli::Command::InitializeRialtoHeadersBridgeInMillau { + rialto, + millau, + millau_sign, + rialto_bridge_params, + } => { + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + let millau_signer_next_index = millau_client + .next_account_index(millau_sign.signer.public().into()) + .await?; + + headers_initialize::initialize( + rialto_client, + millau_client.clone(), + rialto_bridge_params.rialto_initial_header, + rialto_bridge_params.rialto_initial_authorities, + rialto_bridge_params.rialto_initial_authorities_set_id, + move |initialization_data| { + Ok(Bytes( + Millau::sign_transaction( + &millau_client, + &millau_sign.signer, + millau_signer_next_index, + millau_runtime::SudoCall::sudo(Box::new( + millau_runtime::BridgeRialtoCall::initialize(initialization_data).into(), + )) + .into(), + ) + .encode(), + )) + }, + ) + .await; + } cli::Command::RialtoHeadersToMillau { rialto, millau, From ca0bf1127f82b64620978260779382eea92ed100 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 10 Nov 2020 17:33:48 -0500 Subject: [PATCH 0223/1210] Remove Millau Genesis Config in Rialto Node (#494) --- bin/rialto/node/src/chain_spec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index b562e646a62e8..8dd57e2d6e86b 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -186,7 +186,7 @@ fn load_kovan_bridge_config() -> Option { fn load_millau_bridge_config() -> Option { Some(BridgeMillauConfig { - init_data: Some(rialto_runtime::millau::init_data()), + init_data: None, owner: Some([0; 32].into()), }) } From 7e60247ea275ccc366c59c6a0f86c5c8bb0a9e15 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 11 Nov 2020 18:04:21 +0300 Subject: [PATCH 0224/1210] Fix Typo in Relay CLI Subcommand Description (#497) --- relays/substrate/src/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 334ebd0d5c696..2b622c362be04 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -90,7 +90,7 @@ pub enum Command { #[structopt(long)] lane: HexLaneId, }, - /// Submit message to given Rialto -> Millau lane. + /// Submit message to given Millau -> Rialto lane. SubmitMillauToRialtoMessage { #[structopt(flatten)] millau: MillauConnectionParams, From c7c30cba99bc098cede40c6eb1625c05d6ac62f0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 Nov 2020 19:27:52 +0300 Subject: [PATCH 0225/1210] Removed unused file (#498) * removed unused file * another unused file --- bin/millau/runtime/src/lib.rs | 1 - bin/millau/runtime/src/rialto.rs | 56 ----------------- bin/rialto/runtime/src/lib.rs | 1 - bin/rialto/runtime/src/millau.rs | 100 ------------------------------- 4 files changed, 158 deletions(-) delete mode 100644 bin/millau/runtime/src/rialto.rs delete mode 100644 bin/rialto/runtime/src/millau.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 70134602dad34..e3154d382a294 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -28,7 +28,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod rialto; pub mod rialto_messages; use codec::Decode; diff --git a/bin/millau/runtime/src/rialto.rs b/bin/millau/runtime/src/rialto.rs deleted file mode 100644 index 0c25d93e93ddb..0000000000000 --- a/bin/millau/runtime/src/rialto.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2020 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 . - -//! Configuration parameters for the Rialto Substrate chain. - -use bp_rialto::Header; -use pallet_substrate_bridge::AuthoritySet; -use sp_core::crypto::Public; -use sp_finality_grandpa::AuthorityId; -use sp_std::vec; - -/// The first header known to the pallet. -/// -/// Note that this does not need to be the genesis header of the Rialto -/// chain since the pallet may start at any arbitrary header. -// To get this we first need to call the `chain_getBlockHash` RPC method, and then -// we can use the result from that and call the `chain_getBlock` RPC method to get -// the rest of the info. -// -// In this case we've grabbed the genesis block of the Rialto Substrate chain. -pub fn initial_header() -> Header { - Header { - parent_hash: Default::default(), - number: Default::default(), - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: Default::default(), - } -} - -/// The first set of Grandpa authorities known to the pallet. -/// -/// Note that this doesn't have to be the "genesis" authority set, as the -/// pallet can be configured to start from any height. -pub fn initial_authority_set() -> AuthoritySet { - let set_id = 0; - let authorities = vec![ - (AuthorityId::from_slice(&[1; 32]), 1), - (AuthorityId::from_slice(&[2; 32]), 1), - (AuthorityId::from_slice(&[3; 32]), 1), - ]; - AuthoritySet::new(authorities, set_id) -} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 020be14458350..5953f054c1b17 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -33,7 +33,6 @@ pub mod exchange; #[cfg(feature = "runtime-benchmarks")] pub mod benches; pub mod kovan; -pub mod millau; pub mod millau_messages; pub mod rialto_poa; diff --git a/bin/rialto/runtime/src/millau.rs b/bin/rialto/runtime/src/millau.rs deleted file mode 100644 index 3549360b111b9..0000000000000 --- a/bin/rialto/runtime/src/millau.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2020 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 . - -//! Configuration parameters for the Millau Substrate chain. - -use bp_rialto::Header; -use hex_literal::hex; -use pallet_substrate_bridge::{AuthoritySet, InitializationData}; -use sp_core::crypto::Public; -use sp_finality_grandpa::AuthorityId; -use sp_std::vec; - -/// Information about where the bridge palelt should start syncing from. This includes things like -/// the initial header and the initial authorities of the briged chain. -pub fn init_data() -> InitializationData
{ - let authority_set = initial_authority_set(); - InitializationData { - header: initial_header(), - authority_list: authority_set.authorities, - set_id: authority_set.set_id, - scheduled_change: None, - is_halted: false, - } -} - -/// The first header known to the pallet. -/// -/// Note that this does not need to be the genesis header of the Millau -/// chain since the pallet may start at any arbitrary header. -// To get this we first need to call the `chain_getBlockHash` RPC method, and then -// we can use the result from that and call the `chain_getBlock` RPC method to get -// the rest of the info. -// -// In this case we've grabbed the genesis block of the Millau Substrate chain. -pub fn initial_header() -> Header { - Header { - parent_hash: Default::default(), - number: Default::default(), - state_root: hex!("0f2ca6dde08378ef81958bf087a3c40391079d0dbf434ea3fa0f73d54200839b").into(), - extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - digest: Default::default(), - } -} - -/// The first set of Grandpa authorities known to the pallet. -/// -/// Note that this doesn't have to be the "genesis" authority set, as the -/// pallet can be configured to start from any height. -pub fn initial_authority_set() -> AuthoritySet { - let set_id = 0; - - // These authorities are: Alice, Bob, Charlie, Dave, and Eve. - let authorities = vec![ - ( - AuthorityId::from_slice(&hex!( - "88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee" - )), - 1, - ), - ( - AuthorityId::from_slice(&hex!( - "d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae69" - )), - 1, - ), - ( - AuthorityId::from_slice(&hex!( - "439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f" - )), - 1, - ), - ( - AuthorityId::from_slice(&hex!( - "5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9" - )), - 1, - ), - ( - AuthorityId::from_slice(&hex!( - "1dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b5" - )), - 1, - ), - ]; - - AuthoritySet::new(authorities, set_id) -} From 025cb8c8951f53c3ebce0a266cb268148b36e645 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 16 Nov 2020 14:18:49 -0500 Subject: [PATCH 0226/1210] Fixes for Millau-Rialto Deployment (#493) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Expose two nodes publicly through brucke.link * Use flags for GNU `sed` instead of BSD `sed` * Update Substrate relay entrypoint scripts to initialize bridge * Add Rialto to Millau relay to Compose deployment * Stop initializing Rialto chain through chainspec * Include logging for Substrate pallet * Make Rialto to Millau entrypoint executable * Use YAML references for relay components * Use published Substrate Relay image * Relay messages from Millau to Rialto * Use Bob nodes to serve message lane * Fix some port number issues for PoA-Rialto deployment * Stop directly referencing `environment` anchor in nodes * Add probable cause to relayer error message * Edit monitoring config file in-place * Add some sleep time between bridge init call and starting relays * Expose grafana. * Use Root key as bridge pallet owner In our case that's going to be Alice since she's Root for our Dev and Local chains. Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 13 +++++-------- relays/substrate/src/headers_target.rs | 10 +++++----- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 541d240b6a1ac..957ee4750c4af 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -158,7 +158,7 @@ fn testnet_genesis( pallet_substrate_bridge: Some(BridgeRialtoConfig { // We'll initialize the pallet with a dispatchable instead. init_data: None, - owner: None, + owner: Some(root_key.clone()), }), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 8dd57e2d6e86b..50f141465ba12 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -157,7 +157,11 @@ fn testnet_genesis( pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), - pallet_substrate_bridge: load_millau_bridge_config(), + pallet_substrate_bridge: Some(BridgeMillauConfig { + // We'll initialize the pallet with a dispatchable instead. + init_data: None, + owner: Some(root_key.clone()), + }), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { keys: initial_authorities @@ -183,10 +187,3 @@ fn load_kovan_bridge_config() -> Option { initial_validators: rialto_runtime::kovan::genesis_validators(), }) } - -fn load_millau_bridge_config() -> Option { - Some(BridgeMillauConfig { - init_data: None, - owner: Some([0; 32].into()), - }) -} diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index 6f23706d171cb..6fb4a1500af6e 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -91,11 +91,11 @@ where let decoded_response: Vec<(P::Number, P::Hash)> = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - let best_header = decoded_response.last().ok_or_else(|| { - SubstrateError::ResponseParseFailed( - "Parsed an empty list of headers, we should always have at least one.".into(), - ) - })?; + const WARNING_MSG: &str = "Parsed an empty list of headers, we should always have at least + one. Has the bridge pallet been initialized yet?"; + let best_header = decoded_response + .last() + .ok_or_else(|| SubstrateError::ResponseParseFailed(WARNING_MSG.into()))?; let best_header_id = HeaderId(best_header.0, best_header.1); Ok(best_header_id) } From ad1054d78768ed548b0f971a3038d7ad93ae747a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 17 Nov 2020 23:27:30 +0300 Subject: [PATCH 0227/1210] Limit messages weight in batch (#496) * limit messages in the batch by weight/count * fixed components compilation * reverted obsolete parts of #469 * implement generated_messages_weights * actually use computed weight in message proof * fmt and clippy * fixed TODO * clippy * Update relays/messages-relay/src/message_race_loop.rs Co-authored-by: Hernando Castano * add issue reference * add assert message * grumbles * fmt * reexport weight from bp-message-lane Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/node/src/service.rs | 1 - bin/millau/runtime/src/lib.rs | 19 +- bin/rialto/node/src/service.rs | 1 - bin/rialto/runtime/src/lib.rs | 19 +- modules/message-lane/rpc/Cargo.toml | 2 - modules/message-lane/rpc/src/lib.rs | 43 +- primitives/message-lane/src/lib.rs | 14 +- relays/messages-relay/Cargo.toml | 1 - relays/messages-relay/src/message_lane.rs | 16 - .../messages-relay/src/message_lane_loop.rs | 131 ++++-- .../src/message_race_delivery.rs | 337 ++++++++++++--- .../messages-relay/src/message_race_loop.rs | 90 ++-- .../src/message_race_receiving.rs | 70 +++- .../src/message_race_strategy.rs | 389 +++++++++++------- relays/messages-relay/src/metrics.rs | 17 +- relays/substrate-client/src/client.rs | 7 +- relays/substrate-client/src/error.rs | 3 + relays/substrate-client/src/rpc.rs | 3 +- relays/substrate/src/messages_source.rs | 56 ++- relays/substrate/src/messages_target.rs | 15 +- .../src/millau_messages_to_rialto.rs | 8 +- 21 files changed, 848 insertions(+), 394 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 086ef7609cc1e..04ad152b37b07 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -221,7 +221,6 @@ pub fn new_full(config: Configuration) -> Result { finality_proof_provider.clone(), ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( - client.clone(), backend.clone(), Arc::new(MillauMessageLaneKeys), ))); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index e3154d382a294..7435788acc666 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -542,12 +542,19 @@ impl_runtime_apis! { // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) impl bp_message_lane::OutboundLaneApi for Runtime { - fn messages_dispatch_weight(lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce) -> Weight { - (begin..=end) - .filter_map(|nonce| BridgeRialtoMessageLane::outbound_message_payload(lane, nonce)) - .filter_map(|encoded_payload| rialto_messages::ToRialtoMessagePayload::decode(&mut &encoded_payload[..]).ok()) - .map(|decoded_payload| decoded_payload.weight) - .fold(0, |sum, weight| sum.saturating_add(weight)) + fn messages_dispatch_weight( + lane: bp_message_lane::LaneId, + begin: bp_message_lane::MessageNonce, + end: bp_message_lane::MessageNonce, + ) -> Vec<(bp_message_lane::MessageNonce, Weight)> { + (begin..=end).filter_map(|nonce| { + let encoded_payload = BridgeRialtoMessageLane::outbound_message_payload(lane, nonce)?; + let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode( + &mut &encoded_payload[..] + ).ok()?; + Some((nonce, decoded_payload.weight)) + }) + .collect() } fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 1d7dfdffefbd3..1bb6e3b310fed 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -220,7 +220,6 @@ pub fn new_full(config: Configuration) -> Result { finality_proof_provider.clone(), ))); io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( - client.clone(), backend.clone(), Arc::new(RialtoMessageLaneKeys), ))); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5953f054c1b17..4a3855f69e6d6 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -706,12 +706,19 @@ impl_runtime_apis! { // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) impl bp_message_lane::OutboundLaneApi for Runtime { - fn messages_dispatch_weight(lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce) -> Weight { - (begin..=end) - .filter_map(|nonce| BridgeMillauMessageLane::outbound_message_payload(lane, nonce)) - .filter_map(|encoded_payload| millau_messages::ToMillauMessagePayload::decode(&mut &encoded_payload[..]).ok()) - .map(|decoded_payload| decoded_payload.weight) - .fold(0, |sum, weight| sum.saturating_add(weight)) + fn messages_dispatch_weight( + lane: bp_message_lane::LaneId, + begin: bp_message_lane::MessageNonce, + end: bp_message_lane::MessageNonce, + ) -> Vec<(bp_message_lane::MessageNonce, Weight)> { + (begin..=end).filter_map(|nonce| { + let encoded_payload = BridgeMillauMessageLane::outbound_message_payload(lane, nonce)?; + let decoded_payload = millau_messages::ToMillauMessagePayload::decode( + &mut &encoded_payload[..] + ).ok()?; + Some((nonce, decoded_payload.weight)) + }) + .collect() } fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index cc179f5d366c7..e9ef6c1cc6b2a 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -20,9 +20,7 @@ bp-message-lane = { path = "../../../primitives/message-lane" } # Substrate Dependencies -frame-support = "2.0" sc-client-api = "2.0" -sp-api = "2.0" sp-blockchain = "2.0" sp-core = "2.0" sp-runtime = "2.0" diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index bcc786f3866fc..54ac5eba1e51b 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -18,14 +18,12 @@ use crate::error::{Error, FutureResult}; -use bp_message_lane::{LaneId, MessageNonce, OutboundLaneApi}; +use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; -use frame_support::weights::Weight; use futures::{FutureExt, TryFutureExt}; use jsonrpc_core::futures::Future as _; use jsonrpc_derive::rpc; use sc_client_api::Backend as BackendT; -use sp_api::ProvideRuntimeApi; use sp_blockchain::{Error as BlockchainError, HeaderBackend}; use sp_core::{storage::StorageKey, Bytes}; use sp_runtime::{codec::Encode, generic::BlockId, traits::Block as BlockT}; @@ -56,8 +54,8 @@ pub trait Runtime: Send + Sync + 'static { /// Provides RPC methods for interacting with message-lane pallet. #[rpc] pub trait MessageLaneApi { - /// Returns cumulative dispatch weight of messages in given inclusive range and their storage proof. - /// The state of outbound lane is included in the proof if `include_outbound_lane_state` is true. + /// Returns storage proof of messages in given inclusive range. The state of outbound + /// lane is included in the proof if `include_outbound_lane_state` is true. #[rpc(name = "messageLane_proveMessages")] fn prove_messages( &self, @@ -67,7 +65,7 @@ pub trait MessageLaneApi { end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> FutureResult<(Weight, MessagesProof)>; + ) -> FutureResult; /// Returns proof-of-message(s) delivery. #[rpc(name = "messageLane_proveMessagesDelivery")] @@ -80,18 +78,16 @@ pub trait MessageLaneApi { } /// Implements the MessageLaneApi trait for interacting with message lanes. -pub struct MessageLaneRpcHandler { - client: Arc, +pub struct MessageLaneRpcHandler { backend: Arc, runtime: Arc, _phantom: std::marker::PhantomData, } -impl MessageLaneRpcHandler { +impl MessageLaneRpcHandler { /// Creates new mesage lane RPC handler. - pub fn new(client: Arc, backend: Arc, runtime: Arc) -> Self { + pub fn new(backend: Arc, runtime: Arc) -> Self { Self { - client, backend, runtime, _phantom: Default::default(), @@ -99,11 +95,9 @@ impl MessageLaneRpcHandler } } -impl MessageLaneApi for MessageLaneRpcHandler +impl MessageLaneApi for MessageLaneRpcHandler where Block: BlockT, - Client: ProvideRuntimeApi + Send + Sync + 'static, - Client::Api: OutboundLaneApi, Backend: BackendT + 'static, R: Runtime, { @@ -115,22 +109,7 @@ where end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> FutureResult<(Weight, MessagesProof)> { - let block = unwrap_or_best(&*self.backend, block); - - let messages_dispatch_weight_result = - self.client - .runtime_api() - .messages_dispatch_weight(&BlockId::Hash(block), lane, begin, end); - let messages_dispatch_weight = match messages_dispatch_weight_result { - Ok(messages_dispatch_weight) => messages_dispatch_weight, - Err(error) => { - return Box::new(jsonrpc_core::futures::future::err( - blockchain_err(BlockchainError::Execution(Box::new(format!("{:?}", error)))).into(), - )) - } - }; - + ) -> FutureResult { let runtime = self.runtime.clone(); let outbound_lane_data_key = if include_outbound_lane_state { Some(runtime.inbound_lane_data_key(&instance, &lane)) @@ -140,14 +119,14 @@ where Box::new( prove_keys_read( self.backend.clone(), - Some(block), + block, (begin..=end) .map(move |nonce| runtime.message_key(&instance, &lane, nonce)) .chain(outbound_lane_data_key.into_iter()), ) .boxed() .compat() - .map(move |proof| (messages_dispatch_weight, serialize_storage_proof(proof))) + .map(serialize_storage_proof) .map_err(Into::into), ) } diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index e7ae16135b6ed..760333a8cfcb8 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -23,13 +23,16 @@ #![allow(clippy::unnecessary_mut_passed)] use codec::{Decode, Encode}; -use frame_support::{weights::Weight, RuntimeDebug}; +use frame_support::RuntimeDebug; use sp_api::decl_runtime_apis; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; pub mod target_chain; +// Weight is reexported to avoid additional frame-support dependencies in message-lane related crates. +pub use frame_support::weights::Weight; + /// Lane identifier. pub type LaneId = [u8; 4]; @@ -127,7 +130,14 @@ decl_runtime_apis! { /// Outbound message lane API. pub trait OutboundLaneApi { /// Returns dispatch weight of all messages in given inclusive range. - fn messages_dispatch_weight(lane: LaneId, begin: MessageNonce, end: MessageNonce) -> Weight; + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/relays/messages-relay/Cargo.toml b/relays/messages-relay/Cargo.toml index aa76679351514..9c2daefdb4271 100644 --- a/relays/messages-relay/Cargo.toml +++ b/relays/messages-relay/Cargo.toml @@ -11,7 +11,6 @@ async-trait = "0.1.40" futures = "0.3.5" hex = "0.4" log = "0.4.11" -num-traits = "0.2" parking_lot = "0.11.0" # Bridge Dependencies diff --git a/relays/messages-relay/src/message_lane.rs b/relays/messages-relay/src/message_lane.rs index 89840a6e8f0dd..5b4a6a97cc858 100644 --- a/relays/messages-relay/src/message_lane.rs +++ b/relays/messages-relay/src/message_lane.rs @@ -21,7 +21,6 @@ use relay_utils::HeaderId; -use num_traits::{CheckedSub, One, Zero}; use std::fmt::Debug; /// One-way message lane. @@ -31,21 +30,6 @@ pub trait MessageLane: Clone + Send + Sync { /// Name of the messages target. const TARGET_NAME: &'static str; - /// Message nonce type. - type MessageNonce: Clone - + Send - + Sync - + Copy - + Debug - + Default - + From - + Into - + Ord - + CheckedSub - + std::ops::Add - + One - + Zero; - /// Messages proof. type MessagesProof: Clone + Send + Sync; /// Messages receiving proof. diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index a9333509500e6..d0c4b46d8e226 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -30,18 +30,18 @@ use crate::message_race_receiving::run as run_message_receiving_race; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; -use bp_message_lane::LaneId; +use bp_message_lane::{LaneId, MessageNonce, Weight}; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, process_future_result, retry_backoff, FailedClient, MaybeConnectionError, }; -use std::{fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; +use std::{collections::BTreeMap, fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; /// Message lane loop configuration params. #[derive(Debug, Clone)] -pub struct Params { +pub struct Params { /// Id of lane this loop is servicing. pub lane: LaneId, /// Interval at which we ask target node about its updates. @@ -52,10 +52,31 @@ pub struct Params { pub reconnect_delay: Duration, /// The loop will auto-restart if there has been no updates during this period. pub stall_timeout: Duration, + /// Message delivery race parameters. + pub delivery_params: MessageDeliveryParams, +} + +/// Message delivery race parameters. +#[derive(Debug, Clone)] +pub struct MessageDeliveryParams { /// Message delivery race will stop delivering messages if there are `max_unconfirmed_nonces_at_target` /// unconfirmed nonces on the target node. The race would continue once they're confirmed by the /// receiving race. pub max_unconfirmed_nonces_at_target: MessageNonce, + /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. + pub max_messages_weight_in_single_batch: Weight, +} + +/// Messages weights map. +pub type MessageWeightsMap = BTreeMap; + +/// Message delivery race proof parameters. +#[derive(Debug, PartialEq)] +pub struct MessageProofParameters { + /// Include outbound lane state proof? + pub outbound_state_proof_required: bool, + /// Cumulative dispatch weight of messages that we're building proof for. + pub dispatch_weight: Weight, } /// Source client trait. @@ -74,20 +95,27 @@ pub trait SourceClient: Clone + Send + Sync { async fn latest_generated_nonce( &self, id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error>; + ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error>; /// Get nonce of the latest message, which receiving has been confirmed by the target chain. async fn latest_confirmed_received_nonce( &self, id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error>; + ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error>; + + /// Returns mapping of message nonces, generated on this client, to their weights. + async fn generated_messages_weights( + &self, + id: SourceHeaderIdOf

, + nonces: RangeInclusive, + ) -> Result; /// Prove messages in inclusive range [begin; end]. async fn prove_messages( &self, id: SourceHeaderIdOf

, - nonces: RangeInclusive, - include_outbound_lane_state: bool, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error>; + nonces: RangeInclusive, + proof_parameters: MessageProofParameters, + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error>; /// Submit messages receiving proof. async fn submit_messages_receiving_proof( @@ -113,13 +141,13 @@ pub trait TargetClient: Clone + Send + Sync { async fn latest_received_nonce( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error>; + ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; /// Get nonce of latest confirmed message. async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error>; + ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; /// Prove messages receiving at given block. async fn prove_messages_receiving( @@ -131,9 +159,9 @@ pub trait TargetClient: Clone + Send + Sync { async fn submit_messages_proof( &self, generated_at_header: SourceHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::MessagesProof, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; } /// State of the client. @@ -162,7 +190,7 @@ pub struct ClientsState { /// Run message lane service loop. pub fn run( - params: Params, + params: Params, mut source_client: impl SourceClient

, mut target_client: impl TargetClient

, metrics_params: Option, @@ -257,7 +285,7 @@ pub fn run( /// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. async fn run_until_connection_lost, TC: TargetClient

>( - params: Params, + params: Params, source_client: SC, target_client: TC, mut metrics_global: Option<&mut GlobalMetrics>, @@ -289,7 +317,7 @@ async fn run_until_connection_lost, TC: Targ delivery_target_state_receiver, params.stall_timeout, metrics_msg.clone(), - params.max_unconfirmed_nonces_at_target, + params.delivery_params, ) .fuse(); @@ -430,13 +458,15 @@ pub(crate) mod tests { use relay_utils::HeaderId; use std::sync::Arc; - pub fn header_id(number: TestSourceHeaderNumber) -> HeaderId { + pub fn header_id(number: TestSourceHeaderNumber) -> TestSourceHeaderId { HeaderId(number, number) } - pub type TestMessageNonce = u64; - pub type TestMessagesProof = (RangeInclusive, Option); - pub type TestMessagesReceivingProof = TestMessageNonce; + pub type TestSourceHeaderId = HeaderId; + pub type TestTargetHeaderId = HeaderId; + + pub type TestMessagesProof = (RangeInclusive, Option); + pub type TestMessagesReceivingProof = MessageNonce; pub type TestSourceHeaderNumber = u64; pub type TestSourceHeaderHash = u64; @@ -460,8 +490,6 @@ pub(crate) mod tests { const SOURCE_NAME: &'static str = "TestSource"; const TARGET_NAME: &'static str = "TestTarget"; - type MessageNonce = TestMessageNonce; - type MessagesProof = TestMessagesProof; type MessagesReceivingProof = TestMessagesReceivingProof; @@ -477,14 +505,14 @@ pub(crate) mod tests { is_source_fails: bool, is_source_reconnected: bool, source_state: SourceClientState, - source_latest_generated_nonce: TestMessageNonce, - source_latest_confirmed_received_nonce: TestMessageNonce, + source_latest_generated_nonce: MessageNonce, + source_latest_confirmed_received_nonce: MessageNonce, submitted_messages_receiving_proofs: Vec, is_target_fails: bool, is_target_reconnected: bool, target_state: SourceClientState, - target_latest_received_nonce: TestMessageNonce, - target_latest_confirmed_received_nonce: TestMessageNonce, + target_latest_received_nonce: MessageNonce, + target_latest_confirmed_received_nonce: MessageNonce, submitted_messages_proofs: Vec, } @@ -519,7 +547,7 @@ pub(crate) mod tests { async fn latest_generated_nonce( &self, id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, TestMessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf, MessageNonce), Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { @@ -531,21 +559,29 @@ pub(crate) mod tests { async fn latest_confirmed_received_nonce( &self, id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, TestMessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf, MessageNonce), Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); Ok((id, data.source_latest_confirmed_received_nonce)) } + async fn generated_messages_weights( + &self, + _id: SourceHeaderIdOf, + nonces: RangeInclusive, + ) -> Result { + Ok(nonces.map(|nonce| (nonce, 1)).collect()) + } + async fn prove_messages( &self, id: SourceHeaderIdOf, - nonces: RangeInclusive, - include_outbound_lane_state: bool, + nonces: RangeInclusive, + proof_parameters: MessageProofParameters, ) -> Result< ( SourceHeaderIdOf, - RangeInclusive, + RangeInclusive, TestMessagesProof, ), Self::Error, @@ -557,7 +593,7 @@ pub(crate) mod tests { nonces.clone(), ( nonces, - if include_outbound_lane_state { + if proof_parameters.outbound_state_proof_required { Some(data.source_latest_confirmed_received_nonce) } else { None @@ -610,7 +646,7 @@ pub(crate) mod tests { async fn latest_received_nonce( &self, id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, TestMessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf, MessageNonce), Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { @@ -622,7 +658,7 @@ pub(crate) mod tests { async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, TestMessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf, MessageNonce), Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { @@ -641,9 +677,9 @@ pub(crate) mod tests { async fn submit_messages_proof( &self, _generated_at_header: SourceHeaderIdOf, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: TestMessagesProof, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { @@ -683,8 +719,11 @@ pub(crate) mod tests { source_tick: Duration::from_millis(100), target_tick: Duration::from_millis(100), reconnect_delay: Duration::from_millis(0), - stall_timeout: Duration::from_millis(60), - max_unconfirmed_nonces_at_target: 100, + stall_timeout: Duration::from_millis(60 * 1000), + delivery_params: MessageDeliveryParams { + max_unconfirmed_nonces_at_target: 4, + max_messages_weight_in_single_batch: 4, + }, }, source_client, target_client, @@ -743,8 +782,6 @@ pub(crate) mod tests { #[test] fn message_lane_loop_works() { - // with this configuration, target client must first sync headers [1; 10] and - // then submit proof-of-messages [0; 10] at once let (exit_sender, exit_receiver) = unbounded(); let result = run_loop_test( TestClientData { @@ -762,18 +799,22 @@ pub(crate) mod tests { }, Arc::new(|_: &mut TestClientData| {}), Arc::new(move |data: &mut TestClientData| { - // syncing source headers -> target chain (by one) + // syncing source headers -> target chain (all at once) if data.target_state.best_peer.0 < data.source_state.best_self.0 { - data.target_state.best_peer = - HeaderId(data.target_state.best_peer.0 + 1, data.target_state.best_peer.0 + 1); + data.target_state.best_peer = data.source_state.best_self; } - // syncing source headers -> target chain (all at once) + // syncing target headers -> source chain (all at once) if data.source_state.best_peer.0 < data.target_state.best_self.0 { data.source_state.best_peer = data.target_state.best_self; } - // if target has received all messages => increase target block so that confirmations may be sent - if data.target_latest_received_nonce == 10 { + // if target has received messages batch => increase blocks so that confirmations may be sent + if data.target_latest_received_nonce == 4 + || data.target_latest_received_nonce == 8 + || data.target_latest_received_nonce == 10 + { data.target_state.best_self = + HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.0 + 1); + data.source_state.best_self = HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.0 + 1); } // if source has received all messages receiving confirmations => increase source block so that confirmations may be sent diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 90345f8c61571..370567542cc75 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -15,21 +15,21 @@ use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_lane_loop::{ - SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, - TargetClientState, + MessageDeliveryParams, MessageProofParameters, MessageWeightsMap, SourceClient as MessageLaneSourceClient, + SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, +}; +use crate::message_race_loop::{ + MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient, + TargetClientNonces, }; -use crate::message_race_loop::{ClientNonces, MessageRace, RaceState, RaceStrategy, SourceClient, TargetClient}; use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; +use bp_message_lane::{MessageNonce, Weight}; use futures::stream::FusedStream; -use num_traits::CheckedSub; use relay_utils::FailedClient; -use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; - -/// Maximal number of messages to relay in single transaction. -const MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX: u32 = 4; +use std::{collections::BTreeMap, marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Run message delivery race. pub async fn run( @@ -39,7 +39,7 @@ pub async fn run( target_state_updates: impl FusedStream>, stall_timeout: Duration, metrics_msg: Option, - max_unconfirmed_nonces_at_target: P::MessageNonce, + params: MessageDeliveryParams, ) -> Result<(), FailedClient> { crate::message_race_loop::run( MessageDeliveryRaceSource { @@ -56,10 +56,11 @@ pub async fn run( target_state_updates, stall_timeout, MessageDeliveryStrategy::

{ - max_unconfirmed_nonces_at_target, - source_nonces: None, + max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, + max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, + latest_confirmed_nonce_at_source: None, target_nonces: None, - strategy: BasicStrategy::new(MAX_MESSAGES_TO_RELAY_IN_SINGLE_TX.into()), + strategy: BasicStrategy::new(), }, ) .await @@ -72,7 +73,7 @@ impl MessageRace for MessageDeliveryRace

{ type SourceHeaderId = SourceHeaderIdOf

; type TargetHeaderId = TargetHeaderIdOf

; - type MessageNonce = P::MessageNonce; + type MessageNonce = MessageNonce; type Proof = P::MessagesProof; fn source_name() -> String { @@ -98,12 +99,14 @@ where C: MessageLaneSourceClient

, { type Error = C::Error; - type ProofParameters = bool; + type NoncesRange = MessageWeightsMap; + type ProofParameters = MessageProofParameters; async fn nonces( &self, at_block: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, ClientNonces), Self::Error> { + prev_latest_nonce: MessageNonce, + ) -> Result<(SourceHeaderIdOf

, SourceClientNonces), Self::Error> { let (at_block, latest_generated_nonce) = self.client.latest_generated_nonce(at_block).await?; let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; @@ -112,10 +115,18 @@ where metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); } + let new_nonces = if latest_generated_nonce > prev_latest_nonce { + self.client + .generated_messages_weights(at_block.clone(), prev_latest_nonce + 1..=latest_generated_nonce) + .await? + } else { + MessageWeightsMap::new() + }; + Ok(( at_block, - ClientNonces { - latest_nonce: latest_generated_nonce, + SourceClientNonces { + new_nonces, confirmed_nonce: Some(latest_confirmed_nonce), }, )) @@ -124,13 +135,10 @@ where async fn generate_proof( &self, at_block: SourceHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, proof_parameters: Self::ProofParameters, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { - let outbound_state_proof_required = proof_parameters; - self.client - .prove_messages(at_block, nonces, outbound_state_proof_required) - .await + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { + self.client.prove_messages(at_block, nonces, proof_parameters).await } } @@ -152,7 +160,7 @@ where async fn nonces( &self, at_block: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, ClientNonces), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> { let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; @@ -163,7 +171,7 @@ where Ok(( at_block, - ClientNonces { + TargetClientNonces { latest_nonce: latest_received_nonce, confirmed_nonce: Some(latest_confirmed_nonce), }, @@ -173,9 +181,9 @@ where async fn submit_proof( &self, generated_at_block: SourceHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::MessagesProof, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.client .submit_messages_proof(generated_at_block, nonces, proof) .await @@ -185,11 +193,13 @@ where /// Messages delivery strategy. struct MessageDeliveryStrategy { /// Maximal unconfirmed nonces at target client. - max_unconfirmed_nonces_at_target: P::MessageNonce, - /// Latest nonces from the source client. - source_nonces: Option>, + max_unconfirmed_nonces_at_target: MessageNonce, + /// Maximal cumulative messages weight in the single delivery transaction. + max_messages_weight_in_single_batch: Weight, + /// Latest confirmed nonce at the source client. + latest_confirmed_nonce_at_source: Option, /// Target nonces from the source client. - target_nonces: Option>, + target_nonces: Option, /// Basic delivery strategy. strategy: MessageDeliveryStrategyBase

, } @@ -199,36 +209,41 @@ type MessageDeliveryStrategyBase

= BasicStrategy<

::SourceHeaderHash,

::TargetHeaderNumber,

::TargetHeaderHash, -

::MessageNonce, + MessageWeightsMap,

::MessagesProof, >; -impl RaceStrategy, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof> +impl RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> for MessageDeliveryStrategy

{ - type ProofParameters = bool; + type SourceNoncesRange = MessageWeightsMap; + type ProofParameters = MessageProofParameters; fn is_empty(&self) -> bool { self.strategy.is_empty() } - fn best_at_source(&self) -> P::MessageNonce { + fn best_at_source(&self) -> MessageNonce { self.strategy.best_at_source() } - fn best_at_target(&self) -> P::MessageNonce { + fn best_at_target(&self) -> MessageNonce { self.strategy.best_at_target() } - fn source_nonces_updated(&mut self, at_block: SourceHeaderIdOf

, nonces: ClientNonces) { - self.source_nonces = Some(nonces.clone()); + fn source_nonces_updated( + &mut self, + at_block: SourceHeaderIdOf

, + nonces: SourceClientNonces, + ) { + self.latest_confirmed_nonce_at_source = nonces.confirmed_nonce; self.strategy.source_nonces_updated(at_block, nonces) } fn target_nonces_updated( &mut self, - nonces: ClientNonces, - race_state: &mut RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, + nonces: TargetClientNonces, + race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) { self.target_nonces = Some(nonces.clone()); self.strategy.target_nonces_updated(nonces, race_state) @@ -236,14 +251,14 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M fn select_nonces_to_deliver( &mut self, - race_state: &RaceState, TargetHeaderIdOf

, P::MessageNonce, P::MessagesProof>, - ) -> Option<(RangeInclusive, Self::ProofParameters)> { + race_state: &RaceState, TargetHeaderIdOf

, P::MessagesProof>, + ) -> Option<(RangeInclusive, Self::ProofParameters)> { const CONFIRMED_NONCE_PROOF: &str = "\ ClientNonces are crafted by MessageDeliveryRace(Source|Target);\ MessageDeliveryRace(Source|Target) always fills confirmed_nonce field;\ qed"; - let source_nonces = self.source_nonces.as_ref()?; + let latest_confirmed_nonce_at_source = self.latest_confirmed_nonce_at_source?; let target_nonces = self.target_nonces.as_ref()?; // There's additional condition in the message delivery race: target would reject messages @@ -257,10 +272,9 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M // The receiving race is responsible to deliver confirmations back to the source chain. So if // there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. let latest_received_nonce_at_target = target_nonces.latest_nonce; - let latest_confirmed_nonce_at_source = source_nonces.confirmed_nonce.expect(CONFIRMED_NONCE_PROOF); - let confirmations_missing = latest_received_nonce_at_target.checked_sub(&latest_confirmed_nonce_at_source); + let confirmations_missing = latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); match confirmations_missing { - Some(confirmations_missing) if confirmations_missing > self.max_unconfirmed_nonces_at_target => { + Some(confirmations_missing) if confirmations_missing >= self.max_unconfirmed_nonces_at_target => { log::debug!( target: "bridge", "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ @@ -277,11 +291,7 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M _ => (), } - // If we're here, then the confirmations race did it job && sending side now knows that messages - // have been delivered. Now let's select nonces that we want to deliver. - let selected_nonces = self.strategy.select_nonces_to_deliver(race_state)?.0; - - // Ok - we have new nonces to deliver. But target may still reject new messages, because we haven't + // Ok - we may have new nonces to deliver. But target may still reject new messages, because we haven't // notified it that (some) messages have been confirmed. So we may want to include updated // `source.latest_confirmed` in the proof. // @@ -290,11 +300,226 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M let latest_confirmed_nonce_at_target = target_nonces.confirmed_nonce.expect(CONFIRMED_NONCE_PROOF); let outbound_state_proof_required = latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; - // https://github.com/paritytech/parity-bridges-common/issues/432 - // https://github.com/paritytech/parity-bridges-common/issues/433 - // TODO: number of messages must be no larger than: - // `max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_target)` + // If we're here, then the confirmations race did its job && sending side now knows that messages + // have been delivered. Now let's select nonces that we want to deliver. + // + // We may deliver at most: + // + // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_target) + // + // messages in the batch. But since we're including outbound state proof in the batch, then it + // may be increased to: + // + // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_source) + let future_confirmed_nonce_at_target = if outbound_state_proof_required { + latest_confirmed_nonce_at_source + } else { + latest_confirmed_nonce_at_target + }; + let max_nonces = latest_received_nonce_at_target + .checked_sub(future_confirmed_nonce_at_target) + .and_then(|diff| self.max_unconfirmed_nonces_at_target.checked_sub(diff)) + .unwrap_or_default(); + let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; + let mut selected_weight: Weight = 0; + let mut selected_count: MessageNonce = 0; + + let selected_nonces = self + .strategy + .select_nonces_to_deliver_with_selector(race_state, |range| { + let to_requeue = range + .into_iter() + .skip_while(|(_, weight)| { + // limit messages in the batch by weight + let new_selected_weight = match selected_weight.checked_add(*weight) { + Some(new_selected_weight) if new_selected_weight <= max_messages_weight_in_single_batch => { + new_selected_weight + } + _ => return false, + }; + + // limit number of messages in the batch + let new_selected_count = selected_count + 1; + if new_selected_count > max_nonces { + return false; + } + + selected_weight = new_selected_weight; + selected_count = new_selected_count; + true + }) + .collect::>(); + if to_requeue.is_empty() { + None + } else { + Some(to_requeue) + } + })?; + + Some(( + selected_nonces, + MessageProofParameters { + outbound_state_proof_required, + dispatch_weight: selected_weight, + }, + )) + } +} + +impl NoncesRange for MessageWeightsMap { + fn begin(&self) -> MessageNonce { + self.keys().next().cloned().unwrap_or_default() + } + + fn end(&self) -> MessageNonce { + self.keys().next_back().cloned().unwrap_or_default() + } + + fn greater_than(mut self, nonce: MessageNonce) -> Option { + let gte = self.split_off(&(nonce + 1)); + if gte.is_empty() { + None + } else { + Some(gte) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::message_lane_loop::{ + tests::{header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderId, TestTargetHeaderId}, + ClientState, + }; + + type TestRaceState = RaceState; + type TestStrategy = MessageDeliveryStrategy; + + fn prepare_strategy() -> (TestRaceState, TestStrategy) { + let mut race_state = RaceState { + source_state: Some(ClientState { + best_self: header_id(1), + best_peer: header_id(1), + }), + target_state: Some(ClientState { + best_self: header_id(1), + best_peer: header_id(1), + }), + nonces_to_submit: None, + nonces_submitted: None, + }; + + let mut race_strategy = TestStrategy { + max_unconfirmed_nonces_at_target: 4, + max_messages_weight_in_single_batch: 4, + latest_confirmed_nonce_at_source: Some(19), + target_nonces: Some(TargetClientNonces { + latest_nonce: 19, + confirmed_nonce: Some(19), + }), + strategy: BasicStrategy::new(), + }; + + race_strategy.strategy.source_nonces_updated( + header_id(1), + SourceClientNonces { + new_nonces: vec![(20, 1), (21, 1), (22, 1), (23, 1)].into_iter().collect(), + confirmed_nonce: Some(19), + }, + ); + race_strategy + .strategy + .target_nonces_updated(race_strategy.target_nonces.clone().unwrap(), &mut race_state); + + (race_state, race_strategy) + } + + fn proof_parameters(state_required: bool, weight: Weight) -> MessageProofParameters { + MessageProofParameters { + outbound_state_proof_required: state_required, + dispatch_weight: weight, + } + } + + #[test] + fn weights_map_works_as_nonces_range() { + fn build_map(range: RangeInclusive) -> MessageWeightsMap { + range.map(|idx| (idx, idx)).collect() + } + + let map = build_map(20..=30); + + assert_eq!(map.begin(), 20); + assert_eq!(map.end(), 30); + assert_eq!(map.clone().greater_than(10), Some(build_map(20..=30))); + assert_eq!(map.clone().greater_than(19), Some(build_map(20..=30))); + assert_eq!(map.clone().greater_than(20), Some(build_map(21..=30))); + assert_eq!(map.clone().greater_than(25), Some(build_map(26..=30))); + assert_eq!(map.clone().greater_than(29), Some(build_map(30..=30))); + assert_eq!(map.greater_than(30), None); + } + + #[test] + fn message_delivery_strategy_selects_messages_to_deliver() { + let (state, mut strategy) = prepare_strategy(); + + // both sides are ready to relay new messages + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=23), proof_parameters(false, 4))) + ); + } + + #[test] + fn message_delivery_strategy_selects_nothing_if_too_many_confirmations_missing() { + let (state, mut strategy) = prepare_strategy(); + + // if there are already `max_unconfirmed_nonces_at_target` messages on target, + // we need to wait until confirmations will be delivered by receiving race + strategy.latest_confirmed_nonce_at_source = + Some(strategy.target_nonces.as_ref().unwrap().latest_nonce - strategy.max_unconfirmed_nonces_at_target); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() { + let (state, mut strategy) = prepare_strategy(); + + // if there are new confirmed nonces on source, we want to relay this information + // to target to prune rewards queue + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + strategy.target_nonces.as_mut().unwrap().confirmed_nonce = Some(prev_confirmed_nonce_at_source - 1); + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=23), proof_parameters(true, 4))) + ); + } + + #[test] + fn message_delivery_strategy_limits_batch_by_messages_weight() { + let (state, mut strategy) = prepare_strategy(); + + // not all queued messages may fit in the batch, because batch has max weight + strategy.max_messages_weight_in_single_batch = 3; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=22), proof_parameters(false, 3))) + ); + } - Some((selected_nonces, outbound_state_proof_required)) + #[test] + fn message_delivery_strategy_limits_batch_by_messages_count() { + let (state, mut strategy) = prepare_strategy(); + + // 1 delivery confirmation from target to source is still missing, so we may only + // relay 3 new messages + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + strategy.latest_confirmed_nonce_at_source = Some(prev_confirmed_nonce_at_source - 1); + strategy.target_nonces.as_mut().unwrap().confirmed_nonce = Some(prev_confirmed_nonce_at_source - 1); + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=22), proof_parameters(false, 3))) + ); } } diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 43a2cd9ad275b..8fa8d5ffba36a 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -23,6 +23,7 @@ use crate::message_lane_loop::ClientState; use async_trait::async_trait; +use bp_message_lane::MessageNonce; use futures::{ future::FutureExt, stream::{FusedStream, StreamExt}, @@ -58,10 +59,32 @@ type SourceClientState

= ClientState<

::SourceHeaderId,

= ClientState<

::TargetHeaderId,

::SourceHeaderId>; -/// Nonces on the race client. +/// Inclusive nonces range. +pub trait NoncesRange: Debug + Sized { + /// Get begin of the range. + fn begin(&self) -> MessageNonce; + /// Get end of the range. + fn end(&self) -> MessageNonce; + /// Returns new range with current range nonces that are greater than the passed `nonce`. + /// If there are no such nonces, `None` is returned. + fn greater_than(self, nonce: MessageNonce) -> Option; +} + +/// Nonces on the race source client. #[derive(Debug, Clone)] -pub struct ClientNonces { - /// Latest nonce that is known to the client. +pub struct SourceClientNonces { + /// New nonces range known to the client. `New` here means all nonces generated after + /// `prev_latest_nonce` passed to the `SourceClient::nonces` method. + pub new_nonces: NoncesRange, + /// Latest nonce that is confirmed to the bridged client. This nonce only makes + /// sense in some races. In other races it is `None`. + pub confirmed_nonce: Option, +} + +/// Nonces on the race target client. +#[derive(Debug, Clone)] +pub struct TargetClientNonces { + /// Latest nonce that is known to the target client. pub latest_nonce: MessageNonce, /// Latest nonce that is confirmed to the bridged client. This nonce only makes /// sense in some races. In other races it is `None`. @@ -73,6 +96,8 @@ pub struct ClientNonces { pub trait SourceClient { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; + /// Type of nonces range returned by the source client. + type NoncesRange: NoncesRange; /// Additional proof parameters required to generate proof. type ProofParameters; @@ -80,14 +105,15 @@ pub trait SourceClient { async fn nonces( &self, at_block: P::SourceHeaderId, - ) -> Result<(P::SourceHeaderId, ClientNonces), Self::Error>; + prev_latest_nonce: MessageNonce, + ) -> Result<(P::SourceHeaderId, SourceClientNonces), Self::Error>; /// Generate proof for delivering to the target client. async fn generate_proof( &self, at_block: P::SourceHeaderId, - nonces: RangeInclusive, + nonces: RangeInclusive, proof_parameters: Self::ProofParameters, - ) -> Result<(P::SourceHeaderId, RangeInclusive, P::Proof), Self::Error>; + ) -> Result<(P::SourceHeaderId, RangeInclusive, P::Proof), Self::Error>; } /// One of message lane clients, which is target client for the race. @@ -97,21 +123,21 @@ pub trait TargetClient { type Error: std::fmt::Debug + MaybeConnectionError; /// Return nonces that are known to the target client. - async fn nonces( - &self, - at_block: P::TargetHeaderId, - ) -> Result<(P::TargetHeaderId, ClientNonces), Self::Error>; + async fn nonces(&self, at_block: P::TargetHeaderId) + -> Result<(P::TargetHeaderId, TargetClientNonces), Self::Error>; /// Submit proof to the target client. async fn submit_proof( &self, generated_at_block: P::SourceHeaderId, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::Proof, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; } /// Race strategy. -pub trait RaceStrategy { +pub trait RaceStrategy { + /// Type of nonces range expected from the source client. + type SourceNoncesRange: NoncesRange; /// Additional proof parameters required to generate proof. type ProofParameters; @@ -123,25 +149,25 @@ pub trait RaceStrategy { fn best_at_target(&self) -> MessageNonce; /// Called when nonces are updated at source node of the race. - fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonce: ClientNonces); + fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonces: SourceClientNonces); /// Called when nonces are updated at target node of the race. fn target_nonces_updated( &mut self, - nonces: ClientNonces, - race_state: &mut RaceState, + nonces: TargetClientNonces, + race_state: &mut RaceState, ); /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated /// data) from source to target node. /// Additionally, parameters required to generate proof are returned. fn select_nonces_to_deliver( &mut self, - race_state: &RaceState, + race_state: &RaceState, ) -> Option<(RangeInclusive, Self::ProofParameters)>; } /// State of the race. #[derive(Debug)] -pub struct RaceState { +pub struct RaceState { /// Source state, if known. pub source_state: Option>, /// Target state, if known. @@ -162,8 +188,8 @@ pub async fn run>( mut strategy: impl RaceStrategy< P::SourceHeaderId, P::TargetHeaderId, - P::MessageNonce, P::Proof, + SourceNoncesRange = SC::NoncesRange, ProofParameters = SC::ProofParameters, >, ) -> Result<(), FailedClient> { @@ -337,7 +363,7 @@ pub async fn run>( .expect("source_nonces_required is only true when source_state is Some; qed") .best_self .clone(); - source_nonces.set(race_source.nonces(at_block).fuse()); + source_nonces.set(race_source.nonces(at_block, strategy.best_at_source()).fuse()); } else { source_client_is_online = true; } @@ -375,9 +401,7 @@ pub async fn run>( } } -impl Default - for RaceState -{ +impl Default for RaceState { fn default() -> Self { RaceState { source_state: None, @@ -392,7 +416,7 @@ impl Default fn print_race_progress(prev_time: Instant, strategy: &S) -> Instant where P: MessageRace, - S: RaceStrategy, + S: RaceStrategy, { let now_time = Instant::now(); @@ -414,13 +438,13 @@ where now_time } -fn select_nonces_to_deliver( - race_state: &RaceState, +fn select_nonces_to_deliver( + race_state: &RaceState, strategy: &mut Strategy, ) -> Option<(SourceHeaderId, RangeInclusive, Strategy::ProofParameters)> where SourceHeaderId: Clone, - Strategy: RaceStrategy, + Strategy: RaceStrategy, { race_state.target_state.as_ref().and_then(|target_state| { strategy @@ -442,8 +466,8 @@ mod tests { const BEST_AT_TARGET: u64 = 8; // target node only knows about source' BEST_AT_TARGET block - // source node has BEST_AT_SOURCE > BEST_AT_SOURCE block - let mut race_state = RaceState::<_, _, _, ()> { + // source node has BEST_AT_SOURCE > BEST_AT_TARGET block + let mut race_state = RaceState::<_, _, ()> { source_state: Some(ClientState { best_self: HeaderId(BEST_AT_SOURCE, BEST_AT_SOURCE), best_peer: HeaderId(0, 0), @@ -457,16 +481,16 @@ mod tests { }; // we have some nonces to deliver and they're generated at GENERATED_AT < BEST_AT_SOURCE - let mut strategy = BasicStrategy::new(100); + let mut strategy = BasicStrategy::new(); strategy.source_nonces_updated( HeaderId(GENERATED_AT, GENERATED_AT), - ClientNonces { - latest_nonce: 10u64, + SourceClientNonces { + new_nonces: 0..=10, confirmed_nonce: None, }, ); strategy.target_nonces_updated( - ClientNonces { + TargetClientNonces { latest_nonce: 5u64, confirmed_nonce: None, }, diff --git a/relays/messages-relay/src/message_race_receiving.rs b/relays/messages-relay/src/message_race_receiving.rs index bf9975717c319..852b2893f1a3b 100644 --- a/relays/messages-relay/src/message_race_receiving.rs +++ b/relays/messages-relay/src/message_race_receiving.rs @@ -18,11 +18,14 @@ use crate::message_lane_loop::{ SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }; -use crate::message_race_loop::{ClientNonces, MessageRace, SourceClient, TargetClient}; +use crate::message_race_loop::{ + MessageRace, NoncesRange, SourceClient, SourceClientNonces, TargetClient, TargetClientNonces, +}; use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; +use bp_message_lane::MessageNonce; use futures::stream::FusedStream; use relay_utils::FailedClient; use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; @@ -33,7 +36,7 @@ type ReceivingConfirmationsBasicStrategy

= BasicStrategy<

::TargetHeaderHash,

::SourceHeaderNumber,

::SourceHeaderHash, -

::MessageNonce, + RangeInclusive,

::MessagesReceivingProof, >; @@ -60,7 +63,7 @@ pub async fn run( }, source_state_updates, stall_timeout, - ReceivingConfirmationsBasicStrategy::

::new(std::u32::MAX.into()), + ReceivingConfirmationsBasicStrategy::

::new(), ) .await } @@ -72,7 +75,7 @@ impl MessageRace for ReceivingConfirmationsRace

{ type SourceHeaderId = TargetHeaderIdOf

; type TargetHeaderId = SourceHeaderIdOf

; - type MessageNonce = P::MessageNonce; + type MessageNonce = MessageNonce; type Proof = P::MessagesReceivingProof; fn source_name() -> String { @@ -98,20 +101,22 @@ where C: MessageLaneTargetClient

, { type Error = C::Error; + type NoncesRange = RangeInclusive; type ProofParameters = (); async fn nonces( &self, at_block: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, ClientNonces), Self::Error> { + prev_latest_nonce: MessageNonce, + ) -> Result<(TargetHeaderIdOf

, SourceClientNonces), Self::Error> { let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); } Ok(( at_block, - ClientNonces { - latest_nonce: latest_received_nonce, + SourceClientNonces { + new_nonces: prev_latest_nonce + 1..=latest_received_nonce, confirmed_nonce: None, }, )) @@ -121,12 +126,12 @@ where async fn generate_proof( &self, at_block: TargetHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, _proof_parameters: Self::ProofParameters, ) -> Result< ( TargetHeaderIdOf

, - RangeInclusive, + RangeInclusive, P::MessagesReceivingProof, ), Self::Error, @@ -156,14 +161,14 @@ where async fn nonces( &self, at_block: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, ClientNonces), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, TargetClientNonces), Self::Error> { let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); } Ok(( at_block, - ClientNonces { + TargetClientNonces { latest_nonce: latest_confirmed_nonce, confirmed_nonce: None, }, @@ -173,12 +178,51 @@ where async fn submit_proof( &self, generated_at_block: TargetHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::MessagesReceivingProof, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.client .submit_messages_receiving_proof(generated_at_block, proof) .await?; Ok(nonces) } } + +impl NoncesRange for RangeInclusive { + fn begin(&self) -> MessageNonce { + *RangeInclusive::::start(self) + } + + fn end(&self) -> MessageNonce { + *RangeInclusive::::end(self) + } + + fn greater_than(self, nonce: MessageNonce) -> Option { + let next_nonce = nonce + 1; + let end = *self.end(); + if next_nonce > end { + None + } else { + Some(std::cmp::max(self.begin(), next_nonce)..=end) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn range_inclusive_works_as_nonces_range() { + let range = 20..=30; + + assert_eq!(NoncesRange::begin(&range), 20); + assert_eq!(NoncesRange::end(&range), 30); + assert_eq!(range.clone().greater_than(10), Some(20..=30)); + assert_eq!(range.clone().greater_than(19), Some(20..=30)); + assert_eq!(range.clone().greater_than(20), Some(21..=30)); + assert_eq!(range.clone().greater_than(25), Some(26..=30)); + assert_eq!(range.clone().greater_than(29), Some(30..=30)); + assert_eq!(range.greater_than(30), None); + } +} diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index 4aabf6c200afd..83b139f0f3e2e 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -17,95 +17,172 @@ //! 2) new nonces may be proved to target node (i.e. they have appeared at the //! block, which is known to the target node). -use crate::message_race_loop::{ClientNonces, RaceState, RaceStrategy}; +use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces}; -use num_traits::{One, Zero}; +use bp_message_lane::MessageNonce; use relay_utils::HeaderId; use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Nonces delivery strategy. #[derive(Debug)] -pub struct BasicStrategy { +pub struct BasicStrategy< + SourceHeaderNumber, + SourceHeaderHash, + TargetHeaderNumber, + TargetHeaderHash, + SourceNoncesRange, + Proof, +> { /// All queued nonces. - source_queue: VecDeque<(HeaderId, Nonce)>, + source_queue: VecDeque<(HeaderId, SourceNoncesRange)>, /// Best nonce known to target node. - target_nonce: Nonce, - /// Max nonces to relay in single transaction. - max_nonces_to_relay_in_single_tx: Nonce, + target_nonce: MessageNonce, /// Unused generic types dump. _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, } -impl - BasicStrategy +impl + BasicStrategy +where + SourceHeaderHash: Clone, + SourceHeaderNumber: Clone + Ord, + SourceNoncesRange: NoncesRange, { /// Create new delivery strategy. - pub fn new(max_nonces_to_relay_in_single_tx: Nonce) -> Self { + pub fn new() -> Self { BasicStrategy { source_queue: VecDeque::new(), target_nonce: Default::default(), - max_nonces_to_relay_in_single_tx, _phantom: Default::default(), } } + + /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated + /// data) from source to target node. + /// + /// The `selector` function receives range of nonces and should return `None` if the whole + /// range needs to be delivered. If there are some nonces in the range that can't be delivered + /// right now, it should return `Some` with 'undeliverable' nonces. Please keep in mind that + /// this should be the sub-range that the passed range ends with, because nonces are always + /// delivered in-order. Otherwise the function will panic. + pub fn select_nonces_to_deliver_with_selector( + &mut self, + race_state: &RaceState< + HeaderId, + HeaderId, + Proof, + >, + mut selector: impl FnMut(SourceNoncesRange) -> Option, + ) -> Option> { + // if we have already selected nonces that we want to submit, do nothing + if race_state.nonces_to_submit.is_some() { + return None; + } + + // if we already submitted some nonces, do nothing + if race_state.nonces_submitted.is_some() { + return None; + } + + // 1) we want to deliver all nonces, starting from `target_nonce + 1` + // 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized + // by target client + // 3) selector is used for more complicated logic + let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; + let mut nonces_end = None; + + while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { + // select (sub) range to deliver + let queued_range_begin = queued_range.begin(); + let queued_range_end = queued_range.end(); + let range_to_requeue = if queued_at.0 > best_header_at_target.0 { + // if header that has queued the range is not yet finalized at bridged chain, + // we can't prove anything + Some(queued_range) + } else { + // selector returns `Some(range)` if this `range` needs to be requeued + selector(queued_range) + }; + + // requeue (sub) range and update range to deliver + match range_to_requeue { + Some(range_to_requeue) => { + assert!( + range_to_requeue.begin() <= range_to_requeue.end() + && range_to_requeue.begin() >= queued_range_begin + && range_to_requeue.end() == queued_range_end, + "Incorrect implementation of internal `selector` function. Expected original\ + range {:?} to end with returned range {:?}", + queued_range_begin..=queued_range_end, + range_to_requeue, + ); + + if range_to_requeue.begin() != queued_range_begin { + nonces_end = Some(range_to_requeue.begin() - 1); + } + self.source_queue.push_front((queued_at, range_to_requeue)); + break; + } + None => { + nonces_end = Some(queued_range_end); + } + } + } + + nonces_end.map(|nonces_end| RangeInclusive::new(self.target_nonce + 1, nonces_end)) + } } -impl - RaceStrategy< - HeaderId, - HeaderId, - Nonce, - Proof, - > for BasicStrategy +impl + RaceStrategy, HeaderId, Proof> + for BasicStrategy where SourceHeaderHash: Clone, SourceHeaderNumber: Clone + Ord, - Nonce: Clone + Copy + From + Ord + std::ops::Add + One + Zero, + SourceNoncesRange: NoncesRange, { + type SourceNoncesRange = SourceNoncesRange; type ProofParameters = (); fn is_empty(&self) -> bool { self.source_queue.is_empty() } - fn best_at_source(&self) -> Nonce { - self.source_queue - .back() - .map(|(_, nonce)| *nonce) - .unwrap_or_else(Zero::zero) + fn best_at_source(&self) -> MessageNonce { + std::cmp::max( + self.source_queue + .back() + .map(|(_, range)| range.end()) + .unwrap_or(self.target_nonce), + self.target_nonce, + ) } - fn best_at_target(&self) -> Nonce { + fn best_at_target(&self) -> MessageNonce { self.target_nonce } fn source_nonces_updated( &mut self, at_block: HeaderId, - nonces: ClientNonces, + nonces: SourceClientNonces, ) { - let nonce = nonces.latest_nonce; - - if nonce <= self.target_nonce { - return; - } - - match self.source_queue.back() { - Some((_, prev_nonce)) if *prev_nonce < nonce => (), - Some(_) => return, - None => (), - } - - self.source_queue.push_back((at_block, nonce)) + let prev_best_at_source = self.best_at_source(); + self.source_queue.extend( + nonces + .new_nonces + .greater_than(prev_best_at_source) + .into_iter() + .map(move |range| (at_block.clone(), range)), + ) } fn target_nonces_updated( &mut self, - nonces: ClientNonces, + nonces: TargetClientNonces, race_state: &mut RaceState< HeaderId, HeaderId, - Nonce, Proof, >, ) { @@ -115,12 +192,15 @@ where return; } - while let Some(true) = self - .source_queue - .front() - .map(|(_, source_nonce)| *source_nonce <= nonce) - { - self.source_queue.pop_front(); + while let Some(true) = self.source_queue.front().map(|(_, range)| range.begin() <= nonce) { + let maybe_subrange = self + .source_queue + .pop_front() + .and_then(|(at_block, range)| range.greater_than(nonce).map(|subrange| (at_block, subrange))); + if let Some((at_block, subrange)) = maybe_subrange { + self.source_queue.push_front((at_block, subrange)); + break; + } } let need_to_select_new_nonces = race_state @@ -149,60 +229,11 @@ where race_state: &RaceState< HeaderId, HeaderId, - Nonce, Proof, >, - ) -> Option<(RangeInclusive, Self::ProofParameters)> { - // if we have already selected nonces that we want to submit, do nothing - if race_state.nonces_to_submit.is_some() { - return None; - } - - // if we already submitted some nonces, do nothing - if race_state.nonces_submitted.is_some() { - return None; - } - - // 1) we want to deliver all nonces, starting from `target_nonce + 1` - // 2) we want to deliver at most `self.max_nonces_to_relay_in_single_tx` nonces in this batch - // 3) we can't deliver new nonce until header, that has emitted this nonce, is finalized - // by target client - let nonces_begin = self.target_nonce + 1.into(); - let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; - let mut nonces_end = None; - let mut i = Zero::zero(); - - // https://github.com/paritytech/parity-bridges-common/issues/433 - // TODO: instead of limiting number of messages by number, provide custom limit callback here. - // In delivery race it'll be weight-based callback. In receiving race it'll be unlimited callback. - - while i < self.max_nonces_to_relay_in_single_tx { - let nonce = nonces_begin + i; - - // if queue is empty, we don't need to prove anything - let (first_queued_at, first_queued_nonce) = match self.source_queue.front() { - Some((first_queued_at, first_queued_nonce)) => ((*first_queued_at).clone(), *first_queued_nonce), - None => break, - }; - - // if header that has queued the message is not yet finalized at bridged chain, - // we can't prove anything - if first_queued_at.0 > best_header_at_target.0 { - break; - } - - // ok, we may deliver this nonce - nonces_end = Some(nonce); - - // probably remove it from the queue? - if nonce == first_queued_nonce { - self.source_queue.pop_front(); - } - - i = i + One::one(); - } - - nonces_end.map(|nonces_end| (RangeInclusive::new(nonces_begin, nonces_end), ())) + ) -> Option<(RangeInclusive, Self::ProofParameters)> { + self.select_nonces_to_deliver_with_selector(race_state, |_| None) + .map(|range| (range, ())) } } @@ -211,21 +242,30 @@ mod tests { use super::*; use crate::message_lane::MessageLane; use crate::message_lane_loop::{ - tests::{header_id, TestMessageLane, TestMessageNonce, TestMessagesProof}, + tests::{header_id, TestMessageLane, TestMessagesProof}, ClientState, }; + type SourceNoncesRange = RangeInclusive; + type BasicStrategy

= super::BasicStrategy<

::SourceHeaderNumber,

::SourceHeaderHash,

::TargetHeaderNumber,

::TargetHeaderHash, -

::MessageNonce, + SourceNoncesRange,

::MessagesProof, >; - fn nonces(latest_nonce: TestMessageNonce) -> ClientNonces { - ClientNonces { + fn source_nonces(new_nonces: SourceNoncesRange) -> SourceClientNonces { + SourceClientNonces { + new_nonces, + confirmed_nonce: None, + } + } + + fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces { + TargetClientNonces { latest_nonce, confirmed_nonce: None, } @@ -233,105 +273,116 @@ mod tests { #[test] fn strategy_is_empty_works() { - let mut strategy = BasicStrategy::::new(4); + let mut strategy = BasicStrategy::::new(); assert_eq!(strategy.is_empty(), true); - strategy.source_nonces_updated(header_id(1), nonces(1)); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); assert_eq!(strategy.is_empty(), false); } + #[test] + fn best_at_source_is_never_lower_than_target_nonce() { + let mut strategy = BasicStrategy::::new(); + assert_eq!(strategy.best_at_source(), 0); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); + assert_eq!(strategy.best_at_source(), 5); + strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); + assert_eq!(strategy.source_queue, vec![]); + assert_eq!(strategy.best_at_source(), 10); + } + #[test] fn source_nonce_is_never_lower_than_known_target_nonce() { - let mut strategy = BasicStrategy::::new(4); - strategy.target_nonces_updated(nonces(10), &mut Default::default()); - strategy.source_nonces_updated(header_id(1), nonces(5)); + let mut strategy = BasicStrategy::::new(); + strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); assert_eq!(strategy.source_queue, vec![]); } #[test] fn source_nonce_is_never_lower_than_latest_known_source_nonce() { - let mut strategy = BasicStrategy::::new(4); - strategy.source_nonces_updated(header_id(1), nonces(5)); - strategy.source_nonces_updated(header_id(2), nonces(3)); - strategy.source_nonces_updated(header_id(2), nonces(5)); - assert_eq!(strategy.source_queue, vec![(header_id(1), 5)]); + let mut strategy = BasicStrategy::::new(); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); + strategy.source_nonces_updated(header_id(2), source_nonces(1..=3)); + strategy.source_nonces_updated(header_id(2), source_nonces(1..=5)); + assert_eq!(strategy.source_queue, vec![(header_id(1), 1..=5)]); } #[test] fn target_nonce_is_never_lower_than_latest_known_target_nonce() { - let mut strategy = BasicStrategy::::new(4); - strategy.target_nonces_updated(nonces(10), &mut Default::default()); - strategy.target_nonces_updated(nonces(5), &mut Default::default()); + let mut strategy = BasicStrategy::::new(); + strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); + strategy.target_nonces_updated(target_nonces(5), &mut Default::default()); assert_eq!(strategy.target_nonce, 10); } #[test] fn updated_target_nonce_removes_queued_entries() { - let mut strategy = BasicStrategy::::new(4); - strategy.source_nonces_updated(header_id(1), nonces(5)); - strategy.source_nonces_updated(header_id(2), nonces(10)); - strategy.source_nonces_updated(header_id(3), nonces(15)); - strategy.source_nonces_updated(header_id(4), nonces(20)); - strategy.target_nonces_updated(nonces(15), &mut Default::default()); - assert_eq!(strategy.source_queue, vec![(header_id(4), 20)]); + let mut strategy = BasicStrategy::::new(); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); + strategy.source_nonces_updated(header_id(2), source_nonces(6..=10)); + strategy.source_nonces_updated(header_id(3), source_nonces(11..=15)); + strategy.source_nonces_updated(header_id(4), source_nonces(16..=20)); + strategy.target_nonces_updated(target_nonces(15), &mut Default::default()); + assert_eq!(strategy.source_queue, vec![(header_id(4), 16..=20)]); + strategy.target_nonces_updated(target_nonces(17), &mut Default::default()); + assert_eq!(strategy.source_queue, vec![(header_id(4), 18..=20)]); } #[test] fn selected_nonces_are_dropped_on_target_nonce_update() { let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(4); + let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); - strategy.target_nonces_updated(nonces(7), &mut state); + strategy.target_nonces_updated(target_nonces(7), &mut state); assert!(state.nonces_to_submit.is_some()); - strategy.target_nonces_updated(nonces(10), &mut state); + strategy.target_nonces_updated(target_nonces(10), &mut state); assert!(state.nonces_to_submit.is_none()); } #[test] fn submitted_nonces_are_dropped_on_target_nonce_update() { let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(4); + let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(5..=10); - strategy.target_nonces_updated(nonces(7), &mut state); + strategy.target_nonces_updated(target_nonces(7), &mut state); assert!(state.nonces_submitted.is_some()); - strategy.target_nonces_updated(nonces(10), &mut state); + strategy.target_nonces_updated(target_nonces(10), &mut state); assert!(state.nonces_submitted.is_none()); } #[test] fn nothing_is_selected_if_something_is_already_selected() { let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(4); + let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); - strategy.source_nonces_updated(header_id(1), nonces(10)); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } #[test] fn nothing_is_selected_if_something_is_already_submitted() { let mut state = RaceState::default(); - let mut strategy = BasicStrategy::::new(4); + let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(1..=10); - strategy.source_nonces_updated(header_id(1), nonces(10)); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } #[test] fn select_nonces_to_deliver_works() { - let mut state = RaceState::<_, _, TestMessageNonce, TestMessagesProof>::default(); - let mut strategy = BasicStrategy::::new(4); - strategy.source_nonces_updated(header_id(1), nonces(1)); - strategy.source_nonces_updated(header_id(2), nonces(2)); - strategy.source_nonces_updated(header_id(3), nonces(6)); - strategy.source_nonces_updated(header_id(5), nonces(8)); + let mut state = RaceState::<_, _, TestMessagesProof>::default(); + let mut strategy = BasicStrategy::::new(); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); + strategy.source_nonces_updated(header_id(2), source_nonces(2..=2)); + strategy.source_nonces_updated(header_id(3), source_nonces(6..=6)); + strategy.source_nonces_updated(header_id(5), source_nonces(8..=8)); state.target_state = Some(ClientState { best_self: header_id(0), best_peer: header_id(4), }); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some((1..=4, ()))); - strategy.target_nonces_updated(nonces(4), &mut state); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some((5..=6, ()))); - strategy.target_nonces_updated(nonces(6), &mut state); + assert_eq!(strategy.select_nonces_to_deliver(&state), Some((1..=6, ()))); + strategy.target_nonces_updated(target_nonces(6), &mut state); assert_eq!(strategy.select_nonces_to_deliver(&state), None); state.target_state = Some(ClientState { @@ -339,7 +390,57 @@ mod tests { best_peer: header_id(5), }); assert_eq!(strategy.select_nonces_to_deliver(&state), Some((7..=8, ()))); - strategy.target_nonces_updated(nonces(8), &mut state); + strategy.target_nonces_updated(target_nonces(8), &mut state); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } + + #[test] + fn select_nonces_to_deliver_able_to_split_ranges_with_selector() { + let mut state = RaceState::<_, _, TestMessagesProof>::default(); + let mut strategy = BasicStrategy::::new(); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); + + state.target_state = Some(ClientState { + best_self: header_id(0), + best_peer: header_id(1), + }); + assert_eq!( + strategy.select_nonces_to_deliver_with_selector(&state, |_| Some(50..=100)), + Some(1..=49), + ); + } + + fn run_panic_test_for_incorrect_selector( + invalid_selector: impl Fn(SourceNoncesRange) -> Option, + ) { + let mut state = RaceState::<_, _, TestMessagesProof>::default(); + let mut strategy = BasicStrategy::::new(); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); + strategy.target_nonces_updated(target_nonces(50), &mut state); + state.target_state = Some(ClientState { + best_self: header_id(0), + best_peer: header_id(1), + }); + + strategy.select_nonces_to_deliver_with_selector(&state, invalid_selector); + } + + #[test] + #[should_panic] + fn select_nonces_to_deliver_panics_if_selector_returns_empty_range() { + #[allow(clippy::reversed_empty_ranges)] + run_panic_test_for_incorrect_selector(|_| Some(2..=1)) + } + + #[test] + #[should_panic] + fn select_nonces_to_deliver_panics_if_selector_returns_range_that_starts_before_passed_range() { + run_panic_test_for_incorrect_selector(|range| Some(range.begin() - 1..=*range.end())) + } + + #[test] + #[should_panic] + fn select_nonces_to_deliver_panics_if_selector_returns_range_with_mismatched_end() { + run_panic_test_for_incorrect_selector(|range| Some(range.begin()..=*range.end() + 1)) + } } diff --git a/relays/messages-relay/src/metrics.rs b/relays/messages-relay/src/metrics.rs index 93f4259c106ea..462317028c15d 100644 --- a/relays/messages-relay/src/metrics.rs +++ b/relays/messages-relay/src/metrics.rs @@ -19,6 +19,7 @@ use crate::message_lane::MessageLane; use crate::message_lane_loop::{SourceClientState, TargetClientState}; +use bp_message_lane::MessageNonce; use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; /// Message lane relay metrics. @@ -77,30 +78,30 @@ impl MessageLaneLoopMetrics { } /// Update latest generated nonce at source. - pub fn update_source_latest_generated_nonce(&self, source_latest_generated_nonce: P::MessageNonce) { + pub fn update_source_latest_generated_nonce(&self, source_latest_generated_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["source_latest_generated"]) - .set(source_latest_generated_nonce.into()); + .set(source_latest_generated_nonce); } /// Update latest confirmed nonce at source. - pub fn update_source_latest_confirmed_nonce(&self, source_latest_confirmed_nonce: P::MessageNonce) { + pub fn update_source_latest_confirmed_nonce(&self, source_latest_confirmed_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["source_latest_confirmed"]) - .set(source_latest_confirmed_nonce.into()); + .set(source_latest_confirmed_nonce); } /// Update latest received nonce at target. - pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: P::MessageNonce) { + pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["target_latest_received"]) - .set(target_latest_generated_nonce.into()); + .set(target_latest_generated_nonce); } /// Update latest confirmed nonce at target. - pub fn update_target_latest_confirmed_nonce(&self, target_latest_confirmed_nonce: P::MessageNonce) { + pub fn update_target_latest_confirmed_nonce(&self, target_latest_confirmed_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["target_latest_confirmed"]) - .set(target_latest_confirmed_nonce.into()); + .set(target_latest_confirmed_nonce); } } diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 1e0075f228c43..e52af57cdd59e 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -23,7 +23,6 @@ use crate::{ConnectionParams, Error, Result}; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::Decode; -use frame_support::weights::Weight; use frame_system::AccountInfo; use jsonrpsee::common::DeserializeOwned; use jsonrpsee::raw::RawClient; @@ -215,8 +214,8 @@ impl Client { range: RangeInclusive, include_outbound_lane_state: bool, at_block: C::Hash, - ) -> Result<(Weight, StorageProof)> { - let (dispatch_weight, encoded_trie_nodes) = SubstrateMessageLane::::prove_messages( + ) -> Result { + let encoded_trie_nodes = SubstrateMessageLane::::prove_messages( &self.client, instance, lane, @@ -229,7 +228,7 @@ impl Client { .map_err(Error::Request)?; let decoded_trie_nodes: Vec> = Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; - Ok((dispatch_weight, StorageProof::new(decoded_trie_nodes))) + Ok(StorageProof::new(decoded_trie_nodes)) } /// Returns proof-of-message(s) delivery. diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index 5f41af9aacc33..bafcb1a1fec73 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -36,6 +36,8 @@ pub enum Error { ResponseParseFailed(codec::Error), /// Account does not exist on the chain. AccountDoesNotExist, + /// Custom logic error. + Custom(String), } impl From for Error { @@ -69,6 +71,7 @@ impl ToString for Error { Self::Request(e) => e.to_string(), Self::ResponseParseFailed(e) => e.what().to_string(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), + Self::Custom(e) => e.clone(), } } } diff --git a/relays/substrate-client/src/rpc.rs b/relays/substrate-client/src/rpc.rs index 89ed36695abcc..9c76f593e99b8 100644 --- a/relays/substrate-client/src/rpc.rs +++ b/relays/substrate-client/src/rpc.rs @@ -25,7 +25,6 @@ use crate::chain::Chain; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; -use frame_support::weights::Weight; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, @@ -63,7 +62,7 @@ jsonrpsee::rpc_api! { end: MessageNonce, include_outbound_lane_state: bool, block: Option, - ) -> (Weight, Bytes); + ) -> Bytes; #[rpc(method = "messageLane_proveMessagesDelivery", positional_params)] fn prove_messages_delivery( diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index 46e990e101682..c648289fee147 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -25,7 +25,7 @@ use codec::{Decode, Encode}; use frame_support::weights::Weight; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{ClientState, SourceClient, SourceClientState}, + message_lane_loop::{ClientState, MessageProofParameters, MessageWeightsMap, SourceClient, SourceClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; use relay_utils::HeaderId; @@ -95,7 +95,6 @@ where C::Index: DeserializeOwned, ::Number: Into, P: MessageLane< - MessageNonce = MessageNonce, MessagesProof = SubstrateMessagesProof, SourceHeaderNumber = ::Number, SourceHeaderHash = ::Hash, @@ -119,7 +118,7 @@ where async fn latest_generated_nonce( &self, id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error> { let encoded_response = self .client .state_call( @@ -129,7 +128,7 @@ where Some(id.1), ) .await?; - let latest_generated_nonce: P::MessageNonce = + let latest_generated_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_generated_nonce)) } @@ -137,7 +136,7 @@ where async fn latest_confirmed_received_nonce( &self, id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, P::MessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error> { let encoded_response = self .client .state_call( @@ -147,29 +146,62 @@ where Some(id.1), ) .await?; - let latest_received_nonce: P::MessageNonce = + let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_received_nonce)) } + async fn generated_messages_weights( + &self, + id: SourceHeaderIdOf

, + nonces: RangeInclusive, + ) -> Result { + let encoded_response = self + .client + .state_call( + // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 + "OutboundLaneApi_messages_dispatch_weight".into(), + Bytes((self.lane, nonces.start(), nonces.end()).encode()), + Some(id.1), + ) + .await?; + let weights: Vec<(MessageNonce, Weight)> = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + + let mut expected_nonce = *nonces.start(); + let mut weights_map = MessageWeightsMap::new(); + for (nonce, weight) in weights { + if nonce != expected_nonce { + return Err(SubstrateError::Custom(format!( + "Unexpected nonce in messages_dispatch_weight call result. Expected {}, got {}", + expected_nonce, nonce + ))); + } + + weights_map.insert(nonce, weight); + expected_nonce += 1; + } + Ok(weights_map) + } + async fn prove_messages( &self, id: SourceHeaderIdOf

, - nonces: RangeInclusive, - include_outbound_lane_state: bool, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { - let (weight, proof) = self + nonces: RangeInclusive, + proof_parameters: MessageProofParameters, + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { + let proof = self .client .prove_messages( self.instance, self.lane, nonces.clone(), - include_outbound_lane_state, + proof_parameters.outbound_state_proof_required, id.1, ) .await?; let proof = (id.1, proof, self.lane, *nonces.start(), *nonces.end()); - Ok((id, nonces, (weight, proof))) + Ok((id, nonces, (proof_parameters.dispatch_weight, proof))) } async fn submit_messages_receiving_proof( diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 541b4dc0f2d85..2569b5e2c9ae5 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -53,7 +53,7 @@ pub trait SubstrateTransactionMaker: Clone + Send + Sy async fn make_messages_delivery_transaction( &self, generated_at_header: SourceHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result; } @@ -91,7 +91,6 @@ where C::Index: DeserializeOwned, ::Number: Into, P: MessageLane< - MessageNonce = MessageNonce, MessagesReceivingProof = (HashOf, StorageProof, LaneId), TargetHeaderNumber = ::Number, TargetHeaderHash = ::Hash, @@ -115,7 +114,7 @@ where async fn latest_received_nonce( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error> { let encoded_response = self .client .state_call( @@ -125,7 +124,7 @@ where Some(id.1), ) .await?; - let latest_received_nonce: P::MessageNonce = + let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_received_nonce)) } @@ -133,7 +132,7 @@ where async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error> { let encoded_response = self .client .state_call( @@ -143,7 +142,7 @@ where Some(id.1), ) .await?; - let latest_received_nonce: P::MessageNonce = + let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_received_nonce)) } @@ -163,9 +162,9 @@ where async fn submit_messages_proof( &self, generated_at_header: SourceHeaderIdOf

, - nonces: RangeInclusive, + nonces: RangeInclusive, proof: P::MessagesProof, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let tx = self .tx_maker .make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof) diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 47a5158b552ef..81017f6745fbd 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -52,7 +52,6 @@ impl MessageLane for MillauMessagesToRialto { const SOURCE_NAME: &'static str = "Millau"; const TARGET_NAME: &'static str = "Rialto"; - type MessageNonce = MessageNonce; type MessagesProof = FromMillauMessagesProof; type MessagesReceivingProof = FromRialtoMessagesReceivingProof; @@ -144,7 +143,12 @@ pub fn run( target_tick: rialto_tick, reconnect_delay, stall_timeout, - max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + // TODO: subtract base weight of delivery from this when it'll be known + // https://github.com/paritytech/parity-bridges-common/issues/78 + max_messages_weight_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT, + }, }, MillauSourceClient::new( millau_client.clone(), From 7b41cb7ff7701c94138be50f987a6cd2bf49f260 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Nov 2020 01:46:18 +0300 Subject: [PATCH 0228/1210] Fixed referenced balance in rialto_messages.rs (#509) * fixed referenced balance in rialto_messages * names Co-authored-by: Hernando Castano --- bin/millau/runtime/src/rialto_messages.rs | 6 ++--- bin/rialto/runtime/src/millau_messages.rs | 6 ++--- bin/runtime-common/src/messages.rs | 31 ++++++++++------------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index b810aa1522100..7e7317f16152e 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -104,16 +104,16 @@ impl MessageBridge for WithRialtoMessageBridge { 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 } - fn this_weight_to_balance(weight: Weight) -> bp_rialto::Balance { + fn this_weight_to_this_balance(weight: Weight) -> bp_millau::Balance { ::WeightToFee::calc(&weight) } - fn bridged_weight_to_balance(weight: Weight) -> bp_millau::Balance { + fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_rialto::Balance { // we're using the same weights in both chains now ::WeightToFee::calc(&weight) } - fn this_chain_balance_to_bridged_chain_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { + fn this_balance_to_bridged_balance(this_balance: bp_millau::Balance) -> bp_rialto::Balance { // 1:1 conversion that will probably change in the future this_balance } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 65797322bca52..5a2cfba73da4c 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -104,16 +104,16 @@ impl MessageBridge for WithMillauMessageBridge { 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 } - fn this_weight_to_balance(weight: Weight) -> bp_rialto::Balance { + fn this_weight_to_this_balance(weight: Weight) -> bp_rialto::Balance { ::WeightToFee::calc(&weight) } - fn bridged_weight_to_balance(weight: Weight) -> bp_millau::Balance { + fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_millau::Balance { // we're using the same weights in both chains now ::WeightToFee::calc(&weight) } - fn this_chain_balance_to_bridged_chain_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { + fn this_balance_to_bridged_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { // 1:1 conversion that will probably change in the future this_balance } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 264efd409c208..9a934ee162da5 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -61,15 +61,13 @@ pub trait MessageBridge { fn weight_of_reward_confirmation_transaction_on_target_chain() -> WeightOf>; /// Convert weight of This chain to the fee (paid in Balance) of This chain. - fn this_weight_to_balance(weight: WeightOf>) -> BalanceOf>; + fn this_weight_to_this_balance(weight: WeightOf>) -> BalanceOf>; /// Convert weight of the Bridged chain to the fee (paid in Balance) of the Bridged chain. - fn bridged_weight_to_balance(weight: WeightOf>) -> BalanceOf>; + fn bridged_weight_to_bridged_balance(weight: WeightOf>) -> BalanceOf>; /// Convert This chain Balance into Bridged chain Balance. - fn this_chain_balance_to_bridged_chain_balance( - this_balance: BalanceOf>, - ) -> BalanceOf>; + fn this_balance_to_bridged_balance(this_balance: BalanceOf>) -> BalanceOf>; } /// Chain that has `message-lane` and `call-dispatch` modules. @@ -152,8 +150,7 @@ pub mod source { estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; // compare with actual fee paid - let actual_fee_in_bridged_tokens = - B::this_chain_balance_to_bridged_chain_balance(*delivery_and_dispatch_fee); + let actual_fee_in_bridged_tokens = B::this_balance_to_bridged_balance(*delivery_and_dispatch_fee); if actual_fee_in_bridged_tokens < minimal_fee_in_bridged_tokens { return Err("Too low fee paid"); } @@ -171,13 +168,13 @@ pub mod source { relayer_fee_percent: u32, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - let delivery_fee = B::bridged_weight_to_balance(B::weight_of_delivery_transaction()); - let dispatch_fee = B::bridged_weight_to_balance(payload.weight.into()); + let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction()); + let dispatch_fee = B::bridged_weight_to_bridged_balance(payload.weight.into()); let reward_confirmation_fee = - B::bridged_weight_to_balance(B::weight_of_reward_confirmation_transaction_on_target_chain()); + B::bridged_weight_to_bridged_balance(B::weight_of_reward_confirmation_transaction_on_target_chain()); // the fee (in Bridged tokens) of all transactions that are made on This chain - let delivery_confirmation_fee = B::this_chain_balance_to_bridged_chain_balance(B::this_weight_to_balance( + let delivery_confirmation_fee = B::this_balance_to_bridged_balance(B::this_weight_to_this_balance( B::weight_of_delivery_confirmation_transaction_on_this_chain(), )); @@ -444,15 +441,15 @@ mod tests { REWARD_CONFIRMATION_TRANSACTION_WEIGHT } - fn this_weight_to_balance(weight: Weight) -> ThisChainBalance { + fn this_weight_to_this_balance(weight: Weight) -> ThisChainBalance { ThisChainBalance(weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } - fn bridged_weight_to_balance(weight: Weight) -> BridgedChainBalance { + fn bridged_weight_to_bridged_balance(weight: Weight) -> BridgedChainBalance { BridgedChainBalance(weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } - fn this_chain_balance_to_bridged_chain_balance(this_balance: ThisChainBalance) -> BridgedChainBalance { + fn this_balance_to_bridged_balance(this_balance: ThisChainBalance) -> BridgedChainBalance { BridgedChainBalance(this_balance.0 * THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE as u32) } } @@ -483,15 +480,15 @@ mod tests { unreachable!() } - fn this_weight_to_balance(_weight: Weight) -> BridgedChainBalance { + fn this_weight_to_this_balance(_weight: Weight) -> BridgedChainBalance { unreachable!() } - fn bridged_weight_to_balance(_weight: Weight) -> ThisChainBalance { + fn bridged_weight_to_bridged_balance(_weight: Weight) -> ThisChainBalance { unreachable!() } - fn this_chain_balance_to_bridged_chain_balance(_this_balance: BridgedChainBalance) -> ThisChainBalance { + fn this_balance_to_bridged_balance(_this_balance: BridgedChainBalance) -> ThisChainBalance { unreachable!() } } From 9a21f15583ae1ffec204439ca717f8cb726fc00a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Nov 2020 23:18:42 +0300 Subject: [PATCH 0229/1210] Use different chain primitives in Millau (#517) --- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 4 +- bin/rialto/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 4 +- primitives/millau/Cargo.toml | 16 ++++++ primitives/millau/src/lib.rs | 52 ++++++++++++++--- primitives/millau/src/millau_hash.rs | 57 +++++++++++++++++++ relays/headers-relay/src/sync_types.rs | 16 +----- relays/messages-relay/src/message_lane.rs | 7 +-- relays/substrate-client/src/headers_source.rs | 3 +- relays/substrate/src/headers_pipeline.rs | 6 +- relays/substrate/src/messages_source.rs | 4 +- relays/substrate/src/messages_target.rs | 3 +- relays/utils/Cargo.toml | 1 + relays/utils/src/lib.rs | 45 +++++++++++++++ 15 files changed, 182 insertions(+), 40 deletions(-) create mode 100644 primitives/millau/src/millau_hash.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7435788acc666..bd340f0a7d3ba 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -256,7 +256,7 @@ impl pallet_timestamp::Trait for Runtime { } parameter_types! { - pub const ExistentialDeposit: u128 = 500; + pub const ExistentialDeposit: bp_millau::Balance = 500; // For weight estimation, we assume that the most locks on an individual account will be 50. // This number may need to be adjusted in the future if this assumption no longer holds true. pub const MaxLocks: u32 = 50; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 7e7317f16152e..5674f738e19e9 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -110,12 +110,12 @@ impl MessageBridge for WithRialtoMessageBridge { fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_rialto::Balance { // we're using the same weights in both chains now - ::WeightToFee::calc(&weight) + ::WeightToFee::calc(&weight) as _ } fn this_balance_to_bridged_balance(this_balance: bp_millau::Balance) -> bp_rialto::Balance { // 1:1 conversion that will probably change in the future - this_balance + this_balance as _ } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4a3855f69e6d6..2ff341427fd1e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -365,7 +365,7 @@ impl pallet_timestamp::Trait for Runtime { } parameter_types! { - pub const ExistentialDeposit: u128 = 500; + pub const ExistentialDeposit: bp_rialto::Balance = 500; // For weight estimation, we assume that the most locks on an individual account will be 50. // This number may need to be adjusted in the future if this assumption no longer holds true. pub const MaxLocks: u32 = 50; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 5a2cfba73da4c..6972a11eef098 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -110,12 +110,12 @@ impl MessageBridge for WithMillauMessageBridge { fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_millau::Balance { // we're using the same weights in both chains now - ::WeightToFee::calc(&weight) + ::WeightToFee::calc(&weight) as _ } fn this_balance_to_bridged_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { // 1:1 conversion that will probably change in the future - this_balance + this_balance as _ } } diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index 545bbd88fc757..db8fbf04feeb7 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -12,23 +12,39 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-message-lane = { path = "../message-lane", default-features = false } bp-runtime = { path = "../runtime", default-features = false } +fixed-hash = { version = "0.6.1", default-features = false } +hash256-std-hasher = { version = "0.15.2", default-features = false } +impl-codec = { version = "0.4.2", default-features = false } +impl-serde = { version = "0.3.1", optional = true } +parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies frame-support = { version = "2.0", default-features = false } sp-api = { version = "2.0", default-features = false } sp-core = { version = "2.0", default-features = false } +sp-io = { version = "2.0", default-features = false } sp-runtime = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } +sp-trie = { version = "2.0", default-features = false } [features] default = ["std"] std = [ "bp-message-lane/std", "bp-runtime/std", + "fixed-hash/std", "frame-support/std", + "hash256-std-hasher/std", + "impl-codec/std", + "impl-serde", + "parity-util-mem/std", + "serde", "sp-api/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-std/std", + "sp-trie/std", ] diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index d8c6f5c3008d1..70eba6832640f 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -20,18 +20,56 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +mod millau_hash; + use bp_message_lane::MessageNonce; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, Verify}, + traits::{IdentifyAccount, Verify}, MultiSignature, MultiSigner, }; use sp_std::prelude::*; +use sp_trie::{trie_types::Layout, TrieConfiguration}; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +pub use millau_hash::MillauHash; + +/// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. +#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BlakeTwoAndKeccak256; + +impl sp_core::Hasher for BlakeTwoAndKeccak256 { + type Out = MillauHash; + type StdHasher = hash256_std_hasher::Hash256StdHasher; + const LENGTH: usize = 64; + + fn hash(s: &[u8]) -> Self::Out { + let mut combined_hash = MillauHash::default(); + combined_hash.as_mut()[..32].copy_from_slice(&sp_io::hashing::blake2_256(s)); + combined_hash.as_mut()[32..].copy_from_slice(&sp_io::hashing::keccak_256(s)); + combined_hash + } +} + +impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { + type Output = MillauHash; + + fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { + Layout::::trie_root(input) + } + + fn ordered_trie_root(input: Vec>) -> Self::Output { + Layout::::ordered_trie_root(input) + } +} /// Maximal weight of single Millau block. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2_000_000_000_000; +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 10_000_000_000; /// Portion of block reserved for regular transactions. pub const AVAILABLE_BLOCK_RATIO: u32 = 75; /// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular @@ -39,16 +77,16 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75; pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); /// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; +pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; /// Block number type used in Millau. -pub type BlockNumber = u32; +pub type BlockNumber = u64; /// Hash type used in Millau. -pub type Hash = ::Out; +pub type Hash = ::Out; /// The type of an object that can produce hashes on Millau. -pub type Hasher = BlakeTwo256; +pub type Hasher = BlakeTwoAndKeccak256; /// The header type used by Millau. pub type Header = sp_runtime::generic::Header; @@ -84,7 +122,7 @@ pub type AccountId = <::Signer as IdentifyAccount>::Account pub type AccountSigner = MultiSigner; /// Balance of an account. -pub type Balance = u128; +pub type Balance = u64; sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. diff --git a/primitives/millau/src/millau_hash.rs b/primitives/millau/src/millau_hash.rs new file mode 100644 index 0000000000000..521b8997ad603 --- /dev/null +++ b/primitives/millau/src/millau_hash.rs @@ -0,0 +1,57 @@ +// Copyright 2019-2020 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 . + +use parity_util_mem::MallocSizeOf; +use sp_runtime::traits::CheckEqual; + +// `sp_core::H512` can't be used, because it doesn't implement `CheckEqual`, which is required +// by `frame_system::Trait::Hash`. + +fixed_hash::construct_fixed_hash! { + /// Hash type used in Millau chain. + #[derive(MallocSizeOf)] + pub struct MillauHash(64); +} + +#[cfg(feature = "std")] +impl_serde::impl_fixed_hash_serde!(MillauHash, 64); + +impl_codec::impl_fixed_hash_codec!(MillauHash, 64); + +impl CheckEqual for MillauHash { + #[cfg(feature = "std")] + fn check_equal(&self, other: &Self) { + use sp_core::hexdisplay::HexDisplay; + if self != other { + println!( + "Hash: given={}, expected={}", + HexDisplay::from(self.as_fixed_bytes()), + HexDisplay::from(other.as_fixed_bytes()), + ); + } + } + + #[cfg(not(feature = "std"))] + fn check_equal(&self, other: &Self) { + use frame_support::Printable; + + if self != other { + "Hash not equal".print(); + self.as_bytes().print(); + other.as_bytes().print(); + } + } +} diff --git a/relays/headers-relay/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs index 958c81dd911ed..7f975100f8edf 100644 --- a/relays/headers-relay/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -52,21 +52,7 @@ pub trait HeadersSyncPipeline: Clone + Send + Sync { /// Headers we're syncing are identified by this hash. type Hash: Eq + Clone + Copy + Send + Sync + std::fmt::Debug + std::fmt::Display + std::hash::Hash; /// Headers we're syncing are identified by this number. - type Number: From - + Ord - + Clone - + Copy - + Send - + Sync - + std::fmt::Debug - + std::fmt::Display - + std::hash::Hash - + std::ops::Add - + std::ops::Sub - + num_traits::Saturating - + num_traits::Zero - + num_traits::One - + Into; + type Number: relay_utils::BlockNumberBase; /// Type of header that we're syncing. type Header: SourceHeader; /// Type of extra data for the header that we're receiving from the source node: diff --git a/relays/messages-relay/src/message_lane.rs b/relays/messages-relay/src/message_lane.rs index 5b4a6a97cc858..6abddabb4879c 100644 --- a/relays/messages-relay/src/message_lane.rs +++ b/relays/messages-relay/src/message_lane.rs @@ -19,8 +19,7 @@ //! 1) relay new messages from source to target node; //! 2) relay proof-of-delivery from target to source node. -use relay_utils::HeaderId; - +use relay_utils::{BlockNumberBase, HeaderId}; use std::fmt::Debug; /// One-way message lane. @@ -36,12 +35,12 @@ pub trait MessageLane: Clone + Send + Sync { type MessagesReceivingProof: Clone + Send + Sync; /// Number of the source header. - type SourceHeaderNumber: Clone + Debug + Ord + PartialEq + Into + Send + Sync; + type SourceHeaderNumber: BlockNumberBase; /// Hash of the source header. type SourceHeaderHash: Clone + Debug + Default + PartialEq + Send + Sync; /// Number of the target header. - type TargetHeaderNumber: Clone + Debug + Ord + PartialEq + Into + Send + Sync; + type TargetHeaderNumber: BlockNumberBase; /// Hash of the target header. type TargetHeaderHash: Clone + Debug + Default + PartialEq + Send + Sync; } diff --git a/relays/substrate-client/src/headers_source.rs b/relays/substrate-client/src/headers_source.rs index b9b46774ce588..33f194322ddea 100644 --- a/relays/substrate-client/src/headers_source.rs +++ b/relays/substrate-client/src/headers_source.rs @@ -25,7 +25,6 @@ use headers_relay::{ sync_loop::SourceClient, sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; -use num_traits::Saturating; use sp_runtime::{traits::Header as HeaderT, Justification}; use std::marker::PhantomData; @@ -49,7 +48,7 @@ impl HeadersSource { impl SourceClient

for HeadersSource where C: Chain, - C::BlockNumber: Into + Saturating, + C::BlockNumber: relay_utils::BlockNumberBase, C::Header: Into, P: HeadersSyncPipeline, P::Header: SourceHeader, diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index b00417da39d0e..adcebbc7a7f43 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -26,8 +26,8 @@ use headers_relay::{ sync::{HeadersSyncParams, TargetTransactionMode}, sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; -use num_traits::Saturating; use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, HashOf}; +use relay_utils::BlockNumberBase; use sp_runtime::Justification; use std::marker::PhantomData; @@ -59,7 +59,7 @@ impl HeadersSyncPipeline for SubstrateHeadersToSubstrate where SourceChain: Clone + Chain, - BlockNumberOf: Saturating + Into, + BlockNumberOf: BlockNumberBase, SourceSyncHeader: SourceHeader, BlockNumberOf> + std::ops::Deref, TargetChain: Clone + Chain, @@ -107,7 +107,7 @@ pub async fn run( P::Header: SourceHeader, BlockNumberOf>, SourceChain: Clone + Chain, SourceChain::Header: Into, - BlockNumberOf: Into + Saturating, + BlockNumberOf: BlockNumberBase, TargetChain: Clone + Chain, { let source_justifications = match source_client.clone().subscribe_justifications().await { diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index c648289fee147..eb182f8f1edb1 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -28,7 +28,7 @@ use messages_relay::{ message_lane_loop::{ClientState, MessageProofParameters, MessageWeightsMap, SourceClient, SourceClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; -use relay_utils::HeaderId; +use relay_utils::{BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; @@ -93,7 +93,7 @@ where C: Chain, C::Header: DeserializeOwned, C::Index: DeserializeOwned, - ::Number: Into, + C::BlockNumber: BlockNumberBase, P: MessageLane< MessagesProof = SubstrateMessagesProof, SourceHeaderNumber = ::Number, diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 2569b5e2c9ae5..4ad61caf20e80 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -29,6 +29,7 @@ use messages_relay::{ message_lane_loop::{TargetClient, TargetClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; +use relay_utils::BlockNumberBase; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; @@ -89,7 +90,7 @@ where C: Chain, C::Header: DeserializeOwned, C::Index: DeserializeOwned, - ::Number: Into, + ::Number: BlockNumberBase, P: MessageLane< MessagesReceivingProof = (HashOf, StorageProof, LaneId), TargetHeaderNumber = ::Number, diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index eeb49369f9295..04ceb3ec0dc01 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -12,6 +12,7 @@ backoff = "0.2" env_logger = "0.7.0" futures = "0.3.5" log = "0.4.11" +num-traits = "0.2" sysinfo = "0.15" time = "0.2" diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 49f2ae996598e..e81660299becb 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -30,6 +30,51 @@ pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); pub mod initialize; pub mod metrics; +/// Block number traits shared by all chains that relay is able to serve. +pub trait BlockNumberBase: + 'static + + From + + Into + + Ord + + Clone + + Copy + + Default + + Send + + Sync + + std::fmt::Debug + + std::fmt::Display + + std::hash::Hash + + std::ops::Add + + std::ops::Sub + + num_traits::CheckedSub + + num_traits::Saturating + + num_traits::Zero + + num_traits::One +{ +} + +impl BlockNumberBase for T where + T: 'static + + From + + Into + + Ord + + Clone + + Copy + + Default + + Send + + Sync + + std::fmt::Debug + + std::fmt::Display + + std::hash::Hash + + std::ops::Add + + std::ops::Sub + + num_traits::CheckedSub + + num_traits::Saturating + + num_traits::Zero + + num_traits::One +{ +} + /// Macro that returns (client, Err(error)) tuple from function if result is Err(error). #[macro_export] macro_rules! bail_on_error { From b126eb199be0bddddd13f7b736c13fc710d175d8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Nov 2020 23:23:46 +0300 Subject: [PATCH 0230/1210] Fixed message signed by relay (#515) * fixed message that is signed by relay * clippy --- relays/substrate/src/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 727e4eb24300c..52d09a3dc5e7f 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -274,7 +274,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { }; let rialto_call_weight = rialto_call.get_dispatch_info().weight; - let millau_sender_public = millau_sign.signer.public(); + let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); let rialto_origin_public = rialto_sign.signer.public(); let mut rialto_origin_signature_message = Vec::new(); @@ -289,7 +289,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { spec_version: millau_runtime::VERSION.spec_version, weight: rialto_call_weight, origin: CallOrigin::RealAccount( - millau_sender_public.into(), + millau_sender_public, rialto_origin_public.into(), rialto_origin_signature.into(), ), @@ -301,7 +301,9 @@ async fn run_command(command: cli::Command) -> Result<(), String> { let signed_millau_call = Millau::sign_transaction( &millau_client, &millau_sign.signer, - millau_client.next_account_index(millau_sender_public.into()).await?, + millau_client + .next_account_index(millau_sign.signer.public().clone().into()) + .await?, millau_call, ); From 67ecf05b6faaa441cb70e6b8e27c14de4d796b45 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Nov 2020 23:26:08 +0300 Subject: [PATCH 0231/1210] Fixed outbound_lane_data_key (#516) --- modules/message-lane/rpc/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index 54ac5eba1e51b..df85064f3c414 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -112,7 +112,7 @@ where ) -> FutureResult { let runtime = self.runtime.clone(); let outbound_lane_data_key = if include_outbound_lane_state { - Some(runtime.inbound_lane_data_key(&instance, &lane)) + Some(runtime.outbound_lane_data_key(&instance, &lane)) } else { None }; From 001f9c5c6ae1e3eec08f81f480efe947161e8218 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 19 Nov 2020 10:20:23 -0500 Subject: [PATCH 0232/1210] Avoid Panic When Fetching Info Before Bridge is Initialized (#504) * Allow bridge pallet to return no finalized headers * Update Runtime APIs to optionally return best finalized header * Update relay to handle optional best finalized headers * Fix Clippy lints * Return a dummy header instead of an Option * Remove Option from runtime Apis * Remove support for handling optional finalized headers in relay --- modules/substrate/src/lib.rs | 26 ++++++++++++++++++++++++-- relays/substrate-client/src/error.rs | 3 +++ relays/substrate/src/headers_target.rs | 11 +++++------ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 1515c46ca897a..4e62841af7b56 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -289,6 +289,9 @@ impl Module { /// Get the best finalized header the pallet knows of. /// + /// Returns a dummy header if there is no best header. This can only happen + /// if the pallet has not been initialized yet. + /// /// Since this has been finalized correctly a user of the bridge /// pallet should be confident that any transactions that were /// included in this or any previous header will not be reverted. @@ -424,6 +427,9 @@ pub trait BridgeStorage { fn best_headers(&self) -> Vec>; /// Get the best finalized header the pallet knows of. + /// + /// Returns None if there is no best header. This can only happen if the pallet + /// has not been initialized yet. fn best_finalized_header(&self) -> ImportedHeader; /// Update the best finalized header the pallet knows of. @@ -525,9 +531,22 @@ impl BridgeStorage for PalletStorage { } fn best_finalized_header(&self) -> ImportedHeader> { + // We will only construct a dummy header if the pallet is not initialized and someone tries + // to use the public module interface (not dispatchables) to get the best finalized header. + // This is an edge case since this can only really happen when bootstrapping the bridge. let hash = >::get(); - self.header_by_hash(hash) - .expect("A finalized header was added at genesis, therefore this must always exist") + self.header_by_hash(hash).unwrap_or_else(|| ImportedHeader { + header: >::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), + requires_justification: false, + is_finalized: false, + signal_hash: None, + }) } fn update_best_finalized(&self, hash: BridgedBlockHash) { @@ -620,6 +639,9 @@ mod tests { is_halted: false, }; + assert!(Module::::best_headers().is_empty()); + assert_eq!(Module::::best_finalized(), test_header(0)); + assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); let storage = PalletStorage::::new(); diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index bafcb1a1fec73..c2930c21d217a 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -34,6 +34,8 @@ pub enum Error { Request(RequestError), /// The response from the server could not be SCALE decoded. ResponseParseFailed(codec::Error), + /// The Substrate bridge pallet has not yet been initialized. + UninitializedBridgePallet, /// Account does not exist on the chain. AccountDoesNotExist, /// Custom logic error. @@ -70,6 +72,7 @@ impl ToString for Error { Self::WsConnectionError(e) => e.to_string(), Self::Request(e) => e.to_string(), Self::ResponseParseFailed(e) => e.what().to_string(), + Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), Self::Custom(e) => e.clone(), } diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index 6fb4a1500af6e..d72e032da911b 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -91,13 +91,12 @@ where let decoded_response: Vec<(P::Number, P::Hash)> = Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - const WARNING_MSG: &str = "Parsed an empty list of headers, we should always have at least - one. Has the bridge pallet been initialized yet?"; - let best_header = decoded_response + // If we parse an empty list of headers it means that bridge pallet has not been initalized + // yet. Otherwise we expect to always have at least one header. + decoded_response .last() - .ok_or_else(|| SubstrateError::ResponseParseFailed(WARNING_MSG.into()))?; - let best_header_id = HeaderId(best_header.0, best_header.1); - Ok(best_header_id) + .ok_or(SubstrateError::UninitializedBridgePallet) + .map(|(num, hash)| HeaderId(*num, *hash)) } async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), Self::Error> { From 684242af0b6b3c8e9ec1cde529df2f6440a85238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 20 Nov 2020 15:35:26 +0100 Subject: [PATCH 0233/1210] Fix cargo-deny. (#522) * Fix cargo-deny. * Update time crate. * Fix time issues. --- relays/utils/src/initialize.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index c6c395d18e02a..6b0efb49e480b 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -30,7 +30,9 @@ pub fn initialize_relay() { builder.parse_filters(&filters); builder.format(move |buf, record| { writeln!(buf, "{}", { - let timestamp = time::OffsetDateTime::now_local().format("%Y-%m-%d %H:%M:%S %z"); + let timestamp = time::OffsetDateTime::try_now_local() + .unwrap_or_else(|_| time::OffsetDateTime::now_utc()) + .format("%Y-%m-%d %H:%M:%S %z"); if cfg!(windows) { format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) } else { From 507359724c74cb5347dd9a17d114426e85d779b8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 03:01:51 +0000 Subject: [PATCH 0234/1210] Bump env_logger from 0.8.1 to 0.8.2 (#523) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 69af77a8fa319..c02f449f71e14 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.7.0" async-trait = "0.1.41" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } -env_logger = "0.8.1" +env_logger = "0.8.2" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" From 53d5a536bef02fb6f9f0234fbaf14ad810c61f38 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 03:07:36 +0000 Subject: [PATCH 0235/1210] Bump async-trait from 0.1.41 to 0.1.42 (#524) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index c02f449f71e14..816b1af14a2b3 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" async-std = "1.7.0" -async-trait = "0.1.41" +async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } env_logger = "0.8.2" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index f0d6c1e2183a6..66a6aaea50f5f 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.7.0" -async-trait = "0.1.41" +async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.7" hex = "0.4" From 8bf2a564c0215dc1dc6f901137f07b092960c4b6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 23 Nov 2020 10:28:56 +0300 Subject: [PATCH 0236/1210] Use best block state to craft message relay transactions (#499) * use best block state to craft message relay transactions * removed obsolete TODO * Update relays/messages-relay/src/message_race_loop.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- .../messages-relay/src/message_lane_loop.rs | 38 ++++++---- .../src/message_race_delivery.rs | 21 ++---- .../messages-relay/src/message_race_loop.rs | 73 +++++++++++-------- .../src/message_race_strategy.rs | 38 ++++------ relays/messages-relay/src/metrics.rs | 4 +- relays/substrate/src/messages_source.rs | 12 ++- 6 files changed, 97 insertions(+), 89 deletions(-) diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index d0c4b46d8e226..d7e3778ff55b0 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -169,8 +169,10 @@ pub trait TargetClient: Clone + Send + Sync { pub struct ClientState { /// Best header id of this chain. pub best_self: SelfHeaderId, - /// Best header id of the peer chain. - pub best_peer: PeerHeaderId, + /// Best finalized header id of this chain. + pub best_finalized_self: SelfHeaderId, + /// Best finalized header id of the peer chain read at the best block of this chain (at `best_finalized_self`). + pub best_finalized_peer_at_best_self: PeerHeaderId, } /// State of source client in one-way message lane. @@ -746,12 +748,14 @@ pub(crate) mod tests { is_source_fails: true, source_state: ClientState { best_self: HeaderId(0, 0), - best_peer: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), }, source_latest_generated_nonce: 1, target_state: ClientState { best_self: HeaderId(0, 0), - best_peer: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), }, target_latest_received_nonce: 0, ..Default::default() @@ -766,9 +770,11 @@ pub(crate) mod tests { if data.is_target_reconnected { data.is_target_fails = false; } - if data.target_state.best_peer.0 < 10 { - data.target_state.best_peer = - HeaderId(data.target_state.best_peer.0 + 1, data.target_state.best_peer.0 + 1); + if data.target_state.best_finalized_peer_at_best_self.0 < 10 { + data.target_state.best_finalized_peer_at_best_self = HeaderId( + data.target_state.best_finalized_peer_at_best_self.0 + 1, + data.target_state.best_finalized_peer_at_best_self.0 + 1, + ); } if !data.submitted_messages_proofs.is_empty() { exit_sender.unbounded_send(()).unwrap(); @@ -787,12 +793,14 @@ pub(crate) mod tests { TestClientData { source_state: ClientState { best_self: HeaderId(10, 10), - best_peer: HeaderId(0, 0), + best_finalized_self: HeaderId(10, 10), + best_finalized_peer_at_best_self: HeaderId(0, 0), }, source_latest_generated_nonce: 10, target_state: ClientState { best_self: HeaderId(0, 0), - best_peer: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), }, target_latest_received_nonce: 0, ..Default::default() @@ -800,12 +808,12 @@ pub(crate) mod tests { Arc::new(|_: &mut TestClientData| {}), Arc::new(move |data: &mut TestClientData| { // syncing source headers -> target chain (all at once) - if data.target_state.best_peer.0 < data.source_state.best_self.0 { - data.target_state.best_peer = data.source_state.best_self; + if data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_finalized_self.0 { + data.target_state.best_finalized_peer_at_best_self = data.source_state.best_finalized_self; } - // syncing target headers -> source chain (all at once) - if data.source_state.best_peer.0 < data.target_state.best_self.0 { - data.source_state.best_peer = data.target_state.best_self; + // syncing source headers -> target chain (all at once) + if data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_finalized_self.0 { + data.source_state.best_finalized_peer_at_best_self = data.target_state.best_finalized_self; } // if target has received messages batch => increase blocks so that confirmations may be sent if data.target_latest_received_nonce == 4 @@ -814,8 +822,10 @@ pub(crate) mod tests { { data.target_state.best_self = HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.0 + 1); + data.target_state.best_finalized_self = data.target_state.best_self; data.source_state.best_self = HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.0 + 1); + data.source_state.best_finalized_self = data.source_state.best_self; } // if source has received all messages receiving confirmations => increase source block so that confirmations may be sent if data.source_latest_confirmed_received_nonce == 10 { diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 370567542cc75..dbc5d31400e9f 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -264,11 +264,6 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M // There's additional condition in the message delivery race: target would reject messages // if there are too much unconfirmed messages at the inbound lane. - // https://github.com/paritytech/parity-bridges-common/issues/432 - // TODO: message lane loop works with finalized blocks only, but we're submitting transactions that - // are updating best block (which may not be finalized yet). So all decisions that are made below - // may be outdated. This needs to be changed - all logic here must be built on top of best blocks. - // The receiving race is responsible to deliver confirmations back to the source chain. So if // there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. let latest_received_nonce_at_target = target_nonces.latest_nonce; @@ -388,9 +383,8 @@ impl NoncesRange for MessageWeightsMap { #[cfg(test)] mod tests { use super::*; - use crate::message_lane_loop::{ - tests::{header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderId, TestTargetHeaderId}, - ClientState, + use crate::message_lane_loop::tests::{ + header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderId, TestTargetHeaderId, }; type TestRaceState = RaceState; @@ -398,14 +392,9 @@ mod tests { fn prepare_strategy() -> (TestRaceState, TestStrategy) { let mut race_state = RaceState { - source_state: Some(ClientState { - best_self: header_id(1), - best_peer: header_id(1), - }), - target_state: Some(ClientState { - best_self: header_id(1), - best_peer: header_id(1), - }), + best_finalized_source_header_id_at_source: Some(header_id(1)), + best_finalized_source_header_id_at_best_target: Some(header_id(1)), + best_target_header_id: Some(header_id(1)), nonces_to_submit: None, nonces_submitted: None, }; diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 8fa8d5ffba36a..5db54fbecfd5f 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -168,10 +168,13 @@ pub trait RaceStrategy { /// State of the race. #[derive(Debug)] pub struct RaceState { - /// Source state, if known. - pub source_state: Option>, - /// Target state, if known. - pub target_state: Option>, + /// Best finalized source header id at the source client. + pub best_finalized_source_header_id_at_source: Option, + /// Best finalized source header id at the best block on the target + /// client (at the `best_finalized_source_header_id_at_best_target`). + pub best_finalized_source_header_id_at_best_target: Option, + /// Best header id at the target client. + pub best_target_header_id: Option, /// Range of nonces that we have selected to submit. pub nonces_to_submit: Option<(SourceHeaderId, RangeInclusive, Proof)>, /// Range of nonces that is currently submitted. @@ -227,17 +230,23 @@ pub async fn run>( // when headers ids are updated source_state = race_source_updated.next() => { if let Some(source_state) = source_state { - if race_state.source_state.as_ref() != Some(&source_state) { + let is_source_state_updated = race_state.best_finalized_source_header_id_at_source.as_ref() + != Some(&source_state.best_finalized_self); + if is_source_state_updated { source_nonces_required = true; - race_state.source_state = Some(source_state); + race_state.best_finalized_source_header_id_at_source = Some(source_state.best_finalized_self); } } }, target_state = race_target_updated.next() => { if let Some(target_state) = target_state { - if race_state.target_state.as_ref() != Some(&target_state) { + let is_target_state_updated = race_state.best_target_header_id.as_ref() + != Some(&target_state.best_self); + if is_target_state_updated { target_nonces_required = true; - race_state.target_state = Some(target_state); + race_state.best_target_header_id = Some(target_state.best_self); + race_state.best_finalized_source_header_id_at_best_target + = Some(target_state.best_finalized_peer_at_best_self); } } }, @@ -358,10 +367,12 @@ pub async fn run>( } else if source_nonces_required { log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); let at_block = race_state - .source_state + .best_finalized_source_header_id_at_source .as_ref() - .expect("source_nonces_required is only true when source_state is Some; qed") - .best_self + .expect( + "source_nonces_required is only true when\ + best_finalized_source_header_id_at_source is Some; qed", + ) .clone(); source_nonces.set(race_source.nonces(at_block, strategy.best_at_source()).fuse()); } else { @@ -388,10 +399,9 @@ pub async fn run>( if target_nonces_required { log::debug!(target: "bridge", "Asking {} about message nonces", P::target_name()); let at_block = race_state - .target_state + .best_target_header_id .as_ref() - .expect("target_nonces_required is only true when target_state is Some; qed") - .best_self + .expect("target_nonces_required is only true when best_target_header_id is Some; qed") .clone(); target_nonces.set(race_target.nonces(at_block).fuse()); } else { @@ -404,8 +414,9 @@ pub async fn run>( impl Default for RaceState { fn default() -> Self { RaceState { - source_state: None, - target_state: None, + best_finalized_source_header_id_at_source: None, + best_finalized_source_header_id_at_best_target: None, + best_target_header_id: None, nonces_to_submit: None, nonces_submitted: None, } @@ -446,11 +457,20 @@ where SourceHeaderId: Clone, Strategy: RaceStrategy, { - race_state.target_state.as_ref().and_then(|target_state| { - strategy - .select_nonces_to_deliver(&race_state) - .map(|(nonces_range, proof_parameters)| (target_state.best_peer.clone(), nonces_range, proof_parameters)) - }) + race_state + .best_finalized_source_header_id_at_best_target + .as_ref() + .and_then(|best_finalized_source_header_id_at_best_target| { + strategy + .select_nonces_to_deliver(&race_state) + .map(|(nonces_range, proof_parameters)| { + ( + best_finalized_source_header_id_at_best_target.clone(), + nonces_range, + proof_parameters, + ) + }) + }) } #[cfg(test)] @@ -468,14 +488,9 @@ mod tests { // target node only knows about source' BEST_AT_TARGET block // source node has BEST_AT_SOURCE > BEST_AT_TARGET block let mut race_state = RaceState::<_, _, ()> { - source_state: Some(ClientState { - best_self: HeaderId(BEST_AT_SOURCE, BEST_AT_SOURCE), - best_peer: HeaderId(0, 0), - }), - target_state: Some(ClientState { - best_self: HeaderId(0, 0), - best_peer: HeaderId(BEST_AT_TARGET, BEST_AT_TARGET), - }), + best_finalized_source_header_id_at_source: Some(HeaderId(BEST_AT_SOURCE, BEST_AT_SOURCE)), + best_finalized_source_header_id_at_best_target: Some(HeaderId(BEST_AT_TARGET, BEST_AT_TARGET)), + best_target_header_id: Some(HeaderId(0, 0)), nonces_to_submit: None, nonces_submitted: None, }; diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index 83b139f0f3e2e..dbd080e5a29c4 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -88,9 +88,8 @@ where // 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized // by target client // 3) selector is used for more complicated logic - let best_header_at_target = &race_state.target_state.as_ref()?.best_peer; + let best_header_at_target = &race_state.best_finalized_source_header_id_at_best_target.as_ref()?; let mut nonces_end = None; - while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { // select (sub) range to deliver let queued_range_begin = queued_range.begin(); @@ -241,10 +240,7 @@ where mod tests { use super::*; use crate::message_lane::MessageLane; - use crate::message_lane_loop::{ - tests::{header_id, TestMessageLane, TestMessagesProof}, - ClientState, - }; + use crate::message_lane_loop::tests::{header_id, TestMessageLane, TestMessagesProof}; type SourceNoncesRange = RangeInclusive; @@ -374,21 +370,15 @@ mod tests { let mut strategy = BasicStrategy::::new(); strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); strategy.source_nonces_updated(header_id(2), source_nonces(2..=2)); - strategy.source_nonces_updated(header_id(3), source_nonces(6..=6)); - strategy.source_nonces_updated(header_id(5), source_nonces(8..=8)); + strategy.source_nonces_updated(header_id(3), source_nonces(3..=6)); + strategy.source_nonces_updated(header_id(5), source_nonces(7..=8)); - state.target_state = Some(ClientState { - best_self: header_id(0), - best_peer: header_id(4), - }); + state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); assert_eq!(strategy.select_nonces_to_deliver(&state), Some((1..=6, ()))); strategy.target_nonces_updated(target_nonces(6), &mut state); assert_eq!(strategy.select_nonces_to_deliver(&state), None); - state.target_state = Some(ClientState { - best_self: header_id(0), - best_peer: header_id(5), - }); + state.best_finalized_source_header_id_at_best_target = Some(header_id(5)); assert_eq!(strategy.select_nonces_to_deliver(&state), Some((7..=8, ()))); strategy.target_nonces_updated(target_nonces(8), &mut state); assert_eq!(strategy.select_nonces_to_deliver(&state), None); @@ -400,10 +390,10 @@ mod tests { let mut strategy = BasicStrategy::::new(); strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); - state.target_state = Some(ClientState { - best_self: header_id(0), - best_peer: header_id(1), - }); + state.best_finalized_source_header_id_at_source = Some(header_id(1)); + state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); + state.best_target_header_id = Some(header_id(1)); + assert_eq!( strategy.select_nonces_to_deliver_with_selector(&state, |_| Some(50..=100)), Some(1..=49), @@ -417,11 +407,9 @@ mod tests { let mut strategy = BasicStrategy::::new(); strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); strategy.target_nonces_updated(target_nonces(50), &mut state); - state.target_state = Some(ClientState { - best_self: header_id(0), - best_peer: header_id(1), - }); - + state.best_finalized_source_header_id_at_source = Some(header_id(1)); + state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); + state.best_target_header_id = Some(header_id(1)); strategy.select_nonces_to_deliver_with_selector(&state, invalid_selector); } diff --git a/relays/messages-relay/src/metrics.rs b/relays/messages-relay/src/metrics.rs index 462317028c15d..b001d32926ddb 100644 --- a/relays/messages-relay/src/metrics.rs +++ b/relays/messages-relay/src/metrics.rs @@ -64,7 +64,7 @@ impl MessageLaneLoopMetrics { .set(source_client_state.best_self.0.into()); self.best_block_numbers .with_label_values(&["target_at_source"]) - .set(source_client_state.best_peer.0.into()); + .set(source_client_state.best_finalized_peer_at_best_self.0.into()); } /// Update target client state metrics. @@ -74,7 +74,7 @@ impl MessageLaneLoopMetrics { .set(target_client_state.best_self.0.into()); self.best_block_numbers .with_label_values(&["source_at_target"]) - .set(target_client_state.best_peer.0.into()); + .set(target_client_state.best_finalized_peer_at_best_self.0.into()); } /// Update latest generated nonce at source. diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index eb182f8f1edb1..ad82d252439e9 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -234,13 +234,18 @@ where let self_best_finalized_header = self_client.header_by_hash(self_best_finalized_header_hash).await?; let self_best_finalized_id = HeaderId(*self_best_finalized_header.number(), self_best_finalized_header_hash); + // now let's read our best header on **this** chain + let self_best_header = self_client.best_header().await?; + let self_best_hash = self_best_header.hash(); + let self_best_id = HeaderId(*self_best_header.number(), self_best_hash); + // now let's read id of best finalized peer header at our best finalized block let best_finalized_peer_on_self_method = format!("{}HeaderApi_finalized_block", bridged_chain_name); let encoded_best_finalized_peer_on_self = self_client .state_call( best_finalized_peer_on_self_method, Bytes(Vec::new()), - Some(self_best_finalized_header_hash), + Some(self_best_hash), ) .await?; let decoded_best_finalized_peer_on_self: (BridgedHeaderNumber, BridgedHeaderHash) = @@ -251,7 +256,8 @@ where ); Ok(ClientState { - best_self: self_best_finalized_id, - best_peer: peer_on_self_best_finalized_id, + best_self: self_best_id, + best_finalized_self: self_best_finalized_id, + best_finalized_peer_at_best_self: peer_on_self_best_finalized_id, }) } From 1ec7deff51fb166b5227e67cf2d276561e0fd150 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 23 Nov 2020 10:55:47 +0300 Subject: [PATCH 0237/1210] Chain specific message lane apis (#503) * replace generic message lane APIs with chain-specific * moved SubstrateHeadersSyncPipeline to headers_pipeline.rs * substrate-specific message lane trait * Update relays/substrate/src/messages_lane.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/lib.rs | 6 +- primitives/message-lane/Cargo.toml | 2 - primitives/message-lane/src/lib.rs | 28 ----- primitives/millau/src/lib.rs | 45 ++++++- primitives/rialto/src/lib.rs | 45 ++++++- relays/substrate/src/headers_maintain.rs | 2 +- relays/substrate/src/headers_pipeline.rs | 41 ++++++- relays/substrate/src/headers_target.rs | 33 +----- relays/substrate/src/main.rs | 1 + relays/substrate/src/messages_lane.rs | 63 ++++++++++ relays/substrate/src/messages_source.rs | 78 +++++------- relays/substrate/src/messages_target.rs | 68 ++++------- .../substrate/src/millau_headers_to_rialto.rs | 4 +- .../src/millau_messages_to_rialto.rs | 112 ++++++++---------- .../substrate/src/rialto_headers_to_millau.rs | 4 +- 16 files changed, 308 insertions(+), 230 deletions(-) create mode 100644 relays/substrate/src/messages_lane.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index bd340f0a7d3ba..01c81a5582607 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -540,8 +540,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::OutboundLaneApi for Runtime { + impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn messages_dispatch_weight( lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, @@ -566,8 +565,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::InboundLaneApi for Runtime { + impl bp_rialto::FromRialtoInboundLaneApi for Runtime { fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { BridgeRialtoMessageLane::inbound_latest_received_nonce(lane) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 2ff341427fd1e..7374a805a77b7 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -704,8 +704,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::OutboundLaneApi for Runtime { + impl bp_millau::ToMillauOutboundLaneApi for Runtime { fn messages_dispatch_weight( lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, @@ -730,8 +729,7 @@ impl_runtime_apis! { } } - // TODO: runtime should support several chains (https://github.com/paritytech/parity-bridges-common/issues/457) - impl bp_message_lane::InboundLaneApi for Runtime { + impl bp_millau::FromMillauInboundLaneApi for Runtime { fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { BridgeMillauMessageLane::inbound_latest_received_nonce(lane) } diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index d705c119fe5d0..ecd20d611ea73 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -12,7 +12,6 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Dependencies frame-support = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } sp-std = { version = "2.0", default-features = false } [features] @@ -20,6 +19,5 @@ default = ["std"] std = [ "codec/std", "frame-support/std", - "sp-api/std", "sp-std/std" ] diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 760333a8cfcb8..848acb31b242a 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -24,7 +24,6 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; -use sp_api::decl_runtime_apis; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; @@ -125,30 +124,3 @@ impl Default for OutboundLaneData { } } } - -decl_runtime_apis! { - /// Outbound message lane API. - pub trait OutboundLaneApi { - /// Returns dispatch weight of all messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec<(MessageNonce, Weight)>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API. - pub trait InboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - } -} diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 70eba6832640f..c5af6a07ad695 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -22,7 +22,7 @@ mod millau_hash; -use bp_message_lane::MessageNonce; +use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; @@ -111,6 +111,18 @@ pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; /// Name of the `MillauHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; +/// Name of the `ToMillauOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToMillauOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; +/// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_generated_nonce"; + +/// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_received_nonce"; +/// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; + /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -149,4 +161,35 @@ sp_api::decl_runtime_apis! { /// Returns true if the header is considered finalized by the runtime. fn is_finalized_block(hash: Hash) -> bool; } + + /// Outbound message lane API for messages that are sent to Millau chain. + /// + /// This API is implemented by runtimes that are sending messages to Millau chain, not the + /// Millau runtime itself. + pub trait ToMillauOutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Millau chain. + /// + /// This API is implemented by runtimes that are receiving messages from Millau chain, not the + /// Millau runtime itself. + pub trait FromMillauInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + } } diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 389bd869f13ee..a9a1342a68fb1 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::MessageNonce; +use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; @@ -73,6 +73,18 @@ pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; /// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; +/// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; +/// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; + /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -111,4 +123,35 @@ sp_api::decl_runtime_apis! { /// Returns true if the header is considered finalized by the runtime. fn is_finalized_block(hash: Hash) -> bool; } + + /// Outbound message lane API for messages that are sent to Rialto chain. + /// + /// This API is implemented by runtimes that are sending messages to Rialto chain, not the + /// Rialto runtime itself. + pub trait ToRialtoOutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Rialto chain. + /// + /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the + /// Rialto runtime itself. + pub trait FromRialtoInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + } } diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index fc91494c7b725..0dac3cafb492b 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -29,7 +29,7 @@ //! best finalized header on the target chain, we submit this justification to the target //! node. -use crate::headers_target::SubstrateHeadersSyncPipeline; +use crate::headers_pipeline::SubstrateHeadersSyncPipeline; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index adcebbc7a7f43..a60f8fb0ad64c 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -16,21 +16,50 @@ //! Substrate-to-Substrate headers sync entrypoint. -use crate::{ - headers_maintain::SubstrateHeadersToSubstrateMaintain, - headers_target::{SubstrateHeadersSyncPipeline, SubstrateHeadersTarget}, -}; +use crate::{headers_maintain::SubstrateHeadersToSubstrateMaintain, headers_target::SubstrateHeadersTarget}; +use async_trait::async_trait; use codec::Encode; use headers_relay::{ sync::{HeadersSyncParams, TargetTransactionMode}, - sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader}, + sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, +}; +use relay_substrate_client::{ + headers_source::HeadersSource, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, }; -use relay_substrate_client::{headers_source::HeadersSource, BlockNumberOf, Chain, Client, HashOf}; use relay_utils::BlockNumberBase; use sp_runtime::Justification; use std::marker::PhantomData; +/// Headers sync pipeline for Substrate <-> Substrate relays. +#[async_trait] +pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { + /// Name of the `best_block` runtime method. + const BEST_BLOCK_METHOD: &'static str; + /// Name of the `finalized_block` runtime method. + const FINALIZED_BLOCK_METHOD: &'static str; + /// Name of the `is_known_block` runtime method. + const IS_KNOWN_BLOCK_METHOD: &'static str; + /// Name of the `incomplete_headers` runtime method. + const INCOMPLETE_HEADERS_METHOD: &'static str; + + /// Signed transaction type. + type SignedTransaction: Send + Sync + Encode; + + /// Make submit header transaction. + async fn make_submit_header_transaction( + &self, + header: QueuedHeader, + ) -> Result; + + /// Make completion transaction for the header. + async fn make_complete_header_transaction( + &self, + id: HeaderIdOf, + completion: Justification, + ) -> Result; +} + /// Substrate-to-Substrate headers pipeline. #[derive(Debug, Clone)] pub struct SubstrateHeadersToSubstrate { diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index d72e032da911b..e7fe68a5c0112 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -18,12 +18,14 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. +use crate::headers_pipeline::SubstrateHeadersSyncPipeline; + use async_trait::async_trait; use codec::{Decode, Encode}; use futures::TryFutureExt; use headers_relay::{ sync_loop::TargetClient, - sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, + sync_types::{HeaderIdOf, QueuedHeader, SubmittedHeaders}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_utils::HeaderId; @@ -31,35 +33,6 @@ use sp_core::Bytes; use sp_runtime::Justification; use std::collections::HashSet; -/// Headers sync pipeline for Substrate <-> Substrate relays. -#[async_trait] -pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { - /// Name of the `best_block` runtime method. - const BEST_BLOCK_METHOD: &'static str; - /// Name of the `finalized_block` runtime method. - const FINALIZED_BLOCK_METHOD: &'static str; - /// Name of the `is_known_block` runtime method. - const IS_KNOWN_BLOCK_METHOD: &'static str; - /// Name of the `incomplete_headers` runtime method. - const INCOMPLETE_HEADERS_METHOD: &'static str; - - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make submit header transaction. - async fn make_submit_header_transaction( - &self, - header: QueuedHeader, - ) -> Result; - - /// Make completion transaction for the header. - async fn make_complete_header_transaction( - &self, - id: HeaderIdOf, - completion: Justification, - ) -> Result; -} - /// Substrate client as Substrate headers target. pub struct SubstrateHeadersTarget { client: Client, diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 52d09a3dc5e7f..de8d362a8b8af 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -37,6 +37,7 @@ mod headers_initialize; mod headers_maintain; mod headers_pipeline; mod headers_target; +mod messages_lane; mod messages_source; mod messages_target; mod millau_headers_to_rialto; diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs new file mode 100644 index 0000000000000..3d1e12323ccbe --- /dev/null +++ b/relays/substrate/src/messages_lane.rs @@ -0,0 +1,63 @@ +// Copyright 2019-2020 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 . + +use async_trait::async_trait; +use bp_message_lane::MessageNonce; +use codec::Encode; +use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; +use relay_substrate_client::Error as SubstrateError; +use std::ops::RangeInclusive; + +/// Message sync pipeline for Substrate <-> Substrate relays. +#[async_trait] +pub trait SubstrateMessageLane: MessageLane { + /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. + const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str; + /// Name of the runtime method that returns latest generated nonce at the source chain. + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str; + /// Name of the runtime method that returns latest received (confirmed) nonce at the the source chain. + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; + + /// Name of the runtime method that returns latest received nonce at the source chain. + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; + /// Name of the runtime method that returns latest confirmed (reward-paid) nonce at the source chain. + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; + + /// Name of the runtime method that returns id of best finalized source header at target chain. + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; + /// Name of the runtime method that returns id of best finalized target header at source chain. + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str; + + /// Signed transaction type of the source chain. + type SourceSignedTransaction: Send + Sync + Encode; + /// Signed transaction type of the target chain. + type TargetSignedTransaction: Send + Sync + Encode; + + /// Make messages delivery transaction. + async fn make_messages_delivery_transaction( + &self, + generated_at_header: SourceHeaderIdOf, + nonces: RangeInclusive, + proof: Self::MessagesProof, + ) -> Result; + + /// Make messages receiving proof transaction. + async fn make_messages_receiving_proof_transaction( + &self, + generated_at_header: TargetHeaderIdOf, + proof: Self::MessagesReceivingProof, + ) -> Result; +} diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index ad82d252439e9..412fac2e356d5 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -18,13 +18,15 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. +use crate::messages_lane::SubstrateMessageLane; + use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::{Decode, Encode}; use frame_support::weights::Weight; use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ClientState, MessageProofParameters, MessageWeightsMap, SourceClient, SourceClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; @@ -32,7 +34,7 @@ use relay_utils::{BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; -use std::{marker::PhantomData, ops::RangeInclusive}; +use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and @@ -40,68 +42,50 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, (HashOf, StorageProof, LaneId, MessageNonce, MessageNonce)); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, - tx_maker: M, - lane: LaneId, + lane: P, + lane_id: LaneId, instance: InstanceId, - _marker: PhantomData

, } -/// Substrate transactions maker. -#[async_trait] -pub trait SubstrateTransactionMaker: Clone + Send + Sync { - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make messages receiving proof transaction. - async fn make_messages_receiving_proof_transaction( - &self, - generated_at_block: TargetHeaderIdOf

, - proof: P::MessagesReceivingProof, - ) -> Result; -} - -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. - pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self { + pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { SubstrateMessagesSource { client, - tx_maker, lane, + lane_id, instance, - _marker: Default::default(), } } } -impl Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), - tx_maker: self.tx_maker.clone(), - lane: self.lane, + lane: self.lane.clone(), + lane_id: self.lane_id, instance: self.instance, - _marker: Default::default(), } } } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient

for SubstrateMessagesSource where C: Chain, C::Header: DeserializeOwned, C::Index: DeserializeOwned, C::BlockNumber: BlockNumberBase, - P: MessageLane< + P: SubstrateMessageLane< MessagesProof = SubstrateMessagesProof, SourceHeaderNumber = ::Number, SourceHeaderHash = ::Hash, >, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, - M: SubstrateTransactionMaker, { type Error = SubstrateError; @@ -112,7 +96,11 @@ where } async fn state(&self) -> Result, Self::Error> { - read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>(&self.client, P::TARGET_NAME).await + read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>( + &self.client, + P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE, + ) + .await } async fn latest_generated_nonce( @@ -122,9 +110,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_latest_generated_nonce".into(), - Bytes(self.lane.encode()), + P::OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -140,9 +127,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_latest_received_nonce".into(), - Bytes(self.lane.encode()), + P::OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -159,9 +145,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_messages_dispatch_weight".into(), - Bytes((self.lane, nonces.start(), nonces.end()).encode()), + P::OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD.into(), + Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Some(id.1), ) .await?; @@ -194,13 +179,13 @@ where .client .prove_messages( self.instance, - self.lane, + self.lane_id, nonces.clone(), proof_parameters.outbound_state_proof_required, id.1, ) .await?; - let proof = (id.1, proof, self.lane, *nonces.start(), *nonces.end()); + let proof = (id.1, proof, self.lane_id, *nonces.start(), *nonces.end()); Ok((id, nonces, (proof_parameters.dispatch_weight, proof))) } @@ -210,7 +195,7 @@ where proof: P::MessagesReceivingProof, ) -> Result<(), Self::Error> { let tx = self - .tx_maker + .lane .make_messages_receiving_proof_transaction(generated_at_block, proof) .await?; self.client.submit_extrinsic(Bytes(tx.encode())).await?; @@ -220,7 +205,7 @@ where pub async fn read_client_state( self_client: &Client, - bridged_chain_name: &str, + best_finalized_header_id_method_name: &str, ) -> Result, HeaderId>, SubstrateError> where SelfChain: Chain, @@ -240,10 +225,9 @@ where let self_best_id = HeaderId(*self_best_header.number(), self_best_hash); // now let's read id of best finalized peer header at our best finalized block - let best_finalized_peer_on_self_method = format!("{}HeaderApi_finalized_block", bridged_chain_name); let encoded_best_finalized_peer_on_self = self_client .state_call( - best_finalized_peer_on_self_method, + best_finalized_header_id_method_name.into(), Bytes(Vec::new()), Some(self_best_hash), ) diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 4ad61caf20e80..c42b2fc6849bf 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -18,6 +18,7 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. +use crate::messages_lane::SubstrateMessageLane; use crate::messages_source::read_client_state; use async_trait::async_trait; @@ -25,7 +26,7 @@ use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::{Decode, Encode}; use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; @@ -33,72 +34,53 @@ use relay_utils::BlockNumberBase; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; -use std::{marker::PhantomData, ops::RangeInclusive}; +use std::ops::RangeInclusive; /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, - tx_maker: M, - lane: LaneId, + lane: P, + lane_id: LaneId, instance: InstanceId, - _marker: PhantomData

, } -/// Substrate transactions maker. -#[async_trait] -pub trait SubstrateTransactionMaker: Clone + Send + Sync { - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make messages delivery transaction. - async fn make_messages_delivery_transaction( - &self, - generated_at_header: SourceHeaderIdOf

, - nonces: RangeInclusive, - proof: P::MessagesProof, - ) -> Result; -} - -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. - pub fn new(client: Client, tx_maker: M, lane: LaneId, instance: InstanceId) -> Self { + pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { SubstrateMessagesTarget { client, - tx_maker, lane, + lane_id, instance, - _marker: Default::default(), } } } -impl Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), - tx_maker: self.tx_maker.clone(), - lane: self.lane, + lane: self.lane.clone(), + lane_id: self.lane_id, instance: self.instance, - _marker: Default::default(), } } } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient

for SubstrateMessagesTarget where C: Chain, C::Header: DeserializeOwned, C::Index: DeserializeOwned, ::Number: BlockNumberBase, - P: MessageLane< + P: SubstrateMessageLane< MessagesReceivingProof = (HashOf, StorageProof, LaneId), TargetHeaderNumber = ::Number, TargetHeaderHash = ::Hash, >, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, - M: SubstrateTransactionMaker, { type Error = SubstrateError; @@ -109,7 +91,11 @@ where } async fn state(&self) -> Result, Self::Error> { - read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>(&self.client, P::SOURCE_NAME).await + read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>( + &self.client, + P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, + ) + .await } async fn latest_received_nonce( @@ -119,9 +105,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "InboundLaneApi_latest_received_nonce".into(), - Bytes(self.lane.encode()), + P::INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -137,9 +122,8 @@ where let encoded_response = self .client .state_call( - // TODO: https://github.com/paritytech/parity-bridges-common/issues/457 - "OutboundLaneApi_latest_received_nonce".into(), - Bytes(self.lane.encode()), + P::INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD.into(), + Bytes(self.lane_id.encode()), Some(id.1), ) .await?; @@ -154,9 +138,9 @@ where ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error> { let proof = self .client - .prove_messages_delivery(self.instance, self.lane, id.1) + .prove_messages_delivery(self.instance, self.lane_id, id.1) .await?; - let proof = (id.1, proof, self.lane); + let proof = (id.1, proof, self.lane_id); Ok((id, proof)) } @@ -167,7 +151,7 @@ where proof: P::MessagesProof, ) -> Result, Self::Error> { let tx = self - .tx_maker + .lane .make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof) .await?; self.client.submit_extrinsic(Bytes(tx.encode())).await?; diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index a07138e019367..714a6c22f5e61 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -17,8 +17,8 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::{ - headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, - RialtoClient, + headers_pipeline::{SubstrateHeadersSyncPipeline, SubstrateHeadersToSubstrate}, + MillauClient, RialtoClient, }; use async_trait::async_trait; diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 81017f6745fbd..17d7b10189efd 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -16,8 +16,9 @@ //! Millau-to-Rialto messages sync entrypoint. -use crate::messages_source::{SubstrateMessagesSource, SubstrateTransactionMaker as SubstrateSourceTransactionMaker}; -use crate::messages_target::{SubstrateMessagesTarget, SubstrateTransactionMaker as SubstrateTargetTransactionMaker}; +use crate::messages_lane::SubstrateMessageLane; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; @@ -45,8 +46,14 @@ type FromMillauMessagesProof = ( type FromRialtoMessagesReceivingProof = (HashOf, StorageProof, LaneId); /// Millau-to-Rialto messages pipeline. -#[derive(Debug, Clone, Copy)] -struct MillauMessagesToRialto; +#[derive(Debug, Clone)] +struct MillauMessagesToRialto { + millau_client: MillauClient, + millau_sign: MillauSigningParams, + rialto_client: RialtoClient, + rialto_sign: RialtoSigningParams, + relayer_id: bp_millau::AccountId, +} impl MessageLane for MillauMessagesToRialto { const SOURCE_NAME: &'static str = "Millau"; @@ -62,72 +69,66 @@ impl MessageLane for MillauMessagesToRialto { type TargetHeaderHash = HashOf; } -/// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; +#[async_trait] +impl SubstrateMessageLane for MillauMessagesToRialto { + const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = + bp_rialto::TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; -/// Millau transaction maker. -#[derive(Clone)] -struct MillauTransactionMaker { - client: MillauClient, - sign: MillauSigningParams, -} + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; -#[async_trait] -impl SubstrateSourceTransactionMaker for MillauTransactionMaker { - type SignedTransaction = ::SignedTransaction; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; + + type SourceSignedTransaction = ::SignedTransaction; + type TargetSignedTransaction = ::SignedTransaction; async fn make_messages_receiving_proof_transaction( &self, _generated_at_block: RialtoHeaderId, proof: FromRialtoMessagesReceivingProof, - ) -> Result { - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + ) -> Result { + let account_id = self.millau_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.millau_client.next_account_index(account_id).await?; let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); - let transaction = Millau::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Millau::sign_transaction(&self.millau_client, &self.millau_sign.signer, nonce, call); Ok(transaction) } -} - -/// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; - -/// Rialto transaction maker. -#[derive(Clone)] -struct RialtoTransactionMaker { - client: RialtoClient, - relayer_id: bp_millau::AccountId, - sign: RialtoSigningParams, -} - -#[async_trait] -impl SubstrateTargetTransactionMaker for RialtoTransactionMaker { - type SignedTransaction = ::SignedTransaction; async fn make_messages_delivery_transaction( &self, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, proof: FromMillauMessagesProof, - ) -> Result { + ) -> Result { let (dispatch_weight, proof) = proof; - let account_id = self.sign.signer.public().as_array_ref().clone().into(); - let nonce = self.client.next_account_index(account_id).await?; + let account_id = self.rialto_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.rialto_client.next_account_index(account_id).await?; let call = rialto_runtime::MessageLaneCall::receive_messages_proof(self.relayer_id.clone(), proof, dispatch_weight) .into(); - let transaction = Rialto::sign_transaction(&self.client, &self.sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(&self.rialto_client, &self.rialto_sign.signer, nonce, call); Ok(transaction) } } +/// Millau node as messages source. +type MillauSourceClient = SubstrateMessagesSource; + +/// Rialto node as messages target. +type RialtoTargetClient = SubstrateMessagesTarget; + /// Run Millau-to-Rialto messages sync. pub fn run( millau_client: MillauClient, millau_sign: MillauSigningParams, rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, - lane: LaneId, + lane_id: LaneId, metrics_params: Option, ) { let millau_tick = Duration::from_secs(5); @@ -136,9 +137,17 @@ pub fn run( let stall_timeout = Duration::from_secs(5 * 60); let relayer_id = millau_sign.signer.public().as_array_ref().clone().into(); + let lane = MillauMessagesToRialto { + millau_client: millau_client.clone(), + millau_sign, + rialto_client: rialto_client.clone(), + rialto_sign, + relayer_id, + }; + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { - lane, + lane: lane_id, source_tick: millau_tick, target_tick: rialto_tick, reconnect_delay, @@ -150,25 +159,8 @@ pub fn run( max_messages_weight_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT, }, }, - MillauSourceClient::new( - millau_client.clone(), - MillauTransactionMaker { - client: millau_client, - sign: millau_sign, - }, - lane, - RIALTO_BRIDGE_INSTANCE, - ), - RialtoTargetClient::new( - rialto_client.clone(), - RialtoTransactionMaker { - client: rialto_client, - relayer_id, - sign: rialto_sign, - }, - lane, - MILLAU_BRIDGE_INSTANCE, - ), + MillauSourceClient::new(millau_client, lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), + RialtoTargetClient::new(rialto_client, lane, lane_id, MILLAU_BRIDGE_INSTANCE), metrics_params, futures::future::pending(), ); diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index f458e291244d4..92a141654c503 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -17,8 +17,8 @@ //! Rialto-to-Millau headers sync entrypoint. use crate::{ - headers_pipeline::SubstrateHeadersToSubstrate, headers_target::SubstrateHeadersSyncPipeline, MillauClient, - RialtoClient, + headers_pipeline::{SubstrateHeadersSyncPipeline, SubstrateHeadersToSubstrate}, + MillauClient, RialtoClient, }; use async_trait::async_trait; From f433645340677530d18c4f213ba4b13c64544bf6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 23 Nov 2020 11:25:02 +0300 Subject: [PATCH 0238/1210] Millau -> Rialto messages relay dashboard (#520) --- relays/messages-relay/src/message_lane_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index d7e3778ff55b0..79f4a9493c62e 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -207,7 +207,7 @@ pub fn run( let metrics_enabled = metrics_params.is_some(); metrics_start( format!( - "{}_to_{}_MessageLoop/{}", + "{}_to_{}_MessageLane_{}", P::SOURCE_NAME, P::TARGET_NAME, hex::encode(params.lane) From 18498ad14344999dd1a376d8ff313bd2ed47e9ba Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 16:56:42 +0100 Subject: [PATCH 0239/1210] Bump futures from 0.3.7 to 0.3.8 (#507) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump futures from 0.3.7 to 0.3.8 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.7 to 0.3.8. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.7...0.3.8) Signed-off-by: dependabot-preview[bot] * Fix clippy. * Fix more clippy. * Fix clippy again? * Cliipy yet again. Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Tomasz Drwięga --- relays/ethereum/Cargo.toml | 2 +- relays/headers-relay/src/sync_loop.rs | 23 ++++++++++--------- .../messages-relay/src/message_lane_loop.rs | 4 ++-- .../messages-relay/src/message_race_loop.rs | 8 +++---- relays/substrate/Cargo.toml | 2 +- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 816b1af14a2b3..69e9e010d8509 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ env_logger = "0.8.2" ethabi = "12.0" ethabi-contract = "11.0" ethabi-derive = "12.0" -futures = "0.3.7" +futures = "0.3.8" hex = "0.4" hex-literal = "0.3" log = "0.4.11" diff --git a/relays/headers-relay/src/sync_loop.rs b/relays/headers-relay/src/sync_loop.rs index 4a09e3518df96..15f982af768ad 100644 --- a/relays/headers-relay/src/sync_loop.rs +++ b/relays/headers-relay/src/sync_loop.rs @@ -126,6 +126,7 @@ pub fn run>( metrics_params: Option, exit_signal: impl Future, ) { + #![allow(unused_variables)] // this is to suppress weird errors from clippy let mut local_pool = futures::executor::LocalPool::new(); let mut progress_context = (Instant::now(), None, None); @@ -203,7 +204,7 @@ pub fn run>( &mut source_retry_backoff, |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving best header number from {}", P::SOURCE_NAME), ).is_ok(); }, @@ -213,7 +214,7 @@ pub fn run>( &mut source_retry_backoff, |source_new_header| sync.headers_mut().header_response(source_new_header), &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving header from {} node", P::SOURCE_NAME), ).is_ok(); }, @@ -223,7 +224,7 @@ pub fn run>( &mut source_retry_backoff, |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), ).is_ok(); }, @@ -233,7 +234,7 @@ pub fn run>( &mut source_retry_backoff, |(header, extra)| sync.headers_mut().extra_response(&header, extra), &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), ).is_ok(); }, @@ -243,7 +244,7 @@ pub fn run>( &mut source_retry_backoff, |(header, completion)| sync.headers_mut().completion_response(&header, completion), &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), ).is_ok(); }, @@ -294,7 +295,7 @@ pub fn run>( } }, &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving best known {} header from {} node", P::SOURCE_NAME, P::TARGET_NAME), ).is_ok(); }, @@ -306,7 +307,7 @@ pub fn run>( &mut target_retry_backoff, |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), ).is_ok(); }, @@ -318,7 +319,7 @@ pub fn run>( .headers_mut() .maybe_orphan_response(&target_header, target_existence_status), &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving existence status from {} node", P::TARGET_NAME), ).is_ok(); }, @@ -346,7 +347,7 @@ pub fn run>( &mut target_retry_backoff, |_| {}, &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error submitting headers to {} node", P::TARGET_NAME), ).is_ok(); @@ -367,7 +368,7 @@ pub fn run>( &mut target_retry_backoff, |completed_header| sync.headers_mut().header_completed(&completed_header), &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error completing headers at {}", P::TARGET_NAME), ).is_ok(); }, @@ -379,7 +380,7 @@ pub fn run>( .headers_mut() .maybe_extra_response(&header, extra_check_result), &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), ).is_ok(); }, diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index 79f4a9493c62e..8278f8c3ec64c 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -374,7 +374,7 @@ async fn run_until_connection_lost, TC: Targ } }, &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving state from {} node", P::SOURCE_NAME), ).fail_if_connection_error(FailedClient::Source)?; }, @@ -405,7 +405,7 @@ async fn run_until_connection_lost, TC: Targ } }, &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving state from {} node", P::TARGET_NAME), ).fail_if_connection_error(FailedClient::Target)?; }, diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 5db54fbecfd5f..3267ea9dc287d 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -269,7 +269,7 @@ pub async fn run>( strategy.source_nonces_updated(at_block, nonces); }, &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving nonces from {}", P::source_name()), ).fail_if_connection_error(FailedClient::Source)?; }, @@ -290,7 +290,7 @@ pub async fn run>( strategy.target_nonces_updated(nonces, &mut race_state); }, &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error retrieving nonces from {}", P::target_name()), ).fail_if_connection_error(FailedClient::Target)?; }, @@ -311,7 +311,7 @@ pub async fn run>( race_state.nonces_to_submit = Some((at_block, nonces_range, proof)); }, &mut source_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error generating proof at {}", P::source_name()), ).fail_if_connection_error(FailedClient::Source)?; }, @@ -331,7 +331,7 @@ pub async fn run>( race_state.nonces_submitted = Some(nonces_range); }, &mut target_go_offline_future, - |delay| async_std::task::sleep(delay), + async_std::task::sleep, || format!("Error submitting proof {}", P::target_name()), ).fail_if_connection_error(FailedClient::Target)?; } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 66a6aaea50f5f..6cb9847ea2a69 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.7.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } -futures = "0.3.7" +futures = "0.3.8" hex = "0.4" log = "0.4.11" num-traits = "0.2" From 35f67adc25015e597100fdd0c662a533fd9a660a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 24 Nov 2020 11:01:28 +0300 Subject: [PATCH 0240/1210] Ability to send messages from Rialto to Millau (#525) * relay Rialto messages to Millau * impl SubmitRialtoToMillauMessage * fmt --- bin/millau/runtime/src/lib.rs | 1 + relays/substrate/src/cli.rs | 42 ++++++ relays/substrate/src/main.rs | 117 ++++++++++++++- relays/substrate/src/messages_lane.rs | 56 +++++++- relays/substrate/src/messages_target.rs | 5 +- .../src/millau_messages_to_rialto.rs | 85 ++++------- .../src/rialto_messages_to_millau.rs | 134 ++++++++++++++++++ 7 files changed, 378 insertions(+), 62 deletions(-) create mode 100644 relays/substrate/src/rialto_messages_to_millau.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 01c81a5582607..55519b46382bf 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -54,6 +54,7 @@ pub use frame_support::{ StorageValue, }; +pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeRialtoCall; diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 2b622c362be04..0119359cde223 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -108,6 +108,40 @@ pub enum Command { #[structopt(long)] fee: bp_millau::Balance, }, + /// Serve given lane of Rialto -> Millau messages. + RialtoMessagesToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + /// Hex-encoded id of lane that should be served by relay. + #[structopt(long)] + lane: HexLaneId, + }, + /// Submit message to given Rialto -> Millau lane. + SubmitRialtoToMillauMessage { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + /// Hex-encoded lane id. + #[structopt(long)] + lane: HexLaneId, + /// Message type. + #[structopt(long, possible_values = &ToMillauMessage::variants())] + message: ToMillauMessage, + /// Delivery and dispatch fee. + #[structopt(long)] + fee: bp_rialto::Balance, + }, } arg_enum! { @@ -118,6 +152,14 @@ arg_enum! { } } +arg_enum! { + #[derive(Debug)] + /// All possible messages that may be delivered to the Millau chain. + pub enum ToMillauMessage { + Remark, + } +} + /// Lane id. #[derive(Debug)] pub struct HexLaneId(LaneId); diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index de8d362a8b8af..7d2f4a6dbfc65 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -43,6 +43,7 @@ mod messages_target; mod millau_headers_to_rialto; mod millau_messages_to_rialto; mod rialto_headers_to_millau; +mod rialto_messages_to_millau; fn main() { initialize_relay(); @@ -287,7 +288,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( lane.into(), MessagePayload { - spec_version: millau_runtime::VERSION.spec_version, + spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, origin: CallOrigin::RealAccount( millau_sender_public, @@ -312,6 +313,120 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .submit_extrinsic(Bytes(signed_millau_call.encode())) .await?; } + cli::Command::RialtoMessagesToMillau { + rialto, + rialto_sign, + millau, + millau_sign, + prometheus_params, + lane, + } => { + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let rialto_sign = RialtoSigningParams::from_suri( + &rialto_sign.rialto_signer, + rialto_sign.rialto_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_client = MillauClient::new(ConnectionParams { + host: millau.millau_host, + port: millau.millau_port, + }) + .await?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + + rialto_messages_to_millau::run( + rialto_client, + rialto_sign, + millau_client, + millau_sign, + lane.into(), + prometheus_params.into(), + ); + } + cli::Command::SubmitRialtoToMillauMessage { + rialto, + rialto_sign, + millau_sign, + lane, + message, + fee, + } => { + let rialto_client = RialtoClient::new(ConnectionParams { + host: rialto.rialto_host, + port: rialto.rialto_port, + }) + .await?; + let rialto_sign = RialtoSigningParams::from_suri( + &rialto_sign.rialto_signer, + rialto_sign.rialto_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_sign = MillauSigningParams::from_suri( + &millau_sign.millau_signer, + millau_sign.millau_signer_password.as_deref(), + ) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + + let millau_call = match message { + cli::ToMillauMessage::Remark => millau_runtime::Call::System(millau_runtime::SystemCall::remark( + format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec(), + )), + }; + let millau_call_weight = millau_call.get_dispatch_info().weight; + + let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let millau_origin_public = millau_sign.signer.public(); + + let mut millau_origin_signature_message = Vec::new(); + millau_call.encode_to(&mut millau_origin_signature_message); + rialto_sender_public.encode_to(&mut millau_origin_signature_message); + let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); + + let rialto_call = + rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( + lane.into(), + MessagePayload { + spec_version: millau_runtime::VERSION.spec_version, + weight: millau_call_weight, + origin: CallOrigin::RealAccount( + rialto_sender_public, + millau_origin_public.into(), + millau_origin_signature.into(), + ), + call: millau_call.encode(), + }, + fee, + )); + + let signed_rialto_call = Rialto::sign_transaction( + &rialto_client, + &rialto_sign.signer, + rialto_client + .next_account_index(rialto_sign.signer.public().clone().into()) + .await?, + rialto_call, + ); + + rialto_client + .submit_extrinsic(Bytes(signed_rialto_call.encode())) + .await?; + } } Ok(()) diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs index 3d1e12323ccbe..2ee69feb97186 100644 --- a/relays/substrate/src/messages_lane.rs +++ b/relays/substrate/src/messages_lane.rs @@ -14,11 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::messages_source::SubstrateMessagesProof; +use crate::messages_target::SubstrateMessagesReceivingProof; + use async_trait::async_trait; use bp_message_lane::MessageNonce; use codec::Encode; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use relay_substrate_client::Error as SubstrateError; +use relay_substrate_client::{BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; +use relay_utils::BlockNumberBase; use std::ops::RangeInclusive; /// Message sync pipeline for Substrate <-> Substrate relays. @@ -61,3 +65,53 @@ pub trait SubstrateMessageLane: MessageLane { proof: Self::MessagesReceivingProof, ) -> Result; } + +/// Substrate-to-Substrate message lane. +#[derive(Debug)] +pub struct SubstrateMessageLaneToSubstrate { + /// Client for the source Substrate chain. + pub(crate) source_client: Client, + /// Parameters required to sign transactions for source chain. + pub(crate) source_sign: SourceSignParams, + /// Client for the target Substrate chain. + pub(crate) target_client: Client, + /// Parameters required to sign transactions for target chain. + pub(crate) target_sign: TargetSignParams, + /// Account id of relayer at the source chain. + pub(crate) relayer_id_at_source: Source::AccountId, +} + +impl Clone + for SubstrateMessageLaneToSubstrate +{ + fn clone(&self) -> Self { + Self { + source_client: self.source_client.clone(), + source_sign: self.source_sign.clone(), + target_client: self.target_client.clone(), + target_sign: self.target_sign.clone(), + relayer_id_at_source: self.relayer_id_at_source.clone(), + } + } +} + +impl MessageLane + for SubstrateMessageLaneToSubstrate +where + SourceSignParams: Clone + Send + Sync + 'static, + TargetSignParams: Clone + Send + Sync + 'static, + BlockNumberOf: BlockNumberBase, + BlockNumberOf: BlockNumberBase, +{ + const SOURCE_NAME: &'static str = Source::NAME; + const TARGET_NAME: &'static str = Target::NAME; + + type MessagesProof = SubstrateMessagesProof; + type MessagesReceivingProof = SubstrateMessagesReceivingProof; + + type SourceHeaderNumber = BlockNumberOf; + type SourceHeaderHash = HashOf; + + type TargetHeaderNumber = BlockNumberOf; + type TargetHeaderHash = HashOf; +} diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index c42b2fc6849bf..3825a41578824 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -36,6 +36,9 @@ use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; use std::ops::RangeInclusive; +/// Message receiving proof returned by the target Substrate node. +pub type SubstrateMessagesReceivingProof = (HashOf, StorageProof, LaneId); + /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { client: Client, @@ -75,7 +78,7 @@ where C::Index: DeserializeOwned, ::Number: BlockNumberBase, P: SubstrateMessageLane< - MessagesReceivingProof = (HashOf, StorageProof, LaneId), + MessagesReceivingProof = SubstrateMessagesReceivingProof, TargetHeaderNumber = ::Number, TargetHeaderHash = ::Hash, >, diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 17d7b10189efd..132d43813bcad 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -16,7 +16,7 @@ //! Millau-to-Rialto messages sync entrypoint. -use crate::messages_lane::SubstrateMessageLane; +use crate::messages_lane::{SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use crate::{MillauClient, RialtoClient}; @@ -24,50 +24,16 @@ use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; -use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{BlockNumberOf, Error as SubstrateError, HashOf, TransactionSignScheme}; +use relay_substrate_client::{Chain, Error as SubstrateError, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use sp_core::Pair; -use sp_trie::StorageProof; use std::{ops::RangeInclusive, time::Duration}; -/// Millau -> Rialto messages proof: -/// -/// - cumulative dispatch-weight of messages in the batch; -/// - proof that we'll actually submit to the Rialto node. -type FromMillauMessagesProof = ( - Weight, - (HashOf, StorageProof, LaneId, MessageNonce, MessageNonce), -); -/// Rialto -> Millau messages receiving proof. -type FromRialtoMessagesReceivingProof = (HashOf, StorageProof, LaneId); - -/// Millau-to-Rialto messages pipeline. -#[derive(Debug, Clone)] -struct MillauMessagesToRialto { - millau_client: MillauClient, - millau_sign: MillauSigningParams, - rialto_client: RialtoClient, - rialto_sign: RialtoSigningParams, - relayer_id: bp_millau::AccountId, -} - -impl MessageLane for MillauMessagesToRialto { - const SOURCE_NAME: &'static str = "Millau"; - const TARGET_NAME: &'static str = "Rialto"; - - type MessagesProof = FromMillauMessagesProof; - type MessagesReceivingProof = FromRialtoMessagesReceivingProof; - - type SourceHeaderNumber = BlockNumberOf; - type SourceHeaderHash = HashOf; - - type TargetHeaderNumber = BlockNumberOf; - type TargetHeaderHash = HashOf; -} +/// Millau-to-Rialto message lane. +type MillauMessagesToRialto = SubstrateMessageLaneToSubstrate; #[async_trait] impl SubstrateMessageLane for MillauMessagesToRialto { @@ -90,12 +56,12 @@ impl SubstrateMessageLane for MillauMessagesToRialto { async fn make_messages_receiving_proof_transaction( &self, _generated_at_block: RialtoHeaderId, - proof: FromRialtoMessagesReceivingProof, + proof: ::MessagesReceivingProof, ) -> Result { - let account_id = self.millau_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.millau_client.next_account_index(account_id).await?; + let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.source_client.next_account_index(account_id).await?; let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); - let transaction = Millau::sign_transaction(&self.millau_client, &self.millau_sign.signer, nonce, call); + let transaction = Millau::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); Ok(transaction) } @@ -103,15 +69,18 @@ impl SubstrateMessageLane for MillauMessagesToRialto { &self, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, - proof: FromMillauMessagesProof, + proof: ::MessagesProof, ) -> Result { let (dispatch_weight, proof) = proof; - let account_id = self.rialto_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.rialto_client.next_account_index(account_id).await?; - let call = - rialto_runtime::MessageLaneCall::receive_messages_proof(self.relayer_id.clone(), proof, dispatch_weight) - .into(); - let transaction = Rialto::sign_transaction(&self.rialto_client, &self.rialto_sign.signer, nonce, call); + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + let call = rialto_runtime::MessageLaneCall::receive_messages_proof( + self.relayer_id_at_source.clone(), + proof, + dispatch_weight, + ) + .into(); + let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } } @@ -131,25 +100,23 @@ pub fn run( lane_id: LaneId, metrics_params: Option, ) { - let millau_tick = Duration::from_secs(5); - let rialto_tick = Duration::from_secs(5); let reconnect_delay = Duration::from_secs(10); let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id = millau_sign.signer.public().as_array_ref().clone().into(); + let relayer_id_at_millau = millau_sign.signer.public().as_array_ref().clone().into(); let lane = MillauMessagesToRialto { - millau_client: millau_client.clone(), - millau_sign, - rialto_client: rialto_client.clone(), - rialto_sign, - relayer_id, + source_client: millau_client.clone(), + source_sign: millau_sign, + target_client: rialto_client.clone(), + target_sign: rialto_sign, + relayer_id_at_source: relayer_id_at_millau, }; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, - source_tick: millau_tick, - target_tick: rialto_tick, + source_tick: Millau::AVERAGE_BLOCK_INTERVAL, + target_tick: Rialto::AVERAGE_BLOCK_INTERVAL, reconnect_delay, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs new file mode 100644 index 0000000000000..f772973728a81 --- /dev/null +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -0,0 +1,134 @@ +// Copyright 2019-2020 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 . + +//! Rialto-to-Millau messages sync entrypoint. + +use crate::messages_lane::{SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; +use crate::{MillauClient, RialtoClient}; + +use async_trait::async_trait; +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; +use messages_relay::message_lane::MessageLane; +use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{Chain, Error as SubstrateError, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; +use std::{ops::RangeInclusive, time::Duration}; + +/// Rialto-to-Millau message lane. +type RialtoMessagesToMillau = SubstrateMessageLaneToSubstrate; + +#[async_trait] +impl SubstrateMessageLane for RialtoMessagesToMillau { + const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = + bp_millau::TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; + + type SourceSignedTransaction = ::SignedTransaction; + type TargetSignedTransaction = ::SignedTransaction; + + async fn make_messages_receiving_proof_transaction( + &self, + _generated_at_block: MillauHeaderId, + proof: ::MessagesReceivingProof, + ) -> Result { + let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.source_client.next_account_index(account_id).await?; + let call = rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); + let transaction = Rialto::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); + Ok(transaction) + } + + async fn make_messages_delivery_transaction( + &self, + _generated_at_header: RialtoHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Result { + let (dispatch_weight, proof) = proof; + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + let call = millau_runtime::MessageLaneCall::receive_messages_proof( + self.relayer_id_at_source.clone(), + proof, + dispatch_weight, + ) + .into(); + let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + Ok(transaction) + } +} + +/// Rialto node as messages source. +type RialtoSourceClient = SubstrateMessagesSource; + +/// Millau node as messages target. +type MillauTargetClient = SubstrateMessagesTarget; + +/// Run Rialto-to-Millau messages sync. +pub fn run( + rialto_client: RialtoClient, + rialto_sign: RialtoSigningParams, + millau_client: MillauClient, + millau_sign: MillauSigningParams, + lane_id: LaneId, + metrics_params: Option, +) { + let reconnect_delay = Duration::from_secs(10); + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_rialto = rialto_sign.signer.public().as_array_ref().clone().into(); + + let lane = RialtoMessagesToMillau { + source_client: rialto_client.clone(), + source_sign: rialto_sign, + target_client: millau_client.clone(), + target_sign: millau_sign, + relayer_id_at_source: relayer_id_at_rialto, + }; + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Rialto::AVERAGE_BLOCK_INTERVAL, + target_tick: Millau::AVERAGE_BLOCK_INTERVAL, + reconnect_delay, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + // TODO: subtract base weight of delivery from this when it'll be known + // https://github.com/paritytech/parity-bridges-common/issues/78 + max_messages_weight_in_single_batch: bp_millau::MAXIMUM_EXTRINSIC_WEIGHT, + }, + }, + RialtoSourceClient::new(rialto_client, lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), + MillauTargetClient::new(millau_client, lane, lane_id, RIALTO_BRIDGE_INSTANCE), + metrics_params, + futures::future::pending(), + ); +} From 14edd79553cc34ed74c4dee80dbfc5f58327f2b4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 24 Nov 2020 19:27:23 +0300 Subject: [PATCH 0241/1210] added more relay and message-lane pallet logs (#527) --- modules/message-lane/src/instant_payments.rs | 12 +++++++++--- relays/substrate/src/headers_pipeline.rs | 7 +++++++ relays/substrate/src/millau_messages_to_rialto.rs | 6 ++++++ relays/substrate/src/rialto_messages_to_millau.rs | 6 ++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index 3c11d263cebb4..7db2429e07f10 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -56,14 +56,20 @@ where ); // we can't actually do anything here, because rewards are paid as a part of unrelated transaction - if let Err(error) = pay_result { - frame_support::debug::trace!( + match pay_result { + Ok(_) => frame_support::debug::trace!( + target: "runtime", + "Rewarded relayer {:?} with {:?}", + relayer, + reward, + ), + Err(error) => frame_support::debug::trace!( target: "runtime", "Failed to pay relayer {:?} reward {:?}: {:?}", relayer, reward, error, - ); + ), } } } diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index a60f8fb0ad64c..8ad6fc50b9527 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -159,6 +159,13 @@ pub async fn run( source_justifications, ); + log::info!( + target: "bridge", + "Starting {} -> {} headers relay", + SourceChain::NAME, + TargetChain::NAME, + ); + headers_relay::sync_loop::run( HeadersSource::new(source_client), SourceChain::AVERAGE_BLOCK_INTERVAL, diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 132d43813bcad..fe0e19fa03f50 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -112,6 +112,12 @@ pub fn run( relayer_id_at_source: relayer_id_at_millau, }; + log::info!( + target: "bridge", + "Starting Millau -> Rialto messages relay. Millau relayer account id: {:?}", + lane.relayer_id_at_source, + ); + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index f772973728a81..1fc724921db10 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -112,6 +112,12 @@ pub fn run( relayer_id_at_source: relayer_id_at_rialto, }; + log::info!( + target: "bridge", + "Starting Rialto -> Millau messages relay. Rialto relayer account id: {:?}", + lane.relayer_id_at_source, + ); + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, From 4f445ac780b528ff79a4874ce2480e912af7acfa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 24 Nov 2020 22:39:21 +0300 Subject: [PATCH 0242/1210] Migrate back to Substrate master (#528) * migrate back to Substrate master * fmt * clippy --- bin/millau/node/Cargo.toml | 42 +++++----- bin/millau/node/src/command.rs | 8 +- bin/millau/node/src/service.rs | 83 ++++++++++---------- bin/millau/runtime/Cargo.toml | 50 ++++++------ bin/millau/runtime/src/lib.rs | 3 +- bin/rialto/node/Cargo.toml | 42 +++++----- bin/rialto/node/src/command.rs | 8 +- bin/rialto/node/src/service.rs | 83 ++++++++++---------- bin/rialto/runtime/Cargo.toml | 54 ++++++------- bin/rialto/runtime/src/lib.rs | 3 +- bin/runtime-common/Cargo.toml | 8 +- modules/call-dispatch/Cargo.toml | 12 +-- modules/call-dispatch/src/lib.rs | 4 +- modules/currency-exchange/Cargo.toml | 14 ++-- modules/ethereum-contract/builtin/Cargo.toml | 10 +-- modules/ethereum/Cargo.toml | 12 +-- modules/message-lane/Cargo.toml | 12 +-- modules/message-lane/rpc/Cargo.toml | 18 ++--- modules/shift-session-manager/Cargo.toml | 14 ++-- modules/substrate/Cargo.toml | 20 ++--- primitives/currency-exchange/Cargo.toml | 6 +- primitives/ethereum-poa/Cargo.toml | 8 +- primitives/message-lane/Cargo.toml | 4 +- primitives/millau/Cargo.toml | 14 ++-- primitives/rialto/Cargo.toml | 10 +-- primitives/runtime/Cargo.toml | 8 +- relays/ethereum/Cargo.toml | 12 +-- relays/millau-client/Cargo.toml | 12 +-- relays/rialto-client/Cargo.toml | 12 +-- relays/substrate-client/Cargo.toml | 16 ++-- relays/substrate/Cargo.toml | 10 +-- relays/utils/Cargo.toml | 2 +- 32 files changed, 307 insertions(+), 307 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 7af2f6febda85..254dc4d275091 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -23,30 +23,30 @@ pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } # Substrate Dependencies -frame-benchmarking = "2.0" -frame-benchmarking-cli = "2.0" -sc-basic-authorship = "0.8" -sc-cli = "0.8" -sc-client-api = "2.0" -sc-consensus = "0.8" -sc-consensus-aura = "0.8" -sc-executor = "0.8" -sc-finality-grandpa = "0.8" -sc-finality-grandpa-rpc = "0.8" -sc-service = "0.8" -sc-rpc = "2.0" -sc-transaction-pool = "2.0" -sp-consensus = "0.8" -sp-consensus-aura = "0.8" -sp-core = "2.0" -sp-inherents = "2.0" -sp-finality-grandpa = "2.0" -sp-runtime = "2.0" -substrate-frame-rpc-system = "2.0" +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [build-dependencies] build-script-utils = { package = "substrate-build-script-utils", version = "2.0" } -frame-benchmarking-cli = "2.0" +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } vergen = "3.1.0" [features] diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index fcd107d1ee009..651080bbf200e 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -152,9 +152,11 @@ pub fn run() -> sc_cli::Result<()> { } None => { let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), + runner.run_node_until_exit(|config| async move { + match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + } }) } } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 04ad152b37b07..10e613f5964aa 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -28,16 +28,13 @@ // ===================================================================================== // ===================================================================================== -use bp_message_lane::{LaneId, MessageNonce}; -use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; +use sc_finality_grandpa::SharedVoterState; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use sp_core::storage::StorageKey; use sp_inherents::InherentDataProviders; use std::sync::Arc; use std::time::Duration; @@ -65,7 +62,12 @@ pub fn new_partial( sp_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport, + sc_consensus_aura::AuraBlockImport< + Block, + FullClient, + sc_finality_grandpa::GrandpaBlockImport, + AuraPair, + >, sc_finality_grandpa::LinkHalf, ), >, @@ -73,7 +75,8 @@ pub fn new_partial( > { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore, task_manager) = sc_service::new_full_parts::(&config)?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::(&config)?; let client = Arc::new(client); let select_chain = sc_consensus::LongestChain::new(backend.clone()); @@ -93,9 +96,8 @@ pub fn new_partial( let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import.clone())), - None, + aura_block_import.clone(), + Some(Box::new(grandpa_block_import)), client.clone(), inherent_data_providers.clone(), &task_manager.spawn_handle(), @@ -108,11 +110,11 @@ pub fn new_partial( backend, task_manager, import_queue, - keystore, + keystore_container, select_chain, transaction_pool, inherent_data_providers, - other: (grandpa_block_import, grandpa_link), + other: (aura_block_import, grandpa_link), }) } @@ -123,15 +125,13 @@ pub fn new_full(config: Configuration) -> Result { backend, mut task_manager, import_queue, - keystore, + keystore_container, select_chain, transaction_pool, inherent_data_providers, other: (block_import, grandpa_link), } = new_partial(&config)?; - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -141,8 +141,6 @@ pub fn new_full(config: Configuration) -> Result { import_queue, on_demand: None, block_announce_validator_builder: None, - finality_proof_request_builder: None, - finality_proof_provider: Some(finality_proof_provider), })?; if config.offchain_worker.enabled { @@ -157,12 +155,18 @@ pub fn new_full(config: Configuration) -> Result { let role = config.role.clone(); let force_authoring = config.force_authoring; + let backoff_authoring_blocks: Option<()> = None; let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { + use bp_message_lane::{LaneId, MessageNonce}; + use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; + use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; + use sp_core::storage::StorageKey; + // This struct is here to ease update process. /// Millau runtime from message-lane RPC point of view. @@ -232,7 +236,7 @@ pub fn new_full(config: Configuration) -> Result { sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), - keystore: keystore.clone(), + keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), telemetry_connection_sinks: telemetry_connection_sinks.clone(), @@ -246,21 +250,26 @@ pub fn new_full(config: Configuration) -> Result { })?; if role.is_authority() { - let proposer = - sc_basic_authorship::ProposerFactory::new(client.clone(), transaction_pool, prometheus_registry.as_ref()); + let proposer = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry.as_ref(), + ); let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( + let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _, _>( sc_consensus_aura::slot_duration(&*client)?, client.clone(), select_chain, block_import, proposer, network.clone(), - inherent_data_providers.clone(), + inherent_data_providers, force_authoring, - keystore.clone(), + backoff_authoring_blocks, + keystore_container.sync_keystore(), can_author_with, )?; @@ -272,7 +281,7 @@ pub fn new_full(config: Configuration) -> Result { // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. let keystore = if role.is_authority() { - Some(keystore as sp_core::traits::BareCryptoStorePtr) + Some(keystore_container.sync_keystore()) } else { None }; @@ -298,7 +307,6 @@ pub fn new_full(config: Configuration) -> Result { config: grandpa_config, link: grandpa_link, network, - inherent_data_providers, telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, @@ -311,7 +319,7 @@ pub fn new_full(config: Configuration) -> Result { .spawn_essential_handle() .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); } else { - sc_finality_grandpa::setup_disabled_grandpa(client, &inherent_data_providers, network)?; + sc_finality_grandpa::setup_disabled_grandpa(network)?; } network_starter.start_network(); @@ -320,9 +328,11 @@ pub fn new_full(config: Configuration) -> Result { /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - let (client, backend, keystore, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( config.transaction_pool.clone(), config.prometheus_registry(), @@ -331,20 +341,13 @@ pub fn new_light(config: Configuration) -> Result { on_demand.clone(), )); - let grandpa_block_import = sc_finality_grandpa::light_block_import( - client.clone(), - backend.clone(), - &(client.clone() as Arc<_>), - Arc::new(on_demand.checker().clone()) as Arc<_>, - )?; - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); + let (grandpa_block_import, _) = + sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import, - None, - Some(Box::new(finality_proof_import)), + grandpa_block_import.clone(), + Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), &task_manager.spawn_handle(), @@ -352,8 +355,6 @@ pub fn new_light(config: Configuration) -> Result { sp_consensus::NeverCanAuthor, )?; - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -363,8 +364,6 @@ pub fn new_light(config: Configuration) -> Result { import_queue, on_demand: Some(on_demand.clone()), block_announce_validator_builder: None, - finality_proof_request_builder: Some(finality_proof_request_builder), - finality_proof_provider: Some(finality_proof_provider), })?; if config.offchain_worker.enabled { @@ -386,7 +385,7 @@ pub fn new_light(config: Configuration) -> Result { telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), config, client, - keystore, + keystore: keystore_container.sync_keystore(), backend, network, network_status_sinks, diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 0689bc4fbae44..19794755cf061 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -26,31 +26,31 @@ pallet-substrate-bridge = { path = "../../../modules/substrate", default-feature # Substrate Dependencies -frame-executive = { version = "2.0", default-features = false } -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -frame-system-rpc-runtime-api = { version = "2.0", default-features = false } -pallet-aura = { version = "2.0", default-features = false } -pallet-balances = { version = "2.0", default-features = false } -pallet-grandpa = { version = "2.0", default-features = false } -pallet-randomness-collective-flip = { version = "2.0", default-features = false } -pallet-session = { version = "2.0", default-features = false } -pallet-sudo = { version = "2.0", default-features = false } -pallet-timestamp = { version = "2.0", default-features = false } -pallet-transaction-payment = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } -sp-block-builder = { version = "2.0", default-features = false } -sp-consensus-aura = { version = "0.8", default-features = false } -sp-core = { version = "2.0", default-features = false } -sp-inherents = { version = "2.0", default-features = false } -sp-finality-grandpa = { version = "2.0", default-features = false } -sp-offchain = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-session = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } -sp-transaction-pool = { version = "2.0", default-features = false } -sp-trie = { version = "2.0", default-features = false } -sp-version = { version = "2.0", default-features = false } +frame-executive = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-offchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [build-dependencies] wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2.0.0" } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 55519b46382bf..2949e695ffdef 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -282,8 +282,7 @@ parameter_types! { } impl pallet_transaction_payment::Trait for Runtime { - type Currency = pallet_balances::Module; - type OnTransactionPayment = (); + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index dd905a53a9c27..59e97a64d1eac 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -22,30 +22,30 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies -frame-benchmarking = "2.0" -frame-benchmarking-cli = "2.0" -sc-basic-authorship = "0.8" -sc-cli = "0.8" -sc-client-api = "2.0" -sc-consensus = "0.8" -sc-consensus-aura = "0.8" -sc-executor = "0.8" -sc-finality-grandpa = "0.8" -sc-finality-grandpa-rpc = "0.8" -sc-service = "0.8" -sc-rpc = "2.0" -sc-transaction-pool = "2.0" -sp-consensus = "0.8" -sp-consensus-aura = "0.8" -sp-core = "2.0" -sp-inherents = "2.0" -sp-finality-grandpa = "2.0" -sp-runtime = "2.0" -substrate-frame-rpc-system = "2.0" +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [build-dependencies] build-script-utils = { package = "substrate-build-script-utils", version = "2.0" } -frame-benchmarking-cli = "2.0" +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } vergen = "3.1.0" [features] diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index fb07b77cb0f71..fe423f8803d97 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -152,9 +152,11 @@ pub fn run() -> sc_cli::Result<()> { } None => { let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), + runner.run_node_until_exit(|config| async move { + match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + } }) } } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 1bb6e3b310fed..bd4c587618eb0 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -28,16 +28,13 @@ // ===================================================================================== // ===================================================================================== -use bp_message_lane::{LaneId, MessageNonce}; -use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState}; +use sc_finality_grandpa::SharedVoterState; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use sp_core::storage::StorageKey; use sp_inherents::InherentDataProviders; use std::sync::Arc; use std::time::Duration; @@ -65,7 +62,12 @@ pub fn new_partial( sp_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport, + sc_consensus_aura::AuraBlockImport< + Block, + FullClient, + sc_finality_grandpa::GrandpaBlockImport, + AuraPair, + >, sc_finality_grandpa::LinkHalf, ), >, @@ -73,7 +75,8 @@ pub fn new_partial( > { let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore, task_manager) = sc_service::new_full_parts::(&config)?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::(&config)?; let client = Arc::new(client); let select_chain = sc_consensus::LongestChain::new(backend.clone()); @@ -93,9 +96,8 @@ pub fn new_partial( let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import.clone())), - None, + aura_block_import.clone(), + Some(Box::new(grandpa_block_import)), client.clone(), inherent_data_providers.clone(), &task_manager.spawn_handle(), @@ -108,11 +110,11 @@ pub fn new_partial( backend, task_manager, import_queue, - keystore, + keystore_container, select_chain, transaction_pool, inherent_data_providers, - other: (grandpa_block_import, grandpa_link), + other: (aura_block_import, grandpa_link), }) } @@ -123,15 +125,13 @@ pub fn new_full(config: Configuration) -> Result { backend, mut task_manager, import_queue, - keystore, + keystore_container, select_chain, transaction_pool, inherent_data_providers, other: (block_import, grandpa_link), } = new_partial(&config)?; - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -141,8 +141,6 @@ pub fn new_full(config: Configuration) -> Result { import_queue, on_demand: None, block_announce_validator_builder: None, - finality_proof_request_builder: None, - finality_proof_provider: Some(finality_proof_provider), })?; if config.offchain_worker.enabled { @@ -157,12 +155,18 @@ pub fn new_full(config: Configuration) -> Result { let role = config.role.clone(); let force_authoring = config.force_authoring; + let backoff_authoring_blocks: Option<()> = None; let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { + use bp_message_lane::{LaneId, MessageNonce}; + use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; + use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; + use sp_core::storage::StorageKey; + // This struct is here to ease update process. /// Rialto runtime from message-lane RPC point of view. @@ -231,7 +235,7 @@ pub fn new_full(config: Configuration) -> Result { sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), - keystore: keystore.clone(), + keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), telemetry_connection_sinks: telemetry_connection_sinks.clone(), @@ -245,21 +249,26 @@ pub fn new_full(config: Configuration) -> Result { })?; if role.is_authority() { - let proposer = - sc_basic_authorship::ProposerFactory::new(client.clone(), transaction_pool, prometheus_registry.as_ref()); + let proposer = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry.as_ref(), + ); let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>( + let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _, _>( sc_consensus_aura::slot_duration(&*client)?, client.clone(), select_chain, block_import, proposer, network.clone(), - inherent_data_providers.clone(), + inherent_data_providers, force_authoring, - keystore.clone(), + backoff_authoring_blocks, + keystore_container.sync_keystore(), can_author_with, )?; @@ -271,7 +280,7 @@ pub fn new_full(config: Configuration) -> Result { // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. let keystore = if role.is_authority() { - Some(keystore as sp_core::traits::BareCryptoStorePtr) + Some(keystore_container.sync_keystore()) } else { None }; @@ -297,7 +306,6 @@ pub fn new_full(config: Configuration) -> Result { config: grandpa_config, link: grandpa_link, network, - inherent_data_providers, telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, @@ -310,7 +318,7 @@ pub fn new_full(config: Configuration) -> Result { .spawn_essential_handle() .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); } else { - sc_finality_grandpa::setup_disabled_grandpa(client, &inherent_data_providers, network)?; + sc_finality_grandpa::setup_disabled_grandpa(network)?; } network_starter.start_network(); @@ -319,9 +327,11 @@ pub fn new_full(config: Configuration) -> Result { /// Builds a new service for a light client. pub fn new_light(config: Configuration) -> Result { - let (client, backend, keystore, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; + let select_chain = sc_consensus::LongestChain::new(backend.clone()); + let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( config.transaction_pool.clone(), config.prometheus_registry(), @@ -330,20 +340,13 @@ pub fn new_light(config: Configuration) -> Result { on_demand.clone(), )); - let grandpa_block_import = sc_finality_grandpa::light_block_import( - client.clone(), - backend.clone(), - &(client.clone() as Arc<_>), - Arc::new(on_demand.checker().clone()) as Arc<_>, - )?; - let finality_proof_import = grandpa_block_import.clone(); - let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); + let (grandpa_block_import, _) = + sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import, - None, - Some(Box::new(finality_proof_import)), + grandpa_block_import.clone(), + Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), &task_manager.spawn_handle(), @@ -351,8 +354,6 @@ pub fn new_light(config: Configuration) -> Result { sp_consensus::NeverCanAuthor, )?; - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -362,8 +363,6 @@ pub fn new_light(config: Configuration) -> Result { import_queue, on_demand: Some(on_demand.clone()), block_announce_validator_builder: None, - finality_proof_request_builder: Some(finality_proof_request_builder), - finality_proof_provider: Some(finality_proof_provider), })?; if config.offchain_worker.enabled { @@ -385,7 +384,7 @@ pub fn new_light(config: Configuration) -> Result { telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), config, client, - keystore, + keystore: keystore_container.sync_keystore(), backend, network, network_status_sinks, diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 0b68971c8a379..0fa93448ff4e0 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -33,33 +33,33 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -frame-benchmarking = { version = "2.0", default-features = false, optional = true } -frame-executive = { version = "2.0", default-features = false } -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -frame-system-rpc-runtime-api = { version = "2.0", default-features = false } -pallet-aura = { version = "2.0", default-features = false } -pallet-balances = { version = "2.0", default-features = false } -pallet-grandpa = { version = "2.0", default-features = false } -pallet-randomness-collective-flip = { version = "2.0", default-features = false } -pallet-session = { version = "2.0", default-features = false } -pallet-sudo = { version = "2.0", default-features = false } -pallet-timestamp = { version = "2.0", default-features = false } -pallet-transaction-payment = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } -sp-block-builder = { version = "2.0", default-features = false } -sp-consensus-aura = { version = "0.8", default-features = false } -sp-core = { version = "2.0", default-features = false } -sp-finality-grandpa = { version = "2.0", default-features = false } -sp-inherents = { version = "2.0", default-features = false } -sp-io = { version = "2.0", default-features = false } -sp-offchain = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-session = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } -sp-transaction-pool = { version = "2.0", default-features = false } -sp-trie = { version = "2.0", default-features = false } -sp-version = { version = "2.0", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } +frame-executive = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-offchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 7374a805a77b7..cd5f2df34ed93 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -390,8 +390,7 @@ parameter_types! { } impl pallet_transaction_payment::Trait for Runtime { - type Currency = pallet_balances::Module; - type OnTransactionPayment = (); + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 93e0bf6a2bf32..c7a00209bc3eb 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -21,10 +21,10 @@ pallet-substrate-bridge = { path = "../../modules/substrate", default-features = # Substrate dependencies -frame-support = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } -sp-trie = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index b60cf14d79229..e80f98e0adc1a 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -16,14 +16,14 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] -sp-core = "2.0" -sp-io = "2.0" +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index f6fda67fbae47..e7a35a3423144 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -463,7 +463,7 @@ mod tests { vec![EventRecord { phase: Phase::Initialization, event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( - origin, id, 1305000, 0, + origin, id, 1973000, 0, )), topics: vec![], }], @@ -488,7 +488,7 @@ mod tests { vec![EventRecord { phase: Phase::Initialization, event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( - origin, id, 1305000, 0, + origin, id, 1973000, 0, )), topics: vec![], }], diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 8d400e07bb215..967d578659073 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -17,15 +17,15 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-benchmarking = { version = "2.0", default-features = false, optional = true } -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } [dev-dependencies] -sp-core = "2.0" -sp-io = "2.0" +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 631bc24c44a3f..101a03fb8c26f 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -19,10 +19,10 @@ rialto-runtime = { path = "../../../bin/rialto/runtime" } # Substrate Dependencies -sc-finality-grandpa = "0.8" -sp-blockchain = "2.0" -sp-finality-grandpa = "2.0" -sp-runtime = "2.0" +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [dev-dependencies] -sp-core = "2.0" +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 83be6d79639a4..66db6f9586128 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -17,12 +17,12 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false # Substrate Dependencies -frame-benchmarking = { version = "2.0", default-features = false, optional = true } -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -sp-io = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 480306d2b21bf..05f16f189923d 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -17,15 +17,15 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -sp-core = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] hex-literal = "0.3" -sp-io = "2.0" +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index e9ef6c1cc6b2a..73111d0d28ec7 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] derive_more = "0.99.2" futures = { version = "0.3.5", features = ["compat"] } -jsonrpc-core = "15.0.0" -jsonrpc-core-client = "15.0.0" -jsonrpc-derive = "15.0.0" +jsonrpc-core = "15.1.0" +jsonrpc-core-client = "15.1.0" +jsonrpc-derive = "15.1.0" # Bridge dependencies @@ -20,9 +20,9 @@ bp-message-lane = { path = "../../../primitives/message-lane" } # Substrate Dependencies -sc-client-api = "2.0" -sp-blockchain = "2.0" -sp-core = "2.0" -sp-runtime = "2.0" -sp-state-machine = "0.8" -sp-trie = "2.0" +sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 3f54df20dfe00..1cba12f2f5c58 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -11,15 +11,15 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -pallet-session = { version = "2.0", default-features = false } -sp-staking = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-staking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] -sp-core = "2.0" -sp-runtime = "2.0" +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 82740fc1b4fc2..03da6a16526f8 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -19,18 +19,18 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -frame-system = { version = "2.0", default-features = false } -sp-finality-grandpa = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } -sp-trie = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] -sp-core = "2.0" -sp-io = "2.0" -sp-keyring = "2.0" -sp-state-machine = "0.8" +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index aebde40e902f6..01f7005902b32 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -11,9 +11,9 @@ codec = { package = "parity-scale-codec", version = "1.3.4", default-features = # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 49eab4f084362..724f5594cdf42 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -24,10 +24,10 @@ triehash = { version = "0.8.2", default-features = false } # Substrate Dependencies -sp-api = { version = "2.0", default-features = false } -sp-io = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] hex-literal = "0.2" diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index ecd20d611ea73..63380914e7945 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -11,8 +11,8 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index db8fbf04feeb7..1c22da3cd9bd5 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -21,13 +21,13 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies -frame-support = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } -sp-core = { version = "2.0", default-features = false } -sp-io = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } -sp-trie = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index 6dce5005b5d16..53305d7ed862e 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -15,11 +15,11 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { version = "2.0", default-features = false } -sp-api = { version = "2.0", default-features = false } -sp-core = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index b42fa4bf3ecdd..2452a9f44e630 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -12,10 +12,10 @@ num-traits = { version = "0.2", default-features = false } # Substrate Dependencies -frame-support = { version = "2.0", default-features = false } -sp-io = { version = "2.0", default-features = false } -sp-runtime = { version = "2.0", default-features = false } -sp-std = { version = "2.0", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 69e9e010d8509..ff05ac3dccf94 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -40,9 +40,9 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-system = "2.0" -pallet-transaction-payment = "2.0" -sp-core = "2.0" -sp-keyring = "2.0" -sp-runtime = "2.0" -substrate-prometheus-endpoint = "0.8" +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index 487e4bb6347f6..3ca425730730a 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -17,9 +17,9 @@ millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies -frame-support = "2.0" -frame-system = "2.0" -pallet-transaction-payment = "2.0" -sp-core = "2.0" -sp-keyring = "2.0" -sp-runtime = "2.0" +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml index 7f9b6e9be5f89..007ddfd26721e 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/rialto-client/Cargo.toml @@ -17,9 +17,9 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-system = "2.0" -frame-support = "2.0" -pallet-transaction-payment = "2.0" -sp-core = "2.0" -sp-keyring = "2.0" -sp-runtime = "2.0" +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index d8f9232b25e0f..0e4b43bf7f6b6 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -23,14 +23,14 @@ relay-utils = { path = "../utils" } # Substrate Dependencies -frame-support = "2.0" -frame-system = "2.0" -pallet-balances = "2.0" -sp-core = "2.0" -sp-runtime = "2.0" -sp-std = "2.0" -sp-trie = "2.0" -sp-version = "2.0" +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "master" } #[dev-dependencies] futures = "0.3.7" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 6cb9847ea2a69..e35021d445195 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -35,8 +35,8 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-support = "2.0" -sp-core = "2.0" -sp-finality-grandpa = "2.0" -sp-runtime = "2.0" -sp-trie = "2.0" +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 04ceb3ec0dc01..1f20a063de33a 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -18,4 +18,4 @@ time = "0.2" # Substrate dependencies -substrate-prometheus-endpoint = "0.8" +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate.git", branch = "master" } From c12e494581c3aae1d63ee90bdab8ac21521690a3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 Nov 2020 20:41:45 +0300 Subject: [PATCH 0243/1210] Generic SyncHeader type (#529) * generic SyncHeader type * add panic condition to method description * extract -> into_inner * checked_sub + expect --- relays/headers-relay/src/sync_types.rs | 2 + relays/millau-client/src/lib.rs | 39 +----------- relays/rialto-client/src/lib.rs | 39 +----------- relays/substrate-client/src/lib.rs | 2 + relays/substrate-client/src/sync_header.rs | 61 +++++++++++++++++++ .../substrate/src/millau_headers_to_rialto.rs | 2 +- .../substrate/src/rialto_headers_to_millau.rs | 2 +- 7 files changed, 71 insertions(+), 76 deletions(-) create mode 100644 relays/substrate-client/src/sync_header.rs diff --git a/relays/headers-relay/src/sync_types.rs b/relays/headers-relay/src/sync_types.rs index 7f975100f8edf..e1da6232258c9 100644 --- a/relays/headers-relay/src/sync_types.rs +++ b/relays/headers-relay/src/sync_types.rs @@ -84,6 +84,8 @@ pub trait SourceHeader: Clone + std::fmt::Debug + PartialEq + Send /// Returns ID of header. fn id(&self) -> HeaderId; /// Returns ID of parent header. + /// + /// Panics if called for genesis header. fn parent_id(&self) -> HeaderId; } diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index 9c018a8419a41..c7d04056878fa 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -17,13 +17,9 @@ //! Types used to connect to the Millau-Substrate chain. use codec::Encode; -use headers_relay::sync_types::SourceHeader; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, Client, TransactionSignScheme}; use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{ - generic::SignedPayload, - traits::{Header as HeaderT, IdentifyAccount}, -}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; pub use millau_runtime::BridgeRialtoCall; @@ -126,35 +122,4 @@ impl std::fmt::Debug for SigningParams { } /// Millau header type used in headers sync. -#[derive(Clone, Debug, PartialEq)] -pub struct SyncHeader(millau_runtime::Header); - -impl std::ops::Deref for SyncHeader { - type Target = millau_runtime::Header; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for SyncHeader { - fn from(header: millau_runtime::Header) -> Self { - Self(header) - } -} - -impl From for millau_runtime::Header { - fn from(header: SyncHeader) -> Self { - header.0 - } -} - -impl SourceHeader for SyncHeader { - fn id(&self) -> HeaderId { - relay_utils::HeaderId(*self.number(), self.hash()) - } - - fn parent_id(&self) -> HeaderId { - relay_utils::HeaderId(*self.number() - 1, *self.parent_hash()) - } -} +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs index f45408d1538a4..9e38831d56c43 100644 --- a/relays/rialto-client/src/lib.rs +++ b/relays/rialto-client/src/lib.rs @@ -17,13 +17,9 @@ //! Types used to connect to the Rialto-Substrate chain. use codec::Encode; -use headers_relay::sync_types::SourceHeader; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, Client, TransactionSignScheme}; use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{ - generic::SignedPayload, - traits::{Header as HeaderT, IdentifyAccount}, -}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; pub use rialto_runtime::BridgeMillauCall; @@ -134,35 +130,4 @@ impl Default for SigningParams { } /// Rialto header type used in headers sync. -#[derive(Clone, Debug, PartialEq)] -pub struct SyncHeader(rialto_runtime::Header); - -impl std::ops::Deref for SyncHeader { - type Target = rialto_runtime::Header; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl From for SyncHeader { - fn from(header: rialto_runtime::Header) -> Self { - Self(header) - } -} - -impl From for rialto_runtime::Header { - fn from(header: SyncHeader) -> Self { - header.0 - } -} - -impl SourceHeader for SyncHeader { - fn id(&self) -> HeaderId { - relay_utils::HeaderId(*self.number(), self.hash()) - } - - fn parent_id(&self) -> HeaderId { - relay_utils::HeaderId(*self.number() - 1, *self.parent_hash()) - } -} +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index 567fc4a61984e..c6d077b21c562 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -22,6 +22,7 @@ mod chain; mod client; mod error; mod rpc; +mod sync_header; pub mod guard; pub mod headers_source; @@ -29,6 +30,7 @@ pub mod headers_source; pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme}; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; +pub use crate::sync_header::SyncHeader; pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; /// Header id used by the chain. diff --git a/relays/substrate-client/src/sync_header.rs b/relays/substrate-client/src/sync_header.rs new file mode 100644 index 0000000000000..fd1c582b9480e --- /dev/null +++ b/relays/substrate-client/src/sync_header.rs @@ -0,0 +1,61 @@ +// Copyright 2019-2020 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 . + +use headers_relay::sync_types::SourceHeader; +use num_traits::{CheckedSub, One}; +use relay_utils::HeaderId; +use sp_runtime::traits::Header as HeaderT; + +/// Generic wrapper for `sp_runtime::traits::Header` based headers, that +/// implements `headers_relay::sync_types::SourceHeader` and may be used in headers sync directly. +#[derive(Clone, Debug, PartialEq)] +pub struct SyncHeader

(Header); + +impl
SyncHeader
{ + /// Extracts wrapped header from self. + pub fn into_inner(self) -> Header { + self.0 + } +} + +impl
std::ops::Deref for SyncHeader
{ + type Target = Header; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl
From
for SyncHeader
{ + fn from(header: Header) -> Self { + Self(header) + } +} + +impl SourceHeader for SyncHeader
{ + fn id(&self) -> HeaderId { + relay_utils::HeaderId(*self.number(), self.hash()) + } + + fn parent_id(&self) -> HeaderId { + relay_utils::HeaderId( + self.number() + .checked_sub(&One::one()) + .expect("should never be called for genesis header"), + *self.parent_hash(), + ) + } +} diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 714a6c22f5e61..8b77e71657a09 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -54,7 +54,7 @@ impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = BridgeMillauCall::import_signed_header(header.header().clone().into()).into(); + let call = BridgeMillauCall::import_signed_header(header.header().clone().into_inner()).into(); let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index 92a141654c503..3a13c6e148c63 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -53,7 +53,7 @@ impl SubstrateHeadersSyncPipeline for RialtoHeadersToMillau { ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = BridgeRialtoCall::import_signed_header(header.header().clone().into()).into(); + let call = BridgeRialtoCall::import_signed_header(header.header().clone().into_inner()).into(); let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } From a14ed8e62839e39668180872320c5a5e92e6a156 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 26 Nov 2020 06:56:49 +0300 Subject: [PATCH 0244/1210] Add more substrate accounts + use one account in one relay (#526) * add more substrate accounts * 's * Update deployments/README.md Co-authored-by: Hernando Castano * Update deployments/README.md Co-authored-by: Hernando Castano * more fixes * with messages to -> which contain messages for Co-authored-by: Hernando Castano --- bin/millau/node/src/chain_spec.rs | 6 +++++- bin/rialto/node/src/chain_spec.rs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 957ee4750c4af..f1b6323763c4f 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -111,12 +111,16 @@ impl Alternative { get_account_id_from_seed::("Dave"), get_account_id_from_seed::("Eve"), get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Harry"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("Harry//stash"), ], true, ) @@ -147,7 +151,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }), pallet_balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }), pallet_aura: Some(AuraConfig { authorities: Vec::new(), diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 50f141465ba12..ed226334e5302 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -111,12 +111,16 @@ impl Alternative { get_account_id_from_seed::("Dave"), get_account_id_from_seed::("Eve"), get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Harry"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("Harry//stash"), ], true, ) @@ -147,7 +151,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }), pallet_balances: Some(BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }), pallet_aura: Some(AuraConfig { authorities: Vec::new(), From 2d720f054325f4324ad47d4b073b32c3971eb4c8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 27 Nov 2020 10:44:49 +0300 Subject: [PATCH 0245/1210] Message relay fixes for nightly stuck (#532) * fixed missing else * really wake up when retry timeout is completed * do not query weights if target nonce is unknown * fix compilation --- .../messages-relay/src/message_lane_loop.rs | 3 + .../src/message_race_delivery.rs | 4 +- .../messages-relay/src/message_race_loop.rs | 31 ++++- .../src/message_race_strategy.rs | 59 ++++++--- relays/substrate/src/messages_source.rs | 125 +++++++++++++++--- 5 files changed, 175 insertions(+), 47 deletions(-) diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index 8278f8c3ec64c..7cd0563c3a568 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -103,6 +103,9 @@ pub trait SourceClient: Clone + Send + Sync { ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error>; /// Returns mapping of message nonces, generated on this client, to their weights. + /// + /// Some weights may be missing from returned map, if corresponding messages were pruned at + /// the source chain. async fn generated_messages_weights( &self, id: SourceHeaderIdOf

, diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index dbc5d31400e9f..8f2a0f693ba8d 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -223,11 +223,11 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M self.strategy.is_empty() } - fn best_at_source(&self) -> MessageNonce { + fn best_at_source(&self) -> Option { self.strategy.best_at_source() } - fn best_at_target(&self) -> MessageNonce { + fn best_at_target(&self) -> Option { self.strategy.best_at_target() } diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 3267ea9dc287d..9c80b57400341 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -144,9 +144,14 @@ pub trait RaceStrategy { /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; /// Return best nonce at source node. - fn best_at_source(&self) -> MessageNonce; + /// + /// `Some` is returned only if we are sure that the value is greater or equal + /// than the result of `best_at_target`. + fn best_at_source(&self) -> Option; /// Return best nonce at target node. - fn best_at_target(&self) -> MessageNonce; + /// + /// May return `None` if value is yet unknown. + fn best_at_target(&self) -> Option; /// Called when nonces are updated at source node of the race. fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonces: SourceClientNonces); @@ -334,7 +339,15 @@ pub async fn run>( async_std::task::sleep, || format!("Error submitting proof {}", P::target_name()), ).fail_if_connection_error(FailedClient::Target)?; - } + }, + + // when we're ready to retry request + _ = source_go_offline_future => { + source_client_is_online = true; + }, + _ = target_go_offline_future => { + target_client_is_online = true; + }, } progress_context = print_race_progress::(progress_context, &strategy); @@ -350,6 +363,7 @@ pub async fn run>( source_client_is_online = false; let nonces_to_deliver = select_nonces_to_deliver(&race_state, &mut strategy); + let best_at_source = strategy.best_at_source(); if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { log::debug!( @@ -364,7 +378,7 @@ pub async fn run>( .generate_proof(at_block, nonces_range, proof_parameters) .fuse(), ); - } else if source_nonces_required { + } else if source_nonces_required && best_at_source.is_some() { log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); let at_block = race_state .best_finalized_source_header_id_at_source @@ -374,7 +388,11 @@ pub async fn run>( best_finalized_source_header_id_at_source is Some; qed", ) .clone(); - source_nonces.set(race_source.nonces(at_block, strategy.best_at_source()).fuse()); + source_nonces.set( + race_source + .nonces(at_block, best_at_source.expect("guaranteed by if condition; qed")) + .fuse(), + ); } else { source_client_is_online = true; } @@ -395,8 +413,7 @@ pub async fn run>( .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) .fuse(), ); - } - if target_nonces_required { + } else if target_nonces_required { log::debug!(target: "bridge", "Asking {} about message nonces", P::target_name()); let at_block = race_state .best_target_header_id diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index dbd080e5a29c4..feff1f3e20fe1 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -35,8 +35,8 @@ pub struct BasicStrategy< > { /// All queued nonces. source_queue: VecDeque<(HeaderId, SourceNoncesRange)>, - /// Best nonce known to target node. - target_nonce: MessageNonce, + /// Best nonce known to target node. `None` if it has not been received yet. + target_nonce: Option, /// Unused generic types dump. _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, } @@ -52,7 +52,7 @@ where pub fn new() -> Self { BasicStrategy { source_queue: VecDeque::new(), - target_nonce: Default::default(), + target_nonce: None, _phantom: Default::default(), } } @@ -74,6 +74,9 @@ where >, mut selector: impl FnMut(SourceNoncesRange) -> Option, ) -> Option> { + // if we do not know best nonce at target node, we can't select anything + let target_nonce = self.target_nonce?; + // if we have already selected nonces that we want to submit, do nothing if race_state.nonces_to_submit.is_some() { return None; @@ -128,7 +131,7 @@ where } } - nonces_end.map(|nonces_end| RangeInclusive::new(self.target_nonce + 1, nonces_end)) + nonces_end.map(|nonces_end| RangeInclusive::new(target_nonce + 1, nonces_end)) } } @@ -147,17 +150,16 @@ where self.source_queue.is_empty() } - fn best_at_source(&self) -> MessageNonce { - std::cmp::max( - self.source_queue - .back() - .map(|(_, range)| range.end()) - .unwrap_or(self.target_nonce), - self.target_nonce, - ) + fn best_at_source(&self) -> Option { + let best_in_queue = self.source_queue.back().map(|(_, range)| range.end()); + match (best_in_queue, self.target_nonce) { + (Some(best_in_queue), Some(target_nonce)) if best_in_queue > target_nonce => Some(best_in_queue), + (_, Some(target_nonce)) => Some(target_nonce), + (_, None) => None, + } } - fn best_at_target(&self) -> MessageNonce { + fn best_at_target(&self) -> Option { self.target_nonce } @@ -166,11 +168,16 @@ where at_block: HeaderId, nonces: SourceClientNonces, ) { - let prev_best_at_source = self.best_at_source(); + let best_in_queue = self + .source_queue + .back() + .map(|(_, range)| range.end()) + .or(self.target_nonce) + .unwrap_or_default(); self.source_queue.extend( nonces .new_nonces - .greater_than(prev_best_at_source) + .greater_than(best_in_queue) .into_iter() .map(move |range| (at_block.clone(), range)), ) @@ -187,8 +194,10 @@ where ) { let nonce = nonces.latest_nonce; - if nonce < self.target_nonce { - return; + if let Some(target_nonce) = self.target_nonce { + if nonce < target_nonce { + return; + } } while let Some(true) = self.source_queue.front().map(|(_, range)| range.begin() <= nonce) { @@ -220,7 +229,7 @@ where race_state.nonces_submitted = None; } - self.target_nonce = nonce; + self.target_nonce = Some(nonce); } fn select_nonces_to_deliver( @@ -278,12 +287,12 @@ mod tests { #[test] fn best_at_source_is_never_lower_than_target_nonce() { let mut strategy = BasicStrategy::::new(); - assert_eq!(strategy.best_at_source(), 0); + assert_eq!(strategy.best_at_source(), None); strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); - assert_eq!(strategy.best_at_source(), 5); + assert_eq!(strategy.best_at_source(), None); strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); assert_eq!(strategy.source_queue, vec![]); - assert_eq!(strategy.best_at_source(), 10); + assert_eq!(strategy.best_at_source(), Some(10)); } #[test] @@ -306,9 +315,11 @@ mod tests { #[test] fn target_nonce_is_never_lower_than_latest_known_target_nonce() { let mut strategy = BasicStrategy::::new(); + assert_eq!(strategy.target_nonce, None); strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); + assert_eq!(strategy.target_nonce, Some(10)); strategy.target_nonces_updated(target_nonces(5), &mut Default::default()); - assert_eq!(strategy.target_nonce, 10); + assert_eq!(strategy.target_nonce, Some(10)); } #[test] @@ -351,6 +362,7 @@ mod tests { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); + strategy.target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } @@ -360,6 +372,7 @@ mod tests { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(1..=10); + strategy.target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } @@ -368,6 +381,7 @@ mod tests { fn select_nonces_to_deliver_works() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); + strategy.target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); strategy.source_nonces_updated(header_id(2), source_nonces(2..=2)); strategy.source_nonces_updated(header_id(3), source_nonces(3..=6)); @@ -388,6 +402,7 @@ mod tests { fn select_nonces_to_deliver_able_to_split_ranges_with_selector() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); + strategy.target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); state.best_finalized_source_header_id_at_source = Some(header_id(1)); diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index 412fac2e356d5..1a6b9e6c1119a 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -150,23 +150,11 @@ where Some(id.1), ) .await?; - let weights: Vec<(MessageNonce, Weight)> = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - - let mut expected_nonce = *nonces.start(); - let mut weights_map = MessageWeightsMap::new(); - for (nonce, weight) in weights { - if nonce != expected_nonce { - return Err(SubstrateError::Custom(format!( - "Unexpected nonce in messages_dispatch_weight call result. Expected {}, got {}", - expected_nonce, nonce - ))); - } - weights_map.insert(nonce, weight); - expected_nonce += 1; - } - Ok(weights_map) + make_message_weights_map::( + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?, + nonces, + ) } async fn prove_messages( @@ -245,3 +233,108 @@ where best_finalized_peer_at_best_self: peer_on_self_best_finalized_id, }) } + +fn make_message_weights_map( + weights: Vec<(MessageNonce, Weight)>, + nonces: RangeInclusive, +) -> Result { + let make_missing_nonce_error = |expected_nonce| { + Err(SubstrateError::Custom(format!( + "Missing nonce {} in messages_dispatch_weight call result. Expected all nonces from {:?}", + expected_nonce, nonces, + ))) + }; + + let mut weights_map = MessageWeightsMap::new(); + + // this is actually prevented by external logic + if nonces.is_empty() { + return Ok(weights_map); + } + + // check if last nonce is missing - loop below is not checking this + let last_nonce_is_missing = weights + .last() + .map(|(last_nonce, _)| last_nonce != nonces.end()) + .unwrap_or(true); + if last_nonce_is_missing { + return make_missing_nonce_error(*nonces.end()); + } + + let mut expected_nonce = *nonces.start(); + let mut is_at_head = true; + + for (nonce, weight) in weights { + match (nonce == expected_nonce, is_at_head) { + (true, _) => (), + (false, true) => { + // this may happen if some messages were already pruned from the source node + // + // this is not critical error and will be auto-resolved by messages lane (and target node) + log::info!( + target: "bridge", + "Some messages are missing from the {} node: {:?}. Target node may be out of sync?", + C::NAME, + expected_nonce..nonce, + ); + } + (false, false) => { + // some nonces are missing from the middle/tail of the range + // + // this is critical error, because we can't miss any nonces + return make_missing_nonce_error(expected_nonce); + } + } + + weights_map.insert(nonce, weight); + expected_nonce = nonce + 1; + is_at_head = false; + } + + Ok(weights_map) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn make_message_weights_map_succeeds_if_no_messages_are_missing() { + assert_eq!( + make_message_weights_map::(vec![(1, 0), (2, 0), (3, 0)], 1..=3).unwrap(), + vec![(1, 0), (2, 0), (3, 0)].into_iter().collect(), + ); + } + + #[test] + fn make_message_weights_map_succeeds_if_head_messages_are_missing() { + assert_eq!( + make_message_weights_map::(vec![(2, 0), (3, 0)], 1..=3).unwrap(), + vec![(2, 0), (3, 0)].into_iter().collect(), + ); + } + + #[test] + fn make_message_weights_map_fails_if_mid_messages_are_missing() { + assert!(matches!( + make_message_weights_map::(vec![(1, 0), (3, 0)], 1..=3), + Err(SubstrateError::Custom(_)) + )); + } + + #[test] + fn make_message_weights_map_fails_if_tail_messages_are_missing() { + assert!(matches!( + make_message_weights_map::(vec![(1, 0), (2, 0)], 1..=3), + Err(SubstrateError::Custom(_)) + )); + } + + #[test] + fn make_message_weights_map_fails_if_all_messages_are_missing() { + assert!(matches!( + make_message_weights_map::(vec![], 1..=3), + Err(SubstrateError::Custom(_)) + )); + } +} From 5e4637c2ac15624bcefc16e78bfca54d7d63d22b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 Nov 2020 16:14:07 +0300 Subject: [PATCH 0246/1210] Fixed clippy warnings (#537) * fixed clippy warnings * Revert "Actually use pinned nightly version when building runtimes (#465)" This reverts commit 8343bcbef0c4242f97a78a25f4d265fd76de7ba2. * Revert "Pin Rust Nightly Version (#420)" This reverts commit 8902ac2030cf7ef48ec512463424f134a3b38804. * fix after revert * another fix after revert * more clippy fixes --- bin/millau/node/src/chain_spec.rs | 6 +-- bin/millau/node/src/command.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 22 +++++------ bin/rialto/node/src/command.rs | 2 +- modules/ethereum/src/lib.rs | 41 +++++++++++---------- modules/ethereum/src/validators.rs | 12 ++++-- modules/substrate/src/lib.rs | 1 + relays/headers-relay/src/sync_loop_tests.rs | 7 ++-- relays/utils/src/lib.rs | 11 +++--- 9 files changed, 57 insertions(+), 47 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index f1b6323763c4f..8c7c40472751b 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -65,8 +65,8 @@ pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { impl Alternative { /// Get an actual chain config from one of the alternatives. - pub(crate) fn load(self) -> Result { - Ok(match self { + pub(crate) fn load(self) -> ChainSpec { + match self { Alternative::Development => ChainSpec::from_genesis( "Development", "dev", @@ -131,7 +131,7 @@ impl Alternative { None, None, ), - }) + } } } diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 651080bbf200e..c007d5d848532 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -61,7 +61,7 @@ impl SubstrateCli for Cli { "local" => crate::chain_spec::Alternative::LocalTestnet, _ => return Err(format!("Unsupported chain specification: {}", id)), } - .load()?, + .load(), )) } } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index ed226334e5302..939dcc5e3fe6b 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -65,8 +65,8 @@ pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { impl Alternative { /// Get an actual chain config from one of the alternatives. - pub(crate) fn load(self) -> Result { - Ok(match self { + pub(crate) fn load(self) -> ChainSpec { + match self { Alternative::Development => ChainSpec::from_genesis( "Development", "dev", @@ -131,7 +131,7 @@ impl Alternative { None, None, ), - }) + } } } @@ -156,8 +156,8 @@ fn testnet_genesis( pallet_aura: Some(AuraConfig { authorities: Vec::new(), }), - pallet_bridge_eth_poa_Instance1: load_rialto_poa_bridge_config(), - pallet_bridge_eth_poa_Instance2: load_kovan_bridge_config(), + pallet_bridge_eth_poa_Instance1: Some(load_rialto_poa_bridge_config()), + pallet_bridge_eth_poa_Instance2: Some(load_kovan_bridge_config()), pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), @@ -176,18 +176,18 @@ fn testnet_genesis( } } -fn load_rialto_poa_bridge_config() -> Option { - Some(BridgeRialtoPoAConfig { +fn load_rialto_poa_bridge_config() -> BridgeRialtoPoAConfig { + BridgeRialtoPoAConfig { initial_header: rialto_runtime::rialto_poa::genesis_header(), initial_difficulty: 0.into(), initial_validators: rialto_runtime::rialto_poa::genesis_validators(), - }) + } } -fn load_kovan_bridge_config() -> Option { - Some(BridgeKovanConfig { +fn load_kovan_bridge_config() -> BridgeKovanConfig { + BridgeKovanConfig { initial_header: rialto_runtime::kovan::genesis_header(), initial_difficulty: 0.into(), initial_validators: rialto_runtime::kovan::genesis_validators(), - }) + } } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index fe423f8803d97..52ff1d5a254d3 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -61,7 +61,7 @@ impl SubstrateCli for Cli { "local" => crate::chain_spec::Alternative::LocalTestnet, _ => return Err(format!("Unsupported chain specification: {}", id)), } - .load()?, + .load(), )) } } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ace34f38edb81..75062f763952a 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -1028,7 +1028,7 @@ fn pool_configuration() -> PoolConfiguration { } /// Return iterator of given header ancestors. -fn ancestry<'a, S: Storage>(storage: &'a S, mut parent_hash: H256) -> impl Iterator + 'a { +fn ancestry(storage: &'_ S, mut parent_hash: H256) -> impl Iterator + '_ { sp_std::iter::from_fn(move || { let (header, _) = storage.header(&parent_hash)?; if header.number == 0 { @@ -1069,30 +1069,33 @@ pub(crate) mod tests { } fn example_header_with_failed_receipt() -> AuraHeader { - let mut header = AuraHeader::default(); - header.number = 3; - header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); - header.receipts_root = compute_merkle_root(vec![example_tx_receipt(false)].into_iter()); - header.parent_hash = example_header().compute_hash(); - header + AuraHeader { + number: 3, + transactions_root: compute_merkle_root(vec![example_tx()].into_iter()), + receipts_root: compute_merkle_root(vec![example_tx_receipt(false)].into_iter()), + parent_hash: example_header().compute_hash(), + ..Default::default() + } } fn example_header() -> AuraHeader { - let mut header = AuraHeader::default(); - header.number = 2; - header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); - header.receipts_root = compute_merkle_root(vec![example_tx_receipt(true)].into_iter()); - header.parent_hash = example_header_parent().compute_hash(); - header + AuraHeader { + number: 2, + transactions_root: compute_merkle_root(vec![example_tx()].into_iter()), + receipts_root: compute_merkle_root(vec![example_tx_receipt(true)].into_iter()), + parent_hash: example_header_parent().compute_hash(), + ..Default::default() + } } fn example_header_parent() -> AuraHeader { - let mut header = AuraHeader::default(); - header.number = 1; - header.transactions_root = compute_merkle_root(vec![example_tx()].into_iter()); - header.receipts_root = compute_merkle_root(vec![example_tx_receipt(true)].into_iter()); - header.parent_hash = genesis().compute_hash(); - header + AuraHeader { + number: 1, + transactions_root: compute_merkle_root(vec![example_tx()].into_iter()), + receipts_root: compute_merkle_root(vec![example_tx_receipt(true)].into_iter()), + parent_hash: genesis().compute_hash(), + ..Default::default() + } } fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index dc09b48d55062..d4ddac66b7df0 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -325,8 +325,10 @@ pub(crate) mod tests { // when contract is active, but bloom has no required bits set let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); let validators = Validators::new(&config); - let mut header = AuraHeader::default(); - header.number = u64::max_value(); + let mut header = AuraHeader { + number: u64::max_value(), + ..Default::default() + }; assert!(!validators.maybe_signals_validators_change(&header)); // when contract is active and bloom has required bits set @@ -347,10 +349,12 @@ pub(crate) mod tests { (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), ]); let validators = Validators::new(&config); - let mut header = AuraHeader::default(); + let mut header = AuraHeader { + number: 100, + ..Default::default() + }; // when we're at the block that switches to list source - header.number = 100; assert_eq!( validators.extract_validators_change(&header, None), Ok((None, Some(vec![[2; 20].into()]))), diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 4e62841af7b56..eb77b5af750fb 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -459,6 +459,7 @@ pub trait BridgeStorage { /// Replace the current authority set with the next scheduled set. /// /// Returns an error if there is no scheduled authority set to enact. + #[allow(clippy::result_unit_err)] fn enact_authority_set(&mut self, signal_hash: ::Hash) -> Result<(), ()>; /// Get the next scheduled Grandpa authority set change. diff --git a/relays/headers-relay/src/sync_loop_tests.rs b/relays/headers-relay/src/sync_loop_tests.rs index f41d9708cd61c..27e5daa7da4f4 100644 --- a/relays/headers-relay/src/sync_loop_tests.rs +++ b/relays/headers-relay/src/sync_loop_tests.rs @@ -357,9 +357,10 @@ fn target_accept_all_headers(method: &TargetMethod, data: &mut TargetData, requi if let TargetMethod::SubmitHeaders(ref submitted) = method { assert_eq!(submitted.iter().all(|header| header.extra().is_some()), requires_extra,); - let mut submitted_headers = SubmittedHeaders::default(); - submitted_headers.submitted = submitted.iter().map(|header| header.id()).collect(); - data.submit_headers_result = Some(submitted_headers); + data.submit_headers_result = Some(SubmittedHeaders { + submitted: submitted.iter().map(|header| header.id()).collect(), + ..Default::default() + }); } } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index e81660299becb..2968320ff5c87 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -147,11 +147,12 @@ impl ToString for StringifiedMaybeConnectionError { /// Exponential backoff for connection-unrelated errors retries. pub fn retry_backoff() -> ExponentialBackoff { - let mut backoff = ExponentialBackoff::default(); - // we do not want relayer to stop - backoff.max_elapsed_time = None; - backoff.max_interval = MAX_BACKOFF_INTERVAL; - backoff + ExponentialBackoff { + // we do not want relayer to stop + max_elapsed_time: None, + max_interval: MAX_BACKOFF_INTERVAL, + ..Default::default() + } } /// Compact format of IDs vector. From 73ae6aa3da9665a069e468236f8a8c03a3dde530 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 30 Nov 2020 14:49:09 -0500 Subject: [PATCH 0247/1210] Add Derived Account Origins to Dispatcher (#519) * Update some docs * Add derived account origin * Add tests for derived origin * Do a little bit of cleanup * Change Origin type to use AccountIds instead of Public keys * Update (most) tests to use new Origin types * Remove redundant test * Update `runtime-common` tests to use new Origin types * Remove unused import * Fix documentation around origin verification * Update config types to use AccountIds in runtime * Update Origin type used in message relay * Use correct type when verifying message origin * Make CallOrigin docs more consistent * Use AccountIds instead of Public keys in Runtime types * Introduce trait for converting AccountIds * Bring back standalone function for deriving account IDs * Remove AccountIdConverter configuration trait * Remove old bridge_account_id derivation function * Handle target ID decoding errors more gracefully * Update message-lane to use new AccountId derivation * Update merged code to use new Origin types * Use explicit conversion between H256 and AccountIds * Make relayer fund account a config option in `message-lane` pallet * Add note about deriving the same account on different chains * Fix test weight * Use AccountId instead of Public key when signing Calls * Semi-hardcode relayer fund address into Message Lane pallet --- bin/millau/runtime/src/lib.rs | 5 +- bin/rialto/runtime/src/lib.rs | 5 +- bin/runtime-common/src/messages.rs | 12 +- modules/call-dispatch/Cargo.toml | 3 +- modules/call-dispatch/src/lib.rs | 372 +++++++++++-------- modules/message-lane/src/instant_payments.rs | 34 +- modules/message-lane/src/lib.rs | 18 + modules/message-lane/src/mock.rs | 23 +- primitives/message-dispatch/src/lib.rs | 2 +- primitives/message-lane/src/source_chain.rs | 13 +- primitives/millau/src/lib.rs | 8 + primitives/rialto/src/lib.rs | 9 + primitives/runtime/Cargo.toml | 2 + primitives/runtime/src/lib.rs | 51 ++- relays/substrate/src/main.rs | 15 +- 15 files changed, 376 insertions(+), 196 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2949e695ffdef..cbb4a14d54622 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -226,9 +226,10 @@ impl pallet_bridge_call_dispatch::Trait for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; - type SourceChainAccountPublic = MultiSigner; + type SourceChainAccountId = bp_rialto::AccountId; type TargetChainAccountPublic = MultiSigner; type TargetChainSignature = MultiSignature; + type AccountIdConverter = bp_millau::AccountIdConverter; } impl pallet_grandpa::Trait for Runtime { @@ -336,6 +337,8 @@ impl pallet_message_lane::Trait for Runtime { type InboundMessageFee = bp_rialto::Balance; type InboundRelayer = bp_rialto::AccountId; + type AccountIdConverter = bp_millau::AccountIdConverter; + type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type MessageDeliveryAndDispatchPayment = diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index cd5f2df34ed93..e239af930ceb2 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -277,9 +277,10 @@ impl pallet_bridge_call_dispatch::Trait for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; - type SourceChainAccountPublic = MultiSigner; + type SourceChainAccountId = bp_millau::AccountId; type TargetChainAccountPublic = MultiSigner; type TargetChainSignature = MultiSignature; + type AccountIdConverter = bp_rialto::AccountIdConverter; } pub struct DepositInto; @@ -443,6 +444,8 @@ impl pallet_message_lane::Trait for Runtime { type InboundMessageFee = bp_millau::Balance; type InboundRelayer = bp_millau::AccountId; + type AccountIdConverter = bp_rialto::AccountIdConverter; + type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 9a934ee162da5..b26d9435cd6b0 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -114,7 +114,7 @@ pub mod source { /// Message payload for This -> Bridged chain messages. pub type FromThisChainMessagePayload = pallet_bridge_call_dispatch::MessagePayload< - SignerOf>, + AccountIdOf>, SignerOf>, SignatureOf>, BridgedChainOpaqueCall, @@ -238,14 +238,14 @@ pub mod target { /// Call origin for Bridged -> This chain messages. pub type FromBridgedChainMessageCallOrigin = pallet_bridge_call_dispatch::CallOrigin< - SignerOf>, + AccountIdOf>, SignerOf>, SignatureOf>, >; /// Decoded Bridged -> This message payload. pub type FromBridgedChainDecodedMessagePayload = pallet_bridge_call_dispatch::MessagePayload< - SignerOf>, + AccountIdOf>, SignerOf>, SignatureOf>, CallOf>, @@ -614,7 +614,7 @@ mod tests { let message_on_bridged_chain = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::BridgeAccount, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, call: ThisChainCall::Transfer.encode(), } .encode(); @@ -628,7 +628,7 @@ mod tests { target::FromBridgedChainDecodedMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::BridgeAccount, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, call: ThisChainCall::Transfer, } ); @@ -642,7 +642,7 @@ mod tests { let payload = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::BridgeAccount, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, call: vec![42], }; diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index e80f98e0adc1a..9c25e3a8eb1d7 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -18,11 +18,11 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] @@ -32,6 +32,7 @@ std = [ "bp-runtime/std", "frame-support/std", "frame-system/std", + "sp-core/std", "sp-runtime/std", "sp-std/std", ] diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index e7a35a3423144..63d3ff25d54a2 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -16,18 +16,16 @@ //! Runtime module which takes care of dispatching messages received over the bridge. //! -//! The messages are interpreted directly as runtime `Call`s, we attempt to decode -//! them and then dispatch as usualy. -//! To prevent compatibility issues, the calls have to include `spec_version` as well -//! which is being checked before dispatch. -//! -//! In case of succesful dispatch event is emitted. +//! The messages are interpreted directly as runtime `Call`. We attempt to decode +//! them and then dispatch as usual. To prevent compatibility issues, the Calls have +//! to include a `spec_version`. This will be checked before dispatch. In the case of +//! a succesful dispatch an event is emitted. #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] use bp_message_dispatch::{MessageDispatch, Weight}; -use bp_runtime::{bridge_account_id, InstanceId, CALL_DISPATCH_MODULE_PREFIX}; +use bp_runtime::{derive_account_id, InstanceId, SourceAccount}; use codec::{Decode, Encode}; use frame_support::{ decl_event, decl_module, decl_storage, @@ -38,37 +36,51 @@ use frame_support::{ }; use frame_system::{ensure_root, ensure_signed, RawOrigin}; use sp_runtime::{ - traits::{BadOrigin, IdentifyAccount, Verify}, + traits::{BadOrigin, Convert, IdentifyAccount, MaybeDisplay, MaybeSerializeDeserialize, Member, Verify}, DispatchResult, }; -use sp_std::{marker::PhantomData, prelude::*}; +use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; /// Spec version type. pub type SpecVersion = u32; -/// Origin of the call on the target chain. +/// Origin of a Call when it is dispatched on the target chain. +/// +/// The source chain can (and should) verify that the message can be dispatched on the target chain +/// with a particular origin given the source chain's origin. This can be done with the +/// `verify_message_origin()` function. #[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] -pub enum CallOrigin { - /// Call is originated from bridge account, which is (designed to be) specific to - /// the single deployed instance of the messages bridge (message-lane, ...) module. - /// It is assumed that this account is not controlled by anyone and has zero balance - /// (unless someone would make transfer by mistake?). - /// If we trust the source chain to allow sending calls with that origin in case they originate - /// from source chain `root` account (default implementation), `BridgeAccount` represents the - /// source-chain-root origin on the target chain and can be used to send and authorize - /// "control plane" messages between the two runtimes. - BridgeAccount, - /// Call is originated from account, identified by `TargetChainAccountPublic`. The proof - /// that the `SourceChainAccountPublic` controls `TargetChainAccountPublic` is the - /// `TargetChainSignature` over `(Call, SourceChainAccountPublic).encode()`. - /// The source chain must ensure that the message is sent by the owner of - /// `SourceChainAccountPublic` account (use the `fn verify_sending_message()`). - RealAccount(SourceChainAccountPublic, TargetChainAccountPublic, TargetChainSignature), +pub enum CallOrigin { + /// Call is sent by the Root origin on the source chain. On the target chain it is dispatched + /// from a derived account. + /// + /// The derived account represents the source Root account on the target chain. This is useful + /// if the target chain needs some way of knowing that a call came from a priviledged origin on + /// the source chain (maybe to allow a configuration change for example). + SourceRoot, + + /// Call is sent by `SourceChainAccountId` on the source chain. On the target chain it is + /// dispatched from an account controlled by a private key on the target chain. + /// + /// The account can be identified by `TargetChainAccountPublic`. The proof that the + /// `SourceChainAccountId` controls `TargetChainAccountPublic` is the `TargetChainSignature` + /// over `(Call, SourceChainAccountId).encode()`. + TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature), + + /// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is + /// dispatched from a derived account ID. + /// + /// The account ID on the target chain is derived from the source account ID This is useful if + /// you need a way to represent foreign accounts on this chain for call dispatch purposes. + /// + /// Note that the derived account does not need to have a private key on the target chain. This + /// origin can therefore represent proxies, pallets, etc. as well as "regular" accounts. + SourceAccount(SourceChainAccountId), } /// Message payload type used by call-dispatch module. #[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] -pub struct MessagePayload { +pub struct MessagePayload { /// Runtime specification version. We only dispatch messages that have the same /// runtime version. Otherwise we risk to misinterpret encoded calls. pub spec_version: SpecVersion, @@ -76,7 +88,7 @@ pub struct MessagePayload, + pub origin: CallOrigin, /// The call itself. pub call: Call, } @@ -89,8 +101,8 @@ pub trait Trait: frame_system::Trait { /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if /// it comes from message-lane module. type MessageId: Parameter; - /// Type of account public key on source chain. - type SourceChainAccountPublic: Parameter; + /// Type of account ID on source chain. + type SourceChainAccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; /// Type of account public key on target chain. type TargetChainAccountPublic: Parameter + IdentifyAccount; /// Type of signature that may prove that the message has been signed by @@ -103,11 +115,14 @@ pub trait Trait: frame_system::Trait { Origin = ::Origin, PostInfo = frame_support::dispatch::PostDispatchInfo, >; + /// A type which can be turned into an AccountId from a 256-bit hash. + /// + /// Used when deriving target chain AccountIds from source chain AccountIds. + type AccountIdConverter: sp_runtime::traits::Convert; } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as CallDispatch { - } + trait Store for Module, I: Instance = DefaultInstance> as CallDispatch {} } decl_event!( @@ -124,8 +139,8 @@ decl_event!( MessageSignatureMismatch(InstanceId, MessageId), /// Message has been dispatched with given result. MessageDispatched(InstanceId, MessageId, DispatchResult), - /// Phantom member, never used. - Dummy(PhantomData), + /// Phantom member, never used. Needed to handle multiple pallet instances. + _Dummy(PhantomData), } ); @@ -139,7 +154,7 @@ decl_module! { impl, I: Instance> MessageDispatch for Module { type Message = MessagePayload< - T::SourceChainAccountPublic, + T::SourceChainAccountId, T::TargetChainAccountPublic, T::TargetChainSignature, >::Call, @@ -194,11 +209,14 @@ impl, I: Instance> MessageDispatch for Module { // prepare dispatch origin let origin_account = match message.origin { - CallOrigin::BridgeAccount => bridge_account_id(bridge, CALL_DISPATCH_MODULE_PREFIX), - CallOrigin::RealAccount(source_public, target_public, target_signature) => { + CallOrigin::SourceRoot => { + let encoded_id = derive_account_id::(bridge, SourceAccount::Root); + T::AccountIdConverter::convert(encoded_id) + } + CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { let mut signed_message = Vec::new(); message.call.encode_to(&mut signed_message); - source_public.encode_to(&mut signed_message); + source_account_id.encode_to(&mut signed_message); let target_account = target_public.into_account(); if !target_signature.verify(&signed_message[..], &target_account) { @@ -215,6 +233,10 @@ impl, I: Instance> MessageDispatch for Module { target_account } + CallOrigin::SourceAccount(source_account_id) => { + let encoded_id = derive_account_id(bridge, SourceAccount::Account(source_account_id)); + T::AccountIdConverter::convert(encoded_id) + } }; // finally dispatch message @@ -238,35 +260,45 @@ impl, I: Instance> MessageDispatch for Module { } } -/// Verify payload of the message at the sending side. -pub fn verify_sending_message< - ThisChainOuterOrigin, - ThisChainAccountId, - SourceChainAccountPublic, +/// Check if the message is allowed to be dispatched on the target chain given the sender's origin +/// on the source chain. +/// +/// For example, if a message is sent from a "regular" account on the source chain it will not be +/// allowed to be dispatched as Root on the target chain. This is a useful check to do on the source +/// chain _before_ sending a message whose dispatch will be rejected on the target chain. +pub fn verify_message_origin< + SourceChainOuterOrigin, + SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature, Call, >( - sender_origin: ThisChainOuterOrigin, - message: &MessagePayload, -) -> Result, BadOrigin> + sender_origin: SourceChainOuterOrigin, + message: &MessagePayload, +) -> Result, BadOrigin> where - ThisChainOuterOrigin: Into, ThisChainOuterOrigin>>, - TargetChainAccountPublic: Clone + IdentifyAccount, - ThisChainAccountId: PartialEq, + SourceChainOuterOrigin: Into, SourceChainOuterOrigin>>, + SourceChainAccountId: PartialEq, { match message.origin { - CallOrigin::BridgeAccount => { + CallOrigin::SourceRoot => { ensure_root(sender_origin)?; Ok(None) } - CallOrigin::RealAccount(ref this_account_public, _, _) => { - let this_chain_account_id = ensure_signed(sender_origin)?; - if this_chain_account_id != this_account_public.clone().into_account() { + CallOrigin::TargetAccount(ref source_account_id, _, _) => { + let source_chain_signer = ensure_signed(sender_origin)?; + if source_chain_signer != *source_account_id { return Err(BadOrigin); } - Ok(Some(this_chain_account_id)) + Ok(Some(source_chain_signer)) + } + CallOrigin::SourceAccount(ref source_account_id) => { + let source_chain_signer = ensure_signed(sender_origin)?; + if source_chain_signer != *source_account_id { + return Err(BadOrigin); + } + Ok(Some(source_chain_signer)) } } } @@ -280,7 +312,7 @@ mod tests { use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - DispatchError, Perbill, + Perbill, }; type AccountId = u64; @@ -311,6 +343,14 @@ mod tests { } } + pub struct AccountIdConverter; + + impl sp_runtime::traits::Convert for AccountIdConverter { + fn convert(hash: H256) -> AccountId { + hash.to_low_u64_ne() + } + } + #[derive(Clone, Eq, PartialEq)] pub struct TestRuntime; @@ -374,10 +414,11 @@ mod tests { impl Trait for TestRuntime { type Event = TestEvent; type MessageId = MessageId; - type SourceChainAccountPublic = TestAccountPublic; + type SourceChainAccountId = AccountId; type TargetChainAccountPublic = TestAccountPublic; type TargetChainSignature = TestSignature; type Call = Call; + type AccountIdConverter = AccountIdConverter; } const TEST_SPEC_VERSION: SpecVersion = 0; @@ -390,33 +431,62 @@ mod tests { sp_io::TestExternalities::new(t) } - fn prepare_bridge_message( + fn prepare_message( + origin: CallOrigin, call: Call, ) -> as MessageDispatch<::MessageId>>::Message { MessagePayload { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, - origin: CallOrigin::BridgeAccount, + origin, call, } } + fn prepare_root_message( + call: Call, + ) -> as MessageDispatch<::MessageId>>::Message { + prepare_message(CallOrigin::SourceRoot, call) + } + + fn prepare_target_message( + call: Call, + ) -> as MessageDispatch<::MessageId>>::Message { + let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); + prepare_message(origin, call) + } + + fn prepare_source_message( + call: Call, + ) -> as MessageDispatch<::MessageId>>::Message { + let origin = CallOrigin::SourceAccount(1); + prepare_message(origin, call) + } + #[test] - fn should_succesfuly_dispatch_remark() { + fn should_fail_on_spec_version_mismatch() { new_test_ext().execute_with(|| { - let origin = b"ethb".to_owned(); + let bridge = b"ethb".to_owned(); let id = [0; 4]; - let message = - prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); + + const BAD_SPEC_VERSION: SpecVersion = 99; + let mut message = + prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + message.spec_version = BAD_SPEC_VERSION; System::set_block_number(1); - CallDispatch::dispatch(origin, id, message); + CallDispatch::dispatch(bridge, id, message); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageDispatched(origin, id, Ok(()))), + event: TestEvent::call_dispatch(Event::::MessageVersionSpecMismatch( + bridge, + id, + TEST_SPEC_VERSION, + BAD_SPEC_VERSION + )), topics: vec![], }], ); @@ -424,22 +494,24 @@ mod tests { } #[test] - fn should_fail_on_spec_version_mismatch() { + fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { - let origin = b"ethb".to_owned(); + let bridge = b"ethb".to_owned(); let id = [0; 4]; let mut message = - prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); - message.origin = CallOrigin::RealAccount(TestAccountPublic(2), TestAccountPublic(2), TestSignature(1)); + prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + message.weight = 0; System::set_block_number(1); - CallDispatch::dispatch(origin, id, message); + CallDispatch::dispatch(bridge, id, message); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageSignatureMismatch(origin, id,)), + event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( + bridge, id, 1973000, 0, + )), topics: vec![], }], ); @@ -447,24 +519,25 @@ mod tests { } #[test] - fn should_fail_on_weight_mismatch() { + fn should_fail_on_signature_mismatch() { new_test_ext().execute_with(|| { - let origin = b"ethb".to_owned(); + let bridge = b"ethb".to_owned(); let id = [0; 4]; - let mut message = - prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); - message.weight = 0; + + let call_origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(99)); + let message = prepare_message( + call_origin, + Call::System(>::remark(vec![1, 2, 3])), + ); System::set_block_number(1); - CallDispatch::dispatch(origin, id, message); + CallDispatch::dispatch(bridge, id, message); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( - origin, id, 1973000, 0, - )), + event: TestEvent::call_dispatch(Event::::MessageSignatureMismatch(bridge, id)), topics: vec![], }], ); @@ -472,24 +545,20 @@ mod tests { } #[test] - fn should_fail_on_signature_mismatch() { + fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { - let origin = b"ethb".to_owned(); + let bridge = b"ethb".to_owned(); let id = [0; 4]; - let mut message = - prepare_bridge_message(Call::System(>::remark(vec![1, 2, 3]))); - message.weight = 0; + let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); System::set_block_number(1); - CallDispatch::dispatch(origin, id, message); + CallDispatch::dispatch(bridge, id, message); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( - origin, id, 1973000, 0, - )), + event: TestEvent::call_dispatch(Event::::MessageDispatched(bridge, id, Ok(()))), topics: vec![], }], ); @@ -497,104 +566,115 @@ mod tests { } #[test] - fn should_dispatch_bridge_message_from_non_root_origin() { + fn should_dispatch_bridge_message_from_target_origin() { new_test_ext().execute_with(|| { - let origin = b"ethb".to_owned(); let id = [0; 4]; - let message = prepare_bridge_message(Call::System(>::fill_block( - Perbill::from_percent(10), - ))); + let bridge = b"ethb".to_owned(); + + let call = Call::System(>::remark(vec![])); + let message = prepare_target_message(call); System::set_block_number(1); - CallDispatch::dispatch(origin, id, message); + CallDispatch::dispatch(bridge, id, message); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageDispatched( - origin, - id, - Err(DispatchError::BadOrigin) - )), + event: TestEvent::call_dispatch(Event::::MessageDispatched(bridge, id, Ok(()))), topics: vec![], }], ); - }); + }) } #[test] - fn dispatch_supports_different_accounts() { - fn dispatch_suicide(call_origin: CallOrigin) { - let origin = b"ethb".to_owned(); + fn should_dispatch_bridge_message_from_source_origin() { + new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = prepare_bridge_message(Call::System(>::suicide())); - message.origin = call_origin; + let bridge = b"ethb".to_owned(); - System::set_block_number(1); - CallDispatch::dispatch(origin, id, message); - } + let call = Call::System(>::remark(vec![])); + let message = prepare_source_message(call); - new_test_ext().execute_with(|| { - // 'create' real account - let real_account_id = 1; - System::inc_account_nonce(real_account_id); - // 'create' bridge account - let bridge_account_id: AccountId = bridge_account_id(*b"ethb", CALL_DISPATCH_MODULE_PREFIX); - System::inc_account_nonce(bridge_account_id); - - assert_eq!(System::account_nonce(real_account_id), 1); - assert_eq!(System::account_nonce(bridge_account_id), 1); - - // kill real account - dispatch_suicide(CallOrigin::RealAccount( - TestAccountPublic(real_account_id), - TestAccountPublic(real_account_id), - TestSignature(real_account_id), - )); - assert_eq!(System::account_nonce(real_account_id), 0); - assert_eq!(System::account_nonce(bridge_account_id), 1); + System::set_block_number(1); + CallDispatch::dispatch(bridge, id, message); - // kill bridge account - dispatch_suicide(CallOrigin::BridgeAccount); - assert_eq!(System::account_nonce(real_account_id), 0); - assert_eq!(System::account_nonce(bridge_account_id), 0); - }); + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageDispatched(bridge, id, Ok(()))), + topics: vec![], + }], + ); + }) } #[test] - fn origin_is_checked_when_verify_sending_message() { - let mut message = prepare_bridge_message(Call::System(>::suicide())); + fn origin_is_checked_when_verifying_sending_message_using_source_root_account() { + let call = Call::System(>::remark(vec![])); + let message = prepare_root_message(call); - // when message is sent by root, CallOrigin::BridgeAccount is allowed + // When message is sent by Root, CallOrigin::SourceRoot is allowed assert!(matches!( - verify_sending_message(Origin::from(RawOrigin::Root), &message), + verify_message_origin(Origin::from(RawOrigin::Root), &message), Ok(None) )); - // when message is sent by some real account, CallOrigin::BridgeAccount is not allowed + // when message is sent by some real account, CallOrigin::SourceRoot is not allowed + assert!(matches!( + verify_message_origin(Origin::from(RawOrigin::Signed(1)), &message), + Err(BadOrigin) + )); + } + + #[test] + fn origin_is_checked_when_verifying_sending_message_using_target_account() { + let call = Call::System(>::remark(vec![])); + let message = prepare_target_message(call); + + // When message is sent by Root, CallOrigin::TargetAccount is not allowed assert!(matches!( - verify_sending_message(Origin::from(RawOrigin::Signed(1)), &message), + verify_message_origin(Origin::from(RawOrigin::Root), &message), Err(BadOrigin) )); - // when message is sent by root, CallOrigin::RealAccount is not allowed - message.origin = CallOrigin::RealAccount(TestAccountPublic(2), TestAccountPublic(2), TestSignature(2)); + // When message is sent by some other account, it is rejected assert!(matches!( - verify_sending_message(Origin::from(RawOrigin::Root), &message), + verify_message_origin(Origin::from(RawOrigin::Signed(2)), &message), Err(BadOrigin) )); - // when message is sent by some other account, it is rejected + // When message is sent by a real account, it is allowed to have origin + // CallOrigin::TargetAccount assert!(matches!( - verify_sending_message(Origin::from(RawOrigin::Signed(1)), &message), + verify_message_origin(Origin::from(RawOrigin::Signed(1)), &message), + Ok(Some(1)) + )); + } + + #[test] + fn origin_is_checked_when_verifying_sending_message_using_source_account() { + let call = Call::System(>::remark(vec![])); + let message = prepare_source_message(call); + + // Sending a message from the expected origin account works + assert!(matches!( + verify_message_origin(Origin::from(RawOrigin::Signed(1)), &message), + Ok(Some(1)) + )); + + // If we send a message from a different account, it is rejected + assert!(matches!( + verify_message_origin(Origin::from(RawOrigin::Signed(2)), &message), Err(BadOrigin) )); - // when message is sent real account, it is allowed to have origin CallOrigin::RealAccount + // If we try and send the message from Root, it is also rejected assert!(matches!( - verify_sending_message(Origin::from(RawOrigin::Signed(2)), &message), - Ok(Some(2)) + verify_message_origin(Origin::from(RawOrigin::Root), &message), + Err(BadOrigin) )); } } diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index 7db2429e07f10..efc9795b2e155 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -18,8 +18,7 @@ //! All payments are instant. use bp_message_lane::source_chain::MessageDeliveryAndDispatchPayment; -use bp_runtime::{bridge_account_id, MESSAGE_LANE_MODULE_PREFIX, NO_INSTANCE_ID}; -use codec::Decode; +use codec::Encode; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement}; use sp_std::fmt::Debug; @@ -33,23 +32,26 @@ impl MessageDeliveryAndDispatchPayment where Currency: CurrencyT, - AccountId: Debug + Default + Decode, + AccountId: Debug + Default + Encode, { type Error = &'static str; - fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &Currency::Balance) -> Result<(), Self::Error> { - Currency::transfer( - submitter, - &relayers_fund_account(), - *fee, - ExistenceRequirement::AllowDeath, - ) - .map_err(Into::into) + fn pay_delivery_and_dispatch_fee( + submitter: &AccountId, + fee: &Currency::Balance, + relayer_fund_account: &AccountId, + ) -> Result<(), Self::Error> { + Currency::transfer(submitter, relayer_fund_account, *fee, ExistenceRequirement::AllowDeath).map_err(Into::into) } - fn pay_relayer_reward(_confirmation_relayer: &AccountId, relayer: &AccountId, reward: &Currency::Balance) { + fn pay_relayer_reward( + _confirmation_relayer: &AccountId, + relayer: &AccountId, + reward: &Currency::Balance, + relayer_fund_account: &AccountId, + ) { let pay_result = Currency::transfer( - &relayers_fund_account(), + &relayer_fund_account, relayer, *reward, ExistenceRequirement::AllowDeath, @@ -73,9 +75,3 @@ where } } } - -/// Return account id of shared relayers-fund account that is storing all fees -/// paid by submitters, until they're claimed by relayers. -fn relayers_fund_account() -> AccountId { - bridge_account_id(NO_INSTANCE_ID, MESSAGE_LANE_MODULE_PREFIX) -} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 936d590f64108..af822e02a33f3 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -95,6 +95,11 @@ pub trait Trait: frame_system::Trait { /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the bridged chain. type InboundRelayer: Parameter; + /// A type which can be turned into an AccountId from a 256-bit hash. + /// + /// Used when deriving the shared relayer fund account. + type AccountIdConverter: sp_runtime::traits::Convert; + // Types that are used by outbound_lane (on source chain). /// Target header chain. @@ -267,6 +272,7 @@ decl_module! { T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( &submitter, &delivery_and_dispatch_fee, + &relayer_fund_account_id::(), ).map_err(|err| { frame_support::debug::trace!( "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", @@ -396,6 +402,7 @@ decl_module! { let received_range = lane.confirm_delivery(lane_data.latest_received_nonce); if let Some(received_range) = received_range { Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); + let relayer_fund_account = relayer_fund_account_id::(); // reward relayers that have delivered messages // this loop is bounded by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain @@ -413,6 +420,7 @@ decl_module! { &confirmation_relayer, &relayer, &message_data.fee, + &relayer_fund_account, ); } } @@ -636,6 +644,16 @@ fn verify_and_decode_messages_proof, Fee, Dispatch }) } +/// AccountId of the shared relayer fund account. +/// +/// This account stores all the fees paid by submitters. Relayers are able to claim these +/// funds as at their convenience. +fn relayer_fund_account_id, I: Instance>() -> T::AccountId { + use sp_runtime::traits::Convert; + let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); + T::AccountIdConverter::convert(encoded_id) +} + #[cfg(test)] mod tests { use super::*; diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 398f85f655ffd..bc7b15ab14f61 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -36,6 +36,14 @@ pub type TestPayload = (u64, Weight); pub type TestMessageFee = u64; pub type TestRelayer = u64; +pub struct AccountIdConverter; + +impl sp_runtime::traits::Convert for AccountIdConverter { + fn convert(hash: H256) -> AccountId { + hash.to_low_u64_ne() + } +} + #[derive(Clone, Eq, PartialEq, Debug)] pub struct TestRuntime; @@ -106,6 +114,8 @@ impl Trait for TestRuntime { type InboundMessageFee = TestMessageFee; type InboundRelayer = TestRelayer; + type AccountIdConverter = AccountIdConverter; + type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; @@ -234,7 +244,11 @@ impl TestMessageDeliveryAndDispatchPayment { impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { type Error = &'static str; - fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &TestMessageFee) -> Result<(), Self::Error> { + fn pay_delivery_and_dispatch_fee( + submitter: &AccountId, + fee: &TestMessageFee, + _relayer_fund_account: &AccountId, + ) -> Result<(), Self::Error> { if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) { return Err(TEST_ERROR); } @@ -243,7 +257,12 @@ impl MessageDeliveryAndDispatchPayment for TestMessag Ok(()) } - fn pay_relayer_reward(_confirmation_relayer: &AccountId, relayer: &AccountId, fee: &TestMessageFee) { + fn pay_relayer_reward( + _confirmation_relayer: &AccountId, + relayer: &AccountId, + fee: &TestMessageFee, + _relayer_fund_account: &AccountId, + ) { let key = (b":relayer-reward:", relayer, fee).encode(); frame_support::storage::unhashed::put(&key, &true); } diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 1877df90bcb37..321e09654a759 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -39,7 +39,7 @@ pub trait MessageDispatch { /// /// `bridge` indicates instance of deployed bridge where the message came from. /// - /// `id` is a short unique if of the message. + /// `id` is a short unique identifier of the message. /// /// Returns post-dispatch (actual) message weight. fn dispatch(bridge: InstanceId, id: MessageId, message: Self::Message); diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index fd188e56b7c91..4bf964c9b041a 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -93,8 +93,17 @@ pub trait MessageDeliveryAndDispatchPayment { /// Withhold/write-off delivery_and_dispatch_fee from submitter account to /// some relayers-fund account. - fn pay_delivery_and_dispatch_fee(submitter: &AccountId, fee: &Balance) -> Result<(), Self::Error>; + fn pay_delivery_and_dispatch_fee( + submitter: &AccountId, + fee: &Balance, + relayer_fund_account: &AccountId, + ) -> Result<(), Self::Error>; /// Pay reward for delivering message to the given relayer account. - fn pay_relayer_reward(confirmation_relayer: &AccountId, relayer: &AccountId, reward: &Balance); + fn pay_relayer_reward( + confirmation_relayer: &AccountId, + relayer: &AccountId, + reward: &Balance, + relayer_fund_account: &AccountId, + ); } diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index c5af6a07ad695..fc71ea7a26dbe 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -136,6 +136,14 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u64; +/// Convert a 256-bit hash into an AccountId. +pub struct AccountIdConverter; + +impl sp_runtime::traits::Convert for AccountIdConverter { + fn convert(hash: sp_core::H256) -> AccountId { + hash.to_fixed_bytes().into() + } +} sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index a9a1342a68fb1..c7d365c91bcca 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -98,6 +98,15 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u128; +/// Convert a 256-bit hash into an AccountId. +pub struct AccountIdConverter; + +impl sp_runtime::traits::Convert for AccountIdConverter { + fn convert(hash: sp_core::H256) -> AccountId { + hash.to_fixed_bytes().into() + } +} + sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 2452a9f44e630..a5aaa1cfa6444 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -13,6 +13,7 @@ num-traits = { version = "0.2", default-features = false } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -23,6 +24,7 @@ std = [ "codec/std", "frame-support/std", "num-traits/std", + "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index df0975f9815ef..926761b4ba3c4 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -18,7 +18,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode}; +use codec::Encode; +use sp_core::hash::H256; use sp_io::hashing::blake2_256; pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; @@ -46,17 +47,45 @@ pub const MESSAGE_LANE_MODULE_PREFIX: &[u8] = b"pallet-bridge/message-lane"; /// to identify deployed instance dynamically. This type is used for that. pub type InstanceId = [u8; 4]; -/// Returns id of account that acts as "system" account of given bridge instance. -/// The `module_prefix` (arbitrary slice) may be used to generate module-level -/// "system" account, so you could have separate "system" accounts for currency -/// exchange, message dispatch and other modules. +/// Type of accounts on the source chain. +pub enum SourceAccount { + /// 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. /// -/// The account is not supposed to actually exists on the chain, or to have any funds. -/// It is only used to -pub fn bridge_account_id(bridge: InstanceId, module_prefix: &[u8]) -> AccountId +/// 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(bridge_id: InstanceId, id: SourceAccount) -> H256 where - AccountId: Decode + Default, + AccountId: Encode, { - let entropy = (module_prefix, bridge).using_encoded(blake2_256); - AccountId::decode(&mut &entropy[..]).unwrap_or_default() + match id { + SourceAccount::Root => ("root", bridge_id).using_encoded(blake2_256), + SourceAccount::Account(id) => ("account", 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 `message-lane` 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() } diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 7d2f4a6dbfc65..e7812219d174a 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -26,6 +26,7 @@ use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{ConnectionParams, TransactionSignScheme}; use relay_utils::initialize::initialize_relay; use sp_core::{Bytes, Pair}; +use sp_runtime::traits::IdentifyAccount; /// Millau node client. pub type MillauClient = relay_substrate_client::Client; @@ -277,11 +278,12 @@ async fn run_command(command: cli::Command) -> Result<(), String> { let rialto_call_weight = rialto_call.get_dispatch_info().weight; let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); + let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); let rialto_origin_public = rialto_sign.signer.public(); let mut rialto_origin_signature_message = Vec::new(); rialto_call.encode_to(&mut rialto_origin_signature_message); - millau_sender_public.encode_to(&mut rialto_origin_signature_message); + millau_account_id.encode_to(&mut rialto_origin_signature_message); let rialto_origin_signature = rialto_sign.signer.sign(&rialto_origin_signature_message); let millau_call = @@ -290,8 +292,8 @@ async fn run_command(command: cli::Command) -> Result<(), String> { MessagePayload { spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, - origin: CallOrigin::RealAccount( - millau_sender_public, + origin: CallOrigin::TargetAccount( + millau_account_id, rialto_origin_public.into(), rialto_origin_signature.into(), ), @@ -391,11 +393,12 @@ async fn run_command(command: cli::Command) -> Result<(), String> { let millau_call_weight = millau_call.get_dispatch_info().weight; let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); let millau_origin_public = millau_sign.signer.public(); let mut millau_origin_signature_message = Vec::new(); millau_call.encode_to(&mut millau_origin_signature_message); - rialto_sender_public.encode_to(&mut millau_origin_signature_message); + rialto_account_id.encode_to(&mut millau_origin_signature_message); let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); let rialto_call = @@ -404,8 +407,8 @@ async fn run_command(command: cli::Command) -> Result<(), String> { MessagePayload { spec_version: millau_runtime::VERSION.spec_version, weight: millau_call_weight, - origin: CallOrigin::RealAccount( - rialto_sender_public, + origin: CallOrigin::TargetAccount( + rialto_account_id, millau_origin_public.into(), millau_origin_signature.into(), ), From 4614d220f321f2a6a3083df21026716b3ca19f39 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 1 Dec 2020 09:54:40 +0300 Subject: [PATCH 0248/1210] lower limit for message weight (#536) * lower limit for message weight * fmt * do not include tx overhead in weights returned by weight_limits_of_message_on_bridged_chain * Use correct chain in comment Co-authored-by: Hernando Castano --- bin/millau/runtime/src/rialto_messages.rs | 16 ++++++++++++---- bin/rialto/runtime/src/millau_messages.rs | 16 ++++++++++++---- bin/runtime-common/src/messages.rs | 20 +++++++++++++++----- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 5674f738e19e9..b7467e63a5aec 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -30,6 +30,7 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; +use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -87,9 +88,15 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2 + let upper_limit = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2; + + // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), + // the minimal weight of the message may be computed as message.length() + let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + + lower_limit..=upper_limit } fn weight_of_delivery_transaction() -> Weight { @@ -160,8 +167,9 @@ impl TargetHeaderChain for Rialto type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof; fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { - if payload.weight > WithRialtoMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { - return Err("Too large weight declared"); + let weight_limits = WithRialtoMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call); + if !weight_limits.contains(&payload.weight) { + return Err("Incorrect message weight declared"); } Ok(()) diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 6972a11eef098..2f087423aa49a 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -30,6 +30,7 @@ use frame_support::{ RuntimeDebug, }; use sp_core::storage::StorageKey; +use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { @@ -87,9 +88,15 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2 + let upper_limit = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2; + + // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), + // the minimal weight of the message may be computed as message.length() + let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + + lower_limit..=upper_limit } fn weight_of_delivery_transaction() -> Weight { @@ -160,8 +167,9 @@ impl TargetHeaderChain for Millau type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { - if payload.weight > WithMillauMessageBridge::maximal_dispatch_weight_of_message_on_bridged_chain() { - return Err("Payload has weight larger than maximum allowed weight"); + let weight_limits = WithMillauMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call); + if !weight_limits.contains(&payload.weight) { + return Err("Incorrect message weight declared"); } Ok(()) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index b26d9435cd6b0..db05c700c5339 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -30,7 +30,7 @@ use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; use frame_support::{traits::Instance, RuntimeDebug}; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; -use sp_std::{cmp::PartialOrd, marker::PhantomData, vec::Vec}; +use sp_std::{cmp::PartialOrd, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; /// Bidirectional message bridge. @@ -46,8 +46,18 @@ pub trait MessageBridge { /// Bridged chain in context of message bridge. type BridgedChain: ChainWithMessageLanes; - /// Maximal (dispatch) weight of the message that we are able to send to Bridged chain. - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> WeightOf>; + /// Returns feasible weights range for given message payload on the target chain. + /// + /// If message is being sent with the weight that is out of this range, then it + /// should be rejected. + /// + /// Weights returned from this function shall not include transaction overhead + /// (like weight of signature and signed extensions verification), because they're + /// already accounted by the `weight_of_delivery_transaction`. So this function should + /// return pure call dispatch weights range. + fn weight_limits_of_message_on_bridged_chain( + message_payload: &[u8], + ) -> RangeInclusive>>; /// Maximal weight of single message delivery transaction on Bridged chain. fn weight_of_delivery_transaction() -> WeightOf>; @@ -425,7 +435,7 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { unreachable!() } @@ -464,7 +474,7 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn maximal_dispatch_weight_of_message_on_bridged_chain() -> Weight { + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { unreachable!() } From a37d853a7c8942c3f3c509e09097a66fcf93b04d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 3 Dec 2020 09:44:52 +0300 Subject: [PATCH 0249/1210] Limit max number of messages in delivery transaction (#541) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * limit max number of messages in delivery tx * support max-messages-in-delivery-tx in relayer * clippy * clippy * Update modules/message-lane/src/lib.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 6 +- bin/millau/runtime/src/rialto_messages.rs | 3 +- bin/rialto/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/millau_messages.rs | 3 +- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages.rs | 396 +++++++++++++++--- modules/message-lane/src/lib.rs | 30 +- modules/message-lane/src/mock.rs | 3 + primitives/message-lane/src/target_chain.rs | 10 +- primitives/millau/src/lib.rs | 3 + primitives/rialto/src/lib.rs | 3 + .../messages-relay/src/message_lane_loop.rs | 3 + .../src/message_race_delivery.rs | 19 +- .../src/millau_messages_to_rialto.rs | 1 + .../src/rialto_messages_to_millau.rs | 1 + 15 files changed, 424 insertions(+), 65 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index cbb4a14d54622..85d4e3a7ec4b1 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -322,13 +322,17 @@ impl pallet_shift_session_manager::Trait for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = + bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + pub const MaxMessagesInDeliveryTransaction: bp_message_lane::MessageNonce = + bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION; } impl pallet_message_lane::Trait for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; type OutboundPayload = crate::rialto_messages::ToRialtoMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index b7467e63a5aec..4ff4f093d8fc5 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -193,7 +193,8 @@ impl SourceHeaderChain for Rialto { fn verify_messages_proof( proof: Self::MessagesProof, + max_messages: MessageNonce, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::(proof) + messages::target::verify_messages_proof::(proof, max_messages) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e239af930ceb2..f59137be091db 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -429,13 +429,17 @@ impl pallet_shift_session_manager::Trait for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = + bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + pub const MaxMessagesInDeliveryTransaction: bp_message_lane::MessageNonce = + bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION; } impl pallet_message_lane::Trait for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 2f087423aa49a..6a8dfba84baf2 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -193,7 +193,8 @@ impl SourceHeaderChain for Millau { fn verify_messages_proof( proof: Self::MessagesProof, + max_messages: MessageNonce, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::(proof) + messages::target::verify_messages_proof::(proof, max_messages) } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index c7a00209bc3eb..da63005c41b3b 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +hash-db = { version = "0.15.2", default-features = false } # Bridge dependencies @@ -34,6 +35,7 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", + "hash-db/std", "pallet-bridge-call-dispatch/std", "pallet-message-lane/std", "pallet-substrate-bridge/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index db05c700c5339..29caf13f95a58 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -29,6 +29,8 @@ use bp_message_lane::{ use bp_runtime::InstanceId; use codec::{Compact, Decode, Input}; use frame_support::{traits::Instance, RuntimeDebug}; +use hash_db::Hasher; +use pallet_substrate_bridge::StorageProofChecker; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; use sp_std::{cmp::PartialOrd, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; @@ -344,6 +346,7 @@ pub mod target { /// Verify proof of Bridged -> This chain messages. pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof, + max_messages: MessageNonce, ) -> Result>>>, &'static str> where ThisRuntime: pallet_substrate_bridge::Trait, @@ -351,64 +354,147 @@ pub mod target { HashOf>: Into::BridgedChain>>, { - let (bridged_header_hash, bridged_storage_proof, lane_id, begin, end) = proof; - pallet_substrate_bridge::Module::::parse_finalized_storage_proof( - bridged_header_hash.into(), - bridged_storage_proof, - |storage| { - // Read messages first. All messages that are claimed to be in the proof must - // be in the proof. So any error in `read_value`, or even missing value is fatal. - // - // Mind that we allow proofs with no messages if outbound lane state is proved. - let mut messages = Vec::with_capacity(end.saturating_sub(begin) as _); - for nonce in begin..=end { - let message_key = MessageKey { lane_id, nonce }; - let storage_message_key = pallet_message_lane::storage_keys::message_key::< - ThisRuntime, - MessageLaneInstanceOf>, - >(&lane_id, nonce); - let raw_message_data = storage - .read_value(storage_message_key.0.as_ref()) - .map_err(|_| "Failed to read message from storage proof")? - .ok_or("Message is missing from the messages proof")?; - let message_data = MessageData::>>::decode(&mut &raw_message_data[..]) - .map_err(|_| "Failed to decode message from the proof")?; - messages.push(Message { - key: message_key, - data: message_data, - }); - } + verify_messages_proof_with_parser::( + proof, + max_messages, + |bridged_header_hash, bridged_storage_proof| { + pallet_substrate_bridge::Module::::parse_finalized_storage_proof( + bridged_header_hash.into(), + bridged_storage_proof, + |storage_adapter| storage_adapter, + ) + .map(|storage| StorageProofCheckerAdapter::<_, B, ThisRuntime> { + storage, + _dummy: Default::default(), + }) + .map_err(|err| MessageProofError::Custom(err.into())) + }, + ) + .map_err(Into::into) + } - // Now let's check if proof contains outbound lane state proof. It is optional, so we - // simply ignore `read_value` errors and missing value. - let mut proved_lane_messages = ProvedLaneMessages { - lane_state: None, - messages, - }; - let storage_outbound_lane_data_key = pallet_message_lane::storage_keys::outbound_lane_data_key::< - MessageLaneInstanceOf>, - >(&lane_id); - let raw_outbound_lane_data = storage.read_value(storage_outbound_lane_data_key.0.as_ref()); - if let Ok(Some(raw_outbound_lane_data)) = raw_outbound_lane_data { - proved_lane_messages.lane_state = Some( - OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) - .map_err(|_| "Failed to decode outbound lane data from the proof")?, - ); - } + #[derive(Debug, PartialEq)] + pub(crate) enum MessageProofError { + Empty, + TooManyMessages, + MissingRequiredMessage, + FailedToDecodeMessage, + FailedToDecodeOutboundLaneState, + Custom(&'static str), + } - // Now we may actually check if the proof is empty or not. - if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { - return Err("Messages proof is empty"); + impl From for &'static str { + fn from(err: MessageProofError) -> &'static str { + match err { + MessageProofError::Empty => "Messages proof is empty", + MessageProofError::TooManyMessages => "Too many messages in the proof", + MessageProofError::MissingRequiredMessage => "Message is missing from the proof", + MessageProofError::FailedToDecodeMessage => "Failed to decode message from the proof", + MessageProofError::FailedToDecodeOutboundLaneState => { + "Failed to decode outbound lane data from the proof" } + MessageProofError::Custom(err) => err, + } + } + } - // We only support single lane messages in this schema - let mut proved_messages = ProvedMessages::new(); - proved_messages.insert(lane_id, proved_lane_messages); + pub(crate) trait MessageProofParser { + fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option>; + fn read_raw_message(&self, message_key: &MessageKey) -> Option>; + } - Ok(proved_messages) - }, - ) - .map_err(<&'static str>::from)? + struct StorageProofCheckerAdapter { + storage: StorageProofChecker, + _dummy: sp_std::marker::PhantomData<(B, ThisRuntime)>, + } + + impl MessageProofParser for StorageProofCheckerAdapter + where + H: Hasher, + B: MessageBridge, + ThisRuntime: pallet_message_lane::Trait>>, + { + fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { + let storage_outbound_lane_data_key = pallet_message_lane::storage_keys::outbound_lane_data_key::< + MessageLaneInstanceOf>, + >(lane_id); + self.storage + .read_value(storage_outbound_lane_data_key.0.as_ref()) + .ok()? + } + + fn read_raw_message(&self, message_key: &MessageKey) -> Option> { + let storage_message_key = pallet_message_lane::storage_keys::message_key::< + ThisRuntime, + MessageLaneInstanceOf>, + >(&message_key.lane_id, message_key.nonce); + self.storage.read_value(storage_message_key.0.as_ref()).ok()? + } + } + + /// Verify proof of Bridged -> This chain messages using given message proof parser. + pub(crate) fn verify_messages_proof_with_parser( + proof: FromBridgedChainMessagesProof, + max_messages: MessageNonce, + build_parser: BuildParser, + ) -> Result>>>, MessageProofError> + where + BuildParser: FnOnce(HashOf>, StorageProof) -> Result, + Parser: MessageProofParser, + { + let (bridged_header_hash, bridged_storage_proof, lane_id, begin, end) = proof; + + // receiving proofs where end < begin is ok (if proof includes outbound lane state) + // => hence unwrap_or(0) + let messages_in_the_proof = end.checked_sub(begin).and_then(|diff| diff.checked_add(1)).unwrap_or(0); + if messages_in_the_proof > max_messages { + return Err(MessageProofError::TooManyMessages); + } + + let parser = build_parser(bridged_header_hash, bridged_storage_proof)?; + + // Read messages first. All messages that are claimed to be in the proof must + // be in the proof. So any error in `read_value`, or even missing value is fatal. + // + // Mind that we allow proofs with no messages if outbound lane state is proved. + let mut messages = Vec::with_capacity(end.saturating_sub(begin) as _); + for nonce in begin..=end { + let message_key = MessageKey { lane_id, nonce }; + let raw_message_data = parser + .read_raw_message(&message_key) + .ok_or(MessageProofError::MissingRequiredMessage)?; + let message_data = MessageData::>>::decode(&mut &raw_message_data[..]) + .map_err(|_| MessageProofError::FailedToDecodeMessage)?; + messages.push(Message { + key: message_key, + data: message_data, + }); + } + + // Now let's check if proof contains outbound lane state proof. It is optional, so we + // simply ignore `read_value` errors and missing value. + let mut proved_lane_messages = ProvedLaneMessages { + lane_state: None, + messages, + }; + let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane_id); + if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { + proved_lane_messages.lane_state = Some( + OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) + .map_err(|_| MessageProofError::FailedToDecodeOutboundLaneState)?, + ); + } + + // Now we may actually check if the proof is empty or not. + if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { + return Err(MessageProofError::Empty); + } + + // We only support single lane messages in this schema + let mut proved_messages = ProvedMessages::new(); + proved_messages.insert(lane_id, proved_lane_messages); + + Ok(proved_messages) } } @@ -417,6 +503,7 @@ mod tests { use super::*; use codec::{Decode, Encode}; use frame_support::weights::Weight; + use std::ops::RangeInclusive; const DELIVERY_TRANSACTION_WEIGHT: Weight = 100; const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; @@ -685,4 +772,207 @@ mod tests { .is_ok(), ); } + + #[derive(Debug)] + struct TestMessageProofParser { + failing: bool, + messages: RangeInclusive, + outbound_lane_data: Option, + } + + impl target::MessageProofParser for TestMessageProofParser { + fn read_raw_outbound_lane_data(&self, _lane_id: &LaneId) -> Option> { + if self.failing { + Some(vec![]) + } else { + self.outbound_lane_data.clone().map(|data| data.encode()) + } + } + + fn read_raw_message(&self, message_key: &MessageKey) -> Option> { + if self.failing { + Some(vec![]) + } else if self.messages.contains(&message_key.nonce) { + Some( + MessageData:: { + payload: message_key.nonce.encode(), + fee: BridgedChainBalance(0), + } + .encode(), + ) + } else { + None + } + } + } + + #[allow(clippy::reversed_empty_ranges)] + fn no_messages_range() -> RangeInclusive { + 1..=0 + } + + #[test] + fn messages_proof_is_rejected_if_there_are_too_many_messages() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 11), + 10, + |_, _| unreachable!(), + ), + Err(target::MessageProofError::TooManyMessages), + ); + } + + #[test] + fn message_proof_is_rejected_if_build_parser_fails() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + 10, + |_, _| Err(target::MessageProofError::Custom("test")), + ), + Err(target::MessageProofError::Custom("test")), + ); + } + + #[test] + fn message_proof_is_rejected_if_required_message_is_missing() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + 10, + |_, _| Ok(TestMessageProofParser { + failing: false, + messages: 1..=5, + outbound_lane_data: None, + }), + ), + Err(target::MessageProofError::MissingRequiredMessage), + ); + } + + #[test] + fn message_proof_is_rejected_if_message_decode_fails() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + 10, + |_, _| Ok(TestMessageProofParser { + failing: true, + messages: 1..=10, + outbound_lane_data: None, + }), + ), + Err(target::MessageProofError::FailedToDecodeMessage), + ); + } + + #[test] + fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), + 10, + |_, _| Ok(TestMessageProofParser { + failing: true, + messages: no_messages_range(), + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, + }), + }), + ), + Err(target::MessageProofError::FailedToDecodeOutboundLaneState), + ); + } + + #[test] + fn message_proof_is_rejected_if_it_is_empty() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), + 10, + |_, _| Ok(TestMessageProofParser { + failing: false, + messages: no_messages_range(), + outbound_lane_data: None, + }), + ), + Err(target::MessageProofError::Empty), + ); + } + + #[test] + fn non_empty_message_proof_without_messages_is_accepted() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), + 10, + |_, _| Ok(TestMessageProofParser { + failing: false, + messages: no_messages_range(), + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, + }), + }), + ), + Ok(vec![( + Default::default(), + ProvedLaneMessages { + lane_state: Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, + }), + messages: Vec::new(), + }, + )] + .into_iter() + .collect()), + ); + } + + #[test] + fn non_empty_message_proof_is_accepted() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 1), + 10, + |_, _| Ok(TestMessageProofParser { + failing: false, + messages: 1..=1, + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, + }), + }), + ), + Ok(vec![( + Default::default(), + ProvedLaneMessages { + lane_state: Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, + }), + messages: vec![Message { + key: MessageKey { + lane_id: Default::default(), + nonce: 1 + }, + data: MessageData { + payload: 1u64.encode(), + fee: BridgedChainBalance(0) + }, + }], + }, + )] + .into_iter() + .collect()), + ); + } } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index af822e02a33f3..f51f7620a69ac 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -57,8 +57,12 @@ pub mod instant_payments; mod mock; // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) -/// Upper bound of delivery transaction weight. -const DELIVERY_BASE_WEIGHT: Weight = 0; +/// Weight of message delivery without any code that is touching messages. +const DELIVERY_OVERHEAD_WEIGHT: Weight = 0; +// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) +/// Single-message delivery weight. This shall not include message dispatch weight and +/// any delivery transaction code that is not specific to this message. +const SINGLE_MESSAGE_DELIVERY_WEIGHT: Weight = 0; /// The module configuration trait pub trait Trait: frame_system::Trait { @@ -82,6 +86,11 @@ pub trait Trait: frame_system::Trait { /// transaction#2 with individual messages [3; 4], this would be treated as single "Message" and /// would occupy single unit of `MaxUnconfirmedMessagesAtInboundLane` limit. type MaxUnconfirmedMessagesAtInboundLane: Get; + /// Maximal number of messages in single delivery transaction. This directly affects the base + /// weight of the delivery transaction. + /// + /// All transactions that deliver more messages than this number, are rejected. + type MaxMessagesInDeliveryTransaction: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter; @@ -305,7 +314,13 @@ decl_module! { } /// Receive messages proof from bridged chain. - #[weight = DELIVERY_BASE_WEIGHT + dispatch_weight] + #[weight = DELIVERY_OVERHEAD_WEIGHT + .saturating_add( + T::MaxMessagesInDeliveryTransaction::get() + .saturating_mul(SINGLE_MESSAGE_DELIVERY_WEIGHT) + ) + .saturating_add(*dispatch_weight) + ] pub fn receive_messages_proof( origin, relayer_id: T::InboundRelayer, @@ -316,7 +331,11 @@ decl_module! { let _ = ensure_signed(origin)?; // verify messages proof && convert proof into messages - let messages = verify_and_decode_messages_proof::(proof) + let messages = verify_and_decode_messages_proof::< + T::SourceHeaderChain, + T::InboundMessageFee, + T::InboundPayload, + >(proof, T::MaxMessagesInDeliveryTransaction::get()) .map_err(|err| { frame_support::debug::trace!( "Rejecting invalid messages proof: {:?}", @@ -627,8 +646,9 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorag /// Verify messages proof and return proved messages with decoded payload. fn verify_and_decode_messages_proof, Fee, DispatchPayload: Decode>( proof: Chain::MessagesProof, + max_messages: MessageNonce, ) -> Result>, Chain::Error> { - Chain::verify_messages_proof(proof).map(|messages_by_lane| { + Chain::verify_messages_proof(proof, max_messages).map(|messages_by_lane| { messages_by_lane .into_iter() .map(|(lane, lane_data)| { diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index bc7b15ab14f61..2315adba13202 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -100,12 +100,14 @@ impl frame_system::Trait for TestRuntime { parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 16; + pub const MaxMessagesInDeliveryTransaction: u64 = 128; } impl Trait for TestRuntime { type Event = TestEvent; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; type OutboundPayload = TestPayload; type OutboundMessageFee = TestMessageFee; @@ -279,6 +281,7 @@ impl SourceHeaderChain for TestSourceHeaderChain { fn verify_messages_proof( proof: Self::MessagesProof, + _max_messages: MessageNonce, ) -> Result>, Self::Error> { proof .result diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index 7b6514f26ef8f..6e64c423d1da0 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -16,7 +16,7 @@ //! Primitives of message lane module, that are used on the target chain. -use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; +use crate::{LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData}; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; @@ -67,9 +67,15 @@ pub trait SourceHeaderChain { /// Verify messages proof and return proved messages. /// + /// Returns error if either proof is incorrect, or the number of messages in the proof + /// is larger than `max_messages`. + /// /// Messages vector is required to be sorted by nonce within each lane. Out-of-order /// messages will be rejected. - fn verify_messages_proof(proof: Self::MessagesProof) -> Result>, Self::Error>; + fn verify_messages_proof( + proof: Self::MessagesProof, + max_messages: MessageNonce, + ) -> Result>, Self::Error>; } /// Called when inbound message is received. diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index fc71ea7a26dbe..1996b488fe4d6 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -76,6 +76,9 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75; /// transactions minus 10% for initialization). pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); +// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 +/// Maximal number of messages in single delivery transaction. +pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index c7d365c91bcca..618ddf5e1204a 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -38,6 +38,9 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75; /// transactions minus 10% for initialization). pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); +// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 +/// Maximal number of messages in single delivery transaction. +pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index 7cd0563c3a568..ac2a7faeb3bab 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -63,6 +63,8 @@ pub struct MessageDeliveryParams { /// unconfirmed nonces on the target node. The race would continue once they're confirmed by the /// receiving race. pub max_unconfirmed_nonces_at_target: MessageNonce, + /// Maximal number of relayed messages in single delivery transaction. + pub max_messages_in_single_batch: MessageNonce, /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. pub max_messages_weight_in_single_batch: Weight, } @@ -727,6 +729,7 @@ pub(crate) mod tests { stall_timeout: Duration::from_millis(60 * 1000), delivery_params: MessageDeliveryParams { max_unconfirmed_nonces_at_target: 4, + max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, }, }, diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 8f2a0f693ba8d..e1ad25b2748d4 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -57,6 +57,7 @@ pub async fn run( stall_timeout, MessageDeliveryStrategy::

{ max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, + max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, latest_confirmed_nonce_at_source: None, target_nonces: None, @@ -194,6 +195,8 @@ where struct MessageDeliveryStrategy { /// Maximal unconfirmed nonces at target client. max_unconfirmed_nonces_at_target: MessageNonce, + /// Maximal number of messages in the single delivery transaction. + max_messages_in_single_batch: MessageNonce, /// Maximal cumulative messages weight in the single delivery transaction. max_messages_weight_in_single_batch: Weight, /// Latest confirmed nonce at the source client. @@ -315,6 +318,7 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M .checked_sub(future_confirmed_nonce_at_target) .and_then(|diff| self.max_unconfirmed_nonces_at_target.checked_sub(diff)) .unwrap_or_default(); + let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; let mut selected_weight: Weight = 0; let mut selected_count: MessageNonce = 0; @@ -401,6 +405,7 @@ mod tests { let mut race_strategy = TestStrategy { max_unconfirmed_nonces_at_target: 4, + max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, latest_confirmed_nonce_at_source: Some(19), target_nonces: Some(TargetClientNonces { @@ -498,7 +503,19 @@ mod tests { } #[test] - fn message_delivery_strategy_limits_batch_by_messages_count() { + fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() { + let (state, mut strategy) = prepare_strategy(); + + // not all queued messages may fit in the batch, because batch has max number of messages limit + strategy.max_messages_in_single_batch = 3; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=22), proof_parameters(false, 3))) + ); + } + + #[test] + fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces() { let (state, mut strategy) = prepare_strategy(); // 1 delivery confirmation from target to source is still missing, so we may only diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index fe0e19fa03f50..617e79372ea45 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -127,6 +127,7 @@ pub fn run( stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch: bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, // TODO: subtract base weight of delivery from this when it'll be known // https://github.com/paritytech/parity-bridges-common/issues/78 max_messages_weight_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT, diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 1fc724921db10..fbec7801db56d 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -127,6 +127,7 @@ pub fn run( stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch: bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, // TODO: subtract base weight of delivery from this when it'll be known // https://github.com/paritytech/parity-bridges-common/issues/78 max_messages_weight_in_single_batch: bp_millau::MAXIMUM_EXTRINSIC_WEIGHT, From 5e096849e14982255c6743ad77fb54b4fe48f08b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 4 Dec 2020 14:14:39 +0300 Subject: [PATCH 0250/1210] reject too large (by size) messages (#551) --- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 11 +-- bin/rialto/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 11 +-- bin/runtime-common/src/messages.rs | 110 +++++++++++++++++++++- primitives/millau/src/lib.rs | 4 + primitives/rialto/src/lib.rs | 4 + 7 files changed, 127 insertions(+), 17 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 85d4e3a7ec4b1..0abd9ec5a4402 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -153,7 +153,7 @@ parameter_types! { pub const ExtrinsicBaseWeight: Weight = 10_000_000; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_millau::AVAILABLE_BLOCK_RATIO); pub MaximumExtrinsicWeight: Weight = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT; - pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const MaximumBlockLength: u32 = bp_millau::MAXIMUM_BLOCK_SIZE; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 60_000_000, // ~0.06 ms = ~60 µs diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 4ff4f093d8fc5..061137e2151b9 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -88,6 +88,10 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; + fn maximal_extrinsic_size_on_target_chain() -> u32 { + bp_rialto::MAXIMUM_EXTRINSIC_SIZE + } + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2; @@ -167,12 +171,7 @@ impl TargetHeaderChain for Rialto type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof; fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { - let weight_limits = WithRialtoMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call); - if !weight_limits.contains(&payload.weight) { - return Err("Incorrect message weight declared"); - } - - Ok(()) + messages::source::verify_chain_message::(payload) } fn verify_messages_delivery_proof( diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index f59137be091db..5b6716578c25a 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -161,7 +161,7 @@ parameter_types! { pub const ExtrinsicBaseWeight: Weight = 10_000_000; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_rialto::AVAILABLE_BLOCK_RATIO); pub MaximumExtrinsicWeight: Weight = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT; - pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; + pub const MaximumBlockLength: u32 = bp_rialto::MAXIMUM_BLOCK_SIZE; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 60_000_000, // ~0.06 ms = ~60 µs diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 6a8dfba84baf2..db2076eaa1702 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -88,6 +88,10 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; + fn maximal_extrinsic_size_on_target_chain() -> u32 { + bp_millau::MAXIMUM_EXTRINSIC_SIZE + } + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2; @@ -167,12 +171,7 @@ impl TargetHeaderChain for Millau type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { - let weight_limits = WithMillauMessageBridge::weight_limits_of_message_on_bridged_chain(&payload.call); - if !weight_limits.contains(&payload.weight) { - return Err("Incorrect message weight declared"); - } - - Ok(()) + messages::source::verify_chain_message::(payload) } fn verify_messages_delivery_proof( diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 29caf13f95a58..82c28bfa7f68d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -48,6 +48,9 @@ pub trait MessageBridge { /// Bridged chain in context of message bridge. type BridgedChain: ChainWithMessageLanes; + /// Maximal extrinsic size on target chain. + fn maximal_extrinsic_size_on_target_chain() -> u32; + /// Returns feasible weights range for given message payload on the target chain. /// /// If message is being sent with the weight that is out of this range, then it @@ -98,7 +101,7 @@ pub trait ChainWithMessageLanes { /// `frame_support::weight::Weight`. But since the meaning of weight on different chains /// may be different, the `WeightOf<>` construct is used to avoid confusion between /// different weights. - type Weight: From; + type Weight: From + PartialOrd; /// Type of balances that is used on the chain. type Balance: Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; @@ -171,6 +174,36 @@ pub mod source { } } + /// Do basic Bridged-chain specific verification of This -> Bridged chain message. + /// + /// Ok result from this function means that the delivery transaction with this message + /// may be 'mined' by the target chain. But the lane may have its own checks (e.g. fee + /// check) that would reject message (see `FromThisChainMessageVerifier`). + pub fn verify_chain_message( + payload: &FromThisChainMessagePayload, + ) -> Result<(), &'static str> { + let weight_limits = B::weight_limits_of_message_on_bridged_chain(&payload.call); + if !weight_limits.contains(&payload.weight.into()) { + return Err("Incorrect message weight declared"); + } + + // The maximal size of extrinsic at Substrate-based chain depends on the + // `frame_system::Trait::MaximumBlockLength` and `frame_system::Trait::AvailableBlockRatio` + // constants. This check is here to be sure that the lane won't stuck because message is too + // large to fit into delivery transaction. + // + // **IMPORTANT NOTE**: the delivery transaction contains storage proof of the message, not + // the message itself. The proof is always larger than the message. But unless chain state + // is enormously large, it should be several dozens/hundreds of bytes. The delivery + // transaction also contains signatures and signed extensions. Because of this, we reserve + // 1/3 of the the maximal extrinsic weight for this data. + if payload.call.len() > B::maximal_extrinsic_size_on_target_chain() as usize * 2 / 3 { + return Err("The message is too large to be sent over the lane"); + } + + Ok(()) + } + /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged chain. /// /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional conversions. @@ -511,6 +544,8 @@ mod tests { const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; const THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE: u32 = 6; + const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048; + const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain; struct OnThisChainBridge; @@ -522,8 +557,13 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; - fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { - unreachable!() + fn maximal_extrinsic_size_on_target_chain() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + + fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { + let begin = std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); + begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } fn weight_of_delivery_transaction() -> Weight { @@ -561,6 +601,10 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; + fn maximal_extrinsic_size_on_target_chain() -> u32 { + unreachable!() + } + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { unreachable!() } @@ -773,6 +817,66 @@ mod tests { ); } + #[test] + fn verify_chain_message_rejects_message_with_too_small_declared_weight() { + assert!( + source::verify_chain_message::(&source::FromThisChainMessagePayload::< + OnThisChainBridge, + > { + spec_version: 1, + weight: 5, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: vec![1, 2, 3, 4, 5, 6], + },) + .is_err() + ); + } + + #[test] + fn verify_chain_message_rejects_message_with_too_large_declared_weight() { + assert!( + source::verify_chain_message::(&source::FromThisChainMessagePayload::< + OnThisChainBridge, + > { + spec_version: 1, + weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: vec![1, 2, 3, 4, 5, 6], + },) + .is_err() + ); + } + + #[test] + fn verify_chain_message_rejects_message_too_large_message() { + assert!( + source::verify_chain_message::(&source::FromThisChainMessagePayload::< + OnThisChainBridge, + > { + spec_version: 1, + weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: vec![0; BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE as usize * 2 / 3 + 1], + },) + .is_err() + ); + } + + #[test] + fn verify_chain_message_accepts_maximal_message() { + assert_eq!( + source::verify_chain_message::(&source::FromThisChainMessagePayload::< + OnThisChainBridge, + > { + spec_version: 1, + weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: vec![0; BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE as usize * 2 / 3], + },), + Ok(()), + ); + } + #[derive(Debug)] struct TestMessageProofParser { failing: bool, diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 1996b488fe4d6..f3e90851be320 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -75,6 +75,10 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75; /// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular /// transactions minus 10% for initialization). pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); +/// Maximal size of Millau block. +pub const MAXIMUM_BLOCK_SIZE: u32 = 2 * 1024 * 1024; +/// Maximal size of single normal Millau extrinsic (75% of maximal block size). +pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLOCK_RATIO; // TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 618ddf5e1204a..ac7b260e16569 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -37,6 +37,10 @@ pub const AVAILABLE_BLOCK_RATIO: u32 = 75; /// Maximal weight of single Rialto extrinsic (65% of maximum block weight = 75% for regular /// transactions minus 10% for initialization). pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); +/// Maximal size of Rialto block. +pub const MAXIMUM_BLOCK_SIZE: u32 = 5 * 1024 * 1024; +/// Maximal size of single normal Rialto extrinsic (75% of maximal block size). +pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLOCK_RATIO; // TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. From 2277aa8b4c3d2082a9644396fd9fc6bc5f9b558a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 4 Dec 2020 18:46:35 +0300 Subject: [PATCH 0251/1210] Polkadot integration (#542) * kusama primitives + client * polkadot primitives + client * lost Chain definitions * fix compilation and fmt * Update primitives/runtime/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- primitives/kusama/Cargo.toml | 34 ++++++ primitives/kusama/src/lib.rs | 150 +++++++++++++++++++++++++++ primitives/polkadot/Cargo.toml | 34 ++++++ primitives/polkadot/src/lib.rs | 150 +++++++++++++++++++++++++++ primitives/runtime/src/lib.rs | 6 ++ relays/kusama-client/Cargo.toml | 25 +++++ relays/kusama-client/src/lib.rs | 47 +++++++++ relays/polkadot-client/Cargo.toml | 25 +++++ relays/polkadot-client/src/lib.rs | 47 +++++++++ relays/substrate-client/src/chain.rs | 3 +- relays/substrate/Cargo.toml | 4 + relays/substrate/src/main.rs | 3 + 12 files changed, 526 insertions(+), 2 deletions(-) create mode 100644 primitives/kusama/Cargo.toml create mode 100644 primitives/kusama/src/lib.rs create mode 100644 primitives/polkadot/Cargo.toml create mode 100644 primitives/polkadot/src/lib.rs create mode 100644 relays/kusama-client/Cargo.toml create mode 100644 relays/kusama-client/src/lib.rs create mode 100644 relays/polkadot-client/Cargo.toml create mode 100644 relays/polkadot-client/src/lib.rs diff --git a/primitives/kusama/Cargo.toml b/primitives/kusama/Cargo.toml new file mode 100644 index 0000000000000..619a1947126bb --- /dev/null +++ b/primitives/kusama/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "bp-kusama" +description = "Primitives of Kusama runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-message-lane = { path = "../message-lane", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/kusama/src/lib.rs b/primitives/kusama/src/lib.rs new file mode 100644 index 0000000000000..732db82bcd2fa --- /dev/null +++ b/primitives/kusama/src/lib.rs @@ -0,0 +1,150 @@ +// Copyright 2019-2020 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::Chain; +use frame_support::{weights::Weight, RuntimeDebug}; +use sp_core::Hasher as HasherT; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, +}; +use sp_std::prelude::*; + +/// Block number type used in Kusama. +pub type BlockNumber = u32; + +/// Hash type used in Kusama. +pub type Hash = ::Out; + +/// The type of an object that can produce hashes on Kusama. +pub type Hasher = BlakeTwo256; + +/// The header type used by Kusama. +pub type Header = generic::Header; + +/// Signature type used by Kusama. +pub type Signature = MultiSignature; + +/// Public key of account on Kusama chain. +pub type AccountPublic = ::Signer; + +/// Id of account on Kusama chain. +pub type AccountId = ::AccountId; + +/// Index of a transaction on the Kusama chain. +pub type Nonce = u32; + +/// Block type of Kusama. +pub type Block = generic::Block; + +/// Kusama block signed with a Justification. +pub type SignedBlock = generic::SignedBlock; + +/// The balance of an account on Polkadot. +pub type Balance = u128; + +/// Kusama chain. +#[derive(RuntimeDebug)] +pub struct Kusama; + +impl Chain for Kusama { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; +} + +/// Name of the `KusamaHeaderApi::best_blocks` runtime method. +pub const BEST_KUSAMA_BLOCKS_METHOD: &str = "KusamaHeaderApi_best_blocks"; +/// Name of the `KusamaHeaderApi::finalized_block` runtime method. +pub const FINALIZED_KUSAMA_BLOCK_METHOD: &str = "KusamaHeaderApi_finalized_block"; +/// Name of the `KusamaHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_KUSAMA_BLOCK_METHOD: &str = "KusamaHeaderApi_is_known_block"; +/// Name of the `KusamaHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_KUSAMA_HEADERS_METHOD: &str = "KusamaHeaderApi_incomplete_headers"; + +/// Maximal weight of single Kusama extrinsic. +pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = 725_000_000_000; + +// TODO: should be selected keeping in mind: finality delay on both chains + reward payout cost + messages throughput. +/// Maximal number of unconfirmed messages at inbound lane. +pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; + +sp_api::decl_runtime_apis! { + /// API for querying information about Kusama headers from the Bridge Pallet instance. + /// + /// This API is implemented by runtimes that are bridging with Kusama chain, not the + /// Kusama runtime itself. + pub trait KusamaHeaderApi { + /// Returns number and hash of the best blocks known to the bridge module. + /// + /// Will return multiple headers if there are many headers at the same "best" height. + /// + /// The caller should only submit an `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_blocks() -> Vec<(BlockNumber, Hash)>; + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (BlockNumber, Hash); + /// Returns numbers and hashes of headers that require finality proofs. + /// + /// An empty response means that there are no headers which currently require a + /// finality proof. + fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; + /// Returns true if the header is known to the runtime. + fn is_known_block(hash: Hash) -> bool; + /// Returns true if the header is considered finalized by the runtime. + fn is_finalized_block(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Kusama chain. + /// + /// This API is implemented by runtimes that are sending messages to Kusama chain, not the + /// Kusama runtime itself. + pub trait ToKusamaOutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Kusama chain. + /// + /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the + /// Kusama runtime itself. + pub trait FromKusamaInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + } +} diff --git a/primitives/polkadot/Cargo.toml b/primitives/polkadot/Cargo.toml new file mode 100644 index 0000000000000..6f79e6bd1b984 --- /dev/null +++ b/primitives/polkadot/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "bp-polkadot" +description = "Primitives of Polkadot runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-message-lane = { path = "../message-lane", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/polkadot/src/lib.rs b/primitives/polkadot/src/lib.rs new file mode 100644 index 0000000000000..d716601474679 --- /dev/null +++ b/primitives/polkadot/src/lib.rs @@ -0,0 +1,150 @@ +// Copyright 2019-2020 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_message_lane::{LaneId, MessageNonce}; +use bp_runtime::Chain; +use frame_support::{weights::Weight, RuntimeDebug}; +use sp_core::Hasher as HasherT; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, +}; +use sp_std::prelude::*; + +/// Block number type used in Polkadot. +pub type BlockNumber = u32; + +/// Hash type used in Polkadot. +pub type Hash = ::Out; + +/// The type of an object that can produce hashes on Polkadot. +pub type Hasher = BlakeTwo256; + +/// The header type used by Polkadot. +pub type Header = generic::Header; + +/// Signature type used by Polkadot. +pub type Signature = MultiSignature; + +/// Public key of account on Polkadot chain. +pub type AccountPublic = ::Signer; + +/// Id of account on Polkadot chain. +pub type AccountId = ::AccountId; + +/// Index of a transaction on the Polkadot chain. +pub type Nonce = u32; + +/// Block type of Polkadot. +pub type Block = generic::Block; + +/// Polkadot block signed with a Justification. +pub type SignedBlock = generic::SignedBlock; + +/// The balance of an account on Polkadot. +pub type Balance = u128; + +/// Polkadot chain. +#[derive(RuntimeDebug)] +pub struct Polkadot; + +impl Chain for Polkadot { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; +} + +/// Name of the `PolkadotHeaderApi::best_blocks` runtime method. +pub const BEST_POLKADOT_BLOCKS_METHOD: &str = "PolkadotHeaderApi_best_blocks"; +/// Name of the `PolkadotHeaderApi::finalized_block` runtime method. +pub const FINALIZED_POLKADOT_BLOCK_METHOD: &str = "PolkadotHeaderApi_finalized_block"; +/// Name of the `PolkadotHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_POLKADOT_BLOCK_METHOD: &str = "PolkadotHeaderApi_is_known_block"; +/// Name of the `PolkadotHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_POLKADOT_HEADERS_METHOD: &str = "PolkadotHeaderApi_incomplete_headers"; + +/// Maximal weight of single Polkadot extrinsic. +pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = 725_000_000_000; + +// TODO: should be selected keeping in mind: finality delay on both chains + reward payout cost + messages throughput. +/// Maximal number of unconfirmed messages at inbound lane. +pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; + +sp_api::decl_runtime_apis! { + /// API for querying information about Polkadot headers from the Bridge Pallet instance. + /// + /// This API is implemented by runtimes that are bridging with Polkadot chain, not the + /// Polkadot runtime itself. + pub trait PolkadotHeaderApi { + /// Returns number and hash of the best blocks known to the bridge module. + /// + /// Will return multiple headers if there are many headers at the same "best" height. + /// + /// The caller should only submit an `import_header` transaction that makes + /// (or leads to making) other header the best one. + fn best_blocks() -> Vec<(BlockNumber, Hash)>; + /// Returns number and hash of the best finalized block known to the bridge module. + fn finalized_block() -> (BlockNumber, Hash); + /// Returns numbers and hashes of headers that require finality proofs. + /// + /// An empty response means that there are no headers which currently require a + /// finality proof. + fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; + /// Returns true if the header is known to the runtime. + fn is_known_block(hash: Hash) -> bool; + /// Returns true if the header is considered finalized by the runtime. + fn is_finalized_block(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Polkadot chain. + /// + /// This API is implemented by runtimes that are sending messages to Polkadot chain, not the + /// Polkadot runtime itself. + pub trait ToPolkadotOutboundLaneApi { + /// Returns dispatch weight of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Polkadot chain. + /// + /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the + /// Polkadot runtime itself. + pub trait FromPolkadotInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + } +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 926761b4ba3c4..e23a8d887cec5 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -35,6 +35,12 @@ 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"; + /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; diff --git a/relays/kusama-client/Cargo.toml b/relays/kusama-client/Cargo.toml new file mode 100644 index 0000000000000..4ea971f0e14f8 --- /dev/null +++ b/relays/kusama-client/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "relay-kusama-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.4" } +headers-relay = { path = "../headers-relay" } +relay-substrate-client = { path = "../substrate-client" } +relay-utils = { path = "../utils" } + +# Bridge dependencies + +bp-kusama = { path = "../../primitives/kusama" } + +# Substrate Dependencies + +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/kusama-client/src/lib.rs b/relays/kusama-client/src/lib.rs new file mode 100644 index 0000000000000..9f9507f5ca62e --- /dev/null +++ b/relays/kusama-client/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2019-2020 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 . + +//! Types used to connect to the Kusama chain. + +use relay_substrate_client::{Chain, ChainBase}; +use std::time::Duration; + +/// Kusama header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Kusama chain definition +#[derive(Debug, Clone, Copy)] +pub struct Kusama; + +impl ChainBase for Kusama { + type BlockNumber = bp_kusama::BlockNumber; + type Hash = bp_kusama::Hash; + type Hasher = bp_kusama::Hasher; + type Header = bp_kusama::Header; +} + +impl Chain for Kusama { + const NAME: &'static str = "Kusama"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type AccountId = bp_kusama::AccountId; + type Index = bp_kusama::Nonce; + type SignedBlock = bp_kusama::SignedBlock; + type Call = (); +} + +/// Kusama header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/polkadot-client/Cargo.toml b/relays/polkadot-client/Cargo.toml new file mode 100644 index 0000000000000..e4b1d84eaa110 --- /dev/null +++ b/relays/polkadot-client/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "relay-polkadot-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.4" } +headers-relay = { path = "../headers-relay" } +relay-substrate-client = { path = "../substrate-client" } +relay-utils = { path = "../utils" } + +# Bridge dependencies + +bp-polkadot = { path = "../../primitives/polkadot" } + +# Substrate Dependencies + +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/polkadot-client/src/lib.rs b/relays/polkadot-client/src/lib.rs new file mode 100644 index 0000000000000..7f85de13632c3 --- /dev/null +++ b/relays/polkadot-client/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2019-2020 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 . + +//! Types used to connect to the Polkadot chain. + +use relay_substrate_client::{Chain, ChainBase}; +use std::time::Duration; + +/// Polkadot header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Polkadot chain definition +#[derive(Debug, Clone, Copy)] +pub struct Polkadot; + +impl ChainBase for Polkadot { + type BlockNumber = bp_polkadot::BlockNumber; + type Hash = bp_polkadot::Hash; + type Hasher = bp_polkadot::Hasher; + type Header = bp_polkadot::Header; +} + +impl Chain for Polkadot { + const NAME: &'static str = "Polkadot"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type AccountId = bp_polkadot::AccountId; + type Index = bp_polkadot::Nonce; + type SignedBlock = bp_polkadot::SignedBlock; + type Call = (); +} + +/// Polkadot header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index 1de2bf401f13b..37ce156a0ed2a 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -40,8 +40,7 @@ pub trait Chain: ChainBase { /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; - /// Account index (aka nonce) type. This stores the number of previous transactions associated - /// with a sender account. + /// Index of a transaction used by the chain. type Index: Parameter + Member + MaybeSerialize diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e35021d445195..f4ac7723298d3 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -18,8 +18,10 @@ structopt = "0.3" # Bridge dependencies +bp-kusama = { path = "../../primitives/kusama" } bp-message-lane = { path = "../../primitives/message-lane" } bp-millau = { path = "../../primitives/millau" } +bp-polkadot = { path = "../../primitives/polkadot" } bp-runtime = { path = "../../primitives/runtime" } bp-rialto = { path = "../../primitives/rialto" } headers-relay = { path = "../headers-relay" } @@ -27,7 +29,9 @@ messages-relay = { path = "../messages-relay" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } pallet-substrate-bridge = { path = "../../modules/substrate" } +relay-kusama-client = { path = "../kusama-client" } relay-millau-client = { path = "../millau-client" } +relay-polkadot-client = { path = "../polkadot-client" } relay-rialto-client = { path = "../rialto-client" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index e7812219d174a..8258f985a77eb 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -21,6 +21,7 @@ use codec::Encode; use frame_support::weights::GetDispatchInfo; use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; +use relay_kusama_client::Kusama; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{ConnectionParams, TransactionSignScheme}; @@ -28,6 +29,8 @@ use relay_utils::initialize::initialize_relay; use sp_core::{Bytes, Pair}; use sp_runtime::traits::IdentifyAccount; +/// Kusama node client. +pub type KusamaClient = relay_substrate_client::Client; /// Millau node client. pub type MillauClient = relay_substrate_client::Client; /// Rialto node client. From 307c79922e3852ec83c232ebe8aba963f39db246 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Dec 2020 03:13:00 +0000 Subject: [PATCH 0252/1210] Bump structopt from 0.3.20 to 0.3.21 (#562) --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 254dc4d275091..149731529f782 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.1.0" -structopt = "0.3.20" +structopt = "0.3.21" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 59e97a64d1eac..08b152b682252 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.1.0" -structopt = "0.3.20" +structopt = "0.3.21" # Bridge dependencies From 364e99bae10df929c0bf785ac389a8d7b6c90038 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Dec 2020 03:26:25 +0000 Subject: [PATCH 0253/1210] Bump serde_json from 1.0.59 to 1.0.60 (#563) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index ff05ac3dccf94..5570e9fe08778 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.11" num-traits = "0.2" parity-crypto = { version = "0.6", features = ["publickey"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.59" +serde_json = "1.0.60" time = "0.2" # Bridge dependencies From 0361091b324c16533c65ff4b158737efb035e090 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Dec 2020 04:12:59 +0000 Subject: [PATCH 0254/1210] Bump serde from 1.0.117 to 1.0.118 (#564) --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 19794755cf061..b8f4c4e232068 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" -serde = { version = "1.0.117", optional = true, features = ["derive"] } +serde = { version = "1.0.118", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 0fa93448ff4e0..aa426c02ec5a1 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } -serde = { version = "1.0.117", optional = true, features = ["derive"] } +serde = { version = "1.0.118", optional = true, features = ["derive"] } # Bridge dependencies From 53297fce9d7a81a249a6676ae4313ea03cf988fd Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 8 Dec 2020 13:58:07 +0300 Subject: [PATCH 0255/1210] Limit max number of unconfirmed messages at inbound lane (#545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * limit maximal number of unconfirmed messages at inbound lane * unrewarded_relayer_entries API * change relay to support max unrewarded relayer entries * Update modules/message-lane/src/inbound_lane.rs Co-authored-by: Tomasz Drwięga * Update relays/messages-relay/src/message_lane_loop.rs Co-authored-by: Hernando Castano * removed pub Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 7 + bin/rialto/runtime/src/lib.rs | 7 + modules/message-lane/src/inbound_lane.rs | 47 +++++- modules/message-lane/src/lib.rs | 52 +++++-- modules/message-lane/src/mock.rs | 4 +- primitives/message-lane/src/lib.rs | 10 ++ primitives/millau/src/lib.rs | 8 +- primitives/rialto/src/lib.rs | 8 +- .../messages-relay/src/message_lane_loop.rs | 25 +++- .../src/message_race_delivery.rs | 138 +++++++++++++++--- .../messages-relay/src/message_race_loop.rs | 26 ++-- .../src/message_race_receiving.rs | 5 +- .../src/message_race_strategy.rs | 7 +- relays/substrate/src/messages_lane.rs | 6 +- relays/substrate/src/messages_target.rs | 19 ++- .../src/millau_messages_to_rialto.rs | 2 + .../src/rialto_messages_to_millau.rs | 2 + 17 files changed, 321 insertions(+), 52 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 0abd9ec5a4402..53da30ad53514 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -322,6 +322,8 @@ impl pallet_shift_session_manager::Trait for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_message_lane::MessageNonce = + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; pub const MaxMessagesInDeliveryTransaction: bp_message_lane::MessageNonce = @@ -331,6 +333,7 @@ parameter_types! { impl pallet_message_lane::Trait for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; @@ -580,5 +583,9 @@ impl_runtime_apis! { fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { BridgeRialtoMessageLane::inbound_latest_confirmed_nonce(lane) } + + fn unrewarded_relayers_state(lane: bp_message_lane::LaneId) -> bp_message_lane::UnrewardedRelayersState { + BridgeRialtoMessageLane::inbound_unrewarded_relayers_state(lane) + } } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5b6716578c25a..2e5220b790588 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -429,6 +429,8 @@ impl pallet_shift_session_manager::Trait for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_message_lane::MessageNonce = + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; pub const MaxMessagesInDeliveryTransaction: bp_message_lane::MessageNonce = @@ -438,6 +440,7 @@ parameter_types! { impl pallet_message_lane::Trait for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; @@ -743,6 +746,10 @@ impl_runtime_apis! { fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { BridgeMillauMessageLane::inbound_latest_confirmed_nonce(lane) } + + fn unrewarded_relayers_state(lane: bp_message_lane::LaneId) -> bp_message_lane::UnrewardedRelayersState { + BridgeMillauMessageLane::inbound_unrewarded_relayers_state(lane) + } } #[cfg(feature = "runtime-benchmarks")] diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index 1d63b5675cf06..3a21a10223fa3 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -31,6 +31,8 @@ pub trait InboundLaneStorage { /// Lane id. fn id(&self) -> LaneId; + /// Return maximal number of unrewarded relayer entries in inbound lane. + fn max_unrewarded_relayer_entries(&self) -> MessageNonce; /// Return maximal number of unconfirmed messages in inbound lane. fn max_unconfirmed_messages(&self) -> MessageNonce; /// Get lane data from the storage. @@ -97,8 +99,14 @@ impl InboundLane { return false; } + // if there are more unrewarded relayer entries than we may accept, reject this message + if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() { + return false; + } + // if there are more unconfirmed messages than we may accept, reject this message - if self.storage.max_unconfirmed_messages() <= data.relayers.len() as MessageNonce { + let unconfirmed_messages_count = nonce.saturating_sub(data.latest_confirmed_nonce); + if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { return false; } @@ -271,10 +279,10 @@ mod tests { } #[test] - fn fails_to_receive_messages_above_max_limit_per_lane() { + fn fails_to_receive_messages_above_unrewarded_relayer_entries_limit_per_lane() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); + let max_nonce = ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); for current_nonce in 1..max_nonce + 1 { assert!(lane.receive_message::( TEST_RELAYER_A + current_nonce, @@ -303,6 +311,39 @@ mod tests { }); } + #[test] + fn fails_to_receive_messages_above_unconfirmed_messages_limit_per_lane() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); + for current_nonce in 1..=max_nonce { + assert!(lane.receive_message::( + TEST_RELAYER_A, + current_nonce, + message_data(REGULAR_PAYLOAD).into() + )); + } + // Fails to dispatch new message from different than latest relayer. + assert_eq!( + false, + lane.receive_message::( + TEST_RELAYER_B, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ) + ); + // Fails to dispatch new messages from latest relayer. + assert_eq!( + false, + lane.receive_message::( + TEST_RELAYER_A, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ) + ); + }); + } + #[test] fn correctly_receives_following_messages_from_two_relayers_alternately() { run_test(|| { diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index f51f7620a69ac..4ef8f690f3e1e 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -75,16 +75,20 @@ pub trait Trait: frame_system::Trait { /// confirmed. The reason is that if you want to use lane, you should be ready to pay /// for it. type MaxMessagesToPruneAtOnce: Get; - /// Maximal number of "messages" (see note below) in the 'unconfirmed' state at inbound lane. - /// Unconfirmed message at inbound lane is the message that has been: sent, delivered and - /// dispatched. Its delivery confirmation is still pending. This limit is introduced to bound - /// maximal number of relayers-ids in the inbound lane state. + /// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the + /// relayer has delivered messages, but either confirmations haven't been delivered back to the + /// source chain, or we haven't received reward confirmations yet. /// - /// "Message" in this context does not necessarily mean an individual message, but instead - /// continuous range of individual messages, that are delivered by single relayer. So if relayer#1 - /// has submitted delivery transaction#1 with individual messages [1; 2] and then delivery - /// transaction#2 with individual messages [3; 4], this would be treated as single "Message" and - /// would occupy single unit of `MaxUnconfirmedMessagesAtInboundLane` limit. + /// This constant limits maximal number of entries in the `InboundLaneData::relayers`. Keep + /// in mind that the same relayer account may take several (non-consecutive) entries in this + /// set. + type MaxUnrewardedRelayerEntriesAtInboundLane: Get; + /// Maximal number of unconfirmed messages at inbound lane. Unconfirmed means that the + /// message has been delivered, but either confirmations haven't been delivered back to the + /// source chain, or we haven't received reward confirmations for these messages yet. + /// + /// This constant limits difference between last message from last entry of the + /// `InboundLaneData::relayers` and first message at the first entry. type MaxUnconfirmedMessagesAtInboundLane: Get; /// Maximal number of messages in single delivery transaction. This directly affects the base /// weight of the delivery transaction. @@ -481,6 +485,17 @@ impl, I: Instance> Module { pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { InboundLanes::::get(&lane).latest_confirmed_nonce } + + /// Get state of unrewarded relayers set. + pub fn inbound_unrewarded_relayers_state( + lane: bp_message_lane::LaneId, + ) -> bp_message_lane::UnrewardedRelayersState { + let relayers = InboundLanes::::get(&lane).relayers; + bp_message_lane::UnrewardedRelayersState { + unrewarded_relayer_entries: relayers.len() as _, + messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0), + } + } } /// Getting storage keys for messages and lanes states. These keys are normally used when building @@ -569,6 +584,10 @@ impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage< self.lane_id } + fn max_unrewarded_relayer_entries(&self) -> MessageNonce { + T::MaxUnrewardedRelayerEntriesAtInboundLane::get() + } + fn max_unconfirmed_messages(&self) -> MessageNonce { T::MaxUnconfirmedMessagesAtInboundLane::get() } @@ -681,6 +700,7 @@ mod tests { message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesProof, TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; + use bp_message_lane::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Module as System, Phase}; use hex_literal::hex; @@ -916,6 +936,13 @@ mod tests { .collect(), }, ); + assert_eq!( + Module::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + messages_in_oldest_entry: 1, + }, + ); // message proof includes outbound lane state with latest confirmed message updated to 9 let mut message_proof: TestMessagesProof = Ok(vec![message(11, REGULAR_PAYLOAD)]).into(); @@ -941,6 +968,13 @@ mod tests { latest_confirmed_nonce: 9, }, ); + assert_eq!( + Module::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + messages_in_oldest_entry: 1, + }, + ); }); } diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 2315adba13202..149f27ebcf3cd 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -99,13 +99,15 @@ impl frame_system::Trait for TestRuntime { parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; - pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 16; + pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; + pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; pub const MaxMessagesInDeliveryTransaction: u64 = 128; } impl Trait for TestRuntime { type Event = TestEvent; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 848acb31b242a..86dea983d045e 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -102,6 +102,16 @@ impl Default for InboundLaneData { } } +/// Gist of `InboundLaneData::relayers` field used by runtime APIs. +#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +pub struct UnrewardedRelayersState { + /// Number of entries in the `InboundLaneData::relayers` set. + pub unrewarded_relayer_entries: MessageNonce, + /// Number of messages in the oldest entry of `InboundLaneData::relayers`. This is the + /// minimal number of reward proofs required to push out this entry from the set. + pub messages_in_oldest_entry: MessageNonce, +} + /// Outbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct OutboundLaneData { diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index f3e90851be320..054b2462169ff 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -22,7 +22,7 @@ mod millau_hash; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; @@ -83,6 +83,8 @@ pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLO // TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 1024; +/// Maximal number of unrewarded relayer entries at inbound lane. +pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; @@ -129,6 +131,8 @@ pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = "ToMillauOutboundLaneA pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_received_nonce"; /// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneApi_unrewarded_relayers_state"; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -206,5 +210,7 @@ sp_api::decl_runtime_apis! { fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index ac7b260e16569..30b1f0ae79ce2 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, MessageNonce}; +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; @@ -45,6 +45,8 @@ pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLO // TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; +/// Maximal number of unrewarded relayer entries at inbound lane. +pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; @@ -91,6 +93,8 @@ pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneAp pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; /// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneApi_unrewarded_relayers_state"; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -169,5 +173,7 @@ sp_api::decl_runtime_apis! { fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index ac2a7faeb3bab..542415ca0a8fb 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -30,7 +30,7 @@ use crate::message_race_receiving::run as run_message_receiving_race; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce, Weight}; +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, @@ -59,6 +59,10 @@ pub struct Params { /// Message delivery race parameters. #[derive(Debug, Clone)] pub struct MessageDeliveryParams { + /// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number of entries + /// in the `InboundLaneData::relayers` set, all new messages will be rejected until reward payment will + /// be proved (by including outbound lane state to the message delivery transaction). + pub max_unrewarded_relayer_entries_at_target: MessageNonce, /// Message delivery race will stop delivering messages if there are `max_unconfirmed_nonces_at_target` /// unconfirmed nonces on the target node. The race would continue once they're confirmed by the /// receiving race. @@ -153,6 +157,11 @@ pub trait TargetClient: Clone + Send + Sync { &self, id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; + /// Get state of unrewarded relayers set at the inbound lane. + async fn unrewarded_relayers_state( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, UnrewardedRelayersState), Self::Error>; /// Prove messages receiving at given block. async fn prove_messages_receiving( @@ -662,6 +671,19 @@ pub(crate) mod tests { Ok((id, data.target_latest_received_nonce)) } + async fn unrewarded_relayers_state( + &self, + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), Self::Error> { + Ok(( + id, + UnrewardedRelayersState { + unrewarded_relayer_entries: 0, + messages_in_oldest_entry: 0, + }, + )) + } + async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf, @@ -728,6 +750,7 @@ pub(crate) mod tests { reconnect_delay: Duration::from_millis(0), stall_timeout: Duration::from_millis(60 * 1000), delivery_params: MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index e1ad25b2748d4..6ad2a14533561 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -26,7 +26,7 @@ use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; -use bp_message_lane::{MessageNonce, Weight}; +use bp_message_lane::{MessageNonce, UnrewardedRelayersState, Weight}; use futures::stream::FusedStream; use relay_utils::FailedClient; use std::{collections::BTreeMap, marker::PhantomData, ops::RangeInclusive, time::Duration}; @@ -56,6 +56,7 @@ pub async fn run( target_state_updates, stall_timeout, MessageDeliveryStrategy::

{ + max_unrewarded_relayer_entries_at_target: params.max_unrewarded_relayer_entries_at_target, max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, @@ -157,13 +158,15 @@ where C: MessageLaneTargetClient

, { type Error = C::Error; + type TargetNoncesData = DeliveryRaceTargetNoncesData; async fn nonces( &self, at_block: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> { let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; + let (at_block, unrewarded_relayers) = self.client.unrewarded_relayers_state(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); @@ -174,7 +177,10 @@ where at_block, TargetClientNonces { latest_nonce: latest_received_nonce, - confirmed_nonce: Some(latest_confirmed_nonce), + nonces_data: DeliveryRaceTargetNoncesData { + confirmed_nonce: latest_confirmed_nonce, + unrewarded_relayers, + }, }, )) } @@ -191,8 +197,21 @@ where } } +/// Additional nonces data from the target client used by message delivery race. +#[derive(Debug, Clone)] +struct DeliveryRaceTargetNoncesData { + /// Latest nonce that we know: (1) has been delivered to us (2) has been confirmed + /// back to the source node (by confirmations race) and (3) relayer has received + /// reward for (and this has been confirmed by the message delivery race). + confirmed_nonce: MessageNonce, + /// State of the unrewarded relayers set at the target node. + unrewarded_relayers: UnrewardedRelayersState, +} + /// Messages delivery strategy. struct MessageDeliveryStrategy { + /// Maximal unrewarded relayer entries at target client. + max_unrewarded_relayer_entries_at_target: MessageNonce, /// Maximal unconfirmed nonces at target client. max_unconfirmed_nonces_at_target: MessageNonce, /// Maximal number of messages in the single delivery transaction. @@ -202,7 +221,7 @@ struct MessageDeliveryStrategy { /// Latest confirmed nonce at the source client. latest_confirmed_nonce_at_source: Option, /// Target nonces from the source client. - target_nonces: Option, + target_nonces: Option>, /// Basic delivery strategy. strategy: MessageDeliveryStrategyBase

, } @@ -221,6 +240,7 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M { type SourceNoncesRange = MessageWeightsMap; type ProofParameters = MessageProofParameters; + type TargetNoncesData = DeliveryRaceTargetNoncesData; fn is_empty(&self) -> bool { self.strategy.is_empty() @@ -245,22 +265,23 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M fn target_nonces_updated( &mut self, - nonces: TargetClientNonces, + nonces: TargetClientNonces, race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) { self.target_nonces = Some(nonces.clone()); - self.strategy.target_nonces_updated(nonces, race_state) + self.strategy.target_nonces_updated( + TargetClientNonces { + latest_nonce: nonces.latest_nonce, + nonces_data: (), + }, + race_state, + ) } fn select_nonces_to_deliver( &mut self, race_state: &RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) -> Option<(RangeInclusive, Self::ProofParameters)> { - const CONFIRMED_NONCE_PROOF: &str = "\ - ClientNonces are crafted by MessageDeliveryRace(Source|Target);\ - MessageDeliveryRace(Source|Target) always fills confirmed_nonce field;\ - qed"; - let latest_confirmed_nonce_at_source = self.latest_confirmed_nonce_at_source?; let target_nonces = self.target_nonces.as_ref()?; @@ -295,9 +316,28 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M // // Important note: we're including outbound state lane proof whenever there are unconfirmed nonces // on the target chain. Other strategy is to include it only if it's absolutely necessary. - let latest_confirmed_nonce_at_target = target_nonces.confirmed_nonce.expect(CONFIRMED_NONCE_PROOF); + let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce; let outbound_state_proof_required = latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; + // The target node would also reject messages if there are too many entries in the + // "unrewarded relayers" set. If we are unable to prove new rewards to the target node, then + // we should wait for confirmations race. + let unrewarded_relayer_entries_limit_reached = + target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries + >= self.max_unrewarded_relayer_entries_at_target; + if unrewarded_relayer_entries_limit_reached { + // so there are already too many unrewarded relayer entries in the set + // + // => check if we can prove enough rewards. If not, we should wait for more rewards to be paid + let number_of_rewards_being_proved = + latest_confirmed_nonce_at_source.saturating_sub(latest_confirmed_nonce_at_target); + let enough_rewards_being_proved = number_of_rewards_being_proved + >= target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry; + if !enough_rewards_being_proved { + return None; + } + } + // If we're here, then the confirmations race did its job && sending side now knows that messages // have been delivered. Now let's select nonces that we want to deliver. // @@ -404,13 +444,20 @@ mod tests { }; let mut race_strategy = TestStrategy { + max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, latest_confirmed_nonce_at_source: Some(19), target_nonces: Some(TargetClientNonces { latest_nonce: 19, - confirmed_nonce: Some(19), + nonces_data: DeliveryRaceTargetNoncesData { + confirmed_nonce: 19, + unrewarded_relayers: UnrewardedRelayersState { + unrewarded_relayer_entries: 0, + messages_in_oldest_entry: 0, + }, + }, }), strategy: BasicStrategy::new(), }; @@ -422,9 +469,13 @@ mod tests { confirmed_nonce: Some(19), }, ); - race_strategy - .strategy - .target_nonces_updated(race_strategy.target_nonces.clone().unwrap(), &mut race_state); + race_strategy.strategy.target_nonces_updated( + TargetClientNonces { + latest_nonce: 19, + nonces_data: (), + }, + &mut race_state, + ); (race_state, race_strategy) } @@ -483,7 +534,58 @@ mod tests { // if there are new confirmed nonces on source, we want to relay this information // to target to prune rewards queue let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); - strategy.target_nonces.as_mut().unwrap().confirmed_nonce = Some(prev_confirmed_nonce_at_source - 1); + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=23), proof_parameters(true, 4))) + ); + } + + #[test] + fn message_delivery_strategy_selects_nothing_if_there_are_too_many_unrewarded_relayers() { + let (state, mut strategy) = prepare_strategy(); + + // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, + // we need to wait until rewards will be paid + { + let mut unrewarded_relayers = &mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers; + unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; + unrewarded_relayers.messages_in_oldest_entry = 4; + } + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn message_delivery_strategy_selects_nothing_if_proved_rewards_is_not_enough_to_remove_oldest_unrewarded_entry() { + let (state, mut strategy) = prepare_strategy(); + + // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, + // we need to prove at least `messages_in_oldest_entry` rewards + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + { + let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; + nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; + unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; + unrewarded_relayers.messages_in_oldest_entry = 4; + } + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + } + + #[test] + fn message_delivery_strategy_includes_outbound_state_proof_if_proved_rewards_is_enough() { + let (state, mut strategy) = prepare_strategy(); + + // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, + // we need to prove at least `messages_in_oldest_entry` rewards + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + { + let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; + nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 3; + let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; + unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; + unrewarded_relayers.messages_in_oldest_entry = 3; + } assert_eq!( strategy.select_nonces_to_deliver(&state), Some(((20..=23), proof_parameters(true, 4))) @@ -522,7 +624,7 @@ mod tests { // relay 3 new messages let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); strategy.latest_confirmed_nonce_at_source = Some(prev_confirmed_nonce_at_source - 1); - strategy.target_nonces.as_mut().unwrap().confirmed_nonce = Some(prev_confirmed_nonce_at_source - 1); + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; assert_eq!( strategy.select_nonces_to_deliver(&state), Some(((20..=22), proof_parameters(false, 3))) diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 9c80b57400341..0be247e114b77 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -83,12 +83,11 @@ pub struct SourceClientNonces { /// Nonces on the race target client. #[derive(Debug, Clone)] -pub struct TargetClientNonces { +pub struct TargetClientNonces { /// Latest nonce that is known to the target client. pub latest_nonce: MessageNonce, - /// Latest nonce that is confirmed to the bridged client. This nonce only makes - /// sense in some races. In other races it is `None`. - pub confirmed_nonce: Option, + /// Additional data from target node that may be used by the race. + pub nonces_data: TargetNoncesData, } /// One of message lane clients, which is source client for the race. @@ -121,10 +120,14 @@ pub trait SourceClient { pub trait TargetClient { /// Type of error this clients returns. type Error: std::fmt::Debug + MaybeConnectionError; + /// Type of the additional data from the target client, used by the race. + type TargetNoncesData: std::fmt::Debug; /// Return nonces that are known to the target client. - async fn nonces(&self, at_block: P::TargetHeaderId) - -> Result<(P::TargetHeaderId, TargetClientNonces), Self::Error>; + async fn nonces( + &self, + at_block: P::TargetHeaderId, + ) -> Result<(P::TargetHeaderId, TargetClientNonces), Self::Error>; /// Submit proof to the target client. async fn submit_proof( &self, @@ -140,6 +143,8 @@ pub trait RaceStrategy { type SourceNoncesRange: NoncesRange; /// Additional proof parameters required to generate proof. type ProofParameters; + /// Additional data expected from the target client. + type TargetNoncesData; /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; @@ -158,7 +163,7 @@ pub trait RaceStrategy { /// Called when nonces are updated at target node of the race. fn target_nonces_updated( &mut self, - nonces: TargetClientNonces, + nonces: TargetClientNonces, race_state: &mut RaceState, ); /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated @@ -187,10 +192,10 @@ pub struct RaceState { } /// Run race loop until connection with target or source node is lost. -pub async fn run>( +pub async fn run, TC: TargetClient

>( race_source: SC, race_source_updated: impl FusedStream>, - race_target: impl TargetClient

, + race_target: TC, race_target_updated: impl FusedStream>, stall_timeout: Duration, mut strategy: impl RaceStrategy< @@ -199,6 +204,7 @@ pub async fn run>( P::Proof, SourceNoncesRange = SC::NoncesRange, ProofParameters = SC::ProofParameters, + TargetNoncesData = TC::TargetNoncesData, >, ) -> Result<(), FailedClient> { let mut progress_context = Instant::now(); @@ -524,7 +530,7 @@ mod tests { strategy.target_nonces_updated( TargetClientNonces { latest_nonce: 5u64, - confirmed_nonce: None, + nonces_data: (), }, &mut race_state, ); diff --git a/relays/messages-relay/src/message_race_receiving.rs b/relays/messages-relay/src/message_race_receiving.rs index 852b2893f1a3b..0da5fffe8b06f 100644 --- a/relays/messages-relay/src/message_race_receiving.rs +++ b/relays/messages-relay/src/message_race_receiving.rs @@ -157,11 +157,12 @@ where C: MessageLaneSourceClient

, { type Error = C::Error; + type TargetNoncesData = (); async fn nonces( &self, at_block: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, TargetClientNonces), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, TargetClientNonces<()>), Self::Error> { let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); @@ -170,7 +171,7 @@ where at_block, TargetClientNonces { latest_nonce: latest_confirmed_nonce, - confirmed_nonce: None, + nonces_data: (), }, )) } diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index feff1f3e20fe1..32ae46d28a4a6 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -145,6 +145,7 @@ where { type SourceNoncesRange = SourceNoncesRange; type ProofParameters = (); + type TargetNoncesData = (); fn is_empty(&self) -> bool { self.source_queue.is_empty() @@ -185,7 +186,7 @@ where fn target_nonces_updated( &mut self, - nonces: TargetClientNonces, + nonces: TargetClientNonces<()>, race_state: &mut RaceState< HeaderId, HeaderId, @@ -269,10 +270,10 @@ mod tests { } } - fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces { + fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces<()> { TargetClientNonces { latest_nonce, - confirmed_nonce: None, + nonces_data: (), } } diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs index 2ee69feb97186..0440a68dd3724 100644 --- a/relays/substrate/src/messages_lane.rs +++ b/relays/substrate/src/messages_lane.rs @@ -35,10 +35,12 @@ pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns latest received (confirmed) nonce at the the source chain. const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns latest received nonce at the source chain. + /// Name of the runtime method that returns latest received nonce at the target chain. const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns latest confirmed (reward-paid) nonce at the source chain. + /// Name of the runtime method that returns latest confirmed (reward-paid) nonce at the target chain. const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; + /// Numebr of the runtime method that returns state of "unrewarded relayers" set at the target chain. + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str; /// Name of the runtime method that returns id of best finalized source header at target chain. const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 3825a41578824..6b745cc7a83d2 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -22,7 +22,7 @@ use crate::messages_lane::SubstrateMessageLane; use crate::messages_source::read_client_state; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::InstanceId; use codec::{Decode, Encode}; use messages_relay::{ @@ -135,6 +135,23 @@ where Ok((id, latest_received_nonce)) } + async fn unrewarded_relayers_state( + &self, + id: TargetHeaderIdOf

, + ) -> Result<(TargetHeaderIdOf

, UnrewardedRelayersState), Self::Error> { + let encoded_response = self + .client + .state_call( + P::INBOUND_LANE_UNREWARDED_RELAYERS_STATE.into(), + Bytes(self.lane_id.encode()), + Some(id.1), + ) + .await?; + let unrewarded_relayers_state: UnrewardedRelayersState = + Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + Ok((id, unrewarded_relayers_state)) + } + async fn prove_messages_receiving( &self, id: TargetHeaderIdOf

, diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 617e79372ea45..5b60a90c36ec8 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -46,6 +46,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; @@ -126,6 +127,7 @@ pub fn run( reconnect_delay, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch: bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, // TODO: subtract base weight of delivery from this when it'll be known diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index fbec7801db56d..8697c79595544 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -46,6 +46,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; @@ -126,6 +127,7 @@ pub fn run( reconnect_delay, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch: bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, // TODO: subtract base weight of delivery from this when it'll be known From 0cba674679601bb8b7fc630751ccd731344ead27 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Dec 2020 01:27:21 +0300 Subject: [PATCH 0256/1210] Message lane benchmarks: start (#554) * message lane benchmarks: start * finish send_message_worst_case benchmark * fix compilation * removed redundant bench param --- bin/rialto/runtime/Cargo.toml | 1 + bin/rialto/runtime/src/lib.rs | 47 ++++++++++++ bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/src/messages.rs | 11 ++- modules/message-lane/Cargo.toml | 6 ++ modules/message-lane/src/benchmarking.rs | 92 +++++++++++++++++++++++ modules/message-lane/src/lib.rs | 11 ++- 7 files changed, 162 insertions(+), 8 deletions(-) create mode 100644 modules/message-lane/src/benchmarking.rs diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index aa426c02ec5a1..29226e1cb114b 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -121,5 +121,6 @@ runtime-benchmarks = [ "libsecp256k1", "pallet-bridge-currency-exchange/runtime-benchmarks", "pallet-bridge-eth-poa/runtime-benchmarks", + "pallet-message-lane/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 2e5220b790588..b5b1d2dddee91 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -437,6 +437,7 @@ parameter_types! { bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION; } +pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInstance; impl pallet_message_lane::Trait for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; @@ -814,6 +815,46 @@ impl_runtime_apis! { } } + use pallet_message_lane::benchmarking::{ + Module as MessageLaneBench, + Trait as MessageLaneTrait, + MessageParams as MessageLaneMessageParams, + }; + + impl MessageLaneTrait for Runtime { + fn endow_account(account: &Self::AccountId) { + pallet_balances::Module::::make_free_balance_be( + account, + 1_000_000_000_000, + ); + } + + fn prepare_message( + params: MessageLaneMessageParams, + ) -> (millau_messages::ToMillauMessagePayload, Balance) { + use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; + use bridge_runtime_common::messages; + use pallet_message_lane::benchmarking::WORST_MESSAGE_SIZE_FACTOR; + + let max_message_size = messages::source::maximal_message_size::(); + let message_size = match params.size_factor { + 0 => 1, + factor => max_message_size / WORST_MESSAGE_SIZE_FACTOR + * sp_std::cmp::min(factor, WORST_MESSAGE_SIZE_FACTOR), + }; + let message_payload = vec![0; message_size as usize]; + let dispatch_origin = pallet_bridge_call_dispatch::CallOrigin::SourceAccount(Default::default()); + + let message = ToMillauMessagePayload { + spec_version: 0, + weight: message_size as _, + origin: dispatch_origin, + call: message_payload, + }; + (message, 1_000_000_000) + } + } + add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeKovan); add_benchmark!( params, @@ -821,6 +862,12 @@ impl_runtime_apis! { pallet_bridge_currency_exchange, BridgeCurrencyExchangeBench:: ); + add_benchmark!( + params, + batches, + pallet_message_lane, + MessageLaneBench:: + ); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index db2076eaa1702..680fcb747f8cd 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -143,7 +143,7 @@ impl messages::ChainWithMessageLanes for Rialto { type Weight = Weight; type Balance = bp_rialto::Balance; - type MessageLaneInstance = pallet_message_lane::DefaultInstance; + type MessageLaneInstance = crate::WithMillauMessageLaneInstance; } /// Millau chain from message lane point of view. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 82c28bfa7f68d..e0fc4bcfe60d2 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -174,6 +174,11 @@ pub mod source { } } + /// Return maximal message size of This -> Bridged chain message. + pub fn maximal_message_size() -> u32 { + B::maximal_extrinsic_size_on_target_chain() / 3 * 2 + } + /// Do basic Bridged-chain specific verification of This -> Bridged chain message. /// /// Ok result from this function means that the delivery transaction with this message @@ -197,7 +202,7 @@ pub mod source { // is enormously large, it should be several dozens/hundreds of bytes. The delivery // transaction also contains signatures and signed extensions. Because of this, we reserve // 1/3 of the the maximal extrinsic weight for this data. - if payload.call.len() > B::maximal_extrinsic_size_on_target_chain() as usize * 2 / 3 { + if payload.call.len() > maximal_message_size::() as usize { return Err("The message is too large to be sent over the lane"); } @@ -856,7 +861,7 @@ mod tests { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: vec![0; BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE as usize * 2 / 3 + 1], + call: vec![0; source::maximal_message_size::() as usize + 1], },) .is_err() ); @@ -871,7 +876,7 @@ mod tests { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: vec![0; BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE as usize * 2 / 3], + call: vec![0; source::maximal_message_size::() as _], },), Ok(()), ); diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 05f16f189923d..7f443732cbf8f 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +num-traits = { version = "0.2", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -17,6 +18,7 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies +frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -35,8 +37,12 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "num-traits/std", "serde", "sp-core/std", "sp-runtime/std", "sp-std/std", ] +runtime-benchmarks = [ + "frame-benchmarking", +] diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs new file mode 100644 index 0000000000000..98fc68eae00d6 --- /dev/null +++ b/modules/message-lane/src/benchmarking.rs @@ -0,0 +1,92 @@ +// Copyright 2019-2020 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 . + +//! Message lane pallet benchmarking. + +use crate::{Call, Instance}; + +use bp_message_lane::{LaneId, MessageData, MessageNonce}; +use frame_benchmarking::{account, benchmarks_instance}; +use frame_support::traits::Get; +use frame_system::RawOrigin; +use num_traits::Zero; +use sp_std::prelude::*; + +/// Message crafted with this size factor should be the largest possible message. +pub const WORST_MESSAGE_SIZE_FACTOR: u32 = 1000; + +const SEED: u32 = 0; + +/// Module we're benchmarking here. +pub struct Module, I: crate::Instance>(crate::Module); + +/// Benchmark-specific message parameters. +pub struct MessageParams { + /// Size factor of the message payload. Message payload grows with every factor + /// increment. Zero is the smallest possible message and the `WORST_MESSAGE_SIZE_FACTOR` is + /// largest possible message. + pub size_factor: u32, +} + +/// Trait that must be implemented by runtime. +pub trait Trait: crate::Trait { + /// Create given account and give it enough balance for test purposes. + fn endow_account(account: &Self::AccountId); + /// Prepare message to send over lane. + fn prepare_message(params: MessageParams) -> (Self::OutboundPayload, Self::OutboundMessageFee); +} + +benchmarks_instance! { + _ { } + + // Benchmark `send_message` extrinsic with the worst possible conditions: + // * outbound lane already has state, so it needs to be read and decoded; + // * relayers fund account does not exists (in practice it needs to exist in production environment); + // * maximal number of messages is being pruned during the call; + // * message size is maximal for the target chain. + send_message_worst_case { + let i in 1..100; + + let lane_id = bench_lane_id(); + let sender = account("sender", i, SEED); + T::endow_account(&sender); + + // 'send' messages that are to be pruned when our message is sent + for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { + send_regular_message::(); + } + confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); + + let (payload, fee) = T::prepare_message(MessageParams { size_factor: WORST_MESSAGE_SIZE_FACTOR }); + }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) +} + +fn bench_lane_id() -> LaneId { + *b"test" +} + +fn send_regular_message, I: Instance>() { + let mut outbound_lane = crate::outbound_lane::(bench_lane_id()); + outbound_lane.send_message(MessageData { + payload: vec![], + fee: Zero::zero(), + }); +} + +fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { + let mut outbound_lane = crate::outbound_lane::(bench_lane_id()); + assert!(outbound_lane.confirm_delivery(nonce).is_some()); +} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 4ef8f690f3e1e..13d43848938d2 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -45,6 +45,7 @@ use frame_support::{ Parameter, StorageMap, }; use frame_system::{ensure_signed, RawOrigin}; +use num_traits::Zero; use sp_runtime::{traits::BadOrigin, DispatchResult}; use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; @@ -53,6 +54,9 @@ mod outbound_lane; pub mod instant_payments; +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + #[cfg(test)] mod mock; @@ -71,9 +75,8 @@ pub trait Trait: frame_system::Trait { /// They overarching event type. type Event: From> + Into<::Event>; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs - /// whenever outbound lane is updated - i.e. when new message is sent, or receival is - /// confirmed. The reason is that if you want to use lane, you should be ready to pay - /// for it. + /// whenever new message is sent. The reason is that if you want to use lane, you should + /// be ready to pay for its maintenance. type MaxMessagesToPruneAtOnce: Get; /// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the /// relayer has delivered messages, but either confirmations haven't been delivered back to the @@ -99,7 +102,7 @@ pub trait Trait: frame_system::Trait { /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter; /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Parameter; + type OutboundMessageFee: Parameter + Zero; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; From a6783b0e5256f7d92fc2be58f3ea29304f1cf363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 8 Dec 2020 23:29:32 +0100 Subject: [PATCH 0257/1210] Verify Source origin in TargetChainVerifier (#558) * Make sure to verify sender's origin. * Make sure to use dispatch verification. * Add tests. * cargo fmt --all * Remove superfluous lifetime. * Move the check to MessageLanVerifier. * cargo fmt --all * Fix docs. --- bin/runtime-common/src/messages.rs | 106 ++++++++++++++++--- modules/call-dispatch/src/lib.rs | 58 +++++----- modules/message-lane/src/instant_payments.rs | 15 ++- modules/message-lane/src/lib.rs | 19 ++-- modules/message-lane/src/mock.rs | 8 +- primitives/message-lane/Cargo.toml | 2 + primitives/message-lane/src/source_chain.rs | 11 +- 7 files changed, 153 insertions(+), 66 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index e0fc4bcfe60d2..0c7d4ff4be02b 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -22,7 +22,7 @@ use bp_message_dispatch::MessageDispatch as _; use bp_message_lane::{ - source_chain::LaneMessageVerifier, + source_chain::{LaneMessageVerifier, Sender}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; @@ -149,25 +149,34 @@ pub mod source { #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); - impl - LaneMessageVerifier>, FromThisChainMessagePayload, BalanceOf>> + pub(crate) const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; + pub(crate) const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; + + impl LaneMessageVerifier>, FromThisChainMessagePayload, BalanceOf>> for FromThisChainMessageVerifier + where + B: MessageBridge, + AccountIdOf>: PartialEq + Clone, { type Error = &'static str; fn verify_message( - _submitter: &AccountIdOf>, + submitter: &Sender>>, delivery_and_dispatch_fee: &BalanceOf>, _lane: &LaneId, payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { + // Do the dispatch-specific check. We assume that the target chain uses + // `CallDispatch`, so we verify the message accordingly. + pallet_bridge_call_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; + let minimal_fee_in_bridged_tokens = estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; // compare with actual fee paid let actual_fee_in_bridged_tokens = B::this_balance_to_bridged_balance(*delivery_and_dispatch_fee); if actual_fee_in_bridged_tokens < minimal_fee_in_bridged_tokens { - return Err("Too low fee paid"); + return Err(TOO_LOW_FEE); } Ok(()) @@ -639,7 +648,7 @@ mod tests { } } - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Decode, Encode, Clone)] struct ThisChainAccountId(u32); #[derive(Debug, PartialEq, Decode, Encode)] struct ThisChainSigner(u32); @@ -780,6 +789,8 @@ mod tests { ); } + const TEST_LANE_ID: &LaneId = b"test"; + #[test] fn message_fee_is_checked_by_verifier() { const EXPECTED_MINIMAL_FEE: u32 = 2640; @@ -802,20 +813,91 @@ mod tests { ); // and now check that the verifier checks the fee - assert!( + assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &ThisChainAccountId(0), + &Sender::Root, &ThisChainBalance(1), - &*b"test", + &TEST_LANE_ID, + &payload, + ), + Err(source::TOO_LOW_FEE) + ); + assert!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::Root, + &ThisChainBalance(1_000_000), + &TEST_LANE_ID, &payload, ) - .is_err(), + .is_ok(), + ); + } + + #[test] + fn should_disallow_root_calls_from_regular_accounts() { + // payload of the This -> Bridged chain message + let payload = source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: 100, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: vec![42], + }; + + // and now check that the verifier checks the fee + assert_eq!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::Signed(ThisChainAccountId(0)), + &ThisChainBalance(1_000_000), + &TEST_LANE_ID, + &payload, + ), + Err(source::BAD_ORIGIN) + ); + assert_eq!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::None, + &ThisChainBalance(1_000_000), + &TEST_LANE_ID, + &payload, + ), + Err(source::BAD_ORIGIN) + ); + assert!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::Root, + &ThisChainBalance(1_000_000), + &TEST_LANE_ID, + &payload, + ) + .is_ok(), + ); + } + + #[test] + fn should_verify_source_and_target_origin_matching() { + // payload of the This -> Bridged chain message + let payload = source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: 100, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), + call: vec![42], + }; + + // and now check that the verifier checks the fee + assert_eq!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::Signed(ThisChainAccountId(0)), + &ThisChainBalance(1_000_000), + &TEST_LANE_ID, + &payload, + ), + Err(source::BAD_ORIGIN) ); assert!( source::FromThisChainMessageVerifier::::verify_message( - &ThisChainAccountId(0), + &Sender::Signed(ThisChainAccountId(1)), &ThisChainBalance(1_000_000), - &*b"test", + &TEST_LANE_ID, &payload, ) .is_ok(), diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 63d3ff25d54a2..6e7d26f545e0d 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -30,11 +30,12 @@ use codec::{Decode, Encode}; use frame_support::{ decl_event, decl_module, decl_storage, dispatch::{Dispatchable, Parameter}, + ensure, traits::Get, weights::{extract_actual_weight, GetDispatchInfo}, RuntimeDebug, }; -use frame_system::{ensure_root, ensure_signed, RawOrigin}; +use frame_system::RawOrigin; use sp_runtime::{ traits::{BadOrigin, Convert, IdentifyAccount, MaybeDisplay, MaybeSerializeDeserialize, Member, Verify}, DispatchResult, @@ -266,39 +267,31 @@ impl, I: Instance> MessageDispatch for Module { /// For example, if a message is sent from a "regular" account on the source chain it will not be /// allowed to be dispatched as Root on the target chain. This is a useful check to do on the source /// chain _before_ sending a message whose dispatch will be rejected on the target chain. -pub fn verify_message_origin< - SourceChainOuterOrigin, - SourceChainAccountId, - TargetChainAccountPublic, - TargetChainSignature, - Call, ->( - sender_origin: SourceChainOuterOrigin, +pub fn verify_message_origin( + sender_origin: &RawOrigin, message: &MessagePayload, ) -> Result, BadOrigin> where - SourceChainOuterOrigin: Into, SourceChainOuterOrigin>>, - SourceChainAccountId: PartialEq, + SourceChainAccountId: PartialEq + Clone, { match message.origin { CallOrigin::SourceRoot => { - ensure_root(sender_origin)?; + ensure!(sender_origin == &RawOrigin::Root, BadOrigin); Ok(None) } CallOrigin::TargetAccount(ref source_account_id, _, _) => { - let source_chain_signer = ensure_signed(sender_origin)?; - if source_chain_signer != *source_account_id { - return Err(BadOrigin); - } - - Ok(Some(source_chain_signer)) + ensure!( + sender_origin == &RawOrigin::Signed(source_account_id.clone()), + BadOrigin + ); + Ok(Some(source_account_id.clone())) } CallOrigin::SourceAccount(ref source_account_id) => { - let source_chain_signer = ensure_signed(sender_origin)?; - if source_chain_signer != *source_account_id { - return Err(BadOrigin); - } - Ok(Some(source_chain_signer)) + ensure!( + sender_origin == &RawOrigin::Signed(source_account_id.clone()), + BadOrigin + ); + Ok(Some(source_account_id.clone())) } } } @@ -617,14 +610,11 @@ mod tests { let message = prepare_root_message(call); // When message is sent by Root, CallOrigin::SourceRoot is allowed - assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Root), &message), - Ok(None) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(None))); // when message is sent by some real account, CallOrigin::SourceRoot is not allowed assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Signed(1)), &message), + verify_message_origin(&RawOrigin::Signed(1), &message), Err(BadOrigin) )); } @@ -636,20 +626,20 @@ mod tests { // When message is sent by Root, CallOrigin::TargetAccount is not allowed assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Root), &message), + verify_message_origin(&RawOrigin::Root, &message), Err(BadOrigin) )); // When message is sent by some other account, it is rejected assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Signed(2)), &message), + verify_message_origin(&RawOrigin::Signed(2), &message), Err(BadOrigin) )); // When message is sent by a real account, it is allowed to have origin // CallOrigin::TargetAccount assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Signed(1)), &message), + verify_message_origin(&RawOrigin::Signed(1), &message), Ok(Some(1)) )); } @@ -661,19 +651,19 @@ mod tests { // Sending a message from the expected origin account works assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Signed(1)), &message), + verify_message_origin(&RawOrigin::Signed(1), &message), Ok(Some(1)) )); // If we send a message from a different account, it is rejected assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Signed(2)), &message), + verify_message_origin(&RawOrigin::Signed(2), &message), Err(BadOrigin) )); // If we try and send the message from Root, it is also rejected assert!(matches!( - verify_message_origin(Origin::from(RawOrigin::Root), &message), + verify_message_origin(&RawOrigin::Root, &message), Err(BadOrigin) )); } diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index efc9795b2e155..fe860fdb3f8ac 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -17,7 +17,7 @@ //! Implementation of `MessageDeliveryAndDispatchPayment` trait on top of `Currency` trait. //! All payments are instant. -use bp_message_lane::source_chain::MessageDeliveryAndDispatchPayment; +use bp_message_lane::source_chain::{MessageDeliveryAndDispatchPayment, Sender}; use codec::Encode; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement}; use sp_std::fmt::Debug; @@ -37,11 +37,20 @@ where type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &AccountId, + submitter: &Sender, fee: &Currency::Balance, relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { - Currency::transfer(submitter, relayer_fund_account, *fee, ExistenceRequirement::AllowDeath).map_err(Into::into) + match submitter { + Sender::Signed(submitter) => { + Currency::transfer(submitter, relayer_fund_account, *fee, ExistenceRequirement::AllowDeath) + .map_err(Into::into) + } + Sender::Root | Sender::None => { + // fixme: we might want to add root account id to this struct. + Err("Root and None account is not allowed to send regular messages.") + } + } } fn pay_relayer_reward( diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 13d43848938d2..1c8553b8bb89b 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -255,18 +255,19 @@ decl_module! { delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResult { ensure_operational::()?; - let submitter = ensure_signed(origin)?; + let submitter = origin.into().map_err(|_| BadOrigin)?; // let's first check if message can be delivered to target chain - T::TargetHeaderChain::verify_message(&payload).map_err(|err| { - frame_support::debug::trace!( - "Message to lane {:?} is rejected by target chain: {:?}", - lane_id, - err, - ); + T::TargetHeaderChain::verify_message(&payload) + .map_err(|err| { + frame_support::debug::trace!( + "Message to lane {:?} is rejected by target chain: {:?}", + lane_id, + err, + ); - Error::::MessageRejectedByChainVerifier - })?; + Error::::MessageRejectedByChainVerifier + })?; // now let's enforce any additional lane rules T::LaneMessageVerifier::verify_message( diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 149f27ebcf3cd..cdf29938d8987 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -17,7 +17,7 @@ use crate::Trait; use bp_message_lane::{ - source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, + source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, Sender, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, }; @@ -209,7 +209,7 @@ impl LaneMessageVerifier for TestLaneMes type Error = &'static str; fn verify_message( - _submitter: &AccountId, + _submitter: &Sender, delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, _payload: &TestPayload, @@ -234,7 +234,7 @@ impl TestMessageDeliveryAndDispatchPayment { /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - frame_support::storage::unhashed::get(b":message-fee:") == Some((submitter, fee)) + frame_support::storage::unhashed::get(b":message-fee:") == Some((Sender::Signed(submitter), fee)) } /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is @@ -249,7 +249,7 @@ impl MessageDeliveryAndDispatchPayment for TestMessag type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &AccountId, + submitter: &Sender, fee: &TestMessageFee, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index 63380914e7945..87088aed64d58 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "1.3.1", default-features = # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [features] @@ -19,5 +20,6 @@ default = ["std"] std = [ "codec/std", "frame-support/std", + "frame-system/std", "sp-std/std" ] diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index 4bf964c9b041a..f854b0356c130 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -21,12 +21,15 @@ use crate::{InboundLaneData, LaneId}; use frame_support::Parameter; use sp_std::fmt::Debug; +/// The sender of the message on the source chain. +pub type Sender = frame_system::RawOrigin; + /// Target chain API. Used by source chain to verify target chain proofs. /// /// All implementations of this trait should only work with finalized data that /// can't change. Wrong implementation may lead to invalid lane states (i.e. lane /// that's stuck) and/or processing messages without paying fees. -pub trait TargetHeaderChain { +pub trait TargetHeaderChain { /// Error type. type Error: Debug + Into<&'static str>; @@ -50,7 +53,7 @@ pub trait TargetHeaderChain { /// Verify messages delivery proof and return lane && nonce of the latest recevied message. fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error>; + ) -> Result<(LaneId, InboundLaneData), Self::Error>; } /// Lane message verifier. @@ -67,7 +70,7 @@ pub trait LaneMessageVerifier { /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the lane. fn verify_message( - submitter: &Submitter, + submitter: &Sender, delivery_and_dispatch_fee: &Fee, lane: &LaneId, payload: &Payload, @@ -94,7 +97,7 @@ pub trait MessageDeliveryAndDispatchPayment { /// Withhold/write-off delivery_and_dispatch_fee from submitter account to /// some relayers-fund account. fn pay_delivery_and_dispatch_fee( - submitter: &AccountId, + submitter: &Sender, fee: &Balance, relayer_fund_account: &AccountId, ) -> Result<(), Self::Error>; From f8666a03f99e7309129775653238a87467e96502 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 9 Dec 2020 07:30:52 -0500 Subject: [PATCH 0258/1210] Cross-Chain Transfer Generator (#535) * Attempt at adding Cross-Chain Transfer Generator * Add Transfer subcommand for sending messages to Rialto * Add temp helper script for sending messages * Remove Message and Lane Ids from Dispatch Event * Increase transfer amount used by script * Endow derived Dave account on Rialto with funds * Update Message generator to send more types of messages This commit first of all updates the script to use the new CLI commands for sending messages. Second, it adds messages which are sent from both Target and Source origins. * Generate messages from Root origin * Remove dbg! logs from relayer * Log AccountId as well as HexId * Remove Balances logs * Add InstanceId and MessageId back to Dispatch Event * Add InstanceId and MessageId types for Apps * Add missing comment * Document derived accounts as tests * Move shared commands to variables * Add example usage for send_message script * Add docs to message variants * Fix Clippy complaint --- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/chain_spec.rs | 24 +++++++++++++++++ modules/call-dispatch/src/lib.rs | 16 ++++++++--- primitives/rialto/src/lib.rs | 17 ++++++++++-- relays/substrate/src/cli.rs | 35 ++++++++++++++++++------ relays/substrate/src/main.rs | 44 ++++++++++++++++++++++--------- 6 files changed, 111 insertions(+), 26 deletions(-) diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 08b152b682252..c5453468f7b13 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,6 +17,7 @@ structopt = "0.3.21" bp-message-lane = { path = "../../../primitives/message-lane" } bp-runtime = { path = "../../../primitives/runtime" } +bp-rialto = { path = "../../../primitives/rialto" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } rialto-runtime = { path = "../runtime" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 939dcc5e3fe6b..229fbd1cc90ef 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_rialto::derive_account_from_millau_id; use rialto_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauConfig, BridgeRialtoPoAConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, @@ -121,6 +122,10 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + derive_account_from_millau_id(bp_runtime::SourceAccount::Root), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), ], true, ) @@ -191,3 +196,22 @@ fn load_kovan_bridge_config() -> BridgeKovanConfig { initial_validators: rialto_runtime::kovan::genesis_validators(), } } + +#[test] +fn derived_dave_account_is_as_expected() { + let dave = get_account_id_from_seed::("Dave"); + let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); + assert_eq!( + derived.to_string(), + "5Hg7WQyk8C1FmPzxY3xSjR7S6zZZC5sAL35vMr6NpW17jBhQ".to_string() + ); +} + +#[test] +fn derived_root_account_is_as_expected() { + let root: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Root); + assert_eq!( + root.to_string(), + "5HYYwXQvxhgdcBYs6kzqfK1HW6M3UF3Kh4YM7j288yiqbhnt".to_string() + ); +} diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 6e7d26f545e0d..19c728162e64c 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -211,8 +211,10 @@ impl, I: Instance> MessageDispatch for Module { // prepare dispatch origin let origin_account = match message.origin { CallOrigin::SourceRoot => { - let encoded_id = derive_account_id::(bridge, SourceAccount::Root); - T::AccountIdConverter::convert(encoded_id) + let hex_id = derive_account_id::(bridge, SourceAccount::Root); + let target_id = T::AccountIdConverter::convert(hex_id); + frame_support::debug::trace!("Root Account: {:?}", &target_id); + target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { let mut signed_message = Vec::new(); @@ -232,18 +234,24 @@ impl, I: Instance> MessageDispatch for Module { return; } + frame_support::debug::trace!("Target Account: {:?}", &target_account); target_account } CallOrigin::SourceAccount(source_account_id) => { - let encoded_id = derive_account_id(bridge, SourceAccount::Account(source_account_id)); - T::AccountIdConverter::convert(encoded_id) + let hex_id = derive_account_id(bridge, SourceAccount::Account(source_account_id)); + let target_id = T::AccountIdConverter::convert(hex_id); + frame_support::debug::trace!("Source Account: {:?}", &target_id); + target_id } }; // finally dispatch message let origin = RawOrigin::Signed(origin_account).into(); + + frame_support::debug::trace!("Message being dispatched is: {:?}", &message.call); let dispatch_result = message.call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); + frame_support::debug::trace!( "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", bridge, diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 30b1f0ae79ce2..458a3abc0a758 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::Chain; use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::Hasher as HasherT; use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, Verify}, + traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, MultiSignature, MultiSigner, }; use sp_std::prelude::*; @@ -112,12 +112,25 @@ pub type Balance = u128; /// Convert a 256-bit hash into an AccountId. pub struct AccountIdConverter; -impl sp_runtime::traits::Convert for AccountIdConverter { +impl Convert for AccountIdConverter { fn convert(hash: sp_core::H256) -> AccountId { hash.to_fixed_bytes().into() } } +// We use this to get the account on Rialto (target) which is derived from Millau's (source) +// account. We do this so we can fund the derived account on Rialto at Genesis to it can pay +// transaction fees. +// +// The reason we can use the same `AccountId` type for both chains is because they share the same +// development seed phrase. +// +// Note that this should only be used for testing. +pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(*b"mlau", id); + AccountIdConverter::convert(encoded_id) +} + sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 0119359cde223..d3662ba26840e 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -101,12 +101,15 @@ pub enum Command { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, - /// Message type. - #[structopt(long, possible_values = &ToRialtoMessage::variants())] - message: ToRialtoMessage, /// Delivery and dispatch fee. #[structopt(long)] fee: bp_millau::Balance, + /// Message type. + #[structopt(subcommand)] + message: ToRialtoMessage, + /// The origin to use when dispatching the message on the target chain. + #[structopt(long, possible_values = &Origins::variants())] + origin: Origins, }, /// Serve given lane of Rialto -> Millau messages. RialtoMessagesToMillau { @@ -144,19 +147,35 @@ pub enum Command { }, } +/// All possible messages that may be delivered to the Rialto chain. +#[derive(StructOpt, Debug)] +pub enum ToRialtoMessage { + /// Make an on-chain remark (comment). + Remark, + /// Transfer the specified `amount` of native tokens to a particular `recipient`. + Transfer { + #[structopt(long)] + recipient: bp_rialto::AccountId, + #[structopt(long)] + amount: bp_rialto::Balance, + }, +} + arg_enum! { #[derive(Debug)] - /// All possible messages that may be delivered to the Rialto chain. - pub enum ToRialtoMessage { + /// All possible messages that may be delivered to the Millau chain. + pub enum ToMillauMessage { Remark, } } arg_enum! { #[derive(Debug)] - /// All possible messages that may be delivered to the Millau chain. - pub enum ToMillauMessage { - Remark, + /// The origin to use when dispatching the message on the target chain. + pub enum Origins { + Root, + Target, + Source, } } diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 8258f985a77eb..789105a27b18a 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -248,6 +248,8 @@ async fn run_command(command: cli::Command) -> Result<(), String> { lane, message, fee, + origin, + .. } => { let millau_client = MillauClient::new(ConnectionParams { host: millau.millau_host, @@ -277,33 +279,51 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .as_bytes() .to_vec(), )), + cli::ToRialtoMessage::Transfer { recipient, amount } => { + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) + } }; - let rialto_call_weight = rialto_call.get_dispatch_info().weight; + let rialto_call_weight = rialto_call.get_dispatch_info().weight; let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); let rialto_origin_public = rialto_sign.signer.public(); - let mut rialto_origin_signature_message = Vec::new(); - rialto_call.encode_to(&mut rialto_origin_signature_message); - millau_account_id.encode_to(&mut rialto_origin_signature_message); - let rialto_origin_signature = rialto_sign.signer.sign(&rialto_origin_signature_message); + let payload = match origin { + cli::Origins::Root => MessagePayload { + spec_version: rialto_runtime::VERSION.spec_version, + weight: rialto_call_weight, + origin: CallOrigin::SourceRoot, + call: rialto_call.encode(), + }, + cli::Origins::Source => MessagePayload { + spec_version: rialto_runtime::VERSION.spec_version, + weight: rialto_call_weight, + origin: CallOrigin::SourceAccount(millau_account_id), + call: rialto_call.encode(), + }, + cli::Origins::Target => { + let mut rialto_origin_signature_message = Vec::new(); + rialto_call.encode_to(&mut rialto_origin_signature_message); + millau_account_id.encode_to(&mut rialto_origin_signature_message); + let rialto_origin_signature = rialto_sign.signer.sign(&rialto_origin_signature_message); - let millau_call = - millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( - lane.into(), MessagePayload { spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, origin: CallOrigin::TargetAccount( - millau_account_id, + millau_account_id.clone(), rialto_origin_public.into(), rialto_origin_signature.into(), ), call: rialto_call.encode(), - }, - fee, - )); + } + } + }; + + let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( + millau_runtime::MessageLaneCall::send_message(lane.into(), payload, fee), + ); let signed_millau_call = Millau::sign_transaction( &millau_client, From ca6134a926a966df89ac2dc3395dd89faf05b3ee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Dec 2020 10:10:05 +0300 Subject: [PATCH 0259/1210] fix send_message_worst_case (#571) --- bin/rialto/runtime/src/lib.rs | 6 ++++-- modules/message-lane/src/benchmarking.rs | 11 ++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index b5b1d2dddee91..ff078a3b2b9a0 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -830,7 +830,7 @@ impl_runtime_apis! { } fn prepare_message( - params: MessageLaneMessageParams, + params: MessageLaneMessageParams, ) -> (millau_messages::ToMillauMessagePayload, Balance) { use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bridge_runtime_common::messages; @@ -843,7 +843,9 @@ impl_runtime_apis! { * sp_std::cmp::min(factor, WORST_MESSAGE_SIZE_FACTOR), }; let message_payload = vec![0; message_size as usize]; - let dispatch_origin = pallet_bridge_call_dispatch::CallOrigin::SourceAccount(Default::default()); + let dispatch_origin = pallet_bridge_call_dispatch::CallOrigin::SourceAccount( + params.sender_account, + ); let message = ToMillauMessagePayload { spec_version: 0, diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index 98fc68eae00d6..ce1d4eb19c968 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -34,11 +34,13 @@ const SEED: u32 = 0; pub struct Module, I: crate::Instance>(crate::Module); /// Benchmark-specific message parameters. -pub struct MessageParams { +pub struct MessageParams { /// Size factor of the message payload. Message payload grows with every factor /// increment. Zero is the smallest possible message and the `WORST_MESSAGE_SIZE_FACTOR` is /// largest possible message. pub size_factor: u32, + /// Message sender account. + pub sender_account: ThisAccountId, } /// Trait that must be implemented by runtime. @@ -46,7 +48,7 @@ pub trait Trait: crate::Trait { /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); /// Prepare message to send over lane. - fn prepare_message(params: MessageParams) -> (Self::OutboundPayload, Self::OutboundMessageFee); + fn prepare_message(params: MessageParams) -> (Self::OutboundPayload, Self::OutboundMessageFee); } benchmarks_instance! { @@ -70,7 +72,10 @@ benchmarks_instance! { } confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - let (payload, fee) = T::prepare_message(MessageParams { size_factor: WORST_MESSAGE_SIZE_FACTOR }); + let (payload, fee) = T::prepare_message(MessageParams { + size_factor: WORST_MESSAGE_SIZE_FACTOR, + sender_account: sender.clone(), + }); }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) } From 5371332d24fb14413ced3d697f46e0a20c01f47a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 14 Dec 2020 15:29:09 +0000 Subject: [PATCH 0260/1210] Bump async-std from 1.7.0 to 1.8.0 (#574) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 5570e9fe08778..2aff3d95ad99a 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" -async-std = "1.7.0" +async-std = "1.8.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index f4ac7723298d3..41b7d5ad7e344 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.7.0" +async-std = "1.8.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.8" From 4ca7312f517bea26b7f1351ccbf762c118badef9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 14 Dec 2020 18:44:19 -0500 Subject: [PATCH 0261/1210] High-Level Documentation (#565) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * High level docs - start. * Clean up README * Start adding details to high level docs * More docs on the header sync pallet * Testing scenarios document. * Add some scenarios. * Add multi-sig scenario. * Start writing about message dispatch pallet * Move content from old README into PoA specific doc * Apply suggestions from code review Co-authored-by: Andreas Doerr * GRANDPA for consistency. * Describe scenario steps. * WiP * Add notes about block production and forks * Update. * Add sequence diagram for Millau to Rialto transfer * Clean up header sync pallet overview * Remove leftover example code * Clean up testing scenarios and amend sequence diagram. * Linking docs. * Add some more docs. * Do a bit of cleanup on the high-level docs * Clean up the testing scenario * Fix typos in flow charts * Fix small typo * Fix indentation of Rust block * Another attempt at rendering block correctly * TIL about lazy list numbering in Markdown * Add list numbers across sections * Start counting from correct number * Update README to use correct path to local scripts * Wrap ASCII art in code block Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga Co-authored-by: Andreas Doerr --- README.md | 238 ++++++++----------------- docs/high-level-overview.md | 177 ++++++++++++++++++ modules/substrate/src/fork_tests.rs | 6 +- modules/substrate/src/justification.rs | 4 +- modules/substrate/src/lib.rs | 16 +- modules/substrate/src/storage.rs | 10 +- modules/substrate/src/verifier.rs | 12 +- primitives/runtime/src/chain.rs | 2 +- 8 files changed, 280 insertions(+), 185 deletions(-) create mode 100644 docs/high-level-overview.md diff --git a/README.md b/README.md index 8c086d0b6df1b..da98270b65951 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,18 @@ This is a collection of components for building bridges. -These components include runtime modules to help you construct your bridge's runtime, as well as -bridge relays for cross-chain communication. +These components include Substrate pallets for syncing headers, passing arbitrary messages, as well +as libraries for building relayers to provide cross-chain communication capabilities. -A bridge node is also available. The node can be used to run a test network which has support for bridging Ethereum -PoA chains to Substrate. We're working on expanding this functionality in the future. +Three bridge nodes are also available. The nodes can be used to run test networks which bridge other +Substrate chains or Ethereum Proof-of-Authority chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 ## Contents - [Installation](#installation) +- [High-Level Architecture](#high-level-architecture) - [Project Layout](#project-layout) -- [Rialto Runtime](#rialto-runtime) -- [Ethereum Node](#ethereum-node) -- [Bridge Relay](#bridge-relay) - [Running the Bridge](#running-the-bridge) ## Installation @@ -40,199 +38,119 @@ If you need more information about setting up your development environment Subst [Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good resource. -## Project Layout -Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual -"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and -the `relays` which are used to pass messages between chains. - -``` -├── bin -│ └── node // Bridge ready chain implementation -├── modules // Runtime Modules -│ ├── ethereum // Manage Ethereum PoA chain info -│ ├── ethereum-contract // Ethereum built-in for validating Substrate block info -│ ├── currency-exchange // Cross-chain fund transfers -│ └── substrate // Manage Substrate chain info -├── primitives // Shared runtime and node code -│ └── ethereum-poa // Helpers for Ethereum PoA -├── relays // Cross-chain communication -│ ├── ethereum // Sync and communicate between Ethereum PoA + Substrate chains -│ └── substrate // 🚧 WIP 🚧 -``` - -## Rialto Runtime -The node runtime consists of several runtime modules, however not all of them are used at the same -time. When running an Ethereum PoA to Substrate bridge the modules required are the Ethereum module -and the currency exchange module. When running a Substrate to Substrate bridge the Substrate and -currency exchange modules are required. - -Below is a brief description of each of the runtime modules. - -### Ethereum Bridge Runtime Module -The main job of this runtime module is to keep track of useful information an Ethereum PoA chain -which has been submitted by a bridge relayer. This includes: +## High-Level Architecture - - Ethereum headers and their status (e.g are they the best header, are they finalized, etc.) - - Current validator set, and upcoming validator sets - -This runtime module has more responsibilties than simply storing headers and validator sets. It is -able to perform checks on the incoming headers to verify their general integrity, as well as whether -or not they've been finalized by the authorities on the PoA chain. - -This module is laid out as so: +This repo has support for bridging foreign chains together using a combination of Substrate pallets +and external processes called relayers. A bridge chain is one that is able to follow the consensus +of a foreign chain independently. For example, consider the case below where we want to bridge two +Substrate based chains. ``` -├── ethereum -│ └── src -│ ├── error.rs // Runtime error handling -│ ├── finality.rs // Manage finality operations -│ ├── import.rs // Import new Ethereum headers -│ ├── lib.rs // Store headers and validator set info -│ ├── validators.rs // Track current and future PoA validator sets -│ └── verification.rs // Verify validity of incoming Ethereum headers ++---------------+ +---------------+ +| | | | +| Rialto | | Millau | +| | | | ++-------+-------+ +-------+-------+ + ^ ^ + | +---------------+ | + | | | | + +-----> | Bridge Relay | <-------+ + | | + +---------------+ ``` -### Currency Exchange Runtime Module -The currency exchange module is used to faciliate cross-chain funds transfers. It works by accepting -a transaction which proves that funds were locked on one chain, and releases a corresponding amount -of funds on the recieving chain. - -For example: Alice would like to send funds from chain A to chain B. What she would do is send a -transaction to chain A indicating that she would like to send funds to an address on chain B. This -transaction would contain the amount of funds she would like to send, as well as the address of the -recipient on chain B. These funds would now be locked on chain A. Once the block containing this -"locked-funds" transaction is finalized it can be relayed to chain B. Chain B will verify that this -transaction was included in a finalized block on chain A, and if successful deposit funds into the -recipient account on chain B. - -Chain B would need a way to convert from a foreign currency to its local currency. How this is done -is left to the runtime developer for chain B. - -This module is one example of how an on-chain light client can be used to prove a particular action -was taken on a foreign chain. In particular it enables transfers of the foreign chain's native -currency, but more sophisticated modules such as ERC20 token transfers or arbitrary message transfers -are being worked on as well. +The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by +using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact +directly they need an external service, called a relayer, to communicate. The relayer will subscribe +to new Rialto headers via RPC and submit them to the Millau chain for verification. -### Substrate Bridge Runtime Module -👷 Under Construction 👷‍♀️ +Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth +description of the bridge interaction. -## Ethereum Node -On the Ethereum side of things, we require two things. First, a Solidity smart contract to track the -Substrate headers which have been submitted to the bridge (by the relay), and a built-in contract to -be able to verify that headers have been finalized by the Grandpa finality gadget. Together this -allows the Ethereum PoA chain to verify the integrity and finality of incoming Substrate headers. - -The Solidity smart contract is not part of this repo, but can be found -[here](https://github.com/svyatonik/substrate-bridge-sol/blob/master/substrate-bridge.sol) if you're -curious. We have the contract ABI in the `ethereum/relays/res` directory. - -## Bridge Relay -The bridge relay is responsible for syncing the chains which are being bridged, and passing messages -between them. The current implementation of the relay supportings syncing and interacting with -Ethereum PoA and Substrate chains. - -The folder structure of the bridge relay is as follows: +## Project Layout +Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual +"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and +the `relays` which are used to pass messages between chains. ``` -├── relays -│ ├── ethereum -│ │ ├── res -│ │ │ └── ... -│ │ └── src -│ │ ├── ethereum_client.rs // Interface for Ethereum RPC -│ │ ├── ethereum_deploy_contract.rs // Utility for deploying bridge contract to Ethereum -│ │ ├── ethereum_exchange.rs // Relay proof of PoA -> Substrate exchange transactions -│ │ ├── ethereum_sync_loop.rs // Sync headers from Ethereum, submit to Substrate -│ │ ├── ethereum_types.rs // Useful Ethereum types -│ │ ├── exchange.rs // Relay proof of exchange transactions -│ │ ├── headers.rs // Track synced and incoming block headers -│ │ ├── main.rs // Entry point to binary -│ │ ├── substrate_client.rs // Interface for Substrate RPC -│ │ ├── substrate_sync_loop.rs // Sync headers from Substrate, submit to Ethereum -│ │ ├── substrate_types.rs // Useful Ethereum types -│ │ ├── sync.rs // Sync configuration and helpers -│ │ ├── sync_loop.rs // Header synchronization between source and target chains -│ │ ├── sync_types.rs // Useful sync types -│ │ └── utils.rs // General utilities -``` +├── bin // Node and Runtime for the various Substrate chains +│ └── ... +├── deployments // Useful tools for deploying test networks +│ └── ... +├── diagrams // Pretty pictures of the project architecture +│ └── ... +├── modules // Substrate Runtime Modules (a.k.a Pallets) +│ ├── ethereum // Ethereum PoA Header Sync Module +│ ├── substrate // Substrate Based Chain Header Sync Module +│ ├── message-lane // Cross Chain Message Passing +│ └── ... +├── primitives // Code shared between modules, runtimes, and relays +│ └── ... +├── relays // Application for sending headers and messages between chains +│ └── ... +└── scripts // Useful development and maintenence scripts + ``` ## Running the Bridge To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes -on each side of the bridge (home & foreign chain). An easy way to build all the required nodes is -through Docker. +on each side of the bridge (source and target chain). -### Local Development Build +There are 3 ways to run the bridge, described below: + - building & running from source, + - building or using Docker images for each individual component, + - running a Docker Compose setup (recommended). -#### Building +### Building -First you'll need to build the bridge node and relay. This can be done as follows: +First you'll need to build the bridge nodes and relay. This can be done as follows: ```bash # In `parity-bridges-common` folder cargo build -p rialto-bridge-node -cargo build -p ethereum-poa-relay -``` - -Next you'll need to clone the following [fork of OpenEthereum](https://github.com/paritytech/openethereum). -If you're doing development which only involves the Ethereum to Substrate side of the bridge you may -use the `master` branch. Otherwise you'll need to checkout the `substrate-builtins-stubs` branch. - -```bash -# Should be at the same level as `parity-bridges-common` folder -git clone https://github.com/paritytech/openethereum.git openethereum -git fetch -git checkout substrate-builtins-stubs +cargo build -p millau-bridge-node +cargo build -p substrate-relay ``` -If you've checked out the `substrate-builtins-stubs` branch make sure you've cloned the OpenEthereum -repo at the same level as `parity-bridges-common` since it references the repo. - -Next you'll need to build the Ethereum node: - -```bash -# In `openethereum` folder -cargo build -``` - -#### Running +### Running To run a simple dev network you'll can use the scripts located in -[the `scripts` folder](./scripts). Since the relay connects to both the Substrate and Ethereum -chains it must be run last. +[the `scripts` folder](./scripts). Since the relay connects to both Substrate chains it must be run +last. ```bash # In `parity-bridges-common` folder -./scripts/run-openethereum-node.sh -./scripts/run-rialto-bridge-node.sh -./scripts/run-eth2sub-relay.sh +./deployments/local-scripts/run-rialto-bridge-node.sh +./deployments/local-scripts/run-millau-bridge-node.sh +./deployments/local-scripts/run-millau-to-rialto-relay.sh +./deployments/local-scripts/run-rialto-to-millau-relay.sh ``` -At this point you should see the relayer submitting blocks from the Ethereum chain -to the Substrate chain. + +At this point you should see the relayer submitting blocks from the Millau Substrate chain to the +Rialto Substrate chain and vice-versa. ### Local Docker Build If you want to make a Docker container using your local source files you can run the following command at the top level of the repository: ```bash -docker build . -t bridge-relay-dev +docker build . -t local/rialto-bridge-node --build-arg PROJECT=rialto-bridge-node +docker build . -t local/millau-bridge-node --build-arg PROJECT=millau-bridge-node +docker build . -t local/substrate-relay --build-arg PROJECT=substrate-relay ``` -You can also build and run the Substrate based node as follows: +You can then run the network as follows: ```bash -docker build . -t bridge-node-dev --build-arg PROJECT=rialto-bridge-node -``` - -To run the Substrate node you can do the following: - -```bash -docker run -it bridge-node-dev --dev --tmp +docker run -it local/rialto-bridge-node --dev --tmp +docker run -it local/millau-bridge-node --dev --tmp +docker run -it local/substrate-relay ``` Notice that the `docker run` command will accept all the normal Substrate flags. For local development you should at minimum run with the `--dev` flag or else no blocks will be produced. -### Full Network Docker Setup -See [Deployments README](./deployments/README.md) to learn more about how to run -a more sophisticated test network using `docker-compose` setup. +### Full Network Docker Compose Setup + +For a more sophisticated deployment which includes bidirectional header sync, message passing, +monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md new file mode 100644 index 0000000000000..763371bbf193f --- /dev/null +++ b/docs/high-level-overview.md @@ -0,0 +1,177 @@ +# High-Level Bridge Documentation + +## Purpose + +Trustless connecting between two Substrate-based chains using GRANDPA finality. + +## Overview + +Even though we support two-way bridging, the documentation will generally talk about a one-sided +interaction. That's to say, we will only talk about syncing headers and messages from a _source_ +chain to a _target_ chain. This is because the two-sided interaction is really just the one-sided +interaction with the source and target chains switched. + +To understand the full interaction with the bridge, take a look at the +[testing scenarios](./testing-scenarios.md) document. It describes potential use cases and describes +how each of the layers outlined below is involved. + +The bridge is built from various components. Here is a quick overview of the important ones. + +### Header Sync + +A light client of the source chain built into the target chain's runtime. It is a single FRAME +pallet. It provides a "source of truth" about the source chain headers which have been finalized. +This is useful for higher level applications. + +### Headers Relayer + +A standalone application connected to both chains. It submits every source chain header it sees to +the target chain through RPC. + +### Message Delivery + +A FRAME pallet built on top of the header sync pallet. It allows users to submit messages to the +source chain, which are to be delivered to the target chain. The delivery protocol doesn't care +about the payload more than it has to. Handles replay protection and message ordering. + +### Message Dispatch + +A FRAME pallet responsible for interpreting the payload of delivered messages. + +### Message Relayer + +A standalone application handling delivery of the messages from source chain to the target chain. + +## Processes + +High level sequence charts of the process can be found in [a separate document](./high-level.html). + +### Substrate (GRANDPA) Header Sync + +The header sync pallet (`pallet-substrate-bridge`) is an on-chain light client for chains which use +GRANDPA finality. It is part of the target chain's runtime, and accepts headers from the source +chain. Its main goals are to accept valid headers, track GRANDPA finality set changes, and verify +GRANDPA finality proofs (a.k.a justifications). + +The pallet does not care about what block production mechanism is used for the source chain +(e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. Due to this it is possible for +the pallet to import (but not necessarily finalize) headers which are _not_ valid according to the +source chain's block production mechanism. + +The pallet has support for tracking forks and uses the longest chain rule to determine what the +canonical chain is. The pallet allows headers to be imported on a different fork from the canonical +one as long as the headers being imported don't conflict with already finalized headers (for +example, it will not allow importing a header at a lower height than the best finalized header). + +When tracking authority set changes, the pallet - unlike the full GRANDPA protocol - does not +support tracking multiple authority set changes across forks. Each fork can have at most one pending +authority set change. This is done to prevent DoS attacks if GRANDPA on the source chain were to +stall for a long time (the pallet would have to do a lot of expensive ancestry checks to catch up). + +Referer to the [pallet documentation](../modules/substrate/src/lib.rs) for more details. + +#### Header Relayer strategy + +There is currently no reward strategy for the relayers at all. They also are not required to be +staked or registered on-chain, unlike in other bridge designs. We consider the header sync to be +an essential part of the bridge and the incentivisation should be happening on the higher layers. + +At the moment, signed transactions are the only way to submit headers to the header sync pallet. +However, in the future we would like to use unsigned transactions for headers delivery. This will +allow transaction de-duplication to be done at the transaction pool level and also remove the cost +for message relayers to run header relayers. + +### Message Passing + +Once header sync is maintained, the target side of the bridge can receive and verify proofs about +events happening on the source chain, or its internal state. On top of this, we built a message +passing protocol which consists of two parts described in following sections: message delivery and +message dispatch. + +#### Message Lanes Delivery + +The [Message delivery pallet](../modules/message-lane/src/lib.rs) is responsible for queueing up +messages and delivering them in order on the target chain. It also dispatches messages, but we will +cover that in the next section. + +The pallet supports multiple lanes (channels) where messages can be added. Every lane can be +considered completely independent from others, which allows them to make progress in parallel. +Different lanes can be configured to validated messages differently (e.g higher rewards, specific +types of payload, etc.) and may be associated with a particular "user application" built on top of +the bridge. Note that messages in the same lane MUST be delivered _in the same order_ they were +queued up. + +The message delivery protocol does not care about the payload it transports and can be coupled +with an arbitrary message dispatch mechanism that will interpret and execute the payload if delivery +conditions are met. Each delivery on the target chain is confirmed back to the source chain by the +relayer. This is so that she can collect the reward for delivering these messages. + +Users of the pallet add their messages to an "outbound lane" on the source chain. When a block is +finalized message relayers are responsible for reading the current queue of messages and submitting +some (or all) of them to the "inbound lane" of the target chain. Each message has a `nonce` +associated with it, which serves as the ordering of messages. The inbound lane stores the last +delivered nonce to prevent replaying messages. To succesfuly deliver the message to the inbound lane +on target chain the relayer has to present present a storage proof which shows that the message was +part of the outbound lane on the source chain. + +During delivery of messages they are immediately dispatched on the target chain and the relayer is +required to declare the correct `weight` to cater for all messages dispatch and pay all required +fees of the target chain. To make sure the relayer is incentivised to do so, on the source chain: +- the user provides a declared dispatch weight of the payload +- the pallet calculates the expected fee on the target chain based on the declared weight +- the pallet converts the target fee into source tokens (based on a price oracle) and reserves + enough tokens to cover for the delivery, dispatch, confirmation and additional relayers reward. + +If the declared weight turns out to be too low on the target chain the message is delivered but +it immediately fails to dispatch. The fee and reward is collected by the relayer upon confirmation +of delivery. + +Due to the fact that message lanes require delivery confirmation transactions, they also strictly +require bi-directional header sync (i.e. you can't use message delivery with one-way header sync). + +#### Dispatching Messages + +The [Message dispatch pallet](../modules/call-dispatch/src/lib.rs) is used to perform the actions +specified by messages which have come over the bridge. For Substrate-based chains this means +interpreting the source chain's message as a `Call` on the target chain. + +An example `Call` of the target chain would look something like this: + +```rust +target_runtime::Call::Balances(target_runtime::pallet_balances::Call::transfer(recipient, amount)) +``` + +When sending a `Call` it must first be SCALE encoded and then sent to the source chain. The `Call` +is then delivered by the message lane delivery mechanism from the source chain to the target chain. +When a message is received the inbound message lane on the target chain will try and decode the +message payload into a `Call` enum. If it's successful it will be dispatched after we check that the +weight of the call does not exceed the weight declared by the sender. The relayer pays fees for +executing the transaction on the target chain, but her costs should be covered by the sender on the +source chain. + +When dispatching messages there are three Origins which can be used by the target chain: +1. Root Origin +2. Source Origin +3. Target Origin + +Senders of a message can indicate which one of the three origins they would like to dispatch their +message with. However, there are restrictions on who/what is allowed to dispatch messages with a +particular origin. + +The Root origin represents the source chain's Root account on the target chain. This origin can can +only be dispatched on the target chain if the "send message" request was made by the Root origin of +the source chain - otherwise the message will fail to be dispatched. + +The Source origin represents an account without a private key on the target chain. This account will +be generated/derived using the account ID of the sender on the source chain. We don't necessarily +require the source account id to be associated with a private key on the source chain either. This +is useful for representing things such as source chain proxies or pallets. + +The Target origin represents an account with a private key on the target chain. The sender on the +source chain needs to prove ownership of this account by using their target chain private key to +sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and +verified by the target chain before dispatch. + +See [`CallOrigin` documentation](../modules/call-dispatch/src/lib.rs) for more details. + +#### Message Relayers Strategy diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index cd146cd1ec8d8..f90d2c0231ca6 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -134,7 +134,7 @@ fn fork_does_not_allow_competing_finality_proofs() { // // Not allowed to import 3 until we get F2 // -// Note: Grandpa would technically allow 3 to be imported as long as it didn't try and enact an +// Note: GRANDPA would technically allow 3 to be imported as long as it didn't try and enact an // authority set change. However, since we expect finality proofs to be imported quickly we've // decided to simplify our import process and disallow header imports until we get a finality proof. #[test] @@ -161,9 +161,9 @@ fn fork_waits_for_finality_proof_before_importing_header_past_one_which_enacts_a // // [1] <- [2: S|1] <- [3: S|0] // -// Grandpa can have multiple authority set changes pending on the same fork. However, we've decided +// GRANDPA can have multiple authority set changes pending on the same fork. However, we've decided // to introduce a limit of _one_ pending authority set change per fork in order to simplify pallet -// logic and to prevent DoS attacks if Grandpa finality were to temporarily stall for a long time +// logic and to prevent DoS attacks if GRANDPA finality were to temporarily stall for a long time // (we'd have to perform a lot of expensive ancestry checks to catch back up). #[test] fn fork_does_not_allow_multiple_scheduled_changes_on_the_same_fork() { diff --git a/modules/substrate/src/justification.rs b/modules/substrate/src/justification.rs index 911ebf3f2c8c4..c285dd34b808d 100644 --- a/modules/substrate/src/justification.rs +++ b/modules/substrate/src/justification.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Module for checking Grandpa Finality Proofs. +//! Module for checking GRANDPA Finality Proofs. //! //! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin //! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. @@ -123,7 +123,7 @@ where Ok(()) } -/// A Grandpa Justification is a proof that a given header was finalized +/// A GRANDPA Justification is a proof that a given header was finalized /// at a certain height and with a certain set of authorities. /// /// This particular proof is used to prove that headers on a bridged chain diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index eb77b5af750fb..58bf3ea05dd9d 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -21,7 +21,7 @@ //! It has a simple interface for achieving this. First it can import headers to the runtime //! storage. During this it will check the validity of the headers and ensure they don't conflict //! with any existing headers (e.g they're on a different finalized chain). Secondly it can finalize -//! an already imported header (and its ancestors) given a valid Grandpa justification. +//! an already imported header (and its ancestors) given a valid GRANDPA justification. //! //! With these two functions the pallet is able to form a "source of truth" for what headers have //! been finalized on a given Substrate chain. This can be a useful source of info for other @@ -94,17 +94,17 @@ decl_storage! { /// Hash of the best finalized header. BestFinalized: BridgedBlockHash; /// The set of header IDs (number, hash) which enact an authority set change and therefore - /// require a Grandpa justification. + /// require a GRANDPA justification. RequiresJustification: map hasher(identity) BridgedBlockHash => BridgedBlockNumber; /// Headers which have been imported into the pallet. ImportedHeaders: map hasher(identity) BridgedBlockHash => Option>>; - /// The current Grandpa Authority set. + /// The current GRANDPA Authority set. CurrentAuthoritySet: AuthoritySet; /// The next scheduled authority set change for a given fork. /// /// The fork is indicated by the header which _signals_ the change (key in the mapping). /// Note that this is different than a header which _enacts_ a change. - // Grandpa doesn't require there to always be a pending change. In fact, most of the time + // GRANDPA doesn't require there to always be a pending change. In fact, most of the time // there will be no pending change available. NextScheduledChange: map hasher(identity) BridgedBlockHash => Option>>; /// Optional pallet owner. @@ -448,10 +448,10 @@ pub trait BridgeStorage { /// Returns None if it is not known to the pallet. fn header_by_hash(&self, hash: ::Hash) -> Option>; - /// Get the current Grandpa authority set. + /// Get the current GRANDPA authority set. fn current_authority_set(&self) -> AuthoritySet; - /// Update the current Grandpa authority set. + /// Update the current GRANDPA authority set. /// /// Should only be updated when a scheduled change has been triggered. fn update_current_authority_set(&self, new_set: AuthoritySet); @@ -462,13 +462,13 @@ pub trait BridgeStorage { #[allow(clippy::result_unit_err)] fn enact_authority_set(&mut self, signal_hash: ::Hash) -> Result<(), ()>; - /// Get the next scheduled Grandpa authority set change. + /// Get the next scheduled GRANDPA authority set change. fn scheduled_set_change( &self, signal_hash: ::Hash, ) -> Option::Number>>; - /// Schedule a Grandpa authority set change in the future. + /// Schedule a GRANDPA authority set change in the future. /// /// Takes the hash of the header which scheduled this particular change. fn schedule_next_set_change( diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs index 86677f67c54f8..93f30bdec7c9a 100644 --- a/modules/substrate/src/storage.rs +++ b/modules/substrate/src/storage.rs @@ -42,24 +42,24 @@ pub struct InitializationData { pub is_halted: bool, } -/// A Grandpa Authority List and ID. +/// A GRANDPA Authority List and ID. #[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct AuthoritySet { - /// List of Grandpa authorities for the current round. + /// List of GRANDPA authorities for the current round. pub authorities: AuthorityList, - /// Monotonic identifier of the current Grandpa authority set. + /// Monotonic identifier of the current GRANDPA authority set. pub set_id: SetId, } impl AuthoritySet { - /// Create a new Grandpa Authority Set. + /// Create a new GRANDPA Authority Set. pub fn new(authorities: AuthorityList, set_id: SetId) -> Self { Self { authorities, set_id } } } -/// Keeps track of when the next Grandpa authority set change will occur. +/// Keeps track of when the next GRANDPA authority set change will occur. #[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ScheduledChange { diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 1b58df03f85e0..913129f19c6ef 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -19,7 +19,7 @@ //! //! When importing headers it performs checks to ensure that no invariants are broken (like //! importing the same header twice). When it imports finality proofs it will ensure that the proof -//! has been signed off by the correct Grandpa authorities, and also enact any authority set changes +//! has been signed off by the correct GRANDPA authorities, and also enact any authority set changes //! if required. use crate::justification::verify_justification; @@ -34,8 +34,8 @@ use sp_std::{prelude::Vec, vec}; /// The finality proof used by the pallet. /// -/// For a Substrate based chain using Grandpa this will -/// be an encoded Grandpa Justification. +/// For a Substrate based chain using GRANDPA this will +/// be an encoded GRANDPA Justification. #[derive(RuntimeDebug)] pub struct FinalityProof(Vec); @@ -139,7 +139,7 @@ where // we need to make a note of it. // // Note: This assumes that we can only have one authority set change pending per fork at a - // time. While this is not strictly true of Grandpa (it can have multiple pending changes, + // time. While this is not strictly true of GRANDPA (it can have multiple pending changes, // even across forks), this assumption simplifies our tracking of authority set changes. let mut signal_hash = parent_header.signal_hash; let scheduled_change = find_scheduled_change(&header); @@ -213,7 +213,7 @@ where Ok(()) } - /// Verify that a previously imported header can be finalized with the given Grandpa finality + /// Verify that a previously imported header can be finalized with the given GRANDPA finality /// proof. If the header enacts an authority set change the change will be applied once the /// header has been finalized. pub fn import_finality_proof(&mut self, hash: H::Hash, proof: FinalityProof) -> Result<(), FinalizationError> { @@ -680,7 +680,7 @@ mod tests { let mut storage = PalletStorage::::new(); let _imported_headers = write_default_headers(&mut storage, vec![1]); - // Nothing special about this header, yet Grandpa may have created a justification + // Nothing special about this header, yet GRANDPA may have created a justification // for it since it does that periodically let header = test_header(2); diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 1edd4675da1b8..348b5bf1d277d 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -29,7 +29,7 @@ pub trait Chain: Send + Sync + 'static { // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html#associatedtype.Number // - // Note that the `AsPrimitive` trait is required by the Grandpa justification + // Note that the `AsPrimitive` trait is required by the GRANDPA justification // verifier, and is not usually part of a Substrate Header's Number type. type BlockNumber: Parameter + Member From 9b18750968018815152754418e2a390c943c38dc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 15 Dec 2020 13:46:14 +0300 Subject: [PATCH 0262/1210] Limit size of message delivery transaction (#575) * limit messages size in delivery transaction * docs --- bin/millau/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/lib.rs | 4 +- primitives/kusama/src/lib.rs | 4 +- primitives/millau/src/lib.rs | 4 +- primitives/polkadot/src/lib.rs | 4 +- primitives/rialto/src/lib.rs | 4 +- .../messages-relay/src/message_lane_loop.rs | 18 ++- .../src/message_race_delivery.rs | 104 +++++++++++++++++- .../src/message_race_strategy.rs | 8 ++ relays/substrate/src/messages_source.rs | 42 +++++-- .../src/millau_messages_to_rialto.rs | 2 + .../src/rialto_messages_to_millau.rs | 2 + 12 files changed, 170 insertions(+), 30 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 53da30ad53514..1502e3946736b 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -555,13 +555,13 @@ impl_runtime_apis! { lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce, - ) -> Vec<(bp_message_lane::MessageNonce, Weight)> { + ) -> Vec<(bp_message_lane::MessageNonce, Weight, u32)> { (begin..=end).filter_map(|nonce| { let encoded_payload = BridgeRialtoMessageLane::outbound_message_payload(lane, nonce)?; let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode( &mut &encoded_payload[..] ).ok()?; - Some((nonce, decoded_payload.weight)) + Some((nonce, decoded_payload.weight, encoded_payload.len() as _)) }) .collect() } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index ff078a3b2b9a0..57b041f649369 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -719,13 +719,13 @@ impl_runtime_apis! { lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, end: bp_message_lane::MessageNonce, - ) -> Vec<(bp_message_lane::MessageNonce, Weight)> { + ) -> Vec<(bp_message_lane::MessageNonce, Weight, u32)> { (begin..=end).filter_map(|nonce| { let encoded_payload = BridgeMillauMessageLane::outbound_message_payload(lane, nonce)?; let decoded_payload = millau_messages::ToMillauMessagePayload::decode( &mut &encoded_payload[..] ).ok()?; - Some((nonce, decoded_payload.weight)) + Some((nonce, decoded_payload.weight, encoded_payload.len() as _)) }) .collect() } diff --git a/primitives/kusama/src/lib.rs b/primitives/kusama/src/lib.rs index 732db82bcd2fa..e6d69a6539bee 100644 --- a/primitives/kusama/src/lib.rs +++ b/primitives/kusama/src/lib.rs @@ -122,7 +122,7 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are sending messages to Kusama chain, not the /// Kusama runtime itself. pub trait ToKusamaOutboundLaneApi { - /// Returns dispatch weight of all messages in given inclusive range. + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. @@ -130,7 +130,7 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight)>; + ) -> Vec<(MessageNonce, Weight, u32)>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 054b2462169ff..148a19be0f016 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -186,7 +186,7 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are sending messages to Millau chain, not the /// Millau runtime itself. pub trait ToMillauOutboundLaneApi { - /// Returns dispatch weight of all messages in given inclusive range. + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. @@ -194,7 +194,7 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight)>; + ) -> Vec<(MessageNonce, Weight, u32)>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/polkadot/src/lib.rs b/primitives/polkadot/src/lib.rs index d716601474679..83cb7db41c2b8 100644 --- a/primitives/polkadot/src/lib.rs +++ b/primitives/polkadot/src/lib.rs @@ -122,7 +122,7 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are sending messages to Polkadot chain, not the /// Polkadot runtime itself. pub trait ToPolkadotOutboundLaneApi { - /// Returns dispatch weight of all messages in given inclusive range. + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. @@ -130,7 +130,7 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight)>; + ) -> Vec<(MessageNonce, Weight, u32)>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 458a3abc0a758..f91f1689b9470 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -162,7 +162,7 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are sending messages to Rialto chain, not the /// Rialto runtime itself. pub trait ToRialtoOutboundLaneApi { - /// Returns dispatch weight of all messages in given inclusive range. + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. @@ -170,7 +170,7 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight)>; + ) -> Vec<(MessageNonce, Weight, u32)>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index 542415ca0a8fb..c34323ace58de 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -71,10 +71,21 @@ pub struct MessageDeliveryParams { pub max_messages_in_single_batch: MessageNonce, /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. pub max_messages_weight_in_single_batch: Weight, + /// Maximal cumulative size of relayed messages in single delivery transaction. + pub max_messages_size_in_single_batch: usize, +} + +/// Message weights. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct MessageWeights { + /// Message dispatch weight. + pub weight: Weight, + /// Message size (number of bytes in encoded payload). + pub size: usize, } /// Messages weights map. -pub type MessageWeightsMap = BTreeMap; +pub type MessageWeightsMap = BTreeMap; /// Message delivery race proof parameters. #[derive(Debug, PartialEq)] @@ -586,7 +597,9 @@ pub(crate) mod tests { _id: SourceHeaderIdOf, nonces: RangeInclusive, ) -> Result { - Ok(nonces.map(|nonce| (nonce, 1)).collect()) + Ok(nonces + .map(|nonce| (nonce, MessageWeights { weight: 1, size: 1 })) + .collect()) } async fn prove_messages( @@ -754,6 +767,7 @@ pub(crate) mod tests { max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, + max_messages_size_in_single_batch: 4, }, }, source_client, diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 6ad2a14533561..f6933d9bd12e6 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -60,6 +60,7 @@ pub async fn run( max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, + max_messages_size_in_single_batch: params.max_messages_size_in_single_batch, latest_confirmed_nonce_at_source: None, target_nonces: None, strategy: BasicStrategy::new(), @@ -218,6 +219,8 @@ struct MessageDeliveryStrategy { max_messages_in_single_batch: MessageNonce, /// Maximal cumulative messages weight in the single delivery transaction. max_messages_weight_in_single_batch: Weight, + /// Maximal messages size in the single delivery transaction. + max_messages_size_in_single_batch: usize, /// Latest confirmed nonce at the source client. latest_confirmed_nonce_at_source: Option, /// Target nonces from the source client. @@ -360,7 +363,9 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M .unwrap_or_default(); let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; + let max_messages_size_in_single_batch = self.max_messages_size_in_single_batch; let mut selected_weight: Weight = 0; + let mut selected_size: usize = 0; let mut selected_count: MessageNonce = 0; let selected_nonces = self @@ -369,11 +374,44 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M let to_requeue = range .into_iter() .skip_while(|(_, weight)| { + // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` + // and `max_messages_size_in_single_batch`, we may still try to submit transaction + // with single message if message overflows these limits. The worst case would be if + // transaction will be rejected by the target runtime, but at least we have tried. + // limit messages in the batch by weight - let new_selected_weight = match selected_weight.checked_add(*weight) { + let new_selected_weight = match selected_weight.checked_add(weight.weight) { Some(new_selected_weight) if new_selected_weight <= max_messages_weight_in_single_batch => { new_selected_weight } + new_selected_weight if selected_count == 0 => { + log::warn!( + target: "bridge", + "Going to submit message delivery transaction with declared dispatch \ + weight {:?} that overflows maximal configured weight {}", + new_selected_weight, + max_messages_weight_in_single_batch, + ); + new_selected_weight.unwrap_or(Weight::MAX) + } + _ => return false, + }; + + // limit messages in the batch by size + let new_selected_size = match selected_size.checked_add(weight.size) { + Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => { + new_selected_size + } + new_selected_size if selected_count == 0 => { + log::warn!( + target: "bridge", + "Going to submit message delivery transaction with message \ + size {:?} that overflows maximal configured size {}", + new_selected_size, + max_messages_size_in_single_batch, + ); + new_selected_size.unwrap_or(usize::MAX) + } _ => return false, }; @@ -384,6 +422,7 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M } selected_weight = new_selected_weight; + selected_size = new_selected_size; selected_count = new_selected_count; true }) @@ -427,8 +466,9 @@ impl NoncesRange for MessageWeightsMap { #[cfg(test)] mod tests { use super::*; - use crate::message_lane_loop::tests::{ - header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderId, TestTargetHeaderId, + use crate::message_lane_loop::{ + tests::{header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderId, TestTargetHeaderId}, + MessageWeights, }; type TestRaceState = RaceState; @@ -448,6 +488,7 @@ mod tests { max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, + max_messages_size_in_single_batch: 4, latest_confirmed_nonce_at_source: Some(19), target_nonces: Some(TargetClientNonces { latest_nonce: 19, @@ -465,7 +506,14 @@ mod tests { race_strategy.strategy.source_nonces_updated( header_id(1), SourceClientNonces { - new_nonces: vec![(20, 1), (21, 1), (22, 1), (23, 1)].into_iter().collect(), + new_nonces: vec![ + (20, MessageWeights { weight: 1, size: 1 }), + (21, MessageWeights { weight: 1, size: 1 }), + (22, MessageWeights { weight: 1, size: 1 }), + (23, MessageWeights { weight: 1, size: 1 }), + ] + .into_iter() + .collect(), confirmed_nonce: Some(19), }, ); @@ -490,7 +538,17 @@ mod tests { #[test] fn weights_map_works_as_nonces_range() { fn build_map(range: RangeInclusive) -> MessageWeightsMap { - range.map(|idx| (idx, idx)).collect() + range + .map(|idx| { + ( + idx, + MessageWeights { + weight: idx, + size: idx as _, + }, + ) + }) + .collect() } let map = build_map(20..=30); @@ -604,6 +662,42 @@ mod tests { ); } + #[test] + fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight() { + let (state, mut strategy) = prepare_strategy(); + + // first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4) + strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().weight = 10; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=20), proof_parameters(false, 10))) + ); + } + + #[test] + fn message_delivery_strategy_limits_batch_by_messages_size() { + let (state, mut strategy) = prepare_strategy(); + + // not all queued messages may fit in the batch, because batch has max weight + strategy.max_messages_size_in_single_batch = 3; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=22), proof_parameters(false, 3))) + ); + } + + #[test] + fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size() { + let (state, mut strategy) = prepare_strategy(); + + // first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4) + strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().size = 10; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=20), proof_parameters(false, 1))) + ); + } + #[test] fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() { let (state, mut strategy) = prepare_strategy(); diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index 32ae46d28a4a6..ce41c2e19a24c 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -57,6 +57,14 @@ where } } + /// Mutable reference to source queue to use in tests. + #[cfg(test)] + pub(crate) fn source_queue_mut( + &mut self, + ) -> &mut VecDeque<(HeaderId, SourceNoncesRange)> { + &mut self.source_queue + } + /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated /// data) from source to target node. /// diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index 1a6b9e6c1119a..9376a14ce6f67 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -27,7 +27,9 @@ use codec::{Decode, Encode}; use frame_support::weights::Weight; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{ClientState, MessageProofParameters, MessageWeightsMap, SourceClient, SourceClientState}, + message_lane_loop::{ + ClientState, MessageProofParameters, MessageWeights, MessageWeightsMap, SourceClient, SourceClientState, + }, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; use relay_utils::{BlockNumberBase, HeaderId}; @@ -235,7 +237,7 @@ where } fn make_message_weights_map( - weights: Vec<(MessageNonce, Weight)>, + weights: Vec<(MessageNonce, Weight, u32)>, nonces: RangeInclusive, ) -> Result { let make_missing_nonce_error = |expected_nonce| { @@ -255,7 +257,7 @@ fn make_message_weights_map( // check if last nonce is missing - loop below is not checking this let last_nonce_is_missing = weights .last() - .map(|(last_nonce, _)| last_nonce != nonces.end()) + .map(|(last_nonce, _, _)| last_nonce != nonces.end()) .unwrap_or(true); if last_nonce_is_missing { return make_missing_nonce_error(*nonces.end()); @@ -264,7 +266,7 @@ fn make_message_weights_map( let mut expected_nonce = *nonces.start(); let mut is_at_head = true; - for (nonce, weight) in weights { + for (nonce, weight, size) in weights { match (nonce == expected_nonce, is_at_head) { (true, _) => (), (false, true) => { @@ -286,7 +288,13 @@ fn make_message_weights_map( } } - weights_map.insert(nonce, weight); + weights_map.insert( + nonce, + MessageWeights { + weight, + size: size as _, + }, + ); expected_nonce = nonce + 1; is_at_head = false; } @@ -301,23 +309,35 @@ mod tests { #[test] fn make_message_weights_map_succeeds_if_no_messages_are_missing() { assert_eq!( - make_message_weights_map::(vec![(1, 0), (2, 0), (3, 0)], 1..=3).unwrap(), - vec![(1, 0), (2, 0), (3, 0)].into_iter().collect(), + make_message_weights_map::(vec![(1, 0, 0), (2, 0, 0), (3, 0, 0)], 1..=3,) + .unwrap(), + vec![ + (1, MessageWeights { weight: 0, size: 0 }), + (2, MessageWeights { weight: 0, size: 0 }), + (3, MessageWeights { weight: 0, size: 0 }), + ] + .into_iter() + .collect(), ); } #[test] fn make_message_weights_map_succeeds_if_head_messages_are_missing() { assert_eq!( - make_message_weights_map::(vec![(2, 0), (3, 0)], 1..=3).unwrap(), - vec![(2, 0), (3, 0)].into_iter().collect(), + make_message_weights_map::(vec![(2, 0, 0), (3, 0, 0)], 1..=3,).unwrap(), + vec![ + (2, MessageWeights { weight: 0, size: 0 }), + (3, MessageWeights { weight: 0, size: 0 }), + ] + .into_iter() + .collect(), ); } #[test] fn make_message_weights_map_fails_if_mid_messages_are_missing() { assert!(matches!( - make_message_weights_map::(vec![(1, 0), (3, 0)], 1..=3), + make_message_weights_map::(vec![(1, 0, 0), (3, 0, 0)], 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -325,7 +345,7 @@ mod tests { #[test] fn make_message_weights_map_fails_if_tail_messages_are_missing() { assert!(matches!( - make_message_weights_map::(vec![(1, 0), (2, 0)], 1..=3), + make_message_weights_map::(vec![(1, 0, 0), (2, 0, 0)], 1..=3,), Err(SubstrateError::Custom(_)) )); } diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 5b60a90c36ec8..736e278771f0a 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -133,6 +133,8 @@ pub fn run( // TODO: subtract base weight of delivery from this when it'll be known // https://github.com/paritytech/parity-bridges-common/issues/78 max_messages_weight_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT, + // 2/3 is reserved for proofs and tx overhead + max_messages_size_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_SIZE as usize / 3, }, }, MillauSourceClient::new(millau_client, lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 8697c79595544..2f869a122a73c 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -133,6 +133,8 @@ pub fn run( // TODO: subtract base weight of delivery from this when it'll be known // https://github.com/paritytech/parity-bridges-common/issues/78 max_messages_weight_in_single_batch: bp_millau::MAXIMUM_EXTRINSIC_WEIGHT, + // 2/3 is reserved for proofs and tx overhead + max_messages_size_in_single_batch: bp_millau::MAXIMUM_EXTRINSIC_SIZE as usize / 3, }, }, RialtoSourceClient::new(rialto_client, lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), From e8fe30f83ad9b2a59620600fef979e614b2ed318 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Dec 2020 04:52:53 -0500 Subject: [PATCH 0263/1210] Update Substrate Dependency (#566) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update `sp-io` dependency * Rename Trait to Config * RustFmt * Bump `sp-io` again * Use new frame_system weight types in Rialto and Millau runtimes * Update test Runtimes to use new weight types * Bump `sp-io` again * Update to not-the latest first. * Update benchmarks. * Another Trai. * Move new weight types into runtime primitive crates This allows us to check limits for extrinsics from other parts of the codebase without pulling in the entire chain runtime. * Remove leftover comments * Move new functions to a better location * Small formatting fixes * Add actual documentation to new weight config types * Decrease maximum block weight of Millau chain * Decreease maximum block length of Millau chain Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/service.rs | 2 - bin/millau/runtime/src/lib.rs | 61 ++++++-------- bin/millau/runtime/src/rialto_messages.rs | 8 +- bin/rialto/node/src/service.rs | 2 - bin/rialto/runtime/src/exchange.rs | 2 +- bin/rialto/runtime/src/lib.rs | 83 ++++++++----------- bin/rialto/runtime/src/millau_messages.rs | 8 +- bin/runtime-common/src/messages.rs | 18 ++-- modules/call-dispatch/src/lib.rs | 40 ++++----- modules/currency-exchange/src/benchmarking.rs | 10 +-- modules/currency-exchange/src/lib.rs | 38 ++++----- modules/ethereum/src/benchmarking.rs | 2 +- modules/ethereum/src/lib.rs | 18 ++-- modules/ethereum/src/mock.rs | 16 ++-- modules/ethereum/src/test_utils.rs | 6 +- modules/message-lane/src/benchmarking.rs | 8 +- modules/message-lane/src/inbound_lane.rs | 4 +- modules/message-lane/src/lib.rs | 48 +++++------ modules/message-lane/src/mock.rs | 16 ++-- modules/shift-session-manager/src/lib.rs | 28 +++---- modules/substrate/src/lib.rs | 26 +++--- modules/substrate/src/mock.rs | 24 +++--- modules/substrate/src/storage_proof.rs | 2 +- primitives/millau/Cargo.toml | 2 + primitives/millau/src/lib.rs | 69 ++++++++++++--- primitives/millau/src/millau_hash.rs | 2 +- primitives/rialto/Cargo.toml | 2 + primitives/rialto/src/lib.rs | 66 ++++++++++++--- relays/substrate-client/src/chain.rs | 2 +- .../src/millau_messages_to_rialto.rs | 4 +- .../src/rialto_messages_to_millau.rs | 4 +- 31 files changed, 328 insertions(+), 293 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 10e613f5964aa..a9d866af73a37 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -318,8 +318,6 @@ pub fn new_full(config: Configuration) -> Result { task_manager .spawn_essential_handle() .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); - } else { - sc_finality_grandpa::setup_disabled_grandpa(network)?; } network_starter.start_network(); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1502e3946736b..fcf443e9370f4 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -31,6 +31,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto_messages; use codec::Decode; +use frame_system::limits; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -50,7 +51,7 @@ use sp_version::RuntimeVersion; pub use frame_support::{ construct_runtime, parameter_types, traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, Randomness}, - weights::{IdentityFee, RuntimeDbWeight, Weight}, + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -149,19 +150,17 @@ pub fn native_version() -> NativeVersion { parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = bp_millau::MAXIMUM_BLOCK_WEIGHT; - pub const ExtrinsicBaseWeight: Weight = 10_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_millau::AVAILABLE_BLOCK_RATIO); - pub MaximumExtrinsicWeight: Weight = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT; - pub const MaximumBlockLength: u32 = bp_millau::MAXIMUM_BLOCK_SIZE; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; + + pub RuntimeBlockLength: limits::BlockLength = bp_millau::runtime_block_length(); + pub RuntimeBlockWeights: limits::BlockWeights = bp_millau::runtime_block_weights(); } -impl frame_system::Trait for Runtime { +impl frame_system::Config for Runtime { /// The basic call filter to use in dispatchable. type BaseCallFilter = (); /// The identifier used to distinguish between accounts. @@ -186,24 +185,6 @@ impl frame_system::Trait for Runtime { type Origin = Origin; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; - /// Maximum weight of each block. - type MaximumBlockWeight = MaximumBlockWeight; - /// The weight of database operations that the runtime can invoke. - type DbWeight = DbWeight; - /// The weight of the overhead invoked on the block import process, independent of the - /// extrinsics included in that block. - type BlockExecutionWeight = (); - /// The base weight of any extrinsic processed by the runtime, independent of the - /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; - /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, - /// idependent of the logic of that extrinsics. (Roughly max block weight - average on - /// initialize cost). - type MaximumExtrinsicWeight = MaximumExtrinsicWeight; - /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. - type MaximumBlockLength = MaximumBlockLength; - /// Portion of the block weight that is available to all normal transactions. - type AvailableBlockRatio = AvailableBlockRatio; /// Version of the runtime. type Version = Version; /// Provides information about the pallet setup in the runtime. @@ -217,12 +198,18 @@ impl frame_system::Trait for Runtime { // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); + /// Block and extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// The weight of database operations that the runtime can invoke. + type DbWeight = DbWeight; } -impl pallet_aura::Trait for Runtime { +impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; } -impl pallet_bridge_call_dispatch::Trait for Runtime { +impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; @@ -232,7 +219,7 @@ impl pallet_bridge_call_dispatch::Trait for Runtime { type AccountIdConverter = bp_millau::AccountIdConverter; } -impl pallet_grandpa::Trait for Runtime { +impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; type KeyOwnerProofSystem = (); @@ -248,7 +235,7 @@ parameter_types! { pub const MinimumPeriod: u64 = SLOT_DURATION / 2; } -impl pallet_timestamp::Trait for Runtime { +impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; @@ -264,7 +251,7 @@ parameter_types! { pub const MaxLocks: u32 = 50; } -impl pallet_balances::Trait for Runtime { +impl pallet_balances::Config for Runtime { /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type. @@ -282,14 +269,14 @@ parameter_types! { pub const TransactionByteFee: Balance = 1; } -impl pallet_transaction_payment::Trait for Runtime { +impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } -impl pallet_sudo::Trait for Runtime { +impl pallet_sudo::Config for Runtime { type Event = Event; type Call = Call; } @@ -300,9 +287,9 @@ parameter_types! { pub const Offset: BlockNumber = 0; } -impl pallet_session::Trait for Runtime { +impl pallet_session::Config for Runtime { type Event = Event; - type ValidatorId = ::AccountId; + type ValidatorId = ::AccountId; type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; @@ -314,11 +301,11 @@ impl pallet_session::Trait for Runtime { type WeightInfo = (); } -impl pallet_substrate_bridge::Trait for Runtime { +impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_rialto::Rialto; } -impl pallet_shift_session_manager::Trait for Runtime {} +impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; @@ -330,7 +317,7 @@ parameter_types! { bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION; } -impl pallet_message_lane::Trait for Runtime { +impl pallet_message_lane::Config for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 061137e2151b9..a2fba5faf270a 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -89,12 +89,12 @@ impl MessageBridge for WithRialtoMessageBridge { type BridgedChain = Rialto; fn maximal_extrinsic_size_on_target_chain() -> u32 { - bp_rialto::MAXIMUM_EXTRINSIC_SIZE + bp_rialto::max_extrinsic_size() } fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT / 2; + let upper_limit = bp_rialto::max_extrinsic_weight() / 2; // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() @@ -116,12 +116,12 @@ impl MessageBridge for WithRialtoMessageBridge { } fn this_weight_to_this_balance(weight: Weight) -> bp_millau::Balance { - ::WeightToFee::calc(&weight) + ::WeightToFee::calc(&weight) } fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_rialto::Balance { // we're using the same weights in both chains now - ::WeightToFee::calc(&weight) as _ + ::WeightToFee::calc(&weight) as _ } fn this_balance_to_bridged_balance(this_balance: bp_millau::Balance) -> bp_rialto::Balance { diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index bd4c587618eb0..57415b73447f6 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -317,8 +317,6 @@ pub fn new_full(config: Configuration) -> Result { task_manager .spawn_essential_handle() .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); - } else { - sc_finality_grandpa::setup_disabled_grandpa(network)?; } network_starter.start_network(); diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index 1e68ce83f71fe..12fbadf012dd1 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -128,7 +128,7 @@ impl MaybeLockFundsTransaction for EthTransaction { /// Prepares everything required to bench claim of funds locked by given transaction. #[cfg(feature = "runtime-benchmarks")] -pub(crate) fn prepare_environment_for_claim, I: frame_support::traits::Instance>( +pub(crate) fn prepare_environment_for_claim, I: frame_support::traits::Instance>( transactions: &[(RawTransaction, RawTransactionReceipt)], ) -> bp_eth_poa::H256 { use bp_eth_poa::compute_merkle_root; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 57b041f649369..04534d48021bf 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -37,6 +37,7 @@ pub mod millau_messages; pub mod rialto_poa; use codec::Decode; +use frame_system::limits; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -56,7 +57,7 @@ use sp_version::RuntimeVersion; pub use frame_support::{ construct_runtime, parameter_types, traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, Randomness}, - weights::{IdentityFee, RuntimeDbWeight, Weight}, + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -157,19 +158,17 @@ pub fn native_version() -> NativeVersion { parameter_types! { pub const BlockHashCount: BlockNumber = 250; - pub const MaximumBlockWeight: Weight = bp_rialto::MAXIMUM_BLOCK_WEIGHT; - pub const ExtrinsicBaseWeight: Weight = 10_000_000; - pub const AvailableBlockRatio: Perbill = Perbill::from_percent(bp_rialto::AVAILABLE_BLOCK_RATIO); - pub MaximumExtrinsicWeight: Weight = bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT; - pub const MaximumBlockLength: u32 = bp_rialto::MAXIMUM_BLOCK_SIZE; pub const Version: RuntimeVersion = VERSION; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; + + pub RuntimeBlockLength: limits::BlockLength = bp_rialto::runtime_block_length(); + pub RuntimeBlockWeights: limits::BlockWeights = bp_rialto::runtime_block_weights(); } -impl frame_system::Trait for Runtime { +impl frame_system::Config for Runtime { /// The basic call filter to use in dispatchable. type BaseCallFilter = (); /// The identifier used to distinguish between accounts. @@ -194,24 +193,6 @@ impl frame_system::Trait for Runtime { type Origin = Origin; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; - /// Maximum weight of each block. - type MaximumBlockWeight = MaximumBlockWeight; - /// The weight of database operations that the runtime can invoke. - type DbWeight = DbWeight; - /// The weight of the overhead invoked on the block import process, independent of the - /// extrinsics included in that block. - type BlockExecutionWeight = (); - /// The base weight of any extrinsic processed by the runtime, independent of the - /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...) - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; - /// The maximum weight that a single extrinsic of `Normal` dispatch class can have, - /// idependent of the logic of that extrinsics. (Roughly max block weight - average on - /// initialize cost). - type MaximumExtrinsicWeight = MaximumExtrinsicWeight; - /// Maximum size of all encoded transactions (in bytes) that are allowed in one block. - type MaximumBlockLength = MaximumBlockLength; - /// Portion of the block weight that is available to all normal transactions. - type AvailableBlockRatio = AvailableBlockRatio; /// Version of the runtime. type Version = Version; /// Provides information about the pallet setup in the runtime. @@ -225,14 +206,20 @@ impl frame_system::Trait for Runtime { // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); + /// Block and extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// The weight of database operations that the runtime can invoke. + type DbWeight = DbWeight; } -impl pallet_aura::Trait for Runtime { +impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; } type RialtoPoA = pallet_bridge_eth_poa::Instance1; -impl pallet_bridge_eth_poa::Trait for Runtime { +impl pallet_bridge_eth_poa::Config for Runtime { type AuraConfiguration = rialto_poa::BridgeAuraConfiguration; type FinalityVotesCachingInterval = rialto_poa::FinalityVotesCachingInterval; type ValidatorsConfiguration = rialto_poa::BridgeValidatorsConfiguration; @@ -242,7 +229,7 @@ impl pallet_bridge_eth_poa::Trait for Runtime { } type Kovan = pallet_bridge_eth_poa::Instance2; -impl pallet_bridge_eth_poa::Trait for Runtime { +impl pallet_bridge_eth_poa::Config for Runtime { type AuraConfiguration = kovan::BridgeAuraConfiguration; type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval; type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration; @@ -252,7 +239,7 @@ impl pallet_bridge_eth_poa::Trait for Runtime { } type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1; -impl pallet_bridge_currency_exchange::Trait for Runtime { +impl pallet_bridge_currency_exchange::Config for Runtime { type OnTransactionSubmitted = (); type PeerBlockchain = rialto_poa::RialtoBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; @@ -263,7 +250,7 @@ impl pallet_bridge_currency_exchange::Trait for Runtime } type KovanCurrencyExchange = pallet_bridge_currency_exchange::Instance2; -impl pallet_bridge_currency_exchange::Trait for Runtime { +impl pallet_bridge_currency_exchange::Config for Runtime { type OnTransactionSubmitted = (); type PeerBlockchain = kovan::KovanBlockchain; type PeerMaybeLockFundsTransaction = exchange::EthTransaction; @@ -273,7 +260,7 @@ impl pallet_bridge_currency_exchange::Trait for Runtime { type DepositInto = DepositInto; } -impl pallet_bridge_call_dispatch::Trait for Runtime { +impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; @@ -340,7 +327,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { } } -impl pallet_grandpa::Trait for Runtime { +impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; type KeyOwnerProofSystem = (); @@ -356,7 +343,7 @@ parameter_types! { pub const MinimumPeriod: u64 = SLOT_DURATION / 2; } -impl pallet_timestamp::Trait for Runtime { +impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; @@ -372,7 +359,7 @@ parameter_types! { pub const MaxLocks: u32 = 50; } -impl pallet_balances::Trait for Runtime { +impl pallet_balances::Config for Runtime { /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type. @@ -390,14 +377,14 @@ parameter_types! { pub const TransactionByteFee: Balance = 1; } -impl pallet_transaction_payment::Trait for Runtime { +impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } -impl pallet_sudo::Trait for Runtime { +impl pallet_sudo::Config for Runtime { type Event = Event; type Call = Call; } @@ -407,9 +394,9 @@ parameter_types! { pub const Offset: BlockNumber = 0; } -impl pallet_session::Trait for Runtime { +impl pallet_session::Config for Runtime { type Event = Event; - type ValidatorId = ::AccountId; + type ValidatorId = ::AccountId; type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; @@ -421,11 +408,11 @@ impl pallet_session::Trait for Runtime { type WeightInfo = (); } -impl pallet_substrate_bridge::Trait for Runtime { +impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_millau::Millau; } -impl pallet_shift_session_manager::Trait for Runtime {} +impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; @@ -438,7 +425,7 @@ parameter_types! { } pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInstance; -impl pallet_message_lane::Trait for Runtime { +impl pallet_message_lane::Config for Runtime { type Event = Event; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -777,18 +764,18 @@ impl_runtime_apis! { use pallet_bridge_currency_exchange::benchmarking::{ Module as BridgeCurrencyExchangeBench, - Trait as BridgeCurrencyExchangeTrait, + Config as BridgeCurrencyExchangeConfig, ProofParams as BridgeCurrencyExchangeProofParams, }; - impl BridgeCurrencyExchangeTrait for Runtime { + impl BridgeCurrencyExchangeConfig for Runtime { fn make_proof( proof_params: BridgeCurrencyExchangeProofParams, ) -> crate::exchange::EthereumTransactionInclusionProof { use bp_currency_exchange::DepositInto; if proof_params.recipient_exists { - >::DepositInto::deposit_into( + >::DepositInto::deposit_into( proof_params.recipient.clone(), ExistentialDeposit::get(), ).unwrap(); @@ -817,11 +804,11 @@ impl_runtime_apis! { use pallet_message_lane::benchmarking::{ Module as MessageLaneBench, - Trait as MessageLaneTrait, + Config as MessageLaneConfig, MessageParams as MessageLaneMessageParams, }; - impl MessageLaneTrait for Runtime { + impl MessageLaneConfig for Runtime { fn endow_account(account: &Self::AccountId) { pallet_balances::Module::::make_free_balance_be( account, @@ -923,7 +910,7 @@ mod tests { let initial_amount = as Currency>::free_balance(&existing_account); let additional_amount = 10_000; - >::DepositInto::deposit_into( + >::DepositInto::deposit_into( existing_account.clone(), additional_amount, ) @@ -942,7 +929,7 @@ mod tests { let initial_amount = 0; let additional_amount = ExistentialDeposit::get() + 10_000; let new_account: AccountId = [42u8; 32].into(); - >::DepositInto::deposit_into( + >::DepositInto::deposit_into( new_account.clone(), additional_amount, ) diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 680fcb747f8cd..77139b2bb6ab6 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -89,12 +89,12 @@ impl MessageBridge for WithMillauMessageBridge { type BridgedChain = Millau; fn maximal_extrinsic_size_on_target_chain() -> u32 { - bp_millau::MAXIMUM_EXTRINSIC_SIZE + bp_millau::max_extrinsic_size() } fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = bp_millau::MAXIMUM_EXTRINSIC_WEIGHT / 2; + let upper_limit = bp_millau::max_extrinsic_weight() / 2; // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() @@ -116,12 +116,12 @@ impl MessageBridge for WithMillauMessageBridge { } fn this_weight_to_this_balance(weight: Weight) -> bp_rialto::Balance { - ::WeightToFee::calc(&weight) + ::WeightToFee::calc(&weight) } fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_millau::Balance { // we're using the same weights in both chains now - ::WeightToFee::calc(&weight) as _ + ::WeightToFee::calc(&weight) as _ } fn this_balance_to_bridged_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 0c7d4ff4be02b..3ec1fb7284905 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -202,7 +202,7 @@ pub mod source { } // The maximal size of extrinsic at Substrate-based chain depends on the - // `frame_system::Trait::MaximumBlockLength` and `frame_system::Trait::AvailableBlockRatio` + // `frame_system::Config::MaximumBlockLength` and `frame_system::Config::AvailableBlockRatio` // constants. This check is here to be sure that the lane won't stuck because message is too // large to fit into delivery transaction. // @@ -261,10 +261,10 @@ pub mod source { proof: FromBridgedChainMessagesDeliveryProof, ) -> Result, &'static str> where - ThisRuntime: pallet_substrate_bridge::Trait, - ThisRuntime: pallet_message_lane::Trait>>, + ThisRuntime: pallet_substrate_bridge::Config, + ThisRuntime: pallet_message_lane::Config>>, HashOf>: - Into::BridgedChain>>, + Into::BridgedChain>>, { let (bridged_header_hash, bridged_storage_proof, lane) = proof; pallet_substrate_bridge::Module::::parse_finalized_storage_proof( @@ -359,7 +359,7 @@ pub mod target { for FromBridgedChainMessageDispatch where ThisCallDispatchInstance: frame_support::traits::Instance, - ThisRuntime: pallet_bridge_call_dispatch::Trait, + ThisRuntime: pallet_bridge_call_dispatch::Config, pallet_bridge_call_dispatch::Module: bp_message_dispatch::MessageDispatch< (LaneId, MessageNonce), @@ -396,10 +396,10 @@ pub mod target { max_messages: MessageNonce, ) -> Result>>>, &'static str> where - ThisRuntime: pallet_substrate_bridge::Trait, - ThisRuntime: pallet_message_lane::Trait>>, + ThisRuntime: pallet_substrate_bridge::Config, + ThisRuntime: pallet_message_lane::Config>>, HashOf>: - Into::BridgedChain>>, + Into::BridgedChain>>, { verify_messages_proof_with_parser::( proof, @@ -459,7 +459,7 @@ pub mod target { where H: Hasher, B: MessageBridge, - ThisRuntime: pallet_message_lane::Trait>>, + ThisRuntime: pallet_message_lane::Config>>, { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { let storage_outbound_lane_data_key = pallet_message_lane::storage_keys::outbound_lane_data_key::< diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 19c728162e64c..09e49702656f1 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -95,9 +95,9 @@ pub struct MessagePayload: frame_system::Trait { +pub trait Config: frame_system::Config { /// The overarching event type. - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; /// Id of the message. Whenever message is passed to the dispatch module, it emits /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if /// it comes from message-lane module. @@ -113,7 +113,7 @@ pub trait Trait: frame_system::Trait { type Call: Parameter + GetDispatchInfo + Dispatchable< - Origin = ::Origin, + Origin = ::Origin, PostInfo = frame_support::dispatch::PostDispatchInfo, >; /// A type which can be turned into an AccountId from a 256-bit hash. @@ -123,12 +123,12 @@ pub trait Trait: frame_system::Trait { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as CallDispatch {} + trait Store for Module, I: Instance = DefaultInstance> as CallDispatch {} } decl_event!( pub enum Event where - >::MessageId + >::MessageId { /// Message has been rejected by dispatcher because of spec version mismatch. /// Last two arguments are: expected and passed spec version. @@ -147,18 +147,18 @@ decl_event!( decl_module! { /// Call Dispatch FRAME Pallet. - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; } } -impl, I: Instance> MessageDispatch for Module { +impl, I: Instance> MessageDispatch for Module { type Message = MessagePayload< T::SourceChainAccountId, T::TargetChainAccountPublic, T::TargetChainSignature, - >::Call, + >::Call, >; fn dispatch_weight(message: &Self::Message) -> Weight { @@ -168,7 +168,7 @@ impl, I: Instance> MessageDispatch for Module { fn dispatch(bridge: InstanceId, id: T::MessageId, message: Self::Message) { // verify spec version // (we want it to be the same, because otherwise we may decode Call improperly) - let expected_version = ::Version::get().spec_version; + let expected_version = ::Version::get().spec_version; if message.spec_version != expected_version { frame_support::debug::trace!( "Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}", @@ -384,7 +384,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } - impl frame_system::Trait for TestRuntime { + impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; type Call = Call; @@ -396,13 +396,6 @@ mod tests { type Header = Header; type Event = TestEvent; type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; type Version = (); type PalletInfo = (); type AccountData = (); @@ -410,9 +403,12 @@ mod tests { type OnKilledAccount = (); type BaseCallFilter = (); type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); } - impl Trait for TestRuntime { + impl Config for TestRuntime { type Event = TestEvent; type MessageId = MessageId; type SourceChainAccountId = AccountId; @@ -435,7 +431,7 @@ mod tests { fn prepare_message( origin: CallOrigin, call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { MessagePayload { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, @@ -446,20 +442,20 @@ mod tests { fn prepare_root_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { prepare_message(CallOrigin::SourceRoot, call) } fn prepare_target_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); prepare_message(origin, call) } fn prepare_source_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { let origin = CallOrigin::SourceAccount(1); prepare_message(origin, call) } diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index 189dac8407b9d..73304ff40bc38 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -18,7 +18,7 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{BaseHeaderChain, Call, Instance, Module as CurrencyExchangeModule, Trait as CurrencyExchangeTrait}; +use super::{BaseHeaderChain, Call, Config as CurrencyExchangeConfig, Instance, Module as CurrencyExchangeModule}; use sp_std::prelude::*; use frame_benchmarking::{account, benchmarks_instance}; @@ -29,7 +29,7 @@ const WORST_TX_SIZE_FACTOR: u32 = 1000; const WORST_PROOF_SIZE_FACTOR: u32 = 1000; /// Module we're benchmarking here. -pub struct Module, I: Instance>(CurrencyExchangeModule); +pub struct Module, I: Instance>(CurrencyExchangeModule); /// Proof benchmarking parameters. pub struct ProofParams { @@ -45,12 +45,12 @@ pub struct ProofParams { pub proof_size_factor: u32, } -/// Trait that must be implemented by runtime. -pub trait Trait: CurrencyExchangeTrait { +/// Config that must be implemented by runtime. +pub trait Config: CurrencyExchangeConfig { /// Prepare proof for importing exchange transaction. fn make_proof( proof_params: ProofParams, - ) -> <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof; + ) -> <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof; } benchmarks_instance! { diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 036f3b564c10d..4ff88e7b03ab3 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -35,7 +35,7 @@ pub trait OnTransactionSubmitted { } /// The module configuration trait -pub trait Trait: frame_system::Trait { +pub trait Config: frame_system::Config { /// Handler for transaction submission result. type OnTransactionSubmitted: OnTransactionSubmitted; /// Represents the blockchain that we'll be exchanging currency with. @@ -61,7 +61,7 @@ pub trait Trait: frame_system::Trait { } decl_error! { - pub enum Error for Module, I: Instance> { + pub enum Error for Module, I: Instance> { /// Invalid peer blockchain transaction provided. InvalidTransaction, /// Peer transaction has invalid amount. @@ -84,12 +84,12 @@ decl_error! { } decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Imports lock fund transaction of the peer blockchain. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_peer_transaction( origin, - proof: <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, + proof: <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; @@ -125,13 +125,13 @@ decl_module! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as Bridge { + trait Store for Module, I: Instance = DefaultInstance> as Bridge { /// All transfers that have already been claimed. Transfers: map hasher(blake2_128_concat) ::Id => (); } } -impl, I: Instance> Module { +impl, I: Instance> Module { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { @@ -149,7 +149,7 @@ impl, I: Instance> Module { } } -impl, I: Instance> From for Error { +impl, I: Instance> From for Error { fn from(error: ExchangeError) -> Self { match error { ExchangeError::InvalidTransaction => Error::InvalidTransaction, @@ -168,7 +168,7 @@ impl OnTransactionSubmitted for () { } /// Exchange deposit details. -struct DepositDetails, I: Instance> { +struct DepositDetails, I: Instance> { /// Transfer id. pub transfer_id: ::Id, /// Transfer recipient. @@ -179,16 +179,16 @@ struct DepositDetails, I: Instance> { /// Verify and parse transaction proof, preparing everything required for importing /// this transaction proof. -fn prepare_deposit_details, I: Instance>( - proof: &<>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, +fn prepare_deposit_details, I: Instance>( + proof: &<>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, ) -> Result, Error> { // ensure that transaction is included in finalized block that we know of - let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) + let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) .ok_or(Error::::UnfinalizedTransaction)?; // parse transaction let transaction = - >::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; + >::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; let transfer_id = transaction.id; ensure!( !Transfers::::contains_key(&transfer_id), @@ -325,7 +325,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } - impl frame_system::Trait for TestRuntime { + impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; type Call = (); @@ -337,13 +337,6 @@ mod tests { type Header = Header; type Event = (); type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; type Version = (); type PalletInfo = (); type AccountData = (); @@ -351,9 +344,12 @@ mod tests { type OnKilledAccount = (); type BaseCallFilter = (); type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); } - impl Trait for TestRuntime { + impl Config for TestRuntime { type OnTransactionSubmitted = DummyTransactionSubmissionHandler; type PeerBlockchain = DummyBlockchain; type PeerMaybeLockFundsTransaction = DummyTransaction; diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 2dd58d664822f..35a202f3f2fe7 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -218,7 +218,7 @@ benchmarks_instance! { } } -fn initialize_bench, I: Instance>(num_validators: usize) -> AuraHeader { +fn initialize_bench, I: Instance>(num_validators: usize) -> AuraHeader { // Initialize storage with some initial header let initial_header = build_genesis_header(&validator(0)); let initial_difficulty = initial_header.difficulty; diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 75062f763952a..70ebbe624ce5f 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -370,7 +370,7 @@ impl OnHeadersSubmitted for () { } /// The module configuration trait. -pub trait Trait: frame_system::Trait { +pub trait Config: frame_system::Config { /// Aura configuration. type AuraConfiguration: Get; /// Validators configuration. @@ -393,7 +393,7 @@ pub trait Trait: frame_system::Trait { } decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Import single Aura header. Requires transaction to be **UNSIGNED**. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_unsigned_header(origin, header: AuraHeader, receipts: Option>) { @@ -457,7 +457,7 @@ decl_module! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as Bridge { + trait Store for Module, I: Instance = DefaultInstance> as Bridge { /// Best known block. BestBlock: (HeaderId, U256); /// Best finalized block. @@ -505,7 +505,7 @@ decl_storage! { } } -impl, I: Instance> Module { +impl, I: Instance> Module { /// Returns number and hash of the best block known to the bridge module. /// The caller should only submit `import_header` transaction that makes /// (or leads to making) other header the best one. @@ -542,7 +542,7 @@ impl, I: Instance> Module { } } -impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Module { +impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Module { type Call = Call; fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { @@ -584,7 +584,7 @@ impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Mod #[derive(Default)] pub struct BridgeStorage(sp_std::marker::PhantomData<(T, I)>); -impl, I: Instance> BridgeStorage { +impl, I: Instance> BridgeStorage { /// Create new BridgeStorage. pub fn new() -> Self { BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default()) @@ -683,7 +683,7 @@ impl, I: Instance> BridgeStorage { } } -impl, I: Instance> Storage for BridgeStorage { +impl, I: Instance> Storage for BridgeStorage { type Submitter = T::AccountId; fn best_block(&self) -> (HeaderId, U256) { @@ -863,7 +863,7 @@ impl, I: Instance> Storage for BridgeStorage { /// Initialize storage. #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] -pub(crate) fn initialize_storage, I: Instance>( +pub(crate) fn initialize_storage, I: Instance>( initial_header: &AuraHeader, initial_difficulty: U256, initial_validators: &[Address], @@ -1263,7 +1263,7 @@ pub(crate) mod tests { fn finality_votes_are_cached() { run_test(TOTAL_VALIDATORS, |ctx| { let mut storage = BridgeStorage::::new(); - let interval = ::FinalityVotesCachingInterval::get().unwrap(); + let interval = ::FinalityVotesCachingInterval::get().unwrap(); // for all headers with number < interval, cache entry is not created for i in 1..interval { diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 1255cc671962b..e6d105070fc32 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -18,7 +18,7 @@ pub use crate::test_utils::{insert_header, validator_utils::*, validators_change pub use bp_eth_poa::signatures::secret_to_address; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, ChainTime, GenesisConfig, PruningStrategy, Trait}; +use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig, PruningStrategy}; use bp_eth_poa::{Address, AuraHeader, H256, U256}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use secp256k1::SecretKey; @@ -44,7 +44,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } -impl frame_system::Trait for TestRuntime { +impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; type Call = (); @@ -56,13 +56,6 @@ impl frame_system::Trait for TestRuntime { type Header = SubstrateHeader; type Event = (); type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; type Version = (); type PalletInfo = (); type AccountData = (); @@ -70,6 +63,9 @@ impl frame_system::Trait for TestRuntime { type OnKilledAccount = (); type BaseCallFilter = (); type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); } parameter_types! { @@ -78,7 +74,7 @@ parameter_types! { pub TestValidatorsConfiguration: ValidatorsConfiguration = test_validators_config(); } -impl Trait for TestRuntime { +impl Config for TestRuntime { type AuraConfiguration = TestAuraConfiguration; type ValidatorsConfiguration = TestValidatorsConfiguration; type FinalityVotesCachingInterval = TestFinalityVotesCachingInterval; diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index b669856fdb445..e1e145f3d1236 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -27,7 +27,7 @@ use crate::finality::FinalityVotes; use crate::validators::CHANGE_EVENT_HASH; use crate::verification::calculate_score; -use crate::{HeaderToImport, Storage, Trait}; +use crate::{Config, HeaderToImport, Storage}; use bp_eth_poa::{ rlp_encode, @@ -73,7 +73,7 @@ impl HeaderBuilder { } /// Creates default header on top of parent with given hash. - pub fn with_parent_hash_on_runtime, I: crate::Instance>(parent_hash: H256) -> Self { + pub fn with_parent_hash_on_runtime, I: crate::Instance>(parent_hash: H256) -> Self { use crate::Headers; use frame_support::StorageMap; @@ -82,7 +82,7 @@ impl HeaderBuilder { } /// Creates default header on top of parent with given number. First parent is selected. - pub fn with_parent_number_on_runtime, I: crate::Instance>(parent_number: u64) -> Self { + pub fn with_parent_number_on_runtime, I: crate::Instance>(parent_number: u64) -> Self { use crate::HeadersByNumber; use frame_support::StorageMap; diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index ce1d4eb19c968..e56038a555970 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -31,7 +31,7 @@ pub const WORST_MESSAGE_SIZE_FACTOR: u32 = 1000; const SEED: u32 = 0; /// Module we're benchmarking here. -pub struct Module, I: crate::Instance>(crate::Module); +pub struct Module, I: crate::Instance>(crate::Module); /// Benchmark-specific message parameters. pub struct MessageParams { @@ -44,7 +44,7 @@ pub struct MessageParams { } /// Trait that must be implemented by runtime. -pub trait Trait: crate::Trait { +pub trait Config: crate::Config { /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); /// Prepare message to send over lane. @@ -83,7 +83,7 @@ fn bench_lane_id() -> LaneId { *b"test" } -fn send_regular_message, I: Instance>() { +fn send_regular_message, I: Instance>() { let mut outbound_lane = crate::outbound_lane::(bench_lane_id()); outbound_lane.send_message(MessageData { payload: vec![], @@ -91,7 +91,7 @@ fn send_regular_message, I: Instance>() { }); } -fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { +fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { let mut outbound_lane = crate::outbound_lane::(bench_lane_id()); assert!(outbound_lane.confirm_delivery(nonce).is_some()); } diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index 3a21a10223fa3..10ec2f54a20fe 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -282,7 +282,7 @@ mod tests { fn fails_to_receive_messages_above_unrewarded_relayer_entries_limit_per_lane() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let max_nonce = ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); + let max_nonce = ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); for current_nonce in 1..max_nonce + 1 { assert!(lane.receive_message::( TEST_RELAYER_A + current_nonce, @@ -315,7 +315,7 @@ mod tests { fn fails_to_receive_messages_above_unconfirmed_messages_limit_per_lane() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); + let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); for current_nonce in 1..=max_nonce { assert!(lane.receive_message::( TEST_RELAYER_A, diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 1c8553b8bb89b..77bfc72f2caaf 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -69,11 +69,11 @@ const DELIVERY_OVERHEAD_WEIGHT: Weight = 0; const SINGLE_MESSAGE_DELIVERY_WEIGHT: Weight = 0; /// The module configuration trait -pub trait Trait: frame_system::Trait { +pub trait Config: frame_system::Config { // General types /// They overarching event type. - type Event: From> + Into<::Event>; + type Event: From> + Into<::Event>; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever new message is sent. The reason is that if you want to use lane, you should /// be ready to pay for its maintenance. @@ -133,17 +133,17 @@ pub trait Trait: frame_system::Trait { type MessageDispatch: MessageDispatch; } -/// Shortcut to messages proof type for Trait. +/// Shortcut to messages proof type for Config. type MessagesProofOf = - <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; -/// Shortcut to messages delivery proof type for Trait. -type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< - >::OutboundPayload, - ::AccountId, + <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; +/// Shortcut to messages delivery proof type for Config. +type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< + >::OutboundPayload, + ::AccountId, >>::MessagesDeliveryProof; decl_error! { - pub enum Error for Module, I: Instance> { + pub enum Error for Module, I: Instance> { /// All pallet operations are halted. Halted, /// Message has been treated as invalid by chain verifier. @@ -162,7 +162,7 @@ decl_error! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as MessageLane { + trait Store for Module, I: Instance = DefaultInstance> as MessageLane { /// Optional pallet owner. /// /// Pallet owner has a right to halt all pallet operations and then resume it. If it is @@ -192,7 +192,7 @@ decl_storage! { decl_event!( pub enum Event where - ::AccountId, + ::AccountId, { /// Message has been accepted and is waiting to be delivered. MessageAccepted(LaneId, MessageNonce), @@ -204,7 +204,7 @@ decl_event!( ); decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; @@ -443,7 +443,7 @@ decl_module! { nonce, }).expect("message was just confirmed; we never prune unconfirmed messages; qed"); - >::MessageDeliveryAndDispatchPayment::pay_relayer_reward( + >::MessageDeliveryAndDispatchPayment::pay_relayer_reward( &confirmation_relayer, &relayer, &message_data.fee, @@ -464,7 +464,7 @@ decl_module! { } } -impl, I: Instance> Module { +impl, I: Instance> Module { /// Get payload of given outbound message. pub fn outbound_message_payload(lane: LaneId, nonce: MessageNonce) -> Option { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(|message_data| message_data.payload) @@ -521,7 +521,7 @@ pub mod storage_keys { use sp_core::storage::StorageKey; /// Storage key of the outbound message in the runtime storage. - pub fn message_key, I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey { + pub fn message_key, I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey { let message_key = MessageKey { lane_id: *lane, nonce }; let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); StorageKey(raw_storage_key) @@ -533,13 +533,13 @@ pub mod storage_keys { } /// Storage key of the inbound message lane state in the runtime storage. - pub fn inbound_lane_data_key, I: Instance>(lane: &LaneId) -> StorageKey { + pub fn inbound_lane_data_key, I: Instance>(lane: &LaneId) -> StorageKey { StorageKey(InboundLanes::::storage_map_final_key(*lane)) } } /// Ensure that the origin is either root, or `ModuleOwner`. -fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<(), BadOrigin> { +fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), Ok(RawOrigin::Signed(ref signer)) if Some(signer) == Module::::module_owner().as_ref() => Ok(()), @@ -548,7 +548,7 @@ fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<( } /// Ensure that the pallet is in operational mode (not halted). -fn ensure_operational, I: Instance>() -> Result<(), Error> { +fn ensure_operational, I: Instance>() -> Result<(), Error> { if IsHalted::::get() { Err(Error::::Halted) } else { @@ -557,7 +557,7 @@ fn ensure_operational, I: Instance>() -> Result<(), Error> { } /// Creates new inbound lane object, backed by runtime storage. -fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { +fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { InboundLane::new(RuntimeInboundLaneStorage { lane_id, cached_data: RefCell::new(None), @@ -566,7 +566,7 @@ fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane, I: Instance>(lane_id: LaneId) -> OutboundLane> { +fn outbound_lane, I: Instance>(lane_id: LaneId) -> OutboundLane> { OutboundLane::new(RuntimeOutboundLaneStorage { lane_id, _phantom: Default::default(), @@ -574,13 +574,13 @@ fn outbound_lane, I: Instance>(lane_id: LaneId) -> OutboundLane, I = DefaultInstance> { +struct RuntimeInboundLaneStorage, I = DefaultInstance> { lane_id: LaneId, cached_data: RefCell>>, _phantom: PhantomData, } -impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { +impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { type MessageFee = T::InboundMessageFee; type Relayer = T::InboundRelayer; @@ -625,7 +625,7 @@ struct RuntimeOutboundLaneStorage { _phantom: PhantomData<(T, I)>, } -impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorage { +impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorage { type MessageFee = T::OutboundMessageFee; fn id(&self) -> LaneId { @@ -691,7 +691,7 @@ fn verify_and_decode_messages_proof, Fee, Dispatch /// /// This account stores all the fees paid by submitters. Relayers are able to claim these /// funds as at their convenience. -fn relayer_fund_account_id, I: Instance>() -> T::AccountId { +fn relayer_fund_account_id, I: Instance>() -> T::AccountId { use sp_runtime::traits::Convert; let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); T::AccountIdConverter::convert(encoded_id) diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index cdf29938d8987..2c3418b98f44e 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::Trait; +use crate::Config; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, Sender, TargetHeaderChain}, @@ -69,7 +69,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } -impl frame_system::Trait for TestRuntime { +impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; type Call = (); @@ -81,13 +81,6 @@ impl frame_system::Trait for TestRuntime { type Header = SubstrateHeader; type Event = TestEvent; type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = MaximumBlockWeight; - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; type Version = (); type PalletInfo = (); type AccountData = (); @@ -95,6 +88,9 @@ impl frame_system::Trait for TestRuntime { type OnKilledAccount = (); type BaseCallFilter = (); type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); } parameter_types! { @@ -104,7 +100,7 @@ parameter_types! { pub const MaxMessagesInDeliveryTransaction: u64 = 128; } -impl Trait for TestRuntime { +impl Config for TestRuntime { type Event = TestEvent; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 918c2513f41bc..88928986f0df0 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -23,21 +23,21 @@ use frame_support::{decl_module, decl_storage}; use sp_std::prelude::*; /// The module configuration trait. -pub trait Trait: pallet_session::Trait {} +pub trait Config: pallet_session::Config {} decl_module! { /// Shift session manager pallet. - pub struct Module for enum Call where origin: T::Origin {} + pub struct Module for enum Call where origin: T::Origin {} } decl_storage! { - trait Store for Module as ShiftSessionManager { + trait Store for Module as ShiftSessionManager { /// Validators of first two sessions. InitialValidators: Option>; } } -impl pallet_session::SessionManager for Module { +impl pallet_session::SessionManager for Module { fn end_session(_: sp_staking::SessionIndex) {} fn start_session(_: sp_staking::SessionIndex) {} fn new_session(session_index: sp_staking::SessionIndex) -> Option> { @@ -61,7 +61,7 @@ impl pallet_session::SessionManager for Module { } } -impl Module { +impl Module { /// Select validators for session. fn select_validators( session_index: sp_staking::SessionIndex, @@ -112,7 +112,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } - impl frame_system::Trait for TestRuntime { + impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; type Call = (); @@ -124,13 +124,6 @@ mod tests { type Header = Header; type Event = (); type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; type Version = (); type PalletInfo = (); type AccountData = (); @@ -138,6 +131,9 @@ mod tests { type OnKilledAccount = (); type BaseCallFilter = (); type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); } parameter_types! { @@ -145,9 +141,9 @@ mod tests { pub const Offset: u64 = 0; } - impl pallet_session::Trait for TestRuntime { + impl pallet_session::Config for TestRuntime { type Event = (); - type ValidatorId = ::AccountId; + type ValidatorId = ::AccountId; type ValidatorIdOf = ConvertInto; type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; @@ -158,7 +154,7 @@ mod tests { type WeightInfo = (); } - impl Trait for TestRuntime {} + impl Config for TestRuntime {} pub struct TestSessionHandler; impl pallet_session::SessionHandler for TestSessionHandler { diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 58bf3ea05dd9d..aa01c32964759 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -60,13 +60,13 @@ mod mock; mod fork_tests; /// Block number of the bridged chain. -pub(crate) type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; +pub(crate) type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; /// Block hash of the bridged chain. -pub(crate) type BridgedBlockHash = HashOf<::BridgedChain>; +pub(crate) type BridgedBlockHash = HashOf<::BridgedChain>; /// Hasher of the bridged chain. -pub(crate) type BridgedBlockHasher = HasherOf<::BridgedChain>; +pub(crate) type BridgedBlockHasher = HasherOf<::BridgedChain>; /// Header of the bridged chain. -pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; +pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; /// A convenience type identifying headers. #[derive(RuntimeDebug, PartialEq)] @@ -77,13 +77,13 @@ pub struct HeaderId { pub hash: H::Hash, } -pub trait Trait: frame_system::Trait { +pub trait Config: frame_system::Config { /// Chain that we are bridging here. type BridgedChain: Chain; } decl_storage! { - trait Store for Module as SubstrateBridge { + trait Store for Module as SubstrateBridge { /// The number of the highest block(s) we know of. BestHeight: BridgedBlockNumber; /// Hash of the header at the highest known height. @@ -137,7 +137,7 @@ decl_storage! { } decl_error! { - pub enum Error for Module { + pub enum Error for Module { /// This header has failed basic verification. InvalidHeader, /// This header has not been finalized. @@ -156,7 +156,7 @@ decl_error! { } decl_module! { - pub struct Module for enum Call where origin: T::Origin { + pub struct Module for enum Call where origin: T::Origin { type Error = Error; /// Import a signed Substrate header into the runtime. @@ -277,7 +277,7 @@ decl_module! { } } -impl Module { +impl Module { /// Get the highest header(s) that the pallet knows of. pub fn best_headers() -> Vec<(BridgedBlockNumber, BridgedBlockHash)> { PalletStorage::::new() @@ -353,7 +353,7 @@ impl Module { } /// Ensure that the origin is either root, or `ModuleOwner`. -fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { +fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::module_owner().as_ref() => Ok(()), @@ -362,7 +362,7 @@ fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { } /// Ensure that the pallet is in operational mode (not halted). -fn ensure_operational() -> Result<(), Error> { +fn ensure_operational() -> Result<(), Error> { if IsHalted::get() { Err(>::Halted) } else { @@ -372,7 +372,7 @@ fn ensure_operational() -> Result<(), Error> { /// Since this writes to storage with no real checks this should only be used in functions that were /// called by a trusted origin. -fn initialize_bridge(init_params: InitializationData>) { +fn initialize_bridge(init_params: InitializationData>) { let InitializationData { header, authority_list, @@ -488,7 +488,7 @@ impl PalletStorage { } } -impl BridgeStorage for PalletStorage { +impl BridgeStorage for PalletStorage { type Header = BridgedHeader; fn write_header(&mut self, header: &ImportedHeader>) { diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index 88ed2ed469816..7c2b5429ed982 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -20,7 +20,7 @@ #![cfg(test)] -use crate::Trait; +use crate::Config; use bp_runtime::Chain; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use sp_runtime::{ @@ -45,7 +45,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } -impl frame_system::Trait for TestRuntime { +impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; type Call = (); @@ -57,13 +57,6 @@ impl frame_system::Trait for TestRuntime { type Header = Header; type Event = (); type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type DbWeight = (); - type BlockExecutionWeight = (); - type ExtrinsicBaseWeight = (); - type MaximumExtrinsicWeight = (); - type AvailableBlockRatio = AvailableBlockRatio; - type MaximumBlockLength = MaximumBlockLength; type Version = (); type PalletInfo = (); type AccountData = (); @@ -71,9 +64,12 @@ impl frame_system::Trait for TestRuntime { type OnKilledAccount = (); type BaseCallFilter = (); type SystemWeightInfo = (); + type DbWeight = (); + type BlockWeights = (); + type BlockLength = (); } -impl Trait for TestRuntime { +impl Config for TestRuntime { type BridgedChain = TestBridgedChain; } @@ -81,10 +77,10 @@ impl Trait for TestRuntime { pub struct TestBridgedChain; impl Chain for TestBridgedChain { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hashing; - type Header = ::Header; + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hashing; + type Header = ::Header; } pub fn run_test(test: impl FnOnce() -> T) -> T { diff --git a/modules/substrate/src/storage_proof.rs b/modules/substrate/src/storage_proof.rs index 820a84737f175..4b908dde15e9f 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/modules/substrate/src/storage_proof.rs @@ -65,7 +65,7 @@ pub enum Error { StorageValueUnavailable, } -impl From for crate::Error { +impl From for crate::Error { fn from(error: Error) -> Self { match error { Error::StorageRootMismatch => crate::Error::StorageRootMismatch, diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index 1c22da3cd9bd5..d512fc632a515 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -22,6 +22,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -36,6 +37,7 @@ std = [ "bp-runtime/std", "fixed-hash/std", "frame-support/std", + "frame-system/std", "hash256-std-hasher/std", "impl-codec/std", "impl-serde", diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 148a19be0f016..5b74ec54c1318 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -24,11 +24,14 @@ mod millau_hash; use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; -use frame_support::{weights::Weight, RuntimeDebug}; +use frame_support::{ + weights::{constants::WEIGHT_PER_MILLIS, DispatchClass, Weight}, + RuntimeDebug, +}; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{IdentifyAccount, Verify}, - MultiSignature, MultiSigner, + MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; use sp_trie::{trie_types::Layout, TrieConfiguration}; @@ -68,23 +71,25 @@ impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { } } -/// Maximal weight of single Millau block. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 10_000_000_000; -/// Portion of block reserved for regular transactions. -pub const AVAILABLE_BLOCK_RATIO: u32 = 75; -/// Maximal weight of single Millau extrinsic (65% of maximum block weight = 75% for regular -/// transactions minus 10% for initialization). -pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); -/// Maximal size of Millau block. -pub const MAXIMUM_BLOCK_SIZE: u32 = 2 * 1024 * 1024; -/// Maximal size of single normal Millau extrinsic (75% of maximal block size). -pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLOCK_RATIO; +/// Maximum weight of single Millau block. +/// +/// This represents 0.1 seconds of compute assuming a target block time of six seconds. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 10 * WEIGHT_PER_MILLIS; + +/// Represents the average portion of a block's weight that will be used by an +/// `on_initialize()` runtime call. +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); + +/// Represents the portion of a block that will be used by Normal extrinsics. +pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); // TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 1024; + /// Maximal number of unrewarded relayer entries at inbound lane. pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; + /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; @@ -155,6 +160,44 @@ impl sp_runtime::traits::Convert for AccountIdConverte hash.to_fixed_bytes().into() } } + +/// Get a struct which defines the weight limits and values used during extrinsic execution. +pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { + frame_system::limits::BlockWeights::builder() + // Allowance for Normal class + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + // Allowance for Operational class + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Extra reserved space for Operational class + weights.reserved = Some(MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + // By default Mandatory class is not limited at all. + // This parameter is used to derive maximal size of a single extrinsic. + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic() +} + +/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. +pub fn max_extrinsic_weight() -> Weight { + runtime_block_weights() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) +} + +/// Get a struct which tracks the length in bytes for each extrinsic class in a Millau block. +pub fn runtime_block_length() -> frame_system::limits::BlockLength { + frame_system::limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO) +} + +/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. +pub fn max_extrinsic_size() -> u32 { + *runtime_block_length().max.get(DispatchClass::Normal) +} + sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// diff --git a/primitives/millau/src/millau_hash.rs b/primitives/millau/src/millau_hash.rs index 521b8997ad603..e917329d2cc09 100644 --- a/primitives/millau/src/millau_hash.rs +++ b/primitives/millau/src/millau_hash.rs @@ -18,7 +18,7 @@ use parity_util_mem::MallocSizeOf; use sp_runtime::traits::CheckEqual; // `sp_core::H512` can't be used, because it doesn't implement `CheckEqual`, which is required -// by `frame_system::Trait::Hash`. +// by `frame_system::Config::Hash`. fixed_hash::construct_fixed_hash! { /// Hash type used in Millau chain. diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index 53305d7ed862e..6d12dd0b0a413 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -16,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -27,6 +28,7 @@ std = [ "bp-message-lane/std", "bp-runtime/std", "frame-support/std", + "frame-system/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index f91f1689b9470..26599786c2d45 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -22,31 +22,36 @@ use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; -use frame_support::{weights::Weight, RuntimeDebug}; +use frame_support::{ + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, + RuntimeDebug, +}; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, + MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; /// Maximal weight of single Rialto block. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2_000_000_000_000; -/// Portion of block reserved for regular transactions. -pub const AVAILABLE_BLOCK_RATIO: u32 = 75; -/// Maximal weight of single Rialto extrinsic (65% of maximum block weight = 75% for regular -/// transactions minus 10% for initialization). -pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = MAXIMUM_BLOCK_WEIGHT / 100 * (AVAILABLE_BLOCK_RATIO as Weight - 10); -/// Maximal size of Rialto block. -pub const MAXIMUM_BLOCK_SIZE: u32 = 5 * 1024 * 1024; -/// Maximal size of single normal Rialto extrinsic (75% of maximal block size). -pub const MAXIMUM_EXTRINSIC_SIZE: u32 = MAXIMUM_BLOCK_SIZE / 100 * AVAILABLE_BLOCK_RATIO; +/// +/// This represents two seconds of compute assuming a target block time of six seconds. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; + +/// Represents the average portion of a block's weight that will be used by an +/// `on_initialize()` runtime call. +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); + +/// Represents the portion of a block that will be used by Normal extrinsics. +pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); // TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; + /// Maximal number of unrewarded relayer entries at inbound lane. pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; + /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; @@ -131,6 +136,43 @@ pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Get a struct which defines the weight limits and values used during extrinsic execution. +pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { + frame_system::limits::BlockWeights::builder() + // Allowance for Normal class + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + // Allowance for Operational class + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Extra reserved space for Operational class + weights.reserved = Some(MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + // By default Mandatory class is not limited at all. + // This parameter is used to derive maximal size of a single extrinsic. + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic() +} + +/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. +pub fn max_extrinsic_weight() -> Weight { + runtime_block_weights() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) +} + +/// Get a struct which tracks the length in bytes for each extrinsic class in a Millau block. +pub fn runtime_block_length() -> frame_system::limits::BlockLength { + frame_system::limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO) +} + +/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. +pub fn max_extrinsic_size() -> u32 { + *runtime_block_length().max.get(DispatchClass::Normal) +} + sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index 37ce156a0ed2a..f309c3f775e76 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -56,7 +56,7 @@ pub trait Chain: ChainBase { type Call: Dispatchable + Debug; } -/// Substrate-based chain with `frame_system::Trait::AccountData` set to +/// Substrate-based chain with `frame_system::Config::AccountData` set to /// the `pallet_balances::AccountData`. pub trait ChainWithBalances: Chain { /// Balance of an account in native tokens. diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 736e278771f0a..268a20beb76ef 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -132,9 +132,9 @@ pub fn run( max_messages_in_single_batch: bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, // TODO: subtract base weight of delivery from this when it'll be known // https://github.com/paritytech/parity-bridges-common/issues/78 - max_messages_weight_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_WEIGHT, + max_messages_weight_in_single_batch: bp_rialto::max_extrinsic_weight(), // 2/3 is reserved for proofs and tx overhead - max_messages_size_in_single_batch: bp_rialto::MAXIMUM_EXTRINSIC_SIZE as usize / 3, + max_messages_size_in_single_batch: bp_rialto::max_extrinsic_size() as usize / 3, }, }, MillauSourceClient::new(millau_client, lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 2f869a122a73c..0615810612b70 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -132,9 +132,9 @@ pub fn run( max_messages_in_single_batch: bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, // TODO: subtract base weight of delivery from this when it'll be known // https://github.com/paritytech/parity-bridges-common/issues/78 - max_messages_weight_in_single_batch: bp_millau::MAXIMUM_EXTRINSIC_WEIGHT, + max_messages_weight_in_single_batch: bp_millau::max_extrinsic_weight(), // 2/3 is reserved for proofs and tx overhead - max_messages_size_in_single_batch: bp_millau::MAXIMUM_EXTRINSIC_SIZE as usize / 3, + max_messages_size_in_single_batch: bp_millau::max_extrinsic_size() as usize / 3, }, }, RialtoSourceClient::new(rialto_client, lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), From baec090830c960c517393d8c12766fc8d7c5ac28 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 16 Dec 2020 06:24:35 -0500 Subject: [PATCH 0264/1210] Rialto to Millau Transfer Generator (#568) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add option to relay for sending transfers to Millau chain * Endow derived accounts on Millau chain * Update message generator entrypoint script to send transfers * Use correct command when sending messages * Send Root messages from Root origin on source chain * Wrap calls from Root Origin in Sudo Call * Allow Root to send messages without paying fees * Use correct variable when sending messages to Rialto * Print warning if no message type is provided to script. * Add note mentioning that certain source origins aren't supported yet * Use correct runtime when initializing header sync * Remove option to send messages as Root * Remove endowment of derived Root accounts * Fix indentation. Co-authored-by: Tomasz Drwięga --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/chain_spec.rs | 14 ++++++ bin/rialto/node/src/chain_spec.rs | 10 ----- modules/message-lane/src/instant_payments.rs | 8 ++-- primitives/millau/src/lib.rs | 14 ++++++ primitives/rialto/src/lib.rs | 2 +- relays/substrate/src/cli.rs | 28 +++++++----- relays/substrate/src/main.rs | 46 ++++++++++++-------- 8 files changed, 80 insertions(+), 44 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 149731529f782..1696f73a48173 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -16,7 +16,7 @@ structopt = "0.3.21" # Bridge dependencies bp-message-lane = { path = "../../../primitives/message-lane" } -bp-rialto = { path = "../../../primitives/rialto" } +bp-millau= { path = "../../../primitives/millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 8c7c40472751b..2ead8612fac21 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, @@ -121,6 +122,9 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), ], true, ) @@ -173,3 +177,13 @@ fn testnet_genesis( }), } } + +#[test] +fn derived_dave_account_is_as_expected() { + let dave = get_account_id_from_seed::("Dave"); + let derived: AccountId = derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); + assert_eq!( + derived.to_string(), + "5G81vRqUUysQGtN5aEThD5UsLdt4rZWSbVLkjuZzLHadp8ZD".to_string() + ); +} diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 229fbd1cc90ef..dc2a9afea6135 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -122,7 +122,6 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), - derive_account_from_millau_id(bp_runtime::SourceAccount::Root), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), @@ -206,12 +205,3 @@ fn derived_dave_account_is_as_expected() { "5Hg7WQyk8C1FmPzxY3xSjR7S6zZZC5sAL35vMr6NpW17jBhQ".to_string() ); } - -#[test] -fn derived_root_account_is_as_expected() { - let root: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Root); - assert_eq!( - root.to_string(), - "5HYYwXQvxhgdcBYs6kzqfK1HW6M3UF3Kh4YM7j288yiqbhnt".to_string() - ); -} diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index fe860fdb3f8ac..41f8b48b74749 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -46,9 +46,11 @@ where Currency::transfer(submitter, relayer_fund_account, *fee, ExistenceRequirement::AllowDeath) .map_err(Into::into) } - Sender::Root | Sender::None => { - // fixme: we might want to add root account id to this struct. - Err("Root and None account is not allowed to send regular messages.") + Sender::Root => { + Err("Sending messages from Root account is not supported yet. See GitHub issue #559 for more.") + } + Sender::None => { + Err("Sending messages from None account is not supported yet. See GitHub issue #559 for more.") } } } diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 5b74ec54c1318..8642b04cf0d43 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -29,6 +29,7 @@ use frame_support::{ RuntimeDebug, }; use sp_core::Hasher as HasherT; +use sp_runtime::traits::Convert; use sp_runtime::{ traits::{IdentifyAccount, Verify}, MultiSignature, MultiSigner, Perbill, @@ -161,6 +162,19 @@ impl sp_runtime::traits::Convert for AccountIdConverte } } +/// We use this to get the account on Millau (target) which is derived from Rialto's (source) +/// account. We do this so we can fund the derived account on Millau at Genesis to it can pay +/// transaction fees. +/// +/// The reason we can use the same `AccountId` type for both chains is because they share the same +/// development seed phrase. +/// +/// Note that this should only be used for testing. +pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + /// Get a struct which defines the weight limits and values used during extrinsic execution. pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { frame_system::limits::BlockWeights::builder() diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 26599786c2d45..71f0329afc37d 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -132,7 +132,7 @@ impl Convert for AccountIdConverter { // // Note that this should only be used for testing. pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(*b"mlau", id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_BRIDGE_INSTANCE, id); AccountIdConverter::convert(encoded_id) } diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index d3662ba26840e..0e7f92001a355 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -138,12 +138,15 @@ pub enum Command { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, - /// Message type. - #[structopt(long, possible_values = &ToMillauMessage::variants())] - message: ToMillauMessage, /// Delivery and dispatch fee. #[structopt(long)] fee: bp_rialto::Balance, + /// Message type. + #[structopt(subcommand)] + message: ToMillauMessage, + /// The origin to use when dispatching the message on the target chain. + #[structopt(long, possible_values = &Origins::variants())] + origin: Origins, }, } @@ -161,19 +164,24 @@ pub enum ToRialtoMessage { }, } -arg_enum! { - #[derive(Debug)] - /// All possible messages that may be delivered to the Millau chain. - pub enum ToMillauMessage { - Remark, - } +/// All possible messages that may be delivered to the Millau chain. +#[derive(StructOpt, Debug)] +pub enum ToMillauMessage { + /// Make an on-chain remark (comment). + Remark, + /// Transfer the specified `amount` of native tokens to a particular `recipient`. + Transfer { + #[structopt(long)] + recipient: bp_millau::AccountId, + #[structopt(long)] + amount: bp_millau::Balance, + }, } arg_enum! { #[derive(Debug)] /// The origin to use when dispatching the message on the target chain. pub enum Origins { - Root, Target, Source, } diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 789105a27b18a..a63dc9623ed16 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -97,7 +97,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { &rialto_client, &rialto_sign.signer, rialto_signer_next_index, - millau_runtime::SudoCall::sudo(Box::new( + rialto_runtime::SudoCall::sudo(Box::new( rialto_runtime::BridgeMillauCall::initialize(initialization_data).into(), )) .into(), @@ -290,12 +290,6 @@ async fn run_command(command: cli::Command) -> Result<(), String> { let rialto_origin_public = rialto_sign.signer.public(); let payload = match origin { - cli::Origins::Root => MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: CallOrigin::SourceRoot, - call: rialto_call.encode(), - }, cli::Origins::Source => MessagePayload { spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, @@ -312,7 +306,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { spec_version: rialto_runtime::VERSION.spec_version, weight: rialto_call_weight, origin: CallOrigin::TargetAccount( - millau_account_id.clone(), + millau_account_id, rialto_origin_public.into(), rialto_origin_signature.into(), ), @@ -383,6 +377,8 @@ async fn run_command(command: cli::Command) -> Result<(), String> { lane, message, fee, + origin, + .. } => { let rialto_client = RialtoClient::new(ConnectionParams { host: rialto.rialto_host, @@ -412,21 +408,29 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .as_bytes() .to_vec(), )), + cli::ToMillauMessage::Transfer { recipient, amount } => { + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) + } }; - let millau_call_weight = millau_call.get_dispatch_info().weight; + let millau_call_weight = millau_call.get_dispatch_info().weight; let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); let millau_origin_public = millau_sign.signer.public(); - let mut millau_origin_signature_message = Vec::new(); - millau_call.encode_to(&mut millau_origin_signature_message); - rialto_account_id.encode_to(&mut millau_origin_signature_message); - let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); + let payload = match origin { + cli::Origins::Source => MessagePayload { + spec_version: millau_runtime::VERSION.spec_version, + weight: millau_call_weight, + origin: CallOrigin::SourceAccount(rialto_account_id), + call: millau_call.encode(), + }, + cli::Origins::Target => { + let mut millau_origin_signature_message = Vec::new(); + millau_call.encode_to(&mut millau_origin_signature_message); + rialto_account_id.encode_to(&mut millau_origin_signature_message); + let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); - let rialto_call = - rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( - lane.into(), MessagePayload { spec_version: millau_runtime::VERSION.spec_version, weight: millau_call_weight, @@ -436,9 +440,13 @@ async fn run_command(command: cli::Command) -> Result<(), String> { millau_origin_signature.into(), ), call: millau_call.encode(), - }, - fee, - )); + } + } + }; + + let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( + rialto_runtime::MessageLaneCall::send_message(lane.into(), payload, fee), + ); let signed_rialto_call = Rialto::sign_transaction( &rialto_client, From e929a746203b9f5493927031262b28e1b25e44a0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 16 Dec 2020 15:40:16 +0300 Subject: [PATCH 0265/1210] Benchmarks for message delivery transaction (#567) * benchmarks for pallet_message_lane::receive_messages_proof * use CallOrigin::TargetAccount (worst case of CallOrigin) * fmt * closures * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * fix compilation Co-authored-by: Hernando Castano --- bin/rialto/runtime/Cargo.toml | 1 + bin/rialto/runtime/src/lib.rs | 76 +++++- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/Cargo.toml | 11 + bin/runtime-common/src/lib.rs | 1 + bin/runtime-common/src/messages.rs | 12 +- .../src/messages_benchmarking.rs | 144 +++++++++++ modules/message-lane/src/benchmarking.rs | 228 +++++++++++++++++- modules/message-lane/src/lib.rs | 9 +- modules/substrate/Cargo.toml | 1 + modules/substrate/src/lib.rs | 12 + 11 files changed, 479 insertions(+), 18 deletions(-) create mode 100644 bin/runtime-common/src/messages_benchmarking.rs diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 29226e1cb114b..e1ab858a033e7 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -115,6 +115,7 @@ std = [ "sp-version/std", ] runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", "frame-benchmarking", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 04534d48021bf..89d84f2e72bc6 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -806,9 +806,14 @@ impl_runtime_apis! { Module as MessageLaneBench, Config as MessageLaneConfig, MessageParams as MessageLaneMessageParams, + MessageProofParams as MessageLaneMessageProofParams, }; impl MessageLaneConfig for Runtime { + fn bridged_relayer_id() -> Self::InboundRelayer { + Default::default() + } + fn endow_account(account: &Self::AccountId) { pallet_balances::Module::::make_free_balance_be( account, @@ -816,7 +821,7 @@ impl_runtime_apis! { ); } - fn prepare_message( + fn prepare_outbound_message( params: MessageLaneMessageParams, ) -> (millau_messages::ToMillauMessagePayload, Balance) { use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; @@ -842,6 +847,75 @@ impl_runtime_apis! { }; (message, 1_000_000_000) } + + fn prepare_message_proof( + params: MessageLaneMessageProofParams, + ) -> (millau_messages::FromMillauMessagesProof, Weight) { + use crate::millau_messages::{Millau, WithMillauMessageBridge}; + use bp_message_lane::MessageKey; + use bridge_runtime_common::{ + messages::ChainWithMessageLanes, + messages_benchmarking::{ed25519_sign, prepare_message_proof}, + }; + use codec::Encode; + use frame_support::weights::GetDispatchInfo; + use pallet_message_lane::storage_keys; + use sp_runtime::traits::Header; + + let call = Call::System(SystemCall::remark(vec![])); + let call_weight = call.get_dispatch_info().weight; + + let millau_account_id: bp_millau::AccountId = Default::default(); + let (rialto_raw_public, rialto_raw_signature) = ed25519_sign( + &call, + &millau_account_id, + ); + let rialto_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(rialto_raw_public)); + let rialto_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( + rialto_raw_signature, + )); + + let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< + Runtime, + ::MessageLaneInstance, + >( + &message_key.lane_id, message_key.nonce, + ).0; + let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::< + ::MessageLaneInstance, + >( + &lane_id, + ).0; + let make_millau_header = |state_root| bp_millau::Header::new( + 0, + Default::default(), + state_root, + Default::default(), + Default::default(), + ); + + prepare_message_proof::( + params, + make_millau_message_key, + make_millau_outbound_lane_data_key, + make_millau_header, + call_weight, + pallet_bridge_call_dispatch::MessagePayload { + spec_version: VERSION.spec_version, + weight: call_weight, + origin: pallet_bridge_call_dispatch::CallOrigin::< + bp_millau::AccountId, + MultiSigner, + Signature, + >::TargetAccount( + millau_account_id, + rialto_public, + rialto_signature, + ), + call: call.encode(), + }.encode(), + ) + } } add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeKovan); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 77139b2bb6ab6..e1395d99b1e51 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -71,7 +71,7 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi >; /// Messages proof for Millau -> Rialto messages. -type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; +pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Rialto -> Millau messages. type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index da63005c41b3b..99cc02c20babd 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } # Bridge dependencies @@ -23,7 +24,9 @@ pallet-substrate-bridge = { path = "../../modules/substrate", default-features = # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -39,7 +42,15 @@ std = [ "pallet-bridge-call-dispatch/std", "pallet-message-lane/std", "pallet-substrate-bridge/std", + "sp-core/std", "sp-runtime/std", + "sp-state-machine/std", "sp-std/std", "sp-trie/std", ] +runtime-benchmarks = [ + "ed25519-dalek/u64_backend", + "pallet-message-lane/runtime-benchmarks", + "pallet-substrate-bridge/runtime-benchmarks", + "sp-state-machine", +] diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 3168383f5eb8f..2842e3b6592a4 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -19,3 +19,4 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod messages; +pub mod messages_benchmarking; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3ec1fb7284905..029707a017ebb 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -27,7 +27,7 @@ use bp_message_lane::{ InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use bp_runtime::InstanceId; -use codec::{Compact, Decode, Input}; +use codec::{Compact, Decode, Encode, Input}; use frame_support::{traits::Instance, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; @@ -96,14 +96,14 @@ pub trait ChainWithMessageLanes { /// Signature type used on the chain. type Signature: Decode; /// Call type on the chain. - type Call: Decode; + type Call: Encode + Decode; /// Type of weight that is used on the chain. This would almost always be a regular /// `frame_support::weight::Weight`. But since the meaning of weight on different chains /// may be different, the `WeightOf<>` construct is used to avoid confusion between /// different weights. type Weight: From + PartialOrd; /// Type of balances that is used on the chain. - type Balance: Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; + type Balance: Encode + Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; /// Instance of the message-lane pallet. type MessageLaneInstance: Instance; @@ -327,6 +327,12 @@ pub mod target { /// Message payload for Bridged -> This messages. pub struct FromBridgedChainMessagePayload(pub(crate) FromBridgedChainDecodedMessagePayload); + impl From> for FromBridgedChainMessagePayload { + fn from(decoded_payload: FromBridgedChainDecodedMessagePayload) -> Self { + Self(decoded_payload) + } + } + impl Decode for FromBridgedChainMessagePayload { fn decode(input: &mut I) -> Result { // for bridged chain our Calls are opaque - they're encoded to Vec by submitter diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs new file mode 100644 index 0000000000000..e3dd705f8fc35 --- /dev/null +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -0,0 +1,144 @@ +// Copyright 2019-2020 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 . + +//! Everything required to run benchmarks of message-lanes, based on +//! `bridge_runtime_common::messages` implementation. + +#![cfg(feature = "runtime-benchmarks")] + +use crate::messages::{target::FromBridgedChainMessagesProof, BalanceOf, BridgedChain, HashOf, MessageBridge}; + +use bp_message_lane::{LaneId, MessageData, MessageKey, MessagePayload}; +use codec::Encode; +use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; +use frame_support::weights::Weight; +use pallet_message_lane::benchmarking::MessageProofParams; +use sp_core::Hasher; +use sp_runtime::traits::Header; +use sp_std::prelude::*; +use sp_trie::{read_trie_value_with, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, StorageProof, TrieMut}; + +/// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. +/// +/// Returns public key of the signer and the signature itself. +pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode) -> ([u8; 32], [u8; 64]) { + // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) + let target_secret = SecretKey::from_bytes(&[ + 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050, + 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, + ]) + .expect("harcoded key is valid"); + let target_public: PublicKey = (&target_secret).into(); + + let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; + target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); + target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); + let target_pair = ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); + + let mut signature_message = Vec::new(); + target_call.encode_to(&mut signature_message); + source_account_id.encode_to(&mut signature_message); + let target_origin_signature = target_pair + .try_sign(&signature_message) + .expect("Ed25519 try_sign should not fail in benchmarks"); + + (target_public.to_bytes(), target_origin_signature.to_bytes()) +} + +/// Prepare proof of messages for the `receive_messages_proof` call. +pub fn prepare_message_proof( + params: MessageProofParams, + make_bridged_message_storage_key: MM, + make_bridged_outbound_lane_data_key: ML, + make_bridged_header: MH, + message_dispatch_weight: Weight, + message_payload: MessagePayload, +) -> (FromBridgedChainMessagesProof, Weight) +where + B: MessageBridge, + H: Hasher, + R: pallet_substrate_bridge::Config, + ::Hash: Into>>, + MM: Fn(MessageKey) -> Vec, + ML: Fn(LaneId) -> Vec, + MH: Fn(H::Out) -> ::Header, +{ + // prepare Bridged chain storage with messages and (optionally) outbound lane state + let message_count = params + .message_nonces + .end() + .saturating_sub(*params.message_nonces.start()) + + 1; + let mut storage_keys = Vec::with_capacity(message_count as usize + 1); + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + + // insert messages + for nonce in params.message_nonces.clone() { + let message_key = MessageKey { + lane_id: params.lane, + nonce, + }; + let message_data = MessageData { + fee: BalanceOf::>::from(0), + payload: message_payload.clone(), + }; + let storage_key = make_bridged_message_storage_key(message_key); + trie.insert(&storage_key, &message_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + + // insert outbound lane state + if let Some(outbound_lane_data) = params.outbound_lane_data { + let storage_key = make_bridged_outbound_lane_data_key(params.lane); + trie.insert(&storage_key, &outbound_lane_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + } + + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::::new(); + for storage_key in storage_keys { + read_trie_value_with::, _, _>(&mdb, &root, &storage_key, &mut proof_recorder) + .map_err(|_| "read_trie_value_with has failed") + .expect("read_trie_value_with should not fail in benchmarks"); + } + let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + // prepare Bridged chain header and insert it into the Substrate pallet + let bridged_header = make_bridged_header(root); + let bridged_header_hash = bridged_header.hash(); + pallet_substrate_bridge::initialize_for_benchmarks::(bridged_header); + + ( + ( + bridged_header_hash.into(), + StorageProof::new(storage_proof), + params.lane, + *params.message_nonces.start(), + *params.message_nonces.end(), + ), + message_dispatch_weight + .checked_mul(message_count) + .expect("too many messages requested by benchmark"), + ) +} diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index e56038a555970..67b69345ee966 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -16,14 +16,16 @@ //! Message lane pallet benchmarking. -use crate::{Call, Instance}; +use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance}; -use bp_message_lane::{LaneId, MessageData, MessageNonce}; +use bp_message_lane::{ + target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, +}; use frame_benchmarking::{account, benchmarks_instance}; -use frame_support::traits::Get; +use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; use num_traits::Zero; -use sp_std::prelude::*; +use sp_std::{convert::TryInto, ops::RangeInclusive, prelude::*}; /// Message crafted with this size factor should be the largest possible message. pub const WORST_MESSAGE_SIZE_FACTOR: u32 = 1000; @@ -43,27 +45,52 @@ pub struct MessageParams { pub sender_account: ThisAccountId, } +/// Benchmark-specific message proof parameters. +pub struct MessageProofParams { + /// Id of the lane. + pub lane: LaneId, + /// Range of messages to include in the proof. + pub message_nonces: RangeInclusive, + /// If `Some`, the proof needs to include this outbound lane data. + pub outbound_lane_data: Option, +} + /// Trait that must be implemented by runtime. pub trait Config: crate::Config { + /// Return id of relayer account at the bridged chain. + fn bridged_relayer_id() -> Self::InboundRelayer; /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); /// Prepare message to send over lane. - fn prepare_message(params: MessageParams) -> (Self::OutboundPayload, Self::OutboundMessageFee); + fn prepare_outbound_message( + params: MessageParams, + ) -> (Self::OutboundPayload, Self::OutboundMessageFee); + /// Prepare messages proof to receive by the module. + fn prepare_message_proof( + params: MessageProofParams, + ) -> ( + >::MessagesProof, + Weight, + ); } benchmarks_instance! { _ { } + // + // Benchmarks that are used directly by the runtime. + // + // Benchmark `send_message` extrinsic with the worst possible conditions: // * outbound lane already has state, so it needs to be read and decoded; // * relayers fund account does not exists (in practice it needs to exist in production environment); // * maximal number of messages is being pruned during the call; // * message size is maximal for the target chain. + // + // Results of this benchmark may be directly used in the `send_message`. send_message_worst_case { - let i in 1..100; - let lane_id = bench_lane_id(); - let sender = account("sender", i, SEED); + let sender = account("sender", 0, SEED); T::endow_account(&sender); // 'send' messages that are to be pruned when our message is sent @@ -72,11 +99,181 @@ benchmarks_instance! { } confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - let (payload, fee) = T::prepare_message(MessageParams { + let (payload, fee) = T::prepare_outbound_message(MessageParams { size_factor: WORST_MESSAGE_SIZE_FACTOR, sender_account: sender.clone(), }); }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) + verify { + assert_eq!( + crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + T::MaxMessagesToPruneAtOnce::get() + 1, + ); + } + + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // This is base benchmark for all other message delivery benchmarks. + receive_single_message_proof { + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 1..=1, + outbound_lane_data: None, + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 1, + ); + } + + // Benchmark `receive_messages_proof` extrinsic with two minimal-weight messages and following conditions: + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // The weight of single message delivery could be approximated as + // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. + // This won't be super-accurate if message has non-zero dispatch weight, but estimation should + // be close enough to real weight. + receive_two_messages_proof { + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 1..=2, + outbound_lane_data: None, + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 2, + ); + } + + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * proof includes outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // The weight of outbound lane state delivery would be + // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. + // This won't be super-accurate if message has non-zero dispatch weight, but estimation should + // be close enough to real weight. + receive_single_message_proof_with_outbound_lane_state { + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 21, + latest_received_nonce: 20, + latest_generated_nonce: 21, + }), + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 21, + ); + assert_eq!( + crate::Module::::inbound_latest_confirmed_nonce(bench_lane_id()), + 20, + ); + } + + // + // Benchmarks for manual checks. + // + + // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // This benchmarks gives us an approximation of single message delivery weight. It is similar to the + // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. So it may be used + // to verify that the other approximation is correct. + receive_multiple_messages_proof { + let i in 1..T::MaxMessagesInDeliveryTransaction::get() + .try_into() + .expect("Value of MaxMessagesInDeliveryTransaction is too large"); + + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 1..=i as _, + outbound_lane_data: None, + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + i as MessageNonce, + ); + } + + // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: + // * proof includes outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // This benchmarks gives us an approximation of outbound lane state delivery weight. It is similar to the + // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. + // So it may be used to verify that the other approximation is correct. + receive_multiple_messages_proof_with_outbound_lane_state { + let i in 1..T::MaxMessagesInDeliveryTransaction::get() + .try_into() + .expect("Value of MaxMessagesInDeliveryTransaction is too large"); + + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 21..=20 + i as MessageNonce, + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 21, + latest_received_nonce: 20, + latest_generated_nonce: 21, + }), + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 20 + i as MessageNonce, + ); + assert_eq!( + crate::Module::::inbound_latest_confirmed_nonce(bench_lane_id()), + 20, + ); + } } fn bench_lane_id() -> LaneId { @@ -84,7 +281,7 @@ fn bench_lane_id() -> LaneId { } fn send_regular_message, I: Instance>() { - let mut outbound_lane = crate::outbound_lane::(bench_lane_id()); + let mut outbound_lane = outbound_lane::(bench_lane_id()); outbound_lane.send_message(MessageData { payload: vec![], fee: Zero::zero(), @@ -92,6 +289,15 @@ fn send_regular_message, I: Instance>() { } fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { - let mut outbound_lane = crate::outbound_lane::(bench_lane_id()); + let mut outbound_lane = outbound_lane::(bench_lane_id()); assert!(outbound_lane.confirm_delivery(nonce).is_some()); } + +fn receive_messages, I: Instance>(nonce: MessageNonce) { + let mut inbound_lane_storage = inbound_lane_storage::(bench_lane_id()); + inbound_lane_storage.set_data(InboundLaneData { + relayers: vec![(1, nonce, T::bridged_relayer_id())].into_iter().collect(), + latest_received_nonce: nonce, + latest_confirmed_nonce: 0, + }); +} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 77bfc72f2caaf..60cd2ce584a8d 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -558,11 +558,16 @@ fn ensure_operational, I: Instance>() -> Result<(), Error> { /// Creates new inbound lane object, backed by runtime storage. fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { - InboundLane::new(RuntimeInboundLaneStorage { + InboundLane::new(inbound_lane_storage::(lane_id)) +} + +/// Creates new runtime inbound lane storage. +fn inbound_lane_storage, I: Instance>(lane_id: LaneId) -> RuntimeInboundLaneStorage { + RuntimeInboundLaneStorage { lane_id, cached_data: RefCell::new(None), _phantom: Default::default(), - }) + } } /// Creates new outbound lane object, backed by runtime storage. diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 03da6a16526f8..44022d6779b07 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -47,3 +47,4 @@ std = [ "sp-std/std", "sp-trie/std", ] +runtime-benchmarks = [] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index aa01c32964759..fa957c384fb05 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -370,6 +370,18 @@ fn ensure_operational() -> Result<(), Error> { } } +/// (Re)initialize bridge with given header for using it in external benchmarks. +#[cfg(feature = "runtime-benchmarks")] +pub fn initialize_for_benchmarks(header: HeaderOf) { + initialize_bridge::(InitializationData { + header, + authority_list: Vec::new(), // we don't verify any proofs in external benchmarks + set_id: 0, + scheduled_change: None, + is_halted: false, + }); +} + /// Since this writes to storage with no real checks this should only be used in functions that were /// called by a trusted origin. fn initialize_bridge(init_params: InitializationData>) { From 734330b124dfd14403fa5c196efb1f061b327852 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 17 Dec 2020 12:47:45 +0300 Subject: [PATCH 0266/1210] Add messages count parameter to delivery transaction (#581) * add messages count parameter to delivery transaction * fix benchmarks compilation --- bin/millau/runtime/src/lib.rs | 3 -- bin/millau/runtime/src/rialto_messages.rs | 4 +- bin/rialto/runtime/src/lib.rs | 3 -- bin/rialto/runtime/src/millau_messages.rs | 4 +- bin/runtime-common/src/messages.rs | 42 ++++++++++++------- modules/message-lane/src/benchmarking.rs | 34 +++++++++------ modules/message-lane/src/lib.rs | 27 ++++++------ modules/message-lane/src/mock.rs | 4 +- primitives/message-lane/src/target_chain.rs | 4 +- primitives/millau/src/lib.rs | 4 -- primitives/rialto/src/lib.rs | 4 -- .../src/millau_messages_to_rialto.rs | 17 ++++++-- .../src/rialto_messages_to_millau.rs | 17 ++++++-- 13 files changed, 96 insertions(+), 71 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index fcf443e9370f4..8dc9fea6283a4 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -313,8 +313,6 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; - pub const MaxMessagesInDeliveryTransaction: bp_message_lane::MessageNonce = - bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION; } impl pallet_message_lane::Config for Runtime { @@ -322,7 +320,6 @@ impl pallet_message_lane::Config for Runtime { type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; type OutboundPayload = crate::rialto_messages::ToRialtoMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index a2fba5faf270a..b5e1cc0fdb07c 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -192,8 +192,8 @@ impl SourceHeaderChain for Rialto { fn verify_messages_proof( proof: Self::MessagesProof, - max_messages: MessageNonce, + messages_count: MessageNonce, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::(proof, max_messages) + messages::target::verify_messages_proof::(proof, messages_count) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 89d84f2e72bc6..52cd0896e9f69 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -420,8 +420,6 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; - pub const MaxMessagesInDeliveryTransaction: bp_message_lane::MessageNonce = - bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION; } pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInstance; @@ -430,7 +428,6 @@ impl pallet_message_lane::Config for Runtime { type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index e1395d99b1e51..6fead2b451065 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -192,8 +192,8 @@ impl SourceHeaderChain for Millau { fn verify_messages_proof( proof: Self::MessagesProof, - max_messages: MessageNonce, + messages_count: MessageNonce, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::(proof, max_messages) + messages::target::verify_messages_proof::(proof, messages_count) } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 029707a017ebb..6715295dd6048 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -399,7 +399,7 @@ pub mod target { /// Verify proof of Bridged -> This chain messages. pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof, - max_messages: MessageNonce, + messages_count: MessageNonce, ) -> Result>>>, &'static str> where ThisRuntime: pallet_substrate_bridge::Config, @@ -409,7 +409,7 @@ pub mod target { { verify_messages_proof_with_parser::( proof, - max_messages, + messages_count, |bridged_header_hash, bridged_storage_proof| { pallet_substrate_bridge::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), @@ -429,7 +429,7 @@ pub mod target { #[derive(Debug, PartialEq)] pub(crate) enum MessageProofError { Empty, - TooManyMessages, + MessagesCountMismatch, MissingRequiredMessage, FailedToDecodeMessage, FailedToDecodeOutboundLaneState, @@ -440,7 +440,7 @@ pub mod target { fn from(err: MessageProofError) -> &'static str { match err { MessageProofError::Empty => "Messages proof is empty", - MessageProofError::TooManyMessages => "Too many messages in the proof", + MessageProofError::MessagesCountMismatch => "Declared messages count doesn't match actual value", MessageProofError::MissingRequiredMessage => "Message is missing from the proof", MessageProofError::FailedToDecodeMessage => "Failed to decode message from the proof", MessageProofError::FailedToDecodeOutboundLaneState => { @@ -488,7 +488,7 @@ pub mod target { /// Verify proof of Bridged -> This chain messages using given message proof parser. pub(crate) fn verify_messages_proof_with_parser( proof: FromBridgedChainMessagesProof, - max_messages: MessageNonce, + messages_count: MessageNonce, build_parser: BuildParser, ) -> Result>>>, MessageProofError> where @@ -500,8 +500,8 @@ pub mod target { // receiving proofs where end < begin is ok (if proof includes outbound lane state) // => hence unwrap_or(0) let messages_in_the_proof = end.checked_sub(begin).and_then(|diff| diff.checked_add(1)).unwrap_or(0); - if messages_in_the_proof > max_messages { - return Err(MessageProofError::TooManyMessages); + if messages_in_the_proof != messages_count { + return Err(MessageProofError::MessagesCountMismatch); } let parser = build_parser(bridged_header_hash, bridged_storage_proof)?; @@ -1009,14 +1009,26 @@ mod tests { } #[test] - fn messages_proof_is_rejected_if_there_are_too_many_messages() { + fn messages_proof_is_rejected_if_declared_less_than_actual_number_of_messages() { assert_eq!( target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 11), - 10, + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + 5, |_, _| unreachable!(), ), - Err(target::MessageProofError::TooManyMessages), + Err(target::MessageProofError::MessagesCountMismatch), + ); + } + + #[test] + fn messages_proof_is_rejected_if_declared_more_than_actual_number_of_messages() { + assert_eq!( + target::verify_messages_proof_with_parser::( + (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + 15, + |_, _| unreachable!(), + ), + Err(target::MessageProofError::MessagesCountMismatch), ); } @@ -1069,7 +1081,7 @@ mod tests { assert_eq!( target::verify_messages_proof_with_parser::( (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), - 10, + 0, |_, _| Ok(TestMessageProofParser { failing: true, messages: no_messages_range(), @@ -1089,7 +1101,7 @@ mod tests { assert_eq!( target::verify_messages_proof_with_parser::( (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), - 10, + 0, |_, _| Ok(TestMessageProofParser { failing: false, messages: no_messages_range(), @@ -1105,7 +1117,7 @@ mod tests { assert_eq!( target::verify_messages_proof_with_parser::( (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), - 10, + 0, |_, _| Ok(TestMessageProofParser { failing: false, messages: no_messages_range(), @@ -1137,7 +1149,7 @@ mod tests { assert_eq!( target::verify_messages_proof_with_parser::( (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 1), - 10, + 1, |_, _| Ok(TestMessageProofParser { failing: false, messages: 1..=1, diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index 67b69345ee966..e0d20a6558977 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -25,7 +25,7 @@ use frame_benchmarking::{account, benchmarks_instance}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; use num_traits::Zero; -use sp_std::{convert::TryInto, ops::RangeInclusive, prelude::*}; +use sp_std::{ops::RangeInclusive, prelude::*}; /// Message crafted with this size factor should be the largest possible message. pub const WORST_MESSAGE_SIZE_FACTOR: u32 = 1000; @@ -127,7 +127,7 @@ benchmarks_instance! { message_nonces: 1..=1, outbound_lane_data: None, }); - }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), @@ -154,7 +154,7 @@ benchmarks_instance! { message_nonces: 1..=2, outbound_lane_data: None, }); - }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), @@ -188,7 +188,7 @@ benchmarks_instance! { latest_generated_nonce: 21, }), }); - }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), @@ -214,19 +214,24 @@ benchmarks_instance! { // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. So it may be used // to verify that the other approximation is correct. receive_multiple_messages_proof { - let i in 1..T::MaxMessagesInDeliveryTransaction::get() - .try_into() - .expect("Value of MaxMessagesInDeliveryTransaction is too large"); + let i in 1..128; let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + let messages_count = i as _; let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { lane: bench_lane_id(), message_nonces: 1..=i as _, outbound_lane_data: None, }); - }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + }: receive_messages_proof( + RawOrigin::Signed(relayer_id_on_target), + relayer_id_on_source, + proof, + messages_count, + dispatch_weight + ) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), @@ -244,12 +249,11 @@ benchmarks_instance! { // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. // So it may be used to verify that the other approximation is correct. receive_multiple_messages_proof_with_outbound_lane_state { - let i in 1..T::MaxMessagesInDeliveryTransaction::get() - .try_into() - .expect("Value of MaxMessagesInDeliveryTransaction is too large"); + let i in 1..128; let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + let messages_count = i as _; // mark messages 1..=20 as delivered receive_messages::(20); @@ -263,7 +267,13 @@ benchmarks_instance! { latest_generated_nonce: 21, }), }); - }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, dispatch_weight) + }: receive_messages_proof( + RawOrigin::Signed(relayer_id_on_target), + relayer_id_on_source, + proof, + messages_count, + dispatch_weight + ) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 60cd2ce584a8d..2b6dcb6bda0a4 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -93,11 +93,6 @@ pub trait Config: frame_system::Config { /// This constant limits difference between last message from last entry of the /// `InboundLaneData::relayers` and first message at the first entry. type MaxUnconfirmedMessagesAtInboundLane: Get; - /// Maximal number of messages in single delivery transaction. This directly affects the base - /// weight of the delivery transaction. - /// - /// All transactions that deliver more messages than this number, are rejected. - type MaxMessagesInDeliveryTransaction: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter; @@ -322,17 +317,16 @@ decl_module! { } /// Receive messages proof from bridged chain. - #[weight = DELIVERY_OVERHEAD_WEIGHT - .saturating_add( - T::MaxMessagesInDeliveryTransaction::get() - .saturating_mul(SINGLE_MESSAGE_DELIVERY_WEIGHT) - ) + #[weight = messages_count + .saturating_mul(SINGLE_MESSAGE_DELIVERY_WEIGHT) + .saturating_add(DELIVERY_OVERHEAD_WEIGHT) .saturating_add(*dispatch_weight) ] pub fn receive_messages_proof( origin, relayer_id: T::InboundRelayer, proof: MessagesProofOf, + messages_count: MessageNonce, dispatch_weight: Weight, ) -> DispatchResult { ensure_operational::()?; @@ -343,7 +337,7 @@ decl_module! { T::SourceHeaderChain, T::InboundMessageFee, T::InboundPayload, - >(proof, T::MaxMessagesInDeliveryTransaction::get()) + >(proof, messages_count) .map_err(|err| { frame_support::debug::trace!( "Rejecting invalid messages proof: {:?}", @@ -674,9 +668,9 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStora /// Verify messages proof and return proved messages with decoded payload. fn verify_and_decode_messages_proof, Fee, DispatchPayload: Decode>( proof: Chain::MessagesProof, - max_messages: MessageNonce, + messages_count: MessageNonce, ) -> Result>, Chain::Error> { - Chain::verify_messages_proof(proof, max_messages).map(|messages_by_lane| { + Chain::verify_messages_proof(proof, messages_count).map(|messages_by_lane| { messages_by_lane .into_iter() .map(|(lane, lane_data)| { @@ -846,6 +840,7 @@ mod tests { Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(2, REGULAR_PAYLOAD)]).into(), + 1, REGULAR_PAYLOAD.1, ), Error::::Halted, @@ -924,6 +919,7 @@ mod tests { Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + 1, REGULAR_PAYLOAD.1, )); @@ -964,6 +960,7 @@ mod tests { Origin::signed(1), TEST_RELAYER_A, message_proof, + 1, REGULAR_PAYLOAD.1, )); @@ -995,6 +992,7 @@ mod tests { Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + 1, REGULAR_PAYLOAD.1 - 1, ), Error::::InvalidMessagesDispatchWeight, @@ -1010,6 +1008,7 @@ mod tests { Origin::signed(1), TEST_RELAYER_A, Err(()).into(), + 1, 0, ), Error::::InvalidMessagesProof, @@ -1112,6 +1111,7 @@ mod tests { Origin::signed(1), TEST_RELAYER_A, Ok(vec![invalid_message]).into(), + 1, 0, // weight may be zero in this case (all messages are improperly encoded) ),); @@ -1134,6 +1134,7 @@ mod tests { message(3, REGULAR_PAYLOAD), ]) .into(), + 3, REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1, ),); diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 2c3418b98f44e..8250b955be2db 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -97,7 +97,6 @@ parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; - pub const MaxMessagesInDeliveryTransaction: u64 = 128; } impl Config for TestRuntime { @@ -105,7 +104,6 @@ impl Config for TestRuntime { type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - type MaxMessagesInDeliveryTransaction = MaxMessagesInDeliveryTransaction; type OutboundPayload = TestPayload; type OutboundMessageFee = TestMessageFee; @@ -279,7 +277,7 @@ impl SourceHeaderChain for TestSourceHeaderChain { fn verify_messages_proof( proof: Self::MessagesProof, - _max_messages: MessageNonce, + _messages_count: MessageNonce, ) -> Result>, Self::Error> { proof .result diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index 6e64c423d1da0..04eab55affd87 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -68,13 +68,13 @@ pub trait SourceHeaderChain { /// Verify messages proof and return proved messages. /// /// Returns error if either proof is incorrect, or the number of messages in the proof - /// is larger than `max_messages`. + /// is not matching the `messages_count`. /// /// Messages vector is required to be sorted by nonce within each lane. Out-of-order /// messages will be rejected. fn verify_messages_proof( proof: Self::MessagesProof, - max_messages: MessageNonce, + messages_count: MessageNonce, ) -> Result>, Self::Error>; } diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 8642b04cf0d43..c9e90501ffdf1 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -84,10 +84,6 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 -/// Maximal number of messages in single delivery transaction. -pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 1024; - /// Maximal number of unrewarded relayer entries at inbound lane. pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 71f0329afc37d..fffa556f72bfa 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -45,10 +45,6 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 -/// Maximal number of messages in single delivery transaction. -pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; - /// Maximal number of unrewarded relayer entries at inbound lane. pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 268a20beb76ef..ebbb6a2bd55d8 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -73,11 +73,14 @@ impl SubstrateMessageLane for MillauMessagesToRialto { proof: ::MessagesProof, ) -> Result { let (dispatch_weight, proof) = proof; + let (_, _, _, ref nonces_begin, ref nonces_end) = proof; + let messages_count = nonces_end - nonces_begin + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; let call = rialto_runtime::MessageLaneCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, + messages_count, dispatch_weight, ) .into(); @@ -119,6 +122,14 @@ pub fn run( lane.relayer_id_at_source, ); + // TODO: these two parameters need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 + // the rough idea is to reserve some portion (1/3?) of max extrinsic weight for delivery tx overhead + messages + // overhead + // this must be tuned mostly with `max_messages_in_single_batch`, but `max_messages_weight_in_single_batch` also + // needs to be updated (subtract tx overhead) + let max_messages_in_single_batch = 1024; + let max_messages_weight_in_single_batch = bp_rialto::max_extrinsic_weight(); + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -129,10 +140,8 @@ pub fn run( delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unrewarded_relayer_entries_at_target: bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch: bp_rialto::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, - // TODO: subtract base weight of delivery from this when it'll be known - // https://github.com/paritytech/parity-bridges-common/issues/78 - max_messages_weight_in_single_batch: bp_rialto::max_extrinsic_weight(), + max_messages_in_single_batch, + max_messages_weight_in_single_batch, // 2/3 is reserved for proofs and tx overhead max_messages_size_in_single_batch: bp_rialto::max_extrinsic_size() as usize / 3, }, diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 0615810612b70..0e059f7cfd295 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -73,11 +73,14 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { proof: ::MessagesProof, ) -> Result { let (dispatch_weight, proof) = proof; + let (_, _, _, ref nonces_begin, ref nonces_end) = proof; + let messages_count = nonces_end - nonces_begin + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; let call = millau_runtime::MessageLaneCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, + messages_count, dispatch_weight, ) .into(); @@ -119,6 +122,14 @@ pub fn run( lane.relayer_id_at_source, ); + // TODO: these two parameters need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 + // the rough idea is to reserve some portion (1/3?) of max extrinsic weight for delivery tx overhead + messages + // overhead + // this must be tuned mostly with `max_messages_in_single_batch`, but `max_messages_weight_in_single_batch` also + // needs to be updated (subtract tx overhead) + let max_messages_in_single_batch = 1024; + let max_messages_weight_in_single_batch = bp_rialto::max_extrinsic_weight(); + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -129,10 +140,8 @@ pub fn run( delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unrewarded_relayer_entries_at_target: bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch: bp_millau::MAX_MESSAGES_IN_DELIVERY_TRANSACTION, - // TODO: subtract base weight of delivery from this when it'll be known - // https://github.com/paritytech/parity-bridges-common/issues/78 - max_messages_weight_in_single_batch: bp_millau::max_extrinsic_weight(), + max_messages_in_single_batch, + max_messages_weight_in_single_batch, // 2/3 is reserved for proofs and tx overhead max_messages_size_in_single_batch: bp_millau::max_extrinsic_size() as usize / 3, }, From 84cbec739cf5714a21ed7ce36fa0890ef4d2a291 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 17 Dec 2020 14:33:56 -0500 Subject: [PATCH 0267/1210] Add correct Docker commands in README (#580) * Add correct Docker commands in README * Split long line --- README.md | 71 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index da98270b65951..7157600e3fd82 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ There are 3 ways to run the bridge, described below: - building or using Docker images for each individual component, - running a Docker Compose setup (recommended). -### Building +### Using the Source First you'll need to build the bridge nodes and relay. This can be done as follows: @@ -115,41 +115,76 @@ cargo build -p substrate-relay ### Running To run a simple dev network you'll can use the scripts located in -[the `scripts` folder](./scripts). Since the relay connects to both Substrate chains it must be run -last. +[the `deployments/local-scripts` folder](./deployments/local-scripts). Since the relayer connects to +both Substrate chains it must be run last. ```bash # In `parity-bridges-common` folder ./deployments/local-scripts/run-rialto-bridge-node.sh ./deployments/local-scripts/run-millau-bridge-node.sh ./deployments/local-scripts/run-millau-to-rialto-relay.sh -./deployments/local-scripts/run-rialto-to-millau-relay.sh ``` -At this point you should see the relayer submitting blocks from the Millau Substrate chain to the -Rialto Substrate chain and vice-versa. +At this point you should see the relayer submitting headers from the Millau Substrate chain to the +Rialto Substrate chain. -### Local Docker Build -If you want to make a Docker container using your local source files you can run the following -command at the top level of the repository: +### Local Docker Setup -```bash -docker build . -t local/rialto-bridge-node --build-arg PROJECT=rialto-bridge-node -docker build . -t local/millau-bridge-node --build-arg PROJECT=millau-bridge-node -docker build . -t local/substrate-relay --build-arg PROJECT=substrate-relay -``` +To get up and running quickly you can use published Docker images for the bridge nodes and relayer. +The images are published on [Docker Hub](https://hub.docker.com/u/paritytech). -You can then run the network as follows: +To run the dev network we first run the two bridge nodes: ```bash -docker run -it local/rialto-bridge-node --dev --tmp -docker run -it local/millau-bridge-node --dev --tmp -docker run -it local/substrate-relay +docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ + -it paritytech/rialto-bridge-node --dev --tmp \ + --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external + +docker run -p 30334:30333 -p 9934:9933 -p 9945:9944 \ + -it paritytech/millau-bridge-node --dev --tmp \ + --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external ``` Notice that the `docker run` command will accept all the normal Substrate flags. For local development you should at minimum run with the `--dev` flag or else no blocks will be produced. +Then we need to initialize and run the relayer: + +```bash +docker run --network=host -it \ + paritytech/substrate-relay initialize-rialto-headers-bridge-in-millau \ + --millau-host localhost \ + --millau-port 9945 \ + --rialto-host localhost \ + --rialto-port 9944 \ + --millau-signer //Alice + +docker run --network=host -it \ + paritytech/substrate-relay rialto-headers-to-millau \ + --millau-host localhost \ + --millau-port 9945 \ + --rialto-host localhost \ + --rialto-port 9944 \ + --millau-signer //Bob \ +``` + +You should now see the relayer submitting headers from the Millau chain to the Rialto chain. + +If you don't want to use the published Docker images you can build images yourself. You can do this +by running the following commands at the top level of the repository. + +```bash +# In `parity-bridges-common` folder +docker build . -t local/rialto-bridge-node --build-arg PROJECT=rialto-bridge-node +docker build . -t local/millau-bridge-node --build-arg PROJECT=millau-bridge-node +docker build . -t local/substrate-relay --build-arg PROJECT=substrate-relay +``` + +_Note: Building the node images will take a long time, so make sure you have some coffee handy._ + +Once you have the images built you can use them in the previous commands by replacing +`paritytech/` with `local/` everywhere. + ### Full Network Docker Compose Setup For a more sophisticated deployment which includes bidirectional header sync, message passing, From 5044a5f4de2162121ca8cfd5d1f32b41b79268df Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 17 Dec 2020 22:48:21 +0300 Subject: [PATCH 0268/1210] Fix grandpa initialization (#583) * fix grandpa initialization * fnt --- bin/millau/node/src/service.rs | 14 ++++++++++++-- bin/rialto/node/src/service.rs | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index a9d866af73a37..9cbd2b06a9b45 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -119,7 +119,7 @@ pub fn new_partial( } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { +pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { client, backend, @@ -132,6 +132,11 @@ pub fn new_full(config: Configuration) -> Result { other: (block_import, grandpa_link), } = new_partial(&config)?; + config + .network + .notifications_protocols + .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -325,10 +330,15 @@ pub fn new_full(config: Configuration) -> Result { } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) -> Result { +pub fn new_light(mut config: Configuration) -> Result { let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; + config + .network + .notifications_protocols + .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + let select_chain = sc_consensus::LongestChain::new(backend.clone()); let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 57415b73447f6..c235a8e757f8d 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -119,7 +119,7 @@ pub fn new_partial( } /// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { +pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { client, backend, @@ -132,6 +132,11 @@ pub fn new_full(config: Configuration) -> Result { other: (block_import, grandpa_link), } = new_partial(&config)?; + config + .network + .notifications_protocols + .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -324,10 +329,15 @@ pub fn new_full(config: Configuration) -> Result { } /// Builds a new service for a light client. -pub fn new_light(config: Configuration) -> Result { +pub fn new_light(mut config: Configuration) -> Result { let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; + config + .network + .notifications_protocols + .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + let select_chain = sc_consensus::LongestChain::new(backend.clone()); let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( From c6891ba2c2ff065ddb0c675bec2a95293ae1cdac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 18 Dec 2020 13:59:59 +0300 Subject: [PATCH 0269/1210] Benchmark for message delivery confirmation transaction (#570) * receive_delivery_proof benchmarks * fix compilation * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/rialto/runtime/src/lib.rs | 33 +++ bin/rialto/runtime/src/millau_messages.rs | 5 +- bin/runtime-common/src/messages.rs | 2 +- .../src/messages_benchmarking.rs | 51 ++++- modules/message-lane/src/benchmarking.rs | 213 +++++++++++++++++- modules/message-lane/src/lib.rs | 19 +- 6 files changed, 308 insertions(+), 15 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 52cd0896e9f69..31c08aba223bd 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -802,6 +802,7 @@ impl_runtime_apis! { use pallet_message_lane::benchmarking::{ Module as MessageLaneBench, Config as MessageLaneConfig, + MessageDeliveryProofParams as MessageLaneMessageDeliveryProofParams, MessageParams as MessageLaneMessageParams, MessageProofParams as MessageLaneMessageProofParams, }; @@ -811,6 +812,10 @@ impl_runtime_apis! { Default::default() } + fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { + pallet_balances::Module::::free_balance(account) + } + fn endow_account(account: &Self::AccountId) { pallet_balances::Module::::make_free_balance_be( account, @@ -913,6 +918,34 @@ impl_runtime_apis! { }.encode(), ) } + + fn prepare_message_delivery_proof( + params: MessageLaneMessageDeliveryProofParams, + ) -> millau_messages::FromMillauMessagesDeliveryProof { + use crate::millau_messages::{Millau, WithMillauMessageBridge}; + use bridge_runtime_common::{ + messages::ChainWithMessageLanes, + messages_benchmarking::prepare_message_delivery_proof, + }; + use sp_runtime::traits::Header; + + prepare_message_delivery_proof::( + params, + |lane_id| pallet_message_lane::storage_keys::inbound_lane_data_key::< + Runtime, + ::MessageLaneInstance, + >( + &lane_id, + ).0, + |state_root| bp_millau::Header::new( + 0, + Default::default(), + state_root, + Default::default(), + Default::default(), + ), + ) + } } add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeKovan); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 6fead2b451065..33d254e9b5e40 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -74,7 +74,8 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Rialto -> Millau messages. -type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; +pub type FromMillauMessagesDeliveryProof = + messages::source::FromBridgedChainMessagesDeliveryProof; /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] @@ -168,7 +169,7 @@ impl TargetHeaderChain for Millau // - hash of the header this proof has been created with; // - the storage proof of one or several keys; // - id of the lane we prove state of. - type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; + type MessagesDeliveryProof = FromMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { messages::source::verify_chain_message::(payload) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 6715295dd6048..30c6a1f7d1c2e 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -90,7 +90,7 @@ pub trait ChainWithMessageLanes { /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. - type AccountId: Decode; + type AccountId: Encode + Decode; /// Public key of the chain account that may be used to verify signatures. type Signer: Decode; /// Signature type used on the chain. diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index e3dd705f8fc35..70cbb76f433ee 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -19,13 +19,16 @@ #![cfg(feature = "runtime-benchmarks")] -use crate::messages::{target::FromBridgedChainMessagesProof, BalanceOf, BridgedChain, HashOf, MessageBridge}; +use crate::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, AccountIdOf, BalanceOf, + BridgedChain, HashOf, MessageBridge, ThisChain, +}; use bp_message_lane::{LaneId, MessageData, MessageKey, MessagePayload}; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; use frame_support::weights::Weight; -use pallet_message_lane::benchmarking::MessageProofParams; +use pallet_message_lane::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; use sp_core::Hasher; use sp_runtime::traits::Header; use sp_std::prelude::*; @@ -142,3 +145,47 @@ where .expect("too many messages requested by benchmark"), ) } + +/// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. +pub fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams>>, + make_bridged_inbound_lane_data_key: ML, + make_bridged_header: MH, +) -> FromBridgedChainMessagesDeliveryProof +where + B: MessageBridge, + H: Hasher, + R: pallet_substrate_bridge::Config, + ::Hash: Into>>, + ML: Fn(LaneId) -> Vec, + MH: Fn(H::Out) -> ::Header, +{ + // prepare Bridged chain storage with inbound lane state + let storage_key = make_bridged_inbound_lane_data_key(params.lane); + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + } + + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::::new(); + read_trie_value_with::, _, _>(&mdb, &root, &storage_key, &mut proof_recorder) + .map_err(|_| "read_trie_value_with has failed") + .expect("read_trie_value_with should not fail in benchmarks"); + let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + // prepare Bridged chain header and insert it into the Substrate pallet + let bridged_header = make_bridged_header(root); + let bridged_header_hash = bridged_header.hash(); + pallet_substrate_bridge::initialize_for_benchmarks::(bridged_header); + + ( + bridged_header_hash.into(), + StorageProof::new(storage_proof), + params.lane, + ) +} diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index e0d20a6558977..f211f95c39ab9 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -16,19 +16,23 @@ //! Message lane pallet benchmarking. -use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance}; +use crate::{ + inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, relayer_fund_account_id, Call, Instance, +}; use bp_message_lane::{ - target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, + source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, + MessageNonce, OutboundLaneData, }; use frame_benchmarking::{account, benchmarks_instance}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; -use num_traits::Zero; -use sp_std::{ops::RangeInclusive, prelude::*}; +use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, ops::RangeInclusive, prelude::*}; /// Message crafted with this size factor should be the largest possible message. pub const WORST_MESSAGE_SIZE_FACTOR: u32 = 1000; +/// Fee paid by submitter for single message delivery. +const MESSAGE_FEE: u32 = 1_000_000; const SEED: u32 = 0; @@ -55,10 +59,20 @@ pub struct MessageProofParams { pub outbound_lane_data: Option, } +/// Benchmark-specific message delivery proof parameters. +pub struct MessageDeliveryProofParams { + /// Id of the lane. + pub lane: LaneId, + /// The proof needs to include this inbound lane data. + pub inbound_lane_data: InboundLaneData, +} + /// Trait that must be implemented by runtime. pub trait Config: crate::Config { /// Return id of relayer account at the bridged chain. fn bridged_relayer_id() -> Self::InboundRelayer; + /// Return balance of given account. + fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee; /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); /// Prepare message to send over lane. @@ -72,6 +86,10 @@ pub trait Config: crate::Config { >::MessagesProof, Weight, ); + /// Prepare messages delivery proof to receive by the module. + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> >::MessagesDeliveryProof; } benchmarks_instance! { @@ -200,6 +218,111 @@ benchmarks_instance! { ); } + // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: + // * single relayer is rewarded for relaying single message; + // * relayer account does not exist (in practice it needs to exist in production environment). + // + // This is base benchmark for all other confirmations delivery benchmarks. + receive_delivery_proof_for_single_message { + let relayers_fund_id = relayer_fund_account_id::(); + let relayer_id: T::AccountId = account("relayer", 0, SEED); + let relayer_balance = T::account_balance(&relayer_id); + T::endow_account(&relayers_fund_id); + + // send message that we're going to confirm + send_regular_message::(); + + let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { + lane: bench_lane_id(), + inbound_lane_data: InboundLaneData { + relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(), + latest_received_nonce: 1, + latest_confirmed_nonce: 0, + } + }); + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof) + verify { + assert_eq!( + T::account_balance(&relayer_id), + relayer_balance + MESSAGE_FEE.into(), + ); + } + + // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: + // * single relayer is rewarded for relaying two messages; + // * relayer account does not exist (in practice it needs to exist in production environment). + // + // Additional weight for paying single-message reward to the same relayer could be computed + // as `weight(receive_delivery_proof_for_two_messages_by_single_relayer) + // - weight(receive_delivery_proof_for_single_message)`. + receive_delivery_proof_for_two_messages_by_single_relayer { + let relayers_fund_id = relayer_fund_account_id::(); + let relayer_id: T::AccountId = account("relayer", 0, SEED); + let relayer_balance = T::account_balance(&relayer_id); + T::endow_account(&relayers_fund_id); + + // send message that we're going to confirm + send_regular_message::(); + send_regular_message::(); + + let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { + lane: bench_lane_id(), + inbound_lane_data: InboundLaneData { + relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(), + latest_received_nonce: 2, + latest_confirmed_nonce: 0, + } + }); + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof) + verify { + assert_eq!( + T::account_balance(&relayer_id), + relayer_balance + (MESSAGE_FEE * 2).into(), + ); + } + + // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: + // * two relayers are rewarded for relaying single message each; + // * relayer account does not exist (in practice it needs to exist in production environment). + // + // Additional weight for paying reward to the next relayer could be computed + // as `weight(receive_delivery_proof_for_two_messages_by_two_relayers) + // - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`. + receive_delivery_proof_for_two_messages_by_two_relayers { + let relayers_fund_id = relayer_fund_account_id::(); + let relayer1_id: T::AccountId = account("relayer1", 1, SEED); + let relayer1_balance = T::account_balance(&relayer1_id); + let relayer2_id: T::AccountId = account("relayer2", 2, SEED); + let relayer2_balance = T::account_balance(&relayer2_id); + T::endow_account(&relayers_fund_id); + + // send message that we're going to confirm + send_regular_message::(); + send_regular_message::(); + + let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { + lane: bench_lane_id(), + inbound_lane_data: InboundLaneData { + relayers: vec![ + (1, 1, relayer1_id.clone()), + (2, 2, relayer2_id.clone()), + ].into_iter().collect(), + latest_received_nonce: 2, + latest_confirmed_nonce: 0, + } + }); + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof) + verify { + assert_eq!( + T::account_balance(&relayer1_id), + relayer1_balance + MESSAGE_FEE.into(), + ); + assert_eq!( + T::account_balance(&relayer2_id), + relayer2_balance + MESSAGE_FEE.into(), + ); + } + // // Benchmarks for manual checks. // @@ -284,6 +407,86 @@ benchmarks_instance! { 20, ); } + + // Benchmark `receive_messages_delivery_proof` extrinsic where single relayer delivers multiple messages. + receive_delivery_proof_for_multiple_messages_by_single_relayer { + // there actually should be used value of `MaxUnrewardedRelayerEntriesAtInboundLane` from the bridged + // chain, but we're more interested in additional weight/message than in max weight + let i in 1..T::MaxUnrewardedRelayerEntriesAtInboundLane::get() + .try_into() + .expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large"); + + let relayers_fund_id = relayer_fund_account_id::(); + let relayer_id: T::AccountId = account("relayer", 0, SEED); + let relayer_balance = T::account_balance(&relayer_id); + T::endow_account(&relayers_fund_id); + + // send messages that we're going to confirm + for _ in 1..=i { + send_regular_message::(); + } + + let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { + lane: bench_lane_id(), + inbound_lane_data: InboundLaneData { + relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(), + latest_received_nonce: i as MessageNonce, + latest_confirmed_nonce: 0, + } + }); + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof) + verify { + assert_eq!( + T::account_balance(&relayer_id), + relayer_balance + (MESSAGE_FEE * i).into(), + ); + } + + // Benchmark `receive_messages_delivery_proof` extrinsic where every relayer delivers single messages. + receive_delivery_proof_for_multiple_messages_by_multiple_relayers { + // there actually should be used value of `MaxUnconfirmedMessagesAtInboundLane` from the bridged + // chain, but we're more interested in additional weight/message than in max weight + let i in 1..T::MaxUnconfirmedMessagesAtInboundLane::get() + .try_into() + .expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large "); + + let relayers_fund_id = relayer_fund_account_id::(); + let confirmation_relayer_id = account("relayer", 0, SEED); + let relayers: BTreeMap = (1..=i) + .map(|j| { + let relayer_id = account("relayer", j + 1, SEED); + let relayer_balance = T::account_balance(&relayer_id); + (relayer_id, relayer_balance) + }) + .collect(); + T::endow_account(&relayers_fund_id); + + // send messages that we're going to confirm + for _ in 1..=i { + send_regular_message::(); + } + + let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { + lane: bench_lane_id(), + inbound_lane_data: InboundLaneData { + relayers: relayers + .keys() + .enumerate() + .map(|(j, relayer_id)| (j as MessageNonce + 1, j as MessageNonce + 1, relayer_id.clone())) + .collect(), + latest_received_nonce: i as MessageNonce, + latest_confirmed_nonce: 0, + } + }); + }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof) + verify { + for (relayer_id, prev_balance) in relayers { + assert_eq!( + T::account_balance(&relayer_id), + prev_balance + MESSAGE_FEE.into(), + ); + } + } } fn bench_lane_id() -> LaneId { @@ -294,7 +497,7 @@ fn send_regular_message, I: Instance>() { let mut outbound_lane = outbound_lane::(bench_lane_id()); outbound_lane.send_message(MessageData { payload: vec![], - fee: Zero::zero(), + fee: MESSAGE_FEE.into(), }); } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 2b6dcb6bda0a4..468df6867d6d0 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -45,7 +45,7 @@ use frame_support::{ Parameter, StorageMap, }; use frame_system::{ensure_signed, RawOrigin}; -use num_traits::Zero; +use num_traits::{SaturatingAdd, Zero}; use sp_runtime::{traits::BadOrigin, DispatchResult}; use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; @@ -92,12 +92,15 @@ pub trait Config: frame_system::Config { /// /// This constant limits difference between last message from last entry of the /// `InboundLaneData::relayers` and first message at the first entry. + /// + /// There is no point of making this parameter lesser than MaxUnrewardedRelayerEntriesAtInboundLane, + /// because then maximal number of relayer entries will be limited by maximal number of messages. type MaxUnconfirmedMessagesAtInboundLane: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter; /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Parameter + Zero; + type OutboundMessageFee: From + Parameter + SaturatingAdd + Zero; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; @@ -423,24 +426,30 @@ decl_module! { let received_range = lane.confirm_delivery(lane_data.latest_received_nonce); if let Some(received_range) = received_range { Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); - let relayer_fund_account = relayer_fund_account_id::(); // reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain + let relayer_fund_account = relayer_fund_account_id::(); for (nonce_low, nonce_high, relayer) in lane_data.relayers { let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0); let nonce_end = sp_std::cmp::min(nonce_high, received_range.1); + // loop won't proceed if current entry is ahead of received range (begin > end). + // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + let mut relayer_fee: T::OutboundMessageFee = Zero::zero(); for nonce in nonce_begin..nonce_end + 1 { let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce, }).expect("message was just confirmed; we never prune unconfirmed messages; qed"); + relayer_fee = relayer_fee.saturating_add(&message_data.fee); + } + if !relayer_fee.is_zero() { >::MessageDeliveryAndDispatchPayment::pay_relayer_reward( &confirmation_relayer, &relayer, - &message_data.fee, + &relayer_fee, &relayer_fund_account, ); } From bbb811e15887b06c967b2b098fc504bc8826ebdc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Dec 2020 19:00:35 +0300 Subject: [PATCH 0270/1210] Fix clippy warning (#591) * clippy * still clippy * clippy again --- modules/ethereum/src/verification.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index b762a280f5848..aac1d20067b71 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -232,7 +232,11 @@ fn contextual_checks( let parent_step = context.parent_header().step().ok_or(Error::MissingStep)?; // Ensure header is from the step after context. - if header_step == parent_step || (header.number >= config.validate_step_transition && header_step <= parent_step) { + if header_step == parent_step { + return Err(Error::DoubleVote); + } + #[allow(clippy::suspicious_operation_groupings)] + if header.number >= config.validate_step_transition && header_step < parent_step { return Err(Error::DoubleVote); } From 8b7c05b500fad3a2f47454d7555919ee30b09b76 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Dec 2020 23:16:29 +0300 Subject: [PATCH 0271/1210] Enable Wasmtime and Remove `secp256k1` (#593) Co-authored-by: Hernando Castano --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- relays/ethereum-client/Cargo.toml | 8 +++---- relays/ethereum-client/src/sign.rs | 22 +++++++++---------- relays/ethereum/Cargo.toml | 2 +- relays/ethereum/src/ethereum_client.rs | 3 ++- .../ethereum/src/ethereum_exchange_submit.rs | 12 +++++----- relays/ethereum/src/main.rs | 9 ++++---- 8 files changed, 29 insertions(+), 31 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 1696f73a48173..34044c2766305 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -26,7 +26,7 @@ pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index c5453468f7b13..c2620ab9e3cec 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -26,7 +26,7 @@ rialto-runtime = { path = "../runtime" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/ethereum-client/Cargo.toml b/relays/ethereum-client/Cargo.toml index 4923b8a111fbc..e1ae2a8446aac 100644 --- a/relays/ethereum-client/Cargo.toml +++ b/relays/ethereum-client/Cargo.toml @@ -6,12 +6,12 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "1.3.4" } -ethereum-tx-sign = "3.0" headers-relay = { path = "../headers-relay" } -hex = "0.4" +hex-literal = "0.3" jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } +libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" -parity-crypto = { version = "0.6", features = ["publickey"] } relay-utils = { path = "../utils" } -web3 = "0.13" +web3 = { version = "0.14", default-features = false } diff --git a/relays/ethereum-client/src/sign.rs b/relays/ethereum-client/src/sign.rs index f5b80a34e5a7b..462cb5dbd7d27 100644 --- a/relays/ethereum-client/src/sign.rs +++ b/relays/ethereum-client/src/sign.rs @@ -16,8 +16,9 @@ use crate::types::{Address, CallRequest, U256}; use crate::{Client, Result}; - -use parity_crypto::publickey::KeyPair; +use bp_eth_poa::signatures::{secret_to_address, SignTransaction}; +use hex_literal::hex; +use secp256k1::SecretKey; /// Ethereum signing params. #[derive(Clone, Debug)] @@ -25,7 +26,7 @@ pub struct SigningParams { /// Ethereum chain id. pub chain_id: u64, /// Ethereum transactions signer. - pub signer: KeyPair, + pub signer: SecretKey, /// Gas price we agree to pay. pub gas_price: U256, } @@ -37,10 +38,9 @@ impl Default for SigningParams { // account that has a lot of ether when we run instant seal engine // address: 0x00a329c0648769a73afac7f9381e08fb43dbea72 // secret: 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 - signer: KeyPair::from_secret_slice( - &hex::decode("4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7") - .expect("secret is hardcoded, thus valid; qed"), - ) + signer: SecretKey::parse(&hex!( + "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" + )) .expect("secret is hardcoded, thus valid; qed"), gas_price: 8_000_000_000u64.into(), // 8 Gwei } @@ -59,7 +59,7 @@ pub async fn sign_and_submit_transaction( let nonce = if let Some(n) = nonce { n } else { - let address: Address = params.signer.address().as_fixed_bytes().into(); + let address: Address = secret_to_address(¶ms.signer); client.account_nonce(address).await? }; @@ -70,15 +70,15 @@ pub async fn sign_and_submit_transaction( }; let gas = client.estimate_gas(call_request).await?; - let raw_transaction = ethereum_tx_sign::RawTransaction { + let raw_transaction = bp_eth_poa::UnsignedTransaction { nonce, to: contract_address, value: U256::zero(), gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, gas_price: params.gas_price, - data: encoded_call, + payload: encoded_call, } - .sign(¶ms.signer.secret().as_fixed_bytes().into(), ¶ms.chain_id); + .sign_by(¶ms.signer, Some(params.chain_id)); let _ = client.submit_transaction(raw_transaction).await?; Ok(()) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 2aff3d95ad99a..95f83453524f2 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -18,9 +18,9 @@ ethabi-derive = "12.0" futures = "0.3.8" hex = "0.4" hex-literal = "0.3" +libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" num-traits = "0.2" -parity-crypto = { version = "0.6", features = ["publickey"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.60" time = "0.2" diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/ethereum/src/ethereum_client.rs index 19d88199853b2..46c2c76feee08 100644 --- a/relays/ethereum/src/ethereum_client.rs +++ b/relays/ethereum/src/ethereum_client.rs @@ -18,6 +18,7 @@ use crate::rpc_errors::RpcError; use crate::substrate_sync_loop::QueuedRialtoHeader; use async_trait::async_trait; +use bp_eth_poa::signatures::secret_to_address; use codec::{Decode, Encode}; use ethabi::FunctionOutputDecoder; use headers_relay::sync_types::SubmittedHeaders; @@ -134,7 +135,7 @@ impl EthereumHighLevelRpc for EthereumClient { headers: Vec, ) -> SubmittedHeaders { // read nonce of signer - let address: Address = params.signer.address().as_fixed_bytes().into(); + let address: Address = secret_to_address(¶ms.signer); let nonce = match self.account_nonce(address).await { Ok(nonce) => nonce, Err(error) => { diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index 519fdba8cb99a..d2842b78a4a2e 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -17,7 +17,7 @@ //! Submitting Ethereum -> Substrate exchange transactions. use bp_eth_poa::{ - signatures::{SecretKey, SignTransaction}, + signatures::{secret_to_address, SignTransaction}, UnsignedTransaction, }; use relay_ethereum_client::{ @@ -56,7 +56,7 @@ pub fn run(params: EthereumExchangeSubmitParams) { let result: Result<_, String> = local_pool.run_until(async move { let eth_client = EthereumClient::new(eth_params); - let eth_signer_address = eth_sign.signer.address(); + let eth_signer_address = secret_to_address(ð_sign.signer); let sub_recipient_encoded = sub_recipient; let nonce = match eth_nonce { Some(eth_nonce) => eth_nonce, @@ -83,11 +83,9 @@ pub fn run(params: EthereumExchangeSubmitParams) { value: eth_amount, payload: sub_recipient_encoded.to_vec(), }; - let eth_tx_signed = eth_tx_unsigned.clone().sign_by( - &SecretKey::parse(eth_sign.signer.secret().as_fixed_bytes()) - .expect("key is accepted by secp256k1::KeyPair and thus is valid; qed"), - Some(eth_sign.chain_id), - ); + let eth_tx_signed = eth_tx_unsigned + .clone() + .sign_by(ð_sign.signer, Some(eth_sign.chain_id)); eth_client .submit_transaction(eth_tx_signed) .await diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index fd46847c6d9de..1dd5dd0442aa0 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -34,8 +34,8 @@ use ethereum_sync_loop::EthereumSyncParams; use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; use instances::{BridgeInstance, Kovan, RialtoPoA}; -use parity_crypto::publickey::{KeyPair, Secret}; use relay_utils::{initialize::initialize_relay, metrics::MetricsParams}; +use secp256k1::SecretKey; use sp_core::crypto::Pair; use substrate_sync_loop::SubstrateSyncParams; @@ -134,10 +134,9 @@ fn ethereum_connection_params(matches: &clap::ArgMatches) -> Result Result { let mut params = EthereumSigningParams::default(); if let Some(eth_signer) = matches.value_of("eth-signer") { - params.signer = eth_signer - .parse::() - .map_err(|e| format!("Failed to parse eth-signer: {}", e)) - .and_then(|secret| KeyPair::from_secret(secret).map_err(|e| format!("Invalid eth-signer: {}", e)))?; + params.signer = + SecretKey::parse_slice(&hex::decode(eth_signer).map_err(|e| format!("Failed to parse eth-signer: {}", e))?) + .map_err(|e| format!("Invalid eth-signer: {}", e))?; } if let Some(eth_chain_id) = matches.value_of("eth-chain-id") { params.chain_id = eth_chain_id From 520ac1936b20c6a0779dc7358519f8f023ebaf54 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Dec 2020 09:22:07 +0300 Subject: [PATCH 0272/1210] add relayers_state param to the receive_messages_delivery_proof (#584) --- modules/message-lane/src/lib.rs | 93 +++++++++++++++++-- primitives/message-lane/src/lib.rs | 14 ++- .../messages-relay/src/message_lane_loop.rs | 1 + .../src/message_race_delivery.rs | 1 + relays/substrate/src/messages_target.rs | 5 +- .../src/millau_messages_to_rialto.rs | 3 +- .../src/rialto_messages_to_millau.rs | 3 +- 7 files changed, 109 insertions(+), 11 deletions(-) diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 468df6867d6d0..267ad334398f2 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -35,11 +35,12 @@ use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, + total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, + OutboundLaneData, UnrewardedRelayersState, }; use codec::{Decode, Encode}; use frame_support::{ - decl_error, decl_event, decl_module, decl_storage, + decl_error, decl_event, decl_module, decl_storage, ensure, traits::Get, weights::{DispatchClass, Weight}, Parameter, StorageMap, @@ -156,6 +157,8 @@ decl_error! { InvalidMessagesDispatchWeight, /// Invalid messages delivery proof has been submitted. InvalidMessagesDeliveryProof, + /// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call. + InvalidUnrewardedRelayersState, } } @@ -408,7 +411,11 @@ decl_module! { /// Receive messages delivery proof from bridged chain. #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn receive_messages_delivery_proof(origin, proof: MessagesDeliveryProofOf) -> DispatchResult { + pub fn receive_messages_delivery_proof( + origin, + proof: MessagesDeliveryProofOf, + relayers_state: UnrewardedRelayersState, + ) -> DispatchResult { ensure_operational::()?; let confirmation_relayer = ensure_signed(origin)?; @@ -421,6 +428,14 @@ decl_module! { Error::::InvalidMessagesDeliveryProof })?; + // verify that the relayer has declared correct `lane_data::relayers` state + // (we only care about total number of entries and messages, because this affects call weight) + ensure!( + total_unrewarded_messages(&lane_data.relayers) == relayers_state.total_messages + && lane_data.relayers.len() as MessageNonce == relayers_state.unrewarded_relayer_entries, + Error::::InvalidUnrewardedRelayersState + ); + // mark messages as delivered let mut lane = outbound_lane::(lane_id); let received_range = lane.confirm_delivery(lane_data.latest_received_nonce); @@ -501,6 +516,7 @@ impl, I: Instance> Module { bp_message_lane::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0), + total_messages: total_unrewarded_messages(&relayers), } } } @@ -754,8 +770,9 @@ mod tests { InboundLaneData { latest_received_nonce: 1, ..Default::default() - } + }, )), + Default::default(), )); assert_eq!( @@ -863,8 +880,9 @@ mod tests { InboundLaneData { latest_received_nonce: 1, ..Default::default() - } + }, )), + Default::default(), ), Error::::Halted, ); @@ -955,6 +973,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, + total_messages: 2, }, ); @@ -988,6 +1007,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, + total_messages: 2, }, ); }); @@ -1065,6 +1085,11 @@ mod tests { ..Default::default() } )), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, )); assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, @@ -1088,6 +1113,11 @@ mod tests { ..Default::default() } )), + UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + total_messages: 2, + ..Default::default() + }, )); assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid( TEST_RELAYER_A, @@ -1104,12 +1134,63 @@ mod tests { fn receive_messages_delivery_proof_rejects_invalid_proof() { run_test(|| { assert_noop!( - Module::::receive_messages_delivery_proof(Origin::signed(1), Err(()),), + Module::::receive_messages_delivery_proof(Origin::signed(1), Err(()), Default::default(),), Error::::InvalidMessagesDeliveryProof, ); }); } + #[test] + fn receive_messages_delivery_proof_rejects_proof_if_declared_relayers_state_is_invalid() { + run_test(|| { + // when number of relayers entires is invalid + assert_noop!( + Module::::receive_messages_delivery_proof( + Origin::signed(1), + Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] + .into_iter() + .collect(), + latest_received_nonce: 2, + ..Default::default() + } + )), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 2, + ..Default::default() + }, + ), + Error::::InvalidUnrewardedRelayersState, + ); + + // when number of messages is invalid + assert_noop!( + Module::::receive_messages_delivery_proof( + Origin::signed(1), + Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] + .into_iter() + .collect(), + latest_received_nonce: 2, + ..Default::default() + } + )), + UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + total_messages: 1, + ..Default::default() + }, + ), + Error::::InvalidUnrewardedRelayersState, + ); + }); + } + #[test] fn receive_messages_accepts_single_message_with_invalid_payload() { run_test(|| { diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 86dea983d045e..4edf936bff3b8 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -103,13 +103,15 @@ impl Default for InboundLaneData { } /// Gist of `InboundLaneData::relayers` field used by runtime APIs. -#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] pub struct UnrewardedRelayersState { /// Number of entries in the `InboundLaneData::relayers` set. pub unrewarded_relayer_entries: MessageNonce, /// Number of messages in the oldest entry of `InboundLaneData::relayers`. This is the /// minimal number of reward proofs required to push out this entry from the set. pub messages_in_oldest_entry: MessageNonce, + /// Total number of messages in the relayers vector. + pub total_messages: MessageNonce, } /// Outbound lane data. @@ -134,3 +136,13 @@ impl Default for OutboundLaneData { } } } + +/// Returns total number of messages in the `InboundLaneData::relayers` vector. +pub fn total_unrewarded_messages( + relayers: &VecDeque<(MessageNonce, MessageNonce, RelayerId)>, +) -> MessageNonce { + match (relayers.front(), relayers.back()) { + (Some((begin, _, _)), Some((_, end, _))) => end.checked_sub(*begin).and_then(|d| d.checked_add(1)).unwrap_or(0), + _ => 0, + } +} diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index c34323ace58de..b60cbf35137e3 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -693,6 +693,7 @@ pub(crate) mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 0, messages_in_oldest_entry: 0, + total_messages: 0, }, )) } diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index f6933d9bd12e6..7724e9235da6f 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -497,6 +497,7 @@ mod tests { unrewarded_relayers: UnrewardedRelayersState { unrewarded_relayer_entries: 0, messages_in_oldest_entry: 0, + total_messages: 0, }, }, }), diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 6b745cc7a83d2..8a16ecdd6edc0 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -37,7 +37,7 @@ use sp_trie::StorageProof; use std::ops::RangeInclusive; /// Message receiving proof returned by the target Substrate node. -pub type SubstrateMessagesReceivingProof = (HashOf, StorageProof, LaneId); +pub type SubstrateMessagesReceivingProof = (UnrewardedRelayersState, (HashOf, StorageProof, LaneId)); /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { @@ -156,12 +156,13 @@ where &self, id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error> { + let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; let proof = self .client .prove_messages_delivery(self.instance, self.lane_id, id.1) .await?; let proof = (id.1, proof, self.lane_id); - Ok((id, proof)) + Ok((id, (relayers_state, proof))) } async fn submit_messages_proof( diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index ebbb6a2bd55d8..b5d1db888e96d 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -59,9 +59,10 @@ impl SubstrateMessageLane for MillauMessagesToRialto { _generated_at_block: RialtoHeaderId, proof: ::MessagesReceivingProof, ) -> Result { + let (relayers_state, proof) = proof; let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); let nonce = self.source_client.next_account_index(account_id).await?; - let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); + let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); let transaction = Millau::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); Ok(transaction) } diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 0e059f7cfd295..22e56e312d99f 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -59,9 +59,10 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { _generated_at_block: MillauHeaderId, proof: ::MessagesReceivingProof, ) -> Result { + let (relayers_state, proof) = proof; let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); let nonce = self.source_client.next_account_index(account_id).await?; - let call = rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof).into(); + let call = rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); let transaction = Rialto::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); Ok(transaction) } From 407348cfd8bc8d9e1748b97b1c9ebc1d689c45ba Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Dec 2020 10:03:50 +0300 Subject: [PATCH 0273/1210] fix benchmarks compilation (#595) --- modules/message-lane/src/benchmarking.rs | 37 ++++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index f211f95c39ab9..a565b8c50fe38 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -22,7 +22,7 @@ use crate::{ use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, - MessageNonce, OutboundLaneData, + MessageNonce, OutboundLaneData, UnrewardedRelayersState, }; use frame_benchmarking::{account, benchmarks_instance}; use frame_support::{traits::Get, weights::Weight}; @@ -232,6 +232,11 @@ benchmarks_instance! { // send message that we're going to confirm send_regular_message::(); + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -240,7 +245,7 @@ benchmarks_instance! { latest_confirmed_nonce: 0, } }); - }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof) + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { assert_eq!( T::account_balance(&relayer_id), @@ -265,6 +270,11 @@ benchmarks_instance! { send_regular_message::(); send_regular_message::(); + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 2, + total_messages: 2, + }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -273,7 +283,7 @@ benchmarks_instance! { latest_confirmed_nonce: 0, } }); - }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof) + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { assert_eq!( T::account_balance(&relayer_id), @@ -300,6 +310,11 @@ benchmarks_instance! { send_regular_message::(); send_regular_message::(); + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + messages_in_oldest_entry: 1, + total_messages: 2, + }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -311,7 +326,7 @@ benchmarks_instance! { latest_confirmed_nonce: 0, } }); - }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof) + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) verify { assert_eq!( T::account_balance(&relayer1_id), @@ -426,6 +441,11 @@ benchmarks_instance! { send_regular_message::(); } + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: i as MessageNonce, + }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -434,7 +454,7 @@ benchmarks_instance! { latest_confirmed_nonce: 0, } }); - }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof) + }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { assert_eq!( T::account_balance(&relayer_id), @@ -466,6 +486,11 @@ benchmarks_instance! { send_regular_message::(); } + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: i as MessageNonce, + messages_in_oldest_entry: 1, + total_messages: i as MessageNonce, + }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -478,7 +503,7 @@ benchmarks_instance! { latest_confirmed_nonce: 0, } }); - }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof) + }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) verify { for (relayer_id, prev_balance) in relayers { assert_eq!( From 62d26dd7411655a46c6c1e0ac22f7a33c84e1ce9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Dec 2020 20:06:24 +0300 Subject: [PATCH 0274/1210] Automated weights for message lane module (#590) * automated weights * associated WeightInfo type * update weights using wasmtime * disable clippy for autogenerated weight.rs * fix --- bin/millau/runtime/src/lib.rs | 2 + bin/rialto/runtime/src/lib.rs | 1 + modules/message-lane/src/lib.rs | 4 + modules/message-lane/src/mock.rs | 1 + modules/message-lane/src/weights.rs | 195 ++++++++++++++++++++++++++++ 5 files changed, 203 insertions(+) create mode 100644 modules/message-lane/src/weights.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8dc9fea6283a4..24c379ffb2094 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -317,6 +317,8 @@ parameter_types! { impl pallet_message_lane::Config for Runtime { type Event = Event; + // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 + type WeightInfo = pallet_message_lane::weights::RialtoWeight; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 31c08aba223bd..89e9aea484957 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -425,6 +425,7 @@ parameter_types! { pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInstance; impl pallet_message_lane::Config for Runtime { type Event = Event; + type WeightInfo = pallet_message_lane::weights::RialtoWeight; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 267ad334398f2..c93218cc80963 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -31,6 +31,7 @@ use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; +use crate::weights::WeightInfo; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, @@ -54,6 +55,7 @@ mod inbound_lane; mod outbound_lane; pub mod instant_payments; +pub mod weights; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; @@ -75,6 +77,8 @@ pub trait Config: frame_system::Config { /// They overarching event type. type Event: From> + Into<::Event>; + /// Benchmarks results from runtime we're plugged into. + type WeightInfo: WeightInfo; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever new message is sent. The reason is that if you want to use lane, you should /// be ready to pay for its maintenance. diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 8250b955be2db..59ca1ab0b769c 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -101,6 +101,7 @@ parameter_types! { impl Config for TestRuntime { type Event = TestEvent; + type WeightInfo = (); type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/modules/message-lane/src/weights.rs b/modules/message-lane/src/weights.rs new file mode 100644 index 0000000000000..d819e5d574433 --- /dev/null +++ b/modules/message-lane/src/weights.rs @@ -0,0 +1,195 @@ +// Copyright 2019-2020 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 . + +//! Autogenerated weights for pallet_message_lane +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0 +//! DATE: 2020-12-22, STEPS: [50, ], REPEAT: 20 +//! LOW RANGE: [], HIGH RANGE: [] +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled +//! CHAIN: Some("local"), DB CACHE: 128 + +// Executed Command: +// target/release/rialto-bridge-node +// benchmark +// --chain=local +// --steps=50 +// --repeat=20 +// --pallet=pallet_message_lane +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./modules/message-lane/src/weights.rs +// --template=./.maintain/rialto-weight-template.hbs + +#![allow(clippy::all)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_message_lane. +pub trait WeightInfo { + fn send_message_worst_case() -> Weight; + fn receive_single_message_proof() -> Weight; + fn receive_two_messages_proof() -> Weight; + fn receive_single_message_proof_with_outbound_lane_state() -> Weight; + fn receive_delivery_proof_for_single_message() -> Weight; + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; + fn receive_multiple_messages_proof(i: u32) -> Weight; + fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; + fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight; + fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; +} + +/// Weights for pallet_message_lane using the Rialto node and recommended hardware. +pub struct RialtoWeight(PhantomData); +impl WeightInfo for RialtoWeight { + fn send_message_worst_case() -> Weight { + (4_289_189_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(12 as Weight)) + } + fn receive_single_message_proof() -> Weight { + (186_909_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_two_messages_proof() -> Weight { + (339_281_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + (215_607_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_delivery_proof_for_single_message() -> Weight { + (202_085_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + (213_142_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + (300_159_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + fn receive_multiple_messages_proof(i: u32) -> Weight { + (0 as Weight) + .saturating_add((150_558_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { + (0 as Weight) + .saturating_add((204_949_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { + (79_087_000 as Weight) + .saturating_add((12_889_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { + (131_794_000 as Weight) + .saturating_add((108_620_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn send_message_worst_case() -> Weight { + (4_289_189_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + } + fn receive_single_message_proof() -> Weight { + (186_909_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_two_messages_proof() -> Weight { + (339_281_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + (215_607_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_delivery_proof_for_single_message() -> Weight { + (202_085_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + (213_142_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + (300_159_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + fn receive_multiple_messages_proof(i: u32) -> Weight { + (0 as Weight) + .saturating_add((150_558_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { + (0 as Weight) + .saturating_add((204_949_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { + (79_087_000 as Weight) + .saturating_add((12_889_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { + (131_794_000 as Weight) + .saturating_add((108_620_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) + } +} From 7bc687e42524765c43104871ee917cfb6a15aa41 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Tue, 22 Dec 2020 21:20:15 +0100 Subject: [PATCH 0275/1210] Readme community section (#594) * Readme community section * better links * address review * correct Element history * Update README.md Co-authored-by: Hernando Castano * Fix link to Element.io Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 7157600e3fd82..546a7835a4e4d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Substrate chains or Ethereum Proof-of-Authority chains. - [High-Level Architecture](#high-level-architecture) - [Project Layout](#project-layout) - [Running the Bridge](#running-the-bridge) +- [Community](#community) ## Installation To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web @@ -189,3 +190,16 @@ Once you have the images built you can use them in the previous commands by repl For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). + +## Community + +Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat +server like, for example, Discord. Most discussions around Polkadot and Substrate happen +in various Element "rooms" (channels). So, joining Element might be a good idea, anyway. + +If you are interested in information exchange and development of Polkadot related bridges please +feel free to join the [Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) +Element channel. + +The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element +channel is most suited for discussions regarding Substrate itself. From a4d4a9f5cb51e684190f7f48d619120859916fdb Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 23 Dec 2020 03:53:47 -0500 Subject: [PATCH 0276/1210] Fixes for Polkadot Integration (#586) * Add AccountIdConverter impl to Kusama and Polkadot primitives * Add missing message lane config constants * Add more consts * Add another missing const * Move consts in primitives so that they're consistent across files * Move types and consts to more intuitive locations * Downgrade hyper from v0.13.8 to v0.13.6 This conflicts with a requirement on the Polkadot side which requires that hyper is =v0.13.6 * Update hyper to v0.13.9 * Update async-io to v1.3.1 * Update socket2 from v0.3.15 to v0.3.18 * Update message weight/size constants * Make BlockWeights/Length parameter types Allows us to re-use these types from both the runtime and the message lane config files without creating a new instance of them. * Remove uneccesary weight constants These can be found in the `runtime-common` crate used by Polkadot/Kusama. The constants there will also be the most up-to-date versions. --- bin/millau/runtime/src/lib.rs | 8 +- bin/rialto/runtime/src/lib.rs | 8 +- primitives/kusama/Cargo.toml | 2 + primitives/kusama/src/lib.rs | 28 +++++-- primitives/millau/src/lib.rs | 139 ++++++++++++++++----------------- primitives/polkadot/Cargo.toml | 2 + primitives/polkadot/src/lib.rs | 28 +++++-- primitives/rialto/src/lib.rs | 87 ++++++++++----------- 8 files changed, 160 insertions(+), 142 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 24c379ffb2094..982a58fd728b8 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -31,7 +31,6 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto_messages; use codec::Decode; -use frame_system::limits; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -155,9 +154,6 @@ parameter_types! { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; - - pub RuntimeBlockLength: limits::BlockLength = bp_millau::runtime_block_length(); - pub RuntimeBlockWeights: limits::BlockWeights = bp_millau::runtime_block_weights(); } impl frame_system::Config for Runtime { @@ -199,9 +195,9 @@ impl frame_system::Config for Runtime { /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); /// Block and extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; + type BlockWeights = bp_millau::BlockWeights; /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; + type BlockLength = bp_millau::BlockLength; /// The weight of database operations that the runtime can invoke. type DbWeight = DbWeight; } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 89e9aea484957..aeecebe3a2414 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -37,7 +37,6 @@ pub mod millau_messages; pub mod rialto_poa; use codec::Decode; -use frame_system::limits; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -163,9 +162,6 @@ parameter_types! { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; - - pub RuntimeBlockLength: limits::BlockLength = bp_rialto::runtime_block_length(); - pub RuntimeBlockWeights: limits::BlockWeights = bp_rialto::runtime_block_weights(); } impl frame_system::Config for Runtime { @@ -207,9 +203,9 @@ impl frame_system::Config for Runtime { /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); /// Block and extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; + type BlockWeights = bp_rialto::BlockWeights; /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; + type BlockLength = bp_rialto::BlockLength; /// The weight of database operations that the runtime can invoke. type DbWeight = DbWeight; } diff --git a/primitives/kusama/Cargo.toml b/primitives/kusama/Cargo.toml index 619a1947126bb..1a4142f75a317 100644 --- a/primitives/kusama/Cargo.toml +++ b/primitives/kusama/Cargo.toml @@ -16,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } @@ -27,6 +28,7 @@ std = [ "bp-message-lane/std", "bp-runtime/std", "frame-support/std", + "frame-system/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/kusama/src/lib.rs b/primitives/kusama/src/lib.rs index e6d69a6539bee..9ec032dbd5138 100644 --- a/primitives/kusama/src/lib.rs +++ b/primitives/kusama/src/lib.rs @@ -31,6 +31,18 @@ use sp_runtime::{ }; use sp_std::prelude::*; +// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 +/// Maximal number of messages in single delivery transaction. +pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; + +/// Maximal number of unrewarded relayer entries at inbound lane. +pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; + +// TODO: should be selected keeping in mind: +// finality delay on both chains + reward payout cost + messages throughput. +/// Maximal number of unconfirmed messages at inbound lane. +pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; + /// Block number type used in Kusama. pub type BlockNumber = u32; @@ -75,6 +87,15 @@ impl Chain for Kusama { type Header = Header; } +/// Convert a 256-bit hash into an AccountId. +pub struct AccountIdConverter; + +impl sp_runtime::traits::Convert for AccountIdConverter { + fn convert(hash: sp_core::H256) -> AccountId { + hash.to_fixed_bytes().into() + } +} + /// Name of the `KusamaHeaderApi::best_blocks` runtime method. pub const BEST_KUSAMA_BLOCKS_METHOD: &str = "KusamaHeaderApi_best_blocks"; /// Name of the `KusamaHeaderApi::finalized_block` runtime method. @@ -84,13 +105,6 @@ pub const IS_KNOWN_KUSAMA_BLOCK_METHOD: &str = "KusamaHeaderApi_is_known_block"; /// Name of the `KusamaHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_KUSAMA_HEADERS_METHOD: &str = "KusamaHeaderApi_incomplete_headers"; -/// Maximal weight of single Kusama extrinsic. -pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = 725_000_000_000; - -// TODO: should be selected keeping in mind: finality delay on both chains + reward payout cost + messages throughput. -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; - sp_api::decl_runtime_apis! { /// API for querying information about Kusama headers from the Bridge Pallet instance. /// diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index c9e90501ffdf1..38cbf37a4b4e1 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -28,6 +28,7 @@ use frame_support::{ weights::{constants::WEIGHT_PER_MILLIS, DispatchClass, Weight}, RuntimeDebug, }; +use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::traits::Convert; use sp_runtime::{ @@ -42,36 +43,6 @@ use serde::{Deserialize, Serialize}; pub use millau_hash::MillauHash; -/// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. -#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct BlakeTwoAndKeccak256; - -impl sp_core::Hasher for BlakeTwoAndKeccak256 { - type Out = MillauHash; - type StdHasher = hash256_std_hasher::Hash256StdHasher; - const LENGTH: usize = 64; - - fn hash(s: &[u8]) -> Self::Out { - let mut combined_hash = MillauHash::default(); - combined_hash.as_mut()[..32].copy_from_slice(&sp_io::hashing::blake2_256(s)); - combined_hash.as_mut()[32..].copy_from_slice(&sp_io::hashing::keccak_256(s)); - combined_hash - } -} - -impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { - type Output = MillauHash; - - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - Layout::::trie_root(input) - } - - fn ordered_trie_root(input: Vec>) -> Self::Output { - Layout::::ordered_trie_root(input) - } -} - /// Maximum weight of single Millau block. /// /// This represents 0.1 seconds of compute assuming a target block time of six seconds. @@ -102,6 +73,19 @@ pub type Hasher = BlakeTwoAndKeccak256; /// The header type used by Millau. pub type Header = sp_runtime::generic::Header; +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// Balance of an account. +pub type Balance = u64; + /// Millau chain. #[derive(RuntimeDebug)] pub struct Millau; @@ -113,41 +97,35 @@ impl Chain for Millau { type Header = Header; } -/// Name of the `MillauHeaderApi::best_block` runtime method. -pub const BEST_MILLAU_BLOCKS_METHOD: &str = "MillauHeaderApi_best_blocks"; -/// Name of the `MillauHeaderApi::finalized_block` runtime method. -pub const FINALIZED_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_finalized_block"; -/// Name of the `MillauHeaderApi::is_known_block` runtime method. -pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; -/// Name of the `MillauHeaderApi::incomplete_headers` runtime method. -pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; - -/// Name of the `ToMillauOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToMillauOutboundLaneApi_messages_dispatch_weight"; -/// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; -/// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_generated_nonce"; +/// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. +#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BlakeTwoAndKeccak256; -/// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_received_nonce"; -/// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneApi_unrewarded_relayers_state"; +impl sp_core::Hasher for BlakeTwoAndKeccak256 { + type Out = MillauHash; + type StdHasher = hash256_std_hasher::Hash256StdHasher; + const LENGTH: usize = 64; -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; + fn hash(s: &[u8]) -> Self::Out { + let mut combined_hash = MillauHash::default(); + combined_hash.as_mut()[..32].copy_from_slice(&sp_io::hashing::blake2_256(s)); + combined_hash.as_mut()[32..].copy_from_slice(&sp_io::hashing::keccak_256(s)); + combined_hash + } +} -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { + type Output = MillauHash; -/// Public key of the chain account that may be used to verify signatures. -pub type AccountSigner = MultiSigner; + fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { + Layout::::trie_root(input) + } -/// Balance of an account. -pub type Balance = u64; + fn ordered_trie_root(input: Vec>) -> Self::Output { + Layout::::ordered_trie_root(input) + } +} /// Convert a 256-bit hash into an AccountId. pub struct AccountIdConverter; @@ -171,9 +149,10 @@ pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Get a struct which defines the weight limits and values used during extrinsic execution. -pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { - frame_system::limits::BlockWeights::builder() +frame_support::parameter_types! { + pub BlockLength: limits::BlockLength = + limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() // Allowance for Normal class .for_class(DispatchClass::Normal, |weights| { weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); @@ -187,27 +166,45 @@ pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { // By default Mandatory class is not limited at all. // This parameter is used to derive maximal size of a single extrinsic. .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic() + .build_or_panic(); } /// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. pub fn max_extrinsic_weight() -> Weight { - runtime_block_weights() + BlockWeights::get() .get(DispatchClass::Normal) .max_extrinsic .unwrap_or(Weight::MAX) } -/// Get a struct which tracks the length in bytes for each extrinsic class in a Millau block. -pub fn runtime_block_length() -> frame_system::limits::BlockLength { - frame_system::limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO) -} - /// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. pub fn max_extrinsic_size() -> u32 { - *runtime_block_length().max.get(DispatchClass::Normal) + *BlockLength::get().max.get(DispatchClass::Normal) } +/// Name of the `MillauHeaderApi::best_block` runtime method. +pub const BEST_MILLAU_BLOCKS_METHOD: &str = "MillauHeaderApi_best_blocks"; +/// Name of the `MillauHeaderApi::finalized_block` runtime method. +pub const FINALIZED_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_finalized_block"; +/// Name of the `MillauHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; +/// Name of the `MillauHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; + +/// Name of the `ToMillauOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToMillauOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; +/// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_generated_nonce"; + +/// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_received_nonce"; +/// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneApi_unrewarded_relayers_state"; + sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// diff --git a/primitives/polkadot/Cargo.toml b/primitives/polkadot/Cargo.toml index 6f79e6bd1b984..396cbd5b47ea0 100644 --- a/primitives/polkadot/Cargo.toml +++ b/primitives/polkadot/Cargo.toml @@ -16,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } @@ -27,6 +28,7 @@ std = [ "bp-message-lane/std", "bp-runtime/std", "frame-support/std", + "frame-system/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/polkadot/src/lib.rs b/primitives/polkadot/src/lib.rs index 83cb7db41c2b8..a82dd5075bb67 100644 --- a/primitives/polkadot/src/lib.rs +++ b/primitives/polkadot/src/lib.rs @@ -31,6 +31,18 @@ use sp_runtime::{ }; use sp_std::prelude::*; +// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 +/// Maximal number of messages in single delivery transaction. +pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; + +/// Maximal number of unrewarded relayer entries at inbound lane. +pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; + +// TODO: should be selected keeping in mind: +// finality delay on both chains + reward payout cost + messages throughput. +/// Maximal number of unconfirmed messages at inbound lane. +pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; + /// Block number type used in Polkadot. pub type BlockNumber = u32; @@ -75,6 +87,15 @@ impl Chain for Polkadot { type Header = Header; } +/// Convert a 256-bit hash into an AccountId. +pub struct AccountIdConverter; + +impl sp_runtime::traits::Convert for AccountIdConverter { + fn convert(hash: sp_core::H256) -> AccountId { + hash.to_fixed_bytes().into() + } +} + /// Name of the `PolkadotHeaderApi::best_blocks` runtime method. pub const BEST_POLKADOT_BLOCKS_METHOD: &str = "PolkadotHeaderApi_best_blocks"; /// Name of the `PolkadotHeaderApi::finalized_block` runtime method. @@ -84,13 +105,6 @@ pub const IS_KNOWN_POLKADOT_BLOCK_METHOD: &str = "PolkadotHeaderApi_is_known_blo /// Name of the `PolkadotHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_POLKADOT_HEADERS_METHOD: &str = "PolkadotHeaderApi_incomplete_headers"; -/// Maximal weight of single Polkadot extrinsic. -pub const MAXIMUM_EXTRINSIC_WEIGHT: Weight = 725_000_000_000; - -// TODO: should be selected keeping in mind: finality delay on both chains + reward payout cost + messages throughput. -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; - sp_api::decl_runtime_apis! { /// API for querying information about Polkadot headers from the Bridge Pallet instance. /// diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index fffa556f72bfa..2b293d70f958b 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -26,6 +26,7 @@ use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, RuntimeDebug, }; +use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, @@ -63,40 +64,6 @@ pub type Hasher = BlakeTwo256; /// The header type used by Rialto. pub type Header = sp_runtime::generic::Header; -/// Rialto chain. -#[derive(RuntimeDebug)] -pub struct Rialto; - -impl Chain for Rialto { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; -} - -/// Name of the `RialtoHeaderApi::best_blocks` runtime method. -pub const BEST_RIALTO_BLOCKS_METHOD: &str = "RialtoHeaderApi_best_blocks"; -/// Name of the `RialtoHeaderApi::finalized_block` runtime method. -pub const FINALIZED_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_finalized_block"; -/// Name of the `RialtoHeaderApi::is_known_block` runtime method. -pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; -/// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. -pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; - -/// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; -/// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; -/// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneApi_unrewarded_relayers_state"; - /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; @@ -110,6 +77,17 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u128; +/// Rialto chain. +#[derive(RuntimeDebug)] +pub struct Rialto; + +impl Chain for Rialto { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; +} + /// Convert a 256-bit hash into an AccountId. pub struct AccountIdConverter; @@ -132,9 +110,10 @@ pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Get a struct which defines the weight limits and values used during extrinsic execution. -pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { - frame_system::limits::BlockWeights::builder() +frame_support::parameter_types! { + pub BlockLength: limits::BlockLength = + limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() // Allowance for Normal class .for_class(DispatchClass::Normal, |weights| { weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); @@ -148,27 +127,45 @@ pub fn runtime_block_weights() -> frame_system::limits::BlockWeights { // By default Mandatory class is not limited at all. // This parameter is used to derive maximal size of a single extrinsic. .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic() + .build_or_panic(); } /// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. pub fn max_extrinsic_weight() -> Weight { - runtime_block_weights() + BlockWeights::get() .get(DispatchClass::Normal) .max_extrinsic .unwrap_or(Weight::MAX) } -/// Get a struct which tracks the length in bytes for each extrinsic class in a Millau block. -pub fn runtime_block_length() -> frame_system::limits::BlockLength { - frame_system::limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO) -} - /// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. pub fn max_extrinsic_size() -> u32 { - *runtime_block_length().max.get(DispatchClass::Normal) + *BlockLength::get().max.get(DispatchClass::Normal) } +/// Name of the `RialtoHeaderApi::best_blocks` runtime method. +pub const BEST_RIALTO_BLOCKS_METHOD: &str = "RialtoHeaderApi_best_blocks"; +/// Name of the `RialtoHeaderApi::finalized_block` runtime method. +pub const FINALIZED_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_finalized_block"; +/// Name of the `RialtoHeaderApi::is_known_block` runtime method. +pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; +/// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. +pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; + +/// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; +/// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneApi_unrewarded_relayers_state"; + sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// From 11f76d25aff62a198434b51a90d39286c1628cd5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Dec 2020 11:29:33 +0300 Subject: [PATCH 0277/1210] Message lane weight formulas (#596) * weight formulas for message-lane calls * extracted WeightInfoExt into separate file --- bin/rialto/runtime/src/lib.rs | 5 ++ modules/message-lane/src/lib.rs | 43 +++++++---- modules/message-lane/src/weights_ext.rs | 95 +++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 modules/message-lane/src/weights_ext.rs diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index aeecebe3a2414..33e4972d05935 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1005,6 +1005,11 @@ mod tests { }); } + #[test] + fn ensure_rialto_message_lane_weights_are_correct() { + pallet_message_lane::ensure_weights_are_correct::>(); + } + #[test] fn deposit_into_existing_account_works() { run_deposit_into_test(|existing_account| { diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index c93218cc80963..51e29322a5541 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -26,9 +26,17 @@ //! Once message is sent, its progress can be tracked by looking at module events. //! The assigned nonce is reported using `MessageAccepted` event. When message is //! delivered to the the bridged chain, it is reported using `MessagesDelivered` event. +//! +//! **IMPORTANT NOTE**: after generating weights (custom `WeighInfo` implementation) for +//! your runtime (where this module is plugged to), please add test for these weights. +//! The test should call the `ensure_weights_are_correct` function from this module. +//! If this test fails with your weights, then either weights are computed incorrectly, +//! or some benchmarks assumptions are broken for your runtime. #![cfg_attr(not(feature = "std"), no_std)] +pub use crate::weights_ext::{ensure_weights_are_correct, WeightInfoExt}; + use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use crate::weights::WeightInfo; @@ -53,6 +61,7 @@ use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; +mod weights_ext; pub mod instant_payments; pub mod weights; @@ -63,14 +72,6 @@ pub mod benchmarking; #[cfg(test)] mod mock; -// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) -/// Weight of message delivery without any code that is touching messages. -const DELIVERY_OVERHEAD_WEIGHT: Weight = 0; -// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) -/// Single-message delivery weight. This shall not include message dispatch weight and -/// any delivery transaction code that is not specific to this message. -const SINGLE_MESSAGE_DELIVERY_WEIGHT: Weight = 0; - /// The module configuration trait pub trait Config: frame_system::Config { // General types @@ -78,7 +79,7 @@ pub trait Config: frame_system::Config { /// They overarching event type. type Event: From> + Into<::Event>; /// Benchmarks results from runtime we're plugged into. - type WeightInfo: WeightInfo; + type WeightInfo: WeightInfoExt; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever new message is sent. The reason is that if you want to use lane, you should /// be ready to pay for its maintenance. @@ -252,7 +253,10 @@ decl_module! { } /// Send message over lane. - #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + /// + /// The weight of the call assumes that the largest possible message is sent in + /// worst possible environment. + #[weight = T::WeightInfo::send_message_worst_case()] pub fn send_message( origin, lane_id: LaneId, @@ -327,9 +331,13 @@ decl_module! { } /// Receive messages proof from bridged chain. - #[weight = messages_count - .saturating_mul(SINGLE_MESSAGE_DELIVERY_WEIGHT) - .saturating_add(DELIVERY_OVERHEAD_WEIGHT) + /// + /// The weight of the call assumes that the transaction always brings outbound lane + /// state update. Because of that, the submitter (relayer) has no benefit of not including + /// this data in the transaction, so reward confirmations lags should be minimal. + #[weight = T::WeightInfo::receive_messages_proof_overhead() + .saturating_add(T::WeightInfo::receive_messages_proof_outbound_lane_state_overhead()) + .saturating_add(T::WeightInfo::receive_messages_proof_messages_overhead(*messages_count)) .saturating_add(*dispatch_weight) ] pub fn receive_messages_proof( @@ -414,7 +422,14 @@ decl_module! { } /// Receive messages delivery proof from bridged chain. - #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + #[weight = T::WeightInfo::receive_messages_delivery_proof_overhead() + .saturating_add(T::WeightInfo::receive_messages_delivery_proof_messages_overhead( + relayers_state.total_messages + )) + .saturating_add(T::WeightInfo::receive_messages_delivery_proof_relayers_overhead( + relayers_state.unrewarded_relayer_entries + )) + ] pub fn receive_messages_delivery_proof( origin, proof: MessagesDeliveryProofOf, diff --git a/modules/message-lane/src/weights_ext.rs b/modules/message-lane/src/weights_ext.rs new file mode 100644 index 0000000000000..5e1f1c88615c8 --- /dev/null +++ b/modules/message-lane/src/weights_ext.rs @@ -0,0 +1,95 @@ +// Copyright 2019-2020 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 . + +//! Weight-related utilities. + +use crate::weights::WeightInfo; + +use bp_message_lane::MessageNonce; +use frame_support::weights::Weight; + +/// Ensure that weights from `WeightInfoExt` implementation are looking correct. +pub fn ensure_weights_are_correct() { + assert_ne!(W::send_message_worst_case(), 0); + + assert_ne!(W::receive_messages_proof_overhead(), 0); + assert_ne!(W::receive_messages_proof_messages_overhead(1), 0); + assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), 0); + + assert_ne!(W::receive_messages_delivery_proof_overhead(), 0); + assert_ne!(W::receive_messages_delivery_proof_messages_overhead(1), 0); + assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1), 0); +} + +/// Extended weight info. +pub trait WeightInfoExt: WeightInfo { + /// Returns weight overhead of message delivery transaction (`receive_messages_proof`). + fn receive_messages_proof_overhead() -> Weight { + let weight_of_two_messages_and_two_tx_overheads = Self::receive_single_message_proof().saturating_mul(2); + let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof(); + weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead) + } + + /// Returns weight that needs to be accounted when receiving given number of messages with message + /// delivery transaction (`receive_messages_proof`). + fn receive_messages_proof_messages_overhead(messages: MessageNonce) -> Weight { + let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof(); + let weight_of_single_message_and_single_tx_overhead = Self::receive_single_message_proof(); + weight_of_two_messages_and_single_tx_overhead + .saturating_sub(weight_of_single_message_and_single_tx_overhead) + .saturating_mul(messages as Weight) + } + + /// Returns weight that needs to be accounted when message delivery transaction (`receive_messages_proof`) + /// is carrying outbound lane state proof. + fn receive_messages_proof_outbound_lane_state_overhead() -> Weight { + let weight_of_single_message_and_lane_state = Self::receive_single_message_proof_with_outbound_lane_state(); + let weight_of_single_message = Self::receive_single_message_proof(); + weight_of_single_message_and_lane_state.saturating_sub(weight_of_single_message) + } + + /// Returns weight overhead of delivery confirmation transaction (`receive_messages_delivery_proof`). + fn receive_messages_delivery_proof_overhead() -> Weight { + let weight_of_two_messages_and_two_tx_overheads = + Self::receive_delivery_proof_for_single_message().saturating_mul(2); + let weight_of_two_messages_and_single_tx_overhead = + Self::receive_delivery_proof_for_two_messages_by_single_relayer(); + weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead) + } + + /// Returns weight that needs to be accounted when receiving confirmations for given number of + /// messages with delivery confirmation transaction (`receive_messages_delivery_proof`). + fn receive_messages_delivery_proof_messages_overhead(messages: MessageNonce) -> Weight { + let weight_of_two_messages = Self::receive_delivery_proof_for_two_messages_by_single_relayer(); + let weight_of_single_message = Self::receive_delivery_proof_for_single_message(); + weight_of_two_messages + .saturating_sub(weight_of_single_message) + .saturating_mul(messages as Weight) + } + + /// Returns weight that needs to be accounted when receiving confirmations for given number of + /// relayers entries with delivery confirmation transaction (`receive_messages_delivery_proof`). + fn receive_messages_delivery_proof_relayers_overhead(relayers: MessageNonce) -> Weight { + let weight_of_two_messages_by_two_relayers = Self::receive_delivery_proof_for_two_messages_by_two_relayers(); + let weight_of_two_messages_by_single_relayer = + Self::receive_delivery_proof_for_two_messages_by_single_relayer(); + weight_of_two_messages_by_two_relayers + .saturating_sub(weight_of_two_messages_by_single_relayer) + .saturating_mul(relayers as Weight) + } +} + +impl WeightInfoExt for T {} From b2b1351d9af7af25830502b556a1f4d81c0d844d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 29 Dec 2020 01:43:44 +0300 Subject: [PATCH 0278/1210] increase maximal blokc weight at Millau (#602) --- primitives/millau/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 38cbf37a4b4e1..daef9abf2fc46 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -25,7 +25,7 @@ mod millau_hash; use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ - weights::{constants::WEIGHT_PER_MILLIS, DispatchClass, Weight}, + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, RuntimeDebug, }; use frame_system::limits; @@ -45,8 +45,8 @@ pub use millau_hash::MillauHash; /// Maximum weight of single Millau block. /// -/// This represents 0.1 seconds of compute assuming a target block time of six seconds. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 10 * WEIGHT_PER_MILLIS; +/// This represents 0.5 seconds of compute assuming a target block time of six seconds. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2; /// Represents the average portion of a block's weight that will be used by an /// `on_initialize()` runtime call. From 75f0a7f106264fe07eafec2d0c89e49041f5870f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 4 Jan 2021 03:01:14 +0000 Subject: [PATCH 0279/1210] Bump serde_json from 1.0.60 to 1.0.61 (#606) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 95f83453524f2..4b13ff5d24794 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac" log = "0.4.11" num-traits = "0.2" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.60" +serde_json = "1.0.61" time = "0.2" # Bridge dependencies From 2bfcbafbaff48dc188f9e5acfa8a9d585e242188 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 4 Jan 2021 22:33:18 +0300 Subject: [PATCH 0280/1210] Fix Ethereum pallet benchmarks (#601) --- bin/rialto/runtime/src/exchange.rs | 4 +-- modules/ethereum/src/finality.rs | 2 +- modules/ethereum/src/lib.rs | 39 +++++++++++------------------- modules/ethereum/src/test_utils.rs | 34 ++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index 12fbadf012dd1..926d9595372a0 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -133,7 +133,7 @@ pub(crate) fn prepare_environment_for_claim, ) -> bp_eth_poa::H256 { use bp_eth_poa::compute_merkle_root; use pallet_bridge_eth_poa::{ - test_utils::{insert_header, validator_utils::validator, HeaderBuilder}, + test_utils::{insert_dummy_header, validator_utils::validator, HeaderBuilder}, BridgeStorage, Storage, }; @@ -143,7 +143,7 @@ pub(crate) fn prepare_environment_for_claim, .receipts_root(compute_merkle_root(transactions.iter().map(|(_, receipt)| receipt))) .sign_by(&validator(0)); let header_id = header.compute_id(); - insert_header(&mut storage, header); + insert_dummy_header(&mut storage, header); storage.finalize_and_prune_headers(Some(header_id), 0); header_id.hash diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index e53ce91ed3cf9..608708a0c7bad 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -140,7 +140,7 @@ fn is_finalized( } /// Prepare 'votes' of header and its ancestors' signers. -fn prepare_votes( +pub(crate) fn prepare_votes( mut cached_votes: CachedFinalityVotes, best_finalized: HeaderId, validators: &BTreeSet<&Address>, diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 70ebbe624ce5f..05beb279a926c 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -1049,6 +1049,7 @@ pub(crate) mod tests { genesis, insert_header, run_test, run_test_with_genesis, validators_addresses, HeaderBuilder, TestRuntime, GAS_LIMIT, }; + use crate::test_utils::validator_utils::*; use bp_eth_poa::compute_merkle_root; const TOTAL_VALIDATORS: usize = 3; @@ -1069,33 +1070,24 @@ pub(crate) mod tests { } fn example_header_with_failed_receipt() -> AuraHeader { - AuraHeader { - number: 3, - transactions_root: compute_merkle_root(vec![example_tx()].into_iter()), - receipts_root: compute_merkle_root(vec![example_tx_receipt(false)].into_iter()), - parent_hash: example_header().compute_hash(), - ..Default::default() - } + HeaderBuilder::with_parent(&example_header()) + .transactions_root(compute_merkle_root(vec![example_tx()].into_iter())) + .receipts_root(compute_merkle_root(vec![example_tx_receipt(false)].into_iter())) + .sign_by(&validator(0)) } fn example_header() -> AuraHeader { - AuraHeader { - number: 2, - transactions_root: compute_merkle_root(vec![example_tx()].into_iter()), - receipts_root: compute_merkle_root(vec![example_tx_receipt(true)].into_iter()), - parent_hash: example_header_parent().compute_hash(), - ..Default::default() - } + HeaderBuilder::with_parent(&example_header_parent()) + .transactions_root(compute_merkle_root(vec![example_tx()].into_iter())) + .receipts_root(compute_merkle_root(vec![example_tx_receipt(true)].into_iter())) + .sign_by(&validator(0)) } fn example_header_parent() -> AuraHeader { - AuraHeader { - number: 1, - transactions_root: compute_merkle_root(vec![example_tx()].into_iter()), - receipts_root: compute_merkle_root(vec![example_tx_receipt(true)].into_iter()), - parent_hash: genesis().compute_hash(), - ..Default::default() - } + HeaderBuilder::with_parent(&genesis()) + .transactions_root(compute_merkle_root(vec![example_tx()].into_iter())) + .receipts_root(compute_merkle_root(vec![example_tx_receipt(true)].into_iter())) + .sign_by(&validator(0)) } fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { @@ -1277,10 +1269,7 @@ pub(crate) mod tests { let header_with_entry = HeaderBuilder::with_parent_number(interval - 1).sign_by_set(&ctx.validators); let header_with_entry_hash = header_with_entry.compute_hash(); insert_header(&mut storage, header_with_entry); - assert_eq!( - FinalityCache::::get(&header_with_entry_hash), - Some(Default::default()), - ); + assert!(FinalityCache::::get(&header_with_entry_hash).is_some()); // when we later prune this header, cache entry is removed BlocksToPrune::::put(PruningRange { diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index e1e145f3d1236..f41652f570813 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -228,7 +228,41 @@ where } /// Insert unverified header into storage. +/// +/// This function assumes that the header is signed by validator from the current set. pub fn insert_header(storage: &mut S, header: AuraHeader) { + let id = header.compute_id(); + let best_finalized = storage.finalized_block(); + let import_context = storage.import_context(None, &header.parent_hash).unwrap(); + let parent_finality_votes = storage.cached_finality_votes(&header.parent_id().unwrap(), &best_finalized, |_| false); + let finality_votes = crate::finality::prepare_votes( + parent_finality_votes, + best_finalized, + &import_context.validators_set().validators.iter().collect(), + id, + &header, + None, + ) + .unwrap(); + + storage.insert_header(HeaderToImport { + context: storage.import_context(None, &header.parent_hash).unwrap(), + is_best: true, + id, + header, + total_difficulty: 0.into(), + enacted_change: None, + scheduled_change: None, + finality_votes, + }); +} + +/// Insert unverified header into storage. +/// +/// No assumptions about header author are made. The cost is that finality votes cache +/// is filled incorrectly, so this function shall not be used if you're going to insert +/// (or import) header descendants. +pub fn insert_dummy_header(storage: &mut S, header: AuraHeader) { storage.insert_header(HeaderToImport { context: storage.import_context(None, &header.parent_hash).unwrap(), is_best: true, From 8ce4b7b6bbae56c33c77655fe6b5d54e80c348ff Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 4 Jan 2021 23:52:58 +0300 Subject: [PATCH 0281/1210] Update Substrate reference (#604) --- bin/millau/node/src/command.rs | 2 +- bin/rialto/node/src/command.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index c007d5d848532..1b387d02dda71 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -84,7 +84,7 @@ pub fn run() -> sc_cli::Result<()> { Ok(()) } } - Some(Subcommand::Key(cmd)) => cmd.run(), + Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), Some(Subcommand::Vanity(cmd)) => cmd.run(), diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 52ff1d5a254d3..0ba8c87238b1f 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -84,7 +84,7 @@ pub fn run() -> sc_cli::Result<()> { Ok(()) } } - Some(Subcommand::Key(cmd)) => cmd.run(), + Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), Some(Subcommand::Vanity(cmd)) => cmd.run(), From 369cc1f92dc9e8807451e1ef23544076c2bb642d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 4 Jan 2021 23:54:51 +0300 Subject: [PATCH 0282/1210] Estimate message fee api (#600) * estimate_message_delivery_and_dispatch_fee runtime API * auto-determine message fees in relay * remove fee argument from relay calls * Fix import of weight contant Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 15 +++++- bin/millau/runtime/src/rialto_messages.rs | 4 +- bin/rialto/runtime/src/lib.rs | 15 +++++- bin/rialto/runtime/src/millau_messages.rs | 4 +- bin/runtime-common/src/messages.rs | 33 ++++++------- primitives/millau/src/lib.rs | 20 +++++++- primitives/rialto/src/lib.rs | 20 +++++++- relays/substrate/src/cli.rs | 8 +-- relays/substrate/src/main.rs | 60 +++++++++++++++++++++-- 9 files changed, 144 insertions(+), 35 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 982a58fd728b8..b7a294900580c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -30,6 +30,9 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto_messages; +use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; + +use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; @@ -532,7 +535,17 @@ impl_runtime_apis! { } } - impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { + impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { + fn estimate_message_delivery_and_dispatch_fee( + _lane_id: bp_message_lane::LaneId, + payload: ToRialtoMessagePayload, + ) -> Option { + estimate_message_dispatch_and_delivery_fee::( + &payload, + WithRialtoMessageBridge::RELAYER_FEE_PERCENT, + ).ok() + } + fn messages_dispatch_weight( lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index b5e1cc0fdb07c..cf3e6511801c8 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -124,9 +124,9 @@ impl MessageBridge for WithRialtoMessageBridge { ::WeightToFee::calc(&weight) as _ } - fn this_balance_to_bridged_balance(this_balance: bp_millau::Balance) -> bp_rialto::Balance { + fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { // 1:1 conversion that will probably change in the future - this_balance as _ + bridged_balance as _ } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 33e4972d05935..6a7562c5913cf 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -36,6 +36,9 @@ pub mod kovan; pub mod millau_messages; pub mod rialto_poa; +use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; + +use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use sp_api::impl_runtime_apis; @@ -695,7 +698,17 @@ impl_runtime_apis! { } } - impl bp_millau::ToMillauOutboundLaneApi for Runtime { + impl bp_millau::ToMillauOutboundLaneApi for Runtime { + fn estimate_message_delivery_and_dispatch_fee( + _lane_id: bp_message_lane::LaneId, + payload: ToMillauMessagePayload, + ) -> Option { + estimate_message_dispatch_and_delivery_fee::( + &payload, + WithMillauMessageBridge::RELAYER_FEE_PERCENT, + ).ok() + } + fn messages_dispatch_weight( lane: bp_message_lane::LaneId, begin: bp_message_lane::MessageNonce, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 33d254e9b5e40..85b06c35af343 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -125,9 +125,9 @@ impl MessageBridge for WithMillauMessageBridge { ::WeightToFee::calc(&weight) as _ } - fn this_balance_to_bridged_balance(this_balance: bp_rialto::Balance) -> bp_millau::Balance { + fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { // 1:1 conversion that will probably change in the future - this_balance as _ + bridged_balance as _ } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 30c6a1f7d1c2e..503dcaeddf77e 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -81,8 +81,8 @@ pub trait MessageBridge { /// Convert weight of the Bridged chain to the fee (paid in Balance) of the Bridged chain. fn bridged_weight_to_bridged_balance(weight: WeightOf>) -> BalanceOf>; - /// Convert This chain Balance into Bridged chain Balance. - fn this_balance_to_bridged_balance(this_balance: BalanceOf>) -> BalanceOf>; + /// Convert Bridged chain Balance into This chain Balance. + fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; } /// Chain that has `message-lane` and `call-dispatch` modules. @@ -170,12 +170,11 @@ pub mod source { // `CallDispatch`, so we verify the message accordingly. pallet_bridge_call_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; - let minimal_fee_in_bridged_tokens = + let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; // compare with actual fee paid - let actual_fee_in_bridged_tokens = B::this_balance_to_bridged_balance(*delivery_and_dispatch_fee); - if actual_fee_in_bridged_tokens < minimal_fee_in_bridged_tokens { + if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { return Err(TOO_LOW_FEE); } @@ -225,22 +224,22 @@ pub mod source { pub fn estimate_message_dispatch_and_delivery_fee( payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, - ) -> Result>, &'static str> { + ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction()); let dispatch_fee = B::bridged_weight_to_bridged_balance(payload.weight.into()); let reward_confirmation_fee = B::bridged_weight_to_bridged_balance(B::weight_of_reward_confirmation_transaction_on_target_chain()); - // the fee (in Bridged tokens) of all transactions that are made on This chain - let delivery_confirmation_fee = B::this_balance_to_bridged_balance(B::this_weight_to_this_balance( - B::weight_of_delivery_confirmation_transaction_on_this_chain(), - )); + // the fee (in This tokens) of all transactions that are made on This chain + let delivery_confirmation_fee = + B::this_weight_to_this_balance(B::weight_of_delivery_confirmation_transaction_on_this_chain()); - // minimal fee (in Bridged tokens) is a sum of all required fees + // minimal fee (in This tokens) is a sum of all required fees let minimal_fee = delivery_fee .checked_add(&dispatch_fee) .and_then(|fee| fee.checked_add(&reward_confirmation_fee)) + .map(B::bridged_balance_to_this_balance) .and_then(|fee| fee.checked_add(&delivery_confirmation_fee)); // before returning, add extra fee that is paid to the relayer (relayer interest) @@ -563,7 +562,7 @@ mod tests { const REWARD_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; - const THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE: u32 = 6; + const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048; const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; @@ -606,8 +605,8 @@ mod tests { BridgedChainBalance(weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } - fn this_balance_to_bridged_balance(this_balance: ThisChainBalance) -> BridgedChainBalance { - BridgedChainBalance(this_balance.0 * THIS_CHAIN_TO_BRIDGED_CHAIN_BALANCE_RATE as u32) + fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { + ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) } } @@ -649,7 +648,7 @@ mod tests { unreachable!() } - fn this_balance_to_bridged_balance(_this_balance: BridgedChainBalance) -> ThisChainBalance { + fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { unreachable!() } } @@ -799,7 +798,7 @@ mod tests { #[test] fn message_fee_is_checked_by_verifier() { - const EXPECTED_MINIMAL_FEE: u32 = 2640; + const EXPECTED_MINIMAL_FEE: u32 = 8140; // payload of the This -> Bridged chain message let payload = source::FromThisChainMessagePayload:: { @@ -815,7 +814,7 @@ mod tests { &payload, OnThisChainBridge::RELAYER_FEE_PERCENT, ), - Ok(BridgedChainBalance(EXPECTED_MINIMAL_FEE)), + Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); // and now check that the verifier checks the fee diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index daef9abf2fc46..636697847cd40 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -26,7 +26,7 @@ use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, - RuntimeDebug, + Parameter, RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; @@ -191,6 +191,9 @@ pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; /// Name of the `MillauHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; +/// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToMillauOutboundLaneApi::messages_dispatch_weight` runtime method. pub const TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToMillauOutboundLaneApi_messages_dispatch_weight"; /// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. @@ -235,7 +238,20 @@ sp_api::decl_runtime_apis! { /// /// This API is implemented by runtimes that are sending messages to Millau chain, not the /// Millau runtime itself. - pub trait ToMillauOutboundLaneApi { + pub trait ToMillauOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Millau from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 2b293d70f958b..a514254b22565 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -24,7 +24,7 @@ use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, - RuntimeDebug, + Parameter, RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; @@ -152,6 +152,9 @@ pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; /// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; +/// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; /// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. @@ -196,7 +199,20 @@ sp_api::decl_runtime_apis! { /// /// This API is implemented by runtimes that are sending messages to Rialto chain, not the /// Rialto runtime itself. - pub trait ToRialtoOutboundLaneApi { + pub trait ToRialtoOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Rialto from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 0e7f92001a355..a6dd5ab67b33c 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -101,9 +101,9 @@ pub enum Command { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, - /// Delivery and dispatch fee. + /// Delivery and dispatch fee. If not passed, determined automatically. #[structopt(long)] - fee: bp_millau::Balance, + fee: Option, /// Message type. #[structopt(subcommand)] message: ToRialtoMessage, @@ -138,9 +138,9 @@ pub enum Command { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, - /// Delivery and dispatch fee. + /// Delivery and dispatch fee. If not passed, determined automatically. #[structopt(long)] - fee: bp_rialto::Balance, + fee: Option, /// Message type. #[structopt(subcommand)] message: ToMillauMessage, diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index a63dc9623ed16..c6b89e7ee1fba 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -18,13 +18,13 @@ #![warn(missing_docs)] -use codec::Encode; +use codec::{Decode, Encode}; use frame_support::weights::GetDispatchInfo; use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; use relay_kusama_client::Kusama; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ConnectionParams, TransactionSignScheme}; +use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; use relay_utils::initialize::initialize_relay; use sp_core::{Bytes, Pair}; use sp_runtime::traits::IdentifyAccount; @@ -315,8 +315,27 @@ async fn run_command(command: cli::Command) -> Result<(), String> { } }; + let lane = lane.into(); + let fee = match fee { + Some(fee) => fee, + None => match estimate_message_delivery_and_dispatch_fee( + &millau_client, + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) + .await + { + Ok(Some(fee)) => fee, + Ok(None) => return Err("Failed to estimate message fee. Message is too heavy?".into()), + Err(error) => return Err(format!("Failed to estimate message fee: {:?}", error)), + }, + }; + + log::error!(target: "bridge", "Sending message to Rialto. Fee: {}", fee); + let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( - millau_runtime::MessageLaneCall::send_message(lane.into(), payload, fee), + millau_runtime::MessageLaneCall::send_message(lane, payload, fee), ); let signed_millau_call = Millau::sign_transaction( @@ -444,8 +463,27 @@ async fn run_command(command: cli::Command) -> Result<(), String> { } }; + let lane = lane.into(); + let fee = match fee { + Some(fee) => fee, + None => match estimate_message_delivery_and_dispatch_fee( + &rialto_client, + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) + .await + { + Ok(Some(fee)) => fee, + Ok(None) => return Err("Failed to estimate message fee. Message is too heavy?".into()), + Err(error) => return Err(format!("Failed to estimate message fee: {:?}", error)), + }, + }; + + log::info!(target: "bridge", "Sending message to Millau. Fee: {}", fee); + let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( - rialto_runtime::MessageLaneCall::send_message(lane.into(), payload, fee), + rialto_runtime::MessageLaneCall::send_message(lane, payload, fee), ); let signed_rialto_call = Rialto::sign_transaction( @@ -465,3 +503,17 @@ async fn run_command(command: cli::Command) -> Result<(), String> { Ok(()) } + +async fn estimate_message_delivery_and_dispatch_fee( + client: &relay_substrate_client::Client, + estimate_fee_method: &str, + lane: bp_message_lane::LaneId, + payload: P, +) -> Result, relay_substrate_client::Error> { + let encoded_response = client + .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .await?; + let decoded_response: Option = + Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?; + Ok(decoded_response) +} From 07c7ed9b17f36f71dd6acf99df3ee43aa81a548b Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Wed, 6 Jan 2021 10:35:50 +0100 Subject: [PATCH 0283/1210] reference correct relayer startup script in readme (#623) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 546a7835a4e4d..27e1192f9815b 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ both Substrate chains it must be run last. # In `parity-bridges-common` folder ./deployments/local-scripts/run-rialto-bridge-node.sh ./deployments/local-scripts/run-millau-bridge-node.sh -./deployments/local-scripts/run-millau-to-rialto-relay.sh +./deployments/local-scripts/relay-millau-to-rialto.sh ``` At this point you should see the relayer submitting headers from the Millau Substrate chain to the From 2eee77360e394cd7439390cd2306439bc60998f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 6 Jan 2021 18:15:41 +0100 Subject: [PATCH 0284/1210] Relayer rewards improvements (#624) * Document relayers fund existence and add root account. * Introduce initialize method instead of assuming that relayer_fund_account is always required. * cargo fmt --all * Fix benchmarks. * cargo fmt --all * Fix docs for the relayer fund account. --- bin/millau/runtime/src/lib.rs | 8 +- bin/rialto/runtime/src/lib.rs | 8 +- modules/message-lane/src/benchmarking.rs | 14 ++-- modules/message-lane/src/instant_payments.rs | 83 +++++++++++++------- modules/message-lane/src/lib.rs | 33 +++++--- primitives/message-lane/src/source_chain.rs | 8 ++ 6 files changed, 100 insertions(+), 54 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b7a294900580c..a163b933b1d3c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -312,6 +312,7 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + pub const RootAccountForPayments: Option = None; } impl pallet_message_lane::Config for Runtime { @@ -333,8 +334,11 @@ impl pallet_message_lane::Config for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_message_lane::instant_payments::InstantCurrencyPayments>; + type MessageDeliveryAndDispatchPayment = pallet_message_lane::instant_payments::InstantCurrencyPayments< + Runtime, + pallet_balances::Module, + RootAccountForPayments, + >; type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6a7562c5913cf..be1c66d98ddb1 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -419,6 +419,7 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + pub const RootAccountForPayments: Option = None; } pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInstance; @@ -440,8 +441,11 @@ impl pallet_message_lane::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_message_lane::instant_payments::InstantCurrencyPayments>; + type MessageDeliveryAndDispatchPayment = pallet_message_lane::instant_payments::InstantCurrencyPayments< + Runtime, + pallet_balances::Module, + RootAccountForPayments, + >; type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index a565b8c50fe38..d1aef1140b8db 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -16,9 +16,7 @@ //! Message lane pallet benchmarking. -use crate::{ - inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, relayer_fund_account_id, Call, Instance, -}; +use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance}; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, @@ -224,7 +222,7 @@ benchmarks_instance! { // // This is base benchmark for all other confirmations delivery benchmarks. receive_delivery_proof_for_single_message { - let relayers_fund_id = relayer_fund_account_id::(); + let relayers_fund_id = crate::Module::::relayer_fund_account_id(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -261,7 +259,7 @@ benchmarks_instance! { // as `weight(receive_delivery_proof_for_two_messages_by_single_relayer) // - weight(receive_delivery_proof_for_single_message)`. receive_delivery_proof_for_two_messages_by_single_relayer { - let relayers_fund_id = relayer_fund_account_id::(); + let relayers_fund_id = crate::Module::::relayer_fund_account_id(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -299,7 +297,7 @@ benchmarks_instance! { // as `weight(receive_delivery_proof_for_two_messages_by_two_relayers) // - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`. receive_delivery_proof_for_two_messages_by_two_relayers { - let relayers_fund_id = relayer_fund_account_id::(); + let relayers_fund_id = crate::Module::::relayer_fund_account_id(); let relayer1_id: T::AccountId = account("relayer1", 1, SEED); let relayer1_balance = T::account_balance(&relayer1_id); let relayer2_id: T::AccountId = account("relayer2", 2, SEED); @@ -431,7 +429,7 @@ benchmarks_instance! { .try_into() .expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large"); - let relayers_fund_id = relayer_fund_account_id::(); + let relayers_fund_id = crate::Module::::relayer_fund_account_id(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -470,7 +468,7 @@ benchmarks_instance! { .try_into() .expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large "); - let relayers_fund_id = relayer_fund_account_id::(); + let relayers_fund_id = crate::Module::::relayer_fund_account_id(); let confirmation_relayer_id = account("relayer", 0, SEED); let relayers: BTreeMap = (1..=i) .map(|j| { diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index 41f8b48b74749..28038af0f9b5d 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -15,57 +15,80 @@ // along with Parity Bridges Common. If not, see . //! Implementation of `MessageDeliveryAndDispatchPayment` trait on top of `Currency` trait. -//! All payments are instant. +//! +//! The payment is first transferred to a special `relayers-fund` account and only transferred +//! to the actual relayer in case confirmation is received. use bp_message_lane::source_chain::{MessageDeliveryAndDispatchPayment, Sender}; -use codec::Encode; -use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement}; -use sp_std::fmt::Debug; +use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; -/// Instant message payments made in given currency. Until claimed, fee is stored in special -/// 'relayers-fund' account. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(AccountId, Currency)>, +/// Instant message payments made in given currency. +/// +/// The balance is initally reserved in a special `relayers-fund` account, and transferred +/// to the relayer when message delivery is confirmed. +/// +/// NOTE The `relayers-fund` account must always exist i.e. be over Existential Deposit (ED; the +/// pallet enforces that) to make sure that even if the message cost is below ED it is still payed +/// to the relayer account. +/// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they +/// can receive the payment. +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, Currency, RootAccount)>, } -impl MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments +impl MessageDeliveryAndDispatchPayment + for InstantCurrencyPayments where - Currency: CurrencyT, - AccountId: Debug + Default + Encode, + T: frame_system::Config, + Currency: CurrencyT, + RootAccount: Get>, { type Error = &'static str; + fn initialize(relayer_fund_account: &T::AccountId) -> usize { + assert!( + frame_system::Module::::account_exists(relayer_fund_account), + "The relayer fund account ({:?}) must exist for the message lanes pallet to work correctly.", + relayer_fund_account, + ); + 1 + } + fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &Sender, fee: &Currency::Balance, - relayer_fund_account: &AccountId, + relayer_fund_account: &T::AccountId, ) -> Result<(), Self::Error> { - match submitter { - Sender::Signed(submitter) => { - Currency::transfer(submitter, relayer_fund_account, *fee, ExistenceRequirement::AllowDeath) - .map_err(Into::into) - } - Sender::Root => { - Err("Sending messages from Root account is not supported yet. See GitHub issue #559 for more.") - } - Sender::None => { - Err("Sending messages from None account is not supported yet. See GitHub issue #559 for more.") - } - } + let root_account = RootAccount::get(); + let account = match submitter { + Sender::Signed(submitter) => submitter, + Sender::Root | Sender::None => root_account + .as_ref() + .ok_or("Sending messages using Root or None origin is disallowed.")?, + }; + + Currency::transfer( + account, + relayer_fund_account, + *fee, + // it's fine for the submitter to go below Existential Deposit and die. + ExistenceRequirement::AllowDeath, + ) + .map_err(Into::into) } fn pay_relayer_reward( - _confirmation_relayer: &AccountId, - relayer: &AccountId, + _confirmation_relayer: &T::AccountId, + relayer: &T::AccountId, reward: &Currency::Balance, - relayer_fund_account: &AccountId, + relayer_fund_account: &T::AccountId, ) { let pay_result = Currency::transfer( &relayer_fund_account, relayer, *reward, - ExistenceRequirement::AllowDeath, + // the relayer fund account must stay above ED (needs to be pre-funded) + ExistenceRequirement::KeepAlive, ); // we can't actually do anything here, because rewards are paid as a part of unrelated transaction diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 51e29322a5541..9840048f00533 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -214,6 +214,14 @@ decl_module! { /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; + /// Ensure runtime invariants. + fn on_runtime_upgrade() -> Weight { + let reads = T::MessageDeliveryAndDispatchPayment::initialize( + &Self::relayer_fund_account_id() + ); + T::DbWeight::get().reads(reads as u64) + } + /// Change `ModuleOwner`. /// /// May only be called either by root, or by `ModuleOwner`. @@ -298,7 +306,7 @@ decl_module! { T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( &submitter, &delivery_and_dispatch_fee, - &relayer_fund_account_id::(), + &Self::relayer_fund_account_id(), ).map_err(|err| { frame_support::debug::trace!( "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", @@ -463,7 +471,7 @@ decl_module! { // reward relayers that have delivered messages // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let relayer_fund_account = relayer_fund_account_id::(); + let relayer_fund_account = Self::relayer_fund_account_id(); for (nonce_low, nonce_high, relayer) in lane_data.relayers { let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0); let nonce_end = sp_std::cmp::min(nonce_high, received_range.1); @@ -538,6 +546,17 @@ impl, I: Instance> Module { total_messages: total_unrewarded_messages(&relayers), } } + + /// AccountId of the shared relayer fund account. + /// + /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending + /// on the implementation it can be used to store relayers rewards. + /// See [InstantCurrencyPayments] for a concrete implementation. + pub fn relayer_fund_account_id() -> T::AccountId { + use sp_runtime::traits::Convert; + let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); + T::AccountIdConverter::convert(encoded_id) + } } /// Getting storage keys for messages and lanes states. These keys are normally used when building @@ -730,16 +749,6 @@ fn verify_and_decode_messages_proof, Fee, Dispatch }) } -/// AccountId of the shared relayer fund account. -/// -/// This account stores all the fees paid by submitters. Relayers are able to claim these -/// funds as at their convenience. -fn relayer_fund_account_id, I: Instance>() -> T::AccountId { - use sp_runtime::traits::Convert; - let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); - T::AccountIdConverter::convert(encoded_id) -} - #[cfg(test)] mod tests { use super::*; diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index f854b0356c130..d607ab7545cb7 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -109,4 +109,12 @@ pub trait MessageDeliveryAndDispatchPayment { reward: &Balance, relayer_fund_account: &AccountId, ); + + /// Perform some initialization in externalities-provided environment. + /// + /// For instance you may ensure that particular required accounts or storage items are present. + /// Returns the number of storage reads performed. + fn initialize(_relayer_fund_account: &AccountId) -> usize { + 0 + } } From 2f652e21f88684ae413b855554ac8016e1d992d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 6 Jan 2021 18:20:26 +0100 Subject: [PATCH 0285/1210] Add more documentation for the TargetAccount variant. (#625) --- modules/call-dispatch/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 09e49702656f1..19f1224c906cd 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -66,6 +66,16 @@ pub enum CallOrigin, Call::Transfer(X, 5))` + /// The owner of `some-source-account-id` can send that message multiple times, which would + /// result with multiple transfer calls being dispatched on the target chain. + /// So please, NEVER USE YOUR PRIVATE KEY TO SIGN SOMETHING YOU DON'T FULLY UNDERSTAND! TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature), /// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is From 760c01f7c05a006922b81a74d8c6b1d1f532beeb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 12 Jan 2021 12:20:40 +0300 Subject: [PATCH 0286/1210] `send_message` weight now depends on message size (#603) * `send_message` weight now depends on message size * fix tests * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/rialto/runtime/src/lib.rs | 20 ++-- modules/call-dispatch/src/lib.rs | 10 +- modules/message-lane/src/benchmarking.rs | 126 +++++++++++++++++++++-- modules/message-lane/src/lib.rs | 11 +- modules/message-lane/src/mock.rs | 14 ++- modules/message-lane/src/weights.rs | 95 +++++++++++------ modules/message-lane/src/weights_ext.rs | 15 ++- primitives/runtime/src/lib.rs | 9 ++ 8 files changed, 237 insertions(+), 63 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index be1c66d98ddb1..154865c6a03be 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -813,6 +813,8 @@ impl_runtime_apis! { } } + use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; + use bridge_runtime_common::messages; use pallet_message_lane::benchmarking::{ Module as MessageLaneBench, Config as MessageLaneConfig, @@ -822,6 +824,10 @@ impl_runtime_apis! { }; impl MessageLaneConfig for Runtime { + fn maximal_message_size() -> u32 { + messages::source::maximal_message_size::() + } + fn bridged_relayer_id() -> Self::InboundRelayer { Default::default() } @@ -840,24 +846,14 @@ impl_runtime_apis! { fn prepare_outbound_message( params: MessageLaneMessageParams, ) -> (millau_messages::ToMillauMessagePayload, Balance) { - use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; - use bridge_runtime_common::messages; - use pallet_message_lane::benchmarking::WORST_MESSAGE_SIZE_FACTOR; - - let max_message_size = messages::source::maximal_message_size::(); - let message_size = match params.size_factor { - 0 => 1, - factor => max_message_size / WORST_MESSAGE_SIZE_FACTOR - * sp_std::cmp::min(factor, WORST_MESSAGE_SIZE_FACTOR), - }; - let message_payload = vec![0; message_size as usize]; + let message_payload = vec![0; params.size as usize]; let dispatch_origin = pallet_bridge_call_dispatch::CallOrigin::SourceAccount( params.sender_account, ); let message = ToMillauMessagePayload { spec_version: 0, - weight: message_size as _, + weight: params.size as _, origin: dispatch_origin, call: message_payload, }; diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 19f1224c906cd..74584ee570a84 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -25,7 +25,7 @@ #![warn(missing_docs)] use bp_message_dispatch::{MessageDispatch, Weight}; -use bp_runtime::{derive_account_id, InstanceId, SourceAccount}; +use bp_runtime::{derive_account_id, InstanceId, Size, SourceAccount}; use codec::{Decode, Encode}; use frame_support::{ decl_event, decl_module, decl_storage, @@ -104,6 +104,14 @@ pub struct MessagePayload Size + for MessagePayload> +{ + fn size_hint(&self) -> u32 { + self.call.len() as _ + } +} + /// The module configuration trait. pub trait Config: frame_system::Config { /// The overarching event type. diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index d1aef1140b8db..3243a25f1631d 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -27,8 +27,6 @@ use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, ops::RangeInclusive, prelude::*}; -/// Message crafted with this size factor should be the largest possible message. -pub const WORST_MESSAGE_SIZE_FACTOR: u32 = 1000; /// Fee paid by submitter for single message delivery. const MESSAGE_FEE: u32 = 1_000_000; @@ -39,10 +37,8 @@ pub struct Module, I: crate::Instance>(crate::Module); /// Benchmark-specific message parameters. pub struct MessageParams { - /// Size factor of the message payload. Message payload grows with every factor - /// increment. Zero is the smallest possible message and the `WORST_MESSAGE_SIZE_FACTOR` is - /// largest possible message. - pub size_factor: u32, + /// Size of the message payload. + pub size: u32, /// Message sender account. pub sender_account: ThisAccountId, } @@ -67,6 +63,8 @@ pub struct MessageDeliveryProofParams { /// Trait that must be implemented by runtime. pub trait Config: crate::Config { + /// Get maximal size of the message payload. + fn maximal_message_size() -> u32; /// Return id of relayer account at the bridged chain. fn bridged_relayer_id() -> Self::InboundRelayer; /// Return balance of given account. @@ -101,10 +99,12 @@ benchmarks_instance! { // * outbound lane already has state, so it needs to be read and decoded; // * relayers fund account does not exists (in practice it needs to exist in production environment); // * maximal number of messages is being pruned during the call; - // * message size is maximal for the target chain. + // * message size is minimal for the target chain. // - // Results of this benchmark may be directly used in the `send_message`. - send_message_worst_case { + // Result of this benchmark is used as a base weight for `send_message` call. Then the 'message weight' + // (estimated using `send_half_maximal_message_worst_case` and `send_maximal_message_worst_case`) is + // added. + send_minimal_message_worst_case { let lane_id = bench_lane_id(); let sender = account("sender", 0, SEED); T::endow_account(&sender); @@ -116,7 +116,81 @@ benchmarks_instance! { confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); let (payload, fee) = T::prepare_outbound_message(MessageParams { - size_factor: WORST_MESSAGE_SIZE_FACTOR, + size: 0, + sender_account: sender.clone(), + }); + }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) + verify { + assert_eq!( + crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + T::MaxMessagesToPruneAtOnce::get() + 1, + ); + } + + // Benchmark `send_message` extrinsic with the worst possible conditions: + // * outbound lane already has state, so it needs to be read and decoded; + // * relayers fund account does not exists (in practice it needs to exist in production environment); + // * maximal number of messages is being pruned during the call; + // * message size is 1KB. + // + // With single KB of message size, the weight of the call is increased (roughly) by + // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. + send_1_kb_message_worst_case { + let lane_id = bench_lane_id(); + let sender = account("sender", 0, SEED); + T::endow_account(&sender); + + // 'send' messages that are to be pruned when our message is sent + for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { + send_regular_message::(); + } + confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); + + let size = 1024; + assert!( + T::maximal_message_size() > size, + "This benchmark can only be used with runtime that accepts 1KB messages", + ); + + let (payload, fee) = T::prepare_outbound_message(MessageParams { + size, + sender_account: sender.clone(), + }); + }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) + verify { + assert_eq!( + crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + T::MaxMessagesToPruneAtOnce::get() + 1, + ); + } + + // Benchmark `send_message` extrinsic with the worst possible conditions: + // * outbound lane already has state, so it needs to be read and decoded; + // * relayers fund account does not exists (in practice it needs to exist in production environment); + // * maximal number of messages is being pruned during the call; + // * message size is 16KB. + // + // With single KB of message size, the weight of the call is increased (roughly) by + // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. + send_16_kb_message_worst_case { + let lane_id = bench_lane_id(); + let sender = account("sender", 0, SEED); + T::endow_account(&sender); + + // 'send' messages that are to be pruned when our message is sent + for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { + send_regular_message::(); + } + confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); + + let size = 16 * 1024; + assert!( + T::maximal_message_size() > size, + "This benchmark can only be used with runtime that accepts 16KB messages", + ); + + let (payload, fee) = T::prepare_outbound_message(MessageParams { + size, sender_account: sender.clone(), }); }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) @@ -340,6 +414,38 @@ benchmarks_instance! { // Benchmarks for manual checks. // + // Benchmark `send_message` extrinsic with following conditions: + // * outbound lane already has state, so it needs to be read and decoded; + // * relayers fund account does not exists (in practice it needs to exist in production environment); + // * maximal number of messages is being pruned during the call; + // * message size varies from minimal to maximal for the target chain. + // + // Results of this benchmark may be used to check how message size affects `send_message` performance. + send_messages_of_various_lengths { + let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); + + let lane_id = bench_lane_id(); + let sender = account("sender", 0, SEED); + T::endow_account(&sender); + + // 'send' messages that are to be pruned when our message is sent + for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { + send_regular_message::(); + } + confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); + + let (payload, fee) = T::prepare_outbound_message(MessageParams { + size: i as _, + sender_account: sender.clone(), + }); + }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) + verify { + assert_eq!( + crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + T::MaxMessagesToPruneAtOnce::get() + 1, + ); + } + // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 9840048f00533..88dd033cbcacb 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -39,7 +39,6 @@ pub use crate::weights_ext::{ensure_weights_are_correct, WeightInfoExt}; use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; -use crate::weights::WeightInfo; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, @@ -47,6 +46,7 @@ use bp_message_lane::{ total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayersState, }; +use bp_runtime::Size; use codec::{Decode, Encode}; use frame_support::{ decl_error, decl_event, decl_module, decl_storage, ensure, @@ -104,7 +104,7 @@ pub trait Config: frame_system::Config { type MaxUnconfirmedMessagesAtInboundLane: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. - type OutboundPayload: Parameter; + type OutboundPayload: Parameter + Size; /// Message fee type of outbound messages. This fee is paid on this chain. type OutboundMessageFee: From + Parameter + SaturatingAdd + Zero; @@ -261,10 +261,9 @@ decl_module! { } /// Send message over lane. - /// - /// The weight of the call assumes that the largest possible message is sent in - /// worst possible environment. - #[weight = T::WeightInfo::send_message_worst_case()] + #[weight = T::WeightInfo::send_message_overhead() + .saturating_add(T::WeightInfo::send_message_size_overhead(Size::size_hint(payload))) + ] pub fn send_message( origin, lane_id: LaneId, diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 59ca1ab0b769c..f4d98f4c6dc42 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -21,6 +21,7 @@ use bp_message_lane::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, }; +use bp_runtime::Size; use codec::{Decode, Encode}; use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; use sp_core::H256; @@ -32,7 +33,8 @@ use sp_runtime::{ use std::collections::BTreeMap; pub type AccountId = u64; -pub type TestPayload = (u64, Weight); +#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)] +pub struct TestPayload(pub u64, pub Weight); pub type TestMessageFee = u64; pub type TestRelayer = u64; @@ -123,6 +125,12 @@ impl Config for TestRuntime { type MessageDispatch = TestMessageDispatch; } +impl Size for TestPayload { + fn size_hint(&self) -> u32 { + 16 + } +} + /// Account id of test relayer. pub const TEST_RELAYER_A: AccountId = 100; @@ -139,10 +147,10 @@ pub const TEST_ERROR: &str = "Test error"; pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; /// Regular message payload. -pub const REGULAR_PAYLOAD: TestPayload = (0, 50); +pub const REGULAR_PAYLOAD: TestPayload = TestPayload(0, 50); /// Payload that is rejected by `TestTargetHeaderChain`. -pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = (1, 50); +pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = TestPayload(1, 50); /// Vec of proved messages, grouped by lane. pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages>)>; diff --git a/modules/message-lane/src/weights.rs b/modules/message-lane/src/weights.rs index d819e5d574433..016af708a66b5 100644 --- a/modules/message-lane/src/weights.rs +++ b/modules/message-lane/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_message_lane //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0 -//! DATE: 2020-12-22, STEPS: [50, ], REPEAT: 20 +//! DATE: 2020-12-28, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("local"), DB CACHE: 128 @@ -48,13 +48,16 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_message_lane. pub trait WeightInfo { - fn send_message_worst_case() -> Weight; + fn send_minimal_message_worst_case() -> Weight; + fn send_1_kb_message_worst_case() -> Weight; + fn send_16_kb_message_worst_case() -> Weight; fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; fn receive_single_message_proof_with_outbound_lane_state() -> Weight; fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; + fn send_messages_of_various_lengths(i: u32) -> Weight; fn receive_multiple_messages_proof(i: u32) -> Weight; fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight; @@ -64,63 +67,79 @@ pub trait WeightInfo { /// Weights for pallet_message_lane using the Rialto node and recommended hardware. pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { - fn send_message_worst_case() -> Weight { - (4_289_189_000 as Weight) + fn send_minimal_message_worst_case() -> Weight { + (249_486_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(12 as Weight)) + } + fn send_1_kb_message_worst_case() -> Weight { + (257_454_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(12 as Weight)) + } + fn send_16_kb_message_worst_case() -> Weight { + (344_817_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_single_message_proof() -> Weight { - (186_909_000 as Weight) + (197_341_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (339_281_000 as Weight) + (341_056_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (215_607_000 as Weight) + (227_735_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (202_085_000 as Weight) + (208_305_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (213_142_000 as Weight) + (239_511_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (300_159_000 as Weight) + (341_307_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } + fn send_messages_of_various_lengths(i: u32) -> Weight { + (206_352_000 as Weight) + .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(12 as Weight)) + } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((150_558_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((157_613_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((204_949_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((166_416_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (79_087_000 as Weight) - .saturating_add((12_889_000 as Weight).saturating_mul(i as Weight)) + (107_561_000 as Weight) + .saturating_add((12_218_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (131_794_000 as Weight) - .saturating_add((108_620_000 as Weight).saturating_mul(i as Weight)) + (124_619_000 as Weight) + .saturating_add((104_750_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(2 as Weight)) @@ -130,63 +149,79 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { - fn send_message_worst_case() -> Weight { - (4_289_189_000 as Weight) + fn send_minimal_message_worst_case() -> Weight { + (249_486_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + } + fn send_1_kb_message_worst_case() -> Weight { + (257_454_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + } + fn send_16_kb_message_worst_case() -> Weight { + (344_817_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_single_message_proof() -> Weight { - (186_909_000 as Weight) + (197_341_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (339_281_000 as Weight) + (341_056_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (215_607_000 as Weight) + (227_735_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (202_085_000 as Weight) + (208_305_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (213_142_000 as Weight) + (239_511_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (300_159_000 as Weight) + (341_307_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } + fn send_messages_of_various_lengths(i: u32) -> Weight { + (206_352_000 as Weight) + .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((150_558_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((157_613_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((204_949_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((166_416_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (79_087_000 as Weight) - .saturating_add((12_889_000 as Weight).saturating_mul(i as Weight)) + (107_561_000 as Weight) + .saturating_add((12_218_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (131_794_000 as Weight) - .saturating_add((108_620_000 as Weight).saturating_mul(i as Weight)) + (124_619_000 as Weight) + .saturating_add((104_750_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) diff --git a/modules/message-lane/src/weights_ext.rs b/modules/message-lane/src/weights_ext.rs index 5e1f1c88615c8..b9b33a6f21f9e 100644 --- a/modules/message-lane/src/weights_ext.rs +++ b/modules/message-lane/src/weights_ext.rs @@ -23,7 +23,8 @@ use frame_support::weights::Weight; /// Ensure that weights from `WeightInfoExt` implementation are looking correct. pub fn ensure_weights_are_correct() { - assert_ne!(W::send_message_worst_case(), 0); + assert_ne!(W::send_message_overhead(), 0); + assert_ne!(W::send_message_size_overhead(0), 0); assert_ne!(W::receive_messages_proof_overhead(), 0); assert_ne!(W::receive_messages_proof_messages_overhead(1), 0); @@ -36,6 +37,18 @@ pub fn ensure_weights_are_correct() { /// Extended weight info. pub trait WeightInfoExt: WeightInfo { + /// Returns weight of message send transaction (`send_message`). + fn send_message_overhead() -> Weight { + Self::send_minimal_message_worst_case() + } + + /// Returns weight that needs to be accounted when message of given size is sent (`send_message`). + fn send_message_size_overhead(message_size: u32) -> Weight { + let message_size_in_kb = (1024u64 + message_size as u64) / 1024; + let single_kb_weight = (Self::send_16_kb_message_worst_case() - Self::send_1_kb_message_worst_case()) / 15; + message_size_in_kb * single_kb_weight + } + /// Returns weight overhead of message delivery transaction (`receive_messages_proof`). fn receive_messages_proof_overhead() -> Weight { let weight_of_two_messages_and_two_tx_overheads = Self::receive_single_message_proof().saturating_mul(2); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index e23a8d887cec5..b0a352b7dd2cc 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -95,3 +95,12 @@ where 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; +} From fedd27cb42785814723dad4ce2ef8ebdee22e4d7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 12 Jan 2021 12:51:20 +0000 Subject: [PATCH 0287/1210] Bump substrate & deps (#637) --- bin/millau/node/src/service.rs | 8 ++++---- bin/millau/runtime/src/lib.rs | 3 +++ bin/rialto/node/src/service.rs | 8 ++++---- bin/rialto/runtime/src/lib.rs | 3 +++ modules/call-dispatch/src/lib.rs | 1 + modules/currency-exchange/src/benchmarking.rs | 2 -- modules/currency-exchange/src/lib.rs | 1 + modules/ethereum-contract/builtin/Cargo.toml | 2 +- modules/ethereum/src/benchmarking.rs | 2 -- modules/ethereum/src/mock.rs | 1 + modules/ethereum/src/test_utils.rs | 8 ++++---- modules/ethereum/src/verification.rs | 10 +++++----- modules/message-lane/src/benchmarking.rs | 2 -- modules/message-lane/src/mock.rs | 1 + modules/shift-session-manager/src/lib.rs | 1 + modules/substrate/src/mock.rs | 1 + primitives/ethereum-poa/Cargo.toml | 12 ++++++------ primitives/ethereum-poa/src/lib.rs | 8 ++++---- primitives/ethereum-poa/src/signatures.rs | 4 ++-- primitives/millau/Cargo.toml | 4 ++-- relays/ethereum-client/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 4 ++-- 22 files changed, 47 insertions(+), 41 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 9cbd2b06a9b45..d5dc945cad24a 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -134,8 +134,8 @@ pub fn new_full(mut config: Configuration) -> Result config .network - .notifications_protocols - .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config()); let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -336,8 +336,8 @@ pub fn new_light(mut config: Configuration) -> Result config .network - .notifications_protocols - .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config()); let select_chain = sc_consensus::LongestChain::new(backend.clone()); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index a163b933b1d3c..9969eb96fa938 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -157,6 +157,7 @@ parameter_types! { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; + pub const SS58Prefix: u8 = 86; } impl frame_system::Config for Runtime { @@ -203,6 +204,8 @@ impl frame_system::Config for Runtime { type BlockLength = bp_millau::BlockLength; /// The weight of database operations that the runtime can invoke. type DbWeight = DbWeight; + /// The designated SS58 prefix of this chain. + type SS58Prefix = SS58Prefix; } impl pallet_aura::Config for Runtime { diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index c235a8e757f8d..d88f37ac0a80d 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -134,8 +134,8 @@ pub fn new_full(mut config: Configuration) -> Result config .network - .notifications_protocols - .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config()); let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -335,8 +335,8 @@ pub fn new_light(mut config: Configuration) -> Result config .network - .notifications_protocols - .push(sc_finality_grandpa::GRANDPA_PROTOCOL_NAME.into()); + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config()); let select_chain = sc_consensus::LongestChain::new(backend.clone()); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 154865c6a03be..e80281560c8a6 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -165,6 +165,7 @@ parameter_types! { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; + pub const SS58Prefix: u8 = 84; } impl frame_system::Config for Runtime { @@ -211,6 +212,8 @@ impl frame_system::Config for Runtime { type BlockLength = bp_rialto::BlockLength; /// The weight of database operations that the runtime can invoke. type DbWeight = DbWeight; + /// The designated SS58 prefix of this chain. + type SS58Prefix = SS58Prefix; } impl pallet_aura::Config for Runtime { diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 74584ee570a84..a0c2af0572524 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -424,6 +424,7 @@ mod tests { type BlockWeights = (); type BlockLength = (); type DbWeight = (); + type SS58Prefix = (); } impl Config for TestRuntime { diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index 73304ff40bc38..8b38d42eaa7ec 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -54,8 +54,6 @@ pub trait Config: CurrencyExchangeConfig { } benchmarks_instance! { - _ { } - // Benchmark `import_peer_transaction` extrinsic with the best possible conditions: // * Proof is the transaction itself. // * Transaction has minimal size. diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 4ff88e7b03ab3..d3e12bff3902b 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -347,6 +347,7 @@ mod tests { type BlockWeights = (); type BlockLength = (); type DbWeight = (); + type SS58Prefix = (); } impl Config for TestRuntime { diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 101a03fb8c26f..9275d10bf6638 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.4" } -ethereum-types = "0.9.2" +ethereum-types = "0.10.0" finality-grandpa = "0.12.3" hex = "0.4" log = "0.4.11" diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 35a202f3f2fe7..5de6e80f16a1f 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -26,8 +26,6 @@ use frame_benchmarking::benchmarks_instance; use frame_system::RawOrigin; benchmarks_instance! { - _ { } - // Benchmark `import_unsigned_header` extrinsic with the best possible conditions: // * Parent header is finalized. // * New header doesn't require receipts. diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index e6d105070fc32..af99d476b8802 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -66,6 +66,7 @@ impl frame_system::Config for TestRuntime { type BlockWeights = (); type BlockLength = (); type DbWeight = (); + type SS58Prefix = (); } parameter_types! { diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index f41652f570813..ad4019412892d 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -53,7 +53,7 @@ impl HeaderBuilder { Self { header: AuraHeader { gas_limit: GAS_LIMIT.into(), - seal: vec![bp_eth_poa::rlp_encode(¤t_step), vec![]], + seal: vec![bp_eth_poa::rlp_encode(¤t_step).to_vec(), vec![]], ..Default::default() }, parent_header: Default::default(), @@ -95,7 +95,7 @@ impl HeaderBuilder { pub fn with_number(number: u64) -> Self { Self::with_parent(&AuraHeader { number: number - 1, - seal: vec![bp_eth_poa::rlp_encode(&(number - 1)), vec![]], + seal: vec![bp_eth_poa::rlp_encode(&(number - 1)).to_vec(), vec![]], ..Default::default() }) } @@ -109,7 +109,7 @@ impl HeaderBuilder { parent_hash: parent_header.compute_hash(), number: parent_header.number + 1, gas_limit: GAS_LIMIT.into(), - seal: vec![bp_eth_poa::rlp_encode(¤t_step), vec![]], + seal: vec![bp_eth_poa::rlp_encode(¤t_step).to_vec(), vec![]], difficulty: calculate_score(parent_step, current_step, 0), ..Default::default() }, @@ -120,7 +120,7 @@ impl HeaderBuilder { /// Update step of this header. pub fn step(mut self, step: u64) -> Self { let parent_step = self.parent_header.step(); - self.header.seal[0] = rlp_encode(&step); + self.header.seal[0] = rlp_encode(&step).to_vec(); self.header.difficulty = parent_step .map(|parent_step| calculate_score(parent_step, step, 0)) .unwrap_or_default(); diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index aac1d20067b71..3882e6b529edf 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -637,11 +637,11 @@ mod tests { assert_eq!(default_verify(&header), Err(Error::MissingStep)); // when step is the same as for the parent block - header.seal[0] = rlp_encode(&42u64); + header.seal[0] = rlp_encode(&42u64).to_vec(); assert_eq!(default_verify(&header), Err(Error::DoubleVote)); // when step is OK - header.seal[0] = rlp_encode(&43u64); + header.seal[0] = rlp_encode(&43u64).to_vec(); assert_ne!(default_verify(&header), Err(Error::DoubleVote)); // now check with validate_step check enabled @@ -649,12 +649,12 @@ mod tests { config.validate_step_transition = 0; // when step is lesser that for the parent block - header.seal[0] = rlp_encode(&40u64); + header.seal[0] = rlp_encode(&40u64).to_vec(); header.seal = vec![vec![40], vec![]]; assert_eq!(verify_with_config(&config, &header), Err(Error::DoubleVote)); // when step is OK - header.seal[0] = rlp_encode(&44u64); + header.seal[0] = rlp_encode(&44u64).to_vec(); assert_ne!(verify_with_config(&config, &header), Err(Error::DoubleVote)); } @@ -720,7 +720,7 @@ mod tests { // when header signature is invalid let mut header = good_header.clone(); - header.seal[1] = rlp_encode(&H520::default()); + header.seal[1] = rlp_encode(&H520::default()).to_vec(); assert_eq!(default_verify(&header), Err(Error::NotValidator)); // when everything is OK diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index 3243a25f1631d..4b0df8213a2aa 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -89,8 +89,6 @@ pub trait Config: crate::Config { } benchmarks_instance! { - _ { } - // // Benchmarks that are used directly by the runtime. // diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index f4d98f4c6dc42..5b24a29eb9b28 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -93,6 +93,7 @@ impl frame_system::Config for TestRuntime { type BlockWeights = (); type BlockLength = (); type DbWeight = (); + type SS58Prefix = (); } parameter_types! { diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 88928986f0df0..102c3fcbc1679 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -134,6 +134,7 @@ mod tests { type BlockWeights = (); type BlockLength = (); type DbWeight = (); + type SS58Prefix = (); } parameter_types! { diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index 7c2b5429ed982..e6415aae8e411 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -67,6 +67,7 @@ impl frame_system::Config for TestRuntime { type DbWeight = (); type BlockWeights = (); type BlockLength = (); + type SS58Prefix = (); } impl Config for TestRuntime { diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 724f5594cdf42..726ca04c74bc4 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -8,16 +8,16 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } -ethbloom = { version = "0.8", default-features = false } -fixed-hash = { version = "0.5", default-features = false } +ethbloom = { version = "0.10.0", default-features = false, features = ["rlp"] } +fixed-hash = { version = "0.7", default-features = false } hash-db = { version = "0.15.2", default-features = false } -impl-rlp = { version = "0.2", default-features = false } -impl-serde = { version = "0.2.3", optional = true } +impl-rlp = { version = "0.3", default-features = false } +impl-serde = { version = "0.3.1", optional = true } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } parity-bytes = { version = "0.1", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } -primitive-types = { version = "0.7", default-features = false, features = ["codec", "rlp"] } -rlp = { version = "0.4", default-features = false } +primitive-types = { version = "0.8", default-features = false, features = ["codec", "rlp"] } +rlp = { version = "0.5", default-features = false } serde = { version = "1.0", optional = true } serde-big-array = { version = "0.2", optional = true } triehash = { version = "0.8.2", default-features = false } diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 63d2dda207e83..dc65ac432b144 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -289,7 +289,7 @@ impl AuraHeader { } } - s.out() + s.out().to_vec() } } @@ -320,7 +320,7 @@ impl UnsignedTransaction { pub fn rlp(&self, chain_id: Option) -> Bytes { let mut stream = RlpStream::new_list(if chain_id.is_some() { 9 } else { 6 }); self.rlp_to(chain_id, &mut stream); - stream.out() + stream.out().to_vec() } /// Encode to given rlp stream. @@ -392,7 +392,7 @@ impl Receipt { s.append(&log.data); } - s.out() + s.out().to_vec() } } @@ -412,7 +412,7 @@ impl SealedEmptyStep { for empty_step in empty_steps { s.begin_list(2).append(&empty_step.signature).append(&empty_step.step); } - s.out() + s.out().to_vec() } } diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs index cab8fdfa2f435..21c6f3f860fff 100644 --- a/primitives/ethereum-poa/src/signatures.rs +++ b/primitives/ethereum-poa/src/signatures.rs @@ -49,7 +49,7 @@ impl SignHeader for AuraHeader { let message = self.seal_hash(false).unwrap(); let signature = sign(author, message); - self.seal[1] = rlp_encode(&signature); + self.seal[1] = rlp_encode(&signature).to_vec(); self } @@ -74,7 +74,7 @@ impl SignTransaction for UnsignedTransaction { stream.append(&signature_v); stream.append(&signature_r); stream.append(&signature_s); - stream.out() + stream.out().to_vec() } } diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index d512fc632a515..b72a0f4018b64 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -12,11 +12,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-message-lane = { path = "../message-lane", default-features = false } bp-runtime = { path = "../runtime", default-features = false } -fixed-hash = { version = "0.6.1", default-features = false } +fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.4.2", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.8.0", default-features = false, features = ["primitive-types"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/relays/ethereum-client/Cargo.toml b/relays/ethereum-client/Cargo.toml index e1ae2a8446aac..ad50a18e3967a 100644 --- a/relays/ethereum-client/Cargo.toml +++ b/relays/ethereum-client/Cargo.toml @@ -14,4 +14,4 @@ jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shar libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } -web3 = { version = "0.14", default-features = false } +web3 = { version = "0.15", default-features = false } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4b13ff5d24794..4ff9430b4a1f1 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -12,9 +12,9 @@ async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } env_logger = "0.8.2" -ethabi = "12.0" +ethabi = "13.0" ethabi-contract = "11.0" -ethabi-derive = "12.0" +ethabi-derive = "13.0" futures = "0.3.8" hex = "0.4" hex-literal = "0.3" From 66a9c0d78f8ac7b8c7d4550908eff02bea99e7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 12 Jan 2021 22:27:53 +0100 Subject: [PATCH 0288/1210] Remove redundant data from InboundLaneData (#638) * Remove latest_*_nonce. * cargo fmt --all * Fix tests. * cargo fmt --all * Fix benchmarking. * Update docs. --- modules/message-lane/src/benchmarking.rs | 18 ++++------ modules/message-lane/src/inbound_lane.rs | 42 +++++++++++----------- modules/message-lane/src/lib.rs | 35 +++++++++--------- primitives/message-lane/src/lib.rs | 46 +++++++++++++++++------- 4 files changed, 78 insertions(+), 63 deletions(-) diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index 4b0df8213a2aa..c9a27a4d9e2f2 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -311,8 +311,7 @@ benchmarks_instance! { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(), - latest_received_nonce: 1, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) @@ -349,8 +348,7 @@ benchmarks_instance! { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(), - latest_received_nonce: 2, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) @@ -392,8 +390,7 @@ benchmarks_instance! { (1, 1, relayer1_id.clone()), (2, 2, relayer2_id.clone()), ].into_iter().collect(), - latest_received_nonce: 2, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) @@ -552,8 +549,7 @@ benchmarks_instance! { lane: bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(), - latest_received_nonce: i as MessageNonce, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) @@ -601,8 +597,7 @@ benchmarks_instance! { .enumerate() .map(|(j, relayer_id)| (j as MessageNonce + 1, j as MessageNonce + 1, relayer_id.clone())) .collect(), - latest_received_nonce: i as MessageNonce, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } }); }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) @@ -637,7 +632,6 @@ fn receive_messages, I: Instance>(nonce: MessageNonce) { let mut inbound_lane_storage = inbound_lane_storage::(bench_lane_id()); inbound_lane_storage.set_data(InboundLaneData { relayers: vec![(1, nonce, T::bridged_relayer_id())].into_iter().collect(), - latest_received_nonce: nonce, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, }); } diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/message-lane/src/inbound_lane.rs index 10ec2f54a20fe..7359aa4ed188a 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/message-lane/src/inbound_lane.rs @@ -55,20 +55,23 @@ impl InboundLane { /// Receive state of the corresponding outbound lane. pub fn receive_state_update(&mut self, outbound_lane_data: OutboundLaneData) -> Option { let mut data = self.storage.data(); - if outbound_lane_data.latest_received_nonce > data.latest_received_nonce { + let last_delivered_nonce = data.last_delivered_nonce(); + + if outbound_lane_data.latest_received_nonce > last_delivered_nonce { // this is something that should never happen if proofs are correct return None; } - if outbound_lane_data.latest_received_nonce <= data.latest_confirmed_nonce { + if outbound_lane_data.latest_received_nonce <= data.last_confirmed_nonce { return None; } - data.latest_confirmed_nonce = outbound_lane_data.latest_received_nonce; + let new_confirmed_nonce = outbound_lane_data.latest_received_nonce; + data.last_confirmed_nonce = new_confirmed_nonce; // Firstly, remove all of the records where higher nonce <= new confirmed nonce while data .relayers .front() - .map(|(_, nonce_high, _)| *nonce_high <= data.latest_confirmed_nonce) + .map(|(_, nonce_high, _)| *nonce_high <= new_confirmed_nonce) .unwrap_or(false) { data.relayers.pop_front(); @@ -76,8 +79,8 @@ impl InboundLane { // Secondly, update the next record with lower nonce equal to new confirmed nonce if needed. // Note: There will be max. 1 record to update as we don't allow messages from relayers to overlap. match data.relayers.front_mut() { - Some((nonce_low, _, _)) if *nonce_low < data.latest_confirmed_nonce => { - *nonce_low = data.latest_confirmed_nonce + 1; + Some((nonce_low, _, _)) if *nonce_low < new_confirmed_nonce => { + *nonce_low = new_confirmed_nonce + 1; } _ => {} } @@ -94,7 +97,7 @@ impl InboundLane { message_data: DispatchMessageData, ) -> bool { let mut data = self.storage.data(); - let is_correct_message = nonce == data.latest_received_nonce + 1; + let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { return false; } @@ -105,13 +108,11 @@ impl InboundLane { } // if there are more unconfirmed messages than we may accept, reject this message - let unconfirmed_messages_count = nonce.saturating_sub(data.latest_confirmed_nonce); + let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce); if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { return false; } - data.latest_received_nonce = nonce; - let push_new = match data.relayers.back_mut() { Some((_, nonce_high, last_relayer)) if last_relayer == &relayer => { *nonce_high = nonce; @@ -173,7 +174,7 @@ mod tests { None, ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 0); + assert_eq!(lane.storage.data().last_confirmed_nonce, 0); }); } @@ -191,7 +192,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!( lane.receive_state_update(OutboundLaneData { @@ -200,7 +201,7 @@ mod tests { }), None, ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); }); } @@ -211,7 +212,7 @@ mod tests { receive_regular_message(&mut lane, 1); receive_regular_message(&mut lane, 2); receive_regular_message(&mut lane, 3); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 0); + assert_eq!(lane.storage.data().last_confirmed_nonce, 0); assert_eq!(lane.storage.data().relayers, vec![(1, 3, TEST_RELAYER_A)]); assert_eq!( @@ -221,7 +222,7 @@ mod tests { }), Some(2), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 2); + assert_eq!(lane.storage.data().last_confirmed_nonce, 2); assert_eq!(lane.storage.data().relayers, vec![(3, 3, TEST_RELAYER_A)]); assert_eq!( @@ -231,7 +232,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!(lane.storage.data().relayers, vec![]); }); } @@ -242,8 +243,7 @@ mod tests { let mut lane = inbound_lane::(TEST_LANE_ID); let mut seed_storage_data = lane.storage.data(); // Prepare data - seed_storage_data.latest_confirmed_nonce = 0; - seed_storage_data.latest_received_nonce = 5; + seed_storage_data.last_confirmed_nonce = 0; seed_storage_data.relayers.push_back((1, 1, TEST_RELAYER_A)); // Simulate messages batch (2, 3, 4) from relayer #2 seed_storage_data.relayers.push_back((2, 4, TEST_RELAYER_B)); @@ -257,7 +257,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().latest_confirmed_nonce, 3); + assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!( lane.storage.data().relayers, vec![(4, 4, TEST_RELAYER_B), (5, 5, TEST_RELAYER_C)] @@ -274,7 +274,7 @@ mod tests { 10, message_data(REGULAR_PAYLOAD).into() )); - assert_eq!(lane.storage.data().latest_received_nonce, 0); + assert_eq!(lane.storage.data().last_delivered_nonce(), 0); }); } @@ -391,7 +391,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); receive_regular_message(&mut lane, 1); - assert_eq!(lane.storage.data().latest_received_nonce, 1); + assert_eq!(lane.storage.data().last_delivered_nonce(), 1); }); } } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 88dd033cbcacb..10b3ec22c226d 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -464,7 +464,8 @@ decl_module! { // mark messages as delivered let mut lane = outbound_lane::(lane_id); - let received_range = lane.confirm_delivery(lane_data.latest_received_nonce); + let last_delivered_nonce = lane_data.last_delivered_nonce(); + let received_range = lane.confirm_delivery(last_delivered_nonce); if let Some(received_range) = received_range { Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); @@ -499,7 +500,7 @@ decl_module! { frame_support::debug::trace!( "Received messages delivery proof up to (and including) {} at lane {:?}", - lane_data.latest_received_nonce, + last_delivered_nonce, lane_id, ); @@ -526,12 +527,12 @@ impl, I: Instance> Module { /// Get nonce of latest received message at given inbound lane. pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).latest_received_nonce + InboundLanes::::get(&lane).last_delivered_nonce() } /// Get nonce of latest confirmed message at given inbound lane. pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).latest_confirmed_nonce + InboundLanes::::get(&lane).last_confirmed_nonce } /// Get state of unrewarded relayers set. @@ -795,7 +796,7 @@ mod tests { Ok(( TEST_LANE_ID, InboundLaneData { - latest_received_nonce: 1, + last_confirmed_nonce: 1, ..Default::default() }, )), @@ -905,7 +906,7 @@ mod tests { Ok(( TEST_LANE_ID, InboundLaneData { - latest_received_nonce: 1, + last_confirmed_nonce: 1, ..Default::default() }, )), @@ -977,7 +978,7 @@ mod tests { REGULAR_PAYLOAD.1, )); - assert_eq!(InboundLanes::::get(TEST_LANE_ID).latest_received_nonce, 1); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1); }); } @@ -988,8 +989,7 @@ mod tests { InboundLanes::::insert( TEST_LANE_ID, InboundLaneData { - latest_confirmed_nonce: 8, - latest_received_nonce: 10, + last_confirmed_nonce: 8, relayers: vec![(9, 9, TEST_RELAYER_A), (10, 10, TEST_RELAYER_B)] .into_iter() .collect(), @@ -1022,11 +1022,10 @@ mod tests { assert_eq!( InboundLanes::::get(TEST_LANE_ID), InboundLaneData { + last_confirmed_nonce: 9, relayers: vec![(10, 10, TEST_RELAYER_B), (11, 11, TEST_RELAYER_A)] .into_iter() .collect(), - latest_received_nonce: 11, - latest_confirmed_nonce: 9, }, ); assert_eq!( @@ -1108,7 +1107,6 @@ mod tests { TEST_LANE_ID, InboundLaneData { relayers: vec![(1, 1, TEST_RELAYER_A)].into_iter().collect(), - latest_received_nonce: 1, ..Default::default() } )), @@ -1136,7 +1134,6 @@ mod tests { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] .into_iter() .collect(), - latest_received_nonce: 2, ..Default::default() } )), @@ -1180,7 +1177,6 @@ mod tests { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] .into_iter() .collect(), - latest_received_nonce: 2, ..Default::default() } )), @@ -1203,7 +1199,6 @@ mod tests { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] .into_iter() .collect(), - latest_received_nonce: 2, ..Default::default() } )), @@ -1232,7 +1227,10 @@ mod tests { 0, // weight may be zero in this case (all messages are improperly encoded) ),); - assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 1,); + assert_eq!( + InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), + 1, + ); }); } @@ -1255,7 +1253,10 @@ mod tests { REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1, ),); - assert_eq!(InboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 3,); + assert_eq!( + InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), + 3, + ); }); } diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 4edf936bff3b8..9dba82a71c200 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -74,34 +74,54 @@ pub struct Message { /// Inbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct InboundLaneData { - /// Identifiers of relayers and messages that they have delivered (ordered by message nonce). - /// It is guaranteed to have at most N entries, where N is configured at module level. If - /// there are N entries in this vec, then: + /// Identifiers of relayers and messages that they have delivered to this lane (ordered by message nonce). + /// + /// This serves as a helper storage item, to allow the source chain to easily pay rewards + /// to the relayers who succesfuly delivered messages to the target chain (inbound lane). + /// + /// It is guaranteed to have at most N entries, where N is configured at the module level. + /// If there are N entries in this vec, then: /// 1) all incoming messages are rejected if they're missing corresponding `proof-of(outbound-lane.state)`; - /// 2) all incoming messages are rejected if `proof-of(outbound-lane.state).latest_received_nonce` is - /// equal to `this.latest_confirmed_nonce`. - /// Given what is said above, all nonces in this queue are in range (latest_confirmed_nonce; latest_received_nonce]. + /// 2) all incoming messages are rejected if `proof-of(outbound-lane.state).last_delivered_nonce` is + /// equal to `self.last_confirmed_nonce`. + /// Given what is said above, all nonces in this queue are in range: + /// `(self.last_confirmed_nonce; self.last_delivered_nonce()]`. /// /// When a relayer sends a single message, both of MessageNonces are the same. /// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce. - /// Multiple dispatches from the same relayer one are allowed. + /// Multiple dispatches from the same relayer are allowed. pub relayers: VecDeque<(MessageNonce, MessageNonce, RelayerId)>, - /// Nonce of latest message that we have received from bridged chain. - pub latest_received_nonce: MessageNonce, - /// Nonce of latest message that has been confirmed to the bridged chain. - pub latest_confirmed_nonce: MessageNonce, + + /// Nonce of the last message that + /// a) has been delivered to the target (this) chain and + /// b) the delivery has been confirmed on the source chain + /// + /// that the target chain knows of. + /// + /// This value is updated indirectly when an `OutboundLane` state of the source + /// chain is received alongside with new messages delivery. + pub last_confirmed_nonce: MessageNonce, } impl Default for InboundLaneData { fn default() -> Self { InboundLaneData { relayers: VecDeque::new(), - latest_received_nonce: 0, - latest_confirmed_nonce: 0, + last_confirmed_nonce: 0, } } } +impl InboundLaneData { + /// Nonce of the last message that has been delivered to this (target) chain. + pub fn last_delivered_nonce(&self) -> MessageNonce { + self.relayers + .back() + .map(|(_, last_nonce, _)| *last_nonce) + .unwrap_or(self.last_confirmed_nonce) + } +} + /// Gist of `InboundLaneData::relayers` field used by runtime APIs. #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] pub struct UnrewardedRelayersState { From 86de8a8a231c20c4cd00ca61fe2dbe6c4faa9319 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 13 Jan 2021 13:34:33 +0300 Subject: [PATCH 0289/1210] swap target <-> source in race logs (#641) --- relays/messages-relay/src/message_race_receiving.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/messages-relay/src/message_race_receiving.rs b/relays/messages-relay/src/message_race_receiving.rs index 0da5fffe8b06f..af89ab8e34d05 100644 --- a/relays/messages-relay/src/message_race_receiving.rs +++ b/relays/messages-relay/src/message_race_receiving.rs @@ -79,11 +79,11 @@ impl MessageRace for ReceivingConfirmationsRace

{ type Proof = P::MessagesReceivingProof; fn source_name() -> String { - format!("{}::ReceivingConfirmationsDelivery", P::SOURCE_NAME) + format!("{}::ReceivingConfirmationsDelivery", P::TARGET_NAME) } fn target_name() -> String { - format!("{}::ReceivingConfirmationsDelivery", P::TARGET_NAME) + format!("{}::ReceivingConfirmationsDelivery", P::SOURCE_NAME) } } From 7a8bd1406b3e85739dd58e2212f8a4a8df3e3d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 13 Jan 2021 12:11:20 +0100 Subject: [PATCH 0290/1210] Expose message lane storage. (#642) --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 9969eb96fa938..1a4838c2621e0 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -354,7 +354,7 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, - BridgeRialtoMessageLane: pallet_message_lane::{Module, Call, Event}, + BridgeRialtoMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e80281560c8a6..6420ae818e594 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -466,7 +466,7 @@ construct_runtime!( BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, - BridgeMillauMessageLane: pallet_message_lane::{Module, Call, Event}, + BridgeMillauMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, From c1ac59d716aaa5cdc02f8c3eaaacebb52fd22910 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 13 Jan 2021 15:01:25 +0300 Subject: [PATCH 0291/1210] fix log level (#644) --- relays/substrate/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index c6b89e7ee1fba..88d436371e34d 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -332,7 +332,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { }, }; - log::error!(target: "bridge", "Sending message to Rialto. Fee: {}", fee); + log::info!(target: "bridge", "Sending message to Rialto. Fee: {}", fee); let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( millau_runtime::MessageLaneCall::send_message(lane, payload, fee), From b5f405c865fe35e431dcfa4008aa882bbff889c9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 15 Jan 2021 00:11:51 +0300 Subject: [PATCH 0292/1210] Reward delivery confirmation transaction submitter (aka confirmation relayer) (#599) * reward confirmation relayer * Update modules/message-lane/src/instant_payments.rs Co-authored-by: Hernando Castano * added some constants * pallet_balances * removed comment * fix typo Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 3 + bin/rialto/runtime/src/lib.rs | 3 + modules/message-lane/Cargo.toml | 1 + modules/message-lane/src/instant_payments.rs | 198 ++++++++++++++++--- modules/message-lane/src/lib.rs | 32 +-- modules/message-lane/src/mock.rs | 43 +++- primitives/message-lane/src/source_chain.rs | 28 ++- relays/utils/Cargo.toml | 2 +- 8 files changed, 250 insertions(+), 60 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1a4838c2621e0..0e56f24d66085 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -315,6 +315,8 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + // TODO: https://github.com/paritytech/parity-bridges-common/pull/598 + pub GetDeliveryConfirmationTransactionFee: Balance = 0; pub const RootAccountForPayments: Option = None; } @@ -340,6 +342,7 @@ impl pallet_message_lane::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_message_lane::instant_payments::InstantCurrencyPayments< Runtime, pallet_balances::Module, + GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6420ae818e594..a77d590612609 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -422,6 +422,8 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + // TODO: https://github.com/paritytech/parity-bridges-common/pull/598 + pub GetDeliveryConfirmationTransactionFee: Balance = 0; pub const RootAccountForPayments: Option = None; } @@ -447,6 +449,7 @@ impl pallet_message_lane::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_message_lane::instant_payments::InstantCurrencyPayments< Runtime, pallet_balances::Module, + GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 7f443732cbf8f..300b0493912eb 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -28,6 +28,7 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master [dev-dependencies] hex-literal = "0.3" sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index 28038af0f9b5d..63c94e6ffdfea 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -19,28 +19,40 @@ //! The payment is first transferred to a special `relayers-fund` account and only transferred //! to the actual relayer in case confirmation is received. -use bp_message_lane::source_chain::{MessageDeliveryAndDispatchPayment, Sender}; +use bp_message_lane::{ + source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, + MessageNonce, +}; +use codec::Encode; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; +use num_traits::Zero; +use sp_runtime::traits::Saturating; +use sp_std::fmt::Debug; /// Instant message payments made in given currency. /// /// The balance is initally reserved in a special `relayers-fund` account, and transferred /// to the relayer when message delivery is confirmed. /// +/// Additionaly, confirmation transaction submitter (`confirmation_relayer`) is reimbursed +/// with the confirmation rewards (part of message fee, reserved to pay for delivery confirmation). +/// /// NOTE The `relayers-fund` account must always exist i.e. be over Existential Deposit (ED; the /// pallet enforces that) to make sure that even if the message cost is below ED it is still payed /// to the relayer account. /// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they /// can receive the payment. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(T, Currency, RootAccount)>, +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, Currency, GetConfirmationFee, RootAccount)>, } -impl MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments +impl MessageDeliveryAndDispatchPayment + for InstantCurrencyPayments where T: frame_system::Config, Currency: CurrencyT, + Currency::Balance: From, + GetConfirmationFee: Get, RootAccount: Get>, { type Error = &'static str; @@ -77,35 +89,163 @@ where .map_err(Into::into) } - fn pay_relayer_reward( - _confirmation_relayer: &T::AccountId, - relayer: &T::AccountId, - reward: &Currency::Balance, + fn pay_relayers_rewards( + confirmation_relayer: &T::AccountId, + relayers_rewards: RelayersRewards, relayer_fund_account: &T::AccountId, ) { - let pay_result = Currency::transfer( - &relayer_fund_account, - relayer, - *reward, - // the relayer fund account must stay above ED (needs to be pre-funded) - ExistenceRequirement::KeepAlive, + pay_relayers_rewards::( + confirmation_relayer, + relayers_rewards, + relayer_fund_account, + GetConfirmationFee::get(), ); + } +} + +/// Pay rewards to given relayers, optionally rewarding confirmation relayer. +fn pay_relayers_rewards( + confirmation_relayer: &AccountId, + relayers_rewards: RelayersRewards, + relayer_fund_account: &AccountId, + confirmation_fee: Currency::Balance, +) where + AccountId: Debug + Default + Encode + PartialEq, + Currency: CurrencyT, + Currency::Balance: From, +{ + // reward every relayer except `confirmation_relayer` + let mut confirmation_relayer_reward = Currency::Balance::zero(); + for (relayer, reward) in relayers_rewards { + let mut relayer_reward = reward.reward; + + if relayer != *confirmation_relayer { + // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee + // from relayer reward. + // + // If confirmation fee has been increased (or if it was the only component of message fee), + // then messages relayer may receive zero reward. + let mut confirmation_reward = confirmation_fee.saturating_mul(reward.messages.into()); + if confirmation_reward > relayer_reward { + confirmation_reward = relayer_reward; + } + relayer_reward = relayer_reward.saturating_sub(confirmation_reward); + confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(confirmation_reward); + } else { + // If delivery confirmation is submitted by this relayer, let's add confirmation fee + // from other relayers to this relayer reward. + confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward); + continue; + } + + pay_relayer_reward::(relayer_fund_account, &relayer, relayer_reward); + } + + // finally - pay reward to confirmation relayer + pay_relayer_reward::(relayer_fund_account, confirmation_relayer, confirmation_relayer_reward); +} + +/// Transfer funds from relayers fund account to given relayer. +fn pay_relayer_reward( + relayer_fund_account: &AccountId, + relayer_account: &AccountId, + reward: Currency::Balance, +) where + AccountId: Debug, + Currency: CurrencyT, +{ + if reward.is_zero() { + return; + } + + let pay_result = Currency::transfer( + relayer_fund_account, + relayer_account, + reward, + // the relayer fund account must stay above ED (needs to be pre-funded) + ExistenceRequirement::KeepAlive, + ); - // we can't actually do anything here, because rewards are paid as a part of unrelated transaction - match pay_result { - Ok(_) => frame_support::debug::trace!( - target: "runtime", - "Rewarded relayer {:?} with {:?}", - relayer, - reward, + match pay_result { + Ok(_) => frame_support::debug::trace!( + target: "runtime", + "Rewarded relayer {:?} with {:?}", + relayer_account, + reward, + ), + Err(error) => frame_support::debug::trace!( + target: "runtime", + "Failed to pay relayer {:?} reward {:?}: {:?}", + relayer_account, + reward, + error, + ), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{run_test, AccountId as TestAccountId, Balance as TestBalance, TestRuntime}; + use bp_message_lane::source_chain::RelayerRewards; + + type Balances = pallet_balances::Module; + + const RELAYER_1: TestAccountId = 1; + const RELAYER_2: TestAccountId = 2; + const RELAYER_3: TestAccountId = 3; + const RELAYERS_FUND_ACCOUNT: TestAccountId = crate::mock::ENDOWED_ACCOUNT; + + fn relayers_rewards() -> RelayersRewards { + vec![ + ( + RELAYER_1, + RelayerRewards { + reward: 100, + messages: 2, + }, ), - Err(error) => frame_support::debug::trace!( - target: "runtime", - "Failed to pay relayer {:?} reward {:?}: {:?}", - relayer, - reward, - error, + ( + RELAYER_2, + RelayerRewards { + reward: 100, + messages: 3, + }, ), - } + ] + .into_iter() + .collect() + } + + #[test] + fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { + run_test(|| { + pay_relayers_rewards::(&RELAYER_2, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 10); + + assert_eq!(Balances::free_balance(&RELAYER_1), 80); + assert_eq!(Balances::free_balance(&RELAYER_2), 120); + }); + } + + #[test] + fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { + run_test(|| { + pay_relayers_rewards::(&RELAYER_3, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 10); + + assert_eq!(Balances::free_balance(&RELAYER_1), 80); + assert_eq!(Balances::free_balance(&RELAYER_2), 70); + assert_eq!(Balances::free_balance(&RELAYER_3), 50); + }); + } + + #[test] + fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { + run_test(|| { + pay_relayers_rewards::(&RELAYER_3, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 1000); + + assert_eq!(Balances::free_balance(&RELAYER_1), 0); + assert_eq!(Balances::free_balance(&RELAYER_2), 0); + assert_eq!(Balances::free_balance(&RELAYER_3), 200); + }); } } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 10b3ec22c226d..04cd9c8983752 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -41,7 +41,7 @@ use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use bp_message_lane::{ - source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, + source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayersState, @@ -106,7 +106,7 @@ pub trait Config: frame_system::Config { /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter + Size; /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: From + Parameter + SaturatingAdd + Zero; + type OutboundMessageFee: Default + From + Parameter + SaturatingAdd + Zero; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; @@ -464,40 +464,42 @@ decl_module! { // mark messages as delivered let mut lane = outbound_lane::(lane_id); + let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); let received_range = lane.confirm_delivery(last_delivered_nonce); if let Some(received_range) = received_range { Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); - // reward relayers that have delivered messages + // remember to reward relayers that have delivered messages // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let relayer_fund_account = Self::relayer_fund_account_id(); for (nonce_low, nonce_high, relayer) in lane_data.relayers { let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0); let nonce_end = sp_std::cmp::min(nonce_high, received_range.1); // loop won't proceed if current entry is ahead of received range (begin > end). // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain - let mut relayer_fee: T::OutboundMessageFee = Zero::zero(); + let mut relayer_reward = relayers_rewards.entry(relayer).or_default(); for nonce in nonce_begin..nonce_end + 1 { let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce, }).expect("message was just confirmed; we never prune unconfirmed messages; qed"); - relayer_fee = relayer_fee.saturating_add(&message_data.fee); - } - - if !relayer_fee.is_zero() { - >::MessageDeliveryAndDispatchPayment::pay_relayer_reward( - &confirmation_relayer, - &relayer, - &relayer_fee, - &relayer_fund_account, - ); + relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); + relayer_reward.messages += 1; } } } + // if some new messages have been confirmed, reward relayers + if !relayers_rewards.is_empty() { + let relayer_fund_account = Self::relayer_fund_account_id(); + >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( + &confirmation_relayer, + relayers_rewards, + &relayer_fund_account, + ); + } + frame_support::debug::trace!( "Received messages delivery proof up to (and including) {} at lane {:?}", last_delivered_nonce, diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 5b24a29eb9b28..98ae5c6f608df 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -17,7 +17,9 @@ use crate::Config; use bp_message_lane::{ - source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, Sender, TargetHeaderChain}, + source_chain::{ + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, Sender, TargetHeaderChain, + }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, }; @@ -33,6 +35,7 @@ use sp_runtime::{ use std::collections::BTreeMap; pub type AccountId = u64; +pub type Balance = u64; #[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)] pub struct TestPayload(pub u64, pub Weight); pub type TestMessageFee = u64; @@ -56,6 +59,7 @@ mod message_lane { impl_outer_event! { pub enum TestEvent for TestRuntime { frame_system, + pallet_balances, message_lane, } } @@ -85,7 +89,7 @@ impl frame_system::Config for TestRuntime { type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = (); - type AccountData = (); + type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); type BaseCallFilter = (); @@ -96,6 +100,20 @@ impl frame_system::Config for TestRuntime { type SS58Prefix = (); } +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} + +impl pallet_balances::Config for TestRuntime { + type MaxLocks = (); + type Balance = Balance; + type DustRemoval = (); + type Event = TestEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = frame_system::Module; + type WeightInfo = (); +} + parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; @@ -132,6 +150,9 @@ impl Size for TestPayload { } } +/// Account that has balance to use in tests. +pub const ENDOWED_ACCOUNT: AccountId = 0xDEAD; + /// Account id of test relayer. pub const TEST_RELAYER_A: AccountId = 100; @@ -265,14 +286,15 @@ impl MessageDeliveryAndDispatchPayment for TestMessag Ok(()) } - fn pay_relayer_reward( + fn pay_relayers_rewards( _confirmation_relayer: &AccountId, - relayer: &AccountId, - fee: &TestMessageFee, + relayers_rewards: RelayersRewards, _relayer_fund_account: &AccountId, ) { - let key = (b":relayer-reward:", relayer, fee).encode(); - frame_support::storage::unhashed::put(&key, &true); + for (relayer, reward) in relayers_rewards { + let key = (b":relayer-reward:", relayer, reward.reward).encode(); + frame_support::storage::unhashed::put(&key, &true); + } } } @@ -334,9 +356,14 @@ pub fn message_data(payload: TestPayload) -> MessageData { /// Run message lane test. pub fn run_test(test: impl FnOnce() -> T) -> T { - let t = frame_system::GenesisConfig::default() + let mut t = frame_system::GenesisConfig::default() .build_storage::() .unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(ENDOWED_ACCOUNT, 1_000_000)], + } + .assimilate_storage(&mut t) + .unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(test) } diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index d607ab7545cb7..813188bd79134 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -16,14 +16,26 @@ //! Primitives of message lane module, that are used on the source chain. -use crate::{InboundLaneData, LaneId}; +use crate::{InboundLaneData, LaneId, MessageNonce}; -use frame_support::Parameter; -use sp_std::fmt::Debug; +use frame_support::{Parameter, RuntimeDebug}; +use sp_std::{collections::btree_map::BTreeMap, fmt::Debug}; /// The sender of the message on the source chain. pub type Sender = frame_system::RawOrigin; +/// Relayers rewards, grouped by relayer account id. +pub type RelayersRewards = BTreeMap>; + +/// Single relayer rewards. +#[derive(RuntimeDebug, Default)] +pub struct RelayerRewards { + /// Total rewards that are to be paid to the relayer. + pub reward: Balance, + /// Total number of messages relayed by this relayer. + pub messages: MessageNonce, +} + /// Target chain API. Used by source chain to verify target chain proofs. /// /// All implementations of this trait should only work with finalized data that @@ -102,11 +114,13 @@ pub trait MessageDeliveryAndDispatchPayment { relayer_fund_account: &AccountId, ) -> Result<(), Self::Error>; - /// Pay reward for delivering message to the given relayer account. - fn pay_relayer_reward( + /// Pay rewards for delivering messages to the given relayers. + /// + /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is + /// a relayer that has submitted delivery confirmation transaction. + fn pay_relayers_rewards( confirmation_relayer: &AccountId, - relayer: &AccountId, - reward: &Balance, + relayers_rewards: RelayersRewards, relayer_fund_account: &AccountId, ); diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 1f20a063de33a..5320e91fd558b 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" ansi_term = "0.12" async-std = "1.6.5" backoff = "0.2" -env_logger = "0.7.0" +env_logger = "0.8.2" futures = "0.3.5" log = "0.4.11" num-traits = "0.2" From 3e05d76b5c9d6fff855b9426cd67d4f88b94688f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 15 Jan 2021 11:17:40 +0300 Subject: [PATCH 0293/1210] Do not refetch completion data instantly (#649) * do not refetch completion data instantly * clippy --- relays/headers-relay/src/headers.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/relays/headers-relay/src/headers.rs b/relays/headers-relay/src/headers.rs index 6081cb1c18d73..99ccc197afc18 100644 --- a/relays/headers-relay/src/headers.rs +++ b/relays/headers-relay/src/headers.rs @@ -368,7 +368,10 @@ impl QueuedHeaders

{ // completion 'notification' // this could lead to duplicate completion retrieval (if completion transaction isn't mined // for too long) - if self.incomplete_headers.get(id).is_some() { + // + // instead, we're moving entry to the end of the queue, so that completion data won't be + // refetched instantly + if self.incomplete_headers.remove(id).is_some() { log::debug!( target: "bridge", "Received completion data from {} for header: {:?}", @@ -377,6 +380,7 @@ impl QueuedHeaders

{ ); self.completion_data.insert(*id, completion); + self.incomplete_headers.insert(*id, Some(Instant::now())); } } @@ -1410,26 +1414,29 @@ pub(crate) mod tests { let mut queue = QueuedHeaders::::default(); queue.incomplete_headers.insert(id(100), None); queue.incomplete_headers.insert(id(200), Some(Instant::now())); + queue.incomplete_headers.insert(id(300), Some(Instant::now())); - // when headers isn't incompete, nothing changes - queue.completion_response(&id(300), None); - assert_eq!(queue.incomplete_headers.len(), 2); + // when header isn't incompete, nothing changes + queue.completion_response(&id(400), None); + assert_eq!(queue.incomplete_headers.len(), 3); assert_eq!(queue.completion_data.len(), 0); assert_eq!(queue.header_to_complete(), None); // when response is None, nothing changes queue.completion_response(&id(100), None); - assert_eq!(queue.incomplete_headers.len(), 2); + assert_eq!(queue.incomplete_headers.len(), 3); assert_eq!(queue.completion_data.len(), 0); assert_eq!(queue.header_to_complete(), None); // when response is Some, we're scheduling completion queue.completion_response(&id(200), Some(200_200)); - assert_eq!(queue.incomplete_headers.len(), 2); assert_eq!(queue.completion_data.len(), 1); - assert!(queue.incomplete_headers.contains_key(&id(100))); assert!(queue.completion_data.contains_key(&id(200))); assert_eq!(queue.header_to_complete(), Some((id(200), &200_200))); + assert_eq!( + queue.incomplete_headers.keys().collect::>(), + vec![&id(100), &id(300), &id(200)], + ); } #[test] From 02052d5bf0922cf4e6efcf0195c71ee72ff023f9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 15 Jan 2021 18:52:31 +0300 Subject: [PATCH 0294/1210] Improve Substrate pallet logs (#650) --- modules/substrate/src/fork_tests.rs | 8 ++++++-- modules/substrate/src/lib.rs | 21 ++++++++++++++++----- modules/substrate/src/verifier.rs | 28 +++++++++++++++------------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index f90d2c0231ca6..c71ed3938e1bb 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -397,7 +397,9 @@ where } // Try and import into storage - let res = verifier.import_header(header.clone()).map_err(TestError::Import); + let res = verifier + .import_header(header.hash(), header.clone()) + .map_err(TestError::Import); assert_eq!( res, *expected_result, "Expected {:?} while importing header ({}, {}), got {:?}", @@ -427,7 +429,9 @@ where header.digest = change_log(*delay); } - let res = verifier.import_header(header.clone()).map_err(TestError::Import); + let res = verifier + .import_header(header.hash(), header.clone()) + .map_err(TestError::Import); assert_eq!( res, *expected_result, "Expected {:?} while importing header ({}, {}), got {:?}", diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index fa957c384fb05..fbd6cab95734e 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -172,15 +172,21 @@ decl_module! { ) -> DispatchResult { ensure_operational::()?; let _ = ensure_signed(origin)?; - frame_support::debug::trace!("Got header {:?}", header); + let hash = header.hash(); + frame_support::debug::trace!("Going to import header {:?}: {:?}", hash, header); let mut verifier = verifier::Verifier { storage: PalletStorage::::new(), }; let _ = verifier - .import_header(header) - .map_err(|_| >::InvalidHeader)?; + .import_header(hash, header) + .map_err(|e| { + frame_support::debug::error!("Failed to import header {:?}: {:?}", hash, e); + >::InvalidHeader + })?; + + frame_support::debug::trace!("Successfully imported header: {:?}", hash); Ok(()) } @@ -199,7 +205,7 @@ decl_module! { ) -> DispatchResult { ensure_operational::()?; let _ = ensure_signed(origin)?; - frame_support::debug::trace!("Got header hash {:?}", hash); + frame_support::debug::trace!("Going to finalize header: {:?}", hash); let mut verifier = verifier::Verifier { storage: PalletStorage::::new(), @@ -207,7 +213,12 @@ decl_module! { let _ = verifier .import_finality_proof(hash, finality_proof.into()) - .map_err(|_| >::UnfinalizedHeader)?; + .map_err(|e| { + frame_support::debug::error!("Failed to finalize header {:?}: {:?}", hash, e); + >::UnfinalizedHeader + })?; + + frame_support::debug::trace!("Successfully finalized header: {:?}", hash); Ok(()) } diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 913129f19c6ef..41139cfebeb0c 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -112,8 +112,7 @@ where /// /// Will perform some basic checks to make sure that this header doesn't break any assumptions /// such as being on a different finalized fork. - pub fn import_header(&mut self, header: H) -> Result<(), ImportError> { - let hash = header.hash(); + pub fn import_header(&mut self, hash: H::Hash, header: H) -> Result<(), ImportError> { let best_finalized = self.storage.best_finalized_header(); if header.number() <= best_finalized.number() { @@ -424,7 +423,7 @@ mod tests { let header = test_header(1); let mut verifier = Verifier { storage }; - assert_err!(verifier.import_header(header), ImportError::OldHeader); + assert_err!(verifier.import_header(header.hash(), header), ImportError::OldHeader); }) } @@ -440,7 +439,10 @@ mod tests { let header = TestHeader::new_from_number(2); let mut verifier = Verifier { storage }; - assert_err!(verifier.import_header(header), ImportError::MissingParent); + assert_err!( + verifier.import_header(header.hash(), header), + ImportError::MissingParent + ); }) } @@ -460,7 +462,7 @@ mod tests { >::insert(header.hash(), &imported_header); let mut verifier = Verifier { storage }; - assert_err!(verifier.import_header(header), ImportError::OldHeader); + assert_err!(verifier.import_header(header.hash(), header), ImportError::OldHeader); }) } @@ -484,7 +486,7 @@ mod tests { let mut verifier = Verifier { storage: storage.clone(), }; - assert_ok!(verifier.import_header(header.clone())); + assert_ok!(verifier.import_header(header.hash(), header.clone())); let stored_header = storage .header_by_hash(header.hash()) @@ -514,8 +516,8 @@ mod tests { }; // It should be fine to import both - assert_ok!(verifier.import_header(header_on_fork1.clone())); - assert_ok!(verifier.import_header(header_on_fork2.clone())); + assert_ok!(verifier.import_header(header_on_fork1.hash(), header_on_fork1.clone())); + assert_ok!(verifier.import_header(header_on_fork2.hash(), header_on_fork2.clone())); // We should have two headers marked as being the best since they're // both at the same height @@ -559,7 +561,7 @@ mod tests { let mut verifier = Verifier { storage: storage.clone(), }; - assert_ok!(verifier.import_header(better_header.clone())); + assert_ok!(verifier.import_header(better_header.hash(), better_header.clone())); // Since `better_header` is the only one at height = 2 we should only have // a single "best header" now. @@ -668,7 +670,7 @@ mod tests { let mut verifier = Verifier { storage }; assert_eq!( - verifier.import_header(header).unwrap_err(), + verifier.import_header(header.hash(), header).unwrap_err(), ImportError::InvalidAuthoritySet ); }) @@ -697,7 +699,7 @@ mod tests { storage: storage.clone(), }; - assert_ok!(verifier.import_header(header.clone())); + assert_ok!(verifier.import_header(header.hash(), header.clone())); assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); assert_eq!(storage.best_finalized_header().header, header); }) @@ -724,7 +726,7 @@ mod tests { let mut verifier = Verifier { storage: storage.clone(), }; - assert!(verifier.import_header(header.clone()).is_ok()); + assert!(verifier.import_header(header.hash(), header.clone()).is_ok()); assert!(verifier .import_finality_proof(header.hash(), justification.into()) .is_ok()); @@ -776,7 +778,7 @@ mod tests { storage: storage.clone(), }; - assert_ok!(verifier.import_header(header.clone())); + assert_ok!(verifier.import_header(header.hash(), header.clone())); assert_eq!(storage.missing_justifications().len(), 1); assert_eq!(storage.missing_justifications()[0].hash, header.hash()); From c7ec8a443ba0082aca909a134531317ceec89db7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 15 Jan 2021 14:00:35 -0500 Subject: [PATCH 0295/1210] Move justification code to primitives crate (#640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move justification module to header-chain primitives crate * Get justification module compiling in new location * Get justification module tests compiling * Use justification code from `header-chain` crate Mostly compiles, having issues with std/test feature flags across crates. * Move some code around * Move justification tests to integration testing crate * Add `test-utils` crate * Remove tests and test-helper module from justification code * Use `test-utils` in Substrate bridge pallet tests * Remove `sp-keyring` related code from `pallet-substrate-bridge` * Remove `helpers` module from `pallet-substrate-bridge` * Add some documentation * Add more documentation * Fix typo Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- modules/substrate/Cargo.toml | 4 +- modules/substrate/src/fork_tests.rs | 7 +- modules/substrate/src/lib.rs | 6 +- modules/substrate/src/mock.rs | 77 ++------ modules/substrate/src/verifier.rs | 5 +- primitives/header-chain/Cargo.toml | 26 ++- .../header-chain}/src/justification.rs | 168 +----------------- primitives/header-chain/src/lib.rs | 4 +- .../header-chain/tests/justification.rs | 114 ++++++++++++ primitives/test-utils/Cargo.toml | 13 ++ primitives/test-utils/src/lib.rs | 151 ++++++++++++++++ relays/substrate/Cargo.toml | 1 + relays/substrate/src/headers_maintain.rs | 2 +- 13 files changed, 338 insertions(+), 240 deletions(-) rename {modules/substrate => primitives/header-chain}/src/justification.rs (58%) create mode 100644 primitives/header-chain/tests/justification.rs create mode 100644 primitives/test-utils/Cargo.toml create mode 100644 primitives/test-utils/src/lib.rs diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 44022d6779b07..8eb253606101d 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -15,6 +15,7 @@ serde = { version = "1.0", optional = true } # Bridge Dependencies +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies @@ -27,14 +28,15 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] +bp-test-utils = {path = "../../primitives/test-utils" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-runtime/std", "codec/std", "finality-grandpa/std", diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index c71ed3938e1bb..a2529dec13d5e 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -54,11 +54,11 @@ //! Import a finality proof for header 2 on fork 1. This finalty proof should fail to be imported //! because the header is an old header. -use crate::justification::tests::*; -use crate::mock::{helpers::*, *}; +use crate::mock::*; use crate::storage::{AuthoritySet, ImportedHeader}; use crate::verifier::*; use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; +use bp_test_utils::{alice, authority_list, bob, make_justification_for_header}; use codec::Encode; use frame_support::{IterableStorageMap, StorageValue}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -456,8 +456,7 @@ where let grandpa_round = 1; let set_id = 1; let authorities = authority_list(); - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + let justification = make_justification_for_header(header, grandpa_round, set_id, &authorities).encode(); let res = verifier .import_finality_proof(header.hash(), justification.into()) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index fbd6cab95734e..2129f0004979d 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -45,10 +45,8 @@ use sp_trie::StorageProof; // Re-export since the node uses these when configuring genesis pub use storage::{AuthoritySet, InitializationData, ScheduledChange}; -pub use justification::decode_justification_target; pub use storage_proof::StorageProofChecker; -mod justification; mod storage; mod storage_proof; mod verifier; @@ -622,8 +620,8 @@ impl BridgeStorage for PalletStorage { #[cfg(test)] mod tests { use super::*; - use crate::mock::helpers::{authority_list, test_header, unfinalized_header}; - use crate::mock::{run_test, Origin, TestRuntime}; + use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestRuntime}; + use bp_test_utils::authority_list; use frame_support::{assert_noop, assert_ok}; use sp_runtime::DispatchError; diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index e6415aae8e411..e5b0c26c13ab2 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -16,11 +16,11 @@ //! Mock Runtime for Substrate Pallet Testing. //! -//! Includes some useful testing utilities in the `helpers` module. +//! Includes some useful testing types and functions. #![cfg(test)] -use crate::Config; +use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader, Config}; use bp_runtime::Chain; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use sp_runtime::{ @@ -30,6 +30,9 @@ use sp_runtime::{ }; pub type AccountId = u64; +pub type TestHeader = BridgedHeader; +pub type TestNumber = BridgedBlockNumber; +pub type TestHash = BridgedBlockHash; #[derive(Clone, Eq, PartialEq, Debug)] pub struct TestRuntime; @@ -88,66 +91,16 @@ pub fn run_test(test: impl FnOnce() -> T) -> T { sp_io::TestExternalities::new(Default::default()).execute_with(test) } -pub mod helpers { - use super::*; - use crate::storage::ImportedHeader; - use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader}; - use finality_grandpa::voter_set::VoterSet; - use sp_finality_grandpa::{AuthorityId, AuthorityList}; - use sp_keyring::Ed25519Keyring; - - pub type TestHeader = BridgedHeader; - pub type TestNumber = BridgedBlockNumber; - pub type TestHash = BridgedBlockHash; - pub type HeaderId = (TestHash, TestNumber); - - pub fn test_header(num: TestNumber) -> TestHeader { - let mut header = TestHeader::new_from_number(num); - header.parent_hash = if num == 0 { - Default::default() - } else { - test_header(num - 1).hash() - }; - - header - } - - pub fn unfinalized_header(num: u64) -> ImportedHeader { - ImportedHeader { - header: test_header(num), - requires_justification: false, - is_finalized: false, - signal_hash: None, - } - } - - pub fn header_id(index: u8) -> HeaderId { - (test_header(index.into()).hash(), index as _) - } - - pub fn extract_keyring(id: &AuthorityId) -> Ed25519Keyring { - let mut raw_public = [0; 32]; - raw_public.copy_from_slice(id.as_ref()); - Ed25519Keyring::from_raw_public(raw_public).unwrap() - } - - pub fn voter_set() -> VoterSet { - VoterSet::new(authority_list()).unwrap() - } - - pub fn authority_list() -> AuthorityList { - vec![(alice(), 1), (bob(), 1), (charlie(), 1)] - } - - pub fn alice() -> AuthorityId { - Ed25519Keyring::Alice.public().into() - } - - pub fn bob() -> AuthorityId { - Ed25519Keyring::Bob.public().into() - } +pub fn test_header(num: TestNumber) -> TestHeader { + // We wrap the call to avoid explicit type annotations in our tests + bp_test_utils::test_header(num) +} - pub fn charlie() -> AuthorityId { - Ed25519Keyring::Charlie.public().into() +pub fn unfinalized_header(num: u64) -> crate::storage::ImportedHeader { + crate::storage::ImportedHeader { + header: test_header(num), + requires_justification: false, + is_finalized: false, + signal_hash: None, } } diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 41139cfebeb0c..edbc77d54a746 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -22,9 +22,9 @@ //! has been signed off by the correct GRANDPA authorities, and also enact any authority set changes //! if required. -use crate::justification::verify_justification; use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; use crate::BridgeStorage; +use bp_header_chain::justification::verify_justification; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::generic::OpaqueDigestItemId; @@ -350,10 +350,9 @@ fn find_scheduled_change(header: &H) -> Option"] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -[dependencies.parity-scale-codec] -version = "1.3.1" -default-features = false -features = ["derive"] +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +finality-grandpa = { version = "0.12.3", default-features = false } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } + +[dev-dependencies] +bp-test-utils = { path = "../test-utils" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] std = [ - "parity-scale-codec/std", + "codec/std", + "finality-grandpa/std", + "frame-support/std", + "sp-core/std", + "sp-finality-grandpa/std", + "sp-std/std", ] diff --git a/modules/substrate/src/justification.rs b/primitives/header-chain/src/justification.rs similarity index 58% rename from modules/substrate/src/justification.rs rename to primitives/header-chain/src/justification.rs index c285dd34b808d..54a44d9b7ad04 100644 --- a/modules/substrate/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -19,7 +19,7 @@ //! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin //! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. -use codec::Decode; +use codec::{Decode, Encode}; use finality_grandpa::{voter_set::VoterSet, Chain, Error as GrandpaError}; use frame_support::RuntimeDebug; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; @@ -128,12 +128,14 @@ where /// /// This particular proof is used to prove that headers on a bridged chain /// (so not our chain) have been finalized correctly. -#[derive(Decode, RuntimeDebug)] -#[cfg_attr(test, derive(codec::Encode))] -pub(crate) struct GrandpaJustification { - round: u64, - commit: finality_grandpa::Commit, - votes_ancestries: Vec

, +#[derive(Encode, Decode, RuntimeDebug)] +pub struct GrandpaJustification { + /// The round (voting period) this justification is valid for. + pub round: u64, + /// The set of votes for the chain which is to be finalized. + pub commit: finality_grandpa::Commit, + /// A proof that the chain of blocks in the commit are related to each other. + pub votes_ancestries: Vec
, } /// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. @@ -181,155 +183,3 @@ where unreachable!("is only used during voting; qed") } } - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::mock::helpers::*; - use codec::Encode; - use sp_core::H256; - use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; - use sp_keyring::Ed25519Keyring; - - const TEST_GRANDPA_ROUND: u64 = 1; - const TEST_GRANDPA_SET_ID: SetId = 1; - - pub(crate) fn signed_precommit( - signer: Ed25519Keyring, - target: HeaderId, - round: u64, - set_id: SetId, - ) -> finality_grandpa::SignedPrecommit { - let precommit = finality_grandpa::Precommit { - target_hash: target.0, - target_number: target.1, - }; - let encoded = sp_finality_grandpa::localized_payload( - round, - set_id, - &finality_grandpa::Message::Precommit(precommit.clone()), - ); - let signature = signer.sign(&encoded[..]).into(); - finality_grandpa::SignedPrecommit { - precommit, - signature, - id: signer.public().into(), - } - } - - pub(crate) fn make_justification_for_header( - header: &TestHeader, - round: u64, - set_id: SetId, - authorities: &[(AuthorityId, AuthorityWeight)], - ) -> GrandpaJustification { - let (target_hash, target_number) = (header.hash(), *header.number()); - let mut precommits = vec![]; - let mut votes_ancestries = vec![]; - - // We want to make sure that the header included in the vote ancestries - // is actually related to our target header - let mut precommit_header = test_header(target_number + 1); - precommit_header.parent_hash = target_hash; - - // I'm using the same header for all the voters since it doesn't matter as long - // as they all vote on blocks _ahead_ of the one we're interested in finalizing - for (id, _weight) in authorities.iter() { - let signer = extract_keyring(&id); - let precommit = signed_precommit( - signer, - (precommit_header.hash(), *precommit_header.number()), - round, - set_id, - ); - precommits.push(precommit); - votes_ancestries.push(precommit_header.clone()); - } - - GrandpaJustification { - round, - commit: finality_grandpa::Commit { - target_hash, - target_number, - precommits, - }, - votes_ancestries, - } - } - - pub(crate) fn make_justification_for_header_1() -> GrandpaJustification { - make_justification_for_header( - &test_header(1), - TEST_GRANDPA_ROUND, - TEST_GRANDPA_SET_ID, - &authority_list(), - ) - } - - #[test] - fn justification_with_invalid_encoding_rejected() { - assert_eq!( - verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &[],), - Err(Error::JustificationDecode), - ); - } - - #[test] - fn justification_with_invalid_target_rejected() { - assert_eq!( - verify_justification::( - header_id(2), - TEST_GRANDPA_SET_ID, - voter_set(), - &make_justification_for_header_1().encode(), - ), - Err(Error::InvalidJustificationTarget), - ); - } - - #[test] - fn justification_with_invalid_commit_rejected() { - let mut justification = make_justification_for_header_1(); - justification.commit.precommits.clear(); - - assert_eq!( - verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &justification.encode(),), - Err(Error::InvalidJustificationCommit), - ); - } - - #[test] - fn justification_with_invalid_authority_signature_rejected() { - let mut justification = make_justification_for_header_1(); - justification.commit.precommits[0].signature = Default::default(); - - assert_eq!( - verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &justification.encode(),), - Err(Error::InvalidAuthoritySignature), - ); - } - - #[test] - fn justification_with_invalid_precommit_ancestry() { - let mut justification = make_justification_for_header_1(); - justification.votes_ancestries.push(test_header(10)); - - assert_eq!( - verify_justification::(header_id(1), TEST_GRANDPA_SET_ID, voter_set(), &justification.encode(),), - Err(Error::InvalidPrecommitAncestries), - ); - } - - #[test] - fn valid_justification_accepted() { - assert_eq!( - verify_justification::( - header_id(1), - TEST_GRANDPA_SET_ID, - voter_set(), - &make_justification_for_header_1().encode(), - ), - Ok(()), - ); - } -} diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 7e5fa058cfe8c..00978d8081d1d 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,10 +19,12 @@ #![cfg_attr(not(feature = "std"), no_std)] +use codec::{Codec, EncodeLike}; use core::clone::Clone; use core::cmp::Eq; use core::fmt::Debug; -use parity_scale_codec::{Codec, EncodeLike}; + +pub mod justification; /// A type that can be used as a parameter in a dispatchable function. /// diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs new file mode 100644 index 0000000000000..81bd83b1ad3b4 --- /dev/null +++ b/primitives/header-chain/tests/justification.rs @@ -0,0 +1,114 @@ +// Copyright 2020 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 . + +//! Tests for Grandpa Justification code. + +use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; +use bp_test_utils::*; +use codec::Encode; + +type TestHeader = sp_runtime::testing::Header; + +fn make_justification_for_header_1() -> GrandpaJustification { + make_justification_for_header( + &test_header(1), + TEST_GRANDPA_ROUND, + TEST_GRANDPA_SET_ID, + &authority_list(), + ) +} + +#[test] +fn justification_with_invalid_encoding_rejected() { + assert_eq!( + verify_justification::(header_id::(1), TEST_GRANDPA_SET_ID, voter_set(), &[],), + Err(Error::JustificationDecode), + ); +} + +#[test] +fn justification_with_invalid_target_rejected() { + assert_eq!( + verify_justification::( + header_id::(2), + TEST_GRANDPA_SET_ID, + voter_set(), + &make_justification_for_header_1().encode(), + ), + Err(Error::InvalidJustificationTarget), + ); +} + +#[test] +fn justification_with_invalid_commit_rejected() { + let mut justification = make_justification_for_header_1(); + justification.commit.precommits.clear(); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + voter_set(), + &justification.encode(), + ), + Err(Error::InvalidJustificationCommit), + ); +} + +#[test] +fn justification_with_invalid_authority_signature_rejected() { + let mut justification = make_justification_for_header_1(); + justification.commit.precommits[0].signature = Default::default(); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + voter_set(), + &justification.encode(), + ), + Err(Error::InvalidAuthoritySignature), + ); +} + +#[test] +fn justification_with_invalid_precommit_ancestry() { + let mut justification = make_justification_for_header_1(); + justification.votes_ancestries.push(test_header(10)); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + voter_set(), + &justification.encode(), + ), + Err(Error::InvalidPrecommitAncestries), + ); +} + +#[test] +fn valid_justification_accepted() { + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + voter_set(), + &make_justification_for_header_1().encode(), + ), + Ok(()), + ); +} diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml new file mode 100644 index 0000000000000..aa330d4521f4b --- /dev/null +++ b/primitives/test-utils/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "bp-test-utils" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +finality-grandpa = { version = "0.12.3" } +bp-header-chain = { path = "../header-chain" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs new file mode 100644 index 0000000000000..182eb2cb796b7 --- /dev/null +++ b/primitives/test-utils/src/lib.rs @@ -0,0 +1,151 @@ +// Copyright 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 . + +//! Utilities for testing runtime code. +//! +//! Unlike other crates in the `primitives` folder, this crate does *not* need to compile in a +//! `no_std` environment. This is fine because this code should only be used, as the name implies, +//! in tests. + +use bp_header_chain::justification::GrandpaJustification; +use finality_grandpa::voter_set::VoterSet; +use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; +use sp_finality_grandpa::{AuthoritySignature, SetId}; +use sp_keyring::Ed25519Keyring; +use sp_runtime::traits::Header as HeaderT; +use sp_runtime::traits::{One, Zero}; + +pub const TEST_GRANDPA_ROUND: u64 = 1; +pub const TEST_GRANDPA_SET_ID: SetId = 1; + +/// Get a valid Grandpa justification for a header given a Grandpa round, authority set ID, and +/// authority list. +pub fn make_justification_for_header( + header: &H, + round: u64, + set_id: SetId, + authorities: &[(AuthorityId, AuthorityWeight)], +) -> GrandpaJustification { + let (target_hash, target_number) = (header.hash(), *header.number()); + let mut precommits = vec![]; + let mut votes_ancestries = vec![]; + + // We want to make sure that the header included in the vote ancestries + // is actually related to our target header + let mut precommit_header = test_header::(target_number + One::one()); + precommit_header.set_parent_hash(target_hash); + + // I'm using the same header for all the voters since it doesn't matter as long + // as they all vote on blocks _ahead_ of the one we're interested in finalizing + for (id, _weight) in authorities.iter() { + let signer = extract_keyring(&id); + let precommit = signed_precommit::( + signer, + (precommit_header.hash(), *precommit_header.number()), + round, + set_id, + ); + precommits.push(precommit); + votes_ancestries.push(precommit_header.clone()); + } + + GrandpaJustification { + round, + commit: finality_grandpa::Commit { + target_hash, + target_number, + precommits, + }, + votes_ancestries, + } +} + +fn signed_precommit( + signer: Ed25519Keyring, + target: (H::Hash, H::Number), + round: u64, + set_id: SetId, +) -> finality_grandpa::SignedPrecommit { + let precommit = finality_grandpa::Precommit { + target_hash: target.0, + target_number: target.1, + }; + let encoded = + sp_finality_grandpa::localized_payload(round, set_id, &finality_grandpa::Message::Precommit(precommit.clone())); + let signature = signer.sign(&encoded[..]).into(); + finality_grandpa::SignedPrecommit { + precommit, + signature, + id: signer.public().into(), + } +} + +/// Get a header for testing. +/// +/// The correct parent hash will be used if given a non-zero header. +pub fn test_header(number: H::Number) -> H { + let mut header = H::new( + number, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + + if number != Zero::zero() { + let parent_hash = test_header::(number - One::one()).hash(); + header.set_parent_hash(parent_hash); + } + + header +} + +/// Convenience function for generating a Header ID at a given block number. +pub fn header_id(index: u8) -> (H::Hash, H::Number) { + (test_header::(index.into()).hash(), index.into()) +} + +/// Get the identity of a test account given an ED25519 Public key. +pub fn extract_keyring(id: &AuthorityId) -> Ed25519Keyring { + let mut raw_public = [0; 32]; + raw_public.copy_from_slice(id.as_ref()); + Ed25519Keyring::from_raw_public(raw_public).unwrap() +} + +/// Get a valid set of voters for a Grandpa round. +pub fn voter_set() -> VoterSet { + VoterSet::new(authority_list()).unwrap() +} + +/// Convenience function to get a list of Grandpa authorities. +pub fn authority_list() -> AuthorityList { + vec![(alice(), 1), (bob(), 1), (charlie(), 1)] +} + +/// Get the Public key of the Alice test account. +pub fn alice() -> AuthorityId { + Ed25519Keyring::Alice.public().into() +} + +/// Get the Public key of the Bob test account. +pub fn bob() -> AuthorityId { + Ed25519Keyring::Bob.public().into() +} + +/// Get the Public key of the Charlie test account. +pub fn charlie() -> AuthorityId { + Ed25519Keyring::Charlie.public().into() +} diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 41b7d5ad7e344..1853b19b9524b 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -18,6 +18,7 @@ structopt = "0.3" # Bridge dependencies +bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/kusama" } bp-message-lane = { path = "../../primitives/message-lane" } bp-millau = { path = "../../primitives/millau" } diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index 0dac3cafb492b..d2996083b95ac 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -190,7 +190,7 @@ where }; // decode justification target - let target = pallet_substrate_bridge::decode_justification_target::(&justification); + let target = bp_header_chain::justification::decode_justification_target::(&justification); let target = match target { Ok((target_hash, target_number)) => HeaderId(target_number.into(), target_hash.into()), Err(error) => { From dc9e054747985501cfc0ad6cecc28bc6c2a2f1e3 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 Jan 2021 03:06:07 +0000 Subject: [PATCH 0296/1210] Bump async-std from 1.8.0 to 1.9.0 (#654) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 4ff9430b4a1f1..3f0485f36e61a 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" -async-std = "1.8.0" +async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "1.3.4" } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 1853b19b9524b..a0aad4be58d72 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.8.0" +async-std = "1.9.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.8" From d88b34ff3a3fe0c147050338e175ebff564a43eb Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 Jan 2021 03:15:00 +0000 Subject: [PATCH 0297/1210] Bump futures from 0.3.9 to 0.3.12 (#655) --- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 3f0485f36e61a..082820f2aa4cf 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -15,7 +15,7 @@ env_logger = "0.8.2" ethabi = "13.0" ethabi-contract = "11.0" ethabi-derive = "13.0" -futures = "0.3.8" +futures = "0.3.12" hex = "0.4" hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index a0aad4be58d72..171bb1027157e 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.9.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } -futures = "0.3.8" +futures = "0.3.12" hex = "0.4" log = "0.4.11" num-traits = "0.2" From 9e58634c1fb7156ea958f8b02fb7479cd3aa7689 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 18 Jan 2021 20:04:50 +0300 Subject: [PATCH 0298/1210] fixed actual dispatch weight calculation (#658) --- modules/message-lane/src/lib.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 04cd9c8983752..b667120f101eb 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -379,9 +379,9 @@ decl_module! { .messages .iter() .map(T::MessageDispatch::dispatch_weight) - .sum::() + .fold(0, |sum, weight| sum.saturating_add(&weight)) ) - .sum(); + .fold(0, |sum, weight| sum.saturating_add(weight)); if dispatch_weight < actual_dispatch_weight { frame_support::debug::trace!( "Rejecting messages proof because of dispatch weight mismatch: declared={}, expected={}", @@ -755,8 +755,8 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesProof, TestRuntime, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesProof, TestPayload, + TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_message_lane::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; @@ -1291,4 +1291,25 @@ mod tests { hex!("87f1ffe31b52878f09495ca7482df1a4e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), ); } + + #[test] + fn actual_dispatch_weight_does_not_overlow() { + run_test(|| { + let message1 = message(1, TestPayload(0, Weight::MAX / 2)); + let message2 = message(2, TestPayload(0, Weight::MAX / 2)); + let message3 = message(2, TestPayload(0, Weight::MAX / 2)); + + assert_noop!( + Module::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + // this may cause overflow if source chain storage is invalid + Ok(vec![message1, message2, message3]).into(), + 3, + 100, + ), + Error::::InvalidMessagesDispatchWeight, + ); + }); + } } From 4d91945239bb1fbd4a9e9b5e46220ec6a02ca537 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 19 Jan 2021 11:43:37 +0000 Subject: [PATCH 0299/1210] Bump log from 0.4.11 to 0.4.13 (#657) --- modules/ethereum-contract/builtin/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 9275d10bf6638..76f252401d826 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "1.3.4" } ethereum-types = "0.10.0" finality-grandpa = "0.12.3" hex = "0.4" -log = "0.4.11" +log = "0.4.13" # Runtime/chain specific dependencies diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 082820f2aa4cf..3a2010aa6c513 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.12" hex = "0.4" hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } -log = "0.4.11" +log = "0.4.13" num-traits = "0.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.61" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 171bb1027157e..e5243781e6b86 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -11,7 +11,7 @@ async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.12" hex = "0.4" -log = "0.4.11" +log = "0.4.13" num-traits = "0.2" paste = "1.0" structopt = "0.3" From 66ab3505d3107fd2718b61216607fba17008cb04 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 19 Jan 2021 11:03:26 -0500 Subject: [PATCH 0300/1210] Disallow Duplicate Best Headers (#653) * Add test proving bug * Add checks for duplicate headers * Fix Clippy error --- modules/substrate/src/lib.rs | 7 +++- modules/substrate/src/verifier.rs | 56 ++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 2129f0004979d..e1c797c2ae22c 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -521,7 +521,12 @@ impl BridgeStorage for PalletStorage { match current_height.cmp(&best_height) { Ordering::Equal => { - >::append(hash); + // Want to avoid duplicates in the case where we're writing a finalized header to + // storage which also happens to be at the best height the best height + let not_duplicate = !>::contains_key(hash); + if not_duplicate { + >::append(hash); + } } Ordering::Greater => { >::kill(); diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index edbc77d54a746..5cb47cb6566e8 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -24,6 +24,7 @@ use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; use crate::BridgeStorage; + use bp_header_chain::justification::verify_justification; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -545,8 +546,23 @@ mod tests { run_test(|| { let mut storage = PalletStorage::::new(); + // We want to write the genesis header to storage + let _ = write_headers(&mut storage, vec![]); + // Write two headers at the same height to storage. - let imported_headers = write_default_headers(&mut storage, vec![1, 1]); + let best_header = test_header(1); + let mut also_best_header = test_header(1); + + // We need to change _something_ to make it a different header + also_best_header.state_root = [1; 32].into(); + + let mut verifier = Verifier { + storage: storage.clone(), + }; + + // It should be fine to import both + assert_ok!(verifier.import_header(best_header.hash(), best_header.clone())); + assert_ok!(verifier.import_header(also_best_header.hash(), also_best_header)); // The headers we manually imported should have been marked as the best // upon writing to storage. Let's confirm that. @@ -555,11 +571,8 @@ mod tests { // Now let's build something at a better height. let mut better_header = test_header(2); - better_header.parent_hash = imported_headers[1].hash(); + better_header.parent_hash = best_header.hash(); - let mut verifier = Verifier { - storage: storage.clone(), - }; assert_ok!(verifier.import_header(better_header.hash(), better_header.clone())); // Since `better_header` is the only one at height = 2 we should only have @@ -577,6 +590,39 @@ mod tests { }) } + #[test] + fn doesnt_write_best_header_twice_upon_finalization() { + run_test(|| { + let mut storage = PalletStorage::::new(); + let _imported_headers = write_default_headers(&mut storage, vec![1]); + + let set_id = 1; + let authorities = authority_list(); + let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id); + storage.update_current_authority_set(initial_authority_set); + + // Let's import our header + let header = test_header(2); + let mut verifier = Verifier { + storage: storage.clone(), + }; + assert_ok!(verifier.import_header(header.hash(), header.clone())); + + // Our header should be the only best header we have + assert_eq!(storage.best_headers()[0].hash, header.hash()); + assert_eq!(storage.best_headers().len(), 1); + + // Now lets finalize our best header + let grandpa_round = 1; + let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); + + // Our best header should only appear once in the list of best headers + assert_eq!(storage.best_headers()[0].hash, header.hash()); + assert_eq!(storage.best_headers().len(), 1); + }) + } + #[test] fn related_headers_are_ancestors() { run_test(|| { From fb92583398d8b51a1ceb29fc4a21f59d9f9fd14f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 20 Jan 2021 12:11:53 +0300 Subject: [PATCH 0301/1210] Fixed messages count check (#659) * fixed messages count check * explicit check of `messages_count` in the receive_messages_proof * change messages_count to be u32 * Update modules/message-lane/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/src/messages.rs | 53 ++++++++++++++++--- modules/message-lane/src/lib.rs | 42 +++++++++++++-- modules/message-lane/src/mock.rs | 2 +- primitives/message-lane/src/lib.rs | 31 +++++++++-- primitives/message-lane/src/target_chain.rs | 8 ++- .../src/millau_messages_to_rialto.rs | 2 +- .../src/rialto_messages_to_millau.rs | 2 +- 9 files changed, 121 insertions(+), 23 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index cf3e6511801c8..5129276d04f9b 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -192,7 +192,7 @@ impl SourceHeaderChain for Rialto { fn verify_messages_proof( proof: Self::MessagesProof, - messages_count: MessageNonce, + messages_count: u32, ) -> Result>, Self::Error> { messages::target::verify_messages_proof::(proof, messages_count) } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 85b06c35af343..173bde8cad6e8 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -193,7 +193,7 @@ impl SourceHeaderChain for Millau { fn verify_messages_proof( proof: Self::MessagesProof, - messages_count: MessageNonce, + messages_count: u32, ) -> Result>, Self::Error> { messages::target::verify_messages_proof::(proof, messages_count) } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 503dcaeddf77e..897de2af6a224 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -396,9 +396,13 @@ pub mod target { } /// Verify proof of Bridged -> This chain messages. + /// + /// The `messages_count` argument verification (sane limits) is supposed to be made + /// outside of this function. This function only verifies that the proof declares exactly + /// `messages_count` messages. pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof, - messages_count: MessageNonce, + messages_count: u32, ) -> Result>>>, &'static str> where ThisRuntime: pallet_substrate_bridge::Config, @@ -487,7 +491,7 @@ pub mod target { /// Verify proof of Bridged -> This chain messages using given message proof parser. pub(crate) fn verify_messages_proof_with_parser( proof: FromBridgedChainMessagesProof, - messages_count: MessageNonce, + messages_count: u32, build_parser: BuildParser, ) -> Result>>>, MessageProofError> where @@ -497,11 +501,18 @@ pub mod target { let (bridged_header_hash, bridged_storage_proof, lane_id, begin, end) = proof; // receiving proofs where end < begin is ok (if proof includes outbound lane state) - // => hence unwrap_or(0) - let messages_in_the_proof = end.checked_sub(begin).and_then(|diff| diff.checked_add(1)).unwrap_or(0); - if messages_in_the_proof != messages_count { - return Err(MessageProofError::MessagesCountMismatch); - } + let messages_in_the_proof = if let Some(nonces_difference) = end.checked_sub(begin) { + // let's check that the user (relayer) has passed correct `messages_count` + // (this bounds maximal capacity of messages vec below) + let messages_in_the_proof = nonces_difference.saturating_add(1); + if messages_in_the_proof != MessageNonce::from(messages_count) { + return Err(MessageProofError::MessagesCountMismatch); + } + + messages_in_the_proof + } else { + 0 + }; let parser = build_parser(bridged_header_hash, bridged_storage_proof)?; @@ -509,7 +520,7 @@ pub mod target { // be in the proof. So any error in `read_value`, or even missing value is fatal. // // Mind that we allow proofs with no messages if outbound lane state is proved. - let mut messages = Vec::with_capacity(end.saturating_sub(begin) as _); + let mut messages = Vec::with_capacity(messages_in_the_proof as _); for nonce in begin..=end { let message_key = MessageKey { lane_id, nonce }; let raw_message_data = parser @@ -1183,4 +1194,30 @@ mod tests { .collect()), ); } + + #[test] + fn verify_messages_proof_with_parser_does_not_panic_if_messages_count_mismatches() { + assert_eq!( + target::verify_messages_proof_with_parser::( + ( + Default::default(), + StorageProof::new(vec![]), + Default::default(), + 0, + u64::MAX + ), + 0, + |_, _| Ok(TestMessageProofParser { + failing: false, + messages: 0..=u64::MAX, + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, + }), + }), + ), + Err(target::MessageProofError::MessagesCountMismatch), + ); + } } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index b667120f101eb..b6cf818f5bd9c 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -101,6 +101,10 @@ pub trait Config: frame_system::Config { /// /// There is no point of making this parameter lesser than MaxUnrewardedRelayerEntriesAtInboundLane, /// because then maximal number of relayer entries will be limited by maximal number of messages. + /// + /// This value also represents maximal number of messages in single delivery transaction. Transaction + /// that is declaring more messages than this value, will be rejected. Even if these messages are + /// from different lanes. type MaxUnconfirmedMessagesAtInboundLane: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. @@ -156,6 +160,8 @@ decl_error! { MessageRejectedByLaneVerifier, /// Submitter has failed to pay fee for delivering and dispatching messages. FailedToWithdrawMessageFee, + /// The transaction brings too many messages. + TooManyMessagesInTheProof, /// Invalid messages has been submitted. InvalidMessagesProof, /// Invalid messages dispatch weight has been declared by the relayer. @@ -344,19 +350,25 @@ decl_module! { /// this data in the transaction, so reward confirmations lags should be minimal. #[weight = T::WeightInfo::receive_messages_proof_overhead() .saturating_add(T::WeightInfo::receive_messages_proof_outbound_lane_state_overhead()) - .saturating_add(T::WeightInfo::receive_messages_proof_messages_overhead(*messages_count)) + .saturating_add(T::WeightInfo::receive_messages_proof_messages_overhead(MessageNonce::from(*messages_count))) .saturating_add(*dispatch_weight) ] pub fn receive_messages_proof( origin, relayer_id: T::InboundRelayer, proof: MessagesProofOf, - messages_count: MessageNonce, + messages_count: u32, dispatch_weight: Weight, ) -> DispatchResult { ensure_operational::()?; let _ = ensure_signed(origin)?; + // reject transactions that are declaring too many messages + ensure!( + MessageNonce::from(messages_count) <= T::MaxUnconfirmedMessagesAtInboundLane::get(), + Error::::TooManyMessagesInTheProof + ); + // verify messages proof && convert proof into messages let messages = verify_and_decode_messages_proof::< T::SourceHeaderChain, @@ -457,7 +469,8 @@ decl_module! { // verify that the relayer has declared correct `lane_data::relayers` state // (we only care about total number of entries and messages, because this affects call weight) ensure!( - total_unrewarded_messages(&lane_data.relayers) == relayers_state.total_messages + total_unrewarded_messages(&lane_data.relayers) + .unwrap_or(MessageNonce::MAX) == relayers_state.total_messages && lane_data.relayers.len() as MessageNonce == relayers_state.unrewarded_relayer_entries, Error::::InvalidUnrewardedRelayersState ); @@ -545,7 +558,7 @@ impl, I: Instance> Module { bp_message_lane::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers), + total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), } } @@ -733,8 +746,11 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStora /// Verify messages proof and return proved messages with decoded payload. fn verify_and_decode_messages_proof, Fee, DispatchPayload: Decode>( proof: Chain::MessagesProof, - messages_count: MessageNonce, + messages_count: u32, ) -> Result>, Chain::Error> { + // `receive_messages_proof` weight formula and `MaxUnconfirmedMessagesAtInboundLane` check + // guarantees that the `message_count` is sane and Vec may be allocated. + // (tx with too many messages will either be rejected from the pool, or will fail earlier) Chain::verify_messages_proof(proof, messages_count).map(|messages_by_lane| { messages_by_lane .into_iter() @@ -1073,6 +1089,22 @@ mod tests { }); } + #[test] + fn receive_messages_proof_rejects_proof_with_too_many_messages() { + run_test(|| { + assert_noop!( + Module::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + u32::MAX, + 0, + ), + Error::::TooManyMessagesInTheProof, + ); + }); + } + #[test] fn receive_messages_delivery_proof_works() { run_test(|| { diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 98ae5c6f608df..94f570a84d317 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -309,7 +309,7 @@ impl SourceHeaderChain for TestSourceHeaderChain { fn verify_messages_proof( proof: Self::MessagesProof, - _messages_count: MessageNonce, + _messages_count: u32, ) -> Result>, Self::Error> { proof .result diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 9dba82a71c200..74086cccce846 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -158,11 +158,36 @@ impl Default for OutboundLaneData { } /// Returns total number of messages in the `InboundLaneData::relayers` vector. +/// +/// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`). pub fn total_unrewarded_messages( relayers: &VecDeque<(MessageNonce, MessageNonce, RelayerId)>, -) -> MessageNonce { +) -> Option { match (relayers.front(), relayers.back()) { - (Some((begin, _, _)), Some((_, end, _))) => end.checked_sub(*begin).and_then(|d| d.checked_add(1)).unwrap_or(0), - _ => 0, + (Some((begin, _, _)), Some((_, end, _))) => { + if let Some(difference) = end.checked_sub(*begin) { + difference.checked_add(1) + } else { + Some(0) + } + } + _ => Some(0), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn total_unrewarded_messages_does_not_overflow() { + assert_eq!( + total_unrewarded_messages( + &vec![(0, 0, 1), (MessageNonce::MAX, MessageNonce::MAX, 2)] + .into_iter() + .collect() + ), + None, + ); } } diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index 04eab55affd87..c79b534156f64 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -16,7 +16,7 @@ //! Primitives of message lane module, that are used on the target chain. -use crate::{LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData}; +use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; @@ -72,9 +72,13 @@ pub trait SourceHeaderChain { /// /// Messages vector is required to be sorted by nonce within each lane. Out-of-order /// messages will be rejected. + /// + /// The `messages_count` argument verification (sane limits) is supposed to be made + /// outside of this function. This function only verifies that the proof declares exactly + /// `messages_count` messages. fn verify_messages_proof( proof: Self::MessagesProof, - messages_count: MessageNonce, + messages_count: u32, ) -> Result>, Self::Error>; } diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index b5d1db888e96d..1f8088fa7f31d 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -81,7 +81,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let call = rialto_runtime::MessageLaneCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, - messages_count, + messages_count as _, dispatch_weight, ) .into(); diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 22e56e312d99f..a9ab41b41fe80 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -81,7 +81,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let call = millau_runtime::MessageLaneCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, - messages_count, + messages_count as _, dispatch_weight, ) .into(); From fa32a9f439a34e65846433d60235031596574cb1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 21 Jan 2021 12:35:04 +0300 Subject: [PATCH 0302/1210] Use real weights to compute message delivery and dispatch fee (#598) * message fee formula * update GetDelvieryConfirmationTransactionFee * include cost of transactions (i.e. not only dispatch cost) in delivery_and_dispatch_fee * endow relayers fund account * include db ops weight in max tx weight estimation * (in bytes) Co-authored-by: Hernando Castano --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/chain_spec.rs | 1 + bin/millau/runtime/src/lib.rs | 19 +++++++- bin/millau/runtime/src/rialto_messages.rs | 32 ++++++++++---- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/chain_spec.rs | 1 + bin/rialto/runtime/src/lib.rs | 12 +++-- bin/rialto/runtime/src/millau_messages.rs | 32 ++++++++++---- bin/runtime-common/src/messages.rs | 54 +++++++++++++---------- modules/message-lane/rpc/Cargo.toml | 1 + modules/message-lane/rpc/src/lib.rs | 17 ++++++- modules/message-lane/src/lib.rs | 7 ++- modules/message-lane/src/weights_ext.rs | 29 +++++++++++- primitives/message-lane/src/lib.rs | 34 ++++++++++++++ primitives/millau/src/lib.rs | 38 ++++++++++++++++ primitives/rialto/src/lib.rs | 38 ++++++++++++++++ 16 files changed, 265 insertions(+), 52 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 34044c2766305..83ff05f7049cf 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -19,6 +19,7 @@ bp-message-lane = { path = "../../../primitives/message-lane" } bp-millau= { path = "../../../primitives/millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } +pallet-message-lane = { path = "../../../modules/message-lane" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } # Substrate Dependencies diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 2ead8612fac21..bf1dce3ae5594 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -122,6 +122,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + pallet_message_lane::Module::::relayer_fund_account_id(), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 0e56f24d66085..e79b34d2790ef 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -315,8 +315,9 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; - // TODO: https://github.com/paritytech/parity-bridges-common/pull/598 - pub GetDeliveryConfirmationTransactionFee: Balance = 0; + // `IdentityFee` is used by Millau => we may use weight directly + pub const GetDeliveryConfirmationTransactionFee: Balance = + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; } @@ -594,3 +595,17 @@ impl_runtime_apis! { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ensure_millau_message_lane_weights_are_correct() { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 + pallet_message_lane::ensure_weights_are_correct::>( + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ); + } +} diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 5129276d04f9b..9f2144b5636d5 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -26,7 +26,7 @@ use bp_message_lane::{ use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ - weights::{Weight, WeightToFeePolynomial}, + weights::{DispatchClass, Weight, WeightToFeePolynomial}, RuntimeDebug, }; use sp_core::storage::StorageKey; @@ -98,21 +98,35 @@ impl MessageBridge for WithRialtoMessageBridge { // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() - let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + let lower_limit = u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX); lower_limit..=upper_limit } - fn weight_of_delivery_transaction() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX) + .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + ) } fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 - } - - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + let inbounded_data_size: Weight = + InboundLaneData::::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) + .map(Into::into) + .unwrap_or(Weight::MAX); + + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + inbounded_data_size.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ) } fn this_weight_to_this_balance(weight: Weight) -> bp_millau::Balance { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index c2620ab9e3cec..aade85879c551 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -18,6 +18,7 @@ structopt = "0.3.21" bp-message-lane = { path = "../../../primitives/message-lane" } bp-runtime = { path = "../../../primitives/runtime" } bp-rialto = { path = "../../../primitives/rialto" } +pallet-message-lane = { path = "../../../modules/message-lane" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } rialto-runtime = { path = "../runtime" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index dc2a9afea6135..cf90802239569 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -122,6 +122,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + pallet_message_lane::Module::::relayer_fund_account_id(), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a77d590612609..060784ab3ec56 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -419,11 +419,12 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_message_lane::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; - // TODO: https://github.com/paritytech/parity-bridges-common/pull/598 - pub GetDeliveryConfirmationTransactionFee: Balance = 0; + // `IdentityFee` is used by Rialto => we may use weight directly + pub const GetDeliveryConfirmationTransactionFee: Balance = + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; } @@ -1026,7 +1027,10 @@ mod tests { #[test] fn ensure_rialto_message_lane_weights_are_correct() { - pallet_message_lane::ensure_weights_are_correct::>(); + pallet_message_lane::ensure_weights_are_correct::>( + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ); } #[test] diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 173bde8cad6e8..61a8682d12754 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -26,7 +26,7 @@ use bp_message_lane::{ use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; use frame_support::{ - weights::{Weight, WeightToFeePolynomial}, + weights::{DispatchClass, Weight, WeightToFeePolynomial}, RuntimeDebug, }; use sp_core::storage::StorageKey; @@ -99,21 +99,35 @@ impl MessageBridge for WithMillauMessageBridge { // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() - let lower_limit = Weight::try_from(message_payload.len()).unwrap_or(Weight::MAX); + let lower_limit = u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX); lower_limit..=upper_limit } - fn weight_of_delivery_transaction() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX) + .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + ) } fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 - } - - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - 0 // TODO: https://github.com/paritytech/parity-bridges-common/issues/391 + let inbounded_data_size: Weight = + InboundLaneData::::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) + .map(Into::into) + .unwrap_or(Weight::MAX); + + messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + inbounded_data_size.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + ) } fn this_weight_to_this_balance(weight: Weight) -> bp_rialto::Balance { diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 897de2af6a224..cd84612d109be 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -28,7 +28,7 @@ use bp_message_lane::{ }; use bp_runtime::InstanceId; use codec::{Compact, Decode, Encode, Input}; -use frame_support::{traits::Instance, RuntimeDebug}; +use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; @@ -65,16 +65,11 @@ pub trait MessageBridge { ) -> RangeInclusive>>; /// Maximal weight of single message delivery transaction on Bridged chain. - fn weight_of_delivery_transaction() -> WeightOf>; + fn weight_of_delivery_transaction(message_payload: &[u8]) -> WeightOf>; /// Maximal weight of single message delivery confirmation transaction on This chain. fn weight_of_delivery_confirmation_transaction_on_this_chain() -> WeightOf>; - /// Weight of single message reward confirmation on the Bridged chain. This confirmation - /// is a part of delivery transaction, so this weight is added to the delivery - /// transaction weight. - fn weight_of_reward_confirmation_transaction_on_target_chain() -> WeightOf>; - /// Convert weight of This chain to the fee (paid in Balance) of This chain. fn this_weight_to_this_balance(weight: WeightOf>) -> BalanceOf>; @@ -120,6 +115,31 @@ pub(crate) type BalanceOf = ::Balance; pub(crate) type CallOf = ::Call; pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; +/// Compute weight of transaction at runtime where: +/// +/// - transaction payment pallet is being used; +/// - fee multiplier is zero. +pub fn transaction_weight_without_multiplier( + base_weight: Weight, + payload_size: Weight, + dispatch_weight: Weight, +) -> Weight { + // non-adjustable per-byte weight is mapped 1:1 to tx weight + let per_byte_weight = payload_size; + + // we assume that adjustable per-byte weight is always zero + let adjusted_per_byte_weight = 0; + + // we assume that transaction tip we use is also zero + let transaction_tip_weight = 0; + + base_weight + .saturating_add(per_byte_weight) + .saturating_add(adjusted_per_byte_weight) + .saturating_add(transaction_tip_weight) + .saturating_add(dispatch_weight) +} + /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -226,10 +246,8 @@ pub mod source { relayer_fee_percent: u32, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction()); + let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction(&payload.call)); let dispatch_fee = B::bridged_weight_to_bridged_balance(payload.weight.into()); - let reward_confirmation_fee = - B::bridged_weight_to_bridged_balance(B::weight_of_reward_confirmation_transaction_on_target_chain()); // the fee (in This tokens) of all transactions that are made on This chain let delivery_confirmation_fee = @@ -238,7 +256,6 @@ pub mod source { // minimal fee (in This tokens) is a sum of all required fees let minimal_fee = delivery_fee .checked_add(&dispatch_fee) - .and_then(|fee| fee.checked_add(&reward_confirmation_fee)) .map(B::bridged_balance_to_this_balance) .and_then(|fee| fee.checked_add(&delivery_confirmation_fee)); @@ -570,7 +587,6 @@ mod tests { const DELIVERY_TRANSACTION_WEIGHT: Weight = 100; const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; - const REWARD_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; @@ -596,7 +612,7 @@ mod tests { begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } - fn weight_of_delivery_transaction() -> Weight { + fn weight_of_delivery_transaction(_message_payload: &[u8]) -> Weight { DELIVERY_TRANSACTION_WEIGHT } @@ -604,10 +620,6 @@ mod tests { DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT } - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - REWARD_CONFIRMATION_TRANSACTION_WEIGHT - } - fn this_weight_to_this_balance(weight: Weight) -> ThisChainBalance { ThisChainBalance(weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } @@ -639,7 +651,7 @@ mod tests { unreachable!() } - fn weight_of_delivery_transaction() -> Weight { + fn weight_of_delivery_transaction(_message_payload: &[u8]) -> Weight { unreachable!() } @@ -647,10 +659,6 @@ mod tests { unreachable!() } - fn weight_of_reward_confirmation_transaction_on_target_chain() -> Weight { - unreachable!() - } - fn this_weight_to_this_balance(_weight: Weight) -> BridgedChainBalance { unreachable!() } @@ -809,7 +817,7 @@ mod tests { #[test] fn message_fee_is_checked_by_verifier() { - const EXPECTED_MINIMAL_FEE: u32 = 8140; + const EXPECTED_MINIMAL_FEE: u32 = 5500; // payload of the This -> Bridged chain message let payload = source::FromThisChainMessagePayload:: { diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index 73111d0d28ec7..28481a7ad8834 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -12,6 +12,7 @@ futures = { version = "0.3.5", features = ["compat"] } jsonrpc-core = "15.1.0" jsonrpc-core-client = "15.1.0" jsonrpc-derive = "15.1.0" +log = "0.4.11" # Bridge dependencies diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/message-lane/rpc/src/lib.rs index df85064f3c414..8532ed0c5d0e7 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/message-lane/rpc/src/lib.rs @@ -116,6 +116,7 @@ where } else { None }; + let messages_count = if end >= begin { end - begin + 1 } else { 0 }; Box::new( prove_keys_read( self.backend.clone(), @@ -126,7 +127,15 @@ where ) .boxed() .compat() - .map(serialize_storage_proof) + .map(move |proof| { + let serialized_proof = serialize_storage_proof(proof); + log::trace!( + "Generated proof of {} messages. Size: {}", + messages_count, + serialized_proof.len() + ); + serialized_proof + }) .map_err(Into::into), ) } @@ -145,7 +154,11 @@ where ) .boxed() .compat() - .map(serialize_storage_proof) + .map(|proof| { + let serialized_proof = serialize_storage_proof(proof); + log::trace!("Generated message delivery proof. Size: {}", serialized_proof.len()); + serialized_proof + }) .map_err(Into::into), ) } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index b6cf818f5bd9c..9c44e7289bfd5 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -326,16 +326,19 @@ decl_module! { // finally, save message in outbound storage and emit event let mut lane = outbound_lane::(lane_id); + let encoded_payload = payload.encode(); + let encoded_payload_len = encoded_payload.len(); let nonce = lane.send_message(MessageData { - payload: payload.encode(), + payload: encoded_payload, fee: delivery_and_dispatch_fee, }); lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); frame_support::debug::trace!( - "Accepted message {} to lane {:?}", + "Accepted message {} to lane {:?}. Message size: {:?}", nonce, lane_id, + encoded_payload_len, ); Self::deposit_event(RawEvent::MessageAccepted(lane_id, nonce)); diff --git a/modules/message-lane/src/weights_ext.rs b/modules/message-lane/src/weights_ext.rs index b9b33a6f21f9e..95bc8239a9463 100644 --- a/modules/message-lane/src/weights_ext.rs +++ b/modules/message-lane/src/weights_ext.rs @@ -22,7 +22,10 @@ use bp_message_lane::MessageNonce; use frame_support::weights::Weight; /// Ensure that weights from `WeightInfoExt` implementation are looking correct. -pub fn ensure_weights_are_correct() { +pub fn ensure_weights_are_correct( + expected_max_single_message_delivery_tx_weight: Weight, + expected_max_messages_delivery_tx_weight: Weight, +) { assert_ne!(W::send_message_overhead(), 0); assert_ne!(W::send_message_size_overhead(0), 0); @@ -30,9 +33,33 @@ pub fn ensure_weights_are_correct() { assert_ne!(W::receive_messages_proof_messages_overhead(1), 0); assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), 0); + let actual_max_single_message_delivery_tx_weight = W::receive_messages_proof_overhead() + .checked_add(W::receive_messages_proof_messages_overhead(1)) + .expect("weights are too large") + .checked_add(W::receive_messages_proof_outbound_lane_state_overhead()) + .expect("weights are too large"); + assert!( + actual_max_single_message_delivery_tx_weight <= expected_max_single_message_delivery_tx_weight, + "Single message delivery transaction weight {} is larger than expected weight {}", + actual_max_single_message_delivery_tx_weight, + expected_max_single_message_delivery_tx_weight, + ); + assert_ne!(W::receive_messages_delivery_proof_overhead(), 0); assert_ne!(W::receive_messages_delivery_proof_messages_overhead(1), 0); assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1), 0); + + let actual_max_messages_delivery_tx_weight = W::receive_messages_delivery_proof_overhead() + .checked_add(W::receive_messages_delivery_proof_messages_overhead(1)) + .expect("weights are too large") + .checked_add(W::receive_messages_delivery_proof_relayers_overhead(1)) + .expect("weights are too large"); + assert!( + actual_max_messages_delivery_tx_weight <= expected_max_messages_delivery_tx_weight, + "Messages delivery confirmation transaction weight {} is larger than expected weight {}", + actual_max_messages_delivery_tx_weight, + expected_max_messages_delivery_tx_weight, + ); } /// Extended weight info. diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 74086cccce846..47f33970ae111 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -113,6 +113,17 @@ impl Default for InboundLaneData { } impl InboundLaneData { + /// Returns approximate size of the struct, given number of entries in the `relayers` set and + /// size of each entry. + /// + /// Returns `None` if size overflows `u32` limits. + pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32) -> Option { + let message_nonce_size = 8; + let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; + let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; + relayers_size.checked_add(message_nonce_size) + } + /// Nonce of the last message that has been delivered to this (target) chain. pub fn last_delivered_nonce(&self) -> MessageNonce { self.relayers @@ -191,3 +202,26 @@ mod tests { ); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn inbound_lane_data_returns_correct_hint() { + let expected_size = InboundLaneData::::encoded_size_hint(1, 13); + let actual_size = InboundLaneData { + relayers: (1u8..=13u8).map(|i| (i as _, i as _, i)).collect(), + last_confirmed_nonce: 13, + } + .encode() + .len(); + let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs(); + assert!( + difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1, + "Too large difference between actual ({}) and expected ({:?}) inbound lane data size", + actual_size, + expected_size, + ); + } +} diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 636697847cd40..5c0febdca399a 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -43,6 +43,14 @@ use serde::{Deserialize, Serialize}; pub use millau_hash::MillauHash; +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// Millau chain. This mostly depends on number of entries (and their density) in the storage trie. +/// Some reserve is reserved to account future chain growth. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. +pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; + /// Maximum weight of single Millau block. /// /// This represents 0.5 seconds of compute assuming a target block time of six seconds. @@ -61,6 +69,20 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal weight of single message delivery transaction on Millau chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation +/// for the case when single message is delivered. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; + +/// Maximal weight of single message delivery confirmation transaction on Millau chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_delivery_proof` weight formula computation +/// for the case when single message is confirmed. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; + /// Block number type used in Millau. pub type BlockNumber = u64; @@ -280,3 +302,19 @@ sp_api::decl_runtime_apis! { fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::codec::Encode; + + #[test] + fn maximal_account_size_does_not_overflow_constant() { + assert!( + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + "Actual maximal size of encoded AccountId ({}) overflows expected ({})", + AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + ); + } +} diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index a514254b22565..b347ce5ec5f88 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -34,6 +34,14 @@ use sp_runtime::{ }; use sp_std::prelude::*; +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie. +/// Some reserve is reserved to account future chain growth. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. +pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; + /// Maximal weight of single Rialto block. /// /// This represents two seconds of compute assuming a target block time of six seconds. @@ -52,6 +60,20 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal weight of single message delivery transaction on Rialto chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation +/// for the case when single message is delivered. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; + +/// Maximal weight of single message delivery confirmation transaction on Rialto chain. +/// +/// This value is a result of `pallet_message_lane::Module::receive_messages_delivery_proof` weight formula computation +/// for the case when single message is confirmed. The result then must be rounded up to account possible future +/// runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; + /// Block number type used in Rialto. pub type BlockNumber = u32; @@ -241,3 +263,19 @@ sp_api::decl_runtime_apis! { fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::codec::Encode; + + #[test] + fn maximal_account_size_does_not_overflow_constant() { + assert!( + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + "Actual maximal size of encoded AccountId ({}) overflows expected ({})", + AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + ); + } +} From 882a80d38642a0f1b19c45552e05609d0489f38b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 21 Jan 2021 04:37:10 -0500 Subject: [PATCH 0303/1210] Explain why we defer signature verification (#668) --- primitives/header-chain/src/justification.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 54a44d9b7ad04..3e4b9043c08a5 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -63,23 +63,25 @@ pub fn verify_justification( where Header::Number: finality_grandpa::BlockNumberOps, { - // decode justification first + // Decode justification first let justification = GrandpaJustification::
::decode(&mut &raw_justification[..]).map_err(|_| Error::JustificationDecode)?; - // ensure that it is justification for the expected header + // Ensure that it is justification for the expected header if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { return Err(Error::InvalidJustificationTarget); } - // validate commit of the justification (it just assumes all signatures are valid) + // Validate commit of the justification. Note that `validate_commit()` assumes that all + // signatures are valid. We'll check the validity of the signatures later since they're more + // resource intensive to verify. let ancestry_chain = AncestryChain::new(&justification.votes_ancestries); match finality_grandpa::validate_commit(&justification.commit, &authorities_set, &ancestry_chain) { Ok(ref result) if result.ghost().is_some() => {} _ => return Err(Error::InvalidJustificationCommit), } - // now that we know that the commit is correct, check authorities signatures + // Now that we know that the commit is correct, check authorities signatures let mut buf = Vec::new(); let mut visited_hashes = BTreeSet::new(); for signed in &justification.commit.precommits { From 418d1ba99edf0398ae8f7e8098c6b4bcab398175 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 21 Jan 2021 12:58:34 +0300 Subject: [PATCH 0304/1210] fix compilation (#671) --- primitives/message-lane/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 47f33970ae111..0c1dee7f2a010 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -201,11 +201,6 @@ mod tests { None, ); } -} - -#[cfg(test)] -mod tests { - use super::*; #[test] fn inbound_lane_data_returns_correct_hint() { From da4fd5d2e774d76bd67804c6c919923843d85c9a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 21 Jan 2021 10:09:59 -0500 Subject: [PATCH 0305/1210] Finality Verifier Pallet (#629) * Add skeleton for `pallet-finality-verifier` * Sketch out implementation for importing finality proofs * Get pallet compiling * Introduce skeleton for mock runtime * Start using real Grandpa types in finality pallet * Redefine types in header chain primitives crate * Implement HeaderChain for Substrate bridge pallet * Plug Substrate Bridge Pallet into verifier mock * Fix compilation of `header-chain` primitives * Start writing to base pallet storage * Add first "cross-pallet" test * Move keyring primitives used in tests to shared crate * Stop pulling `std` deps into `no_std` builds * Revert "Stop pulling `std` deps into `no_std` builds" This reverts commit f74dd660652f98b7336936d1534a4e63cc9169a5. * Revert "Move keyring primitives used in tests to shared crate" This reverts commit b774fa730b2cdc40545afff308a66b0840266001. * Use new SS58Prefix type in mock * Start using `bp-test-utils` in finality pallet * Start using real justification code * Get a test working with real justification verification * Add basic tests for invalid proofs * Get rid of AncestryProof config type * Add error types to transaction outcome * Bound number of headers allowed in a single ancestry proof * Disallow invalid authority sets * Remove unused items * Add some documentation * Get rid of Clippy warnings * Rename BaseHeaderChain to TransactionVerifier * Remove unused code * Make dummy trait implementations more generic * Fix more Clippy complaints * Update tests to use fix for duplicate headers * Fix benchmarking compilation * Rename TransactionVerifier to InclusionProofVerifier --- bin/rialto/runtime/src/kovan.rs | 4 +- bin/rialto/runtime/src/rialto_poa.rs | 4 +- modules/currency-exchange/src/benchmarking.rs | 6 +- modules/currency-exchange/src/lib.rs | 16 +- modules/finality-verifier/Cargo.toml | 45 +++ modules/finality-verifier/src/lib.rs | 300 ++++++++++++++++++ modules/finality-verifier/src/mock.rs | 110 +++++++ modules/substrate/Cargo.toml | 1 + modules/substrate/src/fork_tests.rs | 3 +- modules/substrate/src/lib.rs | 35 +- modules/substrate/src/storage.rs | 18 +- modules/substrate/src/verifier.rs | 4 +- primitives/header-chain/Cargo.toml | 4 +- primitives/header-chain/src/lib.rs | 80 ++++- 14 files changed, 592 insertions(+), 38 deletions(-) create mode 100644 modules/finality-verifier/Cargo.toml create mode 100644 modules/finality-verifier/src/lib.rs create mode 100644 modules/finality-verifier/src/mock.rs diff --git a/bin/rialto/runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs index bc2252bbb9594..fa76347db251e 100644 --- a/bin/rialto/runtime/src/kovan.rs +++ b/bin/rialto/runtime/src/kovan.rs @@ -17,7 +17,7 @@ use crate::exchange::EthereumTransactionInclusionProof; use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; -use bp_header_chain::BaseHeaderChain; +use bp_header_chain::InclusionProofVerifier; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_eth_poa::{ @@ -149,7 +149,7 @@ impl TChainTime for ChainTime { /// The Kovan Blockchain as seen by the runtime. pub struct KovanBlockchain; -impl BaseHeaderChain for KovanBlockchain { +impl InclusionProofVerifier for KovanBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; diff --git a/bin/rialto/runtime/src/rialto_poa.rs b/bin/rialto/runtime/src/rialto_poa.rs index 324179b55d88c..54ac8e25713a0 100644 --- a/bin/rialto/runtime/src/rialto_poa.rs +++ b/bin/rialto/runtime/src/rialto_poa.rs @@ -19,7 +19,7 @@ use crate::exchange::EthereumTransactionInclusionProof; use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; -use bp_header_chain::BaseHeaderChain; +use bp_header_chain::InclusionProofVerifier; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_eth_poa::{ @@ -124,7 +124,7 @@ impl TChainTime for ChainTime { /// The Rialto PoA Blockchain as seen by the runtime. pub struct RialtoBlockchain; -impl BaseHeaderChain for RialtoBlockchain { +impl InclusionProofVerifier for RialtoBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index 8b38d42eaa7ec..d10dd3c684126 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -18,7 +18,9 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{BaseHeaderChain, Call, Config as CurrencyExchangeConfig, Instance, Module as CurrencyExchangeModule}; +use super::{ + Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Instance, Module as CurrencyExchangeModule, +}; use sp_std::prelude::*; use frame_benchmarking::{account, benchmarks_instance}; @@ -50,7 +52,7 @@ pub trait Config: CurrencyExchangeConfig { /// Prepare proof for importing exchange transaction. fn make_proof( proof_params: ProofParams, - ) -> <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof; + ) -> <>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof; } benchmarks_instance! { diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index d3e12bff3902b..463b052caca90 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -21,7 +21,7 @@ use bp_currency_exchange::{ CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, }; -use bp_header_chain::BaseHeaderChain; +use bp_header_chain::InclusionProofVerifier; use frame_support::{decl_error, decl_module, decl_storage, ensure}; use sp_runtime::DispatchResult; @@ -39,10 +39,10 @@ pub trait Config: frame_system::Config { /// Handler for transaction submission result. type OnTransactionSubmitted: OnTransactionSubmitted; /// Represents the blockchain that we'll be exchanging currency with. - type PeerBlockchain: BaseHeaderChain; + type PeerBlockchain: InclusionProofVerifier; /// Peer blockchain transaction parser. type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< - Transaction = ::Transaction, + Transaction = ::Transaction, >; /// Map between blockchains recipients. type RecipientsMap: RecipientsMap< @@ -89,7 +89,7 @@ decl_module! { #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_peer_transaction( origin, - proof: <>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, + proof: <>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; @@ -134,7 +134,9 @@ decl_storage! { impl, I: Instance> Module { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. - pub fn filter_transaction_proof(proof: &::TransactionInclusionProof) -> bool { + pub fn filter_transaction_proof( + proof: &::TransactionInclusionProof, + ) -> bool { if let Err(err) = prepare_deposit_details::(proof) { frame_support::debug::trace!( target: "runtime", @@ -180,7 +182,7 @@ struct DepositDetails, I: Instance> { /// Verify and parse transaction proof, preparing everything required for importing /// this transaction proof. fn prepare_deposit_details, I: Instance>( - proof: &<>::PeerBlockchain as BaseHeaderChain>::TransactionInclusionProof, + proof: &<>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, ) -> Result, Error> { // ensure that transaction is included in finalized block that we know of let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) @@ -239,7 +241,7 @@ mod tests { pub struct DummyBlockchain; - impl BaseHeaderChain for DummyBlockchain { + impl InclusionProofVerifier for DummyBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = (bool, RawTransaction); diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml new file mode 100644 index 0000000000000..b98f995b61693 --- /dev/null +++ b/modules/finality-verifier/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pallet-finality-verifier" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +finality-grandpa = { version = "0.12.3", default-features = false } +serde = { version = "1.0", optional = true } + +# Bridge Dependencies + +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } + +[dev-dependencies] +bp-test-utils = {path = "../../primitives/test-utils" } +pallet-substrate-bridge = { path = "../../modules/substrate" } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } + + +[features] +default = ["std"] +std = [ + "bp-runtime/std", + "bp-header-chain/std", + "codec/std", + "finality-grandpa/std", + "frame-support/std", + "frame-system/std", + "serde", + "sp-runtime/std", + "sp-std/std", +] diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs new file mode 100644 index 0000000000000..299bc368d47ec --- /dev/null +++ b/modules/finality-verifier/src/lib.rs @@ -0,0 +1,300 @@ +// Copyright 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 . + +//! Substrate Finality Verifier Pallet +//! +//! The goal of this pallet is to provide a safe interface for writing finalized headers to an +//! external pallet which tracks headers and finality proofs. By safe, we mean that only headers +//! whose finality has been verified will be written to the underlying pallet. +//! +//! By verifying the finality of headers before writing them to storage we prevent DoS vectors in +//! which unfinalized headers get written to storage even if they don't have a chance of being +//! finalized in the future (such as in the case where a different fork gets finalized). +//! +//! The underlying pallet used for storage is assumed to be a pallet which tracks headers and +//! GRANDPA authority set changes. This information is used during the verification of GRANDPA +//! finality proofs. + +#![cfg_attr(not(feature = "std"), no_std)] +// Runtime-generated enums +#![allow(clippy::large_enum_variant)] + +use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain}; +use bp_runtime::{Chain, HeaderOf}; +use finality_grandpa::voter_set::VoterSet; +use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get}; +use frame_system::ensure_signed; +use sp_runtime::traits::Header as HeaderT; + +#[cfg(test)] +mod mock; + +/// Header of the bridged chain. +pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; + +/// The module configuration trait. +pub trait Config: frame_system::Config { + /// The chain we are bridging to here. + type BridgedChain: Chain; + /// The pallet which we will use as our underlying storage mechanism. + type HeaderChain: HeaderChain<::Header>; + /// The type through which we will verify that a given header is related to the last + /// finalized header in our storage pallet. + type AncestryChecker: AncestryChecker< + ::Header, + Vec<::Header>, + >; + /// The maximum length of headers we can have in a single ancestry proof. This prevents + /// unbounded iteration when verifying proofs. + type MaxHeadersInSingleProof: Get; +} + +decl_storage! { + trait Store for Module as FinalityVerifier {} +} + +decl_error! { + pub enum Error for Module { + /// The given justification is invalid for the given header. + InvalidJustification, + /// The given ancestry proof is unable to verify that the child and ancestor headers are + /// related. + InvalidAncestryProof, + /// The authority set from the underlying header chain is invalid. + InvalidAuthoritySet, + /// Failed to write a header to the underlying header chain. + FailedToWriteHeader, + /// Failed to write finality proof to the underlying header chain. + FailedToWriteFinalityProof, + /// The given ancestry proof is too large to be verified in a single transaction. + OversizedAncestryProof, + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + + /// Verify a header is finalized according to the given finality proof. + /// + /// Will use the underlying storage pallet to fetch information about the current + /// authorities and best finalized header in order to verify that the header is finalized. + /// + /// If successful in verification, it will write the headers to the underlying storage + /// pallet as well as import the valid finality proof. + #[weight = 0] + pub fn submit_finality_proof( + origin, + finality_target: BridgedHeader, + justification: Vec, + ancestry_proof: Vec>, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + + ensure!( + ancestry_proof.len() <= T::MaxHeadersInSingleProof::get() as usize, + >::OversizedAncestryProof + ); + + let authority_set = T::HeaderChain::authority_set(); + let voter_set = + VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; + let set_id = authority_set.set_id; + + verify_justification::>( + (finality_target.hash(), *finality_target.number()), + set_id, + voter_set, + &justification + ) + .map_err(|_| >::InvalidJustification)?; + + let best_finalized = T::HeaderChain::best_finalized(); + ensure!( + T::AncestryChecker::are_ancestors(&best_finalized, &finality_target, &ancestry_proof), + >::InvalidAncestryProof + ); + + // If for whatever reason we are unable to fully import headers and the corresponding + // finality proof we want to avoid writing to the base pallet storage + use frame_support::storage::{with_transaction, TransactionOutcome}; + with_transaction(|| { + for header in ancestry_proof { + if T::HeaderChain::import_header(header).is_err() { + return TransactionOutcome::Rollback(Err(>::FailedToWriteHeader)) + } + } + + if T::HeaderChain::import_finality_proof(finality_target, justification).is_err() { + return TransactionOutcome::Rollback(Err(>::FailedToWriteFinalityProof)) + } + + TransactionOutcome::Commit(Ok(())) + })?; + + Ok(()) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{run_test, test_header, Origin, TestRuntime}; + use bp_test_utils::{authority_list, make_justification_for_header}; + use codec::Encode; + use frame_support::{assert_err, assert_ok}; + + fn initialize_substrate_bridge() { + let genesis = test_header(0); + + let init_data = pallet_substrate_bridge::InitializationData { + header: genesis, + authority_list: authority_list(), + set_id: 1, + scheduled_change: None, + is_halted: false, + }; + + assert_ok!(pallet_substrate_bridge::Module::::initialize( + Origin::root(), + init_data + )); + } + + #[test] + fn succesfully_imports_header_with_valid_finality_and_ancestry_proofs() { + run_test(|| { + initialize_substrate_bridge(); + + let child = test_header(1); + let header = test_header(2); + + let set_id = 1; + let grandpa_round = 1; + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let ancestry_proof = vec![child, header.clone()]; + + assert_ok!(Module::::submit_finality_proof( + Origin::signed(1), + header.clone(), + justification, + ancestry_proof, + )); + + assert_eq!( + pallet_substrate_bridge::Module::::best_headers(), + vec![(*header.number(), header.hash())] + ); + + assert_eq!(pallet_substrate_bridge::Module::::best_finalized(), header); + }) + } + + #[test] + fn does_not_import_header_with_invalid_finality_proof() { + run_test(|| { + initialize_substrate_bridge(); + + let child = test_header(1); + let header = test_header(2); + + let justification = [1u8; 32].encode(); + let ancestry_proof = vec![child, header.clone()]; + + assert_err!( + Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + >::InvalidJustification + ); + }) + } + + #[test] + fn does_not_import_header_with_invalid_ancestry_proof() { + run_test(|| { + initialize_substrate_bridge(); + + let header = test_header(2); + + let set_id = 1; + let grandpa_round = 1; + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + + // For testing, we've made it so that an empty ancestry proof is invalid + let ancestry_proof = vec![]; + + assert_err!( + Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + >::InvalidAncestryProof + ); + }) + } + + #[test] + fn disallows_ancestry_proofs_which_are_too_large() { + run_test(|| { + initialize_substrate_bridge(); + + let header = test_header(1); + let justification = [1u8; 32].encode(); + + let mut ancestry_proof = vec![]; + let max_len = ::MaxHeadersInSingleProof::get(); + for i in 1..=max_len + 1 { + ancestry_proof.push(test_header(i as u64)); + } + + assert_err!( + Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + >::OversizedAncestryProof + ); + }) + } + + #[test] + fn disallows_invalid_authority_set() { + run_test(|| { + use bp_test_utils::{alice, bob}; + + let genesis = test_header(0); + + let invalid_authority_list = vec![(alice(), u64::MAX), (bob(), u64::MAX)]; + let init_data = pallet_substrate_bridge::InitializationData { + header: genesis, + authority_list: invalid_authority_list, + set_id: 1, + scheduled_change: None, + is_halted: false, + }; + + assert_ok!(pallet_substrate_bridge::Module::::initialize( + Origin::root(), + init_data + )); + + let header = test_header(1); + let justification = [1u8; 32].encode(); + let ancestry_proof = vec![]; + + assert_err!( + Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + >::InvalidAuthoritySet + ); + }) + } +} diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs new file mode 100644 index 0000000000000..71b1e28420593 --- /dev/null +++ b/modules/finality-verifier/src/mock.rs @@ -0,0 +1,110 @@ +// 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 . + +use crate::{BridgedHeader, Config}; +use bp_runtime::{BlockNumberOf, Chain}; +use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use sp_runtime::{ + testing::{Header, H256}, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +pub type AccountId = u64; +pub type TestHeader = BridgedHeader; +pub type TestNumber = BlockNumberOf<::BridgedChain>; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub struct TestRuntime; + +impl_outer_origin! { + pub enum Origin for TestRuntime where system = frame_system {} +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Config for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = (); + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = (); + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = (); + type SystemWeightInfo = (); + type DbWeight = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = (); +} + +impl pallet_substrate_bridge::Config for TestRuntime { + type BridgedChain = TestBridgedChain; +} + +parameter_types! { + pub const MaxHeadersInSingleProof: u8 = 5; +} + +impl crate::Config for TestRuntime { + type BridgedChain = TestBridgedChain; + type HeaderChain = pallet_substrate_bridge::Module; + type AncestryChecker = Checker<::Header, Vec<::Header>>; + type MaxHeadersInSingleProof = MaxHeadersInSingleProof; +} + +#[derive(Debug)] +pub struct TestBridgedChain; + +impl Chain for TestBridgedChain { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hashing; + type Header = ::Header; +} + +#[derive(Debug)] +pub struct Checker(std::marker::PhantomData<(H, P)>); + +impl crate::AncestryChecker> for Checker> { + fn are_ancestors(_ancestor: &H, _child: &H, proof: &Vec) -> bool { + !proof.is_empty() + } +} + +pub fn run_test(test: impl FnOnce() -> T) -> T { + sp_io::TestExternalities::new(Default::default()).execute_with(test) +} + +pub fn test_header(num: TestNumber) -> TestHeader { + // We wrap the call to avoid explicit type annotations in our tests + bp_test_utils::test_header(num) +} diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 8eb253606101d..02c3b17047eef 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -38,6 +38,7 @@ default = ["std"] std = [ "bp-header-chain/std", "bp-runtime/std", + "bp-header-chain/std", "codec/std", "finality-grandpa/std", "frame-support/std", diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index a2529dec13d5e..810678852c465 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -55,9 +55,10 @@ //! because the header is an old header. use crate::mock::*; -use crate::storage::{AuthoritySet, ImportedHeader}; +use crate::storage::ImportedHeader; use crate::verifier::*; use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; +use bp_header_chain::AuthoritySet; use bp_test_utils::{alice, authority_list, bob, make_justification_for_header}; use codec::Encode; use frame_support::{IterableStorageMap, StorageValue}; diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index e1c797c2ae22c..9644e508ed0c2 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -32,6 +32,7 @@ #![allow(clippy::large_enum_variant)] use crate::storage::ImportedHeader; +use bp_header_chain::AuthoritySet; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use frame_support::{ decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, weights::DispatchClass, @@ -43,7 +44,7 @@ use sp_std::{marker::PhantomData, prelude::*}; use sp_trie::StorageProof; // Re-export since the node uses these when configuring genesis -pub use storage::{AuthoritySet, InitializationData, ScheduledChange}; +pub use storage::{InitializationData, ScheduledChange}; pub use storage_proof::StorageProofChecker; @@ -361,6 +362,38 @@ impl Module { } } +impl bp_header_chain::HeaderChain> for Module { + fn best_finalized() -> BridgedHeader { + PalletStorage::::new().best_finalized_header().header + } + + fn authority_set() -> AuthoritySet { + PalletStorage::::new().current_authority_set() + } + + fn import_header(header: BridgedHeader) -> Result<(), ()> { + let mut verifier = verifier::Verifier { + storage: PalletStorage::::new(), + }; + + let _ = verifier.import_header(header.hash(), header).map_err(|_| ())?; + + Ok(()) + } + + fn import_finality_proof(header: BridgedHeader, finality_proof: Vec) -> Result<(), ()> { + let mut verifier = verifier::Verifier { + storage: PalletStorage::::new(), + }; + + let _ = verifier + .import_finality_proof(header.hash(), finality_proof.into()) + .map_err(|_| ())?; + + Ok(()) + } +} + /// Ensure that the origin is either root, or `ModuleOwner`. fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs index 93f30bdec7c9a..5b521306b2cd1 100644 --- a/modules/substrate/src/storage.rs +++ b/modules/substrate/src/storage.rs @@ -16,6 +16,7 @@ //! Storage primitives for the Substrate light client (a.k.a bridge) pallet. +use bp_header_chain::AuthoritySet; use codec::{Decode, Encode}; use core::default::Default; #[cfg(feature = "std")] @@ -42,23 +43,6 @@ pub struct InitializationData { pub is_halted: bool, } -/// A GRANDPA Authority List and ID. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct AuthoritySet { - /// List of GRANDPA authorities for the current round. - pub authorities: AuthorityList, - /// Monotonic identifier of the current GRANDPA authority set. - pub set_id: SetId, -} - -impl AuthoritySet { - /// Create a new GRANDPA Authority Set. - pub fn new(authorities: AuthorityList, set_id: SetId) -> Self { - Self { authorities, set_id } - } -} - /// Keeps track of when the next GRANDPA authority set change will occur. #[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 5cb47cb6566e8..b22d69f78db87 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -22,10 +22,10 @@ //! has been signed off by the correct GRANDPA authorities, and also enact any authority set changes //! if required. -use crate::storage::{AuthoritySet, ImportedHeader, ScheduledChange}; +use crate::storage::{ImportedHeader, ScheduledChange}; use crate::BridgeStorage; -use bp_header_chain::justification::verify_justification; +use bp_header_chain::{justification::verify_justification, AuthoritySet}; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::generic::OpaqueDigestItemId; diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index d9b4a70e57ce1..ecd5f05940e0e 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } +serde = { version = "1.0", optional = true } # Substrate Dependencies @@ -20,15 +21,16 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master [dev-dependencies] bp-test-utils = { path = "../test-utils" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [features] default = ["std"] std = [ "codec/std", "finality-grandpa/std", + "serde/std", "frame-support/std", "sp-core/std", "sp-finality-grandpa/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 00978d8081d1d..699e79cae59ea 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,10 +19,16 @@ #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Codec, EncodeLike}; +use codec::{Codec, Decode, Encode, EncodeLike}; use core::clone::Clone; use core::cmp::Eq; +use core::default::Default; use core::fmt::Debug; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_finality_grandpa::{AuthorityList, SetId}; +use sp_runtime::RuntimeDebug; +use sp_std::prelude::Vec; pub mod justification; @@ -32,8 +38,25 @@ pub mod justification; pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug {} impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug {} -/// A base trait for pallets which want to keep track of a full set of headers from a bridged chain. -pub trait BaseHeaderChain { +/// A GRANDPA Authority List and ID. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct AuthoritySet { + /// List of GRANDPA authorities for the current round. + pub authorities: AuthorityList, + /// Monotonic identifier of the current GRANDPA authority set. + pub set_id: SetId, +} + +impl AuthoritySet { + /// Create a new GRANDPA Authority Set. + pub fn new(authorities: AuthorityList, set_id: SetId) -> Self { + Self { authorities, set_id } + } +} + +/// base trait for verifying transaction inclusion proofs. +pub trait InclusionProofVerifier { /// Transaction type. type Transaction: Parameter; /// Transaction inclusion proof type. @@ -44,3 +67,54 @@ pub trait BaseHeaderChain { /// Returns Some(transaction) if proof is valid and None otherwise. fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option; } + +/// A base trait for pallets which want to keep track of a full set of headers from a bridged chain. +pub trait HeaderChain { + /// Get the best finalized header known to the header chain. + fn best_finalized() -> H; + + /// Get the best authority set known to the header chain. + fn authority_set() -> AuthoritySet; + + /// Write the given header to the underlying pallet storage. + #[allow(clippy::result_unit_err)] + fn import_header(header: H) -> Result<(), ()>; + + /// Submit a valid finality proof for the given header to the underlying pallet storage. + /// + /// This will finalize the given header and enact any authority set changes if required. + #[allow(clippy::result_unit_err)] + fn import_finality_proof(header: H, finality_proof: Vec) -> Result<(), ()>; +} + +impl HeaderChain for () { + fn best_finalized() -> H { + H::default() + } + + fn authority_set() -> AuthoritySet { + AuthoritySet::default() + } + + #[allow(clippy::result_unit_err)] + fn import_header(_header: H) -> Result<(), ()> { + Ok(()) + } + + #[allow(clippy::result_unit_err)] + fn import_finality_proof(_header: H, _finality_proof: Vec) -> Result<(), ()> { + Ok(()) + } +} + +/// A trait for checking if a given child header is a direct decendant of an ancestor. +pub trait AncestryChecker { + /// Is the child header a decendant of the ancestor header? + fn are_ancestors(ancestor: &H, child: &H, proof: &P) -> bool; +} + +impl AncestryChecker for () { + fn are_ancestors(_ancestor: &H, _child: &H, _proof: &P) -> bool { + true + } +} From 923855b5b33396ace2782930642dae8869fc9cad Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 22 Jan 2021 13:07:37 -0500 Subject: [PATCH 0306/1210] Migrate Finality Verifier Pallet to FRAME v2 (#669) * Get pallet compiling with FRAME v2 * Get tests compiling * Stop printing metadata in tests * Remove more metadata related code * Remove unecessary storage attribute --- modules/finality-verifier/src/lib.rs | 115 ++++++++++++++------------ modules/finality-verifier/src/mock.rs | 6 +- 2 files changed, 65 insertions(+), 56 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 299bc368d47ec..170b03462ef7b 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -35,59 +35,51 @@ use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain}; use bp_runtime::{Chain, HeaderOf}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get}; +use frame_support::{ensure, traits::Get}; use frame_system::ensure_signed; use sp_runtime::traits::Header as HeaderT; #[cfg(test)] mod mock; -/// Header of the bridged chain. -pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; - -/// The module configuration trait. -pub trait Config: frame_system::Config { - /// The chain we are bridging to here. - type BridgedChain: Chain; - /// The pallet which we will use as our underlying storage mechanism. - type HeaderChain: HeaderChain<::Header>; - /// The type through which we will verify that a given header is related to the last - /// finalized header in our storage pallet. - type AncestryChecker: AncestryChecker< - ::Header, - Vec<::Header>, - >; - /// The maximum length of headers we can have in a single ancestry proof. This prevents - /// unbounded iteration when verifying proofs. - type MaxHeadersInSingleProof: Get; -} - -decl_storage! { - trait Store for Module as FinalityVerifier {} -} - -decl_error! { - pub enum Error for Module { - /// The given justification is invalid for the given header. - InvalidJustification, - /// The given ancestry proof is unable to verify that the child and ancestor headers are - /// related. - InvalidAncestryProof, - /// The authority set from the underlying header chain is invalid. - InvalidAuthoritySet, - /// Failed to write a header to the underlying header chain. - FailedToWriteHeader, - /// Failed to write finality proof to the underlying header chain. - FailedToWriteFinalityProof, - /// The given ancestry proof is too large to be verified in a single transaction. - OversizedAncestryProof, +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + /// Header of the bridged chain. + pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The chain we are bridging to here. + type BridgedChain: Chain; + + /// The pallet which we will use as our underlying storage mechanism. + type HeaderChain: HeaderChain<::Header>; + + /// The type through which we will verify that a given header is related to the last + /// finalized header in our storage pallet. + type AncestryChecker: AncestryChecker< + ::Header, + Vec<::Header>, + >; + + /// The maximum length of headers we can have in a single ancestry proof. This prevents + /// unbounded iteration when verifying proofs. + #[pallet::constant] + type MaxHeadersInSingleProof: Get; } -} -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; + #[pallet::pallet] + pub struct Pallet(PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + #[pallet::call] + impl Pallet { /// Verify a header is finalized according to the given finality proof. /// /// Will use the underlying storage pallet to fetch information about the current @@ -95,13 +87,13 @@ decl_module! { /// /// If successful in verification, it will write the headers to the underlying storage /// pallet as well as import the valid finality proof. - #[weight = 0] + #[pallet::weight(0)] pub fn submit_finality_proof( - origin, + origin: OriginFor, finality_target: BridgedHeader, justification: Vec, ancestry_proof: Vec>, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; ensure!( @@ -110,15 +102,14 @@ decl_module! { ); let authority_set = T::HeaderChain::authority_set(); - let voter_set = - VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; + let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; let set_id = authority_set.set_id; verify_justification::>( (finality_target.hash(), *finality_target.number()), set_id, voter_set, - &justification + &justification, ) .map_err(|_| >::InvalidJustification)?; @@ -134,24 +125,42 @@ decl_module! { with_transaction(|| { for header in ancestry_proof { if T::HeaderChain::import_header(header).is_err() { - return TransactionOutcome::Rollback(Err(>::FailedToWriteHeader)) + return TransactionOutcome::Rollback(Err(>::FailedToWriteHeader)); } } if T::HeaderChain::import_finality_proof(finality_target, justification).is_err() { - return TransactionOutcome::Rollback(Err(>::FailedToWriteFinalityProof)) + return TransactionOutcome::Rollback(Err(>::FailedToWriteFinalityProof)); } TransactionOutcome::Commit(Ok(())) })?; - Ok(()) + Ok(().into()) } } + + #[pallet::error] + pub enum Error { + /// The given justification is invalid for the given header. + InvalidJustification, + /// The given ancestry proof is unable to verify that the child and ancestor headers are + /// related. + InvalidAncestryProof, + /// The authority set from the underlying header chain is invalid. + InvalidAuthoritySet, + /// Failed to write a header to the underlying header chain. + FailedToWriteHeader, + /// Failed to write finality proof to the underlying header chain. + FailedToWriteFinalityProof, + /// The given ancestry proof is too large to be verified in a single transaction. + OversizedAncestryProof, + } } #[cfg(test)] mod tests { + use super::pallet::*; use super::*; use crate::mock::{run_test, test_header, Origin, TestRuntime}; use bp_test_utils::{authority_list, make_justification_for_header}; diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index 71b1e28420593..daacc4584123c 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{BridgedHeader, Config}; +use crate::pallet::{BridgedHeader, Config}; use bp_runtime::{BlockNumberOf, Chain}; use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; use sp_runtime::{ @@ -74,7 +74,7 @@ parameter_types! { pub const MaxHeadersInSingleProof: u8 = 5; } -impl crate::Config for TestRuntime { +impl crate::pallet::Config for TestRuntime { type BridgedChain = TestBridgedChain; type HeaderChain = pallet_substrate_bridge::Module; type AncestryChecker = Checker<::Header, Vec<::Header>>; @@ -94,7 +94,7 @@ impl Chain for TestBridgedChain { #[derive(Debug)] pub struct Checker(std::marker::PhantomData<(H, P)>); -impl crate::AncestryChecker> for Checker> { +impl bp_header_chain::AncestryChecker> for Checker> { fn are_ancestors(_ancestor: &H, _child: &H, proof: &Vec) -> bool { !proof.is_empty() } From 6adfa481d729eb0dcb19e0d97ff2f5d7fb077d50 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 26 Jan 2021 01:17:40 +0300 Subject: [PATCH 0307/1210] Update weight related parameters in relay (#662) * update weight-related parameters in relay * asserts + docs Co-authored-by: Hernando Castano --- relays/substrate/Cargo.toml | 1 + relays/substrate/src/messages_lane.rs | 63 +++++++++++++++++++ .../src/millau_messages_to_rialto.rs | 15 +++-- .../src/rialto_messages_to_millau.rs | 14 ++--- 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e5243781e6b86..011b8b3be69bd 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -29,6 +29,7 @@ headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } +pallet-message-lane = { path = "../../modules/message-lane" } pallet-substrate-bridge = { path = "../../modules/substrate" } relay-kusama-client = { path = "../kusama-client" } relay-millau-client = { path = "../millau-client" } diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs index 0440a68dd3724..96efaa6a43606 100644 --- a/relays/substrate/src/messages_lane.rs +++ b/relays/substrate/src/messages_lane.rs @@ -20,6 +20,7 @@ use crate::messages_target::SubstrateMessagesReceivingProof; use async_trait::async_trait; use bp_message_lane::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use relay_substrate_client::{BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::BlockNumberBase; @@ -117,3 +118,65 @@ where type TargetHeaderNumber = BlockNumberOf; type TargetHeaderHash = HashOf; } + +/// Returns maximal number of messages and their maximal cumulative dispatch weight, based +/// on given chain parameters. +pub fn select_delivery_transaction_limits( + max_extrinsic_weight: Weight, + max_unconfirmed_messages_at_inbound_lane: MessageNonce, +) -> (MessageNonce, Weight) { + // We may try to guess accurate value, based on maximal number of messages and per-message + // weight overhead, but the relay loop isn't using this info in a super-accurate way anyway. + // So just a rough guess: let's say 1/3 of max tx weight is for tx itself and the rest is + // for messages dispatch. + + // Another thing to keep in mind is that our runtimes (when this code was written) accept + // messages with dispatch weight <= max_extrinsic_weight/2. So we can't reserve less than + // that for dispatch. + + let weight_for_delivery_tx = max_extrinsic_weight / 3; + let weight_for_messages_dispatch = max_extrinsic_weight - weight_for_delivery_tx; + + let delivery_tx_base_weight = + W::receive_messages_proof_overhead() + W::receive_messages_proof_outbound_lane_state_overhead(); + let delivery_tx_weight_rest = weight_for_delivery_tx - delivery_tx_base_weight; + let max_number_of_messages = std::cmp::min( + delivery_tx_weight_rest / W::receive_messages_proof_messages_overhead(1), + max_unconfirmed_messages_at_inbound_lane, + ); + + assert!( + max_number_of_messages > 0, + "Relay should fit at least one message in every delivery transaction", + ); + assert!( + weight_for_messages_dispatch >= max_extrinsic_weight / 2, + "Relay shall be able to deliver messages with dispatch weight = max_extrinsic_weight / 2", + ); + + (max_number_of_messages, weight_for_messages_dispatch) +} + +#[cfg(test)] +mod tests { + use super::*; + + type RialtoToMillauMessageLaneWeights = pallet_message_lane::weights::RialtoWeight; + + #[test] + fn select_delivery_transaction_limits_works() { + let (max_count, max_weight) = select_delivery_transaction_limits::( + bp_rialto::max_extrinsic_weight(), + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + assert_eq!( + (max_count, max_weight), + // We don't actually care about these values, so feel free to update them whenever test + // fails. The only thing to do before that is to ensure that new values looks sane: i.e. weight + // reserved for messages dispatch allows dispatch of non-trivial messages. + // + // Any significant change in this values should attract additional attention. + (1024, 866_583_333_334), + ); + } +} diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 1f8088fa7f31d..7fa948b8c4731 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -16,7 +16,7 @@ //! Millau-to-Rialto messages sync entrypoint. -use crate::messages_lane::{SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; +use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use crate::{MillauClient, RialtoClient}; @@ -123,13 +123,12 @@ pub fn run( lane.relayer_id_at_source, ); - // TODO: these two parameters need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 - // the rough idea is to reserve some portion (1/3?) of max extrinsic weight for delivery tx overhead + messages - // overhead - // this must be tuned mostly with `max_messages_in_single_batch`, but `max_messages_weight_in_single_batch` also - // needs to be updated (subtract tx overhead) - let max_messages_in_single_batch = 1024; - let max_messages_weight_in_single_batch = bp_rialto::max_extrinsic_weight(); + // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_millau::max_extrinsic_weight(), + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index a9ab41b41fe80..ef11f6cecf783 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -16,7 +16,7 @@ //! Rialto-to-Millau messages sync entrypoint. -use crate::messages_lane::{SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; +use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use crate::{MillauClient, RialtoClient}; @@ -123,13 +123,11 @@ pub fn run( lane.relayer_id_at_source, ); - // TODO: these two parameters need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 - // the rough idea is to reserve some portion (1/3?) of max extrinsic weight for delivery tx overhead + messages - // overhead - // this must be tuned mostly with `max_messages_in_single_batch`, but `max_messages_weight_in_single_batch` also - // needs to be updated (subtract tx overhead) - let max_messages_in_single_batch = 1024; - let max_messages_weight_in_single_batch = bp_rialto::max_extrinsic_weight(); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_rialto::max_extrinsic_weight(), + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { From 2d89951c8cd6603666134b4275d805eaeae9e2c3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 26 Jan 2021 03:18:29 -0500 Subject: [PATCH 0308/1210] Clean up initialization tests slightly (#678) --- modules/substrate/src/lib.rs | 54 +++++++++++++----------------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 9644e508ed0c2..2ecee8628e491 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -658,51 +658,43 @@ impl BridgeStorage for PalletStorage { #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestRuntime}; + use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestHeader, TestRuntime}; use bp_test_utils::authority_list; use frame_support::{assert_noop, assert_ok}; use sp_runtime::DispatchError; + fn init_with_origin(origin: Origin) -> Result, DispatchError> { + let init_data = InitializationData { + header: test_header(1), + authority_list: authority_list(), + set_id: 1, + scheduled_change: None, + is_halted: false, + }; + + Module::::initialize(origin, init_data.clone()).map(|_| init_data) + } + #[test] fn init_root_or_owner_origin_can_initialize_pallet() { run_test(|| { - let init_data = InitializationData { - header: test_header(1), - authority_list: authority_list(), - set_id: 1, - scheduled_change: None, - is_halted: false, - }; - - assert_noop!( - Module::::initialize(Origin::signed(1), init_data.clone()), - DispatchError::BadOrigin, - ); - - assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + assert_noop!(init_with_origin(Origin::signed(1)), DispatchError::BadOrigin); + assert_ok!(init_with_origin(Origin::root())); // Reset storage so we can initialize the pallet again BestFinalized::::kill(); ModuleOwner::::put(2); - assert_ok!(Module::::initialize(Origin::signed(2), init_data)); + assert_ok!(init_with_origin(Origin::signed(2))); }) } #[test] fn init_storage_entries_are_correctly_initialized() { run_test(|| { - let init_data = InitializationData { - header: test_header(1), - authority_list: authority_list(), - set_id: 1, - scheduled_change: None, - is_halted: false, - }; - assert!(Module::::best_headers().is_empty()); assert_eq!(Module::::best_finalized(), test_header(0)); - assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + let init_data = init_with_origin(Origin::root()).unwrap(); let storage = PalletStorage::::new(); assert!(storage.header_exists(init_data.header.hash())); @@ -722,17 +714,9 @@ mod tests { #[test] fn init_can_only_initialize_pallet_once() { run_test(|| { - let init_data = InitializationData { - header: test_header(1), - authority_list: authority_list(), - set_id: 1, - scheduled_change: None, - is_halted: false, - }; - - assert_ok!(Module::::initialize(Origin::root(), init_data.clone())); + assert_ok!(init_with_origin(Origin::root())); assert_noop!( - Module::::initialize(Origin::root(), init_data), + init_with_origin(Origin::root()), >::AlreadyInitialized ); }) From 87c82679b10c447f98600a46a1b8dde525267298 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 26 Jan 2021 11:19:17 +0300 Subject: [PATCH 0309/1210] Emit dispatch message when whole message (payload) has invalid encoding (#664) * emit dispatch message when whole message (payload) has invalid encoding * DispatchMessage::dispatch accepts Result --- bin/runtime-common/src/messages.rs | 17 +++++----- modules/call-dispatch/src/lib.rs | 46 ++++++++++++++++++++++---- primitives/message-dispatch/src/lib.rs | 7 ++-- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index cd84612d109be..924aafd07054d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -381,7 +381,9 @@ pub mod target { for FromBridgedChainMessageDispatch where ThisCallDispatchInstance: frame_support::traits::Instance, - ThisRuntime: pallet_bridge_call_dispatch::Config, + ThisRuntime: pallet_bridge_call_dispatch::Config, + >::Event: + From>, pallet_bridge_call_dispatch::Module: bp_message_dispatch::MessageDispatch< (LaneId, MessageNonce), @@ -402,13 +404,12 @@ pub mod target { } fn dispatch(message: DispatchMessage>>) { - if let Ok(payload) = message.data.payload { - pallet_bridge_call_dispatch::Module::::dispatch( - B::INSTANCE, - (message.key.lane_id, message.key.nonce), - payload.0, - ); - } + let message_id = (message.key.lane_id, message.key.nonce); + pallet_bridge_call_dispatch::Module::::dispatch( + B::INSTANCE, + message_id, + message.data.payload.map_err(drop).map(|payload| payload.0), + ); } } diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index a0c2af0572524..c0b1e578d75a5 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -148,6 +148,8 @@ decl_event!( pub enum Event where >::MessageId { + /// Message has been rejected before reaching dispatch. + MessageRejected(InstanceId, MessageId), /// Message has been rejected by dispatcher because of spec version mismatch. /// Last two arguments are: expected and passed spec version. MessageVersionSpecMismatch(InstanceId, MessageId, SpecVersion, SpecVersion), @@ -183,7 +185,17 @@ impl, I: Instance> MessageDispatch for Module { message.weight } - fn dispatch(bridge: InstanceId, id: T::MessageId, message: Self::Message) { + fn dispatch(bridge: InstanceId, id: T::MessageId, message: Result) { + // emit special even if message has been rejected by external component + let message = match message { + Ok(message) => message, + Err(_) => { + frame_support::debug::trace!("Message {:?}/{:?}: rejected before actual dispatch", bridge, id); + Self::deposit_event(RawEvent::MessageRejected(bridge, id)); + return; + } + }; + // verify spec version // (we want it to be the same, because otherwise we may decode Call improperly) let expected_version = ::Version::get().spec_version; @@ -491,7 +503,7 @@ mod tests { message.spec_version = BAD_SPEC_VERSION; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, message); + CallDispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -519,7 +531,7 @@ mod tests { message.weight = 0; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, message); + CallDispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -547,7 +559,7 @@ mod tests { ); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, message); + CallDispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -560,6 +572,26 @@ mod tests { }); } + #[test] + fn should_emit_event_for_rejected_messages() { + new_test_ext().execute_with(|| { + let bridge = b"ethb".to_owned(); + let id = [0; 4]; + + System::set_block_number(1); + CallDispatch::dispatch(bridge, id, Err(())); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageRejected(bridge, id)), + topics: vec![], + }], + ); + }); + } + #[test] fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { @@ -568,7 +600,7 @@ mod tests { let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, message); + CallDispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -591,7 +623,7 @@ mod tests { let message = prepare_target_message(call); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, message); + CallDispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -614,7 +646,7 @@ mod tests { let message = prepare_source_message(call); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, message); + CallDispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 321e09654a759..1932d8cb0b8d4 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -41,6 +41,9 @@ pub trait MessageDispatch { /// /// `id` is a short unique identifier of the message. /// - /// Returns post-dispatch (actual) message weight. - fn dispatch(bridge: InstanceId, id: MessageId, message: Self::Message); + /// If message is `Ok`, then it should be dispatched. If it is `Err`, then it's just + /// a sign that some other component has rejected the message even before it has + /// reached `dispatch` method (right now this may only be caused if we fail to decode + /// the whole message). + fn dispatch(bridge: InstanceId, id: MessageId, message: Result); } From f6f3c8167ff2441cb2a7d437b64eba3d318cfc90 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Tue, 26 Jan 2021 14:32:59 +0100 Subject: [PATCH 0310/1210] Prevent potential signature reuse (#667) * patch audit findings #42 * extend msg signature for substrate relay * signature verification test * make proof dependet on call_dispatch crate * silence clippy * revert deny exception * address code review * since it's not really a proof, call it digest --- bin/millau/runtime/src/lib.rs | 23 ++++++++++ bin/rialto/runtime/src/lib.rs | 23 ++++++++++ modules/call-dispatch/src/lib.rs | 35 ++++++++++++--- relays/substrate/src/main.rs | 74 +++++++++++++++++++++++++++----- 4 files changed, 140 insertions(+), 15 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index e79b34d2790ef..90498c7cde803 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -596,6 +596,29 @@ impl_runtime_apis! { } } +/// Rialto account ownership digest from Millau. +/// +/// The byte vector returned by this function should be signed with a Rialto account private key. +/// This way, the owner of `millau_account_id` on Millau proves that the Rialto account private key +/// is also under his control. +pub fn rialto_account_ownership_digest( + rialto_call: Call, + millau_account_id: AccountId, + rialto_spec_version: SpecVersion, +) -> sp_std::vec::Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_call_dispatch::account_ownership_digest( + rialto_call, + millau_account_id, + rialto_spec_version, + bp_runtime::MILLAU_BRIDGE_INSTANCE, + ) +} + #[cfg(test)] mod tests { use super::*; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 060784ab3ec56..313948e6a05be 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -985,6 +985,29 @@ impl_runtime_apis! { } } +/// Millau account ownership digest from Rialto. +/// +/// The byte vector returned by this function should be signed with a Millau account private key. +/// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private key +/// is also under his control. +pub fn millau_account_ownership_digest( + millau_call: Call, + rialto_account_id: AccountId, + millau_spec_version: SpecVersion, +) -> sp_std::vec::Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_call_dispatch::account_ownership_digest( + millau_call, + rialto_account_id, + millau_spec_version, + bp_runtime::RIALTO_BRIDGE_INSTANCE, + ) +} + #[cfg(test)] mod tests { use super::*; diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index c0b1e578d75a5..d60492be34aea 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -65,7 +65,7 @@ pub enum CallOrigin, I: Instance> MessageDispatch for Module { target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { - let mut signed_message = Vec::new(); - message.call.encode_to(&mut signed_message); - source_account_id.encode_to(&mut signed_message); + let digest = + account_ownership_digest(message.call.clone(), source_account_id, message.spec_version, bridge); let target_account = target_public.into_account(); - if !target_signature.verify(&signed_message[..], &target_account) { + if !target_signature.verify(&digest[..], &target_account) { frame_support::debug::trace!( "Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}", bridge, @@ -334,6 +333,32 @@ where } } +/// Target account ownership digest from the source chain. +/// +/// The byte vector returned by this function will be signed with a target chain account +/// private key. This way, the owner of `source_account_id` on the source chain proves that +/// the target chain account private key is also under his control. +pub fn account_ownership_digest( + call: Call, + source_account_id: AccountId, + target_spec_version: SpecVersion, + source_instance_id: BridgeId, +) -> Vec +where + Call: Encode, + AccountId: Encode, + SpecVersion: Encode, + BridgeId: Encode, +{ + let mut proof = Vec::new(); + call.encode_to(&mut proof); + source_account_id.encode_to(&mut proof); + target_spec_version.encode_to(&mut proof); + source_instance_id.encode_to(&mut proof); + + proof +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 88d436371e34d..c0f0ab2bcac92 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -297,10 +297,13 @@ async fn run_command(command: cli::Command) -> Result<(), String> { call: rialto_call.encode(), }, cli::Origins::Target => { - let mut rialto_origin_signature_message = Vec::new(); - rialto_call.encode_to(&mut rialto_origin_signature_message); - millau_account_id.encode_to(&mut rialto_origin_signature_message); - let rialto_origin_signature = rialto_sign.signer.sign(&rialto_origin_signature_message); + let digest = millau_runtime::rialto_account_ownership_digest( + rialto_call.clone(), + millau_account_id.clone(), + rialto_runtime::VERSION.spec_version, + ); + + let digest_signature = rialto_sign.signer.sign(&digest); MessagePayload { spec_version: rialto_runtime::VERSION.spec_version, @@ -308,7 +311,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { origin: CallOrigin::TargetAccount( millau_account_id, rialto_origin_public.into(), - rialto_origin_signature.into(), + digest_signature.into(), ), call: rialto_call.encode(), } @@ -445,10 +448,13 @@ async fn run_command(command: cli::Command) -> Result<(), String> { call: millau_call.encode(), }, cli::Origins::Target => { - let mut millau_origin_signature_message = Vec::new(); - millau_call.encode_to(&mut millau_origin_signature_message); - rialto_account_id.encode_to(&mut millau_origin_signature_message); - let millau_origin_signature = millau_sign.signer.sign(&millau_origin_signature_message); + let digest = rialto_runtime::millau_account_ownership_digest( + millau_call.clone(), + rialto_account_id.clone(), + millau_runtime::VERSION.spec_version, + ); + + let digest_signature = millau_sign.signer.sign(&digest); MessagePayload { spec_version: millau_runtime::VERSION.spec_version, @@ -456,7 +462,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { origin: CallOrigin::TargetAccount( rialto_account_id, millau_origin_public.into(), - millau_origin_signature.into(), + digest_signature.into(), ), call: millau_call.encode(), } @@ -517,3 +523,51 @@ async fn estimate_message_delivery_and_dispatch_fee Date: Tue, 26 Jan 2021 17:14:33 +0300 Subject: [PATCH 0311/1210] Extract common part of relay loops (#660) * extract common parts of relay loops: begin * merge client impls * backoff in exchange loop * reconnect without clone --- relays/ethereum-client/src/client.rs | 18 +- relays/ethereum/src/ethereum_exchange.rs | 41 +- relays/ethereum/src/ethereum_sync_loop.rs | 48 +- relays/ethereum/src/substrate_sync_loop.rs | 29 +- relays/exchange-relay/src/exchange.rs | 63 +- relays/exchange-relay/src/exchange_loop.rs | 155 +-- .../src/exchange_loop_metrics.rs | 3 +- relays/headers-relay/src/sync_loop.rs | 935 +++++++++--------- relays/headers-relay/src/sync_loop_metrics.rs | 3 +- relays/headers-relay/src/sync_loop_tests.rs | 46 +- .../messages-relay/src/message_lane_loop.rs | 170 ++-- relays/substrate-client/src/client.rs | 9 +- relays/substrate-client/src/headers_source.rs | 38 +- relays/substrate/src/headers_maintain.rs | 14 + relays/substrate/src/headers_target.rs | 37 +- relays/substrate/src/messages_source.rs | 31 +- relays/substrate/src/messages_target.rs | 31 +- .../src/millau_messages_to_rialto.rs | 3 +- .../src/rialto_messages_to_millau.rs | 3 +- relays/utils/Cargo.toml | 1 + relays/utils/src/lib.rs | 1 + relays/utils/src/metrics.rs | 16 +- relays/utils/src/relay_loop.rs | 95 ++ 23 files changed, 1015 insertions(+), 775 deletions(-) create mode 100644 relays/utils/src/relay_loop.rs diff --git a/relays/ethereum-client/src/client.rs b/relays/ethereum-client/src/client.rs index 0042b13c6ef18..b5fe3ab6bf179 100644 --- a/relays/ethereum-client/src/client.rs +++ b/relays/ethereum-client/src/client.rs @@ -28,22 +28,32 @@ use jsonrpsee::Client as RpcClient; /// The client used to interact with an Ethereum node through RPC. #[derive(Clone)] pub struct Client { + params: ConnectionParams, client: RpcClient, } impl Client { /// Create a new Ethereum RPC Client. pub fn new(params: ConnectionParams) -> Self { + Self { + client: Self::build_client(¶ms), + params, + } + } + + /// Build client to use in connection. + fn build_client(params: &ConnectionParams) -> RpcClient { let uri = format!("http://{}:{}", params.host, params.port); let transport = HttpTransportClient::new(&uri); let raw_client = RawClient::new(transport); - let client: RpcClient = raw_client.into(); + raw_client.into() + } - Self { client } + /// Reopen client connection. + pub fn reconnect(&mut self) { + self.client = Self::build_client(&self.params); } -} -impl Client { /// Estimate gas usage for the given call. pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { Ok(Ethereum::estimate_gas(&self.client, call_request).await?) diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 870de74f7835a..19d9f44cef0e9 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -39,7 +39,7 @@ use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{ Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, }; -use relay_utils::{metrics::MetricsParams, HeaderId}; +use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; use std::{sync::Arc, time::Duration}; @@ -120,19 +120,28 @@ impl SourceTransaction for EthereumSourceTransaction { } /// Ethereum node as transactions proof source. +#[derive(Clone)] struct EthereumTransactionsSource { client: EthereumClient, } #[async_trait] -impl SourceClient for EthereumTransactionsSource { +impl RelayClient for EthereumTransactionsSource { type Error = RpcError; + async fn reconnect(&mut self) -> Result<(), RpcError> { + self.client.reconnect(); + Ok(()) + } +} + +#[async_trait] +impl SourceClient for EthereumTransactionsSource { async fn tick(&self) { async_std::task::sleep(ETHEREUM_TICK_INTERVAL).await; } - async fn block_by_hash(&self, hash: H256) -> Result { + async fn block_by_hash(&self, hash: H256) -> Result { self.client .header_by_hash_with_transactions(hash) .await @@ -140,7 +149,7 @@ impl SourceClient for EthereumTransactionsSource { .map_err(Into::into) } - async fn block_by_number(&self, number: u64) -> Result { + async fn block_by_number(&self, number: u64) -> Result { self.client .header_by_number_with_transactions(number) .await @@ -151,7 +160,7 @@ impl SourceClient for EthereumTransactionsSource { async fn transaction_block( &self, hash: &EthereumTransactionHash, - ) -> Result, Self::Error> { + ) -> Result, RpcError> { let eth_tx = match self.client.transaction_by_hash(*hash).await? { Some(eth_tx) => eth_tx, None => return Ok(None), @@ -173,7 +182,7 @@ impl SourceClient for EthereumTransactionsSource { &self, block: &EthereumSourceBlock, tx_index: usize, - ) -> Result { + ) -> Result { const TRANSACTION_HAS_RAW_FIELD_PROOF: &str = "RPC level checks that transactions from Ethereum\ node are having `raw` field; qed"; const BLOCK_HAS_HASH_FIELD_PROOF: &str = "RPC level checks that block has `hash` field; qed"; @@ -199,6 +208,7 @@ impl SourceClient for EthereumTransactionsSource { } /// Substrate node as transactions proof target. +#[derive(Clone)] struct SubstrateTransactionsTarget { client: SubstrateClient, sign_params: RialtoSigningParams, @@ -206,18 +216,25 @@ struct SubstrateTransactionsTarget { } #[async_trait] -impl TargetClient for SubstrateTransactionsTarget { +impl RelayClient for SubstrateTransactionsTarget { type Error = RpcError; + async fn reconnect(&mut self) -> Result<(), RpcError> { + Ok(self.client.reconnect().await?) + } +} + +#[async_trait] +impl TargetClient for SubstrateTransactionsTarget { async fn tick(&self) { async_std::task::sleep(Rialto::AVERAGE_BLOCK_INTERVAL).await; } - async fn is_header_known(&self, id: &EthereumHeaderId) -> Result { + async fn is_header_known(&self, id: &EthereumHeaderId) -> Result { self.client.ethereum_header_known(*id).await } - async fn is_header_finalized(&self, id: &EthereumHeaderId) -> Result { + async fn is_header_finalized(&self, id: &EthereumHeaderId) -> Result { // we check if header is finalized by simple comparison of the header number and // number of best finalized PoA header known to Substrate node. // @@ -230,11 +247,11 @@ impl TargetClient for SubstrateTransactionsTarget { Ok(id.0 <= best_finalized_ethereum_block.0) } - async fn best_finalized_header_id(&self) -> Result { + async fn best_finalized_header_id(&self) -> Result { self.client.best_ethereum_finalized_block().await } - async fn filter_transaction_proof(&self, proof: &EthereumTransactionInclusionProof) -> Result { + async fn filter_transaction_proof(&self, proof: &EthereumTransactionInclusionProof) -> Result { // let's try to parse transaction locally let (raw_tx, raw_tx_receipt) = &proof.proof[proof.index as usize]; let parse_result = rialto_runtime::exchange::EthTransaction::parse(raw_tx); @@ -253,7 +270,7 @@ impl TargetClient for SubstrateTransactionsTarget { self.client.verify_exchange_transaction_proof(proof.clone()).await } - async fn submit_transaction_proof(&self, proof: EthereumTransactionInclusionProof) -> Result<(), Self::Error> { + async fn submit_transaction_proof(&self, proof: EthereumTransactionInclusionProof) -> Result<(), RpcError> { let (sign_params, bridge_instance) = (self.sign_params.clone(), self.bridge_instance.clone()); self.client .submit_exchange_transaction_proof(sign_params, bridge_instance, proof) diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index ec0c95c70ca72..b84626d230c6d 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -37,7 +37,7 @@ use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{ Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, }; -use relay_utils::metrics::MetricsParams; +use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; use std::fmt::Debug; use std::{collections::HashSet, sync::Arc, time::Duration}; @@ -105,6 +105,7 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { pub type QueuedEthereumHeader = QueuedHeader; /// Ethereum client as headers source. +#[derive(Clone)] struct EthereumHeadersSource { /// Ethereum node client. client: EthereumClient, @@ -117,14 +118,22 @@ impl EthereumHeadersSource { } #[async_trait] -impl SourceClient for EthereumHeadersSource { +impl RelayClient for EthereumHeadersSource { type Error = RpcError; - async fn best_block_number(&self) -> Result { + async fn reconnect(&mut self) -> Result<(), RpcError> { + self.client.reconnect(); + Ok(()) + } +} + +#[async_trait] +impl SourceClient for EthereumHeadersSource { + async fn best_block_number(&self) -> Result { self.client.best_block_number().await.map_err(Into::into) } - async fn header_by_hash(&self, hash: HeaderHash) -> Result { + async fn header_by_hash(&self, hash: HeaderHash) -> Result { self.client .header_by_hash(hash) .await @@ -132,7 +141,7 @@ impl SourceClient for EthereumHeadersSource { .map_err(Into::into) } - async fn header_by_number(&self, number: u64) -> Result { + async fn header_by_number(&self, number: u64) -> Result { self.client .header_by_number(number) .await @@ -140,7 +149,7 @@ impl SourceClient for EthereumHeadersSource { .map_err(Into::into) } - async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), Self::Error> { + async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), RpcError> { Ok((id, None)) } @@ -148,13 +157,14 @@ impl SourceClient for EthereumHeadersSource { &self, id: EthereumHeaderId, header: QueuedEthereumHeader, - ) -> Result<(EthereumHeaderId, Vec), Self::Error> { + ) -> Result<(EthereumHeaderId, Vec), RpcError> { self.client .transaction_receipts(id, header.header().transactions.clone()) .await } } +#[derive(Clone)] struct SubstrateHeadersTarget { /// Substrate node client. client: SubstrateClient, @@ -183,21 +193,25 @@ impl SubstrateHeadersTarget { } #[async_trait] -impl TargetClient for SubstrateHeadersTarget { +impl RelayClient for SubstrateHeadersTarget { type Error = RpcError; - async fn best_header_id(&self) -> Result { + async fn reconnect(&mut self) -> Result<(), RpcError> { + Ok(self.client.reconnect().await?) + } +} + +#[async_trait] +impl TargetClient for SubstrateHeadersTarget { + async fn best_header_id(&self) -> Result { self.client.best_ethereum_block().await } - async fn is_known_header(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, bool), Self::Error> { + async fn is_known_header(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, bool), RpcError> { Ok((id, self.client.ethereum_header_known(id).await?)) } - async fn submit_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders { + async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { let (sign_params, bridge_instance, sign_transactions) = ( self.sign_params.clone(), self.bridge_instance.clone(), @@ -208,16 +222,16 @@ impl TargetClient for SubstrateHeadersTarget { .await } - async fn incomplete_headers_ids(&self) -> Result, Self::Error> { + async fn incomplete_headers_ids(&self) -> Result, RpcError> { Ok(HashSet::new()) } #[allow(clippy::unit_arg)] - async fn complete_header(&self, id: EthereumHeaderId, _completion: ()) -> Result { + async fn complete_header(&self, id: EthereumHeaderId, _completion: ()) -> Result { Ok(id) } - async fn requires_extra(&self, header: QueuedEthereumHeader) -> Result<(EthereumHeaderId, bool), Self::Error> { + async fn requires_extra(&self, header: QueuedEthereumHeader) -> Result<(EthereumHeaderId, bool), RpcError> { // we can minimize number of receipts_check calls by checking header // logs bloom here, but it may give us false positives (when authorities // source is contract, we never need any logs) diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 7ca9d797dfe55..298fe0e592545 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -35,7 +35,7 @@ use relay_substrate_client::{ headers_source::HeadersSource, Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, }; -use relay_utils::metrics::MetricsParams; +use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; use sp_runtime::Justification; use std::fmt::Debug; @@ -98,6 +98,7 @@ pub type QueuedRialtoHeader = QueuedHeader; type SubstrateHeadersSource = HeadersSource; /// Ethereum client as Substrate headers target. +#[derive(Clone)] struct EthereumHeadersTarget { /// Ethereum node client. client: EthereumClient, @@ -118,38 +119,42 @@ impl EthereumHeadersTarget { } #[async_trait] -impl TargetClient for EthereumHeadersTarget { +impl RelayClient for EthereumHeadersTarget { type Error = RpcError; - async fn best_header_id(&self) -> Result { + async fn reconnect(&mut self) -> Result<(), RpcError> { + self.client.reconnect(); + Ok(()) + } +} + +#[async_trait] +impl TargetClient for EthereumHeadersTarget { + async fn best_header_id(&self) -> Result { self.client.best_substrate_block(self.contract).await } - async fn is_known_header(&self, id: RialtoHeaderId) -> Result<(RialtoHeaderId, bool), Self::Error> { + async fn is_known_header(&self, id: RialtoHeaderId) -> Result<(RialtoHeaderId, bool), RpcError> { self.client.substrate_header_known(self.contract, id).await } - async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { + async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { self.client .submit_substrate_headers(self.sign_params.clone(), self.contract, headers) .await } - async fn incomplete_headers_ids(&self) -> Result, Self::Error> { + async fn incomplete_headers_ids(&self) -> Result, RpcError> { self.client.incomplete_substrate_headers(self.contract).await } - async fn complete_header( - &self, - id: RialtoHeaderId, - completion: Justification, - ) -> Result { + async fn complete_header(&self, id: RialtoHeaderId, completion: Justification) -> Result { self.client .complete_substrate_header(self.sign_params.clone(), self.contract, id, completion) .await } - async fn requires_extra(&self, header: QueuedRialtoHeader) -> Result<(RialtoHeaderId, bool), Self::Error> { + async fn requires_extra(&self, header: QueuedRialtoHeader) -> Result<(RialtoHeaderId, bool), RpcError> { Ok((header.header().id(), false)) } } diff --git a/relays/exchange-relay/src/exchange.rs b/relays/exchange-relay/src/exchange.rs index 0df2927d56c6e..cdf9c1a9f3588 100644 --- a/relays/exchange-relay/src/exchange.rs +++ b/relays/exchange-relay/src/exchange.rs @@ -17,7 +17,9 @@ //! Relaying proofs of exchange transaction. use async_trait::async_trait; -use relay_utils::{MaybeConnectionError, StringifiedMaybeConnectionError}; +use relay_utils::{ + relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, StringifiedMaybeConnectionError, +}; use std::{ fmt::{Debug, Display}, string::ToString, @@ -84,10 +86,7 @@ pub type HeaderId

= relay_utils::HeaderId, BlockNumberOf

>; /// Source client API. #[async_trait] -pub trait SourceClient { - /// Error type. - type Error: Debug + MaybeConnectionError; - +pub trait SourceClient: RelayClient { /// Sleep until exchange-related data is (probably) updated. async fn tick(&self); /// Get block by hash. @@ -104,10 +103,7 @@ pub trait SourceClient { /// Target client API. #[async_trait] -pub trait TargetClient { - /// Error type. - type Error: Debug + MaybeConnectionError; - +pub trait TargetClient: RelayClient { /// Sleep until exchange-related data is (probably) updated. async fn tick(&self); /// Returns `Ok(true)` if header is known to the target node. @@ -146,7 +142,7 @@ pub async fn relay_block_transactions( target_client: &impl TargetClient

, source_block: &P::Block, mut relayed_transactions: RelayedBlockTransactions, -) -> Result { +) -> Result { let transactions_to_process = source_block .transactions() .into_iter() @@ -156,16 +152,21 @@ pub async fn relay_block_transactions( let result = async { let source_tx_id = format!("{}/{}", source_block.id().1, source_tx_index); let source_tx_proof = - prepare_transaction_proof(source_client, &source_tx_id, source_block, source_tx_index).await?; + prepare_transaction_proof(source_client, &source_tx_id, source_block, source_tx_index) + .await + .map_err(|e| (FailedClient::Source, e))?; let needs_to_be_relayed = target_client .filter_transaction_proof(&source_tx_proof) .await .map_err(|err| { - StringifiedMaybeConnectionError::new( - err.is_connection_error(), - format!("Transaction filtering has failed with {:?}", err), + ( + FailedClient::Target, + StringifiedMaybeConnectionError::new( + err.is_connection_error(), + format!("Transaction filtering has failed with {:?}", err), + ), ) })?; @@ -176,6 +177,7 @@ pub async fn relay_block_transactions( relay_ready_transaction_proof(target_client, &source_tx_id, source_tx_proof) .await .map(|_| true) + .map_err(|e| (FailedClient::Target, e)) } .await; @@ -205,7 +207,7 @@ pub async fn relay_block_transactions( relayed_transactions.processed += 1; relayed_transactions.relayed += 1; } - Err(err) => { + Err((failed_client, err)) => { log::error!( target: "bridge", "Error relaying {} transaction {} proof to {} node: {}. {}", @@ -221,7 +223,7 @@ pub async fn relay_block_transactions( ); if err.is_connection_error() { - return Err(relayed_transactions); + return Err((failed_client, relayed_transactions)); } relayed_transactions.processed += 1; @@ -529,8 +531,9 @@ pub(crate) mod tests { #[derive(Debug, Clone, PartialEq)] pub struct TestTransactionProof(pub TestTransactionHash); + #[derive(Clone)] pub struct TestTransactionsSource { - pub on_tick: Box, + pub on_tick: Arc, pub data: Arc>, } @@ -543,7 +546,7 @@ pub(crate) mod tests { impl TestTransactionsSource { pub fn new(on_tick: Box) -> Self { Self { - on_tick, + on_tick: Arc::new(on_tick), data: Arc::new(Mutex::new(TestTransactionsSourceData { block: Ok(test_block()), transaction_block: Ok(Some((test_block_id(), 0))), @@ -554,9 +557,16 @@ pub(crate) mod tests { } #[async_trait] - impl SourceClient for TestTransactionsSource { + impl RelayClient for TestTransactionsSource { type Error = TestError; + async fn reconnect(&mut self) -> Result<(), TestError> { + Ok(()) + } + } + + #[async_trait] + impl SourceClient for TestTransactionsSource { async fn tick(&self) { (self.on_tick)(&mut *self.data.lock()) } @@ -584,8 +594,9 @@ pub(crate) mod tests { } } + #[derive(Clone)] pub struct TestTransactionsTarget { - pub on_tick: Box, + pub on_tick: Arc, pub data: Arc>, } @@ -600,7 +611,7 @@ pub(crate) mod tests { impl TestTransactionsTarget { pub fn new(on_tick: Box) -> Self { Self { - on_tick, + on_tick: Arc::new(on_tick), data: Arc::new(Mutex::new(TestTransactionsTargetData { is_header_known: Ok(true), is_header_finalized: Ok(true), @@ -613,9 +624,16 @@ pub(crate) mod tests { } #[async_trait] - impl TargetClient for TestTransactionsTarget { + impl RelayClient for TestTransactionsTarget { type Error = TestError; + async fn reconnect(&mut self) -> Result<(), TestError> { + Ok(()) + } + } + + #[async_trait] + impl TargetClient for TestTransactionsTarget { async fn tick(&self) { (self.on_tick)(&mut *self.data.lock()) } @@ -784,6 +802,7 @@ pub(crate) mod tests { ), pre_relayed, )) + .map_err(|(_, transactions)| transactions) } #[test] diff --git a/relays/exchange-relay/src/exchange_loop.rs b/relays/exchange-relay/src/exchange_loop.rs index 645672ba3f403..06f4d3f40ab01 100644 --- a/relays/exchange-relay/src/exchange_loop.rs +++ b/relays/exchange-relay/src/exchange_loop.rs @@ -27,13 +27,9 @@ use futures::{future::FutureExt, select}; use num_traits::One; use relay_utils::{ metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, - retry_backoff, + retry_backoff, FailedClient, MaybeConnectionError, }; -use std::{future::Future, time::Duration}; - -/// Delay after connection-related error happened before we'll try -/// reconnection again. -const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); +use std::future::Future; /// Transactions proofs relay state. #[derive(Debug)] @@ -43,7 +39,7 @@ pub struct TransactionProofsRelayState { } /// Transactions proofs relay storage. -pub trait TransactionProofsRelayStorage { +pub trait TransactionProofsRelayStorage: Clone { /// Associated block number. type BlockNumber; @@ -54,7 +50,7 @@ pub trait TransactionProofsRelayStorage { } /// In-memory storage for auto-relay loop. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct InMemoryStorage { best_processed_header_number: BlockNumber, } @@ -84,68 +80,101 @@ impl TransactionProofsRelayStorage for InMemoryStorag /// Run proofs synchronization. pub fn run( - mut storage: impl TransactionProofsRelayStorage>, + storage: impl TransactionProofsRelayStorage>, source_client: impl SourceClient

, target_client: impl TargetClient

, metrics_params: Option, exit_signal: impl Future, ) { - let mut local_pool = futures::executor::LocalPool::new(); - - local_pool.run_until(async move { - let mut retry_backoff = retry_backoff(); - let mut state = storage.state(); - let mut current_finalized_block = None; - - let mut metrics_global = GlobalMetrics::default(); - let mut metrics_exch = ExchangeLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), - metrics_params, - &metrics_global, - &metrics_exch, - ); + let exit_signal = exit_signal.shared(); + let metrics_global = GlobalMetrics::default(); + let metrics_exch = ExchangeLoopMetrics::default(); + let metrics_enabled = metrics_params.is_some(); + metrics_start( + format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), + metrics_params, + &metrics_global, + &metrics_exch, + ); + + relay_utils::relay_loop::run( + relay_utils::relay_loop::RECONNECT_DELAY, + source_client, + target_client, + |source_client, target_client| { + run_until_connection_lost( + storage.clone(), + source_client, + target_client, + if metrics_enabled { + Some(metrics_global.clone()) + } else { + None + }, + if metrics_enabled { + Some(metrics_exch.clone()) + } else { + None + }, + exit_signal.clone(), + ) + }, + ); +} + +/// Run proofs synchronization. +async fn run_until_connection_lost( + mut storage: impl TransactionProofsRelayStorage>, + source_client: impl SourceClient

, + target_client: impl TargetClient

, + metrics_global: Option, + metrics_exch: Option, + exit_signal: impl Future, +) -> Result<(), FailedClient> { + let mut retry_backoff = retry_backoff(); + let mut state = storage.state(); + let mut current_finalized_block = None; - let exit_signal = exit_signal.fuse(); + let exit_signal = exit_signal.fuse(); - futures::pin_mut!(exit_signal); + futures::pin_mut!(exit_signal); - loop { - let iteration_result = run_loop_iteration( - &mut storage, - &source_client, - &target_client, - &mut state, - &mut current_finalized_block, - if metrics_enabled { Some(&mut metrics_exch) } else { None }, - ) - .await; + loop { + let iteration_result = run_loop_iteration( + &mut storage, + &source_client, + &target_client, + &mut state, + &mut current_finalized_block, + metrics_exch.as_ref(), + ) + .await; + + if let Some(ref metrics_global) = metrics_global { + metrics_global.update().await; + } - if metrics_enabled { - metrics_global.update(); + if let Err((is_connection_error, failed_client)) = iteration_result { + if is_connection_error { + return Err(failed_client); } - match iteration_result { - Ok(_) => { - retry_backoff.reset(); - - select! { - _ = source_client.tick().fuse() => {}, - _ = exit_signal => return, - } - } - Err(_) => { - let retry_timeout = retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY); + let retry_timeout = retry_backoff + .next_backoff() + .unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY); + select! { + _ = async_std::task::sleep(retry_timeout).fuse() => {}, + _ = exit_signal => return Ok(()), + } + } else { + retry_backoff.reset(); - select! { - _ = async_std::task::sleep(retry_timeout).fuse() => {}, - _ = exit_signal => return, - } - } + select! { + _ = source_client.tick().fuse() => {}, + _ = exit_signal => return Ok(()), } } - }); + } } /// Run exchange loop until we need to break. @@ -155,8 +184,8 @@ async fn run_loop_iteration( target_client: &impl TargetClient

, state: &mut TransactionProofsRelayState>, current_finalized_block: &mut Option<(P::Block, RelayedBlockTransactions)>, - mut exchange_loop_metrics: Option<&mut ExchangeLoopMetrics>, -) -> Result<(), ()> { + exchange_loop_metrics: Option<&ExchangeLoopMetrics>, +) -> Result<(), (bool, FailedClient)> { let best_finalized_header_id = match target_client.best_finalized_header_id().await { Ok(best_finalized_header_id) => { log::debug!( @@ -178,7 +207,7 @@ async fn run_loop_iteration( err, ); - return Err(()); + return Err((err.is_connection_error(), FailedClient::Target)); } }; @@ -202,7 +231,7 @@ async fn run_loop_iteration( state.best_processed_header_number = state.best_processed_header_number + One::one(); storage.set_state(state); - if let Some(exchange_loop_metrics) = exchange_loop_metrics.as_mut() { + if let Some(ref exchange_loop_metrics) = exchange_loop_metrics { exchange_loop_metrics.update::

( state.best_processed_header_number, best_finalized_header_id.0, @@ -212,9 +241,9 @@ async fn run_loop_iteration( // we have just updated state => proceed to next block retrieval } - Err(relayed_transactions) => { + Err((failed_client, relayed_transactions)) => { *current_finalized_block = Some((block, relayed_transactions)); - return Err(()); + return Err((true, failed_client)); } } } @@ -240,7 +269,7 @@ async fn run_loop_iteration( err, ); - return Err(()); + return Err((err.is_connection_error(), FailedClient::Source)); } } } diff --git a/relays/exchange-relay/src/exchange_loop_metrics.rs b/relays/exchange-relay/src/exchange_loop_metrics.rs index 325bfd2c9dfcd..bf8f0243b693a 100644 --- a/relays/exchange-relay/src/exchange_loop_metrics.rs +++ b/relays/exchange-relay/src/exchange_loop_metrics.rs @@ -20,6 +20,7 @@ use crate::exchange::{BlockNumberOf, RelayedBlockTransactions, TransactionProofP use relay_utils::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; /// Exchange transactions relay metrics. +#[derive(Clone)] pub struct ExchangeLoopMetrics { /// Best finalized block numbers - "processed" and "known". best_block_numbers: GaugeVec, @@ -60,7 +61,7 @@ impl Default for ExchangeLoopMetrics { impl ExchangeLoopMetrics { /// Update metrics when single block is relayed. pub fn update( - &mut self, + &self, best_processed_block_number: BlockNumberOf

, best_known_block_number: BlockNumberOf

, relayed_transactions: RelayedBlockTransactions, diff --git a/relays/headers-relay/src/sync_loop.rs b/relays/headers-relay/src/sync_loop.rs index 15f982af768ad..d2584f2ccb2c8 100644 --- a/relays/headers-relay/src/sync_loop.rs +++ b/relays/headers-relay/src/sync_loop.rs @@ -26,7 +26,9 @@ use num_traits::{Saturating, Zero}; use relay_utils::{ format_ids, interval, metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, - process_future_result, retry_backoff, MaybeConnectionError, StringifiedMaybeConnectionError, + process_future_result, + relay_loop::Client as RelayClient, + retry_backoff, FailedClient, MaybeConnectionError, StringifiedMaybeConnectionError, }; use std::{ collections::HashSet, @@ -53,10 +55,7 @@ const MAINTAIN_INTERVAL: Duration = Duration::from_secs(30); /// Source client trait. #[async_trait] -pub trait SourceClient { - /// Type of error this clients returns. - type Error: std::fmt::Debug + MaybeConnectionError; - +pub trait SourceClient: RelayClient { /// Get best block number. async fn best_block_number(&self) -> Result; @@ -80,10 +79,7 @@ pub trait SourceClient { /// Target client trait. #[async_trait] -pub trait TargetClient { - /// Type of error this clients returns. - type Error: std::fmt::Debug + MaybeConnectionError; - +pub trait TargetClient: RelayClient { /// Returns ID of best header known to the target node. async fn best_header_id(&self) -> Result, Self::Error>; @@ -106,7 +102,7 @@ pub trait TargetClient { /// Synchronization maintain procedure. #[async_trait] -pub trait SyncMaintain: Send + Sync { +pub trait SyncMaintain: Clone + Send + Sync { /// Run custom maintain procedures. This is guaranteed to be called when both source and target /// clients are unoccupied. async fn maintain(&self, _sync: &mut HeadersSync

) {} @@ -126,465 +122,506 @@ pub fn run>( metrics_params: Option, exit_signal: impl Future, ) { - #![allow(unused_variables)] // this is to suppress weird errors from clippy - let mut local_pool = futures::executor::LocalPool::new(); - let mut progress_context = (Instant::now(), None, None); + let exit_signal = exit_signal.shared(); + + let metrics_global = GlobalMetrics::default(); + let metrics_sync = SyncLoopMetrics::default(); + let metrics_enabled = metrics_params.is_some(); + metrics_start( + format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), + metrics_params, + &metrics_global, + &metrics_sync, + ); - local_pool.run_until(async move { - let mut sync = HeadersSync::

::new(sync_params); - let mut stall_countdown = None; - let mut last_update_time = Instant::now(); - - let mut metrics_global = GlobalMetrics::default(); - let mut metrics_sync = SyncLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), - metrics_params, - &metrics_global, - &metrics_sync, - ); - - let mut source_retry_backoff = retry_backoff(); - let mut source_client_is_online = false; - let mut source_best_block_number_required = false; - let source_best_block_number_future = source_client.best_block_number().fuse(); - let source_new_header_future = futures::future::Fuse::terminated(); - let source_orphan_header_future = futures::future::Fuse::terminated(); - let source_extra_future = futures::future::Fuse::terminated(); - let source_completion_future = futures::future::Fuse::terminated(); - let source_go_offline_future = futures::future::Fuse::terminated(); - let source_tick_stream = interval(source_tick).fuse(); - - let mut target_retry_backoff = retry_backoff(); - let mut target_client_is_online = false; - let mut target_best_block_required = false; - let mut target_incomplete_headers_required = true; - let target_best_block_future = target_client.best_header_id().fuse(); - let target_incomplete_headers_future = futures::future::Fuse::terminated(); - let target_extra_check_future = futures::future::Fuse::terminated(); - let target_existence_status_future = futures::future::Fuse::terminated(); - let target_submit_header_future = futures::future::Fuse::terminated(); - let target_complete_header_future = futures::future::Fuse::terminated(); - let target_go_offline_future = futures::future::Fuse::terminated(); - let target_tick_stream = interval(target_tick).fuse(); - - let mut maintain_required = false; - let maintain_stream = interval(MAINTAIN_INTERVAL).fuse(); - - let exit_signal = exit_signal.fuse(); - - futures::pin_mut!( - source_best_block_number_future, - source_new_header_future, - source_orphan_header_future, - source_extra_future, - source_completion_future, - source_go_offline_future, - source_tick_stream, - target_best_block_future, - target_incomplete_headers_future, - target_extra_check_future, - target_existence_status_future, - target_submit_header_future, - target_complete_header_future, - target_go_offline_future, - target_tick_stream, - maintain_stream, - exit_signal - ); - - loop { - futures::select! { - source_best_block_number = source_best_block_number_future => { - source_best_block_number_required = false; - - source_client_is_online = process_future_result( - source_best_block_number, - &mut source_retry_backoff, - |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving best header number from {}", P::SOURCE_NAME), - ).is_ok(); - }, - source_new_header = source_new_header_future => { - source_client_is_online = process_future_result( - source_new_header, - &mut source_retry_backoff, - |source_new_header| sync.headers_mut().header_response(source_new_header), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving header from {} node", P::SOURCE_NAME), - ).is_ok(); - }, - source_orphan_header = source_orphan_header_future => { - source_client_is_online = process_future_result( - source_orphan_header, - &mut source_retry_backoff, - |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), - ).is_ok(); - }, - source_extra = source_extra_future => { - source_client_is_online = process_future_result( - source_extra, - &mut source_retry_backoff, - |(header, extra)| sync.headers_mut().extra_response(&header, extra), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), - ).is_ok(); - }, - source_completion = source_completion_future => { - source_client_is_online = process_future_result( - source_completion, - &mut source_retry_backoff, - |(header, completion)| sync.headers_mut().completion_response(&header, completion), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), - ).is_ok(); - }, - source_client = source_go_offline_future => { - source_client_is_online = true; - }, - _ = source_tick_stream.next() => { - if sync.is_almost_synced() { - source_best_block_number_required = true; - } - }, - target_best_block = target_best_block_future => { - target_best_block_required = false; - - target_client_is_online = process_future_result( - target_best_block, - &mut target_retry_backoff, - |target_best_block| { - let head_updated = sync.target_best_header_response(target_best_block); - if head_updated { - last_update_time = Instant::now(); - } - match head_updated { - // IF head is updated AND there are still our transactions: - // => restart stall countdown timer - true if sync.headers().headers_in_status(HeaderStatus::Submitted) != 0 => - stall_countdown = Some(Instant::now()), - // IF head is updated AND there are no our transactions: - // => stop stall countdown timer - true => stall_countdown = None, - // IF head is not updated AND stall countdown is not yet completed - // => do nothing - false if stall_countdown - .map(|stall_countdown| stall_countdown.elapsed() < STALL_SYNC_TIMEOUT) - .unwrap_or(true) - => (), - // IF head is not updated AND stall countdown has completed - // => restart sync - false => { - log::info!( - target: "bridge", - "Sync has stalled. Restarting {} headers synchronization.", - P::SOURCE_NAME, - ); - stall_countdown = None; - sync.restart(); - }, - } - }, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving best known {} header from {} node", P::SOURCE_NAME, P::TARGET_NAME), - ).is_ok(); - }, - incomplete_headers_ids = target_incomplete_headers_future => { - target_incomplete_headers_required = false; - - target_client_is_online = process_future_result( - incomplete_headers_ids, - &mut target_retry_backoff, - |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), - ).is_ok(); - }, - target_existence_status = target_existence_status_future => { - target_client_is_online = process_future_result( - target_existence_status, - &mut target_retry_backoff, - |(target_header, target_existence_status)| sync - .headers_mut() - .maybe_orphan_response(&target_header, target_existence_status), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving existence status from {} node", P::TARGET_NAME), - ).is_ok(); - }, - submitted_headers = target_submit_header_future => { - // following line helps Rust understand the type of `submitted_headers` :/ - let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; - let submitted_headers_str = format!("{}", submitted_headers); - let all_headers_rejected = submitted_headers.submitted.is_empty() - && submitted_headers.incomplete.is_empty(); - let has_submitted_headers = sync.headers().headers_in_status(HeaderStatus::Submitted) != 0; - - let maybe_fatal_error = match submitted_headers.fatal_error { - Some(fatal_error) => Err(StringifiedMaybeConnectionError::new( - fatal_error.is_connection_error(), - format!("{:?}", fatal_error), - )), - None if all_headers_rejected && !has_submitted_headers => - Err(StringifiedMaybeConnectionError::new(false, "All headers were rejected".into())), - None => Ok(()), - }; - - let no_fatal_error = maybe_fatal_error.is_ok(); - target_client_is_online = process_future_result( - maybe_fatal_error, - &mut target_retry_backoff, - |_| {}, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error submitting headers to {} node", P::TARGET_NAME), - ).is_ok(); - - log::debug!(target: "bridge", "Header submit result: {}", submitted_headers_str); - - sync.headers_mut().headers_submitted(submitted_headers.submitted); - sync.headers_mut().add_incomplete_headers(false, submitted_headers.incomplete); - - // when there's no fatal error, but node has rejected all our headers we may - // want to pause until our submitted headers will be accepted - if no_fatal_error && all_headers_rejected && has_submitted_headers { - sync.pause_submit(); - } - }, - target_complete_header_result = target_complete_header_future => { - target_client_is_online = process_future_result( - target_complete_header_result, - &mut target_retry_backoff, - |completed_header| sync.headers_mut().header_completed(&completed_header), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error completing headers at {}", P::TARGET_NAME), - ).is_ok(); - }, - target_extra_check_result = target_extra_check_future => { - target_client_is_online = process_future_result( - target_extra_check_result, - &mut target_retry_backoff, - |(header, extra_check_result)| sync - .headers_mut() - .maybe_extra_response(&header, extra_check_result), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), - ).is_ok(); - }, - target_client = target_go_offline_future => { - target_client_is_online = true; - }, - _ = target_tick_stream.next() => { - target_best_block_required = true; - target_incomplete_headers_required = true; + relay_utils::relay_loop::run( + relay_utils::relay_loop::RECONNECT_DELAY, + source_client, + target_client, + |source_client, target_client| { + run_until_connection_lost( + source_client, + source_tick, + target_client, + target_tick, + sync_maintain.clone(), + sync_params.clone(), + if metrics_enabled { + Some(metrics_global.clone()) + } else { + None }, - - _ = maintain_stream.next() => { - maintain_required = true; + if metrics_enabled { + Some(metrics_sync.clone()) + } else { + None }, - _ = exit_signal => { - return; - } - } + exit_signal.clone(), + ) + }, + ); +} - // update metrics - if metrics_enabled { - metrics_global.update(); - metrics_sync.update(&sync); - } +/// Run headers synchronization. +#[allow(clippy::too_many_arguments)] +async fn run_until_connection_lost>( + source_client: impl SourceClient

, + source_tick: Duration, + target_client: TC, + target_tick: Duration, + sync_maintain: impl SyncMaintain

, + sync_params: HeadersSyncParams, + metrics_global: Option, + metrics_sync: Option, + exit_signal: impl Future, +) -> Result<(), FailedClient> { + let mut progress_context = (Instant::now(), None, None); - // print progress - progress_context = print_sync_progress(progress_context, &sync); + let mut sync = HeadersSync::

::new(sync_params); + let mut stall_countdown = None; + let mut last_update_time = Instant::now(); + + let mut source_retry_backoff = retry_backoff(); + let mut source_client_is_online = false; + let mut source_best_block_number_required = false; + let source_best_block_number_future = source_client.best_block_number().fuse(); + let source_new_header_future = futures::future::Fuse::terminated(); + let source_orphan_header_future = futures::future::Fuse::terminated(); + let source_extra_future = futures::future::Fuse::terminated(); + let source_completion_future = futures::future::Fuse::terminated(); + let source_go_offline_future = futures::future::Fuse::terminated(); + let source_tick_stream = interval(source_tick).fuse(); + + let mut target_retry_backoff = retry_backoff(); + let mut target_client_is_online = false; + let mut target_best_block_required = false; + let mut target_incomplete_headers_required = true; + let target_best_block_future = target_client.best_header_id().fuse(); + let target_incomplete_headers_future = futures::future::Fuse::terminated(); + let target_extra_check_future = futures::future::Fuse::terminated(); + let target_existence_status_future = futures::future::Fuse::terminated(); + let target_submit_header_future = futures::future::Fuse::terminated(); + let target_complete_header_future = futures::future::Fuse::terminated(); + let target_go_offline_future = futures::future::Fuse::terminated(); + let target_tick_stream = interval(target_tick).fuse(); + + let mut maintain_required = false; + let maintain_stream = interval(MAINTAIN_INTERVAL).fuse(); + + let exit_signal = exit_signal.fuse(); + + futures::pin_mut!( + source_best_block_number_future, + source_new_header_future, + source_orphan_header_future, + source_extra_future, + source_completion_future, + source_go_offline_future, + source_tick_stream, + target_best_block_future, + target_incomplete_headers_future, + target_extra_check_future, + target_existence_status_future, + target_submit_header_future, + target_complete_header_future, + target_go_offline_future, + target_tick_stream, + maintain_stream, + exit_signal + ); - // run maintain procedures - if maintain_required && source_client_is_online && target_client_is_online { - log::debug!(target: "bridge", "Maintaining headers sync loop"); - maintain_required = false; - sync_maintain.maintain(&mut sync).await; + loop { + futures::select! { + source_best_block_number = source_best_block_number_future => { + source_best_block_number_required = false; + + source_client_is_online = process_future_result( + source_best_block_number, + &mut source_retry_backoff, + |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), + &mut source_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving best header number from {}", P::SOURCE_NAME), + ).fail_if_connection_error(FailedClient::Source)?; + }, + source_new_header = source_new_header_future => { + source_client_is_online = process_future_result( + source_new_header, + &mut source_retry_backoff, + |source_new_header| sync.headers_mut().header_response(source_new_header), + &mut source_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving header from {} node", P::SOURCE_NAME), + ).fail_if_connection_error(FailedClient::Source)?; + }, + source_orphan_header = source_orphan_header_future => { + source_client_is_online = process_future_result( + source_orphan_header, + &mut source_retry_backoff, + |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), + &mut source_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), + ).fail_if_connection_error(FailedClient::Source)?; + }, + source_extra = source_extra_future => { + source_client_is_online = process_future_result( + source_extra, + &mut source_retry_backoff, + |(header, extra)| sync.headers_mut().extra_response(&header, extra), + &mut source_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), + ).fail_if_connection_error(FailedClient::Source)?; + }, + source_completion = source_completion_future => { + source_client_is_online = process_future_result( + source_completion, + &mut source_retry_backoff, + |(header, completion)| sync.headers_mut().completion_response(&header, completion), + &mut source_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), + ).fail_if_connection_error(FailedClient::Source)?; + }, + _ = source_go_offline_future => { + source_client_is_online = true; + }, + _ = source_tick_stream.next() => { + if sync.is_almost_synced() { + source_best_block_number_required = true; + } + }, + target_best_block = target_best_block_future => { + target_best_block_required = false; + + target_client_is_online = process_future_result( + target_best_block, + &mut target_retry_backoff, + |target_best_block| { + let head_updated = sync.target_best_header_response(target_best_block); + if head_updated { + last_update_time = Instant::now(); + } + match head_updated { + // IF head is updated AND there are still our transactions: + // => restart stall countdown timer + true if sync.headers().headers_in_status(HeaderStatus::Submitted) != 0 => + stall_countdown = Some(Instant::now()), + // IF head is updated AND there are no our transactions: + // => stop stall countdown timer + true => stall_countdown = None, + // IF head is not updated AND stall countdown is not yet completed + // => do nothing + false if stall_countdown + .map(|stall_countdown| stall_countdown.elapsed() < STALL_SYNC_TIMEOUT) + .unwrap_or(true) + => (), + // IF head is not updated AND stall countdown has completed + // => restart sync + false => { + log::info!( + target: "bridge", + "Sync has stalled. Restarting {} headers synchronization.", + P::SOURCE_NAME, + ); + stall_countdown = None; + sync.restart(); + }, + } + }, + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving best known {} header from {} node", P::SOURCE_NAME, P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + }, + incomplete_headers_ids = target_incomplete_headers_future => { + target_incomplete_headers_required = false; + + target_client_is_online = process_future_result( + incomplete_headers_ids, + &mut target_retry_backoff, + |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + }, + target_existence_status = target_existence_status_future => { + target_client_is_online = process_future_result( + target_existence_status, + &mut target_retry_backoff, + |(target_header, target_existence_status)| sync + .headers_mut() + .maybe_orphan_response(&target_header, target_existence_status), + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving existence status from {} node", P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + }, + submitted_headers = target_submit_header_future => { + // following line helps Rust understand the type of `submitted_headers` :/ + let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; + let submitted_headers_str = format!("{}", submitted_headers); + let all_headers_rejected = submitted_headers.submitted.is_empty() + && submitted_headers.incomplete.is_empty(); + let has_submitted_headers = sync.headers().headers_in_status(HeaderStatus::Submitted) != 0; + + let maybe_fatal_error = match submitted_headers.fatal_error { + Some(fatal_error) => Err(StringifiedMaybeConnectionError::new( + fatal_error.is_connection_error(), + format!("{:?}", fatal_error), + )), + None if all_headers_rejected && !has_submitted_headers => + Err(StringifiedMaybeConnectionError::new(false, "All headers were rejected".into())), + None => Ok(()), + }; + + let no_fatal_error = maybe_fatal_error.is_ok(); + target_client_is_online = process_future_result( + maybe_fatal_error, + &mut target_retry_backoff, + |_| {}, + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error submitting headers to {} node", P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + + log::debug!(target: "bridge", "Header submit result: {}", submitted_headers_str); + + sync.headers_mut().headers_submitted(submitted_headers.submitted); + sync.headers_mut().add_incomplete_headers(false, submitted_headers.incomplete); + + // when there's no fatal error, but node has rejected all our headers we may + // want to pause until our submitted headers will be accepted + if no_fatal_error && all_headers_rejected && has_submitted_headers { + sync.pause_submit(); + } + }, + target_complete_header_result = target_complete_header_future => { + target_client_is_online = process_future_result( + target_complete_header_result, + &mut target_retry_backoff, + |completed_header| sync.headers_mut().header_completed(&completed_header), + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error completing headers at {}", P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + }, + target_extra_check_result = target_extra_check_future => { + target_client_is_online = process_future_result( + target_extra_check_result, + &mut target_retry_backoff, + |(header, extra_check_result)| sync + .headers_mut() + .maybe_extra_response(&header, extra_check_result), + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), + ).fail_if_connection_error(FailedClient::Target)?; + }, + _ = target_go_offline_future => { + target_client_is_online = true; + }, + _ = target_tick_stream.next() => { + target_best_block_required = true; + target_incomplete_headers_required = true; + }, + + _ = maintain_stream.next() => { + maintain_required = true; + }, + _ = exit_signal => { + return Ok(()); } + } - // If the target client is accepting requests we update the requests that - // we want it to run - if !maintain_required && target_client_is_online { - // NOTE: Is is important to reset this so that we only have one - // request being processed by the client at a time. This prevents - // race conditions like receiving two transactions with the same - // nonce from the client. - target_client_is_online = false; - - // The following is how we prioritize requests: - // - // 1. Get best block - // - Stops us from downloading or submitting new blocks - // - Only called rarely - // - // 2. Get incomplete headers - // - Stops us from submitting new blocks - // - Only called rarely - // - // 3. Get complete headers - // - Stops us from submitting new blocks - // - // 4. Check if we need extra data from source - // - Stops us from downloading or submitting new blocks - // - // 5. Check existence of header - // - Stops us from submitting new blocks - // - // 6. Submit header - - if target_best_block_required { - log::debug!(target: "bridge", "Asking {} about best block", P::TARGET_NAME); - target_best_block_future.set(target_client.best_header_id().fuse()); - } else if target_incomplete_headers_required { - log::debug!(target: "bridge", "Asking {} about incomplete headers", P::TARGET_NAME); - target_incomplete_headers_future.set(target_client.incomplete_headers_ids().fuse()); - } else if let Some((id, completion)) = sync.headers_mut().header_to_complete() { - log::debug!( - target: "bridge", - "Going to complete header: {:?}", - id, - ); - - target_complete_header_future.set(target_client.complete_header(id, completion.clone()).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeExtra) { - log::debug!( - target: "bridge", - "Checking if header submission requires extra: {:?}", - header.id(), - ); - - target_extra_check_future.set(target_client.requires_extra(header.clone()).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeOrphan) { - // for MaybeOrphan we actually ask for parent' header existence - let parent_id = header.parent_id(); + // update metrics + if let Some(ref metrics_global) = metrics_global { + metrics_global.update().await; + } + if let Some(ref metrics_sync) = metrics_sync { + metrics_sync.update(&sync); + } - log::debug!( - target: "bridge", - "Asking {} node for existence of: {:?}", - P::TARGET_NAME, - parent_id, - ); + // print progress + progress_context = print_sync_progress(progress_context, &sync); - target_existence_status_future.set(target_client.is_known_header(parent_id).fuse()); - } else if let Some(headers) = - sync.select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) - { - log::debug!( - target: "bridge", - "Submitting {} header(s) to {} node: {:?}", - headers.len(), - P::TARGET_NAME, - format_ids(headers.iter().map(|header| header.id())), - ); - - let headers = headers.into_iter().cloned().collect(); - target_submit_header_future.set(target_client.submit_headers(headers).fuse()); + // run maintain procedures + if maintain_required && source_client_is_online && target_client_is_online { + log::debug!(target: "bridge", "Maintaining headers sync loop"); + maintain_required = false; + sync_maintain.maintain(&mut sync).await; + } - // remember that we have submitted some headers - if stall_countdown.is_none() { - stall_countdown = Some(Instant::now()); - } - } else { - target_client_is_online = true; + // If the target client is accepting requests we update the requests that + // we want it to run + if !maintain_required && target_client_is_online { + // NOTE: Is is important to reset this so that we only have one + // request being processed by the client at a time. This prevents + // race conditions like receiving two transactions with the same + // nonce from the client. + target_client_is_online = false; + + // The following is how we prioritize requests: + // + // 1. Get best block + // - Stops us from downloading or submitting new blocks + // - Only called rarely + // + // 2. Get incomplete headers + // - Stops us from submitting new blocks + // - Only called rarely + // + // 3. Get complete headers + // - Stops us from submitting new blocks + // + // 4. Check if we need extra data from source + // - Stops us from downloading or submitting new blocks + // + // 5. Check existence of header + // - Stops us from submitting new blocks + // + // 6. Submit header + + if target_best_block_required { + log::debug!(target: "bridge", "Asking {} about best block", P::TARGET_NAME); + target_best_block_future.set(target_client.best_header_id().fuse()); + } else if target_incomplete_headers_required { + log::debug!(target: "bridge", "Asking {} about incomplete headers", P::TARGET_NAME); + target_incomplete_headers_future.set(target_client.incomplete_headers_ids().fuse()); + } else if let Some((id, completion)) = sync.headers_mut().header_to_complete() { + log::debug!( + target: "bridge", + "Going to complete header: {:?}", + id, + ); + + target_complete_header_future.set(target_client.complete_header(id, completion.clone()).fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeExtra) { + log::debug!( + target: "bridge", + "Checking if header submission requires extra: {:?}", + header.id(), + ); + + target_extra_check_future.set(target_client.requires_extra(header.clone()).fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeOrphan) { + // for MaybeOrphan we actually ask for parent' header existence + let parent_id = header.parent_id(); + + log::debug!( + target: "bridge", + "Asking {} node for existence of: {:?}", + P::TARGET_NAME, + parent_id, + ); + + target_existence_status_future.set(target_client.is_known_header(parent_id).fuse()); + } else if let Some(headers) = + sync.select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) + { + log::debug!( + target: "bridge", + "Submitting {} header(s) to {} node: {:?}", + headers.len(), + P::TARGET_NAME, + format_ids(headers.iter().map(|header| header.id())), + ); + + let headers = headers.into_iter().cloned().collect(); + target_submit_header_future.set(target_client.submit_headers(headers).fuse()); + + // remember that we have submitted some headers + if stall_countdown.is_none() { + stall_countdown = Some(Instant::now()); } + } else { + target_client_is_online = true; } + } - // If the source client is accepting requests we update the requests that - // we want it to run - if !maintain_required && source_client_is_online { - // NOTE: Is is important to reset this so that we only have one - // request being processed by the client at a time. This prevents - // race conditions like receiving two transactions with the same - // nonce from the client. - source_client_is_online = false; - - // The following is how we prioritize requests: - // - // 1. Get best block - // - Stops us from downloading or submitting new blocks - // - Only called rarely - // - // 2. Download completion data - // - Stops us from submitting new blocks - // - // 3. Download extra data - // - Stops us from submitting new blocks - // - // 4. Download missing headers - // - Stops us from downloading or submitting new blocks - // - // 5. Downloading new headers - - if source_best_block_number_required { - log::debug!(target: "bridge", "Asking {} node about best block number", P::SOURCE_NAME); - source_best_block_number_future.set(source_client.best_block_number().fuse()); - } else if let Some(id) = sync.headers_mut().incomplete_header() { - log::debug!( - target: "bridge", - "Retrieving completion data for header: {:?}", - id, - ); - source_completion_future.set(source_client.header_completion(id).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::Extra) { - let id = header.id(); - log::debug!( - target: "bridge", - "Retrieving extra data for header: {:?}", - id, - ); - source_extra_future.set(source_client.header_extra(id, header.clone()).fuse()); - } else if let Some(header) = sync.select_orphan_header_to_download() { - // for Orphan we actually ask for parent' header - let parent_id = header.parent_id(); - - // if we have end up with orphan header#0, then we are misconfigured - if parent_id.0.is_zero() { - log::error!( - target: "bridge", - "Misconfiguration. Genesis {} header is considered orphan by {} node", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - return; - } - - log::debug!( - target: "bridge", - "Going to download orphan header from {} node: {:?}", - P::SOURCE_NAME, - parent_id, - ); - - source_orphan_header_future.set(source_client.header_by_hash(parent_id.1).fuse()); - } else if let Some(id) = sync.select_new_header_to_download() { - log::debug!( + // If the source client is accepting requests we update the requests that + // we want it to run + if !maintain_required && source_client_is_online { + // NOTE: Is is important to reset this so that we only have one + // request being processed by the client at a time. This prevents + // race conditions like receiving two transactions with the same + // nonce from the client. + source_client_is_online = false; + + // The following is how we prioritize requests: + // + // 1. Get best block + // - Stops us from downloading or submitting new blocks + // - Only called rarely + // + // 2. Download completion data + // - Stops us from submitting new blocks + // + // 3. Download extra data + // - Stops us from submitting new blocks + // + // 4. Download missing headers + // - Stops us from downloading or submitting new blocks + // + // 5. Downloading new headers + + if source_best_block_number_required { + log::debug!(target: "bridge", "Asking {} node about best block number", P::SOURCE_NAME); + source_best_block_number_future.set(source_client.best_block_number().fuse()); + } else if let Some(id) = sync.headers_mut().incomplete_header() { + log::debug!( + target: "bridge", + "Retrieving completion data for header: {:?}", + id, + ); + source_completion_future.set(source_client.header_completion(id).fuse()); + } else if let Some(header) = sync.headers().header(HeaderStatus::Extra) { + let id = header.id(); + log::debug!( + target: "bridge", + "Retrieving extra data for header: {:?}", + id, + ); + source_extra_future.set(source_client.header_extra(id, header.clone()).fuse()); + } else if let Some(header) = sync.select_orphan_header_to_download() { + // for Orphan we actually ask for parent' header + let parent_id = header.parent_id(); + + // if we have end up with orphan header#0, then we are misconfigured + if parent_id.0.is_zero() { + log::error!( target: "bridge", - "Going to download new header from {} node: {:?}", + "Misconfiguration. Genesis {} header is considered orphan by {} node", P::SOURCE_NAME, - id, + P::TARGET_NAME, ); - - source_new_header_future.set(source_client.header_by_number(id).fuse()); - } else { - source_client_is_online = true; + return Ok(()); } + + log::debug!( + target: "bridge", + "Going to download orphan header from {} node: {:?}", + P::SOURCE_NAME, + parent_id, + ); + + source_orphan_header_future.set(source_client.header_by_hash(parent_id.1).fuse()); + } else if let Some(id) = sync.select_new_header_to_download() { + log::debug!( + target: "bridge", + "Going to download new header from {} node: {:?}", + P::SOURCE_NAME, + id, + ); + + source_new_header_future.set(source_client.header_by_number(id).fuse()); + } else { + source_client_is_online = true; } } - }); + } } /// Print synchronization progress. diff --git a/relays/headers-relay/src/sync_loop_metrics.rs b/relays/headers-relay/src/sync_loop_metrics.rs index 26939ee372cb7..456aa0a6b0522 100644 --- a/relays/headers-relay/src/sync_loop_metrics.rs +++ b/relays/headers-relay/src/sync_loop_metrics.rs @@ -23,6 +23,7 @@ use num_traits::Zero; use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; /// Headers sync metrics. +#[derive(Clone)] pub struct SyncLoopMetrics { /// Best syncing headers at "source" and "target" nodes. best_block_numbers: GaugeVec, @@ -57,7 +58,7 @@ impl Default for SyncLoopMetrics { impl SyncLoopMetrics { /// Update metrics. - pub fn update(&mut self, sync: &HeadersSync

) { + pub fn update(&self, sync: &HeadersSync

) { let headers = sync.headers(); let source_best_number = sync.source_best_number().unwrap_or_else(Zero::zero); let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); diff --git a/relays/headers-relay/src/sync_loop_tests.rs b/relays/headers-relay/src/sync_loop_tests.rs index 27e5daa7da4f4..5cfd5e4f57b66 100644 --- a/relays/headers-relay/src/sync_loop_tests.rs +++ b/relays/headers-relay/src/sync_loop_tests.rs @@ -23,7 +23,9 @@ use async_trait::async_trait; use backoff::backoff::Backoff; use futures::{future::FutureExt, stream::StreamExt}; use parking_lot::Mutex; -use relay_utils::{process_future_result, retry_backoff, HeaderId, MaybeConnectionError}; +use relay_utils::{ + process_future_result, relay_loop::Client as RelayClient, retry_backoff, HeaderId, MaybeConnectionError, +}; use std::{ collections::{HashMap, HashSet}, sync::Arc, @@ -89,8 +91,9 @@ enum SourceMethod { HeaderExtra(TestHeaderId, TestQueuedHeader), } +#[derive(Clone)] struct Source { - data: Mutex, + data: Arc>, on_method_call: Arc, } @@ -109,7 +112,7 @@ impl Source { on_method_call: impl Fn(SourceMethod, &mut SourceData) + Send + Sync + 'static, ) -> Self { Source { - data: Mutex::new(SourceData { + data: Arc::new(Mutex::new(SourceData { best_block_number: Ok(best_block_id.0), header_by_hash: headers .iter() @@ -127,35 +130,42 @@ impl Source { .collect(), provides_completion: true, provides_extra: true, - }), + })), on_method_call: Arc::new(on_method_call), } } } #[async_trait] -impl SourceClient for Source { +impl RelayClient for Source { type Error = TestError; - async fn best_block_number(&self) -> Result { + async fn reconnect(&mut self) -> Result<(), TestError> { + unimplemented!() + } +} + +#[async_trait] +impl SourceClient for Source { + async fn best_block_number(&self) -> Result { let mut data = self.data.lock(); (self.on_method_call)(SourceMethod::BestBlockNumber, &mut *data); data.best_block_number.clone() } - async fn header_by_hash(&self, hash: TestHash) -> Result { + async fn header_by_hash(&self, hash: TestHash) -> Result { let mut data = self.data.lock(); (self.on_method_call)(SourceMethod::HeaderByHash(hash), &mut *data); data.header_by_hash.get(&hash).cloned().ok_or(TestError(false)) } - async fn header_by_number(&self, number: TestNumber) -> Result { + async fn header_by_number(&self, number: TestNumber) -> Result { let mut data = self.data.lock(); (self.on_method_call)(SourceMethod::HeaderByNumber(number), &mut *data); data.header_by_number.get(&number).cloned().ok_or(TestError(false)) } - async fn header_completion(&self, id: TestHeaderId) -> Result<(TestHeaderId, Option), Self::Error> { + async fn header_completion(&self, id: TestHeaderId) -> Result<(TestHeaderId, Option), TestError> { let mut data = self.data.lock(); (self.on_method_call)(SourceMethod::HeaderCompletion(id), &mut *data); if data.provides_completion { @@ -169,7 +179,7 @@ impl SourceClient for Source { &self, id: TestHeaderId, header: TestQueuedHeader, - ) -> Result<(TestHeaderId, TestExtra), Self::Error> { + ) -> Result<(TestHeaderId, TestExtra), TestError> { let mut data = self.data.lock(); (self.on_method_call)(SourceMethod::HeaderExtra(id, header), &mut *data); if data.provides_extra { @@ -189,8 +199,9 @@ enum TargetMethod { RequiresExtra(TestQueuedHeader), } +#[derive(Clone)] struct Target { - data: Mutex, + data: Arc>, on_method_call: Arc, } @@ -211,7 +222,7 @@ impl Target { on_method_call: impl Fn(TargetMethod, &mut TargetData) + Send + Sync + 'static, ) -> Self { Target { - data: Mutex::new(TargetData { + data: Arc::new(Mutex::new(TargetData { best_header_id: Ok(best_header_id), is_known_header_by_hash: headers.iter().map(|header| (header.1, true)).collect(), submitted_headers: HashMap::new(), @@ -219,16 +230,23 @@ impl Target { completed_headers: HashMap::new(), requires_completion: false, requires_extra: false, - }), + })), on_method_call: Arc::new(on_method_call), } } } #[async_trait] -impl TargetClient for Target { +impl RelayClient for Target { type Error = TestError; + async fn reconnect(&mut self) -> Result<(), TestError> { + unimplemented!() + } +} + +#[async_trait] +impl TargetClient for Target { async fn best_header_id(&self) -> Result { let mut data = self.data.lock(); (self.on_method_call)(TargetMethod::BestHeaderId, &mut *data); diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/messages-relay/src/message_lane_loop.rs index b60cbf35137e3..28b55dba47cc7 100644 --- a/relays/messages-relay/src/message_lane_loop.rs +++ b/relays/messages-relay/src/message_lane_loop.rs @@ -35,7 +35,9 @@ use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, - process_future_result, retry_backoff, FailedClient, MaybeConnectionError, + process_future_result, + relay_loop::Client as RelayClient, + retry_backoff, FailedClient, }; use std::{collections::BTreeMap, fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; @@ -98,13 +100,7 @@ pub struct MessageProofParameters { /// Source client trait. #[async_trait] -pub trait SourceClient: Clone + Send + Sync { - /// Type of error this clients returns. - type Error: std::fmt::Debug + MaybeConnectionError; - - /// Try to reconnect to source node. - async fn reconnect(self) -> Result; - +pub trait SourceClient: RelayClient { /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -147,13 +143,7 @@ pub trait SourceClient: Clone + Send + Sync { /// Target client trait. #[async_trait] -pub trait TargetClient: Clone + Send + Sync { - /// Type of error this clients returns. - type Error: std::fmt::Debug + MaybeConnectionError; - - /// Try to reconnect to source node. - async fn reconnect(self) -> Result; - +pub trait TargetClient: RelayClient { /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -218,37 +208,38 @@ pub struct ClientsState { /// Run message lane service loop. pub fn run( params: Params, - mut source_client: impl SourceClient

, - mut target_client: impl TargetClient

, + source_client: impl SourceClient

, + target_client: impl TargetClient

, metrics_params: Option, exit_signal: impl Future, ) { - let mut local_pool = futures::executor::LocalPool::new(); let exit_signal = exit_signal.shared(); + let metrics_global = GlobalMetrics::default(); + let metrics_msg = MessageLaneLoopMetrics::default(); + let metrics_enabled = metrics_params.is_some(); + metrics_start( + format!( + "{}_to_{}_MessageLane_{}", + P::SOURCE_NAME, + P::TARGET_NAME, + hex::encode(params.lane) + ), + metrics_params, + &metrics_global, + &metrics_msg, + ); - local_pool.run_until(async move { - let mut metrics_global = GlobalMetrics::default(); - let metrics_msg = MessageLaneLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!( - "{}_to_{}_MessageLane_{}", - P::SOURCE_NAME, - P::TARGET_NAME, - hex::encode(params.lane) - ), - metrics_params, - &metrics_global, - &metrics_msg, - ); - - loop { - let result = run_until_connection_lost( + relay_utils::relay_loop::run( + params.reconnect_delay, + source_client, + target_client, + |source_client, target_client| { + run_until_connection_lost( params.clone(), - source_client.clone(), - target_client.clone(), + source_client, + target_client, if metrics_enabled { - Some(&mut metrics_global) + Some(metrics_global.clone()) } else { None }, @@ -259,55 +250,8 @@ pub fn run( }, exit_signal.clone(), ) - .await; - - match result { - Ok(()) => break, - Err(failed_client) => loop { - async_std::task::sleep(params.reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - source_client = match source_client.clone().reconnect().await { - Ok(source_client) => source_client, - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect {}. Going to retry in {}s: {:?}", - P::SOURCE_NAME, - params.reconnect_delay.as_secs(), - error, - ); - continue; - } - } - } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - target_client = match target_client.clone().reconnect().await { - Ok(target_client) => target_client, - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect {}. Going to retry in {}s: {:?}", - P::TARGET_NAME, - params.reconnect_delay.as_secs(), - error, - ); - continue; - } - } - } - - break; - }, - } - - log::debug!( - target: "bridge", - "Restarting lane {} -> {}", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - } - }); + }, + ); } /// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. @@ -315,7 +259,7 @@ async fn run_until_connection_lost, TC: Targ params: Params, source_client: SC, target_client: TC, - mut metrics_global: Option<&mut GlobalMetrics>, + metrics_global: Option, metrics_msg: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { @@ -459,8 +403,8 @@ async fn run_until_connection_lost, TC: Targ } } - if let Some(metrics_global) = metrics_global.as_mut() { - metrics_global.update(); + if let Some(ref metrics_global) = metrics_global { + metrics_global.update().await; } if source_client_is_online && source_state_required { @@ -482,7 +426,7 @@ pub(crate) mod tests { use super::*; use futures::stream::StreamExt; use parking_lot::Mutex; - use relay_utils::HeaderId; + use relay_utils::{HeaderId, MaybeConnectionError}; use std::sync::Arc; pub fn header_id(number: TestSourceHeaderNumber) -> TestSourceHeaderId { @@ -550,19 +494,22 @@ pub(crate) mod tests { } #[async_trait] - impl SourceClient for TestSourceClient { + impl RelayClient for TestSourceClient { type Error = TestError; - async fn reconnect(self) -> Result { + async fn reconnect(&mut self) -> Result<(), TestError> { { let mut data = self.data.lock(); (self.tick)(&mut *data); data.is_source_reconnected = true; } - Ok(self) + Ok(()) } + } - async fn state(&self) -> Result, Self::Error> { + #[async_trait] + impl SourceClient for TestSourceClient { + async fn state(&self) -> Result, TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { @@ -574,7 +521,7 @@ pub(crate) mod tests { async fn latest_generated_nonce( &self, id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { @@ -586,7 +533,7 @@ pub(crate) mod tests { async fn latest_confirmed_received_nonce( &self, id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); Ok((id, data.source_latest_confirmed_received_nonce)) @@ -596,7 +543,7 @@ pub(crate) mod tests { &self, _id: SourceHeaderIdOf, nonces: RangeInclusive, - ) -> Result { + ) -> Result { Ok(nonces .map(|nonce| (nonce, MessageWeights { weight: 1, size: 1 })) .collect()) @@ -613,7 +560,7 @@ pub(crate) mod tests { RangeInclusive, TestMessagesProof, ), - Self::Error, + TestError, > { let mut data = self.data.lock(); (self.tick)(&mut *data); @@ -635,7 +582,7 @@ pub(crate) mod tests { &self, _generated_at_block: TargetHeaderIdOf, proof: TestMessagesReceivingProof, - ) -> Result<(), Self::Error> { + ) -> Result<(), TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); data.submitted_messages_receiving_proofs.push(proof); @@ -651,19 +598,22 @@ pub(crate) mod tests { } #[async_trait] - impl TargetClient for TestTargetClient { + impl RelayClient for TestTargetClient { type Error = TestError; - async fn reconnect(self) -> Result { + async fn reconnect(&mut self) -> Result<(), TestError> { { let mut data = self.data.lock(); (self.tick)(&mut *data); data.is_target_reconnected = true; } - Ok(self) + Ok(()) } + } - async fn state(&self) -> Result, Self::Error> { + #[async_trait] + impl TargetClient for TestTargetClient { + async fn state(&self) -> Result, TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { @@ -675,7 +625,7 @@ pub(crate) mod tests { async fn latest_received_nonce( &self, id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { @@ -687,7 +637,7 @@ pub(crate) mod tests { async fn unrewarded_relayers_state( &self, id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), Self::Error> { + ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), TestError> { Ok(( id, UnrewardedRelayersState { @@ -701,7 +651,7 @@ pub(crate) mod tests { async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { @@ -713,7 +663,7 @@ pub(crate) mod tests { async fn prove_messages_receiving( &self, id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, TestMessagesReceivingProof), Self::Error> { + ) -> Result<(TargetHeaderIdOf, TestMessagesReceivingProof), TestError> { Ok((id, self.data.lock().target_latest_received_nonce)) } @@ -722,7 +672,7 @@ pub(crate) mod tests { _generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: TestMessagesProof, - ) -> Result, Self::Error> { + ) -> Result, TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index e52af57cdd59e..cfa644bc8c71e 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -89,12 +89,9 @@ impl Client { } /// Reopen client connection. - pub async fn reconnect(self) -> Result { - Ok(Self { - params: self.params.clone(), - client: Self::build_client(self.params).await?, - genesis_hash: self.genesis_hash, - }) + pub async fn reconnect(&mut self) -> Result<()> { + self.client = Self::build_client(self.params.clone()).await?; + Ok(()) } /// Build client to use in connection. diff --git a/relays/substrate-client/src/headers_source.rs b/relays/substrate-client/src/headers_source.rs index 33f194322ddea..040cc08e99766 100644 --- a/relays/substrate-client/src/headers_source.rs +++ b/relays/substrate-client/src/headers_source.rs @@ -25,6 +25,7 @@ use headers_relay::{ sync_loop::SourceClient, sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; +use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::{traits::Header as HeaderT, Justification}; use std::marker::PhantomData; @@ -44,6 +45,24 @@ impl HeadersSource { } } +impl Clone for HeadersSource { + fn clone(&self) -> Self { + HeadersSource { + client: self.client.clone(), + _phantom: Default::default(), + } + } +} + +#[async_trait] +impl RelayClient for HeadersSource { + type Error = Error; + + async fn reconnect(&mut self) -> Result<(), Error> { + self.client.reconnect().await + } +} + #[async_trait] impl SourceClient

for HeadersSource where @@ -53,13 +72,11 @@ where P: HeadersSyncPipeline, P::Header: SourceHeader, { - type Error = Error; - - async fn best_block_number(&self) -> Result { + async fn best_block_number(&self) -> Result { Ok(*self.client.best_header().await?.number()) } - async fn header_by_hash(&self, hash: P::Hash) -> Result { + async fn header_by_hash(&self, hash: P::Hash) -> Result { self.client .header_by_hash(hash) .await @@ -67,7 +84,7 @@ where .map_err(Into::into) } - async fn header_by_number(&self, number: P::Number) -> Result { + async fn header_by_number(&self, number: P::Number) -> Result { self.client .header_by_number(number) .await @@ -75,10 +92,7 @@ where .map_err(Into::into) } - async fn header_completion( - &self, - id: HeaderIdOf

, - ) -> Result<(HeaderIdOf

, Option), Self::Error> { + async fn header_completion(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, Option), Error> { let hash = id.1; let signed_block = self.client.get_block(Some(hash)).await?; let grandpa_justification = signed_block.justification().cloned(); @@ -86,11 +100,7 @@ where Ok((id, grandpa_justification)) } - async fn header_extra( - &self, - id: HeaderIdOf

, - _header: QueuedHeader

, - ) -> Result<(HeaderIdOf

, ()), Self::Error> { + async fn header_extra(&self, id: HeaderIdOf

, _header: QueuedHeader

) -> Result<(HeaderIdOf

, ()), Error> { Ok((id, ())) } } diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index d2996083b95ac..14432487ea308 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -80,6 +80,20 @@ impl } } +#[async_trait] +impl Clone + for SubstrateHeadersToSubstrateMaintain +{ + fn clone(&self) -> Self { + SubstrateHeadersToSubstrateMaintain { + pipeline: self.pipeline.clone(), + target_client: self.target_client.clone(), + justifications: self.justifications.clone(), + _marker: Default::default(), + } + } +} + #[async_trait] impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain where diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index e7fe68a5c0112..c962511270805 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -28,7 +28,7 @@ use headers_relay::{ sync_types::{HeaderIdOf, QueuedHeader, SubmittedHeaders}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError}; -use relay_utils::HeaderId; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::Bytes; use sp_runtime::Justification; use std::collections::HashSet; @@ -46,6 +46,24 @@ impl SubstrateHeadersTarget { } } +impl Clone for SubstrateHeadersTarget { + fn clone(&self) -> Self { + SubstrateHeadersTarget { + client: self.client.clone(), + pipeline: self.pipeline.clone(), + } + } +} + +#[async_trait] +impl RelayClient for SubstrateHeadersTarget { + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + #[async_trait] impl TargetClient

for SubstrateHeadersTarget where @@ -54,9 +72,7 @@ where P::Hash: Decode + Encode, P: SubstrateHeadersSyncPipeline, { - type Error = SubstrateError; - - async fn best_header_id(&self) -> Result, Self::Error> { + async fn best_header_id(&self) -> Result, SubstrateError> { let call = P::BEST_BLOCK_METHOD.into(); let data = Bytes(Vec::new()); @@ -72,7 +88,7 @@ where .map(|(num, hash)| HeaderId(*num, *hash)) } - async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), Self::Error> { + async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), SubstrateError> { let call = P::IS_KNOWN_BLOCK_METHOD.into(); let data = Bytes(id.1.encode()); @@ -83,7 +99,10 @@ where Ok((id, is_known_block)) } - async fn submit_headers(&self, mut headers: Vec>) -> SubmittedHeaders, Self::Error> { + async fn submit_headers( + &self, + mut headers: Vec>, + ) -> SubmittedHeaders, SubstrateError> { debug_assert_eq!( headers.len(), 1, @@ -114,7 +133,7 @@ where } } - async fn incomplete_headers_ids(&self) -> Result>, Self::Error> { + async fn incomplete_headers_ids(&self) -> Result>, SubstrateError> { let call = P::INCOMPLETE_HEADERS_METHOD.into(); let data = Bytes(Vec::new()); @@ -133,13 +152,13 @@ where &self, id: HeaderIdOf

, completion: Justification, - ) -> Result, Self::Error> { + ) -> Result, SubstrateError> { let tx = self.pipeline.make_complete_header_transaction(id, completion).await?; self.client.submit_extrinsic(Bytes(tx.encode())).await?; Ok(id) } - async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), Self::Error> { + async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), SubstrateError> { Ok((header.id(), false)) } } diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index 9376a14ce6f67..b9a8d01a7c258 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -32,7 +32,7 @@ use messages_relay::{ }, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; -use relay_utils::{BlockNumberBase, HeaderId}; +use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; @@ -74,6 +74,15 @@ impl Clone for SubstrateMessagesSource } } +#[async_trait] +impl RelayClient for SubstrateMessagesSource { + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + #[async_trait] impl SourceClient

for SubstrateMessagesSource where @@ -89,15 +98,7 @@ where P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, { - type Error = SubstrateError; - - async fn reconnect(mut self) -> Result { - let new_client = self.client.clone().reconnect().await?; - self.client = new_client; - Ok(self) - } - - async fn state(&self) -> Result, Self::Error> { + async fn state(&self) -> Result, SubstrateError> { read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>( &self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE, @@ -108,7 +109,7 @@ where async fn latest_generated_nonce( &self, id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -125,7 +126,7 @@ where async fn latest_confirmed_received_nonce( &self, id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -143,7 +144,7 @@ where &self, id: SourceHeaderIdOf

, nonces: RangeInclusive, - ) -> Result { + ) -> Result { let encoded_response = self .client .state_call( @@ -164,7 +165,7 @@ where id: SourceHeaderIdOf

, nonces: RangeInclusive, proof_parameters: MessageProofParameters, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), SubstrateError> { let proof = self .client .prove_messages( @@ -183,7 +184,7 @@ where &self, generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, - ) -> Result<(), Self::Error> { + ) -> Result<(), SubstrateError> { let tx = self .lane .make_messages_receiving_proof_transaction(generated_at_block, proof) diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 8a16ecdd6edc0..0bc81d9be05a3 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -30,7 +30,7 @@ use messages_relay::{ message_lane_loop::{TargetClient, TargetClientState}, }; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; -use relay_utils::BlockNumberBase; +use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use sp_trie::StorageProof; @@ -70,6 +70,15 @@ impl Clone for SubstrateMessagesTarget } } +#[async_trait] +impl RelayClient for SubstrateMessagesTarget { + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + #[async_trait] impl TargetClient

for SubstrateMessagesTarget where @@ -85,15 +94,7 @@ where P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, { - type Error = SubstrateError; - - async fn reconnect(mut self) -> Result { - let new_client = self.client.clone().reconnect().await?; - self.client = new_client; - Ok(self) - } - - async fn state(&self) -> Result, Self::Error> { + async fn state(&self) -> Result, SubstrateError> { read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>( &self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, @@ -104,7 +105,7 @@ where async fn latest_received_nonce( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -121,7 +122,7 @@ where async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -138,7 +139,7 @@ where async fn unrewarded_relayers_state( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, UnrewardedRelayersState), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, UnrewardedRelayersState), SubstrateError> { let encoded_response = self .client .state_call( @@ -155,7 +156,7 @@ where async fn prove_messages_receiving( &self, id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), SubstrateError> { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; let proof = self .client @@ -170,7 +171,7 @@ where generated_at_header: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, - ) -> Result, Self::Error> { + ) -> Result, SubstrateError> { let tx = self .lane .make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof) diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 7fa948b8c4731..1d9239ff37156 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -105,7 +105,6 @@ pub fn run( lane_id: LaneId, metrics_params: Option, ) { - let reconnect_delay = Duration::from_secs(10); let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_millau = millau_sign.signer.public().as_array_ref().clone().into(); @@ -135,7 +134,7 @@ pub fn run( lane: lane_id, source_tick: Millau::AVERAGE_BLOCK_INTERVAL, target_tick: Rialto::AVERAGE_BLOCK_INTERVAL, - reconnect_delay, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unrewarded_relayer_entries_at_target: bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index ef11f6cecf783..a336637e4daf2 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -105,7 +105,6 @@ pub fn run( lane_id: LaneId, metrics_params: Option, ) { - let reconnect_delay = Duration::from_secs(10); let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rialto = rialto_sign.signer.public().as_array_ref().clone().into(); @@ -134,7 +133,7 @@ pub fn run( lane: lane_id, source_tick: Rialto::AVERAGE_BLOCK_INTERVAL, target_tick: Millau::AVERAGE_BLOCK_INTERVAL, - reconnect_delay, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unrewarded_relayer_entries_at_target: bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 5320e91fd558b..01aa866ee43d1 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" async-std = "1.6.5" +async-trait = "0.1.40" backoff = "0.2" env_logger = "0.8.2" futures = "0.3.5" diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 2968320ff5c87..3ece57d0a3201 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -29,6 +29,7 @@ pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); pub mod initialize; pub mod metrics; +pub mod relay_loop; /// Block number traits shared by all chains that relay is able to serve. pub trait BlockNumberBase: diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 0667bdb922a00..f38d1bda3a5d8 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -16,6 +16,7 @@ pub use substrate_prometheus_endpoint::{register, Counter, CounterVec, Gauge, GaugeVec, Opts, Registry, F64, U64}; +use async_std::sync::{Arc, Mutex}; use std::net::SocketAddr; use substrate_prometheus_endpoint::init_prometheus; use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; @@ -36,9 +37,9 @@ pub trait Metrics { } /// Global Prometheus metrics. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct GlobalMetrics { - system: System, + system: Arc>, system_average_load: GaugeVec, process_cpu_usage_percentage: Gauge, process_memory_usage_bytes: Gauge, @@ -110,7 +111,7 @@ impl Metrics for GlobalMetrics { impl Default for GlobalMetrics { fn default() -> Self { GlobalMetrics { - system: System::new_with_specifics(RefreshKind::everything()), + system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) .expect("metric is static and thus valid; qed"), process_cpu_usage_percentage: Gauge::new("process_cpu_usage_percentage", "Process CPU usage") @@ -126,9 +127,10 @@ impl Default for GlobalMetrics { impl GlobalMetrics { /// Update metrics. - pub fn update(&mut self) { + pub async fn update(&self) { // update system-wide metrics - let load = self.system.get_load_average(); + let mut system = self.system.lock().await; + let load = system.get_load_average(); self.system_average_load.with_label_values(&["1min"]).set(load.one); self.system_average_load.with_label_values(&["5min"]).set(load.five); self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); @@ -139,8 +141,8 @@ impl GlobalMetrics { relay is not supposed to run in such MetricsParamss;\ qed", ); - let is_process_refreshed = self.system.refresh_process(pid); - match (is_process_refreshed, self.system.get_process(pid)) { + let is_process_refreshed = system.refresh_process(pid); + match (is_process_refreshed, system.get_process(pid)) { (true, Some(process_info)) => { let cpu_usage = process_info.cpu_usage() as f64; let memory_usage = process_info.memory() * 1024; diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs new file mode 100644 index 0000000000000..d750358edaa02 --- /dev/null +++ b/relays/utils/src/relay_loop.rs @@ -0,0 +1,95 @@ +// Copyright 2019-2020 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 . + +use crate::{FailedClient, MaybeConnectionError}; + +use async_trait::async_trait; +use std::{fmt::Debug, future::Future, time::Duration}; + +/// Default pause between reconnect attempts. +pub const RECONNECT_DELAY: Duration = Duration::from_secs(10); + +/// Basic blockchain client from relay perspective. +#[async_trait] +pub trait Client: Clone + Send + Sync { + /// Type of error this clients returns. + type Error: Debug + MaybeConnectionError; + + /// Try to reconnect to source node. + async fn reconnect(&mut self) -> Result<(), Self::Error>; +} + +/// Run relay loop. +/// +/// This function represents an outer loop, which in turn calls provided `loop_run` function to do +/// actual job. When `loop_run` returns, this outer loop reconnects to failed client (source, +/// target or both) and calls `loop_run` again. +pub fn run( + reconnect_delay: Duration, + mut source_client: SC, + mut target_client: TC, + loop_run: R, +) where + R: Fn(SC, TC) -> F, + F: Future>, +{ + let mut local_pool = futures::executor::LocalPool::new(); + + local_pool.run_until(async move { + loop { + let result = loop_run(source_client.clone(), target_client.clone()).await; + + match result { + Ok(()) => break, + Err(failed_client) => loop { + async_std::task::sleep(reconnect_delay).await; + if failed_client == FailedClient::Both || failed_client == FailedClient::Source { + match source_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to source client. Going to retry in {}s: {:?}", + reconnect_delay.as_secs(), + error, + ); + continue; + } + } + } + if failed_client == FailedClient::Both || failed_client == FailedClient::Target { + match target_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to target client. Going to retry in {}s: {:?}", + reconnect_delay.as_secs(), + error, + ); + continue; + } + } + } + + break; + }, + } + + log::debug!(target: "bridge", "Restarting relay loop"); + } + }); +} From 7fe8c70b398d23719f76b080b855160e2b4b16fe Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 27 Jan 2021 09:22:17 +0300 Subject: [PATCH 0312/1210] decode call after spec_version check (#663) --- bin/millau/runtime/src/lib.rs | 3 +- bin/millau/runtime/src/rialto_messages.rs | 3 + bin/rialto/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/millau_messages.rs | 3 + bin/runtime-common/src/messages.rs | 69 +++++-------- modules/call-dispatch/src/lib.rs | 119 +++++++++++++++------- relays/substrate/src/main.rs | 8 +- 7 files changed, 126 insertions(+), 82 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 90498c7cde803..d85be22b246d0 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -215,6 +215,7 @@ impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; + type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; type SourceChainAccountId = bp_rialto::AccountId; type TargetChainAccountPublic = MultiSigner; type TargetChainSignature = MultiSignature; @@ -602,7 +603,7 @@ impl_runtime_apis! { /// This way, the owner of `millau_account_id` on Millau proves that the Rialto account private key /// is also under his control. pub fn rialto_account_ownership_digest( - rialto_call: Call, + rialto_call: &Call, millau_account_id: AccountId, rialto_spec_version: SpecVersion, ) -> sp_std::vec::Vec diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 9f2144b5636d5..4ae8d09d64c3f 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -63,6 +63,9 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifie /// Message payload for Rialto -> Millau messages. pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +/// Encoded Millau Call as it comes from Rialto. +pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; + /// Messages proof for Rialto -> Millau messages. type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 313948e6a05be..35f16540d46d3 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -266,6 +266,7 @@ impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; + type EncodedCall = crate::millau_messages::FromMillauEncodedCall; type SourceChainAccountId = bp_millau::AccountId; type TargetChainAccountPublic = MultiSigner; type TargetChainSignature = MultiSignature; @@ -991,7 +992,7 @@ impl_runtime_apis! { /// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private key /// is also under his control. pub fn millau_account_ownership_digest( - millau_call: Call, + millau_call: &Call, rialto_account_id: AccountId, millau_spec_version: SpecVersion, ) -> sp_std::vec::Vec diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 61a8682d12754..222da01f1cd66 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -63,6 +63,9 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifie /// Message payload for Millau -> Rialto messages. pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +/// Encoded Rialto Call as it comes from Millau. +pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; + /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithMillauMessageBridge, diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 924aafd07054d..dfb1307580fab 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -27,7 +27,7 @@ use bp_message_lane::{ InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use bp_runtime::InstanceId; -use codec::{Compact, Decode, Encode, Input}; +use codec::{Compact, Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; @@ -319,11 +319,11 @@ pub mod target { >; /// Decoded Bridged -> This message payload. - pub type FromBridgedChainDecodedMessagePayload = pallet_bridge_call_dispatch::MessagePayload< + pub type FromBridgedChainMessagePayload = pallet_bridge_call_dispatch::MessagePayload< AccountIdOf>, SignerOf>, SignatureOf>, - CallOf>, + FromBridgedChainEncodedMessageCall, >; /// Messages proof from bridged chain: @@ -340,33 +340,21 @@ pub mod target { MessageNonce, ); - /// Message payload for Bridged -> This messages. - pub struct FromBridgedChainMessagePayload(pub(crate) FromBridgedChainDecodedMessagePayload); - - impl From> for FromBridgedChainMessagePayload { - fn from(decoded_payload: FromBridgedChainDecodedMessagePayload) -> Self { - Self(decoded_payload) - } + /// Encoded Call of This chain as it is transferred over bridge. + /// + /// Our Call is opaque (`Vec`) for Bridged chain. So it is encoded, prefixed with + /// vector length. Custom decode implementation here is exactly to deal with this. + #[derive(Decode, Encode, RuntimeDebug, PartialEq)] + pub struct FromBridgedChainEncodedMessageCall { + pub(crate) encoded_call: Vec, + pub(crate) _marker: PhantomData, } - impl Decode for FromBridgedChainMessagePayload { - fn decode(input: &mut I) -> Result { - // for bridged chain our Calls are opaque - they're encoded to Vec by submitter - // => skip encoded vec length here before decoding Call - let spec_version = pallet_bridge_call_dispatch::SpecVersion::decode(input)?; - let weight = frame_support::weights::Weight::decode(input)?; - let origin = FromBridgedChainMessageCallOrigin::::decode(input)?; - let _skipped_length = Compact::::decode(input)?; - let call = CallOf::>::decode(input)?; - - Ok(FromBridgedChainMessagePayload( - pallet_bridge_call_dispatch::MessagePayload { - spec_version, - weight, - origin, - call, - }, - )) + impl From> for Result>, ()> { + fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { + let mut input = &encoded_call.encoded_call[..]; + let _skipped_length = Compact::::decode(&mut input).map_err(drop)?; + CallOf::>::decode(&mut input).map_err(drop) } } @@ -385,22 +373,14 @@ pub mod target { >::Event: From>, pallet_bridge_call_dispatch::Module: - bp_message_dispatch::MessageDispatch< - (LaneId, MessageNonce), - Message = FromBridgedChainDecodedMessagePayload, - >, + bp_message_dispatch::MessageDispatch<(LaneId, MessageNonce), Message = FromBridgedChainMessagePayload>, { type DispatchPayload = FromBridgedChainMessagePayload; fn dispatch_weight( message: &DispatchMessage>>, ) -> frame_support::weights::Weight { - message - .data - .payload - .as_ref() - .map(|payload| payload.0.weight) - .unwrap_or(0) + message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0) } fn dispatch(message: DispatchMessage>>) { @@ -408,7 +388,7 @@ pub mod target { pallet_bridge_call_dispatch::Module::::dispatch( B::INSTANCE, message_id, - message.data.payload.map_err(drop).map(|payload| payload.0), + message.data.payload.map_err(drop), ); } } @@ -595,6 +575,7 @@ mod tests { const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain; + #[derive(Debug, PartialEq)] struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { @@ -635,6 +616,7 @@ mod tests { } /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from ThisChain; + #[derive(Debug, PartialEq)] struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { @@ -804,12 +786,15 @@ mod tests { target::FromBridgedChainMessagePayload::::decode(&mut &message_on_bridged_chain[..]) .unwrap(); assert_eq!( - message_on_this_chain.0, - target::FromBridgedChainDecodedMessagePayload:: { + message_on_this_chain, + target::FromBridgedChainMessagePayload:: { spec_version: 1, weight: 100, origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: ThisChainCall::Transfer, + call: target::FromBridgedChainEncodedMessageCall:: { + encoded_call: ThisChainCall::Transfer.encode(), + _marker: PhantomData::default(), + }, } ); } diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index d60492be34aea..b68ff3aa5e427 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -134,6 +134,16 @@ pub trait Config: frame_system::Config { Origin = ::Origin, PostInfo = frame_support::dispatch::PostDispatchInfo, >; + /// The type that is used to wrap the `Self::Call` when it is moved over bridge. + /// + /// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure + /// that all other stuff (like `spec_version`) is ok. If we would try to decode + /// `Call` which has been encoded using previous `spec_version`, then we might end + /// up with decoding error, instead of `MessageVersionSpecMismatch`. + /// + /// The `Encode` implementation should match `Encode` implementation of the actual + /// `Call`, that (may) have been used to produce signature for `CallOrigin::TargetAccount`. + type EncodedCall: Decode + Encode + Into>::Call, ()>>; /// A type which can be turned into an AccountId from a 256-bit hash. /// /// Used when deriving target chain AccountIds from source chain AccountIds. @@ -160,6 +170,8 @@ decl_event!( MessageSignatureMismatch(InstanceId, MessageId), /// Message has been dispatched with given result. MessageDispatched(InstanceId, MessageId, DispatchResult), + /// We have failed to decode Call from the message. + MessageCallDecodeFailed(InstanceId, MessageId), /// Phantom member, never used. Needed to handle multiple pallet instances. _Dummy(PhantomData), } @@ -174,12 +186,8 @@ decl_module! { } impl, I: Instance> MessageDispatch for Module { - type Message = MessagePayload< - T::SourceChainAccountId, - T::TargetChainAccountPublic, - T::TargetChainSignature, - >::Call, - >; + type Message = + MessagePayload; fn dispatch_weight(message: &Self::Message) -> Weight { message.weight @@ -216,28 +224,6 @@ impl, I: Instance> MessageDispatch for Module { return; } - // verify weight - // (we want passed weight to be at least equal to pre-dispatch weight of the call - // because otherwise Calls may be dispatched at lower price) - let dispatch_info = message.call.get_dispatch_info(); - let expected_weight = dispatch_info.weight; - if message.weight < expected_weight { - frame_support::debug::trace!( - "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", - bridge, - id, - expected_weight, - message.weight, - ); - Self::deposit_event(RawEvent::MessageWeightMismatch( - bridge, - id, - expected_weight, - message.weight, - )); - return; - } - // prepare dispatch origin let origin_account = match message.origin { CallOrigin::SourceRoot => { @@ -247,8 +233,7 @@ impl, I: Instance> MessageDispatch for Module { target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { - let digest = - account_ownership_digest(message.call.clone(), source_account_id, message.spec_version, bridge); + let digest = account_ownership_digest(&message.call, source_account_id, message.spec_version, bridge); let target_account = target_public.into_account(); if !target_signature.verify(&digest[..], &target_account) { @@ -274,11 +259,43 @@ impl, I: Instance> MessageDispatch for Module { } }; + // now that we have everything checked, let's decode the call + let call = match message.call.into() { + Ok(call) => call, + Err(_) => { + frame_support::debug::trace!("Failed to decode Call from message {:?}/{:?}", bridge, id,); + Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id)); + return; + } + }; + + // verify weight + // (we want passed weight to be at least equal to pre-dispatch weight of the call + // because otherwise Calls may be dispatched at lower price) + let dispatch_info = call.get_dispatch_info(); + let expected_weight = dispatch_info.weight; + if message.weight < expected_weight { + frame_support::debug::trace!( + "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", + bridge, + id, + expected_weight, + message.weight, + ); + Self::deposit_event(RawEvent::MessageWeightMismatch( + bridge, + id, + expected_weight, + message.weight, + )); + return; + } + // finally dispatch message let origin = RawOrigin::Signed(origin_account).into(); - frame_support::debug::trace!("Message being dispatched is: {:?}", &message.call); - let dispatch_result = message.call.dispatch(origin); + frame_support::debug::trace!("Message being dispatched is: {:?}", &call); + let dispatch_result = call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); frame_support::debug::trace!( @@ -339,7 +356,7 @@ where /// private key. This way, the owner of `source_account_id` on the source chain proves that /// the target chain account private key is also under his control. pub fn account_ownership_digest( - call: Call, + call: &Call, source_account_id: AccountId, target_spec_version: SpecVersion, source_instance_id: BridgeId, @@ -471,9 +488,19 @@ mod tests { type TargetChainAccountPublic = TestAccountPublic; type TargetChainSignature = TestSignature; type Call = Call; + type EncodedCall = EncodedCall; type AccountIdConverter = AccountIdConverter; } + #[derive(Decode, Encode)] + pub struct EncodedCall(Vec); + + impl From for Result { + fn from(call: EncodedCall) -> Result { + Call::decode(&mut &call.0[..]).map_err(drop) + } + } + const TEST_SPEC_VERSION: SpecVersion = 0; const TEST_WEIGHT: Weight = 1_000_000_000; @@ -492,7 +519,7 @@ mod tests { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, origin, - call, + call: EncodedCall(call.encode()), } } @@ -617,6 +644,30 @@ mod tests { }); } + #[test] + fn should_fail_on_call_decode() { + new_test_ext().execute_with(|| { + let bridge = b"ethb".to_owned(); + let id = [0; 4]; + + let mut message = + prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + message.call.0 = vec![]; + + System::set_block_number(1); + CallDispatch::dispatch(bridge, id, Ok(message)); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageCallDecodeFailed(bridge, id)), + topics: vec![], + }], + ); + }); + } + #[test] fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index c0f0ab2bcac92..e0d6149870994 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -298,7 +298,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { }, cli::Origins::Target => { let digest = millau_runtime::rialto_account_ownership_digest( - rialto_call.clone(), + &rialto_call, millau_account_id.clone(), rialto_runtime::VERSION.spec_version, ); @@ -449,7 +449,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { }, cli::Origins::Target => { let digest = rialto_runtime::millau_account_ownership_digest( - millau_call.clone(), + &millau_call, rialto_account_id.clone(), millau_runtime::VERSION.spec_version, ); @@ -539,7 +539,7 @@ mod tests { let millau_account_id: bp_millau::AccountId = millau_public.into_account(); let digest = millau_runtime::rialto_account_ownership_digest( - call, + &call, millau_account_id, rialto_runtime::VERSION.spec_version, ); @@ -560,7 +560,7 @@ mod tests { let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); let digest = rialto_runtime::millau_account_ownership_digest( - call, + &call, rialto_account_id, millau_runtime::VERSION.spec_version, ); From 6fc1087e92fff7b1fe3da4aa4b528eb67717e1fc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 27 Jan 2021 16:57:27 -0500 Subject: [PATCH 0313/1210] Add Unchecked Header Writes to Bridge Pallet (#672) * Add method for unchecked header imports * Update docs for importing unchecked headers * Import unchecked headers in HeaderChain implementation * Fix Clippy warnings * Move unchecked header import out of Verifier struct * Clean up unchecked import tests * Change HeaderChain API to accept iterator of headers * Use chains of headers in tests * Remove unused Result return type when appending finalized headers * Add test which shows that genesis changes are not enacted * Use initial header's hash for unchecked authority set changes * Appease Clippy * Check ancestry before making unchecked writes * Fix typo * Fix Clippy warning * Add note about `ancestry_proof` structure * Use best hash storage item directly Co-authored-by: Svyatoslav Nikolsky --- modules/finality-verifier/src/lib.rs | 35 ++-- modules/substrate/src/fork_tests.rs | 2 +- modules/substrate/src/lib.rs | 234 +++++++++++++++++++++++++-- modules/substrate/src/verifier.rs | 10 +- primitives/header-chain/src/lib.rs | 32 ++-- 5 files changed, 251 insertions(+), 62 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 170b03462ef7b..924a1c005460c 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -35,7 +35,7 @@ use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain}; use bp_runtime::{Chain, HeaderOf}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{ensure, traits::Get}; +use frame_support::{dispatch::DispatchError, ensure, traits::Get}; use frame_system::ensure_signed; use sp_runtime::traits::Header as HeaderT; @@ -57,7 +57,7 @@ pub mod pallet { type BridgedChain: Chain; /// The pallet which we will use as our underlying storage mechanism. - type HeaderChain: HeaderChain<::Header>; + type HeaderChain: HeaderChain<::Header, DispatchError>; /// The type through which we will verify that a given header is related to the last /// finalized header in our storage pallet. @@ -80,13 +80,16 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// Verify a header is finalized according to the given finality proof. + /// Verify a target header is finalized according to the given finality proof. /// /// Will use the underlying storage pallet to fetch information about the current /// authorities and best finalized header in order to verify that the header is finalized. /// - /// If successful in verification, it will write the headers to the underlying storage - /// pallet as well as import the valid finality proof. + /// If successful in verification, it will write the header as well as its ancestors (from + /// the given `ancestry_proof`) to the underlying storage pallet. + /// + /// Note that the expected format for `ancestry_proof` is a continguous list of finalized + /// headers containing (current_best_finalized_header, finality_target] #[pallet::weight(0)] pub fn submit_finality_proof( origin: OriginFor, @@ -119,22 +122,10 @@ pub mod pallet { >::InvalidAncestryProof ); - // If for whatever reason we are unable to fully import headers and the corresponding - // finality proof we want to avoid writing to the base pallet storage - use frame_support::storage::{with_transaction, TransactionOutcome}; - with_transaction(|| { - for header in ancestry_proof { - if T::HeaderChain::import_header(header).is_err() { - return TransactionOutcome::Rollback(Err(>::FailedToWriteHeader)); - } - } - - if T::HeaderChain::import_finality_proof(finality_target, justification).is_err() { - return TransactionOutcome::Rollback(Err(>::FailedToWriteFinalityProof)); - } - - TransactionOutcome::Commit(Ok(())) - })?; + // Note that this won't work if we ever change the `ancestry_proof` format to be + // sparse since this expects a contiguous set of finalized headers. + let _ = + T::HeaderChain::append_finalized_chain(ancestry_proof).map_err(|_| >::FailedToWriteHeader)?; Ok(().into()) } @@ -151,8 +142,6 @@ pub mod pallet { InvalidAuthoritySet, /// Failed to write a header to the underlying header chain. FailedToWriteHeader, - /// Failed to write finality proof to the underlying header chain. - FailedToWriteFinalityProof, /// The given ancestry proof is too large to be verified in a single transaction. OversizedAncestryProof, } diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index 810678852c465..445ffd8ce5008 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -503,7 +503,7 @@ where storage.update_current_authority_set(authority_set); } -fn change_log(delay: u64) -> Digest { +pub(crate) fn change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { next_authorities: vec![(alice(), 1), (bob(), 1)], delay, diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 2ecee8628e491..2a3ad1b0184fd 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -83,6 +83,8 @@ pub trait Config: frame_system::Config { decl_storage! { trait Store for Module as SubstrateBridge { + /// Hash of the header used to bootstrap the pallet. + InitialHash: BridgedBlockHash; /// The number of the highest block(s) we know of. BestHeight: BridgedBlockNumber; /// Hash of the header at the highest known height. @@ -151,6 +153,8 @@ decl_error! { Halted, /// The pallet has already been initialized. AlreadyInitialized, + /// The given header is not a descendant of a particular header. + NotDescendant, } } @@ -362,7 +366,7 @@ impl Module { } } -impl bp_header_chain::HeaderChain> for Module { +impl bp_header_chain::HeaderChain, sp_runtime::DispatchError> for Module { fn best_finalized() -> BridgedHeader { PalletStorage::::new().best_finalized_header().header } @@ -371,27 +375,92 @@ impl bp_header_chain::HeaderChain> for Module { PalletStorage::::new().current_authority_set() } - fn import_header(header: BridgedHeader) -> Result<(), ()> { - let mut verifier = verifier::Verifier { - storage: PalletStorage::::new(), - }; + fn append_finalized_chain( + headers: impl IntoIterator>, + ) -> Result<(), sp_runtime::DispatchError> { + let mut storage = PalletStorage::::new(); + + let mut header_iter = headers.into_iter().peekable(); + let first_header = header_iter.peek().ok_or(Error::::NotDescendant)?; + + // Quick ancestry check to make sure we're not writing complete nonsense to storage + ensure!( + >::get() == *first_header.parent_hash(), + Error::::NotDescendant, + ); - let _ = verifier.import_header(header.hash(), header).map_err(|_| ())?; + for header in header_iter { + import_header_unchecked::<_, T>(&mut storage, header); + } Ok(()) } +} - fn import_finality_proof(header: BridgedHeader, finality_proof: Vec) -> Result<(), ()> { - let mut verifier = verifier::Verifier { - storage: PalletStorage::::new(), - }; +/// Import a finalized header without checking if this is true. +/// +/// This function assumes that all the given header has already been proven to be valid and +/// finalized. Using this assumption it will write them to storage with minimal checks. That +/// means it's of great importance that this function *not* called with any headers whose +/// finality has not been checked, otherwise you risk bricking your bridge. +/// +/// One thing this function does do for you is GRANDPA authority set handoffs. However, since it +/// does not do verification on the incoming header it will assume that the authority set change +/// signals in the digest are well formed. +fn import_header_unchecked(storage: &mut S, header: BridgedHeader) +where + S: BridgeStorage

>, + T: Config, +{ + // Since we want to use the existing storage infrastructure we need to indicate the fork + // that we're on. We will assume that since we are using the unchecked import there are no + // forks, and can indicate that by using the first imported header's "fork". + let dummy_fork_hash = >::get(); + + // If we have a pending change in storage let's check if the current header enacts it. + let enact_change = if let Some(pending_change) = storage.scheduled_set_change(dummy_fork_hash) { + pending_change.height == *header.number() + } else { + // We don't have a scheduled change in storage at the moment. Let's check if the current + // header signals an authority set change. + if let Some(change) = verifier::find_scheduled_change(&header) { + let next_set = AuthoritySet { + authorities: change.next_authorities, + set_id: storage.current_authority_set().set_id + 1, + }; - let _ = verifier - .import_finality_proof(header.hash(), finality_proof.into()) - .map_err(|_| ())?; + let height = *header.number() + change.delay; + let scheduled_change = ScheduledChange { + authority_set: next_set, + height, + }; - Ok(()) + storage.schedule_next_set_change(dummy_fork_hash, scheduled_change); + + // If the delay is 0 this header will enact the change it signaled + height == *header.number() + } else { + false + } + }; + + if enact_change { + const ENACT_SET_PROOF: &str = "We only set `enact_change` as `true` if we are sure that there is a scheduled + authority set change in storage. Therefore, it must exist."; + + // If we are unable to enact an authority set it means our storage entry for scheduled + // changes is missing. Best to crash since this is likely a bug. + let _ = storage.enact_authority_set(dummy_fork_hash).expect(ENACT_SET_PROOF); } + + storage.update_best_finalized(header.hash()); + + storage.write_header(&ImportedHeader { + header, + requires_justification: false, + is_finalized: true, + signal_hash: None, + }); } /// Ensure that the origin is either root, or `ModuleOwner`. @@ -448,6 +517,7 @@ fn initialize_bridge(init_params: InitializationData >::insert(initial_hash, change); }; + >::put(initial_hash); >::put(header.number()); >::put(vec![initial_hash]); >::put(initial_hash); @@ -659,7 +729,8 @@ impl BridgeStorage for PalletStorage { mod tests { use super::*; use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestHeader, TestRuntime}; - use bp_test_utils::authority_list; + use bp_header_chain::HeaderChain; + use bp_test_utils::{alice, authority_list, bob}; use frame_support::{assert_noop, assert_ok}; use sp_runtime::DispatchError; @@ -845,4 +916,137 @@ mod tests { ); }); } + + #[test] + fn importing_unchecked_headers_works() { + run_test(|| { + init_with_origin(Origin::root()).unwrap(); + let storage = PalletStorage::::new(); + + let child = test_header(2); + let header = test_header(3); + + let header_chain = vec![child.clone(), header.clone()]; + assert_ok!(Module::::append_finalized_chain(header_chain)); + + assert!(storage.header_by_hash(child.hash()).unwrap().is_finalized); + assert!(storage.header_by_hash(header.hash()).unwrap().is_finalized); + + assert_eq!(storage.best_finalized_header().header, header); + assert_eq!(storage.best_headers()[0].hash, header.hash()); + }) + } + + #[test] + fn prevents_unchecked_header_import_if_headers_are_unrelated() { + run_test(|| { + init_with_origin(Origin::root()).unwrap(); + + // Pallet is expecting test_header(2) as the child + let not_a_child = test_header(3); + let header_chain = vec![not_a_child]; + + assert_noop!( + Module::::append_finalized_chain(header_chain), + Error::::NotDescendant, + ); + }) + } + + #[test] + fn importing_unchecked_headers_enacts_new_authority_set() { + run_test(|| { + init_with_origin(Origin::root()).unwrap(); + let storage = PalletStorage::::new(); + + let next_set_id = 2; + let next_authorities = vec![(alice(), 1), (bob(), 1)]; + + // Need to update the header digest to indicate that our header signals an authority set + // change. The change will be enacted when we import our header. + let mut header = test_header(2); + header.digest = fork_tests::change_log(0); + + // Let's import our test header + assert_ok!(Module::::append_finalized_chain(vec![header.clone()])); + + // Make sure that our header is the best finalized + assert_eq!(storage.best_finalized_header().header, header); + assert_eq!(storage.best_headers()[0].hash, header.hash()); + + // Make sure that the authority set actually changed upon importing our header + assert_eq!( + storage.current_authority_set(), + AuthoritySet::new(next_authorities, next_set_id), + ); + }) + } + + #[test] + fn importing_unchecked_headers_enacts_new_authority_set_from_old_header() { + run_test(|| { + init_with_origin(Origin::root()).unwrap(); + let storage = PalletStorage::::new(); + + let next_set_id = 2; + let next_authorities = vec![(alice(), 1), (bob(), 1)]; + + // Need to update the header digest to indicate that our header signals an authority set + // change. However, the change doesn't happen until the next block. + let mut schedules_change = test_header(2); + schedules_change.digest = fork_tests::change_log(1); + let header = test_header(3); + + // Let's import our test headers + let header_chain = vec![schedules_change, header.clone()]; + assert_ok!(Module::::append_finalized_chain(header_chain)); + + // Make sure that our header is the best finalized + assert_eq!(storage.best_finalized_header().header, header); + assert_eq!(storage.best_headers()[0].hash, header.hash()); + + // Make sure that the authority set actually changed upon importing our header + assert_eq!( + storage.current_authority_set(), + AuthoritySet::new(next_authorities, next_set_id), + ); + }) + } + + #[test] + fn importing_unchecked_header_can_enact_set_change_scheduled_at_genesis() { + run_test(|| { + let storage = PalletStorage::::new(); + + let next_authorities = vec![(alice(), 1)]; + let next_set_id = 2; + let next_authority_set = AuthoritySet::new(next_authorities.clone(), next_set_id); + + let first_scheduled_change = ScheduledChange { + authority_set: next_authority_set, + height: 2, + }; + + let init_data = InitializationData { + header: test_header(1), + authority_list: authority_list(), + set_id: 1, + scheduled_change: Some(first_scheduled_change), + is_halted: false, + }; + + assert_ok!(Module::::initialize(Origin::root(), init_data)); + + // We are expecting an authority set change at height 2, so this header should enact + // that upon being imported. + let header_chain = vec![test_header(2)]; + assert_ok!(Module::::append_finalized_chain(header_chain)); + + // Make sure that the authority set actually changed upon importing our header + assert_eq!( + storage.current_authority_set(), + AuthoritySet::new(next_authorities, next_set_id), + ); + }) + } } diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index b22d69f78db87..0c3bd1b5ddd49 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -242,9 +242,13 @@ where &proof.0, ) .map_err(|_| FinalizationError::InvalidJustification)?; - frame_support::debug::trace!(target: "sub-bridge", "Received valid justification for {:?}", header); + frame_support::debug::trace!("Received valid justification for {:?}", header); - frame_support::debug::trace!(target: "sub-bridge", "Checking ancestry for headers between {:?} and {:?}", last_finalized, header); + frame_support::debug::trace!( + "Checking ancestry for headers between {:?} and {:?}", + last_finalized, + header + ); let mut finalized_headers = if let Some(ancestors) = headers_between(&self.storage, last_finalized, header.clone()) { // Since we only try and finalize headers with a height strictly greater @@ -335,7 +339,7 @@ where Some(ancestors) } -fn find_scheduled_change(header: &H) -> Option> { +pub(crate) fn find_scheduled_change(header: &H) -> Option> { let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); let filter_log = |log: ConsensusLog| match log { diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 699e79cae59ea..b65325b850eb4 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -28,7 +28,6 @@ use core::fmt::Debug; use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, SetId}; use sp_runtime::RuntimeDebug; -use sp_std::prelude::Vec; pub mod justification; @@ -69,25 +68,24 @@ pub trait InclusionProofVerifier { } /// A base trait for pallets which want to keep track of a full set of headers from a bridged chain. -pub trait HeaderChain { +pub trait HeaderChain { /// Get the best finalized header known to the header chain. fn best_finalized() -> H; /// Get the best authority set known to the header chain. fn authority_set() -> AuthoritySet; - /// Write the given header to the underlying pallet storage. - #[allow(clippy::result_unit_err)] - fn import_header(header: H) -> Result<(), ()>; - - /// Submit a valid finality proof for the given header to the underlying pallet storage. + /// Write a finalized chain of headers to the underlying pallet storage. + /// + /// It is assumed that each header in this chain been finalized, and that the given headers are + /// in order (e.g vec![header_1, header_2, ..., header_n]). /// - /// This will finalize the given header and enact any authority set changes if required. - #[allow(clippy::result_unit_err)] - fn import_finality_proof(header: H, finality_proof: Vec) -> Result<(), ()>; + /// This function should fail if the first header is not a child of the current best finalized + /// header known to the underlying pallet storage. + fn append_finalized_chain(headers: impl IntoIterator) -> Result<(), E>; } -impl HeaderChain for () { +impl HeaderChain for () { fn best_finalized() -> H { H::default() } @@ -96,20 +94,14 @@ impl HeaderChain for () { AuthoritySet::default() } - #[allow(clippy::result_unit_err)] - fn import_header(_header: H) -> Result<(), ()> { - Ok(()) - } - - #[allow(clippy::result_unit_err)] - fn import_finality_proof(_header: H, _finality_proof: Vec) -> Result<(), ()> { + fn append_finalized_chain(_headers: impl IntoIterator) -> Result<(), E> { Ok(()) } } -/// A trait for checking if a given child header is a direct decendant of an ancestor. +/// A trait for checking if a given child header is a direct descendant of an ancestor. pub trait AncestryChecker { - /// Is the child header a decendant of the ancestor header? + /// Is the child header a descendant of the ancestor header? fn are_ancestors(ancestor: &H, child: &H, proof: &P) -> bool; } From 1f93ced01788359dc3807ef0260835f9b9ee2efc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 29 Jan 2021 12:05:01 -0500 Subject: [PATCH 0314/1210] Make Account Derivation More Unique (#686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use more unique prefix when generating account IDs * Update derived addresses used in tests * Make `account` prefix more unique Co-authored-by: Tomasz Drwięga * Update test account IDs again Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 2 +- primitives/runtime/src/lib.rs | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index bf1dce3ae5594..8e9aded9f11d3 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -185,6 +185,6 @@ fn derived_dave_account_is_as_expected() { let derived: AccountId = derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); assert_eq!( derived.to_string(), - "5G81vRqUUysQGtN5aEThD5UsLdt4rZWSbVLkjuZzLHadp8ZD".to_string() + "5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string() ); } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index cf90802239569..00a73cd4457ed 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -203,6 +203,6 @@ fn derived_dave_account_is_as_expected() { let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); assert_eq!( derived.to_string(), - "5Hg7WQyk8C1FmPzxY3xSjR7S6zZZC5sAL35vMr6NpW17jBhQ".to_string() + "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string() ); } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index b0a352b7dd2cc..b9d73d2b9c100 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -47,6 +47,12 @@ pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; /// Message-lane module prefix. pub const MESSAGE_LANE_MODULE_PREFIX: &[u8] = b"pallet-bridge/message-lane"; +/// 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. message-lane pallet may be deployed twice in the same /// runtime to bridge ThisChain with Chain1 and Chain2. Sometimes we need to be able @@ -80,8 +86,8 @@ where AccountId: Encode, { match id { - SourceAccount::Root => ("root", bridge_id).using_encoded(blake2_256), - SourceAccount::Account(id) => ("account", 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() } From 07f1032f50cdd71f79750c04fadb691854d15c4c Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 29 Jan 2021 16:24:11 -0500 Subject: [PATCH 0315/1210] Bump Substrate Dependency (#684) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump Substrate to commit `0b0d124d5` * Get Millau node compiling * Get Rialto node compiling * Increase account reference count before test * Fix Clippy warnings for Millau node * Fix Clippy warnings for Rialto node * Trigger build. Co-authored-by: Tomasz Drwięga --- README.md | 1 + bin/millau/node/Cargo.toml | 2 + bin/millau/node/src/command.rs | 1 + bin/millau/node/src/service.rs | 58 +++++++++++++++++------ bin/rialto/node/Cargo.toml | 2 + bin/rialto/node/src/command.rs | 14 +++--- bin/rialto/node/src/service.rs | 59 ++++++++++++++++++------ modules/shift-session-manager/src/lib.rs | 31 ++++++++----- 8 files changed, 120 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 27e1192f9815b..915fa46dd5368 100644 --- a/README.md +++ b/README.md @@ -203,3 +203,4 @@ Element channel. The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element channel is most suited for discussions regarding Substrate itself. + diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 83ff05f7049cf..f1e59a45243a2 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -34,9 +34,11 @@ sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branc sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-telemetry = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 1b387d02dda71..ef506e5cdc725 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -157,6 +157,7 @@ pub fn run() -> sc_cli::Result<()> { Role::Light => service::new_light(config), _ => service::new_full(config), } + .map_err(sc_cli::Error::Service) }) } } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index d5dc945cad24a..aef79d9170b49 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -33,7 +33,9 @@ use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_finality_grandpa::SharedVoterState; +use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sc_telemetry::TelemetrySpan; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -69,13 +71,17 @@ pub fn new_partial( AuraPair, >, sc_finality_grandpa::LinkHalf, + Option, ), >, ServiceError, > { + if config.keystore_remote.is_some() { + return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); + } let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore_container, task_manager) = + let (client, backend, keystore_container, task_manager, telemetry_span) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -114,10 +120,17 @@ pub fn new_partial( select_chain, transaction_pool, inherent_data_providers, - other: (aura_block_import, grandpa_link), + other: (aura_block_import, grandpa_link, telemetry_span), }) } +fn remote_keystore(_url: &str) -> Result, &'static str> { + // FIXME: here would the concrete keystore be built, + // must return a concrete type (NOT `LocalKeystore`) that + // implements `CryptoStore` and `SyncCryptoStore` + Err("Remote Keystore not supported.") +} + /// Builds a new service for a full client. pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { @@ -125,13 +138,25 @@ pub fn new_full(mut config: Configuration) -> Result backend, mut task_manager, import_queue, - keystore_container, + mut keystore_container, select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link), + other: (block_import, grandpa_link, telemetry_span), } = new_partial(&config)?; + if let Some(url) = &config.keystore_remote { + match remote_keystore(url) { + Ok(k) => keystore_container.set_remote_keystore(k), + Err(e) => { + return Err(ServiceError::Other(format!( + "Error hooking up remote keystore for {}: {}", + url, e + ))) + } + }; + } + config .network .extra_sets @@ -164,7 +189,6 @@ pub fn new_full(mut config: Configuration) -> Result let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); - let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { use bp_message_lane::{LaneId, MessageNonce}; @@ -211,11 +235,12 @@ pub fn new_full(mut config: Configuration) -> Result let justification_stream = grandpa_link.justification_stream(); let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); - Box::new(move |_, subscription_executor| { - let shared_voter_state = SharedVoterState::empty(); + let finality_proof_provider = + GrandpaFinalityProofProvider::new_for_service(backend.clone(), Some(shared_authority_set.clone())); + Box::new(move |_, subscription_executor| { let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( client.clone(), @@ -224,7 +249,7 @@ pub fn new_full(mut config: Configuration) -> Result ))); io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( shared_authority_set.clone(), - shared_voter_state, + shared_voter_state.clone(), justification_stream.clone(), subscription_executor, finality_proof_provider.clone(), @@ -238,13 +263,12 @@ pub fn new_full(mut config: Configuration) -> Result }) }; - sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), - telemetry_connection_sinks: telemetry_connection_sinks.clone(), rpc_extensions_builder, on_demand: None, remote_blockchain: None, @@ -252,6 +276,7 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, + telemetry_span, })?; if role.is_authority() { @@ -312,7 +337,7 @@ pub fn new_full(mut config: Configuration) -> Result config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), + telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), @@ -331,7 +356,7 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand, telemetry_span) = sc_service::new_light_parts::(&config)?; config @@ -352,9 +377,12 @@ pub fn new_light(mut config: Configuration) -> Result let (grandpa_block_import, _) = sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; + let aura_block_import = + sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import.clone(), + aura_block_import, Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), @@ -390,7 +418,6 @@ pub fn new_light(mut config: Configuration) -> Result task_manager: &mut task_manager, on_demand: Some(on_demand), rpc_extensions_builder: Box::new(|_, _| ()), - telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), config, client, keystore: keystore_container.sync_keystore(), @@ -398,6 +425,7 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, + telemetry_span, })?; network_starter.start_network(); diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index aade85879c551..072667694a196 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -34,9 +34,11 @@ sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branc sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-telemetry = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 0ba8c87238b1f..72404d64226e2 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -152,12 +152,14 @@ pub fn run() -> sc_cli::Result<()> { } None => { let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } - }) + runner + .run_node_until_exit(|config| async move { + match config.role { + Role::Light => service::new_light(config), + _ => service::new_full(config), + } + }) + .map_err(sc_cli::Error::Service) } } } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index d88f37ac0a80d..f54e43b16dad2 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -33,7 +33,9 @@ use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_finality_grandpa::SharedVoterState; +use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sc_telemetry::TelemetrySpan; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -69,13 +71,17 @@ pub fn new_partial( AuraPair, >, sc_finality_grandpa::LinkHalf, + Option, ), >, ServiceError, > { + if config.keystore_remote.is_some() { + return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); + } let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore_container, task_manager) = + let (client, backend, keystore_container, task_manager, telemetry_span) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -114,10 +120,17 @@ pub fn new_partial( select_chain, transaction_pool, inherent_data_providers, - other: (aura_block_import, grandpa_link), + other: (aura_block_import, grandpa_link, telemetry_span), }) } +fn remote_keystore(_url: &str) -> Result, &'static str> { + // FIXME: here would the concrete keystore be built, + // must return a concrete type (NOT `LocalKeystore`) that + // implements `CryptoStore` and `SyncCryptoStore` + Err("Remote Keystore not supported.") +} + /// Builds a new service for a full client. pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { @@ -125,13 +138,25 @@ pub fn new_full(mut config: Configuration) -> Result backend, mut task_manager, import_queue, - keystore_container, + mut keystore_container, select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link), + other: (block_import, grandpa_link, telemetry_span), } = new_partial(&config)?; + if let Some(url) = &config.keystore_remote { + match remote_keystore(url) { + Ok(k) => keystore_container.set_remote_keystore(k), + Err(e) => { + return Err(ServiceError::Other(format!( + "Error hooking up remote keystore for {}: {}", + url, e + ))) + } + }; + } + config .network .extra_sets @@ -164,7 +189,6 @@ pub fn new_full(mut config: Configuration) -> Result let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); - let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default(); let rpc_extensions_builder = { use bp_message_lane::{LaneId, MessageNonce}; @@ -204,17 +228,19 @@ pub fn new_full(mut config: Configuration) -> Result use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; + let backend = backend.clone(); let client = client.clone(); let pool = transaction_pool.clone(); let justification_stream = grandpa_link.justification_stream(); let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone()); + let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); - Box::new(move |_, subscription_executor| { - let shared_voter_state = SharedVoterState::empty(); + let finality_proof_provider = + GrandpaFinalityProofProvider::new_for_service(backend.clone(), Some(shared_authority_set.clone())); + Box::new(move |_, subscription_executor| { let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( client.clone(), @@ -223,7 +249,7 @@ pub fn new_full(mut config: Configuration) -> Result ))); io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( shared_authority_set.clone(), - shared_voter_state, + shared_voter_state.clone(), justification_stream.clone(), subscription_executor, finality_proof_provider.clone(), @@ -237,13 +263,12 @@ pub fn new_full(mut config: Configuration) -> Result }) }; - sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), - telemetry_connection_sinks: telemetry_connection_sinks.clone(), rpc_extensions_builder, on_demand: None, remote_blockchain: None, @@ -251,6 +276,7 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, + telemetry_span, })?; if role.is_authority() { @@ -311,7 +337,7 @@ pub fn new_full(mut config: Configuration) -> Result config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()), + telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), @@ -330,7 +356,7 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand) = + let (client, backend, keystore_container, mut task_manager, on_demand, telemetry_span) = sc_service::new_light_parts::(&config)?; config @@ -351,9 +377,12 @@ pub fn new_light(mut config: Configuration) -> Result let (grandpa_block_import, _) = sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; + let aura_block_import = + sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); + let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( sc_consensus_aura::slot_duration(&*client)?, - grandpa_block_import.clone(), + aura_block_import, Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), @@ -389,7 +418,6 @@ pub fn new_light(mut config: Configuration) -> Result task_manager: &mut task_manager, on_demand: Some(on_demand), rpc_extensions_builder: Box::new(|_, _| ()), - telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(), config, client, keystore: keystore_container.sync_keystore(), @@ -397,6 +425,7 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, + telemetry_span, })?; network_starter.start_network(); diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 102c3fcbc1679..0d16e0b7d1f42 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -93,7 +93,7 @@ mod tests { traits::{BlakeTwo256, ConvertInto, IdentityLookup}, Perbill, RuntimeAppPublic, }; - use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; + use frame_support::{impl_outer_origin, parameter_types, weights::Weight, BasicExternalities}; use sp_core::H256; type AccountId = u64; @@ -172,17 +172,24 @@ mod tests { let mut t = frame_system::GenesisConfig::default() .build_storage::() .unwrap(); - pallet_session::GenesisConfig:: { - keys: vec![ - (1, 1, UintAuthorityId(1)), - (2, 2, UintAuthorityId(2)), - (3, 3, UintAuthorityId(3)), - (4, 4, UintAuthorityId(4)), - (5, 5, UintAuthorityId(5)), - ], - } - .assimilate_storage(&mut t) - .unwrap(); + + let keys = vec![ + (1, 1, UintAuthorityId(1)), + (2, 2, UintAuthorityId(2)), + (3, 3, UintAuthorityId(3)), + (4, 4, UintAuthorityId(4)), + (5, 5, UintAuthorityId(5)), + ]; + + BasicExternalities::execute_with_storage(&mut t, || { + for (ref k, ..) in &keys { + frame_system::Module::::inc_providers(k); + } + }); + + pallet_session::GenesisConfig:: { keys } + .assimilate_storage(&mut t) + .unwrap(); TestExternalities::new(t) } From f0445b1012c3b394900d6f78e8fdd325740ecdff Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Sat, 30 Jan 2021 00:25:33 +0300 Subject: [PATCH 0316/1210] Add proof-size related benchmarks to message lane module (#675) * fix benchmakrs + proof-size related benchmarks * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/rialto/runtime/src/lib.rs | 4 +- .../src/messages_benchmarking.rs | 48 ++++++- modules/message-lane/src/benchmarking.rs | 130 +++++++++++++++--- modules/message-lane/src/lib.rs | 4 +- modules/message-lane/src/weights.rs | 106 ++++++++------ 5 files changed, 220 insertions(+), 72 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 35f16540d46d3..d45164f6ad98e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -847,7 +847,7 @@ impl_runtime_apis! { fn endow_account(account: &Self::AccountId) { pallet_balances::Module::::make_free_balance_be( account, - 1_000_000_000_000, + Balance::MAX / 100, ); } @@ -865,7 +865,7 @@ impl_runtime_apis! { origin: dispatch_origin, call: message_payload, }; - (message, 1_000_000_000) + (message, pallet_message_lane::benchmarking::MESSAGE_FEE.into()) } fn prepare_message_proof( diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 70cbb76f433ee..fdae3a7fcc92e 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -28,11 +28,13 @@ use bp_message_lane::{LaneId, MessageData, MessageKey, MessagePayload}; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; use frame_support::weights::Weight; -use pallet_message_lane::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; +use pallet_message_lane::benchmarking::{MessageDeliveryProofParams, MessageProofParams, ProofSize}; use sp_core::Hasher; use sp_runtime::traits::Header; use sp_std::prelude::*; -use sp_trie::{read_trie_value_with, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, StorageProof, TrieMut}; +use sp_trie::{ + read_trie_value_with, record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, StorageProof, TrieMut, +}; /// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. /// @@ -117,14 +119,13 @@ where storage_keys.push(storage_key); } } + root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain let mut proof_recorder = Recorder::::new(); - for storage_key in storage_keys { - read_trie_value_with::, _, _>(&mdb, &root, &storage_key, &mut proof_recorder) - .map_err(|_| "read_trie_value_with has failed") - .expect("read_trie_value_with should not fail in benchmarks"); - } + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); // prepare Bridged chain header and insert it into the Substrate pallet @@ -189,3 +190,36 @@ where params.lane, ) } + +/// Populate trie with dummy keys+values until trie has (approximately) at least given size. +fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: ProofSize) -> H::Out { + let (iterations, leaf_size, minimal_trie_size) = match trie_size { + ProofSize::Minimal => return root, + ProofSize::HasLargeLeaf(size) => (1, size, size), + ProofSize::HasExtraNodes(size) => (8, 1, size), + }; + + let mut key_index = 0; + loop { + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); + let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); + if size > minimal_trie_size as _ { + return root; + } + + let mut trie = TrieDBMut::::from_existing(mdb, &mut root) + .map_err(|_| "TrieDBMut::from_existing has failed") + .expect("TrieDBMut::from_existing should not fail in benchmarks"); + for _ in 0..iterations { + trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + key_index += 1; + } + trie.commit(); + } +} diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index c9a27a4d9e2f2..0ad445385f2db 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -28,13 +28,25 @@ use frame_system::RawOrigin; use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, ops::RangeInclusive, prelude::*}; /// Fee paid by submitter for single message delivery. -const MESSAGE_FEE: u32 = 1_000_000; +pub const MESSAGE_FEE: u64 = 10_000_000_000; const SEED: u32 = 0; /// Module we're benchmarking here. pub struct Module, I: crate::Instance>(crate::Module); +/// Proof size requirements. +pub enum ProofSize { + /// The proof is expected to be minimal. + Minimal, + /// The proof is expected to have at least given size and grow by increasing number of trie nodes + /// included in the proof. + HasExtraNodes(u32), + /// The proof is expected to have at least given size and grow by increasing value that is stored + /// in the trie. + HasLargeLeaf(u32), +} + /// Benchmark-specific message parameters. pub struct MessageParams { /// Size of the message payload. @@ -51,6 +63,8 @@ pub struct MessageProofParams { pub message_nonces: RangeInclusive, /// If `Some`, the proof needs to include this outbound lane data. pub outbound_lane_data: Option, + /// Proof size requirements. + pub size: ProofSize, } /// Benchmark-specific message delivery proof parameters. @@ -214,6 +228,7 @@ benchmarks_instance! { lane: bench_lane_id(), message_nonces: 1..=1, outbound_lane_data: None, + size: ProofSize::Minimal, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -241,6 +256,7 @@ benchmarks_instance! { lane: bench_lane_id(), message_nonces: 1..=2, outbound_lane_data: None, + size: ProofSize::Minimal, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { @@ -275,6 +291,7 @@ benchmarks_instance! { latest_received_nonce: 20, latest_generated_nonce: 21, }), + size: ProofSize::Minimal, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -353,10 +370,7 @@ benchmarks_instance! { }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { - assert_eq!( - T::account_balance(&relayer_id), - relayer_balance + (MESSAGE_FEE * 2).into(), - ); + ensure_relayer_rewarded::(&relayer_id, &relayer_balance); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -395,14 +409,8 @@ benchmarks_instance! { }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) verify { - assert_eq!( - T::account_balance(&relayer1_id), - relayer1_balance + MESSAGE_FEE.into(), - ); - assert_eq!( - T::account_balance(&relayer2_id), - relayer2_balance + MESSAGE_FEE.into(), - ); + ensure_relayer_rewarded::(&relayer1_id, &relayer1_balance); + ensure_relayer_rewarded::(&relayer2_id, &relayer2_balance); } // @@ -461,6 +469,7 @@ benchmarks_instance! { lane: bench_lane_id(), message_nonces: 1..=i as _, outbound_lane_data: None, + size: ProofSize::Minimal, }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -503,6 +512,7 @@ benchmarks_instance! { latest_received_nonce: 20, latest_generated_nonce: 21, }), + size: ProofSize::Minimal, }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -522,6 +532,80 @@ benchmarks_instance! { ); } + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // Results of this benchmark may be used to check how extra nodes in proof affect transaction performance. + receive_message_proofs_with_extra_nodes { + let i in 0..T::maximal_message_size(); + + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + let messages_count = 1u32; + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + size: ProofSize::HasExtraNodes(i as _), + }); + }: receive_messages_proof( + RawOrigin::Signed(relayer_id_on_target), + relayer_id_on_source, + proof, + messages_count, + dispatch_weight + ) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 21, + ); + } + + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // Results of this benchmark may be used to check how large (extra) leaf in proof affect transaction performance. + receive_message_proofs_with_large_leaf { + let i in 0..T::maximal_message_size(); + + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + let messages_count = 1u32; + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + size: ProofSize::HasLargeLeaf(i as _), + }); + }: receive_messages_proof( + RawOrigin::Signed(relayer_id_on_target), + relayer_id_on_source, + proof, + messages_count, + dispatch_weight + ) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 21, + ); + } + // Benchmark `receive_messages_delivery_proof` extrinsic where single relayer delivers multiple messages. receive_delivery_proof_for_multiple_messages_by_single_relayer { // there actually should be used value of `MaxUnrewardedRelayerEntriesAtInboundLane` from the bridged @@ -554,10 +638,7 @@ benchmarks_instance! { }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { - assert_eq!( - T::account_balance(&relayer_id), - relayer_balance + (MESSAGE_FEE * i).into(), - ); + ensure_relayer_rewarded::(&relayer_id, &relayer_balance); } // Benchmark `receive_messages_delivery_proof` extrinsic where every relayer delivers single messages. @@ -603,10 +684,7 @@ benchmarks_instance! { }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) verify { for (relayer_id, prev_balance) in relayers { - assert_eq!( - T::account_balance(&relayer_id), - prev_balance + MESSAGE_FEE.into(), - ); + ensure_relayer_rewarded::(&relayer_id, &prev_balance); } } } @@ -635,3 +713,13 @@ fn receive_messages, I: Instance>(nonce: MessageNonce) { last_confirmed_nonce: 0, }); } + +fn ensure_relayer_rewarded, I: Instance>(relayer_id: &T::AccountId, old_balance: &T::OutboundMessageFee) { + let new_balance = T::account_balance(relayer_id); + assert!( + new_balance > *old_balance, + "Relayer haven't received reward for relaying message: old balance = {:?}, new balance = {:?}", + old_balance, + new_balance, + ); +} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 9c44e7289bfd5..eccebc1fcc9de 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -57,7 +57,7 @@ use frame_support::{ use frame_system::{ensure_signed, RawOrigin}; use num_traits::{SaturatingAdd, Zero}; use sp_runtime::{traits::BadOrigin, DispatchResult}; -use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; +use sp_std::{cell::RefCell, cmp::PartialOrd, marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; @@ -110,7 +110,7 @@ pub trait Config: frame_system::Config { /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter + Size; /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Default + From + Parameter + SaturatingAdd + Zero; + type OutboundMessageFee: Default + From + PartialOrd + Parameter + SaturatingAdd + Zero; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; diff --git a/modules/message-lane/src/weights.rs b/modules/message-lane/src/weights.rs index 016af708a66b5..33a84ecbafa9c 100644 --- a/modules/message-lane/src/weights.rs +++ b/modules/message-lane/src/weights.rs @@ -16,8 +16,8 @@ //! Autogenerated weights for pallet_message_lane //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0 -//! DATE: 2020-12-28, STEPS: [50, ], REPEAT: 20 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1 +//! DATE: 2021-01-25, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("local"), DB CACHE: 128 @@ -60,6 +60,8 @@ pub trait WeightInfo { fn send_messages_of_various_lengths(i: u32) -> Weight; fn receive_multiple_messages_proof(i: u32) -> Weight; fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; + fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight; + fn receive_message_proofs_with_large_leaf(i: u32) -> Weight; fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight; fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } @@ -68,81 +70,93 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (249_486_000 as Weight) + (123_511_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (257_454_000 as Weight) + (132_218_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (344_817_000 as Weight) + (187_458_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_single_message_proof() -> Weight { - (197_341_000 as Weight) + (156_005_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (341_056_000 as Weight) + (266_292_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (227_735_000 as Weight) + (171_319_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (208_305_000 as Weight) + (127_537_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (239_511_000 as Weight) + (135_281_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (341_307_000 as Weight) + (180_862_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (206_352_000 as Weight) - .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) + (98_452_000 as Weight) + .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((157_613_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((124_098_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((166_416_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((128_267_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { + (437_756_000 as Weight) + .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { + (164_484_000 as Weight) + .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (107_561_000 as Weight) - .saturating_add((12_218_000 as Weight).saturating_mul(i as Weight)) + (122_609_000 as Weight) + .saturating_add((7_289_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (124_619_000 as Weight) - .saturating_add((104_750_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (129_622_000 as Weight) + .saturating_add((53_214_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } @@ -150,81 +164,93 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (249_486_000 as Weight) + (123_511_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (257_454_000 as Weight) + (132_218_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (344_817_000 as Weight) + (187_458_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_single_message_proof() -> Weight { - (197_341_000 as Weight) + (156_005_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (341_056_000 as Weight) + (266_292_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (227_735_000 as Weight) + (171_319_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (208_305_000 as Weight) + (127_537_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (239_511_000 as Weight) + (135_281_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (341_307_000 as Weight) + (180_862_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (206_352_000 as Weight) - .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) + (98_452_000 as Weight) + .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((157_613_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((124_098_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((166_416_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((128_267_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { + (437_756_000 as Weight) + .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { + (164_484_000 as Weight) + .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (107_561_000 as Weight) - .saturating_add((12_218_000 as Weight).saturating_mul(i as Weight)) + (122_609_000 as Weight) + .saturating_add((7_289_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (124_619_000 as Weight) - .saturating_add((104_750_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (129_622_000 as Weight) + .saturating_add((53_214_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) } } From 01c31f0bbf3f7824959fb55564827e3caec8e970 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Feb 2021 02:53:30 +0000 Subject: [PATCH 0317/1210] Bump log from 0.4.13 to 0.4.14 (#692) --- modules/ethereum-contract/builtin/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 76f252401d826..d9bff725dcb8c 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "1.3.4" } ethereum-types = "0.10.0" finality-grandpa = "0.12.3" hex = "0.4" -log = "0.4.13" +log = "0.4.14" # Runtime/chain specific dependencies diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 3a2010aa6c513..bf30bb47d6289 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -19,7 +19,7 @@ futures = "0.3.12" hex = "0.4" hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } -log = "0.4.13" +log = "0.4.14" num-traits = "0.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.61" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 011b8b3be69bd..e1e4e2ec9a9c4 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -11,7 +11,7 @@ async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "1.3.4" } futures = "0.3.12" hex = "0.4" -log = "0.4.13" +log = "0.4.14" num-traits = "0.2" paste = "1.0" structopt = "0.3" From e62820811806d2a2f9911482228a891f5d17ff50 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Feb 2021 03:00:39 +0000 Subject: [PATCH 0318/1210] Bump ethereum-types from 0.10.0 to 0.11.0 (#693) --- modules/ethereum-contract/builtin/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index d9bff725dcb8c..1deb6a6c595a5 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.4" } -ethereum-types = "0.10.0" +ethereum-types = "0.11.0" finality-grandpa = "0.12.3" hex = "0.4" log = "0.4.14" From 6703ecf4043285427688bc25b4f65ae003c9e01f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 Feb 2021 23:53:33 +0300 Subject: [PATCH 0319/1210] Pre-dispatch call filter (#687) * pre-dispatch call filter * swap filter <-> weight * clippy * fmt --- bin/millau/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + modules/call-dispatch/src/lib.rs | 55 +++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d85be22b246d0..3164c8a9d831f 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -215,6 +215,7 @@ impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; + type CallFilter = (); type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; type SourceChainAccountId = bp_rialto::AccountId; type TargetChainAccountPublic = MultiSigner; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index d45164f6ad98e..677ca283c480a 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -266,6 +266,7 @@ impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); type Call = Call; + type CallFilter = (); type EncodedCall = crate::millau_messages::FromMillauEncodedCall; type SourceChainAccountId = bp_millau::AccountId; type TargetChainAccountPublic = MultiSigner; diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index b68ff3aa5e427..1f932dcfe348e 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -31,7 +31,7 @@ use frame_support::{ decl_event, decl_module, decl_storage, dispatch::{Dispatchable, Parameter}, ensure, - traits::Get, + traits::{Filter, Get}, weights::{extract_actual_weight, GetDispatchInfo}, RuntimeDebug, }; @@ -134,6 +134,11 @@ pub trait Config: frame_system::Config { Origin = ::Origin, PostInfo = frame_support::dispatch::PostDispatchInfo, >; + /// Pre-dispatch filter for incoming calls. + /// + /// The pallet will filter all incoming calls right before they're dispatched. If this filter + /// rejects the call, special event (`Event::MessageCallRejected`) is emitted. + type CallFilter: Filter<>::Call>; /// The type that is used to wrap the `Self::Call` when it is moved over bridge. /// /// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure @@ -172,6 +177,8 @@ decl_event!( MessageDispatched(InstanceId, MessageId, DispatchResult), /// We have failed to decode Call from the message. MessageCallDecodeFailed(InstanceId, MessageId), + /// The call from the message has been rejected by the call filter. + MessageCallRejected(InstanceId, MessageId), /// Phantom member, never used. Needed to handle multiple pallet instances. _Dummy(PhantomData), } @@ -269,6 +276,18 @@ impl, I: Instance> MessageDispatch for Module { } }; + // filter the call + if !T::CallFilter::filter(&call) { + frame_support::debug::trace!( + "Message {:?}/{:?}: the call ({:?}) is rejected by filter", + bridge, + id, + call, + ); + Self::deposit_event(RawEvent::MessageCallRejected(bridge, id)); + return; + } + // verify weight // (we want passed weight to be at least equal to pre-dispatch weight of the call // because otherwise Calls may be dispatched at lower price) @@ -488,6 +507,7 @@ mod tests { type TargetChainAccountPublic = TestAccountPublic; type TargetChainSignature = TestSignature; type Call = Call; + type CallFilter = TestCallFilter; type EncodedCall = EncodedCall; type AccountIdConverter = AccountIdConverter; } @@ -501,6 +521,14 @@ mod tests { } } + pub struct TestCallFilter; + + impl Filter for TestCallFilter { + fn filter(call: &Call) -> bool { + !matches!(*call, Call::System(frame_system::Call::fill_block(_))) + } + } + const TEST_SPEC_VERSION: SpecVersion = 0; const TEST_WEIGHT: Weight = 1_000_000_000; @@ -668,6 +696,31 @@ mod tests { }); } + #[test] + fn should_emit_event_for_rejected_calls() { + new_test_ext().execute_with(|| { + let bridge = b"ethb".to_owned(); + let id = [0; 4]; + + let call = Call::System(>::fill_block(Perbill::from_percent(75))); + let weight = call.get_dispatch_info().weight; + let mut message = prepare_root_message(call); + message.weight = weight; + + System::set_block_number(1); + CallDispatch::dispatch(bridge, id, Ok(message)); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::call_dispatch(Event::::MessageCallRejected(bridge, id)), + topics: vec![], + }], + ); + }); + } + #[test] fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { From 1ed4808e264a055be6af9ecf4fbcaaaa629bd54d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 2 Feb 2021 13:27:18 +0300 Subject: [PATCH 0320/1210] pause relays(s) when node is syncing (#605) --- relays/ethereum-client/src/client.rs | 24 +++++++++++++++++-- relays/ethereum-client/src/error.rs | 14 ++++++++++- relays/ethereum-client/src/rpc.rs | 5 +++- relays/ethereum-client/src/types.rs | 2 +- relays/ethereum/src/ethereum_exchange.rs | 4 ++++ relays/ethereum/src/ethereum_sync_loop.rs | 7 ++++++ relays/ethereum/src/substrate_sync_loop.rs | 4 ++++ relays/substrate-client/Cargo.toml | 1 + relays/substrate-client/src/client.rs | 11 +++++++++ relays/substrate-client/src/error.rs | 10 +++++++- relays/substrate-client/src/headers_source.rs | 2 ++ relays/substrate-client/src/rpc.rs | 3 +++ relays/substrate/src/headers_target.rs | 4 ++++ relays/substrate/src/messages_source.rs | 4 ++++ relays/substrate/src/messages_target.rs | 4 ++++ 15 files changed, 93 insertions(+), 6 deletions(-) diff --git a/relays/ethereum-client/src/client.rs b/relays/ethereum-client/src/client.rs index b5fe3ab6bf179..30a62a400e1dd 100644 --- a/relays/ethereum-client/src/client.rs +++ b/relays/ethereum-client/src/client.rs @@ -16,8 +16,8 @@ use crate::rpc::Ethereum; use crate::types::{ - Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, Transaction, TransactionHash, - H256, U256, + Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, SyncState, Transaction, + TransactionHash, H256, U256, }; use crate::{ConnectionParams, Error, Result}; @@ -25,6 +25,9 @@ use jsonrpsee::raw::RawClient; use jsonrpsee::transport::http::HttpTransportClient; use jsonrpsee::Client as RpcClient; +/// Number of headers missing from the Ethereum node for us to consider node not synced. +const MAJOR_SYNC_BLOCKS: u64 = 5; + /// The client used to interact with an Ethereum node through RPC. #[derive(Clone)] pub struct Client { @@ -53,6 +56,23 @@ impl Client { pub fn reconnect(&mut self) { self.client = Self::build_client(&self.params); } +} + +impl Client { + /// Returns true if client is connected to at least one peer and is in synced state. + pub async fn ensure_synced(&self) -> Result<()> { + match Ethereum::syncing(&self.client).await? { + SyncState::NotSyncing => Ok(()), + SyncState::Syncing(syncing) => { + let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block); + if missing_headers > MAJOR_SYNC_BLOCKS.into() { + return Err(Error::ClientNotSynced(missing_headers)); + } + + Ok(()) + } + } + } /// Estimate gas usage for the given call. pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { diff --git a/relays/ethereum-client/src/error.rs b/relays/ethereum-client/src/error.rs index b02e5fecf5842..afcc3c678254e 100644 --- a/relays/ethereum-client/src/error.rs +++ b/relays/ethereum-client/src/error.rs @@ -16,6 +16,8 @@ //! Ethereum node RPC errors. +use crate::types::U256; + use jsonrpsee::client::RequestError; use relay_utils::MaybeConnectionError; @@ -40,6 +42,9 @@ pub enum Error { InvalidSubstrateBlockNumber, /// An invalid index has been received from an Ethereum node. InvalidIncompleteIndex, + /// The client we're connected to is not synced, so we can't rely on its state. Contains + /// number of unsynced headers. + ClientNotSynced(U256), } impl From for Error { @@ -50,7 +55,11 @@ impl From for Error { impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { - matches!(*self, Error::Request(RequestError::TransportError(_))) + matches!( + *self, + Error::Request(RequestError::TransportError(_)) + | Error::ClientNotSynced(_), + ) } } @@ -66,6 +75,9 @@ impl ToString for Error { Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), Self::InvalidIncompleteIndex => "Received an invalid incomplete index from Ethereum Node".to_string(), + Self::ClientNotSynced(missing_headers) => { + format!("Ethereum client is not synced: syncing {} headers", missing_headers) + } } } } diff --git a/relays/ethereum-client/src/rpc.rs b/relays/ethereum-client/src/rpc.rs index 9739d3edbe280..3fa4f6ceb9cd9 100644 --- a/relays/ethereum-client/src/rpc.rs +++ b/relays/ethereum-client/src/rpc.rs @@ -22,11 +22,14 @@ #![allow(unused_variables)] use crate::types::{ - Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, Transaction, TransactionHash, H256, U256, U64, + Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SyncState, Transaction, TransactionHash, + H256, U256, U64, }; jsonrpsee::rpc_api! { pub(crate) Ethereum { + #[rpc(method = "eth_syncing", positional_params)] + fn syncing() -> SyncState; #[rpc(method = "eth_estimateGas", positional_params)] fn estimate_gas(call_request: CallRequest) -> U256; #[rpc(method = "eth_blockNumber", positional_params)] diff --git a/relays/ethereum-client/src/types.rs b/relays/ethereum-client/src/types.rs index f64362ade0e88..1bb9233b82ea4 100644 --- a/relays/ethereum-client/src/types.rs +++ b/relays/ethereum-client/src/types.rs @@ -18,7 +18,7 @@ use headers_relay::sync_types::SourceHeader; -pub use web3::types::{Address, Bytes, CallRequest, H256, U128, U256, U64}; +pub use web3::types::{Address, Bytes, CallRequest, SyncState, H256, U128, U256, U64}; /// When header is just received from the Ethereum node, we check that it has /// both number and hash fields filled. diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 19d9f44cef0e9..92ba211535129 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -248,6 +248,10 @@ impl TargetClient for SubstrateTransactionsTarget { } async fn best_finalized_header_id(&self) -> Result { + // we can't continue to relay exchange proofs if Substrate node is out of sync, because + // it may have already received (some of) proofs that we're going to relay + self.client.ensure_synced().await?; + self.client.best_ethereum_finalized_block().await } diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index b84626d230c6d..c8741c2fe18a6 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -130,6 +130,9 @@ impl RelayClient for EthereumHeadersSource { #[async_trait] impl SourceClient for EthereumHeadersSource { async fn best_block_number(&self) -> Result { + // we **CAN** continue to relay headers if Ethereum node is out of sync, because + // Substrate node may be missing headers that are already available at the Ethereum + self.client.best_block_number().await.map_err(Into::into) } @@ -204,6 +207,10 @@ impl RelayClient for SubstrateHeadersTarget { #[async_trait] impl TargetClient for SubstrateHeadersTarget { async fn best_header_id(&self) -> Result { + // we can't continue to relay headers if Substrate node is out of sync, because + // it may have already received (some of) headers that we're going to relay + self.client.ensure_synced().await?; + self.client.best_ethereum_block().await } diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 298fe0e592545..9e15b9223826a 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -131,6 +131,10 @@ impl RelayClient for EthereumHeadersTarget { #[async_trait] impl TargetClient for EthereumHeadersTarget { async fn best_header_id(&self) -> Result { + // we can't continue to relay headers if Ethereum node is out of sync, because + // it may have already received (some of) headers that we're going to relay + self.client.ensure_synced().await?; + self.client.best_substrate_block(self.contract).await } diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 0e4b43bf7f6b6..320abf280f040 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -26,6 +26,7 @@ relay-utils = { path = "../utils" } frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index cfa644bc8c71e..a5ddf143f1b03 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -104,6 +104,17 @@ impl Client { } impl Client { + /// Returns true if client is connected to at least one peer and is in synced state. + pub async fn ensure_synced(&self) -> Result<()> { + let health = Substrate::::system_health(&self.client).await?; + let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); + if is_synced { + Ok(()) + } else { + Err(Error::ClientNotSynced(health)) + } + } + /// Return hash of the genesis block. pub fn genesis_hash(&self) -> &C::Hash { &self.genesis_hash diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index c2930c21d217a..f0212ed501ae2 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -19,6 +19,7 @@ use jsonrpsee::client::RequestError; use jsonrpsee::transport::ws::WsNewDnsError; use relay_utils::MaybeConnectionError; +use sc_rpc_api::system::Health; /// Result type used by Substrate client. pub type Result = std::result::Result; @@ -38,6 +39,8 @@ pub enum Error { UninitializedBridgePallet, /// Account does not exist on the chain. AccountDoesNotExist, + /// The client we're connected to is not synced, so we can't rely on its state. + ClientNotSynced(Health), /// Custom logic error. Custom(String), } @@ -56,7 +59,11 @@ impl From for Error { impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { - matches!(*self, Error::Request(RequestError::TransportError(_))) + matches!( + *self, + Error::Request(RequestError::TransportError(_)) + | Error::ClientNotSynced(_) + ) } } @@ -74,6 +81,7 @@ impl ToString for Error { Self::ResponseParseFailed(e) => e.what().to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), + Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), Self::Custom(e) => e.clone(), } } diff --git a/relays/substrate-client/src/headers_source.rs b/relays/substrate-client/src/headers_source.rs index 040cc08e99766..b347a1c9f57f2 100644 --- a/relays/substrate-client/src/headers_source.rs +++ b/relays/substrate-client/src/headers_source.rs @@ -73,6 +73,8 @@ where P::Header: SourceHeader, { async fn best_block_number(&self) -> Result { + // we **CAN** continue to relay headers if source node is out of sync, because + // target node may be missing headers that are already available at the source Ok(*self.client.best_header().await?.number()) } diff --git a/relays/substrate-client/src/rpc.rs b/relays/substrate-client/src/rpc.rs index 9c76f593e99b8..2e832b4018174 100644 --- a/relays/substrate-client/src/rpc.rs +++ b/relays/substrate-client/src/rpc.rs @@ -25,6 +25,7 @@ use crate::chain::Chain; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; +use sc_rpc_api::system::Health; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, @@ -33,6 +34,8 @@ use sp_version::RuntimeVersion; jsonrpsee::rpc_api! { pub(crate) Substrate { + #[rpc(method = "system_health", positional_params)] + fn system_health() -> Health; #[rpc(method = "chain_getHeader", positional_params)] fn chain_get_header(block_hash: Option) -> C::Header; #[rpc(method = "chain_getFinalizedHead", positional_params)] diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs index c962511270805..2b5f63a7feae3 100644 --- a/relays/substrate/src/headers_target.rs +++ b/relays/substrate/src/headers_target.rs @@ -73,6 +73,10 @@ where P: SubstrateHeadersSyncPipeline, { async fn best_header_id(&self) -> Result, SubstrateError> { + // we can't continue to relay headers if target node is out of sync, because + // it may have already received (some of) headers that we're going to relay + self.client.ensure_synced().await?; + let call = P::BEST_BLOCK_METHOD.into(); let data = Bytes(Vec::new()); diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index b9a8d01a7c258..375c469fde1a9 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -99,6 +99,10 @@ where P::TargetHeaderHash: Decode, { async fn state(&self) -> Result, SubstrateError> { + // we can't continue to deliver confirmations if source node is out of sync, because + // it may have already received confirmations that we're going to deliver + self.client.ensure_synced().await?; + read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>( &self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE, diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index 0bc81d9be05a3..e8610aac9533c 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -95,6 +95,10 @@ where P::SourceHeaderHash: Decode, { async fn state(&self) -> Result, SubstrateError> { + // we can't continue to deliver messages if target node is out of sync, because + // it may have already received (some of) messages that we're going to deliver + self.client.ensure_synced().await?; + read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>( &self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, From aa7b32019a4f5f5f2bed7220b6b2257ea7a1228b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 2 Feb 2021 19:28:45 +0000 Subject: [PATCH 0321/1210] Bump serde from 1.0.118 to 1.0.121 (#674) --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index b8f4c4e232068..7cc68340f61a1 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" -serde = { version = "1.0.118", optional = true, features = ["derive"] } +serde = { version = "1.0.121", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index e1ab858a033e7..dab6b2c6d2c13 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } -serde = { version = "1.0.118", optional = true, features = ["derive"] } +serde = { version = "1.0.121", optional = true, features = ["derive"] } # Bridge dependencies From b4c503db8dbf708a26b53517fc45f027fee7836e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 2 Feb 2021 23:27:57 +0100 Subject: [PATCH 0322/1210] Add finality verifier test with different validator set id. (#698) * Add test for invalid set id. * cargo fmt --all * Update modules/finality-verifier/src/lib.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- modules/finality-verifier/src/lib.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 924a1c005460c..bfb5394705590 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -203,6 +203,27 @@ mod tests { }) } + #[test] + fn rejects_justification_that_skips_authority_set_transition() { + run_test(|| { + initialize_substrate_bridge(); + + let child = test_header(1); + let header = test_header(2); + + let set_id = 2; + let grandpa_round = 1; + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let ancestry_proof = vec![child, header.clone()]; + + assert_err!( + Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + >::InvalidJustification + ); + }) + } + #[test] fn does_not_import_header_with_invalid_finality_proof() { run_test(|| { From 75bbe2f42f37577523a694af5f9ae146a32d727c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 3 Feb 2021 11:10:10 +0300 Subject: [PATCH 0323/1210] Fixed call encoding in signature digest (#699) * fixed call encoding in signature digets * udpated test --- bin/runtime-common/src/messages.rs | 7 +++---- modules/call-dispatch/src/lib.rs | 25 +++++++++++-------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index dfb1307580fab..13b3a4e9458f6 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -27,7 +27,7 @@ use bp_message_lane::{ InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use bp_runtime::InstanceId; -use codec::{Compact, Decode, Encode}; +use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; @@ -352,9 +352,7 @@ pub mod target { impl From> for Result>, ()> { fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { - let mut input = &encoded_call.encoded_call[..]; - let _skipped_length = Compact::::decode(&mut input).map_err(drop)?; - CallOf::>::decode(&mut input).map_err(drop) + CallOf::>::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) } } @@ -797,6 +795,7 @@ mod tests { }, } ); + assert_eq!(Ok(ThisChainCall::Transfer), message_on_this_chain.call.into()); } const TEST_LANE_ID: &LaneId = b"test"; diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 1f932dcfe348e..53466607acc97 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -145,9 +145,6 @@ pub trait Config: frame_system::Config { /// that all other stuff (like `spec_version`) is ok. If we would try to decode /// `Call` which has been encoded using previous `spec_version`, then we might end /// up with decoding error, instead of `MessageVersionSpecMismatch`. - /// - /// The `Encode` implementation should match `Encode` implementation of the actual - /// `Call`, that (may) have been used to produce signature for `CallOrigin::TargetAccount`. type EncodedCall: Decode + Encode + Into>::Call, ()>>; /// A type which can be turned into an AccountId from a 256-bit hash. /// @@ -231,6 +228,16 @@ impl, I: Instance> MessageDispatch for Module { return; } + // now that we have spec version checked, let's decode the call + let call = match message.call.into() { + Ok(call) => call, + Err(_) => { + frame_support::debug::trace!("Failed to decode Call from message {:?}/{:?}", bridge, id,); + Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id)); + return; + } + }; + // prepare dispatch origin let origin_account = match message.origin { CallOrigin::SourceRoot => { @@ -240,7 +247,7 @@ impl, I: Instance> MessageDispatch for Module { target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { - let digest = account_ownership_digest(&message.call, source_account_id, message.spec_version, bridge); + let digest = account_ownership_digest(&call, source_account_id, message.spec_version, bridge); let target_account = target_public.into_account(); if !target_signature.verify(&digest[..], &target_account) { @@ -266,16 +273,6 @@ impl, I: Instance> MessageDispatch for Module { } }; - // now that we have everything checked, let's decode the call - let call = match message.call.into() { - Ok(call) => call, - Err(_) => { - frame_support::debug::trace!("Failed to decode Call from message {:?}/{:?}", bridge, id,); - Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id)); - return; - } - }; - // filter the call if !T::CallFilter::filter(&call) { frame_support::debug::trace!( From affbf7e7f3a1a44a3e246f64e77e41a28c346528 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 3 Feb 2021 14:33:49 -0500 Subject: [PATCH 0324/1210] Wire Finality Verifier Pallet Into Runtimes (#696) * Add Finality Verifier pallet to runtimes * Implement simple ancestry checker * Use the new checker in runtimes * Remove unused import warning * Bump max allowed ancestry proof size * Add a few optimization suggestions when verifying ancestry * Use session length as upper bound for ancestry proof size * Remove unused time units --- bin/millau/runtime/Cargo.toml | 4 ++ bin/millau/runtime/src/lib.rs | 27 +++++--- bin/rialto/runtime/Cargo.toml | 2 + bin/rialto/runtime/src/lib.rs | 27 +++++--- modules/finality-verifier/Cargo.toml | 2 + modules/finality-verifier/src/lib.rs | 10 ++- primitives/header-chain/src/lib.rs | 100 +++++++++++++++++++++++++++ primitives/millau/src/lib.rs | 18 +++++ primitives/rialto/src/lib.rs | 18 +++++ 9 files changed, 183 insertions(+), 25 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 7cc68340f61a1..0f23a9442f08b 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -14,12 +14,14 @@ serde = { version = "1.0.121", optional = true, features = ["derive"] } # Bridge dependencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } bp-millau = { path = "../../../primitives/millau", default-features = false } bp-rialto = { path = "../../../primitives/rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } +pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } @@ -58,6 +60,7 @@ wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2. [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-message-lane/std", "bp-millau/std", "bp-rialto/std", @@ -71,6 +74,7 @@ std = [ "pallet-aura/std", "pallet-balances/std", "pallet-bridge-call-dispatch/std", + "pallet-finality-verifier/std", "pallet-grandpa/std", "pallet-message-lane/std", "pallet-randomness-collective-flip/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3164c8a9d831f..3bf9309dfbeda 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -132,15 +132,6 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 1, }; -pub const MILLISECS_PER_BLOCK: u64 = 6000; - -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// These time units are defined in number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { @@ -236,7 +227,7 @@ impl pallet_grandpa::Config for Runtime { } parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; + pub const MinimumPeriod: u64 = bp_millau::SLOT_DURATION / 2; } impl pallet_timestamp::Config for Runtime { @@ -287,7 +278,7 @@ impl pallet_sudo::Config for Runtime { parameter_types! { /// Authorities are changing every 5 minutes. - pub const Period: BlockNumber = 5 * MINUTES; + pub const Period: BlockNumber = bp_millau::SESSION_LENGTH; pub const Offset: BlockNumber = 0; } @@ -309,6 +300,19 @@ impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_rialto::Rialto; } +parameter_types! { + // We'll use the length of a session on the bridged chain as our bound since GRANDPA is + // guaranteed to produce a justification every session. + pub const MaxHeadersInSingleProof: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; +} + +impl pallet_finality_verifier::Config for Runtime { + type BridgedChain = bp_rialto::Rialto; + type HeaderChain = pallet_substrate_bridge::Module; + type AncestryChecker = bp_header_chain::LinearAncestryChecker; + type MaxHeadersInSingleProof = MaxHeadersInSingleProof; +} + impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { @@ -362,6 +366,7 @@ construct_runtime!( BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeRialtoMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, + BridgeFinalityVerifier: pallet_finality_verifier::{Module, Call}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index dab6b2c6d2c13..855a1754e724c 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -27,6 +27,7 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } +pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } @@ -90,6 +91,7 @@ std = [ "pallet-bridge-eth-poa/std", "pallet-bridge-call-dispatch/std", "pallet-bridge-currency-exchange/std", + "pallet-finality-verifier/std", "pallet-grandpa/std", "pallet-message-lane/std", "pallet-randomness-collective-flip/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 677ca283c480a..f7717b1c769ec 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -140,15 +140,6 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 1, }; -pub const MILLISECS_PER_BLOCK: u64 = 6000; - -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// These time units are defined in number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { @@ -344,7 +335,7 @@ impl pallet_grandpa::Config for Runtime { } parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; + pub const MinimumPeriod: u64 = bp_rialto::SLOT_DURATION / 2; } impl pallet_timestamp::Config for Runtime { @@ -394,7 +385,7 @@ impl pallet_sudo::Config for Runtime { } parameter_types! { - pub const Period: BlockNumber = 4; + pub const Period: BlockNumber = bp_rialto::SESSION_LENGTH; pub const Offset: BlockNumber = 0; } @@ -416,6 +407,19 @@ impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_millau::Millau; } +parameter_types! { + // We'll use the length of a session on the bridged chain as our bound since GRANDPA is + // guaranteed to produce a justification every session. + pub const MaxHeadersInSingleProof: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; +} + +impl pallet_finality_verifier::Config for Runtime { + type BridgedChain = bp_millau::Millau; + type HeaderChain = pallet_substrate_bridge::Module; + type AncestryChecker = bp_header_chain::LinearAncestryChecker; + type MaxHeadersInSingleProof = MaxHeadersInSingleProof; +} + impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { @@ -471,6 +475,7 @@ construct_runtime!( BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, + BridgeFinalityVerifier: pallet_finality_verifier::{Module, Call}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, BridgeMillauMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index b98f995b61693..c1e09c7cf9798 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } serde = { version = "1.0", optional = true } +num-traits = { version = "0.2", default-features = false } # Bridge Dependencies @@ -39,6 +40,7 @@ std = [ "finality-grandpa/std", "frame-support/std", "frame-system/std", + "num-traits/std", "serde", "sp-runtime/std", "sp-std/std", diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index bfb5394705590..fb708ae294d7e 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -37,11 +37,16 @@ use bp_runtime::{Chain, HeaderOf}; use finality_grandpa::voter_set::VoterSet; use frame_support::{dispatch::DispatchError, ensure, traits::Get}; use frame_system::ensure_signed; +use num_traits::AsPrimitive; use sp_runtime::traits::Header as HeaderT; +use sp_std::vec::Vec; #[cfg(test)] mod mock; +// Re-export in crate namespace for `construct_runtime!` +pub use pallet::*; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -69,7 +74,7 @@ pub mod pallet { /// The maximum length of headers we can have in a single ancestry proof. This prevents /// unbounded iteration when verifying proofs. #[pallet::constant] - type MaxHeadersInSingleProof: Get; + type MaxHeadersInSingleProof: Get<::BlockNumber>; } #[pallet::pallet] @@ -100,7 +105,7 @@ pub mod pallet { let _ = ensure_signed(origin)?; ensure!( - ancestry_proof.len() <= T::MaxHeadersInSingleProof::get() as usize, + ancestry_proof.len() <= T::MaxHeadersInSingleProof::get().as_(), >::OversizedAncestryProof ); @@ -149,7 +154,6 @@ pub mod pallet { #[cfg(test)] mod tests { - use super::pallet::*; use super::*; use crate::mock::{run_test, test_header, Origin, TestRuntime}; use bp_test_utils::{authority_list, make_justification_for_header}; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index b65325b850eb4..a9623b13dc4f5 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -27,7 +27,9 @@ use core::fmt::Debug; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, SetId}; +use sp_runtime::traits::Header as HeaderT; use sp_runtime::RuntimeDebug; +use sp_std::vec::Vec; pub mod justification; @@ -110,3 +112,101 @@ impl AncestryChecker for () { true } } + +/// A simple ancestry checker which verifies ancestry by walking every header between `child` and +/// `ancestor`. +pub struct LinearAncestryChecker; + +impl AncestryChecker> for LinearAncestryChecker { + fn are_ancestors(ancestor: &H, child: &H, proof: &Vec) -> bool { + // You can't be your own parent + if proof.len() < 2 { + return false; + } + + // Let's make sure that the given headers are actually in the proof + match proof.first() { + Some(first) if first == ancestor => {} + _ => return false, + } + + match proof.last() { + Some(last) if last == child => {} + _ => return false, + } + + // Now we actually check the proof + for i in 1..proof.len() { + if &proof[i - 1].hash() != proof[i].parent_hash() { + return false; + } + } + + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_test_utils::test_header; + use sp_runtime::testing::Header; + + #[test] + fn can_verify_ancestry_correctly() { + let ancestor: Header = test_header(1); + let header2: Header = test_header(2); + let header3: Header = test_header(3); + let child: Header = test_header(4); + + let ancestry_proof = vec![ancestor.clone(), header2, header3, child.clone()]; + + assert!(LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof)); + } + + #[test] + fn does_not_verify_invalid_proof() { + let ancestor: Header = test_header(1); + let header2: Header = test_header(2); + let header3: Header = test_header(3); + let child: Header = test_header(4); + + let ancestry_proof = vec![ancestor.clone(), header3, header2, child.clone()]; + + let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof); + assert!(invalid); + } + + #[test] + fn header_is_not_allowed_to_be_its_own_ancestor() { + let ancestor: Header = test_header(1); + let child: Header = ancestor.clone(); + let ancestry_proof = vec![ancestor.clone()]; + + let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof); + assert!(invalid); + } + + #[test] + fn proof_is_considered_invalid_if_child_and_ancestor_do_not_match() { + let ancestor: Header = test_header(1); + let header2: Header = test_header(2); + let header3: Header = test_header(3); + let child: Header = test_header(4); + + let ancestry_proof = vec![ancestor, header3.clone(), header2.clone(), child]; + + let invalid = !LinearAncestryChecker::are_ancestors(&header2, &header3, &ancestry_proof); + assert!(invalid); + } + + #[test] + fn empty_proof_is_invalid() { + let ancestor: Header = test_header(1); + let child: Header = ancestor.clone(); + let ancestry_proof = vec![]; + + let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof); + assert!(invalid); + } +} diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 5c0febdca399a..b6f32582e9b6f 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -83,6 +83,24 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +/// The length of a session (how often authorities change) on Millau measured in of number of blocks. +pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; + +/// Re-export `time_units` to make usage easier. +pub use time_units::*; + +/// Human readable time units defined in terms of number of blocks. +pub mod time_units { + use super::BlockNumber; + + pub const MILLISECS_PER_BLOCK: u64 = 6000; + pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + + pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); + pub const HOURS: BlockNumber = MINUTES * 60; + pub const DAYS: BlockNumber = HOURS * 24; +} + /// Block number type used in Millau. pub type BlockNumber = u64; diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index b347ce5ec5f88..715004efba74f 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -74,6 +74,24 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +/// The length of a session (how often authorities change) on Rialto measured in of number of blocks. +pub const SESSION_LENGTH: BlockNumber = 4; + +/// Re-export `time_units` to make usage easier. +pub use time_units::*; + +/// Human readable time units defined in terms of number of blocks. +pub mod time_units { + use super::BlockNumber; + + pub const MILLISECS_PER_BLOCK: u64 = 6000; + pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + + pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); + pub const HOURS: BlockNumber = MINUTES * 60; + pub const DAYS: BlockNumber = HOURS * 24; +} + /// Block number type used in Rialto. pub type BlockNumber = u32; From 9a081d0b740975d02800581a737de49e93fdd629 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 4 Feb 2021 12:53:49 -0500 Subject: [PATCH 0325/1210] Add Logging to Finality Verifier Pallet (#702) * Add some logging to the finality verifier pallet * Add finality target to happy path log --- modules/finality-verifier/src/lib.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index fb708ae294d7e..4e0a3583a2494 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -104,6 +104,9 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; + frame_support::debug::trace!("Going to try and finalize header {:?}", finality_target); + frame_support::debug::trace!("Got ancestry proof of length {}", ancestry_proof.len()); + ensure!( ancestry_proof.len() <= T::MaxHeadersInSingleProof::get().as_(), >::OversizedAncestryProof @@ -119,9 +122,14 @@ pub mod pallet { voter_set, &justification, ) - .map_err(|_| >::InvalidJustification)?; + .map_err(|e| { + frame_support::debug::error!("Received invalid justification for {:?}: {:?}", finality_target, e); + >::InvalidJustification + })?; let best_finalized = T::HeaderChain::best_finalized(); + frame_support::debug::trace!("Checking ancestry against best finalized header: {:?}", &best_finalized); + ensure!( T::AncestryChecker::are_ancestors(&best_finalized, &finality_target, &ancestry_proof), >::InvalidAncestryProof @@ -129,8 +137,15 @@ pub mod pallet { // Note that this won't work if we ever change the `ancestry_proof` format to be // sparse since this expects a contiguous set of finalized headers. - let _ = - T::HeaderChain::append_finalized_chain(ancestry_proof).map_err(|_| >::FailedToWriteHeader)?; + let _ = T::HeaderChain::append_finalized_chain(ancestry_proof).map_err(|_| { + frame_support::debug::error!("Failed to append finalized header chain."); + >::FailedToWriteHeader + })?; + + frame_support::debug::info!( + "Succesfully imported finalized header chain for target header {:?}!", + finality_target + ); Ok(().into()) } From 01a37babd9c9ccc42828d5a6ca0ef15d146f578b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 9 Feb 2021 16:16:43 +0000 Subject: [PATCH 0326/1210] Bump serde from 1.0.121 to 1.0.123 (#709) --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 0f23a9442f08b..358537e32fa4e 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" -serde = { version = "1.0.121", optional = true, features = ["derive"] } +serde = { version = "1.0.123", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 855a1754e724c..ebd259aa503c3 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } -serde = { version = "1.0.121", optional = true, features = ["derive"] } +serde = { version = "1.0.123", optional = true, features = ["derive"] } # Bridge dependencies From 48b3d138a3e246502e0485bc3e76de6286b96b37 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 9 Feb 2021 15:49:50 -0500 Subject: [PATCH 0327/1210] Bump serde_json from 1.0.61 to 1.0.62 (#708) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.61 to 1.0.62. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.61...v1.0.62) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index bf30bb47d6289..8f58c27330ea0 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac" log = "0.4.14" num-traits = "0.2" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.61" +serde_json = "1.0.62" time = "0.2" # Bridge dependencies From 0b3b2e2a24875eb73b932b486a436749e5fbbad9 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 10 Feb 2021 05:14:58 -0500 Subject: [PATCH 0328/1210] Stop Importing Full Header Chain (#707) * Make AncestryProof type more flexible * Only import single finalized header instead of a chain * Fix unchecked header import tests * Add option for limiting ancestry proof size * Update finality verifier Config in runtimes * Update some documentation * Fix Clippy warning * Allow AncestryChecker to return proof size Stops us from abusing the `Size` trait * Remove Size impl for Vec * Remove size contraints for ancestry proofs With different proof types its unclear how to "size" should be interpreted, so we remove this requirement all together to avoid confusion. --- bin/millau/runtime/src/lib.rs | 8 +-- bin/rialto/runtime/src/lib.rs | 8 +-- modules/finality-verifier/Cargo.toml | 2 - modules/finality-verifier/src/lib.rs | 89 +++++++-------------------- modules/finality-verifier/src/mock.rs | 6 +- modules/substrate/src/lib.rs | 55 +++-------------- primitives/header-chain/src/lib.rs | 16 ++--- 7 files changed, 38 insertions(+), 146 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3bf9309dfbeda..65cd08970f3cd 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -300,17 +300,11 @@ impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_rialto::Rialto; } -parameter_types! { - // We'll use the length of a session on the bridged chain as our bound since GRANDPA is - // guaranteed to produce a justification every session. - pub const MaxHeadersInSingleProof: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; -} - impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type HeaderChain = pallet_substrate_bridge::Module; + type AncestryProof = Vec; type AncestryChecker = bp_header_chain::LinearAncestryChecker; - type MaxHeadersInSingleProof = MaxHeadersInSingleProof; } impl pallet_shift_session_manager::Config for Runtime {} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index f7717b1c769ec..3ebb487fe99bc 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -407,17 +407,11 @@ impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_millau::Millau; } -parameter_types! { - // We'll use the length of a session on the bridged chain as our bound since GRANDPA is - // guaranteed to produce a justification every session. - pub const MaxHeadersInSingleProof: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; -} - impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_millau::Millau; type HeaderChain = pallet_substrate_bridge::Module; + type AncestryProof = Vec; type AncestryChecker = bp_header_chain::LinearAncestryChecker; - type MaxHeadersInSingleProof = MaxHeadersInSingleProof; } impl pallet_shift_session_manager::Config for Runtime {} diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index c1e09c7cf9798..b98f995b61693 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -11,7 +11,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } finality-grandpa = { version = "0.12.3", default-features = false } serde = { version = "1.0", optional = true } -num-traits = { version = "0.2", default-features = false } # Bridge Dependencies @@ -40,7 +39,6 @@ std = [ "finality-grandpa/std", "frame-support/std", "frame-system/std", - "num-traits/std", "serde", "sp-runtime/std", "sp-std/std", diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 4e0a3583a2494..cfcb610e7f5f8 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -35,9 +35,8 @@ use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain}; use bp_runtime::{Chain, HeaderOf}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{dispatch::DispatchError, ensure, traits::Get}; +use frame_support::{dispatch::DispatchError, ensure}; use frame_system::ensure_signed; -use num_traits::AsPrimitive; use sp_runtime::traits::Header as HeaderT; use sp_std::vec::Vec; @@ -64,17 +63,15 @@ pub mod pallet { /// The pallet which we will use as our underlying storage mechanism. type HeaderChain: HeaderChain<::Header, DispatchError>; + /// The type of ancestry proof used by the pallet. + /// + /// Will be used by the ancestry checker to verify that the header being finalized is + /// related to the best finalized header in storage. + type AncestryProof: Parameter; + /// The type through which we will verify that a given header is related to the last /// finalized header in our storage pallet. - type AncestryChecker: AncestryChecker< - ::Header, - Vec<::Header>, - >; - - /// The maximum length of headers we can have in a single ancestry proof. This prevents - /// unbounded iteration when verifying proofs. - #[pallet::constant] - type MaxHeadersInSingleProof: Get<::BlockNumber>; + type AncestryChecker: AncestryChecker<::Header, Self::AncestryProof>; } #[pallet::pallet] @@ -87,45 +84,33 @@ pub mod pallet { impl Pallet { /// Verify a target header is finalized according to the given finality proof. /// - /// Will use the underlying storage pallet to fetch information about the current + /// It will use the underlying storage pallet to fetch information about the current /// authorities and best finalized header in order to verify that the header is finalized. /// - /// If successful in verification, it will write the header as well as its ancestors (from - /// the given `ancestry_proof`) to the underlying storage pallet. - /// - /// Note that the expected format for `ancestry_proof` is a continguous list of finalized - /// headers containing (current_best_finalized_header, finality_target] + /// If successful in verification, it will write the target header to the underlying storage + /// pallet. #[pallet::weight(0)] pub fn submit_finality_proof( origin: OriginFor, finality_target: BridgedHeader, justification: Vec, - ancestry_proof: Vec>, + ancestry_proof: T::AncestryProof, ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; frame_support::debug::trace!("Going to try and finalize header {:?}", finality_target); - frame_support::debug::trace!("Got ancestry proof of length {}", ancestry_proof.len()); - - ensure!( - ancestry_proof.len() <= T::MaxHeadersInSingleProof::get().as_(), - >::OversizedAncestryProof - ); let authority_set = T::HeaderChain::authority_set(); let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; let set_id = authority_set.set_id; - verify_justification::>( - (finality_target.hash(), *finality_target.number()), - set_id, - voter_set, - &justification, - ) - .map_err(|e| { - frame_support::debug::error!("Received invalid justification for {:?}: {:?}", finality_target, e); - >::InvalidJustification - })?; + let (hash, number) = (finality_target.hash(), *finality_target.number()); + verify_justification::>((hash, number), set_id, voter_set, &justification).map_err( + |e| { + frame_support::debug::error!("Received invalid justification for {:?}: {:?}", finality_target, e); + >::InvalidJustification + }, + )?; let best_finalized = T::HeaderChain::best_finalized(); frame_support::debug::trace!("Checking ancestry against best finalized header: {:?}", &best_finalized); @@ -135,17 +120,8 @@ pub mod pallet { >::InvalidAncestryProof ); - // Note that this won't work if we ever change the `ancestry_proof` format to be - // sparse since this expects a contiguous set of finalized headers. - let _ = T::HeaderChain::append_finalized_chain(ancestry_proof).map_err(|_| { - frame_support::debug::error!("Failed to append finalized header chain."); - >::FailedToWriteHeader - })?; - - frame_support::debug::info!( - "Succesfully imported finalized header chain for target header {:?}!", - finality_target - ); + T::HeaderChain::append_header(finality_target); + frame_support::debug::info!("Succesfully imported finalized header with hash {:?}!", hash); Ok(().into()) } @@ -162,8 +138,6 @@ pub mod pallet { InvalidAuthoritySet, /// Failed to write a header to the underlying header chain. FailedToWriteHeader, - /// The given ancestry proof is too large to be verified in a single transaction. - OversizedAncestryProof, } } @@ -283,27 +257,6 @@ mod tests { }) } - #[test] - fn disallows_ancestry_proofs_which_are_too_large() { - run_test(|| { - initialize_substrate_bridge(); - - let header = test_header(1); - let justification = [1u8; 32].encode(); - - let mut ancestry_proof = vec![]; - let max_len = ::MaxHeadersInSingleProof::get(); - for i in 1..=max_len + 1 { - ancestry_proof.push(test_header(i as u64)); - } - - assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), - >::OversizedAncestryProof - ); - }) - } - #[test] fn disallows_invalid_authority_set() { run_test(|| { diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index daacc4584123c..1ef1249545906 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -71,14 +71,14 @@ impl pallet_substrate_bridge::Config for TestRuntime { } parameter_types! { - pub const MaxHeadersInSingleProof: u8 = 5; + pub const MaxElementsInSingleProof: Option = Some(5); } impl crate::pallet::Config for TestRuntime { type BridgedChain = TestBridgedChain; type HeaderChain = pallet_substrate_bridge::Module; - type AncestryChecker = Checker<::Header, Vec<::Header>>; - type MaxHeadersInSingleProof = MaxHeadersInSingleProof; + type AncestryProof = Vec<::Header>; + type AncestryChecker = Checker<::Header, Self::AncestryProof>; } #[derive(Debug)] diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 2a3ad1b0184fd..c14db8596f89e 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -375,25 +375,8 @@ impl bp_header_chain::HeaderChain, sp_runtime::Dispa PalletStorage::::new().current_authority_set() } - fn append_finalized_chain( - headers: impl IntoIterator>, - ) -> Result<(), sp_runtime::DispatchError> { - let mut storage = PalletStorage::::new(); - - let mut header_iter = headers.into_iter().peekable(); - let first_header = header_iter.peek().ok_or(Error::::NotDescendant)?; - - // Quick ancestry check to make sure we're not writing complete nonsense to storage - ensure!( - >::get() == *first_header.parent_hash(), - Error::::NotDescendant, - ); - - for header in header_iter { - import_header_unchecked::<_, T>(&mut storage, header); - } - - Ok(()) + fn append_header(header: BridgedHeader) { + import_header_unchecked::<_, T>(&mut PalletStorage::::new(), header); } } @@ -923,36 +906,15 @@ mod tests { init_with_origin(Origin::root()).unwrap(); let storage = PalletStorage::::new(); - let child = test_header(2); - let header = test_header(3); - - let header_chain = vec![child.clone(), header.clone()]; - assert_ok!(Module::::append_finalized_chain(header_chain)); + let header = test_header(2); + Module::::append_header(header.clone()); - assert!(storage.header_by_hash(child.hash()).unwrap().is_finalized); assert!(storage.header_by_hash(header.hash()).unwrap().is_finalized); - assert_eq!(storage.best_finalized_header().header, header); assert_eq!(storage.best_headers()[0].hash, header.hash()); }) } - #[test] - fn prevents_unchecked_header_import_if_headers_are_unrelated() { - run_test(|| { - init_with_origin(Origin::root()).unwrap(); - - // Pallet is expecting test_header(2) as the child - let not_a_child = test_header(3); - let header_chain = vec![not_a_child]; - - assert_noop!( - Module::::append_finalized_chain(header_chain), - Error::::NotDescendant, - ); - }) - } - #[test] fn importing_unchecked_headers_enacts_new_authority_set() { run_test(|| { @@ -968,7 +930,7 @@ mod tests { header.digest = fork_tests::change_log(0); // Let's import our test header - assert_ok!(Module::::append_finalized_chain(vec![header.clone()])); + Module::::append_header(header.clone()); // Make sure that our header is the best finalized assert_eq!(storage.best_finalized_header().header, header); @@ -998,8 +960,8 @@ mod tests { let header = test_header(3); // Let's import our test headers - let header_chain = vec![schedules_change, header.clone()]; - assert_ok!(Module::::append_finalized_chain(header_chain)); + Module::::append_header(schedules_change); + Module::::append_header(header.clone()); // Make sure that our header is the best finalized assert_eq!(storage.best_finalized_header().header, header); @@ -1039,8 +1001,7 @@ mod tests { // We are expecting an authority set change at height 2, so this header should enact // that upon being imported. - let header_chain = vec![test_header(2)]; - assert_ok!(Module::::append_finalized_chain(header_chain)); + Module::::append_header(test_header(2)); // Make sure that the authority set actually changed upon importing our header assert_eq!( diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index a9623b13dc4f5..1663717646021 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -69,7 +69,7 @@ pub trait InclusionProofVerifier { fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option; } -/// A base trait for pallets which want to keep track of a full set of headers from a bridged chain. +/// A trait for pallets which want to keep track of finalized headers from a bridged chain. pub trait HeaderChain { /// Get the best finalized header known to the header chain. fn best_finalized() -> H; @@ -77,14 +77,8 @@ pub trait HeaderChain { /// Get the best authority set known to the header chain. fn authority_set() -> AuthoritySet; - /// Write a finalized chain of headers to the underlying pallet storage. - /// - /// It is assumed that each header in this chain been finalized, and that the given headers are - /// in order (e.g vec![header_1, header_2, ..., header_n]). - /// - /// This function should fail if the first header is not a child of the current best finalized - /// header known to the underlying pallet storage. - fn append_finalized_chain(headers: impl IntoIterator) -> Result<(), E>; + /// Write a header finalized by GRANDPA to the underlying pallet storage. + fn append_header(header: H); } impl HeaderChain for () { @@ -96,9 +90,7 @@ impl HeaderChain for () { AuthoritySet::default() } - fn append_finalized_chain(_headers: impl IntoIterator) -> Result<(), E> { - Ok(()) - } + fn append_header(_header: H) {} } /// A trait for checking if a given child header is a direct descendant of an ancestor. From 55dfe71009a727c9b67cef13e2faa3af940ad109 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 10 Feb 2021 20:26:47 +0300 Subject: [PATCH 0329/1210] Account proof size in weight formula (#679) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix broken message lane benchmarks * proof-size related benchmarks * impl Size for proof parameters * include proof weight into weight formula * left TODO * fixed proof size * WeightInfoExt::receive_messages_proof_weight * charge for extra message bytes delivery in send_message * removed default impl of WeightsInfoExt * moved weight formulas to WeightInfoExt * receive_messages_proof_outbound_lane_state_overhead is included twice in weight * typo * typo * fixed TODO * more asserts * started wotk on message-lane documentation * expected_extra_storage_proof_size() is actually expected in delivery confirmation tx * update README.md * ensure_able_to_receive_confirmation * test rialto message lane weights * removed TODO * removed unnecessary trait requirements * fixed arguments * fix compilation * decreased basic delivery tx weight * fmt * clippy * Update modules/message-lane/src/benchmarking.rs Co-authored-by: Hernando Castano * structs * Update primitives/millau/src/lib.rs Co-authored-by: Hernando Castano * removed readme.md * removed obsolete trait bounds * Revert "removed readme.md" This reverts commit 50b7376a41687a94c27bf77565434be153f87ca1. * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * Update bin/runtime-common/src/messages.rs Co-authored-by: Tomasz Drwięga * PreComputedSize Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 38 ++- bin/millau/runtime/src/rialto_messages.rs | 22 +- bin/rialto/runtime/src/lib.rs | 47 +++- bin/rialto/runtime/src/millau_messages.rs | 23 +- bin/runtime-common/src/messages.rs | 196 +++++++++------ .../src/messages_benchmarking.rs | 43 ++-- modules/message-lane/Cargo.toml | 2 + modules/message-lane/README.md | 132 ++++++++++ modules/message-lane/src/benchmarking.rs | 182 ++++++++++---- modules/message-lane/src/lib.rs | 59 +++-- modules/message-lane/src/mock.rs | 20 +- modules/message-lane/src/weights.rs | 118 +++++---- modules/message-lane/src/weights_ext.rs | 226 ++++++++++++++++-- primitives/message-lane/Cargo.toml | 5 + primitives/message-lane/src/source_chain.rs | 3 +- primitives/message-lane/src/target_chain.rs | 3 +- primitives/millau/src/lib.rs | 7 +- primitives/rialto/src/lib.rs | 7 +- primitives/runtime/src/lib.rs | 10 + relays/substrate-client/src/client.rs | 4 +- relays/substrate/Cargo.toml | 1 + relays/substrate/src/messages_source.rs | 16 +- relays/substrate/src/messages_target.rs | 13 +- .../src/millau_messages_to_rialto.rs | 9 +- .../src/rialto_messages_to_millau.rs | 9 +- 25 files changed, 905 insertions(+), 290 deletions(-) create mode 100644 modules/message-lane/README.md diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 65cd08970f3cd..bf688f5eb19c1 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -623,13 +623,49 @@ where #[cfg(test)] mod tests { use super::*; + use bridge_runtime_common::messages; #[test] fn ensure_millau_message_lane_weights_are_correct() { // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - pallet_message_lane::ensure_weights_are_correct::>( + type Weights = pallet_message_lane::weights::RialtoWeight; + + pallet_message_lane::ensure_weights_are_correct::( bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, ); + + let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( + messages::target::maximal_incoming_message_size(bp_millau::max_extrinsic_size()), + ); + pallet_message_lane::ensure_able_to_receive_message::( + bp_millau::max_extrinsic_size(), + bp_millau::max_extrinsic_weight(), + max_incoming_message_proof_size, + bridge_runtime_common::messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + max_incoming_message_proof_size as _, + 0, + ), + messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()), + ); + + let max_incoming_inbound_lane_data_proof_size = bp_message_lane::InboundLaneData::<()>::encoded_size_hint( + bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, + ) + .unwrap_or(u32::MAX); + pallet_message_lane::ensure_able_to_receive_confirmation::( + bp_millau::max_extrinsic_size(), + bp_millau::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + bridge_runtime_common::messages::transaction_weight_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + max_incoming_inbound_lane_data_proof_size as _, + 0, + ), + ); } } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 4ae8d09d64c3f..9538f18f55426 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -67,10 +67,10 @@ pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePay pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Messages proof for Rialto -> Millau messages. -type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; +type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Millau -> Rialto messages. -type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; +type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; /// Call-dispatch based message dispatch for Rialto -> Millau messages. pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< @@ -97,7 +97,7 @@ impl MessageBridge for WithRialtoMessageBridge { fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = bp_rialto::max_extrinsic_weight() / 2; + let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() @@ -109,13 +109,17 @@ impl MessageBridge for WithRialtoMessageBridge { } fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { + let message_payload_len = u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX); + let extra_bytes_in_payload = + message_payload_len.saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); messages::transaction_weight_without_multiplier( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - u32::try_from(message_payload.len()) - .map(Into::into) - .unwrap_or(Weight::MAX) - .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + message_payload_len.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), + extra_bytes_in_payload + .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + .saturating_add(bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT), ) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 3ebb487fe99bc..d2ade4592af26 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -829,6 +829,7 @@ impl_runtime_apis! { MessageDeliveryProofParams as MessageLaneMessageDeliveryProofParams, MessageParams as MessageLaneMessageParams, MessageProofParams as MessageLaneMessageProofParams, + ProofSize as MessageLaneProofSize, }; impl MessageLaneConfig for Runtime { @@ -882,7 +883,11 @@ impl_runtime_apis! { use pallet_message_lane::storage_keys; use sp_runtime::traits::Header; - let call = Call::System(SystemCall::remark(vec![])); + let remark = match params.size { + MessageLaneProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }; + let call = Call::System(SystemCall::remark(remark)); let call_weight = call.get_dispatch_info().weight; let millau_account_id: bp_millau::AccountId = Default::default(); @@ -939,7 +944,7 @@ impl_runtime_apis! { fn prepare_message_delivery_proof( params: MessageLaneMessageDeliveryProofParams, - ) -> millau_messages::FromMillauMessagesDeliveryProof { + ) -> millau_messages::ToMillauMessagesDeliveryProof { use crate::millau_messages::{Millau, WithMillauMessageBridge}; use bridge_runtime_common::{ messages::ChainWithMessageLanes, @@ -1013,6 +1018,7 @@ where mod tests { use super::*; use bp_currency_exchange::DepositInto; + use bridge_runtime_common::messages; fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) { let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::().unwrap().into(); @@ -1051,10 +1057,45 @@ mod tests { #[test] fn ensure_rialto_message_lane_weights_are_correct() { - pallet_message_lane::ensure_weights_are_correct::>( + type Weights = pallet_message_lane::weights::RialtoWeight; + + pallet_message_lane::ensure_weights_are_correct::( bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, ); + + let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( + messages::target::maximal_incoming_message_size(bp_rialto::max_extrinsic_size()), + ); + pallet_message_lane::ensure_able_to_receive_message::( + bp_rialto::max_extrinsic_size(), + bp_rialto::max_extrinsic_weight(), + max_incoming_message_proof_size, + bridge_runtime_common::messages::transaction_weight_without_multiplier( + bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + max_incoming_message_proof_size as _, + 0, + ), + messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), + ); + + let max_incoming_inbound_lane_data_proof_size = bp_message_lane::InboundLaneData::<()>::encoded_size_hint( + bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, + ) + .unwrap_or(u32::MAX); + pallet_message_lane::ensure_able_to_receive_confirmation::( + bp_rialto::max_extrinsic_size(), + bp_rialto::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + bridge_runtime_common::messages::transaction_weight_without_multiplier( + bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + max_incoming_inbound_lane_data_proof_size as _, + 0, + ), + ); } #[test] diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 222da01f1cd66..2810e888e7b80 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -74,11 +74,10 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi >; /// Messages proof for Millau -> Rialto messages. -pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; +pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Rialto -> Millau messages. -pub type FromMillauMessagesDeliveryProof = - messages::source::FromBridgedChainMessagesDeliveryProof; +pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] @@ -98,7 +97,7 @@ impl MessageBridge for WithMillauMessageBridge { fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = bp_millau::max_extrinsic_weight() / 2; + let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()); // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), // the minimal weight of the message may be computed as message.length() @@ -110,13 +109,17 @@ impl MessageBridge for WithMillauMessageBridge { } fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { + let message_payload_len = u32::try_from(message_payload.len()) + .map(Into::into) + .unwrap_or(Weight::MAX); + let extra_bytes_in_payload = + message_payload_len.saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); messages::transaction_weight_without_multiplier( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - u32::try_from(message_payload.len()) - .map(Into::into) - .unwrap_or(Weight::MAX) - .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + message_payload_len.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), + extra_bytes_in_payload + .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + .saturating_add(bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT), ) } @@ -186,7 +189,7 @@ impl TargetHeaderChain for Millau // - hash of the header this proof has been created with; // - the storage proof of one or several keys; // - id of the lane we prove state of. - type MessagesDeliveryProof = FromMillauMessagesDeliveryProof; + type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { messages::source::verify_chain_message::(payload) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 13b3a4e9458f6..3054334d52df2 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -26,13 +26,13 @@ use bp_message_lane::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_runtime::InstanceId; +use bp_runtime::{InstanceId, Size}; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; -use sp_std::{cmp::PartialOrd, marker::PhantomData, ops::RangeInclusive, vec::Vec}; +use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; /// Bidirectional message bridge. @@ -115,6 +115,9 @@ pub(crate) type BalanceOf = ::Balance; pub(crate) type CallOf = ::Call; pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; +/// Raw storage proof type (just raw trie nodes). +type RawStorageProof = Vec>; + /// Compute weight of transaction at runtime where: /// /// - transaction payment pallet is being used; @@ -160,7 +163,26 @@ pub mod source { /// - hash of finalized header; /// - storage proof of inbound lane state; /// - lane id. - pub type FromBridgedChainMessagesDeliveryProof = (HashOf>, StorageProof, LaneId); + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] + pub struct FromBridgedChainMessagesDeliveryProof { + /// Hash of the bridge header the proof is for. + pub bridged_header_hash: BridgedHeaderHash, + /// Storage trie proof generated for [`Self::bridged_header_hash`]. + pub storage_proof: RawStorageProof, + /// Lane id of which messages were delivered and the proof is for. + pub lane: LaneId, + } + + impl Size for FromBridgedChainMessagesDeliveryProof { + fn size_hint(&self) -> u32 { + u32::try_from( + self.storage_proof + .iter() + .fold(0usize, |sum, node| sum.saturating_add(node.len())), + ) + .unwrap_or(u32::MAX) + } + } /// 'Parsed' message delivery proof - inbound lane id and its state. pub type ParsedMessagesDeliveryProofFromBridgedChain = (LaneId, InboundLaneData>>); @@ -204,7 +226,7 @@ pub mod source { /// Return maximal message size of This -> Bridged chain message. pub fn maximal_message_size() -> u32 { - B::maximal_extrinsic_size_on_target_chain() / 3 * 2 + super::target::maximal_incoming_message_size(B::maximal_extrinsic_size_on_target_chain()) } /// Do basic Bridged-chain specific verification of This -> Bridged chain message. @@ -274,7 +296,7 @@ pub mod source { /// Verify proof of This -> Bridged chain messages delivery. pub fn verify_messages_delivery_proof( - proof: FromBridgedChainMessagesDeliveryProof, + proof: FromBridgedChainMessagesDeliveryProof>>, ) -> Result, &'static str> where ThisRuntime: pallet_substrate_bridge::Config, @@ -282,10 +304,14 @@ pub mod source { HashOf>: Into::BridgedChain>>, { - let (bridged_header_hash, bridged_storage_proof, lane) = proof; + let FromBridgedChainMessagesDeliveryProof { + bridged_header_hash, + storage_proof, + lane, + } = proof; pallet_substrate_bridge::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), - bridged_storage_proof, + StorageProof::new(storage_proof), |storage| { // Messages delivery proof is just proof of single storage key read => any error // is fatal. @@ -332,13 +358,29 @@ pub mod target { /// - storage proof of messages and (optionally) outbound lane state; /// - lane id; /// - nonces (inclusive range) of messages which are included in this proof. - pub type FromBridgedChainMessagesProof = ( - HashOf>, - StorageProof, - LaneId, - MessageNonce, - MessageNonce, - ); + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] + pub struct FromBridgedChainMessagesProof { + /// Hash of the finalized bridged header the proof is for. + pub bridged_header_hash: BridgedHeaderHash, + /// A storage trie proof of messages being delivered. + pub storage_proof: RawStorageProof, + pub lane: LaneId, + /// Nonce of the first message being delivered. + pub nonces_start: MessageNonce, + /// Nonce of the last message being delivered. + pub nonces_end: MessageNonce, + } + + impl Size for FromBridgedChainMessagesProof { + fn size_hint(&self) -> u32 { + u32::try_from( + self.storage_proof + .iter() + .fold(0usize, |sum, node| sum.saturating_add(node.len())), + ) + .unwrap_or(u32::MAX) + } + } /// Encoded Call of This chain as it is transferred over bridge. /// @@ -391,13 +433,23 @@ pub mod target { } } + /// Return maximal dispatch weight of the message we're able to receive. + pub fn maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { + maximal_extrinsic_weight / 2 + } + + /// Return maximal message size given maximal extrinsic size. + pub fn maximal_incoming_message_size(maximal_extrinsic_size: u32) -> u32 { + maximal_extrinsic_size / 3 * 2 + } + /// Verify proof of Bridged -> This chain messages. /// /// The `messages_count` argument verification (sane limits) is supposed to be made /// outside of this function. This function only verifies that the proof declares exactly /// `messages_count` messages. pub fn verify_messages_proof( - proof: FromBridgedChainMessagesProof, + proof: FromBridgedChainMessagesProof>>, messages_count: u32, ) -> Result>>>, &'static str> where @@ -412,7 +464,7 @@ pub mod target { |bridged_header_hash, bridged_storage_proof| { pallet_substrate_bridge::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), - bridged_storage_proof, + StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, ) .map(|storage| StorageProofCheckerAdapter::<_, B, ThisRuntime> { @@ -486,18 +538,24 @@ pub mod target { /// Verify proof of Bridged -> This chain messages using given message proof parser. pub(crate) fn verify_messages_proof_with_parser( - proof: FromBridgedChainMessagesProof, + proof: FromBridgedChainMessagesProof>>, messages_count: u32, build_parser: BuildParser, ) -> Result>>>, MessageProofError> where - BuildParser: FnOnce(HashOf>, StorageProof) -> Result, + BuildParser: FnOnce(HashOf>, RawStorageProof) -> Result, Parser: MessageProofParser, { - let (bridged_header_hash, bridged_storage_proof, lane_id, begin, end) = proof; + let FromBridgedChainMessagesProof { + bridged_header_hash, + storage_proof, + lane, + nonces_start, + nonces_end, + } = proof; // receiving proofs where end < begin is ok (if proof includes outbound lane state) - let messages_in_the_proof = if let Some(nonces_difference) = end.checked_sub(begin) { + let messages_in_the_proof = if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { // let's check that the user (relayer) has passed correct `messages_count` // (this bounds maximal capacity of messages vec below) let messages_in_the_proof = nonces_difference.saturating_add(1); @@ -510,15 +568,15 @@ pub mod target { 0 }; - let parser = build_parser(bridged_header_hash, bridged_storage_proof)?; + let parser = build_parser(bridged_header_hash, storage_proof)?; // Read messages first. All messages that are claimed to be in the proof must // be in the proof. So any error in `read_value`, or even missing value is fatal. // // Mind that we allow proofs with no messages if outbound lane state is proved. let mut messages = Vec::with_capacity(messages_in_the_proof as _); - for nonce in begin..=end { - let message_key = MessageKey { lane_id, nonce }; + for nonce in nonces_start..=nonces_end { + let message_key = MessageKey { lane_id: lane, nonce }; let raw_message_data = parser .read_raw_message(&message_key) .ok_or(MessageProofError::MissingRequiredMessage)?; @@ -536,7 +594,7 @@ pub mod target { lane_state: None, messages, }; - let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane_id); + let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane); if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { proved_lane_messages.lane_state = Some( OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) @@ -551,7 +609,7 @@ pub mod target { // We only support single lane messages in this schema let mut proved_messages = ProvedMessages::new(); - proved_messages.insert(lane_id, proved_lane_messages); + proved_messages.insert(lane, proved_lane_messages); Ok(proved_messages) } @@ -573,7 +631,7 @@ mod tests { const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain; - #[derive(Debug, PartialEq)] + #[derive(Debug, PartialEq, Eq)] struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { @@ -614,7 +672,7 @@ mod tests { } /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from ThisChain; - #[derive(Debug, PartialEq)] + #[derive(Debug, PartialEq, Eq)] struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { @@ -1011,11 +1069,21 @@ mod tests { 1..=0 } + fn messages_proof(nonces_end: MessageNonce) -> target::FromBridgedChainMessagesProof<()> { + target::FromBridgedChainMessagesProof { + bridged_header_hash: (), + storage_proof: vec![], + lane: Default::default(), + nonces_start: 1, + nonces_end, + } + } + #[test] fn messages_proof_is_rejected_if_declared_less_than_actual_number_of_messages() { assert_eq!( target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + messages_proof(10), 5, |_, _| unreachable!(), ), @@ -1027,7 +1095,7 @@ mod tests { fn messages_proof_is_rejected_if_declared_more_than_actual_number_of_messages() { assert_eq!( target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + messages_proof(10), 15, |_, _| unreachable!(), ), @@ -1039,7 +1107,7 @@ mod tests { fn message_proof_is_rejected_if_build_parser_fails() { assert_eq!( target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), + messages_proof(10), 10, |_, _| Err(target::MessageProofError::Custom("test")), ), @@ -1050,15 +1118,13 @@ mod tests { #[test] fn message_proof_is_rejected_if_required_message_is_missing() { assert_eq!( - target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), - 10, - |_, _| Ok(TestMessageProofParser { + target::verify_messages_proof_with_parser::(messages_proof(10), 10, |_, _| Ok( + TestMessageProofParser { failing: false, messages: 1..=5, outbound_lane_data: None, - }), - ), + } + ),), Err(target::MessageProofError::MissingRequiredMessage), ); } @@ -1066,15 +1132,13 @@ mod tests { #[test] fn message_proof_is_rejected_if_message_decode_fails() { assert_eq!( - target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 10), - 10, - |_, _| Ok(TestMessageProofParser { + target::verify_messages_proof_with_parser::(messages_proof(10), 10, |_, _| Ok( + TestMessageProofParser { failing: true, messages: 1..=10, outbound_lane_data: None, - }), - ), + } + ),), Err(target::MessageProofError::FailedToDecodeMessage), ); } @@ -1082,10 +1146,8 @@ mod tests { #[test] fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() { assert_eq!( - target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), - 0, - |_, _| Ok(TestMessageProofParser { + target::verify_messages_proof_with_parser::(messages_proof(0), 0, |_, _| Ok( + TestMessageProofParser { failing: true, messages: no_messages_range(), outbound_lane_data: Some(OutboundLaneData { @@ -1093,8 +1155,8 @@ mod tests { latest_received_nonce: 1, latest_generated_nonce: 1, }), - }), - ), + } + ),), Err(target::MessageProofError::FailedToDecodeOutboundLaneState), ); } @@ -1102,15 +1164,13 @@ mod tests { #[test] fn message_proof_is_rejected_if_it_is_empty() { assert_eq!( - target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), - 0, - |_, _| Ok(TestMessageProofParser { + target::verify_messages_proof_with_parser::(messages_proof(0), 0, |_, _| Ok( + TestMessageProofParser { failing: false, messages: no_messages_range(), outbound_lane_data: None, - }), - ), + } + ),), Err(target::MessageProofError::Empty), ); } @@ -1118,10 +1178,8 @@ mod tests { #[test] fn non_empty_message_proof_without_messages_is_accepted() { assert_eq!( - target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 0), - 0, - |_, _| Ok(TestMessageProofParser { + target::verify_messages_proof_with_parser::(messages_proof(0), 0, |_, _| Ok( + TestMessageProofParser { failing: false, messages: no_messages_range(), outbound_lane_data: Some(OutboundLaneData { @@ -1129,8 +1187,8 @@ mod tests { latest_received_nonce: 1, latest_generated_nonce: 1, }), - }), - ), + } + ),), Ok(vec![( Default::default(), ProvedLaneMessages { @@ -1150,10 +1208,8 @@ mod tests { #[test] fn non_empty_message_proof_is_accepted() { assert_eq!( - target::verify_messages_proof_with_parser::( - (Default::default(), StorageProof::new(vec![]), Default::default(), 1, 1), - 1, - |_, _| Ok(TestMessageProofParser { + target::verify_messages_proof_with_parser::(messages_proof(1), 1, |_, _| Ok( + TestMessageProofParser { failing: false, messages: 1..=1, outbound_lane_data: Some(OutboundLaneData { @@ -1161,8 +1217,8 @@ mod tests { latest_received_nonce: 1, latest_generated_nonce: 1, }), - }), - ), + } + ),), Ok(vec![( Default::default(), ProvedLaneMessages { @@ -1192,13 +1248,7 @@ mod tests { fn verify_messages_proof_with_parser_does_not_panic_if_messages_count_mismatches() { assert_eq!( target::verify_messages_proof_with_parser::( - ( - Default::default(), - StorageProof::new(vec![]), - Default::default(), - 0, - u64::MAX - ), + messages_proof(u64::MAX), 0, |_, _| Ok(TestMessageProofParser { failing: false, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index fdae3a7fcc92e..4aa2abbd6b471 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -32,9 +32,7 @@ use pallet_message_lane::benchmarking::{MessageDeliveryProofParams, MessageProof use sp_core::Hasher; use sp_runtime::traits::Header; use sp_std::prelude::*; -use sp_trie::{ - read_trie_value_with, record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, StorageProof, TrieMut, -}; +use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut}; /// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. /// @@ -71,7 +69,7 @@ pub fn prepare_message_proof( make_bridged_header: MH, message_dispatch_weight: Weight, message_payload: MessagePayload, -) -> (FromBridgedChainMessagesProof, Weight) +) -> (FromBridgedChainMessagesProof>>, Weight) where B: MessageBridge, H: Hasher, @@ -134,13 +132,13 @@ where pallet_substrate_bridge::initialize_for_benchmarks::(bridged_header); ( - ( - bridged_header_hash.into(), - StorageProof::new(storage_proof), - params.lane, - *params.message_nonces.start(), - *params.message_nonces.end(), - ), + FromBridgedChainMessagesProof { + bridged_header_hash: bridged_header_hash.into(), + storage_proof, + lane: params.lane, + nonces_start: *params.message_nonces.start(), + nonces_end: *params.message_nonces.end(), + }, message_dispatch_weight .checked_mul(message_count) .expect("too many messages requested by benchmark"), @@ -152,7 +150,7 @@ pub fn prepare_message_delivery_proof( params: MessageDeliveryProofParams>>, make_bridged_inbound_lane_data_key: ML, make_bridged_header: MH, -) -> FromBridgedChainMessagesDeliveryProof +) -> FromBridgedChainMessagesDeliveryProof>> where B: MessageBridge, H: Hasher, @@ -171,12 +169,13 @@ where .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); } + root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain let mut proof_recorder = Recorder::::new(); - read_trie_value_with::, _, _>(&mdb, &root, &storage_key, &mut proof_recorder) - .map_err(|_| "read_trie_value_with has failed") - .expect("read_trie_value_with should not fail in benchmarks"); + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); // prepare Bridged chain header and insert it into the Substrate pallet @@ -184,17 +183,17 @@ where let bridged_header_hash = bridged_header.hash(); pallet_substrate_bridge::initialize_for_benchmarks::(bridged_header); - ( - bridged_header_hash.into(), - StorageProof::new(storage_proof), - params.lane, - ) + FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: bridged_header_hash.into(), + storage_proof, + lane: params.lane, + } } -/// Populate trie with dummy keys+values until trie has (approximately) at least given size. +/// Populate trie with dummy keys+values until trie has at least given size. fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: ProofSize) -> H::Out { let (iterations, leaf_size, minimal_trie_size) = match trie_size { - ProofSize::Minimal => return root, + ProofSize::Minimal(_) => return root, ProofSize::HasLargeLeaf(size) => (1, size, size), ProofSize::HasExtraNodes(size) => (8, 1, size), }; diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 300b0493912eb..83721a645fdb3 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -14,6 +14,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-rialto = { path = "../../primitives/rialto", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies @@ -35,6 +36,7 @@ default = ["std"] std = [ "bp-message-lane/std", "bp-runtime/std", + "bp-rialto/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/modules/message-lane/README.md b/modules/message-lane/README.md new file mode 100644 index 0000000000000..3213aafe25188 --- /dev/null +++ b/modules/message-lane/README.md @@ -0,0 +1,132 @@ +# Message Lane Module + +The Message Lane Module is used to deliver messages from source to target chain. Message is (almost) opaque to the module and the final goal is to hand message to the message dispatch mechanism. + +## Overview + +*In progress* + +## Weights of module extrinsics + +The main assumptions behind weight formulas is: +- all possible costs are paid in advance by the message submitter; +- whenever possible, relayer tries to minimize cost of its transactions. So e.g. even though sender always pays for delivering outbound lane state proof, relayer may not include it in the delivery transaction (unless message lane module on target chain requires that); +- weight formula should incentivize relayer to not to submit any redundand data in the extrinsics arguments; +- the extrinsic shall never be executing slower (i.e. has larger actual weight) than defined by the formula. + +### Weight of `send_message` call + +#### Related benchmarks + +| Benchmark | Description | +|-----------------------------------|--------------------------------------------------------| +| `send_minimal_message_worst_case` | Sends 0-size message with worst possible conditions | +| `send_1_kb_message_worst_case` | Sends 1KB-size message with worst possible conditions | +| `send_16_kb_message_worst_case` | Sends 16KB-size message with worst possible conditions | + +#### Weight formula + +The weight formula is: +``` +Weight = BaseWeight + MessageSizeInKilobytes * MessageKiloByteSendWeight +``` + +Where: + +| Component | How it is computed? | Description | +|-----------------------------|------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------| +| `SendMessageOverhead` | `send_minimal_message_worst_case` | Weight of sending minimal (0 bytes) message | +| `MessageKiloByteSendWeight` | `(send_16_kb_message_worst_case - send_1_kb_message_worst_case)/15` | Weight of sending every additional kilobyte of the message | + +### Weight of `receive_messages_proof` call + +#### Related benchmarks + +| Benchmark | Description* | +|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------| +| `receive_single_message_proof` | Receives proof of single `EXPECTED_DEFAULT_MESSAGE_LENGTH` message | +| `receive_two_messages_proof` | Receives proof of two identical `EXPECTED_DEFAULT_MESSAGE_LENGTH` messages | +| `receive_single_message_proof_with_outbound_lane_state` | Receives proof of single `EXPECTED_DEFAULT_MESSAGE_LENGTH` message and proof of outbound lane state at the source chain | +| `receive_single_message_proof_1_kb` | Receives proof of single message. The proof has size of approximately 1KB** | +| `receive_single_message_proof_16_kb` | Receives proof of single message. The proof has size of approximately 16KB** | + +*\* - In all benchmarks all received messages are dispatched and their dispatch cost is near to zero* + +*\*\* - Trie leafs are assumed to have minimal values. The proof is derived from the minimal proof by including more trie nodes. That's because according to `receive_message_proofs_with_large_leaf` and `receive_message_proofs_with_extra_nodes` benchmarks, increasing proof by including more nodes has slightly larger impact on performance than increasing values stored in leafs*. + +#### Weight formula + +The weight formula is: +``` +Weight = BaseWeight + OutboundStateDeliveryWeight + MessagesCount * MessageDeliveryWeight + MessagesDispatchWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight +``` + +Where: + +| Component | How it is computed? | Description | +|-------------------------------|------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `BaseWeight` | `2*receive_single_message_proof - receive_two_messages_proof` | Weight of receiving and parsing minimal proof | +| `OutboundStateDeliveryWeight` | `receive_single_message_proof_with_outbound_lane_state - receive_single_message_proof` | Additional weight when proof includes outbound lane state | +| `MessageDeliveryWeight` | `receive_two_messages_proof - receive_single_message_proof` | Weight of of parsing and dispatching (without actual dispatch cost) of every message | +| `MessagesCount` | | Provided by relayer | +| `MessagesDispatchWeight` | | Provided by relayer | +| `ActualProofSize` | | Provided by relayer | +| `ExpectedProofSize` | `EXPECTED_DEFAULT_MESSAGE_LENGTH * MessagesCount + EXTRA_STORAGE_PROOF_SIZE` | Size of proof that we are expecting. This only includes `EXTRA_STORAGE_PROOF_SIZE` once, because we assume that intermediate nodes likely to be included in the proof only once. This may be wrong, but since weight of processing proof with many nodes is almost equal to processing proof with large leafs, additional cost will be covered because we're charging for extra proof bytes anyway | +| `ProofByteDeliveryWeight` | `(receive_single_message_proof_16_kb - receive_single_message_proof_1_kb) / (15 * 1024)` | Weight of processing every additional proof byte over `ExpectedProofSize` limit | + +#### Why for every message sent using `send_message` we will be able to craft `receive_messages_proof` transaction? + +We have following checks in `send_message` transaction on the source chain: +- message size should be less than or equal to `2/3` of maximal extrinsic size on the target chain; +- message dispatch weight should be less than or equal to the `1/2` of maximal extrinsic dispatch weight on the target chain. + +Delivery transaction is an encoded delivery call and signed extensions. So we have `1/3` of maximal extrinsic size reserved for: +- storage proof, excluding the message itself. Currently, on our test chains, the overhead is always within `EXTRA_STORAGE_PROOF_SIZE` limits (1024 bytes); +- signed extras and other call arguments (`relayer_id: SourceChain::AccountId`, `messages_count: u32`, `dispatch_weight: u64`). + +On Millau chain, maximal extrinsic size is `0.75 * 2MB`, so `1/3` is `512KB` (`524_288` bytes). This should be enough to cover these extra arguments and signed extensions. + +Let's exclude message dispatch cost from single message delivery transaction weight formula: +``` +Weight = BaseWeight + OutboundStateDeliveryWeight + MessageDeliveryWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight +``` + +So we have `1/2` of maximal extrinsic weight to cover these components. `BaseWeight`, `OutboundStateDeliveryWeight` and `MessageDeliveryWeight` are determined using benchmarks and are hardcoded into runtime. Adequate relayer would only include required trie nodes into the proof. So if message size would be maximal (`2/3` of `MaximalExtrinsicSize`), then the extra proof size would be `MaximalExtrinsicSize / 3 * 2 - EXPECTED_DEFAULT_MESSAGE_LENGTH`. + +Both conditions are verified by `pallet_message_lane::ensure_weights_are_correct` and `pallet_message_lane::ensure_able_to_receive_messages` functions, which must be called from every runtime' tests. + +### Weight of `receive_messages_delivery_proof` call + +#### Related benchmarks + +| Benchmark | Description | +|-------------------------------------------------------------|------------------------------------------------------------------------------------------| +| `receive_delivery_proof_for_single_message` | Receives proof of single message delivery | +| `receive_delivery_proof_for_two_messages_by_single_relayer` | Receives proof of two messages delivery. Both messages are delivered by the same relayer | +| `receive_delivery_proof_for_two_messages_by_two_relayers` | Receives proof of two messages delivery. Messages are delivered by different relayers | + +#### Weight formula + +The weight formula is: +``` +Weight = BaseWeight + MessagesCount * MessageConfirmationWeight + RelayersCount * RelayerRewardWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight +``` + +Where: + +| Component | How it is computed? | Description | +|---------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `BaseWeight` | `2*receive_delivery_proof_for_single_message - receive_delivery_proof_for_two_messages_by_single_relayer` | Weight of receiving and parsing minimal delivery proof | +| `MessageDeliveryWeight` | `receive_delivery_proof_for_two_messages_by_single_relayer - receive_delivery_proof_for_single_message` | Weight of confirming every additional message | +| `MessagesCount` | | Provided by relayer | +| `RelayerRewardWeight` | `receive_delivery_proof_for_two_messages_by_two_relayers - receive_delivery_proof_for_two_messages_by_single_relayer` | Weight of rewarding every additional relayer | +| `RelayersCount` | | Provided by relayer | +| `ActualProofSize` | | Provided by relayer | +| `ExpectedProofSize` | `EXTRA_STORAGE_PROOF_SIZE` | Size of proof that we are expecting | +| `ProofByteDeliveryWeight` | `(receive_single_message_proof_16_kb - receive_single_message_proof_1_kb) / (15 * 1024)` | Weight of processing every additional proof byte over `ExpectedProofSize` limit. We're using the same formula, as for message delivery, because proof mechanism is assumed to be the same in both cases | + +#### Why we're always able to craft `receive_messages_delivery_proof` transaction? + +There can be at most `::MaxUnconfirmedMessagesAtInboundLane` messages and at most `::MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers in the single delivery confirmation transaction. + +We're checking that this transaction may be crafted in the `pallet_message_lane::ensure_able_to_receive_confirmation` function, which must be called from every runtime' tests. diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index 0ad445385f2db..675bc310f59ab 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -16,6 +16,7 @@ //! Message lane pallet benchmarking. +use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH; use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance}; use bp_message_lane::{ @@ -37,8 +38,9 @@ pub struct Module, I: crate::Instance>(crate::Module); /// Proof size requirements. pub enum ProofSize { - /// The proof is expected to be minimal. - Minimal, + /// The proof is expected to be minimal. If value size may be changed, then it is expected to + /// have given size. + Minimal(u32), /// The proof is expected to have at least given size and grow by increasing number of trie nodes /// included in the proof. HasExtraNodes(u32), @@ -73,6 +75,8 @@ pub struct MessageDeliveryProofParams { pub lane: LaneId, /// The proof needs to include this inbound lane data. pub inbound_lane_data: InboundLaneData, + /// Proof size requirements. + pub size: ProofSize, } /// Trait that must be implemented by runtime. @@ -224,17 +228,20 @@ benchmarks_instance! { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + // mark messages 1..=20 as delivered + receive_messages::(20); + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { lane: bench_lane_id(), - message_nonces: 1..=1, + message_nonces: 21..=21, outbound_lane_data: None, - size: ProofSize::Minimal, + size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), - 1, + 21, ); } @@ -252,17 +259,20 @@ benchmarks_instance! { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + // mark messages 1..=20 as delivered + receive_messages::(20); + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { lane: bench_lane_id(), - message_nonces: 1..=2, + message_nonces: 21..=22, outbound_lane_data: None, - size: ProofSize::Minimal, + size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), - 2, + 22, ); } @@ -291,7 +301,7 @@ benchmarks_instance! { latest_received_nonce: 20, latest_generated_nonce: 21, }), - size: ProofSize::Minimal, + size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -305,6 +315,68 @@ benchmarks_instance! { ); } + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * the proof has many redundand trie nodes with total size of approximately 1KB; + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // With single KB of messages proof, the weight of the call is increased (roughly) by + // `(receive_single_message_proof_16KB - receive_single_message_proof_1_kb) / 15`. + receive_single_message_proof_1_kb { + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + size: ProofSize::HasExtraNodes(1024), + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 21, + ); + } + + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * the proof has many redundand trie nodes with total size of approximately 16KB; + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher. + // + // Size of proof grows because it contains extra trie nodes in it. + // + // With single KB of messages proof, the weight of the call is increased (roughly) by + // `(receive_single_message_proof_16KB - receive_single_message_proof) / 15`. + receive_single_message_proof_16_kb { + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + size: ProofSize::HasExtraNodes(16 * 1024), + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) + verify { + assert_eq!( + crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + 21, + ); + } + // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: // * single relayer is rewarded for relaying single message; // * relayer account does not exist (in practice it needs to exist in production environment). @@ -329,7 +401,8 @@ benchmarks_instance! { inbound_lane_data: InboundLaneData { relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(), last_confirmed_nonce: 0, - } + }, + size: ProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { @@ -366,7 +439,8 @@ benchmarks_instance! { inbound_lane_data: InboundLaneData { relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(), last_confirmed_nonce: 0, - } + }, + size: ProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { @@ -405,7 +479,8 @@ benchmarks_instance! { (2, 2, relayer2_id.clone()), ].into_iter().collect(), last_confirmed_nonce: 0, - } + }, + size: ProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) verify { @@ -459,17 +534,20 @@ benchmarks_instance! { // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. So it may be used // to verify that the other approximation is correct. receive_multiple_messages_proof { - let i in 1..128; + let i in 1..64; let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); let messages_count = i as _; + // mark messages 1..=20 as delivered + receive_messages::(20); + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { lane: bench_lane_id(), - message_nonces: 1..=i as _, + message_nonces: 21..=(20 + i as MessageNonce), outbound_lane_data: None, - size: ProofSize::Minimal, + size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -481,38 +559,32 @@ benchmarks_instance! { verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), - i as MessageNonce, + 20 + i as MessageNonce, ); } - // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: - // * proof includes outbound lane state proof; + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; // * message is successfully dispatched; // * message requires all heavy checks done by dispatcher. // - // This benchmarks gives us an approximation of outbound lane state delivery weight. It is similar to the - // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. - // So it may be used to verify that the other approximation is correct. - receive_multiple_messages_proof_with_outbound_lane_state { - let i in 1..128; + // Results of this benchmark may be used to check how proof size affects `receive_message_proof` performance. + receive_message_proofs_with_extra_nodes { + let i in 0..T::maximal_message_size(); let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = i as _; + let messages_count = 1u32; // mark messages 1..=20 as delivered receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { lane: bench_lane_id(), - message_nonces: 21..=20 + i as MessageNonce, - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 21, - latest_received_nonce: 20, - latest_generated_nonce: 21, - }), - size: ProofSize::Minimal, + message_nonces: 21..=21, + outbound_lane_data: None, + size: ProofSize::HasExtraNodes(i as _), }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -524,11 +596,7 @@ benchmarks_instance! { verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), - 20 + i as MessageNonce, - ); - assert_eq!( - crate::Module::::inbound_latest_confirmed_nonce(bench_lane_id()), - 20, + 21, ); } @@ -538,8 +606,8 @@ benchmarks_instance! { // * message is successfully dispatched; // * message requires all heavy checks done by dispatcher. // - // Results of this benchmark may be used to check how extra nodes in proof affect transaction performance. - receive_message_proofs_with_extra_nodes { + // Results of this benchmark may be used to check how message size affects `receive_message_proof` performance. + receive_message_proofs_with_large_leaf { let i in 0..T::maximal_message_size(); let relayer_id_on_source = T::bridged_relayer_id(); @@ -553,7 +621,7 @@ benchmarks_instance! { lane: bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: ProofSize::HasExtraNodes(i as _), + size: ProofSize::HasLargeLeaf(i as _), }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -569,28 +637,34 @@ benchmarks_instance! { ); } - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * proof does not include outbound lane state proof; + // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: + // * proof includes outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; // * message is successfully dispatched; // * message requires all heavy checks done by dispatcher. // - // Results of this benchmark may be used to check how large (extra) leaf in proof affect transaction performance. - receive_message_proofs_with_large_leaf { - let i in 0..T::maximal_message_size(); + // This benchmarks gives us an approximation of outbound lane state delivery weight. It is similar to the + // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. + // So it may be used to verify that the other approximation is correct. + receive_multiple_messages_proof_with_outbound_lane_state { + let i in 1..128; let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = 1u32; + let messages_count = i as _; // mark messages 1..=20 as delivered receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { lane: bench_lane_id(), - message_nonces: 21..=21, - outbound_lane_data: None, - size: ProofSize::HasLargeLeaf(i as _), + message_nonces: 21..=20 + i as MessageNonce, + outbound_lane_data: Some(OutboundLaneData { + oldest_unpruned_nonce: 21, + latest_received_nonce: 20, + latest_generated_nonce: 21, + }), + size: ProofSize::Minimal(0), }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -602,7 +676,11 @@ benchmarks_instance! { verify { assert_eq!( crate::Module::::inbound_latest_received_nonce(bench_lane_id()), - 21, + 20 + i as MessageNonce, + ); + assert_eq!( + crate::Module::::inbound_latest_confirmed_nonce(bench_lane_id()), + 20, ); } @@ -634,7 +712,8 @@ benchmarks_instance! { inbound_lane_data: InboundLaneData { relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(), last_confirmed_nonce: 0, - } + }, + size: ProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { @@ -679,7 +758,8 @@ benchmarks_instance! { .map(|(j, relayer_id)| (j as MessageNonce + 1, j as MessageNonce + 1, relayer_id.clone())) .collect(), last_confirmed_nonce: 0, - } + }, + size: ProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) verify { diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index eccebc1fcc9de..c14ccdb45546c 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -35,7 +35,10 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use crate::weights_ext::{ensure_weights_are_correct, WeightInfoExt}; +pub use crate::weights_ext::{ + ensure_able_to_receive_confirmation, ensure_able_to_receive_message, ensure_weights_are_correct, WeightInfoExt, + EXPECTED_DEFAULT_MESSAGE_LENGTH, +}; use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; @@ -267,9 +270,7 @@ decl_module! { } /// Send message over lane. - #[weight = T::WeightInfo::send_message_overhead() - .saturating_add(T::WeightInfo::send_message_size_overhead(Size::size_hint(payload))) - ] + #[weight = T::WeightInfo::send_message_weight(payload)] pub fn send_message( origin, lane_id: LaneId, @@ -351,11 +352,7 @@ decl_module! { /// The weight of the call assumes that the transaction always brings outbound lane /// state update. Because of that, the submitter (relayer) has no benefit of not including /// this data in the transaction, so reward confirmations lags should be minimal. - #[weight = T::WeightInfo::receive_messages_proof_overhead() - .saturating_add(T::WeightInfo::receive_messages_proof_outbound_lane_state_overhead()) - .saturating_add(T::WeightInfo::receive_messages_proof_messages_overhead(MessageNonce::from(*messages_count))) - .saturating_add(*dispatch_weight) - ] + #[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)] pub fn receive_messages_proof( origin, relayer_id: T::InboundRelayer, @@ -444,14 +441,7 @@ decl_module! { } /// Receive messages delivery proof from bridged chain. - #[weight = T::WeightInfo::receive_messages_delivery_proof_overhead() - .saturating_add(T::WeightInfo::receive_messages_delivery_proof_messages_overhead( - relayers_state.total_messages - )) - .saturating_add(T::WeightInfo::receive_messages_delivery_proof_relayers_overhead( - relayers_state.unrewarded_relayer_entries - )) - ] + #[weight = T::WeightInfo::receive_messages_delivery_proof_weight(proof, relayers_state)] pub fn receive_messages_delivery_proof( origin, proof: MessagesDeliveryProofOf, @@ -774,8 +764,9 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesProof, TestPayload, - TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, + TestMessagesProof, TestPayload, TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, + TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_message_lane::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; @@ -814,13 +805,13 @@ mod tests { assert_ok!(Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok(( + TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, ..Default::default() }, - )), + ))), Default::default(), )); @@ -924,13 +915,13 @@ mod tests { assert_noop!( Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok(( + TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, ..Default::default() }, - )), + ))), Default::default(), ), Error::::Halted, @@ -1140,13 +1131,13 @@ mod tests { // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A assert_ok!(Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok(( + TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { relayers: vec![(1, 1, TEST_RELAYER_A)].into_iter().collect(), ..Default::default() } - )), + ))), UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 1, @@ -1165,7 +1156,7 @@ mod tests { // this reports delivery of both message 1 and message 2 => reward is paid only to TEST_RELAYER_B assert_ok!(Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok(( + TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] @@ -1173,7 +1164,7 @@ mod tests { .collect(), ..Default::default() } - )), + ))), UnrewardedRelayersState { unrewarded_relayer_entries: 2, total_messages: 2, @@ -1195,7 +1186,11 @@ mod tests { fn receive_messages_delivery_proof_rejects_invalid_proof() { run_test(|| { assert_noop!( - Module::::receive_messages_delivery_proof(Origin::signed(1), Err(()), Default::default(),), + Module::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Err(())), + Default::default(), + ), Error::::InvalidMessagesDeliveryProof, ); }); @@ -1208,7 +1203,7 @@ mod tests { assert_noop!( Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok(( + TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] @@ -1216,7 +1211,7 @@ mod tests { .collect(), ..Default::default() } - )), + ))), UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 2, @@ -1230,7 +1225,7 @@ mod tests { assert_noop!( Module::::receive_messages_delivery_proof( Origin::signed(1), - Ok(( + TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] @@ -1238,7 +1233,7 @@ mod tests { .collect(), ..Default::default() } - )), + ))), UnrewardedRelayersState { unrewarded_relayer_entries: 2, total_messages: 1, diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 94f570a84d317..4d1bb488908b8 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -183,6 +183,12 @@ pub struct TestMessagesProof { pub result: Result, } +impl Size for TestMessagesProof { + fn size_hint(&self) -> u32 { + 0 + } +} + impl From>, ()>> for TestMessagesProof { fn from(result: Result>, ()>) -> Self { Self { @@ -202,6 +208,16 @@ impl From>, ()>> for TestMessagesProof { } } +/// Messages delivery proof used in tests. +#[derive(Debug, Encode, Decode, Eq, Clone, PartialEq)] +pub struct TestMessagesDeliveryProof(pub Result<(LaneId, InboundLaneData), ()>); + +impl Size for TestMessagesDeliveryProof { + fn size_hint(&self) -> u32 { + 0 + } +} + /// Target header chain that is used in tests. #[derive(Debug, Default)] pub struct TestTargetHeaderChain; @@ -209,7 +225,7 @@ pub struct TestTargetHeaderChain; impl TargetHeaderChain for TestTargetHeaderChain { type Error = &'static str; - type MessagesDeliveryProof = Result<(LaneId, InboundLaneData), ()>; + type MessagesDeliveryProof = TestMessagesDeliveryProof; fn verify_message(payload: &TestPayload) -> Result<(), Self::Error> { if *payload == PAYLOAD_REJECTED_BY_TARGET_CHAIN { @@ -222,7 +238,7 @@ impl TargetHeaderChain for TestTargetHeaderChain { fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - proof.map_err(|_| TEST_ERROR) + proof.0.map_err(|_| TEST_ERROR) } } diff --git a/modules/message-lane/src/weights.rs b/modules/message-lane/src/weights.rs index 33a84ecbafa9c..44ce61020ee6c 100644 --- a/modules/message-lane/src/weights.rs +++ b/modules/message-lane/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_message_lane //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1 -//! DATE: 2021-01-25, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-02-01, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("local"), DB CACHE: 128 @@ -54,14 +54,16 @@ pub trait WeightInfo { fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; fn receive_single_message_proof_with_outbound_lane_state() -> Weight; + fn receive_single_message_proof_1_kb() -> Weight; + fn receive_single_message_proof_16_kb() -> Weight; fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; fn send_messages_of_various_lengths(i: u32) -> Weight; fn receive_multiple_messages_proof(i: u32) -> Weight; - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight; fn receive_message_proofs_with_large_leaf(i: u32) -> Weight; + fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight; fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } @@ -70,90 +72,100 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (123_511_000 as Weight) + (138_421_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (132_218_000 as Weight) + (142_633_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (187_458_000 as Weight) + (194_483_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_single_message_proof() -> Weight { - (156_005_000 as Weight) + (154_651_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (266_292_000 as Weight) + (271_722_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (171_319_000 as Weight) + (170_821_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_single_message_proof_1_kb() -> Weight { + (189_540_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn receive_single_message_proof_16_kb() -> Weight { + (484_899_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (127_537_000 as Weight) + (145_328_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (135_281_000 as Weight) + (150_165_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (180_862_000 as Weight) + (215_954_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (98_452_000 as Weight) + (117_961_000 as Weight) .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((124_098_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((128_267_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((117_783_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (437_756_000 as Weight) + (448_951_000 as Weight) .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (164_484_000 as Weight) + (97_174_000 as Weight) .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { + (0 as Weight) + .saturating_add((120_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (122_609_000 as Weight) - .saturating_add((7_289_000 as Weight).saturating_mul(i as Weight)) + (132_970_000 as Weight) + .saturating_add((7_243_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (129_622_000 as Weight) - .saturating_add((53_214_000 as Weight).saturating_mul(i as Weight)) + (62_936_000 as Weight) + .saturating_add((67_932_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -164,90 +176,100 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (123_511_000 as Weight) + (138_421_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (132_218_000 as Weight) + (142_633_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (187_458_000 as Weight) + (194_483_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_single_message_proof() -> Weight { - (156_005_000 as Weight) + (154_651_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (266_292_000 as Weight) + (271_722_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (171_319_000 as Weight) + (170_821_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_single_message_proof_1_kb() -> Weight { + (189_540_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn receive_single_message_proof_16_kb() -> Weight { + (484_899_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (127_537_000 as Weight) + (145_328_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (135_281_000 as Weight) + (150_165_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (180_862_000 as Weight) + (215_954_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (98_452_000 as Weight) + (117_961_000 as Weight) .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((124_098_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((128_267_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((117_783_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (437_756_000 as Weight) + (448_951_000 as Weight) .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (164_484_000 as Weight) + (97_174_000 as Weight) .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { + (0 as Weight) + .saturating_add((120_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (122_609_000 as Weight) - .saturating_add((7_289_000 as Weight).saturating_mul(i as Weight)) + (132_970_000 as Weight) + .saturating_add((7_243_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (129_622_000 as Weight) - .saturating_add((53_214_000 as Weight).saturating_mul(i as Weight)) + (62_936_000 as Weight) + .saturating_add((67_932_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/modules/message-lane/src/weights_ext.rs b/modules/message-lane/src/weights_ext.rs index 95bc8239a9463..18d80159a1b80 100644 --- a/modules/message-lane/src/weights_ext.rs +++ b/modules/message-lane/src/weights_ext.rs @@ -18,52 +18,213 @@ use crate::weights::WeightInfo; -use bp_message_lane::MessageNonce; +use bp_message_lane::{MessageNonce, UnrewardedRelayersState}; +use bp_runtime::{PreComputedSize, Size}; use frame_support::weights::Weight; +/// Size of the message being delivered in benchmarks. +pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128; + +/// We assume that size of signed extensions on all our chains and size of all 'small' arguments of calls +/// we're checking here would fit 1KB. +const SIGNED_EXTENSIONS_SIZE: u32 = 1024; + /// Ensure that weights from `WeightInfoExt` implementation are looking correct. pub fn ensure_weights_are_correct( - expected_max_single_message_delivery_tx_weight: Weight, - expected_max_messages_delivery_tx_weight: Weight, + expected_single_regular_message_delivery_tx_weight: Weight, + expected_messages_delivery_confirmation_tx_weight: Weight, ) { + // verify `send_message` weight components assert_ne!(W::send_message_overhead(), 0); assert_ne!(W::send_message_size_overhead(0), 0); + // verify `receive_messages_proof` weight components assert_ne!(W::receive_messages_proof_overhead(), 0); assert_ne!(W::receive_messages_proof_messages_overhead(1), 0); assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), 0); + assert_ne!(W::storage_proof_size_overhead(1), 0); - let actual_max_single_message_delivery_tx_weight = W::receive_messages_proof_overhead() - .checked_add(W::receive_messages_proof_messages_overhead(1)) - .expect("weights are too large") - .checked_add(W::receive_messages_proof_outbound_lane_state_overhead()) - .expect("weights are too large"); + // verify that the hardcoded value covers `receive_messages_proof` weight + let actual_single_regular_message_delivery_tx_weight = W::receive_messages_proof_weight( + &PreComputedSize((EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize), + 1, + 0, + ); assert!( - actual_max_single_message_delivery_tx_weight <= expected_max_single_message_delivery_tx_weight, + actual_single_regular_message_delivery_tx_weight <= expected_single_regular_message_delivery_tx_weight, "Single message delivery transaction weight {} is larger than expected weight {}", - actual_max_single_message_delivery_tx_weight, - expected_max_single_message_delivery_tx_weight, + actual_single_regular_message_delivery_tx_weight, + expected_single_regular_message_delivery_tx_weight, ); + // verify `receive_messages_delivery_proof` weight components assert_ne!(W::receive_messages_delivery_proof_overhead(), 0); assert_ne!(W::receive_messages_delivery_proof_messages_overhead(1), 0); assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1), 0); + assert_ne!(W::storage_proof_size_overhead(1), 0); - let actual_max_messages_delivery_tx_weight = W::receive_messages_delivery_proof_overhead() - .checked_add(W::receive_messages_delivery_proof_messages_overhead(1)) - .expect("weights are too large") - .checked_add(W::receive_messages_delivery_proof_relayers_overhead(1)) - .expect("weights are too large"); + // verify that the hardcoded value covers `receive_messages_delivery_proof` weight + let actual_messages_delivery_confirmation_tx_weight = W::receive_messages_delivery_proof_weight( + &PreComputedSize(W::expected_extra_storage_proof_size() as usize), + &UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + ); assert!( - actual_max_messages_delivery_tx_weight <= expected_max_messages_delivery_tx_weight, + actual_messages_delivery_confirmation_tx_weight <= expected_messages_delivery_confirmation_tx_weight, "Messages delivery confirmation transaction weight {} is larger than expected weight {}", - actual_max_messages_delivery_tx_weight, - expected_max_messages_delivery_tx_weight, + actual_messages_delivery_confirmation_tx_weight, + expected_messages_delivery_confirmation_tx_weight, + ); +} + +/// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain. +pub fn ensure_able_to_receive_message( + max_extrinsic_size: u32, + max_extrinsic_weight: Weight, + max_incoming_message_proof_size: u32, + // This is a base weight (which includes cost of tx itself, per-byte cost, adjusted per-byte cost) of single + // message delivery transaction that brings `max_incoming_message_proof_size` proof. + max_incoming_message_proof_base_weight: Weight, + max_incoming_message_dispatch_weight: Weight, +) { + // verify that we're able to receive proof of maximal-size message + let max_delivery_transaction_size = max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE); + assert!( + max_delivery_transaction_size <= max_extrinsic_size, + "Size of maximal message delivery transaction {} + {} is larger than maximal possible transaction size {}", + max_incoming_message_proof_size, + SIGNED_EXTENSIONS_SIZE, + max_extrinsic_size, + ); + + // verify that we're able to receive proof of maximal-size message with maximal dispatch weight + let max_delivery_transaction_dispatch_weight = W::receive_messages_proof_weight( + &PreComputedSize((max_incoming_message_proof_size + W::expected_extra_storage_proof_size()) as usize), + 1, + max_incoming_message_dispatch_weight, + ); + let max_delivery_transaction_weight = + max_incoming_message_proof_base_weight.saturating_add(max_delivery_transaction_dispatch_weight); + assert!( + max_delivery_transaction_weight <= max_extrinsic_weight, + "Weight of maximal message delivery transaction {} + {} is larger than maximal possible transaction weight {}", + max_delivery_transaction_weight, + max_delivery_transaction_dispatch_weight, + max_extrinsic_weight, + ); +} + +/// Ensure that we're able to receive maximal confirmation from other chain. +pub fn ensure_able_to_receive_confirmation( + max_extrinsic_size: u32, + max_extrinsic_weight: Weight, + max_inbound_lane_data_proof_size_from_peer_chain: u32, + max_unrewarded_relayer_entries_at_peer_inbound_lane: MessageNonce, + max_unconfirmed_messages_at_inbound_lane: MessageNonce, + // This is a base weight (which includes cost of tx itself, per-byte cost, adjusted per-byte cost) of single + // confirmation transaction that brings `max_inbound_lane_data_proof_size_from_peer_chain` proof. + max_incoming_delivery_proof_base_weight: Weight, +) { + // verify that we're able to receive confirmation of maximal-size + let max_confirmation_transaction_size = + max_inbound_lane_data_proof_size_from_peer_chain.saturating_add(SIGNED_EXTENSIONS_SIZE); + assert!( + max_confirmation_transaction_size <= max_extrinsic_size, + "Size of maximal message delivery confirmation transaction {} + {} is larger than maximal possible transaction size {}", + max_inbound_lane_data_proof_size_from_peer_chain, + SIGNED_EXTENSIONS_SIZE, + max_extrinsic_size, + ); + + // verify that we're able to reward maximal number of relayers that have delivered maximal number of messages + let max_confirmation_transaction_dispatch_weight = W::receive_messages_delivery_proof_weight( + &PreComputedSize(max_inbound_lane_data_proof_size_from_peer_chain as usize), + &UnrewardedRelayersState { + unrewarded_relayer_entries: max_unrewarded_relayer_entries_at_peer_inbound_lane, + total_messages: max_unconfirmed_messages_at_inbound_lane, + ..Default::default() + }, + ); + let max_confirmation_transaction_weight = + max_incoming_delivery_proof_base_weight.saturating_add(max_confirmation_transaction_dispatch_weight); + assert!( + max_confirmation_transaction_weight <= max_extrinsic_weight, + "Weight of maximal confirmation transaction {} + {} is larger than maximal possible transaction weight {}", + max_incoming_delivery_proof_base_weight, + max_confirmation_transaction_dispatch_weight, + max_extrinsic_weight, ); } /// Extended weight info. pub trait WeightInfoExt: WeightInfo { + /// Size of proof that is already included in the single message delivery weight. + /// + /// The message submitter (at source chain) has already covered this cost. But there are two + /// factors that may increase proof size: (1) the message size may be larger than predefined + /// and (2) relayer may add extra trie nodes to the proof. So if proof size is larger than + /// this value, we're going to charge relayer for that. + fn expected_extra_storage_proof_size() -> u32; + + // Functions that are directly mapped to extrinsics weights. + + /// Weight of message send extrinsic. + fn send_message_weight(message: &impl Size) -> Weight { + let transaction_overhead = Self::send_message_overhead(); + let message_size_overhead = Self::send_message_size_overhead(message.size_hint()); + + transaction_overhead.saturating_add(message_size_overhead) + } + + /// Weight of message delivery extrinsic. + fn receive_messages_proof_weight(proof: &impl Size, messages_count: u32, dispatch_weight: Weight) -> Weight { + // basic components of extrinsic weight + let transaction_overhead = Self::receive_messages_proof_overhead(); + let outbound_state_delivery_weight = Self::receive_messages_proof_outbound_lane_state_overhead(); + let messages_delivery_weight = + Self::receive_messages_proof_messages_overhead(MessageNonce::from(messages_count)); + let messages_dispatch_weight = dispatch_weight; + + // proof size overhead weight + let expected_proof_size = EXPECTED_DEFAULT_MESSAGE_LENGTH + .saturating_mul(messages_count.saturating_sub(1)) + .saturating_add(Self::expected_extra_storage_proof_size()); + let actual_proof_size = proof.size_hint(); + let proof_size_overhead = + Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size)); + + transaction_overhead + .saturating_add(outbound_state_delivery_weight) + .saturating_add(messages_delivery_weight) + .saturating_add(messages_dispatch_weight) + .saturating_add(proof_size_overhead) + } + + /// Weight of confirmation delivery extrinsic. + fn receive_messages_delivery_proof_weight(proof: &impl Size, relayers_state: &UnrewardedRelayersState) -> Weight { + // basic components of extrinsic weight + let transaction_overhead = Self::receive_messages_delivery_proof_overhead(); + let messages_overhead = Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages); + let relayers_overhead = + Self::receive_messages_delivery_proof_relayers_overhead(relayers_state.unrewarded_relayer_entries); + + // proof size overhead weight + let expected_proof_size = Self::expected_extra_storage_proof_size(); + let actual_proof_size = proof.size_hint(); + let proof_size_overhead = + Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size)); + + transaction_overhead + .saturating_add(messages_overhead) + .saturating_add(relayers_overhead) + .saturating_add(proof_size_overhead) + } + + // Functions that are used by extrinsics weights formulas. + /// Returns weight of message send transaction (`send_message`). fn send_message_overhead() -> Weight { Self::send_minimal_message_worst_case() @@ -130,6 +291,31 @@ pub trait WeightInfoExt: WeightInfo { .saturating_sub(weight_of_two_messages_by_single_relayer) .saturating_mul(relayers as Weight) } + + /// Returns weight that needs to be accounted when storage proof of given size is recieved (either in + /// `receive_messages_proof` or `receive_messages_delivery_proof`). + /// + /// **IMPORTANT**: this overhead is already included in the 'base' transaction cost - e.g. proof + /// size depends on messages count or number of entries in the unrewarded relayers set. So this + /// shouldn't be added to cost of transaction, but instead should act as a minimal cost that the + /// relayer must pay when it relays proof of given size (even if cost based on other parameters + /// is less than that cost). + fn storage_proof_size_overhead(proof_size: u32) -> Weight { + let proof_size_in_bytes = proof_size as Weight; + let byte_weight = + (Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024); + proof_size_in_bytes * byte_weight + } } -impl WeightInfoExt for T {} +impl WeightInfoExt for () { + fn expected_extra_storage_proof_size() -> u32 { + bp_rialto::EXTRA_STORAGE_PROOF_SIZE + } +} + +impl WeightInfoExt for crate::weights::RialtoWeight { + fn expected_extra_storage_proof_size() -> u32 { + bp_rialto::EXTRA_STORAGE_PROOF_SIZE + } +} diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index 87088aed64d58..e002ccd36a235 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -9,6 +9,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +# Bridge dependencies + +bp-runtime = { path = "../runtime", default-features = false } + # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -18,6 +22,7 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master [features] default = ["std"] std = [ + "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index 813188bd79134..1c47d8c6debb7 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -18,6 +18,7 @@ use crate::{InboundLaneData, LaneId, MessageNonce}; +use bp_runtime::Size; use frame_support::{Parameter, RuntimeDebug}; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug}; @@ -46,7 +47,7 @@ pub trait TargetHeaderChain { type Error: Debug + Into<&'static str>; /// Proof that messages have been received by target chain. - type MessagesDeliveryProof: Parameter; + type MessagesDeliveryProof: Parameter + Size; /// Verify message payload before we accept it. /// diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index c79b534156f64..825fe67c54915 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -18,6 +18,7 @@ use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; +use bp_runtime::Size; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*}; @@ -63,7 +64,7 @@ pub trait SourceHeaderChain { /// Proof that messages are sent from source chain. This may also include proof /// of corresponding outbound lane states. - type MessagesProof: Parameter; + type MessagesProof: Parameter + Size; /// Verify messages proof and return proved messages. /// diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index b6f32582e9b6f..017aef6da72f1 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -69,12 +69,15 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; -/// Maximal weight of single message delivery transaction on Millau chain. +/// Maximal weight of single regular message delivery transaction on Millau chain. /// /// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation /// for the case when single message is delivered. The result then must be rounded up to account possible future /// runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; +pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; + +/// Increase of delivery transaction weight on Millau chain with every additional message byte. +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 3_000; /// Maximal weight of single message delivery confirmation transaction on Millau chain. /// diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 715004efba74f..9bec3b1862ba0 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -60,12 +60,15 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; -/// Maximal weight of single message delivery transaction on Rialto chain. +/// Maximal weight of single regular message delivery transaction on Rialto chain. /// /// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation /// for the case when single message is delivered. The result then must be rounded up to account possible future /// runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; +pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; + +/// Increase of delivery transaction weight on Rialto chain with every additional message byte. +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 3_000; /// Maximal weight of single message delivery confirmation transaction on Rialto chain. /// diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index b9d73d2b9c100..058c510c1b526 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -21,6 +21,7 @@ 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}; @@ -110,3 +111,12 @@ pub trait Size { /// accurate. fn size_hint(&self) -> u32; } + +/// 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) + } +} diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index a5ddf143f1b03..767002d686543 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -245,14 +245,14 @@ impl Client { instance: InstanceId, lane: LaneId, at_block: C::Hash, - ) -> Result { + ) -> Result>> { let encoded_trie_nodes = SubstrateMessageLane::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) .await .map_err(Error::Request)?; let decoded_trie_nodes: Vec> = Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; - Ok(StorageProof::new(decoded_trie_nodes)) + Ok(decoded_trie_nodes) } /// Return new justifications stream. diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e1e4e2ec9a9c4..137741a135424 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -25,6 +25,7 @@ bp-millau = { path = "../../primitives/millau" } bp-polkadot = { path = "../../primitives/polkadot" } bp-runtime = { path = "../../primitives/runtime" } bp-rialto = { path = "../../primitives/rialto" } +bridge-runtime-common = { path = "../../bin/runtime-common" } headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } millau-runtime = { path = "../../bin/millau/runtime" } diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index 375c469fde1a9..db894df8c7ac6 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -23,6 +23,7 @@ use crate::messages_lane::SubstrateMessageLane; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::{Decode, Encode}; use frame_support::weights::Weight; use messages_relay::{ @@ -35,13 +36,12 @@ use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, Hea use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use sp_trie::StorageProof; use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and /// the proof itself. -pub type SubstrateMessagesProof = (Weight, (HashOf, StorageProof, LaneId, MessageNonce, MessageNonce)); +pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. pub struct SubstrateMessagesSource { @@ -179,8 +179,16 @@ where proof_parameters.outbound_state_proof_required, id.1, ) - .await?; - let proof = (id.1, proof, self.lane_id, *nonces.start(), *nonces.end()); + .await? + .iter_nodes() + .collect(); + let proof = FromBridgedChainMessagesProof { + bridged_header_hash: id.1, + storage_proof: proof, + lane: self.lane_id, + nonces_start: *nonces.start(), + nonces_end: *nonces.end(), + }; Ok((id, nonces, (proof_parameters.dispatch_weight, proof))) } diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index e8610aac9533c..e5ac8880c845d 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -24,6 +24,7 @@ use crate::messages_source::read_client_state; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::InstanceId; +use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use codec::{Decode, Encode}; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, @@ -33,11 +34,13 @@ use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use sp_trie::StorageProof; use std::ops::RangeInclusive; /// Message receiving proof returned by the target Substrate node. -pub type SubstrateMessagesReceivingProof = (UnrewardedRelayersState, (HashOf, StorageProof, LaneId)); +pub type SubstrateMessagesReceivingProof = ( + UnrewardedRelayersState, + FromBridgedChainMessagesDeliveryProof>, +); /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { @@ -166,7 +169,11 @@ where .client .prove_messages_delivery(self.instance, self.lane_id, id.1) .await?; - let proof = (id.1, proof, self.lane_id); + let proof = FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: id.1, + storage_proof: proof, + lane: self.lane_id, + }; Ok((id, (relayers_state, proof))) } diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index 1d9239ff37156..c0b5c8a8103e9 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -24,6 +24,7 @@ use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; @@ -74,8 +75,12 @@ impl SubstrateMessageLane for MillauMessagesToRialto { proof: ::MessagesProof, ) -> Result { let (dispatch_weight, proof) = proof; - let (_, _, _, ref nonces_begin, ref nonces_end) = proof; - let messages_count = nonces_end - nonces_begin + 1; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; let call = rialto_runtime::MessageLaneCall::receive_messages_proof( diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index a336637e4daf2..2ddf660270666 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -24,6 +24,7 @@ use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; @@ -74,8 +75,12 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { proof: ::MessagesProof, ) -> Result { let (dispatch_weight, proof) = proof; - let (_, _, _, ref nonces_begin, ref nonces_end) = proof; - let messages_count = nonces_end - nonces_begin + 1; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; let call = millau_runtime::MessageLaneCall::receive_messages_proof( From 1811a7080e641745ba3e0430bd080a825d3aa7d0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 11 Feb 2021 10:36:14 +0300 Subject: [PATCH 0330/1210] limit number of pending messages at outbound lane (#715) --- bin/millau/runtime/src/rialto_messages.rs | 10 ++ bin/rialto/runtime/src/millau_messages.rs | 10 ++ bin/runtime-common/src/messages.rs | 126 ++++++++++++++++++-- modules/message-lane/src/lib.rs | 3 +- modules/message-lane/src/mock.rs | 3 +- modules/message-lane/src/outbound_lane.rs | 5 + primitives/message-lane/src/source_chain.rs | 3 +- 7 files changed, 148 insertions(+), 12 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 9538f18f55426..caec651f70167 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -167,6 +167,16 @@ impl messages::ChainWithMessageLanes for Millau { type MessageLaneInstance = pallet_message_lane::DefaultInstance; } +impl messages::ThisChainWithMessageLanes for Millau { + fn is_outbound_lane_enabled(lane: &LaneId) -> bool { + *lane == LaneId::default() + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + MessageNonce::MAX + } +} + /// Rialto chain from message lane point of view. #[derive(RuntimeDebug, Clone, Copy)] pub struct Rialto; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 2810e888e7b80..9207d79edb78c 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -167,6 +167,16 @@ impl messages::ChainWithMessageLanes for Rialto { type MessageLaneInstance = crate::WithMillauMessageLaneInstance; } +impl messages::ThisChainWithMessageLanes for Rialto { + fn is_outbound_lane_enabled(lane: &LaneId) -> bool { + *lane == LaneId::default() + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + MessageNonce::MAX + } +} + /// Millau chain from message lane point of view. #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3054334d52df2..04b2317749b0a 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -44,7 +44,7 @@ pub trait MessageBridge { const RELAYER_FEE_PERCENT: u32; /// This chain in context of message bridge. - type ThisChain: ChainWithMessageLanes; + type ThisChain: ThisChainWithMessageLanes; /// Bridged chain in context of message bridge. type BridgedChain: ChainWithMessageLanes; @@ -104,6 +104,17 @@ pub trait ChainWithMessageLanes { type MessageLaneInstance: Instance; } +/// This chain that has `message-lane` and `call-dispatch` modules. +pub trait ThisChainWithMessageLanes: ChainWithMessageLanes { + /// Are we accepting any messages to the given lane? + fn is_outbound_lane_enabled(lane: &LaneId) -> bool; + + /// Maximal number of pending (not yet delivered) messages at this chain. + /// + /// Any messages over this limit, will be rejected. + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; +} + pub(crate) type ThisChain = ::ThisChain; pub(crate) type BridgedChain = ::BridgedChain; pub(crate) type HashOf = ::Hash; @@ -187,10 +198,24 @@ pub mod source { /// 'Parsed' message delivery proof - inbound lane id and its state. pub type ParsedMessagesDeliveryProofFromBridgedChain = (LaneId, InboundLaneData>>); - /// Message verifier that requires submitter to pay minimal delivery and dispatch fee. + /// Message verifier that is doing all basic checks. + /// + /// This verifier assumes following: + /// + /// - all message lanes are equivalent, so all checks are the same; + /// - messages are being dispatched using `pallet-bridge-call-dispatch` pallet on the target chain. + /// + /// Following checks are made: + /// + /// - message is rejected if its lane is currently blocked; + /// - message is rejected if there are too many pending (undelivered) messages at the outbound lane; + /// - check that the sender has rights to dispatch the call on target chain using provided dispatch origin; + /// - check that the sender has paid enough funds for both message delivery and dispatch. #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); + pub(crate) const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; + pub(crate) const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; pub(crate) const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; pub(crate) const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; @@ -205,9 +230,24 @@ pub mod source { fn verify_message( submitter: &Sender>>, delivery_and_dispatch_fee: &BalanceOf>, - _lane: &LaneId, + lane: &LaneId, + lane_outbound_data: &OutboundLaneData, payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { + // reject message if lane is blocked + if !ThisChain::::is_outbound_lane_enabled(lane) { + return Err(OUTBOUND_LANE_DISABLED); + } + + // reject message if there are too many pending messages at this lane + let max_pending_messages = ThisChain::::maximal_pending_messages_at_outbound_lane(); + let pending_messages = lane_outbound_data + .latest_generated_nonce + .saturating_sub(lane_outbound_data.latest_received_nonce); + if pending_messages > max_pending_messages { + return Err(TOO_MANY_PENDING_MESSAGES); + } + // Do the dispatch-specific check. We assume that the target chain uses // `CallDispatch`, so we verify the message accordingly. pallet_bridge_call_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; @@ -812,6 +852,16 @@ mod tests { type MessageLaneInstance = pallet_message_lane::DefaultInstance; } + impl ThisChainWithMessageLanes for ThisChain { + fn is_outbound_lane_enabled(lane: &LaneId) -> bool { + lane == TEST_LANE_ID + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + } + } + struct BridgedChain; impl ChainWithMessageLanes for BridgedChain { @@ -826,6 +876,20 @@ mod tests { type MessageLaneInstance = pallet_message_lane::DefaultInstance; } + impl ThisChainWithMessageLanes for BridgedChain { + fn is_outbound_lane_enabled(_lane: &LaneId) -> bool { + unreachable!() + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + unreachable!() + } + } + + fn test_lane_outbound_data() -> OutboundLaneData { + OutboundLaneData::default() + } + #[test] fn message_from_bridged_chain_is_decoded() { // the message is encoded on the bridged chain @@ -857,18 +921,23 @@ mod tests { } const TEST_LANE_ID: &LaneId = b"test"; + const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; + + fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { + source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: 100, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: vec![42], + } + } #[test] fn message_fee_is_checked_by_verifier() { const EXPECTED_MINIMAL_FEE: u32 = 5500; // payload of the This -> Bridged chain message - let payload = source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: vec![42], - }; + let payload = regular_outbound_message_payload(); // let's check if estimation matching hardcoded value assert_eq!( @@ -885,6 +954,7 @@ mod tests { &Sender::Root, &ThisChainBalance(1), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ), Err(source::TOO_LOW_FEE) @@ -894,6 +964,7 @@ mod tests { &Sender::Root, &ThisChainBalance(1_000_000), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ) .is_ok(), @@ -916,6 +987,7 @@ mod tests { &Sender::Signed(ThisChainAccountId(0)), &ThisChainBalance(1_000_000), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ), Err(source::BAD_ORIGIN) @@ -925,6 +997,7 @@ mod tests { &Sender::None, &ThisChainBalance(1_000_000), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ), Err(source::BAD_ORIGIN) @@ -934,6 +1007,7 @@ mod tests { &Sender::Root, &ThisChainBalance(1_000_000), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ) .is_ok(), @@ -956,6 +1030,7 @@ mod tests { &Sender::Signed(ThisChainAccountId(0)), &ThisChainBalance(1_000_000), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ), Err(source::BAD_ORIGIN) @@ -965,12 +1040,45 @@ mod tests { &Sender::Signed(ThisChainAccountId(1)), &ThisChainBalance(1_000_000), &TEST_LANE_ID, + &test_lane_outbound_data(), &payload, ) .is_ok(), ); } + #[test] + fn message_is_rejected_when_sent_using_disabled_lane() { + assert_eq!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::Root, + &ThisChainBalance(1_000_000), + b"dsbl", + &test_lane_outbound_data(), + ®ular_outbound_message_payload(), + ), + Err(source::OUTBOUND_LANE_DISABLED) + ); + } + + #[test] + fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { + assert_eq!( + source::FromThisChainMessageVerifier::::verify_message( + &Sender::Root, + &ThisChainBalance(1_000_000), + &TEST_LANE_ID, + &OutboundLaneData { + latest_received_nonce: 100, + latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1, + ..Default::default() + }, + ®ular_outbound_message_payload(), + ), + Err(source::TOO_MANY_PENDING_MESSAGES) + ); + } + #[test] fn verify_chain_message_rejects_message_with_too_small_declared_weight() { assert!( diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index c14ccdb45546c..9b55343680e37 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -293,10 +293,12 @@ decl_module! { })?; // now let's enforce any additional lane rules + let mut lane = outbound_lane::(lane_id); T::LaneMessageVerifier::verify_message( &submitter, &delivery_and_dispatch_fee, &lane_id, + &lane.data(), &payload, ).map_err(|err| { frame_support::debug::trace!( @@ -326,7 +328,6 @@ decl_module! { })?; // finally, save message in outbound storage and emit event - let mut lane = outbound_lane::(lane_id); let encoded_payload = payload.encode(); let encoded_payload_len = encoded_payload.len(); let nonce = lane.send_message(MessageData { diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 4d1bb488908b8..244d580f05782 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -21,7 +21,7 @@ use bp_message_lane::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, Sender, TargetHeaderChain, }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, + InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -253,6 +253,7 @@ impl LaneMessageVerifier for TestLaneMes _submitter: &Sender, delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, + _lane_outbound_data: &OutboundLaneData, _payload: &TestPayload, ) -> Result<(), Self::Error> { if *delivery_and_dispatch_fee != 0 { diff --git a/modules/message-lane/src/outbound_lane.rs b/modules/message-lane/src/outbound_lane.rs index dc1ec413012d0..8496d7f8c026d 100644 --- a/modules/message-lane/src/outbound_lane.rs +++ b/modules/message-lane/src/outbound_lane.rs @@ -49,6 +49,11 @@ impl OutboundLane { OutboundLane { storage } } + /// Get this lane data. + pub fn data(&self) -> OutboundLaneData { + self.storage.data() + } + /// Send message over lane. /// /// Returns new message nonce. diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index 1c47d8c6debb7..1bb0d591586f9 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -16,7 +16,7 @@ //! Primitives of message lane module, that are used on the source chain. -use crate::{InboundLaneData, LaneId, MessageNonce}; +use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; use bp_runtime::Size; use frame_support::{Parameter, RuntimeDebug}; @@ -86,6 +86,7 @@ pub trait LaneMessageVerifier { submitter: &Sender, delivery_and_dispatch_fee: &Fee, lane: &LaneId, + outbound_data: &OutboundLaneData, payload: &Payload, ) -> Result<(), Self::Error>; } From 376e19346b1b44ca77abe41c9a195ec87e532add Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 12 Feb 2021 13:13:01 +0300 Subject: [PATCH 0331/1210] Fix max extrinsic weight in relay + logging (#717) * fix max weight in relay + logging * removed duplicate info --- relays/messages-relay/src/message_lane.rs | 4 +- .../src/message_race_delivery.rs | 30 +++++++++++ .../messages-relay/src/message_race_loop.rs | 13 ++++- .../src/message_race_strategy.rs | 11 ++-- .../src/millau_messages_to_rialto.rs | 51 +++++++++++++++---- .../src/rialto_messages_to_millau.rs | 51 +++++++++++++++---- 6 files changed, 130 insertions(+), 30 deletions(-) diff --git a/relays/messages-relay/src/message_lane.rs b/relays/messages-relay/src/message_lane.rs index 6abddabb4879c..0eab02ae299f2 100644 --- a/relays/messages-relay/src/message_lane.rs +++ b/relays/messages-relay/src/message_lane.rs @@ -30,9 +30,9 @@ pub trait MessageLane: Clone + Send + Sync { const TARGET_NAME: &'static str; /// Messages proof. - type MessagesProof: Clone + Send + Sync; + type MessagesProof: Clone + Debug + Send + Sync; /// Messages receiving proof. - type MessagesReceivingProof: Clone + Send + Sync; + type MessagesReceivingProof: Clone + Debug + Send + Sync; /// Number of the source header. type SourceHeaderNumber: BlockNumberBase; diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 7724e9235da6f..5e86b9560acf3 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -238,6 +238,36 @@ type MessageDeliveryStrategyBase

= BasicStrategy<

::MessagesProof, >; +impl std::fmt::Debug for MessageDeliveryStrategy

{ + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("MessageDeliveryStrategy") + .field( + "max_unrewarded_relayer_entries_at_target", + &self.max_unrewarded_relayer_entries_at_target, + ) + .field( + "max_unconfirmed_nonces_at_target", + &self.max_unconfirmed_nonces_at_target, + ) + .field("max_messages_in_single_batch", &self.max_messages_in_single_batch) + .field( + "max_messages_weight_in_single_batch", + &self.max_messages_weight_in_single_batch, + ) + .field( + "max_messages_size_in_single_batch", + &self.max_messages_size_in_single_batch, + ) + .field( + "latest_confirmed_noncs_at_source", + &self.latest_confirmed_nonce_at_source, + ) + .field("target_nonces", &self.target_nonces) + .field("strategy", &self.strategy) + .finish() + } +} + impl RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> for MessageDeliveryStrategy

{ diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index 0be247e114b77..f15fdf71fed29 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -45,7 +45,7 @@ pub trait MessageRace { /// Message nonce used in the race. type MessageNonce: Debug + Clone; /// Proof that is generated and delivered in this race. - type Proof: Clone; + type Proof: Debug + Clone; /// Name of the race source. fn source_name() -> String; @@ -138,7 +138,7 @@ pub trait TargetClient { } /// Race strategy. -pub trait RaceStrategy { +pub trait RaceStrategy: Debug { /// Type of nonces range expected from the source client. type SourceNoncesRange: NoncesRange; /// Additional proof parameters required to generate proof. @@ -359,6 +359,15 @@ pub async fn run, TC: TargetClient

>( progress_context = print_race_progress::(progress_context, &strategy); if stall_countdown.elapsed() > stall_timeout { + log::warn!( + target: "bridge", + "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", + P::source_name(), + P::target_name(), + race_state, + strategy, + ); + return Err(FailedClient::Both); } else if race_state.nonces_to_submit.is_none() && race_state.nonces_submitted.is_none() && strategy.is_empty() { diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index ce41c2e19a24c..45321691e6b7a 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -21,7 +21,7 @@ use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClien use bp_message_lane::MessageNonce; use relay_utils::HeaderId; -use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive}; +use std::{collections::VecDeque, fmt::Debug, marker::PhantomData, ops::RangeInclusive}; /// Nonces delivery strategy. #[derive(Debug)] @@ -147,9 +147,12 @@ impl, HeaderId, Proof> for BasicStrategy where - SourceHeaderHash: Clone, - SourceHeaderNumber: Clone + Ord, - SourceNoncesRange: NoncesRange, + SourceHeaderHash: Clone + Debug, + SourceHeaderNumber: Clone + Ord + Debug, + SourceNoncesRange: NoncesRange + Debug, + TargetHeaderHash: Debug, + TargetHeaderNumber: Debug, + Proof: Debug, { type SourceNoncesRange = SourceNoncesRange; type ProofParameters = (); diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index c0b5c8a8103e9..ebab5cfb381d3 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -25,6 +25,8 @@ use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use codec::Encode; +use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; @@ -63,8 +65,18 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let (relayers_state, proof) = proof; let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); let nonce = self.source_client.next_account_index(account_id).await?; - let call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); + let call: millau_runtime::Call = + millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); + let call_weight = call.get_dispatch_info().weight; let transaction = Millau::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); + log::trace!( + target: "bridge", + "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", + call_weight, + bp_millau::max_extrinsic_weight(), + transaction.encode().len(), + bp_millau::max_extrinsic_size(), + ); Ok(transaction) } @@ -83,14 +95,23 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let messages_count = nonces_end - nonces_start + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = rialto_runtime::MessageLaneCall::receive_messages_proof( + let call: rialto_runtime::Call = rialto_runtime::MessageLaneCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, messages_count as _, dispatch_weight, ) .into(); + let call_weight = call.get_dispatch_info().weight; let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + log::trace!( + target: "bridge", + "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", + call_weight, + bp_rialto::max_extrinsic_weight(), + transaction.encode().len(), + bp_rialto::max_extrinsic_size(), + ); Ok(transaction) } } @@ -121,19 +142,28 @@ pub fn run( relayer_id_at_source: relayer_id_at_millau, }; - log::info!( - target: "bridge", - "Starting Millau -> Rialto messages relay. Millau relayer account id: {:?}", - lane.relayer_id_at_source, - ); - + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() as usize / 3; // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = select_delivery_transaction_limits::>( - bp_millau::max_extrinsic_weight(), + bp_rialto::max_extrinsic_weight(), bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); + log::info!( + target: "bridge", + "Starting Millau -> Rialto messages relay.\n\t\ + Millau relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}", + lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + ); + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -146,8 +176,7 @@ pub fn run( max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, - // 2/3 is reserved for proofs and tx overhead - max_messages_size_in_single_batch: bp_rialto::max_extrinsic_size() as usize / 3, + max_messages_size_in_single_batch, }, }, MillauSourceClient::new(millau_client, lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 2ddf660270666..1c11a111413c9 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -25,6 +25,8 @@ use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use codec::Encode; +use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; @@ -63,8 +65,18 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let (relayers_state, proof) = proof; let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); let nonce = self.source_client.next_account_index(account_id).await?; - let call = rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); + let call: rialto_runtime::Call = + rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); + let call_weight = call.get_dispatch_info().weight; let transaction = Rialto::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); + log::trace!( + target: "bridge", + "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", + call_weight, + bp_rialto::max_extrinsic_weight(), + transaction.encode().len(), + bp_rialto::max_extrinsic_size(), + ); Ok(transaction) } @@ -83,14 +95,23 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let messages_count = nonces_end - nonces_start + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = millau_runtime::MessageLaneCall::receive_messages_proof( + let call: millau_runtime::Call = millau_runtime::MessageLaneCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, messages_count as _, dispatch_weight, ) .into(); + let call_weight = call.get_dispatch_info().weight; let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + log::trace!( + target: "bridge", + "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", + call_weight, + bp_millau::max_extrinsic_weight(), + transaction.encode().len(), + bp_millau::max_extrinsic_size(), + ); Ok(transaction) } } @@ -121,18 +142,27 @@ pub fn run( relayer_id_at_source: relayer_id_at_rialto, }; - log::info!( - target: "bridge", - "Starting Rialto -> Millau messages relay. Rialto relayer account id: {:?}", - lane.relayer_id_at_source, - ); - + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() as usize / 3; let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = select_delivery_transaction_limits::>( - bp_rialto::max_extrinsic_weight(), + bp_millau::max_extrinsic_weight(), bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); + log::info!( + target: "bridge", + "Starting Rialto -> Millau messages relay.\n\t\ + Rialto relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}", + lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + ); + messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -145,8 +175,7 @@ pub fn run( max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, - // 2/3 is reserved for proofs and tx overhead - max_messages_size_in_single_batch: bp_millau::max_extrinsic_size() as usize / 3, + max_messages_size_in_single_batch, }, }, RialtoSourceClient::new(rialto_client, lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), From 2e363df91517cd639e20041b99f683e2e37a7554 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 12 Feb 2021 10:55:30 -0500 Subject: [PATCH 0332/1210] Finality Pallet Rate Limiter (#720) * Add simple rate limiting mechanism * Add tests * Small test cleanup * Hook MaxRequests into runtimes --- bin/millau/runtime/src/lib.rs | 9 ++ bin/rialto/runtime/src/lib.rs | 9 ++ modules/finality-verifier/src/lib.rs | 124 ++++++++++++++++++++++---- modules/finality-verifier/src/mock.rs | 3 +- 4 files changed, 128 insertions(+), 17 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index bf688f5eb19c1..bd261f4e91835 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -300,11 +300,20 @@ impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_rialto::Rialto; } +parameter_types! { + // This is a pretty unscientific cap. + // + // Note that once this is hit the pallet will essentially throttle incoming requests down to one + // call per block. + pub const MaxRequests: u32 = 50; +} + impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type HeaderChain = pallet_substrate_bridge::Module; type AncestryProof = Vec; type AncestryChecker = bp_header_chain::LinearAncestryChecker; + type MaxRequests = MaxRequests; } impl pallet_shift_session_manager::Config for Runtime {} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index d2ade4592af26..84055f92a6204 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -407,11 +407,20 @@ impl pallet_substrate_bridge::Config for Runtime { type BridgedChain = bp_millau::Millau; } +parameter_types! { + // This is a pretty unscientific cap. + // + // Note that once this is hit the pallet will essentially throttle incoming requests down to one + // call per block. + pub const MaxRequests: u32 = 50; +} + impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_millau::Millau; type HeaderChain = pallet_substrate_bridge::Module; type AncestryProof = Vec; type AncestryChecker = bp_header_chain::LinearAncestryChecker; + type MaxRequests = MaxRequests; } impl pallet_shift_session_manager::Config for Runtime {} diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index cfcb610e7f5f8..a87bd75b992f5 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -72,13 +72,28 @@ pub mod pallet { /// The type through which we will verify that a given header is related to the last /// finalized header in our storage pallet. type AncestryChecker: AncestryChecker<::Header, Self::AncestryProof>; + + /// The upper bound on the number of requests allowed by the pallet. + /// + /// Once this bound is reached the pallet will not allow any dispatchables to be called + /// until the request count has decreased. + #[pallet::constant] + type MaxRequests: Get; } #[pallet::pallet] pub struct Pallet(PhantomData); #[pallet::hooks] - impl Hooks> for Pallet {} + impl Hooks> for Pallet { + fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { + >::mutate(|count| *count = count.saturating_sub(1)); + + (0_u64) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + } #[pallet::call] impl Pallet { @@ -98,6 +113,12 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { let _ = ensure_signed(origin)?; + ensure!( + Self::request_count() < T::MaxRequests::get(), + >::TooManyRequests + ); + >::mutate(|count| *count += 1); + frame_support::debug::trace!("Going to try and finalize header {:?}", finality_target); let authority_set = T::HeaderChain::authority_set(); @@ -127,6 +148,17 @@ pub mod pallet { } } + /// The current number of requests for calling dispatchables. + /// + /// If the `RequestCount` hits `MaxRequests`, no more calls will be allowed to the pallet until + /// the request capacity is increased. + /// + /// The `RequestCount` is decreased by one at the beginning of every block. This is to ensure + /// that the pallet can always make progress. + #[pallet::storage] + #[pallet::getter(fn request_count)] + pub(super) type RequestCount = StorageValue<_, u32, ValueQuery>; + #[pallet::error] pub enum Error { /// The given justification is invalid for the given header. @@ -138,6 +170,8 @@ pub mod pallet { InvalidAuthoritySet, /// Failed to write a header to the underlying header chain. FailedToWriteHeader, + /// There are too many requests for the current window to handle. + TooManyRequests, } } @@ -166,27 +200,34 @@ mod tests { )); } + fn submit_finality_proof() -> frame_support::dispatch::DispatchResultWithPostInfo { + let child = test_header(1); + let header = test_header(2); + + let set_id = 1; + let grandpa_round = 1; + let justification = make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let ancestry_proof = vec![child, header.clone()]; + + Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof) + } + + fn next_block() { + use frame_support::traits::OnInitialize; + + let current_number = frame_system::Module::::block_number(); + frame_system::Module::::set_block_number(current_number + 1); + let _ = Module::::on_initialize(current_number); + } + #[test] fn succesfully_imports_header_with_valid_finality_and_ancestry_proofs() { run_test(|| { initialize_substrate_bridge(); - let child = test_header(1); - let header = test_header(2); - - let set_id = 1; - let grandpa_round = 1; - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); - let ancestry_proof = vec![child, header.clone()]; - - assert_ok!(Module::::submit_finality_proof( - Origin::signed(1), - header.clone(), - justification, - ancestry_proof, - )); + assert_ok!(submit_finality_proof()); + let header = test_header(2); assert_eq!( pallet_substrate_bridge::Module::::best_headers(), vec![(*header.number(), header.hash())] @@ -288,4 +329,55 @@ mod tests { ); }) } + + #[test] + fn disallows_imports_once_limit_is_hit_in_single_block() { + run_test(|| { + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof()); + assert_err!(submit_finality_proof(), >::TooManyRequests); + }) + } + + #[test] + fn allows_request_after_new_block_has_started() { + run_test(|| { + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof()); + + next_block(); + assert_ok!(submit_finality_proof()); + }) + } + + #[test] + fn disallows_imports_once_limit_is_hit_across_different_blocks() { + run_test(|| { + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof()); + + next_block(); + assert_ok!(submit_finality_proof()); + assert_err!(submit_finality_proof(), >::TooManyRequests); + }) + } + + #[test] + fn allows_max_requests_after_long_time_with_no_activity() { + run_test(|| { + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof()); + + next_block(); + next_block(); + + next_block(); + assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof()); + }) + } } diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index 1ef1249545906..d492759f1bb0f 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -71,7 +71,7 @@ impl pallet_substrate_bridge::Config for TestRuntime { } parameter_types! { - pub const MaxElementsInSingleProof: Option = Some(5); + pub const MaxRequests: u32 = 2; } impl crate::pallet::Config for TestRuntime { @@ -79,6 +79,7 @@ impl crate::pallet::Config for TestRuntime { type HeaderChain = pallet_substrate_bridge::Module; type AncestryProof = Vec<::Header>; type AncestryChecker = Checker<::Header, Self::AncestryProof>; + type MaxRequests = MaxRequests; } #[derive(Debug)] From d4682feed36407e6abf2e9ea5a54428698cea962 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 12 Feb 2021 19:10:27 +0300 Subject: [PATCH 0333/1210] Increase message fee call (#718) * fn increase_message_fee() * benchmarks + weights * - extra lines * split error --- modules/message-lane/src/benchmarking.rs | 105 +++++++++++++--------- modules/message-lane/src/lib.rs | 108 +++++++++++++++++++++++ modules/message-lane/src/weights.rs | 105 ++++++++++++---------- 3 files changed, 231 insertions(+), 87 deletions(-) diff --git a/modules/message-lane/src/benchmarking.rs b/modules/message-lane/src/benchmarking.rs index 675bc310f59ab..cd59d1347f269 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/message-lane/src/benchmarking.rs @@ -81,6 +81,10 @@ pub struct MessageDeliveryProofParams { /// Trait that must be implemented by runtime. pub trait Config: crate::Config { + /// Lane id to use in benchmarks. + fn bench_lane_id() -> LaneId { + Default::default() + } /// Get maximal size of the message payload. fn maximal_message_size() -> u32; /// Return id of relayer account at the bridged chain. @@ -121,7 +125,7 @@ benchmarks_instance! { // (estimated using `send_half_maximal_message_worst_case` and `send_maximal_message_worst_case`) is // added. send_minimal_message_worst_case { - let lane_id = bench_lane_id(); + let lane_id = T::bench_lane_id(); let sender = account("sender", 0, SEED); T::endow_account(&sender); @@ -138,7 +142,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -152,7 +156,7 @@ benchmarks_instance! { // With single KB of message size, the weight of the call is increased (roughly) by // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_1_kb_message_worst_case { - let lane_id = bench_lane_id(); + let lane_id = T::bench_lane_id(); let sender = account("sender", 0, SEED); T::endow_account(&sender); @@ -175,7 +179,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -189,7 +193,7 @@ benchmarks_instance! { // With single KB of message size, the weight of the call is increased (roughly) by // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_16_kb_message_worst_case { - let lane_id = bench_lane_id(); + let lane_id = T::bench_lane_id(); let sender = account("sender", 0, SEED); T::endow_account(&sender); @@ -212,11 +216,28 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } + // Benchmark `increase_message_fee` with following conditions: + // * message has maximal message; + // * submitter account is killed because its balance is less than ED after payment. + increase_message_fee { + let sender = account("sender", 42, SEED); + T::endow_account(&sender); + + let additional_fee = T::account_balance(&sender); + let lane_id = T::bench_lane_id(); + let nonce = 1; + + send_regular_message_with_payload::(vec![42u8; T::maximal_message_size() as _]); + }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) + verify { + assert_eq!(T::account_balance(&sender), 0.into()); + } + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; @@ -232,7 +253,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), @@ -240,7 +261,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -263,7 +284,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=22, outbound_lane_data: None, size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), @@ -271,7 +292,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 22, ); } @@ -294,7 +315,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: Some(OutboundLaneData { oldest_unpruned_nonce: 21, @@ -306,11 +327,11 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); assert_eq!( - crate::Module::::inbound_latest_confirmed_nonce(bench_lane_id()), + crate::Module::::inbound_latest_confirmed_nonce(T::bench_lane_id()), 20, ); } @@ -332,7 +353,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasExtraNodes(1024), @@ -340,7 +361,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -364,7 +385,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasExtraNodes(16 * 1024), @@ -372,7 +393,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -397,7 +418,7 @@ benchmarks_instance! { total_messages: 1, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(), last_confirmed_nonce: 0, @@ -435,7 +456,7 @@ benchmarks_instance! { total_messages: 2, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(), last_confirmed_nonce: 0, @@ -472,7 +493,7 @@ benchmarks_instance! { total_messages: 2, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![ (1, 1, relayer1_id.clone()), @@ -502,7 +523,7 @@ benchmarks_instance! { send_messages_of_various_lengths { let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); - let lane_id = bench_lane_id(); + let lane_id = T::bench_lane_id(); let sender = account("sender", 0, SEED); T::endow_account(&sender); @@ -519,7 +540,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(bench_lane_id()), + crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -544,7 +565,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=(20 + i as MessageNonce), outbound_lane_data: None, size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), @@ -558,7 +579,7 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 20 + i as MessageNonce, ); } @@ -581,7 +602,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasExtraNodes(i as _), @@ -595,7 +616,7 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -618,7 +639,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasLargeLeaf(i as _), @@ -632,7 +653,7 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -657,7 +678,7 @@ benchmarks_instance! { receive_messages::(20); let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), message_nonces: 21..=20 + i as MessageNonce, outbound_lane_data: Some(OutboundLaneData { oldest_unpruned_nonce: 21, @@ -675,11 +696,11 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(bench_lane_id()), + crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), 20 + i as MessageNonce, ); assert_eq!( - crate::Module::::inbound_latest_confirmed_nonce(bench_lane_id()), + crate::Module::::inbound_latest_confirmed_nonce(T::bench_lane_id()), 20, ); } @@ -708,7 +729,7 @@ benchmarks_instance! { total_messages: i as MessageNonce, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(), last_confirmed_nonce: 0, @@ -750,7 +771,7 @@ benchmarks_instance! { total_messages: i as MessageNonce, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: bench_lane_id(), + lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: relayers .keys() @@ -769,25 +790,29 @@ benchmarks_instance! { } } -fn bench_lane_id() -> LaneId { - *b"test" -} - fn send_regular_message, I: Instance>() { - let mut outbound_lane = outbound_lane::(bench_lane_id()); + let mut outbound_lane = outbound_lane::(T::bench_lane_id()); outbound_lane.send_message(MessageData { payload: vec![], fee: MESSAGE_FEE.into(), }); } +fn send_regular_message_with_payload, I: Instance>(payload: Vec) { + let mut outbound_lane = outbound_lane::(T::bench_lane_id()); + outbound_lane.send_message(MessageData { + payload, + fee: MESSAGE_FEE.into(), + }); +} + fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { - let mut outbound_lane = outbound_lane::(bench_lane_id()); + let mut outbound_lane = outbound_lane::(T::bench_lane_id()); assert!(outbound_lane.confirm_delivery(nonce).is_some()); } fn receive_messages, I: Instance>(nonce: MessageNonce) { - let mut inbound_lane_storage = inbound_lane_storage::(bench_lane_id()); + let mut inbound_lane_storage = inbound_lane_storage::(T::bench_lane_id()); inbound_lane_storage.set_data(InboundLaneData { relayers: vec![(1, nonce, T::bridged_relayer_id())].into_iter().collect(), last_confirmed_nonce: 0, diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 9b55343680e37..d6ae1d092573b 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -42,6 +42,7 @@ pub use crate::weights_ext::{ use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; +use crate::weights::WeightInfo; use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, @@ -173,6 +174,10 @@ decl_error! { InvalidMessagesDeliveryProof, /// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call. InvalidUnrewardedRelayersState, + /// The message someone is trying to work with (i.e. increase fee) is already-delivered. + MessageIsAlreadyDelivered, + /// The message someone is trying to work with (i.e. increase fee) is not yet sent. + MessageIsNotYetSent } } @@ -348,6 +353,57 @@ decl_module! { Ok(()) } + /// Pay additional fee for the message. + #[weight = T::WeightInfo::increase_message_fee()] + pub fn increase_message_fee( + origin, + lane_id: LaneId, + nonce: MessageNonce, + additional_fee: T::OutboundMessageFee, + ) -> DispatchResult { + // if someone tries to pay for already-delivered message, we're rejecting this intention + // (otherwise this additional fee will be locked forever in relayers fund) + // + // if someone tries to pay for not-yet-sent message, we're rejeting this intention, or + // we're risking to have mess in the storage + let lane = outbound_lane::(lane_id); + ensure!(nonce > lane.data().latest_received_nonce, Error::::MessageIsAlreadyDelivered); + ensure!(nonce <= lane.data().latest_generated_nonce, Error::::MessageIsNotYetSent); + + // withdraw additional fee from submitter + let submitter = origin.into().map_err(|_| BadOrigin)?; + T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( + &submitter, + &additional_fee, + &Self::relayer_fund_account_id(), + ).map_err(|err| { + frame_support::debug::trace!( + "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", + submitter, + additional_fee, + lane_id, + nonce, + err, + ); + + Error::::FailedToWithdrawMessageFee + })?; + + // and finally update fee in the storage + let message_key = MessageKey { lane_id, nonce }; + OutboundMessages::::mutate(message_key, |message_data| { + // saturating_add is fine here - overflow here means that someone controls all + // chain funds, which shouldn't ever happen + `pay_delivery_and_dispatch_fee` + // above will fail before we reach here + let message_data = message_data + .as_mut() + .expect("the message is sent and not yet delivered; so it is in the storage; qed"); + message_data.fee = message_data.fee.saturating_add(&additional_fee); + }); + + Ok(()) + } + /// Receive messages proof from bridged chain. /// /// The weight of the call assumes that the transaction always brings outbound lane @@ -1343,4 +1399,56 @@ mod tests { ); }); } + + #[test] + fn increase_message_fee_fails_if_message_is_already_delivered() { + run_test(|| { + send_regular_message(); + receive_messages_delivery_proof(); + + assert_noop!( + Module::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Error::::MessageIsAlreadyDelivered, + ); + }); + } + + #[test] + fn increase_message_fee_fails_if_message_is_not_yet_sent() { + run_test(|| { + assert_noop!( + Module::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Error::::MessageIsNotYetSent, + ); + }); + } + + #[test] + fn increase_message_fee_fails_if_submitter_cant_pay_additional_fee() { + run_test(|| { + send_regular_message(); + + TestMessageDeliveryAndDispatchPayment::reject_payments(); + + assert_noop!( + Module::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Error::::FailedToWithdrawMessageFee, + ); + }); + } + + #[test] + fn increase_message_fee_succeeds() { + run_test(|| { + send_regular_message(); + + assert_ok!(Module::::increase_message_fee( + Origin::signed(1), + TEST_LANE_ID, + 1, + 100, + ),); + assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100)); + }); + } } diff --git a/modules/message-lane/src/weights.rs b/modules/message-lane/src/weights.rs index 44ce61020ee6c..b0ec6522b2c6e 100644 --- a/modules/message-lane/src/weights.rs +++ b/modules/message-lane/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_message_lane //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1 -//! DATE: 2021-02-01, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-02-11, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("local"), DB CACHE: 128 @@ -51,6 +51,7 @@ pub trait WeightInfo { fn send_minimal_message_worst_case() -> Weight; fn send_1_kb_message_worst_case() -> Weight; fn send_16_kb_message_worst_case() -> Weight; + fn increase_message_fee() -> Weight; fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; fn receive_single_message_proof_with_outbound_lane_state() -> Weight; @@ -72,100 +73,105 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (138_421_000 as Weight) + (140_645_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (142_633_000 as Weight) + (146_434_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (194_483_000 as Weight) + (214_721_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } + fn increase_message_fee() -> Weight { + (8_395_221_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } fn receive_single_message_proof() -> Weight { - (154_651_000 as Weight) + (156_390_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (271_722_000 as Weight) + (269_316_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (170_821_000 as Weight) + (174_342_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (189_540_000 as Weight) + (186_621_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (484_899_000 as Weight) + (487_028_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (145_328_000 as Weight) + (144_893_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (150_165_000 as Weight) + (151_134_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (215_954_000 as Weight) + (212_650_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (117_961_000 as Weight) - .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) + (88_670_000 as Weight) + .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((117_783_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((125_956_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (448_951_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) + (462_389_000 as Weight) + .saturating_add((11_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (97_174_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) + (120_744_000 as Weight) + .saturating_add((8_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((120_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((130_087_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (132_970_000 as Weight) - .saturating_add((7_243_000 as Weight).saturating_mul(i as Weight)) + (126_833_000 as Weight) + .saturating_add((7_793_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (62_936_000 as Weight) - .saturating_add((67_932_000 as Weight).saturating_mul(i as Weight)) + (71_269_000 as Weight) + .saturating_add((72_377_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -176,100 +182,105 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (138_421_000 as Weight) + (140_645_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (142_633_000 as Weight) + (146_434_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (194_483_000 as Weight) + (214_721_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } + fn increase_message_fee() -> Weight { + (8_395_221_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } fn receive_single_message_proof() -> Weight { - (154_651_000 as Weight) + (156_390_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (271_722_000 as Weight) + (269_316_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (170_821_000 as Weight) + (174_342_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (189_540_000 as Weight) + (186_621_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (484_899_000 as Weight) + (487_028_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (145_328_000 as Weight) + (144_893_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (150_165_000 as Weight) + (151_134_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (215_954_000 as Weight) + (212_650_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (117_961_000 as Weight) - .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) + (88_670_000 as Weight) + .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((117_783_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((125_956_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (448_951_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) + (462_389_000 as Weight) + .saturating_add((11_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (97_174_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) + (120_744_000 as Weight) + .saturating_add((8_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((120_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((130_087_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (132_970_000 as Weight) - .saturating_add((7_243_000 as Weight).saturating_mul(i as Weight)) + (126_833_000 as Weight) + .saturating_add((7_793_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (62_936_000 as Weight) - .saturating_add((67_932_000 as Weight).saturating_mul(i as Weight)) + (71_269_000 as Weight) + .saturating_add((72_377_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) From 543ba22d4cb28c6ffa360f1848290cd7f963f7d4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 15 Feb 2021 15:10:46 +0300 Subject: [PATCH 0334/1210] Keep multiple latest confirmed nonces at source in messages relay (#719) * keep multiple latest confirmed nonces at source in messages relay * post-merge fix --- .../src/message_race_delivery.rs | 171 +++++++++++++++--- .../messages-relay/src/message_race_loop.rs | 95 ++++++++-- .../src/message_race_receiving.rs | 7 +- .../src/message_race_strategy.rs | 84 +++++---- 4 files changed, 275 insertions(+), 82 deletions(-) diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/messages-relay/src/message_race_delivery.rs index 5e86b9560acf3..c7e308fee1e18 100644 --- a/relays/messages-relay/src/message_race_delivery.rs +++ b/relays/messages-relay/src/message_race_delivery.rs @@ -29,7 +29,12 @@ use async_trait::async_trait; use bp_message_lane::{MessageNonce, UnrewardedRelayersState, Weight}; use futures::stream::FusedStream; use relay_utils::FailedClient; -use std::{collections::BTreeMap, marker::PhantomData, ops::RangeInclusive, time::Duration}; +use std::{ + collections::{BTreeMap, VecDeque}, + marker::PhantomData, + ops::RangeInclusive, + time::Duration, +}; /// Run message delivery race. pub async fn run( @@ -61,7 +66,7 @@ pub async fn run( max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, max_messages_size_in_single_batch: params.max_messages_size_in_single_batch, - latest_confirmed_nonce_at_source: None, + latest_confirmed_nonces_at_source: VecDeque::new(), target_nonces: None, strategy: BasicStrategy::new(), }, @@ -164,14 +169,17 @@ where async fn nonces( &self, at_block: TargetHeaderIdOf

, + update_metrics: bool, ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> { let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; let (at_block, unrewarded_relayers) = self.client.unrewarded_relayers_state(at_block).await?; - if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); - metrics_msg.update_target_latest_confirmed_nonce::

(latest_confirmed_nonce); + if update_metrics { + if let Some(metrics_msg) = self.metrics_msg.as_ref() { + metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); + metrics_msg.update_target_latest_confirmed_nonce::

(latest_confirmed_nonce); + } } Ok(( @@ -221,8 +229,8 @@ struct MessageDeliveryStrategy { max_messages_weight_in_single_batch: Weight, /// Maximal messages size in the single delivery transaction. max_messages_size_in_single_batch: usize, - /// Latest confirmed nonce at the source client. - latest_confirmed_nonce_at_source: Option, + /// Latest confirmed nonces at the source client + the header id where we have first met this nonce. + latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, /// Target nonces from the source client. target_nonces: Option>, /// Basic delivery strategy. @@ -259,8 +267,8 @@ impl std::fmt::Debug for MessageDeliveryStrategy

{ &self.max_messages_size_in_single_batch, ) .field( - "latest_confirmed_noncs_at_source", - &self.latest_confirmed_nonce_at_source, + "latest_confirmed_nonces_at_source", + &self.latest_confirmed_nonces_at_source, ) .field("target_nonces", &self.target_nonces) .field("strategy", &self.strategy) @@ -292,17 +300,64 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M at_block: SourceHeaderIdOf

, nonces: SourceClientNonces, ) { - self.latest_confirmed_nonce_at_source = nonces.confirmed_nonce; + if let Some(confirmed_nonce) = nonces.confirmed_nonce { + let is_confirmed_nonce_updated = self + .latest_confirmed_nonces_at_source + .back() + .map(|(_, prev_nonce)| *prev_nonce != confirmed_nonce) + .unwrap_or(true); + if is_confirmed_nonce_updated { + self.latest_confirmed_nonces_at_source + .push_back((at_block.clone(), confirmed_nonce)); + } + } self.strategy.source_nonces_updated(at_block, nonces) } - fn target_nonces_updated( + fn best_target_nonces_updated( &mut self, nonces: TargetClientNonces, race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) { - self.target_nonces = Some(nonces.clone()); - self.strategy.target_nonces_updated( + // best target nonces must always be ge than finalized target nonces + let mut target_nonces = self.target_nonces.take().unwrap_or_else(|| nonces.clone()); + target_nonces.nonces_data = nonces.nonces_data.clone(); + target_nonces.latest_nonce = std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); + self.target_nonces = Some(target_nonces); + + self.strategy.best_target_nonces_updated( + TargetClientNonces { + latest_nonce: nonces.latest_nonce, + nonces_data: (), + }, + race_state, + ) + } + + fn finalized_target_nonces_updated( + &mut self, + nonces: TargetClientNonces, + race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, + ) { + if let Some(ref best_finalized_source_header_id_at_best_target) = + race_state.best_finalized_source_header_id_at_best_target + { + let oldest_header_number_to_keep = best_finalized_source_header_id_at_best_target.0; + while self + .latest_confirmed_nonces_at_source + .front() + .map(|(id, _)| id.0 < oldest_header_number_to_keep) + .unwrap_or(false) + { + self.latest_confirmed_nonces_at_source.pop_front(); + } + } + + if let Some(ref mut target_nonces) = self.target_nonces { + target_nonces.latest_nonce = std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); + } + + self.strategy.finalized_target_nonces_updated( TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: (), @@ -315,7 +370,14 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M &mut self, race_state: &RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) -> Option<(RangeInclusive, Self::ProofParameters)> { - let latest_confirmed_nonce_at_source = self.latest_confirmed_nonce_at_source?; + let best_finalized_source_header_id_at_best_target = + race_state.best_finalized_source_header_id_at_best_target.clone()?; + let latest_confirmed_nonce_at_source = self + .latest_confirmed_nonces_at_source + .iter() + .take_while(|(id, _)| id.0 <= best_finalized_source_header_id_at_best_target.0) + .last() + .map(|(_, nonce)| *nonce)?; let target_nonces = self.target_nonces.as_ref()?; // There's additional condition in the message delivery race: target would reject messages @@ -509,6 +571,7 @@ mod tests { best_finalized_source_header_id_at_source: Some(header_id(1)), best_finalized_source_header_id_at_best_target: Some(header_id(1)), best_target_header_id: Some(header_id(1)), + best_finalized_target_header_id: Some(header_id(1)), nonces_to_submit: None, nonces_submitted: None, }; @@ -519,7 +582,7 @@ mod tests { max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, max_messages_size_in_single_batch: 4, - latest_confirmed_nonce_at_source: Some(19), + latest_confirmed_nonces_at_source: vec![(header_id(1), 19)].into_iter().collect(), target_nonces: Some(TargetClientNonces { latest_nonce: 19, nonces_data: DeliveryRaceTargetNoncesData { @@ -548,13 +611,17 @@ mod tests { confirmed_nonce: Some(19), }, ); - race_strategy.strategy.target_nonces_updated( - TargetClientNonces { - latest_nonce: 19, - nonces_data: (), - }, - &mut race_state, - ); + + let target_nonces = TargetClientNonces { + latest_nonce: 19, + nonces_data: (), + }; + race_strategy + .strategy + .best_target_nonces_updated(target_nonces.clone(), &mut race_state); + race_strategy + .strategy + .finalized_target_nonces_updated(target_nonces, &mut race_state); (race_state, race_strategy) } @@ -611,8 +678,12 @@ mod tests { // if there are already `max_unconfirmed_nonces_at_target` messages on target, // we need to wait until confirmations will be delivered by receiving race - strategy.latest_confirmed_nonce_at_source = - Some(strategy.target_nonces.as_ref().unwrap().latest_nonce - strategy.max_unconfirmed_nonces_at_target); + strategy.latest_confirmed_nonces_at_source = vec![( + header_id(1), + strategy.target_nonces.as_ref().unwrap().latest_nonce - strategy.max_unconfirmed_nonces_at_target, + )] + .into_iter() + .collect(); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } @@ -622,7 +693,7 @@ mod tests { // if there are new confirmed nonces on source, we want to relay this information // to target to prune rewards queue - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; assert_eq!( strategy.select_nonces_to_deliver(&state), @@ -650,7 +721,7 @@ mod tests { // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, // we need to prove at least `messages_in_oldest_entry` rewards - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; { let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; @@ -667,7 +738,7 @@ mod tests { // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, // we need to prove at least `messages_in_oldest_entry` rewards - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; { let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 3; @@ -747,12 +818,54 @@ mod tests { // 1 delivery confirmation from target to source is still missing, so we may only // relay 3 new messages - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonce_at_source.unwrap(); - strategy.latest_confirmed_nonce_at_source = Some(prev_confirmed_nonce_at_source - 1); + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + strategy.latest_confirmed_nonces_at_source = vec![(header_id(1), prev_confirmed_nonce_at_source - 1)] + .into_iter() + .collect(); + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=22), proof_parameters(false, 3))) + ); + } + + #[test] + fn message_delivery_strategy_waits_for_confirmed_nonce_header_to_appear_on_target() { + // 1 delivery confirmation from target to source is still missing, so we may deliver + // reward confirmation with our message delivery transaction. But the problem is that + // the reward has been paid at header 2 && this header is still unknown to target node. + // + // => so we can't deliver more than 3 messages + let (mut state, mut strategy) = prepare_strategy(); + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + strategy.latest_confirmed_nonces_at_source = vec![ + (header_id(1), prev_confirmed_nonce_at_source - 1), + (header_id(2), prev_confirmed_nonce_at_source), + ] + .into_iter() + .collect(); strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); assert_eq!( strategy.select_nonces_to_deliver(&state), Some(((20..=22), proof_parameters(false, 3))) ); + + // the same situation, but the header 2 is known to the target node, so we may deliver reward confirmation + let (mut state, mut strategy) = prepare_strategy(); + let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + strategy.latest_confirmed_nonces_at_source = vec![ + (header_id(1), prev_confirmed_nonce_at_source - 1), + (header_id(2), prev_confirmed_nonce_at_source), + ] + .into_iter() + .collect(); + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + state.best_finalized_source_header_id_at_source = Some(header_id(2)); + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=23), proof_parameters(true, 4))) + ); } } diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/messages-relay/src/message_race_loop.rs index f15fdf71fed29..a11a1d7ff5dde 100644 --- a/relays/messages-relay/src/message_race_loop.rs +++ b/relays/messages-relay/src/message_race_loop.rs @@ -127,6 +127,7 @@ pub trait TargetClient { async fn nonces( &self, at_block: P::TargetHeaderId, + update_metrics: bool, ) -> Result<(P::TargetHeaderId, TargetClientNonces), Self::Error>; /// Submit proof to the target client. async fn submit_proof( @@ -160,8 +161,14 @@ pub trait RaceStrategy: Debug { /// Called when nonces are updated at source node of the race. fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonces: SourceClientNonces); - /// Called when nonces are updated at target node of the race. - fn target_nonces_updated( + /// Called when best nonces are updated at target node of the race. + fn best_target_nonces_updated( + &mut self, + nonces: TargetClientNonces, + race_state: &mut RaceState, + ); + /// Called when finalized nonces are updated at target node of the race. + fn finalized_target_nonces_updated( &mut self, nonces: TargetClientNonces, race_state: &mut RaceState, @@ -185,6 +192,8 @@ pub struct RaceState { pub best_finalized_source_header_id_at_best_target: Option, /// Best header id at the target client. pub best_target_header_id: Option, + /// Best finalized header id at the target client. + pub best_finalized_target_header_id: Option, /// Range of nonces that we have selected to submit. pub nonces_to_submit: Option<(SourceHeaderId, RangeInclusive, Proof)>, /// Range of nonces that is currently submitted. @@ -220,8 +229,10 @@ pub async fn run, TC: TargetClient

>( let mut target_retry_backoff = retry_backoff(); let mut target_client_is_online = true; - let mut target_nonces_required = false; - let target_nonces = futures::future::Fuse::terminated(); + let mut target_best_nonces_required = false; + let mut target_finalized_nonces_required = false; + let target_best_nonces = futures::future::Fuse::terminated(); + let target_finalized_nonces = futures::future::Fuse::terminated(); let target_submit_proof = futures::future::Fuse::terminated(); let target_go_offline_future = futures::future::Fuse::terminated(); @@ -231,7 +242,8 @@ pub async fn run, TC: TargetClient

>( source_generate_proof, source_go_offline_future, race_target_updated, - target_nonces, + target_best_nonces, + target_finalized_nonces, target_submit_proof, target_go_offline_future, ); @@ -251,14 +263,22 @@ pub async fn run, TC: TargetClient

>( }, target_state = race_target_updated.next() => { if let Some(target_state) = target_state { - let is_target_state_updated = race_state.best_target_header_id.as_ref() + let is_target_best_state_updated = race_state.best_target_header_id.as_ref() != Some(&target_state.best_self); - if is_target_state_updated { - target_nonces_required = true; + + if is_target_best_state_updated { + target_best_nonces_required = true; race_state.best_target_header_id = Some(target_state.best_self); race_state.best_finalized_source_header_id_at_best_target = Some(target_state.best_finalized_peer_at_best_self); } + + let is_target_finalized_state_updated = race_state.best_finalized_target_header_id.as_ref() + != Some(&target_state.best_finalized_self); + if is_target_finalized_state_updated { + target_finalized_nonces_required = true; + race_state.best_finalized_target_header_id = Some(target_state.best_finalized_self); + } } }, @@ -284,8 +304,8 @@ pub async fn run, TC: TargetClient

>( || format!("Error retrieving nonces from {}", P::source_name()), ).fail_if_connection_error(FailedClient::Source)?; }, - nonces = target_nonces => { - target_nonces_required = false; + nonces = target_best_nonces => { + target_best_nonces_required = false; target_client_is_online = process_future_result( nonces, @@ -293,16 +313,41 @@ pub async fn run, TC: TargetClient

>( |(_, nonces)| { log::debug!( target: "bridge", - "Received nonces from {}: {:?}", + "Received best nonces from {}: {:?}", P::target_name(), nonces, ); - strategy.target_nonces_updated(nonces, &mut race_state); + let prev_best_at_target = strategy.best_at_target(); + strategy.best_target_nonces_updated(nonces, &mut race_state); + if strategy.best_at_target() != prev_best_at_target { + stall_countdown = Instant::now(); + } }, &mut target_go_offline_future, async_std::task::sleep, - || format!("Error retrieving nonces from {}", P::target_name()), + || format!("Error retrieving best nonces from {}", P::target_name()), + ).fail_if_connection_error(FailedClient::Target)?; + }, + nonces = target_finalized_nonces => { + target_finalized_nonces_required = false; + + target_client_is_online = process_future_result( + nonces, + &mut target_retry_backoff, + |(_, nonces)| { + log::debug!( + target: "bridge", + "Received finalized nonces from {}: {:?}", + P::target_name(), + nonces, + ); + + strategy.finalized_target_nonces_updated(nonces, &mut race_state); + }, + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error retrieving finalized nonces from {}", P::target_name()), ).fail_if_connection_error(FailedClient::Target)?; }, @@ -340,6 +385,7 @@ pub async fn run, TC: TargetClient

>( race_state.nonces_to_submit = None; race_state.nonces_submitted = Some(nonces_range); + stall_countdown = Instant::now(); }, &mut target_go_offline_future, async_std::task::sleep, @@ -428,14 +474,25 @@ pub async fn run, TC: TargetClient

>( .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) .fuse(), ); - } else if target_nonces_required { - log::debug!(target: "bridge", "Asking {} about message nonces", P::target_name()); + } else if target_best_nonces_required { + log::debug!(target: "bridge", "Asking {} about best message nonces", P::target_name()); let at_block = race_state .best_target_header_id .as_ref() - .expect("target_nonces_required is only true when best_target_header_id is Some; qed") + .expect("target_best_nonces_required is only true when best_target_header_id is Some; qed") + .clone(); + target_best_nonces.set(race_target.nonces(at_block, false).fuse()); + } else if target_finalized_nonces_required { + log::debug!(target: "bridge", "Asking {} about finalized message nonces", P::target_name()); + let at_block = race_state + .best_finalized_target_header_id + .as_ref() + .expect( + "target_finalized_nonces_required is only true when\ + best_finalized_target_header_id is Some; qed", + ) .clone(); - target_nonces.set(race_target.nonces(at_block).fuse()); + target_finalized_nonces.set(race_target.nonces(at_block, true).fuse()); } else { target_client_is_online = true; } @@ -449,6 +506,7 @@ impl Default for RaceState, + update_metrics: bool, ) -> Result<(SourceHeaderIdOf

, TargetClientNonces<()>), Self::Error> { let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; - if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); + if update_metrics { + if let Some(metrics_msg) = self.metrics_msg.as_ref() { + metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); + } } Ok(( at_block, diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/messages-relay/src/message_race_strategy.rs index 45321691e6b7a..dcbcbc4d377e0 100644 --- a/relays/messages-relay/src/message_race_strategy.rs +++ b/relays/messages-relay/src/message_race_strategy.rs @@ -35,8 +35,8 @@ pub struct BasicStrategy< > { /// All queued nonces. source_queue: VecDeque<(HeaderId, SourceNoncesRange)>, - /// Best nonce known to target node. `None` if it has not been received yet. - target_nonce: Option, + /// Best nonce known to target node (at its best block). `None` if it has not been received yet. + best_target_nonce: Option, /// Unused generic types dump. _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, } @@ -52,7 +52,7 @@ where pub fn new() -> Self { BasicStrategy { source_queue: VecDeque::new(), - target_nonce: None, + best_target_nonce: None, _phantom: Default::default(), } } @@ -83,7 +83,7 @@ where mut selector: impl FnMut(SourceNoncesRange) -> Option, ) -> Option> { // if we do not know best nonce at target node, we can't select anything - let target_nonce = self.target_nonce?; + let target_nonce = self.best_target_nonce?; // if we have already selected nonces that we want to submit, do nothing if race_state.nonces_to_submit.is_some() { @@ -164,15 +164,15 @@ where fn best_at_source(&self) -> Option { let best_in_queue = self.source_queue.back().map(|(_, range)| range.end()); - match (best_in_queue, self.target_nonce) { - (Some(best_in_queue), Some(target_nonce)) if best_in_queue > target_nonce => Some(best_in_queue), - (_, Some(target_nonce)) => Some(target_nonce), + match (best_in_queue, self.best_target_nonce) { + (Some(best_in_queue), Some(best_target_nonce)) if best_in_queue > best_target_nonce => Some(best_in_queue), + (_, Some(best_target_nonce)) => Some(best_target_nonce), (_, None) => None, } } fn best_at_target(&self) -> Option { - self.target_nonce + self.best_target_nonce } fn source_nonces_updated( @@ -184,7 +184,7 @@ where .source_queue .back() .map(|(_, range)| range.end()) - .or(self.target_nonce) + .or(self.best_target_nonce) .unwrap_or_default(); self.source_queue.extend( nonces @@ -195,7 +195,7 @@ where ) } - fn target_nonces_updated( + fn best_target_nonces_updated( &mut self, nonces: TargetClientNonces<()>, race_state: &mut RaceState< @@ -206,8 +206,8 @@ where ) { let nonce = nonces.latest_nonce; - if let Some(target_nonce) = self.target_nonce { - if nonce < target_nonce { + if let Some(best_target_nonce) = self.best_target_nonce { + if nonce < best_target_nonce { return; } } @@ -241,7 +241,25 @@ where race_state.nonces_submitted = None; } - self.target_nonce = Some(nonce); + self.best_target_nonce = Some(std::cmp::max( + self.best_target_nonce.unwrap_or(nonces.latest_nonce), + nonce, + )); + } + + fn finalized_target_nonces_updated( + &mut self, + nonces: TargetClientNonces<()>, + _race_state: &mut RaceState< + HeaderId, + HeaderId, + Proof, + >, + ) { + self.best_target_nonce = Some(std::cmp::max( + self.best_target_nonce.unwrap_or(nonces.latest_nonce), + nonces.latest_nonce, + )); } fn select_nonces_to_deliver( @@ -302,7 +320,7 @@ mod tests { assert_eq!(strategy.best_at_source(), None); strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); assert_eq!(strategy.best_at_source(), None); - strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); + strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); assert_eq!(strategy.source_queue, vec![]); assert_eq!(strategy.best_at_source(), Some(10)); } @@ -310,7 +328,7 @@ mod tests { #[test] fn source_nonce_is_never_lower_than_known_target_nonce() { let mut strategy = BasicStrategy::::new(); - strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); + strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); assert_eq!(strategy.source_queue, vec![]); } @@ -327,11 +345,11 @@ mod tests { #[test] fn target_nonce_is_never_lower_than_latest_known_target_nonce() { let mut strategy = BasicStrategy::::new(); - assert_eq!(strategy.target_nonce, None); - strategy.target_nonces_updated(target_nonces(10), &mut Default::default()); - assert_eq!(strategy.target_nonce, Some(10)); - strategy.target_nonces_updated(target_nonces(5), &mut Default::default()); - assert_eq!(strategy.target_nonce, Some(10)); + assert_eq!(strategy.best_target_nonce, None); + strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); + assert_eq!(strategy.best_target_nonce, Some(10)); + strategy.best_target_nonces_updated(target_nonces(5), &mut Default::default()); + assert_eq!(strategy.best_target_nonce, Some(10)); } #[test] @@ -341,9 +359,9 @@ mod tests { strategy.source_nonces_updated(header_id(2), source_nonces(6..=10)); strategy.source_nonces_updated(header_id(3), source_nonces(11..=15)); strategy.source_nonces_updated(header_id(4), source_nonces(16..=20)); - strategy.target_nonces_updated(target_nonces(15), &mut Default::default()); + strategy.best_target_nonces_updated(target_nonces(15), &mut Default::default()); assert_eq!(strategy.source_queue, vec![(header_id(4), 16..=20)]); - strategy.target_nonces_updated(target_nonces(17), &mut Default::default()); + strategy.best_target_nonces_updated(target_nonces(17), &mut Default::default()); assert_eq!(strategy.source_queue, vec![(header_id(4), 18..=20)]); } @@ -352,9 +370,9 @@ mod tests { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); - strategy.target_nonces_updated(target_nonces(7), &mut state); + strategy.best_target_nonces_updated(target_nonces(7), &mut state); assert!(state.nonces_to_submit.is_some()); - strategy.target_nonces_updated(target_nonces(10), &mut state); + strategy.best_target_nonces_updated(target_nonces(10), &mut state); assert!(state.nonces_to_submit.is_none()); } @@ -363,9 +381,9 @@ mod tests { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(5..=10); - strategy.target_nonces_updated(target_nonces(7), &mut state); + strategy.best_target_nonces_updated(target_nonces(7), &mut state); assert!(state.nonces_submitted.is_some()); - strategy.target_nonces_updated(target_nonces(10), &mut state); + strategy.best_target_nonces_updated(target_nonces(10), &mut state); assert!(state.nonces_submitted.is_none()); } @@ -374,7 +392,7 @@ mod tests { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); - strategy.target_nonces_updated(target_nonces(0), &mut state); + strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } @@ -384,7 +402,7 @@ mod tests { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(1..=10); - strategy.target_nonces_updated(target_nonces(0), &mut state); + strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } @@ -393,7 +411,7 @@ mod tests { fn select_nonces_to_deliver_works() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); - strategy.target_nonces_updated(target_nonces(0), &mut state); + strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); strategy.source_nonces_updated(header_id(2), source_nonces(2..=2)); strategy.source_nonces_updated(header_id(3), source_nonces(3..=6)); @@ -401,12 +419,12 @@ mod tests { state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); assert_eq!(strategy.select_nonces_to_deliver(&state), Some((1..=6, ()))); - strategy.target_nonces_updated(target_nonces(6), &mut state); + strategy.best_target_nonces_updated(target_nonces(6), &mut state); assert_eq!(strategy.select_nonces_to_deliver(&state), None); state.best_finalized_source_header_id_at_best_target = Some(header_id(5)); assert_eq!(strategy.select_nonces_to_deliver(&state), Some((7..=8, ()))); - strategy.target_nonces_updated(target_nonces(8), &mut state); + strategy.best_target_nonces_updated(target_nonces(8), &mut state); assert_eq!(strategy.select_nonces_to_deliver(&state), None); } @@ -414,7 +432,7 @@ mod tests { fn select_nonces_to_deliver_able_to_split_ranges_with_selector() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); - strategy.target_nonces_updated(target_nonces(0), &mut state); + strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); state.best_finalized_source_header_id_at_source = Some(header_id(1)); @@ -433,7 +451,7 @@ mod tests { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); - strategy.target_nonces_updated(target_nonces(50), &mut state); + strategy.best_target_nonces_updated(target_nonces(50), &mut state); state.best_finalized_source_header_id_at_source = Some(header_id(1)); state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); state.best_target_header_id = Some(header_id(1)); From 1a37572bf6fcc85874659f61ce3aaf2a1a4cfcc0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 15 Feb 2021 15:11:17 +0300 Subject: [PATCH 0335/1210] remove lower limit of message weight (#727) --- bin/millau/runtime/src/rialto_messages.rs | 13 ++++++------- bin/rialto/runtime/src/millau_messages.rs | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index caec651f70167..1ba7f8361f120 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -95,17 +95,16 @@ impl MessageBridge for WithRialtoMessageBridge { bp_rialto::max_extrinsic_size() } - fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); - // given Rialto chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), - // the minimal weight of the message may be computed as message.length() - let lower_limit = u32::try_from(message_payload.len()) - .map(Into::into) - .unwrap_or(Weight::MAX); + // we're charging for payload bytes in `WithRialtoMessageBridge::weight_of_delivery_transaction` function + // + // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about + // minimal dispatch weight here - lower_limit..=upper_limit + 0..=upper_limit } fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 9207d79edb78c..b43226d60d58e 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -95,17 +95,16 @@ impl MessageBridge for WithMillauMessageBridge { bp_millau::max_extrinsic_size() } - fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { + fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()); - // given Millau chain parameters (`TransactionByteFee`, `WeightToFee`, `FeeMultiplierUpdate`), - // the minimal weight of the message may be computed as message.length() - let lower_limit = u32::try_from(message_payload.len()) - .map(Into::into) - .unwrap_or(Weight::MAX); + // we're charging for payload bytes in `WithMillauMessageBridge::weight_of_delivery_transaction` function + // + // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about + // minimal dispatch weight here - lower_limit..=upper_limit + 0..=upper_limit } fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { From c93cbdd5ed3763dc057c6bf5f795a62a7a53b956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 16 Feb 2021 07:10:01 +0100 Subject: [PATCH 0336/1210] Update to latest substrate (#723) * Bump substrate deps. * Bump scale. * Bump ethabi. * Remove inherent from aura. * Migrate to construct_runtime * cargo fmt --all --- bin/millau/node/Cargo.toml | 1 - bin/millau/node/src/service.rs | 13 ++-- bin/millau/runtime/Cargo.toml | 2 +- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/node/src/service.rs | 13 ++-- bin/rialto/runtime/Cargo.toml | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/call-dispatch/Cargo.toml | 3 +- modules/call-dispatch/src/lib.rs | 76 ++++++++++---------- modules/currency-exchange/Cargo.toml | 2 +- modules/currency-exchange/src/lib.rs | 26 ++++--- modules/ethereum-contract/builtin/Cargo.toml | 4 +- modules/ethereum/Cargo.toml | 2 +- modules/ethereum/src/mock.rs | 29 +++++--- modules/finality-verifier/Cargo.toml | 4 +- modules/finality-verifier/src/mock.rs | 28 +++++--- modules/message-lane/Cargo.toml | 2 +- modules/message-lane/src/lib.rs | 10 +-- modules/message-lane/src/mock.rs | 38 +++++----- modules/shift-session-manager/Cargo.toml | 3 +- modules/shift-session-manager/src/lib.rs | 23 +++--- modules/substrate/Cargo.toml | 4 +- modules/substrate/src/mock.rs | 23 ++++-- primitives/currency-exchange/Cargo.toml | 2 +- primitives/ethereum-poa/Cargo.toml | 4 +- primitives/header-chain/Cargo.toml | 4 +- primitives/message-dispatch/Cargo.toml | 2 +- primitives/message-lane/Cargo.toml | 2 +- primitives/millau/Cargo.toml | 4 +- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 2 +- relays/ethereum-client/Cargo.toml | 4 +- relays/ethereum/Cargo.toml | 8 +-- relays/kusama-client/Cargo.toml | 2 +- relays/millau-client/Cargo.toml | 2 +- relays/polkadot-client/Cargo.toml | 2 +- relays/rialto-client/Cargo.toml | 2 +- relays/substrate-client/Cargo.toml | 2 +- relays/substrate-client/src/error.rs | 2 +- relays/substrate/Cargo.toml | 2 +- 41 files changed, 200 insertions(+), 162 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index f1e59a45243a2..a03078163a189 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -38,7 +38,6 @@ sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "m sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-telemetry = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index aef79d9170b49..6727ee682d8d6 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -35,7 +35,6 @@ pub use sc_executor::NativeExecutor; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; -use sc_telemetry::TelemetrySpan; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -71,7 +70,6 @@ pub fn new_partial( AuraPair, >, sc_finality_grandpa::LinkHalf, - Option, ), >, ServiceError, @@ -81,7 +79,7 @@ pub fn new_partial( } let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore_container, task_manager, telemetry_span) = + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -89,6 +87,7 @@ pub fn new_partial( let transaction_pool = sc_transaction_pool::BasicPool::new_full( config.transaction_pool.clone(), + config.role.is_authority().into(), config.prometheus_registry(), task_manager.spawn_handle(), client.clone(), @@ -120,7 +119,7 @@ pub fn new_partial( select_chain, transaction_pool, inherent_data_providers, - other: (aura_block_import, grandpa_link, telemetry_span), + other: (aura_block_import, grandpa_link), }) } @@ -142,7 +141,7 @@ pub fn new_full(mut config: Configuration) -> Result select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link, telemetry_span), + other: (block_import, grandpa_link), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -276,7 +275,6 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, - telemetry_span, })?; if role.is_authority() { @@ -356,7 +354,7 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand, telemetry_span) = + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; config @@ -425,7 +423,6 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, - telemetry_span, })?; network_starter.start_network(); diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 358537e32fa4e..3173294bec793 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" serde = { version = "1.0.123", optional = true, features = ["derive"] } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index bd261f4e91835..7a4bcae9668fb 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -373,7 +373,7 @@ construct_runtime!( System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Aura: pallet_aura::{Module, Config, Inherent}, + Aura: pallet_aura::{Module, Config}, Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index f54e43b16dad2..fdac6d2327913 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -35,7 +35,6 @@ pub use sc_executor::NativeExecutor; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; -use sc_telemetry::TelemetrySpan; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -71,7 +70,6 @@ pub fn new_partial( AuraPair, >, sc_finality_grandpa::LinkHalf, - Option, ), >, ServiceError, @@ -81,7 +79,7 @@ pub fn new_partial( } let inherent_data_providers = sp_inherents::InherentDataProviders::new(); - let (client, backend, keystore_container, task_manager, telemetry_span) = + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::(&config)?; let client = Arc::new(client); @@ -89,6 +87,7 @@ pub fn new_partial( let transaction_pool = sc_transaction_pool::BasicPool::new_full( config.transaction_pool.clone(), + config.role.is_authority().into(), config.prometheus_registry(), task_manager.spawn_handle(), client.clone(), @@ -120,7 +119,7 @@ pub fn new_partial( select_chain, transaction_pool, inherent_data_providers, - other: (aura_block_import, grandpa_link, telemetry_span), + other: (aura_block_import, grandpa_link), }) } @@ -142,7 +141,7 @@ pub fn new_full(mut config: Configuration) -> Result select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link, telemetry_span), + other: (block_import, grandpa_link), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -276,7 +275,6 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, - telemetry_span, })?; if role.is_authority() { @@ -356,7 +354,7 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { - let (client, backend, keystore_container, mut task_manager, on_demand, telemetry_span) = + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::(&config)?; config @@ -425,7 +423,6 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, - telemetry_span, })?; network_starter.start_network(); diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index ebd259aa503c3..712092ea06642 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } serde = { version = "1.0.123", optional = true, features = ["derive"] } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 84055f92a6204..fc6ae5b01b4b7 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -484,7 +484,7 @@ construct_runtime!( System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Aura: pallet_aura::{Module, Config, Inherent}, + Aura: pallet_aura::{Module, Config}, Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 99cc02c20babd..1a6a5db5370e4 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index 9c25e3a8eb1d7..9b4c0bfeea443 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } # Bridge dependencies @@ -24,6 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "ma [dev-dependencies] sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +serde = "1.0" [features] default = ["std"] diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 53466607acc97..5eeca178d1484 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -395,7 +395,7 @@ where #[cfg(test)] mod tests { use super::*; - use frame_support::{impl_outer_dispatch, impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; + use frame_support::{parameter_types, weights::Weight}; use frame_system::{EventRecord, Phase}; use sp_core::H256; use sp_runtime::{ @@ -405,9 +405,6 @@ mod tests { }; type AccountId = u64; - type CallDispatch = Module; - type System = frame_system::Module; - type MessageId = [u8; 4]; #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] @@ -440,28 +437,19 @@ mod tests { } } - #[derive(Clone, Eq, PartialEq)] - pub struct TestRuntime; + type Block = frame_system::mocking::MockBlock; + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - mod call_dispatch { - pub use crate::Event; - } + use crate as call_dispatch; - impl_outer_event! { - pub enum TestEvent for TestRuntime { - frame_system, - call_dispatch, - } - } - - impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} - } - - impl_outer_dispatch! { - pub enum Call for TestRuntime where origin: Origin { - frame_system::System, - call_dispatch::CallDispatch, + frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + CallDispatch: call_dispatch::{Module, Call, Event}, } } @@ -482,10 +470,10 @@ mod tests { type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type Event = TestEvent; + type Event = Event; type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); @@ -498,7 +486,7 @@ mod tests { } impl Config for TestRuntime { - type Event = TestEvent; + type Event = Event; type MessageId = MessageId; type SourceChainAccountId = AccountId; type TargetChainAccountPublic = TestAccountPublic; @@ -586,7 +574,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageVersionSpecMismatch( + event: Event::call_dispatch(call_dispatch::Event::::MessageVersionSpecMismatch( bridge, id, TEST_SPEC_VERSION, @@ -614,7 +602,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageWeightMismatch( + event: Event::call_dispatch(call_dispatch::Event::::MessageWeightMismatch( bridge, id, 1973000, 0, )), topics: vec![], @@ -642,7 +630,9 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageSignatureMismatch(bridge, id)), + event: Event::call_dispatch(call_dispatch::Event::::MessageSignatureMismatch( + bridge, id + )), topics: vec![], }], ); @@ -662,7 +652,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageRejected(bridge, id)), + event: Event::call_dispatch(call_dispatch::Event::::MessageRejected(bridge, id)), topics: vec![], }], ); @@ -686,7 +676,9 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageCallDecodeFailed(bridge, id)), + event: Event::call_dispatch(call_dispatch::Event::::MessageCallDecodeFailed( + bridge, id + )), topics: vec![], }], ); @@ -711,7 +703,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageCallRejected(bridge, id)), + event: Event::call_dispatch(call_dispatch::Event::::MessageCallRejected(bridge, id)), topics: vec![], }], ); @@ -732,7 +724,11 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageDispatched(bridge, id, Ok(()))), + event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + bridge, + id, + Ok(()) + )), topics: vec![], }], ); @@ -755,7 +751,11 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageDispatched(bridge, id, Ok(()))), + event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + bridge, + id, + Ok(()) + )), topics: vec![], }], ); @@ -778,7 +778,11 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::call_dispatch(Event::::MessageDispatched(bridge, id, Ok(()))), + event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + bridge, + id, + Ok(()) + )), topics: vec![], }], ); diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 967d578659073..f92eb2ca7b66f 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 463b052caca90..9d1eb9f4489ba 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -212,7 +212,7 @@ fn prepare_deposit_details, I: Instance>( mod tests { use super::*; use bp_currency_exchange::LockFundsTransaction; - use frame_support::{assert_noop, assert_ok, impl_outer_origin, parameter_types, weights::Weight}; + use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight}; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -313,11 +313,19 @@ mod tests { } } - #[derive(Clone, Eq, PartialEq)] - pub struct TestRuntime; - - impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + type Block = frame_system::mocking::MockBlock; + use crate as pallet_bridge_currency_exchange; + + construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Exchange: pallet_bridge_currency_exchange::{Module}, + } } parameter_types! { @@ -330,7 +338,7 @@ mod tests { impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; - type Call = (); + type Call = Call; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -340,7 +348,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); @@ -362,8 +370,6 @@ mod tests { type DepositInto = DummyDepositInto; } - type Exchange = Module; - fn new_test_ext() -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::default() .build_storage::() diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index 1deb6a6c595a5..c65a490516f2b 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } ethereum-types = "0.11.0" -finality-grandpa = "0.12.3" +finality-grandpa = "0.13.0" hex = "0.4" log = "0.4.14" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 66db6f9586128..080957d780134 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"], optional = true } serde = { version = "1.0", optional = true } diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index af99d476b8802..bf5fc54da6e74 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -18,9 +18,9 @@ pub use crate::test_utils::{insert_header, validator_utils::*, validators_change pub use bp_eth_poa::signatures::secret_to_address; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig, PruningStrategy}; +use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy}; use bp_eth_poa::{Address, AuraHeader, H256, U256}; -use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use frame_support::{parameter_types, weights::Weight}; use secp256k1::SecretKey; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -30,11 +30,20 @@ use sp_runtime::{ pub type AccountId = u64; -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct TestRuntime; +type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} +use crate as pallet_ethereum; + +frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Ethereum: pallet_ethereum::{Module, Call}, + } } parameter_types! { @@ -47,17 +56,17 @@ parameter_types! { impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; - type Call = (); + type Call = Call; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = SubstrateHeader; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); @@ -134,7 +143,7 @@ pub fn run_test_with_genesis( let validators = validators(total_validators); let addresses = validators_addresses(total_validators); sp_io::TestExternalities::new( - GenesisConfig { + CrateGenesisConfig { initial_header: genesis.clone(), initial_difficulty: 0.into(), initial_validators: addresses.clone(), diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index b98f995b61693..060c6c3be67b6 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -8,8 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -finality-grandpa = { version = "0.12.3", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +finality-grandpa = { version = "0.13.0", default-features = false } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index d492759f1bb0f..b78cce664ba98 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -16,7 +16,7 @@ use crate::pallet::{BridgedHeader, Config}; use bp_runtime::{BlockNumberOf, Chain}; -use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use frame_support::{construct_runtime, parameter_types, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, IdentityLookup}, @@ -27,11 +27,21 @@ pub type AccountId = u64; pub type TestHeader = BridgedHeader; pub type TestNumber = BlockNumberOf<::BridgedChain>; -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct TestRuntime; +type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} +use crate as finality_verifier; + +construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Bridge: pallet_substrate_bridge::{Module}, + FinalityVerifier: finality_verifier::{Module}, + } } parameter_types! { @@ -44,7 +54,7 @@ parameter_types! { impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; - type Call = (); + type Call = Call; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -54,7 +64,7 @@ impl frame_system::Config for TestRuntime { type Event = (); type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); @@ -74,9 +84,9 @@ parameter_types! { pub const MaxRequests: u32 = 2; } -impl crate::pallet::Config for TestRuntime { +impl finality_verifier::Config for TestRuntime { type BridgedChain = TestBridgedChain; - type HeaderChain = pallet_substrate_bridge::Module; + type HeaderChain = pallet_substrate_bridge::Module; type AncestryProof = Vec<::Header>; type AncestryChecker = Checker<::Header, Self::AncestryProof>; type MaxRequests = MaxRequests; diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 83721a645fdb3..be07b1173ac9a 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } num-traits = { version = "0.2", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index d6ae1d092573b..117bd2b465b84 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -821,9 +821,9 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, run_test, Origin, TestEvent, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, - TestMessagesProof, TestPayload, TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, - TEST_RELAYER_A, TEST_RELAYER_B, + message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, + TestMessagesDeliveryProof, TestMessagesProof, TestPayload, TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, + REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_message_lane::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; @@ -847,7 +847,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::message_lane(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), + event: TestEvent::pallet_message_lane(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), topics: vec![], }], ); @@ -876,7 +876,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::message_lane(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), + event: TestEvent::pallet_message_lane(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), topics: vec![], }], ); diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 244d580f05782..340360a126806 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -25,7 +25,7 @@ use bp_message_lane::{ }; use bp_runtime::Size; use codec::{Decode, Encode}; -use frame_support::{impl_outer_event, impl_outer_origin, parameter_types, weights::Weight}; +use frame_support::{parameter_types, weights::Weight}; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -49,25 +49,23 @@ impl sp_runtime::traits::Convert for AccountIdConverter { } } -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct TestRuntime; +type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -mod message_lane { - pub use crate::Event; -} +use crate as pallet_message_lane; -impl_outer_event! { - pub enum TestEvent for TestRuntime { - frame_system, - pallet_balances, - message_lane, +frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Balances: pallet_balances::{Module, Call, Event}, + MessageLane: pallet_message_lane::{Module, Call, Event}, } } -impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} -} - parameter_types! { pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = 1024; @@ -78,17 +76,17 @@ parameter_types! { impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; - type Call = (); + type Call = Call; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = SubstrateHeader; - type Event = TestEvent; + type Event = Event; type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); @@ -108,7 +106,7 @@ impl pallet_balances::Config for TestRuntime { type MaxLocks = (); type Balance = Balance; type DustRemoval = (); - type Event = TestEvent; + type Event = Event; type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Module; type WeightInfo = (); @@ -121,7 +119,7 @@ parameter_types! { } impl Config for TestRuntime { - type Event = TestEvent; + type Event = Event; type WeightInfo = (); type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 1cba12f2f5c58..04a5194c34942 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } # Substrate Dependencies @@ -20,6 +20,7 @@ sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +serde = "1.0" [features] default = ["std"] diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 0d16e0b7d1f42..ef96fc5318c1d 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -93,16 +93,23 @@ mod tests { traits::{BlakeTwo256, ConvertInto, IdentityLookup}, Perbill, RuntimeAppPublic, }; - use frame_support::{impl_outer_origin, parameter_types, weights::Weight, BasicExternalities}; + use frame_support::{parameter_types, weights::Weight, BasicExternalities}; use sp_core::H256; type AccountId = u64; - #[derive(Clone, Eq, PartialEq)] - pub struct TestRuntime; - - impl_outer_origin! { - pub enum Origin for TestRuntime {} + type Block = frame_system::mocking::MockBlock; + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + + frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Session: pallet_session::{Module}, + } } parameter_types! { @@ -115,7 +122,7 @@ mod tests { impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; - type Call = (); + type Call = Call; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -125,7 +132,7 @@ mod tests { type Event = (); type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 02c3b17047eef..dd047d6b89907 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -8,8 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -finality-grandpa = { version = "0.12.3", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +finality-grandpa = { version = "0.13.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } serde = { version = "1.0", optional = true } diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index e5b0c26c13ab2..c13c466c3a810 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -22,7 +22,7 @@ use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader, Config}; use bp_runtime::Chain; -use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use frame_support::{parameter_types, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, IdentityLookup}, @@ -34,11 +34,20 @@ pub type TestHeader = BridgedHeader; pub type TestNumber = BridgedBlockNumber; pub type TestHash = BridgedBlockHash; -#[derive(Clone, Eq, PartialEq, Debug)] -pub struct TestRuntime; +type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -impl_outer_origin! { - pub enum Origin for TestRuntime where system = frame_system {} +use crate as pallet_substrate; + +frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Module, Call, Config, Storage, Event}, + Substrate: pallet_substrate::{Module, Call}, + } } parameter_types! { @@ -51,7 +60,7 @@ parameter_types! { impl frame_system::Config for TestRuntime { type Origin = Origin; type Index = u64; - type Call = (); + type Call = Call; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; @@ -61,7 +70,7 @@ impl frame_system::Config for TestRuntime { type Event = (); type BlockHashCount = BlockHashCount; type Version = (); - type PalletInfo = (); + type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 01f7005902b32..585855b294ee3 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } # Substrate Dependencies diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 726ca04c74bc4..86cb43193c003 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } ethbloom = { version = "0.10.0", default-features = false, features = ["rlp"] } fixed-hash = { version = "0.7", default-features = false } hash-db = { version = "0.15.2", default-features = false } @@ -16,7 +16,7 @@ impl-serde = { version = "0.3.1", optional = true } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } parity-bytes = { version = "0.1", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } -primitive-types = { version = "0.8", default-features = false, features = ["codec", "rlp"] } +primitive-types = { version = "0.9", default-features = false, features = ["codec", "rlp"] } rlp = { version = "0.5", default-features = false } serde = { version = "1.0", optional = true } serde-big-array = { version = "0.2", optional = true } diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index ecd5f05940e0e..0dc169303929c 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } -finality-grandpa = { version = "0.12.3", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +finality-grandpa = { version = "0.13.0", default-features = false } serde = { version = "1.0", optional = true } # Substrate Dependencies diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index a6bf4b7cc57dc..293c637e8df25 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } [features] default = ["std"] diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index e002ccd36a235..451a3c0400ad0 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index b72a0f4018b64..aea2f8eec2efc 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -14,9 +14,9 @@ bp-message-lane = { path = "../message-lane", default-features = false } bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } -impl-codec = { version = "0.4.2", default-features = false } +impl-codec = { version = "0.5.0", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.8.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.9.0", default-features = false, features = ["primitive-types"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index a5aaa1cfa6444..50305013cebf1 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.1", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } num-traits = { version = "0.2", default-features = false } # Substrate Dependencies diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index aa330d4521f4b..944700e9d3c3e 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -finality-grandpa = { version = "0.12.3" } +finality-grandpa = { version = "0.13.0" } bp-header-chain = { path = "../header-chain" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/ethereum-client/Cargo.toml b/relays/ethereum-client/Cargo.toml index ad50a18e3967a..b0f6485ffd384 100644 --- a/relays/ethereum-client/Cargo.toml +++ b/relays/ethereum-client/Cargo.toml @@ -7,11 +7,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-eth-poa = { path = "../../primitives/ethereum-poa" } -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers-relay" } hex-literal = "0.3" jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } -web3 = { version = "0.15", default-features = false } +web3 = { version = "0.15", git = "https://github.com/tomusdrw/rust-web3.git", branch ="td-ethabi", default-features = false } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 8f58c27330ea0..3343548555689 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -10,11 +10,11 @@ ansi_term = "0.12" async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } env_logger = "0.8.2" -ethabi = "13.0" -ethabi-contract = "11.0" -ethabi-derive = "13.0" +ethabi = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } +ethabi-contract = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } +ethabi-derive = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } futures = "0.3.12" hex = "0.4" hex-literal = "0.3" diff --git a/relays/kusama-client/Cargo.toml b/relays/kusama-client/Cargo.toml index 4ea971f0e14f8..6695758113ad7 100644 --- a/relays/kusama-client/Cargo.toml +++ b/relays/kusama-client/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers-relay" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index 3ca425730730a..c05d44a42e92c 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers-relay" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } diff --git a/relays/polkadot-client/Cargo.toml b/relays/polkadot-client/Cargo.toml index e4b1d84eaa110..5a05aa0a2cf46 100644 --- a/relays/polkadot-client/Cargo.toml +++ b/relays/polkadot-client/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers-relay" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml index 007ddfd26721e..6c90defe37a11 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/rialto-client/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers-relay" } relay-substrate-client = { path = "../substrate-client" } relay-utils = { path = "../utils" } diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 320abf280f040..1c60f861e2e5a 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" async-trait = "0.1.40" -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["ws"] } log = "0.4.11" num-traits = "0.2" diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index f0212ed501ae2..f5bb250d9fb47 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -78,7 +78,7 @@ impl ToString for Error { match self { Self::WsConnectionError(e) => e.to_string(), Self::Request(e) => e.to_string(), - Self::ResponseParseFailed(e) => e.what().to_string(), + Self::ResponseParseFailed(e) => e.to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 137741a135424..6ea5e839d8ef0 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.9.0" async-trait = "0.1.42" -codec = { package = "parity-scale-codec", version = "1.3.4" } +codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.12" hex = "0.4" log = "0.4.14" From 6bd36cf09eccbb937409edbe11373dc45d811c1d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 16 Feb 2021 13:04:44 +0300 Subject: [PATCH 0337/1210] Bump env_logger from 0.8.2 to 0.8.3 (#725) Bumps [env_logger](https://github.com/env-logger-rs/env_logger) from 0.8.2 to 0.8.3. - [Release notes](https://github.com/env-logger-rs/env_logger/releases) - [Changelog](https://github.com/env-logger-rs/env_logger/blob/master/CHANGELOG.md) - [Commits](https://github.com/env-logger-rs/env_logger/compare/v0.8.2...v0.8.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 3343548555689..0e9fdb7c8a88f 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "2.0.0" } -env_logger = "0.8.2" +env_logger = "0.8.3" ethabi = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } ethabi-contract = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } ethabi-derive = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } From b2f0f313733f40ca0e98f3efab4ca621b42d8bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 16 Feb 2021 16:26:38 +0100 Subject: [PATCH 0338/1210] Rework relay CLI a bit (#734) * Change CLI UX. * De-duplicate main. * De-duplicate send message. * Add more docs and extract functions. * Fix scripts. * cargo fmt --all * Add missing 'u'. --- relays/substrate/src/cli.rs | 123 +++++--- relays/substrate/src/main.rs | 544 +++++++++++++++++------------------ 2 files changed, 339 insertions(+), 328 deletions(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index a6dd5ab67b33c..96f13d33841ab 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -26,12 +26,36 @@ pub fn parse_args() -> Command { Command::from_args() } -/// Substrate-to-Substrate relay CLI args. +/// Substrate-to-Substrate bridge utilities. #[derive(StructOpt)] #[structopt(about = "Substrate-to-Substrate relay")] pub enum Command { - /// Initialize Millau headers bridge in Rialto. - InitializeMillauHeadersBridgeInRialto { + /// Start headers relay between two chains. + /// + /// The on-chain bridge component should have been already initialized with + /// `init-bridge` sub-command. + RelayHeaders(RelayHeaders), + /// Start messages relay between two chains. + /// + /// Ties up to `MessageLane` pallets on both chains and starts relaying messages. + /// Requires the header relay to be already running. + RelayMessages(RelayMessages), + /// Initialize on-chain bridge pallet with current header data. + /// + /// Sends initialization transaction to bootstrap the bridge with current finalized block data. + InitBridge(InitBridge), + /// Send custom message over the bridge. + /// + /// Allows interacting with the bridge by sending messages over `MessageLane` component. + /// The message is being sent to the source chain, delivered to the target chain and dispatched + /// there. + SendMessage(SendMessage), +} + +#[derive(StructOpt)] +pub enum RelayHeaders { + /// Relay Millau headers to Rialto. + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] @@ -39,59 +63,87 @@ pub enum Command { #[structopt(flatten)] rialto_sign: RialtoSigningParams, #[structopt(flatten)] - millau_bridge_params: MillauBridgeInitializationParams, + prometheus_params: PrometheusParams, }, - /// Relay Millau headers to Rialto. - MillauHeadersToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, + /// Relay Rialto headers to Millau. + RialtoToMillau { #[structopt(flatten)] rialto: RialtoConnectionParams, #[structopt(flatten)] - rialto_sign: RialtoSigningParams, + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, #[structopt(flatten)] prometheus_params: PrometheusParams, }, - /// Initialize Rialto headers bridge in Millau. - InitializeRialtoHeadersBridgeInMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, +} + +#[derive(StructOpt)] +pub enum RelayMessages { + /// Serve given lane of Millau -> Rialto messages. + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] millau_sign: MillauSigningParams, #[structopt(flatten)] - rialto_bridge_params: RialtoBridgeInitializationParams, + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + /// Hex-encoded id of lane that should be served by relay. + #[structopt(long)] + lane: HexLaneId, }, - /// Relay Rialto headers to Millau. - RialtoHeadersToMillau { + /// Serve given lane of Rialto -> Millau messages. + RialtoToMillau { #[structopt(flatten)] rialto: RialtoConnectionParams, #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] millau_sign: MillauSigningParams, #[structopt(flatten)] prometheus_params: PrometheusParams, + /// Hex-encoded id of lane that should be served by relay. + #[structopt(long)] + lane: HexLaneId, }, - /// Serve given lane of Millau -> Rialto messages. - MillauMessagesToRialto { +} + +#[derive(StructOpt)] +pub enum InitBridge { + /// Initialize Millau headers bridge in Rialto. + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] rialto: RialtoConnectionParams, #[structopt(flatten)] rialto_sign: RialtoSigningParams, #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded id of lane that should be served by relay. - #[structopt(long)] - lane: HexLaneId, + millau_bridge_params: MillauBridgeInitializationParams, }, + /// Initialize Rialto headers bridge in Millau. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto_bridge_params: RialtoBridgeInitializationParams, + }, +} + +#[derive(StructOpt)] +pub enum SendMessage { /// Submit message to given Millau -> Rialto lane. - SubmitMillauToRialtoMessage { + MillauToRialto { #[structopt(flatten)] millau: MillauConnectionParams, #[structopt(flatten)] @@ -111,24 +163,8 @@ pub enum Command { #[structopt(long, possible_values = &Origins::variants())] origin: Origins, }, - /// Serve given lane of Rialto -> Millau messages. - RialtoMessagesToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded id of lane that should be served by relay. - #[structopt(long)] - lane: HexLaneId, - }, /// Submit message to given Rialto -> Millau lane. - SubmitRialtoToMillauMessage { + RialtoToMillau { #[structopt(flatten)] rialto: RialtoConnectionParams, #[structopt(flatten)] @@ -181,6 +217,9 @@ pub enum ToMillauMessage { arg_enum! { #[derive(Debug)] /// The origin to use when dispatching the message on the target chain. + /// + /// - `Target` uses account existing on the target chain (requires target private key). + /// - `Origin` uses account derived from the source-chain account. pub enum Origins { Target, Source, diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index e0d6149870994..c700022a0f1b9 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -60,27 +60,25 @@ fn main() { async fn run_command(command: cli::Command) -> Result<(), String> { match command { - cli::Command::InitializeMillauHeadersBridgeInRialto { + cli::Command::InitBridge(arg) => run_init_bridge(arg).await, + cli::Command::RelayHeaders(arg) => run_relay_headers(arg).await, + cli::Command::RelayMessages(arg) => run_relay_messages(arg).await, + cli::Command::SendMessage(arg) => run_send_message(arg).await, + } +} + +async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { + match command { + cli::InitBridge::MillauToRialto { millau, rialto, rialto_sign, millau_bridge_params, } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_client = millau.into_client().await?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let rialto_signer_next_index = rialto_client .next_account_index(rialto_sign.signer.public().into()) .await?; @@ -108,50 +106,15 @@ async fn run_command(command: cli::Command) -> Result<(), String> { ) .await; } - cli::Command::MillauHeadersToRialto { - millau, - rialto, - rialto_sign, - prometheus_params, - } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; - } - cli::Command::InitializeRialtoHeadersBridgeInMillau { + cli::InitBridge::RialtoToMillau { rialto, millau, millau_sign, rialto_bridge_params, } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; + let rialto_client = rialto.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; let millau_signer_next_index = millau_client .next_account_index(millau_sign.signer.public().into()) .await?; @@ -179,31 +142,41 @@ async fn run_command(command: cli::Command) -> Result<(), String> { ) .await; } - cli::Command::RialtoHeadersToMillau { + } + Ok(()) +} + +async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { + match command { + cli::RelayHeaders::MillauToRialto { + millau, + rialto, + rialto_sign, + prometheus_params, + } => { + let millau_client = millau.into_client().await?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; + } + cli::RelayHeaders::RialtoToMillau { rialto, millau, millau_sign, prometheus_params, } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - + let rialto_client = rialto.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; } - cli::Command::MillauMessagesToRialto { + } + Ok(()) +} + +async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { + match command { + cli::RelayMessages::MillauToRialto { millau, millau_sign, rialto, @@ -211,26 +184,10 @@ async fn run_command(command: cli::Command) -> Result<(), String> { prometheus_params, lane, } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; millau_messages_to_rialto::run( millau_client, @@ -241,7 +198,35 @@ async fn run_command(command: cli::Command) -> Result<(), String> { prometheus_params.into(), ); } - cli::Command::SubmitMillauToRialtoMessage { + cli::RelayMessages::RialtoToMillau { + rialto, + rialto_sign, + millau, + millau_sign, + prometheus_params, + lane, + } => { + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + + rialto_messages_to_millau::run( + rialto_client, + rialto_sign, + millau_client, + millau_sign, + lane.into(), + prometheus_params.into(), + ); + } + } + Ok(()) +} + +async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { + match command { + cli::SendMessage::MillauToRialto { millau, millau_sign, rialto_sign, @@ -251,89 +236,23 @@ async fn run_command(command: cli::Command) -> Result<(), String> { origin, .. } => { - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - - let rialto_call = match message { - cli::ToRialtoMessage::Remark => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( - format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - )), - cli::ToRialtoMessage::Transfer { recipient, amount } => { - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) - } - }; - - let rialto_call_weight = rialto_call.get_dispatch_info().weight; - let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); - let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); - let rialto_origin_public = rialto_sign.signer.public(); - - let payload = match origin { - cli::Origins::Source => MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: CallOrigin::SourceAccount(millau_account_id), - call: rialto_call.encode(), - }, - cli::Origins::Target => { - let digest = millau_runtime::rialto_account_ownership_digest( - &rialto_call, - millau_account_id.clone(), - rialto_runtime::VERSION.spec_version, - ); - - let digest_signature = rialto_sign.signer.sign(&digest); - - MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: CallOrigin::TargetAccount( - millau_account_id, - rialto_origin_public.into(), - digest_signature.into(), - ), - call: rialto_call.encode(), - } - } - }; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let rialto_sign = rialto_sign.parse()?; + let rialto_call = message.into_call(); + + let payload = millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin); let lane = lane.into(); - let fee = match fee { - Some(fee) => fee, - None => match estimate_message_delivery_and_dispatch_fee( + let fee = get_fee(fee, || { + estimate_message_delivery_and_dispatch_fee( &millau_client, bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone(), ) - .await - { - Ok(Some(fee)) => fee, - Ok(None) => return Err("Failed to estimate message fee. Message is too heavy?".into()), - Err(error) => return Err(format!("Failed to estimate message fee: {:?}", error)), - }, - }; + }) + .await?; log::info!(target: "bridge", "Sending message to Rialto. Fee: {}", fee); @@ -354,45 +273,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .submit_extrinsic(Bytes(signed_millau_call.encode())) .await?; } - cli::Command::RialtoMessagesToMillau { - rialto, - rialto_sign, - millau, - millau_sign, - prometheus_params, - lane, - } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - let millau_client = MillauClient::new(ConnectionParams { - host: millau.millau_host, - port: millau.millau_port, - }) - .await?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - - rialto_messages_to_millau::run( - rialto_client, - rialto_sign, - millau_client, - millau_sign, - lane.into(), - prometheus_params.into(), - ); - } - cli::Command::SubmitRialtoToMillauMessage { + cli::SendMessage::RialtoToMillau { rialto, rialto_sign, millau_sign, @@ -402,89 +283,23 @@ async fn run_command(command: cli::Command) -> Result<(), String> { origin, .. } => { - let rialto_client = RialtoClient::new(ConnectionParams { - host: rialto.rialto_host, - port: rialto.rialto_port, - }) - .await?; - let rialto_sign = RialtoSigningParams::from_suri( - &rialto_sign.rialto_signer, - rialto_sign.rialto_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e))?; - let millau_sign = MillauSigningParams::from_suri( - &millau_sign.millau_signer, - millau_sign.millau_signer_password.as_deref(), - ) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e))?; - - let millau_call = match message { - cli::ToMillauMessage::Remark => millau_runtime::Call::System(millau_runtime::SystemCall::remark( - format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - )), - cli::ToMillauMessage::Transfer { recipient, amount } => { - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) - } - }; - - let millau_call_weight = millau_call.get_dispatch_info().weight; - let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); - let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); - let millau_origin_public = millau_sign.signer.public(); - - let payload = match origin { - cli::Origins::Source => MessagePayload { - spec_version: millau_runtime::VERSION.spec_version, - weight: millau_call_weight, - origin: CallOrigin::SourceAccount(rialto_account_id), - call: millau_call.encode(), - }, - cli::Origins::Target => { - let digest = rialto_runtime::millau_account_ownership_digest( - &millau_call, - rialto_account_id.clone(), - millau_runtime::VERSION.spec_version, - ); - - let digest_signature = millau_sign.signer.sign(&digest); - - MessagePayload { - spec_version: millau_runtime::VERSION.spec_version, - weight: millau_call_weight, - origin: CallOrigin::TargetAccount( - rialto_account_id, - millau_origin_public.into(), - digest_signature.into(), - ), - call: millau_call.encode(), - } - } - }; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let millau_sign = millau_sign.parse()?; + let millau_call = message.into_call(); + + let payload = rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin); let lane = lane.into(); - let fee = match fee { - Some(fee) => fee, - None => match estimate_message_delivery_and_dispatch_fee( + let fee = get_fee(fee, || { + estimate_message_delivery_and_dispatch_fee( &rialto_client, bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone(), ) - .await - { - Ok(Some(fee)) => fee, - Ok(None) => return Err("Failed to estimate message fee. Message is too heavy?".into()), - Err(error) => return Err(format!("Failed to estimate message fee: {:?}", error)), - }, - }; + }) + .await?; log::info!(target: "bridge", "Sending message to Millau. Fee: {}", fee); @@ -506,7 +321,6 @@ async fn run_command(command: cli::Command) -> Result<(), String> { .await?; } } - Ok(()) } @@ -524,6 +338,164 @@ async fn estimate_message_delivery_and_dispatch_fee Vec { + format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec() +} + +fn rialto_to_millau_message_payload( + rialto_sign: &RialtoSigningParams, + millau_sign: &MillauSigningParams, + millau_call: &millau_runtime::Call, + origin: cli::Origins, +) -> rialto_runtime::millau_messages::ToMillauMessagePayload { + let millau_call_weight = millau_call.get_dispatch_info().weight; + let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); + let millau_origin_public = millau_sign.signer.public(); + + MessagePayload { + spec_version: millau_runtime::VERSION.spec_version, + weight: millau_call_weight, + origin: match origin { + cli::Origins::Source => CallOrigin::SourceAccount(rialto_account_id), + cli::Origins::Target => { + let digest = rialto_runtime::millau_account_ownership_digest( + &millau_call, + rialto_account_id.clone(), + millau_runtime::VERSION.spec_version, + ); + + let digest_signature = millau_sign.signer.sign(&digest); + + CallOrigin::TargetAccount(rialto_account_id, millau_origin_public.into(), digest_signature.into()) + } + }, + call: millau_call.encode(), + } +} + +fn millau_to_rialto_message_payload( + millau_sign: &MillauSigningParams, + rialto_sign: &RialtoSigningParams, + rialto_call: &rialto_runtime::Call, + origin: cli::Origins, +) -> millau_runtime::rialto_messages::ToRialtoMessagePayload { + let rialto_call_weight = rialto_call.get_dispatch_info().weight; + let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); + let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); + let rialto_origin_public = rialto_sign.signer.public(); + + MessagePayload { + spec_version: rialto_runtime::VERSION.spec_version, + weight: rialto_call_weight, + origin: match origin { + cli::Origins::Source => CallOrigin::SourceAccount(millau_account_id), + cli::Origins::Target => { + let digest = millau_runtime::rialto_account_ownership_digest( + &rialto_call, + millau_account_id.clone(), + rialto_runtime::VERSION.spec_version, + ); + + let digest_signature = rialto_sign.signer.sign(&digest); + + CallOrigin::TargetAccount(millau_account_id, rialto_origin_public.into(), digest_signature.into()) + } + }, + call: rialto_call.encode(), + } +} + +async fn get_fee(fee: Option, f: F) -> Result +where + Fee: Decode, + F: FnOnce() -> R, + R: std::future::Future, E>>, + E: std::fmt::Debug, +{ + match fee { + Some(fee) => Ok(fee), + None => match f().await { + Ok(Some(fee)) => Ok(fee), + Ok(None) => Err("Failed to estimate message fee. Message is too heavy?".into()), + Err(error) => Err(format!("Failed to estimate message fee: {:?}", error)), + }, + } +} + +impl crate::cli::RialtoSigningParams { + /// Parse CLI parameters into typed signing params. + pub fn parse(self) -> Result { + RialtoSigningParams::from_suri(&self.rialto_signer, self.rialto_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e)) + } +} + +impl crate::cli::MillauSigningParams { + /// Parse CLI parameters into typed signing params. + pub fn parse(self) -> Result { + MillauSigningParams::from_suri(&self.millau_signer, self.millau_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e)) + } +} + +impl crate::cli::MillauConnectionParams { + /// Convert CLI connection parameters into Millau RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + MillauClient::new(ConnectionParams { + host: self.millau_host, + port: self.millau_port, + }) + .await + } +} +impl crate::cli::RialtoConnectionParams { + /// Convert CLI connection parameters into Rialto RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + RialtoClient::new(ConnectionParams { + host: self.rialto_host, + port: self.rialto_port, + }) + .await + } +} + +impl crate::cli::ToRialtoMessage { + /// Convert CLI call request into runtime `Call` instance. + pub fn into_call(self) -> rialto_runtime::Call { + match self { + cli::ToRialtoMessage::Remark => { + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload())) + } + cli::ToRialtoMessage::Transfer { recipient, amount } => { + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) + } + } + } +} + +impl crate::cli::ToMillauMessage { + /// Convert CLI call request into runtime `Call` instance. + pub fn into_call(self) -> millau_runtime::Call { + match self { + cli::ToMillauMessage::Remark => { + millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload())) + } + cli::ToMillauMessage::Transfer { recipient, amount } => { + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) + } + } + } +} + #[cfg(test)] mod tests { use sp_core::Pair; From 81019a67d71aac22941fc45f18f01f06dfc76a03 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 17 Feb 2021 15:09:02 +0300 Subject: [PATCH 0339/1210] ForbidOutboundMessages and ForbidInboundMessages (#735) --- primitives/message-lane/src/source_chain.rs | 56 +++++++++++++++++++++ primitives/message-lane/src/target_chain.rs | 29 +++++++++++ primitives/runtime/src/lib.rs | 6 +++ 3 files changed, 91 insertions(+) diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/message-lane/src/source_chain.rs index 1bb0d591586f9..d0dc36bb69352 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/message-lane/src/source_chain.rs @@ -134,3 +134,59 @@ pub trait MessageDeliveryAndDispatchPayment { 0 } } + +/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and +/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden. +pub struct ForbidOutboundMessages; + +/// Error message that is used in `ForbidOutboundMessages` implementation. +const ALL_OUTBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all outbound messages"; + +impl TargetHeaderChain for ForbidOutboundMessages { + type Error = &'static str; + + type MessagesDeliveryProof = (); + + fn verify_message(_payload: &Payload) -> Result<(), Self::Error> { + Err(ALL_OUTBOUND_MESSAGES_REJECTED) + } + + fn verify_messages_delivery_proof( + _proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + Err(ALL_OUTBOUND_MESSAGES_REJECTED) + } +} + +impl LaneMessageVerifier for ForbidOutboundMessages { + type Error = &'static str; + + fn verify_message( + _submitter: &Sender, + _delivery_and_dispatch_fee: &Fee, + _lane: &LaneId, + _outbound_data: &OutboundLaneData, + _payload: &Payload, + ) -> Result<(), Self::Error> { + Err(ALL_OUTBOUND_MESSAGES_REJECTED) + } +} + +impl MessageDeliveryAndDispatchPayment for ForbidOutboundMessages { + type Error = &'static str; + + fn pay_delivery_and_dispatch_fee( + _submitter: &Sender, + _fee: &Balance, + _relayer_fund_account: &AccountId, + ) -> Result<(), Self::Error> { + Err(ALL_OUTBOUND_MESSAGES_REJECTED) + } + + fn pay_relayers_rewards( + _confirmation_relayer: &AccountId, + _relayers_rewards: RelayersRewards, + _relayer_fund_account: &AccountId, + ) { + } +} diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/message-lane/src/target_chain.rs index 825fe67c54915..765ce64f63b39 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/message-lane/src/target_chain.rs @@ -129,3 +129,32 @@ impl From> for DispatchMessageDat } } } + +/// Structure that may be used in place of `SourceHeaderChain` and `MessageDispatch` on chains, +/// where inbound messages are forbidden. +pub struct ForbidInboundMessages; + +/// Error message that is used in `ForbidOutboundMessages` implementation. +const ALL_INBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all inbound messages"; + +impl SourceHeaderChain for ForbidInboundMessages { + type Error = &'static str; + type MessagesProof = (); + + fn verify_messages_proof( + _proof: Self::MessagesProof, + _messages_count: u32, + ) -> Result>, Self::Error> { + Err(ALL_INBOUND_MESSAGES_REJECTED) + } +} + +impl MessageDispatch for ForbidInboundMessages { + type DispatchPayload = (); + + fn dispatch_weight(_message: &DispatchMessage) -> Weight { + Weight::MAX + } + + fn dispatch(_message: DispatchMessage) {} +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 058c510c1b526..6612e26c37dca 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -112,6 +112,12 @@ pub trait Size { fn size_hint(&self) -> u32; } +impl Size for () { + fn size_hint(&self) -> u32 { + 0 + } +} + /// Pre-computed size. pub struct PreComputedSize(pub usize); From 67fccad03845c6c063d3defb95ec07a2f106b140 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 17 Feb 2021 15:38:25 +0300 Subject: [PATCH 0340/1210] Fix updated clippy grumbles (#733) * Revert "Pin Rust Nightly to 2020-12-17 (#652)" This reverts commit e54e6f7e3d34c28d698e637f9099162b3c1917e9. * fix clippy * clippy again * more clippy in test code * and new cargo fmt * another try --- bin/millau/runtime/src/lib.rs | 2 ++ bin/rialto/runtime/src/lib.rs | 2 ++ modules/call-dispatch/src/lib.rs | 3 +++ modules/currency-exchange/src/lib.rs | 3 +++ modules/ethereum-contract/builtin/src/lib.rs | 6 +++--- modules/ethereum/src/mock.rs | 3 +++ modules/finality-verifier/src/mock.rs | 3 +++ modules/message-lane/src/mock.rs | 3 +++ modules/shift-session-manager/src/lib.rs | 3 +++ modules/substrate/src/mock.rs | 2 ++ primitives/header-chain/src/justification.rs | 4 ++-- relays/ethereum-client/src/error.rs | 3 +-- relays/ethereum/src/main.rs | 2 -- relays/substrate-client/src/error.rs | 3 +-- 14 files changed, 31 insertions(+), 11 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7a4bcae9668fb..8217967020768 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -23,6 +23,8 @@ #![allow(clippy::large_enum_variant)] // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +// From construct_runtime macro +#![allow(clippy::from_over_into)] // Make the WASM binary available. #[cfg(feature = "std")] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index fc6ae5b01b4b7..4881dea298298 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -23,6 +23,8 @@ #![allow(clippy::large_enum_variant)] // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] +// From construct_runtime macro +#![allow(clippy::from_over_into)] // Make the WASM binary available. #[cfg(feature = "std")] diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 5eeca178d1484..7f41322455455 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -394,6 +394,9 @@ where #[cfg(test)] mod tests { + // From construct_runtime macro + #![allow(clippy::from_over_into)] + use super::*; use frame_support::{parameter_types, weights::Weight}; use frame_system::{EventRecord, Phase}; diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 9d1eb9f4489ba..7c7d7e4a4d0fc 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -210,6 +210,9 @@ fn prepare_deposit_details, I: Instance>( #[cfg(test)] mod tests { + // From construct_runtime macro + #![allow(clippy::from_over_into)] + use super::*; use bp_currency_exchange::LockFundsTransaction; use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight}; diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract/builtin/src/lib.rs index abb7375103dff..5762d510b2a90 100644 --- a/modules/ethereum-contract/builtin/src/lib.rs +++ b/modules/ethereum-contract/builtin/src/lib.rs @@ -85,7 +85,7 @@ pub fn from_substrate_block_number(number: BlockNumber) -> Result { /// Parse Substrate header. pub fn parse_substrate_header(raw_header: &[u8]) -> Result { - let substrate_header = RuntimeHeader::decode(&mut &raw_header[..]) + let substrate_header = RuntimeHeader::decode(&mut &*raw_header) .map(|header| Header { hash: header.hash(), parent_hash: header.parent_hash, @@ -100,7 +100,7 @@ pub fn parse_substrate_header(raw_header: &[u8]) -> Result { } }) }) - .and_then(|log| ConsensusLog::decode(&mut &log[..]).ok()) + .and_then(|log| ConsensusLog::decode(&mut &*log).ok()) .and_then(|log| match log { ConsensusLog::ScheduledChange(scheduled_change) => Some(ValidatorsSetSignal { delay: scheduled_change.delay, @@ -133,7 +133,7 @@ pub fn verify_substrate_finality_proof( raw_best_set: &[u8], raw_finality_proof: &[u8], ) -> Result<(), Error> { - let best_set = AuthorityList::decode(&mut &raw_best_set[..]) + let best_set = AuthorityList::decode(&mut &*raw_best_set) .map_err(Error::BestSetDecode) .and_then(|authorities| VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet)); diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index bf5fc54da6e74..6808062d4d0c3 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +// From construct_runtime macro +#![allow(clippy::from_over_into)] + pub use crate::test_utils::{insert_header, validator_utils::*, validators_change_receipt, HeaderBuilder, GAS_LIMIT}; pub use bp_eth_poa::signatures::secret_to_address; diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index b78cce664ba98..26890d9d23a1f 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +// From construct_runtime macro +#![allow(clippy::from_over_into)] + use crate::pallet::{BridgedHeader, Config}; use bp_runtime::{BlockNumberOf, Chain}; use frame_support::{construct_runtime, parameter_types, weights::Weight}; diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 340360a126806..948c107d0518b 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +// From construct_runtime macro +#![allow(clippy::from_over_into)] + use crate::Config; use bp_message_lane::{ diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index ef96fc5318c1d..6fc92d73eceb2 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -86,6 +86,9 @@ impl Module { #[cfg(test)] mod tests { + // From construct_runtime macro + #![allow(clippy::from_over_into)] + use super::*; use frame_support::sp_io::TestExternalities; use frame_support::sp_runtime::{ diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index c13c466c3a810..85782b7ea4fe1 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -19,6 +19,8 @@ //! Includes some useful testing types and functions. #![cfg(test)] +// From construct_runtime macro +#![allow(clippy::from_over_into)] use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader, Config}; use bp_runtime::Chain; diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 3e4b9043c08a5..929ef17bdca2e 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -48,7 +48,7 @@ pub enum Error { pub fn decode_justification_target( raw_justification: &[u8], ) -> Result<(Header::Hash, Header::Number), Error> { - GrandpaJustification::

::decode(&mut &raw_justification[..]) + GrandpaJustification::
::decode(&mut &*raw_justification) .map(|justification| (justification.commit.target_hash, justification.commit.target_number)) .map_err(|_| Error::JustificationDecode) } @@ -65,7 +65,7 @@ where { // Decode justification first let justification = - GrandpaJustification::
::decode(&mut &raw_justification[..]).map_err(|_| Error::JustificationDecode)?; + GrandpaJustification::
::decode(&mut &*raw_justification).map_err(|_| Error::JustificationDecode)?; // Ensure that it is justification for the expected header if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { diff --git a/relays/ethereum-client/src/error.rs b/relays/ethereum-client/src/error.rs index afcc3c678254e..0f47891138aba 100644 --- a/relays/ethereum-client/src/error.rs +++ b/relays/ethereum-client/src/error.rs @@ -57,8 +57,7 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::Request(RequestError::TransportError(_)) - | Error::ClientNotSynced(_), + Error::Request(RequestError::TransportError(_)) | Error::ClientNotSynced(_), ) } } diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 1dd5dd0442aa0..b75c0f44bb856 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -63,7 +63,6 @@ fn main() { .is_err() { log::error!(target: "bridge", "Unable to get Substrate genesis block for Ethereum sync."); - return; }; } ("sub-to-eth", Some(sub_to_eth_matches)) => { @@ -78,7 +77,6 @@ fn main() { .is_err() { log::error!(target: "bridge", "Unable to get Substrate genesis block for Substrate sync."); - return; }; } ("eth-deploy-contract", Some(eth_deploy_matches)) => { diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index f5bb250d9fb47..67aefe9885534 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -61,8 +61,7 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::Request(RequestError::TransportError(_)) - | Error::ClientNotSynced(_) + Error::Request(RequestError::TransportError(_)) | Error::ClientNotSynced(_) ) } } From 0bfad7f59650ad882e868aed703d584fda681f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 17 Feb 2021 18:39:04 +0100 Subject: [PATCH 0341/1210] Fix formatting. (#738) --- relays/utils/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 3ece57d0a3201..f787e8763a7a5 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -83,7 +83,7 @@ macro_rules! bail_on_error { match $result { (client, Ok(result)) => (client, result), (client, Err(error)) => return (client, Err(error)), - } + } }; } @@ -94,7 +94,7 @@ macro_rules! bail_on_arg_error { match $result { Ok(result) => result, Err(error) => return ($client, Err(error)), - } + } }; } From 33f523ed9cdb47fc25183005852ee5b165a4eb86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 18 Feb 2021 06:00:10 +0100 Subject: [PATCH 0342/1210] Change SS58Prefixes (#739) * Workaround for SS58Prefix issues in the UI. * Change prefixes. Co-authored-by: adoerr <0xad@gmx.net> --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8217967020768..7d493d849310d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -150,7 +150,7 @@ parameter_types! { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; - pub const SS58Prefix: u8 = 86; + pub const SS58Prefix: u8 = 60; } impl frame_system::Config for Runtime { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4881dea298298..52344cd27e505 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -158,7 +158,7 @@ parameter_types! { read: 60_000_000, // ~0.06 ms = ~60 µs write: 200_000_000, // ~0.2 ms = 200 µs }; - pub const SS58Prefix: u8 = 84; + pub const SS58Prefix: u8 = 48; } impl frame_system::Config for Runtime { From 286768154501a268ff9efdc9f91b8bd2a8a74645 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 18 Feb 2021 10:15:12 +0300 Subject: [PATCH 0343/1210] Message lane pallet parameters + updatable conversion rate (#728) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * message lane pallet parameters * updated comment * Update modules/message-lane/src/lib.rs Co-authored-by: Tomasz Drwięga * fmt Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 1 + bin/millau/runtime/src/rialto_messages.rs | 31 ++++- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/millau_messages.rs | 31 ++++- modules/message-lane/src/lib.rs | 135 ++++++++++++++++++++-- modules/message-lane/src/mock.rs | 20 +++- primitives/message-lane/src/lib.rs | 6 + 7 files changed, 211 insertions(+), 14 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7d493d849310d..2f0641907160e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -336,6 +336,7 @@ impl pallet_message_lane::Config for Runtime { type Event = Event; // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 type WeightInfo = pallet_message_lane::weights::RialtoWeight; + type Parameter = rialto_messages::MillauToRialtoMessageLaneParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 1ba7f8361f120..59f7542d90365 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -21,17 +21,25 @@ use crate::Runtime; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, + InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessageLaneParameter, }; use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; +use codec::{Decode, Encode}; use frame_support::{ + parameter_types, weights::{DispatchClass, Weight, WeightToFeePolynomial}, RuntimeDebug, }; use sp_core::storage::StorageKey; +use sp_runtime::{FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; +parameter_types! { + /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. + storage RialtoToMillauConversionRate: FixedU128 = 1.into(); +} + /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { pallet_message_lane::storage_keys::message_key::::MessageLaneInstance>( @@ -145,8 +153,8 @@ impl MessageBridge for WithRialtoMessageBridge { } fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { - // 1:1 conversion that will probably change in the future - bridged_balance as _ + bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) + .unwrap_or(bp_millau::Balance::MAX) } } @@ -227,3 +235,20 @@ impl SourceHeaderChain for Rialto { messages::target::verify_messages_proof::(proof, messages_count) } } + +/// Millau -> Rialto message lane pallet parameters. +#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] +pub enum MillauToRialtoMessageLaneParameter { + /// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`. + RialtoToMillauConversionRate(FixedU128), +} + +impl MessageLaneParameter for MillauToRialtoMessageLaneParameter { + fn save(&self) { + match *self { + MillauToRialtoMessageLaneParameter::RialtoToMillauConversionRate(ref conversion_rate) => { + RialtoToMillauConversionRate::set(conversion_rate) + } + } + } +} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 52344cd27e505..6e56676a531a4 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -443,6 +443,7 @@ pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInst impl pallet_message_lane::Config for Runtime { type Event = Event; type WeightInfo = pallet_message_lane::weights::RialtoWeight; + type Parameter = millau_messages::RialtoToMillauMessageLaneParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index b43226d60d58e..3fc11f59c75f7 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -21,17 +21,25 @@ use crate::Runtime; use bp_message_lane::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, + InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessageLaneParameter, }; use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; +use codec::{Decode, Encode}; use frame_support::{ + parameter_types, weights::{DispatchClass, Weight, WeightToFeePolynomial}, RuntimeDebug, }; use sp_core::storage::StorageKey; +use sp_runtime::{FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; +parameter_types! { + /// Millau to Rialto conversion rate. Initially we treat both tokens as equal. + storage MillauToRialtoConversionRate: FixedU128 = 1.into(); +} + /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { pallet_message_lane::storage_keys::message_key::::MessageLaneInstance>( @@ -145,8 +153,8 @@ impl MessageBridge for WithMillauMessageBridge { } fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { - // 1:1 conversion that will probably change in the future - bridged_balance as _ + bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) + .unwrap_or(bp_rialto::Balance::MAX) } } @@ -227,3 +235,20 @@ impl SourceHeaderChain for Millau { messages::target::verify_messages_proof::(proof, messages_count) } } + +/// Rialto -> Millau message lane pallet parameters. +#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] +pub enum RialtoToMillauMessageLaneParameter { + /// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`. + MillauToRialtoConversionRate(FixedU128), +} + +impl MessageLaneParameter for RialtoToMillauMessageLaneParameter { + fn save(&self) { + match *self { + RialtoToMillauMessageLaneParameter::MillauToRialtoConversionRate(ref conversion_rate) => { + MillauToRialtoConversionRate::set(conversion_rate) + } + } + } +} diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 117bd2b465b84..45da09eba0ff4 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -48,7 +48,7 @@ use bp_message_lane::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, - OutboundLaneData, UnrewardedRelayersState, + OutboundLaneData, Parameter as MessageLaneParameter, UnrewardedRelayersState, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -84,6 +84,12 @@ pub trait Config: frame_system::Config { type Event: From> + Into<::Event>; /// Benchmarks results from runtime we're plugged into. type WeightInfo: WeightInfoExt; + /// Pallet parameter that is opaque to the pallet itself, but may be used by the runtime + /// for integrating the pallet. + /// + /// All pallet parameters may only be updated either by the root, or by the pallet owner. + type Parameter: MessageLaneParameter; + /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever new message is sent. The reason is that if you want to use lane, you should /// be ready to pay for its maintenance. @@ -211,9 +217,13 @@ decl_storage! { } decl_event!( - pub enum Event where - ::AccountId, + pub enum Event + where + AccountId = ::AccountId, + Parameter = >::Parameter, { + /// Pallet parameter has been updated. + ParameterUpdated(Parameter), /// Message has been accepted and is waiting to be delivered. MessageAccepted(LaneId, MessageNonce), /// Messages in the inclusive range have been delivered and processed by the bridged chain. @@ -274,6 +284,18 @@ decl_module! { frame_support::debug::info!("Resuming pallet operations."); } + /// Update pallet parameter. + /// + /// May only be called either by root, or by `ModuleOwner`. + /// + /// The weight is: single read for permissions check + 2 writes for parameter value and event. + #[weight = (T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational)] + pub fn update_pallet_parameter(origin, parameter: T::Parameter) { + ensure_owner_or_root::(origin)?; + parameter.save(); + Self::deposit_event(RawEvent::ParameterUpdated(parameter)); + } + /// Send message over lane. #[weight = T::WeightInfo::send_message_weight(payload)] pub fn send_message( @@ -821,9 +843,9 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, - TestMessagesDeliveryProof, TestMessagesProof, TestPayload, TestRuntime, PAYLOAD_REJECTED_BY_TARGET_CHAIN, - REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, TestMessageLaneParameter, + TestMessagesDeliveryProof, TestMessagesProof, TestPayload, TestRuntime, TokenConversionRate, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_message_lane::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; @@ -831,9 +853,13 @@ mod tests { use hex_literal::hex; use sp_runtime::DispatchError; - fn send_regular_message() { + fn get_ready_for_events() { System::::set_block_number(1); System::::reset_events(); + } + + fn send_regular_message() { + get_ready_for_events(); assert_ok!(Module::::send_message( Origin::signed(1), @@ -940,6 +966,101 @@ mod tests { }); } + #[test] + fn pallet_parameter_may_be_updated_by_root() { + run_test(|| { + get_ready_for_events(); + + let parameter = TestMessageLaneParameter::TokenConversionRate(10.into()); + assert_ok!(Module::::update_pallet_parameter( + Origin::root(), + parameter.clone(), + )); + + assert_eq!(TokenConversionRate::get(), 10.into()); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::pallet_message_lane(RawEvent::ParameterUpdated(parameter)), + topics: vec![], + }], + ); + }); + } + + #[test] + fn pallet_parameter_may_be_updated_by_owner() { + run_test(|| { + ModuleOwner::::put(2); + get_ready_for_events(); + + let parameter = TestMessageLaneParameter::TokenConversionRate(10.into()); + assert_ok!(Module::::update_pallet_parameter( + Origin::signed(2), + parameter.clone(), + )); + + assert_eq!(TokenConversionRate::get(), 10.into()); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::pallet_message_lane(RawEvent::ParameterUpdated(parameter)), + topics: vec![], + }], + ); + }); + } + + #[test] + fn pallet_parameter_cant_be_updated_by_arbitrary_submitter() { + run_test(|| { + assert_noop!( + Module::::update_pallet_parameter( + Origin::signed(2), + TestMessageLaneParameter::TokenConversionRate(10.into()), + ), + DispatchError::BadOrigin, + ); + + ModuleOwner::::put(2); + + assert_noop!( + Module::::update_pallet_parameter( + Origin::signed(1), + TestMessageLaneParameter::TokenConversionRate(10.into()), + ), + DispatchError::BadOrigin, + ); + }); + } + + #[test] + fn fixed_u128_works_as_i_think() { + // this test is here just to be sure that conversion rate may be represented with FixedU128 + run_test(|| { + use sp_runtime::{FixedPointNumber, FixedU128}; + + // 1:1 conversion that we use by default for testnets + let rialto_token = 1u64; + let rialto_token_in_millau_tokens = TokenConversionRate::get().saturating_mul_int(rialto_token); + assert_eq!(rialto_token_in_millau_tokens, 1); + + // let's say conversion rate is 1:1.7 + let conversion_rate = FixedU128::saturating_from_rational(170, 100); + let rialto_tokens = 100u64; + let rialto_tokens_in_millau_tokens = conversion_rate.saturating_mul_int(rialto_tokens); + assert_eq!(rialto_tokens_in_millau_tokens, 170); + + // let's say conversion rate is 1:0.25 + let conversion_rate = FixedU128::saturating_from_rational(25, 100); + let rialto_tokens = 100u64; + let rialto_tokens_in_millau_tokens = conversion_rate.saturating_mul_int(rialto_tokens); + assert_eq!(rialto_tokens_in_millau_tokens, 25); + }); + } + #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { diff --git a/modules/message-lane/src/mock.rs b/modules/message-lane/src/mock.rs index 948c107d0518b..cf14ca105c22f 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/message-lane/src/mock.rs @@ -25,6 +25,7 @@ use bp_message_lane::{ }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, + Parameter as MessageLaneParameter, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -33,7 +34,7 @@ use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, traits::{BlakeTwo256, IdentityLookup}, - Perbill, + FixedU128, Perbill, }; use std::collections::BTreeMap; @@ -119,11 +120,28 @@ parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; + pub storage TokenConversionRate: FixedU128 = 1.into(); +} + +#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)] +pub enum TestMessageLaneParameter { + TokenConversionRate(FixedU128), +} + +impl MessageLaneParameter for TestMessageLaneParameter { + fn save(&self) { + match *self { + TestMessageLaneParameter::TokenConversionRate(conversion_rate) => { + TokenConversionRate::set(&conversion_rate) + } + } + } } impl Config for TestRuntime { type Event = Event; type WeightInfo = (); + type Parameter = TestMessageLaneParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/primitives/message-lane/src/lib.rs b/primitives/message-lane/src/lib.rs index 0c1dee7f2a010..de2dbd9ae63da 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/message-lane/src/lib.rs @@ -32,6 +32,12 @@ pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in message-lane related crates. pub use frame_support::weights::Weight; +/// Message lane pallet parameter. +pub trait Parameter: frame_support::Parameter { + /// Save parameter value in the runtime storage. + fn save(&self); +} + /// Lane identifier. pub type LaneId = [u8; 4]; From 764119bd2d2f65498f3773a283a12829041a5eda Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Fri, 19 Feb 2021 14:19:53 +0100 Subject: [PATCH 0344/1210] Send message doc (#746) * add document * Send message documentation * Apply review Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Svyatoslav Nikolsky --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 915fa46dd5368..eaa63ad14c77b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Substrate chains or Ethereum Proof-of-Authority chains. - [High-Level Architecture](#high-level-architecture) - [Project Layout](#project-layout) - [Running the Bridge](#running-the-bridge) +- [How to send a message](#how-to-send-a-message) - [Community](#community) ## Installation @@ -191,6 +192,10 @@ Once you have the images built you can use them in the previous commands by repl For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). +### How to send a message + +A straightforward way to interact with and test the bridge is sending messages. This is explained +in the [send message](./docs/send-message.md) document. ## Community Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat From dd933ee72d806e1f380d5e73a7482d53a75e4d58 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 22 Feb 2021 18:55:40 +0300 Subject: [PATCH 0345/1210] Generate large messages (#700) * generate large messages * consider headers sync lag when computing number of rewards in confirmation * more fixes * fix logs * fix warnings * do not wait until tx that has delivered nonces will be finalized before submitting other tx * tests for maximal weight/size * cleanup * cleanup * clippy * compilation * args for dispatch weight and remark size * ExplicitOrMaximal * clippy --- relays/substrate/src/cli.rs | 45 +++++- relays/substrate/src/main.rs | 222 ++++++++++++++++++++++---- relays/substrate/src/messages_lane.rs | 4 +- 3 files changed, 238 insertions(+), 33 deletions(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 96f13d33841ab..8dc241f069e1c 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -17,6 +17,7 @@ //! Deal with CLI args of substrate-to-substrate relay. use bp_message_lane::LaneId; +use frame_support::weights::Weight; use sp_core::Bytes; use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId; use structopt::{clap::arg_enum, StructOpt}; @@ -153,6 +154,9 @@ pub enum SendMessage { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, + /// Dispatch weight of the message. If not passed, determined automatically. + #[structopt(long)] + dispatch_weight: Option>, /// Delivery and dispatch fee. If not passed, determined automatically. #[structopt(long)] fee: Option, @@ -174,6 +178,9 @@ pub enum SendMessage { /// Hex-encoded lane id. #[structopt(long)] lane: HexLaneId, + /// Dispatch weight of the message. If not passed, determined automatically. + #[structopt(long)] + dispatch_weight: Option>, /// Delivery and dispatch fee. If not passed, determined automatically. #[structopt(long)] fee: Option, @@ -190,7 +197,11 @@ pub enum SendMessage { #[derive(StructOpt, Debug)] pub enum ToRialtoMessage { /// Make an on-chain remark (comment). - Remark, + Remark { + /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. + #[structopt(long)] + remark_size: Option>, + }, /// Transfer the specified `amount` of native tokens to a particular `recipient`. Transfer { #[structopt(long)] @@ -204,7 +215,11 @@ pub enum ToRialtoMessage { #[derive(StructOpt, Debug)] pub enum ToMillauMessage { /// Make an on-chain remark (comment). - Remark, + Remark { + /// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark. + #[structopt(long)] + remark_size: Option>, + }, /// Transfer the specified `amount` of native tokens to a particular `recipient`. Transfer { #[structopt(long)] @@ -273,6 +288,32 @@ impl From for Option { } } +/// Either explicit or maximal allowed value. +#[derive(Debug)] +pub enum ExplicitOrMaximal { + /// User has explicitly specified argument value. + Explicit(V), + /// Maximal allowed value for this argument. + Maximal, +} + +impl std::str::FromStr for ExplicitOrMaximal +where + V::Err: std::fmt::Debug, +{ + type Err = String; + + fn from_str(s: &str) -> Result { + if s.to_lowercase() == "max" { + return Ok(ExplicitOrMaximal::Maximal); + } + + V::from_str(s) + .map(ExplicitOrMaximal::Explicit) + .map_err(|e| format!("Failed to parse '{:?}'. Expected 'max' or explicit value", e)) + } +} + macro_rules! declare_chain_options { ($chain:ident, $chain_prefix:ident) => { paste::item! { diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index c700022a0f1b9..c73533cdfca8a 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -19,7 +19,7 @@ #![warn(missing_docs)] use codec::{Decode, Encode}; -use frame_support::weights::GetDispatchInfo; +use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; use relay_kusama_client::Kusama; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; @@ -232,6 +232,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { rialto_sign, lane, message, + dispatch_weight, fee, origin, .. @@ -241,7 +242,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { let rialto_sign = rialto_sign.parse()?; let rialto_call = message.into_call(); - let payload = millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin); + let payload = + millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin, dispatch_weight); + let dispatch_weight = payload.weight; let lane = lane.into(); let fee = get_fee(fee, || { @@ -254,8 +257,6 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { }) .await?; - log::info!(target: "bridge", "Sending message to Rialto. Fee: {}", fee); - let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( millau_runtime::MessageLaneCall::send_message(lane, payload, fee), ); @@ -267,11 +268,18 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { .next_account_index(millau_sign.signer.public().clone().into()) .await?, millau_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}", + signed_millau_call.len(), + dispatch_weight, + fee, ); - millau_client - .submit_extrinsic(Bytes(signed_millau_call.encode())) - .await?; + millau_client.submit_extrinsic(Bytes(signed_millau_call)).await?; } cli::SendMessage::RialtoToMillau { rialto, @@ -279,6 +287,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { millau_sign, lane, message, + dispatch_weight, fee, origin, .. @@ -288,7 +297,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { let millau_sign = millau_sign.parse()?; let millau_call = message.into_call(); - let payload = rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin); + let payload = + rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin, dispatch_weight); + let dispatch_weight = payload.weight; let lane = lane.into(); let fee = get_fee(fee, || { @@ -301,8 +312,6 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { }) .await?; - log::info!(target: "bridge", "Sending message to Millau. Fee: {}", fee); - let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( rialto_runtime::MessageLaneCall::send_message(lane, payload, fee), ); @@ -314,11 +323,18 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { .next_account_index(rialto_sign.signer.public().clone().into()) .await?, rialto_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}", + signed_rialto_call.len(), + dispatch_weight, + fee, ); - rialto_client - .submit_extrinsic(Bytes(signed_rialto_call.encode())) - .await?; + rialto_client.submit_extrinsic(Bytes(signed_rialto_call)).await?; } } Ok(()) @@ -338,16 +354,20 @@ async fn estimate_message_delivery_and_dispatch_fee Vec { - format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec() +fn remark_payload(remark_size: Option>, maximal_allowed_size: u32) -> Vec { + match remark_size { + Some(cli::ExplicitOrMaximal::Explicit(remark_size)) => vec![0; remark_size], + Some(cli::ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], + None => format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec(), + } } fn rialto_to_millau_message_payload( @@ -355,8 +375,13 @@ fn rialto_to_millau_message_payload( millau_sign: &MillauSigningParams, millau_call: &millau_runtime::Call, origin: cli::Origins, + user_specified_dispatch_weight: Option>, ) -> rialto_runtime::millau_messages::ToMillauMessagePayload { - let millau_call_weight = millau_call.get_dispatch_info().weight; + let millau_call_weight = prepare_call_dispatch_weight( + user_specified_dispatch_weight, + cli::ExplicitOrMaximal::Explicit(millau_call.get_dispatch_info().weight), + compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()), + ); let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); let millau_origin_public = millau_sign.signer.public(); @@ -387,8 +412,13 @@ fn millau_to_rialto_message_payload( rialto_sign: &RialtoSigningParams, rialto_call: &rialto_runtime::Call, origin: cli::Origins, + user_specified_dispatch_weight: Option>, ) -> millau_runtime::rialto_messages::ToRialtoMessagePayload { - let rialto_call_weight = rialto_call.get_dispatch_info().weight; + let rialto_call_weight = prepare_call_dispatch_weight( + user_specified_dispatch_weight, + cli::ExplicitOrMaximal::Explicit(rialto_call.get_dispatch_info().weight), + compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), + ); let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); let rialto_origin_public = rialto_sign.signer.public(); @@ -414,6 +444,17 @@ fn millau_to_rialto_message_payload( } } +fn prepare_call_dispatch_weight( + user_specified_dispatch_weight: Option>, + weight_from_pre_dispatch_call: cli::ExplicitOrMaximal, + maximal_allowed_weight: Weight, +) -> Weight { + match user_specified_dispatch_weight.unwrap_or(weight_from_pre_dispatch_call) { + cli::ExplicitOrMaximal::Explicit(weight) => weight, + cli::ExplicitOrMaximal::Maximal => maximal_allowed_weight, + } +} + async fn get_fee(fee: Option, f: F) -> Result where Fee: Decode, @@ -431,6 +472,30 @@ where } } +fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { + bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) +} + +fn compute_maximal_message_arguments_size( + maximal_source_extrinsic_size: u32, + maximal_target_extrinsic_size: u32, +) -> u32 { + // assume that both signed extensions and other arguments fit 1KB + let service_tx_bytes_on_source_chain = 1024; + let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; + let maximal_call_size = + bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size); + let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { + maximal_source_extrinsic_size + } else { + maximal_call_size + }; + + // bytes in Call encoding that are used to encode everything except arguments + let service_bytes = 1 + 1 + 4; + maximal_call_size - service_bytes +} + impl crate::cli::RialtoSigningParams { /// Parse CLI parameters into typed signing params. pub fn parse(self) -> Result { @@ -472,8 +537,14 @@ impl crate::cli::ToRialtoMessage { /// Convert CLI call request into runtime `Call` instance. pub fn into_call(self) -> rialto_runtime::Call { match self { - cli::ToRialtoMessage::Remark => { - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload())) + cli::ToRialtoMessage::Remark { remark_size } => { + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload( + remark_size, + compute_maximal_message_arguments_size( + bp_millau::max_extrinsic_size(), + bp_rialto::max_extrinsic_size(), + ), + ))) } cli::ToRialtoMessage::Transfer { recipient, amount } => { rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) @@ -486,8 +557,14 @@ impl crate::cli::ToMillauMessage { /// Convert CLI call request into runtime `Call` instance. pub fn into_call(self) -> millau_runtime::Call { match self { - cli::ToMillauMessage::Remark => { - millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload())) + cli::ToMillauMessage::Remark { remark_size } => { + millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( + remark_size, + compute_maximal_message_arguments_size( + bp_rialto::max_extrinsic_size(), + bp_millau::max_extrinsic_size(), + ), + ))) } cli::ToMillauMessage::Transfer { recipient, amount } => { millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) @@ -498,6 +575,8 @@ impl crate::cli::ToMillauMessage { #[cfg(test)] mod tests { + use super::*; + use bp_message_lane::source_chain::TargetHeaderChain; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -542,4 +621,89 @@ mod tests { assert!(signature.verify(&digest[..], &millau_signer.signer.public())); } + + #[test] + fn maximal_rialto_to_millau_message_arguments_size_is_computed_correctly() { + use rialto_runtime::millau_messages::Millau; + + let maximal_remark_size = + compute_maximal_message_arguments_size(bp_rialto::max_extrinsic_size(), bp_millau::max_extrinsic_size()); + + let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); + let payload = pallet_bridge_call_dispatch::MessagePayload { + spec_version: Default::default(), + weight: call.get_dispatch_info().weight, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: call.encode(), + }; + assert_eq!(Millau::verify_message(&payload), Ok(())); + + let call: millau_runtime::Call = + millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into(); + let payload = pallet_bridge_call_dispatch::MessagePayload { + spec_version: Default::default(), + weight: call.get_dispatch_info().weight, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: call.encode(), + }; + assert!(Millau::verify_message(&payload).is_err()); + } + + #[test] + fn maximal_size_remark_to_rialto_is_generated_correctly() { + assert!( + bridge_runtime_common::messages::target::maximal_incoming_message_size( + bp_rialto::max_extrinsic_size() + ) > bp_millau::max_extrinsic_size(), + "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", + ) + } + + #[test] + fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() { + use rialto_runtime::millau_messages::Millau; + + let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); + let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); + + let payload = pallet_bridge_call_dispatch::MessagePayload { + spec_version: Default::default(), + weight: maximal_dispatch_weight, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: call.encode(), + }; + assert_eq!(Millau::verify_message(&payload), Ok(())); + + let payload = pallet_bridge_call_dispatch::MessagePayload { + spec_version: Default::default(), + weight: maximal_dispatch_weight + 1, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: call.encode(), + }; + assert!(Millau::verify_message(&payload).is_err()); + } + + #[test] + fn maximal_weight_fill_block_to_rialto_is_generated_correctly() { + use millau_runtime::rialto_messages::Rialto; + + let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); + let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); + + let payload = pallet_bridge_call_dispatch::MessagePayload { + spec_version: Default::default(), + weight: maximal_dispatch_weight, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: call.encode(), + }; + assert_eq!(Rialto::verify_message(&payload), Ok(())); + + let payload = pallet_bridge_call_dispatch::MessagePayload { + spec_version: Default::default(), + weight: maximal_dispatch_weight + 1, + origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + call: call.encode(), + }; + assert!(Rialto::verify_message(&payload).is_err()); + } } diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs index 96efaa6a43606..78b5f5c024880 100644 --- a/relays/substrate/src/messages_lane.rs +++ b/relays/substrate/src/messages_lane.rs @@ -166,7 +166,7 @@ mod tests { #[test] fn select_delivery_transaction_limits_works() { let (max_count, max_weight) = select_delivery_transaction_limits::( - bp_rialto::max_extrinsic_weight(), + bp_millau::max_extrinsic_weight(), bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); assert_eq!( @@ -176,7 +176,7 @@ mod tests { // reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (1024, 866_583_333_334), + (955, 216_583_333_334), ); } } From ae07704fefc2f542a781e61467eb46840ad925f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 22 Feb 2021 17:15:04 +0100 Subject: [PATCH 0346/1210] Set weird substrate global state for custom SS58 prefixes (#754) * Issue with SS58 decoding. * Switch to test branch. * Fix set. * Revert "Switch to test branch." This reverts commit d79e42ea9bc780edb20296dae546d534f1916fc7. * cargo fmt --all Co-authored-by: adoerr <0xad@gmx.net> --- bin/millau/node/src/command.rs | 4 ++++ bin/rialto/node/src/command.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index ef506e5cdc725..8751a4516d1de 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -69,6 +69,10 @@ impl SubstrateCli for Cli { /// Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); + // make sure to set correct crypto version. + sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom( + millau_runtime::SS58Prefix::get() as u16, + )); match &cli.subcommand { Some(Subcommand::Benchmark(cmd)) => { diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 72404d64226e2..8242c9eaaba03 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -69,6 +69,9 @@ impl SubstrateCli for Cli { /// Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); + sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom( + rialto_runtime::SS58Prefix::get() as u16, + )); match &cli.subcommand { Some(Subcommand::Benchmark(cmd)) => { From 5942ddf189b55fc2ae2b63c07de5e905b8978730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 24 Feb 2021 01:16:35 +0100 Subject: [PATCH 0347/1210] Bump substrate in subtree import preparation. (#759) --- bin/millau/node/src/service.rs | 8 +++++--- bin/rialto/node/src/service.rs | 8 +++++--- modules/ethereum-contract/builtin/Cargo.toml | 2 +- modules/finality-verifier/Cargo.toml | 2 +- modules/substrate/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/header-chain/src/justification.rs | 4 ---- primitives/test-utils/Cargo.toml | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 6727ee682d8d6..2f72e5717faee 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -105,7 +105,7 @@ pub fn new_partial( Some(Box::new(grandpa_block_import)), client.clone(), inherent_data_providers.clone(), - &task_manager.spawn_handle(), + &task_manager.spawn_essential_handle(), config.prometheus_registry(), sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), )?; @@ -275,6 +275,7 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, + telemetry_span: None, })?; if role.is_authority() { @@ -321,7 +322,7 @@ pub fn new_full(mut config: Configuration) -> Result name: Some(name), observer_enabled: false, keystore, - is_authority: role.is_network_authority(), + is_authority: role.is_authority(), }; if enable_grandpa { @@ -384,7 +385,7 @@ pub fn new_light(mut config: Configuration) -> Result Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), - &task_manager.spawn_handle(), + &task_manager.spawn_essential_handle(), config.prometheus_registry(), sp_consensus::NeverCanAuthor, )?; @@ -423,6 +424,7 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, + telemetry_span: None, })?; network_starter.start_network(); diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index fdac6d2327913..67ca185137c0a 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -105,7 +105,7 @@ pub fn new_partial( Some(Box::new(grandpa_block_import)), client.clone(), inherent_data_providers.clone(), - &task_manager.spawn_handle(), + &task_manager.spawn_essential_handle(), config.prometheus_registry(), sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), )?; @@ -275,6 +275,7 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, + telemetry_span: None, })?; if role.is_authority() { @@ -321,7 +322,7 @@ pub fn new_full(mut config: Configuration) -> Result name: Some(name), observer_enabled: false, keystore, - is_authority: role.is_network_authority(), + is_authority: role.is_authority(), }; if enable_grandpa { @@ -384,7 +385,7 @@ pub fn new_light(mut config: Configuration) -> Result Some(Box::new(grandpa_block_import)), client.clone(), InherentDataProviders::new(), - &task_manager.spawn_handle(), + &task_manager.spawn_essential_handle(), config.prometheus_registry(), sp_consensus::NeverCanAuthor, )?; @@ -423,6 +424,7 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, + telemetry_span: None, })?; network_starter.start_network(); diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract/builtin/Cargo.toml index c65a490516f2b..0d34cf56444e2 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract/builtin/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } ethereum-types = "0.11.0" -finality-grandpa = "0.13.0" +finality-grandpa = "0.14.0" hex = "0.4" log = "0.4.14" diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index 060c6c3be67b6..8afc30cd30ed0 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -finality-grandpa = { version = "0.13.0", default-features = false } +finality-grandpa = { version = "0.14.0", default-features = false } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index dd047d6b89907..6f6e9cafddabe 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -finality-grandpa = { version = "0.13.0", default-features = false } +finality-grandpa = { version = "0.14.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } serde = { version = "1.0", optional = true } diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 0dc169303929c..8a017610a3e86 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -finality-grandpa = { version = "0.13.0", default-features = false } +finality-grandpa = { version = "0.14.0", default-features = false } serde = { version = "1.0", optional = true } # Substrate Dependencies diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 929ef17bdca2e..fef9aedac90c8 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -180,8 +180,4 @@ where Ok(route) } - - fn best_chain_containing(&self, _block: Header::Hash) -> Option<(Header::Hash, Header::Number)> { - unreachable!("is only used during voting; qed") - } } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 944700e9d3c3e..2b9bb5cd191c2 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -finality-grandpa = { version = "0.13.0" } +finality-grandpa = { version = "0.14.0" } bp-header-chain = { path = "../header-chain" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } From 7980aa2cf7a73e9ba0cc9afce72d26857fd554d6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 24 Feb 2021 03:19:18 +0300 Subject: [PATCH 0348/1210] verify ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT constant value (#731) --- bin/millau/runtime/src/lib.rs | 3 ++- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/runtime/src/lib.rs | 3 ++- bin/rialto/runtime/src/millau_messages.rs | 2 +- modules/message-lane/src/weights_ext.rs | 18 ++++++++++++++---- primitives/millau/src/lib.rs | 16 ++++++++++------ primitives/rialto/src/lib.rs | 16 ++++++++++------ 7 files changed, 40 insertions(+), 20 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2f0641907160e..bee7881f26d84 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -643,7 +643,8 @@ mod tests { type Weights = pallet_message_lane::weights::RialtoWeight; pallet_message_lane::ensure_weights_are_correct::( - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, ); diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 59f7542d90365..9775c93d2d0c6 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -126,7 +126,7 @@ impl MessageBridge for WithRialtoMessageBridge { message_payload_len.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), extra_bytes_in_payload .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) - .saturating_add(bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT), + .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT), ) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6e56676a531a4..af1d7c6c9faf3 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1072,7 +1072,8 @@ mod tests { type Weights = pallet_message_lane::weights::RialtoWeight; pallet_message_lane::ensure_weights_are_correct::( - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, ); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 3fc11f59c75f7..9fb57ee861b64 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -126,7 +126,7 @@ impl MessageBridge for WithMillauMessageBridge { message_payload_len.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), extra_bytes_in_payload .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) - .saturating_add(bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT), + .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT), ) } diff --git a/modules/message-lane/src/weights_ext.rs b/modules/message-lane/src/weights_ext.rs index 18d80159a1b80..d99a20007dac1 100644 --- a/modules/message-lane/src/weights_ext.rs +++ b/modules/message-lane/src/weights_ext.rs @@ -31,7 +31,8 @@ const SIGNED_EXTENSIONS_SIZE: u32 = 1024; /// Ensure that weights from `WeightInfoExt` implementation are looking correct. pub fn ensure_weights_are_correct( - expected_single_regular_message_delivery_tx_weight: Weight, + expected_default_message_delivery_tx_weight: Weight, + expected_additional_byte_delivery_weight: Weight, expected_messages_delivery_confirmation_tx_weight: Weight, ) { // verify `send_message` weight components @@ -51,10 +52,19 @@ pub fn ensure_weights_are_correct( 0, ); assert!( - actual_single_regular_message_delivery_tx_weight <= expected_single_regular_message_delivery_tx_weight, - "Single message delivery transaction weight {} is larger than expected weight {}", + actual_single_regular_message_delivery_tx_weight <= expected_default_message_delivery_tx_weight, + "Default message delivery transaction weight {} is larger than expected weight {}", actual_single_regular_message_delivery_tx_weight, - expected_single_regular_message_delivery_tx_weight, + expected_default_message_delivery_tx_weight, + ); + + // verify that hardcoded value covers additional byte length of `receive_messages_proof` weight + let actual_additional_byte_delivery_weight = W::storage_proof_size_overhead(1); + assert!( + actual_additional_byte_delivery_weight <= expected_additional_byte_delivery_weight, + "Single additional byte delivery weight {} is larger than expected weight {}", + actual_additional_byte_delivery_weight, + expected_additional_byte_delivery_weight, ); // verify `receive_messages_delivery_proof` weight components diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 017aef6da72f1..84096d116ef53 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -69,15 +69,19 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; -/// Maximal weight of single regular message delivery transaction on Millau chain. +/// Weight of single regular message delivery transaction on Millau chain. /// -/// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation -/// for the case when single message is delivered. The result then must be rounded up to account possible future -/// runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; +/// This value is a result of `pallet_message_lane::Module::receive_messages_proof_weight()` call +/// for the case when single message of `pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. +/// The message must have dispatch weight set to zero. The result then must be rounded up to account +/// possible future runtime upgrades. +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; /// Increase of delivery transaction weight on Millau chain with every additional message byte. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 3_000; +/// +/// This value is a result of `pallet_message_lane::WeightInfoExt::storage_proof_size_overhead(1)` call. The +/// result then must be rounded up to account possible future runtime upgrades. +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Millau chain. /// diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 9bec3b1862ba0..706e2f27854d2 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -60,15 +60,19 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; -/// Maximal weight of single regular message delivery transaction on Rialto chain. +/// Weight of single regular message delivery transaction on Rialto chain. /// -/// This value is a result of `pallet_message_lane::Module::receive_messages_proof` weight formula computation -/// for the case when single message is delivered. The result then must be rounded up to account possible future -/// runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; +/// This value is a result of `pallet_message_lane::Module::receive_messages_proof_weight()` call +/// for the case when single message of `pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. +/// The message must have dispatch weight set to zero. The result then must be rounded up to account +/// possible future runtime upgrades. +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; /// Increase of delivery transaction weight on Rialto chain with every additional message byte. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 3_000; +/// +/// This value is a result of `pallet_message_lane::WeightInfoExt::storage_proof_size_overhead(1)` call. The +/// result then must be rounded up to account possible future runtime upgrades. +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Rialto chain. /// From 05a053f1eb3fd3aa646c44ce6a4d09c310c67cee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 24 Feb 2021 09:31:28 +0300 Subject: [PATCH 0349/1210] Message lane integration documentation (#736) * how-to-integrate-message-lane-module * added README stub for bridge-runtime-common * added README stub for pallet-bridge-call-dispatch * bridge-runtime-common documentation * call dispatch module documentation * some fixes * more fixes * more fixes * more fixes * more fixes for runtime-common/README.md * more fixes in call-dispatch/README.md * more fixes in call-dispatch/README.md * more fixes in call-dispatch/README.md * more fixes in message-lane/README.md * more fixes in message-lane/README.md * Wrap most text at 100 characters * Clean up some of the formatting * Fix broken link * Stop running CI for README changes * Don't run any CI steps on documentation changes Co-authored-by: Hernando Castano --- bin/runtime-common/README.md | 183 +++++++++++++++++++ modules/call-dispatch/README.md | 61 +++++++ modules/message-lane/README.md | 309 +++++++++++++++++++++++++++++--- 3 files changed, 528 insertions(+), 25 deletions(-) create mode 100644 bin/runtime-common/README.md create mode 100644 modules/call-dispatch/README.md diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md new file mode 100644 index 0000000000000..58fe92c9ca0dd --- /dev/null +++ b/bin/runtime-common/README.md @@ -0,0 +1,183 @@ +# Helpers for Message Lane Module Integration + +The [`messages`](./src/messages.rs) module of this crate contains a bunch of helpers for integrating +message lane module into your runtime. Basic prerequisites of these helpers are: +- we're going to bridge Substrate-based chain with another Substrate-based chain; +- both chains have [message lane module](../../modules/message-lane/README.md), Substrate bridge + module and the [call dispatch module](../../modules/call-dispatch/README.md); +- all message lanes are identical and may be used to transfer the same messages; +- the messages sent over the bridge are dispatched using + [call dispatch module](../../modules/call-dispatch/README.md); +- the messages are `pallet_bridge_call_dispatch::MessagePayload` structures, where `call` field is + encoded `Call` of the target chain. This means that the `Call` is opaque to the + [message lane module](../../modules/message-lane/README.md) instance at the source chain. + It is pre-encoded by the message submitter; +- all proofs in the [message lane module](../../modules/message-lane/README.md) transactions are + based on the storage proofs from the bridged chain: storage proof of the outbound message (value + from the `pallet_message_lane::Store::MessagePayload` map), storage proof of the outbound lane + state (value from the `pallet_message_lane::Store::OutboundLanes` map) and storage proof of the + inbound lane state (value from the `pallet_message_lane::Store::InboundLanes` map); +- storage proofs are built at the finalized headers of the corresponding chain. So all message lane + transactions with proofs are verifying storage proofs against finalized chain headers from + Substrate bridge module. + +**IMPORTANT NOTE**: after reading this document, you may refer to our test runtimes +([rialto_messages.rs](../millau/runtime/src/rialto_messages.rs) and/or +[millau_messages.rs](../rialto/runtime/src/millau_messages.rs)) to see how to use these helpers. + +## Contents +- [`MessageBridge` Trait](#messagebridge-trait) +- [`ChainWithMessageLanes` Trait ](#chainwithmessagelanes-trait) +- [Helpers for the Source Chain](#helpers-for-the-source-chain) +- [Helpers for the Target Chain](#helpers-for-the-target-chain) + +## `MessageBridge` Trait + +The essence of your integration will be a struct that implements a `MessageBridge` trait. Let's +review every method and give some implementation hints here: + +- `MessageBridge::maximal_extrinsic_size_on_target_chain`: you will need to return the maximal + extrinsic size of the target chain from this function. This may be the constant that is updated + when your runtime is upgraded, or you may use the + [message lane parameters functionality](../../modules/message-lane/README.md#Non-Essential-Functionality) + to allow the pallet owner to update this value more frequently (you may also want to use this + functionality for all constants that are used in other methods described below). + +- `MessageBridge::weight_limits_of_message_on_bridged_chain`: you'll need to return a range of + dispatch weights that the outbound message may take at the target chain. Please keep in mind that + our helpers assume that the message is an encoded call of the target chain. But we never decode + this call at the source chain. So you can't simply get dispatch weight from pre-dispatch + information. Instead there are two options to prepare this range: if you know which calls are to + be sent over your bridge, then you may just return weight ranges for these particular calls. + Otherwise, if you're going to accept all kinds of calls, you may just return range `[0; maximal + incoming message dispatch weight]`. If you choose the latter, then you shall remember that the + delivery transaction itself has some weight, so you can't accept messages with weight equal to + maximal weight of extrinsic at the target chain. In our test chains, we reject all messages that + have declared dispatch weight larger than 50% of the maximal bridged extrinsic weight. + +- `MessageBridge::weight_of_delivery_transaction`: you will need to return the maximal weight of the + delivery transaction that delivers a given message to the target chain. There are three main + things to notice: + + 1. weight, returned from this function is then used to compute the fee that the + message sender needs to pay for the delivery transaction. So it shall not be a simple dispatch + weight of delivery call - it should be the "weight" of the transaction itself, including per-byte + "weight", "weight" of signed extras and etc. + 1. the delivery transaction brings storage proof of + the message, not the message itself. So your transaction will include extra bytes. We suggest + computing the size of single empty value storage proof at the source chain, increase this value a + bit and hardcode it in the source chain runtime code. This size then must be added to the size of + payload and included in the weight computation; + 1. before implementing this function, please take + a look at the + [weight formula of delivery transaction](../../modules/message-lane/README.md#Weight-of-receive_messages_proof-call). + It adds some extra weight for every additional byte of the proof (everything above + `pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH`), so it's not trivial. Even better, please + refer to [our implementation](../millau/runtime/src/rialto_messages.rs) for test chains for + details. + +- `MessageBridge::weight_of_delivery_confirmation_transaction_on_this_chain`: you'll need to return + the maximal weight of a single message delivery confirmation transaction on this chain. All points + from the previous paragraph are also relevant here. + +- `MessageBridge::this_weight_to_this_balance`: this function needs to convert weight units into fee + units on this chain. Most probably this can be done by calling + `pallet_transaction_payment::Config::WeightToFee::calc()` for passed weight. + +- `MessageBridge::bridged_weight_to_bridged_balance`: this function needs to convert weight units + into fee units on the target chain. The best case is when you have the same conversion formula on + both chains - then you may just call the same formula from the previous paragraph. Otherwise, + you'll need to hardcode this formula into your runtime. + +- `MessageBridge::bridged_balance_to_this_balance`: this may be the easiest method to implement and + the hardest to maintain at the same time. If you don't have any automatic methods to determine + conversion rate, then you'll probably need to maintain it by yourself (by updating conversion + rate, stored in runtime storage). This means that if you're too late with an update, then you risk + to accept messages with lower-than-expected fee. So it may be wise to have some reserve in this + conversion rate, even if that means larger delivery and dispatch fees. + +## `ChainWithMessageLanes` Trait + +Apart from its methods, `MessageBridge` also has two associated types that are implementing the +`ChainWithMessageLanes` trait. One is for this chain and the other is for the bridged chain. The +trait is quite simple and can easily be implemented - you just need to specify types used at the +corresponding chain. There are two exceptions, though. Both may be changed in the future. Here they +are: + +- `ChainWithMessageLanes::Call`: it isn't a good idea to reference bridged chain runtime from your + runtime (cyclic references + maintaining on upgrades). So you can't know the type of bridged chain + call in your runtime. This type isn't actually used at this chain, so you may use `()` instead. + +- `ChainWithMessageLanes::MessageLaneInstance`: this is used to compute runtime storage keys. There + may be several instances of message lane pallet, included in the Runtime. Every instance stores + messages and these messages stored under different keys. When we are verifying storage proofs from + the bridged chain, we should know which instance we're talking to. This is fine, but there's + significant inconvenience with that - this chain runtime must have the same message lane pallet + instance. This does not necessarily mean that we should use the same instance on both chains - + this instance may be used to bridge with another chain/instance, or may not be used at all. + +## Helpers for the Source Chain + +The helpers for the Source Chain reside in the `source` submodule of the +[`messages`](./src/messages.rs) module. The structs are: `FromThisChainMessagePayload`, +`FromBridgedChainMessagesDeliveryProof`, `FromThisChainMessageVerifier`. And the helper functions +are: `maximal_message_size`, `verify_chain_message`, `verify_messages_delivery_proof` and +`estimate_message_dispatch_and_delivery_fee`. + +`FromThisChainMessagePayload` is a message that the sender sends through our bridge. It is the +`pallet_bridge_call_dispatch::MessagePayload`, where `call` field is encoded target chain call. So +at this chain we don't see internals of this call - we just know its size. + +`FromThisChainMessageVerifier` is an implementation of `bp_message_lane::LaneMessageVerifier`. It +has following checks in its `verify_message` method: + +1. it'll verify that the used outbound lane is enabled in our runtime; + +1. it'll reject messages if there are too many undelivered outbound messages at this lane. The + sender need to wait while relayers will do their work before sending the message again; + +1. it'll reject a message if it has the wrong dispatch origin declared. Like if the submitter is not + the root of this chain, but it tries to dispatch the message at the target chain using + `pallet_bridge_call_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature + in the `pallet_bridge_call_dispatch::CallOrigin::TargetAccount` origin; + +1. it'll reject a message if the delivery and dispatch fee that the submitter wants to pay is lesser + than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function. + +`estimate_message_dispatch_and_delivery_fee` returns a minimal fee that the submitter needs to pay +for sending a given message. The fee includes: payment for the delivery transaction at the target +chain, payment for delivery confirmation transaction on this chain, payment for `Call` dispatch at +the target chain and relayer interest. + +`FromBridgedChainMessagesDeliveryProof` holds the lane identifier and the storage proof of this +inbound lane state at the bridged chain. This also holds the hash of the target chain header, that +was used to generate this storage proof. The proof is verified by the +`verify_messages_delivery_proof`, which simply checks that the target chain header is finalized +(using Substrate bridge module) and then reads the inbound lane state from the proof. + +`verify_chain_message` function checks that the message may be delivered to the bridged chain. There +are two main checks: + +1. that the message size is less than or equal to the `2/3` of maximal extrinsic size at the target + chain. We leave `1/3` for signed extras and for the storage proof overhead; + +1. that the message dispatch weight is less than or equal to the `1/2` of maximal normal extrinsic + weight at the target chain. We leave `1/2` for the delivery transaction overhead. + +## Helpers for the Target Chain + +The helpers for the target chain reside in the `target` submodule of the +[`messages`](./src/messages.rs) module. The structs are: `FromBridgedChainMessagePayload`, +`FromBridgedChainMessagesProof`, `FromBridgedChainMessagesProof`. And the helper functions are: +`maximal_incoming_message_dispatch_weight`, `maximal_incoming_message_size` and +`verify_messages_proof`. + +`FromBridgedChainMessagePayload` corresponds to the `FromThisChainMessagePayload` at the bridged +chain. We expect that messages with this payload are stored in the `OutboundMessages` storage map of +the [message lane module](../../modules/message-lane/README.md). This map is used to build +`FromBridgedChainMessagesProof`. The proof holds the lane id, range of message nonces included in +the proof, storage proof of `OutboundMessages` entries and the hash of bridged chain header that has +been used to build the proof. Additionally, there's storage proof may contain the proof of outbound +lane state. It may be required to prune `relayers` entries at this chain (see +[message lane module documentation](../../modules/message-lane/README.md#What-about-other-Constants-in-the-Message-Lane-Module-Configuration-Trait) +for details). This proof is verified by the `verify_messages_proof` function. diff --git a/modules/call-dispatch/README.md b/modules/call-dispatch/README.md new file mode 100644 index 0000000000000..0351aa9e503bc --- /dev/null +++ b/modules/call-dispatch/README.md @@ -0,0 +1,61 @@ +# Call Dispatch Module + +The call dispatch module has a single internal (only callable by other runtime modules) entry point +for dispatching encoded calls (`pallet_bridge_call_dispatch::Module::dispatch`). Every dispatch +(successful or not) emits a corresponding module event. The module doesn't have any call-related +requirements - they may come from the bridged chain over some message lane, or they may be crafted +locally. But in this document we'll mostly talk about this module in the context of bridges. + +Every message that is being dispatched has three main characteristics: +- `bridge` is the 4-bytes identifier of the bridge where this message comes from. This may be the + identifier of the bridged chain (like `b"rlto"` for messages coming from `Rialto`), or the + identifier of the bridge itself (`b"rimi"` for `Rialto` <-> `Millau` bridge); +- `id` is the unique id of the message within the given bridge. For messages coming from the + [message lane module](../message-lane/README.md), it may worth to use a tuple + `(LaneId, MessageNonce)` to identify a message; +- `message` is the `pallet_bridge_call_dispatch::MessagePayload` structure. The `call` field is set + to the (potentially) encoded `Call` of this chain. + +The easiest way to understand what is happening when a `Call` is being dispatched, is to look at the +module events set: + +- `MessageRejected` event is emitted if a message has been rejected even before it has reached the + module. Dispatch then is called just to reflect the fact that message has been received, but we + have failed to pre-process it (e.g. because we have failed to decode `MessagePayload` structure + from the proof); +- `MessageVersionSpecMismatch` event is emitted if current runtime specification version differs + from the version that has been used to encode the `Call`. The message payload has the + `spec_version`, that is filled by the message submitter. If this value differs from the current + runtime version, dispatch mechanism rejects to dispatch the message. Without this check, we may + decode the wrong `Call` for example if method arguments were changed; +- `MessageCallDecodeFailed` event is emitted if we have failed to decode `Call` from the payload. + This may happen if the submitter has provided incorrect value in the `call` field, or if source + chain storage has been corrupted. The `Call` is decoded after `spec_version` check, so we'll never + try to decode `Call` from other runtime version; +- `MessageSignatureMismatch` event is emitted if submitter has chose to dispatch message using + specified this chain account (`pallet_bridge_call_dispatch::CallOrigin::TargetAccount` origin), + but he has failed to prove that he owns the private key for this account; +- `MessageCallRejected` event is emitted if the module has been deployed with some call filter and + this filter has rejected the `Call`. In your bridge you may choose to reject all messages except + e.g. balance transfer calls; +- `MessageWeightMismatch` event is emitted if the message submitter has specified invalid `Call` + dispatch weight in the `weight` field of the message payload. The value of this field is compared + to the pre-dispatch weight of the decoded `Call`. If it is less than the actual pre-dispatch + weight, the dispatch is rejected. Keep in mind, that even if post-dispatch weight will be less + than specified, the submitter still have to declare (and pay for) the maximal possible weight + (that is the pre-dispatch weight); +- `MessageDispatched` event is emitted if the message has passed all checks and we have actually + dispatched it. The dispatch may still fail, though - that's why we are including the dispatch + result in the event payload. + +When we talk about module in context of bridges, these events are helping in following cases: + +1. when the message submitter has access to the state of both chains and wants to monitor what has + happened with his message. Then he could use the message id (that he gets from the + [message lane module events](../message-lane/README.md#General-Information)) to filter events of + call dispatch module at the target chain and actually see what has happened with his message; + +1. when the message submitter only has access to the source chain state (for example, when sender is + the runtime module at the source chain). In this case, your bridge may have additional mechanism + to deliver dispatch proofs (which are storage proof of module events) back to the source chain, + thus allowing the submitter to see what has happened with his messages. diff --git a/modules/message-lane/README.md b/modules/message-lane/README.md index 3213aafe25188..a732042bd0d49 100644 --- a/modules/message-lane/README.md +++ b/modules/message-lane/README.md @@ -1,28 +1,262 @@ # Message Lane Module -The Message Lane Module is used to deliver messages from source to target chain. Message is (almost) opaque to the module and the final goal is to hand message to the message dispatch mechanism. +The message lane module is used to deliver messages from source chain to target chain. Message is +(almost) opaque to the module and the final goal is to hand message to the message dispatch +mechanism. -## Overview +## Contents +- [Overview](#overview) +- [Message Workflow](#message-workflow) +- [Integrating Message Lane Module into Runtime](#integrating-message-lane-module-into-runtime) +- [Non-Essential Functionality](#non-essential-functionality) +- [Weights of Module Extrinsics](#weights-of-module-extrinsics) -*In progress* +## Overview -## Weights of module extrinsics +Message lane is an unidirectional channel, where messages are sent from source chain to the target +chain. At the same time, a single instance of message lane module supports both outbound lanes and +inbound lanes. So the chain where the module is deployed (this chain), may act as a source chain for +outbound messages (heading to a bridged chain) and as a target chain for inbound messages (coming +from a bridged chain). + +Message lane module supports multiple message lanes. Every message lane is identified with a 4-byte +identifier. Messages sent through the lane are assigned unique (for this lane) increasing integer +value that is known as nonce ("number that can only be used once"). Messages that are sent over the +same lane are guaranteed to be delivered to the target chain in the same order they're sent from +the source chain. In other words, message with nonce `N` will be delivered right before delivering a +message with nonce `N+1`. + +Single message lane may be seen as a transport channel for single application (onchain, offchain or +mixed). At the same time the module itself never dictates any lane or message rules. In the end, it +is the runtime developer who defines what message lane and message mean for this runtime. + +## Message Workflow + +The message "appears" when its submitter calls the `send_message()` function of the module. The +submitter specifies the lane that he's willing to use, the message itself and the fee that he's +willing to pay for the message delivery and dispatch. If a message passes all checks, the nonce is +assigned and the message is stored in the module storage. The message is in an "undelivered" state +now. + +We assume that there are external, offchain actors, called relayers, that are submitting module +related transactions to both target and source chains. The pallet itself has no assumptions about +relayers incentivization scheme, but it has some callbacks for paying rewards. See +[Integrating Message Lane Module into runtime](#Integrating-Message-Lane-Module-into-runtime) +for details. + +Eventually, some relayer would notice this message in the "undelivered" state and it would decide to +deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery +transaction) for the message lane module instance, deployed at the target chain. Relayer provides +his account id at the source chain, the proof of message (or several messages), the number of +messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the +message is considered "delivered". + +Once a message is delivered, the relayer may want to confirm delivery back to the source chain. +There are two reasons why he would want to do that. The first is that we intentionally limit number +of "delivered", but not yet "confirmed" messages at inbound lanes +(see [What about other Constants in the Message Lane Module Configuration Trait](#What-about-other-Constants-in-the-Message-Lane-Module-Configuration-Trait) for explanation). +So at some point, the target chain may stop accepting new messages until relayers confirm some of +these. The second is that if the relayer wants to be rewarded for delivery, he must prove the fact +that he has actually delivered the message. And this proof may only be generated after the delivery +transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka +confirmation transaction) for the message lane module instance, deployed at the source chain. Once +this transaction is mined, the message is considered "confirmed". + +The "confirmed" state is the final state of the message. But there's one last thing related to the +message - the fact that it is now "confirmed" and reward has been paid to the relayer (or at least +callback for this has been called), must be confirmed to the target chain. Otherwise, we may reach +the limit of "unconfirmed" messages at the target chain and it will stop accepting new messages. So +relayer sometimes includes a nonce of the latest "confirmed" message in the next +`receive_messages_proof()` transaction, proving that some messages have been confirmed. + +## Integrating Message Lane Module into Runtime + +As it has been said above, the message lane module supports both outbound and inbound message lanes. +So if we will integrate a module in some runtime, it may act as the source chain runtime for +outbound messages and as the target chain runtime for inbound messages. In this section, we'll +sometimes refer to the chain we're currently integrating with, as this chain and the other chain as +bridged chain. + +Message lane module doesn't simply accept transactions that are claiming that the bridged chain has +some updated data for us. Instead of this, the module assumes that the bridged chain is able to +prove that updated data in some way. The proof is abstracted from the module and may be of any kind. +In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other bridges may use +transaction proofs, Substrate header digests or anything else that may be proved. + +**IMPORTANT NOTE**: everything below in this chapter describes details of the message lane module +configuration. But if you interested in well-probed and relatively easy integration of two +Substrate-based chains, you may want to look at the +[bridge-runtime-common](../../bin/runtime-common/README.md) crate. This crate is providing a lot of +helpers for integration, which may be directly used from within your runtime. Then if you'll decide +to change something in this scheme, get back here for detailed information. + +### General Information + +The message lane module supports instances. Every module instance is supposed to bridge this chain +and some bridged chain. To bridge with another chain, using another instance is suggested (this +isn't forced anywhere in the code, though). + +Message submitters may track message progress by inspecting module events. When Message is accepted, +the `MessageAccepted` event is emitted in the `send_message()` transaction. The event contains both +message lane identifier and nonce that has been assigned to the message. When a message is delivered +to the target chain, the `MessagesDelivered` event is emitted from the +`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane +identifier and inclusive range of delivered message nonces. + +### How to plug-in Message Lane Module to Send Messages to the Bridged Chain? + +The `pallet_message_lane::Config` trait has 3 main associated types that are used to work with +outbound messages. The `pallet_message_lane::Config::TargetHeaderChain` defines how we see the +bridged chain as the target for our outbound messages. It must be able to check that the bridged +chain may accept our message - like that the message has size below maximal possible transaction +size of the chain and so on. And when the relayer sends us a confirmation transaction, this +implementation must be able to parse and verify the proof of messages delivery. Normally, you would +reuse the same (configurable) type on all chains that are sending messages to the same bridged +chain. + +The `pallet_message_lane::Config::LaneMessageVerifier` defines a single callback to verify outbound +messages. The simplest callback may just accept all messages. But in this case you'll need to answer +many questions first. Who will pay for the delivery and confirmation transaction? Are we sure that +someone will ever deliver this message to the bridged chain? Are we sure that we don't bloat our +runtime storage by accepting this message? What if the message is improperly encoded or has some +fields set to invalid values? Answering all those (and similar) questions would lead to correct +implementation. + +There's another thing to consider when implementing type for use in +`pallet_message_lane::Config::LaneMessageVerifier`. It is whether we treat all message lanes +identically, or they'll have different sets of verification rules? For example, you may reserve +lane#1 for messages coming from some 'wrapped-token' pallet - then you may verify in your +implementation that the origin is associated with this pallet. Lane#2 may be reserved for 'system' +messages and you may charge zero fee for such messages. You may have some rate limiting for messages +sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is +all up to the `pallet_message_lane::Config::LaneMessageVerifier` implementation. + +The last type is the `pallet_message_lane::Config::MessageDeliveryAndDispatchPayment`. When all +checks are made and we have decided to accept the message, we're calling the +`pay_delivery_and_dispatch_fee()` callback, passing the corresponding argument of the `send_message` +function. Later, when message delivery is confirmed, we're calling `pay_relayers_rewards()` +callback, passing accounts of relayers and messages that they have delivered. The simplest +implementation of this trait is in the [`instant_payments.rs`](./src/instant_payments.rs) module and +simply calls `Currency::transfer()` when those callbacks are called. So `Currency` units are +transferred between submitter, 'relayers fund' and relayers accounts. Other implementations may use +more or less sophisticated techniques - the whole relayers incentivization scheme is not a part of +the message lane module. + +### I have a Message Lane Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? + +You should be looking at the `bp_message_lane::source_chain::ForbidOutboundMessages` structure +[`bp_message_lane::source_chain`](../../primitives/message-lane/src/source_chain.rs). It implements +all required traits and will simply reject all transactions, related to outbound messages. + +### How to plug-in Message Lane Module to Receive Messages from the Bridged Chain? + +The `pallet_message_lane::Config` trait has 2 main associated types that are used to work with +inbound messages. The `pallet_message_lane::Config::SourceHeaderChain` defines how we see the +bridged chain as the source or our inbound messages. When relayer sends us a delivery transaction, +this implementation must be able to parse and verify the proof of messages wrapped in this +transaction. Normally, you would reuse the same (configurable) type on all chains that are sending +messages to the same bridged chain. + +The `pallet_message_lane::Config::MessageDispatch` defines a way on how to dispatch delivered +messages. Apart from actually dispatching the message, the implementation must return the correct +dispatch weight of the message before dispatch is called. + +### I have a Message Lane Module in my Runtime, but I Want to Reject all Inbound Messages. What +shall I do? + +You should be looking at the `bp_message_lane::target_chain::ForbidInboundMessages` structure from +the [`bp_message_lane::target_chain`](../../primitives/message-lane/src/target_chain.rs) module. It +implements all required traits and will simply reject all transactions, related to inbound messages. + +### What about other Constants in the Message Lane Module Configuration Trait? + +Message is being stored in the source chain storage until its delivery will be confirmed. After +that, we may safely remove the message from the storage. Lane messages are removed (pruned) when +someone sends a new message using the same lane. So the message submitter pays for that pruning. To +avoid pruning too many messages in a single transaction, there's +`pallet_message_lane::Config::MaxMessagesToPruneAtOnce` configuration parameter. We will never prune +more than this number of messages in the single transaction. That said, the value should not be too +big to avoid waste of resources when there are no messages to prune. + +To be able to reward the relayer for delivering messages, we store a map of message nonces range => +identifier of the relayer that has delivered this range at the target chain runtime storage. If a +relayer delivers multiple consequent ranges, they're merged into single entry. So there may be more +than one entry for the same relayer. Eventually, this whole map must be delivered back to the source +chain to confirm delivery and pay rewards. So to make sure we are able to craft this confirmation +transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure that +the weight of processing this map is below a certain limit. Both size and processing weight mostly +depend on the number of entries. The number of entries is limited with the +`pallet_message_lane::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight +also depends on the total number of messages that are being confirmed, because every confirmed +message needs to be read. So there's another +`pallet_message_lane::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. + +When choosing values for these parameters, you must also keep in mind that if proof in your scheme +is based on finality of headers (and it is the most obvious option for Substrate-based chains with +finality notion), then choosing too small values for these parameters may cause significant delays +in message delivery. That's because there too many actors involved in this scheme: 1) authorities +that are finalizing headers of the target chain need to finalize header with non-empty map; 2) the +headers relayer then needs to submit this header and its finality proof to the source chain; 3) the +messages relayer must then send confirmation transaction (storage proof of this map) to the source +chain; 4) when the confirmation transaction will be mined at some header, source chain authorities +must finalize this header; 5) the headers relay then needs to submit this header and its finality +proof to the target chain; 6) only now the messages relayer may submit new messages from the source +to target chain and prune the entry from the map. + +Delivery transaction requires the relayer to provide both number of entries and total number of +messages in the map. This means that the module never charges an extra cost for delivering a map - +the relayer would need to pay exactly for the number of entries+messages it has delivered. So the +best guess for values of these parameters would be the pair that would occupy `N` percent of the +maximal transaction size and weight of the source chain. The `N` should be large enough to process +large maps, at the same time keeping reserve for future source chain upgrades. + +## Non-Essential Functionality + +Apart from the message related calls, the module exposes a set of auxiliary calls. They fall in two +groups, described in the next two paragraphs. + +There may be a special account in every runtime where the message lane module is deployed. This +account, named 'module owner', is like a module-level sudo account - he's able to halt all and +result all module operations without requiring runtime upgrade. The module may have no message +owner, but we suggest to use it at least for initial deployment. To calls that are related to this +account are: +- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; +- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all + module operations. After this call, all message-related transactions will be rejected until + further `resume_operations` call'. This call may be used when something extraordinary happens with + the bridge; +- `fn resume_operations()`: module owner may call this function to resume bridge operations. The + module will resume its regular operations after this call. + +Apart from halting and resuming the bridge, the module owner may also tune module configuration +parameters without runtime upgrades. The set of parameters needs to be designed in advance, though. +The module configuration trait has associated `Parameter` type, which may be e.g. enum and represent +a set of parameters that may be updated by the module owner. For example, if your bridge needs to +convert sums between different tokens, you may define a 'conversion rate' parameter and let the +module owner update this parameter when there are significant changes in the rate. The corresponding +module call is `fn update_pallet_parameter()`. + +## Weights of Module Extrinsics The main assumptions behind weight formulas is: - all possible costs are paid in advance by the message submitter; -- whenever possible, relayer tries to minimize cost of its transactions. So e.g. even though sender always pays for delivering outbound lane state proof, relayer may not include it in the delivery transaction (unless message lane module on target chain requires that); -- weight formula should incentivize relayer to not to submit any redundand data in the extrinsics arguments; -- the extrinsic shall never be executing slower (i.e. has larger actual weight) than defined by the formula. +- whenever possible, relayer tries to minimize cost of its transactions. So e.g. even though sender + always pays for delivering outbound lane state proof, relayer may not include it in the delivery + transaction (unless message lane module on target chain requires that); +- weight formula should incentivize relayer to not to submit any redundant data in the extrinsics + arguments; +- the extrinsic shall never be executing slower (i.e. has larger actual weight) than defined by the + formula. ### Weight of `send_message` call #### Related benchmarks -| Benchmark | Description | -|-----------------------------------|--------------------------------------------------------| -| `send_minimal_message_worst_case` | Sends 0-size message with worst possible conditions | -| `send_1_kb_message_worst_case` | Sends 1KB-size message with worst possible conditions | -| `send_16_kb_message_worst_case` | Sends 16KB-size message with worst possible conditions | +| Benchmark | Description | +|-----------------------------------|-----------------------------------------------------| +`send_minimal_message_worst_case` | Sends 0-size message with worst possible conditions | +`send_1_kb_message_worst_case` | Sends 1KB-size message with worst possible conditions | +`send_16_kb_message_worst_case` | Sends 16KB-size message with worst possible conditions | #### Weight formula @@ -52,13 +286,19 @@ Where: *\* - In all benchmarks all received messages are dispatched and their dispatch cost is near to zero* -*\*\* - Trie leafs are assumed to have minimal values. The proof is derived from the minimal proof by including more trie nodes. That's because according to `receive_message_proofs_with_large_leaf` and `receive_message_proofs_with_extra_nodes` benchmarks, increasing proof by including more nodes has slightly larger impact on performance than increasing values stored in leafs*. +*\*\* - Trie leafs are assumed to have minimal values. The proof is derived from the minimal proof +by including more trie nodes. That's because according to `receive_message_proofs_with_large_leaf` +and `receive_message_proofs_with_extra_nodes` benchmarks, increasing proof by including more nodes +has slightly larger impact on performance than increasing values stored in leafs*. #### Weight formula The weight formula is: ``` -Weight = BaseWeight + OutboundStateDeliveryWeight + MessagesCount * MessageDeliveryWeight + MessagesDispatchWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight +Weight = BaseWeight + OutboundStateDeliveryWeight + + MessagesCount * MessageDeliveryWeight + + MessagesDispatchWeight + + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight ``` Where: @@ -78,22 +318,34 @@ Where: We have following checks in `send_message` transaction on the source chain: - message size should be less than or equal to `2/3` of maximal extrinsic size on the target chain; -- message dispatch weight should be less than or equal to the `1/2` of maximal extrinsic dispatch weight on the target chain. +- message dispatch weight should be less than or equal to the `1/2` of maximal extrinsic dispatch + weight on the target chain. -Delivery transaction is an encoded delivery call and signed extensions. So we have `1/3` of maximal extrinsic size reserved for: -- storage proof, excluding the message itself. Currently, on our test chains, the overhead is always within `EXTRA_STORAGE_PROOF_SIZE` limits (1024 bytes); -- signed extras and other call arguments (`relayer_id: SourceChain::AccountId`, `messages_count: u32`, `dispatch_weight: u64`). +Delivery transaction is an encoded delivery call and signed extensions. So we have `1/3` of maximal +extrinsic size reserved for: +- storage proof, excluding the message itself. Currently, on our test chains, the overhead is always + within `EXTRA_STORAGE_PROOF_SIZE` limits (1024 bytes); +- signed extras and other call arguments (`relayer_id: SourceChain::AccountId`, `messages_count: + u32`, `dispatch_weight: u64`). -On Millau chain, maximal extrinsic size is `0.75 * 2MB`, so `1/3` is `512KB` (`524_288` bytes). This should be enough to cover these extra arguments and signed extensions. +On Millau chain, maximal extrinsic size is `0.75 * 2MB`, so `1/3` is `512KB` (`524_288` bytes). This +should be enough to cover these extra arguments and signed extensions. Let's exclude message dispatch cost from single message delivery transaction weight formula: ``` -Weight = BaseWeight + OutboundStateDeliveryWeight + MessageDeliveryWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight +Weight = BaseWeight + OutboundStateDeliveryWeight + MessageDeliveryWeight + + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight ``` -So we have `1/2` of maximal extrinsic weight to cover these components. `BaseWeight`, `OutboundStateDeliveryWeight` and `MessageDeliveryWeight` are determined using benchmarks and are hardcoded into runtime. Adequate relayer would only include required trie nodes into the proof. So if message size would be maximal (`2/3` of `MaximalExtrinsicSize`), then the extra proof size would be `MaximalExtrinsicSize / 3 * 2 - EXPECTED_DEFAULT_MESSAGE_LENGTH`. +So we have `1/2` of maximal extrinsic weight to cover these components. `BaseWeight`, +`OutboundStateDeliveryWeight` and `MessageDeliveryWeight` are determined using benchmarks and are +hardcoded into runtime. Adequate relayer would only include required trie nodes into the proof. So +if message size would be maximal (`2/3` of `MaximalExtrinsicSize`), then the extra proof size would +be `MaximalExtrinsicSize / 3 * 2 - EXPECTED_DEFAULT_MESSAGE_LENGTH`. -Both conditions are verified by `pallet_message_lane::ensure_weights_are_correct` and `pallet_message_lane::ensure_able_to_receive_messages` functions, which must be called from every runtime' tests. +Both conditions are verified by `pallet_message_lane::ensure_weights_are_correct` and +`pallet_message_lane::ensure_able_to_receive_messages` functions, which must be called from every +runtime's tests. ### Weight of `receive_messages_delivery_proof` call @@ -109,7 +361,9 @@ Both conditions are verified by `pallet_message_lane::ensure_weights_are_correct The weight formula is: ``` -Weight = BaseWeight + MessagesCount * MessageConfirmationWeight + RelayersCount * RelayerRewardWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight +Weight = BaseWeight + MessagesCount * MessageConfirmationWeight + + RelayersCount * RelayerRewardWeight + + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight ``` Where: @@ -127,6 +381,11 @@ Where: #### Why we're always able to craft `receive_messages_delivery_proof` transaction? -There can be at most `::MaxUnconfirmedMessagesAtInboundLane` messages and at most `::MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers in the single delivery confirmation transaction. +There can be at most `::MaxUnconfirmedMessagesAtInboundLane` +messages and at most +`::MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded +relayers in the single delivery confirmation transaction. -We're checking that this transaction may be crafted in the `pallet_message_lane::ensure_able_to_receive_confirmation` function, which must be called from every runtime' tests. +We're checking that this transaction may be crafted in the +`pallet_message_lane::ensure_able_to_receive_confirmation` function, which must be called from every +runtime' tests. From 23eb4b031037484ec9aca82f0acca135f577978a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 25 Feb 2021 06:21:39 +0100 Subject: [PATCH 0350/1210] Add inspect command to take a look at extrinsics. (#762) * Add inspect command to take a look at extrinsics. * cargo fmt --all * New weight for on-chain remark in tests * Minor style tweaks. Co-authored-by: adoerr <0xad@gmx.net> --- bin/millau/node/Cargo.toml | 5 +++-- bin/millau/node/src/cli.rs | 7 +++++-- bin/millau/node/src/command.rs | 6 +++++- bin/rialto/node/Cargo.toml | 7 ++++--- bin/rialto/node/src/cli.rs | 7 +++++-- bin/rialto/node/src/command.rs | 6 +++++- modules/call-dispatch/src/lib.rs | 2 +- 7 files changed, 28 insertions(+), 12 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index a03078163a189..3432701e0d337 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -26,6 +26,7 @@ pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +node-inspect = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } @@ -35,14 +36,14 @@ sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "m sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 1149c4f910c8d..c1d42a1f21b12 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -31,6 +31,7 @@ pub struct Cli { pub enum Subcommand { /// Key management cli utilities Key(sc_cli::KeySubcommand), + /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. Verify(sc_cli::VerifyCmd), @@ -61,7 +62,9 @@ pub enum Subcommand { /// Revert the chain to a previous state. Revert(sc_cli::RevertCmd), - /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + /// Inspect blocks or extrinsics. + Inspect(node_inspect::cli::InspectCmd), + + /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), } diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 8751a4516d1de..8e6427ed804bb 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -17,7 +17,7 @@ use crate::cli::{Cli, Subcommand}; use crate::service; use crate::service::new_partial; -use millau_runtime::Block; +use millau_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; @@ -154,6 +154,10 @@ pub fn run() -> sc_cli::Result<()> { Ok((cmd.run(client, backend), task_manager)) }) } + Some(Subcommand::Inspect(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run::(config)) + } None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 072667694a196..da602d35861f9 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -26,6 +26,7 @@ rialto-runtime = { path = "../runtime" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +node-inspect = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } @@ -35,15 +36,15 @@ sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "m sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 1149c4f910c8d..c1d42a1f21b12 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -31,6 +31,7 @@ pub struct Cli { pub enum Subcommand { /// Key management cli utilities Key(sc_cli::KeySubcommand), + /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. Verify(sc_cli::VerifyCmd), @@ -61,7 +62,9 @@ pub enum Subcommand { /// Revert the chain to a previous state. Revert(sc_cli::RevertCmd), - /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + /// Inspect blocks or extrinsics. + Inspect(node_inspect::cli::InspectCmd), + + /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 8242c9eaaba03..83d2a98b67b5b 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -17,7 +17,7 @@ use crate::cli::{Cli, Subcommand}; use crate::service; use crate::service::new_partial; -use rialto_runtime::Block; +use rialto_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; @@ -153,6 +153,10 @@ pub fn run() -> sc_cli::Result<()> { Ok((cmd.run(client, backend), task_manager)) }) } + Some(Subcommand::Inspect(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run::(config)) + } None => { let runner = cli.create_runner(&cli.run)?; runner diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 7f41322455455..87f7238d9a62b 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -606,7 +606,7 @@ mod tests { vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageWeightMismatch( - bridge, id, 1973000, 0, + bridge, id, 1279000, 0, )), topics: vec![], }], From 4d58eb2666eb1269065b8047a02cba265cb3dc22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 25 Feb 2021 18:28:03 +0100 Subject: [PATCH 0351/1210] Add default for some options. (#763) --- relays/substrate/src/cli.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 8dc241f069e1c..38785665e1460 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -93,8 +93,8 @@ pub enum RelayMessages { rialto_sign: RialtoSigningParams, #[structopt(flatten)] prometheus_params: PrometheusParams, - /// Hex-encoded id of lane that should be served by relay. - #[structopt(long)] + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] lane: HexLaneId, }, /// Serve given lane of Rialto -> Millau messages. @@ -109,8 +109,8 @@ pub enum RelayMessages { millau_sign: MillauSigningParams, #[structopt(flatten)] prometheus_params: PrometheusParams, - /// Hex-encoded id of lane that should be served by relay. - #[structopt(long)] + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] lane: HexLaneId, }, } @@ -151,8 +151,8 @@ pub enum SendMessage { millau_sign: MillauSigningParams, #[structopt(flatten)] rialto_sign: RialtoSigningParams, - /// Hex-encoded lane id. - #[structopt(long)] + /// Hex-encoded lane id. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] lane: HexLaneId, /// Dispatch weight of the message. If not passed, determined automatically. #[structopt(long)] @@ -163,8 +163,9 @@ pub enum SendMessage { /// Message type. #[structopt(subcommand)] message: ToRialtoMessage, - /// The origin to use when dispatching the message on the target chain. - #[structopt(long, possible_values = &Origins::variants())] + /// The origin to use when dispatching the message on the target chain. Defaults to + /// `SourceAccount`. + #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] origin: Origins, }, /// Submit message to given Rialto -> Millau lane. @@ -175,8 +176,8 @@ pub enum SendMessage { rialto_sign: RialtoSigningParams, #[structopt(flatten)] millau_sign: MillauSigningParams, - /// Hex-encoded lane id. - #[structopt(long)] + /// Hex-encoded lane id. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] lane: HexLaneId, /// Dispatch weight of the message. If not passed, determined automatically. #[structopt(long)] @@ -187,8 +188,9 @@ pub enum SendMessage { /// Message type. #[structopt(subcommand)] message: ToMillauMessage, - /// The origin to use when dispatching the message on the target chain. - #[structopt(long, possible_values = &Origins::variants())] + /// The origin to use when dispatching the message on the target chain. Defaults to + /// `SourceAccount`. + #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] origin: Origins, }, } @@ -321,7 +323,7 @@ macro_rules! declare_chain_options { #[derive(StructOpt)] pub struct [<$chain ConnectionParams>] { #[doc = "Connect to " $chain " node at given host."] - #[structopt(long)] + #[structopt(long, default_value = "127.0.0.1")] pub [<$chain_prefix _host>]: String, #[doc = "Connect to " $chain " node websocket server at given port."] #[structopt(long)] From c0732370d45cc735339fd0b77ae822f765363a25 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 26 Feb 2021 06:43:05 -0500 Subject: [PATCH 0352/1210] Stop counting invalid requests towards rate limit (#765) --- modules/finality-verifier/src/lib.rs | 39 ++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index a87bd75b992f5..4e05c5754d989 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -75,6 +75,8 @@ pub mod pallet { /// The upper bound on the number of requests allowed by the pallet. /// + /// A request refers to an action which writes a header to storage. + /// /// Once this bound is reached the pallet will not allow any dispatchables to be called /// until the request count has decreased. #[pallet::constant] @@ -117,7 +119,6 @@ pub mod pallet { Self::request_count() < T::MaxRequests::get(), >::TooManyRequests ); - >::mutate(|count| *count += 1); frame_support::debug::trace!("Going to try and finalize header {:?}", finality_target); @@ -144,11 +145,13 @@ pub mod pallet { T::HeaderChain::append_header(finality_target); frame_support::debug::info!("Succesfully imported finalized header with hash {:?}!", hash); + >::mutate(|count| *count += 1); + Ok(().into()) } } - /// The current number of requests for calling dispatchables. + /// The current number of requests which have written to storage. /// /// If the `RequestCount` hits `MaxRequests`, no more calls will be allowed to the pallet until /// the request capacity is increased. @@ -340,6 +343,38 @@ mod tests { }) } + #[test] + fn invalid_requests_do_not_count_towards_request_count() { + run_test(|| { + let submit_invalid_request = || { + let child = test_header(1); + let header = test_header(2); + + let invalid_justification = vec![4, 2, 4, 2].encode(); + let ancestry_proof = vec![child, header.clone()]; + + Module::::submit_finality_proof( + Origin::signed(1), + header, + invalid_justification, + ancestry_proof, + ) + }; + + initialize_substrate_bridge(); + + for _ in 0..::MaxRequests::get() + 1 { + // Notice that the error here *isn't* `TooManyRequests` + assert_err!(submit_invalid_request(), >::InvalidJustification); + } + + // Can still submit `MaxRequests` requests afterwards + assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof()); + assert_err!(submit_finality_proof(), >::TooManyRequests); + }) + } + #[test] fn allows_request_after_new_block_has_started() { run_test(|| { From 94487280fe23c16105073900067f35055a242df4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 26 Feb 2021 12:57:06 -0500 Subject: [PATCH 0353/1210] Use No-Op Ancestry Checker (#755) * Use no-op ancestry checker * Check that current header height is greater than last finalized * Ensure that incoming headers are strictly greater than last finalized * Ensure that header numbers always increase in tests --- bin/millau/runtime/src/lib.rs | 4 +-- bin/rialto/runtime/src/lib.rs | 4 +-- modules/finality-verifier/src/lib.rs | 38 ++++++++++++------------ modules/substrate/src/lib.rs | 44 +++++++++++++++++++++++----- primitives/header-chain/src/lib.rs | 6 ++-- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index bee7881f26d84..89440184002ff 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -313,8 +313,8 @@ parameter_types! { impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type HeaderChain = pallet_substrate_bridge::Module; - type AncestryProof = Vec; - type AncestryChecker = bp_header_chain::LinearAncestryChecker; + type AncestryProof = (); + type AncestryChecker = (); type MaxRequests = MaxRequests; } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index af1d7c6c9faf3..6bb73ef037aa0 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -420,8 +420,8 @@ parameter_types! { impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_millau::Millau; type HeaderChain = pallet_substrate_bridge::Module; - type AncestryProof = Vec; - type AncestryChecker = bp_header_chain::LinearAncestryChecker; + type AncestryProof = (); + type AncestryChecker = (); type MaxRequests = MaxRequests; } diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 4e05c5754d989..8f3505252ecd5 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -142,7 +142,7 @@ pub mod pallet { >::InvalidAncestryProof ); - T::HeaderChain::append_header(finality_target); + let _ = T::HeaderChain::append_header(finality_target)?; frame_support::debug::info!("Succesfully imported finalized header with hash {:?}!", hash); >::mutate(|count| *count += 1); @@ -203,9 +203,9 @@ mod tests { )); } - fn submit_finality_proof() -> frame_support::dispatch::DispatchResultWithPostInfo { - let child = test_header(1); - let header = test_header(2); + fn submit_finality_proof(child: u8, header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { + let child = test_header(child.into()); + let header = test_header(header.into()); let set_id = 1; let grandpa_round = 1; @@ -228,7 +228,7 @@ mod tests { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof(1, 2)); let header = test_header(2); assert_eq!( @@ -337,9 +337,9 @@ mod tests { fn disallows_imports_once_limit_is_hit_in_single_block() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof()); - assert_ok!(submit_finality_proof()); - assert_err!(submit_finality_proof(), >::TooManyRequests); + assert_ok!(submit_finality_proof(1, 2)); + assert_ok!(submit_finality_proof(3, 4)); + assert_err!(submit_finality_proof(5, 6), >::TooManyRequests); }) } @@ -379,11 +379,11 @@ mod tests { fn allows_request_after_new_block_has_started() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof()); - assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof(1, 2)); + assert_ok!(submit_finality_proof(3, 4)); next_block(); - assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof(5, 6)); }) } @@ -391,12 +391,12 @@ mod tests { fn disallows_imports_once_limit_is_hit_across_different_blocks() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof()); - assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof(1, 2)); + assert_ok!(submit_finality_proof(3, 4)); next_block(); - assert_ok!(submit_finality_proof()); - assert_err!(submit_finality_proof(), >::TooManyRequests); + assert_ok!(submit_finality_proof(5, 6)); + assert_err!(submit_finality_proof(7, 8), >::TooManyRequests); }) } @@ -404,15 +404,15 @@ mod tests { fn allows_max_requests_after_long_time_with_no_activity() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof()); - assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof(1, 2)); + assert_ok!(submit_finality_proof(3, 4)); next_block(); next_block(); next_block(); - assert_ok!(submit_finality_proof()); - assert_ok!(submit_finality_proof()); + assert_ok!(submit_finality_proof(5, 6)); + assert_ok!(submit_finality_proof(7, 8)); }) } } diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index c14db8596f89e..1ae23fdf91b1c 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -155,6 +155,11 @@ decl_error! { AlreadyInitialized, /// The given header is not a descendant of a particular header. NotDescendant, + /// The header being imported is on a fork which is incompatible with the current chain. + /// + /// This can happen if we try and import a finalized header at a lower height than our + /// current `best_finalized` header. + ConflictingFork, } } @@ -375,8 +380,14 @@ impl bp_header_chain::HeaderChain, sp_runtime::Dispa PalletStorage::::new().current_authority_set() } - fn append_header(header: BridgedHeader) { + fn append_header(header: BridgedHeader) -> Result<(), sp_runtime::DispatchError> { + // We do a quick check here to ensure that our header chain is making progress and isn't + // "travelling back in time" (which would be indicative of something bad, e.g a hard-fork). + let best_finalized = PalletStorage::::new().best_finalized_header().header; + ensure!(best_finalized.number() < header.number(), >::ConflictingFork); import_header_unchecked::<_, T>(&mut PalletStorage::::new(), header); + + Ok(()) } } @@ -714,7 +725,7 @@ mod tests { use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestHeader, TestRuntime}; use bp_header_chain::HeaderChain; use bp_test_utils::{alice, authority_list, bob}; - use frame_support::{assert_noop, assert_ok}; + use frame_support::{assert_err, assert_noop, assert_ok}; use sp_runtime::DispatchError; fn init_with_origin(origin: Origin) -> Result, DispatchError> { @@ -907,7 +918,7 @@ mod tests { let storage = PalletStorage::::new(); let header = test_header(2); - Module::::append_header(header.clone()); + assert_ok!(Module::::append_header(header.clone())); assert!(storage.header_by_hash(header.hash()).unwrap().is_finalized); assert_eq!(storage.best_finalized_header().header, header); @@ -915,6 +926,25 @@ mod tests { }) } + #[test] + fn importing_unchecked_header_ensures_that_chain_is_extended() { + run_test(|| { + init_with_origin(Origin::root()).unwrap(); + + let header = test_header(3); + assert_ok!(Module::::append_header(header)); + + let header = test_header(2); + assert_err!( + Module::::append_header(header), + Error::::ConflictingFork, + ); + + let header = test_header(4); + assert_ok!(Module::::append_header(header)); + }) + } + #[test] fn importing_unchecked_headers_enacts_new_authority_set() { run_test(|| { @@ -930,7 +960,7 @@ mod tests { header.digest = fork_tests::change_log(0); // Let's import our test header - Module::::append_header(header.clone()); + assert_ok!(Module::::append_header(header.clone())); // Make sure that our header is the best finalized assert_eq!(storage.best_finalized_header().header, header); @@ -960,8 +990,8 @@ mod tests { let header = test_header(3); // Let's import our test headers - Module::::append_header(schedules_change); - Module::::append_header(header.clone()); + assert_ok!(Module::::append_header(schedules_change)); + assert_ok!(Module::::append_header(header.clone())); // Make sure that our header is the best finalized assert_eq!(storage.best_finalized_header().header, header); @@ -1001,7 +1031,7 @@ mod tests { // We are expecting an authority set change at height 2, so this header should enact // that upon being imported. - Module::::append_header(test_header(2)); + assert_ok!(Module::::append_header(test_header(2))); // Make sure that the authority set actually changed upon importing our header assert_eq!( diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 1663717646021..a2d8574b6dc48 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -78,7 +78,7 @@ pub trait HeaderChain { fn authority_set() -> AuthoritySet; /// Write a header finalized by GRANDPA to the underlying pallet storage. - fn append_header(header: H); + fn append_header(header: H) -> Result<(), E>; } impl HeaderChain for () { @@ -90,7 +90,9 @@ impl HeaderChain for () { AuthoritySet::default() } - fn append_header(_header: H) {} + fn append_header(_header: H) -> Result<(), E> { + Ok(()) + } } /// A trait for checking if a given child header is a direct descendant of an ancestor. From d2adab7f9e6e51a9205d549f378dadbad22e07d6 Mon Sep 17 00:00:00 2001 From: Andreas Doerr Date: Sat, 27 Feb 2021 19:13:48 +0100 Subject: [PATCH 0354/1210] Bump Substrate and Deps (#770) * Bump Substrate and Deps * silence clippy --- relays/ethereum/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index b75c0f44bb856..3ff6d5499a1d2 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -243,6 +243,8 @@ fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result Some( sub_initial_authorities_set_id @@ -270,6 +272,7 @@ fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result Result { + #[allow(clippy::manual_map)] let eth_nonce = if let Some(eth_nonce) = matches.value_of("eth-nonce") { Some( relay_ethereum_client::types::U256::from_dec_str(ð_nonce) @@ -329,6 +332,7 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result ethereum_exchange::ExchangeRelayMode::Auto(match matches.value_of("eth-start-with-block") { Some(eth_start_with_block) => Some( eth_start_with_block From e2680e21e13f446be320224e781e2923f719455f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Feb 2021 07:22:58 +0100 Subject: [PATCH 0355/1210] Disable cache in CI builds. (#772) * Disable cache. * Fix tests. * Fix clippy? * cargo fmt --all --- modules/finality-verifier/src/lib.rs | 6 +-- relays/ethereum/src/main.rs | 72 ++++++++++++++-------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 8f3505252ecd5..3db6cb7bf7cd6 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -369,9 +369,9 @@ mod tests { } // Can still submit `MaxRequests` requests afterwards - assert_ok!(submit_finality_proof()); - assert_ok!(submit_finality_proof()); - assert_err!(submit_finality_proof(), >::TooManyRequests); + assert_ok!(submit_finality_proof(1, 2)); + assert_ok!(submit_finality_proof(3, 4)); + assert_err!(submit_finality_proof(5, 6), >::TooManyRequests); }) } diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index 3ff6d5499a1d2..c0c36cc130666 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -243,16 +243,13 @@ fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result Some( - sub_initial_authorities_set_id - .parse() - .map_err(|e| format!("Failed to parse sub-authorities-set-id: {}", e))?, - ), - None => None, - }; + let sub_initial_authorities_set_id = matches + .value_of("sub-authorities-set-id") + .map(|set| { + set.parse() + .map_err(|e| format!("Failed to parse sub-authorities-set-id: {}", e)) + }) + .transpose()?; let sub_initial_authorities_set = parse_hex_argument(matches, "sub-authorities-set")?; let sub_initial_header = parse_hex_argument(matches, "sub-initial-header")?; @@ -272,24 +269,26 @@ fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result Result { - #[allow(clippy::manual_map)] - let eth_nonce = if let Some(eth_nonce) = matches.value_of("eth-nonce") { - Some( + let eth_nonce = matches + .value_of("eth-nonce") + .map(|eth_nonce| { relay_ethereum_client::types::U256::from_dec_str(ð_nonce) - .map_err(|e| format!("Failed to parse eth-nonce: {}", e))?, - ) - } else { - None - }; - - let eth_amount = if let Some(eth_amount) = matches.value_of("eth-amount") { - eth_amount - .parse() - .map_err(|e| format!("Failed to parse eth-amount: {}", e))? - } else { - // This is in Wei, represents 1 ETH - 1_000_000_000_000_000_000_u64.into() - }; + .map_err(|e| format!("Failed to parse eth-nonce: {}", e)) + }) + .transpose()?; + + let eth_amount = matches + .value_of("eth-amount") + .map(|eth_amount| { + eth_amount + .parse() + .map_err(|e| format!("Failed to parse eth-amount: {}", e)) + }) + .transpose()? + .unwrap_or_else(|| { + // This is in Wei, represents 1 ETH + 1_000_000_000_000_000_000_u64.into() + }); // This is the well-known Substrate account of Ferdie let default_recepient = hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"); @@ -332,15 +331,16 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result ethereum_exchange::ExchangeRelayMode::Auto(match matches.value_of("eth-start-with-block") { - Some(eth_start_with_block) => Some( - eth_start_with_block - .parse() - .map_err(|e| format!("Failed to parse eth-start-with-block: {}", e))?, - ), - None => None, - }), + None => ethereum_exchange::ExchangeRelayMode::Auto( + matches + .value_of("eth-start-with-block") + .map(|eth_start_with_block| { + eth_start_with_block + .parse() + .map_err(|e| format!("Failed to parse eth-start-with-block: {}", e)) + }) + .transpose()?, + ), }; let params = EthereumExchangeParams { From 5acb741dbd486e14b3731880033ee912ab07d28f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 03:21:32 +0000 Subject: [PATCH 0356/1210] Bump serde_json from 1.0.63 to 1.0.64 (#777) --- relays/ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index 0e9fdb7c8a88f..e6f507625b60d 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -22,7 +22,7 @@ libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac" log = "0.4.14" num-traits = "0.2" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.62" +serde_json = "1.0.64" time = "0.2" # Bridge dependencies From 7e599bfa9fb90b97255a4df26aae64a6f680c9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 1 Mar 2021 14:54:08 +0100 Subject: [PATCH 0357/1210] Add few CLI helpers (#764) * Adding call encoding. * Add message payload encoding. * Nicer output. * Add fee estimation. * cargo fmt --all * Split message payload encoding into separate command. * Use HexBytes. * cargo fmt --all * Fix compilation. --- relays/substrate/src/cli.rs | 128 +++++++++++++++ relays/substrate/src/main.rs | 298 ++++++++++++++++++++++++++++------- 2 files changed, 369 insertions(+), 57 deletions(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 38785665e1460..090ff3f92a9f7 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -51,8 +51,21 @@ pub enum Command { /// The message is being sent to the source chain, delivered to the target chain and dispatched /// there. SendMessage(SendMessage), + /// Generate SCALE-encoded `Call` for choosen network. + /// + /// The call can be used either as message payload or can be wrapped into a transaction + /// and executed on the chain directly. + EncodeCall(EncodeCall), + /// Generate SCALE-encoded `MessagePayload` object that can be sent over selected bridge. + /// + /// The `MessagePayload` can be then fed to `MessageLane::send_message` function and sent over + /// the bridge. + EncodeMessagePayload(EncodeMessagePayload), + /// Estimate Delivery and Dispatch Fee required for message submission to message lane. + EstimateFee(EstimateFee), } +/// Start headers relayer process. #[derive(StructOpt)] pub enum RelayHeaders { /// Relay Millau headers to Rialto. @@ -79,6 +92,7 @@ pub enum RelayHeaders { }, } +/// Start message relayer process. #[derive(StructOpt)] pub enum RelayMessages { /// Serve given lane of Millau -> Rialto messages. @@ -115,6 +129,7 @@ pub enum RelayMessages { }, } +/// Initialize bridge pallet. #[derive(StructOpt)] pub enum InitBridge { /// Initialize Millau headers bridge in Rialto. @@ -141,6 +156,7 @@ pub enum InitBridge { }, } +/// Send bridge message. #[derive(StructOpt)] pub enum SendMessage { /// Submit message to given Millau -> Rialto lane. @@ -195,9 +211,112 @@ pub enum SendMessage { }, } +/// A call to encode. +#[derive(StructOpt)] +pub enum EncodeCall { + /// Encode Rialto's Call. + Rialto { + #[structopt(flatten)] + call: ToRialtoMessage, + }, + /// Encode Millau's Call. + Millau { + #[structopt(flatten)] + call: ToMillauMessage, + }, +} + +/// A `MessagePayload` to encode. +#[derive(StructOpt)] +pub enum EncodeMessagePayload { + /// Message Payload of Rialto to Millau call. + RialtoToMillau { + #[structopt(flatten)] + payload: RialtoToMillauMessagePayload, + }, + /// Message Payload of Millau to Rialto call. + MillauToRialto { + #[structopt(flatten)] + payload: MillauToRialtoMessagePayload, + }, +} + +/// Estimate Delivery & Dispatch Fee command. +#[derive(StructOpt)] +pub enum EstimateFee { + /// Estimate fee of Rialto to Millau message. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + /// Hex-encoded id of lane that will be delivering the message. + #[structopt(long)] + lane: HexLaneId, + /// Payload to send over the bridge. + #[structopt(flatten)] + payload: RialtoToMillauMessagePayload, + }, + /// Estimate fee of Rialto to Millau message. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + /// Hex-encoded id of lane that will be delivering the message. + #[structopt(long)] + lane: HexLaneId, + /// Payload to send over the bridge. + #[structopt(flatten)] + payload: MillauToRialtoMessagePayload, + }, +} + +/// MessagePayload that can be delivered to message lane pallet on Millau. +#[derive(StructOpt, Debug)] +pub enum MillauToRialtoMessagePayload { + /// Raw, SCALE-encoded `MessagePayload`. + Raw { + /// Hex-encoded SCALE data. + #[structopt(long)] + data: Bytes, + }, + /// Construct message to send over the bridge. + Message { + /// Message details. + #[structopt(flatten)] + message: ToRialtoMessage, + /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) + #[structopt(long)] + sender: bp_rialto::AccountId, + }, +} + +/// MessagePayload that can be delivered to message lane pallet on Rialto. +#[derive(StructOpt, Debug)] +pub enum RialtoToMillauMessagePayload { + /// Raw, SCALE-encoded `MessagePayload`. + Raw { + /// Hex-encoded SCALE data. + #[structopt(long)] + data: Bytes, + }, + /// Construct message to send over the bridge. + Message { + /// Message details. + #[structopt(flatten)] + message: ToMillauMessage, + + /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) + #[structopt(long)] + sender: bp_rialto::AccountId, + }, +} + /// All possible messages that may be delivered to the Rialto chain. #[derive(StructOpt, Debug)] pub enum ToRialtoMessage { + /// Raw bytes for the message + Raw { + /// Raw, SCALE-encoded message + data: Bytes, + }, /// Make an on-chain remark (comment). Remark { /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. @@ -206,8 +325,10 @@ pub enum ToRialtoMessage { }, /// Transfer the specified `amount` of native tokens to a particular `recipient`. Transfer { + /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) #[structopt(long)] recipient: bp_rialto::AccountId, + /// Amount of target tokens to send. #[structopt(long)] amount: bp_rialto::Balance, }, @@ -216,6 +337,11 @@ pub enum ToRialtoMessage { /// All possible messages that may be delivered to the Millau chain. #[derive(StructOpt, Debug)] pub enum ToMillauMessage { + /// Raw bytes for the message + Raw { + /// Raw, SCALE-encoded message + data: Bytes, + }, /// Make an on-chain remark (comment). Remark { /// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark. @@ -224,8 +350,10 @@ pub enum ToMillauMessage { }, /// Transfer the specified `amount` of native tokens to a particular `recipient`. Transfer { + /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) #[structopt(long)] recipient: bp_millau::AccountId, + /// Amount of target tokens to send. #[structopt(long)] amount: bp_millau::Balance, }, diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index c73533cdfca8a..ed17e309670c3 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -28,6 +28,7 @@ use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; use relay_utils::initialize::initialize_relay; use sp_core::{Bytes, Pair}; use sp_runtime::traits::IdentifyAccount; +use std::fmt::Debug; /// Kusama node client. pub type KusamaClient = relay_substrate_client::Client; @@ -64,6 +65,9 @@ async fn run_command(command: cli::Command) -> Result<(), String> { cli::Command::RelayHeaders(arg) => run_relay_headers(arg).await, cli::Command::RelayMessages(arg) => run_relay_messages(arg).await, cli::Command::SendMessage(arg) => run_send_message(arg).await, + cli::Command::EncodeCall(arg) => run_encode_call(arg).await, + cli::Command::EncodeMessagePayload(arg) => run_encode_message_payload(arg).await, + cli::Command::EstimateFee(arg) => run_estimate_fee(arg).await, } } @@ -240,7 +244,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { let millau_client = millau.into_client().await?; let millau_sign = millau_sign.parse()?; let rialto_sign = rialto_sign.parse()?; - let rialto_call = message.into_call(); + let rialto_call = message.into_call()?; let payload = millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin, dispatch_weight); @@ -295,7 +299,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { let rialto_client = rialto.into_client().await?; let rialto_sign = rialto_sign.parse()?; let millau_sign = millau_sign.parse()?; - let millau_call = message.into_call(); + let millau_call = message.into_call()?; let payload = rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin, dispatch_weight); @@ -340,6 +344,74 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { Ok(()) } +async fn run_encode_call(call: cli::EncodeCall) -> Result<(), String> { + match call { + cli::EncodeCall::Rialto { call } => { + let call = call.into_call()?; + + println!("{:?}", HexBytes::encode(&call)); + } + cli::EncodeCall::Millau { call } => { + let call = call.into_call()?; + println!("{:?}", HexBytes::encode(&call)); + } + } + Ok(()) +} + +async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<(), String> { + match call { + cli::EncodeMessagePayload::RialtoToMillau { payload } => { + let payload = payload.into_payload()?; + + println!("{:?}", HexBytes::encode(&payload)); + } + cli::EncodeMessagePayload::MillauToRialto { payload } => { + let payload = payload.into_payload()?; + + println!("{:?}", HexBytes::encode(&payload)); + } + } + Ok(()) +} + +async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { + match cmd { + cli::EstimateFee::RialtoToMillau { rialto, lane, payload } => { + let client = rialto.into_client().await?; + let lane = lane.into(); + let payload = payload.into_payload()?; + + let fee: Option = estimate_message_delivery_and_dispatch_fee( + &client, + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; + + println!("Fee: {:?}", fee); + } + cli::EstimateFee::MillauToRialto { millau, lane, payload } => { + let client = millau.into_client().await?; + let lane = lane.into(); + let payload = payload.into_payload()?; + + let fee: Option = estimate_message_delivery_and_dispatch_fee( + &client, + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; + + println!("Fee: {:?}", fee); + } + } + + Ok(()) +} + async fn estimate_message_delivery_and_dispatch_fee( client: &relay_substrate_client::Client, estimate_fee_method: &str, @@ -370,6 +442,43 @@ fn remark_payload(remark_size: Option>, maximal_al } } +fn message_payload( + spec_version: u32, + weight: Weight, + origin: CallOrigin, + call: &impl Encode, +) -> MessagePayload> +where + SAccountId: Encode + Debug, + TPublic: Encode + Debug, + TSignature: Encode + Debug, +{ + // Display nicely formatted call. + let payload = MessagePayload { + spec_version, + weight, + origin, + call: HexBytes::encode(call), + }; + + log::info!(target: "bridge", "Created Message Payload: {:#?}", payload); + log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); + + // re-pack to return `Vec` + let MessagePayload { + spec_version, + weight, + origin, + call, + } = payload; + MessagePayload { + spec_version, + weight, + origin, + call: call.0, + } +} + fn rialto_to_millau_message_payload( rialto_sign: &RialtoSigningParams, millau_sign: &MillauSigningParams, @@ -386,10 +495,10 @@ fn rialto_to_millau_message_payload( let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); let millau_origin_public = millau_sign.signer.public(); - MessagePayload { - spec_version: millau_runtime::VERSION.spec_version, - weight: millau_call_weight, - origin: match origin { + message_payload( + millau_runtime::VERSION.spec_version, + millau_call_weight, + match origin { cli::Origins::Source => CallOrigin::SourceAccount(rialto_account_id), cli::Origins::Target => { let digest = rialto_runtime::millau_account_ownership_digest( @@ -403,8 +512,8 @@ fn rialto_to_millau_message_payload( CallOrigin::TargetAccount(rialto_account_id, millau_origin_public.into(), digest_signature.into()) } }, - call: millau_call.encode(), - } + &millau_call, + ) } fn millau_to_rialto_message_payload( @@ -423,10 +532,10 @@ fn millau_to_rialto_message_payload( let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); let rialto_origin_public = rialto_sign.signer.public(); - MessagePayload { - spec_version: rialto_runtime::VERSION.spec_version, - weight: rialto_call_weight, - origin: match origin { + message_payload( + rialto_runtime::VERSION.spec_version, + rialto_call_weight, + match origin { cli::Origins::Source => CallOrigin::SourceAccount(millau_account_id), cli::Origins::Target => { let digest = millau_runtime::rialto_account_ownership_digest( @@ -440,8 +549,8 @@ fn millau_to_rialto_message_payload( CallOrigin::TargetAccount(millau_account_id, rialto_origin_public.into(), digest_signature.into()) } }, - call: rialto_call.encode(), - } + &rialto_call, + ) } fn prepare_call_dispatch_weight( @@ -460,7 +569,7 @@ where Fee: Decode, F: FnOnce() -> R, R: std::future::Future, E>>, - E: std::fmt::Debug, + E: Debug, { match fee { Some(fee) => Ok(fee), @@ -496,6 +605,46 @@ fn compute_maximal_message_arguments_size( maximal_call_size - service_bytes } +impl crate::cli::MillauToRialtoMessagePayload { + /// Parse the CLI parameters and construct message payload. + pub fn into_payload( + self, + ) -> Result>, String> { + match self { + Self::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), + Self::Message { message, sender } => { + let spec_version = rialto_runtime::VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender); + let call = message.into_call()?; + let weight = call.get_dispatch_info().weight; + + Ok(message_payload(spec_version, weight, origin, &call)) + } + } + } +} + +impl crate::cli::RialtoToMillauMessagePayload { + /// Parse the CLI parameters and construct message payload. + pub fn into_payload( + self, + ) -> Result>, String> { + match self { + Self::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), + Self::Message { message, sender } => { + let spec_version = millau_runtime::VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender); + let call = message.into_call()?; + let weight = call.get_dispatch_info().weight; + + Ok(message_payload(spec_version, weight, origin, &call)) + } + } + } +} + impl crate::cli::RialtoSigningParams { /// Parse CLI parameters into typed signing params. pub fn parse(self) -> Result { @@ -535,8 +684,11 @@ impl crate::cli::RialtoConnectionParams { impl crate::cli::ToRialtoMessage { /// Convert CLI call request into runtime `Call` instance. - pub fn into_call(self) -> rialto_runtime::Call { - match self { + pub fn into_call(self) -> Result { + let call = match self { + cli::ToRialtoMessage::Raw { data } => { + Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? + } cli::ToRialtoMessage::Remark { remark_size } => { rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload( remark_size, @@ -549,14 +701,23 @@ impl crate::cli::ToRialtoMessage { cli::ToRialtoMessage::Transfer { recipient, amount } => { rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) } - } + }; + + log::info!(target: "bridge", "Generated Rialto call: {:#?}", call); + log::info!(target: "bridge", "Weight of Rialto call: {}", call.get_dispatch_info().weight); + log::info!(target: "bridge", "Encoded Rialto call: {:?}", HexBytes::encode(&call)); + + Ok(call) } } impl crate::cli::ToMillauMessage { /// Convert CLI call request into runtime `Call` instance. - pub fn into_call(self) -> millau_runtime::Call { - match self { + pub fn into_call(self) -> Result { + let call = match self { + cli::ToMillauMessage::Raw { data } => { + Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? + } cli::ToMillauMessage::Remark { remark_size } => { millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( remark_size, @@ -569,7 +730,30 @@ impl crate::cli::ToMillauMessage { cli::ToMillauMessage::Transfer { recipient, amount } => { millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) } - } + }; + + log::info!(target: "bridge", "Generated Millau call: {:#?}", call); + log::info!(target: "bridge", "Weight of Millau call: {}", call.get_dispatch_info().weight); + log::info!(target: "bridge", "Encoded Millau call: {:?}", HexBytes::encode(&call)); + + Ok(call) + } +} + +/// Nicer formatting for raw bytes vectors. +#[derive(Encode, Decode)] +struct HexBytes(Vec); + +impl Debug for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "0x{}", hex::encode(&self.0)) + } +} + +impl HexBytes { + /// Encode given object and wrap into nicely formatted bytes. + pub fn encode(t: &T) -> Self { + Self(t.encode()) } } @@ -630,22 +814,22 @@ mod tests { compute_maximal_message_arguments_size(bp_rialto::max_extrinsic_size(), bp_millau::max_extrinsic_size()); let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); - let payload = pallet_bridge_call_dispatch::MessagePayload { - spec_version: Default::default(), - weight: call.get_dispatch_info().weight, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: call.encode(), - }; + let payload = message_payload( + Default::default(), + call.get_dispatch_info().weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); assert_eq!(Millau::verify_message(&payload), Ok(())); let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into(); - let payload = pallet_bridge_call_dispatch::MessagePayload { - spec_version: Default::default(), - weight: call.get_dispatch_info().weight, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: call.encode(), - }; + let payload = message_payload( + Default::default(), + call.get_dispatch_info().weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); assert!(Millau::verify_message(&payload).is_err()); } @@ -666,20 +850,20 @@ mod tests { let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); - let payload = pallet_bridge_call_dispatch::MessagePayload { - spec_version: Default::default(), - weight: maximal_dispatch_weight, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: call.encode(), - }; + let payload = message_payload( + Default::default(), + maximal_dispatch_weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); assert_eq!(Millau::verify_message(&payload), Ok(())); - let payload = pallet_bridge_call_dispatch::MessagePayload { - spec_version: Default::default(), - weight: maximal_dispatch_weight + 1, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: call.encode(), - }; + let payload = message_payload( + Default::default(), + maximal_dispatch_weight + 1, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); assert!(Millau::verify_message(&payload).is_err()); } @@ -690,20 +874,20 @@ mod tests { let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); - let payload = pallet_bridge_call_dispatch::MessagePayload { - spec_version: Default::default(), - weight: maximal_dispatch_weight, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: call.encode(), - }; + let payload = message_payload( + Default::default(), + maximal_dispatch_weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); assert_eq!(Rialto::verify_message(&payload), Ok(())); - let payload = pallet_bridge_call_dispatch::MessagePayload { - spec_version: Default::default(), - weight: maximal_dispatch_weight + 1, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - call: call.encode(), - }; + let payload = message_payload( + Default::default(), + maximal_dispatch_weight + 1, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); assert!(Rialto::verify_message(&payload).is_err()); } } From 780bee1d3552f6d0ee707303572ab4e993532594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 2 Mar 2021 01:26:03 +0100 Subject: [PATCH 0358/1210] Derive bridged accounts (#781) * Add derivation support. * Add custom decoder for Accounts. * cargo fmt --all * Fix warn. * Fix articles. Co-authored-by: Hernando Castano --- relays/substrate/src/cli.rs | 70 +++++++++++++++++++++++++++++++++--- relays/substrate/src/main.rs | 32 +++++++++++++++-- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 090ff3f92a9f7..9914cd2e3a5db 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -20,6 +20,7 @@ use bp_message_lane::LaneId; use frame_support::weights::Weight; use sp_core::Bytes; use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId; +use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; /// Parse relay CLI args. @@ -63,6 +64,8 @@ pub enum Command { EncodeMessagePayload(EncodeMessagePayload), /// Estimate Delivery and Dispatch Fee required for message submission to message lane. EstimateFee(EstimateFee), + /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. + DeriveAccount(DeriveAccount), } /// Start headers relayer process. @@ -268,6 +271,20 @@ pub enum EstimateFee { }, } +/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. +/// +/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call +/// that has been sent over the bridge. +/// This account can also be used to receive target-chain funds (or other form of ownership), +/// since messages sent over the bridge will be able to spend these. +#[derive(StructOpt)] +pub enum DeriveAccount { + /// Given Rialto AccountId, display corresponding Millau AccountId. + RialtoToMillau { account: AccountId }, + /// Given Millau AccountId, display corresponding Rialto AccountId. + MillauToRialto { account: AccountId }, +} + /// MessagePayload that can be delivered to message lane pallet on Millau. #[derive(StructOpt, Debug)] pub enum MillauToRialtoMessagePayload { @@ -284,7 +301,7 @@ pub enum MillauToRialtoMessagePayload { message: ToRialtoMessage, /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) #[structopt(long)] - sender: bp_rialto::AccountId, + sender: AccountId, }, } @@ -305,7 +322,7 @@ pub enum RialtoToMillauMessagePayload { /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) #[structopt(long)] - sender: bp_rialto::AccountId, + sender: AccountId, }, } @@ -327,7 +344,7 @@ pub enum ToRialtoMessage { Transfer { /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) #[structopt(long)] - recipient: bp_rialto::AccountId, + recipient: AccountId, /// Amount of target tokens to send. #[structopt(long)] amount: bp_rialto::Balance, @@ -352,7 +369,7 @@ pub enum ToMillauMessage { Transfer { /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) #[structopt(long)] - recipient: bp_millau::AccountId, + recipient: AccountId, /// Amount of target tokens to send. #[structopt(long)] amount: bp_millau::Balance, @@ -371,6 +388,51 @@ arg_enum! { } } +/// Generic account id with custom parser. +#[derive(Debug)] +pub struct AccountId { + account: sp_runtime::AccountId32, + version: sp_core::crypto::Ss58AddressFormat, +} + +impl std::str::FromStr for AccountId { + type Err = String; + + fn from_str(s: &str) -> Result { + let (account, version) = sp_runtime::AccountId32::from_ss58check_with_version(s) + .map_err(|err| format!("Unable to decode SS58 address: {:?}", err))?; + Ok(Self { account, version }) + } +} + +impl AccountId { + /// Perform runtime checks of SS58 version and get Rialto's AccountId. + pub fn into_rialto(self) -> bp_rialto::AccountId { + self.check_and_get("Rialto", rialto_runtime::SS58Prefix::get()) + } + + /// Perform runtime checks of SS58 version and get Millau's AccountId. + pub fn into_millau(self) -> bp_millau::AccountId { + self.check_and_get("Millau", millau_runtime::SS58Prefix::get()) + } + + /// Check SS58Prefix and return the account id. + fn check_and_get(self, net: &str, expected_prefix: u8) -> sp_runtime::AccountId32 { + let version: u16 = self.version.into(); + println!("Version: {} vs {}", version, expected_prefix); + if version != expected_prefix as u16 { + log::warn!( + target: "bridge", + "Following address: {} does not seem to match {}'s format, got: {}", + self.account, + net, + self.version, + ) + } + self.account + } +} + /// Lane id. #[derive(Debug)] pub struct HexLaneId(LaneId); diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index ed17e309670c3..f5c8c6a1e4366 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -68,6 +68,7 @@ async fn run_command(command: cli::Command) -> Result<(), String> { cli::Command::EncodeCall(arg) => run_encode_call(arg).await, cli::Command::EncodeMessagePayload(arg) => run_encode_message_payload(arg).await, cli::Command::EstimateFee(arg) => run_estimate_fee(arg).await, + cli::Command::DeriveAccount(arg) => run_derive_account(arg).await, } } @@ -412,6 +413,31 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { Ok(()) } +async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { + match cmd { + cli::DeriveAccount::RialtoToMillau { account } => { + let account = account.into_rialto(); + let acc = bp_runtime::SourceAccount::Account(account.clone()); + let id = bp_millau::derive_account_from_rialto_id(acc); + println!( + "{} (Rialto)\n\nCorresponding (derived) account id:\n-> {} (Millau)", + account, id + ) + } + cli::DeriveAccount::MillauToRialto { account } => { + let account = account.into_millau(); + let acc = bp_runtime::SourceAccount::Account(account.clone()); + let id = bp_rialto::derive_account_from_millau_id(acc); + println!( + "{} (Millau)\n\nCorresponding (derived) account id:\n-> {} (Rialto)", + account, id + ) + } + } + + Ok(()) +} + async fn estimate_message_delivery_and_dispatch_fee( client: &relay_substrate_client::Client, estimate_fee_method: &str, @@ -615,7 +641,7 @@ impl crate::cli::MillauToRialtoMessagePayload { .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), Self::Message { message, sender } => { let spec_version = rialto_runtime::VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender); + let origin = CallOrigin::SourceAccount(sender.into_millau()); let call = message.into_call()?; let weight = call.get_dispatch_info().weight; @@ -635,7 +661,7 @@ impl crate::cli::RialtoToMillauMessagePayload { .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), Self::Message { message, sender } => { let spec_version = millau_runtime::VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender); + let origin = CallOrigin::SourceAccount(sender.into_rialto()); let call = message.into_call()?; let weight = call.get_dispatch_info().weight; @@ -699,6 +725,7 @@ impl crate::cli::ToRialtoMessage { ))) } cli::ToRialtoMessage::Transfer { recipient, amount } => { + let recipient = recipient.into_rialto(); rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) } }; @@ -728,6 +755,7 @@ impl crate::cli::ToMillauMessage { ))) } cli::ToMillauMessage::Transfer { recipient, amount } => { + let recipient = recipient.into_millau(); millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) } }; From 5e563bb7866b5313e31ac0cd0b44ec280906b43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 2 Mar 2021 16:20:47 +0100 Subject: [PATCH 0359/1210] Add Bridge calls encoding to relay CLI (#780) * Bridge calls. * Allow encoding messages for both Rialto and Millua. * Add docs. * Display full extrinsics in debug. * cargo fmt --all * Use info instead of debug,. * Clarify units. --- relays/substrate/src/cli.rs | 35 ++++++++++++++++++++++++++++------- relays/substrate/src/main.rs | 16 ++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index 9914cd2e3a5db..d9bec5774740e 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -176,7 +176,7 @@ pub enum SendMessage { /// Dispatch weight of the message. If not passed, determined automatically. #[structopt(long)] dispatch_weight: Option>, - /// Delivery and dispatch fee. If not passed, determined automatically. + /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. #[structopt(long)] fee: Option, /// Message type. @@ -201,7 +201,7 @@ pub enum SendMessage { /// Dispatch weight of the message. If not passed, determined automatically. #[structopt(long)] dispatch_weight: Option>, - /// Delivery and dispatch fee. If not passed, determined automatically. + /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. #[structopt(long)] fee: Option, /// Message type. @@ -291,7 +291,6 @@ pub enum MillauToRialtoMessagePayload { /// Raw, SCALE-encoded `MessagePayload`. Raw { /// Hex-encoded SCALE data. - #[structopt(long)] data: Bytes, }, /// Construct message to send over the bridge. @@ -311,7 +310,6 @@ pub enum RialtoToMillauMessagePayload { /// Raw, SCALE-encoded `MessagePayload`. Raw { /// Hex-encoded SCALE data. - #[structopt(long)] data: Bytes, }, /// Construct message to send over the bridge. @@ -319,7 +317,6 @@ pub enum RialtoToMillauMessagePayload { /// Message details. #[structopt(flatten)] message: ToMillauMessage, - /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) #[structopt(long)] sender: AccountId, @@ -345,10 +342,22 @@ pub enum ToRialtoMessage { /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) #[structopt(long)] recipient: AccountId, - /// Amount of target tokens to send. + /// Amount of target tokens to send in target chain base currency units. #[structopt(long)] amount: bp_rialto::Balance, }, + /// A call to the Millau Bridge Message Lane pallet to send a message over the bridge. + MillauSendMessage { + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. + #[structopt(long)] + payload: Bytes, + /// Declared delivery and dispatch fee in base source-chain currency units. + #[structopt(long)] + fee: bp_rialto::Balance, + }, } /// All possible messages that may be delivered to the Millau chain. @@ -370,10 +379,22 @@ pub enum ToMillauMessage { /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) #[structopt(long)] recipient: AccountId, - /// Amount of target tokens to send. + /// Amount of target tokens to send in target chain base currency units. #[structopt(long)] amount: bp_millau::Balance, }, + /// A call to the Rialto Bridge Message Lane pallet to send a message over the bridge. + RialtoSendMessage { + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. + #[structopt(long)] + payload: Bytes, + /// Declared delivery and dispatch fee in base source-chain currency units. + #[structopt(long)] + fee: bp_millau::Balance, + }, } arg_enum! { diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index f5c8c6a1e4366..3a3c3620aeb25 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -283,6 +283,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { dispatch_weight, fee, ); + log::info!(target: "bridge", "Signed Millau Call: {:?}", HexBytes::encode(&signed_millau_call)); millau_client.submit_extrinsic(Bytes(signed_millau_call)).await?; } @@ -338,6 +339,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { dispatch_weight, fee, ); + log::info!(target: "bridge", "Signed Rialto Call: {:?}", HexBytes::encode(&signed_rialto_call)); rialto_client.submit_extrinsic(Bytes(signed_rialto_call)).await?; } @@ -728,6 +730,13 @@ impl crate::cli::ToRialtoMessage { let recipient = recipient.into_rialto(); rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) } + cli::ToRialtoMessage::MillauSendMessage { lane, payload, fee } => { + let payload = cli::RialtoToMillauMessagePayload::Raw { data: payload }.into_payload()?; + let lane = lane.into(); + rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( + lane, payload, fee, + )) + } }; log::info!(target: "bridge", "Generated Rialto call: {:#?}", call); @@ -758,6 +767,13 @@ impl crate::cli::ToMillauMessage { let recipient = recipient.into_millau(); millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) } + cli::ToMillauMessage::RialtoSendMessage { lane, payload, fee } => { + let payload = cli::MillauToRialtoMessagePayload::Raw { data: payload }.into_payload()?; + let lane = lane.into(); + millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( + lane, payload, fee, + )) + } }; log::info!(target: "bridge", "Generated Millau call: {:#?}", call); From 7041a169dafe8f0e469ffe25806de52dccbd93e7 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 3 Mar 2021 16:42:35 -0500 Subject: [PATCH 0360/1210] Update Substrate Node build script (#786) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomasz Drwięga --- bin/millau/node/Cargo.toml | 3 +-- bin/millau/node/build.rs | 8 +++----- bin/rialto/node/Cargo.toml | 3 +-- bin/rialto/node/build.rs | 8 +++----- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3432701e0d337..e035bbd224250 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -48,9 +48,8 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "ma substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [build-dependencies] -build-script-utils = { package = "substrate-build-script-utils", version = "2.0" } +substrate-build-script-utils = "3.0.0" frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -vergen = "3.1.0" [features] default = [] diff --git a/bin/millau/node/build.rs b/bin/millau/node/build.rs index e9a10ff8ad009..b0d117f37c927 100644 --- a/bin/millau/node/build.rs +++ b/bin/millau/node/build.rs @@ -14,12 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use vergen::{generate_cargo_keys, ConstantsFlags}; - -const ERROR_MSG: &str = "Failed to generate metadata files"; +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; fn main() { - generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); + generate_cargo_keys(); - build_script_utils::rerun_if_git_head_changed(); + rerun_if_git_head_changed(); } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index da602d35861f9..9d3e3fc16c2ab 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -49,9 +49,8 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "ma substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } [build-dependencies] -build-script-utils = { package = "substrate-build-script-utils", version = "2.0" } +substrate-build-script-utils = "3.0.0" frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -vergen = "3.1.0" [features] default = [] diff --git a/bin/rialto/node/build.rs b/bin/rialto/node/build.rs index e9a10ff8ad009..b0d117f37c927 100644 --- a/bin/rialto/node/build.rs +++ b/bin/rialto/node/build.rs @@ -14,12 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use vergen::{generate_cargo_keys, ConstantsFlags}; - -const ERROR_MSG: &str = "Failed to generate metadata files"; +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; fn main() { - generate_cargo_keys(ConstantsFlags::SHA_SHORT).expect(ERROR_MSG); + generate_cargo_keys(); - build_script_utils::rerun_if_git_head_changed(); + rerun_if_git_head_changed(); } From f4c6614ff68460578105e962deee926afd3282e4 Mon Sep 17 00:00:00 2001 From: Bobin Mathew Date: Thu, 4 Mar 2021 22:06:14 +0530 Subject: [PATCH 0361/1210] Create CODE_OF_CONDUCT.md (#791) --- CODE_OF_CONDUCT.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000..70541fb72fa25 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,80 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers +pledge to making participation in our project and our community a harassment-free experience for +everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity +and expression, level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit + permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +### Facilitation, Not Strongarming + +We recognise that this software is merely a tool for users to create and maintain their blockchain +of preference. We see that blockchains are naturally community platforms with users being the +ultimate decision makers. We assert that good software will maximise user agency by facilitate +user-expression on the network. As such: + +- This project will strive to give users as much choice as is both reasonable and possible over what + protocol they adhere to; but +- use of the project's technical forums, commenting systems, pull requests and issue trackers as a + means to express individual protocol preferences is forbidden. + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are +expected to take appropriate and fair corrective action in response to any instances of unacceptable +behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, +code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or +to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is +representing the project or its community. Examples of representing a project or community include +using an official project e-mail address, posting via an official social media account, or acting as +an appointed representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting +the project team at admin@parity.io. All complaints will be reviewed and investigated and will +result in a response that is deemed necessary and appropriate to the circumstances. The project team +is obligated to maintain confidentiality with regard to the reporter of an incident. Further +details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face +temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq From 591a7cde5f82c8f9e6947b14f5cd998ed08ee3e3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 4 Mar 2021 14:50:30 -0500 Subject: [PATCH 0362/1210] Unify Substrate Bridge Pallet with Finality Verifier (#783) * Add relevant storage items from Substrate pallet * Add function for importing finalized headers to storage * Remove unused getter functions * Add GenesisConfig to pallet * Add initialization extrinsic * Add operational extrinsic * Get existing finality verifier tests compiling again * Add tests for pallet initialization * Add tests related to pallet's operational status * Update tests which were using `pallet-substrate-bridge` * Add tests related to header imports * Use wrapper function when init-ing some tests * Add prefix to tests related to rate limiter * Fix failed compilation related to GenesisConfig * Add some documentation * Change some extrinsics to be Operational * Add public interface to pallet * Implement runtime APIs for finality-verifier pallet * Justify use of `expect` when importing headers * Reject headers with forced changes * Add weight to initialize extrinsic * Remove TODO which will be addressed later * Move succesful import log to correct location * Expand proof for when `best_finalized` is fetched * Move check for newer finalized blocks earlier in pipeline * Rename `ConflictingFork` error to be more generic * Only compute finality_target's hash once * Add missing documentation to Runtime APIs * Add TODO about using `set_id` from `ScheduledChange` digest --- bin/millau/runtime/src/lib.rs | 11 + bin/rialto/runtime/src/lib.rs | 11 + modules/finality-verifier/Cargo.toml | 2 + modules/finality-verifier/src/lib.rs | 605 ++++++++++++++++++++++++-- modules/finality-verifier/src/mock.rs | 8 +- primitives/millau/src/lib.rs | 18 +- primitives/rialto/src/lib.rs | 18 +- 7 files changed, 630 insertions(+), 43 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 89440184002ff..090257419d549 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -559,6 +559,17 @@ impl_runtime_apis! { } } + impl bp_rialto::RialtoFinalityApi for Runtime { + fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { + let header = BridgeFinalityVerifier::best_finalized(); + (header.number, header.hash()) + } + + fn is_known_header(hash: bp_rialto::Hash) -> bool { + BridgeFinalityVerifier::is_known_header(hash) + } + } + impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_message_lane::LaneId, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6bb73ef037aa0..eed087bdf82cf 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -642,6 +642,17 @@ impl_runtime_apis! { } } + impl bp_millau::MillauFinalityApi for Runtime { + fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { + let header = BridgeFinalityVerifier::best_finalized(); + (header.number, header.hash()) + } + + fn is_known_header(hash: bp_millau::Hash) -> bool { + BridgeFinalityVerifier::is_known_header(hash) + } + } + impl bp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index 8afc30cd30ed0..79279f038bd26 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -21,6 +21,7 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -40,6 +41,7 @@ std = [ "frame-support/std", "frame-system/std", "serde", + "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", ] diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 3db6cb7bf7cd6..8d0aa7b8cacd5 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -33,11 +33,16 @@ #![allow(clippy::large_enum_variant)] use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain}; -use bp_runtime::{Chain, HeaderOf}; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; +use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::{dispatch::DispatchError, ensure}; -use frame_system::ensure_signed; -use sp_runtime::traits::Header as HeaderT; +use frame_system::{ensure_signed, RawOrigin}; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; +use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; +use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; #[cfg(test)] @@ -46,15 +51,21 @@ mod mock; // Re-export in crate namespace for `construct_runtime!` pub use pallet::*; +/// Block number of the bridged chain. +pub type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; +/// Block hash of the bridged chain. +pub type BridgedBlockHash = HashOf<::BridgedChain>; +/// Hasher of the bridged chain. +pub type _BridgedBlockHasher = HasherOf<::BridgedChain>; +/// Header of the bridged chain. +pub type BridgedHeader = HeaderOf<::BridgedChain>; + #[frame_support::pallet] pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// Header of the bridged chain. - pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; - #[pallet::config] pub trait Config: frame_system::Config { /// The chain we are bridging to here. @@ -113,6 +124,7 @@ pub mod pallet { justification: Vec, ancestry_proof: T::AncestryProof, ) -> DispatchResultWithPostInfo { + ensure_operational::()?; let _ = ensure_signed(origin)?; ensure!( @@ -120,14 +132,24 @@ pub mod pallet { >::TooManyRequests ); + let (hash, number) = (finality_target.hash(), finality_target.number()); frame_support::debug::trace!("Going to try and finalize header {:?}", finality_target); - let authority_set = T::HeaderChain::authority_set(); + let best_finalized = >::get(>::get()).expect( + "In order to reach this point the bridge must have been initialized. Afterwards, + every time `BestFinalized` is updated `ImportedHeaders` is also updated. Therefore + `ImportedHeaders` must contain an entry for `BestFinalized`.", + ); + + // We do a quick check here to ensure that our header chain is making progress and isn't + // "travelling back in time" (which could be indicative of something bad, e.g a hard-fork). + ensure!(best_finalized.number() < number, >::OldHeader); + + let authority_set = >::get(); let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; let set_id = authority_set.set_id; - let (hash, number) = (finality_target.hash(), *finality_target.number()); - verify_justification::>((hash, number), set_id, voter_set, &justification).map_err( + verify_justification::>((hash, *number), set_id, voter_set, &justification).map_err( |e| { frame_support::debug::error!("Received invalid justification for {:?}: {:?}", finality_target, e); >::InvalidJustification @@ -142,11 +164,85 @@ pub mod pallet { >::InvalidAncestryProof ); - let _ = T::HeaderChain::append_header(finality_target)?; - frame_support::debug::info!("Succesfully imported finalized header with hash {:?}!", hash); + let _ = T::HeaderChain::append_header(finality_target.clone())?; + import_header::(hash, finality_target)?; >::mutate(|count| *count += 1); + frame_support::debug::info!("Succesfully imported finalized header with hash {:?}!", hash); + + Ok(().into()) + } + + /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. + /// + /// The initial configuration provided does not need to be the genesis header of the bridged + /// chain, it can be any arbirary header. You can also provide the next scheduled set change + /// if it is already know. + /// + /// This function is only allowed to be called from a trusted origin and writes to storage + /// with practically no checks in terms of the validity of the data. It is important that + /// you ensure that valid data is being passed in. + #[pallet::weight((T::DbWeight::get().reads_writes(2, 5), DispatchClass::Operational))] + pub fn initialize( + origin: OriginFor, + init_data: super::InitializationData>, + ) -> DispatchResultWithPostInfo { + ensure_owner_or_root::(origin)?; + + let init_allowed = !>::exists(); + ensure!(init_allowed, >::AlreadyInitialized); + initialize_bridge::(init_data.clone()); + + frame_support::debug::info!( + "Pallet has been initialized with the following parameters: {:?}", + init_data + ); + + Ok(().into()) + } + + /// Change `ModuleOwner`. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResultWithPostInfo { + ensure_owner_or_root::(origin)?; + match new_owner { + Some(new_owner) => { + ModuleOwner::::put(&new_owner); + frame_support::debug::info!("Setting pallet Owner to: {:?}", new_owner); + } + None => { + ModuleOwner::::kill(); + frame_support::debug::info!("Removed Owner of pallet."); + } + } + + Ok(().into()) + } + + /// Halt all pallet operations. Operations may be resumed using `resume_operations` call. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn halt_operations(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure_owner_or_root::(origin)?; + >::put(true); + frame_support::debug::warn!("Stopping pallet operations."); + + Ok(().into()) + } + + /// Resume all pallet operations. May be called even if pallet is halted. + /// + /// May only be called either by root, or by `ModuleOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn resume_operations(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure_owner_or_root::(origin)?; + >::put(false); + frame_support::debug::info!("Resuming pallet operations."); + Ok(().into()) } } @@ -162,6 +258,68 @@ pub mod pallet { #[pallet::getter(fn request_count)] pub(super) type RequestCount = StorageValue<_, u32, ValueQuery>; + /// Hash of the header used to bootstrap the pallet. + #[pallet::storage] + pub(super) type InitialHash = StorageValue<_, BridgedBlockHash, ValueQuery>; + + /// Hash of the best finalized header. + #[pallet::storage] + pub(super) type BestFinalized = StorageValue<_, BridgedBlockHash, ValueQuery>; + + /// Headers which have been imported into the pallet. + #[pallet::storage] + pub(super) type ImportedHeaders = StorageMap<_, Identity, BridgedBlockHash, BridgedHeader>; + + /// The current GRANDPA Authority set. + #[pallet::storage] + pub(super) type CurrentAuthoritySet = StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>; + + /// Optional pallet owner. + /// + /// Pallet owner has a right to halt all pallet operations and then resume it. If it is + /// `None`, then there are no direct ways to halt/resume pallet operations, but other + /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt + /// flag directly or call the `halt_operations`). + #[pallet::storage] + pub(super) type ModuleOwner = StorageValue<_, T::AccountId, OptionQuery>; + + /// If true, all pallet transactions are failed immediately. + #[pallet::storage] + pub(super) type IsHalted = StorageValue<_, bool, ValueQuery>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + owner: Option, + init_data: Option>>, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + owner: None, + init_data: None, + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + if let Some(ref owner) = self.owner { + >::put(owner); + } + + if let Some(init_data) = self.init_data.clone() { + initialize_bridge::(init_data); + } else { + // Since the bridge hasn't been initialized we shouldn't allow anyone to perform + // transactions. + >::put(true); + } + } + } + #[pallet::error] pub enum Error { /// The given justification is invalid for the given header. @@ -175,32 +333,199 @@ pub mod pallet { FailedToWriteHeader, /// There are too many requests for the current window to handle. TooManyRequests, + /// The header being imported is older than the best finalized header known to the pallet. + OldHeader, + /// The scheduled authority set change found in the header is unsupported by the pallet. + /// + /// This is the case for non-standard (e.g forced) authority set changes. + UnsupportedScheduledChange, + /// The pallet has already been initialized. + AlreadyInitialized, + /// All pallet operations are halted. + Halted, + } + + /// Import the given header to the pallet's storage. + /// + /// This function will also check if the header schedules and enacts authority set changes, + /// updating the current authority set accordingly. + /// + /// Note: This function assumes that the given header has already been proven to be valid and + /// finalized. Using this assumption it will write them to storage with minimal checks. That + /// means it's of great importance that this function *not* called with any headers whose + /// finality has not been checked, otherwise you risk bricking your bridge. + pub(crate) fn import_header( + hash: BridgedBlockHash, + header: BridgedHeader, + ) -> Result<(), sp_runtime::DispatchError> { + // We don't support forced changes - at that point governance intervention is required. + ensure!( + super::find_forced_change(&header).is_none(), + >::UnsupportedScheduledChange + ); + + if let Some(change) = super::find_scheduled_change(&header) { + // GRANDPA only includes a `delay` for forced changes, so this isn't valid. + ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); + + // TODO [#788]: Stop manually increasing the `set_id` here. + let next_authorities = bp_header_chain::AuthoritySet { + authorities: change.next_authorities, + set_id: >::get().set_id + 1, + }; + + // Since our header schedules a change and we know the delay is 0, it must also enact + // the change. + >::put(next_authorities); + }; + + >::put(hash); + >::insert(hash, header); + + Ok(()) + } + + /// Since this writes to storage with no real checks this should only be used in functions that + /// were called by a trusted origin. + fn initialize_bridge(init_params: super::InitializationData>) { + let super::InitializationData { + header, + authority_list, + set_id, + is_halted, + } = init_params; + + let initial_hash = header.hash(); + >::put(initial_hash); + >::put(initial_hash); + >::insert(initial_hash, header); + + let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); + >::put(authority_set); + + >::put(is_halted); + } + + /// Ensure that the origin is either root, or `ModuleOwner`. + fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { + match origin.into() { + Ok(RawOrigin::Root) => Ok(()), + Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::get().as_ref() => Ok(()), + _ => Err(BadOrigin), + } + } + + /// Ensure that the pallet is in operational mode (not halted). + fn ensure_operational() -> Result<(), Error> { + if >::get() { + Err(>::Halted) + } else { + Ok(()) + } } } +impl Pallet { + /// Get the best finalized header the pallet knows of. + /// + /// Returns a dummy header if there is no best header. This can only happen + /// if the pallet has not been initialized yet. + pub fn best_finalized() -> BridgedHeader { + let hash = >::get(); + >::get(hash).unwrap_or_else(|| { + >::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ) + }) + } + + /// Check if a particular header is known to the bridge pallet. + pub fn is_known_header(hash: BridgedBlockHash) -> bool { + >::contains_key(hash) + } +} + +/// Data required for initializing the bridge pallet. +/// +/// The bridge needs to know where to start its sync from, and this provides that initial context. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct InitializationData { + /// The header from which we should start syncing. + pub header: H, + /// The initial authorities of the pallet. + pub authority_list: sp_finality_grandpa::AuthorityList, + /// The ID of the initial authority set. + pub set_id: sp_finality_grandpa::SetId, + /// Should the pallet block transaction immediately after initialization. + pub is_halted: bool, +} + +pub(crate) fn find_scheduled_change(header: &H) -> Option> { + use sp_runtime::generic::OpaqueDigestItemId; + + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + + let filter_log = |log: ConsensusLog| match log { + ConsensusLog::ScheduledChange(change) => Some(change), + _ => None, + }; + + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +} + +/// Checks the given header for a consensus digest signalling a **forced** scheduled change and +/// extracts it. +pub(crate) fn find_forced_change( + header: &H, +) -> Option<(H::Number, sp_finality_grandpa::ScheduledChange)> { + use sp_runtime::generic::OpaqueDigestItemId; + + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + + let filter_log = |log: ConsensusLog| match log { + ConsensusLog::ForcedChange(delay, change) => Some((delay, change)), + _ => None, + }; + + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +} + #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_header, Origin, TestRuntime}; - use bp_test_utils::{authority_list, make_justification_for_header}; + use crate::mock::{run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime}; + use bp_test_utils::{alice, authority_list, bob, make_justification_for_header}; use codec::Encode; - use frame_support::{assert_err, assert_ok}; + use frame_support::weights::PostDispatchInfo; + use frame_support::{assert_err, assert_noop, assert_ok}; + use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { + assert_ok!(init_with_origin(Origin::root())); + } + + fn init_with_origin( + origin: Origin, + ) -> Result, sp_runtime::DispatchErrorWithPostInfo> { let genesis = test_header(0); - let init_data = pallet_substrate_bridge::InitializationData { + let init_data = InitializationData { header: genesis, authority_list: authority_list(), set_id: 1, - scheduled_change: None, is_halted: false, }; - assert_ok!(pallet_substrate_bridge::Module::::initialize( - Origin::root(), - init_data - )); + Module::::initialize(origin, init_data.clone()).map(|_| init_data) } fn submit_finality_proof(child: u8, header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { @@ -223,6 +548,146 @@ mod tests { let _ = Module::::on_initialize(current_number); } + fn change_log(delay: u64) -> Digest { + let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + next_authorities: vec![(alice(), 1), (bob(), 1)], + delay, + }); + + Digest:: { + logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], + } + } + + fn forced_change_log(delay: u64) -> Digest { + let consensus_log = ConsensusLog::::ForcedChange( + delay, + sp_finality_grandpa::ScheduledChange { + next_authorities: vec![(alice(), 1), (bob(), 1)], + delay, + }, + ); + + Digest:: { + logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], + } + } + + #[test] + fn init_root_or_owner_origin_can_initialize_pallet() { + run_test(|| { + assert_noop!(init_with_origin(Origin::signed(1)), DispatchError::BadOrigin); + assert_ok!(init_with_origin(Origin::root())); + + // Reset storage so we can initialize the pallet again + BestFinalized::::kill(); + ModuleOwner::::put(2); + assert_ok!(init_with_origin(Origin::signed(2))); + }) + } + + #[test] + fn init_storage_entries_are_correctly_initialized() { + run_test(|| { + assert_eq!( + BestFinalized::::get(), + BridgedBlockHash::::default() + ); + assert_eq!(Module::::best_finalized(), test_header(0)); + + let init_data = init_with_origin(Origin::root()).unwrap(); + + assert!(>::contains_key(init_data.header.hash())); + assert_eq!(BestFinalized::::get(), init_data.header.hash()); + assert_eq!( + CurrentAuthoritySet::::get().authorities, + init_data.authority_list + ); + assert_eq!(IsHalted::::get(), false); + }) + } + + #[test] + fn init_can_only_initialize_pallet_once() { + run_test(|| { + initialize_substrate_bridge(); + assert_noop!( + init_with_origin(Origin::root()), + >::AlreadyInitialized + ); + }) + } + + #[test] + fn pallet_owner_may_change_owner() { + run_test(|| { + ModuleOwner::::put(2); + + assert_ok!(Module::::set_owner(Origin::root(), Some(1))); + assert_noop!( + Module::::halt_operations(Origin::signed(2)), + DispatchError::BadOrigin, + ); + assert_ok!(Module::::halt_operations(Origin::root())); + + assert_ok!(Module::::set_owner(Origin::signed(1), None)); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + assert_noop!( + Module::::resume_operations(Origin::signed(2)), + DispatchError::BadOrigin, + ); + assert_ok!(Module::::resume_operations(Origin::root())); + }); + } + + #[test] + fn pallet_may_be_halted_by_root() { + run_test(|| { + assert_ok!(Module::::halt_operations(Origin::root())); + assert_ok!(Module::::resume_operations(Origin::root())); + }); + } + + #[test] + fn pallet_may_be_halted_by_owner() { + run_test(|| { + ModuleOwner::::put(2); + + assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_ok!(Module::::resume_operations(Origin::signed(2))); + + assert_noop!( + Module::::halt_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + + assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_noop!( + Module::::resume_operations(Origin::signed(1)), + DispatchError::BadOrigin, + ); + }); + } + + #[test] + fn pallet_rejects_transactions_if_halted() { + run_test(|| { + >::put(true); + + assert_noop!( + Module::::submit_finality_proof(Origin::signed(1), test_header(1), vec![], vec![]), + Error::::Halted, + ); + }) + } + #[test] fn succesfully_imports_header_with_valid_finality_and_ancestry_proofs() { run_test(|| { @@ -231,12 +696,8 @@ mod tests { assert_ok!(submit_finality_proof(1, 2)); let header = test_header(2); - assert_eq!( - pallet_substrate_bridge::Module::::best_headers(), - vec![(*header.number(), header.hash())] - ); - - assert_eq!(pallet_substrate_bridge::Module::::best_finalized(), header); + assert_eq!(>::get(), header.hash()); + assert!(>::contains_key(header.hash())); }) } @@ -309,18 +770,14 @@ mod tests { let genesis = test_header(0); let invalid_authority_list = vec![(alice(), u64::MAX), (bob(), u64::MAX)]; - let init_data = pallet_substrate_bridge::InitializationData { + let init_data = InitializationData { header: genesis, authority_list: invalid_authority_list, set_id: 1, - scheduled_change: None, is_halted: false, }; - assert_ok!(pallet_substrate_bridge::Module::::initialize( - Origin::root(), - init_data - )); + assert_ok!(Module::::initialize(Origin::root(), init_data)); let header = test_header(1); let justification = [1u8; 32].encode(); @@ -334,7 +791,81 @@ mod tests { } #[test] - fn disallows_imports_once_limit_is_hit_in_single_block() { + fn importing_header_ensures_that_chain_is_extended() { + run_test(|| { + initialize_substrate_bridge(); + + assert_ok!(submit_finality_proof(5, 6)); + assert_err!(submit_finality_proof(3, 4), Error::::OldHeader); + assert_ok!(submit_finality_proof(7, 8)); + }) + } + + #[test] + fn importing_header_enacts_new_authority_set() { + run_test(|| { + initialize_substrate_bridge(); + + let next_set_id = 2; + let next_authorities = vec![(alice(), 1), (bob(), 1)]; + + // Need to update the header digest to indicate that our header signals an authority set + // change. The change will be enacted when we import our header. + let mut header = test_header(2); + header.digest = change_log(0); + + // Let's import our test header + assert_ok!(pallet::import_header::(header.hash(), header.clone())); + + // Make sure that our header is the best finalized + assert_eq!(>::get(), header.hash()); + assert!(>::contains_key(header.hash())); + + // Make sure that the authority set actually changed upon importing our header + assert_eq!( + >::get(), + bp_header_chain::AuthoritySet::new(next_authorities, next_set_id), + ); + }) + } + + #[test] + fn importing_header_rejects_header_with_scheduled_change_delay() { + run_test(|| { + initialize_substrate_bridge(); + + // Need to update the header digest to indicate that our header signals an authority set + // change. However, the change doesn't happen until the next block. + let mut header = test_header(2); + header.digest = change_log(1); + + // Should not be allowed to import this header + assert_err!( + pallet::import_header::(header.hash(), header), + >::UnsupportedScheduledChange + ); + }) + } + + #[test] + fn importing_header_rejects_header_with_forced_changes() { + run_test(|| { + initialize_substrate_bridge(); + + // Need to update the header digest to indicate that it signals a forced authority set + // change. + let mut header = test_header(2); + header.digest = forced_change_log(0); + + // Should not be allowed to import this header + assert_err!( + pallet::import_header::(header.hash(), header), + >::UnsupportedScheduledChange + ); + }) + } + #[test] + fn rate_limiter_disallows_imports_once_limit_is_hit_in_single_block() { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1, 2)); @@ -344,7 +875,7 @@ mod tests { } #[test] - fn invalid_requests_do_not_count_towards_request_count() { + fn rate_limiter_invalid_requests_do_not_count_towards_request_count() { run_test(|| { let submit_invalid_request = || { let child = test_header(1); @@ -376,7 +907,7 @@ mod tests { } #[test] - fn allows_request_after_new_block_has_started() { + fn rate_limiter_allows_request_after_new_block_has_started() { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1, 2)); @@ -388,7 +919,7 @@ mod tests { } #[test] - fn disallows_imports_once_limit_is_hit_across_different_blocks() { + fn rate_limiter_disallows_imports_once_limit_is_hit_across_different_blocks() { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1, 2)); @@ -401,7 +932,7 @@ mod tests { } #[test] - fn allows_max_requests_after_long_time_with_no_activity() { + fn rate_limiter_allows_max_requests_after_long_time_with_no_activity() { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1, 2)); diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index 26890d9d23a1f..dc2fc27394f85 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -17,8 +17,7 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::pallet::{BridgedHeader, Config}; -use bp_runtime::{BlockNumberOf, Chain}; +use bp_runtime::Chain; use frame_support::{construct_runtime, parameter_types, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, @@ -27,8 +26,9 @@ use sp_runtime::{ }; pub type AccountId = u64; -pub type TestHeader = BridgedHeader; -pub type TestNumber = BlockNumberOf<::BridgedChain>; +pub type TestHeader = crate::BridgedHeader; +pub type TestNumber = crate::BridgedBlockNumber; +pub type TestHash = crate::BridgedBlockHash; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 84096d116ef53..23acef4701a65 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -238,6 +238,11 @@ pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; /// Name of the `MillauHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; +/// Name of the `RialtoFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; +/// Name of the `RialtoFinalityApi::is_known_header` runtime method. +pub const IS_KNOW_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_is_known_header"; + /// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; @@ -258,7 +263,7 @@ pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneAp sp_api::decl_runtime_apis! { /// API for querying information about Millau headers from the Bridge Pallet instance. /// - /// This API is implemented by runtimes that are bridging with Millau chain, not the + /// This API is implemented by runtimes that are bridging with the Millau chain, not the /// Millau runtime itself. pub trait MillauHeaderApi { /// Returns number and hash of the best blocks known to the bridge module. @@ -281,6 +286,17 @@ sp_api::decl_runtime_apis! { fn is_finalized_block(hash: Hash) -> bool; } + /// API for querying information about the finalized Millau headers. + /// + /// This API is implemented by runtimes that are bridging with the Millau chain, not the + /// Millau runtime itself. + pub trait MillauFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + /// Outbound message lane API for messages that are sent to Millau chain. /// /// This API is implemented by runtimes that are sending messages to Millau chain, not the diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 706e2f27854d2..856dd8b7fbfed 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -199,6 +199,11 @@ pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; /// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; +/// Name of the `RialtoFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_finalized"; +/// Name of the `RialtoFinalityApi::is_known_header` runtime method. +pub const IS_KNOW_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_is_known_header"; + /// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; @@ -219,7 +224,7 @@ pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneAp sp_api::decl_runtime_apis! { /// API for querying information about Rialto headers from the Bridge Pallet instance. /// - /// This API is implemented by runtimes that are bridging with Rialto chain, not the + /// This API is implemented by runtimes that are bridging with the Rialto chain, not the /// Rialto runtime itself. pub trait RialtoHeaderApi { /// Returns number and hash of the best blocks known to the bridge module. @@ -242,6 +247,17 @@ sp_api::decl_runtime_apis! { fn is_finalized_block(hash: Hash) -> bool; } + /// API for querying information about the finalized Rialto headers. + /// + /// This API is implemented by runtimes that are bridging with the Rialto chain, not the + /// Millau runtime itself. + pub trait RialtoFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + /// Outbound message lane API for messages that are sent to Rialto chain. /// /// This API is implemented by runtimes that are sending messages to Rialto chain, not the From 52890c0389e2288ba467a52434f2ace712db73aa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 5 Mar 2021 00:00:26 +0300 Subject: [PATCH 0363/1210] Migrate to jsonrpsee v2 (#787) * POC jsonrpsee v2 * POC update ws client * connect to eth nodes using ws * fix for subscriptions * reverted unncecessary changes * reference jsonrpsee from crates.io * fixed eth port in deployments * fmt * order deps * remove unnecessary comment * clone is no longer required for subscriptions * treat RpcError::Internal as connection error * resubscribe on terminate * Update deployments/bridges/poa-rialto/entrypoints/poa-exchange-tx-generator-entrypoint.sh Co-authored-by: Niklas Adolfsson Co-authored-by: Hernando Castano --- relays/ethereum-client/Cargo.toml | 4 +- relays/ethereum-client/src/client.rs | 54 ++++++------ relays/ethereum-client/src/error.rs | 18 ++-- relays/ethereum-client/src/lib.rs | 8 +- relays/ethereum-client/src/rpc.rs | 2 +- relays/ethereum/src/cli.yml | 6 +- .../ethereum/src/ethereum_deploy_contract.rs | 2 +- relays/ethereum/src/ethereum_exchange.rs | 8 +- .../ethereum/src/ethereum_exchange_submit.rs | 4 +- relays/ethereum/src/ethereum_sync_loop.rs | 7 +- relays/ethereum/src/substrate_sync_loop.rs | 7 +- relays/substrate-client/Cargo.toml | 4 +- relays/substrate-client/src/chain.rs | 2 +- relays/substrate-client/src/client.rs | 52 ++++++------ relays/substrate-client/src/error.rs | 28 +++---- relays/substrate-client/src/rpc.rs | 2 +- relays/substrate/src/headers_maintain.rs | 82 ++++++++++++++++--- relays/substrate/src/headers_pipeline.rs | 19 +---- 18 files changed, 178 insertions(+), 131 deletions(-) diff --git a/relays/ethereum-client/Cargo.toml b/relays/ethereum-client/Cargo.toml index b0f6485ffd384..ac5930145888f 100644 --- a/relays/ethereum-client/Cargo.toml +++ b/relays/ethereum-client/Cargo.toml @@ -10,7 +10,9 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers-relay" } hex-literal = "0.3" -jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["http"] } +jsonrpsee-proc-macros = "0.2.0-alpha" +jsonrpsee-types = "0.2.0-alpha" +jsonrpsee-ws-client = "0.2.0-alpha" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/ethereum-client/src/client.rs b/relays/ethereum-client/src/client.rs index 30a62a400e1dd..593e40d67a473 100644 --- a/relays/ethereum-client/src/client.rs +++ b/relays/ethereum-client/src/client.rs @@ -21,9 +21,8 @@ use crate::types::{ }; use crate::{ConnectionParams, Error, Result}; -use jsonrpsee::raw::RawClient; -use jsonrpsee::transport::http::HttpTransportClient; -use jsonrpsee::Client as RpcClient; +use jsonrpsee_ws_client::{WsClient as RpcClient, WsConfig as RpcConfig}; +use std::sync::Arc; /// Number of headers missing from the Ethereum node for us to consider node not synced. const MAJOR_SYNC_BLOCKS: u64 = 5; @@ -32,36 +31,36 @@ const MAJOR_SYNC_BLOCKS: u64 = 5; #[derive(Clone)] pub struct Client { params: ConnectionParams, - client: RpcClient, + client: Arc, } impl Client { /// Create a new Ethereum RPC Client. - pub fn new(params: ConnectionParams) -> Self { - Self { - client: Self::build_client(¶ms), + pub async fn new(params: ConnectionParams) -> Result { + Ok(Self { + client: Self::build_client(¶ms).await?, params, - } + }) } /// Build client to use in connection. - fn build_client(params: &ConnectionParams) -> RpcClient { - let uri = format!("http://{}:{}", params.host, params.port); - let transport = HttpTransportClient::new(&uri); - let raw_client = RawClient::new(transport); - raw_client.into() + async fn build_client(params: &ConnectionParams) -> Result> { + let uri = format!("ws://{}:{}", params.host, params.port); + let client = RpcClient::new(RpcConfig::with_url(&uri)).await?; + Ok(Arc::new(client)) } /// Reopen client connection. - pub fn reconnect(&mut self) { - self.client = Self::build_client(&self.params); + pub async fn reconnect(&mut self) -> Result<()> { + self.client = Self::build_client(&self.params).await?; + Ok(()) } } impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { - match Ethereum::syncing(&self.client).await? { + match Ethereum::syncing(&*self.client).await? { SyncState::NotSyncing => Ok(()), SyncState::Syncing(syncing) => { let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block); @@ -76,18 +75,18 @@ impl Client { /// Estimate gas usage for the given call. pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { - Ok(Ethereum::estimate_gas(&self.client, call_request).await?) + Ok(Ethereum::estimate_gas(&*self.client, call_request).await?) } /// Retrieve number of the best known block from the Ethereum node. pub async fn best_block_number(&self) -> Result { - Ok(Ethereum::block_number(&self.client).await?.as_u64()) + Ok(Ethereum::block_number(&*self.client).await?.as_u64()) } /// Retrieve number of the best known block from the Ethereum node. pub async fn header_by_number(&self, block_number: u64) -> Result
{ let get_full_tx_objects = false; - let header = Ethereum::get_block_by_number(&self.client, block_number, get_full_tx_objects).await?; + let header = Ethereum::get_block_by_number(&*self.client, block_number, get_full_tx_objects).await?; match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { true => Ok(header), false => Err(Error::IncompleteHeader), @@ -97,7 +96,7 @@ impl Client { /// Retrieve block header by its hash from Ethereum node. pub async fn header_by_hash(&self, hash: H256) -> Result
{ let get_full_tx_objects = false; - let header = Ethereum::get_block_by_hash(&self.client, hash, get_full_tx_objects).await?; + let header = Ethereum::get_block_by_hash(&*self.client, hash, get_full_tx_objects).await?; match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { true => Ok(header), false => Err(Error::IncompleteHeader), @@ -107,7 +106,8 @@ impl Client { /// Retrieve block header and its transactions by its number from Ethereum node. pub async fn header_by_number_with_transactions(&self, number: u64) -> Result { let get_full_tx_objects = true; - let header = Ethereum::get_block_by_number_with_transactions(&self.client, number, get_full_tx_objects).await?; + let header = + Ethereum::get_block_by_number_with_transactions(&*self.client, number, get_full_tx_objects).await?; let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); if !is_complete_header { @@ -125,7 +125,7 @@ impl Client { /// Retrieve block header and its transactions by its hash from Ethereum node. pub async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { let get_full_tx_objects = true; - let header = Ethereum::get_block_by_hash_with_transactions(&self.client, hash, get_full_tx_objects).await?; + let header = Ethereum::get_block_by_hash_with_transactions(&*self.client, hash, get_full_tx_objects).await?; let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); if !is_complete_header { @@ -142,17 +142,17 @@ impl Client { /// Retrieve transaction by its hash from Ethereum node. pub async fn transaction_by_hash(&self, hash: H256) -> Result> { - Ok(Ethereum::transaction_by_hash(&self.client, hash).await?) + Ok(Ethereum::transaction_by_hash(&*self.client, hash).await?) } /// Retrieve transaction receipt by transaction hash. pub async fn transaction_receipt(&self, transaction_hash: H256) -> Result { - Ok(Ethereum::get_transaction_receipt(&self.client, transaction_hash).await?) + Ok(Ethereum::get_transaction_receipt(&*self.client, transaction_hash).await?) } /// Get the nonce of the given account. pub async fn account_nonce(&self, address: Address) -> Result { - Ok(Ethereum::get_transaction_count(&self.client, address).await?) + Ok(Ethereum::get_transaction_count(&*self.client, address).await?) } /// Submit an Ethereum transaction. @@ -160,13 +160,13 @@ impl Client { /// The transaction must already be signed before sending it through this method. pub async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result { let transaction = Bytes(signed_raw_tx); - let tx_hash = Ethereum::submit_transaction(&self.client, transaction).await?; + let tx_hash = Ethereum::submit_transaction(&*self.client, transaction).await?; log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); Ok(tx_hash) } /// Call Ethereum smart contract. pub async fn eth_call(&self, call_transaction: CallRequest) -> Result { - Ok(Ethereum::call(&self.client, call_transaction).await?) + Ok(Ethereum::call(&*self.client, call_transaction).await?) } } diff --git a/relays/ethereum-client/src/error.rs b/relays/ethereum-client/src/error.rs index 0f47891138aba..80d4e89d5ee96 100644 --- a/relays/ethereum-client/src/error.rs +++ b/relays/ethereum-client/src/error.rs @@ -18,7 +18,7 @@ use crate::types::U256; -use jsonrpsee::client::RequestError; +use jsonrpsee_types::error::Error as RpcError; use relay_utils::MaybeConnectionError; /// Result type used by Ethereum client. @@ -30,7 +30,7 @@ pub type Result = std::result::Result; pub enum Error { /// An error that can occur when making an HTTP request to /// an JSON-RPC client. - Request(RequestError), + RpcError(RpcError), /// Failed to parse response. ResponseParseFailed(String), /// We have received a header with missing fields. @@ -47,9 +47,9 @@ pub enum Error { ClientNotSynced(U256), } -impl From for Error { - fn from(error: RequestError) -> Self { - Error::Request(error) +impl From for Error { + fn from(error: RpcError) -> Self { + Error::RpcError(error) } } @@ -57,7 +57,11 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::Request(RequestError::TransportError(_)) | Error::ClientNotSynced(_), + Error::RpcError(RpcError::TransportError(_)) + // right now if connection to the ws server is dropped (after it is already established), + // we're getting this error + | Error::RpcError(RpcError::Internal(_)) + | Error::ClientNotSynced(_), ) } } @@ -65,7 +69,7 @@ impl MaybeConnectionError for Error { impl ToString for Error { fn to_string(&self) -> String { match self { - Self::Request(e) => e.to_string(), + Self::RpcError(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(), Self::IncompleteHeader => { "Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom)" diff --git a/relays/ethereum-client/src/lib.rs b/relays/ethereum-client/src/lib.rs index 8c5a00e01b4d7..17bfda6e6443b 100644 --- a/relays/ethereum-client/src/lib.rs +++ b/relays/ethereum-client/src/lib.rs @@ -29,12 +29,12 @@ pub use crate::sign::{sign_and_submit_transaction, SigningParams}; pub mod types; -/// Ethereum connection params. +/// Ethereum-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { - /// Ethereum RPC host. + /// Websocket server hostname. pub host: String, - /// Ethereum RPC port. + /// Websocket server TCP port. pub port: u16, } @@ -42,7 +42,7 @@ impl Default for ConnectionParams { fn default() -> Self { ConnectionParams { host: "localhost".into(), - port: 8545, + port: 8546, } } } diff --git a/relays/ethereum-client/src/rpc.rs b/relays/ethereum-client/src/rpc.rs index 3fa4f6ceb9cd9..26cc3a6d969e0 100644 --- a/relays/ethereum-client/src/rpc.rs +++ b/relays/ethereum-client/src/rpc.rs @@ -26,7 +26,7 @@ use crate::types::{ H256, U256, U64, }; -jsonrpsee::rpc_api! { +jsonrpsee_proc_macros::rpc_client_api! { pub(crate) Ethereum { #[rpc(method = "eth_syncing", positional_params)] fn syncing() -> SyncState; diff --git a/relays/ethereum/src/cli.yml b/relays/ethereum/src/cli.yml index c6a5b08e1bb04..78971787c0e2b 100644 --- a/relays/ethereum/src/cli.yml +++ b/relays/ethereum/src/cli.yml @@ -9,17 +9,17 @@ subcommands: - eth-host: ð-host long: eth-host value_name: ETH_HOST - help: Connect to Ethereum node at given host. + help: Connect to Ethereum node websocket server at given host. takes_value: true - eth-port: ð-port long: eth-port value_name: ETH_PORT - help: Connect to Ethereum node at given port. + help: Connect to Ethereum node websocket server at given port. takes_value: true - sub-host: &sub-host long: sub-host value_name: SUB_HOST - help: Connect to Substrate node at given host. + help: Connect to Substrate node websocket server at given host. takes_value: true - sub-port: &sub-port long: sub-port diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index 25f8c873e5903..e703711843a9c 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -62,7 +62,7 @@ pub fn run(params: EthereumDeployContractParams) { } = params; let result = local_pool.run_until(async move { - let eth_client = EthereumClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; let sub_client = SubstrateClient::::new(sub_params).await.map_err(RpcError::Substrate)?; let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index 92ba211535129..ecd22ab81a1f9 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -130,8 +130,7 @@ impl RelayClient for EthereumTransactionsSource { type Error = RpcError; async fn reconnect(&mut self) -> Result<(), RpcError> { - self.client.reconnect(); - Ok(()) + self.client.reconnect().await.map_err(Into::into) } } @@ -305,7 +304,7 @@ fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H25 } = params; let result = local_pool.run_until(async move { - let eth_client = EthereumClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; let sub_client = SubstrateClient::::new(sub_params) .await .map_err(RpcError::Substrate)?; @@ -351,7 +350,8 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi } = params; let do_run_loop = move || -> Result<(), String> { - let eth_client = EthereumClient::new(eth_params); + let eth_client = async_std::task::block_on(EthereumClient::new(eth_params)) + .map_err(|err| format!("Error starting Ethereum client: {:?}", err))?; let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params)) .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index d2842b78a4a2e..8f9f942dac53e 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -54,7 +54,9 @@ pub fn run(params: EthereumExchangeSubmitParams) { } = params; let result: Result<_, String> = local_pool.run_until(async move { - let eth_client = EthereumClient::new(eth_params); + let eth_client = EthereumClient::new(eth_params) + .await + .map_err(|err| format!("error connecting to Ethereum node: {:?}", err))?; let eth_signer_address = secret_to_address(ð_sign.signer); let sub_recipient_encoded = sub_recipient; diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index c8741c2fe18a6..2c1abb358c63f 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -122,8 +122,7 @@ impl RelayClient for EthereumHeadersSource { type Error = RpcError; async fn reconnect(&mut self) -> Result<(), RpcError> { - self.client.reconnect(); - Ok(()) + self.client.reconnect().await.map_err(Into::into) } } @@ -259,8 +258,8 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { instance, } = params; - let eth_client = EthereumClient::new(eth_params); - let sub_client = async_std::task::block_on(async { SubstrateClient::::new(sub_params).await })?; + let eth_client = async_std::task::block_on(EthereumClient::new(eth_params))?; + let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params))?; let sign_sub_transactions = match sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 9e15b9223826a..5f30e247c5a79 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -123,8 +123,7 @@ impl RelayClient for EthereumHeadersTarget { type Error = RpcError; async fn reconnect(&mut self) -> Result<(), RpcError> { - self.client.reconnect(); - Ok(()) + self.client.reconnect().await.map_err(Into::into) } } @@ -174,8 +173,8 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { metrics_params, } = params; - let eth_client = EthereumClient::new(eth_params); - let sub_client = async_std::task::block_on(async { SubstrateClient::::new(sub_params).await })?; + let eth_client = async_std::task::block_on(EthereumClient::new(eth_params))?; + let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params))?; let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 1c60f861e2e5a..18df0dba874b5 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -9,7 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } -jsonrpsee = { git = "https://github.com/svyatonik/jsonrpsee.git", branch = "shared-client-in-rpc-api", default-features = false, features = ["ws"] } +jsonrpsee-proc-macros = "0.2.0-alpha" +jsonrpsee-types = "0.2.0-alpha" +jsonrpsee-ws-client = "0.2.0-alpha" log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index f309c3f775e76..352a63dc48884 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -18,7 +18,7 @@ use crate::client::Client; use bp_runtime::Chain as ChainBase; use frame_support::Parameter; -use jsonrpsee::common::{DeserializeOwned, Serialize}; +use jsonrpsee_types::jsonrpc::{DeserializeOwned, Serialize}; use num_traits::{CheckedSub, Zero}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ diff --git a/relays/substrate-client/src/client.rs b/relays/substrate-client/src/client.rs index 767002d686543..813dda6940335 100644 --- a/relays/substrate-client/src/client.rs +++ b/relays/substrate-client/src/client.rs @@ -24,10 +24,8 @@ use bp_message_lane::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::Decode; use frame_system::AccountInfo; -use jsonrpsee::common::DeserializeOwned; -use jsonrpsee::raw::RawClient; -use jsonrpsee::transport::ws::WsTransportClient; -use jsonrpsee::{client::Subscription, Client as RpcClient}; +use jsonrpsee_types::{jsonrpc::DeserializeOwned, traits::SubscriptionClient}; +use jsonrpsee_ws_client::{WsClient as RpcClient, WsConfig as RpcConfig, WsSubscription as Subscription}; use num_traits::Zero; use pallet_balances::AccountData; use sp_core::Bytes; @@ -36,6 +34,7 @@ use sp_version::RuntimeVersion; use std::ops::RangeInclusive; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; +const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// Opaque justifications subscription type. pub type JustificationsSubscription = Subscription; @@ -79,7 +78,7 @@ impl Client { let client = Self::build_client(params.clone()).await?; let number: C::BlockNumber = Zero::zero(); - let genesis_hash = Substrate::::chain_get_block_hash(&client, number).await?; + let genesis_hash = Substrate::::chain_get_block_hash(&client, number).await?; Ok(Self { params, @@ -97,16 +96,17 @@ impl Client { /// Build client to use in connection. async fn build_client(params: ConnectionParams) -> Result { let uri = format!("ws://{}:{}", params.host, params.port); - let transport = WsTransportClient::new(&uri).await?; - let raw_client = RawClient::new(transport); - Ok(raw_client.into()) + let mut config = RpcConfig::with_url(&uri); + config.max_subscription_capacity = MAX_SUBSCRIPTION_CAPACITY; + let client = RpcClient::new(config).await?; + Ok(client) } } impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { - let health = Substrate::::system_health(&self.client).await?; + let health = Substrate::::system_health(&self.client).await?; let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); if is_synced { Ok(()) @@ -122,7 +122,7 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { - Ok(Substrate::::chain_get_finalized_head(&self.client).await?) + Ok(Substrate::::chain_get_finalized_head(&self.client).await?) } /// Returns the best Substrate header. @@ -130,12 +130,12 @@ impl Client { where C::Header: DeserializeOwned, { - Ok(Substrate::::chain_get_header(&self.client, None).await?) + Ok(Substrate::::chain_get_header(&self.client, None).await?) } /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { - Ok(Substrate::::chain_get_block(&self.client, block_hash).await?) + Ok(Substrate::::chain_get_block(&self.client, block_hash).await?) } /// Get a Substrate header by its hash. @@ -143,12 +143,12 @@ impl Client { where C::Header: DeserializeOwned, { - Ok(Substrate::::chain_get_header(&self.client, block_hash).await?) + Ok(Substrate::::chain_get_header(&self.client, block_hash).await?) } /// Get a Substrate block hash by its number. pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { - Ok(Substrate::::chain_get_block_hash(&self.client, number).await?) + Ok(Substrate::::chain_get_block_hash(&self.client, number).await?) } /// Get a Substrate header by its number. @@ -162,7 +162,7 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { - Ok(Substrate::::runtime_version(&self.client).await?) + Ok(Substrate::::runtime_version(&self.client).await?) } /// Return native tokens balance of the account. @@ -171,7 +171,7 @@ impl Client { C: ChainWithBalances, { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = Substrate::::get_storage(&self.client, storage_key) + let encoded_account_data = Substrate::::get_storage(&self.client, storage_key) .await? .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = @@ -184,14 +184,14 @@ impl Client { /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { - Ok(Substrate::::system_account_next_index(&self.client, account).await?) + Ok(Substrate::::system_account_next_index(&self.client, account).await?) } /// Submit an extrinsic for inclusion in a block. /// /// Note: The given transaction does not need be SCALE encoded beforehand. pub async fn submit_extrinsic(&self, transaction: Bytes) -> Result { - let tx_hash = Substrate::::author_submit_extrinsic(&self.client, transaction).await?; + let tx_hash = Substrate::::author_submit_extrinsic(&self.client, transaction).await?; log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); Ok(tx_hash) } @@ -201,7 +201,7 @@ impl Client { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); - let encoded_response = Substrate::::state_call(&self.client, call, data, Some(block)).await?; + let encoded_response = Substrate::::state_call(&self.client, call, data, Some(block)).await?; let authority_list = encoded_response.0; Ok(authority_list) @@ -209,7 +209,7 @@ impl Client { /// Execute runtime call at given block. pub async fn state_call(&self, method: String, data: Bytes, at_block: Option) -> Result { - Substrate::::state_call(&self.client, method, data, at_block) + Substrate::::state_call(&self.client, method, data, at_block) .await .map_err(Into::into) } @@ -223,7 +223,7 @@ impl Client { include_outbound_lane_state: bool, at_block: C::Hash, ) -> Result { - let encoded_trie_nodes = SubstrateMessageLane::::prove_messages( + let encoded_trie_nodes = SubstrateMessageLane::::prove_messages( &self.client, instance, lane, @@ -233,7 +233,7 @@ impl Client { Some(at_block), ) .await - .map_err(Error::Request)?; + .map_err(Error::RpcError)?; let decoded_trie_nodes: Vec> = Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; Ok(StorageProof::new(decoded_trie_nodes)) @@ -247,21 +247,21 @@ impl Client { at_block: C::Hash, ) -> Result>> { let encoded_trie_nodes = - SubstrateMessageLane::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) + SubstrateMessageLane::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) .await - .map_err(Error::Request)?; + .map_err(Error::RpcError)?; let decoded_trie_nodes: Vec> = Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; Ok(decoded_trie_nodes) } /// Return new justifications stream. - pub async fn subscribe_justifications(self) -> Result { + pub async fn subscribe_justifications(&self) -> Result { Ok(self .client .subscribe( "grandpa_subscribeJustifications", - jsonrpsee::common::Params::None, + jsonrpsee_types::jsonrpc::Params::None, "grandpa_unsubscribeJustifications", ) .await?) diff --git a/relays/substrate-client/src/error.rs b/relays/substrate-client/src/error.rs index 67aefe9885534..c513cf1b70f0d 100644 --- a/relays/substrate-client/src/error.rs +++ b/relays/substrate-client/src/error.rs @@ -16,8 +16,7 @@ //! Substrate node RPC errors. -use jsonrpsee::client::RequestError; -use jsonrpsee::transport::ws::WsNewDnsError; +use jsonrpsee_types::error::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; @@ -28,11 +27,9 @@ pub type Result = std::result::Result; /// a Substrate node through RPC. #[derive(Debug)] pub enum Error { - /// Web socket connection error. - WsConnectionError(WsNewDnsError), /// An error that can occur when making a request to /// an JSON-RPC server. - Request(RequestError), + RpcError(RpcError), /// The response from the server could not be SCALE decoded. ResponseParseFailed(codec::Error), /// The Substrate bridge pallet has not yet been initialized. @@ -45,15 +42,9 @@ pub enum Error { Custom(String), } -impl From for Error { - fn from(error: WsNewDnsError) -> Self { - Error::WsConnectionError(error) - } -} - -impl From for Error { - fn from(error: RequestError) -> Self { - Error::Request(error) +impl From for Error { + fn from(error: RpcError) -> Self { + Error::RpcError(error) } } @@ -61,7 +52,11 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::Request(RequestError::TransportError(_)) | Error::ClientNotSynced(_) + Error::RpcError(RpcError::TransportError(_)) + // right now if connection to the ws server is dropped (after it is already established), + // we're getting this error + | Error::RpcError(RpcError::Internal(_)) + | Error::ClientNotSynced(_), ) } } @@ -75,8 +70,7 @@ impl From for String { impl ToString for Error { fn to_string(&self) -> String { match self { - Self::WsConnectionError(e) => e.to_string(), - Self::Request(e) => e.to_string(), + Self::RpcError(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), diff --git a/relays/substrate-client/src/rpc.rs b/relays/substrate-client/src/rpc.rs index 2e832b4018174..d768912a2f1a5 100644 --- a/relays/substrate-client/src/rpc.rs +++ b/relays/substrate-client/src/rpc.rs @@ -32,7 +32,7 @@ use sp_core::{ }; use sp_version::RuntimeVersion; -jsonrpsee::rpc_api! { +jsonrpsee_proc_macros::rpc_client_api! { pub(crate) Substrate { #[rpc(method = "system_health", positional_params)] fn system_health() -> Health; diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs index 14432487ea308..fb609a2ef0705 100644 --- a/relays/substrate/src/headers_maintain.rs +++ b/relays/substrate/src/headers_maintain.rs @@ -47,8 +47,10 @@ use sp_runtime::{traits::Header as HeaderT, Justification}; use std::{collections::VecDeque, marker::PhantomData, task::Poll}; /// Substrate-to-Substrate headers synchronization maintain procedure. -pub struct SubstrateHeadersToSubstrateMaintain { +pub struct SubstrateHeadersToSubstrateMaintain +{ pipeline: P, + source_client: Client, target_client: Client, justifications: Arc>>, _marker: PhantomData, @@ -56,20 +58,23 @@ pub struct SubstrateHeadersToSubstrateMaintain { - /// Justifications stream. - stream: JustificationsSubscription, + /// Justifications stream. None if it hasn't been initialized yet, or it has been dropped + /// by the rpc library. + stream: Option, /// Justifications that we have read from the stream but have not sent to the /// target node, because their targets were still not synced. queue: VecDeque<(HeaderIdOf

, Justification)>, } -impl +impl SubstrateHeadersToSubstrateMaintain { /// Create new maintain procedure. - pub fn new(pipeline: P, target_client: Client, justifications: JustificationsSubscription) -> Self { + pub async fn new(pipeline: P, source_client: Client, target_client: Client) -> Self { + let justifications = subscribe_justifications(&source_client).await; SubstrateHeadersToSubstrateMaintain { pipeline, + source_client, target_client, justifications: Arc::new(Mutex::new(Justifications { stream: justifications, @@ -81,12 +86,13 @@ impl } #[async_trait] -impl Clone +impl Clone for SubstrateHeadersToSubstrateMaintain { fn clone(&self) -> Self { SubstrateHeadersToSubstrateMaintain { pipeline: self.pipeline.clone(), + source_client: self.source_client.clone(), target_client: self.target_client.clone(), justifications: self.justifications.clone(), _marker: Default::default(), @@ -141,18 +147,23 @@ where // Select justification to submit to the target node. We're submitting at most one justification // on every maintain call. So maintain rate directly affects finalization rate. - let justification_to_submit = poll_fn(|context| { + let (resubscribe, justification_to_submit) = poll_fn(|context| { // read justifications from the stream and push to the queue - justifications.read_from_stream::(context); + let resubscribe = !justifications.read_from_stream::(context); // remove all obsolete justifications from the queue remove_obsolete::

(&mut justifications.queue, best_finalized); // select justification to submit - Poll::Ready(select_justification(&mut justifications.queue, sync)) + Poll::Ready((resubscribe, select_justification(&mut justifications.queue, sync))) }) .await; + // if justifications subscription has been dropped, resubscribe + if resubscribe { + justifications.stream = subscribe_justifications(&self.source_client).await; + } + // finally - submit selected justification if let Some((target, justification)) = justification_to_submit { let submit_result = self @@ -187,20 +198,42 @@ where P: SubstrateHeadersSyncPipeline, { /// Read justifications from the subscription stream without blocking. - fn read_from_stream<'a, SourceHeader>(&mut self, context: &mut std::task::Context<'a>) + /// + /// Returns `true` if justifications stream is still readable and `false` if it has been + /// dropped by the RPC crate && we need to resubscribe. + #[must_use] + fn read_from_stream<'a, SourceHeader>(&mut self, context: &mut std::task::Context<'a>) -> bool where SourceHeader: HeaderT, SourceHeader::Number: Into, SourceHeader::Hash: Into, { + let stream = match self.stream.as_mut() { + Some(stream) => stream, + None => return false, + }; + loop { - let maybe_next_justification = self.stream.next(); + let maybe_next_justification = stream.next(); futures::pin_mut!(maybe_next_justification); let maybe_next_justification = maybe_next_justification.poll_unpin(context); let justification = match maybe_next_justification { Poll::Ready(justification) => justification, - Poll::Pending => return, + Poll::Pending => return true, + }; + + let justification = match justification { + Some(justification) => justification, + None => { + log::warn!( + target: "bridge", + "{} justifications stream has been dropped. Will be trying to resubscribe", + P::SOURCE_NAME, + ); + + return false; + } }; // decode justification target @@ -302,6 +335,31 @@ where Ok(best_header_id) } +/// Subscribe to justifications stream at source node. +async fn subscribe_justifications(client: &Client) -> Option { + match client.subscribe_justifications().await { + Ok(source_justifications) => { + log::debug!( + target: "bridge", + "Successfully (re)subscribed to {} justifications", + C::NAME, + ); + + Some(source_justifications) + } + Err(error) => { + log::warn!( + target: "bridge", + "Failed to subscribe to {} justifications: {:?}", + C::NAME, + error, + ); + + None + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs index 8ad6fc50b9527..541a613735c52 100644 --- a/relays/substrate/src/headers_pipeline.rs +++ b/relays/substrate/src/headers_pipeline.rs @@ -139,25 +139,12 @@ pub async fn run( BlockNumberOf: BlockNumberBase, TargetChain: Clone + Chain, { - let source_justifications = match source_client.clone().subscribe_justifications().await { - Ok(source_justifications) => source_justifications, - Err(error) => { - log::warn!( - target: "bridge", - "Failed to subscribe to {} justifications: {:?}", - SourceChain::NAME, - error, - ); - - return; - } - }; - let sync_maintain = SubstrateHeadersToSubstrateMaintain::<_, SourceChain, _>::new( pipeline.clone(), + source_client.clone(), target_client.clone(), - source_justifications, - ); + ) + .await; log::info!( target: "bridge", From d1267442be7d27e6f4c43be155c280e3e22bcf42 Mon Sep 17 00:00:00 2001 From: Hector Bulgarini Date: Fri, 5 Mar 2021 13:25:51 -0300 Subject: [PATCH 0364/1210] Adding message relayer scripts, reformating send message scripts (#790) * Adding message relayer scripts, reformating send message scripts * Addressing PR feedback * Update README.md Valid . Co-authored-by: Hernando Castano * Fixing send-message-from-rialto-millau * Fixing send message script from millau to rialot Co-authored-by: Hernando Castano --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eaa63ad14c77b..c02608a9d6a93 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Substrate chains or Ethereum Proof-of-Authority chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 ## Contents + - [Installation](#installation) - [High-Level Architecture](#high-level-architecture) - [Project Layout](#project-layout) @@ -19,6 +20,7 @@ Substrate chains or Ethereum Proof-of-Authority chains. - [Community](#community) ## Installation + To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web Assembly (WASM) runtime for the node. You can configure the WASM support as so: @@ -70,6 +72,7 @@ Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) description of the bridge interaction. ## Project Layout + Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual "blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass messages between chains. @@ -91,7 +94,7 @@ the `relays` which are used to pass messages between chains. ├── relays // Application for sending headers and messages between chains │ └── ... └── scripts // Useful development and maintenence scripts - ``` +``` ## Running the Bridge @@ -99,9 +102,9 @@ To run the Bridge you need to be able to connect the bridge relay node to the RP on each side of the bridge (source and target chain). There are 3 ways to run the bridge, described below: - - building & running from source, - - building or using Docker images for each individual component, - - running a Docker Compose setup (recommended). +- building & running from source, +- building or using Docker images for each individual component, +- running a Docker Compose setup (recommended). ### Using the Source @@ -196,6 +199,7 @@ monitoring dashboards, etc. see the [Deployments README](./deployments/README.md A straightforward way to interact with and test the bridge is sending messages. This is explained in the [send message](./docs/send-message.md) document. + ## Community Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat @@ -208,4 +212,3 @@ Element channel. The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element channel is most suited for discussions regarding Substrate itself. - From 6faabbc8b45c5ac3e94b644bd373da07aba09706 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 8 Mar 2021 13:18:53 +0300 Subject: [PATCH 0365/1210] Relay Millau && Rialto headers using (future) finality verifier API (#761) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * finality proofs relay * SyncHeader::is_mandatory * empty ancestry proof * logs * fixed submit condition * fixed wrong split index * tick comment * recent_finality_proofs * basic finality loop tests * removed obsolete files * rename files in substrate relay * fmt * clippy * fixed TODOs * clippy * stop syncing if target node is out of sync * more clippy * more clippy * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Hernando Castano * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Hernando Castano * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Hernando Castano * docs * moved doc * typo * Update relays/finality-relay/src/finality_loop_tests.rs Co-authored-by: Hernando Castano * Update relays/finality-relay/src/finality_loop_tests.rs Co-authored-by: Hernando Castano * header_and_finality_proof_by_number -> header_and_finality_proof * VecDeque isn't required (because of make_contiguous) * fixed wrong expect * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Hernando Castano * Update relays/substrate/src/rialto_headers_to_millau.rs Co-authored-by: Hernando Castano * Update relays/substrate/src/rialto_headers_to_millau.rs Co-authored-by: Hernando Castano * RialtoSyncHeader * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Tomasz Drwięga * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Tomasz Drwięga * removed wrong comment * Update relays/finality-relay/src/finality_loop.rs Co-authored-by: Tomasz Drwięga * fix used runtime methods names * fix for new jsonrpsee * fix comment * initialize finality verifier pallet * fmt Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + modules/substrate/src/lib.rs | 2 +- modules/substrate/src/verifier.rs | 21 +- primitives/header-chain/src/lib.rs | 20 +- primitives/millau/src/lib.rs | 13 +- primitives/rialto/src/lib.rs | 11 - relays/finality-relay/Cargo.toml | 20 + relays/finality-relay/src/finality_loop.rs | 581 ++++++++++++++++++ .../finality-relay/src/finality_loop_tests.rs | 339 ++++++++++ relays/finality-relay/src/lib.rs | 60 ++ relays/headers-relay/src/sync_loop_metrics.rs | 22 +- relays/substrate-client/Cargo.toml | 2 + relays/substrate-client/src/chain.rs | 18 +- .../substrate-client/src/finality_source.rs | 147 +++++ relays/substrate-client/src/guard.rs | 3 +- relays/substrate-client/src/lib.rs | 1 + relays/substrate-client/src/sync_header.rs | 14 +- relays/substrate/Cargo.toml | 3 +- relays/substrate/src/finality_pipeline.rs | 130 ++++ relays/substrate/src/finality_target.rs | 91 +++ relays/substrate/src/headers_initialize.rs | 8 +- relays/substrate/src/headers_maintain.rs | 458 -------------- relays/substrate/src/headers_pipeline.rs | 166 ----- relays/substrate/src/headers_target.rs | 168 ----- relays/substrate/src/main.rs | 9 +- relays/substrate/src/messages_target.rs | 2 +- .../substrate/src/millau_headers_to_rialto.rs | 58 +- .../src/millau_messages_to_rialto.rs | 4 +- .../substrate/src/rialto_headers_to_millau.rs | 57 +- .../src/rialto_messages_to_millau.rs | 4 +- 31 files changed, 1490 insertions(+), 944 deletions(-) create mode 100644 relays/finality-relay/Cargo.toml create mode 100644 relays/finality-relay/src/finality_loop.rs create mode 100644 relays/finality-relay/src/finality_loop_tests.rs create mode 100644 relays/finality-relay/src/lib.rs create mode 100644 relays/substrate-client/src/finality_source.rs create mode 100644 relays/substrate/src/finality_pipeline.rs create mode 100644 relays/substrate/src/finality_target.rs delete mode 100644 relays/substrate/src/headers_maintain.rs delete mode 100644 relays/substrate/src/headers_pipeline.rs delete mode 100644 relays/substrate/src/headers_target.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 090257419d549..ee6f1d483b0ea 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -61,6 +61,7 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; +pub use pallet_finality_verifier::Call as FinalityBridgeRialtoCall; pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_sudo::Call as SudoCall; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index eed087bdf82cf..9f289d2c87f79 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -69,6 +69,7 @@ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use pallet_finality_verifier::Call as FinalityBridgeMillauCall; pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeMillauCall; pub use pallet_sudo::Call as SudoCall; diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 1ae23fdf91b1c..90213e5c9b9ab 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -417,7 +417,7 @@ where } else { // We don't have a scheduled change in storage at the moment. Let's check if the current // header signals an authority set change. - if let Some(change) = verifier::find_scheduled_change(&header) { + if let Some(change) = bp_header_chain::find_grandpa_authorities_scheduled_change(&header) { let next_set = AuthoritySet { authorities: change.next_authorities, set_id: storage.current_authority_set().set_id + 1, diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 0c3bd1b5ddd49..effb5761b650c 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -25,10 +25,8 @@ use crate::storage::{ImportedHeader, ScheduledChange}; use crate::BridgeStorage; -use bp_header_chain::{justification::verify_justification, AuthoritySet}; +use bp_header_chain::{find_grandpa_authorities_scheduled_change, justification::verify_justification, AuthoritySet}; use finality_grandpa::voter_set::VoterSet; -use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; -use sp_runtime::generic::OpaqueDigestItemId; use sp_runtime::traits::{CheckedAdd, Header as HeaderT, One}; use sp_runtime::RuntimeDebug; use sp_std::{prelude::Vec, vec}; @@ -142,7 +140,7 @@ where // time. While this is not strictly true of GRANDPA (it can have multiple pending changes, // even across forks), this assumption simplifies our tracking of authority set changes. let mut signal_hash = parent_header.signal_hash; - let scheduled_change = find_scheduled_change(&header); + let scheduled_change = find_grandpa_authorities_scheduled_change(&header); // Check if our fork is expecting an authority set change let requires_justification = if let Some(hash) = signal_hash { @@ -339,19 +337,6 @@ where Some(ancestors) } -pub(crate) fn find_scheduled_change(header: &H) -> Option> { - let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); - - let filter_log = |log: ConsensusLog| match log { - ConsensusLog::ScheduledChange(change) => Some(change), - _ => None, - }; - - // find the first consensus digest with the right ID which converts to - // the right kind of consensus log. - header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) -} - #[cfg(test)] mod tests { use super::*; @@ -361,7 +346,7 @@ mod tests { use codec::Encode; use frame_support::{assert_err, assert_ok}; use frame_support::{StorageMap, StorageValue}; - use sp_finality_grandpa::{AuthorityId, SetId}; + use sp_finality_grandpa::{AuthorityId, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{Digest, DigestItem}; fn schedule_next_change( diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index a2d8574b6dc48..65181df316859 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -26,9 +26,9 @@ use core::default::Default; use core::fmt::Debug; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -use sp_finality_grandpa::{AuthorityList, SetId}; -use sp_runtime::traits::Header as HeaderT; +use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::RuntimeDebug; +use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT}; use sp_std::vec::Vec; pub mod justification; @@ -140,6 +140,22 @@ impl AncestryChecker> for LinearAncestryChecker { } } +/// Find header digest that schedules next GRANDPA authorities set. +pub fn find_grandpa_authorities_scheduled_change( + header: &H, +) -> Option> { + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + + let filter_log = |log: ConsensusLog| match log { + ConsensusLog::ScheduledChange(change) => Some(change), + _ => None, + }; + + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index 23acef4701a65..afaf36de32e75 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -229,19 +229,8 @@ pub fn max_extrinsic_size() -> u32 { *BlockLength::get().max.get(DispatchClass::Normal) } -/// Name of the `MillauHeaderApi::best_block` runtime method. -pub const BEST_MILLAU_BLOCKS_METHOD: &str = "MillauHeaderApi_best_blocks"; -/// Name of the `MillauHeaderApi::finalized_block` runtime method. -pub const FINALIZED_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_finalized_block"; -/// Name of the `MillauHeaderApi::is_known_block` runtime method. -pub const IS_KNOWN_MILLAU_BLOCK_METHOD: &str = "MillauHeaderApi_is_known_block"; -/// Name of the `MillauHeaderApi::incomplete_headers` runtime method. -pub const INCOMPLETE_MILLAU_HEADERS_METHOD: &str = "MillauHeaderApi_incomplete_headers"; - -/// Name of the `RialtoFinalityApi::best_finalized` runtime method. +/// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; -/// Name of the `RialtoFinalityApi::is_known_header` runtime method. -pub const IS_KNOW_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_is_known_header"; /// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index 856dd8b7fbfed..c598b7ee8379b 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -190,19 +190,8 @@ pub fn max_extrinsic_size() -> u32 { *BlockLength::get().max.get(DispatchClass::Normal) } -/// Name of the `RialtoHeaderApi::best_blocks` runtime method. -pub const BEST_RIALTO_BLOCKS_METHOD: &str = "RialtoHeaderApi_best_blocks"; -/// Name of the `RialtoHeaderApi::finalized_block` runtime method. -pub const FINALIZED_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_finalized_block"; -/// Name of the `RialtoHeaderApi::is_known_block` runtime method. -pub const IS_KNOWN_RIALTO_BLOCK_METHOD: &str = "RialtoHeaderApi_is_known_block"; -/// Name of the `RialtoHeaderApi::incomplete_headers` runtime method. -pub const INCOMPLETE_RIALTO_HEADERS_METHOD: &str = "RialtoHeaderApi_incomplete_headers"; - /// Name of the `RialtoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_finalized"; -/// Name of the `RialtoFinalityApi::is_known_header` runtime method. -pub const IS_KNOW_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_is_known_header"; /// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = diff --git a/relays/finality-relay/Cargo.toml b/relays/finality-relay/Cargo.toml new file mode 100644 index 0000000000000..9667ba2fa674c --- /dev/null +++ b/relays/finality-relay/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "finality-relay" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +description = "Finality proofs relay" + +[dependencies] +async-std = "1.6.5" +async-trait = "0.1.40" +backoff = "0.2" +futures = "0.3.5" +headers-relay = { path = "../headers-relay" } +log = "0.4.11" +num-traits = "0.2" +relay-utils = { path = "../utils" } + +[dev-dependencies] +parking_lot = "0.11.0" diff --git a/relays/finality-relay/src/finality_loop.rs b/relays/finality-relay/src/finality_loop.rs new file mode 100644 index 0000000000000..50c23b3757233 --- /dev/null +++ b/relays/finality-relay/src/finality_loop.rs @@ -0,0 +1,581 @@ +// 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 . + +//! The loop basically reads all missing headers and their finality proofs from the source client. +//! The proof for the best possible header is then submitted to the target node. The only exception +//! is the mandatory headers, which we always submit to the target node. For such headers, we +//! assume that the persistent proof either exists, or will eventually become available. + +use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; + +use async_trait::async_trait; +use backoff::backoff::Backoff; +use futures::{select, Future, FutureExt, Stream, StreamExt}; +use headers_relay::sync_loop_metrics::SyncLoopMetrics; +use num_traits::{One, Saturating}; +use relay_utils::{ + metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + relay_loop::Client as RelayClient, + retry_backoff, FailedClient, MaybeConnectionError, +}; +use std::{ + pin::Pin, + time::{Duration, Instant}, +}; + +/// Finality proof synchronization loop parameters. +#[derive(Debug, Clone)] +pub struct FinalitySyncParams { + /// Interval at which we check updates on both clients. Normally should be larger than + /// `min(source_block_time, target_block_time)`. + /// + /// This parameter may be used to limit transactions rate. Increase the value && you'll get + /// infrequent updates => sparse headers => potential slow down of bridge applications, but pallet storage + /// won't be super large. Decrease the value to near `source_block_time` and you'll get + /// transaction for (almost) every block of the source chain => all source headers will be known + /// to the target chain => bridge applications will run faster, but pallet storage may explode + /// (but if pruning is there, then it's fine). + pub tick: Duration, + /// Number of finality proofs to keep in internal buffer between loop wakeups. + /// + /// While in "major syncing" state, we still read finality proofs from the stream. They're stored + /// in the internal buffer between loop wakeups. When we're close to the tip of the chain, we may + /// meet finality delays if headers are not finalized frequently. So instead of waiting for next + /// finality proof to appear in the stream, we may use existing proof from that buffer. + pub recent_finality_proofs_limit: usize, + /// Timeout before we treat our transactions as lost and restart the whole sync process. + pub stall_timeout: Duration, +} + +/// Source client used in finality synchronization loop. +#[async_trait] +pub trait SourceClient: RelayClient { + /// Stream of new finality proofs. The stream is allowed to miss proofs for some + /// headers, even if those headers are mandatory. + type FinalityProofsStream: Stream; + + /// Get best finalized block number. + async fn best_finalized_block_number(&self) -> Result; + + /// Get canonical header and its finality proof by number. + async fn header_and_finality_proof( + &self, + number: P::Number, + ) -> Result<(P::Header, Option), Self::Error>; + + /// Subscribe to new finality proofs. + async fn finality_proofs(&self) -> Result; +} + +/// Target client used in finality synchronization loop. +#[async_trait] +pub trait TargetClient: RelayClient { + /// Get best finalized source block number. + async fn best_finalized_source_block_number(&self) -> Result; + + /// Submit header finality proof. + async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), Self::Error>; +} + +/// Run finality proofs synchronization loop. +pub fn run( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + sync_params: FinalitySyncParams, + metrics_params: Option, + exit_signal: impl Future, +) { + let exit_signal = exit_signal.shared(); + + let metrics_global = GlobalMetrics::default(); + let metrics_sync = SyncLoopMetrics::default(); + let metrics_enabled = metrics_params.is_some(); + metrics_start( + format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), + metrics_params, + &metrics_global, + &metrics_sync, + ); + + relay_utils::relay_loop::run( + relay_utils::relay_loop::RECONNECT_DELAY, + source_client, + target_client, + |source_client, target_client| { + run_until_connection_lost( + source_client, + target_client, + sync_params.clone(), + if metrics_enabled { + Some(metrics_global.clone()) + } else { + None + }, + if metrics_enabled { + Some(metrics_sync.clone()) + } else { + None + }, + exit_signal.clone(), + ) + }, + ); +} + +/// Unjustified headers container. Ordered by header number. +pub(crate) type UnjustifiedHeaders

= Vec<

::Header>; +/// Finality proofs container. Ordered by target header number. +pub(crate) type FinalityProofs

= Vec<( +

::Number, +

::FinalityProof, +)>; + +/// Error that may happen inside finality synchronization loop. +#[derive(Debug)] +enum Error { + /// Source client request has failed with given error. + Source(SourceError), + /// Target client request has failed with given error. + Target(TargetError), + /// Finality proof for mandatory header is missing from the source node. + MissingMandatoryFinalityProof(P::Number), + /// The synchronization has stalled. + Stalled, +} + +impl Error +where + P: FinalitySyncPipeline, + SourceError: MaybeConnectionError, + TargetError: MaybeConnectionError, +{ + fn fail_if_connection_error(&self) -> Result<(), FailedClient> { + match *self { + Error::Source(ref error) if error.is_connection_error() => Err(FailedClient::Source), + Error::Target(ref error) if error.is_connection_error() => Err(FailedClient::Target), + Error::Stalled => Err(FailedClient::Both), + _ => Ok(()), + } + } +} + +/// Information about transaction that we have submitted. +#[derive(Debug, Clone)] +struct Transaction { + /// Time when we have submitted this transaction. + pub time: Instant, + /// The number of the header we have submitted. + pub submitted_header_number: Number, +} + +/// Finality proofs stream that may be restarted. +struct RestartableFinalityProofsStream { + /// Flag that the stream needs to be restarted. + needs_restart: bool, + /// The stream itself. + stream: Pin>, +} + +/// Finality synchronization loop state. +struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { + /// Synchronization loop progress. + progress: &'a mut (Instant, Option), + /// Finality proofs stream. + finality_proofs_stream: &'a mut RestartableFinalityProofsStream, + /// Recent finality proofs that we have read from the stream. + recent_finality_proofs: &'a mut FinalityProofs

, + /// Last transaction that we have submitted to the target node. + last_transaction: Option>, +} + +async fn run_until_connection_lost( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + sync_params: FinalitySyncParams, + metrics_global: Option, + metrics_sync: Option, + exit_signal: impl Future, +) -> Result<(), FailedClient> { + let restart_finality_proofs_stream = || async { + source_client.finality_proofs().await.map_err(|error| { + log::error!( + target: "bridge", + "Failed to subscribe to {} justifications: {:?}. Going to reconnect", + P::SOURCE_NAME, + error, + ); + + FailedClient::Source + }) + }; + + let exit_signal = exit_signal.fuse(); + futures::pin_mut!(exit_signal); + + let mut finality_proofs_stream = RestartableFinalityProofsStream { + needs_restart: false, + stream: Box::pin(restart_finality_proofs_stream().await?), + }; + let mut recent_finality_proofs = Vec::new(); + + let mut progress = (Instant::now(), None); + let mut retry_backoff = retry_backoff(); + let mut last_transaction = None; + + loop { + // run loop iteration + let iteration_result = run_loop_iteration( + &source_client, + &target_client, + FinalityLoopState { + progress: &mut progress, + finality_proofs_stream: &mut finality_proofs_stream, + recent_finality_proofs: &mut recent_finality_proofs, + last_transaction: last_transaction.clone(), + }, + &sync_params, + &metrics_sync, + ) + .await; + + // update global metrics + if let Some(ref metrics_global) = metrics_global { + metrics_global.update().await; + } + + // deal with errors + let next_tick = match iteration_result { + Ok(updated_last_transaction) => { + last_transaction = updated_last_transaction; + retry_backoff.reset(); + sync_params.tick + } + Err(error) => { + log::error!(target: "bridge", "Finality sync loop iteration has failed with error: {:?}", error); + error.fail_if_connection_error()?; + retry_backoff + .next_backoff() + .unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) + } + }; + if finality_proofs_stream.needs_restart { + finality_proofs_stream.needs_restart = false; + finality_proofs_stream.stream = Box::pin(restart_finality_proofs_stream().await?); + } + + // wait till exit signal, or new source block + select! { + _ = async_std::task::sleep(next_tick).fuse() => {}, + _ = exit_signal => return Ok(()), + } + } +} + +async fn run_loop_iteration( + source_client: &SC, + target_client: &TC, + state: FinalityLoopState<'_, P, SC::FinalityProofsStream>, + sync_params: &FinalitySyncParams, + metrics_sync: &Option, +) -> Result>, Error> +where + P: FinalitySyncPipeline, + SC: SourceClient

, + TC: TargetClient

, +{ + // read best source headers ids from source and target nodes + let best_number_at_source = source_client + .best_finalized_block_number() + .await + .map_err(Error::Source)?; + let best_number_at_target = target_client + .best_finalized_source_block_number() + .await + .map_err(Error::Target)?; + if let Some(ref metrics_sync) = *metrics_sync { + metrics_sync.update_best_block_at_source(best_number_at_source); + metrics_sync.update_best_block_at_target(best_number_at_target); + } + *state.progress = print_sync_progress::

(*state.progress, best_number_at_source, best_number_at_target); + + // if we have already submitted header, then we just need to wait for it + // if we're waiting too much, then we believe our transaction has been lost and restart sync + if let Some(last_transaction) = state.last_transaction { + if best_number_at_target >= last_transaction.submitted_header_number { + // transaction has been mined && we can continue + } else if last_transaction.time.elapsed() > sync_params.stall_timeout { + log::error!( + target: "bridge", + "Finality synchronization from {} to {} has stalled. Going to restart", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + + return Err(Error::Stalled); + } else { + return Ok(Some(last_transaction)); + } + } + + // submit new header if we have something new + match select_header_to_submit( + source_client, + target_client, + state.finality_proofs_stream, + state.recent_finality_proofs, + best_number_at_source, + best_number_at_target, + sync_params, + ) + .await? + { + Some((header, justification)) => { + let new_transaction = Transaction { + time: Instant::now(), + submitted_header_number: header.number(), + }; + + log::debug!( + target: "bridge", + "Going to submit finality proof of {} header #{:?} to {}", + P::SOURCE_NAME, + new_transaction.submitted_header_number, + P::TARGET_NAME, + ); + + target_client + .submit_finality_proof(header, justification) + .await + .map_err(Error::Target)?; + Ok(Some(new_transaction)) + } + None => Ok(None), + } +} + +async fn select_header_to_submit( + source_client: &SC, + _target_client: &TC, + finality_proofs_stream: &mut RestartableFinalityProofsStream, + recent_finality_proofs: &mut FinalityProofs

, + best_number_at_source: P::Number, + best_number_at_target: P::Number, + sync_params: &FinalitySyncParams, +) -> Result, Error> +where + P: FinalitySyncPipeline, + SC: SourceClient

, + TC: TargetClient

, +{ + let mut selected_finality_proof = None; + let mut unjustified_headers = Vec::new(); + + // to see that the loop is progressing + log::trace!( + target: "bridge", + "Considering range of headers ({:?}; {:?}]", + best_number_at_target, + best_number_at_source, + ); + + // read missing headers. if we see that the header schedules GRANDPA change, we need to + // submit this header + let mut header_number = best_number_at_target + One::one(); + while header_number <= best_number_at_source { + let (header, finality_proof) = source_client + .header_and_finality_proof(header_number) + .await + .map_err(Error::Source)?; + let is_mandatory = header.is_mandatory(); + + match (is_mandatory, finality_proof) { + (true, Some(finality_proof)) => { + log::trace!(target: "bridge", "Header {:?} is mandatory", header_number); + return Ok(Some((header, finality_proof))); + } + (true, None) => return Err(Error::MissingMandatoryFinalityProof(header.number())), + (false, Some(finality_proof)) => { + log::trace!(target: "bridge", "Header {:?} has persistent finality proof", header_number); + selected_finality_proof = Some((header, finality_proof)); + prune_unjustified_headers::

(header_number, &mut unjustified_headers); + } + (false, None) => { + unjustified_headers.push(header); + } + } + + header_number = header_number + One::one(); + } + + // see if we can improve finality by using recent finality proofs + if !unjustified_headers.is_empty() && !recent_finality_proofs.is_empty() { + const NOT_EMPTY_PROOF: &str = "we have checked that the vec is not empty; qed"; + + // we need proofs for headers in range unjustified_range_begin..=unjustified_range_end + let unjustified_range_begin = unjustified_headers.first().expect(NOT_EMPTY_PROOF).number(); + let unjustified_range_end = unjustified_headers.last().expect(NOT_EMPTY_PROOF).number(); + + // we have proofs for headers in range buffered_range_begin..=buffered_range_end + let buffered_range_begin = recent_finality_proofs.first().expect(NOT_EMPTY_PROOF).0; + let buffered_range_end = recent_finality_proofs.last().expect(NOT_EMPTY_PROOF).0; + + // we have two ranges => find intersection + let intersection_begin = std::cmp::max(unjustified_range_begin, buffered_range_begin); + let intersection_end = std::cmp::min(unjustified_range_end, buffered_range_end); + let intersection = intersection_begin..=intersection_end; + + // find last proof from intersection + let selected_finality_proof_index = recent_finality_proofs + .binary_search_by_key(intersection.end(), |(number, _)| *number) + .unwrap_or_else(|index| index.saturating_sub(1)); + let (selected_header_number, finality_proof) = &recent_finality_proofs[selected_finality_proof_index]; + if intersection.contains(selected_header_number) { + // now remove all obsolete headers and extract selected header + let selected_header = prune_unjustified_headers::

(*selected_header_number, &mut unjustified_headers) + .expect("unjustified_headers contain all headers from intersection; qed"); + selected_finality_proof = Some((selected_header, finality_proof.clone())); + } + } + + // read all proofs from the stream, probably selecting updated proof that we're going to submit + loop { + let next_proof = finality_proofs_stream.stream.next(); + let finality_proof = match next_proof.now_or_never() { + Some(Some(finality_proof)) => finality_proof, + Some(None) => { + finality_proofs_stream.needs_restart = true; + break; + } + None => break, + }; + let finality_proof_target_header_number = match finality_proof.target_header_number() { + Some(target_header_number) => target_header_number, + None => { + continue; + } + }; + + let justified_header = + prune_unjustified_headers::

(finality_proof_target_header_number, &mut unjustified_headers); + if let Some(justified_header) = justified_header { + recent_finality_proofs.clear(); + selected_finality_proof = Some((justified_header, finality_proof)); + } else { + // the number of proofs read during single wakeup is expected to be low, so we aren't pruning + // `recent_finality_proofs` collection too often + recent_finality_proofs.push((finality_proof_target_header_number, finality_proof)); + } + } + + // remove obsolete 'recent' finality proofs + keep its size under certain limit + let oldest_finality_proof_to_keep = selected_finality_proof + .as_ref() + .map(|(header, _)| header.number()) + .unwrap_or(best_number_at_target); + prune_recent_finality_proofs::

( + oldest_finality_proof_to_keep, + recent_finality_proofs, + sync_params.recent_finality_proofs_limit, + ); + + Ok(selected_finality_proof) +} + +/// Remove headers from `unjustified_headers` collection with number lower or equal than `justified_header_number`. +/// +/// Returns the header that matches `justified_header_number` (if any). +pub(crate) fn prune_unjustified_headers( + justified_header_number: P::Number, + unjustified_headers: &mut UnjustifiedHeaders

, +) -> Option { + prune_ordered_vec(justified_header_number, unjustified_headers, usize::MAX, |header| { + header.number() + }) +} + +pub(crate) fn prune_recent_finality_proofs( + justified_header_number: P::Number, + recent_finality_proofs: &mut FinalityProofs

, + recent_finality_proofs_limit: usize, +) { + prune_ordered_vec( + justified_header_number, + recent_finality_proofs, + recent_finality_proofs_limit, + |(header_number, _)| *header_number, + ); +} + +fn prune_ordered_vec( + header_number: Number, + ordered_vec: &mut Vec, + maximal_vec_size: usize, + extract_header_number: impl Fn(&T) -> Number, +) -> Option { + let position = ordered_vec.binary_search_by_key(&header_number, extract_header_number); + + // first extract element we're interested in + let extracted_element = match position { + Ok(position) => { + let updated_vec = ordered_vec.split_off(position + 1); + let extracted_element = ordered_vec.pop().expect( + "binary_search_by_key has returned Ok(); so there's element at `position`;\ + we're splitting vec at `position+1`; so we have pruned at least 1 element;\ + qed", + ); + *ordered_vec = updated_vec; + Some(extracted_element) + } + Err(position) => { + *ordered_vec = ordered_vec.split_off(position); + None + } + }; + + // now - limit vec by size + let split_index = ordered_vec.len().saturating_sub(maximal_vec_size); + *ordered_vec = ordered_vec.split_off(split_index); + + extracted_element +} + +fn print_sync_progress( + progress_context: (Instant, Option), + best_number_at_source: P::Number, + best_number_at_target: P::Number, +) -> (Instant, Option) { + let (prev_time, prev_best_number_at_target) = progress_context; + let now = Instant::now(); + + let need_update = now - prev_time > Duration::from_secs(10) + || prev_best_number_at_target + .map(|prev_best_number_at_target| { + best_number_at_target.saturating_sub(prev_best_number_at_target) > 10.into() + }) + .unwrap_or(true); + + if !need_update { + return (prev_time, prev_best_number_at_target); + } + + log::info!( + target: "bridge", + "Synced {:?} of {:?} headers", + best_number_at_target, + best_number_at_source, + ); + (now, Some(best_number_at_target)) +} diff --git a/relays/finality-relay/src/finality_loop_tests.rs b/relays/finality-relay/src/finality_loop_tests.rs new file mode 100644 index 0000000000000..5dfe8edd2124a --- /dev/null +++ b/relays/finality-relay/src/finality_loop_tests.rs @@ -0,0 +1,339 @@ +// 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 . + +//! Tests for finality synchronization loop. + +#![cfg(test)] + +use crate::finality_loop::{ + prune_recent_finality_proofs, prune_unjustified_headers, run, FinalityProofs, FinalitySyncParams, SourceClient, + TargetClient, UnjustifiedHeaders, +}; +use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; + +use async_trait::async_trait; +use futures::{FutureExt, Stream, StreamExt}; +use parking_lot::Mutex; +use relay_utils::{relay_loop::Client as RelayClient, MaybeConnectionError}; +use std::{collections::HashMap, pin::Pin, sync::Arc, time::Duration}; + +type IsMandatory = bool; +type TestNumber = u64; + +#[derive(Debug, Clone)] +enum TestError { + NonConnection, +} + +impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + false + } +} + +#[derive(Debug, Clone)] +struct TestFinalitySyncPipeline; + +impl FinalitySyncPipeline for TestFinalitySyncPipeline { + const SOURCE_NAME: &'static str = "TestSource"; + const TARGET_NAME: &'static str = "TestTarget"; + + type Hash = u64; + type Number = TestNumber; + type Header = TestSourceHeader; + type FinalityProof = TestFinalityProof; +} + +#[derive(Debug, Clone, PartialEq)] +struct TestSourceHeader(IsMandatory, TestNumber); + +impl SourceHeader for TestSourceHeader { + fn number(&self) -> TestNumber { + self.1 + } + + fn is_mandatory(&self) -> bool { + self.0 + } +} + +#[derive(Debug, Clone, PartialEq)] +struct TestFinalityProof(Option); + +impl FinalityProof for TestFinalityProof { + fn target_header_number(&self) -> Option { + self.0 + } +} + +#[derive(Debug, Clone, Default)] +struct ClientsData { + source_best_block_number: TestNumber, + source_headers: HashMap)>, + source_proofs: Vec, + + target_best_block_number: TestNumber, + target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, +} + +#[derive(Clone)] +struct TestSourceClient { + on_method_call: Arc, + data: Arc>, +} + +#[async_trait] +impl RelayClient for TestSourceClient { + type Error = TestError; + + async fn reconnect(&mut self) -> Result<(), TestError> { + unreachable!() + } +} + +#[async_trait] +impl SourceClient for TestSourceClient { + type FinalityProofsStream = Pin>>; + + async fn best_finalized_block_number(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut *data); + Ok(data.source_best_block_number) + } + + async fn header_and_finality_proof( + &self, + number: TestNumber, + ) -> Result<(TestSourceHeader, Option), TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(&mut *data); + data.source_headers + .get(&number) + .cloned() + .ok_or(TestError::NonConnection) + } + + async fn finality_proofs(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut *data); + Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) + } +} + +#[derive(Clone)] +struct TestTargetClient { + on_method_call: Arc, + data: Arc>, +} + +#[async_trait] +impl RelayClient for TestTargetClient { + type Error = TestError; + + async fn reconnect(&mut self) -> Result<(), TestError> { + unreachable!() + } +} + +#[async_trait] +impl TargetClient for TestTargetClient { + async fn best_finalized_source_block_number(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut *data); + Ok(data.target_best_block_number) + } + + async fn submit_finality_proof(&self, header: TestSourceHeader, proof: TestFinalityProof) -> Result<(), TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(&mut *data); + data.target_best_block_number = header.number(); + data.target_headers.push((header, proof)); + Ok(()) + } +} + +fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static) -> ClientsData { + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + let internal_state_function: Arc = Arc::new(move |data| { + if state_function(data) { + exit_sender.unbounded_send(()).unwrap(); + } + }); + let clients_data = Arc::new(Mutex::new(ClientsData { + source_best_block_number: 10, + source_headers: vec![ + (6, (TestSourceHeader(false, 6), None)), + (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(Some(7))))), + (8, (TestSourceHeader(true, 8), Some(TestFinalityProof(Some(8))))), + (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(Some(9))))), + (10, (TestSourceHeader(false, 10), None)), + ] + .into_iter() + .collect(), + source_proofs: vec![TestFinalityProof(Some(12)), TestFinalityProof(Some(14))], + + target_best_block_number: 5, + target_headers: vec![], + })); + let source_client = TestSourceClient { + on_method_call: internal_state_function.clone(), + data: clients_data.clone(), + }; + let target_client = TestTargetClient { + on_method_call: internal_state_function, + data: clients_data.clone(), + }; + let sync_params = FinalitySyncParams { + tick: Duration::from_secs(0), + recent_finality_proofs_limit: 1024, + stall_timeout: Duration::from_secs(1), + }; + + run( + source_client, + target_client, + sync_params, + None, + exit_receiver.into_future().map(|(_, _)| ()), + ); + + let clients_data = clients_data.lock().clone(); + clients_data +} + +#[test] +fn finality_sync_loop_works() { + let client_data = run_sync_loop(|data| { + // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, because + // header#8 has persistent finality proof && it is mandatory => it is submitted + // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, because + // there are no more persistent finality proofs + // + // once this ^^^ is done, we generate more blocks && read proof for blocks 12, 14 and 16 from the stream + // but we only submit proof for 16 + // + // proof for block 15 is ignored - we haven't managed to decode it + if data.target_best_block_number == 9 { + data.source_best_block_number = 17; + data.source_headers.insert(11, (TestSourceHeader(false, 11), None)); + data.source_headers + .insert(12, (TestSourceHeader(false, 12), Some(TestFinalityProof(Some(12))))); + data.source_headers.insert(13, (TestSourceHeader(false, 13), None)); + data.source_headers + .insert(14, (TestSourceHeader(false, 14), Some(TestFinalityProof(Some(14))))); + data.source_headers + .insert(15, (TestSourceHeader(false, 15), Some(TestFinalityProof(None)))); + data.source_headers + .insert(16, (TestSourceHeader(false, 16), Some(TestFinalityProof(Some(16))))); + data.source_headers.insert(17, (TestSourceHeader(false, 17), None)); + } + + data.target_best_block_number == 16 + }); + + assert_eq!( + client_data.target_headers, + vec![ + (TestSourceHeader(true, 8), TestFinalityProof(Some(8))), + (TestSourceHeader(false, 9), TestFinalityProof(Some(9))), + (TestSourceHeader(false, 16), TestFinalityProof(Some(16))), + ], + ); +} + +#[test] +fn prune_unjustified_headers_works() { + let original_unjustified_headers: UnjustifiedHeaders = vec![ + TestSourceHeader(false, 10), + TestSourceHeader(false, 13), + TestSourceHeader(false, 15), + TestSourceHeader(false, 17), + TestSourceHeader(false, 19), + ] + .into_iter() + .collect(); + + // when header is in the collection + let mut unjustified_headers = original_unjustified_headers.clone(); + assert_eq!( + prune_unjustified_headers::(10, &mut unjustified_headers), + Some(TestSourceHeader(false, 10)), + ); + assert_eq!(&original_unjustified_headers[1..], unjustified_headers,); + + // when the header doesn't exist in the collection + let mut unjustified_headers = original_unjustified_headers.clone(); + assert_eq!( + prune_unjustified_headers::(11, &mut unjustified_headers), + None, + ); + assert_eq!(&original_unjustified_headers[1..], unjustified_headers,); + + // when last entry is pruned + let mut unjustified_headers = original_unjustified_headers.clone(); + assert_eq!( + prune_unjustified_headers::(19, &mut unjustified_headers), + Some(TestSourceHeader(false, 19)), + ); + + assert_eq!(&original_unjustified_headers[5..], unjustified_headers,); + + // when we try and prune past last entry + let mut unjustified_headers = original_unjustified_headers.clone(); + assert_eq!( + prune_unjustified_headers::(20, &mut unjustified_headers), + None, + ); + assert_eq!(&original_unjustified_headers[5..], unjustified_headers,); +} + +#[test] +fn prune_recent_finality_proofs_works() { + let original_recent_finality_proofs: FinalityProofs = vec![ + (10, TestFinalityProof(Some(10))), + (13, TestFinalityProof(Some(13))), + (15, TestFinalityProof(Some(15))), + (17, TestFinalityProof(Some(17))), + (19, TestFinalityProof(Some(19))), + ] + .into_iter() + .collect(); + + // when there's proof for justified header in the vec + let mut recent_finality_proofs = original_recent_finality_proofs.clone(); + prune_recent_finality_proofs::(10, &mut recent_finality_proofs, 1024); + assert_eq!(&original_recent_finality_proofs[1..], recent_finality_proofs,); + + // when there are no proof for justified header in the vec + let mut recent_finality_proofs = original_recent_finality_proofs.clone(); + prune_recent_finality_proofs::(11, &mut recent_finality_proofs, 1024); + assert_eq!(&original_recent_finality_proofs[1..], recent_finality_proofs,); + + // when there are too many entries after initial prune && they also need to be pruned + let mut recent_finality_proofs = original_recent_finality_proofs.clone(); + prune_recent_finality_proofs::(10, &mut recent_finality_proofs, 2); + assert_eq!(&original_recent_finality_proofs[3..], recent_finality_proofs,); + + // when last entry is pruned + let mut recent_finality_proofs = original_recent_finality_proofs.clone(); + prune_recent_finality_proofs::(19, &mut recent_finality_proofs, 2); + assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); + + // when post-last entry is pruned + let mut recent_finality_proofs = original_recent_finality_proofs.clone(); + prune_recent_finality_proofs::(20, &mut recent_finality_proofs, 2); + assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); +} diff --git a/relays/finality-relay/src/lib.rs b/relays/finality-relay/src/lib.rs new file mode 100644 index 0000000000000..e9d946e27f189 --- /dev/null +++ b/relays/finality-relay/src/lib.rs @@ -0,0 +1,60 @@ +// 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 . + +//! This crate has single entrypoint to run synchronization loop that is built around finality +//! proofs, as opposed to headers synchronization loop, which is built around headers. The headers +//! are still submitted to the target node, but are treated as auxiliary data as we are not trying +//! to submit all source headers to the target node. + +pub use crate::finality_loop::{run, FinalitySyncParams, SourceClient, TargetClient}; + +use std::fmt::Debug; + +mod finality_loop; +mod finality_loop_tests; + +/// Finality proofs synchronization pipeline. +pub trait FinalitySyncPipeline: Clone + Debug + Send + Sync { + /// Name of the finality proofs source. + const SOURCE_NAME: &'static str; + /// Name of the finality proofs target. + const TARGET_NAME: &'static str; + + /// Headers we're syncing are identified by this hash. + type Hash: Eq + Clone + Copy + Send + Sync + Debug; + /// Headers we're syncing are identified by this number. + type Number: relay_utils::BlockNumberBase; + /// Type of header that we're syncing. + type Header: SourceHeader; + /// Finality proof type. + type FinalityProof: FinalityProof; +} + +/// Header that we're receiving from source node. +pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { + /// Returns number of header. + fn number(&self) -> Number; + /// Returns true if this header needs to be submitted to target node. + fn is_mandatory(&self) -> bool; +} + +/// Abstract finality proof that is justifying block finality. +pub trait FinalityProof: Clone + Send + Sync + Debug { + /// Return header id that this proof is generated for. + /// + /// None is returned if proof is invalid from relayer PoV. + fn target_header_number(&self) -> Option; +} diff --git a/relays/headers-relay/src/sync_loop_metrics.rs b/relays/headers-relay/src/sync_loop_metrics.rs index 456aa0a6b0522..9cec0e891dc81 100644 --- a/relays/headers-relay/src/sync_loop_metrics.rs +++ b/relays/headers-relay/src/sync_loop_metrics.rs @@ -57,18 +57,28 @@ impl Default for SyncLoopMetrics { } impl SyncLoopMetrics { - /// Update metrics. - pub fn update(&self, sync: &HeadersSync

) { - let headers = sync.headers(); - let source_best_number = sync.source_best_number().unwrap_or_else(Zero::zero); - let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); - + /// Update best block number at source. + pub fn update_best_block_at_source>(&self, source_best_number: Number) { self.best_block_numbers .with_label_values(&["source"]) .set(source_best_number.into()); + } + + /// Update best block number at target. + pub fn update_best_block_at_target>(&self, target_best_number: Number) { self.best_block_numbers .with_label_values(&["target"]) .set(target_best_number.into()); + } + + /// Update metrics. + pub fn update(&self, sync: &HeadersSync

) { + let headers = sync.headers(); + let source_best_number = sync.source_best_number().unwrap_or_else(Zero::zero); + let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); + + self.update_best_block_at_source(source_best_number); + self.update_best_block_at_target(target_best_number); self.blocks_in_state .with_label_values(&["maybe_orphan"]) diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 18df0dba874b5..8a794c86081b6 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -18,8 +18,10 @@ rand = "0.7" # Bridge dependencies +bp-header-chain = { path = "../../primitives/header-chain" } bp-message-lane = { path = "../../primitives/message-lane" } bp-runtime = { path = "../../primitives/runtime" } +finality-relay = { path = "../finality-relay" } headers-relay = { path = "../headers-relay" } relay-utils = { path = "../utils" } diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index 352a63dc48884..60a3cc5d17491 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -23,7 +23,9 @@ use num_traits::{CheckedSub, Zero}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, - traits::{AtLeast32Bit, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member}, + traits::{ + AtLeast32Bit, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member, + }, Justification, }; use std::{fmt::Debug, time::Duration}; @@ -51,7 +53,7 @@ pub trait Chain: ChainBase { + AtLeast32Bit + Copy; /// Block type. - type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; + type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. type Call: Dispatchable + Debug; } @@ -67,7 +69,9 @@ pub trait ChainWithBalances: Chain { } /// Block with justification. -pub trait BlockWithJustification { +pub trait BlockWithJustification

{ + /// Return block header. + fn header(&self) -> Header; /// Return block justification, if known. fn justification(&self) -> Option<&Justification>; } @@ -90,13 +94,11 @@ pub trait TransactionSignScheme { ) -> Self::SignedTransaction; } -impl BlockWithJustification for () { - fn justification(&self) -> Option<&Justification> { - None +impl BlockWithJustification for SignedBlock { + fn header(&self) -> Block::Header { + self.block.header().clone() } -} -impl BlockWithJustification for SignedBlock { fn justification(&self) -> Option<&Justification> { self.justification.as_ref() } diff --git a/relays/substrate-client/src/finality_source.rs b/relays/substrate-client/src/finality_source.rs new file mode 100644 index 0000000000000..2c76619e867fa --- /dev/null +++ b/relays/substrate-client/src/finality_source.rs @@ -0,0 +1,147 @@ +// 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 . + +//! Default generic implementation of finality source for basic Substrate client. + +use crate::chain::{BlockWithJustification, Chain}; +use crate::client::Client; +use crate::error::Error; +use crate::sync_header::SyncHeader; + +use async_trait::async_trait; +use finality_relay::{FinalityProof, FinalitySyncPipeline, SourceClient, SourceHeader}; +use futures::stream::{unfold, Stream, StreamExt}; +use relay_utils::relay_loop::Client as RelayClient; +use sp_runtime::traits::Header as HeaderT; +use std::{marker::PhantomData, pin::Pin}; + +/// Wrapped raw Justification. +#[derive(Debug, Clone)] +pub struct Justification
{ + raw_justification: sp_runtime::Justification, + _phantom: PhantomData
, +} + +impl
Justification
{ + /// Extract raw justification. + pub fn into_inner(self) -> sp_runtime::Justification { + self.raw_justification + } +} + +impl
FinalityProof for Justification
+where + Header: HeaderT, +{ + fn target_header_number(&self) -> Option { + bp_header_chain::justification::decode_justification_target::
(&self.raw_justification) + .ok() + .map(|(_, number)| number) + } +} + +/// Substrate node as finality source. +pub struct FinalitySource { + client: Client, + _phantom: PhantomData

, +} + +impl FinalitySource { + /// Create new headers source using given client. + pub fn new(client: Client) -> Self { + FinalitySource { + client, + _phantom: Default::default(), + } + } +} + +impl Clone for FinalitySource { + fn clone(&self) -> Self { + FinalitySource { + client: self.client.clone(), + _phantom: Default::default(), + } + } +} + +#[async_trait] +impl RelayClient for FinalitySource { + type Error = Error; + + async fn reconnect(&mut self) -> Result<(), Error> { + self.client.reconnect().await + } +} + +#[async_trait] +impl SourceClient

for FinalitySource +where + C: Chain, + C::BlockNumber: relay_utils::BlockNumberBase, + P: FinalitySyncPipeline< + Hash = C::Hash, + Number = C::BlockNumber, + Header = SyncHeader, + FinalityProof = Justification, + >, + P::Header: SourceHeader, +{ + type FinalityProofsStream = Pin>>>; + + async fn best_finalized_block_number(&self) -> Result { + // we **CAN** continue to relay finality proofs if source node is out of sync, because + // target node may be missing proofs that are already available at the source + let finalized_header_hash = self.client.best_finalized_header_hash().await?; + let finalized_header = self.client.header_by_hash(finalized_header_hash).await?; + Ok(*finalized_header.number()) + } + + async fn header_and_finality_proof( + &self, + number: P::Number, + ) -> Result<(P::Header, Option), Error> { + let header_hash = self.client.block_hash_by_number(number).await?; + let signed_block = self.client.get_block(Some(header_hash)).await?; + Ok(( + signed_block.header().into(), + signed_block + .justification() + .cloned() + .map(|raw_justification| Justification { + raw_justification, + _phantom: Default::default(), + }), + )) + } + + async fn finality_proofs(&self) -> Result { + Ok(unfold( + self.client.clone().subscribe_justifications().await?, + move |mut subscription| async move { + let next_justification = subscription.next().await?; + Some(( + Justification { + raw_justification: next_justification.0, + _phantom: Default::default(), + }, + subscription, + )) + }, + ) + .boxed()) + } +} diff --git a/relays/substrate-client/src/guard.rs b/relays/substrate-client/src/guard.rs index d439ec890763d..e924b94b6f79f 100644 --- a/relays/substrate-client/src/guard.rs +++ b/relays/substrate-client/src/guard.rs @@ -187,7 +187,8 @@ mod tests { type AccountId = u32; type Index = u32; - type SignedBlock = (); + type SignedBlock = + sp_runtime::generic::SignedBlock>; type Call = (); } diff --git a/relays/substrate-client/src/lib.rs b/relays/substrate-client/src/lib.rs index c6d077b21c562..6a21e3bffa207 100644 --- a/relays/substrate-client/src/lib.rs +++ b/relays/substrate-client/src/lib.rs @@ -24,6 +24,7 @@ mod error; mod rpc; mod sync_header; +pub mod finality_source; pub mod guard; pub mod headers_source; diff --git a/relays/substrate-client/src/sync_header.rs b/relays/substrate-client/src/sync_header.rs index fd1c582b9480e..30e33a39279a2 100644 --- a/relays/substrate-client/src/sync_header.rs +++ b/relays/substrate-client/src/sync_header.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_header_chain::find_grandpa_authorities_scheduled_change; +use finality_relay::SourceHeader as FinalitySourceHeader; use headers_relay::sync_types::SourceHeader; use num_traits::{CheckedSub, One}; use relay_utils::HeaderId; @@ -47,7 +49,7 @@ impl

From
for SyncHeader
{ impl SourceHeader for SyncHeader
{ fn id(&self) -> HeaderId { - relay_utils::HeaderId(*self.number(), self.hash()) + relay_utils::HeaderId(*self.0.number(), self.hash()) } fn parent_id(&self) -> HeaderId { @@ -59,3 +61,13 @@ impl SourceHeader for SyncHeader< ) } } + +impl FinalitySourceHeader for SyncHeader
{ + fn number(&self) -> Header::Number { + *self.0.number() + } + + fn is_mandatory(&self) -> bool { + find_grandpa_authorities_scheduled_change(&self.0).is_some() + } +} diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 6ea5e839d8ef0..08cf40c383521 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -26,12 +26,13 @@ bp-polkadot = { path = "../../primitives/polkadot" } bp-runtime = { path = "../../primitives/runtime" } bp-rialto = { path = "../../primitives/rialto" } bridge-runtime-common = { path = "../../bin/runtime-common" } +finality-relay = { path = "../finality-relay" } headers-relay = { path = "../headers-relay" } messages-relay = { path = "../messages-relay" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } +pallet-finality-verifier = { path = "../../modules/finality-verifier" } pallet-message-lane = { path = "../../modules/message-lane" } -pallet-substrate-bridge = { path = "../../modules/substrate" } relay-kusama-client = { path = "../kusama-client" } relay-millau-client = { path = "../millau-client" } relay-polkadot-client = { path = "../polkadot-client" } diff --git a/relays/substrate/src/finality_pipeline.rs b/relays/substrate/src/finality_pipeline.rs new file mode 100644 index 0000000000000..7ec592d5dee1a --- /dev/null +++ b/relays/substrate/src/finality_pipeline.rs @@ -0,0 +1,130 @@ +// 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 . + +//! Substrate-to-Substrate headers sync entrypoint. + +use crate::finality_target::SubstrateFinalityTarget; + +use async_trait::async_trait; +use codec::Encode; +use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; +use relay_substrate_client::{ + finality_source::{FinalitySource, Justification}, + BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, SyncHeader, +}; +use relay_utils::BlockNumberBase; +use std::{fmt::Debug, marker::PhantomData, time::Duration}; + +/// Default synchronization loop timeout. +const STALL_TIMEOUT: Duration = Duration::from_secs(120); +/// Default limit of recent finality proofs. +/// +/// Finality delay of 4096 blocks is unlikely to happen in practice in +/// Substrate+GRANDPA based chains (good to know). +const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; + +/// Headers sync pipeline for Substrate <-> Substrate relays. +#[async_trait] +pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { + /// Name of the runtime method that returns id of best finalized source header at target chain. + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; + + /// Signed transaction type. + type SignedTransaction: Send + Sync + Encode; + + /// Make submit header transaction. + async fn make_submit_finality_proof_transaction( + &self, + header: Self::Header, + proof: Self::FinalityProof, + ) -> Result; +} + +/// Substrate-to-Substrate finality proof pipeline. +#[derive(Debug, Clone)] +pub struct SubstrateFinalityToSubstrate { + /// Client for the target chain. + pub(crate) target_client: Client, + /// Data required to sign target chain transactions. + pub(crate) target_sign: TargetSign, + /// Unused generic arguments dump. + _marker: PhantomData, +} + +impl SubstrateFinalityToSubstrate { + /// Create new Substrate-to-Substrate headers pipeline. + pub fn new(target_client: Client, target_sign: TargetSign) -> Self { + SubstrateFinalityToSubstrate { + target_client, + target_sign, + _marker: Default::default(), + } + } +} + +impl FinalitySyncPipeline + for SubstrateFinalityToSubstrate +where + SourceChain: Clone + Chain + Debug, + BlockNumberOf: BlockNumberBase, + TargetChain: Clone + Chain + Debug, + TargetSign: Clone + Send + Sync + Debug, +{ + const SOURCE_NAME: &'static str = SourceChain::NAME; + const TARGET_NAME: &'static str = TargetChain::NAME; + + type Hash = HashOf; + type Number = BlockNumberOf; + type Header = SyncHeader; + type FinalityProof = Justification; +} + +/// Run Substrate-to-Substrate finality sync. +pub async fn run( + pipeline: P, + source_client: Client, + target_client: Client, + metrics_params: Option, +) where + P: SubstrateFinalitySyncPipeline< + Hash = HashOf, + Number = BlockNumberOf, + Header = SyncHeader, + FinalityProof = Justification, + >, + SourceChain: Clone + Chain, + BlockNumberOf: BlockNumberBase, + TargetChain: Clone + Chain, +{ + log::info!( + target: "bridge", + "Starting {} -> {} finality proof relay", + SourceChain::NAME, + TargetChain::NAME, + ); + + finality_relay::run( + FinalitySource::new(source_client), + SubstrateFinalityTarget::new(target_client, pipeline), + FinalitySyncParams { + tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), + recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, + stall_timeout: STALL_TIMEOUT, + }, + metrics_params, + futures::future::pending(), + ); +} diff --git a/relays/substrate/src/finality_target.rs b/relays/substrate/src/finality_target.rs new file mode 100644 index 0000000000000..18312556f9e17 --- /dev/null +++ b/relays/substrate/src/finality_target.rs @@ -0,0 +1,91 @@ +// Copyright 2019-2020 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 . + +//! Substrate client as Substrate finality proof target. The chain we connect to should have +//! runtime that implements `FinalityApi` to allow bridging with +//! chain. + +use crate::finality_pipeline::SubstrateFinalitySyncPipeline; + +use async_trait::async_trait; +use codec::{Decode, Encode}; +use finality_relay::TargetClient; +use futures::TryFutureExt; +use relay_substrate_client::{Chain, Client, Error as SubstrateError}; +use relay_utils::relay_loop::Client as RelayClient; +use sp_core::Bytes; + +/// Substrate client as Substrate finality target. +pub struct SubstrateFinalityTarget { + client: Client, + pipeline: P, +} + +impl SubstrateFinalityTarget { + /// Create new Substrate headers target. + pub fn new(client: Client, pipeline: P) -> Self { + SubstrateFinalityTarget { client, pipeline } + } +} + +impl Clone for SubstrateFinalityTarget { + fn clone(&self) -> Self { + SubstrateFinalityTarget { + client: self.client.clone(), + pipeline: self.pipeline.clone(), + } + } +} + +#[async_trait] +impl RelayClient for SubstrateFinalityTarget { + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + +#[async_trait] +impl TargetClient

for SubstrateFinalityTarget +where + C: Chain, + P::Number: Decode, + P::Hash: Decode, + P: SubstrateFinalitySyncPipeline, +{ + async fn best_finalized_source_block_number(&self) -> Result { + // we can't continue to relay finality if target node is out of sync, because + // it may have already received (some of) headers that we're going to relay + self.client.ensure_synced().await?; + + Ok(crate::messages_source::read_client_state::( + &self.client, + P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, + ) + .await? + .best_finalized_peer_at_best_self + .0) + } + + async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), SubstrateError> { + self.pipeline + .make_submit_finality_proof_transaction(header, proof) + .and_then(|tx| self.client.submit_extrinsic(Bytes(tx.encode()))) + .await + .map(drop) + } +} diff --git a/relays/substrate/src/headers_initialize.rs b/relays/substrate/src/headers_initialize.rs index 6b66a2e9bd7fb..2386f28f1b1ac 100644 --- a/relays/substrate/src/headers_initialize.rs +++ b/relays/substrate/src/headers_initialize.rs @@ -17,12 +17,12 @@ //! Initialize Substrate -> Substrate headers bridge. //! //! Initialization is a transaction that calls `initialize()` function of the -//! `pallet-substrate-bridge` pallet. This transaction brings initial header +//! `pallet-finality-verifier` pallet. This transaction brings initial header //! and authorities set from source to target chain. The headers sync starts //! with this header. use codec::Decode; -use pallet_substrate_bridge::InitializationData; +use pallet_finality_verifier::InitializationData; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, SetId as GrandpaAuthoritiesSetId}; @@ -132,10 +132,6 @@ async fn prepare_initialization_data( header: initial_header, authority_list: initial_authorities_set, set_id: initial_authorities_set_id.unwrap_or(0), - // There may be multiple scheduled changes, so on real chains we should select proper - // moment, when there's nothing scheduled. On ephemeral (temporary) chains, it is ok to - // start with genesis. - scheduled_change: None, is_halted: false, }) } diff --git a/relays/substrate/src/headers_maintain.rs b/relays/substrate/src/headers_maintain.rs deleted file mode 100644 index fb609a2ef0705..0000000000000 --- a/relays/substrate/src/headers_maintain.rs +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright 2019-2020 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 . - -//! Substrate-to-Substrate headers synchronization maintain procedure. -//! -//! Regular headers synchronization only depends on persistent justifications -//! that are generated when authorities set changes. This happens rarely on -//! real-word chains. So some other way to finalize headers is required. -//! -//! Full nodes are listening to GRANDPA messages, so they may have track authorities -//! votes on their own. They're returning both persistent and ephemeral justifications -//! (justifications that are not stored in the database and not broadcasted over network) -//! throught `grandpa_subscribeJustifications` RPC subscription. -//! -//! The idea of this maintain procedure is that when we see justification that 'improves' -//! best finalized header on the target chain, we submit this justification to the target -//! node. - -use crate::headers_pipeline::SubstrateHeadersSyncPipeline; - -use async_std::sync::{Arc, Mutex}; -use async_trait::async_trait; -use codec::{Decode, Encode}; -use futures::future::{poll_fn, FutureExt, TryFutureExt}; -use headers_relay::{ - sync::HeadersSync, - sync_loop::SyncMaintain, - sync_types::{HeaderIdOf, HeaderStatus}, -}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError, JustificationsSubscription}; -use relay_utils::HeaderId; -use sp_core::Bytes; -use sp_runtime::{traits::Header as HeaderT, Justification}; -use std::{collections::VecDeque, marker::PhantomData, task::Poll}; - -/// Substrate-to-Substrate headers synchronization maintain procedure. -pub struct SubstrateHeadersToSubstrateMaintain -{ - pipeline: P, - source_client: Client, - target_client: Client, - justifications: Arc>>, - _marker: PhantomData, -} - -/// Future and already received justifications from the source chain. -struct Justifications { - /// Justifications stream. None if it hasn't been initialized yet, or it has been dropped - /// by the rpc library. - stream: Option, - /// Justifications that we have read from the stream but have not sent to the - /// target node, because their targets were still not synced. - queue: VecDeque<(HeaderIdOf

, Justification)>, -} - -impl - SubstrateHeadersToSubstrateMaintain -{ - /// Create new maintain procedure. - pub async fn new(pipeline: P, source_client: Client, target_client: Client) -> Self { - let justifications = subscribe_justifications(&source_client).await; - SubstrateHeadersToSubstrateMaintain { - pipeline, - source_client, - target_client, - justifications: Arc::new(Mutex::new(Justifications { - stream: justifications, - queue: VecDeque::new(), - })), - _marker: Default::default(), - } - } -} - -#[async_trait] -impl Clone - for SubstrateHeadersToSubstrateMaintain -{ - fn clone(&self) -> Self { - SubstrateHeadersToSubstrateMaintain { - pipeline: self.pipeline.clone(), - source_client: self.source_client.clone(), - target_client: self.target_client.clone(), - justifications: self.justifications.clone(), - _marker: Default::default(), - } - } -} - -#[async_trait] -impl SyncMaintain

for SubstrateHeadersToSubstrateMaintain -where - SourceChain: Chain, - ::Number: Into, - ::Hash: Into, - TargetChain: Chain, - P::Number: Decode, - P::Hash: Decode, - P: SubstrateHeadersSyncPipeline, -{ - async fn maintain(&self, sync: &mut HeadersSync

) { - // lock justifications before doing anything else - let mut justifications = match self.justifications.try_lock() { - Some(justifications) => justifications, - None => { - // this should never happen, as we use single-thread executor - log::warn!(target: "bridge", "Failed to acquire {} justifications lock", P::SOURCE_NAME); - return; - } - }; - - // we need to read best finalized header from the target node to be able to - // choose justification to submit - let best_finalized = match best_finalized_header_id::(&self.target_client).await { - Ok(best_finalized) => best_finalized, - Err(error) => { - log::warn!( - target: "bridge", - "Failed to read best finalized {} block from maintain: {:?}", - P::SOURCE_NAME, - error, - ); - return; - } - }; - - log::debug!( - target: "bridge", - "Read best finalized {} block from {}: {:?}", - P::SOURCE_NAME, - P::TARGET_NAME, - best_finalized, - ); - - // Select justification to submit to the target node. We're submitting at most one justification - // on every maintain call. So maintain rate directly affects finalization rate. - let (resubscribe, justification_to_submit) = poll_fn(|context| { - // read justifications from the stream and push to the queue - let resubscribe = !justifications.read_from_stream::(context); - - // remove all obsolete justifications from the queue - remove_obsolete::

(&mut justifications.queue, best_finalized); - - // select justification to submit - Poll::Ready((resubscribe, select_justification(&mut justifications.queue, sync))) - }) - .await; - - // if justifications subscription has been dropped, resubscribe - if resubscribe { - justifications.stream = subscribe_justifications(&self.source_client).await; - } - - // finally - submit selected justification - if let Some((target, justification)) = justification_to_submit { - let submit_result = self - .pipeline - .make_complete_header_transaction(target, justification) - .and_then(|tx| self.target_client.submit_extrinsic(Bytes(tx.encode()))) - .await; - - match submit_result { - Ok(_) => log::debug!( - target: "bridge", - "Submitted justification received over {} subscription. Target: {:?}", - P::SOURCE_NAME, - target, - ), - Err(error) => log::warn!( - target: "bridge", - "Failed to submit justification received over {} subscription for {:?}: {:?}", - P::SOURCE_NAME, - target, - error, - ), - } - } - } -} - -impl

Justifications

-where - P::Number: Decode, - P::Hash: Decode, - P: SubstrateHeadersSyncPipeline, -{ - /// Read justifications from the subscription stream without blocking. - /// - /// Returns `true` if justifications stream is still readable and `false` if it has been - /// dropped by the RPC crate && we need to resubscribe. - #[must_use] - fn read_from_stream<'a, SourceHeader>(&mut self, context: &mut std::task::Context<'a>) -> bool - where - SourceHeader: HeaderT, - SourceHeader::Number: Into, - SourceHeader::Hash: Into, - { - let stream = match self.stream.as_mut() { - Some(stream) => stream, - None => return false, - }; - - loop { - let maybe_next_justification = stream.next(); - futures::pin_mut!(maybe_next_justification); - - let maybe_next_justification = maybe_next_justification.poll_unpin(context); - let justification = match maybe_next_justification { - Poll::Ready(justification) => justification, - Poll::Pending => return true, - }; - - let justification = match justification { - Some(justification) => justification, - None => { - log::warn!( - target: "bridge", - "{} justifications stream has been dropped. Will be trying to resubscribe", - P::SOURCE_NAME, - ); - - return false; - } - }; - - // decode justification target - let target = bp_header_chain::justification::decode_justification_target::(&justification); - let target = match target { - Ok((target_hash, target_number)) => HeaderId(target_number.into(), target_hash.into()), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to decode justification from {} subscription: {:?}", - P::SOURCE_NAME, - error, - ); - continue; - } - }; - - log::debug!( - target: "bridge", - "Received {} justification over subscription. Target: {:?}", - P::SOURCE_NAME, - target, - ); - - self.queue.push_back((target, justification.0)); - } - } -} - -/// Clean queue of all justifications that are justifying already finalized blocks. -fn remove_obsolete( - queue: &mut VecDeque<(HeaderIdOf

, Justification)>, - best_finalized: HeaderIdOf

, -) { - while queue - .front() - .map(|(target, _)| target.0 <= best_finalized.0) - .unwrap_or(false) - { - queue.pop_front(); - } -} - -/// Select appropriate justification that would improve best finalized block on target node. -/// -/// It is assumed that the selected justification will be submitted to the target node. The -/// justification itself and all preceeding justifications are removed from the queue. -fn select_justification

( - queue: &mut VecDeque<(HeaderIdOf

, Justification)>, - sync: &mut HeadersSync

, -) -> Option<(HeaderIdOf

, Justification)> -where - P: SubstrateHeadersSyncPipeline, -{ - let mut selected_justification = None; - while let Some((target, justification)) = queue.pop_front() { - // if we're waiting for this justification, report it - if sync.headers().requires_completion_data(&target) { - sync.headers_mut().completion_response(&target, Some(justification)); - // we won't submit previous justifications as we going to submit justification for - // next header - selected_justification = None; - // we won't submit next justifications as we need to submit previous justifications - // first - break; - } - - // if we know that the header is already synced (it is known to the target node), let's - // select it for submission. We still may select better justification on the next iteration. - if sync.headers().status(&target) == HeaderStatus::Synced { - selected_justification = Some((target, justification)); - continue; - } - - // finally - return justification back to the queue - queue.push_back((target, justification)); - break; - } - - selected_justification -} - -/// Returns best finalized source header on the target chain. -async fn best_finalized_header_id(client: &Client) -> Result, SubstrateError> -where - P: SubstrateHeadersSyncPipeline, - P::Number: Decode, - P::Hash: Decode, - C: Chain, -{ - let call = P::FINALIZED_BLOCK_METHOD.into(); - let data = Bytes(Vec::new()); - - let encoded_response = client.state_call(call, data, None).await?; - let decoded_response: (P::Number, P::Hash) = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); - Ok(best_header_id) -} - -/// Subscribe to justifications stream at source node. -async fn subscribe_justifications(client: &Client) -> Option { - match client.subscribe_justifications().await { - Ok(source_justifications) => { - log::debug!( - target: "bridge", - "Successfully (re)subscribed to {} justifications", - C::NAME, - ); - - Some(source_justifications) - } - Err(error) => { - log::warn!( - target: "bridge", - "Failed to subscribe to {} justifications: {:?}", - C::NAME, - error, - ); - - None - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::headers_pipeline::sync_params; - use crate::millau_headers_to_rialto::MillauHeadersToRialto; - - fn parent_hash(index: u8) -> bp_millau::Hash { - if index == 1 { - Default::default() - } else { - header(index - 1).hash() - } - } - - fn header_hash(index: u8) -> bp_millau::Hash { - header(index).hash() - } - - fn header(index: u8) -> bp_millau::Header { - bp_millau::Header::new( - index as _, - Default::default(), - Default::default(), - parent_hash(index), - Default::default(), - ) - } - - #[test] - fn obsolete_justifications_are_removed() { - let mut queue = vec![ - (HeaderId(1, header_hash(1)), vec![1]), - (HeaderId(2, header_hash(2)), vec![2]), - (HeaderId(3, header_hash(3)), vec![3]), - ] - .into_iter() - .collect(); - - remove_obsolete::(&mut queue, HeaderId(2, header_hash(2))); - - assert_eq!( - queue, - vec![(HeaderId(3, header_hash(3)), vec![3])] - .into_iter() - .collect::>(), - ); - } - - #[test] - fn latest_justification_is_selected() { - let mut queue = vec![ - (HeaderId(1, header_hash(1)), vec![1]), - (HeaderId(2, header_hash(2)), vec![2]), - (HeaderId(3, header_hash(3)), vec![3]), - ] - .into_iter() - .collect(); - let mut sync = HeadersSync::::new(sync_params()); - sync.headers_mut().header_response(header(1).into()); - sync.headers_mut().header_response(header(2).into()); - sync.headers_mut().header_response(header(3).into()); - sync.target_best_header_response(HeaderId(2, header_hash(2))); - - assert_eq!( - select_justification(&mut queue, &mut sync), - Some((HeaderId(2, header_hash(2)), vec![2])), - ); - } - - #[test] - fn required_justification_is_reported() { - let mut queue = vec![ - (HeaderId(1, header_hash(1)), vec![1]), - (HeaderId(2, header_hash(2)), vec![2]), - (HeaderId(3, header_hash(3)), vec![3]), - ] - .into_iter() - .collect(); - let mut sync = HeadersSync::::new(sync_params()); - sync.headers_mut().header_response(header(1).into()); - sync.headers_mut().header_response(header(2).into()); - sync.headers_mut().header_response(header(3).into()); - sync.headers_mut() - .incomplete_headers_response(vec![HeaderId(2, header_hash(2))].into_iter().collect()); - sync.target_best_header_response(HeaderId(2, header_hash(2))); - - assert_eq!(sync.headers_mut().header_to_complete(), None,); - - assert_eq!(select_justification(&mut queue, &mut sync), None,); - - assert_eq!( - sync.headers_mut().header_to_complete(), - Some((HeaderId(2, header_hash(2)), &vec![2])), - ); - } -} diff --git a/relays/substrate/src/headers_pipeline.rs b/relays/substrate/src/headers_pipeline.rs deleted file mode 100644 index 541a613735c52..0000000000000 --- a/relays/substrate/src/headers_pipeline.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2019-2020 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 . - -//! Substrate-to-Substrate headers sync entrypoint. - -use crate::{headers_maintain::SubstrateHeadersToSubstrateMaintain, headers_target::SubstrateHeadersTarget}; - -use async_trait::async_trait; -use codec::Encode; -use headers_relay::{ - sync::{HeadersSyncParams, TargetTransactionMode}, - sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, -}; -use relay_substrate_client::{ - headers_source::HeadersSource, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, -}; -use relay_utils::BlockNumberBase; -use sp_runtime::Justification; -use std::marker::PhantomData; - -/// Headers sync pipeline for Substrate <-> Substrate relays. -#[async_trait] -pub trait SubstrateHeadersSyncPipeline: HeadersSyncPipeline { - /// Name of the `best_block` runtime method. - const BEST_BLOCK_METHOD: &'static str; - /// Name of the `finalized_block` runtime method. - const FINALIZED_BLOCK_METHOD: &'static str; - /// Name of the `is_known_block` runtime method. - const IS_KNOWN_BLOCK_METHOD: &'static str; - /// Name of the `incomplete_headers` runtime method. - const INCOMPLETE_HEADERS_METHOD: &'static str; - - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; - - /// Make submit header transaction. - async fn make_submit_header_transaction( - &self, - header: QueuedHeader, - ) -> Result; - - /// Make completion transaction for the header. - async fn make_complete_header_transaction( - &self, - id: HeaderIdOf, - completion: Justification, - ) -> Result; -} - -/// Substrate-to-Substrate headers pipeline. -#[derive(Debug, Clone)] -pub struct SubstrateHeadersToSubstrate { - /// Client for the target chain. - pub(crate) target_client: Client, - /// Data required to sign target chain transactions. - pub(crate) target_sign: TargetSign, - /// Unused generic arguments dump. - _marker: PhantomData<(SourceChain, SourceSyncHeader)>, -} - -impl - SubstrateHeadersToSubstrate -{ - /// Create new Substrate-to-Substrate headers pipeline. - pub fn new(target_client: Client, target_sign: TargetSign) -> Self { - SubstrateHeadersToSubstrate { - target_client, - target_sign, - _marker: Default::default(), - } - } -} - -impl HeadersSyncPipeline - for SubstrateHeadersToSubstrate -where - SourceChain: Clone + Chain, - BlockNumberOf: BlockNumberBase, - SourceSyncHeader: - SourceHeader, BlockNumberOf> + std::ops::Deref, - TargetChain: Clone + Chain, - TargetSign: Clone + Send + Sync, -{ - const SOURCE_NAME: &'static str = SourceChain::NAME; - const TARGET_NAME: &'static str = TargetChain::NAME; - - type Hash = HashOf; - type Number = BlockNumberOf; - type Header = SourceSyncHeader; - type Extra = (); - type Completion = Justification; - - fn estimate_size(source: &QueuedHeader) -> usize { - source.header().encode().len() - } -} - -/// Return sync parameters for Substrate-to-Substrate headers sync. -pub fn sync_params() -> HeadersSyncParams { - HeadersSyncParams { - max_future_headers_to_download: 32, - max_headers_in_submitted_status: 8, - max_headers_in_single_submit: 1, - max_headers_size_in_single_submit: 1024 * 1024, - prune_depth: 256, - target_tx_mode: TargetTransactionMode::Signed, - } -} - -/// Run Substrate-to-Substrate headers sync. -pub async fn run( - pipeline: P, - source_client: Client, - target_client: Client, - metrics_params: Option, -) where - P: SubstrateHeadersSyncPipeline< - Hash = HashOf, - Number = BlockNumberOf, - Completion = Justification, - Extra = (), - >, - P::Header: SourceHeader, BlockNumberOf>, - SourceChain: Clone + Chain, - SourceChain::Header: Into, - BlockNumberOf: BlockNumberBase, - TargetChain: Clone + Chain, -{ - let sync_maintain = SubstrateHeadersToSubstrateMaintain::<_, SourceChain, _>::new( - pipeline.clone(), - source_client.clone(), - target_client.clone(), - ) - .await; - - log::info!( - target: "bridge", - "Starting {} -> {} headers relay", - SourceChain::NAME, - TargetChain::NAME, - ); - - headers_relay::sync_loop::run( - HeadersSource::new(source_client), - SourceChain::AVERAGE_BLOCK_INTERVAL, - SubstrateHeadersTarget::new(target_client, pipeline), - TargetChain::AVERAGE_BLOCK_INTERVAL, - sync_maintain, - sync_params(), - metrics_params, - futures::future::pending(), - ); -} diff --git a/relays/substrate/src/headers_target.rs b/relays/substrate/src/headers_target.rs deleted file mode 100644 index 2b5f63a7feae3..0000000000000 --- a/relays/substrate/src/headers_target.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2019-2020 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 . - -//! Substrate client as Substrate headers target. The chain we connect to should have -//! runtime that implements `HeaderApi` to allow bridging with -//! chain. - -use crate::headers_pipeline::SubstrateHeadersSyncPipeline; - -use async_trait::async_trait; -use codec::{Decode, Encode}; -use futures::TryFutureExt; -use headers_relay::{ - sync_loop::TargetClient, - sync_types::{HeaderIdOf, QueuedHeader, SubmittedHeaders}, -}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError}; -use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; -use sp_core::Bytes; -use sp_runtime::Justification; -use std::collections::HashSet; - -/// Substrate client as Substrate headers target. -pub struct SubstrateHeadersTarget { - client: Client, - pipeline: P, -} - -impl SubstrateHeadersTarget { - /// Create new Substrate headers target. - pub fn new(client: Client, pipeline: P) -> Self { - SubstrateHeadersTarget { client, pipeline } - } -} - -impl Clone for SubstrateHeadersTarget { - fn clone(&self) -> Self { - SubstrateHeadersTarget { - client: self.client.clone(), - pipeline: self.pipeline.clone(), - } - } -} - -#[async_trait] -impl RelayClient for SubstrateHeadersTarget { - type Error = SubstrateError; - - async fn reconnect(&mut self) -> Result<(), SubstrateError> { - self.client.reconnect().await - } -} - -#[async_trait] -impl TargetClient

for SubstrateHeadersTarget -where - C: Chain, - P::Number: Decode, - P::Hash: Decode + Encode, - P: SubstrateHeadersSyncPipeline, -{ - async fn best_header_id(&self) -> Result, SubstrateError> { - // we can't continue to relay headers if target node is out of sync, because - // it may have already received (some of) headers that we're going to relay - self.client.ensure_synced().await?; - - let call = P::BEST_BLOCK_METHOD.into(); - let data = Bytes(Vec::new()); - - let encoded_response = self.client.state_call(call, data, None).await?; - let decoded_response: Vec<(P::Number, P::Hash)> = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - - // If we parse an empty list of headers it means that bridge pallet has not been initalized - // yet. Otherwise we expect to always have at least one header. - decoded_response - .last() - .ok_or(SubstrateError::UninitializedBridgePallet) - .map(|(num, hash)| HeaderId(*num, *hash)) - } - - async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), SubstrateError> { - let call = P::IS_KNOWN_BLOCK_METHOD.into(); - let data = Bytes(id.1.encode()); - - let encoded_response = self.client.state_call(call, data, None).await?; - let is_known_block: bool = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - - Ok((id, is_known_block)) - } - - async fn submit_headers( - &self, - mut headers: Vec>, - ) -> SubmittedHeaders, SubstrateError> { - debug_assert_eq!( - headers.len(), - 1, - "Substrate pallet only supports single header / transaction" - ); - - let header = headers.remove(0); - let id = header.id(); - let submit_transaction_result = self - .pipeline - .make_submit_header_transaction(header) - .and_then(|tx| self.client.submit_extrinsic(Bytes(tx.encode()))) - .await; - - match submit_transaction_result { - Ok(_) => SubmittedHeaders { - submitted: vec![id], - incomplete: Vec::new(), - rejected: Vec::new(), - fatal_error: None, - }, - Err(error) => SubmittedHeaders { - submitted: Vec::new(), - incomplete: Vec::new(), - rejected: vec![id], - fatal_error: Some(error), - }, - } - } - - async fn incomplete_headers_ids(&self) -> Result>, SubstrateError> { - let call = P::INCOMPLETE_HEADERS_METHOD.into(); - let data = Bytes(Vec::new()); - - let encoded_response = self.client.state_call(call, data, None).await?; - let decoded_response: Vec<(P::Number, P::Hash)> = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - - let incomplete_headers = decoded_response - .into_iter() - .map(|(number, hash)| HeaderId(number, hash)) - .collect(); - Ok(incomplete_headers) - } - - async fn complete_header( - &self, - id: HeaderIdOf

, - completion: Justification, - ) -> Result, SubstrateError> { - let tx = self.pipeline.make_complete_header_transaction(id, completion).await?; - self.client.submit_extrinsic(Bytes(tx.encode())).await?; - Ok(id) - } - - async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), SubstrateError> { - Ok((header.id(), false)) - } -} diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 3a3c3620aeb25..722f850d89ef7 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -38,10 +38,9 @@ pub type MillauClient = relay_substrate_client::Client; pub type RialtoClient = relay_substrate_client::Client; mod cli; +mod finality_pipeline; +mod finality_target; mod headers_initialize; -mod headers_maintain; -mod headers_pipeline; -mod headers_target; mod messages_lane; mod messages_source; mod messages_target; @@ -101,7 +100,7 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { &rialto_sign.signer, rialto_signer_next_index, rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::BridgeMillauCall::initialize(initialization_data).into(), + rialto_runtime::FinalityBridgeMillauCall::initialize(initialization_data).into(), )) .into(), ) @@ -137,7 +136,7 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { &millau_sign.signer, millau_signer_next_index, millau_runtime::SudoCall::sudo(Box::new( - millau_runtime::BridgeRialtoCall::initialize(initialization_data).into(), + millau_runtime::FinalityBridgeRialtoCall::initialize(initialization_data).into(), )) .into(), ) diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index e5ac8880c845d..db12be361f653 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 8b77e71657a09..7b9df18d8a92c 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -17,70 +17,52 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::{ - headers_pipeline::{SubstrateHeadersSyncPipeline, SubstrateHeadersToSubstrate}, + finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}, MillauClient, RialtoClient, }; use async_trait::async_trait; -use bp_millau::{ - BEST_MILLAU_BLOCKS_METHOD, FINALIZED_MILLAU_BLOCK_METHOD, INCOMPLETE_MILLAU_HEADERS_METHOD, - IS_KNOWN_MILLAU_BLOCK_METHOD, -}; -use headers_relay::sync_types::QueuedHeader; -use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SyncHeader as MillauSyncHeader}; -use relay_rialto_client::{BridgeMillauCall, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Error as SubstrateError, TransactionSignScheme}; +use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; +use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{finality_source::Justification, Error as SubstrateError, TransactionSignScheme}; use sp_core::Pair; -use sp_runtime::Justification; -/// Millau-to-Rialto headers sync pipeline. -pub(crate) type MillauHeadersToRialto = - SubstrateHeadersToSubstrate; -/// Millau header in-the-queue. -type QueuedMillauHeader = QueuedHeader; +/// Millau-to-Rialto finality sync pipeline. +pub(crate) type MillauFinalityToRialto = SubstrateFinalityToSubstrate; #[async_trait] -impl SubstrateHeadersSyncPipeline for MillauHeadersToRialto { - const BEST_BLOCK_METHOD: &'static str = BEST_MILLAU_BLOCKS_METHOD; - const FINALIZED_BLOCK_METHOD: &'static str = FINALIZED_MILLAU_BLOCK_METHOD; - const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_MILLAU_BLOCK_METHOD; - const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_MILLAU_HEADERS_METHOD; +impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; type SignedTransaction = ::SignedTransaction; - async fn make_submit_header_transaction( - &self, - header: QueuedMillauHeader, - ) -> Result { - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; - let call = BridgeMillauCall::import_signed_header(header.header().clone().into_inner()).into(); - let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); - Ok(transaction) - } - - async fn make_complete_header_transaction( + async fn make_submit_finality_proof_transaction( &self, - id: MillauHeaderId, - completion: Justification, + header: MillauSyncHeader, + proof: Justification, ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = BridgeMillauCall::finalize_header(id.1, completion).into(); + let call = rialto_runtime::FinalityBridgeMillauCall::submit_finality_proof( + header.into_inner(), + proof.into_inner(), + (), + ) + .into(); let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } } -/// Run Millau-to-Rialto headers sync. +/// Run Millau-to-Rialto finality sync. pub async fn run( millau_client: MillauClient, rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, metrics_params: Option, ) { - crate::headers_pipeline::run( - MillauHeadersToRialto::new(rialto_client.clone(), rialto_sign), + crate::finality_pipeline::run( + MillauFinalityToRialto::new(rialto_client.clone(), rialto_sign), millau_client, rialto_client, metrics_params, diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index ebab5cfb381d3..ecd59e146fa13 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -51,8 +51,8 @@ impl SubstrateMessageLane for MillauMessagesToRialto { bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; type SourceSignedTransaction = ::SignedTransaction; type TargetSignedTransaction = ::SignedTransaction; diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index 3a13c6e148c63..6560d83c8c265 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -17,69 +17,52 @@ //! Rialto-to-Millau headers sync entrypoint. use crate::{ - headers_pipeline::{SubstrateHeadersSyncPipeline, SubstrateHeadersToSubstrate}, + finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}, MillauClient, RialtoClient, }; use async_trait::async_trait; -use bp_rialto::{ - BEST_RIALTO_BLOCKS_METHOD, FINALIZED_RIALTO_BLOCK_METHOD, INCOMPLETE_RIALTO_HEADERS_METHOD, - IS_KNOWN_RIALTO_BLOCK_METHOD, -}; -use headers_relay::sync_types::QueuedHeader; -use relay_millau_client::{BridgeRialtoCall, Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Error as SubstrateError, TransactionSignScheme}; +use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; +use relay_substrate_client::{finality_source::Justification, Error as SubstrateError, TransactionSignScheme}; use sp_core::Pair; -use sp_runtime::Justification; -/// Rialto-to-Millau headers sync pipeline. -type RialtoHeadersToMillau = SubstrateHeadersToSubstrate; -/// Rialto header in-the-queue. -type QueuedRialtoHeader = QueuedHeader; +/// Rialto-to-Millau finality sync pipeline. +pub(crate) type RialtoFinalityToMillau = SubstrateFinalityToSubstrate; #[async_trait] -impl SubstrateHeadersSyncPipeline for RialtoHeadersToMillau { - const BEST_BLOCK_METHOD: &'static str = BEST_RIALTO_BLOCKS_METHOD; - const FINALIZED_BLOCK_METHOD: &'static str = FINALIZED_RIALTO_BLOCK_METHOD; - const IS_KNOWN_BLOCK_METHOD: &'static str = IS_KNOWN_RIALTO_BLOCK_METHOD; - const INCOMPLETE_HEADERS_METHOD: &'static str = INCOMPLETE_RIALTO_HEADERS_METHOD; +impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; type SignedTransaction = ::SignedTransaction; - async fn make_submit_header_transaction( - &self, - header: QueuedRialtoHeader, - ) -> Result { - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; - let call = BridgeRialtoCall::import_signed_header(header.header().clone().into_inner()).into(); - let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); - Ok(transaction) - } - - async fn make_complete_header_transaction( + async fn make_submit_finality_proof_transaction( &self, - id: RialtoHeaderId, - completion: Justification, + header: RialtoSyncHeader, + proof: Justification, ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = BridgeRialtoCall::finalize_header(id.1, completion).into(); + let call = millau_runtime::FinalityBridgeRialtoCall::submit_finality_proof( + header.into_inner(), + proof.into_inner(), + (), + ) + .into(); let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); Ok(transaction) } } -/// Run Rialto-to-Millau headers sync. +/// Run Rialto-to-Millau finality sync. pub async fn run( rialto_client: RialtoClient, millau_client: MillauClient, millau_sign: MillauSigningParams, metrics_params: Option, ) { - crate::headers_pipeline::run( - RialtoHeadersToMillau::new(millau_client.clone(), millau_sign), + crate::finality_pipeline::run( + RialtoFinalityToMillau::new(millau_client.clone(), millau_sign), rialto_client, millau_client, metrics_params, diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 1c11a111413c9..07af9ce82866d 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -51,8 +51,8 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::FINALIZED_RIALTO_BLOCK_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::FINALIZED_MILLAU_BLOCK_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; type SourceSignedTransaction = ::SignedTransaction; type TargetSignedTransaction = ::SignedTransaction; From 8b5973f752487d374111b8e2b6d76323177fc8b0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 8 Mar 2021 13:59:58 +0100 Subject: [PATCH 0366/1210] Bump serde from 1.0.123 to 1.0.124 (#801) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.123 to 1.0.124. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.123...v1.0.124) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 3173294bec793..58ce4f127a085 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" -serde = { version = "1.0.123", optional = true, features = ["derive"] } +serde = { version = "1.0.124", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 712092ea06642..812af7ceade47 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } -serde = { version = "1.0.123", optional = true, features = ["derive"] } +serde = { version = "1.0.124", optional = true, features = ["derive"] } # Bridge dependencies From 01caa0f780530e90a2dce298042a734b2ca45fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 8 Mar 2021 17:39:15 +0100 Subject: [PATCH 0367/1210] bridges: fix random_seed (#797) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: André Silva --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index ee6f1d483b0ea..0b6bf9f8ea214 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -459,7 +459,7 @@ impl_runtime_apis! { } fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed() + RandomnessCollectiveFlip::random_seed().0.into() } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9f289d2c87f79..259c283cf5302 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -570,7 +570,7 @@ impl_runtime_apis! { } fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed() + RandomnessCollectiveFlip::random_seed().0.into() } } From b32c5c3145515501b755e619dad303e4a5b3a7ae Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 8 Mar 2021 11:55:51 -0500 Subject: [PATCH 0368/1210] Bump Substrate (#796) * Bump Substrate to version used by Polkadot (`5f056830`) * Use `log` crate for runtime logging See https://github.com/paritytech/substrate/pull/8128/ for more info. * Stop using return value from `execute_block` * Update test weight --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/Cargo.toml | 2 ++ bin/rialto/runtime/src/exchange.rs | 6 ++-- bin/rialto/runtime/src/lib.rs | 8 +++--- modules/call-dispatch/Cargo.toml | 2 ++ modules/call-dispatch/src/lib.rs | 24 ++++++++-------- modules/currency-exchange/Cargo.toml | 2 ++ modules/currency-exchange/src/lib.rs | 4 +-- modules/ethereum/Cargo.toml | 2 ++ modules/ethereum/src/lib.rs | 28 +++++++++--------- modules/ethereum/src/verification.rs | 4 +-- modules/finality-verifier/Cargo.toml | 2 ++ modules/finality-verifier/src/lib.rs | 18 ++++++------ modules/message-lane/Cargo.toml | 2 ++ modules/message-lane/src/instant_payments.rs | 4 +-- modules/message-lane/src/lib.rs | 30 ++++++++++---------- modules/substrate/Cargo.toml | 2 ++ modules/substrate/src/lib.rs | 22 +++++++------- modules/substrate/src/verifier.rs | 4 +-- 19 files changed, 91 insertions(+), 77 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 0b6bf9f8ea214..7c5d93ca2e15e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -424,7 +424,7 @@ impl_runtime_apis! { } fn execute_block(block: Block) { - Executive::execute_block(block) + Executive::execute_block(block); } fn initialize_block(header: &::Header) { diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 812af7ceade47..d69e241870b4f 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } +log = { version = "0.4.14", default-features = false } serde = { version = "1.0.124", optional = true, features = ["derive"] } # Bridge dependencies @@ -86,6 +87,7 @@ std = [ "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", + "log/std", "pallet-aura/std", "pallet-balances/std", "pallet-bridge-eth-poa/std", diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index 926d9595372a0..ac67a6c446b1a 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -81,7 +81,7 @@ impl MaybeLockFundsTransaction for EthTransaction { // we only accept transactions sending funds directly to the pre-configured address if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Failed to parse fund locks transaction. Invalid peer recipient: {:?}", tx.unsigned.to, @@ -94,7 +94,7 @@ impl MaybeLockFundsTransaction for EthTransaction { match tx.unsigned.payload.len() { 32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.unsigned.payload), len => { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Failed to parse fund locks transaction. Invalid recipient length: {}", len, @@ -106,7 +106,7 @@ impl MaybeLockFundsTransaction for EthTransaction { let amount = tx.unsigned.value.low_u128(); if tx.unsigned.value != amount.into() { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Failed to parse fund locks transaction. Invalid amount: {}", tx.unsigned.value, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 259c283cf5302..eaac1f5a61d7f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -290,7 +290,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { // - deposited != 0: (should never happen in practice) deposit has been partially completed match deposited_amount { _ if deposited_amount == amount => { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Deposited {} to {:?}", amount, @@ -300,7 +300,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { Ok(()) } _ if deposited_amount == 0 => { - frame_support::debug::error!( + log::error!( target: "runtime", "Deposit of {} to {:?} has failed", amount, @@ -310,7 +310,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { Err(bp_currency_exchange::Error::DepositFailed) } _ => { - frame_support::debug::error!( + log::error!( target: "runtime", "Deposit of {} to {:?} has partially competed. {} has been deposited", amount, @@ -535,7 +535,7 @@ impl_runtime_apis! { } fn execute_block(block: Block) { - Executive::execute_block(block) + Executive::execute_block(block); } fn initialize_block(header: &::Header) { diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index 9b4c0bfeea443..99c7962dc34c8 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } # Bridge dependencies @@ -33,6 +34,7 @@ std = [ "bp-runtime/std", "frame-support/std", "frame-system/std", + "log/std", "sp-core/std", "sp-runtime/std", "sp-std/std", diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 87f7238d9a62b..3f6bf632a2b1a 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -202,7 +202,7 @@ impl, I: Instance> MessageDispatch for Module { let message = match message { Ok(message) => message, Err(_) => { - frame_support::debug::trace!("Message {:?}/{:?}: rejected before actual dispatch", bridge, id); + log::trace!("Message {:?}/{:?}: rejected before actual dispatch", bridge, id); Self::deposit_event(RawEvent::MessageRejected(bridge, id)); return; } @@ -212,7 +212,7 @@ impl, I: Instance> MessageDispatch for Module { // (we want it to be the same, because otherwise we may decode Call improperly) let expected_version = ::Version::get().spec_version; if message.spec_version != expected_version { - frame_support::debug::trace!( + log::trace!( "Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}", bridge, id, @@ -232,7 +232,7 @@ impl, I: Instance> MessageDispatch for Module { let call = match message.call.into() { Ok(call) => call, Err(_) => { - frame_support::debug::trace!("Failed to decode Call from message {:?}/{:?}", bridge, id,); + log::trace!("Failed to decode Call from message {:?}/{:?}", bridge, id,); Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id)); return; } @@ -243,7 +243,7 @@ impl, I: Instance> MessageDispatch for Module { CallOrigin::SourceRoot => { let hex_id = derive_account_id::(bridge, SourceAccount::Root); let target_id = T::AccountIdConverter::convert(hex_id); - frame_support::debug::trace!("Root Account: {:?}", &target_id); + log::trace!("Root Account: {:?}", &target_id); target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { @@ -251,7 +251,7 @@ impl, I: Instance> MessageDispatch for Module { let target_account = target_public.into_account(); if !target_signature.verify(&digest[..], &target_account) { - frame_support::debug::trace!( + log::trace!( "Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}", bridge, id, @@ -262,20 +262,20 @@ impl, I: Instance> MessageDispatch for Module { return; } - frame_support::debug::trace!("Target Account: {:?}", &target_account); + log::trace!("Target Account: {:?}", &target_account); target_account } CallOrigin::SourceAccount(source_account_id) => { let hex_id = derive_account_id(bridge, SourceAccount::Account(source_account_id)); let target_id = T::AccountIdConverter::convert(hex_id); - frame_support::debug::trace!("Source Account: {:?}", &target_id); + log::trace!("Source Account: {:?}", &target_id); target_id } }; // filter the call if !T::CallFilter::filter(&call) { - frame_support::debug::trace!( + log::trace!( "Message {:?}/{:?}: the call ({:?}) is rejected by filter", bridge, id, @@ -291,7 +291,7 @@ impl, I: Instance> MessageDispatch for Module { let dispatch_info = call.get_dispatch_info(); let expected_weight = dispatch_info.weight; if message.weight < expected_weight { - frame_support::debug::trace!( + log::trace!( "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", bridge, id, @@ -310,11 +310,11 @@ impl, I: Instance> MessageDispatch for Module { // finally dispatch message let origin = RawOrigin::Signed(origin_account).into(); - frame_support::debug::trace!("Message being dispatched is: {:?}", &call); + log::trace!("Message being dispatched is: {:?}", &call); let dispatch_result = call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); - frame_support::debug::trace!( + log::trace!( "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", bridge, id, @@ -606,7 +606,7 @@ mod tests { vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageWeightMismatch( - bridge, id, 1279000, 0, + bridge, id, 1345000, 0, )), topics: vec![], }], diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index f92eb2ca7b66f..f12fa1fc8d52a 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -36,6 +37,7 @@ std = [ "frame-benchmarking/std", "frame-support/std", "frame-system/std", + "log/std", "serde", "sp-runtime/std", "sp-std/std", diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 7c7d7e4a4d0fc..bd48e6c8a205d 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -113,7 +113,7 @@ decl_module! { // reward submitter for providing valid message T::OnTransactionSubmitted::on_valid_transaction_submitted(submitter); - frame_support::debug::trace!( + log::trace!( target: "runtime", "Completed currency exchange: {:?}", deposit.transfer_id, @@ -138,7 +138,7 @@ impl, I: Instance> Module { proof: &::TransactionInclusionProof, ) -> bool { if let Err(err) = prepare_deposit_details::(proof) { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Can't accept exchange transaction: {:?}", err, diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 080957d780134..219242be1493a 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"], optional = true } +log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -36,6 +37,7 @@ std = [ "frame-benchmarking/std", "frame-support/std", "frame-system/std", + "log/std", "serde", "sp-io/std", "sp-runtime/std", diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 05beb279a926c..fd08ba0da6fac 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -603,7 +603,7 @@ impl, I: Instance> BridgeStorage { // start pruning blocks let begin = new_pruning_range.oldest_unpruned_block; let end = new_pruning_range.oldest_block_to_keep; - frame_support::debug::trace!(target: "runtime", "Pruning blocks in range [{}..{})", begin, end); + log::trace!(target: "runtime", "Pruning blocks in range [{}..{})", begin, end); for number in begin..end { // if we can't prune anything => break if max_blocks_to_prune == 0 { @@ -629,7 +629,7 @@ impl, I: Instance> BridgeStorage { // we have pruned all headers at number new_pruning_range.oldest_unpruned_block = number + 1; - frame_support::debug::trace!( + log::trace!( target: "runtime", "Oldest unpruned PoA header is now: {}", new_pruning_range.oldest_unpruned_block, @@ -658,7 +658,7 @@ impl, I: Instance> BridgeStorage { // physically remove headers and (probably) obsolete validators sets while let Some(hash) = blocks_at_number.pop() { let header = Headers::::take(&hash); - frame_support::debug::trace!( + log::trace!( target: "runtime", "Pruning PoA header: ({}, {})", number, @@ -818,7 +818,7 @@ impl, I: Instance> Storage for BridgeStorage { } } - frame_support::debug::trace!( + log::trace!( target: "runtime", "Inserting PoA header: ({}, {})", header.header.number, @@ -846,7 +846,7 @@ impl, I: Instance> Storage for BridgeStorage { .map(|f| f.number) .unwrap_or_else(|| FinalizedBlock::::get().number); if let Some(finalized) = finalized { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Finalizing PoA header: ({}, {})", finalized.number, @@ -869,7 +869,7 @@ pub(crate) fn initialize_storage, I: Instance>( initial_validators: &[Address], ) { let initial_hash = initial_header.compute_hash(); - frame_support::debug::trace!( + log::trace!( target: "runtime", "Initializing bridge with PoA header: ({}, {})", initial_header.number, @@ -917,7 +917,7 @@ pub fn verify_transaction_finalized( proof: &[(RawTransaction, RawTransactionReceipt)], ) -> bool { if tx_index >= proof.len() as _ { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: transaction index ({}) is larger than number of transactions ({})", tx_index, @@ -930,7 +930,7 @@ pub fn verify_transaction_finalized( let header = match storage.header(&block) { Some((header, _)) => header, None => { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: can't find header in the storage: {}", block, @@ -943,7 +943,7 @@ pub fn verify_transaction_finalized( // if header is not yet finalized => return if header.number > finalized.number { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: header {}/{} is not finalized. Best finalized: {}", header.number, @@ -962,7 +962,7 @@ pub fn verify_transaction_finalized( false => block == finalized.hash, }; if !is_finalized { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: header {} is not finalized: no canonical path to best finalized block {}", block, @@ -974,7 +974,7 @@ pub fn verify_transaction_finalized( // verify that transaction is included in the block if let Err(computed_root) = header.check_transactions_root(proof.iter().map(|(tx, _)| tx)) { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: transactions root mismatch. Expected: {}, computed: {}", header.transactions_root, @@ -986,7 +986,7 @@ pub fn verify_transaction_finalized( // verify that transaction receipt is included in the block if let Err(computed_root) = header.check_raw_receipts_root(proof.iter().map(|(_, r)| r)) { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: receipts root mismatch. Expected: {}, computed: {}", header.receipts_root, @@ -1001,7 +1001,7 @@ pub fn verify_transaction_finalized( match is_successful_raw_receipt { Ok(true) => true, Ok(false) => { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: receipt shows that transaction has failed", ); @@ -1009,7 +1009,7 @@ pub fn verify_transaction_finalized( false } Err(err) => { - frame_support::debug::trace!( + log::trace!( target: "runtime", "Tx finality check failed: receipt check has failed: {}", err, diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 3882e6b529edf..7b1f175f54292 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -144,7 +144,7 @@ pub fn accept_aura_header_into_pool( // the heaviest, but rare operation - we do not want invalid receipts in the pool if let Some(receipts) = receipts { - frame_support::debug::trace!(target: "runtime", "Got receipts! {:?}", receipts); + log::trace!(target: "runtime", "Got receipts! {:?}", receipts); if header.check_receipts_root(receipts).is_err() { return Err(Error::TransactionsReceiptsMismatch); } @@ -166,7 +166,7 @@ pub fn verify_aura_header( // the rest of checks requires access to the parent header let context = storage.import_context(submitter, &header.parent_hash).ok_or_else(|| { - frame_support::debug::warn!( + log::warn!( target: "runtime", "Missing parent PoA block: ({:?}, {})", header.number.checked_sub(1), diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index 79279f038bd26..539ef03a425d1 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } finality-grandpa = { version = "0.14.0", default-features = false } +log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -40,6 +41,7 @@ std = [ "finality-grandpa/std", "frame-support/std", "frame-system/std", + "log/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 8d0aa7b8cacd5..5eba7f1588731 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -133,7 +133,7 @@ pub mod pallet { ); let (hash, number) = (finality_target.hash(), finality_target.number()); - frame_support::debug::trace!("Going to try and finalize header {:?}", finality_target); + log::trace!("Going to try and finalize header {:?}", finality_target); let best_finalized = >::get(>::get()).expect( "In order to reach this point the bridge must have been initialized. Afterwards, @@ -151,13 +151,13 @@ pub mod pallet { verify_justification::>((hash, *number), set_id, voter_set, &justification).map_err( |e| { - frame_support::debug::error!("Received invalid justification for {:?}: {:?}", finality_target, e); + log::error!("Received invalid justification for {:?}: {:?}", finality_target, e); >::InvalidJustification }, )?; let best_finalized = T::HeaderChain::best_finalized(); - frame_support::debug::trace!("Checking ancestry against best finalized header: {:?}", &best_finalized); + log::trace!("Checking ancestry against best finalized header: {:?}", &best_finalized); ensure!( T::AncestryChecker::are_ancestors(&best_finalized, &finality_target, &ancestry_proof), @@ -169,7 +169,7 @@ pub mod pallet { import_header::(hash, finality_target)?; >::mutate(|count| *count += 1); - frame_support::debug::info!("Succesfully imported finalized header with hash {:?}!", hash); + log::info!("Succesfully imported finalized header with hash {:?}!", hash); Ok(().into()) } @@ -194,7 +194,7 @@ pub mod pallet { ensure!(init_allowed, >::AlreadyInitialized); initialize_bridge::(init_data.clone()); - frame_support::debug::info!( + log::info!( "Pallet has been initialized with the following parameters: {:?}", init_data ); @@ -211,11 +211,11 @@ pub mod pallet { match new_owner { Some(new_owner) => { ModuleOwner::::put(&new_owner); - frame_support::debug::info!("Setting pallet Owner to: {:?}", new_owner); + log::info!("Setting pallet Owner to: {:?}", new_owner); } None => { ModuleOwner::::kill(); - frame_support::debug::info!("Removed Owner of pallet."); + log::info!("Removed Owner of pallet."); } } @@ -229,7 +229,7 @@ pub mod pallet { pub fn halt_operations(origin: OriginFor) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; >::put(true); - frame_support::debug::warn!("Stopping pallet operations."); + log::warn!("Stopping pallet operations."); Ok(().into()) } @@ -241,7 +241,7 @@ pub mod pallet { pub fn resume_operations(origin: OriginFor) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; >::put(false); - frame_support::debug::info!("Resuming pallet operations."); + log::info!("Resuming pallet operations."); Ok(().into()) } diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index be07b1173ac9a..69160e3afb795 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } @@ -40,6 +41,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "log/std", "num-traits/std", "serde", "sp-core/std", diff --git a/modules/message-lane/src/instant_payments.rs b/modules/message-lane/src/instant_payments.rs index 63c94e6ffdfea..4dffc35935252 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/message-lane/src/instant_payments.rs @@ -167,13 +167,13 @@ fn pay_relayer_reward( ); match pay_result { - Ok(_) => frame_support::debug::trace!( + Ok(_) => log::trace!( target: "runtime", "Rewarded relayer {:?} with {:?}", relayer_account, reward, ), - Err(error) => frame_support::debug::trace!( + Err(error) => log::trace!( target: "runtime", "Failed to pay relayer {:?} reward {:?}: {:?}", relayer_account, diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index 45da09eba0ff4..cf434229ff165 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -255,11 +255,11 @@ decl_module! { match new_owner { Some(new_owner) => { ModuleOwner::::put(&new_owner); - frame_support::debug::info!("Setting pallet Owner to: {:?}", new_owner); + log::info!("Setting pallet Owner to: {:?}", new_owner); }, None => { ModuleOwner::::kill(); - frame_support::debug::info!("Removed Owner of pallet."); + log::info!("Removed Owner of pallet."); }, } } @@ -271,7 +271,7 @@ decl_module! { pub fn halt_operations(origin) { ensure_owner_or_root::(origin)?; IsHalted::::put(true); - frame_support::debug::warn!("Stopping pallet operations."); + log::warn!("Stopping pallet operations."); } /// Resume all pallet operations. May be called even if pallet is halted. @@ -281,7 +281,7 @@ decl_module! { pub fn resume_operations(origin) { ensure_owner_or_root::(origin)?; IsHalted::::put(false); - frame_support::debug::info!("Resuming pallet operations."); + log::info!("Resuming pallet operations."); } /// Update pallet parameter. @@ -310,7 +310,7 @@ decl_module! { // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload) .map_err(|err| { - frame_support::debug::trace!( + log::trace!( "Message to lane {:?} is rejected by target chain: {:?}", lane_id, err, @@ -328,7 +328,7 @@ decl_module! { &lane.data(), &payload, ).map_err(|err| { - frame_support::debug::trace!( + log::trace!( "Message to lane {:?} is rejected by lane verifier: {:?}", lane_id, err, @@ -343,7 +343,7 @@ decl_module! { &delivery_and_dispatch_fee, &Self::relayer_fund_account_id(), ).map_err(|err| { - frame_support::debug::trace!( + log::trace!( "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", lane_id, submitter, @@ -363,7 +363,7 @@ decl_module! { }); lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); - frame_support::debug::trace!( + log::trace!( "Accepted message {} to lane {:?}. Message size: {:?}", nonce, lane_id, @@ -399,7 +399,7 @@ decl_module! { &additional_fee, &Self::relayer_fund_account_id(), ).map_err(|err| { - frame_support::debug::trace!( + log::trace!( "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", submitter, additional_fee, @@ -455,7 +455,7 @@ decl_module! { T::InboundPayload, >(proof, messages_count) .map_err(|err| { - frame_support::debug::trace!( + log::trace!( "Rejecting invalid messages proof: {:?}", err, ); @@ -474,7 +474,7 @@ decl_module! { ) .fold(0, |sum, weight| sum.saturating_add(weight)); if dispatch_weight < actual_dispatch_weight { - frame_support::debug::trace!( + log::trace!( "Rejecting messages proof because of dispatch weight mismatch: declared={}, expected={}", dispatch_weight, actual_dispatch_weight, @@ -492,7 +492,7 @@ decl_module! { if let Some(lane_state) = lane_data.lane_state { let updated_latest_confirmed_nonce = lane.receive_state_update(lane_state); if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { - frame_support::debug::trace!( + log::trace!( "Received lane {:?} state update: latest_confirmed_nonce={}", lane_id, updated_latest_confirmed_nonce, @@ -510,7 +510,7 @@ decl_module! { } } - frame_support::debug::trace!( + log::trace!( "Received messages: total={}, valid={}", total_messages, valid_messages, @@ -530,7 +530,7 @@ decl_module! { let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { - frame_support::debug::trace!( + log::trace!( "Rejecting invalid messages delivery proof: {:?}", err, ); @@ -585,7 +585,7 @@ decl_module! { ); } - frame_support::debug::trace!( + log::trace!( "Received messages delivery proof up to (and including) {} at lane {:?}", last_delivered_nonce, lane_id, diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index 6f6e9cafddabe..cffb942f0134d 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } finality-grandpa = { version = "0.14.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } +log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -44,6 +45,7 @@ std = [ "frame-support/std", "frame-system/std", "hash-db/std", + "log/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 90213e5c9b9ab..abadbb9dd0aa5 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -181,7 +181,7 @@ decl_module! { ensure_operational::()?; let _ = ensure_signed(origin)?; let hash = header.hash(); - frame_support::debug::trace!("Going to import header {:?}: {:?}", hash, header); + log::trace!("Going to import header {:?}: {:?}", hash, header); let mut verifier = verifier::Verifier { storage: PalletStorage::::new(), @@ -190,11 +190,11 @@ decl_module! { let _ = verifier .import_header(hash, header) .map_err(|e| { - frame_support::debug::error!("Failed to import header {:?}: {:?}", hash, e); + log::error!("Failed to import header {:?}: {:?}", hash, e); >::InvalidHeader })?; - frame_support::debug::trace!("Successfully imported header: {:?}", hash); + log::trace!("Successfully imported header: {:?}", hash); Ok(()) } @@ -213,7 +213,7 @@ decl_module! { ) -> DispatchResult { ensure_operational::()?; let _ = ensure_signed(origin)?; - frame_support::debug::trace!("Going to finalize header: {:?}", hash); + log::trace!("Going to finalize header: {:?}", hash); let mut verifier = verifier::Verifier { storage: PalletStorage::::new(), @@ -222,11 +222,11 @@ decl_module! { let _ = verifier .import_finality_proof(hash, finality_proof.into()) .map_err(|e| { - frame_support::debug::error!("Failed to finalize header {:?}: {:?}", hash, e); + log::error!("Failed to finalize header {:?}: {:?}", hash, e); >::UnfinalizedHeader })?; - frame_support::debug::trace!("Successfully finalized header: {:?}", hash); + log::trace!("Successfully finalized header: {:?}", hash); Ok(()) } @@ -251,7 +251,7 @@ decl_module! { ensure!(init_allowed, >::AlreadyInitialized); initialize_bridge::(init_data.clone()); - frame_support::debug::info!( + log::info!( "Pallet has been initialized with the following parameters: {:?}", init_data ); } @@ -265,11 +265,11 @@ decl_module! { match new_owner { Some(new_owner) => { ModuleOwner::::put(&new_owner); - frame_support::debug::info!("Setting pallet Owner to: {:?}", new_owner); + log::info!("Setting pallet Owner to: {:?}", new_owner); }, None => { ModuleOwner::::kill(); - frame_support::debug::info!("Removed Owner of pallet."); + log::info!("Removed Owner of pallet."); }, } } @@ -281,7 +281,7 @@ decl_module! { pub fn halt_operations(origin) { ensure_owner_or_root::(origin)?; IsHalted::put(true); - frame_support::debug::warn!("Stopping pallet operations."); + log::warn!("Stopping pallet operations."); } /// Resume all pallet operations. May be called even if pallet is halted. @@ -291,7 +291,7 @@ decl_module! { pub fn resume_operations(origin) { ensure_owner_or_root::(origin)?; IsHalted::put(false); - frame_support::debug::info!("Resuming pallet operations."); + log::info!("Resuming pallet operations."); } } } diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index effb5761b650c..11d54fade7342 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -240,9 +240,9 @@ where &proof.0, ) .map_err(|_| FinalizationError::InvalidJustification)?; - frame_support::debug::trace!("Received valid justification for {:?}", header); + log::trace!("Received valid justification for {:?}", header); - frame_support::debug::trace!( + log::trace!( "Checking ancestry for headers between {:?} and {:?}", last_finalized, header From 6a1197b7a46c23ebb98d6af18662e826b3c9df08 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 8 Mar 2021 21:07:20 +0300 Subject: [PATCH 0369/1210] Changed delivery and dispatch fee computation methods (#795) * removed weight <-> fee mess * updated documentation Co-authored-by: Hernando Castano --- bin/millau/runtime/src/lib.rs | 10 - bin/millau/runtime/src/rialto_messages.rs | 131 +++++---- bin/rialto/runtime/src/lib.rs | 10 - bin/rialto/runtime/src/millau_messages.rs | 131 +++++---- bin/runtime-common/README.md | 129 ++++----- bin/runtime-common/src/messages.rs | 263 ++++++++++-------- modules/message-lane/src/weights_ext.rs | 20 +- primitives/millau/src/lib.rs | 5 + primitives/rialto/src/lib.rs | 5 + relays/ethereum/src/rialto_client.rs | 4 +- relays/millau-client/src/lib.rs | 8 +- relays/rialto-client/src/lib.rs | 8 +- relays/substrate-client/src/chain.rs | 4 +- relays/substrate/Cargo.toml | 3 + relays/substrate/src/main.rs | 44 ++- .../substrate/src/millau_headers_to_rialto.rs | 5 +- .../src/millau_messages_to_rialto.rs | 6 +- .../substrate/src/rialto_headers_to_millau.rs | 5 +- .../src/rialto_messages_to_millau.rs | 6 +- 19 files changed, 440 insertions(+), 357 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7c5d93ca2e15e..0add4f3235676 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -667,11 +667,6 @@ mod tests { bp_millau::max_extrinsic_size(), bp_millau::max_extrinsic_weight(), max_incoming_message_proof_size, - bridge_runtime_common::messages::transaction_weight_without_multiplier( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - max_incoming_message_proof_size as _, - 0, - ), messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()), ); @@ -686,11 +681,6 @@ mod tests { max_incoming_inbound_lane_data_proof_size, bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - bridge_runtime_common::messages::transaction_weight_without_multiplier( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - max_incoming_inbound_lane_data_proof_size as _, - 0, - ), ); } } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 9775c93d2d0c6..dfe08b6e3d824 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -24,11 +24,11 @@ use bp_message_lane::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessageLaneParameter, }; use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; -use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; +use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge, MessageLaneTransaction}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, - weights::{DispatchClass, Weight, WeightToFeePolynomial}, + weights::{DispatchClass, Weight}, RuntimeDebug, }; use sp_core::storage::StorageKey; @@ -99,59 +99,6 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; - fn maximal_extrinsic_size_on_target_chain() -> u32 { - bp_rialto::max_extrinsic_size() - } - - fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { - // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); - - // we're charging for payload bytes in `WithRialtoMessageBridge::weight_of_delivery_transaction` function - // - // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about - // minimal dispatch weight here - - 0..=upper_limit - } - - fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { - let message_payload_len = u32::try_from(message_payload.len()) - .map(Into::into) - .unwrap_or(Weight::MAX); - let extra_bytes_in_payload = - message_payload_len.saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); - messages::transaction_weight_without_multiplier( - bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - message_payload_len.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), - extra_bytes_in_payload - .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) - .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT), - ) - } - - fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - let inbounded_data_size: Weight = - InboundLaneData::::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) - .map(Into::into) - .unwrap_or(Weight::MAX); - - messages::transaction_weight_without_multiplier( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - inbounded_data_size.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - ) - } - - fn this_weight_to_this_balance(weight: Weight) -> bp_millau::Balance { - ::WeightToFee::calc(&weight) - } - - fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_rialto::Balance { - // we're using the same weights in both chains now - ::WeightToFee::calc(&weight) as _ - } - fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) .unwrap_or(bp_millau::Balance::MAX) @@ -167,7 +114,6 @@ impl messages::ChainWithMessageLanes for Millau { type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; - type Call = crate::Call; type Weight = Weight; type Balance = bp_millau::Balance; @@ -175,6 +121,8 @@ impl messages::ChainWithMessageLanes for Millau { } impl messages::ThisChainWithMessageLanes for Millau { + type Call = crate::Call; + fn is_outbound_lane_enabled(lane: &LaneId) -> bool { *lane == LaneId::default() } @@ -182,6 +130,29 @@ impl messages::ThisChainWithMessageLanes for Millau { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } + + fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction { + let inbound_data_size = + InboundLaneData::::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) + .unwrap_or(u32::MAX); + + MessageLaneTransaction { + dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + size: inbound_data_size + .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_millau::TX_EXTRA_BYTES), + } + } + + fn transaction_payment(transaction: MessageLaneTransaction) -> bp_millau::Balance { + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + 1, + |weight| weight as _, + transaction, + ) + } } /// Rialto chain from message lane point of view. @@ -193,13 +164,59 @@ impl messages::ChainWithMessageLanes for Rialto { type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; - type Call = (); // unknown to us type Weight = Weight; type Balance = bp_rialto::Balance; type MessageLaneInstance = pallet_message_lane::DefaultInstance; } +impl messages::BridgedChainWithMessageLanes for Rialto { + fn maximal_extrinsic_size() -> u32 { + bp_rialto::max_extrinsic_size() + } + + fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { + // we don't want to relay too large messages + keep reserve for future upgrades + let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); + + // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` function + // + // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about + // minimal dispatch weight here + + 0..=upper_limit + } + + fn estimate_delivery_transaction( + message_payload: &[u8], + message_dispatch_weight: Weight, + ) -> MessageLaneTransaction { + let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); + let extra_bytes_in_payload = Weight::from(message_payload_len) + .saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + + MessageLaneTransaction { + dispatch_weight: extra_bytes_in_payload + .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) + .saturating_add(message_dispatch_weight), + size: message_payload_len + .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_rialto::TX_EXTRA_BYTES), + } + } + + fn transaction_payment(transaction: MessageLaneTransaction) -> bp_rialto::Balance { + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment_without_multiplier( + bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + 1, + |weight| weight as _, + transaction, + ) + } +} + impl TargetHeaderChain for Rialto { type Error = &'static str; // The proof is: diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index eaac1f5a61d7f..18c88a188627b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1096,11 +1096,6 @@ mod tests { bp_rialto::max_extrinsic_size(), bp_rialto::max_extrinsic_weight(), max_incoming_message_proof_size, - bridge_runtime_common::messages::transaction_weight_without_multiplier( - bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - max_incoming_message_proof_size as _, - 0, - ), messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), ); @@ -1115,11 +1110,6 @@ mod tests { max_incoming_inbound_lane_data_proof_size, bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - bridge_runtime_common::messages::transaction_weight_without_multiplier( - bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - max_incoming_inbound_lane_data_proof_size as _, - 0, - ), ); } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 9fb57ee861b64..f2ccd71204299 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -24,11 +24,11 @@ use bp_message_lane::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessageLaneParameter, }; use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; -use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge}; +use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge, MessageLaneTransaction}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, - weights::{DispatchClass, Weight, WeightToFeePolynomial}, + weights::{DispatchClass, Weight}, RuntimeDebug, }; use sp_core::storage::StorageKey; @@ -99,59 +99,6 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; - fn maximal_extrinsic_size_on_target_chain() -> u32 { - bp_millau::max_extrinsic_size() - } - - fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { - // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()); - - // we're charging for payload bytes in `WithMillauMessageBridge::weight_of_delivery_transaction` function - // - // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about - // minimal dispatch weight here - - 0..=upper_limit - } - - fn weight_of_delivery_transaction(message_payload: &[u8]) -> Weight { - let message_payload_len = u32::try_from(message_payload.len()) - .map(Into::into) - .unwrap_or(Weight::MAX); - let extra_bytes_in_payload = - message_payload_len.saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); - messages::transaction_weight_without_multiplier( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - message_payload_len.saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE as _), - extra_bytes_in_payload - .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) - .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT), - ) - } - - fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - let inbounded_data_size: Weight = - InboundLaneData::::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) - .map(Into::into) - .unwrap_or(Weight::MAX); - - messages::transaction_weight_without_multiplier( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - inbounded_data_size.saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE as _), - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - ) - } - - fn this_weight_to_this_balance(weight: Weight) -> bp_rialto::Balance { - ::WeightToFee::calc(&weight) - } - - fn bridged_weight_to_bridged_balance(weight: Weight) -> bp_millau::Balance { - // we're using the same weights in both chains now - ::WeightToFee::calc(&weight) as _ - } - fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) .unwrap_or(bp_rialto::Balance::MAX) @@ -167,7 +114,6 @@ impl messages::ChainWithMessageLanes for Rialto { type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; - type Call = crate::Call; type Weight = Weight; type Balance = bp_rialto::Balance; @@ -175,6 +121,8 @@ impl messages::ChainWithMessageLanes for Rialto { } impl messages::ThisChainWithMessageLanes for Rialto { + type Call = crate::Call; + fn is_outbound_lane_enabled(lane: &LaneId) -> bool { *lane == LaneId::default() } @@ -182,6 +130,29 @@ impl messages::ThisChainWithMessageLanes for Rialto { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } + + fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction { + let inbound_data_size = + InboundLaneData::::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) + .unwrap_or(u32::MAX); + + MessageLaneTransaction { + dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + size: inbound_data_size + .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_rialto::TX_EXTRA_BYTES), + } + } + + fn transaction_payment(transaction: MessageLaneTransaction) -> bp_rialto::Balance { + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment_without_multiplier( + bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + 1, + |weight| weight as _, + transaction, + ) + } } /// Millau chain from message lane point of view. @@ -193,13 +164,59 @@ impl messages::ChainWithMessageLanes for Millau { type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; - type Call = (); // unknown to us type Weight = Weight; type Balance = bp_millau::Balance; type MessageLaneInstance = pallet_message_lane::DefaultInstance; } +impl messages::BridgedChainWithMessageLanes for Millau { + fn maximal_extrinsic_size() -> u32 { + bp_millau::max_extrinsic_size() + } + + fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { + // we don't want to relay too large messages + keep reserve for future upgrades + let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()); + + // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` function + // + // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about + // minimal dispatch weight here + + 0..=upper_limit + } + + fn estimate_delivery_transaction( + message_payload: &[u8], + message_dispatch_weight: Weight, + ) -> MessageLaneTransaction { + let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); + let extra_bytes_in_payload = Weight::from(message_payload_len) + .saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + + MessageLaneTransaction { + dispatch_weight: extra_bytes_in_payload + .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) + .saturating_add(message_dispatch_weight), + size: message_payload_len + .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_millau::TX_EXTRA_BYTES), + } + } + + fn transaction_payment(transaction: MessageLaneTransaction) -> bp_millau::Balance { + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment_without_multiplier( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + 1, + |weight| weight as _, + transaction, + ) + } +} + impl TargetHeaderChain for Millau { type Error = &'static str; // The proof is: diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index 58fe92c9ca0dd..8d90bc7a8c84e 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -33,17 +33,63 @@ message lane module into your runtime. Basic prerequisites of these helpers are: ## `MessageBridge` Trait -The essence of your integration will be a struct that implements a `MessageBridge` trait. Let's -review every method and give some implementation hints here: +The essence of your integration will be a struct that implements a `MessageBridge` trait. It has +single method (`MessageBridge::bridged_balance_to_this_balance`), used to convert from bridged chain +tokens into this chain tokens. The bridge also requires two associated types to be specified - +`ThisChain` and `BridgedChain`. + +Worth to say that if you're going to use hardcoded constant (conversion rate) in the +`MessageBridge::bridged_balance_to_this_balance` method (or in any other method of +`ThisChainWithMessageLanes` or `BridgedChainWithMessageLanes` traits), then you should take a +look at the +[message lane parameters functionality](../../modules/message-lane/README.md#Non-Essential-Functionality). +They allow pallet owner to update constants more frequently than runtime upgrade happens. -- `MessageBridge::maximal_extrinsic_size_on_target_chain`: you will need to return the maximal - extrinsic size of the target chain from this function. This may be the constant that is updated - when your runtime is upgraded, or you may use the - [message lane parameters functionality](../../modules/message-lane/README.md#Non-Essential-Functionality) - to allow the pallet owner to update this value more frequently (you may also want to use this - functionality for all constants that are used in other methods described below). +## `ChainWithMessageLanes` Trait + +The trait is quite simple and can easily be implemented - you just need to specify types used at the +corresponding chain. There is single exception, though (it may be changed in the future): + +- `ChainWithMessageLanes::MessageLaneInstance`: this is used to compute runtime storage keys. There + may be several instances of message lane pallet, included in the Runtime. Every instance stores + messages and these messages stored under different keys. When we are verifying storage proofs from + the bridged chain, we should know which instance we're talking to. This is fine, but there's + significant inconvenience with that - this chain runtime must have the same message lane pallet + instance. This does not necessarily mean that we should use the same instance on both chains - + this instance may be used to bridge with another chain/instance, or may not be used at all. + +## `ThisChainWithMessageLanes` Trait + +This trait represents this chain from bridge point of view. Let's review every method of this trait: + +- `ThisChainWithMessageLanes::is_outbound_lane_enabled`: is used to check whether given lane accepts + outbound messages. + +- `ThisChainWithMessageLanes::maximal_pending_messages_at_outbound_lane`: you should return maximal + number of pending (undelivered) messages from this function. Returning small values would require + relayers to operate faster and could make message sending logic more complicated. On the other + hand, returning large values could lead to chain state growth. + +- `ThisChainWithMessageLanes::estimate_delivery_confirmation_transaction`: you'll need to return + estimated size and dispatch weight of the delivery confirmation transaction (that happens on + this chain) from this function. -- `MessageBridge::weight_limits_of_message_on_bridged_chain`: you'll need to return a range of +- `ThisChainWithMessageLanes::transaction_payment`: you'll need to return fee that the submitter + must pay for given transaction on this chain. Normally, you would use transaction payment pallet + for this. However, if your chain has non-zero fee multiplier set, this would mean that the + payment will be computed using current value of this multiplier. But since this transaction + will be submitted in the future, you may want to choose other value instead. Otherwise, + non-altruistic relayer may choose not to submit this transaction until number of transactions + will decrease. + +## `BridgedChainWithMessageLanes` Trait + +This trait represents this chain from bridge point of view. Let's review every method of this trait: + +- `BridgedChainWithMessageLanes::maximal_extrinsic_size`: you will need to return the maximal + extrinsic size of the target chain from this function. + +- `MessageBridge::message_weight_limits`: you'll need to return a range of dispatch weights that the outbound message may take at the target chain. Please keep in mind that our helpers assume that the message is an encoded call of the target chain. But we never decode this call at the source chain. So you can't simply get dispatch weight from pre-dispatch @@ -55,66 +101,13 @@ review every method and give some implementation hints here: maximal weight of extrinsic at the target chain. In our test chains, we reject all messages that have declared dispatch weight larger than 50% of the maximal bridged extrinsic weight. -- `MessageBridge::weight_of_delivery_transaction`: you will need to return the maximal weight of the - delivery transaction that delivers a given message to the target chain. There are three main - things to notice: - - 1. weight, returned from this function is then used to compute the fee that the - message sender needs to pay for the delivery transaction. So it shall not be a simple dispatch - weight of delivery call - it should be the "weight" of the transaction itself, including per-byte - "weight", "weight" of signed extras and etc. - 1. the delivery transaction brings storage proof of - the message, not the message itself. So your transaction will include extra bytes. We suggest - computing the size of single empty value storage proof at the source chain, increase this value a - bit and hardcode it in the source chain runtime code. This size then must be added to the size of - payload and included in the weight computation; - 1. before implementing this function, please take - a look at the - [weight formula of delivery transaction](../../modules/message-lane/README.md#Weight-of-receive_messages_proof-call). - It adds some extra weight for every additional byte of the proof (everything above - `pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH`), so it's not trivial. Even better, please - refer to [our implementation](../millau/runtime/src/rialto_messages.rs) for test chains for - details. - -- `MessageBridge::weight_of_delivery_confirmation_transaction_on_this_chain`: you'll need to return - the maximal weight of a single message delivery confirmation transaction on this chain. All points - from the previous paragraph are also relevant here. - -- `MessageBridge::this_weight_to_this_balance`: this function needs to convert weight units into fee - units on this chain. Most probably this can be done by calling - `pallet_transaction_payment::Config::WeightToFee::calc()` for passed weight. - -- `MessageBridge::bridged_weight_to_bridged_balance`: this function needs to convert weight units - into fee units on the target chain. The best case is when you have the same conversion formula on - both chains - then you may just call the same formula from the previous paragraph. Otherwise, - you'll need to hardcode this formula into your runtime. - -- `MessageBridge::bridged_balance_to_this_balance`: this may be the easiest method to implement and - the hardest to maintain at the same time. If you don't have any automatic methods to determine - conversion rate, then you'll probably need to maintain it by yourself (by updating conversion - rate, stored in runtime storage). This means that if you're too late with an update, then you risk - to accept messages with lower-than-expected fee. So it may be wise to have some reserve in this - conversion rate, even if that means larger delivery and dispatch fees. - -## `ChainWithMessageLanes` Trait - -Apart from its methods, `MessageBridge` also has two associated types that are implementing the -`ChainWithMessageLanes` trait. One is for this chain and the other is for the bridged chain. The -trait is quite simple and can easily be implemented - you just need to specify types used at the -corresponding chain. There are two exceptions, though. Both may be changed in the future. Here they -are: - -- `ChainWithMessageLanes::Call`: it isn't a good idea to reference bridged chain runtime from your - runtime (cyclic references + maintaining on upgrades). So you can't know the type of bridged chain - call in your runtime. This type isn't actually used at this chain, so you may use `()` instead. +- `MessageBridge::estimate_delivery_transaction`: you will need to return estimated dispatch weight and + size of the delivery transaction that delivers a given message to the target chain. -- `ChainWithMessageLanes::MessageLaneInstance`: this is used to compute runtime storage keys. There - may be several instances of message lane pallet, included in the Runtime. Every instance stores - messages and these messages stored under different keys. When we are verifying storage proofs from - the bridged chain, we should know which instance we're talking to. This is fine, but there's - significant inconvenience with that - this chain runtime must have the same message lane pallet - instance. This does not necessarily mean that we should use the same instance on both chains - - this instance may be used to bridge with another chain/instance, or may not be used at all. +- `MessageBridge::transaction_payment`: you'll need to return fee that the submitter + must pay for given transaction on bridged chain. The best case is when you have the same conversion + formula on both chains - then you may just reuse the `ThisChainWithMessageLanes::transaction_payment` + implementation. Otherwise, you'll need to hardcode this formula into your runtime. ## Helpers for the Source Chain diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 04b2317749b0a..755562db1f72b 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -31,7 +31,7 @@ use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use pallet_substrate_bridge::StorageProofChecker; -use sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul}; +use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; @@ -46,37 +46,9 @@ pub trait MessageBridge { /// This chain in context of message bridge. type ThisChain: ThisChainWithMessageLanes; /// Bridged chain in context of message bridge. - type BridgedChain: ChainWithMessageLanes; + type BridgedChain: BridgedChainWithMessageLanes; - /// Maximal extrinsic size on target chain. - fn maximal_extrinsic_size_on_target_chain() -> u32; - - /// Returns feasible weights range for given message payload on the target chain. - /// - /// If message is being sent with the weight that is out of this range, then it - /// should be rejected. - /// - /// Weights returned from this function shall not include transaction overhead - /// (like weight of signature and signed extensions verification), because they're - /// already accounted by the `weight_of_delivery_transaction`. So this function should - /// return pure call dispatch weights range. - fn weight_limits_of_message_on_bridged_chain( - message_payload: &[u8], - ) -> RangeInclusive>>; - - /// Maximal weight of single message delivery transaction on Bridged chain. - fn weight_of_delivery_transaction(message_payload: &[u8]) -> WeightOf>; - - /// Maximal weight of single message delivery confirmation transaction on This chain. - fn weight_of_delivery_confirmation_transaction_on_this_chain() -> WeightOf>; - - /// Convert weight of This chain to the fee (paid in Balance) of This chain. - fn this_weight_to_this_balance(weight: WeightOf>) -> BalanceOf>; - - /// Convert weight of the Bridged chain to the fee (paid in Balance) of the Bridged chain. - fn bridged_weight_to_bridged_balance(weight: WeightOf>) -> BalanceOf>; - - /// Convert Bridged chain Balance into This chain Balance. + /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; } @@ -90,8 +62,6 @@ pub trait ChainWithMessageLanes { type Signer: Decode; /// Signature type used on the chain. type Signature: Decode; - /// Call type on the chain. - type Call: Encode + Decode; /// Type of weight that is used on the chain. This would almost always be a regular /// `frame_support::weight::Weight`. But since the meaning of weight on different chains /// may be different, the `WeightOf<>` construct is used to avoid confusion between @@ -104,15 +74,59 @@ pub trait ChainWithMessageLanes { type MessageLaneInstance: Instance; } +/// Message-lane related transaction parameters estimation. +#[derive(RuntimeDebug)] +pub struct MessageLaneTransaction { + /// The estimated dispatch weight of the transaction. + pub dispatch_weight: Weight, + /// The estimated size of the encoded transaction. + pub size: u32, +} + /// This chain that has `message-lane` and `call-dispatch` modules. pub trait ThisChainWithMessageLanes: ChainWithMessageLanes { + /// Call type on the chain. + type Call: Encode + Decode; + /// Are we accepting any messages to the given lane? fn is_outbound_lane_enabled(lane: &LaneId) -> bool; - /// Maximal number of pending (not yet delivered) messages at this chain. + /// Maximal number of pending (not yet delivered) messages at This chain. /// /// Any messages over this limit, will be rejected. fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; + + /// Estimate size and weight of single message delivery confirmation transaction at This chain. + fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction>; + + /// Returns minimal transaction fee that must be paid for given transaction at This chain. + fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf; +} + +/// Bridged chain that has `message-lane` and `call-dispatch` modules. +pub trait BridgedChainWithMessageLanes: ChainWithMessageLanes { + /// Maximal extrinsic size at Bridged chain. + fn maximal_extrinsic_size() -> u32; + + /// Returns feasible weights range for given message payload at the Bridged chain. + /// + /// If message is being sent with the weight that is out of this range, then it + /// should be rejected. + /// + /// Weights returned from this function shall not include transaction overhead + /// (like weight of signature and signed extensions verification), because they're + /// already accounted by the `weight_of_delivery_transaction`. So this function should + /// return pure call dispatch weights range. + fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive; + + /// Estimate size and weight of single message delivery transaction at the Bridged chain. + fn estimate_delivery_transaction( + message_payload: &[u8], + message_dispatch_weight: WeightOf, + ) -> MessageLaneTransaction>; + + /// Returns minimal transaction fee that must be paid for given transaction at the Bridged chain. + fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf; } pub(crate) type ThisChain = ::ThisChain; @@ -123,35 +137,35 @@ pub(crate) type SignerOf = ::Signer; pub(crate) type SignatureOf = ::Signature; pub(crate) type WeightOf = ::Weight; pub(crate) type BalanceOf = ::Balance; -pub(crate) type CallOf = ::Call; pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; +pub(crate) type CallOf = ::Call; + /// Raw storage proof type (just raw trie nodes). type RawStorageProof = Vec>; -/// Compute weight of transaction at runtime where: +/// Compute fee of transaction at runtime where: /// /// - transaction payment pallet is being used; /// - fee multiplier is zero. -pub fn transaction_weight_without_multiplier( - base_weight: Weight, - payload_size: Weight, - dispatch_weight: Weight, -) -> Weight { - // non-adjustable per-byte weight is mapped 1:1 to tx weight - let per_byte_weight = payload_size; - - // we assume that adjustable per-byte weight is always zero - let adjusted_per_byte_weight = 0; - - // we assume that transaction tip we use is also zero - let transaction_tip_weight = 0; - - base_weight - .saturating_add(per_byte_weight) - .saturating_add(adjusted_per_byte_weight) - .saturating_add(transaction_tip_weight) - .saturating_add(dispatch_weight) +pub fn transaction_payment_without_multiplier( + base_extrinsic_weight: Weight, + per_byte_fee: Balance, + weight_to_fee: impl Fn(Weight) -> Balance, + transaction: MessageLaneTransaction, +) -> Balance { + // base fee is charged for every tx + let base_fee = weight_to_fee(base_extrinsic_weight); + + // non-adjustable per-byte fee + let len_fee = per_byte_fee.saturating_mul(Balance::from(transaction.size)); + + // the adjustable part of the fee + // + // here we assume that the fee multiplier is zero, so this part is also always zero + let adjusted_weight_fee = Balance::zero(); + + base_fee.saturating_add(len_fee).saturating_add(adjusted_weight_fee) } /// Sub-module that is declaring types required for processing This -> Bridged chain messages. @@ -266,7 +280,7 @@ pub mod source { /// Return maximal message size of This -> Bridged chain message. pub fn maximal_message_size() -> u32 { - super::target::maximal_incoming_message_size(B::maximal_extrinsic_size_on_target_chain()) + super::target::maximal_incoming_message_size(BridgedChain::::maximal_extrinsic_size()) } /// Do basic Bridged-chain specific verification of This -> Bridged chain message. @@ -277,7 +291,7 @@ pub mod source { pub fn verify_chain_message( payload: &FromThisChainMessagePayload, ) -> Result<(), &'static str> { - let weight_limits = B::weight_limits_of_message_on_bridged_chain(&payload.call); + let weight_limits = BridgedChain::::message_weight_limits(&payload.call); if !weight_limits.contains(&payload.weight.into()) { return Err("Incorrect message weight declared"); } @@ -308,18 +322,17 @@ pub mod source { relayer_fee_percent: u32, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - let delivery_fee = B::bridged_weight_to_bridged_balance(B::weight_of_delivery_transaction(&payload.call)); - let dispatch_fee = B::bridged_weight_to_bridged_balance(payload.weight.into()); + let delivery_transaction = + BridgedChain::::estimate_delivery_transaction(&payload.call, payload.weight.into()); + let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); // the fee (in This tokens) of all transactions that are made on This chain - let delivery_confirmation_fee = - B::this_weight_to_this_balance(B::weight_of_delivery_confirmation_transaction_on_this_chain()); + let confirmation_transaction = ThisChain::::estimate_delivery_confirmation_transaction(); + let confirmation_transaction_fee = ThisChain::::transaction_payment(confirmation_transaction); // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = delivery_fee - .checked_add(&dispatch_fee) - .map(B::bridged_balance_to_this_balance) - .and_then(|fee| fee.checked_add(&delivery_confirmation_fee)); + let minimal_fee = + B::bridged_balance_to_this_balance(delivery_transaction_fee).checked_add(&confirmation_transaction_fee); // before returning, add extra fee that is paid to the relayer (relayer interest) minimal_fee @@ -681,31 +694,6 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; - fn maximal_extrinsic_size_on_target_chain() -> u32 { - BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE - } - - fn weight_limits_of_message_on_bridged_chain(message_payload: &[u8]) -> RangeInclusive { - let begin = std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); - begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT - } - - fn weight_of_delivery_transaction(_message_payload: &[u8]) -> Weight { - DELIVERY_TRANSACTION_WEIGHT - } - - fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT - } - - fn this_weight_to_this_balance(weight: Weight) -> ThisChainBalance { - ThisChainBalance(weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) - } - - fn bridged_weight_to_bridged_balance(weight: Weight) -> BridgedChainBalance { - BridgedChainBalance(weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) - } - fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) } @@ -722,30 +710,6 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn maximal_extrinsic_size_on_target_chain() -> u32 { - unreachable!() - } - - fn weight_limits_of_message_on_bridged_chain(_message_payload: &[u8]) -> RangeInclusive { - unreachable!() - } - - fn weight_of_delivery_transaction(_message_payload: &[u8]) -> Weight { - unreachable!() - } - - fn weight_of_delivery_confirmation_transaction_on_this_chain() -> Weight { - unreachable!() - } - - fn this_weight_to_this_balance(_weight: Weight) -> BridgedChainBalance { - unreachable!() - } - - fn bridged_weight_to_bridged_balance(_weight: Weight) -> ThisChainBalance { - unreachable!() - } - fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { unreachable!() } @@ -845,7 +809,6 @@ mod tests { type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; type Signature = ThisChainSignature; - type Call = ThisChainCall; type Weight = frame_support::weights::Weight; type Balance = ThisChainBalance; @@ -853,6 +816,8 @@ mod tests { } impl ThisChainWithMessageLanes for ThisChain { + type Call = ThisChainCall; + fn is_outbound_lane_enabled(lane: &LaneId) -> bool { lane == TEST_LANE_ID } @@ -860,6 +825,38 @@ mod tests { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE } + + fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction> { + MessageLaneTransaction { + dispatch_weight: DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT, + size: 0, + } + } + + fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf { + ThisChainBalance(transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) + } + } + + impl BridgedChainWithMessageLanes for ThisChain { + fn maximal_extrinsic_size() -> u32 { + unreachable!() + } + + fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { + unreachable!() + } + + fn estimate_delivery_transaction( + _message_payload: &[u8], + _message_dispatch_weight: WeightOf, + ) -> MessageLaneTransaction> { + unreachable!() + } + + fn transaction_payment(_transaction: MessageLaneTransaction>) -> BalanceOf { + unreachable!() + } } struct BridgedChain; @@ -869,7 +866,6 @@ mod tests { type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; type Signature = BridgedChainSignature; - type Call = BridgedChainCall; type Weight = frame_support::weights::Weight; type Balance = BridgedChainBalance; @@ -877,6 +873,8 @@ mod tests { } impl ThisChainWithMessageLanes for BridgedChain { + type Call = BridgedChainCall; + fn is_outbound_lane_enabled(_lane: &LaneId) -> bool { unreachable!() } @@ -884,6 +882,39 @@ mod tests { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { unreachable!() } + + fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction> { + unreachable!() + } + + fn transaction_payment(_transaction: MessageLaneTransaction>) -> BalanceOf { + unreachable!() + } + } + + impl BridgedChainWithMessageLanes for BridgedChain { + fn maximal_extrinsic_size() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + + fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive { + let begin = std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); + begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + } + + fn estimate_delivery_transaction( + _message_payload: &[u8], + message_dispatch_weight: WeightOf, + ) -> MessageLaneTransaction> { + MessageLaneTransaction { + dispatch_weight: DELIVERY_TRANSACTION_WEIGHT + message_dispatch_weight, + size: 0, + } + } + + fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf { + BridgedChainBalance(transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) + } } fn test_lane_outbound_data() -> OutboundLaneData { diff --git a/modules/message-lane/src/weights_ext.rs b/modules/message-lane/src/weights_ext.rs index d99a20007dac1..bc75cd5ba0ac9 100644 --- a/modules/message-lane/src/weights_ext.rs +++ b/modules/message-lane/src/weights_ext.rs @@ -95,9 +95,6 @@ pub fn ensure_able_to_receive_message( max_extrinsic_size: u32, max_extrinsic_weight: Weight, max_incoming_message_proof_size: u32, - // This is a base weight (which includes cost of tx itself, per-byte cost, adjusted per-byte cost) of single - // message delivery transaction that brings `max_incoming_message_proof_size` proof. - max_incoming_message_proof_base_weight: Weight, max_incoming_message_dispatch_weight: Weight, ) { // verify that we're able to receive proof of maximal-size message @@ -116,12 +113,9 @@ pub fn ensure_able_to_receive_message( 1, max_incoming_message_dispatch_weight, ); - let max_delivery_transaction_weight = - max_incoming_message_proof_base_weight.saturating_add(max_delivery_transaction_dispatch_weight); assert!( - max_delivery_transaction_weight <= max_extrinsic_weight, - "Weight of maximal message delivery transaction {} + {} is larger than maximal possible transaction weight {}", - max_delivery_transaction_weight, + max_delivery_transaction_dispatch_weight <= max_extrinsic_weight, + "Weight of maximal message delivery transaction + {} is larger than maximal possible transaction weight {}", max_delivery_transaction_dispatch_weight, max_extrinsic_weight, ); @@ -134,9 +128,6 @@ pub fn ensure_able_to_receive_confirmation( max_inbound_lane_data_proof_size_from_peer_chain: u32, max_unrewarded_relayer_entries_at_peer_inbound_lane: MessageNonce, max_unconfirmed_messages_at_inbound_lane: MessageNonce, - // This is a base weight (which includes cost of tx itself, per-byte cost, adjusted per-byte cost) of single - // confirmation transaction that brings `max_inbound_lane_data_proof_size_from_peer_chain` proof. - max_incoming_delivery_proof_base_weight: Weight, ) { // verify that we're able to receive confirmation of maximal-size let max_confirmation_transaction_size = @@ -158,12 +149,9 @@ pub fn ensure_able_to_receive_confirmation( ..Default::default() }, ); - let max_confirmation_transaction_weight = - max_incoming_delivery_proof_base_weight.saturating_add(max_confirmation_transaction_dispatch_weight); assert!( - max_confirmation_transaction_weight <= max_extrinsic_weight, - "Weight of maximal confirmation transaction {} + {} is larger than maximal possible transaction weight {}", - max_incoming_delivery_proof_base_weight, + max_confirmation_transaction_dispatch_weight <= max_extrinsic_weight, + "Weight of maximal confirmation transaction {} is larger than maximal possible transaction weight {}", max_confirmation_transaction_dispatch_weight, max_extrinsic_weight, ); diff --git a/primitives/millau/src/lib.rs b/primitives/millau/src/lib.rs index afaf36de32e75..7397fcf474555 100644 --- a/primitives/millau/src/lib.rs +++ b/primitives/millau/src/lib.rs @@ -48,6 +48,11 @@ pub use millau_hash::MillauHash; /// Some reserve is reserved to account future chain growth. pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; +/// Number of bytes, included in the signed Millau transaction apart from the encoded call itself. +/// +/// Can be computed by subtracting encoded call size from raw transaction size. +pub const TX_EXTRA_BYTES: u32 = 103; + /// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; diff --git a/primitives/rialto/src/lib.rs b/primitives/rialto/src/lib.rs index c598b7ee8379b..ccb2154ee4f45 100644 --- a/primitives/rialto/src/lib.rs +++ b/primitives/rialto/src/lib.rs @@ -39,6 +39,11 @@ use sp_std::prelude::*; /// Some reserve is reserved to account future chain growth. pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; +/// Number of bytes, included in the signed Rialto transaction apart from the encoded call itself. +/// +/// Can be computed by subtracting encoded call size from raw transaction size. +pub const TX_EXTRA_BYTES: u32 = 103; + /// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; diff --git a/relays/ethereum/src/rialto_client.rs b/relays/ethereum/src/rialto_client.rs index 861ef8efeb970..11eb200a1c316 100644 --- a/relays/ethereum/src/rialto_client.rs +++ b/relays/ethereum/src/rialto_client.rs @@ -160,7 +160,7 @@ impl SubmitEthereumHeaders for SubstrateClient { let nonce = self.next_account_index(account_id).await?; let call = instance.build_signed_header_call(headers); - let transaction = Rialto::sign_transaction(self, ¶ms.signer, nonce, call); + let transaction = Rialto::sign_transaction(*self.genesis_hash(), ¶ms.signer, nonce, call); let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; Ok(()) @@ -256,7 +256,7 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { let nonce = self.next_account_index(account_id).await?; let call = instance.build_currency_exchange_call(proof); - let transaction = Rialto::sign_transaction(self, ¶ms.signer, nonce, call); + let transaction = Rialto::sign_transaction(*self.genesis_hash(), ¶ms.signer, nonce, call); let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; Ok(()) diff --git a/relays/millau-client/src/lib.rs b/relays/millau-client/src/lib.rs index c7d04056878fa..36444cda45ca8 100644 --- a/relays/millau-client/src/lib.rs +++ b/relays/millau-client/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Millau-Substrate chain. use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -65,7 +65,7 @@ impl TransactionSignScheme for Millau { type SignedTransaction = millau_runtime::UncheckedExtrinsic; fn sign_transaction( - client: &Client, + genesis_hash: ::Hash, signer: &Self::AccountKeyPair, signer_nonce: ::Index, call: ::Call, @@ -84,8 +84,8 @@ impl TransactionSignScheme for Millau { ( millau_runtime::VERSION.spec_version, millau_runtime::VERSION.transaction_version, - *client.genesis_hash(), - *client.genesis_hash(), + genesis_hash, + genesis_hash, (), (), (), diff --git a/relays/rialto-client/src/lib.rs b/relays/rialto-client/src/lib.rs index 9e38831d56c43..bac65b6427615 100644 --- a/relays/rialto-client/src/lib.rs +++ b/relays/rialto-client/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Rialto-Substrate chain. use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -65,7 +65,7 @@ impl TransactionSignScheme for Rialto { type SignedTransaction = rialto_runtime::UncheckedExtrinsic; fn sign_transaction( - client: &Client, + genesis_hash: ::Hash, signer: &Self::AccountKeyPair, signer_nonce: ::Index, call: ::Call, @@ -84,8 +84,8 @@ impl TransactionSignScheme for Rialto { ( rialto_runtime::VERSION.spec_version, rialto_runtime::VERSION.transaction_version, - *client.genesis_hash(), - *client.genesis_hash(), + genesis_hash, + genesis_hash, (), (), (), diff --git a/relays/substrate-client/src/chain.rs b/relays/substrate-client/src/chain.rs index 60a3cc5d17491..86ad4bc8c9bc8 100644 --- a/relays/substrate-client/src/chain.rs +++ b/relays/substrate-client/src/chain.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::client::Client; - use bp_runtime::Chain as ChainBase; use frame_support::Parameter; use jsonrpsee_types::jsonrpc::{DeserializeOwned, Serialize}; @@ -87,7 +85,7 @@ pub trait TransactionSignScheme { /// Create transaction for given runtime call, signed by given account. fn sign_transaction( - client: &Client, + genesis_hash: ::Hash, signer: &Self::AccountKeyPair, signer_nonce: ::Index, call: ::Call, diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 08cf40c383521..b56b3a3cbddb9 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -48,3 +48,6 @@ sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "maste sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } + +[dev-dependencies] +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 722f850d89ef7..8cd437027c95c 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -96,7 +96,7 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { move |initialization_data| { Ok(Bytes( Rialto::sign_transaction( - &rialto_client, + *rialto_client.genesis_hash(), &rialto_sign.signer, rialto_signer_next_index, rialto_runtime::SudoCall::sudo(Box::new( @@ -132,7 +132,7 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { move |initialization_data| { Ok(Bytes( Millau::sign_transaction( - &millau_client, + *millau_client.genesis_hash(), &millau_sign.signer, millau_signer_next_index, millau_runtime::SudoCall::sudo(Box::new( @@ -266,7 +266,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { ); let signed_millau_call = Millau::sign_transaction( - &millau_client, + *millau_client.genesis_hash(), &millau_sign.signer, millau_client .next_account_index(millau_sign.signer.public().clone().into()) @@ -322,7 +322,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { ); let signed_rialto_call = Rialto::sign_transaction( - &rialto_client, + *rialto_client.genesis_hash(), &rialto_sign.signer, rialto_client .next_account_index(rialto_sign.signer.public().clone().into()) @@ -933,4 +933,40 @@ mod tests { ); assert!(Rialto::verify_message(&payload).is_err()); } + + #[test] + fn rialto_tx_extra_bytes_constant_is_correct() { + let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); + let rialto_tx = Rialto::sign_transaction( + Default::default(), + &sp_keyring::AccountKeyring::Alice.pair(), + 0, + rialto_call.clone(), + ); + let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); + assert!( + bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, + "Hardcoded number of extra bytes in Rialto transaction {} is lower than actual value: {}", + bp_rialto::TX_EXTRA_BYTES, + extra_bytes_in_transaction, + ); + } + + #[test] + fn millau_tx_extra_bytes_constant_is_correct() { + let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); + let millau_tx = Millau::sign_transaction( + Default::default(), + &sp_keyring::AccountKeyring::Alice.pair(), + 0, + millau_call.clone(), + ); + let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); + assert!( + bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, + "Hardcoded number of extra bytes in Millau transaction {} is lower than actual value: {}", + bp_millau::TX_EXTRA_BYTES, + extra_bytes_in_transaction, + ); + } } diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 7b9df18d8a92c..1ac12d2eebede 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -49,7 +49,10 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { (), ) .into(); - let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + Ok(transaction) } } diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/millau_messages_to_rialto.rs index ecd59e146fa13..f3dfdadf9a38d 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/millau_messages_to_rialto.rs @@ -68,7 +68,8 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let call: millau_runtime::Call = millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; - let transaction = Millau::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); + let genesis_hash = *self.source_client.genesis_hash(); + let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign.signer, nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -103,7 +104,8 @@ impl SubstrateMessageLane for MillauMessagesToRialto { ) .into(); let call_weight = call.get_dispatch_info().weight; - let transaction = Rialto::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index 6560d83c8c265..27fe697aadf76 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -49,7 +49,10 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { (), ) .into(); - let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + Ok(transaction) } } diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_messages_to_millau.rs index 07af9ce82866d..96211bd944f64 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_messages_to_millau.rs @@ -68,7 +68,8 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let call: rialto_runtime::Call = rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; - let transaction = Rialto::sign_transaction(&self.source_client, &self.source_sign.signer, nonce, call); + let genesis_hash = *self.source_client.genesis_hash(); + let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign.signer, nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -103,7 +104,8 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { ) .into(); let call_weight = call.get_dispatch_info().weight; - let transaction = Millau::sign_transaction(&self.target_client, &self.target_sign.signer, nonce, call); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", From 57d74b1b9d49ebefa91bbf7a3bb7c3656c3dc266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 8 Mar 2021 22:35:07 +0100 Subject: [PATCH 0370/1210] Use globs for workspace members. (#802) * Add all members. * Change members to globs. * Remove runtime-common. --- .../builtin => ethereum-contract-builtin}/Cargo.toml | 2 +- .../builtin => ethereum-contract-builtin}/src/lib.rs | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename modules/{ethereum-contract/builtin => ethereum-contract-builtin}/Cargo.toml (94%) rename modules/{ethereum-contract/builtin => ethereum-contract-builtin}/src/lib.rs (100%) diff --git a/modules/ethereum-contract/builtin/Cargo.toml b/modules/ethereum-contract-builtin/Cargo.toml similarity index 94% rename from modules/ethereum-contract/builtin/Cargo.toml rename to modules/ethereum-contract-builtin/Cargo.toml index 0d34cf56444e2..324afb8db878e 100644 --- a/modules/ethereum-contract/builtin/Cargo.toml +++ b/modules/ethereum-contract-builtin/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.14" # Runtime/chain specific dependencies -rialto-runtime = { path = "../../../bin/rialto/runtime" } +rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/modules/ethereum-contract/builtin/src/lib.rs b/modules/ethereum-contract-builtin/src/lib.rs similarity index 100% rename from modules/ethereum-contract/builtin/src/lib.rs rename to modules/ethereum-contract-builtin/src/lib.rs From 1ec6db2569ecded39f55382577fab69833cff9de Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 8 Mar 2021 17:13:25 -0500 Subject: [PATCH 0371/1210] Move Storage Parser from Bridge Pallet (#793) * Move storage proof checker to runtime primtives * Add method for parsing storage proofs * Use finality-verifier pallet in runtime-common * Get bridge pallet compiling again * Use storage prover from bp-runtime in a few more places * Don't leak `std` items from proof helper into `no-std` builds * Fix benchmarking compilation * Remove unused import in fuzzer --- bin/runtime-common/Cargo.toml | 6 +- bin/runtime-common/src/messages.rs | 15 ++-- .../src/messages_benchmarking.rs | 8 +-- modules/finality-verifier/Cargo.toml | 3 + modules/finality-verifier/src/lib.rs | 68 ++++++++++++++++++- modules/substrate/src/lib.rs | 11 ++- primitives/runtime/Cargo.toml | 9 +++ primitives/runtime/src/lib.rs | 5 ++ .../runtime}/src/storage_proof.rs | 63 ++++++++--------- 9 files changed, 128 insertions(+), 60 deletions(-) rename {modules/substrate => primitives/runtime}/src/storage_proof.rs (70%) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 1a6a5db5370e4..a0221cbb7cb99 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -19,7 +19,7 @@ bp-message-lane = { path = "../../primitives/message-lane", default-features = f bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } pallet-message-lane = { path = "../../modules/message-lane", default-features = false } -pallet-substrate-bridge = { path = "../../modules/substrate", default-features = false } +pallet-finality-verifier = { path = "../../modules/finality-verifier", default-features = false } # Substrate dependencies @@ -40,8 +40,8 @@ std = [ "frame-support/std", "hash-db/std", "pallet-bridge-call-dispatch/std", + "pallet-finality-verifier/std", "pallet-message-lane/std", - "pallet-substrate-bridge/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", @@ -50,7 +50,7 @@ std = [ ] runtime-benchmarks = [ "ed25519-dalek/u64_backend", + "pallet-finality-verifier/runtime-benchmarks", "pallet-message-lane/runtime-benchmarks", - "pallet-substrate-bridge/runtime-benchmarks", "sp-state-machine", ] diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 755562db1f72b..cc30a33671a15 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -26,11 +26,10 @@ use bp_message_lane::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_runtime::{InstanceId, Size}; +use bp_runtime::{InstanceId, Size, StorageProofChecker}; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; -use pallet_substrate_bridge::StorageProofChecker; use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; @@ -352,17 +351,17 @@ pub mod source { proof: FromBridgedChainMessagesDeliveryProof>>, ) -> Result, &'static str> where - ThisRuntime: pallet_substrate_bridge::Config, + ThisRuntime: pallet_finality_verifier::Config, ThisRuntime: pallet_message_lane::Config>>, HashOf>: - Into::BridgedChain>>, + Into::BridgedChain>>, { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane, } = proof; - pallet_substrate_bridge::Module::::parse_finalized_storage_proof( + pallet_finality_verifier::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), |storage| { @@ -506,16 +505,16 @@ pub mod target { messages_count: u32, ) -> Result>>>, &'static str> where - ThisRuntime: pallet_substrate_bridge::Config, + ThisRuntime: pallet_finality_verifier::Config, ThisRuntime: pallet_message_lane::Config>>, HashOf>: - Into::BridgedChain>>, + Into::BridgedChain>>, { verify_messages_proof_with_parser::( proof, messages_count, |bridged_header_hash, bridged_storage_proof| { - pallet_substrate_bridge::Module::::parse_finalized_storage_proof( + pallet_finality_verifier::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 4aa2abbd6b471..73bdd5755f068 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -73,7 +73,7 @@ pub fn prepare_message_proof( where B: MessageBridge, H: Hasher, - R: pallet_substrate_bridge::Config, + R: pallet_finality_verifier::Config, ::Hash: Into>>, MM: Fn(MessageKey) -> Vec, ML: Fn(LaneId) -> Vec, @@ -129,7 +129,7 @@ where // prepare Bridged chain header and insert it into the Substrate pallet let bridged_header = make_bridged_header(root); let bridged_header_hash = bridged_header.hash(); - pallet_substrate_bridge::initialize_for_benchmarks::(bridged_header); + pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); ( FromBridgedChainMessagesProof { @@ -154,7 +154,7 @@ pub fn prepare_message_delivery_proof( where B: MessageBridge, H: Hasher, - R: pallet_substrate_bridge::Config, + R: pallet_finality_verifier::Config, ::Hash: Into>>, ML: Fn(LaneId) -> Vec, MH: Fn(H::Out) -> ::Header, @@ -181,7 +181,7 @@ where // prepare Bridged chain header and insert it into the Substrate pallet let bridged_header = make_bridged_header(root); let bridged_header_hash = bridged_header.hash(); - pallet_substrate_bridge::initialize_for_benchmarks::(bridged_header); + pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index 539ef03a425d1..fe670aeb68fca 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -25,6 +25,7 @@ frame-system = { git = "https://github.com/paritytech/substrate.git", branch = " sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } [dev-dependencies] bp-test-utils = {path = "../../primitives/test-utils" } @@ -46,4 +47,6 @@ std = [ "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", + "sp-trie/std", ] +runtime-benchmarks = [] diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 5eba7f1588731..41a6cacc15d5f 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -56,7 +56,7 @@ pub type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; /// Block hash of the bridged chain. pub type BridgedBlockHash = HashOf<::BridgedChain>; /// Hasher of the bridged chain. -pub type _BridgedBlockHasher = HasherOf<::BridgedChain>; +pub type BridgedBlockHasher = HasherOf<::BridgedChain>; /// Header of the bridged chain. pub type BridgedHeader = HeaderOf<::BridgedChain>; @@ -335,6 +335,8 @@ pub mod pallet { TooManyRequests, /// The header being imported is older than the best finalized header known to the pallet. OldHeader, + /// The header is unknown to the pallet. + UnknownHeader, /// The scheduled authority set change found in the header is unsupported by the pallet. /// /// This is the case for non-standard (e.g forced) authority set changes. @@ -343,6 +345,8 @@ pub mod pallet { AlreadyInitialized, /// All pallet operations are halted. Halted, + /// The storage proof doesn't contains storage root. So it is invalid for given header. + StorageRootMismatch, } /// Import the given header to the pallet's storage. @@ -387,7 +391,7 @@ pub mod pallet { /// Since this writes to storage with no real checks this should only be used in functions that /// were called by a trusted origin. - fn initialize_bridge(init_params: super::InitializationData>) { + pub(crate) fn initialize_bridge(init_params: super::InitializationData>) { let super::InitializationData { header, authority_list, @@ -447,6 +451,21 @@ impl Pallet { pub fn is_known_header(hash: BridgedBlockHash) -> bool { >::contains_key(hash) } + + /// Verify that the passed storage proof is valid, given it is crafted using + /// known finalized header. If the proof is valid, then the `parse` callback + /// is called and the function returns its result. + pub fn parse_finalized_storage_proof( + hash: BridgedBlockHash, + storage_proof: sp_trie::StorageProof, + parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, + ) -> Result { + let header = >::get(hash).ok_or(Error::::UnknownHeader)?; + let storage_proof_checker = bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) + .map_err(|_| Error::::StorageRootMismatch)?; + + Ok(parse(storage_proof_checker)) + } } /// Data required for initializing the bridge pallet. @@ -499,6 +518,17 @@ pub(crate) fn find_forced_change( header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) } +/// (Re)initialize bridge with given header for using it in external benchmarks. +#[cfg(feature = "runtime-benchmarks")] +pub fn initialize_for_benchmarks(header: BridgedHeader) { + initialize_bridge::(InitializationData { + header, + authority_list: Vec::new(), // we don't verify any proofs in external benchmarks + set_id: 0, + is_halted: false, + }); +} + #[cfg(test)] mod tests { use super::*; @@ -864,6 +894,40 @@ mod tests { ); }) } + + #[test] + fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { + run_test(|| { + assert_noop!( + Module::::parse_finalized_storage_proof( + Default::default(), + sp_trie::StorageProof::new(vec![]), + |_| (), + ), + Error::::UnknownHeader, + ); + }); + } + + #[test] + fn parse_finalized_storage_accepts_valid_proof() { + run_test(|| { + let (state_root, storage_proof) = bp_runtime::craft_valid_storage_proof(); + + let mut header = test_header(2); + header.set_state_root(state_root); + + let hash = header.hash(); + >::put(hash); + >::insert(hash, header); + + assert_ok!( + Module::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), + (), + ); + }); + } + #[test] fn rate_limiter_disallows_imports_once_limit_is_hit_in_single_block() { run_test(|| { diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index abadbb9dd0aa5..86925d52cf2cc 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -46,10 +46,7 @@ use sp_trie::StorageProof; // Re-export since the node uses these when configuring genesis pub use storage::{InitializationData, ScheduledChange}; -pub use storage_proof::StorageProofChecker; - mod storage; -mod storage_proof; mod verifier; #[cfg(test)] @@ -355,7 +352,7 @@ impl Module { pub fn parse_finalized_storage_proof( finalized_header_hash: BridgedBlockHash, storage_proof: StorageProof, - parse: impl FnOnce(StorageProofChecker>) -> R, + parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, ) -> Result { let storage = PalletStorage::::new(); let header = storage @@ -365,8 +362,8 @@ impl Module { return Err(Error::::UnfinalizedHeader.into()); } - let storage_proof_checker = - StorageProofChecker::new(*header.state_root(), storage_proof).map_err(Error::::from)?; + let storage_proof_checker = bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) + .map_err(|_| Error::::StorageRootMismatch)?; Ok(parse(storage_proof_checker)) } } @@ -898,7 +895,7 @@ mod tests { fn parse_finalized_storage_accepts_valid_proof() { run_test(|| { let mut storage = PalletStorage::::new(); - let (state_root, storage_proof) = storage_proof::tests::craft_valid_storage_proof(); + let (state_root, storage_proof) = bp_runtime::craft_valid_storage_proof(); let mut header = unfinalized_header(1); header.is_finalized = true; header.header.set_state_root(state_root); diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 50305013cebf1..37d769c92802c 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -8,6 +8,7 @@ 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 @@ -17,15 +18,23 @@ sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "maste sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } + +[dev-dependencies] +sp-core = { git = "https://github.com/paritytech/substrate.git", 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", ] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 6612e26c37dca..3eb2c53771786 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -24,8 +24,13 @@ use sp_io::hashing::blake2_256; use sp_std::convert::TryFrom; pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; +pub use storage_proof::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]; diff --git a/modules/substrate/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs similarity index 70% rename from modules/substrate/src/storage_proof.rs rename to primitives/runtime/src/storage_proof.rs index 4b908dde15e9f..4c8c2047d2fd4 100644 --- a/modules/substrate/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -14,12 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// TODO: remove on actual use -#![allow(dead_code)] - //! Logic for checking Substrate storage proofs. use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; +use sp_core::H256; use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; use sp_trie::{read_trie_value, Layout, MemoryDB, StorageProof}; @@ -65,49 +63,42 @@ pub enum Error { StorageValueUnavailable, } -impl From for crate::Error { - fn from(error: Error) -> Self { - match error { - Error::StorageRootMismatch => crate::Error::StorageRootMismatch, - Error::StorageValueUnavailable => crate::Error::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() -> (H256, StorageProof) { + use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; + + // construct storage proof + let backend = >::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::*; - use sp_core::{Blake2Hasher, H256}; - use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; - - /// Return valid storage proof and state root. - pub fn craft_valid_storage_proof() -> (H256, StorageProof) { - // construct storage proof - let backend = >::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) - } - #[test] fn storage_proof_check() { let (root, proof) = craft_valid_storage_proof(); // check proof in runtime - let checker = >::new(root, proof.clone()).unwrap(); + let checker = >::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)); @@ -115,7 +106,7 @@ pub mod tests { // checking proof against invalid commitment fails assert_eq!( - >::new(H256::random(), proof).err(), + >::new(H256::random(), proof).err(), Some(Error::StorageRootMismatch) ); } From ce5cbbad46e18d4ceddd8ab0c3dbf2adf6a14174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 9 Mar 2021 12:46:53 +0100 Subject: [PATCH 0372/1210] Add Transaction Payment Custom RPC (#806) * Transaction payment RPC. * Add payment RuntimeApi to fix the build. * cargo fmt --all --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/service.rs | 5 ++++- bin/millau/runtime/Cargo.toml | 2 ++ bin/millau/runtime/src/lib.rs | 13 +++++++++++++ bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/service.rs | 4 ++++ bin/rialto/runtime/Cargo.toml | 2 ++ bin/rialto/runtime/src/lib.rs | 13 +++++++++++++ 8 files changed, 40 insertions(+), 1 deletion(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index e035bbd224250..9684799f2feea 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -27,6 +27,7 @@ pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 2f72e5717faee..0729353af3454 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -224,6 +224,7 @@ pub fn new_full(mut config: Configuration) -> Result } use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; @@ -246,6 +247,9 @@ pub fn new_full(mut config: Configuration) -> Result pool.clone(), DenyUnsafe::No, ))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( + client.clone(), + ))); io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( shared_authority_set.clone(), shared_voter_state.clone(), @@ -257,7 +261,6 @@ pub fn new_full(mut config: Configuration) -> Result backend.clone(), Arc::new(MillauMessageLaneKeys), ))); - io }) }; diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 58ce4f127a085..204beee9988be 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -40,6 +40,7 @@ pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = pallet-sudo = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -84,6 +85,7 @@ std = [ "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment/std", + "pallet-transaction-payment-rpc-runtime-api/std", "serde", "sp-api/std", "sp-block-builder/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 0add4f3235676..d1ef18eb3c175 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -37,6 +37,7 @@ use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; +use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -494,6 +495,18 @@ impl_runtime_apis! { } } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< + Block, + Balance, + > for Runtime { + fn query_info(uxt: ::Extrinsic, len: u32) -> RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + } + impl sp_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { SessionKeys::generate(seed) diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 9d3e3fc16c2ab..e8095543eea27 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -27,6 +27,7 @@ rialto-runtime = { path = "../runtime" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 67ca185137c0a..5c5ff92e88309 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -224,6 +224,7 @@ pub fn new_full(mut config: Configuration) -> Result } use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{FullSystem, SystemApi}; @@ -246,6 +247,9 @@ pub fn new_full(mut config: Configuration) -> Result pool.clone(), DenyUnsafe::No, ))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( + client.clone(), + ))); io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( shared_authority_set.clone(), shared_voter_state.clone(), diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index d69e241870b4f..d93f5d2b0a629 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -48,6 +48,7 @@ pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = pallet-sudo = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } @@ -102,6 +103,7 @@ std = [ "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment/std", + "pallet-transaction-payment-rpc-runtime-api/std", "serde", "sp-api/std", "sp-block-builder/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 18c88a188627b..6410e824221c5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -43,6 +43,7 @@ use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; +use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -691,6 +692,18 @@ impl_runtime_apis! { } } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< + Block, + Balance, + > for Runtime { + fn query_info(uxt: ::Extrinsic, len: u32) -> RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + } + impl sp_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { SessionKeys::generate(seed) From 1f2900107f30f5768a4aa6ac7be2e8acdd944f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 9 Mar 2021 16:44:00 +0100 Subject: [PATCH 0373/1210] Uniform git dependencies (Backport of substrate#2589) (#805) * Make Substrate deps uniform * Rest of the deps. * Fix broken merge. * Revert substrate. * Fix tests Co-authored-by: Pierre Krieger --- bin/millau/node/Cargo.toml | 48 ++++++++--------- bin/millau/runtime/Cargo.toml | 50 +++++++++--------- bin/rialto/node/Cargo.toml | 51 +++++++++--------- bin/rialto/runtime/Cargo.toml | 55 ++++++++++---------- bin/runtime-common/Cargo.toml | 12 ++--- modules/call-dispatch/Cargo.toml | 12 ++--- modules/currency-exchange/Cargo.toml | 14 ++--- modules/ethereum-contract-builtin/Cargo.toml | 10 ++-- modules/ethereum/Cargo.toml | 12 ++--- modules/finality-verifier/Cargo.toml | 15 +++--- modules/message-lane/Cargo.toml | 16 +++--- modules/message-lane/rpc/Cargo.toml | 12 ++--- modules/shift-session-manager/Cargo.toml | 14 ++--- modules/substrate/Cargo.toml | 18 +++---- primitives/currency-exchange/Cargo.toml | 6 +-- primitives/ethereum-poa/Cargo.toml | 8 +-- primitives/header-chain/Cargo.toml | 10 ++-- primitives/kusama/Cargo.toml | 12 ++--- primitives/message-lane/Cargo.toml | 6 +-- primitives/millau/Cargo.toml | 16 +++--- primitives/polkadot/Cargo.toml | 12 ++--- primitives/rialto/Cargo.toml | 12 ++--- primitives/runtime/Cargo.toml | 17 +++--- primitives/test-utils/Cargo.toml | 6 +-- relays/ethereum/Cargo.toml | 12 ++--- relays/kusama-client/Cargo.toml | 12 ++--- relays/millau-client/Cargo.toml | 12 ++--- relays/polkadot-client/Cargo.toml | 12 ++--- relays/rialto-client/Cargo.toml | 12 ++--- relays/substrate-client/Cargo.toml | 18 +++---- relays/substrate/Cargo.toml | 12 ++--- relays/utils/Cargo.toml | 2 +- 32 files changed, 269 insertions(+), 267 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 9684799f2feea..d41f23fb03d1b 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -24,33 +24,33 @@ pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -node-inspect = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } -sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] substrate-build-script-utils = "3.0.0" -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = [] diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 204beee9988be..8b54741f19f5e 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -28,32 +28,32 @@ pallet-substrate-bridge = { path = "../../../modules/substrate", default-feature # Substrate Dependencies -frame-executive = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-consensus-aura = { 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-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [build-dependencies] wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2.0.0" } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index e8095543eea27..cda8c7fa95762 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -24,34 +24,35 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -node-inspect = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master", features = ["wasmtime"] } -sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-executor = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-telemetry = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-consensus = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } + +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] substrate-build-script-utils = "3.0.0" -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = [] diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index d93f5d2b0a629..1fa22e22fe96b 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -35,34 +35,35 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-offchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-consensus-aura = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } + [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index a0221cbb7cb99..dfae0861bbfc9 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -23,12 +23,12 @@ pallet-finality-verifier = { path = "../../modules/finality-verifier", default-f # Substrate dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", 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-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, optional = true } +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"] diff --git a/modules/call-dispatch/Cargo.toml b/modules/call-dispatch/Cargo.toml index 99c7962dc34c8..3c5fb6cba0c16 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/call-dispatch/Cargo.toml @@ -17,14 +17,14 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } serde = "1.0" [features] diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index f12fa1fc8d52a..8094f0f2b6eeb 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -18,15 +18,15 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/modules/ethereum-contract-builtin/Cargo.toml b/modules/ethereum-contract-builtin/Cargo.toml index 324afb8db878e..82e287a3abdcd 100644 --- a/modules/ethereum-contract-builtin/Cargo.toml +++ b/modules/ethereum-contract-builtin/Cargo.toml @@ -19,10 +19,10 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-blockchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 219242be1493a..fdd93ed73311b 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -18,12 +18,12 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } diff --git a/modules/finality-verifier/Cargo.toml b/modules/finality-verifier/Cargo.toml index fe670aeb68fca..e4af91d75381c 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/finality-verifier/Cargo.toml @@ -20,18 +20,17 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-finality-grandpa = { 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-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] bp-test-utils = {path = "../../primitives/test-utils" } pallet-substrate-bridge = { path = "../../modules/substrate" } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } - +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 69160e3afb795..8a411dcb91679 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -20,17 +20,17 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] hex-literal = "0.3" -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/message-lane/rpc/Cargo.toml index 28481a7ad8834..23dac80b407c0 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/message-lane/rpc/Cargo.toml @@ -21,9 +21,9 @@ bp-message-lane = { path = "../../../primitives/message-lane" } # Substrate Dependencies -sc-client-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-blockchain = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 04a5194c34942..6dac97ddde601 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -11,15 +11,15 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-staking = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-staking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } serde = "1.0" [features] diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml index cffb942f0134d..bcd9faaede768 100644 --- a/modules/substrate/Cargo.toml +++ b/modules/substrate/Cargo.toml @@ -21,18 +21,18 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-finality-grandpa = { 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-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] bp-test-utils = {path = "../../primitives/test-utils" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 585855b294ee3..43367ba7992b1 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -11,9 +11,9 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 86cb43193c003..cd2c3a97a0f32 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -24,10 +24,10 @@ triehash = { version = "0.8.2", default-features = false } # Substrate Dependencies -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] hex-literal = "0.2" diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 8a017610a3e86..dc58dafb979ef 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -13,11 +13,11 @@ serde = { version = "1.0", optional = true } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", 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-finality-grandpa = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] bp-test-utils = { path = "../test-utils" } diff --git a/primitives/kusama/Cargo.toml b/primitives/kusama/Cargo.toml index 1a4142f75a317..784f0b013289a 100644 --- a/primitives/kusama/Cargo.toml +++ b/primitives/kusama/Cargo.toml @@ -15,12 +15,12 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/message-lane/Cargo.toml b/primitives/message-lane/Cargo.toml index 451a3c0400ad0..cbddcb1614606 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/message-lane/Cargo.toml @@ -15,9 +15,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/millau/Cargo.toml b/primitives/millau/Cargo.toml index aea2f8eec2efc..124d8199e2c23 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/millau/Cargo.toml @@ -21,14 +21,14 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { 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-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"] diff --git a/primitives/polkadot/Cargo.toml b/primitives/polkadot/Cargo.toml index 396cbd5b47ea0..f7c9b9717d1cd 100644 --- a/primitives/polkadot/Cargo.toml +++ b/primitives/polkadot/Cargo.toml @@ -15,12 +15,12 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/rialto/Cargo.toml b/primitives/rialto/Cargo.toml index 6d12dd0b0a413..d6c12fc84809b 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/rialto/Cargo.toml @@ -15,12 +15,12 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [features] default = ["std"] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 37d769c92802c..17fa96b2c908c 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -13,16 +13,17 @@ num-traits = { version = "0.2", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" , default-features = false } -sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "master", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate.git", 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.git", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } + [features] default = ["std"] diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 2b9bb5cd191c2..396e0e764635c 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -8,6 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] finality-grandpa = { version = "0.14.0" } bp-header-chain = { path = "../header-chain" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index e6f507625b60d..b7fe7273c155f 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -40,9 +40,9 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/kusama-client/Cargo.toml b/relays/kusama-client/Cargo.toml index 6695758113ad7..04958cf2b3618 100644 --- a/relays/kusama-client/Cargo.toml +++ b/relays/kusama-client/Cargo.toml @@ -17,9 +17,9 @@ bp-kusama = { path = "../../primitives/kusama" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/millau-client/Cargo.toml b/relays/millau-client/Cargo.toml index c05d44a42e92c..5f9cbd170c938 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/millau-client/Cargo.toml @@ -17,9 +17,9 @@ millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/polkadot-client/Cargo.toml b/relays/polkadot-client/Cargo.toml index 5a05aa0a2cf46..8764b6509b242 100644 --- a/relays/polkadot-client/Cargo.toml +++ b/relays/polkadot-client/Cargo.toml @@ -17,9 +17,9 @@ bp-polkadot = { path = "../../primitives/polkadot" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/rialto-client/Cargo.toml b/relays/rialto-client/Cargo.toml index 6c90defe37a11..6142ba05c963c 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/rialto-client/Cargo.toml @@ -17,9 +17,9 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/substrate-client/Cargo.toml b/relays/substrate-client/Cargo.toml index 8a794c86081b6..d02c08ab7ad70 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/substrate-client/Cargo.toml @@ -27,15 +27,15 @@ relay-utils = { path = "../utils" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-version = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } #[dev-dependencies] futures = "0.3.7" diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index b56b3a3cbddb9..7aeefb3cab56a 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -43,11 +43,11 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 01aa866ee43d1..ce6a20bbc4fee 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -19,4 +19,4 @@ time = "0.2" # Substrate dependencies -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate.git", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } From 76a414dcc960cc7f289d10fc050a70d39d06a9e8 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 10 Mar 2021 09:45:15 -0500 Subject: [PATCH 0374/1210] Simplify operational extrinsics (#810) * Simplify operational extrinsics * Remove old extrinsics from finality verifier --- modules/finality-verifier/src/lib.rs | 49 ++++++++++++---------------- modules/message-lane/src/lib.rs | 47 ++++++++++++-------------- 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 41a6cacc15d5f..7c331bc09e561 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -222,26 +222,19 @@ pub mod pallet { Ok(().into()) } - /// Halt all pallet operations. Operations may be resumed using `resume_operations` call. + /// Halt or resume all pallet operations. /// /// May only be called either by root, or by `ModuleOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn halt_operations(origin: OriginFor) -> DispatchResultWithPostInfo { + pub fn set_operational(origin: OriginFor, operational: bool) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; - >::put(true); - log::warn!("Stopping pallet operations."); + >::put(operational); - Ok(().into()) - } - - /// Resume all pallet operations. May be called even if pallet is halted. - /// - /// May only be called either by root, or by `ModuleOwner`. - #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn resume_operations(origin: OriginFor) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; - >::put(false); - log::info!("Resuming pallet operations."); + if operational { + log::info!("Resuming pallet operations."); + } else { + log::warn!("Stopping pallet operations."); + } Ok(().into()) } @@ -655,29 +648,29 @@ mod tests { assert_ok!(Module::::set_owner(Origin::root(), Some(1))); assert_noop!( - Module::::halt_operations(Origin::signed(2)), + Module::::set_operational(Origin::signed(2), false), DispatchError::BadOrigin, ); - assert_ok!(Module::::halt_operations(Origin::root())); + assert_ok!(Module::::set_operational(Origin::root(), false)); assert_ok!(Module::::set_owner(Origin::signed(1), None)); assert_noop!( - Module::::resume_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); assert_noop!( - Module::::resume_operations(Origin::signed(2)), + Module::::set_operational(Origin::signed(2), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::resume_operations(Origin::root())); + assert_ok!(Module::::set_operational(Origin::root(), true)); }); } #[test] fn pallet_may_be_halted_by_root() { run_test(|| { - assert_ok!(Module::::halt_operations(Origin::root())); - assert_ok!(Module::::resume_operations(Origin::root())); + assert_ok!(Module::::set_operational(Origin::root(), false)); + assert_ok!(Module::::set_operational(Origin::root(), true)); }); } @@ -686,21 +679,21 @@ mod tests { run_test(|| { ModuleOwner::::put(2); - assert_ok!(Module::::halt_operations(Origin::signed(2))); - assert_ok!(Module::::resume_operations(Origin::signed(2))); + assert_ok!(Module::::set_operational(Origin::signed(2), false)); + assert_ok!(Module::::set_operational(Origin::signed(2), true)); assert_noop!( - Module::::halt_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), false), DispatchError::BadOrigin, ); assert_noop!( - Module::::resume_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_ok!(Module::::set_operational(Origin::signed(2), false)); assert_noop!( - Module::::resume_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); }); diff --git a/modules/message-lane/src/lib.rs b/modules/message-lane/src/lib.rs index cf434229ff165..3132773eadd10 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/message-lane/src/lib.rs @@ -264,24 +264,19 @@ decl_module! { } } - /// Halt all pallet operations. Operations may be resumed using `resume_operations` call. + /// Halt or resume all pallet operations. /// /// May only be called either by root, or by `ModuleOwner`. #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn halt_operations(origin) { + pub fn set_operational(origin, operational: bool) { ensure_owner_or_root::(origin)?; - IsHalted::::put(true); - log::warn!("Stopping pallet operations."); - } + >::put(operational); - /// Resume all pallet operations. May be called even if pallet is halted. - /// - /// May only be called either by root, or by `ModuleOwner`. - #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn resume_operations(origin) { - ensure_owner_or_root::(origin)?; - IsHalted::::put(false); - log::info!("Resuming pallet operations."); + if operational { + log::info!("Resuming pallet operations."); + } else { + log::warn!("Stopping pallet operations."); + } } /// Update pallet parameter. @@ -915,29 +910,29 @@ mod tests { assert_ok!(Module::::set_owner(Origin::root(), Some(1))); assert_noop!( - Module::::halt_operations(Origin::signed(2)), + Module::::set_operational(Origin::signed(2), false), DispatchError::BadOrigin, ); - assert_ok!(Module::::halt_operations(Origin::root())); + assert_ok!(Module::::set_operational(Origin::root(), false)); assert_ok!(Module::::set_owner(Origin::signed(1), None)); assert_noop!( - Module::::resume_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); assert_noop!( - Module::::resume_operations(Origin::signed(2)), + Module::::set_operational(Origin::signed(2), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::resume_operations(Origin::root())); + assert_ok!(Module::::set_operational(Origin::root(), true)); }); } #[test] fn pallet_may_be_halted_by_root() { run_test(|| { - assert_ok!(Module::::halt_operations(Origin::root())); - assert_ok!(Module::::resume_operations(Origin::root())); + assert_ok!(Module::::set_operational(Origin::root(), false)); + assert_ok!(Module::::set_operational(Origin::root(), true)); }); } @@ -946,21 +941,21 @@ mod tests { run_test(|| { ModuleOwner::::put(2); - assert_ok!(Module::::halt_operations(Origin::signed(2))); - assert_ok!(Module::::resume_operations(Origin::signed(2))); + assert_ok!(Module::::set_operational(Origin::signed(2), false)); + assert_ok!(Module::::set_operational(Origin::signed(2), true)); assert_noop!( - Module::::halt_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), false), DispatchError::BadOrigin, ); assert_noop!( - Module::::resume_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::halt_operations(Origin::signed(2))); + assert_ok!(Module::::set_operational(Origin::signed(2), false)); assert_noop!( - Module::::resume_operations(Origin::signed(1)), + Module::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); }); From 27a3670ffdde8b845c828558bde97f867e994f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 10 Mar 2021 15:54:18 +0100 Subject: [PATCH 0375/1210] Add Westend & Rococo primitives (#808) * Move chain primitives to a sub-folder. * Update workspace members. * Extract core parts of polkadot. * cargo fmt --all * Remove TODO. * cargo fmt --all * Fix crate names. * Add to the latest API. * cargo fmt --all * Add nested lock files to ignore (generated during cargo fmt) * Fix compilation. * cargo fmt --all * Fix ignore pattern. * Address review comments. --- bin/millau/node/Cargo.toml | 2 +- bin/millau/runtime/Cargo.toml | 4 +- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 4 +- modules/message-lane/Cargo.toml | 2 +- primitives/chains/kusama/Cargo.toml | 28 +++ primitives/chains/kusama/src/lib.rs | 117 +++++++++++++ primitives/{ => chains}/millau/Cargo.toml | 4 +- primitives/{ => chains}/millau/src/lib.rs | 0 .../{ => chains}/millau/src/millau_hash.rs | 0 primitives/chains/polkadot/Cargo.toml | 29 ++++ primitives/chains/polkadot/src/lib.rs | 117 +++++++++++++ primitives/{ => chains}/rialto/Cargo.toml | 4 +- primitives/{ => chains}/rialto/src/lib.rs | 0 primitives/chains/rococo/Cargo.toml | 28 +++ primitives/chains/rococo/src/lib.rs | 117 +++++++++++++ primitives/chains/westend/Cargo.toml | 28 +++ primitives/chains/westend/src/lib.rs | 117 +++++++++++++ primitives/kusama/src/lib.rs | 164 ------------------ .../{kusama => polkadot-core}/Cargo.toml | 4 +- primitives/polkadot-core/src/lib.rs | 96 ++++++++++ primitives/polkadot/Cargo.toml | 36 ---- primitives/polkadot/src/lib.rs | 164 ------------------ primitives/runtime/src/lib.rs | 6 + relays/ethereum-client/Cargo.toml | 2 +- relays/ethereum/Cargo.toml | 6 +- relays/kusama-client/Cargo.toml | 2 +- relays/polkadot-client/Cargo.toml | 2 +- relays/substrate/Cargo.toml | 8 +- 29 files changed, 706 insertions(+), 387 deletions(-) create mode 100644 primitives/chains/kusama/Cargo.toml create mode 100644 primitives/chains/kusama/src/lib.rs rename primitives/{ => chains}/millau/Cargo.toml (93%) rename primitives/{ => chains}/millau/src/lib.rs (100%) rename primitives/{ => chains}/millau/src/millau_hash.rs (100%) create mode 100644 primitives/chains/polkadot/Cargo.toml create mode 100644 primitives/chains/polkadot/src/lib.rs rename primitives/{ => chains}/rialto/Cargo.toml (88%) rename primitives/{ => chains}/rialto/src/lib.rs (100%) create mode 100644 primitives/chains/rococo/Cargo.toml create mode 100644 primitives/chains/rococo/src/lib.rs create mode 100644 primitives/chains/westend/Cargo.toml create mode 100644 primitives/chains/westend/src/lib.rs delete mode 100644 primitives/kusama/src/lib.rs rename primitives/{kusama => polkadot-core}/Cargo.toml (93%) create mode 100644 primitives/polkadot-core/src/lib.rs delete mode 100644 primitives/polkadot/Cargo.toml delete mode 100644 primitives/polkadot/src/lib.rs diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index d41f23fb03d1b..4e8606b497ef4 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -16,7 +16,7 @@ structopt = "0.3.21" # Bridge dependencies bp-message-lane = { path = "../../../primitives/message-lane" } -bp-millau= { path = "../../../primitives/millau" } +bp-millau= { path = "../../../primitives/chains/millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } pallet-message-lane = { path = "../../../modules/message-lane" } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 8b54741f19f5e..058598e5c1c01 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -16,8 +16,8 @@ serde = { version = "1.0.124", optional = true, features = ["derive"] } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } -bp-millau = { path = "../../../primitives/millau", default-features = false } -bp-rialto = { path = "../../../primitives/rialto", default-features = false } +bp-millau = { path = "../../../primitives/chains/millau", default-features = false } +bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index cda8c7fa95762..d287b0c3c9f3f 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ structopt = "0.3.21" bp-message-lane = { path = "../../../primitives/message-lane" } bp-runtime = { path = "../../../primitives/runtime" } -bp-rialto = { path = "../../../primitives/rialto" } +bp-rialto = { path = "../../../primitives/chains/rialto" } pallet-message-lane = { path = "../../../modules/message-lane" } pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } rialto-runtime = { path = "../runtime" } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 1fa22e22fe96b..bb4740071e86e 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -21,8 +21,8 @@ bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = fal bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } -bp-millau = { path = "../../../primitives/millau", default-features = false } -bp-rialto = { path = "../../../primitives/rialto", default-features = false } +bp-millau = { path = "../../../primitives/chains/millau", default-features = false } +bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } diff --git a/modules/message-lane/Cargo.toml b/modules/message-lane/Cargo.toml index 8a411dcb91679..d4bced08110b6 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/message-lane/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies bp-message-lane = { path = "../../primitives/message-lane", default-features = false } -bp-rialto = { path = "../../primitives/rialto", default-features = false } +bp-rialto = { path = "../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies diff --git a/primitives/chains/kusama/Cargo.toml b/primitives/chains/kusama/Cargo.toml new file mode 100644 index 0000000000000..bb65292883b07 --- /dev/null +++ b/primitives/chains/kusama/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "bp-kusama" +description = "Primitives of Kusama runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies +bp-message-lane = { path = "../../message-lane", default-features = false } +bp-polkadot-core = { path = "../../polkadot-core", default-features = false } +bp-runtime = { path = "../../runtime", default-features = false } + +# Substrate Based Dependencies +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/chains/kusama/src/lib.rs b/primitives/chains/kusama/src/lib.rs new file mode 100644 index 0000000000000..4e1134f162d37 --- /dev/null +++ b/primitives/chains/kusama/src/lib.rs @@ -0,0 +1,117 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use sp_std::prelude::*; + +pub use bp_polkadot_core::*; + +/// Kusama Chain +pub type Kusama = PolkadotLike; + +// We use this to get the account on Kusama (target) which is derived from Polkadot's (source) +// account. +pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::POLKADOT_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + +/// Name of the `KusamaFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; +/// Name of the `KusamaFinalityApi::is_known_header` runtime method. +pub const IS_KNOWN_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_is_known_header"; + +/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToKusamaOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_KUSAMA_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToKusamaOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToKusamaOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD: &str = "ToKusamaOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToKusamaOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = "ToKusamaOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromKusamaInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = "FromKusamaInboundLaneApi_latest_received_nonce"; +/// Name of the `FromKusamaInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromKusamaInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromKusamaInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = "FromKusamaInboundLaneApi_unrewarded_relayers_state"; + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized Kusama headers. + /// + /// This API is implemented by runtimes that are bridging with the Kusama chain, not the + /// Kusama runtime itself. + pub trait KusamaFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Kusama chain. + /// + /// This API is implemented by runtimes that are sending messages to Kusama chain, not the + /// Kusama runtime itself. + pub trait ToKusamaOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Kusama from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight, u32)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Kusama chain. + /// + /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the + /// Kusama runtime itself. + pub trait FromKusamaInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } +} diff --git a/primitives/millau/Cargo.toml b/primitives/chains/millau/Cargo.toml similarity index 93% rename from primitives/millau/Cargo.toml rename to primitives/chains/millau/Cargo.toml index 124d8199e2c23..a7df6f6bbd7ea 100644 --- a/primitives/millau/Cargo.toml +++ b/primitives/chains/millau/Cargo.toml @@ -10,8 +10,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-message-lane = { path = "../message-lane", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-message-lane = { path = "../../message-lane", default-features = false } +bp-runtime = { path = "../../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.5.0", default-features = false } diff --git a/primitives/millau/src/lib.rs b/primitives/chains/millau/src/lib.rs similarity index 100% rename from primitives/millau/src/lib.rs rename to primitives/chains/millau/src/lib.rs diff --git a/primitives/millau/src/millau_hash.rs b/primitives/chains/millau/src/millau_hash.rs similarity index 100% rename from primitives/millau/src/millau_hash.rs rename to primitives/chains/millau/src/millau_hash.rs diff --git a/primitives/chains/polkadot/Cargo.toml b/primitives/chains/polkadot/Cargo.toml new file mode 100644 index 0000000000000..e1e646d5a1209 --- /dev/null +++ b/primitives/chains/polkadot/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "bp-polkadot" +description = "Primitives of Polkadot runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies +bp-message-lane = { path = "../../message-lane", default-features = false } +bp-polkadot-core = { path = "../../polkadot-core", default-features = false } +bp-runtime = { path = "../../runtime", default-features = false } + +# Substrate Based Dependencies + +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/chains/polkadot/src/lib.rs b/primitives/chains/polkadot/src/lib.rs new file mode 100644 index 0000000000000..53fe1917ea7b7 --- /dev/null +++ b/primitives/chains/polkadot/src/lib.rs @@ -0,0 +1,117 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use sp_std::prelude::*; + +pub use bp_polkadot_core::*; + +/// Polkadot Chain +pub type Polkadot = PolkadotLike; + +// We use this to get the account on Polkadot (target) which is derived from Kusama's (source) +// account. +pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::KUSAMA_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + +/// Name of the `PolkadotFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; +/// Name of the `PolkadotFinalityApi::is_known_header` runtime method. +pub const IS_KNOWN_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_is_known_header"; + +/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToPolkadotOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_POLKADOT_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToPolkadotOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToPolkadotOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD: &str = "ToPolkadotOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToPolkadotOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = "ToPolkadotOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromPolkadotInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = "FromPolkadotInboundLaneApi_latest_received_nonce"; +/// Name of the `FromPolkadotInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromPolkadotInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromPolkadotInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_POLKADOT_UNREWARDED_RELAYERS_STATE: &str = "FromPolkadotInboundLaneApi_unrewarded_relayers_state"; + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized Polkadot headers. + /// + /// This API is implemented by runtimes that are bridging with the Polkadot chain, not the + /// Polkadot runtime itself. + pub trait PolkadotFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Polkadot chain. + /// + /// This API is implemented by runtimes that are sending messages to Polkadot chain, not the + /// Polkadot runtime itself. + pub trait ToPolkadotOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Polkadot from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight, u32)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Polkadot chain. + /// + /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the + /// Polkadot runtime itself. + pub trait FromPolkadotInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } +} diff --git a/primitives/rialto/Cargo.toml b/primitives/chains/rialto/Cargo.toml similarity index 88% rename from primitives/rialto/Cargo.toml rename to primitives/chains/rialto/Cargo.toml index d6c12fc84809b..a225f79b3432b 100644 --- a/primitives/rialto/Cargo.toml +++ b/primitives/chains/rialto/Cargo.toml @@ -10,8 +10,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-message-lane = { path = "../message-lane", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-message-lane = { path = "../../message-lane", default-features = false } +bp-runtime = { path = "../../runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/rialto/src/lib.rs b/primitives/chains/rialto/src/lib.rs similarity index 100% rename from primitives/rialto/src/lib.rs rename to primitives/chains/rialto/src/lib.rs diff --git a/primitives/chains/rococo/Cargo.toml b/primitives/chains/rococo/Cargo.toml new file mode 100644 index 0000000000000..dc09d1a3bf305 --- /dev/null +++ b/primitives/chains/rococo/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "bp-rococo" +description = "Primitives of Rococo runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies +bp-message-lane = { path = "../../message-lane", default-features = false } +bp-polkadot-core = { path = "../../polkadot-core", default-features = false } +bp-runtime = { path = "../../runtime", default-features = false } + +# Substrate Based Dependencies +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/chains/rococo/src/lib.rs b/primitives/chains/rococo/src/lib.rs new file mode 100644 index 0000000000000..ef372540a340a --- /dev/null +++ b/primitives/chains/rococo/src/lib.rs @@ -0,0 +1,117 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_message_lane::{LaneId, Weight, MessageNonce, UnrewardedRelayersState}; +use sp_std::prelude::*; + +pub use bp_polkadot_core::*; + +/// Rococo Chain +pub type Rococo = PolkadotLike; + +// We use this to get the account on Rococo (target) which is derived from Westend's (source) +// account. +pub fn derive_account_from_westend_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::WESTEND_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + +/// Name of the `RococoFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; +/// Name of the `RococoFinalityApi::is_known_header` runtime method. +pub const IS_KNOWN_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_is_known_header"; + +/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToRococoOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_ROCOCO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRococoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToRococoOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRococoOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToRococoOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRococoOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromRococoInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRococoInboundLaneApi_latest_received_nonce"; +/// Name of the `FromRococoInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRococoInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromRococoInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromRococoInboundLaneApi_unrewarded_relayers_state"; + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized Rococo headers. + /// + /// This API is implemented by runtimes that are bridging with the Rococo chain, not the + /// Rococo runtime itself. + pub trait RococoFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Rococo chain. + /// + /// This API is implemented by runtimes that are sending messages to Rococo chain, not the + /// Rococo runtime itself. + pub trait ToRococoOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Rococo from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight, u32)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Rococo chain. + /// + /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the + /// Rococo runtime itself. + pub trait FromRococoInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } +} diff --git a/primitives/chains/westend/Cargo.toml b/primitives/chains/westend/Cargo.toml new file mode 100644 index 0000000000000..6253f4bef9694 --- /dev/null +++ b/primitives/chains/westend/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "bp-westend" +description = "Primitives of Westend runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies +bp-message-lane = { path = "../../message-lane", default-features = false } +bp-polkadot-core = { path = "../../polkadot-core", default-features = false } +bp-runtime = { path = "../../runtime", default-features = false } + +# Substrate Based Dependencies +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-message-lane/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/chains/westend/src/lib.rs b/primitives/chains/westend/src/lib.rs new file mode 100644 index 0000000000000..a2345e3b76daa --- /dev/null +++ b/primitives/chains/westend/src/lib.rs @@ -0,0 +1,117 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_message_lane::{LaneId, Weight, MessageNonce, UnrewardedRelayersState}; +use sp_std::prelude::*; + +pub use bp_polkadot_core::*; + +/// Westend Chain +pub type Westend = PolkadotLike; + +// We use this to get the account on Westend (target) which is derived from Rococo's (source) +// account. +pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + +/// Name of the `WestendFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; +/// Name of the `WestendFinalityApi::is_known_header` runtime method. +pub const IS_KNOWN_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_is_known_header"; + +/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_WESTEND_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToWestendOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToWestendOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_WESTEND_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToWestendOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToWestendOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_WESTEND_LATEST_GENERATED_NONCE_METHOD: &str = "ToWestendOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToWestendOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = "ToWestendOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromWestendInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = "FromWestendInboundLaneApi_latest_received_nonce"; +/// Name of the `FromWestendInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_WESTEND_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWestendInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromWestendInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_WESTEND_UNREWARDED_RELAYERS_STATE: &str = "FromWestendInboundLaneApi_unrewarded_relayers_state"; + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized Westend headers. + /// + /// This API is implemented by runtimes that are bridging with the Westend chain, not the + /// Westend runtime itself. + pub trait WestendFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Westend chain. + /// + /// This API is implemented by runtimes that are sending messages to Westend chain, not the + /// Westend runtime itself. + pub trait ToWestendOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Westend from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight, u32)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Westend chain. + /// + /// This API is implemented by runtimes that are receiving messages from Westend chain, not the + /// Westend runtime itself. + pub trait FromWestendInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } +} diff --git a/primitives/kusama/src/lib.rs b/primitives/kusama/src/lib.rs deleted file mode 100644 index 9ec032dbd5138..0000000000000 --- a/primitives/kusama/src/lib.rs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2019-2020 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] - -use bp_message_lane::{LaneId, MessageNonce}; -use bp_runtime::Chain; -use frame_support::{weights::Weight, RuntimeDebug}; -use sp_core::Hasher as HasherT; -use sp_runtime::{ - generic, - traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, -}; -use sp_std::prelude::*; - -// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 -/// Maximal number of messages in single delivery transaction. -pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; - -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; - -// TODO: should be selected keeping in mind: -// finality delay on both chains + reward payout cost + messages throughput. -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; - -/// Block number type used in Kusama. -pub type BlockNumber = u32; - -/// Hash type used in Kusama. -pub type Hash = ::Out; - -/// The type of an object that can produce hashes on Kusama. -pub type Hasher = BlakeTwo256; - -/// The header type used by Kusama. -pub type Header = generic::Header; - -/// Signature type used by Kusama. -pub type Signature = MultiSignature; - -/// Public key of account on Kusama chain. -pub type AccountPublic = ::Signer; - -/// Id of account on Kusama chain. -pub type AccountId = ::AccountId; - -/// Index of a transaction on the Kusama chain. -pub type Nonce = u32; - -/// Block type of Kusama. -pub type Block = generic::Block; - -/// Kusama block signed with a Justification. -pub type SignedBlock = generic::SignedBlock; - -/// The balance of an account on Polkadot. -pub type Balance = u128; - -/// Kusama chain. -#[derive(RuntimeDebug)] -pub struct Kusama; - -impl Chain for Kusama { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; -} - -/// Convert a 256-bit hash into an AccountId. -pub struct AccountIdConverter; - -impl sp_runtime::traits::Convert for AccountIdConverter { - fn convert(hash: sp_core::H256) -> AccountId { - hash.to_fixed_bytes().into() - } -} - -/// Name of the `KusamaHeaderApi::best_blocks` runtime method. -pub const BEST_KUSAMA_BLOCKS_METHOD: &str = "KusamaHeaderApi_best_blocks"; -/// Name of the `KusamaHeaderApi::finalized_block` runtime method. -pub const FINALIZED_KUSAMA_BLOCK_METHOD: &str = "KusamaHeaderApi_finalized_block"; -/// Name of the `KusamaHeaderApi::is_known_block` runtime method. -pub const IS_KNOWN_KUSAMA_BLOCK_METHOD: &str = "KusamaHeaderApi_is_known_block"; -/// Name of the `KusamaHeaderApi::incomplete_headers` runtime method. -pub const INCOMPLETE_KUSAMA_HEADERS_METHOD: &str = "KusamaHeaderApi_incomplete_headers"; - -sp_api::decl_runtime_apis! { - /// API for querying information about Kusama headers from the Bridge Pallet instance. - /// - /// This API is implemented by runtimes that are bridging with Kusama chain, not the - /// Kusama runtime itself. - pub trait KusamaHeaderApi { - /// Returns number and hash of the best blocks known to the bridge module. - /// - /// Will return multiple headers if there are many headers at the same "best" height. - /// - /// The caller should only submit an `import_header` transaction that makes - /// (or leads to making) other header the best one. - fn best_blocks() -> Vec<(BlockNumber, Hash)>; - /// Returns number and hash of the best finalized block known to the bridge module. - fn finalized_block() -> (BlockNumber, Hash); - /// Returns numbers and hashes of headers that require finality proofs. - /// - /// An empty response means that there are no headers which currently require a - /// finality proof. - fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; - /// Returns true if the header is known to the runtime. - fn is_known_block(hash: Hash) -> bool; - /// Returns true if the header is considered finalized by the runtime. - fn is_finalized_block(hash: Hash) -> bool; - } - - /// Outbound message lane API for messages that are sent to Kusama chain. - /// - /// This API is implemented by runtimes that are sending messages to Kusama chain, not the - /// Kusama runtime itself. - pub trait ToKusamaOutboundLaneApi { - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API for messages sent by Kusama chain. - /// - /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the - /// Kusama runtime itself. - pub trait FromKusamaInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - } -} diff --git a/primitives/kusama/Cargo.toml b/primitives/polkadot-core/Cargo.toml similarity index 93% rename from primitives/kusama/Cargo.toml rename to primitives/polkadot-core/Cargo.toml index 784f0b013289a..0a19bad97aaec 100644 --- a/primitives/kusama/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "bp-kusama" -description = "Primitives of Kusama runtime." +name = "bp-polkadot-core" +description = "Primitives of Polkadot-like runtime." version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs new file mode 100644 index 0000000000000..78a9fe8480c4d --- /dev/null +++ b/primitives/polkadot-core/src/lib.rs @@ -0,0 +1,96 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_message_lane::MessageNonce; +use bp_runtime::Chain; +use frame_support::RuntimeDebug; +use sp_core::Hasher as HasherT; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, +}; + +// Re-export's to avoid extra substrate dependencies in chain-specific crates. +pub use frame_support::Parameter; +pub use sp_runtime::traits::Convert; + +// TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 +/// Maximal number of messages in single delivery transaction. +pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; + +/// Maximal number of unrewarded relayer entries at inbound lane. +pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; + +// TODO [#438] should be selected keeping in mind: +// finality delay on both chains + reward payout cost + messages throughput. +/// Maximal number of unconfirmed messages at inbound lane. +pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; + +/// Block number type used in Polkadot-like chains. +pub type BlockNumber = u32; + +/// Hash type used in Polkadot-like chains. +pub type Hash = ::Out; + +/// The type of an object that can produce hashes on Polkadot-like chains. +pub type Hasher = BlakeTwo256; + +/// The header type used by Polkadot-like chains. +pub type Header = generic::Header; + +/// Signature type used by Polkadot-like chains. +pub type Signature = MultiSignature; + +/// Public key of account on Polkadot-like chains. +pub type AccountPublic = ::Signer; + +/// Id of account on Polkadot-like chains. +pub type AccountId = ::AccountId; + +/// Index of a transaction on the Polkadot-like chains. +pub type Nonce = u32; + +/// Block type of Polkadot-like chains. +pub type Block = generic::Block; + +/// Polkadot-like block signed with a Justification. +pub type SignedBlock = generic::SignedBlock; + +/// The balance of an account on Polkadot-like chain. +pub type Balance = u128; + +/// Polkadot-like chain. +#[derive(RuntimeDebug)] +pub struct PolkadotLike; + +impl Chain for PolkadotLike { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; +} + +/// Convert a 256-bit hash into an AccountId. +pub struct AccountIdConverter; + +impl Convert for AccountIdConverter { + fn convert(hash: sp_core::H256) -> AccountId { + hash.to_fixed_bytes().into() + } +} diff --git a/primitives/polkadot/Cargo.toml b/primitives/polkadot/Cargo.toml deleted file mode 100644 index f7c9b9717d1cd..0000000000000 --- a/primitives/polkadot/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "bp-polkadot" -description = "Primitives of Polkadot runtime." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# Bridge Dependencies - -bp-message-lane = { path = "../message-lane", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } - -# Substrate Based Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[features] -default = ["std"] -std = [ - "bp-message-lane/std", - "bp-runtime/std", - "frame-support/std", - "frame-system/std", - "sp-api/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/primitives/polkadot/src/lib.rs b/primitives/polkadot/src/lib.rs deleted file mode 100644 index a82dd5075bb67..0000000000000 --- a/primitives/polkadot/src/lib.rs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2019-2020 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] - -use bp_message_lane::{LaneId, MessageNonce}; -use bp_runtime::Chain; -use frame_support::{weights::Weight, RuntimeDebug}; -use sp_core::Hasher as HasherT; -use sp_runtime::{ - generic, - traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, -}; -use sp_std::prelude::*; - -// TODO: may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 -/// Maximal number of messages in single delivery transaction. -pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; - -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; - -// TODO: should be selected keeping in mind: -// finality delay on both chains + reward payout cost + messages throughput. -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; - -/// Block number type used in Polkadot. -pub type BlockNumber = u32; - -/// Hash type used in Polkadot. -pub type Hash = ::Out; - -/// The type of an object that can produce hashes on Polkadot. -pub type Hasher = BlakeTwo256; - -/// The header type used by Polkadot. -pub type Header = generic::Header; - -/// Signature type used by Polkadot. -pub type Signature = MultiSignature; - -/// Public key of account on Polkadot chain. -pub type AccountPublic = ::Signer; - -/// Id of account on Polkadot chain. -pub type AccountId = ::AccountId; - -/// Index of a transaction on the Polkadot chain. -pub type Nonce = u32; - -/// Block type of Polkadot. -pub type Block = generic::Block; - -/// Polkadot block signed with a Justification. -pub type SignedBlock = generic::SignedBlock; - -/// The balance of an account on Polkadot. -pub type Balance = u128; - -/// Polkadot chain. -#[derive(RuntimeDebug)] -pub struct Polkadot; - -impl Chain for Polkadot { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; -} - -/// Convert a 256-bit hash into an AccountId. -pub struct AccountIdConverter; - -impl sp_runtime::traits::Convert for AccountIdConverter { - fn convert(hash: sp_core::H256) -> AccountId { - hash.to_fixed_bytes().into() - } -} - -/// Name of the `PolkadotHeaderApi::best_blocks` runtime method. -pub const BEST_POLKADOT_BLOCKS_METHOD: &str = "PolkadotHeaderApi_best_blocks"; -/// Name of the `PolkadotHeaderApi::finalized_block` runtime method. -pub const FINALIZED_POLKADOT_BLOCK_METHOD: &str = "PolkadotHeaderApi_finalized_block"; -/// Name of the `PolkadotHeaderApi::is_known_block` runtime method. -pub const IS_KNOWN_POLKADOT_BLOCK_METHOD: &str = "PolkadotHeaderApi_is_known_block"; -/// Name of the `PolkadotHeaderApi::incomplete_headers` runtime method. -pub const INCOMPLETE_POLKADOT_HEADERS_METHOD: &str = "PolkadotHeaderApi_incomplete_headers"; - -sp_api::decl_runtime_apis! { - /// API for querying information about Polkadot headers from the Bridge Pallet instance. - /// - /// This API is implemented by runtimes that are bridging with Polkadot chain, not the - /// Polkadot runtime itself. - pub trait PolkadotHeaderApi { - /// Returns number and hash of the best blocks known to the bridge module. - /// - /// Will return multiple headers if there are many headers at the same "best" height. - /// - /// The caller should only submit an `import_header` transaction that makes - /// (or leads to making) other header the best one. - fn best_blocks() -> Vec<(BlockNumber, Hash)>; - /// Returns number and hash of the best finalized block known to the bridge module. - fn finalized_block() -> (BlockNumber, Hash); - /// Returns numbers and hashes of headers that require finality proofs. - /// - /// An empty response means that there are no headers which currently require a - /// finality proof. - fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; - /// Returns true if the header is known to the runtime. - fn is_known_block(hash: Hash) -> bool; - /// Returns true if the header is considered finalized by the runtime. - fn is_finalized_block(hash: Hash) -> bool; - } - - /// Outbound message lane API for messages that are sent to Polkadot chain. - /// - /// This API is implemented by runtimes that are sending messages to Polkadot chain, not the - /// Polkadot runtime itself. - pub trait ToPolkadotOutboundLaneApi { - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API for messages sent by Polkadot chain. - /// - /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the - /// Polkadot runtime itself. - pub trait FromPolkadotInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - } -} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 3eb2c53771786..862edf7b972d3 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -47,6 +47,12 @@ 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/call-dispatch"; diff --git a/relays/ethereum-client/Cargo.toml b/relays/ethereum-client/Cargo.toml index ac5930145888f..4c04f4889469b 100644 --- a/relays/ethereum-client/Cargo.toml +++ b/relays/ethereum-client/Cargo.toml @@ -16,4 +16,4 @@ jsonrpsee-ws-client = "0.2.0-alpha" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } -web3 = { version = "0.15", git = "https://github.com/tomusdrw/rust-web3.git", branch ="td-ethabi", default-features = false } +web3 = { version = "0.15", git = "https://github.com/tomusdrw/rust-web3", branch ="td-ethabi", default-features = false } diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index b7fe7273c155f..fbc1ef00fcaa9 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -12,9 +12,9 @@ async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "2.0.0" } env_logger = "0.8.3" -ethabi = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } -ethabi-contract = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } -ethabi-derive = { git = "https://github.com/paritytech/ethabi.git", branch = "td-eth-types-11" } +ethabi = { git = "https://github.com/paritytech/ethabi", branch = "td-eth-types-11" } +ethabi-contract = { git = "https://github.com/paritytech/ethabi", branch = "td-eth-types-11" } +ethabi-derive = { git = "https://github.com/paritytech/ethabi", branch = "td-eth-types-11" } futures = "0.3.12" hex = "0.4" hex-literal = "0.3" diff --git a/relays/kusama-client/Cargo.toml b/relays/kusama-client/Cargo.toml index 04958cf2b3618..cd311830ae615 100644 --- a/relays/kusama-client/Cargo.toml +++ b/relays/kusama-client/Cargo.toml @@ -13,7 +13,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies -bp-kusama = { path = "../../primitives/kusama" } +bp-kusama = { path = "../../primitives/chains/kusama" } # Substrate Dependencies diff --git a/relays/polkadot-client/Cargo.toml b/relays/polkadot-client/Cargo.toml index 8764b6509b242..a1d82758f8d62 100644 --- a/relays/polkadot-client/Cargo.toml +++ b/relays/polkadot-client/Cargo.toml @@ -13,7 +13,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies -bp-polkadot = { path = "../../primitives/polkadot" } +bp-polkadot = { path = "../../primitives/chains/polkadot" } # Substrate Dependencies diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index 7aeefb3cab56a..fb5d48120c46b 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -19,12 +19,12 @@ structopt = "0.3" # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } -bp-kusama = { path = "../../primitives/kusama" } +bp-kusama = { path = "../../primitives/chains/kusama" } bp-message-lane = { path = "../../primitives/message-lane" } -bp-millau = { path = "../../primitives/millau" } -bp-polkadot = { path = "../../primitives/polkadot" } +bp-millau = { path = "../../primitives/chains/millau" } +bp-polkadot = { path = "../../primitives/chains/polkadot" } bp-runtime = { path = "../../primitives/runtime" } -bp-rialto = { path = "../../primitives/rialto" } +bp-rialto = { path = "../../primitives/chains/rialto" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality-relay" } headers-relay = { path = "../headers-relay" } From 6bc21f423b4d51ee29e859686cf27b726e1f5284 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 10 Mar 2021 15:21:20 -0500 Subject: [PATCH 0376/1210] Clean Finality Verifier Pallet (#804) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove unused Config types from `pallet-finality-verifier` * Remove unused AncestryChecker trait * Remove ancestry proof parameter from relayer calls * Update docs to reflect current state of pallet * Remove mock ancestry checker * Remove unused error * Write headers outside of function used for authority set changes * Move justification verification into helper function * Add documentation suggestions Co-authored-by: Tomasz Drwięga * Clean up module level documentation a bit Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 3 - bin/rialto/runtime/src/lib.rs | 3 - modules/finality-verifier/src/lib.rs | 265 ++++++++---------- modules/finality-verifier/src/mock.rs | 17 -- primitives/header-chain/src/lib.rs | 111 -------- .../substrate/src/millau_headers_to_rialto.rs | 9 +- .../substrate/src/rialto_headers_to_millau.rs | 9 +- 7 files changed, 126 insertions(+), 291 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d1ef18eb3c175..8e0a2f3bd7d2b 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -314,9 +314,6 @@ parameter_types! { impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_rialto::Rialto; - type HeaderChain = pallet_substrate_bridge::Module; - type AncestryProof = (); - type AncestryChecker = (); type MaxRequests = MaxRequests; } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6410e824221c5..0c9a97318515d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -421,9 +421,6 @@ parameter_types! { impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_millau::Millau; - type HeaderChain = pallet_substrate_bridge::Module; - type AncestryProof = (); - type AncestryChecker = (); type MaxRequests = MaxRequests; } diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 7c331bc09e561..a072fc537b801 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -16,27 +16,30 @@ //! Substrate Finality Verifier Pallet //! -//! The goal of this pallet is to provide a safe interface for writing finalized headers to an -//! external pallet which tracks headers and finality proofs. By safe, we mean that only headers -//! whose finality has been verified will be written to the underlying pallet. +//! This pallet is an on-chain GRANDPA light client for Substrate based chains. //! -//! By verifying the finality of headers before writing them to storage we prevent DoS vectors in -//! which unfinalized headers get written to storage even if they don't have a chance of being -//! finalized in the future (such as in the case where a different fork gets finalized). +//! This pallet achieves this by trustlessly verifying GRANDPA finality proofs on-chain. Once +//! verified, finalized headers are stored in the pallet, thereby creating a sparse header chain. +//! This sparse header chain can be used as a source of truth for other higher-level applications. //! -//! The underlying pallet used for storage is assumed to be a pallet which tracks headers and -//! GRANDPA authority set changes. This information is used during the verification of GRANDPA -//! finality proofs. +//! The pallet is responsible for tracking GRANDPA validator set hand-offs. We only import headers +//! with justifications signed by the current validator set we know of. The header is inspected for +//! a `ScheduledChanges` digest item, which is then used to update to next validator set. +//! +//! Since this pallet only tracks finalized headers it does not deal with forks. Forks can only +//! occur if the GRANDPA validator set on the bridged chain is either colluding or there is a severe +//! bug causing resulting in an equivocation. Such events are outside of the scope of this pallet. +//! Shall the fork occur on the bridged chain governance intervention will be required to +//! re-initialize the bridge and track the right fork. #![cfg_attr(not(feature = "std"), no_std)] // Runtime-generated enums #![allow(clippy::large_enum_variant)] -use bp_header_chain::{justification::verify_justification, AncestryChecker, HeaderChain}; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{dispatch::DispatchError, ensure}; +use frame_support::ensure; use frame_system::{ensure_signed, RawOrigin}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -71,19 +74,6 @@ pub mod pallet { /// The chain we are bridging to here. type BridgedChain: Chain; - /// The pallet which we will use as our underlying storage mechanism. - type HeaderChain: HeaderChain<::Header, DispatchError>; - - /// The type of ancestry proof used by the pallet. - /// - /// Will be used by the ancestry checker to verify that the header being finalized is - /// related to the best finalized header in storage. - type AncestryProof: Parameter; - - /// The type through which we will verify that a given header is related to the last - /// finalized header in our storage pallet. - type AncestryChecker: AncestryChecker<::Header, Self::AncestryProof>; - /// The upper bound on the number of requests allowed by the pallet. /// /// A request refers to an action which writes a header to storage. @@ -122,7 +112,6 @@ pub mod pallet { origin: OriginFor, finality_target: BridgedHeader, justification: Vec, - ancestry_proof: T::AncestryProof, ) -> DispatchResultWithPostInfo { ensure_operational::()?; let _ = ensure_signed(origin)?; @@ -145,28 +134,11 @@ pub mod pallet { // "travelling back in time" (which could be indicative of something bad, e.g a hard-fork). ensure!(best_finalized.number() < number, >::OldHeader); - let authority_set = >::get(); - let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; - let set_id = authority_set.set_id; - - verify_justification::>((hash, *number), set_id, voter_set, &justification).map_err( - |e| { - log::error!("Received invalid justification for {:?}: {:?}", finality_target, e); - >::InvalidJustification - }, - )?; - - let best_finalized = T::HeaderChain::best_finalized(); - log::trace!("Checking ancestry against best finalized header: {:?}", &best_finalized); - - ensure!( - T::AncestryChecker::are_ancestors(&best_finalized, &finality_target, &ancestry_proof), - >::InvalidAncestryProof - ); - - let _ = T::HeaderChain::append_header(finality_target.clone())?; + verify_justification::(&justification, hash, *number)?; - import_header::(hash, finality_target)?; + try_enact_authority_change::(&finality_target)?; + >::put(hash); + >::insert(hash, finality_target); >::mutate(|count| *count += 1); log::info!("Succesfully imported finalized header with hash {:?}!", hash); @@ -317,13 +289,8 @@ pub mod pallet { pub enum Error { /// The given justification is invalid for the given header. InvalidJustification, - /// The given ancestry proof is unable to verify that the child and ancestor headers are - /// related. - InvalidAncestryProof, /// The authority set from the underlying header chain is invalid. InvalidAuthoritySet, - /// Failed to write a header to the underlying header chain. - FailedToWriteHeader, /// There are too many requests for the current window to handle. TooManyRequests, /// The header being imported is older than the best finalized header known to the pallet. @@ -342,46 +309,70 @@ pub mod pallet { StorageRootMismatch, } - /// Import the given header to the pallet's storage. + /// Check the given header for a GRANDPA scheduled authority set change. If a change + /// is found it will be enacted immediately. /// - /// This function will also check if the header schedules and enacts authority set changes, - /// updating the current authority set accordingly. - /// - /// Note: This function assumes that the given header has already been proven to be valid and - /// finalized. Using this assumption it will write them to storage with minimal checks. That - /// means it's of great importance that this function *not* called with any headers whose - /// finality has not been checked, otherwise you risk bricking your bridge. - pub(crate) fn import_header( - hash: BridgedBlockHash, - header: BridgedHeader, + /// This function does not support forced changes, or scheduled changes with delays + /// since these types of changes are indicitive of abnormal behaviour from GRANDPA. + pub(crate) fn try_enact_authority_change( + header: &BridgedHeader, ) -> Result<(), sp_runtime::DispatchError> { // We don't support forced changes - at that point governance intervention is required. ensure!( - super::find_forced_change(&header).is_none(), + super::find_forced_change(header).is_none(), >::UnsupportedScheduledChange ); - if let Some(change) = super::find_scheduled_change(&header) { + if let Some(change) = super::find_scheduled_change(header) { // GRANDPA only includes a `delay` for forced changes, so this isn't valid. ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); + let current_set_id = >::get().set_id; // TODO [#788]: Stop manually increasing the `set_id` here. let next_authorities = bp_header_chain::AuthoritySet { authorities: change.next_authorities, - set_id: >::get().set_id + 1, + set_id: current_set_id + 1, }; // Since our header schedules a change and we know the delay is 0, it must also enact // the change. - >::put(next_authorities); - }; + >::put(&next_authorities); - >::put(hash); - >::insert(hash, header); + log::info!( + "Transitioned from authority set {} to {}! New authorities are: {:?}", + current_set_id, + current_set_id + 1, + next_authorities, + ); + }; Ok(()) } + /// Verify a GRANDPA justification (finality proof) for a given header. + /// + /// Will use the GRANDPA current authorities known to the pallet. + pub(crate) fn verify_justification( + justification: &[u8], + hash: BridgedBlockHash, + number: BridgedBlockNumber, + ) -> Result<(), sp_runtime::DispatchError> { + use bp_header_chain::justification::verify_justification; + + let authority_set = >::get(); + let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; + let set_id = authority_set.set_id; + + Ok( + verify_justification::>((hash, number), set_id, voter_set, &justification).map_err( + |e| { + log::error!("Received invalid justification for {:?}: {:?}", hash, e); + >::InvalidJustification + }, + )?, + ) + } + /// Since this writes to storage with no real checks this should only be used in functions that /// were called by a trusted origin. pub(crate) fn initialize_bridge(init_params: super::InitializationData>) { @@ -551,16 +542,14 @@ mod tests { Module::::initialize(origin, init_data.clone()).map(|_| init_data) } - fn submit_finality_proof(child: u8, header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { - let child = test_header(child.into()); + fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { let header = test_header(header.into()); let set_id = 1; let grandpa_round = 1; let justification = make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); - let ancestry_proof = vec![child, header.clone()]; - Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof) + Module::::submit_finality_proof(Origin::signed(1), header, justification) } fn next_block() { @@ -705,20 +694,19 @@ mod tests { >::put(true); assert_noop!( - Module::::submit_finality_proof(Origin::signed(1), test_header(1), vec![], vec![]), + Module::::submit_finality_proof(Origin::signed(1), test_header(1), vec![]), Error::::Halted, ); }) } #[test] - fn succesfully_imports_header_with_valid_finality_and_ancestry_proofs() { + fn succesfully_imports_header_with_valid_finality() { run_test(|| { initialize_substrate_bridge(); + assert_ok!(submit_finality_proof(1)); - assert_ok!(submit_finality_proof(1, 2)); - - let header = test_header(2); + let header = test_header(1); assert_eq!(>::get(), header.hash()); assert!(>::contains_key(header.hash())); }) @@ -729,17 +717,15 @@ mod tests { run_test(|| { initialize_substrate_bridge(); - let child = test_header(1); - let header = test_header(2); + let header = test_header(1); let set_id = 2; let grandpa_round = 1; let justification = make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); - let ancestry_proof = vec![child, header.clone()]; assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + Module::::submit_finality_proof(Origin::signed(1), header, justification,), >::InvalidJustification ); }) @@ -750,41 +736,16 @@ mod tests { run_test(|| { initialize_substrate_bridge(); - let child = test_header(1); - let header = test_header(2); - + let header = test_header(1); let justification = [1u8; 32].encode(); - let ancestry_proof = vec![child, header.clone()]; assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + Module::::submit_finality_proof(Origin::signed(1), header, justification,), >::InvalidJustification ); }) } - #[test] - fn does_not_import_header_with_invalid_ancestry_proof() { - run_test(|| { - initialize_substrate_bridge(); - - let header = test_header(2); - - let set_id = 1; - let grandpa_round = 1; - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); - - // For testing, we've made it so that an empty ancestry proof is invalid - let ancestry_proof = vec![]; - - assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), - >::InvalidAncestryProof - ); - }) - } - #[test] fn disallows_invalid_authority_set() { run_test(|| { @@ -804,10 +765,9 @@ mod tests { let header = test_header(1); let justification = [1u8; 32].encode(); - let ancestry_proof = vec![]; assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification, ancestry_proof,), + Module::::submit_finality_proof(Origin::signed(1), header, justification,), >::InvalidAuthoritySet ); }) @@ -818,9 +778,9 @@ mod tests { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(5, 6)); - assert_err!(submit_finality_proof(3, 4), Error::::OldHeader); - assert_ok!(submit_finality_proof(7, 8)); + assert_ok!(submit_finality_proof(4)); + assert_err!(submit_finality_proof(3), Error::::OldHeader); + assert_ok!(submit_finality_proof(5)); }) } @@ -837,8 +797,18 @@ mod tests { let mut header = test_header(2); header.digest = change_log(0); + // Create a valid justification for the header + let set_id = 1; + let grandpa_round = 1; + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + // Let's import our test header - assert_ok!(pallet::import_header::(header.hash(), header.clone())); + assert_ok!(Module::::submit_finality_proof( + Origin::signed(1), + header.clone(), + justification + )); // Make sure that our header is the best finalized assert_eq!(>::get(), header.hash()); @@ -862,9 +832,15 @@ mod tests { let mut header = test_header(2); header.digest = change_log(1); + // Create a valid justification for the header + let set_id = 1; + let grandpa_round = 1; + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + // Should not be allowed to import this header assert_err!( - pallet::import_header::(header.hash(), header), + Module::::submit_finality_proof(Origin::signed(1), header, justification), >::UnsupportedScheduledChange ); }) @@ -880,9 +856,15 @@ mod tests { let mut header = test_header(2); header.digest = forced_change_log(0); + // Create a valid justification for the header + let set_id = 1; + let grandpa_round = 1; + let justification = + make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + // Should not be allowed to import this header assert_err!( - pallet::import_header::(header.hash(), header), + Module::::submit_finality_proof(Origin::signed(1), header, justification), >::UnsupportedScheduledChange ); }) @@ -925,9 +907,10 @@ mod tests { fn rate_limiter_disallows_imports_once_limit_is_hit_in_single_block() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1, 2)); - assert_ok!(submit_finality_proof(3, 4)); - assert_err!(submit_finality_proof(5, 6), >::TooManyRequests); + + assert_ok!(submit_finality_proof(1)); + assert_ok!(submit_finality_proof(2)); + assert_err!(submit_finality_proof(3), >::TooManyRequests); }) } @@ -935,18 +918,10 @@ mod tests { fn rate_limiter_invalid_requests_do_not_count_towards_request_count() { run_test(|| { let submit_invalid_request = || { - let child = test_header(1); - let header = test_header(2); - + let header = test_header(1); let invalid_justification = vec![4, 2, 4, 2].encode(); - let ancestry_proof = vec![child, header.clone()]; - - Module::::submit_finality_proof( - Origin::signed(1), - header, - invalid_justification, - ancestry_proof, - ) + + Module::::submit_finality_proof(Origin::signed(1), header, invalid_justification) }; initialize_substrate_bridge(); @@ -957,9 +932,9 @@ mod tests { } // Can still submit `MaxRequests` requests afterwards - assert_ok!(submit_finality_proof(1, 2)); - assert_ok!(submit_finality_proof(3, 4)); - assert_err!(submit_finality_proof(5, 6), >::TooManyRequests); + assert_ok!(submit_finality_proof(1)); + assert_ok!(submit_finality_proof(2)); + assert_err!(submit_finality_proof(3), >::TooManyRequests); }) } @@ -967,11 +942,11 @@ mod tests { fn rate_limiter_allows_request_after_new_block_has_started() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1, 2)); - assert_ok!(submit_finality_proof(3, 4)); + assert_ok!(submit_finality_proof(1)); + assert_ok!(submit_finality_proof(2)); next_block(); - assert_ok!(submit_finality_proof(5, 6)); + assert_ok!(submit_finality_proof(3)); }) } @@ -979,12 +954,12 @@ mod tests { fn rate_limiter_disallows_imports_once_limit_is_hit_across_different_blocks() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1, 2)); - assert_ok!(submit_finality_proof(3, 4)); + assert_ok!(submit_finality_proof(1)); + assert_ok!(submit_finality_proof(2)); next_block(); - assert_ok!(submit_finality_proof(5, 6)); - assert_err!(submit_finality_proof(7, 8), >::TooManyRequests); + assert_ok!(submit_finality_proof(3)); + assert_err!(submit_finality_proof(4), >::TooManyRequests); }) } @@ -992,15 +967,15 @@ mod tests { fn rate_limiter_allows_max_requests_after_long_time_with_no_activity() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1, 2)); - assert_ok!(submit_finality_proof(3, 4)); + assert_ok!(submit_finality_proof(1)); + assert_ok!(submit_finality_proof(2)); next_block(); next_block(); next_block(); - assert_ok!(submit_finality_proof(5, 6)); - assert_ok!(submit_finality_proof(7, 8)); + assert_ok!(submit_finality_proof(5)); + assert_ok!(submit_finality_proof(7)); }) } } diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index dc2fc27394f85..f80a374f3710f 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -42,7 +42,6 @@ construct_runtime! { UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Module, Call, Config, Storage, Event}, - Bridge: pallet_substrate_bridge::{Module}, FinalityVerifier: finality_verifier::{Module}, } } @@ -79,19 +78,12 @@ impl frame_system::Config for TestRuntime { type SS58Prefix = (); } -impl pallet_substrate_bridge::Config for TestRuntime { - type BridgedChain = TestBridgedChain; -} - parameter_types! { pub const MaxRequests: u32 = 2; } impl finality_verifier::Config for TestRuntime { type BridgedChain = TestBridgedChain; - type HeaderChain = pallet_substrate_bridge::Module; - type AncestryProof = Vec<::Header>; - type AncestryChecker = Checker<::Header, Self::AncestryProof>; type MaxRequests = MaxRequests; } @@ -105,15 +97,6 @@ impl Chain for TestBridgedChain { type Header = ::Header; } -#[derive(Debug)] -pub struct Checker(std::marker::PhantomData<(H, P)>); - -impl bp_header_chain::AncestryChecker> for Checker> { - fn are_ancestors(_ancestor: &H, _child: &H, proof: &Vec) -> bool { - !proof.is_empty() - } -} - pub fn run_test(test: impl FnOnce() -> T) -> T { sp_io::TestExternalities::new(Default::default()).execute_with(test) } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 65181df316859..e9f6cee9c9ab8 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -29,7 +29,6 @@ use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::RuntimeDebug; use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT}; -use sp_std::vec::Vec; pub mod justification; @@ -95,51 +94,6 @@ impl HeaderChain for () { } } -/// A trait for checking if a given child header is a direct descendant of an ancestor. -pub trait AncestryChecker { - /// Is the child header a descendant of the ancestor header? - fn are_ancestors(ancestor: &H, child: &H, proof: &P) -> bool; -} - -impl AncestryChecker for () { - fn are_ancestors(_ancestor: &H, _child: &H, _proof: &P) -> bool { - true - } -} - -/// A simple ancestry checker which verifies ancestry by walking every header between `child` and -/// `ancestor`. -pub struct LinearAncestryChecker; - -impl AncestryChecker> for LinearAncestryChecker { - fn are_ancestors(ancestor: &H, child: &H, proof: &Vec) -> bool { - // You can't be your own parent - if proof.len() < 2 { - return false; - } - - // Let's make sure that the given headers are actually in the proof - match proof.first() { - Some(first) if first == ancestor => {} - _ => return false, - } - - match proof.last() { - Some(last) if last == child => {} - _ => return false, - } - - // Now we actually check the proof - for i in 1..proof.len() { - if &proof[i - 1].hash() != proof[i].parent_hash() { - return false; - } - } - - true - } -} - /// Find header digest that schedules next GRANDPA authorities set. pub fn find_grandpa_authorities_scheduled_change( header: &H, @@ -155,68 +109,3 @@ pub fn find_grandpa_authorities_scheduled_change( // the right kind of consensus log. header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) } - -#[cfg(test)] -mod tests { - use super::*; - use bp_test_utils::test_header; - use sp_runtime::testing::Header; - - #[test] - fn can_verify_ancestry_correctly() { - let ancestor: Header = test_header(1); - let header2: Header = test_header(2); - let header3: Header = test_header(3); - let child: Header = test_header(4); - - let ancestry_proof = vec![ancestor.clone(), header2, header3, child.clone()]; - - assert!(LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof)); - } - - #[test] - fn does_not_verify_invalid_proof() { - let ancestor: Header = test_header(1); - let header2: Header = test_header(2); - let header3: Header = test_header(3); - let child: Header = test_header(4); - - let ancestry_proof = vec![ancestor.clone(), header3, header2, child.clone()]; - - let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof); - assert!(invalid); - } - - #[test] - fn header_is_not_allowed_to_be_its_own_ancestor() { - let ancestor: Header = test_header(1); - let child: Header = ancestor.clone(); - let ancestry_proof = vec![ancestor.clone()]; - - let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof); - assert!(invalid); - } - - #[test] - fn proof_is_considered_invalid_if_child_and_ancestor_do_not_match() { - let ancestor: Header = test_header(1); - let header2: Header = test_header(2); - let header3: Header = test_header(3); - let child: Header = test_header(4); - - let ancestry_proof = vec![ancestor, header3.clone(), header2.clone(), child]; - - let invalid = !LinearAncestryChecker::are_ancestors(&header2, &header3, &ancestry_proof); - assert!(invalid); - } - - #[test] - fn empty_proof_is_invalid() { - let ancestor: Header = test_header(1); - let child: Header = ancestor.clone(); - let ancestry_proof = vec![]; - - let invalid = !LinearAncestryChecker::are_ancestors(&ancestor, &child, &ancestry_proof); - assert!(invalid); - } -} diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 1ac12d2eebede..889676d673bfc 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -43,12 +43,9 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = rialto_runtime::FinalityBridgeMillauCall::submit_finality_proof( - header.into_inner(), - proof.into_inner(), - (), - ) - .into(); + let call = + rialto_runtime::FinalityBridgeMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner()) + .into(); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index 27fe697aadf76..12b2086728a76 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -43,12 +43,9 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = millau_runtime::FinalityBridgeRialtoCall::submit_finality_proof( - header.into_inner(), - proof.into_inner(), - (), - ) - .into(); + let call = + millau_runtime::FinalityBridgeRialtoCall::submit_finality_proof(header.into_inner(), proof.into_inner()) + .into(); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); From 78b3497e7d438c8c88cccfaa0681ea6f5d894b3b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 11 Mar 2021 16:33:01 +0300 Subject: [PATCH 0377/1210] More tests for finality relay (#816) * more tests for finality relay * clippy * remove env_logger dep * fmt * more clippy * removed prune_unjustified_headers * review --- relays/finality-relay/src/finality_loop.rs | 265 ++++++++++-------- .../finality-relay/src/finality_loop_tests.rs | 177 ++++++++---- relays/finality-relay/src/lib.rs | 6 +- .../substrate-client/src/finality_source.rs | 59 ++-- relays/substrate/src/finality_pipeline.rs | 4 +- .../substrate/src/millau_headers_to_rialto.rs | 2 +- .../substrate/src/rialto_headers_to_millau.rs | 2 +- 7 files changed, 315 insertions(+), 200 deletions(-) diff --git a/relays/finality-relay/src/finality_loop.rs b/relays/finality-relay/src/finality_loop.rs index 50c23b3757233..af5da42cee70c 100644 --- a/relays/finality-relay/src/finality_loop.rs +++ b/relays/finality-relay/src/finality_loop.rs @@ -136,16 +136,21 @@ pub fn run( } /// Unjustified headers container. Ordered by header number. -pub(crate) type UnjustifiedHeaders

= Vec<

::Header>; +pub(crate) type UnjustifiedHeaders = Vec; /// Finality proofs container. Ordered by target header number. pub(crate) type FinalityProofs

= Vec<(

::Number,

::FinalityProof, )>; +/// Reference to finality proofs container. +pub(crate) type FinalityProofsRef<'a, P> = &'a [( +

::Number, +

::FinalityProof, +)]; /// Error that may happen inside finality synchronization loop. #[derive(Debug)] -enum Error { +pub(crate) enum Error { /// Source client request has failed with given error. Source(SourceError), /// Target client request has failed with given error. @@ -182,13 +187,23 @@ struct Transaction { } /// Finality proofs stream that may be restarted. -struct RestartableFinalityProofsStream { +pub(crate) struct RestartableFinalityProofsStream { /// Flag that the stream needs to be restarted. - needs_restart: bool, + pub(crate) needs_restart: bool, /// The stream itself. stream: Pin>, } +#[cfg(test)] +impl From for RestartableFinalityProofsStream { + fn from(stream: S) -> Self { + RestartableFinalityProofsStream { + needs_restart: false, + stream: Box::pin(stream), + } + } +} + /// Finality synchronization loop state. struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { /// Synchronization loop progress. @@ -272,6 +287,8 @@ async fn run_until_connection_lost( } }; if finality_proofs_stream.needs_restart { + log::warn!(target: "bridge", "{} finality proofs stream is being restarted", P::SOURCE_NAME); + finality_proofs_stream.needs_restart = false; finality_proofs_stream.stream = Box::pin(restart_finality_proofs_stream().await?); } @@ -368,7 +385,7 @@ where async fn select_header_to_submit( source_client: &SC, - _target_client: &TC, + target_client: &TC, finality_proofs_stream: &mut RestartableFinalityProofsStream, recent_finality_proofs: &mut FinalityProofs

, best_number_at_source: P::Number, @@ -380,9 +397,6 @@ where SC: SourceClient

, TC: TargetClient

, { - let mut selected_finality_proof = None; - let mut unjustified_headers = Vec::new(); - // to see that the loop is progressing log::trace!( target: "bridge", @@ -393,6 +407,70 @@ where // read missing headers. if we see that the header schedules GRANDPA change, we need to // submit this header + let selected_finality_proof = read_missing_headers::( + source_client, + target_client, + best_number_at_source, + best_number_at_target, + ) + .await?; + let (mut unjustified_headers, mut selected_finality_proof) = match selected_finality_proof { + SelectedFinalityProof::Mandatory(header, finality_proof) => return Ok(Some((header, finality_proof))), + SelectedFinalityProof::Regular(unjustified_headers, header, finality_proof) => { + (unjustified_headers, Some((header, finality_proof))) + } + SelectedFinalityProof::None(unjustified_headers) => (unjustified_headers, None), + }; + + // all headers that are missing from the target client are non-mandatory + // => even if we have already selected some header and its persistent finality proof, + // we may try to select better header by reading non-persistent proofs from the stream + read_finality_proofs_from_stream::(finality_proofs_stream, recent_finality_proofs); + selected_finality_proof = select_better_recent_finality_proof::

( + recent_finality_proofs, + &mut unjustified_headers, + selected_finality_proof, + ); + + // remove obsolete 'recent' finality proofs + keep its size under certain limit + let oldest_finality_proof_to_keep = selected_finality_proof + .as_ref() + .map(|(header, _)| header.number()) + .unwrap_or(best_number_at_target); + prune_recent_finality_proofs::

( + oldest_finality_proof_to_keep, + recent_finality_proofs, + sync_params.recent_finality_proofs_limit, + ); + + Ok(selected_finality_proof) +} + +/// Finality proof that has been selected by the `read_missing_headers` function. +pub(crate) enum SelectedFinalityProof { + /// Mandatory header and its proof has been selected. We shall submit proof for this header. + Mandatory(Header, FinalityProof), + /// Regular header and its proof has been selected. We may submit this proof, or proof for + /// some better header. + Regular(UnjustifiedHeaders

, Header, FinalityProof), + /// We haven't found any missing header with persistent proof at the target client. + None(UnjustifiedHeaders
), +} + +/// Read missing headers and their persistent finality proofs from the target client. +/// +/// If we have found some header with known proof, it is returned. +/// Otherwise, `SelectedFinalityProof::None` is returned. +/// +/// Unless we have found mandatory header, all missing headers are collected and returned. +pub(crate) async fn read_missing_headers, TC: TargetClient

>( + source_client: &SC, + _target_client: &TC, + best_number_at_source: P::Number, + best_number_at_target: P::Number, +) -> Result, Error> { + let mut unjustified_headers = Vec::new(); + let mut selected_finality_proof = None; let mut header_number = best_number_at_target + One::one(); while header_number <= best_number_at_source { let (header, finality_proof) = source_client @@ -404,13 +482,13 @@ where match (is_mandatory, finality_proof) { (true, Some(finality_proof)) => { log::trace!(target: "bridge", "Header {:?} is mandatory", header_number); - return Ok(Some((header, finality_proof))); + return Ok(SelectedFinalityProof::Mandatory(header, finality_proof)); } (true, None) => return Err(Error::MissingMandatoryFinalityProof(header.number())), (false, Some(finality_proof)) => { log::trace!(target: "bridge", "Header {:?} has persistent finality proof", header_number); + unjustified_headers.clear(); selected_finality_proof = Some((header, finality_proof)); - prune_unjustified_headers::

(header_number, &mut unjustified_headers); } (false, None) => { unjustified_headers.push(header); @@ -420,37 +498,17 @@ where header_number = header_number + One::one(); } - // see if we can improve finality by using recent finality proofs - if !unjustified_headers.is_empty() && !recent_finality_proofs.is_empty() { - const NOT_EMPTY_PROOF: &str = "we have checked that the vec is not empty; qed"; - - // we need proofs for headers in range unjustified_range_begin..=unjustified_range_end - let unjustified_range_begin = unjustified_headers.first().expect(NOT_EMPTY_PROOF).number(); - let unjustified_range_end = unjustified_headers.last().expect(NOT_EMPTY_PROOF).number(); - - // we have proofs for headers in range buffered_range_begin..=buffered_range_end - let buffered_range_begin = recent_finality_proofs.first().expect(NOT_EMPTY_PROOF).0; - let buffered_range_end = recent_finality_proofs.last().expect(NOT_EMPTY_PROOF).0; - - // we have two ranges => find intersection - let intersection_begin = std::cmp::max(unjustified_range_begin, buffered_range_begin); - let intersection_end = std::cmp::min(unjustified_range_end, buffered_range_end); - let intersection = intersection_begin..=intersection_end; - - // find last proof from intersection - let selected_finality_proof_index = recent_finality_proofs - .binary_search_by_key(intersection.end(), |(number, _)| *number) - .unwrap_or_else(|index| index.saturating_sub(1)); - let (selected_header_number, finality_proof) = &recent_finality_proofs[selected_finality_proof_index]; - if intersection.contains(selected_header_number) { - // now remove all obsolete headers and extract selected header - let selected_header = prune_unjustified_headers::

(*selected_header_number, &mut unjustified_headers) - .expect("unjustified_headers contain all headers from intersection; qed"); - selected_finality_proof = Some((selected_header, finality_proof.clone())); - } - } + Ok(match selected_finality_proof { + Some((header, proof)) => SelectedFinalityProof::Regular(unjustified_headers, header, proof), + None => SelectedFinalityProof::None(unjustified_headers), + }) +} - // read all proofs from the stream, probably selecting updated proof that we're going to submit +/// Read finality proofs from the stream. +pub(crate) fn read_finality_proofs_from_stream>( + finality_proofs_stream: &mut RestartableFinalityProofsStream, + recent_finality_proofs: &mut FinalityProofs

, +) { loop { let next_proof = finality_proofs_stream.stream.next(); let finality_proof = match next_proof.now_or_never() { @@ -461,49 +519,52 @@ where } None => break, }; - let finality_proof_target_header_number = match finality_proof.target_header_number() { - Some(target_header_number) => target_header_number, - None => { - continue; - } - }; - let justified_header = - prune_unjustified_headers::

(finality_proof_target_header_number, &mut unjustified_headers); - if let Some(justified_header) = justified_header { - recent_finality_proofs.clear(); - selected_finality_proof = Some((justified_header, finality_proof)); - } else { - // the number of proofs read during single wakeup is expected to be low, so we aren't pruning - // `recent_finality_proofs` collection too often - recent_finality_proofs.push((finality_proof_target_header_number, finality_proof)); - } + recent_finality_proofs.push((finality_proof.target_header_number(), finality_proof)); } +} - // remove obsolete 'recent' finality proofs + keep its size under certain limit - let oldest_finality_proof_to_keep = selected_finality_proof - .as_ref() - .map(|(header, _)| header.number()) - .unwrap_or(best_number_at_target); - prune_recent_finality_proofs::

( - oldest_finality_proof_to_keep, - recent_finality_proofs, - sync_params.recent_finality_proofs_limit, - ); +/// Try to select better header and its proof, given finality proofs that we +/// have recently read from the stream. +pub(crate) fn select_better_recent_finality_proof( + recent_finality_proofs: FinalityProofsRef

, + unjustified_headers: &mut UnjustifiedHeaders, + selected_finality_proof: Option<(P::Header, P::FinalityProof)>, +) -> Option<(P::Header, P::FinalityProof)> { + if unjustified_headers.is_empty() || recent_finality_proofs.is_empty() { + return selected_finality_proof; + } - Ok(selected_finality_proof) -} + const NOT_EMPTY_PROOF: &str = "we have checked that the vec is not empty; qed"; -/// Remove headers from `unjustified_headers` collection with number lower or equal than `justified_header_number`. -/// -/// Returns the header that matches `justified_header_number` (if any). -pub(crate) fn prune_unjustified_headers( - justified_header_number: P::Number, - unjustified_headers: &mut UnjustifiedHeaders

, -) -> Option { - prune_ordered_vec(justified_header_number, unjustified_headers, usize::MAX, |header| { - header.number() - }) + // we need proofs for headers in range unjustified_range_begin..=unjustified_range_end + let unjustified_range_begin = unjustified_headers.first().expect(NOT_EMPTY_PROOF).number(); + let unjustified_range_end = unjustified_headers.last().expect(NOT_EMPTY_PROOF).number(); + + // we have proofs for headers in range buffered_range_begin..=buffered_range_end + let buffered_range_begin = recent_finality_proofs.first().expect(NOT_EMPTY_PROOF).0; + let buffered_range_end = recent_finality_proofs.last().expect(NOT_EMPTY_PROOF).0; + + // we have two ranges => find intersection + let intersection_begin = std::cmp::max(unjustified_range_begin, buffered_range_begin); + let intersection_end = std::cmp::min(unjustified_range_end, buffered_range_end); + let intersection = intersection_begin..=intersection_end; + + // find last proof from intersection + let selected_finality_proof_index = recent_finality_proofs + .binary_search_by_key(intersection.end(), |(number, _)| *number) + .unwrap_or_else(|index| index.saturating_sub(1)); + let (selected_header_number, finality_proof) = &recent_finality_proofs[selected_finality_proof_index]; + if !intersection.contains(selected_header_number) { + return selected_finality_proof; + } + + // now remove all obsolete headers and extract selected header + let selected_header_position = unjustified_headers + .binary_search_by_key(selected_header_number, |header| header.number()) + .expect("unjustified_headers contain all headers from intersection; qed"); + let selected_header = unjustified_headers.swap_remove(selected_header_position); + Some((selected_header, finality_proof.clone())) } pub(crate) fn prune_recent_finality_proofs( @@ -511,45 +572,21 @@ pub(crate) fn prune_recent_finality_proofs( recent_finality_proofs: &mut FinalityProofs

, recent_finality_proofs_limit: usize, ) { - prune_ordered_vec( - justified_header_number, - recent_finality_proofs, - recent_finality_proofs_limit, - |(header_number, _)| *header_number, + let position = + recent_finality_proofs.binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number); + + // remove all obsolete elements + *recent_finality_proofs = recent_finality_proofs.split_off( + position + .map(|position| position + 1) + .unwrap_or_else(|position| position), ); -} - -fn prune_ordered_vec( - header_number: Number, - ordered_vec: &mut Vec, - maximal_vec_size: usize, - extract_header_number: impl Fn(&T) -> Number, -) -> Option { - let position = ordered_vec.binary_search_by_key(&header_number, extract_header_number); - - // first extract element we're interested in - let extracted_element = match position { - Ok(position) => { - let updated_vec = ordered_vec.split_off(position + 1); - let extracted_element = ordered_vec.pop().expect( - "binary_search_by_key has returned Ok(); so there's element at `position`;\ - we're splitting vec at `position+1`; so we have pruned at least 1 element;\ - qed", - ); - *ordered_vec = updated_vec; - Some(extracted_element) - } - Err(position) => { - *ordered_vec = ordered_vec.split_off(position); - None - } - }; // now - limit vec by size - let split_index = ordered_vec.len().saturating_sub(maximal_vec_size); - *ordered_vec = ordered_vec.split_off(split_index); - - extracted_element + let split_index = recent_finality_proofs + .len() + .saturating_sub(recent_finality_proofs_limit); + *recent_finality_proofs = recent_finality_proofs.split_off(split_index); } fn print_sync_progress( diff --git a/relays/finality-relay/src/finality_loop_tests.rs b/relays/finality-relay/src/finality_loop_tests.rs index 5dfe8edd2124a..53f5225ab7e33 100644 --- a/relays/finality-relay/src/finality_loop_tests.rs +++ b/relays/finality-relay/src/finality_loop_tests.rs @@ -19,8 +19,8 @@ #![cfg(test)] use crate::finality_loop::{ - prune_recent_finality_proofs, prune_unjustified_headers, run, FinalityProofs, FinalitySyncParams, SourceClient, - TargetClient, UnjustifiedHeaders, + prune_recent_finality_proofs, read_finality_proofs_from_stream, run, select_better_recent_finality_proof, + FinalityProofs, FinalitySyncParams, SourceClient, TargetClient, }; use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; @@ -71,10 +71,10 @@ impl SourceHeader for TestSourceHeader { } #[derive(Debug, Clone, PartialEq)] -struct TestFinalityProof(Option); +struct TestFinalityProof(TestNumber); impl FinalityProof for TestFinalityProof { - fn target_header_number(&self) -> Option { + fn target_header_number(&self) -> TestNumber { self.0 } } @@ -176,14 +176,14 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync source_best_block_number: 10, source_headers: vec![ (6, (TestSourceHeader(false, 6), None)), - (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(Some(7))))), - (8, (TestSourceHeader(true, 8), Some(TestFinalityProof(Some(8))))), - (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(Some(9))))), + (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), + (8, (TestSourceHeader(true, 8), Some(TestFinalityProof(8)))), + (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), (10, (TestSourceHeader(false, 10), None)), ] .into_iter() .collect(), - source_proofs: vec![TestFinalityProof(Some(12)), TestFinalityProof(Some(14))], + source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], target_best_block_number: 5, target_headers: vec![], @@ -222,22 +222,22 @@ fn finality_sync_loop_works() { // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, because // there are no more persistent finality proofs // - // once this ^^^ is done, we generate more blocks && read proof for blocks 12, 14 and 16 from the stream - // but we only submit proof for 16 - // - // proof for block 15 is ignored - we haven't managed to decode it + // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from the stream if data.target_best_block_number == 9 { - data.source_best_block_number = 17; + data.source_best_block_number = 14; data.source_headers.insert(11, (TestSourceHeader(false, 11), None)); data.source_headers - .insert(12, (TestSourceHeader(false, 12), Some(TestFinalityProof(Some(12))))); + .insert(12, (TestSourceHeader(false, 12), Some(TestFinalityProof(12)))); data.source_headers.insert(13, (TestSourceHeader(false, 13), None)); data.source_headers - .insert(14, (TestSourceHeader(false, 14), Some(TestFinalityProof(Some(14))))); - data.source_headers - .insert(15, (TestSourceHeader(false, 15), Some(TestFinalityProof(None)))); + .insert(14, (TestSourceHeader(false, 14), Some(TestFinalityProof(14)))); + } + // once this ^^^ is done, we generate more blocks && read persistent proof for block 16 + if data.target_best_block_number == 14 { + data.source_best_block_number = 17; + data.source_headers.insert(15, (TestSourceHeader(false, 15), None)); data.source_headers - .insert(16, (TestSourceHeader(false, 16), Some(TestFinalityProof(Some(16))))); + .insert(16, (TestSourceHeader(false, 16), Some(TestFinalityProof(16)))); data.source_headers.insert(17, (TestSourceHeader(false, 17), None)); } @@ -247,67 +247,132 @@ fn finality_sync_loop_works() { assert_eq!( client_data.target_headers, vec![ - (TestSourceHeader(true, 8), TestFinalityProof(Some(8))), - (TestSourceHeader(false, 9), TestFinalityProof(Some(9))), - (TestSourceHeader(false, 16), TestFinalityProof(Some(16))), + // before adding 11..14: finality proof for mandatory header#8 + (TestSourceHeader(true, 8), TestFinalityProof(8)), + // before adding 11..14: persistent finality proof for non-mandatory header#9 + (TestSourceHeader(false, 9), TestFinalityProof(9)), + // after adding 11..14: ephemeral finality proof for non-mandatory header#14 + (TestSourceHeader(false, 14), TestFinalityProof(14)), + // after adding 15..17: persistent finality proof for non-mandatory header#16 + (TestSourceHeader(false, 16), TestFinalityProof(16)), ], ); } #[test] -fn prune_unjustified_headers_works() { - let original_unjustified_headers: UnjustifiedHeaders = vec![ - TestSourceHeader(false, 10), - TestSourceHeader(false, 13), - TestSourceHeader(false, 15), - TestSourceHeader(false, 17), - TestSourceHeader(false, 19), - ] - .into_iter() - .collect(); +fn select_better_recent_finality_proof_works() { + // if there are no unjustified headers, nothing is changed + assert_eq!( + select_better_recent_finality_proof::( + &[(5, TestFinalityProof(5))], + &mut vec![], + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ), + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ); - // when header is in the collection - let mut unjustified_headers = original_unjustified_headers.clone(); + // if there are no recent finality proofs, nothing is changed assert_eq!( - prune_unjustified_headers::(10, &mut unjustified_headers), - Some(TestSourceHeader(false, 10)), + select_better_recent_finality_proof::( + &[], + &mut vec![TestSourceHeader(false, 5)], + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ), + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), ); - assert_eq!(&original_unjustified_headers[1..], unjustified_headers,); - // when the header doesn't exist in the collection - let mut unjustified_headers = original_unjustified_headers.clone(); + // if there's no intersection between recent finality proofs and unjustified headers, nothing is changed + let mut unjustified_headers = vec![TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; assert_eq!( - prune_unjustified_headers::(11, &mut unjustified_headers), - None, + select_better_recent_finality_proof::( + &[(1, TestFinalityProof(1)), (4, TestFinalityProof(4))], + &mut unjustified_headers, + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ), + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), ); - assert_eq!(&original_unjustified_headers[1..], unjustified_headers,); - // when last entry is pruned - let mut unjustified_headers = original_unjustified_headers.clone(); + // if there's intersection between recent finality proofs and unjustified headers, but there are no + // proofs in this intersection, nothing is changed + let mut unjustified_headers = vec![ + TestSourceHeader(false, 8), + TestSourceHeader(false, 9), + TestSourceHeader(false, 10), + ]; assert_eq!( - prune_unjustified_headers::(19, &mut unjustified_headers), - Some(TestSourceHeader(false, 19)), + select_better_recent_finality_proof::( + &[(7, TestFinalityProof(7)), (11, TestFinalityProof(11))], + &mut unjustified_headers, + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ), + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ); + assert_eq!( + unjustified_headers, + vec![ + TestSourceHeader(false, 8), + TestSourceHeader(false, 9), + TestSourceHeader(false, 10) + ] ); - assert_eq!(&original_unjustified_headers[5..], unjustified_headers,); + // if there's intersection between recent finality proofs and unjustified headers and there's + // a proof in this intersection: + // - this better (last from intersection) proof is selected; + // - 'obsolete' unjustified headers are pruned. + let mut unjustified_headers = vec![ + TestSourceHeader(false, 8), + TestSourceHeader(false, 9), + TestSourceHeader(false, 10), + ]; + assert_eq!( + select_better_recent_finality_proof::( + &[(7, TestFinalityProof(7)), (9, TestFinalityProof(9))], + &mut unjustified_headers, + Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + ), + Some((TestSourceHeader(false, 9), TestFinalityProof(9))), + ); +} - // when we try and prune past last entry - let mut unjustified_headers = original_unjustified_headers.clone(); +#[test] +fn read_finality_proofs_from_stream_works() { + // when stream is currently empty, nothing is changed + let mut recent_finality_proofs = vec![(1, TestFinalityProof(1))]; + let mut stream = futures::stream::pending().into(); + read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); + assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1))]); + assert_eq!(stream.needs_restart, false); + + // when stream has entry with target, it is added to the recent proofs container + let mut stream = futures::stream::iter(vec![TestFinalityProof(4)]) + .chain(futures::stream::pending()) + .into(); + read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); assert_eq!( - prune_unjustified_headers::(20, &mut unjustified_headers), - None, + recent_finality_proofs, + vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] + ); + assert_eq!(stream.needs_restart, false); + + // when stream has ended, we'll need to restart it + let mut stream = futures::stream::empty().into(); + read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); + assert_eq!( + recent_finality_proofs, + vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] ); - assert_eq!(&original_unjustified_headers[5..], unjustified_headers,); + assert_eq!(stream.needs_restart, true); } #[test] fn prune_recent_finality_proofs_works() { let original_recent_finality_proofs: FinalityProofs = vec![ - (10, TestFinalityProof(Some(10))), - (13, TestFinalityProof(Some(13))), - (15, TestFinalityProof(Some(15))), - (17, TestFinalityProof(Some(17))), - (19, TestFinalityProof(Some(19))), + (10, TestFinalityProof(10)), + (13, TestFinalityProof(13)), + (15, TestFinalityProof(15)), + (17, TestFinalityProof(17)), + (19, TestFinalityProof(19)), ] .into_iter() .collect(); diff --git a/relays/finality-relay/src/lib.rs b/relays/finality-relay/src/lib.rs index e9d946e27f189..a246e4bd954c0 100644 --- a/relays/finality-relay/src/lib.rs +++ b/relays/finality-relay/src/lib.rs @@ -53,8 +53,6 @@ pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { /// Abstract finality proof that is justifying block finality. pub trait FinalityProof: Clone + Send + Sync + Debug { - /// Return header id that this proof is generated for. - /// - /// None is returned if proof is invalid from relayer PoV. - fn target_header_number(&self) -> Option; + /// Return number of header that this proof is generated for. + fn target_header_number(&self) -> Number; } diff --git a/relays/substrate-client/src/finality_source.rs b/relays/substrate-client/src/finality_source.rs index 2c76619e867fa..18293efa128f9 100644 --- a/relays/substrate-client/src/finality_source.rs +++ b/relays/substrate-client/src/finality_source.rs @@ -22,6 +22,7 @@ use crate::error::Error; use crate::sync_header::SyncHeader; use async_trait::async_trait; +use bp_header_chain::justification::decode_justification_target; use finality_relay::{FinalityProof, FinalitySyncPipeline, SourceClient, SourceHeader}; use futures::stream::{unfold, Stream, StreamExt}; use relay_utils::relay_loop::Client as RelayClient; @@ -30,26 +31,23 @@ use std::{marker::PhantomData, pin::Pin}; /// Wrapped raw Justification. #[derive(Debug, Clone)] -pub struct Justification

{ +pub struct Justification { + /// Header number decoded from the [`raw_justification`]. + target_header_number: Number, + /// Raw, encoded justification bytes. raw_justification: sp_runtime::Justification, - _phantom: PhantomData
, } -impl
Justification
{ +impl Justification { /// Extract raw justification. pub fn into_inner(self) -> sp_runtime::Justification { self.raw_justification } } -impl
FinalityProof for Justification
-where - Header: HeaderT, -{ - fn target_header_number(&self) -> Option { - bp_header_chain::justification::decode_justification_target::
(&self.raw_justification) - .ok() - .map(|(_, number)| number) +impl FinalityProof for Justification { + fn target_header_number(&self) -> Number { + self.target_header_number } } @@ -96,11 +94,11 @@ where Hash = C::Hash, Number = C::BlockNumber, Header = SyncHeader, - FinalityProof = Justification, + FinalityProof = Justification, >, P::Header: SourceHeader, { - type FinalityProofsStream = Pin>>>; + type FinalityProofsStream = Pin>>>; async fn best_finalized_block_number(&self) -> Result { // we **CAN** continue to relay finality proofs if source node is out of sync, because @@ -122,8 +120,8 @@ where .justification() .cloned() .map(|raw_justification| Justification { + target_header_number: number, raw_justification, - _phantom: Default::default(), }), )) } @@ -132,14 +130,31 @@ where Ok(unfold( self.client.clone().subscribe_justifications().await?, move |mut subscription| async move { - let next_justification = subscription.next().await?; - Some(( - Justification { - raw_justification: next_justification.0, - _phantom: Default::default(), - }, - subscription, - )) + loop { + let next_justification = subscription.next().await?; + let decoded_target = decode_justification_target::(&next_justification.0); + let target_header_number = match decoded_target { + Ok((_, number)) => number, + Err(err) => { + log::error!( + target: "bridge", + "Failed to decode justification target from the {} justifications stream: {:?}", + P::SOURCE_NAME, + err, + ); + + continue; + } + }; + + return Some(( + Justification { + target_header_number, + raw_justification: next_justification.0, + }, + subscription, + )); + } }, ) .boxed()) diff --git a/relays/substrate/src/finality_pipeline.rs b/relays/substrate/src/finality_pipeline.rs index 7ec592d5dee1a..21865b6c4485b 100644 --- a/relays/substrate/src/finality_pipeline.rs +++ b/relays/substrate/src/finality_pipeline.rs @@ -89,7 +89,7 @@ where type Hash = HashOf; type Number = BlockNumberOf; type Header = SyncHeader; - type FinalityProof = Justification; + type FinalityProof = Justification; } /// Run Substrate-to-Substrate finality sync. @@ -103,7 +103,7 @@ pub async fn run( Hash = HashOf, Number = BlockNumberOf, Header = SyncHeader, - FinalityProof = Justification, + FinalityProof = Justification, >, SourceChain: Clone + Chain, BlockNumberOf: BlockNumberBase, diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/millau_headers_to_rialto.rs index 889676d673bfc..f84eee03a9fd0 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/millau_headers_to_rialto.rs @@ -39,7 +39,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { async fn make_submit_finality_proof_transaction( &self, header: MillauSyncHeader, - proof: Justification, + proof: Justification, ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_headers_to_millau.rs index 12b2086728a76..5a9bbb12133a2 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_headers_to_millau.rs @@ -39,7 +39,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { async fn make_submit_finality_proof_transaction( &self, header: RialtoSyncHeader, - proof: Justification, + proof: Justification, ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; From 2700c9fc33f979c24ac604e2f63f25b7691bf6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 12 Mar 2021 06:50:20 +0100 Subject: [PATCH 0378/1210] Reorganize relay code to make it easy to add new networks. (#813) * Nest some crates. * Alter command execution to make it easier to add new bridges. * Rename sub-dirs. * cargo fmt --all * Address clippy. * Update relays/substrate/src/rialto_millau/cli.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- .../ethereum}/Cargo.toml | 6 +- .../ethereum}/src/client.rs | 0 .../ethereum}/src/error.rs | 0 .../ethereum}/src/lib.rs | 0 .../ethereum}/src/rpc.rs | 0 .../ethereum}/src/sign.rs | 0 .../ethereum}/src/types.rs | 0 .../kusama}/Cargo.toml | 8 +- .../kusama}/src/lib.rs | 0 .../millau}/Cargo.toml | 8 +- .../millau}/src/lib.rs | 0 .../polkadot}/Cargo.toml | 8 +- .../polkadot}/src/lib.rs | 0 .../rialto}/Cargo.toml | 8 +- .../rialto}/src/lib.rs | 0 .../substrate}/Cargo.toml | 12 +- .../substrate}/src/chain.rs | 0 .../substrate}/src/client.rs | 0 .../substrate}/src/error.rs | 0 .../substrate}/src/finality_source.rs | 0 .../substrate}/src/guard.rs | 0 .../substrate}/src/headers_source.rs | 0 .../substrate}/src/lib.rs | 0 .../substrate}/src/rpc.rs | 0 .../substrate}/src/sync_header.rs | 0 relays/ethereum/Cargo.toml | 14 +- .../exchange}/Cargo.toml | 0 .../exchange}/src/exchange.rs | 0 .../exchange}/src/exchange_loop.rs | 0 .../exchange}/src/exchange_loop_metrics.rs | 0 .../exchange}/src/lib.rs | 0 .../finality}/Cargo.toml | 2 +- .../finality}/src/finality_loop.rs | 0 .../finality}/src/finality_loop_tests.rs | 0 .../finality}/src/lib.rs | 0 .../headers}/Cargo.toml | 0 .../headers}/src/headers.rs | 0 .../headers}/src/lib.rs | 0 .../headers}/src/sync.rs | 0 .../headers}/src/sync_loop.rs | 0 .../headers}/src/sync_loop_metrics.rs | 0 .../headers}/src/sync_loop_tests.rs | 0 .../headers}/src/sync_types.rs | 0 .../messages}/Cargo.toml | 2 +- .../messages}/src/lib.rs | 0 .../messages}/src/message_lane.rs | 0 .../messages}/src/message_lane_loop.rs | 0 .../messages}/src/message_race_delivery.rs | 0 .../messages}/src/message_race_loop.rs | 0 .../messages}/src/message_race_receiving.rs | 0 .../messages}/src/message_race_strategy.rs | 0 .../messages}/src/metrics.rs | 0 relays/{ => generic}/utils/Cargo.toml | 0 relays/{ => generic}/utils/src/initialize.rs | 0 relays/{ => generic}/utils/src/lib.rs | 0 relays/{ => generic}/utils/src/metrics.rs | 0 relays/{ => generic}/utils/src/relay_loop.rs | 0 relays/substrate/Cargo.toml | 19 +- relays/substrate/src/cli.rs | 442 +++----- relays/substrate/src/main.rs | 941 +----------------- relays/substrate/src/rialto_millau/cli.rs | 423 ++++++++ .../millau_headers_to_rialto.rs | 6 +- .../millau_messages_to_rialto.rs | 2 +- relays/substrate/src/rialto_millau/mod.rs | 922 +++++++++++++++++ .../rialto_headers_to_millau.rs | 6 +- .../rialto_messages_to_millau.rs | 2 +- 66 files changed, 1548 insertions(+), 1283 deletions(-) rename relays/{ethereum-client => clients/ethereum}/Cargo.toml (79%) rename relays/{ethereum-client => clients/ethereum}/src/client.rs (100%) rename relays/{ethereum-client => clients/ethereum}/src/error.rs (100%) rename relays/{ethereum-client => clients/ethereum}/src/lib.rs (100%) rename relays/{ethereum-client => clients/ethereum}/src/rpc.rs (100%) rename relays/{ethereum-client => clients/ethereum}/src/sign.rs (100%) rename relays/{ethereum-client => clients/ethereum}/src/types.rs (100%) rename relays/{kusama-client => clients/kusama}/Cargo.toml (80%) rename relays/{kusama-client => clients/kusama}/src/lib.rs (100%) rename relays/{millau-client => clients/millau}/Cargo.toml (79%) rename relays/{millau-client => clients/millau}/src/lib.rs (100%) rename relays/{polkadot-client => clients/polkadot}/Cargo.toml (79%) rename relays/{polkadot-client => clients/polkadot}/src/lib.rs (100%) rename relays/{rialto-client => clients/rialto}/Cargo.toml (80%) rename relays/{rialto-client => clients/rialto}/src/lib.rs (100%) rename relays/{substrate-client => clients/substrate}/Cargo.toml (79%) rename relays/{substrate-client => clients/substrate}/src/chain.rs (100%) rename relays/{substrate-client => clients/substrate}/src/client.rs (100%) rename relays/{substrate-client => clients/substrate}/src/error.rs (100%) rename relays/{substrate-client => clients/substrate}/src/finality_source.rs (100%) rename relays/{substrate-client => clients/substrate}/src/guard.rs (100%) rename relays/{substrate-client => clients/substrate}/src/headers_source.rs (100%) rename relays/{substrate-client => clients/substrate}/src/lib.rs (100%) rename relays/{substrate-client => clients/substrate}/src/rpc.rs (100%) rename relays/{substrate-client => clients/substrate}/src/sync_header.rs (100%) rename relays/{exchange-relay => generic/exchange}/Cargo.toml (100%) rename relays/{exchange-relay => generic/exchange}/src/exchange.rs (100%) rename relays/{exchange-relay => generic/exchange}/src/exchange_loop.rs (100%) rename relays/{exchange-relay => generic/exchange}/src/exchange_loop_metrics.rs (100%) rename relays/{exchange-relay => generic/exchange}/src/lib.rs (100%) rename relays/{finality-relay => generic/finality}/Cargo.toml (90%) rename relays/{finality-relay => generic/finality}/src/finality_loop.rs (100%) rename relays/{finality-relay => generic/finality}/src/finality_loop_tests.rs (100%) rename relays/{finality-relay => generic/finality}/src/lib.rs (100%) rename relays/{headers-relay => generic/headers}/Cargo.toml (100%) rename relays/{headers-relay => generic/headers}/src/headers.rs (100%) rename relays/{headers-relay => generic/headers}/src/lib.rs (100%) rename relays/{headers-relay => generic/headers}/src/sync.rs (100%) rename relays/{headers-relay => generic/headers}/src/sync_loop.rs (100%) rename relays/{headers-relay => generic/headers}/src/sync_loop_metrics.rs (100%) rename relays/{headers-relay => generic/headers}/src/sync_loop_tests.rs (100%) rename relays/{headers-relay => generic/headers}/src/sync_types.rs (100%) rename relays/{messages-relay => generic/messages}/Cargo.toml (85%) rename relays/{messages-relay => generic/messages}/src/lib.rs (100%) rename relays/{messages-relay => generic/messages}/src/message_lane.rs (100%) rename relays/{messages-relay => generic/messages}/src/message_lane_loop.rs (100%) rename relays/{messages-relay => generic/messages}/src/message_race_delivery.rs (100%) rename relays/{messages-relay => generic/messages}/src/message_race_loop.rs (100%) rename relays/{messages-relay => generic/messages}/src/message_race_receiving.rs (100%) rename relays/{messages-relay => generic/messages}/src/message_race_strategy.rs (100%) rename relays/{messages-relay => generic/messages}/src/metrics.rs (100%) rename relays/{ => generic}/utils/Cargo.toml (100%) rename relays/{ => generic}/utils/src/initialize.rs (100%) rename relays/{ => generic}/utils/src/lib.rs (100%) rename relays/{ => generic}/utils/src/metrics.rs (100%) rename relays/{ => generic}/utils/src/relay_loop.rs (100%) create mode 100644 relays/substrate/src/rialto_millau/cli.rs rename relays/substrate/src/{ => rialto_millau}/millau_headers_to_rialto.rs (95%) rename relays/substrate/src/{ => rialto_millau}/millau_messages_to_rialto.rs (99%) create mode 100644 relays/substrate/src/rialto_millau/mod.rs rename relays/substrate/src/{ => rialto_millau}/rialto_headers_to_millau.rs (95%) rename relays/substrate/src/{ => rialto_millau}/rialto_messages_to_millau.rs (99%) diff --git a/relays/ethereum-client/Cargo.toml b/relays/clients/ethereum/Cargo.toml similarity index 79% rename from relays/ethereum-client/Cargo.toml rename to relays/clients/ethereum/Cargo.toml index 4c04f4889469b..b73a66a44c0e1 100644 --- a/relays/ethereum-client/Cargo.toml +++ b/relays/clients/ethereum/Cargo.toml @@ -6,14 +6,14 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-eth-poa = { path = "../../primitives/ethereum-poa" } +bp-eth-poa = { path = "../../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../headers-relay" } +headers-relay = { path = "../../generic/headers" } hex-literal = "0.3" jsonrpsee-proc-macros = "0.2.0-alpha" jsonrpsee-types = "0.2.0-alpha" jsonrpsee-ws-client = "0.2.0-alpha" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" -relay-utils = { path = "../utils" } +relay-utils = { path = "../../generic/utils" } web3 = { version = "0.15", git = "https://github.com/tomusdrw/rust-web3", branch ="td-ethabi", default-features = false } diff --git a/relays/ethereum-client/src/client.rs b/relays/clients/ethereum/src/client.rs similarity index 100% rename from relays/ethereum-client/src/client.rs rename to relays/clients/ethereum/src/client.rs diff --git a/relays/ethereum-client/src/error.rs b/relays/clients/ethereum/src/error.rs similarity index 100% rename from relays/ethereum-client/src/error.rs rename to relays/clients/ethereum/src/error.rs diff --git a/relays/ethereum-client/src/lib.rs b/relays/clients/ethereum/src/lib.rs similarity index 100% rename from relays/ethereum-client/src/lib.rs rename to relays/clients/ethereum/src/lib.rs diff --git a/relays/ethereum-client/src/rpc.rs b/relays/clients/ethereum/src/rpc.rs similarity index 100% rename from relays/ethereum-client/src/rpc.rs rename to relays/clients/ethereum/src/rpc.rs diff --git a/relays/ethereum-client/src/sign.rs b/relays/clients/ethereum/src/sign.rs similarity index 100% rename from relays/ethereum-client/src/sign.rs rename to relays/clients/ethereum/src/sign.rs diff --git a/relays/ethereum-client/src/types.rs b/relays/clients/ethereum/src/types.rs similarity index 100% rename from relays/ethereum-client/src/types.rs rename to relays/clients/ethereum/src/types.rs diff --git a/relays/kusama-client/Cargo.toml b/relays/clients/kusama/Cargo.toml similarity index 80% rename from relays/kusama-client/Cargo.toml rename to relays/clients/kusama/Cargo.toml index cd311830ae615..e8e44ce2a87c0 100644 --- a/relays/kusama-client/Cargo.toml +++ b/relays/clients/kusama/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../headers-relay" } -relay-substrate-client = { path = "../substrate-client" } -relay-utils = { path = "../utils" } +headers-relay = { path = "../../generic/headers" } +relay-substrate-client = { path = "../substrate" } +relay-utils = { path = "../../generic/utils" } # Bridge dependencies -bp-kusama = { path = "../../primitives/chains/kusama" } +bp-kusama = { path = "../../../primitives/chains/kusama" } # Substrate Dependencies diff --git a/relays/kusama-client/src/lib.rs b/relays/clients/kusama/src/lib.rs similarity index 100% rename from relays/kusama-client/src/lib.rs rename to relays/clients/kusama/src/lib.rs diff --git a/relays/millau-client/Cargo.toml b/relays/clients/millau/Cargo.toml similarity index 79% rename from relays/millau-client/Cargo.toml rename to relays/clients/millau/Cargo.toml index 5f9cbd170c938..f975022aea869 100644 --- a/relays/millau-client/Cargo.toml +++ b/relays/clients/millau/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../headers-relay" } -relay-substrate-client = { path = "../substrate-client" } -relay-utils = { path = "../utils" } +headers-relay = { path = "../../generic/headers" } +relay-substrate-client = { path = "../../clients/substrate" } +relay-utils = { path = "../../generic/utils" } # Supported Chains -millau-runtime = { path = "../../bin/millau/runtime" } +millau-runtime = { path = "../../../bin/millau/runtime" } # Substrate Dependencies diff --git a/relays/millau-client/src/lib.rs b/relays/clients/millau/src/lib.rs similarity index 100% rename from relays/millau-client/src/lib.rs rename to relays/clients/millau/src/lib.rs diff --git a/relays/polkadot-client/Cargo.toml b/relays/clients/polkadot/Cargo.toml similarity index 79% rename from relays/polkadot-client/Cargo.toml rename to relays/clients/polkadot/Cargo.toml index a1d82758f8d62..b40397f194f34 100644 --- a/relays/polkadot-client/Cargo.toml +++ b/relays/clients/polkadot/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../headers-relay" } -relay-substrate-client = { path = "../substrate-client" } -relay-utils = { path = "../utils" } +headers-relay = { path = "../../generic/headers" } +relay-substrate-client = { path = "../substrate" } +relay-utils = { path = "../../generic/utils" } # Bridge dependencies -bp-polkadot = { path = "../../primitives/chains/polkadot" } +bp-polkadot = { path = "../../../primitives/chains/polkadot" } # Substrate Dependencies diff --git a/relays/polkadot-client/src/lib.rs b/relays/clients/polkadot/src/lib.rs similarity index 100% rename from relays/polkadot-client/src/lib.rs rename to relays/clients/polkadot/src/lib.rs diff --git a/relays/rialto-client/Cargo.toml b/relays/clients/rialto/Cargo.toml similarity index 80% rename from relays/rialto-client/Cargo.toml rename to relays/clients/rialto/Cargo.toml index 6142ba05c963c..74aeb8c30f00b 100644 --- a/relays/rialto-client/Cargo.toml +++ b/relays/clients/rialto/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../headers-relay" } -relay-substrate-client = { path = "../substrate-client" } -relay-utils = { path = "../utils" } +headers-relay = { path = "../../generic/headers" } +relay-substrate-client = { path = "../substrate" } +relay-utils = { path = "../../generic/utils" } # Bridge dependencies -rialto-runtime = { path = "../../bin/rialto/runtime" } +rialto-runtime = { path = "../../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/rialto-client/src/lib.rs b/relays/clients/rialto/src/lib.rs similarity index 100% rename from relays/rialto-client/src/lib.rs rename to relays/clients/rialto/src/lib.rs diff --git a/relays/substrate-client/Cargo.toml b/relays/clients/substrate/Cargo.toml similarity index 79% rename from relays/substrate-client/Cargo.toml rename to relays/clients/substrate/Cargo.toml index d02c08ab7ad70..bd73043e0a50d 100644 --- a/relays/substrate-client/Cargo.toml +++ b/relays/clients/substrate/Cargo.toml @@ -18,12 +18,12 @@ rand = "0.7" # Bridge dependencies -bp-header-chain = { path = "../../primitives/header-chain" } -bp-message-lane = { path = "../../primitives/message-lane" } -bp-runtime = { path = "../../primitives/runtime" } -finality-relay = { path = "../finality-relay" } -headers-relay = { path = "../headers-relay" } -relay-utils = { path = "../utils" } +bp-header-chain = { path = "../../../primitives/header-chain" } +bp-message-lane = { path = "../../../primitives/message-lane" } +bp-runtime = { path = "../../../primitives/runtime" } +finality-relay = { path = "../../generic/finality" } +headers-relay = { path = "../../generic/headers" } +relay-utils = { path = "../../generic/utils" } # Substrate Dependencies diff --git a/relays/substrate-client/src/chain.rs b/relays/clients/substrate/src/chain.rs similarity index 100% rename from relays/substrate-client/src/chain.rs rename to relays/clients/substrate/src/chain.rs diff --git a/relays/substrate-client/src/client.rs b/relays/clients/substrate/src/client.rs similarity index 100% rename from relays/substrate-client/src/client.rs rename to relays/clients/substrate/src/client.rs diff --git a/relays/substrate-client/src/error.rs b/relays/clients/substrate/src/error.rs similarity index 100% rename from relays/substrate-client/src/error.rs rename to relays/clients/substrate/src/error.rs diff --git a/relays/substrate-client/src/finality_source.rs b/relays/clients/substrate/src/finality_source.rs similarity index 100% rename from relays/substrate-client/src/finality_source.rs rename to relays/clients/substrate/src/finality_source.rs diff --git a/relays/substrate-client/src/guard.rs b/relays/clients/substrate/src/guard.rs similarity index 100% rename from relays/substrate-client/src/guard.rs rename to relays/clients/substrate/src/guard.rs diff --git a/relays/substrate-client/src/headers_source.rs b/relays/clients/substrate/src/headers_source.rs similarity index 100% rename from relays/substrate-client/src/headers_source.rs rename to relays/clients/substrate/src/headers_source.rs diff --git a/relays/substrate-client/src/lib.rs b/relays/clients/substrate/src/lib.rs similarity index 100% rename from relays/substrate-client/src/lib.rs rename to relays/clients/substrate/src/lib.rs diff --git a/relays/substrate-client/src/rpc.rs b/relays/clients/substrate/src/rpc.rs similarity index 100% rename from relays/substrate-client/src/rpc.rs rename to relays/clients/substrate/src/rpc.rs diff --git a/relays/substrate-client/src/sync_header.rs b/relays/clients/substrate/src/sync_header.rs similarity index 100% rename from relays/substrate-client/src/sync_header.rs rename to relays/clients/substrate/src/sync_header.rs diff --git a/relays/ethereum/Cargo.toml b/relays/ethereum/Cargo.toml index fbc1ef00fcaa9..1975830e5a5a4 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/ethereum/Cargo.toml @@ -29,13 +29,13 @@ time = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } -exchange-relay = { path = "../exchange-relay" } -headers-relay = { path = "../headers-relay" } -messages-relay = { path = "../messages-relay" } -relay-ethereum-client = { path = "../ethereum-client" } -relay-rialto-client = { path = "../rialto-client" } -relay-substrate-client = { path = "../substrate-client" } -relay-utils = { path = "../utils" } +exchange-relay = { path = "../generic/exchange" } +headers-relay = { path = "../generic/headers" } +messages-relay = { path = "../generic/messages" } +relay-ethereum-client = { path = "../clients/ethereum" } +relay-rialto-client = { path = "../clients/rialto" } +relay-substrate-client = { path = "../clients/substrate" } +relay-utils = { path = "../generic/utils" } rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/exchange-relay/Cargo.toml b/relays/generic/exchange/Cargo.toml similarity index 100% rename from relays/exchange-relay/Cargo.toml rename to relays/generic/exchange/Cargo.toml diff --git a/relays/exchange-relay/src/exchange.rs b/relays/generic/exchange/src/exchange.rs similarity index 100% rename from relays/exchange-relay/src/exchange.rs rename to relays/generic/exchange/src/exchange.rs diff --git a/relays/exchange-relay/src/exchange_loop.rs b/relays/generic/exchange/src/exchange_loop.rs similarity index 100% rename from relays/exchange-relay/src/exchange_loop.rs rename to relays/generic/exchange/src/exchange_loop.rs diff --git a/relays/exchange-relay/src/exchange_loop_metrics.rs b/relays/generic/exchange/src/exchange_loop_metrics.rs similarity index 100% rename from relays/exchange-relay/src/exchange_loop_metrics.rs rename to relays/generic/exchange/src/exchange_loop_metrics.rs diff --git a/relays/exchange-relay/src/lib.rs b/relays/generic/exchange/src/lib.rs similarity index 100% rename from relays/exchange-relay/src/lib.rs rename to relays/generic/exchange/src/lib.rs diff --git a/relays/finality-relay/Cargo.toml b/relays/generic/finality/Cargo.toml similarity index 90% rename from relays/finality-relay/Cargo.toml rename to relays/generic/finality/Cargo.toml index 9667ba2fa674c..e70fb39d137e1 100644 --- a/relays/finality-relay/Cargo.toml +++ b/relays/generic/finality/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" futures = "0.3.5" -headers-relay = { path = "../headers-relay" } +headers-relay = { path = "../headers" } log = "0.4.11" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality-relay/src/finality_loop.rs b/relays/generic/finality/src/finality_loop.rs similarity index 100% rename from relays/finality-relay/src/finality_loop.rs rename to relays/generic/finality/src/finality_loop.rs diff --git a/relays/finality-relay/src/finality_loop_tests.rs b/relays/generic/finality/src/finality_loop_tests.rs similarity index 100% rename from relays/finality-relay/src/finality_loop_tests.rs rename to relays/generic/finality/src/finality_loop_tests.rs diff --git a/relays/finality-relay/src/lib.rs b/relays/generic/finality/src/lib.rs similarity index 100% rename from relays/finality-relay/src/lib.rs rename to relays/generic/finality/src/lib.rs diff --git a/relays/headers-relay/Cargo.toml b/relays/generic/headers/Cargo.toml similarity index 100% rename from relays/headers-relay/Cargo.toml rename to relays/generic/headers/Cargo.toml diff --git a/relays/headers-relay/src/headers.rs b/relays/generic/headers/src/headers.rs similarity index 100% rename from relays/headers-relay/src/headers.rs rename to relays/generic/headers/src/headers.rs diff --git a/relays/headers-relay/src/lib.rs b/relays/generic/headers/src/lib.rs similarity index 100% rename from relays/headers-relay/src/lib.rs rename to relays/generic/headers/src/lib.rs diff --git a/relays/headers-relay/src/sync.rs b/relays/generic/headers/src/sync.rs similarity index 100% rename from relays/headers-relay/src/sync.rs rename to relays/generic/headers/src/sync.rs diff --git a/relays/headers-relay/src/sync_loop.rs b/relays/generic/headers/src/sync_loop.rs similarity index 100% rename from relays/headers-relay/src/sync_loop.rs rename to relays/generic/headers/src/sync_loop.rs diff --git a/relays/headers-relay/src/sync_loop_metrics.rs b/relays/generic/headers/src/sync_loop_metrics.rs similarity index 100% rename from relays/headers-relay/src/sync_loop_metrics.rs rename to relays/generic/headers/src/sync_loop_metrics.rs diff --git a/relays/headers-relay/src/sync_loop_tests.rs b/relays/generic/headers/src/sync_loop_tests.rs similarity index 100% rename from relays/headers-relay/src/sync_loop_tests.rs rename to relays/generic/headers/src/sync_loop_tests.rs diff --git a/relays/headers-relay/src/sync_types.rs b/relays/generic/headers/src/sync_types.rs similarity index 100% rename from relays/headers-relay/src/sync_types.rs rename to relays/generic/headers/src/sync_types.rs diff --git a/relays/messages-relay/Cargo.toml b/relays/generic/messages/Cargo.toml similarity index 85% rename from relays/messages-relay/Cargo.toml rename to relays/generic/messages/Cargo.toml index 9c2daefdb4271..427fe4829d7be 100644 --- a/relays/messages-relay/Cargo.toml +++ b/relays/generic/messages/Cargo.toml @@ -15,5 +15,5 @@ parking_lot = "0.11.0" # Bridge Dependencies -bp-message-lane = { path = "../../primitives/message-lane" } +bp-message-lane = { path = "../../../primitives/message-lane" } relay-utils = { path = "../utils" } diff --git a/relays/messages-relay/src/lib.rs b/relays/generic/messages/src/lib.rs similarity index 100% rename from relays/messages-relay/src/lib.rs rename to relays/generic/messages/src/lib.rs diff --git a/relays/messages-relay/src/message_lane.rs b/relays/generic/messages/src/message_lane.rs similarity index 100% rename from relays/messages-relay/src/message_lane.rs rename to relays/generic/messages/src/message_lane.rs diff --git a/relays/messages-relay/src/message_lane_loop.rs b/relays/generic/messages/src/message_lane_loop.rs similarity index 100% rename from relays/messages-relay/src/message_lane_loop.rs rename to relays/generic/messages/src/message_lane_loop.rs diff --git a/relays/messages-relay/src/message_race_delivery.rs b/relays/generic/messages/src/message_race_delivery.rs similarity index 100% rename from relays/messages-relay/src/message_race_delivery.rs rename to relays/generic/messages/src/message_race_delivery.rs diff --git a/relays/messages-relay/src/message_race_loop.rs b/relays/generic/messages/src/message_race_loop.rs similarity index 100% rename from relays/messages-relay/src/message_race_loop.rs rename to relays/generic/messages/src/message_race_loop.rs diff --git a/relays/messages-relay/src/message_race_receiving.rs b/relays/generic/messages/src/message_race_receiving.rs similarity index 100% rename from relays/messages-relay/src/message_race_receiving.rs rename to relays/generic/messages/src/message_race_receiving.rs diff --git a/relays/messages-relay/src/message_race_strategy.rs b/relays/generic/messages/src/message_race_strategy.rs similarity index 100% rename from relays/messages-relay/src/message_race_strategy.rs rename to relays/generic/messages/src/message_race_strategy.rs diff --git a/relays/messages-relay/src/metrics.rs b/relays/generic/messages/src/metrics.rs similarity index 100% rename from relays/messages-relay/src/metrics.rs rename to relays/generic/messages/src/metrics.rs diff --git a/relays/utils/Cargo.toml b/relays/generic/utils/Cargo.toml similarity index 100% rename from relays/utils/Cargo.toml rename to relays/generic/utils/Cargo.toml diff --git a/relays/utils/src/initialize.rs b/relays/generic/utils/src/initialize.rs similarity index 100% rename from relays/utils/src/initialize.rs rename to relays/generic/utils/src/initialize.rs diff --git a/relays/utils/src/lib.rs b/relays/generic/utils/src/lib.rs similarity index 100% rename from relays/utils/src/lib.rs rename to relays/generic/utils/src/lib.rs diff --git a/relays/utils/src/metrics.rs b/relays/generic/utils/src/metrics.rs similarity index 100% rename from relays/utils/src/metrics.rs rename to relays/generic/utils/src/metrics.rs diff --git a/relays/utils/src/relay_loop.rs b/relays/generic/utils/src/relay_loop.rs similarity index 100% rename from relays/utils/src/relay_loop.rs rename to relays/generic/utils/src/relay_loop.rs diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index fb5d48120c46b..d71cfa2f1e10f 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "2.0.0" } @@ -26,19 +27,19 @@ bp-polkadot = { path = "../../primitives/chains/polkadot" } bp-runtime = { path = "../../primitives/runtime" } bp-rialto = { path = "../../primitives/chains/rialto" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-relay = { path = "../finality-relay" } -headers-relay = { path = "../headers-relay" } -messages-relay = { path = "../messages-relay" } +finality-relay = { path = "../generic/finality" } +headers-relay = { path = "../generic/headers" } +messages-relay = { path = "../generic/messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } pallet-finality-verifier = { path = "../../modules/finality-verifier" } pallet-message-lane = { path = "../../modules/message-lane" } -relay-kusama-client = { path = "../kusama-client" } -relay-millau-client = { path = "../millau-client" } -relay-polkadot-client = { path = "../polkadot-client" } -relay-rialto-client = { path = "../rialto-client" } -relay-substrate-client = { path = "../substrate-client" } -relay-utils = { path = "../utils" } +relay-kusama-client = { path = "../clients/kusama" } +relay-millau-client = { path = "../clients/millau" } +relay-polkadot-client = { path = "../clients/polkadot" } +relay-rialto-client = { path = "../clients/rialto" } +relay-substrate-client = { path = "../clients/substrate" } +relay-utils = { path = "../generic/utils" } rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index d9bec5774740e..bfe5f6f549229 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -17,12 +17,12 @@ //! Deal with CLI args of substrate-to-substrate relay. use bp_message_lane::LaneId; -use frame_support::weights::Weight; -use sp_core::Bytes; -use sp_finality_grandpa::SetId as GrandpaAuthoritiesSetId; +use codec::{Decode, Encode}; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +use crate::rialto_millau::cli as rialto_millau; + /// Parse relay CLI args. pub fn parse_args() -> Command { Command::from_args() @@ -68,207 +68,140 @@ pub enum Command { DeriveAccount(DeriveAccount), } +impl Command { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::InitBridge(arg) => arg.run().await?, + Self::RelayHeaders(arg) => arg.run().await?, + Self::RelayMessages(arg) => arg.run().await?, + Self::SendMessage(arg) => arg.run().await?, + Self::EncodeCall(arg) => arg.run().await?, + Self::EncodeMessagePayload(arg) => arg.run().await?, + Self::EstimateFee(arg) => arg.run().await?, + Self::DeriveAccount(arg) => arg.run().await?, + } + Ok(()) + } +} + /// Start headers relayer process. #[derive(StructOpt)] pub enum RelayHeaders { - /// Relay Millau headers to Rialto. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - }, - /// Relay Rialto headers to Millau. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::RelayHeaders), +} + +impl RelayHeaders { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// Start message relayer process. #[derive(StructOpt)] pub enum RelayMessages { - /// Serve given lane of Millau -> Rialto messages. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - }, - /// Serve given lane of Rialto -> Millau messages. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::RelayMessages), +} + +impl RelayMessages { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// Initialize bridge pallet. #[derive(StructOpt)] pub enum InitBridge { - /// Initialize Millau headers bridge in Rialto. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau_bridge_params: MillauBridgeInitializationParams, - }, - /// Initialize Rialto headers bridge in Millau. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - rialto_bridge_params: RialtoBridgeInitializationParams, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::InitBridge), +} + +impl InitBridge { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// Send bridge message. #[derive(StructOpt)] pub enum SendMessage { - /// Submit message to given Millau -> Rialto lane. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - /// Hex-encoded lane id. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Dispatch weight of the message. If not passed, determined automatically. - #[structopt(long)] - dispatch_weight: Option>, - /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. - #[structopt(long)] - fee: Option, - /// Message type. - #[structopt(subcommand)] - message: ToRialtoMessage, - /// The origin to use when dispatching the message on the target chain. Defaults to - /// `SourceAccount`. - #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] - origin: Origins, - }, - /// Submit message to given Rialto -> Millau lane. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - /// Hex-encoded lane id. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Dispatch weight of the message. If not passed, determined automatically. - #[structopt(long)] - dispatch_weight: Option>, - /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. - #[structopt(long)] - fee: Option, - /// Message type. - #[structopt(subcommand)] - message: ToMillauMessage, - /// The origin to use when dispatching the message on the target chain. Defaults to - /// `SourceAccount`. - #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] - origin: Origins, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::SendMessage), +} + +impl SendMessage { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// A call to encode. #[derive(StructOpt)] pub enum EncodeCall { - /// Encode Rialto's Call. - Rialto { - #[structopt(flatten)] - call: ToRialtoMessage, - }, - /// Encode Millau's Call. - Millau { - #[structopt(flatten)] - call: ToMillauMessage, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::EncodeCall), +} + +impl EncodeCall { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// A `MessagePayload` to encode. #[derive(StructOpt)] pub enum EncodeMessagePayload { - /// Message Payload of Rialto to Millau call. - RialtoToMillau { - #[structopt(flatten)] - payload: RialtoToMillauMessagePayload, - }, - /// Message Payload of Millau to Rialto call. - MillauToRialto { - #[structopt(flatten)] - payload: MillauToRialtoMessagePayload, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::EncodeMessagePayload), +} + +impl EncodeMessagePayload { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// Estimate Delivery & Dispatch Fee command. #[derive(StructOpt)] pub enum EstimateFee { - /// Estimate fee of Rialto to Millau message. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - /// Hex-encoded id of lane that will be delivering the message. - #[structopt(long)] - lane: HexLaneId, - /// Payload to send over the bridge. - #[structopt(flatten)] - payload: RialtoToMillauMessagePayload, - }, - /// Estimate fee of Rialto to Millau message. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - /// Hex-encoded id of lane that will be delivering the message. - #[structopt(long)] - lane: HexLaneId, - /// Payload to send over the bridge. - #[structopt(flatten)] - payload: MillauToRialtoMessagePayload, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::EstimateFee), +} + +impl EstimateFee { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. @@ -279,122 +212,18 @@ pub enum EstimateFee { /// since messages sent over the bridge will be able to spend these. #[derive(StructOpt)] pub enum DeriveAccount { - /// Given Rialto AccountId, display corresponding Millau AccountId. - RialtoToMillau { account: AccountId }, - /// Given Millau AccountId, display corresponding Rialto AccountId. - MillauToRialto { account: AccountId }, -} - -/// MessagePayload that can be delivered to message lane pallet on Millau. -#[derive(StructOpt, Debug)] -pub enum MillauToRialtoMessagePayload { - /// Raw, SCALE-encoded `MessagePayload`. - Raw { - /// Hex-encoded SCALE data. - data: Bytes, - }, - /// Construct message to send over the bridge. - Message { - /// Message details. - #[structopt(flatten)] - message: ToRialtoMessage, - /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) - #[structopt(long)] - sender: AccountId, - }, -} - -/// MessagePayload that can be delivered to message lane pallet on Rialto. -#[derive(StructOpt, Debug)] -pub enum RialtoToMillauMessagePayload { - /// Raw, SCALE-encoded `MessagePayload`. - Raw { - /// Hex-encoded SCALE data. - data: Bytes, - }, - /// Construct message to send over the bridge. - Message { - /// Message details. - #[structopt(flatten)] - message: ToMillauMessage, - /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) - #[structopt(long)] - sender: AccountId, - }, -} - -/// All possible messages that may be delivered to the Rialto chain. -#[derive(StructOpt, Debug)] -pub enum ToRialtoMessage { - /// Raw bytes for the message - Raw { - /// Raw, SCALE-encoded message - data: Bytes, - }, - /// Make an on-chain remark (comment). - Remark { - /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. - #[structopt(long)] - remark_size: Option>, - }, - /// Transfer the specified `amount` of native tokens to a particular `recipient`. - Transfer { - /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) - #[structopt(long)] - recipient: AccountId, - /// Amount of target tokens to send in target chain base currency units. - #[structopt(long)] - amount: bp_rialto::Balance, - }, - /// A call to the Millau Bridge Message Lane pallet to send a message over the bridge. - MillauSendMessage { - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. - #[structopt(long)] - payload: Bytes, - /// Declared delivery and dispatch fee in base source-chain currency units. - #[structopt(long)] - fee: bp_rialto::Balance, - }, -} - -/// All possible messages that may be delivered to the Millau chain. -#[derive(StructOpt, Debug)] -pub enum ToMillauMessage { - /// Raw bytes for the message - Raw { - /// Raw, SCALE-encoded message - data: Bytes, - }, - /// Make an on-chain remark (comment). - Remark { - /// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark. - #[structopt(long)] - remark_size: Option>, - }, - /// Transfer the specified `amount` of native tokens to a particular `recipient`. - Transfer { - /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) - #[structopt(long)] - recipient: AccountId, - /// Amount of target tokens to send in target chain base currency units. - #[structopt(long)] - amount: bp_millau::Balance, - }, - /// A call to the Rialto Bridge Message Lane pallet to send a message over the bridge. - RialtoSendMessage { - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. - #[structopt(long)] - payload: Bytes, - /// Declared delivery and dispatch fee in base source-chain currency units. - #[structopt(long)] - fee: bp_millau::Balance, - }, + #[structopt(flatten)] + RialtoMillau(rialto_millau::DeriveAccount), +} + +impl DeriveAccount { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + Self::RialtoMillau(arg) => arg.run().await?, + } + Ok(()) + } } arg_enum! { @@ -456,7 +285,7 @@ impl AccountId { /// Lane id. #[derive(Debug)] -pub struct HexLaneId(LaneId); +pub struct HexLaneId(pub LaneId); impl From for LaneId { fn from(lane_id: HexLaneId) -> LaneId { @@ -474,6 +303,31 @@ impl std::str::FromStr for HexLaneId { } } +/// Nicer formatting for raw bytes vectors. +#[derive(Encode, Decode)] +pub struct HexBytes(pub Vec); + +impl std::str::FromStr for HexBytes { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + Ok(Self(hex::decode(s)?)) + } +} + +impl std::fmt::Debug for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "0x{}", hex::encode(&self.0)) + } +} + +impl HexBytes { + /// Encode given object and wrap into nicely formatted bytes. + pub fn encode(t: &T) -> Self { + Self(t.encode()) + } +} + /// Prometheus metrics params. #[derive(StructOpt)] pub struct PrometheusParams { @@ -527,6 +381,9 @@ where } } +/// Create chain-specific set of configuration objects: connection parameters, +/// signing parameters and bridge initialisation parameters. +#[macro_export] macro_rules! declare_chain_options { ($chain:ident, $chain_prefix:ident) => { paste::item! { @@ -557,17 +414,14 @@ macro_rules! declare_chain_options { pub struct [<$chain BridgeInitializationParams>] { #[doc = "Hex-encoded " $chain " header to initialize bridge with. If not specified, genesis header is used."] #[structopt(long)] - pub [<$chain_prefix _initial_header>]: Option, + pub [<$chain_prefix _initial_header>]: Option, #[doc = "Hex-encoded " $chain " GRANDPA authorities set to initialize bridge with. If not specified, set from genesis block is used."] #[structopt(long)] - pub [<$chain_prefix _initial_authorities>]: Option, + pub [<$chain_prefix _initial_authorities>]: Option, #[doc = "Id of the " $chain " GRANDPA authorities set to initialize bridge with. If not specified, zero is used."] #[structopt(long)] - pub [<$chain_prefix _initial_authorities_set_id>]: Option, + pub [<$chain_prefix _initial_authorities_set_id>]: Option, } } }; } - -declare_chain_options!(Rialto, rialto); -declare_chain_options!(Millau, millau); diff --git a/relays/substrate/src/main.rs b/relays/substrate/src/main.rs index 8cd437027c95c..eaaa9848836e9 100644 --- a/relays/substrate/src/main.rs +++ b/relays/substrate/src/main.rs @@ -18,24 +18,7 @@ #![warn(missing_docs)] -use codec::{Decode, Encode}; -use frame_support::weights::{GetDispatchInfo, Weight}; -use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; -use relay_kusama_client::Kusama; -use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; use relay_utils::initialize::initialize_relay; -use sp_core::{Bytes, Pair}; -use sp_runtime::traits::IdentifyAccount; -use std::fmt::Debug; - -/// Kusama node client. -pub type KusamaClient = relay_substrate_client::Client; -/// Millau node client. -pub type MillauClient = relay_substrate_client::Client; -/// Rialto node client. -pub type RialtoClient = relay_substrate_client::Client; mod cli; mod finality_pipeline; @@ -44,929 +27,15 @@ mod headers_initialize; mod messages_lane; mod messages_source; mod messages_target; -mod millau_headers_to_rialto; -mod millau_messages_to_rialto; -mod rialto_headers_to_millau; -mod rialto_messages_to_millau; + +mod rialto_millau; fn main() { initialize_relay(); - - let result = async_std::task::block_on(run_command(cli::parse_args())); + let command = cli::parse_args(); + let run = command.run(); + let result = async_std::task::block_on(run); if let Err(error) = result { log::error!(target: "bridge", "Failed to start relay: {}", error); } } - -async fn run_command(command: cli::Command) -> Result<(), String> { - match command { - cli::Command::InitBridge(arg) => run_init_bridge(arg).await, - cli::Command::RelayHeaders(arg) => run_relay_headers(arg).await, - cli::Command::RelayMessages(arg) => run_relay_messages(arg).await, - cli::Command::SendMessage(arg) => run_send_message(arg).await, - cli::Command::EncodeCall(arg) => run_encode_call(arg).await, - cli::Command::EncodeMessagePayload(arg) => run_encode_message_payload(arg).await, - cli::Command::EstimateFee(arg) => run_estimate_fee(arg).await, - cli::Command::DeriveAccount(arg) => run_derive_account(arg).await, - } -} - -async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { - match command { - cli::InitBridge::MillauToRialto { - millau, - rialto, - rialto_sign, - millau_bridge_params, - } => { - let millau_client = millau.into_client().await?; - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - - let rialto_signer_next_index = rialto_client - .next_account_index(rialto_sign.signer.public().into()) - .await?; - - headers_initialize::initialize( - millau_client, - rialto_client.clone(), - millau_bridge_params.millau_initial_header, - millau_bridge_params.millau_initial_authorities, - millau_bridge_params.millau_initial_authorities_set_id, - move |initialization_data| { - Ok(Bytes( - Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, - rialto_signer_next_index, - rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::FinalityBridgeMillauCall::initialize(initialization_data).into(), - )) - .into(), - ) - .encode(), - )) - }, - ) - .await; - } - cli::InitBridge::RialtoToMillau { - rialto, - millau, - millau_sign, - rialto_bridge_params, - } => { - let rialto_client = rialto.into_client().await?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - let millau_signer_next_index = millau_client - .next_account_index(millau_sign.signer.public().into()) - .await?; - - headers_initialize::initialize( - rialto_client, - millau_client.clone(), - rialto_bridge_params.rialto_initial_header, - rialto_bridge_params.rialto_initial_authorities, - rialto_bridge_params.rialto_initial_authorities_set_id, - move |initialization_data| { - Ok(Bytes( - Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - millau_signer_next_index, - millau_runtime::SudoCall::sudo(Box::new( - millau_runtime::FinalityBridgeRialtoCall::initialize(initialization_data).into(), - )) - .into(), - ) - .encode(), - )) - }, - ) - .await; - } - } - Ok(()) -} - -async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { - match command { - cli::RelayHeaders::MillauToRialto { - millau, - rialto, - rialto_sign, - prometheus_params, - } => { - let millau_client = millau.into_client().await?; - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; - } - cli::RelayHeaders::RialtoToMillau { - rialto, - millau, - millau_sign, - prometheus_params, - } => { - let rialto_client = rialto.into_client().await?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; - } - } - Ok(()) -} - -async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { - match command { - cli::RelayMessages::MillauToRialto { - millau, - millau_sign, - rialto, - rialto_sign, - prometheus_params, - lane, - } => { - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - - millau_messages_to_rialto::run( - millau_client, - millau_sign, - rialto_client, - rialto_sign, - lane.into(), - prometheus_params.into(), - ); - } - cli::RelayMessages::RialtoToMillau { - rialto, - rialto_sign, - millau, - millau_sign, - prometheus_params, - lane, - } => { - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - - rialto_messages_to_millau::run( - rialto_client, - rialto_sign, - millau_client, - millau_sign, - lane.into(), - prometheus_params.into(), - ); - } - } - Ok(()) -} - -async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { - match command { - cli::SendMessage::MillauToRialto { - millau, - millau_sign, - rialto_sign, - lane, - message, - dispatch_weight, - fee, - origin, - .. - } => { - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - let rialto_sign = rialto_sign.parse()?; - let rialto_call = message.into_call()?; - - let payload = - millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin, dispatch_weight); - let dispatch_weight = payload.weight; - - let lane = lane.into(); - let fee = get_fee(fee, || { - estimate_message_delivery_and_dispatch_fee( - &millau_client, - bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload.clone(), - ) - }) - .await?; - - let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( - millau_runtime::MessageLaneCall::send_message(lane, payload, fee), - ); - - let signed_millau_call = Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - millau_client - .next_account_index(millau_sign.signer.public().clone().into()) - .await?, - millau_call, - ) - .encode(); - - log::info!( - target: "bridge", - "Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}", - signed_millau_call.len(), - dispatch_weight, - fee, - ); - log::info!(target: "bridge", "Signed Millau Call: {:?}", HexBytes::encode(&signed_millau_call)); - - millau_client.submit_extrinsic(Bytes(signed_millau_call)).await?; - } - cli::SendMessage::RialtoToMillau { - rialto, - rialto_sign, - millau_sign, - lane, - message, - dispatch_weight, - fee, - origin, - .. - } => { - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - let millau_sign = millau_sign.parse()?; - let millau_call = message.into_call()?; - - let payload = - rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin, dispatch_weight); - let dispatch_weight = payload.weight; - - let lane = lane.into(); - let fee = get_fee(fee, || { - estimate_message_delivery_and_dispatch_fee( - &rialto_client, - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload.clone(), - ) - }) - .await?; - - let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( - rialto_runtime::MessageLaneCall::send_message(lane, payload, fee), - ); - - let signed_rialto_call = Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, - rialto_client - .next_account_index(rialto_sign.signer.public().clone().into()) - .await?, - rialto_call, - ) - .encode(); - - log::info!( - target: "bridge", - "Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}", - signed_rialto_call.len(), - dispatch_weight, - fee, - ); - log::info!(target: "bridge", "Signed Rialto Call: {:?}", HexBytes::encode(&signed_rialto_call)); - - rialto_client.submit_extrinsic(Bytes(signed_rialto_call)).await?; - } - } - Ok(()) -} - -async fn run_encode_call(call: cli::EncodeCall) -> Result<(), String> { - match call { - cli::EncodeCall::Rialto { call } => { - let call = call.into_call()?; - - println!("{:?}", HexBytes::encode(&call)); - } - cli::EncodeCall::Millau { call } => { - let call = call.into_call()?; - println!("{:?}", HexBytes::encode(&call)); - } - } - Ok(()) -} - -async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<(), String> { - match call { - cli::EncodeMessagePayload::RialtoToMillau { payload } => { - let payload = payload.into_payload()?; - - println!("{:?}", HexBytes::encode(&payload)); - } - cli::EncodeMessagePayload::MillauToRialto { payload } => { - let payload = payload.into_payload()?; - - println!("{:?}", HexBytes::encode(&payload)); - } - } - Ok(()) -} - -async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { - match cmd { - cli::EstimateFee::RialtoToMillau { rialto, lane, payload } => { - let client = rialto.into_client().await?; - let lane = lane.into(); - let payload = payload.into_payload()?; - - let fee: Option = estimate_message_delivery_and_dispatch_fee( - &client, - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload, - ) - .await?; - - println!("Fee: {:?}", fee); - } - cli::EstimateFee::MillauToRialto { millau, lane, payload } => { - let client = millau.into_client().await?; - let lane = lane.into(); - let payload = payload.into_payload()?; - - let fee: Option = estimate_message_delivery_and_dispatch_fee( - &client, - bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload, - ) - .await?; - - println!("Fee: {:?}", fee); - } - } - - Ok(()) -} - -async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { - match cmd { - cli::DeriveAccount::RialtoToMillau { account } => { - let account = account.into_rialto(); - let acc = bp_runtime::SourceAccount::Account(account.clone()); - let id = bp_millau::derive_account_from_rialto_id(acc); - println!( - "{} (Rialto)\n\nCorresponding (derived) account id:\n-> {} (Millau)", - account, id - ) - } - cli::DeriveAccount::MillauToRialto { account } => { - let account = account.into_millau(); - let acc = bp_runtime::SourceAccount::Account(account.clone()); - let id = bp_rialto::derive_account_from_millau_id(acc); - println!( - "{} (Millau)\n\nCorresponding (derived) account id:\n-> {} (Rialto)", - account, id - ) - } - } - - Ok(()) -} - -async fn estimate_message_delivery_and_dispatch_fee( - client: &relay_substrate_client::Client, - estimate_fee_method: &str, - lane: bp_message_lane::LaneId, - payload: P, -) -> Result, relay_substrate_client::Error> { - let encoded_response = client - .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) - .await?; - let decoded_response: Option = - Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?; - Ok(decoded_response) -} - -fn remark_payload(remark_size: Option>, maximal_allowed_size: u32) -> Vec { - match remark_size { - Some(cli::ExplicitOrMaximal::Explicit(remark_size)) => vec![0; remark_size], - Some(cli::ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], - None => format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - } -} - -fn message_payload( - spec_version: u32, - weight: Weight, - origin: CallOrigin, - call: &impl Encode, -) -> MessagePayload> -where - SAccountId: Encode + Debug, - TPublic: Encode + Debug, - TSignature: Encode + Debug, -{ - // Display nicely formatted call. - let payload = MessagePayload { - spec_version, - weight, - origin, - call: HexBytes::encode(call), - }; - - log::info!(target: "bridge", "Created Message Payload: {:#?}", payload); - log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); - - // re-pack to return `Vec` - let MessagePayload { - spec_version, - weight, - origin, - call, - } = payload; - MessagePayload { - spec_version, - weight, - origin, - call: call.0, - } -} - -fn rialto_to_millau_message_payload( - rialto_sign: &RialtoSigningParams, - millau_sign: &MillauSigningParams, - millau_call: &millau_runtime::Call, - origin: cli::Origins, - user_specified_dispatch_weight: Option>, -) -> rialto_runtime::millau_messages::ToMillauMessagePayload { - let millau_call_weight = prepare_call_dispatch_weight( - user_specified_dispatch_weight, - cli::ExplicitOrMaximal::Explicit(millau_call.get_dispatch_info().weight), - compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()), - ); - let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); - let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); - let millau_origin_public = millau_sign.signer.public(); - - message_payload( - millau_runtime::VERSION.spec_version, - millau_call_weight, - match origin { - cli::Origins::Source => CallOrigin::SourceAccount(rialto_account_id), - cli::Origins::Target => { - let digest = rialto_runtime::millau_account_ownership_digest( - &millau_call, - rialto_account_id.clone(), - millau_runtime::VERSION.spec_version, - ); - - let digest_signature = millau_sign.signer.sign(&digest); - - CallOrigin::TargetAccount(rialto_account_id, millau_origin_public.into(), digest_signature.into()) - } - }, - &millau_call, - ) -} - -fn millau_to_rialto_message_payload( - millau_sign: &MillauSigningParams, - rialto_sign: &RialtoSigningParams, - rialto_call: &rialto_runtime::Call, - origin: cli::Origins, - user_specified_dispatch_weight: Option>, -) -> millau_runtime::rialto_messages::ToRialtoMessagePayload { - let rialto_call_weight = prepare_call_dispatch_weight( - user_specified_dispatch_weight, - cli::ExplicitOrMaximal::Explicit(rialto_call.get_dispatch_info().weight), - compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), - ); - let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); - let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); - let rialto_origin_public = rialto_sign.signer.public(); - - message_payload( - rialto_runtime::VERSION.spec_version, - rialto_call_weight, - match origin { - cli::Origins::Source => CallOrigin::SourceAccount(millau_account_id), - cli::Origins::Target => { - let digest = millau_runtime::rialto_account_ownership_digest( - &rialto_call, - millau_account_id.clone(), - rialto_runtime::VERSION.spec_version, - ); - - let digest_signature = rialto_sign.signer.sign(&digest); - - CallOrigin::TargetAccount(millau_account_id, rialto_origin_public.into(), digest_signature.into()) - } - }, - &rialto_call, - ) -} - -fn prepare_call_dispatch_weight( - user_specified_dispatch_weight: Option>, - weight_from_pre_dispatch_call: cli::ExplicitOrMaximal, - maximal_allowed_weight: Weight, -) -> Weight { - match user_specified_dispatch_weight.unwrap_or(weight_from_pre_dispatch_call) { - cli::ExplicitOrMaximal::Explicit(weight) => weight, - cli::ExplicitOrMaximal::Maximal => maximal_allowed_weight, - } -} - -async fn get_fee(fee: Option, f: F) -> Result -where - Fee: Decode, - F: FnOnce() -> R, - R: std::future::Future, E>>, - E: Debug, -{ - match fee { - Some(fee) => Ok(fee), - None => match f().await { - Ok(Some(fee)) => Ok(fee), - Ok(None) => Err("Failed to estimate message fee. Message is too heavy?".into()), - Err(error) => Err(format!("Failed to estimate message fee: {:?}", error)), - }, - } -} - -fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { - bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) -} - -fn compute_maximal_message_arguments_size( - maximal_source_extrinsic_size: u32, - maximal_target_extrinsic_size: u32, -) -> u32 { - // assume that both signed extensions and other arguments fit 1KB - let service_tx_bytes_on_source_chain = 1024; - let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; - let maximal_call_size = - bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size); - let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { - maximal_source_extrinsic_size - } else { - maximal_call_size - }; - - // bytes in Call encoding that are used to encode everything except arguments - let service_bytes = 1 + 1 + 4; - maximal_call_size - service_bytes -} - -impl crate::cli::MillauToRialtoMessagePayload { - /// Parse the CLI parameters and construct message payload. - pub fn into_payload( - self, - ) -> Result>, String> { - match self { - Self::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), - Self::Message { message, sender } => { - let spec_version = rialto_runtime::VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.into_millau()); - let call = message.into_call()?; - let weight = call.get_dispatch_info().weight; - - Ok(message_payload(spec_version, weight, origin, &call)) - } - } - } -} - -impl crate::cli::RialtoToMillauMessagePayload { - /// Parse the CLI parameters and construct message payload. - pub fn into_payload( - self, - ) -> Result>, String> { - match self { - Self::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), - Self::Message { message, sender } => { - let spec_version = millau_runtime::VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.into_rialto()); - let call = message.into_call()?; - let weight = call.get_dispatch_info().weight; - - Ok(message_payload(spec_version, weight, origin, &call)) - } - } - } -} - -impl crate::cli::RialtoSigningParams { - /// Parse CLI parameters into typed signing params. - pub fn parse(self) -> Result { - RialtoSigningParams::from_suri(&self.rialto_signer, self.rialto_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e)) - } -} - -impl crate::cli::MillauSigningParams { - /// Parse CLI parameters into typed signing params. - pub fn parse(self) -> Result { - MillauSigningParams::from_suri(&self.millau_signer, self.millau_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e)) - } -} - -impl crate::cli::MillauConnectionParams { - /// Convert CLI connection parameters into Millau RPC Client. - pub async fn into_client(self) -> relay_substrate_client::Result { - MillauClient::new(ConnectionParams { - host: self.millau_host, - port: self.millau_port, - }) - .await - } -} -impl crate::cli::RialtoConnectionParams { - /// Convert CLI connection parameters into Rialto RPC Client. - pub async fn into_client(self) -> relay_substrate_client::Result { - RialtoClient::new(ConnectionParams { - host: self.rialto_host, - port: self.rialto_port, - }) - .await - } -} - -impl crate::cli::ToRialtoMessage { - /// Convert CLI call request into runtime `Call` instance. - pub fn into_call(self) -> Result { - let call = match self { - cli::ToRialtoMessage::Raw { data } => { - Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? - } - cli::ToRialtoMessage::Remark { remark_size } => { - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload( - remark_size, - compute_maximal_message_arguments_size( - bp_millau::max_extrinsic_size(), - bp_rialto::max_extrinsic_size(), - ), - ))) - } - cli::ToRialtoMessage::Transfer { recipient, amount } => { - let recipient = recipient.into_rialto(); - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) - } - cli::ToRialtoMessage::MillauSendMessage { lane, payload, fee } => { - let payload = cli::RialtoToMillauMessagePayload::Raw { data: payload }.into_payload()?; - let lane = lane.into(); - rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( - lane, payload, fee, - )) - } - }; - - log::info!(target: "bridge", "Generated Rialto call: {:#?}", call); - log::info!(target: "bridge", "Weight of Rialto call: {}", call.get_dispatch_info().weight); - log::info!(target: "bridge", "Encoded Rialto call: {:?}", HexBytes::encode(&call)); - - Ok(call) - } -} - -impl crate::cli::ToMillauMessage { - /// Convert CLI call request into runtime `Call` instance. - pub fn into_call(self) -> Result { - let call = match self { - cli::ToMillauMessage::Raw { data } => { - Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? - } - cli::ToMillauMessage::Remark { remark_size } => { - millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( - remark_size, - compute_maximal_message_arguments_size( - bp_rialto::max_extrinsic_size(), - bp_millau::max_extrinsic_size(), - ), - ))) - } - cli::ToMillauMessage::Transfer { recipient, amount } => { - let recipient = recipient.into_millau(); - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) - } - cli::ToMillauMessage::RialtoSendMessage { lane, payload, fee } => { - let payload = cli::MillauToRialtoMessagePayload::Raw { data: payload }.into_payload()?; - let lane = lane.into(); - millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( - lane, payload, fee, - )) - } - }; - - log::info!(target: "bridge", "Generated Millau call: {:#?}", call); - log::info!(target: "bridge", "Weight of Millau call: {}", call.get_dispatch_info().weight); - log::info!(target: "bridge", "Encoded Millau call: {:?}", HexBytes::encode(&call)); - - Ok(call) - } -} - -/// Nicer formatting for raw bytes vectors. -#[derive(Encode, Decode)] -struct HexBytes(Vec); - -impl Debug for HexBytes { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "0x{}", hex::encode(&self.0)) - } -} - -impl HexBytes { - /// Encode given object and wrap into nicely formatted bytes. - pub fn encode(t: &T) -> Self { - Self(t.encode()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_message_lane::source_chain::TargetHeaderChain; - use sp_core::Pair; - use sp_runtime::traits::{IdentifyAccount, Verify}; - - #[test] - fn millau_signature_is_valid_on_rialto() { - let millau_sign = relay_millau_client::SigningParams::from_suri("//Dave", None).unwrap(); - - let call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); - - let millau_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); - let millau_account_id: bp_millau::AccountId = millau_public.into_account(); - - let digest = millau_runtime::rialto_account_ownership_digest( - &call, - millau_account_id, - rialto_runtime::VERSION.spec_version, - ); - - let rialto_signer = relay_rialto_client::SigningParams::from_suri("//Dave", None).unwrap(); - let signature = rialto_signer.signer.sign(&digest); - - assert!(signature.verify(&digest[..], &rialto_signer.signer.public())); - } - - #[test] - fn rialto_signature_is_valid_on_millau() { - let rialto_sign = relay_rialto_client::SigningParams::from_suri("//Dave", None).unwrap(); - - let call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); - - let rialto_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); - let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); - - let digest = rialto_runtime::millau_account_ownership_digest( - &call, - rialto_account_id, - millau_runtime::VERSION.spec_version, - ); - - let millau_signer = relay_millau_client::SigningParams::from_suri("//Dave", None).unwrap(); - let signature = millau_signer.signer.sign(&digest); - - assert!(signature.verify(&digest[..], &millau_signer.signer.public())); - } - - #[test] - fn maximal_rialto_to_millau_message_arguments_size_is_computed_correctly() { - use rialto_runtime::millau_messages::Millau; - - let maximal_remark_size = - compute_maximal_message_arguments_size(bp_rialto::max_extrinsic_size(), bp_millau::max_extrinsic_size()); - - let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); - let payload = message_payload( - Default::default(), - call.get_dispatch_info().weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - &call, - ); - assert_eq!(Millau::verify_message(&payload), Ok(())); - - let call: millau_runtime::Call = - millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into(); - let payload = message_payload( - Default::default(), - call.get_dispatch_info().weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - &call, - ); - assert!(Millau::verify_message(&payload).is_err()); - } - - #[test] - fn maximal_size_remark_to_rialto_is_generated_correctly() { - assert!( - bridge_runtime_common::messages::target::maximal_incoming_message_size( - bp_rialto::max_extrinsic_size() - ) > bp_millau::max_extrinsic_size(), - "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", - ) - } - - #[test] - fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() { - use rialto_runtime::millau_messages::Millau; - - let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); - let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); - - let payload = message_payload( - Default::default(), - maximal_dispatch_weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - &call, - ); - assert_eq!(Millau::verify_message(&payload), Ok(())); - - let payload = message_payload( - Default::default(), - maximal_dispatch_weight + 1, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - &call, - ); - assert!(Millau::verify_message(&payload).is_err()); - } - - #[test] - fn maximal_weight_fill_block_to_rialto_is_generated_correctly() { - use millau_runtime::rialto_messages::Rialto; - - let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); - let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); - - let payload = message_payload( - Default::default(), - maximal_dispatch_weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - &call, - ); - assert_eq!(Rialto::verify_message(&payload), Ok(())); - - let payload = message_payload( - Default::default(), - maximal_dispatch_weight + 1, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, - &call, - ); - assert!(Rialto::verify_message(&payload).is_err()); - } - - #[test] - fn rialto_tx_extra_bytes_constant_is_correct() { - let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); - let rialto_tx = Rialto::sign_transaction( - Default::default(), - &sp_keyring::AccountKeyring::Alice.pair(), - 0, - rialto_call.clone(), - ); - let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); - assert!( - bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, - "Hardcoded number of extra bytes in Rialto transaction {} is lower than actual value: {}", - bp_rialto::TX_EXTRA_BYTES, - extra_bytes_in_transaction, - ); - } - - #[test] - fn millau_tx_extra_bytes_constant_is_correct() { - let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); - let millau_tx = Millau::sign_transaction( - Default::default(), - &sp_keyring::AccountKeyring::Alice.pair(), - 0, - millau_call.clone(), - ); - let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); - assert!( - bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, - "Hardcoded number of extra bytes in Millau transaction {} is lower than actual value: {}", - bp_millau::TX_EXTRA_BYTES, - extra_bytes_in_transaction, - ); - } -} diff --git a/relays/substrate/src/rialto_millau/cli.rs b/relays/substrate/src/rialto_millau/cli.rs new file mode 100644 index 0000000000000..6ef5625921e32 --- /dev/null +++ b/relays/substrate/src/rialto_millau/cli.rs @@ -0,0 +1,423 @@ +// Copyright 2019-2020 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 . + +//! Deal with CLI args of Rialto <> Millau relay. + +use frame_support::weights::Weight; +use structopt::StructOpt; + +use crate::cli::{AccountId, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, PrometheusParams}; +use crate::declare_chain_options; + +/// Start headers relayer process. +#[derive(StructOpt)] +pub enum RelayHeaders { + /// Relay Millau headers to Rialto. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + }, + /// Relay Rialto headers to Millau. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + }, +} + +impl RelayHeaders { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_relay_headers(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// Start message relayer process. +#[derive(StructOpt)] +pub enum RelayMessages { + /// Serve given lane of Millau -> Rialto messages. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + }, + /// Serve given lane of Rialto -> Millau messages. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + }, +} + +impl RelayMessages { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_relay_messages(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// Initialize bridge pallet. +#[derive(StructOpt)] +pub enum InitBridge { + /// Initialize Millau headers bridge in Rialto. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau_bridge_params: MillauBridgeInitializationParams, + }, + /// Initialize Rialto headers bridge in Millau. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto_bridge_params: RialtoBridgeInitializationParams, + }, +} + +impl InitBridge { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_init_bridge(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// Send bridge message. +#[derive(StructOpt)] +pub enum SendMessage { + /// Submit message to given Millau -> Rialto lane. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + /// Hex-encoded lane id. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Dispatch weight of the message. If not passed, determined automatically. + #[structopt(long)] + dispatch_weight: Option>, + /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. + #[structopt(long)] + fee: Option, + /// Message type. + #[structopt(subcommand)] + message: ToRialtoMessage, + /// The origin to use when dispatching the message on the target chain. Defaults to + /// `SourceAccount`. + #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] + origin: Origins, + }, + /// Submit message to given Rialto -> Millau lane. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + #[structopt(flatten)] + rialto_sign: RialtoSigningParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + /// Hex-encoded lane id. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Dispatch weight of the message. If not passed, determined automatically. + #[structopt(long)] + dispatch_weight: Option>, + /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. + #[structopt(long)] + fee: Option, + /// Message type. + #[structopt(subcommand)] + message: ToMillauMessage, + /// The origin to use when dispatching the message on the target chain. Defaults to + /// `SourceAccount`. + #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] + origin: Origins, + }, +} + +impl SendMessage { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_send_message(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// A call to encode. +#[derive(StructOpt)] +pub enum EncodeCall { + /// Encode Rialto's Call. + Rialto { + #[structopt(flatten)] + call: ToRialtoMessage, + }, + /// Encode Millau's Call. + Millau { + #[structopt(flatten)] + call: ToMillauMessage, + }, +} + +impl EncodeCall { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_encode_call(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// A `MessagePayload` to encode. +#[derive(StructOpt)] +pub enum EncodeMessagePayload { + /// Message Payload of Rialto to Millau call. + RialtoToMillau { + #[structopt(flatten)] + payload: RialtoToMillauMessagePayload, + }, + /// Message Payload of Millau to Rialto call. + MillauToRialto { + #[structopt(flatten)] + payload: MillauToRialtoMessagePayload, + }, +} + +impl EncodeMessagePayload { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_encode_message_payload(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// Estimate Delivery & Dispatch Fee command. +#[derive(StructOpt)] +pub enum EstimateFee { + /// Estimate fee of Rialto to Millau message. + RialtoToMillau { + #[structopt(flatten)] + rialto: RialtoConnectionParams, + /// Hex-encoded id of lane that will be delivering the message. + #[structopt(long)] + lane: HexLaneId, + /// Payload to send over the bridge. + #[structopt(flatten)] + payload: RialtoToMillauMessagePayload, + }, + /// Estimate fee of Rialto to Millau message. + MillauToRialto { + #[structopt(flatten)] + millau: MillauConnectionParams, + /// Hex-encoded id of lane that will be delivering the message. + #[structopt(long)] + lane: HexLaneId, + /// Payload to send over the bridge. + #[structopt(flatten)] + payload: MillauToRialtoMessagePayload, + }, +} + +impl EstimateFee { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_estimate_fee(self).await.map_err(format_err)?; + Ok(()) + } +} + +/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. +/// +/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call +/// that has been sent over the bridge. +/// This account can also be used to receive target-chain funds (or other form of ownership), +/// since messages sent over the bridge will be able to spend these. +#[derive(StructOpt)] +pub enum DeriveAccount { + /// Given Rialto AccountId, display corresponding Millau AccountId. + RialtoToMillau { account: AccountId }, + /// Given Millau AccountId, display corresponding Rialto AccountId. + MillauToRialto { account: AccountId }, +} + +impl DeriveAccount { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + super::run_derive_account(self).await.map_err(format_err)?; + Ok(()) + } +} + +fn format_err(err: String) -> anyhow::Error { + anyhow::anyhow!(err) +} + +/// MessagePayload that can be delivered to message lane pallet on Millau. +#[derive(StructOpt, Debug)] +pub enum MillauToRialtoMessagePayload { + /// Raw, SCALE-encoded `MessagePayload`. + Raw { + /// Hex-encoded SCALE data. + data: HexBytes, + }, + /// Construct message to send over the bridge. + Message { + /// Message details. + #[structopt(flatten)] + message: ToRialtoMessage, + /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) + #[structopt(long)] + sender: AccountId, + }, +} + +/// MessagePayload that can be delivered to message lane pallet on Rialto. +#[derive(StructOpt, Debug)] +pub enum RialtoToMillauMessagePayload { + /// Raw, SCALE-encoded `MessagePayload`. + Raw { + /// Hex-encoded SCALE data. + data: HexBytes, + }, + /// Construct message to send over the bridge. + Message { + /// Message details. + #[structopt(flatten)] + message: ToMillauMessage, + /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) + #[structopt(long)] + sender: AccountId, + }, +} + +/// All possible messages that may be delivered to the Rialto chain. +#[derive(StructOpt, Debug)] +pub enum ToRialtoMessage { + /// Raw bytes for the message + Raw { + /// Raw, SCALE-encoded message + data: HexBytes, + }, + /// Make an on-chain remark (comment). + Remark { + /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. + #[structopt(long)] + remark_size: Option>, + }, + /// Transfer the specified `amount` of native tokens to a particular `recipient`. + Transfer { + /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) + #[structopt(long)] + recipient: AccountId, + /// Amount of target tokens to send in target chain base currency units. + #[structopt(long)] + amount: bp_rialto::Balance, + }, + /// A call to the Millau Bridge Message Lane pallet to send a message over the bridge. + MillauSendMessage { + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. + #[structopt(long)] + payload: HexBytes, + /// Declared delivery and dispatch fee in base source-chain currency units. + #[structopt(long)] + fee: bp_rialto::Balance, + }, +} + +/// All possible messages that may be delivered to the Millau chain. +#[derive(StructOpt, Debug)] +pub enum ToMillauMessage { + /// Raw bytes for the message + Raw { + /// Raw, SCALE-encoded message + data: HexBytes, + }, + /// Make an on-chain remark (comment). + Remark { + /// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark. + #[structopt(long)] + remark_size: Option>, + }, + /// Transfer the specified `amount` of native tokens to a particular `recipient`. + Transfer { + /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) + #[structopt(long)] + recipient: AccountId, + /// Amount of target tokens to send in target chain base currency units. + #[structopt(long)] + amount: bp_millau::Balance, + }, + /// A call to the Rialto Bridge Message Lane pallet to send a message over the bridge. + RialtoSendMessage { + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. + #[structopt(long)] + payload: HexBytes, + /// Declared delivery and dispatch fee in base source-chain currency units. + #[structopt(long)] + fee: bp_millau::Balance, + }, +} + +declare_chain_options!(Rialto, rialto); +declare_chain_options!(Millau, millau); diff --git a/relays/substrate/src/millau_headers_to_rialto.rs b/relays/substrate/src/rialto_millau/millau_headers_to_rialto.rs similarity index 95% rename from relays/substrate/src/millau_headers_to_rialto.rs rename to relays/substrate/src/rialto_millau/millau_headers_to_rialto.rs index f84eee03a9fd0..de03fead20144 100644 --- a/relays/substrate/src/millau_headers_to_rialto.rs +++ b/relays/substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -16,10 +16,8 @@ //! Millau-to-Rialto headers sync entrypoint. -use crate::{ - finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}, - MillauClient, RialtoClient, -}; +use super::{MillauClient, RialtoClient}; +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use async_trait::async_trait; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; diff --git a/relays/substrate/src/millau_messages_to_rialto.rs b/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs similarity index 99% rename from relays/substrate/src/millau_messages_to_rialto.rs rename to relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs index f3dfdadf9a38d..84664e4572bba 100644 --- a/relays/substrate/src/millau_messages_to_rialto.rs +++ b/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -16,10 +16,10 @@ //! Millau-to-Rialto messages sync entrypoint. +use super::{MillauClient, RialtoClient}; use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; -use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; diff --git a/relays/substrate/src/rialto_millau/mod.rs b/relays/substrate/src/rialto_millau/mod.rs new file mode 100644 index 0000000000000..756a034974565 --- /dev/null +++ b/relays/substrate/src/rialto_millau/mod.rs @@ -0,0 +1,922 @@ +// Copyright 2019-2020 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 . + +//! Rialto <> Millau Bridge commands. + +pub mod cli; +pub mod millau_headers_to_rialto; +pub mod millau_messages_to_rialto; +pub mod rialto_headers_to_millau; +pub mod rialto_messages_to_millau; + +/// Millau node client. +pub type MillauClient = relay_substrate_client::Client; +/// Rialto node client. +pub type RialtoClient = relay_substrate_client::Client; + +use crate::cli::{ExplicitOrMaximal, HexBytes, Origins}; +use codec::{Decode, Encode}; +use frame_support::weights::{GetDispatchInfo, Weight}; +use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; +use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; +use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; +use sp_core::{Bytes, Pair}; +use sp_runtime::traits::IdentifyAccount; +use std::fmt::Debug; + +async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { + match command { + cli::InitBridge::MillauToRialto { + millau, + rialto, + rialto_sign, + millau_bridge_params, + } => { + let millau_client = millau.into_client().await?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + + let rialto_signer_next_index = rialto_client + .next_account_index(rialto_sign.signer.public().into()) + .await?; + + crate::headers_initialize::initialize( + millau_client, + rialto_client.clone(), + millau_bridge_params.millau_initial_header, + millau_bridge_params.millau_initial_authorities, + millau_bridge_params.millau_initial_authorities_set_id, + move |initialization_data| { + Ok(Bytes( + Rialto::sign_transaction( + *rialto_client.genesis_hash(), + &rialto_sign.signer, + rialto_signer_next_index, + rialto_runtime::SudoCall::sudo(Box::new( + rialto_runtime::FinalityBridgeMillauCall::initialize(initialization_data).into(), + )) + .into(), + ) + .encode(), + )) + }, + ) + .await; + } + cli::InitBridge::RialtoToMillau { + rialto, + millau, + millau_sign, + rialto_bridge_params, + } => { + let rialto_client = rialto.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let millau_signer_next_index = millau_client + .next_account_index(millau_sign.signer.public().into()) + .await?; + + crate::headers_initialize::initialize( + rialto_client, + millau_client.clone(), + rialto_bridge_params.rialto_initial_header, + rialto_bridge_params.rialto_initial_authorities, + rialto_bridge_params.rialto_initial_authorities_set_id, + move |initialization_data| { + Ok(Bytes( + Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + millau_signer_next_index, + millau_runtime::SudoCall::sudo(Box::new( + millau_runtime::FinalityBridgeRialtoCall::initialize(initialization_data).into(), + )) + .into(), + ) + .encode(), + )) + }, + ) + .await; + } + } + Ok(()) +} + +async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { + match command { + cli::RelayHeaders::MillauToRialto { + millau, + rialto, + rialto_sign, + prometheus_params, + } => { + let millau_client = millau.into_client().await?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; + } + cli::RelayHeaders::RialtoToMillau { + rialto, + millau, + millau_sign, + prometheus_params, + } => { + let rialto_client = rialto.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; + } + } + Ok(()) +} + +async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { + match command { + cli::RelayMessages::MillauToRialto { + millau, + millau_sign, + rialto, + rialto_sign, + prometheus_params, + lane, + } => { + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + + millau_messages_to_rialto::run( + millau_client, + millau_sign, + rialto_client, + rialto_sign, + lane.into(), + prometheus_params.into(), + ); + } + cli::RelayMessages::RialtoToMillau { + rialto, + rialto_sign, + millau, + millau_sign, + prometheus_params, + lane, + } => { + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + + rialto_messages_to_millau::run( + rialto_client, + rialto_sign, + millau_client, + millau_sign, + lane.into(), + prometheus_params.into(), + ); + } + } + Ok(()) +} + +async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { + match command { + cli::SendMessage::MillauToRialto { + millau, + millau_sign, + rialto_sign, + lane, + message, + dispatch_weight, + fee, + origin, + .. + } => { + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let rialto_sign = rialto_sign.parse()?; + let rialto_call = message.into_call()?; + + let payload = + millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin, dispatch_weight); + let dispatch_weight = payload.weight; + + let lane = lane.into(); + let fee = get_fee(fee, || { + estimate_message_delivery_and_dispatch_fee( + &millau_client, + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) + }) + .await?; + + let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( + millau_runtime::MessageLaneCall::send_message(lane, payload, fee), + ); + + let signed_millau_call = Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + millau_client + .next_account_index(millau_sign.signer.public().clone().into()) + .await?, + millau_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}", + signed_millau_call.len(), + dispatch_weight, + fee, + ); + log::info!(target: "bridge", "Signed Millau Call: {:?}", HexBytes::encode(&signed_millau_call)); + + millau_client.submit_extrinsic(Bytes(signed_millau_call)).await?; + } + cli::SendMessage::RialtoToMillau { + rialto, + rialto_sign, + millau_sign, + lane, + message, + dispatch_weight, + fee, + origin, + .. + } => { + let rialto_client = rialto.into_client().await?; + let rialto_sign = rialto_sign.parse()?; + let millau_sign = millau_sign.parse()?; + let millau_call = message.into_call()?; + + let payload = + rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin, dispatch_weight); + let dispatch_weight = payload.weight; + + let lane = lane.into(); + let fee = get_fee(fee, || { + estimate_message_delivery_and_dispatch_fee( + &rialto_client, + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) + }) + .await?; + + let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( + rialto_runtime::MessageLaneCall::send_message(lane, payload, fee), + ); + + let signed_rialto_call = Rialto::sign_transaction( + *rialto_client.genesis_hash(), + &rialto_sign.signer, + rialto_client + .next_account_index(rialto_sign.signer.public().clone().into()) + .await?, + rialto_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}", + signed_rialto_call.len(), + dispatch_weight, + fee, + ); + log::info!(target: "bridge", "Signed Rialto Call: {:?}", HexBytes::encode(&signed_rialto_call)); + + rialto_client.submit_extrinsic(Bytes(signed_rialto_call)).await?; + } + } + Ok(()) +} + +async fn run_encode_call(call: cli::EncodeCall) -> Result<(), String> { + match call { + cli::EncodeCall::Rialto { call } => { + let call = call.into_call()?; + + println!("{:?}", HexBytes::encode(&call)); + } + cli::EncodeCall::Millau { call } => { + let call = call.into_call()?; + println!("{:?}", HexBytes::encode(&call)); + } + } + Ok(()) +} + +async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<(), String> { + match call { + cli::EncodeMessagePayload::RialtoToMillau { payload } => { + let payload = payload.into_payload()?; + + println!("{:?}", HexBytes::encode(&payload)); + } + cli::EncodeMessagePayload::MillauToRialto { payload } => { + let payload = payload.into_payload()?; + + println!("{:?}", HexBytes::encode(&payload)); + } + } + Ok(()) +} + +async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { + match cmd { + cli::EstimateFee::RialtoToMillau { rialto, lane, payload } => { + let client = rialto.into_client().await?; + let lane = lane.into(); + let payload = payload.into_payload()?; + + let fee: Option = estimate_message_delivery_and_dispatch_fee( + &client, + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; + + println!("Fee: {:?}", fee); + } + cli::EstimateFee::MillauToRialto { millau, lane, payload } => { + let client = millau.into_client().await?; + let lane = lane.into(); + let payload = payload.into_payload()?; + + let fee: Option = estimate_message_delivery_and_dispatch_fee( + &client, + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; + + println!("Fee: {:?}", fee); + } + } + + Ok(()) +} + +async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { + match cmd { + cli::DeriveAccount::RialtoToMillau { account } => { + let account = account.into_rialto(); + let acc = bp_runtime::SourceAccount::Account(account.clone()); + let id = bp_millau::derive_account_from_rialto_id(acc); + println!( + "{} (Rialto)\n\nCorresponding (derived) account id:\n-> {} (Millau)", + account, id + ) + } + cli::DeriveAccount::MillauToRialto { account } => { + let account = account.into_millau(); + let acc = bp_runtime::SourceAccount::Account(account.clone()); + let id = bp_rialto::derive_account_from_millau_id(acc); + println!( + "{} (Millau)\n\nCorresponding (derived) account id:\n-> {} (Rialto)", + account, id + ) + } + } + + Ok(()) +} + +async fn estimate_message_delivery_and_dispatch_fee( + client: &relay_substrate_client::Client, + estimate_fee_method: &str, + lane: bp_message_lane::LaneId, + payload: P, +) -> Result, relay_substrate_client::Error> { + let encoded_response = client + .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .await?; + let decoded_response: Option = + Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?; + Ok(decoded_response) +} + +fn remark_payload(remark_size: Option>, maximal_allowed_size: u32) -> Vec { + match remark_size { + Some(ExplicitOrMaximal::Explicit(remark_size)) => vec![0; remark_size], + Some(ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], + None => format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec(), + } +} + +fn message_payload( + spec_version: u32, + weight: Weight, + origin: CallOrigin, + call: &impl Encode, +) -> MessagePayload> +where + SAccountId: Encode + Debug, + TPublic: Encode + Debug, + TSignature: Encode + Debug, +{ + // Display nicely formatted call. + let payload = MessagePayload { + spec_version, + weight, + origin, + call: HexBytes::encode(call), + }; + + log::info!(target: "bridge", "Created Message Payload: {:#?}", payload); + log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); + + // re-pack to return `Vec` + let MessagePayload { + spec_version, + weight, + origin, + call, + } = payload; + MessagePayload { + spec_version, + weight, + origin, + call: call.0, + } +} + +fn rialto_to_millau_message_payload( + rialto_sign: &RialtoSigningParams, + millau_sign: &MillauSigningParams, + millau_call: &millau_runtime::Call, + origin: Origins, + user_specified_dispatch_weight: Option>, +) -> rialto_runtime::millau_messages::ToMillauMessagePayload { + let millau_call_weight = prepare_call_dispatch_weight( + user_specified_dispatch_weight, + ExplicitOrMaximal::Explicit(millau_call.get_dispatch_info().weight), + compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()), + ); + let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); + let millau_origin_public = millau_sign.signer.public(); + + message_payload( + millau_runtime::VERSION.spec_version, + millau_call_weight, + match origin { + Origins::Source => CallOrigin::SourceAccount(rialto_account_id), + Origins::Target => { + let digest = rialto_runtime::millau_account_ownership_digest( + &millau_call, + rialto_account_id.clone(), + millau_runtime::VERSION.spec_version, + ); + + let digest_signature = millau_sign.signer.sign(&digest); + + CallOrigin::TargetAccount(rialto_account_id, millau_origin_public.into(), digest_signature.into()) + } + }, + &millau_call, + ) +} + +fn millau_to_rialto_message_payload( + millau_sign: &MillauSigningParams, + rialto_sign: &RialtoSigningParams, + rialto_call: &rialto_runtime::Call, + origin: Origins, + user_specified_dispatch_weight: Option>, +) -> millau_runtime::rialto_messages::ToRialtoMessagePayload { + let rialto_call_weight = prepare_call_dispatch_weight( + user_specified_dispatch_weight, + ExplicitOrMaximal::Explicit(rialto_call.get_dispatch_info().weight), + compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), + ); + let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); + let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); + let rialto_origin_public = rialto_sign.signer.public(); + + message_payload( + rialto_runtime::VERSION.spec_version, + rialto_call_weight, + match origin { + Origins::Source => CallOrigin::SourceAccount(millau_account_id), + Origins::Target => { + let digest = millau_runtime::rialto_account_ownership_digest( + &rialto_call, + millau_account_id.clone(), + rialto_runtime::VERSION.spec_version, + ); + + let digest_signature = rialto_sign.signer.sign(&digest); + + CallOrigin::TargetAccount(millau_account_id, rialto_origin_public.into(), digest_signature.into()) + } + }, + &rialto_call, + ) +} + +fn prepare_call_dispatch_weight( + user_specified_dispatch_weight: Option>, + weight_from_pre_dispatch_call: ExplicitOrMaximal, + maximal_allowed_weight: Weight, +) -> Weight { + match user_specified_dispatch_weight.unwrap_or(weight_from_pre_dispatch_call) { + ExplicitOrMaximal::Explicit(weight) => weight, + ExplicitOrMaximal::Maximal => maximal_allowed_weight, + } +} + +async fn get_fee(fee: Option, f: F) -> Result +where + Fee: Decode, + F: FnOnce() -> R, + R: std::future::Future, E>>, + E: Debug, +{ + match fee { + Some(fee) => Ok(fee), + None => match f().await { + Ok(Some(fee)) => Ok(fee), + Ok(None) => Err("Failed to estimate message fee. Message is too heavy?".into()), + Err(error) => Err(format!("Failed to estimate message fee: {:?}", error)), + }, + } +} + +fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { + bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) +} + +fn compute_maximal_message_arguments_size( + maximal_source_extrinsic_size: u32, + maximal_target_extrinsic_size: u32, +) -> u32 { + // assume that both signed extensions and other arguments fit 1KB + let service_tx_bytes_on_source_chain = 1024; + let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; + let maximal_call_size = + bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size); + let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { + maximal_source_extrinsic_size + } else { + maximal_call_size + }; + + // bytes in Call encoding that are used to encode everything except arguments + let service_bytes = 1 + 1 + 4; + maximal_call_size - service_bytes +} + +impl cli::MillauToRialtoMessagePayload { + /// Parse the CLI parameters and construct message payload. + pub fn into_payload( + self, + ) -> Result>, String> { + match self { + Self::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), + Self::Message { message, sender } => { + let spec_version = rialto_runtime::VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.into_millau()); + let call = message.into_call()?; + let weight = call.get_dispatch_info().weight; + + Ok(message_payload(spec_version, weight, origin, &call)) + } + } + } +} + +impl cli::RialtoToMillauMessagePayload { + /// Parse the CLI parameters and construct message payload. + pub fn into_payload( + self, + ) -> Result>, String> { + match self { + Self::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), + Self::Message { message, sender } => { + let spec_version = millau_runtime::VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.into_rialto()); + let call = message.into_call()?; + let weight = call.get_dispatch_info().weight; + + Ok(message_payload(spec_version, weight, origin, &call)) + } + } + } +} + +impl cli::RialtoSigningParams { + /// Parse CLI parameters into typed signing params. + pub fn parse(self) -> Result { + RialtoSigningParams::from_suri(&self.rialto_signer, self.rialto_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e)) + } +} + +impl cli::MillauSigningParams { + /// Parse CLI parameters into typed signing params. + pub fn parse(self) -> Result { + MillauSigningParams::from_suri(&self.millau_signer, self.millau_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse millau-signer: {:?}", e)) + } +} + +impl cli::MillauConnectionParams { + /// Convert CLI connection parameters into Millau RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + MillauClient::new(ConnectionParams { + host: self.millau_host, + port: self.millau_port, + }) + .await + } +} +impl cli::RialtoConnectionParams { + /// Convert CLI connection parameters into Rialto RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + RialtoClient::new(ConnectionParams { + host: self.rialto_host, + port: self.rialto_port, + }) + .await + } +} + +impl cli::ToRialtoMessage { + /// Convert CLI call request into runtime `Call` instance. + pub fn into_call(self) -> Result { + let call = match self { + cli::ToRialtoMessage::Raw { data } => { + Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? + } + cli::ToRialtoMessage::Remark { remark_size } => { + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload( + remark_size, + compute_maximal_message_arguments_size( + bp_millau::max_extrinsic_size(), + bp_rialto::max_extrinsic_size(), + ), + ))) + } + cli::ToRialtoMessage::Transfer { recipient, amount } => { + let recipient = recipient.into_rialto(); + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) + } + cli::ToRialtoMessage::MillauSendMessage { lane, payload, fee } => { + let payload = cli::RialtoToMillauMessagePayload::Raw { data: payload }.into_payload()?; + let lane = lane.into(); + rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( + lane, payload, fee, + )) + } + }; + + log::info!(target: "bridge", "Generated Rialto call: {:#?}", call); + log::info!(target: "bridge", "Weight of Rialto call: {}", call.get_dispatch_info().weight); + log::info!(target: "bridge", "Encoded Rialto call: {:?}", HexBytes::encode(&call)); + + Ok(call) + } +} + +impl cli::ToMillauMessage { + /// Convert CLI call request into runtime `Call` instance. + pub fn into_call(self) -> Result { + let call = match self { + cli::ToMillauMessage::Raw { data } => { + Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? + } + cli::ToMillauMessage::Remark { remark_size } => { + millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( + remark_size, + compute_maximal_message_arguments_size( + bp_rialto::max_extrinsic_size(), + bp_millau::max_extrinsic_size(), + ), + ))) + } + cli::ToMillauMessage::Transfer { recipient, amount } => { + let recipient = recipient.into_millau(); + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) + } + cli::ToMillauMessage::RialtoSendMessage { lane, payload, fee } => { + let payload = cli::MillauToRialtoMessagePayload::Raw { data: payload }.into_payload()?; + let lane = lane.into(); + millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( + lane, payload, fee, + )) + } + }; + + log::info!(target: "bridge", "Generated Millau call: {:#?}", call); + log::info!(target: "bridge", "Weight of Millau call: {}", call.get_dispatch_info().weight); + log::info!(target: "bridge", "Encoded Millau call: {:?}", HexBytes::encode(&call)); + + Ok(call) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_message_lane::source_chain::TargetHeaderChain; + use sp_core::Pair; + use sp_runtime::traits::{IdentifyAccount, Verify}; + + #[test] + fn millau_signature_is_valid_on_rialto() { + let millau_sign = relay_millau_client::SigningParams::from_suri("//Dave", None).unwrap(); + + let call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); + + let millau_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); + let millau_account_id: bp_millau::AccountId = millau_public.into_account(); + + let digest = millau_runtime::rialto_account_ownership_digest( + &call, + millau_account_id, + rialto_runtime::VERSION.spec_version, + ); + + let rialto_signer = relay_rialto_client::SigningParams::from_suri("//Dave", None).unwrap(); + let signature = rialto_signer.signer.sign(&digest); + + assert!(signature.verify(&digest[..], &rialto_signer.signer.public())); + } + + #[test] + fn rialto_signature_is_valid_on_millau() { + let rialto_sign = relay_rialto_client::SigningParams::from_suri("//Dave", None).unwrap(); + + let call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); + + let rialto_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); + + let digest = rialto_runtime::millau_account_ownership_digest( + &call, + rialto_account_id, + millau_runtime::VERSION.spec_version, + ); + + let millau_signer = relay_millau_client::SigningParams::from_suri("//Dave", None).unwrap(); + let signature = millau_signer.signer.sign(&digest); + + assert!(signature.verify(&digest[..], &millau_signer.signer.public())); + } + + #[test] + fn maximal_rialto_to_millau_message_arguments_size_is_computed_correctly() { + use rialto_runtime::millau_messages::Millau; + + let maximal_remark_size = + compute_maximal_message_arguments_size(bp_rialto::max_extrinsic_size(), bp_millau::max_extrinsic_size()); + + let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); + let payload = message_payload( + Default::default(), + call.get_dispatch_info().weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); + assert_eq!(Millau::verify_message(&payload), Ok(())); + + let call: millau_runtime::Call = + millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into(); + let payload = message_payload( + Default::default(), + call.get_dispatch_info().weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); + assert!(Millau::verify_message(&payload).is_err()); + } + + #[test] + fn maximal_size_remark_to_rialto_is_generated_correctly() { + assert!( + bridge_runtime_common::messages::target::maximal_incoming_message_size( + bp_rialto::max_extrinsic_size() + ) > bp_millau::max_extrinsic_size(), + "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", + ) + } + + #[test] + fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() { + use rialto_runtime::millau_messages::Millau; + + let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); + let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); + + let payload = message_payload( + Default::default(), + maximal_dispatch_weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); + assert_eq!(Millau::verify_message(&payload), Ok(())); + + let payload = message_payload( + Default::default(), + maximal_dispatch_weight + 1, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); + assert!(Millau::verify_message(&payload).is_err()); + } + + #[test] + fn maximal_weight_fill_block_to_rialto_is_generated_correctly() { + use millau_runtime::rialto_messages::Rialto; + + let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); + let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); + + let payload = message_payload( + Default::default(), + maximal_dispatch_weight, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); + assert_eq!(Rialto::verify_message(&payload), Ok(())); + + let payload = message_payload( + Default::default(), + maximal_dispatch_weight + 1, + pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + &call, + ); + assert!(Rialto::verify_message(&payload).is_err()); + } + + #[test] + fn rialto_tx_extra_bytes_constant_is_correct() { + let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); + let rialto_tx = Rialto::sign_transaction( + Default::default(), + &sp_keyring::AccountKeyring::Alice.pair(), + 0, + rialto_call.clone(), + ); + let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); + assert!( + bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, + "Hardcoded number of extra bytes in Rialto transaction {} is lower than actual value: {}", + bp_rialto::TX_EXTRA_BYTES, + extra_bytes_in_transaction, + ); + } + + #[test] + fn millau_tx_extra_bytes_constant_is_correct() { + let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); + let millau_tx = Millau::sign_transaction( + Default::default(), + &sp_keyring::AccountKeyring::Alice.pair(), + 0, + millau_call.clone(), + ); + let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); + assert!( + bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, + "Hardcoded number of extra bytes in Millau transaction {} is lower than actual value: {}", + bp_millau::TX_EXTRA_BYTES, + extra_bytes_in_transaction, + ); + } +} diff --git a/relays/substrate/src/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs similarity index 95% rename from relays/substrate/src/rialto_headers_to_millau.rs rename to relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs index 5a9bbb12133a2..7e9b855afd183 100644 --- a/relays/substrate/src/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -16,10 +16,8 @@ //! Rialto-to-Millau headers sync entrypoint. -use crate::{ - finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}, - MillauClient, RialtoClient, -}; +use super::{MillauClient, RialtoClient}; +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use async_trait::async_trait; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; diff --git a/relays/substrate/src/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs similarity index 99% rename from relays/substrate/src/rialto_messages_to_millau.rs rename to relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs index 96211bd944f64..3083ce3cbf5d4 100644 --- a/relays/substrate/src/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -16,10 +16,10 @@ //! Rialto-to-Millau messages sync entrypoint. +use super::{MillauClient, RialtoClient}; use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; -use crate::{MillauClient, RialtoClient}; use async_trait::async_trait; use bp_message_lane::{LaneId, MessageNonce}; From 43c6afb26fe3aa89e1e2a38e7830841ed7b4eca1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 15 Mar 2021 14:53:52 +0300 Subject: [PATCH 0379/1210] Added some ML-related constants for polkadot-like chains (#822) * added some ML-related constants for polkadot-like chains * comment --- primitives/polkadot-core/src/lib.rs | 114 +++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 78a9fe8480c4d..f56d4c52aa789 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -18,18 +18,111 @@ use bp_message_lane::MessageNonce; use bp_runtime::Chain; -use frame_support::RuntimeDebug; +use frame_support::{ + parameter_types, + weights::{ + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, + DispatchClass, Weight, + }, + RuntimeDebug, +}; +use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ generic, traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, + MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, Perbill, }; // Re-export's to avoid extra substrate dependencies in chain-specific crates. pub use frame_support::Parameter; pub use sp_runtime::traits::Convert; +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// Polkadot-like chain. This mostly depends on number of entries in the storage trie. +/// Some reserve is reserved to account future chain growth. +/// +/// To compute this value, we've synced Kusama chain blocks [0; 6545733] to see if there were +/// any significant changes of the storage proof size (NO): +/// +/// - at block 3072 the storage proof size overhead was 579 bytes; +/// - at block 2479616 it was 578 bytes; +/// - at block 4118528 it was 711 bytes; +/// - at block 6540800 it was 779 bytes. +/// +/// The number of storage entries at the block 6546170 was 351207 and number of trie nodes in +/// the storage proof was 5 (log(16, 351207) ~ 4.6). +/// +/// So the assumption is that the storage proof size overhead won't be larger than 1024 in the +/// nearest future. If it'll ever break this barrier, then we'll need to update this constant +/// at next runtime upgrade. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. +/// +/// All polkadot-like chains are using same crypto. +pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; + +/// All Polkadot-like chains allow normal extrinsics to fill block up to 75%. +/// +/// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +/// All Polkadot-like chains allow 2 seconds of compute with a 6 second average block time. +/// +/// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; + +/// All Polkadot-like chains assume that an on-initialize consumes 1% of the weight on average, +/// hence a single extrinsic will not be allowed to consume more than `AvailableBlockRatio - 1%`. +/// +/// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(1); + +parameter_types! { + /// All Polkadot-like chains have maximal block size set to 5MB. + /// + /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. + pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio( + 5 * 1024 * 1024, + NORMAL_DISPATCH_RATIO, + ); + /// All Polkadot-like chains have the same block weights. + /// + /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have an extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT, + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); +} + +/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can use. +pub fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) +} + +/// Get the maximum length in bytes that a Normal extrinsic on the Polkadot-like chain requires. +pub fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) +} + // TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; @@ -94,3 +187,20 @@ impl Convert for AccountIdConverter { hash.to_fixed_bytes().into() } } + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::codec::Encode; + + #[test] + fn maximal_encoded_account_id_size_is_correct() { + let actual_size = AccountId::default().encode().len(); + assert!( + actual_size <= MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize, + "Actual size of encoded account id for Polkadot-like chains ({}) is larger than expected {}", + actual_size, + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + ); + } +} From c5a94f5052e98dad0c8a8ee2bbad3ab4d0bc9539 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 15 Mar 2021 18:11:56 +0300 Subject: [PATCH 0380/1210] Make finality verifier pallet instantiable (#825) * make finality verifier pallet instantiable * try to fix benchmarks * fix benchmarks compilation --- bin/rialto/runtime/src/lib.rs | 4 +- .../src/messages_benchmarking.rs | 14 +- modules/finality-verifier/src/lib.rs | 168 +++++++++--------- modules/finality-verifier/src/mock.rs | 6 +- 4 files changed, 99 insertions(+), 93 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0c9a97318515d..0674965da50cf 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -953,7 +953,7 @@ impl_runtime_apis! { Default::default(), ); - prepare_message_proof::( + prepare_message_proof::( params, make_millau_message_key, make_millau_outbound_lane_data_key, @@ -986,7 +986,7 @@ impl_runtime_apis! { }; use sp_runtime::traits::Header; - prepare_message_delivery_proof::( + prepare_message_delivery_proof::( params, |lane_id| pallet_message_lane::storage_keys::inbound_lane_data_key::< Runtime, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 73bdd5755f068..56b427cb0e67f 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -62,7 +62,7 @@ pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode) } /// Prepare proof of messages for the `receive_messages_proof` call. -pub fn prepare_message_proof( +pub fn prepare_message_proof( params: MessageProofParams, make_bridged_message_storage_key: MM, make_bridged_outbound_lane_data_key: ML, @@ -73,7 +73,8 @@ pub fn prepare_message_proof( where B: MessageBridge, H: Hasher, - R: pallet_finality_verifier::Config, + R: pallet_finality_verifier::Config, + FI: 'static, ::Hash: Into>>, MM: Fn(MessageKey) -> Vec, ML: Fn(LaneId) -> Vec, @@ -129,7 +130,7 @@ where // prepare Bridged chain header and insert it into the Substrate pallet let bridged_header = make_bridged_header(root); let bridged_header_hash = bridged_header.hash(); - pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); + pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); ( FromBridgedChainMessagesProof { @@ -146,7 +147,7 @@ where } /// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. -pub fn prepare_message_delivery_proof( +pub fn prepare_message_delivery_proof( params: MessageDeliveryProofParams>>, make_bridged_inbound_lane_data_key: ML, make_bridged_header: MH, @@ -154,7 +155,8 @@ pub fn prepare_message_delivery_proof( where B: MessageBridge, H: Hasher, - R: pallet_finality_verifier::Config, + R: pallet_finality_verifier::Config, + FI: 'static, ::Hash: Into>>, ML: Fn(LaneId) -> Vec, MH: Fn(H::Out) -> ::Header, @@ -181,7 +183,7 @@ where // prepare Bridged chain header and insert it into the Substrate pallet let bridged_header = make_bridged_header(root); let bridged_header_hash = bridged_header.hash(); - pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); + pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index a072fc537b801..8127daba3eb5f 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -55,13 +55,13 @@ mod mock; pub use pallet::*; /// Block number of the bridged chain. -pub type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; +pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; /// Block hash of the bridged chain. -pub type BridgedBlockHash = HashOf<::BridgedChain>; +pub type BridgedBlockHash = HashOf<>::BridgedChain>; /// Hasher of the bridged chain. -pub type BridgedBlockHasher = HasherOf<::BridgedChain>; +pub type BridgedBlockHasher = HasherOf<>::BridgedChain>; /// Header of the bridged chain. -pub type BridgedHeader = HeaderOf<::BridgedChain>; +pub type BridgedHeader = HeaderOf<>::BridgedChain>; #[frame_support::pallet] pub mod pallet { @@ -70,7 +70,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config { /// The chain we are bridging to here. type BridgedChain: Chain; @@ -85,12 +85,12 @@ pub mod pallet { } #[pallet::pallet] - pub struct Pallet(PhantomData); + pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] - impl Hooks> for Pallet { + impl, I: 'static> Hooks> for Pallet { fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { - >::mutate(|count| *count = count.saturating_sub(1)); + >::mutate(|count| *count = count.saturating_sub(1)); (0_u64) .saturating_add(T::DbWeight::get().reads(1)) @@ -99,7 +99,7 @@ pub mod pallet { } #[pallet::call] - impl Pallet { + impl, I: 'static> Pallet { /// Verify a target header is finalized according to the given finality proof. /// /// It will use the underlying storage pallet to fetch information about the current @@ -110,21 +110,21 @@ pub mod pallet { #[pallet::weight(0)] pub fn submit_finality_proof( origin: OriginFor, - finality_target: BridgedHeader, + finality_target: BridgedHeader, justification: Vec, ) -> DispatchResultWithPostInfo { - ensure_operational::()?; + ensure_operational::()?; let _ = ensure_signed(origin)?; ensure!( Self::request_count() < T::MaxRequests::get(), - >::TooManyRequests + >::TooManyRequests ); let (hash, number) = (finality_target.hash(), finality_target.number()); log::trace!("Going to try and finalize header {:?}", finality_target); - let best_finalized = >::get(>::get()).expect( + let best_finalized = >::get(>::get()).expect( "In order to reach this point the bridge must have been initialized. Afterwards, every time `BestFinalized` is updated `ImportedHeaders` is also updated. Therefore `ImportedHeaders` must contain an entry for `BestFinalized`.", @@ -132,14 +132,14 @@ pub mod pallet { // We do a quick check here to ensure that our header chain is making progress and isn't // "travelling back in time" (which could be indicative of something bad, e.g a hard-fork). - ensure!(best_finalized.number() < number, >::OldHeader); + ensure!(best_finalized.number() < number, >::OldHeader); - verify_justification::(&justification, hash, *number)?; + verify_justification::(&justification, hash, *number)?; - try_enact_authority_change::(&finality_target)?; - >::put(hash); - >::insert(hash, finality_target); - >::mutate(|count| *count += 1); + try_enact_authority_change::(&finality_target)?; + >::put(hash); + >::insert(hash, finality_target); + >::mutate(|count| *count += 1); log::info!("Succesfully imported finalized header with hash {:?}!", hash); @@ -158,13 +158,13 @@ pub mod pallet { #[pallet::weight((T::DbWeight::get().reads_writes(2, 5), DispatchClass::Operational))] pub fn initialize( origin: OriginFor, - init_data: super::InitializationData>, + init_data: super::InitializationData>, ) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; + ensure_owner_or_root::(origin)?; - let init_allowed = !>::exists(); - ensure!(init_allowed, >::AlreadyInitialized); - initialize_bridge::(init_data.clone()); + let init_allowed = !>::exists(); + ensure!(init_allowed, >::AlreadyInitialized); + initialize_bridge::(init_data.clone()); log::info!( "Pallet has been initialized with the following parameters: {:?}", @@ -179,14 +179,14 @@ pub mod pallet { /// May only be called either by root, or by `ModuleOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; + ensure_owner_or_root::(origin)?; match new_owner { Some(new_owner) => { - ModuleOwner::::put(&new_owner); + ModuleOwner::::put(&new_owner); log::info!("Setting pallet Owner to: {:?}", new_owner); } None => { - ModuleOwner::::kill(); + ModuleOwner::::kill(); log::info!("Removed Owner of pallet."); } } @@ -199,8 +199,8 @@ pub mod pallet { /// May only be called either by root, or by `ModuleOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operational(origin: OriginFor, operational: bool) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; - >::put(operational); + ensure_owner_or_root::(origin)?; + >::put(operational); if operational { log::info!("Resuming pallet operations."); @@ -221,23 +221,25 @@ pub mod pallet { /// that the pallet can always make progress. #[pallet::storage] #[pallet::getter(fn request_count)] - pub(super) type RequestCount = StorageValue<_, u32, ValueQuery>; + pub(super) type RequestCount, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; /// Hash of the header used to bootstrap the pallet. #[pallet::storage] - pub(super) type InitialHash = StorageValue<_, BridgedBlockHash, ValueQuery>; + pub(super) type InitialHash, I: 'static = ()> = StorageValue<_, BridgedBlockHash, ValueQuery>; /// Hash of the best finalized header. #[pallet::storage] - pub(super) type BestFinalized = StorageValue<_, BridgedBlockHash, ValueQuery>; + pub(super) type BestFinalized, I: 'static = ()> = StorageValue<_, BridgedBlockHash, ValueQuery>; /// Headers which have been imported into the pallet. #[pallet::storage] - pub(super) type ImportedHeaders = StorageMap<_, Identity, BridgedBlockHash, BridgedHeader>; + pub(super) type ImportedHeaders, I: 'static = ()> = + StorageMap<_, Identity, BridgedBlockHash, BridgedHeader>; /// The current GRANDPA Authority set. #[pallet::storage] - pub(super) type CurrentAuthoritySet = StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>; + pub(super) type CurrentAuthoritySet, I: 'static = ()> = + StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>; /// Optional pallet owner. /// @@ -246,20 +248,20 @@ pub mod pallet { /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). #[pallet::storage] - pub(super) type ModuleOwner = StorageValue<_, T::AccountId, OptionQuery>; + pub(super) type ModuleOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; /// If true, all pallet transactions are failed immediately. #[pallet::storage] - pub(super) type IsHalted = StorageValue<_, bool, ValueQuery>; + pub(super) type IsHalted, I: 'static = ()> = StorageValue<_, bool, ValueQuery>; #[pallet::genesis_config] - pub struct GenesisConfig { + pub struct GenesisConfig, I: 'static = ()> { owner: Option, - init_data: Option>>, + init_data: Option>>, } #[cfg(feature = "std")] - impl Default for GenesisConfig { + impl, I: 'static> Default for GenesisConfig { fn default() -> Self { Self { owner: None, @@ -269,24 +271,24 @@ pub mod pallet { } #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { + impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { if let Some(ref owner) = self.owner { - >::put(owner); + >::put(owner); } if let Some(init_data) = self.init_data.clone() { - initialize_bridge::(init_data); + initialize_bridge::(init_data); } else { // Since the bridge hasn't been initialized we shouldn't allow anyone to perform // transactions. - >::put(true); + >::put(true); } } } #[pallet::error] - pub enum Error { + pub enum Error { /// The given justification is invalid for the given header. InvalidJustification, /// The authority set from the underlying header chain is invalid. @@ -314,20 +316,20 @@ pub mod pallet { /// /// This function does not support forced changes, or scheduled changes with delays /// since these types of changes are indicitive of abnormal behaviour from GRANDPA. - pub(crate) fn try_enact_authority_change( - header: &BridgedHeader, + pub(crate) fn try_enact_authority_change, I: 'static>( + header: &BridgedHeader, ) -> Result<(), sp_runtime::DispatchError> { // We don't support forced changes - at that point governance intervention is required. ensure!( super::find_forced_change(header).is_none(), - >::UnsupportedScheduledChange + >::UnsupportedScheduledChange ); if let Some(change) = super::find_scheduled_change(header) { // GRANDPA only includes a `delay` for forced changes, so this isn't valid. - ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); + ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); - let current_set_id = >::get().set_id; + let current_set_id = >::get().set_id; // TODO [#788]: Stop manually increasing the `set_id` here. let next_authorities = bp_header_chain::AuthoritySet { authorities: change.next_authorities, @@ -336,7 +338,7 @@ pub mod pallet { // Since our header schedules a change and we know the delay is 0, it must also enact // the change. - >::put(&next_authorities); + >::put(&next_authorities); log::info!( "Transitioned from authority set {} to {}! New authorities are: {:?}", @@ -352,22 +354,22 @@ pub mod pallet { /// Verify a GRANDPA justification (finality proof) for a given header. /// /// Will use the GRANDPA current authorities known to the pallet. - pub(crate) fn verify_justification( + pub(crate) fn verify_justification, I: 'static>( justification: &[u8], - hash: BridgedBlockHash, - number: BridgedBlockNumber, + hash: BridgedBlockHash, + number: BridgedBlockNumber, ) -> Result<(), sp_runtime::DispatchError> { use bp_header_chain::justification::verify_justification; - let authority_set = >::get(); - let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; + let authority_set = >::get(); + let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; let set_id = authority_set.set_id; Ok( - verify_justification::>((hash, number), set_id, voter_set, &justification).map_err( + verify_justification::>((hash, number), set_id, voter_set, &justification).map_err( |e| { log::error!("Received invalid justification for {:?}: {:?}", hash, e); - >::InvalidJustification + >::InvalidJustification }, )?, ) @@ -375,7 +377,9 @@ pub mod pallet { /// Since this writes to storage with no real checks this should only be used in functions that /// were called by a trusted origin. - pub(crate) fn initialize_bridge(init_params: super::InitializationData>) { + pub(crate) fn initialize_bridge, I: 'static>( + init_params: super::InitializationData>, + ) { let super::InitializationData { header, authority_list, @@ -384,44 +388,44 @@ pub mod pallet { } = init_params; let initial_hash = header.hash(); - >::put(initial_hash); - >::put(initial_hash); - >::insert(initial_hash, header); + >::put(initial_hash); + >::put(initial_hash); + >::insert(initial_hash, header); let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); - >::put(authority_set); + >::put(authority_set); - >::put(is_halted); + >::put(is_halted); } /// Ensure that the origin is either root, or `ModuleOwner`. - fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { + fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::get().as_ref() => Ok(()), + Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::get().as_ref() => Ok(()), _ => Err(BadOrigin), } } /// Ensure that the pallet is in operational mode (not halted). - fn ensure_operational() -> Result<(), Error> { - if >::get() { - Err(>::Halted) + fn ensure_operational, I: 'static>() -> Result<(), Error> { + if >::get() { + Err(>::Halted) } else { Ok(()) } } } -impl Pallet { +impl, I: 'static> Pallet { /// Get the best finalized header the pallet knows of. /// /// Returns a dummy header if there is no best header. This can only happen /// if the pallet has not been initialized yet. - pub fn best_finalized() -> BridgedHeader { - let hash = >::get(); - >::get(hash).unwrap_or_else(|| { - >::new( + pub fn best_finalized() -> BridgedHeader { + let hash = >::get(); + >::get(hash).unwrap_or_else(|| { + >::new( Default::default(), Default::default(), Default::default(), @@ -432,21 +436,21 @@ impl Pallet { } /// Check if a particular header is known to the bridge pallet. - pub fn is_known_header(hash: BridgedBlockHash) -> bool { - >::contains_key(hash) + pub fn is_known_header(hash: BridgedBlockHash) -> bool { + >::contains_key(hash) } /// Verify that the passed storage proof is valid, given it is crafted using /// known finalized header. If the proof is valid, then the `parse` callback /// is called and the function returns its result. pub fn parse_finalized_storage_proof( - hash: BridgedBlockHash, + hash: BridgedBlockHash, storage_proof: sp_trie::StorageProof, - parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, + parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, ) -> Result { - let header = >::get(hash).ok_or(Error::::UnknownHeader)?; + let header = >::get(hash).ok_or(Error::::UnknownHeader)?; let storage_proof_checker = bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) - .map_err(|_| Error::::StorageRootMismatch)?; + .map_err(|_| Error::::StorageRootMismatch)?; Ok(parse(storage_proof_checker)) } @@ -504,8 +508,8 @@ pub(crate) fn find_forced_change( /// (Re)initialize bridge with given header for using it in external benchmarks. #[cfg(feature = "runtime-benchmarks")] -pub fn initialize_for_benchmarks(header: BridgedHeader) { - initialize_bridge::(InitializationData { +pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader) { + initialize_bridge::(InitializationData { header, authority_list: Vec::new(), // we don't verify any proofs in external benchmarks set_id: 0, @@ -603,7 +607,7 @@ mod tests { run_test(|| { assert_eq!( BestFinalized::::get(), - BridgedBlockHash::::default() + BridgedBlockHash::::default() ); assert_eq!(Module::::best_finalized(), test_header(0)); diff --git a/modules/finality-verifier/src/mock.rs b/modules/finality-verifier/src/mock.rs index f80a374f3710f..59f658e53940c 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/finality-verifier/src/mock.rs @@ -26,9 +26,9 @@ use sp_runtime::{ }; pub type AccountId = u64; -pub type TestHeader = crate::BridgedHeader; -pub type TestNumber = crate::BridgedBlockNumber; -pub type TestHash = crate::BridgedBlockHash; +pub type TestHeader = crate::BridgedHeader; +pub type TestNumber = crate::BridgedBlockNumber; +pub type TestHash = crate::BridgedBlockHash; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; From 53223382aec8782cb8e30a6bf787bb970b49c3d8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 16 Mar 2021 10:09:02 +0300 Subject: [PATCH 0381/1210] Sync Westend to Millau (#824) * make finality verifier pallet instantiable * add second instance of finality verifier pallet to the Millau runtime * add Westend -> Millau headers relay * use wss to connect to public westend nodes * initialize with best_finalized_block * typo * Revert "initialize with best_finalized_block" This reverts commit 954ed2832372d67618abc1a06d47e66faa93f674. * pass VoterSet by ref * new bridge initialization code * loop upper bound * Polkadot -> Westend * fixed tests compilation * default-features * assert --- bin/millau/runtime/Cargo.toml | 2 + bin/millau/runtime/src/lib.rs | 26 +- modules/finality-verifier/src/lib.rs | 2 +- modules/substrate/src/verifier.rs | 2 +- primitives/chains/westend/src/lib.rs | 2 +- primitives/header-chain/src/justification.rs | 4 +- .../header-chain/tests/justification.rs | 12 +- relays/clients/substrate/src/client.rs | 7 +- relays/clients/substrate/src/lib.rs | 3 + relays/clients/westend/Cargo.toml | 25 ++ relays/clients/westend/src/lib.rs | 47 ++++ relays/substrate/Cargo.toml | 3 + relays/substrate/src/cli.rs | 17 +- relays/substrate/src/headers_initialize.rs | 224 +++++++++++++----- relays/substrate/src/rialto_millau/cli.rs | 23 +- relays/substrate/src/rialto_millau/mod.rs | 134 +++++++---- .../rialto_millau/rialto_headers_to_millau.rs | 9 +- .../westend_headers_to_millau.rs | 72 ++++++ 18 files changed, 476 insertions(+), 138 deletions(-) create mode 100644 relays/clients/westend/Cargo.toml create mode 100644 relays/clients/westend/src/lib.rs create mode 100644 relays/substrate/src/rialto_millau/westend_headers_to_millau.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 058598e5c1c01..92193b1153740 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -19,6 +19,7 @@ bp-message-lane = { path = "../../../primitives/message-lane", default-features bp-millau = { path = "../../../primitives/chains/millau", default-features = false } bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } +bp-westend = { path = "../../../primitives/chains/westend", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } @@ -66,6 +67,7 @@ std = [ "bp-millau/std", "bp-rialto/std", "bp-runtime/std", + "bp-westend/std", "bridge-runtime-common/std", "codec/std", "frame-executive/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8e0a2f3bd7d2b..87d5ab87143bd 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -63,6 +63,7 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_finality_verifier::Call as FinalityBridgeRialtoCall; +pub use pallet_finality_verifier::Call as FinalityBridgeWestendCall; pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_sudo::Call as SudoCall; @@ -312,11 +313,18 @@ parameter_types! { pub const MaxRequests: u32 = 50; } +pub type RialtoFinalityVerifierInstance = (); impl pallet_finality_verifier::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type MaxRequests = MaxRequests; } +pub type WestendFinalityVerifierInstance = pallet_finality_verifier::Instance1; +impl pallet_finality_verifier::Config for Runtime { + type BridgedChain = bp_westend::Westend; + type MaxRequests = MaxRequests; +} + impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { @@ -371,7 +379,8 @@ construct_runtime!( BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeRialtoMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, - BridgeFinalityVerifier: pallet_finality_verifier::{Module, Call}, + BridgeRialtoFinalityVerifier: pallet_finality_verifier::{Module, Call}, + BridgeWestendFinalityVerifier: pallet_finality_verifier::::{Module, Call}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, @@ -572,12 +581,23 @@ impl_runtime_apis! { impl bp_rialto::RialtoFinalityApi for Runtime { fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { - let header = BridgeFinalityVerifier::best_finalized(); + let header = BridgeRialtoFinalityVerifier::best_finalized(); (header.number, header.hash()) } fn is_known_header(hash: bp_rialto::Hash) -> bool { - BridgeFinalityVerifier::is_known_header(hash) + BridgeRialtoFinalityVerifier::is_known_header(hash) + } + } + + impl bp_westend::WestendFinalityApi for Runtime { + fn best_finalized() -> (bp_westend::BlockNumber, bp_westend::Hash) { + let header = BridgeWestendFinalityVerifier::best_finalized(); + (header.number, header.hash()) + } + + fn is_known_header(hash: bp_westend::Hash) -> bool { + BridgeWestendFinalityVerifier::is_known_header(hash) } } diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 8127daba3eb5f..0f450273a1143 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -366,7 +366,7 @@ pub mod pallet { let set_id = authority_set.set_id; Ok( - verify_justification::>((hash, number), set_id, voter_set, &justification).map_err( + verify_justification::>((hash, number), set_id, &voter_set, &justification).map_err( |e| { log::error!("Received invalid justification for {:?}: {:?}", hash, e); >::InvalidJustification diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 11d54fade7342..5ae3ed366b56b 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -236,7 +236,7 @@ where verify_justification::( (hash, *header.number()), current_authority_set.set_id, - voter_set, + &voter_set, &proof.0, ) .map_err(|_| FinalizationError::InvalidJustification)?; diff --git a/primitives/chains/westend/src/lib.rs b/primitives/chains/westend/src/lib.rs index a2345e3b76daa..5b43eeeae5277 100644 --- a/primitives/chains/westend/src/lib.rs +++ b/primitives/chains/westend/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, Weight, MessageNonce, UnrewardedRelayersState}; +use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use sp_std::prelude::*; pub use bp_polkadot_core::*; diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index fef9aedac90c8..67968258a5c5c 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -57,7 +57,7 @@ pub fn decode_justification_target( pub fn verify_justification( finalized_target: (Header::Hash, Header::Number), authorities_set_id: SetId, - authorities_set: VoterSet, + authorities_set: &VoterSet, raw_justification: &[u8], ) -> Result<(), Error> where @@ -76,7 +76,7 @@ where // signatures are valid. We'll check the validity of the signatures later since they're more // resource intensive to verify. let ancestry_chain = AncestryChain::new(&justification.votes_ancestries); - match finality_grandpa::validate_commit(&justification.commit, &authorities_set, &ancestry_chain) { + match finality_grandpa::validate_commit(&justification.commit, authorities_set, &ancestry_chain) { Ok(ref result) if result.ghost().is_some() => {} _ => return Err(Error::InvalidJustificationCommit), } diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 81bd83b1ad3b4..e71db25e41ee4 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -34,7 +34,7 @@ fn make_justification_for_header_1() -> GrandpaJustification { #[test] fn justification_with_invalid_encoding_rejected() { assert_eq!( - verify_justification::(header_id::(1), TEST_GRANDPA_SET_ID, voter_set(), &[],), + verify_justification::(header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), &[],), Err(Error::JustificationDecode), ); } @@ -45,7 +45,7 @@ fn justification_with_invalid_target_rejected() { verify_justification::( header_id::(2), TEST_GRANDPA_SET_ID, - voter_set(), + &voter_set(), &make_justification_for_header_1().encode(), ), Err(Error::InvalidJustificationTarget), @@ -61,7 +61,7 @@ fn justification_with_invalid_commit_rejected() { verify_justification::( header_id::(1), TEST_GRANDPA_SET_ID, - voter_set(), + &voter_set(), &justification.encode(), ), Err(Error::InvalidJustificationCommit), @@ -77,7 +77,7 @@ fn justification_with_invalid_authority_signature_rejected() { verify_justification::( header_id::(1), TEST_GRANDPA_SET_ID, - voter_set(), + &voter_set(), &justification.encode(), ), Err(Error::InvalidAuthoritySignature), @@ -93,7 +93,7 @@ fn justification_with_invalid_precommit_ancestry() { verify_justification::( header_id::(1), TEST_GRANDPA_SET_ID, - voter_set(), + &voter_set(), &justification.encode(), ), Err(Error::InvalidPrecommitAncestries), @@ -106,7 +106,7 @@ fn valid_justification_accepted() { verify_justification::( header_id::(1), TEST_GRANDPA_SET_ID, - voter_set(), + &voter_set(), &make_justification_for_header_1().encode(), ), Ok(()), diff --git a/relays/clients/substrate/src/client.rs b/relays/clients/substrate/src/client.rs index 813dda6940335..ec18e9ba23d5e 100644 --- a/relays/clients/substrate/src/client.rs +++ b/relays/clients/substrate/src/client.rs @@ -95,7 +95,12 @@ impl Client { /// Build client to use in connection. async fn build_client(params: ConnectionParams) -> Result { - let uri = format!("ws://{}:{}", params.host, params.port); + let uri = format!( + "{}://{}:{}", + if params.secure { "wss" } else { "ws" }, + params.host, + params.port, + ); let mut config = RpcConfig::with_url(&uri); config.max_subscription_capacity = MAX_SUBSCRIPTION_CAPACITY; let client = RpcClient::new(config).await?; diff --git a/relays/clients/substrate/src/lib.rs b/relays/clients/substrate/src/lib.rs index 6a21e3bffa207..d18189647fa36 100644 --- a/relays/clients/substrate/src/lib.rs +++ b/relays/clients/substrate/src/lib.rs @@ -44,6 +44,8 @@ pub struct ConnectionParams { pub host: String, /// Websocket server TCP port. pub port: u16, + /// Use secure websocket connection. + pub secure: bool, } impl Default for ConnectionParams { @@ -51,6 +53,7 @@ impl Default for ConnectionParams { ConnectionParams { host: "localhost".into(), port: 9944, + secure: false, } } } diff --git a/relays/clients/westend/Cargo.toml b/relays/clients/westend/Cargo.toml new file mode 100644 index 0000000000000..d5d56154f3522 --- /dev/null +++ b/relays/clients/westend/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "relay-westend-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0" } +headers-relay = { path = "../../generic/headers" } +relay-substrate-client = { path = "../substrate" } +relay-utils = { path = "../../generic/utils" } + +# Bridge dependencies + +bp-westend = { path = "../../../primitives/chains/westend" } + +# Substrate Dependencies + +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/clients/westend/src/lib.rs b/relays/clients/westend/src/lib.rs new file mode 100644 index 0000000000000..0abbbb100cf14 --- /dev/null +++ b/relays/clients/westend/src/lib.rs @@ -0,0 +1,47 @@ +// Copyright 2019-2020 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 . + +//! Types used to connect to the Westend chain. + +use relay_substrate_client::{Chain, ChainBase}; +use std::time::Duration; + +/// Westend header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Westend chain definition +#[derive(Debug, Clone, Copy)] +pub struct Westend; + +impl ChainBase for Westend { + type BlockNumber = bp_westend::BlockNumber; + type Hash = bp_westend::Hash; + type Hasher = bp_westend::Hasher; + type Header = bp_westend::Header; +} + +impl Chain for Westend { + const NAME: &'static str = "Westend"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type AccountId = bp_westend::AccountId; + type Index = bp_westend::Nonce; + type SignedBlock = bp_westend::SignedBlock; + type Call = (); +} + +/// Westend header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index d71cfa2f1e10f..e9e969930de02 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -26,7 +26,9 @@ bp-millau = { path = "../../primitives/chains/millau" } bp-polkadot = { path = "../../primitives/chains/polkadot" } bp-runtime = { path = "../../primitives/runtime" } bp-rialto = { path = "../../primitives/chains/rialto" } +bp-westend = { path = "../../primitives/chains/westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } +finality-grandpa = { version = "0.14.0" } finality-relay = { path = "../generic/finality" } headers-relay = { path = "../generic/headers" } messages-relay = { path = "../generic/messages" } @@ -39,6 +41,7 @@ relay-millau-client = { path = "../clients/millau" } relay-polkadot-client = { path = "../clients/polkadot" } relay-rialto-client = { path = "../clients/rialto" } relay-substrate-client = { path = "../clients/substrate" } +relay-westend-client = { path = "../clients/westend" } relay-utils = { path = "../generic/utils" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index bfe5f6f549229..a4296226e250e 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -396,6 +396,9 @@ macro_rules! declare_chain_options { #[doc = "Connect to " $chain " node websocket server at given port."] #[structopt(long)] pub [<$chain_prefix _port>]: u16, + #[doc = "Use secure websocket connection."] + #[structopt(long)] + pub [<$chain_prefix _secure>]: bool, } #[doc = $chain " signing params."] @@ -408,20 +411,6 @@ macro_rules! declare_chain_options { #[structopt(long)] pub [<$chain_prefix _signer_password>]: Option, } - - #[doc = $chain " headers bridge initialization params."] - #[derive(StructOpt)] - pub struct [<$chain BridgeInitializationParams>] { - #[doc = "Hex-encoded " $chain " header to initialize bridge with. If not specified, genesis header is used."] - #[structopt(long)] - pub [<$chain_prefix _initial_header>]: Option, - #[doc = "Hex-encoded " $chain " GRANDPA authorities set to initialize bridge with. If not specified, set from genesis block is used."] - #[structopt(long)] - pub [<$chain_prefix _initial_authorities>]: Option, - #[doc = "Id of the " $chain " GRANDPA authorities set to initialize bridge with. If not specified, zero is used."] - #[structopt(long)] - pub [<$chain_prefix _initial_authorities_set_id>]: Option, - } } }; } diff --git a/relays/substrate/src/headers_initialize.rs b/relays/substrate/src/headers_initialize.rs index 2386f28f1b1ac..0fb05ad4a982c 100644 --- a/relays/substrate/src/headers_initialize.rs +++ b/relays/substrate/src/headers_initialize.rs @@ -21,30 +21,26 @@ //! and authorities set from source to target chain. The headers sync starts //! with this header. +use bp_header_chain::{ + find_grandpa_authorities_scheduled_change, + justification::{decode_justification_target, verify_justification}, +}; use codec::Decode; +use finality_grandpa::voter_set::VoterSet; +use num_traits::{One, Zero}; use pallet_finality_verifier::InitializationData; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; -use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, SetId as GrandpaAuthoritiesSetId}; +use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; +use sp_runtime::traits::Header as HeaderT; /// Submit headers-bridge initialization transaction. pub async fn initialize( source_client: Client, target_client: Client, - raw_initial_header: Option, - raw_initial_authorities_set: Option, - initial_authorities_set_id: Option, prepare_initialize_transaction: impl FnOnce(InitializationData) -> Result, ) { - let result = do_initialize( - source_client, - target_client, - raw_initial_header, - raw_initial_authorities_set, - initial_authorities_set_id, - prepare_initialize_transaction, - ) - .await; + let result = do_initialize(source_client, target_client, prepare_initialize_transaction).await; match result { Ok(tx_hash) => log::info!( @@ -68,18 +64,17 @@ pub async fn initialize( async fn do_initialize( source_client: Client, target_client: Client, - raw_initial_header: Option, - raw_initial_authorities_set: Option, - initial_authorities_set_id: Option, prepare_initialize_transaction: impl FnOnce(InitializationData) -> Result, ) -> Result { - let initialization_data = prepare_initialization_data( - source_client, - raw_initial_header, - raw_initial_authorities_set, - initial_authorities_set_id, - ) - .await?; + let initialization_data = prepare_initialization_data(source_client).await?; + log::info!( + target: "bridge", + "Prepared initialization data for {}-headers bridge at {}: {:?}", + SourceChain::NAME, + TargetChain::NAME, + initialization_data, + ); + let initialization_tx = prepare_initialize_transaction(initialization_data)?; let initialization_tx_hash = target_client .submit_extrinsic(initialization_tx) @@ -88,50 +83,161 @@ async fn do_initialize( Ok(initialization_tx_hash) } -/// Prepare initialization data for the headers-bridge pallet. +/// Prepare initialization data for the finality-verifier pallet. async fn prepare_initialization_data( source_client: Client, - raw_initial_header: Option, - raw_initial_authorities_set: Option, - initial_authorities_set_id: Option, ) -> Result, String> { - let source_genesis_hash = *source_client.genesis_hash(); - - let initial_header = match raw_initial_header { - Some(raw_initial_header) => SourceChain::Header::decode(&mut &raw_initial_header.0[..]) - .map_err(|err| format!("Failed to decode {} initial header: {:?}", SourceChain::NAME, err))?, - None => source_client - .header_by_hash(source_genesis_hash) - .await - .map_err(|err| format!("Failed to retrive {} genesis header: {:?}", SourceChain::NAME, err))?, - }; - - let raw_initial_authorities_set = match raw_initial_authorities_set { - Some(raw_initial_authorities_set) => raw_initial_authorities_set.0, - None => source_client - .grandpa_authorities_set(source_genesis_hash) - .await - .map_err(|err| { - format!( - "Failed to retrive {} authorities set at genesis header: {:?}", - SourceChain::NAME, - err - ) - })?, - }; - let initial_authorities_set = - GrandpaAuthoritiesSet::decode(&mut &raw_initial_authorities_set[..]).map_err(|err| { - format!( - "Failed to decode {} initial authorities set: {:?}", + // In ideal world we just need to get best finalized header and then to read GRANDPA authorities + // set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at this header. + // + // But now there are problems with this approach - `CurrentSetId` may return invalid value. So here + // we're waiting for the next justification, read the authorities set and then try to figure out + // the set id with bruteforce. + let mut justifications = source_client + .subscribe_justifications() + .await + .map_err(|err| format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err))?; + + // Read next justification - the header that it finalizes will be used as initial header. + let justification = justifications.next().await.ok_or_else(|| { + format!( + "Failed to read {} justification from the stream: stream has ended unexpectedly", + SourceChain::NAME, + ) + })?; + + // Read initial header. + let (initial_header_hash, initial_header_number) = + decode_justification_target::(&justification.0) + .map_err(|err| format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err))?; + let initial_header = source_header(&source_client, initial_header_hash).await?; + log::trace!(target: "bridge", "Selected {} initial header: {}/{}", + SourceChain::NAME, + initial_header_number, + initial_header_hash, + ); + + // Read GRANDPA authorities set at initial header. + let initial_authorities_set = source_authorities_set(&source_client, initial_header_hash).await?; + log::trace!(target: "bridge", "Selected {} initial authorities set: {:?}", + SourceChain::NAME, + initial_authorities_set, + ); + + // If initial header changes the GRANDPA authorities set, then we need previous authorities + // to verify justification. + let mut authorities_for_verification = initial_authorities_set.clone(); + let scheduled_change = find_grandpa_authorities_scheduled_change(&initial_header); + assert!( + scheduled_change.as_ref().map(|c| c.delay.is_zero()).unwrap_or(true), + "GRANDPA authorities change at {} scheduled to happen in {:?} blocks. We expect\ + regular hange to have zero delay", + initial_header_hash, + scheduled_change.as_ref().map(|c| c.delay), + ); + let schedules_change = scheduled_change.is_some(); + if schedules_change { + authorities_for_verification = source_authorities_set(&source_client, *initial_header.parent_hash()).await?; + log::trace!( + target: "bridge", + "Selected {} header is scheduling GRANDPA authorities set changes. Using previous set: {:?}", + SourceChain::NAME, + authorities_for_verification, + ); + } + + // Now let's try to guess authorities set id by verifying justification. + let mut initial_authorities_set_id = 0; + let mut min_possible_block_number = SourceChain::BlockNumber::zero(); + let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()).ok_or_else(|| { + format!( + "Read invalid {} authorities set: {:?}", + SourceChain::NAME, + authorities_for_verification, + ) + })?; + loop { + log::trace!( + target: "bridge", "Trying {} GRANDPA authorities set id: {}", + SourceChain::NAME, + initial_authorities_set_id, + ); + + let is_valid_set_id = verify_justification::( + (initial_header_hash, initial_header_number), + initial_authorities_set_id, + &authorities_for_verification, + &justification.0, + ) + .is_ok(); + if is_valid_set_id { + break; + } + + initial_authorities_set_id += 1; + min_possible_block_number += One::one(); + if min_possible_block_number > initial_header_number { + // there can't be more authorities set changes than headers => if we have reached `initial_block_number` + // and still have not found correct value of `initial_authorities_set_id`, then something + // else is broken => fail + return Err(format!( + "Failed to guess initial {} GRANDPA authorities set id: checked all\ + possible ids in range [0; {}]", SourceChain::NAME, - err - ) - })?; + initial_header_number + )); + } + } Ok(InitializationData { header: initial_header, authority_list: initial_authorities_set, - set_id: initial_authorities_set_id.unwrap_or(0), + set_id: if schedules_change { + initial_authorities_set_id + 1 + } else { + initial_authorities_set_id + }, is_halted: false, }) } + +/// Read header by hash from the source client. +async fn source_header( + source_client: &Client, + header_hash: SourceChain::Hash, +) -> Result { + source_client.header_by_hash(header_hash).await.map_err(|err| { + format!( + "Failed to retrive {} header with hash {}: {:?}", + SourceChain::NAME, + header_hash, + err, + ) + }) +} + +/// Read GRANDPA authorities set at given header. +async fn source_authorities_set( + source_client: &Client, + header_hash: SourceChain::Hash, +) -> Result { + let raw_authorities_set = source_client + .grandpa_authorities_set(header_hash) + .await + .map_err(|err| { + format!( + "Failed to retrive {} GRANDPA authorities set at header {}: {:?}", + SourceChain::NAME, + header_hash, + err, + ) + })?; + GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..]).map_err(|err| { + format!( + "Failed to decode {} GRANDPA authorities set at header {}: {:?}", + SourceChain::NAME, + header_hash, + err, + ) + }) +} diff --git a/relays/substrate/src/rialto_millau/cli.rs b/relays/substrate/src/rialto_millau/cli.rs index 6ef5625921e32..86693331ded90 100644 --- a/relays/substrate/src/rialto_millau/cli.rs +++ b/relays/substrate/src/rialto_millau/cli.rs @@ -47,6 +47,17 @@ pub enum RelayHeaders { #[structopt(flatten)] prometheus_params: PrometheusParams, }, + /// Relay Westend headers to Millau. + WestendToMillau { + #[structopt(flatten)] + westend: WestendConnectionParams, + #[structopt(flatten)] + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, + }, } impl RelayHeaders { @@ -113,8 +124,6 @@ pub enum InitBridge { rialto: RialtoConnectionParams, #[structopt(flatten)] rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - millau_bridge_params: MillauBridgeInitializationParams, }, /// Initialize Rialto headers bridge in Millau. RialtoToMillau { @@ -124,8 +133,15 @@ pub enum InitBridge { millau: MillauConnectionParams, #[structopt(flatten)] millau_sign: MillauSigningParams, + }, + /// Initialize Westend headers bridge in Millau. + WestendToMillau { + #[structopt(flatten)] + westend: WestendConnectionParams, #[structopt(flatten)] - rialto_bridge_params: RialtoBridgeInitializationParams, + millau: MillauConnectionParams, + #[structopt(flatten)] + millau_sign: MillauSigningParams, }, } @@ -421,3 +437,4 @@ pub enum ToMillauMessage { declare_chain_options!(Rialto, rialto); declare_chain_options!(Millau, millau); +declare_chain_options!(Westend, westend); diff --git a/relays/substrate/src/rialto_millau/mod.rs b/relays/substrate/src/rialto_millau/mod.rs index 756a034974565..72919ccb2422d 100644 --- a/relays/substrate/src/rialto_millau/mod.rs +++ b/relays/substrate/src/rialto_millau/mod.rs @@ -21,11 +21,14 @@ pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; +pub mod westend_headers_to_millau; /// Millau node client. pub type MillauClient = relay_substrate_client::Client; /// Rialto node client. pub type RialtoClient = relay_substrate_client::Client; +/// Westend node client. +pub type WestendClient = relay_substrate_client::Client; use crate::cli::{ExplicitOrMaximal, HexBytes, Origins}; use codec::{Decode, Encode}; @@ -34,6 +37,7 @@ use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; +use relay_westend_client::Westend; use sp_core::{Bytes, Pair}; use sp_runtime::traits::IdentifyAccount; use std::fmt::Debug; @@ -44,7 +48,6 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { millau, rialto, rialto_sign, - millau_bridge_params, } => { let millau_client = millau.into_client().await?; let rialto_client = rialto.into_client().await?; @@ -54,34 +57,26 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { .next_account_index(rialto_sign.signer.public().into()) .await?; - crate::headers_initialize::initialize( - millau_client, - rialto_client.clone(), - millau_bridge_params.millau_initial_header, - millau_bridge_params.millau_initial_authorities, - millau_bridge_params.millau_initial_authorities_set_id, - move |initialization_data| { - Ok(Bytes( - Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, - rialto_signer_next_index, - rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::FinalityBridgeMillauCall::initialize(initialization_data).into(), - )) - .into(), - ) - .encode(), - )) - }, - ) + crate::headers_initialize::initialize(millau_client, rialto_client.clone(), move |initialization_data| { + Ok(Bytes( + Rialto::sign_transaction( + *rialto_client.genesis_hash(), + &rialto_sign.signer, + rialto_signer_next_index, + rialto_runtime::SudoCall::sudo(Box::new( + rialto_runtime::FinalityBridgeMillauCall::initialize(initialization_data).into(), + )) + .into(), + ) + .encode(), + )) + }) .await; } cli::InitBridge::RialtoToMillau { rialto, millau, millau_sign, - rialto_bridge_params, } => { let rialto_client = rialto.into_client().await?; let millau_client = millau.into_client().await?; @@ -90,27 +85,52 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { .next_account_index(millau_sign.signer.public().into()) .await?; - crate::headers_initialize::initialize( - rialto_client, - millau_client.clone(), - rialto_bridge_params.rialto_initial_header, - rialto_bridge_params.rialto_initial_authorities, - rialto_bridge_params.rialto_initial_authorities_set_id, - move |initialization_data| { - Ok(Bytes( - Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - millau_signer_next_index, - millau_runtime::SudoCall::sudo(Box::new( - millau_runtime::FinalityBridgeRialtoCall::initialize(initialization_data).into(), - )) - .into(), - ) - .encode(), - )) - }, - ) + crate::headers_initialize::initialize(rialto_client, millau_client.clone(), move |initialization_data| { + let initialize_call = millau_runtime::FinalityBridgeRialtoCall::< + millau_runtime::Runtime, + millau_runtime::RialtoFinalityVerifierInstance, + >::initialize(initialization_data); + + Ok(Bytes( + Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + millau_signer_next_index, + millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into(), + ) + .encode(), + )) + }) + .await; + } + cli::InitBridge::WestendToMillau { + westend, + millau, + millau_sign, + } => { + let westend_client = westend.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + let millau_signer_next_index = millau_client + .next_account_index(millau_sign.signer.public().into()) + .await?; + + crate::headers_initialize::initialize(westend_client, millau_client.clone(), move |initialization_data| { + let initialize_call = millau_runtime::FinalityBridgeWestendCall::< + millau_runtime::Runtime, + millau_runtime::WestendFinalityVerifierInstance, + >::initialize(initialization_data); + + Ok(Bytes( + Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + millau_signer_next_index, + millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into(), + ) + .encode(), + )) + }) .await; } } @@ -141,6 +161,17 @@ async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { let millau_sign = millau_sign.parse()?; rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; } + cli::RelayHeaders::WestendToMillau { + westend, + millau, + millau_sign, + prometheus_params, + } => { + let westend_client = westend.into_client().await?; + let millau_client = millau.into_client().await?; + let millau_sign = millau_sign.parse()?; + westend_headers_to_millau::run(westend_client, millau_client, millau_sign, prometheus_params.into()).await; + } } Ok(()) } @@ -661,16 +692,31 @@ impl cli::MillauConnectionParams { MillauClient::new(ConnectionParams { host: self.millau_host, port: self.millau_port, + secure: self.millau_secure, }) .await } } + impl cli::RialtoConnectionParams { /// Convert CLI connection parameters into Rialto RPC Client. pub async fn into_client(self) -> relay_substrate_client::Result { RialtoClient::new(ConnectionParams { host: self.rialto_host, port: self.rialto_port, + secure: self.rialto_secure, + }) + .await + } +} + +impl cli::WestendConnectionParams { + /// Convert CLI connection parameters into Westend RPC Client. + pub async fn into_client(self) -> relay_substrate_client::Result { + WestendClient::new(ConnectionParams { + host: self.westend_host, + port: self.westend_port, + secure: self.westend_secure, }) .await } diff --git a/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs index 7e9b855afd183..f16b37ad54ee5 100644 --- a/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -41,9 +41,12 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { ) -> Result { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = - millau_runtime::FinalityBridgeRialtoCall::submit_finality_proof(header.into_inner(), proof.into_inner()) - .into(); + + let call = millau_runtime::FinalityBridgeRialtoCall::< + millau_runtime::Runtime, + millau_runtime::RialtoFinalityVerifierInstance, + >::submit_finality_proof(header.into_inner(), proof.into_inner()) + .into(); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); diff --git a/relays/substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/substrate/src/rialto_millau/westend_headers_to_millau.rs new file mode 100644 index 0000000000000..c32f262218c36 --- /dev/null +++ b/relays/substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -0,0 +1,72 @@ +// Copyright 2019-2020 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 . + +//! Westend-to-Millau headers sync entrypoint. + +use super::{MillauClient, WestendClient}; +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use async_trait::async_trait; +use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; +use relay_substrate_client::{finality_source::Justification, Error as SubstrateError, TransactionSignScheme}; +use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; +use sp_core::Pair; + +/// Westend-to-Millau finality sync pipeline. +pub(crate) type WestendFinalityToMillau = SubstrateFinalityToSubstrate; + +#[async_trait] +impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; + + type SignedTransaction = ::SignedTransaction; + + async fn make_submit_finality_proof_transaction( + &self, + header: WestendSyncHeader, + proof: Justification, + ) -> Result { + let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); + let nonce = self.target_client.next_account_index(account_id).await?; + + let call = millau_runtime::FinalityBridgeWestendCall::< + millau_runtime::Runtime, + millau_runtime::WestendFinalityVerifierInstance, + >::submit_finality_proof(header.into_inner(), proof.into_inner()) + .into(); + + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + + Ok(transaction) + } +} + +/// Run Westend-to-Millau finality sync. +pub async fn run( + westend_client: WestendClient, + millau_client: MillauClient, + millau_sign: MillauSigningParams, + metrics_params: Option, +) { + crate::finality_pipeline::run( + WestendFinalityToMillau::new(millau_client.clone(), millau_sign), + westend_client, + millau_client, + metrics_params, + ) + .await; +} From 3e6b99ce54a0e40760dc2305a9cbac00b91b2003 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 16 Mar 2021 13:02:22 +0300 Subject: [PATCH 0382/1210] updat jsonrpsee (#828) --- relays/clients/ethereum/Cargo.toml | 6 +++--- relays/clients/ethereum/src/rpc.rs | 5 ----- relays/clients/substrate/Cargo.toml | 6 +++--- relays/clients/substrate/src/client.rs | 2 +- relays/clients/substrate/src/rpc.rs | 5 ----- 5 files changed, 7 insertions(+), 17 deletions(-) diff --git a/relays/clients/ethereum/Cargo.toml b/relays/clients/ethereum/Cargo.toml index b73a66a44c0e1..e0e1a778c7449 100644 --- a/relays/clients/ethereum/Cargo.toml +++ b/relays/clients/ethereum/Cargo.toml @@ -10,9 +10,9 @@ bp-eth-poa = { path = "../../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../../generic/headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = "0.2.0-alpha" -jsonrpsee-types = "0.2.0-alpha" -jsonrpsee-ws-client = "0.2.0-alpha" +jsonrpsee-proc-macros = "0.2.0-alpha.2" +jsonrpsee-types = "0.2.0-alpha.2" +jsonrpsee-ws-client = "0.2.0-alpha.2" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../../generic/utils" } diff --git a/relays/clients/ethereum/src/rpc.rs b/relays/clients/ethereum/src/rpc.rs index 26cc3a6d969e0..9826d92e0ceb8 100644 --- a/relays/clients/ethereum/src/rpc.rs +++ b/relays/clients/ethereum/src/rpc.rs @@ -16,11 +16,6 @@ //! Ethereum node RPC interface. -// The compiler doesn't think we're using the -// code from rpc_api! -#![allow(dead_code)] -#![allow(unused_variables)] - use crate::types::{ Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SyncState, Transaction, TransactionHash, H256, U256, U64, diff --git a/relays/clients/substrate/Cargo.toml b/relays/clients/substrate/Cargo.toml index bd73043e0a50d..13eb51c8f5b4e 100644 --- a/relays/clients/substrate/Cargo.toml +++ b/relays/clients/substrate/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } -jsonrpsee-proc-macros = "0.2.0-alpha" -jsonrpsee-types = "0.2.0-alpha" -jsonrpsee-ws-client = "0.2.0-alpha" +jsonrpsee-proc-macros = "0.2.0-alpha.2" +jsonrpsee-types = "0.2.0-alpha.2" +jsonrpsee-ws-client = "0.2.0-alpha.2" log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/clients/substrate/src/client.rs b/relays/clients/substrate/src/client.rs index ec18e9ba23d5e..8332813042896 100644 --- a/relays/clients/substrate/src/client.rs +++ b/relays/clients/substrate/src/client.rs @@ -102,7 +102,7 @@ impl Client { params.port, ); let mut config = RpcConfig::with_url(&uri); - config.max_subscription_capacity = MAX_SUBSCRIPTION_CAPACITY; + config.max_notifs_per_subscription = MAX_SUBSCRIPTION_CAPACITY; let client = RpcClient::new(config).await?; Ok(client) } diff --git a/relays/clients/substrate/src/rpc.rs b/relays/clients/substrate/src/rpc.rs index d768912a2f1a5..98b95750028cd 100644 --- a/relays/clients/substrate/src/rpc.rs +++ b/relays/clients/substrate/src/rpc.rs @@ -16,11 +16,6 @@ //! The most generic Substrate node RPC interface. -// The compiler doesn't think we're using the -// code from rpc_api! -#![allow(dead_code)] -#![allow(unused_variables)] - use crate::chain::Chain; use bp_message_lane::{LaneId, MessageNonce}; From ada2271a65bd14bb2ba73a178aa09638fe075dc5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 16 Mar 2021 13:31:53 +0300 Subject: [PATCH 0383/1210] relay_loop().await from main relay function (#829) --- .../clients/substrate/src/finality_source.rs | 2 +- .../ethereum/src/ethereum_deploy_contract.rs | 8 +- relays/ethereum/src/ethereum_exchange.rs | 157 +++++++++--------- .../ethereum/src/ethereum_exchange_submit.rs | 9 +- relays/ethereum/src/ethereum_sync_loop.rs | 5 +- relays/ethereum/src/main.rs | 28 ++-- relays/ethereum/src/substrate_sync_loop.rs | 5 +- relays/generic/exchange/src/exchange_loop.rs | 5 +- relays/generic/finality/src/finality_loop.rs | 5 +- relays/generic/headers/src/sync_loop.rs | 5 +- .../generic/messages/src/message_lane_loop.rs | 5 +- relays/generic/utils/src/relay_loop.rs | 76 ++++----- relays/substrate/src/finality_pipeline.rs | 3 +- .../millau_messages_to_rialto.rs | 5 +- relays/substrate/src/rialto_millau/mod.rs | 6 +- .../rialto_messages_to_millau.rs | 5 +- 16 files changed, 163 insertions(+), 166 deletions(-) diff --git a/relays/clients/substrate/src/finality_source.rs b/relays/clients/substrate/src/finality_source.rs index 18293efa128f9..9b6c0975a45cf 100644 --- a/relays/clients/substrate/src/finality_source.rs +++ b/relays/clients/substrate/src/finality_source.rs @@ -98,7 +98,7 @@ where >, P::Header: SourceHeader, { - type FinalityProofsStream = Pin>>>; + type FinalityProofsStream = Pin> + Send>>; async fn best_finalized_block_number(&self) -> Result { // we **CAN** continue to relay finality proofs if source node is out of sync, because diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/ethereum/src/ethereum_deploy_contract.rs index e703711843a9c..b70decd6f49f9 100644 --- a/relays/ethereum/src/ethereum_deploy_contract.rs +++ b/relays/ethereum/src/ethereum_deploy_contract.rs @@ -48,9 +48,7 @@ pub struct EthereumDeployContractParams { } /// Deploy Bridge contract on Ethereum chain. -pub fn run(params: EthereumDeployContractParams) { - let mut local_pool = futures::executor::LocalPool::new(); - +pub async fn run(params: EthereumDeployContractParams) { let EthereumDeployContractParams { eth_params, eth_sign, @@ -61,7 +59,7 @@ pub fn run(params: EthereumDeployContractParams) { eth_contract_code, } = params; - let result = local_pool.run_until(async move { + let result = async move { let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; let sub_client = SubstrateClient::::new(sub_params).await.map_err(RpcError::Substrate)?; @@ -91,7 +89,7 @@ pub fn run(params: EthereumDeployContractParams) { initial_set_id, initial_set, ).await - }); + }.await; if let Err(error) = result { log::error!(target: "bridge", "{}", error); diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/ethereum/src/ethereum_exchange.rs index ecd22ab81a1f9..5fed62b9ca686 100644 --- a/relays/ethereum/src/ethereum_exchange.rs +++ b/relays/ethereum/src/ethereum_exchange.rs @@ -282,19 +282,39 @@ impl TargetClient for SubstrateTransactionsTarget { } /// Relay exchange transaction proof(s) to Substrate node. -pub fn run(params: EthereumExchangeParams) { +pub async fn run(params: EthereumExchangeParams) { match params.mode { - ExchangeRelayMode::Single(eth_tx_hash) => run_single_transaction_relay(params, eth_tx_hash), + ExchangeRelayMode::Single(eth_tx_hash) => { + let result = run_single_transaction_relay(params, eth_tx_hash).await; + match result { + Ok(_) => log::info!( + target: "bridge", + "Ethereum transaction {} proof has been successfully submitted to Substrate node", + eth_tx_hash, + ), + Err(err) => log::error!( + target: "bridge", + "Error submitting Ethereum transaction {} proof to Substrate node: {}", + eth_tx_hash, + err, + ), + } + } ExchangeRelayMode::Auto(eth_start_with_block_number) => { - run_auto_transactions_relay_loop(params, eth_start_with_block_number) + let result = run_auto_transactions_relay_loop(params, eth_start_with_block_number).await; + if let Err(err) = result { + log::error!( + target: "bridge", + "Error auto-relaying Ethereum transactions proofs to Substrate node: {}", + err, + ); + } } - }; + } } /// Run single transaction proof relay and stop. -fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) { - let mut local_pool = futures::executor::LocalPool::new(); - +async fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) -> Result<(), String> { let EthereumExchangeParams { eth_params, sub_params, @@ -303,43 +323,25 @@ fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H25 .. } = params; - let result = local_pool.run_until(async move { - let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::new(sub_params) - .await - .map_err(RpcError::Substrate)?; - - let source = EthereumTransactionsSource { client: eth_client }; - let target = SubstrateTransactionsTarget { - client: sub_client, - sign_params: sub_sign, - bridge_instance: instance, - }; + let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; + let sub_client = SubstrateClient::::new(sub_params) + .await + .map_err(RpcError::Substrate)?; - relay_single_transaction_proof(&source, &target, eth_tx_hash).await - }); + let source = EthereumTransactionsSource { client: eth_client }; + let target = SubstrateTransactionsTarget { + client: sub_client, + sign_params: sub_sign, + bridge_instance: instance, + }; - match result { - Ok(_) => { - log::info!( - target: "bridge", - "Ethereum transaction {} proof has been successfully submitted to Substrate node", - eth_tx_hash, - ); - } - Err(err) => { - log::error!( - target: "bridge", - "Error submitting Ethereum transaction {} proof to Substrate node: {}", - eth_tx_hash, - err, - ); - } - } + relay_single_transaction_proof(&source, &target, eth_tx_hash).await } -/// Run auto-relay loop. -fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_with_block_number: Option) { +async fn run_auto_transactions_relay_loop( + params: EthereumExchangeParams, + eth_start_with_block_number: Option, +) -> Result<(), String> { let EthereumExchangeParams { eth_params, sub_params, @@ -349,46 +351,41 @@ fn run_auto_transactions_relay_loop(params: EthereumExchangeParams, eth_start_wi .. } = params; - let do_run_loop = move || -> Result<(), String> { - let eth_client = async_std::task::block_on(EthereumClient::new(eth_params)) - .map_err(|err| format!("Error starting Ethereum client: {:?}", err))?; - let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params)) - .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; - - let eth_start_with_block_number = match eth_start_with_block_number { - Some(eth_start_with_block_number) => eth_start_with_block_number, - None => { - async_std::task::block_on(sub_client.best_ethereum_finalized_block()) - .map_err(|err| { - format!( - "Error retrieving best finalized Ethereum block from Substrate node: {:?}", - err - ) - })? - .0 - } - }; - - run_loop( - InMemoryStorage::new(eth_start_with_block_number), - EthereumTransactionsSource { client: eth_client }, - SubstrateTransactionsTarget { - client: sub_client, - sign_params: sub_sign, - bridge_instance: instance, - }, - metrics_params, - futures::future::pending(), - ); - - Ok(()) + let eth_client = EthereumClient::new(eth_params) + .await + .map_err(|err| format!("Error starting Ethereum client: {:?}", err))?; + let sub_client = SubstrateClient::::new(sub_params) + .await + .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; + + let eth_start_with_block_number = match eth_start_with_block_number { + Some(eth_start_with_block_number) => eth_start_with_block_number, + None => { + sub_client + .best_ethereum_finalized_block() + .await + .map_err(|err| { + format!( + "Error retrieving best finalized Ethereum block from Substrate node: {:?}", + err + ) + })? + .0 + } }; - if let Err(err) = do_run_loop() { - log::error!( - target: "bridge", - "Error auto-relaying Ethereum transactions proofs to Substrate node: {}", - err, - ); - } + run_loop( + InMemoryStorage::new(eth_start_with_block_number), + EthereumTransactionsSource { client: eth_client }, + SubstrateTransactionsTarget { + client: sub_client, + sign_params: sub_sign, + bridge_instance: instance, + }, + metrics_params, + futures::future::pending(), + ) + .await; + + Ok(()) } diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/ethereum/src/ethereum_exchange_submit.rs index 8f9f942dac53e..8616cce2166cb 100644 --- a/relays/ethereum/src/ethereum_exchange_submit.rs +++ b/relays/ethereum/src/ethereum_exchange_submit.rs @@ -42,9 +42,7 @@ pub struct EthereumExchangeSubmitParams { } /// Submit single Ethereum -> Substrate exchange transaction. -pub fn run(params: EthereumExchangeSubmitParams) { - let mut local_pool = futures::executor::LocalPool::new(); - +pub async fn run(params: EthereumExchangeSubmitParams) { let EthereumExchangeSubmitParams { eth_params, eth_sign, @@ -53,7 +51,7 @@ pub fn run(params: EthereumExchangeSubmitParams) { sub_recipient, } = params; - let result: Result<_, String> = local_pool.run_until(async move { + let result: Result<_, String> = async move { let eth_client = EthereumClient::new(eth_params) .await .map_err(|err| format!("error connecting to Ethereum node: {:?}", err))?; @@ -94,7 +92,8 @@ pub fn run(params: EthereumExchangeSubmitParams) { .map_err(|err| format!("error submitting transaction: {:?}", err))?; Ok(eth_tx_unsigned) - }); + } + .await; match result { Ok(eth_tx_unsigned) => { diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/ethereum/src/ethereum_sync_loop.rs index 2c1abb358c63f..b4fd788f9f674 100644 --- a/relays/ethereum/src/ethereum_sync_loop.rs +++ b/relays/ethereum/src/ethereum_sync_loop.rs @@ -248,7 +248,7 @@ impl TargetClient for SubstrateHeadersTarget { } /// Run Ethereum headers synchronization. -pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { +pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { let EthereumSyncParams { eth_params, sub_params, @@ -278,7 +278,8 @@ pub fn run(params: EthereumSyncParams) -> Result<(), RpcError> { sync_params, metrics_params, futures::future::pending(), - ); + ) + .await; Ok(()) } diff --git a/relays/ethereum/src/main.rs b/relays/ethereum/src/main.rs index c0c36cc130666..b2080c396f2d7 100644 --- a/relays/ethereum/src/main.rs +++ b/relays/ethereum/src/main.rs @@ -50,6 +50,10 @@ fn main() { let yaml = clap::load_yaml!("cli.yml"); let matches = clap::App::from_yaml(yaml).get_matches(); + async_std::task::block_on(run_command(&matches)); +} + +async fn run_command(matches: &clap::ArgMatches<'_>) { match matches.subcommand() { ("eth-to-sub", Some(eth_to_sub_matches)) => { log::info!(target: "bridge", "Starting ETH ➡ SUB relay."); @@ -60,6 +64,7 @@ fn main() { return; } }) + .await .is_err() { log::error!(target: "bridge", "Unable to get Substrate genesis block for Ethereum sync."); @@ -74,6 +79,7 @@ fn main() { return; } }) + .await .is_err() { log::error!(target: "bridge", "Unable to get Substrate genesis block for Substrate sync."); @@ -87,7 +93,8 @@ fn main() { log::error!(target: "bridge", "Error during contract deployment: {}", err); return; } - }); + }) + .await; } ("eth-submit-exchange-tx", Some(eth_exchange_submit_matches)) => { log::info!(target: "bridge", "Submitting ETH ➡ SUB exchange transaction."); @@ -97,7 +104,8 @@ fn main() { log::error!(target: "bridge", "Error submitting Eethereum exchange transaction: {}", err); return; } - }); + }) + .await; } ("eth-exchange-sub", Some(eth_exchange_matches)) => { log::info!(target: "bridge", "Starting ETH ➡ SUB exchange transactions relay."); @@ -107,7 +115,8 @@ fn main() { log::error!(target: "bridge", "Error relaying Ethereum transactions proofs: {}", err); return; } - }); + }) + .await; } ("", _) => { log::error!(target: "bridge", "No subcommand specified"); @@ -398,16 +407,3 @@ fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> Result Ok(None), } } - -#[cfg(test)] -mod tests { - - // Details: https://github.com/paritytech/parity-bridges-common/issues/118 - #[test] - fn async_std_sleep_works() { - let mut local_pool = futures::executor::LocalPool::new(); - local_pool.run_until(async move { - async_std::task::sleep(std::time::Duration::from_secs(1)).await; - }); - } -} diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/ethereum/src/substrate_sync_loop.rs index 5f30e247c5a79..a0ff44d4d9bea 100644 --- a/relays/ethereum/src/substrate_sync_loop.rs +++ b/relays/ethereum/src/substrate_sync_loop.rs @@ -163,7 +163,7 @@ impl TargetClient for EthereumHeadersTarget { } /// Run Substrate headers synchronization. -pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { +pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { let SubstrateSyncParams { sub_params, eth_params, @@ -188,7 +188,8 @@ pub fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { sync_params, metrics_params, futures::future::pending(), - ); + ) + .await; Ok(()) } diff --git a/relays/generic/exchange/src/exchange_loop.rs b/relays/generic/exchange/src/exchange_loop.rs index 06f4d3f40ab01..f09ad7de41bb5 100644 --- a/relays/generic/exchange/src/exchange_loop.rs +++ b/relays/generic/exchange/src/exchange_loop.rs @@ -79,7 +79,7 @@ impl TransactionProofsRelayStorage for InMemoryStorag } /// Run proofs synchronization. -pub fn run( +pub async fn run( storage: impl TransactionProofsRelayStorage>, source_client: impl SourceClient

, target_client: impl TargetClient

, @@ -119,7 +119,8 @@ pub fn run( exit_signal.clone(), ) }, - ); + ) + .await; } /// Run proofs synchronization. diff --git a/relays/generic/finality/src/finality_loop.rs b/relays/generic/finality/src/finality_loop.rs index af5da42cee70c..7aafce075e608 100644 --- a/relays/generic/finality/src/finality_loop.rs +++ b/relays/generic/finality/src/finality_loop.rs @@ -91,7 +91,7 @@ pub trait TargetClient: RelayClient { } /// Run finality proofs synchronization loop. -pub fn run( +pub async fn run( source_client: impl SourceClient

, target_client: impl TargetClient

, sync_params: FinalitySyncParams, @@ -132,7 +132,8 @@ pub fn run( exit_signal.clone(), ) }, - ); + ) + .await; } /// Unjustified headers container. Ordered by header number. diff --git a/relays/generic/headers/src/sync_loop.rs b/relays/generic/headers/src/sync_loop.rs index d2584f2ccb2c8..7da8fd4f42fec 100644 --- a/relays/generic/headers/src/sync_loop.rs +++ b/relays/generic/headers/src/sync_loop.rs @@ -112,7 +112,7 @@ impl SyncMaintain

for () {} /// Run headers synchronization. #[allow(clippy::too_many_arguments)] -pub fn run>( +pub async fn run>( source_client: impl SourceClient

, source_tick: Duration, target_client: TC, @@ -159,7 +159,8 @@ pub fn run>( exit_signal.clone(), ) }, - ); + ) + .await; } /// Run headers synchronization. diff --git a/relays/generic/messages/src/message_lane_loop.rs b/relays/generic/messages/src/message_lane_loop.rs index 28b55dba47cc7..afbaf7a015a45 100644 --- a/relays/generic/messages/src/message_lane_loop.rs +++ b/relays/generic/messages/src/message_lane_loop.rs @@ -206,7 +206,7 @@ pub struct ClientsState { } /// Run message lane service loop. -pub fn run( +pub async fn run( params: Params, source_client: impl SourceClient

, target_client: impl TargetClient

, @@ -251,7 +251,8 @@ pub fn run( exit_signal.clone(), ) }, - ); + ) + .await; } /// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. diff --git a/relays/generic/utils/src/relay_loop.rs b/relays/generic/utils/src/relay_loop.rs index d750358edaa02..6a61ecd289343 100644 --- a/relays/generic/utils/src/relay_loop.rs +++ b/relays/generic/utils/src/relay_loop.rs @@ -37,7 +37,7 @@ pub trait Client: Clone + Send + Sync { /// This function represents an outer loop, which in turn calls provided `loop_run` function to do /// actual job. When `loop_run` returns, this outer loop reconnects to failed client (source, /// target or both) and calls `loop_run` again. -pub fn run( +pub async fn run( reconnect_delay: Duration, mut source_client: SC, mut target_client: TC, @@ -46,50 +46,46 @@ pub fn run( R: Fn(SC, TC) -> F, F: Future>, { - let mut local_pool = futures::executor::LocalPool::new(); + loop { + let result = loop_run(source_client.clone(), target_client.clone()).await; - local_pool.run_until(async move { - loop { - let result = loop_run(source_client.clone(), target_client.clone()).await; - - match result { - Ok(()) => break, - Err(failed_client) => loop { - async_std::task::sleep(reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - match source_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to source client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue; - } + match result { + Ok(()) => break, + Err(failed_client) => loop { + async_std::task::sleep(reconnect_delay).await; + if failed_client == FailedClient::Both || failed_client == FailedClient::Source { + match source_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to source client. Going to retry in {}s: {:?}", + reconnect_delay.as_secs(), + error, + ); + continue; } } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - match target_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to target client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue; - } + } + if failed_client == FailedClient::Both || failed_client == FailedClient::Target { + match target_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to target client. Going to retry in {}s: {:?}", + reconnect_delay.as_secs(), + error, + ); + continue; } } + } - break; - }, - } - - log::debug!(target: "bridge", "Restarting relay loop"); + break; + }, } - }); + + log::debug!(target: "bridge", "Restarting relay loop"); + } } diff --git a/relays/substrate/src/finality_pipeline.rs b/relays/substrate/src/finality_pipeline.rs index 21865b6c4485b..574db6a3f533a 100644 --- a/relays/substrate/src/finality_pipeline.rs +++ b/relays/substrate/src/finality_pipeline.rs @@ -126,5 +126,6 @@ pub async fn run( }, metrics_params, futures::future::pending(), - ); + ) + .await; } diff --git a/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs index 84664e4572bba..08a0fe9c08806 100644 --- a/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -125,7 +125,7 @@ type MillauSourceClient = SubstrateMessagesSource; /// Run Millau-to-Rialto messages sync. -pub fn run( +pub async fn run( millau_client: MillauClient, millau_sign: MillauSigningParams, rialto_client: RialtoClient, @@ -185,5 +185,6 @@ pub fn run( RialtoTargetClient::new(rialto_client, lane, lane_id, MILLAU_BRIDGE_INSTANCE), metrics_params, futures::future::pending(), - ); + ) + .await; } diff --git a/relays/substrate/src/rialto_millau/mod.rs b/relays/substrate/src/rialto_millau/mod.rs index 72919ccb2422d..45ef7e322af8b 100644 --- a/relays/substrate/src/rialto_millau/mod.rs +++ b/relays/substrate/src/rialto_millau/mod.rs @@ -198,7 +198,8 @@ async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { rialto_sign, lane.into(), prometheus_params.into(), - ); + ) + .await; } cli::RelayMessages::RialtoToMillau { rialto, @@ -220,7 +221,8 @@ async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { millau_sign, lane.into(), prometheus_params.into(), - ); + ) + .await; } } Ok(()) diff --git a/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs index 3083ce3cbf5d4..b0ce256aa7669 100644 --- a/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -125,7 +125,7 @@ type RialtoSourceClient = SubstrateMessagesSource; /// Run Rialto-to-Millau messages sync. -pub fn run( +pub async fn run( rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, millau_client: MillauClient, @@ -184,5 +184,6 @@ pub fn run( MillauTargetClient::new(millau_client, lane, lane_id, RIALTO_BRIDGE_INSTANCE), metrics_params, futures::future::pending(), - ); + ) + .await; } From 3646cede65680af9269c76ea7cb3ac147a46f6c0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 17 Mar 2021 15:51:13 +0300 Subject: [PATCH 0384/1210] Add multiplier parameter to transaction_payment function (#830) * transaction_payment_without_multiplier -> transaction_payment * tests * fmt --- bin/millau/runtime/src/rialto_messages.rs | 8 ++-- bin/rialto/runtime/src/millau_messages.rs | 6 ++- bin/runtime-common/src/messages.rs | 55 +++++++++++++++++++---- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index dfe08b6e3d824..1d84fc32b8b04 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -37,7 +37,7 @@ use sp_std::{convert::TryFrom, ops::RangeInclusive}; parameter_types! { /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. - storage RialtoToMillauConversionRate: FixedU128 = 1.into(); + storage RialtoToMillauConversionRate: FixedU128 = FixedU128::one(); } /// Storage key of the Millau -> Rialto message in the runtime storage. @@ -146,9 +146,10 @@ impl messages::ThisChainWithMessageLanes for Millau { fn transaction_payment(transaction: MessageLaneTransaction) -> bp_millau::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment_without_multiplier( + messages::transaction_payment( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, + FixedU128::zero(), |weight| weight as _, transaction, ) @@ -208,9 +209,10 @@ impl messages::BridgedChainWithMessageLanes for Rialto { fn transaction_payment(transaction: MessageLaneTransaction) -> bp_rialto::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment_without_multiplier( + messages::transaction_payment( bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, + FixedU128::zero(), |weight| weight as _, transaction, ) diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index f2ccd71204299..d6898ef8db685 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -146,9 +146,10 @@ impl messages::ThisChainWithMessageLanes for Rialto { fn transaction_payment(transaction: MessageLaneTransaction) -> bp_rialto::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment_without_multiplier( + messages::transaction_payment( bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, + FixedU128::zero(), |weight| weight as _, transaction, ) @@ -208,9 +209,10 @@ impl messages::BridgedChainWithMessageLanes for Millau { fn transaction_payment(transaction: MessageLaneTransaction) -> bp_millau::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment_without_multiplier( + messages::transaction_payment( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, + FixedU128::zero(), |weight| weight as _, transaction, ) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index cc30a33671a15..c69b2073d7d53 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -30,7 +30,10 @@ use bp_runtime::{InstanceId, Size, StorageProofChecker}; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; -use sp_runtime::traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, + FixedPointNumber, FixedPointOperand, FixedU128, +}; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; use sp_trie::StorageProof; @@ -143,13 +146,16 @@ pub(crate) type CallOf = ::Call; /// Raw storage proof type (just raw trie nodes). type RawStorageProof = Vec>; -/// Compute fee of transaction at runtime where: +/// Compute fee of transaction at runtime where regular transaction payment pallet is being used. /// -/// - transaction payment pallet is being used; -/// - fee multiplier is zero. -pub fn transaction_payment_without_multiplier( +/// The value of `multiplier` parameter is the expected value of `pallet_transaction_payment::NextFeeMultiplier` +/// at the moment when transaction is submitted. If you're charging this payment in advance (and that's what +/// happens with delivery and confirmation transaction in this crate), then there's a chance that the actual +/// fee will be larger than what is paid in advance. So the value must be chosen carefully. +pub fn transaction_payment( base_extrinsic_weight: Weight, per_byte_fee: Balance, + multiplier: FixedU128, weight_to_fee: impl Fn(Weight) -> Balance, transaction: MessageLaneTransaction, ) -> Balance { @@ -160,9 +166,8 @@ pub fn transaction_payment_without_multiplier( let len_fee = per_byte_fee.saturating_mul(Balance::from(transaction.size)); // the adjustable part of the fee - // - // here we assume that the fee multiplier is zero, so this part is also always zero - let adjusted_weight_fee = Balance::zero(); + let unadjusted_weight_fee = weight_to_fee(transaction.dispatch_weight); + let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee); base_fee.saturating_add(len_fee).saturating_add(adjusted_weight_fee) } @@ -1401,4 +1406,38 @@ mod tests { Err(target::MessageProofError::MessagesCountMismatch), ); } + + #[test] + fn transaction_payment_works_with_zero_multiplier() { + assert_eq!( + transaction_payment( + 100, + 10, + FixedU128::zero(), + |weight| weight, + MessageLaneTransaction { + size: 50, + dispatch_weight: 777 + }, + ), + 100 + 50 * 10, + ); + } + + #[test] + fn transaction_payment_works_with_non_zero_multiplier() { + assert_eq!( + transaction_payment( + 100, + 10, + FixedU128::one(), + |weight| weight, + MessageLaneTransaction { + size: 50, + dispatch_weight: 777 + }, + ), + 100 + 50 * 10 + 777, + ); + } } From 33943ea1e9cf36ec5a5ece88f7695ae5b5825573 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 18 Mar 2021 16:46:52 -0400 Subject: [PATCH 0385/1210] Make Test Helpers `no_std` Compatible (#823) * Use `sp-application-crypto` when generating test justifications * Try to justifications tests compiling * Try using `ed25519_dalek` for justification creation * Small cleanup * Correctly generate a Keypair The public key didn't correspond to what would be derived with the given private key. * Remove enum index hack * Clean up test account helper functions * Fix tests in `pallet-finality-verifier` * Get `pallet-substrate-bridge` tests compiling again * Use the correct keyring in justification tests * Clean up Keyring related code a bit * Appease Clippy * Remove unused import * Use keyring variants directly * Remove unecessary From implementation --- modules/finality-verifier/src/lib.rs | 29 +++-- modules/substrate/src/fork_tests.rs | 10 +- modules/substrate/src/lib.rs | 11 +- modules/substrate/src/verifier.rs | 28 ++--- .../header-chain/tests/justification.rs | 7 +- primitives/test-utils/Cargo.toml | 24 +++- primitives/test-utils/src/lib.rs | 105 ++++++++++++------ 7 files changed, 128 insertions(+), 86 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 0f450273a1143..8c77745025c0a 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -521,7 +521,10 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader mod tests { use super::*; use crate::mock::{run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime}; - use bp_test_utils::{alice, authority_list, bob, make_justification_for_header}; + use bp_test_utils::{ + authority_list, keyring, make_justification_for_header, + Keyring::{Alice, Bob}, + }; use codec::Encode; use frame_support::weights::PostDispatchInfo; use frame_support::{assert_err, assert_noop, assert_ok}; @@ -551,7 +554,7 @@ mod tests { let set_id = 1; let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); Module::::submit_finality_proof(Origin::signed(1), header, justification) } @@ -566,7 +569,7 @@ mod tests { fn change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(alice(), 1), (bob(), 1)], + next_authorities: vec![(Alice.into(), 1), (Bob.into(), 1)], delay, }); @@ -579,7 +582,7 @@ mod tests { let consensus_log = ConsensusLog::::ForcedChange( delay, sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(alice(), 1), (bob(), 1)], + next_authorities: vec![(Alice.into(), 1), (Bob.into(), 1)], delay, }, ); @@ -725,8 +728,7 @@ mod tests { let set_id = 2; let grandpa_round = 1; - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); assert_err!( Module::::submit_finality_proof(Origin::signed(1), header, justification,), @@ -753,11 +755,9 @@ mod tests { #[test] fn disallows_invalid_authority_set() { run_test(|| { - use bp_test_utils::{alice, bob}; - let genesis = test_header(0); - let invalid_authority_list = vec![(alice(), u64::MAX), (bob(), u64::MAX)]; + let invalid_authority_list = vec![(Alice.into(), u64::MAX), (Bob.into(), u64::MAX)]; let init_data = InitializationData { header: genesis, authority_list: invalid_authority_list, @@ -794,7 +794,7 @@ mod tests { initialize_substrate_bridge(); let next_set_id = 2; - let next_authorities = vec![(alice(), 1), (bob(), 1)]; + let next_authorities = vec![(Alice.into(), 1), (Bob.into(), 1)]; // Need to update the header digest to indicate that our header signals an authority set // change. The change will be enacted when we import our header. @@ -804,8 +804,7 @@ mod tests { // Create a valid justification for the header let set_id = 1; let grandpa_round = 1; - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); // Let's import our test header assert_ok!(Module::::submit_finality_proof( @@ -839,8 +838,7 @@ mod tests { // Create a valid justification for the header let set_id = 1; let grandpa_round = 1; - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); // Should not be allowed to import this header assert_err!( @@ -863,8 +861,7 @@ mod tests { // Create a valid justification for the header let set_id = 1; let grandpa_round = 1; - let justification = - make_justification_for_header(&header, grandpa_round, set_id, &authority_list()).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); // Should not be allowed to import this header assert_err!( diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index 445ffd8ce5008..9dc145b6412ef 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -59,7 +59,10 @@ use crate::storage::ImportedHeader; use crate::verifier::*; use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; use bp_header_chain::AuthoritySet; -use bp_test_utils::{alice, authority_list, bob, make_justification_for_header}; +use bp_test_utils::{ + authority_list, keyring, make_justification_for_header, + Keyring::{Alice, Bob}, +}; use codec::Encode; use frame_support::{IterableStorageMap, StorageValue}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -456,8 +459,7 @@ where // See for more: https://github.com/paritytech/parity-bridges-common/issues/430 let grandpa_round = 1; let set_id = 1; - let authorities = authority_list(); - let justification = make_justification_for_header(header, grandpa_round, set_id, &authorities).encode(); + let justification = make_justification_for_header(header, grandpa_round, set_id, &keyring()).encode(); let res = verifier .import_finality_proof(header.hash(), justification.into()) @@ -505,7 +507,7 @@ where pub(crate) fn change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(alice(), 1), (bob(), 1)], + next_authorities: vec![(Alice.into(), 1), (Bob.into(), 1)], delay, }); diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 86925d52cf2cc..8a53ed336e06c 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -721,7 +721,10 @@ mod tests { use super::*; use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestHeader, TestRuntime}; use bp_header_chain::HeaderChain; - use bp_test_utils::{alice, authority_list, bob}; + use bp_test_utils::{ + authority_list, + Keyring::{Alice, Bob}, + }; use frame_support::{assert_err, assert_noop, assert_ok}; use sp_runtime::DispatchError; @@ -949,7 +952,7 @@ mod tests { let storage = PalletStorage::::new(); let next_set_id = 2; - let next_authorities = vec![(alice(), 1), (bob(), 1)]; + let next_authorities = vec![(Alice.into(), 1), (Bob.into(), 1)]; // Need to update the header digest to indicate that our header signals an authority set // change. The change will be enacted when we import our header. @@ -978,7 +981,7 @@ mod tests { let storage = PalletStorage::::new(); let next_set_id = 2; - let next_authorities = vec![(alice(), 1), (bob(), 1)]; + let next_authorities = vec![(Alice.into(), 1), (Bob.into(), 1)]; // Need to update the header digest to indicate that our header signals an authority set // change. However, the change doesn't happen until the next block. @@ -1007,7 +1010,7 @@ mod tests { run_test(|| { let storage = PalletStorage::::new(); - let next_authorities = vec![(alice(), 1)]; + let next_authorities = vec![(Alice.into(), 1)]; let next_set_id = 2; let next_authority_set = AuthoritySet::new(next_authorities.clone(), next_set_id); diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 5ae3ed366b56b..47647aafc52be 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -342,7 +342,10 @@ mod tests { use super::*; use crate::mock::*; use crate::{BestFinalized, BestHeight, HeaderId, ImportedHeaders, PalletStorage}; - use bp_test_utils::{alice, authority_list, bob, make_justification_for_header}; + use bp_test_utils::{ + authority_list, keyring, make_justification_for_header, + Keyring::{Alice, Bob}, + }; use codec::Encode; use frame_support::{assert_err, assert_ok}; use frame_support::{StorageMap, StorageValue}; @@ -587,7 +590,7 @@ mod tests { let set_id = 1; let authorities = authority_list(); - let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id); + let initial_authority_set = AuthoritySet::new(authorities, set_id); storage.update_current_authority_set(initial_authority_set); // Let's import our header @@ -603,7 +606,7 @@ mod tests { // Now lets finalize our best header let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); // Our best header should only appear once in the list of best headers @@ -693,7 +696,7 @@ mod tests { // This is an *invalid* authority set because the combined weight of the // authorities is greater than `u64::MAX` let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(alice(), u64::MAX), (bob(), u64::MAX)], + next_authorities: vec![(Alice.into(), u64::MAX), (Bob.into(), u64::MAX)], delay: 0, }); @@ -722,12 +725,12 @@ mod tests { let set_id = 1; let authorities = authority_list(); - let authority_set = AuthoritySet::new(authorities.clone(), set_id); + let authority_set = AuthoritySet::new(authorities, set_id); storage.update_current_authority_set(authority_set); // We'll need this justification to finalize the header let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); let mut verifier = Verifier { storage: storage.clone(), @@ -748,14 +751,11 @@ mod tests { let set_id = 1; let authorities = authority_list(); - let authority_set = AuthoritySet { - authorities: authorities.clone(), - set_id, - }; + let authority_set = AuthoritySet { authorities, set_id }; storage.update_current_authority_set(authority_set); let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); let mut verifier = Verifier { storage: storage.clone(), @@ -792,19 +792,19 @@ mod tests { let set_id = 1; let authorities = authority_list(); - let initial_authority_set = AuthoritySet::new(authorities.clone(), set_id); + let initial_authority_set = AuthoritySet::new(authorities, set_id); storage.update_current_authority_set(initial_authority_set); // This header enacts an authority set change upon finalization let header = test_header(2); let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &authorities).encode(); + let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); // Schedule a change at the height of our header let set_id = 2; let height = *header.number(); - let authorities = vec![alice()]; + let authorities = vec![Alice.into()]; let change = schedule_next_change(authorities, set_id, height); storage.schedule_next_set_change(genesis_hash, change.clone()); diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index e71db25e41ee4..74f3a39f26768 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -23,12 +23,7 @@ use codec::Encode; type TestHeader = sp_runtime::testing::Header; fn make_justification_for_header_1() -> GrandpaJustification { - make_justification_for_header( - &test_header(1), - TEST_GRANDPA_ROUND, - TEST_GRANDPA_SET_ID, - &authority_list(), - ) + make_justification_for_header(&test_header(1), TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, &keyring()) } #[test] diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 396e0e764635c..64a85a2c67098 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -6,8 +6,22 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -finality-grandpa = { version = "0.14.0" } -bp-header-chain = { path = "../header-chain" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +bp-header-chain = { path = "../header-chain", default-features = false } +ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } +finality-grandpa = { version = "0.14.0", default-features = false } +sp-finality-grandpa = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-header-chain/std", + "ed25519-dalek/std", + "finality-grandpa/std", + "sp-finality-grandpa/std", + "sp-runtime/std", + "sp-std/std", + "sp-application-crypto/std", +] diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 182eb2cb796b7..499d1a5a21cce 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -15,18 +15,18 @@ // along with Parity Bridges Common. If not, see . //! Utilities for testing runtime code. -//! -//! Unlike other crates in the `primitives` folder, this crate does *not* need to compile in a -//! `no_std` environment. This is fine because this code should only be used, as the name implies, -//! in tests. + +#![cfg_attr(not(feature = "std"), no_std)] use bp_header_chain::justification::GrandpaJustification; +use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature, Signer}; use finality_grandpa::voter_set::VoterSet; +use sp_application_crypto::{Public, TryFrom}; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_finality_grandpa::{AuthoritySignature, SetId}; -use sp_keyring::Ed25519Keyring; -use sp_runtime::traits::Header as HeaderT; -use sp_runtime::traits::{One, Zero}; +use sp_runtime::traits::{Header as HeaderT, One, Zero}; +use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; pub const TEST_GRANDPA_ROUND: u64 = 1; pub const TEST_GRANDPA_SET_ID: SetId = 1; @@ -37,7 +37,7 @@ pub fn make_justification_for_header( header: &H, round: u64, set_id: SetId, - authorities: &[(AuthorityId, AuthorityWeight)], + authorities: &[(Keyring, AuthorityWeight)], ) -> GrandpaJustification { let (target_hash, target_number) = (header.hash(), *header.number()); let mut precommits = vec![]; @@ -51,13 +51,7 @@ pub fn make_justification_for_header( // I'm using the same header for all the voters since it doesn't matter as long // as they all vote on blocks _ahead_ of the one we're interested in finalizing for (id, _weight) in authorities.iter() { - let signer = extract_keyring(&id); - let precommit = signed_precommit::( - signer, - (precommit_header.hash(), *precommit_header.number()), - round, - set_id, - ); + let precommit = signed_precommit::(id, (precommit_header.hash(), *precommit_header.number()), round, set_id); precommits.push(precommit); votes_ancestries.push(precommit_header.clone()); } @@ -74,7 +68,7 @@ pub fn make_justification_for_header( } fn signed_precommit( - signer: Ed25519Keyring, + signer: &Keyring, target: (H::Hash, H::Number), round: u64, set_id: SetId, @@ -83,13 +77,24 @@ fn signed_precommit( target_hash: target.0, target_number: target.1, }; + let encoded = sp_finality_grandpa::localized_payload(round, set_id, &finality_grandpa::Message::Precommit(precommit.clone())); - let signature = signer.sign(&encoded[..]).into(); + + let signature = signer.pair().sign(&encoded); + let raw_signature: Vec = signature.to_bytes().into(); + + // Need to wrap our signature and id types that they match what our `SignedPrecommit` is expecting + let signature = AuthoritySignature::try_from(raw_signature).expect( + "We know our Keypair is good, + so our signature must also be good.", + ); + let id = (*signer).into(); + finality_grandpa::SignedPrecommit { precommit, signature, - id: signer.public().into(), + id, } } @@ -118,11 +123,47 @@ pub fn header_id(index: u8) -> (H::Hash, H::Number) { (test_header::(index.into()).hash(), index.into()) } -/// Get the identity of a test account given an ED25519 Public key. -pub fn extract_keyring(id: &AuthorityId) -> Ed25519Keyring { - let mut raw_public = [0; 32]; - raw_public.copy_from_slice(id.as_ref()); - Ed25519Keyring::from_raw_public(raw_public).unwrap() +/// Set of test accounts. +#[derive(RuntimeDebug, Clone, Copy)] +pub enum Keyring { + Alice, + Bob, + Charlie, + Dave, + Eve, + Ferdie, +} + +impl Keyring { + pub fn public(&self) -> PublicKey { + (&self.secret()).into() + } + + pub fn secret(&self) -> SecretKey { + SecretKey::from_bytes(&[*self as u8; 32]).expect("A static array of the correct length is a known good.") + } + + pub fn pair(self) -> Keypair { + let mut pair: [u8; 64] = [0; 64]; + + let secret = self.secret(); + pair[..32].copy_from_slice(&secret.to_bytes()); + + let public = self.public(); + pair[32..].copy_from_slice(&public.to_bytes()); + + Keypair::from_bytes(&pair).expect("We expect the SecretKey to be good, so this must also be good.") + } + + pub fn sign(self, msg: &[u8]) -> Signature { + self.pair().sign(msg) + } +} + +impl From for AuthorityId { + fn from(k: Keyring) -> Self { + AuthorityId::from_slice(&k.public().to_bytes()) + } } /// Get a valid set of voters for a Grandpa round. @@ -132,20 +173,10 @@ pub fn voter_set() -> VoterSet { /// Convenience function to get a list of Grandpa authorities. pub fn authority_list() -> AuthorityList { - vec![(alice(), 1), (bob(), 1), (charlie(), 1)] -} - -/// Get the Public key of the Alice test account. -pub fn alice() -> AuthorityId { - Ed25519Keyring::Alice.public().into() -} - -/// Get the Public key of the Bob test account. -pub fn bob() -> AuthorityId { - Ed25519Keyring::Bob.public().into() + keyring().iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect() } -/// Get the Public key of the Charlie test account. -pub fn charlie() -> AuthorityId { - Ed25519Keyring::Charlie.public().into() +/// Get the corresponding identities from the keyring for the "standard" authority set. +pub fn keyring() -> Vec<(Keyring, u64)> { + vec![(Keyring::Alice, 1), (Keyring::Bob, 1), (Keyring::Charlie, 1)] } From 96159d2039d9d05ea2d0371b014e65f8b9c7a7e2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 22 Mar 2021 19:28:31 +0300 Subject: [PATCH 0386/1210] Rename pallet-message-lane into pallet-bridge-messages (#834) * use runtime:: prefix for message-lane pallet traces * renamed message-lane (module and primitives) folder into messages * replace "message lane" with "messages" where appropriate --- README.md | 2 +- bin/millau/node/Cargo.toml | 6 +- bin/millau/node/src/chain_spec.rs | 5 +- bin/millau/node/src/service.rs | 14 +-- bin/millau/runtime/Cargo.toml | 8 +- bin/millau/runtime/src/lib.rs | 62 +++++----- bin/millau/runtime/src/rialto_messages.rs | 48 ++++---- bin/rialto/node/Cargo.toml | 6 +- bin/rialto/node/src/chain_spec.rs | 5 +- bin/rialto/node/src/service.rs | 14 +-- bin/rialto/runtime/Cargo.toml | 10 +- bin/rialto/runtime/src/lib.rs | 110 ++++++++--------- bin/rialto/runtime/src/millau_messages.rs | 48 ++++---- bin/runtime-common/Cargo.toml | 10 +- bin/runtime-common/README.md | 52 ++++---- bin/runtime-common/src/messages.rs | 112 +++++++++--------- .../src/messages_benchmarking.rs | 6 +- docs/high-level-overview.md | 2 +- modules/call-dispatch/README.md | 4 +- modules/call-dispatch/src/lib.rs | 2 +- modules/{message-lane => messages}/Cargo.toml | 7 +- modules/{message-lane => messages}/README.md | 86 +++++++------- .../{message-lane => messages}/rpc/Cargo.toml | 6 +- .../rpc/src/error.rs | 2 +- .../{message-lane => messages}/rpc/src/lib.rs | 20 ++-- .../src/benchmarking.rs | 4 +- .../src/inbound_lane.rs | 2 +- .../src/instant_payments.rs | 8 +- modules/{message-lane => messages}/src/lib.rs | 79 +++++++----- .../{message-lane => messages}/src/mock.rs | 20 ++-- .../src/outbound_lane.rs | 2 +- .../{message-lane => messages}/src/weights.rs | 10 +- .../src/weights_ext.rs | 2 +- primitives/chains/kusama/Cargo.toml | 4 +- primitives/chains/kusama/src/lib.rs | 2 +- primitives/chains/millau/Cargo.toml | 4 +- primitives/chains/millau/src/lib.rs | 10 +- primitives/chains/polkadot/Cargo.toml | 4 +- primitives/chains/polkadot/src/lib.rs | 2 +- primitives/chains/rialto/Cargo.toml | 4 +- primitives/chains/rialto/src/lib.rs | 10 +- primitives/chains/rococo/Cargo.toml | 4 +- primitives/chains/rococo/src/lib.rs | 2 +- primitives/chains/westend/Cargo.toml | 4 +- primitives/chains/westend/src/lib.rs | 2 +- .../{message-lane => messages}/Cargo.toml | 4 +- .../{message-lane => messages}/src/lib.rs | 6 +- .../src/source_chain.rs | 2 +- .../src/target_chain.rs | 2 +- primitives/polkadot-core/Cargo.toml | 4 +- primitives/polkadot-core/src/lib.rs | 2 +- primitives/runtime/src/lib.rs | 7 +- relays/clients/substrate/Cargo.toml | 2 +- relays/clients/substrate/src/client.rs | 8 +- relays/clients/substrate/src/rpc.rs | 8 +- relays/generic/messages/Cargo.toml | 2 +- relays/generic/messages/src/lib.rs | 2 +- .../generic/messages/src/message_lane_loop.rs | 4 +- .../messages/src/message_race_delivery.rs | 2 +- .../generic/messages/src/message_race_loop.rs | 2 +- .../messages/src/message_race_receiving.rs | 2 +- .../messages/src/message_race_strategy.rs | 2 +- relays/generic/messages/src/metrics.rs | 2 +- relays/substrate/Cargo.toml | 4 +- relays/substrate/src/cli.rs | 10 +- relays/substrate/src/messages_lane.rs | 8 +- relays/substrate/src/messages_source.rs | 2 +- relays/substrate/src/messages_target.rs | 2 +- relays/substrate/src/rialto_millau/cli.rs | 12 +- .../millau_messages_to_rialto.rs | 8 +- relays/substrate/src/rialto_millau/mod.rs | 20 ++-- .../rialto_messages_to_millau.rs | 8 +- 72 files changed, 492 insertions(+), 471 deletions(-) rename modules/{message-lane => messages}/Cargo.toml (93%) rename modules/{message-lane => messages}/README.md (88%) rename modules/{message-lane => messages}/rpc/Cargo.toml (83%) rename modules/{message-lane => messages}/rpc/src/error.rs (96%) rename modules/{message-lane => messages}/rpc/src/lib.rs (90%) rename modules/{message-lane => messages}/src/benchmarking.rs (99%) rename modules/{message-lane => messages}/src/inbound_lane.rs (99%) rename modules/{message-lane => messages}/src/instant_payments.rs (98%) rename modules/{message-lane => messages}/src/lib.rs (94%) rename modules/{message-lane => messages}/src/mock.rs (96%) rename modules/{message-lane => messages}/src/outbound_lane.rs (98%) rename modules/{message-lane => messages}/src/weights.rs (97%) rename modules/{message-lane => messages}/src/weights_ext.rs (99%) rename primitives/{message-lane => messages}/Cargo.toml (91%) rename primitives/{message-lane => messages}/src/lib.rs (98%) rename primitives/{message-lane => messages}/src/source_chain.rs (99%) rename primitives/{message-lane => messages}/src/target_chain.rs (98%) diff --git a/README.md b/README.md index c02608a9d6a93..7258eb6c5dfd3 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ the `relays` which are used to pass messages between chains. ├── modules // Substrate Runtime Modules (a.k.a Pallets) │ ├── ethereum // Ethereum PoA Header Sync Module │ ├── substrate // Substrate Based Chain Header Sync Module -│ ├── message-lane // Cross Chain Message Passing +│ ├── messages // Cross Chain Message Passing │ └── ... ├── primitives // Code shared between modules, runtimes, and relays │ └── ... diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 4e8606b497ef4..5c09367b362e8 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -15,12 +15,12 @@ structopt = "0.3.21" # Bridge dependencies -bp-message-lane = { path = "../../../primitives/message-lane" } +bp-messages = { path = "../../../primitives/messages" } bp-millau= { path = "../../../primitives/chains/millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } -pallet-message-lane = { path = "../../../modules/message-lane" } -pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } +pallet-bridge-messages = { path = "../../../modules/messages" } +pallet-bridge-messages-rpc = { path = "../../../modules/messages/rpc" } # Substrate Dependencies diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 8e9aded9f11d3..ac9a873f4f24f 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -122,7 +122,10 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), - pallet_message_lane::Module::::relayer_fund_account_id(), + pallet_bridge_messages::Module::< + millau_runtime::Runtime, + pallet_bridge_messages::DefaultInstance, + >::relayer_fund_account_id(), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 0729353af3454..18c46736dc84d 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -190,17 +190,17 @@ pub fn new_full(mut config: Configuration) -> Result let prometheus_registry = config.prometheus_registry().cloned(); let rpc_extensions_builder = { - use bp_message_lane::{LaneId, MessageNonce}; + use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; use sp_core::storage::StorageKey; // This struct is here to ease update process. - /// Millau runtime from message-lane RPC point of view. - struct MillauMessageLaneKeys; + /// Millau runtime from messages RPC point of view. + struct MillauMessagesKeys; - impl pallet_message_lane_rpc::Runtime for MillauMessageLaneKeys { + impl pallet_bridge_messages_rpc::Runtime for MillauMessagesKeys { fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option { match *instance { RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::message_key(lane, nonce)), @@ -223,7 +223,7 @@ pub fn new_full(mut config: Configuration) -> Result } } - use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; + use pallet_bridge_messages_rpc::{MessagesApi, MessagesRpcHandler}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; @@ -257,9 +257,9 @@ pub fn new_full(mut config: Configuration) -> Result subscription_executor, finality_proof_provider.clone(), ))); - io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + io.extend_with(MessagesApi::to_delegate(MessagesRpcHandler::new( backend.clone(), - Arc::new(MillauMessageLaneKeys), + Arc::new(MillauMessagesKeys), ))); io }) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 92193b1153740..c95328b0a91f7 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.124", optional = true, features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } -bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } +bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chains/millau", default-features = false } bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } @@ -23,7 +23,7 @@ bp-westend = { path = "../../../primitives/chains/westend", default-features = f bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } -pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } +pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } @@ -63,7 +63,7 @@ wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2. default = ["std"] std = [ "bp-header-chain/std", - "bp-message-lane/std", + "bp-messages/std", "bp-millau/std", "bp-rialto/std", "bp-runtime/std", @@ -79,7 +79,7 @@ std = [ "pallet-bridge-call-dispatch/std", "pallet-finality-verifier/std", "pallet-grandpa/std", - "pallet-message-lane/std", + "pallet-bridge-messages/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", "pallet-session/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 87d5ab87143bd..0be3642dec383 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -62,9 +62,9 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; +pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_finality_verifier::Call as FinalityBridgeRialtoCall; pub use pallet_finality_verifier::Call as FinalityBridgeWestendCall; -pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -209,7 +209,7 @@ impl pallet_aura::Config for Runtime { } impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; - type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); + type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; type CallFilter = (); type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; @@ -328,10 +328,10 @@ impl pallet_finality_verifier::Config for Runti impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { - pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; - pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_message_lane::MessageNonce = + pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; // `IdentityFee` is used by Millau => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = @@ -339,11 +339,11 @@ parameter_types! { pub const RootAccountForPayments: Option = None; } -impl pallet_message_lane::Config for Runtime { +impl pallet_bridge_messages::Config for Runtime { type Event = Event; // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - type WeightInfo = pallet_message_lane::weights::RialtoWeight; - type Parameter = rialto_messages::MillauToRialtoMessageLaneParameter; + type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; + type Parameter = rialto_messages::MillauToRialtoMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -359,7 +359,7 @@ impl pallet_message_lane::Config for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type MessageDeliveryAndDispatchPayment = pallet_message_lane::instant_payments::InstantCurrencyPayments< + type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, pallet_balances::Module, GetDeliveryConfirmationTransactionFee, @@ -377,7 +377,7 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic { BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, - BridgeRialtoMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, + BridgeRialtoMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, BridgeRialtoFinalityVerifier: pallet_finality_verifier::{Module, Call}, BridgeWestendFinalityVerifier: pallet_finality_verifier::::{Module, Call}, @@ -603,7 +603,7 @@ impl_runtime_apis! { impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn estimate_message_delivery_and_dispatch_fee( - _lane_id: bp_message_lane::LaneId, + _lane_id: bp_messages::LaneId, payload: ToRialtoMessagePayload, ) -> Option { estimate_message_dispatch_and_delivery_fee::( @@ -613,12 +613,12 @@ impl_runtime_apis! { } fn messages_dispatch_weight( - lane: bp_message_lane::LaneId, - begin: bp_message_lane::MessageNonce, - end: bp_message_lane::MessageNonce, - ) -> Vec<(bp_message_lane::MessageNonce, Weight, u32)> { + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec<(bp_messages::MessageNonce, Weight, u32)> { (begin..=end).filter_map(|nonce| { - let encoded_payload = BridgeRialtoMessageLane::outbound_message_payload(lane, nonce)?; + let encoded_payload = BridgeRialtoMessages::outbound_message_payload(lane, nonce)?; let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode( &mut &encoded_payload[..] ).ok()?; @@ -627,26 +627,26 @@ impl_runtime_apis! { .collect() } - fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeRialtoMessageLane::outbound_latest_received_nonce(lane) + fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeRialtoMessages::outbound_latest_received_nonce(lane) } - fn latest_generated_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeRialtoMessageLane::outbound_latest_generated_nonce(lane) + fn latest_generated_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeRialtoMessages::outbound_latest_generated_nonce(lane) } } impl bp_rialto::FromRialtoInboundLaneApi for Runtime { - fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeRialtoMessageLane::inbound_latest_received_nonce(lane) + fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeRialtoMessages::inbound_latest_received_nonce(lane) } - fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeRialtoMessageLane::inbound_latest_confirmed_nonce(lane) + fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeRialtoMessages::inbound_latest_confirmed_nonce(lane) } - fn unrewarded_relayers_state(lane: bp_message_lane::LaneId) -> bp_message_lane::UnrewardedRelayersState { - BridgeRialtoMessageLane::inbound_unrewarded_relayers_state(lane) + fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { + BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane) } } } @@ -682,9 +682,9 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - type Weights = pallet_message_lane::weights::RialtoWeight; + type Weights = pallet_bridge_messages::weights::RialtoWeight; - pallet_message_lane::ensure_weights_are_correct::( + pallet_bridge_messages::ensure_weights_are_correct::( bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, @@ -693,19 +693,19 @@ mod tests { let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( messages::target::maximal_incoming_message_size(bp_millau::max_extrinsic_size()), ); - pallet_message_lane::ensure_able_to_receive_message::( + pallet_bridge_messages::ensure_able_to_receive_message::( bp_millau::max_extrinsic_size(), bp_millau::max_extrinsic_weight(), max_incoming_message_proof_size, messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()), ); - let max_incoming_inbound_lane_data_proof_size = bp_message_lane::InboundLaneData::<()>::encoded_size_hint( + let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, ) .unwrap_or(u32::MAX); - pallet_message_lane::ensure_able_to_receive_confirmation::( + pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_millau::max_extrinsic_size(), bp_millau::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 1d84fc32b8b04..48908432b6180 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -14,17 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Everything required to serve Millau <-> Rialto message lanes. +//! Everything required to serve Millau <-> Rialto messages. use crate::Runtime; -use bp_message_lane::{ +use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessageLaneParameter, + InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; -use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge, MessageLaneTransaction}; +use bridge_runtime_common::messages::{self, ChainWithMessages, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -42,23 +42,23 @@ parameter_types! { /// Storage key of the Millau -> Rialto message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - pallet_message_lane::storage_keys::message_key::::MessageLaneInstance>( + pallet_bridge_messages::storage_keys::message_key::::MessagesInstance>( lane, nonce, ) } /// Storage key of the Millau -> Rialto message lane state in the runtime storage. pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_message_lane::storage_keys::outbound_lane_data_key::<::MessageLaneInstance>( + pallet_bridge_messages::storage_keys::outbound_lane_data_key::<::MessagesInstance>( lane, ) } /// Storage key of the Rialto -> Millau message lane state in the runtime storage. pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_message_lane::storage_keys::inbound_lane_data_key::< + pallet_bridge_messages::storage_keys::inbound_lane_data_key::< Runtime, - ::MessageLaneInstance, + ::MessagesInstance, >(lane) } @@ -109,7 +109,7 @@ impl MessageBridge for WithRialtoMessageBridge { #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; -impl messages::ChainWithMessageLanes for Millau { +impl messages::ChainWithMessages for Millau { type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; @@ -117,10 +117,10 @@ impl messages::ChainWithMessageLanes for Millau { type Weight = Weight; type Balance = bp_millau::Balance; - type MessageLaneInstance = pallet_message_lane::DefaultInstance; + type MessagesInstance = pallet_bridge_messages::DefaultInstance; } -impl messages::ThisChainWithMessageLanes for Millau { +impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { @@ -131,12 +131,12 @@ impl messages::ThisChainWithMessageLanes for Millau { MessageNonce::MAX } - fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction { + fn estimate_delivery_confirmation_transaction() -> MessageTransaction { let inbound_data_size = InboundLaneData::::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) .unwrap_or(u32::MAX); - MessageLaneTransaction { + MessageTransaction { dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, size: inbound_data_size .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE) @@ -144,7 +144,7 @@ impl messages::ThisChainWithMessageLanes for Millau { } } - fn transaction_payment(transaction: MessageLaneTransaction) -> bp_millau::Balance { + fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, @@ -160,7 +160,7 @@ impl messages::ThisChainWithMessageLanes for Millau { #[derive(RuntimeDebug, Clone, Copy)] pub struct Rialto; -impl messages::ChainWithMessageLanes for Rialto { +impl messages::ChainWithMessages for Rialto { type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; @@ -168,10 +168,10 @@ impl messages::ChainWithMessageLanes for Rialto { type Weight = Weight; type Balance = bp_rialto::Balance; - type MessageLaneInstance = pallet_message_lane::DefaultInstance; + type MessagesInstance = pallet_bridge_messages::DefaultInstance; } -impl messages::BridgedChainWithMessageLanes for Rialto { +impl messages::BridgedChainWithMessages for Rialto { fn maximal_extrinsic_size() -> u32 { bp_rialto::max_extrinsic_size() } @@ -191,12 +191,12 @@ impl messages::BridgedChainWithMessageLanes for Rialto { fn estimate_delivery_transaction( message_payload: &[u8], message_dispatch_weight: Weight, - ) -> MessageLaneTransaction { + ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); - MessageLaneTransaction { + MessageTransaction { dispatch_weight: extra_bytes_in_payload .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) @@ -207,7 +207,7 @@ impl messages::BridgedChainWithMessageLanes for Rialto { } } - fn transaction_payment(transaction: MessageLaneTransaction) -> bp_rialto::Balance { + fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, @@ -257,15 +257,15 @@ impl SourceHeaderChain for Rialto { /// Millau -> Rialto message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] -pub enum MillauToRialtoMessageLaneParameter { +pub enum MillauToRialtoMessagesParameter { /// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`. RialtoToMillauConversionRate(FixedU128), } -impl MessageLaneParameter for MillauToRialtoMessageLaneParameter { +impl MessagesParameter for MillauToRialtoMessagesParameter { fn save(&self) { match *self { - MillauToRialtoMessageLaneParameter::RialtoToMillauConversionRate(ref conversion_rate) => { + MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) => { RialtoToMillauConversionRate::set(conversion_rate) } } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index d287b0c3c9f3f..a3bbd8c018fdf 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -15,11 +15,11 @@ structopt = "0.3.21" # Bridge dependencies -bp-message-lane = { path = "../../../primitives/message-lane" } +bp-messages = { path = "../../../primitives/messages" } bp-runtime = { path = "../../../primitives/runtime" } bp-rialto = { path = "../../../primitives/chains/rialto" } -pallet-message-lane = { path = "../../../modules/message-lane" } -pallet-message-lane-rpc = { path = "../../../modules/message-lane/rpc" } +pallet-bridge-messages = { path = "../../../modules/messages" } +pallet-bridge-messages-rpc = { path = "../../../modules/messages/rpc" } rialto-runtime = { path = "../runtime" } # Substrate Dependencies diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 00a73cd4457ed..55a2abbd08b50 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -122,7 +122,10 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), - pallet_message_lane::Module::::relayer_fund_account_id(), + pallet_bridge_messages::Module::< + rialto_runtime::Runtime, + pallet_bridge_messages::DefaultInstance, + >::relayer_fund_account_id(), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 5c5ff92e88309..7f3958997da24 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -190,17 +190,17 @@ pub fn new_full(mut config: Configuration) -> Result let prometheus_registry = config.prometheus_registry().cloned(); let rpc_extensions_builder = { - use bp_message_lane::{LaneId, MessageNonce}; + use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; use sp_core::storage::StorageKey; // This struct is here to ease update process. - /// Rialto runtime from message-lane RPC point of view. - struct RialtoMessageLaneKeys; + /// Rialto runtime from messages RPC point of view. + struct RialtoMessagesKeys; - impl pallet_message_lane_rpc::Runtime for RialtoMessageLaneKeys { + impl pallet_bridge_messages_rpc::Runtime for RialtoMessagesKeys { fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option { match *instance { MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::message_key(lane, nonce)), @@ -223,7 +223,7 @@ pub fn new_full(mut config: Configuration) -> Result } } - use pallet_message_lane_rpc::{MessageLaneApi, MessageLaneRpcHandler}; + use pallet_bridge_messages_rpc::{MessagesApi, MessagesRpcHandler}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; @@ -257,9 +257,9 @@ pub fn new_full(mut config: Configuration) -> Result subscription_executor, finality_proof_provider.clone(), ))); - io.extend_with(MessageLaneApi::to_delegate(MessageLaneRpcHandler::new( + io.extend_with(MessagesApi::to_delegate(MessagesRpcHandler::new( backend.clone(), - Arc::new(RialtoMessageLaneKeys), + Arc::new(RialtoMessagesKeys), ))); io diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index bb4740071e86e..536c90bce1823 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -20,7 +20,7 @@ bp-currency-exchange = { path = "../../../primitives/currency-exchange", default bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = false } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } -bp-message-lane = { path = "../../../primitives/message-lane", default-features = false } +bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chains/millau", default-features = false } bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } @@ -30,7 +30,7 @@ pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } -pallet-message-lane = { path = "../../../modules/message-lane", default-features = false } +pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies @@ -78,7 +78,7 @@ std = [ "bp-eth-poa/std", "bp-header-chain/std", "bp-message-dispatch/std", - "bp-message-lane/std", + "bp-messages/std", "bp-millau/std", "bp-rialto/std", "bp-runtime/std", @@ -97,7 +97,7 @@ std = [ "pallet-bridge-currency-exchange/std", "pallet-finality-verifier/std", "pallet-grandpa/std", - "pallet-message-lane/std", + "pallet-bridge-messages/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", "pallet-substrate-bridge/std", @@ -129,6 +129,6 @@ runtime-benchmarks = [ "libsecp256k1", "pallet-bridge-currency-exchange/runtime-benchmarks", "pallet-bridge-eth-poa/runtime-benchmarks", - "pallet-message-lane/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0674965da50cf..4aa81269002f8 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -70,8 +70,8 @@ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_finality_verifier::Call as FinalityBridgeMillauCall; -pub use pallet_message_lane::Call as MessageLaneCall; pub use pallet_substrate_bridge::Call as BridgeMillauCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -259,7 +259,7 @@ impl pallet_bridge_currency_exchange::Config for Runtime impl pallet_bridge_call_dispatch::Config for Runtime { type Event = Event; - type MessageId = (bp_message_lane::LaneId, bp_message_lane::MessageNonce); + type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; type CallFilter = (); type EncodedCall = crate::millau_messages::FromMillauEncodedCall; @@ -427,10 +427,10 @@ impl pallet_finality_verifier::Config for Runtime { impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { - pub const MaxMessagesToPruneAtOnce: bp_message_lane::MessageNonce = 8; - pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_message_lane::MessageNonce = + pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_message_lane::MessageNonce = + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; // `IdentityFee` is used by Rialto => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = @@ -438,11 +438,11 @@ parameter_types! { pub const RootAccountForPayments: Option = None; } -pub(crate) type WithMillauMessageLaneInstance = pallet_message_lane::DefaultInstance; -impl pallet_message_lane::Config for Runtime { +pub(crate) type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance; +impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_message_lane::weights::RialtoWeight; - type Parameter = millau_messages::RialtoToMillauMessageLaneParameter; + type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; + type Parameter = millau_messages::RialtoToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -458,7 +458,7 @@ impl pallet_message_lane::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = pallet_message_lane::instant_payments::InstantCurrencyPayments< + type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, pallet_balances::Module, GetDeliveryConfirmationTransactionFee, @@ -482,7 +482,7 @@ construct_runtime!( BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeFinalityVerifier: pallet_finality_verifier::{Module, Call}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, - BridgeMillauMessageLane: pallet_message_lane::{Module, Call, Storage, Event}, + BridgeMillauMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, @@ -746,7 +746,7 @@ impl_runtime_apis! { impl bp_millau::ToMillauOutboundLaneApi for Runtime { fn estimate_message_delivery_and_dispatch_fee( - _lane_id: bp_message_lane::LaneId, + _lane_id: bp_messages::LaneId, payload: ToMillauMessagePayload, ) -> Option { estimate_message_dispatch_and_delivery_fee::( @@ -756,12 +756,12 @@ impl_runtime_apis! { } fn messages_dispatch_weight( - lane: bp_message_lane::LaneId, - begin: bp_message_lane::MessageNonce, - end: bp_message_lane::MessageNonce, - ) -> Vec<(bp_message_lane::MessageNonce, Weight, u32)> { + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec<(bp_messages::MessageNonce, Weight, u32)> { (begin..=end).filter_map(|nonce| { - let encoded_payload = BridgeMillauMessageLane::outbound_message_payload(lane, nonce)?; + let encoded_payload = BridgeMillauMessages::outbound_message_payload(lane, nonce)?; let decoded_payload = millau_messages::ToMillauMessagePayload::decode( &mut &encoded_payload[..] ).ok()?; @@ -770,26 +770,26 @@ impl_runtime_apis! { .collect() } - fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeMillauMessageLane::outbound_latest_received_nonce(lane) + fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeMillauMessages::outbound_latest_received_nonce(lane) } - fn latest_generated_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeMillauMessageLane::outbound_latest_generated_nonce(lane) + fn latest_generated_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeMillauMessages::outbound_latest_generated_nonce(lane) } } impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn latest_received_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeMillauMessageLane::inbound_latest_received_nonce(lane) + fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeMillauMessages::inbound_latest_received_nonce(lane) } - fn latest_confirmed_nonce(lane: bp_message_lane::LaneId) -> bp_message_lane::MessageNonce { - BridgeMillauMessageLane::inbound_latest_confirmed_nonce(lane) + fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { + BridgeMillauMessages::inbound_latest_confirmed_nonce(lane) } - fn unrewarded_relayers_state(lane: bp_message_lane::LaneId) -> bp_message_lane::UnrewardedRelayersState { - BridgeMillauMessageLane::inbound_unrewarded_relayers_state(lane) + fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { + BridgeMillauMessages::inbound_unrewarded_relayers_state(lane) } } @@ -857,16 +857,16 @@ impl_runtime_apis! { use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bridge_runtime_common::messages; - use pallet_message_lane::benchmarking::{ - Module as MessageLaneBench, - Config as MessageLaneConfig, - MessageDeliveryProofParams as MessageLaneMessageDeliveryProofParams, - MessageParams as MessageLaneMessageParams, - MessageProofParams as MessageLaneMessageProofParams, - ProofSize as MessageLaneProofSize, + use pallet_bridge_messages::benchmarking::{ + Module as MessagesBench, + Config as MessagesConfig, + MessageDeliveryProofParams, + MessageParams, + MessageProofParams, + ProofSize as MessagesProofSize, }; - impl MessageLaneConfig for Runtime { + impl MessagesConfig for Runtime { fn maximal_message_size() -> u32 { messages::source::maximal_message_size::() } @@ -887,7 +887,7 @@ impl_runtime_apis! { } fn prepare_outbound_message( - params: MessageLaneMessageParams, + params: MessageParams, ) -> (millau_messages::ToMillauMessagePayload, Balance) { let message_payload = vec![0; params.size as usize]; let dispatch_origin = pallet_bridge_call_dispatch::CallOrigin::SourceAccount( @@ -900,25 +900,25 @@ impl_runtime_apis! { origin: dispatch_origin, call: message_payload, }; - (message, pallet_message_lane::benchmarking::MESSAGE_FEE.into()) + (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) } fn prepare_message_proof( - params: MessageLaneMessageProofParams, + params: MessageProofParams, ) -> (millau_messages::FromMillauMessagesProof, Weight) { use crate::millau_messages::{Millau, WithMillauMessageBridge}; - use bp_message_lane::MessageKey; + use bp_messages::MessageKey; use bridge_runtime_common::{ - messages::ChainWithMessageLanes, + messages::ChainWithMessages, messages_benchmarking::{ed25519_sign, prepare_message_proof}, }; use codec::Encode; use frame_support::weights::GetDispatchInfo; - use pallet_message_lane::storage_keys; + use pallet_bridge_messages::storage_keys; use sp_runtime::traits::Header; let remark = match params.size { - MessageLaneProofSize::Minimal(ref size) => vec![0u8; *size as _], + MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], _ => vec![], }; let call = Call::System(SystemCall::remark(remark)); @@ -936,12 +936,12 @@ impl_runtime_apis! { let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< Runtime, - ::MessageLaneInstance, + ::MessagesInstance, >( &message_key.lane_id, message_key.nonce, ).0; let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::< - ::MessageLaneInstance, + ::MessagesInstance, >( &lane_id, ).0; @@ -977,20 +977,20 @@ impl_runtime_apis! { } fn prepare_message_delivery_proof( - params: MessageLaneMessageDeliveryProofParams, + params: MessageDeliveryProofParams, ) -> millau_messages::ToMillauMessagesDeliveryProof { use crate::millau_messages::{Millau, WithMillauMessageBridge}; use bridge_runtime_common::{ - messages::ChainWithMessageLanes, + messages::ChainWithMessages, messages_benchmarking::prepare_message_delivery_proof, }; use sp_runtime::traits::Header; prepare_message_delivery_proof::( params, - |lane_id| pallet_message_lane::storage_keys::inbound_lane_data_key::< + |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::< Runtime, - ::MessageLaneInstance, + ::MessagesInstance, >( &lane_id, ).0, @@ -1015,8 +1015,8 @@ impl_runtime_apis! { add_benchmark!( params, batches, - pallet_message_lane, - MessageLaneBench:: + pallet_bridge_messages, + MessagesBench:: ); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } @@ -1091,9 +1091,9 @@ mod tests { #[test] fn ensure_rialto_message_lane_weights_are_correct() { - type Weights = pallet_message_lane::weights::RialtoWeight; + type Weights = pallet_bridge_messages::weights::RialtoWeight; - pallet_message_lane::ensure_weights_are_correct::( + pallet_bridge_messages::ensure_weights_are_correct::( bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, @@ -1102,19 +1102,19 @@ mod tests { let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( messages::target::maximal_incoming_message_size(bp_rialto::max_extrinsic_size()), ); - pallet_message_lane::ensure_able_to_receive_message::( + pallet_bridge_messages::ensure_able_to_receive_message::( bp_rialto::max_extrinsic_size(), bp_rialto::max_extrinsic_weight(), max_incoming_message_proof_size, messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), ); - let max_incoming_inbound_lane_data_proof_size = bp_message_lane::InboundLaneData::<()>::encoded_size_hint( + let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, ) .unwrap_or(u32::MAX); - pallet_message_lane::ensure_able_to_receive_confirmation::( + pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_rialto::max_extrinsic_size(), bp_rialto::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index d6898ef8db685..8b0aaea994fba 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -14,17 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Everything required to serve Millau <-> Rialto message lanes. +//! Everything required to serve Millau <-> Rialto messages. use crate::Runtime; -use bp_message_lane::{ +use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessageLaneParameter, + InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; -use bridge_runtime_common::messages::{self, ChainWithMessageLanes, MessageBridge, MessageLaneTransaction}; +use bridge_runtime_common::messages::{self, ChainWithMessages, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -42,23 +42,23 @@ parameter_types! { /// Storage key of the Rialto -> Millau message in the runtime storage. pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - pallet_message_lane::storage_keys::message_key::::MessageLaneInstance>( + pallet_bridge_messages::storage_keys::message_key::::MessagesInstance>( lane, nonce, ) } /// Storage key of the Rialto -> Millau message lane state in the runtime storage. pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_message_lane::storage_keys::outbound_lane_data_key::<::MessageLaneInstance>( + pallet_bridge_messages::storage_keys::outbound_lane_data_key::<::MessagesInstance>( lane, ) } /// Storage key of the Millau -> Rialto message lane state in the runtime storage. pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_message_lane::storage_keys::inbound_lane_data_key::< + pallet_bridge_messages::storage_keys::inbound_lane_data_key::< Runtime, - ::MessageLaneInstance, + ::MessagesInstance, >(lane) } @@ -109,7 +109,7 @@ impl MessageBridge for WithMillauMessageBridge { #[derive(RuntimeDebug, Clone, Copy)] pub struct Rialto; -impl messages::ChainWithMessageLanes for Rialto { +impl messages::ChainWithMessages for Rialto { type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; @@ -117,10 +117,10 @@ impl messages::ChainWithMessageLanes for Rialto { type Weight = Weight; type Balance = bp_rialto::Balance; - type MessageLaneInstance = crate::WithMillauMessageLaneInstance; + type MessagesInstance = crate::WithMillauMessagesInstance; } -impl messages::ThisChainWithMessageLanes for Rialto { +impl messages::ThisChainWithMessages for Rialto { type Call = crate::Call; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { @@ -131,12 +131,12 @@ impl messages::ThisChainWithMessageLanes for Rialto { MessageNonce::MAX } - fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction { + fn estimate_delivery_confirmation_transaction() -> MessageTransaction { let inbound_data_size = InboundLaneData::::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) .unwrap_or(u32::MAX); - MessageLaneTransaction { + MessageTransaction { dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, size: inbound_data_size .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) @@ -144,7 +144,7 @@ impl messages::ThisChainWithMessageLanes for Rialto { } } - fn transaction_payment(transaction: MessageLaneTransaction) -> bp_rialto::Balance { + fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, @@ -160,7 +160,7 @@ impl messages::ThisChainWithMessageLanes for Rialto { #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; -impl messages::ChainWithMessageLanes for Millau { +impl messages::ChainWithMessages for Millau { type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; @@ -168,10 +168,10 @@ impl messages::ChainWithMessageLanes for Millau { type Weight = Weight; type Balance = bp_millau::Balance; - type MessageLaneInstance = pallet_message_lane::DefaultInstance; + type MessagesInstance = pallet_bridge_messages::DefaultInstance; } -impl messages::BridgedChainWithMessageLanes for Millau { +impl messages::BridgedChainWithMessages for Millau { fn maximal_extrinsic_size() -> u32 { bp_millau::max_extrinsic_size() } @@ -191,12 +191,12 @@ impl messages::BridgedChainWithMessageLanes for Millau { fn estimate_delivery_transaction( message_payload: &[u8], message_dispatch_weight: Weight, - ) -> MessageLaneTransaction { + ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); - MessageLaneTransaction { + MessageTransaction { dispatch_weight: extra_bytes_in_payload .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) @@ -207,7 +207,7 @@ impl messages::BridgedChainWithMessageLanes for Millau { } } - fn transaction_payment(transaction: MessageLaneTransaction) -> bp_millau::Balance { + fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, @@ -257,15 +257,15 @@ impl SourceHeaderChain for Millau { /// Rialto -> Millau message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] -pub enum RialtoToMillauMessageLaneParameter { +pub enum RialtoToMillauMessagesParameter { /// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`. MillauToRialtoConversionRate(FixedU128), } -impl MessageLaneParameter for RialtoToMillauMessageLaneParameter { +impl MessagesParameter for RialtoToMillauMessagesParameter { fn save(&self) { match *self { - RialtoToMillauMessageLaneParameter::MillauToRialtoConversionRate(ref conversion_rate) => { + RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => { MillauToRialtoConversionRate::set(conversion_rate) } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index dfae0861bbfc9..2bbf942180acc 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -15,10 +15,10 @@ hash-db = { version = "0.15.2", default-features = false } # Bridge dependencies bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } -bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } -pallet-message-lane = { path = "../../modules/message-lane", default-features = false } +pallet-bridge-messages = { path = "../../modules/messages", default-features = false } pallet-finality-verifier = { path = "../../modules/finality-verifier", default-features = false } # Substrate dependencies @@ -34,14 +34,14 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default = ["std"] std = [ "bp-message-dispatch/std", - "bp-message-lane/std", + "bp-messages/std", "bp-runtime/std", "codec/std", "frame-support/std", "hash-db/std", "pallet-bridge-call-dispatch/std", "pallet-finality-verifier/std", - "pallet-message-lane/std", + "pallet-bridge-messages/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", @@ -51,6 +51,6 @@ std = [ runtime-benchmarks = [ "ed25519-dalek/u64_backend", "pallet-finality-verifier/runtime-benchmarks", - "pallet-message-lane/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", "sp-state-machine", ] diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index 8d90bc7a8c84e..90ebc8976d30a 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -1,22 +1,22 @@ -# Helpers for Message Lane Module Integration +# Helpers for Messages Module Integration The [`messages`](./src/messages.rs) module of this crate contains a bunch of helpers for integrating -message lane module into your runtime. Basic prerequisites of these helpers are: +messages module into your runtime. Basic prerequisites of these helpers are: - we're going to bridge Substrate-based chain with another Substrate-based chain; -- both chains have [message lane module](../../modules/message-lane/README.md), Substrate bridge +- both chains have [messages module](../../modules/messages/README.md), Substrate bridge module and the [call dispatch module](../../modules/call-dispatch/README.md); - all message lanes are identical and may be used to transfer the same messages; - the messages sent over the bridge are dispatched using [call dispatch module](../../modules/call-dispatch/README.md); - the messages are `pallet_bridge_call_dispatch::MessagePayload` structures, where `call` field is encoded `Call` of the target chain. This means that the `Call` is opaque to the - [message lane module](../../modules/message-lane/README.md) instance at the source chain. + [messages module](../../modules/messages/README.md) instance at the source chain. It is pre-encoded by the message submitter; -- all proofs in the [message lane module](../../modules/message-lane/README.md) transactions are +- all proofs in the [messages module](../../modules/messages/README.md) transactions are based on the storage proofs from the bridged chain: storage proof of the outbound message (value - from the `pallet_message_lane::Store::MessagePayload` map), storage proof of the outbound lane - state (value from the `pallet_message_lane::Store::OutboundLanes` map) and storage proof of the - inbound lane state (value from the `pallet_message_lane::Store::InboundLanes` map); + from the `pallet_bridge_messages::Store::MessagePayload` map), storage proof of the outbound lane + state (value from the `pallet_bridge_messages::Store::OutboundLanes` map) and storage proof of the + inbound lane state (value from the `pallet_bridge_messages::Store::InboundLanes` map); - storage proofs are built at the finalized headers of the corresponding chain. So all message lane transactions with proofs are verifying storage proofs against finalized chain headers from Substrate bridge module. @@ -27,7 +27,7 @@ message lane module into your runtime. Basic prerequisites of these helpers are: ## Contents - [`MessageBridge` Trait](#messagebridge-trait) -- [`ChainWithMessageLanes` Trait ](#chainwithmessagelanes-trait) +- [`ChainWithMessages` Trait ](#ChainWithMessages-trait) - [Helpers for the Source Chain](#helpers-for-the-source-chain) - [Helpers for the Target Chain](#helpers-for-the-target-chain) @@ -40,41 +40,41 @@ tokens into this chain tokens. The bridge also requires two associated types to Worth to say that if you're going to use hardcoded constant (conversion rate) in the `MessageBridge::bridged_balance_to_this_balance` method (or in any other method of -`ThisChainWithMessageLanes` or `BridgedChainWithMessageLanes` traits), then you should take a +`ThisChainWithMessages` or `BridgedChainWithMessages` traits), then you should take a look at the -[message lane parameters functionality](../../modules/message-lane/README.md#Non-Essential-Functionality). +[messages parameters functionality](../../modules/messages/README.md#Non-Essential-Functionality). They allow pallet owner to update constants more frequently than runtime upgrade happens. -## `ChainWithMessageLanes` Trait +## `ChainWithMessages` Trait The trait is quite simple and can easily be implemented - you just need to specify types used at the corresponding chain. There is single exception, though (it may be changed in the future): -- `ChainWithMessageLanes::MessageLaneInstance`: this is used to compute runtime storage keys. There - may be several instances of message lane pallet, included in the Runtime. Every instance stores +- `ChainWithMessages::MessagesInstance`: this is used to compute runtime storage keys. There + may be several instances of messages pallet, included in the Runtime. Every instance stores messages and these messages stored under different keys. When we are verifying storage proofs from the bridged chain, we should know which instance we're talking to. This is fine, but there's - significant inconvenience with that - this chain runtime must have the same message lane pallet + significant inconvenience with that - this chain runtime must have the same messages pallet instance. This does not necessarily mean that we should use the same instance on both chains - this instance may be used to bridge with another chain/instance, or may not be used at all. -## `ThisChainWithMessageLanes` Trait +## `ThisChainWithMessages` Trait This trait represents this chain from bridge point of view. Let's review every method of this trait: -- `ThisChainWithMessageLanes::is_outbound_lane_enabled`: is used to check whether given lane accepts +- `ThisChainWithMessages::is_outbound_lane_enabled`: is used to check whether given lane accepts outbound messages. -- `ThisChainWithMessageLanes::maximal_pending_messages_at_outbound_lane`: you should return maximal +- `ThisChainWithMessages::maximal_pending_messages_at_outbound_lane`: you should return maximal number of pending (undelivered) messages from this function. Returning small values would require relayers to operate faster and could make message sending logic more complicated. On the other hand, returning large values could lead to chain state growth. -- `ThisChainWithMessageLanes::estimate_delivery_confirmation_transaction`: you'll need to return +- `ThisChainWithMessages::estimate_delivery_confirmation_transaction`: you'll need to return estimated size and dispatch weight of the delivery confirmation transaction (that happens on this chain) from this function. -- `ThisChainWithMessageLanes::transaction_payment`: you'll need to return fee that the submitter +- `ThisChainWithMessages::transaction_payment`: you'll need to return fee that the submitter must pay for given transaction on this chain. Normally, you would use transaction payment pallet for this. However, if your chain has non-zero fee multiplier set, this would mean that the payment will be computed using current value of this multiplier. But since this transaction @@ -82,11 +82,11 @@ This trait represents this chain from bridge point of view. Let's review every m non-altruistic relayer may choose not to submit this transaction until number of transactions will decrease. -## `BridgedChainWithMessageLanes` Trait +## `BridgedChainWithMessages` Trait This trait represents this chain from bridge point of view. Let's review every method of this trait: -- `BridgedChainWithMessageLanes::maximal_extrinsic_size`: you will need to return the maximal +- `BridgedChainWithMessages::maximal_extrinsic_size`: you will need to return the maximal extrinsic size of the target chain from this function. - `MessageBridge::message_weight_limits`: you'll need to return a range of @@ -106,7 +106,7 @@ This trait represents this chain from bridge point of view. Let's review every m - `MessageBridge::transaction_payment`: you'll need to return fee that the submitter must pay for given transaction on bridged chain. The best case is when you have the same conversion - formula on both chains - then you may just reuse the `ThisChainWithMessageLanes::transaction_payment` + formula on both chains - then you may just reuse the `ThisChainWithMessages::transaction_payment` implementation. Otherwise, you'll need to hardcode this formula into your runtime. ## Helpers for the Source Chain @@ -121,7 +121,7 @@ are: `maximal_message_size`, `verify_chain_message`, `verify_messages_delivery_p `pallet_bridge_call_dispatch::MessagePayload`, where `call` field is encoded target chain call. So at this chain we don't see internals of this call - we just know its size. -`FromThisChainMessageVerifier` is an implementation of `bp_message_lane::LaneMessageVerifier`. It +`FromThisChainMessageVerifier` is an implementation of `bp_messages::LaneMessageVerifier`. It has following checks in its `verify_message` method: 1. it'll verify that the used outbound lane is enabled in our runtime; @@ -167,10 +167,10 @@ The helpers for the target chain reside in the `target` submodule of the `FromBridgedChainMessagePayload` corresponds to the `FromThisChainMessagePayload` at the bridged chain. We expect that messages with this payload are stored in the `OutboundMessages` storage map of -the [message lane module](../../modules/message-lane/README.md). This map is used to build +the [messages module](../../modules/messages/README.md). This map is used to build `FromBridgedChainMessagesProof`. The proof holds the lane id, range of message nonces included in the proof, storage proof of `OutboundMessages` entries and the hash of bridged chain header that has been used to build the proof. Additionally, there's storage proof may contain the proof of outbound lane state. It may be required to prune `relayers` entries at this chain (see -[message lane module documentation](../../modules/message-lane/README.md#What-about-other-Constants-in-the-Message-Lane-Module-Configuration-Trait) +[messages module documentation](../../modules/messages/README.md#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for details). This proof is verified by the `verify_messages_proof` function. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index c69b2073d7d53..26c087ac69e83 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -21,7 +21,7 @@ //! of to elements - message lane id and message nonce. use bp_message_dispatch::MessageDispatch as _; -use bp_message_lane::{ +use bp_messages::{ source_chain::{LaneMessageVerifier, Sender}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, @@ -46,16 +46,16 @@ pub trait MessageBridge { const RELAYER_FEE_PERCENT: u32; /// This chain in context of message bridge. - type ThisChain: ThisChainWithMessageLanes; + type ThisChain: ThisChainWithMessages; /// Bridged chain in context of message bridge. - type BridgedChain: BridgedChainWithMessageLanes; + type BridgedChain: BridgedChainWithMessages; /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; } -/// Chain that has `message-lane` and `call-dispatch` modules. -pub trait ChainWithMessageLanes { +/// Chain that has `pallet-bridge-messages` and `call-dispatch` modules. +pub trait ChainWithMessages { /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. @@ -72,21 +72,21 @@ pub trait ChainWithMessageLanes { /// Type of balances that is used on the chain. type Balance: Encode + Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; - /// Instance of the message-lane pallet. - type MessageLaneInstance: Instance; + /// Instance of the `pallet-bridge-messages` pallet. + type MessagesInstance: Instance; } -/// Message-lane related transaction parameters estimation. +/// Message related transaction parameters estimation. #[derive(RuntimeDebug)] -pub struct MessageLaneTransaction { +pub struct MessageTransaction { /// The estimated dispatch weight of the transaction. pub dispatch_weight: Weight, /// The estimated size of the encoded transaction. pub size: u32, } -/// This chain that has `message-lane` and `call-dispatch` modules. -pub trait ThisChainWithMessageLanes: ChainWithMessageLanes { +/// This chain that has `pallet-bridge-messages` and `call-dispatch` modules. +pub trait ThisChainWithMessages: ChainWithMessages { /// Call type on the chain. type Call: Encode + Decode; @@ -99,14 +99,14 @@ pub trait ThisChainWithMessageLanes: ChainWithMessageLanes { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; /// Estimate size and weight of single message delivery confirmation transaction at This chain. - fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction>; + fn estimate_delivery_confirmation_transaction() -> MessageTransaction>; /// Returns minimal transaction fee that must be paid for given transaction at This chain. - fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf; + fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } -/// Bridged chain that has `message-lane` and `call-dispatch` modules. -pub trait BridgedChainWithMessageLanes: ChainWithMessageLanes { +/// Bridged chain that has `pallet-bridge-messages` and `call-dispatch` modules. +pub trait BridgedChainWithMessages: ChainWithMessages { /// Maximal extrinsic size at Bridged chain. fn maximal_extrinsic_size() -> u32; @@ -125,23 +125,23 @@ pub trait BridgedChainWithMessageLanes: ChainWithMessageLanes { fn estimate_delivery_transaction( message_payload: &[u8], message_dispatch_weight: WeightOf, - ) -> MessageLaneTransaction>; + ) -> MessageTransaction>; /// Returns minimal transaction fee that must be paid for given transaction at the Bridged chain. - fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf; + fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } pub(crate) type ThisChain = ::ThisChain; pub(crate) type BridgedChain = ::BridgedChain; -pub(crate) type HashOf = ::Hash; -pub(crate) type AccountIdOf = ::AccountId; -pub(crate) type SignerOf = ::Signer; -pub(crate) type SignatureOf = ::Signature; -pub(crate) type WeightOf = ::Weight; -pub(crate) type BalanceOf = ::Balance; -pub(crate) type MessageLaneInstanceOf = ::MessageLaneInstance; +pub(crate) type HashOf = ::Hash; +pub(crate) type AccountIdOf = ::AccountId; +pub(crate) type SignerOf = ::Signer; +pub(crate) type SignatureOf = ::Signature; +pub(crate) type WeightOf = ::Weight; +pub(crate) type BalanceOf = ::Balance; +pub(crate) type MessagesInstanceOf = ::MessagesInstance; -pub(crate) type CallOf = ::Call; +pub(crate) type CallOf = ::Call; /// Raw storage proof type (just raw trie nodes). type RawStorageProof = Vec>; @@ -157,7 +157,7 @@ pub fn transaction_payment( per_byte_fee: Balance, multiplier: FixedU128, weight_to_fee: impl Fn(Weight) -> Balance, - transaction: MessageLaneTransaction, + transaction: MessageTransaction, ) -> Balance { // base fee is charged for every tx let base_fee = weight_to_fee(base_extrinsic_weight); @@ -357,7 +357,7 @@ pub mod source { ) -> Result, &'static str> where ThisRuntime: pallet_finality_verifier::Config, - ThisRuntime: pallet_message_lane::Config>>, + ThisRuntime: pallet_bridge_messages::Config>>, HashOf>: Into::BridgedChain>>, { @@ -372,9 +372,9 @@ pub mod source { |storage| { // Messages delivery proof is just proof of single storage key read => any error // is fatal. - let storage_inbound_lane_data_key = pallet_message_lane::storage_keys::inbound_lane_data_key::< + let storage_inbound_lane_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::< ThisRuntime, - MessageLaneInstanceOf>, + MessagesInstanceOf>, >(&lane); let raw_inbound_lane_data = storage .read_value(storage_inbound_lane_data_key.0.as_ref()) @@ -462,7 +462,7 @@ pub mod target { } impl - MessageDispatch< as ChainWithMessageLanes>::Balance> + MessageDispatch< as ChainWithMessages>::Balance> for FromBridgedChainMessageDispatch where ThisCallDispatchInstance: frame_support::traits::Instance, @@ -511,7 +511,7 @@ pub mod target { ) -> Result>>>, &'static str> where ThisRuntime: pallet_finality_verifier::Config, - ThisRuntime: pallet_message_lane::Config>>, + ThisRuntime: pallet_bridge_messages::Config>>, HashOf>: Into::BridgedChain>>, { @@ -573,11 +573,11 @@ pub mod target { where H: Hasher, B: MessageBridge, - ThisRuntime: pallet_message_lane::Config>>, + ThisRuntime: pallet_bridge_messages::Config>>, { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { - let storage_outbound_lane_data_key = pallet_message_lane::storage_keys::outbound_lane_data_key::< - MessageLaneInstanceOf>, + let storage_outbound_lane_data_key = pallet_bridge_messages::storage_keys::outbound_lane_data_key::< + MessagesInstanceOf>, >(lane_id); self.storage .read_value(storage_outbound_lane_data_key.0.as_ref()) @@ -585,9 +585,9 @@ pub mod target { } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - let storage_message_key = pallet_message_lane::storage_keys::message_key::< + let storage_message_key = pallet_bridge_messages::storage_keys::message_key::< ThisRuntime, - MessageLaneInstanceOf>, + MessagesInstanceOf>, >(&message_key.lane_id, message_key.nonce); self.storage.read_value(storage_message_key.0.as_ref()).ok()? } @@ -808,7 +808,7 @@ mod tests { struct ThisChain; - impl ChainWithMessageLanes for ThisChain { + impl ChainWithMessages for ThisChain { type Hash = (); type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; @@ -816,10 +816,10 @@ mod tests { type Weight = frame_support::weights::Weight; type Balance = ThisChainBalance; - type MessageLaneInstance = pallet_message_lane::DefaultInstance; + type MessagesInstance = pallet_bridge_messages::DefaultInstance; } - impl ThisChainWithMessageLanes for ThisChain { + impl ThisChainWithMessages for ThisChain { type Call = ThisChainCall; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { @@ -830,19 +830,19 @@ mod tests { MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE } - fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction> { - MessageLaneTransaction { + fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { + MessageTransaction { dispatch_weight: DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT, size: 0, } } - fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf { + fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { ThisChainBalance(transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } } - impl BridgedChainWithMessageLanes for ThisChain { + impl BridgedChainWithMessages for ThisChain { fn maximal_extrinsic_size() -> u32 { unreachable!() } @@ -854,18 +854,18 @@ mod tests { fn estimate_delivery_transaction( _message_payload: &[u8], _message_dispatch_weight: WeightOf, - ) -> MessageLaneTransaction> { + ) -> MessageTransaction> { unreachable!() } - fn transaction_payment(_transaction: MessageLaneTransaction>) -> BalanceOf { + fn transaction_payment(_transaction: MessageTransaction>) -> BalanceOf { unreachable!() } } struct BridgedChain; - impl ChainWithMessageLanes for BridgedChain { + impl ChainWithMessages for BridgedChain { type Hash = (); type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; @@ -873,10 +873,10 @@ mod tests { type Weight = frame_support::weights::Weight; type Balance = BridgedChainBalance; - type MessageLaneInstance = pallet_message_lane::DefaultInstance; + type MessagesInstance = pallet_bridge_messages::DefaultInstance; } - impl ThisChainWithMessageLanes for BridgedChain { + impl ThisChainWithMessages for BridgedChain { type Call = BridgedChainCall; fn is_outbound_lane_enabled(_lane: &LaneId) -> bool { @@ -887,16 +887,16 @@ mod tests { unreachable!() } - fn estimate_delivery_confirmation_transaction() -> MessageLaneTransaction> { + fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { unreachable!() } - fn transaction_payment(_transaction: MessageLaneTransaction>) -> BalanceOf { + fn transaction_payment(_transaction: MessageTransaction>) -> BalanceOf { unreachable!() } } - impl BridgedChainWithMessageLanes for BridgedChain { + impl BridgedChainWithMessages for BridgedChain { fn maximal_extrinsic_size() -> u32 { BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE } @@ -909,14 +909,14 @@ mod tests { fn estimate_delivery_transaction( _message_payload: &[u8], message_dispatch_weight: WeightOf, - ) -> MessageLaneTransaction> { - MessageLaneTransaction { + ) -> MessageTransaction> { + MessageTransaction { dispatch_weight: DELIVERY_TRANSACTION_WEIGHT + message_dispatch_weight, size: 0, } } - fn transaction_payment(transaction: MessageLaneTransaction>) -> BalanceOf { + fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { BridgedChainBalance(transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) } } @@ -1415,7 +1415,7 @@ mod tests { 10, FixedU128::zero(), |weight| weight, - MessageLaneTransaction { + MessageTransaction { size: 50, dispatch_weight: 777 }, @@ -1432,7 +1432,7 @@ mod tests { 10, FixedU128::one(), |weight| weight, - MessageLaneTransaction { + MessageTransaction { size: 50, dispatch_weight: 777 }, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 56b427cb0e67f..39d3ec9262727 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Everything required to run benchmarks of message-lanes, based on +//! Everything required to run benchmarks of messages module, based on //! `bridge_runtime_common::messages` implementation. #![cfg(feature = "runtime-benchmarks")] @@ -24,11 +24,11 @@ use crate::messages::{ BridgedChain, HashOf, MessageBridge, ThisChain, }; -use bp_message_lane::{LaneId, MessageData, MessageKey, MessagePayload}; +use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload}; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; use frame_support::weights::Weight; -use pallet_message_lane::benchmarking::{MessageDeliveryProofParams, MessageProofParams, ProofSize}; +use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams, ProofSize}; use sp_core::Hasher; use sp_runtime::traits::Header; use sp_std::prelude::*; diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 763371bbf193f..e7dba6c65cf62 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -90,7 +90,7 @@ message dispatch. #### Message Lanes Delivery -The [Message delivery pallet](../modules/message-lane/src/lib.rs) is responsible for queueing up +The [Message delivery pallet](../modules/messages/src/lib.rs) is responsible for queueing up messages and delivering them in order on the target chain. It also dispatches messages, but we will cover that in the next section. diff --git a/modules/call-dispatch/README.md b/modules/call-dispatch/README.md index 0351aa9e503bc..d870193e0e40e 100644 --- a/modules/call-dispatch/README.md +++ b/modules/call-dispatch/README.md @@ -11,7 +11,7 @@ Every message that is being dispatched has three main characteristics: identifier of the bridged chain (like `b"rlto"` for messages coming from `Rialto`), or the identifier of the bridge itself (`b"rimi"` for `Rialto` <-> `Millau` bridge); - `id` is the unique id of the message within the given bridge. For messages coming from the - [message lane module](../message-lane/README.md), it may worth to use a tuple + [messages module](../messages/README.md), it may worth to use a tuple `(LaneId, MessageNonce)` to identify a message; - `message` is the `pallet_bridge_call_dispatch::MessagePayload` structure. The `call` field is set to the (potentially) encoded `Call` of this chain. @@ -52,7 +52,7 @@ When we talk about module in context of bridges, these events are helping in fol 1. when the message submitter has access to the state of both chains and wants to monitor what has happened with his message. Then he could use the message id (that he gets from the - [message lane module events](../message-lane/README.md#General-Information)) to filter events of + [messages module events](../messages/README.md#General-Information)) to filter events of call dispatch module at the target chain and actually see what has happened with his message; 1. when the message submitter only has access to the source chain state (for example, when sender is diff --git a/modules/call-dispatch/src/lib.rs b/modules/call-dispatch/src/lib.rs index 3f6bf632a2b1a..9e6fb9e53100e 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/call-dispatch/src/lib.rs @@ -118,7 +118,7 @@ pub trait Config: frame_system::Config { type Event: From> + Into<::Event>; /// Id of the message. Whenever message is passed to the dispatch module, it emits /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if - /// it comes from message-lane module. + /// it comes from the messages module. type MessageId: Parameter; /// Type of account ID on source chain. type SourceChainAccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; diff --git a/modules/message-lane/Cargo.toml b/modules/messages/Cargo.toml similarity index 93% rename from modules/message-lane/Cargo.toml rename to modules/messages/Cargo.toml index d4bced08110b6..19dc78af721e1 100644 --- a/modules/message-lane/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-message-lane" +name = "pallet-bridge-messages" description = "Module that allows bridged chains to exchange messages using lane concept." version = "0.1.0" authors = ["Parity Technologies "] @@ -14,7 +14,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies -bp-message-lane = { path = "../../primitives/message-lane", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } bp-rialto = { path = "../../primitives/chains/rialto", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } @@ -28,6 +28,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] +hex = "0.4" hex-literal = "0.3" sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -35,7 +36,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-runtime/std", "bp-rialto/std", "codec/std", diff --git a/modules/message-lane/README.md b/modules/messages/README.md similarity index 88% rename from modules/message-lane/README.md rename to modules/messages/README.md index a732042bd0d49..eda5e28a6c888 100644 --- a/modules/message-lane/README.md +++ b/modules/messages/README.md @@ -1,25 +1,25 @@ -# Message Lane Module +# Messages Module -The message lane module is used to deliver messages from source chain to target chain. Message is +The messages module is used to deliver messages from source chain to target chain. Message is (almost) opaque to the module and the final goal is to hand message to the message dispatch mechanism. ## Contents - [Overview](#overview) - [Message Workflow](#message-workflow) -- [Integrating Message Lane Module into Runtime](#integrating-message-lane-module-into-runtime) +- [Integrating Message Lane Module into Runtime](#integrating-messages-module-into-runtime) - [Non-Essential Functionality](#non-essential-functionality) - [Weights of Module Extrinsics](#weights-of-module-extrinsics) ## Overview Message lane is an unidirectional channel, where messages are sent from source chain to the target -chain. At the same time, a single instance of message lane module supports both outbound lanes and +chain. At the same time, a single instance of messages module supports both outbound lanes and inbound lanes. So the chain where the module is deployed (this chain), may act as a source chain for outbound messages (heading to a bridged chain) and as a target chain for inbound messages (coming from a bridged chain). -Message lane module supports multiple message lanes. Every message lane is identified with a 4-byte +Messages module supports multiple message lanes. Every message lane is identified with a 4-byte identifier. Messages sent through the lane are assigned unique (for this lane) increasing integer value that is known as nonce ("number that can only be used once"). Messages that are sent over the same lane are guaranteed to be delivered to the target chain in the same order they're sent from @@ -41,12 +41,12 @@ now. We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to both target and source chains. The pallet itself has no assumptions about relayers incentivization scheme, but it has some callbacks for paying rewards. See -[Integrating Message Lane Module into runtime](#Integrating-Message-Lane-Module-into-runtime) +[Integrating Messages Module into runtime](#Integrating-Messages-Module-into-runtime) for details. Eventually, some relayer would notice this message in the "undelivered" state and it would decide to deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery -transaction) for the message lane module instance, deployed at the target chain. Relayer provides +transaction) for the messages module instance, deployed at the target chain. Relayer provides his account id at the source chain, the proof of message (or several messages), the number of messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the message is considered "delivered". @@ -54,12 +54,12 @@ message is considered "delivered". Once a message is delivered, the relayer may want to confirm delivery back to the source chain. There are two reasons why he would want to do that. The first is that we intentionally limit number of "delivered", but not yet "confirmed" messages at inbound lanes -(see [What about other Constants in the Message Lane Module Configuration Trait](#What-about-other-Constants-in-the-Message-Lane-Module-Configuration-Trait) for explanation). +(see [What about other Constants in the Messages Module Configuration Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). So at some point, the target chain may stop accepting new messages until relayers confirm some of these. The second is that if the relayer wants to be rewarded for delivery, he must prove the fact that he has actually delivered the message. And this proof may only be generated after the delivery transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka -confirmation transaction) for the message lane module instance, deployed at the source chain. Once +confirmation transaction) for the messages module instance, deployed at the source chain. Once this transaction is mined, the message is considered "confirmed". The "confirmed" state is the final state of the message. But there's one last thing related to the @@ -69,21 +69,21 @@ the limit of "unconfirmed" messages at the target chain and it will stop accepti relayer sometimes includes a nonce of the latest "confirmed" message in the next `receive_messages_proof()` transaction, proving that some messages have been confirmed. -## Integrating Message Lane Module into Runtime +## Integrating Messages Module into Runtime -As it has been said above, the message lane module supports both outbound and inbound message lanes. +As it has been said above, the messages module supports both outbound and inbound message lanes. So if we will integrate a module in some runtime, it may act as the source chain runtime for outbound messages and as the target chain runtime for inbound messages. In this section, we'll sometimes refer to the chain we're currently integrating with, as this chain and the other chain as bridged chain. -Message lane module doesn't simply accept transactions that are claiming that the bridged chain has +Messages module doesn't simply accept transactions that are claiming that the bridged chain has some updated data for us. Instead of this, the module assumes that the bridged chain is able to prove that updated data in some way. The proof is abstracted from the module and may be of any kind. In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other bridges may use transaction proofs, Substrate header digests or anything else that may be proved. -**IMPORTANT NOTE**: everything below in this chapter describes details of the message lane module +**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module configuration. But if you interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at the [bridge-runtime-common](../../bin/runtime-common/README.md) crate. This crate is providing a lot of @@ -92,7 +92,7 @@ to change something in this scheme, get back here for detailed information. ### General Information -The message lane module supports instances. Every module instance is supposed to bridge this chain +The messages module supports instances. Every module instance is supposed to bridge this chain and some bridged chain. To bridge with another chain, using another instance is suggested (this isn't forced anywhere in the code, though). @@ -103,10 +103,10 @@ to the target chain, the `MessagesDelivered` event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane identifier and inclusive range of delivered message nonces. -### How to plug-in Message Lane Module to Send Messages to the Bridged Chain? +### How to plug-in Messages Module to Send Messages to the Bridged Chain? -The `pallet_message_lane::Config` trait has 3 main associated types that are used to work with -outbound messages. The `pallet_message_lane::Config::TargetHeaderChain` defines how we see the +The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with +outbound messages. The `pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the bridged chain as the target for our outbound messages. It must be able to check that the bridged chain may accept our message - like that the message has size below maximal possible transaction size of the chain and so on. And when the relayer sends us a confirmation transaction, this @@ -114,7 +114,7 @@ implementation must be able to parse and verify the proof of messages delivery. reuse the same (configurable) type on all chains that are sending messages to the same bridged chain. -The `pallet_message_lane::Config::LaneMessageVerifier` defines a single callback to verify outbound +The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the bridged chain? Are we sure that we don't bloat our @@ -123,15 +123,15 @@ fields set to invalid values? Answering all those (and similar) questions would implementation. There's another thing to consider when implementing type for use in -`pallet_message_lane::Config::LaneMessageVerifier`. It is whether we treat all message lanes +`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some 'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet. Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is -all up to the `pallet_message_lane::Config::LaneMessageVerifier` implementation. +all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation. -The last type is the `pallet_message_lane::Config::MessageDeliveryAndDispatchPayment`. When all +The last type is the `pallet_bridge_messages::Config::MessageDeliveryAndDispatchPayment`. When all checks are made and we have decided to accept the message, we're calling the `pay_delivery_and_dispatch_fee()` callback, passing the corresponding argument of the `send_message` function. Later, when message delivery is confirmed, we're calling `pay_relayers_rewards()` @@ -140,41 +140,41 @@ implementation of this trait is in the [`instant_payments.rs`](./src/instant_pay simply calls `Currency::transfer()` when those callbacks are called. So `Currency` units are transferred between submitter, 'relayers fund' and relayers accounts. Other implementations may use more or less sophisticated techniques - the whole relayers incentivization scheme is not a part of -the message lane module. +the messages module. -### I have a Message Lane Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? +### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? -You should be looking at the `bp_message_lane::source_chain::ForbidOutboundMessages` structure -[`bp_message_lane::source_chain`](../../primitives/message-lane/src/source_chain.rs). It implements +You should be looking at the `bp_messages::source_chain::ForbidOutboundMessages` structure +[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements all required traits and will simply reject all transactions, related to outbound messages. -### How to plug-in Message Lane Module to Receive Messages from the Bridged Chain? +### How to plug-in Messages Module to Receive Messages from the Bridged Chain? -The `pallet_message_lane::Config` trait has 2 main associated types that are used to work with -inbound messages. The `pallet_message_lane::Config::SourceHeaderChain` defines how we see the +The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with +inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the bridged chain as the source or our inbound messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are sending messages to the same bridged chain. -The `pallet_message_lane::Config::MessageDispatch` defines a way on how to dispatch delivered +The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered messages. Apart from actually dispatching the message, the implementation must return the correct dispatch weight of the message before dispatch is called. -### I have a Message Lane Module in my Runtime, but I Want to Reject all Inbound Messages. What +### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do? -You should be looking at the `bp_message_lane::target_chain::ForbidInboundMessages` structure from -the [`bp_message_lane::target_chain`](../../primitives/message-lane/src/target_chain.rs) module. It +You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from +the [`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It implements all required traits and will simply reject all transactions, related to inbound messages. -### What about other Constants in the Message Lane Module Configuration Trait? +### What about other Constants in the Messages Module Configuration Trait? Message is being stored in the source chain storage until its delivery will be confirmed. After that, we may safely remove the message from the storage. Lane messages are removed (pruned) when someone sends a new message using the same lane. So the message submitter pays for that pruning. To avoid pruning too many messages in a single transaction, there's -`pallet_message_lane::Config::MaxMessagesToPruneAtOnce` configuration parameter. We will never prune +`pallet_bridge_messages::Config::MaxMessagesToPruneAtOnce` configuration parameter. We will never prune more than this number of messages in the single transaction. That said, the value should not be too big to avoid waste of resources when there are no messages to prune. @@ -186,10 +186,10 @@ chain to confirm delivery and pay rewards. So to make sure we are able to craft transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure that the weight of processing this map is below a certain limit. Both size and processing weight mostly depend on the number of entries. The number of entries is limited with the -`pallet_message_lane::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight +`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight also depends on the total number of messages that are being confirmed, because every confirmed message needs to be read. So there's another -`pallet_message_lane::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. +`pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. When choosing values for these parameters, you must also keep in mind that if proof in your scheme is based on finality of headers (and it is the most obvious option for Substrate-based chains with @@ -215,7 +215,7 @@ large maps, at the same time keeping reserve for future source chain upgrades. Apart from the message related calls, the module exposes a set of auxiliary calls. They fall in two groups, described in the next two paragraphs. -There may be a special account in every runtime where the message lane module is deployed. This +There may be a special account in every runtime where the messages module is deployed. This account, named 'module owner', is like a module-level sudo account - he's able to halt all and result all module operations without requiring runtime upgrade. The module may have no message owner, but we suggest to use it at least for initial deployment. To calls that are related to this @@ -242,7 +242,7 @@ The main assumptions behind weight formulas is: - all possible costs are paid in advance by the message submitter; - whenever possible, relayer tries to minimize cost of its transactions. So e.g. even though sender always pays for delivering outbound lane state proof, relayer may not include it in the delivery - transaction (unless message lane module on target chain requires that); + transaction (unless messages module on target chain requires that); - weight formula should incentivize relayer to not to submit any redundant data in the extrinsics arguments; - the extrinsic shall never be executing slower (i.e. has larger actual weight) than defined by the @@ -343,8 +343,8 @@ hardcoded into runtime. Adequate relayer would only include required trie nodes if message size would be maximal (`2/3` of `MaximalExtrinsicSize`), then the extra proof size would be `MaximalExtrinsicSize / 3 * 2 - EXPECTED_DEFAULT_MESSAGE_LENGTH`. -Both conditions are verified by `pallet_message_lane::ensure_weights_are_correct` and -`pallet_message_lane::ensure_able_to_receive_messages` functions, which must be called from every +Both conditions are verified by `pallet_bridge_messages::ensure_weights_are_correct` and +`pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every runtime's tests. ### Weight of `receive_messages_delivery_proof` call @@ -381,11 +381,11 @@ Where: #### Why we're always able to craft `receive_messages_delivery_proof` transaction? -There can be at most `::MaxUnconfirmedMessagesAtInboundLane` +There can be at most `::MaxUnconfirmedMessagesAtInboundLane` messages and at most -`::MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded +`::MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers in the single delivery confirmation transaction. We're checking that this transaction may be crafted in the -`pallet_message_lane::ensure_able_to_receive_confirmation` function, which must be called from every +`pallet_bridge_messages::ensure_able_to_receive_confirmation` function, which must be called from every runtime' tests. diff --git a/modules/message-lane/rpc/Cargo.toml b/modules/messages/rpc/Cargo.toml similarity index 83% rename from modules/message-lane/rpc/Cargo.toml rename to modules/messages/rpc/Cargo.toml index 23dac80b407c0..bb0d1e0c54477 100644 --- a/modules/message-lane/rpc/Cargo.toml +++ b/modules/messages/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "pallet-message-lane-rpc" -description = "Module that provides RPC methods specific to message-lane pallet." +name = "pallet-bridge-messages-rpc" +description = "Module that provides RPC methods specific to pallet-bridge-messages pallet." version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" @@ -17,7 +17,7 @@ log = "0.4.11" # Bridge dependencies bp-runtime = { path = "../../../primitives/runtime" } -bp-message-lane = { path = "../../../primitives/message-lane" } +bp-messages = { path = "../../../primitives/messages" } # Substrate Dependencies diff --git a/modules/message-lane/rpc/src/error.rs b/modules/messages/rpc/src/error.rs similarity index 96% rename from modules/message-lane/rpc/src/error.rs rename to modules/messages/rpc/src/error.rs index 74fd829fcdb3b..ce7039705567f 100644 --- a/modules/message-lane/rpc/src/error.rs +++ b/modules/messages/rpc/src/error.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Possible errors and results of message-lane RPC calls. +//! Possible errors and results of messages pallet RPC calls. /// Future Result type. pub type FutureResult = jsonrpc_core::BoxFuture; diff --git a/modules/message-lane/rpc/src/lib.rs b/modules/messages/rpc/src/lib.rs similarity index 90% rename from modules/message-lane/rpc/src/lib.rs rename to modules/messages/rpc/src/lib.rs index 8532ed0c5d0e7..3fd1ffdb82558 100644 --- a/modules/message-lane/rpc/src/lib.rs +++ b/modules/messages/rpc/src/lib.rs @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Module that provides RPC methods specific to message-lane pallet. +//! Module that provides RPC methods specific to messages pallet. use crate::error::{Error, FutureResult}; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use futures::{FutureExt, TryFutureExt}; use jsonrpc_core::futures::Future as _; @@ -51,12 +51,12 @@ pub trait Runtime: Send + Sync + 'static { fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option; } -/// Provides RPC methods for interacting with message-lane pallet. +/// Provides RPC methods for interacting with messages pallet. #[rpc] -pub trait MessageLaneApi { +pub trait MessagesApi { /// Returns storage proof of messages in given inclusive range. The state of outbound /// lane is included in the proof if `include_outbound_lane_state` is true. - #[rpc(name = "messageLane_proveMessages")] + #[rpc(name = "messages_proveMessages")] fn prove_messages( &self, instance: InstanceId, @@ -68,7 +68,7 @@ pub trait MessageLaneApi { ) -> FutureResult; /// Returns proof-of-message(s) delivery. - #[rpc(name = "messageLane_proveMessagesDelivery")] + #[rpc(name = "messages_proveMessagesDelivery")] fn prove_messages_delivery( &self, instance: InstanceId, @@ -77,14 +77,14 @@ pub trait MessageLaneApi { ) -> FutureResult; } -/// Implements the MessageLaneApi trait for interacting with message lanes. -pub struct MessageLaneRpcHandler { +/// Implements the MessagesApi trait for interacting with message lanes. +pub struct MessagesRpcHandler { backend: Arc, runtime: Arc, _phantom: std::marker::PhantomData, } -impl MessageLaneRpcHandler { +impl MessagesRpcHandler { /// Creates new mesage lane RPC handler. pub fn new(backend: Arc, runtime: Arc) -> Self { Self { @@ -95,7 +95,7 @@ impl MessageLaneRpcHandler { } } -impl MessageLaneApi for MessageLaneRpcHandler +impl MessagesApi for MessagesRpcHandler where Block: BlockT, Backend: BackendT + 'static, diff --git a/modules/message-lane/src/benchmarking.rs b/modules/messages/src/benchmarking.rs similarity index 99% rename from modules/message-lane/src/benchmarking.rs rename to modules/messages/src/benchmarking.rs index cd59d1347f269..0265db0429364 100644 --- a/modules/message-lane/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Message lane pallet benchmarking. +//! Messages pallet benchmarking. use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH; use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance}; -use bp_message_lane::{ +use bp_messages::{ source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayersState, }; diff --git a/modules/message-lane/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs similarity index 99% rename from modules/message-lane/src/inbound_lane.rs rename to modules/messages/src/inbound_lane.rs index 7359aa4ed188a..a2ec02b74d32c 100644 --- a/modules/message-lane/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -16,7 +16,7 @@ //! Everything about incoming messages receival. -use bp_message_lane::{ +use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, }; diff --git a/modules/message-lane/src/instant_payments.rs b/modules/messages/src/instant_payments.rs similarity index 98% rename from modules/message-lane/src/instant_payments.rs rename to modules/messages/src/instant_payments.rs index 4dffc35935252..c6d30950be6bb 100644 --- a/modules/message-lane/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -19,7 +19,7 @@ //! The payment is first transferred to a special `relayers-fund` account and only transferred //! to the actual relayer in case confirmation is received. -use bp_message_lane::{ +use bp_messages::{ source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, MessageNonce, }; @@ -168,13 +168,13 @@ fn pay_relayer_reward( match pay_result { Ok(_) => log::trace!( - target: "runtime", + target: "runtime::bridge-messages", "Rewarded relayer {:?} with {:?}", relayer_account, reward, ), Err(error) => log::trace!( - target: "runtime", + target: "runtime::bridge-messages", "Failed to pay relayer {:?} reward {:?}: {:?}", relayer_account, reward, @@ -187,7 +187,7 @@ fn pay_relayer_reward( mod tests { use super::*; use crate::mock::{run_test, AccountId as TestAccountId, Balance as TestBalance, TestRuntime}; - use bp_message_lane::source_chain::RelayerRewards; + use bp_messages::source_chain::RelayerRewards; type Balances = pallet_balances::Module; diff --git a/modules/message-lane/src/lib.rs b/modules/messages/src/lib.rs similarity index 94% rename from modules/message-lane/src/lib.rs rename to modules/messages/src/lib.rs index 3132773eadd10..c134b2ebaf867 100644 --- a/modules/message-lane/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -44,11 +44,11 @@ use crate::inbound_lane::{InboundLane, InboundLaneStorage}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use crate::weights::WeightInfo; -use bp_message_lane::{ +use bp_messages::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, - OutboundLaneData, Parameter as MessageLaneParameter, UnrewardedRelayersState, + OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -88,7 +88,7 @@ pub trait Config: frame_system::Config { /// for integrating the pallet. /// /// All pallet parameters may only be updated either by the root, or by the pallet owner. - type Parameter: MessageLaneParameter; + type Parameter: MessagesParameter; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever new message is sent. The reason is that if you want to use lane, you should @@ -188,7 +188,7 @@ decl_error! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as MessageLane { + trait Store for Module, I: Instance = DefaultInstance> as BridgeMessages { /// Optional pallet owner. /// /// Pallet owner has a right to halt all pallet operations and then resume it. If it is @@ -255,11 +255,11 @@ decl_module! { match new_owner { Some(new_owner) => { ModuleOwner::::put(&new_owner); - log::info!("Setting pallet Owner to: {:?}", new_owner); + log::info!(target: "runtime::bridge-messages", "Setting pallet Owner to: {:?}", new_owner); }, None => { ModuleOwner::::kill(); - log::info!("Removed Owner of pallet."); + log::info!(target: "runtime::bridge-messages", "Removed Owner of pallet."); }, } } @@ -273,9 +273,9 @@ decl_module! { >::put(operational); if operational { - log::info!("Resuming pallet operations."); + log::info!(target: "runtime::bridge-messages", "Resuming pallet operations."); } else { - log::warn!("Stopping pallet operations."); + log::warn!(target: "runtime::bridge-messages", "Stopping pallet operations."); } } @@ -306,6 +306,7 @@ decl_module! { T::TargetHeaderChain::verify_message(&payload) .map_err(|err| { log::trace!( + target: "runtime::bridge-messages", "Message to lane {:?} is rejected by target chain: {:?}", lane_id, err, @@ -324,6 +325,7 @@ decl_module! { &payload, ).map_err(|err| { log::trace!( + target: "runtime::bridge-messages", "Message to lane {:?} is rejected by lane verifier: {:?}", lane_id, err, @@ -339,6 +341,7 @@ decl_module! { &Self::relayer_fund_account_id(), ).map_err(|err| { log::trace!( + target: "runtime::bridge-messages", "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", lane_id, submitter, @@ -359,6 +362,7 @@ decl_module! { lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); log::trace!( + target: "runtime::bridge-messages", "Accepted message {} to lane {:?}. Message size: {:?}", nonce, lane_id, @@ -395,6 +399,7 @@ decl_module! { &Self::relayer_fund_account_id(), ).map_err(|err| { log::trace!( + target: "runtime::bridge-messages", "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", submitter, additional_fee, @@ -451,6 +456,7 @@ decl_module! { >(proof, messages_count) .map_err(|err| { log::trace!( + target: "runtime::bridge-messages", "Rejecting invalid messages proof: {:?}", err, ); @@ -470,6 +476,7 @@ decl_module! { .fold(0, |sum, weight| sum.saturating_add(weight)); if dispatch_weight < actual_dispatch_weight { log::trace!( + target: "runtime::bridge-messages", "Rejecting messages proof because of dispatch weight mismatch: declared={}, expected={}", dispatch_weight, actual_dispatch_weight, @@ -488,6 +495,7 @@ decl_module! { let updated_latest_confirmed_nonce = lane.receive_state_update(lane_state); if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { log::trace!( + target: "runtime::bridge-messages", "Received lane {:?} state update: latest_confirmed_nonce={}", lane_id, updated_latest_confirmed_nonce, @@ -506,6 +514,7 @@ decl_module! { } log::trace!( + target: "runtime::bridge-messages", "Received messages: total={}, valid={}", total_messages, valid_messages, @@ -526,6 +535,7 @@ decl_module! { let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { log::trace!( + target: "runtime::bridge-messages", "Rejecting invalid messages delivery proof: {:?}", err, ); @@ -581,6 +591,7 @@ decl_module! { } log::trace!( + target: "runtime::bridge-messages", "Received messages delivery proof up to (and including) {} at lane {:?}", last_delivered_nonce, lane_id, @@ -618,11 +629,9 @@ impl, I: Instance> Module { } /// Get state of unrewarded relayers set. - pub fn inbound_unrewarded_relayers_state( - lane: bp_message_lane::LaneId, - ) -> bp_message_lane::UnrewardedRelayersState { + pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { let relayers = InboundLanes::::get(&lane).relayers; - bp_message_lane::UnrewardedRelayersState { + bp_messages::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0), total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), @@ -838,11 +847,12 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, TestMessageLaneParameter, - TestMessagesDeliveryProof, TestMessagesProof, TestPayload, TestRuntime, TokenConversionRate, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, + TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestPayload, TestRuntime, + TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, + TEST_RELAYER_B, }; - use bp_message_lane::UnrewardedRelayersState; + use bp_messages::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Module as System, Phase}; use hex_literal::hex; @@ -868,7 +878,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_message_lane(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), + event: TestEvent::pallet_bridge_messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), topics: vec![], }], ); @@ -897,7 +907,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_message_lane(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), + event: TestEvent::pallet_bridge_messages(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), topics: vec![], }], ); @@ -966,7 +976,7 @@ mod tests { run_test(|| { get_ready_for_events(); - let parameter = TestMessageLaneParameter::TokenConversionRate(10.into()); + let parameter = TestMessagesParameter::TokenConversionRate(10.into()); assert_ok!(Module::::update_pallet_parameter( Origin::root(), parameter.clone(), @@ -977,7 +987,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_message_lane(RawEvent::ParameterUpdated(parameter)), + event: TestEvent::pallet_bridge_messages(RawEvent::ParameterUpdated(parameter)), topics: vec![], }], ); @@ -990,7 +1000,7 @@ mod tests { ModuleOwner::::put(2); get_ready_for_events(); - let parameter = TestMessageLaneParameter::TokenConversionRate(10.into()); + let parameter = TestMessagesParameter::TokenConversionRate(10.into()); assert_ok!(Module::::update_pallet_parameter( Origin::signed(2), parameter.clone(), @@ -1001,7 +1011,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_message_lane(RawEvent::ParameterUpdated(parameter)), + event: TestEvent::pallet_bridge_messages(RawEvent::ParameterUpdated(parameter)), topics: vec![], }], ); @@ -1014,7 +1024,7 @@ mod tests { assert_noop!( Module::::update_pallet_parameter( Origin::signed(2), - TestMessageLaneParameter::TokenConversionRate(10.into()), + TestMessagesParameter::TokenConversionRate(10.into()), ), DispatchError::BadOrigin, ); @@ -1024,7 +1034,7 @@ mod tests { assert_noop!( Module::::update_pallet_parameter( Origin::signed(1), - TestMessageLaneParameter::TokenConversionRate(10.into()), + TestMessagesParameter::TokenConversionRate(10.into()), ), DispatchError::BadOrigin, ); @@ -1469,9 +1479,12 @@ mod tests { fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted messages proofs. + let storage_key = storage_keys::message_key::(&*b"test", 42).0; assert_eq!( - storage_keys::message_key::(&*b"test", 42).0, - hex!("87f1ffe31b52878f09495ca7482df1a48a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), ); } @@ -1479,9 +1492,12 @@ mod tests { fn outbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted outbound lane state proofs. + let storage_key = storage_keys::outbound_lane_data_key::(&*b"test").0; assert_eq!( - storage_keys::outbound_lane_data_key::(&*b"test").0, - hex!("87f1ffe31b52878f09495ca7482df1a496c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), ); } @@ -1489,9 +1505,12 @@ mod tests { fn inbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted inbound lane state proofs. + let storage_key = storage_keys::inbound_lane_data_key::(&*b"test").0; assert_eq!( - storage_keys::inbound_lane_data_key::(&*b"test").0, - hex!("87f1ffe31b52878f09495ca7482df1a4e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), ); } diff --git a/modules/message-lane/src/mock.rs b/modules/messages/src/mock.rs similarity index 96% rename from modules/message-lane/src/mock.rs rename to modules/messages/src/mock.rs index cf14ca105c22f..836aedf3a6a42 100644 --- a/modules/message-lane/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -19,13 +19,13 @@ use crate::Config; -use bp_message_lane::{ +use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, Sender, TargetHeaderChain, }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, - Parameter as MessageLaneParameter, + Parameter as MessagesParameter, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -56,7 +56,7 @@ impl sp_runtime::traits::Convert for AccountIdConverter { type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -use crate as pallet_message_lane; +use crate as pallet_bridge_messages; frame_support::construct_runtime! { pub enum TestRuntime where @@ -66,7 +66,7 @@ frame_support::construct_runtime! { { System: frame_system::{Module, Call, Config, Storage, Event}, Balances: pallet_balances::{Module, Call, Event}, - MessageLane: pallet_message_lane::{Module, Call, Event}, + Messages: pallet_bridge_messages::{Module, Call, Event}, } } @@ -124,16 +124,14 @@ parameter_types! { } #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)] -pub enum TestMessageLaneParameter { +pub enum TestMessagesParameter { TokenConversionRate(FixedU128), } -impl MessageLaneParameter for TestMessageLaneParameter { +impl MessagesParameter for TestMessagesParameter { fn save(&self) { match *self { - TestMessageLaneParameter::TokenConversionRate(conversion_rate) => { - TokenConversionRate::set(&conversion_rate) - } + TestMessagesParameter::TokenConversionRate(conversion_rate) => TokenConversionRate::set(&conversion_rate), } } } @@ -141,7 +139,7 @@ impl MessageLaneParameter for TestMessageLaneParameter { impl Config for TestRuntime { type Event = Event; type WeightInfo = (); - type Parameter = TestMessageLaneParameter; + type Parameter = TestMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -390,7 +388,7 @@ pub fn message_data(payload: TestPayload) -> MessageData { } } -/// Run message lane test. +/// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { let mut t = frame_system::GenesisConfig::default() .build_storage::() diff --git a/modules/message-lane/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs similarity index 98% rename from modules/message-lane/src/outbound_lane.rs rename to modules/messages/src/outbound_lane.rs index 8496d7f8c026d..0a6dd5670c53a 100644 --- a/modules/message-lane/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -16,7 +16,7 @@ //! Everything about outgoing messages sending. -use bp_message_lane::{LaneId, MessageData, MessageNonce, OutboundLaneData}; +use bp_messages::{LaneId, MessageData, MessageNonce, OutboundLaneData}; /// Outbound lane storage. pub trait OutboundLaneStorage { diff --git a/modules/message-lane/src/weights.rs b/modules/messages/src/weights.rs similarity index 97% rename from modules/message-lane/src/weights.rs rename to modules/messages/src/weights.rs index b0ec6522b2c6e..2ccb03c4c9349 100644 --- a/modules/message-lane/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for pallet_message_lane +//! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1 //! DATE: 2021-02-11, STEPS: [50, ], REPEAT: 20 @@ -28,12 +28,12 @@ // --chain=local // --steps=50 // --repeat=20 -// --pallet=pallet_message_lane +// --pallet=pallet_bridge_messages // --extrinsic=* // --execution=wasm // --wasm-execution=Compiled // --heap-pages=4096 -// --output=./modules/message-lane/src/weights.rs +// --output=./modules/messages/src/weights.rs // --template=./.maintain/rialto-weight-template.hbs #![allow(clippy::all)] @@ -46,7 +46,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_message_lane. +/// Weight functions needed for pallet_bridge_messages. pub trait WeightInfo { fn send_minimal_message_worst_case() -> Weight; fn send_1_kb_message_worst_case() -> Weight; @@ -69,7 +69,7 @@ pub trait WeightInfo { fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } -/// Weights for pallet_message_lane using the Rialto node and recommended hardware. +/// Weights for pallet_bridge_messages using the Rialto node and recommended hardware. pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { diff --git a/modules/message-lane/src/weights_ext.rs b/modules/messages/src/weights_ext.rs similarity index 99% rename from modules/message-lane/src/weights_ext.rs rename to modules/messages/src/weights_ext.rs index bc75cd5ba0ac9..89dbea89497f7 100644 --- a/modules/message-lane/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -18,7 +18,7 @@ use crate::weights::WeightInfo; -use bp_message_lane::{MessageNonce, UnrewardedRelayersState}; +use bp_messages::{MessageNonce, UnrewardedRelayersState}; use bp_runtime::{PreComputedSize, Size}; use frame_support::weights::Weight; diff --git a/primitives/chains/kusama/Cargo.toml b/primitives/chains/kusama/Cargo.toml index bb65292883b07..15614a922babb 100644 --- a/primitives/chains/kusama/Cargo.toml +++ b/primitives/chains/kusama/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-message-lane = { path = "../../message-lane", default-features = false } +bp-messages = { path = "../../messages", default-features = false } bp-polkadot-core = { path = "../../polkadot-core", default-features = false } bp-runtime = { path = "../../runtime", default-features = false } @@ -20,7 +20,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "sp-api/std", diff --git a/primitives/chains/kusama/src/lib.rs b/primitives/chains/kusama/src/lib.rs index 4e1134f162d37..7163d15ef1378 100644 --- a/primitives/chains/kusama/src/lib.rs +++ b/primitives/chains/kusama/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use sp_std::prelude::*; pub use bp_polkadot_core::*; diff --git a/primitives/chains/millau/Cargo.toml b/primitives/chains/millau/Cargo.toml index a7df6f6bbd7ea..ae27d2ce6287e 100644 --- a/primitives/chains/millau/Cargo.toml +++ b/primitives/chains/millau/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-message-lane = { path = "../../message-lane", default-features = false } +bp-messages = { path = "../../messages", default-features = false } bp-runtime = { path = "../../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } @@ -33,7 +33,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-runtime/std", "fixed-hash/std", "frame-support/std", diff --git a/primitives/chains/millau/src/lib.rs b/primitives/chains/millau/src/lib.rs index 7397fcf474555..a8fa00af3f036 100644 --- a/primitives/chains/millau/src/lib.rs +++ b/primitives/chains/millau/src/lib.rs @@ -22,7 +22,7 @@ mod millau_hash; -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, @@ -76,21 +76,21 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; /// Weight of single regular message delivery transaction on Millau chain. /// -/// This value is a result of `pallet_message_lane::Module::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. +/// This value is a result of `pallet_bridge_messages::Module::receive_messages_proof_weight()` call +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. /// The message must have dispatch weight set to zero. The result then must be rounded up to account /// possible future runtime upgrades. pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; /// Increase of delivery transaction weight on Millau chain with every additional message byte. /// -/// This value is a result of `pallet_message_lane::WeightInfoExt::storage_proof_size_overhead(1)` call. The +/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The /// result then must be rounded up to account possible future runtime upgrades. pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Millau chain. /// -/// This value is a result of `pallet_message_lane::Module::receive_messages_delivery_proof` weight formula computation +/// This value is a result of `pallet_bridge_messages::Module::receive_messages_delivery_proof` weight formula computation /// for the case when single message is confirmed. The result then must be rounded up to account possible future /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; diff --git a/primitives/chains/polkadot/Cargo.toml b/primitives/chains/polkadot/Cargo.toml index e1e646d5a1209..595fb149f4435 100644 --- a/primitives/chains/polkadot/Cargo.toml +++ b/primitives/chains/polkadot/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-message-lane = { path = "../../message-lane", default-features = false } +bp-messages = { path = "../../messages", default-features = false } bp-polkadot-core = { path = "../../polkadot-core", default-features = false } bp-runtime = { path = "../../runtime", default-features = false } @@ -21,7 +21,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "sp-api/std", diff --git a/primitives/chains/polkadot/src/lib.rs b/primitives/chains/polkadot/src/lib.rs index 53fe1917ea7b7..8e0d30cdb607f 100644 --- a/primitives/chains/polkadot/src/lib.rs +++ b/primitives/chains/polkadot/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use sp_std::prelude::*; pub use bp_polkadot_core::*; diff --git a/primitives/chains/rialto/Cargo.toml b/primitives/chains/rialto/Cargo.toml index a225f79b3432b..6dbbe7549a39b 100644 --- a/primitives/chains/rialto/Cargo.toml +++ b/primitives/chains/rialto/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-message-lane = { path = "../../message-lane", default-features = false } +bp-messages = { path = "../../messages", default-features = false } bp-runtime = { path = "../../runtime", default-features = false } # Substrate Based Dependencies @@ -25,7 +25,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-runtime/std", "frame-support/std", "frame-system/std", diff --git a/primitives/chains/rialto/src/lib.rs b/primitives/chains/rialto/src/lib.rs index ccb2154ee4f45..b373bbe9a00cd 100644 --- a/primitives/chains/rialto/src/lib.rs +++ b/primitives/chains/rialto/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, @@ -67,21 +67,21 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; /// Weight of single regular message delivery transaction on Rialto chain. /// -/// This value is a result of `pallet_message_lane::Module::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_message_lane::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. +/// This value is a result of `pallet_bridge_messages::Module::receive_messages_proof_weight()` call +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. /// The message must have dispatch weight set to zero. The result then must be rounded up to account /// possible future runtime upgrades. pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; /// Increase of delivery transaction weight on Rialto chain with every additional message byte. /// -/// This value is a result of `pallet_message_lane::WeightInfoExt::storage_proof_size_overhead(1)` call. The +/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The /// result then must be rounded up to account possible future runtime upgrades. pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Rialto chain. /// -/// This value is a result of `pallet_message_lane::Module::receive_messages_delivery_proof` weight formula computation +/// This value is a result of `pallet_bridge_messages::Module::receive_messages_delivery_proof` weight formula computation /// for the case when single message is confirmed. The result then must be rounded up to account possible future /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; diff --git a/primitives/chains/rococo/Cargo.toml b/primitives/chains/rococo/Cargo.toml index dc09d1a3bf305..db6bc121562d1 100644 --- a/primitives/chains/rococo/Cargo.toml +++ b/primitives/chains/rococo/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-message-lane = { path = "../../message-lane", default-features = false } +bp-messages = { path = "../../messages", default-features = false } bp-polkadot-core = { path = "../../polkadot-core", default-features = false } bp-runtime = { path = "../../runtime", default-features = false } @@ -20,7 +20,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "sp-api/std", diff --git a/primitives/chains/rococo/src/lib.rs b/primitives/chains/rococo/src/lib.rs index ef372540a340a..b52049cd631e7 100644 --- a/primitives/chains/rococo/src/lib.rs +++ b/primitives/chains/rococo/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, Weight, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, Weight, MessageNonce, UnrewardedRelayersState}; use sp_std::prelude::*; pub use bp_polkadot_core::*; diff --git a/primitives/chains/westend/Cargo.toml b/primitives/chains/westend/Cargo.toml index 6253f4bef9694..654f0291461b3 100644 --- a/primitives/chains/westend/Cargo.toml +++ b/primitives/chains/westend/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-message-lane = { path = "../../message-lane", default-features = false } +bp-messages = { path = "../../messages", default-features = false } bp-polkadot-core = { path = "../../polkadot-core", default-features = false } bp-runtime = { path = "../../runtime", default-features = false } @@ -20,7 +20,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "sp-api/std", diff --git a/primitives/chains/westend/src/lib.rs b/primitives/chains/westend/src/lib.rs index 5b43eeeae5277..0596da1b7dcdc 100644 --- a/primitives/chains/westend/src/lib.rs +++ b/primitives/chains/westend/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use sp_std::prelude::*; pub use bp_polkadot_core::*; diff --git a/primitives/message-lane/Cargo.toml b/primitives/messages/Cargo.toml similarity index 91% rename from primitives/message-lane/Cargo.toml rename to primitives/messages/Cargo.toml index cbddcb1614606..9cb037a34ce8b 100644 --- a/primitives/message-lane/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "bp-message-lane" -description = "Primitives of message lane module." +name = "bp-messages" +description = "Primitives of messages module." version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" diff --git a/primitives/message-lane/src/lib.rs b/primitives/messages/src/lib.rs similarity index 98% rename from primitives/message-lane/src/lib.rs rename to primitives/messages/src/lib.rs index de2dbd9ae63da..83bd902a1e81a 100644 --- a/primitives/message-lane/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Primitives of message lane module. +//! Primitives of messages module. #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions @@ -29,10 +29,10 @@ use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; pub mod target_chain; -// Weight is reexported to avoid additional frame-support dependencies in message-lane related crates. +// Weight is reexported to avoid additional frame-support dependencies in related crates. pub use frame_support::weights::Weight; -/// Message lane pallet parameter. +/// Messages pallet parameter. pub trait Parameter: frame_support::Parameter { /// Save parameter value in the runtime storage. fn save(&self); diff --git a/primitives/message-lane/src/source_chain.rs b/primitives/messages/src/source_chain.rs similarity index 99% rename from primitives/message-lane/src/source_chain.rs rename to primitives/messages/src/source_chain.rs index d0dc36bb69352..8cc62a0090231 100644 --- a/primitives/message-lane/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Primitives of message lane module, that are used on the source chain. +//! Primitives of messages module, that are used on the source chain. use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; diff --git a/primitives/message-lane/src/target_chain.rs b/primitives/messages/src/target_chain.rs similarity index 98% rename from primitives/message-lane/src/target_chain.rs rename to primitives/messages/src/target_chain.rs index 765ce64f63b39..530a228022354 100644 --- a/primitives/message-lane/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Primitives of message lane module, that are used on the target chain. +//! Primitives of messages module, that are used on the target chain. use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 0a19bad97aaec..8df209ca671ed 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-message-lane = { path = "../message-lane", default-features = false } +bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies @@ -25,7 +25,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-message-lane/std", + "bp-messages/std", "bp-runtime/std", "frame-support/std", "frame-system/std", diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index f56d4c52aa789..f3f95637740e6 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -16,7 +16,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_message_lane::MessageNonce; +use bp_messages::MessageNonce; use bp_runtime::Chain; use frame_support::{ parameter_types, diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 862edf7b972d3..9e6e878bf4d87 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -56,9 +56,6 @@ pub const WESTEND_BRIDGE_INSTANCE: InstanceId = *b"wend"; /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; -/// Message-lane module prefix. -pub const MESSAGE_LANE_MODULE_PREFIX: &[u8] = b"pallet-bridge/message-lane"; - /// A unique prefix for entropy when generating cross-chain account IDs. pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/account"; @@ -66,7 +63,7 @@ pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/ 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. message-lane pallet may be deployed twice in the same +/// 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]; @@ -108,7 +105,7 @@ 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 `message-lane` if the same +/// 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() diff --git a/relays/clients/substrate/Cargo.toml b/relays/clients/substrate/Cargo.toml index 13eb51c8f5b4e..3f62731d521de 100644 --- a/relays/clients/substrate/Cargo.toml +++ b/relays/clients/substrate/Cargo.toml @@ -19,7 +19,7 @@ rand = "0.7" # Bridge dependencies bp-header-chain = { path = "../../../primitives/header-chain" } -bp-message-lane = { path = "../../../primitives/message-lane" } +bp-messages = { path = "../../../primitives/messages" } bp-runtime = { path = "../../../primitives/runtime" } finality-relay = { path = "../../generic/finality" } headers-relay = { path = "../../generic/headers" } diff --git a/relays/clients/substrate/src/client.rs b/relays/clients/substrate/src/client.rs index 8332813042896..56fcb33bf92cb 100644 --- a/relays/clients/substrate/src/client.rs +++ b/relays/clients/substrate/src/client.rs @@ -17,10 +17,10 @@ //! Substrate node client. use crate::chain::{Chain, ChainWithBalances}; -use crate::rpc::{Substrate, SubstrateMessageLane}; +use crate::rpc::{Substrate, SubstrateMessages}; use crate::{ConnectionParams, Error, Result}; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::Decode; use frame_system::AccountInfo; @@ -228,7 +228,7 @@ impl Client { include_outbound_lane_state: bool, at_block: C::Hash, ) -> Result { - let encoded_trie_nodes = SubstrateMessageLane::::prove_messages( + let encoded_trie_nodes = SubstrateMessages::::prove_messages( &self.client, instance, lane, @@ -252,7 +252,7 @@ impl Client { at_block: C::Hash, ) -> Result>> { let encoded_trie_nodes = - SubstrateMessageLane::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) + SubstrateMessages::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) .await .map_err(Error::RpcError)?; let decoded_trie_nodes: Vec> = diff --git a/relays/clients/substrate/src/rpc.rs b/relays/clients/substrate/src/rpc.rs index 98b95750028cd..fcc3e9dd890ce 100644 --- a/relays/clients/substrate/src/rpc.rs +++ b/relays/clients/substrate/src/rpc.rs @@ -18,7 +18,7 @@ use crate::chain::Chain; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use sc_rpc_api::system::Health; use sp_core::{ @@ -51,8 +51,8 @@ jsonrpsee_proc_macros::rpc_client_api! { fn runtime_version() -> RuntimeVersion; } - pub(crate) SubstrateMessageLane { - #[rpc(method = "messageLane_proveMessages", positional_params)] + pub(crate) SubstrateMessages { + #[rpc(method = "messages_proveMessages", positional_params)] fn prove_messages( instance: InstanceId, lane: LaneId, @@ -62,7 +62,7 @@ jsonrpsee_proc_macros::rpc_client_api! { block: Option, ) -> Bytes; - #[rpc(method = "messageLane_proveMessagesDelivery", positional_params)] + #[rpc(method = "messages_proveMessagesDelivery", positional_params)] fn prove_messages_delivery( instance: InstanceId, lane: LaneId, diff --git a/relays/generic/messages/Cargo.toml b/relays/generic/messages/Cargo.toml index 427fe4829d7be..e5bd7efaca88e 100644 --- a/relays/generic/messages/Cargo.toml +++ b/relays/generic/messages/Cargo.toml @@ -15,5 +15,5 @@ parking_lot = "0.11.0" # Bridge Dependencies -bp-message-lane = { path = "../../../primitives/message-lane" } +bp-messages = { path = "../../../primitives/messages" } relay-utils = { path = "../utils" } diff --git a/relays/generic/messages/src/lib.rs b/relays/generic/messages/src/lib.rs index 99222f0e02fbc..facb82ac8e7fa 100644 --- a/relays/generic/messages/src/lib.rs +++ b/relays/generic/messages/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Relaying [`message-lane`](../pallet_message_lane/index.html) application specific +//! Relaying [`pallet-bridge-messages`](../pallet_bridge_messages/index.html) application specific //! data. Message lane allows sending arbitrary messages between bridged chains. This //! module provides entrypoint that starts reading messages from given message lane //! of source chain and submits proof-of-message-at-source-chain transactions to the diff --git a/relays/generic/messages/src/message_lane_loop.rs b/relays/generic/messages/src/message_lane_loop.rs index afbaf7a015a45..dd4cd176dfce4 100644 --- a/relays/generic/messages/src/message_lane_loop.rs +++ b/relays/generic/messages/src/message_lane_loop.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Message delivery loop. Designed to work with message-lane pallet. +//! Message delivery loop. Designed to work with messages pallet. //! //! Single relay instance delivers messages of single lane in single direction. //! To serve two-way lane, you would need two instances of relay. @@ -30,7 +30,7 @@ use crate::message_race_receiving::run as run_message_receiving_race; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, diff --git a/relays/generic/messages/src/message_race_delivery.rs b/relays/generic/messages/src/message_race_delivery.rs index c7e308fee1e18..1ee39c9c9f908 100644 --- a/relays/generic/messages/src/message_race_delivery.rs +++ b/relays/generic/messages/src/message_race_delivery.rs @@ -26,7 +26,7 @@ use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; -use bp_message_lane::{MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; use futures::stream::FusedStream; use relay_utils::FailedClient; use std::{ diff --git a/relays/generic/messages/src/message_race_loop.rs b/relays/generic/messages/src/message_race_loop.rs index a11a1d7ff5dde..2c04466f1fb5f 100644 --- a/relays/generic/messages/src/message_race_loop.rs +++ b/relays/generic/messages/src/message_race_loop.rs @@ -23,7 +23,7 @@ use crate::message_lane_loop::ClientState; use async_trait::async_trait; -use bp_message_lane::MessageNonce; +use bp_messages::MessageNonce; use futures::{ future::FutureExt, stream::{FusedStream, StreamExt}, diff --git a/relays/generic/messages/src/message_race_receiving.rs b/relays/generic/messages/src/message_race_receiving.rs index cba6ee385893c..0fc025abb7d1a 100644 --- a/relays/generic/messages/src/message_race_receiving.rs +++ b/relays/generic/messages/src/message_race_receiving.rs @@ -25,7 +25,7 @@ use crate::message_race_strategy::BasicStrategy; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; -use bp_message_lane::MessageNonce; +use bp_messages::MessageNonce; use futures::stream::FusedStream; use relay_utils::FailedClient; use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; diff --git a/relays/generic/messages/src/message_race_strategy.rs b/relays/generic/messages/src/message_race_strategy.rs index dcbcbc4d377e0..fbc7877a3ab6b 100644 --- a/relays/generic/messages/src/message_race_strategy.rs +++ b/relays/generic/messages/src/message_race_strategy.rs @@ -19,7 +19,7 @@ use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces}; -use bp_message_lane::MessageNonce; +use bp_messages::MessageNonce; use relay_utils::HeaderId; use std::{collections::VecDeque, fmt::Debug, marker::PhantomData, ops::RangeInclusive}; diff --git a/relays/generic/messages/src/metrics.rs b/relays/generic/messages/src/metrics.rs index b001d32926ddb..3f4cbfa3047d8 100644 --- a/relays/generic/messages/src/metrics.rs +++ b/relays/generic/messages/src/metrics.rs @@ -19,7 +19,7 @@ use crate::message_lane::MessageLane; use crate::message_lane_loop::{SourceClientState, TargetClientState}; -use bp_message_lane::MessageNonce; +use bp_messages::MessageNonce; use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; /// Message lane relay metrics. diff --git a/relays/substrate/Cargo.toml b/relays/substrate/Cargo.toml index e9e969930de02..be4f74fb3d9a8 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/substrate/Cargo.toml @@ -21,7 +21,7 @@ structopt = "0.3" bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chains/kusama" } -bp-message-lane = { path = "../../primitives/message-lane" } +bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chains/millau" } bp-polkadot = { path = "../../primitives/chains/polkadot" } bp-runtime = { path = "../../primitives/runtime" } @@ -35,7 +35,7 @@ messages-relay = { path = "../generic/messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } pallet-finality-verifier = { path = "../../modules/finality-verifier" } -pallet-message-lane = { path = "../../modules/message-lane" } +pallet-bridge-messages = { path = "../../modules/messages" } relay-kusama-client = { path = "../clients/kusama" } relay-millau-client = { path = "../clients/millau" } relay-polkadot-client = { path = "../clients/polkadot" } diff --git a/relays/substrate/src/cli.rs b/relays/substrate/src/cli.rs index a4296226e250e..d6623b671d1c5 100644 --- a/relays/substrate/src/cli.rs +++ b/relays/substrate/src/cli.rs @@ -16,7 +16,7 @@ //! Deal with CLI args of substrate-to-substrate relay. -use bp_message_lane::LaneId; +use bp_messages::LaneId; use codec::{Decode, Encode}; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; @@ -39,7 +39,7 @@ pub enum Command { RelayHeaders(RelayHeaders), /// Start messages relay between two chains. /// - /// Ties up to `MessageLane` pallets on both chains and starts relaying messages. + /// Ties up to `Messages` pallets on both chains and starts relaying messages. /// Requires the header relay to be already running. RelayMessages(RelayMessages), /// Initialize on-chain bridge pallet with current header data. @@ -48,7 +48,7 @@ pub enum Command { InitBridge(InitBridge), /// Send custom message over the bridge. /// - /// Allows interacting with the bridge by sending messages over `MessageLane` component. + /// Allows interacting with the bridge by sending messages over `Messages` component. /// The message is being sent to the source chain, delivered to the target chain and dispatched /// there. SendMessage(SendMessage), @@ -59,10 +59,10 @@ pub enum Command { EncodeCall(EncodeCall), /// Generate SCALE-encoded `MessagePayload` object that can be sent over selected bridge. /// - /// The `MessagePayload` can be then fed to `MessageLane::send_message` function and sent over + /// The `MessagePayload` can be then fed to `Messages::send_message` function and sent over /// the bridge. EncodeMessagePayload(EncodeMessagePayload), - /// Estimate Delivery and Dispatch Fee required for message submission to message lane. + /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. EstimateFee(EstimateFee), /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. DeriveAccount(DeriveAccount), diff --git a/relays/substrate/src/messages_lane.rs b/relays/substrate/src/messages_lane.rs index 78b5f5c024880..372b47f2a2635 100644 --- a/relays/substrate/src/messages_lane.rs +++ b/relays/substrate/src/messages_lane.rs @@ -18,7 +18,7 @@ use crate::messages_source::SubstrateMessagesProof; use crate::messages_target::SubstrateMessagesReceivingProof; use async_trait::async_trait; -use bp_message_lane::MessageNonce; +use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; @@ -121,7 +121,7 @@ where /// Returns maximal number of messages and their maximal cumulative dispatch weight, based /// on given chain parameters. -pub fn select_delivery_transaction_limits( +pub fn select_delivery_transaction_limits( max_extrinsic_weight: Weight, max_unconfirmed_messages_at_inbound_lane: MessageNonce, ) -> (MessageNonce, Weight) { @@ -161,11 +161,11 @@ pub fn select_delivery_transaction_limits mod tests { use super::*; - type RialtoToMillauMessageLaneWeights = pallet_message_lane::weights::RialtoWeight; + type RialtoToMillauMessagesWeights = pallet_bridge_messages::weights::RialtoWeight; #[test] fn select_delivery_transaction_limits_works() { - let (max_count, max_weight) = select_delivery_transaction_limits::( + let (max_count, max_weight) = select_delivery_transaction_limits::( bp_millau::max_extrinsic_weight(), bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); diff --git a/relays/substrate/src/messages_source.rs b/relays/substrate/src/messages_source.rs index db894df8c7ac6..607247f8c0033 100644 --- a/relays/substrate/src/messages_source.rs +++ b/relays/substrate/src/messages_source.rs @@ -21,7 +21,7 @@ use crate::messages_lane::SubstrateMessageLane; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::{Decode, Encode}; diff --git a/relays/substrate/src/messages_target.rs b/relays/substrate/src/messages_target.rs index db12be361f653..ec2d751d37785 100644 --- a/relays/substrate/src/messages_target.rs +++ b/relays/substrate/src/messages_target.rs @@ -22,7 +22,7 @@ use crate::messages_lane::SubstrateMessageLane; use crate::messages_source::read_client_state; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::InstanceId; use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use codec::{Decode, Encode}; diff --git a/relays/substrate/src/rialto_millau/cli.rs b/relays/substrate/src/rialto_millau/cli.rs index 86693331ded90..9c89e823430bf 100644 --- a/relays/substrate/src/rialto_millau/cli.rs +++ b/relays/substrate/src/rialto_millau/cli.rs @@ -323,7 +323,7 @@ fn format_err(err: String) -> anyhow::Error { anyhow::anyhow!(err) } -/// MessagePayload that can be delivered to message lane pallet on Millau. +/// MessagePayload that can be delivered to messages pallet on Millau. #[derive(StructOpt, Debug)] pub enum MillauToRialtoMessagePayload { /// Raw, SCALE-encoded `MessagePayload`. @@ -342,7 +342,7 @@ pub enum MillauToRialtoMessagePayload { }, } -/// MessagePayload that can be delivered to message lane pallet on Rialto. +/// MessagePayload that can be delivered to messages pallet on Rialto. #[derive(StructOpt, Debug)] pub enum RialtoToMillauMessagePayload { /// Raw, SCALE-encoded `MessagePayload`. @@ -384,12 +384,12 @@ pub enum ToRialtoMessage { #[structopt(long)] amount: bp_rialto::Balance, }, - /// A call to the Millau Bridge Message Lane pallet to send a message over the bridge. + /// A call to the Millau Bridge Messages pallet to send a message over the bridge. MillauSendMessage { /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. + /// Raw SCALE-encoded Message Payload to submit to the messages pallet. #[structopt(long)] payload: HexBytes, /// Declared delivery and dispatch fee in base source-chain currency units. @@ -421,12 +421,12 @@ pub enum ToMillauMessage { #[structopt(long)] amount: bp_millau::Balance, }, - /// A call to the Rialto Bridge Message Lane pallet to send a message over the bridge. + /// A call to the Rialto Bridge Messages pallet to send a message over the bridge. RialtoSendMessage { /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the message lane pallet. + /// Raw SCALE-encoded Message Payload to submit to the messages pallet. #[structopt(long)] payload: HexBytes, /// Declared delivery and dispatch fee in base source-chain currency units. diff --git a/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs index 08a0fe9c08806..5b6d080d5a741 100644 --- a/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -22,7 +22,7 @@ use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; @@ -66,7 +66,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); let nonce = self.source_client.next_account_index(account_id).await?; let call: millau_runtime::Call = - millau_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); + millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.source_client.genesis_hash(); let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign.signer, nonce, call); @@ -96,7 +96,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let messages_count = nonces_end - nonces_start + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call: rialto_runtime::Call = rialto_runtime::MessageLaneCall::receive_messages_proof( + let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, messages_count as _, @@ -148,7 +148,7 @@ pub async fn run( let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() as usize / 3; // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::>( bp_rialto::max_extrinsic_weight(), bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); diff --git a/relays/substrate/src/rialto_millau/mod.rs b/relays/substrate/src/rialto_millau/mod.rs index 45ef7e322af8b..82402d71d483a 100644 --- a/relays/substrate/src/rialto_millau/mod.rs +++ b/relays/substrate/src/rialto_millau/mod.rs @@ -261,9 +261,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { }) .await?; - let millau_call = millau_runtime::Call::BridgeRialtoMessageLane( - millau_runtime::MessageLaneCall::send_message(lane, payload, fee), - ); + let millau_call = millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( + lane, payload, fee, + )); let signed_millau_call = Millau::sign_transaction( *millau_client.genesis_hash(), @@ -317,9 +317,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { }) .await?; - let rialto_call = rialto_runtime::Call::BridgeMillauMessageLane( - rialto_runtime::MessageLaneCall::send_message(lane, payload, fee), - ); + let rialto_call = rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( + lane, payload, fee, + )); let signed_rialto_call = Rialto::sign_transaction( *rialto_client.genesis_hash(), @@ -442,7 +442,7 @@ async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { async fn estimate_message_delivery_and_dispatch_fee( client: &relay_substrate_client::Client, estimate_fee_method: &str, - lane: bp_message_lane::LaneId, + lane: bp_messages::LaneId, payload: P, ) -> Result, relay_substrate_client::Error> { let encoded_response = client @@ -747,7 +747,7 @@ impl cli::ToRialtoMessage { cli::ToRialtoMessage::MillauSendMessage { lane, payload, fee } => { let payload = cli::RialtoToMillauMessagePayload::Raw { data: payload }.into_payload()?; let lane = lane.into(); - rialto_runtime::Call::BridgeMillauMessageLane(rialto_runtime::MessageLaneCall::send_message( + rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( lane, payload, fee, )) } @@ -784,7 +784,7 @@ impl cli::ToMillauMessage { cli::ToMillauMessage::RialtoSendMessage { lane, payload, fee } => { let payload = cli::MillauToRialtoMessagePayload::Raw { data: payload }.into_payload()?; let lane = lane.into(); - millau_runtime::Call::BridgeRialtoMessageLane(millau_runtime::MessageLaneCall::send_message( + millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( lane, payload, fee, )) } @@ -801,7 +801,7 @@ impl cli::ToMillauMessage { #[cfg(test)] mod tests { use super::*; - use bp_message_lane::source_chain::TargetHeaderChain; + use bp_messages::source_chain::TargetHeaderChain; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; diff --git a/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs index b0ce256aa7669..df94c25f3ce60 100644 --- a/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -22,7 +22,7 @@ use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use async_trait::async_trait; -use bp_message_lane::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; @@ -66,7 +66,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); let nonce = self.source_client.next_account_index(account_id).await?; let call: rialto_runtime::Call = - rialto_runtime::MessageLaneCall::receive_messages_delivery_proof(proof, relayers_state).into(); + rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.source_client.genesis_hash(); let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign.signer, nonce, call); @@ -96,7 +96,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let messages_count = nonces_end - nonces_start + 1; let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call: millau_runtime::Call = millau_runtime::MessageLaneCall::receive_messages_proof( + let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, messages_count as _, @@ -147,7 +147,7 @@ pub async fn run( // 2/3 is reserved for proofs and tx overhead let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() as usize / 3; let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::>( bp_millau::max_extrinsic_weight(), bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); From b7515afaf47f79e4c5d2980fd8e58b1792e8359d Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 22 Mar 2021 15:32:48 -0400 Subject: [PATCH 0387/1210] Tunable Justification Generator (#835) * Add way to create tunable GRANDPA justifications * Use new function in tests * Allow multiple authorities on a single fork * Only store pre-commit targets instead of full ancestry chains * Rename precommit_header to be more generic * Push new digest item instead of overriding entire digest * Ensure that we generate chains with non-zero length * Extract justification creation parameters into struct * Appease Clippy --- modules/finality-verifier/src/lib.rs | 27 ++-- modules/substrate/src/fork_tests.rs | 6 +- modules/substrate/src/verifier.rs | 14 +- .../header-chain/tests/justification.rs | 71 ++++++++-- primitives/test-utils/src/lib.rs | 123 +++++++++++++++--- 5 files changed, 184 insertions(+), 57 deletions(-) diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 8c77745025c0a..4399d78a745da 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -522,7 +522,7 @@ mod tests { use super::*; use crate::mock::{run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime}; use bp_test_utils::{ - authority_list, keyring, make_justification_for_header, + authority_list, make_default_justification, make_justification_for_header, JustificationGeneratorParams, Keyring::{Alice, Bob}, }; use codec::Encode; @@ -551,10 +551,7 @@ mod tests { fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { let header = test_header(header.into()); - - let set_id = 1; - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); Module::::submit_finality_proof(Origin::signed(1), header, justification) } @@ -726,9 +723,11 @@ mod tests { let header = test_header(1); - let set_id = 2; - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let params = JustificationGeneratorParams:: { + set_id: 2, + ..Default::default() + }; + let justification = make_justification_for_header(params).encode(); assert_err!( Module::::submit_finality_proof(Origin::signed(1), header, justification,), @@ -802,9 +801,7 @@ mod tests { header.digest = change_log(0); // Create a valid justification for the header - let set_id = 1; - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); // Let's import our test header assert_ok!(Module::::submit_finality_proof( @@ -836,9 +833,7 @@ mod tests { header.digest = change_log(1); // Create a valid justification for the header - let set_id = 1; - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); // Should not be allowed to import this header assert_err!( @@ -859,9 +854,7 @@ mod tests { header.digest = forced_change_log(0); // Create a valid justification for the header - let set_id = 1; - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); // Should not be allowed to import this header assert_err!( diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index 9dc145b6412ef..acd147109a773 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -60,7 +60,7 @@ use crate::verifier::*; use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; use bp_header_chain::AuthoritySet; use bp_test_utils::{ - authority_list, keyring, make_justification_for_header, + authority_list, make_default_justification, Keyring::{Alice, Bob}, }; use codec::Encode; @@ -457,9 +457,7 @@ where // `grandpa_round`). // // See for more: https://github.com/paritytech/parity-bridges-common/issues/430 - let grandpa_round = 1; - let set_id = 1; - let justification = make_justification_for_header(header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(header).encode(); let res = verifier .import_finality_proof(header.hash(), justification.into()) diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 47647aafc52be..4849941124302 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -343,7 +343,7 @@ mod tests { use crate::mock::*; use crate::{BestFinalized, BestHeight, HeaderId, ImportedHeaders, PalletStorage}; use bp_test_utils::{ - authority_list, keyring, make_justification_for_header, + authority_list, make_default_justification, Keyring::{Alice, Bob}, }; use codec::Encode; @@ -605,8 +605,7 @@ mod tests { assert_eq!(storage.best_headers().len(), 1); // Now lets finalize our best header - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); // Our best header should only appear once in the list of best headers @@ -729,8 +728,7 @@ mod tests { storage.update_current_authority_set(authority_set); // We'll need this justification to finalize the header - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); let mut verifier = Verifier { storage: storage.clone(), @@ -754,8 +752,7 @@ mod tests { let authority_set = AuthoritySet { authorities, set_id }; storage.update_current_authority_set(authority_set); - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); let mut verifier = Verifier { storage: storage.clone(), @@ -798,8 +795,7 @@ mod tests { // This header enacts an authority set change upon finalization let header = test_header(2); - let grandpa_round = 1; - let justification = make_justification_for_header(&header, grandpa_round, set_id, &keyring()).encode(); + let justification = make_default_justification(&header).encode(); // Schedule a change at the height of our header let set_id = 2; diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 74f3a39f26768..29ba744133fad 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -16,14 +16,55 @@ //! Tests for Grandpa Justification code. -use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; +use bp_header_chain::justification::{verify_justification, Error}; +use bp_test_utils::Keyring::*; use bp_test_utils::*; use codec::Encode; type TestHeader = sp_runtime::testing::Header; -fn make_justification_for_header_1() -> GrandpaJustification { - make_justification_for_header(&test_header(1), TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, &keyring()) +#[test] +fn valid_justification_accepted() { + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: vec![(Alice, 1), (Bob, 1), (Charlie, 1), (Dave, 1), (Eve, 1)], + depth: 5, + forks: 5, + }; + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &make_justification_for_header::(params).encode() + ), + Ok(()), + ); +} + +#[test] +fn valid_justification_accepted_with_single_fork() { + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: vec![(Alice, 1), (Bob, 1), (Charlie, 1), (Dave, 1), (Eve, 1)], + depth: 5, + forks: 1, + }; + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &make_justification_for_header::(params).encode() + ), + Ok(()), + ); } #[test] @@ -41,7 +82,7 @@ fn justification_with_invalid_target_rejected() { header_id::(2), TEST_GRANDPA_SET_ID, &voter_set(), - &make_justification_for_header_1().encode(), + &make_default_justification::(&test_header(1)).encode(), ), Err(Error::InvalidJustificationTarget), ); @@ -49,7 +90,7 @@ fn justification_with_invalid_target_rejected() { #[test] fn justification_with_invalid_commit_rejected() { - let mut justification = make_justification_for_header_1(); + let mut justification = make_default_justification::(&test_header(1)); justification.commit.precommits.clear(); assert_eq!( @@ -65,7 +106,7 @@ fn justification_with_invalid_commit_rejected() { #[test] fn justification_with_invalid_authority_signature_rejected() { - let mut justification = make_justification_for_header_1(); + let mut justification = make_default_justification::(&test_header(1)); justification.commit.precommits[0].signature = Default::default(); assert_eq!( @@ -81,7 +122,7 @@ fn justification_with_invalid_authority_signature_rejected() { #[test] fn justification_with_invalid_precommit_ancestry() { - let mut justification = make_justification_for_header_1(); + let mut justification = make_default_justification::(&test_header(1)); justification.votes_ancestries.push(test_header(10)); assert_eq!( @@ -96,14 +137,24 @@ fn justification_with_invalid_precommit_ancestry() { } #[test] -fn valid_justification_accepted() { +fn justification_is_invalid_if_we_dont_meet_threshold() { + // Need at least three authorities to sign off or else the voter set threshold can't be reached + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: vec![(Alice, 1), (Bob, 1)], + depth: 2, + forks: 2, + }; + assert_eq!( verify_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &make_justification_for_header_1().encode(), + &make_justification_for_header::(params).encode() ), - Ok(()), + Err(Error::InvalidJustificationCommit), ); } diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 499d1a5a21cce..31dabde5ea766 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -31,29 +31,95 @@ use sp_std::prelude::*; pub const TEST_GRANDPA_ROUND: u64 = 1; pub const TEST_GRANDPA_SET_ID: SetId = 1; -/// Get a valid Grandpa justification for a header given a Grandpa round, authority set ID, and -/// authority list. -pub fn make_justification_for_header( - header: &H, - round: u64, - set_id: SetId, - authorities: &[(Keyring, AuthorityWeight)], -) -> GrandpaJustification { +/// Configuration parameters when generating test GRANDPA justifications. +pub struct JustificationGeneratorParams { + /// The header which we want to finalize. + pub header: H, + /// The GRANDPA round number for the current authority set. + pub round: u64, + /// The current authority set ID. + pub set_id: SetId, + /// The current GRANDPA authority set. + pub authorities: Vec<(Keyring, AuthorityWeight)>, + /// The number of headers included in our justification's vote ancestries. + pub depth: u32, + /// The number of forks, and thus the number of pre-commits in our justification. + pub forks: u32, +} + +impl Default for JustificationGeneratorParams { + fn default() -> Self { + Self { + header: test_header(One::one()), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: keyring(), + depth: 2, + forks: 1, + } + } +} + +/// Make a valid GRANDPA justification with sensible defaults +pub fn make_default_justification(header: &H) -> GrandpaJustification { + let params = JustificationGeneratorParams:: { + header: header.clone(), + ..Default::default() + }; + + make_justification_for_header(params) +} + +/// Generate justifications in a way where we are able to tune the number of pre-commits +/// and vote ancestries which are included in the justification. +/// +/// This is useful for benchmarkings where we want to generate valid justifications with +/// a specific number of pre-commits (tuned with the "forks" parameter) and/or a specific +/// number of vote ancestries (tuned with the "depth" parameter). +/// +/// Note: This needs at least three authorities or else the verifier will complain about +/// being given an invalid commit. +pub fn make_justification_for_header(params: JustificationGeneratorParams) -> GrandpaJustification { + let JustificationGeneratorParams { + header, + round, + set_id, + authorities, + depth, + forks, + } = params; + let (target_hash, target_number) = (header.hash(), *header.number()); let mut precommits = vec![]; let mut votes_ancestries = vec![]; - // We want to make sure that the header included in the vote ancestries - // is actually related to our target header - let mut precommit_header = test_header::(target_number + One::one()); - precommit_header.set_parent_hash(target_hash); + assert!(depth != 0, "Can't have a chain of zero length."); + assert!( + forks as usize <= authorities.len(), + "If we have more forks than authorities we can't create valid pre-commits for all the forks." + ); + + let mut unsigned_precommits = vec![]; + for i in 0..forks { + let chain = generate_chain(i as u8, depth, &header); + + // We don't include our finality target header in the vote ancestries + for child in &chain[1..] { + votes_ancestries.push(child.clone()); + } + + // The header we need to use when pre-commiting is the one at the highest height + // on our chain. + let precommit_candidate = chain.last().map(|h| (h.hash(), *h.number())).unwrap(); + unsigned_precommits.push(precommit_candidate); + } + + for (i, (id, _weight)) in authorities.iter().enumerate() { + // Assign authorities to sign pre-commits in a round-robin fashion + let target = unsigned_precommits[i % forks as usize]; + let precommit = signed_precommit::(&id, target, round, set_id); - // I'm using the same header for all the voters since it doesn't matter as long - // as they all vote on blocks _ahead_ of the one we're interested in finalizing - for (id, _weight) in authorities.iter() { - let precommit = signed_precommit::(id, (precommit_header.hash(), *precommit_header.number()), round, set_id); precommits.push(precommit); - votes_ancestries.push(precommit_header.clone()); } GrandpaJustification { @@ -67,6 +133,29 @@ pub fn make_justification_for_header( } } +fn generate_chain(fork_id: u8, depth: u32, ancestor: &H) -> Vec { + let mut headers = vec![ancestor.clone()]; + + for i in 1..depth { + let parent = &headers[(i - 1) as usize]; + let (hash, num) = (parent.hash(), *parent.number()); + + let mut header = test_header::(num + One::one()); + header.set_parent_hash(hash); + + // Modifying the digest so headers at the same height but in different forks have different + // hashes + header + .digest_mut() + .logs + .push(sp_runtime::DigestItem::Other(vec![fork_id])); + + headers.push(header); + } + + headers +} + fn signed_precommit( signer: &Keyring, target: (H::Hash, H::Number), From 6dacb043a742ce23565b734cb30e5b43cae7794f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 23 Mar 2021 09:50:13 +0300 Subject: [PATCH 0388/1210] Westend->Millau headers relay in deployments (#831) * reorganize monitoring * Westend->Millau bridge * support multiple bridges * initialize Westend -> Millau bridge byMillau.George * fix intersecting ports * ignore dashboards * single bridged network * deal with multple --env-file args * fix chain name * use images from docker hub * update show_help * updated comment * mount whole dashboards directory * removed unneeded network * reverted reverse-proxy changes * prometheus -> targets * separate Grafana.Dockerfile with builtin /etc/grafana * Revert "separate Grafana.Dockerfile with builtin /etc/grafana" This reverts commit 53e04c4556f882d19e3af0fac581a926b8e0c167. * read dashboards from /etc/grafana/dashboards * stop comment --- bin/millau/node/src/chain_spec.rs | 11 +++++++++-- bin/millau/runtime/src/lib.rs | 2 +- modules/finality-verifier/src/lib.rs | 6 ++++-- relays/substrate/src/rialto_millau/mod.rs | 5 ++++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index ac9a873f4f24f..a9f977f6371a9 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -16,8 +16,8 @@ use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, GenesisConfig, GrandpaConfig, SessionConfig, - SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, BridgeWestendFinalityVerifierConfig, GenesisConfig, + GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -179,6 +179,13 @@ fn testnet_genesis( .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), }), + pallet_finality_verifier_Instance1: Some(BridgeWestendFinalityVerifierConfig { + // for our deployments to avoid multiple same-nonces transactions: + // //Alice is already used to initialize Rialto<->Millau bridge + // => let's use //George to initialize Westend->Millau bridge + owner: Some(get_account_id_from_seed::("George")), + ..Default::default() + }), } } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 0be3642dec383..f9c534bf56e71 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -380,7 +380,7 @@ construct_runtime!( BridgeRialtoMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, BridgeRialtoFinalityVerifier: pallet_finality_verifier::{Module, Call}, - BridgeWestendFinalityVerifier: pallet_finality_verifier::::{Module, Call}, + BridgeWestendFinalityVerifier: pallet_finality_verifier::::{Module, Call, Config}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, diff --git a/modules/finality-verifier/src/lib.rs b/modules/finality-verifier/src/lib.rs index 4399d78a745da..7e6b8a83536c8 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/finality-verifier/src/lib.rs @@ -256,8 +256,10 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { - owner: Option, - init_data: Option>>, + /// Optional module owner account. + pub owner: Option, + /// Optional module initialization data. + pub init_data: Option>>, } #[cfg(feature = "std")] diff --git a/relays/substrate/src/rialto_millau/mod.rs b/relays/substrate/src/rialto_millau/mod.rs index 82402d71d483a..be7d20debfda3 100644 --- a/relays/substrate/src/rialto_millau/mod.rs +++ b/relays/substrate/src/rialto_millau/mod.rs @@ -115,6 +115,9 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { .next_account_index(millau_sign.signer.public().into()) .await?; + // at Westend -> Millau initialization we're not using sudo, because otherwise our deployments + // may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge. + // => since there's single possible sudo account, one of transaction may fail with duplicate nonce error crate::headers_initialize::initialize(westend_client, millau_client.clone(), move |initialization_data| { let initialize_call = millau_runtime::FinalityBridgeWestendCall::< millau_runtime::Runtime, @@ -126,7 +129,7 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { *millau_client.genesis_hash(), &millau_sign.signer, millau_signer_next_index, - millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into(), + initialize_call.into(), ) .encode(), )) From 59eaa224de9fc1e2d2bf0a6e421e532477f47bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 23 Mar 2021 14:17:33 +0100 Subject: [PATCH 0389/1210] Flatten back the structure (#837) * Remove chains. * Move relay clients. * Flatten generic. * Fix fmt. --- bin/millau/node/Cargo.toml | 2 +- bin/millau/runtime/Cargo.toml | 8 ++--- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 4 +-- modules/messages/Cargo.toml | 2 +- .../kusama => chain-kusama}/Cargo.toml | 6 ++-- .../kusama => chain-kusama}/src/lib.rs | 0 .../millau => chain-millau}/Cargo.toml | 4 +-- .../millau => chain-millau}/src/lib.rs | 0 .../src/millau_hash.rs | 0 .../polkadot => chain-polkadot}/Cargo.toml | 6 ++-- .../polkadot => chain-polkadot}/src/lib.rs | 0 .../rialto => chain-rialto}/Cargo.toml | 4 +-- .../rialto => chain-rialto}/src/lib.rs | 0 .../rococo => chain-rococo}/Cargo.toml | 6 ++-- .../rococo => chain-rococo}/src/lib.rs | 2 +- .../westend => chain-westend}/Cargo.toml | 6 ++-- .../westend => chain-westend}/src/lib.rs | 0 relays/{ethereum => bin-ethereum}/Cargo.toml | 14 ++++---- relays/{ethereum => bin-ethereum}/README.md | 0 .../res/substrate-bridge-abi.json | 0 .../res/substrate-bridge-bytecode.hex | 0 .../res/substrate-bridge-metadata.txt | 0 relays/{ethereum => bin-ethereum}/src/cli.yml | 0 .../src/ethereum_client.rs | 0 .../src/ethereum_deploy_contract.rs | 0 .../src/ethereum_exchange.rs | 0 .../src/ethereum_exchange_submit.rs | 0 .../src/ethereum_sync_loop.rs | 0 .../src/instances.rs | 0 relays/{ethereum => bin-ethereum}/src/main.rs | 0 .../src/rialto_client.rs | 0 .../src/rpc_errors.rs | 0 .../src/substrate_sync_loop.rs | 0 .../src/substrate_types.rs | 0 .../{substrate => bin-substrate}/Cargo.toml | 32 +++++++++---------- .../{substrate => bin-substrate}/src/cli.rs | 0 .../src/finality_pipeline.rs | 0 .../src/finality_target.rs | 0 .../src/headers_initialize.rs | 0 .../{substrate => bin-substrate}/src/main.rs | 0 .../src/messages_lane.rs | 0 .../src/messages_source.rs | 0 .../src/messages_target.rs | 0 .../src/rialto_millau/cli.rs | 0 .../rialto_millau/millau_headers_to_rialto.rs | 0 .../millau_messages_to_rialto.rs | 0 .../src/rialto_millau/mod.rs | 0 .../rialto_millau/rialto_headers_to_millau.rs | 0 .../rialto_messages_to_millau.rs | 0 .../westend_headers_to_millau.rs | 0 .../ethereum => client-ethereum}/Cargo.toml | 6 ++-- .../src/client.rs | 0 .../ethereum => client-ethereum}/src/error.rs | 0 .../ethereum => client-ethereum}/src/lib.rs | 0 .../ethereum => client-ethereum}/src/rpc.rs | 0 .../ethereum => client-ethereum}/src/sign.rs | 0 .../ethereum => client-ethereum}/src/types.rs | 0 .../kusama => client-kusama}/Cargo.toml | 8 ++--- .../kusama => client-kusama}/src/lib.rs | 0 .../millau => client-millau}/Cargo.toml | 8 ++--- .../millau => client-millau}/src/lib.rs | 0 .../polkadot => client-polkadot}/Cargo.toml | 8 ++--- .../polkadot => client-polkadot}/src/lib.rs | 0 .../rialto => client-rialto}/Cargo.toml | 8 ++--- .../rialto => client-rialto}/src/lib.rs | 0 .../substrate => client-substrate}/Cargo.toml | 12 +++---- .../src/chain.rs | 0 .../src/client.rs | 0 .../src/error.rs | 0 .../src/finality_source.rs | 0 .../src/guard.rs | 0 .../src/headers_source.rs | 0 .../substrate => client-substrate}/src/lib.rs | 0 .../substrate => client-substrate}/src/rpc.rs | 0 .../src/sync_header.rs | 0 .../westend => client-westend}/Cargo.toml | 8 ++--- .../westend => client-westend}/src/lib.rs | 0 relays/{generic => }/exchange/Cargo.toml | 0 relays/{generic => }/exchange/src/exchange.rs | 0 .../exchange/src/exchange_loop.rs | 4 +-- .../exchange/src/exchange_loop_metrics.rs | 0 relays/{generic => }/exchange/src/lib.rs | 0 relays/{generic => }/finality/Cargo.toml | 0 .../finality/src/finality_loop.rs | 0 .../finality/src/finality_loop_tests.rs | 4 +-- relays/{generic => }/finality/src/lib.rs | 0 relays/{generic => }/headers/Cargo.toml | 0 relays/{generic => }/headers/src/headers.rs | 0 relays/{generic => }/headers/src/lib.rs | 0 relays/{generic => }/headers/src/sync.rs | 0 relays/{generic => }/headers/src/sync_loop.rs | 0 .../headers/src/sync_loop_metrics.rs | 0 .../headers/src/sync_loop_tests.rs | 4 +-- .../{generic => }/headers/src/sync_types.rs | 0 relays/{generic => }/messages/Cargo.toml | 2 +- relays/{generic => }/messages/src/lib.rs | 0 .../messages/src/message_lane.rs | 0 .../messages/src/message_lane_loop.rs | 3 +- .../messages/src/message_race_delivery.rs | 0 .../messages/src/message_race_loop.rs | 0 .../messages/src/message_race_receiving.rs | 0 .../messages/src/message_race_strategy.rs | 0 relays/{generic => }/messages/src/metrics.rs | 0 relays/{generic => }/utils/Cargo.toml | 0 relays/{generic => }/utils/src/initialize.rs | 0 relays/{generic => }/utils/src/lib.rs | 0 relays/{generic => }/utils/src/metrics.rs | 0 relays/{generic => }/utils/src/relay_loop.rs | 0 109 files changed, 87 insertions(+), 86 deletions(-) rename primitives/{chains/kusama => chain-kusama}/Cargo.toml (75%) rename primitives/{chains/kusama => chain-kusama}/src/lib.rs (100%) rename primitives/{chains/millau => chain-millau}/Cargo.toml (93%) rename primitives/{chains/millau => chain-millau}/src/lib.rs (100%) rename primitives/{chains/millau => chain-millau}/src/millau_hash.rs (100%) rename primitives/{chains/polkadot => chain-polkadot}/Cargo.toml (75%) rename primitives/{chains/polkadot => chain-polkadot}/src/lib.rs (100%) rename primitives/{chains/rialto => chain-rialto}/Cargo.toml (89%) rename primitives/{chains/rialto => chain-rialto}/src/lib.rs (100%) rename primitives/{chains/rococo => chain-rococo}/Cargo.toml (75%) rename primitives/{chains/rococo => chain-rococo}/src/lib.rs (98%) rename primitives/{chains/westend => chain-westend}/Cargo.toml (75%) rename primitives/{chains/westend => chain-westend}/src/lib.rs (100%) rename relays/{ethereum => bin-ethereum}/Cargo.toml (82%) rename relays/{ethereum => bin-ethereum}/README.md (100%) rename relays/{ethereum => bin-ethereum}/res/substrate-bridge-abi.json (100%) rename relays/{ethereum => bin-ethereum}/res/substrate-bridge-bytecode.hex (100%) rename relays/{ethereum => bin-ethereum}/res/substrate-bridge-metadata.txt (100%) rename relays/{ethereum => bin-ethereum}/src/cli.yml (100%) rename relays/{ethereum => bin-ethereum}/src/ethereum_client.rs (100%) rename relays/{ethereum => bin-ethereum}/src/ethereum_deploy_contract.rs (100%) rename relays/{ethereum => bin-ethereum}/src/ethereum_exchange.rs (100%) rename relays/{ethereum => bin-ethereum}/src/ethereum_exchange_submit.rs (100%) rename relays/{ethereum => bin-ethereum}/src/ethereum_sync_loop.rs (100%) rename relays/{ethereum => bin-ethereum}/src/instances.rs (100%) rename relays/{ethereum => bin-ethereum}/src/main.rs (100%) rename relays/{ethereum => bin-ethereum}/src/rialto_client.rs (100%) rename relays/{ethereum => bin-ethereum}/src/rpc_errors.rs (100%) rename relays/{ethereum => bin-ethereum}/src/substrate_sync_loop.rs (100%) rename relays/{ethereum => bin-ethereum}/src/substrate_types.rs (100%) rename relays/{substrate => bin-substrate}/Cargo.toml (66%) rename relays/{substrate => bin-substrate}/src/cli.rs (100%) rename relays/{substrate => bin-substrate}/src/finality_pipeline.rs (100%) rename relays/{substrate => bin-substrate}/src/finality_target.rs (100%) rename relays/{substrate => bin-substrate}/src/headers_initialize.rs (100%) rename relays/{substrate => bin-substrate}/src/main.rs (100%) rename relays/{substrate => bin-substrate}/src/messages_lane.rs (100%) rename relays/{substrate => bin-substrate}/src/messages_source.rs (100%) rename relays/{substrate => bin-substrate}/src/messages_target.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/cli.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/millau_headers_to_rialto.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/millau_messages_to_rialto.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/mod.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/rialto_headers_to_millau.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/rialto_messages_to_millau.rs (100%) rename relays/{substrate => bin-substrate}/src/rialto_millau/westend_headers_to_millau.rs (100%) rename relays/{clients/ethereum => client-ethereum}/Cargo.toml (79%) rename relays/{clients/ethereum => client-ethereum}/src/client.rs (100%) rename relays/{clients/ethereum => client-ethereum}/src/error.rs (100%) rename relays/{clients/ethereum => client-ethereum}/src/lib.rs (100%) rename relays/{clients/ethereum => client-ethereum}/src/rpc.rs (100%) rename relays/{clients/ethereum => client-ethereum}/src/sign.rs (100%) rename relays/{clients/ethereum => client-ethereum}/src/types.rs (100%) rename relays/{clients/kusama => client-kusama}/Cargo.toml (80%) rename relays/{clients/kusama => client-kusama}/src/lib.rs (100%) rename relays/{clients/millau => client-millau}/Cargo.toml (79%) rename relays/{clients/millau => client-millau}/src/lib.rs (100%) rename relays/{clients/polkadot => client-polkadot}/Cargo.toml (79%) rename relays/{clients/polkadot => client-polkadot}/src/lib.rs (100%) rename relays/{clients/rialto => client-rialto}/Cargo.toml (80%) rename relays/{clients/rialto => client-rialto}/src/lib.rs (100%) rename relays/{clients/substrate => client-substrate}/Cargo.toml (80%) rename relays/{clients/substrate => client-substrate}/src/chain.rs (100%) rename relays/{clients/substrate => client-substrate}/src/client.rs (100%) rename relays/{clients/substrate => client-substrate}/src/error.rs (100%) rename relays/{clients/substrate => client-substrate}/src/finality_source.rs (100%) rename relays/{clients/substrate => client-substrate}/src/guard.rs (100%) rename relays/{clients/substrate => client-substrate}/src/headers_source.rs (100%) rename relays/{clients/substrate => client-substrate}/src/lib.rs (100%) rename relays/{clients/substrate => client-substrate}/src/rpc.rs (100%) rename relays/{clients/substrate => client-substrate}/src/sync_header.rs (100%) rename relays/{clients/westend => client-westend}/Cargo.toml (79%) rename relays/{clients/westend => client-westend}/src/lib.rs (100%) rename relays/{generic => }/exchange/Cargo.toml (100%) rename relays/{generic => }/exchange/src/exchange.rs (100%) rename relays/{generic => }/exchange/src/exchange_loop.rs (99%) rename relays/{generic => }/exchange/src/exchange_loop_metrics.rs (100%) rename relays/{generic => }/exchange/src/lib.rs (100%) rename relays/{generic => }/finality/Cargo.toml (100%) rename relays/{generic => }/finality/src/finality_loop.rs (100%) rename relays/{generic => }/finality/src/finality_loop_tests.rs (99%) rename relays/{generic => }/finality/src/lib.rs (100%) rename relays/{generic => }/headers/Cargo.toml (100%) rename relays/{generic => }/headers/src/headers.rs (100%) rename relays/{generic => }/headers/src/lib.rs (100%) rename relays/{generic => }/headers/src/sync.rs (100%) rename relays/{generic => }/headers/src/sync_loop.rs (100%) rename relays/{generic => }/headers/src/sync_loop_metrics.rs (100%) rename relays/{generic => }/headers/src/sync_loop_tests.rs (99%) rename relays/{generic => }/headers/src/sync_types.rs (100%) rename relays/{generic => }/messages/Cargo.toml (86%) rename relays/{generic => }/messages/src/lib.rs (100%) rename relays/{generic => }/messages/src/message_lane.rs (100%) rename relays/{generic => }/messages/src/message_lane_loop.rs (99%) rename relays/{generic => }/messages/src/message_race_delivery.rs (100%) rename relays/{generic => }/messages/src/message_race_loop.rs (100%) rename relays/{generic => }/messages/src/message_race_receiving.rs (100%) rename relays/{generic => }/messages/src/message_race_strategy.rs (100%) rename relays/{generic => }/messages/src/metrics.rs (100%) rename relays/{generic => }/utils/Cargo.toml (100%) rename relays/{generic => }/utils/src/initialize.rs (100%) rename relays/{generic => }/utils/src/lib.rs (100%) rename relays/{generic => }/utils/src/metrics.rs (100%) rename relays/{generic => }/utils/src/relay_loop.rs (100%) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 5c09367b362e8..c71eb8bfe3191 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -16,7 +16,7 @@ structopt = "0.3.21" # Bridge dependencies bp-messages = { path = "../../../primitives/messages" } -bp-millau= { path = "../../../primitives/chains/millau" } +bp-millau= { path = "../../../primitives/chain-millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } pallet-bridge-messages = { path = "../../../modules/messages" } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index c95328b0a91f7..8dc08d33366af 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -16,14 +16,14 @@ serde = { version = "1.0.124", optional = true, features = ["derive"] } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } -bp-millau = { path = "../../../primitives/chains/millau", default-features = false } -bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } +bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } -bp-westend = { path = "../../../primitives/chains/westend", default-features = false } +bp-westend = { path = "../../../primitives/chain-westend", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } -pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } +pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index a3bbd8c018fdf..fffbe9655a4ad 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ structopt = "0.3.21" bp-messages = { path = "../../../primitives/messages" } bp-runtime = { path = "../../../primitives/runtime" } -bp-rialto = { path = "../../../primitives/chains/rialto" } +bp-rialto = { path = "../../../primitives/chain-rialto" } pallet-bridge-messages = { path = "../../../modules/messages" } pallet-bridge-messages-rpc = { path = "../../../modules/messages/rpc" } rialto-runtime = { path = "../runtime" } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 536c90bce1823..3824f9cbc5e5c 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -21,8 +21,8 @@ bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = fal bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } -bp-millau = { path = "../../../primitives/chains/millau", default-features = false } -bp-rialto = { path = "../../../primitives/chains/rialto", default-features = false } +bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 19dc78af721e1..4a75fa8181f8a 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies bp-messages = { path = "../../primitives/messages", default-features = false } -bp-rialto = { path = "../../primitives/chains/rialto", default-features = false } +bp-rialto = { path = "../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies diff --git a/primitives/chains/kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml similarity index 75% rename from primitives/chains/kusama/Cargo.toml rename to primitives/chain-kusama/Cargo.toml index 15614a922babb..70ff3b844df07 100644 --- a/primitives/chains/kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-messages = { path = "../../messages", default-features = false } -bp-polkadot-core = { path = "../../polkadot-core", default-features = false } -bp-runtime = { path = "../../runtime", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } diff --git a/primitives/chains/kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs similarity index 100% rename from primitives/chains/kusama/src/lib.rs rename to primitives/chain-kusama/src/lib.rs diff --git a/primitives/chains/millau/Cargo.toml b/primitives/chain-millau/Cargo.toml similarity index 93% rename from primitives/chains/millau/Cargo.toml rename to primitives/chain-millau/Cargo.toml index ae27d2ce6287e..67db08c208608 100644 --- a/primitives/chains/millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -10,8 +10,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-messages = { path = "../../messages", default-features = false } -bp-runtime = { path = "../../runtime", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.5.0", default-features = false } diff --git a/primitives/chains/millau/src/lib.rs b/primitives/chain-millau/src/lib.rs similarity index 100% rename from primitives/chains/millau/src/lib.rs rename to primitives/chain-millau/src/lib.rs diff --git a/primitives/chains/millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs similarity index 100% rename from primitives/chains/millau/src/millau_hash.rs rename to primitives/chain-millau/src/millau_hash.rs diff --git a/primitives/chains/polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml similarity index 75% rename from primitives/chains/polkadot/Cargo.toml rename to primitives/chain-polkadot/Cargo.toml index 595fb149f4435..22ded41b9145c 100644 --- a/primitives/chains/polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-messages = { path = "../../messages", default-features = false } -bp-polkadot-core = { path = "../../polkadot-core", default-features = false } -bp-runtime = { path = "../../runtime", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chains/polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs similarity index 100% rename from primitives/chains/polkadot/src/lib.rs rename to primitives/chain-polkadot/src/lib.rs diff --git a/primitives/chains/rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml similarity index 89% rename from primitives/chains/rialto/Cargo.toml rename to primitives/chain-rialto/Cargo.toml index 6dbbe7549a39b..7e039a40acd96 100644 --- a/primitives/chains/rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -10,8 +10,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-messages = { path = "../../messages", default-features = false } -bp-runtime = { path = "../../runtime", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chains/rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs similarity index 100% rename from primitives/chains/rialto/src/lib.rs rename to primitives/chain-rialto/src/lib.rs diff --git a/primitives/chains/rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml similarity index 75% rename from primitives/chains/rococo/Cargo.toml rename to primitives/chain-rococo/Cargo.toml index db6bc121562d1..863203ad8d741 100644 --- a/primitives/chains/rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-messages = { path = "../../messages", default-features = false } -bp-polkadot-core = { path = "../../polkadot-core", default-features = false } -bp-runtime = { path = "../../runtime", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } diff --git a/primitives/chains/rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs similarity index 98% rename from primitives/chains/rococo/src/lib.rs rename to primitives/chain-rococo/src/lib.rs index b52049cd631e7..13a99347807e4 100644 --- a/primitives/chains/rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, Weight, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use sp_std::prelude::*; pub use bp_polkadot_core::*; diff --git a/primitives/chains/westend/Cargo.toml b/primitives/chain-westend/Cargo.toml similarity index 75% rename from primitives/chains/westend/Cargo.toml rename to primitives/chain-westend/Cargo.toml index 654f0291461b3..df8becd9596a5 100644 --- a/primitives/chains/westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies -bp-messages = { path = "../../messages", default-features = false } -bp-polkadot-core = { path = "../../polkadot-core", default-features = false } -bp-runtime = { path = "../../runtime", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } diff --git a/primitives/chains/westend/src/lib.rs b/primitives/chain-westend/src/lib.rs similarity index 100% rename from primitives/chains/westend/src/lib.rs rename to primitives/chain-westend/src/lib.rs diff --git a/relays/ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml similarity index 82% rename from relays/ethereum/Cargo.toml rename to relays/bin-ethereum/Cargo.toml index 1975830e5a5a4..efd9c0194b28c 100644 --- a/relays/ethereum/Cargo.toml +++ b/relays/bin-ethereum/Cargo.toml @@ -29,13 +29,13 @@ time = "0.2" bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } -exchange-relay = { path = "../generic/exchange" } -headers-relay = { path = "../generic/headers" } -messages-relay = { path = "../generic/messages" } -relay-ethereum-client = { path = "../clients/ethereum" } -relay-rialto-client = { path = "../clients/rialto" } -relay-substrate-client = { path = "../clients/substrate" } -relay-utils = { path = "../generic/utils" } +exchange-relay = { path = "../exchange" } +headers-relay = { path = "../headers" } +messages-relay = { path = "../messages" } +relay-ethereum-client = { path = "../client-ethereum" } +relay-rialto-client = { path = "../client-rialto" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/ethereum/README.md b/relays/bin-ethereum/README.md similarity index 100% rename from relays/ethereum/README.md rename to relays/bin-ethereum/README.md diff --git a/relays/ethereum/res/substrate-bridge-abi.json b/relays/bin-ethereum/res/substrate-bridge-abi.json similarity index 100% rename from relays/ethereum/res/substrate-bridge-abi.json rename to relays/bin-ethereum/res/substrate-bridge-abi.json diff --git a/relays/ethereum/res/substrate-bridge-bytecode.hex b/relays/bin-ethereum/res/substrate-bridge-bytecode.hex similarity index 100% rename from relays/ethereum/res/substrate-bridge-bytecode.hex rename to relays/bin-ethereum/res/substrate-bridge-bytecode.hex diff --git a/relays/ethereum/res/substrate-bridge-metadata.txt b/relays/bin-ethereum/res/substrate-bridge-metadata.txt similarity index 100% rename from relays/ethereum/res/substrate-bridge-metadata.txt rename to relays/bin-ethereum/res/substrate-bridge-metadata.txt diff --git a/relays/ethereum/src/cli.yml b/relays/bin-ethereum/src/cli.yml similarity index 100% rename from relays/ethereum/src/cli.yml rename to relays/bin-ethereum/src/cli.yml diff --git a/relays/ethereum/src/ethereum_client.rs b/relays/bin-ethereum/src/ethereum_client.rs similarity index 100% rename from relays/ethereum/src/ethereum_client.rs rename to relays/bin-ethereum/src/ethereum_client.rs diff --git a/relays/ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs similarity index 100% rename from relays/ethereum/src/ethereum_deploy_contract.rs rename to relays/bin-ethereum/src/ethereum_deploy_contract.rs diff --git a/relays/ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs similarity index 100% rename from relays/ethereum/src/ethereum_exchange.rs rename to relays/bin-ethereum/src/ethereum_exchange.rs diff --git a/relays/ethereum/src/ethereum_exchange_submit.rs b/relays/bin-ethereum/src/ethereum_exchange_submit.rs similarity index 100% rename from relays/ethereum/src/ethereum_exchange_submit.rs rename to relays/bin-ethereum/src/ethereum_exchange_submit.rs diff --git a/relays/ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs similarity index 100% rename from relays/ethereum/src/ethereum_sync_loop.rs rename to relays/bin-ethereum/src/ethereum_sync_loop.rs diff --git a/relays/ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs similarity index 100% rename from relays/ethereum/src/instances.rs rename to relays/bin-ethereum/src/instances.rs diff --git a/relays/ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs similarity index 100% rename from relays/ethereum/src/main.rs rename to relays/bin-ethereum/src/main.rs diff --git a/relays/ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs similarity index 100% rename from relays/ethereum/src/rialto_client.rs rename to relays/bin-ethereum/src/rialto_client.rs diff --git a/relays/ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs similarity index 100% rename from relays/ethereum/src/rpc_errors.rs rename to relays/bin-ethereum/src/rpc_errors.rs diff --git a/relays/ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs similarity index 100% rename from relays/ethereum/src/substrate_sync_loop.rs rename to relays/bin-ethereum/src/substrate_sync_loop.rs diff --git a/relays/ethereum/src/substrate_types.rs b/relays/bin-ethereum/src/substrate_types.rs similarity index 100% rename from relays/ethereum/src/substrate_types.rs rename to relays/bin-ethereum/src/substrate_types.rs diff --git a/relays/substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml similarity index 66% rename from relays/substrate/Cargo.toml rename to relays/bin-substrate/Cargo.toml index be4f74fb3d9a8..ff2a7fc6a2be2 100644 --- a/relays/substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -20,29 +20,29 @@ structopt = "0.3" # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } -bp-kusama = { path = "../../primitives/chains/kusama" } +bp-kusama = { path = "../../primitives/chain-kusama" } bp-messages = { path = "../../primitives/messages" } -bp-millau = { path = "../../primitives/chains/millau" } -bp-polkadot = { path = "../../primitives/chains/polkadot" } +bp-millau = { path = "../../primitives/chain-millau" } +bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-rialto = { path = "../../primitives/chain-rialto" } bp-runtime = { path = "../../primitives/runtime" } -bp-rialto = { path = "../../primitives/chains/rialto" } -bp-westend = { path = "../../primitives/chains/westend" } +bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-grandpa = { version = "0.14.0" } -finality-relay = { path = "../generic/finality" } -headers-relay = { path = "../generic/headers" } -messages-relay = { path = "../generic/messages" } +finality-relay = { path = "../finality" } +headers-relay = { path = "../headers" } +messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } -pallet-finality-verifier = { path = "../../modules/finality-verifier" } pallet-bridge-messages = { path = "../../modules/messages" } -relay-kusama-client = { path = "../clients/kusama" } -relay-millau-client = { path = "../clients/millau" } -relay-polkadot-client = { path = "../clients/polkadot" } -relay-rialto-client = { path = "../clients/rialto" } -relay-substrate-client = { path = "../clients/substrate" } -relay-westend-client = { path = "../clients/westend" } -relay-utils = { path = "../generic/utils" } +pallet-finality-verifier = { path = "../../modules/finality-verifier" } +relay-kusama-client = { path = "../client-kusama" } +relay-millau-client = { path = "../client-millau" } +relay-polkadot-client = { path = "../client-polkadot" } +relay-rialto-client = { path = "../client-rialto" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } +relay-westend-client = { path = "../client-westend" } rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/substrate/src/cli.rs b/relays/bin-substrate/src/cli.rs similarity index 100% rename from relays/substrate/src/cli.rs rename to relays/bin-substrate/src/cli.rs diff --git a/relays/substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs similarity index 100% rename from relays/substrate/src/finality_pipeline.rs rename to relays/bin-substrate/src/finality_pipeline.rs diff --git a/relays/substrate/src/finality_target.rs b/relays/bin-substrate/src/finality_target.rs similarity index 100% rename from relays/substrate/src/finality_target.rs rename to relays/bin-substrate/src/finality_target.rs diff --git a/relays/substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs similarity index 100% rename from relays/substrate/src/headers_initialize.rs rename to relays/bin-substrate/src/headers_initialize.rs diff --git a/relays/substrate/src/main.rs b/relays/bin-substrate/src/main.rs similarity index 100% rename from relays/substrate/src/main.rs rename to relays/bin-substrate/src/main.rs diff --git a/relays/substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs similarity index 100% rename from relays/substrate/src/messages_lane.rs rename to relays/bin-substrate/src/messages_lane.rs diff --git a/relays/substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs similarity index 100% rename from relays/substrate/src/messages_source.rs rename to relays/bin-substrate/src/messages_source.rs diff --git a/relays/substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs similarity index 100% rename from relays/substrate/src/messages_target.rs rename to relays/bin-substrate/src/messages_target.rs diff --git a/relays/substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs similarity index 100% rename from relays/substrate/src/rialto_millau/cli.rs rename to relays/bin-substrate/src/rialto_millau/cli.rs diff --git a/relays/substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs similarity index 100% rename from relays/substrate/src/rialto_millau/millau_headers_to_rialto.rs rename to relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs diff --git a/relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs similarity index 100% rename from relays/substrate/src/rialto_millau/millau_messages_to_rialto.rs rename to relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs diff --git a/relays/substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs similarity index 100% rename from relays/substrate/src/rialto_millau/mod.rs rename to relays/bin-substrate/src/rialto_millau/mod.rs diff --git a/relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs similarity index 100% rename from relays/substrate/src/rialto_millau/rialto_headers_to_millau.rs rename to relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs diff --git a/relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs similarity index 100% rename from relays/substrate/src/rialto_millau/rialto_messages_to_millau.rs rename to relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs diff --git a/relays/substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs similarity index 100% rename from relays/substrate/src/rialto_millau/westend_headers_to_millau.rs rename to relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs diff --git a/relays/clients/ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml similarity index 79% rename from relays/clients/ethereum/Cargo.toml rename to relays/client-ethereum/Cargo.toml index e0e1a778c7449..79f6ab0cf6feb 100644 --- a/relays/clients/ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -6,14 +6,14 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-eth-poa = { path = "../../../primitives/ethereum-poa" } +bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../../generic/headers" } +headers-relay = { path = "../headers" } hex-literal = "0.3" jsonrpsee-proc-macros = "0.2.0-alpha.2" jsonrpsee-types = "0.2.0-alpha.2" jsonrpsee-ws-client = "0.2.0-alpha.2" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" -relay-utils = { path = "../../generic/utils" } +relay-utils = { path = "../utils" } web3 = { version = "0.15", git = "https://github.com/tomusdrw/rust-web3", branch ="td-ethabi", default-features = false } diff --git a/relays/clients/ethereum/src/client.rs b/relays/client-ethereum/src/client.rs similarity index 100% rename from relays/clients/ethereum/src/client.rs rename to relays/client-ethereum/src/client.rs diff --git a/relays/clients/ethereum/src/error.rs b/relays/client-ethereum/src/error.rs similarity index 100% rename from relays/clients/ethereum/src/error.rs rename to relays/client-ethereum/src/error.rs diff --git a/relays/clients/ethereum/src/lib.rs b/relays/client-ethereum/src/lib.rs similarity index 100% rename from relays/clients/ethereum/src/lib.rs rename to relays/client-ethereum/src/lib.rs diff --git a/relays/clients/ethereum/src/rpc.rs b/relays/client-ethereum/src/rpc.rs similarity index 100% rename from relays/clients/ethereum/src/rpc.rs rename to relays/client-ethereum/src/rpc.rs diff --git a/relays/clients/ethereum/src/sign.rs b/relays/client-ethereum/src/sign.rs similarity index 100% rename from relays/clients/ethereum/src/sign.rs rename to relays/client-ethereum/src/sign.rs diff --git a/relays/clients/ethereum/src/types.rs b/relays/client-ethereum/src/types.rs similarity index 100% rename from relays/clients/ethereum/src/types.rs rename to relays/client-ethereum/src/types.rs diff --git a/relays/clients/kusama/Cargo.toml b/relays/client-kusama/Cargo.toml similarity index 80% rename from relays/clients/kusama/Cargo.toml rename to relays/client-kusama/Cargo.toml index e8e44ce2a87c0..b9c397bca6c01 100644 --- a/relays/clients/kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../../generic/headers" } -relay-substrate-client = { path = "../substrate" } -relay-utils = { path = "../../generic/utils" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } # Bridge dependencies -bp-kusama = { path = "../../../primitives/chains/kusama" } +bp-kusama = { path = "../../primitives/chain-kusama" } # Substrate Dependencies diff --git a/relays/clients/kusama/src/lib.rs b/relays/client-kusama/src/lib.rs similarity index 100% rename from relays/clients/kusama/src/lib.rs rename to relays/client-kusama/src/lib.rs diff --git a/relays/clients/millau/Cargo.toml b/relays/client-millau/Cargo.toml similarity index 79% rename from relays/clients/millau/Cargo.toml rename to relays/client-millau/Cargo.toml index f975022aea869..e16f06f8528b6 100644 --- a/relays/clients/millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../../generic/headers" } -relay-substrate-client = { path = "../../clients/substrate" } -relay-utils = { path = "../../generic/utils" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } # Supported Chains -millau-runtime = { path = "../../../bin/millau/runtime" } +millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies diff --git a/relays/clients/millau/src/lib.rs b/relays/client-millau/src/lib.rs similarity index 100% rename from relays/clients/millau/src/lib.rs rename to relays/client-millau/src/lib.rs diff --git a/relays/clients/polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml similarity index 79% rename from relays/clients/polkadot/Cargo.toml rename to relays/client-polkadot/Cargo.toml index b40397f194f34..b148745f5a987 100644 --- a/relays/clients/polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../../generic/headers" } -relay-substrate-client = { path = "../substrate" } -relay-utils = { path = "../../generic/utils" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } # Bridge dependencies -bp-polkadot = { path = "../../../primitives/chains/polkadot" } +bp-polkadot = { path = "../../primitives/chain-polkadot" } # Substrate Dependencies diff --git a/relays/clients/polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs similarity index 100% rename from relays/clients/polkadot/src/lib.rs rename to relays/client-polkadot/src/lib.rs diff --git a/relays/clients/rialto/Cargo.toml b/relays/client-rialto/Cargo.toml similarity index 80% rename from relays/clients/rialto/Cargo.toml rename to relays/client-rialto/Cargo.toml index 74aeb8c30f00b..88e8e12add401 100644 --- a/relays/clients/rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../../generic/headers" } -relay-substrate-client = { path = "../substrate" } -relay-utils = { path = "../../generic/utils" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } # Bridge dependencies -rialto-runtime = { path = "../../../bin/rialto/runtime" } +rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/clients/rialto/src/lib.rs b/relays/client-rialto/src/lib.rs similarity index 100% rename from relays/clients/rialto/src/lib.rs rename to relays/client-rialto/src/lib.rs diff --git a/relays/clients/substrate/Cargo.toml b/relays/client-substrate/Cargo.toml similarity index 80% rename from relays/clients/substrate/Cargo.toml rename to relays/client-substrate/Cargo.toml index 3f62731d521de..83252358a746d 100644 --- a/relays/clients/substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -18,12 +18,12 @@ rand = "0.7" # Bridge dependencies -bp-header-chain = { path = "../../../primitives/header-chain" } -bp-messages = { path = "../../../primitives/messages" } -bp-runtime = { path = "../../../primitives/runtime" } -finality-relay = { path = "../../generic/finality" } -headers-relay = { path = "../../generic/headers" } -relay-utils = { path = "../../generic/utils" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } +bp-runtime = { path = "../../primitives/runtime" } +finality-relay = { path = "../finality" } +headers-relay = { path = "../headers" } +relay-utils = { path = "../utils" } # Substrate Dependencies diff --git a/relays/clients/substrate/src/chain.rs b/relays/client-substrate/src/chain.rs similarity index 100% rename from relays/clients/substrate/src/chain.rs rename to relays/client-substrate/src/chain.rs diff --git a/relays/clients/substrate/src/client.rs b/relays/client-substrate/src/client.rs similarity index 100% rename from relays/clients/substrate/src/client.rs rename to relays/client-substrate/src/client.rs diff --git a/relays/clients/substrate/src/error.rs b/relays/client-substrate/src/error.rs similarity index 100% rename from relays/clients/substrate/src/error.rs rename to relays/client-substrate/src/error.rs diff --git a/relays/clients/substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs similarity index 100% rename from relays/clients/substrate/src/finality_source.rs rename to relays/client-substrate/src/finality_source.rs diff --git a/relays/clients/substrate/src/guard.rs b/relays/client-substrate/src/guard.rs similarity index 100% rename from relays/clients/substrate/src/guard.rs rename to relays/client-substrate/src/guard.rs diff --git a/relays/clients/substrate/src/headers_source.rs b/relays/client-substrate/src/headers_source.rs similarity index 100% rename from relays/clients/substrate/src/headers_source.rs rename to relays/client-substrate/src/headers_source.rs diff --git a/relays/clients/substrate/src/lib.rs b/relays/client-substrate/src/lib.rs similarity index 100% rename from relays/clients/substrate/src/lib.rs rename to relays/client-substrate/src/lib.rs diff --git a/relays/clients/substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs similarity index 100% rename from relays/clients/substrate/src/rpc.rs rename to relays/client-substrate/src/rpc.rs diff --git a/relays/clients/substrate/src/sync_header.rs b/relays/client-substrate/src/sync_header.rs similarity index 100% rename from relays/clients/substrate/src/sync_header.rs rename to relays/client-substrate/src/sync_header.rs diff --git a/relays/clients/westend/Cargo.toml b/relays/client-westend/Cargo.toml similarity index 79% rename from relays/clients/westend/Cargo.toml rename to relays/client-westend/Cargo.toml index d5d56154f3522..a408ae3a46daf 100644 --- a/relays/clients/westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -7,13 +7,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0" } -headers-relay = { path = "../../generic/headers" } -relay-substrate-client = { path = "../substrate" } -relay-utils = { path = "../../generic/utils" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } # Bridge dependencies -bp-westend = { path = "../../../primitives/chains/westend" } +bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies diff --git a/relays/clients/westend/src/lib.rs b/relays/client-westend/src/lib.rs similarity index 100% rename from relays/clients/westend/src/lib.rs rename to relays/client-westend/src/lib.rs diff --git a/relays/generic/exchange/Cargo.toml b/relays/exchange/Cargo.toml similarity index 100% rename from relays/generic/exchange/Cargo.toml rename to relays/exchange/Cargo.toml diff --git a/relays/generic/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs similarity index 100% rename from relays/generic/exchange/src/exchange.rs rename to relays/exchange/src/exchange.rs diff --git a/relays/generic/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs similarity index 99% rename from relays/generic/exchange/src/exchange_loop.rs rename to relays/exchange/src/exchange_loop.rs index f09ad7de41bb5..d3282d70f6642 100644 --- a/relays/generic/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -321,12 +321,12 @@ mod tests { } })); - run( + async_std::task::block_on(run( storage, source, target, None, exit_receiver.into_future().map(|(_, _)| ()), - ); + )); } } diff --git a/relays/generic/exchange/src/exchange_loop_metrics.rs b/relays/exchange/src/exchange_loop_metrics.rs similarity index 100% rename from relays/generic/exchange/src/exchange_loop_metrics.rs rename to relays/exchange/src/exchange_loop_metrics.rs diff --git a/relays/generic/exchange/src/lib.rs b/relays/exchange/src/lib.rs similarity index 100% rename from relays/generic/exchange/src/lib.rs rename to relays/exchange/src/lib.rs diff --git a/relays/generic/finality/Cargo.toml b/relays/finality/Cargo.toml similarity index 100% rename from relays/generic/finality/Cargo.toml rename to relays/finality/Cargo.toml diff --git a/relays/generic/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs similarity index 100% rename from relays/generic/finality/src/finality_loop.rs rename to relays/finality/src/finality_loop.rs diff --git a/relays/generic/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs similarity index 99% rename from relays/generic/finality/src/finality_loop_tests.rs rename to relays/finality/src/finality_loop_tests.rs index 53f5225ab7e33..64ab91420fb91 100644 --- a/relays/generic/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -202,13 +202,13 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync stall_timeout: Duration::from_secs(1), }; - run( + async_std::task::block_on(run( source_client, target_client, sync_params, None, exit_receiver.into_future().map(|(_, _)| ()), - ); + )); let clients_data = clients_data.lock().clone(); clients_data diff --git a/relays/generic/finality/src/lib.rs b/relays/finality/src/lib.rs similarity index 100% rename from relays/generic/finality/src/lib.rs rename to relays/finality/src/lib.rs diff --git a/relays/generic/headers/Cargo.toml b/relays/headers/Cargo.toml similarity index 100% rename from relays/generic/headers/Cargo.toml rename to relays/headers/Cargo.toml diff --git a/relays/generic/headers/src/headers.rs b/relays/headers/src/headers.rs similarity index 100% rename from relays/generic/headers/src/headers.rs rename to relays/headers/src/headers.rs diff --git a/relays/generic/headers/src/lib.rs b/relays/headers/src/lib.rs similarity index 100% rename from relays/generic/headers/src/lib.rs rename to relays/headers/src/lib.rs diff --git a/relays/generic/headers/src/sync.rs b/relays/headers/src/sync.rs similarity index 100% rename from relays/generic/headers/src/sync.rs rename to relays/headers/src/sync.rs diff --git a/relays/generic/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs similarity index 100% rename from relays/generic/headers/src/sync_loop.rs rename to relays/headers/src/sync_loop.rs diff --git a/relays/generic/headers/src/sync_loop_metrics.rs b/relays/headers/src/sync_loop_metrics.rs similarity index 100% rename from relays/generic/headers/src/sync_loop_metrics.rs rename to relays/headers/src/sync_loop_metrics.rs diff --git a/relays/generic/headers/src/sync_loop_tests.rs b/relays/headers/src/sync_loop_tests.rs similarity index 99% rename from relays/generic/headers/src/sync_loop_tests.rs rename to relays/headers/src/sync_loop_tests.rs index 5cfd5e4f57b66..aec9f1fa883fe 100644 --- a/relays/generic/headers/src/sync_loop_tests.rs +++ b/relays/headers/src/sync_loop_tests.rs @@ -493,7 +493,7 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { target.data.lock().requires_extra = target_requires_extra; target.data.lock().requires_completion = target_requires_completion; - run( + async_std::task::block_on(run( source, test_tick(), target, @@ -502,7 +502,7 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { crate::sync::tests::default_sync_params(), None, exit_receiver.into_future().map(|(_, _)| ()), - ); + )); } #[test] diff --git a/relays/generic/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs similarity index 100% rename from relays/generic/headers/src/sync_types.rs rename to relays/headers/src/sync_types.rs diff --git a/relays/generic/messages/Cargo.toml b/relays/messages/Cargo.toml similarity index 86% rename from relays/generic/messages/Cargo.toml rename to relays/messages/Cargo.toml index e5bd7efaca88e..e02f8ccc86828 100644 --- a/relays/generic/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -15,5 +15,5 @@ parking_lot = "0.11.0" # Bridge Dependencies -bp-messages = { path = "../../../primitives/messages" } +bp-messages = { path = "../../primitives/messages" } relay-utils = { path = "../utils" } diff --git a/relays/generic/messages/src/lib.rs b/relays/messages/src/lib.rs similarity index 100% rename from relays/generic/messages/src/lib.rs rename to relays/messages/src/lib.rs diff --git a/relays/generic/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs similarity index 100% rename from relays/generic/messages/src/message_lane.rs rename to relays/messages/src/message_lane.rs diff --git a/relays/generic/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs similarity index 99% rename from relays/generic/messages/src/message_lane_loop.rs rename to relays/messages/src/message_lane_loop.rs index dd4cd176dfce4..44d31aec975b9 100644 --- a/relays/generic/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -726,7 +726,8 @@ pub(crate) mod tests { target_client, None, exit_signal, - ); + ) + .await; let result = data.lock().clone(); result }) diff --git a/relays/generic/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs similarity index 100% rename from relays/generic/messages/src/message_race_delivery.rs rename to relays/messages/src/message_race_delivery.rs diff --git a/relays/generic/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs similarity index 100% rename from relays/generic/messages/src/message_race_loop.rs rename to relays/messages/src/message_race_loop.rs diff --git a/relays/generic/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs similarity index 100% rename from relays/generic/messages/src/message_race_receiving.rs rename to relays/messages/src/message_race_receiving.rs diff --git a/relays/generic/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs similarity index 100% rename from relays/generic/messages/src/message_race_strategy.rs rename to relays/messages/src/message_race_strategy.rs diff --git a/relays/generic/messages/src/metrics.rs b/relays/messages/src/metrics.rs similarity index 100% rename from relays/generic/messages/src/metrics.rs rename to relays/messages/src/metrics.rs diff --git a/relays/generic/utils/Cargo.toml b/relays/utils/Cargo.toml similarity index 100% rename from relays/generic/utils/Cargo.toml rename to relays/utils/Cargo.toml diff --git a/relays/generic/utils/src/initialize.rs b/relays/utils/src/initialize.rs similarity index 100% rename from relays/generic/utils/src/initialize.rs rename to relays/utils/src/initialize.rs diff --git a/relays/generic/utils/src/lib.rs b/relays/utils/src/lib.rs similarity index 100% rename from relays/generic/utils/src/lib.rs rename to relays/utils/src/lib.rs diff --git a/relays/generic/utils/src/metrics.rs b/relays/utils/src/metrics.rs similarity index 100% rename from relays/generic/utils/src/metrics.rs rename to relays/utils/src/metrics.rs diff --git a/relays/generic/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs similarity index 100% rename from relays/generic/utils/src/relay_loop.rs rename to relays/utils/src/relay_loop.rs From 574f3cfd006d54554bdbb74405edf5e75e702526 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 23 Mar 2021 11:37:41 -0400 Subject: [PATCH 0390/1210] Rename Finality Verifier and Call Dispatch Pallets (#838) * Rename `pallet-finality-verifier` to `pallet-bridge-grandpa` * Missed some CamelCase ones * Update logging target in GRANDPA pallet * Rename `pallet-bridge-call-dispatch` to `pallet-bridge-dispatch` * Rename the dispatch pallet folder * Update logging target in Dispatch pallet * Missed a couple * Format the repo * Stop listing individual pallets in Compose logs * Use correct pallet name in module doc comments * Add `pallet-bridge-dispatch` to README project layout * Sort crate names in TOML files * Rename `pallet-bridge-grandpa` runtime Call alias --- README.md | 3 +- bin/millau/node/src/chain_spec.rs | 4 +- bin/millau/runtime/Cargo.toml | 20 +++--- bin/millau/runtime/src/lib.rs | 30 ++++---- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/runtime/Cargo.toml | 18 ++--- bin/rialto/runtime/src/lib.rs | 22 +++--- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/Cargo.toml | 10 +-- bin/runtime-common/README.md | 12 ++-- bin/runtime-common/src/messages.rs | 70 +++++++++---------- .../src/messages_benchmarking.rs | 8 +-- docs/high-level-overview.md | 4 +- .../{call-dispatch => dispatch}/Cargo.toml | 2 +- modules/{call-dispatch => dispatch}/README.md | 6 +- .../{call-dispatch => dispatch}/src/lib.rs | 40 ++++++----- .../{finality-verifier => grandpa}/Cargo.toml | 2 +- .../{finality-verifier => grandpa}/src/lib.rs | 18 ++--- .../src/mock.rs | 6 +- primitives/runtime/src/lib.rs | 2 +- relays/bin-substrate/Cargo.toml | 4 +- .../bin-substrate/src/headers_initialize.rs | 6 +- .../rialto_millau/millau_headers_to_rialto.rs | 2 +- relays/bin-substrate/src/rialto_millau/mod.rs | 24 +++---- .../rialto_millau/rialto_headers_to_millau.rs | 4 +- .../westend_headers_to_millau.rs | 4 +- 26 files changed, 165 insertions(+), 160 deletions(-) rename modules/{call-dispatch => dispatch}/Cargo.toml (97%) rename modules/{call-dispatch => dispatch}/README.md (93%) rename modules/{call-dispatch => dispatch}/src/lib.rs (95%) rename modules/{finality-verifier => grandpa}/Cargo.toml (98%) rename modules/{finality-verifier => grandpa}/src/lib.rs (97%) rename modules/{finality-verifier => grandpa}/src/mock.rs (96%) diff --git a/README.md b/README.md index 7258eb6c5dfd3..c122b8af6d705 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,9 @@ the `relays` which are used to pass messages between chains. │ └── ... ├── modules // Substrate Runtime Modules (a.k.a Pallets) │ ├── ethereum // Ethereum PoA Header Sync Module -│ ├── substrate // Substrate Based Chain Header Sync Module +│ ├── grandpa // On-Chain GRANDPA Light Client │ ├── messages // Cross Chain Message Passing +│ ├── dispatch // Target Chain Message Execution │ └── ... ├── primitives // Code shared between modules, runtimes, and relays │ └── ... diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index a9f977f6371a9..22f1827e35286 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -16,7 +16,7 @@ use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, BridgeWestendFinalityVerifierConfig, GenesisConfig, + AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -179,7 +179,7 @@ fn testnet_genesis( .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), }), - pallet_finality_verifier_Instance1: Some(BridgeWestendFinalityVerifierConfig { + pallet_bridge_grandpa_Instance1: Some(BridgeWestendGrandpaConfig { // for our deployments to avoid multiple same-nonces transactions: // //Alice is already used to initialize Rialto<->Millau bridge // => let's use //George to initialize Westend->Millau bridge diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 8dc08d33366af..a1406d69d8947 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -21,9 +21,9 @@ bp-rialto = { path = "../../../primitives/chain-rialto", default-features = fals bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-westend = { path = "../../../primitives/chain-westend", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } +pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } +pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } -pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } @@ -46,8 +46,8 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-consensus-aura = { 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-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-offchain = { 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-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } @@ -72,29 +72,29 @@ std = [ "codec/std", "frame-executive/std", "frame-support/std", - "frame-system/std", "frame-system-rpc-runtime-api/std", + "frame-system/std", "pallet-aura/std", "pallet-balances/std", - "pallet-bridge-call-dispatch/std", - "pallet-finality-verifier/std", - "pallet-grandpa/std", + "pallet-bridge-dispatch/std", + "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-grandpa/std", "pallet-randomness-collective-flip/std", - "pallet-shift-session-manager/std", "pallet-session/std", + "pallet-shift-session-manager/std", "pallet-substrate-bridge/std", "pallet-sudo/std", "pallet-timestamp/std", - "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", "serde", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", "sp-core/std", - "sp-inherents/std", "sp-finality-grandpa/std", + "sp-inherents/std", "sp-offchain/std", "sp-runtime/std", "sp-session/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f9c534bf56e71..693543fa1c2c7 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -62,9 +62,9 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; +pub use pallet_bridge_grandpa::Call as BridgeGrandpaRialtoCall; +pub use pallet_bridge_grandpa::Call as BridgeGrandpaWestendCall; pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_finality_verifier::Call as FinalityBridgeRialtoCall; -pub use pallet_finality_verifier::Call as FinalityBridgeWestendCall; pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -207,7 +207,7 @@ impl frame_system::Config for Runtime { impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; } -impl pallet_bridge_call_dispatch::Config for Runtime { +impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; @@ -313,14 +313,14 @@ parameter_types! { pub const MaxRequests: u32 = 50; } -pub type RialtoFinalityVerifierInstance = (); -impl pallet_finality_verifier::Config for Runtime { +pub type RialtoGrandpaInstance = (); +impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type MaxRequests = MaxRequests; } -pub type WestendFinalityVerifierInstance = pallet_finality_verifier::Instance1; -impl pallet_finality_verifier::Config for Runtime { +pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; +impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; type MaxRequests = MaxRequests; } @@ -378,9 +378,9 @@ construct_runtime!( { BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeRialtoMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, - BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, - BridgeRialtoFinalityVerifier: pallet_finality_verifier::{Module, Call}, - BridgeWestendFinalityVerifier: pallet_finality_verifier::::{Module, Call, Config}, + BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, + BridgeRialtoGrandpa: pallet_bridge_grandpa::{Module, Call}, + BridgeWestendGrandpa: pallet_bridge_grandpa::::{Module, Call, Config}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, @@ -581,23 +581,23 @@ impl_runtime_apis! { impl bp_rialto::RialtoFinalityApi for Runtime { fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { - let header = BridgeRialtoFinalityVerifier::best_finalized(); + let header = BridgeRialtoGrandpa::best_finalized(); (header.number, header.hash()) } fn is_known_header(hash: bp_rialto::Hash) -> bool { - BridgeRialtoFinalityVerifier::is_known_header(hash) + BridgeRialtoGrandpa::is_known_header(hash) } } impl bp_westend::WestendFinalityApi for Runtime { fn best_finalized() -> (bp_westend::BlockNumber, bp_westend::Hash) { - let header = BridgeWestendFinalityVerifier::best_finalized(); + let header = BridgeWestendGrandpa::best_finalized(); (header.number, header.hash()) } fn is_known_header(hash: bp_westend::Hash) -> bool { - BridgeWestendFinalityVerifier::is_known_header(hash) + BridgeWestendGrandpa::is_known_header(hash) } } @@ -666,7 +666,7 @@ where AccountId: codec::Encode, SpecVersion: codec::Encode, { - pallet_bridge_call_dispatch::account_ownership_digest( + pallet_bridge_dispatch::account_ownership_digest( rialto_call, millau_account_id, rialto_spec_version, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 48908432b6180..842fcdf6c0993 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -84,7 +84,7 @@ type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesD pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithRialtoMessageBridge, crate::Runtime, - pallet_bridge_call_dispatch::DefaultInstance, + pallet_bridge_dispatch::DefaultInstance, >; /// Millau <-> Rialto message bridge. diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 3824f9cbc5e5c..74365eec899c3 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -25,13 +25,13 @@ bp-millau = { path = "../../../primitives/chain-millau", default-features = fals bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } -pallet-bridge-call-dispatch = { path = "../../../modules/call-dispatch", default-features = false } pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } -pallet-finality-verifier = { path = "../../../modules/finality-verifier", default-features = false } -pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } +pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } +pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } +pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } +pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } # Substrate Dependencies @@ -92,19 +92,19 @@ std = [ "log/std", "pallet-aura/std", "pallet-balances/std", - "pallet-bridge-eth-poa/std", - "pallet-bridge-call-dispatch/std", "pallet-bridge-currency-exchange/std", - "pallet-finality-verifier/std", - "pallet-grandpa/std", + "pallet-bridge-dispatch/std", + "pallet-bridge-eth-poa/std", + "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", "pallet-substrate-bridge/std", "pallet-sudo/std", "pallet-timestamp/std", - "pallet-transaction-payment/std", "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", "serde", "sp-api/std", "sp-block-builder/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4aa81269002f8..dcbb3510e156d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -70,8 +70,8 @@ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; +pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall; pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_finality_verifier::Call as FinalityBridgeMillauCall; pub use pallet_substrate_bridge::Call as BridgeMillauCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -257,7 +257,7 @@ impl pallet_bridge_currency_exchange::Config for Runtime type DepositInto = DepositInto; } -impl pallet_bridge_call_dispatch::Config for Runtime { +impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; @@ -419,7 +419,7 @@ parameter_types! { pub const MaxRequests: u32 = 50; } -impl pallet_finality_verifier::Config for Runtime { +impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; } @@ -480,8 +480,8 @@ construct_runtime!( BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, - BridgeFinalityVerifier: pallet_finality_verifier::{Module, Call}, - BridgeCallDispatch: pallet_bridge_call_dispatch::{Module, Event}, + BridgeGrandpa: pallet_bridge_grandpa::{Module, Call}, + BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, BridgeMillauMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, @@ -643,12 +643,12 @@ impl_runtime_apis! { impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { - let header = BridgeFinalityVerifier::best_finalized(); + let header = BridgeGrandpa::best_finalized(); (header.number, header.hash()) } fn is_known_header(hash: bp_millau::Hash) -> bool { - BridgeFinalityVerifier::is_known_header(hash) + BridgeGrandpa::is_known_header(hash) } } @@ -890,7 +890,7 @@ impl_runtime_apis! { params: MessageParams, ) -> (millau_messages::ToMillauMessagePayload, Balance) { let message_payload = vec![0; params.size as usize]; - let dispatch_origin = pallet_bridge_call_dispatch::CallOrigin::SourceAccount( + let dispatch_origin = pallet_bridge_dispatch::CallOrigin::SourceAccount( params.sender_account, ); @@ -959,10 +959,10 @@ impl_runtime_apis! { make_millau_outbound_lane_data_key, make_millau_header, call_weight, - pallet_bridge_call_dispatch::MessagePayload { + pallet_bridge_dispatch::MessagePayload { spec_version: VERSION.spec_version, weight: call_weight, - origin: pallet_bridge_call_dispatch::CallOrigin::< + origin: pallet_bridge_dispatch::CallOrigin::< bp_millau::AccountId, MultiSigner, Signature, @@ -1040,7 +1040,7 @@ where AccountId: codec::Encode, SpecVersion: codec::Encode, { - pallet_bridge_call_dispatch::account_ownership_digest( + pallet_bridge_dispatch::account_ownership_digest( millau_call, rialto_account_id, millau_spec_version, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 8b0aaea994fba..2cd7d787ea133 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -78,7 +78,7 @@ pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessag pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithMillauMessageBridge, crate::Runtime, - pallet_bridge_call_dispatch::DefaultInstance, + pallet_bridge_dispatch::DefaultInstance, >; /// Messages proof for Millau -> Rialto messages. diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 2bbf942180acc..83803d06deb5d 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -17,9 +17,9 @@ hash-db = { version = "0.15.2", default-features = false } bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } -pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch", default-features = false } +pallet-bridge-dispatch = { path = "../../modules/dispatch", default-features = false } +pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } -pallet-finality-verifier = { path = "../../modules/finality-verifier", default-features = false } # Substrate dependencies @@ -39,8 +39,8 @@ std = [ "codec/std", "frame-support/std", "hash-db/std", - "pallet-bridge-call-dispatch/std", - "pallet-finality-verifier/std", + "pallet-bridge-dispatch/std", + "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "sp-core/std", "sp-runtime/std", @@ -50,7 +50,7 @@ std = [ ] runtime-benchmarks = [ "ed25519-dalek/u64_backend", - "pallet-finality-verifier/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "sp-state-machine", ] diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index 90ebc8976d30a..b375f48309c3a 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -4,11 +4,11 @@ The [`messages`](./src/messages.rs) module of this crate contains a bunch of hel messages module into your runtime. Basic prerequisites of these helpers are: - we're going to bridge Substrate-based chain with another Substrate-based chain; - both chains have [messages module](../../modules/messages/README.md), Substrate bridge - module and the [call dispatch module](../../modules/call-dispatch/README.md); + module and the [call dispatch module](../../modules/dispatch/README.md); - all message lanes are identical and may be used to transfer the same messages; - the messages sent over the bridge are dispatched using - [call dispatch module](../../modules/call-dispatch/README.md); -- the messages are `pallet_bridge_call_dispatch::MessagePayload` structures, where `call` field is + [call dispatch module](../../modules/dispatch/README.md); +- the messages are `pallet_bridge_dispatch::MessagePayload` structures, where `call` field is encoded `Call` of the target chain. This means that the `Call` is opaque to the [messages module](../../modules/messages/README.md) instance at the source chain. It is pre-encoded by the message submitter; @@ -118,7 +118,7 @@ are: `maximal_message_size`, `verify_chain_message`, `verify_messages_delivery_p `estimate_message_dispatch_and_delivery_fee`. `FromThisChainMessagePayload` is a message that the sender sends through our bridge. It is the -`pallet_bridge_call_dispatch::MessagePayload`, where `call` field is encoded target chain call. So +`pallet_bridge_dispatch::MessagePayload`, where `call` field is encoded target chain call. So at this chain we don't see internals of this call - we just know its size. `FromThisChainMessageVerifier` is an implementation of `bp_messages::LaneMessageVerifier`. It @@ -131,8 +131,8 @@ has following checks in its `verify_message` method: 1. it'll reject a message if it has the wrong dispatch origin declared. Like if the submitter is not the root of this chain, but it tries to dispatch the message at the target chain using - `pallet_bridge_call_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature - in the `pallet_bridge_call_dispatch::CallOrigin::TargetAccount` origin; + `pallet_bridge_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature + in the `pallet_bridge_dispatch::CallOrigin::TargetAccount` origin; 1. it'll reject a message if the delivery and dispatch fee that the submitter wants to pay is lesser than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 26c087ac69e83..c25f7091d9546 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -54,7 +54,7 @@ pub trait MessageBridge { fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; } -/// Chain that has `pallet-bridge-messages` and `call-dispatch` modules. +/// Chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ChainWithMessages { /// Hash used in the chain. type Hash: Decode; @@ -85,7 +85,7 @@ pub struct MessageTransaction { pub size: u32, } -/// This chain that has `pallet-bridge-messages` and `call-dispatch` modules. +/// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { /// Call type on the chain. type Call: Encode + Decode; @@ -105,7 +105,7 @@ pub trait ThisChainWithMessages: ChainWithMessages { fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } -/// Bridged chain that has `pallet-bridge-messages` and `call-dispatch` modules. +/// Bridged chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait BridgedChainWithMessages: ChainWithMessages { /// Maximal extrinsic size at Bridged chain. fn maximal_extrinsic_size() -> u32; @@ -180,7 +180,7 @@ pub mod source { pub type BridgedChainOpaqueCall = Vec; /// Message payload for This -> Bridged chain messages. - pub type FromThisChainMessagePayload = pallet_bridge_call_dispatch::MessagePayload< + pub type FromThisChainMessagePayload = pallet_bridge_dispatch::MessagePayload< AccountIdOf>, SignerOf>, SignatureOf>, @@ -221,7 +221,7 @@ pub mod source { /// This verifier assumes following: /// /// - all message lanes are equivalent, so all checks are the same; - /// - messages are being dispatched using `pallet-bridge-call-dispatch` pallet on the target chain. + /// - messages are being dispatched using `pallet-bridge-dispatch` pallet on the target chain. /// /// Following checks are made: /// @@ -267,8 +267,8 @@ pub mod source { } // Do the dispatch-specific check. We assume that the target chain uses - // `CallDispatch`, so we verify the message accordingly. - pallet_bridge_call_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; + // `Dispatch`, so we verify the message accordingly. + pallet_bridge_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; @@ -356,17 +356,16 @@ pub mod source { proof: FromBridgedChainMessagesDeliveryProof>>, ) -> Result, &'static str> where - ThisRuntime: pallet_finality_verifier::Config, + ThisRuntime: pallet_bridge_grandpa::Config, ThisRuntime: pallet_bridge_messages::Config>>, - HashOf>: - Into::BridgedChain>>, + HashOf>: Into::BridgedChain>>, { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane, } = proof; - pallet_finality_verifier::Module::::parse_finalized_storage_proof( + pallet_bridge_grandpa::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), |storage| { @@ -395,14 +394,14 @@ pub mod target { use super::*; /// Call origin for Bridged -> This chain messages. - pub type FromBridgedChainMessageCallOrigin = pallet_bridge_call_dispatch::CallOrigin< + pub type FromBridgedChainMessageCallOrigin = pallet_bridge_dispatch::CallOrigin< AccountIdOf>, SignerOf>, SignatureOf>, >; /// Decoded Bridged -> This message payload. - pub type FromBridgedChainMessagePayload = pallet_bridge_call_dispatch::MessagePayload< + pub type FromBridgedChainMessagePayload = pallet_bridge_dispatch::MessagePayload< AccountIdOf>, SignerOf>, SignatureOf>, @@ -457,19 +456,19 @@ pub mod target { /// Dispatching Bridged -> This chain messages. #[derive(RuntimeDebug, Clone, Copy)] - pub struct FromBridgedChainMessageDispatch { - _marker: PhantomData<(B, ThisRuntime, ThisCallDispatchInstance)>, + pub struct FromBridgedChainMessageDispatch { + _marker: PhantomData<(B, ThisRuntime, ThisDispatchInstance)>, } - impl + impl MessageDispatch< as ChainWithMessages>::Balance> - for FromBridgedChainMessageDispatch + for FromBridgedChainMessageDispatch where - ThisCallDispatchInstance: frame_support::traits::Instance, - ThisRuntime: pallet_bridge_call_dispatch::Config, - >::Event: - From>, - pallet_bridge_call_dispatch::Module: + ThisDispatchInstance: frame_support::traits::Instance, + ThisRuntime: pallet_bridge_dispatch::Config, + >::Event: + From>, + pallet_bridge_dispatch::Module: bp_message_dispatch::MessageDispatch<(LaneId, MessageNonce), Message = FromBridgedChainMessagePayload>, { type DispatchPayload = FromBridgedChainMessagePayload; @@ -482,7 +481,7 @@ pub mod target { fn dispatch(message: DispatchMessage>>) { let message_id = (message.key.lane_id, message.key.nonce); - pallet_bridge_call_dispatch::Module::::dispatch( + pallet_bridge_dispatch::Module::::dispatch( B::INSTANCE, message_id, message.data.payload.map_err(drop), @@ -510,16 +509,15 @@ pub mod target { messages_count: u32, ) -> Result>>>, &'static str> where - ThisRuntime: pallet_finality_verifier::Config, + ThisRuntime: pallet_bridge_grandpa::Config, ThisRuntime: pallet_bridge_messages::Config>>, - HashOf>: - Into::BridgedChain>>, + HashOf>: Into::BridgedChain>>, { verify_messages_proof_with_parser::( proof, messages_count, |bridged_header_hash, bridged_storage_proof| { - pallet_finality_verifier::Module::::parse_finalized_storage_proof( + pallet_bridge_grandpa::Module::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, @@ -931,7 +929,7 @@ mod tests { let message_on_bridged_chain = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: ThisChainCall::Transfer.encode(), } .encode(); @@ -945,7 +943,7 @@ mod tests { target::FromBridgedChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: target::FromBridgedChainEncodedMessageCall:: { encoded_call: ThisChainCall::Transfer.encode(), _marker: PhantomData::default(), @@ -962,7 +960,7 @@ mod tests { source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: vec![42], } } @@ -1012,7 +1010,7 @@ mod tests { let payload = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: vec![42], }; @@ -1055,7 +1053,7 @@ mod tests { let payload = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), + origin: pallet_bridge_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), call: vec![42], }; @@ -1122,7 +1120,7 @@ mod tests { > { spec_version: 1, weight: 5, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: vec![1, 2, 3, 4, 5, 6], },) .is_err() @@ -1137,7 +1135,7 @@ mod tests { > { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: vec![1, 2, 3, 4, 5, 6], },) .is_err() @@ -1152,7 +1150,7 @@ mod tests { > { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: vec![0; source::maximal_message_size::() as usize + 1], },) .is_err() @@ -1167,7 +1165,7 @@ mod tests { > { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, call: vec![0; source::maximal_message_size::() as _], },), Ok(()), diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 39d3ec9262727..5694b9a05c4d3 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -73,7 +73,7 @@ pub fn prepare_message_proof( where B: MessageBridge, H: Hasher, - R: pallet_finality_verifier::Config, + R: pallet_bridge_grandpa::Config, FI: 'static, ::Hash: Into>>, MM: Fn(MessageKey) -> Vec, @@ -130,7 +130,7 @@ where // prepare Bridged chain header and insert it into the Substrate pallet let bridged_header = make_bridged_header(root); let bridged_header_hash = bridged_header.hash(); - pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); + pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); ( FromBridgedChainMessagesProof { @@ -155,7 +155,7 @@ pub fn prepare_message_delivery_proof( where B: MessageBridge, H: Hasher, - R: pallet_finality_verifier::Config, + R: pallet_bridge_grandpa::Config, FI: 'static, ::Hash: Into>>, ML: Fn(LaneId) -> Vec, @@ -183,7 +183,7 @@ where // prepare Bridged chain header and insert it into the Substrate pallet let bridged_header = make_bridged_header(root); let bridged_header_hash = bridged_header.hash(); - pallet_finality_verifier::initialize_for_benchmarks::(bridged_header); + pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index e7dba6c65cf62..14b1eee6d4505 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -131,7 +131,7 @@ require bi-directional header sync (i.e. you can't use message delivery with one #### Dispatching Messages -The [Message dispatch pallet](../modules/call-dispatch/src/lib.rs) is used to perform the actions +The [Message dispatch pallet](../modules/dispatch/src/lib.rs) is used to perform the actions specified by messages which have come over the bridge. For Substrate-based chains this means interpreting the source chain's message as a `Call` on the target chain. @@ -172,6 +172,6 @@ source chain needs to prove ownership of this account by using their target chai sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and verified by the target chain before dispatch. -See [`CallOrigin` documentation](../modules/call-dispatch/src/lib.rs) for more details. +See [`CallOrigin` documentation](../modules/dispatch/src/lib.rs) for more details. #### Message Relayers Strategy diff --git a/modules/call-dispatch/Cargo.toml b/modules/dispatch/Cargo.toml similarity index 97% rename from modules/call-dispatch/Cargo.toml rename to modules/dispatch/Cargo.toml index 3c5fb6cba0c16..6170af272ad9f 100644 --- a/modules/call-dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-bridge-call-dispatch" +name = "pallet-bridge-dispatch" description = "A Substrate Runtime module that dispatches a bridge message, treating it simply as encoded Call" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/modules/call-dispatch/README.md b/modules/dispatch/README.md similarity index 93% rename from modules/call-dispatch/README.md rename to modules/dispatch/README.md index d870193e0e40e..f2ee04beaf53e 100644 --- a/modules/call-dispatch/README.md +++ b/modules/dispatch/README.md @@ -1,7 +1,7 @@ # Call Dispatch Module The call dispatch module has a single internal (only callable by other runtime modules) entry point -for dispatching encoded calls (`pallet_bridge_call_dispatch::Module::dispatch`). Every dispatch +for dispatching encoded calls (`pallet_bridge_dispatch::Module::dispatch`). Every dispatch (successful or not) emits a corresponding module event. The module doesn't have any call-related requirements - they may come from the bridged chain over some message lane, or they may be crafted locally. But in this document we'll mostly talk about this module in the context of bridges. @@ -13,7 +13,7 @@ Every message that is being dispatched has three main characteristics: - `id` is the unique id of the message within the given bridge. For messages coming from the [messages module](../messages/README.md), it may worth to use a tuple `(LaneId, MessageNonce)` to identify a message; -- `message` is the `pallet_bridge_call_dispatch::MessagePayload` structure. The `call` field is set +- `message` is the `pallet_bridge_dispatch::MessagePayload` structure. The `call` field is set to the (potentially) encoded `Call` of this chain. The easiest way to understand what is happening when a `Call` is being dispatched, is to look at the @@ -33,7 +33,7 @@ module events set: chain storage has been corrupted. The `Call` is decoded after `spec_version` check, so we'll never try to decode `Call` from other runtime version; - `MessageSignatureMismatch` event is emitted if submitter has chose to dispatch message using - specified this chain account (`pallet_bridge_call_dispatch::CallOrigin::TargetAccount` origin), + specified this chain account (`pallet_bridge_dispatch::CallOrigin::TargetAccount` origin), but he has failed to prove that he owns the private key for this account; - `MessageCallRejected` event is emitted if the module has been deployed with some call filter and this filter has rejected the `Call`. In your bridge you may choose to reject all messages except diff --git a/modules/call-dispatch/src/lib.rs b/modules/dispatch/src/lib.rs similarity index 95% rename from modules/call-dispatch/src/lib.rs rename to modules/dispatch/src/lib.rs index 9e6fb9e53100e..b2fdf2b70647e 100644 --- a/modules/call-dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -89,7 +89,7 @@ pub enum CallOrigin { /// Runtime specification version. We only dispatch messages that have the same @@ -153,7 +153,7 @@ pub trait Config: frame_system::Config { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as CallDispatch {} + trait Store for Module, I: Instance = DefaultInstance> as Dispatch {} } decl_event!( @@ -202,7 +202,7 @@ impl, I: Instance> MessageDispatch for Module { let message = match message { Ok(message) => message, Err(_) => { - log::trace!("Message {:?}/{:?}: rejected before actual dispatch", bridge, id); + log::trace!(target: "runtime::bridge-dispatch", "Message {:?}/{:?}: rejected before actual dispatch", bridge, id); Self::deposit_event(RawEvent::MessageRejected(bridge, id)); return; } @@ -232,7 +232,7 @@ impl, I: Instance> MessageDispatch for Module { let call = match message.call.into() { Ok(call) => call, Err(_) => { - log::trace!("Failed to decode Call from message {:?}/{:?}", bridge, id,); + log::trace!(target: "runtime::bridge-dispatch", "Failed to decode Call from message {:?}/{:?}", bridge, id,); Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id)); return; } @@ -243,7 +243,7 @@ impl, I: Instance> MessageDispatch for Module { CallOrigin::SourceRoot => { let hex_id = derive_account_id::(bridge, SourceAccount::Root); let target_id = T::AccountIdConverter::convert(hex_id); - log::trace!("Root Account: {:?}", &target_id); + log::trace!(target: "runtime::bridge-dispatch", "Root Account: {:?}", &target_id); target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { @@ -252,6 +252,7 @@ impl, I: Instance> MessageDispatch for Module { let target_account = target_public.into_account(); if !target_signature.verify(&digest[..], &target_account) { log::trace!( + target: "runtime::bridge-dispatch", "Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}", bridge, id, @@ -262,13 +263,13 @@ impl, I: Instance> MessageDispatch for Module { return; } - log::trace!("Target Account: {:?}", &target_account); + log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account); target_account } CallOrigin::SourceAccount(source_account_id) => { let hex_id = derive_account_id(bridge, SourceAccount::Account(source_account_id)); let target_id = T::AccountIdConverter::convert(hex_id); - log::trace!("Source Account: {:?}", &target_id); + log::trace!(target: "runtime::bridge-dispatch", "Source Account: {:?}", &target_id); target_id } }; @@ -276,6 +277,7 @@ impl, I: Instance> MessageDispatch for Module { // filter the call if !T::CallFilter::filter(&call) { log::trace!( + target: "runtime::bridge-dispatch", "Message {:?}/{:?}: the call ({:?}) is rejected by filter", bridge, id, @@ -292,6 +294,7 @@ impl, I: Instance> MessageDispatch for Module { let expected_weight = dispatch_info.weight; if message.weight < expected_weight { log::trace!( + target: "runtime::bridge-dispatch", "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", bridge, id, @@ -310,11 +313,12 @@ impl, I: Instance> MessageDispatch for Module { // finally dispatch message let origin = RawOrigin::Signed(origin_account).into(); - log::trace!("Message being dispatched is: {:?}", &call); + log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:?}", &call); let dispatch_result = call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); log::trace!( + target: "runtime::bridge-dispatch", "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", bridge, id, @@ -452,7 +456,7 @@ mod tests { UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Module, Call, Config, Storage, Event}, - CallDispatch: call_dispatch::{Module, Call, Event}, + Dispatch: call_dispatch::{Module, Call, Event}, } } @@ -571,7 +575,7 @@ mod tests { message.spec_version = BAD_SPEC_VERSION; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -599,7 +603,7 @@ mod tests { message.weight = 0; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -627,7 +631,7 @@ mod tests { ); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -649,7 +653,7 @@ mod tests { let id = [0; 4]; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Err(())); + Dispatch::dispatch(bridge, id, Err(())); assert_eq!( System::events(), @@ -673,7 +677,7 @@ mod tests { message.call.0 = vec![]; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -700,7 +704,7 @@ mod tests { message.weight = weight; System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -721,7 +725,7 @@ mod tests { let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -748,7 +752,7 @@ mod tests { let message = prepare_target_message(call); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), @@ -775,7 +779,7 @@ mod tests { let message = prepare_source_message(call); System::set_block_number(1); - CallDispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(bridge, id, Ok(message)); assert_eq!( System::events(), diff --git a/modules/finality-verifier/Cargo.toml b/modules/grandpa/Cargo.toml similarity index 98% rename from modules/finality-verifier/Cargo.toml rename to modules/grandpa/Cargo.toml index e4af91d75381c..4b35905ecb7c1 100644 --- a/modules/finality-verifier/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-finality-verifier" +name = "pallet-bridge-grandpa" version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" diff --git a/modules/finality-verifier/src/lib.rs b/modules/grandpa/src/lib.rs similarity index 97% rename from modules/finality-verifier/src/lib.rs rename to modules/grandpa/src/lib.rs index 7e6b8a83536c8..21ec2d6528a96 100644 --- a/modules/finality-verifier/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Substrate Finality Verifier Pallet +//! Substrate GRANDPA Pallet //! //! This pallet is an on-chain GRANDPA light client for Substrate based chains. //! @@ -122,7 +122,7 @@ pub mod pallet { ); let (hash, number) = (finality_target.hash(), finality_target.number()); - log::trace!("Going to try and finalize header {:?}", finality_target); + log::trace!(target: "runtime::bridge-grandpa", "Going to try and finalize header {:?}", finality_target); let best_finalized = >::get(>::get()).expect( "In order to reach this point the bridge must have been initialized. Afterwards, @@ -141,7 +141,7 @@ pub mod pallet { >::insert(hash, finality_target); >::mutate(|count| *count += 1); - log::info!("Succesfully imported finalized header with hash {:?}!", hash); + log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); Ok(().into()) } @@ -167,6 +167,7 @@ pub mod pallet { initialize_bridge::(init_data.clone()); log::info!( + target: "runtime::bridge-grandpa", "Pallet has been initialized with the following parameters: {:?}", init_data ); @@ -183,11 +184,11 @@ pub mod pallet { match new_owner { Some(new_owner) => { ModuleOwner::::put(&new_owner); - log::info!("Setting pallet Owner to: {:?}", new_owner); + log::info!(target: "runtime::bridge-grandpa", "Setting pallet Owner to: {:?}", new_owner); } None => { ModuleOwner::::kill(); - log::info!("Removed Owner of pallet."); + log::info!(target: "runtime::bridge-grandpa", "Removed Owner of pallet."); } } @@ -203,9 +204,9 @@ pub mod pallet { >::put(operational); if operational { - log::info!("Resuming pallet operations."); + log::info!(target: "runtime::bridge-grandpa", "Resuming pallet operations."); } else { - log::warn!("Stopping pallet operations."); + log::warn!(target: "runtime::bridge-grandpa", "Stopping pallet operations."); } Ok(().into()) @@ -343,6 +344,7 @@ pub mod pallet { >::put(&next_authorities); log::info!( + target: "runtime::bridge-grandpa", "Transitioned from authority set {} to {}! New authorities are: {:?}", current_set_id, current_set_id + 1, @@ -370,7 +372,7 @@ pub mod pallet { Ok( verify_justification::>((hash, number), set_id, &voter_set, &justification).map_err( |e| { - log::error!("Received invalid justification for {:?}: {:?}", hash, e); + log::error!(target: "runtime::bridge-grandpa", "Received invalid justification for {:?}: {:?}", hash, e); >::InvalidJustification }, )?, diff --git a/modules/finality-verifier/src/mock.rs b/modules/grandpa/src/mock.rs similarity index 96% rename from modules/finality-verifier/src/mock.rs rename to modules/grandpa/src/mock.rs index 59f658e53940c..8deca8ae85881 100644 --- a/modules/finality-verifier/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -33,7 +33,7 @@ pub type TestHash = crate::BridgedBlockHash; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -use crate as finality_verifier; +use crate as grandpa; construct_runtime! { pub enum TestRuntime where @@ -42,7 +42,7 @@ construct_runtime! { UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Module, Call, Config, Storage, Event}, - FinalityVerifier: finality_verifier::{Module}, + Grandpa: grandpa::{Module}, } } @@ -82,7 +82,7 @@ parameter_types! { pub const MaxRequests: u32 = 2; } -impl finality_verifier::Config for TestRuntime { +impl grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 9e6e878bf4d87..c776944fb3c86 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -54,7 +54,7 @@ pub const ROCOCO_BRIDGE_INSTANCE: InstanceId = *b"roco"; pub const WESTEND_BRIDGE_INSTANCE: InstanceId = *b"wend"; /// Call-dispatch module prefix. -pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/call-dispatch"; +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"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index ff2a7fc6a2be2..a94d6d09ef051 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -33,9 +33,9 @@ finality-relay = { path = "../finality" } headers-relay = { path = "../headers" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } -pallet-bridge-call-dispatch = { path = "../../modules/call-dispatch" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } -pallet-finality-verifier = { path = "../../modules/finality-verifier" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index 0fb05ad4a982c..768d299acde77 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -17,7 +17,7 @@ //! Initialize Substrate -> Substrate headers bridge. //! //! Initialization is a transaction that calls `initialize()` function of the -//! `pallet-finality-verifier` pallet. This transaction brings initial header +//! `pallet-bridge-grandpa` pallet. This transaction brings initial header //! and authorities set from source to target chain. The headers sync starts //! with this header. @@ -28,7 +28,7 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use pallet_finality_verifier::InitializationData; +use pallet_bridge_grandpa::InitializationData; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; @@ -83,7 +83,7 @@ async fn do_initialize( Ok(initialization_tx_hash) } -/// Prepare initialization data for the finality-verifier pallet. +/// Prepare initialization data for the GRANDPA verifier pallet. async fn prepare_initialization_data( source_client: Client, ) -> Result, String> { diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index de03fead20144..934c77830a68d 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -42,7 +42,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; let call = - rialto_runtime::FinalityBridgeMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner()) + rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner()) .into(); let genesis_hash = *self.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index be7d20debfda3..d3e85ca14eac9 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -33,7 +33,7 @@ pub type WestendClient = relay_substrate_client::Client; use crate::cli::{ExplicitOrMaximal, HexBytes, Origins}; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; -use pallet_bridge_call_dispatch::{CallOrigin, MessagePayload}; +use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; @@ -64,7 +64,7 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { &rialto_sign.signer, rialto_signer_next_index, rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::FinalityBridgeMillauCall::initialize(initialization_data).into(), + rialto_runtime::BridgeGrandpaMillauCall::initialize(initialization_data).into(), )) .into(), ) @@ -86,9 +86,9 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { .await?; crate::headers_initialize::initialize(rialto_client, millau_client.clone(), move |initialization_data| { - let initialize_call = millau_runtime::FinalityBridgeRialtoCall::< + let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::< millau_runtime::Runtime, - millau_runtime::RialtoFinalityVerifierInstance, + millau_runtime::RialtoGrandpaInstance, >::initialize(initialization_data); Ok(Bytes( @@ -119,9 +119,9 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { // may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge. // => since there's single possible sudo account, one of transaction may fail with duplicate nonce error crate::headers_initialize::initialize(westend_client, millau_client.clone(), move |initialization_data| { - let initialize_call = millau_runtime::FinalityBridgeWestendCall::< + let initialize_call = millau_runtime::BridgeGrandpaWestendCall::< millau_runtime::Runtime, - millau_runtime::WestendFinalityVerifierInstance, + millau_runtime::WestendGrandpaInstance, >::initialize(initialization_data); Ok(Bytes( @@ -861,7 +861,7 @@ mod tests { let payload = message_payload( Default::default(), call.get_dispatch_info().weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + pallet_bridge_dispatch::CallOrigin::SourceRoot, &call, ); assert_eq!(Millau::verify_message(&payload), Ok(())); @@ -871,7 +871,7 @@ mod tests { let payload = message_payload( Default::default(), call.get_dispatch_info().weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + pallet_bridge_dispatch::CallOrigin::SourceRoot, &call, ); assert!(Millau::verify_message(&payload).is_err()); @@ -897,7 +897,7 @@ mod tests { let payload = message_payload( Default::default(), maximal_dispatch_weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + pallet_bridge_dispatch::CallOrigin::SourceRoot, &call, ); assert_eq!(Millau::verify_message(&payload), Ok(())); @@ -905,7 +905,7 @@ mod tests { let payload = message_payload( Default::default(), maximal_dispatch_weight + 1, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + pallet_bridge_dispatch::CallOrigin::SourceRoot, &call, ); assert!(Millau::verify_message(&payload).is_err()); @@ -921,7 +921,7 @@ mod tests { let payload = message_payload( Default::default(), maximal_dispatch_weight, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + pallet_bridge_dispatch::CallOrigin::SourceRoot, &call, ); assert_eq!(Rialto::verify_message(&payload), Ok(())); @@ -929,7 +929,7 @@ mod tests { let payload = message_payload( Default::default(), maximal_dispatch_weight + 1, - pallet_bridge_call_dispatch::CallOrigin::SourceRoot, + pallet_bridge_dispatch::CallOrigin::SourceRoot, &call, ); assert!(Rialto::verify_message(&payload).is_err()); diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index f16b37ad54ee5..046883f11c329 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -42,9 +42,9 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = millau_runtime::FinalityBridgeRialtoCall::< + let call = millau_runtime::BridgeGrandpaRialtoCall::< millau_runtime::Runtime, - millau_runtime::RialtoFinalityVerifierInstance, + millau_runtime::RialtoGrandpaInstance, >::submit_finality_proof(header.into_inner(), proof.into_inner()) .into(); diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index c32f262218c36..ded1df32ce737 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -42,9 +42,9 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); let nonce = self.target_client.next_account_index(account_id).await?; - let call = millau_runtime::FinalityBridgeWestendCall::< + let call = millau_runtime::BridgeGrandpaWestendCall::< millau_runtime::Runtime, - millau_runtime::WestendFinalityVerifierInstance, + millau_runtime::WestendGrandpaInstance, >::submit_finality_proof(header.into_inner(), proof.into_inner()) .into(); From f5674e1898145ac750057840051eb2a52023d19a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 24 Mar 2021 11:46:30 +0300 Subject: [PATCH 0391/1210] Changed how relay loops are started (#840) * slightly changed relay loop initialization * git mv * clippy * more clippy * loop_run -> run_loop * review and clippy * clippy --- relays/bin-ethereum/src/ethereum_exchange.rs | 2 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 7 +- relays/bin-ethereum/src/rpc_errors.rs | 3 + .../bin-ethereum/src/substrate_sync_loop.rs | 7 +- relays/bin-substrate/src/finality_pipeline.rs | 5 +- .../rialto_millau/millau_headers_to_rialto.rs | 4 +- .../millau_messages_to_rialto.rs | 4 +- relays/bin-substrate/src/rialto_millau/mod.rs | 12 +- .../rialto_millau/rialto_headers_to_millau.rs | 4 +- .../rialto_messages_to_millau.rs | 4 +- .../westend_headers_to_millau.rs | 4 +- relays/exchange/src/exchange_loop.rs | 50 ++--- relays/finality/src/finality_loop.rs | 49 ++--- relays/finality/src/finality_loop_tests.rs | 2 +- relays/headers/src/sync_loop.rs | 47 ++-- relays/headers/src/sync_loop_tests.rs | 2 +- relays/messages/src/message_lane_loop.rs | 51 ++--- relays/utils/src/lib.rs | 2 + relays/utils/src/metrics.rs | 143 ++---------- relays/utils/src/metrics/global.rs | 109 ++++++++++ relays/utils/src/relay_loop.rs | 204 +++++++++++++----- 21 files changed, 373 insertions(+), 342 deletions(-) create mode 100644 relays/utils/src/metrics/global.rs diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index 5fed62b9ca686..c075ecb7f81b6 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -385,7 +385,7 @@ async fn run_auto_transactions_relay_loop( metrics_params, futures::future::pending(), ) - .await; + .await?; Ok(()) } diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index b4fd788f9f674..ab6483cdb881c 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -258,8 +258,8 @@ pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { instance, } = params; - let eth_client = async_std::task::block_on(EthereumClient::new(eth_params))?; - let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params))?; + let eth_client = EthereumClient::new(eth_params).await?; + let sub_client = SubstrateClient::::new(sub_params).await?; let sign_sub_transactions = match sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, @@ -279,7 +279,8 @@ pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { metrics_params, futures::future::pending(), ) - .await; + .await + .map_err(RpcError::SyncLoop)?; Ok(()) } diff --git a/relays/bin-ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs index 9f7f14cf9a1f5..6f1c06040e110 100644 --- a/relays/bin-ethereum/src/rpc_errors.rs +++ b/relays/bin-ethereum/src/rpc_errors.rs @@ -29,6 +29,8 @@ pub enum RpcError { Ethereum(EthereumNodeError), /// An error occured when interacting with a Substrate node. Substrate(SubstrateNodeError), + /// Error running relay loop. + SyncLoop(String), } impl From for String { @@ -37,6 +39,7 @@ impl From for String { RpcError::Serialization(e) => e.to_string(), RpcError::Ethereum(e) => e.to_string(), RpcError::Substrate(e) => e.to_string(), + RpcError::SyncLoop(e) => e, } } } diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index a0ff44d4d9bea..f72fcd96324d8 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -173,8 +173,8 @@ pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { metrics_params, } = params; - let eth_client = async_std::task::block_on(EthereumClient::new(eth_params))?; - let sub_client = async_std::task::block_on(SubstrateClient::::new(sub_params))?; + let eth_client = EthereumClient::new(eth_params).await?; + let sub_client = SubstrateClient::::new(sub_params).await?; let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); @@ -189,7 +189,8 @@ pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { metrics_params, futures::future::pending(), ) - .await; + .await + .map_err(RpcError::SyncLoop)?; Ok(()) } diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index 574db6a3f533a..0ddc4a9a8de98 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -98,7 +98,8 @@ pub async fn run( source_client: Client, target_client: Client, metrics_params: Option, -) where +) -> Result<(), String> +where P: SubstrateFinalitySyncPipeline< Hash = HashOf, Number = BlockNumberOf, @@ -127,5 +128,5 @@ pub async fn run( metrics_params, futures::future::pending(), ) - .await; + .await } diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index 934c77830a68d..a14fb691275a2 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -58,12 +58,12 @@ pub async fn run( rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, metrics_params: Option, -) { +) -> Result<(), String> { crate::finality_pipeline::run( MillauFinalityToRialto::new(rialto_client.clone(), rialto_sign), millau_client, rialto_client, metrics_params, ) - .await; + .await } diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index 5b6d080d5a741..df2cb3a03dee7 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -132,7 +132,7 @@ pub async fn run( rialto_sign: RialtoSigningParams, lane_id: LaneId, metrics_params: Option, -) { +) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_millau = millau_sign.signer.public().as_array_ref().clone().into(); @@ -186,5 +186,5 @@ pub async fn run( metrics_params, futures::future::pending(), ) - .await; + .await } diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index d3e85ca14eac9..eadee1484f7b5 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -151,7 +151,7 @@ async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { let millau_client = millau.into_client().await?; let rialto_client = rialto.into_client().await?; let rialto_sign = rialto_sign.parse()?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await; + millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await } cli::RelayHeaders::RialtoToMillau { rialto, @@ -162,7 +162,7 @@ async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { let rialto_client = rialto.into_client().await?; let millau_client = millau.into_client().await?; let millau_sign = millau_sign.parse()?; - rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await; + rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await } cli::RelayHeaders::WestendToMillau { westend, @@ -173,10 +173,9 @@ async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { let westend_client = westend.into_client().await?; let millau_client = millau.into_client().await?; let millau_sign = millau_sign.parse()?; - westend_headers_to_millau::run(westend_client, millau_client, millau_sign, prometheus_params.into()).await; + westend_headers_to_millau::run(westend_client, millau_client, millau_sign, prometheus_params.into()).await } } - Ok(()) } async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { @@ -202,7 +201,7 @@ async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { lane.into(), prometheus_params.into(), ) - .await; + .await } cli::RelayMessages::RialtoToMillau { rialto, @@ -225,10 +224,9 @@ async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { lane.into(), prometheus_params.into(), ) - .await; + .await } } - Ok(()) } async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index 046883f11c329..3a6e7a8fc3028 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -61,12 +61,12 @@ pub async fn run( millau_client: MillauClient, millau_sign: MillauSigningParams, metrics_params: Option, -) { +) -> Result<(), String> { crate::finality_pipeline::run( RialtoFinalityToMillau::new(millau_client.clone(), millau_sign), rialto_client, millau_client, metrics_params, ) - .await; + .await } diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index df94c25f3ce60..97df3734ff7d8 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -132,7 +132,7 @@ pub async fn run( millau_sign: MillauSigningParams, lane_id: LaneId, metrics_params: Option, -) { +) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rialto = rialto_sign.signer.public().as_array_ref().clone().into(); @@ -185,5 +185,5 @@ pub async fn run( metrics_params, futures::future::pending(), ) - .await; + .await } diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index ded1df32ce737..4f2ed8a211734 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -61,12 +61,12 @@ pub async fn run( millau_client: MillauClient, millau_sign: MillauSigningParams, metrics_params: Option, -) { +) -> Result<(), String> { crate::finality_pipeline::run( WestendFinalityToMillau::new(millau_client.clone(), millau_sign), westend_client, millau_client, metrics_params, ) - .await; + .await } diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index d3282d70f6642..101a655c25768 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -26,7 +26,7 @@ use backoff::backoff::Backoff; use futures::{future::FutureExt, select}; use num_traits::One; use relay_utils::{ - metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + metrics::{GlobalMetrics, MetricsParams}, retry_backoff, FailedClient, MaybeConnectionError, }; use std::future::Future; @@ -85,42 +85,25 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: Option, exit_signal: impl Future, -) { +) -> Result<(), String> { let exit_signal = exit_signal.shared(); - let metrics_global = GlobalMetrics::default(); - let metrics_exch = ExchangeLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), - metrics_params, - &metrics_global, - &metrics_exch, - ); - - relay_utils::relay_loop::run( - relay_utils::relay_loop::RECONNECT_DELAY, - source_client, - target_client, - |source_client, target_client| { + + relay_utils::relay_loop(source_client, target_client) + .with_metrics(format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME)) + .loop_metric(ExchangeLoopMetrics::default())? + .standalone_metric(GlobalMetrics::default())? + .expose(metrics_params) + .await? + .run(|source_client, target_client, metrics| { run_until_connection_lost( storage.clone(), source_client, target_client, - if metrics_enabled { - Some(metrics_global.clone()) - } else { - None - }, - if metrics_enabled { - Some(metrics_exch.clone()) - } else { - None - }, + metrics, exit_signal.clone(), ) - }, - ) - .await; + }) + .await } /// Run proofs synchronization. @@ -128,7 +111,6 @@ async fn run_until_connection_lost( mut storage: impl TransactionProofsRelayStorage>, source_client: impl SourceClient

, target_client: impl TargetClient

, - metrics_global: Option, metrics_exch: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { @@ -151,10 +133,6 @@ async fn run_until_connection_lost( ) .await; - if let Some(ref metrics_global) = metrics_global { - metrics_global.update().await; - } - if let Err((is_connection_error, failed_client)) = iteration_result { if is_connection_error { return Err(failed_client); @@ -321,7 +299,7 @@ mod tests { } })); - async_std::task::block_on(run( + let _ = async_std::task::block_on(run( storage, source, target, diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 7aafce075e608..512c51b4b2423 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -27,7 +27,7 @@ use futures::{select, Future, FutureExt, Stream, StreamExt}; use headers_relay::sync_loop_metrics::SyncLoopMetrics; use num_traits::{One, Saturating}; use relay_utils::{ - metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + metrics::{GlobalMetrics, MetricsParams}, relay_loop::Client as RelayClient, retry_backoff, FailedClient, MaybeConnectionError, }; @@ -97,43 +97,24 @@ pub async fn run( sync_params: FinalitySyncParams, metrics_params: Option, exit_signal: impl Future, -) { +) -> Result<(), String> { let exit_signal = exit_signal.shared(); - - let metrics_global = GlobalMetrics::default(); - let metrics_sync = SyncLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), - metrics_params, - &metrics_global, - &metrics_sync, - ); - - relay_utils::relay_loop::run( - relay_utils::relay_loop::RECONNECT_DELAY, - source_client, - target_client, - |source_client, target_client| { + relay_utils::relay_loop(source_client, target_client) + .with_metrics(format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME)) + .loop_metric(SyncLoopMetrics::default())? + .standalone_metric(GlobalMetrics::default())? + .expose(metrics_params) + .await? + .run(|source_client, target_client, metrics| { run_until_connection_lost( source_client, target_client, sync_params.clone(), - if metrics_enabled { - Some(metrics_global.clone()) - } else { - None - }, - if metrics_enabled { - Some(metrics_sync.clone()) - } else { - None - }, + metrics, exit_signal.clone(), ) - }, - ) - .await; + }) + .await } /// Unjustified headers container. Ordered by header number. @@ -221,7 +202,6 @@ async fn run_until_connection_lost( source_client: impl SourceClient

, target_client: impl TargetClient

, sync_params: FinalitySyncParams, - metrics_global: Option, metrics_sync: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { @@ -267,11 +247,6 @@ async fn run_until_connection_lost( ) .await; - // update global metrics - if let Some(ref metrics_global) = metrics_global { - metrics_global.update().await; - } - // deal with errors let next_tick = match iteration_result { Ok(updated_last_transaction) => { diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 64ab91420fb91..e19f924376d72 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -202,7 +202,7 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync stall_timeout: Duration::from_secs(1), }; - async_std::task::block_on(run( + let _ = async_std::task::block_on(run( source_client, target_client, sync_params, diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index 7da8fd4f42fec..9b55456f7900d 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -25,7 +25,7 @@ use futures::{future::FutureExt, stream::StreamExt}; use num_traits::{Saturating, Zero}; use relay_utils::{ format_ids, interval, - metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + metrics::{GlobalMetrics, MetricsParams}, process_future_result, relay_loop::Client as RelayClient, retry_backoff, FailedClient, MaybeConnectionError, StringifiedMaybeConnectionError, @@ -121,24 +121,15 @@ pub async fn run>( sync_params: HeadersSyncParams, metrics_params: Option, exit_signal: impl Future, -) { +) -> Result<(), String> { let exit_signal = exit_signal.shared(); - - let metrics_global = GlobalMetrics::default(); - let metrics_sync = SyncLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), - metrics_params, - &metrics_global, - &metrics_sync, - ); - - relay_utils::relay_loop::run( - relay_utils::relay_loop::RECONNECT_DELAY, - source_client, - target_client, - |source_client, target_client| { + relay_utils::relay_loop(source_client, target_client) + .with_metrics(format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME)) + .loop_metric(SyncLoopMetrics::default())? + .standalone_metric(GlobalMetrics::default())? + .expose(metrics_params) + .await? + .run(|source_client, target_client, metrics| { run_until_connection_lost( source_client, source_tick, @@ -146,21 +137,11 @@ pub async fn run>( target_tick, sync_maintain.clone(), sync_params.clone(), - if metrics_enabled { - Some(metrics_global.clone()) - } else { - None - }, - if metrics_enabled { - Some(metrics_sync.clone()) - } else { - None - }, + metrics, exit_signal.clone(), ) - }, - ) - .await; + }) + .await } /// Run headers synchronization. @@ -172,7 +153,6 @@ async fn run_until_connection_lost>( target_tick: Duration, sync_maintain: impl SyncMaintain

, sync_params: HeadersSyncParams, - metrics_global: Option, metrics_sync: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { @@ -438,9 +418,6 @@ async fn run_until_connection_lost>( } // update metrics - if let Some(ref metrics_global) = metrics_global { - metrics_global.update().await; - } if let Some(ref metrics_sync) = metrics_sync { metrics_sync.update(&sync); } diff --git a/relays/headers/src/sync_loop_tests.rs b/relays/headers/src/sync_loop_tests.rs index aec9f1fa883fe..03303214bc52a 100644 --- a/relays/headers/src/sync_loop_tests.rs +++ b/relays/headers/src/sync_loop_tests.rs @@ -493,7 +493,7 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { target.data.lock().requires_extra = target_requires_extra; target.data.lock().requires_completion = target_requires_completion; - async_std::task::block_on(run( + let _ = async_std::task::block_on(run( source, test_tick(), target, diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 44d31aec975b9..77265f4ac96b7 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -34,7 +34,7 @@ use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, - metrics::{start as metrics_start, GlobalMetrics, MetricsParams}, + metrics::{GlobalMetrics, MetricsParams}, process_future_result, relay_loop::Client as RelayClient, retry_backoff, FailedClient, @@ -212,47 +212,29 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: Option, exit_signal: impl Future, -) { +) -> Result<(), String> { let exit_signal = exit_signal.shared(); - let metrics_global = GlobalMetrics::default(); - let metrics_msg = MessageLaneLoopMetrics::default(); - let metrics_enabled = metrics_params.is_some(); - metrics_start( - format!( + relay_utils::relay_loop(source_client, target_client) + .with_metrics(format!( "{}_to_{}_MessageLane_{}", P::SOURCE_NAME, P::TARGET_NAME, hex::encode(params.lane) - ), - metrics_params, - &metrics_global, - &metrics_msg, - ); - - relay_utils::relay_loop::run( - params.reconnect_delay, - source_client, - target_client, - |source_client, target_client| { + )) + .loop_metric(MessageLaneLoopMetrics::default())? + .standalone_metric(GlobalMetrics::default())? + .expose(metrics_params) + .await? + .run(|source_client, target_client, metrics| { run_until_connection_lost( params.clone(), source_client, target_client, - if metrics_enabled { - Some(metrics_global.clone()) - } else { - None - }, - if metrics_enabled { - Some(metrics_msg.clone()) - } else { - None - }, + metrics, exit_signal.clone(), ) - }, - ) - .await; + }) + .await } /// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. @@ -260,7 +242,6 @@ async fn run_until_connection_lost, TC: Targ params: Params, source_client: SC, target_client: TC, - metrics_global: Option, metrics_msg: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { @@ -404,10 +385,6 @@ async fn run_until_connection_lost, TC: Targ } } - if let Some(ref metrics_global) = metrics_global { - metrics_global.update().await; - } - if source_client_is_online && source_state_required { log::debug!(target: "bridge", "Asking {} node about its state", P::SOURCE_NAME); source_state.set(source_client.state().fuse()); @@ -707,7 +684,7 @@ pub(crate) mod tests { data: data.clone(), tick: target_tick, }; - run( + let _ = run( Params { lane: [0, 0, 0, 0], source_tick: Duration::from_millis(100), diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index f787e8763a7a5..0dcc7e9a4f983 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -16,6 +16,8 @@ //! Utilities used by different relays. +pub use relay_loop::relay_loop; + use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::future::FutureExt; use std::time::Duration; diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index f38d1bda3a5d8..c42b10cad97f7 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -14,12 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +pub use global::GlobalMetrics; pub use substrate_prometheus_endpoint::{register, Counter, CounterVec, Gauge, GaugeVec, Opts, Registry, F64, U64}; -use async_std::sync::{Arc, Mutex}; -use std::net::SocketAddr; -use substrate_prometheus_endpoint::init_prometheus; -use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; +use async_trait::async_trait; +use std::time::Duration; + +mod global; /// Prometheus endpoint MetricsParams. #[derive(Debug, Clone)] @@ -31,62 +32,32 @@ pub struct MetricsParams { } /// Metrics API. -pub trait Metrics { +pub trait Metrics: Clone + Send + Sync + 'static { /// Register metrics in the registry. fn register(&self, registry: &Registry) -> Result<(), String>; } -/// Global Prometheus metrics. -#[derive(Debug, Clone)] -pub struct GlobalMetrics { - system: Arc>, - system_average_load: GaugeVec, - process_cpu_usage_percentage: Gauge, - process_memory_usage_bytes: Gauge, -} - -/// Start Prometheus endpoint with given metrics registry. -pub fn start( - prefix: String, - params: Option, - global_metrics: &GlobalMetrics, - extra_metrics: &impl Metrics, -) { - let params = match params { - Some(params) => params, - None => return, - }; +/// Standalone metrics API. +/// +/// Metrics of this kind know how to update themselves, so we may just spawn and forget the +/// asynchronous self-update task. +#[async_trait] +pub trait StandaloneMetrics: Metrics { + /// Update metric values. + async fn update(&self); - assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); + /// Metrics update interval. + fn update_interval(&self) -> Duration; - let do_start = move || { - let prometheus_socket_addr = SocketAddr::new( - params - .host - .parse() - .map_err(|err| format!("Invalid Prometheus host {}: {}", params.host, err))?, - params.port, - ); - let metrics_registry = - Registry::new_custom(Some(prefix), None).expect("only fails if prefix is empty; prefix is not empty; qed"); - global_metrics.register(&metrics_registry)?; - extra_metrics.register(&metrics_registry)?; + /// Spawn the self update task that will keep update metric value at given intervals. + fn spawn(self) { async_std::task::spawn(async move { - init_prometheus(prometheus_socket_addr, metrics_registry) - .await - .map_err(|err| format!("Error starting Prometheus endpoint: {}", err)) + let update_interval = self.update_interval(); + loop { + self.update().await; + async_std::task::sleep(update_interval).await; + } }); - - Ok(()) - }; - - let result: Result<(), String> = do_start(); - if let Err(err) = result { - log::warn!( - target: "bridge", - "Failed to expose metrics: {}", - err, - ); } } @@ -98,71 +69,3 @@ impl Default for MetricsParams { } } } - -impl Metrics for GlobalMetrics { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.system_average_load.clone(), registry).map_err(|e| e.to_string())?; - register(self.process_cpu_usage_percentage.clone(), registry).map_err(|e| e.to_string())?; - register(self.process_memory_usage_bytes.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } -} - -impl Default for GlobalMetrics { - fn default() -> Self { - GlobalMetrics { - system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), - system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) - .expect("metric is static and thus valid; qed"), - process_cpu_usage_percentage: Gauge::new("process_cpu_usage_percentage", "Process CPU usage") - .expect("metric is static and thus valid; qed"), - process_memory_usage_bytes: Gauge::new( - "process_memory_usage_bytes", - "Process memory (resident set size) usage", - ) - .expect("metric is static and thus valid; qed"), - } - } -} - -impl GlobalMetrics { - /// Update metrics. - pub async fn update(&self) { - // update system-wide metrics - let mut system = self.system.lock().await; - let load = system.get_load_average(); - self.system_average_load.with_label_values(&["1min"]).set(load.one); - self.system_average_load.with_label_values(&["5min"]).set(load.five); - self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); - - // update process-related metrics - let pid = sysinfo::get_current_pid().expect( - "only fails where pid is unavailable (os=unknown || arch=wasm32);\ - relay is not supposed to run in such MetricsParamss;\ - qed", - ); - let is_process_refreshed = system.refresh_process(pid); - match (is_process_refreshed, system.get_process(pid)) { - (true, Some(process_info)) => { - let cpu_usage = process_info.cpu_usage() as f64; - let memory_usage = process_info.memory() * 1024; - log::trace!( - target: "bridge-metrics", - "Refreshed process metrics: CPU={}, memory={}", - cpu_usage, - memory_usage, - ); - - self.process_cpu_usage_percentage - .set(if cpu_usage.is_finite() { cpu_usage } else { 0f64 }); - self.process_memory_usage_bytes.set(memory_usage); - } - _ => { - log::warn!( - target: "bridge", - "Failed to refresh process information. Metrics may show obsolete values", - ); - } - } - } -} diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs new file mode 100644 index 0000000000000..c19ac8d46819b --- /dev/null +++ b/relays/utils/src/metrics/global.rs @@ -0,0 +1,109 @@ +// 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 . + +//! Global system-wide Prometheus metrics exposed by relays. + +use crate::metrics::{Metrics, StandaloneMetrics}; + +use async_std::sync::{Arc, Mutex}; +use async_trait::async_trait; +use std::time::Duration; +use substrate_prometheus_endpoint::{register, Gauge, GaugeVec, Opts, Registry, F64, U64}; +use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; + +/// Global metrics update interval. +const UPDATE_INTERVAL: Duration = Duration::from_secs(10); + +/// Global Prometheus metrics. +#[derive(Debug, Clone)] +pub struct GlobalMetrics { + system: Arc>, + system_average_load: GaugeVec, + process_cpu_usage_percentage: Gauge, + process_memory_usage_bytes: Gauge, +} + +impl Metrics for GlobalMetrics { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.system_average_load.clone(), registry).map_err(|e| e.to_string())?; + register(self.process_cpu_usage_percentage.clone(), registry).map_err(|e| e.to_string())?; + register(self.process_memory_usage_bytes.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + +#[async_trait] +impl StandaloneMetrics for GlobalMetrics { + async fn update(&self) { + // update system-wide metrics + let mut system = self.system.lock().await; + let load = system.get_load_average(); + self.system_average_load.with_label_values(&["1min"]).set(load.one); + self.system_average_load.with_label_values(&["5min"]).set(load.five); + self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); + + // update process-related metrics + let pid = sysinfo::get_current_pid().expect( + "only fails where pid is unavailable (os=unknown || arch=wasm32);\ + relay is not supposed to run in such MetricsParamss;\ + qed", + ); + let is_process_refreshed = system.refresh_process(pid); + match (is_process_refreshed, system.get_process(pid)) { + (true, Some(process_info)) => { + let cpu_usage = process_info.cpu_usage() as f64; + let memory_usage = process_info.memory() * 1024; + log::trace!( + target: "bridge-metrics", + "Refreshed process metrics: CPU={}, memory={}", + cpu_usage, + memory_usage, + ); + + self.process_cpu_usage_percentage + .set(if cpu_usage.is_finite() { cpu_usage } else { 0f64 }); + self.process_memory_usage_bytes.set(memory_usage); + } + _ => { + log::warn!( + target: "bridge", + "Failed to refresh process information. Metrics may show obsolete values", + ); + } + } + } + + fn update_interval(&self) -> Duration { + UPDATE_INTERVAL + } +} + +impl Default for GlobalMetrics { + fn default() -> Self { + GlobalMetrics { + system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), + system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) + .expect("metric is static and thus valid; qed"), + process_cpu_usage_percentage: Gauge::new("process_cpu_usage_percentage", "Process CPU usage") + .expect("metric is static and thus valid; qed"), + process_memory_usage_bytes: Gauge::new( + "process_memory_usage_bytes", + "Process memory (resident set size) usage", + ) + .expect("metric is static and thus valid; qed"), + } + } +} diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 6a61ecd289343..d21f6d28ef5bb 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -14,10 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::metrics::{Metrics, MetricsParams, StandaloneMetrics}; use crate::{FailedClient, MaybeConnectionError}; use async_trait::async_trait; -use std::{fmt::Debug, future::Future, time::Duration}; +use std::{fmt::Debug, future::Future, net::SocketAddr, time::Duration}; +use substrate_prometheus_endpoint::{init_prometheus, Registry}; /// Default pause between reconnect attempts. pub const RECONNECT_DELAY: Duration = Duration::from_secs(10); @@ -32,60 +34,164 @@ pub trait Client: Clone + Send + Sync { async fn reconnect(&mut self) -> Result<(), Self::Error>; } -/// Run relay loop. -/// -/// This function represents an outer loop, which in turn calls provided `loop_run` function to do -/// actual job. When `loop_run` returns, this outer loop reconnects to failed client (source, -/// target or both) and calls `loop_run` again. -pub async fn run( - reconnect_delay: Duration, - mut source_client: SC, - mut target_client: TC, - loop_run: R, -) where - R: Fn(SC, TC) -> F, - F: Future>, -{ - loop { - let result = loop_run(source_client.clone(), target_client.clone()).await; - - match result { - Ok(()) => break, - Err(failed_client) => loop { - async_std::task::sleep(reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - match source_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to source client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue; +/// Returns generic loop that may be customized and started. +pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { + Loop { + source_client, + target_client, + loop_metric: None, + } +} + +/// Generic relay loop. +pub struct Loop { + source_client: SC, + target_client: TC, + loop_metric: Option, +} + +/// Relay loop metrics builder. +pub struct LoopMetrics { + relay_loop: Loop, + registry: Registry, + loop_metric: Option, +} + +impl Loop { + /// Start building loop metrics using given prefix. + /// + /// Panics if `prefix` is empty. + pub fn with_metrics(self, prefix: String) -> LoopMetrics { + assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); + + LoopMetrics { + relay_loop: Loop { + source_client: self.source_client, + target_client: self.target_client, + loop_metric: None, + }, + registry: Registry::new_custom(Some(prefix), None) + .expect("only fails if prefix is empty; prefix is not empty; qed"), + loop_metric: None, + } + } + + /// Run relay loop. + /// + /// This function represents an outer loop, which in turn calls provided `run_loop` function to do + /// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, + /// target or both) and calls `run_loop` again. + pub async fn run(mut self, run_loop: R) -> Result<(), String> + where + R: Fn(SC, TC, Option) -> F, + F: Future>, + SC: Client, + TC: Client, + LM: Clone, + { + loop { + let result = run_loop( + self.source_client.clone(), + self.target_client.clone(), + self.loop_metric.clone(), + ) + .await; + + match result { + Ok(()) => break, + Err(failed_client) => loop { + async_std::task::sleep(RECONNECT_DELAY).await; + if failed_client == FailedClient::Both || failed_client == FailedClient::Source { + match self.source_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to source client. Going to retry in {}s: {:?}", + RECONNECT_DELAY.as_secs(), + error, + ); + continue; + } } } - } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - match target_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to target client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue; + if failed_client == FailedClient::Both || failed_client == FailedClient::Target { + match self.target_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to target client. Going to retry in {}s: {:?}", + RECONNECT_DELAY.as_secs(), + error, + ); + continue; + } } } - } - break; - }, + break; + }, + } + + log::debug!(target: "bridge", "Restarting relay loop"); + } + + Ok(()) + } +} + +impl LoopMetrics { + /// Add relay loop metrics. + /// + /// Loop metrics will be passed to the loop callback. + pub fn loop_metric(self, loop_metric: NewLM) -> Result, String> { + loop_metric.register(&self.registry)?; + + Ok(LoopMetrics { + relay_loop: self.relay_loop, + registry: self.registry, + loop_metric: Some(loop_metric), + }) + } + + /// Add standalone metrics. + pub fn standalone_metric(self, standalone_metrics: M) -> Result { + standalone_metrics.register(&self.registry)?; + standalone_metrics.spawn(); + Ok(self) + } + + /// Expose metrics using given params. + /// + /// If `params` is `None`, metrics are not exposed. + pub async fn expose(self, params: Option) -> Result, String> { + if let Some(params) = params { + let socket_addr = SocketAddr::new( + params.host.parse().map_err(|err| { + format!( + "Invalid host {} is used to expose Prometheus metrics: {}", + params.host, err, + ) + })?, + params.port, + ); + + let registry = self.registry; + async_std::task::spawn(async move { + let result = init_prometheus(socket_addr, registry).await; + log::trace!( + target: "bridge-metrics", + "Prometheus endpoint has exited with result: {:?}", + result, + ); + }); } - log::debug!(target: "bridge", "Restarting relay loop"); + Ok(Loop { + source_client: self.relay_loop.source_client, + target_client: self.relay_loop.target_client, + loop_metric: self.loop_metric, + }) } } From 2daae57616f3f616e6a03548145cf003068a9093 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 24 Mar 2021 16:14:15 -0400 Subject: [PATCH 0392/1210] Larger Test Keyring Support (#842) * Allow creation of authority lists with any number of authorities * Move keyring helpers into their own module * Add helper for generating list of test accounts * Fix import names in tests * Rename Keyring trait to Signer * Get list of accounts in a more functional way * Clarify meaning of `test_keyring` return type * Use concrete test account type instead of generics * Make sure voter set contains all authorities which signed off on pre-commits --- modules/grandpa/src/lib.rs | 12 +-- modules/substrate/src/fork_tests.rs | 7 +- modules/substrate/src/lib.rs | 11 +-- modules/substrate/src/verifier.rs | 9 +- .../header-chain/tests/justification.rs | 41 ++++++++- primitives/test-utils/src/keyring.rs | 91 +++++++++++++++++++ primitives/test-utils/src/lib.rs | 78 +++------------- 7 files changed, 154 insertions(+), 95 deletions(-) create mode 100644 primitives/test-utils/src/keyring.rs diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 21ec2d6528a96..4f3afcbbf7876 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -526,8 +526,8 @@ mod tests { use super::*; use crate::mock::{run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime}; use bp_test_utils::{ - authority_list, make_default_justification, make_justification_for_header, JustificationGeneratorParams, - Keyring::{Alice, Bob}, + authority_list, make_default_justification, make_justification_for_header, JustificationGeneratorParams, ALICE, + BOB, }; use codec::Encode; use frame_support::weights::PostDispatchInfo; @@ -570,7 +570,7 @@ mod tests { fn change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(Alice.into(), 1), (Bob.into(), 1)], + next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], delay, }); @@ -583,7 +583,7 @@ mod tests { let consensus_log = ConsensusLog::::ForcedChange( delay, sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(Alice.into(), 1), (Bob.into(), 1)], + next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], delay, }, ); @@ -760,7 +760,7 @@ mod tests { run_test(|| { let genesis = test_header(0); - let invalid_authority_list = vec![(Alice.into(), u64::MAX), (Bob.into(), u64::MAX)]; + let invalid_authority_list = vec![(ALICE.into(), u64::MAX), (BOB.into(), u64::MAX)]; let init_data = InitializationData { header: genesis, authority_list: invalid_authority_list, @@ -797,7 +797,7 @@ mod tests { initialize_substrate_bridge(); let next_set_id = 2; - let next_authorities = vec![(Alice.into(), 1), (Bob.into(), 1)]; + let next_authorities = vec![(ALICE.into(), 1), (BOB.into(), 1)]; // Need to update the header digest to indicate that our header signals an authority set // change. The change will be enacted when we import our header. diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index acd147109a773..40b40678a86db 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -59,10 +59,7 @@ use crate::storage::ImportedHeader; use crate::verifier::*; use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; use bp_header_chain::AuthoritySet; -use bp_test_utils::{ - authority_list, make_default_justification, - Keyring::{Alice, Bob}, -}; +use bp_test_utils::{authority_list, make_default_justification, ALICE, BOB}; use codec::Encode; use frame_support::{IterableStorageMap, StorageValue}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -505,7 +502,7 @@ where pub(crate) fn change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(Alice.into(), 1), (Bob.into(), 1)], + next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], delay, }); diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index 8a53ed336e06c..ce4006688515f 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -721,10 +721,7 @@ mod tests { use super::*; use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestHeader, TestRuntime}; use bp_header_chain::HeaderChain; - use bp_test_utils::{ - authority_list, - Keyring::{Alice, Bob}, - }; + use bp_test_utils::{authority_list, ALICE, BOB}; use frame_support::{assert_err, assert_noop, assert_ok}; use sp_runtime::DispatchError; @@ -952,7 +949,7 @@ mod tests { let storage = PalletStorage::::new(); let next_set_id = 2; - let next_authorities = vec![(Alice.into(), 1), (Bob.into(), 1)]; + let next_authorities = vec![(ALICE.into(), 1), (BOB.into(), 1)]; // Need to update the header digest to indicate that our header signals an authority set // change. The change will be enacted when we import our header. @@ -981,7 +978,7 @@ mod tests { let storage = PalletStorage::::new(); let next_set_id = 2; - let next_authorities = vec![(Alice.into(), 1), (Bob.into(), 1)]; + let next_authorities = vec![(ALICE.into(), 1), (BOB.into(), 1)]; // Need to update the header digest to indicate that our header signals an authority set // change. However, the change doesn't happen until the next block. @@ -1010,7 +1007,7 @@ mod tests { run_test(|| { let storage = PalletStorage::::new(); - let next_authorities = vec![(Alice.into(), 1)]; + let next_authorities = vec![(ALICE.into(), 1)]; let next_set_id = 2; let next_authority_set = AuthoritySet::new(next_authorities.clone(), next_set_id); diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 4849941124302..f2e33e21e481f 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -342,10 +342,7 @@ mod tests { use super::*; use crate::mock::*; use crate::{BestFinalized, BestHeight, HeaderId, ImportedHeaders, PalletStorage}; - use bp_test_utils::{ - authority_list, make_default_justification, - Keyring::{Alice, Bob}, - }; + use bp_test_utils::{authority_list, make_default_justification, ALICE, BOB}; use codec::Encode; use frame_support::{assert_err, assert_ok}; use frame_support::{StorageMap, StorageValue}; @@ -695,7 +692,7 @@ mod tests { // This is an *invalid* authority set because the combined weight of the // authorities is greater than `u64::MAX` let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(Alice.into(), u64::MAX), (Bob.into(), u64::MAX)], + next_authorities: vec![(ALICE.into(), u64::MAX), (BOB.into(), u64::MAX)], delay: 0, }); @@ -800,7 +797,7 @@ mod tests { // Schedule a change at the height of our header let set_id = 2; let height = *header.number(); - let authorities = vec![Alice.into()]; + let authorities = vec![ALICE.into()]; let change = schedule_next_change(authorities, set_id, height); storage.schedule_next_set_change(genesis_hash, change.clone()); diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 29ba744133fad..33808461f6515 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -17,7 +17,6 @@ //! Tests for Grandpa Justification code. use bp_header_chain::justification::{verify_justification, Error}; -use bp_test_utils::Keyring::*; use bp_test_utils::*; use codec::Encode; @@ -29,7 +28,7 @@ fn valid_justification_accepted() { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(Alice, 1), (Bob, 1), (Charlie, 1), (Dave, 1), (Eve, 1)], + authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)], depth: 5, forks: 5, }; @@ -51,7 +50,7 @@ fn valid_justification_accepted_with_single_fork() { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(Alice, 1), (Bob, 1), (Charlie, 1), (Dave, 1), (Eve, 1)], + authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)], depth: 5, forks: 1, }; @@ -67,6 +66,40 @@ fn valid_justification_accepted_with_single_fork() { ); } +#[test] +fn valid_justification_accepted_with_arbitrary_number_of_authorities() { + use finality_grandpa::voter_set::VoterSet; + use sp_finality_grandpa::AuthorityId; + + let n = 15; + let authorities = accounts(n).iter().map(|k| (*k, 1)).collect::>(); + + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: authorities.clone(), + depth: 5, + forks: n.into(), + }; + + let authorities = authorities + .iter() + .map(|(id, w)| (AuthorityId::from(*id), *w)) + .collect::>(); + let voter_set = VoterSet::new(authorities).unwrap(); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set, + &make_justification_for_header::(params).encode() + ), + Ok(()), + ); +} + #[test] fn justification_with_invalid_encoding_rejected() { assert_eq!( @@ -143,7 +176,7 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(Alice, 1), (Bob, 1)], + authorities: vec![(ALICE, 1), (BOB, 1)], depth: 2, forks: 2, }; diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs new file mode 100644 index 0000000000000..5b96b98a3ad54 --- /dev/null +++ b/primitives/test-utils/src/keyring.rs @@ -0,0 +1,91 @@ +// Copyright 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 . + +//! Utilities for working with test accounts. + +use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; +use finality_grandpa::voter_set::VoterSet; +use sp_application_crypto::Public; +use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; +use sp_runtime::RuntimeDebug; + +/// Set of test accounts with friendly names. +pub const ALICE: Account = Account(0); +pub const BOB: Account = Account(1); +pub const CHARLIE: Account = Account(2); +pub const DAVE: Account = Account(3); +pub const EVE: Account = Account(4); +pub const FERDIE: Account = Account(5); + +/// A test account which can be used to sign messages. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Account(pub u8); + +impl Account { + pub fn public(&self) -> PublicKey { + (&self.secret()).into() + } + + pub fn secret(&self) -> SecretKey { + SecretKey::from_bytes(&[self.0; 32]).expect("A static array of the correct length is a known good.") + } + + pub fn pair(&self) -> Keypair { + let mut pair: [u8; 64] = [0; 64]; + + let secret = self.secret(); + pair[..32].copy_from_slice(&secret.to_bytes()); + + let public = self.public(); + pair[32..].copy_from_slice(&public.to_bytes()); + + Keypair::from_bytes(&pair).expect("We expect the SecretKey to be good, so this must also be good.") + } + + pub fn sign(&self, msg: &[u8]) -> Signature { + use ed25519_dalek::Signer; + self.pair().sign(msg) + } +} + +impl From for AuthorityId { + fn from(p: Account) -> Self { + AuthorityId::from_slice(&p.public().to_bytes()) + } +} + +/// Get a valid set of voters for a Grandpa round. +pub fn voter_set() -> VoterSet { + VoterSet::new(authority_list()).unwrap() +} + +/// Convenience function to get a list of Grandpa authorities. +pub fn authority_list() -> AuthorityList { + test_keyring() + .iter() + .map(|(id, w)| (AuthorityId::from(*id), *w)) + .collect() +} + +/// Get the corresponding identities from the keyring for the "standard" authority set. +pub fn test_keyring() -> Vec<(Account, AuthorityWeight)> { + vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)] +} + +/// Get a list of "unique" accounts. +pub fn accounts(len: u8) -> Vec { + (0..len).into_iter().map(Account).collect() +} diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 31dabde5ea766..f6c2f6d094967 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -19,15 +19,17 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_header_chain::justification::GrandpaJustification; -use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature, Signer}; -use finality_grandpa::voter_set::VoterSet; -use sp_application_crypto::{Public, TryFrom}; -use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; +use sp_application_crypto::TryFrom; +use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; use sp_finality_grandpa::{AuthoritySignature, SetId}; use sp_runtime::traits::{Header as HeaderT, One, Zero}; -use sp_runtime::RuntimeDebug; use sp_std::prelude::*; +// Re-export all our test account utilities +pub use keyring::*; + +mod keyring; + pub const TEST_GRANDPA_ROUND: u64 = 1; pub const TEST_GRANDPA_SET_ID: SetId = 1; @@ -40,7 +42,7 @@ pub struct JustificationGeneratorParams { /// The current authority set ID. pub set_id: SetId, /// The current GRANDPA authority set. - pub authorities: Vec<(Keyring, AuthorityWeight)>, + pub authorities: Vec<(Account, AuthorityWeight)>, /// The number of headers included in our justification's vote ancestries. pub depth: u32, /// The number of forks, and thus the number of pre-commits in our justification. @@ -53,7 +55,7 @@ impl Default for JustificationGeneratorParams { header: test_header(One::one()), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: keyring(), + authorities: test_keyring(), depth: 2, forks: 1, } @@ -157,7 +159,7 @@ fn generate_chain(fork_id: u8, depth: u32, ancestor: &H) -> Vec { } fn signed_precommit( - signer: &Keyring, + signer: &Account, target: (H::Hash, H::Number), round: u64, set_id: SetId, @@ -170,7 +172,7 @@ fn signed_precommit( let encoded = sp_finality_grandpa::localized_payload(round, set_id, &finality_grandpa::Message::Precommit(precommit.clone())); - let signature = signer.pair().sign(&encoded); + let signature = signer.sign(&encoded); let raw_signature: Vec = signature.to_bytes().into(); // Need to wrap our signature and id types that they match what our `SignedPrecommit` is expecting @@ -211,61 +213,3 @@ pub fn test_header(number: H::Number) -> H { pub fn header_id(index: u8) -> (H::Hash, H::Number) { (test_header::(index.into()).hash(), index.into()) } - -/// Set of test accounts. -#[derive(RuntimeDebug, Clone, Copy)] -pub enum Keyring { - Alice, - Bob, - Charlie, - Dave, - Eve, - Ferdie, -} - -impl Keyring { - pub fn public(&self) -> PublicKey { - (&self.secret()).into() - } - - pub fn secret(&self) -> SecretKey { - SecretKey::from_bytes(&[*self as u8; 32]).expect("A static array of the correct length is a known good.") - } - - pub fn pair(self) -> Keypair { - let mut pair: [u8; 64] = [0; 64]; - - let secret = self.secret(); - pair[..32].copy_from_slice(&secret.to_bytes()); - - let public = self.public(); - pair[32..].copy_from_slice(&public.to_bytes()); - - Keypair::from_bytes(&pair).expect("We expect the SecretKey to be good, so this must also be good.") - } - - pub fn sign(self, msg: &[u8]) -> Signature { - self.pair().sign(msg) - } -} - -impl From for AuthorityId { - fn from(k: Keyring) -> Self { - AuthorityId::from_slice(&k.public().to_bytes()) - } -} - -/// Get a valid set of voters for a Grandpa round. -pub fn voter_set() -> VoterSet { - VoterSet::new(authority_list()).unwrap() -} - -/// Convenience function to get a list of Grandpa authorities. -pub fn authority_list() -> AuthorityList { - keyring().iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect() -} - -/// Get the corresponding identities from the keyring for the "standard" authority set. -pub fn keyring() -> Vec<(Keyring, u64)> { - vec![(Keyring::Alice, 1), (Keyring::Bob, 1), (Keyring::Charlie, 1)] -} From a9a4ff72f7fcd19772625f336a9e4fb456be4dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 25 Mar 2021 16:04:09 +0100 Subject: [PATCH 0393/1210] Initialize logger properly. (#843) --- relays/utils/src/initialize.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index 6b0efb49e480b..40b541b3c2e79 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -21,13 +21,9 @@ use std::io::Write; /// Initialize relay environment. pub fn initialize_relay() { let mut builder = env_logger::Builder::new(); - - let filters = match std::env::var("RUST_LOG") { - Ok(env_filters) => format!("bridge=info,{}", env_filters), - Err(_) => "bridge=info".into(), - }; - - builder.parse_filters(&filters); + builder.filter_level(log::LevelFilter::Warn); + builder.filter_module("bridge", log::LevelFilter::Info); + builder.parse_default_env(); builder.format(move |buf, record| { writeln!(buf, "{}", { let timestamp = time::OffsetDateTime::try_now_local() From 37b1fda47ee0e54f3fc15f8236151842df9ce310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 25 Mar 2021 20:37:46 +0100 Subject: [PATCH 0394/1210] Expose storage of finality-verifier pallets. (#844) * Expose storage of finality-verifier pallets. * Fix compilation. --- bin/millau/runtime/src/lib.rs | 4 ++-- bin/rialto/runtime/src/lib.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 693543fa1c2c7..7ac3cc73bfbe2 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -379,8 +379,8 @@ construct_runtime!( BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeRialtoMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, - BridgeRialtoGrandpa: pallet_bridge_grandpa::{Module, Call}, - BridgeWestendGrandpa: pallet_bridge_grandpa::::{Module, Call, Config}, + BridgeRialtoGrandpa: pallet_bridge_grandpa::{Module, Call, Storage}, + BridgeWestendGrandpa: pallet_bridge_grandpa::::{Module, Call, Config, Storage}, System: frame_system::{Module, Call, Config, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index dcbb3510e156d..c2c50f05a77a5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -480,7 +480,7 @@ construct_runtime!( BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, - BridgeGrandpa: pallet_bridge_grandpa::{Module, Call}, + BridgeMillauGrandpa: pallet_bridge_grandpa::{Module, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, BridgeMillauMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, System: frame_system::{Module, Call, Config, Storage, Event}, @@ -643,12 +643,12 @@ impl_runtime_apis! { impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { - let header = BridgeGrandpa::best_finalized(); + let header = BridgeMillauGrandpa::best_finalized(); (header.number, header.hash()) } fn is_known_header(hash: bp_millau::Hash) -> bool { - BridgeGrandpa::is_known_header(hash) + BridgeMillauGrandpa::is_known_header(hash) } } From fc3a6fbeb6d80788379b2c7ab1bc8e9ce1f84b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 25 Mar 2021 23:12:02 +0100 Subject: [PATCH 0395/1210] Rococo (mocky)Runtime and Client (#841) * Implement fake rococo runtime. * Generate correct storage key. * cargo fmt --all * Move client-rococo. * Satisfy clippy. * Apply suggestions from code review Co-authored-by: Hernando Castano * Address review comments. * Clippy again. Co-authored-by: Hernando Castano --- primitives/chain-rococo/Cargo.toml | 11 +++ primitives/chain-rococo/src/lib.rs | 66 ++++++++++++++++ primitives/polkadot-core/Cargo.toml | 4 + primitives/polkadot-core/src/lib.rs | 91 +++++++++++++++++++++- relays/client-rococo/Cargo.toml | 23 ++++++ relays/client-rococo/src/lib.rs | 116 ++++++++++++++++++++++++++++ 6 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 relays/client-rococo/Cargo.toml create mode 100644 relays/client-rococo/src/lib.rs diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 863203ad8d741..667b11275ff3a 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } @@ -14,8 +15,14 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[dev-dependencies] +hex = "0.4" [features] default = ["std"] @@ -23,6 +30,10 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", + "parity-scale-codec/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", + "sp-version/std", ] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 13a99347807e4..3d1ce94c04313 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -21,10 +21,60 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use frame_support::{Blake2_128Concat, StorageHasher, Twox128}; use sp_std::prelude::*; +use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("rococo"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v1-1"), + authoring_version: 0, + spec_version: 30, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 6, +}; + +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + MockModule, +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} + +/// Return a storage key for account data. +/// +/// This is based on FRAME storage-generation code from Substrate: +/// https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74 +/// The equivalent command to invoke in case full `Runtime` is known is this: +/// `let key = frame_system::Account::::storage_map_final_key(&account_id);` +pub fn account_info_storage_key(id: &AccountId) -> Vec { + let module_prefix_hashed = Twox128::hash(b"System"); + let storage_prefix_hashed = Twox128::hash(b"Account"); + let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash); + + let mut final_key = Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(&key_hashed); + + final_key +} + /// Rococo Chain pub type Rococo = PolkadotLike; @@ -115,3 +165,19 @@ sp_api::decl_runtime_apis! { fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_generate_storage_key() { + let acc = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, + ] + .into(); + let key = account_info_storage_key(&acc); + assert_eq!(hex::encode(key), "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92dccd599abfe1920a1cff8a7358231430102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"); + } +} diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 8df209ca671ed..af5fe84d2a688 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies @@ -21,6 +22,7 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , sp-core = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -29,8 +31,10 @@ std = [ "bp-runtime/std", "frame-support/std", "frame-system/std", + "parity-scale-codec/std", "sp-api/std", "sp-core/std", "sp-runtime/std", "sp-std/std", + "sp-version/std", ] diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index f3f95637740e6..eaeddfa2afee3 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -19,6 +19,7 @@ use bp_messages::MessageNonce; use bp_runtime::Chain; use frame_support::{ + dispatch::Dispatchable, parameter_types, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, @@ -31,7 +32,7 @@ use sp_core::Hasher as HasherT; use sp_runtime::{ generic, traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, OpaqueExtrinsic as UncheckedExtrinsic, Perbill, + MultiSignature, OpaqueExtrinsic, Perbill, }; // Re-export's to avoid extra substrate dependencies in chain-specific crates. @@ -141,6 +142,12 @@ pub type BlockNumber = u32; /// Hash type used in Polkadot-like chains. pub type Hash = ::Out; +/// Account Index (a.k.a. nonce). +pub type Index = u32; + +/// Hashing type. +pub type Hashing = BlakeTwo256; + /// The type of an object that can produce hashes on Polkadot-like chains. pub type Hasher = BlakeTwo256; @@ -160,7 +167,7 @@ pub type AccountId = ::AccountId; pub type Nonce = u32; /// Block type of Polkadot-like chains. -pub type Block = generic::Block; +pub type Block = generic::Block; /// Polkadot-like block signed with a Justification. pub type SignedBlock = generic::SignedBlock; @@ -168,6 +175,86 @@ pub type SignedBlock = generic::SignedBlock; /// The balance of an account on Polkadot-like chain. pub type Balance = u128; +/// Unchecked Extrinsic type. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic>; + +/// A type of the data encoded as part of the transaction. +pub type SignedExtra = ((), (), (), sp_runtime::generic::Era, Nonce, (), Balance); + +/// Parameters which are part of the payload used to produce transaction signature, +/// but don't end up in the transaction itself (i.e. inherent part of the runtime). +pub type AdditionalSigned = (u32, u32, Hash, Hash, (), (), ()); + +/// A simplified version of signed extensions meant for producing signed transactions +/// and signed payload in the client code. +#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +pub struct SignedExtensions { + encode_payload: SignedExtra, + additional_signed: AdditionalSigned, + _data: sp_std::marker::PhantomData, +} + +impl parity_scale_codec::Encode for SignedExtensions { + fn using_encoded R>(&self, f: F) -> R { + self.encode_payload.using_encoded(f) + } +} + +impl parity_scale_codec::Decode for SignedExtensions { + fn decode(_input: &mut I) -> Result { + unimplemented!("SignedExtensions are never meant to be decoded, they are only used to create transaction"); + } +} + +impl SignedExtensions { + pub fn new( + version: sp_version::RuntimeVersion, + era: sp_runtime::generic::Era, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + ) -> Self { + Self { + encode_payload: ( + (), // spec version + (), // tx version + (), // genesis + era, // era + nonce, // nonce (compact encoding) + (), // Check weight + tip, // transaction payment / tip (compact encoding) + ), + additional_signed: ( + version.spec_version, + version.transaction_version, + genesis_hash, + genesis_hash, + (), + (), + (), + ), + _data: Default::default(), + } + } +} + +impl sp_runtime::traits::SignedExtension for SignedExtensions +where + Call: parity_scale_codec::Codec + sp_std::fmt::Debug + Sync + Send + Clone + Eq + PartialEq, + Call: Dispatchable, +{ + const IDENTIFIER: &'static str = "Not needed."; + + type AccountId = AccountId; + type Call = Call; + type AdditionalSigned = AdditionalSigned; + type Pre = (); + + fn additional_signed(&self) -> Result { + Ok(self.additional_signed) + } +} + /// Polkadot-like chain. #[derive(RuntimeDebug)] pub struct PolkadotLike; diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml new file mode 100644 index 0000000000000..095f365374a80 --- /dev/null +++ b/relays/client-rococo/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "relay-rococo-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + +# Bridge dependencies +bp-rococo = { path = "../../primitives/chain-rococo" } + +# Substrate Dependencies +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs new file mode 100644 index 0000000000000..3661b31e69e32 --- /dev/null +++ b/relays/client-rococo/src/lib.rs @@ -0,0 +1,116 @@ +// 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 . + +//! Types used to connect to the Rococo-Substrate chain. + +use codec::Encode; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Rococo header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Rococo chain definition +#[derive(Debug, Clone, Copy)] +pub struct Rococo; + +impl ChainBase for Rococo { + type BlockNumber = bp_rococo::BlockNumber; + type Hash = bp_rococo::Hash; + type Hasher = bp_rococo::Hashing; + type Header = bp_rococo::Header; +} + +impl Chain for Rococo { + const NAME: &'static str = "Rococo"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type AccountId = bp_rococo::AccountId; + type Index = bp_rococo::Index; + type SignedBlock = bp_rococo::SignedBlock; + type Call = bp_rococo::Call; +} + +impl ChainWithBalances for Rococo { + type NativeBalance = bp_rococo::Balance; + + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_rococo::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for Rococo { + type Chain = Rococo; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = bp_rococo::UncheckedExtrinsic; + + fn sign_transaction( + genesis_hash: ::Hash, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + call, + bp_rococo::SignedExtensions::new( + bp_rococo::VERSION, + sp_runtime::generic::Era::Immortal, + genesis_hash, + signer_nonce, + 0, + ), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_rococo::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + } +} + +/// Rococo signing params. +#[derive(Clone)] +pub struct SigningParams { + /// Substrate transactions signer. + pub signer: sp_core::sr25519::Pair, +} + +impl SigningParams { + /// Create signing params from SURI and password. + pub fn from_suri(suri: &str, password: Option<&str>) -> Result { + Ok(SigningParams { + signer: sp_core::sr25519::Pair::from_string(suri, password)?, + }) + } +} + +impl std::fmt::Debug for SigningParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.signer.public()) + } +} + +impl Default for SigningParams { + fn default() -> Self { + SigningParams { + signer: sp_keyring::AccountKeyring::Alice.pair(), + } + } +} + +/// Rococo header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; From 6f54960eb2e3001ad9762ccf9a3e0bb0befee75d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 26 Mar 2021 08:49:59 +0300 Subject: [PATCH 0396/1210] on-demand headers relay (#833) * on-demand headers relay * bool::then * move file * atomic submit_signed_extrinsic * remove cli options from future * test on-demand relay * TODOs * fixed initialization call for Westend -> Millau * Update relays/client-substrate/src/client.rs Co-authored-by: Hernando Castano * removed on_demand_headers_relay.rs * on_demand_headers_relay traces * fix compilation * fmt * docs Co-authored-by: Hernando Castano --- relays/bin-ethereum/src/rialto_client.rs | 46 ++-- relays/bin-substrate/src/finality_pipeline.rs | 19 +- relays/bin-substrate/src/finality_target.rs | 14 +- .../bin-substrate/src/headers_initialize.rs | 19 +- relays/bin-substrate/src/messages_lane.rs | 30 ++- relays/bin-substrate/src/messages_source.rs | 12 +- relays/bin-substrate/src/messages_target.rs | 16 +- .../rialto_millau/millau_headers_to_rialto.rs | 24 +- .../millau_messages_to_rialto.rs | 40 ++-- relays/bin-substrate/src/rialto_millau/mod.rs | 211 +++++++++--------- .../rialto_millau/rialto_headers_to_millau.rs | 25 ++- .../rialto_messages_to_millau.rs | 40 ++-- .../westend_headers_to_millau.rs | 25 ++- relays/client-substrate/src/client.rs | 33 ++- relays/messages/src/message_lane_loop.rs | 33 ++- relays/messages/src/message_race_delivery.rs | 4 + relays/messages/src/message_race_loop.rs | 11 + relays/messages/src/message_race_receiving.rs | 4 + 18 files changed, 375 insertions(+), 231 deletions(-) diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index 11eb200a1c316..c6d731b841c12 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -156,13 +156,21 @@ impl SubmitEthereumHeaders for SubstrateClient { ) -> SubmittedHeaders { let ids = headers.iter().map(|header| header.id()).collect(); let submission_result = async { - let account_id = params.signer.public().as_array_ref().clone().into(); - let nonce = self.next_account_index(account_id).await?; - - let call = instance.build_signed_header_call(headers); - let transaction = Rialto::sign_transaction(*self.genesis_hash(), ¶ms.signer, nonce, call); - - let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + self.submit_signed_extrinsic( + params.signer.public().as_array_ref().clone().into(), + |transaction_nonce| { + Bytes( + Rialto::sign_transaction( + *self.genesis_hash(), + ¶ms.signer, + transaction_nonce, + instance.build_signed_header_call(headers), + ) + .encode(), + ) + }, + ) + .await?; Ok(()) } .await; @@ -197,7 +205,7 @@ impl SubmitEthereumHeaders for SubstrateClient { let call = instance.build_unsigned_header_call(header); let transaction = create_unsigned_submit_transaction(call); - match self.submit_extrinsic(Bytes(transaction.encode())).await { + match self.submit_unsigned_extrinsic(Bytes(transaction.encode())).await { Ok(_) => submitted_headers.submitted.push(id), Err(error) => { submitted_headers.rejected.push(id); @@ -252,13 +260,21 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { instance: Arc, proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { - let account_id = params.signer.public().as_array_ref().clone().into(); - let nonce = self.next_account_index(account_id).await?; - - let call = instance.build_currency_exchange_call(proof); - let transaction = Rialto::sign_transaction(*self.genesis_hash(), ¶ms.signer, nonce, call); - - let _ = self.submit_extrinsic(Bytes(transaction.encode())).await?; + self.submit_signed_extrinsic( + params.signer.public().as_array_ref().clone().into(), + |transaction_nonce| { + Bytes( + Rialto::sign_transaction( + *self.genesis_hash(), + ¶ms.signer, + transaction_nonce, + instance.build_currency_exchange_call(proof), + ) + .encode(), + ) + }, + ) + .await?; Ok(()) } } diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index 0ddc4a9a8de98..d5ae55162e3f8 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -18,14 +18,13 @@ use crate::finality_target::SubstrateFinalityTarget; -use async_trait::async_trait; -use codec::Encode; use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; use relay_substrate_client::{ finality_source::{FinalitySource, Justification}, - BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, SyncHeader, + BlockNumberOf, Chain, Client, HashOf, SyncHeader, }; use relay_utils::BlockNumberBase; +use sp_core::Bytes; use std::{fmt::Debug, marker::PhantomData, time::Duration}; /// Default synchronization loop timeout. @@ -37,20 +36,23 @@ const STALL_TIMEOUT: Duration = Duration::from_secs(120); const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; /// Headers sync pipeline for Substrate <-> Substrate relays. -#[async_trait] pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { /// Name of the runtime method that returns id of best finalized source header at target chain. const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; - /// Signed transaction type. - type SignedTransaction: Send + Sync + Encode; + /// Chain with GRANDPA bridge pallet. + type TargetChain: Chain; + + /// Returns id of account that we're using to sign transactions at target chain. + fn transactions_author(&self) -> ::AccountId; /// Make submit header transaction. - async fn make_submit_finality_proof_transaction( + fn make_submit_finality_proof_transaction( &self, + transaction_nonce: ::Index, header: Self::Header, proof: Self::FinalityProof, - ) -> Result; + ) -> Bytes; } /// Substrate-to-Substrate finality proof pipeline. @@ -105,6 +107,7 @@ where Number = BlockNumberOf, Header = SyncHeader, FinalityProof = Justification, + TargetChain = TargetChain, >, SourceChain: Clone + Chain, BlockNumberOf: BlockNumberBase, diff --git a/relays/bin-substrate/src/finality_target.rs b/relays/bin-substrate/src/finality_target.rs index 18312556f9e17..37f433ad06d05 100644 --- a/relays/bin-substrate/src/finality_target.rs +++ b/relays/bin-substrate/src/finality_target.rs @@ -21,12 +21,10 @@ use crate::finality_pipeline::SubstrateFinalitySyncPipeline; use async_trait::async_trait; -use codec::{Decode, Encode}; +use codec::Decode; use finality_relay::TargetClient; -use futures::TryFutureExt; use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_utils::relay_loop::Client as RelayClient; -use sp_core::Bytes; /// Substrate client as Substrate finality target. pub struct SubstrateFinalityTarget { @@ -65,7 +63,7 @@ where C: Chain, P::Number: Decode, P::Hash: Decode, - P: SubstrateFinalitySyncPipeline, + P: SubstrateFinalitySyncPipeline, { async fn best_finalized_source_block_number(&self) -> Result { // we can't continue to relay finality if target node is out of sync, because @@ -82,9 +80,11 @@ where } async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), SubstrateError> { - self.pipeline - .make_submit_finality_proof_transaction(header, proof) - .and_then(|tx| self.client.submit_extrinsic(Bytes(tx.encode()))) + self.client + .submit_signed_extrinsic(self.pipeline.transactions_author(), move |transaction_nonce| { + self.pipeline + .make_submit_finality_proof_transaction(transaction_nonce, header, proof) + }) .await .map(drop) } diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index 768d299acde77..bc191df3b7153 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -38,9 +38,16 @@ use sp_runtime::traits::Header as HeaderT; pub async fn initialize( source_client: Client, target_client: Client, - prepare_initialize_transaction: impl FnOnce(InitializationData) -> Result, + target_transactions_signer: TargetChain::AccountId, + prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes, ) { - let result = do_initialize(source_client, target_client, prepare_initialize_transaction).await; + let result = do_initialize( + source_client, + target_client, + target_transactions_signer, + prepare_initialize_transaction, + ) + .await; match result { Ok(tx_hash) => log::info!( @@ -64,7 +71,8 @@ pub async fn initialize( async fn do_initialize( source_client: Client, target_client: Client, - prepare_initialize_transaction: impl FnOnce(InitializationData) -> Result, + target_transactions_signer: TargetChain::AccountId, + prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes, ) -> Result { let initialization_data = prepare_initialization_data(source_client).await?; log::info!( @@ -75,9 +83,10 @@ async fn do_initialize( initialization_data, ); - let initialization_tx = prepare_initialize_transaction(initialization_data)?; let initialization_tx_hash = target_client - .submit_extrinsic(initialization_tx) + .submit_signed_extrinsic(target_transactions_signer, move |transaction_nonce| { + prepare_initialize_transaction(transaction_nonce, initialization_data) + }) .await .map_err(|err| format!("Failed to submit {} transaction: {:?}", TargetChain::NAME, err))?; Ok(initialization_tx_hash) diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 372b47f2a2635..01814ad6a9c6f 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -17,17 +17,15 @@ use crate::messages_source::SubstrateMessagesProof; use crate::messages_target::SubstrateMessagesReceivingProof; -use async_trait::async_trait; use bp_messages::MessageNonce; -use codec::Encode; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use relay_substrate_client::{BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; +use relay_substrate_client::{BlockNumberOf, Chain, Client, HashOf}; use relay_utils::BlockNumberBase; +use sp_core::Bytes; use std::ops::RangeInclusive; /// Message sync pipeline for Substrate <-> Substrate relays. -#[async_trait] pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str; @@ -48,25 +46,33 @@ pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns id of best finalized target header at source chain. const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str; - /// Signed transaction type of the source chain. - type SourceSignedTransaction: Send + Sync + Encode; - /// Signed transaction type of the target chain. - type TargetSignedTransaction: Send + Sync + Encode; + /// Source chain. + type SourceChain: Chain; + /// Target chain. + type TargetChain: Chain; + + /// Returns id of account that we're using to sign transactions at target chain (messages proof). + fn target_transactions_author(&self) -> ::AccountId; /// Make messages delivery transaction. - async fn make_messages_delivery_transaction( + fn make_messages_delivery_transaction( &self, + transaction_nonce: ::Index, generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: Self::MessagesProof, - ) -> Result; + ) -> Bytes; + + /// Returns id of account that we're using to sign transactions at source chain (delivery proof). + fn source_transactions_author(&self) -> ::AccountId; /// Make messages receiving proof transaction. - async fn make_messages_receiving_proof_transaction( + fn make_messages_receiving_proof_transaction( &self, + transaction_nonce: ::Index, generated_at_header: TargetHeaderIdOf, proof: Self::MessagesReceivingProof, - ) -> Result; + ) -> Bytes; } /// Substrate-to-Substrate message lane. diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 607247f8c0033..278fff6d2d99e 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -94,6 +94,7 @@ where MessagesProof = SubstrateMessagesProof, SourceHeaderNumber = ::Number, SourceHeaderHash = ::Hash, + SourceChain = C, >, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, @@ -197,13 +198,16 @@ where generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, ) -> Result<(), SubstrateError> { - let tx = self - .lane - .make_messages_receiving_proof_transaction(generated_at_block, proof) + self.client + .submit_signed_extrinsic(self.lane.source_transactions_author(), move |transaction_nonce| { + self.lane + .make_messages_receiving_proof_transaction(transaction_nonce, generated_at_block, proof) + }) .await?; - self.client.submit_extrinsic(Bytes(tx.encode())).await?; Ok(()) } + + async fn activate_target_to_source_headers_relay(&self, _activate: bool) {} } pub async fn read_client_state( diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index ec2d751d37785..3d8ab4fd0045f 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -90,6 +90,7 @@ where C::Index: DeserializeOwned, ::Number: BlockNumberBase, P: SubstrateMessageLane< + TargetChain = C, MessagesReceivingProof = SubstrateMessagesReceivingProof, TargetHeaderNumber = ::Number, TargetHeaderHash = ::Hash, @@ -183,11 +184,18 @@ where nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result, SubstrateError> { - let tx = self - .lane - .make_messages_delivery_transaction(generated_at_header, nonces.clone(), proof) + self.client + .submit_signed_extrinsic(self.lane.target_transactions_author(), |transaction_nonce| { + self.lane.make_messages_delivery_transaction( + transaction_nonce, + generated_at_header, + nonces.clone(), + proof, + ) + }) .await?; - self.client.submit_extrinsic(Bytes(tx.encode())).await?; Ok(nonces) } + + async fn activate_source_to_target_headers_relay(&self, _activate: bool) {} } diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index a14fb691275a2..5a30974ba4c47 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -19,36 +19,38 @@ use super::{MillauClient, RialtoClient}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; -use async_trait::async_trait; +use codec::Encode; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{finality_source::Justification, Error as SubstrateError, TransactionSignScheme}; -use sp_core::Pair; +use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme}; +use sp_core::{Bytes, Pair}; /// Millau-to-Rialto finality sync pipeline. pub(crate) type MillauFinalityToRialto = SubstrateFinalityToSubstrate; -#[async_trait] impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - type SignedTransaction = ::SignedTransaction; + type TargetChain = Rialto; - async fn make_submit_finality_proof_transaction( + fn transactions_author(&self) -> bp_rialto::AccountId { + self.target_sign.signer.public().as_array_ref().clone().into() + } + + fn make_submit_finality_proof_transaction( &self, + transaction_nonce: ::Index, header: MillauSyncHeader, proof: Justification, - ) -> Result { - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; + ) -> Bytes { let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner()) .into(); let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); - Ok(transaction) + Bytes(transaction.encode()) } } diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index df2cb3a03dee7..edfd907776500 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -21,7 +21,6 @@ use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageL use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; -use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; @@ -30,15 +29,14 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Error as SubstrateError, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; -use sp_core::Pair; +use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; /// Millau-to-Rialto message lane. type MillauMessagesToRialto = SubstrateMessageLaneToSubstrate; -#[async_trait] impl SubstrateMessageLane for MillauMessagesToRialto { const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD; @@ -54,22 +52,25 @@ impl SubstrateMessageLane for MillauMessagesToRialto { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - type SourceSignedTransaction = ::SignedTransaction; - type TargetSignedTransaction = ::SignedTransaction; + type SourceChain = Millau; + type TargetChain = Rialto; - async fn make_messages_receiving_proof_transaction( + fn source_transactions_author(&self) -> bp_rialto::AccountId { + self.source_sign.signer.public().as_array_ref().clone().into() + } + + fn make_messages_receiving_proof_transaction( &self, + transaction_nonce: ::Index, _generated_at_block: RialtoHeaderId, proof: ::MessagesReceivingProof, - ) -> Result { + ) -> Bytes { let (relayers_state, proof) = proof; - let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.source_client.next_account_index(account_id).await?; let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign.signer, nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign.signer, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -78,15 +79,20 @@ impl SubstrateMessageLane for MillauMessagesToRialto { transaction.encode().len(), bp_millau::max_extrinsic_size(), ); - Ok(transaction) + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_rialto::AccountId { + self.target_sign.signer.public().as_array_ref().clone().into() } - async fn make_messages_delivery_transaction( + fn make_messages_delivery_transaction( &self, + transaction_nonce: ::Index, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, proof: ::MessagesProof, - ) -> Result { + ) -> Bytes { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { ref nonces_start, @@ -94,8 +100,6 @@ impl SubstrateMessageLane for MillauMessagesToRialto { .. } = proof; let messages_count = nonces_end - nonces_start + 1; - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, @@ -105,7 +109,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", @@ -114,7 +118,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { transaction.encode().len(), bp_rialto::max_extrinsic_size(), ); - Ok(transaction) + Bytes(transaction.encode()) } } diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index eadee1484f7b5..df9e36a0c450c 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -53,24 +53,25 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { let rialto_client = rialto.into_client().await?; let rialto_sign = rialto_sign.parse()?; - let rialto_signer_next_index = rialto_client - .next_account_index(rialto_sign.signer.public().into()) - .await?; - - crate::headers_initialize::initialize(millau_client, rialto_client.clone(), move |initialization_data| { - Ok(Bytes( - Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, - rialto_signer_next_index, - rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::BridgeGrandpaMillauCall::initialize(initialization_data).into(), - )) - .into(), + crate::headers_initialize::initialize( + millau_client, + rialto_client.clone(), + rialto_sign.signer.public().into(), + move |transaction_nonce, initialization_data| { + Bytes( + Rialto::sign_transaction( + *rialto_client.genesis_hash(), + &rialto_sign.signer, + transaction_nonce, + rialto_runtime::SudoCall::sudo(Box::new( + rialto_runtime::BridgeGrandpaMillauCall::initialize(initialization_data).into(), + )) + .into(), + ) + .encode(), ) - .encode(), - )) - }) + }, + ) .await; } cli::InitBridge::RialtoToMillau { @@ -81,26 +82,28 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { let rialto_client = rialto.into_client().await?; let millau_client = millau.into_client().await?; let millau_sign = millau_sign.parse()?; - let millau_signer_next_index = millau_client - .next_account_index(millau_sign.signer.public().into()) - .await?; - crate::headers_initialize::initialize(rialto_client, millau_client.clone(), move |initialization_data| { - let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::< - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >::initialize(initialization_data); - - Ok(Bytes( - Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - millau_signer_next_index, - millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into(), + crate::headers_initialize::initialize( + rialto_client, + millau_client.clone(), + millau_sign.signer.public().into(), + move |transaction_nonce, initialization_data| { + let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::< + millau_runtime::Runtime, + millau_runtime::RialtoGrandpaInstance, + >::initialize(initialization_data); + + Bytes( + Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + transaction_nonce, + millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into(), + ) + .encode(), ) - .encode(), - )) - }) + }, + ) .await; } cli::InitBridge::WestendToMillau { @@ -111,29 +114,31 @@ async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { let westend_client = westend.into_client().await?; let millau_client = millau.into_client().await?; let millau_sign = millau_sign.parse()?; - let millau_signer_next_index = millau_client - .next_account_index(millau_sign.signer.public().into()) - .await?; // at Westend -> Millau initialization we're not using sudo, because otherwise our deployments // may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge. // => since there's single possible sudo account, one of transaction may fail with duplicate nonce error - crate::headers_initialize::initialize(westend_client, millau_client.clone(), move |initialization_data| { - let initialize_call = millau_runtime::BridgeGrandpaWestendCall::< - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >::initialize(initialization_data); - - Ok(Bytes( - Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - millau_signer_next_index, - initialize_call.into(), + crate::headers_initialize::initialize( + westend_client, + millau_client.clone(), + millau_sign.signer.public().into(), + move |transaction_nonce, initialization_data| { + let initialize_call = millau_runtime::BridgeGrandpaWestendCall::< + millau_runtime::Runtime, + millau_runtime::WestendGrandpaInstance, + >::initialize(initialization_data); + + Bytes( + Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + transaction_nonce, + initialize_call.into(), + ) + .encode(), ) - .encode(), - )) - }) + }, + ) .await; } } @@ -262,30 +267,32 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { }) .await?; - let millau_call = millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( - lane, payload, fee, - )); - - let signed_millau_call = Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - millau_client - .next_account_index(millau_sign.signer.public().clone().into()) - .await?, - millau_call, - ) - .encode(); - - log::info!( - target: "bridge", - "Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}", - signed_millau_call.len(), - dispatch_weight, - fee, - ); - log::info!(target: "bridge", "Signed Millau Call: {:?}", HexBytes::encode(&signed_millau_call)); - - millau_client.submit_extrinsic(Bytes(signed_millau_call)).await?; + millau_client + .submit_signed_extrinsic(millau_sign.signer.public().clone().into(), |transaction_nonce| { + let millau_call = millau_runtime::Call::BridgeRialtoMessages( + millau_runtime::MessagesCall::send_message(lane, payload, fee), + ); + + let signed_millau_call = Millau::sign_transaction( + *millau_client.genesis_hash(), + &millau_sign.signer, + transaction_nonce, + millau_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}", + signed_millau_call.len(), + dispatch_weight, + fee, + ); + log::info!(target: "bridge", "Signed Millau Call: {:?}", HexBytes::encode(&signed_millau_call)); + + Bytes(signed_millau_call) + }) + .await?; } cli::SendMessage::RialtoToMillau { rialto, @@ -318,30 +325,32 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { }) .await?; - let rialto_call = rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( - lane, payload, fee, - )); - - let signed_rialto_call = Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, - rialto_client - .next_account_index(rialto_sign.signer.public().clone().into()) - .await?, - rialto_call, - ) - .encode(); - - log::info!( - target: "bridge", - "Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}", - signed_rialto_call.len(), - dispatch_weight, - fee, - ); - log::info!(target: "bridge", "Signed Rialto Call: {:?}", HexBytes::encode(&signed_rialto_call)); - - rialto_client.submit_extrinsic(Bytes(signed_rialto_call)).await?; + rialto_client + .submit_signed_extrinsic(rialto_sign.signer.public().clone().into(), |transaction_nonce| { + let rialto_call = rialto_runtime::Call::BridgeMillauMessages( + rialto_runtime::MessagesCall::send_message(lane, payload, fee), + ); + + let signed_rialto_call = Rialto::sign_transaction( + *rialto_client.genesis_hash(), + &rialto_sign.signer, + transaction_nonce, + rialto_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}", + signed_rialto_call.len(), + dispatch_weight, + fee, + ); + log::info!(target: "bridge", "Signed Rialto Call: {:?}", HexBytes::encode(&signed_rialto_call)); + + Bytes(signed_rialto_call) + }) + .await?; } } Ok(()) diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index 3a6e7a8fc3028..910d2bf03bf46 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -19,29 +19,30 @@ use super::{MillauClient, RialtoClient}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; -use async_trait::async_trait; +use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{finality_source::Justification, Error as SubstrateError, TransactionSignScheme}; -use sp_core::Pair; +use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme}; +use sp_core::{Bytes, Pair}; /// Rialto-to-Millau finality sync pipeline. pub(crate) type RialtoFinalityToMillau = SubstrateFinalityToSubstrate; -#[async_trait] impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - type SignedTransaction = ::SignedTransaction; + type TargetChain = Millau; - async fn make_submit_finality_proof_transaction( + fn transactions_author(&self) -> bp_millau::AccountId { + self.target_sign.signer.public().as_array_ref().clone().into() + } + + fn make_submit_finality_proof_transaction( &self, + transaction_nonce: ::Index, header: RialtoSyncHeader, proof: Justification, - ) -> Result { - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; - + ) -> Bytes { let call = millau_runtime::BridgeGrandpaRialtoCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, @@ -49,9 +50,9 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { .into(); let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); - Ok(transaction) + Bytes(transaction.encode()) } } diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index 97df3734ff7d8..7268ff07e00db 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -21,7 +21,6 @@ use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageL use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; -use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; @@ -30,15 +29,14 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Error as SubstrateError, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; -use sp_core::Pair; +use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; /// Rialto-to-Millau message lane. type RialtoMessagesToMillau = SubstrateMessageLaneToSubstrate; -#[async_trait] impl SubstrateMessageLane for RialtoMessagesToMillau { const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD; @@ -54,22 +52,25 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - type SourceSignedTransaction = ::SignedTransaction; - type TargetSignedTransaction = ::SignedTransaction; + type SourceChain = Rialto; + type TargetChain = Millau; - async fn make_messages_receiving_proof_transaction( + fn source_transactions_author(&self) -> bp_rialto::AccountId { + self.source_sign.signer.public().as_array_ref().clone().into() + } + + fn make_messages_receiving_proof_transaction( &self, + transaction_nonce: ::Index, _generated_at_block: MillauHeaderId, proof: ::MessagesReceivingProof, - ) -> Result { + ) -> Bytes { let (relayers_state, proof) = proof; - let account_id = self.source_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.source_client.next_account_index(account_id).await?; let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign.signer, nonce, call); + let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign.signer, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -78,15 +79,20 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { transaction.encode().len(), bp_rialto::max_extrinsic_size(), ); - Ok(transaction) + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_rialto::AccountId { + self.target_sign.signer.public().as_array_ref().clone().into() } - async fn make_messages_delivery_transaction( + fn make_messages_delivery_transaction( &self, + transaction_nonce: ::Index, _generated_at_header: RialtoHeaderId, _nonces: RangeInclusive, proof: ::MessagesProof, - ) -> Result { + ) -> Bytes { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { ref nonces_start, @@ -94,8 +100,6 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { .. } = proof; let messages_count = nonces_end - nonces_start + 1; - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof( self.relayer_id_at_source.clone(), proof, @@ -105,7 +109,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", @@ -114,7 +118,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { transaction.encode().len(), bp_millau::max_extrinsic_size(), ); - Ok(transaction) + Bytes(transaction.encode()) } } diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index 4f2ed8a211734..ca670e05f3285 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -19,29 +19,30 @@ use super::{MillauClient, WestendClient}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; -use async_trait::async_trait; +use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{finality_source::Justification, Error as SubstrateError, TransactionSignScheme}; +use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme}; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; -use sp_core::Pair; +use sp_core::{Bytes, Pair}; /// Westend-to-Millau finality sync pipeline. pub(crate) type WestendFinalityToMillau = SubstrateFinalityToSubstrate; -#[async_trait] impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; - type SignedTransaction = ::SignedTransaction; + type TargetChain = Millau; - async fn make_submit_finality_proof_transaction( + fn transactions_author(&self) -> bp_millau::AccountId { + self.target_sign.signer.public().as_array_ref().clone().into() + } + + fn make_submit_finality_proof_transaction( &self, + transaction_nonce: ::Index, header: WestendSyncHeader, proof: Justification, - ) -> Result { - let account_id = self.target_sign.signer.public().as_array_ref().clone().into(); - let nonce = self.target_client.next_account_index(account_id).await?; - + ) -> Bytes { let call = millau_runtime::BridgeGrandpaWestendCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, @@ -49,9 +50,9 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { .into(); let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); - Ok(transaction) + Bytes(transaction.encode()) } } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 56fcb33bf92cb..a03cf493ca105 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -20,6 +20,7 @@ use crate::chain::{Chain, ChainWithBalances}; use crate::rpc::{Substrate, SubstrateMessages}; use crate::{ConnectionParams, Error, Result}; +use async_std::sync::{Arc, Mutex}; use bp_messages::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use codec::Decode; @@ -52,6 +53,10 @@ pub struct Client { client: RpcClient, /// Genesis block hash. genesis_hash: C::Hash, + /// If several tasks are submitting their transactions simultaneously using `submit_signed_extrinsic` + /// method, they may get the same transaction nonce. So one of transactions will be rejected + /// from the pool. This lock is here to prevent situations like that. + submit_signed_extrinsic_lock: Arc>, } impl Clone for Client { @@ -60,6 +65,7 @@ impl Clone for Client { params: self.params.clone(), client: self.client.clone(), genesis_hash: self.genesis_hash, + submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(), } } } @@ -84,6 +90,7 @@ impl Client { params, client, genesis_hash, + submit_signed_extrinsic_lock: Arc::new(Mutex::new(())), }) } @@ -192,15 +199,35 @@ impl Client { Ok(Substrate::::system_account_next_index(&self.client, account).await?) } - /// Submit an extrinsic for inclusion in a block. + /// Submit unsigned extrinsic for inclusion in a block. /// - /// Note: The given transaction does not need be SCALE encoded beforehand. - pub async fn submit_extrinsic(&self, transaction: Bytes) -> Result { + /// Note: The given transaction needs to be SCALE encoded beforehand. + pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { let tx_hash = Substrate::::author_submit_extrinsic(&self.client, transaction).await?; log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); Ok(tx_hash) } + /// Submit an extrinsic signed by given account. + /// + /// All calls of this method are synchronized, so there can't be more than one active + /// `submit_signed_extrinsic()` call. This guarantees that no nonces collision may happen + /// if all client instances are clones of the same initial `Client`. + /// + /// Note: The given transaction needs to be SCALE encoded beforehand. + pub async fn submit_signed_extrinsic( + &self, + extrinsic_signer: C::AccountId, + prepare_extrinsic: impl FnOnce(C::Index) -> Bytes, + ) -> Result { + let _guard = self.submit_signed_extrinsic_lock.lock().await; + let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let extrinsic = prepare_extrinsic(transaction_nonce); + let tx_hash = Substrate::::author_submit_extrinsic(&self.client, extrinsic).await?; + log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); + Ok(tx_hash) + } + /// Get the GRANDPA authority set at given block. pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 77265f4ac96b7..159bd4c769592 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -139,6 +139,9 @@ pub trait SourceClient: RelayClient { generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, ) -> Result<(), Self::Error>; + + /// Activate (or deactivate) headers relay that relays target headers to source node. + async fn activate_target_to_source_headers_relay(&self, activate: bool); } /// Target client trait. @@ -177,6 +180,9 @@ pub trait TargetClient: RelayClient { nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result, Self::Error>; + + /// Activate (or deactivate) headers relay that relays source headers to target node. + async fn activate_source_to_target_headers_relay(&self, activate: bool); } /// State of the client. @@ -463,6 +469,8 @@ pub(crate) mod tests { target_latest_received_nonce: MessageNonce, target_latest_confirmed_received_nonce: MessageNonce, submitted_messages_proofs: Vec, + is_target_to_source_headers_relay_activated: bool, + is_source_to_target_headers_relay_activated: bool, } #[derive(Clone)] @@ -567,6 +575,12 @@ pub(crate) mod tests { data.source_latest_confirmed_received_nonce = proof; Ok(()) } + + async fn activate_target_to_source_headers_relay(&self, activate: bool) { + let mut data = self.data.lock(); + data.is_target_to_source_headers_relay_activated = activate; + (self.tick)(&mut *data); + } } #[derive(Clone)] @@ -665,6 +679,12 @@ pub(crate) mod tests { data.submitted_messages_proofs.push(proof); Ok(nonces) } + + async fn activate_source_to_target_headers_relay(&self, activate: bool) { + let mut data = self.data.lock(); + data.is_source_to_target_headers_relay_activated = activate; + (self.tick)(&mut *data); + } } fn run_loop_test( @@ -778,8 +798,19 @@ pub(crate) mod tests { target_latest_received_nonce: 0, ..Default::default() }, - Arc::new(|_: &mut TestClientData| {}), + Arc::new(|data: &mut TestClientData| { + // headers relay must only be started when we need new target headers at source node + if data.is_target_to_source_headers_relay_activated { + assert!(data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_self.0); + data.is_target_to_source_headers_relay_activated = false; + } + }), Arc::new(move |data: &mut TestClientData| { + // headers relay must only be started when we need new source headers at target node + if data.is_target_to_source_headers_relay_activated { + assert!(data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_self.0); + data.is_target_to_source_headers_relay_activated = false; + } // syncing source headers -> target chain (all at once) if data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_finalized_self.0 { data.target_state.best_finalized_peer_at_best_self = data.source_state.best_finalized_self; diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 1ee39c9c9f908..80709055be0e9 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -166,6 +166,10 @@ where type Error = C::Error; type TargetNoncesData = DeliveryRaceTargetNoncesData; + async fn require_more_source_headers(&self, activate: bool) { + self.client.activate_source_to_target_headers_relay(activate).await + } + async fn nonces( &self, at_block: TargetHeaderIdOf

, diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 2c04466f1fb5f..56bc881bf7a9a 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -123,6 +123,9 @@ pub trait TargetClient { /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; + /// Ask headers relay to relay more headers from race source to race target. + async fn require_more_source_headers(&self, activate: bool); + /// Return nonces that are known to the target client. async fn nonces( &self, @@ -216,6 +219,7 @@ pub async fn run, TC: TargetClient

>( TargetNoncesData = TC::TargetNoncesData, >, ) -> Result<(), FailedClient> { + let mut is_strategy_empty = true; let mut progress_context = Instant::now(); let mut race_state = RaceState::default(); let mut stall_countdown = Instant::now(); @@ -404,6 +408,13 @@ pub async fn run, TC: TargetClient

>( progress_context = print_race_progress::(progress_context, &strategy); + // ask for more headers if we have nonces to deliver + let prev_is_strategy_empty = is_strategy_empty; + is_strategy_empty = strategy.is_empty(); + if is_strategy_empty != prev_is_strategy_empty { + race_target.require_more_source_headers(!is_strategy_empty).await; + } + if stall_countdown.elapsed() > stall_timeout { log::warn!( target: "bridge", diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index 0fc025abb7d1a..2178882437eb6 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -159,6 +159,10 @@ where type Error = C::Error; type TargetNoncesData = (); + async fn require_more_source_headers(&self, activate: bool) { + self.client.activate_target_to_source_headers_relay(activate).await + } + async fn nonces( &self, at_block: SourceHeaderIdOf

, From 8a29fbca554ebd2546fd587ba862ec1332840ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 30 Mar 2021 23:53:39 +0200 Subject: [PATCH 0397/1210] Correctly format SS58-prefixed addresses in the CLI (#845) * Fix SS58 formatting of addresses. * cargo fmt --all * Use only lifetime hint. * Update relays/bin-substrate/src/cli.rs Co-authored-by: Hernando Castano * Remove unnecessary optimisation. * Add re-formatting test. * cargo fmt --all Co-authored-by: Hernando Castano --- relays/bin-substrate/src/cli.rs | 102 ++++++++++++++---- relays/bin-substrate/src/main.rs | 4 +- relays/bin-substrate/src/rialto_millau/mod.rs | 87 ++++++++++----- relays/utils/src/initialize.rs | 86 +++++++++++---- 4 files changed, 207 insertions(+), 72 deletions(-) diff --git a/relays/bin-substrate/src/cli.rs b/relays/bin-substrate/src/cli.rs index d6623b671d1c5..f871b7919b096 100644 --- a/relays/bin-substrate/src/cli.rs +++ b/relays/bin-substrate/src/cli.rs @@ -16,6 +16,8 @@ //! Deal with CLI args of substrate-to-substrate relay. +use std::convert::TryInto; + use bp_messages::LaneId; use codec::{Decode, Encode}; use sp_runtime::app_crypto::Ss58Codec; @@ -239,50 +241,78 @@ arg_enum! { } /// Generic account id with custom parser. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AccountId { account: sp_runtime::AccountId32, - version: sp_core::crypto::Ss58AddressFormat, + ss58_format: sp_core::crypto::Ss58AddressFormat, +} + +impl std::fmt::Display for AccountId { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{}", self.account.to_ss58check_with_version(self.ss58_format)) + } } impl std::str::FromStr for AccountId { type Err = String; fn from_str(s: &str) -> Result { - let (account, version) = sp_runtime::AccountId32::from_ss58check_with_version(s) + let (account, ss58_format) = sp_runtime::AccountId32::from_ss58check_with_version(s) .map_err(|err| format!("Unable to decode SS58 address: {:?}", err))?; - Ok(Self { account, version }) + Ok(Self { account, ss58_format }) } } -impl AccountId { - /// Perform runtime checks of SS58 version and get Rialto's AccountId. - pub fn into_rialto(self) -> bp_rialto::AccountId { - self.check_and_get("Rialto", rialto_runtime::SS58Prefix::get()) - } +const SS58_FORMAT_PROOF: &str = "u16 -> Ss58Format is infallible; qed"; - /// Perform runtime checks of SS58 version and get Millau's AccountId. - pub fn into_millau(self) -> bp_millau::AccountId { - self.check_and_get("Millau", millau_runtime::SS58Prefix::get()) +impl AccountId { + /// Create new SS58-formatted address from raw account id. + pub fn from_raw(account: sp_runtime::AccountId32) -> Self { + Self { + account, + ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF), + } } - /// Check SS58Prefix and return the account id. - fn check_and_get(self, net: &str, expected_prefix: u8) -> sp_runtime::AccountId32 { - let version: u16 = self.version.into(); - println!("Version: {} vs {}", version, expected_prefix); - if version != expected_prefix as u16 { + /// Enforces formatting account to be for given `AccountChain` type. + /// + /// This will change the `ss58format` of the account to match the requested one. + /// Note that a warning will be produced in case the current format does not match + /// the requested one, but the conversion always succeeds. + pub fn enforce_chain(&mut self) { + let original = self.clone(); + self.ss58_format = T::ss58_format().try_into().expect(SS58_FORMAT_PROOF); + log::debug!("{} SS58 format: {} (RAW: {})", self, self.ss58_format, self.account); + if original.ss58_format != self.ss58_format { log::warn!( target: "bridge", - "Following address: {} does not seem to match {}'s format, got: {}", - self.account, - net, - self.version, + "Address {} does not seem to match {}'s SS58 format (got: {}, expected: {}).\nConverted to: {}", + original, + T::NAME, + original.ss58_format, + self.ss58_format, + self, ) } - self.account + } + + /// Returns the raw (no SS58-prefixed) account id. + pub fn raw_id(&self) -> sp_runtime::AccountId32 { + self.account.clone() } } +/// A trait representing an account address bound to a specific chain. +/// +/// Can be used to convert [`AccountId`] formatting to be chain-specific. +pub trait AccountChain { + /// Network name associated with the SS58 format. + const NAME: &'static str; + + /// Numeric value of SS58 format. + fn ss58_format() -> u16; +} + /// Lane id. #[derive(Debug)] pub struct HexLaneId(pub LaneId); @@ -414,3 +444,31 @@ macro_rules! declare_chain_options { } }; } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + #[test] + fn should_format_addresses_with_ss58_format() { + // given + let rialto1 = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU"; + let rialto2 = "5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2"; + let millau1 = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"; + let millau2 = "74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5"; + + let expected = vec![rialto1, rialto2, millau1, millau2]; + + // when + let parsed = expected + .iter() + .map(|s| AccountId::from_str(s).unwrap()) + .collect::>(); + + let actual = parsed.iter().map(|a| format!("{}", a)).collect::>(); + + assert_eq!(actual, expected) + } +} diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index eaaa9848836e9..4047c0b54e453 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -18,7 +18,7 @@ #![warn(missing_docs)] -use relay_utils::initialize::initialize_relay; +use relay_utils::initialize::initialize_logger; mod cli; mod finality_pipeline; @@ -31,7 +31,7 @@ mod messages_target; mod rialto_millau; fn main() { - initialize_relay(); + initialize_logger(false); let command = cli::parse_args(); let run = command.run(); let result = async_std::task::block_on(run); diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index df9e36a0c450c..51e9d2898d2cb 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -30,7 +30,7 @@ pub type RialtoClient = relay_substrate_client::Client; /// Westend node client. pub type WestendClient = relay_substrate_client::Client; -use crate::cli::{ExplicitOrMaximal, HexBytes, Origins}; +use crate::cli::{AccountChain, AccountId, ExplicitOrMaximal, HexBytes, Origins}; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; @@ -426,23 +426,21 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { match cmd { - cli::DeriveAccount::RialtoToMillau { account } => { - let account = account.into_rialto(); - let acc = bp_runtime::SourceAccount::Account(account.clone()); + cli::DeriveAccount::RialtoToMillau { mut account } => { + account.enforce_chain::(); + let acc = bp_runtime::SourceAccount::Account(account.raw_id()); let id = bp_millau::derive_account_from_rialto_id(acc); - println!( - "{} (Rialto)\n\nCorresponding (derived) account id:\n-> {} (Millau)", - account, id - ) + let derived_account = AccountId::from_raw::(id); + println!("Source address:\n{} (Rialto)", account); + println!("->Corresponding (derived) address:\n{} (Millau)", derived_account); } - cli::DeriveAccount::MillauToRialto { account } => { - let account = account.into_millau(); - let acc = bp_runtime::SourceAccount::Account(account.clone()); + cli::DeriveAccount::MillauToRialto { mut account } => { + account.enforce_chain::(); + let acc = bp_runtime::SourceAccount::Account(account.raw_id()); let id = bp_rialto::derive_account_from_millau_id(acc); - println!( - "{} (Millau)\n\nCorresponding (derived) account id:\n-> {} (Rialto)", - account, id - ) + let derived_account = AccountId::from_raw::(id); + println!("Source address:\n{} (Millau)", account); + println!("->Corresponding (derived) address:\n{} (Rialto)", derived_account); } } @@ -650,9 +648,10 @@ impl cli::MillauToRialtoMessagePayload { match self { Self::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), - Self::Message { message, sender } => { + Self::Message { message, mut sender } => { let spec_version = rialto_runtime::VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.into_millau()); + sender.enforce_chain::(); + let origin = CallOrigin::SourceAccount(sender.raw_id()); let call = message.into_call()?; let weight = call.get_dispatch_info().weight; @@ -670,9 +669,10 @@ impl cli::RialtoToMillauMessagePayload { match self { Self::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), - Self::Message { message, sender } => { + Self::Message { message, mut sender } => { let spec_version = millau_runtime::VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.into_rialto()); + sender.enforce_chain::(); + let origin = CallOrigin::SourceAccount(sender.raw_id()); let call = message.into_call()?; let weight = call.get_dispatch_info().weight; @@ -750,9 +750,9 @@ impl cli::ToRialtoMessage { ), ))) } - cli::ToRialtoMessage::Transfer { recipient, amount } => { - let recipient = recipient.into_rialto(); - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient, amount)) + cli::ToRialtoMessage::Transfer { mut recipient, amount } => { + recipient.enforce_chain::(); + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) } cli::ToRialtoMessage::MillauSendMessage { lane, payload, fee } => { let payload = cli::RialtoToMillauMessagePayload::Raw { data: payload }.into_payload()?; @@ -787,9 +787,9 @@ impl cli::ToMillauMessage { ), ))) } - cli::ToMillauMessage::Transfer { recipient, amount } => { - let recipient = recipient.into_millau(); - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient, amount)) + cli::ToMillauMessage::Transfer { mut recipient, amount } => { + recipient.enforce_chain::(); + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) } cli::ToMillauMessage::RialtoSendMessage { lane, payload, fee } => { let payload = cli::MillauToRialtoMessagePayload::Raw { data: payload }.into_payload()?; @@ -808,6 +808,22 @@ impl cli::ToMillauMessage { } } +impl AccountChain for Rialto { + const NAME: &'static str = "Rialto"; + + fn ss58_format() -> u16 { + rialto_runtime::SS58Prefix::get() as u16 + } +} + +impl AccountChain for Millau { + const NAME: &'static str = "Millau"; + + fn ss58_format() -> u16 { + millau_runtime::SS58Prefix::get() as u16 + } +} + #[cfg(test)] mod tests { use super::*; @@ -977,4 +993,25 @@ mod tests { extra_bytes_in_transaction, ); } + + #[test] + fn should_reformat_addresses() { + // given + let mut rialto1: AccountId = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU".parse().unwrap(); + let mut millau1: AccountId = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9".parse().unwrap(); + + // when + rialto1.enforce_chain::(); + millau1.enforce_chain::(); + + // then + assert_eq!( + &format!("{}", rialto1), + "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9" + ); + assert_eq!( + &format!("{}", millau1), + "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU" + ); + } } diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index 40b541b3c2e79..ee09cc8d9f08f 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -16,40 +16,80 @@ //! Relayer initialization functions. -use std::io::Write; +use std::{fmt::Display, io::Write}; /// Initialize relay environment. pub fn initialize_relay() { + initialize_logger(true); +} + +/// Initialize Relay logger instance. +pub fn initialize_logger(with_timestamp: bool) { let mut builder = env_logger::Builder::new(); builder.filter_level(log::LevelFilter::Warn); builder.filter_module("bridge", log::LevelFilter::Info); builder.parse_default_env(); - builder.format(move |buf, record| { - writeln!(buf, "{}", { + if with_timestamp { + builder.format(move |buf, record| { let timestamp = time::OffsetDateTime::try_now_local() .unwrap_or_else(|_| time::OffsetDateTime::now_utc()) .format("%Y-%m-%d %H:%M:%S %z"); - if cfg!(windows) { - format!("{} {} {} {}", timestamp, record.level(), record.target(), record.args()) + + let log_level = color_level(record.level()); + let log_target = color_target(record.target()); + let timestamp = if cfg!(windows) { + Either::Left(timestamp) } else { - use ansi_term::Colour as Color; - let log_level = match record.level() { - log::Level::Error => Color::Fixed(9).bold().paint(record.level().to_string()), - log::Level::Warn => Color::Fixed(11).bold().paint(record.level().to_string()), - log::Level::Info => Color::Fixed(10).paint(record.level().to_string()), - log::Level::Debug => Color::Fixed(14).paint(record.level().to_string()), - log::Level::Trace => Color::Fixed(12).paint(record.level().to_string()), - }; - format!( - "{} {} {} {}", - Color::Fixed(8).bold().paint(timestamp), - log_level, - Color::Fixed(8).paint(record.target()), - record.args() - ) - } - }) - }); + Either::Right(ansi_term::Colour::Fixed(8).bold().paint(timestamp)) + }; + + writeln!(buf, "{} {} {} {}", timestamp, log_level, log_target, record.args(),) + }); + } else { + builder.format(move |buf, record| { + let log_level = color_level(record.level()); + let log_target = color_target(record.target()); + + writeln!(buf, "{} {} {}", log_level, log_target, record.args(),) + }); + } builder.init(); } + +enum Either { + Left(A), + Right(B), +} +impl Display for Either { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Left(a) => write!(fmt, "{}", a), + Self::Right(b) => write!(fmt, "{}", b), + } + } +} + +fn color_target(target: &str) -> impl Display + '_ { + if cfg!(windows) { + Either::Left(target) + } else { + Either::Right(ansi_term::Colour::Fixed(8).paint(target)) + } +} + +fn color_level(level: log::Level) -> impl Display { + if cfg!(windows) { + Either::Left(level) + } else { + let s = level.to_string(); + use ansi_term::Colour as Color; + Either::Right(match level { + log::Level::Error => Color::Fixed(9).bold().paint(s), + log::Level::Warn => Color::Fixed(11).bold().paint(s), + log::Level::Info => Color::Fixed(10).paint(s), + log::Level::Debug => Color::Fixed(14).paint(s), + log::Level::Trace => Color::Fixed(12).paint(s), + }) + } +} From 5b72dd8901d442922be37c1950d9cea02aec7e47 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 31 Mar 2021 14:50:55 +0300 Subject: [PATCH 0398/1210] fix delay in message_lane_loop_is_able_to_recover_from_connection_errors (#850) --- relays/messages/src/message_lane_loop.rs | 1 + relays/utils/src/relay_loop.rs | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 159bd4c769592..b5f650f117c65 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -221,6 +221,7 @@ pub async fn run( ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) + .reconnect_delay(params.reconnect_delay) .with_metrics(format!( "{}_to_{}_MessageLane_{}", P::SOURCE_NAME, diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index d21f6d28ef5bb..2e12f71459ab2 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -37,6 +37,7 @@ pub trait Client: Clone + Send + Sync { /// Returns generic loop that may be customized and started. pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { Loop { + reconnect_delay: RECONNECT_DELAY, source_client, target_client, loop_metric: None, @@ -45,6 +46,7 @@ pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { + reconnect_delay: Duration, source_client: SC, target_client: TC, loop_metric: Option, @@ -58,6 +60,12 @@ pub struct LoopMetrics { } impl Loop { + /// Customize delay between reconnect attempts. + pub fn reconnect_delay(mut self, reconnect_delay: Duration) -> Self { + self.reconnect_delay = reconnect_delay; + self + } + /// Start building loop metrics using given prefix. /// /// Panics if `prefix` is empty. @@ -66,6 +74,7 @@ impl Loop { LoopMetrics { relay_loop: Loop { + reconnect_delay: self.reconnect_delay, source_client: self.source_client, target_client: self.target_client, loop_metric: None, @@ -100,7 +109,7 @@ impl Loop { match result { Ok(()) => break, Err(failed_client) => loop { - async_std::task::sleep(RECONNECT_DELAY).await; + async_std::task::sleep(self.reconnect_delay).await; if failed_client == FailedClient::Both || failed_client == FailedClient::Source { match self.source_client.reconnect().await { Ok(()) => (), @@ -108,7 +117,7 @@ impl Loop { log::warn!( target: "bridge", "Failed to reconnect to source client. Going to retry in {}s: {:?}", - RECONNECT_DELAY.as_secs(), + self.reconnect_delay.as_secs(), error, ); continue; @@ -122,7 +131,7 @@ impl Loop { log::warn!( target: "bridge", "Failed to reconnect to target client. Going to retry in {}s: {:?}", - RECONNECT_DELAY.as_secs(), + self.reconnect_delay.as_secs(), error, ); continue; @@ -189,6 +198,7 @@ impl LoopMetrics { } Ok(Loop { + reconnect_delay: self.relay_loop.reconnect_delay, source_client: self.relay_loop.source_client, target_client: self.relay_loop.target_client, loop_metric: self.loop_metric, From 57948a746b45445c8d82383f20bc4228829b1dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 1 Apr 2021 12:49:49 +0200 Subject: [PATCH 0399/1210] Make relay CLI generic (#849) * Start generalizing rialto-millau commands. * cargo fmt --all * Introduce generic balance. * Unify message payloads. * cargo fmt --all * init - generic * Attempt to unify send message. * Start moving things around. * cargo fmt --all * Move init-bridge. * cargo fmt --all * Improve UX of bridge argument. * Fix clippy. * Fix docs and scripts. * Add docs. * Apply suggestions from code review Co-authored-by: Hernando Castano * Fix copyright. * Add issue numbers. * More todos. * Update comments. Co-authored-by: Hernando Castano --- README.md | 24 +- primitives/chain-westend/Cargo.toml | 2 + primitives/chain-westend/src/lib.rs | 12 + relays/bin-ethereum/src/ethereum_exchange.rs | 14 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 14 +- relays/bin-ethereum/src/main.rs | 5 +- relays/bin-ethereum/src/rialto_client.rs | 46 +- relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/cli/init_bridge.rs | 137 +++ .../bin-substrate/src/{cli.rs => cli/mod.rs} | 120 ++- relays/bin-substrate/src/cli/relay_headers.rs | 91 ++ relays/bin-substrate/src/finality_pipeline.rs | 17 +- relays/bin-substrate/src/rialto_millau/cli.rs | 240 ++--- .../rialto_millau/millau_headers_to_rialto.rs | 21 +- .../millau_messages_to_rialto.rs | 10 +- relays/bin-substrate/src/rialto_millau/mod.rs | 854 ++++++++---------- .../rialto_millau/rialto_headers_to_millau.rs | 21 +- .../rialto_messages_to_millau.rs | 10 +- .../westend_headers_to_millau.rs | 21 +- relays/client-millau/src/lib.rs | 21 +- relays/client-rialto/src/lib.rs | 29 +- relays/client-substrate/src/error.rs | 35 +- 22 files changed, 881 insertions(+), 864 deletions(-) create mode 100644 relays/bin-substrate/src/cli/init_bridge.rs rename relays/bin-substrate/src/{cli.rs => cli/mod.rs} (81%) create mode 100644 relays/bin-substrate/src/cli/relay_headers.rs diff --git a/README.md b/README.md index c122b8af6d705..8f6446c8875aa 100644 --- a/README.md +++ b/README.md @@ -158,20 +158,20 @@ Then we need to initialize and run the relayer: ```bash docker run --network=host -it \ - paritytech/substrate-relay initialize-rialto-headers-bridge-in-millau \ - --millau-host localhost \ - --millau-port 9945 \ - --rialto-host localhost \ - --rialto-port 9944 \ - --millau-signer //Alice + paritytech/substrate-relay init-bridge RialtoToMillau \ + --target-host localhost \ + --target-port 9945 \ + --source-host localhost \ + --source-port 9944 \ + --target-signer //Alice docker run --network=host -it \ - paritytech/substrate-relay rialto-headers-to-millau \ - --millau-host localhost \ - --millau-port 9945 \ - --rialto-host localhost \ - --rialto-port 9944 \ - --millau-signer //Bob \ + paritytech/substrate-relay relay-headers RialtoToMillau \ + --target-host localhost \ + --target-port 9945 \ + --source-host localhost \ + --source-port 9944 \ + --target-signer //Bob \ ``` You should now see the relayer submitting headers from the Millau chain to the Rialto chain. diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index df8becd9596a5..3552141da5773 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -16,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { 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-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -25,4 +26,5 @@ std = [ "bp-runtime/std", "sp-api/std", "sp-std/std", + "sp-version/std", ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 0596da1b7dcdc..0587e76125327 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -22,12 +22,24 @@ use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use sp_std::prelude::*; +use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; /// Westend Chain pub type Westend = PolkadotLike; +/// Runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("westend"), + impl_name: sp_version::create_runtime_str!("parity-westend"), + authoring_version: 2, + spec_version: 50, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 5, +}; + // We use this to get the account on Westend (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index c075ecb7f81b6..b92581e1f54fa 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -56,7 +56,6 @@ pub enum ExchangeRelayMode { } /// PoA exchange transaction relay params. -#[derive(Debug)] pub struct EthereumExchangeParams { /// Ethereum connection params. pub eth_params: EthereumConnectionParams, @@ -72,6 +71,19 @@ pub struct EthereumExchangeParams { pub instance: Arc, } +impl std::fmt::Debug for EthereumExchangeParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("EthereumExchangeParams") + .field("eth_params", &self.eth_params) + .field("sub_params", &self.sub_params) + .field("sub_sign", &sp_core::Pair::public(&self.sub_sign)) + .field("mode", &self.mode) + .field("metrics_params", &self.metrics_params) + .field("instance", &self.instance) + .finish() + } +} + /// Ethereum to Substrate exchange pipeline. struct EthereumToSubstrateExchange; diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index ab6483cdb881c..b2e18b1c8fe59 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -62,7 +62,6 @@ pub mod consts { } /// Ethereum synchronization parameters. -#[derive(Debug)] pub struct EthereumSyncParams { /// Ethereum connection params. pub eth_params: EthereumConnectionParams, @@ -78,6 +77,19 @@ pub struct EthereumSyncParams { pub instance: Arc, } +impl Debug for EthereumSyncParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("EthereumSyncParams") + .field("eth_params", &self.eth_params) + .field("sub_params", &self.sub_params) + .field("sub_sign", &sp_core::Pair::public(&self.sub_sign)) + .field("sync_params", &self.sync_params) + .field("metrics_params", &self.metrics_params) + .field("instance", &self.instance) + .finish() + } +} + /// Ethereum synchronization pipeline. #[derive(Clone, Copy, Debug)] #[cfg_attr(test, derive(PartialEq))] diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index b2080c396f2d7..40f056c61c049 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -167,10 +167,11 @@ fn substrate_connection_params(matches: &clap::ArgMatches) -> Result Result { - let mut params = RialtoSigningParams::default(); + let mut params = sp_keyring::AccountKeyring::Alice.pair(); + if let Some(sub_signer) = matches.value_of("sub-signer") { let sub_signer_password = matches.value_of("sub-signer-password"); - params.signer = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) + params = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) .map_err(|e| format!("Failed to parse sub-signer: {:?}", e))?; } Ok(params) diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index c6d731b841c12..06605fdfd5437 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -156,20 +156,17 @@ impl SubmitEthereumHeaders for SubstrateClient { ) -> SubmittedHeaders { let ids = headers.iter().map(|header| header.id()).collect(); let submission_result = async { - self.submit_signed_extrinsic( - params.signer.public().as_array_ref().clone().into(), - |transaction_nonce| { - Bytes( - Rialto::sign_transaction( - *self.genesis_hash(), - ¶ms.signer, - transaction_nonce, - instance.build_signed_header_call(headers), - ) - .encode(), + self.submit_signed_extrinsic(params.public().as_array_ref().clone().into(), |transaction_nonce| { + Bytes( + Rialto::sign_transaction( + *self.genesis_hash(), + ¶ms, + transaction_nonce, + instance.build_signed_header_call(headers), ) - }, - ) + .encode(), + ) + }) .await?; Ok(()) } @@ -260,20 +257,17 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { instance: Arc, proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { - self.submit_signed_extrinsic( - params.signer.public().as_array_ref().clone().into(), - |transaction_nonce| { - Bytes( - Rialto::sign_transaction( - *self.genesis_hash(), - ¶ms.signer, - transaction_nonce, - instance.build_currency_exchange_call(proof), - ) - .encode(), + self.submit_signed_extrinsic(params.public().as_array_ref().clone().into(), |transaction_nonce| { + Bytes( + Rialto::sign_transaction( + *self.genesis_hash(), + ¶ms, + transaction_nonce, + instance.build_currency_exchange_call(proof), ) - }, - ) + .encode(), + ) + }) .await?; Ok(()) } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a94d6d09ef051..8942bf8130953 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -52,6 +52,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs new file mode 100644 index 0000000000000..ac2b8c7a705b8 --- /dev/null +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -0,0 +1,137 @@ +// 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 . + +use crate::cli::{CliChain, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use bp_runtime::Chain as ChainBase; +use codec::Encode; +use pallet_bridge_grandpa::InitializationData; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use sp_core::{Bytes, Pair}; +use structopt::{clap::arg_enum, StructOpt}; + +/// Initialize bridge pallet. +#[derive(StructOpt)] +pub struct InitBridge { + /// A bridge instance to initalize. + #[structopt(possible_values = &InitBridgeName::variants(), case_insensitive = true)] + bridge: InitBridgeName, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, +} + +// TODO [#851] Use kebab-case. +arg_enum! { + #[derive(Debug)] + /// Bridge to initialize. + pub enum InitBridgeName { + MillauToRialto, + RialtoToMillau, + WestendToMillau, + } +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + InitBridgeName::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + rialto_runtime::SudoCall::sudo(Box::new( + rialto_runtime::BridgeGrandpaMillauCall::initialize(init_data).into(), + )) + .into() + } + + $generic + } + InitBridgeName::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::< + millau_runtime::Runtime, + millau_runtime::RialtoGrandpaInstance, + >::initialize(init_data); + millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into() + } + + $generic + } + InitBridgeName::WestendToMillau => { + type Source = relay_westend_client::Westend; + type Target = relay_millau_client::Millau; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + // at Westend -> Millau initialization we're not using sudo, because otherwise our deployments + // may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge. + // => since there's single possible sudo account, one of transaction may fail with duplicate nonce error + millau_runtime::BridgeGrandpaWestendCall::< + millau_runtime::Runtime, + millau_runtime::WestendGrandpaInstance, + >::initialize(init_data) + .into() + } + + $generic + } + } + }; +} + +impl InitBridge { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + let source_client = crate::rialto_millau::source_chain_client::(self.source).await?; + let target_client = crate::rialto_millau::target_chain_client::(self.target).await?; + let target_sign = + Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?; + + crate::headers_initialize::initialize( + source_client, + target_client.clone(), + target_sign.public().into(), + move |transaction_nonce, initialization_data| { + Bytes( + Target::sign_transaction( + *target_client.genesis_hash(), + &target_sign, + transaction_nonce, + encode_init_bridge(initialization_data), + ) + .encode(), + ) + }, + ) + .await; + + Ok(()) + }) + } +} diff --git a/relays/bin-substrate/src/cli.rs b/relays/bin-substrate/src/cli/mod.rs similarity index 81% rename from relays/bin-substrate/src/cli.rs rename to relays/bin-substrate/src/cli/mod.rs index f871b7919b096..6418848c29489 100644 --- a/relays/bin-substrate/src/cli.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 @@ -18,12 +18,15 @@ use std::convert::TryInto; +use crate::rialto_millau::cli as rialto_millau; use bp_messages::LaneId; use codec::{Decode, Encode}; +use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; -use crate::rialto_millau::cli as rialto_millau; +mod init_bridge; +mod relay_headers; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -38,7 +41,7 @@ pub enum Command { /// /// The on-chain bridge component should have been already initialized with /// `init-bridge` sub-command. - RelayHeaders(RelayHeaders), + RelayHeaders(relay_headers::RelayHeaders), /// Start messages relay between two chains. /// /// Ties up to `Messages` pallets on both chains and starts relaying messages. @@ -47,7 +50,7 @@ pub enum Command { /// Initialize on-chain bridge pallet with current header data. /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. - InitBridge(InitBridge), + InitBridge(init_bridge::InitBridge), /// Send custom message over the bridge. /// /// Allows interacting with the bridge by sending messages over `Messages` component. @@ -74,9 +77,9 @@ impl Command { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self { - Self::InitBridge(arg) => arg.run().await?, Self::RelayHeaders(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?, + Self::InitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, Self::EncodeCall(arg) => arg.run().await?, Self::EncodeMessagePayload(arg) => arg.run().await?, @@ -87,23 +90,6 @@ impl Command { } } -/// Start headers relayer process. -#[derive(StructOpt)] -pub enum RelayHeaders { - #[structopt(flatten)] - RialtoMillau(rialto_millau::RelayHeaders), -} - -impl RelayHeaders { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - /// Start message relayer process. #[derive(StructOpt)] pub enum RelayMessages { @@ -121,23 +107,6 @@ impl RelayMessages { } } -/// Initialize bridge pallet. -#[derive(StructOpt)] -pub enum InitBridge { - #[structopt(flatten)] - RialtoMillau(rialto_millau::InitBridge), -} - -impl InitBridge { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - /// Send bridge message. #[derive(StructOpt)] pub enum SendMessage { @@ -240,6 +209,25 @@ arg_enum! { } } +/// Generic balance type. +#[derive(Debug)] +pub struct Balance(pub u128); + +impl std::str::FromStr for Balance { + type Err = ::Err; + + fn from_str(s: &str) -> Result { + Ok(Self(s.parse()?)) + } +} + +impl Balance { + /// Cast balance to `u64` type, panicking if it's too large. + pub fn cast(&self) -> u64 { + self.0.try_into().expect("Balance is too high for this chain.") + } +} + /// Generic account id with custom parser. #[derive(Debug, Clone)] pub struct AccountId { @@ -267,19 +255,19 @@ const SS58_FORMAT_PROOF: &str = "u16 -> Ss58Format is infallible; qed"; impl AccountId { /// Create new SS58-formatted address from raw account id. - pub fn from_raw(account: sp_runtime::AccountId32) -> Self { + pub fn from_raw(account: sp_runtime::AccountId32) -> Self { Self { account, ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF), } } - /// Enforces formatting account to be for given `AccountChain` type. + /// Enforces formatting account to be for given [`CliChain`] type. /// /// This will change the `ss58format` of the account to match the requested one. /// Note that a warning will be produced in case the current format does not match /// the requested one, but the conversion always succeeds. - pub fn enforce_chain(&mut self) { + pub fn enforce_chain(&mut self) { let original = self.clone(); self.ss58_format = T::ss58_format().try_into().expect(SS58_FORMAT_PROOF); log::debug!("{} SS58 format: {} (RAW: {})", self, self.ss58_format, self.account); @@ -302,15 +290,48 @@ impl AccountId { } } -/// A trait representing an account address bound to a specific chain. +/// Bridge-supported network definition. /// -/// Can be used to convert [`AccountId`] formatting to be chain-specific. -pub trait AccountChain { - /// Network name associated with the SS58 format. - const NAME: &'static str; +/// Used to abstract away CLI commands. +pub trait CliChain: relay_substrate_client::Chain { + /// Chain's current version of the runtime. + const RUNTIME_VERSION: sp_version::RuntimeVersion; + + /// Crypto keypair type used to send messages. + /// + /// In case of chains supporting multiple cryptos, pick one used by the CLI. + type KeyPair: sp_core::crypto::Pair; + + /// Bridge Message Payload type. + /// + /// TODO [#854] This should be removed in favour of target-specifc types. + type MessagePayload; /// Numeric value of SS58 format. fn ss58_format() -> u16; + + /// Parse CLI call and encode it to be dispatched on this specific chain. + fn encode_call(call: crate::rialto_millau::cli::Call) -> Result; + + /// Construct message payload to be sent over the bridge. + fn encode_message(message: crate::rialto_millau::cli::MessagePayload) -> Result; + + /// Maximal extrinsic weight (from the runtime). + fn max_extrinsic_weight() -> Weight; + + /// Convert CLI signing parameters of `Source` chain into a `KeyPair` instance. + fn source_signing_params(params: SourceSigningParams) -> Result { + use sp_core::crypto::Pair; + Self::KeyPair::from_string(¶ms.source_signer, params.source_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse source-signer: {:?}", e)) + } + + /// Convert CLI signing parameters of `Target` chain into a `KeyPair` instance. + fn target_signing_params(params: TargetSigningParams) -> Result { + use sp_core::crypto::Pair; + Self::KeyPair::from_string(¶ms.target_signer, params.target_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse target-signer: {:?}", e)) + } } /// Lane id. @@ -445,6 +466,11 @@ macro_rules! declare_chain_options { }; } +// TODO [#852] Use structop renames instead of different fields. +// TODO [#852] Add Into? +declare_chain_options!(Source, source); +declare_chain_options!(Target, target); + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs new file mode 100644 index 0000000000000..6e903325764a6 --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -0,0 +1,91 @@ +// 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 . + +use crate::cli::{CliChain, PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use structopt::{clap::arg_enum, StructOpt}; + +/// Start headers relayer process. +#[derive(StructOpt)] +pub struct RelayHeaders { + /// A bridge instance to relay headers for. + #[structopt(possible_values = &RelayHeadersBridge::variants(), case_insensitive = true)] + bridge: RelayHeadersBridge, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +// TODO [#851] Use kebab-case. +arg_enum! { + #[derive(Debug)] + /// Headers relay bridge. + pub enum RelayHeadersBridge { + MillauToRialto, + RialtoToMillau, + WestendToMillau, + } +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + RelayHeadersBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + type Finality = crate::rialto_millau::millau_headers_to_rialto::MillauFinalityToRialto; + + $generic + } + RelayHeadersBridge::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + type Finality = crate::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; + $generic + } + RelayHeadersBridge::WestendToMillau => { + type Source = relay_westend_client::Westend; + type Target = relay_millau_client::Millau; + type Finality = crate::rialto_millau::westend_headers_to_millau::WestendFinalityToMillau; + $generic + } + } + }; +} + +impl RelayHeaders { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + let source_client = crate::rialto_millau::source_chain_client::(self.source).await?; + let target_client = crate::rialto_millau::target_chain_client::(self.target).await?; + let target_sign = + Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?; + + crate::finality_pipeline::run( + Finality::new(target_client.clone(), target_sign), + source_client, + target_client, + self.prometheus_params.into(), + ) + .await + }) + } +} diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index d5ae55162e3f8..d58306f44ff52 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -56,7 +56,7 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { } /// Substrate-to-Substrate finality proof pipeline. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct SubstrateFinalityToSubstrate { /// Client for the target chain. pub(crate) target_client: Client, @@ -66,6 +66,16 @@ pub struct SubstrateFinalityToSubstrate, } +impl Debug + for SubstrateFinalityToSubstrate +{ + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("SubstrateFinalityToSubstrate") + .field("target_client", &self.target_client) + .finish() + } +} + impl SubstrateFinalityToSubstrate { /// Create new Substrate-to-Substrate headers pipeline. pub fn new(target_client: Client, target_sign: TargetSign) -> Self { @@ -83,7 +93,7 @@ where SourceChain: Clone + Chain + Debug, BlockNumberOf: BlockNumberBase, TargetChain: Clone + Chain + Debug, - TargetSign: Clone + Send + Sync + Debug, + TargetSign: Clone + Send + Sync, { const SOURCE_NAME: &'static str = SourceChain::NAME; const TARGET_NAME: &'static str = TargetChain::NAME; @@ -100,7 +110,7 @@ pub async fn run( source_client: Client, target_client: Client, metrics_params: Option, -) -> Result<(), String> +) -> anyhow::Result<()> where P: SubstrateFinalitySyncPipeline< Hash = HashOf, @@ -132,4 +142,5 @@ where futures::future::pending(), ) .await + .map_err(|e| anyhow::format_err!("{}", e)) } diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs index 9c89e823430bf..1005e85472229 100644 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/relays/bin-substrate/src/rialto_millau/cli.rs @@ -19,68 +19,26 @@ use frame_support::weights::Weight; use structopt::StructOpt; -use crate::cli::{AccountId, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, PrometheusParams}; -use crate::declare_chain_options; - -/// Start headers relayer process. -#[derive(StructOpt)] -pub enum RelayHeaders { - /// Relay Millau headers to Rialto. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - }, - /// Relay Rialto headers to Millau. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - }, - /// Relay Westend headers to Millau. - WestendToMillau { - #[structopt(flatten)] - westend: WestendConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - }, -} - -impl RelayHeaders { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_relay_headers(self).await.map_err(format_err)?; - Ok(()) - } -} +use crate::cli::{ + AccountId, Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, PrometheusParams, SourceConnectionParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, +}; /// Start message relayer process. +/// +/// TODO [#855] Move to separate module. #[derive(StructOpt)] pub enum RelayMessages { /// Serve given lane of Millau -> Rialto messages. MillauToRialto { #[structopt(flatten)] - millau: MillauConnectionParams, + source: SourceConnectionParams, #[structopt(flatten)] - millau_sign: MillauSigningParams, + source_sign: SourceSigningParams, #[structopt(flatten)] - rialto: RialtoConnectionParams, + target: TargetConnectionParams, #[structopt(flatten)] - rialto_sign: RialtoSigningParams, + target_sign: TargetSigningParams, #[structopt(flatten)] prometheus_params: PrometheusParams, /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. @@ -90,13 +48,13 @@ pub enum RelayMessages { /// Serve given lane of Rialto -> Millau messages. RialtoToMillau { #[structopt(flatten)] - rialto: RialtoConnectionParams, + source: SourceConnectionParams, #[structopt(flatten)] - rialto_sign: RialtoSigningParams, + source_sign: SourceSigningParams, #[structopt(flatten)] - millau: MillauConnectionParams, + target: TargetConnectionParams, #[structopt(flatten)] - millau_sign: MillauSigningParams, + target_sign: TargetSigningParams, #[structopt(flatten)] prometheus_params: PrometheusParams, /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. @@ -113,57 +71,19 @@ impl RelayMessages { } } -/// Initialize bridge pallet. -#[derive(StructOpt)] -pub enum InitBridge { - /// Initialize Millau headers bridge in Rialto. - MillauToRialto { - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - rialto_sign: RialtoSigningParams, - }, - /// Initialize Rialto headers bridge in Millau. - RialtoToMillau { - #[structopt(flatten)] - rialto: RialtoConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - }, - /// Initialize Westend headers bridge in Millau. - WestendToMillau { - #[structopt(flatten)] - westend: WestendConnectionParams, - #[structopt(flatten)] - millau: MillauConnectionParams, - #[structopt(flatten)] - millau_sign: MillauSigningParams, - }, -} - -impl InitBridge { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_init_bridge(self).await.map_err(format_err)?; - Ok(()) - } -} - /// Send bridge message. +/// +/// TODO [#855] Move to separate module. #[derive(StructOpt)] pub enum SendMessage { /// Submit message to given Millau -> Rialto lane. MillauToRialto { #[structopt(flatten)] - millau: MillauConnectionParams, + source: SourceConnectionParams, #[structopt(flatten)] - millau_sign: MillauSigningParams, + source_sign: SourceSigningParams, #[structopt(flatten)] - rialto_sign: RialtoSigningParams, + target_sign: TargetSigningParams, /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -172,10 +92,10 @@ pub enum SendMessage { dispatch_weight: Option>, /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. #[structopt(long)] - fee: Option, + fee: Option, /// Message type. #[structopt(subcommand)] - message: ToRialtoMessage, + message: Call, /// The origin to use when dispatching the message on the target chain. Defaults to /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] @@ -184,11 +104,11 @@ pub enum SendMessage { /// Submit message to given Rialto -> Millau lane. RialtoToMillau { #[structopt(flatten)] - rialto: RialtoConnectionParams, + source: SourceConnectionParams, #[structopt(flatten)] - rialto_sign: RialtoSigningParams, + source_sign: SourceSigningParams, #[structopt(flatten)] - millau_sign: MillauSigningParams, + target_sign: TargetSigningParams, /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -197,10 +117,10 @@ pub enum SendMessage { dispatch_weight: Option>, /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. #[structopt(long)] - fee: Option, + fee: Option, /// Message type. #[structopt(subcommand)] - message: ToMillauMessage, + message: Call, /// The origin to use when dispatching the message on the target chain. Defaults to /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] @@ -217,17 +137,19 @@ impl SendMessage { } /// A call to encode. +/// +/// TODO [#855] Move to separate module. #[derive(StructOpt)] pub enum EncodeCall { /// Encode Rialto's Call. Rialto { #[structopt(flatten)] - call: ToRialtoMessage, + call: Call, }, /// Encode Millau's Call. Millau { #[structopt(flatten)] - call: ToMillauMessage, + call: Call, }, } @@ -240,17 +162,19 @@ impl EncodeCall { } /// A `MessagePayload` to encode. +/// +/// TODO [#855] Move to separate module. #[derive(StructOpt)] pub enum EncodeMessagePayload { /// Message Payload of Rialto to Millau call. RialtoToMillau { #[structopt(flatten)] - payload: RialtoToMillauMessagePayload, + payload: MessagePayload, }, /// Message Payload of Millau to Rialto call. MillauToRialto { #[structopt(flatten)] - payload: MillauToRialtoMessagePayload, + payload: MessagePayload, }, } @@ -263,29 +187,31 @@ impl EncodeMessagePayload { } /// Estimate Delivery & Dispatch Fee command. +/// +/// TODO [#855] Move to separate module. #[derive(StructOpt)] pub enum EstimateFee { /// Estimate fee of Rialto to Millau message. RialtoToMillau { #[structopt(flatten)] - rialto: RialtoConnectionParams, + source: SourceConnectionParams, /// Hex-encoded id of lane that will be delivering the message. #[structopt(long)] lane: HexLaneId, /// Payload to send over the bridge. #[structopt(flatten)] - payload: RialtoToMillauMessagePayload, + payload: MessagePayload, }, /// Estimate fee of Rialto to Millau message. MillauToRialto { #[structopt(flatten)] - millau: MillauConnectionParams, + source: SourceConnectionParams, /// Hex-encoded id of lane that will be delivering the message. #[structopt(long)] lane: HexLaneId, /// Payload to send over the bridge. #[structopt(flatten)] - payload: MillauToRialtoMessagePayload, + payload: MessagePayload, }, } @@ -303,6 +229,8 @@ impl EstimateFee { /// that has been sent over the bridge. /// This account can also be used to receive target-chain funds (or other form of ownership), /// since messages sent over the bridge will be able to spend these. +/// +/// TODO [#855] Move to separate module. #[derive(StructOpt)] pub enum DeriveAccount { /// Given Rialto AccountId, display corresponding Millau AccountId. @@ -323,47 +251,31 @@ fn format_err(err: String) -> anyhow::Error { anyhow::anyhow!(err) } -/// MessagePayload that can be delivered to messages pallet on Millau. -#[derive(StructOpt, Debug)] -pub enum MillauToRialtoMessagePayload { - /// Raw, SCALE-encoded `MessagePayload`. - Raw { - /// Hex-encoded SCALE data. - data: HexBytes, - }, - /// Construct message to send over the bridge. - Message { - /// Message details. - #[structopt(flatten)] - message: ToRialtoMessage, - /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) - #[structopt(long)] - sender: AccountId, - }, -} - -/// MessagePayload that can be delivered to messages pallet on Rialto. +/// Generic message payload. #[derive(StructOpt, Debug)] -pub enum RialtoToMillauMessagePayload { +pub enum MessagePayload { /// Raw, SCALE-encoded `MessagePayload`. Raw { /// Hex-encoded SCALE data. data: HexBytes, }, /// Construct message to send over the bridge. - Message { + Call { /// Message details. #[structopt(flatten)] - message: ToMillauMessage, + call: Call, /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) #[structopt(long)] sender: AccountId, }, } -/// All possible messages that may be delivered to the Rialto chain. +/// All possible messages that may be delivered to generic Substrate chain. +/// +/// Note this enum may be used in the context of both Source (as part of `encode-call`) +/// and Target chain (as part of `encode-message/send-message`). #[derive(StructOpt, Debug)] -pub enum ToRialtoMessage { +pub enum Call { /// Raw bytes for the message Raw { /// Raw, SCALE-encoded message @@ -382,47 +294,11 @@ pub enum ToRialtoMessage { recipient: AccountId, /// Amount of target tokens to send in target chain base currency units. #[structopt(long)] - amount: bp_rialto::Balance, - }, - /// A call to the Millau Bridge Messages pallet to send a message over the bridge. - MillauSendMessage { - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the messages pallet. - #[structopt(long)] - payload: HexBytes, - /// Declared delivery and dispatch fee in base source-chain currency units. - #[structopt(long)] - fee: bp_rialto::Balance, - }, -} - -/// All possible messages that may be delivered to the Millau chain. -#[derive(StructOpt, Debug)] -pub enum ToMillauMessage { - /// Raw bytes for the message - Raw { - /// Raw, SCALE-encoded message - data: HexBytes, - }, - /// Make an on-chain remark (comment). - Remark { - /// Size of the remark. If not passed, small UTF8-encoded string is generated by relay as remark. - #[structopt(long)] - remark_size: Option>, - }, - /// Transfer the specified `amount` of native tokens to a particular `recipient`. - Transfer { - /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) - #[structopt(long)] - recipient: AccountId, - /// Amount of target tokens to send in target chain base currency units. - #[structopt(long)] - amount: bp_millau::Balance, + amount: Balance, }, - /// A call to the Rialto Bridge Messages pallet to send a message over the bridge. - RialtoSendMessage { + // TODO [#853] Support multiple bridges. + /// A call to the specific Bridge Messages pallet to queue message to be sent over a bridge. + BridgeSendMessage { /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -431,10 +307,6 @@ pub enum ToMillauMessage { payload: HexBytes, /// Declared delivery and dispatch fee in base source-chain currency units. #[structopt(long)] - fee: bp_millau::Balance, + fee: Balance, }, } - -declare_chain_options!(Rialto, rialto); -declare_chain_options!(Millau, millau); -declare_chain_options!(Westend, westend); diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index 5a30974ba4c47..f85560bf19266 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -16,7 +16,6 @@ //! Millau-to-Rialto headers sync entrypoint. -use super::{MillauClient, RialtoClient}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use codec::Encode; @@ -34,7 +33,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { type TargetChain = Rialto; fn transactions_author(&self) -> bp_rialto::AccountId { - self.target_sign.signer.public().as_array_ref().clone().into() + self.target_sign.public().as_array_ref().clone().into() } fn make_submit_finality_proof_transaction( @@ -48,24 +47,8 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { .into(); let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); + let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); Bytes(transaction.encode()) } } - -/// Run Millau-to-Rialto finality sync. -pub async fn run( - millau_client: MillauClient, - rialto_client: RialtoClient, - rialto_sign: RialtoSigningParams, - metrics_params: Option, -) -> Result<(), String> { - crate::finality_pipeline::run( - MillauFinalityToRialto::new(rialto_client.clone(), rialto_sign), - millau_client, - rialto_client, - metrics_params, - ) - .await -} diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index edfd907776500..38fe71d36879f 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -56,7 +56,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { type TargetChain = Rialto; fn source_transactions_author(&self) -> bp_rialto::AccountId { - self.source_sign.signer.public().as_array_ref().clone().into() + self.source_sign.public().as_array_ref().clone().into() } fn make_messages_receiving_proof_transaction( @@ -70,7 +70,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign.signer, transaction_nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -83,7 +83,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } fn target_transactions_author(&self) -> bp_rialto::AccountId { - self.target_sign.signer.public().as_array_ref().clone().into() + self.target_sign.public().as_array_ref().clone().into() } fn make_messages_delivery_transaction( @@ -109,7 +109,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); + let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", @@ -138,7 +138,7 @@ pub async fn run( metrics_params: Option, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id_at_millau = millau_sign.signer.public().as_array_ref().clone().into(); + let relayer_id_at_millau = millau_sign.public().as_array_ref().clone().into(); let lane = MillauMessagesToRialto { source_client: millau_client.clone(), diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index 51e9d2898d2cb..7a48119be7ff2 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -27,205 +27,72 @@ pub mod westend_headers_to_millau; pub type MillauClient = relay_substrate_client::Client; /// Rialto node client. pub type RialtoClient = relay_substrate_client::Client; -/// Westend node client. -pub type WestendClient = relay_substrate_client::Client; -use crate::cli::{AccountChain, AccountId, ExplicitOrMaximal, HexBytes, Origins}; +use crate::cli::{ + AccountId, CliChain, ExplicitOrMaximal, HexBytes, Origins, SourceConnectionParams, SourceSigningParams, + TargetConnectionParams, TargetSigningParams, +}; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; -use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; use relay_westend_client::Westend; use sp_core::{Bytes, Pair}; -use sp_runtime::traits::IdentifyAccount; +use sp_runtime::{traits::IdentifyAccount, MultiSigner}; +use sp_version::RuntimeVersion; use std::fmt::Debug; -async fn run_init_bridge(command: cli::InitBridge) -> Result<(), String> { - match command { - cli::InitBridge::MillauToRialto { - millau, - rialto, - rialto_sign, - } => { - let millau_client = millau.into_client().await?; - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - - crate::headers_initialize::initialize( - millau_client, - rialto_client.clone(), - rialto_sign.signer.public().into(), - move |transaction_nonce, initialization_data| { - Bytes( - Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, - transaction_nonce, - rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::BridgeGrandpaMillauCall::initialize(initialization_data).into(), - )) - .into(), - ) - .encode(), - ) - }, - ) - .await; - } - cli::InitBridge::RialtoToMillau { - rialto, - millau, - millau_sign, - } => { - let rialto_client = rialto.into_client().await?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - - crate::headers_initialize::initialize( - rialto_client, - millau_client.clone(), - millau_sign.signer.public().into(), - move |transaction_nonce, initialization_data| { - let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::< - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >::initialize(initialization_data); - - Bytes( - Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - transaction_nonce, - millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into(), - ) - .encode(), - ) - }, - ) - .await; - } - cli::InitBridge::WestendToMillau { - westend, - millau, - millau_sign, - } => { - let westend_client = westend.into_client().await?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - - // at Westend -> Millau initialization we're not using sudo, because otherwise our deployments - // may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge. - // => since there's single possible sudo account, one of transaction may fail with duplicate nonce error - crate::headers_initialize::initialize( - westend_client, - millau_client.clone(), - millau_sign.signer.public().into(), - move |transaction_nonce, initialization_data| { - let initialize_call = millau_runtime::BridgeGrandpaWestendCall::< - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >::initialize(initialization_data); - - Bytes( - Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, - transaction_nonce, - initialize_call.into(), - ) - .encode(), - ) - }, - ) - .await; - } - } - Ok(()) -} - -async fn run_relay_headers(command: cli::RelayHeaders) -> Result<(), String> { - match command { - cli::RelayHeaders::MillauToRialto { - millau, - rialto, - rialto_sign, - prometheus_params, - } => { - let millau_client = millau.into_client().await?; - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - millau_headers_to_rialto::run(millau_client, rialto_client, rialto_sign, prometheus_params.into()).await - } - cli::RelayHeaders::RialtoToMillau { - rialto, - millau, - millau_sign, - prometheus_params, - } => { - let rialto_client = rialto.into_client().await?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - rialto_headers_to_millau::run(rialto_client, millau_client, millau_sign, prometheus_params.into()).await - } - cli::RelayHeaders::WestendToMillau { - westend, - millau, - millau_sign, - prometheus_params, - } => { - let westend_client = westend.into_client().await?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - westend_headers_to_millau::run(westend_client, millau_client, millau_sign, prometheus_params.into()).await - } - } -} - async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { match command { cli::RelayMessages::MillauToRialto { - millau, - millau_sign, - rialto, - rialto_sign, + source, + source_sign, + target, + target_sign, prometheus_params, lane, } => { - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; + type Source = Millau; + type Target = Rialto; + + let source_client = source_chain_client::(source).await?; + let source_sign = Source::source_signing_params(source_sign)?; + let target_client = target_chain_client::(target).await?; + let target_sign = Target::target_signing_params(target_sign)?; millau_messages_to_rialto::run( - millau_client, - millau_sign, - rialto_client, - rialto_sign, + source_client, + source_sign, + target_client, + target_sign, lane.into(), prometheus_params.into(), ) .await } cli::RelayMessages::RialtoToMillau { - rialto, - rialto_sign, - millau, - millau_sign, + source, + source_sign, + target, + target_sign, prometheus_params, lane, } => { - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; + type Source = Rialto; + type Target = Millau; + + let source_client = source_chain_client::(source).await?; + let source_sign = Source::source_signing_params(source_sign)?; + let target_client = target_chain_client::(target).await?; + let target_sign = Target::target_signing_params(target_sign)?; rialto_messages_to_millau::run( - rialto_client, - rialto_sign, - millau_client, - millau_sign, + source_client, + source_sign, + target_client, + target_sign, lane.into(), prometheus_params.into(), ) @@ -237,9 +104,9 @@ async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { match command { cli::SendMessage::MillauToRialto { - millau, - millau_sign, - rialto_sign, + source, + source_sign, + target_sign, lane, message, dispatch_weight, @@ -247,57 +114,105 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { origin, .. } => { - let millau_client = millau.into_client().await?; - let millau_sign = millau_sign.parse()?; - let rialto_sign = rialto_sign.parse()?; - let rialto_call = message.into_call()?; - - let payload = - millau_to_rialto_message_payload(&millau_sign, &rialto_sign, &rialto_call, origin, dispatch_weight); + type Source = Millau; + type Target = Rialto; + + let account_ownership_digest = |target_call, source_account_id| { + millau_runtime::rialto_account_ownership_digest( + &target_call, + source_account_id, + Target::RUNTIME_VERSION.spec_version, + ) + }; + let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; + let fee = fee.map(|x| x.cast()); + let send_message_call = |lane, payload, fee| { + millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( + lane, payload, fee, + )) + }; + + let source_client = source_chain_client::(source).await?; + let source_sign = Source::source_signing_params(source_sign)?; + let target_sign = Target::target_signing_params(target_sign)?; + let target_call = Target::encode_call(message)?; + + let payload = { + let target_call_weight = prepare_call_dispatch_weight( + dispatch_weight, + ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), + compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), + ); + let source_sender_public: MultiSigner = source_sign.public().into(); + let source_account_id = source_sender_public.into_account(); + + message_payload( + Target::RUNTIME_VERSION.spec_version, + target_call_weight, + match origin { + Origins::Source => CallOrigin::SourceAccount(source_account_id), + Origins::Target => { + let digest = account_ownership_digest(&target_call, source_account_id.clone()); + let target_origin_public = target_sign.public(); + let digest_signature = target_sign.sign(&digest); + CallOrigin::TargetAccount( + source_account_id, + target_origin_public.into(), + digest_signature.into(), + ) + } + }, + &target_call, + ) + }; let dispatch_weight = payload.weight; let lane = lane.into(); let fee = get_fee(fee, || { estimate_message_delivery_and_dispatch_fee( - &millau_client, - bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, + &source_client, + estimate_message_fee_method, lane, payload.clone(), ) }) .await?; - millau_client - .submit_signed_extrinsic(millau_sign.signer.public().clone().into(), |transaction_nonce| { - let millau_call = millau_runtime::Call::BridgeRialtoMessages( - millau_runtime::MessagesCall::send_message(lane, payload, fee), - ); + source_client + .submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| { + let send_message_call = send_message_call(lane, payload, fee); - let signed_millau_call = Millau::sign_transaction( - *millau_client.genesis_hash(), - &millau_sign.signer, + let signed_source_call = Source::sign_transaction( + *source_client.genesis_hash(), + &source_sign, transaction_nonce, - millau_call, + send_message_call, ) .encode(); log::info!( target: "bridge", - "Sending message to Rialto. Size: {}. Dispatch weight: {}. Fee: {}", - signed_millau_call.len(), + "Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}", + Target::NAME, + signed_source_call.len(), dispatch_weight, fee, ); - log::info!(target: "bridge", "Signed Millau Call: {:?}", HexBytes::encode(&signed_millau_call)); + log::info!( + target: "bridge", + "Signed {} Call: {:?}", + Source::NAME, + HexBytes::encode(&signed_source_call) + ); - Bytes(signed_millau_call) + Bytes(signed_source_call) }) .await?; } cli::SendMessage::RialtoToMillau { - rialto, - rialto_sign, - millau_sign, + source, + source_sign, + target_sign, lane, message, dispatch_weight, @@ -305,50 +220,98 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { origin, .. } => { - let rialto_client = rialto.into_client().await?; - let rialto_sign = rialto_sign.parse()?; - let millau_sign = millau_sign.parse()?; - let millau_call = message.into_call()?; - - let payload = - rialto_to_millau_message_payload(&rialto_sign, &millau_sign, &millau_call, origin, dispatch_weight); + type Source = Rialto; + type Target = Millau; + + let account_ownership_digest = |target_call, source_account_id| { + rialto_runtime::millau_account_ownership_digest( + &target_call, + source_account_id, + Target::RUNTIME_VERSION.spec_version, + ) + }; + let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + let fee = fee.map(|x| x.0); + let send_message_call = |lane, payload, fee| { + rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( + lane, payload, fee, + )) + }; + + let source_client = source_chain_client::(source).await?; + let source_sign = Source::source_signing_params(source_sign)?; + let target_sign = Target::target_signing_params(target_sign)?; + let target_call = Target::encode_call(message)?; + + let payload = { + let target_call_weight = prepare_call_dispatch_weight( + dispatch_weight, + ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), + compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), + ); + let source_sender_public: MultiSigner = source_sign.public().into(); + let source_account_id = source_sender_public.into_account(); + + message_payload( + Target::RUNTIME_VERSION.spec_version, + target_call_weight, + match origin { + Origins::Source => CallOrigin::SourceAccount(source_account_id), + Origins::Target => { + let digest = account_ownership_digest(&target_call, source_account_id.clone()); + let target_origin_public = target_sign.public(); + let digest_signature = target_sign.sign(&digest); + CallOrigin::TargetAccount( + source_account_id, + target_origin_public.into(), + digest_signature.into(), + ) + } + }, + &target_call, + ) + }; let dispatch_weight = payload.weight; let lane = lane.into(); let fee = get_fee(fee, || { estimate_message_delivery_and_dispatch_fee( - &rialto_client, - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, + &source_client, + estimate_message_fee_method, lane, payload.clone(), ) }) .await?; - rialto_client - .submit_signed_extrinsic(rialto_sign.signer.public().clone().into(), |transaction_nonce| { - let rialto_call = rialto_runtime::Call::BridgeMillauMessages( - rialto_runtime::MessagesCall::send_message(lane, payload, fee), - ); + source_client + .submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| { + let send_message_call = send_message_call(lane, payload, fee); - let signed_rialto_call = Rialto::sign_transaction( - *rialto_client.genesis_hash(), - &rialto_sign.signer, + let signed_source_call = Source::sign_transaction( + *source_client.genesis_hash(), + &source_sign, transaction_nonce, - rialto_call, + send_message_call, ) .encode(); log::info!( target: "bridge", - "Sending message to Millau. Size: {}. Dispatch weight: {}. Fee: {}", - signed_rialto_call.len(), + "Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}", + Target::NAME, + signed_source_call.len(), dispatch_weight, fee, ); - log::info!(target: "bridge", "Signed Rialto Call: {:?}", HexBytes::encode(&signed_rialto_call)); + log::info!( + target: "bridge", + "Signed {} Call: {:?}", + Source::NAME, + HexBytes::encode(&signed_source_call) + ); - Bytes(signed_rialto_call) + Bytes(signed_source_call) }) .await?; } @@ -359,12 +322,15 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { async fn run_encode_call(call: cli::EncodeCall) -> Result<(), String> { match call { cli::EncodeCall::Rialto { call } => { - let call = call.into_call()?; + type Source = Rialto; + let call = Source::encode_call(call)?; println!("{:?}", HexBytes::encode(&call)); } cli::EncodeCall::Millau { call } => { - let call = call.into_call()?; + type Source = Millau; + + let call = Source::encode_call(call)?; println!("{:?}", HexBytes::encode(&call)); } } @@ -374,13 +340,15 @@ async fn run_encode_call(call: cli::EncodeCall) -> Result<(), String> { async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<(), String> { match call { cli::EncodeMessagePayload::RialtoToMillau { payload } => { - let payload = payload.into_payload()?; + type Source = Rialto; + let payload = Source::encode_message(payload)?; println!("{:?}", HexBytes::encode(&payload)); } cli::EncodeMessagePayload::MillauToRialto { payload } => { - let payload = payload.into_payload()?; + type Source = Millau; + let payload = Source::encode_message(payload)?; println!("{:?}", HexBytes::encode(&payload)); } } @@ -389,33 +357,35 @@ async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<( async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { match cmd { - cli::EstimateFee::RialtoToMillau { rialto, lane, payload } => { - let client = rialto.into_client().await?; + cli::EstimateFee::RialtoToMillau { source, lane, payload } => { + type Source = Rialto; + type SourceBalance = bp_rialto::Balance; + + let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + + let source_client = source_chain_client::(source).await?; let lane = lane.into(); - let payload = payload.into_payload()?; + let payload = Source::encode_message(payload)?; - let fee: Option = estimate_message_delivery_and_dispatch_fee( - &client, - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload, - ) - .await?; + let fee: Option = + estimate_message_delivery_and_dispatch_fee(&source_client, estimate_message_fee_method, lane, payload) + .await?; println!("Fee: {:?}", fee); } - cli::EstimateFee::MillauToRialto { millau, lane, payload } => { - let client = millau.into_client().await?; + cli::EstimateFee::MillauToRialto { source, lane, payload } => { + type Source = Millau; + type SourceBalance = bp_millau::Balance; + + let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; + + let source_client = source_chain_client::(source).await?; let lane = lane.into(); - let payload = payload.into_payload()?; + let payload = Source::encode_message(payload)?; - let fee: Option = estimate_message_delivery_and_dispatch_fee( - &client, - bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload, - ) - .await?; + let fee: Option = + estimate_message_delivery_and_dispatch_fee(&source_client, estimate_message_fee_method, lane, payload) + .await?; println!("Fee: {:?}", fee); } @@ -427,20 +397,34 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { match cmd { cli::DeriveAccount::RialtoToMillau { mut account } => { - account.enforce_chain::(); + type Source = Rialto; + type Target = Millau; + + account.enforce_chain::(); let acc = bp_runtime::SourceAccount::Account(account.raw_id()); let id = bp_millau::derive_account_from_rialto_id(acc); - let derived_account = AccountId::from_raw::(id); - println!("Source address:\n{} (Rialto)", account); - println!("->Corresponding (derived) address:\n{} (Millau)", derived_account); + let derived_account = AccountId::from_raw::(id); + println!("Source address:\n{} ({})", account, Source::NAME); + println!( + "->Corresponding (derived) address:\n{} ({})", + derived_account, + Target::NAME, + ); } cli::DeriveAccount::MillauToRialto { mut account } => { - account.enforce_chain::(); + type Source = Millau; + type Target = Rialto; + + account.enforce_chain::(); let acc = bp_runtime::SourceAccount::Account(account.raw_id()); let id = bp_rialto::derive_account_from_millau_id(acc); - let derived_account = AccountId::from_raw::(id); - println!("Source address:\n{} (Millau)", account); - println!("->Corresponding (derived) address:\n{} (Rialto)", derived_account); + let derived_account = AccountId::from_raw::(id); + println!("Source address:\n{} ({})", account, Source::NAME); + println!( + "->Corresponding (derived) address:\n{} ({})", + derived_account, + Target::NAME, + ); } } @@ -514,80 +498,6 @@ where } } -fn rialto_to_millau_message_payload( - rialto_sign: &RialtoSigningParams, - millau_sign: &MillauSigningParams, - millau_call: &millau_runtime::Call, - origin: Origins, - user_specified_dispatch_weight: Option>, -) -> rialto_runtime::millau_messages::ToMillauMessagePayload { - let millau_call_weight = prepare_call_dispatch_weight( - user_specified_dispatch_weight, - ExplicitOrMaximal::Explicit(millau_call.get_dispatch_info().weight), - compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()), - ); - let rialto_sender_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); - let rialto_account_id: bp_rialto::AccountId = rialto_sender_public.into_account(); - let millau_origin_public = millau_sign.signer.public(); - - message_payload( - millau_runtime::VERSION.spec_version, - millau_call_weight, - match origin { - Origins::Source => CallOrigin::SourceAccount(rialto_account_id), - Origins::Target => { - let digest = rialto_runtime::millau_account_ownership_digest( - &millau_call, - rialto_account_id.clone(), - millau_runtime::VERSION.spec_version, - ); - - let digest_signature = millau_sign.signer.sign(&digest); - - CallOrigin::TargetAccount(rialto_account_id, millau_origin_public.into(), digest_signature.into()) - } - }, - &millau_call, - ) -} - -fn millau_to_rialto_message_payload( - millau_sign: &MillauSigningParams, - rialto_sign: &RialtoSigningParams, - rialto_call: &rialto_runtime::Call, - origin: Origins, - user_specified_dispatch_weight: Option>, -) -> millau_runtime::rialto_messages::ToRialtoMessagePayload { - let rialto_call_weight = prepare_call_dispatch_weight( - user_specified_dispatch_weight, - ExplicitOrMaximal::Explicit(rialto_call.get_dispatch_info().weight), - compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), - ); - let millau_sender_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); - let millau_account_id: bp_millau::AccountId = millau_sender_public.into_account(); - let rialto_origin_public = rialto_sign.signer.public(); - - message_payload( - rialto_runtime::VERSION.spec_version, - rialto_call_weight, - match origin { - Origins::Source => CallOrigin::SourceAccount(millau_account_id), - Origins::Target => { - let digest = millau_runtime::rialto_account_ownership_digest( - &rialto_call, - millau_account_id.clone(), - rialto_runtime::VERSION.spec_version, - ); - - let digest_signature = rialto_sign.signer.sign(&digest); - - CallOrigin::TargetAccount(millau_account_id, rialto_origin_public.into(), digest_signature.into()) - } - }, - &rialto_call, - ) -} - fn prepare_call_dispatch_weight( user_specified_dispatch_weight: Option>, weight_from_pre_dispatch_call: ExplicitOrMaximal, @@ -640,40 +550,72 @@ fn compute_maximal_message_arguments_size( maximal_call_size - service_bytes } -impl cli::MillauToRialtoMessagePayload { - /// Parse the CLI parameters and construct message payload. - pub fn into_payload( - self, - ) -> Result>, String> { - match self { - Self::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), - Self::Message { message, mut sender } => { - let spec_version = rialto_runtime::VERSION.spec_version; - sender.enforce_chain::(); - let origin = CallOrigin::SourceAccount(sender.raw_id()); - let call = message.into_call()?; - let weight = call.get_dispatch_info().weight; +impl CliChain for Millau { + const RUNTIME_VERSION: RuntimeVersion = millau_runtime::VERSION; - Ok(message_payload(spec_version, weight, origin, &call)) + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = MessagePayload>; + + fn ss58_format() -> u16 { + millau_runtime::SS58Prefix::get() as u16 + } + + fn max_extrinsic_weight() -> Weight { + bp_millau::max_extrinsic_weight() + } + + fn encode_call(call: cli::Call) -> Result { + let call = match call { + cli::Call::Raw { data } => { + Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? } - } + cli::Call::Remark { remark_size } => { + millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( + remark_size, + compute_maximal_message_arguments_size( + bp_rialto::max_extrinsic_size(), + bp_millau::max_extrinsic_size(), + ), + ))) + } + cli::Call::Transfer { mut recipient, amount } => { + recipient.enforce_chain::(); + let amount = amount.cast(); + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) + } + cli::Call::BridgeSendMessage { lane, payload, fee } => { + type Target = Rialto; + + let payload = Target::encode_message(cli::MessagePayload::Raw { data: payload })?; + let lane = lane.into(); + millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( + lane, + payload, + fee.cast(), + )) + } + }; + + log::info!(target: "bridge", "Generated Millau call: {:#?}", call); + log::info!(target: "bridge", "Weight of Millau call: {}", call.get_dispatch_info().weight); + log::info!(target: "bridge", "Encoded Millau call: {:?}", HexBytes::encode(&call)); + + Ok(call) } -} -impl cli::RialtoToMillauMessagePayload { - /// Parse the CLI parameters and construct message payload. - pub fn into_payload( - self, - ) -> Result>, String> { - match self { - Self::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), - Self::Message { message, mut sender } => { - let spec_version = millau_runtime::VERSION.spec_version; - sender.enforce_chain::(); + // TODO [#854|#843] support multiple bridges? + fn encode_message(message: cli::MessagePayload) -> Result { + match message { + cli::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), + cli::MessagePayload::Call { call, mut sender } => { + type Source = Millau; + type Target = Rialto; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - let call = message.into_call()?; + let call = Target::encode_call(call)?; let weight = call.get_dispatch_info().weight; Ok(message_payload(spec_version, weight, origin, &call)) @@ -682,66 +624,26 @@ impl cli::RialtoToMillauMessagePayload { } } -impl cli::RialtoSigningParams { - /// Parse CLI parameters into typed signing params. - pub fn parse(self) -> Result { - RialtoSigningParams::from_suri(&self.rialto_signer, self.rialto_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse rialto-signer: {:?}", e)) - } -} - -impl cli::MillauSigningParams { - /// Parse CLI parameters into typed signing params. - pub fn parse(self) -> Result { - MillauSigningParams::from_suri(&self.millau_signer, self.millau_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse millau-signer: {:?}", e)) - } -} +impl CliChain for Rialto { + const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; -impl cli::MillauConnectionParams { - /// Convert CLI connection parameters into Millau RPC Client. - pub async fn into_client(self) -> relay_substrate_client::Result { - MillauClient::new(ConnectionParams { - host: self.millau_host, - port: self.millau_port, - secure: self.millau_secure, - }) - .await - } -} + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = MessagePayload>; -impl cli::RialtoConnectionParams { - /// Convert CLI connection parameters into Rialto RPC Client. - pub async fn into_client(self) -> relay_substrate_client::Result { - RialtoClient::new(ConnectionParams { - host: self.rialto_host, - port: self.rialto_port, - secure: self.rialto_secure, - }) - .await + fn ss58_format() -> u16 { + rialto_runtime::SS58Prefix::get() as u16 } -} -impl cli::WestendConnectionParams { - /// Convert CLI connection parameters into Westend RPC Client. - pub async fn into_client(self) -> relay_substrate_client::Result { - WestendClient::new(ConnectionParams { - host: self.westend_host, - port: self.westend_port, - secure: self.westend_secure, - }) - .await + fn max_extrinsic_weight() -> Weight { + bp_rialto::max_extrinsic_weight() } -} -impl cli::ToRialtoMessage { - /// Convert CLI call request into runtime `Call` instance. - pub fn into_call(self) -> Result { - let call = match self { - cli::ToRialtoMessage::Raw { data } => { + fn encode_call(call: cli::Call) -> Result { + let call = match call { + cli::Call::Raw { data } => { Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? } - cli::ToRialtoMessage::Remark { remark_size } => { + cli::Call::Remark { remark_size } => { rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload( remark_size, compute_maximal_message_arguments_size( @@ -750,15 +652,20 @@ impl cli::ToRialtoMessage { ), ))) } - cli::ToRialtoMessage::Transfer { mut recipient, amount } => { - recipient.enforce_chain::(); + cli::Call::Transfer { mut recipient, amount } => { + type Source = Rialto; + + recipient.enforce_chain::(); + let amount = amount.0; rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) } - cli::ToRialtoMessage::MillauSendMessage { lane, payload, fee } => { - let payload = cli::RialtoToMillauMessagePayload::Raw { data: payload }.into_payload()?; + cli::Call::BridgeSendMessage { lane, payload, fee } => { + type Target = Millau; + + let payload = Target::encode_message(cli::MessagePayload::Raw { data: payload })?; let lane = lane.into(); rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( - lane, payload, fee, + lane, payload, fee.0, )) } }; @@ -769,59 +676,80 @@ impl cli::ToRialtoMessage { Ok(call) } -} -impl cli::ToMillauMessage { - /// Convert CLI call request into runtime `Call` instance. - pub fn into_call(self) -> Result { - let call = match self { - cli::ToMillauMessage::Raw { data } => { - Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? - } - cli::ToMillauMessage::Remark { remark_size } => { - millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( - remark_size, - compute_maximal_message_arguments_size( - bp_rialto::max_extrinsic_size(), - bp_millau::max_extrinsic_size(), - ), - ))) - } - cli::ToMillauMessage::Transfer { mut recipient, amount } => { - recipient.enforce_chain::(); - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) - } - cli::ToMillauMessage::RialtoSendMessage { lane, payload, fee } => { - let payload = cli::MillauToRialtoMessagePayload::Raw { data: payload }.into_payload()?; - let lane = lane.into(); - millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( - lane, payload, fee, - )) + fn encode_message(message: cli::MessagePayload) -> Result { + match message { + cli::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), + cli::MessagePayload::Call { call, mut sender } => { + type Source = Rialto; + type Target = Millau; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + let call = Target::encode_call(call)?; + let weight = call.get_dispatch_info().weight; + + Ok(message_payload(spec_version, weight, origin, &call)) } - }; + } + } - log::info!(target: "bridge", "Generated Millau call: {:#?}", call); - log::info!(target: "bridge", "Weight of Millau call: {}", call.get_dispatch_info().weight); - log::info!(target: "bridge", "Encoded Millau call: {:?}", HexBytes::encode(&call)); + fn source_signing_params(params: SourceSigningParams) -> Result { + Self::KeyPair::from_string(¶ms.source_signer, params.source_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse source-signer: {:?}", e)) + } - Ok(call) + fn target_signing_params(params: TargetSigningParams) -> Result { + Self::KeyPair::from_string(¶ms.target_signer, params.target_signer_password.as_deref()) + .map_err(|e| format!("Failed to parse target-signer: {:?}", e)) } } -impl AccountChain for Rialto { - const NAME: &'static str = "Rialto"; +impl CliChain for Westend { + const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); fn ss58_format() -> u16 { - rialto_runtime::SS58Prefix::get() as u16 + 42 } -} -impl AccountChain for Millau { - const NAME: &'static str = "Millau"; + fn max_extrinsic_weight() -> Weight { + 0 + } - fn ss58_format() -> u16 { - millau_runtime::SS58Prefix::get() as u16 + fn encode_call(_: cli::Call) -> Result { + Err("Calling into Westend is not supported yet.".into()) } + + fn encode_message(_message: cli::MessagePayload) -> Result { + Err("Sending messages from Westend is not yet supported.".into()) + } +} + +pub async fn source_chain_client( + params: SourceConnectionParams, +) -> relay_substrate_client::Result> { + relay_substrate_client::Client::new(ConnectionParams { + host: params.source_host, + port: params.source_port, + secure: params.source_secure, + }) + .await +} + +pub async fn target_chain_client( + params: TargetConnectionParams, +) -> relay_substrate_client::Result> { + relay_substrate_client::Client::new(ConnectionParams { + host: params.target_host, + port: params.target_port, + secure: params.target_secure, + }) + .await } #[cfg(test)] @@ -833,11 +761,11 @@ mod tests { #[test] fn millau_signature_is_valid_on_rialto() { - let millau_sign = relay_millau_client::SigningParams::from_suri("//Dave", None).unwrap(); + let millau_sign = relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); let call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); - let millau_public: bp_millau::AccountSigner = millau_sign.signer.public().clone().into(); + let millau_public: bp_millau::AccountSigner = millau_sign.public().into(); let millau_account_id: bp_millau::AccountId = millau_public.into_account(); let digest = millau_runtime::rialto_account_ownership_digest( @@ -846,19 +774,19 @@ mod tests { rialto_runtime::VERSION.spec_version, ); - let rialto_signer = relay_rialto_client::SigningParams::from_suri("//Dave", None).unwrap(); - let signature = rialto_signer.signer.sign(&digest); + let rialto_signer = relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); + let signature = rialto_signer.sign(&digest); - assert!(signature.verify(&digest[..], &rialto_signer.signer.public())); + assert!(signature.verify(&digest[..], &rialto_signer.public())); } #[test] fn rialto_signature_is_valid_on_millau() { - let rialto_sign = relay_rialto_client::SigningParams::from_suri("//Dave", None).unwrap(); + let rialto_sign = relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); let call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); - let rialto_public: bp_rialto::AccountSigner = rialto_sign.signer.public().clone().into(); + let rialto_public: bp_rialto::AccountSigner = rialto_sign.public().into(); let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); let digest = rialto_runtime::millau_account_ownership_digest( @@ -867,10 +795,10 @@ mod tests { millau_runtime::VERSION.spec_version, ); - let millau_signer = relay_millau_client::SigningParams::from_suri("//Dave", None).unwrap(); - let signature = millau_signer.signer.sign(&digest); + let millau_signer = relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); + let signature = millau_signer.sign(&digest); - assert!(signature.verify(&digest[..], &millau_signer.signer.public())); + assert!(signature.verify(&digest[..], &millau_signer.public())); } #[test] diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index 910d2bf03bf46..93a5e48b83cd8 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -16,7 +16,6 @@ //! Rialto-to-Millau headers sync entrypoint. -use super::{MillauClient, RialtoClient}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use codec::Encode; @@ -34,7 +33,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { type TargetChain = Millau; fn transactions_author(&self) -> bp_millau::AccountId { - self.target_sign.signer.public().as_array_ref().clone().into() + self.target_sign.public().as_array_ref().clone().into() } fn make_submit_finality_proof_transaction( @@ -50,24 +49,8 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { .into(); let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); Bytes(transaction.encode()) } } - -/// Run Rialto-to-Millau finality sync. -pub async fn run( - rialto_client: RialtoClient, - millau_client: MillauClient, - millau_sign: MillauSigningParams, - metrics_params: Option, -) -> Result<(), String> { - crate::finality_pipeline::run( - RialtoFinalityToMillau::new(millau_client.clone(), millau_sign), - rialto_client, - millau_client, - metrics_params, - ) - .await -} diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index 7268ff07e00db..23c338390bfe1 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -56,7 +56,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { type TargetChain = Millau; fn source_transactions_author(&self) -> bp_rialto::AccountId { - self.source_sign.signer.public().as_array_ref().clone().into() + self.source_sign.public().as_array_ref().clone().into() } fn make_messages_receiving_proof_transaction( @@ -70,7 +70,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign.signer, transaction_nonce, call); + let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -83,7 +83,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } fn target_transactions_author(&self) -> bp_rialto::AccountId { - self.target_sign.signer.public().as_array_ref().clone().into() + self.target_sign.public().as_array_ref().clone().into() } fn make_messages_delivery_transaction( @@ -109,7 +109,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", @@ -138,7 +138,7 @@ pub async fn run( metrics_params: Option, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id_at_rialto = rialto_sign.signer.public().as_array_ref().clone().into(); + let relayer_id_at_rialto = rialto_sign.public().as_array_ref().clone().into(); let lane = RialtoMessagesToMillau { source_client: rialto_client.clone(), diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index ca670e05f3285..4aa6b569f0895 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -16,7 +16,6 @@ //! Westend-to-Millau headers sync entrypoint. -use super::{MillauClient, WestendClient}; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use codec::Encode; @@ -34,7 +33,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; fn transactions_author(&self) -> bp_millau::AccountId { - self.target_sign.signer.public().as_array_ref().clone().into() + self.target_sign.public().as_array_ref().clone().into() } fn make_submit_finality_proof_transaction( @@ -50,24 +49,8 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { .into(); let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign.signer, transaction_nonce, call); + let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); Bytes(transaction.encode()) } } - -/// Run Westend-to-Millau finality sync. -pub async fn run( - westend_client: WestendClient, - millau_client: MillauClient, - millau_sign: MillauSigningParams, - metrics_params: Option, -) -> Result<(), String> { - crate::finality_pipeline::run( - WestendFinalityToMillau::new(millau_client.clone(), millau_sign), - westend_client, - millau_client, - metrics_params, - ) - .await -} diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 36444cda45ca8..a547fb9ac63fd 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -100,26 +100,7 @@ impl TransactionSignScheme for Millau { } /// Millau signing params. -#[derive(Clone)] -pub struct SigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl SigningParams { - /// Create signing params from SURI and password. - pub fn from_suri(suri: &str, password: Option<&str>) -> Result { - Ok(SigningParams { - signer: sp_core::sr25519::Pair::from_string(suri, password)?, - }) - } -} - -impl std::fmt::Debug for SigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} +pub type SigningParams = sp_core::sr25519::Pair; /// Millau header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index bac65b6427615..d74d6a8806047 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -100,34 +100,7 @@ impl TransactionSignScheme for Rialto { } /// Rialto signing params. -#[derive(Clone)] -pub struct SigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl SigningParams { - /// Create signing params from SURI and password. - pub fn from_suri(suri: &str, password: Option<&str>) -> Result { - Ok(SigningParams { - signer: sp_core::sr25519::Pair::from_string(suri, password)?, - }) - } -} - -impl std::fmt::Debug for SigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} - -impl Default for SigningParams { - fn default() -> Self { - SigningParams { - signer: sp_keyring::AccountKeyring::Alice.pair(), - } - } -} +pub type SigningParams = sp_core::sr25519::Pair; /// Rialto header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index c513cf1b70f0d..4e1f45eca3e64 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -42,6 +42,19 @@ pub enum Error { Custom(String), } +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::RpcError(ref e) => Some(e), + Self::ResponseParseFailed(ref e) => Some(e), + Self::UninitializedBridgePallet => None, + Self::AccountDoesNotExist => None, + Self::ClientNotSynced(_) => None, + Self::Custom(_) => None, + } + } +} + impl From for Error { fn from(error: RpcError) -> Self { Error::RpcError(error) @@ -61,21 +74,23 @@ impl MaybeConnectionError for Error { } } -impl From for String { - fn from(error: Error) -> String { - error.to_string() - } -} - -impl ToString for Error { - fn to_string(&self) -> String { - match self { +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let s = match self { Self::RpcError(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), Self::Custom(e) => e.clone(), - } + }; + + write!(f, "{}", s) + } +} + +impl From for String { + fn from(error: Error) -> String { + error.to_string() } } From 146c70f76aa7239e0dcb41b12d4087f738e15aab Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 1 Apr 2021 07:08:28 -0400 Subject: [PATCH 0400/1210] Use GrandpaJustification instead of Vec in Pallet API (#847) * Stop passing raw encoded justifications to pallet API By having the API accept a struct-ified justification we are able to better utilize the justifications fields for weight calculations. * Update relayer code to use decoded justifications * Add justification to `expect()` statement * Fix some imports * Make justification wrapper contain decoded justification * Rename some fields * Get rid of warnings * Appease Clippy * Only decode justification once at init time * Remove unnecessary method * Remove justification wrapper This became kinda unnecessary since we could implement the FinalityProof trait on GrandpaJustification directly. --- modules/grandpa/src/lib.rs | 31 +++++---- modules/substrate/src/verifier.rs | 8 ++- primitives/header-chain/src/justification.rs | 16 +++-- primitives/header-chain/src/lib.rs | 6 ++ .../header-chain/tests/justification.rs | 25 +++---- primitives/runtime/src/storage_proof.rs | 5 +- relays/bin-substrate/src/finality_pipeline.rs | 10 ++- .../bin-substrate/src/headers_initialize.rs | 12 ++-- .../rialto_millau/millau_headers_to_rialto.rs | 9 ++- .../rialto_millau/rialto_headers_to_millau.rs | 7 +- .../westend_headers_to_millau.rs | 7 +- .../client-substrate/src/finality_source.rs | 65 ++++++------------- relays/finality/Cargo.toml | 1 + relays/finality/src/lib.rs | 7 +- 14 files changed, 92 insertions(+), 117 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 4f3afcbbf7876..acf9b7e736010 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -36,6 +36,7 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] +use bp_header_chain::justification::GrandpaJustification; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; @@ -46,7 +47,6 @@ use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; use sp_runtime::RuntimeDebug; -use sp_std::vec::Vec; #[cfg(test)] mod mock; @@ -111,7 +111,7 @@ pub mod pallet { pub fn submit_finality_proof( origin: OriginFor, finality_target: BridgedHeader, - justification: Vec, + justification: GrandpaJustification>, ) -> DispatchResultWithPostInfo { ensure_operational::()?; let _ = ensure_signed(origin)?; @@ -359,7 +359,7 @@ pub mod pallet { /// /// Will use the GRANDPA current authorities known to the pallet. pub(crate) fn verify_justification, I: 'static>( - justification: &[u8], + justification: &GrandpaJustification>, hash: BridgedBlockHash, number: BridgedBlockNumber, ) -> Result<(), sp_runtime::DispatchError> { @@ -515,7 +515,7 @@ pub(crate) fn find_forced_change( pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader) { initialize_bridge::(InitializationData { header, - authority_list: Vec::new(), // we don't verify any proofs in external benchmarks + authority_list: sp_std::vec::Vec::new(), // we don't verify any proofs in external benchmarks set_id: 0, is_halted: false, }); @@ -555,7 +555,7 @@ mod tests { fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { let header = test_header(header.into()); - let justification = make_default_justification(&header).encode(); + let justification = make_default_justification(&header); Module::::submit_finality_proof(Origin::signed(1), header, justification) } @@ -701,10 +701,7 @@ mod tests { run_test(|| { >::put(true); - assert_noop!( - Module::::submit_finality_proof(Origin::signed(1), test_header(1), vec![]), - Error::::Halted, - ); + assert_noop!(submit_finality_proof(1), Error::::Halted,); }) } @@ -731,7 +728,7 @@ mod tests { set_id: 2, ..Default::default() }; - let justification = make_justification_for_header(params).encode(); + let justification = make_justification_for_header(params); assert_err!( Module::::submit_finality_proof(Origin::signed(1), header, justification,), @@ -746,7 +743,8 @@ mod tests { initialize_substrate_bridge(); let header = test_header(1); - let justification = [1u8; 32].encode(); + let mut justification = make_default_justification(&header); + justification.round = 42; assert_err!( Module::::submit_finality_proof(Origin::signed(1), header, justification,), @@ -771,7 +769,7 @@ mod tests { assert_ok!(Module::::initialize(Origin::root(), init_data)); let header = test_header(1); - let justification = [1u8; 32].encode(); + let justification = make_default_justification(&header); assert_err!( Module::::submit_finality_proof(Origin::signed(1), header, justification,), @@ -805,7 +803,7 @@ mod tests { header.digest = change_log(0); // Create a valid justification for the header - let justification = make_default_justification(&header).encode(); + let justification = make_default_justification(&header); // Let's import our test header assert_ok!(Module::::submit_finality_proof( @@ -837,7 +835,7 @@ mod tests { header.digest = change_log(1); // Create a valid justification for the header - let justification = make_default_justification(&header).encode(); + let justification = make_default_justification(&header); // Should not be allowed to import this header assert_err!( @@ -858,7 +856,7 @@ mod tests { header.digest = forced_change_log(0); // Create a valid justification for the header - let justification = make_default_justification(&header).encode(); + let justification = make_default_justification(&header); // Should not be allowed to import this header assert_err!( @@ -917,7 +915,8 @@ mod tests { run_test(|| { let submit_invalid_request = || { let header = test_header(1); - let invalid_justification = vec![4, 2, 4, 2].encode(); + let mut invalid_justification = make_default_justification(&header); + invalid_justification.round = 42; Module::::submit_finality_proof(Origin::signed(1), header, invalid_justification) }; diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index f2e33e21e481f..891864554baaa 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -215,6 +215,8 @@ where /// proof. If the header enacts an authority set change the change will be applied once the /// header has been finalized. pub fn import_finality_proof(&mut self, hash: H::Hash, proof: FinalityProof) -> Result<(), FinalizationError> { + use codec::Decode; + // Make sure that we've previously imported this header let header = self .storage @@ -233,11 +235,15 @@ where "We verified the correctness of the authority list during header import, before writing them to storage. This must always be valid.", ); + + let justification = bp_header_chain::justification::GrandpaJustification::::decode(&mut proof.0.as_slice()) + .map_err(|_| FinalizationError::InvalidJustification)?; + verify_justification::( (hash, *header.number()), current_authority_set.set_id, &voter_set, - &proof.0, + &justification, ) .map_err(|_| FinalizationError::InvalidJustification)?; log::trace!("Received valid justification for {:?}", header); diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 67968258a5c5c..1db15440fb5c2 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -25,7 +25,7 @@ use frame_support::RuntimeDebug; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::traits::Header as HeaderT; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; -use sp_std::prelude::Vec; +use sp_std::prelude::*; /// Justification verification error. #[derive(RuntimeDebug, PartialEq)] @@ -58,15 +58,11 @@ pub fn verify_justification( finalized_target: (Header::Hash, Header::Number), authorities_set_id: SetId, authorities_set: &VoterSet, - raw_justification: &[u8], + justification: &GrandpaJustification

, ) -> Result<(), Error> where Header::Number: finality_grandpa::BlockNumberOps, { - // Decode justification first - let justification = - GrandpaJustification::
::decode(&mut &*raw_justification).map_err(|_| Error::JustificationDecode)?; - // Ensure that it is justification for the expected header if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { return Err(Error::InvalidJustificationTarget); @@ -130,7 +126,7 @@ where /// /// This particular proof is used to prove that headers on a bridged chain /// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, RuntimeDebug)] +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] pub struct GrandpaJustification { /// The round (voting period) this justification is valid for. pub round: u64, @@ -140,6 +136,12 @@ pub struct GrandpaJustification { pub votes_ancestries: Vec
, } +impl crate::FinalityProof for GrandpaJustification { + fn target_header_number(&self) -> H::Number { + self.commit.target_number + } +} + /// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. #[derive(RuntimeDebug)] struct AncestryChain { diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index e9f6cee9c9ab8..ba47d614faaa8 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -94,6 +94,12 @@ impl HeaderChain for () { } } +/// Abstract finality proof that is justifying block finality. +pub trait FinalityProof: Clone + Send + Sync + Debug { + /// Return number of header that this proof is generated for. + fn target_header_number(&self) -> Number; +} + /// Find header digest that schedules next GRANDPA authorities set. pub fn find_grandpa_authorities_scheduled_change( header: &H, diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 33808461f6515..96bb6d442a77c 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -18,7 +18,6 @@ use bp_header_chain::justification::{verify_justification, Error}; use bp_test_utils::*; -use codec::Encode; type TestHeader = sp_runtime::testing::Header; @@ -38,7 +37,7 @@ fn valid_justification_accepted() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &make_justification_for_header::(params).encode() + &make_justification_for_header::(params) ), Ok(()), ); @@ -60,7 +59,7 @@ fn valid_justification_accepted_with_single_fork() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &make_justification_for_header::(params).encode() + &make_justification_for_header::(params) ), Ok(()), ); @@ -94,20 +93,12 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set, - &make_justification_for_header::(params).encode() + &make_justification_for_header::(params) ), Ok(()), ); } -#[test] -fn justification_with_invalid_encoding_rejected() { - assert_eq!( - verify_justification::(header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), &[],), - Err(Error::JustificationDecode), - ); -} - #[test] fn justification_with_invalid_target_rejected() { assert_eq!( @@ -115,7 +106,7 @@ fn justification_with_invalid_target_rejected() { header_id::(2), TEST_GRANDPA_SET_ID, &voter_set(), - &make_default_justification::(&test_header(1)).encode(), + &make_default_justification::(&test_header(1)), ), Err(Error::InvalidJustificationTarget), ); @@ -131,7 +122,7 @@ fn justification_with_invalid_commit_rejected() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &justification.encode(), + &justification, ), Err(Error::InvalidJustificationCommit), ); @@ -147,7 +138,7 @@ fn justification_with_invalid_authority_signature_rejected() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &justification.encode(), + &justification, ), Err(Error::InvalidAuthoritySignature), ); @@ -163,7 +154,7 @@ fn justification_with_invalid_precommit_ancestry() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &justification.encode(), + &justification, ), Err(Error::InvalidPrecommitAncestries), ); @@ -186,7 +177,7 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &make_justification_for_header::(params).encode() + &make_justification_for_header::(params) ), Err(Error::InvalidJustificationCommit), ); diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 4c8c2047d2fd4..2d81e5a4b6cc5 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -17,7 +17,6 @@ //! Logic for checking Substrate storage proofs. use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; -use sp_core::H256; use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; use sp_trie::{read_trie_value, Layout, MemoryDB, StorageProof}; @@ -67,7 +66,7 @@ pub enum Error { /// /// NOTE: This should only be used for **testing**. #[cfg(feature = "std")] -pub fn craft_valid_storage_proof() -> (H256, StorageProof) { +pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; // construct storage proof @@ -106,7 +105,7 @@ pub mod tests { // checking proof against invalid commitment fails assert_eq!( - >::new(H256::random(), proof).err(), + >::new(sp_core::H256::random(), proof).err(), Some(Error::StorageRootMismatch) ); } diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index d58306f44ff52..0b035cd57f2aa 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -18,11 +18,9 @@ use crate::finality_target::SubstrateFinalityTarget; +use bp_header_chain::justification::GrandpaJustification; use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; -use relay_substrate_client::{ - finality_source::{FinalitySource, Justification}, - BlockNumberOf, Chain, Client, HashOf, SyncHeader, -}; +use relay_substrate_client::{finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader}; use relay_utils::BlockNumberBase; use sp_core::Bytes; use std::{fmt::Debug, marker::PhantomData, time::Duration}; @@ -101,7 +99,7 @@ where type Hash = HashOf; type Number = BlockNumberOf; type Header = SyncHeader; - type FinalityProof = Justification; + type FinalityProof = GrandpaJustification; } /// Run Substrate-to-Substrate finality sync. @@ -116,7 +114,7 @@ where Hash = HashOf, Number = BlockNumberOf, Header = SyncHeader, - FinalityProof = Justification, + FinalityProof = GrandpaJustification, TargetChain = TargetChain, >, SourceChain: Clone + Chain, diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index bc191df3b7153..07d6d0f06d91a 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -23,7 +23,7 @@ use bp_header_chain::{ find_grandpa_authorities_scheduled_change, - justification::{decode_justification_target, verify_justification}, + justification::{verify_justification, GrandpaJustification}, }; use codec::Decode; use finality_grandpa::voter_set::VoterSet; @@ -116,9 +116,12 @@ async fn prepare_initialization_data( })?; // Read initial header. + let justification: GrandpaJustification = Decode::decode(&mut &justification.0[..]) + .map_err(|err| format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err))?; + let (initial_header_hash, initial_header_number) = - decode_justification_target::(&justification.0) - .map_err(|err| format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err))?; + (justification.commit.target_hash, justification.commit.target_number); + let initial_header = source_header(&source_client, initial_header_hash).await?; log::trace!(target: "bridge", "Selected {} initial header: {}/{}", SourceChain::NAME, @@ -176,9 +179,10 @@ async fn prepare_initialization_data( (initial_header_hash, initial_header_number), initial_authorities_set_id, &authorities_for_verification, - &justification.0, + &justification, ) .is_ok(); + if is_valid_set_id { break; } diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index f85560bf19266..43ae3954c36f2 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -18,10 +18,11 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; /// Millau-to-Rialto finality sync pipeline. @@ -40,11 +41,9 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { &self, transaction_nonce: ::Index, header: MillauSyncHeader, - proof: Justification, + proof: GrandpaJustification, ) -> Bytes { - let call = - rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof.into_inner()) - .into(); + let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof).into(); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index 93a5e48b83cd8..f18f108320386 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -18,10 +18,11 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; /// Rialto-to-Millau finality sync pipeline. @@ -40,12 +41,12 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { &self, transaction_nonce: ::Index, header: RialtoSyncHeader, - proof: Justification, + proof: GrandpaJustification, ) -> Bytes { let call = millau_runtime::BridgeGrandpaRialtoCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, - >::submit_finality_proof(header.into_inner(), proof.into_inner()) + >::submit_finality_proof(header.into_inner(), proof) .into(); let genesis_hash = *self.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index 4aa6b569f0895..f042c0bd3919e 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -18,9 +18,10 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{finality_source::Justification, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use sp_core::{Bytes, Pair}; @@ -40,12 +41,12 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { &self, transaction_nonce: ::Index, header: WestendSyncHeader, - proof: Justification, + proof: GrandpaJustification, ) -> Bytes { let call = millau_runtime::BridgeGrandpaWestendCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, - >::submit_finality_proof(header.into_inner(), proof.into_inner()) + >::submit_finality_proof(header.into_inner(), proof) .into(); let genesis_hash = *self.target_client.genesis_hash(); diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 9b6c0975a45cf..38500934191d2 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -22,35 +22,14 @@ use crate::error::Error; use crate::sync_header::SyncHeader; use async_trait::async_trait; -use bp_header_chain::justification::decode_justification_target; -use finality_relay::{FinalityProof, FinalitySyncPipeline, SourceClient, SourceHeader}; +use bp_header_chain::justification::GrandpaJustification; +use codec::Decode; +use finality_relay::{FinalitySyncPipeline, SourceClient, SourceHeader}; use futures::stream::{unfold, Stream, StreamExt}; use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::traits::Header as HeaderT; use std::{marker::PhantomData, pin::Pin}; -/// Wrapped raw Justification. -#[derive(Debug, Clone)] -pub struct Justification { - /// Header number decoded from the [`raw_justification`]. - target_header_number: Number, - /// Raw, encoded justification bytes. - raw_justification: sp_runtime::Justification, -} - -impl Justification { - /// Extract raw justification. - pub fn into_inner(self) -> sp_runtime::Justification { - self.raw_justification - } -} - -impl FinalityProof for Justification { - fn target_header_number(&self) -> Number { - self.target_header_number - } -} - /// Substrate node as finality source. pub struct FinalitySource { client: Client, @@ -94,11 +73,11 @@ where Hash = C::Hash, Number = C::BlockNumber, Header = SyncHeader, - FinalityProof = Justification, + FinalityProof = GrandpaJustification, >, P::Header: SourceHeader, { - type FinalityProofsStream = Pin> + Send>>; + type FinalityProofsStream = Pin> + Send>>; async fn best_finalized_block_number(&self) -> Result { // we **CAN** continue to relay finality proofs if source node is out of sync, because @@ -114,16 +93,14 @@ where ) -> Result<(P::Header, Option), Error> { let header_hash = self.client.block_hash_by_number(number).await?; let signed_block = self.client.get_block(Some(header_hash)).await?; - Ok(( - signed_block.header().into(), - signed_block - .justification() - .cloned() - .map(|raw_justification| Justification { - target_header_number: number, - raw_justification, - }), - )) + + let justification = signed_block + .justification() + .map(|raw_justification| GrandpaJustification::::decode(&mut raw_justification.as_slice())) + .transpose() + .map_err(Error::ResponseParseFailed)?; + + Ok((signed_block.header().into(), justification)) } async fn finality_proofs(&self) -> Result { @@ -132,9 +109,11 @@ where move |mut subscription| async move { loop { let next_justification = subscription.next().await?; - let decoded_target = decode_justification_target::(&next_justification.0); - let target_header_number = match decoded_target { - Ok((_, number)) => number, + let decoded_justification = + GrandpaJustification::::decode(&mut &next_justification.0[..]); + + let justification = match decoded_justification { + Ok(j) => j, Err(err) => { log::error!( target: "bridge", @@ -147,13 +126,7 @@ where } }; - return Some(( - Justification { - target_header_number, - raw_justification: next_justification.0, - }, - subscription, - )); + return Some((justification, subscription)); } }, ) diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index e70fb39d137e1..944da9837ffcb 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -10,6 +10,7 @@ description = "Finality proofs relay" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" +bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.5" headers-relay = { path = "../headers" } log = "0.4.11" diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index a246e4bd954c0..f58774997601a 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -21,6 +21,7 @@ pub use crate::finality_loop::{run, FinalitySyncParams, SourceClient, TargetClient}; +use bp_header_chain::FinalityProof; use std::fmt::Debug; mod finality_loop; @@ -50,9 +51,3 @@ pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { /// Returns true if this header needs to be submitted to target node. fn is_mandatory(&self) -> bool; } - -/// Abstract finality proof that is justifying block finality. -pub trait FinalityProof: Clone + Send + Sync + Debug { - /// Return number of header that this proof is generated for. - fn target_header_number(&self) -> Number; -} From 5b7288fa189182f072b5f8c6bde8cc60b69f5e2f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 1 Apr 2021 12:51:43 -0400 Subject: [PATCH 0401/1210] Weights for `pallet-bridge-grandpa` (#815) * Add benchmarking skeleton * Allow runtime to indicate concrete header type for benches * Set up skeleton for benchmark tests * Play around with mutating bench header * Create a working test for benchmarking * Add benches related to enacting authority set changes * Add bench for checking effect of prec-commits/vote ancestries * Use new `no_std` test utils in benchmarks * Support pallet instances in benchmarking * Use correct benchmarking instance macro * Add instance to runtime benchmark helper impl * Start using new justification creation API * Allow mock header's number to be specified * Set up benches with correct fork/depth parameters * Use new pallet name during runtime bench setup * Use correct `set_id` in tests * Limit number of forks as workaround to get tests passing * Use number of authorities which matches number of forks * Make sure test post-conditions are checked properly * Only read `CurrentAuthoritySet` from storage once * Add combined benchmark for `submit_finality_proof` * Add bench test * Introduce config bounds related to justification verification * Use config consts from pallet in benchmarking * Return data relevant to benchmarks from helper functions * Annotate `submit_finality_proof` with autogenerated weights * Return actual weight after call execution * Ignore Clippy warnings in bench template * Update benchmark template * Use `test-utils` to create test headers * Clarify that helper is only for messages benches * Add more documentation to benches * Update TODOs * Clarify return types in comment * Fix pallet name post-merge * Update NOTE to a TODO item * Indicate that Config params are max values, not actual values * Change Config validator count type to be `u32` * Return decoded justification instead of fields * Add missing trait bounds for tests * Correctly issue weight refund Thanks for spotting this Tomek! * Update comment * Add note about SESSION_LENGTH * Fix benchmarking code --- bin/millau/runtime/src/lib.rs | 16 ++ bin/rialto/runtime/src/lib.rs | 11 +- modules/grandpa/Cargo.toml | 15 +- modules/grandpa/src/benchmarking.rs | 264 +++++++++++++++++++++++++++ modules/grandpa/src/lib.rs | 72 +++++++- modules/grandpa/src/mock.rs | 5 + modules/grandpa/src/weights.rs | 141 ++++++++++++++ primitives/chain-millau/src/lib.rs | 6 +- primitives/chain-rialto/src/lib.rs | 6 +- primitives/chain-westend/src/lib.rs | 7 + primitives/polkadot-core/src/lib.rs | 15 ++ primitives/test-utils/src/keyring.rs | 1 + 12 files changed, 544 insertions(+), 15 deletions(-) create mode 100644 modules/grandpa/src/benchmarking.rs create mode 100644 modules/grandpa/src/weights.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7ac3cc73bfbe2..cdd8b5a87f9ed 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -311,18 +311,34 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; + pub const WestendSessionLength: bp_westend::BlockNumber = bp_westend::SESSION_LENGTH; + pub const RialtoSessionLength: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; + + // TODO [#846]: Right now this will break benchmarking if it is greater than `u8::MAX` + pub const RialtoValidatorCount: u32 = 255; + pub const WestendValidatorCount: u32 = 255; } pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type MaxRequests = MaxRequests; + type MaxBridgedSessionLength = RialtoSessionLength; + type MaxBridgedValidatorCount = RialtoValidatorCount; + + // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. + type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; } pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; type MaxRequests = MaxRequests; + type MaxBridgedSessionLength = WestendSessionLength; + type MaxBridgedValidatorCount = WestendValidatorCount; + + // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. + type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; } impl pallet_shift_session_manager::Config for Runtime {} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index c2c50f05a77a5..a0ccbf27e624b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -417,11 +417,18 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; + pub const MillauSessionLength: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; + + // TODO [#846]: Right now this will break benchmarking if it is greater than `u8::MAX` + pub const MillauValidatorCount: u32 = 255; } impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; + type MaxBridgedSessionLength = MillauSessionLength; + type MaxBridgedValidatorCount = MillauValidatorCount; + type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -799,6 +806,7 @@ impl_runtime_apis! { config: frame_benchmarking::BenchmarkConfig, ) -> Result, sp_runtime::RuntimeString> { use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -945,6 +953,7 @@ impl_runtime_apis! { >( &lane_id, ).0; + let make_millau_header = |state_root| bp_millau::Header::new( 0, Default::default(), @@ -1005,7 +1014,6 @@ impl_runtime_apis! { } } - add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeKovan); add_benchmark!( params, batches, @@ -1018,6 +1026,7 @@ impl_runtime_apis! { pallet_bridge_messages, MessagesBench:: ); + add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeMillauGrandpa); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 4b35905ecb7c1..1191c8c8fcf49 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } finality-grandpa = { version = "0.14.0", default-features = false } log = { version = "0.4.14", default-features = false } +num-traits = { version = "0.2", default-features = false } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -27,25 +28,33 @@ sp-runtime = { 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 } +# Optional Benchmarking Dependencies +bp-test-utils = { path = "../../primitives/test-utils", default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } + [dev-dependencies] -bp-test-utils = {path = "../../primitives/test-utils" } pallet-substrate-bridge = { path = "../../modules/substrate" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] std = [ - "bp-runtime/std", "bp-header-chain/std", + "bp-runtime/std", + "bp-test-utils/std", "codec/std", "finality-grandpa/std", "frame-support/std", "frame-system/std", "log/std", + "num-traits/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", ] -runtime-benchmarks = [] +runtime-benchmarks = [ + "bp-test-utils", + "frame-benchmarking", +] diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs new file mode 100644 index 0000000000000..089e7f88e7765 --- /dev/null +++ b/modules/grandpa/src/benchmarking.rs @@ -0,0 +1,264 @@ +// 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 . + +//! Benchmarks for the GRANDPA Pallet. +//! +//! The main dispatchable for the GRANDPA pallet is `submit_finality_proof`, so these benchmarks are +//! based around that. There are to main factors which affect finality proof verification: +//! +//! 1. The number of `votes-ancestries` in the justification +//! 2. The number of `pre-commits` in the justification +//! +//! Vote ancestries are the headers between (`finality_target`, `head_of_chain`], where +//! `header_of_chain` is a decendant of `finality_target`. +//! +//! Pre-commits are messages which are signed by validators at the head of the chain they think is +//! the best. +//! +//! Consider the following: +//! +//! / [B'] <- [C'] +//! [A] <- [B] <- [C] +//! +//! The common ancestor of both forks is block A, so this is what GRANDPA will finalize. In order to +//! verify this we will have vote ancestries of [B, C, B', C'] and pre-commits [C, C']. +//! +//! Note that the worst case scenario here would be a justification where each validator has it's +//! own fork which is `SESSION_LENGTH` blocks long. +//! +//! As far as benchmarking results go, the only benchmark that should be used in +//! `pallet-bridge-grandpa` to annotate weights is the `submit_finality_proof` one. The others are +//! looking at the effects of specific code paths and do not actually reflect the overall worst case +//! scenario. + +use crate::*; + +use bp_test_utils::{ + accounts, authority_list, make_justification_for_header, test_keyring, JustificationGeneratorParams, ALICE, + TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, +}; +use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; +use frame_support::traits::Get; +use frame_system::RawOrigin; +use num_traits::cast::AsPrimitive; +use sp_finality_grandpa::AuthorityId; +use sp_runtime::traits::{One, Zero}; +use sp_std::{vec, vec::Vec}; + +benchmarks_instance_pallet! { + // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to + // annotate the weight in the pallet. + // + // The other benchmarks related to `submit_finality_proof` are looking at the effect of specific + // parameters and are there mostly for seeing how specific codepaths behave. + submit_finality_proof { + let s in 1..T::MaxBridgedSessionLength::get().as_() as u32; + let p in 1..T::MaxBridgedValidatorCount::get(); + + let caller: T::AccountId = whitelisted_caller(); + + let authority_list = accounts(p as u8) + .iter() + .map(|id| (AuthorityId::from(*id), 1)) + .collect::>(); + + let init_data = InitializationData { + header: bp_test_utils::test_header(Zero::zero()), + authority_list, + set_id: TEST_GRANDPA_SET_ID, + is_halted: false, + }; + + initialize_bridge::(init_data); + let header: BridgedHeader = bp_test_utils::test_header(One::one()); + + let params = JustificationGeneratorParams { + header: header.clone(), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: accounts(p as u8).iter().map(|k| (*k, 1)).collect::>(), + depth: s, + forks: p, + }; + + let justification = make_justification_for_header(params); + + }: _(RawOrigin::Signed(caller), header, justification) + verify { + let header: BridgedHeader = bp_test_utils::test_header(One::one()); + let expected_hash = header.hash(); + + assert_eq!(>::get(), expected_hash); + assert!(>::contains_key(expected_hash)); + } + + // What we want to check here is the effect of vote ancestries on justification verification + // do this by varying the number of headers between `finality_target` and `header_of_chain`. + submit_finality_proof_on_single_fork { + let s in 1..T::MaxBridgedSessionLength::get().as_() as u32; + + let caller: T::AccountId = whitelisted_caller(); + + let init_data = InitializationData { + header: bp_test_utils::test_header(Zero::zero()), + authority_list: authority_list(), + set_id: TEST_GRANDPA_SET_ID, + is_halted: false, + }; + + initialize_bridge::(init_data); + let header: BridgedHeader = bp_test_utils::test_header(One::one()); + + let params = JustificationGeneratorParams { + header: header.clone(), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: test_keyring(), + depth: s, + forks: 1, + }; + + let justification = make_justification_for_header(params); + + }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) + verify { + let header: BridgedHeader = bp_test_utils::test_header(One::one()); + let expected_hash = header.hash(); + + assert_eq!(>::get(), expected_hash); + assert!(>::contains_key(expected_hash)); + } + + // What we want to check here is the effect of many pre-commits on justification verification. + // We do this by creating many forks, whose head will be used as a signed pre-commit in the + // final justification. + submit_finality_proof_on_many_forks { + let p in 1..T::MaxBridgedValidatorCount::get(); + + let caller: T::AccountId = whitelisted_caller(); + + let authority_list = accounts(p as u8) + .iter() + .map(|id| (AuthorityId::from(*id), 1)) + .collect::>(); + + let init_data = InitializationData { + header: bp_test_utils::test_header(Zero::zero()), + authority_list, + set_id: TEST_GRANDPA_SET_ID, + is_halted: false, + }; + + initialize_bridge::(init_data); + let header: BridgedHeader = bp_test_utils::test_header(One::one()); + + let params = JustificationGeneratorParams { + header: header.clone(), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: accounts(p as u8).iter().map(|k| (*k, 1)).collect::>(), + depth: 2, + forks: p, + }; + + let justification = make_justification_for_header(params); + + }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) + verify { + let header: BridgedHeader = bp_test_utils::test_header(One::one()); + let expected_hash = header.hash(); + + assert_eq!(>::get(), expected_hash); + assert!(>::contains_key(expected_hash)); + } + + // Here we want to find out the overheaded of looking through consensus digests found in a + // header. As the number of logs in a header grows, how much more work do we require to look + // through them? + // + // Note that this should be the same for looking through scheduled changes and forces changes, + // which is why we only have one benchmark for this. + find_scheduled_change { + // Not really sure what a good bound for this is. + let n in 1..1000; + + let mut logs = vec![]; + for i in 0..n { + // We chose a non-consensus log on purpose since that way we have to look through all + // the logs in the header + logs.push(sp_runtime::DigestItem::Other(vec![])); + } + + let mut header: BridgedHeader = bp_test_utils::test_header(Zero::zero()); + let digest = header.digest_mut(); + *digest = sp_runtime::Digest { + logs, + }; + + }: { + crate::find_scheduled_change(&header) + } + + // What we want to check here is how long it takes to read and write the authority set tracked + // by the pallet as the number of authorities grows. + read_write_authority_sets { + // The current max target number of validators on Polkadot/Kusama + let n in 1..1000; + + let mut authorities = vec![]; + for i in 0..n { + authorities.push((ALICE, 1)); + } + + let authority_set = bp_header_chain::AuthoritySet { + authorities: authorities.iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect(), + set_id: 0 + }; + + >::put(&authority_set); + + }: { + let authority_set = >::get(); + >::put(&authority_set); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::assert_ok; + + #[test] + fn finality_proof_is_valid() { + mock::run_test(|| { + assert_ok!(test_benchmark_submit_finality_proof::()); + }); + } + + #[test] + fn single_fork_finality_proof_is_valid() { + mock::run_test(|| { + assert_ok!(test_benchmark_submit_finality_proof_on_single_fork::()); + }); + } + + #[test] + fn multi_fork_finality_proof_is_valid() { + mock::run_test(|| { + assert_ok!(test_benchmark_submit_finality_proof_on_many_forks::()); + }); + } +} diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index acf9b7e736010..2721507d47fa8 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -36,12 +36,15 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] +use crate::weights::WeightInfo; + use bp_header_chain::justification::GrandpaJustification; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::ensure; use frame_system::{ensure_signed, RawOrigin}; +use num_traits::cast::AsPrimitive; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -51,6 +54,12 @@ use sp_runtime::RuntimeDebug; #[cfg(test)] mod mock; +/// Module containing weights for this pallet. +pub mod weights; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + // Re-export in crate namespace for `construct_runtime!` pub use pallet::*; @@ -82,6 +91,30 @@ pub mod pallet { /// until the request count has decreased. #[pallet::constant] type MaxRequests: Get; + + /// The maximum length of a session on the bridged chain. + /// + /// The pallet uses this to bound justification verification since justifications contain + /// ancestry proofs whose size is capped at `MaxBridgedSessionLength`. + #[pallet::constant] + type MaxBridgedSessionLength: Get>; + + /// The number of validators on the bridged chain. + /// + /// The pallet uses this to bound justification verification since justifications may + /// contain up to `MaxBridgedValidatorCount` number of signed `pre-commit` messages which + /// need to be verified. + /// + /// Note that `MaxBridgedValidatorCount` should *not* match the exact number of validators + /// on the bridged chain. Instead it should be a number which is greater than the actual + /// number of validators in order to provide some buffer room should the validator set + /// increase in size. If this number ends up being lower than the actual number of + /// validators on the bridged chain you risk stalling the bridge. + #[pallet::constant] + type MaxBridgedValidatorCount: Get; + + /// Weights gathered through benchmarking. + type WeightInfo: WeightInfo; } #[pallet::pallet] @@ -107,7 +140,10 @@ pub mod pallet { /// /// If successful in verification, it will write the target header to the underlying storage /// pallet. - #[pallet::weight(0)] + #[pallet::weight(T::WeightInfo::submit_finality_proof( + T::MaxBridgedSessionLength::get().as_() as u32, + T::MaxBridgedValidatorCount::get(), + ))] pub fn submit_finality_proof( origin: OriginFor, finality_target: BridgedHeader, @@ -134,16 +170,26 @@ pub mod pallet { // "travelling back in time" (which could be indicative of something bad, e.g a hard-fork). ensure!(best_finalized.number() < number, >::OldHeader); - verify_justification::(&justification, hash, *number)?; + let authority_set = >::get(); + let set_id = authority_set.set_id; + verify_justification::(&justification, hash, *number, authority_set)?; - try_enact_authority_change::(&finality_target)?; + let _enacted = try_enact_authority_change::(&finality_target, set_id)?; >::put(hash); >::insert(hash, finality_target); >::mutate(|count| *count += 1); log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); - Ok(().into()) + // Note that the number of precommits is indicitive of the number of GRANDPA forks being + // voted on. + let precommits = justification.commit.precommits.len(); + + // This represents the average number of votes in a single fork since the weight formula + // uses that metric instead of the aggregated number of vote ancestries. + let votes = (justification.votes_ancestries.len() + precommits - 1) / precommits; + + Ok(Some(T::WeightInfo::submit_finality_proof(votes as u32, precommits as u32)).into()) } /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. @@ -319,9 +365,14 @@ pub mod pallet { /// /// This function does not support forced changes, or scheduled changes with delays /// since these types of changes are indicitive of abnormal behaviour from GRANDPA. + /// + /// Returned value will indicate if a change was enacted or not. pub(crate) fn try_enact_authority_change, I: 'static>( header: &BridgedHeader, - ) -> Result<(), sp_runtime::DispatchError> { + current_set_id: sp_finality_grandpa::SetId, + ) -> Result { + let mut change_enacted = false; + // We don't support forced changes - at that point governance intervention is required. ensure!( super::find_forced_change(header).is_none(), @@ -332,7 +383,6 @@ pub mod pallet { // GRANDPA only includes a `delay` for forced changes, so this isn't valid. ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); - let current_set_id = >::get().set_id; // TODO [#788]: Stop manually increasing the `set_id` here. let next_authorities = bp_header_chain::AuthoritySet { authorities: change.next_authorities, @@ -342,6 +392,7 @@ pub mod pallet { // Since our header schedules a change and we know the delay is 0, it must also enact // the change. >::put(&next_authorities); + change_enacted = true; log::info!( target: "runtime::bridge-grandpa", @@ -352,20 +403,23 @@ pub mod pallet { ); }; - Ok(()) + Ok(change_enacted) } /// Verify a GRANDPA justification (finality proof) for a given header. /// /// Will use the GRANDPA current authorities known to the pallet. + /// + /// If succesful it returns the decoded GRANDPA justification so we can refund any weight which + /// was overcharged in the initial call. pub(crate) fn verify_justification, I: 'static>( justification: &GrandpaJustification>, hash: BridgedBlockHash, number: BridgedBlockNumber, + authority_set: bp_header_chain::AuthoritySet, ) -> Result<(), sp_runtime::DispatchError> { use bp_header_chain::justification::verify_justification; - let authority_set = >::get(); let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; let set_id = authority_set.set_id; @@ -510,7 +564,7 @@ pub(crate) fn find_forced_change( header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) } -/// (Re)initialize bridge with given header for using it in external benchmarks. +/// (Re)initialize bridge with given header for using it in `pallet-bridge-messages` benchmarks. #[cfg(feature = "runtime-benchmarks")] pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader) { initialize_bridge::(InitializationData { diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 8deca8ae85881..1f9857eaf004b 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -80,11 +80,16 @@ impl frame_system::Config for TestRuntime { parameter_types! { pub const MaxRequests: u32 = 2; + pub const SessionLength: u64 = 5; + pub const NumValidators: u32 = 5; } impl grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; + type MaxBridgedSessionLength = SessionLength; + type MaxBridgedValidatorCount = NumValidators; + type WeightInfo = (); } #[derive(Debug)] diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs new file mode 100644 index 0000000000000..dec26d061dd5b --- /dev/null +++ b/modules/grandpa/src/weights.rs @@ -0,0 +1,141 @@ +// Copyright 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 . + +//! Autogenerated weights for pallet_bridge_grandpa +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 +//! DATE: 2021-03-26, STEPS: [50, ], REPEAT: 20 +//! LOW RANGE: [], HIGH RANGE: [] +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled +//! CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// ./target/release/rialto-bridge-node +// benchmark +// --chain +// dev +// --execution +// wasm +// --extrinsic +// * +// --pallet +// pallet_bridge_grandpa +// --wasm-execution +// compiled +// --steps +// 50 +// --repeat +// 20 +// --template +// ./.maintain/rialto-weight-template.hbs +// --output +// ./grandpa-template.txt +// --raw + +#![allow(clippy::all)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_bridge_grandpa. +pub trait WeightInfo { + fn submit_finality_proof(s: u32, p: u32) -> Weight; + fn submit_finality_proof_on_single_fork(s: u32) -> Weight; + fn submit_finality_proof_on_many_forks(p: u32) -> Weight; + fn find_scheduled_change(n: u32) -> Weight; + fn read_write_authority_sets(n: u32) -> Weight; + fn write_authority_sets(n: u32) -> Weight; +} + +/// Weights for pallet_bridge_grandpa using the Rialto node and recommended hardware. +pub struct RialtoWeight(PhantomData); +impl WeightInfo for RialtoWeight { + fn submit_finality_proof(s: u32, p: u32) -> Weight { + (0 as Weight) + .saturating_add((3_248_661_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((776_552_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn submit_finality_proof_on_single_fork(s: u32) -> Weight { + (189_213_000 as Weight) + .saturating_add((12_937_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn submit_finality_proof_on_many_forks(p: u32) -> Weight { + (0 as Weight) + .saturating_add((138_751_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn find_scheduled_change(n: u32) -> Weight { + (301_000 as Weight).saturating_add((10_000 as Weight).saturating_mul(n as Weight)) + } + fn read_write_authority_sets(n: u32) -> Weight { + (6_787_000 as Weight) + .saturating_add((247_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn write_authority_sets(n: u32) -> Weight { + (3_383_000 as Weight) + .saturating_add((99_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn submit_finality_proof(s: u32, p: u32) -> Weight { + (0 as Weight) + .saturating_add((3_248_661_000 as Weight).saturating_mul(s as Weight)) + .saturating_add((776_552_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn submit_finality_proof_on_single_fork(s: u32) -> Weight { + (189_213_000 as Weight) + .saturating_add((12_937_000 as Weight).saturating_mul(s as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn submit_finality_proof_on_many_forks(p: u32) -> Weight { + (0 as Weight) + .saturating_add((138_751_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn find_scheduled_change(n: u32) -> Weight { + (301_000 as Weight).saturating_add((10_000 as Weight).saturating_mul(n as Weight)) + } + fn read_write_authority_sets(n: u32) -> Weight { + (6_787_000 as Weight) + .saturating_add((247_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + fn write_authority_sets(n: u32) -> Weight { + (3_383_000 as Weight) + .saturating_add((99_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } +} diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index a8fa00af3f036..28ad3a38818e1 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -95,7 +95,11 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; -/// The length of a session (how often authorities change) on Millau measured in of number of blocks. +/// The target length of a session (how often authorities change) on Millau measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; /// Re-export `time_units` to make usage easier. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index b373bbe9a00cd..f85e239fbe14c 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -86,7 +86,11 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; -/// The length of a session (how often authorities change) on Rialto measured in of number of blocks. +/// The target length of a session (how often authorities change) on Rialto measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. pub const SESSION_LENGTH: BlockNumber = 4; /// Re-export `time_units` to make usage easier. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 0587e76125327..c4f4b0b644a36 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -69,6 +69,13 @@ pub const FROM_WESTEND_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWestendInbound /// Name of the `FromWestendInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_WESTEND_UNREWARDED_RELAYERS_STATE: &str = "FromWestendInboundLaneApi_unrewarded_relayers_state"; +/// The target length of a session (how often authorities change) on Westend measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. +pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Westend headers. /// diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index eaeddfa2afee3..94e9dda903509 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -136,6 +136,21 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; +/// Re-export `time_units` to make usage easier. +pub use time_units::*; + +/// Human readable time units defined in terms of number of blocks. +pub mod time_units { + use super::BlockNumber; + + pub const MILLISECS_PER_BLOCK: u64 = 6000; + pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + + pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); + pub const HOURS: BlockNumber = MINUTES * 60; + pub const DAYS: BlockNumber = HOURS * 24; +} + /// Block number type used in Polkadot-like chains. pub type BlockNumber = u32; diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index 5b96b98a3ad54..fbc1496e16358 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -21,6 +21,7 @@ use finality_grandpa::voter_set::VoterSet; use sp_application_crypto::Public; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; /// Set of test accounts with friendly names. pub const ALICE: Account = Account(0); From cc91335c9be350d8fce6a59a4a5ed750e6828b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 2 Apr 2021 21:24:01 +0200 Subject: [PATCH 0402/1210] CLI: Relay Messages (#858) * Relay Messages. * Fix docs. * Fix copyright date. * copyright increment Co-authored-by: adoerr <0xad@gmx.net> --- relays/bin-substrate/src/cli/mod.rs | 20 +--- .../bin-substrate/src/cli/relay_messages.rs | 97 +++++++++++++++++++ relays/bin-substrate/src/rialto_millau/cli.rs | 53 +--------- relays/bin-substrate/src/rialto_millau/mod.rs | 59 +---------- 4 files changed, 103 insertions(+), 126 deletions(-) create mode 100644 relays/bin-substrate/src/cli/relay_messages.rs diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 6418848c29489..5419f82637890 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -27,6 +27,7 @@ use structopt::{clap::arg_enum, StructOpt}; mod init_bridge; mod relay_headers; +mod relay_messages; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -46,7 +47,7 @@ pub enum Command { /// /// Ties up to `Messages` pallets on both chains and starts relaying messages. /// Requires the header relay to be already running. - RelayMessages(RelayMessages), + RelayMessages(relay_messages::RelayMessages), /// Initialize on-chain bridge pallet with current header data. /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. @@ -90,23 +91,6 @@ impl Command { } } -/// Start message relayer process. -#[derive(StructOpt)] -pub enum RelayMessages { - #[structopt(flatten)] - RialtoMillau(rialto_millau::RelayMessages), -} - -impl RelayMessages { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - /// Send bridge message. #[derive(StructOpt)] pub enum SendMessage { diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs new file mode 100644 index 0000000000000..80cb0654a3d69 --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -0,0 +1,97 @@ +// 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 . + +use crate::cli::{ + CliChain, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, + TargetSigningParams, +}; +use structopt::{clap::arg_enum, StructOpt}; + +/// Start messages relayer process. +#[derive(StructOpt)] +pub struct RelayMessages { + /// A bridge instance to relay messages for. + #[structopt(possible_values = &RelayMessagesBridge::variants(), case_insensitive = true)] + bridge: RelayMessagesBridge, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +arg_enum! { + #[derive(Debug)] + /// Headers relay bridge. + pub enum RelayMessagesBridge { + MillauToRialto, + RialtoToMillau, + } +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + RelayMessagesBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + use crate::rialto_millau::millau_messages_to_rialto::run; + + $generic + } + RelayMessagesBridge::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + use crate::rialto_millau::rialto_messages_to_millau::run; + + $generic + } + } + }; +} + +impl RelayMessages { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + let source_client = crate::rialto_millau::source_chain_client::(self.source).await?; + let source_sign = + Source::source_signing_params(self.source_sign).map_err(|e| anyhow::format_err!("{}", e))?; + let target_client = crate::rialto_millau::target_chain_client::(self.target).await?; + let target_sign = + Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?; + + run( + source_client, + source_sign, + target_client, + target_sign, + self.lane.into(), + self.prometheus_params.into(), + ) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + }) + } +} diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs index 1005e85472229..3d314cc71b238 100644 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/relays/bin-substrate/src/rialto_millau/cli.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 @@ -20,57 +20,10 @@ use frame_support::weights::Weight; use structopt::StructOpt; use crate::cli::{ - AccountId, Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, PrometheusParams, SourceConnectionParams, - SourceSigningParams, TargetConnectionParams, TargetSigningParams, + AccountId, Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, + TargetSigningParams, }; -/// Start message relayer process. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum RelayMessages { - /// Serve given lane of Millau -> Rialto messages. - MillauToRialto { - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - }, - /// Serve given lane of Rialto -> Millau messages. - RialtoToMillau { - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - }, -} - -impl RelayMessages { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_relay_messages(self).await.map_err(format_err)?; - Ok(()) - } -} - /// Send bridge message. /// /// TODO [#855] Move to separate module. diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index 7a48119be7ff2..5446e382a7bc2 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 @@ -44,63 +44,6 @@ use sp_runtime::{traits::IdentifyAccount, MultiSigner}; use sp_version::RuntimeVersion; use std::fmt::Debug; -async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> { - match command { - cli::RelayMessages::MillauToRialto { - source, - source_sign, - target, - target_sign, - prometheus_params, - lane, - } => { - type Source = Millau; - type Target = Rialto; - - let source_client = source_chain_client::(source).await?; - let source_sign = Source::source_signing_params(source_sign)?; - let target_client = target_chain_client::(target).await?; - let target_sign = Target::target_signing_params(target_sign)?; - - millau_messages_to_rialto::run( - source_client, - source_sign, - target_client, - target_sign, - lane.into(), - prometheus_params.into(), - ) - .await - } - cli::RelayMessages::RialtoToMillau { - source, - source_sign, - target, - target_sign, - prometheus_params, - lane, - } => { - type Source = Rialto; - type Target = Millau; - - let source_client = source_chain_client::(source).await?; - let source_sign = Source::source_signing_params(source_sign)?; - let target_client = target_chain_client::(target).await?; - let target_sign = Target::target_signing_params(target_sign)?; - - rialto_messages_to_millau::run( - source_client, - source_sign, - target_client, - target_sign, - lane.into(), - prometheus_params.into(), - ) - .await - } - } -} - async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { match command { cli::SendMessage::MillauToRialto { From e92670c13ee0ae502ca016d6d6489127fac69a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 5 Apr 2021 17:58:34 +0200 Subject: [PATCH 0403/1210] CLI: Derive Account (#860) * Move derive account. * Fix account derivation. --- .../bin-substrate/src/cli/derive_account.rs | 135 ++++++++++++++++++ relays/bin-substrate/src/cli/mod.rs | 27 +--- relays/bin-substrate/src/rialto_millau/cli.rs | 24 ---- relays/bin-substrate/src/rialto_millau/mod.rs | 60 +------- 4 files changed, 139 insertions(+), 107 deletions(-) create mode 100644 relays/bin-substrate/src/cli/derive_account.rs diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs new file mode 100644 index 0000000000000..cd40fb5891ae4 --- /dev/null +++ b/relays/bin-substrate/src/cli/derive_account.rs @@ -0,0 +1,135 @@ +// 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 . + +use crate::cli::AccountId; +use relay_substrate_client::Chain; +use structopt::{clap::arg_enum, StructOpt}; + +/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. +/// +/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call +/// that has been sent over the bridge. +/// This account can also be used to receive target-chain funds (or other form of ownership), +/// since messages sent over the bridge will be able to spend these. +#[derive(StructOpt)] +pub struct DeriveAccount { + /// A bridge instance to initalize. + #[structopt(possible_values = &DeriveAccountBridge::variants(), case_insensitive = true)] + bridge: DeriveAccountBridge, + /// Source-chain address to derive Target-chain address from. + account: AccountId, +} + +arg_enum! { + #[derive(Debug)] + /// Bridge to derive account for. + pub enum DeriveAccountBridge { + MillauToRialto, + RialtoToMillau, + } +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + DeriveAccountBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + + #[allow(unused_imports)] // the import is not used in `run` + use bp_millau::derive_account_from_rialto_id as derive_account; + + $generic + } + DeriveAccountBridge::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + + #[allow(unused_imports)] // the import is not used in `run`. + use bp_rialto::derive_account_from_millau_id as derive_account; + + $generic + } + } + }; +} + +impl DeriveAccount { + /// Parse CLI arguments and derive account. + /// + /// Returns both the Source account in correct SS58 format and the derived account. + fn derive_account(&self) -> (AccountId, AccountId) { + select_bridge!(self.bridge, { + let mut account = self.account.clone(); + account.enforce_chain::(); + let acc = bp_runtime::SourceAccount::Account(account.raw_id()); + let id = derive_account(acc); + let derived_account = AccountId::from_raw::(id); + (account, derived_account) + }) + } + + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + let (account, derived_account) = self.derive_account(); + println!("Source address:\n{} ({})", account, Source::NAME); + println!( + "->Corresponding (derived) address:\n{} ({})", + derived_account, + Target::NAME, + ); + + Ok(()) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn derive_account_cli(bridge: &str, account: &str) -> (AccountId, AccountId) { + DeriveAccount::from_iter(vec!["derive-account", bridge, account]).derive_account() + } + + #[test] + fn should_derive_accounts_correctly() { + // given + let rialto = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU"; + let millau = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"; + + // when + let (rialto_parsed, rialto_derived) = derive_account_cli("RialtoToMillau", rialto); + let (millau_parsed, millau_derived) = derive_account_cli("MillauToRialto", millau); + let (millau2_parsed, millau2_derived) = derive_account_cli("MillauToRialto", rialto); + + // then + assert_eq!(format!("{}", rialto_parsed), rialto); + assert_eq!(format!("{}", millau_parsed), millau); + assert_eq!(format!("{}", millau2_parsed), millau); + + assert_eq!( + format!("{}", rialto_derived), + "73gLnUwrAdH4vMjbXCiNEpgyz1PLk9JxCaY4cKzvfSZT73KE" + ); + assert_eq!( + format!("{}", millau_derived), + "5rpTJqGv1BPAYy2sXzkPpc3Wx1ZpQtgfuBsrDpNV4HsXAmbi" + ); + assert_eq!(millau_derived, millau2_derived); + } +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 5419f82637890..3bcc1bf5847ae 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -25,6 +25,7 @@ use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +mod derive_account; mod init_bridge; mod relay_headers; mod relay_messages; @@ -71,7 +72,7 @@ pub enum Command { /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. EstimateFee(EstimateFee), /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. - DeriveAccount(DeriveAccount), + DeriveAccount(derive_account::DeriveAccount), } impl Command { @@ -159,28 +160,6 @@ impl EstimateFee { } } -/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. -/// -/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call -/// that has been sent over the bridge. -/// This account can also be used to receive target-chain funds (or other form of ownership), -/// since messages sent over the bridge will be able to spend these. -#[derive(StructOpt)] -pub enum DeriveAccount { - #[structopt(flatten)] - RialtoMillau(rialto_millau::DeriveAccount), -} - -impl DeriveAccount { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - arg_enum! { #[derive(Debug)] /// The origin to use when dispatching the message on the target chain. @@ -213,7 +192,7 @@ impl Balance { } /// Generic account id with custom parser. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct AccountId { account: sp_runtime::AccountId32, ss58_format: sp_core::crypto::Ss58AddressFormat, diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs index 3d314cc71b238..2f11156537364 100644 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/relays/bin-substrate/src/rialto_millau/cli.rs @@ -176,30 +176,6 @@ impl EstimateFee { } } -/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. -/// -/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call -/// that has been sent over the bridge. -/// This account can also be used to receive target-chain funds (or other form of ownership), -/// since messages sent over the bridge will be able to spend these. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum DeriveAccount { - /// Given Rialto AccountId, display corresponding Millau AccountId. - RialtoToMillau { account: AccountId }, - /// Given Millau AccountId, display corresponding Rialto AccountId. - MillauToRialto { account: AccountId }, -} - -impl DeriveAccount { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_derive_account(self).await.map_err(format_err)?; - Ok(()) - } -} - fn format_err(err: String) -> anyhow::Error { anyhow::anyhow!(err) } diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index 5446e382a7bc2..bcc7821e20d46 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -29,7 +29,7 @@ pub type MillauClient = relay_substrate_client::Client; pub type RialtoClient = relay_substrate_client::Client; use crate::cli::{ - AccountId, CliChain, ExplicitOrMaximal, HexBytes, Origins, SourceConnectionParams, SourceSigningParams, + CliChain, ExplicitOrMaximal, HexBytes, Origins, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use codec::{Decode, Encode}; @@ -337,43 +337,6 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { Ok(()) } -async fn run_derive_account(cmd: cli::DeriveAccount) -> Result<(), String> { - match cmd { - cli::DeriveAccount::RialtoToMillau { mut account } => { - type Source = Rialto; - type Target = Millau; - - account.enforce_chain::(); - let acc = bp_runtime::SourceAccount::Account(account.raw_id()); - let id = bp_millau::derive_account_from_rialto_id(acc); - let derived_account = AccountId::from_raw::(id); - println!("Source address:\n{} ({})", account, Source::NAME); - println!( - "->Corresponding (derived) address:\n{} ({})", - derived_account, - Target::NAME, - ); - } - cli::DeriveAccount::MillauToRialto { mut account } => { - type Source = Millau; - type Target = Rialto; - - account.enforce_chain::(); - let acc = bp_runtime::SourceAccount::Account(account.raw_id()); - let id = bp_rialto::derive_account_from_millau_id(acc); - let derived_account = AccountId::from_raw::(id); - println!("Source address:\n{} ({})", account, Source::NAME); - println!( - "->Corresponding (derived) address:\n{} ({})", - derived_account, - Target::NAME, - ); - } - } - - Ok(()) -} - async fn estimate_message_delivery_and_dispatch_fee( client: &relay_substrate_client::Client, estimate_fee_method: &str, @@ -864,25 +827,4 @@ mod tests { extra_bytes_in_transaction, ); } - - #[test] - fn should_reformat_addresses() { - // given - let mut rialto1: AccountId = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU".parse().unwrap(); - let mut millau1: AccountId = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9".parse().unwrap(); - - // when - rialto1.enforce_chain::(); - millau1.enforce_chain::(); - - // then - assert_eq!( - &format!("{}", rialto1), - "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9" - ); - assert_eq!( - &format!("{}", millau1), - "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU" - ); - } } From f7c6ab87b8558e0d4771552df0e8f7aa66f3e20e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 5 Apr 2021 12:36:29 -0400 Subject: [PATCH 0404/1210] Use Vote Ancestries Directly in Weight Calculations (#862) * Use more accurate weight calculation in declared weight * Remove session length and validator set size config constants * Remove config params from mock * Allow specifying total number of votes-ancestries per justification * Change limits used during benchmarking * Regenerate weights * Use simplified weight annotation * Remove comment * Address leftover TODO * Prevent possible divide by zero errors * Use correct argument order in weight declaration --- bin/millau/runtime/src/lib.rs | 9 --- bin/rialto/runtime/src/lib.rs | 6 -- modules/grandpa/src/benchmarking.rs | 30 ++++++---- modules/grandpa/src/lib.rs | 36 +---------- modules/grandpa/src/mock.rs | 2 - modules/grandpa/src/weights.rs | 59 ++++++++----------- .../header-chain/tests/justification.rs | 23 +++++--- primitives/test-utils/src/lib.rs | 37 +++++++++--- 8 files changed, 90 insertions(+), 112 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index cdd8b5a87f9ed..1a60d16d7daf4 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -311,11 +311,6 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; - pub const WestendSessionLength: bp_westend::BlockNumber = bp_westend::SESSION_LENGTH; - pub const RialtoSessionLength: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; - - // TODO [#846]: Right now this will break benchmarking if it is greater than `u8::MAX` - pub const RialtoValidatorCount: u32 = 255; pub const WestendValidatorCount: u32 = 255; } @@ -323,8 +318,6 @@ pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type MaxRequests = MaxRequests; - type MaxBridgedSessionLength = RialtoSessionLength; - type MaxBridgedValidatorCount = RialtoValidatorCount; // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; @@ -334,8 +327,6 @@ pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; type MaxRequests = MaxRequests; - type MaxBridgedSessionLength = WestendSessionLength; - type MaxBridgedValidatorCount = WestendValidatorCount; // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a0ccbf27e624b..dae683aa82dbf 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -417,17 +417,11 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; - pub const MillauSessionLength: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; - - // TODO [#846]: Right now this will break benchmarking if it is greater than `u8::MAX` - pub const MillauValidatorCount: u32 = 255; } impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; - type MaxBridgedSessionLength = MillauSessionLength; - type MaxBridgedValidatorCount = MillauValidatorCount; type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; } diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 089e7f88e7765..a3abe508d8a88 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -51,13 +51,23 @@ use bp_test_utils::{ TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, }; use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; -use frame_support::traits::Get; use frame_system::RawOrigin; -use num_traits::cast::AsPrimitive; use sp_finality_grandpa::AuthorityId; use sp_runtime::traits::{One, Zero}; use sp_std::{vec, vec::Vec}; +// The maximum number of vote ancestries to include in a justification. +// +// In practice this would be limited by the session length (number of blocks a single authority set +// can produce) of a given chain. +const MAX_VOTE_ANCESTRIES: u32 = 1000; + +// The maximum number of pre-commits to include in a justification. In practice this scales with the +// number of validators. +// +// TODO [#846]: Right now this will break benchmarking if it is greater than `u8::MAX` +const MAX_VALIDATOR_SET_SIZE: u32 = 255; + benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to // annotate the weight in the pallet. @@ -65,8 +75,8 @@ benchmarks_instance_pallet! { // The other benchmarks related to `submit_finality_proof` are looking at the effect of specific // parameters and are there mostly for seeing how specific codepaths behave. submit_finality_proof { - let s in 1..T::MaxBridgedSessionLength::get().as_() as u32; - let p in 1..T::MaxBridgedValidatorCount::get(); + let v in 1..MAX_VOTE_ANCESTRIES; + let p in 1..MAX_VALIDATOR_SET_SIZE; let caller: T::AccountId = whitelisted_caller(); @@ -90,8 +100,8 @@ benchmarks_instance_pallet! { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: accounts(p as u8).iter().map(|k| (*k, 1)).collect::>(), - depth: s, - forks: p, + votes: v, + forks: 1, }; let justification = make_justification_for_header(params); @@ -108,7 +118,7 @@ benchmarks_instance_pallet! { // What we want to check here is the effect of vote ancestries on justification verification // do this by varying the number of headers between `finality_target` and `header_of_chain`. submit_finality_proof_on_single_fork { - let s in 1..T::MaxBridgedSessionLength::get().as_() as u32; + let v in 1..MAX_VOTE_ANCESTRIES; let caller: T::AccountId = whitelisted_caller(); @@ -127,7 +137,7 @@ benchmarks_instance_pallet! { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: test_keyring(), - depth: s, + votes: v, forks: 1, }; @@ -146,7 +156,7 @@ benchmarks_instance_pallet! { // We do this by creating many forks, whose head will be used as a signed pre-commit in the // final justification. submit_finality_proof_on_many_forks { - let p in 1..T::MaxBridgedValidatorCount::get(); + let p in 1..MAX_VALIDATOR_SET_SIZE; let caller: T::AccountId = whitelisted_caller(); @@ -170,7 +180,7 @@ benchmarks_instance_pallet! { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: accounts(p as u8).iter().map(|k| (*k, 1)).collect::>(), - depth: 2, + votes: p, forks: p, }; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 2721507d47fa8..9f7ca8231c0c4 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -44,7 +44,6 @@ use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::ensure; use frame_system::{ensure_signed, RawOrigin}; -use num_traits::cast::AsPrimitive; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -92,27 +91,6 @@ pub mod pallet { #[pallet::constant] type MaxRequests: Get; - /// The maximum length of a session on the bridged chain. - /// - /// The pallet uses this to bound justification verification since justifications contain - /// ancestry proofs whose size is capped at `MaxBridgedSessionLength`. - #[pallet::constant] - type MaxBridgedSessionLength: Get>; - - /// The number of validators on the bridged chain. - /// - /// The pallet uses this to bound justification verification since justifications may - /// contain up to `MaxBridgedValidatorCount` number of signed `pre-commit` messages which - /// need to be verified. - /// - /// Note that `MaxBridgedValidatorCount` should *not* match the exact number of validators - /// on the bridged chain. Instead it should be a number which is greater than the actual - /// number of validators in order to provide some buffer room should the validator set - /// increase in size. If this number ends up being lower than the actual number of - /// validators on the bridged chain you risk stalling the bridge. - #[pallet::constant] - type MaxBridgedValidatorCount: Get; - /// Weights gathered through benchmarking. type WeightInfo: WeightInfo; } @@ -141,8 +119,8 @@ pub mod pallet { /// If successful in verification, it will write the target header to the underlying storage /// pallet. #[pallet::weight(T::WeightInfo::submit_finality_proof( - T::MaxBridgedSessionLength::get().as_() as u32, - T::MaxBridgedValidatorCount::get(), + justification.votes_ancestries.len() as u32, + justification.commit.precommits.len() as u32, ))] pub fn submit_finality_proof( origin: OriginFor, @@ -181,15 +159,7 @@ pub mod pallet { log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); - // Note that the number of precommits is indicitive of the number of GRANDPA forks being - // voted on. - let precommits = justification.commit.precommits.len(); - - // This represents the average number of votes in a single fork since the weight formula - // uses that metric instead of the aggregated number of vote ancestries. - let votes = (justification.votes_ancestries.len() + precommits - 1) / precommits; - - Ok(Some(T::WeightInfo::submit_finality_proof(votes as u32, precommits as u32)).into()) + Ok(().into()) } /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 1f9857eaf004b..9646ebc552a61 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -87,8 +87,6 @@ parameter_types! { impl grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; - type MaxBridgedSessionLength = SessionLength; - type MaxBridgedValidatorCount = NumValidators; type WeightInfo = (); } diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index dec26d061dd5b..57dba9a6846a1 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// 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 @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-03-26, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-04-02, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -57,85 +57,74 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_bridge_grandpa. pub trait WeightInfo { - fn submit_finality_proof(s: u32, p: u32) -> Weight; - fn submit_finality_proof_on_single_fork(s: u32) -> Weight; + fn submit_finality_proof(v: u32, p: u32) -> Weight; + fn submit_finality_proof_on_single_fork(v: u32) -> Weight; fn submit_finality_proof_on_many_forks(p: u32) -> Weight; fn find_scheduled_change(n: u32) -> Weight; fn read_write_authority_sets(n: u32) -> Weight; - fn write_authority_sets(n: u32) -> Weight; } /// Weights for pallet_bridge_grandpa using the Rialto node and recommended hardware. pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { - fn submit_finality_proof(s: u32, p: u32) -> Weight { + fn submit_finality_proof(v: u32, p: u32) -> Weight { (0 as Weight) - .saturating_add((3_248_661_000 as Weight).saturating_mul(s as Weight)) - .saturating_add((776_552_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((160_060_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((640_223_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } - fn submit_finality_proof_on_single_fork(s: u32) -> Weight { - (189_213_000 as Weight) - .saturating_add((12_937_000 as Weight).saturating_mul(s as Weight)) + fn submit_finality_proof_on_single_fork(v: u32) -> Weight { + (189_597_000 as Weight) + .saturating_add((11_680_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn submit_finality_proof_on_many_forks(p: u32) -> Weight { (0 as Weight) - .saturating_add((138_751_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((130_061_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn find_scheduled_change(n: u32) -> Weight { - (301_000 as Weight).saturating_add((10_000 as Weight).saturating_mul(n as Weight)) + (502_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) } fn read_write_authority_sets(n: u32) -> Weight { - (6_787_000 as Weight) - .saturating_add((247_000 as Weight).saturating_mul(n as Weight)) + (7_677_000 as Weight) + .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } - fn write_authority_sets(n: u32) -> Weight { - (3_383_000 as Weight) - .saturating_add((99_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } } // For backwards compatibility and tests impl WeightInfo for () { - fn submit_finality_proof(s: u32, p: u32) -> Weight { + fn submit_finality_proof(v: u32, p: u32) -> Weight { (0 as Weight) - .saturating_add((3_248_661_000 as Weight).saturating_mul(s as Weight)) - .saturating_add((776_552_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((160_060_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((640_223_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } - fn submit_finality_proof_on_single_fork(s: u32) -> Weight { - (189_213_000 as Weight) - .saturating_add((12_937_000 as Weight).saturating_mul(s as Weight)) + fn submit_finality_proof_on_single_fork(v: u32) -> Weight { + (189_597_000 as Weight) + .saturating_add((11_680_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn submit_finality_proof_on_many_forks(p: u32) -> Weight { (0 as Weight) - .saturating_add((138_751_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((130_061_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn find_scheduled_change(n: u32) -> Weight { - (301_000 as Weight).saturating_add((10_000 as Weight).saturating_mul(n as Weight)) + (502_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) } fn read_write_authority_sets(n: u32) -> Weight { - (6_787_000 as Weight) - .saturating_add((247_000 as Weight).saturating_mul(n as Weight)) + (7_677_000 as Weight) + .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } - fn write_authority_sets(n: u32) -> Weight { - (3_383_000 as Weight) - .saturating_add((99_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } } diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 96bb6d442a77c..e17b24ed815bd 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -23,24 +23,29 @@ type TestHeader = sp_runtime::testing::Header; #[test] fn valid_justification_accepted() { + let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)]; let params = JustificationGeneratorParams { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)], - depth: 5, - forks: 5, + authorities: authorities.clone(), + votes: 7, + forks: 3, }; + let justification = make_justification_for_header::(params.clone()); assert_eq!( verify_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - &make_justification_for_header::(params) + &justification, ), Ok(()), ); + + assert_eq!(justification.commit.precommits.len(), authorities.len()); + assert_eq!(justification.votes_ancestries.len(), params.votes as usize); } #[test] @@ -50,7 +55,7 @@ fn valid_justification_accepted_with_single_fork() { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)], - depth: 5, + votes: 5, forks: 1, }; @@ -78,7 +83,7 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: authorities.clone(), - depth: 5, + votes: n.into(), forks: n.into(), }; @@ -163,12 +168,14 @@ fn justification_with_invalid_precommit_ancestry() { #[test] fn justification_is_invalid_if_we_dont_meet_threshold() { // Need at least three authorities to sign off or else the voter set threshold can't be reached + let authorities = vec![(ALICE, 1), (BOB, 1)]; + let params = JustificationGeneratorParams { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(ALICE, 1), (BOB, 1)], - depth: 2, + authorities: authorities.clone(), + votes: 2 * authorities.len() as u32, forks: 2, }; diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index f6c2f6d094967..39652fc83aebe 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -34,6 +34,7 @@ pub const TEST_GRANDPA_ROUND: u64 = 1; pub const TEST_GRANDPA_SET_ID: SetId = 1; /// Configuration parameters when generating test GRANDPA justifications. +#[derive(Clone)] pub struct JustificationGeneratorParams { /// The header which we want to finalize. pub header: H, @@ -42,10 +43,16 @@ pub struct JustificationGeneratorParams { /// The current authority set ID. pub set_id: SetId, /// The current GRANDPA authority set. + /// + /// The size of the set will determine the number of pre-commits in our justification. pub authorities: Vec<(Account, AuthorityWeight)>, - /// The number of headers included in our justification's vote ancestries. - pub depth: u32, - /// The number of forks, and thus the number of pre-commits in our justification. + /// The total number of vote ancestries in our justification. + /// + /// These may be distributed among many different forks. + pub votes: u32, + /// The number of forks. + /// + /// Useful for creating a "worst-case" scenario in which each authority is on its own fork. pub forks: u32, } @@ -56,7 +63,7 @@ impl Default for JustificationGeneratorParams { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: test_keyring(), - depth: 2, + votes: 2, forks: 1, } } @@ -76,8 +83,8 @@ pub fn make_default_justification(header: &H) -> GrandpaJustificatio /// and vote ancestries which are included in the justification. /// /// This is useful for benchmarkings where we want to generate valid justifications with -/// a specific number of pre-commits (tuned with the "forks" parameter) and/or a specific -/// number of vote ancestries (tuned with the "depth" parameter). +/// a specific number of pre-commits (tuned with the number of "authorities") and/or a specific +/// number of vote ancestries (tuned with the "votes" parameter). /// /// Note: This needs at least three authorities or else the verifier will complain about /// being given an invalid commit. @@ -87,7 +94,7 @@ pub fn make_justification_for_header(params: JustificationGeneratorP round, set_id, authorities, - depth, + mut votes, forks, } = params; @@ -95,15 +102,27 @@ pub fn make_justification_for_header(params: JustificationGeneratorP let mut precommits = vec![]; let mut votes_ancestries = vec![]; - assert!(depth != 0, "Can't have a chain of zero length."); + assert!(forks != 0, "Need at least one fork to have a chain.."); + assert!(votes >= forks, "Need at least one header per fork."); assert!( forks as usize <= authorities.len(), "If we have more forks than authorities we can't create valid pre-commits for all the forks." ); + // Roughly, how many vote ancestries do we want per fork + let target_depth = (votes + forks - 1) / forks; + let mut unsigned_precommits = vec![]; for i in 0..forks { - let chain = generate_chain(i as u8, depth, &header); + let depth = if votes >= target_depth { + votes -= target_depth; + target_depth + } else { + votes + }; + + // Note: Adding 1 to account for the target header + let chain = generate_chain(i as u8, depth + 1, &header); // We don't include our finality target header in the vote ancestries for child in &chain[1..] { From 09c3a1d26a98217b4ee8985dd935eb9f8b8cc903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 5 Apr 2021 18:59:06 +0200 Subject: [PATCH 0405/1210] De-duplicate signing/connection params. (#861) Co-authored-by: Hernando Castano --- relays/bin-substrate/src/cli/init_bridge.rs | 9 ++- relays/bin-substrate/src/cli/mod.rs | 42 ++++++++------ relays/bin-substrate/src/cli/relay_headers.rs | 9 ++- .../bin-substrate/src/cli/relay_messages.rs | 12 ++-- relays/bin-substrate/src/rialto_millau/mod.rs | 55 ++++--------------- 5 files changed, 51 insertions(+), 76 deletions(-) diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index ac2b8c7a705b8..4a073cfa1ddc5 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{CliChain, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use crate::cli::{SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; use bp_runtime::Chain as ChainBase; use codec::Encode; use pallet_bridge_grandpa::InitializationData; @@ -108,10 +108,9 @@ impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = crate::rialto_millau::source_chain_client::(self.source).await?; - let target_client = crate::rialto_millau::target_chain_client::(self.target).await?; - let target_sign = - Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?; + let source_client = self.source.into_client::().await?; + let target_client = self.target.into_client::().await?; + let target_sign = self.target_sign.into_keypair::()?; crate::headers_initialize::initialize( source_client, diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 3bcc1bf5847ae..f3f7dfefd9fe3 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -281,20 +281,6 @@ pub trait CliChain: relay_substrate_client::Chain { /// Maximal extrinsic weight (from the runtime). fn max_extrinsic_weight() -> Weight; - - /// Convert CLI signing parameters of `Source` chain into a `KeyPair` instance. - fn source_signing_params(params: SourceSigningParams) -> Result { - use sp_core::crypto::Pair; - Self::KeyPair::from_string(¶ms.source_signer, params.source_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse source-signer: {:?}", e)) - } - - /// Convert CLI signing parameters of `Target` chain into a `KeyPair` instance. - fn target_signing_params(params: TargetSigningParams) -> Result { - use sp_core::crypto::Pair; - Self::KeyPair::from_string(¶ms.target_signer, params.target_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse target-signer: {:?}", e)) - } } /// Lane id. @@ -425,12 +411,36 @@ macro_rules! declare_chain_options { #[structopt(long)] pub [<$chain_prefix _signer_password>]: Option, } + + impl [<$chain SigningParams>] { + /// Parse signing params into chain-specific KeyPair. + pub fn into_keypair(self) -> anyhow::Result { + use sp_core::crypto::Pair; + Chain::KeyPair::from_string( + &self.[<$chain_prefix _signer>], + self.[<$chain_prefix _signer_password>].as_deref() + ).map_err(|e| anyhow::format_err!("{:?}", e)) + } + } + + impl [<$chain ConnectionParams>] { + /// Convert connection params into Substrate client. + pub async fn into_client( + self, + ) -> anyhow::Result> { + Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { + host: self.[<$chain_prefix _host>], + port: self.[<$chain_prefix _port>], + secure: self.[<$chain_prefix _secure>], + }) + .await? + ) + } + } } }; } -// TODO [#852] Use structop renames instead of different fields. -// TODO [#852] Add Into? declare_chain_options!(Source, source); declare_chain_options!(Target, target); diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 6e903325764a6..6c2b2f1d66d8a 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{CliChain, PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; use structopt::{clap::arg_enum, StructOpt}; /// Start headers relayer process. @@ -74,10 +74,9 @@ impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = crate::rialto_millau::source_chain_client::(self.source).await?; - let target_client = crate::rialto_millau::target_chain_client::(self.target).await?; - let target_sign = - Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?; + let source_client = self.source.into_client::().await?; + let target_client = self.target.into_client::().await?; + let target_sign = self.target_sign.into_keypair::()?; crate::finality_pipeline::run( Finality::new(target_client.clone(), target_sign), diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 80cb0654a3d69..72a194ef90302 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ - CliChain, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, + HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use structopt::{clap::arg_enum, StructOpt}; @@ -75,12 +75,10 @@ impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = crate::rialto_millau::source_chain_client::(self.source).await?; - let source_sign = - Source::source_signing_params(self.source_sign).map_err(|e| anyhow::format_err!("{}", e))?; - let target_client = crate::rialto_millau::target_chain_client::(self.target).await?; - let target_sign = - Target::target_signing_params(self.target_sign).map_err(|e| anyhow::format_err!("{}", e))?; + let source_client = self.source.into_client::().await?; + let source_sign = self.source_sign.into_keypair::()?; + let target_client = self.target.into_client::().await?; + let target_sign = self.target_sign.into_keypair::()?; run( source_client, diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index bcc7821e20d46..f039aadef54dd 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -28,16 +28,13 @@ pub type MillauClient = relay_substrate_client::Client; /// Rialto node client. pub type RialtoClient = relay_substrate_client::Client; -use crate::cli::{ - CliChain, ExplicitOrMaximal, HexBytes, Origins, SourceConnectionParams, SourceSigningParams, - TargetConnectionParams, TargetSigningParams, -}; +use crate::cli::{CliChain, ExplicitOrMaximal, HexBytes, Origins}; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::{Chain, ConnectionParams, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_westend_client::Westend; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, MultiSigner}; @@ -75,9 +72,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { )) }; - let source_client = source_chain_client::(source).await?; - let source_sign = Source::source_signing_params(source_sign)?; - let target_sign = Target::target_signing_params(target_sign)?; + let source_client = source.into_client::().await.map_err(format_err)?; + let source_sign = source_sign.into_keypair::().map_err(format_err)?; + let target_sign = target_sign.into_keypair::().map_err(format_err)?; let target_call = Target::encode_call(message)?; let payload = { @@ -181,9 +178,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { )) }; - let source_client = source_chain_client::(source).await?; - let source_sign = Source::source_signing_params(source_sign)?; - let target_sign = Target::target_signing_params(target_sign)?; + let source_client = source.into_client::().await.map_err(format_err)?; + let source_sign = source_sign.into_keypair::().map_err(format_err)?; + let target_sign = target_sign.into_keypair::().map_err(format_err)?; let target_call = Target::encode_call(message)?; let payload = { @@ -306,7 +303,7 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; - let source_client = source_chain_client::(source).await?; + let source_client = source.into_client::().await.map_err(format_err)?; let lane = lane.into(); let payload = Source::encode_message(payload)?; @@ -322,7 +319,7 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; - let source_client = source_chain_client::(source).await?; + let source_client = source.into_client::().await.map_err(format_err)?; let lane = lane.into(); let payload = Source::encode_message(payload)?; @@ -601,16 +598,6 @@ impl CliChain for Rialto { } } } - - fn source_signing_params(params: SourceSigningParams) -> Result { - Self::KeyPair::from_string(¶ms.source_signer, params.source_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse source-signer: {:?}", e)) - } - - fn target_signing_params(params: TargetSigningParams) -> Result { - Self::KeyPair::from_string(¶ms.target_signer, params.target_signer_password.as_deref()) - .map_err(|e| format!("Failed to parse target-signer: {:?}", e)) - } } impl CliChain for Westend { @@ -636,26 +623,8 @@ impl CliChain for Westend { } } -pub async fn source_chain_client( - params: SourceConnectionParams, -) -> relay_substrate_client::Result> { - relay_substrate_client::Client::new(ConnectionParams { - host: params.source_host, - port: params.source_port, - secure: params.source_secure, - }) - .await -} - -pub async fn target_chain_client( - params: TargetConnectionParams, -) -> relay_substrate_client::Result> { - relay_substrate_client::Client::new(ConnectionParams { - host: params.target_host, - port: params.target_port, - secure: params.target_secure, - }) - .await +fn format_err(e: anyhow::Error) -> String { + e.to_string() } #[cfg(test)] From c4c38d13a51777f67533993cc20edbee70b78e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 5 Apr 2021 19:48:47 +0200 Subject: [PATCH 0406/1210] CLI: Encode Call & Multiple Bridge Instances. (#859) * Encode Call & Multiple Bridge Instances. * Remove redundant clone. * Fix comment. * Rename pallet index bridge instance index. * Update error messages related to target instances Co-authored-by: Hernando Castano --- relays/bin-substrate/src/cli/encode_call.rs | 249 ++++++++++++++++++ relays/bin-substrate/src/cli/mod.rs | 47 ++-- relays/bin-substrate/src/rialto_millau/cli.rs | 72 +---- relays/bin-substrate/src/rialto_millau/mod.rs | 235 +++++++---------- 4 files changed, 367 insertions(+), 236 deletions(-) create mode 100644 relays/bin-substrate/src/cli/encode_call.rs diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs new file mode 100644 index 0000000000000..3afe8d43b9429 --- /dev/null +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -0,0 +1,249 @@ +// 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 . + +use crate::cli::{AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId}; +use frame_support::dispatch::GetDispatchInfo; +use relay_substrate_client::Chain; +use structopt::{clap::arg_enum, StructOpt}; + +/// Encode source chain runtime call. +#[derive(StructOpt)] +pub struct EncodeCall { + /// A bridge instance to encode call for. + #[structopt(possible_values = &EncodeCallBridge::variants(), case_insensitive = true)] + bridge: EncodeCallBridge, + #[structopt(flatten)] + call: Call, +} + +/// All possible messages that may be delivered to generic Substrate chain. +/// +/// Note this enum may be used in the context of both Source (as part of `encode-call`) +/// and Target chain (as part of `encode-message/send-message`). +#[derive(StructOpt, Debug)] +pub enum Call { + /// Raw bytes for the message + Raw { + /// Raw, SCALE-encoded message + data: HexBytes, + }, + /// Make an on-chain remark (comment). + Remark { + /// Explicit remark payload. + #[structopt(long, conflicts_with("remark_size"))] + remark_payload: HexBytes, + /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. + #[structopt(long, conflicts_with("remark_payload"))] + remark_size: Option>, + }, + /// Transfer the specified `amount` of native tokens to a particular `recipient`. + Transfer { + /// Address of an account to receive the transfer. + #[structopt(long)] + recipient: AccountId, + /// Amount of target tokens to send in target chain base currency units. + #[structopt(long)] + amount: Balance, + }, + /// A call to the specific Bridge Messages pallet to queue message to be sent over a bridge. + BridgeSendMessage { + /// An index of the bridge instance which represents the expected target chain. + #[structopt(skip = 255)] + bridge_instance_index: u8, + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Raw SCALE-encoded Message Payload to submit to the messages pallet. + /// + /// This can be obtained by encoding call for the target chain. + #[structopt(long)] + payload: HexBytes, + /// Declared delivery and dispatch fee in base source-chain currency units. + #[structopt(long)] + fee: Balance, + }, +} + +pub trait CliEncodeCall: Chain { + /// Maximal size (in bytes) of any extrinsic (from the runtime). + fn max_extrinsic_size() -> u32; + + /// Encode a CLI call. + fn encode_call(call: &Call) -> anyhow::Result; +} + +arg_enum! { + #[derive(Debug)] + /// Bridge to encode call for. + pub enum EncodeCallBridge { + MillauToRialto, + RialtoToMillau, + } +} + +impl EncodeCallBridge { + fn bridge_instance_index(&self) -> u8 { + match self { + Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, + Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, + } + } +} + +pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; +pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + EncodeCallBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + + $generic + } + EncodeCallBridge::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + + $generic + } + } + }; +} + +impl EncodeCall { + fn encode(&mut self) -> anyhow::Result { + select_bridge!(self.bridge, { + preprocess_call::(&mut self.call, self.bridge.bridge_instance_index()); + let call = Source::encode_call(&self.call)?; + + let encoded = HexBytes::encode(&call); + + log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); + log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, call.get_dispatch_info().weight); + log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); + + Ok(encoded) + }) + } + + /// Run the command. + pub async fn run(mut self) -> anyhow::Result<()> { + println!("{:?}", self.encode()?); + Ok(()) + } +} + +/// Prepare the call to be passed to [`CliEncodeCall::encode_call`]. +/// +/// This function will fill in all optional and missing pieces and will make sure that +/// values are converted to bridge-specific ones. +/// +/// Most importantly, the method will fill-in [`bridge_instance_index`] parameter for +/// target-chain specific calls. +pub(crate) fn preprocess_call( + call: &mut Call, + bridge_instance: u8, +) { + match *call { + Call::Raw { .. } => {} + Call::Remark { + ref remark_size, + ref mut remark_payload, + } => { + if remark_payload.0.is_empty() { + *remark_payload = HexBytes(generate_remark_payload( + &remark_size, + compute_maximal_message_arguments_size(Source::max_extrinsic_size(), Target::max_extrinsic_size()), + )); + } + } + Call::Transfer { ref mut recipient, .. } => { + recipient.enforce_chain::(); + } + Call::BridgeSendMessage { + ref mut bridge_instance_index, + .. + } => { + *bridge_instance_index = bridge_instance; + } + }; +} + +fn generate_remark_payload(remark_size: &Option>, maximal_allowed_size: u32) -> Vec { + match remark_size { + Some(ExplicitOrMaximal::Explicit(remark_size)) => vec![0; *remark_size], + Some(ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], + None => format!( + "Unix time: {}", + std::time::SystemTime::now() + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ) + .as_bytes() + .to_vec(), + } +} + +pub(crate) fn compute_maximal_message_arguments_size( + maximal_source_extrinsic_size: u32, + maximal_target_extrinsic_size: u32, +) -> u32 { + // assume that both signed extensions and other arguments fit 1KB + let service_tx_bytes_on_source_chain = 1024; + let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; + let maximal_call_size = + bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size); + let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { + maximal_source_extrinsic_size + } else { + maximal_call_size + }; + + // bytes in Call encoding that are used to encode everything except arguments + let service_bytes = 1 + 1 + 4; + maximal_call_size - service_bytes +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_encode_transfer_call() { + // given + let mut encode_call = EncodeCall::from_iter(vec![ + "encode-call", + "RialtoToMillau", + "transfer", + "--amount", + "12345", + "--recipient", + "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU", + ]); + + // when + let hex = encode_call.encode().unwrap(); + + // then + assert_eq!( + format!("{:?}", hex), + "0x0d00d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" + ); + } +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index f3f7dfefd9fe3..216b778c21832 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -25,6 +25,8 @@ use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +pub(crate) mod encode_call; + mod derive_account; mod init_bridge; mod relay_headers; @@ -63,7 +65,7 @@ pub enum Command { /// /// The call can be used either as message payload or can be wrapped into a transaction /// and executed on the chain directly. - EncodeCall(EncodeCall), + EncodeCall(encode_call::EncodeCall), /// Generate SCALE-encoded `MessagePayload` object that can be sent over selected bridge. /// /// The `MessagePayload` can be then fed to `Messages::send_message` function and sent over @@ -109,23 +111,6 @@ impl SendMessage { } } -/// A call to encode. -#[derive(StructOpt)] -pub enum EncodeCall { - #[structopt(flatten)] - RialtoMillau(rialto_millau::EncodeCall), -} - -impl EncodeCall { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - /// A `MessagePayload` to encode. #[derive(StructOpt)] pub enum EncodeMessagePayload { @@ -273,9 +258,6 @@ pub trait CliChain: relay_substrate_client::Chain { /// Numeric value of SS58 format. fn ss58_format() -> u16; - /// Parse CLI call and encode it to be dispatched on this specific chain. - fn encode_call(call: crate::rialto_millau::cli::Call) -> Result; - /// Construct message payload to be sent over the bridge. fn encode_message(message: crate::rialto_millau::cli::MessagePayload) -> Result; @@ -304,7 +286,7 @@ impl std::str::FromStr for HexLaneId { } /// Nicer formatting for raw bytes vectors. -#[derive(Encode, Decode)] +#[derive(Default, Encode, Decode)] pub struct HexBytes(pub Vec); impl std::str::FromStr for HexBytes { @@ -317,7 +299,13 @@ impl std::str::FromStr for HexBytes { impl std::fmt::Debug for HexBytes { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "0x{}", hex::encode(&self.0)) + write!(fmt, "0x{}", self) + } +} + +impl std::fmt::Display for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{}", hex::encode(&self.0)) } } @@ -470,4 +458,17 @@ mod tests { assert_eq!(actual, expected) } + + #[test] + fn hex_bytes_display_matches_from_str_for_clap() { + // given + let hex = HexBytes(vec![1, 2, 3, 4]); + let display = format!("{}", hex); + + // when + let hex2: HexBytes = display.parse().unwrap(); + + // then + assert_eq!(hex.0, hex2.0); + } } diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs index 2f11156537364..9e5788b1cb69d 100644 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/relays/bin-substrate/src/rialto_millau/cli.rs @@ -48,7 +48,7 @@ pub enum SendMessage { fee: Option, /// Message type. #[structopt(subcommand)] - message: Call, + message: crate::cli::encode_call::Call, /// The origin to use when dispatching the message on the target chain. Defaults to /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] @@ -73,7 +73,7 @@ pub enum SendMessage { fee: Option, /// Message type. #[structopt(subcommand)] - message: Call, + message: crate::cli::encode_call::Call, /// The origin to use when dispatching the message on the target chain. Defaults to /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] @@ -89,31 +89,6 @@ impl SendMessage { } } -/// A call to encode. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum EncodeCall { - /// Encode Rialto's Call. - Rialto { - #[structopt(flatten)] - call: Call, - }, - /// Encode Millau's Call. - Millau { - #[structopt(flatten)] - call: Call, - }, -} - -impl EncodeCall { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_encode_call(self).await.map_err(format_err)?; - Ok(()) - } -} - /// A `MessagePayload` to encode. /// /// TODO [#855] Move to separate module. @@ -192,50 +167,9 @@ pub enum MessagePayload { Call { /// Message details. #[structopt(flatten)] - call: Call, + call: crate::cli::encode_call::Call, /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) #[structopt(long)] sender: AccountId, }, } - -/// All possible messages that may be delivered to generic Substrate chain. -/// -/// Note this enum may be used in the context of both Source (as part of `encode-call`) -/// and Target chain (as part of `encode-message/send-message`). -#[derive(StructOpt, Debug)] -pub enum Call { - /// Raw bytes for the message - Raw { - /// Raw, SCALE-encoded message - data: HexBytes, - }, - /// Make an on-chain remark (comment). - Remark { - /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. - #[structopt(long)] - remark_size: Option>, - }, - /// Transfer the specified `amount` of native tokens to a particular `recipient`. - Transfer { - /// SS58 encoded account that will receive the transfer (must have SS58Prefix = 42) - #[structopt(long)] - recipient: AccountId, - /// Amount of target tokens to send in target chain base currency units. - #[structopt(long)] - amount: Balance, - }, - // TODO [#853] Support multiple bridges. - /// A call to the specific Bridge Messages pallet to queue message to be sent over a bridge. - BridgeSendMessage { - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the messages pallet. - #[structopt(long)] - payload: HexBytes, - /// Declared delivery and dispatch fee in base source-chain currency units. - #[structopt(long)] - fee: Balance, - }, -} diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index f039aadef54dd..52f1d5201cdec 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -28,7 +28,10 @@ pub type MillauClient = relay_substrate_client::Client; /// Rialto node client. pub type RialtoClient = relay_substrate_client::Client; -use crate::cli::{CliChain, ExplicitOrMaximal, HexBytes, Origins}; +use crate::cli::{ + encode_call::{self, Call, CliEncodeCall, MILLAU_TO_RIALTO_INDEX, RIALTO_TO_MILLAU_INDEX}, + CliChain, ExplicitOrMaximal, HexBytes, Origins, +}; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; @@ -48,7 +51,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { source_sign, target_sign, lane, - message, + mut message, dispatch_weight, fee, origin, @@ -75,7 +78,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { let source_client = source.into_client::().await.map_err(format_err)?; let source_sign = source_sign.into_keypair::().map_err(format_err)?; let target_sign = target_sign.into_keypair::().map_err(format_err)?; - let target_call = Target::encode_call(message)?; + + encode_call::preprocess_call::(&mut message, MILLAU_TO_RIALTO_INDEX); + let target_call = Target::encode_call(&message).map_err(|e| e.to_string())?; let payload = { let target_call_weight = prepare_call_dispatch_weight( @@ -154,7 +159,7 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { source_sign, target_sign, lane, - message, + mut message, dispatch_weight, fee, origin, @@ -181,7 +186,9 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { let source_client = source.into_client::().await.map_err(format_err)?; let source_sign = source_sign.into_keypair::().map_err(format_err)?; let target_sign = target_sign.into_keypair::().map_err(format_err)?; - let target_call = Target::encode_call(message)?; + + encode_call::preprocess_call::(&mut message, RIALTO_TO_MILLAU_INDEX); + let target_call = Target::encode_call(&message).map_err(|e| e.to_string())?; let payload = { let target_call_weight = prepare_call_dispatch_weight( @@ -259,24 +266,6 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { Ok(()) } -async fn run_encode_call(call: cli::EncodeCall) -> Result<(), String> { - match call { - cli::EncodeCall::Rialto { call } => { - type Source = Rialto; - - let call = Source::encode_call(call)?; - println!("{:?}", HexBytes::encode(&call)); - } - cli::EncodeCall::Millau { call } => { - type Source = Millau; - - let call = Source::encode_call(call)?; - println!("{:?}", HexBytes::encode(&call)); - } - } - Ok(()) -} - async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<(), String> { match call { cli::EncodeMessagePayload::RialtoToMillau { payload } => { @@ -348,22 +337,6 @@ async fn estimate_message_delivery_and_dispatch_fee>, maximal_allowed_size: u32) -> Vec { - match remark_size { - Some(ExplicitOrMaximal::Explicit(remark_size)) => vec![0; remark_size], - Some(ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], - None => format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - } -} - fn message_payload( spec_version: u32, weight: Weight, @@ -433,24 +406,41 @@ fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) } -fn compute_maximal_message_arguments_size( - maximal_source_extrinsic_size: u32, - maximal_target_extrinsic_size: u32, -) -> u32 { - // assume that both signed extensions and other arguments fit 1KB - let service_tx_bytes_on_source_chain = 1024; - let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; - let maximal_call_size = - bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size); - let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { - maximal_source_extrinsic_size - } else { - maximal_call_size - }; +impl CliEncodeCall for Millau { + fn max_extrinsic_size() -> u32 { + bp_millau::max_extrinsic_size() + } - // bytes in Call encoding that are used to encode everything except arguments - let service_bytes = 1 + 1 + 4; - maximal_call_size - service_bytes + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Remark { remark_payload, .. } => { + millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload.0.clone())) + } + Call::Transfer { recipient, amount } => millau_runtime::Call::Balances( + millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount.cast()), + ), + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + encode_call::MILLAU_TO_RIALTO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( + lane.0, + payload, + fee.cast(), + )) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + }) + } } impl CliChain for Millau { @@ -467,58 +457,20 @@ impl CliChain for Millau { bp_millau::max_extrinsic_weight() } - fn encode_call(call: cli::Call) -> Result { - let call = match call { - cli::Call::Raw { data } => { - Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? - } - cli::Call::Remark { remark_size } => { - millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload( - remark_size, - compute_maximal_message_arguments_size( - bp_rialto::max_extrinsic_size(), - bp_millau::max_extrinsic_size(), - ), - ))) - } - cli::Call::Transfer { mut recipient, amount } => { - recipient.enforce_chain::(); - let amount = amount.cast(); - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) - } - cli::Call::BridgeSendMessage { lane, payload, fee } => { - type Target = Rialto; - - let payload = Target::encode_message(cli::MessagePayload::Raw { data: payload })?; - let lane = lane.into(); - millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( - lane, - payload, - fee.cast(), - )) - } - }; - - log::info!(target: "bridge", "Generated Millau call: {:#?}", call); - log::info!(target: "bridge", "Weight of Millau call: {}", call.get_dispatch_info().weight); - log::info!(target: "bridge", "Encoded Millau call: {:?}", HexBytes::encode(&call)); - - Ok(call) - } - // TODO [#854|#843] support multiple bridges? fn encode_message(message: cli::MessagePayload) -> Result { match message { cli::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), - cli::MessagePayload::Call { call, mut sender } => { + cli::MessagePayload::Call { mut call, mut sender } => { type Source = Millau; type Target = Rialto; sender.enforce_chain::(); let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - let call = Target::encode_call(call)?; + encode_call::preprocess_call::(&mut call, MILLAU_TO_RIALTO_INDEX); + let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; Ok(message_payload(spec_version, weight, origin, &call)) @@ -527,6 +479,41 @@ impl CliChain for Millau { } } +impl CliEncodeCall for Rialto { + fn max_extrinsic_size() -> u32 { + bp_rialto::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Remark { remark_payload, .. } => { + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload.0.clone())) + } + Call::Transfer { recipient, amount } => { + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount.0)) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + encode_call::RIALTO_TO_MILLAU_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( + lane.0, payload, fee.0, + )) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + }) + } +} + impl CliChain for Rialto { const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; @@ -541,57 +528,19 @@ impl CliChain for Rialto { bp_rialto::max_extrinsic_weight() } - fn encode_call(call: cli::Call) -> Result { - let call = match call { - cli::Call::Raw { data } => { - Decode::decode(&mut &*data.0).map_err(|e| format!("Unable to decode message: {:#?}", e))? - } - cli::Call::Remark { remark_size } => { - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload( - remark_size, - compute_maximal_message_arguments_size( - bp_millau::max_extrinsic_size(), - bp_rialto::max_extrinsic_size(), - ), - ))) - } - cli::Call::Transfer { mut recipient, amount } => { - type Source = Rialto; - - recipient.enforce_chain::(); - let amount = amount.0; - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount)) - } - cli::Call::BridgeSendMessage { lane, payload, fee } => { - type Target = Millau; - - let payload = Target::encode_message(cli::MessagePayload::Raw { data: payload })?; - let lane = lane.into(); - rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( - lane, payload, fee.0, - )) - } - }; - - log::info!(target: "bridge", "Generated Rialto call: {:#?}", call); - log::info!(target: "bridge", "Weight of Rialto call: {}", call.get_dispatch_info().weight); - log::info!(target: "bridge", "Encoded Rialto call: {:?}", HexBytes::encode(&call)); - - Ok(call) - } - fn encode_message(message: cli::MessagePayload) -> Result { match message { cli::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), - cli::MessagePayload::Call { call, mut sender } => { + cli::MessagePayload::Call { mut call, mut sender } => { type Source = Rialto; type Target = Millau; sender.enforce_chain::(); let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - let call = Target::encode_call(call)?; + encode_call::preprocess_call::(&mut call, RIALTO_TO_MILLAU_INDEX); + let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; Ok(message_payload(spec_version, weight, origin, &call)) @@ -614,10 +563,6 @@ impl CliChain for Westend { 0 } - fn encode_call(_: cli::Call) -> Result { - Err("Calling into Westend is not supported yet.".into()) - } - fn encode_message(_message: cli::MessagePayload) -> Result { Err("Sending messages from Westend is not yet supported.".into()) } @@ -680,8 +625,10 @@ mod tests { fn maximal_rialto_to_millau_message_arguments_size_is_computed_correctly() { use rialto_runtime::millau_messages::Millau; - let maximal_remark_size = - compute_maximal_message_arguments_size(bp_rialto::max_extrinsic_size(), bp_millau::max_extrinsic_size()); + let maximal_remark_size = encode_call::compute_maximal_message_arguments_size( + bp_rialto::max_extrinsic_size(), + bp_millau::max_extrinsic_size(), + ); let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); let payload = message_payload( From f40d5d8f1466f943ddd919cd6d17613b49cdedd3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Apr 2021 05:09:48 -0400 Subject: [PATCH 0407/1210] Update Copyright Date to 2021 (#864) * Update copyright date to 2021 * Bump date in license header template --- bin/millau/node/build.rs | 2 +- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/node/src/cli.rs | 2 +- bin/millau/node/src/command.rs | 2 +- bin/millau/node/src/lib.rs | 2 +- bin/millau/node/src/main.rs | 2 +- bin/millau/node/src/service.rs | 2 +- bin/millau/runtime/build.rs | 2 +- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/node/build.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/cli.rs | 2 +- bin/rialto/node/src/command.rs | 2 +- bin/rialto/node/src/main.rs | 2 +- bin/rialto/node/src/service.rs | 2 +- bin/rialto/runtime/build.rs | 2 +- bin/rialto/runtime/src/benches.rs | 2 +- bin/rialto/runtime/src/exchange.rs | 2 +- bin/rialto/runtime/src/kovan.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/rialto_poa.rs | 2 +- bin/runtime-common/src/lib.rs | 2 +- bin/runtime-common/src/messages.rs | 2 +- bin/runtime-common/src/messages_benchmarking.rs | 2 +- modules/currency-exchange/src/benchmarking.rs | 2 +- modules/currency-exchange/src/lib.rs | 2 +- modules/dispatch/src/lib.rs | 2 +- modules/ethereum-contract-builtin/src/lib.rs | 2 +- modules/ethereum/src/benchmarking.rs | 2 +- modules/ethereum/src/error.rs | 2 +- modules/ethereum/src/finality.rs | 2 +- modules/ethereum/src/import.rs | 2 +- modules/ethereum/src/lib.rs | 2 +- modules/ethereum/src/mock.rs | 2 +- modules/ethereum/src/test_utils.rs | 2 +- modules/ethereum/src/validators.rs | 2 +- modules/ethereum/src/verification.rs | 2 +- modules/messages/rpc/src/error.rs | 2 +- modules/messages/rpc/src/lib.rs | 2 +- modules/messages/src/benchmarking.rs | 2 +- modules/messages/src/inbound_lane.rs | 2 +- modules/messages/src/instant_payments.rs | 2 +- modules/messages/src/lib.rs | 2 +- modules/messages/src/mock.rs | 2 +- modules/messages/src/outbound_lane.rs | 2 +- modules/messages/src/weights.rs | 2 +- modules/messages/src/weights_ext.rs | 2 +- modules/shift-session-manager/src/lib.rs | 2 +- modules/substrate/src/fork_tests.rs | 2 +- modules/substrate/src/lib.rs | 2 +- modules/substrate/src/mock.rs | 2 +- modules/substrate/src/storage.rs | 2 +- modules/substrate/src/verifier.rs | 2 +- primitives/chain-millau/src/lib.rs | 2 +- primitives/chain-millau/src/millau_hash.rs | 2 +- primitives/chain-rialto/src/lib.rs | 2 +- primitives/currency-exchange/src/lib.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 2 +- primitives/ethereum-poa/src/signatures.rs | 2 +- primitives/header-chain/src/justification.rs | 2 +- primitives/header-chain/src/lib.rs | 2 +- primitives/header-chain/tests/justification.rs | 2 +- primitives/message-dispatch/src/lib.rs | 2 +- primitives/messages/src/lib.rs | 2 +- primitives/messages/src/source_chain.rs | 2 +- primitives/messages/src/target_chain.rs | 2 +- primitives/runtime/src/chain.rs | 2 +- primitives/runtime/src/lib.rs | 2 +- primitives/runtime/src/storage_proof.rs | 2 +- relays/bin-ethereum/src/ethereum_client.rs | 2 +- relays/bin-ethereum/src/ethereum_deploy_contract.rs | 2 +- relays/bin-ethereum/src/ethereum_exchange.rs | 2 +- relays/bin-ethereum/src/ethereum_exchange_submit.rs | 2 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 2 +- relays/bin-ethereum/src/instances.rs | 2 +- relays/bin-ethereum/src/main.rs | 2 +- relays/bin-ethereum/src/rialto_client.rs | 2 +- relays/bin-ethereum/src/rpc_errors.rs | 2 +- relays/bin-ethereum/src/substrate_sync_loop.rs | 2 +- relays/bin-ethereum/src/substrate_types.rs | 2 +- relays/bin-substrate/src/finality_target.rs | 2 +- relays/bin-substrate/src/headers_initialize.rs | 2 +- relays/bin-substrate/src/main.rs | 2 +- relays/bin-substrate/src/messages_lane.rs | 2 +- relays/bin-substrate/src/messages_source.rs | 2 +- .../bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs | 2 +- .../src/rialto_millau/millau_messages_to_rialto.rs | 2 +- .../bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs | 2 +- .../src/rialto_millau/rialto_messages_to_millau.rs | 2 +- .../src/rialto_millau/westend_headers_to_millau.rs | 2 +- relays/client-ethereum/src/client.rs | 2 +- relays/client-ethereum/src/error.rs | 2 +- relays/client-ethereum/src/lib.rs | 2 +- relays/client-ethereum/src/rpc.rs | 2 +- relays/client-ethereum/src/sign.rs | 2 +- relays/client-ethereum/src/types.rs | 2 +- relays/client-kusama/src/lib.rs | 2 +- relays/client-millau/src/lib.rs | 2 +- relays/client-polkadot/src/lib.rs | 2 +- relays/client-rialto/src/lib.rs | 2 +- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 2 +- relays/client-substrate/src/error.rs | 2 +- relays/client-substrate/src/guard.rs | 2 +- relays/client-substrate/src/headers_source.rs | 2 +- relays/client-substrate/src/lib.rs | 2 +- relays/client-substrate/src/rpc.rs | 2 +- relays/client-substrate/src/sync_header.rs | 2 +- relays/client-westend/src/lib.rs | 2 +- relays/exchange/src/exchange.rs | 2 +- relays/exchange/src/exchange_loop.rs | 2 +- relays/exchange/src/exchange_loop_metrics.rs | 2 +- relays/exchange/src/lib.rs | 2 +- relays/headers/src/headers.rs | 2 +- relays/headers/src/lib.rs | 2 +- relays/headers/src/sync.rs | 2 +- relays/headers/src/sync_loop.rs | 2 +- relays/headers/src/sync_loop_metrics.rs | 2 +- relays/headers/src/sync_loop_tests.rs | 2 +- relays/headers/src/sync_types.rs | 2 +- relays/messages/src/lib.rs | 2 +- relays/messages/src/message_lane.rs | 2 +- relays/messages/src/message_lane_loop.rs | 2 +- relays/messages/src/message_race_delivery.rs | 2 +- relays/messages/src/message_race_loop.rs | 2 +- relays/messages/src/message_race_receiving.rs | 2 +- relays/messages/src/message_race_strategy.rs | 2 +- relays/messages/src/metrics.rs | 2 +- relays/utils/src/initialize.rs | 2 +- relays/utils/src/lib.rs | 2 +- relays/utils/src/metrics.rs | 2 +- relays/utils/src/relay_loop.rs | 2 +- 134 files changed, 134 insertions(+), 134 deletions(-) diff --git a/bin/millau/node/build.rs b/bin/millau/node/build.rs index b0d117f37c927..d9b50049e2628 100644 --- a/bin/millau/node/build.rs +++ b/bin/millau/node/build.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 22f1827e35286..64dca2f255011 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index c1d42a1f21b12..46323ed25c9ed 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 8e6427ed804bb..d73f9b1ac9b2c 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/node/src/lib.rs b/bin/millau/node/src/lib.rs index fdecc0b45f0ea..382d1c2d7fb1c 100644 --- a/bin/millau/node/src/lib.rs +++ b/bin/millau/node/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/node/src/main.rs b/bin/millau/node/src/main.rs index 07ec88727df5f..cf6dd9f733a16 100644 --- a/bin/millau/node/src/main.rs +++ b/bin/millau/node/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 18c46736dc84d..25cc4c7fb21a9 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/runtime/build.rs b/bin/millau/runtime/build.rs index 4fda040c9bd14..dcb5cb06218e5 100644 --- a/bin/millau/runtime/build.rs +++ b/bin/millau/runtime/build.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1a60d16d7daf4..ed622e7eea2c8 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 842fcdf6c0993..c96b6f610db91 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/node/build.rs b/bin/rialto/node/build.rs index b0d117f37c927..d9b50049e2628 100644 --- a/bin/rialto/node/build.rs +++ b/bin/rialto/node/build.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 55a2abbd08b50..2794496fc35c1 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index c1d42a1f21b12..46323ed25c9ed 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 83d2a98b67b5b..a9930c57417ec 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/node/src/main.rs b/bin/rialto/node/src/main.rs index 164afae2bb90d..f319d1437a98f 100644 --- a/bin/rialto/node/src/main.rs +++ b/bin/rialto/node/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 7f3958997da24..4f35a8fddf045 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/runtime/build.rs b/bin/rialto/runtime/build.rs index 4fda040c9bd14..dcb5cb06218e5 100644 --- a/bin/rialto/runtime/build.rs +++ b/bin/rialto/runtime/build.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/runtime/src/benches.rs b/bin/rialto/runtime/src/benches.rs index 4ca476e5f3ca6..86d6b8361c635 100644 --- a/bin/rialto/runtime/src/benches.rs +++ b/bin/rialto/runtime/src/benches.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index ac67a6c446b1a..a054962a79c71 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs index fa76347db251e..03b0ca8a07163 100644 --- a/bin/rialto/runtime/src/kovan.rs +++ b/bin/rialto/runtime/src/kovan.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index dae683aa82dbf..39693de2c0b5b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 2cd7d787ea133..90a79891e6b8d 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/rialto/runtime/src/rialto_poa.rs b/bin/rialto/runtime/src/rialto_poa.rs index 54ac8e25713a0..83b263975a322 100644 --- a/bin/rialto/runtime/src/rialto_poa.rs +++ b/bin/rialto/runtime/src/rialto_poa.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 2842e3b6592a4..ae7efb4a41968 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index c25f7091d9546..2497f07131fe2 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 5694b9a05c4d3..639e5f6c5049b 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index d10dd3c684126..204398e12d8c6 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index bd48e6c8a205d..569a01e03ecb6 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index b2fdf2b70647e..d383e884696d1 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum-contract-builtin/src/lib.rs b/modules/ethereum-contract-builtin/src/lib.rs index 5762d510b2a90..47c4452aee6cd 100644 --- a/modules/ethereum-contract-builtin/src/lib.rs +++ b/modules/ethereum-contract-builtin/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 5de6e80f16a1f..960dbe9afec24 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index 50dccd6ea2ced..ad798379da7dc 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 608708a0c7bad..58987c6b29bc5 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 1b41c3a8b20ad..8cd4c8a17c771 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index fd08ba0da6fac..c29c7844a1c0e 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 6808062d4d0c3..8c305dedf7884 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index ad4019412892d..18ad6876d68ba 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index d4ddac66b7df0..7ec22a44391d2 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 7b1f175f54292..c79242d1d4d9e 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/rpc/src/error.rs b/modules/messages/rpc/src/error.rs index ce7039705567f..983b53b65ba37 100644 --- a/modules/messages/rpc/src/error.rs +++ b/modules/messages/rpc/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/rpc/src/lib.rs b/modules/messages/rpc/src/lib.rs index 3fd1ffdb82558..381725f06e7f0 100644 --- a/modules/messages/rpc/src/lib.rs +++ b/modules/messages/rpc/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 0265db0429364..f160168d0bdac 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index a2ec02b74d32c..b5576bc30a1e3 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index c6d30950be6bb..24261cf5cfb0a 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index c134b2ebaf867..9abd2f087fc42 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 836aedf3a6a42..8cd764e4417dc 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 0a6dd5670c53a..47616c33eac83 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 2ccb03c4c9349..4e275b1f248b2 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 89dbea89497f7..cb754a1023106 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 6fc92d73eceb2..6df5cae377385 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs index 40b40678a86db..58b9749620a21 100644 --- a/modules/substrate/src/fork_tests.rs +++ b/modules/substrate/src/fork_tests.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs index ce4006688515f..20f0833873514 100644 --- a/modules/substrate/src/lib.rs +++ b/modules/substrate/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs index 85782b7ea4fe1..f2bb422d3dc69 100644 --- a/modules/substrate/src/mock.rs +++ b/modules/substrate/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs index 5b521306b2cd1..fe730c45d99fe 100644 --- a/modules/substrate/src/storage.rs +++ b/modules/substrate/src/storage.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs index 891864554baaa..1b9e11dc2973f 100644 --- a/modules/substrate/src/verifier.rs +++ b/modules/substrate/src/verifier.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 28ad3a38818e1..cb8f047cbd80c 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/chain-millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs index e917329d2cc09..936791217af18 100644 --- a/primitives/chain-millau/src/millau_hash.rs +++ b/primitives/chain-millau/src/millau_hash.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index f85e239fbe14c..feeeadf45a9bc 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index 131daf66eda51..88695dbb5ef40 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index dc65ac432b144..57c539f2e27b5 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs index 21c6f3f860fff..a4e076f2200c6 100644 --- a/primitives/ethereum-poa/src/signatures.rs +++ b/primitives/ethereum-poa/src/signatures.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 1db15440fb5c2..a2a354d9de7aa 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index ba47d614faaa8..d33a6d36eb1b8 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index e17b24ed815bd..1ce739e4536f1 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 1932d8cb0b8d4..3b83e38517e2d 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 83bd902a1e81a..c3ffce8baa525 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 8cc62a0090231..1d313634bcba3 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 530a228022354..676e919bc6191 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 348b5bf1d277d..cb19c6e72681d 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index c776944fb3c86..5d5469017dfeb 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 2d81e5a4b6cc5..d70be93b1d251 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/ethereum_client.rs b/relays/bin-ethereum/src/ethereum_client.rs index 46c2c76feee08..b57b407d774a4 100644 --- a/relays/bin-ethereum/src/ethereum_client.rs +++ b/relays/bin-ethereum/src/ethereum_client.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs index b70decd6f49f9..84c12be7a7081 100644 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index b92581e1f54fa..813eab0789baa 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/ethereum_exchange_submit.rs b/relays/bin-ethereum/src/ethereum_exchange_submit.rs index 8616cce2166cb..09871a0fc786b 100644 --- a/relays/bin-ethereum/src/ethereum_exchange_submit.rs +++ b/relays/bin-ethereum/src/ethereum_exchange_submit.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index b2e18b1c8fe59..0fbe378259814 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs index 7f29c26d8c362..0d2a508f455a3 100644 --- a/relays/bin-ethereum/src/instances.rs +++ b/relays/bin-ethereum/src/instances.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index 40f056c61c049..d1171d1461d47 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index 06605fdfd5437..c294edbf4e877 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs index 6f1c06040e110..27b233135f325 100644 --- a/relays/bin-ethereum/src/rpc_errors.rs +++ b/relays/bin-ethereum/src/rpc_errors.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index f72fcd96324d8..0765cca031569 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-ethereum/src/substrate_types.rs b/relays/bin-ethereum/src/substrate_types.rs index b88f383139385..af68d7e028555 100644 --- a/relays/bin-ethereum/src/substrate_types.rs +++ b/relays/bin-ethereum/src/substrate_types.rs @@ -1,4 +1,4 @@ -// Copyright 2020 Parity Technologies (UK) Ltd. +// Copyright 2020-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 diff --git a/relays/bin-substrate/src/finality_target.rs b/relays/bin-substrate/src/finality_target.rs index 37f433ad06d05..ffa10cabacbfa 100644 --- a/relays/bin-substrate/src/finality_target.rs +++ b/relays/bin-substrate/src/finality_target.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index 07d6d0f06d91a..83db39bf7bb6a 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 4047c0b54e453..11ff67e83b403 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 01814ad6a9c6f..ada5ce12bfc33 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 278fff6d2d99e..99f88fbbbb30e 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index 43ae3954c36f2..3091df31ff1eb 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index 38fe71d36879f..ba68b9e490a8d 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index f18f108320386..1c36991fd2727 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index 23c338390bfe1..e29d23b015bf0 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index f042c0bd3919e..2ba9069b2552b 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs index 593e40d67a473..10fba1fb99fd1 100644 --- a/relays/client-ethereum/src/client.rs +++ b/relays/client-ethereum/src/client.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index 80d4e89d5ee96..69ade23f741cb 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-ethereum/src/lib.rs b/relays/client-ethereum/src/lib.rs index 17bfda6e6443b..8b3c6d8f8e733 100644 --- a/relays/client-ethereum/src/lib.rs +++ b/relays/client-ethereum/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-ethereum/src/rpc.rs b/relays/client-ethereum/src/rpc.rs index 9826d92e0ceb8..0fb81f7655a46 100644 --- a/relays/client-ethereum/src/rpc.rs +++ b/relays/client-ethereum/src/rpc.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-ethereum/src/sign.rs b/relays/client-ethereum/src/sign.rs index 462cb5dbd7d27..6f479ab7d5cd4 100644 --- a/relays/client-ethereum/src/sign.rs +++ b/relays/client-ethereum/src/sign.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-ethereum/src/types.rs b/relays/client-ethereum/src/types.rs index 1bb9233b82ea4..f589474aff1be 100644 --- a/relays/client-ethereum/src/types.rs +++ b/relays/client-ethereum/src/types.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 9f9507f5ca62e..3c3b1cd4c5d80 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index a547fb9ac63fd..5b521012c0063 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 7f85de13632c3..2c117c6d3d1ce 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index d74d6a8806047..7061205ec8d02 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 86ad4bc8c9bc8..1a06582ec1e34 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index a03cf493ca105..289118753c408 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 4e1f45eca3e64..899ce4a2b2bb6 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index e924b94b6f79f..66a6fbdee7d7d 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/headers_source.rs b/relays/client-substrate/src/headers_source.rs index b347a1c9f57f2..ad53a33a9f5fa 100644 --- a/relays/client-substrate/src/headers_source.rs +++ b/relays/client-substrate/src/headers_source.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index d18189647fa36..9190e17247b33 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index fcc3e9dd890ce..1816e8cd3f263 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-substrate/src/sync_header.rs b/relays/client-substrate/src/sync_header.rs index 30e33a39279a2..0b74dee690f21 100644 --- a/relays/client-substrate/src/sync_header.rs +++ b/relays/client-substrate/src/sync_header.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 0abbbb100cf14..c8594a925dd1b 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs index cdf9c1a9f3588..cec0d7cba1fa4 100644 --- a/relays/exchange/src/exchange.rs +++ b/relays/exchange/src/exchange.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 101a655c25768..3ef6503353f6f 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/exchange/src/exchange_loop_metrics.rs b/relays/exchange/src/exchange_loop_metrics.rs index bf8f0243b693a..320f662c6dc5c 100644 --- a/relays/exchange/src/exchange_loop_metrics.rs +++ b/relays/exchange/src/exchange_loop_metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/exchange/src/lib.rs b/relays/exchange/src/lib.rs index f975ef2aa0ff4..370f085b4bf7c 100644 --- a/relays/exchange/src/lib.rs +++ b/relays/exchange/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs index 99ccc197afc18..be3e2cb6e6d89 100644 --- a/relays/headers/src/headers.rs +++ b/relays/headers/src/headers.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/lib.rs b/relays/headers/src/lib.rs index d91fe94d9d50b..94cfd83f40644 100644 --- a/relays/headers/src/lib.rs +++ b/relays/headers/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/sync.rs b/relays/headers/src/sync.rs index 8e4c671dbaa9e..e992b1f8e583c 100644 --- a/relays/headers/src/sync.rs +++ b/relays/headers/src/sync.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index 9b55456f7900d..0e535d8caae5d 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/sync_loop_metrics.rs b/relays/headers/src/sync_loop_metrics.rs index 9cec0e891dc81..616a04360d6b5 100644 --- a/relays/headers/src/sync_loop_metrics.rs +++ b/relays/headers/src/sync_loop_metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/sync_loop_tests.rs b/relays/headers/src/sync_loop_tests.rs index 03303214bc52a..ff56dc45d2326 100644 --- a/relays/headers/src/sync_loop_tests.rs +++ b/relays/headers/src/sync_loop_tests.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs index e1da6232258c9..e6500ad5facb0 100644 --- a/relays/headers/src/sync_types.rs +++ b/relays/headers/src/sync_types.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/lib.rs b/relays/messages/src/lib.rs index facb82ac8e7fa..cdd94bca95412 100644 --- a/relays/messages/src/lib.rs +++ b/relays/messages/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs index 0eab02ae299f2..5090ef124e7f7 100644 --- a/relays/messages/src/message_lane.rs +++ b/relays/messages/src/message_lane.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index b5f650f117c65..24a5314d23043 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 80709055be0e9..3b1644b728923 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 56bc881bf7a9a..f3bf2626ef4b8 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index 2178882437eb6..6538061965ae9 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index fbc7877a3ab6b..2d8e90d433e62 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 3f4cbfa3047d8..a9a0ac4081f1f 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index ee09cc8d9f08f..7d5f66a53815c 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 0dcc7e9a4f983..ab913b758ddf1 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index c42b10cad97f7..41df88ecd0036 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 2e12f71459ab2..04077bf08aadc 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// 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 From a0ae9ed97577039fa3509663e62621ab4d0b2485 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Apr 2021 12:54:15 +0300 Subject: [PATCH 0408/1210] Pre-create metrics registry before loop is started + administrative metrics (#848) * administrative metrics * fmt * fix compilation * fix compilation again * and another one * remove GenericLoopMetrics * chttp -> isahc * remove redundant marker * not about price metrics * fmt --- bin/millau/runtime/src/rialto_messages.rs | 5 +- bin/rialto/runtime/src/millau_messages.rs | 5 +- primitives/runtime/src/lib.rs | 2 +- relays/bin-ethereum/src/ethereum_exchange.rs | 2 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 2 +- relays/bin-ethereum/src/main.rs | 13 +- .../bin-ethereum/src/substrate_sync_loop.rs | 2 +- relays/bin-substrate/src/cli/mod.rs | 9 +- relays/bin-substrate/src/cli/relay_headers.rs | 4 +- relays/bin-substrate/src/finality_pipeline.rs | 9 +- .../millau_messages_to_rialto.rs | 29 +++- .../rialto_messages_to_millau.rs | 29 +++- .../westend_headers_to_millau.rs | 24 ++++ relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 10 +- relays/client-substrate/src/error.rs | 4 + relays/client-substrate/src/guard.rs | 1 + relays/client-substrate/src/lib.rs | 1 + .../src/metrics/float_storage_value.rs | 91 ++++++++++++ relays/client-substrate/src/metrics/mod.rs | 23 +++ .../src/metrics/storage_proof_overhead.rs | 135 ++++++++++++++++++ relays/exchange/src/exchange_loop.rs | 11 +- relays/finality/src/finality_loop.rs | 11 +- relays/finality/src/finality_loop_tests.rs | 4 +- relays/finality/src/lib.rs | 2 +- relays/headers/src/sync_loop.rs | 6 +- relays/headers/src/sync_loop_tests.rs | 5 +- relays/messages/src/message_lane_loop.rs | 23 +-- relays/utils/Cargo.toml | 3 + relays/utils/src/lib.rs | 2 +- relays/utils/src/metrics.rs | 79 +++++++++- relays/utils/src/metrics/float_json_value.rs | 125 ++++++++++++++++ relays/utils/src/metrics/global.rs | 5 +- relays/utils/src/relay_loop.rs | 54 +++++-- 34 files changed, 659 insertions(+), 73 deletions(-) create mode 100644 relays/client-substrate/src/metrics/float_storage_value.rs create mode 100644 relays/client-substrate/src/metrics/mod.rs create mode 100644 relays/client-substrate/src/metrics/storage_proof_overhead.rs create mode 100644 relays/utils/src/metrics/float_json_value.rs diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index c96b6f610db91..9162596e7c969 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -35,9 +35,12 @@ use sp_core::storage::StorageKey; use sp_runtime::{FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; +/// Initial value of `RialtoToMillauConversionRate` parameter. +pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); + parameter_types! { /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. - storage RialtoToMillauConversionRate: FixedU128 = FixedU128::one(); + pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE; } /// Storage key of the Millau -> Rialto message in the runtime storage. diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 90a79891e6b8d..62f4ec714747e 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -35,9 +35,12 @@ use sp_core::storage::StorageKey; use sp_runtime::{FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; +/// Initial value of `MillauToRialtoConversionRate` parameter. +pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); + parameter_types! { /// Millau to Rialto conversion rate. Initially we treat both tokens as equal. - storage MillauToRialtoConversionRate: FixedU128 = 1.into(); + pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE; } /// Storage key of the Rialto -> Millau message in the runtime storage. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 5d5469017dfeb..e7f990d283096 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -24,7 +24,7 @@ use sp_io::hashing::blake2_256; use sp_std::convert::TryFrom; pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; -pub use storage_proof::StorageProofChecker; +pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index 813eab0789baa..18470512b5d6b 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -66,7 +66,7 @@ pub struct EthereumExchangeParams { /// Relay working mode. pub mode: ExchangeRelayMode, /// Metrics parameters. - pub metrics_params: Option, + pub metrics_params: MetricsParams, /// Instance of the bridge pallet being synchronized. pub instance: Arc, } diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index 0fbe378259814..3dcd27e18f6be 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -72,7 +72,7 @@ pub struct EthereumSyncParams { /// Synchronization parameters. pub sync_params: HeadersSyncParams, /// Metrics parameters. - pub metrics_params: Option, + pub metrics_params: MetricsParams, /// Instance of the bridge pallet being synchronized. pub instance: Arc, } diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index d1171d1461d47..234e1237fcf55 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -34,7 +34,10 @@ use ethereum_sync_loop::EthereumSyncParams; use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; use instances::{BridgeInstance, Kovan, RialtoPoA}; -use relay_utils::{initialize::initialize_relay, metrics::MetricsParams}; +use relay_utils::{ + initialize::initialize_relay, + metrics::{MetricsAddress, MetricsParams}, +}; use secp256k1::SecretKey; use sp_core::crypto::Pair; use substrate_sync_loop::SubstrateSyncParams; @@ -367,12 +370,12 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result Result, String> { +fn metrics_params(matches: &clap::ArgMatches) -> Result { if matches.is_present("no-prometheus") { - return Ok(None); + return Ok(None.into()); } - let mut metrics_params = MetricsParams::default(); + let mut metrics_params = MetricsAddress::default(); if let Some(prometheus_host) = matches.value_of("prometheus-host") { metrics_params.host = prometheus_host.into(); @@ -383,7 +386,7 @@ fn metrics_params(matches: &clap::ArgMatches) -> Result, S .map_err(|e| format!("Failed to parse prometheus-port: {}", e))?; } - Ok(Some(metrics_params)) + Ok(Some(metrics_params).into()) } fn instance_params(matches: &clap::ArgMatches) -> Result, String> { diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index 0765cca031569..c0f44da3dff82 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -68,7 +68,7 @@ pub struct SubstrateSyncParams { /// Synchronization parameters. pub sync_params: HeadersSyncParams, /// Metrics parameters. - pub metrics_params: Option, + pub metrics_params: MetricsParams, } /// Substrate synchronization pipeline. diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 216b778c21832..ebceb3a25e0a2 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -330,15 +330,16 @@ pub struct PrometheusParams { pub prometheus_port: u16, } -impl From for Option { - fn from(cli_params: PrometheusParams) -> Option { +impl From for relay_utils::metrics::MetricsParams { + fn from(cli_params: PrometheusParams) -> relay_utils::metrics::MetricsParams { if !cli_params.no_prometheus { - Some(relay_utils::metrics::MetricsParams { + Some(relay_utils::metrics::MetricsAddress { host: cli_params.prometheus_host, port: cli_params.prometheus_port, }) + .into() } else { - None + None.into() } } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 6c2b2f1d66d8a..44b9b70d2b993 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use crate::finality_pipeline::SubstrateFinalitySyncPipeline; use structopt::{clap::arg_enum, StructOpt}; /// Start headers relayer process. @@ -77,12 +78,13 @@ impl RelayHeaders { let source_client = self.source.into_client::().await?; let target_client = self.target.into_client::().await?; let target_sign = self.target_sign.into_keypair::()?; + let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; crate::finality_pipeline::run( Finality::new(target_client.clone(), target_sign), source_client, target_client, - self.prometheus_params.into(), + metrics_params, ) .await }) diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index 0b035cd57f2aa..bc8461f6a8385 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -21,7 +21,7 @@ use crate::finality_target::SubstrateFinalityTarget; use bp_header_chain::justification::GrandpaJustification; use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; use relay_substrate_client::{finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader}; -use relay_utils::BlockNumberBase; +use relay_utils::{metrics::MetricsParams, BlockNumberBase}; use sp_core::Bytes; use std::{fmt::Debug, marker::PhantomData, time::Duration}; @@ -41,6 +41,11 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { /// Chain with GRANDPA bridge pallet. type TargetChain: Chain; + /// Customize metrics exposed by headers sync loop. + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + Ok(params) + } + /// Returns id of account that we're using to sign transactions at target chain. fn transactions_author(&self) -> ::AccountId; @@ -107,7 +112,7 @@ pub async fn run( pipeline: P, source_client: Client, target_client: Client, - metrics_params: Option, + metrics_params: MetricsParams, ) -> anyhow::Result<()> where P: SubstrateFinalitySyncPipeline< diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index ba68b9e490a8d..0e80aacc176da 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -29,7 +29,10 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{ + metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, + Chain, TransactionSignScheme, +}; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -135,7 +138,7 @@ pub async fn run( rialto_client: RialtoClient, rialto_sign: RialtoSigningParams, lane_id: LaneId, - metrics_params: Option, + metrics_params: MetricsParams, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_millau = millau_sign.public().as_array_ref().clone().into(); @@ -185,9 +188,27 @@ pub async fn run( max_messages_size_in_single_batch, }, }, - MillauSourceClient::new(millau_client, lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), + MillauSourceClient::new(millau_client.clone(), lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), RialtoTargetClient::new(rialto_client, lane, lane_id, MILLAU_BRIDGE_INSTANCE), - metrics_params, + relay_utils::relay_metrics( + messages_relay::message_lane_loop::metrics_prefix::(&lane_id), + metrics_params.address, + ) + .standalone_metric(StorageProofOverheadMetric::new( + millau_client.clone(), + (bp_runtime::RIALTO_BRIDGE_INSTANCE, lane_id), + millau_runtime::rialto_messages::inbound_lane_data_key(&lane_id), + "millau_storage_proof_overhead".into(), + "Millau storage proof overhead".into(), + ))? + .standalone_metric(FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + millau_client, + sp_core::storage::StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), + Some(millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE), + "millau_rialto_to_millau_conversion_rate".into(), + "Rialto to Millau tokens conversion rate (used by Rialto)".into(), + ))? + .into_params(), futures::future::pending(), ) .await diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index e29d23b015bf0..ed231cd208e9e 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -29,7 +29,10 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{ + metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, + Chain, TransactionSignScheme, +}; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -135,7 +138,7 @@ pub async fn run( millau_client: MillauClient, millau_sign: MillauSigningParams, lane_id: LaneId, - metrics_params: Option, + metrics_params: MetricsParams, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rialto = rialto_sign.public().as_array_ref().clone().into(); @@ -184,9 +187,27 @@ pub async fn run( max_messages_size_in_single_batch, }, }, - RialtoSourceClient::new(rialto_client, lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), + RialtoSourceClient::new(rialto_client.clone(), lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), MillauTargetClient::new(millau_client, lane, lane_id, RIALTO_BRIDGE_INSTANCE), - metrics_params, + relay_utils::relay_metrics( + messages_relay::message_lane_loop::metrics_prefix::(&lane_id), + metrics_params.address, + ) + .standalone_metric(StorageProofOverheadMetric::new( + rialto_client.clone(), + (bp_runtime::MILLAU_BRIDGE_INSTANCE, lane_id), + rialto_runtime::millau_messages::inbound_lane_data_key(&lane_id), + "rialto_storage_proof_overhead".into(), + "Rialto storage proof overhead".into(), + ))? + .standalone_metric(FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + rialto_client, + sp_core::storage::StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), + Some(rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE), + "rialto_millau_to_rialto_conversion_rate".into(), + "Millau to Rialto tokens conversion rate (used by Millau)".into(), + ))? + .into_params(), futures::future::pending(), ) .await diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index 2ba9069b2552b..ac69a7437ed3d 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -22,6 +22,7 @@ use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use sp_core::{Bytes, Pair}; @@ -33,6 +34,29 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + Ok( + relay_utils::relay_metrics(finality_relay::metrics_prefix::(), params.address) + // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama + // relays, but we want to test metrics/dashboards in advance + .standalone_metric(FloatJsonValueMetric::new( + "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), + "$.polkadot.usd".into(), + "polkadot_price".into(), + "Polkadot price in USD".into(), + )) + .map_err(|e| anyhow::format_err!("{}", e))? + .standalone_metric(FloatJsonValueMetric::new( + "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), + "$.kusama.usd".into(), + "kusama_price".into(), + "Kusama price in USD".into(), + )) + .map_err(|e| anyhow::format_err!("{}", e))? + .into_params(), + ) + } + fn transactions_author(&self) -> bp_millau::AccountId { self.target_sign.public().as_array_ref().clone().into() } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 1a06582ec1e34..07e0a9e17c391 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -29,7 +29,7 @@ use sp_runtime::{ use std::{fmt::Debug, time::Duration}; /// Substrate-based chain from minimal relay-client point of view. -pub trait Chain: ChainBase { +pub trait Chain: ChainBase + Clone { /// Chain name. const NAME: &'static str; /// Average block interval. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 289118753c408..a149ba69701f6 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -29,7 +29,7 @@ use jsonrpsee_types::{jsonrpc::DeserializeOwned, traits::SubscriptionClient}; use jsonrpsee_ws_client::{WsClient as RpcClient, WsConfig as RpcConfig, WsSubscription as Subscription}; use num_traits::Zero; use pallet_balances::AccountData; -use sp_core::Bytes; +use sp_core::{storage::StorageKey, Bytes}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; use std::ops::RangeInclusive; @@ -177,6 +177,14 @@ impl Client { Ok(Substrate::::runtime_version(&self.client).await?) } + /// Read value from runtime storage. + pub async fn storage_value(&self, storage_key: StorageKey) -> Result> { + Substrate::::get_storage(&self.client, storage_key) + .await? + .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) + .transpose() + } + /// Return native tokens balance of the account. pub async fn free_native_balance(&self, account: C::AccountId) -> Result where diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 899ce4a2b2bb6..db1cdb4374542 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -38,6 +38,8 @@ pub enum Error { AccountDoesNotExist, /// The client we're connected to is not synced, so we can't rely on its state. ClientNotSynced(Health), + /// An error has happened when we have tried to parse storage proof. + StorageProofError(bp_runtime::StorageProofError), /// Custom logic error. Custom(String), } @@ -50,6 +52,7 @@ impl std::error::Error for Error { Self::UninitializedBridgePallet => None, Self::AccountDoesNotExist => None, Self::ClientNotSynced(_) => None, + Self::StorageProofError(_) => None, Self::Custom(_) => None, } } @@ -81,6 +84,7 @@ impl std::fmt::Display for Error { Self::ResponseParseFailed(e) => e.to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), + Self::StorageProofError(e) => format!("Error when parsing storage proof: {:?}", e), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), Self::Custom(e) => e.clone(), }; diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 66a6fbdee7d7d..3bd3df9098c00 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -172,6 +172,7 @@ mod tests { SinkExt, }; + #[derive(Debug, Clone)] struct TestChain; impl bp_runtime::Chain for TestChain { diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 9190e17247b33..0f1bfb481e71a 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -27,6 +27,7 @@ mod sync_header; pub mod finality_source; pub mod guard; pub mod headers_source; +pub mod metrics; pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme}; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs new file mode 100644 index 0000000000000..e1647d4bcd51c --- /dev/null +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -0,0 +1,91 @@ +// 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 . + +use crate::chain::Chain; +use crate::client::Client; + +use async_trait::async_trait; +use codec::Decode; +use relay_utils::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, F64}; +use sp_core::storage::StorageKey; +use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; +use std::time::Duration; + +/// Storage value update interval (in blocks). +const UPDATE_INTERVAL_IN_BLOCKS: u32 = 5; + +/// Metric that represents fixed-point runtime storage value as float gauge. +#[derive(Clone, Debug)] +pub struct FloatStorageValueMetric { + client: Client, + storage_key: StorageKey, + maybe_default_value: Option, + metric: Gauge, +} + +impl FloatStorageValueMetric { + /// Create new metric. + pub fn new( + client: Client, + storage_key: StorageKey, + maybe_default_value: Option, + name: String, + help: String, + ) -> Self { + FloatStorageValueMetric { + client, + storage_key, + maybe_default_value, + metric: Gauge::new(name, help).expect( + "only fails if gauge options are customized;\ + we use default options;\ + qed", + ), + } + } +} + +impl Metrics for FloatStorageValueMetric { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.metric.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + +#[async_trait] +impl StandaloneMetrics for FloatStorageValueMetric +where + T: 'static + Decode + Send + Sync + FixedPointNumber, +{ + fn update_interval(&self) -> Duration { + C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS + } + + async fn update(&self) { + relay_utils::metrics::set_gauge_value( + &self.metric, + self.client + .storage_value::(self.storage_key.clone()) + .await + .map(|maybe_storage_value| { + maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { + storage_value.into_inner().unique_saturated_into() as f64 + / T::DIV.unique_saturated_into() as f64 + }) + }), + ); + } +} diff --git a/relays/client-substrate/src/metrics/mod.rs b/relays/client-substrate/src/metrics/mod.rs new file mode 100644 index 0000000000000..177e2a709cf2d --- /dev/null +++ b/relays/client-substrate/src/metrics/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2019-2020 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 . + +//! Contains several Substrate-specific metrics that may be exposed by relay. + +pub use float_storage_value::FloatStorageValueMetric; +pub use storage_proof_overhead::StorageProofOverheadMetric; + +mod float_storage_value; +mod storage_proof_overhead; diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs new file mode 100644 index 0000000000000..167f59605d27e --- /dev/null +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -0,0 +1,135 @@ +// 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 . + +use crate::chain::Chain; +use crate::client::Client; +use crate::error::Error; + +use async_trait::async_trait; +use bp_messages::LaneId; +use bp_runtime::InstanceId; +use relay_utils::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, U64}; +use sp_core::storage::StorageKey; +use sp_runtime::traits::Header as HeaderT; +use sp_trie::StorageProof; +use std::time::Duration; + +/// Storage proof overhead update interval (in blocks). +const UPDATE_INTERVAL_IN_BLOCKS: u32 = 100; + +/// Metric that represents extra size of storage proof as unsigned integer gauge. +/// +/// Regular Substrate node does not provide any RPC endpoints that return storage proofs. +/// So here we're using our own `pallet-bridge-messages-rpc` RPC API, which returns proof +/// of the inbound message lane state. Then we simply subtract size of this state from +/// the size of storage proof to compute metric value. +/// +/// There are two things to keep in mind when using this metric: +/// +/// 1) it'll only work on inbound lanes that have already accepted at least one message; +/// 2) the overhead may be slightly different for other values, but this metric gives a good estimation. +#[derive(Debug)] +pub struct StorageProofOverheadMetric { + client: Client, + inbound_lane: (InstanceId, LaneId), + inbound_lane_data_key: StorageKey, + metric: Gauge, +} + +impl Clone for StorageProofOverheadMetric { + fn clone(&self) -> Self { + StorageProofOverheadMetric { + client: self.client.clone(), + inbound_lane: self.inbound_lane, + inbound_lane_data_key: self.inbound_lane_data_key.clone(), + metric: self.metric.clone(), + } + } +} + +impl StorageProofOverheadMetric { + /// Create new metric instance with given name and help. + pub fn new( + client: Client, + inbound_lane: (InstanceId, LaneId), + inbound_lane_data_key: StorageKey, + name: String, + help: String, + ) -> Self { + StorageProofOverheadMetric { + client, + inbound_lane, + inbound_lane_data_key, + metric: Gauge::new(name, help).expect( + "only fails if gauge options are customized;\ + we use default options;\ + qed", + ), + } + } + + /// Returns approximate storage proof size overhead. + /// + /// Returs `Ok(None)` if inbound lane we're watching for has no state. This shouldn't be treated as error. + async fn compute_storage_proof_overhead(&self) -> Result, Error> { + let best_header_hash = self.client.best_finalized_header_hash().await?; + let best_header = self.client.header_by_hash(best_header_hash).await?; + + let storage_proof = self + .client + .prove_messages_delivery(self.inbound_lane.0, self.inbound_lane.1, best_header_hash) + .await?; + let storage_proof_size: usize = storage_proof.iter().map(|n| n.len()).sum(); + + let storage_value_reader = bp_runtime::StorageProofChecker::::new( + *best_header.state_root(), + StorageProof::new(storage_proof), + ) + .map_err(Error::StorageProofError)?; + let maybe_encoded_storage_value = storage_value_reader + .read_value(&self.inbound_lane_data_key.0) + .map_err(Error::StorageProofError)?; + let encoded_storage_value_size = match maybe_encoded_storage_value { + Some(encoded_storage_value) => encoded_storage_value.len(), + None => return Ok(None), + }; + + Ok(Some(storage_proof_size - encoded_storage_value_size)) + } +} + +impl Metrics for StorageProofOverheadMetric { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.metric.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + +#[async_trait] +impl StandaloneMetrics for StorageProofOverheadMetric { + fn update_interval(&self) -> Duration { + C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS + } + + async fn update(&self) { + relay_utils::metrics::set_gauge_value( + &self.metric, + self.compute_storage_proof_overhead() + .await + .map(|v| v.map(|overhead| overhead as u64)), + ); + } +} diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 3ef6503353f6f..7bb4abb7461b6 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -83,16 +83,19 @@ pub async fn run( storage: impl TransactionProofsRelayStorage>, source_client: impl SourceClient

, target_client: impl TargetClient

, - metrics_params: Option, + metrics_params: MetricsParams, exit_signal: impl Future, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics(format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME)) + .with_metrics( + format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), + metrics_params, + ) .loop_metric(ExchangeLoopMetrics::default())? .standalone_metric(GlobalMetrics::default())? - .expose(metrics_params) + .expose() .await? .run(|source_client, target_client, metrics| { run_until_connection_lost( @@ -303,7 +306,7 @@ mod tests { storage, source, target, - None, + MetricsParams::disabled(), exit_receiver.into_future().map(|(_, _)| ()), )); } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 512c51b4b2423..e0ad8a7c1b6d1 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -90,20 +90,25 @@ pub trait TargetClient: RelayClient { async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), Self::Error>; } +/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop. +pub fn metrics_prefix() -> String { + format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) +} + /// Run finality proofs synchronization loop. pub async fn run( source_client: impl SourceClient

, target_client: impl TargetClient

, sync_params: FinalitySyncParams, - metrics_params: Option, + metrics_params: MetricsParams, exit_signal: impl Future, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics(format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME)) + .with_metrics(metrics_prefix::

(), metrics_params) .loop_metric(SyncLoopMetrics::default())? .standalone_metric(GlobalMetrics::default())? - .expose(metrics_params) + .expose() .await? .run(|source_client, target_client, metrics| { run_until_connection_lost( diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index e19f924376d72..eedd902003308 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -27,7 +27,7 @@ use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; use async_trait::async_trait; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; -use relay_utils::{relay_loop::Client as RelayClient, MaybeConnectionError}; +use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, MaybeConnectionError}; use std::{collections::HashMap, pin::Pin, sync::Arc, time::Duration}; type IsMandatory = bool; @@ -206,7 +206,7 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync source_client, target_client, sync_params, - None, + MetricsParams::disabled(), exit_receiver.into_future().map(|(_, _)| ()), )); diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index f58774997601a..d5048aa1607d5 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -19,7 +19,7 @@ //! are still submitted to the target node, but are treated as auxiliary data as we are not trying //! to submit all source headers to the target node. -pub use crate::finality_loop::{run, FinalitySyncParams, SourceClient, TargetClient}; +pub use crate::finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}; use bp_header_chain::FinalityProof; use std::fmt::Debug; diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index 0e535d8caae5d..2e0d12ec87c8f 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -119,15 +119,15 @@ pub async fn run>( target_tick: Duration, sync_maintain: impl SyncMaintain

, sync_params: HeadersSyncParams, - metrics_params: Option, + metrics_params: MetricsParams, exit_signal: impl Future, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics(format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME)) + .with_metrics(format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), metrics_params) .loop_metric(SyncLoopMetrics::default())? .standalone_metric(GlobalMetrics::default())? - .expose(metrics_params) + .expose() .await? .run(|source_client, target_client, metrics| { run_until_connection_lost( diff --git a/relays/headers/src/sync_loop_tests.rs b/relays/headers/src/sync_loop_tests.rs index ff56dc45d2326..3347c4d0d3bd0 100644 --- a/relays/headers/src/sync_loop_tests.rs +++ b/relays/headers/src/sync_loop_tests.rs @@ -24,7 +24,8 @@ use backoff::backoff::Backoff; use futures::{future::FutureExt, stream::StreamExt}; use parking_lot::Mutex; use relay_utils::{ - process_future_result, relay_loop::Client as RelayClient, retry_backoff, HeaderId, MaybeConnectionError, + metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, retry_backoff, HeaderId, + MaybeConnectionError, }; use std::{ collections::{HashMap, HashSet}, @@ -500,7 +501,7 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { test_tick(), (), crate::sync::tests::default_sync_params(), - None, + MetricsParams::disabled(), exit_receiver.into_future().map(|(_, _)| ()), )); } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 24a5314d23043..daa74b50735b3 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -211,26 +211,31 @@ pub struct ClientsState { pub target: Option>, } +/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop. +pub fn metrics_prefix(lane: &LaneId) -> String { + format!( + "{}_to_{}_MessageLane_{}", + P::SOURCE_NAME, + P::TARGET_NAME, + hex::encode(lane) + ) +} + /// Run message lane service loop. pub async fn run( params: Params, source_client: impl SourceClient

, target_client: impl TargetClient

, - metrics_params: Option, + metrics_params: MetricsParams, exit_signal: impl Future, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) - .with_metrics(format!( - "{}_to_{}_MessageLane_{}", - P::SOURCE_NAME, - P::TARGET_NAME, - hex::encode(params.lane) - )) + .with_metrics(metrics_prefix::

(¶ms.lane), metrics_params) .loop_metric(MessageLaneLoopMetrics::default())? .standalone_metric(GlobalMetrics::default())? - .expose(metrics_params) + .expose() .await? .run(|source_client, target_client, metrics| { run_until_connection_lost( @@ -722,7 +727,7 @@ pub(crate) mod tests { }, source_client, target_client, - None, + MetricsParams::disabled(), exit_signal, ) .await; diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ce6a20bbc4fee..ff80cab533813 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -10,10 +10,13 @@ ansi_term = "0.12" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" +isahc = "1.2" env_logger = "0.8.2" futures = "0.3.5" +jsonpath_lib = "0.2" log = "0.4.11" num-traits = "0.2" +serde_json = "1.0" sysinfo = "0.15" time = "0.2" diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index ab913b758ddf1..446e00cd23e67 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -16,7 +16,7 @@ //! Utilities used by different relays. -pub use relay_loop::relay_loop; +pub use relay_loop::{relay_loop, relay_metrics}; use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::future::FutureExt; diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 41df88ecd0036..789ff8a108502 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -14,23 +14,37 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +pub use float_json_value::FloatJsonValueMetric; pub use global::GlobalMetrics; -pub use substrate_prometheus_endpoint::{register, Counter, CounterVec, Gauge, GaugeVec, Opts, Registry, F64, U64}; +pub use substrate_prometheus_endpoint::{ + prometheus::core::{Atomic, Collector}, + register, Counter, CounterVec, Gauge, GaugeVec, Opts, Registry, F64, U64, +}; use async_trait::async_trait; -use std::time::Duration; +use std::{fmt::Debug, time::Duration}; +mod float_json_value; mod global; -/// Prometheus endpoint MetricsParams. +/// Unparsed address that needs to be used to expose Prometheus metrics. #[derive(Debug, Clone)] -pub struct MetricsParams { +pub struct MetricsAddress { /// Serve HTTP requests at given host. pub host: String, /// Serve HTTP requests at given port. pub port: u16, } +/// Prometheus endpoint MetricsParams. +#[derive(Debug, Clone)] +pub struct MetricsParams { + /// Interface and TCP port to be used when exposing Prometheus metrics. + pub address: Option, + /// Metrics registry. May be `Some(_)` if several components share the same endpoint. + pub registry: Option, +} + /// Metrics API. pub trait Metrics: Clone + Send + Sync + 'static { /// Register metrics in the registry. @@ -61,11 +75,64 @@ pub trait StandaloneMetrics: Metrics { } } -impl Default for MetricsParams { +impl Default for MetricsAddress { fn default() -> Self { - MetricsParams { + MetricsAddress { host: "127.0.0.1".into(), port: 9616, } } } + +impl MetricsParams { + /// Creates metrics params so that metrics are not exposed. + pub fn disabled() -> Self { + MetricsParams { + address: None, + registry: None, + } + } +} + +impl From> for MetricsParams { + fn from(address: Option) -> Self { + MetricsParams { + address, + registry: None, + } + } +} + +/// Set value of gauge metric. +/// +/// If value is `Ok(None)` or `Err(_)`, metric would have default value. +pub fn set_gauge_value, E: Debug>(gauge: &Gauge, value: Result, E>) { + gauge.set(match value { + Ok(Some(value)) => { + log::trace!( + target: "bridge-metrics", + "Updated value of metric '{:?}': {:?}", + gauge.desc().first().map(|d| &d.fq_name), + value, + ); + value + } + Ok(None) => { + log::warn!( + target: "bridge-metrics", + "Failed to update metric '{:?}': value is empty", + gauge.desc().first().map(|d| &d.fq_name), + ); + Default::default() + } + Err(error) => { + log::warn!( + target: "bridge-metrics", + "Failed to update metric '{:?}': {:?}", + gauge.desc().first().map(|d| &d.fq_name), + error, + ); + Default::default() + } + }) +} diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs new file mode 100644 index 0000000000000..902b3e819509d --- /dev/null +++ b/relays/utils/src/metrics/float_json_value.rs @@ -0,0 +1,125 @@ +// Copyright 2019-2020 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 . + +use crate::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, F64}; + +use async_trait::async_trait; +use std::time::Duration; + +/// Value update interval. +const UPDATE_INTERVAL: Duration = Duration::from_secs(60); + +/// Metric that represents float value received from HTTP service as float gauge. +#[derive(Debug, Clone)] +pub struct FloatJsonValueMetric { + url: String, + json_path: String, + metric: Gauge, +} + +impl FloatJsonValueMetric { + /// Create new metric instance with given name and help. + pub fn new(url: String, json_path: String, name: String, help: String) -> Self { + FloatJsonValueMetric { + url, + json_path, + metric: Gauge::new(name, help).expect( + "only fails if gauge options are customized;\ + we use default options;\ + qed", + ), + } + } + + /// Read value from HTTP service. + async fn read_value(&self) -> Result { + use isahc::{AsyncReadResponseExt, HttpClient, Request}; + + fn map_isahc_err(err: impl std::fmt::Display) -> String { + format!("Failed to fetch token price from remote server: {}", err) + } + + let request = Request::get(&self.url) + .header("Accept", "application/json") + .body(()) + .map_err(map_isahc_err)?; + let raw_response = HttpClient::new() + .map_err(map_isahc_err)? + .send_async(request) + .await + .map_err(map_isahc_err)? + .text() + .await + .map_err(map_isahc_err)?; + + parse_service_response(&self.json_path, &raw_response) + } +} + +impl Metrics for FloatJsonValueMetric { + fn register(&self, registry: &Registry) -> Result<(), String> { + register(self.metric.clone(), registry).map_err(|e| e.to_string())?; + Ok(()) + } +} + +#[async_trait] +impl StandaloneMetrics for FloatJsonValueMetric { + fn update_interval(&self) -> Duration { + UPDATE_INTERVAL + } + + async fn update(&self) { + crate::metrics::set_gauge_value(&self.metric, self.read_value().await.map(Some)); + } +} + +/// Parse HTTP service response. +fn parse_service_response(json_path: &str, response: &str) -> Result { + let json = serde_json::from_str(response).map_err(|err| { + format!( + "Failed to parse HTTP service response: {:?}. Response: {:?}", + err, response, + ) + })?; + + let mut selector = jsonpath_lib::selector(&json); + let maybe_selected_value = selector(json_path).map_err(|err| { + format!( + "Failed to select value from response: {:?}. Response: {:?}", + err, response, + ) + })?; + let selected_value = maybe_selected_value + .first() + .and_then(|v| v.as_f64()) + .ok_or_else(|| format!("Missing required value from response: {:?}", response,))?; + + Ok(selected_value) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_service_response_works() { + assert_eq!( + parse_service_response("$.kusama.usd", r#"{"kusama":{"usd":433.05}}"#).map_err(drop), + Ok(433.05), + ); + } +} diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs index c19ac8d46819b..98c7d9a570c0e 100644 --- a/relays/utils/src/metrics/global.rs +++ b/relays/utils/src/metrics/global.rs @@ -16,12 +16,11 @@ //! Global system-wide Prometheus metrics exposed by relays. -use crate::metrics::{Metrics, StandaloneMetrics}; +use crate::metrics::{register, Gauge, GaugeVec, Metrics, Opts, Registry, StandaloneMetrics, F64, U64}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use std::time::Duration; -use substrate_prometheus_endpoint::{register, Gauge, GaugeVec, Opts, Registry, F64, U64}; use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; /// Global metrics update interval. @@ -79,7 +78,7 @@ impl StandaloneMetrics for GlobalMetrics { } _ => { log::warn!( - target: "bridge", + target: "bridge-metrics", "Failed to refresh process information. Metrics may show obsolete values", ); } diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 04077bf08aadc..1a8d63e1dbe76 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{Metrics, MetricsParams, StandaloneMetrics}; +use crate::metrics::{Metrics, MetricsAddress, MetricsParams, StandaloneMetrics}; use crate::{FailedClient, MaybeConnectionError}; use async_trait::async_trait; @@ -44,6 +44,24 @@ pub fn relay_loop(source_client: SC, target_client: TC) -> Loop) -> LoopMetrics<(), (), ()> { + assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); + + LoopMetrics { + relay_loop: Loop { + reconnect_delay: RECONNECT_DELAY, + source_client: (), + target_client: (), + loop_metric: None, + }, + address, + registry: Registry::new_custom(Some(prefix), None) + .expect("only fails if prefix is empty; prefix is not empty; qed"), + loop_metric: None, + } +} + /// Generic relay loop. pub struct Loop { reconnect_delay: Duration, @@ -55,6 +73,7 @@ pub struct Loop { /// Relay loop metrics builder. pub struct LoopMetrics { relay_loop: Loop, + address: Option, registry: Registry, loop_metric: Option, } @@ -69,7 +88,7 @@ impl Loop { /// Start building loop metrics using given prefix. /// /// Panics if `prefix` is empty. - pub fn with_metrics(self, prefix: String) -> LoopMetrics { + pub fn with_metrics(self, prefix: String, params: MetricsParams) -> LoopMetrics { assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); LoopMetrics { @@ -79,8 +98,12 @@ impl Loop { target_client: self.target_client, loop_metric: None, }, - registry: Registry::new_custom(Some(prefix), None) - .expect("only fails if prefix is empty; prefix is not empty; qed"), + address: params.address, + registry: match params.registry { + Some(registry) => registry, + None => Registry::new_custom(Some(prefix), None) + .expect("only fails if prefix is empty; prefix is not empty; qed"), + }, loop_metric: None, } } @@ -159,6 +182,7 @@ impl LoopMetrics { Ok(LoopMetrics { relay_loop: self.relay_loop, + address: self.address, registry: self.registry, loop_metric: Some(loop_metric), }) @@ -171,19 +195,27 @@ impl LoopMetrics { Ok(self) } - /// Expose metrics using given params. + /// Convert into `MetricsParams` structure so that metrics registry may be extended later. + pub fn into_params(self) -> MetricsParams { + MetricsParams { + address: self.address, + registry: Some(self.registry), + } + } + + /// Expose metrics using address passed at creation. /// - /// If `params` is `None`, metrics are not exposed. - pub async fn expose(self, params: Option) -> Result, String> { - if let Some(params) = params { + /// If passed `address` is `None`, metrics are not exposed. + pub async fn expose(self) -> Result, String> { + if let Some(address) = self.address { let socket_addr = SocketAddr::new( - params.host.parse().map_err(|err| { + address.host.parse().map_err(|err| { format!( "Invalid host {} is used to expose Prometheus metrics: {}", - params.host, err, + address.host, err, ) })?, - params.port, + address.port, ); let registry = self.registry; From 22654feeb1f2c5933cc682ecbf69179630159f31 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Apr 2021 06:19:23 -0400 Subject: [PATCH 0409/1210] Remove Substrate Pallet (#866) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove `pallet-substrate-bridge` * Fix transfer call encoding test Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/chain_spec.rs | 9 +- bin/millau/runtime/Cargo.toml | 2 - bin/millau/runtime/src/lib.rs | 29 - bin/rialto/node/src/chain_spec.rs | 9 +- bin/rialto/runtime/Cargo.toml | 2 - bin/rialto/runtime/src/lib.rs | 29 - modules/grandpa/Cargo.toml | 1 - modules/substrate/Cargo.toml | 55 - modules/substrate/src/fork_tests.rs | 512 --------- modules/substrate/src/lib.rs | 1040 ------------------- modules/substrate/src/mock.rs | 117 --- modules/substrate/src/storage.rs | 80 -- modules/substrate/src/verifier.rs | 855 --------------- relays/bin-substrate/src/cli/encode_call.rs | 2 +- relays/client-millau/src/lib.rs | 2 - relays/client-rialto/src/lib.rs | 2 - 16 files changed, 5 insertions(+), 2741 deletions(-) delete mode 100644 modules/substrate/Cargo.toml delete mode 100644 modules/substrate/src/fork_tests.rs delete mode 100644 modules/substrate/src/lib.rs delete mode 100644 modules/substrate/src/mock.rs delete mode 100644 modules/substrate/src/storage.rs delete mode 100644 modules/substrate/src/verifier.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 64dca2f255011..df790c7580bb8 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -16,8 +16,8 @@ use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeRialtoConfig, BridgeWestendGrandpaConfig, GenesisConfig, - GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, + SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -167,11 +167,6 @@ fn testnet_genesis( pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), - pallet_substrate_bridge: Some(BridgeRialtoConfig { - // We'll initialize the pallet with a dispatchable instead. - init_data: None, - owner: Some(root_key.clone()), - }), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { keys: initial_authorities diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index a1406d69d8947..411835ab6fec7 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -25,7 +25,6 @@ pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } -pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } # Substrate Dependencies @@ -83,7 +82,6 @@ std = [ "pallet-randomness-collective-flip/std", "pallet-session/std", "pallet-shift-session-manager/std", - "pallet-substrate-bridge/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index ed622e7eea2c8..b627cce404063 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -65,7 +65,6 @@ pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaRialtoCall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaWestendCall; pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_substrate_bridge::Call as BridgeRialtoCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -301,10 +300,6 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } -impl pallet_substrate_bridge::Config for Runtime { - type BridgedChain = bp_rialto::Rialto; -} - parameter_types! { // This is a pretty unscientific cap. // @@ -383,7 +378,6 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialto: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeRialtoMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, BridgeRialtoGrandpa: pallet_bridge_grandpa::{Module, Call, Storage}, @@ -563,29 +557,6 @@ impl_runtime_apis! { } } - impl bp_rialto::RialtoHeaderApi for Runtime { - fn best_blocks() -> Vec<(bp_rialto::BlockNumber, bp_rialto::Hash)> { - BridgeRialto::best_headers() - } - - fn finalized_block() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { - let header = BridgeRialto::best_finalized(); - (header.number, header.hash()) - } - - fn incomplete_headers() -> Vec<(bp_rialto::BlockNumber, bp_rialto::Hash)> { - BridgeRialto::require_justifications() - } - - fn is_known_block(hash: bp_rialto::Hash) -> bool { - BridgeRialto::is_known_header(hash) - } - - fn is_finalized_block(hash: bp_rialto::Hash) -> bool { - BridgeRialto::is_finalized_header(hash) - } - } - impl bp_rialto::RialtoFinalityApi for Runtime { fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { let header = BridgeRialtoGrandpa::best_finalized(); diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 2794496fc35c1..14b2c3b84c33b 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -16,8 +16,8 @@ use bp_rialto::derive_account_from_millau_id; use rialto_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauConfig, BridgeRialtoPoAConfig, GenesisConfig, - GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoAConfig, GenesisConfig, GrandpaConfig, + SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -169,11 +169,6 @@ fn testnet_genesis( pallet_grandpa: Some(GrandpaConfig { authorities: Vec::new(), }), - pallet_substrate_bridge: Some(BridgeMillauConfig { - // We'll initialize the pallet with a dispatchable instead. - init_data: None, - owner: Some(root_key.clone()), - }), pallet_sudo: Some(SudoConfig { key: root_key }), pallet_session: Some(SessionConfig { keys: initial_authorities diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 74365eec899c3..ea8c51d0e8c00 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -31,7 +31,6 @@ pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } -pallet-substrate-bridge = { path = "../../../modules/substrate", default-features = false } # Substrate Dependencies @@ -100,7 +99,6 @@ std = [ "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", - "pallet-substrate-bridge/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 39693de2c0b5b..5fd10b12de9a6 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -72,7 +72,6 @@ pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall; pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_substrate_bridge::Call as BridgeMillauCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -407,10 +406,6 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } -impl pallet_substrate_bridge::Config for Runtime { - type BridgedChain = bp_millau::Millau; -} - parameter_types! { // This is a pretty unscientific cap. // @@ -480,7 +475,6 @@ construct_runtime!( BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, - BridgeMillau: pallet_substrate_bridge::{Module, Call, Storage, Config}, BridgeMillauGrandpa: pallet_bridge_grandpa::{Module, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, BridgeMillauMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, @@ -619,29 +613,6 @@ impl_runtime_apis! { } } - impl bp_millau::MillauHeaderApi for Runtime { - fn best_blocks() -> Vec<(bp_millau::BlockNumber, bp_millau::Hash)> { - BridgeMillau::best_headers() - } - - fn finalized_block() -> (bp_millau::BlockNumber, bp_millau::Hash) { - let header = BridgeMillau::best_finalized(); - (header.number, header.hash()) - } - - fn incomplete_headers() -> Vec<(bp_millau::BlockNumber, bp_millau::Hash)> { - BridgeMillau::require_justifications() - } - - fn is_known_block(hash: bp_millau::Hash) -> bool { - BridgeMillau::is_known_header(hash) - } - - fn is_finalized_block(hash: bp_millau::Hash) -> bool { - BridgeMillau::is_finalized_header(hash) - } - } - impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { let header = BridgeMillauGrandpa::best_finalized(); diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 1191c8c8fcf49..810dce3dd5a4c 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -33,7 +33,6 @@ bp-test-utils = { path = "../../primitives/test-utils", default-features = false frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } [dev-dependencies] -pallet-substrate-bridge = { path = "../../modules/substrate" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] diff --git a/modules/substrate/Cargo.toml b/modules/substrate/Cargo.toml deleted file mode 100644 index bcd9faaede768..0000000000000 --- a/modules/substrate/Cargo.toml +++ /dev/null @@ -1,55 +0,0 @@ -[package] -name = "pallet-substrate-bridge" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -finality-grandpa = { version = "0.14.0", default-features = false } -hash-db = { version = "0.15.2", default-features = false } -log = { version = "0.4.14", default-features = false } -serde = { version = "1.0", optional = true } - -# Bridge Dependencies - -bp-header-chain = { path = "../../primitives/header-chain", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-finality-grandpa = { 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-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] -bp-test-utils = {path = "../../primitives/test-utils" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } - -[features] -default = ["std"] -std = [ - "bp-header-chain/std", - "bp-runtime/std", - "bp-header-chain/std", - "codec/std", - "finality-grandpa/std", - "frame-support/std", - "frame-system/std", - "hash-db/std", - "log/std", - "serde", - "sp-finality-grandpa/std", - "sp-runtime/std", - "sp-std/std", - "sp-trie/std", -] -runtime-benchmarks = [] diff --git a/modules/substrate/src/fork_tests.rs b/modules/substrate/src/fork_tests.rs deleted file mode 100644 index 58b9749620a21..0000000000000 --- a/modules/substrate/src/fork_tests.rs +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright 2020-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 . - -//! Tests for checking that behaviour of importing headers and finality proofs works correctly. -//! -//! The tests are built around the idea that we will be importing headers on different forks and we -//! should be able to check that we're correctly importing headers, scheduling changes, and -//! finalizing headers across different forks. -//! -//! Each test is depicted using beautiful ASCII art. The symbols used in the tests are the -//! following: -//! -//! - S|N: Schedules change in N blocks -//! - E: Enacts change -//! - F: Finalized -//! - FN: Finality proof imported for header N -//! -//! Each diagram also comes with an import order. This is important since we expect things to fail -//! when headers or proofs are imported in a certain order. -//! -//! Tests can be read as follows: -//! -//! ## Example Import 1 -//! -//! (Type::Header(2, 1, None, None), Ok(())) -//! -//! Import header 2 on fork 1. This does not create a fork, or schedule an authority set change. We -//! expect this header import to be succesful. -//! -//! ## Example Import 2 -//! -//! (Type::Header(4, 2, Some((3, 1)), Some(0)), Ok(())) -//! -//! Import header 4 on fork 2. This header starts a new fork from header 3 on fork 1. It also -//! schedules a change with a delay of 0 blocks. It should be succesfully imported. -//! -//! ## Example Import 3 -//! -//! (Type::Finality(2, 1), Err(FinalizationError::OldHeader.into())) -//! -//! Import a finality proof for header 2 on fork 1. This finalty proof should fail to be imported -//! because the header is an old header. - -use crate::mock::*; -use crate::storage::ImportedHeader; -use crate::verifier::*; -use crate::{BestFinalized, BestHeight, BridgeStorage, NextScheduledChange, PalletStorage}; -use bp_header_chain::AuthoritySet; -use bp_test_utils::{authority_list, make_default_justification, ALICE, BOB}; -use codec::Encode; -use frame_support::{IterableStorageMap, StorageValue}; -use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; -use sp_runtime::{Digest, DigestItem}; -use std::collections::BTreeMap; - -type ForkId = u64; -type Delay = u64; - -// Indicates when to start a new fork. The first item in the tuple -// will be the parent header of the header starting this fork. -type ForksAt = Option<(TestNumber, ForkId)>; -type ScheduledChangeAt = Option; - -#[derive(Debug)] -enum Type { - Header(TestNumber, ForkId, ForksAt, ScheduledChangeAt), - Finality(TestNumber, ForkId), -} - -// Order: 1, 2, 2', 3, 3'' -// -// / [3''] -// / [2'] -// [1] <- [2] <- [3] -#[test] -fn fork_can_import_headers_on_different_forks() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, None), Ok(())), - (Type::Header(2, 2, Some((1, 1)), None), Ok(())), - (Type::Header(3, 1, None, None), Ok(())), - (Type::Header(3, 3, Some((2, 2)), None), Ok(())), - ]; - - create_chain(&mut storage, &mut chain); - - let best_headers = storage.best_headers(); - assert_eq!(best_headers.len(), 2); - assert_eq!(>::get(), 3); - }) -} - -// Order: 1, 2, 2', F2, F2' -// -// [1] <- [2: F] -// \ [2'] -// -// Not allowed to finalize 2' -#[test] -fn fork_does_not_allow_competing_finality_proofs() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, None), Ok(())), - (Type::Header(2, 2, Some((1, 1)), None), Ok(())), - (Type::Finality(2, 1), Ok(())), - (Type::Finality(2, 2), Err(FinalizationError::OldHeader.into())), - ]; - - create_chain(&mut storage, &mut chain); - }) -} - -// Order: 1, 2, 3, F2, 3 -// -// [1] <- [2: S|0] <- [3] -// -// Not allowed to import 3 until we get F2 -// -// Note: GRANDPA would technically allow 3 to be imported as long as it didn't try and enact an -// authority set change. However, since we expect finality proofs to be imported quickly we've -// decided to simplify our import process and disallow header imports until we get a finality proof. -#[test] -fn fork_waits_for_finality_proof_before_importing_header_past_one_which_enacts_a_change() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(0)), Ok(())), - ( - Type::Header(3, 1, None, None), - Err(ImportError::AwaitingFinalityProof.into()), - ), - (Type::Finality(2, 1), Ok(())), - (Type::Header(3, 1, None, None), Ok(())), - ]; - - create_chain(&mut storage, &mut chain); - }) -} - -// Order: 1, 2, F2, 3 -// -// [1] <- [2: S|1] <- [3: S|0] -// -// GRANDPA can have multiple authority set changes pending on the same fork. However, we've decided -// to introduce a limit of _one_ pending authority set change per fork in order to simplify pallet -// logic and to prevent DoS attacks if GRANDPA finality were to temporarily stall for a long time -// (we'd have to perform a lot of expensive ancestry checks to catch back up). -#[test] -fn fork_does_not_allow_multiple_scheduled_changes_on_the_same_fork() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(1)), Ok(())), - ( - Type::Header(3, 1, None, Some(0)), - Err(ImportError::PendingAuthoritySetChange.into()), - ), - (Type::Finality(2, 1), Ok(())), - (Type::Header(3, 1, None, Some(0)), Ok(())), - ]; - - create_chain(&mut storage, &mut chain); - }) -} - -// Order: 1, 2, 2' -// -// / [2': S|0] -// [1] <- [2: S|0] -// -// Both 2 and 2' should be marked as needing justifications since they enact changes. -#[test] -fn fork_correctly_tracks_which_headers_require_finality_proofs() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(0)), Ok(())), - (Type::Header(2, 2, Some((1, 1)), Some(0)), Ok(())), - ]; - - create_chain(&mut storage, &mut chain); - - let header_ids = storage.missing_justifications(); - assert_eq!(header_ids.len(), 2); - assert!(header_ids[0].hash != header_ids[1].hash); - assert_eq!(header_ids[0].number, 2); - assert_eq!(header_ids[1].number, 2); - }) -} - -// Order: 1, 2, 2', 3', F2, 3, 4' -// -// / [2': S|1] <- [3'] <- [4'] -// [1] <- [2: S|0] <- [3] -// -// -// Not allowed to import 3 or 4' -// Can only import 3 after we get the finality proof for 2 -#[test] -fn fork_does_not_allow_importing_past_header_that_enacts_changes_on_forks() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(0)), Ok(())), - (Type::Header(2, 2, Some((1, 1)), Some(1)), Ok(())), - ( - Type::Header(3, 1, None, None), - Err(ImportError::AwaitingFinalityProof.into()), - ), - (Type::Header(3, 2, None, None), Ok(())), - (Type::Finality(2, 1), Ok(())), - (Type::Header(3, 1, None, None), Ok(())), - ( - Type::Header(4, 2, None, None), - Err(ImportError::AwaitingFinalityProof.into()), - ), - ]; - - create_chain(&mut storage, &mut chain); - - // Since we can't query the map directly to check if we applied the right authority set - // change (we don't know the header hash of 2) we need to get a little clever. - let mut next_change = >::iter(); - let (_, scheduled_change_on_fork) = next_change.next().unwrap(); - assert_eq!(scheduled_change_on_fork.height, 3); - - // Sanity check to make sure we enacted the change on the canonical change - assert_eq!(next_change.next(), None); - }) -} - -// Order: 1, 2, 3, 2', 3' -// -// / [2'] <- [3'] -// [1] <- [2: S|0] <- [3] -// -// Not allowed to import 3 -// Fine to import 2' and 3' -#[test] -fn fork_allows_importing_on_different_fork_while_waiting_for_finality_proof() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(0)), Ok(())), - ( - Type::Header(3, 1, None, None), - Err(ImportError::AwaitingFinalityProof.into()), - ), - (Type::Header(2, 2, Some((1, 1)), None), Ok(())), - (Type::Header(3, 2, None, None), Ok(())), - ]; - - create_chain(&mut storage, &mut chain); - }) -} - -// Order: 1, 2, 2', F2, 3, 3' -// -// / [2'] <- [3'] -// [1] <- [2: F] <- [3] -// -// In our current implementation we're allowed to keep building on fork 2 for as long as our hearts' -// content. However, we'll never be able to finalize anything on that fork. We'd have to check for -// ancestry with `best_finalized` on every import which will get expensive. -// -// I think this is fine as long as we run pruning every so often to clean up these dead forks. -#[test] -fn fork_allows_importing_on_different_fork_past_finalized_header() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(0)), Ok(())), - (Type::Header(2, 2, Some((1, 1)), None), Ok(())), - (Type::Finality(2, 1), Ok(())), - (Type::Header(3, 1, None, None), Ok(())), - (Type::Header(3, 2, None, None), Ok(())), - ]; - - create_chain(&mut storage, &mut chain); - }) -} - -// Order: 1, 2, 3, 4, 3', 4' -// -// / [3': E] <- [4'] -// [1] <- [2: S|1] <- [3: E] <- [4] -// -// Not allowed to import {4|4'} -#[test] -fn fork_can_track_scheduled_changes_across_forks() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut chain = vec![ - (Type::Header(1, 1, None, None), Ok(())), - (Type::Header(2, 1, None, Some(1)), Ok(())), - (Type::Header(3, 1, None, None), Ok(())), - ( - Type::Header(4, 1, None, None), - Err(ImportError::AwaitingFinalityProof.into()), - ), - (Type::Header(3, 2, Some((2, 1)), None), Ok(())), - ( - Type::Header(4, 2, None, None), - Err(ImportError::AwaitingFinalityProof.into()), - ), - ]; - - create_chain(&mut storage, &mut chain); - }) -} - -#[derive(Debug, PartialEq)] -enum TestError { - Import(ImportError), - Finality(FinalizationError), -} - -impl From for TestError { - fn from(e: ImportError) -> Self { - TestError::Import(e) - } -} - -impl From for TestError { - fn from(e: FinalizationError) -> Self { - TestError::Finality(e) - } -} - -// Builds a fork-aware representation of a blockchain given a list of headers. -// -// Takes a list of headers and finality proof operations which will be applied in order. The -// expected outcome for each operation is also required. -// -// The first header in the list will be used as the genesis header and will be manually imported -// into storage. -fn create_chain(storage: &mut S, chain: &mut Vec<(Type, Result<(), TestError>)>) -where - S: BridgeStorage

+ Clone, -{ - let mut map = BTreeMap::new(); - let mut verifier = Verifier { - storage: storage.clone(), - }; - initialize_genesis(storage, &mut map, chain.remove(0).0); - - for h in chain { - match h { - (Type::Header(num, fork_id, does_fork, schedules_change), expected_result) => { - // If we've never seen this fork before - if !map.contains_key(&fork_id) { - // Let's get the info about where to start the fork - if let Some((parent_num, forked_from_id)) = does_fork { - let fork = &*map.get(&forked_from_id).unwrap(); - let parent = fork - .iter() - .find(|h| h.number == *parent_num) - .expect("Trying to fork on a parent which doesn't exist"); - - let mut header = test_header(*num); - header.parent_hash = parent.hash(); - header.state_root = [*fork_id as u8; 32].into(); - - if let Some(delay) = schedules_change { - header.digest = change_log(*delay); - } - - // Try and import into storage - let res = verifier - .import_header(header.hash(), header.clone()) - .map_err(TestError::Import); - assert_eq!( - res, *expected_result, - "Expected {:?} while importing header ({}, {}), got {:?}", - *expected_result, *num, *fork_id, res, - ); - - // Let's mark the header down in a new fork - if res.is_ok() { - map.insert(*fork_id, vec![header]); - } - } - } else { - // We've seen this fork before so let's append our new header to it - let parent_hash = { - let fork = &*map.get(&fork_id).unwrap(); - fork.last().unwrap().hash() - }; - - let mut header = test_header(*num); - header.parent_hash = parent_hash; - - // Doing this to make sure headers at the same height but on - // different forks have different hashes - header.state_root = [*fork_id as u8; 32].into(); - - if let Some(delay) = schedules_change { - header.digest = change_log(*delay); - } - - let res = verifier - .import_header(header.hash(), header.clone()) - .map_err(TestError::Import); - assert_eq!( - res, *expected_result, - "Expected {:?} while importing header ({}, {}), got {:?}", - *expected_result, *num, *fork_id, res, - ); - - if res.is_ok() { - map.get_mut(&fork_id).unwrap().push(header); - } - } - } - (Type::Finality(num, fork_id), expected_result) => { - let header = map[fork_id] - .iter() - .find(|h| h.number == *num) - .expect("Trying to finalize block that doesn't exist"); - - // This is technically equivocating (accepting the same justification on the same - // `grandpa_round`). - // - // See for more: https://github.com/paritytech/parity-bridges-common/issues/430 - let justification = make_default_justification(header).encode(); - - let res = verifier - .import_finality_proof(header.hash(), justification.into()) - .map_err(TestError::Finality); - assert_eq!( - res, *expected_result, - "Expected {:?} while importing finality proof for header ({}, {}), got {:?}", - *expected_result, *num, *fork_id, res, - ); - } - } - } - - for (key, value) in map.iter() { - println!("{}: {:#?}", key, value); - } -} - -fn initialize_genesis(storage: &mut S, map: &mut BTreeMap>, genesis: Type) -where - S: BridgeStorage
, -{ - if let Type::Header(num, fork_id, None, None) = genesis { - let genesis = test_header(num); - map.insert(fork_id, vec![genesis.clone()]); - - let genesis = ImportedHeader { - header: genesis, - requires_justification: false, - is_finalized: true, - signal_hash: None, - }; - - >::put(genesis.hash()); - storage.write_header(&genesis); - } else { - panic!("Unexpected genesis block format {:#?}", genesis) - } - - let set_id = 1; - let authorities = authority_list(); - let authority_set = AuthoritySet::new(authorities, set_id); - storage.update_current_authority_set(authority_set); -} - -pub(crate) fn change_log(delay: u64) -> Digest { - let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], - delay, - }); - - Digest:: { - logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], - } -} diff --git a/modules/substrate/src/lib.rs b/modules/substrate/src/lib.rs deleted file mode 100644 index 20f0833873514..0000000000000 --- a/modules/substrate/src/lib.rs +++ /dev/null @@ -1,1040 +0,0 @@ -// Copyright 2020-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 . - -//! Substrate Bridge Pallet -//! -//! This pallet is an on-chain light client for chains which have a notion of finality. -//! -//! It has a simple interface for achieving this. First it can import headers to the runtime -//! storage. During this it will check the validity of the headers and ensure they don't conflict -//! with any existing headers (e.g they're on a different finalized chain). Secondly it can finalize -//! an already imported header (and its ancestors) given a valid GRANDPA justification. -//! -//! With these two functions the pallet is able to form a "source of truth" for what headers have -//! been finalized on a given Substrate chain. This can be a useful source of info for other -//! higher-level applications. - -#![cfg_attr(not(feature = "std"), no_std)] -// Runtime-generated enums -#![allow(clippy::large_enum_variant)] - -use crate::storage::ImportedHeader; -use bp_header_chain::AuthoritySet; -use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; -use frame_support::{ - decl_error, decl_module, decl_storage, dispatch::DispatchResult, ensure, traits::Get, weights::DispatchClass, -}; -use frame_system::{ensure_signed, RawOrigin}; -use sp_runtime::traits::Header as HeaderT; -use sp_runtime::{traits::BadOrigin, RuntimeDebug}; -use sp_std::{marker::PhantomData, prelude::*}; -use sp_trie::StorageProof; - -// Re-export since the node uses these when configuring genesis -pub use storage::{InitializationData, ScheduledChange}; - -mod storage; -mod verifier; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod fork_tests; - -/// Block number of the bridged chain. -pub(crate) type BridgedBlockNumber = BlockNumberOf<::BridgedChain>; -/// Block hash of the bridged chain. -pub(crate) type BridgedBlockHash = HashOf<::BridgedChain>; -/// Hasher of the bridged chain. -pub(crate) type BridgedBlockHasher = HasherOf<::BridgedChain>; -/// Header of the bridged chain. -pub(crate) type BridgedHeader = HeaderOf<::BridgedChain>; - -/// A convenience type identifying headers. -#[derive(RuntimeDebug, PartialEq)] -pub struct HeaderId { - /// The block number of the header. - pub number: H::Number, - /// The hash of the header. - pub hash: H::Hash, -} - -pub trait Config: frame_system::Config { - /// Chain that we are bridging here. - type BridgedChain: Chain; -} - -decl_storage! { - trait Store for Module as SubstrateBridge { - /// Hash of the header used to bootstrap the pallet. - InitialHash: BridgedBlockHash; - /// The number of the highest block(s) we know of. - BestHeight: BridgedBlockNumber; - /// Hash of the header at the highest known height. - /// - /// If there are multiple headers at the same "best" height - /// this will contain all of their hashes. - BestHeaders: Vec>; - /// Hash of the best finalized header. - BestFinalized: BridgedBlockHash; - /// The set of header IDs (number, hash) which enact an authority set change and therefore - /// require a GRANDPA justification. - RequiresJustification: map hasher(identity) BridgedBlockHash => BridgedBlockNumber; - /// Headers which have been imported into the pallet. - ImportedHeaders: map hasher(identity) BridgedBlockHash => Option>>; - /// The current GRANDPA Authority set. - CurrentAuthoritySet: AuthoritySet; - /// The next scheduled authority set change for a given fork. - /// - /// The fork is indicated by the header which _signals_ the change (key in the mapping). - /// Note that this is different than a header which _enacts_ a change. - // GRANDPA doesn't require there to always be a pending change. In fact, most of the time - // there will be no pending change available. - NextScheduledChange: map hasher(identity) BridgedBlockHash => Option>>; - /// Optional pallet owner. - /// - /// Pallet owner has a right to halt all pallet operations and then resume it. If it is - /// `None`, then there are no direct ways to halt/resume pallet operations, but other - /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt - /// flag directly or call the `halt_operations`). - ModuleOwner get(fn module_owner): Option; - /// If true, all pallet transactions are failed immediately. - IsHalted get(fn is_halted): bool; - } - add_extra_genesis { - config(owner): Option; - config(init_data): Option>>; - build(|config| { - if let Some(ref owner) = config.owner { - >::put(owner); - } - - if let Some(init_data) = config.init_data.clone() { - initialize_bridge::(init_data); - } else { - // Since the bridge hasn't been initialized we shouldn't allow anyone to perform - // transactions. - IsHalted::put(true); - } - }) - } -} - -decl_error! { - pub enum Error for Module { - /// This header has failed basic verification. - InvalidHeader, - /// This header has not been finalized. - UnfinalizedHeader, - /// The header is unknown. - UnknownHeader, - /// The storage proof doesn't contains storage root. So it is invalid for given header. - StorageRootMismatch, - /// Error when trying to fetch storage value from the proof. - StorageValueUnavailable, - /// All pallet operations are halted. - Halted, - /// The pallet has already been initialized. - AlreadyInitialized, - /// The given header is not a descendant of a particular header. - NotDescendant, - /// The header being imported is on a fork which is incompatible with the current chain. - /// - /// This can happen if we try and import a finalized header at a lower height than our - /// current `best_finalized` header. - ConflictingFork, - } -} - -decl_module! { - pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - - /// Import a signed Substrate header into the runtime. - /// - /// This will perform some basic checks to make sure it is fine to - /// import into the runtime. However, it does not perform any checks - /// related to finality. - // TODO: Update weights [#78] - #[weight = 0] - pub fn import_signed_header( - origin, - header: BridgedHeader, - ) -> DispatchResult { - ensure_operational::()?; - let _ = ensure_signed(origin)?; - let hash = header.hash(); - log::trace!("Going to import header {:?}: {:?}", hash, header); - - let mut verifier = verifier::Verifier { - storage: PalletStorage::::new(), - }; - - let _ = verifier - .import_header(hash, header) - .map_err(|e| { - log::error!("Failed to import header {:?}: {:?}", hash, e); - >::InvalidHeader - })?; - - log::trace!("Successfully imported header: {:?}", hash); - - Ok(()) - } - - /// Import a finalty proof for a particular header. - /// - /// This will take care of finalizing any already imported headers - /// which get finalized when importing this particular proof, as well - /// as updating the current and next validator sets. - // TODO: Update weights [#78] - #[weight = 0] - pub fn finalize_header( - origin, - hash: BridgedBlockHash, - finality_proof: Vec, - ) -> DispatchResult { - ensure_operational::()?; - let _ = ensure_signed(origin)?; - log::trace!("Going to finalize header: {:?}", hash); - - let mut verifier = verifier::Verifier { - storage: PalletStorage::::new(), - }; - - let _ = verifier - .import_finality_proof(hash, finality_proof.into()) - .map_err(|e| { - log::error!("Failed to finalize header {:?}: {:?}", hash, e); - >::UnfinalizedHeader - })?; - - log::trace!("Successfully finalized header: {:?}", hash); - - Ok(()) - } - - /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. - /// - /// The initial configuration provided does not need to be the genesis header of the bridged - /// chain, it can be any arbirary header. You can also provide the next scheduled set change - /// if it is already know. - /// - /// This function is only allowed to be called from a trusted origin and writes to storage - /// with practically no checks in terms of the validity of the data. It is important that - /// you ensure that valid data is being passed in. - //TODO: Update weights [#78] - #[weight = 0] - pub fn initialize( - origin, - init_data: InitializationData>, - ) { - ensure_owner_or_root::(origin)?; - let init_allowed = !>::exists(); - ensure!(init_allowed, >::AlreadyInitialized); - initialize_bridge::(init_data.clone()); - - log::info!( - "Pallet has been initialized with the following parameters: {:?}", init_data - ); - } - - /// Change `ModuleOwner`. - /// - /// May only be called either by root, or by `ModuleOwner`. - #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn set_owner(origin, new_owner: Option) { - ensure_owner_or_root::(origin)?; - match new_owner { - Some(new_owner) => { - ModuleOwner::::put(&new_owner); - log::info!("Setting pallet Owner to: {:?}", new_owner); - }, - None => { - ModuleOwner::::kill(); - log::info!("Removed Owner of pallet."); - }, - } - } - - /// Halt all pallet operations. Operations may be resumed using `resume_operations` call. - /// - /// May only be called either by root, or by `ModuleOwner`. - #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn halt_operations(origin) { - ensure_owner_or_root::(origin)?; - IsHalted::put(true); - log::warn!("Stopping pallet operations."); - } - - /// Resume all pallet operations. May be called even if pallet is halted. - /// - /// May only be called either by root, or by `ModuleOwner`. - #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn resume_operations(origin) { - ensure_owner_or_root::(origin)?; - IsHalted::put(false); - log::info!("Resuming pallet operations."); - } - } -} - -impl Module { - /// Get the highest header(s) that the pallet knows of. - pub fn best_headers() -> Vec<(BridgedBlockNumber, BridgedBlockHash)> { - PalletStorage::::new() - .best_headers() - .iter() - .map(|id| (id.number, id.hash)) - .collect() - } - - /// Get the best finalized header the pallet knows of. - /// - /// Returns a dummy header if there is no best header. This can only happen - /// if the pallet has not been initialized yet. - /// - /// Since this has been finalized correctly a user of the bridge - /// pallet should be confident that any transactions that were - /// included in this or any previous header will not be reverted. - pub fn best_finalized() -> BridgedHeader { - PalletStorage::::new().best_finalized_header().header - } - - /// Check if a particular header is known to the bridge pallet. - pub fn is_known_header(hash: BridgedBlockHash) -> bool { - PalletStorage::::new().header_exists(hash) - } - - /// Check if a particular header is finalized. - /// - /// Will return false if the header is not known to the pallet. - // One thing worth noting here is that this approach won't work well - // once we track forks since there could be an older header on a - // different fork which isn't an ancestor of our best finalized header. - pub fn is_finalized_header(hash: BridgedBlockHash) -> bool { - let storage = PalletStorage::::new(); - if let Some(header) = storage.header_by_hash(hash) { - header.is_finalized - } else { - false - } - } - - /// Returns a list of headers which require finality proofs. - /// - /// These headers require proofs because they enact authority set changes. - pub fn require_justifications() -> Vec<(BridgedBlockNumber, BridgedBlockHash)> { - PalletStorage::::new() - .missing_justifications() - .iter() - .map(|id| (id.number, id.hash)) - .collect() - } - - /// Verify that the passed storage proof is valid, given it is crafted using - /// known finalized header. If the proof is valid, then the `parse` callback - /// is called and the function returns its result. - pub fn parse_finalized_storage_proof( - finalized_header_hash: BridgedBlockHash, - storage_proof: StorageProof, - parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, - ) -> Result { - let storage = PalletStorage::::new(); - let header = storage - .header_by_hash(finalized_header_hash) - .ok_or(Error::::UnknownHeader)?; - if !header.is_finalized { - return Err(Error::::UnfinalizedHeader.into()); - } - - let storage_proof_checker = bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) - .map_err(|_| Error::::StorageRootMismatch)?; - Ok(parse(storage_proof_checker)) - } -} - -impl bp_header_chain::HeaderChain, sp_runtime::DispatchError> for Module { - fn best_finalized() -> BridgedHeader { - PalletStorage::::new().best_finalized_header().header - } - - fn authority_set() -> AuthoritySet { - PalletStorage::::new().current_authority_set() - } - - fn append_header(header: BridgedHeader) -> Result<(), sp_runtime::DispatchError> { - // We do a quick check here to ensure that our header chain is making progress and isn't - // "travelling back in time" (which would be indicative of something bad, e.g a hard-fork). - let best_finalized = PalletStorage::::new().best_finalized_header().header; - ensure!(best_finalized.number() < header.number(), >::ConflictingFork); - import_header_unchecked::<_, T>(&mut PalletStorage::::new(), header); - - Ok(()) - } -} - -/// Import a finalized header without checking if this is true. -/// -/// This function assumes that all the given header has already been proven to be valid and -/// finalized. Using this assumption it will write them to storage with minimal checks. That -/// means it's of great importance that this function *not* called with any headers whose -/// finality has not been checked, otherwise you risk bricking your bridge. -/// -/// One thing this function does do for you is GRANDPA authority set handoffs. However, since it -/// does not do verification on the incoming header it will assume that the authority set change -/// signals in the digest are well formed. -fn import_header_unchecked(storage: &mut S, header: BridgedHeader) -where - S: BridgeStorage
>, - T: Config, -{ - // Since we want to use the existing storage infrastructure we need to indicate the fork - // that we're on. We will assume that since we are using the unchecked import there are no - // forks, and can indicate that by using the first imported header's "fork". - let dummy_fork_hash = >::get(); - - // If we have a pending change in storage let's check if the current header enacts it. - let enact_change = if let Some(pending_change) = storage.scheduled_set_change(dummy_fork_hash) { - pending_change.height == *header.number() - } else { - // We don't have a scheduled change in storage at the moment. Let's check if the current - // header signals an authority set change. - if let Some(change) = bp_header_chain::find_grandpa_authorities_scheduled_change(&header) { - let next_set = AuthoritySet { - authorities: change.next_authorities, - set_id: storage.current_authority_set().set_id + 1, - }; - - let height = *header.number() + change.delay; - let scheduled_change = ScheduledChange { - authority_set: next_set, - height, - }; - - storage.schedule_next_set_change(dummy_fork_hash, scheduled_change); - - // If the delay is 0 this header will enact the change it signaled - height == *header.number() - } else { - false - } - }; - - if enact_change { - const ENACT_SET_PROOF: &str = "We only set `enact_change` as `true` if we are sure that there is a scheduled - authority set change in storage. Therefore, it must exist."; - - // If we are unable to enact an authority set it means our storage entry for scheduled - // changes is missing. Best to crash since this is likely a bug. - let _ = storage.enact_authority_set(dummy_fork_hash).expect(ENACT_SET_PROOF); - } - - storage.update_best_finalized(header.hash()); - - storage.write_header(&ImportedHeader { - header, - requires_justification: false, - is_finalized: true, - signal_hash: None, - }); -} - -/// Ensure that the origin is either root, or `ModuleOwner`. -fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { - match origin.into() { - Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::module_owner().as_ref() => Ok(()), - _ => Err(BadOrigin), - } -} - -/// Ensure that the pallet is in operational mode (not halted). -fn ensure_operational() -> Result<(), Error> { - if IsHalted::get() { - Err(>::Halted) - } else { - Ok(()) - } -} - -/// (Re)initialize bridge with given header for using it in external benchmarks. -#[cfg(feature = "runtime-benchmarks")] -pub fn initialize_for_benchmarks(header: HeaderOf) { - initialize_bridge::(InitializationData { - header, - authority_list: Vec::new(), // we don't verify any proofs in external benchmarks - set_id: 0, - scheduled_change: None, - is_halted: false, - }); -} - -/// Since this writes to storage with no real checks this should only be used in functions that were -/// called by a trusted origin. -fn initialize_bridge(init_params: InitializationData>) { - let InitializationData { - header, - authority_list, - set_id, - scheduled_change, - is_halted, - } = init_params; - - let initial_hash = header.hash(); - - let mut signal_hash = None; - if let Some(ref change) = scheduled_change { - assert!( - change.height > *header.number(), - "Changes must be scheduled past initial header." - ); - - signal_hash = Some(initial_hash); - >::insert(initial_hash, change); - }; - - >::put(initial_hash); - >::put(header.number()); - >::put(vec![initial_hash]); - >::put(initial_hash); - - let authority_set = AuthoritySet::new(authority_list, set_id); - CurrentAuthoritySet::put(authority_set); - - >::insert( - initial_hash, - ImportedHeader { - header, - requires_justification: false, - is_finalized: true, - signal_hash, - }, - ); - - IsHalted::put(is_halted); -} - -/// Expected interface for interacting with bridge pallet storage. -// TODO: This should be split into its own less-Substrate-dependent crate -pub trait BridgeStorage { - /// The header type being used by the pallet. - type Header: HeaderT; - - /// Write a header to storage. - fn write_header(&mut self, header: &ImportedHeader); - - /// Get the header(s) at the highest known height. - fn best_headers(&self) -> Vec>; - - /// Get the best finalized header the pallet knows of. - /// - /// Returns None if there is no best header. This can only happen if the pallet - /// has not been initialized yet. - fn best_finalized_header(&self) -> ImportedHeader; - - /// Update the best finalized header the pallet knows of. - fn update_best_finalized(&self, hash: ::Hash); - - /// Check if a particular header is known to the pallet. - fn header_exists(&self, hash: ::Hash) -> bool; - - /// Returns a list of headers which require justifications. - /// - /// A header will require a justification if it enacts a new authority set. - fn missing_justifications(&self) -> Vec>; - - /// Get a specific header by its hash. - /// - /// Returns None if it is not known to the pallet. - fn header_by_hash(&self, hash: ::Hash) -> Option>; - - /// Get the current GRANDPA authority set. - fn current_authority_set(&self) -> AuthoritySet; - - /// Update the current GRANDPA authority set. - /// - /// Should only be updated when a scheduled change has been triggered. - fn update_current_authority_set(&self, new_set: AuthoritySet); - - /// Replace the current authority set with the next scheduled set. - /// - /// Returns an error if there is no scheduled authority set to enact. - #[allow(clippy::result_unit_err)] - fn enact_authority_set(&mut self, signal_hash: ::Hash) -> Result<(), ()>; - - /// Get the next scheduled GRANDPA authority set change. - fn scheduled_set_change( - &self, - signal_hash: ::Hash, - ) -> Option::Number>>; - - /// Schedule a GRANDPA authority set change in the future. - /// - /// Takes the hash of the header which scheduled this particular change. - fn schedule_next_set_change( - &mut self, - signal_hash: ::Hash, - next_change: ScheduledChange<::Number>, - ); -} - -/// Used to interact with the pallet storage in a more abstract way. -#[derive(Default, Clone)] -pub struct PalletStorage(PhantomData); - -impl PalletStorage { - fn new() -> Self { - Self(PhantomData::::default()) - } -} - -impl BridgeStorage for PalletStorage { - type Header = BridgedHeader; - - fn write_header(&mut self, header: &ImportedHeader>) { - use core::cmp::Ordering; - - let hash = header.hash(); - let current_height = header.number(); - let best_height = >::get(); - - match current_height.cmp(&best_height) { - Ordering::Equal => { - // Want to avoid duplicates in the case where we're writing a finalized header to - // storage which also happens to be at the best height the best height - let not_duplicate = !>::contains_key(hash); - if not_duplicate { - >::append(hash); - } - } - Ordering::Greater => { - >::kill(); - >::append(hash); - >::put(current_height); - } - Ordering::Less => { - // This is fine. We can still have a valid header, but it might just be on a - // different fork and at a lower height than the "best" overall header. - } - } - - if header.requires_justification { - >::insert(hash, current_height); - } else { - // If the key doesn't exist this is a no-op, so it's fine to call it often - >::remove(hash); - } - - >::insert(hash, header); - } - - fn best_headers(&self) -> Vec>> { - let number = >::get(); - >::get() - .iter() - .map(|hash| HeaderId { number, hash: *hash }) - .collect() - } - - fn best_finalized_header(&self) -> ImportedHeader> { - // We will only construct a dummy header if the pallet is not initialized and someone tries - // to use the public module interface (not dispatchables) to get the best finalized header. - // This is an edge case since this can only really happen when bootstrapping the bridge. - let hash = >::get(); - self.header_by_hash(hash).unwrap_or_else(|| ImportedHeader { - header: >::new( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - requires_justification: false, - is_finalized: false, - signal_hash: None, - }) - } - - fn update_best_finalized(&self, hash: BridgedBlockHash) { - >::put(hash); - } - - fn header_exists(&self, hash: BridgedBlockHash) -> bool { - >::contains_key(hash) - } - - fn header_by_hash(&self, hash: BridgedBlockHash) -> Option>> { - >::get(hash) - } - - fn missing_justifications(&self) -> Vec>> { - >::iter() - .map(|(hash, number)| HeaderId { number, hash }) - .collect() - } - - fn current_authority_set(&self) -> AuthoritySet { - CurrentAuthoritySet::get() - } - - fn update_current_authority_set(&self, new_set: AuthoritySet) { - CurrentAuthoritySet::put(new_set) - } - - fn enact_authority_set(&mut self, signal_hash: BridgedBlockHash) -> Result<(), ()> { - let new_set = >::take(signal_hash).ok_or(())?.authority_set; - self.update_current_authority_set(new_set); - - Ok(()) - } - - fn scheduled_set_change(&self, signal_hash: BridgedBlockHash) -> Option>> { - >::get(signal_hash) - } - - fn schedule_next_set_change( - &mut self, - signal_hash: BridgedBlockHash, - next_change: ScheduledChange>, - ) { - >::insert(signal_hash, next_change) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::{run_test, test_header, unfinalized_header, Origin, TestHeader, TestRuntime}; - use bp_header_chain::HeaderChain; - use bp_test_utils::{authority_list, ALICE, BOB}; - use frame_support::{assert_err, assert_noop, assert_ok}; - use sp_runtime::DispatchError; - - fn init_with_origin(origin: Origin) -> Result, DispatchError> { - let init_data = InitializationData { - header: test_header(1), - authority_list: authority_list(), - set_id: 1, - scheduled_change: None, - is_halted: false, - }; - - Module::::initialize(origin, init_data.clone()).map(|_| init_data) - } - - #[test] - fn init_root_or_owner_origin_can_initialize_pallet() { - run_test(|| { - assert_noop!(init_with_origin(Origin::signed(1)), DispatchError::BadOrigin); - assert_ok!(init_with_origin(Origin::root())); - - // Reset storage so we can initialize the pallet again - BestFinalized::::kill(); - ModuleOwner::::put(2); - assert_ok!(init_with_origin(Origin::signed(2))); - }) - } - - #[test] - fn init_storage_entries_are_correctly_initialized() { - run_test(|| { - assert!(Module::::best_headers().is_empty()); - assert_eq!(Module::::best_finalized(), test_header(0)); - - let init_data = init_with_origin(Origin::root()).unwrap(); - - let storage = PalletStorage::::new(); - assert!(storage.header_exists(init_data.header.hash())); - assert_eq!( - storage.best_headers()[0], - crate::HeaderId { - number: *init_data.header.number(), - hash: init_data.header.hash() - } - ); - assert_eq!(storage.best_finalized_header().hash(), init_data.header.hash()); - assert_eq!(storage.current_authority_set().authorities, init_data.authority_list); - assert_eq!(IsHalted::get(), false); - }) - } - - #[test] - fn init_can_only_initialize_pallet_once() { - run_test(|| { - assert_ok!(init_with_origin(Origin::root())); - assert_noop!( - init_with_origin(Origin::root()), - >::AlreadyInitialized - ); - }) - } - - #[test] - fn pallet_owner_may_change_owner() { - run_test(|| { - ModuleOwner::::put(2); - - assert_ok!(Module::::set_owner(Origin::root(), Some(1))); - assert_noop!( - Module::::halt_operations(Origin::signed(2)), - DispatchError::BadOrigin, - ); - assert_ok!(Module::::halt_operations(Origin::root())); - - assert_ok!(Module::::set_owner(Origin::signed(1), None)); - assert_noop!( - Module::::resume_operations(Origin::signed(1)), - DispatchError::BadOrigin, - ); - assert_noop!( - Module::::resume_operations(Origin::signed(2)), - DispatchError::BadOrigin, - ); - assert_ok!(Module::::resume_operations(Origin::root())); - }); - } - - #[test] - fn pallet_may_be_halted_by_root() { - run_test(|| { - assert_ok!(Module::::halt_operations(Origin::root())); - assert_ok!(Module::::resume_operations(Origin::root())); - }); - } - - #[test] - fn pallet_may_be_halted_by_owner() { - run_test(|| { - ModuleOwner::::put(2); - - assert_ok!(Module::::halt_operations(Origin::signed(2))); - assert_ok!(Module::::resume_operations(Origin::signed(2))); - - assert_noop!( - Module::::halt_operations(Origin::signed(1)), - DispatchError::BadOrigin, - ); - assert_noop!( - Module::::resume_operations(Origin::signed(1)), - DispatchError::BadOrigin, - ); - - assert_ok!(Module::::halt_operations(Origin::signed(2))); - assert_noop!( - Module::::resume_operations(Origin::signed(1)), - DispatchError::BadOrigin, - ); - }); - } - - #[test] - fn pallet_rejects_transactions_if_halted() { - run_test(|| { - IsHalted::put(true); - - assert_noop!( - Module::::import_signed_header(Origin::signed(1), test_header(1)), - Error::::Halted, - ); - - assert_noop!( - Module::::finalize_header(Origin::signed(1), test_header(1).hash(), vec![]), - Error::::Halted, - ); - }) - } - - #[test] - fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { - run_test(|| { - assert_noop!( - Module::::parse_finalized_storage_proof( - Default::default(), - StorageProof::new(vec![]), - |_| (), - ), - Error::::UnknownHeader, - ); - }); - } - - #[test] - fn parse_finalized_storage_proof_rejects_proof_on_unfinalized_header() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let header = unfinalized_header(1); - storage.write_header(&header); - - assert_noop!( - Module::::parse_finalized_storage_proof( - header.header.hash(), - StorageProof::new(vec![]), - |_| (), - ), - Error::::UnfinalizedHeader, - ); - }); - } - - #[test] - fn parse_finalized_storage_accepts_valid_proof() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let (state_root, storage_proof) = bp_runtime::craft_valid_storage_proof(); - let mut header = unfinalized_header(1); - header.is_finalized = true; - header.header.set_state_root(state_root); - storage.write_header(&header); - - assert_ok!( - Module::::parse_finalized_storage_proof(header.header.hash(), storage_proof, |_| (),), - (), - ); - }); - } - - #[test] - fn importing_unchecked_headers_works() { - run_test(|| { - init_with_origin(Origin::root()).unwrap(); - let storage = PalletStorage::::new(); - - let header = test_header(2); - assert_ok!(Module::::append_header(header.clone())); - - assert!(storage.header_by_hash(header.hash()).unwrap().is_finalized); - assert_eq!(storage.best_finalized_header().header, header); - assert_eq!(storage.best_headers()[0].hash, header.hash()); - }) - } - - #[test] - fn importing_unchecked_header_ensures_that_chain_is_extended() { - run_test(|| { - init_with_origin(Origin::root()).unwrap(); - - let header = test_header(3); - assert_ok!(Module::::append_header(header)); - - let header = test_header(2); - assert_err!( - Module::::append_header(header), - Error::::ConflictingFork, - ); - - let header = test_header(4); - assert_ok!(Module::::append_header(header)); - }) - } - - #[test] - fn importing_unchecked_headers_enacts_new_authority_set() { - run_test(|| { - init_with_origin(Origin::root()).unwrap(); - let storage = PalletStorage::::new(); - - let next_set_id = 2; - let next_authorities = vec![(ALICE.into(), 1), (BOB.into(), 1)]; - - // Need to update the header digest to indicate that our header signals an authority set - // change. The change will be enacted when we import our header. - let mut header = test_header(2); - header.digest = fork_tests::change_log(0); - - // Let's import our test header - assert_ok!(Module::::append_header(header.clone())); - - // Make sure that our header is the best finalized - assert_eq!(storage.best_finalized_header().header, header); - assert_eq!(storage.best_headers()[0].hash, header.hash()); - - // Make sure that the authority set actually changed upon importing our header - assert_eq!( - storage.current_authority_set(), - AuthoritySet::new(next_authorities, next_set_id), - ); - }) - } - - #[test] - fn importing_unchecked_headers_enacts_new_authority_set_from_old_header() { - run_test(|| { - init_with_origin(Origin::root()).unwrap(); - let storage = PalletStorage::::new(); - - let next_set_id = 2; - let next_authorities = vec![(ALICE.into(), 1), (BOB.into(), 1)]; - - // Need to update the header digest to indicate that our header signals an authority set - // change. However, the change doesn't happen until the next block. - let mut schedules_change = test_header(2); - schedules_change.digest = fork_tests::change_log(1); - let header = test_header(3); - - // Let's import our test headers - assert_ok!(Module::::append_header(schedules_change)); - assert_ok!(Module::::append_header(header.clone())); - - // Make sure that our header is the best finalized - assert_eq!(storage.best_finalized_header().header, header); - assert_eq!(storage.best_headers()[0].hash, header.hash()); - - // Make sure that the authority set actually changed upon importing our header - assert_eq!( - storage.current_authority_set(), - AuthoritySet::new(next_authorities, next_set_id), - ); - }) - } - - #[test] - fn importing_unchecked_header_can_enact_set_change_scheduled_at_genesis() { - run_test(|| { - let storage = PalletStorage::::new(); - - let next_authorities = vec![(ALICE.into(), 1)]; - let next_set_id = 2; - let next_authority_set = AuthoritySet::new(next_authorities.clone(), next_set_id); - - let first_scheduled_change = ScheduledChange { - authority_set: next_authority_set, - height: 2, - }; - - let init_data = InitializationData { - header: test_header(1), - authority_list: authority_list(), - set_id: 1, - scheduled_change: Some(first_scheduled_change), - is_halted: false, - }; - - assert_ok!(Module::::initialize(Origin::root(), init_data)); - - // We are expecting an authority set change at height 2, so this header should enact - // that upon being imported. - assert_ok!(Module::::append_header(test_header(2))); - - // Make sure that the authority set actually changed upon importing our header - assert_eq!( - storage.current_authority_set(), - AuthoritySet::new(next_authorities, next_set_id), - ); - }) - } -} diff --git a/modules/substrate/src/mock.rs b/modules/substrate/src/mock.rs deleted file mode 100644 index f2bb422d3dc69..0000000000000 --- a/modules/substrate/src/mock.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2020-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 . - -//! Mock Runtime for Substrate Pallet Testing. -//! -//! Includes some useful testing types and functions. - -#![cfg(test)] -// From construct_runtime macro -#![allow(clippy::from_over_into)] - -use crate::{BridgedBlockHash, BridgedBlockNumber, BridgedHeader, Config}; -use bp_runtime::Chain; -use frame_support::{parameter_types, weights::Weight}; -use sp_runtime::{ - testing::{Header, H256}, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, -}; - -pub type AccountId = u64; -pub type TestHeader = BridgedHeader; -pub type TestNumber = BridgedBlockNumber; -pub type TestHash = BridgedBlockHash; - -type Block = frame_system::mocking::MockBlock; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - -use crate as pallet_substrate; - -frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Module, Call, Config, Storage, Event}, - Substrate: pallet_substrate::{Module, Call}, - } -} - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - -impl frame_system::Config for TestRuntime { - type Origin = Origin; - type Index = u64; - type Call = Call; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = (); - type SystemWeightInfo = (); - type DbWeight = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = (); -} - -impl Config for TestRuntime { - type BridgedChain = TestBridgedChain; -} - -#[derive(Debug)] -pub struct TestBridgedChain; - -impl Chain for TestBridgedChain { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hashing; - type Header = ::Header; -} - -pub fn run_test(test: impl FnOnce() -> T) -> T { - sp_io::TestExternalities::new(Default::default()).execute_with(test) -} - -pub fn test_header(num: TestNumber) -> TestHeader { - // We wrap the call to avoid explicit type annotations in our tests - bp_test_utils::test_header(num) -} - -pub fn unfinalized_header(num: u64) -> crate::storage::ImportedHeader { - crate::storage::ImportedHeader { - header: test_header(num), - requires_justification: false, - is_finalized: false, - signal_hash: None, - } -} diff --git a/modules/substrate/src/storage.rs b/modules/substrate/src/storage.rs deleted file mode 100644 index fe730c45d99fe..0000000000000 --- a/modules/substrate/src/storage.rs +++ /dev/null @@ -1,80 +0,0 @@ -// 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 . - -//! Storage primitives for the Substrate light client (a.k.a bridge) pallet. - -use bp_header_chain::AuthoritySet; -use codec::{Decode, Encode}; -use core::default::Default; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_finality_grandpa::{AuthorityList, SetId}; -use sp_runtime::traits::Header as HeaderT; -use sp_runtime::RuntimeDebug; - -/// Data required for initializing the bridge pallet. -/// -/// The bridge needs to know where to start its sync from, and this provides that initial context. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct InitializationData { - /// The header from which we should start syncing. - pub header: H, - /// The initial authorities of the pallet. - pub authority_list: AuthorityList, - /// The ID of the initial authority set. - pub set_id: SetId, - /// The first scheduled authority set change of the pallet. - pub scheduled_change: Option>, - /// Should the pallet block transaction immediately after initialization. - pub is_halted: bool, -} - -/// Keeps track of when the next GRANDPA authority set change will occur. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct ScheduledChange { - /// The authority set that will be used once this change is enacted. - pub authority_set: AuthoritySet, - /// The block height at which the authority set should be enacted. - /// - /// Note: It will only be enacted once a header at this height is finalized. - pub height: N, -} - -/// A more useful representation of a header for storage purposes. -#[derive(Default, Encode, Decode, Clone, RuntimeDebug, PartialEq)] -pub struct ImportedHeader { - /// A plain Substrate header. - pub header: H, - /// Does this header enact a new authority set change. If it does - /// then it will require a justification. - pub requires_justification: bool, - /// Has this header been finalized, either explicitly via a justification, - /// or implicitly via one of its children getting finalized. - pub is_finalized: bool, - /// The hash of the header which scheduled a change on this fork. If there are currently - /// not pending changes on this fork this will be empty. - pub signal_hash: Option, -} - -impl core::ops::Deref for ImportedHeader { - type Target = H; - - fn deref(&self) -> &H { - &self.header - } -} diff --git a/modules/substrate/src/verifier.rs b/modules/substrate/src/verifier.rs deleted file mode 100644 index 1b9e11dc2973f..0000000000000 --- a/modules/substrate/src/verifier.rs +++ /dev/null @@ -1,855 +0,0 @@ -// Copyright 2020-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 . - -//! The verifier's role is to check the validity of headers being imported, and also determine if -//! they can be finalized. -//! -//! When importing headers it performs checks to ensure that no invariants are broken (like -//! importing the same header twice). When it imports finality proofs it will ensure that the proof -//! has been signed off by the correct GRANDPA authorities, and also enact any authority set changes -//! if required. - -use crate::storage::{ImportedHeader, ScheduledChange}; -use crate::BridgeStorage; - -use bp_header_chain::{find_grandpa_authorities_scheduled_change, justification::verify_justification, AuthoritySet}; -use finality_grandpa::voter_set::VoterSet; -use sp_runtime::traits::{CheckedAdd, Header as HeaderT, One}; -use sp_runtime::RuntimeDebug; -use sp_std::{prelude::Vec, vec}; - -/// The finality proof used by the pallet. -/// -/// For a Substrate based chain using GRANDPA this will -/// be an encoded GRANDPA Justification. -#[derive(RuntimeDebug)] -pub struct FinalityProof(Vec); - -impl From<&[u8]> for FinalityProof { - fn from(proof: &[u8]) -> Self { - Self(proof.to_vec()) - } -} - -impl From> for FinalityProof { - fn from(proof: Vec) -> Self { - Self(proof) - } -} - -/// Errors which can happen while importing a header. -#[derive(RuntimeDebug, PartialEq)] -pub enum ImportError { - /// This header is at the same height or older than our latest finalized block, thus not useful. - OldHeader, - /// This header has already been imported by the pallet. - HeaderAlreadyExists, - /// We're missing a parent for this header. - MissingParent, - /// The number of the header does not follow its parent's number. - InvalidChildNumber, - /// The height of the next authority set change overflowed. - ScheduledHeightOverflow, - /// Received an authority set which was invalid in some way, such as - /// the authority weights being empty or overflowing the `AuthorityWeight` - /// type. - InvalidAuthoritySet, - /// This header is not allowed to be imported since an ancestor requires a finality proof. - /// - /// This can happen if an ancestor is supposed to enact an authority set change. - AwaitingFinalityProof, - /// This header schedules an authority set change even though we're still waiting - /// for an old authority set change to be enacted on this fork. - PendingAuthoritySetChange, -} - -/// Errors which can happen while verifying a headers finality. -#[derive(RuntimeDebug, PartialEq)] -pub enum FinalizationError { - /// This header has never been imported by the pallet. - UnknownHeader, - /// Trying to prematurely import a justification - PrematureJustification, - /// We failed to verify this header's ancestry. - AncestryCheckFailed, - /// This header is at the same height or older than our latest finalized block, thus not useful. - OldHeader, - /// The given justification was not able to finalize the given header. - /// - /// There are several reasons why this might happen, such as the justification being - /// signed by the wrong authority set, being given alongside an unexpected header, - /// or failing ancestry checks. - InvalidJustification, -} - -/// Used to verify imported headers and their finality status. -#[derive(RuntimeDebug)] -pub struct Verifier { - pub storage: S, -} - -impl Verifier -where - S: BridgeStorage
, - H: HeaderT, - H::Number: finality_grandpa::BlockNumberOps, -{ - /// Import a header to the pallet. - /// - /// Will perform some basic checks to make sure that this header doesn't break any assumptions - /// such as being on a different finalized fork. - pub fn import_header(&mut self, hash: H::Hash, header: H) -> Result<(), ImportError> { - let best_finalized = self.storage.best_finalized_header(); - - if header.number() <= best_finalized.number() { - return Err(ImportError::OldHeader); - } - - if self.storage.header_exists(hash) { - return Err(ImportError::HeaderAlreadyExists); - } - - let parent_header = self - .storage - .header_by_hash(*header.parent_hash()) - .ok_or(ImportError::MissingParent)?; - - let parent_number = *parent_header.number(); - if parent_number + One::one() != *header.number() { - return Err(ImportError::InvalidChildNumber); - } - - // A header requires a justification if it enacts an authority set change. We don't - // need to act on it right away (we'll update the set once the header gets finalized), but - // we need to make a note of it. - // - // Note: This assumes that we can only have one authority set change pending per fork at a - // time. While this is not strictly true of GRANDPA (it can have multiple pending changes, - // even across forks), this assumption simplifies our tracking of authority set changes. - let mut signal_hash = parent_header.signal_hash; - let scheduled_change = find_grandpa_authorities_scheduled_change(&header); - - // Check if our fork is expecting an authority set change - let requires_justification = if let Some(hash) = signal_hash { - const PROOF: &str = "If the header has a signal hash it means there's an accompanying set - change in storage, therefore this must always be valid."; - let pending_change = self.storage.scheduled_set_change(hash).expect(PROOF); - - if scheduled_change.is_some() { - return Err(ImportError::PendingAuthoritySetChange); - } - - if *header.number() > pending_change.height { - return Err(ImportError::AwaitingFinalityProof); - } - - pending_change.height == *header.number() - } else { - // Since we don't currently have a pending authority set change let's check if the header - // contains a log indicating when the next change should be. - if let Some(change) = scheduled_change { - let mut total_weight = 0u64; - - for (_id, weight) in &change.next_authorities { - total_weight = total_weight - .checked_add(*weight) - .ok_or(ImportError::InvalidAuthoritySet)?; - } - - // If none of the authorities have a weight associated with them the - // set is essentially empty. We don't want that. - if total_weight == 0 { - return Err(ImportError::InvalidAuthoritySet); - } - - let next_set = AuthoritySet { - authorities: change.next_authorities, - set_id: self.storage.current_authority_set().set_id + 1, - }; - - let height = (*header.number()) - .checked_add(&change.delay) - .ok_or(ImportError::ScheduledHeightOverflow)?; - - let scheduled_change = ScheduledChange { - authority_set: next_set, - height, - }; - - // Note: It's important that the signal hash is updated if a header schedules a - // change or else we end up with inconsistencies in other places. - signal_hash = Some(hash); - self.storage.schedule_next_set_change(hash, scheduled_change); - - // If the delay is 0 this header will enact the change it signaled - height == *header.number() - } else { - false - } - }; - - self.storage.write_header(&ImportedHeader { - header, - requires_justification, - is_finalized: false, - signal_hash, - }); - - Ok(()) - } - - /// Verify that a previously imported header can be finalized with the given GRANDPA finality - /// proof. If the header enacts an authority set change the change will be applied once the - /// header has been finalized. - pub fn import_finality_proof(&mut self, hash: H::Hash, proof: FinalityProof) -> Result<(), FinalizationError> { - use codec::Decode; - - // Make sure that we've previously imported this header - let header = self - .storage - .header_by_hash(hash) - .ok_or(FinalizationError::UnknownHeader)?; - - // We don't want to finalize an ancestor of an already finalized - // header, this would be inconsistent - let last_finalized = self.storage.best_finalized_header(); - if header.number() <= last_finalized.number() { - return Err(FinalizationError::OldHeader); - } - - let current_authority_set = self.storage.current_authority_set(); - let voter_set = VoterSet::new(current_authority_set.authorities).expect( - "We verified the correctness of the authority list during header import, - before writing them to storage. This must always be valid.", - ); - - let justification = bp_header_chain::justification::GrandpaJustification::::decode(&mut proof.0.as_slice()) - .map_err(|_| FinalizationError::InvalidJustification)?; - - verify_justification::( - (hash, *header.number()), - current_authority_set.set_id, - &voter_set, - &justification, - ) - .map_err(|_| FinalizationError::InvalidJustification)?; - log::trace!("Received valid justification for {:?}", header); - - log::trace!( - "Checking ancestry for headers between {:?} and {:?}", - last_finalized, - header - ); - let mut finalized_headers = - if let Some(ancestors) = headers_between(&self.storage, last_finalized, header.clone()) { - // Since we only try and finalize headers with a height strictly greater - // than `best_finalized` if `headers_between` returns Some we must have - // at least one element. If we don't something's gone wrong, so best - // to die before we write to storage. - assert_eq!( - ancestors.is_empty(), - false, - "Empty ancestry list returned from `headers_between()`", - ); - - // Check if any of our ancestors `requires_justification` a.k.a schedule authority - // set changes. If they're still waiting to be finalized we must reject this - // justification. We don't include our current header in this check. - // - // We do this because it is important to to import justifications _in order_, - // otherwise we risk finalizing headers on competing chains. - let requires_justification = ancestors.iter().skip(1).find(|h| h.requires_justification); - if requires_justification.is_some() { - return Err(FinalizationError::PrematureJustification); - } - - ancestors - } else { - return Err(FinalizationError::AncestryCheckFailed); - }; - - // If the current header was marked as `requires_justification` it means that it enacts a - // new authority set change. When we finalize the header we need to update the current - // authority set. - if header.requires_justification { - const SIGNAL_HASH_PROOF: &str = "When we import a header we only mark it as - `requires_justification` if we have checked that it contains a signal hash. Therefore - this must always be valid."; - - const ENACT_SET_PROOF: &str = - "Headers must only be marked as `requires_justification` if there's a scheduled change in storage."; - - // If we are unable to enact an authority set it means our storage entry for scheduled - // changes is missing. Best to crash since this is likely a bug. - let _ = self - .storage - .enact_authority_set(header.signal_hash.expect(SIGNAL_HASH_PROOF)) - .expect(ENACT_SET_PROOF); - } - - for header in finalized_headers.iter_mut() { - header.is_finalized = true; - header.requires_justification = false; - header.signal_hash = None; - self.storage.write_header(header); - } - - self.storage.update_best_finalized(hash); - - Ok(()) - } -} - -/// Returns the lineage of headers between [child, ancestor) -fn headers_between( - storage: &S, - ancestor: ImportedHeader, - child: ImportedHeader, -) -> Option>> -where - S: BridgeStorage
, - H: HeaderT, -{ - let mut ancestors = vec![]; - let mut current_header = child; - - while ancestor.hash() != current_header.hash() { - // We've gotten to the same height and we're not related - if ancestor.number() >= current_header.number() { - return None; - } - - let parent = storage.header_by_hash(*current_header.parent_hash()); - ancestors.push(current_header); - current_header = match parent { - Some(h) => h, - None => return None, - } - } - - Some(ancestors) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::*; - use crate::{BestFinalized, BestHeight, HeaderId, ImportedHeaders, PalletStorage}; - use bp_test_utils::{authority_list, make_default_justification, ALICE, BOB}; - use codec::Encode; - use frame_support::{assert_err, assert_ok}; - use frame_support::{StorageMap, StorageValue}; - use sp_finality_grandpa::{AuthorityId, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; - use sp_runtime::{Digest, DigestItem}; - - fn schedule_next_change( - authorities: Vec, - set_id: SetId, - height: TestNumber, - ) -> ScheduledChange { - let authorities = authorities.into_iter().map(|id| (id, 1u64)).collect(); - let authority_set = AuthoritySet::new(authorities, set_id); - ScheduledChange { authority_set, height } - } - - // Useful for quickly writing a chain of headers to storage - // Input is expected in the form: vec![(num, requires_justification, is_finalized)] - fn write_headers>( - storage: &mut S, - headers: Vec<(u64, bool, bool)>, - ) -> Vec> { - let mut imported_headers = vec![]; - let genesis = ImportedHeader { - header: test_header(0), - requires_justification: false, - is_finalized: true, - signal_hash: None, - }; - - >::put(genesis.hash()); - storage.write_header(&genesis); - imported_headers.push(genesis); - - for (num, requires_justification, is_finalized) in headers { - let header = ImportedHeader { - header: test_header(num), - requires_justification, - is_finalized, - signal_hash: None, - }; - - storage.write_header(&header); - imported_headers.push(header); - } - - imported_headers - } - - // Given a block number will generate a chain of headers which don't require justification and - // are not considered to be finalized. - fn write_default_headers>( - storage: &mut S, - headers: Vec, - ) -> Vec> { - let headers = headers.iter().map(|num| (*num, false, false)).collect(); - write_headers(storage, headers) - } - - #[test] - fn fails_to_import_old_header() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let parent = unfinalized_header(5); - storage.write_header(&parent); - storage.update_best_finalized(parent.hash()); - - let header = test_header(1); - let mut verifier = Verifier { storage }; - assert_err!(verifier.import_header(header.hash(), header), ImportError::OldHeader); - }) - } - - #[test] - fn fails_to_import_header_without_parent() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let parent = unfinalized_header(1); - storage.write_header(&parent); - storage.update_best_finalized(parent.hash()); - - // By default the parent is `0x00` - let header = TestHeader::new_from_number(2); - - let mut verifier = Verifier { storage }; - assert_err!( - verifier.import_header(header.hash(), header), - ImportError::MissingParent - ); - }) - } - - #[test] - fn fails_to_import_header_twice() { - run_test(|| { - let storage = PalletStorage::::new(); - let header = test_header(1); - >::put(header.hash()); - - let imported_header = ImportedHeader { - header: header.clone(), - requires_justification: false, - is_finalized: false, - signal_hash: None, - }; - >::insert(header.hash(), &imported_header); - - let mut verifier = Verifier { storage }; - assert_err!(verifier.import_header(header.hash(), header), ImportError::OldHeader); - }) - } - - #[test] - fn succesfully_imports_valid_but_unfinalized_header() { - run_test(|| { - let storage = PalletStorage::::new(); - let parent = test_header(1); - let parent_hash = parent.hash(); - >::put(parent.hash()); - - let imported_header = ImportedHeader { - header: parent, - requires_justification: false, - is_finalized: true, - signal_hash: None, - }; - >::insert(parent_hash, &imported_header); - - let header = test_header(2); - let mut verifier = Verifier { - storage: storage.clone(), - }; - assert_ok!(verifier.import_header(header.hash(), header.clone())); - - let stored_header = storage - .header_by_hash(header.hash()) - .expect("Should have been imported successfully"); - assert_eq!(stored_header.is_finalized, false); - assert_eq!(stored_header.hash(), storage.best_headers()[0].hash); - }) - } - - #[test] - fn successfully_imports_two_different_headers_at_same_height() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - // We want to write the genesis header to storage - let _ = write_headers(&mut storage, vec![]); - - // Both of these headers have the genesis header as their parent - let header_on_fork1 = test_header(1); - let mut header_on_fork2 = test_header(1); - - // We need to change _something_ to make it a different header - header_on_fork2.state_root = [1; 32].into(); - - let mut verifier = Verifier { - storage: storage.clone(), - }; - - // It should be fine to import both - assert_ok!(verifier.import_header(header_on_fork1.hash(), header_on_fork1.clone())); - assert_ok!(verifier.import_header(header_on_fork2.hash(), header_on_fork2.clone())); - - // We should have two headers marked as being the best since they're - // both at the same height - let best_headers = storage.best_headers(); - assert_eq!(best_headers.len(), 2); - assert_eq!( - best_headers[0], - HeaderId { - number: *header_on_fork1.number(), - hash: header_on_fork1.hash() - } - ); - assert_eq!( - best_headers[1], - HeaderId { - number: *header_on_fork2.number(), - hash: header_on_fork2.hash() - } - ); - assert_eq!(>::get(), 1); - }) - } - - #[test] - fn correctly_updates_the_best_header_given_a_better_header() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - // We want to write the genesis header to storage - let _ = write_headers(&mut storage, vec![]); - - // Write two headers at the same height to storage. - let best_header = test_header(1); - let mut also_best_header = test_header(1); - - // We need to change _something_ to make it a different header - also_best_header.state_root = [1; 32].into(); - - let mut verifier = Verifier { - storage: storage.clone(), - }; - - // It should be fine to import both - assert_ok!(verifier.import_header(best_header.hash(), best_header.clone())); - assert_ok!(verifier.import_header(also_best_header.hash(), also_best_header)); - - // The headers we manually imported should have been marked as the best - // upon writing to storage. Let's confirm that. - assert_eq!(storage.best_headers().len(), 2); - assert_eq!(>::get(), 1); - - // Now let's build something at a better height. - let mut better_header = test_header(2); - better_header.parent_hash = best_header.hash(); - - assert_ok!(verifier.import_header(better_header.hash(), better_header.clone())); - - // Since `better_header` is the only one at height = 2 we should only have - // a single "best header" now. - let best_headers = storage.best_headers(); - assert_eq!(best_headers.len(), 1); - assert_eq!( - best_headers[0], - HeaderId { - number: *better_header.number(), - hash: better_header.hash() - } - ); - assert_eq!(>::get(), 2); - }) - } - - #[test] - fn doesnt_write_best_header_twice_upon_finalization() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let _imported_headers = write_default_headers(&mut storage, vec![1]); - - let set_id = 1; - let authorities = authority_list(); - let initial_authority_set = AuthoritySet::new(authorities, set_id); - storage.update_current_authority_set(initial_authority_set); - - // Let's import our header - let header = test_header(2); - let mut verifier = Verifier { - storage: storage.clone(), - }; - assert_ok!(verifier.import_header(header.hash(), header.clone())); - - // Our header should be the only best header we have - assert_eq!(storage.best_headers()[0].hash, header.hash()); - assert_eq!(storage.best_headers().len(), 1); - - // Now lets finalize our best header - let justification = make_default_justification(&header).encode(); - assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); - - // Our best header should only appear once in the list of best headers - assert_eq!(storage.best_headers()[0].hash, header.hash()); - assert_eq!(storage.best_headers().len(), 1); - }) - } - - #[test] - fn related_headers_are_ancestors() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let mut imported_headers = write_default_headers(&mut storage, vec![1, 2, 3]); - - for header in imported_headers.iter() { - assert!(storage.header_exists(header.hash())); - } - - let ancestor = imported_headers.remove(0); - let child = imported_headers.pop().unwrap(); - let ancestors = headers_between(&storage, ancestor, child); - - assert!(ancestors.is_some()); - assert_eq!(ancestors.unwrap().len(), 3); - }) - } - - #[test] - fn unrelated_headers_are_not_ancestors() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut imported_headers = write_default_headers(&mut storage, vec![1, 2, 3]); - for header in imported_headers.iter() { - assert!(storage.header_exists(header.hash())); - } - - // Need to give it a different parent_hash or else it'll be - // related to our test genesis header - let mut bad_ancestor = test_header(0); - bad_ancestor.parent_hash = [1u8; 32].into(); - let bad_ancestor = ImportedHeader { - header: bad_ancestor, - requires_justification: false, - is_finalized: false, - signal_hash: None, - }; - - let child = imported_headers.pop().unwrap(); - let ancestors = headers_between(&storage, bad_ancestor, child); - assert!(ancestors.is_none()); - }) - } - - #[test] - fn ancestor_newer_than_child_is_not_related() { - run_test(|| { - let mut storage = PalletStorage::::new(); - - let mut imported_headers = write_default_headers(&mut storage, vec![1, 2, 3]); - for header in imported_headers.iter() { - assert!(storage.header_exists(header.hash())); - } - - // What if we have an "ancestor" that's newer than child? - let new_ancestor = test_header(5); - let new_ancestor = ImportedHeader { - header: new_ancestor, - requires_justification: false, - is_finalized: false, - signal_hash: None, - }; - - let child = imported_headers.pop().unwrap(); - let ancestors = headers_between(&storage, new_ancestor, child); - assert!(ancestors.is_none()); - }) - } - - #[test] - fn doesnt_import_header_which_schedules_change_with_invalid_authority_set() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let _imported_headers = write_default_headers(&mut storage, vec![1]); - let mut header = test_header(2); - - // This is an *invalid* authority set because the combined weight of the - // authorities is greater than `u64::MAX` - let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(ALICE.into(), u64::MAX), (BOB.into(), u64::MAX)], - delay: 0, - }); - - header.digest = Digest:: { - logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], - }; - - let mut verifier = Verifier { storage }; - - assert_eq!( - verifier.import_header(header.hash(), header).unwrap_err(), - ImportError::InvalidAuthoritySet - ); - }) - } - - #[test] - fn finalizes_header_which_doesnt_enact_or_schedule_a_new_authority_set() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let _imported_headers = write_default_headers(&mut storage, vec![1]); - - // Nothing special about this header, yet GRANDPA may have created a justification - // for it since it does that periodically - let header = test_header(2); - - let set_id = 1; - let authorities = authority_list(); - let authority_set = AuthoritySet::new(authorities, set_id); - storage.update_current_authority_set(authority_set); - - // We'll need this justification to finalize the header - let justification = make_default_justification(&header).encode(); - - let mut verifier = Verifier { - storage: storage.clone(), - }; - - assert_ok!(verifier.import_header(header.hash(), header.clone())); - assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); - assert_eq!(storage.best_finalized_header().header, header); - }) - } - - #[test] - fn correctly_verifies_and_finalizes_chain_of_headers() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let imported_headers = write_default_headers(&mut storage, vec![1, 2]); - let header = test_header(3); - - let set_id = 1; - let authorities = authority_list(); - let authority_set = AuthoritySet { authorities, set_id }; - storage.update_current_authority_set(authority_set); - - let justification = make_default_justification(&header).encode(); - - let mut verifier = Verifier { - storage: storage.clone(), - }; - assert!(verifier.import_header(header.hash(), header.clone()).is_ok()); - assert!(verifier - .import_finality_proof(header.hash(), justification.into()) - .is_ok()); - - // Make sure we marked the our headers as finalized - assert!(storage.header_by_hash(imported_headers[1].hash()).unwrap().is_finalized); - assert!(storage.header_by_hash(imported_headers[2].hash()).unwrap().is_finalized); - assert!(storage.header_by_hash(header.hash()).unwrap().is_finalized); - - // Make sure the header at the highest height is the best finalized - assert_eq!(storage.best_finalized_header().header, header); - }); - } - - #[test] - fn updates_authority_set_upon_finalizing_header_which_enacts_change() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let genesis_hash = write_headers(&mut storage, vec![])[0].hash(); - - // We want this header to indicate that there's an upcoming set change on this fork - let parent = ImportedHeader { - header: test_header(1), - requires_justification: false, - is_finalized: false, - signal_hash: Some(genesis_hash), - }; - storage.write_header(&parent); - - let set_id = 1; - let authorities = authority_list(); - let initial_authority_set = AuthoritySet::new(authorities, set_id); - storage.update_current_authority_set(initial_authority_set); - - // This header enacts an authority set change upon finalization - let header = test_header(2); - - let justification = make_default_justification(&header).encode(); - - // Schedule a change at the height of our header - let set_id = 2; - let height = *header.number(); - let authorities = vec![ALICE.into()]; - let change = schedule_next_change(authorities, set_id, height); - storage.schedule_next_set_change(genesis_hash, change.clone()); - - let mut verifier = Verifier { - storage: storage.clone(), - }; - - assert_ok!(verifier.import_header(header.hash(), header.clone())); - assert_eq!(storage.missing_justifications().len(), 1); - assert_eq!(storage.missing_justifications()[0].hash, header.hash()); - - assert_ok!(verifier.import_finality_proof(header.hash(), justification.into())); - assert_eq!(storage.best_finalized_header().header, header); - - // Make sure that we have updated the set now that we've finalized our header - assert_eq!(storage.current_authority_set(), change.authority_set); - assert!(storage.missing_justifications().is_empty()); - }) - } - - #[test] - fn importing_finality_proof_for_already_finalized_header_doesnt_work() { - run_test(|| { - let mut storage = PalletStorage::::new(); - let genesis = test_header(0); - - let genesis = ImportedHeader { - header: genesis, - requires_justification: false, - is_finalized: true, - signal_hash: None, - }; - - // Make sure that genesis is the best finalized header - >::put(genesis.hash()); - storage.write_header(&genesis); - - let mut verifier = Verifier { storage }; - - // Now we want to try and import it again to see what happens - assert_eq!( - verifier - .import_finality_proof(genesis.hash(), vec![4, 2].into()) - .unwrap_err(), - FinalizationError::OldHeader - ); - }); - } -} diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 3afe8d43b9429..2d97c678005ff 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -243,7 +243,7 @@ mod tests { // then assert_eq!( format!("{:?}", hex), - "0x0d00d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" + "0x0c00d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" ); } } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 5b521012c0063..1708a8efa121c 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -22,8 +22,6 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -pub use millau_runtime::BridgeRialtoCall; - /// Millau header id. pub type HeaderId = relay_utils::HeaderId; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 7061205ec8d02..0ddc03681d296 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -22,8 +22,6 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -pub use rialto_runtime::BridgeMillauCall; - /// Rialto header id. pub type HeaderId = relay_utils::HeaderId; From e372bf8b682ce0b0203bd4f831f1c74aa5632730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Apr 2021 16:56:12 +0200 Subject: [PATCH 0410/1210] Fix `encode-call` CLI options (#868) * Add tests. * Fix default and conflicting options. * Fix default variant. * Update tests. --- relays/bin-substrate/src/cli/encode_call.rs | 82 +++++++++++++++++-- relays/bin-substrate/src/rialto_millau/mod.rs | 12 +-- 2 files changed, 81 insertions(+), 13 deletions(-) diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 2d97c678005ff..1a2c8ebfb2407 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -20,7 +20,7 @@ use relay_substrate_client::Chain; use structopt::{clap::arg_enum, StructOpt}; /// Encode source chain runtime call. -#[derive(StructOpt)] +#[derive(StructOpt, Debug)] pub struct EncodeCall { /// A bridge instance to encode call for. #[structopt(possible_values = &EncodeCallBridge::variants(), case_insensitive = true)] @@ -43,10 +43,10 @@ pub enum Call { /// Make an on-chain remark (comment). Remark { /// Explicit remark payload. - #[structopt(long, conflicts_with("remark_size"))] - remark_payload: HexBytes, + #[structopt(long, conflicts_with("remark-size"))] + remark_payload: Option, /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. - #[structopt(long, conflicts_with("remark_payload"))] + #[structopt(long, conflicts_with("remark-payload"))] remark_size: Option>, }, /// Transfer the specified `amount` of native tokens to a particular `recipient`. @@ -165,11 +165,11 @@ pub(crate) fn preprocess_call { - if remark_payload.0.is_empty() { - *remark_payload = HexBytes(generate_remark_payload( + if remark_payload.is_none() { + *remark_payload = Some(HexBytes(generate_remark_payload( &remark_size, compute_maximal_message_arguments_size(Source::max_extrinsic_size(), Target::max_extrinsic_size()), - )); + ))); } } Call::Transfer { ref mut recipient, .. } => { @@ -246,4 +246,72 @@ mod tests { "0x0c00d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" ); } + + #[test] + fn should_encode_remark_with_default_payload() { + // given + let mut encode_call = EncodeCall::from_iter(vec!["encode-call", "RialtoToMillau", "remark"]); + + // when + let hex = encode_call.encode().unwrap(); + + // then + assert!(format!("{:?}", hex).starts_with("0x070154556e69782074696d653a")); + } + + #[test] + fn should_encode_remark_with_explicit_payload() { + // given + let mut encode_call = EncodeCall::from_iter(vec![ + "encode-call", + "RialtoToMillau", + "remark", + "--remark-payload", + "1234", + ]); + + // when + let hex = encode_call.encode().unwrap(); + + // then + assert_eq!(format!("{:?}", hex), "0x0701081234"); + } + + #[test] + fn should_encode_remark_with_size() { + // given + let mut encode_call = + EncodeCall::from_iter(vec!["encode-call", "RialtoToMillau", "remark", "--remark-size", "12"]); + + // when + let hex = encode_call.encode().unwrap(); + + // then + assert_eq!(format!("{:?}", hex), "0x070130000000000000000000000000"); + } + + #[test] + fn should_disallow_both_payload_and_size() { + // when + let err = EncodeCall::from_iter_safe(vec![ + "encode-call", + "RialtoToMillau", + "remark", + "--remark-payload", + "1234", + "--remark-size", + "12", + ]) + .unwrap_err(); + + // then + assert_eq!(err.kind, structopt::clap::ErrorKind::ArgumentConflict); + assert_eq!( + err.info, + Some(vec![ + "remark-size".to_string(), + "--remark-payload ".to_string() + ]) + ); + } } diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index 52f1d5201cdec..a39053aa4f93a 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -414,9 +414,9 @@ impl CliEncodeCall for Millau { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, - Call::Remark { remark_payload, .. } => { - millau_runtime::Call::System(millau_runtime::SystemCall::remark(remark_payload.0.clone())) - } + Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )), Call::Transfer { recipient, amount } => millau_runtime::Call::Balances( millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount.cast()), ), @@ -487,9 +487,9 @@ impl CliEncodeCall for Rialto { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, - Call::Remark { remark_payload, .. } => { - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(remark_payload.0.clone())) - } + Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )), Call::Transfer { recipient, amount } => { rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount.0)) } From e212ea2484e7ff750e552478d00af2bd51a959c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Apr 2021 17:28:28 +0200 Subject: [PATCH 0411/1210] Extract select_bridge macro. (#869) --- relays/bin-substrate/src/cli/bridge.rs | 75 +++++++++++++++++++ .../bin-substrate/src/cli/derive_account.rs | 47 ++---------- relays/bin-substrate/src/cli/encode_call.rs | 50 ++----------- relays/bin-substrate/src/cli/mod.rs | 1 + .../bin-substrate/src/cli/relay_messages.rs | 42 ++--------- relays/bin-substrate/src/rialto_millau/mod.rs | 7 +- 6 files changed, 100 insertions(+), 122 deletions(-) create mode 100644 relays/bin-substrate/src/cli/bridge.rs diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs new file mode 100644 index 0000000000000..83a19f88c2788 --- /dev/null +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -0,0 +1,75 @@ +// 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 . + +use structopt::clap::arg_enum; + +arg_enum! { + #[derive(Debug)] + /// Supported full bridges (headers + messages). + pub enum FullBridge { + MillauToRialto, + RialtoToMillau, + } +} + +impl FullBridge { + /// Return instance index of the bridge pallet in source runtime. + pub fn bridge_instance_index(&self) -> u8 { + match self { + Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, + Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, + } + } +} + +pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; +pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; + +/// The macro allows executing bridge-specific code without going fully generic. +/// +/// It matches on the [`FullBridge`] enum, sets bridge-specific types or imports and injects +/// the `$generic` code at every variant. +#[macro_export] +macro_rules! select_full_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + FullBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + + #[allow(unused_imports)] + use bp_millau::derive_account_from_rialto_id as derive_account; + + #[allow(unused_imports)] + use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages; + + $generic + } + FullBridge::RialtoToMillau => { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; + + #[allow(unused_imports)] + use bp_rialto::derive_account_from_millau_id as derive_account; + + #[allow(unused_imports)] + use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages; + + $generic + } + } + }; +} diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs index cd40fb5891ae4..92b32b0d479ca 100644 --- a/relays/bin-substrate/src/cli/derive_account.rs +++ b/relays/bin-substrate/src/cli/derive_account.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::AccountId; +use crate::cli::{bridge::FullBridge, AccountId}; +use crate::select_full_bridge; use relay_substrate_client::Chain; -use structopt::{clap::arg_enum, StructOpt}; +use structopt::StructOpt; /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. /// @@ -27,52 +28,18 @@ use structopt::{clap::arg_enum, StructOpt}; #[derive(StructOpt)] pub struct DeriveAccount { /// A bridge instance to initalize. - #[structopt(possible_values = &DeriveAccountBridge::variants(), case_insensitive = true)] - bridge: DeriveAccountBridge, + #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + bridge: FullBridge, /// Source-chain address to derive Target-chain address from. account: AccountId, } -arg_enum! { - #[derive(Debug)] - /// Bridge to derive account for. - pub enum DeriveAccountBridge { - MillauToRialto, - RialtoToMillau, - } -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - DeriveAccountBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; - - #[allow(unused_imports)] // the import is not used in `run` - use bp_millau::derive_account_from_rialto_id as derive_account; - - $generic - } - DeriveAccountBridge::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; - - #[allow(unused_imports)] // the import is not used in `run`. - use bp_rialto::derive_account_from_millau_id as derive_account; - - $generic - } - } - }; -} - impl DeriveAccount { /// Parse CLI arguments and derive account. /// /// Returns both the Source account in correct SS58 format and the derived account. fn derive_account(&self) -> (AccountId, AccountId) { - select_bridge!(self.bridge, { + select_full_bridge!(self.bridge, { let mut account = self.account.clone(); account.enforce_chain::(); let acc = bp_runtime::SourceAccount::Account(account.raw_id()); @@ -84,7 +51,7 @@ impl DeriveAccount { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { + select_full_bridge!(self.bridge, { let (account, derived_account) = self.derive_account(); println!("Source address:\n{} ({})", account, Source::NAME); println!( diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 1a2c8ebfb2407..1f7861f21acc3 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -14,17 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::cli::bridge::FullBridge; use crate::cli::{AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId}; +use crate::select_full_bridge; use frame_support::dispatch::GetDispatchInfo; use relay_substrate_client::Chain; -use structopt::{clap::arg_enum, StructOpt}; +use structopt::StructOpt; /// Encode source chain runtime call. #[derive(StructOpt, Debug)] pub struct EncodeCall { /// A bridge instance to encode call for. - #[structopt(possible_values = &EncodeCallBridge::variants(), case_insensitive = true)] - bridge: EncodeCallBridge, + #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + bridge: FullBridge, #[structopt(flatten)] call: Call, } @@ -85,49 +87,9 @@ pub trait CliEncodeCall: Chain { fn encode_call(call: &Call) -> anyhow::Result; } -arg_enum! { - #[derive(Debug)] - /// Bridge to encode call for. - pub enum EncodeCallBridge { - MillauToRialto, - RialtoToMillau, - } -} - -impl EncodeCallBridge { - fn bridge_instance_index(&self) -> u8 { - match self { - Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, - Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, - } - } -} - -pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; -pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - EncodeCallBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; - - $generic - } - EncodeCallBridge::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; - - $generic - } - } - }; -} - impl EncodeCall { fn encode(&mut self) -> anyhow::Result { - select_bridge!(self.bridge, { + select_full_bridge!(self.bridge, { preprocess_call::(&mut self.call, self.bridge.bridge_instance_index()); let call = Source::encode_call(&self.call)?; diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index ebceb3a25e0a2..0ddee88aeef0a 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -25,6 +25,7 @@ use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +pub(crate) mod bridge; pub(crate) mod encode_call; mod derive_account; diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 72a194ef90302..feedea66ef6ab 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -14,18 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::cli::bridge::FullBridge; use crate::cli::{ HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; -use structopt::{clap::arg_enum, StructOpt}; +use crate::select_full_bridge; +use structopt::StructOpt; /// Start messages relayer process. #[derive(StructOpt)] pub struct RelayMessages { /// A bridge instance to relay messages for. - #[structopt(possible_values = &RelayMessagesBridge::variants(), case_insensitive = true)] - bridge: RelayMessagesBridge, + #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + bridge: FullBridge, /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -41,46 +43,16 @@ pub struct RelayMessages { prometheus_params: PrometheusParams, } -arg_enum! { - #[derive(Debug)] - /// Headers relay bridge. - pub enum RelayMessagesBridge { - MillauToRialto, - RialtoToMillau, - } -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - RelayMessagesBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; - use crate::rialto_millau::millau_messages_to_rialto::run; - - $generic - } - RelayMessagesBridge::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; - use crate::rialto_millau::rialto_messages_to_millau::run; - - $generic - } - } - }; -} - impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { + select_full_bridge!(self.bridge, { let source_client = self.source.into_client::().await?; let source_sign = self.source_sign.into_keypair::()?; let target_client = self.target.into_client::().await?; let target_sign = self.target_sign.into_keypair::()?; - run( + relay_messages( source_client, source_sign, target_client, diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index a39053aa4f93a..13e8bc19c3717 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -29,7 +29,8 @@ pub type MillauClient = relay_substrate_client::Client; pub type RialtoClient = relay_substrate_client::Client; use crate::cli::{ - encode_call::{self, Call, CliEncodeCall, MILLAU_TO_RIALTO_INDEX, RIALTO_TO_MILLAU_INDEX}, + bridge::{MILLAU_TO_RIALTO_INDEX, RIALTO_TO_MILLAU_INDEX}, + encode_call::{self, Call, CliEncodeCall}, CliChain, ExplicitOrMaximal, HexBytes, Origins, }; use codec::{Decode, Encode}; @@ -426,7 +427,7 @@ impl CliEncodeCall for Millau { fee, bridge_instance_index, } => match *bridge_instance_index { - encode_call::MILLAU_TO_RIALTO_INDEX => { + MILLAU_TO_RIALTO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( lane.0, @@ -499,7 +500,7 @@ impl CliEncodeCall for Rialto { fee, bridge_instance_index, } => match *bridge_instance_index { - encode_call::RIALTO_TO_MILLAU_INDEX => { + RIALTO_TO_MILLAU_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( lane.0, payload, fee.0, From 64183eb464811a5a14ad20fdd7bb759e3df43fbc Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Apr 2021 11:09:46 -0400 Subject: [PATCH 0412/1210] Check for both possible error variants (#870) --- relays/bin-substrate/src/cli/encode_call.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 1f7861f21acc3..b5cdaaa1d3908 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -268,12 +268,8 @@ mod tests { // then assert_eq!(err.kind, structopt::clap::ErrorKind::ArgumentConflict); - assert_eq!( - err.info, - Some(vec![ - "remark-size".to_string(), - "--remark-payload ".to_string() - ]) - ); + + let info = err.info.unwrap(); + assert!(info.contains(&"remark-payload".to_string()) | info.contains(&"remark-size".to_string())) } } From 27c9514f3114f320d7b10b32513462a29cac5244 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Apr 2021 11:56:45 -0400 Subject: [PATCH 0413/1210] Bump Substrate (#871) * Bump Substrate * Change usage of "Module" to "Pallet" Related Substrate PR: https://github.com/paritytech/substrate/pull/8372 * Add `OnSetCode` config param Related Substrate PR: https://github.com/paritytech/substrate/pull/8496 * Update Aura Slot duration time type Related Substrate PR: https://github.com/paritytech/substrate/pull/8386 * Add `OnSetCode` to mock runtimes * Add support for multiple justifications Related Substrate PR: https://github.com/paritytech/substrate/pull/7640 * Use updated justification type in more places * Make GenesisConfig type non-optional Related Substrate PR: https://github.com/paritytech/substrate/pull/8275 * Update service to use updated telemetry Related Substrate PR: https://github.com/paritytech/substrate/pull/8143 * Appease Clippy --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/chain_spec.rs | 28 ++-- bin/millau/node/src/service.rs | 156 +++++++++++------- bin/millau/runtime/src/lib.rs | 42 ++--- bin/rialto/node/src/chain_spec.rs | 28 ++-- bin/rialto/node/src/service.rs | 156 +++++++++++------- bin/rialto/runtime/src/lib.rs | 74 +++++---- bin/runtime-common/src/messages.rs | 8 +- modules/currency-exchange/src/benchmarking.rs | 6 +- modules/currency-exchange/src/lib.rs | 11 +- modules/dispatch/src/lib.rs | 17 +- modules/ethereum/src/lib.rs | 8 +- modules/ethereum/src/mock.rs | 5 +- modules/grandpa/src/lib.rs | 88 +++++----- modules/grandpa/src/mock.rs | 5 +- modules/messages/rpc/src/lib.rs | 2 +- modules/messages/src/benchmarking.rs | 44 ++--- modules/messages/src/instant_payments.rs | 4 +- modules/messages/src/lib.rs | 132 +++++++-------- modules/messages/src/mock.rs | 9 +- modules/shift-session-manager/src/lib.rs | 25 +-- primitives/chain-millau/src/lib.rs | 4 +- primitives/chain-rialto/src/lib.rs | 4 +- primitives/chain-rococo/src/lib.rs | 2 +- primitives/header-chain/src/justification.rs | 2 +- relays/bin-ethereum/src/ethereum_client.rs | 6 +- .../bin-ethereum/src/substrate_sync_loop.rs | 10 +- relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/chain.rs | 10 +- relays/client-substrate/src/guard.rs | 2 +- relays/client-substrate/src/headers_source.rs | 4 +- relays/headers/src/lib.rs | 2 +- 32 files changed, 501 insertions(+), 395 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index c71eb8bfe3191..076e282bae363 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -39,6 +39,7 @@ sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", bra sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index df790c7580bb8..f9e9502da72ba 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -122,7 +122,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), - pallet_bridge_messages::Module::< + pallet_bridge_messages::Pallet::< millau_runtime::Runtime, pallet_bridge_messages::DefaultInstance, >::relayer_fund_account_id(), @@ -154,33 +154,33 @@ fn testnet_genesis( _enable_println: bool, ) -> GenesisConfig { GenesisConfig { - frame_system: Some(SystemConfig { + frame_system: SystemConfig { code: WASM_BINARY.to_vec(), changes_trie_config: Default::default(), - }), - pallet_balances: Some(BalancesConfig { + }, + pallet_balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), - }), - pallet_aura: Some(AuraConfig { + }, + pallet_aura: AuraConfig { authorities: Vec::new(), - }), - pallet_grandpa: Some(GrandpaConfig { + }, + pallet_grandpa: GrandpaConfig { authorities: Vec::new(), - }), - pallet_sudo: Some(SudoConfig { key: root_key }), - pallet_session: Some(SessionConfig { + }, + pallet_sudo: SudoConfig { key: root_key }, + pallet_session: SessionConfig { keys: initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), - }), - pallet_bridge_grandpa_Instance1: Some(BridgeWestendGrandpaConfig { + }, + pallet_bridge_grandpa_Instance1: BridgeWestendGrandpaConfig { // for our deployments to avoid multiple same-nonces transactions: // //Alice is already used to initialize Rialto<->Millau bridge // => let's use //George to initialize Westend->Millau bridge owner: Some(get_account_id_from_seed::("George")), ..Default::default() - }), + }, } } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 25cc4c7fb21a9..b3834ff68a726 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -30,11 +30,13 @@ use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; +use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -70,6 +72,7 @@ pub fn new_partial( AuraPair, >, sc_finality_grandpa::LinkHalf, + Option, ), >, ServiceError, @@ -77,12 +80,30 @@ pub fn new_partial( if config.keystore_remote.is_some() { return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); } - let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + let inherent_data_providers = InherentDataProviders::new(); + + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::(&config)?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + &config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + )?; let client = Arc::new(client); + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", worker.run()); + telemetry + }); + let select_chain = sc_consensus::LongestChain::new(backend.clone()); let transaction_pool = sc_transaction_pool::BasicPool::new_full( @@ -93,22 +114,28 @@ pub fn new_partial( client.clone(), ); - let (grandpa_block_import, grandpa_link) = - sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + telemetry.as_ref().map(|x| x.handle()), + )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import.clone(), - Some(Box::new(grandpa_block_import)), - client.clone(), - inherent_data_providers.clone(), - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - )?; + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: aura_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import)), + client: client.clone(), + inherent_data_providers: inherent_data_providers.clone(), + spawner: &task_manager.spawn_essential_handle(), + can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + slot_duration: sc_consensus_aura::slot_duration(&*client)?, + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; Ok(sc_service::PartialComponents { client, @@ -119,7 +146,7 @@ pub fn new_partial( select_chain, transaction_pool, inherent_data_providers, - other: (aura_block_import, grandpa_link), + other: (aura_block_import, grandpa_link, telemetry), }) } @@ -141,7 +168,7 @@ pub fn new_full(mut config: Configuration) -> Result select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link), + other: (block_import, grandpa_link, mut telemetry), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -173,13 +200,7 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - backend.clone(), - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } let role = config.role.clone(); @@ -265,7 +286,7 @@ pub fn new_full(mut config: Configuration) -> Result }) }; - let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), @@ -278,32 +299,35 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, - telemetry_span: None, + telemetry: telemetry.as_mut(), })?; if role.is_authority() { - let proposer = sc_basic_authorship::ProposerFactory::new( + let proposer_factory = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), transaction_pool, prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.handle()), ); let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - client.clone(), + let aura = sc_consensus_aura::start_aura::(StartAuraParams { + slot_duration: sc_consensus_aura::slot_duration(&*client)?, + client: client.clone(), select_chain, block_import, - proposer, - network.clone(), + proposer_factory, inherent_data_providers, force_authoring, backoff_authoring_blocks, - keystore_container.sync_keystore(), + keystore: keystore_container.sync_keystore(), can_author_with, - )?; + sync_oracle: network.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. @@ -326,6 +350,7 @@ pub fn new_full(mut config: Configuration) -> Result observer_enabled: false, keystore, is_authority: role.is_authority(), + telemetry: telemetry.as_ref().map(|x| x.handle()), }; if enable_grandpa { @@ -339,10 +364,10 @@ pub fn new_full(mut config: Configuration) -> Result config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), + telemetry: telemetry.as_ref().map(|x| x.handle()), }; // the GRANDPA voter task is considered infallible, i.e. @@ -358,8 +383,27 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + let (client, backend, keystore_container, mut task_manager, on_demand) = - sc_service::new_light_parts::(&config)?; + sc_service::new_light_parts::( + &config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + )?; + + let mut telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", worker.run()); + telemetry + }); config .network @@ -376,22 +420,28 @@ pub fn new_light(mut config: Configuration) -> Result on_demand.clone(), )); - let (grandpa_block_import, _) = - sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; + let (grandpa_block_import, _) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain, + telemetry.as_ref().map(|x| x.handle()), + )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import)), - client.clone(), - InherentDataProviders::new(), - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::NeverCanAuthor, - )?; + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: aura_block_import, + justification_import: Some(Box::new(grandpa_block_import)), + client: client.clone(), + inherent_data_providers: InherentDataProviders::new(), + spawner: &task_manager.spawn_essential_handle(), + can_author_with: sp_consensus::NeverCanAuthor, + slot_duration: sc_consensus_aura::slot_duration(&*client)?, + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -405,13 +455,7 @@ pub fn new_light(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - backend.clone(), - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } sc_service::spawn_tasks(sc_service::SpawnTasksParams { @@ -427,7 +471,7 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, - telemetry_span: None, + telemetry: telemetry.as_mut(), })?; network_starter.start_network(); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b627cce404063..437c9ff36f595 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -201,6 +201,8 @@ impl frame_system::Config for Runtime { type DbWeight = DbWeight; /// The designated SS58 prefix of this chain. type SS58Prefix = SS58Prefix; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); } impl pallet_aura::Config for Runtime { @@ -292,7 +294,7 @@ impl pallet_session::Config for Runtime { type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = pallet_shift_session_manager::Module; + type SessionManager = pallet_shift_session_manager::Pallet; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = (); @@ -363,7 +365,7 @@ impl pallet_bridge_messages::Config for Runtime { type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - pallet_balances::Module, + pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; @@ -378,20 +380,20 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialtoMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, - BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, - BridgeRialtoGrandpa: pallet_bridge_grandpa::{Module, Call, Storage}, - BridgeWestendGrandpa: pallet_bridge_grandpa::::{Module, Call, Config, Storage}, - System: frame_system::{Module, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, - Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Aura: pallet_aura::{Module, Config}, - Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, - Balances: pallet_balances::{Module, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Module, Storage}, - Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, - Session: pallet_session::{Module, Call, Storage, Event, Config}, - ShiftSessionManager: pallet_shift_session_manager::{Module}, + BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event}, + BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, + BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Aura: pallet_aura::{Pallet, Config}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + ShiftSessionManager: pallet_shift_session_manager::{Pallet}, } ); @@ -423,7 +425,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = - frame_executive::Executive, Runtime, AllModules>; + frame_executive::Executive, Runtime, AllPallets>; impl_runtime_apis! { impl sp_api::Core for Runtime { @@ -467,7 +469,7 @@ impl_runtime_apis! { } fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed().0.into() + RandomnessCollectiveFlip::random_seed().0 } } @@ -493,8 +495,8 @@ impl_runtime_apis! { } impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> u64 { - Aura::slot_duration() + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) } fn authorities() -> Vec { diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 14b2c3b84c33b..732cf1a4b13a2 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -122,7 +122,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), - pallet_bridge_messages::Module::< + pallet_bridge_messages::Pallet::< rialto_runtime::Runtime, pallet_bridge_messages::DefaultInstance, >::relayer_fund_account_id(), @@ -154,28 +154,28 @@ fn testnet_genesis( _enable_println: bool, ) -> GenesisConfig { GenesisConfig { - frame_system: Some(SystemConfig { + frame_system: SystemConfig { code: WASM_BINARY.to_vec(), changes_trie_config: Default::default(), - }), - pallet_balances: Some(BalancesConfig { + }, + pallet_balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), - }), - pallet_aura: Some(AuraConfig { + }, + pallet_aura: AuraConfig { authorities: Vec::new(), - }), - pallet_bridge_eth_poa_Instance1: Some(load_rialto_poa_bridge_config()), - pallet_bridge_eth_poa_Instance2: Some(load_kovan_bridge_config()), - pallet_grandpa: Some(GrandpaConfig { + }, + pallet_bridge_eth_poa_Instance1: load_rialto_poa_bridge_config(), + pallet_bridge_eth_poa_Instance2: load_kovan_bridge_config(), + pallet_grandpa: GrandpaConfig { authorities: Vec::new(), - }), - pallet_sudo: Some(SudoConfig { key: root_key }), - pallet_session: Some(SessionConfig { + }, + pallet_sudo: SudoConfig { key: root_key }, + pallet_session: SessionConfig { keys: initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), - }), + }, } } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 4f35a8fddf045..380b0cc8171cc 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -30,11 +30,13 @@ use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; +use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_inherents::InherentDataProviders; use std::sync::Arc; @@ -70,6 +72,7 @@ pub fn new_partial( AuraPair, >, sc_finality_grandpa::LinkHalf, + Option, ), >, ServiceError, @@ -77,12 +80,30 @@ pub fn new_partial( if config.keystore_remote.is_some() { return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); } - let inherent_data_providers = sp_inherents::InherentDataProviders::new(); + let inherent_data_providers = InherentDataProviders::new(); + + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::(&config)?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + &config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + )?; let client = Arc::new(client); + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", worker.run()); + telemetry + }); + let select_chain = sc_consensus::LongestChain::new(backend.clone()); let transaction_pool = sc_transaction_pool::BasicPool::new_full( @@ -93,22 +114,28 @@ pub fn new_partial( client.clone(), ); - let (grandpa_block_import, grandpa_link) = - sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain.clone())?; + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + telemetry.as_ref().map(|x| x.handle()), + )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import.clone(), - Some(Box::new(grandpa_block_import)), - client.clone(), - inherent_data_providers.clone(), - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - )?; + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: aura_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import)), + client: client.clone(), + inherent_data_providers: inherent_data_providers.clone(), + spawner: &task_manager.spawn_essential_handle(), + can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + slot_duration: sc_consensus_aura::slot_duration(&*client)?, + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; Ok(sc_service::PartialComponents { client, @@ -119,7 +146,7 @@ pub fn new_partial( select_chain, transaction_pool, inherent_data_providers, - other: (aura_block_import, grandpa_link), + other: (aura_block_import, grandpa_link, telemetry), }) } @@ -141,7 +168,7 @@ pub fn new_full(mut config: Configuration) -> Result select_chain, transaction_pool, inherent_data_providers, - other: (block_import, grandpa_link), + other: (block_import, grandpa_link, mut telemetry), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -173,13 +200,7 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - backend.clone(), - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } let role = config.role.clone(); @@ -266,7 +287,7 @@ pub fn new_full(mut config: Configuration) -> Result }) }; - let (_rpc_handlers, telemetry_connection_notifier) = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), @@ -279,32 +300,35 @@ pub fn new_full(mut config: Configuration) -> Result network_status_sinks, system_rpc_tx, config, - telemetry_span: None, + telemetry: telemetry.as_mut(), })?; if role.is_authority() { - let proposer = sc_basic_authorship::ProposerFactory::new( + let proposer_factory = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), transaction_pool, prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.handle()), ); let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - client.clone(), + let aura = sc_consensus_aura::start_aura::(StartAuraParams { + slot_duration: sc_consensus_aura::slot_duration(&*client)?, + client: client.clone(), select_chain, block_import, - proposer, - network.clone(), + proposer_factory, inherent_data_providers, force_authoring, backoff_authoring_blocks, - keystore_container.sync_keystore(), + keystore: keystore_container.sync_keystore(), can_author_with, - )?; + sync_oracle: network.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. @@ -327,6 +351,7 @@ pub fn new_full(mut config: Configuration) -> Result observer_enabled: false, keystore, is_authority: role.is_authority(), + telemetry: telemetry.as_ref().map(|x| x.handle()), }; if enable_grandpa { @@ -340,10 +365,10 @@ pub fn new_full(mut config: Configuration) -> Result config: grandpa_config, link: grandpa_link, network, - telemetry_on_connect: telemetry_connection_notifier.map(|x| x.on_connect_stream()), voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), + telemetry: telemetry.as_ref().map(|x| x.handle()), }; // the GRANDPA voter task is considered infallible, i.e. @@ -359,8 +384,27 @@ pub fn new_full(mut config: Configuration) -> Result /// Builds a new service for a light client. pub fn new_light(mut config: Configuration) -> Result { + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + let (client, backend, keystore_container, mut task_manager, on_demand) = - sc_service::new_light_parts::(&config)?; + sc_service::new_light_parts::( + &config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + )?; + + let mut telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", worker.run()); + telemetry + }); config .network @@ -377,22 +421,28 @@ pub fn new_light(mut config: Configuration) -> Result on_demand.clone(), )); - let (grandpa_block_import, _) = - sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?; + let (grandpa_block_import, _) = sc_finality_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain, + telemetry.as_ref().map(|x| x.handle()), + )?; let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>( - sc_consensus_aura::slot_duration(&*client)?, - aura_block_import, - Some(Box::new(grandpa_block_import)), - client.clone(), - InherentDataProviders::new(), - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::NeverCanAuthor, - )?; + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: aura_block_import, + justification_import: Some(Box::new(grandpa_block_import)), + client: client.clone(), + inherent_data_providers: InherentDataProviders::new(), + spawner: &task_manager.spawn_essential_handle(), + can_author_with: sp_consensus::NeverCanAuthor, + slot_duration: sc_consensus_aura::slot_duration(&*client)?, + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; let (network, network_status_sinks, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -406,13 +456,7 @@ pub fn new_light(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - backend.clone(), - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } sc_service::spawn_tasks(sc_service::SpawnTasksParams { @@ -428,7 +472,7 @@ pub fn new_light(mut config: Configuration) -> Result network, network_status_sinks, system_rpc_tx, - telemetry_span: None, + telemetry: telemetry.as_mut(), })?; network_starter.start_network(); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5fd10b12de9a6..4db3101810a1d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -208,6 +208,8 @@ impl frame_system::Config for Runtime { type DbWeight = DbWeight; /// The designated SS58 prefix of this chain. type SS58Prefix = SS58Prefix; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); } impl pallet_aura::Config for Runtime { @@ -277,7 +279,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> bp_currency_exchange::Result<()> { // let balances module make all checks for us (it won't allow depositing lower than existential // deposit, balance overflow, ...) - let deposited = as Currency>::deposit_creating(&recipient, amount); + let deposited = as Currency>::deposit_creating(&recipient, amount); // I'm dropping deposited here explicitly to illustrate the fact that it'll update `TotalIssuance` // on drop @@ -398,7 +400,7 @@ impl pallet_session::Config for Runtime { type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = pallet_shift_session_manager::Module; + type SessionManager = pallet_shift_session_manager::Pallet; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = (); @@ -456,7 +458,7 @@ impl pallet_bridge_messages::Config for Runtime { type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - pallet_balances::Module, + pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; @@ -471,23 +473,23 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialtoPoA: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, - BridgeKovan: pallet_bridge_eth_poa::::{Module, Call, Config, Storage, ValidateUnsigned}, - BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, - BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Module, Call}, - BridgeMillauGrandpa: pallet_bridge_grandpa::{Module, Call, Storage}, - BridgeDispatch: pallet_bridge_dispatch::{Module, Event}, - BridgeMillauMessages: pallet_bridge_messages::{Module, Call, Storage, Event}, - System: frame_system::{Module, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, - Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, - Aura: pallet_aura::{Module, Config}, - Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, - Balances: pallet_balances::{Module, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Module, Storage}, - Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, - Session: pallet_session::{Module, Call, Storage, Event, Config}, - ShiftSessionManager: pallet_shift_session_manager::{Module}, + BridgeRialtoPoA: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, + BridgeKovan: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, + BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, + BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, + BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, + BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Aura: pallet_aura::{Pallet, Config}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + ShiftSessionManager: pallet_shift_session_manager::{Pallet}, } ); @@ -519,7 +521,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = - frame_executive::Executive, Runtime, AllModules>; + frame_executive::Executive, Runtime, AllPallets>; impl_runtime_apis! { impl sp_api::Core for Runtime { @@ -563,7 +565,7 @@ impl_runtime_apis! { } fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed().0.into() + RandomnessCollectiveFlip::random_seed().0 } } @@ -652,8 +654,8 @@ impl_runtime_apis! { } impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> u64 { - Aura::slot_duration() + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) } fn authorities() -> Vec { @@ -789,7 +791,7 @@ impl_runtime_apis! { let params = (&config, &whitelist); use pallet_bridge_currency_exchange::benchmarking::{ - Module as BridgeCurrencyExchangeBench, + Pallet as BridgeCurrencyExchangeBench, Config as BridgeCurrencyExchangeConfig, ProofParams as BridgeCurrencyExchangeProofParams, }; @@ -831,7 +833,7 @@ impl_runtime_apis! { use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bridge_runtime_common::messages; use pallet_bridge_messages::benchmarking::{ - Module as MessagesBench, + Pallet as MessagesBench, Config as MessagesConfig, MessageDeliveryProofParams, MessageParams, @@ -849,11 +851,11 @@ impl_runtime_apis! { } fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { - pallet_balances::Module::::free_balance(account) + pallet_balances::Pallet::::free_balance(account) } fn endow_account(account: &Self::AccountId) { - pallet_balances::Module::::make_free_balance_be( + pallet_balances::Pallet::::make_free_balance_be( account, Balance::MAX / 100, ); @@ -1033,7 +1035,7 @@ mod tests { ext.execute_with(|| { // initially issuance is zero assert_eq!( - as Currency>::total_issuance(), + as Currency>::total_issuance(), 0, ); @@ -1041,14 +1043,14 @@ mod tests { let account: AccountId = [1u8; 32].into(); let initial_amount = ExistentialDeposit::get(); let deposited = - as Currency>::deposit_creating(&account, initial_amount); + as Currency>::deposit_creating(&account, initial_amount); drop(deposited); assert_eq!( - as Currency>::total_issuance(), + as Currency>::total_issuance(), initial_amount, ); assert_eq!( - as Currency>::free_balance(&account), + as Currency>::free_balance(&account), initial_amount, ); @@ -1057,7 +1059,7 @@ mod tests { // check that total issuance has changed by `run_deposit_into_test` assert_eq!( - as Currency>::total_issuance(), + as Currency>::total_issuance(), initial_amount + total_issuance_change, ); }); @@ -1101,7 +1103,7 @@ mod tests { fn deposit_into_existing_account_works() { run_deposit_into_test(|existing_account| { let initial_amount = - as Currency>::free_balance(&existing_account); + as Currency>::free_balance(&existing_account); let additional_amount = 10_000; >::DepositInto::deposit_into( existing_account.clone(), @@ -1109,7 +1111,7 @@ mod tests { ) .unwrap(); assert_eq!( - as Currency>::free_balance(&existing_account), + as Currency>::free_balance(&existing_account), initial_amount + additional_amount, ); additional_amount @@ -1128,7 +1130,7 @@ mod tests { ) .unwrap(); assert_eq!( - as Currency>::free_balance(&new_account), + as Currency>::free_balance(&new_account), initial_amount + additional_amount, ); additional_amount diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 2497f07131fe2..8e83c0f94ada4 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -365,7 +365,7 @@ pub mod source { storage_proof, lane, } = proof; - pallet_bridge_grandpa::Module::::parse_finalized_storage_proof( + pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), |storage| { @@ -468,7 +468,7 @@ pub mod target { ThisRuntime: pallet_bridge_dispatch::Config, >::Event: From>, - pallet_bridge_dispatch::Module: + pallet_bridge_dispatch::Pallet: bp_message_dispatch::MessageDispatch<(LaneId, MessageNonce), Message = FromBridgedChainMessagePayload>, { type DispatchPayload = FromBridgedChainMessagePayload; @@ -481,7 +481,7 @@ pub mod target { fn dispatch(message: DispatchMessage>>) { let message_id = (message.key.lane_id, message.key.nonce); - pallet_bridge_dispatch::Module::::dispatch( + pallet_bridge_dispatch::Pallet::::dispatch( B::INSTANCE, message_id, message.data.payload.map_err(drop), @@ -517,7 +517,7 @@ pub mod target { proof, messages_count, |bridged_header_hash, bridged_storage_proof| { - pallet_bridge_grandpa::Module::::parse_finalized_storage_proof( + pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index 204398e12d8c6..574ae93f6ee0c 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -19,7 +19,7 @@ //! before invoking module calls. use super::{ - Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Instance, Module as CurrencyExchangeModule, + Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Instance, Pallet as CurrencyExchangePallet, }; use sp_std::prelude::*; @@ -30,8 +30,8 @@ const SEED: u32 = 0; const WORST_TX_SIZE_FACTOR: u32 = 1000; const WORST_PROOF_SIZE_FACTOR: u32 = 1000; -/// Module we're benchmarking here. -pub struct Module, I: Instance>(CurrencyExchangeModule); +/// Pallet we're benchmarking here. +pub struct Pallet, I: Instance>(CurrencyExchangePallet); /// Proof benchmarking parameters. pub struct ProofParams { diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 569a01e03ecb6..542082f85ab16 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -61,7 +61,7 @@ pub trait Config: frame_system::Config { } decl_error! { - pub enum Error for Module, I: Instance> { + pub enum Error for Pallet, I: Instance> { /// Invalid peer blockchain transaction provided. InvalidTransaction, /// Peer transaction has invalid amount. @@ -125,13 +125,13 @@ decl_module! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as Bridge { + trait Store for Pallet, I: Instance = DefaultInstance> as Bridge { /// All transfers that have already been claimed. Transfers: map hasher(blake2_128_concat) ::Id => (); } } -impl, I: Instance> Module { +impl, I: Instance> Pallet { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. pub fn filter_transaction_proof( @@ -326,8 +326,8 @@ mod tests { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Exchange: pallet_bridge_currency_exchange::{Module}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Exchange: pallet_bridge_currency_exchange::{Pallet}, } } @@ -361,6 +361,7 @@ mod tests { type BlockLength = (); type DbWeight = (); type SS58Prefix = (); + type OnSetCode = (); } impl Config for TestRuntime { diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index d383e884696d1..76706d4d1e162 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -153,7 +153,7 @@ pub trait Config: frame_system::Config { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as Dispatch {} + trait Store for Pallet, I: Instance = DefaultInstance> as Dispatch {} } decl_event!( @@ -189,7 +189,7 @@ decl_module! { } } -impl, I: Instance> MessageDispatch for Module { +impl, I: Instance> MessageDispatch for Pallet { type Message = MessagePayload; @@ -455,8 +455,8 @@ mod tests { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Dispatch: call_dispatch::{Module, Call, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Dispatch: call_dispatch::{Pallet, Call, Event}, } } @@ -490,6 +490,7 @@ mod tests { type BlockLength = (); type DbWeight = (); type SS58Prefix = (); + type OnSetCode = (); } impl Config for TestRuntime { @@ -534,7 +535,7 @@ mod tests { fn prepare_message( origin: CallOrigin, call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { MessagePayload { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, @@ -545,20 +546,20 @@ mod tests { fn prepare_root_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { prepare_message(CallOrigin::SourceRoot, call) } fn prepare_target_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); prepare_message(origin, call) } fn prepare_source_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch<::MessageId>>::Message { let origin = CallOrigin::SourceAccount(1); prepare_message(origin, call) } diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index c29c7844a1c0e..aeb7d69f763bc 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -313,7 +313,7 @@ pub trait PruningStrategy: Default { /// Every value that is returned from this function, must be greater or equal to the /// previous value. Otherwise it will be ignored (we can't revert pruning). /// - /// Module may prune both finalized and unfinalized blocks. But it can't give any + /// Pallet may prune both finalized and unfinalized blocks. But it can't give any /// guarantees on when it will happen. Example: if some unfinalized block at height N /// has scheduled validators set change, then the module won't prune any blocks with /// number >= N even if strategy allows that. @@ -457,7 +457,7 @@ decl_module! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as Bridge { + trait Store for Pallet, I: Instance = DefaultInstance> as Bridge { /// Best known block. BestBlock: (HeaderId, U256); /// Best finalized block. @@ -505,7 +505,7 @@ decl_storage! { } } -impl, I: Instance> Module { +impl, I: Instance> Pallet { /// Returns number and hash of the best block known to the bridge module. /// The caller should only submit `import_header` transaction that makes /// (or leads to making) other header the best one. @@ -542,7 +542,7 @@ impl, I: Instance> Module { } } -impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Module { +impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Pallet { type Call = Call; fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 8c305dedf7884..35c093f36387c 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -44,8 +44,8 @@ frame_support::construct_runtime! { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Ethereum: pallet_ethereum::{Module, Call}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Ethereum: pallet_ethereum::{Pallet, Call}, } } @@ -79,6 +79,7 @@ impl frame_system::Config for TestRuntime { type BlockLength = (); type DbWeight = (); type SS58Prefix = (); + type OnSetCode = (); } parameter_types! { diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 9f7ca8231c0c4..58f58d6aa6ddf 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -53,7 +53,7 @@ use sp_runtime::RuntimeDebug; #[cfg(test)] mod mock; -/// Module containing weights for this pallet. +/// Pallet containing weights for this pallet. pub mod weights; #[cfg(feature = "runtime-benchmarks")] @@ -191,19 +191,19 @@ pub mod pallet { Ok(().into()) } - /// Change `ModuleOwner`. + /// Change `PalletOwner`. /// - /// May only be called either by root, or by `ModuleOwner`. + /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; match new_owner { Some(new_owner) => { - ModuleOwner::::put(&new_owner); + PalletOwner::::put(&new_owner); log::info!(target: "runtime::bridge-grandpa", "Setting pallet Owner to: {:?}", new_owner); } None => { - ModuleOwner::::kill(); + PalletOwner::::kill(); log::info!(target: "runtime::bridge-grandpa", "Removed Owner of pallet."); } } @@ -213,7 +213,7 @@ pub mod pallet { /// Halt or resume all pallet operations. /// - /// May only be called either by root, or by `ModuleOwner`. + /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operational(origin: OriginFor, operational: bool) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; @@ -265,7 +265,7 @@ pub mod pallet { /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). #[pallet::storage] - pub(super) type ModuleOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; + pub(super) type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; /// If true, all pallet transactions are failed immediately. #[pallet::storage] @@ -293,7 +293,7 @@ pub mod pallet { impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { if let Some(ref owner) = self.owner { - >::put(owner); + >::put(owner); } if let Some(init_data) = self.init_data.clone() { @@ -426,11 +426,11 @@ pub mod pallet { >::put(is_halted); } - /// Ensure that the origin is either root, or `ModuleOwner`. + /// Ensure that the origin is either root, or `PalletOwner`. fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::get().as_ref() => Ok(()), + Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::get().as_ref() => Ok(()), _ => Err(BadOrigin), } } @@ -574,22 +574,22 @@ mod tests { is_halted: false, }; - Module::::initialize(origin, init_data.clone()).map(|_| init_data) + Pallet::::initialize(origin, init_data.clone()).map(|_| init_data) } fn submit_finality_proof(header: u8) -> frame_support::dispatch::DispatchResultWithPostInfo { let header = test_header(header.into()); let justification = make_default_justification(&header); - Module::::submit_finality_proof(Origin::signed(1), header, justification) + Pallet::::submit_finality_proof(Origin::signed(1), header, justification) } fn next_block() { use frame_support::traits::OnInitialize; - let current_number = frame_system::Module::::block_number(); - frame_system::Module::::set_block_number(current_number + 1); - let _ = Module::::on_initialize(current_number); + let current_number = frame_system::Pallet::::block_number(); + frame_system::Pallet::::set_block_number(current_number + 1); + let _ = Pallet::::on_initialize(current_number); } fn change_log(delay: u64) -> Digest { @@ -625,7 +625,7 @@ mod tests { // Reset storage so we can initialize the pallet again BestFinalized::::kill(); - ModuleOwner::::put(2); + PalletOwner::::put(2); assert_ok!(init_with_origin(Origin::signed(2))); }) } @@ -637,7 +637,7 @@ mod tests { BestFinalized::::get(), BridgedBlockHash::::default() ); - assert_eq!(Module::::best_finalized(), test_header(0)); + assert_eq!(Pallet::::best_finalized(), test_header(0)); let init_data = init_with_origin(Origin::root()).unwrap(); @@ -665,56 +665,56 @@ mod tests { #[test] fn pallet_owner_may_change_owner() { run_test(|| { - ModuleOwner::::put(2); + PalletOwner::::put(2); - assert_ok!(Module::::set_owner(Origin::root(), Some(1))); + assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); assert_noop!( - Module::::set_operational(Origin::signed(2), false), + Pallet::::set_operational(Origin::signed(2), false), DispatchError::BadOrigin, ); - assert_ok!(Module::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operational(Origin::root(), false)); - assert_ok!(Module::::set_owner(Origin::signed(1), None)); + assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); assert_noop!( - Module::::set_operational(Origin::signed(1), true), + Pallet::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); assert_noop!( - Module::::set_operational(Origin::signed(2), true), + Pallet::::set_operational(Origin::signed(2), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operational(Origin::root(), true)); }); } #[test] fn pallet_may_be_halted_by_root() { run_test(|| { - assert_ok!(Module::::set_operational(Origin::root(), false)); - assert_ok!(Module::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operational(Origin::root(), true)); }); } #[test] fn pallet_may_be_halted_by_owner() { run_test(|| { - ModuleOwner::::put(2); + PalletOwner::::put(2); - assert_ok!(Module::::set_operational(Origin::signed(2), false)); - assert_ok!(Module::::set_operational(Origin::signed(2), true)); + assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); + assert_ok!(Pallet::::set_operational(Origin::signed(2), true)); assert_noop!( - Module::::set_operational(Origin::signed(1), false), + Pallet::::set_operational(Origin::signed(1), false), DispatchError::BadOrigin, ); assert_noop!( - Module::::set_operational(Origin::signed(1), true), + Pallet::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::set_operational(Origin::signed(2), false)); + assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); assert_noop!( - Module::::set_operational(Origin::signed(1), true), + Pallet::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); }); @@ -755,7 +755,7 @@ mod tests { let justification = make_justification_for_header(params); assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification,), + Pallet::::submit_finality_proof(Origin::signed(1), header, justification,), >::InvalidJustification ); }) @@ -771,7 +771,7 @@ mod tests { justification.round = 42; assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification,), + Pallet::::submit_finality_proof(Origin::signed(1), header, justification,), >::InvalidJustification ); }) @@ -790,13 +790,13 @@ mod tests { is_halted: false, }; - assert_ok!(Module::::initialize(Origin::root(), init_data)); + assert_ok!(Pallet::::initialize(Origin::root(), init_data)); let header = test_header(1); let justification = make_default_justification(&header); assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification,), + Pallet::::submit_finality_proof(Origin::signed(1), header, justification,), >::InvalidAuthoritySet ); }) @@ -830,7 +830,7 @@ mod tests { let justification = make_default_justification(&header); // Let's import our test header - assert_ok!(Module::::submit_finality_proof( + assert_ok!(Pallet::::submit_finality_proof( Origin::signed(1), header.clone(), justification @@ -863,7 +863,7 @@ mod tests { // Should not be allowed to import this header assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification), + Pallet::::submit_finality_proof(Origin::signed(1), header, justification), >::UnsupportedScheduledChange ); }) @@ -884,7 +884,7 @@ mod tests { // Should not be allowed to import this header assert_err!( - Module::::submit_finality_proof(Origin::signed(1), header, justification), + Pallet::::submit_finality_proof(Origin::signed(1), header, justification), >::UnsupportedScheduledChange ); }) @@ -894,7 +894,7 @@ mod tests { fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { run_test(|| { assert_noop!( - Module::::parse_finalized_storage_proof( + Pallet::::parse_finalized_storage_proof( Default::default(), sp_trie::StorageProof::new(vec![]), |_| (), @@ -917,7 +917,7 @@ mod tests { >::insert(hash, header); assert_ok!( - Module::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), + Pallet::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), (), ); }); @@ -942,7 +942,7 @@ mod tests { let mut invalid_justification = make_default_justification(&header); invalid_justification.round = 42; - Module::::submit_finality_proof(Origin::signed(1), header, invalid_justification) + Pallet::::submit_finality_proof(Origin::signed(1), header, invalid_justification) }; initialize_substrate_bridge(); diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 9646ebc552a61..7d5901a679c65 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -41,8 +41,8 @@ construct_runtime! { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Grandpa: grandpa::{Module}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Grandpa: grandpa::{Pallet}, } } @@ -76,6 +76,7 @@ impl frame_system::Config for TestRuntime { type BlockWeights = (); type BlockLength = (); type SS58Prefix = (); + type OnSetCode = (); } parameter_types! { diff --git a/modules/messages/rpc/src/lib.rs b/modules/messages/rpc/src/lib.rs index 381725f06e7f0..a53dcfeb02767 100644 --- a/modules/messages/rpc/src/lib.rs +++ b/modules/messages/rpc/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Module that provides RPC methods specific to messages pallet. +//! Pallet that provides RPC methods specific to messages pallet. use crate::error::{Error, FutureResult}; diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index f160168d0bdac..d1ecf7750002f 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -33,8 +33,8 @@ pub const MESSAGE_FEE: u64 = 10_000_000_000; const SEED: u32 = 0; -/// Module we're benchmarking here. -pub struct Module, I: crate::Instance>(crate::Module); +/// Pallet we're benchmarking here. +pub struct Pallet, I: crate::Instance>(crate::Pallet); /// Proof size requirements. pub enum ProofSize { @@ -142,7 +142,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -179,7 +179,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -216,7 +216,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -261,7 +261,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -292,7 +292,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 22, ); } @@ -327,11 +327,11 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); assert_eq!( - crate::Module::::inbound_latest_confirmed_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), 20, ); } @@ -361,7 +361,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -393,7 +393,7 @@ benchmarks_instance! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -404,7 +404,7 @@ benchmarks_instance! { // // This is base benchmark for all other confirmations delivery benchmarks. receive_delivery_proof_for_single_message { - let relayers_fund_id = crate::Module::::relayer_fund_account_id(); + let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -441,7 +441,7 @@ benchmarks_instance! { // as `weight(receive_delivery_proof_for_two_messages_by_single_relayer) // - weight(receive_delivery_proof_for_single_message)`. receive_delivery_proof_for_two_messages_by_single_relayer { - let relayers_fund_id = crate::Module::::relayer_fund_account_id(); + let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -476,7 +476,7 @@ benchmarks_instance! { // as `weight(receive_delivery_proof_for_two_messages_by_two_relayers) // - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`. receive_delivery_proof_for_two_messages_by_two_relayers { - let relayers_fund_id = crate::Module::::relayer_fund_account_id(); + let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); let relayer1_id: T::AccountId = account("relayer1", 1, SEED); let relayer1_balance = T::account_balance(&relayer1_id); let relayer2_id: T::AccountId = account("relayer2", 2, SEED); @@ -540,7 +540,7 @@ benchmarks_instance! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Module::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -579,7 +579,7 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 20 + i as MessageNonce, ); } @@ -616,7 +616,7 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -653,7 +653,7 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); } @@ -696,11 +696,11 @@ benchmarks_instance! { ) verify { assert_eq!( - crate::Module::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 20 + i as MessageNonce, ); assert_eq!( - crate::Module::::inbound_latest_confirmed_nonce(T::bench_lane_id()), + crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), 20, ); } @@ -713,7 +713,7 @@ benchmarks_instance! { .try_into() .expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large"); - let relayers_fund_id = crate::Module::::relayer_fund_account_id(); + let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -749,7 +749,7 @@ benchmarks_instance! { .try_into() .expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large "); - let relayers_fund_id = crate::Module::::relayer_fund_account_id(); + let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); let confirmation_relayer_id = account("relayer", 0, SEED); let relayers: BTreeMap = (1..=i) .map(|j| { diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index 24261cf5cfb0a..524a3765d6ad4 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -59,7 +59,7 @@ where fn initialize(relayer_fund_account: &T::AccountId) -> usize { assert!( - frame_system::Module::::account_exists(relayer_fund_account), + frame_system::Pallet::::account_exists(relayer_fund_account), "The relayer fund account ({:?}) must exist for the message lanes pallet to work correctly.", relayer_fund_account, ); @@ -189,7 +189,7 @@ mod tests { use crate::mock::{run_test, AccountId as TestAccountId, Balance as TestBalance, TestRuntime}; use bp_messages::source_chain::RelayerRewards; - type Balances = pallet_balances::Module; + type Balances = pallet_balances::Pallet; const RELAYER_1: TestAccountId = 1; const RELAYER_2: TestAccountId = 2; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 9abd2f087fc42..9e2563498feef 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -161,7 +161,7 @@ type MessagesDeliveryProofOf = <>::TargetHeaderChain as Tar >>::MessagesDeliveryProof; decl_error! { - pub enum Error for Module, I: Instance> { + pub enum Error for Pallet, I: Instance> { /// All pallet operations are halted. Halted, /// Message has been treated as invalid by chain verifier. @@ -188,14 +188,14 @@ decl_error! { } decl_storage! { - trait Store for Module, I: Instance = DefaultInstance> as BridgeMessages { + trait Store for Pallet, I: Instance = DefaultInstance> as BridgeMessages { /// Optional pallet owner. /// /// Pallet owner has a right to halt all pallet operations and then resume it. If it is /// `None`, then there are no direct ways to halt/resume pallet operations, but other /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). - pub ModuleOwner get(fn module_owner): Option; + pub PalletOwner get(fn module_owner): Option; /// If true, all pallet transactions are failed immediately. pub IsHalted get(fn is_halted) config(): bool; /// Map of lane id => inbound lane data. @@ -210,7 +210,7 @@ decl_storage! { config(owner): Option; build(|config| { if let Some(ref owner) = config.owner { - >::put(owner); + >::put(owner); } }) } @@ -246,19 +246,19 @@ decl_module! { T::DbWeight::get().reads(reads as u64) } - /// Change `ModuleOwner`. + /// Change `PalletOwner`. /// - /// May only be called either by root, or by `ModuleOwner`. + /// May only be called either by root, or by `PalletOwner`. #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] pub fn set_owner(origin, new_owner: Option) { ensure_owner_or_root::(origin)?; match new_owner { Some(new_owner) => { - ModuleOwner::::put(&new_owner); + PalletOwner::::put(&new_owner); log::info!(target: "runtime::bridge-messages", "Setting pallet Owner to: {:?}", new_owner); }, None => { - ModuleOwner::::kill(); + PalletOwner::::kill(); log::info!(target: "runtime::bridge-messages", "Removed Owner of pallet."); }, } @@ -266,7 +266,7 @@ decl_module! { /// Halt or resume all pallet operations. /// - /// May only be called either by root, or by `ModuleOwner`. + /// May only be called either by root, or by `PalletOwner`. #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] pub fn set_operational(origin, operational: bool) { ensure_owner_or_root::(origin)?; @@ -281,7 +281,7 @@ decl_module! { /// Update pallet parameter. /// - /// May only be called either by root, or by `ModuleOwner`. + /// May only be called either by root, or by `PalletOwner`. /// /// The weight is: single read for permissions check + 2 writes for parameter value and event. #[weight = (T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational)] @@ -602,7 +602,7 @@ decl_module! { } } -impl, I: Instance> Module { +impl, I: Instance> Pallet { /// Get payload of given outbound message. pub fn outbound_message_payload(lane: LaneId, nonce: MessageNonce) -> Option { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(|message_data| message_data.payload) @@ -686,11 +686,11 @@ pub mod storage_keys { } } -/// Ensure that the origin is either root, or `ModuleOwner`. +/// Ensure that the origin is either root, or `PalletOwner`. fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) if Some(signer) == Module::::module_owner().as_ref() => Ok(()), + Ok(RawOrigin::Signed(ref signer)) if Some(signer) == Pallet::::module_owner().as_ref() => Ok(()), _ => Err(BadOrigin), } } @@ -854,7 +854,7 @@ mod tests { }; use bp_messages::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; - use frame_system::{EventRecord, Module as System, Phase}; + use frame_system::{EventRecord, Pallet as System, Phase}; use hex_literal::hex; use sp_runtime::DispatchError; @@ -866,7 +866,7 @@ mod tests { fn send_regular_message() { get_ready_for_events(); - assert_ok!(Module::::send_message( + assert_ok!(Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, @@ -891,7 +891,7 @@ mod tests { System::::set_block_number(1); System::::reset_events(); - assert_ok!(Module::::receive_messages_delivery_proof( + assert_ok!(Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, @@ -916,56 +916,56 @@ mod tests { #[test] fn pallet_owner_may_change_owner() { run_test(|| { - ModuleOwner::::put(2); + PalletOwner::::put(2); - assert_ok!(Module::::set_owner(Origin::root(), Some(1))); + assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); assert_noop!( - Module::::set_operational(Origin::signed(2), false), + Pallet::::set_operational(Origin::signed(2), false), DispatchError::BadOrigin, ); - assert_ok!(Module::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operational(Origin::root(), false)); - assert_ok!(Module::::set_owner(Origin::signed(1), None)); + assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); assert_noop!( - Module::::set_operational(Origin::signed(1), true), + Pallet::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); assert_noop!( - Module::::set_operational(Origin::signed(2), true), + Pallet::::set_operational(Origin::signed(2), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operational(Origin::root(), true)); }); } #[test] fn pallet_may_be_halted_by_root() { run_test(|| { - assert_ok!(Module::::set_operational(Origin::root(), false)); - assert_ok!(Module::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operational(Origin::root(), true)); }); } #[test] fn pallet_may_be_halted_by_owner() { run_test(|| { - ModuleOwner::::put(2); + PalletOwner::::put(2); - assert_ok!(Module::::set_operational(Origin::signed(2), false)); - assert_ok!(Module::::set_operational(Origin::signed(2), true)); + assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); + assert_ok!(Pallet::::set_operational(Origin::signed(2), true)); assert_noop!( - Module::::set_operational(Origin::signed(1), false), + Pallet::::set_operational(Origin::signed(1), false), DispatchError::BadOrigin, ); assert_noop!( - Module::::set_operational(Origin::signed(1), true), + Pallet::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); - assert_ok!(Module::::set_operational(Origin::signed(2), false)); + assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); assert_noop!( - Module::::set_operational(Origin::signed(1), true), + Pallet::::set_operational(Origin::signed(1), true), DispatchError::BadOrigin, ); }); @@ -977,7 +977,7 @@ mod tests { get_ready_for_events(); let parameter = TestMessagesParameter::TokenConversionRate(10.into()); - assert_ok!(Module::::update_pallet_parameter( + assert_ok!(Pallet::::update_pallet_parameter( Origin::root(), parameter.clone(), )); @@ -997,11 +997,11 @@ mod tests { #[test] fn pallet_parameter_may_be_updated_by_owner() { run_test(|| { - ModuleOwner::::put(2); + PalletOwner::::put(2); get_ready_for_events(); let parameter = TestMessagesParameter::TokenConversionRate(10.into()); - assert_ok!(Module::::update_pallet_parameter( + assert_ok!(Pallet::::update_pallet_parameter( Origin::signed(2), parameter.clone(), )); @@ -1022,17 +1022,17 @@ mod tests { fn pallet_parameter_cant_be_updated_by_arbitrary_submitter() { run_test(|| { assert_noop!( - Module::::update_pallet_parameter( + Pallet::::update_pallet_parameter( Origin::signed(2), TestMessagesParameter::TokenConversionRate(10.into()), ), DispatchError::BadOrigin, ); - ModuleOwner::::put(2); + PalletOwner::::put(2); assert_noop!( - Module::::update_pallet_parameter( + Pallet::::update_pallet_parameter( Origin::signed(1), TestMessagesParameter::TokenConversionRate(10.into()), ), @@ -1075,7 +1075,7 @@ mod tests { IsHalted::::put(true); assert_noop!( - Module::::send_message( + Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, @@ -1085,7 +1085,7 @@ mod tests { ); assert_noop!( - Module::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(2, REGULAR_PAYLOAD)]).into(), @@ -1096,7 +1096,7 @@ mod tests { ); assert_noop!( - Module::::receive_messages_delivery_proof( + Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, @@ -1124,7 +1124,7 @@ mod tests { run_test(|| { // messages with this payload are rejected by target chain verifier assert_noop!( - Module::::send_message( + Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN, @@ -1140,7 +1140,7 @@ mod tests { run_test(|| { // messages with zero fee are rejected by lane verifier assert_noop!( - Module::::send_message(Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 0), + Pallet::::send_message(Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 0), Error::::MessageRejectedByLaneVerifier, ); }); @@ -1151,7 +1151,7 @@ mod tests { run_test(|| { TestMessageDeliveryAndDispatchPayment::reject_payments(); assert_noop!( - Module::::send_message( + Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, @@ -1165,7 +1165,7 @@ mod tests { #[test] fn receive_messages_proof_works() { run_test(|| { - assert_ok!(Module::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), @@ -1191,7 +1191,7 @@ mod tests { }, ); assert_eq!( - Module::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + Pallet::::inbound_unrewarded_relayers_state(TEST_LANE_ID), UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, @@ -1206,7 +1206,7 @@ mod tests { ..Default::default() }); - assert_ok!(Module::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, message_proof, @@ -1224,7 +1224,7 @@ mod tests { }, ); assert_eq!( - Module::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + Pallet::::inbound_unrewarded_relayers_state(TEST_LANE_ID), UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, @@ -1238,7 +1238,7 @@ mod tests { fn receive_messages_proof_rejects_invalid_dispatch_weight() { run_test(|| { assert_noop!( - Module::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), @@ -1254,7 +1254,7 @@ mod tests { fn receive_messages_proof_rejects_invalid_proof() { run_test(|| { assert_noop!( - Module::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Err(()).into(), @@ -1270,7 +1270,7 @@ mod tests { fn receive_messages_proof_rejects_proof_with_too_many_messages() { run_test(|| { assert_noop!( - Module::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), @@ -1298,13 +1298,13 @@ mod tests { #[test] fn receive_messages_delivery_proof_rewards_relayers() { run_test(|| { - assert_ok!(Module::::send_message( + assert_ok!(Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 1000, )); - assert_ok!(Module::::send_message( + assert_ok!(Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, @@ -1312,7 +1312,7 @@ mod tests { )); // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A - assert_ok!(Module::::receive_messages_delivery_proof( + assert_ok!(Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, @@ -1337,7 +1337,7 @@ mod tests { )); // this reports delivery of both message 1 and message 2 => reward is paid only to TEST_RELAYER_B - assert_ok!(Module::::receive_messages_delivery_proof( + assert_ok!(Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, @@ -1369,7 +1369,7 @@ mod tests { fn receive_messages_delivery_proof_rejects_invalid_proof() { run_test(|| { assert_noop!( - Module::::receive_messages_delivery_proof( + Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Err(())), Default::default(), @@ -1384,7 +1384,7 @@ mod tests { run_test(|| { // when number of relayers entires is invalid assert_noop!( - Module::::receive_messages_delivery_proof( + Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, @@ -1406,7 +1406,7 @@ mod tests { // when number of messages is invalid assert_noop!( - Module::::receive_messages_delivery_proof( + Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, @@ -1434,7 +1434,7 @@ mod tests { let mut invalid_message = message(1, REGULAR_PAYLOAD); invalid_message.data.payload = Vec::new(); - assert_ok!(Module::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![invalid_message]).into(), @@ -1455,7 +1455,7 @@ mod tests { let mut invalid_message = message(2, REGULAR_PAYLOAD); invalid_message.data.payload = Vec::new(); - assert_ok!(Module::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![ @@ -1522,7 +1522,7 @@ mod tests { let message3 = message(2, TestPayload(0, Weight::MAX / 2)); assert_noop!( - Module::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, // this may cause overflow if source chain storage is invalid @@ -1542,7 +1542,7 @@ mod tests { receive_messages_delivery_proof(); assert_noop!( - Module::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), Error::::MessageIsAlreadyDelivered, ); }); @@ -1552,7 +1552,7 @@ mod tests { fn increase_message_fee_fails_if_message_is_not_yet_sent() { run_test(|| { assert_noop!( - Module::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), Error::::MessageIsNotYetSent, ); }); @@ -1566,7 +1566,7 @@ mod tests { TestMessageDeliveryAndDispatchPayment::reject_payments(); assert_noop!( - Module::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), Error::::FailedToWithdrawMessageFee, ); }); @@ -1577,7 +1577,7 @@ mod tests { run_test(|| { send_regular_message(); - assert_ok!(Module::::increase_message_fee( + assert_ok!(Pallet::::increase_message_fee( Origin::signed(1), TEST_LANE_ID, 1, diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 8cd764e4417dc..e640fa7805426 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -64,9 +64,9 @@ frame_support::construct_runtime! { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Balances: pallet_balances::{Module, Call, Event}, - Messages: pallet_bridge_messages::{Module, Call, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Event}, + Messages: pallet_bridge_messages::{Pallet, Call, Event}, } } @@ -100,6 +100,7 @@ impl frame_system::Config for TestRuntime { type BlockLength = (); type DbWeight = (); type SS58Prefix = (); + type OnSetCode = (); } parameter_types! { @@ -112,7 +113,7 @@ impl pallet_balances::Config for TestRuntime { type DustRemoval = (); type Event = Event; type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Module; + type AccountStore = frame_system::Pallet; type WeightInfo = (); } diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 6df5cae377385..0d867657afa9d 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -31,13 +31,13 @@ decl_module! { } decl_storage! { - trait Store for Module as ShiftSessionManager { + trait Store for Pallet as ShiftSessionManager { /// Validators of first two sessions. InitialValidators: Option>; } } -impl pallet_session::SessionManager for Module { +impl pallet_session::SessionManager for Pallet { fn end_session(_: sp_staking::SessionIndex) {} fn start_session(_: sp_staking::SessionIndex) {} fn new_session(session_index: sp_staking::SessionIndex) -> Option> { @@ -52,7 +52,7 @@ impl pallet_session::SessionManager for Module { // then for every session we select (deterministically) 2/3 of these initial // validators to serve validators of new session let available_validators = InitialValidators::::get().unwrap_or_else(|| { - let validators = >::validators(); + let validators = >::validators(); InitialValidators::::put(validators.clone()); validators }); @@ -61,7 +61,7 @@ impl pallet_session::SessionManager for Module { } } -impl Module { +impl Pallet { /// Select validators for session. fn select_validators( session_index: sp_staking::SessionIndex, @@ -110,8 +110,8 @@ mod tests { NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Module, Call, Config, Storage, Event}, - Session: pallet_session::{Module}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Session: pallet_session::{Pallet}, } } @@ -145,6 +145,7 @@ mod tests { type BlockLength = (); type DbWeight = (); type SS58Prefix = (); + type OnSetCode = (); } parameter_types! { @@ -193,7 +194,7 @@ mod tests { BasicExternalities::execute_with_storage(&mut t, || { for (ref k, ..) in &keys { - frame_system::Module::::inc_providers(k); + frame_system::Pallet::::inc_providers(k); } }); @@ -209,19 +210,19 @@ mod tests { let all_accs = vec![1, 2, 3, 4, 5]; // at least 1 validator is selected - assert_eq!(Module::::select_validators(0, &[1]), vec![1],); + assert_eq!(Pallet::::select_validators(0, &[1]), vec![1],); // at session#0, shift is also 0 - assert_eq!(Module::::select_validators(0, &all_accs), vec![1, 2, 3],); + assert_eq!(Pallet::::select_validators(0, &all_accs), vec![1, 2, 3],); // at session#1, shift is also 1 - assert_eq!(Module::::select_validators(1, &all_accs), vec![2, 3, 4],); + assert_eq!(Pallet::::select_validators(1, &all_accs), vec![2, 3, 4],); // at session#3, we're wrapping - assert_eq!(Module::::select_validators(3, &all_accs), vec![4, 5, 1],); + assert_eq!(Pallet::::select_validators(3, &all_accs), vec![4, 5, 1],); // at session#5, we're starting from the beginning again - assert_eq!(Module::::select_validators(5, &all_accs), vec![1, 2, 3],); + assert_eq!(Pallet::::select_validators(5, &all_accs), vec![1, 2, 3],); }); } } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index cb8f047cbd80c..22f09cb5b0930 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -76,7 +76,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; /// Weight of single regular message delivery transaction on Millau chain. /// -/// This value is a result of `pallet_bridge_messages::Module::receive_messages_proof_weight()` call +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. /// The message must have dispatch weight set to zero. The result then must be rounded up to account /// possible future runtime upgrades. @@ -90,7 +90,7 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Millau chain. /// -/// This value is a result of `pallet_bridge_messages::Module::receive_messages_delivery_proof` weight formula computation +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula computation /// for the case when single message is confirmed. The result then must be rounded up to account possible future /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index feeeadf45a9bc..c10f31bae33f1 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -67,7 +67,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; /// Weight of single regular message delivery transaction on Rialto chain. /// -/// This value is a result of `pallet_bridge_messages::Module::receive_messages_proof_weight()` call +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. /// The message must have dispatch weight set to zero. The result then must be rounded up to account /// possible future runtime upgrades. @@ -81,7 +81,7 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Rialto chain. /// -/// This value is a result of `pallet_bridge_messages::Module::receive_messages_delivery_proof` weight formula computation +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula computation /// for the case when single message is confirmed. The result then must be rounded up to account possible future /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 3d1ce94c04313..a9c014238d586 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -41,7 +41,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - MockModule, + MockPallet, } impl sp_runtime::traits::Dispatchable for Call { diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index a2a354d9de7aa..139b430324391 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Module for checking GRANDPA Finality Proofs. +//! Pallet for checking GRANDPA Finality Proofs. //! //! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin //! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. diff --git a/relays/bin-ethereum/src/ethereum_client.rs b/relays/bin-ethereum/src/ethereum_client.rs index b57b407d774a4..71a3f38859b78 100644 --- a/relays/bin-ethereum/src/ethereum_client.rs +++ b/relays/bin-ethereum/src/ethereum_client.rs @@ -29,7 +29,7 @@ use relay_ethereum_client::{ }; use relay_rialto_client::HeaderId as RialtoHeaderId; use relay_utils::{HeaderId, MaybeConnectionError}; -use sp_runtime::Justification; +use sp_runtime::EncodedJustification; use std::collections::HashSet; // to encode/decode contract calls @@ -68,7 +68,7 @@ pub trait EthereumHighLevelRpc { params: EthereumSigningParams, contract_address: Address, id: RialtoHeaderId, - justification: Justification, + justification: EncodedJustification, ) -> RpcResult; /// Submit ethereum transaction. @@ -194,7 +194,7 @@ impl EthereumHighLevelRpc for EthereumClient { params: EthereumSigningParams, contract_address: Address, id: RialtoHeaderId, - justification: Justification, + justification: EncodedJustification, ) -> RpcResult { let _ = self .submit_ethereum_transaction( diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index c0f44da3dff82..4e7e433d82617 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -36,7 +36,7 @@ use relay_substrate_client::{ ConnectionParams as SubstrateConnectionParams, }; use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; -use sp_runtime::Justification; +use sp_runtime::EncodedJustification; use std::fmt::Debug; use std::{collections::HashSet, time::Duration}; @@ -84,7 +84,7 @@ impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { type Number = rialto_runtime::BlockNumber; type Header = RialtoSyncHeader; type Extra = (); - type Completion = Justification; + type Completion = EncodedJustification; fn estimate_size(source: &QueuedHeader) -> usize { source.header().encode().len() @@ -151,7 +151,11 @@ impl TargetClient for EthereumHeadersTarget { self.client.incomplete_substrate_headers(self.contract).await } - async fn complete_header(&self, id: RialtoHeaderId, completion: Justification) -> Result { + async fn complete_header( + &self, + id: RialtoHeaderId, + completion: EncodedJustification, + ) -> Result { self.client .complete_substrate_header(self.sign_params.clone(), self.contract, id, completion) .await diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 83252358a746d..48feac3834e4e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -32,6 +32,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 07e0a9e17c391..6676873ee61b3 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -24,7 +24,7 @@ use sp_runtime::{ traits::{ AtLeast32Bit, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member, }, - Justification, + EncodedJustification, }; use std::{fmt::Debug, time::Duration}; @@ -71,7 +71,7 @@ pub trait BlockWithJustification
{ /// Return block header. fn header(&self) -> Header; /// Return block justification, if known. - fn justification(&self) -> Option<&Justification>; + fn justification(&self) -> Option<&EncodedJustification>; } /// Substrate-based chain transactions signing scheme. @@ -97,7 +97,9 @@ impl BlockWithJustification for SignedBlock self.block.header().clone() } - fn justification(&self) -> Option<&Justification> { - self.justification.as_ref() + fn justification(&self) -> Option<&EncodedJustification> { + self.justifications + .as_ref() + .and_then(|j| j.get(sp_finality_grandpa::GRANDPA_ENGINE_ID)) } } diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 3bd3df9098c00..68fef1c4c9c29 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Module provides a set of guard functions that are running in background threads +//! Pallet provides a set of guard functions that are running in background threads //! and are aborting process if some condition fails. use crate::{Chain, ChainWithBalances, Client}; diff --git a/relays/client-substrate/src/headers_source.rs b/relays/client-substrate/src/headers_source.rs index ad53a33a9f5fa..3dfcb220de453 100644 --- a/relays/client-substrate/src/headers_source.rs +++ b/relays/client-substrate/src/headers_source.rs @@ -26,7 +26,7 @@ use headers_relay::{ sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; use relay_utils::relay_loop::Client as RelayClient; -use sp_runtime::{traits::Header as HeaderT, Justification}; +use sp_runtime::{traits::Header as HeaderT, EncodedJustification}; use std::marker::PhantomData; /// Substrate node as headers source. @@ -69,7 +69,7 @@ where C: Chain, C::BlockNumber: relay_utils::BlockNumberBase, C::Header: Into, - P: HeadersSyncPipeline, + P: HeadersSyncPipeline, P::Header: SourceHeader, { async fn best_block_number(&self) -> Result { diff --git a/relays/headers/src/lib.rs b/relays/headers/src/lib.rs index 94cfd83f40644..8946355921f0d 100644 --- a/relays/headers/src/lib.rs +++ b/relays/headers/src/lib.rs @@ -16,7 +16,7 @@ //! Relaying source chain headers to target chain. This module provides entrypoint //! that starts reading new headers from source chain and submit these headers as -//! module/contract transactions to the target chain. Module/contract on the target +//! module/contract transactions to the target chain. Pallet/contract on the target //! chain is a light-client of the source chain. All other trustless bridge //! applications are built using this light-client, so running headers-relay is //! essential for running all other bridge applications. From 379bfa717bef217af072d7c81abbeb3efeebd9ce Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 7 Apr 2021 19:50:16 -0400 Subject: [PATCH 0414/1210] Westend Mock Runtime and Client (#874) * Copy-Pasta Call code from mock Rococo to mock Westend runtime * Update Westend client to include signing and call related code * Add missing part of license header * Move `account_info_storage_key` to `polkadot-core` crate --- primitives/chain-rococo/Cargo.toml | 5 -- primitives/chain-rococo/src/lib.rs | 43 ++-------------- primitives/chain-westend/Cargo.toml | 4 ++ primitives/chain-westend/src/lib.rs | 18 +++++++ primitives/polkadot-core/Cargo.toml | 3 ++ primitives/polkadot-core/src/lib.rs | 34 +++++++++++- relays/client-rococo/src/lib.rs | 9 ++-- relays/client-westend/src/lib.rs | 80 +++++++++++++++++++++++++++-- 8 files changed, 143 insertions(+), 53 deletions(-) diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 667b11275ff3a..acdbfc6c51e05 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -15,22 +15,17 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -[dev-dependencies] -hex = "0.4" - [features] default = ["std"] std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", - "frame-support/std", "parity-scale-codec/std", "sp-api/std", "sp-runtime/std", diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a9c014238d586..38dd92561b2fb 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -21,12 +21,14 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; -use frame_support::{Blake2_128Concat, StorageHasher, Twox128}; use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +/// Rococo Chain +pub type Rococo = PolkadotLike; + pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; pub const VERSION: RuntimeVersion = RuntimeVersion { @@ -55,29 +57,6 @@ impl sp_runtime::traits::Dispatchable for Call { } } -/// Return a storage key for account data. -/// -/// This is based on FRAME storage-generation code from Substrate: -/// https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74 -/// The equivalent command to invoke in case full `Runtime` is known is this: -/// `let key = frame_system::Account::::storage_map_final_key(&account_id);` -pub fn account_info_storage_key(id: &AccountId) -> Vec { - let module_prefix_hashed = Twox128::hash(b"System"); - let storage_prefix_hashed = Twox128::hash(b"Account"); - let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash); - - let mut final_key = Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); - - final_key.extend_from_slice(&module_prefix_hashed[..]); - final_key.extend_from_slice(&storage_prefix_hashed[..]); - final_key.extend_from_slice(&key_hashed); - - final_key -} - -/// Rococo Chain -pub type Rococo = PolkadotLike; - // We use this to get the account on Rococo (target) which is derived from Westend's (source) // account. pub fn derive_account_from_westend_id(id: bp_runtime::SourceAccount) -> AccountId { @@ -165,19 +144,3 @@ sp_api::decl_runtime_apis! { fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_generate_storage_key() { - let acc = [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, - ] - .into(); - let key = account_info_storage_key(&acc); - assert_eq!(hex::encode(key), "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92dccd599abfe1920a1cff8a7358231430102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"); - } -} diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 3552141da5773..c96e8703d8087 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } @@ -15,6 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -24,7 +26,9 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "parity-scale-codec/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index c4f4b0b644a36..3b52534afa7ca 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -29,6 +29,8 @@ pub use bp_polkadot_core::*; /// Westend Chain pub type Westend = PolkadotLike; +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + /// Runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("westend"), @@ -40,6 +42,22 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 5, }; +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + MockModule, +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} + // We use this to get the account on Westend (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index af5fe84d2a688..995f948e5d476 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -24,6 +24,9 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +hex = "0.4" + [features] default = ["std"] std = [ diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 94e9dda903509..8cf62c0030974 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -25,7 +25,7 @@ use frame_support::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, DispatchClass, Weight, }, - RuntimeDebug, + Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128, }; use frame_system::limits; use sp_core::Hasher as HasherT; @@ -34,6 +34,7 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, MultiSignature, OpaqueExtrinsic, Perbill, }; +use sp_std::prelude::Vec; // Re-export's to avoid extra substrate dependencies in chain-specific crates. pub use frame_support::Parameter; @@ -290,6 +291,26 @@ impl Convert for AccountIdConverter { } } +/// Return a storage key for account data. +/// +/// This is based on FRAME storage-generation code from Substrate: +/// https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74 +/// The equivalent command to invoke in case full `Runtime` is known is this: +/// `let key = frame_system::Account::::storage_map_final_key(&account_id);` +pub fn account_info_storage_key(id: &AccountId) -> Vec { + let module_prefix_hashed = Twox128::hash(b"System"); + let storage_prefix_hashed = Twox128::hash(b"Account"); + let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash); + + let mut final_key = Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(&key_hashed); + + final_key +} + #[cfg(test)] mod tests { use super::*; @@ -305,4 +326,15 @@ mod tests { MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, ); } + + #[test] + fn should_generate_storage_key() { + let acc = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, + ] + .into(); + let key = account_info_storage_key(&acc); + assert_eq!(hex::encode(key), "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92dccd599abfe1920a1cff8a7358231430102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"); + } } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 3661b31e69e32..ccf7a8916348f 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -1,3 +1,6 @@ +// 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 @@ -22,6 +25,9 @@ use std::time::Duration; /// Rococo header id. pub type HeaderId = relay_utils::HeaderId; +/// Rococo header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + /// Rococo chain definition #[derive(Debug, Clone, Copy)] pub struct Rococo; @@ -111,6 +117,3 @@ impl Default for SigningParams { } } } - -/// Rococo header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index c8594a925dd1b..0a6569512a259 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,12 +16,18 @@ //! Types used to connect to the Westend chain. -use relay_substrate_client::{Chain, ChainBase}; +use codec::Encode; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; /// Westend header id. pub type HeaderId = relay_utils::HeaderId; +/// Westend header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + /// Westend chain definition #[derive(Debug, Clone, Copy)] pub struct Westend; @@ -40,8 +46,74 @@ impl Chain for Westend { type AccountId = bp_westend::AccountId; type Index = bp_westend::Nonce; type SignedBlock = bp_westend::SignedBlock; - type Call = (); + type Call = bp_westend::Call; } -/// Westend header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; +impl ChainWithBalances for Westend { + type NativeBalance = bp_westend::Balance; + + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_westend::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for Westend { + type Chain = Westend; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = bp_westend::UncheckedExtrinsic; + + fn sign_transaction( + genesis_hash: ::Hash, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + call, + bp_westend::SignedExtensions::new( + bp_westend::VERSION, + sp_runtime::generic::Era::Immortal, + genesis_hash, + signer_nonce, + 0, + ), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_westend::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + } +} + +/// Westend signing params. +#[derive(Clone)] +pub struct SigningParams { + /// Substrate transactions signer. + pub signer: sp_core::sr25519::Pair, +} + +impl SigningParams { + /// Create signing params from SURI and password. + pub fn from_suri(suri: &str, password: Option<&str>) -> Result { + Ok(SigningParams { + signer: sp_core::sr25519::Pair::from_string(suri, password)?, + }) + } +} + +impl std::fmt::Debug for SigningParams { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.signer.public()) + } +} + +impl Default for SigningParams { + fn default() -> Self { + SigningParams { + signer: sp_keyring::AccountKeyring::Alice.pair(), + } + } +} From 162effc3aa3a9508329eba3ab74ccc4473863bc6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Apr 2021 15:00:05 +0300 Subject: [PATCH 0415/1210] Install CA certificates in relay images (#880) * update CA certificates in relay images * clippy * clippy * clippy --- relays/bin-ethereum/src/rialto_client.rs | 4 ++-- .../src/rialto_millau/millau_headers_to_rialto.rs | 2 +- .../src/rialto_millau/millau_messages_to_rialto.rs | 6 +++--- .../src/rialto_millau/rialto_headers_to_millau.rs | 2 +- .../src/rialto_millau/rialto_messages_to_millau.rs | 6 +++--- .../src/rialto_millau/westend_headers_to_millau.rs | 2 +- relays/headers/src/sync_loop.rs | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index c294edbf4e877..d9c0f265cbb95 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -156,7 +156,7 @@ impl SubmitEthereumHeaders for SubstrateClient { ) -> SubmittedHeaders { let ids = headers.iter().map(|header| header.id()).collect(); let submission_result = async { - self.submit_signed_extrinsic(params.public().as_array_ref().clone().into(), |transaction_nonce| { + self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), |transaction_nonce| { Bytes( Rialto::sign_transaction( *self.genesis_hash(), @@ -257,7 +257,7 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { instance: Arc, proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { - self.submit_signed_extrinsic(params.public().as_array_ref().clone().into(), |transaction_nonce| { + self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), |transaction_nonce| { Bytes( Rialto::sign_transaction( *self.genesis_hash(), diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs index 3091df31ff1eb..58f0620b0764b 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs @@ -34,7 +34,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { type TargetChain = Rialto; fn transactions_author(&self) -> bp_rialto::AccountId { - self.target_sign.public().as_array_ref().clone().into() + (*self.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index 0e80aacc176da..82c3dbaa3bc7e 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -59,7 +59,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { type TargetChain = Rialto; fn source_transactions_author(&self) -> bp_rialto::AccountId { - self.source_sign.public().as_array_ref().clone().into() + (*self.source_sign.public().as_array_ref()).into() } fn make_messages_receiving_proof_transaction( @@ -86,7 +86,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } fn target_transactions_author(&self) -> bp_rialto::AccountId { - self.target_sign.public().as_array_ref().clone().into() + (*self.target_sign.public().as_array_ref()).into() } fn make_messages_delivery_transaction( @@ -141,7 +141,7 @@ pub async fn run( metrics_params: MetricsParams, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id_at_millau = millau_sign.public().as_array_ref().clone().into(); + let relayer_id_at_millau = (*millau_sign.public().as_array_ref()).into(); let lane = MillauMessagesToRialto { source_client: millau_client.clone(), diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs index 1c36991fd2727..39295c89433e8 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs @@ -34,7 +34,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { type TargetChain = Millau; fn transactions_author(&self) -> bp_millau::AccountId { - self.target_sign.public().as_array_ref().clone().into() + (*self.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index ed231cd208e9e..b98edccdc2dfb 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -59,7 +59,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { type TargetChain = Millau; fn source_transactions_author(&self) -> bp_rialto::AccountId { - self.source_sign.public().as_array_ref().clone().into() + (*self.source_sign.public().as_array_ref()).into() } fn make_messages_receiving_proof_transaction( @@ -86,7 +86,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } fn target_transactions_author(&self) -> bp_rialto::AccountId { - self.target_sign.public().as_array_ref().clone().into() + (*self.target_sign.public().as_array_ref()).into() } fn make_messages_delivery_transaction( @@ -141,7 +141,7 @@ pub async fn run( metrics_params: MetricsParams, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id_at_rialto = rialto_sign.public().as_array_ref().clone().into(); + let relayer_id_at_rialto = (*rialto_sign.public().as_array_ref()).into(); let lane = RialtoMessagesToMillau { source_client: rialto_client.clone(), diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index ac69a7437ed3d..c6f9a1fd3d8ba 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -58,7 +58,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { } fn transactions_author(&self) -> bp_millau::AccountId { - self.target_sign.public().as_array_ref().clone().into() + (*self.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index 2e0d12ec87c8f..d193996d0c301 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -628,5 +628,5 @@ fn print_sync_progress( now_best_header.map(|id| id.0), now_target_header, ); - (now_time, now_best_header.clone().map(|id| id.0), *now_target_header) + (now_time, (*now_best_header).map(|id| id.0), *now_target_header) } From ca515ba985a5d5936485d5ced95426c5a0cb8f9a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 12 Apr 2021 15:16:35 -0400 Subject: [PATCH 0416/1210] Use new Cargo feature resolver (#891) * Use new Cargo feature resolver * Simplify runtime benchmark CI commands * Add `runtime-benchmarks` feature to Millau runtime --- bin/millau/runtime/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 411835ab6fec7..e1f7ed10c63e6 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -101,3 +101,6 @@ std = [ "sp-trie/std", "sp-version/std", ] +# TODO: https://github.com/paritytech/parity-bridges-common/issues/390 +# I've left the feature flag here to test our CI configuration +runtime-benchmarks = [] From e77a969ea05a561531ec09cd0f24732d94ef482e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 12 Apr 2021 17:22:24 -0400 Subject: [PATCH 0417/1210] Bump `jsonrpsee` to Alpha.3 (#892) * Bump `jsonrpsee` to `alpha.3` * Arc-ify `WsClient` --- relays/client-ethereum/Cargo.toml | 6 ++-- relays/client-substrate/Cargo.toml | 6 ++-- relays/client-substrate/src/client.rs | 41 ++++++++++++++------------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 79f6ab0cf6feb..56e346417301b 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -10,9 +10,9 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = "0.2.0-alpha.2" -jsonrpsee-types = "0.2.0-alpha.2" -jsonrpsee-ws-client = "0.2.0-alpha.2" +jsonrpsee-proc-macros = "=0.2.0-alpha.3" +jsonrpsee-types = "=0.2.0-alpha.3" +jsonrpsee-ws-client = "=0.2.0-alpha.3" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 48feac3834e4e..e70351877c2e0 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } -jsonrpsee-proc-macros = "0.2.0-alpha.2" -jsonrpsee-types = "0.2.0-alpha.2" -jsonrpsee-ws-client = "0.2.0-alpha.2" +jsonrpsee-proc-macros = "=0.2.0-alpha.3" +jsonrpsee-types = "=0.2.0-alpha.3" +jsonrpsee-ws-client = "=0.2.0-alpha.3" log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index a149ba69701f6..34763e9979eaf 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -50,7 +50,7 @@ pub struct Client { /// Client connection params. params: ConnectionParams, /// Substrate RPC client. - client: RpcClient, + client: Arc, /// Genesis block hash. genesis_hash: C::Hash, /// If several tasks are submitting their transactions simultaneously using `submit_signed_extrinsic` @@ -84,7 +84,7 @@ impl Client { let client = Self::build_client(params.clone()).await?; let number: C::BlockNumber = Zero::zero(); - let genesis_hash = Substrate::::chain_get_block_hash(&client, number).await?; + let genesis_hash = Substrate::::chain_get_block_hash(&*client, number).await?; Ok(Self { params, @@ -101,7 +101,7 @@ impl Client { } /// Build client to use in connection. - async fn build_client(params: ConnectionParams) -> Result { + async fn build_client(params: ConnectionParams) -> Result> { let uri = format!( "{}://{}:{}", if params.secure { "wss" } else { "ws" }, @@ -111,14 +111,15 @@ impl Client { let mut config = RpcConfig::with_url(&uri); config.max_notifs_per_subscription = MAX_SUBSCRIPTION_CAPACITY; let client = RpcClient::new(config).await?; - Ok(client) + + Ok(Arc::new(client)) } } impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { - let health = Substrate::::system_health(&self.client).await?; + let health = Substrate::::system_health(&*self.client).await?; let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); if is_synced { Ok(()) @@ -134,7 +135,7 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { - Ok(Substrate::::chain_get_finalized_head(&self.client).await?) + Ok(Substrate::::chain_get_finalized_head(&*self.client).await?) } /// Returns the best Substrate header. @@ -142,12 +143,12 @@ impl Client { where C::Header: DeserializeOwned, { - Ok(Substrate::::chain_get_header(&self.client, None).await?) + Ok(Substrate::::chain_get_header(&*self.client, None).await?) } /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { - Ok(Substrate::::chain_get_block(&self.client, block_hash).await?) + Ok(Substrate::::chain_get_block(&*self.client, block_hash).await?) } /// Get a Substrate header by its hash. @@ -155,12 +156,12 @@ impl Client { where C::Header: DeserializeOwned, { - Ok(Substrate::::chain_get_header(&self.client, block_hash).await?) + Ok(Substrate::::chain_get_header(&*self.client, block_hash).await?) } /// Get a Substrate block hash by its number. pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { - Ok(Substrate::::chain_get_block_hash(&self.client, number).await?) + Ok(Substrate::::chain_get_block_hash(&*self.client, number).await?) } /// Get a Substrate header by its number. @@ -174,12 +175,12 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { - Ok(Substrate::::runtime_version(&self.client).await?) + Ok(Substrate::::runtime_version(&*self.client).await?) } /// Read value from runtime storage. pub async fn storage_value(&self, storage_key: StorageKey) -> Result> { - Substrate::::get_storage(&self.client, storage_key) + Substrate::::get_storage(&*self.client, storage_key) .await? .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) .transpose() @@ -191,7 +192,7 @@ impl Client { C: ChainWithBalances, { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = Substrate::::get_storage(&self.client, storage_key) + let encoded_account_data = Substrate::::get_storage(&*self.client, storage_key) .await? .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = @@ -204,14 +205,14 @@ impl Client { /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { - Ok(Substrate::::system_account_next_index(&self.client, account).await?) + Ok(Substrate::::system_account_next_index(&*self.client, account).await?) } /// Submit unsigned extrinsic for inclusion in a block. /// /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { - let tx_hash = Substrate::::author_submit_extrinsic(&self.client, transaction).await?; + let tx_hash = Substrate::::author_submit_extrinsic(&*self.client, transaction).await?; log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); Ok(tx_hash) } @@ -231,7 +232,7 @@ impl Client { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; let extrinsic = prepare_extrinsic(transaction_nonce); - let tx_hash = Substrate::::author_submit_extrinsic(&self.client, extrinsic).await?; + let tx_hash = Substrate::::author_submit_extrinsic(&*self.client, extrinsic).await?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) } @@ -241,7 +242,7 @@ impl Client { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); - let encoded_response = Substrate::::state_call(&self.client, call, data, Some(block)).await?; + let encoded_response = Substrate::::state_call(&*self.client, call, data, Some(block)).await?; let authority_list = encoded_response.0; Ok(authority_list) @@ -249,7 +250,7 @@ impl Client { /// Execute runtime call at given block. pub async fn state_call(&self, method: String, data: Bytes, at_block: Option) -> Result { - Substrate::::state_call(&self.client, method, data, at_block) + Substrate::::state_call(&*self.client, method, data, at_block) .await .map_err(Into::into) } @@ -264,7 +265,7 @@ impl Client { at_block: C::Hash, ) -> Result { let encoded_trie_nodes = SubstrateMessages::::prove_messages( - &self.client, + &*self.client, instance, lane, *range.start(), @@ -287,7 +288,7 @@ impl Client { at_block: C::Hash, ) -> Result>> { let encoded_trie_nodes = - SubstrateMessages::::prove_messages_delivery(&self.client, instance, lane, Some(at_block)) + SubstrateMessages::::prove_messages_delivery(&*self.client, instance, lane, Some(at_block)) .await .map_err(Error::RpcError)?; let decoded_trie_nodes: Vec> = From e1f6ce05f59c856f7fc70b5cbe6279df604fe5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Apr 2021 09:37:26 +0200 Subject: [PATCH 0418/1210] CLI: Encode Message (#889) * Encode message. * Update docs related to `sender` Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Hernando Castano --- relays/bin-substrate/src/cli/bridge.rs | 2 + .../bin-substrate/src/cli/encode_message.rs | 106 ++++++++++++++++++ relays/bin-substrate/src/cli/mod.rs | 24 +--- relays/bin-substrate/src/rialto_millau/cli.rs | 51 +-------- relays/bin-substrate/src/rialto_millau/mod.rs | 34 ++---- 5 files changed, 123 insertions(+), 94 deletions(-) create mode 100644 relays/bin-substrate/src/cli/encode_message.rs diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 83a19f88c2788..a962aa674c7a6 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -48,6 +48,7 @@ macro_rules! select_full_bridge { match $bridge { FullBridge::MillauToRialto => { type Source = relay_millau_client::Millau; + #[allow(dead_code)] type Target = relay_rialto_client::Rialto; #[allow(unused_imports)] @@ -60,6 +61,7 @@ macro_rules! select_full_bridge { } FullBridge::RialtoToMillau => { type Source = relay_rialto_client::Rialto; + #[allow(dead_code)] type Target = relay_millau_client::Millau; #[allow(unused_imports)] diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs new file mode 100644 index 0000000000000..5ef668864ea56 --- /dev/null +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -0,0 +1,106 @@ +// 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 . + +use crate::cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}; +use crate::select_full_bridge; +use structopt::StructOpt; + +/// Generic message payload. +#[derive(StructOpt, Debug)] +pub enum MessagePayload { + /// Raw, SCALE-encoded `MessagePayload`. + Raw { + /// Hex-encoded SCALE data. + data: HexBytes, + }, + /// Construct message to send over the bridge. + Call { + /// Message details. + #[structopt(flatten)] + call: crate::cli::encode_call::Call, + /// SS58 encoded Source account that will send the payload. + #[structopt(long)] + sender: AccountId, + }, +} + +/// A `MessagePayload` to encode. +#[derive(StructOpt)] +pub struct EncodeMessage { + /// A bridge instance to initalize. + #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + bridge: FullBridge, + #[structopt(flatten)] + payload: MessagePayload, +} + +impl EncodeMessage { + /// Run the command. + pub fn encode(self) -> anyhow::Result { + select_full_bridge!(self.bridge, { + let payload = Source::encode_message(self.payload).map_err(|e| anyhow::format_err!("{}", e))?; + Ok(HexBytes::encode(&payload)) + }) + } + + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + let payload = self.encode()?; + println!("{:?}", payload); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::crypto::Ss58Codec; + + #[test] + fn should_encode_raw_message() { + // given + let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c040130000000000000000000000000"; + let encode_message = EncodeMessage::from_iter(vec!["encode-message", "MillauToRialto", "raw", msg]); + + // when + let hex = encode_message.encode().unwrap(); + + // then + assert_eq!(format!("{:?}", hex), format!("0x{}", msg)); + } + + #[test] + fn should_encode_remark_with_size() { + // given + let sender = sp_keyring::AccountKeyring::Alice.to_account_id().to_ss58check(); + let encode_message = EncodeMessage::from_iter(vec![ + "encode-message", + "RialtoToMillau", + "call", + "--sender", + &sender, + "remark", + "--remark-size", + "12", + ]); + + // when + let hex = encode_message.encode().unwrap(); + + // then + assert_eq!(format!("{:?}", hex), "0x01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c040130000000000000000000000000"); + } +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 0ddee88aeef0a..e291f7247020a 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -27,6 +27,7 @@ use structopt::{clap::arg_enum, StructOpt}; pub(crate) mod bridge; pub(crate) mod encode_call; +pub(crate) mod encode_message; mod derive_account; mod init_bridge; @@ -71,7 +72,7 @@ pub enum Command { /// /// The `MessagePayload` can be then fed to `Messages::send_message` function and sent over /// the bridge. - EncodeMessagePayload(EncodeMessagePayload), + EncodeMessage(encode_message::EncodeMessage), /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. EstimateFee(EstimateFee), /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. @@ -87,7 +88,7 @@ impl Command { Self::InitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, Self::EncodeCall(arg) => arg.run().await?, - Self::EncodeMessagePayload(arg) => arg.run().await?, + Self::EncodeMessage(arg) => arg.run().await?, Self::EstimateFee(arg) => arg.run().await?, Self::DeriveAccount(arg) => arg.run().await?, } @@ -112,23 +113,6 @@ impl SendMessage { } } -/// A `MessagePayload` to encode. -#[derive(StructOpt)] -pub enum EncodeMessagePayload { - #[structopt(flatten)] - RialtoMillau(rialto_millau::EncodeMessagePayload), -} - -impl EncodeMessagePayload { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - /// Estimate Delivery & Dispatch Fee command. #[derive(StructOpt)] pub enum EstimateFee { @@ -260,7 +244,7 @@ pub trait CliChain: relay_substrate_client::Chain { fn ss58_format() -> u16; /// Construct message payload to be sent over the bridge. - fn encode_message(message: crate::rialto_millau::cli::MessagePayload) -> Result; + fn encode_message(message: crate::cli::encode_message::MessagePayload) -> Result; /// Maximal extrinsic weight (from the runtime). fn max_extrinsic_weight() -> Weight; diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs index 9e5788b1cb69d..4c92ec1773841 100644 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/relays/bin-substrate/src/rialto_millau/cli.rs @@ -20,8 +20,7 @@ use frame_support::weights::Weight; use structopt::StructOpt; use crate::cli::{ - AccountId, Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, - TargetSigningParams, + Balance, ExplicitOrMaximal, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, TargetSigningParams, }; /// Send bridge message. @@ -89,31 +88,6 @@ impl SendMessage { } } -/// A `MessagePayload` to encode. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum EncodeMessagePayload { - /// Message Payload of Rialto to Millau call. - RialtoToMillau { - #[structopt(flatten)] - payload: MessagePayload, - }, - /// Message Payload of Millau to Rialto call. - MillauToRialto { - #[structopt(flatten)] - payload: MessagePayload, - }, -} - -impl EncodeMessagePayload { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_encode_message_payload(self).await.map_err(format_err)?; - Ok(()) - } -} - /// Estimate Delivery & Dispatch Fee command. /// /// TODO [#855] Move to separate module. @@ -128,7 +102,7 @@ pub enum EstimateFee { lane: HexLaneId, /// Payload to send over the bridge. #[structopt(flatten)] - payload: MessagePayload, + payload: crate::cli::encode_message::MessagePayload, }, /// Estimate fee of Rialto to Millau message. MillauToRialto { @@ -139,7 +113,7 @@ pub enum EstimateFee { lane: HexLaneId, /// Payload to send over the bridge. #[structopt(flatten)] - payload: MessagePayload, + payload: crate::cli::encode_message::MessagePayload, }, } @@ -154,22 +128,3 @@ impl EstimateFee { fn format_err(err: String) -> anyhow::Error { anyhow::anyhow!(err) } - -/// Generic message payload. -#[derive(StructOpt, Debug)] -pub enum MessagePayload { - /// Raw, SCALE-encoded `MessagePayload`. - Raw { - /// Hex-encoded SCALE data. - data: HexBytes, - }, - /// Construct message to send over the bridge. - Call { - /// Message details. - #[structopt(flatten)] - call: crate::cli::encode_call::Call, - /// SS58 encoded account that will send the payload (must have SS58Prefix = 42) - #[structopt(long)] - sender: AccountId, - }, -} diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index 13e8bc19c3717..d6e49ccf2cc2e 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -31,7 +31,7 @@ pub type RialtoClient = relay_substrate_client::Client; use crate::cli::{ bridge::{MILLAU_TO_RIALTO_INDEX, RIALTO_TO_MILLAU_INDEX}, encode_call::{self, Call, CliEncodeCall}, - CliChain, ExplicitOrMaximal, HexBytes, Origins, + encode_message, CliChain, ExplicitOrMaximal, HexBytes, Origins, }; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; @@ -267,24 +267,6 @@ async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { Ok(()) } -async fn run_encode_message_payload(call: cli::EncodeMessagePayload) -> Result<(), String> { - match call { - cli::EncodeMessagePayload::RialtoToMillau { payload } => { - type Source = Rialto; - - let payload = Source::encode_message(payload)?; - println!("{:?}", HexBytes::encode(&payload)); - } - cli::EncodeMessagePayload::MillauToRialto { payload } => { - type Source = Millau; - - let payload = Source::encode_message(payload)?; - println!("{:?}", HexBytes::encode(&payload)); - } - } - Ok(()) -} - async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { match cmd { cli::EstimateFee::RialtoToMillau { source, lane, payload } => { @@ -459,11 +441,11 @@ impl CliChain for Millau { } // TODO [#854|#843] support multiple bridges? - fn encode_message(message: cli::MessagePayload) -> Result { + fn encode_message(message: encode_message::MessagePayload) -> Result { match message { - cli::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), - cli::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender } => { type Source = Millau; type Target = Rialto; @@ -529,11 +511,11 @@ impl CliChain for Rialto { bp_rialto::max_extrinsic_weight() } - fn encode_message(message: cli::MessagePayload) -> Result { + fn encode_message(message: encode_message::MessagePayload) -> Result { match message { - cli::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), - cli::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender } => { type Source = Rialto; type Target = Millau; @@ -564,7 +546,7 @@ impl CliChain for Westend { 0 } - fn encode_message(_message: cli::MessagePayload) -> Result { + fn encode_message(_message: encode_message::MessagePayload) -> Result { Err("Sending messages from Westend is not yet supported.".into()) } } From db15dc171b4fddbea26da824f787f04339cded7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Apr 2021 12:37:08 +0200 Subject: [PATCH 0419/1210] CLI: Send Message (#886) * Send Message WiP * It compiles. * Add tests. * Use common macro. * Nicer balance display. * Get rid of redundant send_message_call function. * Fix clippy. Co-authored-by: Svyatoslav Nikolsky --- relays/bin-substrate/Cargo.toml | 2 + relays/bin-substrate/src/cli/bridge.rs | 18 ++ relays/bin-substrate/src/cli/init_bridge.rs | 6 +- relays/bin-substrate/src/cli/mod.rs | 41 +-- relays/bin-substrate/src/cli/relay_headers.rs | 8 +- .../bin-substrate/src/cli/relay_messages.rs | 8 +- relays/bin-substrate/src/cli/send_message.rs | 274 +++++++++++++++++ relays/bin-substrate/src/rialto_millau/cli.rs | 70 +---- relays/bin-substrate/src/rialto_millau/mod.rs | 277 +----------------- 9 files changed, 336 insertions(+), 368 deletions(-) create mode 100644 relays/bin-substrate/src/cli/send_message.rs diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 8942bf8130953..1a281a6d5861a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -13,6 +13,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0" } futures = "0.3.12" hex = "0.4" log = "0.4.14" +num-format = "0.4" num-traits = "0.2" paste = "1.0" structopt = "0.3" @@ -56,3 +57,4 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [dev-dependencies] sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +hex-literal = "0.3" diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index a962aa674c7a6..2184903e013e7 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -51,12 +51,21 @@ macro_rules! select_full_bridge { #[allow(dead_code)] type Target = relay_rialto_client::Rialto; + // Derive-account #[allow(unused_imports)] use bp_millau::derive_account_from_rialto_id as derive_account; + // Relay-messages #[allow(unused_imports)] use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages; + // Send-message + #[allow(unused_imports)] + use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use millau_runtime::rialto_account_ownership_digest as account_ownership_digest; + $generic } FullBridge::RialtoToMillau => { @@ -64,12 +73,21 @@ macro_rules! select_full_bridge { #[allow(dead_code)] type Target = relay_millau_client::Millau; + // Derive-account #[allow(unused_imports)] use bp_rialto::derive_account_from_millau_id as derive_account; + // Relay-messages #[allow(unused_imports)] use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages; + // Send-message + #[allow(unused_imports)] + use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use rialto_runtime::millau_account_ownership_digest as account_ownership_digest; + $generic } } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 4a073cfa1ddc5..a9923e71e9216 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -108,9 +108,9 @@ impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.into_client::().await?; - let target_client = self.target.into_client::().await?; - let target_sign = self.target_sign.into_keypair::()?; + let source_client = self.source.to_client::().await?; + let target_client = self.target.to_client::().await?; + let target_sign = self.target_sign.to_keypair::()?; crate::headers_initialize::initialize( source_client, diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index e291f7247020a..960e85ea92ae9 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -33,6 +33,7 @@ mod derive_account; mod init_bridge; mod relay_headers; mod relay_messages; +mod send_message; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -62,7 +63,7 @@ pub enum Command { /// Allows interacting with the bridge by sending messages over `Messages` component. /// The message is being sent to the source chain, delivered to the target chain and dispatched /// there. - SendMessage(SendMessage), + SendMessage(send_message::SendMessage), /// Generate SCALE-encoded `Call` for choosen network. /// /// The call can be used either as message payload or can be wrapped into a transaction @@ -96,23 +97,6 @@ impl Command { } } -/// Send bridge message. -#[derive(StructOpt)] -pub enum SendMessage { - #[structopt(flatten)] - RialtoMillau(rialto_millau::SendMessage), -} - -impl SendMessage { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - /// Estimate Delivery & Dispatch Fee command. #[derive(StructOpt)] pub enum EstimateFee { @@ -143,9 +127,16 @@ arg_enum! { } /// Generic balance type. -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct Balance(pub u128); +impl std::fmt::Display for Balance { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + use num_format::{Locale, ToFormattedString}; + write!(fmt, "{}", self.0.to_formatted_string(&Locale::en)) + } +} + impl std::str::FromStr for Balance { type Err = ::Err; @@ -251,7 +242,7 @@ pub trait CliChain: relay_substrate_client::Chain { } /// Lane id. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct HexLaneId(pub LaneId); impl From for LaneId { @@ -330,7 +321,7 @@ impl From for relay_utils::metrics::MetricsParams { } /// Either explicit or maximal allowed value. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ExplicitOrMaximal { /// User has explicitly specified argument value. Explicit(V), @@ -388,7 +379,7 @@ macro_rules! declare_chain_options { impl [<$chain SigningParams>] { /// Parse signing params into chain-specific KeyPair. - pub fn into_keypair(self) -> anyhow::Result { + pub fn to_keypair(&self) -> anyhow::Result { use sp_core::crypto::Pair; Chain::KeyPair::from_string( &self.[<$chain_prefix _signer>], @@ -399,11 +390,11 @@ macro_rules! declare_chain_options { impl [<$chain ConnectionParams>] { /// Convert connection params into Substrate client. - pub async fn into_client( - self, + pub async fn to_client( + &self, ) -> anyhow::Result> { Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { - host: self.[<$chain_prefix _host>], + host: self.[<$chain_prefix _host>].clone(), port: self.[<$chain_prefix _port>], secure: self.[<$chain_prefix _secure>], }) diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 44b9b70d2b993..a60bbe344d6eb 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -59,12 +59,14 @@ macro_rules! select_bridge { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; type Finality = crate::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; + $generic } RelayHeadersBridge::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; type Finality = crate::rialto_millau::westend_headers_to_millau::WestendFinalityToMillau; + $generic } } @@ -75,9 +77,9 @@ impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.into_client::().await?; - let target_client = self.target.into_client::().await?; - let target_sign = self.target_sign.into_keypair::()?; + let source_client = self.source.to_client::().await?; + let target_client = self.target.to_client::().await?; + let target_sign = self.target_sign.to_keypair::()?; let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; crate::finality_pipeline::run( diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index feedea66ef6ab..0e863f25c7a6c 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -47,10 +47,10 @@ impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_full_bridge!(self.bridge, { - let source_client = self.source.into_client::().await?; - let source_sign = self.source_sign.into_keypair::()?; - let target_client = self.target.into_client::().await?; - let target_sign = self.target_sign.into_keypair::()?; + let source_client = self.source.to_client::().await?; + let source_sign = self.source_sign.to_keypair::()?; + let target_client = self.target.to_client::().await?; + let target_sign = self.target_sign.to_keypair::()?; relay_messages( source_client, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs new file mode 100644 index 0000000000000..e6ab7dcfa7f02 --- /dev/null +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -0,0 +1,274 @@ +// 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 . + +use crate::cli::bridge::FullBridge; +use crate::cli::encode_call::{self, CliEncodeCall}; +use crate::cli::{ + Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, + TargetSigningParams, +}; +use codec::Encode; +use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; +use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; +use structopt::StructOpt; + +/// Send bridge message. +#[derive(StructOpt)] +pub struct SendMessage { + /// A bridge instance to encode call for. + #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + bridge: FullBridge, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + // TODO [#885] Move TargetSign to origins + #[structopt(flatten)] + target_sign: TargetSigningParams, + /// Hex-encoded lane id. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Dispatch weight of the message. If not passed, determined automatically. + #[structopt(long)] + dispatch_weight: Option>, + /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. + #[structopt(long)] + fee: Option, + /// Message type. + #[structopt(subcommand)] + message: crate::cli::encode_call::Call, + /// The origin to use when dispatching the message on the target chain. Defaults to + /// `SourceAccount`. + #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] + origin: Origins, +} + +impl SendMessage { + pub fn encode_payload( + &mut self, + ) -> anyhow::Result>> { + crate::select_full_bridge!(self.bridge, { + let SendMessage { + source_sign, + target_sign, + ref mut message, + dispatch_weight, + origin, + bridge, + .. + } = self; + + let source_sign = source_sign.to_keypair::()?; + let target_sign = target_sign.to_keypair::()?; + + encode_call::preprocess_call::(message, bridge.bridge_instance_index()); + let target_call = Target::encode_call(&message)?; + + let payload = { + let target_call_weight = prepare_call_dispatch_weight( + dispatch_weight, + ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), + crate::rialto_millau::compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), + ); + let source_sender_public: MultiSigner = source_sign.public().into(); + let source_account_id = source_sender_public.into_account(); + + crate::rialto_millau::message_payload( + Target::RUNTIME_VERSION.spec_version, + target_call_weight, + match origin { + Origins::Source => CallOrigin::SourceAccount(source_account_id), + Origins::Target => { + let digest = account_ownership_digest( + &target_call, + source_account_id.clone(), + Target::RUNTIME_VERSION.spec_version, + ); + let target_origin_public = target_sign.public(); + let digest_signature = target_sign.sign(&digest); + CallOrigin::TargetAccount( + source_account_id, + target_origin_public.into(), + digest_signature.into(), + ) + } + }, + &target_call, + ) + }; + Ok(payload) + }) + } + + /// Run the command. + pub async fn run(mut self) -> anyhow::Result<()> { + crate::select_full_bridge!(self.bridge, { + let payload = self.encode_payload()?; + + let source_client = self.source.to_client::().await?; + let source_sign = self.source_sign.to_keypair::()?; + + let lane = self.lane.clone().into(); + let fee = match self.fee { + Some(fee) => fee, + None => crate::rialto_millau::estimate_message_delivery_and_dispatch_fee::< + ::NativeBalance, + _, + _, + >(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone()) + .await? + .map(|v| Balance(v as _)) + .ok_or_else(|| anyhow::format_err!("Failed to estimate message fee. Message is too heavy?"))?, + }; + let dispatch_weight = payload.weight; + let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage { + bridge_instance_index: self.bridge.bridge_instance_index(), + lane: self.lane, + payload: HexBytes::encode(&payload), + fee, + })?; + + source_client + .submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| { + let signed_source_call = Source::sign_transaction( + *source_client.genesis_hash(), + &source_sign, + transaction_nonce, + send_message_call, + ) + .encode(); + + log::info!( + target: "bridge", + "Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}", + Target::NAME, + signed_source_call.len(), + dispatch_weight, + fee, + ); + log::info!( + target: "bridge", + "Signed {} Call: {:?}", + Source::NAME, + HexBytes::encode(&signed_source_call) + ); + + Bytes(signed_source_call) + }) + .await?; + }); + + Ok(()) + } +} + +fn prepare_call_dispatch_weight( + user_specified_dispatch_weight: &Option>, + weight_from_pre_dispatch_call: ExplicitOrMaximal, + maximal_allowed_weight: Weight, +) -> Weight { + match user_specified_dispatch_weight + .clone() + .unwrap_or(weight_from_pre_dispatch_call) + { + ExplicitOrMaximal::Explicit(weight) => weight, + ExplicitOrMaximal::Maximal => maximal_allowed_weight, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn send_remark_rialto_to_millau() { + // given + let mut send_message = SendMessage::from_iter(vec![ + "send-message", + "RialtoToMillau", + "--source-port", + "1234", + "--source-signer", + "//Alice", + "--target-signer", + "//Bob", + "remark", + "--remark-payload", + "1234", + ]); + + // when + let payload = send_message.encode_payload().unwrap(); + + // then + assert_eq!( + payload, + MessagePayload { + spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, + weight: 1345000, + origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), + call: hex!("0401081234").to_vec(), + } + ); + } + + #[test] + fn send_remark_millau_to_rialto() { + // given + let mut send_message = SendMessage::from_iter(vec![ + "send-message", + "MillauToRialto", + "--source-port", + "1234", + "--source-signer", + "//Alice", + "--origin", + "Target", + "--target-signer", + "//Bob", + "remark", + "--remark-payload", + "1234", + ]); + + // when + let payload = send_message.encode_payload().unwrap(); + + // then + // Since signatures are randomized we extract it from here and only check the rest. + let signature = match payload.origin { + CallOrigin::TargetAccount(_, _, ref sig) => sig.clone(), + _ => panic!("Unexpected `CallOrigin`: {:?}", payload), + }; + assert_eq!( + payload, + MessagePayload { + spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, + weight: 1345000, + origin: CallOrigin::TargetAccount( + sp_keyring::AccountKeyring::Alice.to_account_id(), + sp_keyring::AccountKeyring::Bob.into(), + signature, + ), + call: hex!("0701081234").to_vec(), + } + ); + } +} diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs index 4c92ec1773841..841f5427baf4d 100644 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ b/relays/bin-substrate/src/rialto_millau/cli.rs @@ -16,77 +16,9 @@ //! Deal with CLI args of Rialto <> Millau relay. -use frame_support::weights::Weight; use structopt::StructOpt; -use crate::cli::{ - Balance, ExplicitOrMaximal, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, TargetSigningParams, -}; - -/// Send bridge message. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum SendMessage { - /// Submit message to given Millau -> Rialto lane. - MillauToRialto { - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - /// Hex-encoded lane id. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Dispatch weight of the message. If not passed, determined automatically. - #[structopt(long)] - dispatch_weight: Option>, - /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. - #[structopt(long)] - fee: Option, - /// Message type. - #[structopt(subcommand)] - message: crate::cli::encode_call::Call, - /// The origin to use when dispatching the message on the target chain. Defaults to - /// `SourceAccount`. - #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] - origin: Origins, - }, - /// Submit message to given Rialto -> Millau lane. - RialtoToMillau { - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - /// Hex-encoded lane id. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Dispatch weight of the message. If not passed, determined automatically. - #[structopt(long)] - dispatch_weight: Option>, - /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. - #[structopt(long)] - fee: Option, - /// Message type. - #[structopt(subcommand)] - message: crate::cli::encode_call::Call, - /// The origin to use when dispatching the message on the target chain. Defaults to - /// `SourceAccount`. - #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] - origin: Origins, - }, -} - -impl SendMessage { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_send_message(self).await.map_err(format_err)?; - Ok(()) - } -} +use crate::cli::{HexLaneId, SourceConnectionParams}; /// Estimate Delivery & Dispatch Fee command. /// diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index d6e49ccf2cc2e..6b61653ae3170 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -29,244 +29,20 @@ pub type MillauClient = relay_substrate_client::Client; pub type RialtoClient = relay_substrate_client::Client; use crate::cli::{ - bridge::{MILLAU_TO_RIALTO_INDEX, RIALTO_TO_MILLAU_INDEX}, + bridge, encode_call::{self, Call, CliEncodeCall}, - encode_message, CliChain, ExplicitOrMaximal, HexBytes, Origins, + encode_message, CliChain, HexBytes, }; use codec::{Decode, Encode}; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::Chain; use relay_westend_client::Westend; -use sp_core::{Bytes, Pair}; -use sp_runtime::{traits::IdentifyAccount, MultiSigner}; use sp_version::RuntimeVersion; use std::fmt::Debug; -async fn run_send_message(command: cli::SendMessage) -> Result<(), String> { - match command { - cli::SendMessage::MillauToRialto { - source, - source_sign, - target_sign, - lane, - mut message, - dispatch_weight, - fee, - origin, - .. - } => { - type Source = Millau; - type Target = Rialto; - - let account_ownership_digest = |target_call, source_account_id| { - millau_runtime::rialto_account_ownership_digest( - &target_call, - source_account_id, - Target::RUNTIME_VERSION.spec_version, - ) - }; - let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; - let fee = fee.map(|x| x.cast()); - let send_message_call = |lane, payload, fee| { - millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( - lane, payload, fee, - )) - }; - - let source_client = source.into_client::().await.map_err(format_err)?; - let source_sign = source_sign.into_keypair::().map_err(format_err)?; - let target_sign = target_sign.into_keypair::().map_err(format_err)?; - - encode_call::preprocess_call::(&mut message, MILLAU_TO_RIALTO_INDEX); - let target_call = Target::encode_call(&message).map_err(|e| e.to_string())?; - - let payload = { - let target_call_weight = prepare_call_dispatch_weight( - dispatch_weight, - ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), - compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), - ); - let source_sender_public: MultiSigner = source_sign.public().into(); - let source_account_id = source_sender_public.into_account(); - - message_payload( - Target::RUNTIME_VERSION.spec_version, - target_call_weight, - match origin { - Origins::Source => CallOrigin::SourceAccount(source_account_id), - Origins::Target => { - let digest = account_ownership_digest(&target_call, source_account_id.clone()); - let target_origin_public = target_sign.public(); - let digest_signature = target_sign.sign(&digest); - CallOrigin::TargetAccount( - source_account_id, - target_origin_public.into(), - digest_signature.into(), - ) - } - }, - &target_call, - ) - }; - let dispatch_weight = payload.weight; - - let lane = lane.into(); - let fee = get_fee(fee, || { - estimate_message_delivery_and_dispatch_fee( - &source_client, - estimate_message_fee_method, - lane, - payload.clone(), - ) - }) - .await?; - - source_client - .submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| { - let send_message_call = send_message_call(lane, payload, fee); - - let signed_source_call = Source::sign_transaction( - *source_client.genesis_hash(), - &source_sign, - transaction_nonce, - send_message_call, - ) - .encode(); - - log::info!( - target: "bridge", - "Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}", - Target::NAME, - signed_source_call.len(), - dispatch_weight, - fee, - ); - log::info!( - target: "bridge", - "Signed {} Call: {:?}", - Source::NAME, - HexBytes::encode(&signed_source_call) - ); - - Bytes(signed_source_call) - }) - .await?; - } - cli::SendMessage::RialtoToMillau { - source, - source_sign, - target_sign, - lane, - mut message, - dispatch_weight, - fee, - origin, - .. - } => { - type Source = Rialto; - type Target = Millau; - - let account_ownership_digest = |target_call, source_account_id| { - rialto_runtime::millau_account_ownership_digest( - &target_call, - source_account_id, - Target::RUNTIME_VERSION.spec_version, - ) - }; - let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; - let fee = fee.map(|x| x.0); - let send_message_call = |lane, payload, fee| { - rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( - lane, payload, fee, - )) - }; - - let source_client = source.into_client::().await.map_err(format_err)?; - let source_sign = source_sign.into_keypair::().map_err(format_err)?; - let target_sign = target_sign.into_keypair::().map_err(format_err)?; - - encode_call::preprocess_call::(&mut message, RIALTO_TO_MILLAU_INDEX); - let target_call = Target::encode_call(&message).map_err(|e| e.to_string())?; - - let payload = { - let target_call_weight = prepare_call_dispatch_weight( - dispatch_weight, - ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), - compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), - ); - let source_sender_public: MultiSigner = source_sign.public().into(); - let source_account_id = source_sender_public.into_account(); - - message_payload( - Target::RUNTIME_VERSION.spec_version, - target_call_weight, - match origin { - Origins::Source => CallOrigin::SourceAccount(source_account_id), - Origins::Target => { - let digest = account_ownership_digest(&target_call, source_account_id.clone()); - let target_origin_public = target_sign.public(); - let digest_signature = target_sign.sign(&digest); - CallOrigin::TargetAccount( - source_account_id, - target_origin_public.into(), - digest_signature.into(), - ) - } - }, - &target_call, - ) - }; - let dispatch_weight = payload.weight; - - let lane = lane.into(); - let fee = get_fee(fee, || { - estimate_message_delivery_and_dispatch_fee( - &source_client, - estimate_message_fee_method, - lane, - payload.clone(), - ) - }) - .await?; - - source_client - .submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| { - let send_message_call = send_message_call(lane, payload, fee); - - let signed_source_call = Source::sign_transaction( - *source_client.genesis_hash(), - &source_sign, - transaction_nonce, - send_message_call, - ) - .encode(); - - log::info!( - target: "bridge", - "Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}", - Target::NAME, - signed_source_call.len(), - dispatch_weight, - fee, - ); - log::info!( - target: "bridge", - "Signed {} Call: {:?}", - Source::NAME, - HexBytes::encode(&signed_source_call) - ); - - Bytes(signed_source_call) - }) - .await?; - } - } - Ok(()) -} - async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { match cmd { cli::EstimateFee::RialtoToMillau { source, lane, payload } => { @@ -275,7 +51,7 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; - let source_client = source.into_client::().await.map_err(format_err)?; + let source_client = source.to_client::().await.map_err(format_err)?; let lane = lane.into(); let payload = Source::encode_message(payload)?; @@ -291,7 +67,7 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; - let source_client = source.into_client::().await.map_err(format_err)?; + let source_client = source.to_client::().await.map_err(format_err)?; let lane = lane.into(); let payload = Source::encode_message(payload)?; @@ -306,7 +82,7 @@ async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { Ok(()) } -async fn estimate_message_delivery_and_dispatch_fee( +pub(crate) async fn estimate_message_delivery_and_dispatch_fee( client: &relay_substrate_client::Client, estimate_fee_method: &str, lane: bp_messages::LaneId, @@ -320,7 +96,7 @@ async fn estimate_message_delivery_and_dispatch_fee( +pub(crate) fn message_payload( spec_version: u32, weight: Weight, origin: CallOrigin, @@ -357,35 +133,7 @@ where } } -fn prepare_call_dispatch_weight( - user_specified_dispatch_weight: Option>, - weight_from_pre_dispatch_call: ExplicitOrMaximal, - maximal_allowed_weight: Weight, -) -> Weight { - match user_specified_dispatch_weight.unwrap_or(weight_from_pre_dispatch_call) { - ExplicitOrMaximal::Explicit(weight) => weight, - ExplicitOrMaximal::Maximal => maximal_allowed_weight, - } -} - -async fn get_fee(fee: Option, f: F) -> Result -where - Fee: Decode, - F: FnOnce() -> R, - R: std::future::Future, E>>, - E: Debug, -{ - match fee { - Some(fee) => Ok(fee), - None => match f().await { - Ok(Some(fee)) => Ok(fee), - Ok(None) => Err("Failed to estimate message fee. Message is too heavy?".into()), - Err(error) => Err(format!("Failed to estimate message fee: {:?}", error)), - }, - } -} - -fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { +pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) } @@ -409,7 +157,7 @@ impl CliEncodeCall for Millau { fee, bridge_instance_index, } => match *bridge_instance_index { - MILLAU_TO_RIALTO_INDEX => { + bridge::MILLAU_TO_RIALTO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( lane.0, @@ -452,7 +200,7 @@ impl CliChain for Millau { sender.enforce_chain::(); let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::(&mut call, MILLAU_TO_RIALTO_INDEX); + encode_call::preprocess_call::(&mut call, bridge::MILLAU_TO_RIALTO_INDEX); let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; @@ -482,7 +230,7 @@ impl CliEncodeCall for Rialto { fee, bridge_instance_index, } => match *bridge_instance_index { - RIALTO_TO_MILLAU_INDEX => { + bridge::RIALTO_TO_MILLAU_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( lane.0, payload, fee.0, @@ -522,7 +270,7 @@ impl CliChain for Rialto { sender.enforce_chain::(); let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::(&mut call, RIALTO_TO_MILLAU_INDEX); + encode_call::preprocess_call::(&mut call, bridge::RIALTO_TO_MILLAU_INDEX); let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; @@ -559,6 +307,7 @@ fn format_err(e: anyhow::Error) -> String { mod tests { use super::*; use bp_messages::source_chain::TargetHeaderChain; + use relay_substrate_client::TransactionSignScheme; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; From a9a197bbde15813cfd73c85d01849be8dd72fbf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Apr 2021 14:13:51 +0200 Subject: [PATCH 0420/1210] CLI: Estimate Fee (#888) * Move estimate-fee * Add parsing test. * Address review comments. * Fix compilation. * Move things around. Co-authored-by: Svyatoslav Nikolsky --- relays/bin-substrate/src/cli/bridge.rs | 11 +- relays/bin-substrate/src/cli/encode_call.rs | 2 +- .../bin-substrate/src/cli/encode_message.rs | 2 +- relays/bin-substrate/src/cli/estimate_fee.rs | 128 ++++++++++++++++++ relays/bin-substrate/src/cli/mod.rs | 35 ++--- relays/bin-substrate/src/cli/send_message.rs | 63 +++++++-- relays/bin-substrate/src/rialto_millau/cli.rs | 62 --------- relays/bin-substrate/src/rialto_millau/mod.rs | 128 ++---------------- 8 files changed, 213 insertions(+), 218 deletions(-) create mode 100644 relays/bin-substrate/src/cli/estimate_fee.rs delete mode 100644 relays/bin-substrate/src/rialto_millau/cli.rs diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 2184903e013e7..5a5715699cf01 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -17,7 +17,7 @@ use structopt::clap::arg_enum; arg_enum! { - #[derive(Debug)] + #[derive(Debug, PartialEq, Eq)] /// Supported full bridges (headers + messages). pub enum FullBridge { MillauToRialto, @@ -59,9 +59,9 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages; - // Send-message + // Send-message / Estimate-fee #[allow(unused_imports)] - use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; // Send-message #[allow(unused_imports)] use millau_runtime::rialto_account_ownership_digest as account_ownership_digest; @@ -81,9 +81,10 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages; - // Send-message + // Send-message / Estimate-fee #[allow(unused_imports)] - use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message #[allow(unused_imports)] use rialto_runtime::millau_account_ownership_digest as account_ownership_digest; diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index b5cdaaa1d3908..6e1130cffc1a6 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -35,7 +35,7 @@ pub struct EncodeCall { /// /// Note this enum may be used in the context of both Source (as part of `encode-call`) /// and Target chain (as part of `encode-message/send-message`). -#[derive(StructOpt, Debug)] +#[derive(StructOpt, Debug, PartialEq, Eq)] pub enum Call { /// Raw bytes for the message Raw { diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 5ef668864ea56..a29aa8597d63a 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -19,7 +19,7 @@ use crate::select_full_bridge; use structopt::StructOpt; /// Generic message payload. -#[derive(StructOpt, Debug)] +#[derive(StructOpt, Debug, PartialEq, Eq)] pub enum MessagePayload { /// Raw, SCALE-encoded `MessagePayload`. Raw { diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs new file mode 100644 index 0000000000000..4e39ad351ede0 --- /dev/null +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -0,0 +1,128 @@ +// 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 . + +use crate::cli::bridge::FullBridge; +use crate::cli::{Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}; +use crate::select_full_bridge; +use codec::{Decode, Encode}; +use relay_substrate_client::{Chain, ChainWithBalances}; +use structopt::StructOpt; + +/// Estimate Delivery & Dispatch Fee command. +#[derive(StructOpt, Debug, PartialEq, Eq)] +pub struct EstimateFee { + /// A bridge instance to encode call for. + #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + bridge: FullBridge, + #[structopt(flatten)] + source: SourceConnectionParams, + /// Hex-encoded id of lane that will be delivering the message. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + /// Payload to send over the bridge. + #[structopt(flatten)] + payload: crate::cli::encode_message::MessagePayload, +} + +impl EstimateFee { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + let Self { + source, + bridge, + lane, + payload, + } = self; + + select_full_bridge!(bridge, { + let source_client = source.to_client::().await?; + let lane = lane.into(); + let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; + + let fee: ::NativeBalance = + estimate_message_delivery_and_dispatch_fee(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload) + .await?; + + log::info!(target: "bridge", "Fee: {:?}", Balance(fee as _)); + println!("{}", fee); + Ok(()) + }) + } +} + +pub(crate) async fn estimate_message_delivery_and_dispatch_fee( + client: &relay_substrate_client::Client, + estimate_fee_method: &str, + lane: bp_messages::LaneId, + payload: P, +) -> anyhow::Result { + let encoded_response = client + .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .await?; + let decoded_response: Option = + Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?; + let fee = decoded_response + .ok_or_else(|| anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())))?; + Ok(fee) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cli::encode_call; + use sp_core::crypto::Ss58Codec; + + #[test] + fn should_parse_cli_options() { + // given + let alice = sp_keyring::AccountKeyring::Alice.to_account_id().to_ss58check(); + + // when + let res = EstimateFee::from_iter(vec![ + "estimate_fee", + "RialtoToMillau", + "--source-port", + "1234", + "call", + "--sender", + &alice, + "remark", + "--remark-payload", + "1234", + ]); + + // then + assert_eq!( + res, + EstimateFee { + bridge: FullBridge::RialtoToMillau, + lane: HexLaneId([0, 0, 0, 0]), + source: SourceConnectionParams { + source_host: "127.0.0.1".into(), + source_port: 1234, + source_secure: false, + }, + payload: crate::cli::encode_message::MessagePayload::Call { + sender: alice.parse().unwrap(), + call: encode_call::Call::Remark { + remark_payload: Some(HexBytes(vec![0x12, 0x34])), + remark_size: None, + } + } + } + ); + } +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 960e85ea92ae9..c77d5071db326 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -18,7 +18,6 @@ use std::convert::TryInto; -use crate::rialto_millau::cli as rialto_millau; use bp_messages::LaneId; use codec::{Decode, Encode}; use frame_support::weights::Weight; @@ -28,12 +27,13 @@ use structopt::{clap::arg_enum, StructOpt}; pub(crate) mod bridge; pub(crate) mod encode_call; pub(crate) mod encode_message; +pub(crate) mod estimate_fee; +pub(crate) mod send_message; mod derive_account; mod init_bridge; mod relay_headers; mod relay_messages; -mod send_message; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -75,7 +75,7 @@ pub enum Command { /// the bridge. EncodeMessage(encode_message::EncodeMessage), /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. - EstimateFee(EstimateFee), + EstimateFee(estimate_fee::EstimateFee), /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. DeriveAccount(derive_account::DeriveAccount), } @@ -97,23 +97,6 @@ impl Command { } } -/// Estimate Delivery & Dispatch Fee command. -#[derive(StructOpt)] -pub enum EstimateFee { - #[structopt(flatten)] - RialtoMillau(rialto_millau::EstimateFee), -} - -impl EstimateFee { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - Self::RialtoMillau(arg) => arg.run().await?, - } - Ok(()) - } -} - arg_enum! { #[derive(Debug)] /// The origin to use when dispatching the message on the target chain. @@ -127,7 +110,7 @@ arg_enum! { } /// Generic balance type. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Balance(pub u128); impl std::fmt::Display for Balance { @@ -242,7 +225,7 @@ pub trait CliChain: relay_substrate_client::Chain { } /// Lane id. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct HexLaneId(pub LaneId); impl From for LaneId { @@ -262,7 +245,7 @@ impl std::str::FromStr for HexLaneId { } /// Nicer formatting for raw bytes vectors. -#[derive(Default, Encode, Decode)] +#[derive(Default, Encode, Decode, PartialEq, Eq)] pub struct HexBytes(pub Vec); impl std::str::FromStr for HexBytes { @@ -321,7 +304,7 @@ impl From for relay_utils::metrics::MetricsParams { } /// Either explicit or maximal allowed value. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum ExplicitOrMaximal { /// User has explicitly specified argument value. Explicit(V), @@ -353,7 +336,7 @@ macro_rules! declare_chain_options { ($chain:ident, $chain_prefix:ident) => { paste::item! { #[doc = $chain " connection params."] - #[derive(StructOpt)] + #[derive(StructOpt, Debug, PartialEq, Eq)] pub struct [<$chain ConnectionParams>] { #[doc = "Connect to " $chain " node at given host."] #[structopt(long, default_value = "127.0.0.1")] @@ -367,7 +350,7 @@ macro_rules! declare_chain_options { } #[doc = $chain " signing params."] - #[derive(StructOpt)] + #[derive(StructOpt, Debug, PartialEq, Eq)] pub struct [<$chain SigningParams>] { #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] #[structopt(long)] diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index e6ab7dcfa7f02..64448f0f1db3f 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -16,6 +16,7 @@ use crate::cli::bridge::FullBridge; use crate::cli::encode_call::{self, CliEncodeCall}; +use crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee; use crate::cli::{ Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, TargetSigningParams, @@ -26,6 +27,7 @@ use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; +use std::fmt::Debug; use structopt::StructOpt; /// Send bridge message. @@ -84,12 +86,12 @@ impl SendMessage { let target_call_weight = prepare_call_dispatch_weight( dispatch_weight, ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), - crate::rialto_millau::compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), + compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), ); let source_sender_public: MultiSigner = source_sign.public().into(); let source_account_id = source_sender_public.into_account(); - crate::rialto_millau::message_payload( + message_payload( Target::RUNTIME_VERSION.spec_version, target_call_weight, match origin { @@ -127,14 +129,14 @@ impl SendMessage { let lane = self.lane.clone().into(); let fee = match self.fee { Some(fee) => fee, - None => crate::rialto_millau::estimate_message_delivery_and_dispatch_fee::< - ::NativeBalance, - _, - _, - >(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone()) - .await? - .map(|v| Balance(v as _)) - .ok_or_else(|| anyhow::format_err!("Failed to estimate message fee. Message is too heavy?"))?, + None => Balance( + estimate_message_delivery_and_dispatch_fee::< + ::NativeBalance, + _, + _, + >(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone()) + .await? as _, + ), }; let dispatch_weight = payload.weight; let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage { @@ -192,6 +194,47 @@ fn prepare_call_dispatch_weight( } } +pub(crate) fn message_payload( + spec_version: u32, + weight: Weight, + origin: CallOrigin, + call: &impl Encode, +) -> MessagePayload> +where + SAccountId: Encode + Debug, + TPublic: Encode + Debug, + TSignature: Encode + Debug, +{ + // Display nicely formatted call. + let payload = MessagePayload { + spec_version, + weight, + origin, + call: HexBytes::encode(call), + }; + + log::info!(target: "bridge", "Created Message Payload: {:#?}", payload); + log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); + + // re-pack to return `Vec` + let MessagePayload { + spec_version, + weight, + origin, + call, + } = payload; + MessagePayload { + spec_version, + weight, + origin, + call: call.0, + } +} + +pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { + bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/bin-substrate/src/rialto_millau/cli.rs b/relays/bin-substrate/src/rialto_millau/cli.rs deleted file mode 100644 index 841f5427baf4d..0000000000000 --- a/relays/bin-substrate/src/rialto_millau/cli.rs +++ /dev/null @@ -1,62 +0,0 @@ -// 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 . - -//! Deal with CLI args of Rialto <> Millau relay. - -use structopt::StructOpt; - -use crate::cli::{HexLaneId, SourceConnectionParams}; - -/// Estimate Delivery & Dispatch Fee command. -/// -/// TODO [#855] Move to separate module. -#[derive(StructOpt)] -pub enum EstimateFee { - /// Estimate fee of Rialto to Millau message. - RialtoToMillau { - #[structopt(flatten)] - source: SourceConnectionParams, - /// Hex-encoded id of lane that will be delivering the message. - #[structopt(long)] - lane: HexLaneId, - /// Payload to send over the bridge. - #[structopt(flatten)] - payload: crate::cli::encode_message::MessagePayload, - }, - /// Estimate fee of Rialto to Millau message. - MillauToRialto { - #[structopt(flatten)] - source: SourceConnectionParams, - /// Hex-encoded id of lane that will be delivering the message. - #[structopt(long)] - lane: HexLaneId, - /// Payload to send over the bridge. - #[structopt(flatten)] - payload: crate::cli::encode_message::MessagePayload, - }, -} - -impl EstimateFee { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - super::run_estimate_fee(self).await.map_err(format_err)?; - Ok(()) - } -} - -fn format_err(err: String) -> anyhow::Error { - anyhow::anyhow!(err) -} diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index 6b61653ae3170..a04cd55f7d849 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -16,7 +16,6 @@ //! Rialto <> Millau Bridge commands. -pub mod cli; pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; @@ -31,111 +30,15 @@ pub type RialtoClient = relay_substrate_client::Client; use crate::cli::{ bridge, encode_call::{self, Call, CliEncodeCall}, - encode_message, CliChain, HexBytes, + encode_message, send_message, CliChain, }; -use codec::{Decode, Encode}; +use codec::Decode; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::Chain; use relay_westend_client::Westend; use sp_version::RuntimeVersion; -use std::fmt::Debug; - -async fn run_estimate_fee(cmd: cli::EstimateFee) -> Result<(), String> { - match cmd { - cli::EstimateFee::RialtoToMillau { source, lane, payload } => { - type Source = Rialto; - type SourceBalance = bp_rialto::Balance; - - let estimate_message_fee_method = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; - - let source_client = source.to_client::().await.map_err(format_err)?; - let lane = lane.into(); - let payload = Source::encode_message(payload)?; - - let fee: Option = - estimate_message_delivery_and_dispatch_fee(&source_client, estimate_message_fee_method, lane, payload) - .await?; - - println!("Fee: {:?}", fee); - } - cli::EstimateFee::MillauToRialto { source, lane, payload } => { - type Source = Millau; - type SourceBalance = bp_millau::Balance; - - let estimate_message_fee_method = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; - - let source_client = source.to_client::().await.map_err(format_err)?; - let lane = lane.into(); - let payload = Source::encode_message(payload)?; - - let fee: Option = - estimate_message_delivery_and_dispatch_fee(&source_client, estimate_message_fee_method, lane, payload) - .await?; - - println!("Fee: {:?}", fee); - } - } - - Ok(()) -} - -pub(crate) async fn estimate_message_delivery_and_dispatch_fee( - client: &relay_substrate_client::Client, - estimate_fee_method: &str, - lane: bp_messages::LaneId, - payload: P, -) -> Result, relay_substrate_client::Error> { - let encoded_response = client - .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) - .await?; - let decoded_response: Option = - Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?; - Ok(decoded_response) -} - -pub(crate) fn message_payload( - spec_version: u32, - weight: Weight, - origin: CallOrigin, - call: &impl Encode, -) -> MessagePayload> -where - SAccountId: Encode + Debug, - TPublic: Encode + Debug, - TSignature: Encode + Debug, -{ - // Display nicely formatted call. - let payload = MessagePayload { - spec_version, - weight, - origin, - call: HexBytes::encode(call), - }; - - log::info!(target: "bridge", "Created Message Payload: {:#?}", payload); - log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); - - // re-pack to return `Vec` - let MessagePayload { - spec_version, - weight, - origin, - call, - } = payload; - MessagePayload { - spec_version, - weight, - origin, - call: call.0, - } -} - -pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { - bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) -} impl CliEncodeCall for Millau { fn max_extrinsic_size() -> u32 { @@ -204,7 +107,7 @@ impl CliChain for Millau { let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; - Ok(message_payload(spec_version, weight, origin, &call)) + Ok(send_message::message_payload(spec_version, weight, origin, &call)) } } } @@ -274,7 +177,7 @@ impl CliChain for Rialto { let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; - Ok(message_payload(spec_version, weight, origin, &call)) + Ok(send_message::message_payload(spec_version, weight, origin, &call)) } } } @@ -299,14 +202,11 @@ impl CliChain for Westend { } } -fn format_err(e: anyhow::Error) -> String { - e.to_string() -} - #[cfg(test)] mod tests { use super::*; use bp_messages::source_chain::TargetHeaderChain; + use codec::Encode; use relay_substrate_client::TransactionSignScheme; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -363,7 +263,7 @@ mod tests { ); let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); - let payload = message_payload( + let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, pallet_bridge_dispatch::CallOrigin::SourceRoot, @@ -373,7 +273,7 @@ mod tests { let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into(); - let payload = message_payload( + let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, pallet_bridge_dispatch::CallOrigin::SourceRoot, @@ -396,10 +296,11 @@ mod tests { fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() { use rialto_runtime::millau_messages::Millau; - let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); + let maximal_dispatch_weight = + send_message::compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); - let payload = message_payload( + let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight, pallet_bridge_dispatch::CallOrigin::SourceRoot, @@ -407,7 +308,7 @@ mod tests { ); assert_eq!(Millau::verify_message(&payload), Ok(())); - let payload = message_payload( + let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight + 1, pallet_bridge_dispatch::CallOrigin::SourceRoot, @@ -420,10 +321,11 @@ mod tests { fn maximal_weight_fill_block_to_rialto_is_generated_correctly() { use millau_runtime::rialto_messages::Rialto; - let maximal_dispatch_weight = compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); + let maximal_dispatch_weight = + send_message::compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); - let payload = message_payload( + let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight, pallet_bridge_dispatch::CallOrigin::SourceRoot, @@ -431,7 +333,7 @@ mod tests { ); assert_eq!(Rialto::verify_message(&payload), Ok(())); - let payload = message_payload( + let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight + 1, pallet_bridge_dispatch::CallOrigin::SourceRoot, From e8785b56e79599ff2a1eee21b41233f21fb402db Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 13 Apr 2021 18:17:41 +0300 Subject: [PATCH 0421/1210] RestartNeeded is a connection error (#894) --- relays/client-substrate/src/error.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index db1cdb4374542..e1269306c3c74 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -72,6 +72,7 @@ impl MaybeConnectionError for Error { // right now if connection to the ws server is dropped (after it is already established), // we're getting this error | Error::RpcError(RpcError::Internal(_)) + | Error::RpcError(RpcError::RestartNeeded(_)) | Error::ClientNotSynced(_), ) } From b57b3b948bfbb02f8b377e3c386b6811a17b83d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Apr 2021 17:30:39 +0200 Subject: [PATCH 0422/1210] Grandpa Pallet Pruning (#890) * Pruning. * Add tests. * Address review. --- bin/millau/runtime/src/lib.rs | 8 ++++++ bin/rialto/runtime/src/lib.rs | 7 +++++ modules/grandpa/src/lib.rs | 53 +++++++++++++++++++++++++++++++++++ modules/grandpa/src/mock.rs | 2 ++ 4 files changed, 70 insertions(+) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 437c9ff36f595..822c0229ea146 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -309,12 +309,19 @@ parameter_types! { // call per block. pub const MaxRequests: u32 = 50; pub const WestendValidatorCount: u32 = 255; + + // Number of headers to keep. + // + // Assuming the worst case of every header being finalized, we will keep headers for at least a + // week. + pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32; } pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; @@ -324,6 +331,7 @@ pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4db3101810a1d..603365130ae03 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -414,11 +414,18 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; + + // Number of headers to keep. + // + // Assuming the worst case of every header being finalized, we will keep headers at least for a + // week. + pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; } impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 58f58d6aa6ddf..98f47dd6f1c61 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -91,6 +91,14 @@ pub mod pallet { #[pallet::constant] type MaxRequests: Get; + /// Maximal number of finalized headers to keep in the storage. + /// + /// The setting is there to prevent growing the on-chain state indefinitely. Note + /// the setting does not relate to block numbers - we will simply keep as much items + /// in the storage, so it doesn't guarantee any fixed timeframe for finality headers. + #[pallet::constant] + type HeadersToKeep: Get; + /// Weights gathered through benchmarking. type WeightInfo: WeightInfo; } @@ -153,10 +161,20 @@ pub mod pallet { verify_justification::(&justification, hash, *number, authority_set)?; let _enacted = try_enact_authority_change::(&finality_target, set_id)?; + let index = >::get(); + let pruning = >::try_get(index); >::put(hash); >::insert(hash, finality_target); + >::insert(index, hash); >::mutate(|count| *count += 1); + // Update ring buffer pointer and remove old header. + >::put((index + 1) % T::HeadersToKeep::get()); + if let Ok(hash) = pruning { + log::debug!(target: "runtime::bridge-grandpa", "Pruning old header: {:?}.", hash); + >::remove(hash); + } + log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); Ok(().into()) @@ -248,6 +266,15 @@ pub mod pallet { #[pallet::storage] pub(super) type BestFinalized, I: 'static = ()> = StorageValue<_, BridgedBlockHash, ValueQuery>; + /// A ring buffer of imported hashes. Ordered by the insertion time. + #[pallet::storage] + pub(super) type ImportedHashes, I: 'static = ()> = + StorageMap<_, Identity, u32, BridgedBlockHash>; + + /// Current ring buffer position. + #[pallet::storage] + pub(super) type ImportedHashesPointer, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; + /// Headers which have been imported into the pallet. #[pallet::storage] pub(super) type ImportedHeaders, I: 'static = ()> = @@ -999,4 +1026,30 @@ mod tests { assert_ok!(submit_finality_proof(7)); }) } + + #[test] + fn should_prune_headers_over_headers_to_keep_parameter() { + run_test(|| { + initialize_substrate_bridge(); + assert_ok!(submit_finality_proof(1)); + let first_header = Pallet::::best_finalized(); + next_block(); + + assert_ok!(submit_finality_proof(2)); + next_block(); + assert_ok!(submit_finality_proof(3)); + next_block(); + assert_ok!(submit_finality_proof(4)); + next_block(); + assert_ok!(submit_finality_proof(5)); + next_block(); + + assert_ok!(submit_finality_proof(6)); + + assert!( + !Pallet::::is_known_header(first_header.hash()), + "First header should be pruned." + ); + }) + } } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 7d5901a679c65..20f5ea7bdf7a1 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -81,6 +81,7 @@ impl frame_system::Config for TestRuntime { parameter_types! { pub const MaxRequests: u32 = 2; + pub const HeadersToKeep: u32 = 5; pub const SessionLength: u64 = 5; pub const NumValidators: u32 = 5; } @@ -88,6 +89,7 @@ parameter_types! { impl grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; type WeightInfo = (); } From dd0c7d65ffd62e8aa26ce02e756bb1daab117bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 13 Apr 2021 22:15:33 +0200 Subject: [PATCH 0423/1210] Support more than `u8::max_value` GRANDPA validators (#896) * Support moar validators. * Update weights script. * Use correct type for benchmarking accounts * Use package name instead of manifest path Co-authored-by: Hernando Castano --- modules/grandpa/src/benchmarking.rs | 12 +++++------- primitives/test-utils/Cargo.toml | 6 ++++-- primitives/test-utils/src/keyring.rs | 10 +++++++--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index a3abe508d8a88..cb170fdc8b193 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -64,9 +64,7 @@ const MAX_VOTE_ANCESTRIES: u32 = 1000; // The maximum number of pre-commits to include in a justification. In practice this scales with the // number of validators. -// -// TODO [#846]: Right now this will break benchmarking if it is greater than `u8::MAX` -const MAX_VALIDATOR_SET_SIZE: u32 = 255; +const MAX_VALIDATOR_SET_SIZE: u32 = 1024; benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to @@ -80,7 +78,7 @@ benchmarks_instance_pallet! { let caller: T::AccountId = whitelisted_caller(); - let authority_list = accounts(p as u8) + let authority_list = accounts(p as u16) .iter() .map(|id| (AuthorityId::from(*id), 1)) .collect::>(); @@ -99,7 +97,7 @@ benchmarks_instance_pallet! { header: header.clone(), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: accounts(p as u8).iter().map(|k| (*k, 1)).collect::>(), + authorities: accounts(p as u16).iter().map(|k| (*k, 1)).collect::>(), votes: v, forks: 1, }; @@ -160,7 +158,7 @@ benchmarks_instance_pallet! { let caller: T::AccountId = whitelisted_caller(); - let authority_list = accounts(p as u8) + let authority_list = accounts(p as u16) .iter() .map(|id| (AuthorityId::from(*id), 1)) .collect::>(); @@ -179,7 +177,7 @@ benchmarks_instance_pallet! { header: header.clone(), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: accounts(p as u8).iter().map(|k| (*k, 1)).collect::>(), + authorities: accounts(p as u16).iter().map(|k| (*k, 1)).collect::>(), votes: p, forks: p, }; diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 64a85a2c67098..5adb2c2b55f54 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -9,10 +9,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-header-chain = { path = "../header-chain", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.14.0", default-features = false } +parity-scale-codec = { version = "2.0.0", default-features = false } +sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -20,8 +21,9 @@ std = [ "bp-header-chain/std", "ed25519-dalek/std", "finality-grandpa/std", + "parity-scale-codec/std", + "sp-application-crypto/std", "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", - "sp-application-crypto/std", ] diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index fbc1496e16358..6c5b1cae9114a 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -18,6 +18,7 @@ use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; use finality_grandpa::voter_set::VoterSet; +use parity_scale_codec::Encode; use sp_application_crypto::Public; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_runtime::RuntimeDebug; @@ -33,7 +34,7 @@ pub const FERDIE: Account = Account(5); /// A test account which can be used to sign messages. #[derive(RuntimeDebug, Clone, Copy)] -pub struct Account(pub u8); +pub struct Account(pub u16); impl Account { pub fn public(&self) -> PublicKey { @@ -41,7 +42,10 @@ impl Account { } pub fn secret(&self) -> SecretKey { - SecretKey::from_bytes(&[self.0; 32]).expect("A static array of the correct length is a known good.") + let data = self.0.encode(); + let mut bytes = [0_u8; 32]; + bytes[0..data.len()].copy_from_slice(&*data); + SecretKey::from_bytes(&bytes).expect("A static array of the correct length is a known good.") } pub fn pair(&self) -> Keypair { @@ -87,6 +91,6 @@ pub fn test_keyring() -> Vec<(Account, AuthorityWeight)> { } /// Get a list of "unique" accounts. -pub fn accounts(len: u8) -> Vec { +pub fn accounts(len: u16) -> Vec { (0..len).into_iter().map(Account).collect() } From 4e5974a877ea543566435c1ca760c416dc260b61 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 14 Apr 2021 09:12:38 +0300 Subject: [PATCH 0424/1210] Use Substrate state_getReadProof RPC method to get storage proofs (#893) * use Substrate state_getReadProof method instead of pallet-bridge-messages-rpc * Fix typo Co-authored-by: Hernando Castano --- bin/millau/node/Cargo.toml | 1 - bin/millau/node/src/service.rs | 38 +--- bin/millau/runtime/src/lib.rs | 5 +- bin/millau/runtime/src/rialto_messages.rs | 27 +-- bin/rialto/node/Cargo.toml | 1 - bin/rialto/node/src/service.rs | 38 +--- bin/rialto/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/millau_messages.rs | 25 +-- modules/messages/rpc/Cargo.toml | 29 --- modules/messages/rpc/src/error.rs | 59 ----- modules/messages/rpc/src/lib.rs | 202 ------------------ relays/bin-substrate/src/messages_source.rs | 47 ++-- relays/bin-substrate/src/messages_target.rs | 32 ++- .../millau_messages_to_rialto.rs | 16 +- .../rialto_messages_to_millau.rs | 16 +- relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/client.rs | 56 +---- relays/client-substrate/src/error.rs | 4 + .../src/metrics/storage_proof_overhead.rs | 58 ++--- relays/client-substrate/src/rpc.rs | 29 +-- 20 files changed, 130 insertions(+), 560 deletions(-) delete mode 100644 modules/messages/rpc/Cargo.toml delete mode 100644 modules/messages/rpc/src/error.rs delete mode 100644 modules/messages/rpc/src/lib.rs diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 076e282bae363..e31e2c871a508 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -20,7 +20,6 @@ bp-millau= { path = "../../../primitives/chain-millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } pallet-bridge-messages = { path = "../../../modules/messages" } -pallet-bridge-messages-rpc = { path = "../../../modules/messages/rpc" } # Substrate Dependencies diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index b3834ff68a726..8677ec2e70df1 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -211,40 +211,8 @@ pub fn new_full(mut config: Configuration) -> Result let prometheus_registry = config.prometheus_registry().cloned(); let rpc_extensions_builder = { - use bp_messages::{LaneId, MessageNonce}; - use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; - use sp_core::storage::StorageKey; - // This struct is here to ease update process. - - /// Millau runtime from messages RPC point of view. - struct MillauMessagesKeys; - - impl pallet_bridge_messages_rpc::Runtime for MillauMessagesKeys { - fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option { - match *instance { - RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::message_key(lane, nonce)), - _ => None, - } - } - - fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { - match *instance { - RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::outbound_lane_data_key(lane)), - _ => None, - } - } - - fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { - match *instance { - RIALTO_BRIDGE_INSTANCE => Some(millau_runtime::rialto_messages::inbound_lane_data_key(lane)), - _ => None, - } - } - } - - use pallet_bridge_messages_rpc::{MessagesApi, MessagesRpcHandler}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; @@ -259,7 +227,7 @@ pub fn new_full(mut config: Configuration) -> Result let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend.clone(), Some(shared_authority_set.clone())); + GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); Box::new(move |_, subscription_executor| { let mut io = jsonrpc_core::IoHandler::default(); @@ -278,10 +246,6 @@ pub fn new_full(mut config: Configuration) -> Result subscription_executor, finality_proof_provider.clone(), ))); - io.extend_with(MessagesApi::to_delegate(MessagesRpcHandler::new( - backend.clone(), - Arc::new(MillauMessagesKeys), - ))); io }) }; diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 822c0229ea146..30cf1bd87cd87 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -351,7 +351,10 @@ parameter_types! { pub const RootAccountForPayments: Option = None; } -impl pallet_bridge_messages::Config for Runtime { +/// Instance of the messages pallet used to relay messages to/from Rialto chain. +pub type WithRialtoMessagesInstance = pallet_bridge_messages::DefaultInstance; + +impl pallet_bridge_messages::Config for Runtime { type Event = Event; // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 9162596e7c969..30f373fa0ad0c 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -24,14 +24,13 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; -use bridge_runtime_common::messages::{self, ChainWithMessages, MessageBridge, MessageTransaction}; +use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, weights::{DispatchClass, Weight}, RuntimeDebug, }; -use sp_core::storage::StorageKey; use sp_runtime::{FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; @@ -43,28 +42,6 @@ parameter_types! { pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE; } -/// Storage key of the Millau -> Rialto message in the runtime storage. -pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - pallet_bridge_messages::storage_keys::message_key::::MessagesInstance>( - lane, nonce, - ) -} - -/// Storage key of the Millau -> Rialto message lane state in the runtime storage. -pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_bridge_messages::storage_keys::outbound_lane_data_key::<::MessagesInstance>( - lane, - ) -} - -/// Storage key of the Rialto -> Millau message lane state in the runtime storage. -pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - Runtime, - ::MessagesInstance, - >(lane) -} - /// Message payload for Millau -> Rialto messages. pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload; @@ -120,7 +97,7 @@ impl messages::ChainWithMessages for Millau { type Weight = Weight; type Balance = bp_millau::Balance; - type MessagesInstance = pallet_bridge_messages::DefaultInstance; + type MessagesInstance = crate::WithRialtoMessagesInstance; } impl messages::ThisChainWithMessages for Millau { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index fffbe9655a4ad..a51ee7a5ab5f2 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -19,7 +19,6 @@ bp-messages = { path = "../../../primitives/messages" } bp-runtime = { path = "../../../primitives/runtime" } bp-rialto = { path = "../../../primitives/chain-rialto" } pallet-bridge-messages = { path = "../../../modules/messages" } -pallet-bridge-messages-rpc = { path = "../../../modules/messages/rpc" } rialto-runtime = { path = "../runtime" } # Substrate Dependencies diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 380b0cc8171cc..841202ac7bfa5 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -211,40 +211,8 @@ pub fn new_full(mut config: Configuration) -> Result let prometheus_registry = config.prometheus_registry().cloned(); let rpc_extensions_builder = { - use bp_messages::{LaneId, MessageNonce}; - use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; - use sp_core::storage::StorageKey; - // This struct is here to ease update process. - - /// Rialto runtime from messages RPC point of view. - struct RialtoMessagesKeys; - - impl pallet_bridge_messages_rpc::Runtime for RialtoMessagesKeys { - fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option { - match *instance { - MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::message_key(lane, nonce)), - _ => None, - } - } - - fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { - match *instance { - MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::outbound_lane_data_key(lane)), - _ => None, - } - } - - fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option { - match *instance { - MILLAU_BRIDGE_INSTANCE => Some(rialto_runtime::millau_messages::inbound_lane_data_key(lane)), - _ => None, - } - } - } - - use pallet_bridge_messages_rpc::{MessagesApi, MessagesRpcHandler}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use sc_rpc::DenyUnsafe; @@ -259,7 +227,7 @@ pub fn new_full(mut config: Configuration) -> Result let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend.clone(), Some(shared_authority_set.clone())); + GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); Box::new(move |_, subscription_executor| { let mut io = jsonrpc_core::IoHandler::default(); @@ -278,10 +246,6 @@ pub fn new_full(mut config: Configuration) -> Result subscription_executor, finality_proof_provider.clone(), ))); - io.extend_with(MessagesApi::to_delegate(MessagesRpcHandler::new( - backend.clone(), - Arc::new(RialtoMessagesKeys), - ))); io }) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 603365130ae03..4e81d3efb1fb1 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -443,8 +443,10 @@ parameter_types! { pub const RootAccountForPayments: Option = None; } -pub(crate) type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance; -impl pallet_bridge_messages::Config for Runtime { +/// Instance of the messages pallet used to relay messages to/from Millau chain. +pub type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance; + +impl pallet_bridge_messages::Config for Runtime { type Event = Event; type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; type Parameter = millau_messages::RialtoToMillauMessagesParameter; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 62f4ec714747e..e8785c464a237 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -24,14 +24,13 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; -use bridge_runtime_common::messages::{self, ChainWithMessages, MessageBridge, MessageTransaction}; +use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, weights::{DispatchClass, Weight}, RuntimeDebug, }; -use sp_core::storage::StorageKey; use sp_runtime::{FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; @@ -43,28 +42,6 @@ parameter_types! { pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE; } -/// Storage key of the Rialto -> Millau message in the runtime storage. -pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - pallet_bridge_messages::storage_keys::message_key::::MessagesInstance>( - lane, nonce, - ) -} - -/// Storage key of the Rialto -> Millau message lane state in the runtime storage. -pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_bridge_messages::storage_keys::outbound_lane_data_key::<::MessagesInstance>( - lane, - ) -} - -/// Storage key of the Millau -> Rialto message lane state in the runtime storage. -pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - Runtime, - ::MessagesInstance, - >(lane) -} - /// Message payload for Rialto -> Millau messages. pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; diff --git a/modules/messages/rpc/Cargo.toml b/modules/messages/rpc/Cargo.toml deleted file mode 100644 index bb0d1e0c54477..0000000000000 --- a/modules/messages/rpc/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "pallet-bridge-messages-rpc" -description = "Module that provides RPC methods specific to pallet-bridge-messages pallet." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -derive_more = "0.99.2" -futures = { version = "0.3.5", features = ["compat"] } -jsonrpc-core = "15.1.0" -jsonrpc-core-client = "15.1.0" -jsonrpc-derive = "15.1.0" -log = "0.4.11" - -# Bridge dependencies - -bp-runtime = { path = "../../../primitives/runtime" } -bp-messages = { path = "../../../primitives/messages" } - -# Substrate Dependencies - -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/messages/rpc/src/error.rs b/modules/messages/rpc/src/error.rs deleted file mode 100644 index 983b53b65ba37..0000000000000 --- a/modules/messages/rpc/src/error.rs +++ /dev/null @@ -1,59 +0,0 @@ -// 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 . - -//! Possible errors and results of messages pallet RPC calls. - -/// Future Result type. -pub type FutureResult = jsonrpc_core::BoxFuture; - -/// State RPC errors. -#[derive(Debug, derive_more::Display, derive_more::From)] -pub enum Error { - /// When unknown instance id is passed. - #[display(fmt = "Message lane instance is unknown")] - UnknownInstance, - /// Client error. - #[display(fmt = "Client error: {}", _0)] - Client(Box), -} - -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Error::UnknownInstance => None, - Error::Client(ref err) => Some(&**err), - } - } -} - -impl From for jsonrpc_core::Error { - fn from(e: Error) -> Self { - const UNKNOW_INSTANCE_CODE: i64 = 1; - - match e { - Error::UnknownInstance => jsonrpc_core::Error { - code: jsonrpc_core::ErrorCode::ServerError(UNKNOW_INSTANCE_CODE), - message: "Unknown instance passed".into(), - data: None, - }, - Error::Client(e) => jsonrpc_core::Error { - code: jsonrpc_core::ErrorCode::InternalError, - message: format!("Unknown error occured: {}", e), - data: Some(format!("{:?}", e).into()), - }, - } - } -} diff --git a/modules/messages/rpc/src/lib.rs b/modules/messages/rpc/src/lib.rs deleted file mode 100644 index a53dcfeb02767..0000000000000 --- a/modules/messages/rpc/src/lib.rs +++ /dev/null @@ -1,202 +0,0 @@ -// 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 . - -//! Pallet that provides RPC methods specific to messages pallet. - -use crate::error::{Error, FutureResult}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::InstanceId; -use futures::{FutureExt, TryFutureExt}; -use jsonrpc_core::futures::Future as _; -use jsonrpc_derive::rpc; -use sc_client_api::Backend as BackendT; -use sp_blockchain::{Error as BlockchainError, HeaderBackend}; -use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::{codec::Encode, generic::BlockId, traits::Block as BlockT}; -use sp_state_machine::prove_read; -use sp_trie::StorageProof; -use std::sync::Arc; - -mod error; - -/// Trie-based storage proof that the message(s) with given key(s) have been sent by the bridged chain. -/// SCALE-encoded trie nodes array `Vec>`. -pub type MessagesProof = Bytes; - -/// Trie-based storage proof that the message(s) with given key(s) have been received by the bridged chain. -/// SCALE-encoded trie nodes array `Vec>`. -pub type MessagesDeliveryProof = Bytes; - -/// Runtime adapter. -pub trait Runtime: Send + Sync + 'static { - /// Return runtime storage key for given message. May return None if instance is unknown. - fn message_key(&self, instance: &InstanceId, lane: &LaneId, nonce: MessageNonce) -> Option; - /// Return runtime storage key for outbound lane state. May return None if instance is unknown. - fn outbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option; - /// Return runtime storage key for inbound lane state. May return None if instance is unknown. - fn inbound_lane_data_key(&self, instance: &InstanceId, lane: &LaneId) -> Option; -} - -/// Provides RPC methods for interacting with messages pallet. -#[rpc] -pub trait MessagesApi { - /// Returns storage proof of messages in given inclusive range. The state of outbound - /// lane is included in the proof if `include_outbound_lane_state` is true. - #[rpc(name = "messages_proveMessages")] - fn prove_messages( - &self, - instance: InstanceId, - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - include_outbound_lane_state: bool, - block: Option, - ) -> FutureResult; - - /// Returns proof-of-message(s) delivery. - #[rpc(name = "messages_proveMessagesDelivery")] - fn prove_messages_delivery( - &self, - instance: InstanceId, - lane: LaneId, - block: Option, - ) -> FutureResult; -} - -/// Implements the MessagesApi trait for interacting with message lanes. -pub struct MessagesRpcHandler { - backend: Arc, - runtime: Arc, - _phantom: std::marker::PhantomData, -} - -impl MessagesRpcHandler { - /// Creates new mesage lane RPC handler. - pub fn new(backend: Arc, runtime: Arc) -> Self { - Self { - backend, - runtime, - _phantom: Default::default(), - } - } -} - -impl MessagesApi for MessagesRpcHandler -where - Block: BlockT, - Backend: BackendT + 'static, - R: Runtime, -{ - fn prove_messages( - &self, - instance: InstanceId, - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - include_outbound_lane_state: bool, - block: Option, - ) -> FutureResult { - let runtime = self.runtime.clone(); - let outbound_lane_data_key = if include_outbound_lane_state { - Some(runtime.outbound_lane_data_key(&instance, &lane)) - } else { - None - }; - let messages_count = if end >= begin { end - begin + 1 } else { 0 }; - Box::new( - prove_keys_read( - self.backend.clone(), - block, - (begin..=end) - .map(move |nonce| runtime.message_key(&instance, &lane, nonce)) - .chain(outbound_lane_data_key.into_iter()), - ) - .boxed() - .compat() - .map(move |proof| { - let serialized_proof = serialize_storage_proof(proof); - log::trace!( - "Generated proof of {} messages. Size: {}", - messages_count, - serialized_proof.len() - ); - serialized_proof - }) - .map_err(Into::into), - ) - } - - fn prove_messages_delivery( - &self, - instance: InstanceId, - lane: LaneId, - block: Option, - ) -> FutureResult { - Box::new( - prove_keys_read( - self.backend.clone(), - block, - vec![self.runtime.inbound_lane_data_key(&instance, &lane)], - ) - .boxed() - .compat() - .map(|proof| { - let serialized_proof = serialize_storage_proof(proof); - log::trace!("Generated message delivery proof. Size: {}", serialized_proof.len()); - serialized_proof - }) - .map_err(Into::into), - ) - } -} - -async fn prove_keys_read( - backend: Arc, - block: Option, - keys: impl IntoIterator>, -) -> Result -where - Block: BlockT, - Backend: BackendT + 'static, -{ - let block = unwrap_or_best(&*backend, block); - let state = backend.state_at(BlockId::Hash(block)).map_err(blockchain_err)?; - let keys = keys - .into_iter() - .map(|key| key.ok_or(Error::UnknownInstance).map(|key| key.0)) - .collect::, _>>()?; - let storage_proof = prove_read(state, keys) - .map_err(BlockchainError::Execution) - .map_err(blockchain_err)?; - Ok(storage_proof) -} - -fn serialize_storage_proof(proof: StorageProof) -> Bytes { - let raw_nodes: Vec> = proof.iter_nodes().map(Into::into).collect(); - raw_nodes.encode().into() -} - -fn unwrap_or_best(backend: &impl BackendT, block: Option) -> Block::Hash { - match block { - Some(block) => block, - None => backend.blockchain().info().best_hash, - } -} - -fn blockchain_err(err: BlockchainError) -> Error { - Error::Client(Box::new(err)) -} diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 99f88fbbbb30e..3123446caadf2 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -25,18 +25,19 @@ use bp_messages::{LaneId, MessageNonce}; use bp_runtime::InstanceId; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::{Decode, Encode}; -use frame_support::weights::Weight; +use frame_support::{traits::Instance, weights::Weight}; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ ClientState, MessageProofParameters, MessageWeights, MessageWeightsMap, SourceClient, SourceClientState, }, }; +use pallet_bridge_messages::Config as MessagesConfig; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use std::ops::RangeInclusive; +use std::{marker::PhantomData, ops::RangeInclusive}; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and @@ -44,14 +45,15 @@ use std::ops::RangeInclusive; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, lane: P, lane_id: LaneId, instance: InstanceId, + _phantom: PhantomData<(R, I)>, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { SubstrateMessagesSource { @@ -59,23 +61,31 @@ impl SubstrateMessagesSource { lane, lane_id, instance, + _phantom: Default::default(), } } } -impl Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), lane: self.lane.clone(), lane_id: self.lane_id, instance: self.instance, + _phantom: Default::default(), } } } #[async_trait] -impl RelayClient for SubstrateMessagesSource { +impl RelayClient for SubstrateMessagesSource +where + C: Chain, + P: SubstrateMessageLane, + R: Send + Sync, + I: Send + Sync + Instance, +{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { @@ -84,7 +94,7 @@ impl RelayClient for SubstrateMessagesSource< } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient

for SubstrateMessagesSource where C: Chain, C::Header: DeserializeOwned, @@ -98,6 +108,8 @@ where >, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, + R: Send + Sync + MessagesConfig, + I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because @@ -171,15 +183,22 @@ where nonces: RangeInclusive, proof_parameters: MessageProofParameters, ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), SubstrateError> { + let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); + let mut message_nonce = *nonces.start(); + while message_nonce <= *nonces.end() { + let message_key = pallet_bridge_messages::storage_keys::message_key::(&self.lane_id, message_nonce); + storage_keys.push(message_key); + message_nonce += 1; + } + if proof_parameters.outbound_state_proof_required { + storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key::( + &self.lane_id, + )); + } + let proof = self .client - .prove_messages( - self.instance, - self.lane_id, - nonces.clone(), - proof_parameters.outbound_state_proof_required, - id.1, - ) + .prove_storage(storage_keys, id.1) .await? .iter_nodes() .collect(); diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 3d8ab4fd0045f..fe3f95ca8e404 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -26,15 +26,17 @@ use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::InstanceId; use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use codec::{Decode, Encode}; +use frame_support::traits::Instance; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; +use pallet_bridge_messages::Config as MessagesConfig; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use std::ops::RangeInclusive; +use std::{marker::PhantomData, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. pub type SubstrateMessagesReceivingProof = ( @@ -43,14 +45,15 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, instance: InstanceId, + _phantom: PhantomData<(R, I)>, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { SubstrateMessagesTarget { @@ -58,23 +61,31 @@ impl SubstrateMessagesTarget { lane, lane_id, instance, + _phantom: Default::default(), } } } -impl Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), lane: self.lane.clone(), lane_id: self.lane_id, instance: self.instance, + _phantom: Default::default(), } } } #[async_trait] -impl RelayClient for SubstrateMessagesTarget { +impl RelayClient for SubstrateMessagesTarget +where + C: Chain, + P: SubstrateMessageLane, + R: Send + Sync, + I: Send + Sync + Instance, +{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { @@ -83,7 +94,7 @@ impl RelayClient for SubstrateMessagesTarget< } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient

for SubstrateMessagesTarget where C: Chain, C::Header: DeserializeOwned, @@ -97,6 +108,8 @@ where >, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, + R: Send + Sync + MessagesConfig, + I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because @@ -166,10 +179,13 @@ where id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), SubstrateError> { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; + let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); let proof = self .client - .prove_messages_delivery(self.instance, self.lane_id, id.1) - .await?; + .prove_storage(vec![inbound_data_key], id.1) + .await? + .iter_nodes() + .collect(); let proof = FromBridgedChainMessagesDeliveryProof { bridged_header_hash: id.1, storage_proof: proof, diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index 82c3dbaa3bc7e..31a0061819df1 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -126,10 +126,20 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } /// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; +type MillauSourceClient = SubstrateMessagesSource< + Millau, + MillauMessagesToRialto, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, +>; /// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; +type RialtoTargetClient = SubstrateMessagesTarget< + Rialto, + MillauMessagesToRialto, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, +>; /// Run Millau-to-Rialto messages sync. pub async fn run( @@ -196,8 +206,6 @@ pub async fn run( ) .standalone_metric(StorageProofOverheadMetric::new( millau_client.clone(), - (bp_runtime::RIALTO_BRIDGE_INSTANCE, lane_id), - millau_runtime::rialto_messages::inbound_lane_data_key(&lane_id), "millau_storage_proof_overhead".into(), "Millau storage proof overhead".into(), ))? diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index b98edccdc2dfb..3b11d998b3a02 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -126,10 +126,20 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } /// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource; +type RialtoSourceClient = SubstrateMessagesSource< + Rialto, + RialtoMessagesToMillau, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, +>; /// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget; +type MillauTargetClient = SubstrateMessagesTarget< + Millau, + RialtoMessagesToMillau, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, +>; /// Run Rialto-to-Millau messages sync. pub async fn run( @@ -195,8 +205,6 @@ pub async fn run( ) .standalone_metric(StorageProofOverheadMetric::new( rialto_client.clone(), - (bp_runtime::MILLAU_BRIDGE_INSTANCE, lane_id), - rialto_runtime::millau_messages::inbound_lane_data_key(&lane_id), "rialto_storage_proof_overhead".into(), "Rialto storage proof overhead".into(), ))? diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index e70351877c2e0..012913d4a4a21 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -34,6 +34,7 @@ sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 34763e9979eaf..ce91f4e33fc74 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -17,12 +17,10 @@ //! Substrate node client. use crate::chain::{Chain, ChainWithBalances}; -use crate::rpc::{Substrate, SubstrateMessages}; +use crate::rpc::Substrate; use crate::{ConnectionParams, Error, Result}; use async_std::sync::{Arc, Mutex}; -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::InstanceId; use codec::Decode; use frame_system::AccountInfo; use jsonrpsee_types::{jsonrpc::DeserializeOwned, traits::SubscriptionClient}; @@ -32,7 +30,6 @@ use pallet_balances::AccountData; use sp_core::{storage::StorageKey, Bytes}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; -use std::ops::RangeInclusive; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; @@ -175,12 +172,12 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { - Ok(Substrate::::runtime_version(&*self.client).await?) + Ok(Substrate::::state_runtime_version(&*self.client).await?) } /// Read value from runtime storage. pub async fn storage_value(&self, storage_key: StorageKey) -> Result> { - Substrate::::get_storage(&*self.client, storage_key) + Substrate::::state_get_storage(&*self.client, storage_key) .await? .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) .transpose() @@ -192,7 +189,7 @@ impl Client { C: ChainWithBalances, { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = Substrate::::get_storage(&*self.client, storage_key) + let encoded_account_data = Substrate::::state_get_storage(&*self.client, storage_key) .await? .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = @@ -255,45 +252,12 @@ impl Client { .map_err(Into::into) } - /// Returns proof-of-message(s) in given inclusive range. - pub async fn prove_messages( - &self, - instance: InstanceId, - lane: LaneId, - range: RangeInclusive, - include_outbound_lane_state: bool, - at_block: C::Hash, - ) -> Result { - let encoded_trie_nodes = SubstrateMessages::::prove_messages( - &*self.client, - instance, - lane, - *range.start(), - *range.end(), - include_outbound_lane_state, - Some(at_block), - ) - .await - .map_err(Error::RpcError)?; - let decoded_trie_nodes: Vec> = - Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; - Ok(StorageProof::new(decoded_trie_nodes)) - } - - /// Returns proof-of-message(s) delivery. - pub async fn prove_messages_delivery( - &self, - instance: InstanceId, - lane: LaneId, - at_block: C::Hash, - ) -> Result>> { - let encoded_trie_nodes = - SubstrateMessages::::prove_messages_delivery(&*self.client, instance, lane, Some(at_block)) - .await - .map_err(Error::RpcError)?; - let decoded_trie_nodes: Vec> = - Decode::decode(&mut &encoded_trie_nodes[..]).map_err(Error::ResponseParseFailed)?; - Ok(decoded_trie_nodes) + /// Returns storage proof of given storage keys. + pub async fn prove_storage(&self, keys: Vec, at_block: C::Hash) -> Result { + Substrate::::state_prove_storage(&*self.client, keys, Some(at_block)) + .await + .map(|proof| StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect())) + .map_err(Into::into) } /// Return new justifications stream. diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index e1269306c3c74..7aee28df18574 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -36,6 +36,8 @@ pub enum Error { UninitializedBridgePallet, /// Account does not exist on the chain. AccountDoesNotExist, + /// Runtime storage is missing mandatory ":code:" entry. + MissingMandatoryCodeEntry, /// The client we're connected to is not synced, so we can't rely on its state. ClientNotSynced(Health), /// An error has happened when we have tried to parse storage proof. @@ -51,6 +53,7 @@ impl std::error::Error for Error { Self::ResponseParseFailed(ref e) => Some(e), Self::UninitializedBridgePallet => None, Self::AccountDoesNotExist => None, + Self::MissingMandatoryCodeEntry => None, Self::ClientNotSynced(_) => None, Self::StorageProofError(_) => None, Self::Custom(_) => None, @@ -85,6 +88,7 @@ impl std::fmt::Display for Error { Self::ResponseParseFailed(e) => e.to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), + Self::MissingMandatoryCodeEntry => "Mandatory :code: entry is missing from runtime storage".into(), Self::StorageProofError(e) => format!("Error when parsing storage proof: {:?}", e), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), Self::Custom(e) => e.clone(), diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs index 167f59605d27e..e440683f527e6 100644 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -19,12 +19,10 @@ use crate::client::Client; use crate::error::Error; use async_trait::async_trait; -use bp_messages::LaneId; -use bp_runtime::InstanceId; use relay_utils::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, U64}; use sp_core::storage::StorageKey; use sp_runtime::traits::Header as HeaderT; -use sp_trie::StorageProof; +use sp_storage::well_known_keys::CODE; use std::time::Duration; /// Storage proof overhead update interval (in blocks). @@ -32,20 +30,11 @@ const UPDATE_INTERVAL_IN_BLOCKS: u32 = 100; /// Metric that represents extra size of storage proof as unsigned integer gauge. /// -/// Regular Substrate node does not provide any RPC endpoints that return storage proofs. -/// So here we're using our own `pallet-bridge-messages-rpc` RPC API, which returns proof -/// of the inbound message lane state. Then we simply subtract size of this state from -/// the size of storage proof to compute metric value. -/// -/// There are two things to keep in mind when using this metric: -/// -/// 1) it'll only work on inbound lanes that have already accepted at least one message; -/// 2) the overhead may be slightly different for other values, but this metric gives a good estimation. +/// There's one thing to keep in mind when using this metric: the overhead may be slightly +/// different for other values, but this metric gives a good estimation. #[derive(Debug)] pub struct StorageProofOverheadMetric { client: Client, - inbound_lane: (InstanceId, LaneId), - inbound_lane_data_key: StorageKey, metric: Gauge, } @@ -53,8 +42,6 @@ impl Clone for StorageProofOverheadMetric { fn clone(&self) -> Self { StorageProofOverheadMetric { client: self.client.clone(), - inbound_lane: self.inbound_lane, - inbound_lane_data_key: self.inbound_lane_data_key.clone(), metric: self.metric.clone(), } } @@ -62,17 +49,9 @@ impl Clone for StorageProofOverheadMetric { impl StorageProofOverheadMetric { /// Create new metric instance with given name and help. - pub fn new( - client: Client, - inbound_lane: (InstanceId, LaneId), - inbound_lane_data_key: StorageKey, - name: String, - help: String, - ) -> Self { + pub fn new(client: Client, name: String, help: String) -> Self { StorageProofOverheadMetric { client, - inbound_lane, - inbound_lane_data_key, metric: Gauge::new(name, help).expect( "only fails if gauge options are customized;\ we use default options;\ @@ -82,32 +61,27 @@ impl StorageProofOverheadMetric { } /// Returns approximate storage proof size overhead. - /// - /// Returs `Ok(None)` if inbound lane we're watching for has no state. This shouldn't be treated as error. - async fn compute_storage_proof_overhead(&self) -> Result, Error> { + async fn compute_storage_proof_overhead(&self) -> Result { let best_header_hash = self.client.best_finalized_header_hash().await?; let best_header = self.client.header_by_hash(best_header_hash).await?; let storage_proof = self .client - .prove_messages_delivery(self.inbound_lane.0, self.inbound_lane.1, best_header_hash) + .prove_storage(vec![StorageKey(CODE.to_vec())], best_header_hash) .await?; - let storage_proof_size: usize = storage_proof.iter().map(|n| n.len()).sum(); + let storage_proof_size: usize = storage_proof.clone().iter_nodes().map(|n| n.len()).sum(); - let storage_value_reader = bp_runtime::StorageProofChecker::::new( - *best_header.state_root(), - StorageProof::new(storage_proof), - ) - .map_err(Error::StorageProofError)?; + let storage_value_reader = + bp_runtime::StorageProofChecker::::new(*best_header.state_root(), storage_proof) + .map_err(Error::StorageProofError)?; let maybe_encoded_storage_value = storage_value_reader - .read_value(&self.inbound_lane_data_key.0) + .read_value(CODE) .map_err(Error::StorageProofError)?; - let encoded_storage_value_size = match maybe_encoded_storage_value { - Some(encoded_storage_value) => encoded_storage_value.len(), - None => return Ok(None), - }; + let encoded_storage_value_size = maybe_encoded_storage_value + .ok_or(Error::MissingMandatoryCodeEntry)? + .len(); - Ok(Some(storage_proof_size - encoded_storage_value_size)) + Ok(storage_proof_size - encoded_storage_value_size) } } @@ -129,7 +103,7 @@ impl StandaloneMetrics for StorageProofOverheadMetric { &self.metric, self.compute_storage_proof_overhead() .await - .map(|v| v.map(|overhead| overhead as u64)), + .map(|overhead| Some(overhead as u64)), ); } } diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 1816e8cd3f263..06df1f705d093 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -18,9 +18,7 @@ use crate::chain::Chain; -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::InstanceId; -use sc_rpc_api::system::Health; +use sc_rpc_api::{state::ReadProof, system::Health}; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, @@ -46,27 +44,10 @@ jsonrpsee_proc_macros::rpc_client_api! { #[rpc(method = "state_call", positional_params)] fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; #[rpc(method = "state_getStorage", positional_params)] - fn get_storage(key: StorageKey) -> Option; + fn state_get_storage(key: StorageKey) -> Option; + #[rpc(method = "state_getReadProof", positional_params)] + fn state_prove_storage(keys: Vec, hash: Option) -> ReadProof; #[rpc(method = "state_getRuntimeVersion", positional_params)] - fn runtime_version() -> RuntimeVersion; - } - - pub(crate) SubstrateMessages { - #[rpc(method = "messages_proveMessages", positional_params)] - fn prove_messages( - instance: InstanceId, - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - include_outbound_lane_state: bool, - block: Option, - ) -> Bytes; - - #[rpc(method = "messages_proveMessagesDelivery", positional_params)] - fn prove_messages_delivery( - instance: InstanceId, - lane: LaneId, - block: Option, - ) -> Bytes; + fn state_runtime_version() -> RuntimeVersion; } } From 419533cd6b4f7ebd9112904b53caf4a9a386ddac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 14 Apr 2021 13:01:03 +0300 Subject: [PATCH 0425/1210] Complex headers+messages Millau<->Rialto relay (#878) * complex headers+messages relay * post-merge fix * fix + test issue with on-demand not starting --- relays/bin-substrate/src/cli/mod.rs | 9 + .../src/cli/relay_headers_and_messages.rs | 183 +++++++++++++ .../bin-substrate/src/cli/relay_messages.rs | 12 +- relays/bin-substrate/src/main.rs | 1 + relays/bin-substrate/src/messages_lane.rs | 25 +- relays/bin-substrate/src/messages_source.rs | 23 +- relays/bin-substrate/src/messages_target.rs | 23 +- relays/bin-substrate/src/on_demand_headers.rs | 255 ++++++++++++++++++ .../millau_messages_to_rialto.rs | 86 +++--- relays/bin-substrate/src/rialto_millau/mod.rs | 5 - .../rialto_messages_to_millau.rs | 86 +++--- .../westend_headers_to_millau.rs | 34 ++- .../src/metrics/float_storage_value.rs | 23 +- .../src/metrics/storage_proof_overhead.rs | 27 +- relays/exchange/src/exchange_loop.rs | 14 +- relays/exchange/src/exchange_loop_metrics.rs | 61 +++-- relays/finality/src/finality_loop.rs | 6 +- relays/headers/src/sync_loop.rs | 11 +- relays/headers/src/sync_loop_metrics.rs | 49 ++-- relays/messages/src/message_lane_loop.rs | 44 +-- relays/messages/src/message_race_delivery.rs | 8 +- relays/messages/src/message_race_loop.rs | 24 +- relays/messages/src/message_race_receiving.rs | 4 +- relays/messages/src/message_race_strategy.rs | 9 + relays/messages/src/metrics.rs | 43 +-- relays/utils/src/metrics.rs | 34 ++- relays/utils/src/metrics/float_json_value.rs | 28 +- relays/utils/src/metrics/global.rs | 51 ++-- relays/utils/src/relay_loop.rs | 61 +++-- 29 files changed, 931 insertions(+), 308 deletions(-) create mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages.rs create mode 100644 relays/bin-substrate/src/on_demand_headers.rs diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index c77d5071db326..8af3301231d85 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -33,6 +33,7 @@ pub(crate) mod send_message; mod derive_account; mod init_bridge; mod relay_headers; +mod relay_headers_and_messages; mod relay_messages; /// Parse relay CLI args. @@ -54,6 +55,13 @@ pub enum Command { /// Ties up to `Messages` pallets on both chains and starts relaying messages. /// Requires the header relay to be already running. RelayMessages(relay_messages::RelayMessages), + /// Start headers and messages relay between two Substrate chains. + /// + /// This high-level relay internally starts four low-level relays: two `RelayHeaders` + /// and two `RelayMessages` relays. Headers are only relayed when they are required by + /// the message relays - i.e. when there are messages or confirmations that needs to be + /// relayed between chains. + RelayHeadersAndMessages(relay_headers_and_messages::RelayHeadersAndMessages), /// Initialize on-chain bridge pallet with current header data. /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. @@ -86,6 +94,7 @@ impl Command { match self { Self::RelayHeaders(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?, + Self::RelayHeadersAndMessages(arg) => arg.run().await?, Self::InitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, Self::EncodeCall(arg) => arg.run().await?, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs new file mode 100644 index 0000000000000..ded79e0f4c9fb --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -0,0 +1,183 @@ +// 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 . + +//! Complex headers+messages relays support. +//! +//! To add new complex relay between `ChainA` and `ChainB`, you must: +//! +//! 1) ensure that there's a `declare_chain_options!(...)` for both chains; +//! 2) add `declare_bridge_options!(...)` for the bridge; +//! 3) add bridge support to the `select_bridge! { ... }` macro. + +use crate::cli::{CliChain, HexLaneId, PrometheusParams}; +use crate::declare_chain_options; +use crate::messages_lane::MessagesRelayParams; +use crate::on_demand_headers::OnDemandHeadersRelay; + +use futures::{FutureExt, TryFutureExt}; +use relay_utils::metrics::MetricsParams; +use structopt::StructOpt; + +/// Start headers+messages relayer process. +#[derive(StructOpt)] +pub enum RelayHeadersAndMessages { + MillauRialto(MillauRialtoHeadersAndMessages), +} + +/// Parameters that have the same names across all bridges. +#[derive(StructOpt)] +pub struct HeadersAndMessagesSharedParams { + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +// The reason behind this macro is that 'normal' relays are using source and target chains terminology, +// which is unusable for both-way relays (if you're relaying headers from Rialto to Millau and from +// Millau to Rialto, then which chain is source?). +macro_rules! declare_bridge_options { + ($chain1:ident, $chain2:ident) => { + paste::item! { + #[doc = $chain1 " and " $chain2 " headers+messages relay params."] + #[derive(StructOpt)] + pub struct [<$chain1 $chain2 HeadersAndMessages>] { + #[structopt(flatten)] + shared: HeadersAndMessagesSharedParams, + #[structopt(flatten)] + left: [<$chain1 ConnectionParams>], + #[structopt(flatten)] + left_sign: [<$chain1 SigningParams>], + #[structopt(flatten)] + right: [<$chain2 ConnectionParams>], + #[structopt(flatten)] + right_sign: [<$chain2 SigningParams>], + } + + #[allow(unreachable_patterns)] + impl From for [<$chain1 $chain2 HeadersAndMessages>] { + fn from(relay_params: RelayHeadersAndMessages) -> [<$chain1 $chain2 HeadersAndMessages>] { + match relay_params { + RelayHeadersAndMessages::[<$chain1 $chain2>](params) => params, + _ => unreachable!(), + } + } + } + } + }; +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + RelayHeadersAndMessages::MillauRialto(_) => { + type Params = MillauRialtoHeadersAndMessages; + + type Left = relay_millau_client::Millau; + type Right = relay_rialto_client::Rialto; + + type LeftToRightFinality = crate::rialto_millau::millau_headers_to_rialto::MillauFinalityToRialto; + type RightToLeftFinality = crate::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; + + type LeftToRightMessages = crate::rialto_millau::millau_messages_to_rialto::MillauMessagesToRialto; + type RightToLeftMessages = crate::rialto_millau::rialto_messages_to_millau::RialtoMessagesToMillau; + + use crate::rialto_millau::millau_messages_to_rialto::run as left_to_right_messages; + use crate::rialto_millau::rialto_messages_to_millau::run as right_to_left_messages; + + $generic + } + } + }; +} + +// All supported chains. +declare_chain_options!(Millau, millau); +declare_chain_options!(Rialto, rialto); +// All supported bridges. +declare_bridge_options!(Millau, Rialto); + +impl RelayHeadersAndMessages { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self, { + let params: Params = self.into(); + + let left_client = params.left.to_client::().await?; + let left_sign = params.left_sign.to_keypair::()?; + let right_client = params.right.to_client::().await?; + let right_sign = params.right_sign.to_keypair::()?; + + let lane = params.shared.lane.into(); + + let metrics_params: MetricsParams = params.shared.prometheus_params.into(); + let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); + + let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( + left_client.clone(), + right_client.clone(), + LeftToRightFinality::new(right_client.clone(), right_sign.clone()), + ); + let right_to_left_on_demand_headers = OnDemandHeadersRelay::new( + right_client.clone(), + left_client.clone(), + RightToLeftFinality::new(left_client.clone(), left_sign.clone()), + ); + + let left_to_right_messages = left_to_right_messages(MessagesRelayParams { + source_client: left_client.clone(), + source_sign: left_sign.clone(), + target_client: right_client.clone(), + target_sign: right_sign.clone(), + source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), + target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), + lane_id: lane, + metrics_params: metrics_params + .clone() + .disable() + .metrics_prefix(messages_relay::message_lane_loop::metrics_prefix::(&lane)), + }) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + let right_to_left_messages = right_to_left_messages(MessagesRelayParams { + source_client: right_client, + source_sign: right_sign, + target_client: left_client.clone(), + target_sign: left_sign.clone(), + source_to_target_headers_relay: Some(right_to_left_on_demand_headers), + target_to_source_headers_relay: Some(left_to_right_on_demand_headers), + lane_id: lane, + metrics_params: metrics_params + .clone() + .disable() + .metrics_prefix(messages_relay::message_lane_loop::metrics_prefix::(&lane)), + }) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + + relay_utils::relay_metrics(None, metrics_params) + .expose() + .await + .map_err(|e| anyhow::format_err!("{}", e))?; + + futures::future::select(left_to_right_messages, right_to_left_messages) + .await + .factor_first() + .0 + }) + } +} diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 0e863f25c7a6c..94630886ca38e 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -19,7 +19,9 @@ use crate::cli::{ HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; +use crate::messages_lane::MessagesRelayParams; use crate::select_full_bridge; + use structopt::StructOpt; /// Start messages relayer process. @@ -52,14 +54,16 @@ impl RelayMessages { let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; - relay_messages( + relay_messages(MessagesRelayParams { source_client, source_sign, target_client, target_sign, - self.lane.into(), - self.prometheus_params.into(), - ) + source_to_target_headers_relay: None, + target_to_source_headers_relay: None, + lane_id: self.lane.into(), + metrics_params: self.prometheus_params.into(), + }) .await .map_err(|e| anyhow::format_err!("{}", e)) }) diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 11ff67e83b403..81da25fcb7de9 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -27,6 +27,7 @@ mod headers_initialize; mod messages_lane; mod messages_source; mod messages_target; +mod on_demand_headers; mod rialto_millau; diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index ada5ce12bfc33..753bf6320d511 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -16,15 +16,36 @@ use crate::messages_source::SubstrateMessagesProof; use crate::messages_target::SubstrateMessagesReceivingProof; +use crate::on_demand_headers::OnDemandHeadersRelay; -use bp_messages::MessageNonce; +use bp_messages::{LaneId, MessageNonce}; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use relay_substrate_client::{BlockNumberOf, Chain, Client, HashOf}; -use relay_utils::BlockNumberBase; +use relay_utils::{metrics::MetricsParams, BlockNumberBase}; use sp_core::Bytes; use std::ops::RangeInclusive; +/// Substrate <-> Substrate messages relay parameters. +pub struct MessagesRelayParams { + /// Messages source client. + pub source_client: Client, + /// Sign parameters for messages source chain. + pub source_sign: SS, + /// Messages target client. + pub target_client: Client, + /// Sign parameters for messages target chain. + pub target_sign: TS, + /// Optional on-demand source to target headers relay. + pub source_to_target_headers_relay: Option>, + /// Optional on-demand target to source headers relay. + pub target_to_source_headers_relay: Option>, + /// Identifier of lane that needs to be served. + pub lane_id: LaneId, + /// Metrics parameters. + pub metrics_params: MetricsParams, +} + /// Message sync pipeline for Substrate <-> Substrate relays. pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 3123446caadf2..cf98f3276be6c 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -19,6 +19,7 @@ //! chain. use crate::messages_lane::SubstrateMessageLane; +use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; @@ -45,22 +46,30 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, lane: P, lane_id: LaneId, instance: InstanceId, + target_to_source_headers_relay: Option>, _phantom: PhantomData<(R, I)>, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. - pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { + pub fn new( + client: Client, + lane: P, + lane_id: LaneId, + instance: InstanceId, + target_to_source_headers_relay: Option>, + ) -> Self { SubstrateMessagesSource { client, lane, lane_id, instance, + target_to_source_headers_relay, _phantom: Default::default(), } } @@ -73,6 +82,7 @@ impl Clone for SubstrateMessagesSource< lane: self.lane.clone(), lane_id: self.lane_id, instance: self.instance, + target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), _phantom: Default::default(), } } @@ -106,6 +116,7 @@ where SourceHeaderHash = ::Hash, SourceChain = C, >, + P::TargetChain: Chain, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, R: Send + Sync + MessagesConfig, @@ -226,7 +237,11 @@ where Ok(()) } - async fn activate_target_to_source_headers_relay(&self, _activate: bool) {} + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

) { + if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { + target_to_source_headers_relay.require_finalized_header(id); + } + } } pub async fn read_client_state( diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index fe3f95ca8e404..176083273069b 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -20,6 +20,7 @@ use crate::messages_lane::SubstrateMessageLane; use crate::messages_source::read_client_state; +use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; @@ -45,22 +46,30 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, instance: InstanceId, + source_to_target_headers_relay: Option>, _phantom: PhantomData<(R, I)>, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. - pub fn new(client: Client, lane: P, lane_id: LaneId, instance: InstanceId) -> Self { + pub fn new( + client: Client, + lane: P, + lane_id: LaneId, + instance: InstanceId, + source_to_target_headers_relay: Option>, + ) -> Self { SubstrateMessagesTarget { client, lane, lane_id, instance, + source_to_target_headers_relay, _phantom: Default::default(), } } @@ -73,6 +82,7 @@ impl Clone for SubstrateMessagesTarget< lane: self.lane.clone(), lane_id: self.lane_id, instance: self.instance, + source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), _phantom: Default::default(), } } @@ -106,6 +116,7 @@ where TargetHeaderNumber = ::Number, TargetHeaderHash = ::Hash, >, + P::SourceChain: Chain, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, R: Send + Sync + MessagesConfig, @@ -213,5 +224,9 @@ where Ok(nonces) } - async fn activate_source_to_target_headers_relay(&self, _activate: bool) {} + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

) { + if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { + source_to_target_headers_relay.require_finalized_header(id); + } + } } diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs new file mode 100644 index 0000000000000..4c86b6a17018a --- /dev/null +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -0,0 +1,255 @@ +// 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 . + +//! On-demand Substrate -> Substrate headers relay. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use crate::finality_target::SubstrateFinalityTarget; + +use bp_header_chain::justification::GrandpaJustification; +use finality_relay::TargetClient as FinalityTargetClient; +use futures::{ + channel::{mpsc, oneshot}, + select, FutureExt, StreamExt, +}; +use num_traits::Zero; +use relay_substrate_client::{BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader}; +use relay_utils::{metrics::MetricsParams, BlockNumberBase, HeaderId}; +use std::fmt::Debug; + +/// On-demand Substrate <-> Substrate headers relay. +/// +/// This relay may be started by messages whenever some other relay (e.g. messages relay) needs more +/// headers to be relayed to continue its regular work. When enough headers are relayed, on-demand +/// relay may be deactivated. +#[derive(Clone)] +pub struct OnDemandHeadersRelay { + /// Background task name. + background_task_name: String, + /// Required headers to background sender. + required_header_tx: mpsc::Sender>, +} + +impl OnDemandHeadersRelay { + /// Create new on-demand headers relay. + pub fn new( + source_client: Client, + target_client: Client, + pipeline: SubstrateFinalityToSubstrate, + ) -> Self + where + SourceChain: Chain + Debug, + SourceChain::BlockNumber: BlockNumberBase, + TargetChain: Chain + Debug, + TargetChain::BlockNumber: BlockNumberBase, + TargetSign: Clone + Send + Sync + 'static, + SubstrateFinalityToSubstrate: SubstrateFinalitySyncPipeline< + Hash = HashOf, + Number = BlockNumberOf, + Header = SyncHeader, + FinalityProof = GrandpaJustification, + TargetChain = TargetChain, + >, + SubstrateFinalityTarget>: + FinalityTargetClient>, + { + let (required_header_tx, required_header_rx) = mpsc::channel(1); + async_std::task::spawn(async move { + background_task(source_client, target_client, pipeline, required_header_rx).await; + }); + + let background_task_name = format!( + "{}-background", + on_demand_headers_relay_name::() + ); + OnDemandHeadersRelay { + background_task_name, + required_header_tx, + } + } + + /// Someone is asking us to relay given finalized header. + pub fn require_finalized_header(&self, header_id: HeaderIdOf) { + if let Err(error) = self.required_header_tx.clone().try_send(header_id) { + log::error!( + target: "bridge", + "Failed to send require header id {:?} to {:?}: {:?}", + header_id, + self.background_task_name, + error, + ); + } + } +} + +/// Background task that is responsible for starting and stopping headers relay when required. +async fn background_task( + source_client: Client, + target_client: Client, + pipeline: SubstrateFinalityToSubstrate, + mut required_header_rx: mpsc::Receiver>, +) where + SourceChain: Chain + Debug, + SourceChain::BlockNumber: BlockNumberBase, + TargetChain: Chain + Debug, + TargetChain::BlockNumber: BlockNumberBase, + TargetSign: Clone + Send + Sync + 'static, + SubstrateFinalityToSubstrate: SubstrateFinalitySyncPipeline< + Hash = HashOf, + Number = BlockNumberOf, + Header = SyncHeader, + FinalityProof = GrandpaJustification, + TargetChain = TargetChain, + >, + SubstrateFinalityTarget>: + FinalityTargetClient>, +{ + let relay_task_name = on_demand_headers_relay_name::(); + let finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); + + let mut active_headers_relay = None; + let mut required_header_number = Zero::zero(); + let mut relay_exited_rx = futures::future::pending().left_future(); + + loop { + // wait for next target block or for new required header + select! { + _ = async_std::task::sleep(TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, + required_header_id = required_header_rx.next() => { + match required_header_id { + Some(required_header_id) => { + if required_header_id.0 > required_header_number { + required_header_number = required_header_id.0; + } + }, + None => { + // that's the only way to exit background task - to drop `required_header_tx` + break + }, + } + }, + _ = relay_exited_rx => { + // there could be a situation when we're receiving exit signals after we + // have already stopped relay or when we have already started new relay. + // but it isn't critical, because even if we'll accidentally stop new relay + // we'll restart it almost immediately + stop_on_demand_headers_relay(active_headers_relay.take()).await; + }, + } + + // read best finalized source block from target + let available_header_number = match finality_target.best_finalized_source_block_number().await { + Ok(available_header_number) => available_header_number, + Err(error) => { + log::error!( + target: "bridge", + "Failed to read best finalized {} header from {} in {} relay: {:?}", + SourceChain::NAME, + TargetChain::NAME, + relay_task_name, + error, + ); + + // we don't know what's happening with target client, so better to stop on-demand relay than + // submit unneeded transactions + // => assume that required header is known to the target node + required_header_number + } + }; + + // start or stop headers relay if required + let activate = required_header_number > available_header_number; + match (activate, active_headers_relay.is_some()) { + (true, false) => { + let (relay_exited_tx, new_relay_exited_rx) = oneshot::channel(); + active_headers_relay = start_on_demand_headers_relay( + relay_task_name.clone(), + relay_exited_tx, + source_client.clone(), + target_client.clone(), + pipeline.clone(), + ); + if active_headers_relay.is_some() { + relay_exited_rx = new_relay_exited_rx.right_future(); + } + } + (false, true) => { + stop_on_demand_headers_relay(active_headers_relay.take()).await; + } + _ => (), + } + } +} + +/// On-demand headers relay task name. +fn on_demand_headers_relay_name() -> String { + format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) +} + +/// Start on-demand headers relay task. +fn start_on_demand_headers_relay( + task_name: String, + relay_exited_tx: oneshot::Sender<()>, + source_client: Client, + target_client: Client, + pipeline: SubstrateFinalityToSubstrate, +) -> Option> +where + SourceChain::BlockNumber: BlockNumberBase, + SubstrateFinalityToSubstrate: SubstrateFinalitySyncPipeline< + Hash = HashOf, + Number = BlockNumberOf, + Header = SyncHeader, + FinalityProof = GrandpaJustification, + TargetChain = TargetChain, + >, + TargetSign: 'static, +{ + let headers_relay_future = + crate::finality_pipeline::run(pipeline, source_client, target_client, MetricsParams::disabled()); + let closure_task_name = task_name.clone(); + async_std::task::Builder::new() + .name(task_name.clone()) + .spawn(async move { + log::info!(target: "bridge", "Starting {} headers relay", closure_task_name); + let result = headers_relay_future.await; + log::trace!(target: "bridge", "{} headers relay has exited. Result: {:?}", closure_task_name, result); + let _ = relay_exited_tx.send(()); + }) + .map_err(|error| { + log::error!( + target: "bridge", + "Failed to start {} relay: {:?}", + task_name, + error, + ); + }) + .ok() +} + +/// Stop on-demand headers relay task. +async fn stop_on_demand_headers_relay(task: Option>) { + if let Some(task) = task { + let task_name = task + .task() + .name() + .expect("on-demand tasks are always started with name; qed") + .to_string(); + log::trace!(target: "bridge", "Cancelling {} headers relay", task_name); + task.cancel().await; + log::info!(target: "bridge", "Cancelled {} headers relay", task_name); + } +} diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs index 31a0061819df1..d96fa7b797209 100644 --- a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs @@ -16,12 +16,13 @@ //! Millau-to-Rialto messages sync entrypoint. -use super::{MillauClient, RialtoClient}; -use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; +use crate::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, +}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; -use bp_messages::{LaneId, MessageNonce}; +use bp_messages::MessageNonce; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; @@ -33,12 +34,12 @@ use relay_substrate_client::{ metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, Chain, TransactionSignScheme, }; -use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; /// Millau-to-Rialto message lane. -type MillauMessagesToRialto = SubstrateMessageLaneToSubstrate; +pub type MillauMessagesToRialto = + SubstrateMessageLaneToSubstrate; impl SubstrateMessageLane for MillauMessagesToRialto { const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = @@ -143,21 +144,18 @@ type RialtoTargetClient = SubstrateMessagesTarget< /// Run Millau-to-Rialto messages sync. pub async fn run( - millau_client: MillauClient, - millau_sign: MillauSigningParams, - rialto_client: RialtoClient, - rialto_sign: RialtoSigningParams, - lane_id: LaneId, - metrics_params: MetricsParams, + params: MessagesRelayParams, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id_at_millau = (*millau_sign.public().as_array_ref()).into(); + let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); + let lane_id = params.lane_id; + let source_client = params.source_client; let lane = MillauMessagesToRialto { - source_client: millau_client.clone(), - source_sign: millau_sign, - target_client: rialto_client.clone(), - target_sign: rialto_sign, + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, relayer_id_at_source: relayer_id_at_millau, }; @@ -198,24 +196,48 @@ pub async fn run( max_messages_size_in_single_batch, }, }, - MillauSourceClient::new(millau_client.clone(), lane.clone(), lane_id, RIALTO_BRIDGE_INSTANCE), - RialtoTargetClient::new(rialto_client, lane, lane_id, MILLAU_BRIDGE_INSTANCE), + MillauSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + RIALTO_BRIDGE_INSTANCE, + params.target_to_source_headers_relay, + ), + RialtoTargetClient::new( + params.target_client, + lane, + lane_id, + MILLAU_BRIDGE_INSTANCE, + params.source_to_target_headers_relay, + ), relay_utils::relay_metrics( - messages_relay::message_lane_loop::metrics_prefix::(&lane_id), - metrics_params.address, + Some(messages_relay::message_lane_loop::metrics_prefix::< + MillauMessagesToRialto, + >(&lane_id)), + params.metrics_params, ) - .standalone_metric(StorageProofOverheadMetric::new( - millau_client.clone(), - "millau_storage_proof_overhead".into(), - "Millau storage proof overhead".into(), - ))? - .standalone_metric(FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - millau_client, - sp_core::storage::StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), - Some(millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE), - "millau_rialto_to_millau_conversion_rate".into(), - "Rialto to Millau tokens conversion rate (used by Rialto)".into(), - ))? + .standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + "millau_storage_proof_overhead".into(), + "Millau storage proof overhead".into(), + ) + })? + .standalone_metric(|registry, prefix| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + registry, + prefix, + source_client, + sp_core::storage::StorageKey( + millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec(), + ), + Some(millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE), + "millau_rialto_to_millau_conversion_rate".into(), + "Rialto to Millau tokens conversion rate (used by Rialto)".into(), + ) + })? .into_params(), futures::future::pending(), ) diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index a04cd55f7d849..af17f62a05fe7 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -22,11 +22,6 @@ pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; pub mod westend_headers_to_millau; -/// Millau node client. -pub type MillauClient = relay_substrate_client::Client; -/// Rialto node client. -pub type RialtoClient = relay_substrate_client::Client; - use crate::cli::{ bridge, encode_call::{self, Call, CliEncodeCall}, diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs index 3b11d998b3a02..ec39a4caa3fcb 100644 --- a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs @@ -16,12 +16,13 @@ //! Rialto-to-Millau messages sync entrypoint. -use super::{MillauClient, RialtoClient}; -use crate::messages_lane::{select_delivery_transaction_limits, SubstrateMessageLane, SubstrateMessageLaneToSubstrate}; +use crate::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, +}; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; -use bp_messages::{LaneId, MessageNonce}; +use bp_messages::MessageNonce; use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; @@ -33,12 +34,12 @@ use relay_substrate_client::{ metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, Chain, TransactionSignScheme, }; -use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; /// Rialto-to-Millau message lane. -type RialtoMessagesToMillau = SubstrateMessageLaneToSubstrate; +pub type RialtoMessagesToMillau = + SubstrateMessageLaneToSubstrate; impl SubstrateMessageLane for RialtoMessagesToMillau { const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = @@ -143,21 +144,18 @@ type MillauTargetClient = SubstrateMessagesTarget< /// Run Rialto-to-Millau messages sync. pub async fn run( - rialto_client: RialtoClient, - rialto_sign: RialtoSigningParams, - millau_client: MillauClient, - millau_sign: MillauSigningParams, - lane_id: LaneId, - metrics_params: MetricsParams, + params: MessagesRelayParams, ) -> Result<(), String> { let stall_timeout = Duration::from_secs(5 * 60); - let relayer_id_at_rialto = (*rialto_sign.public().as_array_ref()).into(); + let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); + let lane_id = params.lane_id; + let source_client = params.source_client; let lane = RialtoMessagesToMillau { - source_client: rialto_client.clone(), - source_sign: rialto_sign, - target_client: millau_client.clone(), - target_sign: millau_sign, + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, relayer_id_at_source: relayer_id_at_rialto, }; @@ -197,24 +195,48 @@ pub async fn run( max_messages_size_in_single_batch, }, }, - RialtoSourceClient::new(rialto_client.clone(), lane.clone(), lane_id, MILLAU_BRIDGE_INSTANCE), - MillauTargetClient::new(millau_client, lane, lane_id, RIALTO_BRIDGE_INSTANCE), + RialtoSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + MILLAU_BRIDGE_INSTANCE, + params.target_to_source_headers_relay, + ), + MillauTargetClient::new( + params.target_client, + lane, + lane_id, + RIALTO_BRIDGE_INSTANCE, + params.source_to_target_headers_relay, + ), relay_utils::relay_metrics( - messages_relay::message_lane_loop::metrics_prefix::(&lane_id), - metrics_params.address, + Some(messages_relay::message_lane_loop::metrics_prefix::< + RialtoMessagesToMillau, + >(&lane_id)), + params.metrics_params, ) - .standalone_metric(StorageProofOverheadMetric::new( - rialto_client.clone(), - "rialto_storage_proof_overhead".into(), - "Rialto storage proof overhead".into(), - ))? - .standalone_metric(FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - rialto_client, - sp_core::storage::StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), - Some(rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE), - "rialto_millau_to_rialto_conversion_rate".into(), - "Millau to Rialto tokens conversion rate (used by Millau)".into(), - ))? + .standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + "rialto_storage_proof_overhead".into(), + "Rialto storage proof overhead".into(), + ) + })? + .standalone_metric(|registry, prefix| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + registry, + prefix, + source_client, + sp_core::storage::StorageKey( + rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec(), + ), + Some(rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE), + "rialto_millau_to_rialto_conversion_rate".into(), + "Millau to Rialto tokens conversion rate (used by Millau)".into(), + ) + })? .into_params(), futures::future::pending(), ) diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index c6f9a1fd3d8ba..f8f023da19b09 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -36,22 +36,30 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { fn customize_metrics(params: MetricsParams) -> anyhow::Result { Ok( - relay_utils::relay_metrics(finality_relay::metrics_prefix::(), params.address) + relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama // relays, but we want to test metrics/dashboards in advance - .standalone_metric(FloatJsonValueMetric::new( - "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), - "$.polkadot.usd".into(), - "polkadot_price".into(), - "Polkadot price in USD".into(), - )) + .standalone_metric(|registry, prefix| { + FloatJsonValueMetric::new( + registry, + prefix, + "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), + "$.polkadot.usd".into(), + "polkadot_price".into(), + "Polkadot price in USD".into(), + ) + }) .map_err(|e| anyhow::format_err!("{}", e))? - .standalone_metric(FloatJsonValueMetric::new( - "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), - "$.kusama.usd".into(), - "kusama_price".into(), - "Kusama price in USD".into(), - )) + .standalone_metric(|registry, prefix| { + FloatJsonValueMetric::new( + registry, + prefix, + "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), + "$.kusama.usd".into(), + "kusama_price".into(), + "Kusama price in USD".into(), + ) + }) .map_err(|e| anyhow::format_err!("{}", e))? .into_params(), ) diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index e1647d4bcd51c..f3ba8988eea4a 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -19,7 +19,7 @@ use crate::client::Client; use async_trait::async_trait; use codec::Decode; -use relay_utils::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, F64}; +use relay_utils::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; use sp_core::storage::StorageKey; use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; use std::time::Duration; @@ -39,29 +39,20 @@ pub struct FloatStorageValueMetric { impl FloatStorageValueMetric { /// Create new metric. pub fn new( + registry: &Registry, + prefix: Option<&str>, client: Client, storage_key: StorageKey, maybe_default_value: Option, name: String, help: String, - ) -> Self { - FloatStorageValueMetric { + ) -> Result { + Ok(FloatStorageValueMetric { client, storage_key, maybe_default_value, - metric: Gauge::new(name, help).expect( - "only fails if gauge options are customized;\ - we use default options;\ - qed", - ), - } - } -} - -impl Metrics for FloatStorageValueMetric { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.metric.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) + metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + }) } } diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs index e440683f527e6..526fe1e048bfc 100644 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -19,7 +19,7 @@ use crate::client::Client; use crate::error::Error; use async_trait::async_trait; -use relay_utils::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, U64}; +use relay_utils::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, U64}; use sp_core::storage::StorageKey; use sp_runtime::traits::Header as HeaderT; use sp_storage::well_known_keys::CODE; @@ -49,15 +49,17 @@ impl Clone for StorageProofOverheadMetric { impl StorageProofOverheadMetric { /// Create new metric instance with given name and help. - pub fn new(client: Client, name: String, help: String) -> Self { - StorageProofOverheadMetric { + pub fn new( + registry: &Registry, + prefix: Option<&str>, + client: Client, + name: String, + help: String, + ) -> Result { + Ok(StorageProofOverheadMetric { client, - metric: Gauge::new(name, help).expect( - "only fails if gauge options are customized;\ - we use default options;\ - qed", - ), - } + metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + }) } /// Returns approximate storage proof size overhead. @@ -85,13 +87,6 @@ impl StorageProofOverheadMetric { } } -impl Metrics for StorageProofOverheadMetric { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.metric.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } -} - #[async_trait] impl StandaloneMetrics for StorageProofOverheadMetric { fn update_interval(&self) -> Duration { diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 7bb4abb7461b6..b46d34e047a8b 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -78,6 +78,11 @@ impl TransactionProofsRelayStorage for InMemoryStorag } } +/// Return prefix that will be used by default to expose Prometheus metrics of the exchange loop. +pub fn metrics_prefix() -> String { + format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME) +} + /// Run proofs synchronization. pub async fn run( storage: impl TransactionProofsRelayStorage>, @@ -89,12 +94,9 @@ pub async fn run( let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics( - format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME), - metrics_params, - ) - .loop_metric(ExchangeLoopMetrics::default())? - .standalone_metric(GlobalMetrics::default())? + .with_metrics(Some(metrics_prefix::

()), metrics_params) + .loop_metric(|registry, prefix| ExchangeLoopMetrics::new(registry, prefix))? + .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? .run(|source_client, target_client, metrics| { diff --git a/relays/exchange/src/exchange_loop_metrics.rs b/relays/exchange/src/exchange_loop_metrics.rs index 320f662c6dc5c..82d3e649d4319 100644 --- a/relays/exchange/src/exchange_loop_metrics.rs +++ b/relays/exchange/src/exchange_loop_metrics.rs @@ -17,7 +17,9 @@ //! Metrics for currency-exchange relay loop. use crate::exchange::{BlockNumberOf, RelayedBlockTransactions, TransactionProofPipeline}; -use relay_utils::metrics::{register, Counter, CounterVec, GaugeVec, Metrics, Opts, Registry, U64}; +use relay_utils::metrics::{ + metric_name, register, Counter, CounterVec, GaugeVec, Opts, PrometheusError, Registry, U64, +}; /// Exchange transactions relay metrics. #[derive(Clone)] @@ -30,31 +32,38 @@ pub struct ExchangeLoopMetrics { processed_transactions: CounterVec, } -impl Metrics for ExchangeLoopMetrics { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; - register(self.processed_blocks.clone(), registry).map_err(|e| e.to_string())?; - register(self.processed_transactions.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } -} - -impl Default for ExchangeLoopMetrics { - fn default() -> Self { - ExchangeLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new("best_block_numbers", "Best finalized block numbers"), - &["type"], - ) - .expect("metric is static and thus valid; qed"), - processed_blocks: Counter::new("processed_blocks", "Total number of processed blocks") - .expect("metric is static and thus valid; qed"), - processed_transactions: CounterVec::new( - Opts::new("processed_transactions", "Total number of processed transactions"), - &["type"], - ) - .expect("metric is static and thus valid; qed"), - } +impl ExchangeLoopMetrics { + /// Create and register exchange loop metrics. + pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + Ok(ExchangeLoopMetrics { + best_block_numbers: register( + GaugeVec::new( + Opts::new( + metric_name(prefix, "best_block_numbers"), + "Best finalized block numbers", + ), + &["type"], + )?, + registry, + )?, + processed_blocks: register( + Counter::new( + metric_name(prefix, "processed_blocks"), + "Total number of processed blocks", + )?, + registry, + )?, + processed_transactions: register( + CounterVec::new( + Opts::new( + metric_name(prefix, "processed_transactions"), + "Total number of processed transactions", + ), + &["type"], + )?, + registry, + )?, + }) } } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index e0ad8a7c1b6d1..aff32e46de443 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -105,9 +105,9 @@ pub async fn run( ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics(metrics_prefix::

(), metrics_params) - .loop_metric(SyncLoopMetrics::default())? - .standalone_metric(GlobalMetrics::default())? + .with_metrics(Some(metrics_prefix::

()), metrics_params) + .loop_metric(|registry, prefix| SyncLoopMetrics::new(registry, prefix))? + .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? .run(|source_client, target_client, metrics| { diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index d193996d0c301..e4f1b7b04507e 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -110,6 +110,11 @@ pub trait SyncMaintain: Clone + Send + Sync { impl SyncMaintain

for () {} +/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop. +pub fn metrics_prefix() -> String { + format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) +} + /// Run headers synchronization. #[allow(clippy::too_many_arguments)] pub async fn run>( @@ -124,9 +129,9 @@ pub async fn run>( ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics(format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME), metrics_params) - .loop_metric(SyncLoopMetrics::default())? - .standalone_metric(GlobalMetrics::default())? + .with_metrics(Some(metrics_prefix::

()), metrics_params) + .loop_metric(|registry, prefix| SyncLoopMetrics::new(registry, prefix))? + .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? .run(|source_client, target_client, metrics| { diff --git a/relays/headers/src/sync_loop_metrics.rs b/relays/headers/src/sync_loop_metrics.rs index 616a04360d6b5..37dae11340428 100644 --- a/relays/headers/src/sync_loop_metrics.rs +++ b/relays/headers/src/sync_loop_metrics.rs @@ -20,7 +20,7 @@ use crate::sync::HeadersSync; use crate::sync_types::{HeaderStatus, HeadersSyncPipeline}; use num_traits::Zero; -use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; +use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; /// Headers sync metrics. #[derive(Clone)] @@ -31,28 +31,31 @@ pub struct SyncLoopMetrics { blocks_in_state: GaugeVec, } -impl Metrics for SyncLoopMetrics { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; - register(self.blocks_in_state.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } -} - -impl Default for SyncLoopMetrics { - fn default() -> Self { - SyncLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new("best_block_numbers", "Best block numbers on source and target nodes"), - &["node"], - ) - .expect("metric is static and thus valid; qed"), - blocks_in_state: GaugeVec::new( - Opts::new("blocks_in_state", "Number of blocks in given state"), - &["state"], - ) - .expect("metric is static and thus valid; qed"), - } +impl SyncLoopMetrics { + /// Create and register headers loop metrics. + pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + Ok(SyncLoopMetrics { + best_block_numbers: register( + GaugeVec::new( + Opts::new( + metric_name(prefix, "best_block_numbers"), + "Best block numbers on source and target nodes", + ), + &["node"], + )?, + registry, + )?, + blocks_in_state: register( + GaugeVec::new( + Opts::new( + metric_name(prefix, "blocks_in_state"), + "Number of blocks in given state", + ), + &["state"], + )?, + registry, + )?, + }) } } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index daa74b50735b3..41eee606d82be 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -140,8 +140,8 @@ pub trait SourceClient: RelayClient { proof: P::MessagesReceivingProof, ) -> Result<(), Self::Error>; - /// Activate (or deactivate) headers relay that relays target headers to source node. - async fn activate_target_to_source_headers_relay(&self, activate: bool); + /// We need given finalized target header on source to continue synchronization. + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

); } /// Target client trait. @@ -181,8 +181,8 @@ pub trait TargetClient: RelayClient { proof: P::MessagesProof, ) -> Result, Self::Error>; - /// Activate (or deactivate) headers relay that relays source headers to target node. - async fn activate_source_to_target_headers_relay(&self, activate: bool); + /// We need given finalized source header on target to continue synchronization. + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

); } /// State of the client. @@ -232,9 +232,9 @@ pub async fn run( let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) - .with_metrics(metrics_prefix::

(¶ms.lane), metrics_params) - .loop_metric(MessageLaneLoopMetrics::default())? - .standalone_metric(GlobalMetrics::default())? + .with_metrics(Some(metrics_prefix::

(¶ms.lane)), metrics_params) + .loop_metric(|registry, prefix| MessageLaneLoopMetrics::new(registry, prefix))? + .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? .run(|source_client, target_client, metrics| { @@ -475,8 +475,10 @@ pub(crate) mod tests { target_latest_received_nonce: MessageNonce, target_latest_confirmed_received_nonce: MessageNonce, submitted_messages_proofs: Vec, - is_target_to_source_headers_relay_activated: bool, - is_source_to_target_headers_relay_activated: bool, + target_to_source_header_required: Option, + target_to_source_header_requirements: Vec, + source_to_target_header_required: Option, + source_to_target_header_requirements: Vec, } #[derive(Clone)] @@ -582,9 +584,10 @@ pub(crate) mod tests { Ok(()) } - async fn activate_target_to_source_headers_relay(&self, activate: bool) { + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { let mut data = self.data.lock(); - data.is_target_to_source_headers_relay_activated = activate; + data.target_to_source_header_required = Some(id); + data.target_to_source_header_requirements.push(id); (self.tick)(&mut *data); } } @@ -686,9 +689,10 @@ pub(crate) mod tests { Ok(nonces) } - async fn activate_source_to_target_headers_relay(&self, activate: bool) { + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { let mut data = self.data.lock(); - data.is_source_to_target_headers_relay_activated = activate; + data.source_to_target_header_required = Some(id); + data.source_to_target_header_requirements.push(id); (self.tick)(&mut *data); } } @@ -806,16 +810,16 @@ pub(crate) mod tests { }, Arc::new(|data: &mut TestClientData| { // headers relay must only be started when we need new target headers at source node - if data.is_target_to_source_headers_relay_activated { + if data.target_to_source_header_required.is_some() { assert!(data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_self.0); - data.is_target_to_source_headers_relay_activated = false; + data.target_to_source_header_required = None; } }), Arc::new(move |data: &mut TestClientData| { // headers relay must only be started when we need new source headers at target node - if data.is_target_to_source_headers_relay_activated { + if data.source_to_target_header_required.is_some() { assert!(data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_self.0); - data.is_target_to_source_headers_relay_activated = false; + data.source_to_target_header_required = None; } // syncing source headers -> target chain (all at once) if data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_finalized_self.0 { @@ -837,7 +841,7 @@ pub(crate) mod tests { HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.0 + 1); data.source_state.best_finalized_self = data.source_state.best_self; } - // if source has received all messages receiving confirmations => increase source block so that confirmations may be sent + // if source has received all messages receiving confirmations => stop if data.source_latest_confirmed_received_nonce == 10 { exit_sender.unbounded_send(()).unwrap(); } @@ -853,5 +857,9 @@ pub(crate) mod tests { assert_eq!(result.submitted_messages_proofs[1].0, 5..=8); assert_eq!(result.submitted_messages_proofs[2].0, 9..=10); assert!(!result.submitted_messages_receiving_proofs.is_empty()); + + // check that we have at least once required new source->target or target->source headers + assert!(!result.target_to_source_header_requirements.is_empty()); + assert!(!result.source_to_target_header_requirements.is_empty()); } } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 3b1644b728923..225c59f23ca33 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -166,8 +166,8 @@ where type Error = C::Error; type TargetNoncesData = DeliveryRaceTargetNoncesData; - async fn require_more_source_headers(&self, activate: bool) { - self.client.activate_source_to_target_headers_relay(activate).await + async fn require_source_header(&self, id: SourceHeaderIdOf

) { + self.client.require_source_header_on_target(id).await } async fn nonces( @@ -291,6 +291,10 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M self.strategy.is_empty() } + fn required_source_header_at_target(&self, current_best: &SourceHeaderIdOf

) -> Option> { + self.strategy.required_source_header_at_target(current_best) + } + fn best_at_source(&self) -> Option { self.strategy.best_at_source() } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index f3bf2626ef4b8..41f5ede1033a5 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -123,8 +123,9 @@ pub trait TargetClient { /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; - /// Ask headers relay to relay more headers from race source to race target. - async fn require_more_source_headers(&self, activate: bool); + /// Ask headers relay to relay finalized headers up to (and including) given header + /// from race source to race target. + async fn require_source_header(&self, id: P::SourceHeaderId); /// Return nonces that are known to the target client. async fn nonces( @@ -152,6 +153,8 @@ pub trait RaceStrategy: Debug { /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; + /// Return id of source header that is required to be on target to continue synchronization. + fn required_source_header_at_target(&self, current_best: &SourceHeaderId) -> Option; /// Return best nonce at source node. /// /// `Some` is returned only if we are sure that the value is greater or equal @@ -219,7 +222,6 @@ pub async fn run, TC: TargetClient

>( TargetNoncesData = TC::TargetNoncesData, >, ) -> Result<(), FailedClient> { - let mut is_strategy_empty = true; let mut progress_context = Instant::now(); let mut race_state = RaceState::default(); let mut stall_countdown = Instant::now(); @@ -307,6 +309,15 @@ pub async fn run, TC: TargetClient

>( async_std::task::sleep, || format!("Error retrieving nonces from {}", P::source_name()), ).fail_if_connection_error(FailedClient::Source)?; + + // ask for more headers if we have nonces to deliver and required headers are missing + let required_source_header_id = race_state + .best_finalized_source_header_id_at_best_target + .as_ref() + .and_then(|best|strategy.required_source_header_at_target(best)); + if let Some(required_source_header_id) = required_source_header_id { + race_target.require_source_header(required_source_header_id).await; + } }, nonces = target_best_nonces => { target_best_nonces_required = false; @@ -408,13 +419,6 @@ pub async fn run, TC: TargetClient

>( progress_context = print_race_progress::(progress_context, &strategy); - // ask for more headers if we have nonces to deliver - let prev_is_strategy_empty = is_strategy_empty; - is_strategy_empty = strategy.is_empty(); - if is_strategy_empty != prev_is_strategy_empty { - race_target.require_more_source_headers(!is_strategy_empty).await; - } - if stall_countdown.elapsed() > stall_timeout { log::warn!( target: "bridge", diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index 6538061965ae9..4381b63591f71 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -159,8 +159,8 @@ where type Error = C::Error; type TargetNoncesData = (); - async fn require_more_source_headers(&self, activate: bool) { - self.client.activate_target_to_source_headers_relay(activate).await + async fn require_source_header(&self, id: TargetHeaderIdOf

) { + self.client.require_target_header_on_source(id).await } async fn nonces( diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 2d8e90d433e62..7088f8d74b557 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -162,6 +162,15 @@ where self.source_queue.is_empty() } + fn required_source_header_at_target( + &self, + current_best: &HeaderId, + ) -> Option> { + self.source_queue + .back() + .and_then(|(h, _)| if h.0 > current_best.0 { Some(h.clone()) } else { None }) + } + fn best_at_source(&self) -> Option { let best_in_queue = self.source_queue.back().map(|(_, range)| range.end()); match (best_in_queue, self.best_target_nonce) { diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index a9a0ac4081f1f..51a4118be8582 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -20,7 +20,7 @@ use crate::message_lane::MessageLane; use crate::message_lane_loop::{SourceClientState, TargetClientState}; use bp_messages::MessageNonce; -use relay_utils::metrics::{register, GaugeVec, Metrics, Opts, Registry, U64}; +use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; /// Message lane relay metrics. /// @@ -34,25 +34,28 @@ pub struct MessageLaneLoopMetrics { lane_state_nonces: GaugeVec, } -impl Metrics for MessageLaneLoopMetrics { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.best_block_numbers.clone(), registry).map_err(|e| e.to_string())?; - register(self.lane_state_nonces.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } -} - -impl Default for MessageLaneLoopMetrics { - fn default() -> Self { - MessageLaneLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new("best_block_numbers", "Best finalized block numbers"), - &["type"], - ) - .expect("metric is static and thus valid; qed"), - lane_state_nonces: GaugeVec::new(Opts::new("lane_state_nonces", "Nonces of the lane state"), &["type"]) - .expect("metric is static and thus valid; qed"), - } +impl MessageLaneLoopMetrics { + /// Create and register messages loop metrics. + pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + Ok(MessageLaneLoopMetrics { + best_block_numbers: register( + GaugeVec::new( + Opts::new( + metric_name(prefix, "best_block_numbers"), + "Best finalized block numbers", + ), + &["type"], + )?, + registry, + )?, + lane_state_nonces: register( + GaugeVec::new( + Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), + &["type"], + )?, + registry, + )?, + }) } } diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 789ff8a108502..c0eaeae337ee1 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -18,7 +18,7 @@ pub use float_json_value::FloatJsonValueMetric; pub use global::GlobalMetrics; pub use substrate_prometheus_endpoint::{ prometheus::core::{Atomic, Collector}, - register, Counter, CounterVec, Gauge, GaugeVec, Opts, Registry, F64, U64, + register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, U64, }; use async_trait::async_trait; @@ -43,13 +43,14 @@ pub struct MetricsParams { pub address: Option, /// Metrics registry. May be `Some(_)` if several components share the same endpoint. pub registry: Option, + /// Prefix that must be used in metric names. + pub metrics_prefix: Option, } /// Metrics API. -pub trait Metrics: Clone + Send + Sync + 'static { - /// Register metrics in the registry. - fn register(&self, registry: &Registry) -> Result<(), String>; -} +pub trait Metrics: Clone + Send + Sync + 'static {} + +impl Metrics for T {} /// Standalone metrics API. /// @@ -90,8 +91,21 @@ impl MetricsParams { MetricsParams { address: None, registry: None, + metrics_prefix: None, } } + + /// Do not expose metrics. + pub fn disable(mut self) -> Self { + self.address = None; + self + } + + /// Set prefix to use in metric names. + pub fn metrics_prefix(mut self, prefix: String) -> Self { + self.metrics_prefix = Some(prefix); + self + } } impl From> for MetricsParams { @@ -99,10 +113,20 @@ impl From> for MetricsParams { MetricsParams { address, registry: None, + metrics_prefix: None, } } } +/// Returns metric name optionally prefixed with given prefix. +pub fn metric_name(prefix: Option<&str>, name: &str) -> String { + if let Some(prefix) = prefix { + format!("{}_{}", prefix, name) + } else { + name.into() + } +} + /// Set value of gauge metric. /// /// If value is `Ok(None)` or `Err(_)`, metric would have default value. diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index 902b3e819509d..d61f9cac7c224 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{register, Gauge, Metrics, Registry, StandaloneMetrics, F64}; +use crate::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; use async_trait::async_trait; use std::time::Duration; @@ -32,16 +32,19 @@ pub struct FloatJsonValueMetric { impl FloatJsonValueMetric { /// Create new metric instance with given name and help. - pub fn new(url: String, json_path: String, name: String, help: String) -> Self { - FloatJsonValueMetric { + pub fn new( + registry: &Registry, + prefix: Option<&str>, + url: String, + json_path: String, + name: String, + help: String, + ) -> Result { + Ok(FloatJsonValueMetric { url, json_path, - metric: Gauge::new(name, help).expect( - "only fails if gauge options are customized;\ - we use default options;\ - qed", - ), - } + metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + }) } /// Read value from HTTP service. @@ -69,13 +72,6 @@ impl FloatJsonValueMetric { } } -impl Metrics for FloatJsonValueMetric { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.metric.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) - } -} - #[async_trait] impl StandaloneMetrics for FloatJsonValueMetric { fn update_interval(&self) -> Duration { diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs index 98c7d9a570c0e..d212480510448 100644 --- a/relays/utils/src/metrics/global.rs +++ b/relays/utils/src/metrics/global.rs @@ -16,7 +16,9 @@ //! Global system-wide Prometheus metrics exposed by relays. -use crate::metrics::{register, Gauge, GaugeVec, Metrics, Opts, Registry, StandaloneMetrics, F64, U64}; +use crate::metrics::{ + metric_name, register, Gauge, GaugeVec, Opts, PrometheusError, Registry, StandaloneMetrics, F64, U64, +}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; @@ -35,12 +37,30 @@ pub struct GlobalMetrics { process_memory_usage_bytes: Gauge, } -impl Metrics for GlobalMetrics { - fn register(&self, registry: &Registry) -> Result<(), String> { - register(self.system_average_load.clone(), registry).map_err(|e| e.to_string())?; - register(self.process_cpu_usage_percentage.clone(), registry).map_err(|e| e.to_string())?; - register(self.process_memory_usage_bytes.clone(), registry).map_err(|e| e.to_string())?; - Ok(()) +impl GlobalMetrics { + /// Create and register global metrics. + pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + Ok(GlobalMetrics { + system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), + system_average_load: register( + GaugeVec::new( + Opts::new(metric_name(prefix, "system_average_load"), "System load average"), + &["over"], + )?, + registry, + )?, + process_cpu_usage_percentage: register( + Gauge::new(metric_name(prefix, "process_cpu_usage_percentage"), "Process CPU usage")?, + registry, + )?, + process_memory_usage_bytes: register( + Gauge::new( + metric_name(prefix, "process_memory_usage_bytes"), + "Process memory (resident set size) usage", + )?, + registry, + )?, + }) } } @@ -89,20 +109,3 @@ impl StandaloneMetrics for GlobalMetrics { UPDATE_INTERVAL } } - -impl Default for GlobalMetrics { - fn default() -> Self { - GlobalMetrics { - system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), - system_average_load: GaugeVec::new(Opts::new("system_average_load", "System load average"), &["over"]) - .expect("metric is static and thus valid; qed"), - process_cpu_usage_percentage: Gauge::new("process_cpu_usage_percentage", "Process CPU usage") - .expect("metric is static and thus valid; qed"), - process_memory_usage_bytes: Gauge::new( - "process_memory_usage_bytes", - "Process memory (resident set size) usage", - ) - .expect("metric is static and thus valid; qed"), - } - } -} diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 1a8d63e1dbe76..8790b0913e176 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{Metrics, MetricsAddress, MetricsParams, StandaloneMetrics}; +use crate::metrics::{Metrics, MetricsAddress, MetricsParams, PrometheusError, StandaloneMetrics}; use crate::{FailedClient, MaybeConnectionError}; use async_trait::async_trait; @@ -45,9 +45,7 @@ pub fn relay_loop(source_client: SC, target_client: TC) -> Loop) -> LoopMetrics<(), (), ()> { - assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); - +pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetrics<(), (), ()> { LoopMetrics { relay_loop: Loop { reconnect_delay: RECONNECT_DELAY, @@ -55,9 +53,9 @@ pub fn relay_metrics(prefix: String, address: Option) -> LoopMet target_client: (), loop_metric: None, }, - address, - registry: Registry::new_custom(Some(prefix), None) - .expect("only fails if prefix is empty; prefix is not empty; qed"), + address: params.address, + registry: params.registry.unwrap_or_else(|| create_metrics_registry(prefix)), + metrics_prefix: params.metrics_prefix, loop_metric: None, } } @@ -75,6 +73,7 @@ pub struct LoopMetrics { relay_loop: Loop, address: Option, registry: Registry, + metrics_prefix: Option, loop_metric: Option, } @@ -86,11 +85,7 @@ impl Loop { } /// Start building loop metrics using given prefix. - /// - /// Panics if `prefix` is empty. - pub fn with_metrics(self, prefix: String, params: MetricsParams) -> LoopMetrics { - assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); - + pub fn with_metrics(self, prefix: Option, params: MetricsParams) -> LoopMetrics { LoopMetrics { relay_loop: Loop { reconnect_delay: self.reconnect_delay, @@ -99,11 +94,8 @@ impl Loop { loop_metric: None, }, address: params.address, - registry: match params.registry { - Some(registry) => registry, - None => Registry::new_custom(Some(prefix), None) - .expect("only fails if prefix is empty; prefix is not empty; qed"), - }, + registry: params.registry.unwrap_or_else(|| create_metrics_registry(prefix)), + metrics_prefix: params.metrics_prefix, loop_metric: None, } } @@ -177,21 +169,34 @@ impl LoopMetrics { /// Add relay loop metrics. /// /// Loop metrics will be passed to the loop callback. - pub fn loop_metric(self, loop_metric: NewLM) -> Result, String> { - loop_metric.register(&self.registry)?; + pub fn loop_metric( + self, + create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, + ) -> Result, String> { + let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref()).map_err(|e| e.to_string())?; Ok(LoopMetrics { relay_loop: self.relay_loop, address: self.address, registry: self.registry, + metrics_prefix: self.metrics_prefix, loop_metric: Some(loop_metric), }) } /// Add standalone metrics. - pub fn standalone_metric(self, standalone_metrics: M) -> Result { - standalone_metrics.register(&self.registry)?; - standalone_metrics.spawn(); + pub fn standalone_metric( + self, + create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, + ) -> Result { + // since standalone metrics are updating themselves, we may just ignore the fact that the same + // standalone metric is exposed by several loops && only spawn single metric + match create_metric(&self.registry, self.metrics_prefix.as_deref()) { + Ok(standalone_metrics) => standalone_metrics.spawn(), + Err(PrometheusError::AlreadyReg) => (), + Err(e) => return Err(e.to_string()), + } + Ok(self) } @@ -200,6 +205,7 @@ impl LoopMetrics { MetricsParams { address: self.address, registry: Some(self.registry), + metrics_prefix: self.metrics_prefix, } } @@ -237,3 +243,14 @@ impl LoopMetrics { }) } } + +/// Create new registry with global metrics. +fn create_metrics_registry(prefix: Option) -> Registry { + match prefix { + Some(prefix) => { + assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); + Registry::new_custom(Some(prefix), None).expect("only fails if prefix is empty; prefix is not empty; qed") + } + None => Registry::new(), + } +} From 8ec192d0550704b0ba28ad059be50bbcc0400985 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 15 Apr 2021 05:56:45 -0400 Subject: [PATCH 0426/1210] Stop recursing when creating test headers (#906) --- primitives/test-utils/src/lib.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 39652fc83aebe..0fcc263763c31 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -212,16 +212,19 @@ fn signed_precommit( /// /// The correct parent hash will be used if given a non-zero header. pub fn test_header(number: H::Number) -> H { - let mut header = H::new( - number, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ); + let default = |num| { + H::new( + num, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ) + }; + let mut header = default(number); if number != Zero::zero() { - let parent_hash = test_header::(number - One::one()).hash(); + let parent_hash = default(number - One::one()).hash(); header.set_parent_hash(parent_hash); } From f217c9f6a6bc857858bbc09c84062f6295ea3e1c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 15 Apr 2021 12:59:08 +0300 Subject: [PATCH 0427/1210] Use complex headers+messages relay in test deployments (#905) * use complex relay in deployments * enable lane 00000001 * add alerts for lane 00000001 * revert local substrate relay * updated doc * review --- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 30f373fa0ad0c..a800117dc5518 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -104,7 +104,7 @@ impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == LaneId::default() + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index e8785c464a237..8ee2094660c10 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -104,7 +104,7 @@ impl messages::ThisChainWithMessages for Rialto { type Call = crate::Call; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == LaneId::default() + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { From fe2d437a904db39f49201ea06d3e2c3bd678ea80 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 15 Apr 2021 11:00:35 -0400 Subject: [PATCH 0428/1210] Westend<>Rococo Headers Relay (#875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add modules for Rococo<>Westend header sync * Use mock Westend and Rococo finaltiy tx calls * Add Westend<>Rococo variants to `init_bridge` * Add Westend<>Rococo variants to `relay_headers` * Simplify the Rococo and Westend signing params * Add `submit_finality_proof` mock Call variant * Add note to more closely match `initialize` Call variant * Accidentally committed `cargo-expand`ed code 🤦 * Add `initialize` Call variant to Rococo mock * Fix call enums. * Add explainatory comment. * clippy. * Add issue number. * De-duplicate metrics customisation. * Add comments to Rococo/Westend runtimes. * Add scale-encoding compatibility test. * Fix tests. * Clippy. Co-authored-by: Tomasz Drwięga --- modules/dispatch/src/lib.rs | 2 + modules/grandpa/src/lib.rs | 21 +-- primitives/chain-rococo/Cargo.toml | 2 + primitives/chain-rococo/src/lib.rs | 27 +++- primitives/chain-westend/Cargo.toml | 2 + primitives/chain-westend/src/lib.rs | 27 +++- primitives/header-chain/src/lib.rs | 16 ++ relays/bin-substrate/Cargo.toml | 3 +- relays/bin-substrate/src/cli/init_bridge.rs | 28 +++- relays/bin-substrate/src/cli/mod.rs | 1 + relays/bin-substrate/src/cli/relay_headers.rs | 16 ++ .../bin-substrate/src/headers_initialize.rs | 2 +- relays/bin-substrate/src/rialto_millau/mod.rs | 142 ++++++++++++++++++ .../rococo_headers_to_westend.rs | 60 ++++++++ .../westend_headers_to_millau.rs | 31 +--- .../westend_headers_to_rococo.rs | 60 ++++++++ relays/client-rococo/src/lib.rs | 29 +--- relays/client-westend/src/lib.rs | 29 +--- 18 files changed, 388 insertions(+), 110 deletions(-) create mode 100644 relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs create mode 100644 relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 76706d4d1e162..416d080b0c17a 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -45,6 +45,7 @@ use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; /// Spec version type. pub type SpecVersion = u32; +// TODO [#895] move to primitives /// Origin of a Call when it is dispatched on the target chain. /// /// The source chain can (and should) verify that the message can be dispatched on the target chain @@ -89,6 +90,7 @@ pub enum CallOrigin { diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 98f47dd6f1c61..9fb7372b0204e 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -39,16 +39,13 @@ use crate::weights::WeightInfo; use bp_header_chain::justification::GrandpaJustification; +use bp_header_chain::InitializationData; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; -use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::ensure; use frame_system::{ensure_signed, RawOrigin}; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; -use sp_runtime::RuntimeDebug; #[cfg(test)] mod mock; @@ -511,22 +508,6 @@ impl, I: 'static> Pallet { } } -/// Data required for initializing the bridge pallet. -/// -/// The bridge needs to know where to start its sync from, and this provides that initial context. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct InitializationData { - /// The header from which we should start syncing. - pub header: H, - /// The initial authorities of the pallet. - pub authority_list: sp_finality_grandpa::AuthorityList, - /// The ID of the initial authority set. - pub set_id: sp_finality_grandpa::SetId, - /// Should the pallet block transaction immediately after initialization. - pub is_halted: bool, -} - pub(crate) fn find_scheduled_change(header: &H) -> Option> { use sp_runtime::generic::OpaqueDigestItemId; diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index acdbfc6c51e05..b97e8d9d1ab10 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -23,6 +24,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 38dd92561b2fb..cc3eb47b1b763 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -41,9 +42,33 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 6, }; +/// Rococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - MockPallet, + /// Westend bridge pallet. + #[codec(index = 40)] + BridgeGrandpaWestend(BridgeGrandpaWestendCall), +} + +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaWestendCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), } impl sp_runtime::traits::Dispatchable for Call { diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index c96e8703d8087..d5fda1ccef05a 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -23,6 +24,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 3b52534afa7ca..dbbfabd5dcf2f 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -42,9 +43,33 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 5, }; +/// Westend Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Westend chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Westend +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/westend/src/lib.rs #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - MockModule, + /// Rococo bridge pallet. + #[codec(index = 40)] + BridgeGrandpaRococo(BridgeGrandpaRococoCall), +} + +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaRococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), } impl sp_runtime::traits::Dispatchable for Call { diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index d33a6d36eb1b8..adac6eb268802 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -55,6 +55,22 @@ impl AuthoritySet { } } +/// Data required for initializing the bridge pallet. +/// +/// The bridge needs to know where to start its sync from, and this provides that initial context. +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct InitializationData { + /// The header from which we should start syncing. + pub header: H, + /// The initial authorities of the pallet. + pub authority_list: AuthorityList, + /// The ID of the initial authority set. + pub set_id: SetId, + /// Should the pallet block transaction immediately after initialization. + pub is_halted: bool, +} + /// base trait for verifying transaction inclusion proofs. pub trait InclusionProofVerifier { /// Transaction type. diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 1a281a6d5861a..d203201e60a44 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -26,6 +26,7 @@ bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } +bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } @@ -35,12 +36,12 @@ headers-relay = { path = "../headers" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-dispatch = { path = "../../modules/dispatch" } -pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } relay-rialto-client = { path = "../client-rialto" } +relay-rococo-client = { path = "../client-rococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index a9923e71e9216..cdd8ec369161d 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -15,9 +15,9 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use bp_header_chain::InitializationData; use bp_runtime::Chain as ChainBase; use codec::Encode; -use pallet_bridge_grandpa::InitializationData; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; use structopt::{clap::arg_enum, StructOpt}; @@ -44,6 +44,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + WestendToRococo, + RococoToWestend, } } @@ -98,6 +100,30 @@ macro_rules! select_bridge { .into() } + $generic + } + InitBridgeName::WestendToRococo => { + type Source = relay_westend_client::Westend; + type Target = relay_rococo_client::Rococo; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaWestendCall::initialize(init_data)) + } + + $generic + } + InitBridgeName::RococoToWestend => { + type Source = relay_rococo_client::Rococo; + type Target = relay_westend_client::Westend; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_westend::Call::BridgeGrandpaRococo(bp_westend::BridgeGrandpaRococoCall::initialize(init_data)) + } + $generic } } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 8af3301231d85..505ef11ee2a51 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -373,6 +373,7 @@ macro_rules! declare_chain_options { /// Parse signing params into chain-specific KeyPair. pub fn to_keypair(&self) -> anyhow::Result { use sp_core::crypto::Pair; + Chain::KeyPair::from_string( &self.[<$chain_prefix _signer>], self.[<$chain_prefix _signer_password>].as_deref() diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index a60bbe344d6eb..8137f8a240da5 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -42,6 +42,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + WestendToRococo, + RococoToWestend, } } @@ -67,6 +69,20 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type Finality = crate::rialto_millau::westend_headers_to_millau::WestendFinalityToMillau; + $generic + } + RelayHeadersBridge::WestendToRococo => { + type Source = relay_westend_client::Westend; + type Target = relay_rococo_client::Rococo; + type Finality = crate::rialto_millau::westend_headers_to_rococo::WestendFinalityToRococo; + + $generic + } + RelayHeadersBridge::RococoToWestend => { + type Source = relay_rococo_client::Rococo; + type Target = relay_westend_client::Westend; + type Finality = crate::rialto_millau::rococo_headers_to_westend::RococoFinalityToWestend; + $generic } } diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index 83db39bf7bb6a..c2eab1bd3534e 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -21,6 +21,7 @@ //! and authorities set from source to target chain. The headers sync starts //! with this header. +use bp_header_chain::InitializationData; use bp_header_chain::{ find_grandpa_authorities_scheduled_change, justification::{verify_justification, GrandpaJustification}, @@ -28,7 +29,6 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use pallet_bridge_grandpa::InitializationData; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/rialto_millau/mod.rs index af17f62a05fe7..cf86f781c0afb 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/rialto_millau/mod.rs @@ -20,7 +20,9 @@ pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; +pub mod rococo_headers_to_westend; pub mod westend_headers_to_millau; +pub mod westend_headers_to_rococo; use crate::cli::{ bridge, @@ -32,9 +34,44 @@ use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::Millau; use relay_rialto_client::Rialto; +use relay_rococo_client::Rococo; +use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; use relay_westend_client::Westend; use sp_version::RuntimeVersion; +pub(crate) fn add_polkadot_kusama_price_metrics( + params: MetricsParams, +) -> anyhow::Result { + Ok( + relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) + // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama + // relays, but we want to test metrics/dashboards in advance + .standalone_metric(|registry, prefix| { + FloatJsonValueMetric::new( + registry, + prefix, + "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), + "$.polkadot.usd".into(), + "polkadot_price".into(), + "Polkadot price in USD".into(), + ) + }) + .map_err(|e| anyhow::format_err!("{}", e))? + .standalone_metric(|registry, prefix| { + FloatJsonValueMetric::new( + registry, + prefix, + "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), + "$.kusama.usd".into(), + "kusama_price".into(), + "Kusama price in USD".into(), + ) + }) + .map_err(|e| anyhow::format_err!("{}", e))? + .into_params(), + ) +} + impl CliEncodeCall for Millau { fn max_extrinsic_size() -> u32 { bp_millau::max_extrinsic_size() @@ -197,6 +234,25 @@ impl CliChain for Westend { } } +impl CliChain for Rococo { + const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + 0 + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Rococo is not yet supported.".into()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -373,3 +429,89 @@ mod tests { ); } } + +#[cfg(test)] +mod rococo_tests { + use bp_header_chain::justification::GrandpaJustification; + use codec::Encode; + + #[test] + fn scale_compatibility_of_bridges_call() { + // given + let header = sp_runtime::generic::Header { + parent_hash: Default::default(), + number: Default::default(), + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: sp_runtime::generic::Digest { logs: vec![] }, + }; + let justification = GrandpaJustification { + round: 0, + commit: finality_grandpa::Commit { + target_hash: Default::default(), + target_number: Default::default(), + precommits: vec![], + }, + votes_ancestries: vec![], + }; + let actual = bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof(header.clone(), justification.clone()); + let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( + header, + justification, + ); + + // when + let actual_encoded = actual.encode(); + let expected_encoded = expected.encode(); + + // then + assert_eq!( + actual_encoded, expected_encoded, + "Encoding difference. Raw: {:?} vs {:?}", + actual, expected + ); + } +} + +#[cfg(test)] +mod westend_tests { + use bp_header_chain::justification::GrandpaJustification; + use codec::Encode; + + #[test] + fn scale_compatibility_of_bridges_call() { + // given + let header = sp_runtime::generic::Header { + parent_hash: Default::default(), + number: Default::default(), + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: sp_runtime::generic::Digest { logs: vec![] }, + }; + let justification = GrandpaJustification { + round: 0, + commit: finality_grandpa::Commit { + target_hash: Default::default(), + target_number: Default::default(), + precommits: vec![], + }, + votes_ancestries: vec![], + }; + let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof(header.clone(), justification.clone()); + let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( + header, + justification, + ); + + // when + let actual_encoded = actual.encode(); + let expected_encoded = expected.encode(); + + // then + assert_eq!( + actual_encoded, expected_encoded, + "Encoding difference. Raw: {:?} vs {:?}", + actual, expected + ); + } +} diff --git a/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs b/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs new file mode 100644 index 0000000000000..82905b4d89b73 --- /dev/null +++ b/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Rococo-to-Westend headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_westend_client::{SigningParams as WestendSigningParams, Westend}; +use sp_core::{Bytes, Pair}; + +/// Rococo-to-Westend finality sync pipeline. +pub(crate) type RococoFinalityToWestend = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for RococoFinalityToWestend { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + + type TargetChain = Westend; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_westend::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: RococoSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_westend::Call::BridgeGrandpaRococo(bp_westend::BridgeGrandpaRococoCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Westend::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs index f8f023da19b09..798cc7c611cf0 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs @@ -22,7 +22,7 @@ use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_substrate_client::{Chain, TransactionSignScheme}; -use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; +use relay_utils::metrics::MetricsParams; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use sp_core::{Bytes, Pair}; @@ -35,34 +35,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - Ok( - relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) - // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama - // relays, but we want to test metrics/dashboards in advance - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=usd".into(), - "$.polkadot.usd".into(), - "polkadot_price".into(), - "Polkadot price in USD".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=usd".into(), - "$.kusama.usd".into(), - "kusama_price".into(), - "Kusama price in USD".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .into_params(), - ) + crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) } fn transactions_author(&self) -> bp_millau::AccountId { diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs b/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs new file mode 100644 index 0000000000000..b57cc75781f44 --- /dev/null +++ b/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Westend-to-Rococo headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; +use sp_core::{Bytes, Pair}; + +/// Westend-to-Rococo finality sync pipeline. +pub(crate) type WestendFinalityToRococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for WestendFinalityToRococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; + + type TargetChain = Rococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_rococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: WestendSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index ccf7a8916348f..1e2dd6569b48f 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -89,31 +89,4 @@ impl TransactionSignScheme for Rococo { } /// Rococo signing params. -#[derive(Clone)] -pub struct SigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl SigningParams { - /// Create signing params from SURI and password. - pub fn from_suri(suri: &str, password: Option<&str>) -> Result { - Ok(SigningParams { - signer: sp_core::sr25519::Pair::from_string(suri, password)?, - }) - } -} - -impl std::fmt::Debug for SigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} - -impl Default for SigningParams { - fn default() -> Self { - SigningParams { - signer: sp_keyring::AccountKeyring::Alice.pair(), - } - } -} +pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 0a6569512a259..5ca4552bc2c2f 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -89,31 +89,4 @@ impl TransactionSignScheme for Westend { } /// Westend signing params. -#[derive(Clone)] -pub struct SigningParams { - /// Substrate transactions signer. - pub signer: sp_core::sr25519::Pair, -} - -impl SigningParams { - /// Create signing params from SURI and password. - pub fn from_suri(suri: &str, password: Option<&str>) -> Result { - Ok(SigningParams { - signer: sp_core::sr25519::Pair::from_string(suri, password)?, - }) - } -} - -impl std::fmt::Debug for SigningParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "{}", self.signer.public()) - } -} - -impl Default for SigningParams { - fn default() -> Self { - SigningParams { - signer: sp_keyring::AccountKeyring::Alice.pair(), - } - } -} +pub type SigningParams = sp_core::sr25519::Pair; From c20afc4ebd3f7e0b3e45f34cb9b23072e823ec5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 15 Apr 2021 18:07:11 +0200 Subject: [PATCH 0429/1210] CLI: naming clean-up. (#897) * Small naming clean up. * Small naming clean up. * Add Rococo module to CLI Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Hernando Castano --- relays/bin-substrate/src/chains/millau.rs | 101 +++++++++ .../millau_headers_to_rialto.rs | 0 .../millau_messages_to_rialto.rs | 0 .../src/{rialto_millau => chains}/mod.rs | 206 +----------------- relays/bin-substrate/src/chains/rialto.rs | 98 +++++++++ .../rialto_headers_to_millau.rs | 0 .../rialto_messages_to_millau.rs | 0 relays/bin-substrate/src/chains/rococo.rs | 39 ++++ .../rococo_headers_to_westend.rs | 2 +- relays/bin-substrate/src/chains/westend.rs | 41 ++++ .../westend_headers_to_millau.rs | 2 +- .../westend_headers_to_rococo.rs | 2 +- relays/bin-substrate/src/cli/bridge.rs | 4 +- relays/bin-substrate/src/cli/relay_headers.rs | 10 +- .../src/cli/relay_headers_and_messages.rs | 12 +- relays/bin-substrate/src/main.rs | 3 +- 16 files changed, 306 insertions(+), 214 deletions(-) create mode 100644 relays/bin-substrate/src/chains/millau.rs rename relays/bin-substrate/src/{rialto_millau => chains}/millau_headers_to_rialto.rs (100%) rename relays/bin-substrate/src/{rialto_millau => chains}/millau_messages_to_rialto.rs (100%) rename relays/bin-substrate/src/{rialto_millau => chains}/mod.rs (63%) create mode 100644 relays/bin-substrate/src/chains/rialto.rs rename relays/bin-substrate/src/{rialto_millau => chains}/rialto_headers_to_millau.rs (100%) rename relays/bin-substrate/src/{rialto_millau => chains}/rialto_messages_to_millau.rs (100%) create mode 100644 relays/bin-substrate/src/chains/rococo.rs rename relays/bin-substrate/src/{rialto_millau => chains}/rococo_headers_to_westend.rs (96%) create mode 100644 relays/bin-substrate/src/chains/westend.rs rename relays/bin-substrate/src/{rialto_millau => chains}/westend_headers_to_millau.rs (97%) rename relays/bin-substrate/src/{rialto_millau => chains}/westend_headers_to_rococo.rs (96%) diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs new file mode 100644 index 0000000000000..ac5e611fdbcb5 --- /dev/null +++ b/relays/bin-substrate/src/chains/millau.rs @@ -0,0 +1,101 @@ +// 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 . + +//! Millau chain specification for CLI. + +use crate::cli::{ + bridge, + encode_call::{self, Call, CliEncodeCall}, + encode_message, send_message, CliChain, +}; +use codec::Decode; +use frame_support::weights::{GetDispatchInfo, Weight}; +use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; +use relay_millau_client::Millau; +use sp_version::RuntimeVersion; + +impl CliEncodeCall for Millau { + fn max_extrinsic_size() -> u32 { + bp_millau::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )), + Call::Transfer { recipient, amount } => millau_runtime::Call::Balances( + millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount.cast()), + ), + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::MILLAU_TO_RIALTO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( + lane.0, + payload, + fee.cast(), + )) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + }) + } +} + +impl CliChain for Millau { + const RUNTIME_VERSION: RuntimeVersion = millau_runtime::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = MessagePayload>; + + fn ss58_format() -> u16 { + millau_runtime::SS58Prefix::get() as u16 + } + + fn max_extrinsic_weight() -> Weight { + bp_millau::max_extrinsic_weight() + } + + // TODO [#854|#843] support multiple bridges? + fn encode_message(message: encode_message::MessagePayload) -> Result { + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender } => { + type Source = Millau; + type Target = relay_rialto_client::Rialto; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::(&mut call, bridge::MILLAU_TO_RIALTO_INDEX); + let call = Target::encode_call(&call).map_err(|e| e.to_string())?; + let weight = call.get_dispatch_info().weight; + + Ok(send_message::message_payload(spec_version, weight, origin, &call)) + } + } + } +} diff --git a/relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs similarity index 100% rename from relays/bin-substrate/src/rialto_millau/millau_headers_to_rialto.rs rename to relays/bin-substrate/src/chains/millau_headers_to_rialto.rs diff --git a/relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs similarity index 100% rename from relays/bin-substrate/src/rialto_millau/millau_messages_to_rialto.rs rename to relays/bin-substrate/src/chains/millau_messages_to_rialto.rs diff --git a/relays/bin-substrate/src/rialto_millau/mod.rs b/relays/bin-substrate/src/chains/mod.rs similarity index 63% rename from relays/bin-substrate/src/rialto_millau/mod.rs rename to relays/bin-substrate/src/chains/mod.rs index cf86f781c0afb..1f6b4134ce841 100644 --- a/relays/bin-substrate/src/rialto_millau/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Rialto <> Millau Bridge commands. +//! Chain-specific relayer configuration. pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; @@ -24,20 +24,12 @@ pub mod rococo_headers_to_westend; pub mod westend_headers_to_millau; pub mod westend_headers_to_rococo; -use crate::cli::{ - bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, send_message, CliChain, -}; -use codec::Decode; -use frame_support::weights::{GetDispatchInfo, Weight}; -use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; -use relay_millau_client::Millau; -use relay_rialto_client::Rialto; -use relay_rococo_client::Rococo; +mod millau; +mod rialto; +mod rococo; +mod westend; + use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; -use relay_westend_client::Westend; -use sp_version::RuntimeVersion; pub(crate) fn add_polkadot_kusama_price_metrics( params: MetricsParams, @@ -72,192 +64,14 @@ pub(crate) fn add_polkadot_kusama_price_metrics u32 { - bp_millau::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { - Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, - Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )), - Call::Transfer { recipient, amount } => millau_runtime::Call::Balances( - millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount.cast()), - ), - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( - lane.0, - payload, - fee.cast(), - )) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }, - }) - } -} - -impl CliChain for Millau { - const RUNTIME_VERSION: RuntimeVersion = millau_runtime::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload>; - - fn ss58_format() -> u16 { - millau_runtime::SS58Prefix::get() as u16 - } - - fn max_extrinsic_weight() -> Weight { - bp_millau::max_extrinsic_weight() - } - - // TODO [#854|#843] support multiple bridges? - fn encode_message(message: encode_message::MessagePayload) -> Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { - type Source = Millau; - type Target = Rialto; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::(&mut call, bridge::MILLAU_TO_RIALTO_INDEX); - let call = Target::encode_call(&call).map_err(|e| e.to_string())?; - let weight = call.get_dispatch_info().weight; - - Ok(send_message::message_payload(spec_version, weight, origin, &call)) - } - } - } -} - -impl CliEncodeCall for Rialto { - fn max_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() - } - - fn encode_call(call: &Call) -> anyhow::Result { - Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, - Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )), - Call::Transfer { recipient, amount } => { - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount.0)) - } - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( - lane.0, payload, fee.0, - )) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }, - }) - } -} - -impl CliChain for Rialto { - const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload>; - - fn ss58_format() -> u16 { - rialto_runtime::SS58Prefix::get() as u16 - } - - fn max_extrinsic_weight() -> Weight { - bp_rialto::max_extrinsic_weight() - } - - fn encode_message(message: encode_message::MessagePayload) -> Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { - type Source = Rialto; - type Target = Millau; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::(&mut call, bridge::RIALTO_TO_MILLAU_INDEX); - let call = Target::encode_call(&call).map_err(|e| e.to_string())?; - let weight = call.get_dispatch_info().weight; - - Ok(send_message::message_payload(spec_version, weight, origin, &call)) - } - } - } -} - -impl CliChain for Westend { - const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); - - fn ss58_format() -> u16 { - 42 - } - - fn max_extrinsic_weight() -> Weight { - 0 - } - - fn encode_message(_message: encode_message::MessagePayload) -> Result { - Err("Sending messages from Westend is not yet supported.".into()) - } -} - -impl CliChain for Rococo { - const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); - - fn ss58_format() -> u16 { - 42 - } - - fn max_extrinsic_weight() -> Weight { - 0 - } - - fn encode_message(_message: encode_message::MessagePayload) -> Result { - Err("Sending messages from Rococo is not yet supported.".into()) - } -} - #[cfg(test)] mod tests { - use super::*; + use crate::cli::{encode_call, send_message}; use bp_messages::source_chain::TargetHeaderChain; use codec::Encode; + use frame_support::dispatch::GetDispatchInfo; + use relay_millau_client::Millau; + use relay_rialto_client::Rialto; use relay_substrate_client::TransactionSignScheme; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs new file mode 100644 index 0000000000000..25c1ab04c9fd1 --- /dev/null +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -0,0 +1,98 @@ +// 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 . + +//! Rialto chain specification for CLI. + +use crate::cli::{ + bridge, + encode_call::{self, Call, CliEncodeCall}, + encode_message, send_message, CliChain, +}; +use codec::Decode; +use frame_support::weights::{GetDispatchInfo, Weight}; +use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; +use relay_rialto_client::Rialto; +use sp_version::RuntimeVersion; + +impl CliEncodeCall for Rialto { + fn max_extrinsic_size() -> u32 { + bp_rialto::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )), + Call::Transfer { recipient, amount } => { + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount.0)) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::RIALTO_TO_MILLAU_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( + lane.0, payload, fee.0, + )) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + }) + } +} + +impl CliChain for Rialto { + const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = MessagePayload>; + + fn ss58_format() -> u16 { + rialto_runtime::SS58Prefix::get() as u16 + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::max_extrinsic_weight() + } + + fn encode_message(message: encode_message::MessagePayload) -> Result { + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender } => { + type Source = Rialto; + type Target = relay_millau_client::Millau; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::(&mut call, bridge::RIALTO_TO_MILLAU_INDEX); + let call = Target::encode_call(&call).map_err(|e| e.to_string())?; + let weight = call.get_dispatch_info().weight; + + Ok(send_message::message_payload(spec_version, weight, origin, &call)) + } + } + } +} diff --git a/relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs similarity index 100% rename from relays/bin-substrate/src/rialto_millau/rialto_headers_to_millau.rs rename to relays/bin-substrate/src/chains/rialto_headers_to_millau.rs diff --git a/relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs similarity index 100% rename from relays/bin-substrate/src/rialto_millau/rialto_messages_to_millau.rs rename to relays/bin-substrate/src/chains/rialto_messages_to_millau.rs diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs new file mode 100644 index 0000000000000..0bcf388c3462e --- /dev/null +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -0,0 +1,39 @@ +// 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 . + +use crate::cli::{encode_message, CliChain}; +use frame_support::weights::Weight; +use relay_rococo_client::Rococo; +use sp_version::RuntimeVersion; + +impl CliChain for Rococo { + const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + 0 + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Rococo is not yet supported.".into()) + } +} diff --git a/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs b/relays/bin-substrate/src/chains/rococo_headers_to_westend.rs similarity index 96% rename from relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs rename to relays/bin-substrate/src/chains/rococo_headers_to_westend.rs index 82905b4d89b73..dca91adb3df68 100644 --- a/relays/bin-substrate/src/rialto_millau/rococo_headers_to_westend.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_westend.rs @@ -35,7 +35,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWestend { type TargetChain = Westend; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn transactions_author(&self) -> bp_westend::AccountId { diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs new file mode 100644 index 0000000000000..27621472d6d99 --- /dev/null +++ b/relays/bin-substrate/src/chains/westend.rs @@ -0,0 +1,41 @@ +// 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 . + +//! Westend chain specification for CLI. + +use crate::cli::{encode_message, CliChain}; +use frame_support::weights::Weight; +use relay_westend_client::Westend; +use sp_version::RuntimeVersion; + +impl CliChain for Westend { + const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + 0 + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Westend is not yet supported.".into()) + } +} diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs similarity index 97% rename from relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs rename to relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 798cc7c611cf0..1523dc1be584c 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -35,7 +35,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn transactions_author(&self) -> bp_millau::AccountId { diff --git a/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs b/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs similarity index 96% rename from relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs rename to relays/bin-substrate/src/chains/westend_headers_to_rococo.rs index b57cc75781f44..577a858d92290 100644 --- a/relays/bin-substrate/src/rialto_millau/westend_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs @@ -35,7 +35,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToRococo { type TargetChain = Rococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::rialto_millau::add_polkadot_kusama_price_metrics::(params) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn transactions_author(&self) -> bp_rococo::AccountId { diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 5a5715699cf01..faf4417d1e995 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -57,7 +57,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::rialto_millau::millau_messages_to_rialto::run as relay_messages; + use crate::chains::millau_messages_to_rialto::run as relay_messages; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -79,7 +79,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::rialto_millau::rialto_messages_to_millau::run as relay_messages; + use crate::chains::rialto_messages_to_millau::run as relay_messages; // Send-message / Estimate-fee #[allow(unused_imports)] diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 8137f8a240da5..346790f2ae74e 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -53,35 +53,35 @@ macro_rules! select_bridge { RelayHeadersBridge::MillauToRialto => { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; - type Finality = crate::rialto_millau::millau_headers_to_rialto::MillauFinalityToRialto; + type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; $generic } RelayHeadersBridge::RialtoToMillau => { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; - type Finality = crate::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; + type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; $generic } RelayHeadersBridge::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; - type Finality = crate::rialto_millau::westend_headers_to_millau::WestendFinalityToMillau; + type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; $generic } RelayHeadersBridge::WestendToRococo => { type Source = relay_westend_client::Westend; type Target = relay_rococo_client::Rococo; - type Finality = crate::rialto_millau::westend_headers_to_rococo::WestendFinalityToRococo; + type Finality = crate::chains::westend_headers_to_rococo::WestendFinalityToRococo; $generic } RelayHeadersBridge::RococoToWestend => { type Source = relay_rococo_client::Rococo; type Target = relay_westend_client::Westend; - type Finality = crate::rialto_millau::rococo_headers_to_westend::RococoFinalityToWestend; + type Finality = crate::chains::rococo_headers_to_westend::RococoFinalityToWestend; $generic } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index ded79e0f4c9fb..98ff1268fae9a 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -90,14 +90,14 @@ macro_rules! select_bridge { type Left = relay_millau_client::Millau; type Right = relay_rialto_client::Rialto; - type LeftToRightFinality = crate::rialto_millau::millau_headers_to_rialto::MillauFinalityToRialto; - type RightToLeftFinality = crate::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; + type LeftToRightFinality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; + type RightToLeftFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; - type LeftToRightMessages = crate::rialto_millau::millau_messages_to_rialto::MillauMessagesToRialto; - type RightToLeftMessages = crate::rialto_millau::rialto_messages_to_millau::RialtoMessagesToMillau; + type LeftToRightMessages = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; + type RightToLeftMessages = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; - use crate::rialto_millau::millau_messages_to_rialto::run as left_to_right_messages; - use crate::rialto_millau::rialto_messages_to_millau::run as right_to_left_messages; + use crate::chains::millau_messages_to_rialto::run as left_to_right_messages; + use crate::chains::rialto_messages_to_millau::run as right_to_left_messages; $generic } diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 81da25fcb7de9..6bf7561fcdb37 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -20,6 +20,7 @@ use relay_utils::initialize::initialize_logger; +mod chains; mod cli; mod finality_pipeline; mod finality_target; @@ -29,8 +30,6 @@ mod messages_source; mod messages_target; mod on_demand_headers; -mod rialto_millau; - fn main() { initialize_logger(false); let command = cli::parse_args(); From 0fa076337bcfa38dff7cb514004c5acee90e5949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 15 Apr 2021 23:51:53 +0200 Subject: [PATCH 0430/1210] Update weights (#898) * New weights. * Fix test. * cargo fmt --all --- modules/grandpa/src/weights.rs | 93 ++++++++-------- modules/messages/src/weights.rs | 124 +++++++++++----------- relays/bin-substrate/src/messages_lane.rs | 2 +- 3 files changed, 105 insertions(+), 114 deletions(-) diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 57dba9a6846a1..a548534a20b7e 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,33 +17,24 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-04-02, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-04-14, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// ./target/release/rialto-bridge-node +// target/release/rialto-bridge-node // benchmark -// --chain -// dev -// --execution -// wasm -// --extrinsic -// * -// --pallet -// pallet_bridge_grandpa -// --wasm-execution -// compiled -// --steps -// 50 -// --repeat -// 20 -// --template -// ./.maintain/rialto-weight-template.hbs -// --output -// ./grandpa-template.txt -// --raw +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_bridge_grandpa +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./modules/grandpa/src/weights.rs +// --template=./.maintain/rialto-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] @@ -69,29 +60,29 @@ pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn submit_finality_proof(v: u32, p: u32) -> Weight { (0 as Weight) - .saturating_add((160_060_000 as Weight).saturating_mul(v as Weight)) - .saturating_add((640_223_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add((837_084_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((874_929_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) } fn submit_finality_proof_on_single_fork(v: u32) -> Weight { - (189_597_000 as Weight) - .saturating_add((11_680_000 as Weight).saturating_mul(v as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (276_463_000 as Weight) + .saturating_add((14_149_000 as Weight).saturating_mul(v as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) } fn submit_finality_proof_on_many_forks(p: u32) -> Weight { - (0 as Weight) - .saturating_add((130_061_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (10_676_019_000 as Weight) + .saturating_add((97_598_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) } fn find_scheduled_change(n: u32) -> Weight { - (502_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) + (618_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) } fn read_write_authority_sets(n: u32) -> Weight { - (7_677_000 as Weight) - .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) + (8_582_000 as Weight) + .saturating_add((234_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -101,29 +92,29 @@ impl WeightInfo for RialtoWeight { impl WeightInfo for () { fn submit_finality_proof(v: u32, p: u32) -> Weight { (0 as Weight) - .saturating_add((160_060_000 as Weight).saturating_mul(v as Weight)) - .saturating_add((640_223_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add((837_084_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((874_929_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } fn submit_finality_proof_on_single_fork(v: u32) -> Weight { - (189_597_000 as Weight) - .saturating_add((11_680_000 as Weight).saturating_mul(v as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (276_463_000 as Weight) + .saturating_add((14_149_000 as Weight).saturating_mul(v as Weight)) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } fn submit_finality_proof_on_many_forks(p: u32) -> Weight { - (0 as Weight) - .saturating_add((130_061_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (10_676_019_000 as Weight) + .saturating_add((97_598_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) } fn find_scheduled_change(n: u32) -> Weight { - (502_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) + (618_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) } fn read_write_authority_sets(n: u32) -> Weight { - (7_677_000 as Weight) - .saturating_add((230_000 as Weight).saturating_mul(n as Weight)) + (8_582_000 as Weight) + .saturating_add((234_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 4e275b1f248b2..0eecd0d846237 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -16,16 +16,16 @@ //! Autogenerated weights for pallet_bridge_messages //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.1 -//! DATE: 2021-02-11, STEPS: [50, ], REPEAT: 20 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 +//! DATE: 2021-04-14, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("local"), DB CACHE: 128 +//! CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: // target/release/rialto-bridge-node // benchmark -// --chain=local +// --chain=dev // --steps=50 // --repeat=20 // --pallet=pallet_bridge_messages @@ -73,105 +73,105 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (140_645_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (149_497_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (146_434_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (154_339_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (214_721_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (200_066_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (8_395_221_000 as Weight) + (6_432_637_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (156_390_000 as Weight) + (141_671_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (269_316_000 as Weight) + (247_393_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (174_342_000 as Weight) + (159_312_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (186_621_000 as Weight) + (167_935_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (487_028_000 as Weight) + (449_846_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (144_893_000 as Weight) + (127_322_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (151_134_000 as Weight) + (134_120_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (212_650_000 as Weight) + (191_193_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (88_670_000 as Weight) - .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (115_699_000 as Weight) + .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((125_956_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((113_551_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (462_389_000 as Weight) - .saturating_add((11_000 as Weight).saturating_mul(i as Weight)) + (458_731_000 as Weight) + .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (120_744_000 as Weight) - .saturating_add((8_000 as Weight).saturating_mul(i as Weight)) + (82_314_000 as Weight) + .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((130_087_000 as Weight).saturating_mul(i as Weight)) + (16_766_000 as Weight) + .saturating_add((115_533_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (126_833_000 as Weight) - .saturating_add((7_793_000 as Weight).saturating_mul(i as Weight)) + (122_146_000 as Weight) + .saturating_add((6_789_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (71_269_000 as Weight) - .saturating_add((72_377_000 as Weight).saturating_mul(i as Weight)) + (155_671_000 as Weight) + .saturating_add((63_020_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -182,105 +182,105 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (140_645_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (149_497_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (146_434_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (154_339_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (214_721_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (200_066_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (8_395_221_000 as Weight) + (6_432_637_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (156_390_000 as Weight) + (141_671_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (269_316_000 as Weight) + (247_393_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (174_342_000 as Weight) + (159_312_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (186_621_000 as Weight) + (167_935_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (487_028_000 as Weight) + (449_846_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (144_893_000 as Weight) + (127_322_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (151_134_000 as Weight) + (134_120_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (212_650_000 as Weight) + (191_193_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (88_670_000 as Weight) - .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (115_699_000 as Weight) + .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((125_956_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((113_551_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (462_389_000 as Weight) - .saturating_add((11_000 as Weight).saturating_mul(i as Weight)) + (458_731_000 as Weight) + .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (120_744_000 as Weight) - .saturating_add((8_000 as Weight).saturating_mul(i as Weight)) + (82_314_000 as Weight) + .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((130_087_000 as Weight).saturating_mul(i as Weight)) + (16_766_000 as Weight) + .saturating_add((115_533_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (126_833_000 as Weight) - .saturating_add((7_793_000 as Weight).saturating_mul(i as Weight)) + (122_146_000 as Weight) + .saturating_add((6_789_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (71_269_000 as Weight) - .saturating_add((72_377_000 as Weight).saturating_mul(i as Weight)) + (155_671_000 as Weight) + .saturating_add((63_020_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 753bf6320d511..9948b6ec08365 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -203,7 +203,7 @@ mod tests { // reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (955, 216_583_333_334), + (1020, 216_583_333_334), ); } } From a5f561cb887bd6072239e4247991d99b4459a5a3 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 15 Apr 2021 18:24:08 -0400 Subject: [PATCH 0431/1210] Prettify test output when encoding doesn't match (#907) --- relays/bin-substrate/src/chains/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 1f6b4134ce841..f33e265f9a870 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -259,6 +259,7 @@ mod rococo_tests { extrinsics_root: Default::default(), digest: sp_runtime::generic::Digest { logs: vec![] }, }; + let justification = GrandpaJustification { round: 0, commit: finality_grandpa::Commit { @@ -268,6 +269,7 @@ mod rococo_tests { }, votes_ancestries: vec![], }; + let actual = bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof(header.clone(), justification.clone()); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, @@ -281,7 +283,7 @@ mod rococo_tests { // then assert_eq!( actual_encoded, expected_encoded, - "Encoding difference. Raw: {:?} vs {:?}", + "\n\nEncoding difference.\nGot {:#?} \nExpected: {:#?}", actual, expected ); } @@ -302,6 +304,7 @@ mod westend_tests { extrinsics_root: Default::default(), digest: sp_runtime::generic::Digest { logs: vec![] }, }; + let justification = GrandpaJustification { round: 0, commit: finality_grandpa::Commit { @@ -311,6 +314,7 @@ mod westend_tests { }, votes_ancestries: vec![], }; + let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof(header.clone(), justification.clone()); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, @@ -324,7 +328,7 @@ mod westend_tests { // then assert_eq!( actual_encoded, expected_encoded, - "Encoding difference. Raw: {:?} vs {:?}", + "\n\nEncoding difference.\nGot {:#?} \nExpected: {:#?}", actual, expected ); } From 465efb008be92f6d2c863a8a6794f0a447d51ff3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Apr 2021 19:10:04 +0300 Subject: [PATCH 0432/1210] fix polkadot primitives (#908) --- primitives/polkadot-core/src/lib.rs | 30 +++++++++++++++++++---------- relays/client-rococo/src/lib.rs | 7 ++++++- relays/client-westend/src/lib.rs | 7 ++++++- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 8cf62c0030974..c9858c0820d71 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -28,11 +28,12 @@ use frame_support::{ Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128, }; use frame_system::limits; +use parity_scale_codec::Compact; use sp_core::Hasher as HasherT; use sp_runtime::{ generic, traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, OpaqueExtrinsic, Perbill, + MultiAddress, MultiSignature, OpaqueExtrinsic, Perbill, }; use sp_std::prelude::Vec; @@ -192,10 +193,19 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic>; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic, Call, Signature, SignedExtensions>; /// A type of the data encoded as part of the transaction. -pub type SignedExtra = ((), (), (), sp_runtime::generic::Era, Nonce, (), Balance); +pub type SignedExtra = ( + (), + (), + (), + sp_runtime::generic::Era, + Compact, + (), + Compact, +); /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). @@ -232,13 +242,13 @@ impl SignedExtensions { ) -> Self { Self { encode_payload: ( - (), // spec version - (), // tx version - (), // genesis - era, // era - nonce, // nonce (compact encoding) - (), // Check weight - tip, // transaction payment / tip (compact encoding) + (), // spec version + (), // tx version + (), // genesis + era, // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + tip.into(), // transaction payment / tip (compact encoding) ), additional_signed: ( version.spec_version, diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 1e2dd6569b48f..09d205f06e910 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -84,7 +84,12 @@ impl TransactionSignScheme for Rococo { let signer: sp_runtime::MultiSigner = signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_rococo::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + bp_rococo::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) } } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 5ca4552bc2c2f..417938ccf5a98 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -84,7 +84,12 @@ impl TransactionSignScheme for Westend { let signer: sp_runtime::MultiSigner = signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_westend::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + bp_westend::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) } } From 1ebb31c34bf76f6bd1fb4f7dcea65c5d8ca09dbc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Apr 2021 19:11:10 +0300 Subject: [PATCH 0433/1210] Update Kusama/Polkadot metrics (#910) --- relays/bin-substrate/src/chains/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index f33e265f9a870..9e6a7361d5fdf 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -42,10 +42,10 @@ pub(crate) fn add_polkadot_kusama_price_metrics Date: Tue, 20 Apr 2021 17:59:03 +0300 Subject: [PATCH 0434/1210] (temporarily) Switch to jsonrpsee master (#913) * (temporarily) switch to jsonrpsee master * removed param used for tests --- relays/client-ethereum/Cargo.toml | 6 +++--- relays/client-ethereum/src/client.rs | 4 ++-- relays/client-substrate/Cargo.toml | 6 +++--- relays/client-substrate/src/client.rs | 9 +++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 56e346417301b..486f84b135eb8 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -10,9 +10,9 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = "=0.2.0-alpha.3" -jsonrpsee-types = "=0.2.0-alpha.3" -jsonrpsee-ws-client = "=0.2.0-alpha.3" +jsonrpsee-proc-macros = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } +jsonrpsee-types = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } +jsonrpsee-ws-client = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs index 10fba1fb99fd1..e2def5fb03d11 100644 --- a/relays/client-ethereum/src/client.rs +++ b/relays/client-ethereum/src/client.rs @@ -21,7 +21,7 @@ use crate::types::{ }; use crate::{ConnectionParams, Error, Result}; -use jsonrpsee_ws_client::{WsClient as RpcClient, WsConfig as RpcConfig}; +use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use std::sync::Arc; /// Number of headers missing from the Ethereum node for us to consider node not synced. @@ -46,7 +46,7 @@ impl Client { /// Build client to use in connection. async fn build_client(params: &ConnectionParams) -> Result> { let uri = format!("ws://{}:{}", params.host, params.port); - let client = RpcClient::new(RpcConfig::with_url(&uri)).await?; + let client = RpcClientBuilder::default().build(&uri).await?; Ok(Arc::new(client)) } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 012913d4a4a21..ee9ce1ace041a 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } -jsonrpsee-proc-macros = "=0.2.0-alpha.3" -jsonrpsee-types = "=0.2.0-alpha.3" -jsonrpsee-ws-client = "=0.2.0-alpha.3" +jsonrpsee-proc-macros = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } +jsonrpsee-types = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } +jsonrpsee-ws-client = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index ce91f4e33fc74..1f7be7c805163 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -24,7 +24,7 @@ use async_std::sync::{Arc, Mutex}; use codec::Decode; use frame_system::AccountInfo; use jsonrpsee_types::{jsonrpc::DeserializeOwned, traits::SubscriptionClient}; -use jsonrpsee_ws_client::{WsClient as RpcClient, WsConfig as RpcConfig, WsSubscription as Subscription}; +use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder, WsSubscription as Subscription}; use num_traits::Zero; use pallet_balances::AccountData; use sp_core::{storage::StorageKey, Bytes}; @@ -105,9 +105,10 @@ impl Client { params.host, params.port, ); - let mut config = RpcConfig::with_url(&uri); - config.max_notifs_per_subscription = MAX_SUBSCRIPTION_CAPACITY; - let client = RpcClient::new(config).await?; + let client = RpcClientBuilder::default() + .max_notifs_per_subscription(MAX_SUBSCRIPTION_CAPACITY) + .build(&uri) + .await?; Ok(Arc::new(client)) } From 5969408e0dbb226415559849817b81e6d5446628 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Tue, 20 Apr 2021 21:03:01 +0200 Subject: [PATCH 0435/1210] Update jsonrpsee to 0.2.0-alpha.5 (#914) * update jsonrpsee to 0.2.0-alpha.5 * cargo fmt --- relays/client-ethereum/Cargo.toml | 5 ++--- relays/client-ethereum/src/error.rs | 2 +- relays/client-substrate/Cargo.toml | 5 ++--- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 6 +++--- relays/client-substrate/src/error.rs | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 486f84b135eb8..ebae252ed5ab3 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -10,9 +10,8 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } -jsonrpsee-types = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } -jsonrpsee-ws-client = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } +jsonrpsee-proc-macros = "=0.2.0-alpha.5" +jsonrpsee-ws-client = "=0.2.0-alpha.5" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index 69ade23f741cb..bcd8edc3f33ae 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -18,7 +18,7 @@ use crate::types::U256; -use jsonrpsee_types::error::Error as RpcError; +use jsonrpsee_ws_client::Error as RpcError; use relay_utils::MaybeConnectionError; /// Result type used by Ethereum client. diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index ee9ce1ace041a..7b3f46230fce1 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,9 +9,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } -jsonrpsee-proc-macros = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } -jsonrpsee-types = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } -jsonrpsee-ws-client = { git = "https://github.com/paritytech/jsonrpsee", rev = "de7b58a881512cd5ab8bbf16a56241ca808c7765" } +jsonrpsee-proc-macros = "=0.2.0-alpha.5" +jsonrpsee-ws-client = "=0.2.0-alpha.5" log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 6676873ee61b3..64c0d6af52b22 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,7 +16,7 @@ use bp_runtime::Chain as ChainBase; use frame_support::Parameter; -use jsonrpsee_types::jsonrpc::{DeserializeOwned, Serialize}; +use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; use num_traits::{CheckedSub, Zero}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 1f7be7c805163..892a63d6d5b00 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -23,8 +23,8 @@ use crate::{ConnectionParams, Error, Result}; use async_std::sync::{Arc, Mutex}; use codec::Decode; use frame_system::AccountInfo; -use jsonrpsee_types::{jsonrpc::DeserializeOwned, traits::SubscriptionClient}; -use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder, WsSubscription as Subscription}; +use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned}; +use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use num_traits::Zero; use pallet_balances::AccountData; use sp_core::{storage::StorageKey, Bytes}; @@ -267,7 +267,7 @@ impl Client { .client .subscribe( "grandpa_subscribeJustifications", - jsonrpsee_types::jsonrpc::Params::None, + JsonRpcParams::NoParams, "grandpa_unsubscribeJustifications", ) .await?) diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 7aee28df18574..304229ede1986 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -16,7 +16,7 @@ //! Substrate node RPC errors. -use jsonrpsee_types::error::Error as RpcError; +use jsonrpsee_ws_client::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; From b2e6ef275b18c95db6acb701bea4d0dc88277c03 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 20 Apr 2021 17:19:34 -0400 Subject: [PATCH 0436/1210] Prep for Westend to Rococo Header Sync (#915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump Rococo and Westend RuntimeVersions * Add helper scripts for running Rococo<>Westend header sync * Remove extra space Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- primitives/chain-rococo/src/lib.rs | 7 ++++--- primitives/chain-westend/src/lib.rs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index cc3eb47b1b763..b79fdf6cfcf01 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -32,14 +32,15 @@ pub type Rococo = PolkadotLike; pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; +// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v1-1"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), authoring_version: 0, - spec_version: 30, + spec_version: 231, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 6, + transaction_version: 0, }; /// Rococo Runtime `Call` enum. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index dbbfabd5dcf2f..db97364ef419a 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -32,12 +32,12 @@ pub type Westend = PolkadotLike; pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; -/// Runtime version. +// NOTE: This needs to be kept up to date with the Westend runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("westend"), impl_name: sp_version::create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 50, + spec_version: 51, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 5, From 58b8672c73fce716ad949d4234b8afec913083fa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Apr 2021 14:44:39 +0300 Subject: [PATCH 0437/1210] Prefix in relay loops logs (#920) * prefix in relay loops logs * fmt --- relays/bin-substrate/src/finality_pipeline.rs | 2 +- relays/bin-substrate/src/messages_source.rs | 2 +- relays/bin-substrate/src/messages_target.rs | 2 +- relays/exchange/src/exchange.rs | 15 +-- relays/exchange/src/exchange_loop.rs | 12 +-- relays/finality/src/finality_loop.rs | 6 +- relays/finality/src/finality_loop_tests.rs | 2 +- relays/finality/src/lib.rs | 2 +- relays/headers/src/sync_loop.rs | 8 +- relays/headers/src/sync_types.rs | 2 +- relays/messages/src/message_lane.rs | 2 +- relays/messages/src/message_lane_loop.rs | 25 +++-- relays/utils/src/initialize.rs | 46 +++++++- relays/utils/src/relay_loop.rs | 100 +++++++++--------- 14 files changed, 137 insertions(+), 89 deletions(-) diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index bc8461f6a8385..9538f35778dcb 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -96,7 +96,7 @@ where SourceChain: Clone + Chain + Debug, BlockNumberOf: BlockNumberBase, TargetChain: Clone + Chain + Debug, - TargetSign: Clone + Send + Sync, + TargetSign: 'static + Clone + Send + Sync, { const SOURCE_NAME: &'static str = SourceChain::NAME; const TARGET_NAME: &'static str = TargetChain::NAME; diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index cf98f3276be6c..0ccf8bbde885a 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -93,7 +93,7 @@ impl RelayClient for SubstrateMessagesSource where C: Chain, P: SubstrateMessageLane, - R: Send + Sync, + R: 'static + Send + Sync, I: Send + Sync + Instance, { type Error = SubstrateError; diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 176083273069b..39f638d7e91c1 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -93,7 +93,7 @@ impl RelayClient for SubstrateMessagesTarget where C: Chain, P: SubstrateMessageLane, - R: Send + Sync, + R: 'static + Send + Sync, I: Send + Sync + Instance, { type Error = SubstrateError; diff --git a/relays/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs index cec0d7cba1fa4..4a2f07fa7f979 100644 --- a/relays/exchange/src/exchange.rs +++ b/relays/exchange/src/exchange.rs @@ -26,7 +26,7 @@ use std::{ }; /// Transaction proof pipeline. -pub trait TransactionProofPipeline { +pub trait TransactionProofPipeline: 'static { /// Name of the transaction proof source. const SOURCE_NAME: &'static str; /// Name of the transaction proof target. @@ -35,18 +35,21 @@ pub trait TransactionProofPipeline { /// Block type. type Block: SourceBlock; /// Transaction inclusion proof type. - type TransactionProof; + type TransactionProof: 'static + Send + Sync; } /// Block that is participating in exchange. -pub trait SourceBlock { +pub trait SourceBlock: 'static + Send + Sync { /// Block hash type. - type Hash: Clone + Debug + Display; + type Hash: 'static + Clone + Send + Sync + Debug + Display; /// Block number type. - type Number: Debug + type Number: 'static + + Debug + Display + Clone + Copy + + Send + + Sync + Into + std::cmp::Ord + std::ops::Add @@ -61,7 +64,7 @@ pub trait SourceBlock { } /// Transaction that is participating in exchange. -pub trait SourceTransaction { +pub trait SourceTransaction: 'static + Send { /// Transaction hash type. type Hash: Debug + Display; diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index b46d34e047a8b..4525c33e36a15 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -39,9 +39,9 @@ pub struct TransactionProofsRelayState { } /// Transactions proofs relay storage. -pub trait TransactionProofsRelayStorage: Clone { +pub trait TransactionProofsRelayStorage: 'static + Clone + Send + Sync { /// Associated block number. - type BlockNumber; + type BlockNumber: 'static + Send + Sync; /// Get relay state. fn state(&self) -> TransactionProofsRelayState; @@ -64,7 +64,7 @@ impl InMemoryStorage { } } -impl TransactionProofsRelayStorage for InMemoryStorage { +impl TransactionProofsRelayStorage for InMemoryStorage { type BlockNumber = BlockNumber; fn state(&self) -> TransactionProofsRelayState { @@ -89,7 +89,7 @@ pub async fn run( source_client: impl SourceClient

, target_client: impl TargetClient

, metrics_params: MetricsParams, - exit_signal: impl Future, + exit_signal: impl Future + 'static + Send, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); @@ -99,7 +99,7 @@ pub async fn run( .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? - .run(|source_client, target_client, metrics| { + .run(metrics_prefix::

(), move |source_client, target_client, metrics| { run_until_connection_lost( storage.clone(), source_client, @@ -117,7 +117,7 @@ async fn run_until_connection_lost( source_client: impl SourceClient

, target_client: impl TargetClient

, metrics_exch: Option, - exit_signal: impl Future, + exit_signal: impl Future + Send, ) -> Result<(), FailedClient> { let mut retry_backoff = retry_backoff(); let mut state = storage.state(); diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index aff32e46de443..cce32839907d9 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -65,7 +65,7 @@ pub struct FinalitySyncParams { pub trait SourceClient: RelayClient { /// Stream of new finality proofs. The stream is allowed to miss proofs for some /// headers, even if those headers are mandatory. - type FinalityProofsStream: Stream; + type FinalityProofsStream: Stream + Send; /// Get best finalized block number. async fn best_finalized_block_number(&self) -> Result; @@ -101,7 +101,7 @@ pub async fn run( target_client: impl TargetClient

, sync_params: FinalitySyncParams, metrics_params: MetricsParams, - exit_signal: impl Future, + exit_signal: impl Future + 'static + Send, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) @@ -110,7 +110,7 @@ pub async fn run( .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? - .run(|source_client, target_client, metrics| { + .run(metrics_prefix::

(), move |source_client, target_client, metrics| { run_until_connection_lost( source_client, target_client, diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index eedd902003308..f7826ead730c9 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -106,7 +106,7 @@ impl RelayClient for TestSourceClient { #[async_trait] impl SourceClient for TestSourceClient { - type FinalityProofsStream = Pin>>; + type FinalityProofsStream = Pin + 'static + Send>>; async fn best_finalized_block_number(&self) -> Result { let mut data = self.data.lock(); diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index d5048aa1607d5..64ec5bed05005 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -28,7 +28,7 @@ mod finality_loop; mod finality_loop_tests; /// Finality proofs synchronization pipeline. -pub trait FinalitySyncPipeline: Clone + Debug + Send + Sync { +pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Name of the finality proofs source. const SOURCE_NAME: &'static str; /// Name of the finality proofs target. diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index e4f1b7b04507e..b204932056509 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -102,7 +102,7 @@ pub trait TargetClient: RelayClient { /// Synchronization maintain procedure. #[async_trait] -pub trait SyncMaintain: Clone + Send + Sync { +pub trait SyncMaintain: 'static + Clone + Send + Sync { /// Run custom maintain procedures. This is guaranteed to be called when both source and target /// clients are unoccupied. async fn maintain(&self, _sync: &mut HeadersSync

) {} @@ -125,7 +125,7 @@ pub async fn run>( sync_maintain: impl SyncMaintain

, sync_params: HeadersSyncParams, metrics_params: MetricsParams, - exit_signal: impl Future, + exit_signal: impl Future + 'static + Send, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) @@ -134,7 +134,7 @@ pub async fn run>( .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? - .run(|source_client, target_client, metrics| { + .run(metrics_prefix::

(), move |source_client, target_client, metrics| { run_until_connection_lost( source_client, source_tick, @@ -159,7 +159,7 @@ async fn run_until_connection_lost>( sync_maintain: impl SyncMaintain

, sync_params: HeadersSyncParams, metrics_sync: Option, - exit_signal: impl Future, + exit_signal: impl Future + Send, ) -> Result<(), FailedClient> { let mut progress_context = (Instant::now(), None, None); diff --git a/relays/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs index e6500ad5facb0..5809ebab59e1c 100644 --- a/relays/headers/src/sync_types.rs +++ b/relays/headers/src/sync_types.rs @@ -43,7 +43,7 @@ pub enum HeaderStatus { } /// Headers synchronization pipeline. -pub trait HeadersSyncPipeline: Clone + Send + Sync { +pub trait HeadersSyncPipeline: 'static + Clone + Send + Sync { /// Name of the headers source. const SOURCE_NAME: &'static str; /// Name of the headers target. diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs index 5090ef124e7f7..6473ec987500b 100644 --- a/relays/messages/src/message_lane.rs +++ b/relays/messages/src/message_lane.rs @@ -23,7 +23,7 @@ use relay_utils::{BlockNumberBase, HeaderId}; use std::fmt::Debug; /// One-way message lane. -pub trait MessageLane: Clone + Send + Sync { +pub trait MessageLane: 'static + Clone + Send + Sync { /// Name of the messages source. const SOURCE_NAME: &'static str; /// Name of the messages target. diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 41eee606d82be..d43fecf9b1660 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -227,7 +227,7 @@ pub async fn run( source_client: impl SourceClient

, target_client: impl TargetClient

, metrics_params: MetricsParams, - exit_signal: impl Future, + exit_signal: impl Future + Send + 'static, ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) @@ -237,15 +237,18 @@ pub async fn run( .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? - .run(|source_client, target_client, metrics| { - run_until_connection_lost( - params.clone(), - source_client, - target_client, - metrics, - exit_signal.clone(), - ) - }) + .run( + metrics_prefix::

(¶ms.lane), + move |source_client, target_client, metrics| { + run_until_connection_lost( + params.clone(), + source_client, + target_client, + metrics, + exit_signal.clone(), + ) + }, + ) .await } @@ -701,7 +704,7 @@ pub(crate) mod tests { data: TestClientData, source_tick: Arc, target_tick: Arc, - exit_signal: impl Future, + exit_signal: impl Future + 'static + Send, ) -> TestClientData { async_std::task::block_on(async { let data = Arc::new(Mutex::new(data)); diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index 7d5f66a53815c..b87937923bd4e 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -16,7 +16,11 @@ //! Relayer initialization functions. -use std::{fmt::Display, io::Write}; +use std::{cell::RefCell, fmt::Display, io::Write}; + +async_std::task_local! { + pub(crate) static LOOP_NAME: RefCell = RefCell::new(String::default()); +} /// Initialize relay environment. pub fn initialize_relay() { @@ -43,20 +47,56 @@ pub fn initialize_logger(with_timestamp: bool) { Either::Right(ansi_term::Colour::Fixed(8).bold().paint(timestamp)) }; - writeln!(buf, "{} {} {} {}", timestamp, log_level, log_target, record.args(),) + writeln!( + buf, + "{}{} {} {} {}", + loop_name_prefix(), + timestamp, + log_level, + log_target, + record.args(), + ) }); } else { builder.format(move |buf, record| { let log_level = color_level(record.level()); let log_target = color_target(record.target()); - writeln!(buf, "{} {} {}", log_level, log_target, record.args(),) + writeln!( + buf, + "{}{} {} {}", + loop_name_prefix(), + log_level, + log_target, + record.args(), + ) }); } builder.init(); } +/// Initialize relay loop. Must only be called once per every loop task. +pub(crate) fn initialize_loop(loop_name: String) { + LOOP_NAME.with(|g_loop_name| *g_loop_name.borrow_mut() = loop_name); +} + +/// Returns loop name prefix to use in logs. The prefix is initialized with the `initialize_loop` call. +fn loop_name_prefix() -> String { + // try_with to avoid panic outside of async-std task context + LOOP_NAME + .try_with(|loop_name| { + // using borrow is ok here, because loop is only initialized once (=> borrow_mut will only be called once) + let loop_name = loop_name.borrow(); + if loop_name.is_empty() { + String::new() + } else { + format!("[{}] ", loop_name) + } + }) + .unwrap_or_else(|_| String::new()) +} + enum Either { Left(A), Right(B), diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 8790b0913e176..ea2e7623ee223 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -26,9 +26,9 @@ pub const RECONNECT_DELAY: Duration = Duration::from_secs(10); /// Basic blockchain client from relay perspective. #[async_trait] -pub trait Client: Clone + Send + Sync { +pub trait Client: 'static + Clone + Send + Sync { /// Type of error this clients returns. - type Error: Debug + MaybeConnectionError; + type Error: 'static + Debug + MaybeConnectionError + Send + Sync; /// Try to reconnect to source node. async fn reconnect(&mut self) -> Result<(), Self::Error>; @@ -105,63 +105,65 @@ impl Loop { /// This function represents an outer loop, which in turn calls provided `run_loop` function to do /// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, /// target or both) and calls `run_loop` again. - pub async fn run(mut self, run_loop: R) -> Result<(), String> + pub async fn run(mut self, loop_name: String, run_loop: R) -> Result<(), String> where - R: Fn(SC, TC, Option) -> F, - F: Future>, - SC: Client, - TC: Client, - LM: Clone, + R: 'static + Send + Fn(SC, TC, Option) -> F, + F: 'static + Send + Future>, + SC: 'static + Client, + TC: 'static + Client, + LM: 'static + Send + Clone, { - loop { - let result = run_loop( - self.source_client.clone(), - self.target_client.clone(), - self.loop_metric.clone(), - ) - .await; + async_std::task::spawn(async move { + crate::initialize::initialize_loop(loop_name); - match result { - Ok(()) => break, - Err(failed_client) => loop { - async_std::task::sleep(self.reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - match self.source_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to source client. Going to retry in {}s: {:?}", - self.reconnect_delay.as_secs(), - error, - ); - continue; + loop { + let loop_metric = self.loop_metric.clone(); + let future_result = run_loop(self.source_client.clone(), self.target_client.clone(), loop_metric); + let result = future_result.await; + + match result { + Ok(()) => break, + Err(failed_client) => loop { + async_std::task::sleep(self.reconnect_delay).await; + if failed_client == FailedClient::Both || failed_client == FailedClient::Source { + match self.source_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to source client. Going to retry in {}s: {:?}", + self.reconnect_delay.as_secs(), + error, + ); + continue; + } } } - } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - match self.target_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to target client. Going to retry in {}s: {:?}", - self.reconnect_delay.as_secs(), - error, - ); - continue; + if failed_client == FailedClient::Both || failed_client == FailedClient::Target { + match self.target_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to target client. Going to retry in {}s: {:?}", + self.reconnect_delay.as_secs(), + error, + ); + continue; + } } } - } - break; - }, - } + break; + }, + } - log::debug!(target: "bridge", "Restarting relay loop"); - } + log::debug!(target: "bridge", "Restarting relay loop"); + } - Ok(()) + Ok(()) + }) + .await } } From 2eca39e719b4161b22fa2719a68a23e20c0b167c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Apr 2021 17:54:21 +0300 Subject: [PATCH 0438/1210] Fix issue with on-demand headers relay not starting (#921) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * require lane source -> target headers when weknow all headers that have produced messages, but are unable to deliver all messages because of unrewarded relayers vec capacity * Update relays/messages/src/message_race_delivery.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- relays/messages/src/message_lane_loop.rs | 42 +++++++++------- relays/messages/src/message_race_delivery.rs | 53 +++++++++++++++++++- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index d43fecf9b1660..af04bf984e1f9 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -582,6 +582,9 @@ pub(crate) mod tests { ) -> Result<(), TestError> { let mut data = self.data.lock(); (self.tick)(&mut *data); + data.source_state.best_self = + HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); + data.source_state.best_finalized_self = data.source_state.best_self; data.submitted_messages_receiving_proofs.push(proof); data.source_latest_confirmed_received_nonce = proof; Ok(()) @@ -684,6 +687,7 @@ pub(crate) mod tests { } data.target_state.best_self = HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); + data.target_state.best_finalized_self = data.target_state.best_self; data.target_latest_received_nonce = *proof.0.end(); if let Some(target_latest_confirmed_received_nonce) = proof.1 { data.target_latest_confirmed_received_nonce = target_latest_confirmed_received_nonce; @@ -812,37 +816,37 @@ pub(crate) mod tests { ..Default::default() }, Arc::new(|data: &mut TestClientData| { + // blocks are produced on every tick + data.source_state.best_self = + HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); + data.source_state.best_finalized_self = data.source_state.best_self; // headers relay must only be started when we need new target headers at source node if data.target_to_source_header_required.is_some() { assert!(data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_self.0); data.target_to_source_header_required = None; } + // syncing target headers -> source chain + if let Some(last_requirement) = data.target_to_source_header_requirements.last() { + if *last_requirement != data.source_state.best_finalized_peer_at_best_self { + data.source_state.best_finalized_peer_at_best_self = *last_requirement; + } + } }), Arc::new(move |data: &mut TestClientData| { + // blocks are produced on every tick + data.target_state.best_self = + HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); + data.target_state.best_finalized_self = data.target_state.best_self; // headers relay must only be started when we need new source headers at target node if data.source_to_target_header_required.is_some() { assert!(data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_self.0); data.source_to_target_header_required = None; } - // syncing source headers -> target chain (all at once) - if data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_finalized_self.0 { - data.target_state.best_finalized_peer_at_best_self = data.source_state.best_finalized_self; - } - // syncing source headers -> target chain (all at once) - if data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_finalized_self.0 { - data.source_state.best_finalized_peer_at_best_self = data.target_state.best_finalized_self; - } - // if target has received messages batch => increase blocks so that confirmations may be sent - if data.target_latest_received_nonce == 4 - || data.target_latest_received_nonce == 8 - || data.target_latest_received_nonce == 10 - { - data.target_state.best_self = - HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.0 + 1); - data.target_state.best_finalized_self = data.target_state.best_self; - data.source_state.best_self = - HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.0 + 1); - data.source_state.best_finalized_self = data.source_state.best_self; + // syncing source headers -> target chain + if let Some(last_requirement) = data.source_to_target_header_requirements.last() { + if *last_requirement != data.target_state.best_finalized_peer_at_best_self { + data.target_state.best_finalized_peer_at_best_self = *last_requirement; + } } // if source has received all messages receiving confirmations => stop if data.source_latest_confirmed_received_nonce == 10 { diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 225c59f23ca33..b50b0ffe31ba3 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -292,7 +292,16 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M } fn required_source_header_at_target(&self, current_best: &SourceHeaderIdOf

) -> Option> { - self.strategy.required_source_header_at_target(current_best) + let header_required_for_messages_delivery = self.strategy.required_source_header_at_target(current_best); + let header_required_for_reward_confirmations_delivery = + self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone()); + match ( + header_required_for_messages_delivery, + header_required_for_reward_confirmations_delivery, + ) { + (Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }), + (a, b) => a.or(b), + } } fn best_at_source(&self) -> Option { @@ -876,4 +885,46 @@ mod tests { Some(((20..=23), proof_parameters(true, 4))) ); } + + #[test] + fn source_header_is_requied_when_confirmations_are_required() { + // let's prepare situation when: + // - all messages [20; 23] have been generated at source block#1; + let (mut state, mut strategy) = prepare_strategy(); + // - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because of unrewarded + // relayers vector capacity; + strategy.max_unconfirmed_nonces_at_target = 2; + assert_eq!( + strategy.select_nonces_to_deliver(&state), + Some(((20..=21), proof_parameters(false, 2))) + ); + strategy.finalized_target_nonces_updated( + TargetClientNonces { + latest_nonce: 21, + nonces_data: DeliveryRaceTargetNoncesData { + confirmed_nonce: 19, + unrewarded_relayers: UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + messages_in_oldest_entry: 2, + total_messages: 2, + }, + }, + }, + &mut state, + ); + assert_eq!(strategy.select_nonces_to_deliver(&state), None); + // - messages [1; 10] receiving confirmation has been delivered at source block#2; + strategy.source_nonces_updated( + header_id(2), + SourceClientNonces { + new_nonces: BTreeMap::new(), + confirmed_nonce: Some(21), + }, + ); + // - so now we'll need to relay source block#11 to be able to accept messages [11; 20]. + assert_eq!( + strategy.required_source_header_at_target(&header_id(1)), + Some(header_id(2)) + ); + } } From 2b4fcd1baa2a84f17325870f35af6c4c67267f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 22 Apr 2021 21:05:04 +0200 Subject: [PATCH 0439/1210] Add properties to Chain Spec (#917) * Add properties to chainspec. * Update bin/millau/node/src/chain_spec.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/chain_spec.rs | 13 +++++++++++-- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/chain_spec.rs | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index e31e2c871a508..cbcb2e710c03c 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -12,6 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.1.0" structopt = "0.3.21" +serde_json = "1.0.59" # Bridge dependencies diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index f9e9502da72ba..340b8fd9dffb3 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -67,6 +67,15 @@ pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { impl Alternative { /// Get an actual chain config from one of the alternatives. pub(crate) fn load(self) -> ChainSpec { + let properties = Some( + serde_json::json!({ + "tokenDecimals": 9, + "tokenSymbol": "MLAU", + }) + .as_object() + .expect("Map given; qed") + .clone(), + ); match self { Alternative::Development => ChainSpec::from_genesis( "Development", @@ -88,7 +97,7 @@ impl Alternative { vec![], None, None, - None, + properties, None, ), Alternative::LocalTestnet => ChainSpec::from_genesis( @@ -136,7 +145,7 @@ impl Alternative { vec![], None, None, - None, + properties, None, ), } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index a51ee7a5ab5f2..370985d8ae634 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -12,6 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] jsonrpc-core = "15.1.0" structopt = "0.3.21" +serde_json = "1.0.59" # Bridge dependencies diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 732cf1a4b13a2..fb6dc92bf6d45 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -19,6 +19,7 @@ use rialto_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoAConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; +use serde_json::json; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; @@ -67,6 +68,15 @@ pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { impl Alternative { /// Get an actual chain config from one of the alternatives. pub(crate) fn load(self) -> ChainSpec { + let properties = Some( + json!({ + "tokenDecimals": 9, + "tokenSymbol": "RLT", + }) + .as_object() + .expect("Map given; qed") + .clone(), + ); match self { Alternative::Development => ChainSpec::from_genesis( "Development", @@ -88,7 +98,7 @@ impl Alternative { vec![], None, None, - None, + properties, None, ), Alternative::LocalTestnet => ChainSpec::from_genesis( @@ -136,7 +146,7 @@ impl Alternative { vec![], None, None, - None, + properties, None, ), } From 8c5837bb949e91ebc55d298baadd9a705bedae90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 22 Apr 2021 21:07:55 +0200 Subject: [PATCH 0440/1210] Add pruning to bechmarks & update weights. (#918) * Insert headers in benchmarks. * Fix benchmarks. * Lower number of headers. * Avoid hardcoding numbers. * Update weights. * cargo fmt --all * Remove todo. * Fix test. * Address review comments. * Fix borrowed value. --- bin/rialto/runtime/src/lib.rs | 30 ++++++-- modules/grandpa/src/benchmarking.rs | 29 ++++--- modules/grandpa/src/lib.rs | 60 +++++++++++---- modules/grandpa/src/weights.rs | 50 ++++++------ modules/messages/src/weights.rs | 94 +++++++++++------------ relays/bin-substrate/src/messages_lane.rs | 2 +- 6 files changed, 159 insertions(+), 106 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4e81d3efb1fb1..69fff6b10c3fa 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -409,16 +409,30 @@ impl pallet_session::Config for Runtime { } parameter_types! { - // This is a pretty unscientific cap. - // - // Note that once this is hit the pallet will essentially throttle incoming requests down to one - // call per block. + /// This is a pretty unscientific cap. + /// + /// Note that once this is hit the pallet will essentially throttle incoming requests down to one + /// call per block. pub const MaxRequests: u32 = 50; +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + /// Number of headers to keep in benchmarks. + /// + /// In benchmarks we always populate with full number of `HeadersToKeep` to make sure that + /// pruning is taken into account. + /// + /// Note: This is lower than regular value, to speed up benchmarking setup. + pub const HeadersToKeep: u32 = 1024; +} - // Number of headers to keep. - // - // Assuming the worst case of every header being finalized, we will keep headers at least for a - // week. +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + /// Number of headers to keep. + /// + /// Assuming the worst case of every header being finalized, we will keep headers at least for a + /// week. pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; } diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index cb170fdc8b193..b7294e918003e 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -51,9 +51,10 @@ use bp_test_utils::{ TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, }; use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; +use frame_support::traits::Get; use frame_system::RawOrigin; use sp_finality_grandpa::AuthorityId; -use sp_runtime::traits::{One, Zero}; +use sp_runtime::traits::Zero; use sp_std::{vec, vec::Vec}; // The maximum number of vote ancestries to include in a justification. @@ -66,6 +67,14 @@ const MAX_VOTE_ANCESTRIES: u32 = 1000; // number of validators. const MAX_VALIDATOR_SET_SIZE: u32 = 1024; +/// Returns number of first header to be imported. +/// +/// Since we boostrap the pallet with `HeadersToKeep` already imported headers, +/// this function computes the next expected header number to import. +fn header_number, I: 'static, N: From>() -> N { + (T::HeadersToKeep::get() + 1).into() +} + benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to // annotate the weight in the pallet. @@ -90,9 +99,9 @@ benchmarks_instance_pallet! { is_halted: false, }; - initialize_bridge::(init_data); - let header: BridgedHeader = bp_test_utils::test_header(One::one()); + bootstrap_bridge::(init_data); + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let params = JustificationGeneratorParams { header: header.clone(), round: TEST_GRANDPA_ROUND, @@ -106,7 +115,7 @@ benchmarks_instance_pallet! { }: _(RawOrigin::Signed(caller), header, justification) verify { - let header: BridgedHeader = bp_test_utils::test_header(One::one()); + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let expected_hash = header.hash(); assert_eq!(>::get(), expected_hash); @@ -127,8 +136,8 @@ benchmarks_instance_pallet! { is_halted: false, }; - initialize_bridge::(init_data); - let header: BridgedHeader = bp_test_utils::test_header(One::one()); + bootstrap_bridge::(init_data); + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let params = JustificationGeneratorParams { header: header.clone(), @@ -143,7 +152,7 @@ benchmarks_instance_pallet! { }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) verify { - let header: BridgedHeader = bp_test_utils::test_header(One::one()); + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let expected_hash = header.hash(); assert_eq!(>::get(), expected_hash); @@ -170,8 +179,8 @@ benchmarks_instance_pallet! { is_halted: false, }; - initialize_bridge::(init_data); - let header: BridgedHeader = bp_test_utils::test_header(One::one()); + bootstrap_bridge::(init_data); + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let params = JustificationGeneratorParams { header: header.clone(), @@ -186,7 +195,7 @@ benchmarks_instance_pallet! { }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) verify { - let header: BridgedHeader = bp_test_utils::test_header(One::one()); + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let expected_hash = header.hash(); assert_eq!(>::get(), expected_hash); diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 9fb7372b0204e..80bc8e951aca9 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -158,20 +158,8 @@ pub mod pallet { verify_justification::(&justification, hash, *number, authority_set)?; let _enacted = try_enact_authority_change::(&finality_target, set_id)?; - let index = >::get(); - let pruning = >::try_get(index); - >::put(hash); - >::insert(hash, finality_target); - >::insert(index, hash); >::mutate(|count| *count += 1); - - // Update ring buffer pointer and remove old header. - >::put((index + 1) % T::HeadersToKeep::get()); - if let Ok(hash) = pruning { - log::debug!(target: "runtime::bridge-grandpa", "Pruning old header: {:?}.", hash); - >::remove(hash); - } - + insert_header::(finality_target, hash); log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); Ok(().into()) @@ -427,6 +415,25 @@ pub mod pallet { ) } + /// Import a previously verified header to the storage. + /// + /// Note this function solely takes care of updating the storage and pruning old entries, + /// but does not verify the validaty of such import. + pub(crate) fn insert_header, I: 'static>(header: BridgedHeader, hash: BridgedBlockHash) { + let index = >::get(); + let pruning = >::try_get(index); + >::put(hash); + >::insert(hash, header); + >::insert(index, hash); + + // Update ring buffer pointer and remove old header. + >::put((index + 1) % T::HeadersToKeep::get()); + if let Ok(hash) = pruning { + log::debug!(target: "runtime::bridge-grandpa", "Pruning old header: {:?}.", hash); + >::remove(hash); + } + } + /// Since this writes to storage with no real checks this should only be used in functions that /// were called by a trusted origin. pub(crate) fn initialize_bridge, I: 'static>( @@ -441,8 +448,8 @@ pub mod pallet { let initial_hash = header.hash(); >::put(initial_hash); - >::put(initial_hash); - >::insert(initial_hash, header); + >::put(0); + insert_header::(header, initial_hash); let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); >::put(authority_set); @@ -450,6 +457,29 @@ pub mod pallet { >::put(is_halted); } + #[cfg(feature = "runtime-benchmarks")] + pub(crate) fn bootstrap_bridge, I: 'static>( + init_params: super::InitializationData>, + ) { + let start_number = *init_params.header.number(); + let end_number = start_number + T::HeadersToKeep::get().into(); + initialize_bridge::(init_params); + + let mut number = start_number; + while number < end_number { + number = number + sp_runtime::traits::One::one(); + let header = >::new( + number, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + let hash = header.hash(); + insert_header::(header, hash); + } + } + /// Ensure that the origin is either root, or `PalletOwner`. fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index a548534a20b7e..9e7c2ebc087e8 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-04-14, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-04-21, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -60,29 +60,29 @@ pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn submit_finality_proof(v: u32, p: u32) -> Weight { (0 as Weight) - .saturating_add((837_084_000 as Weight).saturating_mul(v as Weight)) - .saturating_add((874_929_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((756_462_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((791_236_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } fn submit_finality_proof_on_single_fork(v: u32) -> Weight { - (276_463_000 as Weight) - .saturating_add((14_149_000 as Weight).saturating_mul(v as Weight)) + (280_121_000 as Weight) + .saturating_add((14_098_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } fn submit_finality_proof_on_many_forks(p: u32) -> Weight { - (10_676_019_000 as Weight) - .saturating_add((97_598_000 as Weight).saturating_mul(p as Weight)) + (10_370_940_000 as Weight) + .saturating_add((96_902_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) } fn find_scheduled_change(n: u32) -> Weight { - (618_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) + (479_000 as Weight).saturating_add((11_000 as Weight).saturating_mul(n as Weight)) } fn read_write_authority_sets(n: u32) -> Weight { - (8_582_000 as Weight) - .saturating_add((234_000 as Weight).saturating_mul(n as Weight)) + (8_030_000 as Weight) + .saturating_add((232_000 as Weight).saturating_mul(n as Weight)) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -92,29 +92,29 @@ impl WeightInfo for RialtoWeight { impl WeightInfo for () { fn submit_finality_proof(v: u32, p: u32) -> Weight { (0 as Weight) - .saturating_add((837_084_000 as Weight).saturating_mul(v as Weight)) - .saturating_add((874_929_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((756_462_000 as Weight).saturating_mul(v as Weight)) + .saturating_add((791_236_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } fn submit_finality_proof_on_single_fork(v: u32) -> Weight { - (276_463_000 as Weight) - .saturating_add((14_149_000 as Weight).saturating_mul(v as Weight)) + (280_121_000 as Weight) + .saturating_add((14_098_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } fn submit_finality_proof_on_many_forks(p: u32) -> Weight { - (10_676_019_000 as Weight) - .saturating_add((97_598_000 as Weight).saturating_mul(p as Weight)) + (10_370_940_000 as Weight) + .saturating_add((96_902_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } fn find_scheduled_change(n: u32) -> Weight { - (618_000 as Weight).saturating_add((8_000 as Weight).saturating_mul(n as Weight)) + (479_000 as Weight).saturating_add((11_000 as Weight).saturating_mul(n as Weight)) } fn read_write_authority_sets(n: u32) -> Weight { - (8_582_000 as Weight) - .saturating_add((234_000 as Weight).saturating_mul(n as Weight)) + (8_030_000 as Weight) + .saturating_add((232_000 as Weight).saturating_mul(n as Weight)) .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 0eecd0d846237..f86a21e3ed908 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-04-14, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-04-21, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -73,105 +73,105 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (149_497_000 as Weight) + (149_643_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (154_339_000 as Weight) + (153_329_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (200_066_000 as Weight) + (200_113_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (6_432_637_000 as Weight) + (6_407_252_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (141_671_000 as Weight) + (141_256_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (247_393_000 as Weight) + (247_723_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (159_312_000 as Weight) + (159_731_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (167_935_000 as Weight) + (168_546_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (449_846_000 as Weight) + (450_087_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (127_322_000 as Weight) + (164_519_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (134_120_000 as Weight) + (173_300_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (191_193_000 as Weight) + (246_205_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (115_699_000 as Weight) + (149_551_000 as Weight) .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((113_551_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((114_817_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (458_731_000 as Weight) - .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) + (437_797_000 as Weight) + .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (82_314_000 as Weight) + (137_633_000 as Weight) .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (16_766_000 as Weight) - .saturating_add((115_533_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((118_482_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (122_146_000 as Weight) - .saturating_add((6_789_000 as Weight).saturating_mul(i as Weight)) + (116_036_000 as Weight) + .saturating_add((7_118_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (155_671_000 as Weight) - .saturating_add((63_020_000 as Weight).saturating_mul(i as Weight)) + (172_780_000 as Weight) + .saturating_add((63_718_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -182,105 +182,105 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (149_497_000 as Weight) + (149_643_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (154_339_000 as Weight) + (153_329_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (200_066_000 as Weight) + (200_113_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (6_432_637_000 as Weight) + (6_407_252_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (141_671_000 as Weight) + (141_256_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (247_393_000 as Weight) + (247_723_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (159_312_000 as Weight) + (159_731_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (167_935_000 as Weight) + (168_546_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (449_846_000 as Weight) + (450_087_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (127_322_000 as Weight) + (164_519_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (134_120_000 as Weight) + (173_300_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (191_193_000 as Weight) + (246_205_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (115_699_000 as Weight) + (149_551_000 as Weight) .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((113_551_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((114_817_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (458_731_000 as Weight) - .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) + (437_797_000 as Weight) + .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (82_314_000 as Weight) + (137_633_000 as Weight) .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (16_766_000 as Weight) - .saturating_add((115_533_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((118_482_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (122_146_000 as Weight) - .saturating_add((6_789_000 as Weight).saturating_mul(i as Weight)) + (116_036_000 as Weight) + .saturating_add((7_118_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (155_671_000 as Weight) - .saturating_add((63_020_000 as Weight).saturating_mul(i as Weight)) + (172_780_000 as Weight) + .saturating_add((63_718_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 9948b6ec08365..616e2253a6b03 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -203,7 +203,7 @@ mod tests { // reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (1020, 216_583_333_334), + (1013, 216_583_333_334), ); } } From 021f80faf7048c3d0104437e5e10691095112e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 23 Apr 2021 22:00:07 +0200 Subject: [PATCH 0441/1210] Make sure that relayers have dates in logs. (#927) --- relays/bin-substrate/src/cli/mod.rs | 15 +++++++++++++++ relays/bin-substrate/src/main.rs | 3 --- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 505ef11ee2a51..341051de5c279 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -89,8 +89,23 @@ pub enum Command { } impl Command { + // Initialize logger depending on the command. + fn init_logger(&self) { + use relay_utils::initialize::{initialize_logger, initialize_relay}; + + match self { + Self::RelayHeaders(_) | Self::RelayMessages(_) | Self::RelayHeadersAndMessages(_) | Self::InitBridge(_) => { + initialize_relay(); + } + _ => { + initialize_logger(false); + } + } + } + /// Run the command. pub async fn run(self) -> anyhow::Result<()> { + self.init_logger(); match self { Self::RelayHeaders(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?, diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 6bf7561fcdb37..d119042b0d8dc 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -18,8 +18,6 @@ #![warn(missing_docs)] -use relay_utils::initialize::initialize_logger; - mod chains; mod cli; mod finality_pipeline; @@ -31,7 +29,6 @@ mod messages_target; mod on_demand_headers; fn main() { - initialize_logger(false); let command = cli::parse_args(); let run = command.run(); let result = async_std::task::block_on(run); From 2bb20eb58a87c44745dcff2c1be4f5e6a83a1a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 23 Apr 2021 22:01:04 +0200 Subject: [PATCH 0442/1210] Truncate output in logs. (#930) --- modules/dispatch/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 416d080b0c17a..f9649c58c4787 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -314,8 +314,7 @@ impl, I: Instance> MessageDispatch for Pallet { // finally dispatch message let origin = RawOrigin::Signed(origin_account).into(); - - log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:?}", &call); + log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call); let dispatch_result = call.dispatch(origin); let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); From f2bb11154370aaa807dc8437c94a7ccc767c69d3 Mon Sep 17 00:00:00 2001 From: Nikos Kontakis Date: Sun, 25 Apr 2021 16:20:43 +0300 Subject: [PATCH 0443/1210] Update README.md (#931) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8f6446c8875aa..84d776c4f8eff 100644 --- a/README.md +++ b/README.md @@ -126,8 +126,8 @@ both Substrate chains it must be run last. ```bash # In `parity-bridges-common` folder -./deployments/local-scripts/run-rialto-bridge-node.sh -./deployments/local-scripts/run-millau-bridge-node.sh +./deployments/local-scripts/run-rialto-node.sh +./deployments/local-scripts/run-millau-node.sh ./deployments/local-scripts/relay-millau-to-rialto.sh ``` From f28c791bca6c71175bc2197ba276cf2270680d4b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 26 Apr 2021 05:51:34 -0400 Subject: [PATCH 0444/1210] Remove deprecated Runtime Header APIs (#932) --- bin/millau/runtime/src/lib.rs | 1 - primitives/chain-millau/src/lib.rs | 25 ------------------------- primitives/chain-rialto/src/lib.rs | 25 ------------------------- 3 files changed, 51 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 30cf1bd87cd87..7d25eb90c5e1a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -308,7 +308,6 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; - pub const WestendValidatorCount: u32 = 255; // Number of headers to keep. // diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 22f09cb5b0930..a5f3a888f9ad0 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -259,31 +259,6 @@ pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLa pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { - /// API for querying information about Millau headers from the Bridge Pallet instance. - /// - /// This API is implemented by runtimes that are bridging with the Millau chain, not the - /// Millau runtime itself. - pub trait MillauHeaderApi { - /// Returns number and hash of the best blocks known to the bridge module. - /// - /// Will return multiple headers if there are many headers at the same "best" height. - /// - /// The caller should only submit an `import_header` transaction that makes - /// (or leads to making) other header the best one. - fn best_blocks() -> Vec<(BlockNumber, Hash)>; - /// Returns number and hash of the best finalized block known to the bridge module. - fn finalized_block() -> (BlockNumber, Hash); - /// Returns numbers and hashes of headers that require finality proofs. - /// - /// An empty response means that there are no headers which currently require a - /// finality proof. - fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; - /// Returns true if the header is known to the runtime. - fn is_known_block(hash: Hash) -> bool; - /// Returns true if the header is considered finalized by the runtime. - fn is_finalized_block(hash: Hash) -> bool; - } - /// API for querying information about the finalized Millau headers. /// /// This API is implemented by runtimes that are bridging with the Millau chain, not the diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index c10f31bae33f1..c063dc72a7f25 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -220,31 +220,6 @@ pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLa pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { - /// API for querying information about Rialto headers from the Bridge Pallet instance. - /// - /// This API is implemented by runtimes that are bridging with the Rialto chain, not the - /// Rialto runtime itself. - pub trait RialtoHeaderApi { - /// Returns number and hash of the best blocks known to the bridge module. - /// - /// Will return multiple headers if there are many headers at the same "best" height. - /// - /// The caller should only submit an `import_header` transaction that makes - /// (or leads to making) other header the best one. - fn best_blocks() -> Vec<(BlockNumber, Hash)>; - /// Returns number and hash of the best finalized block known to the bridge module. - fn finalized_block() -> (BlockNumber, Hash); - /// Returns numbers and hashes of headers that require finality proofs. - /// - /// An empty response means that there are no headers which currently require a - /// finality proof. - fn incomplete_headers() -> Vec<(BlockNumber, Hash)>; - /// Returns true if the header is known to the runtime. - fn is_known_block(hash: Hash) -> bool; - /// Returns true if the header is considered finalized by the runtime. - fn is_finalized_block(hash: Hash) -> bool; - } - /// API for querying information about the finalized Rialto headers. /// /// This API is implemented by runtimes that are bridging with the Rialto chain, not the From e12dfe91d4a50dd272c863aef3f201026a967223 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 26 Apr 2021 12:52:30 +0300 Subject: [PATCH 0445/1210] Relay at least one header for every source chain session (#923) * relay at least one header for every session * Update relays/bin-substrate/src/on_demand_headers.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- .../src/cli/relay_headers_and_messages.rs | 5 + relays/bin-substrate/src/on_demand_headers.rs | 229 +++++++++++++++--- 2 files changed, 207 insertions(+), 27 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 98ff1268fae9a..f2238ba5763c1 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -96,6 +96,9 @@ macro_rules! select_bridge { type LeftToRightMessages = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; type RightToLeftMessages = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; + use crate::chains::millau_messages_to_rialto::run as left_to_right_messages; use crate::chains::rialto_messages_to_millau::run as right_to_left_messages; @@ -131,11 +134,13 @@ impl RelayHeadersAndMessages { left_client.clone(), right_client.clone(), LeftToRightFinality::new(right_client.clone(), right_sign.clone()), + MAX_MISSING_LEFT_HEADERS_AT_RIGHT, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::new( right_client.clone(), left_client.clone(), RightToLeftFinality::new(left_client.clone(), left_sign.clone()), + MAX_MISSING_RIGHT_HEADERS_AT_LEFT, ); let left_to_right_messages = left_to_right_messages(MessagesRelayParams { diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs index 4c86b6a17018a..d0aff845de384 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -20,13 +20,18 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityT use crate::finality_target::SubstrateFinalityTarget; use bp_header_chain::justification::GrandpaJustification; -use finality_relay::TargetClient as FinalityTargetClient; +use finality_relay::{ + FinalitySyncPipeline, SourceClient as FinalitySourceClient, TargetClient as FinalityTargetClient, +}; use futures::{ channel::{mpsc, oneshot}, select, FutureExt, StreamExt, }; -use num_traits::Zero; -use relay_substrate_client::{BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader}; +use num_traits::{CheckedSub, Zero}; +use relay_substrate_client::{ + finality_source::FinalitySource as SubstrateFinalitySource, BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, + SyncHeader, +}; use relay_utils::{metrics::MetricsParams, BlockNumberBase, HeaderId}; use std::fmt::Debug; @@ -49,6 +54,7 @@ impl OnDemandHeadersRelay { source_client: Client, target_client: Client, pipeline: SubstrateFinalityToSubstrate, + maximal_headers_difference: SourceChain::BlockNumber, ) -> Self where SourceChain: Chain + Debug, @@ -68,7 +74,14 @@ impl OnDemandHeadersRelay { { let (required_header_tx, required_header_rx) = mpsc::channel(1); async_std::task::spawn(async move { - background_task(source_client, target_client, pipeline, required_header_rx).await; + background_task( + source_client, + target_client, + pipeline, + maximal_headers_difference, + required_header_rx, + ) + .await; }); let background_task_name = format!( @@ -100,6 +113,7 @@ async fn background_task( source_client: Client, target_client: Client, pipeline: SubstrateFinalityToSubstrate, + maximal_headers_difference: SourceChain::BlockNumber, mut required_header_rx: mpsc::Receiver>, ) where SourceChain: Chain + Debug, @@ -118,6 +132,10 @@ async fn background_task( FinalityTargetClient>, { let relay_task_name = on_demand_headers_relay_name::(); + let finality_source = SubstrateFinalitySource::< + _, + SubstrateFinalityToSubstrate, + >::new(source_client.clone()); let finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); let mut active_headers_relay = None; @@ -150,30 +168,25 @@ async fn background_task( }, } - // read best finalized source block from target - let available_header_number = match finality_target.best_finalized_source_block_number().await { - Ok(available_header_number) => available_header_number, - Err(error) => { - log::error!( - target: "bridge", - "Failed to read best finalized {} header from {} in {} relay: {:?}", - SourceChain::NAME, - TargetChain::NAME, - relay_task_name, - error, - ); + // read best finalized source header number from source + let best_finalized_source_header_at_source = + best_finalized_source_header_at_source(&finality_source, &relay_task_name).await; - // we don't know what's happening with target client, so better to stop on-demand relay than - // submit unneeded transactions - // => assume that required header is known to the target node - required_header_number - } - }; + // read best finalized source header number from target + let best_finalized_source_header_at_target = + best_finalized_source_header_at_target::(&finality_target, &relay_task_name).await; // start or stop headers relay if required - let activate = required_header_number > available_header_number; - match (activate, active_headers_relay.is_some()) { - (true, false) => { + let action = select_on_demand_relay_action::( + best_finalized_source_header_at_source, + best_finalized_source_header_at_target, + required_header_number, + maximal_headers_difference, + &relay_task_name, + active_headers_relay.is_some(), + ); + match action { + OnDemandRelayAction::Start => { let (relay_exited_tx, new_relay_exited_rx) = oneshot::channel(); active_headers_relay = start_on_demand_headers_relay( relay_task_name.clone(), @@ -186,14 +199,127 @@ async fn background_task( relay_exited_rx = new_relay_exited_rx.right_future(); } } - (false, true) => { + OnDemandRelayAction::Stop => { stop_on_demand_headers_relay(active_headers_relay.take()).await; } - _ => (), + OnDemandRelayAction::None => (), } } } +/// Read best finalized source block number from source client. +/// +/// Returns `None` if we have failed to read the number. +async fn best_finalized_source_header_at_source( + finality_source: &SubstrateFinalitySource, + relay_task_name: &str, +) -> Option +where + SubstrateFinalitySource: FinalitySourceClient

, + P: FinalitySyncPipeline, +{ + finality_source + .best_finalized_block_number() + .await + .map(Some) + .unwrap_or_else(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from source in {} relay: {:?}", + relay_task_name, + error, + ); + + None + }) +} + +/// Read best finalized source block number from target client. +/// +/// Returns `None` if we have failed to read the number. +async fn best_finalized_source_header_at_target( + finality_target: &SubstrateFinalityTarget, + relay_task_name: &str, +) -> Option +where + SubstrateFinalityTarget: FinalityTargetClient

, + P: FinalitySyncPipeline, +{ + finality_target + .best_finalized_source_block_number() + .await + .map(Some) + .unwrap_or_else(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from target in {} relay: {:?}", + relay_task_name, + error, + ); + + None + }) +} + +/// What to do with the on-demand relay task? +#[derive(Debug, PartialEq)] +enum OnDemandRelayAction { + Start, + Stop, + None, +} + +fn select_on_demand_relay_action( + best_finalized_source_header_at_source: Option, + best_finalized_source_header_at_target: Option, + mut required_source_header_at_target: C::BlockNumber, + maximal_headers_difference: C::BlockNumber, + relay_task_name: &str, + is_active: bool, +) -> OnDemandRelayAction { + // if we have been unable to read header number from the target, then let's assume + // that it is the same as required header number. Otherwise we risk submitting + // unneeded transactions + let best_finalized_source_header_at_target = + best_finalized_source_header_at_target.unwrap_or(required_source_header_at_target); + + // if we have been unable to read header number from the source, then let's assume + // that it is the same as at the target + let best_finalized_source_header_at_source = + best_finalized_source_header_at_source.unwrap_or(best_finalized_source_header_at_target); + + // if there are too many source headers missing from the target node, require some + // new headers at target + // + // why do we need that? When complex headers+messages relay is used, it'll normally only relay + // headers when there are undelivered messages/confirmations. But security model of the + // `pallet-bridge-grandpa` module relies on the fact that headers are synced in real-time and + // that it'll see authorities-change header before unbonding period will end for previous + // authorities set. + let current_headers_difference = best_finalized_source_header_at_source + .checked_sub(&best_finalized_source_header_at_target) + .unwrap_or_else(Zero::zero); + if current_headers_difference > maximal_headers_difference { + log::trace!( + target: "bridge", + "Too many {} headers missing at target in {} relay. Going to sync up to the {}", + C::NAME, + relay_task_name, + best_finalized_source_header_at_source, + ); + + required_source_header_at_target = best_finalized_source_header_at_source; + } + + // now let's select what to do with relay + let needs_to_be_active = required_source_header_at_target > best_finalized_source_header_at_target; + match (needs_to_be_active, is_active) { + (true, false) => OnDemandRelayAction::Start, + (false, true) => OnDemandRelayAction::Stop, + _ => OnDemandRelayAction::None, + } +} + /// On-demand headers relay task name. fn on_demand_headers_relay_name() -> String { format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) @@ -253,3 +379,52 @@ async fn stop_on_demand_headers_relay(task: Option = Some(10); + const AT_TARGET: Option = Some(1); + + #[test] + fn starts_relay_when_headers_are_required() { + assert_eq!( + select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 5, 100, "test", false), + OnDemandRelayAction::Start, + ); + + assert_eq!( + select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 5, 100, "test", true), + OnDemandRelayAction::None, + ); + } + + #[test] + fn starts_relay_when_too_many_headers_missing() { + assert_eq!( + select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 0, 5, "test", false), + OnDemandRelayAction::Start, + ); + + assert_eq!( + select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 0, 5, "test", true), + OnDemandRelayAction::None, + ); + } + + #[test] + fn stops_relay_if_required_header_is_synced() { + assert_eq!( + select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, AT_TARGET.unwrap(), 100, "test", true), + OnDemandRelayAction::Stop, + ); + + assert_eq!( + select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, AT_TARGET.unwrap(), 100, "test", false), + OnDemandRelayAction::None, + ); + } +} From acd7d1f9ffe28c5dfa62f3646a4ec4d672fb4d41 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 26 Apr 2021 16:05:02 +0300 Subject: [PATCH 0446/1210] Do not spawn additional task for on-demand relays (#933) * do not spawn additional task for on-demand relays * compilation --- relays/bin-substrate/src/cli/relay_headers.rs | 1 + relays/bin-substrate/src/finality_pipeline.rs | 2 ++ relays/bin-substrate/src/on_demand_headers.rs | 23 +++++++++------ relays/finality/src/finality_loop.rs | 3 ++ relays/finality/src/finality_loop_tests.rs | 1 + relays/utils/src/relay_loop.rs | 28 +++++++++++++++++-- 6 files changed, 46 insertions(+), 12 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 346790f2ae74e..cbcbbf8926286 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -102,6 +102,7 @@ impl RelayHeaders { Finality::new(target_client.clone(), target_sign), source_client, target_client, + false, metrics_params, ) .await diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index 9538f35778dcb..dad69b1576b0e 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -112,6 +112,7 @@ pub async fn run( pipeline: P, source_client: Client, target_client: Client, + is_on_demand_task: bool, metrics_params: MetricsParams, ) -> anyhow::Result<()> where @@ -137,6 +138,7 @@ where FinalitySource::new(source_client), SubstrateFinalityTarget::new(target_client, pipeline), FinalitySyncParams { + is_on_demand_task, tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs index d0aff845de384..3b65ac7068c3c 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -300,15 +300,20 @@ fn select_on_demand_relay_action( .checked_sub(&best_finalized_source_header_at_target) .unwrap_or_else(Zero::zero); if current_headers_difference > maximal_headers_difference { - log::trace!( - target: "bridge", - "Too many {} headers missing at target in {} relay. Going to sync up to the {}", - C::NAME, - relay_task_name, - best_finalized_source_header_at_source, - ); - required_source_header_at_target = best_finalized_source_header_at_source; + + // don't log if relay is already running + if !is_active { + log::trace!( + target: "bridge", + "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the {}", + C::NAME, + relay_task_name, + best_finalized_source_header_at_source, + best_finalized_source_header_at_target, + best_finalized_source_header_at_source, + ); + } } // now let's select what to do with relay @@ -345,7 +350,7 @@ where TargetSign: 'static, { let headers_relay_future = - crate::finality_pipeline::run(pipeline, source_client, target_client, MetricsParams::disabled()); + crate::finality_pipeline::run(pipeline, source_client, target_client, true, MetricsParams::disabled()); let closure_task_name = task_name.clone(); async_std::task::Builder::new() .name(task_name.clone()) diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index cce32839907d9..3aa55a8ac5915 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -39,6 +39,8 @@ use std::{ /// Finality proof synchronization loop parameters. #[derive(Debug, Clone)] pub struct FinalitySyncParams { + /// If `true`, then the separate async task for running finality loop is NOT spawned. + pub is_on_demand_task: bool, /// Interval at which we check updates on both clients. Normally should be larger than /// `min(source_block_time, target_block_time)`. /// @@ -105,6 +107,7 @@ pub async fn run( ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) + .spawn_loop_task(!sync_params.is_on_demand_task) .with_metrics(Some(metrics_prefix::

()), metrics_params) .loop_metric(|registry, prefix| SyncLoopMetrics::new(registry, prefix))? .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index f7826ead730c9..645aeb1777c60 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -197,6 +197,7 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync data: clients_data.clone(), }; let sync_params = FinalitySyncParams { + is_on_demand_task: false, tick: Duration::from_secs(0), recent_finality_proofs_limit: 1024, stall_timeout: Duration::from_secs(1), diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index ea2e7623ee223..46cd242ce1fdd 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -38,6 +38,7 @@ pub trait Client: 'static + Clone + Send + Sync { pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { Loop { reconnect_delay: RECONNECT_DELAY, + spawn_loop_task: true, source_client, target_client, loop_metric: None, @@ -49,6 +50,7 @@ pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetri LoopMetrics { relay_loop: Loop { reconnect_delay: RECONNECT_DELAY, + spawn_loop_task: true, source_client: (), target_client: (), loop_metric: None, @@ -63,6 +65,7 @@ pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetri /// Generic relay loop. pub struct Loop { reconnect_delay: Duration, + spawn_loop_task: bool, source_client: SC, target_client: TC, loop_metric: Option, @@ -84,11 +87,23 @@ impl Loop { self } + /// Set spawn-dedicated-loop-task flag. + /// + /// If `true` (default), separate async task is spawned to run relay loop. This is the default + /// behavior for all loops. If `false`, then loop is executed as a part of the current + /// task. The `false` is used for on-demand tasks, which are cancelled from time to time + /// and there's already a dedicated on-demand task for running such loops. + pub fn spawn_loop_task(mut self, spawn_loop_task: bool) -> Self { + self.spawn_loop_task = spawn_loop_task; + self + } + /// Start building loop metrics using given prefix. pub fn with_metrics(self, prefix: Option, params: MetricsParams) -> LoopMetrics { LoopMetrics { relay_loop: Loop { reconnect_delay: self.reconnect_delay, + spawn_loop_task: self.spawn_loop_task, source_client: self.source_client, target_client: self.target_client, loop_metric: None, @@ -113,7 +128,8 @@ impl Loop { TC: 'static + Client, LM: 'static + Send + Clone, { - async_std::task::spawn(async move { + let spawn_loop_task = self.spawn_loop_task; + let run_loop_task = async move { crate::initialize::initialize_loop(loop_name); loop { @@ -162,8 +178,13 @@ impl Loop { } Ok(()) - }) - .await + }; + + if spawn_loop_task { + async_std::task::spawn(run_loop_task).await + } else { + run_loop_task.await + } } } @@ -239,6 +260,7 @@ impl LoopMetrics { Ok(Loop { reconnect_delay: self.relay_loop.reconnect_delay, + spawn_loop_task: self.relay_loop.spawn_loop_task, source_client: self.relay_loop.source_client, target_client: self.relay_loop.target_client, loop_metric: self.loop_metric, From b2ea03039498afd3e6bb2a70502c85cb16395955 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 27 Apr 2021 16:33:28 +0300 Subject: [PATCH 0447/1210] reonnect to failed client in on-demand relay background task (#936) --- relays/bin-substrate/src/on_demand_headers.rs | 64 +++++++++----- relays/utils/src/relay_loop.rs | 84 +++++++++++-------- 2 files changed, 92 insertions(+), 56 deletions(-) diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs index 3b65ac7068c3c..77d2b37054104 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -32,7 +32,10 @@ use relay_substrate_client::{ finality_source::FinalitySource as SubstrateFinalitySource, BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader, }; -use relay_utils::{metrics::MetricsParams, BlockNumberBase, HeaderId}; +use relay_utils::{ + metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, HeaderId, + MaybeConnectionError, +}; use std::fmt::Debug; /// On-demand Substrate <-> Substrate headers relay. @@ -132,11 +135,11 @@ async fn background_task( FinalityTargetClient>, { let relay_task_name = on_demand_headers_relay_name::(); - let finality_source = SubstrateFinalitySource::< + let mut finality_source = SubstrateFinalitySource::< _, SubstrateFinalityToSubstrate, >::new(source_client.clone()); - let finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); + let mut finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); let mut active_headers_relay = None; let mut required_header_number = Zero::zero(); @@ -171,15 +174,35 @@ async fn background_task( // read best finalized source header number from source let best_finalized_source_header_at_source = best_finalized_source_header_at_source(&finality_source, &relay_task_name).await; + if matches!(best_finalized_source_header_at_source, Err(ref e) if e.is_connection_error()) { + relay_utils::relay_loop::reconnect_failed_client( + FailedClient::Source, + relay_utils::relay_loop::RECONNECT_DELAY, + &mut finality_source, + &mut finality_target, + ) + .await; + continue; + } // read best finalized source header number from target let best_finalized_source_header_at_target = best_finalized_source_header_at_target::(&finality_target, &relay_task_name).await; + if matches!(best_finalized_source_header_at_target, Err(ref e) if e.is_connection_error()) { + relay_utils::relay_loop::reconnect_failed_client( + FailedClient::Target, + relay_utils::relay_loop::RECONNECT_DELAY, + &mut finality_source, + &mut finality_target, + ) + .await; + continue; + } // start or stop headers relay if required let action = select_on_demand_relay_action::( - best_finalized_source_header_at_source, - best_finalized_source_header_at_target, + best_finalized_source_header_at_source.ok(), + best_finalized_source_header_at_target.ok(), required_header_number, maximal_headers_difference, &relay_task_name, @@ -213,25 +236,21 @@ async fn background_task( async fn best_finalized_source_header_at_source( finality_source: &SubstrateFinalitySource, relay_task_name: &str, -) -> Option +) -> Result as RelayClient>::Error> where SubstrateFinalitySource: FinalitySourceClient

, P: FinalitySyncPipeline, { - finality_source - .best_finalized_block_number() - .await - .map(Some) - .unwrap_or_else(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from source in {} relay: {:?}", - relay_task_name, - error, - ); + finality_source.best_finalized_block_number().await.map_err(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from source in {} relay: {:?}", + relay_task_name, + error, + ); - None - }) + error + }) } /// Read best finalized source block number from target client. @@ -240,7 +259,7 @@ where async fn best_finalized_source_header_at_target( finality_target: &SubstrateFinalityTarget, relay_task_name: &str, -) -> Option +) -> Result as RelayClient>::Error> where SubstrateFinalityTarget: FinalityTargetClient

, P: FinalitySyncPipeline, @@ -248,8 +267,7 @@ where finality_target .best_finalized_source_block_number() .await - .map(Some) - .unwrap_or_else(|error| { + .map_err(|error| { log::error!( target: "bridge", "Failed to read best finalized source header from target in {} relay: {:?}", @@ -257,7 +275,7 @@ where error, ); - None + error }) } diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 46cd242ce1fdd..8fcaabe4430cc 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -139,39 +139,15 @@ impl Loop { match result { Ok(()) => break, - Err(failed_client) => loop { - async_std::task::sleep(self.reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - match self.source_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to source client. Going to retry in {}s: {:?}", - self.reconnect_delay.as_secs(), - error, - ); - continue; - } - } - } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - match self.target_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to target client. Going to retry in {}s: {:?}", - self.reconnect_delay.as_secs(), - error, - ); - continue; - } - } - } - - break; - }, + Err(failed_client) => { + reconnect_failed_client( + failed_client, + self.reconnect_delay, + &mut self.source_client, + &mut self.target_client, + ) + .await + } } log::debug!(target: "bridge", "Restarting relay loop"); @@ -268,6 +244,48 @@ impl LoopMetrics { } } +/// Deal with the client who has returned connection error. +pub async fn reconnect_failed_client( + failed_client: FailedClient, + reconnect_delay: Duration, + source_client: &mut impl Client, + target_client: &mut impl Client, +) { + loop { + async_std::task::sleep(reconnect_delay).await; + if failed_client == FailedClient::Both || failed_client == FailedClient::Source { + match source_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to source client. Going to retry in {}s: {:?}", + reconnect_delay.as_secs(), + error, + ); + continue; + } + } + } + if failed_client == FailedClient::Both || failed_client == FailedClient::Target { + match target_client.reconnect().await { + Ok(()) => (), + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to target client. Going to retry in {}s: {:?}", + reconnect_delay.as_secs(), + error, + ); + continue; + } + } + } + + break; + } +} + /// Create new registry with global metrics. fn create_metrics_registry(prefix: Option) -> Registry { match prefix { From 04a7bddf504c07dd0e959b85075a2db3ed9097c9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 27 Apr 2021 19:24:00 +0300 Subject: [PATCH 0448/1210] jsonrpsee alpha6 (#938) --- relays/client-ethereum/Cargo.toml | 4 ++-- relays/client-substrate/Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index ebae252ed5ab3..da4e7ef59efee 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -10,8 +10,8 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = "=0.2.0-alpha.5" -jsonrpsee-ws-client = "=0.2.0-alpha.5" +jsonrpsee-proc-macros = "=0.2.0-alpha.6" +jsonrpsee-ws-client = "=0.2.0-alpha.6" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 7b3f46230fce1..699c3da400ffe 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,8 +9,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = "1.6.5" async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } -jsonrpsee-proc-macros = "=0.2.0-alpha.5" -jsonrpsee-ws-client = "=0.2.0-alpha.5" +jsonrpsee-proc-macros = "=0.2.0-alpha.6" +jsonrpsee-ws-client = "=0.2.0-alpha.6" log = "0.4.11" num-traits = "0.2" rand = "0.7" From 333fc426f2fb84065f7f240e68b58a812e4e5208 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 27 Apr 2021 16:47:37 -0400 Subject: [PATCH 0449/1210] Bump Substrate (#939) * Bump Substrate to `0856e072` * Fix compilation errors --- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/src/messages.rs | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index a800117dc5518..736301016fa30 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -31,7 +31,7 @@ use frame_support::{ weights::{DispatchClass, Weight}, RuntimeDebug, }; -use sp_runtime::{FixedPointNumber, FixedU128}; +use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Initial value of `RialtoToMillauConversionRate` parameter. diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 8ee2094660c10..77b73c07857b0 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -31,7 +31,7 @@ use frame_support::{ weights::{DispatchClass, Weight}, RuntimeDebug, }; -use sp_runtime::{FixedPointNumber, FixedU128}; +use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Initial value of `MillauToRialtoConversionRate` parameter. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 8e83c0f94ada4..54e8b30031a44 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -1407,6 +1407,8 @@ mod tests { #[test] fn transaction_payment_works_with_zero_multiplier() { + use sp_runtime::traits::Zero; + assert_eq!( transaction_payment( 100, @@ -1424,6 +1426,8 @@ mod tests { #[test] fn transaction_payment_works_with_non_zero_multiplier() { + use sp_runtime::traits::One; + assert_eq!( transaction_payment( 100, From 5949c31923d8fc739e9b68d31516afcf8909468a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Apr 2021 13:55:58 +0300 Subject: [PATCH 0450/1210] do not panic if pallet is not yet initialized (#937) --- modules/grandpa/src/lib.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 80bc8e951aca9..d38f61826f98c 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -42,7 +42,7 @@ use bp_header_chain::justification::GrandpaJustification; use bp_header_chain::InitializationData; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use finality_grandpa::voter_set::VoterSet; -use frame_support::ensure; +use frame_support::{ensure, fail}; use frame_system::{ensure_signed, RawOrigin}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; @@ -143,11 +143,17 @@ pub mod pallet { let (hash, number) = (finality_target.hash(), finality_target.number()); log::trace!(target: "runtime::bridge-grandpa", "Going to try and finalize header {:?}", finality_target); - let best_finalized = >::get(>::get()).expect( - "In order to reach this point the bridge must have been initialized. Afterwards, - every time `BestFinalized` is updated `ImportedHeaders` is also updated. Therefore - `ImportedHeaders` must contain an entry for `BestFinalized`.", - ); + let best_finalized = match >::get(>::get()) { + Some(best_finalized) => best_finalized, + None => { + log::error!( + target: "runtime::bridge-grandpa", + "Cannot finalize header {:?} because pallet is not yet initialized", + finality_target, + ); + fail!(>::NotInitialized); + } + }; // We do a quick check here to ensure that our header chain is making progress and isn't // "travelling back in time" (which could be indicative of something bad, e.g a hard-fork). @@ -334,6 +340,8 @@ pub mod pallet { /// /// This is the case for non-standard (e.g forced) authority set changes. UnsupportedScheduledChange, + /// The pallet is not yet initialized. + NotInitialized, /// The pallet has already been initialized. AlreadyInitialized, /// All pallet operations are halted. @@ -767,6 +775,13 @@ mod tests { }) } + #[test] + fn pallet_rejects_header_if_not_initialized_yet() { + run_test(|| { + assert_noop!(submit_finality_proof(1), Error::::NotInitialized); + }); + } + #[test] fn succesfully_imports_header_with_valid_finality() { run_test(|| { From 072d863b3ea9301c98b0d0a3dd3e4291f477473f Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Wed, 28 Apr 2021 12:08:55 -0400 Subject: [PATCH 0451/1210] Remove Westend<>Rococo header sync (#940) * Remove scripts for Westend<>Rococo header sync * Remove Westend<>Rococo header sync code * Remove Westend<>Rococo init bridge CLI option * Modify Westend mock call to be placeholder * Fix call encoding test --- primitives/chain-rococo/src/lib.rs | 13 +--- relays/bin-substrate/src/chains/mod.rs | 4 +- .../src/chains/rococo_headers_to_westend.rs | 60 ------------------- .../src/chains/westend_headers_to_rococo.rs | 60 ------------------- relays/bin-substrate/src/cli/init_bridge.rs | 26 -------- relays/bin-substrate/src/cli/relay_headers.rs | 16 ----- 6 files changed, 4 insertions(+), 175 deletions(-) delete mode 100644 relays/bin-substrate/src/chains/rococo_headers_to_westend.rs delete mode 100644 relays/bin-substrate/src/chains/westend_headers_to_rococo.rs diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index b79fdf6cfcf01..268ee3cae1502 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -55,14 +55,14 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - /// Westend bridge pallet. + /// Generic bridge pallet. #[codec(index = 40)] - BridgeGrandpaWestend(BridgeGrandpaWestendCall), + BridgeCall(BridgeGrandpaCall), } #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] #[allow(non_camel_case_types)] -pub enum BridgeGrandpaWestendCall { +pub enum BridgeGrandpaCall { #[codec(index = 0)] submit_finality_proof( ::Header, @@ -83,13 +83,6 @@ impl sp_runtime::traits::Dispatchable for Call { } } -// We use this to get the account on Rococo (target) which is derived from Westend's (source) -// account. -pub fn derive_account_from_westend_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::WESTEND_BRIDGE_INSTANCE, id); - AccountIdConverter::convert(encoded_id) -} - /// Name of the `RococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; /// Name of the `RococoFinalityApi::is_known_header` runtime method. diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 9e6a7361d5fdf..2000c4c223da1 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -20,9 +20,7 @@ pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; -pub mod rococo_headers_to_westend; pub mod westend_headers_to_millau; -pub mod westend_headers_to_rococo; mod millau; mod rialto; @@ -270,7 +268,7 @@ mod rococo_tests { votes_ancestries: vec![], }; - let actual = bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof(header.clone(), justification.clone()); + let actual = bp_rococo::BridgeGrandpaCall::submit_finality_proof(header.clone(), justification.clone()); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, justification, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_westend.rs b/relays/bin-substrate/src/chains/rococo_headers_to_westend.rs deleted file mode 100644 index dca91adb3df68..0000000000000 --- a/relays/bin-substrate/src/chains/rococo_headers_to_westend.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 . - -//! Rococo-to-Westend headers sync entrypoint. - -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; - -use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; -use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Chain, TransactionSignScheme}; -use relay_utils::metrics::MetricsParams; -use relay_westend_client::{SigningParams as WestendSigningParams, Westend}; -use sp_core::{Bytes, Pair}; - -/// Rococo-to-Westend finality sync pipeline. -pub(crate) type RococoFinalityToWestend = SubstrateFinalityToSubstrate; - -impl SubstrateFinalitySyncPipeline for RococoFinalityToWestend { - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - - type TargetChain = Westend; - - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn transactions_author(&self) -> bp_westend::AccountId { - (*self.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - transaction_nonce: ::Index, - header: RococoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = bp_westend::Call::BridgeGrandpaRococo(bp_westend::BridgeGrandpaRococoCall::submit_finality_proof( - header.into_inner(), - proof, - )); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Westend::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); - - Bytes(transaction.encode()) - } -} diff --git a/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs b/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs deleted file mode 100644 index 577a858d92290..0000000000000 --- a/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 . - -//! Westend-to-Rococo headers sync entrypoint. - -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; - -use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; -use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; -use relay_utils::metrics::MetricsParams; -use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; -use sp_core::{Bytes, Pair}; - -/// Westend-to-Rococo finality sync pipeline. -pub(crate) type WestendFinalityToRococo = SubstrateFinalityToSubstrate; - -impl SubstrateFinalitySyncPipeline for WestendFinalityToRococo { - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; - - type TargetChain = Rococo; - - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn transactions_author(&self) -> bp_rococo::AccountId { - (*self.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - transaction_nonce: ::Index, - header: WestendSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaWestendCall::submit_finality_proof( - header.into_inner(), - proof, - )); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); - - Bytes(transaction.encode()) - } -} diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index cdd8ec369161d..73af141a36c58 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -44,8 +44,6 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, - WestendToRococo, - RococoToWestend, } } @@ -100,30 +98,6 @@ macro_rules! select_bridge { .into() } - $generic - } - InitBridgeName::WestendToRococo => { - type Source = relay_westend_client::Westend; - type Target = relay_rococo_client::Rococo; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaWestendCall::initialize(init_data)) - } - - $generic - } - InitBridgeName::RococoToWestend => { - type Source = relay_rococo_client::Rococo; - type Target = relay_westend_client::Westend; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - bp_westend::Call::BridgeGrandpaRococo(bp_westend::BridgeGrandpaRococoCall::initialize(init_data)) - } - $generic } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index cbcbbf8926286..1385527d976e4 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -42,8 +42,6 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, - WestendToRococo, - RococoToWestend, } } @@ -69,20 +67,6 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; - $generic - } - RelayHeadersBridge::WestendToRococo => { - type Source = relay_westend_client::Westend; - type Target = relay_rococo_client::Rococo; - type Finality = crate::chains::westend_headers_to_rococo::WestendFinalityToRococo; - - $generic - } - RelayHeadersBridge::RococoToWestend => { - type Source = relay_rococo_client::Rococo; - type Target = relay_westend_client::Westend; - type Finality = crate::chains::rococo_headers_to_westend::RococoFinalityToWestend; - $generic } } From 38067bd7246ddd9e48bfaa8d64b0bd6c16d79e4a Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 29 Apr 2021 11:24:30 -0400 Subject: [PATCH 0452/1210] Add Wococo<>Rococo Header Relayer (#925) * Add Wococo primitives crate * Add more Wococo boilerplate code * Add CLI support for initializing the Wococo<>Rococo bridge * Add support for relaying headers between Rococo and Wococo * Fix test * RustFmt * Fix compilation issues related to enum naming * Bump Rococo `spec_version` * Remove stray Westend references --- primitives/chain-rococo/src/lib.rs | 10 +- primitives/chain-wococo/Cargo.toml | 36 ++++ primitives/chain-wococo/src/lib.rs | 172 ++++++++++++++++++ primitives/runtime/src/lib.rs | 4 +- relays/bin-substrate/Cargo.toml | 2 + relays/bin-substrate/src/chains/mod.rs | 5 +- .../src/chains/rococo_headers_to_wococo.rs | 60 ++++++ .../src/chains/westend_headers_to_rococo.rs | 60 ++++++ relays/bin-substrate/src/chains/wococo.rs | 39 ++++ .../src/chains/wococo_headers_to_rococo.rs | 60 ++++++ relays/bin-substrate/src/cli/init_bridge.rs | 26 +++ relays/bin-substrate/src/cli/relay_headers.rs | 16 ++ relays/client-wococo/Cargo.toml | 23 +++ relays/client-wococo/src/lib.rs | 97 ++++++++++ 14 files changed, 602 insertions(+), 8 deletions(-) create mode 100644 primitives/chain-wococo/Cargo.toml create mode 100644 primitives/chain-wococo/src/lib.rs create mode 100644 relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs create mode 100644 relays/bin-substrate/src/chains/westend_headers_to_rococo.rs create mode 100644 relays/bin-substrate/src/chains/wococo.rs create mode 100644 relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs create mode 100644 relays/client-wococo/Cargo.toml create mode 100644 relays/client-wococo/src/lib.rs diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 268ee3cae1502..66cbb475bda2d 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), authoring_version: 0, - spec_version: 231, + spec_version: 232, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, @@ -55,14 +55,14 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { - /// Generic bridge pallet. - #[codec(index = 40)] - BridgeCall(BridgeGrandpaCall), + /// Wococo bridge pallet. + #[codec(index = 41)] + BridgeGrandpaWococo(BridgeGrandpaWococoCall), } #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] #[allow(non_camel_case_types)] -pub enum BridgeGrandpaCall { +pub enum BridgeGrandpaWococoCall { #[codec(index = 0)] submit_finality_proof( ::Header, diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml new file mode 100644 index 0000000000000..ecf783a51eeb9 --- /dev/null +++ b/primitives/chain-wococo/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "bp-wococo" +description = "Primitives of Wococo runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } + +# Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Based Dependencies +sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-header-chain/std", + "bp-messages/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "parity-scale-codec/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", + "sp-version/std", +] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs new file mode 100644 index 0000000000000..f7a472ddf31df --- /dev/null +++ b/primitives/chain-wococo/src/lib.rs @@ -0,0 +1,172 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_with_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::Chain; +use sp_std::prelude::*; +use sp_version::RuntimeVersion; + +pub use bp_polkadot_core::*; + +/// Wococo Chain +pub type Wococo = PolkadotLike; + +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("rococo"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), + authoring_version: 0, + spec_version: 232, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 0, +}; + +/// Wococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// Rococo bridge pallet. + #[codec(index = 40)] + BridgeGrandpaRococo(BridgeGrandpaRococoCall), +} + +#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaRococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} + +// We use this to get the account on Wococo (target) which is derived from Rococo's (source) +// account. +pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_BRIDGE_INSTANCE, id); + AccountIdConverter::convert(encoded_id) +} + +/// Name of the `WococoFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; +/// Name of the `WococoFinalityApi::is_known_header` runtime method. +pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_header"; + +/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToWococoOutboundLaneApi::messages_dispatch_weight` runtime method. +pub const TO_WOCOCO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToWococoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToWococoOutboundLaneApi::latest_generated_nonce` runtime method. +pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_generated_nonce"; +/// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method. +pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_received_nonce"; + +/// Name of the `FromWococoInboundLaneApi::latest_received_nonce` runtime method. +pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_received_nonce"; +/// Name of the `FromWococoInboundLaneApi::latest_onfirmed_nonce` runtime method. +pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_confirmed_nonce"; +/// Name of the `FromWococoInboundLaneApi::unrewarded_relayers_state` runtime method. +pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromWococoInboundLaneApi_unrewarded_relayers_state"; + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized Wococo headers. + /// + /// This API is implemented by runtimes that are bridging with the Wococo chain, not the + /// Wococo runtime itself. + pub trait WococoFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + /// Returns true if the header is known to the runtime. + fn is_known_header(hash: Hash) -> bool; + } + + /// Outbound message lane API for messages that are sent to Wococo chain. + /// + /// This API is implemented by runtimes that are sending messages to Wococo chain, not the + /// Wococo runtime itself. + pub trait ToWococoOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Wococo from this chain. + /// + /// Please keep in mind that this method returns lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; + /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn messages_dispatch_weight( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec<(MessageNonce, Weight, u32)>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Wococo chain. + /// + /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the + /// Wococo runtime itself. + pub trait FromWococoInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index e7f990d283096..aa457f1d0b0bc 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -50,8 +50,8 @@ 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"; +/// Bridge-with-Wococo instance id. +pub const WOCOCO_BRIDGE_INSTANCE: InstanceId = *b"woco"; /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index d203201e60a44..f5711e0766d1c 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -27,6 +27,7 @@ bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } +bp-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } @@ -42,6 +43,7 @@ relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } relay-rialto-client = { path = "../client-rialto" } relay-rococo-client = { path = "../client-rococo" } +relay-wococo-client = { path = "../client-wococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 2000c4c223da1..20ddf4a92af1b 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -20,12 +20,15 @@ pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; +pub mod rococo_headers_to_wococo; pub mod westend_headers_to_millau; +pub mod wococo_headers_to_rococo; mod millau; mod rialto; mod rococo; mod westend; +mod wococo; use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; @@ -268,7 +271,7 @@ mod rococo_tests { votes_ancestries: vec![], }; - let actual = bp_rococo::BridgeGrandpaCall::submit_finality_proof(header.clone(), justification.clone()); + let actual = bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(header.clone(), justification.clone()); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, justification, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs new file mode 100644 index 0000000000000..5247c6068b5ec --- /dev/null +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Rococo-to-Wococo headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; +use sp_core::{Bytes, Pair}; + +/// Rococo-to-Wococo finality sync pipeline. +pub(crate) type RococoFinalityToWococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + + type TargetChain = Wococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_wococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: RococoSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs b/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs new file mode 100644 index 0000000000000..f1b390215748d --- /dev/null +++ b/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Westend-to-Rococo headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; +use sp_core::{Bytes, Pair}; + +/// Westend-to-Rococo finality sync pipeline. +pub(crate) type WestendFinalityToRococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for WestendFinalityToRococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; + + type TargetChain = Rococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_rococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: WestendSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs new file mode 100644 index 0000000000000..549aa8a882c75 --- /dev/null +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -0,0 +1,39 @@ +// 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 . + +use crate::cli::{encode_message, CliChain}; +use frame_support::weights::Weight; +use relay_wococo_client::Wococo; +use sp_version::RuntimeVersion; + +impl CliChain for Wococo { + const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + 0 + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Wococo is not yet supported.".into()) + } +} diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs new file mode 100644 index 0000000000000..9dfae5294e292 --- /dev/null +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -0,0 +1,60 @@ +// 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 . + +//! Wococo-to-Rococo headers sync entrypoint. + +use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; +use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; +use sp_core::{Bytes, Pair}; + +/// Wococo-to-Rococo finality sync pipeline. +pub(crate) type WococoFinalityToRococo = SubstrateFinalityToSubstrate; + +impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + + type TargetChain = Rococo; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::add_polkadot_kusama_price_metrics::(params) + } + + fn transactions_author(&self) -> bp_rococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + transaction_nonce: ::Index, + header: WococoSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof( + header.into_inner(), + proof, + )); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + + Bytes(transaction.encode()) + } +} diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 73af141a36c58..b5590b9e5a445 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -44,6 +44,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + RococoToWococo, + WococoToRococo, } } @@ -98,6 +100,30 @@ macro_rules! select_bridge { .into() } + $generic + } + InitBridgeName::RococoToWococo => { + type Source = relay_rococo_client::Rococo; + type Target = relay_wococo_client::Wococo; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::initialize(init_data)) + } + + $generic + } + InitBridgeName::WococoToRococo => { + type Source = relay_wococo_client::Wococo; + type Target = relay_rococo_client::Rococo; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::initialize(init_data)) + } + $generic } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 1385527d976e4..e8459b58bf605 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -42,6 +42,8 @@ arg_enum! { MillauToRialto, RialtoToMillau, WestendToMillau, + RococoToWococo, + WococoToRococo, } } @@ -67,6 +69,20 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; + $generic + } + RelayHeadersBridge::RococoToWococo => { + type Source = relay_rococo_client::Rococo; + type Target = relay_wococo_client::Wococo; + type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; + + $generic + } + RelayHeadersBridge::WococoToRococo => { + type Source = relay_wococo_client::Wococo; + type Target = relay_rococo_client::Rococo; + type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + $generic } } diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml new file mode 100644 index 0000000000000..22d710ca3d7b7 --- /dev/null +++ b/relays/client-wococo/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "relay-wococo-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "2.0.0" } +headers-relay = { path = "../headers" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + +# Bridge dependencies +bp-wococo = { path = "../../primitives/chain-wococo" } + +# Substrate Dependencies +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs new file mode 100644 index 0000000000000..be2f872b7d775 --- /dev/null +++ b/relays/client-wococo/src/lib.rs @@ -0,0 +1,97 @@ +// 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 . + +//! Types used to connect to the Wococo-Substrate chain. + +use codec::Encode; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Wococo header id. +pub type HeaderId = relay_utils::HeaderId; + +/// Wococo header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + +/// Wococo chain definition +#[derive(Debug, Clone, Copy)] +pub struct Wococo; + +impl ChainBase for Wococo { + type BlockNumber = bp_wococo::BlockNumber; + type Hash = bp_wococo::Hash; + type Hasher = bp_wococo::Hashing; + type Header = bp_wococo::Header; +} + +impl Chain for Wococo { + const NAME: &'static str = "Wococo"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type AccountId = bp_wococo::AccountId; + type Index = bp_wococo::Index; + type SignedBlock = bp_wococo::SignedBlock; + type Call = bp_wococo::Call; +} + +impl ChainWithBalances for Wococo { + type NativeBalance = bp_wococo::Balance; + + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_wococo::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for Wococo { + type Chain = Wococo; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = bp_wococo::UncheckedExtrinsic; + + fn sign_transaction( + genesis_hash: ::Hash, + signer: &Self::AccountKeyPair, + signer_nonce: ::Index, + call: ::Call, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + call, + bp_wococo::SignedExtensions::new( + bp_wococo::VERSION, + sp_runtime::generic::Era::Immortal, + genesis_hash, + signer_nonce, + 0, + ), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_wococo::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) + } +} + +/// Wococo signing params. +pub type SigningParams = sp_core::sr25519::Pair; From 6b4107e0563ce9005f4840b1e7df69d26556ed10 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Fri, 30 Apr 2021 03:11:33 +0800 Subject: [PATCH 0453/1210] Message dispatch support multiple instances (#942) * message dispatch support multiple instances * format code * define millau grandpa instance in rialto --- bin/millau/runtime/src/rialto_messages.rs | 9 +++++++-- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/millau_messages.rs | 9 +++++++-- bin/runtime-common/src/messages.rs | 18 ++++++++++-------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 736301016fa30..a61d7cce2978d 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -214,7 +214,9 @@ impl TargetHeaderChain for Rialto fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::(proof) + messages::source::verify_messages_delivery_proof::( + proof, + ) } } @@ -231,7 +233,10 @@ impl SourceHeaderChain for Rialto { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::(proof, messages_count) + messages::target::verify_messages_proof::( + proof, + messages_count, + ) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 69fff6b10c3fa..70f770388200c 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -436,6 +436,7 @@ parameter_types! { pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; } +pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 77b73c07857b0..30a34b9276ce1 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -214,7 +214,9 @@ impl TargetHeaderChain for Millau fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::(proof) + messages::source::verify_messages_delivery_proof::( + proof, + ) } } @@ -231,7 +233,10 @@ impl SourceHeaderChain for Millau { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::(proof, messages_count) + messages::target::verify_messages_proof::( + proof, + messages_count, + ) } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 54e8b30031a44..9f25039dc4b61 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -352,20 +352,21 @@ pub mod source { } /// Verify proof of This -> Bridged chain messages delivery. - pub fn verify_messages_delivery_proof( + pub fn verify_messages_delivery_proof( proof: FromBridgedChainMessagesDeliveryProof>>, ) -> Result, &'static str> where - ThisRuntime: pallet_bridge_grandpa::Config, + ThisRuntime: pallet_bridge_grandpa::Config, ThisRuntime: pallet_bridge_messages::Config>>, - HashOf>: Into::BridgedChain>>, + HashOf>: + Into>::BridgedChain>>, { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane, } = proof; - pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( + pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), |storage| { @@ -504,20 +505,21 @@ pub mod target { /// The `messages_count` argument verification (sane limits) is supposed to be made /// outside of this function. This function only verifies that the proof declares exactly /// `messages_count` messages. - pub fn verify_messages_proof( + pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof>>, messages_count: u32, ) -> Result>>>, &'static str> where - ThisRuntime: pallet_bridge_grandpa::Config, + ThisRuntime: pallet_bridge_grandpa::Config, ThisRuntime: pallet_bridge_messages::Config>>, - HashOf>: Into::BridgedChain>>, + HashOf>: + Into>::BridgedChain>>, { verify_messages_proof_with_parser::( proof, messages_count, |bridged_header_hash, bridged_storage_proof| { - pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( + pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, From cf112fcbb4a4e113d8e3d7f81df2a5aabd8ac3f5 Mon Sep 17 00:00:00 2001 From: Tomasz Waszczyk Date: Thu, 29 Apr 2021 22:22:29 +0200 Subject: [PATCH 0454/1210] Add backbone configuration of cargo-spellcheck (#924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(config): add backbone configuration of cargo-spellcheck * feat(config): try to narrow a source code to analysis * feat(config): try to narrow a source code to analysis via find command * Update .github/workflows/lint.yml ;-) Co-authored-by: Hernando Castano * Update .github/workflows/lint.yml Co-authored-by: Hernando Castano * Use bash. * Fix spelling. Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga --- modules/currency-exchange/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 542082f85ab16..9a8af5ba5016f 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -70,7 +70,7 @@ decl_error! { InvalidRecipient, /// Cannot map from peer recipient to this blockchain recipient. FailedToMapRecipients, - /// Failed to convert from peer blockchain currency to this blockhain currency. + /// Failed to convert from peer blockchain currency to this blockchain currency. FailedToConvertCurrency, /// Deposit has failed. DepositFailed, From 39cfe86f20e6ef673bab4011f714a70fe257f07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 2 May 2021 18:29:43 +0200 Subject: [PATCH 0455/1210] Fix account derivation in CLI (#952) * Fix account derivation. * Fix tests. --- relays/bin-substrate/src/cli/bridge.rs | 4 ++-- relays/bin-substrate/src/cli/derive_account.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index faf4417d1e995..996edb49942a1 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -53,7 +53,7 @@ macro_rules! select_full_bridge { // Derive-account #[allow(unused_imports)] - use bp_millau::derive_account_from_rialto_id as derive_account; + use bp_rialto::derive_account_from_millau_id as derive_account; // Relay-messages #[allow(unused_imports)] @@ -75,7 +75,7 @@ macro_rules! select_full_bridge { // Derive-account #[allow(unused_imports)] - use bp_rialto::derive_account_from_millau_id as derive_account; + use bp_millau::derive_account_from_rialto_id as derive_account; // Relay-messages #[allow(unused_imports)] diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs index 92b32b0d479ca..dff62c21f6fea 100644 --- a/relays/bin-substrate/src/cli/derive_account.rs +++ b/relays/bin-substrate/src/cli/derive_account.rs @@ -91,11 +91,11 @@ mod tests { assert_eq!( format!("{}", rialto_derived), - "73gLnUwrAdH4vMjbXCiNEpgyz1PLk9JxCaY4cKzvfSZT73KE" + "74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5" ); assert_eq!( format!("{}", millau_derived), - "5rpTJqGv1BPAYy2sXzkPpc3Wx1ZpQtgfuBsrDpNV4HsXAmbi" + "5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2" ); assert_eq!(millau_derived, millau2_derived); } From 74b3d3ca882a14855cf1ef03a027f23b48780101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 3 May 2021 19:52:00 +0200 Subject: [PATCH 0456/1210] Endow accounts and add `bridgeIds` to chainspec. (#951) * Endow more accounts. * Add bridge ids to properties. * Change accounts on Millau. --- bin/millau/node/src/chain_spec.rs | 16 ++++++++++++++-- bin/rialto/node/src/chain_spec.rs | 14 +++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 340b8fd9dffb3..e36a12d9747c3 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -71,6 +71,9 @@ impl Alternative { serde_json::json!({ "tokenDecimals": 9, "tokenSymbol": "MLAU", + "bridgeIds": { + "Rialto": bp_runtime::RIALTO_BRIDGE_INSTANCE, + } }) .as_object() .expect("Map given; qed") @@ -90,6 +93,9 @@ impl Alternative { get_account_id_from_seed::("Bob"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Alice"), + )), ], true, ) @@ -136,7 +142,13 @@ impl Alternative { pallet_bridge_messages::DefaultInstance, >::relayer_fund_account_id(), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Alice"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Charlie"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Eve"), )), ], true, @@ -168,7 +180,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 20)).collect(), }, pallet_aura: AuraConfig { authorities: Vec::new(), diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index fb6dc92bf6d45..85dd37f56d557 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -72,6 +72,9 @@ impl Alternative { json!({ "tokenDecimals": 9, "tokenSymbol": "RLT", + "bridgeIds": { + "Millau": bp_runtime::MILLAU_BRIDGE_INSTANCE, + } }) .as_object() .expect("Map given; qed") @@ -91,6 +94,9 @@ impl Alternative { get_account_id_from_seed::("Bob"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), ], true, ) @@ -136,9 +142,15 @@ impl Alternative { rialto_runtime::Runtime, pallet_bridge_messages::DefaultInstance, >::relayer_fund_account_id(), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Ferdie"), + )), ], true, ) @@ -169,7 +181,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 20)).collect(), }, pallet_aura: AuraConfig { authorities: Vec::new(), From 5e511ce93484327531429a5d8579a6943d4808f4 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Tue, 4 May 2021 01:52:43 +0800 Subject: [PATCH 0457/1210] Move pallet-bridge-dispatch types to primitives (#948) * message dispatch support multiple instances * Move pallet-bridge-dispatch types to primitives * remove pallet-bridge-dispatch dependency * Update cargo.lock (remove pallet-bridge-dispatch in substrate-relay) * remove extra dependencies --- bin/rialto/runtime/src/lib.rs | 6 +- bin/runtime-common/README.md | 8 +- bin/runtime-common/src/messages.rs | 24 +++--- docs/high-level-overview.md | 2 +- modules/dispatch/README.md | 4 +- modules/dispatch/src/lib.rs | 77 +------------------- primitives/message-dispatch/Cargo.toml | 7 ++ primitives/message-dispatch/src/lib.rs | 75 ++++++++++++++++++- relays/bin-substrate/Cargo.toml | 2 +- relays/bin-substrate/src/chains/millau.rs | 2 +- relays/bin-substrate/src/chains/mod.rs | 12 +-- relays/bin-substrate/src/chains/rialto.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 2 +- 13 files changed, 115 insertions(+), 108 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 70f770388200c..a062744108002 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -889,7 +889,7 @@ impl_runtime_apis! { params: MessageParams, ) -> (millau_messages::ToMillauMessagePayload, Balance) { let message_payload = vec![0; params.size as usize]; - let dispatch_origin = pallet_bridge_dispatch::CallOrigin::SourceAccount( + let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount( params.sender_account, ); @@ -959,10 +959,10 @@ impl_runtime_apis! { make_millau_outbound_lane_data_key, make_millau_header, call_weight, - pallet_bridge_dispatch::MessagePayload { + bp_message_dispatch::MessagePayload { spec_version: VERSION.spec_version, weight: call_weight, - origin: pallet_bridge_dispatch::CallOrigin::< + origin: bp_message_dispatch::CallOrigin::< bp_millau::AccountId, MultiSigner, Signature, diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index b375f48309c3a..a7322af973996 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -8,7 +8,7 @@ messages module into your runtime. Basic prerequisites of these helpers are: - all message lanes are identical and may be used to transfer the same messages; - the messages sent over the bridge are dispatched using [call dispatch module](../../modules/dispatch/README.md); -- the messages are `pallet_bridge_dispatch::MessagePayload` structures, where `call` field is +- the messages are `bp_message_dispatch::MessagePayload` structures, where `call` field is encoded `Call` of the target chain. This means that the `Call` is opaque to the [messages module](../../modules/messages/README.md) instance at the source chain. It is pre-encoded by the message submitter; @@ -118,7 +118,7 @@ are: `maximal_message_size`, `verify_chain_message`, `verify_messages_delivery_p `estimate_message_dispatch_and_delivery_fee`. `FromThisChainMessagePayload` is a message that the sender sends through our bridge. It is the -`pallet_bridge_dispatch::MessagePayload`, where `call` field is encoded target chain call. So +`bp_message_dispatch::MessagePayload`, where `call` field is encoded target chain call. So at this chain we don't see internals of this call - we just know its size. `FromThisChainMessageVerifier` is an implementation of `bp_messages::LaneMessageVerifier`. It @@ -131,8 +131,8 @@ has following checks in its `verify_message` method: 1. it'll reject a message if it has the wrong dispatch origin declared. Like if the submitter is not the root of this chain, but it tries to dispatch the message at the target chain using - `pallet_bridge_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature - in the `pallet_bridge_dispatch::CallOrigin::TargetAccount` origin; + `bp_message_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature + in the `bp_message_dispatch::CallOrigin::TargetAccount` origin; 1. it'll reject a message if the delivery and dispatch fee that the submitter wants to pay is lesser than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 9f25039dc4b61..e879aa17bfb2b 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -180,7 +180,7 @@ pub mod source { pub type BridgedChainOpaqueCall = Vec; /// Message payload for This -> Bridged chain messages. - pub type FromThisChainMessagePayload = pallet_bridge_dispatch::MessagePayload< + pub type FromThisChainMessagePayload = bp_message_dispatch::MessagePayload< AccountIdOf>, SignerOf>, SignatureOf>, @@ -395,14 +395,14 @@ pub mod target { use super::*; /// Call origin for Bridged -> This chain messages. - pub type FromBridgedChainMessageCallOrigin = pallet_bridge_dispatch::CallOrigin< + pub type FromBridgedChainMessageCallOrigin = bp_message_dispatch::CallOrigin< AccountIdOf>, SignerOf>, SignatureOf>, >; /// Decoded Bridged -> This message payload. - pub type FromBridgedChainMessagePayload = pallet_bridge_dispatch::MessagePayload< + pub type FromBridgedChainMessagePayload = bp_message_dispatch::MessagePayload< AccountIdOf>, SignerOf>, SignatureOf>, @@ -931,7 +931,7 @@ mod tests { let message_on_bridged_chain = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: ThisChainCall::Transfer.encode(), } .encode(); @@ -945,7 +945,7 @@ mod tests { target::FromBridgedChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: target::FromBridgedChainEncodedMessageCall:: { encoded_call: ThisChainCall::Transfer.encode(), _marker: PhantomData::default(), @@ -962,7 +962,7 @@ mod tests { source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: vec![42], } } @@ -1012,7 +1012,7 @@ mod tests { let payload = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: vec![42], }; @@ -1055,7 +1055,7 @@ mod tests { let payload = source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, - origin: pallet_bridge_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), + origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), call: vec![42], }; @@ -1122,7 +1122,7 @@ mod tests { > { spec_version: 1, weight: 5, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: vec![1, 2, 3, 4, 5, 6], },) .is_err() @@ -1137,7 +1137,7 @@ mod tests { > { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: vec![1, 2, 3, 4, 5, 6], },) .is_err() @@ -1152,7 +1152,7 @@ mod tests { > { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: vec![0; source::maximal_message_size::() as usize + 1], },) .is_err() @@ -1167,7 +1167,7 @@ mod tests { > { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: pallet_bridge_dispatch::CallOrigin::SourceRoot, + origin: bp_message_dispatch::CallOrigin::SourceRoot, call: vec![0; source::maximal_message_size::() as _], },), Ok(()), diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 14b1eee6d4505..9ca3ca42ff5e5 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -172,6 +172,6 @@ source chain needs to prove ownership of this account by using their target chai sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and verified by the target chain before dispatch. -See [`CallOrigin` documentation](../modules/dispatch/src/lib.rs) for more details. +See [`CallOrigin` documentation](../primitives/message-dispatch/src/lib.rs) for more details. #### Message Relayers Strategy diff --git a/modules/dispatch/README.md b/modules/dispatch/README.md index f2ee04beaf53e..c4e703c402d5a 100644 --- a/modules/dispatch/README.md +++ b/modules/dispatch/README.md @@ -13,7 +13,7 @@ Every message that is being dispatched has three main characteristics: - `id` is the unique id of the message within the given bridge. For messages coming from the [messages module](../messages/README.md), it may worth to use a tuple `(LaneId, MessageNonce)` to identify a message; -- `message` is the `pallet_bridge_dispatch::MessagePayload` structure. The `call` field is set +- `message` is the `bp_message_dispatch::MessagePayload` structure. The `call` field is set to the (potentially) encoded `Call` of this chain. The easiest way to understand what is happening when a `Call` is being dispatched, is to look at the @@ -33,7 +33,7 @@ module events set: chain storage has been corrupted. The `Call` is decoded after `spec_version` check, so we'll never try to decode `Call` from other runtime version; - `MessageSignatureMismatch` event is emitted if submitter has chose to dispatch message using - specified this chain account (`pallet_bridge_dispatch::CallOrigin::TargetAccount` origin), + specified this chain account (`bp_message_dispatch::CallOrigin::TargetAccount` origin), but he has failed to prove that he owns the private key for this account; - `MessageCallRejected` event is emitted if the module has been deployed with some call filter and this filter has rejected the `Call`. In your bridge you may choose to reject all messages except diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index f9649c58c4787..0b0074c20b76b 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -24,8 +24,8 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_message_dispatch::{MessageDispatch, Weight}; -use bp_runtime::{derive_account_id, InstanceId, Size, SourceAccount}; +use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight}; +use bp_runtime::{derive_account_id, InstanceId, SourceAccount}; use codec::{Decode, Encode}; use frame_support::{ decl_event, decl_module, decl_storage, @@ -33,7 +33,6 @@ use frame_support::{ ensure, traits::{Filter, Get}, weights::{extract_actual_weight, GetDispatchInfo}, - RuntimeDebug, }; use frame_system::RawOrigin; use sp_runtime::{ @@ -42,78 +41,6 @@ use sp_runtime::{ }; use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; -/// Spec version type. -pub type SpecVersion = u32; - -// TODO [#895] move to primitives -/// Origin of a Call when it is dispatched on the target chain. -/// -/// The source chain can (and should) verify that the message can be dispatched on the target chain -/// with a particular origin given the source chain's origin. This can be done with the -/// `verify_message_origin()` function. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] -pub enum CallOrigin { - /// Call is sent by the Root origin on the source chain. On the target chain it is dispatched - /// from a derived account. - /// - /// The derived account represents the source Root account on the target chain. This is useful - /// if the target chain needs some way of knowing that a call came from a priviledged origin on - /// the source chain (maybe to allow a configuration change for example). - SourceRoot, - - /// Call is sent by `SourceChainAccountId` on the source chain. On the target chain it is - /// dispatched from an account controlled by a private key on the target chain. - /// - /// The account can be identified by `TargetChainAccountPublic`. The proof that the - /// `SourceChainAccountId` controls `TargetChainAccountPublic` is the `TargetChainSignature` - /// over `(Call, SourceChainAccountId, TargetChainSpecVersion, SourceChainBridgeId).encode()`. - /// - /// NOTE sending messages using this origin (or any other) does not have replay protection! - /// The assumption is that both the source account and the target account is controlled by - /// the same entity, so source-chain replay protection is sufficient. - /// As a consequence, it's extremely important for the target chain user to never produce - /// a signature with their target-private key on something that could be sent over the bridge, - /// i.e. if the target user signs `(, Call::Transfer(X, 5))` - /// The owner of `some-source-account-id` can send that message multiple times, which would - /// result with multiple transfer calls being dispatched on the target chain. - /// So please, NEVER USE YOUR PRIVATE KEY TO SIGN SOMETHING YOU DON'T FULLY UNDERSTAND! - TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature), - - /// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is - /// dispatched from a derived account ID. - /// - /// The account ID on the target chain is derived from the source account ID This is useful if - /// you need a way to represent foreign accounts on this chain for call dispatch purposes. - /// - /// Note that the derived account does not need to have a private key on the target chain. This - /// origin can therefore represent proxies, pallets, etc. as well as "regular" accounts. - SourceAccount(SourceChainAccountId), -} - -// TODO [#895] move to primitives -/// Message payload type used by dispatch module. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] -pub struct MessagePayload { - /// Runtime specification version. We only dispatch messages that have the same - /// runtime version. Otherwise we risk to misinterpret encoded calls. - pub spec_version: SpecVersion, - /// Weight of the call, declared by the message sender. If it is less than actual - /// static weight, the call is not dispatched. - pub weight: Weight, - /// Call origin to be used during dispatch. - pub origin: CallOrigin, - /// The call itself. - pub call: Call, -} - -impl Size - for MessagePayload> -{ - fn size_hint(&self) -> u32 { - self.call.len() as _ - } -} - /// The module configuration trait. pub trait Config: frame_system::Config { /// The overarching event type. diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 293c637e8df25..84fa48553a21a 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -10,9 +10,16 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } + [features] default = ["std"] std = [ "bp-runtime/std", "codec/std", + "frame-support/std", + "sp-std/std", ] diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 3b83e38517e2d..1244371239644 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -19,11 +19,17 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_runtime::InstanceId; +use bp_runtime::{InstanceId, Size}; +use codec::{Decode, Encode}; +use frame_support::RuntimeDebug; +use sp_std::prelude::*; /// Message dispatch weight. pub type Weight = u64; +/// Spec version type. +pub type SpecVersion = u32; + /// A generic trait to dispatch arbitrary messages delivered over the bridge. pub trait MessageDispatch { /// A type of the message to be dispatched. @@ -47,3 +53,70 @@ pub trait MessageDispatch { /// the whole message). fn dispatch(bridge: InstanceId, id: MessageId, message: Result); } + +/// Origin of a Call when it is dispatched on the target chain. +/// +/// The source chain can (and should) verify that the message can be dispatched on the target chain +/// with a particular origin given the source chain's origin. This can be done with the +/// `verify_message_origin()` function. +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +pub enum CallOrigin { + /// Call is sent by the Root origin on the source chain. On the target chain it is dispatched + /// from a derived account. + /// + /// The derived account represents the source Root account on the target chain. This is useful + /// if the target chain needs some way of knowing that a call came from a priviledged origin on + /// the source chain (maybe to allow a configuration change for example). + SourceRoot, + + /// Call is sent by `SourceChainAccountId` on the source chain. On the target chain it is + /// dispatched from an account controlled by a private key on the target chain. + /// + /// The account can be identified by `TargetChainAccountPublic`. The proof that the + /// `SourceChainAccountId` controls `TargetChainAccountPublic` is the `TargetChainSignature` + /// over `(Call, SourceChainAccountId, TargetChainSpecVersion, SourceChainBridgeId).encode()`. + /// + /// NOTE sending messages using this origin (or any other) does not have replay protection! + /// The assumption is that both the source account and the target account is controlled by + /// the same entity, so source-chain replay protection is sufficient. + /// As a consequence, it's extremely important for the target chain user to never produce + /// a signature with their target-private key on something that could be sent over the bridge, + /// i.e. if the target user signs `(, Call::Transfer(X, 5))` + /// The owner of `some-source-account-id` can send that message multiple times, which would + /// result with multiple transfer calls being dispatched on the target chain. + /// So please, NEVER USE YOUR PRIVATE KEY TO SIGN SOMETHING YOU DON'T FULLY UNDERSTAND! + TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature), + + /// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is + /// dispatched from a derived account ID. + /// + /// The account ID on the target chain is derived from the source account ID This is useful if + /// you need a way to represent foreign accounts on this chain for call dispatch purposes. + /// + /// Note that the derived account does not need to have a private key on the target chain. This + /// origin can therefore represent proxies, pallets, etc. as well as "regular" accounts. + SourceAccount(SourceChainAccountId), +} + +/// Message payload type used by dispatch module. +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +pub struct MessagePayload { + /// Runtime specification version. We only dispatch messages that have the same + /// runtime version. Otherwise we risk to misinterpret encoded calls. + pub spec_version: SpecVersion, + /// Weight of the call, declared by the message sender. If it is less than actual + /// static weight, the call is not dispatched. + pub weight: Weight, + /// Call origin to be used during dispatch. + pub origin: CallOrigin, + /// The call itself. + pub call: Call, +} + +impl Size + for MessagePayload> +{ + fn size_hint(&self) -> u32 { + self.call.len() as _ + } +} diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index f5711e0766d1c..fc61d138fde0b 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -23,6 +23,7 @@ structopt = "0.3" bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } bp-messages = { path = "../../primitives/messages" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } @@ -36,7 +37,6 @@ finality-relay = { path = "../finality" } headers-relay = { path = "../headers" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index ac5e611fdbcb5..41ac76082807c 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -21,9 +21,9 @@ use crate::cli::{ encode_call::{self, Call, CliEncodeCall}, encode_message, send_message, CliChain, }; +use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; use frame_support::weights::{GetDispatchInfo, Weight}; -use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_millau_client::Millau; use sp_version::RuntimeVersion; diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 20ddf4a92af1b..b4061ced37f72 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -132,7 +132,7 @@ mod tests { let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, - pallet_bridge_dispatch::CallOrigin::SourceRoot, + bp_message_dispatch::CallOrigin::SourceRoot, &call, ); assert_eq!(Millau::verify_message(&payload), Ok(())); @@ -142,7 +142,7 @@ mod tests { let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, - pallet_bridge_dispatch::CallOrigin::SourceRoot, + bp_message_dispatch::CallOrigin::SourceRoot, &call, ); assert!(Millau::verify_message(&payload).is_err()); @@ -169,7 +169,7 @@ mod tests { let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight, - pallet_bridge_dispatch::CallOrigin::SourceRoot, + bp_message_dispatch::CallOrigin::SourceRoot, &call, ); assert_eq!(Millau::verify_message(&payload), Ok(())); @@ -177,7 +177,7 @@ mod tests { let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight + 1, - pallet_bridge_dispatch::CallOrigin::SourceRoot, + bp_message_dispatch::CallOrigin::SourceRoot, &call, ); assert!(Millau::verify_message(&payload).is_err()); @@ -194,7 +194,7 @@ mod tests { let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight, - pallet_bridge_dispatch::CallOrigin::SourceRoot, + bp_message_dispatch::CallOrigin::SourceRoot, &call, ); assert_eq!(Rialto::verify_message(&payload), Ok(())); @@ -202,7 +202,7 @@ mod tests { let payload = send_message::message_payload( Default::default(), maximal_dispatch_weight + 1, - pallet_bridge_dispatch::CallOrigin::SourceRoot, + bp_message_dispatch::CallOrigin::SourceRoot, &call, ); assert!(Rialto::verify_message(&payload).is_err()); diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 25c1ab04c9fd1..77eeb06da0d70 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -21,9 +21,9 @@ use crate::cli::{ encode_call::{self, Call, CliEncodeCall}, encode_message, send_message, CliChain, }; +use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; use frame_support::weights::{GetDispatchInfo, Weight}; -use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_rialto_client::Rialto; use sp_version::RuntimeVersion; diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 64448f0f1db3f..6fa82a8cdb5e3 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -21,9 +21,9 @@ use crate::cli::{ Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, TargetSigningParams, }; +use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; -use pallet_bridge_dispatch::{CallOrigin, MessagePayload}; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; From cf775ada12a77187b540a4782dada3dbfb19acaa Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 3 May 2021 14:26:56 -0400 Subject: [PATCH 0458/1210] Bump Substrate to `ec180313` (#955) * Bump Substrate to commit `0856e0729c5f9cd5d398b93680ab154fe486e588` * Update service to use new inherent data client Relevant Substrate PR: https://github.com/paritytech/substrate/pull/8526 * Appease Clippy --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/service.rs | 57 +++++++++++++++++++++++++--------- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/service.rs | 55 +++++++++++++++++++++++--------- 4 files changed, 85 insertions(+), 29 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index cbcb2e710c03c..4c5f081e15069 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -47,6 +47,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 8677ec2e70df1..a3cb4fa2457d3 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -37,8 +37,8 @@ use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; +use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use sp_inherents::InherentDataProviders; use std::sync::Arc; use std::time::Duration; @@ -80,8 +80,6 @@ pub fn new_partial( if config.keystore_remote.is_some() { return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); } - let inherent_data_providers = InherentDataProviders::new(); - let telemetry = config .telemetry_endpoints .clone() @@ -124,14 +122,24 @@ pub fn new_partial( let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { block_import: aura_block_import.clone(), justification_import: Some(Box::new(grandpa_block_import)), client: client.clone(), - inherent_data_providers: inherent_data_providers.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot)) + }, spawner: &task_manager.spawn_essential_handle(), can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - slot_duration: sc_consensus_aura::slot_duration(&*client)?, registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -145,7 +153,6 @@ pub fn new_partial( keystore_container, select_chain, transaction_pool, - inherent_data_providers, other: (aura_block_import, grandpa_link, telemetry), }) } @@ -167,7 +174,6 @@ pub fn new_full(mut config: Configuration) -> Result mut keystore_container, select_chain, transaction_pool, - inherent_data_providers, other: (block_import, grandpa_link, mut telemetry), } = new_partial(&config)?; @@ -277,13 +283,25 @@ pub fn new_full(mut config: Configuration) -> Result let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let aura = sc_consensus_aura::start_aura::(StartAuraParams { - slot_duration: sc_consensus_aura::slot_duration(&*client)?, - client: client.clone(), + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + let raw_slot_duration = slot_duration.slot_duration(); + + let aura = sc_consensus_aura::start_aura::(StartAuraParams { + slot_duration, + client, select_chain, block_import, proposer_factory, - inherent_data_providers, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + raw_slot_duration, + ); + + Ok((timestamp, slot)) + }, force_authoring, backoff_authoring_blocks, keystore: keystore_container.sync_keystore(), @@ -394,14 +412,23 @@ pub fn new_light(mut config: Configuration) -> Result let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { block_import: aura_block_import, justification_import: Some(Box::new(grandpa_block_import)), client: client.clone(), - inherent_data_providers: InherentDataProviders::new(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot)) + }, spawner: &task_manager.spawn_essential_handle(), can_author_with: sp_consensus::NeverCanAuthor, - slot_duration: sc_consensus_aura::slot_duration(&*client)?, registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 370985d8ae634..38272cd8c786f 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -48,6 +48,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 841202ac7bfa5..a0d3d311a018b 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -37,8 +37,8 @@ use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; +use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use sp_inherents::InherentDataProviders; use std::sync::Arc; use std::time::Duration; @@ -80,7 +80,6 @@ pub fn new_partial( if config.keystore_remote.is_some() { return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); } - let inherent_data_providers = InherentDataProviders::new(); let telemetry = config .telemetry_endpoints @@ -124,14 +123,24 @@ pub fn new_partial( let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { block_import: aura_block_import.clone(), justification_import: Some(Box::new(grandpa_block_import)), client: client.clone(), - inherent_data_providers: inherent_data_providers.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot)) + }, spawner: &task_manager.spawn_essential_handle(), can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - slot_duration: sc_consensus_aura::slot_duration(&*client)?, registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -145,7 +154,6 @@ pub fn new_partial( keystore_container, select_chain, transaction_pool, - inherent_data_providers, other: (aura_block_import, grandpa_link, telemetry), }) } @@ -167,7 +175,6 @@ pub fn new_full(mut config: Configuration) -> Result mut keystore_container, select_chain, transaction_pool, - inherent_data_providers, other: (block_import, grandpa_link, mut telemetry), } = new_partial(&config)?; @@ -278,13 +285,24 @@ pub fn new_full(mut config: Configuration) -> Result let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let aura = sc_consensus_aura::start_aura::(StartAuraParams { - slot_duration: sc_consensus_aura::slot_duration(&*client)?, - client: client.clone(), + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + let raw_slot_duration = slot_duration.slot_duration(); + let aura = sc_consensus_aura::start_aura::(StartAuraParams { + slot_duration, + client, select_chain, block_import, proposer_factory, - inherent_data_providers, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + raw_slot_duration, + ); + + Ok((timestamp, slot)) + }, force_authoring, backoff_authoring_blocks, keystore: keystore_container.sync_keystore(), @@ -395,14 +413,23 @@ pub fn new_light(mut config: Configuration) -> Result let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { block_import: aura_block_import, justification_import: Some(Box::new(grandpa_block_import)), client: client.clone(), - inherent_data_providers: InherentDataProviders::new(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot)) + }, spawner: &task_manager.spawn_essential_handle(), can_author_with: sp_consensus::NeverCanAuthor, - slot_duration: sc_consensus_aura::slot_duration(&*client)?, registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), From 3a9e70638f917506e413e695f723279ddd9436f4 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 3 May 2021 15:45:46 -0400 Subject: [PATCH 0459/1210] Bump Substrate WASM builder (#947) --- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/runtime/Cargo.toml | 2 +- bin/millau/runtime/build.rs | 5 ++--- bin/rialto/node/src/chain_spec.rs | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/rialto/runtime/build.rs | 5 ++--- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index e36a12d9747c3..aef01737fbe82 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -176,7 +176,7 @@ fn testnet_genesis( ) -> GenesisConfig { GenesisConfig { frame_system: SystemConfig { - code: WASM_BINARY.to_vec(), + code: WASM_BINARY.expect("Millau development WASM not available").to_vec(), changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index e1f7ed10c63e6..240b079d110f4 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -56,7 +56,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2.0.0" } +substrate-wasm-builder = "3.0.0" [features] default = ["std"] diff --git a/bin/millau/runtime/build.rs b/bin/millau/runtime/build.rs index dcb5cb06218e5..cc865704327dd 100644 --- a/bin/millau/runtime/build.rs +++ b/bin/millau/runtime/build.rs @@ -14,13 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates("1.0.11") - .export_heap_base() .import_memory() + .export_heap_base() .build() } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 85dd37f56d557..27a751892451a 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -177,7 +177,7 @@ fn testnet_genesis( ) -> GenesisConfig { GenesisConfig { frame_system: SystemConfig { - code: WASM_BINARY.to_vec(), + code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(), changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index ea8c51d0e8c00..63a48a255bd42 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -68,7 +68,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [build-dependencies] -wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "2.0.0" } +substrate-wasm-builder = "3.0.0" [features] default = ["std"] diff --git a/bin/rialto/runtime/build.rs b/bin/rialto/runtime/build.rs index dcb5cb06218e5..cc865704327dd 100644 --- a/bin/rialto/runtime/build.rs +++ b/bin/rialto/runtime/build.rs @@ -14,13 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use wasm_builder_runner::WasmBuilder; +use substrate_wasm_builder::WasmBuilder; fn main() { WasmBuilder::new() .with_current_project() - .with_wasm_builder_from_crates("1.0.11") - .export_heap_base() .import_memory() + .export_heap_base() .build() } From f03b7672639216d6c1be73d30ab366d2d986c168 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 4 May 2021 06:15:41 -0400 Subject: [PATCH 0460/1210] Bump endowment amounts on Rialto and Millau (#957) --- bin/millau/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index aef01737fbe82..374c0f739c53a 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -180,7 +180,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 20)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 40)).collect(), }, pallet_aura: AuraConfig { authorities: Vec::new(), diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 27a751892451a..cf14845df1906 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -181,7 +181,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 20)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 40)).collect(), }, pallet_aura: AuraConfig { authorities: Vec::new(), From 3ef2240ab2f657bd630f4bd52f037cf40d510ccb Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 4 May 2021 15:19:46 -0400 Subject: [PATCH 0461/1210] Bump Substrate to `b094edaf` (#958) * Bump Substrate to commit `b094edafd1cd5d26e49ecbf92b0ce7553cfad717` * Remove unsafe random seed method See: https://github.com/paritytech/substrate/pull/8718 * Update Subkey syntax See: https://github.com/paritytech/substrate/pull/8678 --- bin/millau/node/src/cli.rs | 2 +- bin/millau/runtime/src/lib.rs | 6 +----- bin/rialto/node/src/cli.rs | 2 +- bin/rialto/runtime/src/lib.rs | 6 +----- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 46323ed25c9ed..12f99b6b95bab 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -63,7 +63,7 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// Inspect blocks or extrinsics. - Inspect(node_inspect::cli::InspectCmd), + Inspect(node_inspect::cli::InspectKeyCmd), /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7d25eb90c5e1a..4f5e083632002 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -55,7 +55,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, Randomness}, + traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -477,10 +477,6 @@ impl_runtime_apis! { ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) } - - fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed().0 - } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 46323ed25c9ed..12f99b6b95bab 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -63,7 +63,7 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// Inspect blocks or extrinsics. - Inspect(node_inspect::cli::InspectCmd), + Inspect(node_inspect::cli::InspectKeyCmd), /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a062744108002..5259a10493a76 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -61,7 +61,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, - traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, Randomness}, + traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -587,10 +587,6 @@ impl_runtime_apis! { ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) } - - fn random_seed() -> ::Hash { - RandomnessCollectiveFlip::random_seed().0 - } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { From 8db5f8d660e742481edafd7af99667a70ded8887 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 4 May 2021 17:11:57 -0400 Subject: [PATCH 0462/1210] Increase account endowment amount (#960) --- bin/millau/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 374c0f739c53a..b0720344b62e2 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -180,7 +180,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 40)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, pallet_aura: AuraConfig { authorities: Vec::new(), diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index cf14845df1906..db2ef4c60bc3a 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -181,7 +181,7 @@ fn testnet_genesis( changes_trie_config: Default::default(), }, pallet_balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 40)).collect(), + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, pallet_aura: AuraConfig { authorities: Vec::new(), From 57f79ea48af66a9c1437027b5ddac54c1d018607 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 11 May 2021 06:26:27 -0400 Subject: [PATCH 0463/1210] Upstream changes from Polkadot repo (#961) * Bump Rococo's spec_version * Use dev node for Rococo helper script * Add helper scripts for relaying Rococo<>Wococo headers * Change Wococo<>Rococo scripts to use Alice for initialization * Add Wococo node helper script --- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-wococo/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 66cbb475bda2d..a4ecf93f1c98c 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), authoring_version: 0, - spec_version: 232, + spec_version: 9001, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index f7a472ddf31df..13462a820b899 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), authoring_version: 0, - spec_version: 232, + spec_version: 9001, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, From b81f5c80dfaf184d77d5b681f715dbde2a4a6a23 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 May 2021 13:04:11 +0300 Subject: [PATCH 0464/1210] pass source and target chain ids to account_ownership_proof (#963) --- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/runtime/src/lib.rs | 5 +- bin/millau/runtime/src/rialto_messages.rs | 8 +- bin/rialto/node/src/chain_spec.rs | 2 +- bin/rialto/runtime/src/lib.rs | 5 +- bin/rialto/runtime/src/millau_messages.rs | 8 +- bin/runtime-common/src/messages.rs | 17 ++- modules/dispatch/src/lib.rs | 136 ++++++++++-------- primitives/chain-kusama/src/lib.rs | 2 +- primitives/chain-millau/src/lib.rs | 2 +- primitives/chain-polkadot/src/lib.rs | 2 +- primitives/chain-rialto/src/lib.rs | 2 +- primitives/chain-westend/src/lib.rs | 2 +- primitives/chain-wococo/src/lib.rs | 2 +- primitives/message-dispatch/src/lib.rs | 7 +- primitives/runtime/src/lib.rs | 30 ++-- .../src/chains/millau_messages_to_rialto.rs | 6 +- relays/bin-substrate/src/chains/mod.rs | 4 +- .../src/chains/rialto_messages_to_millau.rs | 6 +- relays/bin-substrate/src/cli/bridge.rs | 4 +- relays/bin-substrate/src/messages_source.rs | 6 +- relays/bin-substrate/src/messages_target.rs | 6 +- 22 files changed, 149 insertions(+), 115 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index b0720344b62e2..872b81a88ce34 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -72,7 +72,7 @@ impl Alternative { "tokenDecimals": 9, "tokenSymbol": "MLAU", "bridgeIds": { - "Rialto": bp_runtime::RIALTO_BRIDGE_INSTANCE, + "Rialto": bp_runtime::RIALTO_CHAIN_ID, } }) .as_object() diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4f5e083632002..8553045419e06 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -642,7 +642,7 @@ impl_runtime_apis! { /// The byte vector returned by this function should be signed with a Rialto account private key. /// This way, the owner of `millau_account_id` on Millau proves that the Rialto account private key /// is also under his control. -pub fn rialto_account_ownership_digest( +pub fn millau_to_rialto_account_ownership_digest( rialto_call: &Call, millau_account_id: AccountId, rialto_spec_version: SpecVersion, @@ -656,7 +656,8 @@ where rialto_call, millau_account_id, rialto_spec_version, - bp_runtime::MILLAU_BRIDGE_INSTANCE, + bp_runtime::MILLAU_CHAIN_ID, + bp_runtime::RIALTO_CHAIN_ID, ) } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index a61d7cce2978d..6641dc01b7db5 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -23,7 +23,7 @@ use bp_messages::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{InstanceId, RIALTO_BRIDGE_INSTANCE}; +use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -72,8 +72,6 @@ pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDi pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { - const INSTANCE: InstanceId = RIALTO_BRIDGE_INSTANCE; - const RELAYER_FEE_PERCENT: u32 = 10; type ThisChain = Millau; @@ -90,6 +88,8 @@ impl MessageBridge for WithRialtoMessageBridge { pub struct Millau; impl messages::ChainWithMessages for Millau { + const ID: ChainId = MILLAU_CHAIN_ID; + type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; @@ -141,6 +141,8 @@ impl messages::ThisChainWithMessages for Millau { pub struct Rialto; impl messages::ChainWithMessages for Rialto { + const ID: ChainId = RIALTO_CHAIN_ID; + type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index db2ef4c60bc3a..17b13c88fbb3a 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -73,7 +73,7 @@ impl Alternative { "tokenDecimals": 9, "tokenSymbol": "RLT", "bridgeIds": { - "Millau": bp_runtime::MILLAU_BRIDGE_INSTANCE, + "Millau": bp_runtime::MILLAU_CHAIN_ID, } }) .as_object() diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5259a10493a76..e67a1c64cd41f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1026,7 +1026,7 @@ impl_runtime_apis! { /// The byte vector returned by this function should be signed with a Millau account private key. /// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private key /// is also under his control. -pub fn millau_account_ownership_digest( +pub fn rialto_to_millau_account_ownership_digest( millau_call: &Call, rialto_account_id: AccountId, millau_spec_version: SpecVersion, @@ -1040,7 +1040,8 @@ where millau_call, rialto_account_id, millau_spec_version, - bp_runtime::RIALTO_BRIDGE_INSTANCE, + bp_runtime::RIALTO_CHAIN_ID, + bp_runtime::MILLAU_CHAIN_ID, ) } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 30a34b9276ce1..5c1779a7fea94 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -23,7 +23,7 @@ use bp_messages::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{InstanceId, MILLAU_BRIDGE_INSTANCE}; +use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -72,8 +72,6 @@ pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessa pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const INSTANCE: InstanceId = MILLAU_BRIDGE_INSTANCE; - const RELAYER_FEE_PERCENT: u32 = 10; type ThisChain = Rialto; @@ -90,6 +88,8 @@ impl MessageBridge for WithMillauMessageBridge { pub struct Rialto; impl messages::ChainWithMessages for Rialto { + const ID: ChainId = RIALTO_CHAIN_ID; + type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; @@ -141,6 +141,8 @@ impl messages::ThisChainWithMessages for Rialto { pub struct Millau; impl messages::ChainWithMessages for Millau { + const ID: ChainId = MILLAU_CHAIN_ID; + type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index e879aa17bfb2b..487fb356f9f32 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -26,7 +26,7 @@ use bp_messages::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_runtime::{InstanceId, Size, StorageProofChecker}; +use bp_runtime::{ChainId, Size, StorageProofChecker}; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; use hash_db::Hasher; @@ -39,9 +39,6 @@ use sp_trie::StorageProof; /// Bidirectional message bridge. pub trait MessageBridge { - /// Instance id of this bridge. - const INSTANCE: InstanceId; - /// Relayer interest (in percents). const RELAYER_FEE_PERCENT: u32; @@ -56,6 +53,9 @@ pub trait MessageBridge { /// Chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ChainWithMessages { + /// Identifier of this chain. + const ID: ChainId; + /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. @@ -483,7 +483,8 @@ pub mod target { fn dispatch(message: DispatchMessage>>) { let message_id = (message.key.lane_id, message.key.nonce); pallet_bridge_dispatch::Pallet::::dispatch( - B::INSTANCE, + B::BridgedChain::ID, + B::ThisChain::ID, message_id, message.data.payload.map_err(drop), ); @@ -692,7 +693,6 @@ mod tests { struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { - const INSTANCE: InstanceId = *b"this"; const RELAYER_FEE_PERCENT: u32 = 10; type ThisChain = ThisChain; @@ -708,7 +708,6 @@ mod tests { struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { - const INSTANCE: InstanceId = *b"brdg"; const RELAYER_FEE_PERCENT: u32 = 20; type ThisChain = BridgedChain; @@ -809,6 +808,8 @@ mod tests { struct ThisChain; impl ChainWithMessages for ThisChain { + const ID: ChainId = *b"this"; + type Hash = (); type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; @@ -866,6 +867,8 @@ mod tests { struct BridgedChain; impl ChainWithMessages for BridgedChain { + const ID: ChainId = *b"brdg"; + type Hash = (); type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 0b0074c20b76b..7803c1e540e1b 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -25,7 +25,7 @@ #![warn(missing_docs)] use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight}; -use bp_runtime::{derive_account_id, InstanceId, SourceAccount}; +use bp_runtime::{derive_account_id, ChainId, SourceAccount}; use codec::{Decode, Encode}; use frame_support::{ decl_event, decl_module, decl_storage, @@ -90,21 +90,21 @@ decl_event!( >::MessageId { /// Message has been rejected before reaching dispatch. - MessageRejected(InstanceId, MessageId), + MessageRejected(ChainId, MessageId), /// Message has been rejected by dispatcher because of spec version mismatch. /// Last two arguments are: expected and passed spec version. - MessageVersionSpecMismatch(InstanceId, MessageId, SpecVersion, SpecVersion), + MessageVersionSpecMismatch(ChainId, MessageId, SpecVersion, SpecVersion), /// Message has been rejected by dispatcher because of weight mismatch. /// Last two arguments are: expected and passed call weight. - MessageWeightMismatch(InstanceId, MessageId, Weight, Weight), + MessageWeightMismatch(ChainId, MessageId, Weight, Weight), /// Message signature mismatch. - MessageSignatureMismatch(InstanceId, MessageId), + MessageSignatureMismatch(ChainId, MessageId), /// Message has been dispatched with given result. - MessageDispatched(InstanceId, MessageId, DispatchResult), + MessageDispatched(ChainId, MessageId, DispatchResult), /// We have failed to decode Call from the message. - MessageCallDecodeFailed(InstanceId, MessageId), + MessageCallDecodeFailed(ChainId, MessageId), /// The call from the message has been rejected by the call filter. - MessageCallRejected(InstanceId, MessageId), + MessageCallRejected(ChainId, MessageId), /// Phantom member, never used. Needed to handle multiple pallet instances. _Dummy(PhantomData), } @@ -126,13 +126,18 @@ impl, I: Instance> MessageDispatch for Pallet { message.weight } - fn dispatch(bridge: InstanceId, id: T::MessageId, message: Result) { + fn dispatch(source_chain: ChainId, target_chain: ChainId, id: T::MessageId, message: Result) { // emit special even if message has been rejected by external component let message = match message { Ok(message) => message, Err(_) => { - log::trace!(target: "runtime::bridge-dispatch", "Message {:?}/{:?}: rejected before actual dispatch", bridge, id); - Self::deposit_event(RawEvent::MessageRejected(bridge, id)); + log::trace!( + target: "runtime::bridge-dispatch", + "Message {:?}/{:?}: rejected before actual dispatch", + source_chain, + id, + ); + Self::deposit_event(RawEvent::MessageRejected(source_chain, id)); return; } }; @@ -143,13 +148,13 @@ impl, I: Instance> MessageDispatch for Pallet { if message.spec_version != expected_version { log::trace!( "Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}", - bridge, + source_chain, id, expected_version, message.spec_version, ); Self::deposit_event(RawEvent::MessageVersionSpecMismatch( - bridge, + source_chain, id, expected_version, message.spec_version, @@ -161,8 +166,13 @@ impl, I: Instance> MessageDispatch for Pallet { let call = match message.call.into() { Ok(call) => call, Err(_) => { - log::trace!(target: "runtime::bridge-dispatch", "Failed to decode Call from message {:?}/{:?}", bridge, id,); - Self::deposit_event(RawEvent::MessageCallDecodeFailed(bridge, id)); + log::trace!( + target: "runtime::bridge-dispatch", + "Failed to decode Call from message {:?}/{:?}", + source_chain, + id, + ); + Self::deposit_event(RawEvent::MessageCallDecodeFailed(source_chain, id)); return; } }; @@ -170,25 +180,31 @@ impl, I: Instance> MessageDispatch for Pallet { // prepare dispatch origin let origin_account = match message.origin { CallOrigin::SourceRoot => { - let hex_id = derive_account_id::(bridge, SourceAccount::Root); + let hex_id = derive_account_id::(source_chain, SourceAccount::Root); let target_id = T::AccountIdConverter::convert(hex_id); log::trace!(target: "runtime::bridge-dispatch", "Root Account: {:?}", &target_id); target_id } CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { - let digest = account_ownership_digest(&call, source_account_id, message.spec_version, bridge); + let digest = account_ownership_digest( + &call, + source_account_id, + message.spec_version, + source_chain, + target_chain, + ); let target_account = target_public.into_account(); if !target_signature.verify(&digest[..], &target_account) { log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}", - bridge, + source_chain, id, target_account, target_signature, ); - Self::deposit_event(RawEvent::MessageSignatureMismatch(bridge, id)); + Self::deposit_event(RawEvent::MessageSignatureMismatch(source_chain, id)); return; } @@ -196,7 +212,7 @@ impl, I: Instance> MessageDispatch for Pallet { target_account } CallOrigin::SourceAccount(source_account_id) => { - let hex_id = derive_account_id(bridge, SourceAccount::Account(source_account_id)); + let hex_id = derive_account_id(source_chain, SourceAccount::Account(source_account_id)); let target_id = T::AccountIdConverter::convert(hex_id); log::trace!(target: "runtime::bridge-dispatch", "Source Account: {:?}", &target_id); target_id @@ -208,11 +224,11 @@ impl, I: Instance> MessageDispatch for Pallet { log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?}: the call ({:?}) is rejected by filter", - bridge, + source_chain, id, call, ); - Self::deposit_event(RawEvent::MessageCallRejected(bridge, id)); + Self::deposit_event(RawEvent::MessageCallRejected(source_chain, id)); return; } @@ -225,13 +241,13 @@ impl, I: Instance> MessageDispatch for Pallet { log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", - bridge, + source_chain, id, expected_weight, message.weight, ); Self::deposit_event(RawEvent::MessageWeightMismatch( - bridge, + source_chain, id, expected_weight, message.weight, @@ -248,7 +264,7 @@ impl, I: Instance> MessageDispatch for Pallet { log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", - bridge, + source_chain, id, actual_call_weight, message.weight, @@ -256,7 +272,7 @@ impl, I: Instance> MessageDispatch for Pallet { ); Self::deposit_event(RawEvent::MessageDispatched( - bridge, + source_chain, id, dispatch_result.map(drop).map_err(|e| e.error), )); @@ -303,23 +319,24 @@ where /// The byte vector returned by this function will be signed with a target chain account /// private key. This way, the owner of `source_account_id` on the source chain proves that /// the target chain account private key is also under his control. -pub fn account_ownership_digest( +pub fn account_ownership_digest( call: &Call, source_account_id: AccountId, target_spec_version: SpecVersion, - source_instance_id: BridgeId, + source_chain_id: ChainId, + target_chain_id: ChainId, ) -> Vec where Call: Encode, AccountId: Encode, SpecVersion: Encode, - BridgeId: Encode, { let mut proof = Vec::new(); call.encode_to(&mut proof); source_account_id.encode_to(&mut proof); target_spec_version.encode_to(&mut proof); - source_instance_id.encode_to(&mut proof); + source_chain_id.encode_to(&mut proof); + target_chain_id.encode_to(&mut proof); proof } @@ -342,6 +359,9 @@ mod tests { type AccountId = u64; type MessageId = [u8; 4]; + const SOURCE_CHAIN_ID: ChainId = *b"srce"; + const TARGET_CHAIN_ID: ChainId = *b"trgt"; + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] pub struct TestAccountPublic(AccountId); @@ -495,7 +515,6 @@ mod tests { #[test] fn should_fail_on_spec_version_mismatch() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; const BAD_SPEC_VERSION: SpecVersion = 99; @@ -504,14 +523,14 @@ mod tests { message.spec_version = BAD_SPEC_VERSION; System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageVersionSpecMismatch( - bridge, + SOURCE_CHAIN_ID, id, TEST_SPEC_VERSION, BAD_SPEC_VERSION @@ -525,21 +544,23 @@ mod tests { #[test] fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; let mut message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); message.weight = 0; System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageWeightMismatch( - bridge, id, 1345000, 0, + SOURCE_CHAIN_ID, + id, + 1345000, + 0, )), topics: vec![], }], @@ -550,7 +571,6 @@ mod tests { #[test] fn should_fail_on_signature_mismatch() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; let call_origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(99)); @@ -560,14 +580,15 @@ mod tests { ); System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageSignatureMismatch( - bridge, id + SOURCE_CHAIN_ID, + id )), topics: vec![], }], @@ -578,17 +599,19 @@ mod tests { #[test] fn should_emit_event_for_rejected_messages() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; System::set_block_number(1); - Dispatch::dispatch(bridge, id, Err(())); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(())); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageRejected(bridge, id)), + event: Event::call_dispatch(call_dispatch::Event::::MessageRejected( + SOURCE_CHAIN_ID, + id + )), topics: vec![], }], ); @@ -598,7 +621,6 @@ mod tests { #[test] fn should_fail_on_call_decode() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; let mut message = @@ -606,14 +628,15 @@ mod tests { message.call.0 = vec![]; System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageCallDecodeFailed( - bridge, id + SOURCE_CHAIN_ID, + id )), topics: vec![], }], @@ -624,7 +647,6 @@ mod tests { #[test] fn should_emit_event_for_rejected_calls() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; let call = Call::System(>::fill_block(Perbill::from_percent(75))); @@ -633,13 +655,16 @@ mod tests { message.weight = weight; System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageCallRejected(bridge, id)), + event: Event::call_dispatch(call_dispatch::Event::::MessageCallRejected( + SOURCE_CHAIN_ID, + id + )), topics: vec![], }], ); @@ -649,19 +674,18 @@ mod tests { #[test] fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { - let bridge = b"ethb".to_owned(); let id = [0; 4]; let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( - bridge, + SOURCE_CHAIN_ID, id, Ok(()) )), @@ -675,20 +699,19 @@ mod tests { fn should_dispatch_bridge_message_from_target_origin() { new_test_ext().execute_with(|| { let id = [0; 4]; - let bridge = b"ethb".to_owned(); let call = Call::System(>::remark(vec![])); let message = prepare_target_message(call); System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( - bridge, + SOURCE_CHAIN_ID, id, Ok(()) )), @@ -702,20 +725,19 @@ mod tests { fn should_dispatch_bridge_message_from_source_origin() { new_test_ext().execute_with(|| { let id = [0; 4]; - let bridge = b"ethb".to_owned(); let call = Call::System(>::remark(vec![])); let message = prepare_source_message(call); System::set_block_number(1); - Dispatch::dispatch(bridge, id, Ok(message)); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( - bridge, + SOURCE_CHAIN_ID, id, Ok(()) )), diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 7163d15ef1378..758bba5a718b7 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -31,7 +31,7 @@ pub type Kusama = PolkadotLike; // We use this to get the account on Kusama (target) which is derived from Polkadot's (source) // account. pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::POLKADOT_BRIDGE_INSTANCE, id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::POLKADOT_CHAIN_ID, id); AccountIdConverter::convert(encoded_id) } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index a5f3a888f9ad0..7b88b7c49ad04 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -201,7 +201,7 @@ impl sp_runtime::traits::Convert for AccountIdConverte /// /// Note that this should only be used for testing. pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_BRIDGE_INSTANCE, id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_CHAIN_ID, id); AccountIdConverter::convert(encoded_id) } diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 8e0d30cdb607f..7cd155d64a8fb 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -31,7 +31,7 @@ pub type Polkadot = PolkadotLike; // We use this to get the account on Polkadot (target) which is derived from Kusama's (source) // account. pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::KUSAMA_BRIDGE_INSTANCE, id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::KUSAMA_CHAIN_ID, id); AccountIdConverter::convert(encoded_id) } diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index c063dc72a7f25..3cd19739d46f9 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -162,7 +162,7 @@ impl Convert for AccountIdConverter { // // Note that this should only be used for testing. pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_BRIDGE_INSTANCE, id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_CHAIN_ID, id); AccountIdConverter::convert(encoded_id) } diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index db97364ef419a..42298100f670a 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -86,7 +86,7 @@ impl sp_runtime::traits::Dispatchable for Call { // We use this to get the account on Westend (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_BRIDGE_INSTANCE, id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_CHAIN_ID, id); AccountIdConverter::convert(encoded_id) } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 13462a820b899..bcb238e88ba3b 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -86,7 +86,7 @@ impl sp_runtime::traits::Dispatchable for Call { // We use this to get the account on Wococo (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_BRIDGE_INSTANCE, id); + let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_CHAIN_ID, id); AccountIdConverter::convert(encoded_id) } diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 1244371239644..a7b07abc98361 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_runtime::{InstanceId, Size}; +use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_std::prelude::*; @@ -43,7 +43,8 @@ pub trait MessageDispatch { /// Dispatches the message internally. /// - /// `bridge` indicates instance of deployed bridge where the message came from. + /// `source_chain` indicates the chain where the message came from. + /// `target_chain` indicates the chain where message dispatch happens. /// /// `id` is a short unique identifier of the message. /// @@ -51,7 +52,7 @@ pub trait MessageDispatch { /// a sign that some other component has rejected the message even before it has /// reached `dispatch` method (right now this may only be caused if we fail to decode /// the whole message). - fn dispatch(bridge: InstanceId, id: MessageId, message: Result); + fn dispatch(source_chain: ChainId, target_chain: ChainId, id: MessageId, message: Result); } /// Origin of a Call when it is dispatched on the target chain. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index aa457f1d0b0bc..80f644a588b90 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -33,25 +33,25 @@ 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]; +pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0]; /// Bridge-with-Rialto instance id. -pub const RIALTO_BRIDGE_INSTANCE: InstanceId = *b"rlto"; +pub const RIALTO_CHAIN_ID: ChainId = *b"rlto"; /// Bridge-with-Millau instance id. -pub const MILLAU_BRIDGE_INSTANCE: InstanceId = *b"mlau"; +pub const MILLAU_CHAIN_ID: ChainId = *b"mlau"; /// Bridge-with-Polkadot instance id. -pub const POLKADOT_BRIDGE_INSTANCE: InstanceId = *b"pdot"; +pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; /// Bridge-with-Kusama instance id. -pub const KUSAMA_BRIDGE_INSTANCE: InstanceId = *b"ksma"; +pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; /// Bridge-with-Rococo instance id. -pub const ROCOCO_BRIDGE_INSTANCE: InstanceId = *b"roco"; +pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; /// Bridge-with-Wococo instance id. -pub const WOCOCO_BRIDGE_INSTANCE: InstanceId = *b"woco"; +pub const WOCOCO_CHAIN_ID: ChainId = *b"woco"; /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch"; @@ -62,11 +62,13 @@ 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"; -/// 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]; +/// 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. +pub type ChainId = [u8; 4]; /// Type of accounts on the source chain. pub enum SourceAccount { @@ -90,7 +92,7 @@ pub enum SourceAccount { /// 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(bridge_id: InstanceId, id: SourceAccount) -> H256 +pub fn derive_account_id(bridge_id: ChainId, id: SourceAccount) -> H256 where AccountId: Encode, { @@ -107,7 +109,7 @@ where /// /// 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 { +pub fn derive_relayer_fund_account_id(bridge_id: ChainId) -> H256 { ("relayer-fund-account", bridge_id).using_encoded(blake2_256).into() } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index d96fa7b797209..65dbe30d5a4ac 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -23,7 +23,7 @@ use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use bp_messages::MessageNonce; -use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; +use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; @@ -200,14 +200,14 @@ pub async fn run( source_client.clone(), lane.clone(), lane_id, - RIALTO_BRIDGE_INSTANCE, + RIALTO_CHAIN_ID, params.target_to_source_headers_relay, ), RialtoTargetClient::new( params.target_client, lane, lane_id, - MILLAU_BRIDGE_INSTANCE, + MILLAU_CHAIN_ID, params.source_to_target_headers_relay, ), relay_utils::relay_metrics( diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index b4061ced37f72..7b7b768635812 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -86,7 +86,7 @@ mod tests { let millau_public: bp_millau::AccountSigner = millau_sign.public().into(); let millau_account_id: bp_millau::AccountId = millau_public.into_account(); - let digest = millau_runtime::rialto_account_ownership_digest( + let digest = millau_runtime::millau_to_rialto_account_ownership_digest( &call, millau_account_id, rialto_runtime::VERSION.spec_version, @@ -107,7 +107,7 @@ mod tests { let rialto_public: bp_rialto::AccountSigner = rialto_sign.public().into(); let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); - let digest = rialto_runtime::millau_account_ownership_digest( + let digest = rialto_runtime::rialto_to_millau_account_ownership_digest( &call, rialto_account_id, millau_runtime::VERSION.spec_version, diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index ec39a4caa3fcb..3637e771e5b17 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -23,7 +23,7 @@ use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; use bp_messages::MessageNonce; -use bp_runtime::{MILLAU_BRIDGE_INSTANCE, RIALTO_BRIDGE_INSTANCE}; +use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; @@ -199,14 +199,14 @@ pub async fn run( source_client.clone(), lane.clone(), lane_id, - MILLAU_BRIDGE_INSTANCE, + MILLAU_CHAIN_ID, params.target_to_source_headers_relay, ), MillauTargetClient::new( params.target_client, lane, lane_id, - RIALTO_BRIDGE_INSTANCE, + RIALTO_CHAIN_ID, params.source_to_target_headers_relay, ), relay_utils::relay_metrics( diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 996edb49942a1..b54d3a72ad3b2 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -64,7 +64,7 @@ macro_rules! select_full_bridge { use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; // Send-message #[allow(unused_imports)] - use millau_runtime::rialto_account_ownership_digest as account_ownership_digest; + use millau_runtime::millau_to_rialto_account_ownership_digest as account_ownership_digest; $generic } @@ -87,7 +87,7 @@ macro_rules! select_full_bridge { // Send-message #[allow(unused_imports)] - use rialto_runtime::millau_account_ownership_digest as account_ownership_digest; + use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest; $generic } diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 0ccf8bbde885a..36f8b6d85cdea 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -23,7 +23,7 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::InstanceId; +use bp_runtime::ChainId; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight}; @@ -50,7 +50,7 @@ pub struct SubstrateMessagesSource { client: Client, lane: P, lane_id: LaneId, - instance: InstanceId, + instance: ChainId, target_to_source_headers_relay: Option>, _phantom: PhantomData<(R, I)>, } @@ -61,7 +61,7 @@ impl SubstrateMessagesSource, lane: P, lane_id: LaneId, - instance: InstanceId, + instance: ChainId, target_to_source_headers_relay: Option>, ) -> Self { SubstrateMessagesSource { diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 39f638d7e91c1..004bb47db518f 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -24,7 +24,7 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::InstanceId; +use bp_runtime::ChainId; use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use codec::{Decode, Encode}; use frame_support::traits::Instance; @@ -50,7 +50,7 @@ pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, - instance: InstanceId, + instance: ChainId, source_to_target_headers_relay: Option>, _phantom: PhantomData<(R, I)>, } @@ -61,7 +61,7 @@ impl SubstrateMessagesTarget, lane: P, lane_id: LaneId, - instance: InstanceId, + instance: ChainId, source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { From 5a220331412fcb7b5f7a7a6bae46fbe824e7216c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 May 2021 14:00:09 +0300 Subject: [PATCH 0465/1210] Start finality relay spec-version guards for Rococo <> Wococo finality relays (#965) * start finality relay guards * comment --- .../bin-substrate/src/chains/rococo_headers_to_wococo.rs | 9 ++++++++- .../bin-substrate/src/chains/wococo_headers_to_rococo.rs | 9 ++++++++- relays/bin-substrate/src/cli/relay_headers.rs | 1 + relays/bin-substrate/src/finality_pipeline.rs | 7 +++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 5247c6068b5ec..4dfe800b2b6cd 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -21,7 +21,7 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityT use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; use sp_core::{Bytes, Pair}; @@ -38,6 +38,13 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { crate::chains::add_polkadot_kusama_price_metrics::(params) } + fn start_relay_guards(target_client: &Client) { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + bp_wococo::VERSION.spec_version, + ) + } + fn transactions_author(&self) -> bp_wococo::AccountId { (*self.target_sign.public().as_array_ref()).into() } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 9dfae5294e292..3b6a478269a97 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -21,7 +21,7 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityT use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; use sp_core::{Bytes, Pair}; @@ -38,6 +38,13 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { crate::chains::add_polkadot_kusama_price_metrics::(params) } + fn start_relay_guards(target_client: &Client) { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + bp_rococo::VERSION.spec_version, + ) + } + fn transactions_author(&self) -> bp_rococo::AccountId { (*self.target_sign.public().as_array_ref()).into() } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index e8459b58bf605..c0d80f80d36be 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -97,6 +97,7 @@ impl RelayHeaders { let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; + Finality::start_relay_guards(&target_client); crate::finality_pipeline::run( Finality::new(target_client.clone(), target_sign), diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index dad69b1576b0e..f1c72184cc080 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -46,6 +46,13 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { Ok(params) } + /// Start finality relay guards. + /// + /// Different finality bridges may have different set of guards - e.g. on ephemeral chains we + /// don't need version guards, on test chains we don't care that much about relayer account + /// balance, ... So the implementation is left to the specific bridges. + fn start_relay_guards(_target_client: &Client) {} + /// Returns id of account that we're using to sign transactions at target chain. fn transactions_author(&self) -> ::AccountId; From 33416cc582c7735b003fd7883f089b725d137b67 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Thu, 13 May 2021 19:55:35 +0800 Subject: [PATCH 0466/1210] Correct type error (#968) --- relays/bin-substrate/src/chains/millau_messages_to_rialto.rs | 2 +- relays/bin-substrate/src/chains/rialto_messages_to_millau.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 65dbe30d5a4ac..de2246a92303e 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -59,7 +59,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { type SourceChain = Millau; type TargetChain = Rialto; - fn source_transactions_author(&self) -> bp_rialto::AccountId { + fn source_transactions_author(&self) -> bp_millau::AccountId { (*self.source_sign.public().as_array_ref()).into() } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 3637e771e5b17..981bc76db69c1 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -86,7 +86,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { Bytes(transaction.encode()) } - fn target_transactions_author(&self) -> bp_rialto::AccountId { + fn target_transactions_author(&self) -> bp_millau::AccountId { (*self.target_sign.public().as_array_ref()).into() } From b1699f9b5f6cf206a944e718309a6cb2cbdf2ef3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 May 2021 19:28:54 +0300 Subject: [PATCH 0467/1210] Serve multiple lanes with single complex relay instance (#964) * serve multiple lanes with single complex relay instance * Update relays/bin-substrate/src/cli/relay_headers_and_messages.rs Co-authored-by: Hernando Castano * revert default value removal Co-authored-by: Hernando Castano --- .../src/cli/relay_headers_and_messages.rs | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index f2238ba5763c1..4955e8bbef338 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -40,9 +40,9 @@ pub enum RelayHeadersAndMessages { /// Parameters that have the same names across all bridges. #[derive(StructOpt)] pub struct HeadersAndMessagesSharedParams { - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + /// Hex-encoded lane identifiers that should be served by the complex relay. #[structopt(long, default_value = "00000000")] - lane: HexLaneId, + lane: Vec, #[structopt(flatten)] prometheus_params: PrometheusParams, } @@ -125,7 +125,7 @@ impl RelayHeadersAndMessages { let right_client = params.right.to_client::().await?; let right_sign = params.right_sign.to_keypair::()?; - let lane = params.shared.lane.into(); + let lanes = params.shared.lane; let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); @@ -143,46 +143,49 @@ impl RelayHeadersAndMessages { MAX_MISSING_RIGHT_HEADERS_AT_LEFT, ); - let left_to_right_messages = left_to_right_messages(MessagesRelayParams { - source_client: left_client.clone(), - source_sign: left_sign.clone(), - target_client: right_client.clone(), - target_sign: right_sign.clone(), - source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), - target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params - .clone() - .disable() - .metrics_prefix(messages_relay::message_lane_loop::metrics_prefix::(&lane)), - }) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - let right_to_left_messages = right_to_left_messages(MessagesRelayParams { - source_client: right_client, - source_sign: right_sign, - target_client: left_client.clone(), - target_sign: left_sign.clone(), - source_to_target_headers_relay: Some(right_to_left_on_demand_headers), - target_to_source_headers_relay: Some(left_to_right_on_demand_headers), - lane_id: lane, - metrics_params: metrics_params - .clone() - .disable() - .metrics_prefix(messages_relay::message_lane_loop::metrics_prefix::(&lane)), - }) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); + // Need 2x capacity since we consider both directions for each lane + let mut message_relays = Vec::with_capacity(lanes.len() * 2); + for lane in lanes { + let lane = lane.into(); + let left_to_right_messages = left_to_right_messages(MessagesRelayParams { + source_client: left_client.clone(), + source_sign: left_sign.clone(), + target_client: right_client.clone(), + target_sign: right_sign.clone(), + source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), + target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), + lane_id: lane, + metrics_params: metrics_params.clone().disable().metrics_prefix( + messages_relay::message_lane_loop::metrics_prefix::(&lane), + ), + }) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + let right_to_left_messages = right_to_left_messages(MessagesRelayParams { + source_client: right_client.clone(), + source_sign: right_sign.clone(), + target_client: left_client.clone(), + target_sign: left_sign.clone(), + source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), + target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), + lane_id: lane, + metrics_params: metrics_params.clone().disable().metrics_prefix( + messages_relay::message_lane_loop::metrics_prefix::(&lane), + ), + }) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + + message_relays.push(left_to_right_messages); + message_relays.push(right_to_left_messages); + } relay_utils::relay_metrics(None, metrics_params) .expose() .await .map_err(|e| anyhow::format_err!("{}", e))?; - futures::future::select(left_to_right_messages, right_to_left_messages) - .await - .factor_first() - .0 + futures::future::select_all(message_relays).await.0 }) } } From 6e3e12d812a68239938cb2a462a5815dd195e1a7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 14 May 2021 11:52:54 +0300 Subject: [PATCH 0468/1210] removed stray file (#969) --- .../src/chains/westend_headers_to_rococo.rs | 60 ------------------- 1 file changed, 60 deletions(-) delete mode 100644 relays/bin-substrate/src/chains/westend_headers_to_rococo.rs diff --git a/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs b/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs deleted file mode 100644 index f1b390215748d..0000000000000 --- a/relays/bin-substrate/src/chains/westend_headers_to_rococo.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 . - -//! Westend-to-Rococo headers sync entrypoint. - -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; - -use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; -use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; -use relay_utils::metrics::MetricsParams; -use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; -use sp_core::{Bytes, Pair}; - -/// Westend-to-Rococo finality sync pipeline. -pub(crate) type WestendFinalityToRococo = SubstrateFinalityToSubstrate; - -impl SubstrateFinalitySyncPipeline for WestendFinalityToRococo { - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; - - type TargetChain = Rococo; - - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn transactions_author(&self) -> bp_rococo::AccountId { - (*self.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - transaction_nonce: ::Index, - header: WestendSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = bp_rococo::Call::BridgeGrandpaWestend(bp_rococo::BridgeGrandpaCall::submit_finality_proof( - header.into_inner(), - proof, - )); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); - - Bytes(transaction.encode()) - } -} From 5e7f023d01e1e923290a57f781b6b3ce7c6366fc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 18 May 2021 16:35:41 +0300 Subject: [PATCH 0469/1210] in auto-relays keep trying to connect to nodes until connection is established (#971) --- .../src/ethereum_deploy_contract.rs | 4 +-- relays/bin-ethereum/src/ethereum_exchange.rs | 14 +++++------ .../src/ethereum_exchange_submit.rs | 2 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 4 +-- .../bin-ethereum/src/substrate_sync_loop.rs | 4 +-- relays/bin-substrate/src/cli/mod.rs | 2 +- relays/client-ethereum/Cargo.toml | 1 + relays/client-ethereum/src/client.rs | 24 +++++++++++++++++- relays/client-substrate/src/client.rs | 25 ++++++++++++++++++- 9 files changed, 62 insertions(+), 18 deletions(-) diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs index 84c12be7a7081..3f9076f6db229 100644 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -60,8 +60,8 @@ pub async fn run(params: EthereumDeployContractParams) { } = params; let result = async move { - let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::new(sub_params).await.map_err(RpcError::Substrate)?; + let eth_client = EthereumClient::try_connect(eth_params).await.map_err(RpcError::Ethereum)?; + let sub_client = SubstrateClient::::try_connect(sub_params).await.map_err(RpcError::Substrate)?; let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; let initial_set_id = sub_initial_authorities_set_id.unwrap_or(0); diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index 18470512b5d6b..3111aa2de4363 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -335,8 +335,10 @@ async fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_has .. } = params; - let eth_client = EthereumClient::new(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::new(sub_params) + let eth_client = EthereumClient::try_connect(eth_params) + .await + .map_err(RpcError::Ethereum)?; + let sub_client = SubstrateClient::::try_connect(sub_params) .await .map_err(RpcError::Substrate)?; @@ -363,12 +365,8 @@ async fn run_auto_transactions_relay_loop( .. } = params; - let eth_client = EthereumClient::new(eth_params) - .await - .map_err(|err| format!("Error starting Ethereum client: {:?}", err))?; - let sub_client = SubstrateClient::::new(sub_params) - .await - .map_err(|err| format!("Error starting Substrate client: {:?}", err))?; + let eth_client = EthereumClient::new(eth_params).await; + let sub_client = SubstrateClient::::new(sub_params).await; let eth_start_with_block_number = match eth_start_with_block_number { Some(eth_start_with_block_number) => eth_start_with_block_number, diff --git a/relays/bin-ethereum/src/ethereum_exchange_submit.rs b/relays/bin-ethereum/src/ethereum_exchange_submit.rs index 09871a0fc786b..602d4f14e4f0b 100644 --- a/relays/bin-ethereum/src/ethereum_exchange_submit.rs +++ b/relays/bin-ethereum/src/ethereum_exchange_submit.rs @@ -52,7 +52,7 @@ pub async fn run(params: EthereumExchangeSubmitParams) { } = params; let result: Result<_, String> = async move { - let eth_client = EthereumClient::new(eth_params) + let eth_client = EthereumClient::try_connect(eth_params) .await .map_err(|err| format!("error connecting to Ethereum node: {:?}", err))?; diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index 3dcd27e18f6be..111abcd86e710 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -270,8 +270,8 @@ pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { instance, } = params; - let eth_client = EthereumClient::new(eth_params).await?; - let sub_client = SubstrateClient::::new(sub_params).await?; + let eth_client = EthereumClient::new(eth_params).await; + let sub_client = SubstrateClient::::new(sub_params).await; let sign_sub_transactions = match sync_params.target_tx_mode { TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index 4e7e433d82617..542fd41f72732 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -177,8 +177,8 @@ pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { metrics_params, } = params; - let eth_client = EthereumClient::new(eth_params).await?; - let sub_client = SubstrateClient::::new(sub_params).await?; + let eth_client = EthereumClient::new(eth_params).await; + let sub_client = SubstrateClient::::new(sub_params).await; let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); let source = SubstrateHeadersSource::new(sub_client); diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 341051de5c279..49bc5dc8c8372 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -406,7 +406,7 @@ macro_rules! declare_chain_options { port: self.[<$chain_prefix _port>], secure: self.[<$chain_prefix _secure>], }) - .await? + .await ) } } diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index da4e7ef59efee..64a76a6b5dae3 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +async-std = "1.6.5" bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.0.0" } headers-relay = { path = "../headers" } diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs index e2def5fb03d11..71dac5df6d481 100644 --- a/relays/client-ethereum/src/client.rs +++ b/relays/client-ethereum/src/client.rs @@ -22,6 +22,7 @@ use crate::types::{ use crate::{ConnectionParams, Error, Result}; use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; +use relay_utils::relay_loop::RECONNECT_DELAY; use std::sync::Arc; /// Number of headers missing from the Ethereum node for us to consider node not synced. @@ -36,7 +37,28 @@ pub struct Client { impl Client { /// Create a new Ethereum RPC Client. - pub async fn new(params: ConnectionParams) -> Result { + /// + /// This function will keep connecting to given Ethereum node until connection is established + /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. + pub async fn new(params: ConnectionParams) -> Self { + loop { + match Self::try_connect(params.clone()).await { + Ok(client) => return client, + Err(error) => log::error!( + target: "bridge", + "Failed to connect to Ethereum node: {:?}. Going to retry in {}s", + error, + RECONNECT_DELAY.as_secs(), + ), + } + + async_std::task::sleep(RECONNECT_DELAY).await; + } + } + + /// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been established + /// or error otherwise. + pub async fn try_connect(params: ConnectionParams) -> Result { Ok(Self { client: Self::build_client(¶ms).await?, params, diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 892a63d6d5b00..ec4220158e77b 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -27,6 +27,7 @@ use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use num_traits::Zero; use pallet_balances::AccountData; +use relay_utils::relay_loop::RECONNECT_DELAY; use sp_core::{storage::StorageKey, Bytes}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; @@ -77,7 +78,29 @@ impl std::fmt::Debug for Client { impl Client { /// Returns client that is able to call RPCs on Substrate node over websocket connection. - pub async fn new(params: ConnectionParams) -> Result { + /// + /// This function will keep connecting to given Sustrate node until connection is established + /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. + pub async fn new(params: ConnectionParams) -> Self { + loop { + match Self::try_connect(params.clone()).await { + Ok(client) => return client, + Err(error) => log::error!( + target: "bridge", + "Failed to connect to {} node: {:?}. Going to retry in {}s", + C::NAME, + error, + RECONNECT_DELAY.as_secs(), + ), + } + + async_std::task::sleep(RECONNECT_DELAY).await; + } + } + + /// Try to connect to Substrate node over websocket. Returns Substrate RPC client if connection + /// has been established or error otherwise. + pub async fn try_connect(params: ConnectionParams) -> Result { let client = Self::build_client(params.clone()).await?; let number: C::BlockNumber = Zero::zero(); From 5f293af8f32e40ac91899569d934d110c0cdfc73 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 20 May 2021 02:09:13 +0300 Subject: [PATCH 0470/1210] Avoid hashing headers twice in verify_justification (#973) --- primitives/header-chain/src/justification.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 139b430324391..e3bff85e504c3 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -109,12 +109,8 @@ where } } - let ancestry_hashes = justification - .votes_ancestries - .iter() - .map(|h: &Header| h.hash()) - .collect(); - if visited_hashes != ancestry_hashes { + // both iterators are `BTree*` iterators, so have the same order => safe to compare + if !visited_hashes.iter().eq(ancestry_chain.ancestry.keys()) { return Err(Error::InvalidPrecommitAncestries); } From d75ab183d48fd750e052d8b902c5a7a0665f6206 Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Thu, 20 May 2021 11:43:10 -0600 Subject: [PATCH 0471/1210] Revert to use InspectCmd, bump substrate `6bef4f4` (#966) * revert to use InspectCmd * rust toolchain 1.52 * Bump `finality-grandpa` and `parity-scale-codec` * bump to same version for substrate as polkadot v0.9.1 * bump to polkadot 0.9.2 deps for substrate `6bef4f4` Co-authored-by: Hernando Castano --- bin/millau/node/src/cli.rs | 2 +- bin/rialto/node/src/cli.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 12f99b6b95bab..46323ed25c9ed 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -63,7 +63,7 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// Inspect blocks or extrinsics. - Inspect(node_inspect::cli::InspectKeyCmd), + Inspect(node_inspect::cli::InspectCmd), /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 12f99b6b95bab..46323ed25c9ed 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -63,7 +63,7 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// Inspect blocks or extrinsics. - Inspect(node_inspect::cli::InspectKeyCmd), + Inspect(node_inspect::cli::InspectCmd), /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), From 8b47eafed8171359407e24a5a67d315835df8a7e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Fri, 21 May 2021 12:28:03 -0400 Subject: [PATCH 0472/1210] Bump Rococo/Wococo spec_version (#976) --- primitives/chain-rococo/src/lib.rs | 4 ++-- primitives/chain-wococo/src/lib.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a4ecf93f1c98c..5bac304376e63 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -35,9 +35,9 @@ pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), authoring_version: 0, - spec_version: 9001, + spec_version: 9003, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index bcb238e88ba3b..67510f6f46a3c 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -35,9 +35,9 @@ pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v1.5"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), authoring_version: 0, - spec_version: 9001, + spec_version: 9003, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, From 513e257fd66c1f73cb263f46ff5314fb7df4a004 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 26 May 2021 09:23:31 +0300 Subject: [PATCH 0473/1210] Always run on-demand headers relay in complex relay (#975) * always run on-demand headers relay in complex relay * fix compilation --- relays/bin-substrate/src/cli/relay_headers.rs | 1 - relays/bin-substrate/src/finality_pipeline.rs | 8 +- relays/bin-substrate/src/messages_source.rs | 2 +- relays/bin-substrate/src/messages_target.rs | 2 +- relays/bin-substrate/src/on_demand_headers.rs | 372 +++++++----------- relays/client-substrate/Cargo.toml | 2 +- .../client-substrate/src/finality_source.rs | 33 +- relays/finality/src/finality_loop.rs | 3 - relays/finality/src/finality_loop_tests.rs | 1 - relays/utils/src/relay_loop.rs | 23 +- 10 files changed, 166 insertions(+), 281 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index c0d80f80d36be..abce9b3bfe163 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -103,7 +103,6 @@ impl RelayHeaders { Finality::new(target_client.clone(), target_sign), source_client, target_client, - false, metrics_params, ) .await diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index f1c72184cc080..fd222f1c2981b 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -26,12 +26,12 @@ use sp_core::Bytes; use std::{fmt::Debug, marker::PhantomData, time::Duration}; /// Default synchronization loop timeout. -const STALL_TIMEOUT: Duration = Duration::from_secs(120); +pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(120); /// Default limit of recent finality proofs. /// /// Finality delay of 4096 blocks is unlikely to happen in practice in /// Substrate+GRANDPA based chains (good to know). -const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; +pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; /// Headers sync pipeline for Substrate <-> Substrate relays. pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { @@ -119,7 +119,6 @@ pub async fn run( pipeline: P, source_client: Client, target_client: Client, - is_on_demand_task: bool, metrics_params: MetricsParams, ) -> anyhow::Result<()> where @@ -142,10 +141,9 @@ where ); finality_relay::run( - FinalitySource::new(source_client), + FinalitySource::new(source_client, None), SubstrateFinalityTarget::new(target_client, pipeline), FinalitySyncParams { - is_on_demand_task, tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 36f8b6d85cdea..49e2c7efeea93 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -239,7 +239,7 @@ where async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

) { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { - target_to_source_headers_relay.require_finalized_header(id); + target_to_source_headers_relay.require_finalized_header(id).await; } } } diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 004bb47db518f..715efce88ec28 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -226,7 +226,7 @@ where async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

) { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { - source_to_target_headers_relay.require_finalized_header(id); + source_to_target_headers_relay.require_finalized_header(id).await; } } } diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs index 77d2b37054104..5730fc3869be7 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -16,39 +16,38 @@ //! On-demand Substrate -> Substrate headers relay. -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use crate::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, STALL_TIMEOUT, +}; use crate::finality_target::SubstrateFinalityTarget; +use async_std::sync::{Arc, Mutex}; use bp_header_chain::justification::GrandpaJustification; use finality_relay::{ - FinalitySyncPipeline, SourceClient as FinalitySourceClient, TargetClient as FinalityTargetClient, -}; -use futures::{ - channel::{mpsc, oneshot}, - select, FutureExt, StreamExt, + FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, + TargetClient as FinalityTargetClient, }; +use futures::{select, FutureExt}; use num_traits::{CheckedSub, Zero}; use relay_substrate_client::{ - finality_source::FinalitySource as SubstrateFinalitySource, BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, - SyncHeader, + finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef}, + BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader, }; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, HeaderId, - MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, MaybeConnectionError, }; use std::fmt::Debug; /// On-demand Substrate <-> Substrate headers relay. /// -/// This relay may be started by messages whenever some other relay (e.g. messages relay) needs more -/// headers to be relayed to continue its regular work. When enough headers are relayed, on-demand -/// relay may be deactivated. +/// This relay may be requested to sync more headers, whenever some other relay (e.g. messages relay) needs +/// it to continue its regular work. When enough headers are relayed, on-demand stops syncing headers. #[derive(Clone)] pub struct OnDemandHeadersRelay { - /// Background task name. - background_task_name: String, - /// Required headers to background sender. - required_header_tx: mpsc::Sender>, + /// Relay task name. + relay_task_name: String, + /// Shared reference to maximal required finalized header number. + required_header_number: RequiredHeaderNumberRef, } impl OnDemandHeadersRelay { @@ -75,49 +74,49 @@ impl OnDemandHeadersRelay { SubstrateFinalityTarget>: FinalityTargetClient>, { - let (required_header_tx, required_header_rx) = mpsc::channel(1); + let required_header_number = Arc::new(Mutex::new(Zero::zero())); + let this = OnDemandHeadersRelay { + relay_task_name: on_demand_headers_relay_name::(), + required_header_number: required_header_number.clone(), + }; async_std::task::spawn(async move { background_task( source_client, target_client, pipeline, maximal_headers_difference, - required_header_rx, + required_header_number, ) .await; }); - let background_task_name = format!( - "{}-background", - on_demand_headers_relay_name::() - ); - OnDemandHeadersRelay { - background_task_name, - required_header_tx, - } + this } /// Someone is asking us to relay given finalized header. - pub fn require_finalized_header(&self, header_id: HeaderIdOf) { - if let Err(error) = self.required_header_tx.clone().try_send(header_id) { - log::error!( + pub async fn require_finalized_header(&self, header_id: HeaderIdOf) { + let mut required_header_number = self.required_header_number.lock().await; + if header_id.0 > *required_header_number { + log::trace!( target: "bridge", - "Failed to send require header id {:?} to {:?}: {:?}", - header_id, - self.background_task_name, - error, + "More {} headers required in {} relay. Going to sync up to the {}", + SourceChain::NAME, + self.relay_task_name, + header_id.0, ); + + *required_header_number = header_id.0; } } } -/// Background task that is responsible for starting and stopping headers relay when required. +/// Background task that is responsible for starting headers relay. async fn background_task( source_client: Client, target_client: Client, pipeline: SubstrateFinalityToSubstrate, maximal_headers_difference: SourceChain::BlockNumber, - mut required_header_rx: mpsc::Receiver>, + required_header_number: RequiredHeaderNumberRef, ) where SourceChain: Chain + Debug, SourceChain::BlockNumber: BlockNumberBase, @@ -138,36 +137,19 @@ async fn background_task( let mut finality_source = SubstrateFinalitySource::< _, SubstrateFinalityToSubstrate, - >::new(source_client.clone()); + >::new(source_client.clone(), Some(required_header_number.clone())); let mut finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); - let mut active_headers_relay = None; - let mut required_header_number = Zero::zero(); - let mut relay_exited_rx = futures::future::pending().left_future(); + let mut restart_relay = true; + let finality_relay_task = futures::future::Fuse::terminated(); + futures::pin_mut!(finality_relay_task); loop { - // wait for next target block or for new required header select! { _ = async_std::task::sleep(TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, - required_header_id = required_header_rx.next() => { - match required_header_id { - Some(required_header_id) => { - if required_header_id.0 > required_header_number { - required_header_number = required_header_id.0; - } - }, - None => { - // that's the only way to exit background task - to drop `required_header_tx` - break - }, - } - }, - _ = relay_exited_rx => { - // there could be a situation when we're receiving exit signals after we - // have already stopped relay or when we have already started new relay. - // but it isn't critical, because even if we'll accidentally stop new relay - // we'll restart it almost immediately - stop_on_demand_headers_relay(active_headers_relay.take()).await; + _ = finality_relay_task => { + // this should never happen in practice given the current code + restart_relay = true; }, } @@ -199,107 +181,53 @@ async fn background_task( continue; } - // start or stop headers relay if required - let action = select_on_demand_relay_action::( + // update required header + update_required_header_number_if_too_many_are_missing::( best_finalized_source_header_at_source.ok(), best_finalized_source_header_at_target.ok(), - required_header_number, maximal_headers_difference, + &required_header_number, &relay_task_name, - active_headers_relay.is_some(), - ); - match action { - OnDemandRelayAction::Start => { - let (relay_exited_tx, new_relay_exited_rx) = oneshot::channel(); - active_headers_relay = start_on_demand_headers_relay( - relay_task_name.clone(), - relay_exited_tx, - source_client.clone(), - target_client.clone(), - pipeline.clone(), - ); - if active_headers_relay.is_some() { - relay_exited_rx = new_relay_exited_rx.right_future(); - } - } - OnDemandRelayAction::Stop => { - stop_on_demand_headers_relay(active_headers_relay.take()).await; - } - OnDemandRelayAction::None => (), - } - } -} - -/// Read best finalized source block number from source client. -/// -/// Returns `None` if we have failed to read the number. -async fn best_finalized_source_header_at_source( - finality_source: &SubstrateFinalitySource, - relay_task_name: &str, -) -> Result as RelayClient>::Error> -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ - finality_source.best_finalized_block_number().await.map_err(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from source in {} relay: {:?}", - relay_task_name, - error, - ); - - error - }) -} - -/// Read best finalized source block number from target client. -/// -/// Returns `None` if we have failed to read the number. -async fn best_finalized_source_header_at_target( - finality_target: &SubstrateFinalityTarget, - relay_task_name: &str, -) -> Result as RelayClient>::Error> -where - SubstrateFinalityTarget: FinalityTargetClient

, - P: FinalitySyncPipeline, -{ - finality_target - .best_finalized_source_block_number() - .await - .map_err(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from target in {} relay: {:?}", - relay_task_name, - error, + ) + .await; + + // start/restart relay + if restart_relay { + finality_relay_task.set( + finality_relay::run( + finality_source.clone(), + finality_target.clone(), + FinalitySyncParams { + tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), + recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, + stall_timeout: STALL_TIMEOUT, + }, + MetricsParams::disabled(), + futures::future::pending(), + ) + .fuse(), ); - error - }) -} - -/// What to do with the on-demand relay task? -#[derive(Debug, PartialEq)] -enum OnDemandRelayAction { - Start, - Stop, - None, + restart_relay = false; + } + } } -fn select_on_demand_relay_action( +/// If there are too many source headers missing at target, we ask for syncing more headers. +async fn update_required_header_number_if_too_many_are_missing( best_finalized_source_header_at_source: Option, best_finalized_source_header_at_target: Option, - mut required_source_header_at_target: C::BlockNumber, maximal_headers_difference: C::BlockNumber, + required_header_number: &RequiredHeaderNumberRef, relay_task_name: &str, - is_active: bool, -) -> OnDemandRelayAction { +) { + let mut required_header_number = required_header_number.lock().await; + // if we have been unable to read header number from the target, then let's assume // that it is the same as required header number. Otherwise we risk submitting // unneeded transactions let best_finalized_source_header_at_target = - best_finalized_source_header_at_target.unwrap_or(required_source_header_at_target); + best_finalized_source_header_at_target.unwrap_or(*required_header_number); // if we have been unable to read header number from the source, then let's assume // that it is the same as at the target @@ -318,10 +246,8 @@ fn select_on_demand_relay_action( .checked_sub(&best_finalized_source_header_at_target) .unwrap_or_else(Zero::zero); if current_headers_difference > maximal_headers_difference { - required_source_header_at_target = best_finalized_source_header_at_source; - - // don't log if relay is already running - if !is_active { + // if relay is already asked to sync headers, don't log anything + if *required_header_number <= best_finalized_source_header_at_target { log::trace!( target: "bridge", "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the {}", @@ -331,76 +257,67 @@ fn select_on_demand_relay_action( best_finalized_source_header_at_target, best_finalized_source_header_at_source, ); - } - } - // now let's select what to do with relay - let needs_to_be_active = required_source_header_at_target > best_finalized_source_header_at_target; - match (needs_to_be_active, is_active) { - (true, false) => OnDemandRelayAction::Start, - (false, true) => OnDemandRelayAction::Stop, - _ => OnDemandRelayAction::None, + *required_header_number = best_finalized_source_header_at_source; + } } } -/// On-demand headers relay task name. -fn on_demand_headers_relay_name() -> String { - format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) +/// Read best finalized source block number from source client. +/// +/// Returns `None` if we have failed to read the number. +async fn best_finalized_source_header_at_source( + finality_source: &SubstrateFinalitySource, + relay_task_name: &str, +) -> Result +where + SubstrateFinalitySource: FinalitySourceClient

, + P: FinalitySyncPipeline, +{ + finality_source + .on_chain_best_finalized_block_number() + .await + .map_err(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from source in {} relay: {:?}", + relay_task_name, + error, + ); + + error + }) } -/// Start on-demand headers relay task. -fn start_on_demand_headers_relay( - task_name: String, - relay_exited_tx: oneshot::Sender<()>, - source_client: Client, - target_client: Client, - pipeline: SubstrateFinalityToSubstrate, -) -> Option> +/// Read best finalized source block number from target client. +/// +/// Returns `None` if we have failed to read the number. +async fn best_finalized_source_header_at_target( + finality_target: &SubstrateFinalityTarget, + relay_task_name: &str, +) -> Result as RelayClient>::Error> where - SourceChain::BlockNumber: BlockNumberBase, - SubstrateFinalityToSubstrate: SubstrateFinalitySyncPipeline< - Hash = HashOf, - Number = BlockNumberOf, - Header = SyncHeader, - FinalityProof = GrandpaJustification, - TargetChain = TargetChain, - >, - TargetSign: 'static, + SubstrateFinalityTarget: FinalityTargetClient

, + P: FinalitySyncPipeline, { - let headers_relay_future = - crate::finality_pipeline::run(pipeline, source_client, target_client, true, MetricsParams::disabled()); - let closure_task_name = task_name.clone(); - async_std::task::Builder::new() - .name(task_name.clone()) - .spawn(async move { - log::info!(target: "bridge", "Starting {} headers relay", closure_task_name); - let result = headers_relay_future.await; - log::trace!(target: "bridge", "{} headers relay has exited. Result: {:?}", closure_task_name, result); - let _ = relay_exited_tx.send(()); - }) + finality_target + .best_finalized_source_block_number() + .await .map_err(|error| { log::error!( target: "bridge", - "Failed to start {} relay: {:?}", - task_name, + "Failed to read best finalized source header from target in {} relay: {:?}", + relay_task_name, error, ); + + error }) - .ok() } -/// Stop on-demand headers relay task. -async fn stop_on_demand_headers_relay(task: Option>) { - if let Some(task) = task { - let task_name = task - .task() - .name() - .expect("on-demand tasks are always started with name; qed") - .to_string(); - log::trace!(target: "bridge", "Cancelling {} headers relay", task_name); - task.cancel().await; - log::info!(target: "bridge", "Cancelled {} headers relay", task_name); - } +/// On-demand headers relay task name. +fn on_demand_headers_relay_name() -> String { + format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) } #[cfg(test)] @@ -412,42 +329,17 @@ mod tests { const AT_SOURCE: Option = Some(10); const AT_TARGET: Option = Some(1); - #[test] - fn starts_relay_when_headers_are_required() { - assert_eq!( - select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 5, 100, "test", false), - OnDemandRelayAction::Start, - ); - - assert_eq!( - select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 5, 100, "test", true), - OnDemandRelayAction::None, - ); - } - - #[test] - fn starts_relay_when_too_many_headers_missing() { - assert_eq!( - select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 0, 5, "test", false), - OnDemandRelayAction::Start, - ); - - assert_eq!( - select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, 0, 5, "test", true), - OnDemandRelayAction::None, - ); - } - - #[test] - fn stops_relay_if_required_header_is_synced() { - assert_eq!( - select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, AT_TARGET.unwrap(), 100, "test", true), - OnDemandRelayAction::Stop, - ); - - assert_eq!( - select_on_demand_relay_action::(AT_SOURCE, AT_TARGET, AT_TARGET.unwrap(), 100, "test", false), - OnDemandRelayAction::None, - ); + #[async_std::test] + async fn updates_required_header_when_too_many_headers_missing() { + let required_header_number = Arc::new(Mutex::new(0)); + update_required_header_number_if_too_many_are_missing::( + AT_SOURCE, + AT_TARGET, + 5, + &required_header_number, + "test", + ) + .await; + assert_eq!(*required_header_number.lock().await, AT_SOURCE.unwrap()); } } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 699c3da400ffe..f5c2e26560593 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.5" +async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.0.0" } jsonrpsee-proc-macros = "=0.2.0-alpha.6" diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 38500934191d2..140e1f17a6ab6 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -21,6 +21,7 @@ use crate::client::Client; use crate::error::Error; use crate::sync_header::SyncHeader; +use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; use codec::Decode; @@ -30,26 +31,41 @@ use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::traits::Header as HeaderT; use std::{marker::PhantomData, pin::Pin}; +/// Shared updatable reference to the maximal header number that we want to sync from the source. +pub type RequiredHeaderNumberRef = Arc::BlockNumber>>; + /// Substrate node as finality source. pub struct FinalitySource { client: Client, + maximal_header_number: Option>, _phantom: PhantomData

, } impl FinalitySource { /// Create new headers source using given client. - pub fn new(client: Client) -> Self { + pub fn new(client: Client, maximal_header_number: Option>) -> Self { FinalitySource { client, + maximal_header_number, _phantom: Default::default(), } } + + /// Returns best finalized block number. + pub async fn on_chain_best_finalized_block_number(&self) -> Result { + // we **CAN** continue to relay finality proofs if source node is out of sync, because + // target node may be missing proofs that are already available at the source + let finalized_header_hash = self.client.best_finalized_header_hash().await?; + let finalized_header = self.client.header_by_hash(finalized_header_hash).await?; + Ok(*finalized_header.number()) + } } impl Clone for FinalitySource { fn clone(&self) -> Self { FinalitySource { client: self.client.clone(), + maximal_header_number: self.maximal_header_number.clone(), _phantom: Default::default(), } } @@ -80,11 +96,16 @@ where type FinalityProofsStream = Pin> + Send>>; async fn best_finalized_block_number(&self) -> Result { - // we **CAN** continue to relay finality proofs if source node is out of sync, because - // target node may be missing proofs that are already available at the source - let finalized_header_hash = self.client.best_finalized_header_hash().await?; - let finalized_header = self.client.header_by_hash(finalized_header_hash).await?; - Ok(*finalized_header.number()) + let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?; + // never return block number larger than requested. This way we'll never sync headers + // past `maximal_header_number` + if let Some(ref maximal_header_number) = self.maximal_header_number { + let maximal_header_number = *maximal_header_number.lock().await; + if finalized_header_number > maximal_header_number { + finalized_header_number = maximal_header_number; + } + } + Ok(finalized_header_number) } async fn header_and_finality_proof( diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 3aa55a8ac5915..cce32839907d9 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -39,8 +39,6 @@ use std::{ /// Finality proof synchronization loop parameters. #[derive(Debug, Clone)] pub struct FinalitySyncParams { - /// If `true`, then the separate async task for running finality loop is NOT spawned. - pub is_on_demand_task: bool, /// Interval at which we check updates on both clients. Normally should be larger than /// `min(source_block_time, target_block_time)`. /// @@ -107,7 +105,6 @@ pub async fn run( ) -> Result<(), String> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .spawn_loop_task(!sync_params.is_on_demand_task) .with_metrics(Some(metrics_prefix::

()), metrics_params) .loop_metric(|registry, prefix| SyncLoopMetrics::new(registry, prefix))? .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 645aeb1777c60..f7826ead730c9 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -197,7 +197,6 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync data: clients_data.clone(), }; let sync_params = FinalitySyncParams { - is_on_demand_task: false, tick: Duration::from_secs(0), recent_finality_proofs_limit: 1024, stall_timeout: Duration::from_secs(1), diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 8fcaabe4430cc..938136658bd31 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -38,7 +38,6 @@ pub trait Client: 'static + Clone + Send + Sync { pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { Loop { reconnect_delay: RECONNECT_DELAY, - spawn_loop_task: true, source_client, target_client, loop_metric: None, @@ -50,7 +49,6 @@ pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetri LoopMetrics { relay_loop: Loop { reconnect_delay: RECONNECT_DELAY, - spawn_loop_task: true, source_client: (), target_client: (), loop_metric: None, @@ -65,7 +63,6 @@ pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetri /// Generic relay loop. pub struct Loop { reconnect_delay: Duration, - spawn_loop_task: bool, source_client: SC, target_client: TC, loop_metric: Option, @@ -87,23 +84,11 @@ impl Loop { self } - /// Set spawn-dedicated-loop-task flag. - /// - /// If `true` (default), separate async task is spawned to run relay loop. This is the default - /// behavior for all loops. If `false`, then loop is executed as a part of the current - /// task. The `false` is used for on-demand tasks, which are cancelled from time to time - /// and there's already a dedicated on-demand task for running such loops. - pub fn spawn_loop_task(mut self, spawn_loop_task: bool) -> Self { - self.spawn_loop_task = spawn_loop_task; - self - } - /// Start building loop metrics using given prefix. pub fn with_metrics(self, prefix: Option, params: MetricsParams) -> LoopMetrics { LoopMetrics { relay_loop: Loop { reconnect_delay: self.reconnect_delay, - spawn_loop_task: self.spawn_loop_task, source_client: self.source_client, target_client: self.target_client, loop_metric: None, @@ -128,7 +113,6 @@ impl Loop { TC: 'static + Client, LM: 'static + Send + Clone, { - let spawn_loop_task = self.spawn_loop_task; let run_loop_task = async move { crate::initialize::initialize_loop(loop_name); @@ -156,11 +140,7 @@ impl Loop { Ok(()) }; - if spawn_loop_task { - async_std::task::spawn(run_loop_task).await - } else { - run_loop_task.await - } + async_std::task::spawn(run_loop_task).await } } @@ -236,7 +216,6 @@ impl LoopMetrics { Ok(Loop { reconnect_delay: self.relay_loop.reconnect_delay, - spawn_loop_task: self.relay_loop.spawn_loop_task, source_client: self.relay_loop.source_client, target_client: self.relay_loop.target_client, loop_metric: self.loop_metric, From 7b1202e5deb3b9f1522f57cecfd2beefd07cd605 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 31 May 2021 21:58:45 +0300 Subject: [PATCH 0474/1210] Custom justification verification (#979) * custom justification verification * is_ancestor -> ensure_descendant * PrecommitIsNotCommitDescendant * Update primitives/header-chain/src/justification.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- primitives/header-chain/Cargo.toml | 1 + primitives/header-chain/src/justification.rs | 214 +++++++----- .../tests/implementation_match.rs | 317 ++++++++++++++++++ .../header-chain/tests/justification.rs | 8 +- primitives/test-utils/src/lib.rs | 3 +- 5 files changed, 450 insertions(+), 93 deletions(-) create mode 100644 primitives/header-chain/tests/implementation_match.rs diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index dc58dafb979ef..bf2268aeb411f 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -20,6 +20,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [dev-dependencies] +assert_matches = "1.5" bp-test-utils = { path = "../test-utils" } [features] diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index e3bff85e504c3..625d7762597a1 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -20,13 +20,34 @@ //! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. use codec::{Decode, Encode}; -use finality_grandpa::{voter_set::VoterSet, Chain, Error as GrandpaError}; +use finality_grandpa::voter_set::VoterSet; use frame_support::RuntimeDebug; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::traits::Header as HeaderT; use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; use sp_std::prelude::*; +/// A GRANDPA Justification is a proof that a given header was finalized +/// at a certain height and with a certain set of authorities. +/// +/// This particular proof is used to prove that headers on a bridged chain +/// (so not our chain) have been finalized correctly. +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +pub struct GrandpaJustification { + /// The round (voting period) this justification is valid for. + pub round: u64, + /// The set of votes for the chain which is to be finalized. + pub commit: finality_grandpa::Commit, + /// A proof that the chain of blocks in the commit are related to each other. + pub votes_ancestries: Vec

, +} + +impl crate::FinalityProof for GrandpaJustification { + fn target_header_number(&self) -> H::Number { + self.commit.target_number + } +} + /// Justification verification error. #[derive(RuntimeDebug, PartialEq)] pub enum Error { @@ -34,14 +55,15 @@ pub enum Error { JustificationDecode, /// Justification is finalizing unexpected header. InvalidJustificationTarget, - /// Invalid commit in justification. - InvalidJustificationCommit, - /// Justification has invalid authority singature. + /// The authority has provided an invalid signature. InvalidAuthoritySignature, - /// The justification has precommit for the header that has no route from the target header. - InvalidPrecommitAncestryProof, - /// The justification has 'unused' headers in its precommit ancestries. - InvalidPrecommitAncestries, + /// The justification contains precommit for header that is not a descendant of the commit header. + PrecommitIsNotCommitDescendant, + /// The cumulative weight of all votes in the justification is not enough to justify commit + /// header finalization. + TooLowCumulativeWeight, + /// The justification contains extra (unused) headers in its `votes_ancestries` field. + ExtraHeadersInVotesAncestries, } /// Decode justification target. @@ -63,119 +85,135 @@ pub fn verify_justification( where Header::Number: finality_grandpa::BlockNumberOps, { - // Ensure that it is justification for the expected header + // ensure that it is justification for the expected header if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { return Err(Error::InvalidJustificationTarget); } - // Validate commit of the justification. Note that `validate_commit()` assumes that all - // signatures are valid. We'll check the validity of the signatures later since they're more - // resource intensive to verify. - let ancestry_chain = AncestryChain::new(&justification.votes_ancestries); - match finality_grandpa::validate_commit(&justification.commit, authorities_set, &ancestry_chain) { - Ok(ref result) if result.ghost().is_some() => {} - _ => return Err(Error::InvalidJustificationCommit), - } - - // Now that we know that the commit is correct, check authorities signatures - let mut buf = Vec::new(); - let mut visited_hashes = BTreeSet::new(); + let mut chain = AncestryChain::new(&justification.votes_ancestries); + let mut signature_buffer = Vec::new(); + let mut votes = BTreeSet::new(); + let mut cumulative_weight = 0u64; for signed in &justification.commit.precommits { + // authority must be in the set + let authority_info = match authorities_set.get(&signed.id) { + Some(authority_info) => authority_info, + None => { + // just ignore precommit from unknown authority as `finality_grandpa::import_precommit` does + continue; + } + }; + + // check if authority has already voted in the same round. + // + // there's a lot of code in `validate_commit` and `import_precommit` functions inside + // `finality-grandpa` crate (mostly related to reporing equivocations). But the only thing that we + // care about is that only first vote from the authority is accepted + if !votes.insert(signed.id.clone()) { + continue; + } + + // everything below this line can't just `continue`, because state is already altered + + // all precommits must be for block higher than the target + if signed.precommit.target_number < justification.commit.target_number { + return Err(Error::PrecommitIsNotCommitDescendant); + } + // all precommits must be for target block descendents + chain = chain.ensure_descendant(&justification.commit.target_hash, &signed.precommit.target_hash)?; + // since we know now that the precommit target is the descendant of the justification target, + // we may increase 'weight' of the justification target + // + // there's a lot of code in the `VoteGraph::insert` method inside `finality-grandpa` crate, + // but in the end it is only used to find GHOST, which we don't care about. The only thing + // that we care about is that the justification target has enough weight + cumulative_weight = cumulative_weight.checked_add(authority_info.weight().0.into()).expect( + "sum of weights of ALL authorities is expected not to overflow - this is guaranteed by\ + existence of VoterSet;\ + the order of loop conditions guarantees that we can account vote from same authority\ + multiple times;\ + thus we'll never overflow the u64::MAX;\ + qed", + ); + // verify authority signature if !sp_finality_grandpa::check_message_signature_with_buffer( &finality_grandpa::Message::Precommit(signed.precommit.clone()), &signed.id, &signed.signature, justification.round, authorities_set_id, - &mut buf, + &mut signature_buffer, ) { return Err(Error::InvalidAuthoritySignature); } - - if justification.commit.target_hash == signed.precommit.target_hash { - continue; - } - - match ancestry_chain.ancestry(justification.commit.target_hash, signed.precommit.target_hash) { - Ok(route) => { - // ancestry starts from parent hash but the precommit target hash has been visited - visited_hashes.insert(signed.precommit.target_hash); - visited_hashes.extend(route); - } - _ => { - // could this happen in practice? I don't think so, but original code has this check - return Err(Error::InvalidPrecommitAncestryProof); - } - } } - // both iterators are `BTree*` iterators, so have the same order => safe to compare - if !visited_hashes.iter().eq(ancestry_chain.ancestry.keys()) { - return Err(Error::InvalidPrecommitAncestries); + // check that there are no extra headers in the justification + if !chain.unvisited.is_empty() { + return Err(Error::ExtraHeadersInVotesAncestries); } - Ok(()) -} - -/// A GRANDPA Justification is a proof that a given header was finalized -/// at a certain height and with a certain set of authorities. -/// -/// This particular proof is used to prove that headers on a bridged chain -/// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] -pub struct GrandpaJustification { - /// The round (voting period) this justification is valid for. - pub round: u64, - /// The set of votes for the chain which is to be finalized. - pub commit: finality_grandpa::Commit, - /// A proof that the chain of blocks in the commit are related to each other. - pub votes_ancestries: Vec
, -} - -impl crate::FinalityProof for GrandpaJustification { - fn target_header_number(&self) -> H::Number { - self.commit.target_number + // check that the cumulative weight of validators voted for the justification target (or one + // of its descendents) is larger than required threshold. + let threshold = authorities_set.threshold().0.into(); + if cumulative_weight >= threshold { + Ok(()) + } else { + Err(Error::TooLowCumulativeWeight) } } -/// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. +/// Votes ancestries with useful methods. #[derive(RuntimeDebug)] -struct AncestryChain { - ancestry: BTreeMap, +pub struct AncestryChain { + /// Header hash => parent header hash mapping. + pub parents: BTreeMap, + /// Hashes of headers that weren't visited by `is_ancestor` method. + pub unvisited: BTreeSet, } impl AncestryChain
{ - fn new(ancestry: &[Header]) -> AncestryChain
{ - AncestryChain { - ancestry: ancestry - .iter() - .map(|header| (header.hash(), *header.parent_hash())) - .collect(), + /// Create new ancestry chain. + pub fn new(ancestry: &[Header]) -> AncestryChain
{ + let mut parents = BTreeMap::new(); + let mut unvisited = BTreeSet::new(); + for ancestor in ancestry { + let hash = ancestor.hash(); + let parent_hash = *ancestor.parent_hash(); + parents.insert(hash, parent_hash); + unvisited.insert(hash); } + AncestryChain { parents, unvisited } } -} -impl finality_grandpa::Chain for AncestryChain
-where - Header::Number: finality_grandpa::BlockNumberOps, -{ - fn ancestry(&self, base: Header::Hash, block: Header::Hash) -> Result, GrandpaError> { - let mut route = Vec::new(); - let mut current_hash = block; + /// Returns `Err(_)` if `precommit_target` is a descendant of the `commit_target` block and `Ok(_)` otherwise. + pub fn ensure_descendant( + mut self, + commit_target: &Header::Hash, + precommit_target: &Header::Hash, + ) -> Result { + let mut current_hash = *precommit_target; loop { - if current_hash == base { + if current_hash == *commit_target { break; } - match self.ancestry.get(¤t_hash).cloned() { + + let is_visited_before = !self.unvisited.remove(¤t_hash); + current_hash = match self.parents.get(¤t_hash) { Some(parent_hash) => { - current_hash = parent_hash; - route.push(current_hash); + if is_visited_before { + // `Some(parent_hash)` means that the `current_hash` is in the `parents` container + // `is_visited_before` means that it has been visited before in some of previous calls + // => since we assume that previous call has finished with `true`, this also will + // be finished with `true` + return Ok(self); + } + + *parent_hash } - _ => return Err(GrandpaError::NotDescendent), - } + None => return Err(Error::PrecommitIsNotCommitDescendant), + }; } - route.pop(); // remove the base - - Ok(route) + Ok(self) } } diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs new file mode 100644 index 0000000000000..0b55c19035287 --- /dev/null +++ b/primitives/header-chain/tests/implementation_match.rs @@ -0,0 +1,317 @@ +// Copyright 2020-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 . + +//! Tests inside this module are made to ensure that our custom justification verification +//! implementation works exactly as `fn finality_grandpa::validate_commit`. +//! +//! Some of tests in this module may partially duplicate tests from `justification.rs`, +//! but their purpose is different. + +use assert_matches::assert_matches; +use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; +use bp_test_utils::{ + header_id, make_justification_for_header, signed_precommit, test_header, Account, JustificationGeneratorParams, + ALICE, BOB, CHARLIE, DAVE, EVE, TEST_GRANDPA_SET_ID, +}; +use finality_grandpa::voter_set::VoterSet; +use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; +use sp_runtime::traits::Header as HeaderT; + +type TestHeader = sp_runtime::testing::Header; +type TestHash = ::Hash; +type TestNumber = ::Number; + +/// Implementation of `finality_grandpa::Chain` that is used in tests. +struct AncestryChain(bp_header_chain::justification::AncestryChain); + +impl AncestryChain { + fn new(ancestry: &[TestHeader]) -> Self { + Self(bp_header_chain::justification::AncestryChain::new(ancestry)) + } +} + +impl finality_grandpa::Chain for AncestryChain { + fn ancestry(&self, base: TestHash, block: TestHash) -> Result, finality_grandpa::Error> { + let mut route = Vec::new(); + let mut current_hash = block; + loop { + if current_hash == base { + break; + } + match self.0.parents.get(¤t_hash).cloned() { + Some(parent_hash) => { + current_hash = parent_hash; + route.push(current_hash); + } + _ => return Err(finality_grandpa::Error::NotDescendent), + } + } + route.pop(); // remove the base + + Ok(route) + } +} + +/// Get a full set of accounts. +fn full_accounts_set() -> Vec<(Account, AuthorityWeight)> { + vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)] +} + +/// Get a full set of GRANDPA authorities. +fn full_voter_set() -> VoterSet { + VoterSet::new(full_accounts_set().iter().map(|(id, w)| (AuthorityId::from(*id), *w))).unwrap() +} + +/// Get a minimal set of accounts. +fn minimal_accounts_set() -> Vec<(Account, AuthorityWeight)> { + // there are 5 accounts in the full set => we need 2/3 + 1 accounts, which results in 4 accounts + vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1)] +} + +/// Get a minimal subset of GRANDPA authorities that have enough cumulative vote weight to justify a header finality. +pub fn minimal_voter_set() -> VoterSet { + VoterSet::new( + minimal_accounts_set() + .iter() + .map(|(id, w)| (AuthorityId::from(*id), *w)), + ) + .unwrap() +} + +/// Make a valid GRANDPA justification with sensible defaults. +pub fn make_default_justification(header: &TestHeader) -> GrandpaJustification { + make_justification_for_header(JustificationGeneratorParams { + header: header.clone(), + authorities: minimal_accounts_set(), + ..Default::default() + }) +} + +// the `finality_grandpa::validate_commit` function has two ways to report an unsuccessful +// commit validation: +// +// 1) to return `Err()` (which only may happen if `finality_grandpa::Chain` implementation +// returns an error); +// 2) to return `Ok(validation_result) if validation_result.ghost().is_none()`. +// +// Our implementation would just return error in both cases. + +#[test] +fn same_result_when_precommit_target_has_lower_number_than_commit_target() { + let mut justification = make_default_justification(&test_header(1)); + // the number of header in precommit (0) is lower than number of header in commit (1) + justification.commit.precommits[0].precommit.target_number = 0; + + // our implementation returns an error + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Err(Error::PrecommitIsNotCommitDescendant), + ); + // original implementation returns empty GHOST + assert_matches!( + finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .map(|result| result.ghost().cloned()), + Ok(None) + ); +} + +#[test] +fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { + let not_descendant = test_header::(10); + let mut justification = make_default_justification(&test_header(1)); + // the route from header of commit (1) to header of precommit (10) is missing from + // the votes ancestries + justification.commit.precommits[0].precommit.target_number = *not_descendant.number(); + justification.commit.precommits[0].precommit.target_hash = not_descendant.hash(); + justification.votes_ancestries.push(not_descendant); + + // our implementation returns an error + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Err(Error::PrecommitIsNotCommitDescendant), + ); + // original implementation returns empty GHOST + assert_matches!( + finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .map(|result| result.ghost().cloned()), + Ok(None) + ); +} + +#[test] +fn same_result_when_justification_contains_duplicate_vote() { + let mut justification = make_default_justification(&test_header(1)); + // the justification may contain exactly the same vote (i.e. same precommit and same signature) + // multiple times && it isn't treated as an error by original implementation + justification + .commit + .precommits + .push(justification.commit.precommits[0].clone()); + justification + .commit + .precommits + .push(justification.commit.precommits[0].clone()); + + // our implementation succeeds + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Ok(()), + ); + // original implementation returns non-empty GHOST + assert_matches!( + finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .map(|result| result.ghost().cloned()), + Ok(Some(_)) + ); +} + +#[test] +fn same_result_when_authority_equivocates_once_in_a_round() { + let mut justification = make_default_justification(&test_header(1)); + // the justification original implementation allows authority to submit two different + // votes in a single round, of which only first is 'accepted' + justification.commit.precommits.push(signed_precommit::( + &ALICE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); + + // our implementation succeeds + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Ok(()), + ); + // original implementation returns non-empty GHOST + assert_matches!( + finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .map(|result| result.ghost().cloned()), + Ok(Some(_)) + ); +} + +#[test] +fn same_result_when_authority_equivocates_twice_in_a_round() { + let mut justification = make_default_justification(&test_header(1)); + // there's some code in the original implementation that should return an error when + // same authority submits more than two different votes in a single round: + // https://github.com/paritytech/finality-grandpa/blob/6aeea2d1159d0f418f0b86e70739f2130629ca09/src/lib.rs#L473 + // but there's also a code that prevents this from happening: + // https://github.com/paritytech/finality-grandpa/blob/6aeea2d1159d0f418f0b86e70739f2130629ca09/src/round.rs#L287 + // => so now we are also just ignoring all votes from the same authority, except the first one + justification.commit.precommits.push(signed_precommit::( + &ALICE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); + justification.commit.precommits.push(signed_precommit::( + &ALICE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); + + // our implementation succeeds + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Ok(()), + ); + // original implementation returns non-empty GHOST + assert_matches!( + finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .map(|result| result.ghost().cloned()), + Ok(Some(_)) + ); +} + +#[test] +fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_target() { + // just remove one authority from the minimal set and we shall not reach the threshold + let mut authorities_set = minimal_accounts_set(); + authorities_set.pop(); + let justification = make_justification_for_header(JustificationGeneratorParams { + header: test_header(1), + authorities: authorities_set, + ..Default::default() + }); + + // our implementation returns an error + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Err(Error::TooLowCumulativeWeight), + ); + // original implementation returns empty GHOST + assert_matches!( + finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .map(|result| result.ghost().cloned()), + Ok(None) + ); +} diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 1ce739e4536f1..ab8d9c490581f 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -23,7 +23,7 @@ type TestHeader = sp_runtime::testing::Header; #[test] fn valid_justification_accepted() { - let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)]; + let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1)]; let params = JustificationGeneratorParams { header: test_header(1), round: TEST_GRANDPA_ROUND, @@ -129,7 +129,7 @@ fn justification_with_invalid_commit_rejected() { &voter_set(), &justification, ), - Err(Error::InvalidJustificationCommit), + Err(Error::ExtraHeadersInVotesAncestries), ); } @@ -161,7 +161,7 @@ fn justification_with_invalid_precommit_ancestry() { &voter_set(), &justification, ), - Err(Error::InvalidPrecommitAncestries), + Err(Error::ExtraHeadersInVotesAncestries), ); } @@ -186,6 +186,6 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { &voter_set(), &make_justification_for_header::(params) ), - Err(Error::InvalidJustificationCommit), + Err(Error::TooLowCumulativeWeight), ); } diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 0fcc263763c31..0eff3fe585618 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -177,7 +177,8 @@ fn generate_chain(fork_id: u8, depth: u32, ancestor: &H) -> Vec { headers } -fn signed_precommit( +/// Create signed precommit with given target. +pub fn signed_precommit( signer: &Account, target: (H::Hash, H::Number), round: u64, From a6b215c8082e0a415704fae8c125f4015f672698 Mon Sep 17 00:00:00 2001 From: Denis Pisarev Date: Wed, 2 Jun 2021 22:21:40 +0200 Subject: [PATCH 0475/1210] Move CI from GitHub Actions to GitLab (#814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * CI: do not trust this CI 1 * CI: don't want to trigger unneded statuses * CI: debug 1 * CI: new CI * CI: temp allow failure * CI: exclude paths * doc: check if docs won't trigger pipelines * doc: check hybrid changes pipeline * doc: do not push excluded files together with others * CI: undebug fmt * CI: better deny * CI: fix deny and spellcheck * CI: global backtrace * CI: deny config * CI: publishing * Dockerfile: metadata fix [skip ci] * CI: revert me * CI: debug bash * CI: mv ci.Dockerfile; fix buildah bug * CI: fix artifact name * Dockerfile: fix context * CI: separate deny check licenses * CI: when to run * CI: unneded stuff in these Dockerfiles * CI: merged test-refs and build-refs * CI: test-build optimizations * CI: changes, web, scheduled pipelines now work as intended * CI: use tested production CI image * CI: substitute GHA * Fix clippy. * Moar clippy fixes. * Fix more. * Finally fix all? Co-authored-by: Tomasz Drwięga --- README.md | 9 +- modules/dispatch/src/lib.rs | 2 + modules/ethereum/src/lib.rs | 146 ++++++++----------- modules/grandpa/src/lib.rs | 2 +- modules/messages/src/inbound_lane.rs | 61 ++++---- modules/messages/src/lib.rs | 2 + relays/finality/src/finality_loop_tests.rs | 6 +- relays/headers/src/headers.rs | 10 +- relays/messages/src/message_race_strategy.rs | 4 +- 9 files changed, 108 insertions(+), 134 deletions(-) diff --git a/README.md b/README.md index 84d776c4f8eff..f8aabb5ac602c 100644 --- a/README.md +++ b/README.md @@ -24,14 +24,14 @@ Substrate chains or Ethereum Proof-of-Authority chains. To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web Assembly (WASM) runtime for the node. You can configure the WASM support as so: -``` +```bash rustup install nightly rustup target add wasm32-unknown-unknown --toolchain nightly ``` Once this is configured you can build and test the repo as follows: -``` +```bash git clone https://github.com/paritytech/parity-bridges-common.git cd parity-bridges-common cargo build --all @@ -49,7 +49,7 @@ and external processes called relayers. A bridge chain is one that is able to fo of a foreign chain independently. For example, consider the case below where we want to bridge two Substrate based chains. -``` +```bash +---------------+ +---------------+ | | | | | Rialto | | Millau | @@ -77,7 +77,7 @@ Here's an overview of how the project is laid out. The main bits are the `node`, "blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass messages between chains. -``` +```bash ├── bin // Node and Runtime for the various Substrate chains │ └── ... ├── deployments // Useful tools for deploying test networks @@ -103,6 +103,7 @@ To run the Bridge you need to be able to connect the bridge relay node to the RP on each side of the bridge (source and target chain). There are 3 ways to run the bridge, described below: + - building & running from source, - building or using Docker images for each individual component, - running a Docker Compose setup (recommended). diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 7803c1e540e1b..3a4fb8f87a0b6 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -23,6 +23,8 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] +// Generated by `decl_event!` +#![allow(clippy::unused_unit)] use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight}; use bp_runtime::{derive_account_id, ChainId, SourceAccount}; diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index aeb7d69f763bc..facf377d51b82 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -1381,15 +1381,12 @@ pub(crate) mod tests { fn verify_transaction_finalized_works_for_best_finalized_header() { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - assert_eq!( - verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(true))], - ), - true, - ); + assert!(verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(true))], + )); }); } @@ -1400,15 +1397,12 @@ pub(crate) mod tests { insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); - assert_eq!( - verify_transaction_finalized( - &storage, - example_header_parent().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(true))], - ), - true, - ); + assert!(verify_transaction_finalized( + &storage, + example_header_parent().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(true))], + )); }); } @@ -1416,10 +1410,12 @@ pub(crate) mod tests { fn verify_transaction_finalized_rejects_proof_with_missing_tx() { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &[],), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 1, + &[], + ),); }); } @@ -1427,10 +1423,12 @@ pub(crate) mod tests { fn verify_transaction_finalized_rejects_unknown_header() { run_test(TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - assert_eq!( - verify_transaction_finalized(&storage, example_header().compute_hash(), 1, &[],), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 1, + &[], + )); }); } @@ -1440,15 +1438,12 @@ pub(crate) mod tests { let mut storage = BridgeStorage::::new(); insert_header(&mut storage, example_header_parent()); insert_header(&mut storage, example_header()); - assert_eq!( - verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(true))], - ), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(true))], + )); }); } @@ -1464,15 +1459,12 @@ pub(crate) mod tests { insert_header(&mut storage, example_header()); insert_header(&mut storage, finalized_header_sibling); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); - assert_eq!( - verify_transaction_finalized( - &storage, - finalized_header_sibling_hash, - 0, - &[(example_tx(), example_tx_receipt(true))], - ), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + finalized_header_sibling_hash, + 0, + &[(example_tx(), example_tx_receipt(true))], + )); }); } @@ -1488,15 +1480,12 @@ pub(crate) mod tests { insert_header(&mut storage, finalized_header_uncle); insert_header(&mut storage, example_header()); storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); - assert_eq!( - verify_transaction_finalized( - &storage, - finalized_header_uncle_hash, - 0, - &[(example_tx(), example_tx_receipt(true))], - ), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + finalized_header_uncle_hash, + 0, + &[(example_tx(), example_tx_receipt(true))], + )); }); } @@ -1504,18 +1493,15 @@ pub(crate) mod tests { fn verify_transaction_finalized_rejects_invalid_transactions_in_proof() { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - assert_eq!( - verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[ - (example_tx(), example_tx_receipt(true)), - (example_tx(), example_tx_receipt(true)) - ], - ), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[ + (example_tx(), example_tx_receipt(true)), + (example_tx(), example_tx_receipt(true)) + ], + )); }); } @@ -1523,15 +1509,12 @@ pub(crate) mod tests { fn verify_transaction_finalized_rejects_invalid_receipts_in_proof() { run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - assert_eq!( - verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[(example_tx(), vec![42])], - ), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + example_header().compute_hash(), + 0, + &[(example_tx(), vec![42])], + )); }); } @@ -1539,15 +1522,12 @@ pub(crate) mod tests { fn verify_transaction_finalized_rejects_failed_transaction() { run_test_with_genesis(example_header_with_failed_receipt(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - assert_eq!( - verify_transaction_finalized( - &storage, - example_header_with_failed_receipt().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(false))], - ), - false, - ); + assert!(!verify_transaction_finalized( + &storage, + example_header_with_failed_receipt().compute_hash(), + 0, + &[(example_tx(), example_tx_receipt(false))], + )); }); } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index d38f61826f98c..f89950772a601 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -693,7 +693,7 @@ mod tests { CurrentAuthoritySet::::get().authorities, init_data.authority_list ); - assert_eq!(IsHalted::::get(), false); + assert!(!IsHalted::::get()); }) } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index b5576bc30a1e3..f0655f8c958ed 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -291,23 +291,17 @@ mod tests { )); } // Fails to dispatch new message from different than latest relayer. - assert_eq!( - false, - lane.receive_message::( - TEST_RELAYER_A + max_nonce + 1, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - ) - ); + assert!(!lane.receive_message::( + TEST_RELAYER_A + max_nonce + 1, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + )); // Fails to dispatch new messages from latest relayer. Prevents griefing attacks. - assert_eq!( - false, - lane.receive_message::( - TEST_RELAYER_A + max_nonce, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - ) - ); + assert!(!lane.receive_message::( + TEST_RELAYER_A + max_nonce, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + )); }); } @@ -324,23 +318,17 @@ mod tests { )); } // Fails to dispatch new message from different than latest relayer. - assert_eq!( - false, - lane.receive_message::( - TEST_RELAYER_B, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - ) - ); + assert!(!lane.receive_message::( + TEST_RELAYER_B, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + )); // Fails to dispatch new messages from latest relayer. - assert_eq!( - false, - lane.receive_message::( - TEST_RELAYER_A, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - ) - ); + assert!(!lane.receive_message::( + TEST_RELAYER_A, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + )); }); } @@ -379,10 +367,11 @@ mod tests { 1, message_data(REGULAR_PAYLOAD).into() )); - assert_eq!( - false, - lane.receive_message::(TEST_RELAYER_B, 1, message_data(REGULAR_PAYLOAD).into()) - ); + assert!(!lane.receive_message::( + TEST_RELAYER_B, + 1, + message_data(REGULAR_PAYLOAD).into() + )); }); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 9e2563498feef..03f4b0ed74911 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -34,6 +34,8 @@ //! or some benchmarks assumptions are broken for your runtime. #![cfg_attr(not(feature = "std"), no_std)] +// Generated by `decl_event!` +#![allow(clippy::unused_unit)] pub use crate::weights_ext::{ ensure_able_to_receive_confirmation, ensure_able_to_receive_message, ensure_weights_are_correct, WeightInfoExt, diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index f7826ead730c9..72b3cdde3d27a 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -342,7 +342,7 @@ fn read_finality_proofs_from_stream_works() { let mut stream = futures::stream::pending().into(); read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1))]); - assert_eq!(stream.needs_restart, false); + assert!(!stream.needs_restart); // when stream has entry with target, it is added to the recent proofs container let mut stream = futures::stream::iter(vec![TestFinalityProof(4)]) @@ -353,7 +353,7 @@ fn read_finality_proofs_from_stream_works() { recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] ); - assert_eq!(stream.needs_restart, false); + assert!(!stream.needs_restart); // when stream has ended, we'll need to restart it let mut stream = futures::stream::empty().into(); @@ -362,7 +362,7 @@ fn read_finality_proofs_from_stream_works() { recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] ); - assert_eq!(stream.needs_restart, true); + assert!(stream.needs_restart); } #[test] diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs index be3e2cb6e6d89..63dfbe583c4b5 100644 --- a/relays/headers/src/headers.rs +++ b/relays/headers/src/headers.rs @@ -1505,7 +1505,7 @@ pub(crate) mod tests { let mut queue = QueuedHeaders::::default(); // when we do not know header itself - assert_eq!(queue.is_parent_incomplete(&id(50)), false); + assert!(!queue.is_parent_incomplete(&id(50))); // when we do not know parent queue @@ -1514,7 +1514,7 @@ pub(crate) mod tests { .or_default() .insert(hash(100), HeaderStatus::Incomplete); queue.incomplete.entry(100).or_default().insert(hash(100), header(100)); - assert_eq!(queue.is_parent_incomplete(&id(100)), false); + assert!(!queue.is_parent_incomplete(&id(100))); // when parent is inside incomplete queue (i.e. some other ancestor is actually incomplete) queue @@ -1523,7 +1523,7 @@ pub(crate) mod tests { .or_default() .insert(hash(101), HeaderStatus::Submitted); queue.submitted.entry(101).or_default().insert(hash(101), header(101)); - assert_eq!(queue.is_parent_incomplete(&id(101)), true); + assert!(queue.is_parent_incomplete(&id(101))); // when parent is the incomplete header and we do not have completion data queue.incomplete_headers.insert(id(199), None); @@ -1533,7 +1533,7 @@ pub(crate) mod tests { .or_default() .insert(hash(200), HeaderStatus::Submitted); queue.submitted.entry(200).or_default().insert(hash(200), header(200)); - assert_eq!(queue.is_parent_incomplete(&id(200)), true); + assert!(queue.is_parent_incomplete(&id(200))); // when parent is the incomplete header and we have completion data queue.completion_data.insert(id(299), 299_299); @@ -1543,7 +1543,7 @@ pub(crate) mod tests { .or_default() .insert(hash(300), HeaderStatus::Submitted); queue.submitted.entry(300).or_default().insert(hash(300), header(300)); - assert_eq!(queue.is_parent_incomplete(&id(300)), true); + assert!(queue.is_parent_incomplete(&id(300))); } #[test] diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 7088f8d74b557..394574ecb44fc 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -318,9 +318,9 @@ mod tests { #[test] fn strategy_is_empty_works() { let mut strategy = BasicStrategy::::new(); - assert_eq!(strategy.is_empty(), true); + assert!(strategy.is_empty()); strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); - assert_eq!(strategy.is_empty(), false); + assert!(!strategy.is_empty()); } #[test] From b910df5dcf47704781ee34b2b4605597c8c8b9d2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 7 Jun 2021 16:47:23 +0300 Subject: [PATCH 0476/1210] Flag for rejecting all outbound messages (#982) * flag for rejecting all outbound messages * update weights * Revert "update weights" This reverts commit 992b866edc7c9fd97013cee9cd68b9d783f8681e. * Revert "flag for rejecting all outbound messages" This reverts commit d094964bb4f8800ab6978b9d4b12aade2f80d266. * OperatingMode * Update modules/messages/src/lib.rs Co-authored-by: Hernando Castano * Poke CI * RustFmt Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- modules/messages/src/lib.rs | 148 ++++++++++++++++++++++++++------- primitives/messages/Cargo.toml | 2 + primitives/messages/src/lib.rs | 24 ++++++ 3 files changed, 142 insertions(+), 32 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 03f4b0ed74911..4e9800e0c7d17 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -50,7 +50,7 @@ use bp_messages::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, - OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, + OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -198,8 +198,10 @@ decl_storage! { /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). pub PalletOwner get(fn module_owner): Option; - /// If true, all pallet transactions are failed immediately. - pub IsHalted get(fn is_halted) config(): bool; + /// The current operating mode of the pallet. + /// + /// Depending on the mode either all, some, or no transactions will be allowed. + pub PalletOperatingMode get(fn operating_mode) config(): OperatingMode; /// Map of lane id => inbound lane data. pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; /// Map of lane id => outbound lane data. @@ -266,19 +268,18 @@ decl_module! { } } - /// Halt or resume all pallet operations. + /// Halt or resume all/some pallet operations. /// /// May only be called either by root, or by `PalletOwner`. #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn set_operational(origin, operational: bool) { + pub fn set_operating_mode(origin, operating_mode: OperatingMode) { ensure_owner_or_root::(origin)?; - >::put(operational); - - if operational { - log::info!(target: "runtime::bridge-messages", "Resuming pallet operations."); - } else { - log::warn!(target: "runtime::bridge-messages", "Stopping pallet operations."); - } + >::put(operating_mode); + log::info!( + target: "runtime::bridge-messages", + "Setting messages pallet operating mode to {:?}.", + operating_mode, + ); } /// Update pallet parameter. @@ -301,7 +302,7 @@ decl_module! { payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResult { - ensure_operational::()?; + ensure_normal_operating_mode::()?; let submitter = origin.into().map_err(|_| BadOrigin)?; // let's first check if message can be delivered to target chain @@ -384,6 +385,7 @@ decl_module! { nonce: MessageNonce, additional_fee: T::OutboundMessageFee, ) -> DispatchResult { + ensure_not_halted::()?; // if someone tries to pay for already-delivered message, we're rejecting this intention // (otherwise this additional fee will be locked forever in relayers fund) // @@ -441,7 +443,7 @@ decl_module! { messages_count: u32, dispatch_weight: Weight, ) -> DispatchResult { - ensure_operational::()?; + ensure_not_halted::()?; let _ = ensure_signed(origin)?; // reject transactions that are declaring too many messages @@ -532,7 +534,7 @@ decl_module! { proof: MessagesDeliveryProofOf, relayers_state: UnrewardedRelayersState, ) -> DispatchResult { - ensure_operational::()?; + ensure_not_halted::()?; let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { @@ -697,9 +699,18 @@ fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result< } } -/// Ensure that the pallet is in operational mode (not halted). -fn ensure_operational, I: Instance>() -> Result<(), Error> { - if IsHalted::::get() { +/// Ensure that the pallet is in normal operational mode. +fn ensure_normal_operating_mode, I: Instance>() -> Result<(), Error> { + if PalletOperatingMode::::get() != OperatingMode::Normal { + Err(Error::::Halted) + } else { + Ok(()) + } +} + +/// Ensure that the pallet is not halted. +fn ensure_not_halted, I: Instance>() -> Result<(), Error> { + if PalletOperatingMode::::get() == OperatingMode::Halted { Err(Error::::Halted) } else { Ok(()) @@ -922,29 +933,41 @@ mod tests { assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); assert_noop!( - Pallet::::set_operational(Origin::signed(2), false), + Pallet::::set_operating_mode(Origin::signed(2), OperatingMode::Halted), DispatchError::BadOrigin, ); - assert_ok!(Pallet::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + OperatingMode::Halted + )); assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); assert_noop!( - Pallet::::set_operational(Origin::signed(1), true), + Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Normal), DispatchError::BadOrigin, ); assert_noop!( - Pallet::::set_operational(Origin::signed(2), true), + Pallet::::set_operating_mode(Origin::signed(2), OperatingMode::Normal), DispatchError::BadOrigin, ); - assert_ok!(Pallet::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + OperatingMode::Normal + )); }); } #[test] fn pallet_may_be_halted_by_root() { run_test(|| { - assert_ok!(Pallet::::set_operational(Origin::root(), false)); - assert_ok!(Pallet::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + OperatingMode::Halted + )); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + OperatingMode::Normal + )); }); } @@ -953,21 +976,30 @@ mod tests { run_test(|| { PalletOwner::::put(2); - assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); - assert_ok!(Pallet::::set_operational(Origin::signed(2), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(2), + OperatingMode::Halted + )); + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(2), + OperatingMode::Normal + )); assert_noop!( - Pallet::::set_operational(Origin::signed(1), false), + Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Halted), DispatchError::BadOrigin, ); assert_noop!( - Pallet::::set_operational(Origin::signed(1), true), + Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Normal), DispatchError::BadOrigin, ); - assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(2), + OperatingMode::Halted + )); assert_noop!( - Pallet::::set_operational(Origin::signed(1), true), + Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Normal), DispatchError::BadOrigin, ); }); @@ -1074,7 +1106,7 @@ mod tests { // send message first to be able to check that delivery_proof fails later send_regular_message(); - IsHalted::::put(true); + PalletOperatingMode::::put(OperatingMode::Halted); assert_noop!( Pallet::::send_message( @@ -1086,6 +1118,11 @@ mod tests { Error::::Halted, ); + assert_noop!( + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1,), + Error::::Halted, + ); + assert_noop!( Pallet::::receive_messages_proof( Origin::signed(1), @@ -1114,6 +1151,53 @@ mod tests { }); } + #[test] + fn pallet_rejects_new_messages_in_rejecting_outbound_messages_operating_mode() { + run_test(|| { + // send message first to be able to check that delivery_proof fails later + send_regular_message(); + + PalletOperatingMode::::put(OperatingMode::RejectingOutboundMessages); + + assert_noop!( + Pallet::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + REGULAR_PAYLOAD.1, + ), + Error::::Halted, + ); + + assert_ok!(Pallet::::increase_message_fee( + Origin::signed(1), + TEST_LANE_ID, + 1, + 1, + )); + + assert_ok!(Pallet::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + 1, + REGULAR_PAYLOAD.1, + ),); + + assert_ok!(Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 1, + ..Default::default() + }, + ))), + Default::default(), + )); + }); + } + #[test] fn send_message_works() { run_test(|| { diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 9cb037a34ce8b..9b79a3bdb58ce 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -26,5 +27,6 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "serde", "sp-std/std" ] diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index c3ffce8baa525..2bc33723291e3 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -32,6 +32,30 @@ pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in related crates. pub use frame_support::weights::Weight; +/// Messages pallet operating mode. +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub enum OperatingMode { + /// Normal mode, when all operations are allowed. + Normal, + /// The pallet is not accepting outbound messages. Inbound messages and receival proofs + /// are still accepted. + /// + /// This mode may be used e.g. when bridged chain expects upgrade. Then to avoid dispatch + /// failures, the pallet owner may stop accepting new messages, while continuing to deliver + /// queued messages to the bridged chain. Once upgrade is completed, the mode may be switched + /// back to `Normal`. + RejectingOutboundMessages, + /// The pallet is halted. All operations (except operating mode change) are prohibited. + Halted, +} + +impl Default for OperatingMode { + fn default() -> Self { + OperatingMode::Normal + } +} + /// Messages pallet parameter. pub trait Parameter: frame_support::Parameter { /// Save parameter value in the runtime storage. From b451d82abd1646b282e7d67394636b474ee676be Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 7 Jun 2021 17:56:13 +0300 Subject: [PATCH 0477/1210] Update submit finality proof weight formula (#981) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * updated weight formula for submit_finality_proof * remove common prefix traces * update docs * single benchmark * Re-generate weights. * Update delivery transaction limits Co-authored-by: Tomasz Drwięga Co-authored-by: Hernando Castano --- modules/grandpa/src/benchmarking.rs | 231 +++--------------- modules/grandpa/src/lib.rs | 5 +- modules/grandpa/src/weights.rs | 62 +---- modules/messages/src/weights.rs | 90 +++---- .../header-chain/tests/justification.rs | 10 +- primitives/test-utils/Cargo.toml | 4 +- primitives/test-utils/src/keyring.rs | 2 +- primitives/test-utils/src/lib.rs | 27 +- relays/bin-substrate/src/messages_lane.rs | 2 +- 9 files changed, 113 insertions(+), 320 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index b7294e918003e..bc027e86a4b59 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -38,24 +38,18 @@ //! //! Note that the worst case scenario here would be a justification where each validator has it's //! own fork which is `SESSION_LENGTH` blocks long. -//! -//! As far as benchmarking results go, the only benchmark that should be used in -//! `pallet-bridge-grandpa` to annotate weights is the `submit_finality_proof` one. The others are -//! looking at the effects of specific code paths and do not actually reflect the overall worst case -//! scenario. use crate::*; use bp_test_utils::{ - accounts, authority_list, make_justification_for_header, test_keyring, JustificationGeneratorParams, ALICE, - TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, + accounts, make_justification_for_header, JustificationGeneratorParams, TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, }; use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; use frame_support::traits::Get; use frame_system::RawOrigin; use sp_finality_grandpa::AuthorityId; use sp_runtime::traits::Zero; -use sp_std::{vec, vec::Vec}; +use sp_std::vec::Vec; // The maximum number of vote ancestries to include in a justification. // @@ -75,124 +69,46 @@ fn header_number, I: 'static, N: From>() -> N { (T::HeadersToKeep::get() + 1).into() } +/// Prepare header and its justification to submit using `submit_finality_proof`. +fn prepare_benchmark_data, I: 'static>( + precommits: u32, + ancestors: u32, +) -> (BridgedHeader, GrandpaJustification>) { + let authority_list = accounts(precommits as u16) + .iter() + .map(|id| (AuthorityId::from(*id), 1)) + .collect::>(); + + let init_data = InitializationData { + header: bp_test_utils::test_header(Zero::zero()), + authority_list, + set_id: TEST_GRANDPA_SET_ID, + is_halted: false, + }; + + bootstrap_bridge::(init_data); + + let header: BridgedHeader = bp_test_utils::test_header(header_number::()); + let params = JustificationGeneratorParams { + header: header.clone(), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: accounts(precommits as u16).iter().map(|k| (*k, 1)).collect::>(), + ancestors, + forks: 1, + }; + let justification = make_justification_for_header(params); + (header, justification) +} + benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to // annotate the weight in the pallet. - // - // The other benchmarks related to `submit_finality_proof` are looking at the effect of specific - // parameters and are there mostly for seeing how specific codepaths behave. submit_finality_proof { - let v in 1..MAX_VOTE_ANCESTRIES; let p in 1..MAX_VALIDATOR_SET_SIZE; - - let caller: T::AccountId = whitelisted_caller(); - - let authority_list = accounts(p as u16) - .iter() - .map(|id| (AuthorityId::from(*id), 1)) - .collect::>(); - - let init_data = InitializationData { - header: bp_test_utils::test_header(Zero::zero()), - authority_list, - set_id: TEST_GRANDPA_SET_ID, - is_halted: false, - }; - - bootstrap_bridge::(init_data); - - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); - let params = JustificationGeneratorParams { - header: header.clone(), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: accounts(p as u16).iter().map(|k| (*k, 1)).collect::>(), - votes: v, - forks: 1, - }; - - let justification = make_justification_for_header(params); - - }: _(RawOrigin::Signed(caller), header, justification) - verify { - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); - let expected_hash = header.hash(); - - assert_eq!(>::get(), expected_hash); - assert!(>::contains_key(expected_hash)); - } - - // What we want to check here is the effect of vote ancestries on justification verification - // do this by varying the number of headers between `finality_target` and `header_of_chain`. - submit_finality_proof_on_single_fork { let v in 1..MAX_VOTE_ANCESTRIES; - - let caller: T::AccountId = whitelisted_caller(); - - let init_data = InitializationData { - header: bp_test_utils::test_header(Zero::zero()), - authority_list: authority_list(), - set_id: TEST_GRANDPA_SET_ID, - is_halted: false, - }; - - bootstrap_bridge::(init_data); - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); - - let params = JustificationGeneratorParams { - header: header.clone(), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: test_keyring(), - votes: v, - forks: 1, - }; - - let justification = make_justification_for_header(params); - - }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) - verify { - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); - let expected_hash = header.hash(); - - assert_eq!(>::get(), expected_hash); - assert!(>::contains_key(expected_hash)); - } - - // What we want to check here is the effect of many pre-commits on justification verification. - // We do this by creating many forks, whose head will be used as a signed pre-commit in the - // final justification. - submit_finality_proof_on_many_forks { - let p in 1..MAX_VALIDATOR_SET_SIZE; - let caller: T::AccountId = whitelisted_caller(); - - let authority_list = accounts(p as u16) - .iter() - .map(|id| (AuthorityId::from(*id), 1)) - .collect::>(); - - let init_data = InitializationData { - header: bp_test_utils::test_header(Zero::zero()), - authority_list, - set_id: TEST_GRANDPA_SET_ID, - is_halted: false, - }; - - bootstrap_bridge::(init_data); - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); - - let params = JustificationGeneratorParams { - header: header.clone(), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: accounts(p as u16).iter().map(|k| (*k, 1)).collect::>(), - votes: p, - forks: p, - }; - - let justification = make_justification_for_header(params); - + let (header, justification) = prepare_benchmark_data::(p, v); }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) verify { let header: BridgedHeader = bp_test_utils::test_header(header_number::()); @@ -201,81 +117,4 @@ benchmarks_instance_pallet! { assert_eq!(>::get(), expected_hash); assert!(>::contains_key(expected_hash)); } - - // Here we want to find out the overheaded of looking through consensus digests found in a - // header. As the number of logs in a header grows, how much more work do we require to look - // through them? - // - // Note that this should be the same for looking through scheduled changes and forces changes, - // which is why we only have one benchmark for this. - find_scheduled_change { - // Not really sure what a good bound for this is. - let n in 1..1000; - - let mut logs = vec![]; - for i in 0..n { - // We chose a non-consensus log on purpose since that way we have to look through all - // the logs in the header - logs.push(sp_runtime::DigestItem::Other(vec![])); - } - - let mut header: BridgedHeader = bp_test_utils::test_header(Zero::zero()); - let digest = header.digest_mut(); - *digest = sp_runtime::Digest { - logs, - }; - - }: { - crate::find_scheduled_change(&header) - } - - // What we want to check here is how long it takes to read and write the authority set tracked - // by the pallet as the number of authorities grows. - read_write_authority_sets { - // The current max target number of validators on Polkadot/Kusama - let n in 1..1000; - - let mut authorities = vec![]; - for i in 0..n { - authorities.push((ALICE, 1)); - } - - let authority_set = bp_header_chain::AuthoritySet { - authorities: authorities.iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect(), - set_id: 0 - }; - - >::put(&authority_set); - - }: { - let authority_set = >::get(); - >::put(&authority_set); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use frame_support::assert_ok; - - #[test] - fn finality_proof_is_valid() { - mock::run_test(|| { - assert_ok!(test_benchmark_submit_finality_proof::()); - }); - } - - #[test] - fn single_fork_finality_proof_is_valid() { - mock::run_test(|| { - assert_ok!(test_benchmark_submit_finality_proof_on_single_fork::()); - }); - } - - #[test] - fn multi_fork_finality_proof_is_valid() { - mock::run_test(|| { - assert_ok!(test_benchmark_submit_finality_proof_on_many_forks::()); - }); - } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index f89950772a601..1d77bf9861db6 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -46,6 +46,7 @@ use frame_support::{ensure, fail}; use frame_system::{ensure_signed, RawOrigin}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; +use sp_std::convert::TryInto; #[cfg(test)] mod mock; @@ -124,8 +125,8 @@ pub mod pallet { /// If successful in verification, it will write the target header to the underlying storage /// pallet. #[pallet::weight(T::WeightInfo::submit_finality_proof( - justification.votes_ancestries.len() as u32, - justification.commit.precommits.len() as u32, + justification.commit.precommits.len().try_into().unwrap_or(u32::MAX), + justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX), ))] pub fn submit_finality_proof( origin: OriginFor, diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 9e7c2ebc087e8..18d88049f16a8 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-04-21, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -48,74 +48,28 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_bridge_grandpa. pub trait WeightInfo { - fn submit_finality_proof(v: u32, p: u32) -> Weight; - fn submit_finality_proof_on_single_fork(v: u32) -> Weight; - fn submit_finality_proof_on_many_forks(p: u32) -> Weight; - fn find_scheduled_change(n: u32) -> Weight; - fn read_write_authority_sets(n: u32) -> Weight; + fn submit_finality_proof(p: u32, v: u32) -> Weight; } /// Weights for pallet_bridge_grandpa using the Rialto node and recommended hardware. pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { - fn submit_finality_proof(v: u32, p: u32) -> Weight { + fn submit_finality_proof(p: u32, v: u32) -> Weight { (0 as Weight) - .saturating_add((756_462_000 as Weight).saturating_mul(v as Weight)) - .saturating_add((791_236_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((59_692_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((6_876_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } - fn submit_finality_proof_on_single_fork(v: u32) -> Weight { - (280_121_000 as Weight) - .saturating_add((14_098_000 as Weight).saturating_mul(v as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) - } - fn submit_finality_proof_on_many_forks(p: u32) -> Weight { - (10_370_940_000 as Weight) - .saturating_add((96_902_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) - } - fn find_scheduled_change(n: u32) -> Weight { - (479_000 as Weight).saturating_add((11_000 as Weight).saturating_mul(n as Weight)) - } - fn read_write_authority_sets(n: u32) -> Weight { - (8_030_000 as Weight) - .saturating_add((232_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) - } } // For backwards compatibility and tests impl WeightInfo for () { - fn submit_finality_proof(v: u32, p: u32) -> Weight { + fn submit_finality_proof(p: u32, v: u32) -> Weight { (0 as Weight) - .saturating_add((756_462_000 as Weight).saturating_mul(v as Weight)) - .saturating_add((791_236_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((59_692_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((6_876_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } - fn submit_finality_proof_on_single_fork(v: u32) -> Weight { - (280_121_000 as Weight) - .saturating_add((14_098_000 as Weight).saturating_mul(v as Weight)) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(6 as Weight)) - } - fn submit_finality_proof_on_many_forks(p: u32) -> Weight { - (10_370_940_000 as Weight) - .saturating_add((96_902_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(6 as Weight)) - } - fn find_scheduled_change(n: u32) -> Weight { - (479_000 as Weight).saturating_add((11_000 as Weight).saturating_mul(n as Weight)) - } - fn read_write_authority_sets(n: u32) -> Weight { - (8_030_000 as Weight) - .saturating_add((232_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) - } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index f86a21e3ed908..aea0e44239fed 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-04-21, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -73,105 +73,105 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (149_643_000 as Weight) + (140_457_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (153_329_000 as Weight) + (138_097_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (200_113_000 as Weight) + (196_192_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (6_407_252_000 as Weight) + (6_244_063_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (141_256_000 as Weight) + (135_633_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (247_723_000 as Weight) + (229_415_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (159_731_000 as Weight) + (147_408_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (168_546_000 as Weight) + (160_092_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (450_087_000 as Weight) + (452_140_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (164_519_000 as Weight) + (123_704_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (173_300_000 as Weight) + (127_844_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (246_205_000 as Weight) + (183_119_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (149_551_000 as Weight) + (162_249_000 as Weight) .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((114_817_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((107_235_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (437_797_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) + (450_232_000 as Weight) + .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (137_633_000 as Weight) + (181_851_000 as Weight) .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((118_482_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((114_622_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (116_036_000 as Weight) - .saturating_add((7_118_000 as Weight).saturating_mul(i as Weight)) + (103_133_000 as Weight) + .saturating_add((6_676_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (172_780_000 as Weight) - .saturating_add((63_718_000 as Weight).saturating_mul(i as Weight)) + (100_321_000 as Weight) + .saturating_add((59_736_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -182,105 +182,105 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (149_643_000 as Weight) + (140_457_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (153_329_000 as Weight) + (138_097_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (200_113_000 as Weight) + (196_192_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (6_407_252_000 as Weight) + (6_244_063_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (141_256_000 as Weight) + (135_633_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_two_messages_proof() -> Weight { - (247_723_000 as Weight) + (229_415_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (159_731_000 as Weight) + (147_408_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (168_546_000 as Weight) + (160_092_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (450_087_000 as Weight) + (452_140_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (164_519_000 as Weight) + (123_704_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (173_300_000 as Weight) + (127_844_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (246_205_000 as Weight) + (183_119_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (149_551_000 as Weight) + (162_249_000 as Weight) .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((114_817_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((107_235_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (437_797_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) + (450_232_000 as Weight) + .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (137_633_000 as Weight) + (181_851_000 as Weight) .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((118_482_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((114_622_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (116_036_000 as Weight) - .saturating_add((7_118_000 as Weight).saturating_mul(i as Weight)) + (103_133_000 as Weight) + .saturating_add((6_676_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (172_780_000 as Weight) - .saturating_add((63_718_000 as Weight).saturating_mul(i as Weight)) + (100_321_000 as Weight) + .saturating_add((59_736_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index ab8d9c490581f..85846c6d50f95 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -29,7 +29,7 @@ fn valid_justification_accepted() { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: authorities.clone(), - votes: 7, + ancestors: 7, forks: 3, }; @@ -45,7 +45,7 @@ fn valid_justification_accepted() { ); assert_eq!(justification.commit.precommits.len(), authorities.len()); - assert_eq!(justification.votes_ancestries.len(), params.votes as usize); + assert_eq!(justification.votes_ancestries.len(), params.ancestors as usize); } #[test] @@ -55,7 +55,7 @@ fn valid_justification_accepted_with_single_fork() { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)], - votes: 5, + ancestors: 5, forks: 1, }; @@ -83,7 +83,7 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: authorities.clone(), - votes: n.into(), + ancestors: n.into(), forks: n.into(), }; @@ -175,7 +175,7 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: authorities.clone(), - votes: 2 * authorities.len() as u32, + ancestors: 2 * authorities.len() as u32, forks: 2, }; diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 5adb2c2b55f54..461e0ffe93ef6 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -7,9 +7,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.14.0", default-features = false } -parity-scale-codec = { version = "2.0.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -19,9 +19,9 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d default = ["std"] std = [ "bp-header-chain/std", + "codec/std", "ed25519-dalek/std", "finality-grandpa/std", - "parity-scale-codec/std", "sp-application-crypto/std", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index 6c5b1cae9114a..b83678cae5e51 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -16,9 +16,9 @@ //! Utilities for working with test accounts. +use codec::Encode; use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; use finality_grandpa::voter_set::VoterSet; -use parity_scale_codec::Encode; use sp_application_crypto::Public; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_runtime::RuntimeDebug; diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 0eff3fe585618..14260e9b7be81 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -19,6 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; use sp_application_crypto::TryFrom; use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; use sp_finality_grandpa::{AuthoritySignature, SetId}; @@ -46,10 +47,10 @@ pub struct JustificationGeneratorParams { /// /// The size of the set will determine the number of pre-commits in our justification. pub authorities: Vec<(Account, AuthorityWeight)>, - /// The total number of vote ancestries in our justification. + /// The total number of precommit ancestors in the `votes_ancestries` field our justification. /// /// These may be distributed among many different forks. - pub votes: u32, + pub ancestors: u32, /// The number of forks. /// /// Useful for creating a "worst-case" scenario in which each authority is on its own fork. @@ -63,7 +64,7 @@ impl Default for JustificationGeneratorParams { round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, authorities: test_keyring(), - votes: 2, + ancestors: 2, forks: 1, } } @@ -94,35 +95,33 @@ pub fn make_justification_for_header(params: JustificationGeneratorP round, set_id, authorities, - mut votes, + mut ancestors, forks, } = params; - let (target_hash, target_number) = (header.hash(), *header.number()); - let mut precommits = vec![]; let mut votes_ancestries = vec![]; + let mut precommits = vec![]; assert!(forks != 0, "Need at least one fork to have a chain.."); - assert!(votes >= forks, "Need at least one header per fork."); assert!( forks as usize <= authorities.len(), "If we have more forks than authorities we can't create valid pre-commits for all the forks." ); // Roughly, how many vote ancestries do we want per fork - let target_depth = (votes + forks - 1) / forks; + let target_depth = (ancestors + forks - 1) / forks; let mut unsigned_precommits = vec![]; for i in 0..forks { - let depth = if votes >= target_depth { - votes -= target_depth; + let depth = if ancestors >= target_depth { + ancestors -= target_depth; target_depth } else { - votes + ancestors }; // Note: Adding 1 to account for the target header - let chain = generate_chain(i as u8, depth + 1, &header); + let chain = generate_chain(i as u32, depth + 1, &header); // We don't include our finality target header in the vote ancestries for child in &chain[1..] { @@ -154,7 +153,7 @@ pub fn make_justification_for_header(params: JustificationGeneratorP } } -fn generate_chain(fork_id: u8, depth: u32, ancestor: &H) -> Vec { +fn generate_chain(fork_id: u32, depth: u32, ancestor: &H) -> Vec { let mut headers = vec![ancestor.clone()]; for i in 1..depth { @@ -169,7 +168,7 @@ fn generate_chain(fork_id: u8, depth: u32, ancestor: &H) -> Vec { header .digest_mut() .logs - .push(sp_runtime::DigestItem::Other(vec![fork_id])); + .push(sp_runtime::DigestItem::Other(fork_id.encode())); headers.push(header); } diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 616e2253a6b03..bfca980a070c8 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -203,7 +203,7 @@ mod tests { // reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (1013, 216_583_333_334), + (1024, 216_583_333_334), ); } } From 993b72896e01ea8ea60e53c9c77c87ac133ebb60 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Mon, 7 Jun 2021 14:46:29 -0400 Subject: [PATCH 0478/1210] Bump Substrate (#986) * Bump Substrate to commit `0495ead4` * Derive MaxEncodedLen for MillauHash * Add new config params to Balances pallet * Update Millau and Rialto service files * Add new Config items to mock runtime * Bump Substrate to `37bb3ae7` * Update Aura worker params --- bin/millau/node/src/service.rs | 94 +++++++++++---------- bin/millau/runtime/src/lib.rs | 3 + bin/rialto/node/src/service.rs | 96 ++++++++++++---------- bin/rialto/runtime/src/lib.rs | 3 + modules/messages/src/mock.rs | 2 + primitives/chain-millau/Cargo.toml | 2 + primitives/chain-millau/src/millau_hash.rs | 3 +- 7 files changed, 114 insertions(+), 89 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index a3cb4fa2457d3..afd9f09db0dd5 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -39,8 +39,7 @@ use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use std::sync::Arc; -use std::time::Duration; +use std::{sync::Arc, time::Duration}; // Our native executor instance. native_executor_instance!( @@ -65,12 +64,7 @@ pub fn new_partial( sp_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_consensus_aura::AuraBlockImport< - Block, - FullClient, - sc_finality_grandpa::GrandpaBlockImport, - AuraPair, - >, + sc_finality_grandpa::GrandpaBlockImport, sc_finality_grandpa::LinkHalf, Option, ), @@ -80,6 +74,7 @@ pub fn new_partial( if config.keystore_remote.is_some() { return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); } + let telemetry = config .telemetry_endpoints .clone() @@ -119,14 +114,11 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; - let aura_block_import = - sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: aura_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import)), + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), client: client.clone(), create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); @@ -153,7 +145,7 @@ pub fn new_partial( keystore_container, select_chain, transaction_pool, - other: (aura_block_import, grandpa_link, telemetry), + other: (grandpa_block_import, grandpa_link, telemetry), }) } @@ -194,16 +186,15 @@ pub fn new_full(mut config: Configuration) -> Result .extra_sets .push(sc_finality_grandpa::grandpa_peers_set_config()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: None, - block_announce_validator_builder: None, - })?; + let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + })?; if config.offchain_worker.enabled { sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); @@ -266,7 +257,6 @@ pub fn new_full(mut config: Configuration) -> Result on_demand: None, remote_blockchain: None, backend, - network_status_sinks, system_rpc_tx, config, telemetry: telemetry.as_mut(), @@ -286,7 +276,7 @@ pub fn new_full(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let raw_slot_duration = slot_duration.slot_duration(); - let aura = sc_consensus_aura::start_aura::(StartAuraParams { + let aura = sc_consensus_aura::start_aura::(StartAuraParams { slot_duration, client, select_chain, @@ -307,6 +297,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), can_author_with, sync_oracle: network.clone(), + justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), telemetry: telemetry.as_ref().map(|x| x.handle()), })?; @@ -331,7 +322,7 @@ pub fn new_full(mut config: Configuration) -> Result name: Some(name), observer_enabled: false, keystore, - is_authority: role.is_authority(), + local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), }; @@ -402,19 +393,17 @@ pub fn new_light(mut config: Configuration) -> Result on_demand.clone(), )); - let (grandpa_block_import, _) = sc_finality_grandpa::block_import( + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( client.clone(), &(client.clone() as Arc<_>), select_chain, telemetry.as_ref().map(|x| x.handle()), )?; - let aura_block_import = - sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: aura_block_import, + block_import: grandpa_block_import.clone(), justification_import: Some(Box::new(grandpa_block_import)), client: client.clone(), create_inherent_data_providers: move |_, ()| async move { @@ -434,21 +423,40 @@ pub fn new_light(mut config: Configuration) -> Result telemetry: telemetry.as_ref().map(|x| x.handle()), })?; - let (network, network_status_sinks, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - })?; + let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: Some(on_demand.clone()), + block_announce_validator_builder: None, + })?; if config.offchain_worker.enabled { sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } + let enable_grandpa = !config.disable_grandpa; + if enable_grandpa { + let name = config.network.node_name.clone(); + + let config = sc_finality_grandpa::Config { + gossip_duration: std::time::Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: false, + keystore: None, + local_role: config.role.clone(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + }; + + task_manager.spawn_handle().spawn_blocking( + "grandpa-observer", + sc_finality_grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?, + ); + } + sc_service::spawn_tasks(sc_service::SpawnTasksParams { remote_blockchain: Some(backend.remote_blockchain()), transaction_pool, @@ -460,12 +468,10 @@ pub fn new_light(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), backend, network, - network_status_sinks, system_rpc_tx, telemetry: telemetry.as_mut(), })?; network_starter.start_network(); - Ok(task_manager) } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8553045419e06..d793c74a27448 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -250,6 +250,7 @@ parameter_types! { // For weight estimation, we assume that the most locks on an individual account will be 50. // This number may need to be adjusted in the future if this assumption no longer holds true. pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { @@ -263,6 +264,8 @@ impl pallet_balances::Config for Runtime { // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; } parameter_types! { diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index a0d3d311a018b..cefda5dd9a62e 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -28,6 +28,8 @@ // ===================================================================================== // ===================================================================================== +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; @@ -39,8 +41,7 @@ use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use std::sync::Arc; -use std::time::Duration; +use std::{sync::Arc, time::Duration}; // Our native executor instance. native_executor_instance!( @@ -65,12 +66,7 @@ pub fn new_partial( sp_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_consensus_aura::AuraBlockImport< - Block, - FullClient, - sc_finality_grandpa::GrandpaBlockImport, - AuraPair, - >, + sc_finality_grandpa::GrandpaBlockImport, sc_finality_grandpa::LinkHalf, Option, ), @@ -120,14 +116,11 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; - let aura_block_import = - sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: aura_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import)), + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), client: client.clone(), create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); @@ -154,7 +147,7 @@ pub fn new_partial( keystore_container, select_chain, transaction_pool, - other: (aura_block_import, grandpa_link, telemetry), + other: (grandpa_block_import, grandpa_link, telemetry), }) } @@ -195,16 +188,15 @@ pub fn new_full(mut config: Configuration) -> Result .extra_sets .push(sc_finality_grandpa::grandpa_peers_set_config()); - let (network, network_status_sinks, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: None, - block_announce_validator_builder: None, - })?; + let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + })?; if config.offchain_worker.enabled { sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); @@ -268,7 +260,6 @@ pub fn new_full(mut config: Configuration) -> Result on_demand: None, remote_blockchain: None, backend, - network_status_sinks, system_rpc_tx, config, telemetry: telemetry.as_mut(), @@ -287,7 +278,8 @@ pub fn new_full(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let raw_slot_duration = slot_duration.slot_duration(); - let aura = sc_consensus_aura::start_aura::(StartAuraParams { + + let aura = sc_consensus_aura::start_aura::(StartAuraParams { slot_duration, client, select_chain, @@ -308,6 +300,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), can_author_with, sync_oracle: network.clone(), + justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), telemetry: telemetry.as_ref().map(|x| x.handle()), })?; @@ -332,7 +325,7 @@ pub fn new_full(mut config: Configuration) -> Result name: Some(name), observer_enabled: false, keystore, - is_authority: role.is_authority(), + local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), }; @@ -403,19 +396,17 @@ pub fn new_light(mut config: Configuration) -> Result on_demand.clone(), )); - let (grandpa_block_import, _) = sc_finality_grandpa::block_import( + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( client.clone(), &(client.clone() as Arc<_>), select_chain, telemetry.as_ref().map(|x| x.handle()), )?; - let aura_block_import = - sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(grandpa_block_import.clone(), client.clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: aura_block_import, + block_import: grandpa_block_import.clone(), justification_import: Some(Box::new(grandpa_block_import)), client: client.clone(), create_inherent_data_providers: move |_, ()| async move { @@ -435,21 +426,40 @@ pub fn new_light(mut config: Configuration) -> Result telemetry: telemetry.as_ref().map(|x| x.handle()), })?; - let (network, network_status_sinks, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - })?; + let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: Some(on_demand.clone()), + block_announce_validator_builder: None, + })?; if config.offchain_worker.enabled { sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } + let enable_grandpa = !config.disable_grandpa; + if enable_grandpa { + let name = config.network.node_name.clone(); + + let config = sc_finality_grandpa::Config { + gossip_duration: std::time::Duration::from_millis(333), + justification_period: 512, + name: Some(name), + observer_enabled: false, + keystore: None, + local_role: config.role.clone(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + }; + + task_manager.spawn_handle().spawn_blocking( + "grandpa-observer", + sc_finality_grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?, + ); + } + sc_service::spawn_tasks(sc_service::SpawnTasksParams { remote_blockchain: Some(backend.remote_blockchain()), transaction_pool, @@ -461,12 +471,10 @@ pub fn new_light(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), backend, network, - network_status_sinks, system_rpc_tx, telemetry: telemetry.as_mut(), })?; network_starter.start_network(); - Ok(task_manager) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e67a1c64cd41f..6c2a1f7418bad 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -357,6 +357,7 @@ parameter_types! { // For weight estimation, we assume that the most locks on an individual account will be 50. // This number may need to be adjusted in the future if this assumption no longer holds true. pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { @@ -370,6 +371,8 @@ impl pallet_balances::Config for Runtime { // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; } parameter_types! { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index e640fa7805426..460c001842fb0 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -115,6 +115,8 @@ impl pallet_balances::Config for TestRuntime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = (); } parameter_types! { diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 67db08c208608..f4198e35c38c0 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -23,6 +23,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +max-encoded-len = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, features = ["derive"] } sp-api = { 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 } @@ -41,6 +42,7 @@ std = [ "hash256-std-hasher/std", "impl-codec/std", "impl-serde", + "max-encoded-len/std", "parity-util-mem/std", "serde", "sp-api/std", diff --git a/primitives/chain-millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs index 936791217af18..219ceb68a8249 100644 --- a/primitives/chain-millau/src/millau_hash.rs +++ b/primitives/chain-millau/src/millau_hash.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use frame_support::traits::MaxEncodedLen; use parity_util_mem::MallocSizeOf; use sp_runtime::traits::CheckEqual; @@ -22,7 +23,7 @@ use sp_runtime::traits::CheckEqual; fixed_hash::construct_fixed_hash! { /// Hash type used in Millau chain. - #[derive(MallocSizeOf)] + #[derive(MallocSizeOf, MaxEncodedLen)] pub struct MillauHash(64); } From d380df66cb9de77ce017a5bf9a5166e9b72968b8 Mon Sep 17 00:00:00 2001 From: Roman Useinov Date: Tue, 8 Jun 2021 10:55:55 +0200 Subject: [PATCH 0479/1210] Make sure GRANDPA shares state with RPC. (#987) * Make sure GRANDPA shares state with RPC. * RPC shared state with GRANDPA rialto. * fmt * cargo fix * fix clippy --- bin/millau/node/src/service.rs | 7 ++++--- bin/rialto/node/src/service.rs | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index afd9f09db0dd5..632eef06ff65b 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -33,7 +33,7 @@ use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sc_finality_grandpa::SharedVoterState; + use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; @@ -206,6 +206,7 @@ pub fn new_full(mut config: Configuration) -> Result let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); + let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; @@ -221,7 +222,7 @@ pub fn new_full(mut config: Configuration) -> Result let justification_stream = grandpa_link.justification_stream(); let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); + let shared_voter_state = shared_voter_state.clone(); let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); @@ -339,7 +340,7 @@ pub fn new_full(mut config: Configuration) -> Result network, voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, - shared_voter_state: SharedVoterState::empty(), + shared_voter_state, telemetry: telemetry.as_ref().map(|x| x.handle()), }; diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index cefda5dd9a62e..0e90642ecdc23 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -35,7 +35,7 @@ use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; use sc_executor::native_executor_instance; pub use sc_executor::NativeExecutor; -use sc_finality_grandpa::SharedVoterState; + use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; @@ -209,6 +209,8 @@ pub fn new_full(mut config: Configuration) -> Result let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); + let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); + let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; @@ -223,7 +225,7 @@ pub fn new_full(mut config: Configuration) -> Result let justification_stream = grandpa_link.justification_stream(); let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); + let shared_voter_state = shared_voter_state.clone(); let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); @@ -342,7 +344,7 @@ pub fn new_full(mut config: Configuration) -> Result network, voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, - shared_voter_state: SharedVoterState::empty(), + shared_voter_state, telemetry: telemetry.as_ref().map(|x| x.handle()), }; From bcc93fa2b115ec736b60444827a7d3ca1462b4e1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 8 Jun 2021 14:33:48 +0300 Subject: [PATCH 0480/1210] fix clippy issues (#991) --- bin/millau/node/src/service.rs | 2 +- bin/rialto/node/src/service.rs | 2 +- modules/ethereum-contract-builtin/src/lib.rs | 2 +- modules/grandpa/src/lib.rs | 9 +++++++-- primitives/ethereum-poa/src/lib.rs | 4 ++-- primitives/test-utils/src/lib.rs | 2 +- relays/bin-ethereum/src/instances.rs | 4 ++-- relays/bin-ethereum/src/main.rs | 12 ++++++------ relays/bin-substrate/src/cli/encode_call.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 2 +- relays/exchange/src/exchange.rs | 6 +++--- relays/exchange/src/exchange_loop.rs | 2 +- relays/headers/src/headers.rs | 8 ++++---- relays/messages/src/message_race_loop.rs | 2 +- 14 files changed, 32 insertions(+), 27 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 632eef06ff65b..3c138a649e56a 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -87,7 +87,7 @@ pub fn new_partial( .transpose()?; let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - &config, + config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), )?; let client = Arc::new(client); diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 0e90642ecdc23..a1844aa1af0f5 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -89,7 +89,7 @@ pub fn new_partial( .transpose()?; let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - &config, + config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), )?; let client = Arc::new(client); diff --git a/modules/ethereum-contract-builtin/src/lib.rs b/modules/ethereum-contract-builtin/src/lib.rs index 47c4452aee6cd..a07f838cf8d64 100644 --- a/modules/ethereum-contract-builtin/src/lib.rs +++ b/modules/ethereum-contract-builtin/src/lib.rs @@ -151,7 +151,7 @@ pub fn verify_substrate_finality_proof( let best_set = best_set?; let verify_result = sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( - &raw_finality_proof, + raw_finality_proof, (finality_target_hash, finality_target_number), best_set_id, &best_set, diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 1d77bf9861db6..4cca1c7827383 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -415,9 +415,14 @@ pub mod pallet { let set_id = authority_set.set_id; Ok( - verify_justification::>((hash, number), set_id, &voter_set, &justification).map_err( + verify_justification::>((hash, number), set_id, &voter_set, justification).map_err( |e| { - log::error!(target: "runtime::bridge-grandpa", "Received invalid justification for {:?}: {:?}", hash, e); + log::error!( + target: "runtime::bridge-grandpa", + "Received invalid justification for {:?}: {:?}", + hash, + e, + ); >::InvalidJustification }, )?, diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 57c539f2e27b5..382e6f81ee5d3 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -245,7 +245,7 @@ impl AuraHeader { /// Get step this header is generated for. pub fn step(&self) -> Option { - self.seal.get(0).map(|x| Rlp::new(&x)).and_then(|x| x.as_val().ok()) + self.seal.get(0).map(|x| Rlp::new(x)).and_then(|x| x.as_val().ok()) } /// Get header author' signature. @@ -496,7 +496,7 @@ pub fn transaction_decode_rlp(raw_tx: &[u8]) -> Result(params: JustificationGeneratorP for (i, (id, _weight)) in authorities.iter().enumerate() { // Assign authorities to sign pre-commits in a round-robin fashion let target = unsigned_precommits[i % forks as usize]; - let precommit = signed_precommit::(&id, target, round, set_id); + let precommit = signed_precommit::(id, target, round, set_id); precommits.push(precommit); } diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs index 0d2a508f455a3..6d3966ca45dca 100644 --- a/relays/bin-ethereum/src/instances.rs +++ b/relays/bin-ethereum/src/instances.rs @@ -53,7 +53,7 @@ impl BridgeInstance for RialtoPoA { .into_iter() .map(|header| { ( - into_substrate_ethereum_header(&header.header()), + into_substrate_ethereum_header(header.header()), into_substrate_ethereum_receipts(header.extra()), ) }) @@ -65,7 +65,7 @@ impl BridgeInstance for RialtoPoA { fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(&header.header()), + into_substrate_ethereum_header(header.header()), into_substrate_ethereum_receipts(header.extra()), ); diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index 234e1237fcf55..bcdae353d3dc4 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -60,7 +60,7 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { match matches.subcommand() { ("eth-to-sub", Some(eth_to_sub_matches)) => { log::info!(target: "bridge", "Starting ETH ➡ SUB relay."); - if ethereum_sync_loop::run(match ethereum_sync_params(ð_to_sub_matches) { + if ethereum_sync_loop::run(match ethereum_sync_params(eth_to_sub_matches) { Ok(ethereum_sync_params) => ethereum_sync_params, Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); @@ -75,7 +75,7 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { } ("sub-to-eth", Some(sub_to_eth_matches)) => { log::info!(target: "bridge", "Starting SUB ➡ ETH relay."); - if substrate_sync_loop::run(match substrate_sync_params(&sub_to_eth_matches) { + if substrate_sync_loop::run(match substrate_sync_params(sub_to_eth_matches) { Ok(substrate_sync_params) => substrate_sync_params, Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); @@ -90,7 +90,7 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { } ("eth-deploy-contract", Some(eth_deploy_matches)) => { log::info!(target: "bridge", "Deploying ETH contracts."); - ethereum_deploy_contract::run(match ethereum_deploy_contract_params(ð_deploy_matches) { + ethereum_deploy_contract::run(match ethereum_deploy_contract_params(eth_deploy_matches) { Ok(ethereum_deploy_params) => ethereum_deploy_params, Err(err) => { log::error!(target: "bridge", "Error during contract deployment: {}", err); @@ -101,7 +101,7 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { } ("eth-submit-exchange-tx", Some(eth_exchange_submit_matches)) => { log::info!(target: "bridge", "Submitting ETH ➡ SUB exchange transaction."); - ethereum_exchange_submit::run(match ethereum_exchange_submit_params(ð_exchange_submit_matches) { + ethereum_exchange_submit::run(match ethereum_exchange_submit_params(eth_exchange_submit_matches) { Ok(eth_exchange_submit_params) => eth_exchange_submit_params, Err(err) => { log::error!(target: "bridge", "Error submitting Eethereum exchange transaction: {}", err); @@ -112,7 +112,7 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { } ("eth-exchange-sub", Some(eth_exchange_matches)) => { log::info!(target: "bridge", "Starting ETH ➡ SUB exchange transactions relay."); - ethereum_exchange::run(match ethereum_exchange_params(ð_exchange_matches) { + ethereum_exchange::run(match ethereum_exchange_params(eth_exchange_matches) { Ok(eth_exchange_params) => eth_exchange_params, Err(err) => { log::error!(target: "bridge", "Error relaying Ethereum transactions proofs: {}", err); @@ -285,7 +285,7 @@ fn ethereum_exchange_submit_params(matches: &clap::ArgMatches) -> Result { if remark_payload.is_none() { *remark_payload = Some(HexBytes(generate_remark_payload( - &remark_size, + remark_size, compute_maximal_message_arguments_size(Source::max_extrinsic_size(), Target::max_extrinsic_size()), ))); } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 6fa82a8cdb5e3..abca740472f0a 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -80,7 +80,7 @@ impl SendMessage { let target_sign = target_sign.to_keypair::()?; encode_call::preprocess_call::(message, bridge.bridge_instance_index()); - let target_call = Target::encode_call(&message)?; + let target_call = Target::encode_call(message)?; let payload = { let target_call_weight = prepare_call_dispatch_weight( diff --git a/relays/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs index 4a2f07fa7f979..b87b99ee4207e 100644 --- a/relays/exchange/src/exchange.rs +++ b/relays/exchange/src/exchange.rs @@ -324,7 +324,7 @@ async fn wait_transaction_mined( source_tx_hash: &TransactionHashOf

, ) -> Result<(HeaderId

, usize), String> { loop { - let source_header_and_tx = source_client.transaction_block(&source_tx_hash).await.map_err(|err| { + let source_header_and_tx = source_client.transaction_block(source_tx_hash).await.map_err(|err| { format!( "Error retrieving transaction {} from {} node: {:?}", source_tx_hash, @@ -363,7 +363,7 @@ async fn wait_header_imported( source_header_id: &HeaderId

, ) -> Result<(), String> { loop { - let is_header_known = target_client.is_header_known(&source_header_id).await.map_err(|err| { + let is_header_known = target_client.is_header_known(source_header_id).await.map_err(|err| { format!( "Failed to check existence of header {}/{} on {} node: {:?}", source_header_id.0, @@ -406,7 +406,7 @@ async fn wait_header_finalized( ) -> Result<(), String> { loop { let is_header_finalized = target_client - .is_header_finalized(&source_header_id) + .is_header_finalized(source_header_id) .await .map_err(|err| { format!( diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 4525c33e36a15..8da4c3f45687d 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -215,7 +215,7 @@ async fn run_loop_iteration( state.best_processed_header_number = state.best_processed_header_number + One::one(); storage.set_state(state); - if let Some(ref exchange_loop_metrics) = exchange_loop_metrics { + if let Some(exchange_loop_metrics) = exchange_loop_metrics { exchange_loop_metrics.update::

( state.best_processed_header_number, best_finalized_header_id.0, diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs index 63dfbe583c4b5..0b948d9da4cc6 100644 --- a/relays/headers/src/headers.rs +++ b/relays/headers/src/headers.rs @@ -295,7 +295,7 @@ impl QueuedHeaders

{ &mut self.orphan, &mut self.known_headers, HeaderStatus::Orphan, - &id, + id, ); return; } @@ -305,7 +305,7 @@ impl QueuedHeaders

{ &mut self.maybe_extra, &mut self.known_headers, HeaderStatus::MaybeExtra, - &id, + id, ); } @@ -324,7 +324,7 @@ impl QueuedHeaders

{ destination_queue, &mut self.known_headers, destination_status, - &id, + id, |header| header, ); } @@ -654,7 +654,7 @@ impl QueuedHeaders

{ // remember that the header itself is synced // (condition is here to avoid duplicate log messages) if !id_processed { - set_header_status::

(&mut self.known_headers, &id, HeaderStatus::Synced); + set_header_status::

(&mut self.known_headers, id, HeaderStatus::Synced); } // now let's move all descendants from maybe_orphan && orphan queues to diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 41f5ede1033a5..646fad886d764 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -567,7 +567,7 @@ where .as_ref() .and_then(|best_finalized_source_header_id_at_best_target| { strategy - .select_nonces_to_deliver(&race_state) + .select_nonces_to_deliver(race_state) .map(|(nonces_range, proof_parameters)| { ( best_finalized_source_header_id_at_best_target.clone(), From efe38605942bc3854d55a8e710016d6223af7591 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 8 Jun 2021 17:30:13 +0300 Subject: [PATCH 0481/1210] Fix clippy in test code (#993) * fix clippy issues * clippy + tests * more clippy Co-authored-by: adoerr <0xad@gmx.net> --- bin/runtime-common/src/messages.rs | 16 ++++++++-------- modules/ethereum/src/test_utils.rs | 4 ++-- modules/ethereum/src/verification.rs | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 487fb356f9f32..52623c42c6831 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -991,7 +991,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Root, &ThisChainBalance(1), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ), @@ -1001,7 +1001,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Root, &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ) @@ -1024,7 +1024,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Signed(ThisChainAccountId(0)), &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ), @@ -1034,7 +1034,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::None, &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ), @@ -1044,7 +1044,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Root, &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ) @@ -1067,7 +1067,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Signed(ThisChainAccountId(0)), &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ), @@ -1077,7 +1077,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Signed(ThisChainAccountId(1)), &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &test_lane_outbound_data(), &payload, ) @@ -1105,7 +1105,7 @@ mod tests { source::FromThisChainMessageVerifier::::verify_message( &Sender::Root, &ThisChainBalance(1_000_000), - &TEST_LANE_ID, + TEST_LANE_ID, &OutboundLaneData { latest_received_nonce: 100, latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1, diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 18ad6876d68ba..41161089ba6d0 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -214,7 +214,7 @@ impl HeaderBuilder { /// Helper function for getting a genesis header which has been signed by an authority. pub fn build_genesis_header(author: &SecretKey) -> AuraHeader { let genesis = HeaderBuilder::genesis(); - genesis.header.sign_by(&author) + genesis.header.sign_by(author) } /// Helper function for building a custom child header which has been signed by an authority. @@ -222,7 +222,7 @@ pub fn build_custom_header(author: &SecretKey, previous: &AuraHeader, customi where F: FnOnce(AuraHeader) -> AuraHeader, { - let new_header = HeaderBuilder::with_parent(&previous); + let new_header = HeaderBuilder::with_parent(previous); let custom_header = customize_header(new_header.header); custom_header.sign_by(author) } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index c79242d1d4d9e..c8c4deca87f1d 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -396,7 +396,7 @@ mod tests { fn verify_with_config(config: &AuraConfiguration, header: &AuraHeader) -> Result, Error> { run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); - verify_aura_header(&storage, &config, None, header, &ConstChainTime::default()) + verify_aura_header(&storage, config, None, header, &ConstChainTime::default()) }) } @@ -787,7 +787,7 @@ mod tests { fn pool_verifies_future_block_number() { // when header is too far from the future assert_eq!( - default_accept_into_pool(|validators| (HeaderBuilder::with_number(100).sign_by_set(&validators), None),), + default_accept_into_pool(|validators| (HeaderBuilder::with_number(100).sign_by_set(validators), None),), Err(Error::UnsignedTooFarInTheFuture), ); } @@ -800,7 +800,7 @@ mod tests { default_accept_into_pool(|validators| ( HeaderBuilder::with_parent_number(3) .step(GENESIS_STEP + 3) - .sign_by_set(&validators), + .sign_by_set(validators), None, ),), Err(Error::DoubleVote), From 0280875aa7b034c8a4da4bd7319fe3f4a1507969 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 8 Jun 2021 10:54:41 -0400 Subject: [PATCH 0482/1210] Fix some nits (#988) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * This is art, not bash * Remove unused HEALTH build argument Co-authored-by: Tomasz Drwięga --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f8aabb5ac602c..6df1c0b09fe72 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ rustup target add wasm32-unknown-unknown --toolchain nightly Once this is configured you can build and test the repo as follows: -```bash +``` git clone https://github.com/paritytech/parity-bridges-common.git cd parity-bridges-common cargo build --all @@ -49,7 +49,7 @@ and external processes called relayers. A bridge chain is one that is able to fo of a foreign chain independently. For example, consider the case below where we want to bridge two Substrate based chains. -```bash +``` +---------------+ +---------------+ | | | | | Rialto | | Millau | @@ -77,7 +77,7 @@ Here's an overview of how the project is laid out. The main bits are the `node`, "blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass messages between chains. -```bash +``` ├── bin // Node and Runtime for the various Substrate chains │ └── ... ├── deployments // Useful tools for deploying test networks From d0db83fcb2b04d061ea1a2304ecae9fc3793f26e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Jun 2021 16:16:57 +0300 Subject: [PATCH 0483/1210] Move ChainWithBalances::NativeBalance -> Chain::Balance (#990) * move ChainWithBalances::NativeBalance -> Chain::Balance * dummy commit * Revert "dummy commit" This reverts commit c00642153d260685a91d4fffbc424d225741fceb. --- relays/bin-substrate/src/cli/estimate_fee.rs | 4 ++-- relays/bin-substrate/src/cli/send_message.rs | 11 ++++++----- relays/client-kusama/src/lib.rs | 1 + relays/client-millau/src/lib.rs | 3 +-- relays/client-polkadot/src/lib.rs | 1 + relays/client-rialto/src/lib.rs | 3 +-- relays/client-rococo/src/lib.rs | 3 +-- relays/client-substrate/src/chain.rs | 10 ++++++---- relays/client-substrate/src/client.rs | 4 ++-- relays/client-substrate/src/guard.rs | 9 ++++----- relays/client-westend/src/lib.rs | 3 +-- relays/client-wococo/src/lib.rs | 3 +-- 12 files changed, 27 insertions(+), 28 deletions(-) diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 4e39ad351ede0..129699c26917c 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -18,7 +18,7 @@ use crate::cli::bridge::FullBridge; use crate::cli::{Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}; use crate::select_full_bridge; use codec::{Decode, Encode}; -use relay_substrate_client::{Chain, ChainWithBalances}; +use relay_substrate_client::Chain; use structopt::StructOpt; /// Estimate Delivery & Dispatch Fee command. @@ -52,7 +52,7 @@ impl EstimateFee { let lane = lane.into(); let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; - let fee: ::NativeBalance = + let fee: ::Balance = estimate_message_delivery_and_dispatch_fee(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload) .await?; diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index abca740472f0a..f6338dea65da5 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -130,11 +130,12 @@ impl SendMessage { let fee = match self.fee { Some(fee) => fee, None => Balance( - estimate_message_delivery_and_dispatch_fee::< - ::NativeBalance, - _, - _, - >(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone()) + estimate_message_delivery_and_dispatch_fee::<::Balance, _, _>( + &source_client, + ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) .await? as _, ), }; diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 3c3b1cd4c5d80..f2fba32dc1ed0 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -41,6 +41,7 @@ impl Chain for Kusama { type Index = bp_kusama::Nonce; type SignedBlock = bp_kusama::SignedBlock; type Call = (); + type Balance = bp_kusama::Balance; } /// Kusama header type used in headers sync. diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 1708a8efa121c..8597d9e59200f 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -44,11 +44,10 @@ impl Chain for Millau { type Index = millau_runtime::Index; type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::Call; + type Balance = millau_runtime::Balance; } impl ChainWithBalances for Millau { - type NativeBalance = millau_runtime::Balance; - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; StorageKey(frame_system::Account::::storage_map_final_key( diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 2c117c6d3d1ce..e502463187d2c 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -41,6 +41,7 @@ impl Chain for Polkadot { type Index = bp_polkadot::Nonce; type SignedBlock = bp_polkadot::SignedBlock; type Call = (); + type Balance = bp_polkadot::Balance; } /// Polkadot header type used in headers sync. diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 0ddc03681d296..4a0023a87c4f5 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -44,11 +44,10 @@ impl Chain for Rialto { type Index = rialto_runtime::Index; type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::Call; + type Balance = rialto_runtime::Balance; } impl ChainWithBalances for Rialto { - type NativeBalance = rialto_runtime::Balance; - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; StorageKey(frame_system::Account::::storage_map_final_key( diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 09d205f06e910..fe9448d19c623 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -47,11 +47,10 @@ impl Chain for Rococo { type Index = bp_rococo::Index; type SignedBlock = bp_rococo::SignedBlock; type Call = bp_rococo::Call; + type Balance = bp_rococo::Balance; } impl ChainWithBalances for Rococo { - type NativeBalance = bp_rococo::Balance; - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_rococo::account_info_storage_key(account_id)) } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 64c0d6af52b22..ba3634fb6fd0e 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -54,14 +54,16 @@ pub trait Chain: ChainBase + Clone { type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. type Call: Dispatchable + Debug; + /// Balance of an account in native tokens. + /// + /// The chain may suport 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: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + Zero; } /// Substrate-based chain with `frame_system::Config::AccountData` set to -/// the `pallet_balances::AccountData`. +/// the `pallet_balances::AccountData`. pub trait ChainWithBalances: Chain { - /// Balance of an account in native tokens. - type NativeBalance: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + Zero; - /// Return runtime storage key for getting `frame_system::AccountInfo` of given account. fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey; } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index ec4220158e77b..f0b7158ecbe37 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -208,7 +208,7 @@ impl Client { } /// Return native tokens balance of the account. - pub async fn free_native_balance(&self, account: C::AccountId) -> Result + pub async fn free_native_balance(&self, account: C::AccountId) -> Result where C: ChainWithBalances, { @@ -217,7 +217,7 @@ impl Client { .await? .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = - AccountInfo::>::decode(&mut &encoded_account_data.0[..]) + AccountInfo::>::decode(&mut &encoded_account_data.0[..]) .map_err(Error::ResponseParseFailed)?; Ok(decoded_account_data.data.free) } diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 68fef1c4c9c29..c6e191ce078ff 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -33,7 +33,7 @@ pub trait Environment: Send + Sync + 'static { /// Return current runtime version. async fn runtime_version(&mut self) -> Result; /// Return free native balance of the account on the chain. - async fn free_native_balance(&mut self, account: C::AccountId) -> Result; + async fn free_native_balance(&mut self, account: C::AccountId) -> Result; /// Return current time. fn now(&self) -> Instant { @@ -85,7 +85,7 @@ pub fn abort_on_spec_version_change(mut env: impl Environm pub fn abort_when_account_balance_decreased( mut env: impl Environment, account_id: C::AccountId, - maximal_decrease: C::NativeBalance, + maximal_decrease: C::Balance, ) { const DAY: Duration = Duration::from_secs(60 * 60 * 24); @@ -155,7 +155,7 @@ impl Environment for Client { Client::::runtime_version(self).await.map_err(|e| e.to_string()) } - async fn free_native_balance(&mut self, account: C::AccountId) -> Result { + async fn free_native_balance(&mut self, account: C::AccountId) -> Result { Client::::free_native_balance(self, account) .await .map_err(|e| e.to_string()) @@ -191,11 +191,10 @@ mod tests { type SignedBlock = sp_runtime::generic::SignedBlock>; type Call = (); + type Balance = u32; } impl ChainWithBalances for TestChain { - type NativeBalance = u32; - fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey { unreachable!() } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 417938ccf5a98..6768b81f10f8c 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -47,11 +47,10 @@ impl Chain for Westend { type Index = bp_westend::Nonce; type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; + type Balance = bp_westend::Balance; } impl ChainWithBalances for Westend { - type NativeBalance = bp_westend::Balance; - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_westend::account_info_storage_key(account_id)) } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index be2f872b7d775..76ecf5b0a5116 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -47,11 +47,10 @@ impl Chain for Wococo { type Index = bp_wococo::Index; type SignedBlock = bp_wococo::SignedBlock; type Call = bp_wococo::Call; + type Balance = bp_wococo::Balance; } impl ChainWithBalances for Wococo { - type NativeBalance = bp_wococo::Balance; - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_wococo::account_info_storage_key(account_id)) } From 99d3d36f0dcd2f4bcea7d0e899e13216ad3208ca Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 10 Jun 2021 10:48:42 -0400 Subject: [PATCH 0484/1210] Bump Rococo and Wococo spec versions (#999) --- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-wococo/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 5bac304376e63..246e7975674fc 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), authoring_version: 0, - spec_version: 9003, + spec_version: 9004, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 67510f6f46a3c..81dbaff186ff1 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -37,7 +37,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), authoring_version: 0, - spec_version: 9003, + spec_version: 9004, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, From ceeafdd4602c68a5492079d552b77294fb3cd524 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Jun 2021 16:55:05 +0300 Subject: [PATCH 0485/1210] rename messages_dispatch_weight -> message_details (#996) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 16 +++-- bin/rialto/runtime/src/lib.rs | 16 +++-- modules/messages/src/lib.rs | 10 +-- primitives/chain-kusama/src/lib.rs | 13 ++-- primitives/chain-millau/src/lib.rs | 13 ++-- primitives/chain-polkadot/src/lib.rs | 13 ++-- primitives/chain-rialto/src/lib.rs | 13 ++-- primitives/chain-rococo/src/lib.rs | 13 ++-- primitives/chain-westend/src/lib.rs | 13 ++-- primitives/chain-wococo/src/lib.rs | 13 ++-- primitives/messages/src/lib.rs | 13 ++++ .../src/chains/millau_messages_to_rialto.rs | 3 +- .../src/chains/rialto_messages_to_millau.rs | 3 +- relays/bin-substrate/src/messages_lane.rs | 2 +- relays/bin-substrate/src/messages_source.rs | 61 ++++++++++++------- 15 files changed, 130 insertions(+), 85 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d793c74a27448..da2db79b5555b 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -601,17 +601,23 @@ impl_runtime_apis! { ).ok() } - fn messages_dispatch_weight( + fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec<(bp_messages::MessageNonce, Weight, u32)> { + ) -> Vec> { (begin..=end).filter_map(|nonce| { - let encoded_payload = BridgeRialtoMessages::outbound_message_payload(lane, nonce)?; + let message_data = BridgeRialtoMessages::outbound_message_data(lane, nonce)?; let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode( - &mut &encoded_payload[..] + &mut &message_data.payload[..] ).ok()?; - Some((nonce, decoded_payload.weight, encoded_payload.len() as _)) + Some(bp_messages::MessageDetails { + nonce, + dispatch_weight: decoded_payload.weight, + size: message_data.payload.len() as _, + delivery_and_dispatch_fee: message_data.fee, + // TODO: include dispatch fee type (https://github.com/paritytech/parity-bridges-common/pull/911) + }) }) .collect() } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 6c2a1f7418bad..854acdbe1dbb9 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -752,17 +752,23 @@ impl_runtime_apis! { ).ok() } - fn messages_dispatch_weight( + fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec<(bp_messages::MessageNonce, Weight, u32)> { + ) -> Vec> { (begin..=end).filter_map(|nonce| { - let encoded_payload = BridgeMillauMessages::outbound_message_payload(lane, nonce)?; + let message_data = BridgeMillauMessages::outbound_message_data(lane, nonce)?; let decoded_payload = millau_messages::ToMillauMessagePayload::decode( - &mut &encoded_payload[..] + &mut &message_data.payload[..] ).ok()?; - Some((nonce, decoded_payload.weight, encoded_payload.len() as _)) + Some(bp_messages::MessageDetails { + nonce, + dispatch_weight: decoded_payload.weight, + size: message_data.payload.len() as _, + delivery_and_dispatch_fee: message_data.fee, + // TODO: include dispatch fee type (https://github.com/paritytech/parity-bridges-common/pull/911) + }) }) .collect() } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 4e9800e0c7d17..0d9b5788d2d65 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -49,8 +49,8 @@ use crate::weights::WeightInfo; use bp_messages::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, - OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, + total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OperatingMode, + OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, }; use bp_runtime::Size; use codec::{Decode, Encode}; @@ -607,9 +607,9 @@ decl_module! { } impl, I: Instance> Pallet { - /// Get payload of given outbound message. - pub fn outbound_message_payload(lane: LaneId, nonce: MessageNonce) -> Option { - OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(|message_data| message_data.payload) + /// Get stored data of the outbound message with given nonce. + pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option> { + OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } /// Get nonce of latest generated message at given outbound lane. diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 758bba5a718b7..d0e9e3acd503a 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -43,8 +43,8 @@ pub const IS_KNOWN_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_is_known_head /// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToKusamaOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_KUSAMA_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToKusamaOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. +pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; /// Name of the `ToKusamaOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD: &str = "ToKusamaOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToKusamaOutboundLaneApi::latest_received_nonce` runtime method. @@ -87,15 +87,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 7b88b7c49ad04..36c179ca5f29b 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -22,7 +22,7 @@ mod millau_hash; -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, @@ -244,8 +244,8 @@ pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_fi /// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToMillauOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToMillauOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. +pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; /// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; /// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. @@ -288,15 +288,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 7cd155d64a8fb..7ab1c7f4390b7 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -43,8 +43,8 @@ pub const IS_KNOWN_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_is_known_ /// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToPolkadotOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_POLKADOT_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToPolkadotOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. +pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; /// Name of the `ToPolkadotOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD: &str = "ToPolkadotOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToPolkadotOutboundLaneApi::latest_received_nonce` runtime method. @@ -87,15 +87,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 3cd19739d46f9..cc7c8e8c08cc6 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, @@ -205,8 +205,8 @@ pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_fi /// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToRialtoOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRialtoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. +pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; /// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. @@ -249,15 +249,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 246e7975674fc..20a5cd6658bb9 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -91,8 +91,8 @@ pub const IS_KNOWN_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_is_known_head /// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToRococoOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_ROCOCO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToRococoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. +pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; /// Name of the `ToRococoOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRococoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToRococoOutboundLaneApi::latest_received_nonce` runtime method. @@ -135,15 +135,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 42298100f670a..a0895da259d4e 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -98,8 +98,8 @@ pub const IS_KNOWN_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_is_known_he /// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_WESTEND_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToWestendOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToWestendOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_WESTEND_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToWestendOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToWestendOutboundLaneApi::message_details` runtime method. +pub const TO_WESTEND_MESSAGE_DETAILS_METHOD: &str = "ToWestendOutboundLaneApi_message_details"; /// Name of the `ToWestendOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_WESTEND_LATEST_GENERATED_NONCE_METHOD: &str = "ToWestendOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToWestendOutboundLaneApi::latest_received_nonce` runtime method. @@ -149,15 +149,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 81dbaff186ff1..94e3ecbf2e86a 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -98,8 +98,8 @@ pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_head /// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToWococoOutboundLaneApi::messages_dispatch_weight` runtime method. -pub const TO_WOCOCO_MESSAGES_DISPATCH_WEIGHT_METHOD: &str = "ToWococoOutboundLaneApi_messages_dispatch_weight"; +/// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. +pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; /// Name of the `ToWococoOutboundLaneApi::latest_generated_nonce` runtime method. pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method. @@ -142,15 +142,16 @@ sp_api::decl_runtime_apis! { lane_id: LaneId, payload: OutboundPayload, ) -> Option; - /// Returns total dispatch weight and encoded payload size of all messages in given inclusive range. + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. /// /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. - fn messages_dispatch_weight( + fn message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec<(MessageNonce, Weight, u32)>; + ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Returns nonce of the latest message, generated by given lane. diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 2bc33723291e3..211f4e717511f 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -163,6 +163,19 @@ impl InboundLaneData { } } +/// Message details, returned by runtime APIs. +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +pub struct MessageDetails { + /// Nonce assigned to the message. + pub nonce: MessageNonce, + /// Message dispatch weight, declared by the submitter. + pub dispatch_weight: Weight, + /// Size of the encoded message. + pub size: u32, + /// Delivery+dispatch fee paid by the message submitter at the source chain. + pub delivery_and_dispatch_fee: OutboundMessageFee, +} + /// Gist of `InboundLaneData::relayers` field used by runtime APIs. #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] pub struct UnrewardedRelayersState { diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index de2246a92303e..2bca68c37e35d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -42,8 +42,7 @@ pub type MillauMessagesToRialto = SubstrateMessageLaneToSubstrate; impl SubstrateMessageLane for MillauMessagesToRialto { - const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = - bp_rialto::TO_RIALTO_MESSAGES_DISPATCH_WEIGHT_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 981bc76db69c1..c85cf9d367886 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -42,8 +42,7 @@ pub type RialtoMessagesToMillau = SubstrateMessageLaneToSubstrate; impl SubstrateMessageLane for RialtoMessagesToMillau { - const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str = - bp_millau::TO_MILLAU_MESSAGES_DISPATCH_WEIGHT_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index bfca980a070c8..40de424a78d4a 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -49,7 +49,7 @@ pub struct MessagesRelayParams { /// Message sync pipeline for Substrate <-> Substrate relays. pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. - const OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD: &'static str; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; /// Name of the runtime method that returns latest generated nonce at the source chain. const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str; /// Name of the runtime method that returns latest received (confirmed) nonce at the the source chain. diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 49e2c7efeea93..68329a2dbcc3d 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -176,13 +176,13 @@ where let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_MESSAGES_DISPATCH_WEIGHT_METHOD.into(), + P::OUTBOUND_LANE_MESSAGE_DETAILS_METHOD.into(), Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Some(id.1), ) .await?; - make_message_weights_map::( + make_message_details_map::( Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?, nonces, ) @@ -287,8 +287,8 @@ where }) } -fn make_message_weights_map( - weights: Vec<(MessageNonce, Weight, u32)>, +fn make_message_details_map( + weights: Vec>, nonces: RangeInclusive, ) -> Result { let make_missing_nonce_error = |expected_nonce| { @@ -308,7 +308,7 @@ fn make_message_weights_map( // check if last nonce is missing - loop below is not checking this let last_nonce_is_missing = weights .last() - .map(|(last_nonce, _, _)| last_nonce != nonces.end()) + .map(|details| details.nonce != *nonces.end()) .unwrap_or(true); if last_nonce_is_missing { return make_missing_nonce_error(*nonces.end()); @@ -317,8 +317,8 @@ fn make_message_weights_map( let mut expected_nonce = *nonces.start(); let mut is_at_head = true; - for (nonce, weight, size) in weights { - match (nonce == expected_nonce, is_at_head) { + for details in weights { + match (details.nonce == expected_nonce, is_at_head) { (true, _) => (), (false, true) => { // this may happen if some messages were already pruned from the source node @@ -328,7 +328,7 @@ fn make_message_weights_map( target: "bridge", "Some messages are missing from the {} node: {:?}. Target node may be out of sync?", C::NAME, - expected_nonce..nonce, + expected_nonce..details.nonce, ); } (false, false) => { @@ -340,13 +340,13 @@ fn make_message_weights_map( } weights_map.insert( - nonce, + details.nonce, MessageWeights { - weight, - size: size as _, + weight: details.dispatch_weight, + size: details.size as _, }, ); - expected_nonce = nonce + 1; + expected_nonce = details.nonce + 1; is_at_head = false; } @@ -357,11 +357,24 @@ fn make_message_weights_map( mod tests { use super::*; + fn message_details_from_rpc( + nonces: RangeInclusive, + ) -> Vec> { + nonces + .into_iter() + .map(|nonce| bp_messages::MessageDetails { + nonce, + dispatch_weight: 0, + size: 0, + delivery_and_dispatch_fee: 0, + }) + .collect() + } + #[test] - fn make_message_weights_map_succeeds_if_no_messages_are_missing() { + fn make_message_details_map_succeeds_if_no_messages_are_missing() { assert_eq!( - make_message_weights_map::(vec![(1, 0, 0), (2, 0, 0), (3, 0, 0)], 1..=3,) - .unwrap(), + make_message_details_map::(message_details_from_rpc(1..=3), 1..=3,).unwrap(), vec![ (1, MessageWeights { weight: 0, size: 0 }), (2, MessageWeights { weight: 0, size: 0 }), @@ -373,9 +386,9 @@ mod tests { } #[test] - fn make_message_weights_map_succeeds_if_head_messages_are_missing() { + fn make_message_details_map_succeeds_if_head_messages_are_missing() { assert_eq!( - make_message_weights_map::(vec![(2, 0, 0), (3, 0, 0)], 1..=3,).unwrap(), + make_message_details_map::(message_details_from_rpc(2..=3), 1..=3,).unwrap(), vec![ (2, MessageWeights { weight: 0, size: 0 }), (3, MessageWeights { weight: 0, size: 0 }), @@ -386,25 +399,27 @@ mod tests { } #[test] - fn make_message_weights_map_fails_if_mid_messages_are_missing() { + fn make_message_details_map_fails_if_mid_messages_are_missing() { + let mut message_details_from_rpc = message_details_from_rpc(1..=3); + message_details_from_rpc.remove(1); assert!(matches!( - make_message_weights_map::(vec![(1, 0, 0), (3, 0, 0)], 1..=3,), + make_message_details_map::(message_details_from_rpc, 1..=3,), Err(SubstrateError::Custom(_)) )); } #[test] - fn make_message_weights_map_fails_if_tail_messages_are_missing() { + fn make_message_details_map_fails_if_tail_messages_are_missing() { assert!(matches!( - make_message_weights_map::(vec![(1, 0, 0), (2, 0, 0)], 1..=3,), + make_message_details_map::(message_details_from_rpc(1..=2), 1..=3,), Err(SubstrateError::Custom(_)) )); } #[test] - fn make_message_weights_map_fails_if_all_messages_are_missing() { + fn make_message_details_map_fails_if_all_messages_are_missing() { assert!(matches!( - make_message_weights_map::(vec![], 1..=3), + make_message_details_map::(vec![], 1..=3), Err(SubstrateError::Custom(_)) )); } From ab5dfa93af07301f8dbaac14db4ebb0d6593c724 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Jun 2021 22:21:58 +0300 Subject: [PATCH 0486/1210] Rococo <> Wococo relayer balance guard (#998) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * relayer balance guards in Rococo <> Wococo * removed printlns * update constant * update constant * start balance guard for Wococo -> Rococo * Update relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs Co-authored-by: Hernando Castano * Update relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs Co-authored-by: Hernando Castano Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- primitives/chain-rococo/Cargo.toml | 3 + primitives/chain-rococo/src/lib.rs | 18 ++++++ primitives/chain-wococo/Cargo.toml | 4 +- primitives/chain-wococo/src/lib.rs | 14 +---- primitives/polkadot-core/src/lib.rs | 8 +-- relays/bin-substrate/Cargo.toml | 3 +- .../src/chains/rococo_headers_to_wococo.rs | 14 +++-- .../src/chains/wococo_headers_to_rococo.rs | 58 +++++++++++++++++-- relays/bin-substrate/src/cli/relay_headers.rs | 11 +--- relays/bin-substrate/src/finality_pipeline.rs | 2 +- 10 files changed, 99 insertions(+), 36 deletions(-) diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index b97e8d9d1ab10..2f806b36327cf 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +smallvec = "1.6" # Bridge Dependencies bp-header-chain = { path = "../header-chain", default-features = false } @@ -16,6 +17,7 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -28,6 +30,7 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "parity-scale-codec/std", "sp-api/std", "sp-runtime/std", diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 20a5cd6658bb9..7940b40d43ed6 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -22,6 +22,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; +use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -43,6 +44,23 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { transaction_version: 0, }; +// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + const CENTS: Balance = 1_000_000_000_000 / 100; + let p = CENTS; + let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); + smallvec::smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + /// Rococo Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Rococo chain. diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index ecf783a51eeb9..ffa75b5a45ea2 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -13,13 +13,13 @@ parity-scale-codec = { version = "2.0.0", default-features = false, features = [ bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-rococo = { path = "../chain-rococo", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -28,9 +28,9 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "bp-rococo/std", "parity-scale-codec/std", "sp-api/std", "sp-runtime/std", "sp-std/std", - "sp-version/std", ] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 94e3ecbf2e86a..3aaa5a730ad15 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -23,26 +23,16 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use sp_std::prelude::*; -use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +// Rococo runtime = Wococo runtime +pub use bp_rococo::{WeightToFee, VERSION}; /// Wococo Chain pub type Wococo = PolkadotLike; pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; -// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), - authoring_version: 0, - spec_version: 9004, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 0, -}; - /// Wococo Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Rococo chain. diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index c9858c0820d71..a1619b27bcf47 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -22,7 +22,7 @@ use frame_support::{ dispatch::Dispatchable, parameter_types, weights::{ - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, + constants::{BlockExecutionWeight, WEIGHT_PER_SECOND}, DispatchClass, Weight, }, Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128, @@ -33,13 +33,13 @@ use sp_core::Hasher as HasherT; use sp_runtime::{ generic, traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiAddress, MultiSignature, OpaqueExtrinsic, Perbill, + MultiAddress, MultiSignature, OpaqueExtrinsic, }; use sp_std::prelude::Vec; // Re-export's to avoid extra substrate dependencies in chain-specific crates. -pub use frame_support::Parameter; -pub use sp_runtime::traits::Convert; +pub use frame_support::{weights::constants::ExtrinsicBaseWeight, Parameter}; +pub use sp_runtime::{traits::Convert, Perbill}; /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Polkadot-like chain. This mostly depends on number of entries in the storage trie. diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index fc61d138fde0b..3bbf05f3b1c56 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -59,5 +59,6 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } hex-literal = "0.3" +pallet-bridge-grandpa = { path = "../../modules/grandpa" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 4dfe800b2b6cd..4e641aec7490c 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -16,12 +16,13 @@ //! Rococo-to-Wococo headers sync entrypoint. +use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; use sp_core::{Bytes, Pair}; @@ -38,11 +39,16 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { crate::chains::add_polkadot_kusama_price_metrics::(params) } - fn start_relay_guards(target_client: &Client) { + fn start_relay_guards(&self) { relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), + self.target_client.clone(), bp_wococo::VERSION.spec_version, - ) + ); + relay_substrate_client::guard::abort_when_account_balance_decreased( + self.target_client.clone(), + self.transactions_author(), + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); } fn transactions_author(&self) -> bp_wococo::AccountId { diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 3b6a478269a97..4cae33db31d9d 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -21,11 +21,18 @@ use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityT use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; use sp_core::{Bytes, Pair}; +/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat +/// relay as gone wild. +/// +/// See `maximal_balance_decrease_per_day_is_sane` test for details. +/// Note that this is in plancks, so this corresponds to `1500 UNITS`. +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000; + /// Wococo-to-Rococo finality sync pipeline. pub(crate) type WococoFinalityToRococo = SubstrateFinalityToSubstrate; @@ -38,11 +45,16 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { crate::chains::add_polkadot_kusama_price_metrics::(params) } - fn start_relay_guards(target_client: &Client) { + fn start_relay_guards(&self) { relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), + self.target_client.clone(), bp_rococo::VERSION.spec_version, - ) + ); + relay_substrate_client::guard::abort_when_account_balance_decreased( + self.target_client.clone(), + self.transactions_author(), + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); } fn transactions_author(&self) -> bp_rococo::AccountId { @@ -65,3 +77,41 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { Bytes(transaction.encode()) } } + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::weights::WeightToFeePolynomial; + use pallet_bridge_grandpa::weights::WeightInfo; + + #[test] + fn maximal_balance_decrease_per_day_is_sane() { + // Rococo/Wococo GRANDPA pallet weights. They're now using Rialto weights => using `RialtoWeight` is justified. + // + // Using Rialto runtime this is slightly incorrect, because `DbWeight` of Rococo/Wococo runtime may differ + // from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is the same. + type RococoGrandpaPalletWeights = pallet_bridge_grandpa::weights::RialtoWeight; + + // The following formula shall not be treated as super-accurate - guard is to protect from mad relays, + // not to protect from over-average loses. + // + // Worst case: we're submitting proof for every source header. Since we submit every header, the number of + // headers in ancestry proof is near to 0 (let's round up to 2). And the number of authorities is 1024, + // which is (now) larger than on any existing chain => normally there'll be ~1024*2/3+1 commits. + const AVG_VOTES_ANCESTRIES_LEN: u32 = 2; + const AVG_PRECOMMITS_LEN: u32 = 1024 * 2 / 3 + 1; + let number_of_source_headers_per_day: bp_wococo::Balance = bp_wococo::DAYS as _; + let single_source_header_submit_call_weight = + RococoGrandpaPalletWeights::submit_finality_proof(AVG_VOTES_ANCESTRIES_LEN, AVG_PRECOMMITS_LEN); + // for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + adjusted fee + let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2; + let single_source_header_tx_cost = bp_rococo::WeightToFee::calc(&single_source_header_submit_tx_weight); + let maximal_expected_decrease = single_source_header_tx_cost * number_of_source_headers_per_day; + assert!( + MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_expected_decrease, + "Maximal expected loss per day {} is larger than hardcoded {}", + maximal_expected_decrease, + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index abce9b3bfe163..68065882886a8 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -97,15 +97,10 @@ impl RelayHeaders { let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; - Finality::start_relay_guards(&target_client); + let finality = Finality::new(target_client.clone(), target_sign); + finality.start_relay_guards(); - crate::finality_pipeline::run( - Finality::new(target_client.clone(), target_sign), - source_client, - target_client, - metrics_params, - ) - .await + crate::finality_pipeline::run(finality, source_client, target_client, metrics_params).await }) } } diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index fd222f1c2981b..fe0004bbbd05d 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -51,7 +51,7 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { /// Different finality bridges may have different set of guards - e.g. on ephemeral chains we /// don't need version guards, on test chains we don't care that much about relayer account /// balance, ... So the implementation is left to the specific bridges. - fn start_relay_guards(_target_client: &Client) {} + fn start_relay_guards(&self) {} /// Returns id of account that we're using to sign transactions at target chain. fn transactions_author(&self) -> ::AccountId; From 166390cca49d78eea59abc3f2ecceb4dbb116260 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 16 Jun 2021 16:36:19 +0300 Subject: [PATCH 0487/1210] Messages relayer operating mode (#995) * introduce relayer mode enum * removed MaximalReward mode * TODO * Saturating -> SaturatingAdd * ref issue in TODOs * Update relays/messages/src/message_race_delivery.rs Co-authored-by: Hernando Castano Co-authored-by: Hernando Castano --- .../src/chains/millau_messages_to_rialto.rs | 3 +- .../src/chains/rialto_messages_to_millau.rs | 3 +- relays/bin-substrate/src/messages_lane.rs | 1 + relays/bin-substrate/src/messages_source.rs | 66 ++- relays/bin-substrate/src/messages_target.rs | 11 +- relays/client-substrate/src/chain.rs | 4 +- relays/messages/Cargo.toml | 3 +- relays/messages/src/message_lane.rs | 7 + relays/messages/src/message_lane_loop.rs | 99 +++- relays/messages/src/message_race_delivery.rs | 514 ++++++++++++------ relays/messages/src/message_race_loop.rs | 43 +- relays/messages/src/message_race_strategy.rs | 80 ++- 12 files changed, 595 insertions(+), 239 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 2bca68c37e35d..f132088f546de 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -159,7 +159,7 @@ pub async fn run( }; // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() as usize / 3; + let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3; // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = select_delivery_transaction_limits::>( @@ -193,6 +193,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, + relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, }, }, MillauSourceClient::new( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index c85cf9d367886..02c6010f74f02 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -159,7 +159,7 @@ pub async fn run( }; // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() as usize / 3; + let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3; let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = select_delivery_transaction_limits::>( bp_millau::max_extrinsic_weight(), @@ -192,6 +192,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, + relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, }, }, RialtoSourceClient::new( diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 40de424a78d4a..7468c16706b91 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -139,6 +139,7 @@ where type MessagesProof = SubstrateMessagesProof; type MessagesReceivingProof = SubstrateMessagesReceivingProof; + type SourceChainBalance = Source::Balance; type SourceHeaderNumber = BlockNumberOf; type SourceHeaderHash = HashOf; diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 68329a2dbcc3d..ce82f8abe5e7c 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -30,7 +30,7 @@ use frame_support::{traits::Instance, weights::Weight}; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - ClientState, MessageProofParameters, MessageWeights, MessageWeightsMap, SourceClient, SourceClientState, + ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState, }, }; use pallet_bridge_messages::Config as MessagesConfig; @@ -112,6 +112,7 @@ where C::BlockNumber: BlockNumberBase, P: SubstrateMessageLane< MessagesProof = SubstrateMessagesProof, + SourceChainBalance = C::Balance, SourceHeaderNumber = ::Number, SourceHeaderHash = ::Hash, SourceChain = C, @@ -168,11 +169,11 @@ where Ok((id, latest_received_nonce)) } - async fn generated_messages_weights( + async fn generated_message_details( &self, id: SourceHeaderIdOf

, nonces: RangeInclusive, - ) -> Result { + ) -> Result, SubstrateError> { let encoded_response = self .client .state_call( @@ -242,6 +243,10 @@ where target_to_source_headers_relay.require_finalized_header(id).await; } } + + async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance { + num_traits::Zero::zero() // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 + } } pub async fn read_client_state( @@ -290,7 +295,7 @@ where fn make_message_details_map( weights: Vec>, nonces: RangeInclusive, -) -> Result { +) -> Result, SubstrateError> { let make_missing_nonce_error = |expected_nonce| { Err(SubstrateError::Custom(format!( "Missing nonce {} in messages_dispatch_weight call result. Expected all nonces from {:?}", @@ -298,7 +303,7 @@ fn make_message_details_map( ))) }; - let mut weights_map = MessageWeightsMap::new(); + let mut weights_map = MessageDetailsMap::new(); // this is actually prevented by external logic if nonces.is_empty() { @@ -341,9 +346,11 @@ fn make_message_details_map( weights_map.insert( details.nonce, - MessageWeights { - weight: details.dispatch_weight, + MessageDetails { + dispatch_weight: details.dispatch_weight, size: details.size as _, + // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 + reward: num_traits::Zero::zero(), }, ); expected_nonce = details.nonce + 1; @@ -376,9 +383,30 @@ mod tests { assert_eq!( make_message_details_map::(message_details_from_rpc(1..=3), 1..=3,).unwrap(), vec![ - (1, MessageWeights { weight: 0, size: 0 }), - (2, MessageWeights { weight: 0, size: 0 }), - (3, MessageWeights { weight: 0, size: 0 }), + ( + 1, + MessageDetails { + dispatch_weight: 0, + size: 0, + reward: 0 + } + ), + ( + 2, + MessageDetails { + dispatch_weight: 0, + size: 0, + reward: 0 + } + ), + ( + 3, + MessageDetails { + dispatch_weight: 0, + size: 0, + reward: 0 + } + ), ] .into_iter() .collect(), @@ -390,8 +418,22 @@ mod tests { assert_eq!( make_message_details_map::(message_details_from_rpc(2..=3), 1..=3,).unwrap(), vec![ - (2, MessageWeights { weight: 0, size: 0 }), - (3, MessageWeights { weight: 0, size: 0 }), + ( + 2, + MessageDetails { + dispatch_weight: 0, + size: 0, + reward: 0 + } + ), + ( + 3, + MessageDetails { + dispatch_weight: 0, + size: 0, + reward: 0 + } + ), ] .into_iter() .collect(), diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 715efce88ec28..f9ffb922db88b 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -27,7 +27,7 @@ use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::ChainId; use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use codec::{Decode, Encode}; -use frame_support::traits::Instance; +use frame_support::{traits::Instance, weights::Weight}; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, @@ -229,4 +229,13 @@ where source_to_target_headers_relay.require_finalized_header(id).await; } } + + async fn estimate_delivery_transaction_in_source_tokens( + &self, + _nonces: RangeInclusive, + _total_dispatch_weight: Weight, + _total_size: u32, + ) -> P::SourceChainBalance { + num_traits::Zero::zero() // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 + } } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index ba3634fb6fd0e..4cc8a0394d9ad 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -17,7 +17,7 @@ use bp_runtime::Chain as ChainBase; use frame_support::Parameter; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; -use num_traits::{CheckedSub, Zero}; +use num_traits::{CheckedSub, SaturatingAdd, Zero}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, @@ -58,7 +58,7 @@ pub trait Chain: ChainBase + Clone { /// /// The chain may suport 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: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + Zero; + type Balance: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + SaturatingAdd + Zero; } /// Substrate-based chain with `frame_system::Config::AccountData` set to diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index e02f8ccc86828..943a3b7d9cd8a 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -6,11 +6,12 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -async-std = "1.6.5" +async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" futures = "0.3.5" hex = "0.4" log = "0.4.11" +num-traits = "0.2" parking_lot = "0.11.0" # Bridge Dependencies diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs index 6473ec987500b..8757e9322ce44 100644 --- a/relays/messages/src/message_lane.rs +++ b/relays/messages/src/message_lane.rs @@ -19,6 +19,7 @@ //! 1) relay new messages from source to target node; //! 2) relay proof-of-delivery from target to source node. +use num_traits::{SaturatingAdd, Zero}; use relay_utils::{BlockNumberBase, HeaderId}; use std::fmt::Debug; @@ -34,6 +35,12 @@ pub trait MessageLane: 'static + Clone + Send + Sync { /// Messages receiving proof. type MessagesReceivingProof: Clone + Debug + Send + Sync; + /// The type of the source chain token balance, that is used to: + /// + /// 1) pay transaction fees; + /// 2) pay message delivery and dispatch fee; + /// 3) pay relayer rewards. + type SourceChainBalance: Clone + Copy + Debug + PartialOrd + SaturatingAdd + Zero + Send + Sync; /// Number of the source header. type SourceHeaderNumber: BlockNumberBase; /// Hash of the source header. diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index af04bf984e1f9..3ae1cb8a03f62 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -58,6 +58,15 @@ pub struct Params { pub delivery_params: MessageDeliveryParams, } +/// Relayer operating mode. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum RelayerMode { + /// The relayer doesn't care about rewards. + Altruistic, + /// The relayer will deliver all messages and confirmations as long as he's not losing any funds. + NoLosses, +} + /// Message delivery race parameters. #[derive(Debug, Clone)] pub struct MessageDeliveryParams { @@ -74,20 +83,24 @@ pub struct MessageDeliveryParams { /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. pub max_messages_weight_in_single_batch: Weight, /// Maximal cumulative size of relayed messages in single delivery transaction. - pub max_messages_size_in_single_batch: usize, + pub max_messages_size_in_single_batch: u32, + /// Relayer operating mode. + pub relayer_mode: RelayerMode, } -/// Message weights. +/// Message details. #[derive(Debug, Clone, Copy, PartialEq)] -pub struct MessageWeights { +pub struct MessageDetails { /// Message dispatch weight. - pub weight: Weight, + pub dispatch_weight: Weight, /// Message size (number of bytes in encoded payload). - pub size: usize, + pub size: u32, + /// The relayer reward paid in the source chain tokens. + pub reward: SourceChainBalance, } -/// Messages weights map. -pub type MessageWeightsMap = BTreeMap; +/// Messages details map. +pub type MessageDetailsMap = BTreeMap>; /// Message delivery race proof parameters. #[derive(Debug, PartialEq)] @@ -117,13 +130,13 @@ pub trait SourceClient: RelayClient { /// Returns mapping of message nonces, generated on this client, to their weights. /// - /// Some weights may be missing from returned map, if corresponding messages were pruned at + /// Some messages may be missing from returned map, if corresponding messages were pruned at /// the source chain. - async fn generated_messages_weights( + async fn generated_message_details( &self, id: SourceHeaderIdOf

, nonces: RangeInclusive, - ) -> Result; + ) -> Result, Self::Error>; /// Prove messages in inclusive range [begin; end]. async fn prove_messages( @@ -142,6 +155,9 @@ pub trait SourceClient: RelayClient { /// We need given finalized target header on source to continue synchronization. async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

); + + /// Estimate cost of single message confirmation transaction in source chain tokens. + async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance; } /// Target client trait. @@ -183,6 +199,17 @@ pub trait TargetClient: RelayClient { /// We need given finalized source header on target to continue synchronization. async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

); + + /// Estimate cost of messages delivery transaction in source chain tokens. + /// + /// Please keep in mind that the returned cost must be converted to the source chain + /// tokens, even though the transaction fee will be paid in the target chain tokens. + async fn estimate_delivery_transaction_in_source_tokens( + &self, + nonces: RangeInclusive, + total_dispatch_weight: Weight, + total_size: u32, + ) -> P::SourceChainBalance; } /// State of the client. @@ -426,6 +453,10 @@ pub(crate) mod tests { HeaderId(number, number) } + pub const CONFIRMATION_TRANSACTION_COST: TestSourceChainBalance = 1; + pub const DELIVERY_TRANSACTION_COST: TestSourceChainBalance = 1; + + pub type TestSourceChainBalance = u64; pub type TestSourceHeaderId = HeaderId; pub type TestTargetHeaderId = HeaderId; @@ -457,6 +488,7 @@ pub(crate) mod tests { type MessagesProof = TestMessagesProof; type MessagesReceivingProof = TestMessagesReceivingProof; + type SourceChainBalance = TestSourceChainBalance; type SourceHeaderNumber = TestSourceHeaderNumber; type SourceHeaderHash = TestSourceHeaderHash; @@ -490,6 +522,15 @@ pub(crate) mod tests { tick: Arc, } + impl Default for TestSourceClient { + fn default() -> Self { + TestSourceClient { + data: Arc::new(Mutex::new(TestClientData::default())), + tick: Arc::new(|_| {}), + } + } + } + #[async_trait] impl RelayClient for TestSourceClient { type Error = TestError; @@ -536,13 +577,22 @@ pub(crate) mod tests { Ok((id, data.source_latest_confirmed_received_nonce)) } - async fn generated_messages_weights( + async fn generated_message_details( &self, _id: SourceHeaderIdOf, nonces: RangeInclusive, - ) -> Result { + ) -> Result, TestError> { Ok(nonces - .map(|nonce| (nonce, MessageWeights { weight: 1, size: 1 })) + .map(|nonce| { + ( + nonce, + MessageDetails { + dispatch_weight: 1, + size: 1, + reward: 1, + }, + ) + }) .collect()) } @@ -596,6 +646,10 @@ pub(crate) mod tests { data.target_to_source_header_requirements.push(id); (self.tick)(&mut *data); } + + async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance { + CONFIRMATION_TRANSACTION_COST + } } #[derive(Clone)] @@ -604,6 +658,15 @@ pub(crate) mod tests { tick: Arc, } + impl Default for TestTargetClient { + fn default() -> Self { + TestTargetClient { + data: Arc::new(Mutex::new(TestClientData::default())), + tick: Arc::new(|_| {}), + } + } + } + #[async_trait] impl RelayClient for TestTargetClient { type Error = TestError; @@ -702,6 +765,15 @@ pub(crate) mod tests { data.source_to_target_header_requirements.push(id); (self.tick)(&mut *data); } + + async fn estimate_delivery_transaction_in_source_tokens( + &self, + _nonces: RangeInclusive, + _total_dispatch_weight: Weight, + total_size: u32, + ) -> TestSourceChainBalance { + DELIVERY_TRANSACTION_COST * (total_size as TestSourceChainBalance) + } } fn run_loop_test( @@ -734,6 +806,7 @@ pub(crate) mod tests { max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, max_messages_size_in_single_batch: 4, + relayer_mode: RelayerMode::Altruistic, }, }, source_client, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index b50b0ffe31ba3..8e88b3763cd87 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -15,8 +15,9 @@ use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_lane_loop::{ - MessageDeliveryParams, MessageProofParameters, MessageWeightsMap, SourceClient as MessageLaneSourceClient, - SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, + MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, RelayerMode, + SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, + TargetClientState, }; use crate::message_race_loop::{ MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient, @@ -28,13 +29,9 @@ use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; use futures::stream::FusedStream; +use num_traits::{SaturatingAdd, Zero}; use relay_utils::FailedClient; -use std::{ - collections::{BTreeMap, VecDeque}, - marker::PhantomData, - ops::RangeInclusive, - time::Duration, -}; +use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; /// Run message delivery race. pub async fn run( @@ -48,24 +45,27 @@ pub async fn run( ) -> Result<(), FailedClient> { crate::message_race_loop::run( MessageDeliveryRaceSource { - client: source_client, + client: source_client.clone(), metrics_msg: metrics_msg.clone(), _phantom: Default::default(), }, source_state_updates, MessageDeliveryRaceTarget { - client: target_client, + client: target_client.clone(), metrics_msg, _phantom: Default::default(), }, target_state_updates, stall_timeout, - MessageDeliveryStrategy::

{ + MessageDeliveryStrategy:: { + lane_source_client: source_client, + lane_target_client: target_client, max_unrewarded_relayer_entries_at_target: params.max_unrewarded_relayer_entries_at_target, max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, max_messages_size_in_single_batch: params.max_messages_size_in_single_batch, + relayer_mode: params.relayer_mode, latest_confirmed_nonces_at_source: VecDeque::new(), target_nonces: None, strategy: BasicStrategy::new(), @@ -107,7 +107,7 @@ where C: MessageLaneSourceClient

, { type Error = C::Error; - type NoncesRange = MessageWeightsMap; + type NoncesRange = MessageDetailsMap; type ProofParameters = MessageProofParameters; async fn nonces( @@ -125,10 +125,10 @@ where let new_nonces = if latest_generated_nonce > prev_latest_nonce { self.client - .generated_messages_weights(at_block.clone(), prev_latest_nonce + 1..=latest_generated_nonce) + .generated_message_details(at_block.clone(), prev_latest_nonce + 1..=latest_generated_nonce) .await? } else { - MessageWeightsMap::new() + MessageDetailsMap::new() }; Ok(( @@ -222,7 +222,11 @@ struct DeliveryRaceTargetNoncesData { } /// Messages delivery strategy. -struct MessageDeliveryStrategy { +struct MessageDeliveryStrategy { + /// The client that is connected to the message lane source node. + lane_source_client: SC, + /// The client that is connected to the message lane target node. + lane_target_client: TC, /// Maximal unrewarded relayer entries at target client. max_unrewarded_relayer_entries_at_target: MessageNonce, /// Maximal unconfirmed nonces at target client. @@ -232,7 +236,9 @@ struct MessageDeliveryStrategy { /// Maximal cumulative messages weight in the single delivery transaction. max_messages_weight_in_single_batch: Weight, /// Maximal messages size in the single delivery transaction. - max_messages_size_in_single_batch: usize, + max_messages_size_in_single_batch: u32, + /// Relayer operating mode. + relayer_mode: RelayerMode, /// Latest confirmed nonces at the source client + the header id where we have first met this nonce. latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, /// Target nonces from the source client. @@ -246,11 +252,11 @@ type MessageDeliveryStrategyBase

= BasicStrategy<

::SourceHeaderHash,

::TargetHeaderNumber,

::TargetHeaderHash, - MessageWeightsMap, + MessageDetailsMap<

::SourceChainBalance>,

::MessagesProof, >; -impl std::fmt::Debug for MessageDeliveryStrategy

{ +impl std::fmt::Debug for MessageDeliveryStrategy { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { fmt.debug_struct("MessageDeliveryStrategy") .field( @@ -280,10 +286,26 @@ impl std::fmt::Debug for MessageDeliveryStrategy

{ } } -impl RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> - for MessageDeliveryStrategy

+impl MessageDeliveryStrategy { + /// Returns total weight of all undelivered messages. + fn total_queued_dispatch_weight(&self) -> Weight { + self.strategy + .source_queue() + .iter() + .flat_map(|(_, range)| range.values().map(|details| details.dispatch_weight)) + .fold(0, |total, weight| total.saturating_add(weight)) + } +} + +#[async_trait] +impl RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> + for MessageDeliveryStrategy +where + P: MessageLane, + SC: MessageLaneSourceClient

, + TC: MessageLaneTargetClient

, { - type SourceNoncesRange = MessageWeightsMap; + type SourceNoncesRange = MessageDetailsMap; type ProofParameters = MessageProofParameters; type TargetNoncesData = DeliveryRaceTargetNoncesData; @@ -383,9 +405,9 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M ) } - fn select_nonces_to_deliver( + async fn select_nonces_to_deliver( &mut self, - race_state: &RaceState, TargetHeaderIdOf

, P::MessagesProof>, + race_state: RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) -> Option<(RangeInclusive, Self::ProofParameters)> { let best_finalized_source_header_id_at_best_target = race_state.best_finalized_source_header_id_at_best_target.clone()?; @@ -473,87 +495,205 @@ impl RaceStrategy, TargetHeaderIdOf

, P::M let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; let max_messages_size_in_single_batch = self.max_messages_size_in_single_batch; - let mut selected_weight: Weight = 0; - let mut selected_size: usize = 0; - let mut selected_count: MessageNonce = 0; + let relayer_mode = self.relayer_mode; + let lane_source_client = self.lane_source_client.clone(); + let lane_target_client = self.lane_target_client.clone(); + let previous_total_dispatch_weight = self.total_queued_dispatch_weight(); let selected_nonces = self .strategy - .select_nonces_to_deliver_with_selector(race_state, |range| { - let to_requeue = range - .into_iter() - .skip_while(|(_, weight)| { - // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` - // and `max_messages_size_in_single_batch`, we may still try to submit transaction - // with single message if message overflows these limits. The worst case would be if - // transaction will be rejected by the target runtime, but at least we have tried. - - // limit messages in the batch by weight - let new_selected_weight = match selected_weight.checked_add(weight.weight) { - Some(new_selected_weight) if new_selected_weight <= max_messages_weight_in_single_batch => { - new_selected_weight - } - new_selected_weight if selected_count == 0 => { - log::warn!( - target: "bridge", - "Going to submit message delivery transaction with declared dispatch \ - weight {:?} that overflows maximal configured weight {}", - new_selected_weight, - max_messages_weight_in_single_batch, - ); - new_selected_weight.unwrap_or(Weight::MAX) - } - _ => return false, - }; - - // limit messages in the batch by size - let new_selected_size = match selected_size.checked_add(weight.size) { - Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => { - new_selected_size - } - new_selected_size if selected_count == 0 => { - log::warn!( - target: "bridge", - "Going to submit message delivery transaction with message \ - size {:?} that overflows maximal configured size {}", - new_selected_size, - max_messages_size_in_single_batch, - ); - new_selected_size.unwrap_or(usize::MAX) - } - _ => return false, - }; - - // limit number of messages in the batch - let new_selected_count = selected_count + 1; - if new_selected_count > max_nonces { - return false; - } - - selected_weight = new_selected_weight; - selected_size = new_selected_size; - selected_count = new_selected_count; - true - }) - .collect::>(); - if to_requeue.is_empty() { - None - } else { - Some(to_requeue) - } - })?; + .select_nonces_to_deliver_with_selector(race_state.clone(), |range| async { + select_nonces_for_delivery_transaction( + relayer_mode, + max_nonces, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + lane_source_client.clone(), + lane_target_client.clone(), + range, + ) + .await + }) + .await?; + let new_total_dispatch_weight = self.total_queued_dispatch_weight(); + let dispatch_weight = previous_total_dispatch_weight - new_total_dispatch_weight; Some(( selected_nonces, MessageProofParameters { outbound_state_proof_required, - dispatch_weight: selected_weight, + dispatch_weight, }, )) } } -impl NoncesRange for MessageWeightsMap { +/// From given set of source nonces, that are ready to be delivered, select nonces +/// to fit into single delivery transaction. +/// +/// The function returns nonces that are NOT selected for current batch and will be +/// delivered later. +async fn select_nonces_for_delivery_transaction( + relayer_mode: RelayerMode, + max_messages_in_this_batch: MessageNonce, + max_messages_weight_in_single_batch: Weight, + max_messages_size_in_single_batch: u32, + lane_source_client: impl MessageLaneSourceClient

, + lane_target_client: impl MessageLaneTargetClient

, + ready_nonces: MessageDetailsMap, +) -> Option> { + let mut hard_selected_count = 0; + let mut soft_selected_count = 0; + + let mut selected_weight: Weight = 0; + let mut selected_size: u32 = 0; + let mut selected_count: MessageNonce = 0; + + let mut total_reward = P::SourceChainBalance::zero(); + let mut total_confirmations_cost = P::SourceChainBalance::zero(); + let mut total_cost = P::SourceChainBalance::zero(); + + // technically, multiple confirmations will be delivered in a single transaction, + // meaning less loses for relayer. But here we don't know the final relayer yet, so + // we're adding a separate transaction for every message. Normally, this cost is covered + // by the message sender. Probably reconsider this? + let confirmation_transaction_cost = if relayer_mode != RelayerMode::Altruistic { + lane_source_client.estimate_confirmation_transaction().await + } else { + Zero::zero() + }; + + for (index, (nonce, details)) in ready_nonces.iter().enumerate() { + // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` + // and `max_messages_size_in_single_batch`, we may still try to submit transaction + // with single message if message overflows these limits. The worst case would be if + // transaction will be rejected by the target runtime, but at least we have tried. + + // limit messages in the batch by weight + let new_selected_weight = match selected_weight.checked_add(details.dispatch_weight) { + Some(new_selected_weight) if new_selected_weight <= max_messages_weight_in_single_batch => { + new_selected_weight + } + new_selected_weight if selected_count == 0 => { + log::warn!( + target: "bridge", + "Going to submit message delivery transaction with declared dispatch \ + weight {:?} that overflows maximal configured weight {}", + new_selected_weight, + max_messages_weight_in_single_batch, + ); + new_selected_weight.unwrap_or(Weight::MAX) + } + _ => break, + }; + + // limit messages in the batch by size + let new_selected_size = match selected_size.checked_add(details.size) { + Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => new_selected_size, + new_selected_size if selected_count == 0 => { + log::warn!( + target: "bridge", + "Going to submit message delivery transaction with message \ + size {:?} that overflows maximal configured size {}", + new_selected_size, + max_messages_size_in_single_batch, + ); + new_selected_size.unwrap_or(u32::MAX) + } + _ => break, + }; + + // limit number of messages in the batch + let new_selected_count = selected_count + 1; + if new_selected_count > max_messages_in_this_batch { + break; + } + + // now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT + // to deliver it? It depends on the relayer strategy. + match relayer_mode { + RelayerMode::Altruistic => { + soft_selected_count = index + 1; + } + RelayerMode::NoLosses => { + let delivery_transaction_cost = lane_target_client + .estimate_delivery_transaction_in_source_tokens( + 0..=(new_selected_count as MessageNonce - 1), + new_selected_weight, + new_selected_size as u32, + ) + .await; + + // if it is the first message that makes reward less than cost, let's log it + // if this message makes batch profitable again, let's log it + let is_total_reward_less_than_cost = total_reward < total_cost; + let prev_total_cost = total_cost; + let prev_total_reward = total_reward; + total_confirmations_cost = total_confirmations_cost.saturating_add(&confirmation_transaction_cost); + total_reward = total_reward.saturating_add(&details.reward); + total_cost = total_confirmations_cost.saturating_add(&delivery_transaction_cost); + if !is_total_reward_less_than_cost && total_reward < total_cost { + log::debug!( + target: "bridge", + "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ + total reward {:?}->{:?}", + nonce, + details.reward, + prev_total_cost, + total_cost, + prev_total_reward, + total_reward, + ); + } else if is_total_reward_less_than_cost && total_reward >= total_cost { + log::debug!( + target: "bridge", + "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ + equal to the total reward {:?}->{:?} (again)", + nonce, + details.reward, + prev_total_cost, + total_cost, + prev_total_reward, + total_reward, + ); + } + + // NoLosses relayer never want to lose his funds + if total_reward >= total_cost { + soft_selected_count = index + 1; + } + } + } + + hard_selected_count = index + 1; + selected_weight = new_selected_weight; + selected_size = new_selected_size; + selected_count = new_selected_count; + } + + if hard_selected_count != soft_selected_count { + log::warn!( + target: "bridge", + "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy ({:?}) it has selected \ + nonces [{:?}; {:?}].", + ready_nonces.keys().next(), + ready_nonces.keys().next().map(|begin| begin + (hard_selected_count as MessageNonce) - 1), + relayer_mode, + ready_nonces.keys().next(), + ready_nonces.keys().next().map(|begin| begin + (soft_selected_count as MessageNonce) - 1), + + ); + + hard_selected_count = soft_selected_count; + } + if hard_selected_count != ready_nonces.len() { + Some(ready_nonces.into_iter().skip(hard_selected_count).collect()) + } else { + None + } +} + +impl NoncesRange for MessageDetailsMap { fn begin(&self) -> MessageNonce { self.keys().next().cloned().unwrap_or_default() } @@ -576,12 +716,42 @@ impl NoncesRange for MessageWeightsMap { mod tests { use super::*; use crate::message_lane_loop::{ - tests::{header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderId, TestTargetHeaderId}, - MessageWeights, + tests::{ + header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance, TestSourceClient, + TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, CONFIRMATION_TRANSACTION_COST, + DELIVERY_TRANSACTION_COST, + }, + MessageDetails, }; + const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST + DELIVERY_TRANSACTION_COST; + type TestRaceState = RaceState; - type TestStrategy = MessageDeliveryStrategy; + type TestStrategy = MessageDeliveryStrategy; + + fn source_nonces( + new_nonces: RangeInclusive, + confirmed_nonce: MessageNonce, + reward: TestSourceChainBalance, + ) -> SourceClientNonces> { + SourceClientNonces { + new_nonces: new_nonces + .into_iter() + .map(|nonce| { + ( + nonce, + MessageDetails { + dispatch_weight: 1, + size: 1, + reward, + }, + ) + }) + .into_iter() + .collect(), + confirmed_nonce: Some(confirmed_nonce), + } + } fn prepare_strategy() -> (TestRaceState, TestStrategy) { let mut race_state = RaceState { @@ -594,12 +764,15 @@ mod tests { }; let mut race_strategy = TestStrategy { + relayer_mode: RelayerMode::Altruistic, max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, max_messages_size_in_single_batch: 4, latest_confirmed_nonces_at_source: vec![(header_id(1), 19)].into_iter().collect(), + lane_source_client: TestSourceClient::default(), + lane_target_client: TestTargetClient::default(), target_nonces: Some(TargetClientNonces { latest_nonce: 19, nonces_data: DeliveryRaceTargetNoncesData { @@ -614,20 +787,9 @@ mod tests { strategy: BasicStrategy::new(), }; - race_strategy.strategy.source_nonces_updated( - header_id(1), - SourceClientNonces { - new_nonces: vec![ - (20, MessageWeights { weight: 1, size: 1 }), - (21, MessageWeights { weight: 1, size: 1 }), - (22, MessageWeights { weight: 1, size: 1 }), - (23, MessageWeights { weight: 1, size: 1 }), - ] - .into_iter() - .collect(), - confirmed_nonce: Some(19), - }, - ); + race_strategy + .strategy + .source_nonces_updated(header_id(1), source_nonces(20..=23, 19, DEFAULT_REWARD)); let target_nonces = TargetClientNonces { latest_nonce: 19, @@ -652,14 +814,15 @@ mod tests { #[test] fn weights_map_works_as_nonces_range() { - fn build_map(range: RangeInclusive) -> MessageWeightsMap { + fn build_map(range: RangeInclusive) -> MessageDetailsMap { range .map(|idx| { ( idx, - MessageWeights { - weight: idx, + MessageDetails { + dispatch_weight: idx, size: idx as _, + reward: idx as _, }, ) }) @@ -678,19 +841,19 @@ mod tests { assert_eq!(map.greater_than(30), None); } - #[test] - fn message_delivery_strategy_selects_messages_to_deliver() { + #[async_std::test] + async fn message_delivery_strategy_selects_messages_to_deliver() { let (state, mut strategy) = prepare_strategy(); // both sides are ready to relay new messages assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=23), proof_parameters(false, 4))) ); } - #[test] - fn message_delivery_strategy_selects_nothing_if_too_many_confirmations_missing() { + #[async_std::test] + async fn message_delivery_strategy_selects_nothing_if_too_many_confirmations_missing() { let (state, mut strategy) = prepare_strategy(); // if there are already `max_unconfirmed_nonces_at_target` messages on target, @@ -701,11 +864,11 @@ mod tests { )] .into_iter() .collect(); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state).await, None); } - #[test] - fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() { + #[async_std::test] + async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() { let (state, mut strategy) = prepare_strategy(); // if there are new confirmed nonces on source, we want to relay this information @@ -713,13 +876,13 @@ mod tests { let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=23), proof_parameters(true, 4))) ); } - #[test] - fn message_delivery_strategy_selects_nothing_if_there_are_too_many_unrewarded_relayers() { + #[async_std::test] + async fn message_delivery_strategy_selects_nothing_if_there_are_too_many_unrewarded_relayers() { let (state, mut strategy) = prepare_strategy(); // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, @@ -729,11 +892,12 @@ mod tests { unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 4; } - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state).await, None); } - #[test] - fn message_delivery_strategy_selects_nothing_if_proved_rewards_is_not_enough_to_remove_oldest_unrewarded_entry() { + #[async_std::test] + async fn message_delivery_strategy_selects_nothing_if_proved_rewards_is_not_enough_to_remove_oldest_unrewarded_entry( + ) { let (state, mut strategy) = prepare_strategy(); // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, @@ -746,11 +910,11 @@ mod tests { unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 4; } - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state).await, None); } - #[test] - fn message_delivery_strategy_includes_outbound_state_proof_if_proved_rewards_is_enough() { + #[async_std::test] + async fn message_delivery_strategy_includes_outbound_state_proof_if_proved_rewards_is_enough() { let (state, mut strategy) = prepare_strategy(); // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, @@ -764,73 +928,77 @@ mod tests { unrewarded_relayers.messages_in_oldest_entry = 3; } assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=23), proof_parameters(true, 4))) ); } - #[test] - fn message_delivery_strategy_limits_batch_by_messages_weight() { + #[async_std::test] + async fn message_delivery_strategy_limits_batch_by_messages_weight() { let (state, mut strategy) = prepare_strategy(); // not all queued messages may fit in the batch, because batch has max weight strategy.max_messages_weight_in_single_batch = 3; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) ); } - #[test] - fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight() { + #[async_std::test] + async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight() { let (state, mut strategy) = prepare_strategy(); // first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4) - strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().weight = 10; + strategy.strategy.source_queue_mut()[0] + .1 + .get_mut(&20) + .unwrap() + .dispatch_weight = 10; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=20), proof_parameters(false, 10))) ); } - #[test] - fn message_delivery_strategy_limits_batch_by_messages_size() { + #[async_std::test] + async fn message_delivery_strategy_limits_batch_by_messages_size() { let (state, mut strategy) = prepare_strategy(); // not all queued messages may fit in the batch, because batch has max weight strategy.max_messages_size_in_single_batch = 3; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) ); } - #[test] - fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size() { + #[async_std::test] + async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size() { let (state, mut strategy) = prepare_strategy(); // first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4) strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().size = 10; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=20), proof_parameters(false, 1))) ); } - #[test] - fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() { + #[async_std::test] + async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() { let (state, mut strategy) = prepare_strategy(); // not all queued messages may fit in the batch, because batch has max number of messages limit strategy.max_messages_in_single_batch = 3; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) ); } - #[test] - fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces() { + #[async_std::test] + async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces() { let (state, mut strategy) = prepare_strategy(); // 1 delivery confirmation from target to source is still missing, so we may only @@ -841,13 +1009,13 @@ mod tests { .collect(); strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) ); } - #[test] - fn message_delivery_strategy_waits_for_confirmed_nonce_header_to_appear_on_target() { + #[async_std::test] + async fn message_delivery_strategy_waits_for_confirmed_nonce_header_to_appear_on_target() { // 1 delivery confirmation from target to source is still missing, so we may deliver // reward confirmation with our message delivery transaction. But the problem is that // the reward has been paid at header 2 && this header is still unknown to target node. @@ -864,7 +1032,7 @@ mod tests { strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) ); @@ -881,13 +1049,13 @@ mod tests { state.best_finalized_source_header_id_at_source = Some(header_id(2)); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state).await, Some(((20..=23), proof_parameters(true, 4))) ); } - #[test] - fn source_header_is_requied_when_confirmations_are_required() { + #[async_std::test] + async fn source_header_is_required_when_confirmations_are_required() { // let's prepare situation when: // - all messages [20; 23] have been generated at source block#1; let (mut state, mut strategy) = prepare_strategy(); @@ -895,7 +1063,7 @@ mod tests { // relayers vector capacity; strategy.max_unconfirmed_nonces_at_target = 2; assert_eq!( - strategy.select_nonces_to_deliver(&state), + strategy.select_nonces_to_deliver(state.clone()).await, Some(((20..=21), proof_parameters(false, 2))) ); strategy.finalized_target_nonces_updated( @@ -912,12 +1080,12 @@ mod tests { }, &mut state, ); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state).await, None); // - messages [1; 10] receiving confirmation has been delivered at source block#2; strategy.source_nonces_updated( header_id(2), SourceClientNonces { - new_nonces: BTreeMap::new(), + new_nonces: MessageDetailsMap::new(), confirmed_nonce: Some(21), }, ); @@ -927,4 +1095,36 @@ mod tests { Some(header_id(2)) ); } + + #[async_std::test] + async fn no_losses_relayer_is_delivering_messages_if_cost_is_equal_to_reward() { + let (state, mut strategy) = prepare_strategy(); + strategy.relayer_mode = RelayerMode::NoLosses; + + // so now we have: + // - 20..=23 with reward = cost + // => strategy shall select all 20..=23 + assert_eq!( + strategy.select_nonces_to_deliver(state).await, + Some(((20..=23), proof_parameters(false, 4))) + ); + } + + #[async_std::test] + async fn no_losses_relayer_is_not_delivering_messages_if_cost_is_larger_than_reward() { + let (mut state, mut strategy) = prepare_strategy(); + let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD - DELIVERY_TRANSACTION_COST); + strategy.strategy.source_nonces_updated(header_id(2), nonces); + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + strategy.relayer_mode = RelayerMode::NoLosses; + + // so now we have: + // - 20..=23 with reward = cost + // - 24..=25 with reward less than cost + // => strategy shall only select 20..=23 + assert_eq!( + strategy.select_nonces_to_deliver(state).await, + Some(((20..=23), proof_parameters(false, 4))) + ); + } } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 646fad886d764..3b427a2d0e27f 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -143,6 +143,7 @@ pub trait TargetClient { } /// Race strategy. +#[async_trait] pub trait RaceStrategy: Debug { /// Type of nonces range expected from the source client. type SourceNoncesRange: NoncesRange; @@ -182,14 +183,14 @@ pub trait RaceStrategy: Debug { /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated /// data) from source to target node. /// Additionally, parameters required to generate proof are returned. - fn select_nonces_to_deliver( + async fn select_nonces_to_deliver( &mut self, - race_state: &RaceState, + race_state: RaceState, ) -> Option<(RangeInclusive, Self::ProofParameters)>; } /// State of the race. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct RaceState { /// Best finalized source header id at the source client. pub best_finalized_source_header_id_at_source: Option, @@ -438,7 +439,7 @@ pub async fn run, TC: TargetClient

>( if source_client_is_online { source_client_is_online = false; - let nonces_to_deliver = select_nonces_to_deliver(&race_state, &mut strategy); + let nonces_to_deliver = select_nonces_to_deliver(race_state.clone(), &mut strategy).await; let best_at_source = strategy.best_at_source(); if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { @@ -554,27 +555,25 @@ where now_time } -fn select_nonces_to_deliver( - race_state: &RaceState, +async fn select_nonces_to_deliver( + race_state: RaceState, strategy: &mut Strategy, ) -> Option<(SourceHeaderId, RangeInclusive, Strategy::ProofParameters)> where SourceHeaderId: Clone, Strategy: RaceStrategy, { - race_state - .best_finalized_source_header_id_at_best_target - .as_ref() - .and_then(|best_finalized_source_header_id_at_best_target| { - strategy - .select_nonces_to_deliver(race_state) - .map(|(nonces_range, proof_parameters)| { - ( - best_finalized_source_header_id_at_best_target.clone(), - nonces_range, - proof_parameters, - ) - }) + let best_finalized_source_header_id_at_best_target = + race_state.best_finalized_source_header_id_at_best_target.clone()?; + strategy + .select_nonces_to_deliver(race_state) + .await + .map(|(nonces_range, proof_parameters)| { + ( + best_finalized_source_header_id_at_best_target, + nonces_range, + proof_parameters, + ) }) } @@ -584,8 +583,8 @@ mod tests { use crate::message_race_strategy::BasicStrategy; use relay_utils::HeaderId; - #[test] - fn proof_is_generated_at_best_block_known_to_target_node() { + #[async_std::test] + async fn proof_is_generated_at_best_block_known_to_target_node() { const GENERATED_AT: u64 = 6; const BEST_AT_SOURCE: u64 = 10; const BEST_AT_TARGET: u64 = 8; @@ -620,7 +619,7 @@ mod tests { // the proof will be generated on source, but using BEST_AT_TARGET block assert_eq!( - select_nonces_to_deliver(&race_state, &mut strategy), + select_nonces_to_deliver(race_state, &mut strategy).await, Some((HeaderId(BEST_AT_TARGET, BEST_AT_TARGET), 6..=10, (),)) ); } diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 394574ecb44fc..c17845d97f722 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -19,9 +19,10 @@ use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces}; +use async_trait::async_trait; use bp_messages::MessageNonce; use relay_utils::HeaderId; -use std::{collections::VecDeque, fmt::Debug, marker::PhantomData, ops::RangeInclusive}; +use std::{collections::VecDeque, fmt::Debug, future::Future, marker::PhantomData, ops::RangeInclusive}; /// Nonces delivery strategy. #[derive(Debug)] @@ -57,6 +58,13 @@ where } } + /// Reference to source queue. + pub(crate) fn source_queue( + &self, + ) -> &VecDeque<(HeaderId, SourceNoncesRange)> { + &self.source_queue + } + /// Mutable reference to source queue to use in tests. #[cfg(test)] pub(crate) fn source_queue_mut( @@ -73,14 +81,14 @@ where /// right now, it should return `Some` with 'undeliverable' nonces. Please keep in mind that /// this should be the sub-range that the passed range ends with, because nonces are always /// delivered in-order. Otherwise the function will panic. - pub fn select_nonces_to_deliver_with_selector( + pub async fn select_nonces_to_deliver_with_selector>>( &mut self, - race_state: &RaceState< + race_state: RaceState< HeaderId, HeaderId, Proof, >, - mut selector: impl FnMut(SourceNoncesRange) -> Option, + selector: impl Fn(SourceNoncesRange) -> F, ) -> Option> { // if we do not know best nonce at target node, we can't select anything let target_nonce = self.best_target_nonce?; @@ -99,7 +107,7 @@ where // 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized // by target client // 3) selector is used for more complicated logic - let best_header_at_target = &race_state.best_finalized_source_header_id_at_best_target.as_ref()?; + let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target.clone()?; let mut nonces_end = None; while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { // select (sub) range to deliver @@ -111,7 +119,7 @@ where Some(queued_range) } else { // selector returns `Some(range)` if this `range` needs to be requeued - selector(queued_range) + selector(queued_range).await }; // requeue (sub) range and update range to deliver @@ -143,16 +151,17 @@ where } } +#[async_trait] impl RaceStrategy, HeaderId, Proof> for BasicStrategy where - SourceHeaderHash: Clone + Debug, - SourceHeaderNumber: Clone + Ord + Debug, - SourceNoncesRange: NoncesRange + Debug, - TargetHeaderHash: Debug, - TargetHeaderNumber: Debug, - Proof: Debug, + SourceHeaderHash: Clone + Debug + Send, + SourceHeaderNumber: Clone + Ord + Debug + Send, + SourceNoncesRange: NoncesRange + Debug + Send, + TargetHeaderHash: Debug + Send, + TargetHeaderNumber: Debug + Send, + Proof: Debug + Send, { type SourceNoncesRange = SourceNoncesRange; type ProofParameters = (); @@ -271,15 +280,16 @@ where )); } - fn select_nonces_to_deliver( + async fn select_nonces_to_deliver( &mut self, - race_state: &RaceState< + race_state: RaceState< HeaderId, HeaderId, Proof, >, ) -> Option<(RangeInclusive, Self::ProofParameters)> { - self.select_nonces_to_deliver_with_selector(race_state, |_| None) + self.select_nonces_to_deliver_with_selector(race_state, |_| async { None }) + .await .map(|range| (range, ())) } } @@ -396,28 +406,28 @@ mod tests { assert!(state.nonces_submitted.is_none()); } - #[test] - fn nothing_is_selected_if_something_is_already_selected() { + #[async_std::test] + async fn nothing_is_selected_if_something_is_already_selected() { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); } - #[test] - fn nothing_is_selected_if_something_is_already_submitted() { + #[async_std::test] + async fn nothing_is_selected_if_something_is_already_submitted() { let mut state = RaceState::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(1..=10); strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=10)); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); } - #[test] - fn select_nonces_to_deliver_works() { + #[async_std::test] + async fn select_nonces_to_deliver_works() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); strategy.best_target_nonces_updated(target_nonces(0), &mut state); @@ -427,14 +437,20 @@ mod tests { strategy.source_nonces_updated(header_id(5), source_nonces(7..=8)); state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some((1..=6, ()))); + assert_eq!( + strategy.select_nonces_to_deliver(state.clone()).await, + Some((1..=6, ())) + ); strategy.best_target_nonces_updated(target_nonces(6), &mut state); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); state.best_finalized_source_header_id_at_best_target = Some(header_id(5)); - assert_eq!(strategy.select_nonces_to_deliver(&state), Some((7..=8, ()))); + assert_eq!( + strategy.select_nonces_to_deliver(state.clone()).await, + Some((7..=8, ())) + ); strategy.best_target_nonces_updated(target_nonces(8), &mut state); - assert_eq!(strategy.select_nonces_to_deliver(&state), None); + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); } #[test] @@ -449,7 +465,9 @@ mod tests { state.best_target_header_id = Some(header_id(1)); assert_eq!( - strategy.select_nonces_to_deliver_with_selector(&state, |_| Some(50..=100)), + async_std::task::block_on( + strategy.select_nonces_to_deliver_with_selector(state, |_| async { Some(50..=100) }) + ), Some(1..=49), ); } @@ -464,7 +482,11 @@ mod tests { state.best_finalized_source_header_id_at_source = Some(header_id(1)); state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); state.best_target_header_id = Some(header_id(1)); - strategy.select_nonces_to_deliver_with_selector(&state, invalid_selector); + async_std::task::block_on(async move { + strategy + .select_nonces_to_deliver_with_selector(state, |range| async { invalid_selector(range) }) + .await; + }); } #[test] From 20127dcb1e2ac0a4f07c02e7e175a510c7df5aac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 16 Jun 2021 22:03:03 +0300 Subject: [PATCH 0488/1210] Add --only-mandatory-headers mode (#1004) --- relays/bin-substrate/src/cli/relay_headers.rs | 12 +- relays/bin-substrate/src/finality_pipeline.rs | 2 + relays/bin-substrate/src/on_demand_headers.rs | 178 ++++++++++++++---- .../client-substrate/src/finality_source.rs | 5 + relays/finality/src/finality_loop.rs | 9 +- relays/finality/src/finality_loop_tests.rs | 110 +++++++++-- 6 files changed, 259 insertions(+), 57 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 68065882886a8..ec521c2918d85 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -24,6 +24,9 @@ pub struct RelayHeaders { /// A bridge instance to relay headers for. #[structopt(possible_values = &RelayHeadersBridge::variants(), case_insensitive = true)] bridge: RelayHeadersBridge, + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed. + #[structopt(long)] + only_mandatory_headers: bool, #[structopt(flatten)] source: SourceConnectionParams, #[structopt(flatten)] @@ -100,7 +103,14 @@ impl RelayHeaders { let finality = Finality::new(target_client.clone(), target_sign); finality.start_relay_guards(); - crate::finality_pipeline::run(finality, source_client, target_client, metrics_params).await + crate::finality_pipeline::run( + finality, + source_client, + target_client, + self.only_mandatory_headers, + metrics_params, + ) + .await }) } } diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index fe0004bbbd05d..19fa0917df390 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -119,6 +119,7 @@ pub async fn run( pipeline: P, source_client: Client, target_client: Client, + only_mandatory_headers: bool, metrics_params: MetricsParams, ) -> anyhow::Result<()> where @@ -147,6 +148,7 @@ where tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, + only_mandatory_headers, }, metrics_params, futures::future::pending(), diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs index 5730fc3869be7..58ef268a29f78 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -24,11 +24,11 @@ use crate::finality_target::SubstrateFinalityTarget; use async_std::sync::{Arc, Mutex}; use bp_header_chain::justification::GrandpaJustification; use finality_relay::{ - FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, + FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader, TargetClient as FinalityTargetClient, }; use futures::{select, FutureExt}; -use num_traits::{CheckedSub, Zero}; +use num_traits::{CheckedSub, One, Zero}; use relay_substrate_client::{ finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef}, BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader, @@ -139,6 +139,7 @@ async fn background_task( SubstrateFinalityToSubstrate, >::new(source_client.clone(), Some(required_header_number.clone())); let mut finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); + let mut latest_non_mandatory_at_source = Zero::zero(); let mut restart_relay = true; let finality_relay_task = futures::future::Fuse::terminated(); @@ -181,15 +182,48 @@ async fn background_task( continue; } - // update required header - update_required_header_number_if_too_many_are_missing::( + // submit mandatory header if some headers are missing + let best_finalized_source_header_at_target_fmt = format!("{:?}", best_finalized_source_header_at_target); + let mandatory_scan_range = mandatory_headers_scan_range::( best_finalized_source_header_at_source.ok(), best_finalized_source_header_at_target.ok(), maximal_headers_difference, &required_header_number, - &relay_task_name, ) .await; + if let Some(mandatory_scan_range) = mandatory_scan_range { + let relay_mandatory_header_result = relay_mandatory_header_from_range( + &finality_source, + &required_header_number, + best_finalized_source_header_at_target_fmt, + ( + std::cmp::max(mandatory_scan_range.0, latest_non_mandatory_at_source), + mandatory_scan_range.1, + ), + &relay_task_name, + ) + .await; + match relay_mandatory_header_result { + Ok(true) => (), + Ok(false) => { + // there are no (or we don't need to relay them) mandatory headers in the range + // => to avoid scanning the same headers over and over again, remember that + latest_non_mandatory_at_source = mandatory_scan_range.1; + } + Err(e) => { + if e.is_connection_error() { + relay_utils::relay_loop::reconnect_failed_client( + FailedClient::Source, + relay_utils::relay_loop::RECONNECT_DELAY, + &mut finality_source, + &mut finality_target, + ) + .await; + continue; + } + } + } + } // start/restart relay if restart_relay { @@ -201,6 +235,7 @@ async fn background_task( tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, + only_mandatory_headers: false, }, MetricsParams::disabled(), futures::future::pending(), @@ -213,29 +248,29 @@ async fn background_task( } } -/// If there are too many source headers missing at target, we ask for syncing more headers. -async fn update_required_header_number_if_too_many_are_missing( +/// Returns `Some()` with inclusive range of headers which must be scanned for manadatory headers +/// and the first of such headers must be submitted to the target node. +async fn mandatory_headers_scan_range( best_finalized_source_header_at_source: Option, best_finalized_source_header_at_target: Option, maximal_headers_difference: C::BlockNumber, required_header_number: &RequiredHeaderNumberRef, - relay_task_name: &str, -) { - let mut required_header_number = required_header_number.lock().await; +) -> Option<(C::BlockNumber, C::BlockNumber)> { + let required_header_number = *required_header_number.lock().await; // if we have been unable to read header number from the target, then let's assume // that it is the same as required header number. Otherwise we risk submitting // unneeded transactions let best_finalized_source_header_at_target = - best_finalized_source_header_at_target.unwrap_or(*required_header_number); + best_finalized_source_header_at_target.unwrap_or(required_header_number); // if we have been unable to read header number from the source, then let's assume // that it is the same as at the target let best_finalized_source_header_at_source = best_finalized_source_header_at_source.unwrap_or(best_finalized_source_header_at_target); - // if there are too many source headers missing from the target node, require some - // new headers at target + // if there are too many source headers missing from the target node, sync mandatory + // headers to target // // why do we need that? When complex headers+messages relay is used, it'll normally only relay // headers when there are undelivered messages/confirmations. But security model of the @@ -245,22 +280,63 @@ async fn update_required_header_number_if_too_many_are_missing( let current_headers_difference = best_finalized_source_header_at_source .checked_sub(&best_finalized_source_header_at_target) .unwrap_or_else(Zero::zero); - if current_headers_difference > maximal_headers_difference { - // if relay is already asked to sync headers, don't log anything - if *required_header_number <= best_finalized_source_header_at_target { - log::trace!( - target: "bridge", - "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the {}", - C::NAME, - relay_task_name, - best_finalized_source_header_at_source, - best_finalized_source_header_at_target, - best_finalized_source_header_at_source, - ); + if current_headers_difference <= maximal_headers_difference { + return None; + } - *required_header_number = best_finalized_source_header_at_source; - } + // if relay is already asked to sync headers, don't do anything yet + if required_header_number > best_finalized_source_header_at_target { + return None; + } + + Some(( + best_finalized_source_header_at_target + One::one(), + best_finalized_source_header_at_source, + )) +} + +/// Try to find mandatory header in the inclusive headers range and, if one is found, ask to relay it. +/// +/// Returns `true` if header was found and (asked to be) relayed and `false` otherwise. +async fn relay_mandatory_header_from_range( + finality_source: &SubstrateFinalitySource, + required_header_number: &RequiredHeaderNumberRef, + best_finalized_source_header_at_target: String, + range: (SourceChain::BlockNumber, SourceChain::BlockNumber), + relay_task_name: &str, +) -> Result +where + SubstrateFinalitySource: FinalitySourceClient

, + P: FinalitySyncPipeline, +{ + // search for mandatory header first + let mandatory_source_header_number = find_mandatory_header_in_range(finality_source, range).await?; + + // if there are no mandatory headers - we have nothing to do + let mandatory_source_header_number = match mandatory_source_header_number { + Some(mandatory_source_header_number) => mandatory_source_header_number, + None => return Ok(false), + }; + + // `find_mandatory_header` call may take a while => check if `required_header_number` is still + // less than our `mandatory_source_header_number` before logging anything + let mut required_header_number = required_header_number.lock().await; + if *required_header_number >= mandatory_source_header_number { + return Ok(false); } + + log::trace!( + target: "bridge", + "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the mandatory {}", + SourceChain::NAME, + relay_task_name, + best_finalized_source_header_at_target, + range.1, + mandatory_source_header_number, + ); + + *required_header_number = mandatory_source_header_number; + Ok(true) } /// Read best finalized source block number from source client. @@ -315,6 +391,30 @@ where }) } +/// Read first mandatory header in given inclusive range. +/// +/// Returns `Ok(None)` if there were no mandatory headers in the range. +async fn find_mandatory_header_in_range( + finality_source: &SubstrateFinalitySource, + range: (SourceChain::BlockNumber, SourceChain::BlockNumber), +) -> Result, relay_substrate_client::Error> +where + SubstrateFinalitySource: FinalitySourceClient

, + P: FinalitySyncPipeline, +{ + let mut current = range.0; + while current <= range.1 { + let header: SyncHeader = finality_source.client().header_by_number(current).await?.into(); + if header.is_mandatory() { + return Ok(Some(current)); + } + + current += One::one(); + } + + Ok(None) +} + /// On-demand headers relay task name. fn on_demand_headers_relay_name() -> String { format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) @@ -330,16 +430,18 @@ mod tests { const AT_TARGET: Option = Some(1); #[async_std::test] - async fn updates_required_header_when_too_many_headers_missing() { - let required_header_number = Arc::new(Mutex::new(0)); - update_required_header_number_if_too_many_are_missing::( - AT_SOURCE, - AT_TARGET, - 5, - &required_header_number, - "test", - ) - .await; - assert_eq!(*required_header_number.lock().await, AT_SOURCE.unwrap()); + async fn mandatory_headers_scan_range_selects_range_if_too_many_headers_are_missing() { + assert_eq!( + mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, 5, &Arc::new(Mutex::new(0))).await, + Some((AT_TARGET.unwrap() + 1, AT_SOURCE.unwrap())), + ); + } + + #[async_std::test] + async fn mandatory_headers_scan_range_selects_nothing_if_enough_headers_are_relayed() { + assert_eq!( + mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, 10, &Arc::new(Mutex::new(0))).await, + None, + ); } } diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 140e1f17a6ab6..72a11ae99003b 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -51,6 +51,11 @@ impl FinalitySource { } } + /// Returns reference to the underlying RPC client. + pub fn client(&self) -> &Client { + &self.client + } + /// Returns best finalized block number. pub async fn on_chain_best_finalized_block_number(&self) -> Result { // we **CAN** continue to relay finality proofs if source node is out of sync, because diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index cce32839907d9..3ea729d123e7d 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -58,6 +58,8 @@ pub struct FinalitySyncParams { pub recent_finality_proofs_limit: usize, /// Timeout before we treat our transactions as lost and restart the whole sync process. pub stall_timeout: Duration, + /// If true, only mandatory headers are relayed. + pub only_mandatory_headers: bool, } /// Source client used in finality synchronization loop. @@ -364,7 +366,7 @@ where } } -async fn select_header_to_submit( +pub(crate) async fn select_header_to_submit( source_client: &SC, target_client: &TC, finality_proofs_stream: &mut RestartableFinalityProofsStream, @@ -397,6 +399,11 @@ where .await?; let (mut unjustified_headers, mut selected_finality_proof) = match selected_finality_proof { SelectedFinalityProof::Mandatory(header, finality_proof) => return Ok(Some((header, finality_proof))), + _ if sync_params.only_mandatory_headers => { + // we are not reading finality proofs from the stream, so eventually it'll break + // but we don't care about transient proofs at all, so it is acceptable + return Ok(None); + } SelectedFinalityProof::Regular(unjustified_headers, header, finality_proof) => { (unjustified_headers, Some((header, finality_proof))) } diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 72b3cdde3d27a..e7e0cdb39fb35 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -20,7 +20,8 @@ use crate::finality_loop::{ prune_recent_finality_proofs, read_finality_proofs_from_stream, run, select_better_recent_finality_proof, - FinalityProofs, FinalitySyncParams, SourceClient, TargetClient, + select_header_to_submit, FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, + TargetClient, }; use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; @@ -165,8 +166,11 @@ impl TargetClient for TestTargetClient { } } -fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static) -> ClientsData { - let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); +fn prepare_test_clients( + exit_sender: futures::channel::mpsc::UnboundedSender<()>, + state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, + source_headers: HashMap)>, +) -> (TestSourceClient, TestTargetClient) { let internal_state_function: Arc = Arc::new(move |data| { if state_function(data) { exit_sender.unbounded_send(()).unwrap(); @@ -174,7 +178,30 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync }); let clients_data = Arc::new(Mutex::new(ClientsData { source_best_block_number: 10, - source_headers: vec![ + source_headers, + source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], + + target_best_block_number: 5, + target_headers: vec![], + })); + ( + TestSourceClient { + on_method_call: internal_state_function.clone(), + data: clients_data.clone(), + }, + TestTargetClient { + on_method_call: internal_state_function, + data: clients_data, + }, + ) +} + +fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static) -> ClientsData { + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + let (source_client, target_client) = prepare_test_clients( + exit_sender, + state_function, + vec![ (6, (TestSourceHeader(false, 6), None)), (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), (8, (TestSourceHeader(true, 8), Some(TestFinalityProof(8)))), @@ -183,25 +210,15 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync ] .into_iter() .collect(), - source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], - - target_best_block_number: 5, - target_headers: vec![], - })); - let source_client = TestSourceClient { - on_method_call: internal_state_function.clone(), - data: clients_data.clone(), - }; - let target_client = TestTargetClient { - on_method_call: internal_state_function, - data: clients_data.clone(), - }; + ); let sync_params = FinalitySyncParams { tick: Duration::from_secs(0), recent_finality_proofs_limit: 1024, stall_timeout: Duration::from_secs(1), + only_mandatory_headers: false, }; + let clients_data = source_client.data.clone(); let _ = async_std::task::block_on(run( source_client, target_client, @@ -259,6 +276,65 @@ fn finality_sync_loop_works() { ); } +fn run_only_mandatory_headers_mode_test( + only_mandatory_headers: bool, + has_mandatory_headers: bool, +) -> Option<(TestSourceHeader, TestFinalityProof)> { + let (exit_sender, _) = futures::channel::mpsc::unbounded(); + let (source_client, target_client) = prepare_test_clients( + exit_sender, + |_| false, + vec![ + (6, (TestSourceHeader(false, 6), Some(TestFinalityProof(6)))), + (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), + ( + 8, + (TestSourceHeader(has_mandatory_headers, 8), Some(TestFinalityProof(8))), + ), + (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), + (10, (TestSourceHeader(false, 10), Some(TestFinalityProof(10)))), + ] + .into_iter() + .collect(), + ); + async_std::task::block_on(select_header_to_submit( + &source_client, + &target_client, + &mut RestartableFinalityProofsStream::from(futures::stream::empty().boxed()), + &mut vec![], + 10, + 5, + &FinalitySyncParams { + tick: Duration::from_secs(0), + recent_finality_proofs_limit: 0, + stall_timeout: Duration::from_secs(0), + only_mandatory_headers, + }, + )) + .unwrap() +} + +#[test] +fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_headers_are_required() { + assert_eq!(run_only_mandatory_headers_mode_test(true, false), None); + assert_eq!( + run_only_mandatory_headers_mode_test(false, false), + Some((TestSourceHeader(false, 10), TestFinalityProof(10))), + ); +} + +#[test] +fn select_header_to_submit_selects_mandatory_headers_when_only_mandatory_headers_are_required() { + assert_eq!( + run_only_mandatory_headers_mode_test(true, true), + Some((TestSourceHeader(true, 8), TestFinalityProof(8))), + ); + assert_eq!( + run_only_mandatory_headers_mode_test(false, true), + Some((TestSourceHeader(true, 8), TestFinalityProof(8))), + ); +} + #[test] fn select_better_recent_finality_proof_works() { // if there are no unjustified headers, nothing is changed From ac6bce1fb57ff1f19e995520a1137d6248d86f2b Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 17 Jun 2021 12:44:04 -0400 Subject: [PATCH 0489/1210] Bump Substrate to `286d7ce` (#1006) * Bump dependencies - Substrate to `74a1bfdcc` - `finality-grandpa` to `0.14.1` - `fs-swap` to `0.2.6` * Add `pallet_randomness_collective_flip` to runtimes * Rename GenesisConfig fields See Substrate PR: https://github.com/paritytech/substrate/pull/8990 * Missed PoA renames in Rialto GenesisConfig * Use `spawn_essential_handle` for transaction pool See Substrate PR: https://github.com/paritytech/substrate/pull/9074 --- bin/millau/node/src/chain_spec.rs | 14 +++++++------- bin/millau/node/src/service.rs | 4 ++-- bin/millau/runtime/src/lib.rs | 4 +++- bin/rialto/node/src/chain_spec.rs | 22 +++++++++++----------- bin/rialto/node/src/service.rs | 4 ++-- bin/rialto/runtime/src/lib.rs | 14 ++++++++------ bin/rialto/runtime/src/rialto_poa.rs | 2 +- modules/dispatch/src/lib.rs | 18 +++++++++--------- modules/messages/src/lib.rs | 8 ++++---- relays/bin-ethereum/src/instances.rs | 4 ++-- 10 files changed, 49 insertions(+), 45 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 872b81a88ce34..2b920786c971d 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -175,27 +175,27 @@ fn testnet_genesis( _enable_println: bool, ) -> GenesisConfig { GenesisConfig { - frame_system: SystemConfig { + system: SystemConfig { code: WASM_BINARY.expect("Millau development WASM not available").to_vec(), changes_trie_config: Default::default(), }, - pallet_balances: BalancesConfig { + balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, - pallet_aura: AuraConfig { + aura: AuraConfig { authorities: Vec::new(), }, - pallet_grandpa: GrandpaConfig { + grandpa: GrandpaConfig { authorities: Vec::new(), }, - pallet_sudo: SudoConfig { key: root_key }, - pallet_session: SessionConfig { + sudo: SudoConfig { key: root_key }, + session: SessionConfig { keys: initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), }, - pallet_bridge_grandpa_Instance1: BridgeWestendGrandpaConfig { + bridge_westend_grandpa: BridgeWestendGrandpaConfig { // for our deployments to avoid multiple same-nonces transactions: // //Alice is already used to initialize Rialto<->Millau bridge // => let's use //George to initialize Westend->Millau bridge diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 3c138a649e56a..a9d555a872c9b 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -103,7 +103,7 @@ pub fn new_partial( config.transaction_pool.clone(), config.role.is_authority().into(), config.prometheus_registry(), - task_manager.spawn_handle(), + task_manager.spawn_essential_handle(), client.clone(), ); @@ -389,7 +389,7 @@ pub fn new_light(mut config: Configuration) -> Result let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( config.transaction_pool.clone(), config.prometheus_registry(), - task_manager.spawn_handle(), + task_manager.spawn_essential_handle(), client.clone(), on_demand.clone(), )); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index da2db79b5555b..dd13afb06473f 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -205,6 +205,8 @@ impl frame_system::Config for Runtime { type OnSetCode = (); } +impl pallet_randomness_collective_flip::Config for Runtime {} + impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; } @@ -398,7 +400,7 @@ construct_runtime!( BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, System: frame_system::{Pallet, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 17b13c88fbb3a..e354cbc8818fe 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -16,7 +16,7 @@ use bp_rialto::derive_account_from_millau_id; use rialto_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoAConfig, GenesisConfig, GrandpaConfig, + AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; @@ -176,23 +176,23 @@ fn testnet_genesis( _enable_println: bool, ) -> GenesisConfig { GenesisConfig { - frame_system: SystemConfig { + system: SystemConfig { code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(), changes_trie_config: Default::default(), }, - pallet_balances: BalancesConfig { + balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, - pallet_aura: AuraConfig { + aura: AuraConfig { authorities: Vec::new(), }, - pallet_bridge_eth_poa_Instance1: load_rialto_poa_bridge_config(), - pallet_bridge_eth_poa_Instance2: load_kovan_bridge_config(), - pallet_grandpa: GrandpaConfig { + bridge_rialto_poa: load_rialto_poa_bridge_config(), + bridge_kovan: load_kovan_bridge_config(), + grandpa: GrandpaConfig { authorities: Vec::new(), }, - pallet_sudo: SudoConfig { key: root_key }, - pallet_session: SessionConfig { + sudo: SudoConfig { key: root_key }, + session: SessionConfig { keys: initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) @@ -201,8 +201,8 @@ fn testnet_genesis( } } -fn load_rialto_poa_bridge_config() -> BridgeRialtoPoAConfig { - BridgeRialtoPoAConfig { +fn load_rialto_poa_bridge_config() -> BridgeRialtoPoaConfig { + BridgeRialtoPoaConfig { initial_header: rialto_runtime::rialto_poa::genesis_header(), initial_difficulty: 0.into(), initial_validators: rialto_runtime::rialto_poa::genesis_validators(), diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index a1844aa1af0f5..103929cff526d 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -105,7 +105,7 @@ pub fn new_partial( config.transaction_pool.clone(), config.role.is_authority().into(), config.prometheus_registry(), - task_manager.spawn_handle(), + task_manager.spawn_essential_handle(), client.clone(), ); @@ -393,7 +393,7 @@ pub fn new_light(mut config: Configuration) -> Result let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( config.transaction_pool.clone(), config.prometheus_registry(), - task_manager.spawn_handle(), + task_manager.spawn_essential_handle(), client.clone(), on_demand.clone(), )); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 854acdbe1dbb9..dff373afb51f2 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -212,6 +212,8 @@ impl frame_system::Config for Runtime { type OnSetCode = (); } +impl pallet_randomness_collective_flip::Config for Runtime {} + impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; } @@ -500,7 +502,7 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialtoPoA: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, + BridgeRialtoPoa: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, BridgeKovan: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, @@ -508,7 +510,7 @@ construct_runtime!( BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event}, System: frame_system::{Pallet, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Aura: pallet_aura::{Pallet, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, @@ -600,21 +602,21 @@ impl_runtime_apis! { impl bp_eth_poa::RialtoPoAHeaderApi for Runtime { fn best_block() -> (u64, bp_eth_poa::H256) { - let best_block = BridgeRialtoPoA::best_block(); + let best_block = BridgeRialtoPoa::best_block(); (best_block.number, best_block.hash) } fn finalized_block() -> (u64, bp_eth_poa::H256) { - let finalized_block = BridgeRialtoPoA::finalized_block(); + let finalized_block = BridgeRialtoPoa::finalized_block(); (finalized_block.number, finalized_block.hash) } fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool { - BridgeRialtoPoA::is_import_requires_receipts(header) + BridgeRialtoPoa::is_import_requires_receipts(header) } fn is_known_block(hash: bp_eth_poa::H256) -> bool { - BridgeRialtoPoA::is_known_block(hash) + BridgeRialtoPoa::is_known_block(hash) } } diff --git a/bin/rialto/runtime/src/rialto_poa.rs b/bin/rialto/runtime/src/rialto_poa.rs index 83b263975a322..9bc74a2ebaac6 100644 --- a/bin/rialto/runtime/src/rialto_poa.rs +++ b/bin/rialto/runtime/src/rialto_poa.rs @@ -130,7 +130,7 @@ impl InclusionProofVerifier for RialtoBlockchain { fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { let is_transaction_finalized = - crate::BridgeRialtoPoA::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + crate::BridgeRialtoPoa::verify_transaction_finalized(proof.block, proof.index, &proof.proof); if !is_transaction_finalized { return None; diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 3a4fb8f87a0b6..42749e075efe2 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -531,7 +531,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageVersionSpecMismatch( + event: Event::Dispatch(call_dispatch::Event::::MessageVersionSpecMismatch( SOURCE_CHAIN_ID, id, TEST_SPEC_VERSION, @@ -558,7 +558,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageWeightMismatch( + event: Event::Dispatch(call_dispatch::Event::::MessageWeightMismatch( SOURCE_CHAIN_ID, id, 1345000, @@ -588,7 +588,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageSignatureMismatch( + event: Event::Dispatch(call_dispatch::Event::::MessageSignatureMismatch( SOURCE_CHAIN_ID, id )), @@ -610,7 +610,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageRejected( + event: Event::Dispatch(call_dispatch::Event::::MessageRejected( SOURCE_CHAIN_ID, id )), @@ -636,7 +636,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageCallDecodeFailed( + event: Event::Dispatch(call_dispatch::Event::::MessageCallDecodeFailed( SOURCE_CHAIN_ID, id )), @@ -663,7 +663,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageCallRejected( + event: Event::Dispatch(call_dispatch::Event::::MessageCallRejected( SOURCE_CHAIN_ID, id )), @@ -686,7 +686,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( SOURCE_CHAIN_ID, id, Ok(()) @@ -712,7 +712,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( SOURCE_CHAIN_ID, id, Ok(()) @@ -738,7 +738,7 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( SOURCE_CHAIN_ID, id, Ok(()) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 0d9b5788d2d65..e8a004b19aa49 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -891,7 +891,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_bridge_messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), + event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), topics: vec![], }], ); @@ -920,7 +920,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_bridge_messages(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), + event: TestEvent::Messages(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), topics: vec![], }], ); @@ -1021,7 +1021,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_bridge_messages(RawEvent::ParameterUpdated(parameter)), + event: TestEvent::Messages(RawEvent::ParameterUpdated(parameter)), topics: vec![], }], ); @@ -1045,7 +1045,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::pallet_bridge_messages(RawEvent::ParameterUpdated(parameter)), + event: TestEvent::Messages(RawEvent::ParameterUpdated(parameter)), topics: vec![], }], ); diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs index 6d3966ca45dca..2ade8632a92c0 100644 --- a/relays/bin-ethereum/src/instances.rs +++ b/relays/bin-ethereum/src/instances.rs @@ -60,7 +60,7 @@ impl BridgeInstance for RialtoPoA { .collect(), ); - rialto_runtime::Call::BridgeRialtoPoA(pallet_call) + rialto_runtime::Call::BridgeRialtoPoa(pallet_call) } fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { @@ -69,7 +69,7 @@ impl BridgeInstance for RialtoPoA { into_substrate_ethereum_receipts(header.extra()), ); - rialto_runtime::Call::BridgeRialtoPoA(pallet_call) + rialto_runtime::Call::BridgeRialtoPoa(pallet_call) } fn build_currency_exchange_call(&self, proof: Proof) -> Call { From fe757accf63b1d2d321bfab98f736a8bab062f20 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 18 Jun 2021 12:35:15 +0300 Subject: [PATCH 0490/1210] pay dispatch fee at target chain (#911) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * pay dispatch fee at target chain * refund unspent dispatch weight to messages relayer * test that transfer actually happens * pay-at-target-cchain benchmarks + fix previous benchmarks (invalid signature) * include/exclude pay-dispatch-fee weight from delivery_and_dispatch_fee/delivery tx cost * remvoe some redundant traces * enum DispatchFeePayment {} * typo * update docs * (revert removal of valid check) * Update modules/messages/src/benchmarking.rs Co-authored-by: Tomasz Drwięga * Update modules/messages/src/benchmarking.rs Co-authored-by: Tomasz Drwięga * Update modules/messages/src/benchmarking.rs Co-authored-by: Tomasz Drwięga * Update modules/messages/src/benchmarking.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 1 + bin/millau/runtime/src/rialto_messages.rs | 7 + bin/rialto/runtime/src/lib.rs | 26 +- bin/rialto/runtime/src/millau_messages.rs | 91 ++++++ bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/README.md | 4 +- bin/runtime-common/src/messages.rs | 118 ++++++-- .../src/messages_benchmarking.rs | 19 +- modules/dispatch/README.md | 2 + modules/dispatch/src/lib.rs | 179 +++++++++--- modules/messages/Cargo.toml | 2 + modules/messages/README.md | 17 ++ modules/messages/src/benchmarking.rs | 61 ++++- modules/messages/src/inbound_lane.rs | 259 ++++++++++++------ modules/messages/src/lib.rs | 181 +++++++++--- modules/messages/src/mock.rs | 49 +++- modules/messages/src/weights.rs | 173 ++++++------ modules/messages/src/weights_ext.rs | 17 ++ primitives/chain-millau/src/lib.rs | 9 +- primitives/chain-rialto/src/lib.rs | 9 +- primitives/message-dispatch/src/lib.rs | 19 +- primitives/messages/src/target_chain.rs | 21 +- primitives/runtime/src/lib.rs | 2 + primitives/runtime/src/messages.rs | 50 ++++ .../bin-substrate/src/cli/encode_message.rs | 4 +- relays/bin-substrate/src/cli/send_message.rs | 6 + relays/bin-substrate/src/messages_lane.rs | 2 +- 27 files changed, 1052 insertions(+), 278 deletions(-) create mode 100644 primitives/runtime/src/messages.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dd13afb06473f..cbbe7c92ee38a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -686,6 +686,7 @@ mod tests { bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, ); let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 6641dc01b7db5..b2754dcbf7b66 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -64,6 +64,7 @@ type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesD pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithRialtoMessageBridge, crate::Runtime, + pallet_balances::Pallet, pallet_bridge_dispatch::DefaultInstance, >; @@ -172,6 +173,7 @@ impl messages::BridgedChainWithMessages for Rialto { fn estimate_delivery_transaction( message_payload: &[u8], + include_pay_dispatch_fee_cost: bool, message_dispatch_weight: Weight, ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); @@ -182,6 +184,11 @@ impl messages::BridgedChainWithMessages for Rialto { dispatch_weight: extra_bytes_in_payload .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) + .saturating_sub(if include_pay_dispatch_fee_cost { + 0 + } else { + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT + }) .saturating_add(message_dispatch_weight), size: message_payload_len .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index dff373afb51f2..a2e9578c1d308 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -862,6 +862,7 @@ impl_runtime_apis! { } use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; + use bp_runtime::messages::DispatchFeePayment; use bridge_runtime_common::messages; use pallet_bridge_messages::benchmarking::{ Pallet as MessagesBench, @@ -905,6 +906,7 @@ impl_runtime_apis! { weight: params.size as _, origin: dispatch_origin, call: message_payload, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }; (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) } @@ -921,7 +923,7 @@ impl_runtime_apis! { use codec::Encode; use frame_support::weights::GetDispatchInfo; use pallet_bridge_messages::storage_keys; - use sp_runtime::traits::Header; + use sp_runtime::traits::{Header, IdentifyAccount}; let remark = match params.size { MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], @@ -934,12 +936,19 @@ impl_runtime_apis! { let (rialto_raw_public, rialto_raw_signature) = ed25519_sign( &call, &millau_account_id, + VERSION.spec_version, + bp_runtime::MILLAU_CHAIN_ID, + bp_runtime::RIALTO_CHAIN_ID, ); let rialto_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(rialto_raw_public)); let rialto_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( rialto_raw_signature, )); + if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { + Self::endow_account(&rialto_public.clone().into_account()); + } + let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< Runtime, ::MessagesInstance, @@ -960,6 +969,7 @@ impl_runtime_apis! { Default::default(), ); + let dispatch_fee_payment = params.dispatch_fee_payment.clone(); prepare_message_proof::( params, make_millau_message_key, @@ -978,6 +988,7 @@ impl_runtime_apis! { rialto_public, rialto_signature, ), + dispatch_fee_payment, call: call.encode(), }.encode(), ) @@ -1010,6 +1021,18 @@ impl_runtime_apis! { ), ) } + + fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool { + frame_system::Pallet::::events() + .into_iter() + .map(|event_record| event_record.event) + .any(|event| matches!( + event, + Event::pallet_bridge_dispatch(pallet_bridge_dispatch::Event::::MessageDispatched( + _, ([0, 0, 0, 0], nonce_from_event), _, + )) if nonce_from_event == nonce + )) + } } add_benchmark!( @@ -1105,6 +1128,7 @@ mod tests { bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, ); let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 5c1779a7fea94..4945d2a7dfee6 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -58,6 +58,7 @@ pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessag pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithMillauMessageBridge, crate::Runtime, + pallet_balances::Pallet, pallet_bridge_dispatch::DefaultInstance, >; @@ -172,6 +173,7 @@ impl messages::BridgedChainWithMessages for Millau { fn estimate_delivery_transaction( message_payload: &[u8], + include_pay_dispatch_fee_cost: bool, message_dispatch_weight: Weight, ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); @@ -182,6 +184,11 @@ impl messages::BridgedChainWithMessages for Millau { dispatch_weight: extra_bytes_in_payload .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) + .saturating_sub(if include_pay_dispatch_fee_cost { + 0 + } else { + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT + }) .saturating_add(message_dispatch_weight), size: message_payload_len .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE) @@ -258,3 +265,87 @@ impl MessagesParameter for RialtoToMillauMessagesParameter { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{AccountId, Call, ExistentialDeposit, Runtime, SystemCall, SystemConfig, VERSION}; + use bp_message_dispatch::CallOrigin; + use bp_messages::{ + target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, + MessageKey, + }; + use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount}; + use bridge_runtime_common::messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload}; + use frame_support::{ + traits::Currency, + weights::{GetDispatchInfo, WeightToFeePolynomial}, + }; + use sp_runtime::traits::Convert; + + #[test] + fn transfer_happens_when_dispatch_fee_is_paid_at_target_chain() { + // this test actually belongs to the `bridge-runtime-common` crate, but there we have no + // mock runtime. Making another one there just for this test, given that both crates + // live n single repo is an overkill + let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::().unwrap().into(); + ext.execute_with(|| { + let bridge = MILLAU_CHAIN_ID; + let call: Call = SystemCall::remark(vec![]).into(); + let dispatch_weight = call.get_dispatch_info().weight; + let dispatch_fee = ::WeightToFee::calc(&dispatch_weight); + assert!(dispatch_fee > 0); + + // create relayer account with minimal balance + let relayer_account: AccountId = [1u8; 32].into(); + let initial_amount = ExistentialDeposit::get(); + let _ = as Currency>::deposit_creating( + &relayer_account, + initial_amount, + ); + + // create dispatch account with minimal balance + dispatch fee + let dispatch_account = derive_account_id::<::SourceChainAccountId>( + bridge, + SourceAccount::Root, + ); + let dispatch_account = + ::AccountIdConverter::convert(dispatch_account); + let _ = as Currency>::deposit_creating( + &dispatch_account, + initial_amount + dispatch_fee, + ); + + // dispatch message with intention to pay dispatch fee at the target chain + FromMillauMessageDispatch::dispatch( + &relayer_account, + DispatchMessage { + key: MessageKey { + lane_id: Default::default(), + nonce: 0, + }, + data: DispatchMessageData { + payload: Ok(FromBridgedChainMessagePayload:: { + spec_version: VERSION.spec_version, + weight: dispatch_weight, + origin: CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: FromBridgedChainEncodedMessageCall::new(call.encode()), + }), + fee: 1, + }, + }, + ); + + // ensure that fee has been transferred from dispatch to relayer account + assert_eq!( + as Currency>::free_balance(&relayer_account), + initial_amount + dispatch_fee, + ); + assert_eq!( + as Currency>::free_balance(&dispatch_account), + initial_amount, + ); + }); + } +} diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 83803d06deb5d..07fe8910c21f8 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -24,6 +24,7 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-transaction-payment = { 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-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, optional = true } @@ -42,6 +43,7 @@ std = [ "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-transaction-payment/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index a7322af973996..38a47bfdcc9d9 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -102,7 +102,9 @@ This trait represents this chain from bridge point of view. Let's review every m have declared dispatch weight larger than 50% of the maximal bridged extrinsic weight. - `MessageBridge::estimate_delivery_transaction`: you will need to return estimated dispatch weight and - size of the delivery transaction that delivers a given message to the target chain. + size of the delivery transaction that delivers a given message to the target chain. The transaction + weight must or must not include the weight of pay-dispatch-fee operation, depending on the value + of `include_pay_dispatch_fee_cost` argument. - `MessageBridge::transaction_payment`: you'll need to return fee that the submitter must pay for given transaction on bridged chain. The best case is when you have the same conversion diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 52623c42c6831..5628977480910 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -26,9 +26,16 @@ use bp_messages::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_runtime::{ChainId, Size, StorageProofChecker}; +use bp_runtime::{ + messages::{DispatchFeePayment, MessageDispatchResult}, + ChainId, Size, StorageProofChecker, +}; use codec::{Decode, Encode}; -use frame_support::{traits::Instance, weights::Weight, RuntimeDebug}; +use frame_support::{ + traits::{Currency, ExistenceRequirement, Instance}, + weights::{Weight, WeightToFeePolynomial}, + RuntimeDebug, +}; use hash_db::Hasher; use sp_runtime::{ traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, @@ -124,6 +131,7 @@ pub trait BridgedChainWithMessages: ChainWithMessages { /// Estimate size and weight of single message delivery transaction at the Bridged chain. fn estimate_delivery_transaction( message_payload: &[u8], + include_pay_dispatch_fee_cost: bool, message_dispatch_weight: WeightOf, ) -> MessageTransaction>; @@ -326,8 +334,19 @@ pub mod source { relayer_fee_percent: u32, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - let delivery_transaction = - BridgedChain::::estimate_delivery_transaction(&payload.call, payload.weight.into()); + // + // if we're going to pay dispatch fee at the target chain, then we don't include weight + // of the message dispatch in the delivery transaction cost + let pay_dispatch_fee_at_target_chain = payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; + let delivery_transaction = BridgedChain::::estimate_delivery_transaction( + &payload.call, + pay_dispatch_fee_at_target_chain, + if pay_dispatch_fee_at_target_chain { + 0.into() + } else { + payload.weight.into() + }, + ); let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); // the fee (in This tokens) of all transactions that are made on This chain @@ -445,8 +464,18 @@ pub mod target { /// vector length. Custom decode implementation here is exactly to deal with this. #[derive(Decode, Encode, RuntimeDebug, PartialEq)] pub struct FromBridgedChainEncodedMessageCall { - pub(crate) encoded_call: Vec, - pub(crate) _marker: PhantomData, + encoded_call: Vec, + _marker: PhantomData, + } + + impl FromBridgedChainEncodedMessageCall { + /// Create encoded call. + pub fn new(encoded_call: Vec) -> Self { + FromBridgedChainEncodedMessageCall { + encoded_call, + _marker: PhantomData::default(), + } + } } impl From> for Result>, ()> { @@ -457,20 +486,28 @@ pub mod target { /// Dispatching Bridged -> This chain messages. #[derive(RuntimeDebug, Clone, Copy)] - pub struct FromBridgedChainMessageDispatch { - _marker: PhantomData<(B, ThisRuntime, ThisDispatchInstance)>, + pub struct FromBridgedChainMessageDispatch { + _marker: PhantomData<(B, ThisRuntime, ThisCurrency, ThisDispatchInstance)>, } - impl - MessageDispatch< as ChainWithMessages>::Balance> - for FromBridgedChainMessageDispatch + impl + MessageDispatch>, BalanceOf>> + for FromBridgedChainMessageDispatch where ThisDispatchInstance: frame_support::traits::Instance, - ThisRuntime: pallet_bridge_dispatch::Config, - >::Event: - From>, - pallet_bridge_dispatch::Pallet: - bp_message_dispatch::MessageDispatch<(LaneId, MessageNonce), Message = FromBridgedChainMessagePayload>, + ThisRuntime: pallet_bridge_dispatch::Config + + pallet_transaction_payment::Config, + ::OnChargeTransaction: + pallet_transaction_payment::OnChargeTransaction>>, + ThisCurrency: Currency>, Balance = BalanceOf>>, + >::Event: From< + pallet_bridge_dispatch::RawEvent<(LaneId, MessageNonce), AccountIdOf>, ThisDispatchInstance>, + >, + pallet_bridge_dispatch::Pallet: bp_message_dispatch::MessageDispatch< + AccountIdOf>, + (LaneId, MessageNonce), + Message = FromBridgedChainMessagePayload, + >, { type DispatchPayload = FromBridgedChainMessagePayload; @@ -480,14 +517,26 @@ pub mod target { message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0) } - fn dispatch(message: DispatchMessage>>) { + fn dispatch( + relayer_account: &AccountIdOf>, + message: DispatchMessage>>, + ) -> MessageDispatchResult { let message_id = (message.key.lane_id, message.key.nonce); pallet_bridge_dispatch::Pallet::::dispatch( B::BridgedChain::ID, B::ThisChain::ID, message_id, message.data.payload.map_err(drop), - ); + |dispatch_origin, dispatch_weight| { + ThisCurrency::transfer( + dispatch_origin, + relayer_account, + ThisRuntime::WeightToFee::calc(&dispatch_weight), + ExistenceRequirement::AllowDeath, + ) + .map_err(drop) + }, + ) } } @@ -854,6 +903,7 @@ mod tests { fn estimate_delivery_transaction( _message_payload: &[u8], + _include_pay_dispatch_fee_cost: bool, _message_dispatch_weight: WeightOf, ) -> MessageTransaction> { unreachable!() @@ -911,6 +961,7 @@ mod tests { fn estimate_delivery_transaction( _message_payload: &[u8], + _include_pay_dispatch_fee_cost: bool, message_dispatch_weight: WeightOf, ) -> MessageTransaction> { MessageTransaction { @@ -935,6 +986,7 @@ mod tests { spec_version: 1, weight: 100, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, call: ThisChainCall::Transfer.encode(), } .encode(); @@ -949,10 +1001,10 @@ mod tests { spec_version: 1, weight: 100, origin: bp_message_dispatch::CallOrigin::SourceRoot, - call: target::FromBridgedChainEncodedMessageCall:: { - encoded_call: ThisChainCall::Transfer.encode(), - _marker: PhantomData::default(), - }, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: target::FromBridgedChainEncodedMessageCall::::new( + ThisChainCall::Transfer.encode(), + ), } ); assert_eq!(Ok(ThisChainCall::Transfer), message_on_this_chain.call.into()); @@ -966,6 +1018,7 @@ mod tests { spec_version: 1, weight: 100, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![42], } } @@ -986,6 +1039,21 @@ mod tests { Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); + // let's check if estimation is less than hardcoded, if dispatch is paid at target chain + let mut payload_with_pay_on_target = regular_outbound_message_payload(); + payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; + let fee_at_source = source::estimate_message_dispatch_and_delivery_fee::( + &payload_with_pay_on_target, + OnThisChainBridge::RELAYER_FEE_PERCENT, + ) + .expect("estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message"); + assert!( + fee_at_source < EXPECTED_MINIMAL_FEE.into(), + "Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}", + fee_at_source, + EXPECTED_MINIMAL_FEE, + ); + // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( @@ -1016,6 +1084,7 @@ mod tests { spec_version: 1, weight: 100, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![42], }; @@ -1059,6 +1128,7 @@ mod tests { spec_version: 1, weight: 100, origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![42], }; @@ -1126,6 +1196,7 @@ mod tests { spec_version: 1, weight: 5, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![1, 2, 3, 4, 5, 6], },) .is_err() @@ -1141,6 +1212,7 @@ mod tests { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![1, 2, 3, 4, 5, 6], },) .is_err() @@ -1156,6 +1228,7 @@ mod tests { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![0; source::maximal_message_size::() as usize + 1], },) .is_err() @@ -1171,6 +1244,7 @@ mod tests { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![0; source::maximal_message_size::() as _], },), Ok(()), diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 639e5f6c5049b..3785f4a4607f0 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -25,6 +25,7 @@ use crate::messages::{ }; use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload}; +use bp_runtime::ChainId; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; use frame_support::weights::Weight; @@ -37,7 +38,13 @@ use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder /// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. /// /// Returns public key of the signer and the signature itself. -pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode) -> ([u8; 32], [u8; 64]) { +pub fn ed25519_sign( + target_call: &impl Encode, + source_account_id: &impl Encode, + target_spec_version: u32, + source_chain_id: ChainId, + target_chain_id: ChainId, +) -> ([u8; 32], [u8; 64]) { // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) let target_secret = SecretKey::from_bytes(&[ 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050, @@ -51,9 +58,13 @@ pub fn ed25519_sign(target_call: &impl Encode, source_account_id: &impl Encode) target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); let target_pair = ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); - let mut signature_message = Vec::new(); - target_call.encode_to(&mut signature_message); - source_account_id.encode_to(&mut signature_message); + let signature_message = pallet_bridge_dispatch::account_ownership_digest( + target_call, + source_account_id, + target_spec_version, + source_chain_id, + target_chain_id, + ); let target_origin_signature = target_pair .try_sign(&signature_message) .expect("Ed25519 try_sign should not fail in benchmarks"); diff --git a/modules/dispatch/README.md b/modules/dispatch/README.md index c4e703c402d5a..068ff1167f7d8 100644 --- a/modules/dispatch/README.md +++ b/modules/dispatch/README.md @@ -44,6 +44,8 @@ module events set: weight, the dispatch is rejected. Keep in mind, that even if post-dispatch weight will be less than specified, the submitter still have to declare (and pay for) the maximal possible weight (that is the pre-dispatch weight); +- `MessageDispatchPaymentFailed` event is emitted if the message submitter has selected to pay + dispatch fee at the target chain, but has failed to do that; - `MessageDispatched` event is emitted if the message has passed all checks and we have actually dispatched it. The dispatch may still fail, though - that's why we are including the dispatch result in the event payload. diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 42749e075efe2..eeb5d5c17d4ef 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -27,7 +27,11 @@ #![allow(clippy::unused_unit)] use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight}; -use bp_runtime::{derive_account_id, ChainId, SourceAccount}; +use bp_runtime::{ + derive_account_id, + messages::{DispatchFeePayment, MessageDispatchResult}, + ChainId, SourceAccount, +}; use codec::{Decode, Encode}; use frame_support::{ decl_event, decl_module, decl_storage, @@ -89,7 +93,8 @@ decl_storage! { decl_event!( pub enum Event where - >::MessageId + >::MessageId, + AccountId = ::AccountId, { /// Message has been rejected before reaching dispatch. MessageRejected(ChainId, MessageId), @@ -101,12 +106,14 @@ decl_event!( MessageWeightMismatch(ChainId, MessageId, Weight, Weight), /// Message signature mismatch. MessageSignatureMismatch(ChainId, MessageId), - /// Message has been dispatched with given result. - MessageDispatched(ChainId, MessageId, DispatchResult), /// We have failed to decode Call from the message. MessageCallDecodeFailed(ChainId, MessageId), /// The call from the message has been rejected by the call filter. MessageCallRejected(ChainId, MessageId), + /// The origin account has failed to pay fee for dispatching the message. + MessageDispatchPaymentFailed(ChainId, MessageId, AccountId, Weight), + /// Message has been dispatched with given result. + MessageDispatched(ChainId, MessageId, DispatchResult), /// Phantom member, never used. Needed to handle multiple pallet instances. _Dummy(PhantomData), } @@ -120,7 +127,7 @@ decl_module! { } } -impl, I: Instance> MessageDispatch for Pallet { +impl, I: Instance> MessageDispatch for Pallet { type Message = MessagePayload; @@ -128,7 +135,13 @@ impl, I: Instance> MessageDispatch for Pallet { message.weight } - fn dispatch(source_chain: ChainId, target_chain: ChainId, id: T::MessageId, message: Result) { + fn dispatch Result<(), ()>>( + source_chain: ChainId, + target_chain: ChainId, + id: T::MessageId, + message: Result, + pay_dispatch_fee: P, + ) -> MessageDispatchResult { // emit special even if message has been rejected by external component let message = match message { Ok(message) => message, @@ -140,12 +153,19 @@ impl, I: Instance> MessageDispatch for Pallet { id, ); Self::deposit_event(RawEvent::MessageRejected(source_chain, id)); - return; + return MessageDispatchResult { + unspent_weight: 0, + dispatch_fee_paid_during_dispatch: false, + }; } }; // verify spec version // (we want it to be the same, because otherwise we may decode Call improperly) + let mut dispatch_result = MessageDispatchResult { + unspent_weight: message.weight, + dispatch_fee_paid_during_dispatch: false, + }; let expected_version = ::Version::get().spec_version; if message.spec_version != expected_version { log::trace!( @@ -161,7 +181,7 @@ impl, I: Instance> MessageDispatch for Pallet { expected_version, message.spec_version, )); - return; + return dispatch_result; } // now that we have spec version checked, let's decode the call @@ -175,7 +195,7 @@ impl, I: Instance> MessageDispatch for Pallet { id, ); Self::deposit_event(RawEvent::MessageCallDecodeFailed(source_chain, id)); - return; + return dispatch_result; } }; @@ -207,7 +227,7 @@ impl, I: Instance> MessageDispatch for Pallet { target_signature, ); Self::deposit_event(RawEvent::MessageSignatureMismatch(source_chain, id)); - return; + return dispatch_result; } log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account); @@ -231,7 +251,7 @@ impl, I: Instance> MessageDispatch for Pallet { call, ); Self::deposit_event(RawEvent::MessageCallRejected(source_chain, id)); - return; + return dispatch_result; } // verify weight @@ -254,21 +274,43 @@ impl, I: Instance> MessageDispatch for Pallet { expected_weight, message.weight, )); - return; + return dispatch_result; } + // pay dispatch fee right before dispatch + let pay_dispatch_fee_at_target_chain = message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; + if pay_dispatch_fee_at_target_chain && pay_dispatch_fee(&origin_account, message.weight).is_err() { + log::trace!( + target: "runtime::bridge-dispatch", + "Failed to pay dispatch fee for dispatching message {:?}/{:?} with weight {}", + source_chain, + id, + message.weight, + ); + Self::deposit_event(RawEvent::MessageDispatchPaymentFailed( + source_chain, + id, + origin_account, + message.weight, + )); + return dispatch_result; + } + dispatch_result.dispatch_fee_paid_during_dispatch = pay_dispatch_fee_at_target_chain; + // finally dispatch message let origin = RawOrigin::Signed(origin_account).into(); + log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call); - let dispatch_result = call.dispatch(origin); - let actual_call_weight = extract_actual_weight(&dispatch_result, &dispatch_info); + let result = call.dispatch(origin); + let actual_call_weight = extract_actual_weight(&result, &dispatch_info); + dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight); log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", source_chain, id, - actual_call_weight, + dispatch_result.unspent_weight, message.weight, dispatch_result, ); @@ -276,8 +318,10 @@ impl, I: Instance> MessageDispatch for Pallet { Self::deposit_event(RawEvent::MessageDispatched( source_chain, id, - dispatch_result.map(drop).map_err(|e| e.error), + result.map(drop).map_err(|e| e.error), )); + + dispatch_result } } @@ -485,31 +529,32 @@ mod tests { fn prepare_message( origin: CallOrigin, call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch::MessageId>>::Message { MessagePayload { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, origin, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: EncodedCall(call.encode()), } } fn prepare_root_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch::MessageId>>::Message { prepare_message(CallOrigin::SourceRoot, call) } fn prepare_target_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch::MessageId>>::Message { let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); prepare_message(origin, call) } fn prepare_source_message( call: Call, - ) -> as MessageDispatch<::MessageId>>::Message { + ) -> as MessageDispatch::MessageId>>::Message { let origin = CallOrigin::SourceAccount(1); prepare_message(origin, call) } @@ -522,10 +567,12 @@ mod tests { const BAD_SPEC_VERSION: SpecVersion = 99; let mut message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let weight = message.weight; message.spec_version = BAD_SPEC_VERSION; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert_eq!(result.unspent_weight, weight); assert_eq!( System::events(), @@ -549,10 +596,11 @@ mod tests { let id = [0; 4]; let mut message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); - message.weight = 0; + message.weight = 7; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert_eq!(result.unspent_weight, 7); assert_eq!( System::events(), @@ -562,7 +610,7 @@ mod tests { SOURCE_CHAIN_ID, id, 1345000, - 0, + 7, )), topics: vec![], }], @@ -580,9 +628,11 @@ mod tests { call_origin, Call::System(>::remark(vec![1, 2, 3])), ); + let weight = message.weight; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert_eq!(result.unspent_weight, weight); assert_eq!( System::events(), @@ -604,7 +654,7 @@ mod tests { let id = [0; 4]; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(())); + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(()), |_, _| unreachable!()); assert_eq!( System::events(), @@ -627,10 +677,12 @@ mod tests { let mut message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let weight = message.weight; message.call.0 = vec![]; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert_eq!(result.unspent_weight, weight); assert_eq!( System::events(), @@ -657,7 +709,8 @@ mod tests { message.weight = weight; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert_eq!(result.unspent_weight, weight); assert_eq!( System::events(), @@ -673,6 +726,67 @@ mod tests { }); } + #[test] + fn should_emit_event_for_unpaid_calls() { + new_test_ext().execute_with(|| { + let id = [0; 4]; + + let mut message = + prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let weight = message.weight; + message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; + + System::set_block_number(1); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(())); + assert_eq!(result.unspent_weight, weight); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: Event::call_dispatch(call_dispatch::Event::::MessageDispatchPaymentFailed( + SOURCE_CHAIN_ID, + id, + AccountIdConverter::convert(derive_account_id::( + SOURCE_CHAIN_ID, + SourceAccount::Root + )), + TEST_WEIGHT, + )), + topics: vec![], + }], + ); + }); + } + + #[test] + fn should_dispatch_calls_paid_at_target_chain() { + new_test_ext().execute_with(|| { + let id = [0; 4]; + + let mut message = + prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; + + System::set_block_number(1); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(())); + assert!(result.dispatch_fee_paid_during_dispatch); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + SOURCE_CHAIN_ID, + id, + Ok(()) + )), + topics: vec![], + }], + ); + }); + } + #[test] fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { @@ -680,7 +794,8 @@ mod tests { let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert!(!result.dispatch_fee_paid_during_dispatch); assert_eq!( System::events(), @@ -706,7 +821,8 @@ mod tests { let message = prepare_target_message(call); System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert!(!result.dispatch_fee_paid_during_dispatch); assert_eq!( System::events(), @@ -732,7 +848,8 @@ mod tests { let message = prepare_source_message(call); System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message)); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert!(!result.dispatch_fee_paid_during_dispatch); assert_eq!( System::events(), diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 4a75fa8181f8a..983a74fe75083 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -14,6 +14,7 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies +bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } bp-rialto = { path = "../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } @@ -36,6 +37,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m [features] default = ["std"] std = [ + "bp-message-dispatch/std", "bp-messages/std", "bp-runtime/std", "bp-rialto/std", diff --git a/modules/messages/README.md b/modules/messages/README.md index eda5e28a6c888..47bcacdee7650 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -347,6 +347,23 @@ Both conditions are verified by `pallet_bridge_messages::ensure_weights_are_corr `pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every runtime's tests. +### Post-dispatch weight refunds of the `receive_messages_proof` call + +Weight formula of the `receive_messages_proof` call assumes that the dispatch fee of every message is +paid at the target chain (where call is executed), that every message will be dispatched and that +dispatch weight of the message will be exactly the weight that is returned from the +`MessageDispatch::dispatch_weight` method call. This isn't true for all messages, so the call returns +actual weight used to dispatch messages. + +This actual weight is the weight, returned by the weight formula, minus: +- the weight of undispatched messages, if we have failed to dispatch because of different issues; +- the unspent dispatch weight if the declared weight of some messages is less than their actual post-dispatch weight; +- the pay-dispatch-fee weight for every message that had dispatch fee paid at the source chain. + +The last component is computed as a difference between two benchmarks results - the `receive_single_message_proof` +benchmark (that assumes that the fee is paid during dispatch) and the `receive_single_prepaid_message_proof` +(that assumes that the dispatch fee is already paid). + ### Weight of `receive_messages_delivery_proof` call #### Related benchmarks diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index d1ecf7750002f..5fc04bb2b203b 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -23,6 +23,7 @@ use bp_messages::{ source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayersState, }; +use bp_runtime::messages::DispatchFeePayment; use frame_benchmarking::{account, benchmarks_instance}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; @@ -67,6 +68,8 @@ pub struct MessageProofParams { pub outbound_lane_data: Option, /// Proof size requirements. pub size: ProofSize, + /// If true, dispatch fee is paid at the target chain (if supported by configuration). + pub dispatch_fee_payment: DispatchFeePayment, } /// Benchmark-specific message delivery proof parameters. @@ -108,6 +111,8 @@ pub trait Config: crate::Config { fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> >::MessagesDeliveryProof; + /// Returns true if message has been dispatched (either successfully or not). + fn is_message_dispatched(nonce: MessageNonce) -> bool; } benchmarks_instance! { @@ -242,7 +247,8 @@ benchmarks_instance! { // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. + // * message requires all heavy checks done by dispatcher; + // * message dispatch fee is paid at target (this) chain. // // This is base benchmark for all other message delivery benchmarks. receive_single_message_proof { @@ -257,6 +263,7 @@ benchmarks_instance! { message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -264,13 +271,15 @@ benchmarks_instance! { crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); + assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with two minimal-weight messages and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. + // * message requires all heavy checks done by dispatcher; + // * message dispatch fee is paid at target (this) chain. // // The weight of single message delivery could be approximated as // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. @@ -288,6 +297,7 @@ benchmarks_instance! { message_nonces: 21..=22, outbound_lane_data: None, size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { @@ -295,13 +305,15 @@ benchmarks_instance! { crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 22, ); + assert!(T::is_message_dispatched(22)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof includes outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. + // * message requires all heavy checks done by dispatcher; + // * message dispatch fee is paid at target (this) chain. // // The weight of outbound lane state delivery would be // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. @@ -323,6 +335,7 @@ benchmarks_instance! { latest_generated_nonce: 21, }), size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -334,6 +347,7 @@ benchmarks_instance! { crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), 20, ); + assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: @@ -357,6 +371,7 @@ benchmarks_instance! { message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasExtraNodes(1024), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -364,6 +379,7 @@ benchmarks_instance! { crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); + assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: @@ -389,6 +405,40 @@ benchmarks_instance! { message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasExtraNodes(16 * 1024), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) + verify { + assert_eq!( + crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + 21, + ); + assert!(T::is_message_dispatched(21)); + } + + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is successfully dispatched; + // * message requires all heavy checks done by dispatcher; + // * message dispatch fee is paid at source (bridged) chain. + // + // This benchmark is used to compute extra weight spent at target chain when fee is paid there. Then we use + // this information in two places: (1) to reduce weight of delivery tx if sender pays fee at the source chain + // and (2) to refund relayer with this weight if fee has been paid at the source chain. + receive_single_prepaid_message_proof { + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: T::bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -396,6 +446,7 @@ benchmarks_instance! { crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), 21, ); + assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -569,6 +620,7 @@ benchmarks_instance! { message_nonces: 21..=(20 + i as MessageNonce), outbound_lane_data: None, size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -606,6 +658,7 @@ benchmarks_instance! { message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasExtraNodes(i as _), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -643,6 +696,7 @@ benchmarks_instance! { message_nonces: 21..=21, outbound_lane_data: None, size: ProofSize::HasLargeLeaf(i as _), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), @@ -686,6 +740,7 @@ benchmarks_instance! { latest_generated_nonce: 21, }), size: ProofSize::Minimal(0), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof( RawOrigin::Signed(relayer_id_on_target), diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index f0655f8c958ed..92eb8d665dfa8 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -20,6 +20,8 @@ use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, }; +use bp_runtime::messages::MessageDispatchResult; +use frame_support::RuntimeDebug; use sp_std::prelude::PartialEq; /// Inbound lane storage. @@ -27,7 +29,7 @@ pub trait InboundLaneStorage { /// Delivery and dispatch fee type on source chain. type MessageFee; /// Id of relayer on source chain. - type Relayer: PartialEq; + type Relayer: Clone + PartialEq; /// Lane id. fn id(&self) -> LaneId; @@ -41,6 +43,22 @@ pub trait InboundLaneStorage { fn set_data(&mut self, data: InboundLaneData); } +/// Result of single message receival. +#[derive(RuntimeDebug, PartialEq, Eq)] +pub enum ReceivalResult { + /// Message has been received and dispatched. Note that we don't care whether dispatch has + /// been successful or not - in both case message falls into this category. + /// + /// The message dispatch result is also returned. + Dispatched(MessageDispatchResult), + /// Message has invalid nonce and lane has rejected to accept this message. + InvalidNonce, + /// There are too many unrewarded relayer entires at the lane. + TooManyUnrewardedRelayers, + /// There are too many unconfirmed messages at the lane. + TooManyUnconfirmedMessages, +} + /// Inbound messages lane. pub struct InboundLane { storage: S, @@ -90,51 +108,54 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message>( + pub fn receive_message, AccountId>( &mut self, - relayer: S::Relayer, + relayer_at_bridged_chain: &S::Relayer, + relayer_at_this_chain: &AccountId, nonce: MessageNonce, message_data: DispatchMessageData, - ) -> bool { + ) -> ReceivalResult { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { - return false; + return ReceivalResult::InvalidNonce; } // if there are more unrewarded relayer entries than we may accept, reject this message if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() { - return false; + return ReceivalResult::TooManyUnrewardedRelayers; } // if there are more unconfirmed messages than we may accept, reject this message let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce); if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { - return false; + return ReceivalResult::TooManyUnconfirmedMessages; } let push_new = match data.relayers.back_mut() { - Some((_, nonce_high, last_relayer)) if last_relayer == &relayer => { + Some((_, nonce_high, last_relayer)) if last_relayer == relayer_at_bridged_chain => { *nonce_high = nonce; false } _ => true, }; if push_new { - data.relayers.push_back((nonce, nonce, relayer)); + data.relayers + .push_back((nonce, nonce, (*relayer_at_bridged_chain).clone())); } self.storage.set_data(data); - P::dispatch(DispatchMessage { - key: MessageKey { - lane_id: self.storage.id(), - nonce, + ReceivalResult::Dispatched(P::dispatch( + relayer_at_this_chain, + DispatchMessage { + key: MessageKey { + lane_id: self.storage.id(), + nonce, + }, + data: message_data, }, - data: message_data, - }); - - true + )) } } @@ -144,8 +165,8 @@ mod tests { use crate::{ inbound_lane, mock::{ - message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, - TEST_RELAYER_B, TEST_RELAYER_C, + dispatch_result, message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, + TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C, }, DefaultInstance, RuntimeInboundLaneStorage, }; @@ -154,11 +175,15 @@ mod tests { lane: &mut InboundLane>, nonce: MessageNonce, ) { - assert!(lane.receive_message::( - TEST_RELAYER_A, - nonce, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + nonce, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); } #[test] @@ -269,11 +294,15 @@ mod tests { fn fails_to_receive_message_with_incorrect_nonce() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(!lane.receive_message::( - TEST_RELAYER_A, - 10, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + 10, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::InvalidNonce + ); assert_eq!(lane.storage.data().last_delivered_nonce(), 0); }); } @@ -284,24 +313,36 @@ mod tests { let mut lane = inbound_lane::(TEST_LANE_ID); let max_nonce = ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); for current_nonce in 1..max_nonce + 1 { - assert!(lane.receive_message::( - TEST_RELAYER_A + current_nonce, - current_nonce, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &(TEST_RELAYER_A + current_nonce), + &(TEST_RELAYER_A + current_nonce), + current_nonce, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); } // Fails to dispatch new message from different than latest relayer. - assert!(!lane.receive_message::( - TEST_RELAYER_A + max_nonce + 1, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &(TEST_RELAYER_A + max_nonce + 1), + &(TEST_RELAYER_A + max_nonce + 1), + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::TooManyUnrewardedRelayers, + ); // Fails to dispatch new messages from latest relayer. Prevents griefing attacks. - assert!(!lane.receive_message::( - TEST_RELAYER_A + max_nonce, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &(TEST_RELAYER_A + max_nonce), + &(TEST_RELAYER_A + max_nonce), + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::TooManyUnrewardedRelayers, + ); }); } @@ -311,24 +352,36 @@ mod tests { let mut lane = inbound_lane::(TEST_LANE_ID); let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); for current_nonce in 1..=max_nonce { - assert!(lane.receive_message::( - TEST_RELAYER_A, - current_nonce, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + current_nonce, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); } // Fails to dispatch new message from different than latest relayer. - assert!(!lane.receive_message::( - TEST_RELAYER_B, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_B, + &TEST_RELAYER_B, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::TooManyUnconfirmedMessages, + ); // Fails to dispatch new messages from latest relayer. - assert!(!lane.receive_message::( - TEST_RELAYER_A, - max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + max_nonce + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::TooManyUnconfirmedMessages, + ); }); } @@ -336,21 +389,33 @@ mod tests { fn correctly_receives_following_messages_from_two_relayers_alternately() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message::( - TEST_RELAYER_A, - 1, - message_data(REGULAR_PAYLOAD).into() - )); - assert!(lane.receive_message::( - TEST_RELAYER_B, - 2, - message_data(REGULAR_PAYLOAD).into() - )); - assert!(lane.receive_message::( - TEST_RELAYER_A, - 3, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_B, + &TEST_RELAYER_B, + 2, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + 3, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); assert_eq!( lane.storage.data().relayers, vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B), (3, 3, TEST_RELAYER_A)] @@ -362,16 +427,24 @@ mod tests { fn rejects_same_message_from_two_different_relayers() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - assert!(lane.receive_message::( - TEST_RELAYER_A, - 1, - message_data(REGULAR_PAYLOAD).into() - )); - assert!(!lane.receive_message::( - TEST_RELAYER_B, - 1, - message_data(REGULAR_PAYLOAD).into() - )); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::Dispatched(dispatch_result(0)) + ); + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_B, + &TEST_RELAYER_B, + 1, + message_data(REGULAR_PAYLOAD).into() + ), + ReceivalResult::InvalidNonce, + ); }); } @@ -383,4 +456,22 @@ mod tests { assert_eq!(lane.storage.data().last_delivered_nonce(), 1); }); } + + #[test] + fn unspent_weight_is_returned_by_receive_message() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + let mut payload = REGULAR_PAYLOAD; + payload.dispatch_result.unspent_weight = 1; + assert_eq!( + lane.receive_message::( + &TEST_RELAYER_A, + &TEST_RELAYER_A, + 1, + message_data(payload).into() + ), + ReceivalResult::Dispatched(dispatch_result(1)) + ); + }); + } } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index e8a004b19aa49..5b0c609d8512c 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -42,7 +42,7 @@ pub use crate::weights_ext::{ EXPECTED_DEFAULT_MESSAGE_LENGTH, }; -use crate::inbound_lane::{InboundLane, InboundLaneStorage}; +use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult}; use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; use crate::weights::WeightInfo; @@ -55,9 +55,11 @@ use bp_messages::{ use bp_runtime::Size; use codec::{Decode, Encode}; use frame_support::{ - decl_error, decl_event, decl_module, decl_storage, ensure, + decl_error, decl_event, decl_module, decl_storage, + dispatch::DispatchResultWithPostInfo, + ensure, traits::Get, - weights::{DispatchClass, Weight}, + weights::{DispatchClass, Pays, PostDispatchInfo, Weight}, Parameter, StorageMap, }; use frame_system::{ensure_signed, RawOrigin}; @@ -150,7 +152,11 @@ pub trait Config: frame_system::Config { /// Source header chain, as it is represented on target chain. type SourceHeaderChain: SourceHeaderChain; /// Message dispatch. - type MessageDispatch: MessageDispatch; + type MessageDispatch: MessageDispatch< + Self::AccountId, + Self::InboundMessageFee, + DispatchPayload = Self::InboundPayload, + >; } /// Shortcut to messages proof type for Config. @@ -438,13 +444,13 @@ decl_module! { #[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)] pub fn receive_messages_proof( origin, - relayer_id: T::InboundRelayer, + relayer_id_at_bridged_chain: T::InboundRelayer, proof: MessagesProofOf, messages_count: u32, dispatch_weight: Weight, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure_not_halted::()?; - let _ = ensure_signed(origin)?; + let relayer_id_at_this_chain = ensure_signed(origin)?; // reject transactions that are declaring too many messages ensure!( @@ -452,6 +458,23 @@ decl_module! { Error::::TooManyMessagesInTheProof ); + // why do we need to know the weight of this (`receive_messages_proof`) call? Because + // we may want to return some funds for not-dispatching (or partially dispatching) some + // messages to the call origin (relayer). And this is done by returning actual weight + // from the call. But we only know dispatch weight of every messages. So to refund relayer + // because we have not dispatched Message, we need to: + // + // ActualWeight = DeclaredWeight - Message.DispatchWeight + // + // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible + // to get pre-computed value (and it has been already computed by the executive). + let declared_weight = T::WeightInfo::receive_messages_proof_weight( + &proof, + messages_count, + dispatch_weight, + ); + let mut actual_weight = declared_weight; + // verify messages proof && convert proof into messages let messages = verify_and_decode_messages_proof::< T::SourceHeaderChain, @@ -511,20 +534,57 @@ decl_module! { debug_assert_eq!(message.key.lane_id, lane_id); total_messages += 1; - if lane.receive_message::(relayer_id.clone(), message.key.nonce, message.data) { - valid_messages += 1; - } + let dispatch_weight = T::MessageDispatch::dispatch_weight(&message); + let receival_result = lane.receive_message::( + &relayer_id_at_bridged_chain, + &relayer_id_at_this_chain, + message.key.nonce, + message.data, + ); + + // note that we're returning unspent weight to relayer even if message has been + // rejected by the lane. This allows relayers to submit spam transactions with + // e.g. the same set of already delivered messages over and over again, without + // losing funds for messages dispatch. But keep in mind that relayer pays base + // delivery transaction cost anyway. And base cost covers everything except + // dispatch, so we have a balance here. + let (unspent_weight, refund_pay_dispatch_fee) = match receival_result { + ReceivalResult::Dispatched(dispatch_result) => { + valid_messages += 1; + (dispatch_result.unspent_weight, !dispatch_result.dispatch_fee_paid_during_dispatch) + }, + ReceivalResult::InvalidNonce + | ReceivalResult::TooManyUnrewardedRelayers + | ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), + }; + actual_weight = actual_weight + .saturating_sub(sp_std::cmp::min(unspent_weight, dispatch_weight)) + .saturating_sub( + // delivery call weight formula assumes that the fee is paid at + // this (target) chain. If the message is prepaid at the source + // chain, let's refund relayer with this extra cost. + if refund_pay_dispatch_fee { + T::WeightInfo::pay_inbound_dispatch_fee_overhead() + } else { + 0 + } + ); } } log::trace!( target: "runtime::bridge-messages", - "Received messages: total={}, valid={}", + "Received messages: total={}, valid={}. Weight used: {}/{}", total_messages, valid_messages, + actual_weight, + declared_weight, ); - Ok(()) + Ok(PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }) } /// Receive messages delivery proof from bridged chain. @@ -860,10 +920,9 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, - TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestPayload, TestRuntime, - TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, - TEST_RELAYER_B, + message, message_payload, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, + TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestRuntime, TokenConversionRate, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::UnrewardedRelayersState; use frame_support::{assert_noop, assert_ok}; @@ -883,7 +942,7 @@ mod tests { Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, )); // check event with assigned nonce @@ -897,7 +956,10 @@ mod tests { ); // check that fee has been withdrawn from submitter - assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, REGULAR_PAYLOAD.1)); + assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid( + 1, + REGULAR_PAYLOAD.declared_weight + )); } fn receive_messages_delivery_proof() { @@ -1113,7 +1175,7 @@ mod tests { Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, ), Error::::Halted, ); @@ -1129,7 +1191,7 @@ mod tests { TEST_RELAYER_A, Ok(vec![message(2, REGULAR_PAYLOAD)]).into(), 1, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, ), Error::::Halted, ); @@ -1164,7 +1226,7 @@ mod tests { Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, ), Error::::Halted, ); @@ -1181,7 +1243,7 @@ mod tests { TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), 1, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, ),); assert_ok!(Pallet::::receive_messages_delivery_proof( @@ -1214,7 +1276,7 @@ mod tests { Origin::signed(1), TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN, - PAYLOAD_REJECTED_BY_TARGET_CHAIN.1 + PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight ), Error::::MessageRejectedByChainVerifier, ); @@ -1241,7 +1303,7 @@ mod tests { Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.declared_weight ), Error::::FailedToWithdrawMessageFee, ); @@ -1256,7 +1318,7 @@ mod tests { TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), 1, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, )); assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1); @@ -1297,7 +1359,7 @@ mod tests { TEST_RELAYER_A, message_proof, 1, - REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight, )); assert_eq!( @@ -1329,7 +1391,7 @@ mod tests { TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), 1, - REGULAR_PAYLOAD.1 - 1, + REGULAR_PAYLOAD.declared_weight - 1, ), Error::::InvalidMessagesDispatchWeight, ); @@ -1551,7 +1613,7 @@ mod tests { ]) .into(), 3, - REGULAR_PAYLOAD.1 + REGULAR_PAYLOAD.1, + REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight, ),); assert_eq!( @@ -1603,9 +1665,9 @@ mod tests { #[test] fn actual_dispatch_weight_does_not_overlow() { run_test(|| { - let message1 = message(1, TestPayload(0, Weight::MAX / 2)); - let message2 = message(2, TestPayload(0, Weight::MAX / 2)); - let message3 = message(2, TestPayload(0, Weight::MAX / 2)); + let message1 = message(1, message_payload(0, Weight::MAX / 2)); + let message2 = message(2, message_payload(0, Weight::MAX / 2)); + let message3 = message(2, message_payload(0, Weight::MAX / 2)); assert_noop!( Pallet::::receive_messages_proof( @@ -1672,4 +1734,61 @@ mod tests { assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100)); }); } + + #[test] + fn weight_refund_from_receive_messages_proof_works() { + run_test(|| { + fn submit_with_unspent_weight( + nonce: MessageNonce, + unspent_weight: Weight, + is_prepaid: bool, + ) -> (Weight, Weight) { + let mut payload = REGULAR_PAYLOAD; + payload.dispatch_result.unspent_weight = unspent_weight; + payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid; + let proof = Ok(vec![message(nonce, payload)]).into(); + let messages_count = 1; + let pre_dispatch_weight = ::WeightInfo::receive_messages_proof_weight( + &proof, + messages_count, + REGULAR_PAYLOAD.declared_weight, + ); + let post_dispatch_weight = Pallet::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + proof, + messages_count, + REGULAR_PAYLOAD.declared_weight, + ) + .expect("delivery has failed") + .actual_weight + .expect("receive_messages_proof always returns Some"); + + (pre_dispatch_weight, post_dispatch_weight) + } + + // when dispatch is returning `unspent_weight < declared_weight` + let (pre, post) = submit_with_unspent_weight(1, 1, false); + assert_eq!(post, pre - 1); + + // when dispatch is returning `unspent_weight = declared_weight` + let (pre, post) = submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight, false); + assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight); + + // when dispatch is returning `unspent_weight > declared_weight` + let (pre, post) = submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false); + assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight); + + // when there's no unspent weight + let (pre, post) = submit_with_unspent_weight(4, 0, false); + assert_eq!(post, pre); + + // when dispatch is returning `unspent_weight < declared_weight` AND message is prepaid + let (pre, post) = submit_with_unspent_weight(5, 1, true); + assert_eq!( + post, + pre - 1 - ::WeightInfo::pay_inbound_dispatch_fee_overhead() + ); + }); + } } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 460c001842fb0..823ec13dd799a 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -27,7 +27,7 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, Parameter as MessagesParameter, }; -use bp_runtime::Size; +use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; use frame_support::{parameter_types, weights::Weight}; use sp_core::H256; @@ -41,7 +41,17 @@ use std::collections::BTreeMap; pub type AccountId = u64; pub type Balance = u64; #[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)] -pub struct TestPayload(pub u64, pub Weight); +pub struct TestPayload { + /// Field that may be used to identify messages. + pub id: u64, + /// Dispatch weight that is declared by the message sender. + pub declared_weight: Weight, + /// Message dispatch result. + /// + /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, but for test + /// purposes we'll be making it larger than `declared_weight` sometimes. + pub dispatch_result: MessageDispatchResult, +} pub type TestMessageFee = u64; pub type TestRelayer = u64; @@ -189,10 +199,10 @@ pub const TEST_ERROR: &str = "Test error"; pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; /// Regular message payload. -pub const REGULAR_PAYLOAD: TestPayload = TestPayload(0, 50); +pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 50); /// Payload that is rejected by `TestTargetHeaderChain`. -pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = TestPayload(1, 50); +pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = message_payload(1, 50); /// Vec of proved messages, grouped by lane. pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages>)>; @@ -359,17 +369,25 @@ impl SourceHeaderChain for TestSourceHeaderChain { #[derive(Debug)] pub struct TestMessageDispatch; -impl MessageDispatch for TestMessageDispatch { +impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; fn dispatch_weight(message: &DispatchMessage) -> Weight { match message.data.payload.as_ref() { - Ok(payload) => payload.1, + Ok(payload) => payload.declared_weight, Err(_) => 0, } } - fn dispatch(_message: DispatchMessage) {} + fn dispatch( + _relayer_account: &AccountId, + message: DispatchMessage, + ) -> MessageDispatchResult { + match message.data.payload.as_ref() { + Ok(payload) => payload.dispatch_result.clone(), + Err(_) => dispatch_result(0), + } + } } /// Return test lane message with given nonce and payload. @@ -383,6 +401,15 @@ pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message TestPayload { + TestPayload { + id, + declared_weight, + dispatch_result: dispatch_result(0), + } +} + /// Return message data with valid fee for given payload. pub fn message_data(payload: TestPayload) -> MessageData { MessageData { @@ -391,6 +418,14 @@ pub fn message_data(payload: TestPayload) -> MessageData { } } +/// Returns message dispatch result with given unspent weight. +pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult { + MessageDispatchResult { + unspent_weight, + dispatch_fee_paid_during_dispatch: true, + } +} + /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { let mut t = frame_system::GenesisConfig::default() diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index aea0e44239fed..ffe89c58bde59 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-06-15, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -57,6 +57,7 @@ pub trait WeightInfo { fn receive_single_message_proof_with_outbound_lane_state() -> Weight; fn receive_single_message_proof_1_kb() -> Weight; fn receive_single_message_proof_16_kb() -> Weight; + fn receive_single_prepaid_message_proof() -> Weight; fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; @@ -73,105 +74,110 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (140_457_000 as Weight) + (154_371_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (138_097_000 as Weight) + (157_479_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (196_192_000 as Weight) + (186_840_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (6_244_063_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) + (4_377_567_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (135_633_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (205_350_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (229_415_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (337_102_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (147_408_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (218_825_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (160_092_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (230_759_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (452_140_000 as Weight) + (490_522_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn receive_single_prepaid_message_proof() -> Weight { + (136_550_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (123_704_000 as Weight) + (131_397_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (127_844_000 as Weight) + (137_946_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (183_119_000 as Weight) + (194_448_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (162_249_000 as Weight) - .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) + (142_576_000 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((107_235_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add((138_341_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (450_232_000 as Weight) + (472_752_000 as Weight) .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (181_851_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (175_300_000 as Weight) + .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((114_622_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + .saturating_add((142_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (103_133_000 as Weight) - .saturating_add((6_676_000 as Weight).saturating_mul(i as Weight)) + (127_372_000 as Weight) + .saturating_add((7_927_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (100_321_000 as Weight) - .saturating_add((59_736_000 as Weight).saturating_mul(i as Weight)) + (99_781_000 as Weight) + .saturating_add((64_001_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -182,105 +188,110 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (140_457_000 as Weight) + (154_371_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (138_097_000 as Weight) + (157_479_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (196_192_000 as Weight) + (186_840_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (6_244_063_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + (4_377_567_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (135_633_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (205_350_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (229_415_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (337_102_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (147_408_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (218_825_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (160_092_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (230_759_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (452_140_000 as Weight) + (490_522_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn receive_single_prepaid_message_proof() -> Weight { + (136_550_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (123_704_000 as Weight) + (131_397_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (127_844_000 as Weight) + (137_946_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (183_119_000 as Weight) + (194_448_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (162_249_000 as Weight) - .saturating_add((3_000 as Weight).saturating_mul(i as Weight)) + (142_576_000 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((107_235_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add((138_341_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (450_232_000 as Weight) + (472_752_000 as Weight) .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (181_851_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (175_300_000 as Weight) + .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((114_622_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + .saturating_add((142_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (103_133_000 as Weight) - .saturating_add((6_676_000 as Weight).saturating_mul(i as Weight)) + (127_372_000 as Weight) + .saturating_add((7_927_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (100_321_000 as Weight) - .saturating_add((59_736_000 as Weight).saturating_mul(i as Weight)) + (99_781_000 as Weight) + .saturating_add((64_001_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index cb754a1023106..be440174b4b9b 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -34,6 +34,7 @@ pub fn ensure_weights_are_correct( expected_default_message_delivery_tx_weight: Weight, expected_additional_byte_delivery_weight: Weight, expected_messages_delivery_confirmation_tx_weight: Weight, + expected_pay_inbound_dispatch_fee_weight: Weight, ) { // verify `send_message` weight components assert_ne!(W::send_message_overhead(), 0); @@ -88,6 +89,15 @@ pub fn ensure_weights_are_correct( actual_messages_delivery_confirmation_tx_weight, expected_messages_delivery_confirmation_tx_weight, ); + + // verify pay-dispatch-fee overhead for inbound messages + let actual_pay_inbound_dispatch_fee_weight = W::pay_inbound_dispatch_fee_overhead(); + assert!( + actual_pay_inbound_dispatch_fee_weight <= expected_pay_inbound_dispatch_fee_weight, + "Weight {} of pay-dispatch-fee overhead for inbound messages is larger than expected weight {}", + actual_pay_inbound_dispatch_fee_weight, + expected_pay_inbound_dispatch_fee_weight, + ); } /// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain. @@ -304,6 +314,13 @@ pub trait WeightInfoExt: WeightInfo { (Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024); proof_size_in_bytes * byte_weight } + + /// Returns weight of the pay-dispatch-fee operation for inbound messages. + /// + /// This function may return zero if runtime doesn't support pay-dispatch-fee-at-target-chain option. + fn pay_inbound_dispatch_fee_overhead() -> Weight { + Self::receive_single_message_proof().saturating_sub(Self::receive_single_prepaid_message_proof()) + } } impl WeightInfoExt for () { diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 36c179ca5f29b..0efc54e96e6ad 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -80,7 +80,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. /// The message must have dispatch weight set to zero. The result then must be rounded up to account /// possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// Increase of delivery transaction weight on Millau chain with every additional message byte. /// @@ -95,6 +95,13 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +/// Weight of pay-dispatch-fee operation for inbound messages at Millau chain. +/// +/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` +/// call for your chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; + /// The target length of a session (how often authorities change) on Millau measured in of number of /// blocks. /// diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index cc7c8e8c08cc6..8139372959e35 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -71,7 +71,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. /// The message must have dispatch weight set to zero. The result then must be rounded up to account /// possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_000_000_000; +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// Increase of delivery transaction weight on Rialto chain with every additional message byte. /// @@ -86,6 +86,13 @@ pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +/// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. +/// +/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` +/// call for your chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; + /// The target length of a session (how often authorities change) on Rialto measured in of number of /// blocks. /// diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index a7b07abc98361..7a677dba4207c 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -19,7 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_runtime::{ChainId, Size}; +use bp_runtime::{ + messages::{DispatchFeePayment, MessageDispatchResult}, + ChainId, Size, +}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_std::prelude::*; @@ -31,7 +34,7 @@ pub type Weight = u64; pub type SpecVersion = u32; /// A generic trait to dispatch arbitrary messages delivered over the bridge. -pub trait MessageDispatch { +pub trait MessageDispatch { /// A type of the message to be dispatched. type Message: codec::Decode; @@ -52,7 +55,15 @@ pub trait MessageDispatch { /// a sign that some other component has rejected the message even before it has /// reached `dispatch` method (right now this may only be caused if we fail to decode /// the whole message). - fn dispatch(source_chain: ChainId, target_chain: ChainId, id: MessageId, message: Result); + /// + /// Returns unspent dispatch weight. + fn dispatch Result<(), ()>>( + source_chain: ChainId, + target_chain: ChainId, + id: MessageId, + message: Result, + pay_dispatch_fee: P, + ) -> MessageDispatchResult; } /// Origin of a Call when it is dispatched on the target chain. @@ -110,6 +121,8 @@ pub struct MessagePayload, + /// Where message dispatch fee is paid? + pub dispatch_fee_payment: DispatchFeePayment, /// The call itself. pub call: Call, } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 676e919bc6191..2a649f54d7233 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -18,7 +18,7 @@ use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; -use bp_runtime::Size; +use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*}; @@ -84,7 +84,7 @@ pub trait SourceHeaderChain { } /// Called when inbound message is received. -pub trait MessageDispatch { +pub trait MessageDispatch { /// Decoded message payload type. Valid message may contain invalid payload. In this case /// message is delivered, but dispatch fails. Therefore, two separate types of payload /// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch). @@ -100,7 +100,13 @@ pub trait MessageDispatch { /// /// It is up to the implementers of this trait to determine whether the message /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. - fn dispatch(message: DispatchMessage); + /// + /// If your configuration allows paying dispatch fee at the target chain, then + /// it must be paid inside this method to the `relayer_account`. + fn dispatch( + relayer_account: &AccountId, + message: DispatchMessage, + ) -> MessageDispatchResult; } impl Default for ProvedLaneMessages { @@ -149,12 +155,17 @@ impl SourceHeaderChain for ForbidInboundMessages { } } -impl MessageDispatch for ForbidInboundMessages { +impl MessageDispatch for ForbidInboundMessages { type DispatchPayload = (); fn dispatch_weight(_message: &DispatchMessage) -> Weight { Weight::MAX } - fn dispatch(_message: DispatchMessage) {} + fn dispatch(_: &AccountId, _: DispatchMessage) -> MessageDispatchResult { + MessageDispatchResult { + unspent_weight: 0, + dispatch_fee_paid_during_dispatch: false, + } + } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 80f644a588b90..7b17a2947fce9 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -29,6 +29,8 @@ pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; +pub mod messages; + mod chain; mod storage_proof; diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs new file mode 100644 index 0000000000000..e97430c5b05a9 --- /dev/null +++ b/primitives/runtime/src/messages.rs @@ -0,0 +1,50 @@ +// 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 . + +//! Primitives that may be used by different message delivery and dispatch mechanisms. + +use codec::{Decode, Encode}; +use frame_support::{weights::Weight, RuntimeDebug}; + +/// Where message dispatch fee is paid? +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +pub enum DispatchFeePayment { + /// The dispacth fee is paid at the source chain. + AtSourceChain, + /// The dispatch fee is paid at the target chain. + /// + /// The fee will be paid right before the message is dispatched. So in case of any other + /// issues (like invalid call encoding, invalid signature, ...) the dispatch module won't + /// do any direct transfers. Instead, it'll return fee related to this message dispatch to the + /// relayer. + AtTargetChain, +} + +/// Message dispatch result. +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +pub struct MessageDispatchResult { + /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction + /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: + /// + /// 1) if message has been dispatched successfully, but post-dispatch weight is less than + /// the weight, declared by the message sender; + /// 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. + pub dispatch_fee_paid_during_dispatch: bool, +} diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index a29aa8597d63a..b5a38ec3de389 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -72,7 +72,7 @@ mod tests { #[test] fn should_encode_raw_message() { // given - let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c040130000000000000000000000000"; + let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"; let encode_message = EncodeMessage::from_iter(vec!["encode-message", "MillauToRialto", "raw", msg]); // when @@ -101,6 +101,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d3c040130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index f6338dea65da5..7ff96912d478f 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -22,6 +22,7 @@ use crate::cli::{ TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::messages::DispatchFeePayment; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; use relay_substrate_client::{Chain, TransactionSignScheme}; @@ -211,6 +212,7 @@ where spec_version, weight, origin, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: HexBytes::encode(call), }; @@ -222,12 +224,14 @@ where spec_version, weight, origin, + dispatch_fee_payment, call, } = payload; MessagePayload { spec_version, weight, origin, + dispatch_fee_payment, call: call.0, } } @@ -268,6 +272,7 @@ mod tests { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, weight: 1345000, origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: hex!("0401081234").to_vec(), } ); @@ -311,6 +316,7 @@ mod tests { sp_keyring::AccountKeyring::Bob.into(), signature, ), + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: hex!("0701081234").to_vec(), } ); diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 7468c16706b91..5bb64ed077d1c 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -204,7 +204,7 @@ mod tests { // reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (1024, 216_583_333_334), + (814, 216_583_333_334), ); } } From 85c2582dd12d857936f651b5ec23c06b91c63edf Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Jun 2021 09:16:06 +0300 Subject: [PATCH 0491/1210] Use plain source_queue view when selecting nonces for delivery (#1010) * use plain source_queue view when selecting nonces for delivery * Revert "use plain source_queue view when selecting nonces for delivery" This reverts commit f1fdc3fa9a0934271b125328e69e4f16014780d1. * Revert "Revert "use plain source_queue view when selecting nonces for delivery"" This reverts commit ccefa5ece24c675649251ebc5c686ef972eed2f4. * clippy * fmt --- relays/messages/src/message_race_delivery.rs | 102 ++++++++--- relays/messages/src/message_race_strategy.rs | 174 +++++++++---------- 2 files changed, 154 insertions(+), 122 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 8e88b3763cd87..c4a5b235a5fb4 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -23,7 +23,7 @@ use crate::message_race_loop::{ MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient, TargetClientNonces, }; -use crate::message_race_strategy::BasicStrategy; +use crate::message_race_strategy::{BasicStrategy, SourceRangesQueue}; use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; @@ -31,7 +31,12 @@ use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; use futures::stream::FusedStream; use num_traits::{SaturatingAdd, Zero}; use relay_utils::FailedClient; -use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; +use std::{ + collections::VecDeque, + marker::PhantomData, + ops::{Range, RangeInclusive}, + time::Duration, +}; /// Run message delivery race. pub async fn run( @@ -499,22 +504,25 @@ where let lane_source_client = self.lane_source_client.clone(); let lane_target_client = self.lane_target_client.clone(); + let maximal_source_queue_index = self.strategy.maximal_available_source_queue_index(race_state)?; let previous_total_dispatch_weight = self.total_queued_dispatch_weight(); - let selected_nonces = self - .strategy - .select_nonces_to_deliver_with_selector(race_state.clone(), |range| async { - select_nonces_for_delivery_transaction( - relayer_mode, - max_nonces, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - lane_source_client.clone(), - lane_target_client.clone(), - range, - ) - .await - }) - .await?; + let source_queue = self.strategy.source_queue(); + let range_end = select_nonces_for_delivery_transaction( + relayer_mode, + max_nonces, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + lane_source_client.clone(), + lane_target_client.clone(), + source_queue, + 0..maximal_source_queue_index + 1, + ) + .await?; + + let range_begin = source_queue[0].1.begin(); + let selected_nonces = range_begin..=range_end; + self.strategy.remove_le_nonces_from_source_queue(range_end); + let new_total_dispatch_weight = self.total_queued_dispatch_weight(); let dispatch_weight = previous_total_dispatch_weight - new_total_dispatch_weight; @@ -533,6 +541,7 @@ where /// /// The function returns nonces that are NOT selected for current batch and will be /// delivered later. +#[allow(clippy::too_many_arguments)] async fn select_nonces_for_delivery_transaction( relayer_mode: RelayerMode, max_messages_in_this_batch: MessageNonce, @@ -540,8 +549,13 @@ async fn select_nonces_for_delivery_transaction( max_messages_size_in_single_batch: u32, lane_source_client: impl MessageLaneSourceClient

, lane_target_client: impl MessageLaneTargetClient

, - ready_nonces: MessageDetailsMap, -) -> Option> { + nonces_queue: &SourceRangesQueue< + P::SourceHeaderHash, + P::SourceHeaderNumber, + MessageDetailsMap, + >, + nonces_queue_range: Range, +) -> Option { let mut hard_selected_count = 0; let mut soft_selected_count = 0; @@ -563,7 +577,11 @@ async fn select_nonces_for_delivery_transaction( Zero::zero() }; - for (index, (nonce, details)) in ready_nonces.iter().enumerate() { + let all_ready_nonces = nonces_queue + .range(nonces_queue_range.clone()) + .flat_map(|(_, ready_nonces)| ready_nonces.iter()) + .enumerate(); + for (index, (nonce, details)) in all_ready_nonces { // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` // and `max_messages_size_in_single_batch`, we may still try to submit transaction // with single message if message overflows these limits. The worst case would be if @@ -671,23 +689,27 @@ async fn select_nonces_for_delivery_transaction( selected_count = new_selected_count; } + let hard_selected_begin_nonce = nonces_queue[nonces_queue_range.start].1.begin(); if hard_selected_count != soft_selected_count { + let hard_selected_end_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; + let soft_selected_begin_nonce = hard_selected_begin_nonce; + let soft_selected_end_nonce = soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; log::warn!( target: "bridge", "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy ({:?}) it has selected \ nonces [{:?}; {:?}].", - ready_nonces.keys().next(), - ready_nonces.keys().next().map(|begin| begin + (hard_selected_count as MessageNonce) - 1), + hard_selected_begin_nonce, + hard_selected_end_nonce, relayer_mode, - ready_nonces.keys().next(), - ready_nonces.keys().next().map(|begin| begin + (soft_selected_count as MessageNonce) - 1), - + soft_selected_begin_nonce, + soft_selected_end_nonce, ); hard_selected_count = soft_selected_count; } - if hard_selected_count != ready_nonces.len() { - Some(ready_nonces.into_iter().skip(hard_selected_count).collect()) + + if hard_selected_count != 0 { + Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1) } else { None } @@ -1127,4 +1149,30 @@ mod tests { Some(((20..=23), proof_parameters(false, 4))) ); } + + #[async_std::test] + async fn relayer_uses_flattened_view_of_the_source_queue_to_select_nonces() { + // Real scenario that has happened on test deployments: + // 1) relayer witnessed M1 at block 1 => it has separate entry in the `source_queue` + // 2) relayer witnessed M2 at block 2 => it has separate entry in the `source_queue` + // 3) if block 2 is known to the target node, then both M1 and M2 are selected for single delivery, + // even though weight(M1+M2) > larger than largest allowed weight + // + // This was happening because selector (`select_nonces_for_delivery_transaction`) has been called + // for every `source_queue` entry separately without preserving any context. + let (mut state, mut strategy) = prepare_strategy(); + let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD - DELIVERY_TRANSACTION_COST); + strategy.strategy.source_nonces_updated(header_id(2), nonces); + strategy.max_unrewarded_relayer_entries_at_target = 100; + strategy.max_unconfirmed_nonces_at_target = 100; + strategy.max_messages_in_single_batch = 5; + strategy.max_messages_weight_in_single_batch = 100; + strategy.max_messages_size_in_single_batch = 100; + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + + assert_eq!( + strategy.select_nonces_to_deliver(state).await, + Some(((20..=24), proof_parameters(false, 5))) + ); + } } diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index c17845d97f722..ed4a276e1429d 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -22,7 +22,11 @@ use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClien use async_trait::async_trait; use bp_messages::MessageNonce; use relay_utils::HeaderId; -use std::{collections::VecDeque, fmt::Debug, future::Future, marker::PhantomData, ops::RangeInclusive}; +use std::{collections::VecDeque, fmt::Debug, marker::PhantomData, ops::RangeInclusive}; + +/// Queue of nonces known to the source node. +pub type SourceRangesQueue = + VecDeque<(HeaderId, SourceNoncesRange)>; /// Nonces delivery strategy. #[derive(Debug)] @@ -35,7 +39,7 @@ pub struct BasicStrategy< Proof, > { /// All queued nonces. - source_queue: VecDeque<(HeaderId, SourceNoncesRange)>, + source_queue: SourceRangesQueue, /// Best nonce known to target node (at its best block). `None` if it has not been received yet. best_target_nonce: Option, /// Unused generic types dump. @@ -73,25 +77,21 @@ where &mut self.source_queue } - /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated - /// data) from source to target node. + /// Returns index of the latest source queue entry, that may be delivered to the target node. /// - /// The `selector` function receives range of nonces and should return `None` if the whole - /// range needs to be delivered. If there are some nonces in the range that can't be delivered - /// right now, it should return `Some` with 'undeliverable' nonces. Please keep in mind that - /// this should be the sub-range that the passed range ends with, because nonces are always - /// delivered in-order. Otherwise the function will panic. - pub async fn select_nonces_to_deliver_with_selector>>( - &mut self, + /// Returns `None` if no entries may be delivered. All entries before and including the `Some(_)` + /// index are guaranteed to be witnessed at source blocks that are known to be finalized at the + /// target node. + pub fn maximal_available_source_queue_index( + &self, race_state: RaceState< HeaderId, HeaderId, Proof, >, - selector: impl Fn(SourceNoncesRange) -> F, - ) -> Option> { + ) -> Option { // if we do not know best nonce at target node, we can't select anything - let target_nonce = self.best_target_nonce?; + let _ = self.best_target_nonce?; // if we have already selected nonces that we want to submit, do nothing if race_state.nonces_to_submit.is_some() { @@ -107,47 +107,26 @@ where // 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized // by target client // 3) selector is used for more complicated logic - let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target.clone()?; - let mut nonces_end = None; + // + // => let's first select range of entries inside deque that are already finalized at + // the target client and pass this range to the selector + let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target?; + self.source_queue + .iter() + .enumerate() + .take_while(|(_, (queued_at, _))| queued_at.0 <= best_header_at_target.0) + .map(|(index, _)| index) + .last() + } + + /// Remove all nonces that are less than or equal to given nonce from the source queue. + pub fn remove_le_nonces_from_source_queue(&mut self, nonce: MessageNonce) { while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { - // select (sub) range to deliver - let queued_range_begin = queued_range.begin(); - let queued_range_end = queued_range.end(); - let range_to_requeue = if queued_at.0 > best_header_at_target.0 { - // if header that has queued the range is not yet finalized at bridged chain, - // we can't prove anything - Some(queued_range) - } else { - // selector returns `Some(range)` if this `range` needs to be requeued - selector(queued_range).await - }; - - // requeue (sub) range and update range to deliver - match range_to_requeue { - Some(range_to_requeue) => { - assert!( - range_to_requeue.begin() <= range_to_requeue.end() - && range_to_requeue.begin() >= queued_range_begin - && range_to_requeue.end() == queued_range_end, - "Incorrect implementation of internal `selector` function. Expected original\ - range {:?} to end with returned range {:?}", - queued_range_begin..=queued_range_end, - range_to_requeue, - ); - - if range_to_requeue.begin() != queued_range_begin { - nonces_end = Some(range_to_requeue.begin() - 1); - } - self.source_queue.push_front((queued_at, range_to_requeue)); - break; - } - None => { - nonces_end = Some(queued_range_end); - } + if let Some(range_to_requeue) = queued_range.greater_than(nonce) { + self.source_queue.push_front((queued_at, range_to_requeue)); + break; } } - - nonces_end.map(|nonces_end| RangeInclusive::new(target_nonce + 1, nonces_end)) } } @@ -288,9 +267,11 @@ where Proof, >, ) -> Option<(RangeInclusive, Self::ProofParameters)> { - self.select_nonces_to_deliver_with_selector(race_state, |_| async { None }) - .await - .map(|range| (range, ())) + let maximal_source_queue_index = self.maximal_available_source_queue_index(race_state)?; + let range_begin = self.source_queue[0].1.begin(); + let range_end = self.source_queue[maximal_source_queue_index].1.end(); + self.remove_le_nonces_from_source_queue(range_end); + Some((range_begin..=range_end, ())) } } @@ -298,7 +279,9 @@ where mod tests { use super::*; use crate::message_lane::MessageLane; - use crate::message_lane_loop::tests::{header_id, TestMessageLane, TestMessagesProof}; + use crate::message_lane_loop::tests::{ + header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, TestSourceHeaderNumber, + }; type SourceNoncesRange = RangeInclusive; @@ -454,57 +437,58 @@ mod tests { } #[test] - fn select_nonces_to_deliver_able_to_split_ranges_with_selector() { + fn maximal_available_source_queue_index_works() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); strategy.best_target_nonces_updated(target_nonces(0), &mut state); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=3)); + strategy.source_nonces_updated(header_id(2), source_nonces(4..=6)); + strategy.source_nonces_updated(header_id(3), source_nonces(7..=9)); + + state.best_finalized_source_header_id_at_best_target = Some(header_id(0)); + assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), None); - state.best_finalized_source_header_id_at_source = Some(header_id(1)); state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); - state.best_target_header_id = Some(header_id(1)); + assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(0)); - assert_eq!( - async_std::task::block_on( - strategy.select_nonces_to_deliver_with_selector(state, |_| async { Some(50..=100) }) - ), - Some(1..=49), - ); + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(1)); + + state.best_finalized_source_header_id_at_best_target = Some(header_id(3)); + assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(2)); + + state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); + assert_eq!(strategy.maximal_available_source_queue_index(state), Some(2)); } - fn run_panic_test_for_incorrect_selector( - invalid_selector: impl Fn(SourceNoncesRange) -> Option, - ) { + #[test] + fn remove_le_nonces_from_source_queue_works() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); - strategy.source_nonces_updated(header_id(1), source_nonces(1..=100)); - strategy.best_target_nonces_updated(target_nonces(50), &mut state); - state.best_finalized_source_header_id_at_source = Some(header_id(1)); - state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); - state.best_target_header_id = Some(header_id(1)); - async_std::task::block_on(async move { - strategy - .select_nonces_to_deliver_with_selector(state, |range| async { invalid_selector(range) }) - .await; - }); - } + strategy.best_target_nonces_updated(target_nonces(0), &mut state); + strategy.source_nonces_updated(header_id(1), source_nonces(1..=3)); + strategy.source_nonces_updated(header_id(2), source_nonces(4..=6)); + strategy.source_nonces_updated(header_id(3), source_nonces(7..=9)); + + fn source_queue_nonces( + source_queue: &SourceRangesQueue, + ) -> Vec { + source_queue.iter().flat_map(|(_, range)| range.clone()).collect() + } - #[test] - #[should_panic] - fn select_nonces_to_deliver_panics_if_selector_returns_empty_range() { - #[allow(clippy::reversed_empty_ranges)] - run_panic_test_for_incorrect_selector(|_| Some(2..=1)) - } + strategy.remove_le_nonces_from_source_queue(1); + assert_eq!( + source_queue_nonces(&strategy.source_queue), + vec![2, 3, 4, 5, 6, 7, 8, 9], + ); - #[test] - #[should_panic] - fn select_nonces_to_deliver_panics_if_selector_returns_range_that_starts_before_passed_range() { - run_panic_test_for_incorrect_selector(|range| Some(range.begin() - 1..=*range.end())) - } + strategy.remove_le_nonces_from_source_queue(5); + assert_eq!(source_queue_nonces(&strategy.source_queue), vec![6, 7, 8, 9],); - #[test] - #[should_panic] - fn select_nonces_to_deliver_panics_if_selector_returns_range_with_mismatched_end() { - run_panic_test_for_incorrect_selector(|range| Some(range.begin()..=*range.end() + 1)) + strategy.remove_le_nonces_from_source_queue(9); + assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::::new(),); + + strategy.remove_le_nonces_from_source_queue(100); + assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::::new(),); } } From 9d98e3746784e66397229d523cc5b10cdc747854 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Jun 2021 11:41:22 +0300 Subject: [PATCH 0492/1210] Relay basic single-bit message dispatch results back to the source chain (#935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * relay dispatch result flags back to the source chain * OnMessagesDelivered callback * add lane id to OnDeliveredMessages callback * fix benchmarks && upate weights * clippy * clippy * clipy another try * OnMessagesDelivered -> OnDeliveryConfirmed * Update primitives/messages/src/source_chain.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 2 + bin/millau/runtime/src/rialto_messages.rs | 9 +- bin/rialto/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 9 +- modules/dispatch/src/lib.rs | 45 +++- modules/messages/Cargo.toml | 1 + modules/messages/README.md | 9 +- modules/messages/src/benchmarking.rs | 72 +++++- modules/messages/src/inbound_lane.rs | 86 ++++--- modules/messages/src/lib.rs | 202 +++++++++++++---- modules/messages/src/mock.rs | 68 +++++- modules/messages/src/outbound_lane.rs | 259 +++++++++++++++++++--- modules/messages/src/weights.rs | 102 ++++----- primitives/messages/Cargo.toml | 4 +- primitives/messages/src/lib.rs | 168 +++++++++++--- primitives/messages/src/source_chain.rs | 11 +- primitives/messages/src/target_chain.rs | 1 + primitives/runtime/src/messages.rs | 6 + relays/bin-substrate/src/messages_lane.rs | 2 +- 19 files changed, 863 insertions(+), 197 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index cbbe7c92ee38a..84d62c2e30ffb 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -384,6 +384,7 @@ impl pallet_bridge_messages::Config for Runtime { GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; + type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; @@ -702,6 +703,7 @@ mod tests { let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, ) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index b2754dcbf7b66..644ddc6421753 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -113,9 +113,12 @@ impl messages::ThisChainWithMessages for Millau { } fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = - InboundLaneData::::encoded_size_hint(bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) - .unwrap_or(u32::MAX); + let inbound_data_size = InboundLaneData::::encoded_size_hint( + bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + 1, + 1, + ) + .unwrap_or(u32::MAX); MessageTransaction { dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a2e9578c1d308..46c01baf4f9cf 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -491,6 +491,7 @@ impl pallet_bridge_messages::Config for Runtime { GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; + type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; @@ -1028,7 +1029,7 @@ impl_runtime_apis! { .map(|event_record| event_record.event) .any(|event| matches!( event, - Event::pallet_bridge_dispatch(pallet_bridge_dispatch::Event::::MessageDispatched( + Event::BridgeDispatch(pallet_bridge_dispatch::Event::::MessageDispatched( _, ([0, 0, 0, 0], nonce_from_event), _, )) if nonce_from_event == nonce )) @@ -1144,6 +1145,7 @@ mod tests { let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, + bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, ) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 4945d2a7dfee6..edcef4447fec5 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -113,9 +113,12 @@ impl messages::ThisChainWithMessages for Rialto { } fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = - InboundLaneData::::encoded_size_hint(bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1) - .unwrap_or(u32::MAX); + let inbound_data_size = InboundLaneData::::encoded_size_hint( + bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + 1, + 1, + ) + .unwrap_or(u32::MAX); MessageTransaction { dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index eeb5d5c17d4ef..4f61a3b935fa6 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -154,6 +154,7 @@ impl, I: Instance> MessageDispatch for ); Self::deposit_event(RawEvent::MessageRejected(source_chain, id)); return MessageDispatchResult { + dispatch_result: false, unspent_weight: 0, dispatch_fee_paid_during_dispatch: false, }; @@ -163,6 +164,7 @@ impl, I: Instance> MessageDispatch for // verify spec version // (we want it to be the same, because otherwise we may decode Call improperly) let mut dispatch_result = MessageDispatchResult { + dispatch_result: false, unspent_weight: message.weight, dispatch_fee_paid_during_dispatch: false, }; @@ -303,6 +305,7 @@ impl, I: Instance> MessageDispatch for log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call); let result = call.dispatch(origin); let actual_call_weight = extract_actual_weight(&result, &dispatch_info); + dispatch_result.dispatch_result = result.is_ok(); dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight); log::trace!( @@ -573,6 +576,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert_eq!(result.unspent_weight, weight); + assert!(!result.dispatch_result); assert_eq!( System::events(), @@ -601,6 +605,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert_eq!(result.unspent_weight, 7); + assert!(!result.dispatch_result); assert_eq!( System::events(), @@ -633,6 +638,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert_eq!(result.unspent_weight, weight); + assert!(!result.dispatch_result); assert_eq!( System::events(), @@ -683,6 +689,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert_eq!(result.unspent_weight, weight); + assert!(!result.dispatch_result); assert_eq!( System::events(), @@ -711,6 +718,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert_eq!(result.unspent_weight, weight); + assert!(!result.dispatch_result); assert_eq!( System::events(), @@ -739,12 +747,13 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(())); assert_eq!(result.unspent_weight, weight); + assert!(!result.dispatch_result); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageDispatchPaymentFailed( + event: Event::Dispatch(call_dispatch::Event::::MessageDispatchPaymentFailed( SOURCE_CHAIN_ID, id, AccountIdConverter::convert(derive_account_id::( @@ -771,12 +780,13 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(())); assert!(result.dispatch_fee_paid_during_dispatch); + assert!(result.dispatch_result); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::call_dispatch(call_dispatch::Event::::MessageDispatched( + event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( SOURCE_CHAIN_ID, id, Ok(()) @@ -787,6 +797,34 @@ mod tests { }); } + #[test] + fn should_return_dispatch_failed_flag_if_dispatch_happened_but_failed() { + new_test_ext().execute_with(|| { + let id = [0; 4]; + + let call = Call::System(>::set_heap_pages(1)); + let message = prepare_target_message(call); + + System::set_block_number(1); + let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + assert!(!result.dispatch_fee_paid_during_dispatch); + assert!(!result.dispatch_result); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( + SOURCE_CHAIN_ID, + id, + Err(sp_runtime::DispatchError::BadOrigin) + )), + topics: vec![], + }], + ); + }) + } + #[test] fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { @@ -796,6 +834,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert!(!result.dispatch_fee_paid_during_dispatch); + assert!(result.dispatch_result); assert_eq!( System::events(), @@ -823,6 +862,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert!(!result.dispatch_fee_paid_during_dispatch); + assert!(result.dispatch_result); assert_eq!( System::events(), @@ -850,6 +890,7 @@ mod tests { System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); assert!(!result.dispatch_fee_paid_during_dispatch); + assert!(result.dispatch_result); assert_eq!( System::events(), diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 983a74fe75083..a26cf65c028ba 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bitvec = { version = "0.20", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/messages/README.md b/modules/messages/README.md index 47bcacdee7650..973e251083570 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -101,7 +101,14 @@ the `MessageAccepted` event is emitted in the `send_message()` transaction. The message lane identifier and nonce that has been assigned to the message. When a message is delivered to the target chain, the `MessagesDelivered` event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane -identifier and inclusive range of delivered message nonces. +identifier, inclusive range of delivered message nonces and their single-bit dispatch results. + +Please note that the meaning of the 'dispatch result' is determined by the message dispatcher at +the target chain. For example, in case of immediate call dispatcher it will be the `true` if call +has been successfully dispatched and `false` if it has only been delivered. This simple mechanism +built into the messages module allows building basic bridge applications, which only care whether +their messages have been successfully dispatched or not. More sophisticated applications may use +their own dispatch result delivery mechanism to deliver something larger than single bit. ### How to plug-in Messages Module to Send Messages to the Bridged Chain? diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 5fc04bb2b203b..6af28e8c5c8c8 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -17,17 +17,25 @@ //! Messages pallet benchmarking. use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH; -use crate::{inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, Call, Instance}; +use crate::{ + inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, outbound_lane::ReceivalConfirmationResult, + Call, Instance, +}; use bp_messages::{ - source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, InboundLaneData, LaneId, MessageData, - MessageNonce, OutboundLaneData, UnrewardedRelayersState, + source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, InboundLaneData, LaneId, + MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::messages::DispatchFeePayment; use frame_benchmarking::{account, benchmarks_instance}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; -use sp_std::{collections::btree_map::BTreeMap, convert::TryInto, ops::RangeInclusive, prelude::*}; +use sp_std::{ + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + convert::TryInto, + ops::RangeInclusive, + prelude::*, +}; /// Fee paid by submitter for single message delivery. pub const MESSAGE_FEE: u64 = 10_000_000_000; @@ -471,7 +479,10 @@ benchmarks_instance! { let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { - relayers: vec![(1, 1, relayer_id.clone())].into_iter().collect(), + relayers: vec![UnrewardedRelayer { + relayer: relayer_id.clone(), + messages: DeliveredMessages::new(1, true), + }].into_iter().collect(), last_confirmed_nonce: 0, }, size: ProofSize::Minimal(0), @@ -506,10 +517,15 @@ benchmarks_instance! { messages_in_oldest_entry: 2, total_messages: 2, }; + let mut delivered_messages = DeliveredMessages::new(1, true); + delivered_messages.note_dispatched_message(true); let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { - relayers: vec![(1, 2, relayer_id.clone())].into_iter().collect(), + relayers: vec![UnrewardedRelayer { + relayer: relayer_id.clone(), + messages: delivered_messages, + }].into_iter().collect(), last_confirmed_nonce: 0, }, size: ProofSize::Minimal(0), @@ -547,8 +563,14 @@ benchmarks_instance! { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { relayers: vec![ - (1, 1, relayer1_id.clone()), - (2, 2, relayer2_id.clone()), + UnrewardedRelayer { + relayer: relayer1_id.clone(), + messages: DeliveredMessages::new(1, true), + }, + UnrewardedRelayer { + relayer: relayer2_id.clone(), + messages: DeliveredMessages::new(2, true), + }, ].into_iter().collect(), last_confirmed_nonce: 0, }, @@ -783,10 +805,17 @@ benchmarks_instance! { messages_in_oldest_entry: 1, total_messages: i as MessageNonce, }; + let mut delivered_messages = DeliveredMessages::new(1, true); + for nonce in 2..=i { + delivered_messages.note_dispatched_message(true); + } let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { - relayers: vec![(1, i as MessageNonce, relayer_id.clone())].into_iter().collect(), + relayers: vec![UnrewardedRelayer { + relayer: relayer_id.clone(), + messages: delivered_messages, + }].into_iter().collect(), last_confirmed_nonce: 0, }, size: ProofSize::Minimal(0), @@ -831,7 +860,10 @@ benchmarks_instance! { relayers: relayers .keys() .enumerate() - .map(|(j, relayer_id)| (j as MessageNonce + 1, j as MessageNonce + 1, relayer_id.clone())) + .map(|(j, relayer)| UnrewardedRelayer { + relayer: relayer.clone(), + messages: DeliveredMessages::new(j as MessageNonce + 1, true), + }) .collect(), last_confirmed_nonce: 0, }, @@ -863,13 +895,29 @@ fn send_regular_message_with_payload, I: Instance>(payload: Vec fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - assert!(outbound_lane.confirm_delivery(nonce).is_some()); + let latest_received_nonce = outbound_lane.data().latest_received_nonce; + let mut relayers = VecDeque::with_capacity((nonce - latest_received_nonce) as usize); + for nonce in latest_received_nonce + 1..=nonce { + relayers.push_back(UnrewardedRelayer { + relayer: (), + messages: DeliveredMessages::new(nonce, true), + }); + } + assert!(matches!( + outbound_lane.confirm_delivery(nonce, &relayers), + ReceivalConfirmationResult::ConfirmedMessages(_), + )); } fn receive_messages, I: Instance>(nonce: MessageNonce) { let mut inbound_lane_storage = inbound_lane_storage::(T::bench_lane_id()); inbound_lane_storage.set_data(InboundLaneData { - relayers: vec![(1, nonce, T::bridged_relayer_id())].into_iter().collect(), + relayers: vec![UnrewardedRelayer { + relayer: T::bridged_relayer_id(), + messages: DeliveredMessages::new(nonce, true), + }] + .into_iter() + .collect(), last_confirmed_nonce: 0, }); } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 92eb8d665dfa8..83d17dc3c06c2 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -18,7 +18,7 @@ use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, + DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, UnrewardedRelayer, }; use bp_runtime::messages::MessageDispatchResult; use frame_support::RuntimeDebug; @@ -89,7 +89,7 @@ impl InboundLane { while data .relayers .front() - .map(|(_, nonce_high, _)| *nonce_high <= new_confirmed_nonce) + .map(|entry| entry.messages.end <= new_confirmed_nonce) .unwrap_or(false) { data.relayers.pop_front(); @@ -97,8 +97,12 @@ impl InboundLane { // Secondly, update the next record with lower nonce equal to new confirmed nonce if needed. // Note: There will be max. 1 record to update as we don't allow messages from relayers to overlap. match data.relayers.front_mut() { - Some((nonce_low, _, _)) if *nonce_low < new_confirmed_nonce => { - *nonce_low = new_confirmed_nonce + 1; + Some(entry) if entry.messages.begin < new_confirmed_nonce => { + entry.messages.dispatch_results = entry + .messages + .dispatch_results + .split_off((new_confirmed_nonce + 1 - entry.messages.begin) as _); + entry.messages.begin = new_confirmed_nonce + 1; } _ => {} } @@ -132,30 +136,37 @@ impl InboundLane { return ReceivalResult::TooManyUnconfirmedMessages; } + // dispatch message before updating anything in the storage. If dispatch would panic, + // (which should not happen in the runtime) then we simply won't consider message as + // delivered (no changes to the inbound lane storage have been made). + let dispatch_result = P::dispatch( + relayer_at_this_chain, + DispatchMessage { + key: MessageKey { + lane_id: self.storage.id(), + nonce, + }, + data: message_data, + }, + ); + + // now let's update inbound lane storage let push_new = match data.relayers.back_mut() { - Some((_, nonce_high, last_relayer)) if last_relayer == relayer_at_bridged_chain => { - *nonce_high = nonce; + Some(entry) if entry.relayer == *relayer_at_bridged_chain => { + entry.messages.note_dispatched_message(dispatch_result.dispatch_result); false } _ => true, }; if push_new { - data.relayers - .push_back((nonce, nonce, (*relayer_at_bridged_chain).clone())); + data.relayers.push_back(UnrewardedRelayer { + relayer: (*relayer_at_bridged_chain).clone(), + messages: DeliveredMessages::new(nonce, dispatch_result.dispatch_result), + }); } - self.storage.set_data(data); - ReceivalResult::Dispatched(P::dispatch( - relayer_at_this_chain, - DispatchMessage { - key: MessageKey { - lane_id: self.storage.id(), - nonce, - }, - data: message_data, - }, - )) + ReceivalResult::Dispatched(dispatch_result) } } @@ -165,8 +176,8 @@ mod tests { use crate::{ inbound_lane, mock::{ - dispatch_result, message_data, run_test, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, - TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C, + dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch, TestRuntime, + REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C, }, DefaultInstance, RuntimeInboundLaneStorage, }; @@ -238,7 +249,10 @@ mod tests { receive_regular_message(&mut lane, 2); receive_regular_message(&mut lane, 3); assert_eq!(lane.storage.data().last_confirmed_nonce, 0); - assert_eq!(lane.storage.data().relayers, vec![(1, 3, TEST_RELAYER_A)]); + assert_eq!( + lane.storage.data().relayers, + vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)] + ); assert_eq!( lane.receive_state_update(OutboundLaneData { @@ -248,7 +262,10 @@ mod tests { Some(2), ); assert_eq!(lane.storage.data().last_confirmed_nonce, 2); - assert_eq!(lane.storage.data().relayers, vec![(3, 3, TEST_RELAYER_A)]); + assert_eq!( + lane.storage.data().relayers, + vec![unrewarded_relayer(3, 3, TEST_RELAYER_A)] + ); assert_eq!( lane.receive_state_update(OutboundLaneData { @@ -269,10 +286,16 @@ mod tests { let mut seed_storage_data = lane.storage.data(); // Prepare data seed_storage_data.last_confirmed_nonce = 0; - seed_storage_data.relayers.push_back((1, 1, TEST_RELAYER_A)); + seed_storage_data + .relayers + .push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A)); // Simulate messages batch (2, 3, 4) from relayer #2 - seed_storage_data.relayers.push_back((2, 4, TEST_RELAYER_B)); - seed_storage_data.relayers.push_back((5, 5, TEST_RELAYER_C)); + seed_storage_data + .relayers + .push_back(unrewarded_relayer(2, 4, TEST_RELAYER_B)); + seed_storage_data + .relayers + .push_back(unrewarded_relayer(5, 5, TEST_RELAYER_C)); lane.storage.set_data(seed_storage_data); // Check assert_eq!( @@ -285,7 +308,10 @@ mod tests { assert_eq!(lane.storage.data().last_confirmed_nonce, 3); assert_eq!( lane.storage.data().relayers, - vec![(4, 4, TEST_RELAYER_B), (5, 5, TEST_RELAYER_C)] + vec![ + unrewarded_relayer(4, 4, TEST_RELAYER_B), + unrewarded_relayer(5, 5, TEST_RELAYER_C) + ] ); }); } @@ -418,7 +444,11 @@ mod tests { ); assert_eq!( lane.storage.data().relayers, - vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B), (3, 3, TEST_RELAYER_A)] + vec![ + unrewarded_relayer(1, 1, TEST_RELAYER_A), + unrewarded_relayer(2, 2, TEST_RELAYER_B), + unrewarded_relayer(3, 3, TEST_RELAYER_A) + ] ); }); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 5b0c609d8512c..054c0e2a02d4f 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -43,21 +43,23 @@ pub use crate::weights_ext::{ }; use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult}; -use crate::outbound_lane::{OutboundLane, OutboundLaneStorage}; +use crate::outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult}; use crate::weights::WeightInfo; use bp_messages::{ - source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain}, + source_chain::{ + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, TargetHeaderChain, + }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OperatingMode, - OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, + total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, + OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, }; use bp_runtime::Size; use codec::{Decode, Encode}; use frame_support::{ decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResultWithPostInfo, - ensure, + ensure, fail, traits::Get, weights::{DispatchClass, Pays, PostDispatchInfo, Weight}, Parameter, StorageMap, @@ -146,6 +148,8 @@ pub trait Config: frame_system::Config { type LaneMessageVerifier: LaneMessageVerifier; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment; + /// Handler for delivered messages. + type OnDeliveryConfirmed: OnDeliveryConfirmed; // Types that are used by inbound_lane (on target chain). @@ -186,6 +190,8 @@ decl_error! { InvalidMessagesDispatchWeight, /// Invalid messages delivery proof has been submitted. InvalidMessagesDeliveryProof, + /// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane). + InvalidUnrewardedRelayers, /// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call. InvalidUnrewardedRelayersState, /// The message someone is trying to work with (i.e. increase fee) is already-delivered. @@ -236,8 +242,8 @@ decl_event!( ParameterUpdated(Parameter), /// Message has been accepted and is waiting to be delivered. MessageAccepted(LaneId, MessageNonce), - /// Messages in the inclusive range have been delivered and processed by the bridged chain. - MessagesDelivered(LaneId, MessageNonce, MessageNonce), + /// Messages in the inclusive range have been delivered to the bridged chain. + MessagesDelivered(LaneId, DeliveredMessages), /// Phantom member, never used. Dummy(PhantomData<(AccountId, I)>), } @@ -620,19 +626,36 @@ decl_module! { let mut lane = outbound_lane::(lane_id); let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); - let received_range = lane.confirm_delivery(last_delivered_nonce); - if let Some(received_range) = received_range { - Self::deposit_event(RawEvent::MessagesDelivered(lane_id, received_range.0, received_range.1)); + let confirmed_messages = match lane.confirm_delivery(last_delivered_nonce, &lane_data.relayers) { + ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages), + ReceivalConfirmationResult::NoNewConfirmations => None, + error => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", + error, + ); + + fail!(Error::::InvalidUnrewardedRelayers); + }, + }; + if let Some(confirmed_messages) = confirmed_messages { + // handle messages delivery confirmation + T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); + + // emit 'delivered' event + let received_range = confirmed_messages.begin..=confirmed_messages.end; + Self::deposit_event(RawEvent::MessagesDelivered(lane_id, confirmed_messages)); // remember to reward relayers that have delivered messages // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - for (nonce_low, nonce_high, relayer) in lane_data.relayers { - let nonce_begin = sp_std::cmp::max(nonce_low, received_range.0); - let nonce_end = sp_std::cmp::min(nonce_high, received_range.1); + for entry in lane_data.relayers { + let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); + let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); // loop won't proceed if current entry is ahead of received range (begin > end). // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain - let mut relayer_reward = relayers_rewards.entry(relayer).or_default(); + let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); for nonce in nonce_begin..nonce_end + 1 { let message_data = OutboundMessages::::get(MessageKey { lane_id, @@ -697,7 +720,10 @@ impl, I: Instance> Pallet { let relayers = InboundLanes::::get(&lane).relayers; bp_messages::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers.front().map(|(begin, end, _)| 1 + end - begin).unwrap_or(0), + messages_in_oldest_entry: relayers + .front() + .map(|entry| 1 + entry.messages.end - entry.messages.begin) + .unwrap_or(0), total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), } } @@ -920,11 +946,12 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, message_payload, run_test, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, - TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestRuntime, TokenConversionRate, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin, + TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, + TestRuntime, TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, + TEST_RELAYER_A, TEST_RELAYER_B, }; - use bp_messages::UnrewardedRelayersState; + use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use frame_support::{assert_noop, assert_ok}; use frame_system::{EventRecord, Pallet as System, Phase}; use hex_literal::hex; @@ -938,6 +965,10 @@ mod tests { fn send_regular_message() { get_ready_for_events(); + let message_nonce = outbound_lane::(TEST_LANE_ID) + .data() + .latest_generated_nonce + + 1; assert_ok!(Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, @@ -950,7 +981,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)), + event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, message_nonce)), topics: vec![], }], ); @@ -972,17 +1003,29 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, - ..Default::default() + relayers: vec![UnrewardedRelayer { + relayer: 0, + messages: DeliveredMessages::new(1, true), + }] + .into_iter() + .collect(), }, ))), - Default::default(), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, )); assert_eq!( System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(RawEvent::MessagesDelivered(TEST_LANE_ID, 1, 1)), + event: TestEvent::Messages(RawEvent::MessagesDelivered( + TEST_LANE_ID, + DeliveredMessages::new(1, true), + )), topics: vec![], }], ); @@ -1333,9 +1376,12 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 8, - relayers: vec![(9, 9, TEST_RELAYER_A), (10, 10, TEST_RELAYER_B)] - .into_iter() - .collect(), + relayers: vec![ + unrewarded_relayer(9, 9, TEST_RELAYER_A), + unrewarded_relayer(10, 10, TEST_RELAYER_B), + ] + .into_iter() + .collect(), }, ); assert_eq!( @@ -1366,9 +1412,12 @@ mod tests { InboundLanes::::get(TEST_LANE_ID), InboundLaneData { last_confirmed_nonce: 9, - relayers: vec![(10, 10, TEST_RELAYER_B), (11, 11, TEST_RELAYER_A)] - .into_iter() - .collect(), + relayers: vec![ + unrewarded_relayer(10, 10, TEST_RELAYER_B), + unrewarded_relayer(11, 11, TEST_RELAYER_A) + ] + .into_iter() + .collect(), }, ); assert_eq!( @@ -1465,7 +1514,7 @@ mod tests { TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { - relayers: vec![(1, 1, TEST_RELAYER_A)].into_iter().collect(), + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), ..Default::default() } ))), @@ -1490,9 +1539,12 @@ mod tests { TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { - relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] - .into_iter() - .collect(), + relayers: vec![ + unrewarded_relayer(1, 1, TEST_RELAYER_A), + unrewarded_relayer(2, 2, TEST_RELAYER_B) + ] + .into_iter() + .collect(), ..Default::default() } ))), @@ -1537,9 +1589,12 @@ mod tests { TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { - relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] - .into_iter() - .collect(), + relayers: vec![ + unrewarded_relayer(1, 1, TEST_RELAYER_A), + unrewarded_relayer(2, 2, TEST_RELAYER_B) + ] + .into_iter() + .collect(), ..Default::default() } ))), @@ -1559,9 +1614,12 @@ mod tests { TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { - relayers: vec![(1, 1, TEST_RELAYER_A), (2, 2, TEST_RELAYER_B)] - .into_iter() - .collect(), + relayers: vec![ + unrewarded_relayer(1, 1, TEST_RELAYER_A), + unrewarded_relayer(2, 2, TEST_RELAYER_B) + ] + .into_iter() + .collect(), ..Default::default() } ))), @@ -1791,4 +1849,70 @@ mod tests { ); }); } + + #[test] + fn messages_delivered_callbacks_are_called() { + run_test(|| { + send_regular_message(); + send_regular_message(); + send_regular_message(); + + // messages 1+2 are confirmed in 1 tx, message 3 in a separate tx + // dispatch of message 2 has failed + let mut delivered_messages_1_and_2 = DeliveredMessages::new(1, true); + delivered_messages_1_and_2.note_dispatched_message(false); + let messages_1_and_2_proof = Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 0, + relayers: vec![UnrewardedRelayer { + relayer: 0, + messages: delivered_messages_1_and_2.clone(), + }] + .into_iter() + .collect(), + }, + )); + let delivered_message_3 = DeliveredMessages::new(3, true); + let messages_3_proof = Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 0, + relayers: vec![UnrewardedRelayer { + relayer: 0, + messages: delivered_message_3.clone(), + }] + .into_iter() + .collect(), + }, + )); + + // first tx with messages 1+2 + assert_ok!(Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(messages_1_and_2_proof), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 2, + ..Default::default() + }, + )); + // second tx with message 3 + assert_ok!(Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(messages_3_proof), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + )); + + // ensure that both callbacks have been called twice: for 1+2, then for 3 + crate::mock::TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); + crate::mock::TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_message_3); + crate::mock::TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); + crate::mock::TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_message_3); + }); + } } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 823ec13dd799a..2e184dda15857 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -19,13 +19,15 @@ use crate::Config; +use bitvec::prelude::*; use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, Sender, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, Sender, + TargetHeaderChain, }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, - Parameter as MessagesParameter, + DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, + Parameter as MessagesParameter, UnrewardedRelayer, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -169,6 +171,7 @@ impl Config for TestRuntime { type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; + type OnDeliveryConfirmed = (TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2); type SourceHeaderChain = TestSourceHeaderChain; type MessageDispatch = TestMessageDispatch; @@ -345,6 +348,44 @@ impl MessageDeliveryAndDispatchPayment for TestMessag } } +/// First on-messages-delivered callback. +#[derive(Debug)] +pub struct TestOnDeliveryConfirmed1; + +impl TestOnDeliveryConfirmed1 { + /// Verify that the callback has been called with given delivered messages. + pub fn ensure_called(lane: &LaneId, messages: &DeliveredMessages) { + let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode(); + assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); + } +} + +impl OnDeliveryConfirmed for TestOnDeliveryConfirmed1 { + fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) { + let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode(); + frame_support::storage::unhashed::put(&key, &true); + } +} + +/// Seconde on-messages-delivered callback. +#[derive(Debug)] +pub struct TestOnDeliveryConfirmed2; + +impl TestOnDeliveryConfirmed2 { + /// Verify that the callback has been called with given delivered messages. + pub fn ensure_called(lane: &LaneId, messages: &DeliveredMessages) { + let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode(); + assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); + } +} + +impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 { + fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) { + let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode(); + frame_support::storage::unhashed::put(&key, &true); + } +} + /// Source header chain that is used in tests. #[derive(Debug)] pub struct TestSourceHeaderChain; @@ -421,11 +462,32 @@ pub fn message_data(payload: TestPayload) -> MessageData { /// Returns message dispatch result with given unspent weight. pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult { MessageDispatchResult { + dispatch_result: true, unspent_weight, dispatch_fee_paid_during_dispatch: true, } } +/// Constructs unrewarded relayer entry from nonces range and relayer id. +pub fn unrewarded_relayer( + begin: MessageNonce, + end: MessageNonce, + relayer: TestRelayer, +) -> UnrewardedRelayer { + UnrewardedRelayer { + relayer, + messages: DeliveredMessages { + begin, + end, + dispatch_results: if end >= begin { + bitvec![Msb0, u8; 1; (end - begin + 1) as _] + } else { + Default::default() + }, + }, + } +} + /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { let mut t = frame_system::GenesisConfig::default() diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 47616c33eac83..44061d984e1d0 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -16,7 +16,12 @@ //! Everything about outgoing messages sending. -use bp_messages::{LaneId, MessageData, MessageNonce, OutboundLaneData}; +use bitvec::prelude::*; +use bp_messages::{ + DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, +}; +use frame_support::RuntimeDebug; +use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. pub trait OutboundLaneStorage { @@ -38,6 +43,28 @@ pub trait OutboundLaneStorage { fn remove_message(&mut self, nonce: &MessageNonce); } +/// Result of messages receival confirmation. +#[derive(RuntimeDebug, PartialEq, Eq)] +pub enum ReceivalConfirmationResult { + /// New messages have been confirmed by the confirmation transaction. + ConfirmedMessages(DeliveredMessages), + /// Confirmation transaction brings no new confirmation. This may be a result of relayer + /// error or several relayers runnng. + NoNewConfirmations, + /// Bridged chain is trying to confirm more messages than we have generated. May be a result + /// of invalid bridged chain storage. + FailedToConfirmFutureMessages, + /// The unrewarded relayers vec contains an empty entry. May be a result of invalid bridged + /// chain storage. + EmptyUnrewardedRelayerEntry, + /// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid bridged + /// chain storage. + NonConsecutiveUnrewardedRelayerEntries, + /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May be + /// a result of invalid bridged chain storage. + InvalidNumberOfDispatchResults, +} + /// Outbound messages lane. pub struct OutboundLane { storage: S, @@ -69,20 +96,34 @@ impl OutboundLane { } /// Confirm messages delivery. - /// - /// Returns `None` if confirmation is wrong/duplicate. - /// Returns `Some` with inclusive ranges of message nonces that have been received. - pub fn confirm_delivery(&mut self, latest_received_nonce: MessageNonce) -> Option<(MessageNonce, MessageNonce)> { + pub fn confirm_delivery( + &mut self, + latest_received_nonce: MessageNonce, + relayers: &VecDeque>, + ) -> ReceivalConfirmationResult { let mut data = self.storage.data(); - if latest_received_nonce <= data.latest_received_nonce || latest_received_nonce > data.latest_generated_nonce { - return None; + if latest_received_nonce <= data.latest_received_nonce { + return ReceivalConfirmationResult::NoNewConfirmations; + } + if latest_received_nonce > data.latest_generated_nonce { + return ReceivalConfirmationResult::FailedToConfirmFutureMessages; } + let dispatch_results = + match extract_dispatch_results(data.latest_received_nonce, latest_received_nonce, relayers) { + Ok(dispatch_results) => dispatch_results, + Err(extract_error) => return extract_error, + }; + let prev_latest_received_nonce = data.latest_received_nonce; data.latest_received_nonce = latest_received_nonce; self.storage.set_data(data); - Some((prev_latest_received_nonce + 1, latest_received_nonce)) + ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages { + begin: prev_latest_received_nonce + 1, + end: latest_received_nonce, + dispatch_results, + }) } /// Prune at most `max_messages_to_prune` already received messages. @@ -108,13 +149,108 @@ impl OutboundLane { } } +/// Extract new dispatch results from the unrewarded relayers vec. +/// +/// Returns `Err(_)` if unrewarded relayers vec contains invalid data, meaning that the bridged +/// chain has invalid runtime storage. +fn extract_dispatch_results( + prev_latest_received_nonce: MessageNonce, + latest_received_nonce: MessageNonce, + relayers: &VecDeque>, +) -> Result { + // the only caller of this functions checks that the prev_latest_received_nonce..=latest_received_nonce + // is valid, so we're ready to accept messages in this range + // => with_capacity call must succeed here or we'll be unable to receive confirmations at all + let mut received_dispatch_result = + BitVec::with_capacity((latest_received_nonce - prev_latest_received_nonce + 1) as _); + let mut last_entry_end: Option = None; + for entry in relayers { + // unrewarded relayer entry must have at least 1 unconfirmed message + // (guaranteed by the `InboundLane::receive_message()`) + if entry.messages.end < entry.messages.begin { + return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry); + } + // every entry must confirm range of messages that follows previous entry range + // (guaranteed by the `InboundLane::receive_message()`) + if let Some(last_entry_end) = last_entry_end { + let expected_entry_begin = last_entry_end.checked_add(1); + if expected_entry_begin != Some(entry.messages.begin) { + return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries); + } + } + last_entry_end = Some(entry.messages.end); + // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` + // (guaranteed by the `InboundLane::receive_message()`) + if entry.messages.end > latest_received_nonce { + // technically this will be detected in the next loop iteration as `InvalidNumberOfDispatchResults` + // but to guarantee safety of loop operations below this is detected now + return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages); + } + // entry must have single dispatch result for every message + // (guaranteed by the `InboundLane::receive_message()`) + if entry.messages.dispatch_results.len() as MessageNonce != entry.messages.end - entry.messages.begin + 1 { + return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults); + } + + // now we know that the entry is valid + // => let's check if it brings new confirmations + let new_messages_begin = sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1); + let new_messages_end = sp_std::cmp::min(entry.messages.end, latest_received_nonce); + let new_messages_range = new_messages_begin..=new_messages_end; + if new_messages_range.is_empty() { + continue; + } + + // now we know that entry brings new confirmations + // => let's extract dispatch results + received_dispatch_result.extend_from_bitslice( + &entry.messages.dispatch_results[(new_messages_begin - entry.messages.begin) as usize..], + ); + } + + Ok(received_dispatch_result) +} + #[cfg(test)] mod tests { use super::*; use crate::{ - mock::{message_data, run_test, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, + mock::{message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, outbound_lane, }; + use sp_std::ops::RangeInclusive; + + fn unrewarded_relayers(nonces: RangeInclusive) -> VecDeque> { + vec![unrewarded_relayer(*nonces.start(), *nonces.end(), 0)] + .into_iter() + .collect() + } + + fn delivered_messages(nonces: RangeInclusive) -> DeliveredMessages { + DeliveredMessages { + begin: *nonces.start(), + end: *nonces.end(), + dispatch_results: bitvec![Msb0, u8; 1; (nonces.end() - nonces.start() + 1) as _], + } + } + + fn assert_3_messages_confirmation_fails( + latest_received_nonce: MessageNonce, + relayers: &VecDeque>, + ) -> ReceivalConfirmationResult { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + let result = lane.confirm_delivery(latest_received_nonce, relayers); + assert_eq!(lane.storage.data().latest_generated_nonce, 3); + assert_eq!(lane.storage.data().latest_received_nonce, 0); + result + }) + } #[test] fn send_message_works() { @@ -136,7 +272,10 @@ mod tests { assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 3); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); - assert_eq!(lane.confirm_delivery(3), Some((1, 3))); + assert_eq!( + lane.confirm_delivery(3, &unrewarded_relayers(1..=3)), + ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), + ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); }); @@ -151,12 +290,21 @@ mod tests { lane.send_message(message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); - assert_eq!(lane.confirm_delivery(3), Some((1, 3))); - assert_eq!(lane.confirm_delivery(3), None); + assert_eq!( + lane.confirm_delivery(3, &unrewarded_relayers(1..=3)), + ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), + ); + assert_eq!( + lane.confirm_delivery(3, &unrewarded_relayers(1..=3)), + ReceivalConfirmationResult::NoNewConfirmations, + ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); - assert_eq!(lane.confirm_delivery(2), None); + assert_eq!( + lane.confirm_delivery(2, &unrewarded_relayers(1..=1)), + ReceivalConfirmationResult::NoNewConfirmations, + ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); }); @@ -164,17 +312,70 @@ mod tests { #[test] fn confirm_delivery_rejects_nonce_larger_than_last_generated() { - run_test(|| { - let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_received_nonce, 0); - assert_eq!(lane.confirm_delivery(10), None); - assert_eq!(lane.storage.data().latest_generated_nonce, 3); - assert_eq!(lane.storage.data().latest_received_nonce, 0); - }); + assert_eq!( + assert_3_messages_confirmation_fails(10, &unrewarded_relayers(1..=10),), + ReceivalConfirmationResult::FailedToConfirmFutureMessages, + ); + } + + #[test] + fn confirm_delivery_fails_if_entry_confirms_future_messages() { + assert_eq!( + assert_3_messages_confirmation_fails( + 3, + &unrewarded_relayers(1..=1) + .into_iter() + .chain(unrewarded_relayers(2..=30).into_iter()) + .chain(unrewarded_relayers(3..=3).into_iter()) + .collect(), + ), + ReceivalConfirmationResult::FailedToConfirmFutureMessages, + ); + } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn confirm_delivery_fails_if_entry_is_empty() { + assert_eq!( + assert_3_messages_confirmation_fails( + 3, + &unrewarded_relayers(1..=1) + .into_iter() + .chain(unrewarded_relayers(2..=1).into_iter()) + .chain(unrewarded_relayers(2..=3).into_iter()) + .collect(), + ), + ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry, + ); + } + + #[test] + fn confirm_delivery_fails_if_entries_are_non_consecutive() { + assert_eq!( + assert_3_messages_confirmation_fails( + 3, + &unrewarded_relayers(1..=1) + .into_iter() + .chain(unrewarded_relayers(3..=3).into_iter()) + .chain(unrewarded_relayers(2..=2).into_iter()) + .collect(), + ), + ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries, + ); + } + + #[test] + fn confirm_delivery_fails_if_number_of_dispatch_results_in_entry_is_invalid() { + let mut relayers: VecDeque<_> = unrewarded_relayers(1..=1) + .into_iter() + .chain(unrewarded_relayers(2..=2).into_iter()) + .chain(unrewarded_relayers(3..=3).into_iter()) + .collect(); + relayers[0].messages.dispatch_results.clear(); + assert_eq!( + assert_3_messages_confirmation_fails(3, &relayers), + ReceivalConfirmationResult::InvalidNumberOfDispatchResults, + ); } #[test] @@ -191,11 +392,17 @@ mod tests { assert_eq!(lane.prune_messages(100), 0); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // after confirmation, some messages are received - assert_eq!(lane.confirm_delivery(2), Some((1, 2))); + assert_eq!( + lane.confirm_delivery(2, &unrewarded_relayers(1..=2)), + ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)), + ); assert_eq!(lane.prune_messages(100), 2); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3); // after last message is confirmed, everything is pruned - assert_eq!(lane.confirm_delivery(3), Some((3, 3))); + assert_eq!( + lane.confirm_delivery(3, &unrewarded_relayers(3..=3)), + ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)), + ); assert_eq!(lane.prune_messages(100), 1); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4); }); diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index ffe89c58bde59..9b65c8217ad64 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-15, STEPS: [50, ], REPEAT: 20 +//! DATE: 2021-06-18, STEPS: [50, ], REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -74,110 +74,110 @@ pub trait WeightInfo { pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { - (154_371_000 as Weight) + (159_305_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (157_479_000 as Weight) + (164_394_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (186_840_000 as Weight) + (223_521_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (4_377_567_000 as Weight) + (6_709_925_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (205_350_000 as Weight) + (206_769_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (337_102_000 as Weight) + (343_982_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (218_825_000 as Weight) + (223_738_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (230_759_000 as Weight) + (235_369_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (490_522_000 as Weight) + (510_338_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (136_550_000 as Weight) + (141_536_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (131_397_000 as Weight) + (128_805_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (137_946_000 as Weight) + (137_143_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (194_448_000 as Weight) + (193_108_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (142_576_000 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) + (133_632_000 as Weight) + .saturating_add((4_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((138_341_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((145_006_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (472_752_000 as Weight) - .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) + (486_301_000 as Weight) + .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (175_300_000 as Weight) - .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + (178_139_000 as Weight) + .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((142_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((150_844_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (127_372_000 as Weight) - .saturating_add((7_927_000 as Weight).saturating_mul(i as Weight)) + (113_140_000 as Weight) + .saturating_add((7_656_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (99_781_000 as Weight) - .saturating_add((64_001_000 as Weight).saturating_mul(i as Weight)) + (97_424_000 as Weight) + .saturating_add((63_128_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -188,110 +188,110 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (154_371_000 as Weight) + (159_305_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (157_479_000 as Weight) + (164_394_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (186_840_000 as Weight) + (223_521_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn increase_message_fee() -> Weight { - (4_377_567_000 as Weight) + (6_709_925_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (205_350_000 as Weight) + (206_769_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (337_102_000 as Weight) + (343_982_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (218_825_000 as Weight) + (223_738_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (230_759_000 as Weight) + (235_369_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (490_522_000 as Weight) + (510_338_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (136_550_000 as Weight) + (141_536_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (131_397_000 as Weight) + (128_805_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (137_946_000 as Weight) + (137_143_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (194_448_000 as Weight) + (193_108_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (142_576_000 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) + (133_632_000 as Weight) + .saturating_add((4_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { (0 as Weight) - .saturating_add((138_341_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((145_006_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (472_752_000 as Weight) - .saturating_add((9_000 as Weight).saturating_mul(i as Weight)) + (486_301_000 as Weight) + .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (175_300_000 as Weight) - .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + (178_139_000 as Weight) + .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { (0 as Weight) - .saturating_add((142_176_000 as Weight).saturating_mul(i as Weight)) + .saturating_add((150_844_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (127_372_000 as Weight) - .saturating_add((7_927_000 as Weight).saturating_mul(i as Weight)) + (113_140_000 as Weight) + .saturating_add((7_656_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (99_781_000 as Weight) - .saturating_add((64_001_000 as Weight).saturating_mul(i as Weight)) + (97_424_000 as Weight) + .saturating_add((63_128_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 9b79a3bdb58ce..b5b68220a4098 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -7,7 +7,9 @@ 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, features = ["derive"] } +bitvec = { version = "0.20", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive", "bit-vec"] } +impl-trait-for-tuples = "0.2" serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 211f4e717511f..e1e7522181b52 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -22,6 +22,7 @@ // Generated by `DecodeLimit::decode_with_depth_limit` #![allow(clippy::unnecessary_mut_passed)] +use bitvec::prelude::*; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; @@ -120,7 +121,7 @@ pub struct InboundLaneData { /// When a relayer sends a single message, both of MessageNonces are the same. /// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce. /// Multiple dispatches from the same relayer are allowed. - pub relayers: VecDeque<(MessageNonce, MessageNonce, RelayerId)>, + pub relayers: VecDeque>, /// Nonce of the last message that /// a) has been delivered to the target (this) chain and @@ -147,18 +148,22 @@ impl InboundLaneData { /// size of each entry. /// /// Returns `None` if size overflows `u32` limits. - pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32) -> Option { + pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32, messages_count: u32) -> Option { let message_nonce_size = 8; let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; - relayers_size.checked_add(message_nonce_size) + let dispatch_results_per_byte = 8; + let dispatch_result_size = sp_std::cmp::max(relayers_entries, messages_count / dispatch_results_per_byte); + relayers_size + .checked_add(message_nonce_size) + .and_then(|result| result.checked_add(dispatch_result_size)) } /// Nonce of the last message that has been delivered to this (target) chain. pub fn last_delivered_nonce(&self) -> MessageNonce { self.relayers .back() - .map(|(_, last_nonce, _)| *last_nonce) + .map(|entry| entry.messages.end) .unwrap_or(self.last_confirmed_nonce) } } @@ -176,6 +181,71 @@ pub struct MessageDetails { pub delivery_and_dispatch_fee: OutboundMessageFee, } +/// Bit vector of message dispatch results. +pub type DispatchResultsBitVec = BitVec; + +/// Unrewarded relayer entry stored in the inbound lane data. +/// +/// This struct represents a continuous range of messages that have been delivered by the same relayer +/// and whose confirmations are still pending. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct UnrewardedRelayer { + /// Identifier of the relayer. + pub relayer: RelayerId, + /// Messages range, delivered by this relayer. + pub messages: DeliveredMessages, +} + +/// Delivered messages with their dispatch result. +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +pub struct DeliveredMessages { + /// Nonce of the first message that has been delivered (inclusive). + pub begin: MessageNonce, + /// Nonce of the last message that has been delivered (inclusive). + pub end: MessageNonce, + /// Dispatch result (`false`/`true`), returned by the message dispatcher for every + /// message in the `[begin; end]` range. See `dispatch_result` field of the + /// `bp_runtime::messages::MessageDispatchResult` structure for more information. + pub dispatch_results: DispatchResultsBitVec, +} + +impl DeliveredMessages { + /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given dispatch result. + pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { + DeliveredMessages { + begin: nonce, + end: nonce, + dispatch_results: bitvec![Msb0, u8; if dispatch_result { 1 } else { 0 }], + } + } + + /// Note new dispatched message. + pub fn note_dispatched_message(&mut self, dispatch_result: bool) { + self.end += 1; + self.dispatch_results.push(dispatch_result); + } + + /// Returns true if delivered messages contain message with given nonce. + pub fn contains_message(&self, nonce: MessageNonce) -> bool { + (self.begin..=self.end).contains(&nonce) + } + + /// Get dispatch result flag by message nonce. + /// + /// Dispatch result flag must be interpreted using the knowledge of dispatch mechanism + /// at the target chain. See `dispatch_result` field of the + /// `bp_runtime::messages::MessageDispatchResult` structure for more information. + /// + /// Panics if message nonce is not in the `begin..=end` range. Typically you'll first + /// check if message is within the range by calling `contains_message`. + pub fn message_dispatch_result(&self, nonce: MessageNonce) -> bool { + const INVALID_NONCE: &str = "Invalid nonce used to index dispatch_results"; + + let index = nonce.checked_sub(self.begin).expect(INVALID_NONCE) as usize; + *self.dispatch_results.get(index).expect(INVALID_NONCE) + } +} + /// Gist of `InboundLaneData::relayers` field used by runtime APIs. #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] pub struct UnrewardedRelayersState { @@ -214,12 +284,10 @@ impl Default for OutboundLaneData { /// Returns total number of messages in the `InboundLaneData::relayers` vector. /// /// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`). -pub fn total_unrewarded_messages( - relayers: &VecDeque<(MessageNonce, MessageNonce, RelayerId)>, -) -> Option { +pub fn total_unrewarded_messages(relayers: &VecDeque>) -> Option { match (relayers.front(), relayers.back()) { - (Some((begin, _, _)), Some((_, end, _))) => { - if let Some(difference) = end.checked_sub(*begin) { + (Some(front), Some(back)) => { + if let Some(difference) = back.messages.end.checked_sub(front.messages.begin) { difference.checked_add(1) } else { Some(0) @@ -237,9 +305,18 @@ mod tests { fn total_unrewarded_messages_does_not_overflow() { assert_eq!( total_unrewarded_messages( - &vec![(0, 0, 1), (MessageNonce::MAX, MessageNonce::MAX, 2)] - .into_iter() - .collect() + &vec![ + UnrewardedRelayer { + relayer: 1, + messages: DeliveredMessages::new(0, true) + }, + UnrewardedRelayer { + relayer: 2, + messages: DeliveredMessages::new(MessageNonce::MAX, true) + }, + ] + .into_iter() + .collect() ), None, ); @@ -247,19 +324,60 @@ mod tests { #[test] fn inbound_lane_data_returns_correct_hint() { - let expected_size = InboundLaneData::::encoded_size_hint(1, 13); - let actual_size = InboundLaneData { - relayers: (1u8..=13u8).map(|i| (i as _, i as _, i)).collect(), - last_confirmed_nonce: 13, + let test_cases = vec![ + // single relayer, multiple messages + (1, 128u8), + // multiple relayers, single message per relayer + (128u8, 128u8), + // several messages per relayer + (13u8, 128u8), + ]; + for (relayer_entries, messages_count) in test_cases { + let expected_size = InboundLaneData::::encoded_size_hint(1, relayer_entries as _, messages_count as _); + let actual_size = InboundLaneData { + relayers: (1u8..=relayer_entries) + .map(|i| { + let mut entry = UnrewardedRelayer { + relayer: i, + messages: DeliveredMessages::new(i as _, true), + }; + entry.messages.dispatch_results = bitvec![ + Msb0, u8; + 1; + (messages_count / relayer_entries) as _ + ]; + entry + }) + .collect(), + last_confirmed_nonce: messages_count as _, + } + .encode() + .len(); + let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs(); + assert!( + difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1, + "Too large difference between actual ({}) and expected ({:?}) inbound lane data size. Test case: {}+{}", + actual_size, + expected_size, + relayer_entries, + messages_count, + ); } - .encode() - .len(); - let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs(); - assert!( - difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1, - "Too large difference between actual ({}) and expected ({:?}) inbound lane data size", - actual_size, - expected_size, - ); + } + + #[test] + fn message_dispatch_result_works() { + let delivered_messages = DeliveredMessages { + begin: 100, + end: 150, + dispatch_results: bitvec![Msb0, u8; 1; 151], + }; + + assert!(!delivered_messages.contains_message(99)); + assert!(delivered_messages.contains_message(100)); + assert!(delivered_messages.contains_message(150)); + assert!(!delivered_messages.contains_message(151)); + + assert!(delivered_messages.message_dispatch_result(125)); } } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 1d313634bcba3..392331eda6722 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -16,7 +16,7 @@ //! Primitives of messages module, that are used on the source chain. -use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; +use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; use bp_runtime::Size; use frame_support::{Parameter, RuntimeDebug}; @@ -135,6 +135,15 @@ pub trait MessageDeliveryAndDispatchPayment { } } +/// Handler for messages delivery confirmation. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait OnDeliveryConfirmed { + /// Called when we receive confirmation that our messages have been delivered to the + /// target chain. The confirmation also has single bit dispatch result for every + /// confirmed message (see `DeliveredMessages` for details). + fn on_messages_delivered(_lane: &LaneId, _messages: &DeliveredMessages) {} +} + /// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and /// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden. pub struct ForbidOutboundMessages; diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 2a649f54d7233..d1b87fd02323a 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -164,6 +164,7 @@ impl MessageDispatch for ForbidInboundMessages { fn dispatch(_: &AccountId, _: DispatchMessage) -> MessageDispatchResult { MessageDispatchResult { + dispatch_result: false, unspent_weight: 0, dispatch_fee_paid_during_dispatch: false, } diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index e97430c5b05a9..053b44ff049d8 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -36,6 +36,12 @@ pub enum DispatchFeePayment { /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] pub struct MessageDispatchResult { + /// Dispatch result flag. This flag is relayed back to the source chain and, generally + /// speaking, may bring any (that fits in single bit) information from the dispatcher at + /// the target chain to the message submitter at the source chain. If you're using immediate + /// call dispatcher, then it'll be result of the dispatch - `true` if dispatch has succeeded + /// and `false` otherwise. + pub dispatch_result: bool, /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: /// diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 5bb64ed077d1c..7efea545f9a6d 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -204,7 +204,7 @@ mod tests { // reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (814, 216_583_333_334), + (782, 216_583_333_334), ); } } From b3ae24545bfc677561eb12f7b72a43d2f32ec9ee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Jun 2021 22:48:35 +0300 Subject: [PATCH 0493/1210] Return dispatch_fee_payment from message details RPC (#1014) --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- modules/messages/src/benchmarking.rs | 2 +- primitives/message-dispatch/src/lib.rs | 2 +- primitives/messages/src/lib.rs | 5 ++++- relays/bin-substrate/src/messages_source.rs | 2 ++ 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 84d62c2e30ffb..33c21027f8a2a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -619,7 +619,7 @@ impl_runtime_apis! { dispatch_weight: decoded_payload.weight, size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, - // TODO: include dispatch fee type (https://github.com/paritytech/parity-bridges-common/pull/911) + dispatch_fee_payment: decoded_payload.dispatch_fee_payment, }) }) .collect() diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 46c01baf4f9cf..40eb7326a3f44 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -770,7 +770,7 @@ impl_runtime_apis! { dispatch_weight: decoded_payload.weight, size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, - // TODO: include dispatch fee type (https://github.com/paritytech/parity-bridges-common/pull/911) + dispatch_fee_payment: decoded_payload.dispatch_fee_payment, }) }) .collect() diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 6af28e8c5c8c8..54cb7c26cd3d7 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -76,7 +76,7 @@ pub struct MessageProofParams { pub outbound_lane_data: Option, /// Proof size requirements. pub size: ProofSize, - /// If true, dispatch fee is paid at the target chain (if supported by configuration). + /// Where the fee for dispatching message is paid? pub dispatch_fee_payment: DispatchFeePayment, } diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 7a677dba4207c..dcbc9ae085e06 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -121,7 +121,7 @@ pub struct MessagePayload, - /// Where message dispatch fee is paid? + /// Where the fee for dispatching message is paid? pub dispatch_fee_payment: DispatchFeePayment, /// The call itself. pub call: Call, diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index e1e7522181b52..eb44fbea94512 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -23,6 +23,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bitvec::prelude::*; +use bp_runtime::messages::DispatchFeePayment; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; @@ -169,7 +170,7 @@ impl InboundLaneData { } /// Message details, returned by runtime APIs. -#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] pub struct MessageDetails { /// Nonce assigned to the message. pub nonce: MessageNonce, @@ -179,6 +180,8 @@ pub struct MessageDetails { pub size: u32, /// Delivery+dispatch fee paid by the message submitter at the source chain. pub delivery_and_dispatch_fee: OutboundMessageFee, + /// Where the fee for dispatching message is paid? + pub dispatch_fee_payment: DispatchFeePayment, } /// Bit vector of message dispatch results. diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index ce82f8abe5e7c..8b460ea099c3f 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -363,6 +363,7 @@ fn make_message_details_map( #[cfg(test)] mod tests { use super::*; + use bp_runtime::messages::DispatchFeePayment; fn message_details_from_rpc( nonces: RangeInclusive, @@ -374,6 +375,7 @@ mod tests { dispatch_weight: 0, size: 0, delivery_and_dispatch_fee: 0, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }) .collect() } From b48a5e716a942274b645708583e4006bab01ead5 Mon Sep 17 00:00:00 2001 From: kaichao Date: Tue, 22 Jun 2021 15:20:00 +0800 Subject: [PATCH 0494/1210] Allow Root to assume SourceAccount. (#1011) * Allow Root to assume SourceAccount. * fmt code --- modules/dispatch/src/lib.rs | 9 +++------ modules/messages/README.md | 4 ++-- primitives/message-dispatch/src/lib.rs | 2 +- relays/client-substrate/src/lib.rs | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 4f61a3b935fa6..fcf8c73c29792 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -355,7 +355,7 @@ where } CallOrigin::SourceAccount(ref source_account_id) => { ensure!( - sender_origin == &RawOrigin::Signed(source_account_id.clone()), + sender_origin == &RawOrigin::Signed(source_account_id.clone()) || sender_origin == &RawOrigin::Root, BadOrigin ); Ok(Some(source_account_id.clone())) @@ -964,10 +964,7 @@ mod tests { Err(BadOrigin) )); - // If we try and send the message from Root, it is also rejected - assert!(matches!( - verify_message_origin(&RawOrigin::Root, &message), - Err(BadOrigin) - )); + // The Root account is allowed to assume any expected origin account + assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(Some(1)))); } } diff --git a/modules/messages/README.md b/modules/messages/README.md index 973e251083570..be25b3c37f757 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -159,7 +159,7 @@ all required traits and will simply reject all transactions, related to outbound The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the -bridged chain as the source or our inbound messages. When relayer sends us a delivery transaction, +bridged chain as the source or our inbound messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are sending messages to the same bridged chain. @@ -201,7 +201,7 @@ message needs to be read. So there's another When choosing values for these parameters, you must also keep in mind that if proof in your scheme is based on finality of headers (and it is the most obvious option for Substrate-based chains with finality notion), then choosing too small values for these parameters may cause significant delays -in message delivery. That's because there too many actors involved in this scheme: 1) authorities +in message delivery. That's because there are too many actors involved in this scheme: 1) authorities that are finalizing headers of the target chain need to finalize header with non-empty map; 2) the headers relayer then needs to submit this header and its finality proof to the source chain; 3) the messages relayer must then send confirmation transaction (storage proof of this map) to the source diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index dcbc9ae085e06..859dc5e469ad9 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -102,7 +102,7 @@ pub enum CallOrigin. -//! Tools to interact with (Open) Ethereum node using RPC methods. +//! Tools to interact with Substrate node using RPC methods. #![warn(missing_docs)] From da67901c9b71f9037a478af4e03d1cb642c77429 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Jun 2021 17:25:43 +0300 Subject: [PATCH 0495/1210] greedy relayer don't need message dispatch to be prepaid if dispatch is supposed to be paid at the target chain (#1016) --- primitives/runtime/src/messages.rs | 2 +- relays/bin-substrate/src/messages_source.rs | 19 +++-- relays/messages/Cargo.toml | 1 + relays/messages/src/message_lane_loop.rs | 14 +++- relays/messages/src/message_race_delivery.rs | 87 ++++++++++++++++++-- 5 files changed, 102 insertions(+), 21 deletions(-) diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index 053b44ff049d8..f6e04619c7230 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -20,7 +20,7 @@ use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; /// Where message dispatch fee is paid? -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq)] pub enum DispatchFeePayment { /// The dispacth fee is paid at the source chain. AtSourceChain, diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 8b460ea099c3f..35c5b8da191f3 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -23,7 +23,7 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::ChainId; +use bp_runtime::{messages::DispatchFeePayment, ChainId}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight}; @@ -351,6 +351,7 @@ fn make_message_details_map( size: details.size as _, // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 reward: num_traits::Zero::zero(), + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, ); expected_nonce = details.nonce + 1; @@ -363,7 +364,6 @@ fn make_message_details_map( #[cfg(test)] mod tests { use super::*; - use bp_runtime::messages::DispatchFeePayment; fn message_details_from_rpc( nonces: RangeInclusive, @@ -390,7 +390,8 @@ mod tests { MessageDetails { dispatch_weight: 0, size: 0, - reward: 0 + reward: 0, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, } ), ( @@ -398,7 +399,8 @@ mod tests { MessageDetails { dispatch_weight: 0, size: 0, - reward: 0 + reward: 0, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, } ), ( @@ -406,7 +408,8 @@ mod tests { MessageDetails { dispatch_weight: 0, size: 0, - reward: 0 + reward: 0, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, } ), ] @@ -425,7 +428,8 @@ mod tests { MessageDetails { dispatch_weight: 0, size: 0, - reward: 0 + reward: 0, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, } ), ( @@ -433,7 +437,8 @@ mod tests { MessageDetails { dispatch_weight: 0, size: 0, - reward: 0 + reward: 0, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, } ), ] diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 943a3b7d9cd8a..ea5d46845c5a3 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -17,4 +17,5 @@ parking_lot = "0.11.0" # Bridge Dependencies bp-messages = { path = "../../primitives/messages" } +bp-runtime = { path = "../../primitives/runtime" } relay-utils = { path = "../utils" } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 3ae1cb8a03f62..c87c024f39767 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -31,6 +31,7 @@ use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::messages::DispatchFeePayment; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, @@ -97,6 +98,8 @@ pub struct MessageDetails { pub size: u32, /// The relayer reward paid in the source chain tokens. pub reward: SourceChainBalance, + /// Where the fee for dispatching message is paid? + pub dispatch_fee_payment: DispatchFeePayment, } /// Messages details map. @@ -454,7 +457,7 @@ pub(crate) mod tests { } pub const CONFIRMATION_TRANSACTION_COST: TestSourceChainBalance = 1; - pub const DELIVERY_TRANSACTION_COST: TestSourceChainBalance = 1; + pub const BASE_MESSAGE_DELIVERY_TRANSACTION_COST: TestSourceChainBalance = 1; pub type TestSourceChainBalance = u64; pub type TestSourceHeaderId = HeaderId; @@ -590,6 +593,7 @@ pub(crate) mod tests { dispatch_weight: 1, size: 1, reward: 1, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, ) }) @@ -768,11 +772,13 @@ pub(crate) mod tests { async fn estimate_delivery_transaction_in_source_tokens( &self, - _nonces: RangeInclusive, - _total_dispatch_weight: Weight, + nonces: RangeInclusive, + total_dispatch_weight: Weight, total_size: u32, ) -> TestSourceChainBalance { - DELIVERY_TRANSACTION_COST * (total_size as TestSourceChainBalance) + BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) + + total_dispatch_weight + + total_size as TestSourceChainBalance } } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index c4a5b235a5fb4..bde09af7068fd 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -28,6 +28,7 @@ use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; +use bp_runtime::messages::DispatchFeePayment; use futures::stream::FusedStream; use num_traits::{SaturatingAdd, Zero}; use relay_utils::FailedClient; @@ -560,6 +561,7 @@ async fn select_nonces_for_delivery_transaction( let mut soft_selected_count = 0; let mut selected_weight: Weight = 0; + let mut selected_unpaid_weight: Weight = 0; let mut selected_size: u32 = 0; let mut selected_count: MessageNonce = 0; @@ -627,6 +629,18 @@ async fn select_nonces_for_delivery_transaction( break; } + // If dispatch fee has been paid at the source chain, it means that it is **relayer** who's + // paying for dispatch at the target chain AND reward must cover this dispatch fee. + // + // If dispatch fee is paid at the target chain, it means that it'll be withdrawn from the + // dispatch origin account AND reward is not covering this fee. + // + // So in the latter case we're not adding the dispatch weight to the delivery transaction weight. + let new_selected_unpaid_weight = match details.dispatch_fee_payment { + DispatchFeePayment::AtSourceChain => selected_unpaid_weight.saturating_add(details.dispatch_weight), + DispatchFeePayment::AtTargetChain => selected_unpaid_weight, + }; + // now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT // to deliver it? It depends on the relayer strategy. match relayer_mode { @@ -637,7 +651,7 @@ async fn select_nonces_for_delivery_transaction( let delivery_transaction_cost = lane_target_client .estimate_delivery_transaction_in_source_tokens( 0..=(new_selected_count as MessageNonce - 1), - new_selected_weight, + new_selected_unpaid_weight, new_selected_size as u32, ) .await; @@ -685,6 +699,7 @@ async fn select_nonces_for_delivery_transaction( hard_selected_count = index + 1; selected_weight = new_selected_weight; + selected_unpaid_weight = new_selected_unpaid_weight; selected_size = new_selected_size; selected_count = new_selected_count; } @@ -740,13 +755,19 @@ mod tests { use crate::message_lane_loop::{ tests::{ header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance, TestSourceClient, - TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, CONFIRMATION_TRANSACTION_COST, - DELIVERY_TRANSACTION_COST, + TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, BASE_MESSAGE_DELIVERY_TRANSACTION_COST, + CONFIRMATION_TRANSACTION_COST, }, MessageDetails, }; + use bp_runtime::messages::DispatchFeePayment::*; - const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST + DELIVERY_TRANSACTION_COST; + const DEFAULT_DISPATCH_WEIGHT: Weight = 1; + const DEFAULT_SIZE: u32 = 1; + const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST + + BASE_MESSAGE_DELIVERY_TRANSACTION_COST + + DEFAULT_DISPATCH_WEIGHT + + (DEFAULT_SIZE as TestSourceChainBalance); type TestRaceState = RaceState; type TestStrategy = MessageDeliveryStrategy; @@ -755,6 +776,7 @@ mod tests { new_nonces: RangeInclusive, confirmed_nonce: MessageNonce, reward: TestSourceChainBalance, + dispatch_fee_payment: DispatchFeePayment, ) -> SourceClientNonces> { SourceClientNonces { new_nonces: new_nonces @@ -763,9 +785,10 @@ mod tests { ( nonce, MessageDetails { - dispatch_weight: 1, - size: 1, + dispatch_weight: DEFAULT_DISPATCH_WEIGHT, + size: DEFAULT_SIZE, reward, + dispatch_fee_payment, }, ) }) @@ -811,7 +834,7 @@ mod tests { race_strategy .strategy - .source_nonces_updated(header_id(1), source_nonces(20..=23, 19, DEFAULT_REWARD)); + .source_nonces_updated(header_id(1), source_nonces(20..=23, 19, DEFAULT_REWARD, AtSourceChain)); let target_nonces = TargetClientNonces { latest_nonce: 19, @@ -845,6 +868,7 @@ mod tests { dispatch_weight: idx, size: idx as _, reward: idx as _, + dispatch_fee_payment: AtSourceChain, }, ) }) @@ -1135,7 +1159,12 @@ mod tests { #[async_std::test] async fn no_losses_relayer_is_not_delivering_messages_if_cost_is_larger_than_reward() { let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD - DELIVERY_TRANSACTION_COST); + let nonces = source_nonces( + 24..=25, + 19, + DEFAULT_REWARD - BASE_MESSAGE_DELIVERY_TRANSACTION_COST, + AtSourceChain, + ); strategy.strategy.source_nonces_updated(header_id(2), nonces); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); strategy.relayer_mode = RelayerMode::NoLosses; @@ -1150,6 +1179,46 @@ mod tests { ); } + #[async_std::test] + async fn no_losses_relayer_is_delivering_unpaid_messages() { + async fn test_with_dispatch_fee_payment( + dispatch_fee_payment: DispatchFeePayment, + ) -> Option<(RangeInclusive, MessageProofParameters)> { + let (mut state, mut strategy) = prepare_strategy(); + let nonces = source_nonces( + 24..=24, + 19, + DEFAULT_REWARD - DEFAULT_DISPATCH_WEIGHT, + dispatch_fee_payment, + ); + strategy.strategy.source_nonces_updated(header_id(2), nonces); + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + strategy.max_unrewarded_relayer_entries_at_target = 100; + strategy.max_unconfirmed_nonces_at_target = 100; + strategy.max_messages_in_single_batch = 100; + strategy.max_messages_weight_in_single_batch = 100; + strategy.max_messages_size_in_single_batch = 100; + strategy.relayer_mode = RelayerMode::NoLosses; + + // so now we have: + // - 20..=23 with reward = cost + // - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT` from the + // cost, so it should be fine; + // => when MSG#24 fee is paid at the target chain, strategy shall select all 20..=24 + // => when MSG#25 fee is paid at the source chain, strategy shall only select 20..=23 + strategy.select_nonces_to_deliver(state).await + } + + assert_eq!( + test_with_dispatch_fee_payment(AtTargetChain).await, + Some(((20..=24), proof_parameters(false, 5))) + ); + assert_eq!( + test_with_dispatch_fee_payment(AtSourceChain).await, + Some(((20..=23), proof_parameters(false, 4))) + ); + } + #[async_std::test] async fn relayer_uses_flattened_view_of_the_source_queue_to_select_nonces() { // Real scenario that has happened on test deployments: @@ -1161,7 +1230,7 @@ mod tests { // This was happening because selector (`select_nonces_for_delivery_transaction`) has been called // for every `source_queue` entry separately without preserving any context. let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD - DELIVERY_TRANSACTION_COST); + let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, AtSourceChain); strategy.strategy.source_nonces_updated(header_id(2), nonces); strategy.max_unrewarded_relayer_entries_at_target = 100; strategy.max_unconfirmed_nonces_at_target = 100; From 2db6d4e396690cf32e6b7794f9dbd33752c2cbcf Mon Sep 17 00:00:00 2001 From: kaichao Date: Thu, 24 Jun 2021 23:33:35 +0800 Subject: [PATCH 0496/1210] Fix insufficient balance when send message. (#1020) * fix insufficient balance when send message. * Revert "fix insufficient balance when send message." This reverts commit b7a539c77b1eb0c6f7ccb1333e9fd2c4e18f8cbc. * More derived account used for send messages. * typo fix * trigger build --- README.md | 2 +- bin/millau/node/src/chain_spec.rs | 9 +++++++++ bin/rialto/node/src/chain_spec.rs | 9 +++++++++ modules/dispatch/src/lib.rs | 3 ++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6df1c0b09fe72..b407f203b7427 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ the `relays` which are used to pass messages between chains. │ └── ... ├── relays // Application for sending headers and messages between chains │ └── ... -└── scripts // Useful development and maintenence scripts +└── scripts // Useful development and maintenance scripts ``` ## Running the Bridge diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 2b920786c971d..2c50897b965ed 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -144,12 +144,21 @@ impl Alternative { derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Alice"), )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Charlie"), )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Eve"), )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Ferdie"), + )), ], true, ) diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index e354cbc8818fe..4174cda24487e 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -142,12 +142,21 @@ impl Alternative { rialto_runtime::Runtime, pallet_bridge_messages::DefaultInstance, >::relayer_fund_account_id(), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Alice"), + )), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Bob"), )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Charlie"), + )), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Eve"), + )), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Ferdie"), )), diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index fcf8c73c29792..a6ca087a2e2d4 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -310,12 +310,13 @@ impl, I: Instance> MessageDispatch for log::trace!( target: "runtime::bridge-dispatch", - "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}", + "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}. Call dispatch result: {:?}", source_chain, id, dispatch_result.unspent_weight, message.weight, dispatch_result, + result, ); Self::deposit_event(RawEvent::MessageDispatched( From 083eb3448d402ece01b3a64129687b5c1f868506 Mon Sep 17 00:00:00 2001 From: kaichao Date: Fri, 25 Jun 2021 15:22:18 +0800 Subject: [PATCH 0497/1210] Make target signer optional when sending message. (#1018) * make target signer optional in send message. * remove non-used argument * fmt * better doc * trigger build * fix clippy --- relays/bin-substrate/src/cli/send_message.rs | 42 ++++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 7ff96912d478f..0f6fee16a5a6d 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -41,9 +41,12 @@ pub struct SendMessage { source: SourceConnectionParams, #[structopt(flatten)] source_sign: SourceSigningParams, - // TODO [#885] Move TargetSign to origins - #[structopt(flatten)] - target_sign: TargetSigningParams, + /// The SURI of secret key to use when transactions are submitted to the Target node. + #[structopt(long, required_if("origin", "Target"))] + target_signer: Option, + /// The password for the SURI of secret key to use when transactions are submitted to the Target node. + #[structopt(long)] + target_signer_password: Option, /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -69,7 +72,8 @@ impl SendMessage { crate::select_full_bridge!(self.bridge, { let SendMessage { source_sign, - target_sign, + target_signer, + target_signer_password, ref mut message, dispatch_weight, origin, @@ -78,7 +82,6 @@ impl SendMessage { } = self; let source_sign = source_sign.to_keypair::()?; - let target_sign = target_sign.to_keypair::()?; encode_call::preprocess_call::(message, bridge.bridge_instance_index()); let target_call = Target::encode_call(message)?; @@ -98,6 +101,13 @@ impl SendMessage { match origin { Origins::Source => CallOrigin::SourceAccount(source_account_id), Origins::Target => { + let target_sign = TargetSigningParams { + target_signer: target_signer.clone().ok_or_else(|| { + anyhow::format_err!("The argument target_signer is not available") + })?, + target_signer_password: target_signer_password.clone(), + }; + let target_sign = target_sign.to_keypair::()?; let digest = account_ownership_digest( &target_call, source_account_id.clone(), @@ -255,8 +265,6 @@ mod tests { "1234", "--source-signer", "//Alice", - "--target-signer", - "//Bob", "remark", "--remark-payload", "1234", @@ -321,4 +329,24 @@ mod tests { } ); } + + #[test] + fn target_signer_must_exist_if_origin_is_target() { + // given + let send_message = SendMessage::from_iter_safe(vec![ + "send-message", + "MillauToRialto", + "--source-port", + "1234", + "--source-signer", + "//Alice", + "--origin", + "Target", + "remark", + "--remark-payload", + "1234", + ]); + + assert!(send_message.is_err()); + } } From a4588197a5d153112946731c047a99876bd6cf18 Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 25 Jun 2021 09:26:06 +0200 Subject: [PATCH 0498/1210] Update the wasm builder to substrate master (#1029) * chore: update the wasm builder to substrate master * Bump Substrate * Update weight of sending remarks ref https://github.com/paritytech/polkadot/pull/3354 Co-authored-by: Hernando Castano --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/service.rs | 1 + bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/node/src/service.rs | 1 + bin/rialto/runtime/Cargo.toml | 2 +- modules/dispatch/src/lib.rs | 2 +- relays/bin-substrate/src/cli/encode_message.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 4 ++-- 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 4c5f081e15069..8c6d32402ac24 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -51,7 +51,7 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] -substrate-build-script-utils = "3.0.0" +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index a9d555a872c9b..2373d0fbdc67b 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -300,6 +300,7 @@ pub fn new_full(mut config: Configuration) -> Result sync_oracle: network.clone(), justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), })?; diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 240b079d110f4..367c1c3eef704 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -56,7 +56,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } [build-dependencies] -substrate-wasm-builder = "3.0.0" +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 38272cd8c786f..1c9ec8b5bb0ab 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -52,7 +52,7 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] -substrate-build-script-utils = "3.0.0" +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 103929cff526d..35f923c77cc9a 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -304,6 +304,7 @@ pub fn new_full(mut config: Configuration) -> Result sync_oracle: network.clone(), justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), })?; diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 63a48a255bd42..f66b8920c8a55 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -68,7 +68,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master libsecp256k1 = { version = "0.3.4", features = ["hmac"] } [build-dependencies] -substrate-wasm-builder = "3.0.0" +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index a6ca087a2e2d4..e9bf75686bbdd 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -615,7 +615,7 @@ mod tests { event: Event::Dispatch(call_dispatch::Event::::MessageWeightMismatch( SOURCE_CHAIN_ID, id, - 1345000, + 1038000, 7, )), topics: vec![], diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index b5a38ec3de389..213c8377678f9 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -101,6 +101,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x01000000b0d60f000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 0f6fee16a5a6d..508a354ee953b 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -278,7 +278,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 1345000, + weight: 1038000, origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: hex!("0401081234").to_vec(), @@ -318,7 +318,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 1345000, + weight: 1038000, origin: CallOrigin::TargetAccount( sp_keyring::AccountKeyring::Alice.to_account_id(), sp_keyring::AccountKeyring::Bob.into(), From 92a089589865bf499088a93d699760eadfed6037 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Jun 2021 11:06:14 +0300 Subject: [PATCH 0499/1210] Rococo <> Wococo messages relay (#1030) * MessagesInstance -> BridgedMessagesInstance * Chain::ID -> Bridge::THIS_CHAIN_ID+Bridge::BRIDGED_CHAIN_ID * FromBridgedChainEncodedMessageCall -> FromBridgedChainEncodedMessageCall * impl Parameter for () * copypaste storage_map_final_key to avoid different runtime references/dummy runtimes * moved dummy runtime from primitives to relay client * Rococo <> Wococo messages relays * send R<>W messages using relay * fmt * return Result from get_dispatch_info * fix benchmarks compilation * clippy --- bin/millau/runtime/src/rialto_messages.rs | 13 +- bin/rialto/runtime/src/lib.rs | 19 +- bin/rialto/runtime/src/millau_messages.rs | 13 +- bin/runtime-common/src/messages.rs | 79 +++--- modules/messages/src/lib.rs | 34 ++- primitives/chain-rococo/Cargo.toml | 2 - primitives/chain-rococo/src/lib.rs | 51 +--- primitives/chain-wococo/Cargo.toml | 2 - primitives/chain-wococo/src/lib.rs | 45 +--- primitives/messages/src/lib.rs | 4 + relays/bin-substrate/src/chains/millau.rs | 6 +- .../src/chains/millau_messages_to_rialto.rs | 16 +- relays/bin-substrate/src/chains/mod.rs | 7 +- relays/bin-substrate/src/chains/rialto.rs | 6 +- .../src/chains/rialto_messages_to_millau.rs | 16 +- relays/bin-substrate/src/chains/rococo.rs | 65 ++++- .../src/chains/rococo_headers_to_wococo.rs | 7 +- .../src/chains/rococo_messages_to_wococo.rs | 227 ++++++++++++++++++ relays/bin-substrate/src/chains/wococo.rs | 59 ++++- .../src/chains/wococo_headers_to_rococo.rs | 7 +- .../src/chains/wococo_messages_to_rococo.rs | 227 ++++++++++++++++++ relays/bin-substrate/src/cli/bridge.rs | 50 ++++ relays/bin-substrate/src/cli/encode_call.rs | 7 +- relays/bin-substrate/src/cli/init_bridge.rs | 8 +- .../src/cli/relay_headers_and_messages.rs | 24 ++ relays/bin-substrate/src/cli/send_message.rs | 4 +- relays/bin-substrate/src/messages_source.rs | 17 +- relays/bin-substrate/src/messages_target.rs | 17 +- relays/client-rococo/Cargo.toml | 9 + relays/client-rococo/src/lib.rs | 6 +- relays/client-rococo/src/runtime.rs | 135 +++++++++++ relays/client-wococo/Cargo.toml | 9 + relays/client-wococo/src/lib.rs | 6 +- relays/client-wococo/src/runtime.rs | 135 +++++++++++ 34 files changed, 1090 insertions(+), 242 deletions(-) create mode 100644 relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs create mode 100644 relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs create mode 100644 relays/client-rococo/src/runtime.rs create mode 100644 relays/client-wococo/src/runtime.rs diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 644ddc6421753..12af2c328521b 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -52,7 +52,7 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifie pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Encoded Millau Call as it comes from Rialto. -pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; +pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Messages proof for Rialto -> Millau messages. type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -74,9 +74,12 @@ pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; + const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; type ThisChain = Millau; type BridgedChain = Rialto; + type BridgedMessagesInstance = crate::WithRialtoMessagesInstance; fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) @@ -89,16 +92,12 @@ impl MessageBridge for WithRialtoMessageBridge { pub struct Millau; impl messages::ChainWithMessages for Millau { - const ID: ChainId = MILLAU_CHAIN_ID; - type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; type Weight = Weight; type Balance = bp_millau::Balance; - - type MessagesInstance = crate::WithRialtoMessagesInstance; } impl messages::ThisChainWithMessages for Millau { @@ -145,16 +144,12 @@ impl messages::ThisChainWithMessages for Millau { pub struct Rialto; impl messages::ChainWithMessages for Rialto { - const ID: ChainId = RIALTO_CHAIN_ID; - type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; type Weight = Weight; type Balance = bp_rialto::Balance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl messages::BridgedChainWithMessages for Rialto { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 40eb7326a3f44..219feda64693e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -915,10 +915,10 @@ impl_runtime_apis! { fn prepare_message_proof( params: MessageProofParams, ) -> (millau_messages::FromMillauMessagesProof, Weight) { - use crate::millau_messages::{Millau, WithMillauMessageBridge}; + use crate::millau_messages::WithMillauMessageBridge; use bp_messages::MessageKey; use bridge_runtime_common::{ - messages::ChainWithMessages, + messages::MessageBridge, messages_benchmarking::{ed25519_sign, prepare_message_proof}, }; use codec::Encode; @@ -951,13 +951,12 @@ impl_runtime_apis! { } let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< - Runtime, - ::MessagesInstance, + ::BridgedMessagesInstance, >( &message_key.lane_id, message_key.nonce, ).0; let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::< - ::MessagesInstance, + ::BridgedMessagesInstance, >( &lane_id, ).0; @@ -998,18 +997,14 @@ impl_runtime_apis! { fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> millau_messages::ToMillauMessagesDeliveryProof { - use crate::millau_messages::{Millau, WithMillauMessageBridge}; - use bridge_runtime_common::{ - messages::ChainWithMessages, - messages_benchmarking::prepare_message_delivery_proof, - }; + use crate::millau_messages::WithMillauMessageBridge; + use bridge_runtime_common::{messages_benchmarking::prepare_message_delivery_proof}; use sp_runtime::traits::Header; prepare_message_delivery_proof::( params, |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - Runtime, - ::MessagesInstance, + ::BridgedMessagesInstance, >( &lane_id, ).0, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index edcef4447fec5..bf97478a0aa20 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -52,7 +52,7 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifie pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Encoded Rialto Call as it comes from Millau. -pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; +pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< @@ -74,9 +74,12 @@ pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; + const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; type ThisChain = Rialto; type BridgedChain = Millau; + type BridgedMessagesInstance = crate::WithMillauMessagesInstance; fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) @@ -89,16 +92,12 @@ impl MessageBridge for WithMillauMessageBridge { pub struct Rialto; impl messages::ChainWithMessages for Rialto { - const ID: ChainId = RIALTO_CHAIN_ID; - type Hash = bp_rialto::Hash; type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; type Weight = Weight; type Balance = bp_rialto::Balance; - - type MessagesInstance = crate::WithMillauMessagesInstance; } impl messages::ThisChainWithMessages for Rialto { @@ -145,16 +144,12 @@ impl messages::ThisChainWithMessages for Rialto { pub struct Millau; impl messages::ChainWithMessages for Millau { - const ID: ChainId = MILLAU_CHAIN_ID; - type Hash = bp_millau::Hash; type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; type Weight = Weight; type Balance = bp_millau::Balance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl messages::BridgedChainWithMessages for Millau { diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 5628977480910..72249e4f4e338 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -49,10 +49,17 @@ pub trait MessageBridge { /// Relayer interest (in percents). const RELAYER_FEE_PERCENT: u32; + /// Identifier of this chain. + const THIS_CHAIN_ID: ChainId; + /// Identifier of the Bridged chain. + const BRIDGED_CHAIN_ID: ChainId; + /// This chain in context of message bridge. type ThisChain: ThisChainWithMessages; /// Bridged chain in context of message bridge. type BridgedChain: BridgedChainWithMessages; + /// Instance of the `pallet-bridge-messages` pallet at the Bridged chain. + type BridgedMessagesInstance: Instance; /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; @@ -60,9 +67,6 @@ pub trait MessageBridge { /// Chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ChainWithMessages { - /// Identifier of this chain. - const ID: ChainId; - /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. @@ -78,9 +82,6 @@ pub trait ChainWithMessages { type Weight: From + PartialOrd; /// Type of balances that is used on the chain. type Balance: Encode + Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; - - /// Instance of the `pallet-bridge-messages` pallet. - type MessagesInstance: Instance; } /// Message related transaction parameters estimation. @@ -147,7 +148,6 @@ pub(crate) type SignerOf = ::Signer; pub(crate) type SignatureOf = ::Signature; pub(crate) type WeightOf = ::Weight; pub(crate) type BalanceOf = ::Balance; -pub(crate) type MessagesInstanceOf = ::MessagesInstance; pub(crate) type CallOf = ::Call; @@ -376,7 +376,6 @@ pub mod source { ) -> Result, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - ThisRuntime: pallet_bridge_messages::Config>>, HashOf>: Into>::BridgedChain>>, { @@ -391,10 +390,8 @@ pub mod source { |storage| { // Messages delivery proof is just proof of single storage key read => any error // is fatal. - let storage_inbound_lane_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - ThisRuntime, - MessagesInstanceOf>, - >(&lane); + let storage_inbound_lane_data_key = + pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&lane); let raw_inbound_lane_data = storage .read_value(storage_inbound_lane_data_key.0.as_ref()) .map_err(|_| "Failed to read inbound lane state from storage proof")? @@ -425,7 +422,7 @@ pub mod target { AccountIdOf>, SignerOf>, SignatureOf>, - FromBridgedChainEncodedMessageCall, + FromBridgedChainEncodedMessageCall>>, >; /// Messages proof from bridged chain: @@ -463,12 +460,12 @@ pub mod target { /// Our Call is opaque (`Vec`) for Bridged chain. So it is encoded, prefixed with /// vector length. Custom decode implementation here is exactly to deal with this. #[derive(Decode, Encode, RuntimeDebug, PartialEq)] - pub struct FromBridgedChainEncodedMessageCall { + pub struct FromBridgedChainEncodedMessageCall { encoded_call: Vec, - _marker: PhantomData, + _marker: PhantomData, } - impl FromBridgedChainEncodedMessageCall { + impl FromBridgedChainEncodedMessageCall { /// Create encoded call. pub fn new(encoded_call: Vec) -> Self { FromBridgedChainEncodedMessageCall { @@ -478,9 +475,9 @@ pub mod target { } } - impl From> for Result>, ()> { - fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { - CallOf::>::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) + impl From> for Result { + fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { + DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) } } @@ -523,8 +520,8 @@ pub mod target { ) -> MessageDispatchResult { let message_id = (message.key.lane_id, message.key.nonce); pallet_bridge_dispatch::Pallet::::dispatch( - B::BridgedChain::ID, - B::ThisChain::ID, + B::BRIDGED_CHAIN_ID, + B::THIS_CHAIN_ID, message_id, message.data.payload.map_err(drop), |dispatch_origin, dispatch_weight| { @@ -561,7 +558,7 @@ pub mod target { ) -> Result>>>, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - ThisRuntime: pallet_bridge_messages::Config>>, + ThisRuntime: pallet_bridge_messages::Config, HashOf>: Into>::BridgedChain>>, { @@ -574,7 +571,7 @@ pub mod target { StorageProof::new(bridged_storage_proof), |storage_adapter| storage_adapter, ) - .map(|storage| StorageProofCheckerAdapter::<_, B, ThisRuntime> { + .map(|storage| StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default(), }) @@ -614,31 +611,29 @@ pub mod target { fn read_raw_message(&self, message_key: &MessageKey) -> Option>; } - struct StorageProofCheckerAdapter { + struct StorageProofCheckerAdapter { storage: StorageProofChecker, - _dummy: sp_std::marker::PhantomData<(B, ThisRuntime)>, + _dummy: sp_std::marker::PhantomData, } - impl MessageProofParser for StorageProofCheckerAdapter + impl MessageProofParser for StorageProofCheckerAdapter where H: Hasher, B: MessageBridge, - ThisRuntime: pallet_bridge_messages::Config>>, { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { - let storage_outbound_lane_data_key = pallet_bridge_messages::storage_keys::outbound_lane_data_key::< - MessagesInstanceOf>, - >(lane_id); + let storage_outbound_lane_data_key = + pallet_bridge_messages::storage_keys::outbound_lane_data_key::(lane_id); self.storage .read_value(storage_outbound_lane_data_key.0.as_ref()) .ok()? } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - let storage_message_key = pallet_bridge_messages::storage_keys::message_key::< - ThisRuntime, - MessagesInstanceOf>, - >(&message_key.lane_id, message_key.nonce); + let storage_message_key = pallet_bridge_messages::storage_keys::message_key::( + &message_key.lane_id, + message_key.nonce, + ); self.storage.read_value(storage_message_key.0.as_ref()).ok()? } } @@ -743,9 +738,12 @@ mod tests { impl MessageBridge for OnThisChainBridge { const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = *b"this"; + const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; type ThisChain = ThisChain; type BridgedChain = BridgedChain; + type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance; fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) @@ -758,9 +756,12 @@ mod tests { impl MessageBridge for OnBridgedChainBridge { const RELAYER_FEE_PERCENT: u32 = 20; + const THIS_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_CHAIN_ID: ChainId = *b"this"; type ThisChain = BridgedChain; type BridgedChain = ThisChain; + type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance; fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { unreachable!() @@ -857,16 +858,12 @@ mod tests { struct ThisChain; impl ChainWithMessages for ThisChain { - const ID: ChainId = *b"this"; - type Hash = (); type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; type Signature = ThisChainSignature; type Weight = frame_support::weights::Weight; type Balance = ThisChainBalance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl ThisChainWithMessages for ThisChain { @@ -917,16 +914,12 @@ mod tests { struct BridgedChain; impl ChainWithMessages for BridgedChain { - const ID: ChainId = *b"brdg"; - type Hash = (); type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; type Signature = BridgedChainSignature; type Weight = frame_support::weights::Weight; type Balance = BridgedChainBalance; - - type MessagesInstance = pallet_bridge_messages::DefaultInstance; } impl ThisChainWithMessages for BridgedChain { @@ -1002,7 +995,7 @@ mod tests { weight: 100, origin: bp_message_dispatch::CallOrigin::SourceRoot, dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: target::FromBridgedChainEncodedMessageCall::::new( + call: target::FromBridgedChainEncodedMessageCall::::new( ThisChainCall::Transfer.encode(), ), } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 054c0e2a02d4f..a5f94c1eda819 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -755,24 +755,38 @@ impl, I: Instance> Pallet { /// trying to avoid here) - by using strings like "Instance2", "OutboundMessages", etc. pub mod storage_keys { use super::*; - use frame_support::storage::generator::StorageMap; + use frame_support::{traits::Instance, StorageHasher}; use sp_core::storage::StorageKey; /// Storage key of the outbound message in the runtime storage. - pub fn message_key, I: Instance>(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - let message_key = MessageKey { lane_id: *lane, nonce }; - let raw_storage_key = OutboundMessages::::storage_map_final_key(message_key); - StorageKey(raw_storage_key) + pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { + storage_map_final_key::("OutboundMessages", &MessageKey { lane_id: *lane, nonce }.encode()) } /// Storage key of the outbound message lane state in the runtime storage. pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - StorageKey(OutboundLanes::::storage_map_final_key(*lane)) + storage_map_final_key::("OutboundLanes", lane) } /// Storage key of the inbound message lane state in the runtime storage. - pub fn inbound_lane_data_key, I: Instance>(lane: &LaneId) -> StorageKey { - StorageKey(InboundLanes::::storage_map_final_key(*lane)) + pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { + storage_map_final_key::("InboundLanes", lane) + } + + /// This is a copypaste of the `frame_support::storage::generator::StorageMap::storage_map_final_key`. + fn storage_map_final_key(map_name: &str, key: &[u8]) -> StorageKey { + let module_prefix_hashed = frame_support::Twox128::hash(I::PREFIX.as_bytes()); + let storage_prefix_hashed = frame_support::Twox128::hash(map_name.as_bytes()); + let key_hashed = frame_support::Blake2_128Concat::hash(key); + + let mut final_key = + Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); + + final_key.extend_from_slice(&module_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key_hashed.as_ref()); + + StorageKey(final_key) } } @@ -1685,7 +1699,7 @@ mod tests { fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted messages proofs. - let storage_key = storage_keys::message_key::(&*b"test", 42).0; + let storage_key = storage_keys::message_key::(&*b"test", 42).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), @@ -1711,7 +1725,7 @@ mod tests { fn inbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted inbound lane state proofs. - let storage_key = storage_keys::inbound_lane_data_key::(&*b"test").0; + let storage_key = storage_keys::inbound_lane_data_key::(&*b"test").0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 2f806b36327cf..33772c7890a07 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -11,7 +11,6 @@ parity-scale-codec = { version = "2.0.0", default-features = false, features = [ smallvec = "1.6" # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -26,7 +25,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ - "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 7940b40d43ed6..8df064e891833 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -21,7 +21,6 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::Chain; use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -31,7 +30,12 @@ pub use bp_polkadot_core::*; /// Rococo Chain pub type Rococo = PolkadotLike; -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; +/// The target length of a session (how often authorities change) on Westend measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. +pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { @@ -61,44 +65,11 @@ impl WeightToFeePolynomial for WeightToFee { } } -/// Rococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from Metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -pub enum Call { - /// Wococo bridge pallet. - #[codec(index = 41)] - BridgeGrandpaWococo(BridgeGrandpaWococoCall), -} - -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaWococoCall { - #[codec(index = 0)] - submit_finality_proof( - ::Header, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } +// We use this to get the account on Rococo (target) which is derived from Wococo's (source) +// account. +pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::WOCOCO_CHAIN_ID, id); + AccountIdConverter::convert(encoded_id) } /// Name of the `RococoFinalityApi::best_finalized` runtime method. diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index ffa75b5a45ea2..88201dde9ac19 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -10,7 +10,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-rococo = { path = "../chain-rococo", default-features = false } @@ -24,7 +23,6 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "bp-header-chain/std", "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 3aaa5a730ad15..24572e141b20f 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -21,58 +21,15 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::Chain; use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime -pub use bp_rococo::{WeightToFee, VERSION}; +pub use bp_rococo::{WeightToFee, SESSION_LENGTH, VERSION}; /// Wococo Chain pub type Wococo = PolkadotLike; -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Wococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from Metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -pub enum Call { - /// Rococo bridge pallet. - #[codec(index = 40)] - BridgeGrandpaRococo(BridgeGrandpaRococoCall), -} - -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaRococoCall { - #[codec(index = 0)] - submit_finality_proof( - ::Header, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} - // We use this to get the account on Wococo (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index eb44fbea94512..963543ec3213f 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -64,6 +64,10 @@ pub trait Parameter: frame_support::Parameter { fn save(&self); } +impl Parameter for () { + fn save(&self) {} +} + /// Lane identifier. pub type LaneId = [u8; 4]; diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 41ac76082807c..3cba16ea32f44 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -23,7 +23,7 @@ use crate::cli::{ }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use relay_millau_client::Millau; use sp_version::RuntimeVersion; @@ -62,6 +62,10 @@ impl CliEncodeCall for Millau { }, }) } + + fn get_dispatch_info(call: &millau_runtime::Call) -> anyhow::Result { + Ok(call.get_dispatch_info()) + } } impl CliChain for Millau { diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index f132088f546de..31dc51e9c27bb 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -126,20 +126,12 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } /// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource< - Millau, - MillauMessagesToRialto, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, ->; +type MillauSourceClient = + SubstrateMessagesSource; /// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget< - Rialto, - MillauMessagesToRialto, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, ->; +type RialtoTargetClient = + SubstrateMessagesTarget; /// Run Millau-to-Rialto messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 7b7b768635812..09d3c3e9c060a 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -21,8 +21,10 @@ pub mod millau_messages_to_rialto; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; pub mod rococo_headers_to_wococo; +pub mod rococo_messages_to_wococo; pub mod westend_headers_to_millau; pub mod wococo_headers_to_rococo; +pub mod wococo_messages_to_rococo; mod millau; mod rialto; @@ -271,7 +273,10 @@ mod rococo_tests { votes_ancestries: vec![], }; - let actual = bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof(header.clone(), justification.clone()); + let actual = relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( + header.clone(), + justification.clone(), + ); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( header, justification, diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 77eeb06da0d70..9a6185b4fc7d9 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -23,7 +23,7 @@ use crate::cli::{ }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use relay_rialto_client::Rialto; use sp_version::RuntimeVersion; @@ -60,6 +60,10 @@ impl CliEncodeCall for Rialto { }, }) } + + fn get_dispatch_info(call: &rialto_runtime::Call) -> anyhow::Result { + Ok(call.get_dispatch_info()) + } } impl CliChain for Rialto { diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 02c6010f74f02..89f9dd7e997ed 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -126,20 +126,12 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } /// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource< - Rialto, - RialtoMessagesToMillau, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, ->; +type RialtoSourceClient = + SubstrateMessagesSource; /// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget< - Millau, - RialtoMessagesToMillau, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, ->; +type MillauTargetClient = + SubstrateMessagesTarget; /// Run Rialto-to-Millau messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 0bcf388c3462e..ec94450a63de5 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -14,11 +14,70 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{encode_message, CliChain}; -use frame_support::weights::Weight; +use codec::Decode; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; use sp_version::RuntimeVersion; +use crate::cli::{ + bridge, + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; + +/// Weight of the `system::remark` call at Rococo. +/// +/// This weight is larger (x2) than actual weight at current Rooco runtime to avoid unsuccessful +/// calls in the future. But since it is used only in tests (and on test chains), this is ok. +pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; + +impl CliEncodeCall for Rococo { + fn max_extrinsic_size() -> u32 { + bp_rococo::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Remark { remark_payload, .. } => { + relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::ROCOCO_TO_WOCOCO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message(lane.0, payload, fee.0), + ) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + _ => anyhow::bail!("The call is not supported"), + }) + } + + fn get_dispatch_info(call: &relay_rococo_client::runtime::Call) -> anyhow::Result { + match *call { + relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark(_)) => { + Ok(DispatchInfo { + weight: SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }) + } + _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + } + } +} + impl CliChain for Rococo { const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; @@ -30,7 +89,7 @@ impl CliChain for Rococo { } fn max_extrinsic_weight() -> Weight { - 0 + bp_wococo::max_extrinsic_weight() } fn encode_message(_message: encode_message::MessagePayload) -> Result { diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 4e641aec7490c..c7f60100f13c1 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -61,10 +61,9 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { header: RococoSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::submit_finality_proof( - header.into_inner(), - proof, - )); + let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( + relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(header.into_inner(), proof), + ); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs new file mode 100644 index 0000000000000..be5f91116ec33 --- /dev/null +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -0,0 +1,227 @@ +// 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 . + +//! Rococo-to-Wococo messages sync entrypoint. + +use crate::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, +}; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; + +use bp_messages::MessageNonce; +use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use codec::Encode; +use messages_relay::message_lane::MessageLane; +use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; +use sp_core::{Bytes, Pair}; +use std::{ops::RangeInclusive, time::Duration}; + +/// Rococo-to-Wococo message lane. +pub type RococoMessagesToWococo = + SubstrateMessageLaneToSubstrate; + +impl SubstrateMessageLane for RococoMessagesToWococo { + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + + type SourceChain = Rococo; + type TargetChain = Wococo; + + fn source_transactions_author(&self) -> bp_rococo::AccountId { + (*self.source_sign.public().as_array_ref()).into() + } + + fn make_messages_receiving_proof_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_block: WococoHeaderId, + proof: ::MessagesReceivingProof, + ) -> Bytes { + let (relayers_state, proof) = proof; + let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_delivery_proof( + proof, + relayers_state, + ), + ); + let genesis_hash = *self.source_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Wococo -> Rococo confirmation transaction. Weight: /{}, size: {}/{}", + bp_rococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_rococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_wococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_messages_delivery_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_header: RococoHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Bytes { + let (dispatch_weight, proof) = proof; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; + + let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof( + self.relayer_id_at_source.clone(), + proof, + messages_count as _, + dispatch_weight, + ), + ); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Rococo -> Wococo delivery transaction. Weight: /{}, size: {}/{}", + bp_wococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_wococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } +} + +/// Rococo node as messages source. +type RococoSourceClient = + SubstrateMessagesSource; + +/// Wococo node as messages target. +type WococoTargetClient = + SubstrateMessagesTarget; + +/// Run Rococo-to-Wococo messages sync. +pub async fn run( + params: MessagesRelayParams, +) -> Result<(), String> { + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); + + let lane_id = params.lane_id; + let source_client = params.source_client; + let lane = RococoMessagesToWococo { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_rococo, + }; + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_wococo::max_extrinsic_size() / 3; + // we don't know exact weights of the Wococo runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_wococo::max_extrinsic_weight(), + bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( + max_messages_in_single_batch / 2, + max_messages_weight_in_single_batch / 2, + ); + + log::info!( + target: "bridge", + "Starting Rococo -> Wococo messages relay.\n\t\ + Rococo relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}", + lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Rococo::AVERAGE_BLOCK_INTERVAL, + target_tick: Wococo::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + }, + }, + RococoSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + WOCOCO_CHAIN_ID, + params.target_to_source_headers_relay, + ), + WococoTargetClient::new( + params.target_client, + lane, + lane_id, + ROCOCO_CHAIN_ID, + params.source_to_target_headers_relay, + ), + relay_utils::relay_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + RococoMessagesToWococo, + >(&lane_id)), + params.metrics_params, + ) + .standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + "rococo_storage_proof_overhead".into(), + "Rococo storage proof overhead".into(), + ) + })? + .into_params(), + futures::future::pending(), + ) + .await +} diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 549aa8a882c75..9b944d781685d 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -14,11 +14,64 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{encode_message, CliChain}; -use frame_support::weights::Weight; +use codec::Decode; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_wococo_client::Wococo; use sp_version::RuntimeVersion; +use crate::cli::{ + bridge, + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; + +impl CliEncodeCall for Wococo { + fn max_extrinsic_size() -> u32 { + bp_wococo::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Remark { remark_payload, .. } => { + relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::WOCOCO_TO_ROCOCO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message(lane.0, payload, fee.0), + ) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + _ => anyhow::bail!("The call is not supported"), + }) + } + + fn get_dispatch_info(call: &relay_wococo_client::runtime::Call) -> anyhow::Result { + match *call { + relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark(_)) => { + Ok(DispatchInfo { + weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }) + } + _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + } + } +} + impl CliChain for Wococo { const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; @@ -30,7 +83,7 @@ impl CliChain for Wococo { } fn max_extrinsic_weight() -> Weight { - 0 + bp_wococo::max_extrinsic_weight() } fn encode_message(_message: encode_message::MessagePayload) -> Result { diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 4cae33db31d9d..8ee30d3ff4925 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -67,10 +67,9 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { header: WococoSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::submit_finality_proof( - header.into_inner(), - proof, - )); + let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( + relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof), + ); let genesis_hash = *self.target_client.genesis_hash(); let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs new file mode 100644 index 0000000000000..b696801569e87 --- /dev/null +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -0,0 +1,227 @@ +// 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 . + +//! Wococo-to-Rococo messages sync entrypoint. + +use crate::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, +}; +use crate::messages_source::SubstrateMessagesSource; +use crate::messages_target::SubstrateMessagesTarget; + +use bp_messages::MessageNonce; +use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use codec::Encode; +use messages_relay::message_lane::MessageLane; +use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; +use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; +use sp_core::{Bytes, Pair}; +use std::{ops::RangeInclusive, time::Duration}; + +/// Wococo-to-Rococo message lane. +pub type WococoMessagesToRococo = + SubstrateMessageLaneToSubstrate; + +impl SubstrateMessageLane for WococoMessagesToRococo { + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + + type SourceChain = Wococo; + type TargetChain = Rococo; + + fn source_transactions_author(&self) -> bp_wococo::AccountId { + (*self.source_sign.public().as_array_ref()).into() + } + + fn make_messages_receiving_proof_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_block: RococoHeaderId, + proof: ::MessagesReceivingProof, + ) -> Bytes { + let (relayers_state, proof) = proof; + let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_delivery_proof( + proof, + relayers_state, + ), + ); + let genesis_hash = *self.source_client.genesis_hash(); + let transaction = Wococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Rococo -> Wococo confirmation transaction. Weight: /{}, size: {}/{}", + bp_wococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_wococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_rococo::AccountId { + (*self.target_sign.public().as_array_ref()).into() + } + + fn make_messages_delivery_transaction( + &self, + transaction_nonce: ::Index, + _generated_at_header: WococoHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Bytes { + let (dispatch_weight, proof) = proof; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; + + let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof( + self.relayer_id_at_source.clone(), + proof, + messages_count as _, + dispatch_weight, + ), + ); + let genesis_hash = *self.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + log::trace!( + target: "bridge", + "Prepared Wococo -> Rococo delivery transaction. Weight: /{}, size: {}/{}", + bp_rococo::max_extrinsic_weight(), + transaction.encode().len(), + bp_rococo::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } +} + +/// Wococo node as messages source. +type WococoSourceClient = + SubstrateMessagesSource; + +/// Rococo node as messages target. +type RococoTargetClient = + SubstrateMessagesTarget; + +/// Run Wococo-to-Rococo messages sync. +pub async fn run( + params: MessagesRelayParams, +) -> Result<(), String> { + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); + + let lane_id = params.lane_id; + let source_client = params.source_client; + let lane = WococoMessagesToRococo { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_wococo, + }; + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_rococo::max_extrinsic_size() / 3; + // we don't know exact weights of the Rococo runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_rococo::max_extrinsic_weight(), + bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( + max_messages_in_single_batch / 2, + max_messages_weight_in_single_batch / 2, + ); + + log::info!( + target: "bridge", + "Starting Wococo -> Rococo messages relay.\n\t\ + Wococo relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}", + lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Wococo::AVERAGE_BLOCK_INTERVAL, + target_tick: Rococo::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + }, + }, + WococoSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + ROCOCO_CHAIN_ID, + params.target_to_source_headers_relay, + ), + RococoTargetClient::new( + params.target_client, + lane, + lane_id, + WOCOCO_CHAIN_ID, + params.source_to_target_headers_relay, + ), + relay_utils::relay_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + WococoMessagesToRococo, + >(&lane_id)), + params.metrics_params, + ) + .standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + "wococo_storage_proof_overhead".into(), + "Wococo storage proof overhead".into(), + ) + })? + .into_params(), + futures::future::pending(), + ) + .await +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index b54d3a72ad3b2..1feb3dcb1a46d 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -22,6 +22,8 @@ arg_enum! { pub enum FullBridge { MillauToRialto, RialtoToMillau, + RococoToWococo, + WococoToRococo, } } @@ -31,12 +33,16 @@ impl FullBridge { match self { Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, + Self::RococoToWococo => ROCOCO_TO_WOCOCO_INDEX, + Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX, } } } pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; +pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0; +pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0; /// The macro allows executing bridge-specific code without going fully generic. /// @@ -89,6 +95,50 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest; + $generic + } + FullBridge::RococoToWococo => { + type Source = relay_rococo_client::Rococo; + #[allow(dead_code)] + type Target = relay_wococo_client::Wococo; + + // Derive-account + #[allow(unused_imports)] + use bp_wococo::derive_account_from_rococo_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::rococo_messages_to_wococo::run as relay_messages; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_wococo::TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use relay_rococo_client::runtime::rococo_to_wococo_account_ownership_digest as account_ownership_digest; + + $generic + } + FullBridge::WococoToRococo => { + type Source = relay_wococo_client::Wococo; + #[allow(dead_code)] + type Target = relay_rococo_client::Rococo; + + // Derive-account + #[allow(unused_imports)] + use bp_rococo::derive_account_from_wococo_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::wococo_messages_to_rococo::run as relay_messages; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_rococo::TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest; + $generic } } diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 390d8f6ae6816..cfe6d99a4eb9f 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -17,7 +17,7 @@ use crate::cli::bridge::FullBridge; use crate::cli::{AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId}; use crate::select_full_bridge; -use frame_support::dispatch::GetDispatchInfo; +use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -85,6 +85,9 @@ pub trait CliEncodeCall: Chain { /// Encode a CLI call. fn encode_call(call: &Call) -> anyhow::Result; + + /// Get dispatch info for the call. + fn get_dispatch_info(call: &Self::Call) -> anyhow::Result; } impl EncodeCall { @@ -96,7 +99,7 @@ impl EncodeCall { let encoded = HexBytes::encode(&call); log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); - log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, call.get_dispatch_info().weight); + log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call)?.weight); log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); Ok(encoded) diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index b5590b9e5a445..20e6daa500e56 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -109,7 +109,9 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - bp_wococo::Call::BridgeGrandpaRococo(bp_wococo::BridgeGrandpaRococoCall::initialize(init_data)) + relay_wococo_client::runtime::Call::BridgeGrandpaRococo( + relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), + ) } $generic @@ -121,7 +123,9 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - bp_rococo::Call::BridgeGrandpaWococo(bp_rococo::BridgeGrandpaWococoCall::initialize(init_data)) + relay_rococo_client::runtime::Call::BridgeGrandpaWococo( + relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize(init_data), + ) } $generic diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 4955e8bbef338..e71ea6aeaa2f8 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -35,6 +35,7 @@ use structopt::StructOpt; #[derive(StructOpt)] pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), + RococoWococo(RococoWococoHeadersAndMessages), } /// Parameters that have the same names across all bridges. @@ -102,6 +103,26 @@ macro_rules! select_bridge { use crate::chains::millau_messages_to_rialto::run as left_to_right_messages; use crate::chains::rialto_messages_to_millau::run as right_to_left_messages; + $generic + } + RelayHeadersAndMessages::RococoWococo(_) => { + type Params = RococoWococoHeadersAndMessages; + + type Left = relay_rococo_client::Rococo; + type Right = relay_wococo_client::Wococo; + + type LeftToRightFinality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; + type RightToLeftFinality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + + type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo; + type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo; + + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; + + use crate::chains::rococo_messages_to_wococo::run as left_to_right_messages; + use crate::chains::wococo_messages_to_rococo::run as right_to_left_messages; + $generic } } @@ -111,8 +132,11 @@ macro_rules! select_bridge { // All supported chains. declare_chain_options!(Millau, millau); declare_chain_options!(Rialto, rialto); +declare_chain_options!(Rococo, rococo); +declare_chain_options!(Wococo, wococo); // All supported bridges. declare_bridge_options!(Millau, Rialto); +declare_bridge_options!(Rococo, Wococo); impl RelayHeadersAndMessages { /// Run the command. diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 508a354ee953b..f710f814e41d9 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -24,7 +24,7 @@ use crate::cli::{ use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_runtime::messages::DispatchFeePayment; use codec::Encode; -use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; +use frame_support::weights::Weight; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; @@ -89,7 +89,7 @@ impl SendMessage { let payload = { let target_call_weight = prepare_call_dispatch_weight( dispatch_weight, - ExplicitOrMaximal::Explicit(target_call.get_dispatch_info().weight), + ExplicitOrMaximal::Explicit(Target::get_dispatch_info(&target_call)?.weight), compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), ); let source_sender_public: MultiSigner = source_sign.public().into(); diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 35c5b8da191f3..88c8b529dcc61 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -33,7 +33,6 @@ use messages_relay::{ ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState, }, }; -use pallet_bridge_messages::Config as MessagesConfig; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; @@ -46,16 +45,16 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, lane: P, lane_id: LaneId, instance: ChainId, target_to_source_headers_relay: Option>, - _phantom: PhantomData<(R, I)>, + _phantom: PhantomData, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. pub fn new( client: Client, @@ -75,7 +74,7 @@ impl SubstrateMessagesSource Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -89,11 +88,10 @@ impl Clone for SubstrateMessagesSource< } #[async_trait] -impl RelayClient for SubstrateMessagesSource +impl RelayClient for SubstrateMessagesSource where C: Chain, P: SubstrateMessageLane, - R: 'static + Send + Sync, I: Send + Sync + Instance, { type Error = SubstrateError; @@ -104,7 +102,7 @@ where } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient

for SubstrateMessagesSource where C: Chain, C::Header: DeserializeOwned, @@ -120,7 +118,6 @@ where P::TargetChain: Chain, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, - R: Send + Sync + MessagesConfig, I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { @@ -198,7 +195,7 @@ where let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { - let message_key = pallet_bridge_messages::storage_keys::message_key::(&self.lane_id, message_nonce); + let message_key = pallet_bridge_messages::storage_keys::message_key::(&self.lane_id, message_nonce); storage_keys.push(message_key); message_nonce += 1; } diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index f9ffb922db88b..f74efbe61b5af 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -32,7 +32,6 @@ use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; -use pallet_bridge_messages::Config as MessagesConfig; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase}; use sp_core::Bytes; @@ -46,16 +45,16 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, instance: ChainId, source_to_target_headers_relay: Option>, - _phantom: PhantomData<(R, I)>, + _phantom: PhantomData, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. pub fn new( client: Client, @@ -75,7 +74,7 @@ impl SubstrateMessagesTarget Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -89,11 +88,10 @@ impl Clone for SubstrateMessagesTarget< } #[async_trait] -impl RelayClient for SubstrateMessagesTarget +impl RelayClient for SubstrateMessagesTarget where C: Chain, P: SubstrateMessageLane, - R: 'static + Send + Sync, I: Send + Sync + Instance, { type Error = SubstrateError; @@ -104,7 +102,7 @@ where } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient

for SubstrateMessagesTarget where C: Chain, C::Header: DeserializeOwned, @@ -119,7 +117,6 @@ where P::SourceChain: Chain, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, - R: Send + Sync + MessagesConfig, I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { @@ -190,7 +187,7 @@ where id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), SubstrateError> { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; - let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); + let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); let proof = self .client .prove_storage(vec![inbound_data_key], id.1) diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 095f365374a80..5611ac27b1ce4 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -12,7 +12,16 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bridge-runtime-common = { path = "../../bin/runtime-common" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } +bp-wococo = { path = "../../primitives/chain-wococo" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index fe9448d19c623..5a7d8999f7f16 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -22,6 +22,8 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; +pub mod runtime; + /// Rococo header id. pub type HeaderId = relay_utils::HeaderId; @@ -46,7 +48,7 @@ impl Chain for Rococo { type AccountId = bp_rococo::AccountId; type Index = bp_rococo::Index; type SignedBlock = bp_rococo::SignedBlock; - type Call = bp_rococo::Call; + type Call = crate::runtime::Call; type Balance = bp_rococo::Balance; } @@ -59,7 +61,7 @@ impl ChainWithBalances for Rococo { impl TransactionSignScheme for Rococo { type Chain = Rococo; type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_rococo::UncheckedExtrinsic; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; fn sign_transaction( genesis_hash: ::Hash, diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs new file mode 100644 index 0000000000000..6dbd40bee5608 --- /dev/null +++ b/relays/client-rococo/src/runtime.rs @@ -0,0 +1,135 @@ +// 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 . + +//! Types that are specific to the Rococo runtime. + +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_polkadot_core::PolkadotLike; +use bp_runtime::Chain; +use codec::{Decode, Encode}; +use frame_support::weights::Weight; + +/// Instance of messages pallet that is used to bridge with Wococo chain. +pub type WithWococoMessagesInstance = pallet_bridge_messages::Instance1; + +/// Unchecked Rococo extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Wococo account ownership digest from Rococo. +/// +/// The byte vector returned by this function should be signed with a Wococo account private key. +/// This way, the owner of `rococo_account_id` on Rococo proves that the Wococo account private key +/// is also under his control. +pub fn rococo_to_wococo_account_ownership_digest( + wococo_call: &Call, + rococo_account_id: AccountId, + wococo_spec_version: SpecVersion, +) -> Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_dispatch::account_ownership_digest( + wococo_call, + rococo_account_id, + wococo_spec_version, + bp_runtime::ROCOCO_CHAIN_ID, + bp_runtime::WOCOCO_CHAIN_ID, + ) +} + +/// Rococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Wococo bridge pallet. + #[codec(index = 41)] + BridgeGrandpaWococo(BridgeGrandpaWococoCall), + /// Wococo messages pallet. + #[codec(index = 44)] + BridgeMessagesWococo(BridgeMessagesWococoCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaWococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeMessagesWococoCall { + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountId, + bp_wococo::AccountPublic, + Vec, + >, + bp_rococo::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_wococo::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + UnrewardedRelayersState, + ), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 22d710ca3d7b7..c1b9aafd95e7c 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -12,7 +12,16 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bridge-runtime-common = { path = "../../bin/runtime-common" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 76ecf5b0a5116..8ceba7c7c436d 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -22,6 +22,8 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; +pub mod runtime; + /// Wococo header id. pub type HeaderId = relay_utils::HeaderId; @@ -46,7 +48,7 @@ impl Chain for Wococo { type AccountId = bp_wococo::AccountId; type Index = bp_wococo::Index; type SignedBlock = bp_wococo::SignedBlock; - type Call = bp_wococo::Call; + type Call = crate::runtime::Call; type Balance = bp_wococo::Balance; } @@ -59,7 +61,7 @@ impl ChainWithBalances for Wococo { impl TransactionSignScheme for Wococo { type Chain = Wococo; type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_wococo::UncheckedExtrinsic; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; fn sign_transaction( genesis_hash: ::Hash, diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs new file mode 100644 index 0000000000000..e973c3a6d0280 --- /dev/null +++ b/relays/client-wococo/src/runtime.rs @@ -0,0 +1,135 @@ +// 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 . + +//! Types that are specific to the Wococo runtime. + +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_polkadot_core::PolkadotLike; +use bp_runtime::Chain; +use codec::{Decode, Encode}; +use frame_support::weights::Weight; + +/// Instance of messages pallet that is used to bridge with Rococo chain. +pub type WithRococoMessagesInstance = pallet_bridge_messages::DefaultInstance; + +/// Unchecked Wococo extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Rococo account ownership digest from Wococo. +/// +/// The byte vector returned by this function should be signed with a Rococo account private key. +/// This way, the owner of `wococo_account_id` on Rococo proves that the Rococo account private key +/// is also under his control. +pub fn wococo_to_rococo_account_ownership_digest( + rococo_call: &Call, + wococo_account_id: AccountId, + rococo_spec_version: SpecVersion, +) -> Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_dispatch::account_ownership_digest( + rococo_call, + wococo_account_id, + rococo_spec_version, + bp_runtime::WOCOCO_CHAIN_ID, + bp_runtime::ROCOCO_CHAIN_ID, + ) +} + +/// Wococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from Metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Rococo bridge pallet. + #[codec(index = 40)] + BridgeGrandpaRococo(BridgeGrandpaRococoCall), + /// Rococo messages pallet. + #[codec(index = 43)] + BridgeMessagesRococo(BridgeMessagesRococoCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaRococoCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeMessagesRococoCall { + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountId, + bp_wococo::AccountPublic, + Vec, + >, + bp_rococo::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_rococo::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + UnrewardedRelayersState, + ), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} From 74487be9a0a1671fe7d8f88b545cd74f866fbb8a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 28 Jun 2021 12:13:53 +0300 Subject: [PATCH 0500/1210] estimate transaction fee (#1015) --- .../src/chains/millau_messages_to_rialto.rs | 4 +- .../src/chains/rialto_messages_to_millau.rs | 4 +- .../src/chains/rococo_messages_to_wococo.rs | 16 +- .../src/chains/wococo_messages_to_rococo.rs | 16 +- relays/bin-substrate/src/messages_source.rs | 105 +++++++++---- relays/bin-substrate/src/messages_target.rs | 146 ++++++++++++++---- relays/client-kusama/src/lib.rs | 2 + relays/client-millau/Cargo.toml | 1 + relays/client-millau/src/lib.rs | 2 + relays/client-polkadot/src/lib.rs | 2 + relays/client-rialto/Cargo.toml | 1 + relays/client-rialto/src/lib.rs | 2 + relays/client-rococo/src/lib.rs | 2 + relays/client-substrate/Cargo.toml | 3 + relays/client-substrate/src/chain.rs | 26 +++- relays/client-substrate/src/client.rs | 24 ++- relays/client-substrate/src/guard.rs | 2 + relays/client-substrate/src/rpc.rs | 4 + relays/client-westend/src/lib.rs | 2 + relays/client-wococo/src/lib.rs | 2 + 20 files changed, 294 insertions(+), 72 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 31dc51e9c27bb..9932d16a4242c 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -127,11 +127,11 @@ impl SubstrateMessageLane for MillauMessagesToRialto { /// Millau node as messages source. type MillauSourceClient = - SubstrateMessagesSource; + SubstrateMessagesSource; /// Rialto node as messages target. type RialtoTargetClient = - SubstrateMessagesTarget; + SubstrateMessagesTarget; /// Run Millau-to-Rialto messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 89f9dd7e997ed..f472703993ac5 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -127,11 +127,11 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { /// Rialto node as messages source. type RialtoSourceClient = - SubstrateMessagesSource; + SubstrateMessagesSource; /// Millau node as messages target. type MillauTargetClient = - SubstrateMessagesTarget; + SubstrateMessagesTarget; /// Run Rialto-to-Millau messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index be5f91116ec33..f8da60cf1738e 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -124,12 +124,20 @@ impl SubstrateMessageLane for RococoMessagesToWococo { } /// Rococo node as messages source. -type RococoSourceClient = - SubstrateMessagesSource; +type RococoSourceClient = SubstrateMessagesSource< + Rococo, + Wococo, + RococoMessagesToWococo, + relay_rococo_client::runtime::WithWococoMessagesInstance, +>; /// Wococo node as messages target. -type WococoTargetClient = - SubstrateMessagesTarget; +type WococoTargetClient = SubstrateMessagesTarget< + Rococo, + Wococo, + RococoMessagesToWococo, + relay_wococo_client::runtime::WithRococoMessagesInstance, +>; /// Run Rococo-to-Wococo messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index b696801569e87..2e65328831a24 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -124,12 +124,20 @@ impl SubstrateMessageLane for WococoMessagesToRococo { } /// Wococo node as messages source. -type WococoSourceClient = - SubstrateMessagesSource; +type WococoSourceClient = SubstrateMessagesSource< + Wococo, + Rococo, + WococoMessagesToRococo, + relay_wococo_client::runtime::WithRococoMessagesInstance, +>; /// Rococo node as messages target. -type RococoTargetClient = - SubstrateMessagesTarget; +type RococoTargetClient = SubstrateMessagesTarget< + Wococo, + Rococo, + WococoMessagesToRococo, + relay_rococo_client::runtime::WithWococoMessagesInstance, +>; /// Run Wococo-to-Rococo messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 88c8b529dcc61..2271d3e4f1447 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -19,12 +19,15 @@ //! chain. use crate::messages_lane::SubstrateMessageLane; +use crate::messages_target::SubstrateMessagesReceivingProof; use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; -use bp_messages::{LaneId, MessageNonce}; +use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::{messages::DispatchFeePayment, ChainId}; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use bridge_runtime_common::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, +}; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight}; use messages_relay::{ @@ -33,6 +36,7 @@ use messages_relay::{ ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState, }, }; +use num_traits::{Bounded, Zero}; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; @@ -45,23 +49,23 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { - client: Client, +pub struct SubstrateMessagesSource { + client: Client, lane: P, lane_id: LaneId, instance: ChainId, - target_to_source_headers_relay: Option>, + target_to_source_headers_relay: Option>, _phantom: PhantomData, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. pub fn new( - client: Client, + client: Client, lane: P, lane_id: LaneId, instance: ChainId, - target_to_source_headers_relay: Option>, + target_to_source_headers_relay: Option>, ) -> Self { SubstrateMessagesSource { client, @@ -74,7 +78,7 @@ impl SubstrateMessagesSource { } } -impl Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -88,9 +92,10 @@ impl Clone for SubstrateMessagesSource RelayClient for SubstrateMessagesSource +impl RelayClient for SubstrateMessagesSource where - C: Chain, + SC: Chain, + TC: Chain, P: SubstrateMessageLane, I: Send + Sync + Instance, { @@ -102,20 +107,22 @@ where } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient

for SubstrateMessagesSource where - C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, - C::BlockNumber: BlockNumberBase, + SC: Chain, + SC::Hash: Copy, + SC::BlockNumber: Copy, + SC::Balance: Decode + Bounded, + SC::Header: DeserializeOwned, + SC::Index: DeserializeOwned, + SC::BlockNumber: BlockNumberBase, + TC: Chain, P: SubstrateMessageLane< - MessagesProof = SubstrateMessagesProof, - SourceChainBalance = C::Balance, - SourceHeaderNumber = ::Number, - SourceHeaderHash = ::Hash, - SourceChain = C, + MessagesProof = SubstrateMessagesProof, + MessagesReceivingProof = SubstrateMessagesReceivingProof, + SourceChain = SC, + TargetChain = TC, >, - P::TargetChain: Chain, P::TargetHeaderNumber: Decode, P::TargetHeaderHash: Decode, I: Send + Sync + Instance, @@ -180,7 +187,7 @@ where ) .await?; - make_message_details_map::( + make_message_details_map::( Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?, nonces, ) @@ -242,10 +249,40 @@ where } async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance { - num_traits::Zero::zero() // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 + self.client + .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( + Zero::zero(), + HeaderId(Default::default(), Default::default()), + prepare_dummy_messages_delivery_proof::(), + )) + .await + .unwrap_or_else(|_| SC::Balance::max_value()) } } +/// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. +/// +/// We don't care about proof actually being the valid proof, because its validity doesn't +/// affect the call weight - we only care about its size. +fn prepare_dummy_messages_delivery_proof() -> SubstrateMessagesReceivingProof { + let single_message_confirmation_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint(SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1, 1) + .unwrap_or(u32::MAX); + let proof_size = TC::STORAGE_PROOF_OVERHEAD.saturating_add(single_message_confirmation_size); + ( + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + }, + FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: vec![vec![0; proof_size as usize]], + lane: Default::default(), + }, + ) +} + pub async fn read_client_state( self_client: &Client, best_finalized_header_id_method_name: &str, @@ -295,7 +332,7 @@ fn make_message_details_map( ) -> Result, SubstrateError> { let make_missing_nonce_error = |expected_nonce| { Err(SubstrateError::Custom(format!( - "Missing nonce {} in messages_dispatch_weight call result. Expected all nonces from {:?}", + "Missing nonce {} in message_details call result. Expected all nonces from {:?}", expected_nonce, nonces, ))) }; @@ -346,8 +383,7 @@ fn make_message_details_map( MessageDetails { dispatch_weight: details.dispatch_weight, size: details.size as _, - // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 - reward: num_traits::Zero::zero(), + reward: details.delivery_and_dispatch_fee, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, ); @@ -361,6 +397,9 @@ fn make_message_details_map( #[cfg(test)] mod tests { use super::*; + use bp_runtime::messages::DispatchFeePayment; + use relay_millau_client::Millau; + use relay_rialto_client::Rialto; fn message_details_from_rpc( nonces: RangeInclusive, @@ -469,4 +508,16 @@ mod tests { Err(SubstrateError::Custom(_)) )); } + + #[test] + fn prepare_dummy_messages_delivery_proof_works() { + let expected_minimal_size = Rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Millau::STORAGE_PROOF_OVERHEAD; + let dummy_proof = prepare_dummy_messages_delivery_proof::(); + assert!( + dummy_proof.1.encode().len() as u32 > expected_minimal_size, + "Expected proof size at least {}. Got: {}", + expected_minimal_size, + dummy_proof.1.encode().len(), + ); + } } diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index f74efbe61b5af..71f51c1e05502 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -19,24 +19,27 @@ //! chain. use crate::messages_lane::SubstrateMessageLane; -use crate::messages_source::read_client_state; +use crate::messages_source::{read_client_state, SubstrateMessagesProof}; use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; use bp_runtime::ChainId; -use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; +use bridge_runtime_common::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, +}; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight}; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; +use num_traits::{Bounded, One, Zero}; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase}; +use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; -use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use std::{marker::PhantomData, ops::RangeInclusive}; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, FixedPointNumber, FixedU128}; +use std::{convert::TryFrom, marker::PhantomData, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. pub type SubstrateMessagesReceivingProof = ( @@ -45,23 +48,23 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { - client: Client, +pub struct SubstrateMessagesTarget { + client: Client, lane: P, lane_id: LaneId, instance: ChainId, - source_to_target_headers_relay: Option>, + source_to_target_headers_relay: Option>, _phantom: PhantomData, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. pub fn new( - client: Client, + client: Client, lane: P, lane_id: LaneId, instance: ChainId, - source_to_target_headers_relay: Option>, + source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { client, @@ -74,7 +77,7 @@ impl SubstrateMessagesTarget { } } -impl Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -88,9 +91,10 @@ impl Clone for SubstrateMessagesTarget RelayClient for SubstrateMessagesTarget +impl RelayClient for SubstrateMessagesTarget where - C: Chain, + SC: Chain, + TC: Chain, P: SubstrateMessageLane, I: Send + Sync + Instance, { @@ -102,19 +106,22 @@ where } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient

for SubstrateMessagesTarget where - C: Chain, - C::Header: DeserializeOwned, - C::Index: DeserializeOwned, - ::Number: BlockNumberBase, + SC: Chain, + SC::Balance: TryFrom + Bounded, + TC: Chain, + TC::Hash: Copy, + TC::BlockNumber: Copy, + TC::Header: DeserializeOwned, + TC::Index: DeserializeOwned, + ::Number: BlockNumberBase, P: SubstrateMessageLane< - TargetChain = C, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - TargetHeaderNumber = ::Number, - TargetHeaderHash = ::Hash, + MessagesProof = SubstrateMessagesProof, + MessagesReceivingProof = SubstrateMessagesReceivingProof, + SourceChain = SC, + TargetChain = TC, >, - P::SourceChain: Chain, P::SourceHeaderNumber: Decode, P::SourceHeaderHash: Decode, I: Send + Sync + Instance, @@ -229,10 +236,93 @@ where async fn estimate_delivery_transaction_in_source_tokens( &self, - _nonces: RangeInclusive, - _total_dispatch_weight: Weight, - _total_size: u32, + nonces: RangeInclusive, + total_dispatch_weight: Weight, + total_size: u32, ) -> P::SourceChainBalance { - num_traits::Zero::zero() // TODO: https://github.com/paritytech/parity-bridges-common/issues/997 + // TODO: use actual rate (https://github.com/paritytech/parity-bridges-common/issues/997) + convert_target_tokens_to_source_tokens::( + FixedU128::one(), + self.client + .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( + Zero::zero(), + HeaderId(Default::default(), Default::default()), + nonces.clone(), + prepare_dummy_messages_proof::(nonces, total_dispatch_weight, total_size), + )) + .await + .unwrap_or_else(|_| TC::Balance::max_value()), + ) + } +} + +/// Prepare 'dummy' messages proof that will compose the delivery transaction. +/// +/// We don't care about proof actually being the valid proof, because its validity doesn't +/// affect the call weight - we only care about its size. +fn prepare_dummy_messages_proof( + nonces: RangeInclusive, + total_dispatch_weight: Weight, + total_size: u32, +) -> SubstrateMessagesProof { + ( + total_dispatch_weight, + FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof: vec![vec![0; SC::STORAGE_PROOF_OVERHEAD.saturating_add(total_size) as usize]], + lane: Default::default(), + nonces_start: *nonces.start(), + nonces_end: *nonces.end(), + }, + ) +} + +/// Given delivery transaction fee in target chain tokens and conversion rate to the source +/// chain tokens, compute transaction cost in source chain tokens. +fn convert_target_tokens_to_source_tokens( + target_to_source_conversion_rate: FixedU128, + target_transaction_fee: TC::Balance, +) -> SC::Balance +where + SC::Balance: TryFrom, +{ + SC::Balance::try_from(target_to_source_conversion_rate.saturating_mul_int(target_transaction_fee)) + .unwrap_or_else(|_| SC::Balance::max_value()) +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_millau_client::Millau; + use relay_rialto_client::Rialto; + + #[test] + fn prepare_dummy_messages_proof_works() { + const DISPATCH_WEIGHT: Weight = 1_000_000; + const SIZE: u32 = 1_000; + let dummy_proof = prepare_dummy_messages_proof::(1..=10, DISPATCH_WEIGHT, SIZE); + assert_eq!(dummy_proof.0, DISPATCH_WEIGHT); + assert!( + dummy_proof.1.encode().len() as u32 > SIZE, + "Expected proof size at least {}. Got: {}", + SIZE, + dummy_proof.1.encode().len(), + ); + } + + #[test] + fn convert_target_tokens_to_source_tokens_works() { + assert_eq!( + convert_target_tokens_to_source_tokens::((150, 100).into(), 1_000), + 1_500 + ); + assert_eq!( + convert_target_tokens_to_source_tokens::((50, 100).into(), 1_000), + 500 + ); + assert_eq!( + convert_target_tokens_to_source_tokens::((100, 100).into(), 1_000), + 1_000 + ); } } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index f2fba32dc1ed0..01869fb7b1c4b 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -36,6 +36,8 @@ impl ChainBase for Kusama { impl Chain for Kusama { const NAME: &'static str = "Kusama"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = bp_kusama::AccountId; type Index = bp_kusama::Nonce; diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index e16f06f8528b6..5f40e1e557ffe 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -13,6 +13,7 @@ relay-utils = { path = "../utils" } # Supported Chains +bp-millau = { path = "../../primitives/chain-millau" } millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 8597d9e59200f..ac4368392c163 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -39,6 +39,8 @@ impl ChainBase for Millau { impl Chain for Millau { const NAME: &'static str = "Millau"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); + const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = millau_runtime::AccountId; type Index = millau_runtime::Index; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index e502463187d2c..04ddce29d091d 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -36,6 +36,8 @@ impl ChainBase for Polkadot { impl Chain for Polkadot { const NAME: &'static str = "Polkadot"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = bp_polkadot::AccountId; type Index = bp_polkadot::Nonce; diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 88e8e12add401..a1c30da389a2a 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -13,6 +13,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies +bp-rialto = { path = "../../primitives/chain-rialto" } rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 4a0023a87c4f5..646d7629238c3 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -39,6 +39,8 @@ impl ChainBase for Rialto { impl Chain for Rialto { const NAME: &'static str = "Rialto"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); + const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = rialto_runtime::AccountId; type Index = rialto_runtime::Index; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5a7d8999f7f16..4d4812e459c75 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -44,6 +44,8 @@ impl ChainBase for Rococo { impl Chain for Rococo { const NAME: &'static str = "Rococo"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = bp_rococo::AccountId; type Index = bp_rococo::Index; diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index f5c2e26560593..4d7b6a047287d 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -29,9 +29,12 @@ relay-utils = { path = "../utils" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 4cc8a0394d9ad..63432c9701fc3 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -17,14 +17,15 @@ use bp_runtime::Chain as ChainBase; use frame_support::Parameter; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; -use num_traits::{CheckedSub, SaturatingAdd, Zero}; +use num_traits::{Bounded, CheckedSub, SaturatingAdd, Zero}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, traits::{ - AtLeast32Bit, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member, + AtLeast32Bit, AtLeast32BitUnsigned, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, + MaybeSerializeDeserialize, Member, }, - EncodedJustification, + EncodedJustification, FixedPointOperand, }; use std::{fmt::Debug, time::Duration}; @@ -37,6 +38,10 @@ pub trait Chain: ChainBase + Clone { /// How often blocks are produced on that chain. It's suggested to set this value /// to match the block time of the chain. const AVERAGE_BLOCK_INTERVAL: Duration; + /// Maximal expected storage proof overhead (in bytes). + const STORAGE_PROOF_OVERHEAD: u32; + /// Maximal size (in bytes) of SCALE-encoded account id on this chain. + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32; /// The user account identifier type for the runtime. type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; @@ -58,7 +63,20 @@ pub trait Chain: ChainBase + Clone { /// /// The chain may suport 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: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + SaturatingAdd + Zero; + type Balance: AtLeast32BitUnsigned + + FixedPointOperand + + Parameter + + Parameter + + Member + + DeserializeOwned + + Clone + + Copy + + Bounded + + CheckedSub + + PartialOrd + + SaturatingAdd + + Zero + + std::convert::TryFrom; } /// Substrate-based chain with `frame_system::Config::AccountData` set to diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index f0b7158ecbe37..87917c022c730 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -25,12 +25,14 @@ use codec::Decode; use frame_system::AccountInfo; use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned}; use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; -use num_traits::Zero; +use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; +use pallet_transaction_payment::InclusionFee; use relay_utils::relay_loop::RECONNECT_DELAY; use sp_core::{storage::StorageKey, Bytes}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; +use std::convert::TryFrom; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; @@ -258,6 +260,26 @@ impl Client { Ok(tx_hash) } + /// Estimate fee that will be spent on given extrinsic. + pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result { + let fee_details = Substrate::::payment_query_fee_details(&*self.client, transaction, None).await?; + let inclusion_fee = fee_details + .inclusion_fee + .map(|inclusion_fee| { + InclusionFee { + base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + } + .inclusion_fee() + }) + .unwrap_or_else(Zero::zero); + Ok(inclusion_fee) + } + /// Get the GRANDPA authority set at given block. pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index c6e191ce078ff..e7159bf27109e 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -185,6 +185,8 @@ mod tests { impl Chain for TestChain { const NAME: &'static str = "Test"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); + const STORAGE_PROOF_OVERHEAD: u32 = 0; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; type AccountId = u32; type Index = u32; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 06df1f705d093..ddc8c92f77b4b 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -18,11 +18,13 @@ use crate::chain::Chain; +use pallet_transaction_payment_rpc_runtime_api::FeeDetails; use sc_rpc_api::{state::ReadProof, system::Health}; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, }; +use sp_rpc::number::NumberOrHex; use sp_version::RuntimeVersion; jsonrpsee_proc_macros::rpc_client_api! { @@ -49,5 +51,7 @@ jsonrpsee_proc_macros::rpc_client_api! { fn state_prove_storage(keys: Vec, hash: Option) -> ReadProof; #[rpc(method = "state_getRuntimeVersion", positional_params)] fn state_runtime_version() -> RuntimeVersion; + #[rpc(method = "payment_queryFeeDetails", positional_params)] + fn payment_query_fee_details(extrinsic: Bytes, at_block: Option) -> FeeDetails; } } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 6768b81f10f8c..b2347da502e5a 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -42,6 +42,8 @@ impl ChainBase for Westend { impl Chain for Westend { const NAME: &'static str = "Westend"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = bp_westend::AccountId; type Index = bp_westend::Nonce; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 8ceba7c7c436d..3ef55223b527e 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -44,6 +44,8 @@ impl ChainBase for Wococo { impl Chain for Wococo { const NAME: &'static str = "Wococo"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type AccountId = bp_wococo::AccountId; type Index = bp_wococo::Index; From 89fa1480f0f55fa280c4c39dccb8500fd44828a7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 29 Jun 2021 14:24:54 +0300 Subject: [PATCH 0501/1210] Shared reference to conversion rate metric value (#1034) * shared conversion rate metric value * clippy --- relays/bin-ethereum/Cargo.toml | 1 + relays/bin-ethereum/src/ethereum_exchange.rs | 4 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 2 +- .../bin-ethereum/src/substrate_sync_loop.rs | 2 +- .../src/chains/millau_messages_to_rialto.rs | 59 +++++------- relays/bin-substrate/src/chains/mod.rs | 56 ++++++------ .../src/chains/rialto_messages_to_millau.rs | 59 +++++------- .../src/chains/rococo_messages_to_wococo.rs | 40 ++++---- .../src/chains/wococo_messages_to_rococo.rs | 40 ++++---- .../src/cli/relay_headers_and_messages.rs | 18 +++- relays/bin-substrate/src/messages_lane.rs | 91 ++++++++++++++++++- relays/exchange/Cargo.toml | 1 + relays/exchange/src/exchange_loop.rs | 2 +- relays/finality/Cargo.toml | 1 + relays/finality/src/finality_loop.rs | 2 +- relays/headers/Cargo.toml | 1 + relays/headers/src/sync_loop.rs | 2 +- relays/messages/Cargo.toml | 1 + relays/messages/src/message_lane_loop.rs | 2 +- relays/utils/Cargo.toml | 1 + relays/utils/src/metrics.rs | 4 + relays/utils/src/metrics/float_json_value.rs | 15 ++- relays/utils/src/relay_loop.rs | 17 ++-- 23 files changed, 260 insertions(+), 161 deletions(-) diff --git a/relays/bin-ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml index efd9c0194b28c..e4620efe32554 100644 --- a/relays/bin-ethereum/Cargo.toml +++ b/relays/bin-ethereum/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" +anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index 3111aa2de4363..73a107cb40655 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -355,7 +355,7 @@ async fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_has async fn run_auto_transactions_relay_loop( params: EthereumExchangeParams, eth_start_with_block_number: Option, -) -> Result<(), String> { +) -> anyhow::Result<()> { let EthereumExchangeParams { eth_params, sub_params, @@ -375,7 +375,7 @@ async fn run_auto_transactions_relay_loop( .best_ethereum_finalized_block() .await .map_err(|err| { - format!( + anyhow::format_err!( "Error retrieving best finalized Ethereum block from Substrate node: {:?}", err ) diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index 111abcd86e710..c4a5f5102a733 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -292,7 +292,7 @@ pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { futures::future::pending(), ) .await - .map_err(RpcError::SyncLoop)?; + .map_err(|e| RpcError::SyncLoop(e.to_string()))?; Ok(()) } diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index 542fd41f72732..7924661244767 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -194,7 +194,7 @@ pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { futures::future::pending(), ) .await - .map_err(RpcError::SyncLoop)?; + .map_err(|e| RpcError::SyncLoop(e.to_string()))?; Ok(()) } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 9932d16a4242c..5231aaa9a2a98 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -17,7 +17,8 @@ //! Millau-to-Rialto messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -30,10 +31,8 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - Chain, TransactionSignScheme, -}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -136,7 +135,7 @@ type RialtoTargetClient = /// Run Millau-to-Rialto messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); @@ -172,6 +171,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -202,36 +202,25 @@ pub async fn run( MILLAU_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - MillauMessagesToRialto, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "millau_storage_proof_overhead".into(), - "Millau storage proof overhead".into(), - ) - })? - .standalone_metric(|registry, prefix| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - registry, - prefix, - source_client, - sp_core::storage::StorageKey( - millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec(), - ), - Some(millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE), - "millau_rialto_to_millau_conversion_rate".into(), - "Rialto to Millau tokens conversion rate (used by Rialto)".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Millau -> Rialto messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + Some(( + sp_core::storage::StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), + millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, + )), + ) +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 09d3c3e9c060a..7c624179b934e 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -32,38 +32,38 @@ mod rococo; mod westend; mod wococo; -use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; +use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams, PrometheusError, Registry}; pub(crate) fn add_polkadot_kusama_price_metrics( params: MetricsParams, ) -> anyhow::Result { - Ok( - relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) - // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama - // relays, but we want to test metrics/dashboards in advance - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=btc".into(), - "$.polkadot.btc".into(), - "polkadot_to_base_conversion_rate".into(), - "Rate used to convert from DOT to some BASE tokens".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=btc".into(), - "$.kusama.btc".into(), - "kusama_to_base_conversion_rate".into(), - "Rate used to convert from KSM to some BASE tokens".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .into_params(), + // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama + // relays, but we want to test metrics/dashboards in advance + Ok(relay_utils::relay_metrics(None, params) + .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "polkadot"))? + .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "kusama"))? + .into_params()) +} + +/// Creates standalone token price metric. +pub(crate) fn token_price_metric( + registry: &Registry, + prefix: Option<&str>, + token_id: &str, +) -> Result { + FloatJsonValueMetric::new( + registry, + prefix, + format!( + "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", + token_id + ), + format!("$.{}.btc", token_id), + format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), + format!( + "Rate used to convert from {} to some BASE tokens", + token_id.to_uppercase() + ), ) } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index f472703993ac5..e491a14caf426 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -17,7 +17,8 @@ //! Rialto-to-Millau messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -30,10 +31,8 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - Chain, TransactionSignScheme, -}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -136,7 +135,7 @@ type MillauTargetClient = /// Run Rialto-to-Millau messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); @@ -171,6 +170,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -201,36 +201,25 @@ pub async fn run( RIALTO_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - RialtoMessagesToMillau, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "rialto_storage_proof_overhead".into(), - "Rialto storage proof overhead".into(), - ) - })? - .standalone_metric(|registry, prefix| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - registry, - prefix, - source_client, - sp_core::storage::StorageKey( - rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec(), - ), - Some(rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE), - "rialto_millau_to_rialto_conversion_rate".into(), - "Millau to Rialto tokens conversion rate (used by Millau)".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Rialto -> Millau messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + Some(( + sp_core::storage::StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), + rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, + )), + ) +} diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index f8da60cf1738e..e30896dd5ff67 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -17,7 +17,8 @@ //! Rococo-to-Wococo messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -28,7 +29,8 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -142,7 +144,7 @@ type WococoTargetClient = SubstrateMessagesTarget< /// Run Rococo-to-Wococo messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); @@ -183,6 +185,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -213,23 +216,22 @@ pub async fn run( ROCOCO_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - RococoMessagesToWococo, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "rococo_storage_proof_overhead".into(), - "Rococo storage proof overhead".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Rococo -> Wococo messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + None, + ) +} diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 2e65328831a24..3c280c3f5bf6b 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -17,7 +17,8 @@ //! Wococo-to-Rococo messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -28,7 +29,8 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -142,7 +144,7 @@ type RococoTargetClient = SubstrateMessagesTarget< /// Run Wococo-to-Rococo messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); @@ -183,6 +185,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -213,23 +216,22 @@ pub async fn run( WOCOCO_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - WococoMessagesToRococo, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "wococo_storage_proof_overhead".into(), - "Wococo storage proof overhead".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Wococo -> Rococo messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + None, + ) +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index e71ea6aeaa2f8..31accb15a4bda 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -100,8 +100,12 @@ macro_rules! select_bridge { const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; - use crate::chains::millau_messages_to_rialto::run as left_to_right_messages; - use crate::chains::rialto_messages_to_millau::run as right_to_left_messages; + use crate::chains::millau_messages_to_rialto::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, + }; + use crate::chains::rialto_messages_to_millau::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + }; $generic } @@ -120,8 +124,12 @@ macro_rules! select_bridge { const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; - use crate::chains::rococo_messages_to_wococo::run as left_to_right_messages; - use crate::chains::wococo_messages_to_rococo::run as right_to_left_messages; + use crate::chains::rococo_messages_to_wococo::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, + }; + use crate::chains::wococo_messages_to_rococo::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + }; $generic } @@ -153,6 +161,8 @@ impl RelayHeadersAndMessages { let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); + let (metrics_params, _) = add_left_to_right_standalone_metrics(metrics_params, left_client.clone())?; + let (metrics_params, _) = add_right_to_left_standalone_metrics(metrics_params, right_client.clone())?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 7efea545f9a6d..7954319a75621 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -21,9 +21,16 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use bp_messages::{LaneId, MessageNonce}; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use relay_substrate_client::{BlockNumberOf, Chain, Client, HashOf}; -use relay_utils::{metrics::MetricsParams, BlockNumberBase}; -use sp_core::Bytes; +use relay_substrate_client::{ + metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, + BlockNumberOf, Chain, Client, HashOf, +}; +use relay_utils::{ + metrics::{F64SharedRef, MetricsParams}, + BlockNumberBase, +}; +use sp_core::{storage::StorageKey, Bytes}; +use sp_runtime::FixedU128; use std::ops::RangeInclusive; /// Substrate <-> Substrate messages relay parameters. @@ -185,6 +192,84 @@ pub fn select_delivery_transaction_limits chain token conversion rate. + pub target_to_base_conversion_rate: Option, + /// Shared reference to the actual source -> chain token conversion rate. + pub source_to_base_conversion_rate: Option, +} + +/// Add general standalone metrics for the message lane relay loop. +pub fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, + source_chain_token_id: Option<&str>, + target_chain_token_id: Option<&str>, + target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + let mut source_to_base_conversion_rate = None; + let mut target_to_base_conversion_rate = None; + let mut metrics_params = + relay_utils::relay_metrics(None, metrics_params).standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::SourceChain::NAME), + ) + })?; + if let Some((target_to_source_conversion_rate_storage_key, initial_target_to_source_conversion_rate)) = + target_to_source_conversion_rate_params + { + metrics_params = metrics_params.standalone_metric(|registry, prefix| { + let metric = FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + registry, + prefix, + source_client, + target_to_source_conversion_rate_storage_key, + Some(initial_target_to_source_conversion_rate), + format!( + "{}_{}_to_{}_conversion_rate", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::SourceChain::NAME + ), + )?; + Ok(metric) + })?; + } + if let Some(source_chain_token_id) = source_chain_token_id { + metrics_params = metrics_params.standalone_metric(|registry, prefix| { + let metric = crate::chains::token_price_metric(registry, prefix, source_chain_token_id)?; + source_to_base_conversion_rate = Some(metric.shared_value_ref()); + Ok(metric) + })?; + } + if let Some(target_chain_token_id) = target_chain_token_id { + metrics_params = metrics_params.standalone_metric(|registry, prefix| { + let metric = crate::chains::token_price_metric(registry, prefix, target_chain_token_id)?; + target_to_base_conversion_rate = Some(metric.shared_value_ref()); + Ok(metric) + })?; + } + Ok(( + metrics_params.into_params(), + StandaloneMessagesMetrics { + source_to_base_conversion_rate, + target_to_base_conversion_rate, + }, + )) +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/exchange/Cargo.toml b/relays/exchange/Cargo.toml index 62e7a029bbb2c..b8bb8481f616d 100644 --- a/relays/exchange/Cargo.toml +++ b/relays/exchange/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 8da4c3f45687d..0c13f1b5e5259 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -90,7 +90,7 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 944da9837ffcb..3ecda234db3ef 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" [dependencies] +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 3ea729d123e7d..462632fa3fed0 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -104,7 +104,7 @@ pub async fn run( sync_params: FinalitySyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) diff --git a/relays/headers/Cargo.toml b/relays/headers/Cargo.toml index 31d3166a99781..8eda40e9356f8 100644 --- a/relays/headers/Cargo.toml +++ b/relays/headers/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index b204932056509..5ccec4bbab555 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -126,7 +126,7 @@ pub async fn run>( sync_params: HeadersSyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index ea5d46845c5a3..8fc0e7c4f19e6 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" futures = "0.3.5" diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index c87c024f39767..7ad5952603fcb 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -258,7 +258,7 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: MetricsParams, exit_signal: impl Future + Send + 'static, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ff80cab533813..ea5f33b77e85b 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index c0eaeae337ee1..4855dba8ea246 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -21,12 +21,16 @@ pub use substrate_prometheus_endpoint::{ register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, U64, }; +use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use std::{fmt::Debug, time::Duration}; mod float_json_value; mod global; +/// Shared reference to `f64` value that is updated by the metric. +pub type F64SharedRef = Arc>>; + /// Unparsed address that needs to be used to expose Prometheus metrics. #[derive(Debug, Clone)] pub struct MetricsAddress { diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index d61f9cac7c224..2a18df2aac7e1 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; +use crate::metrics::{metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; +use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use std::time::Duration; @@ -28,6 +29,7 @@ pub struct FloatJsonValueMetric { url: String, json_path: String, metric: Gauge, + shared_value_ref: F64SharedRef, } impl FloatJsonValueMetric { @@ -40,13 +42,20 @@ impl FloatJsonValueMetric { name: String, help: String, ) -> Result { + let shared_value_ref = Arc::new(RwLock::new(None)); Ok(FloatJsonValueMetric { url, json_path, metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + shared_value_ref, }) } + /// Get shared reference to metric value. + pub fn shared_value_ref(&self) -> F64SharedRef { + self.shared_value_ref.clone() + } + /// Read value from HTTP service. async fn read_value(&self) -> Result { use isahc::{AsyncReadResponseExt, HttpClient, Request}; @@ -79,7 +88,9 @@ impl StandaloneMetrics for FloatJsonValueMetric { } async fn update(&self) { - crate::metrics::set_gauge_value(&self.metric, self.read_value().await.map(Some)); + let value = self.read_value().await; + crate::metrics::set_gauge_value(&self.metric, value.clone().map(Some)); + *self.shared_value_ref.write().await = value.ok(); } } diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 938136658bd31..ea9d62752110e 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -105,7 +105,7 @@ impl Loop { /// This function represents an outer loop, which in turn calls provided `run_loop` function to do /// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, /// target or both) and calls `run_loop` again. - pub async fn run(mut self, loop_name: String, run_loop: R) -> Result<(), String> + pub async fn run(mut self, loop_name: String, run_loop: R) -> anyhow::Result<()> where R: 'static + Send + Fn(SC, TC, Option) -> F, F: 'static + Send + Future>, @@ -151,8 +151,8 @@ impl LoopMetrics { pub fn loop_metric( self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> Result, String> { - let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref()).map_err(|e| e.to_string())?; + ) -> anyhow::Result> { + let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref())?; Ok(LoopMetrics { relay_loop: self.relay_loop, @@ -167,13 +167,13 @@ impl LoopMetrics { pub fn standalone_metric( self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> Result { + ) -> anyhow::Result { // since standalone metrics are updating themselves, we may just ignore the fact that the same // standalone metric is exposed by several loops && only spawn single metric match create_metric(&self.registry, self.metrics_prefix.as_deref()) { Ok(standalone_metrics) => standalone_metrics.spawn(), Err(PrometheusError::AlreadyReg) => (), - Err(e) => return Err(e.to_string()), + Err(e) => anyhow::bail!(e), } Ok(self) @@ -191,13 +191,14 @@ impl LoopMetrics { /// Expose metrics using address passed at creation. /// /// If passed `address` is `None`, metrics are not exposed. - pub async fn expose(self) -> Result, String> { + pub async fn expose(self) -> anyhow::Result> { if let Some(address) = self.address { let socket_addr = SocketAddr::new( address.host.parse().map_err(|err| { - format!( + anyhow::format_err!( "Invalid host {} is used to expose Prometheus metrics: {}", - address.host, err, + address.host, + err, ) })?, address.port, From f5ad925177635e82556e9226ad49ffbf4f2e0fb0 Mon Sep 17 00:00:00 2001 From: halfpint104 <86686693+halfpint104@users.noreply.github.com> Date: Wed, 30 Jun 2021 17:58:21 +0100 Subject: [PATCH 0502/1210] Use kebab-case for bridge arguments (#1036) * Updates bridge CLI arguments to be kebab case * Updates scripts to use kebab case for bridge initialisation and relaying of headers/messages * Updates message sending subcommand to be kebab case * Updates documentation for message sending subcommand --- README.md | 4 +-- relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/cli/bridge.rs | 21 ++++++++-------- .../bin-substrate/src/cli/derive_account.rs | 9 ++++--- relays/bin-substrate/src/cli/encode_call.rs | 13 +++++----- .../bin-substrate/src/cli/encode_message.rs | 7 +++--- relays/bin-substrate/src/cli/estimate_fee.rs | 5 ++-- relays/bin-substrate/src/cli/init_bridge.rs | 25 +++++++++---------- relays/bin-substrate/src/cli/relay_headers.rs | 25 +++++++++---------- .../bin-substrate/src/cli/relay_messages.rs | 4 +-- relays/bin-substrate/src/cli/send_message.rs | 9 ++++--- 11 files changed, 63 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index b407f203b7427..40aa85973f3bd 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ Then we need to initialize and run the relayer: ```bash docker run --network=host -it \ - paritytech/substrate-relay init-bridge RialtoToMillau \ + paritytech/substrate-relay init-bridge rialto-to-millau \ --target-host localhost \ --target-port 9945 \ --source-host localhost \ @@ -167,7 +167,7 @@ docker run --network=host -it \ --target-signer //Alice docker run --network=host -it \ - paritytech/substrate-relay relay-headers RialtoToMillau \ + paritytech/substrate-relay relay-headers rialto-to-millau \ --target-host localhost \ --target-port 9945 \ --source-host localhost \ diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 3bbf05f3b1c56..1e38a33e9ddd8 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -17,6 +17,7 @@ num-format = "0.4" num-traits = "0.2" paste = "1.0" structopt = "0.3" +strum = { version = "0.21.0", features = ["derive"] } # Bridge dependencies diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 1feb3dcb1a46d..30950b289f5fc 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -14,17 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use structopt::clap::arg_enum; - -arg_enum! { - #[derive(Debug, PartialEq, Eq)] - /// Supported full bridges (headers + messages). - pub enum FullBridge { - MillauToRialto, - RialtoToMillau, - RococoToWococo, - WococoToRococo, - } +use strum::{EnumString, EnumVariantNames}; + +#[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Supported full bridges (headers + messages). +pub enum FullBridge { + MillauToRialto, + RialtoToMillau, + RococoToWococo, + WococoToRococo, } impl FullBridge { diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs index dff62c21f6fea..f1967df8c7452 100644 --- a/relays/bin-substrate/src/cli/derive_account.rs +++ b/relays/bin-substrate/src/cli/derive_account.rs @@ -18,6 +18,7 @@ use crate::cli::{bridge::FullBridge, AccountId}; use crate::select_full_bridge; use relay_substrate_client::Chain; use structopt::StructOpt; +use strum::VariantNames; /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. /// @@ -28,7 +29,7 @@ use structopt::StructOpt; #[derive(StructOpt)] pub struct DeriveAccount { /// A bridge instance to initalize. - #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, /// Source-chain address to derive Target-chain address from. account: AccountId, @@ -80,9 +81,9 @@ mod tests { let millau = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"; // when - let (rialto_parsed, rialto_derived) = derive_account_cli("RialtoToMillau", rialto); - let (millau_parsed, millau_derived) = derive_account_cli("MillauToRialto", millau); - let (millau2_parsed, millau2_derived) = derive_account_cli("MillauToRialto", rialto); + let (rialto_parsed, rialto_derived) = derive_account_cli("rialto-to-millau", rialto); + let (millau_parsed, millau_derived) = derive_account_cli("millau-to-rialto", millau); + let (millau2_parsed, millau2_derived) = derive_account_cli("millau-to-rialto", rialto); // then assert_eq!(format!("{}", rialto_parsed), rialto); diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index cfe6d99a4eb9f..1ae636623b047 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -20,12 +20,13 @@ use crate::select_full_bridge; use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; +use strum::VariantNames; /// Encode source chain runtime call. #[derive(StructOpt, Debug)] pub struct EncodeCall { /// A bridge instance to encode call for. - #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, #[structopt(flatten)] call: Call, @@ -194,7 +195,7 @@ mod tests { // given let mut encode_call = EncodeCall::from_iter(vec![ "encode-call", - "RialtoToMillau", + "rialto-to-millau", "transfer", "--amount", "12345", @@ -215,7 +216,7 @@ mod tests { #[test] fn should_encode_remark_with_default_payload() { // given - let mut encode_call = EncodeCall::from_iter(vec!["encode-call", "RialtoToMillau", "remark"]); + let mut encode_call = EncodeCall::from_iter(vec!["encode-call", "rialto-to-millau", "remark"]); // when let hex = encode_call.encode().unwrap(); @@ -229,7 +230,7 @@ mod tests { // given let mut encode_call = EncodeCall::from_iter(vec![ "encode-call", - "RialtoToMillau", + "rialto-to-millau", "remark", "--remark-payload", "1234", @@ -246,7 +247,7 @@ mod tests { fn should_encode_remark_with_size() { // given let mut encode_call = - EncodeCall::from_iter(vec!["encode-call", "RialtoToMillau", "remark", "--remark-size", "12"]); + EncodeCall::from_iter(vec!["encode-call", "rialto-to-millau", "remark", "--remark-size", "12"]); // when let hex = encode_call.encode().unwrap(); @@ -260,7 +261,7 @@ mod tests { // when let err = EncodeCall::from_iter_safe(vec![ "encode-call", - "RialtoToMillau", + "rialto-to-millau", "remark", "--remark-payload", "1234", diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 213c8377678f9..a2d8a422b5dcf 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -17,6 +17,7 @@ use crate::cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}; use crate::select_full_bridge; use structopt::StructOpt; +use strum::VariantNames; /// Generic message payload. #[derive(StructOpt, Debug, PartialEq, Eq)] @@ -41,7 +42,7 @@ pub enum MessagePayload { #[derive(StructOpt)] pub struct EncodeMessage { /// A bridge instance to initalize. - #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, #[structopt(flatten)] payload: MessagePayload, @@ -73,7 +74,7 @@ mod tests { fn should_encode_raw_message() { // given let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"; - let encode_message = EncodeMessage::from_iter(vec!["encode-message", "MillauToRialto", "raw", msg]); + let encode_message = EncodeMessage::from_iter(vec!["encode-message", "rialto-to-millau", "raw", msg]); // when let hex = encode_message.encode().unwrap(); @@ -88,7 +89,7 @@ mod tests { let sender = sp_keyring::AccountKeyring::Alice.to_account_id().to_ss58check(); let encode_message = EncodeMessage::from_iter(vec![ "encode-message", - "RialtoToMillau", + "rialto-to-millau", "call", "--sender", &sender, diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 129699c26917c..2fa7918fafd2d 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -20,12 +20,13 @@ use crate::select_full_bridge; use codec::{Decode, Encode}; use relay_substrate_client::Chain; use structopt::StructOpt; +use strum::VariantNames; /// Estimate Delivery & Dispatch Fee command. #[derive(StructOpt, Debug, PartialEq, Eq)] pub struct EstimateFee { /// A bridge instance to encode call for. - #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, #[structopt(flatten)] source: SourceConnectionParams, @@ -93,7 +94,7 @@ mod tests { // when let res = EstimateFee::from_iter(vec![ "estimate_fee", - "RialtoToMillau", + "rialto-to-millau", "--source-port", "1234", "call", diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 20e6daa500e56..1ff39ede5cea6 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -20,13 +20,14 @@ use bp_runtime::Chain as ChainBase; use codec::Encode; use relay_substrate_client::{Chain, TransactionSignScheme}; use sp_core::{Bytes, Pair}; -use structopt::{clap::arg_enum, StructOpt}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; /// Initialize bridge pallet. #[derive(StructOpt)] pub struct InitBridge { /// A bridge instance to initalize. - #[structopt(possible_values = &InitBridgeName::variants(), case_insensitive = true)] + #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] bridge: InitBridgeName, #[structopt(flatten)] source: SourceConnectionParams, @@ -36,17 +37,15 @@ pub struct InitBridge { target_sign: TargetSigningParams, } -// TODO [#851] Use kebab-case. -arg_enum! { - #[derive(Debug)] - /// Bridge to initialize. - pub enum InitBridgeName { - MillauToRialto, - RialtoToMillau, - WestendToMillau, - RococoToWococo, - WococoToRococo, - } +#[derive(Debug, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Bridge to initialize. +pub enum InitBridgeName { + MillauToRialto, + RialtoToMillau, + WestendToMillau, + RococoToWococo, + WococoToRococo, } macro_rules! select_bridge { diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index ec521c2918d85..0f699ff9787b4 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -16,13 +16,14 @@ use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; use crate::finality_pipeline::SubstrateFinalitySyncPipeline; -use structopt::{clap::arg_enum, StructOpt}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; /// Start headers relayer process. #[derive(StructOpt)] pub struct RelayHeaders { /// A bridge instance to relay headers for. - #[structopt(possible_values = &RelayHeadersBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = RelayHeadersBridge::VARIANTS, case_insensitive = true)] bridge: RelayHeadersBridge, /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed. #[structopt(long)] @@ -37,17 +38,15 @@ pub struct RelayHeaders { prometheus_params: PrometheusParams, } -// TODO [#851] Use kebab-case. -arg_enum! { - #[derive(Debug)] - /// Headers relay bridge. - pub enum RelayHeadersBridge { - MillauToRialto, - RialtoToMillau, - WestendToMillau, - RococoToWococo, - WococoToRococo, - } +#[derive(Debug, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Headers relay bridge. +pub enum RelayHeadersBridge { + MillauToRialto, + RialtoToMillau, + WestendToMillau, + RococoToWococo, + WococoToRococo, } macro_rules! select_bridge { diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 94630886ca38e..e798888f4ca3f 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -21,14 +21,14 @@ use crate::cli::{ }; use crate::messages_lane::MessagesRelayParams; use crate::select_full_bridge; - use structopt::StructOpt; +use strum::VariantNames; /// Start messages relayer process. #[derive(StructOpt)] pub struct RelayMessages { /// A bridge instance to relay messages for. - #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index f710f814e41d9..ab802546442ec 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -30,12 +30,13 @@ use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; use std::fmt::Debug; use structopt::StructOpt; +use strum::VariantNames; /// Send bridge message. #[derive(StructOpt)] pub struct SendMessage { /// A bridge instance to encode call for. - #[structopt(possible_values = &FullBridge::variants(), case_insensitive = true)] + #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, #[structopt(flatten)] source: SourceConnectionParams, @@ -260,7 +261,7 @@ mod tests { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", - "RialtoToMillau", + "rialto-to-millau", "--source-port", "1234", "--source-signer", @@ -291,7 +292,7 @@ mod tests { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", - "MillauToRialto", + "millau-to-rialto", "--source-port", "1234", "--source-signer", @@ -335,7 +336,7 @@ mod tests { // given let send_message = SendMessage::from_iter_safe(vec![ "send-message", - "MillauToRialto", + "rialto-to-millau", "--source-port", "1234", "--source-signer", From 3221b4f8b8cf062be8fd10a96207899c63b59097 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 1 Jul 2021 08:24:17 +0300 Subject: [PATCH 0503/1210] fixed metrics prefix (#1037) --- .../src/chains/millau_messages_to_rialto.rs | 10 +++++++++- relays/bin-substrate/src/chains/mod.rs | 3 ++- .../src/chains/rialto_messages_to_millau.rs | 10 +++++++++- .../src/chains/rococo_headers_to_wococo.rs | 2 +- .../src/chains/rococo_messages_to_wococo.rs | 10 +++++++++- .../src/chains/westend_headers_to_millau.rs | 2 +- .../src/chains/wococo_headers_to_rococo.rs | 2 +- .../src/chains/wococo_messages_to_rococo.rs | 10 +++++++++- .../src/cli/relay_headers_and_messages.rs | 4 ++-- relays/bin-substrate/src/messages_lane.rs | 3 ++- 10 files changed, 45 insertions(+), 11 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 5231aaa9a2a98..77f1adbd3744d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -171,7 +171,13 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; + let (metrics_params, _) = add_standalone_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + MillauMessagesToRialto, + >(&lane_id)), + params.metrics_params, + source_client.clone(), + )?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -210,10 +216,12 @@ pub async fn run( /// Add standalone metrics for the Millau -> Rialto messages loop. pub(crate) fn add_standalone_metrics( + metrics_prefix: Option, metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { crate::messages_lane::add_standalone_metrics::( + metrics_prefix, metrics_params, source_client, None, diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 7c624179b934e..b79bfcaaad21e 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -35,11 +35,12 @@ mod wococo; use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams, PrometheusError, Registry}; pub(crate) fn add_polkadot_kusama_price_metrics( + prefix: Option, params: MetricsParams, ) -> anyhow::Result { // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama // relays, but we want to test metrics/dashboards in advance - Ok(relay_utils::relay_metrics(None, params) + Ok(relay_utils::relay_metrics(prefix, params) .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "polkadot"))? .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "kusama"))? .into_params()) diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index e491a14caf426..8a82456cdf289 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -170,7 +170,13 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; + let (metrics_params, _) = add_standalone_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + RialtoMessagesToMillau, + >(&lane_id)), + params.metrics_params, + source_client.clone(), + )?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -209,10 +215,12 @@ pub async fn run( /// Add standalone metrics for the Rialto -> Millau messages loop. pub(crate) fn add_standalone_metrics( + metrics_prefix: Option, metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { crate::messages_lane::add_standalone_metrics::( + metrics_prefix, metrics_params, source_client, None, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index c7f60100f13c1..026c918bec494 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -36,7 +36,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { type TargetChain = Wococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) + crate::chains::add_polkadot_kusama_price_metrics::(Some(finality_relay::metrics_prefix::()), params) } fn start_relay_guards(&self) { diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index e30896dd5ff67..1e30f97f49405 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -185,7 +185,13 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; + let (metrics_params, _) = add_standalone_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + RococoMessagesToWococo, + >(&lane_id)), + params.metrics_params, + source_client.clone(), + )?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -224,10 +230,12 @@ pub async fn run( /// Add standalone metrics for the Rococo -> Wococo messages loop. pub(crate) fn add_standalone_metrics( + metrics_prefix: Option, metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { crate::messages_lane::add_standalone_metrics::( + metrics_prefix, metrics_params, source_client, None, diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 1523dc1be584c..f0395dc10d8d9 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -35,7 +35,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) + crate::chains::add_polkadot_kusama_price_metrics::(Some(finality_relay::metrics_prefix::()), params) } fn transactions_author(&self) -> bp_millau::AccountId { diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 8ee30d3ff4925..d23266c6491f2 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -42,7 +42,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { type TargetChain = Rococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) + crate::chains::add_polkadot_kusama_price_metrics::(Some(finality_relay::metrics_prefix::()), params) } fn start_relay_guards(&self) { diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 3c280c3f5bf6b..04f9e1f559403 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -185,7 +185,13 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; + let (metrics_params, _) = add_standalone_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + WococoMessagesToRococo, + >(&lane_id)), + params.metrics_params, + source_client.clone(), + )?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -224,10 +230,12 @@ pub async fn run( /// Add standalone metrics for the Wococo -> Rococo messages loop. pub(crate) fn add_standalone_metrics( + metrics_prefix: Option, metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { crate::messages_lane::add_standalone_metrics::( + metrics_prefix, metrics_params, source_client, None, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 31accb15a4bda..8e2d2ce2a7551 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -161,8 +161,8 @@ impl RelayHeadersAndMessages { let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); - let (metrics_params, _) = add_left_to_right_standalone_metrics(metrics_params, left_client.clone())?; - let (metrics_params, _) = add_right_to_left_standalone_metrics(metrics_params, right_client.clone())?; + let (metrics_params, _) = add_left_to_right_standalone_metrics(None, metrics_params, left_client.clone())?; + let (metrics_params, _) = add_right_to_left_standalone_metrics(None, metrics_params, right_client.clone())?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 7954319a75621..aed208a8ad5eb 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -203,6 +203,7 @@ pub struct StandaloneMessagesMetrics { /// Add general standalone metrics for the message lane relay loop. pub fn add_standalone_metrics( + metrics_prefix: Option, metrics_params: MetricsParams, source_client: Client, source_chain_token_id: Option<&str>, @@ -212,7 +213,7 @@ pub fn add_standalone_metrics( let mut source_to_base_conversion_rate = None; let mut target_to_base_conversion_rate = None; let mut metrics_params = - relay_utils::relay_metrics(None, metrics_params).standalone_metric(|registry, prefix| { + relay_utils::relay_metrics(metrics_prefix, metrics_params).standalone_metric(|registry, prefix| { StorageProofOverheadMetric::new( registry, prefix, From f6f658061d3366f26683455dd349f0469d350a56 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 1 Jul 2021 09:26:54 +0300 Subject: [PATCH 0504/1210] Use real conversion rate in greedy relayer strategy (#1035) * use real conversion rate in greedy relayer strategy * only accept positive, normal numbers in FloatJsonValueMetric --- .../src/chains/millau_messages_to_rialto.rs | 3 +- .../src/chains/rialto_messages_to_millau.rs | 3 +- .../src/chains/rococo_messages_to_wococo.rs | 3 +- .../src/chains/wococo_messages_to_rococo.rs | 3 +- relays/bin-substrate/src/messages_lane.rs | 9 ++++++ relays/bin-substrate/src/messages_target.rs | 28 ++++++++++++++----- relays/messages/src/message_lane_loop.rs | 12 ++++---- relays/messages/src/message_race_delivery.rs | 10 ++++++- relays/utils/src/metrics/float_json_value.rs | 24 ++++++++++++++++ 9 files changed, 78 insertions(+), 17 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 77f1adbd3744d..21a5f6fd279ca 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -171,7 +171,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics( + let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< MillauMessagesToRialto, >(&lane_id)), @@ -206,6 +206,7 @@ pub async fn run( lane, lane_id, MILLAU_CHAIN_ID, + metrics_values, params.source_to_target_headers_relay, ), metrics_params, diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 8a82456cdf289..1c0fc0a52ecf9 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -170,7 +170,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics( + let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< RialtoMessagesToMillau, >(&lane_id)), @@ -205,6 +205,7 @@ pub async fn run( lane, lane_id, RIALTO_CHAIN_ID, + metrics_values, params.source_to_target_headers_relay, ), metrics_params, diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 1e30f97f49405..99bcf53c8a172 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -185,7 +185,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics( + let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< RococoMessagesToWococo, >(&lane_id)), @@ -220,6 +220,7 @@ pub async fn run( lane, lane_id, ROCOCO_CHAIN_ID, + metrics_values, params.source_to_target_headers_relay, ), metrics_params, diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 04f9e1f559403..b9fcd7ac3a99e 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -185,7 +185,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); - let (metrics_params, _) = add_standalone_metrics( + let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< WococoMessagesToRococo, >(&lane_id)), @@ -220,6 +220,7 @@ pub async fn run( lane, lane_id, WOCOCO_CHAIN_ID, + metrics_values, params.source_to_target_headers_relay, ), metrics_params, diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index aed208a8ad5eb..b0119b12f0813 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -201,6 +201,15 @@ pub struct StandaloneMessagesMetrics { pub source_to_base_conversion_rate: Option, } +impl StandaloneMessagesMetrics { + /// Return conversion rate from target to source tokens. + pub async fn target_to_source_conversion_rate(&self) -> Option { + let target_to_base_conversion_rate = (*self.target_to_base_conversion_rate.as_ref()?.read().await)?; + let source_to_base_conversion_rate = (*self.source_to_base_conversion_rate.as_ref()?.read().await)?; + Some(target_to_base_conversion_rate / source_to_base_conversion_rate) + } +} + /// Add general standalone metrics for the message lane relay loop. pub fn add_standalone_metrics( metrics_prefix: Option, diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 71f51c1e05502..5abcd88b85d56 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -18,7 +18,7 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. -use crate::messages_lane::SubstrateMessageLane; +use crate::messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}; use crate::messages_source::{read_client_state, SubstrateMessagesProof}; use crate::on_demand_headers::OnDemandHeadersRelay; @@ -34,7 +34,7 @@ use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; -use num_traits::{Bounded, One, Zero}; +use num_traits::{Bounded, Zero}; use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; @@ -53,6 +53,7 @@ pub struct SubstrateMessagesTarget>, _phantom: PhantomData, } @@ -64,6 +65,7 @@ impl SubstrateMessagesTarget>, ) -> Self { SubstrateMessagesTarget { @@ -71,6 +73,7 @@ impl SubstrateMessagesTarget Clone for SubstrateMessag lane: self.lane.clone(), lane_id: self.lane_id, instance: self.instance, + metric_values: self.metric_values.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), _phantom: Default::default(), } @@ -239,10 +243,20 @@ where nonces: RangeInclusive, total_dispatch_weight: Weight, total_size: u32, - ) -> P::SourceChainBalance { - // TODO: use actual rate (https://github.com/paritytech/parity-bridges-common/issues/997) - convert_target_tokens_to_source_tokens::( - FixedU128::one(), + ) -> Result { + let conversion_rate = self + .metric_values + .target_to_source_conversion_rate() + .await + .ok_or_else(|| { + SubstrateError::Custom(format!( + "Failed to compute conversion rate from {} to {}", + TC::NAME, + SC::NAME, + )) + })?; + Ok(convert_target_tokens_to_source_tokens::( + FixedU128::from_float(conversion_rate), self.client .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( Zero::zero(), @@ -252,7 +266,7 @@ where )) .await .unwrap_or_else(|_| TC::Balance::max_value()), - ) + )) } } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 7ad5952603fcb..c70fc532e9c11 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -212,7 +212,7 @@ pub trait TargetClient: RelayClient { nonces: RangeInclusive, total_dispatch_weight: Weight, total_size: u32, - ) -> P::SourceChainBalance; + ) -> Result; } /// State of the client. @@ -775,10 +775,12 @@ pub(crate) mod tests { nonces: RangeInclusive, total_dispatch_weight: Weight, total_size: u32, - ) -> TestSourceChainBalance { - BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) - + total_dispatch_weight - + total_size as TestSourceChainBalance + ) -> Result { + Ok( + BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) + + total_dispatch_weight + + total_size as TestSourceChainBalance, + ) } } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index bde09af7068fd..a03a671c70ecf 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -654,7 +654,15 @@ async fn select_nonces_for_delivery_transaction( new_selected_unpaid_weight, new_selected_size as u32, ) - .await; + .await + .map_err(|err| { + log::debug!( + target: "bridge", + "Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery", + err, + ); + }) + .ok()?; // if it is the first message that makes reward less than cost, let's log it // if this message makes batch profitable again, let's log it diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index 2a18df2aac7e1..c610ac04dc97d 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -24,6 +24,9 @@ use std::time::Duration; const UPDATE_INTERVAL: Duration = Duration::from_secs(60); /// Metric that represents float value received from HTTP service as float gauge. +/// +/// The float value returned by the service is assumed to be normal (`f64::is_normal` +/// should return `true`) and strictly positive. #[derive(Debug, Clone)] pub struct FloatJsonValueMetric { url: String, @@ -114,6 +117,12 @@ fn parse_service_response(json_path: &str, response: &str) -> Result Date: Fri, 2 Jul 2021 11:08:35 +0300 Subject: [PATCH 0505/1210] give real value to Rialto and Millau tokens (#1038) --- .../src/chains/millau_messages_to_rialto.rs | 4 ++-- relays/bin-substrate/src/chains/mod.rs | 9 +++++++++ .../src/chains/rialto_messages_to_millau.rs | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 21a5f6fd279ca..7761834672e39 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -225,8 +225,8 @@ pub(crate) fn add_standalone_metrics( metrics_prefix, metrics_params, source_client, - None, - None, + Some(crate::chains::MILLAU_ASSOCIATED_TOKEN_ID), + Some(crate::chains::RIALTO_ASSOCIATED_TOKEN_ID), Some(( sp_core::storage::StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index b79bfcaaad21e..bd228ac7c4f09 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -32,6 +32,15 @@ mod rococo; mod westend; mod wococo; +// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we want to +// test our code that is intended to work with real-value chains. So to keep it close to 1:1, we'll be treating +// Rialto as BTC and Millau as wBTC (only in relayer). + +/// The identifier of token, which value is associated with Rialto token value by relayer. +pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = "bitcoin"; +/// The identifier of token, which value is associated with Millau token value by relayer. +pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "wrapped-bitcoin"; + use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams, PrometheusError, Registry}; pub(crate) fn add_polkadot_kusama_price_metrics( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 1c0fc0a52ecf9..c2764c20d8238 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -224,8 +224,8 @@ pub(crate) fn add_standalone_metrics( metrics_prefix, metrics_params, source_client, - None, - None, + Some(crate::chains::RIALTO_ASSOCIATED_TOKEN_ID), + Some(crate::chains::MILLAU_ASSOCIATED_TOKEN_ID), Some(( sp_core::storage::StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, From fe900f8950a94ba128cfcce394326f8891599ef1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 2 Jul 2021 12:30:08 +0300 Subject: [PATCH 0506/1210] pre and post dispatch weights of OnDeliveryConfirmed callback (#1040) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * pre and post dispatch weights of OnDeliveryConfirmed callback * Update modules/messages/README.md Co-authored-by: Tomasz Drwięga * clippy + compilation * fix test issue from parallel PR Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 2 + bin/rialto/runtime/src/lib.rs | 2 + modules/messages/README.md | 12 +- modules/messages/src/lib.rs | 150 +++++++++++++++++++++--- modules/messages/src/mock.rs | 26 +++- modules/messages/src/weights_ext.rs | 23 +++- primitives/messages/src/lib.rs | 9 ++ primitives/messages/src/source_chain.rs | 29 ++++- 8 files changed, 228 insertions(+), 25 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 33c21027f8a2a..491304337358d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -688,6 +688,7 @@ mod tests { bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, + DbWeight::get(), ); let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( @@ -712,6 +713,7 @@ mod tests { max_incoming_inbound_lane_data_proof_size, bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + DbWeight::get(), ); } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 219feda64693e..e53beed389edd 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1125,6 +1125,7 @@ mod tests { bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, + DbWeight::get(), ); let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( @@ -1149,6 +1150,7 @@ mod tests { max_incoming_inbound_lane_data_proof_size, bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + DbWeight::get(), ); } diff --git a/modules/messages/README.md b/modules/messages/README.md index be25b3c37f757..062a966fad70a 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -354,7 +354,7 @@ Both conditions are verified by `pallet_bridge_messages::ensure_weights_are_corr `pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every runtime's tests. -### Post-dispatch weight refunds of the `receive_messages_proof` call +#### Post-dispatch weight refunds of the `receive_messages_proof` call Weight formula of the `receive_messages_proof` call assumes that the dispatch fee of every message is paid at the target chain (where call is executed), that every message will be dispatched and that @@ -388,6 +388,7 @@ The weight formula is: Weight = BaseWeight + MessagesCount * MessageConfirmationWeight + RelayersCount * RelayerRewardWeight + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight + + MessagesCount * (DbReadWeight + DbWriteWeight) ``` Where: @@ -403,6 +404,15 @@ Where: | `ExpectedProofSize` | `EXTRA_STORAGE_PROOF_SIZE` | Size of proof that we are expecting | | `ProofByteDeliveryWeight` | `(receive_single_message_proof_16_kb - receive_single_message_proof_1_kb) / (15 * 1024)` | Weight of processing every additional proof byte over `ExpectedProofSize` limit. We're using the same formula, as for message delivery, because proof mechanism is assumed to be the same in both cases | +#### Post-dispatch weight refunds of the `receive_messages_delivery_proof` call + +Weight formula of the `receive_messages_delivery_proof` call assumes that all messages in the proof +are actually delivered (so there are no already confirmed messages) and every messages is processed +by the `OnDeliveryConfirmed` callback. This means that for every message, we're adding single db read +weight and single db write weight. If, by some reason, messages are not processed by the +`OnDeliveryConfirmed` callback, or their processing is faster than that additional weight, the +difference is refunded to the submitter. + #### Why we're always able to craft `receive_messages_delivery_proof` transaction? There can be at most `::MaxUnconfirmedMessagesAtInboundLane` diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a5f94c1eda819..c1d4fa223a6d4 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -594,14 +594,35 @@ decl_module! { } /// Receive messages delivery proof from bridged chain. - #[weight = T::WeightInfo::receive_messages_delivery_proof_weight(proof, relayers_state)] + #[weight = T::WeightInfo::receive_messages_delivery_proof_weight( + proof, + relayers_state, + T::DbWeight::get(), + )] pub fn receive_messages_delivery_proof( origin, proof: MessagesDeliveryProofOf, relayers_state: UnrewardedRelayersState, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure_not_halted::()?; + // why do we need to know the weight of this (`receive_messages_delivery_proof`) call? Because + // we may want to return some funds for messages that are not processed by the delivery callback, + // or if their actual processing weight is less than accounted by weight formula. + // So to refund relayer, we need to: + // + // ActualWeight = DeclaredWeight - UnspentCallbackWeight + // + // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible + // to get pre-computed value (and it has been already computed by the executive). + let single_message_callback_overhead = T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); + let declared_weight = T::WeightInfo::receive_messages_delivery_proof_weight( + &proof, + &relayers_state, + T::DbWeight::get(), + ); + let mut actual_weight = declared_weight; + let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { log::trace!( @@ -641,7 +662,37 @@ decl_module! { }; if let Some(confirmed_messages) = confirmed_messages { // handle messages delivery confirmation - T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); + let preliminary_callback_overhead = relayers_state.total_messages.saturating_mul( + single_message_callback_overhead + ); + let actual_callback_weight = T::OnDeliveryConfirmed::on_messages_delivered( + &lane_id, + &confirmed_messages, + ); + match preliminary_callback_overhead.checked_sub(actual_callback_weight) { + Some(difference) if difference == 0 => (), + Some(difference) => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery callback has returned unspent weight to refund the submitter: \ + {} - {} = {}", + preliminary_callback_overhead, + actual_callback_weight, + difference, + ); + actual_weight -= difference; + }, + None => { + debug_assert!(false, "The delivery confirmation callback is wrong"); + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery callback has returned more weight that it may spent: \ + {} vs {}", + preliminary_callback_overhead, + actual_callback_weight, + ); + } + } // emit 'delivered' event let received_range = confirmed_messages.begin..=confirmed_messages.end; @@ -684,7 +735,10 @@ decl_module! { lane_id, ); - Ok(()) + Ok(PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }) } } } @@ -962,8 +1016,8 @@ mod tests { use crate::mock::{ message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, - TestRuntime, TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, - TEST_RELAYER_A, TEST_RELAYER_B, + TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, TestRuntime, TokenConversionRate, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use frame_support::{assert_noop, assert_ok}; @@ -1260,10 +1314,14 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, - ..Default::default() + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), }, ))), - Default::default(), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + }, ), Error::::Halted, ); @@ -1309,10 +1367,14 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, - ..Default::default() + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), }, ))), - Default::default(), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + }, )); }); } @@ -1923,10 +1985,70 @@ mod tests { )); // ensure that both callbacks have been called twice: for 1+2, then for 3 - crate::mock::TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); - crate::mock::TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_message_3); - crate::mock::TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); - crate::mock::TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_message_3); + TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); + TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_message_3); + TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); + TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_message_3); + }); + } + + fn confirm_3_messages_delivery() -> (Weight, Weight) { + send_regular_message(); + send_regular_message(); + send_regular_message(); + + let proof = TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 0, + relayers: vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)].into_iter().collect(), + }, + ))); + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 3, + ..Default::default() + }; + let pre_dispatch_weight = ::WeightInfo::receive_messages_delivery_proof_weight( + &proof, + &relayers_state, + crate::mock::DbWeight::get(), + ); + let post_dispatch_weight = + Pallet::::receive_messages_delivery_proof(Origin::signed(1), proof, relayers_state) + .expect("confirmation has failed") + .actual_weight + .expect("receive_messages_delivery_proof always returns Some"); + (pre_dispatch_weight, post_dispatch_weight) + } + + #[test] + fn receive_messages_delivery_proof_refunds_zero_weight() { + run_test(|| { + let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery(); + assert_eq!(pre_dispatch_weight, post_dispatch_weight); + }); + } + + #[test] + fn receive_messages_delivery_proof_refunds_non_zero_weight() { + run_test(|| { + TestOnDeliveryConfirmed1::set_consumed_weight_per_message(crate::mock::DbWeight::get().writes(1)); + + let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery(); + assert_eq!( + pre_dispatch_weight.saturating_sub(post_dispatch_weight), + crate::mock::DbWeight::get().reads(1) * 3 + ); + }); + } + + #[test] + #[should_panic] + fn receive_messages_panics_in_debug_mode_if_callback_is_wrong() { + run_test(|| { + TestOnDeliveryConfirmed1::set_consumed_weight_per_message(crate::mock::DbWeight::get().reads_writes(2, 2)); + confirm_3_messages_delivery() }); } } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 2e184dda15857..9d361b53cf84b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -31,7 +31,10 @@ use bp_messages::{ }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; -use frame_support::{parameter_types, weights::Weight}; +use frame_support::{ + parameter_types, + weights::{RuntimeDbWeight, Weight}, +}; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -87,6 +90,7 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; } impl frame_system::Config for TestRuntime { @@ -110,7 +114,7 @@ impl frame_system::Config for TestRuntime { type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); - type DbWeight = (); + type DbWeight = DbWeight; type SS58Prefix = (); type OnSetCode = (); } @@ -358,12 +362,25 @@ impl TestOnDeliveryConfirmed1 { let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode(); assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); } + + /// Set consumed weight returned by the callback. + pub fn set_consumed_weight_per_message(weight: Weight) { + frame_support::storage::unhashed::put(b"TestOnDeliveryConfirmed1_Weight", &weight); + } + + /// Get consumed weight returned by the callback. + pub fn get_consumed_weight_per_message() -> Option { + frame_support::storage::unhashed::get(b"TestOnDeliveryConfirmed1_Weight") + } } impl OnDeliveryConfirmed for TestOnDeliveryConfirmed1 { - fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) { + fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode(); frame_support::storage::unhashed::put(&key, &true); + Self::get_consumed_weight_per_message() + .unwrap_or_else(|| DbWeight::get().reads_writes(1, 1)) + .saturating_mul(messages.total_messages()) } } @@ -380,9 +397,10 @@ impl TestOnDeliveryConfirmed2 { } impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 { - fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) { + fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode(); frame_support::storage::unhashed::put(&key, &true); + 0 } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index be440174b4b9b..e1b8c7e885362 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -20,7 +20,7 @@ use crate::weights::WeightInfo; use bp_messages::{MessageNonce, UnrewardedRelayersState}; use bp_runtime::{PreComputedSize, Size}; -use frame_support::weights::Weight; +use frame_support::weights::{RuntimeDbWeight, Weight}; /// Size of the message being delivered in benchmarks. pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128; @@ -35,6 +35,7 @@ pub fn ensure_weights_are_correct( expected_additional_byte_delivery_weight: Weight, expected_messages_delivery_confirmation_tx_weight: Weight, expected_pay_inbound_dispatch_fee_weight: Weight, + db_weight: RuntimeDbWeight, ) { // verify `send_message` weight components assert_ne!(W::send_message_overhead(), 0); @@ -82,6 +83,7 @@ pub fn ensure_weights_are_correct( total_messages: 1, ..Default::default() }, + db_weight, ); assert!( actual_messages_delivery_confirmation_tx_weight <= expected_messages_delivery_confirmation_tx_weight, @@ -138,6 +140,7 @@ pub fn ensure_able_to_receive_confirmation( max_inbound_lane_data_proof_size_from_peer_chain: u32, max_unrewarded_relayer_entries_at_peer_inbound_lane: MessageNonce, max_unconfirmed_messages_at_inbound_lane: MessageNonce, + db_weight: RuntimeDbWeight, ) { // verify that we're able to receive confirmation of maximal-size let max_confirmation_transaction_size = @@ -158,6 +161,7 @@ pub fn ensure_able_to_receive_confirmation( total_messages: max_unconfirmed_messages_at_inbound_lane, ..Default::default() }, + db_weight, ); assert!( max_confirmation_transaction_dispatch_weight <= max_extrinsic_weight, @@ -212,7 +216,11 @@ pub trait WeightInfoExt: WeightInfo { } /// Weight of confirmation delivery extrinsic. - fn receive_messages_delivery_proof_weight(proof: &impl Size, relayers_state: &UnrewardedRelayersState) -> Weight { + fn receive_messages_delivery_proof_weight( + proof: &impl Size, + relayers_state: &UnrewardedRelayersState, + db_weight: RuntimeDbWeight, + ) -> Weight { // basic components of extrinsic weight let transaction_overhead = Self::receive_messages_delivery_proof_overhead(); let messages_overhead = Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages); @@ -225,10 +233,16 @@ pub trait WeightInfoExt: WeightInfo { let proof_size_overhead = Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size)); + // and cost of calling `OnDeliveryConfirmed::on_messages_delivered()` for every confirmed message + let callback_overhead = relayers_state + .total_messages + .saturating_mul(Self::single_message_callback_overhead(db_weight)); + transaction_overhead .saturating_add(messages_overhead) .saturating_add(relayers_overhead) .saturating_add(proof_size_overhead) + .saturating_add(callback_overhead) } // Functions that are used by extrinsics weights formulas. @@ -321,6 +335,11 @@ pub trait WeightInfoExt: WeightInfo { fn pay_inbound_dispatch_fee_overhead() -> Weight { Self::receive_single_message_proof().saturating_sub(Self::receive_single_prepaid_message_proof()) } + + /// Returns pre-dispatch weight of single message delivery callback call. + fn single_message_callback_overhead(db_weight: RuntimeDbWeight) -> Weight { + db_weight.reads_writes(1, 1) + } } impl WeightInfoExt for () { diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 963543ec3213f..4ec7c1f9d2b00 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -226,6 +226,15 @@ impl DeliveredMessages { } } + /// Return total count of delivered messages. + pub fn total_messages(&self) -> MessageNonce { + if self.end >= self.begin { + self.end - self.begin + 1 + } else { + 0 + } + } + /// Note new dispatched message. pub fn note_dispatched_message(&mut self, dispatch_result: bool) { self.end += 1; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 392331eda6722..ed69f39c7630f 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -19,7 +19,7 @@ use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; use bp_runtime::Size; -use frame_support::{Parameter, RuntimeDebug}; +use frame_support::{weights::Weight, Parameter, RuntimeDebug}; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug}; /// The sender of the message on the source chain. @@ -136,12 +136,33 @@ pub trait MessageDeliveryAndDispatchPayment { } /// Handler for messages delivery confirmation. -#[impl_trait_for_tuples::impl_for_tuples(30)] pub trait OnDeliveryConfirmed { /// Called when we receive confirmation that our messages have been delivered to the /// target chain. The confirmation also has single bit dispatch result for every - /// confirmed message (see `DeliveredMessages` for details). - fn on_messages_delivered(_lane: &LaneId, _messages: &DeliveredMessages) {} + /// confirmed message (see `DeliveredMessages` for details). Guaranteed to be called + /// only when at least one message is delivered. + /// + /// Should return total weight consumed by the call. + /// + /// NOTE: messages pallet assumes that maximal weight that may be spent on processing + /// single message is single DB read + single DB write. So this function shall never + /// return weight that is larger than total number of messages * (db read + db write). + /// If your pallet needs more time for processing single message, please do it + /// from `on_initialize` call(s) of the next block(s). + fn on_messages_delivered(_lane: &LaneId, _messages: &DeliveredMessages) -> Weight; +} + +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl OnDeliveryConfirmed for Tuple { + fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { + let mut total_weight: Weight = 0; + for_tuples!( + #( + total_weight = total_weight.saturating_add(Tuple::on_messages_delivered(lane, messages)); + )* + ); + total_weight + } } /// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and From 06b148be451dc55147680382f57441a72ab7d8a8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 5 Jul 2021 09:38:23 +0300 Subject: [PATCH 0507/1210] Confirm delivery detects when more than expected messages are confirmed (#1039) * confirm delivery detects when more than expected messages are confirmed * fix benchmarks compilation --- modules/messages/src/benchmarking.rs | 2 +- modules/messages/src/lib.rs | 51 +++++++++++++++++++++++++-- modules/messages/src/outbound_lane.rs | 49 +++++++++++++++++++++---- 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 54cb7c26cd3d7..cab2704f4009f 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -904,7 +904,7 @@ fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { }); } assert!(matches!( - outbound_lane.confirm_delivery(nonce, &relayers), + outbound_lane.confirm_delivery(nonce - latest_received_nonce, nonce, &relayers), ReceivalConfirmationResult::ConfirmedMessages(_), )); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index c1d4fa223a6d4..a8071e9922209 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -197,7 +197,10 @@ decl_error! { /// The message someone is trying to work with (i.e. increase fee) is already-delivered. MessageIsAlreadyDelivered, /// The message someone is trying to work with (i.e. increase fee) is not yet sent. - MessageIsNotYetSent + MessageIsNotYetSent, + /// The number of actually confirmed messages is going to be larger than the number of messages in the proof. + /// This may mean that this or bridged chain storage is corrupted. + TryingToConfirmMoreMessagesThanExpected, } } @@ -647,9 +650,23 @@ decl_module! { let mut lane = outbound_lane::(lane_id); let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); - let confirmed_messages = match lane.confirm_delivery(last_delivered_nonce, &lane_data.relayers) { + let confirmed_messages = match lane.confirm_delivery( + relayers_state.total_messages, + last_delivered_nonce, + &lane_data.relayers, + ) { ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages), ReceivalConfirmationResult::NoNewConfirmations => None, + ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(to_confirm_messages_count) => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery proof contains too many messages to confirm: {} vs declared {}", + to_confirm_messages_count, + relayers_state.total_messages, + ); + + fail!(Error::::TryingToConfirmMoreMessagesThanExpected); + }, error => { log::trace!( target: "runtime::bridge-messages", @@ -660,6 +677,7 @@ decl_module! { fail!(Error::::InvalidUnrewardedRelayers); }, }; + if let Some(confirmed_messages) = confirmed_messages { // handle messages delivery confirmation let preliminary_callback_overhead = relayers_state.total_messages.saturating_mul( @@ -2051,4 +2069,33 @@ mod tests { confirm_3_messages_delivery() }); } + + #[test] + fn receive_messages_delivery_proof_rejects_proof_if_trying_to_confirm_more_messages_than_expected() { + run_test(|| { + // send message first to be able to check that delivery_proof fails later + send_regular_message(); + + // 1) InboundLaneData declares that the `last_confirmed_nonce` is 1; + // 2) InboundLaneData has no entries => `InboundLaneData::last_delivered_nonce()` + // returns `last_confirmed_nonce`; + // 3) it means that we're going to confirm delivery of messages 1..=1; + // 4) so the number of declared messages (see `UnrewardedRelayersState`) is `0` and + // numer of actually confirmed messages is `1`. + assert_noop!( + Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 1, + relayers: Default::default(), + }, + ))), + UnrewardedRelayersState::default(), + ), + Error::::TryingToConfirmMoreMessagesThanExpected, + ); + }); + } } diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 44061d984e1d0..7130bd1bb53d2 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -63,6 +63,8 @@ pub enum ReceivalConfirmationResult { /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May be /// a result of invalid bridged chain storage. InvalidNumberOfDispatchResults, + /// The chain has more messages that need to be confirmed than there is in the proof. + TryingToConfirmMoreMessagesThanExpected(MessageNonce), } /// Outbound messages lane. @@ -98,6 +100,7 @@ impl OutboundLane { /// Confirm messages delivery. pub fn confirm_delivery( &mut self, + max_allowed_messages: MessageNonce, latest_received_nonce: MessageNonce, relayers: &VecDeque>, ) -> ReceivalConfirmationResult { @@ -108,6 +111,16 @@ impl OutboundLane { if latest_received_nonce > data.latest_generated_nonce { return ReceivalConfirmationResult::FailedToConfirmFutureMessages; } + if latest_received_nonce - data.latest_received_nonce > max_allowed_messages { + // that the relayer has declared correct number of messages that the proof contains (it is + // checked outside of the function). But it may happen (but only if this/bridged chain storage is + // corrupted, though) that the actual number of confirmed messages if larger than declared. + // This would mean that 'reward loop' will take more time than the weight formula accounts, + // so we can't allow that. + return ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected( + latest_received_nonce - data.latest_received_nonce, + ); + } let dispatch_results = match extract_dispatch_results(data.latest_received_nonce, latest_received_nonce, relayers) { @@ -245,7 +258,7 @@ mod tests { lane.send_message(message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); - let result = lane.confirm_delivery(latest_received_nonce, relayers); + let result = lane.confirm_delivery(3, latest_received_nonce, relayers); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); result @@ -273,7 +286,7 @@ mod tests { assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( - lane.confirm_delivery(3, &unrewarded_relayers(1..=3)), + lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); @@ -291,18 +304,18 @@ mod tests { assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( - lane.confirm_delivery(3, &unrewarded_relayers(1..=3)), + lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), ); assert_eq!( - lane.confirm_delivery(3, &unrewarded_relayers(1..=3)), + lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), ReceivalConfirmationResult::NoNewConfirmations, ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); assert_eq!( - lane.confirm_delivery(2, &unrewarded_relayers(1..=1)), + lane.confirm_delivery(1, 2, &unrewarded_relayers(1..=1)), ReceivalConfirmationResult::NoNewConfirmations, ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); @@ -393,18 +406,40 @@ mod tests { assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // after confirmation, some messages are received assert_eq!( - lane.confirm_delivery(2, &unrewarded_relayers(1..=2)), + lane.confirm_delivery(2, 2, &unrewarded_relayers(1..=2)), ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)), ); assert_eq!(lane.prune_messages(100), 2); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3); // after last message is confirmed, everything is pruned assert_eq!( - lane.confirm_delivery(3, &unrewarded_relayers(3..=3)), + lane.confirm_delivery(1, 3, &unrewarded_relayers(3..=3)), ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)), ); assert_eq!(lane.prune_messages(100), 1); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4); }); } + + #[test] + fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() { + run_test(|| { + let mut lane = outbound_lane::(TEST_LANE_ID); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(message_data(REGULAR_PAYLOAD)); + assert_eq!( + lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), + ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3), + ); + assert_eq!( + lane.confirm_delivery(2, 3, &unrewarded_relayers(1..=3)), + ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3), + ); + assert_eq!( + lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), + ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), + ); + }); + } } From d547af00bf5f802631252c8134892b4ad3f85a2e Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Tue, 6 Jul 2021 14:43:31 -0400 Subject: [PATCH 0508/1210] Yrong README Fixup + M1 Fixes (#1045) * Fix build error in mac m1 silicon * Improve readme * Clean up local script instructions * Add Docker Hub reference * Slightly improve send a message wording * Fix typo Co-authored-by: ron.yang --- README.md | 123 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 40aa85973f3bd..e71563705df28 100644 --- a/README.md +++ b/README.md @@ -102,10 +102,9 @@ the `relays` which are used to pass messages between chains. To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes on each side of the bridge (source and target chain). -There are 3 ways to run the bridge, described below: +There are 2 ways to run the bridge, described below: -- building & running from source, -- building or using Docker images for each individual component, +- building & running from source - running a Docker Compose setup (recommended). ### Using the Source @@ -119,88 +118,102 @@ cargo build -p millau-bridge-node cargo build -p substrate-relay ``` -### Running +### Running a Dev network -To run a simple dev network you'll can use the scripts located in -[the `deployments/local-scripts` folder](./deployments/local-scripts). Since the relayer connects to -both Substrate chains it must be run last. +We will launch a dev network to demonstrate how to relay a message between two Substrate based +chains (named Rialto and Millau). + +To do this we will need two nodes, two relayers which will relay headers, and two relayers which +will relay messages. + +#### Running from local scripts + +To run a simple dev network you can use the scripts located in the +[`deployments/local-scripts` folder](./deployments/local-scripts). + +First, we must run the two Substrate nodes. ```bash # In `parity-bridges-common` folder ./deployments/local-scripts/run-rialto-node.sh ./deployments/local-scripts/run-millau-node.sh +``` + +After the nodes are up we can run the header relayers. + +```bash ./deployments/local-scripts/relay-millau-to-rialto.sh +./deployments/local-scripts/relay-rialto-to-millau.sh ``` At this point you should see the relayer submitting headers from the Millau Substrate chain to the Rialto Substrate chain. -### Local Docker Setup - -To get up and running quickly you can use published Docker images for the bridge nodes and relayer. -The images are published on [Docker Hub](https://hub.docker.com/u/paritytech). +``` +# Header Relayer Logs +[Millau_to_Rialto_Sync] [date] DEBUG bridge Going to submit finality proof of Millau header #147 to Rialto +[...] [date] INFO bridge Synced 147 of 147 headers +[...] [date] DEBUG bridge Going to submit finality proof of Millau header #148 to Rialto +[...] [date] INFO bridge Synced 148 of 149 headers +``` -To run the dev network we first run the two bridge nodes: +Finally, we can run the message relayers. ```bash -docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ - -it paritytech/rialto-bridge-node --dev --tmp \ - --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external - -docker run -p 30334:30333 -p 9934:9933 -p 9945:9944 \ - -it paritytech/millau-bridge-node --dev --tmp \ - --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external +./deployments/local-scripts/relay-messages-millau-to-rialto.sh +./deployments/local-scripts/relay-messages-millau-to-rialto.sh ``` -Notice that the `docker run` command will accept all the normal Substrate flags. For local -development you should at minimum run with the `--dev` flag or else no blocks will be produced. +You will also see the message lane relayers listening for new messages. -Then we need to initialize and run the relayer: +``` +# Message Relayer Logs +[Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces +[...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race +[...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces +[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } +[...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces +[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } +[...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) } +[...] [date] DEBUG bridge Asking Millau node about its state +[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) } +``` -```bash -docker run --network=host -it \ - paritytech/substrate-relay init-bridge rialto-to-millau \ - --target-host localhost \ - --target-port 9945 \ - --source-host localhost \ - --source-port 9944 \ - --target-signer //Alice +To send a message see the ["How to send a message" section](#how-to-send-a-message). -docker run --network=host -it \ - paritytech/substrate-relay relay-headers rialto-to-millau \ - --target-host localhost \ - --target-port 9945 \ - --source-host localhost \ - --source-port 9944 \ - --target-signer //Bob \ -``` +### Full Network Docker Compose Setup -You should now see the relayer submitting headers from the Millau chain to the Rialto chain. +For a more sophisticated deployment which includes bidirectional header sync, message passing, +monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). -If you don't want to use the published Docker images you can build images yourself. You can do this -by running the following commands at the top level of the repository. +You should note that you can find images for all the bridge components published on +[Docker Hub](https://hub.docker.com/u/paritytech). + +To run a Rialto node for example, you can use the following command: ```bash -# In `parity-bridges-common` folder -docker build . -t local/rialto-bridge-node --build-arg PROJECT=rialto-bridge-node -docker build . -t local/millau-bridge-node --build-arg PROJECT=millau-bridge-node -docker build . -t local/substrate-relay --build-arg PROJECT=substrate-relay +docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ + -it paritytech/rialto-bridge-node --dev --tmp \ + --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external ``` -_Note: Building the node images will take a long time, so make sure you have some coffee handy._ - -Once you have the images built you can use them in the previous commands by replacing -`paritytech/` with `local/` everywhere. +### How to send a message -### Full Network Docker Compose Setup +In this section we'll show you how to quickly send a bridge message, if you want to +interact with and test the bridge see more details in [send message](./docs/send-message.md) -For a more sophisticated deployment which includes bidirectional header sync, message passing, -monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). +```bash +# In `parity-bridges-common` folder +./scripts/send-message-from-millau-rialto.sh remark +``` -### How to send a message +After sending a message you will see the following logs showing a message was successfully sent: -A straightforward way to interact with and test the bridge is sending messages. This is explained -in the [send message](./docs/send-message.md) document. +``` +INFO bridge Sending message to Rialto. Size: 286. Dispatch weight: 1038000. Fee: 275,002,568 +INFO bridge Signed Millau Call: 0x7904... +TRACE bridge Sent transaction to Millau node: 0x5e68... +``` ## Community From baea6929aba587c4ae0aa34ef0fdcd8f24bdae82 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Jul 2021 21:56:23 +0300 Subject: [PATCH 0509/1210] Cli option for greedy relayer + run no-losses relayer by default (#1042) * cli option for greedy relayer + run no-losses relayer by default * trigger build * Revert "trigger build" This reverts commit f77ae3a634b909bb4dc915941a4c1011a86019f0. * NoLosses -> Rational --- .../src/chains/millau_messages_to_rialto.rs | 6 +- .../src/chains/rialto_messages_to_millau.rs | 6 +- .../src/chains/rococo_messages_to_wococo.rs | 6 +- .../src/chains/wococo_messages_to_rococo.rs | 6 +- .../src/cli/relay_headers_and_messages.rs | 8 ++- .../bin-substrate/src/cli/relay_messages.rs | 64 ++++++++++++++++++- relays/bin-substrate/src/messages_lane.rs | 2 + relays/bin-substrate/src/messages_target.rs | 7 ++ relays/messages/src/message_lane.rs | 12 +++- relays/messages/src/message_lane_loop.rs | 2 +- relays/messages/src/message_race_delivery.rs | 35 +++++++--- 11 files changed, 131 insertions(+), 23 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 7761834672e39..05ff36be1f922 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -164,11 +164,13 @@ pub async fn run( Millau relayer account id: {:?}\n\t\ Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}", + Max messages weight in single transaction: {}\n\t\ + Relayer mode: {:?}", lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, + params.relayer_mode, ); let (metrics_params, metrics_values) = add_standalone_metrics( @@ -191,7 +193,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + relayer_mode: params.relayer_mode, }, }, MillauSourceClient::new( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index c2764c20d8238..0aec33a339a3f 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -163,11 +163,13 @@ pub async fn run( Rialto relayer account id: {:?}\n\t\ Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}", + Max messages weight in single transaction: {}\n\t\ + Relayer mode: {:?}", lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, + params.relayer_mode, ); let (metrics_params, metrics_values) = add_standalone_metrics( @@ -190,7 +192,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + relayer_mode: params.relayer_mode, }, }, RialtoSourceClient::new( diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 99bcf53c8a172..080fa3b0491b7 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -178,11 +178,13 @@ pub async fn run( Rococo relayer account id: {:?}\n\t\ Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}", + Max messages weight in single transaction: {}\n\t\ + Relayer mode: {:?}", lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, + params.relayer_mode, ); let (metrics_params, metrics_values) = add_standalone_metrics( @@ -205,7 +207,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + relayer_mode: params.relayer_mode, }, }, RococoSourceClient::new( diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index b9fcd7ac3a99e..b36088388ffe7 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -178,11 +178,13 @@ pub async fn run( Wococo relayer account id: {:?}\n\t\ Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}", + Max messages weight in single transaction: {}\n\t\ + Relayer mode: {:?}", lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, + params.relayer_mode, ); let (metrics_params, metrics_values) = add_standalone_metrics( @@ -205,7 +207,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: messages_relay::message_lane_loop::RelayerMode::Altruistic, + relayer_mode: params.relayer_mode, }, }, WococoSourceClient::new( diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 8e2d2ce2a7551..04ee1a6bc2c67 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -22,7 +22,7 @@ //! 2) add `declare_bridge_options!(...)` for the bridge; //! 3) add bridge support to the `select_bridge! { ... }` macro. -use crate::cli::{CliChain, HexLaneId, PrometheusParams}; +use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}; use crate::declare_chain_options; use crate::messages_lane::MessagesRelayParams; use crate::on_demand_headers::OnDemandHeadersRelay; @@ -30,6 +30,7 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use futures::{FutureExt, TryFutureExt}; use relay_utils::metrics::MetricsParams; use structopt::StructOpt; +use strum::VariantNames; /// Start headers+messages relayer process. #[derive(StructOpt)] @@ -44,6 +45,8 @@ pub struct HeadersAndMessagesSharedParams { /// Hex-encoded lane identifiers that should be served by the complex relay. #[structopt(long, default_value = "00000000")] lane: Vec, + #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] + relayer_mode: RelayerMode, #[structopt(flatten)] prometheus_params: PrometheusParams, } @@ -158,6 +161,7 @@ impl RelayHeadersAndMessages { let right_sign = params.right_sign.to_keypair::()?; let lanes = params.shared.lane; + let relayer_mode = params.shared.relayer_mode.into(); let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); @@ -189,6 +193,7 @@ impl RelayHeadersAndMessages { source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, + relayer_mode, metrics_params: metrics_params.clone().disable().metrics_prefix( messages_relay::message_lane_loop::metrics_prefix::(&lane), ), @@ -203,6 +208,7 @@ impl RelayHeadersAndMessages { source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, + relayer_mode, metrics_params: metrics_params.clone().disable().metrics_prefix( messages_relay::message_lane_loop::metrics_prefix::(&lane), ), diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index e798888f4ca3f..afd59c7a3a167 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -22,7 +22,26 @@ use crate::cli::{ use crate::messages_lane::MessagesRelayParams; use crate::select_full_bridge; use structopt::StructOpt; -use strum::VariantNames; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +/// Relayer operating mode. +#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq)] +#[strum(serialize_all = "kebab_case")] +pub enum RelayerMode { + /// The relayer doesn't care about rewards. + Altruistic, + /// The relayer will deliver all messages and confirmations as long as he's not losing any funds. + Rational, +} + +impl From for messages_relay::message_lane_loop::RelayerMode { + fn from(mode: RelayerMode) -> Self { + match mode { + RelayerMode::Altruistic => Self::Altruistic, + RelayerMode::Rational => Self::Rational, + } + } +} /// Start messages relayer process. #[derive(StructOpt)] @@ -33,6 +52,8 @@ pub struct RelayMessages { /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, + #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] + relayer_mode: RelayerMode, #[structopt(flatten)] source: SourceConnectionParams, #[structopt(flatten)] @@ -62,6 +83,7 @@ impl RelayMessages { source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: self.lane.into(), + relayer_mode: self.relayer_mode.into(), metrics_params: self.prometheus_params.into(), }) .await @@ -69,3 +91,43 @@ impl RelayMessages { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_use_rational_relayer_mode_by_default() { + assert_eq!( + RelayMessages::from_iter(vec![ + "relay-messages", + "rialto-to-millau", + "--source-port=0", + "--source-signer=//Alice", + "--target-port=0", + "--target-signer=//Alice", + "--lane=00000000", + ]) + .relayer_mode, + RelayerMode::Rational, + ); + } + + #[test] + fn should_accept_altruistic_relayer_mode() { + assert_eq!( + RelayMessages::from_iter(vec![ + "relay-messages", + "rialto-to-millau", + "--source-port=0", + "--source-signer=//Alice", + "--target-port=0", + "--target-signer=//Alice", + "--lane=00000000", + "--relayer-mode=altruistic", + ]) + .relayer_mode, + RelayerMode::Altruistic, + ); + } +} diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index b0119b12f0813..1920137f140dc 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -49,6 +49,8 @@ pub struct MessagesRelayParams { pub target_to_source_headers_relay: Option>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, + /// Relayer operating mode. + pub relayer_mode: messages_relay::message_lane_loop::RelayerMode, /// Metrics parameters. pub metrics_params: MetricsParams, } diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index 5abcd88b85d56..bbee261c6d8e4 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -255,6 +255,13 @@ where SC::NAME, )) })?; + log::trace!( + target: "bridge", + "Using conversion rate {} when converting from {} tokens to {} tokens", + conversion_rate, + TC::NAME, + SC::NAME + ); Ok(convert_target_tokens_to_source_tokens::( FixedU128::from_float(conversion_rate), self.client diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs index 8757e9322ce44..d03d40759731f 100644 --- a/relays/messages/src/message_lane.rs +++ b/relays/messages/src/message_lane.rs @@ -21,7 +21,7 @@ use num_traits::{SaturatingAdd, Zero}; use relay_utils::{BlockNumberBase, HeaderId}; -use std::fmt::Debug; +use std::{fmt::Debug, ops::Sub}; /// One-way message lane. pub trait MessageLane: 'static + Clone + Send + Sync { @@ -40,7 +40,15 @@ pub trait MessageLane: 'static + Clone + Send + Sync { /// 1) pay transaction fees; /// 2) pay message delivery and dispatch fee; /// 3) pay relayer rewards. - type SourceChainBalance: Clone + Copy + Debug + PartialOrd + SaturatingAdd + Zero + Send + Sync; + type SourceChainBalance: Clone + + Copy + + Debug + + PartialOrd + + Sub + + SaturatingAdd + + Zero + + Send + + Sync; /// Number of the source header. type SourceHeaderNumber: BlockNumberBase; /// Hash of the source header. diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index c70fc532e9c11..282c3bc8b6b85 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -65,7 +65,7 @@ pub enum RelayerMode { /// The relayer doesn't care about rewards. Altruistic, /// The relayer will deliver all messages and confirmations as long as he's not losing any funds. - NoLosses, + Rational, } /// Message delivery race parameters. diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index a03a671c70ecf..260a72f3f0c72 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -540,8 +540,7 @@ where /// From given set of source nonces, that are ready to be delivered, select nonces /// to fit into single delivery transaction. /// -/// The function returns nonces that are NOT selected for current batch and will be -/// delivered later. +/// The function returns last nonce that must be delivered to the target chain. #[allow(clippy::too_many_arguments)] async fn select_nonces_for_delivery_transaction( relayer_mode: RelayerMode, @@ -564,6 +563,8 @@ async fn select_nonces_for_delivery_transaction( let mut selected_unpaid_weight: Weight = 0; let mut selected_size: u32 = 0; let mut selected_count: MessageNonce = 0; + let mut selected_reward = P::SourceChainBalance::zero(); + let mut selected_cost = P::SourceChainBalance::zero(); let mut total_reward = P::SourceChainBalance::zero(); let mut total_confirmations_cost = P::SourceChainBalance::zero(); @@ -647,7 +648,7 @@ async fn select_nonces_for_delivery_transaction( RelayerMode::Altruistic => { soft_selected_count = index + 1; } - RelayerMode::NoLosses => { + RelayerMode::Rational => { let delivery_transaction_cost = lane_target_client .estimate_delivery_transaction_in_source_tokens( 0..=(new_selected_count as MessageNonce - 1), @@ -698,9 +699,11 @@ async fn select_nonces_for_delivery_transaction( ); } - // NoLosses relayer never want to lose his funds + // Rational relayer never want to lose his funds if total_reward >= total_cost { soft_selected_count = index + 1; + selected_reward = total_reward; + selected_cost = total_cost; } } } @@ -732,6 +735,18 @@ async fn select_nonces_for_delivery_transaction( } if hard_selected_count != 0 { + if relayer_mode != RelayerMode::Altruistic { + log::trace!( + target: "bridge", + "Expected reward from delivering nonces [{:?}; {:?}] is: {:?} - {:?} = {:?}", + hard_selected_begin_nonce, + hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1, + selected_reward, + selected_cost, + selected_reward - selected_cost, + ); + } + Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1) } else { None @@ -1151,9 +1166,9 @@ mod tests { } #[async_std::test] - async fn no_losses_relayer_is_delivering_messages_if_cost_is_equal_to_reward() { + async fn rational_relayer_is_delivering_messages_if_cost_is_equal_to_reward() { let (state, mut strategy) = prepare_strategy(); - strategy.relayer_mode = RelayerMode::NoLosses; + strategy.relayer_mode = RelayerMode::Rational; // so now we have: // - 20..=23 with reward = cost @@ -1165,7 +1180,7 @@ mod tests { } #[async_std::test] - async fn no_losses_relayer_is_not_delivering_messages_if_cost_is_larger_than_reward() { + async fn rational_relayer_is_not_delivering_messages_if_cost_is_larger_than_reward() { let (mut state, mut strategy) = prepare_strategy(); let nonces = source_nonces( 24..=25, @@ -1175,7 +1190,7 @@ mod tests { ); strategy.strategy.source_nonces_updated(header_id(2), nonces); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - strategy.relayer_mode = RelayerMode::NoLosses; + strategy.relayer_mode = RelayerMode::Rational; // so now we have: // - 20..=23 with reward = cost @@ -1188,7 +1203,7 @@ mod tests { } #[async_std::test] - async fn no_losses_relayer_is_delivering_unpaid_messages() { + async fn rational_relayer_is_delivering_unpaid_messages() { async fn test_with_dispatch_fee_payment( dispatch_fee_payment: DispatchFeePayment, ) -> Option<(RangeInclusive, MessageProofParameters)> { @@ -1206,7 +1221,7 @@ mod tests { strategy.max_messages_in_single_batch = 100; strategy.max_messages_weight_in_single_batch = 100; strategy.max_messages_size_in_single_batch = 100; - strategy.relayer_mode = RelayerMode::NoLosses; + strategy.relayer_mode = RelayerMode::Rational; // so now we have: // - 20..=23 with reward = cost From 57538262eae3b5d32de215cc18e55c703bd80cd0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 12 Jul 2021 16:17:47 +0300 Subject: [PATCH 0510/1210] bump dependencies before start referencing polkadot repo (#1048) --- bin/millau/runtime/Cargo.toml | 2 +- bin/millau/runtime/src/lib.rs | 3 ++- bin/rialto/runtime/Cargo.toml | 2 +- bin/rialto/runtime/src/lib.rs | 3 ++- bin/runtime-common/Cargo.toml | 2 +- modules/currency-exchange/Cargo.toml | 2 +- modules/dispatch/Cargo.toml | 2 +- modules/ethereum-contract-builtin/Cargo.toml | 4 ++-- modules/ethereum/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 6 ++---- primitives/chain-millau/src/millau_hash.rs | 3 +-- primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 2 +- primitives/chain-wococo/Cargo.toml | 2 +- primitives/currency-exchange/Cargo.toml | 2 +- primitives/ethereum-poa/Cargo.toml | 4 ++-- primitives/header-chain/Cargo.toml | 2 +- primitives/message-dispatch/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 2 +- relays/bin-ethereum/Cargo.toml | 8 ++++---- relays/bin-substrate/Cargo.toml | 2 +- relays/client-ethereum/Cargo.toml | 4 ++-- relays/client-kusama/Cargo.toml | 2 +- relays/client-millau/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rialto/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-westend/Cargo.toml | 2 +- relays/client-wococo/Cargo.toml | 2 +- 36 files changed, 45 insertions(+), 46 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 367c1c3eef704..cb24864660d66 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } hex-literal = "0.3" serde = { version = "1.0.124", optional = true, features = ["derive"] } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 491304337358d..e98e6f306ac03 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -495,8 +495,9 @@ impl_runtime_apis! { fn validate_transaction( source: TransactionSource, tx: ::Extrinsic, + block_hash: ::Hash, ) -> TransactionValidity { - Executive::validate_transaction(source, tx) + Executive::validate_transaction(source, tx, block_hash) } } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index f66b8920c8a55..a082a62f8c01c 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e53beed389edd..b4a5d806c41d4 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -668,8 +668,9 @@ impl_runtime_apis! { fn validate_transaction( source: TransactionSource, tx: ::Extrinsic, + block_hash: ::Hash, ) -> TransactionValidity { - Executive::validate_transaction(source, tx) + Executive::validate_transaction(source, tx, block_hash) } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 07fe8910c21f8..64d7227874262 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 8094f0f2b6eeb..8f1f501591598 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -7,7 +7,7 @@ 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 } log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 6170af272ad9f..6ba291fc8ffce 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -7,7 +7,7 @@ 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 } log = { version = "0.4.14", default-features = false } # Bridge dependencies diff --git a/modules/ethereum-contract-builtin/Cargo.toml b/modules/ethereum-contract-builtin/Cargo.toml index 82e287a3abdcd..ffb98bc6bd85e 100644 --- a/modules/ethereum-contract-builtin/Cargo.toml +++ b/modules/ethereum-contract-builtin/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } -ethereum-types = "0.11.0" +codec = { package = "parity-scale-codec", version = "2.2.0" } +ethereum-types = "0.12.0" finality-grandpa = "0.14.0" hex = "0.4" log = "0.4.14" diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index fdd93ed73311b..732f510548339 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -7,7 +7,7 @@ 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 } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"], optional = true } log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 810dce3dd5a4c..da74faa87178a 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [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 } finality-grandpa = { version = "0.14.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index a26cf65c028ba..a2febf50af3b5 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bitvec = { version = "0.20", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 6dac97ddde601..5f58a7a50225f 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -7,7 +7,7 @@ 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 } # Substrate Dependencies diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index f4198e35c38c0..3628f9092091a 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -14,16 +14,15 @@ bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } -impl-codec = { version = "0.5.0", default-features = false } +impl-codec = { version = "0.5.1", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.9.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -max-encoded-len = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, features = ["derive"] } sp-api = { 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 } @@ -42,7 +41,6 @@ std = [ "hash256-std-hasher/std", "impl-codec/std", "impl-serde", - "max-encoded-len/std", "parity-util-mem/std", "serde", "sp-api/std", diff --git a/primitives/chain-millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs index 219ceb68a8249..936791217af18 100644 --- a/primitives/chain-millau/src/millau_hash.rs +++ b/primitives/chain-millau/src/millau_hash.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use frame_support::traits::MaxEncodedLen; use parity_util_mem::MallocSizeOf; use sp_runtime::traits::CheckEqual; @@ -23,7 +22,7 @@ use sp_runtime::traits::CheckEqual; fixed_hash::construct_fixed_hash! { /// Hash type used in Millau chain. - #[derive(MallocSizeOf, MaxEncodedLen)] + #[derive(MallocSizeOf)] pub struct MillauHash(64); } diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 33772c7890a07..15a81beeb1c19 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } smallvec = "1.6" # Bridge Dependencies diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index d5fda1ccef05a..42a9e67a7174f 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-header-chain = { path = "../header-chain", default-features = false } diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 88201dde9ac19..3748e7535e32f 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 43367ba7992b1..0e1fa451786d1 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -7,7 +7,7 @@ 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 } # Substrate Dependencies diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index cd2c3a97a0f32..a12b237029bfd 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -7,7 +7,7 @@ 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 } ethbloom = { version = "0.10.0", default-features = false, features = ["rlp"] } fixed-hash = { version = "0.7", default-features = false } hash-db = { version = "0.15.2", default-features = false } @@ -16,7 +16,7 @@ impl-serde = { version = "0.3.1", optional = true } libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } parity-bytes = { version = "0.1", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } -primitive-types = { version = "0.9", default-features = false, features = ["codec", "rlp"] } +primitive-types = { version = "0.10", default-features = false, features = ["codec", "rlp"] } rlp = { version = "0.5", default-features = false } serde = { version = "1.0", optional = true } serde-big-array = { version = "0.2", optional = true } diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index bf2268aeb411f..2c21184c93c41 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -7,7 +7,7 @@ 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 } finality-grandpa = { version = "0.14.0", default-features = false } serde = { version = "1.0", optional = true } diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 84fa48553a21a..f673a22fedb08 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } # Substrate Dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index b5b68220a4098..3f0c3550190fd 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bitvec = { version = "0.20", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" serde = { version = "1.0.101", optional = true, features = ["derive"] } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 995f948e5d476..4f0d73ae079dd 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.0.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 17fa96b2c908c..967df63e2e2eb 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -7,7 +7,7 @@ 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 } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 461e0ffe93ef6..3876f0200a9e9 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.14.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/relays/bin-ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml index e4620efe32554..26f89c7cec324 100644 --- a/relays/bin-ethereum/Cargo.toml +++ b/relays/bin-ethereum/Cargo.toml @@ -11,11 +11,11 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } env_logger = "0.8.3" -ethabi = { git = "https://github.com/paritytech/ethabi", branch = "td-eth-types-11" } -ethabi-contract = { git = "https://github.com/paritytech/ethabi", branch = "td-eth-types-11" } -ethabi-derive = { git = "https://github.com/paritytech/ethabi", branch = "td-eth-types-11" } +ethabi = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } +ethabi-contract = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } +ethabi-derive = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } futures = "0.3.12" hex = "0.4" hex-literal = "0.3" diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 1e38a33e9ddd8..6b68fac986a58 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } futures = "0.3.12" hex = "0.4" log = "0.4.14" diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 64a76a6b5dae3..7e2b86a22dff6 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" bp-eth-poa = { path = "../../primitives/ethereum-poa" } -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" jsonrpsee-proc-macros = "=0.2.0-alpha.6" @@ -16,4 +16,4 @@ jsonrpsee-ws-client = "=0.2.0-alpha.6" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } -web3 = { version = "0.15", git = "https://github.com/tomusdrw/rust-web3", branch ="td-ethabi", default-features = false } +web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "bump-deps" } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index b9c397bca6c01..cd15834a873fb 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 5f40e1e557ffe..342c6dc07fca9 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index b148745f5a987..05228a59514c5 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index a1c30da389a2a..4c43268d4d2d4 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 5611ac27b1ce4..e0a20da778452 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 4d7b6a047287d..85e4636cb74fe 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } jsonrpsee-proc-macros = "=0.2.0-alpha.6" jsonrpsee-ws-client = "=0.2.0-alpha.6" log = "0.4.11" diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index a408ae3a46daf..68b70c8f59b0a 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index c1b9aafd95e7c..5d9e6ed4bd4da 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0" } +codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } From 7c6824aa50451222fa847314ca4eb65dab855080 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 15 Jul 2021 12:08:39 +0300 Subject: [PATCH 0511/1210] Pay dispatch fee at target chain cli option (#1043) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * dispatch-fee-payment=at-target-chain cli option * generate at-target-chain messages * Update relays/bin-substrate/src/cli/send_message.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- relays/bin-substrate/src/chains/millau.rs | 12 +++- relays/bin-substrate/src/chains/mod.rs | 6 ++ relays/bin-substrate/src/chains/rialto.rs | 12 +++- relays/bin-substrate/src/cli/send_message.rs | 64 ++++++++++++++++++-- 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 3cba16ea32f44..7a86455df939f 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -19,7 +19,9 @@ use crate::cli::{ bridge, encode_call::{self, Call, CliEncodeCall}, - encode_message, send_message, CliChain, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; @@ -98,7 +100,13 @@ impl CliChain for Millau { let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; - Ok(send_message::message_payload(spec_version, weight, origin, &call)) + Ok(send_message::message_payload( + spec_version, + weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) } } } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index bd228ac7c4f09..9aec7d19d2582 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -146,6 +146,7 @@ mod tests { call.get_dispatch_info().weight, bp_message_dispatch::CallOrigin::SourceRoot, &call, + send_message::DispatchFeePayment::AtSourceChain, ); assert_eq!(Millau::verify_message(&payload), Ok(())); @@ -156,6 +157,7 @@ mod tests { call.get_dispatch_info().weight, bp_message_dispatch::CallOrigin::SourceRoot, &call, + send_message::DispatchFeePayment::AtSourceChain, ); assert!(Millau::verify_message(&payload).is_err()); } @@ -183,6 +185,7 @@ mod tests { maximal_dispatch_weight, bp_message_dispatch::CallOrigin::SourceRoot, &call, + send_message::DispatchFeePayment::AtSourceChain, ); assert_eq!(Millau::verify_message(&payload), Ok(())); @@ -191,6 +194,7 @@ mod tests { maximal_dispatch_weight + 1, bp_message_dispatch::CallOrigin::SourceRoot, &call, + send_message::DispatchFeePayment::AtSourceChain, ); assert!(Millau::verify_message(&payload).is_err()); } @@ -208,6 +212,7 @@ mod tests { maximal_dispatch_weight, bp_message_dispatch::CallOrigin::SourceRoot, &call, + send_message::DispatchFeePayment::AtSourceChain, ); assert_eq!(Rialto::verify_message(&payload), Ok(())); @@ -216,6 +221,7 @@ mod tests { maximal_dispatch_weight + 1, bp_message_dispatch::CallOrigin::SourceRoot, &call, + send_message::DispatchFeePayment::AtSourceChain, ); assert!(Rialto::verify_message(&payload).is_err()); } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 9a6185b4fc7d9..995ae7ae0d6d0 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -19,7 +19,9 @@ use crate::cli::{ bridge, encode_call::{self, Call, CliEncodeCall}, - encode_message, send_message, CliChain, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; @@ -95,7 +97,13 @@ impl CliChain for Rialto { let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; - Ok(send_message::message_payload(spec_version, weight, origin, &call)) + Ok(send_message::message_payload( + spec_version, + weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) } } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index ab802546442ec..496b3707a9d73 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -22,7 +22,6 @@ use crate::cli::{ TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; -use bp_runtime::messages::DispatchFeePayment; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{Chain, TransactionSignScheme}; @@ -30,7 +29,26 @@ use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; use std::fmt::Debug; use structopt::StructOpt; -use strum::VariantNames; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +/// Relayer operating mode. +#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)] +#[strum(serialize_all = "kebab_case")] +pub enum DispatchFeePayment { + /// The dispacth fee is paid at the source chain. + AtSourceChain, + /// The dispatch fee is paid at the target chain. + AtTargetChain, +} + +impl From for bp_runtime::messages::DispatchFeePayment { + fn from(dispatch_fee_payment: DispatchFeePayment) -> Self { + match dispatch_fee_payment { + DispatchFeePayment::AtSourceChain => Self::AtSourceChain, + DispatchFeePayment::AtTargetChain => Self::AtTargetChain, + } + } +} /// Send bridge message. #[derive(StructOpt)] @@ -51,6 +69,14 @@ pub struct SendMessage { /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, + /// Where dispatch fee is paid? + #[structopt( + long, + possible_values = DispatchFeePayment::VARIANTS, + case_insensitive = true, + default_value = "at-source-chain", + )] + dispatch_fee_payment: DispatchFeePayment, /// Dispatch weight of the message. If not passed, determined automatically. #[structopt(long)] dispatch_weight: Option>, @@ -76,6 +102,7 @@ impl SendMessage { target_signer, target_signer_password, ref mut message, + dispatch_fee_payment, dispatch_weight, origin, bridge, @@ -124,6 +151,7 @@ impl SendMessage { } }, &target_call, + *dispatch_fee_payment, ) }; Ok(payload) @@ -212,6 +240,7 @@ pub(crate) fn message_payload( weight: Weight, origin: CallOrigin, call: &impl Encode, + dispatch_fee_payment: DispatchFeePayment, ) -> MessagePayload> where SAccountId: Encode + Debug, @@ -223,7 +252,7 @@ where spec_version, weight, origin, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + dispatch_fee_payment: dispatch_fee_payment.into(), call: HexBytes::encode(call), }; @@ -281,7 +310,7 @@ mod tests { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, weight: 1038000, origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, call: hex!("0401081234").to_vec(), } ); @@ -325,7 +354,7 @@ mod tests { sp_keyring::AccountKeyring::Bob.into(), signature, ), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, call: hex!("0701081234").to_vec(), } ); @@ -350,4 +379,29 @@ mod tests { assert!(send_message.is_err()); } + + #[test] + fn accepts_non_default_dispatch_fee_payment() { + // given + let mut send_message = SendMessage::from_iter(vec![ + "send-message", + "rialto-to-millau", + "--source-port", + "1234", + "--source-signer", + "//Alice", + "--dispatch-fee-payment", + "at-target-chain", + "remark", + ]); + + // when + let payload = send_message.encode_payload().unwrap(); + + // then + assert_eq!( + payload.dispatch_fee_payment, + bp_runtime::messages::DispatchFeePayment::AtTargetChain + ); + } } From 92dcacab5224cf000403b485981ff3abbe7b1c88 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 15 Jul 2021 12:08:50 +0300 Subject: [PATCH 0512/1210] enable weight fee adjustent in Rialto/Millau (#1044) --- bin/millau/runtime/src/lib.rs | 16 ++++++++++++--- bin/millau/runtime/src/rialto_messages.rs | 17 +++++++++++++--- bin/rialto/runtime/src/lib.rs | 16 ++++++++++++--- bin/rialto/runtime/src/millau_messages.rs | 17 +++++++++++++--- bin/runtime-common/src/messages.rs | 24 +++++++++++++++-------- 5 files changed, 70 insertions(+), 20 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index e98e6f306ac03..46921edd584e3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -37,7 +37,7 @@ use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; -use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; +use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -45,7 +45,7 @@ use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys} use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, MultiSigner, + ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -273,13 +273,23 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; + // values for following parameters are copypasted from polkadot repo, but it is fine + // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); + pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; - type FeeMultiplierUpdate = (); + type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< + Runtime, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + >; } impl pallet_sudo::Config for Runtime { diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 12af2c328521b..2ebf17686f91e 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -31,15 +31,19 @@ use frame_support::{ weights::{DispatchClass, Weight}, RuntimeDebug, }; -use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Initial value of `RialtoToMillauConversionRate` parameter. pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +/// Initial value of `RialtoFeeMultiplier` parameter. +pub const INITIAL_RIALTO_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); parameter_types! { /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE; + /// Fee multiplier value at Rialto chain. + pub storage RialtoFeeMultiplier: FixedU128 = INITIAL_RIALTO_FEE_MULTIPLIER; } /// Message payload for Millau -> Rialto messages. @@ -128,11 +132,15 @@ impl messages::ThisChainWithMessages for Millau { } fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { + // `transaction` may represent transaction from the future, when multiplier value will + // be larger, so let's use slightly increased value + let multiplier = FixedU128::saturating_from_rational(110, 100) + .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, - FixedU128::zero(), + multiplier, |weight| weight as _, transaction, ) @@ -195,11 +203,14 @@ impl messages::BridgedChainWithMessages for Rialto { } fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { + // we don't have a direct access to the value of multiplier at Rialto chain + // => it is a messages module parameter + let multiplier = RialtoFeeMultiplier::get(); // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, - FixedU128::zero(), + multiplier, |weight| weight as _, transaction, ) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index b4a5d806c41d4..bb20312d1d297 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -43,7 +43,7 @@ use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; -use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; +use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -51,7 +51,7 @@ use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys} use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, MultiSigner, + ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -380,13 +380,23 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; + // values for following parameters are copypasted from polkadot repo, but it is fine + // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); + pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); } impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; - type FeeMultiplierUpdate = (); + type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< + Runtime, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + >; } impl pallet_sudo::Config for Runtime { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index bf97478a0aa20..15e1d52f25525 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -31,15 +31,19 @@ use frame_support::{ weights::{DispatchClass, Weight}, RuntimeDebug, }; -use sp_runtime::{traits::Zero, FixedPointNumber, FixedU128}; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Initial value of `MillauToRialtoConversionRate` parameter. pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +/// Initial value of `MillauFeeMultiplier` parameter. +pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); parameter_types! { /// Millau to Rialto conversion rate. Initially we treat both tokens as equal. pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE; + /// Fee multiplier value at Millau chain. + pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER; } /// Message payload for Rialto -> Millau messages. @@ -128,11 +132,15 @@ impl messages::ThisChainWithMessages for Rialto { } fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { + // `transaction` may represent transaction from the future, when multiplier value will + // be larger, so let's use slightly increased value + let multiplier = FixedU128::saturating_from_rational(110, 100) + .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, - FixedU128::zero(), + multiplier, |weight| weight as _, transaction, ) @@ -195,11 +203,14 @@ impl messages::BridgedChainWithMessages for Millau { } fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { + // we don't have a direct access to the value of multiplier at Millau chain + // => it is a messages module parameter + let multiplier = MillauFeeMultiplier::get(); // in our testnets, both per-byte fee and weight-to-fee are 1:1 messages::transaction_payment( bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, - FixedU128::zero(), + multiplier, |weight| weight as _, transaction, ) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 72249e4f4e338..08ef582993e6b 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -38,7 +38,7 @@ use frame_support::{ }; use hash_db::Hasher; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, + traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero}, FixedPointNumber, FixedPointOperand, FixedU128, }; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; @@ -491,6 +491,7 @@ pub mod target { MessageDispatch>, BalanceOf>> for FromBridgedChainMessageDispatch where + BalanceOf>: Saturating + FixedPointOperand, ThisDispatchInstance: frame_support::traits::Instance, ThisRuntime: pallet_bridge_dispatch::Config + pallet_transaction_payment::Config, @@ -525,13 +526,20 @@ pub mod target { message_id, message.data.payload.map_err(drop), |dispatch_origin, dispatch_weight| { - ThisCurrency::transfer( - dispatch_origin, - relayer_account, - ThisRuntime::WeightToFee::calc(&dispatch_weight), - ExistenceRequirement::AllowDeath, - ) - .map_err(drop) + let unadjusted_weight_fee = ThisRuntime::WeightToFee::calc(&dispatch_weight); + let fee_multiplier = pallet_transaction_payment::Pallet::::next_fee_multiplier(); + let adjusted_weight_fee = fee_multiplier.saturating_mul_int(unadjusted_weight_fee); + if !adjusted_weight_fee.is_zero() { + ThisCurrency::transfer( + dispatch_origin, + relayer_account, + adjusted_weight_fee, + ExistenceRequirement::AllowDeath, + ) + .map_err(drop) + } else { + Ok(()) + } }, ) } From e0708595fd68ef98bf376a7ef2ac950e466f5092 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Jul 2021 14:03:59 +0300 Subject: [PATCH 0513/1210] Update jsonrpsee reference (#1049) * update jsonrpsee * test * Revert "test" This reverts commit 2b69652ab92ff0d9649088c76faed2c94384540d. --- .../bin-substrate/src/headers_initialize.rs | 18 ++++++++++----- relays/client-ethereum/Cargo.toml | 4 ++-- relays/client-ethereum/src/error.rs | 5 ++-- relays/client-substrate/Cargo.toml | 4 ++-- relays/client-substrate/src/error.rs | 4 +--- .../client-substrate/src/finality_source.rs | 23 ++++++++++++------- 6 files changed, 34 insertions(+), 24 deletions(-) diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index c2eab1bd3534e..39d8ae706965d 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -108,12 +108,18 @@ async fn prepare_initialization_data( .map_err(|err| format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err))?; // Read next justification - the header that it finalizes will be used as initial header. - let justification = justifications.next().await.ok_or_else(|| { - format!( - "Failed to read {} justification from the stream: stream has ended unexpectedly", - SourceChain::NAME, - ) - })?; + let justification = justifications + .next() + .await + .map_err(|err| err.to_string()) + .and_then(|justification| justification.ok_or_else(|| "stream has ended unexpectedly".into())) + .map_err(|err| { + format!( + "Failed to read {} justification from the stream: {}", + SourceChain::NAME, + err, + ) + })?; // Read initial header. let justification: GrandpaJustification = Decode::decode(&mut &justification.0[..]) diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 7e2b86a22dff6..8ed3cc76f0661 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -11,8 +11,8 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa" } codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = "=0.2.0-alpha.6" -jsonrpsee-ws-client = "=0.2.0-alpha.6" +jsonrpsee-proc-macros = "0.2" +jsonrpsee-ws-client = "0.2" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index bcd8edc3f33ae..e01cdf1bf5594 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -57,10 +57,9 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::RpcError(RpcError::TransportError(_)) - // right now if connection to the ws server is dropped (after it is already established), - // we're getting this error + Error::RpcError(RpcError::Transport(_)) | Error::RpcError(RpcError::Internal(_)) + | Error::RpcError(RpcError::RestartNeeded(_)) | Error::ClientNotSynced(_), ) } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 85e4636cb74fe..7c3e381259cfe 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,8 +9,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.2.0" } -jsonrpsee-proc-macros = "=0.2.0-alpha.6" -jsonrpsee-ws-client = "=0.2.0-alpha.6" +jsonrpsee-proc-macros = "0.2" +jsonrpsee-ws-client = "0.2" log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 304229ede1986..f553d6867e957 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -71,9 +71,7 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::RpcError(RpcError::TransportError(_)) - // right now if connection to the ws server is dropped (after it is already established), - // we're getting this error + Error::RpcError(RpcError::Transport(_)) | Error::RpcError(RpcError::Internal(_)) | Error::RpcError(RpcError::RestartNeeded(_)) | Error::ClientNotSynced(_), diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 72a11ae99003b..546a3ede3e5a6 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -134,20 +134,27 @@ where self.client.clone().subscribe_justifications().await?, move |mut subscription| async move { loop { - let next_justification = subscription.next().await?; + let log_error = |err| { + log::error!( + target: "bridge", + "Failed to read justification target from the {} justifications stream: {:?}", + P::SOURCE_NAME, + err, + ); + }; + + let next_justification = subscription + .next() + .await + .map_err(|err| log_error(err.to_string())) + .ok()??; let decoded_justification = GrandpaJustification::::decode(&mut &next_justification.0[..]); let justification = match decoded_justification { Ok(j) => j, Err(err) => { - log::error!( - target: "bridge", - "Failed to decode justification target from the {} justifications stream: {:?}", - P::SOURCE_NAME, - err, - ); - + log_error(format!("decode failed with error {:?}", err)); continue; } }; From e0da70504f40998b2be02084de3a2f2976f71dae Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Jul 2021 14:45:16 +0300 Subject: [PATCH 0514/1210] Allow reading suri && password override from file (#1059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * allow reading suri && password override from file * fix clippy * Update relays/bin-substrate/src/cli/mod.rs Co-authored-by: Tomasz Drwięga * Update relays/bin-substrate/src/cli/mod.rs Co-authored-by: Tomasz Drwięga Co-authored-by: Tomasz Drwięga --- relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/cli/mod.rs | 126 ++++++++++++++++++- relays/bin-substrate/src/cli/send_message.rs | 21 +--- 3 files changed, 128 insertions(+), 20 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 6b68fac986a58..7b731e3cd707a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -63,3 +63,4 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +tempdir = "0.3" diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 49bc5dc8c8372..3088b06eb05ed 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -374,24 +374,61 @@ macro_rules! declare_chain_options { } #[doc = $chain " signing params."] - #[derive(StructOpt, Debug, PartialEq, Eq)] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] pub struct [<$chain SigningParams>] { #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] #[structopt(long)] - pub [<$chain_prefix _signer>]: String, + pub [<$chain_prefix _signer>]: Option, #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] #[structopt(long)] pub [<$chain_prefix _signer_password>]: Option, + + #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] + #[structopt(long)] + pub [<$chain_prefix _signer_file>]: Option, + #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] + #[structopt(long)] + pub [<$chain_prefix _signer_password_file>]: Option, } impl [<$chain SigningParams>] { /// Parse signing params into chain-specific KeyPair. pub fn to_keypair(&self) -> anyhow::Result { + let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { + (Some(suri), _) => suri.to_owned(), + (None, Some(suri_file)) => std::fs::read_to_string(suri_file) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI from file {:?}: {}", + suri_file, + err, + ))?, + (None, None) => return Err(anyhow::format_err!( + "One of options must be specified: '{}' or '{}'", + stringify!([<$chain_prefix _signer>]), + stringify!([<$chain_prefix _signer_file>]), + )), + }; + + let suri_password = match ( + self.[<$chain_prefix _signer_password>].as_ref(), + self.[<$chain_prefix _signer_password_file>].as_ref(), + ) { + (Some(suri_password), _) => Some(suri_password.to_owned()), + (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) + .map(Some) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI password from file {:?}: {}", + suri_password_file, + err, + ))?, + _ => None, + }; + use sp_core::crypto::Pair; Chain::KeyPair::from_string( - &self.[<$chain_prefix _signer>], - self.[<$chain_prefix _signer_password>].as_deref() + &suri, + suri_password.as_deref() ).map_err(|e| anyhow::format_err!("{:?}", e)) } } @@ -419,6 +456,7 @@ declare_chain_options!(Target, target); #[cfg(test)] mod tests { + use sp_core::Pair; use std::str::FromStr; use super::*; @@ -456,4 +494,84 @@ mod tests { // then assert_eq!(hex.0, hex2.0); } + + #[test] + fn reads_suri_from_file() { + const ALICE: &str = "//Alice"; + const BOB: &str = "//Bob"; + const ALICE_PASSWORD: &str = "alice_password"; + const BOB_PASSWORD: &str = "bob_password"; + + let alice = sp_core::sr25519::Pair::from_string(ALICE, Some(ALICE_PASSWORD)).unwrap(); + let bob = sp_core::sr25519::Pair::from_string(BOB, Some(BOB_PASSWORD)).unwrap(); + let bob_with_alice_password = sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); + + let temp_dir = tempdir::TempDir::new("reads_suri_from_file").unwrap(); + let mut suri_file_path = temp_dir.path().to_path_buf(); + let mut password_file_path = temp_dir.path().to_path_buf(); + suri_file_path.push("suri"); + password_file_path.push("password"); + std::fs::write(&suri_file_path, BOB.as_bytes()).unwrap(); + std::fs::write(&password_file_path, BOB_PASSWORD.as_bytes()).unwrap(); + + // when both seed and password are read from file + assert_eq!( + TargetSigningParams { + target_signer: Some(ALICE.into()), + target_signer_password: Some(ALICE_PASSWORD.into()), + + target_signer_file: None, + target_signer_password_file: None, + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(alice.public()), + ); + + // when both seed and password are read from file + assert_eq!( + TargetSigningParams { + target_signer: None, + target_signer_password: None, + + target_signer_file: Some(suri_file_path.clone()), + target_signer_password_file: Some(password_file_path.clone()), + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(bob.public()), + ); + + // when password are is overriden by cli option + assert_eq!( + TargetSigningParams { + target_signer: None, + target_signer_password: Some(ALICE_PASSWORD.into()), + + target_signer_file: Some(suri_file_path.clone()), + target_signer_password_file: Some(password_file_path.clone()), + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(bob_with_alice_password.public()), + ); + + // when both seed and password are overriden by cli options + assert_eq!( + TargetSigningParams { + target_signer: Some(ALICE.into()), + target_signer_password: Some(ALICE_PASSWORD.into()), + + target_signer_file: Some(suri_file_path), + target_signer_password_file: Some(password_file_path), + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(alice.public()), + ); + } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 496b3707a9d73..dca8205043a1c 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -60,12 +60,8 @@ pub struct SendMessage { source: SourceConnectionParams, #[structopt(flatten)] source_sign: SourceSigningParams, - /// The SURI of secret key to use when transactions are submitted to the Target node. - #[structopt(long, required_if("origin", "Target"))] - target_signer: Option, - /// The password for the SURI of secret key to use when transactions are submitted to the Target node. - #[structopt(long)] - target_signer_password: Option, + #[structopt(flatten)] + target_sign: TargetSigningParams, /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -99,8 +95,7 @@ impl SendMessage { crate::select_full_bridge!(self.bridge, { let SendMessage { source_sign, - target_signer, - target_signer_password, + target_sign, ref mut message, dispatch_fee_payment, dispatch_weight, @@ -129,12 +124,6 @@ impl SendMessage { match origin { Origins::Source => CallOrigin::SourceAccount(source_account_id), Origins::Target => { - let target_sign = TargetSigningParams { - target_signer: target_signer.clone().ok_or_else(|| { - anyhow::format_err!("The argument target_signer is not available") - })?, - target_signer_password: target_signer_password.clone(), - }; let target_sign = target_sign.to_keypair::()?; let digest = account_ownership_digest( &target_call, @@ -361,7 +350,7 @@ mod tests { } #[test] - fn target_signer_must_exist_if_origin_is_target() { + fn accepts_send_message_command_without_target_sign_options() { // given let send_message = SendMessage::from_iter_safe(vec![ "send-message", @@ -377,7 +366,7 @@ mod tests { "1234", ]); - assert!(send_message.is_err()); + assert!(send_message.is_ok()); } #[test] From 84d19d556e7d9fb2039ef84b5e34b940a1e3742c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Jul 2021 15:18:29 +0300 Subject: [PATCH 0515/1210] Use BABE to author blocks on Rialto (previously: Aura) (#1050) * use BABE to author blocks on Rialto (previously: Aura) * removed extra script * use bp_rialto::Moment * fix tests * Babe should control session end * test * Revert "test" This reverts commit 4bbbd76b1fe0aa65002fcfa600cfdc6d15c899e2. * clippy * fix test * Revert "Revert "test"" This reverts commit e9220184d4a14ef4f5a792b239e835528d3baa31. * Revert "Revert "Revert "test""" This reverts commit 9f56a5528945f1d8f82c6346826be68207bf9c75. --- bin/rialto/node/Cargo.toml | 5 +- bin/rialto/node/src/chain_spec.rs | 19 +- bin/rialto/node/src/command.rs | 4 +- bin/rialto/node/src/service.rs | 233 +++++-------------- bin/rialto/runtime/Cargo.toml | 8 +- bin/rialto/runtime/src/lib.rs | 124 +++++++--- primitives/chain-rialto/src/lib.rs | 10 +- relays/bin-substrate/src/cli/encode_call.rs | 8 +- relays/bin-substrate/src/cli/send_message.rs | 2 +- 9 files changed, 192 insertions(+), 221 deletions(-) diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 1c9ec8b5bb0ab..437f4d3c5ba91 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -33,7 +33,7 @@ sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -42,8 +42,9 @@ sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 4174cda24487e..31cd533c3131d 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -16,11 +16,11 @@ use bp_rialto::derive_account_from_millau_id; use rialto_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig, + AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_consensus_babe::AuthorityId as BabeId; use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -56,11 +56,11 @@ where AccountPublic::from(get_from_seed::(seed)).into_account() } -/// Helper function to generate an authority key for Aura -pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { +/// Helper function to generate an authority key for Babe +pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, BabeId, GrandpaId) { ( get_account_id_from_seed::(s), - get_from_seed::(s), + get_from_seed::(s), get_from_seed::(s), ) } @@ -174,12 +174,12 @@ impl Alternative { } } -fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { - SessionKeys { aura, grandpa } +fn session_keys(babe: BabeId, grandpa: GrandpaId) -> SessionKeys { + SessionKeys { babe, grandpa } } fn testnet_genesis( - initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, + initial_authorities: Vec<(AccountId, BabeId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, @@ -192,8 +192,9 @@ fn testnet_genesis( balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, - aura: AuraConfig { + babe: BabeConfig { authorities: Vec::new(), + epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), }, bridge_rialto_poa: load_rialto_poa_bridge_config(), bridge_kovan: load_kovan_bridge_config(), diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index a9930c57417ec..226a21d841dfb 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -162,7 +162,9 @@ pub fn run() -> sc_cli::Result<()> { runner .run_node_until_exit(|config| async move { match config.role { - Role::Light => service::new_light(config), + Role::Light => Err(sc_service::Error::Other( + "Light client is not supported by this node".into(), + )), _ => service::new_full(config), } }) diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 35f923c77cc9a..77d63a68dd99e 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -19,30 +19,28 @@ // ===================================================================================== // ===================================================================================== // ===================================================================================== -// UPDATE GUIDE: -// 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); -// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom RPCs; -// 3) fix compilation errors; -// 4) test :) +// There's no easy way to update this file. Currently it is a merge of two files: +// 1) node-template/src/service.rs from Substrate repo; +// 2) node/service/src/lib.rs from Polkadot repo. +// +// The main things to notice when updating are: +// 1) we are using Babe for authoring blocks; +// 2) support for light client is dropped as we are not using it now. +// ===========================================s========================================== // ===================================================================================== // ===================================================================================== -// ===================================================================================== - -//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. use rialto_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::{ExecutorProvider, RemoteBackend}; -use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; +use sc_client_api::ExecutorProvider; +use sc_consensus_babe::SlotProportion; use sc_executor::native_executor_instance; -pub use sc_executor::NativeExecutor; - use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_consensus::SlotData; -use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; +pub use sc_executor::NativeExecutor; + // Our native executor instance. native_executor_instance!( pub Executor, @@ -54,6 +52,7 @@ native_executor_instance!( type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; +type FullGrandpaBlockImport = sc_finality_grandpa::GrandpaBlockImport; #[allow(clippy::type_complexity)] pub fn new_partial( @@ -66,8 +65,10 @@ pub fn new_partial( sp_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport, + FullGrandpaBlockImport, sc_finality_grandpa::LinkHalf, + sc_consensus_babe::BabeBlockImport, + sc_consensus_babe::BabeLink, Option, ), >, @@ -115,29 +116,36 @@ pub fn new_partial( select_chain.clone(), telemetry.as_ref().map(|x| x.handle()), )?; + let justification_import = grandpa_block_import.clone(); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let (babe_block_import, babe_link) = sc_consensus_babe::block_import( + sc_consensus_babe::Config::get_or_compute(&*client)?, + grandpa_block_import.clone(), + client.clone(), + )?; - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { + let slot_duration = babe_link.config().slot_duration(); + let import_queue = sc_consensus_babe::import_queue( + babe_link.clone(), + babe_block_import.clone(), + Some(Box::new(justification_import)), + client.clone(), + select_chain.clone(), + move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( *timestamp, slot_duration, ); Ok((timestamp, slot)) }, - spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; + &task_manager.spawn_essential_handle(), + config.prometheus_registry(), + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + telemetry.as_ref().map(|x| x.handle()), + )?; Ok(sc_service::PartialComponents { client, @@ -147,7 +155,13 @@ pub fn new_partial( keystore_container, select_chain, transaction_pool, - other: (grandpa_block_import, grandpa_link, telemetry), + other: ( + grandpa_block_import, + grandpa_link, + babe_block_import, + babe_link, + telemetry, + ), }) } @@ -168,7 +182,7 @@ pub fn new_full(mut config: Configuration) -> Result mut keystore_container, select_chain, transaction_pool, - other: (block_import, grandpa_link, mut telemetry), + other: (_grandpa_block_import, grandpa_link, babe_block_import, babe_link, mut telemetry), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -268,7 +282,7 @@ pub fn new_full(mut config: Configuration) -> Result })?; if role.is_authority() { - let proposer_factory = sc_basic_authorship::ProposerFactory::new( + let proposer = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), transaction_pool, @@ -278,39 +292,38 @@ pub fn new_full(mut config: Configuration) -> Result let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let raw_slot_duration = slot_duration.slot_duration(); - - let aura = sc_consensus_aura::start_aura::(StartAuraParams { - slot_duration, + let slot_duration = babe_link.config().slot_duration(); + let babe_config = sc_consensus_babe::BabeParams { + keystore: keystore_container.sync_keystore(), client, select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { + env: proposer, + block_import: babe_block_import, + sync_oracle: network.clone(), + justification_sync_link: network.clone(), + create_inherent_data_providers: move |_parent, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( *timestamp, - raw_slot_duration, + slot_duration, ); Ok((timestamp, slot)) }, force_authoring, backoff_authoring_blocks, - keystore: keystore_container.sync_keystore(), + babe_link, can_author_with, - sync_oracle: network.clone(), - justification_sync_link: network.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + block_proposal_slot_portion: SlotProportion::new(0.5), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; + }; - // the AURA authoring task is considered essential, i.e. if it - // fails we take down the service with it. - task_manager.spawn_essential_handle().spawn_blocking("aura", aura); + let babe = sc_consensus_babe::start_babe(babe_config)?; + task_manager + .spawn_essential_handle() + .spawn_blocking("babe-proposer", babe); } // if the node isn't actively participating in consensus then it doesn't @@ -359,125 +372,3 @@ pub fn new_full(mut config: Configuration) -> Result network_starter.start_network(); Ok(task_manager) } - -/// Builds a new service for a light client. -pub fn new_light(mut config: Configuration) -> Result { - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let (client, backend, keystore_container, mut task_manager, on_demand) = - sc_service::new_light_parts::( - &config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - )?; - - let mut telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); - telemetry - }); - - config - .network - .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config()); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( - config.transaction_pool.clone(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - on_demand.clone(), - )); - - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( - client.clone(), - &(client.clone() as Arc<_>), - select_chain, - telemetry.as_ref().map(|x| x.handle()), - )?; - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); - - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import)), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::NeverCanAuthor, - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; - - let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - })?; - - if config.offchain_worker.enabled { - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); - } - - let enable_grandpa = !config.disable_grandpa; - if enable_grandpa { - let name = config.network.node_name.clone(); - - let config = sc_finality_grandpa::Config { - gossip_duration: std::time::Duration::from_millis(333), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore: None, - local_role: config.role.clone(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - task_manager.spawn_handle().spawn_blocking( - "grandpa-observer", - sc_finality_grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?, - ); - } - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - remote_blockchain: Some(backend.remote_blockchain()), - transaction_pool, - task_manager: &mut task_manager, - on_demand: Some(on_demand), - rpc_extensions_builder: Box::new(|_, _| ()), - config, - client, - keystore: keystore_container.sync_keystore(), - backend, - network, - system_rpc_tx, - telemetry: telemetry.as_mut(), - })?; - - network_starter.start_network(); - Ok(task_manager) -} diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index a082a62f8c01c..d986a33f4b23e 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -39,7 +39,7 @@ frame-executive = { git = "https://github.com/paritytech/substrate", branch = "m frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } @@ -50,7 +50,7 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-consensus-babe = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } @@ -89,7 +89,7 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "log/std", - "pallet-aura/std", + "pallet-babe/std", "pallet-balances/std", "pallet-bridge-currency-exchange/std", "pallet-bridge-dispatch/std", @@ -106,7 +106,7 @@ std = [ "serde", "sp-api/std", "sp-block-builder/std", - "sp-consensus-aura/std", + "sp-consensus-babe/std", "sp-core/std", "sp-finality-grandpa/std", "sp-inherents/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index bb20312d1d297..fe503154c8d51 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -45,7 +45,6 @@ use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}; use sp_runtime::{ @@ -127,7 +126,7 @@ pub mod opaque { impl_opaque_keys! { pub struct SessionKeys { - pub aura: Aura, + pub babe: Babe, pub grandpa: Grandpa, } } @@ -214,8 +213,34 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} -impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; +/// The BABE epoch configuration at genesis. +pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = + sp_consensus_babe::BabeEpochConfiguration { + c: bp_rialto::time_units::PRIMARY_PROBABILITY, + allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryVRFSlots, + }; + +parameter_types! { + pub const EpochDuration: u64 = bp_rialto::time_units::EPOCH_DURATION_IN_SLOTS as u64; + pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK; +} + +impl pallet_babe::Config for Runtime { + type EpochDuration = EpochDuration; + type ExpectedBlockTime = ExpectedBlockTime; + + // session module is the trigger + type EpochChangeTrigger = pallet_babe::ExternalTrigger; + + // equivocation related configuration - we don't expect any equivocations in our testnets + type KeyOwnerProofSystem = (); + type KeyOwnerProof = + >::Proof; + type KeyOwnerIdentification = + >::IdentificationTuple; + type HandleEquivocation = (); + + type WeightInfo = (); } type RialtoPoA = pallet_bridge_eth_poa::Instance1; @@ -347,8 +372,8 @@ parameter_types! { impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. - type Moment = u64; - type OnTimestampSet = Aura; + type Moment = bp_rialto::Moment; + type OnTimestampSet = Babe; type MinimumPeriod = MinimumPeriod; // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); @@ -404,17 +429,12 @@ impl pallet_sudo::Config for Runtime { type Call = Call; } -parameter_types! { - pub const Period: BlockNumber = bp_rialto::SESSION_LENGTH; - pub const Offset: BlockNumber = 0; -} - impl pallet_session::Config for Runtime { type Event = Event; type ValidatorId = ::AccountId; type ValidatorIdOf = (); - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; + type ShouldEndSession = Babe; + type NextSessionRotation = Babe; type SessionManager = pallet_shift_session_manager::Pallet; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; @@ -513,23 +533,32 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + + // Must be before session. + Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned}, + + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + + // Consensus support. + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + ShiftSessionManager: pallet_shift_session_manager::{Pallet}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, + + // Eth-PoA chains bridge modules. BridgeRialtoPoa: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, BridgeKovan: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, + + // Millau bridge modules. BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event}, - System: frame_system::{Pallet, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Aura: pallet_aura::{Pallet, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - ShiftSessionManager: pallet_shift_session_manager::{Pallet}, } ); @@ -690,13 +719,52 @@ impl_runtime_apis! { } } - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + impl sp_consensus_babe::BabeApi for Runtime { + fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { + // The choice of `c` parameter (where `1 - c` represents the + // probability of a slot being empty), is done in accordance to the + // slot duration and expected target block time, for safely + // resisting network delays of maximum two seconds. + // + sp_consensus_babe::BabeGenesisConfiguration { + slot_duration: Babe::slot_duration(), + epoch_length: EpochDuration::get(), + c: BABE_GENESIS_EPOCH_CONFIG.c, + genesis_authorities: Babe::authorities(), + randomness: Babe::randomness(), + allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots, + } + } + + fn current_epoch_start() -> sp_consensus_babe::Slot { + Babe::current_epoch_start() + } + + fn current_epoch() -> sp_consensus_babe::Epoch { + Babe::current_epoch() + } + + fn next_epoch() -> sp_consensus_babe::Epoch { + Babe::next_epoch() + } + + fn generate_key_ownership_proof( + _slot: sp_consensus_babe::Slot, + _authority_id: sp_consensus_babe::AuthorityId, + ) -> Option { + None } - fn authorities() -> Vec { - Aura::authorities() + fn submit_report_equivocation_unsigned_extrinsic( + equivocation_proof: sp_consensus_babe::EquivocationProof<::Header>, + key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, + ) -> Option<()> { + let key_owner_proof = key_owner_proof.decode()?; + + Babe::submit_unsigned_equivocation_report( + equivocation_proof, + key_owner_proof, + ) } } diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 8139372959e35..4fe05547b530b 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -105,7 +105,7 @@ pub use time_units::*; /// Human readable time units defined in terms of number of blocks. pub mod time_units { - use super::BlockNumber; + use super::{BlockNumber, SESSION_LENGTH}; pub const MILLISECS_PER_BLOCK: u64 = 6000; pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; @@ -113,6 +113,11 @@ pub mod time_units { pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); pub const HOURS: BlockNumber = MINUTES * 60; pub const DAYS: BlockNumber = HOURS * 24; + + pub const EPOCH_DURATION_IN_SLOTS: BlockNumber = SESSION_LENGTH; + + // 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. + pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); } /// Block number type used in Rialto. @@ -140,6 +145,9 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u128; +/// An instant or duration in time. +pub type Moment = u64; + /// Rialto chain. #[derive(RuntimeDebug)] pub struct Rialto; diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 1ae636623b047..343b44c378627 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -209,7 +209,7 @@ mod tests { // then assert_eq!( format!("{:?}", hex), - "0x0c00d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" + "0x0400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" ); } @@ -222,7 +222,7 @@ mod tests { let hex = encode_call.encode().unwrap(); // then - assert!(format!("{:?}", hex).starts_with("0x070154556e69782074696d653a")); + assert!(format!("{:?}", hex).starts_with("0x000154556e69782074696d653a")); } #[test] @@ -240,7 +240,7 @@ mod tests { let hex = encode_call.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x0701081234"); + assert_eq!(format!("{:?}", hex), "0x0001081234"); } #[test] @@ -253,7 +253,7 @@ mod tests { let hex = encode_call.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x070130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x000130000000000000000000000000"); } #[test] diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index dca8205043a1c..6ec955ed203a5 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -344,7 +344,7 @@ mod tests { signature, ), dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, - call: hex!("0701081234").to_vec(), + call: hex!("0001081234").to_vec(), } ); } From 6d9a1289a60f6236e0c73028b8c339eb8cf7c30b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 20 Jul 2021 15:18:51 +0300 Subject: [PATCH 0516/1210] use tokio reactor to execute jsonrpsee futures (#1061) --- relays/bin-ethereum/src/rialto_client.rs | 10 +- relays/bin-substrate/src/cli/send_message.rs | 5 +- relays/bin-substrate/src/finality_target.rs | 7 +- .../bin-substrate/src/headers_initialize.rs | 10 +- relays/bin-substrate/src/messages_source.rs | 4 +- relays/bin-substrate/src/messages_target.rs | 11 +- relays/client-ethereum/Cargo.toml | 1 + relays/client-ethereum/src/client.rs | 168 +++++++----- relays/client-ethereum/src/error.rs | 18 ++ relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/client.rs | 252 ++++++++++++------ relays/client-substrate/src/error.rs | 16 ++ .../client-substrate/src/finality_source.rs | 2 +- 13 files changed, 337 insertions(+), 168 deletions(-) diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index d9c0f265cbb95..1ec1e7df79403 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -155,11 +155,12 @@ impl SubmitEthereumHeaders for SubstrateClient { headers: Vec, ) -> SubmittedHeaders { let ids = headers.iter().map(|header| header.id()).collect(); + let genesis_hash = *self.genesis_hash(); let submission_result = async { - self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), |transaction_nonce| { + self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |transaction_nonce| { Bytes( Rialto::sign_transaction( - *self.genesis_hash(), + genesis_hash, ¶ms, transaction_nonce, instance.build_signed_header_call(headers), @@ -257,10 +258,11 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { instance: Arc, proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { - self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), |transaction_nonce| { + let genesis_hash = *self.genesis_hash(); + self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |transaction_nonce| { Bytes( Rialto::sign_transaction( - *self.genesis_hash(), + genesis_hash, ¶ms, transaction_nonce, instance.build_currency_exchange_call(proof), diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 6ec955ed203a5..2834474579644 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -176,10 +176,11 @@ impl SendMessage { fee, })?; + let source_genesis_hash = *source_client.genesis_hash(); source_client - .submit_signed_extrinsic(source_sign.public().into(), |transaction_nonce| { + .submit_signed_extrinsic(source_sign.public().into(), move |transaction_nonce| { let signed_source_call = Source::sign_transaction( - *source_client.genesis_hash(), + source_genesis_hash, &source_sign, transaction_nonce, send_message_call, diff --git a/relays/bin-substrate/src/finality_target.rs b/relays/bin-substrate/src/finality_target.rs index ffa10cabacbfa..6c4c384d11a60 100644 --- a/relays/bin-substrate/src/finality_target.rs +++ b/relays/bin-substrate/src/finality_target.rs @@ -80,10 +80,11 @@ where } async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), SubstrateError> { + let transactions_author = self.pipeline.transactions_author(); + let pipeline = self.pipeline.clone(); self.client - .submit_signed_extrinsic(self.pipeline.transactions_author(), move |transaction_nonce| { - self.pipeline - .make_submit_finality_proof_transaction(transaction_nonce, header, proof) + .submit_signed_extrinsic(transactions_author, move |transaction_nonce| { + pipeline.make_submit_finality_proof_transaction(transaction_nonce, header, proof) }) .await .map(drop) diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/bin-substrate/src/headers_initialize.rs index 39d8ae706965d..d3a78028e0e72 100644 --- a/relays/bin-substrate/src/headers_initialize.rs +++ b/relays/bin-substrate/src/headers_initialize.rs @@ -39,7 +39,9 @@ pub async fn initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes, + prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + + Send + + 'static, ) { let result = do_initialize( source_client, @@ -72,7 +74,9 @@ async fn do_initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes, + prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + + Send + + 'static, ) -> Result { let initialization_data = prepare_initialization_data(source_client).await?; log::info!( @@ -102,7 +106,7 @@ async fn prepare_initialization_data( // But now there are problems with this approach - `CurrentSetId` may return invalid value. So here // we're waiting for the next justification, read the authorities set and then try to figure out // the set id with bruteforce. - let mut justifications = source_client + let justifications = source_client .subscribe_justifications() .await .map_err(|err| format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err))?; diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/bin-substrate/src/messages_source.rs index 2271d3e4f1447..6792848e4a70b 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/bin-substrate/src/messages_source.rs @@ -233,10 +233,10 @@ where generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, ) -> Result<(), SubstrateError> { + let lane = self.lane.clone(); self.client .submit_signed_extrinsic(self.lane.source_transactions_author(), move |transaction_nonce| { - self.lane - .make_messages_receiving_proof_transaction(transaction_nonce, generated_at_block, proof) + lane.make_messages_receiving_proof_transaction(transaction_nonce, generated_at_block, proof) }) .await?; Ok(()) diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/bin-substrate/src/messages_target.rs index bbee261c6d8e4..666bfc48c2a71 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/bin-substrate/src/messages_target.rs @@ -219,14 +219,11 @@ where nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result, SubstrateError> { + let lane = self.lane.clone(); + let nonces_clone = nonces.clone(); self.client - .submit_signed_extrinsic(self.lane.target_transactions_author(), |transaction_nonce| { - self.lane.make_messages_delivery_transaction( - transaction_nonce, - generated_at_header, - nonces.clone(), - proof, - ) + .submit_signed_extrinsic(self.lane.target_transactions_author(), move |transaction_nonce| { + lane.make_messages_delivery_transaction(transaction_nonce, generated_at_header, nonces_clone, proof) }) .await?; Ok(nonces) diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 8ed3cc76f0661..53add5cf58a65 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -16,4 +16,5 @@ jsonrpsee-ws-client = "0.2" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } +tokio = "1.8" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "bump-deps" } diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs index 71dac5df6d481..1e5faa4868c5c 100644 --- a/relays/client-ethereum/src/client.rs +++ b/relays/client-ethereum/src/client.rs @@ -23,7 +23,7 @@ use crate::{ConnectionParams, Error, Result}; use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use relay_utils::relay_loop::RECONNECT_DELAY; -use std::sync::Arc; +use std::{future::Future, sync::Arc}; /// Number of headers missing from the Ethereum node for us to consider node not synced. const MAJOR_SYNC_BLOCKS: u64 = 5; @@ -31,6 +31,7 @@ const MAJOR_SYNC_BLOCKS: u64 = 5; /// The client used to interact with an Ethereum node through RPC. #[derive(Clone)] pub struct Client { + tokio: Arc, params: ConnectionParams, client: Arc, } @@ -59,22 +60,23 @@ impl Client { /// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been established /// or error otherwise. pub async fn try_connect(params: ConnectionParams) -> Result { - Ok(Self { - client: Self::build_client(¶ms).await?, - params, - }) + let (tokio, client) = Self::build_client(¶ms).await?; + Ok(Self { tokio, client, params }) } /// Build client to use in connection. - async fn build_client(params: &ConnectionParams) -> Result> { + async fn build_client(params: &ConnectionParams) -> Result<(Arc, Arc)> { + let tokio = tokio::runtime::Runtime::new()?; let uri = format!("ws://{}:{}", params.host, params.port); - let client = RpcClientBuilder::default().build(&uri).await?; - Ok(Arc::new(client)) + let client = tokio + .spawn(async move { RpcClientBuilder::default().build(&uri).await }) + .await??; + Ok((Arc::new(tokio), Arc::new(client))) } /// Reopen client connection. pub async fn reconnect(&mut self) -> Result<()> { - self.client = Self::build_client(&self.params).await?; + self.client = Self::build_client(&self.params).await?.1; Ok(()) } } @@ -82,113 +84,153 @@ impl Client { impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { - match Ethereum::syncing(&*self.client).await? { - SyncState::NotSyncing => Ok(()), - SyncState::Syncing(syncing) => { - let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block); - if missing_headers > MAJOR_SYNC_BLOCKS.into() { - return Err(Error::ClientNotSynced(missing_headers)); + self.jsonrpsee_execute(move |client| async move { + match Ethereum::syncing(&*client).await? { + SyncState::NotSyncing => Ok(()), + SyncState::Syncing(syncing) => { + let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block); + if missing_headers > MAJOR_SYNC_BLOCKS.into() { + return Err(Error::ClientNotSynced(missing_headers)); + } + + Ok(()) } - - Ok(()) } - } + }) + .await } /// Estimate gas usage for the given call. pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { - Ok(Ethereum::estimate_gas(&*self.client, call_request).await?) + self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::estimate_gas(&*client, call_request).await?) }) + .await } /// Retrieve number of the best known block from the Ethereum node. pub async fn best_block_number(&self) -> Result { - Ok(Ethereum::block_number(&*self.client).await?.as_u64()) + self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::block_number(&*client).await?.as_u64()) }) + .await } /// Retrieve number of the best known block from the Ethereum node. pub async fn header_by_number(&self, block_number: u64) -> Result

{ - let get_full_tx_objects = false; - let header = Ethereum::get_block_by_number(&*self.client, block_number, get_full_tx_objects).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(Error::IncompleteHeader), - } + self.jsonrpsee_execute(move |client| async move { + let get_full_tx_objects = false; + let header = Ethereum::get_block_by_number(&*client, block_number, get_full_tx_objects).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + } + }) + .await } /// Retrieve block header by its hash from Ethereum node. pub async fn header_by_hash(&self, hash: H256) -> Result
{ - let get_full_tx_objects = false; - let header = Ethereum::get_block_by_hash(&*self.client, hash, get_full_tx_objects).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(Error::IncompleteHeader), - } + self.jsonrpsee_execute(move |client| async move { + let get_full_tx_objects = false; + let header = Ethereum::get_block_by_hash(&*client, hash, get_full_tx_objects).await?; + match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { + true => Ok(header), + false => Err(Error::IncompleteHeader), + } + }) + .await } /// Retrieve block header and its transactions by its number from Ethereum node. pub async fn header_by_number_with_transactions(&self, number: u64) -> Result { - let get_full_tx_objects = true; - let header = - Ethereum::get_block_by_number_with_transactions(&*self.client, number, get_full_tx_objects).await?; + self.jsonrpsee_execute(move |client| async move { + let get_full_tx_objects = true; + let header = Ethereum::get_block_by_number_with_transactions(&*client, number, get_full_tx_objects).await?; - let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); - if !is_complete_header { - return Err(Error::IncompleteHeader); - } + let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + if !is_complete_header { + return Err(Error::IncompleteHeader); + } - let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); - if !is_complete_transactions { - return Err(Error::IncompleteTransaction); - } + let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); + if !is_complete_transactions { + return Err(Error::IncompleteTransaction); + } - Ok(header) + Ok(header) + }) + .await } /// Retrieve block header and its transactions by its hash from Ethereum node. pub async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { - let get_full_tx_objects = true; - let header = Ethereum::get_block_by_hash_with_transactions(&*self.client, hash, get_full_tx_objects).await?; + self.jsonrpsee_execute(move |client| async move { + let get_full_tx_objects = true; + let header = Ethereum::get_block_by_hash_with_transactions(&*client, hash, get_full_tx_objects).await?; - let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); - if !is_complete_header { - return Err(Error::IncompleteHeader); - } + let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + if !is_complete_header { + return Err(Error::IncompleteHeader); + } - let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); - if !is_complete_transactions { - return Err(Error::IncompleteTransaction); - } + let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); + if !is_complete_transactions { + return Err(Error::IncompleteTransaction); + } - Ok(header) + Ok(header) + }) + .await } /// Retrieve transaction by its hash from Ethereum node. pub async fn transaction_by_hash(&self, hash: H256) -> Result> { - Ok(Ethereum::transaction_by_hash(&*self.client, hash).await?) + self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::transaction_by_hash(&*client, hash).await?) }) + .await } /// Retrieve transaction receipt by transaction hash. pub async fn transaction_receipt(&self, transaction_hash: H256) -> Result { - Ok(Ethereum::get_transaction_receipt(&*self.client, transaction_hash).await?) + self.jsonrpsee_execute(move |client| async move { + Ok(Ethereum::get_transaction_receipt(&*client, transaction_hash).await?) + }) + .await } /// Get the nonce of the given account. pub async fn account_nonce(&self, address: Address) -> Result { - Ok(Ethereum::get_transaction_count(&*self.client, address).await?) + self.jsonrpsee_execute( + move |client| async move { Ok(Ethereum::get_transaction_count(&*client, address).await?) }, + ) + .await } /// Submit an Ethereum transaction. /// /// The transaction must already be signed before sending it through this method. pub async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result { - let transaction = Bytes(signed_raw_tx); - let tx_hash = Ethereum::submit_transaction(&*self.client, transaction).await?; - log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); - Ok(tx_hash) + self.jsonrpsee_execute(move |client| async move { + let transaction = Bytes(signed_raw_tx); + let tx_hash = Ethereum::submit_transaction(&*client, transaction).await?; + log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); + Ok(tx_hash) + }) + .await } /// Call Ethereum smart contract. pub async fn eth_call(&self, call_transaction: CallRequest) -> Result { - Ok(Ethereum::call(&*self.client, call_transaction).await?) + self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::call(&*client, call_transaction).await?) }) + .await + } + + /// Execute jsonrpsee future in tokio context. + async fn jsonrpsee_execute(&self, make_jsonrpsee_future: MF) -> Result + where + MF: FnOnce(Arc) -> F + Send + 'static, + F: Future> + Send, + T: Send + 'static, + { + let client = self.client.clone(); + self.tokio + .spawn(async move { make_jsonrpsee_future(client).await }) + .await? } } diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index e01cdf1bf5594..3650fd2fd9aad 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -28,6 +28,8 @@ pub type Result = std::result::Result; /// an Ethereum node through RPC. #[derive(Debug)] pub enum Error { + /// IO error. + Io(std::io::Error), /// An error that can occur when making an HTTP request to /// an JSON-RPC client. RpcError(RpcError), @@ -45,6 +47,8 @@ pub enum Error { /// The client we're connected to is not synced, so we can't rely on its state. Contains /// number of unsynced headers. ClientNotSynced(U256), + /// Custom logic error. + Custom(String), } impl From for Error { @@ -53,6 +57,18 @@ impl From for Error { } } +impl From for Error { + fn from(error: std::io::Error) -> Self { + Error::Io(error) + } +} + +impl From for Error { + fn from(error: tokio::task::JoinError) -> Self { + Error::Custom(format!("Failed to wait tokio task: {}", error)) + } +} + impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( @@ -68,6 +84,7 @@ impl MaybeConnectionError for Error { impl ToString for Error { fn to_string(&self) -> String { match self { + Self::Io(e) => e.to_string(), Self::RpcError(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(), Self::IncompleteHeader => { @@ -80,6 +97,7 @@ impl ToString for Error { Self::ClientNotSynced(missing_headers) => { format!("Ethereum client is not synced: syncing {} headers", missing_headers) } + Self::Custom(ref e) => e.clone(), } } } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 7c3e381259cfe..9b8a6f21e3fe4 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,6 +14,7 @@ jsonrpsee-ws-client = "0.2" log = "0.4.11" num-traits = "0.2" rand = "0.7" +tokio = "1.8" # Bridge dependencies diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 87917c022c730..6a486a622e7d3 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -32,13 +32,13 @@ use relay_utils::relay_loop::RECONNECT_DELAY; use sp_core::{storage::StorageKey, Bytes}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; -use std::convert::TryFrom; +use std::{convert::TryFrom, future::Future}; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// Opaque justifications subscription type. -pub type JustificationsSubscription = Subscription; +pub struct JustificationsSubscription(tokio::runtime::Handle, Arc>>); /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; @@ -47,6 +47,8 @@ pub type OpaqueGrandpaAuthoritiesSet = Vec; /// /// Cloning `Client` is a cheap operation. pub struct Client { + /// Tokio runtime handle. + tokio: Arc, /// Client connection params. params: ConnectionParams, /// Substrate RPC client. @@ -62,6 +64,7 @@ pub struct Client { impl Clone for Client { fn clone(&self) -> Self { Client { + tokio: self.tokio.clone(), params: self.params.clone(), client: self.client.clone(), genesis_hash: self.genesis_hash, @@ -103,12 +106,16 @@ impl Client { /// Try to connect to Substrate node over websocket. Returns Substrate RPC client if connection /// has been established or error otherwise. pub async fn try_connect(params: ConnectionParams) -> Result { - let client = Self::build_client(params.clone()).await?; + let (tokio, client) = Self::build_client(params.clone()).await?; let number: C::BlockNumber = Zero::zero(); - let genesis_hash = Substrate::::chain_get_block_hash(&*client, number).await?; + let genesis_hash_client = client.clone(); + let genesis_hash = tokio + .spawn(async move { Substrate::::chain_get_block_hash(&*genesis_hash_client, number).await }) + .await??; Ok(Self { + tokio, params, client, genesis_hash, @@ -118,37 +125,45 @@ impl Client { /// Reopen client connection. pub async fn reconnect(&mut self) -> Result<()> { - self.client = Self::build_client(self.params.clone()).await?; + self.client = Self::build_client(self.params.clone()).await?.1; Ok(()) } /// Build client to use in connection. - async fn build_client(params: ConnectionParams) -> Result> { + async fn build_client(params: ConnectionParams) -> Result<(Arc, Arc)> { + let tokio = tokio::runtime::Runtime::new()?; let uri = format!( "{}://{}:{}", if params.secure { "wss" } else { "ws" }, params.host, params.port, ); - let client = RpcClientBuilder::default() - .max_notifs_per_subscription(MAX_SUBSCRIPTION_CAPACITY) - .build(&uri) - .await?; + let client = tokio + .spawn(async move { + RpcClientBuilder::default() + .max_notifs_per_subscription(MAX_SUBSCRIPTION_CAPACITY) + .build(&uri) + .await + }) + .await??; - Ok(Arc::new(client)) + Ok((Arc::new(tokio), Arc::new(client))) } } impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { - let health = Substrate::::system_health(&*self.client).await?; - let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); - if is_synced { - Ok(()) - } else { - Err(Error::ClientNotSynced(health)) - } + self.jsonrpsee_execute(|client| async move { + let health = Substrate::::system_health(&*client).await?; + let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); + if is_synced { + Ok(()) + } else { + Err(Error::ClientNotSynced(health)) + } + }) + .await } /// Return hash of the genesis block. @@ -158,7 +173,8 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { - Ok(Substrate::::chain_get_finalized_head(&*self.client).await?) + self.jsonrpsee_execute(|client| async move { Ok(Substrate::::chain_get_finalized_head(&*client).await?) }) + .await } /// Returns the best Substrate header. @@ -166,12 +182,16 @@ impl Client { where C::Header: DeserializeOwned, { - Ok(Substrate::::chain_get_header(&*self.client, None).await?) + self.jsonrpsee_execute(|client| async move { Ok(Substrate::::chain_get_header(&*client, None).await?) }) + .await } /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { - Ok(Substrate::::chain_get_block(&*self.client, block_hash).await?) + self.jsonrpsee_execute( + move |client| async move { Ok(Substrate::::chain_get_block(&*client, block_hash).await?) }, + ) + .await } /// Get a Substrate header by its hash. @@ -179,12 +199,18 @@ impl Client { where C::Header: DeserializeOwned, { - Ok(Substrate::::chain_get_header(&*self.client, block_hash).await?) + self.jsonrpsee_execute(move |client| async move { + Ok(Substrate::::chain_get_header(&*client, block_hash).await?) + }) + .await } /// Get a Substrate block hash by its number. pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { - Ok(Substrate::::chain_get_block_hash(&*self.client, number).await?) + self.jsonrpsee_execute(move |client| async move { + Ok(Substrate::::chain_get_block_hash(&*client, number).await?) + }) + .await } /// Get a Substrate header by its number. @@ -193,20 +219,25 @@ impl Client { C::Header: DeserializeOwned, { let block_hash = Self::block_hash_by_number(self, block_number).await?; - Ok(Self::header_by_hash(self, block_hash).await?) + let header_by_hash = Self::header_by_hash(self, block_hash).await?; + Ok(header_by_hash) } /// Return runtime version. pub async fn runtime_version(&self) -> Result { - Ok(Substrate::::state_runtime_version(&*self.client).await?) + self.jsonrpsee_execute(move |client| async move { Ok(Substrate::::state_runtime_version(&*client).await?) }) + .await } /// Read value from runtime storage. - pub async fn storage_value(&self, storage_key: StorageKey) -> Result> { - Substrate::::state_get_storage(&*self.client, storage_key) - .await? - .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) - .transpose() + pub async fn storage_value(&self, storage_key: StorageKey) -> Result> { + self.jsonrpsee_execute(move |client| async move { + Substrate::::state_get_storage(&*client, storage_key) + .await? + .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) + .transpose() + }) + .await } /// Return native tokens balance of the account. @@ -214,30 +245,39 @@ impl Client { where C: ChainWithBalances, { - let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = Substrate::::state_get_storage(&*self.client, storage_key) - .await? - .ok_or(Error::AccountDoesNotExist)?; - let decoded_account_data = - AccountInfo::>::decode(&mut &encoded_account_data.0[..]) - .map_err(Error::ResponseParseFailed)?; - Ok(decoded_account_data.data.free) + self.jsonrpsee_execute(move |client| async move { + let storage_key = C::account_info_storage_key(&account); + let encoded_account_data = Substrate::::state_get_storage(&*client, storage_key) + .await? + .ok_or(Error::AccountDoesNotExist)?; + let decoded_account_data = + AccountInfo::>::decode(&mut &encoded_account_data.0[..]) + .map_err(Error::ResponseParseFailed)?; + Ok(decoded_account_data.data.free) + }) + .await } /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { - Ok(Substrate::::system_account_next_index(&*self.client, account).await?) + self.jsonrpsee_execute(move |client| async move { + Ok(Substrate::::system_account_next_index(&*client, account).await?) + }) + .await } /// Submit unsigned extrinsic for inclusion in a block. /// /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { - let tx_hash = Substrate::::author_submit_extrinsic(&*self.client, transaction).await?; - log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); - Ok(tx_hash) + self.jsonrpsee_execute(move |client| async move { + let tx_hash = Substrate::::author_submit_extrinsic(&*client, transaction).await?; + log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); + Ok(tx_hash) + }) + .await } /// Submit an extrinsic signed by given account. @@ -250,71 +290,117 @@ impl Client { pub async fn submit_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(C::Index) -> Bytes, + prepare_extrinsic: impl FnOnce(C::Index) -> Bytes + Send + 'static, ) -> Result { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; - let extrinsic = prepare_extrinsic(transaction_nonce); - let tx_hash = Substrate::::author_submit_extrinsic(&*self.client, extrinsic).await?; - log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); - Ok(tx_hash) + self.jsonrpsee_execute(move |client| async move { + let extrinsic = prepare_extrinsic(transaction_nonce); + let tx_hash = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; + log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); + Ok(tx_hash) + }) + .await } /// Estimate fee that will be spent on given extrinsic. pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result { - let fee_details = Substrate::::payment_query_fee_details(&*self.client, transaction, None).await?; - let inclusion_fee = fee_details - .inclusion_fee - .map(|inclusion_fee| { - InclusionFee { - base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - } - .inclusion_fee() - }) - .unwrap_or_else(Zero::zero); - Ok(inclusion_fee) + self.jsonrpsee_execute(move |client| async move { + let fee_details = Substrate::::payment_query_fee_details(&*client, transaction, None).await?; + let inclusion_fee = fee_details + .inclusion_fee + .map(|inclusion_fee| { + InclusionFee { + base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + } + .inclusion_fee() + }) + .unwrap_or_else(Zero::zero); + Ok(inclusion_fee) + }) + .await } /// Get the GRANDPA authority set at given block. pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result { - let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); - let data = Bytes(Vec::new()); + self.jsonrpsee_execute(move |client| async move { + let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); + let data = Bytes(Vec::new()); - let encoded_response = Substrate::::state_call(&*self.client, call, data, Some(block)).await?; - let authority_list = encoded_response.0; + let encoded_response = Substrate::::state_call(&*client, call, data, Some(block)).await?; + let authority_list = encoded_response.0; - Ok(authority_list) + Ok(authority_list) + }) + .await } /// Execute runtime call at given block. pub async fn state_call(&self, method: String, data: Bytes, at_block: Option) -> Result { - Substrate::::state_call(&*self.client, method, data, at_block) - .await - .map_err(Into::into) + self.jsonrpsee_execute(move |client| async move { + Substrate::::state_call(&*client, method, data, at_block) + .await + .map_err(Into::into) + }) + .await } /// Returns storage proof of given storage keys. pub async fn prove_storage(&self, keys: Vec, at_block: C::Hash) -> Result { - Substrate::::state_prove_storage(&*self.client, keys, Some(at_block)) - .await - .map(|proof| StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect())) - .map_err(Into::into) + self.jsonrpsee_execute(move |client| async move { + Substrate::::state_prove_storage(&*client, keys, Some(at_block)) + .await + .map(|proof| StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect())) + .map_err(Into::into) + }) + .await } /// Return new justifications stream. pub async fn subscribe_justifications(&self) -> Result { - Ok(self - .client - .subscribe( - "grandpa_subscribeJustifications", - JsonRpcParams::NoParams, - "grandpa_unsubscribeJustifications", - ) - .await?) + let subscription = self + .jsonrpsee_execute(move |client| async move { + Ok(client + .subscribe( + "grandpa_subscribeJustifications", + JsonRpcParams::NoParams, + "grandpa_unsubscribeJustifications", + ) + .await?) + }) + .await?; + Ok(JustificationsSubscription( + self.tokio.handle().clone(), + Arc::new(Mutex::new(subscription)), + )) + } + + /// Execute jsonrpsee future in tokio context. + async fn jsonrpsee_execute(&self, make_jsonrpsee_future: MF) -> Result + where + MF: FnOnce(Arc) -> F + Send + 'static, + F: Future> + Send, + T: Send + 'static, + { + let client = self.client.clone(); + self.tokio + .spawn(async move { make_jsonrpsee_future(client).await }) + .await? + } +} + +impl JustificationsSubscription { + /// Return next justification from the subscription. + pub async fn next(&self) -> Result> { + let subscription = self.1.clone(); + self.0 + .spawn(async move { subscription.lock().await.next().await }) + .await? + .map_err(Error::RpcError) } } diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index f553d6867e957..f06079ef5facf 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -27,6 +27,8 @@ pub type Result = std::result::Result; /// a Substrate node through RPC. #[derive(Debug)] pub enum Error { + /// IO error. + Io(std::io::Error), /// An error that can occur when making a request to /// an JSON-RPC server. RpcError(RpcError), @@ -49,6 +51,7 @@ pub enum Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { + Self::Io(ref e) => Some(e), Self::RpcError(ref e) => Some(e), Self::ResponseParseFailed(ref e) => Some(e), Self::UninitializedBridgePallet => None, @@ -67,6 +70,18 @@ impl From for Error { } } +impl From for Error { + fn from(error: std::io::Error) -> Self { + Error::Io(error) + } +} + +impl From for Error { + fn from(error: tokio::task::JoinError) -> Self { + Error::Custom(format!("Failed to wait tokio task: {}", error)) + } +} + impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( @@ -82,6 +97,7 @@ impl MaybeConnectionError for Error { impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let s = match self { + Self::Io(e) => e.to_string(), Self::RpcError(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(), Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 546a3ede3e5a6..81a98d2f1e9c6 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -132,7 +132,7 @@ where async fn finality_proofs(&self) -> Result { Ok(unfold( self.client.clone().subscribe_justifications().await?, - move |mut subscription| async move { + move |subscription| async move { loop { let log_error = |err| { log::error!( From ecf20981700bd542f577d494be75d8c0cf1a9b84 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 21 Jul 2021 13:59:16 +0300 Subject: [PATCH 0517/1210] When restarting client, also "restart" tokio runtime (#1065) * remember new tokio runtime on reconnect * compilation --- relays/client-ethereum/src/client.rs | 4 +++- relays/client-substrate/src/client.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs index 1e5faa4868c5c..c82dddcf36ee8 100644 --- a/relays/client-ethereum/src/client.rs +++ b/relays/client-ethereum/src/client.rs @@ -76,7 +76,9 @@ impl Client { /// Reopen client connection. pub async fn reconnect(&mut self) -> Result<()> { - self.client = Self::build_client(&self.params).await?.1; + let (tokio, client) = Self::build_client(&self.params).await?; + self.tokio = tokio; + self.client = client; Ok(()) } } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 6a486a622e7d3..554810844a07b 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -125,7 +125,9 @@ impl Client { /// Reopen client connection. pub async fn reconnect(&mut self) -> Result<()> { - self.client = Self::build_client(self.params.clone()).await?.1; + let (tokio, client) = Self::build_client(self.params.clone()).await?; + self.tokio = tokio; + self.client = client; Ok(()) } From fd40a6b4feefe93c23a23ad5e09a8a73bead42e3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 21 Jul 2021 15:13:11 +0300 Subject: [PATCH 0518/1210] Fix Westend -> Millau sync (#1064) * read justifications from stream using channel + task that fills that channel * Arc -> Mutex --- relays/client-substrate/src/client.rs | 51 ++++++++++++++++++++------- relays/finality/src/finality_loop.rs | 45 +++++++++++++++++++++-- 2 files changed, 82 insertions(+), 14 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 554810844a07b..7449dda100f61 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -23,8 +23,9 @@ use crate::{ConnectionParams, Error, Result}; use async_std::sync::{Arc, Mutex}; use codec::Decode; use frame_system::AccountInfo; +use futures::{SinkExt, StreamExt}; use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned}; -use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; +use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; @@ -38,7 +39,7 @@ const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// Opaque justifications subscription type. -pub struct JustificationsSubscription(tokio::runtime::Handle, Arc>>); +pub struct JustificationsSubscription(Mutex>>); /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; @@ -365,7 +366,7 @@ impl Client { /// Return new justifications stream. pub async fn subscribe_justifications(&self) -> Result { - let subscription = self + let mut subscription = self .jsonrpsee_execute(move |client| async move { Ok(client .subscribe( @@ -376,10 +377,38 @@ impl Client { .await?) }) .await?; - Ok(JustificationsSubscription( - self.tokio.handle().clone(), - Arc::new(Mutex::new(subscription)), - )) + let (mut sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); + self.tokio.spawn(async move { + loop { + match subscription.next().await { + Ok(Some(justification)) => { + if sender.send(Some(justification)).await.is_err() { + break; + } + } + Ok(None) => { + log::trace!( + target: "bridge", + "{} justifications subscription stream has returned None. Stream needs to be restarted.", + C::NAME, + ); + let _ = sender.send(None).await; + break; + } + Err(e) => { + log::trace!( + target: "bridge", + "{} justifications subscription stream has returned '{:?}'. Stream needs to be restarted.", + C::NAME, + e, + ); + let _ = sender.send(None).await; + break; + } + } + } + }); + Ok(JustificationsSubscription(Mutex::new(receiver))) } /// Execute jsonrpsee future in tokio context. @@ -399,10 +428,8 @@ impl Client { impl JustificationsSubscription { /// Return next justification from the subscription. pub async fn next(&self) -> Result> { - let subscription = self.1.clone(); - self.0 - .spawn(async move { subscription.lock().await.next().await }) - .await? - .map_err(Error::RpcError) + let mut receiver = self.0.lock().await; + let justification = receiver.next().await; + Ok(justification.unwrap_or(None)) } } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 462632fa3fed0..4805e1536c4b4 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -497,6 +497,9 @@ pub(crate) fn read_finality_proofs_from_stream, recent_finality_proofs: &mut FinalityProofs

, ) { + let mut proofs_count = 0; + let mut first_header_number = None; + let mut last_header_number = None; loop { let next_proof = finality_proofs_stream.stream.next(); let finality_proof = match next_proof.now_or_never() { @@ -508,7 +511,25 @@ pub(crate) fn read_finality_proofs_from_stream break, }; - recent_finality_proofs.push((finality_proof.target_header_number(), finality_proof)); + let target_header_number = finality_proof.target_header_number(); + if first_header_number.is_none() { + first_header_number = Some(target_header_number); + } + last_header_number = Some(target_header_number); + proofs_count += 1; + + recent_finality_proofs.push((target_header_number, finality_proof)); + } + + if proofs_count != 0 { + log::trace!( + target: "bridge", + "Read {} finality proofs from {} finality stream for headers in range [{:?}; {:?}]", + proofs_count, + P::SOURCE_NAME, + first_header_number, + last_header_number, + ); } } @@ -520,6 +541,12 @@ pub(crate) fn select_better_recent_finality_proof( selected_finality_proof: Option<(P::Header, P::FinalityProof)>, ) -> Option<(P::Header, P::FinalityProof)> { if unjustified_headers.is_empty() || recent_finality_proofs.is_empty() { + log::trace!( + target: "bridge", + "Can not improve selected {} finality proof {:?}. No unjustified headers and recent proofs", + P::SOURCE_NAME, + selected_finality_proof.as_ref().map(|(h, _)| h.number()), + ); return selected_finality_proof; } @@ -543,7 +570,21 @@ pub(crate) fn select_better_recent_finality_proof( .binary_search_by_key(intersection.end(), |(number, _)| *number) .unwrap_or_else(|index| index.saturating_sub(1)); let (selected_header_number, finality_proof) = &recent_finality_proofs[selected_finality_proof_index]; - if !intersection.contains(selected_header_number) { + let has_selected_finality_proof = intersection.contains(selected_header_number); + log::trace!( + target: "bridge", + "Trying to improve selected {} finality proof {:?}. Headers range: [{:?}; {:?}]. Proofs range: [{:?}; {:?}].\ + Trying to improve to: {:?}. Result: {}", + P::SOURCE_NAME, + selected_finality_proof.as_ref().map(|(h, _)| h.number()), + unjustified_range_begin, + unjustified_range_end, + buffered_range_begin, + buffered_range_end, + selected_header_number, + if has_selected_finality_proof { "improved" } else { "failed" }, + ); + if !has_selected_finality_proof { return selected_finality_proof; } From 51b684a6c9c221f96580d5b1b53a6471a15a4160 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Jul 2021 10:52:52 +0300 Subject: [PATCH 0519/1210] refund weight for mot pruning messages (#1062) --- modules/messages/src/lib.rs | 74 ++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a8071e9922209..12d8ab342bf51 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -316,10 +316,13 @@ decl_module! { lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure_normal_operating_mode::()?; let submitter = origin.into().map_err(|_| BadOrigin)?; + // initially, actual (post-dispatch) weight is equal to pre-dispatch weight + let mut actual_weight = T::WeightInfo::send_message_weight(&payload); + // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload) .map_err(|err| { @@ -377,7 +380,15 @@ decl_module! { payload: encoded_payload, fee: delivery_and_dispatch_fee, }); - lane.prune_messages(T::MaxMessagesToPruneAtOnce::get()); + + // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages + // the cost of pruning every message is roughly single db write + // => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned + let max_messages_to_prune = T::MaxMessagesToPruneAtOnce::get(); + let pruned_messages = lane.prune_messages(max_messages_to_prune); + if let Some(extra_messages) = max_messages_to_prune.checked_sub(pruned_messages) { + actual_weight = actual_weight.saturating_sub(T::DbWeight::get().writes(extra_messages)); + } log::trace!( target: "runtime::bridge-messages", @@ -389,7 +400,10 @@ decl_module! { Self::deposit_event(RawEvent::MessageAccepted(lane_id, nonce)); - Ok(()) + Ok(PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }) } /// Pay additional fee for the message. @@ -1048,19 +1062,22 @@ mod tests { System::::reset_events(); } - fn send_regular_message() { + fn send_regular_message() -> Weight { get_ready_for_events(); let message_nonce = outbound_lane::(TEST_LANE_ID) .data() .latest_generated_nonce + 1; - assert_ok!(Pallet::::send_message( + let weight = Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, REGULAR_PAYLOAD.declared_weight, - )); + ) + .expect("send_message has failed") + .actual_weight + .expect("send_message always returns Some"); // check event with assigned nonce assert_eq!( @@ -1077,6 +1094,8 @@ mod tests { 1, REGULAR_PAYLOAD.declared_weight )); + + weight } fn receive_messages_delivery_proof() { @@ -2098,4 +2117,47 @@ mod tests { ); }); } + + #[test] + fn weight_is_refunded_for_messages_that_are_not_pruned() { + run_test(|| { + // send first MAX messages - no messages are pruned + let max_messages_to_prune = crate::mock::MaxMessagesToPruneAtOnce::get(); + let when_zero_messages_are_pruned = send_regular_message(); + let mut delivered_messages = DeliveredMessages::new(1, true); + for _ in 1..max_messages_to_prune { + assert_eq!(send_regular_message(), when_zero_messages_are_pruned); + delivered_messages.note_dispatched_message(true); + } + + // confirm delivery of all sent messages + assert_ok!(Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 1, + relayers: vec![UnrewardedRelayer { + relayer: 0, + messages: delivered_messages, + }] + .into_iter() + .collect(), + }, + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: max_messages_to_prune, + ..Default::default() + }, + )); + + // when next message is sent, MAX messages are pruned + let weight_when_max_messages_are_pruned = send_regular_message(); + assert_eq!( + weight_when_max_messages_are_pruned, + when_zero_messages_are_pruned + crate::mock::DbWeight::get().writes(max_messages_to_prune), + ); + }); + } } From a4bdc7a529961570f8d5aad6b23a3f69d94f3738 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 26 Jul 2021 17:32:08 +0300 Subject: [PATCH 0520/1210] extract message_details impl into runtime common (#1070) --- bin/millau/runtime/src/lib.rs | 20 +++------- bin/rialto/runtime/src/lib.rs | 20 +++------- bin/runtime-common/src/lib.rs | 1 + bin/runtime-common/src/messages_api.rs | 52 ++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 30 deletions(-) create mode 100644 bin/runtime-common/src/messages_api.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 46921edd584e3..ff5b39439b60b 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -35,7 +35,6 @@ pub mod rialto_messages; use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; -use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; @@ -620,20 +619,11 @@ impl_runtime_apis! { begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, ) -> Vec> { - (begin..=end).filter_map(|nonce| { - let message_data = BridgeRialtoMessages::outbound_message_data(lane, nonce)?; - let decoded_payload = rialto_messages::ToRialtoMessagePayload::decode( - &mut &message_data.payload[..] - ).ok()?; - Some(bp_messages::MessageDetails { - nonce, - dispatch_weight: decoded_payload.weight, - size: message_data.payload.len() as _, - delivery_and_dispatch_fee: message_data.fee, - dispatch_fee_payment: decoded_payload.dispatch_fee_payment, - }) - }) - .collect() + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithRialtoMessagesInstance, + WithRialtoMessageBridge, + >(lane, begin, end) } fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index fe503154c8d51..762ef1710220f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -41,7 +41,6 @@ pub mod rialto_poa; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; -use codec::Decode; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; @@ -839,20 +838,11 @@ impl_runtime_apis! { begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, ) -> Vec> { - (begin..=end).filter_map(|nonce| { - let message_data = BridgeMillauMessages::outbound_message_data(lane, nonce)?; - let decoded_payload = millau_messages::ToMillauMessagePayload::decode( - &mut &message_data.payload[..] - ).ok()?; - Some(bp_messages::MessageDetails { - nonce, - dispatch_weight: decoded_payload.weight, - size: message_data.payload.len() as _, - delivery_and_dispatch_fee: message_data.fee, - dispatch_fee_payment: decoded_payload.dispatch_fee_payment, - }) - }) - .collect() + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithMillauMessagesInstance, + WithMillauMessageBridge, + >(lane, begin, end) } fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index ae7efb4a41968..66f2c6c3a01f1 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -19,4 +19,5 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod messages; +pub mod messages_api; pub mod messages_benchmarking; diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs new file mode 100644 index 0000000000000..d0f4180b5c143 --- /dev/null +++ b/bin/runtime-common/src/messages_api.rs @@ -0,0 +1,52 @@ +// 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 . + +//! Helpers for implementing various message-related runtime API mthods. + +use crate::messages::{source::FromThisChainMessagePayload, MessageBridge}; + +use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use codec::Decode; +use frame_support::traits::Instance; +use sp_std::vec::Vec; + +/// Implementation of the `To*OutboundLaneApi::message_details`. +pub fn outbound_message_details( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, +) -> Vec> +where + Runtime: pallet_bridge_messages::Config, + MessagesPalletInstance: Instance, + BridgeConfig: MessageBridge, +{ + (begin..=end) + .filter_map(|nonce| { + let message_data = + pallet_bridge_messages::Pallet::::outbound_message_data(lane, nonce)?; + let decoded_payload = + FromThisChainMessagePayload::::decode(&mut &message_data.payload[..]).ok()?; + Some(MessageDetails { + nonce, + dispatch_weight: decoded_payload.weight, + size: message_data.payload.len() as _, + delivery_and_dispatch_fee: message_data.fee, + dispatch_fee_payment: decoded_payload.dispatch_fee_payment, + }) + }) + .collect() +} From 4d246cdfa8e12f3497152a8cef007afc4e3851eb Mon Sep 17 00:00:00 2001 From: Guillaume Thiolliere Date: Wed, 28 Jul 2021 12:11:04 +0200 Subject: [PATCH 0521/1210] companion for https://github.com/paritytech/polkadot/pull/3507 (#1067) * better test * fmt Co-authored-by: Svyatoslav Nikolsky --- modules/dispatch/src/lib.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index e9bf75686bbdd..46f05b487c376 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -599,9 +599,14 @@ mod tests { fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let call = Call::System(>::remark(vec![1, 2, 3])); + let call_weight = call.get_dispatch_info().weight; + let mut message = prepare_root_message(call); message.weight = 7; + assert!( + call_weight != 7, + "needed for test to actually trigger a weight mismatch" + ); System::set_block_number(1); let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); @@ -615,7 +620,7 @@ mod tests { event: Event::Dispatch(call_dispatch::Event::::MessageWeightMismatch( SOURCE_CHAIN_ID, id, - 1038000, + call_weight, 7, )), topics: vec![], From 2fe30b0ff27d90e68f74860e4e52084a26487451 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Jul 2021 15:44:19 +0300 Subject: [PATCH 0522/1210] increase_message_fee depends on stored mesage size (#1066) --- modules/messages/src/benchmarking.rs | 25 +++++++++++- modules/messages/src/lib.rs | 60 +++++++++++++++++++++++++--- modules/messages/src/mock.rs | 5 ++- modules/messages/src/weights.rs | 23 ++++++++--- 4 files changed, 100 insertions(+), 13 deletions(-) diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index cab2704f4009f..e2a3237eb064c 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -38,7 +38,7 @@ use sp_std::{ }; /// Fee paid by submitter for single message delivery. -pub const MESSAGE_FEE: u64 = 10_000_000_000; +pub const MESSAGE_FEE: u64 = 100_000_000_000; const SEED: u32 = 0; @@ -237,7 +237,9 @@ benchmarks_instance! { // Benchmark `increase_message_fee` with following conditions: // * message has maximal message; // * submitter account is killed because its balance is less than ED after payment. - increase_message_fee { + // + // Result of this benchmark is directly used by weight formula of the call. + maximal_increase_message_fee { let sender = account("sender", 42, SEED); T::endow_account(&sender); @@ -251,6 +253,25 @@ benchmarks_instance! { assert_eq!(T::account_balance(&sender), 0.into()); } + // Benchmark `increase_message_fee` with following conditions: + // * message size varies from minimal to maximal; + // * submitter account is killed because its balance is less than ED after payment. + increase_message_fee { + let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); + + let sender = account("sender", 42, SEED); + T::endow_account(&sender); + + let additional_fee = T::account_balance(&sender); + let lane_id = T::bench_lane_id(); + let nonce = 1; + + send_regular_message_with_payload::(vec![42u8; i as _]); + }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) + verify { + assert_eq!(T::account_balance(&sender), 0.into()); + } + // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 12d8ab342bf51..3019129e030bd 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -66,7 +66,7 @@ use frame_support::{ }; use frame_system::{ensure_signed, RawOrigin}; use num_traits::{SaturatingAdd, Zero}; -use sp_runtime::{traits::BadOrigin, DispatchResult}; +use sp_runtime::traits::BadOrigin; use sp_std::{cell::RefCell, cmp::PartialOrd, marker::PhantomData, prelude::*}; mod inbound_lane; @@ -407,13 +407,13 @@ decl_module! { } /// Pay additional fee for the message. - #[weight = T::WeightInfo::increase_message_fee()] + #[weight = T::WeightInfo::maximal_increase_message_fee()] pub fn increase_message_fee( origin, lane_id: LaneId, nonce: MessageNonce, additional_fee: T::OutboundMessageFee, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { ensure_not_halted::()?; // if someone tries to pay for already-delivered message, we're rejecting this intention // (otherwise this additional fee will be locked forever in relayers fund) @@ -446,7 +446,7 @@ decl_module! { // and finally update fee in the storage let message_key = MessageKey { lane_id, nonce }; - OutboundMessages::::mutate(message_key, |message_data| { + let message_size = OutboundMessages::::mutate(message_key, |message_data| { // saturating_add is fine here - overflow here means that someone controls all // chain funds, which shouldn't ever happen + `pay_delivery_and_dispatch_fee` // above will fail before we reach here @@ -454,9 +454,19 @@ decl_module! { .as_mut() .expect("the message is sent and not yet delivered; so it is in the storage; qed"); message_data.fee = message_data.fee.saturating_add(&additional_fee); + message_data.payload.len() }); - Ok(()) + // compute actual dispatch weight that depends on the stored message size + let actual_weight = sp_std::cmp::min( + T::WeightInfo::maximal_increase_message_fee(), + T::WeightInfo::increase_message_fee(message_size as _), + ); + + Ok(PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }) } /// Receive messages proof from bridged chain. @@ -2118,6 +2128,46 @@ mod tests { }); } + #[test] + fn increase_message_fee_weight_depends_on_message_size() { + run_test(|| { + let mut small_payload = message_payload(0, 100); + let mut large_payload = message_payload(1, 100); + small_payload.extra = vec![1; 100]; + large_payload.extra = vec![2; 16_384]; + + assert_ok!(Pallet::::send_message( + Origin::signed(1), + TEST_LANE_ID, + small_payload, + 100, + )); + assert_ok!(Pallet::::send_message( + Origin::signed(1), + TEST_LANE_ID, + large_payload, + 100, + )); + + let small_weight = Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1) + .expect("increase_message_fee has failed") + .actual_weight + .expect("increase_message_fee always returns Some"); + + let large_weight = Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 2, 1) + .expect("increase_message_fee has failed") + .actual_weight + .expect("increase_message_fee always returns Some"); + + assert!( + large_weight > small_weight, + "Actual post-dispatch weigth for larger message {} must be larger than {} for small message", + large_weight, + small_weight, + ); + }); + } + #[test] fn weight_is_refunded_for_messages_that_are_not_pruned() { run_test(|| { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 9d361b53cf84b..063bbfaa5aea7 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -56,6 +56,8 @@ pub struct TestPayload { /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, but for test /// purposes we'll be making it larger than `declared_weight` sometimes. pub dispatch_result: MessageDispatchResult, + /// Extra bytes that affect payload size. + pub extra: Vec, } pub type TestMessageFee = u64; pub type TestRelayer = u64; @@ -183,7 +185,7 @@ impl Config for TestRuntime { impl Size for TestPayload { fn size_hint(&self) -> u32 { - 16 + 16 + self.extra.len() as u32 } } @@ -466,6 +468,7 @@ pub const fn message_payload(id: u64, declared_weight: Weight) -> TestPayload { id, declared_weight, dispatch_result: dispatch_result(0), + extra: Vec::new(), } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 9b65c8217ad64..b3028c8fcc4f2 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -51,7 +51,8 @@ pub trait WeightInfo { fn send_minimal_message_worst_case() -> Weight; fn send_1_kb_message_worst_case() -> Weight; fn send_16_kb_message_worst_case() -> Weight; - fn increase_message_fee() -> Weight; + fn maximal_increase_message_fee() -> Weight; + fn increase_message_fee(i: u32) -> Weight; fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; fn receive_single_message_proof_with_outbound_lane_state() -> Weight; @@ -88,8 +89,14 @@ impl WeightInfo for RialtoWeight { .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } - fn increase_message_fee() -> Weight { - (6_709_925_000 as Weight) + fn maximal_increase_message_fee() -> Weight { + (6_781_470_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn increase_message_fee(i: u32) -> Weight { + (114_963_000 as Weight) + .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -202,8 +209,14 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } - fn increase_message_fee() -> Weight { - (6_709_925_000 as Weight) + fn maximal_increase_message_fee() -> Weight { + (6_781_470_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn increase_message_fee(i: u32) -> Weight { + (114_963_000 as Weight) + .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } From 21f138a73870e84b41ecdd4c5066ab8e3a0c1154 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 28 Jul 2021 17:47:29 +0300 Subject: [PATCH 0523/1210] merge two weight-related loops in messages pallet (#1071) --- modules/messages/src/lib.rs | 87 +++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 3019129e030bd..ed57baaf6e4fa 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -186,8 +186,6 @@ decl_error! { TooManyMessagesInTheProof, /// Invalid messages has been submitted. InvalidMessagesProof, - /// Invalid messages dispatch weight has been declared by the relayer. - InvalidMessagesDispatchWeight, /// Invalid messages delivery proof has been submitted. InvalidMessagesDeliveryProof, /// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane). @@ -524,30 +522,10 @@ decl_module! { Error::::InvalidMessagesProof })?; - // verify that relayer is paying actual dispatch weight - let actual_dispatch_weight: Weight = messages - .values() - .map(|lane_messages| lane_messages - .messages - .iter() - .map(T::MessageDispatch::dispatch_weight) - .fold(0, |sum, weight| sum.saturating_add(&weight)) - ) - .fold(0, |sum, weight| sum.saturating_add(weight)); - if dispatch_weight < actual_dispatch_weight { - log::trace!( - target: "runtime::bridge-messages", - "Rejecting messages proof because of dispatch weight mismatch: declared={}, expected={}", - dispatch_weight, - actual_dispatch_weight, - ); - - return Err(Error::::InvalidMessagesDispatchWeight.into()); - } - // dispatch messages and (optionally) update lane(s) state(s) let mut total_messages = 0; let mut valid_messages = 0; + let mut dispatch_weight_left = dispatch_weight; for (lane_id, lane_data) in messages { let mut lane = inbound_lane::(lane_id); @@ -566,8 +544,22 @@ decl_module! { for message in lane_data.messages { debug_assert_eq!(message.key.lane_id, lane_id); - total_messages += 1; + // ensure that relayer has declared enough weight for dispatching next message on + // this lane. We can't dispatch lane messages out-of-order, so if declared weight + // is not enough, let's move to next lane let dispatch_weight = T::MessageDispatch::dispatch_weight(&message); + if dispatch_weight > dispatch_weight_left { + log::trace!( + target: "runtime::bridge-messages", + "Cannot dispatch any more messages on lane {:?}. Weight: declared={}, left={}", + lane_id, + dispatch_weight, + dispatch_weight_left, + ); + break; + } + total_messages += 1; + let receival_result = lane.receive_message::( &relayer_id_at_bridged_chain, &relayer_id_at_this_chain, @@ -590,8 +582,11 @@ decl_module! { | ReceivalResult::TooManyUnrewardedRelayers | ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), }; + + let unspent_weight = sp_std::cmp::min(unspent_weight, dispatch_weight); + dispatch_weight_left -= dispatch_weight - unspent_weight; actual_weight = actual_weight - .saturating_sub(sp_std::cmp::min(unspent_weight, dispatch_weight)) + .saturating_sub(unspent_weight) .saturating_sub( // delivery call weight formula assumes that the fee is paid at // this (target) chain. If the message is prepaid at the source @@ -1555,18 +1550,16 @@ mod tests { } #[test] - fn receive_messages_proof_rejects_invalid_dispatch_weight() { + fn receive_messages_proof_does_not_accept_message_if_dispatch_weight_is_not_enough() { run_test(|| { - assert_noop!( - Pallet::::receive_messages_proof( - Origin::signed(1), - TEST_RELAYER_A, - Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), - 1, - REGULAR_PAYLOAD.declared_weight - 1, - ), - Error::::InvalidMessagesDispatchWeight, - ); + assert_ok!(Pallet::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + 1, + REGULAR_PAYLOAD.declared_weight - 1, + )); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 0); }); } @@ -1848,19 +1841,17 @@ mod tests { run_test(|| { let message1 = message(1, message_payload(0, Weight::MAX / 2)); let message2 = message(2, message_payload(0, Weight::MAX / 2)); - let message3 = message(2, message_payload(0, Weight::MAX / 2)); + let message3 = message(3, message_payload(0, Weight::MAX / 2)); - assert_noop!( - Pallet::::receive_messages_proof( - Origin::signed(1), - TEST_RELAYER_A, - // this may cause overflow if source chain storage is invalid - Ok(vec![message1, message2, message3]).into(), - 3, - 100, - ), - Error::::InvalidMessagesDispatchWeight, - ); + assert_ok!(Pallet::::receive_messages_proof( + Origin::signed(1), + TEST_RELAYER_A, + // this may cause overflow if source chain storage is invalid + Ok(vec![message1, message2, message3]).into(), + 3, + Weight::MAX, + )); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 2); }); } From d641c3fc0972f2c8d5063a95b11fbf6aa5fa4780 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 29 Jul 2021 10:23:58 +0300 Subject: [PATCH 0524/1210] fixed wrong trace (#1075) --- modules/dispatch/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 46f05b487c376..d3533fcfcb0a4 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -313,7 +313,7 @@ impl, I: Instance> MessageDispatch for "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}. Call dispatch result: {:?}", source_chain, id, - dispatch_result.unspent_weight, + actual_call_weight, message.weight, dispatch_result, result, From f2294beeb6aec73a511ae68d67fdcb473e939fcd Mon Sep 17 00:00:00 2001 From: Tomasz Waszczyk Date: Sun, 1 Aug 2021 20:09:40 +0200 Subject: [PATCH 0525/1210] Fix full spellcheck (#1076) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(spellcheck): test of fixing * fix(hunspell): improved many typos etc. * fix(hunspell): all errors solved * fix(hunspell): extended scope of files - the build should fail * Return error code. * Fix spelling, sort dictionary. * fix(hunspell): added fix to gitlabs check * fix(typo): one typo and test of verification on github * fix(typo): one typo Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/cli.rs | 2 +- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/node/src/cli.rs | 2 +- bin/rialto/runtime/src/exchange.rs | 4 ++-- bin/rialto/runtime/src/kovan.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- docs/high-level-overview.md | 4 ++-- modules/dispatch/src/lib.rs | 2 +- modules/ethereum-contract-builtin/src/lib.rs | 4 ++-- modules/ethereum/src/finality.rs | 4 ++-- modules/ethereum/src/import.rs | 2 +- modules/ethereum/src/lib.rs | 8 ++++---- modules/ethereum/src/test_utils.rs | 2 +- modules/ethereum/src/verification.rs | 2 +- modules/grandpa/src/benchmarking.rs | 4 ++-- modules/grandpa/src/lib.rs | 10 +++++----- modules/messages/src/instant_payments.rs | 6 +++--- modules/messages/src/lib.rs | 10 +++++----- modules/messages/src/mock.rs | 2 +- modules/messages/src/outbound_lane.rs | 2 +- modules/messages/src/weights_ext.rs | 8 ++++---- primitives/chain-kusama/src/lib.rs | 4 ++-- primitives/chain-millau/src/lib.rs | 6 +++--- primitives/chain-polkadot/src/lib.rs | 4 ++-- primitives/chain-rialto/src/lib.rs | 6 +++--- primitives/chain-rococo/src/lib.rs | 4 ++-- primitives/chain-westend/src/lib.rs | 6 +++--- primitives/chain-wococo/src/lib.rs | 4 ++-- primitives/currency-exchange/src/lib.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 4 ++-- primitives/header-chain/src/justification.rs | 2 +- primitives/message-dispatch/src/lib.rs | 2 +- primitives/messages/src/lib.rs | 10 +++++----- primitives/messages/src/source_chain.rs | 6 +++--- primitives/messages/src/target_chain.rs | 2 +- primitives/polkadot-core/src/lib.rs | 12 ++++++------ primitives/runtime/src/lib.rs | 6 +++--- primitives/runtime/src/messages.rs | 2 +- primitives/test-utils/src/lib.rs | 2 +- relays/bin-ethereum/src/ethereum_client.rs | 2 +- relays/bin-ethereum/src/rialto_client.rs | 6 +++--- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/cli/derive_account.rs | 2 +- relays/bin-substrate/src/cli/encode_message.rs | 2 +- relays/bin-substrate/src/cli/init_bridge.rs | 2 +- relays/bin-substrate/src/cli/mod.rs | 4 ++-- relays/bin-substrate/src/cli/send_message.rs | 2 +- relays/bin-substrate/src/finality_pipeline.rs | 2 +- relays/bin-substrate/src/messages_lane.rs | 4 ++-- relays/bin-substrate/src/on_demand_headers.rs | 2 +- relays/client-ethereum/src/sign.rs | 2 +- relays/client-rococo/src/runtime.rs | 2 +- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 4 ++-- relays/client-substrate/src/guard.rs | 2 +- relays/client-wococo/src/runtime.rs | 2 +- relays/headers/src/headers.rs | 10 +++++----- relays/headers/src/sync.rs | 10 +++++----- relays/headers/src/sync_loop.rs | 2 +- relays/headers/src/sync_types.rs | 4 ++-- relays/messages/src/lib.rs | 2 +- relays/messages/src/message_lane_loop.rs | 4 ++-- relays/messages/src/message_race_delivery.rs | 4 ++-- relays/messages/src/message_race_loop.rs | 14 +++++++------- relays/messages/src/message_race_receiving.rs | 2 +- relays/messages/src/message_race_strategy.rs | 2 +- relays/messages/src/metrics.rs | 6 +++--- relays/utils/src/relay_loop.rs | 2 +- 68 files changed, 137 insertions(+), 137 deletions(-) diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 46323ed25c9ed..49f4fc092fac0 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -29,7 +29,7 @@ pub struct Cli { /// Possible subcommands of the main binary. #[derive(Debug, StructOpt)] pub enum Subcommand { - /// Key management cli utilities + /// Key management CLI utilities Key(sc_cli::KeySubcommand), /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index ff5b39439b60b..8d9f5edcf1baa 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -238,7 +238,7 @@ parameter_types! { } impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the unix epoch. + /// A timestamp: milliseconds since the UNIX epoch. type Moment = u64; type OnTimestampSet = Aura; type MinimumPeriod = MinimumPeriod; diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 46323ed25c9ed..49f4fc092fac0 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -29,7 +29,7 @@ pub struct Cli { /// Possible subcommands of the main binary. #[derive(Debug, StructOpt)] pub enum Subcommand { - /// Key management cli utilities + /// Key management CLI utilities Key(sc_cli::KeySubcommand), /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index a054962a79c71..e259856f37559 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -55,7 +55,7 @@ pub struct EthereumTransactionInclusionProof { /// /// The assumption is that this pair will never appear more than once in /// transactions included into finalized blocks. This is obviously true -/// for any existing eth-like chain (that keep current tx format), because +/// for any existing eth-like chain (that keep current TX format), because /// otherwise transaction can be replayed over and over. #[derive(Encode, Decode, PartialEq, RuntimeDebug)] pub struct EthereumTransactionTag { @@ -65,7 +65,7 @@ pub struct EthereumTransactionTag { pub nonce: sp_core::U256, } -/// Eth transaction from runtime perspective. +/// Ethereum transaction from runtime perspective. pub struct EthTransaction; impl MaybeLockFundsTransaction for EthTransaction { diff --git a/bin/rialto/runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs index 03b0ca8a07163..15c73fc6ea3f0 100644 --- a/bin/rialto/runtime/src/kovan.rs +++ b/bin/rialto/runtime/src/kovan.rs @@ -34,7 +34,7 @@ frame_support::parameter_types! { kovan_validators_configuration(); } -/// Max number of finalized headers to keep. It is equivalent of ~24 hours of +/// Max number of finalized headers to keep. It is equivalent of around 24 hours of /// finalized blocks on current Kovan chain. const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 762ef1710220f..3a40139d6d938 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -370,7 +370,7 @@ parameter_types! { } impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the unix epoch. + /// A timestamp: milliseconds since the UNIX epoch. type Moment = bp_rialto::Moment; type OnTimestampSet = Babe; type MinimumPeriod = MinimumPeriod; diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 9ca3ca42ff5e5..2fc210ed7a56e 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -74,7 +74,7 @@ Referer to the [pallet documentation](../modules/substrate/src/lib.rs) for more There is currently no reward strategy for the relayers at all. They also are not required to be staked or registered on-chain, unlike in other bridge designs. We consider the header sync to be -an essential part of the bridge and the incentivisation should be happening on the higher layers. +an essential part of the bridge and the incentivization should be happening on the higher layers. At the moment, signed transactions are the only way to submit headers to the header sync pallet. However, in the future we would like to use unsigned transactions for headers delivery. This will @@ -110,7 +110,7 @@ Users of the pallet add their messages to an "outbound lane" on the source chain finalized message relayers are responsible for reading the current queue of messages and submitting some (or all) of them to the "inbound lane" of the target chain. Each message has a `nonce` associated with it, which serves as the ordering of messages. The inbound lane stores the last -delivered nonce to prevent replaying messages. To succesfuly deliver the message to the inbound lane +delivered nonce to prevent replaying messages. To successfully deliver the message to the inbound lane on target chain the relayer has to present present a storage proof which shows that the message was part of the outbound lane on the source chain. diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index d3533fcfcb0a4..b27295481a2c7 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -19,7 +19,7 @@ //! The messages are interpreted directly as runtime `Call`. We attempt to decode //! them and then dispatch as usual. To prevent compatibility issues, the Calls have //! to include a `spec_version`. This will be checked before dispatch. In the case of -//! a succesful dispatch an event is emitted. +//! a successful dispatch an event is emitted. #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] diff --git a/modules/ethereum-contract-builtin/src/lib.rs b/modules/ethereum-contract-builtin/src/lib.rs index a07f838cf8d64..75004fd2a92f6 100644 --- a/modules/ethereum-contract-builtin/src/lib.rs +++ b/modules/ethereum-contract-builtin/src/lib.rs @@ -28,9 +28,9 @@ pub enum Error { BlockNumberDecode, /// Failed to decode Substrate header. HeaderDecode(codec::Error), - /// Failed to decode best voters set. + /// Failed to decode the best voters set. BestSetDecode(codec::Error), - /// Best voters set is invalid. + /// The best voters set is invalid. InvalidBestSet, /// Failed to decode finality proof. FinalityProofDecode(codec::Error), diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 58987c6b29bc5..25f1ecdb2c3df 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -36,7 +36,7 @@ pub struct CachedFinalityVotes { /// best finalized. pub stopped_at_finalized_sibling: bool, /// Header ancestors that were read while we have been searching for - /// cached votes entry. Newest header has index 0. + /// cached votes entry. The newest header has index 0. pub unaccounted_ancestry: VecDeque<(HeaderId, Option, AuraHeader)>, /// Cached finality votes, if they have been found. The associated /// header is not included into `unaccounted_ancestry`. @@ -59,7 +59,7 @@ pub struct FinalityEffects { pub struct FinalityVotes { /// Number of votes per each validator. pub votes: BTreeMap, - /// Ancestry blocks with oldest ancestors at the beginning and newest at the + /// Ancestry blocks with the oldest ancestors at the beginning and newest at the /// end of the queue. pub ancestry: VecDeque>, } diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 8cd4c8a17c771..89ee39f7b3c41 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -22,7 +22,7 @@ use crate::{AuraConfiguration, ChainTime, ChangeToEnact, PruningStrategy, Storag use bp_eth_poa::{AuraHeader, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; -/// Imports bunch of headers and updates blocks finality. +/// Imports a bunch of headers and updates blocks finality. /// /// Transactions receipts must be provided if `header_import_requires_receipts()` /// has returned true. diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index facf377d51b82..ebb36edbe54d6 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -169,8 +169,8 @@ struct PruningRange { /// were unable to prune for whatever reason (i.e. if it isn't finalized yet and has /// scheduled validators set change). pub oldest_unpruned_block: u64, - /// Number of oldest block(s) that we want to keep. We want to prune blocks in range - /// [`oldest_unpruned_block`; `oldest_block_to_keep`). + /// Number of the oldest block(s) that we want to keep. We want to prune blocks in range + /// [ `oldest_unpruned_block`; `oldest_block_to_keep` ). pub oldest_block_to_keep: u64, } @@ -316,10 +316,10 @@ pub trait PruningStrategy: Default { /// Pallet may prune both finalized and unfinalized blocks. But it can't give any /// guarantees on when it will happen. Example: if some unfinalized block at height N /// has scheduled validators set change, then the module won't prune any blocks with - /// number >= N even if strategy allows that. + /// number greater than or equal to N even if strategy allows that. /// /// If your strategy allows pruning unfinalized blocks, this could lead to switch - /// between finalized forks (only if authorities are misbehaving). But since 50%+1 (or 2/3) + /// between finalized forks (only if authorities are misbehaving). But since 50 percent plus one (or 2/3) /// authorities are able to do whatever they want with the chain, this isn't considered /// fatal. If your strategy only prunes finalized blocks, we'll never be able to finalize /// header that isn't descendant of current best finalized block. diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 41161089ba6d0..853ad0930bb0d 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -19,7 +19,7 @@ //! Although the name implies that it is used by tests, it shouldn't be be used _directly_ by tests. //! Instead these utilities should be used by the Mock runtime, which in turn is used by tests. //! -//! On the other hand, they may be used directly by the bechmarking module. +//! On the other hand, they may be used directly by the benchmark module. // Since this is test code it's fine that not everything is used #![allow(dead_code)] diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index c8c4deca87f1d..638da68af46ad 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -43,7 +43,7 @@ pub fn is_importable_header(storage: &S, header: &AuraHeader) -> Res Ok((id, finalized_id)) } -/// Try accept unsigned aura header into transaction pool. +/// Try to accept unsigned aura header into transaction pool. /// /// Returns required and provided tags. pub fn accept_aura_header_into_pool( diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index bc027e86a4b59..02600201f7466 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -23,7 +23,7 @@ //! 2. The number of `pre-commits` in the justification //! //! Vote ancestries are the headers between (`finality_target`, `head_of_chain`], where -//! `header_of_chain` is a decendant of `finality_target`. +//! `header_of_chain` is a descendant of `finality_target`. //! //! Pre-commits are messages which are signed by validators at the head of the chain they think is //! the best. @@ -34,7 +34,7 @@ //! [A] <- [B] <- [C] //! //! The common ancestor of both forks is block A, so this is what GRANDPA will finalize. In order to -//! verify this we will have vote ancestries of [B, C, B', C'] and pre-commits [C, C']. +//! verify this we will have vote ancestries of `[B, C, B', C']` and pre-commits `[C, C']`. //! //! Note that the worst case scenario here would be a justification where each validator has it's //! own fork which is `SESSION_LENGTH` blocks long. diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 4cca1c7827383..6c25968630e27 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -28,7 +28,7 @@ //! //! Since this pallet only tracks finalized headers it does not deal with forks. Forks can only //! occur if the GRANDPA validator set on the bridged chain is either colluding or there is a severe -//! bug causing resulting in an equivocation. Such events are outside of the scope of this pallet. +//! bug causing resulting in an equivocation. Such events are outside the scope of this pallet. //! Shall the fork occur on the bridged chain governance intervention will be required to //! re-initialize the bridge and track the right fork. @@ -175,7 +175,7 @@ pub mod pallet { /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. /// /// The initial configuration provided does not need to be the genesis header of the bridged - /// chain, it can be any arbirary header. You can also provide the next scheduled set change + /// chain, it can be any arbitrary header. You can also provide the next scheduled set change /// if it is already know. /// /// This function is only allowed to be called from a trusted origin and writes to storage @@ -355,7 +355,7 @@ pub mod pallet { /// is found it will be enacted immediately. /// /// This function does not support forced changes, or scheduled changes with delays - /// since these types of changes are indicitive of abnormal behaviour from GRANDPA. + /// since these types of changes are indicative of abnormal behavior from GRANDPA. /// /// Returned value will indicate if a change was enacted or not. pub(crate) fn try_enact_authority_change, I: 'static>( @@ -401,7 +401,7 @@ pub mod pallet { /// /// Will use the GRANDPA current authorities known to the pallet. /// - /// If succesful it returns the decoded GRANDPA justification so we can refund any weight which + /// If successful it returns the decoded GRANDPA justification so we can refund any weight which /// was overcharged in the initial call. pub(crate) fn verify_justification, I: 'static>( justification: &GrandpaJustification>, @@ -432,7 +432,7 @@ pub mod pallet { /// Import a previously verified header to the storage. /// /// Note this function solely takes care of updating the storage and pruning old entries, - /// but does not verify the validaty of such import. + /// but does not verify the validity of such import. pub(crate) fn insert_header, I: 'static>(header: BridgedHeader, hash: BridgedBlockHash) { let index = >::get(); let pruning = >::try_get(index); diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index 524a3765d6ad4..80bc32f294a6d 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -31,14 +31,14 @@ use sp_std::fmt::Debug; /// Instant message payments made in given currency. /// -/// The balance is initally reserved in a special `relayers-fund` account, and transferred +/// The balance is initially reserved in a special `relayers-fund` account, and transferred /// to the relayer when message delivery is confirmed. /// -/// Additionaly, confirmation transaction submitter (`confirmation_relayer`) is reimbursed +/// Additionally, confirmation transaction submitter (`confirmation_relayer`) is reimbursed /// with the confirmation rewards (part of message fee, reserved to pay for delivery confirmation). /// /// NOTE The `relayers-fund` account must always exist i.e. be over Existential Deposit (ED; the -/// pallet enforces that) to make sure that even if the message cost is below ED it is still payed +/// pallet enforces that) to make sure that even if the message cost is below ED it is still paid /// to the relayer account. /// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they /// can receive the payment. diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index ed57baaf6e4fa..842c28bd4b7d3 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -86,7 +86,7 @@ mod mock; pub trait Config: frame_system::Config { // General types - /// They overarching event type. + /// They are overarching event type. type Event: From> + Into<::Event>; /// Benchmarks results from runtime we're plugged into. type WeightInfo: WeightInfoExt; @@ -786,22 +786,22 @@ impl, I: Instance> Pallet { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } - /// Get nonce of latest generated message at given outbound lane. + /// Get nonce of the latest generated message at given outbound lane. pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { OutboundLanes::::get(&lane).latest_generated_nonce } - /// Get nonce of latest confirmed message at given outbound lane. + /// Get nonce of the latest confirmed message at given outbound lane. pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { OutboundLanes::::get(&lane).latest_received_nonce } - /// Get nonce of latest received message at given inbound lane. + /// Get nonce of the latest received message at given inbound lane. pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { InboundLanes::::get(&lane).last_delivered_nonce() } - /// Get nonce of latest confirmed message at given inbound lane. + /// Get nonce of the latest confirmed message at given inbound lane. pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { InboundLanes::::get(&lane).last_confirmed_nonce } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 063bbfaa5aea7..f2a42ab55e49f 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -386,7 +386,7 @@ impl OnDeliveryConfirmed for TestOnDeliveryConfirmed1 { } } -/// Seconde on-messages-delivered callback. +/// Second on-messages-delivered callback. #[derive(Debug)] pub struct TestOnDeliveryConfirmed2; diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 7130bd1bb53d2..5888fa7fd7f85 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -49,7 +49,7 @@ pub enum ReceivalConfirmationResult { /// New messages have been confirmed by the confirmation transaction. ConfirmedMessages(DeliveredMessages), /// Confirmation transaction brings no new confirmation. This may be a result of relayer - /// error or several relayers runnng. + /// error or several relayers running. NoNewConfirmations, /// Bridged chain is trying to confirm more messages than we have generated. May be a result /// of invalid bridged chain storage. diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index e1b8c7e885362..b17be922f5dbb 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -266,7 +266,7 @@ pub trait WeightInfoExt: WeightInfo { weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead) } - /// Returns weight that needs to be accounted when receiving given number of messages with message + /// Returns weight that needs to be accounted when receiving given a number of messages with message /// delivery transaction (`receive_messages_proof`). fn receive_messages_proof_messages_overhead(messages: MessageNonce) -> Weight { let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof(); @@ -293,7 +293,7 @@ pub trait WeightInfoExt: WeightInfo { weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead) } - /// Returns weight that needs to be accounted when receiving confirmations for given number of + /// Returns weight that needs to be accounted when receiving confirmations for given a number of /// messages with delivery confirmation transaction (`receive_messages_delivery_proof`). fn receive_messages_delivery_proof_messages_overhead(messages: MessageNonce) -> Weight { let weight_of_two_messages = Self::receive_delivery_proof_for_two_messages_by_single_relayer(); @@ -303,7 +303,7 @@ pub trait WeightInfoExt: WeightInfo { .saturating_mul(messages as Weight) } - /// Returns weight that needs to be accounted when receiving confirmations for given number of + /// Returns weight that needs to be accounted when receiving confirmations for given a number of /// relayers entries with delivery confirmation transaction (`receive_messages_delivery_proof`). fn receive_messages_delivery_proof_relayers_overhead(relayers: MessageNonce) -> Weight { let weight_of_two_messages_by_two_relayers = Self::receive_delivery_proof_for_two_messages_by_two_relayers(); @@ -314,7 +314,7 @@ pub trait WeightInfoExt: WeightInfo { .saturating_mul(relayers as Weight) } - /// Returns weight that needs to be accounted when storage proof of given size is recieved (either in + /// Returns weight that needs to be accounted when storage proof of given size is received (either in /// `receive_messages_proof` or `receive_messages_delivery_proof`). /// /// **IMPORTANT**: this overhead is already included in the 'base' transaction cost - e.g. proof diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index d0e9e3acd503a..e5ab47259e54c 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -79,7 +79,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Kusama from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -110,7 +110,7 @@ sp_api::decl_runtime_apis! { pub trait FromKusamaInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 0efc54e96e6ad..d9f4fd51f9696 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -130,7 +130,7 @@ pub type BlockNumber = u64; /// Hash type used in Millau. pub type Hash = ::Out; -/// The type of an object that can produce hashes on Millau. +/// Type of object that can produce hashes on Millau. pub type Hasher = BlakeTwoAndKeccak256; /// The header type used by Millau. @@ -287,7 +287,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Millau from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -318,7 +318,7 @@ sp_api::decl_runtime_apis! { pub trait FromMillauInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 7ab1c7f4390b7..b0ba77c66ffc3 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -79,7 +79,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Polkadot from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -110,7 +110,7 @@ sp_api::decl_runtime_apis! { pub trait FromPolkadotInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 4fe05547b530b..10eac7deb8f54 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -126,7 +126,7 @@ pub type BlockNumber = u32; /// Hash type used in Rialto. pub type Hash = ::Out; -/// The type of an object that can produce hashes on Rialto. +/// The type of object that can produce hashes on Rialto. pub type Hasher = BlakeTwo256; /// The header type used by Rialto. @@ -256,7 +256,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Rialto from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -287,7 +287,7 @@ sp_api::decl_runtime_apis! { pub trait FromRialtoInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 8df064e891833..d76ec8e679d31 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -116,7 +116,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Rococo from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -147,7 +147,7 @@ sp_api::decl_runtime_apis! { pub trait FromRococoInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index a0895da259d4e..4f8b9cccf4c75 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -52,7 +52,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// All entries here (like pretty much in the entire file) must be kept in sync with Westend /// `construct_runtime`, so that we maintain SCALE-compatibility. /// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/westend/src/lib.rs +/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/westend/src/lib.rs) #[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { /// Rococo bridge pallet. @@ -141,7 +141,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Westend from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -172,7 +172,7 @@ sp_api::decl_runtime_apis! { pub trait FromWestendInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 24572e141b20f..e0d49ffe85506 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -81,7 +81,7 @@ sp_api::decl_runtime_apis! { /// /// Returns `None` if message is too expensive to be sent to Wococo from this chain. /// - /// Please keep in mind that this method returns lowest message fee required for message + /// Please keep in mind that this method returns the lowest message fee required for message /// to be accepted to the lane. It may be good idea to pay a bit over this price to account /// future exchange rate changes and guarantee that relayer would deliver your message /// to the target chain. @@ -112,7 +112,7 @@ sp_api::decl_runtime_apis! { pub trait FromWococoInboundLaneApi { /// Returns nonce of the latest message, received by given lane. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of latest message that has been confirmed to the bridged chain. + /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index 88695dbb5ef40..c85a9d4ff7d2b 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -36,7 +36,7 @@ pub enum Error { InvalidRecipient, /// Cannot map from peer recipient to this blockchain recipient. FailedToMapRecipients, - /// Failed to convert from peer blockchain currency to this blockhain currency. + /// Failed to convert from peer blockchain currency to this blockchain currency. FailedToConvertCurrency, /// Deposit has failed. DepositFailed, diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 382e6f81ee5d3..b2e00760c01d6 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -323,7 +323,7 @@ impl UnsignedTransaction { stream.out().to_vec() } - /// Encode to given rlp stream. + /// Encode to given RLP stream. pub fn rlp_to(&self, chain_id: Option, stream: &mut RlpStream) { stream.append(&self.nonce); stream.append(&self.gas_price); @@ -405,7 +405,7 @@ impl SealedEmptyStep { keccak_256(&message.out()).into() } - /// Returns rlp for the vector of empty steps (we only do encoding in tests). + /// Returns RLP for the vector of empty steps (we only do encoding in tests). pub fn rlp_of(empty_steps: &[SealedEmptyStep]) -> Bytes { let mut s = RlpStream::new(); s.begin_list(empty_steps.len()); diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 625d7762597a1..760369fe0d870 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -168,7 +168,7 @@ where pub struct AncestryChain { /// Header hash => parent header hash mapping. pub parents: BTreeMap, - /// Hashes of headers that weren't visited by `is_ancestor` method. + /// Hashes of headers that were not visited by `is_ancestor` method. pub unvisited: BTreeSet, } diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 859dc5e469ad9..65f9fc15dc233 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -77,7 +77,7 @@ pub enum CallOrigin { /// Identifiers of relayers and messages that they have delivered to this lane (ordered by message nonce). /// /// This serves as a helper storage item, to allow the source chain to easily pay rewards - /// to the relayers who succesfuly delivered messages to the target chain (inbound lane). + /// to the relayers who successfully delivered messages to the target chain (inbound lane). /// /// It is guaranteed to have at most N entries, where N is configured at the module level. /// If there are N entries in this vec, then: @@ -149,7 +149,7 @@ impl Default for InboundLaneData { } impl InboundLaneData { - /// Returns approximate size of the struct, given number of entries in the `relayers` set and + /// Returns approximate size of the struct, given a number of entries in the `relayers` set and /// size of each entry. /// /// Returns `None` if size overflows `u32` limits. @@ -277,12 +277,12 @@ pub struct UnrewardedRelayersState { /// Outbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct OutboundLaneData { - /// Nonce of oldest message that we haven't yet pruned. May point to not-yet-generated message if + /// Nonce of the oldest message that we haven't yet pruned. May point to not-yet-generated message if /// all sent messages are already pruned. pub oldest_unpruned_nonce: MessageNonce, - /// Nonce of latest message, received by bridged chain. + /// Nonce of the latest message, received by bridged chain. pub latest_received_nonce: MessageNonce, - /// Nonce of latest message, generated by us. + /// Nonce of the latest message, generated by us. pub latest_generated_nonce: MessageNonce, } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index ed69f39c7630f..a1ec0f19b4ffe 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -56,14 +56,14 @@ pub trait TargetHeaderChain { /// /// The proper implementation must ensure that the delivery-transaction with this /// payload would (at least) be accepted into target chain transaction pool AND - /// eventually will be successfully 'mined'. The most obvious incorrect implementation + /// eventually will be successfully mined. The most obvious incorrect implementation /// example would be implementation for BTC chain that accepts payloads larger than /// 1MB. BTC nodes aren't accepting transactions that are larger than 1MB, so relayer /// will be unable to craft valid transaction => this (and all subsequent) messages will /// never be delivered. fn verify_message(payload: &Payload) -> Result<(), Self::Error>; - /// Verify messages delivery proof and return lane && nonce of the latest recevied message. + /// Verify messages delivery proof and return lane && nonce of the latest received message. fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error>; @@ -102,7 +102,7 @@ pub trait LaneMessageVerifier { /// by relayer. /// /// So to be sure that any non-altruist relayer would agree to deliver message, submitter -/// should set `delivery_and_dispatch_fee` to at least (equialent of): sum of fees from (2) +/// should set `delivery_and_dispatch_fee` to at least (equivalent of): sum of fees from (2) /// to (4) above, plus some interest for the relayer. pub trait MessageDeliveryAndDispatchPayment { /// Error type. diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index d1b87fd02323a..38ce9e800da43 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -75,7 +75,7 @@ pub trait SourceHeaderChain { /// messages will be rejected. /// /// The `messages_count` argument verification (sane limits) is supposed to be made - /// outside of this function. This function only verifies that the proof declares exactly + /// outside this function. This function only verifies that the proof declares exactly /// `messages_count` messages. fn verify_messages_proof( proof: Self::MessagesProof, diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index a1619b27bcf47..4744e29492714 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -66,18 +66,18 @@ pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// All polkadot-like chains are using same crypto. pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; -/// All Polkadot-like chains allow normal extrinsics to fill block up to 75%. +/// All Polkadot-like chains allow normal extrinsics to fill block up to 75 percent. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// All Polkadot-like chains allow 2 seconds of compute with a 6 second average block time. +/// All Polkadot-like chains allow 2 seconds of compute with a 6-second average block time. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; -/// All Polkadot-like chains assume that an on-initialize consumes 1% of the weight on average, -/// hence a single extrinsic will not be allowed to consume more than `AvailableBlockRatio - 1%`. +/// All Polkadot-like chains assume that an on-initialize consumes 1 percent of the weight on average, +/// hence a single extrinsic will not be allowed to consume more than `AvailableBlockRatio - 1 percent`. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(1); @@ -165,7 +165,7 @@ pub type Index = u32; /// Hashing type. pub type Hashing = BlakeTwo256; -/// The type of an object that can produce hashes on Polkadot-like chains. +/// The type of object that can produce hashes on Polkadot-like chains. pub type Hasher = BlakeTwo256; /// The header type used by Polkadot-like chains. @@ -304,7 +304,7 @@ impl Convert for AccountIdConverter { /// Return a storage key for account data. /// /// This is based on FRAME storage-generation code from Substrate: -/// https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74 +/// [link](https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74) /// The equivalent command to invoke in case full `Runtime` is known is this: /// `let key = frame_system::Account::::storage_map_final_key(&account_id);` pub fn account_info_storage_key(id: &AccountId) -> Vec { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 7b17a2947fce9..ed915b7288640 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -74,9 +74,9 @@ pub type ChainId = [u8; 4]; /// Type of accounts on the source chain. pub enum SourceAccount { - /// An account that belongs to Root (priviledged origin). + /// 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.). @@ -86,7 +86,7 @@ pub enum SourceAccount { /// 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. +/// this can be successfully 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. diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index f6e04619c7230..1b00c10fa4930 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -22,7 +22,7 @@ use frame_support::{weights::Weight, RuntimeDebug}; /// Where message dispatch fee is paid? #[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq)] 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. /// diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 64109754086cf..83aac614ab809 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -49,7 +49,7 @@ pub struct JustificationGeneratorParams { pub authorities: Vec<(Account, AuthorityWeight)>, /// The total number of precommit ancestors in the `votes_ancestries` field our justification. /// - /// These may be distributed among many different forks. + /// These may be distributed among many forks. pub ancestors: u32, /// The number of forks. /// diff --git a/relays/bin-ethereum/src/ethereum_client.rs b/relays/bin-ethereum/src/ethereum_client.rs index 71a3f38859b78..007bef49fea07 100644 --- a/relays/bin-ethereum/src/ethereum_client.rs +++ b/relays/bin-ethereum/src/ethereum_client.rs @@ -41,7 +41,7 @@ type RpcResult = std::result::Result; /// interactions involving, for example, an Ethereum contract. #[async_trait] pub trait EthereumHighLevelRpc { - /// Returns best Substrate block that PoA chain knows of. + /// Returns the best Substrate block that PoA chain knows of. async fn best_substrate_block(&self, contract_address: Address) -> RpcResult; /// Returns true if Substrate header is known to Ethereum node. diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index 1ec1e7df79403..311bc9edbc706 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -41,13 +41,13 @@ type RpcResult = std::result::Result; /// interactions involving, for example, an Ethereum bridge module. #[async_trait] pub trait SubstrateHighLevelRpc { - /// Returns best Ethereum block that Substrate runtime knows of. + /// Returns the best Ethereum block that Substrate runtime knows of. async fn best_ethereum_block(&self) -> RpcResult; /// Returns best finalized Ethereum block that Substrate runtime knows of. async fn best_ethereum_finalized_block(&self) -> RpcResult; - /// Returns whether or not transactions receipts are required for Ethereum header submission. + /// Returns whether transactions receipts are required for Ethereum header submission. async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult; - /// Returns whether or not the given Ethereum header is known to the Substrate runtime. + /// Returns whether the given Ethereum header is known to the Substrate runtime. async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult; } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index ec94450a63de5..ec34d9cd33fc7 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,7 +27,7 @@ use crate::cli::{ /// Weight of the `system::remark` call at Rococo. /// -/// This weight is larger (x2) than actual weight at current Rooco runtime to avoid unsuccessful +/// This weight is larger (x2) than actual weight at current Rococo runtime to avoid unsuccessful /// calls in the future. But since it is used only in tests (and on test chains), this is ok. pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs index f1967df8c7452..1903d42c1fcb0 100644 --- a/relays/bin-substrate/src/cli/derive_account.rs +++ b/relays/bin-substrate/src/cli/derive_account.rs @@ -28,7 +28,7 @@ use strum::VariantNames; /// since messages sent over the bridge will be able to spend these. #[derive(StructOpt)] pub struct DeriveAccount { - /// A bridge instance to initalize. + /// A bridge instance to initialize. #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, /// Source-chain address to derive Target-chain address from. diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index a2d8a422b5dcf..d002ab28f4996 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -41,7 +41,7 @@ pub enum MessagePayload { /// A `MessagePayload` to encode. #[derive(StructOpt)] pub struct EncodeMessage { - /// A bridge instance to initalize. + /// A bridge instance to initialize. #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, #[structopt(flatten)] diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 1ff39ede5cea6..647978e430a81 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -26,7 +26,7 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; /// Initialize bridge pallet. #[derive(StructOpt)] pub struct InitBridge { - /// A bridge instance to initalize. + /// A bridge instance to initialize. #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] bridge: InitBridgeName, #[structopt(flatten)] diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 3088b06eb05ed..d108c71f7b44d 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -235,7 +235,7 @@ pub trait CliChain: relay_substrate_client::Chain { /// Bridge Message Payload type. /// - /// TODO [#854] This should be removed in favour of target-specifc types. + /// TODO [#854] This should be removed in favor of target-specifc types. type MessagePayload; /// Numeric value of SS58 format. @@ -354,7 +354,7 @@ where } /// Create chain-specific set of configuration objects: connection parameters, -/// signing parameters and bridge initialisation parameters. +/// signing parameters and bridge initialization parameters. #[macro_export] macro_rules! declare_chain_options { ($chain:ident, $chain_prefix:ident) => { diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 2834474579644..6259c85b50ce4 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -35,7 +35,7 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; #[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)] #[strum(serialize_all = "kebab_case")] 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. AtTargetChain, diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/bin-substrate/src/finality_pipeline.rs index 19fa0917df390..2013ec646b252 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/bin-substrate/src/finality_pipeline.rs @@ -49,7 +49,7 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { /// Start finality relay guards. /// /// Different finality bridges may have different set of guards - e.g. on ephemeral chains we - /// don't need version guards, on test chains we don't care that much about relayer account + /// don't need a version guards, on test chains we don't care that much about relayer account /// balance, ... So the implementation is left to the specific bridges. fn start_relay_guards(&self) {} diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/bin-substrate/src/messages_lane.rs index 1920137f140dc..cea43058d8ed5 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/bin-substrate/src/messages_lane.rs @@ -66,9 +66,9 @@ pub trait SubstrateMessageLane: MessageLane { /// Name of the runtime method that returns latest received nonce at the target chain. const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns latest confirmed (reward-paid) nonce at the target chain. + /// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the target chain. const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; - /// Numebr of the runtime method that returns state of "unrewarded relayers" set at the target chain. + /// Number of the runtime method that returns state of "unrewarded relayers" set at the target chain. const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str; /// Name of the runtime method that returns id of best finalized source header at target chain. diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/bin-substrate/src/on_demand_headers.rs index 58ef268a29f78..4a2b04328b862 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/bin-substrate/src/on_demand_headers.rs @@ -248,7 +248,7 @@ async fn background_task( } } -/// Returns `Some()` with inclusive range of headers which must be scanned for manadatory headers +/// Returns `Some()` with inclusive range of headers which must be scanned for mandatory headers /// and the first of such headers must be submitted to the target node. async fn mandatory_headers_scan_range( best_finalized_source_header_at_source: Option, diff --git a/relays/client-ethereum/src/sign.rs b/relays/client-ethereum/src/sign.rs index 6f479ab7d5cd4..da1dbc4842e4a 100644 --- a/relays/client-ethereum/src/sign.rs +++ b/relays/client-ethereum/src/sign.rs @@ -47,7 +47,7 @@ impl Default for SigningParams { } } -/// Sign and submit tranaction using given Ethereum client. +/// Sign and submit transaction using given Ethereum client. pub async fn sign_and_submit_transaction( client: &Client, params: &SigningParams, diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index 6dbd40bee5608..77d10529bf2d6 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -61,7 +61,7 @@ where /// All entries here (like pretty much in the entire file) must be kept in sync with Rococo /// `construct_runtime`, so that we maintain SCALE-compatibility. /// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 63432c9701fc3..03cbaef2d81af 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -61,7 +61,7 @@ pub trait Chain: ChainBase + Clone { type Call: Dispatchable + Debug; /// Balance of an account in native tokens. /// - /// The chain may suport multiple tokens, but this particular type is for token that is used + /// 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 diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 7449dda100f61..8164501348f47 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -85,7 +85,7 @@ impl std::fmt::Debug for Client { impl Client { /// Returns client that is able to call RPCs on Substrate node over websocket connection. /// - /// This function will keep connecting to given Sustrate node until connection is established + /// This function will keep connecting to given Substrate node until connection is established /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. pub async fn new(params: ConnectionParams) -> Self { loop { @@ -263,7 +263,7 @@ impl Client { /// Get the nonce of the given Substrate account. /// - /// Note: It's the caller's responsibility to make sure `account` is a valid ss58 address. + /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { self.jsonrpsee_execute(move |client| async move { Ok(Substrate::::system_account_next_index(&*client, account).await?) diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index e7159bf27109e..37a7c2aa275c5 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -80,7 +80,7 @@ pub fn abort_on_spec_version_change(mut env: impl Environm }); } -/// Abort if, during a 24 hours, free balance of given account is decreased at least by given value. +/// Abort if, during 24 hours, free balance of given account is decreased at least by given value. /// Other components may increase (or decrease) balance of account and it WILL affect logic of the guard. pub fn abort_when_account_balance_decreased( mut env: impl Environment, diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index e973c3a6d0280..e3e7ce7b31dd6 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -61,7 +61,7 @@ where /// All entries here (like pretty much in the entire file) must be kept in sync with Rococo /// `construct_runtime`, so that we maintain SCALE-compatibility. /// -/// See: https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs +/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] pub enum Call { diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs index 0b948d9da4cc6..b9095e1931099 100644 --- a/relays/headers/src/headers.rs +++ b/relays/headers/src/headers.rs @@ -65,7 +65,7 @@ pub struct QueuedHeaders { /// Headers that are (we believe) currently submitted to target node by our, /// not-yet mined transactions. submitted: HeadersQueue

, - /// Synced headers childrens. We need it to support case when header is synced, but some of + /// Synced headers children. We need it to support case when header is synced, but some of /// its parents are incomplete. synced_children: SyncedChildren

, /// Pointers to all headers that we ever seen and we believe we can touch in the future. @@ -191,7 +191,7 @@ impl QueuedHeaders

{ .unwrap_or(HeaderStatus::Unknown) } - /// Get oldest header from given queue. + /// Get the oldest header from given queue. pub fn header(&self, status: HeaderStatus) -> Option<&QueuedHeader

> { match status { HeaderStatus::Unknown | HeaderStatus::Synced => None, @@ -205,7 +205,7 @@ impl QueuedHeaders

{ } } - /// Get oldest headers from given queue until functor will return false. + /// Get the oldest headers from given queue until functor will return false. pub fn headers( &self, status: HeaderStatus, @@ -282,7 +282,7 @@ impl QueuedHeaders

{ ); } - /// Receive best header from the target node. + /// Receive the best header from the target node. pub fn target_best_header_response(&mut self, id: &HeaderIdOf

) { self.header_synced(id) } @@ -453,7 +453,7 @@ impl QueuedHeaders

{ } } - /// When incomplete headers ids are receved from target node. + /// When incomplete headers ids are received from target node. pub fn incomplete_headers_response(&mut self, ids: HashSet>) { // all new incomplete headers are marked Synced and all their descendants // are moved from Ready/Submitted to Incomplete queue diff --git a/relays/headers/src/sync.rs b/relays/headers/src/sync.rs index e992b1f8e583c..cd5ab0906fd54 100644 --- a/relays/headers/src/sync.rs +++ b/relays/headers/src/sync.rs @@ -35,7 +35,7 @@ pub struct HeadersSyncParams { /// Maximal total headers size in single submit request. pub max_headers_size_in_single_submit: usize, /// We only may store and accept (from Ethereum node) headers that have - /// number >= than best_substrate_header.number - prune_depth. + /// number >= than "best_substrate_header.number" - "prune_depth". pub prune_depth: u32, /// Target transactions mode. pub target_tx_mode: TargetTransactionMode, @@ -58,9 +58,9 @@ pub enum TargetTransactionMode { pub struct HeadersSync { /// Synchronization parameters. params: HeadersSyncParams, - /// Best header number known to source node. + /// The best header number known to source node. source_best_number: Option, - /// Best header known to target node. + /// The best header known to target node. target_best_header: Option>, /// Headers queue. headers: QueuedHeaders

, @@ -85,7 +85,7 @@ impl HeadersSync

{ self.source_best_number } - /// Best header known to target node. + /// The best header known to target node. pub fn target_best_header(&self) -> Option> { self.target_best_header } @@ -150,7 +150,7 @@ impl HeadersSync

{ Some(best_downloaded_number + One::one()) } - /// Selech orphan header to downoload. + /// Selech orphan header to download. pub fn select_orphan_header_to_download(&self) -> Option<&QueuedHeader

> { let orphan_header = self.headers.header(HeaderStatus::Orphan)?; diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index 5ccec4bbab555..c373f41520070 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -80,7 +80,7 @@ pub trait SourceClient: RelayClient { /// Target client trait. #[async_trait] pub trait TargetClient: RelayClient { - /// Returns ID of best header known to the target node. + /// Returns ID of the best header known to the target node. async fn best_header_id(&self) -> Result, Self::Error>; /// Returns true if header is known to the target node. diff --git a/relays/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs index 5809ebab59e1c..f6c36758b8d10 100644 --- a/relays/headers/src/sync_types.rs +++ b/relays/headers/src/sync_types.rs @@ -156,8 +156,8 @@ pub struct SubmittedHeaders { /// IDs of incomplete headers. These headers were submitted (so this id is also in `submitted` vec), /// but all descendants are not. pub incomplete: Vec, - /// IDs of ignored headers that we have decided not to submit (they're either rejected by - /// target node immediately, or they're descendants of incomplete headers). + /// IDs of ignored headers that we have decided not to submit (they are either rejected by + /// target node immediately, or their descendants of incomplete headers). pub rejected: Vec, /// Fatal target node error, if it has occured during submission. pub fatal_error: Option, diff --git a/relays/messages/src/lib.rs b/relays/messages/src/lib.rs index cdd94bca95412..861091ab20506 100644 --- a/relays/messages/src/lib.rs +++ b/relays/messages/src/lib.rs @@ -18,7 +18,7 @@ //! data. Message lane allows sending arbitrary messages between bridged chains. This //! module provides entrypoint that starts reading messages from given message lane //! of source chain and submits proof-of-message-at-source-chain transactions to the -//! target chain. Additionaly, proofs-of-messages-delivery are sent back from the +//! target chain. Additionally, proofs-of-messages-delivery are sent back from the //! target chain to the source chain. // required for futures::select! diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 282c3bc8b6b85..84b0c72408dfa 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -175,7 +175,7 @@ pub trait TargetClient: RelayClient { id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; - /// Get nonce of latest confirmed message. + /// Get nonce of the latest confirmed message. async fn latest_confirmed_received_nonce( &self, id: TargetHeaderIdOf

, @@ -218,7 +218,7 @@ pub trait TargetClient: RelayClient { /// State of the client. #[derive(Clone, Debug, Default, PartialEq)] pub struct ClientState { - /// Best header id of this chain. + /// The best header id of this chain. pub best_self: SelfHeaderId, /// Best finalized header id of this chain. pub best_finalized_self: SelfHeaderId, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 260a72f3f0c72..2e94bbee8b1c4 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -11,7 +11,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -//! Message delivery race delivers proof-of-messages from lane.source to lane.target. +//! Message delivery race delivers proof-of-messages from "lane.source" to "lane.target". use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_lane_loop::{ @@ -219,7 +219,7 @@ where /// Additional nonces data from the target client used by message delivery race. #[derive(Debug, Clone)] struct DeliveryRaceTargetNoncesData { - /// Latest nonce that we know: (1) has been delivered to us (2) has been confirmed + /// The latest nonce that we know: (1) has been delivered to us (2) has been confirmed /// back to the source node (by confirmations race) and (3) relayer has received /// reward for (and this has been confirmed by the message delivery race). confirmed_nonce: MessageNonce, diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 3b427a2d0e27f..399f871980497 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -76,7 +76,7 @@ pub struct SourceClientNonces { /// New nonces range known to the client. `New` here means all nonces generated after /// `prev_latest_nonce` passed to the `SourceClient::nonces` method. pub new_nonces: NoncesRange, - /// Latest nonce that is confirmed to the bridged client. This nonce only makes + /// The latest nonce that is confirmed to the bridged client. This nonce only makes /// sense in some races. In other races it is `None`. pub confirmed_nonce: Option, } @@ -84,7 +84,7 @@ pub struct SourceClientNonces { /// Nonces on the race target client. #[derive(Debug, Clone)] pub struct TargetClientNonces { - /// Latest nonce that is known to the target client. + /// The latest nonce that is known to the target client. pub latest_nonce: MessageNonce, /// Additional data from target node that may be used by the race. pub nonces_data: TargetNoncesData, @@ -93,7 +93,7 @@ pub struct TargetClientNonces { /// One of message lane clients, which is source client for the race. #[async_trait] pub trait SourceClient { - /// Type of error this clients returns. + /// Type of error these clients returns. type Error: std::fmt::Debug + MaybeConnectionError; /// Type of nonces range returned by the source client. type NoncesRange: NoncesRange; @@ -118,7 +118,7 @@ pub trait SourceClient { /// One of message lane clients, which is target client for the race. #[async_trait] pub trait TargetClient { - /// Type of error this clients returns. + /// Type of error these clients returns. type Error: std::fmt::Debug + MaybeConnectionError; /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; @@ -156,12 +156,12 @@ pub trait RaceStrategy: Debug { fn is_empty(&self) -> bool; /// Return id of source header that is required to be on target to continue synchronization. fn required_source_header_at_target(&self, current_best: &SourceHeaderId) -> Option; - /// Return best nonce at source node. + /// Return the best nonce at source node. /// /// `Some` is returned only if we are sure that the value is greater or equal /// than the result of `best_at_target`. fn best_at_source(&self) -> Option; - /// Return best nonce at target node. + /// Return the best nonce at target node. /// /// May return `None` if value is yet unknown. fn best_at_target(&self) -> Option; @@ -197,7 +197,7 @@ pub struct RaceState { /// Best finalized source header id at the best block on the target /// client (at the `best_finalized_source_header_id_at_best_target`). pub best_finalized_source_header_id_at_best_target: Option, - /// Best header id at the target client. + /// The best header id at the target client. pub best_target_header_id: Option, /// Best finalized header id at the target client. pub best_finalized_target_header_id: Option, diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index 4381b63591f71..f9ac61352fbd1 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -11,7 +11,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -//! Message receiving race delivers proof-of-messages-delivery from lane.target to lane.source. +//! Message receiving race delivers proof-of-messages-delivery from "lane.target" to "lane.source". use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use crate::message_lane_loop::{ diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index ed4a276e1429d..bc04ad5bcd9bc 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -40,7 +40,7 @@ pub struct BasicStrategy< > { /// All queued nonces. source_queue: SourceRangesQueue, - /// Best nonce known to target node (at its best block). `None` if it has not been received yet. + /// The best nonce known to target node (at its best block). `None` if it has not been received yet. best_target_nonce: Option, /// Unused generic types dump. _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 51a4118be8582..8f115170523b4 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -87,21 +87,21 @@ impl MessageLaneLoopMetrics { .set(source_latest_generated_nonce); } - /// Update latest confirmed nonce at source. + /// Update the latest confirmed nonce at source. pub fn update_source_latest_confirmed_nonce(&self, source_latest_confirmed_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["source_latest_confirmed"]) .set(source_latest_confirmed_nonce); } - /// Update latest received nonce at target. + /// Update the latest received nonce at target. pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["target_latest_received"]) .set(target_latest_generated_nonce); } - /// Update latest confirmed nonce at target. + /// Update the latest confirmed nonce at target. pub fn update_target_latest_confirmed_nonce(&self, target_latest_confirmed_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["target_latest_confirmed"]) diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index ea9d62752110e..38b636a599c24 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -27,7 +27,7 @@ pub const RECONNECT_DELAY: Duration = Duration::from_secs(10); /// Basic blockchain client from relay perspective. #[async_trait] pub trait Client: 'static + Clone + Send + Sync { - /// Type of error this clients returns. + /// Type of error these clients returns. type Error: 'static + Debug + MaybeConnectionError + Send + Sync; /// Try to reconnect to source node. From bbb2cde0bc3f707694f7e39b85982d04c54e3b0f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 2 Aug 2021 14:42:14 +0300 Subject: [PATCH 0526/1210] Token-swap-over-bridge pallet (#944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * token swap pallet * token swap type (replay protection) * post-merge fixes * post-merge fix * Update modules/token-swap/src/lib.rs Co-authored-by: Tomasz Drwięga * Update modules/token-swap/src/lib.rs Co-authored-by: Tomasz Drwięga * add missing comment part * Update modules/token-swap/src/lib.rs Co-authored-by: Tomasz Drwięga * starting claim after lock period is over is forbidden * move spec_version and weight to arguments Co-authored-by: Tomasz Drwięga --- modules/token-swap/Cargo.toml | 51 ++ modules/token-swap/src/lib.rs | 1028 +++++++++++++++++++++++ modules/token-swap/src/mock.rs | 174 ++++ primitives/messages/src/source_chain.rs | 16 + primitives/token-swap/Cargo.toml | 23 + primitives/token-swap/src/lib.rs | 64 ++ 6 files changed, 1356 insertions(+) create mode 100644 modules/token-swap/Cargo.toml create mode 100644 modules/token-swap/src/lib.rs create mode 100644 modules/token-swap/src/mock.rs create mode 100644 primitives/token-swap/Cargo.toml create mode 100644 primitives/token-swap/src/lib.rs diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml new file mode 100644 index 0000000000000..8a83a88503f38 --- /dev/null +++ b/modules/token-swap/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "pallet-bridge-token-swap" +description = "An Substrate pallet that allows parties on different chains (bridged using messages pallet) to swap their tokens" +version = "0.1.0" +authors = ["Parity Technologies "] +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 } +log = { version = "0.4.14", default-features = false } +serde = { version = "1.0", optional = true } + +# Bridge dependencies + +bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-token-swap = { path = "../../primitives/token-swap", default-features = false } +pallet-bridge-dispatch = { path = "../dispatch", default-features = false } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } + +[dev-dependencies] +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[features] +default = ["std"] +std = [ + "codec/std", + "bp-message-dispatch/std", + "bp-messages/std", + "bp-runtime/std", + "bp-token-swap/std", + "frame-support/std", + "frame-system/std", + "log/std", + "pallet-bridge-dispatch/std", + "serde", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs new file mode 100644 index 0000000000000..a1306c2505595 --- /dev/null +++ b/modules/token-swap/src/lib.rs @@ -0,0 +1,1028 @@ +// 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 . + +//! Runtime module that allows token swap between two parties acting on different chains. +//! +//! The swap is made using message lanes between This (where `pallet-bridge-token-swap` pallet +//! is deployed) and some other Bridged chain. No other assumptions about the Bridged chain are +//! made, so we don't need it to have an instance of the `pallet-bridge-token-swap` pallet deployed. +//! +//! There are four accounts participating in the swap: +//! +//! 1) account of This chain that has signed the `create_swap` transaction and has balance on This chain. +//! We'll be referring to this account as `source_account_at_this_chain`; +//! 2) account of the Bridged chain that is sending the `claim_swap` message from the Bridged to This chain. +//! This account has balance on Bridged chain and is willing to swap these tokens to This chain tokens of +//! the `source_account_at_this_chain`. We'll be referring to this account as `target_account_at_bridged_chain`; +//! 3) account of the Bridged chain that is indirectly controlled by the `source_account_at_this_chain`. We'll be +//! referring this account as `source_account_at_bridged_chain`; +//! 4) account of This chain that is indirectly controlled by the `target_account_at_bridged_chain`. We'll be +//! referring this account as `target_account_at_this_chain`. +//! +//! So the tokens swap is an intention of `source_account_at_this_chain` to swap his `source_balance_at_this_chain` +//! tokens to the `target_balance_at_bridged_chain` tokens owned by `target_account_at_bridged_chain`. The swap +//! process goes as follows: +//! +//! 1) the `source_account_at_this_chain` account submits the `create_swap` transaction on This chain; +//! 2) the tokens transfer message that would transfer `target_balance_at_bridged_chain` tokens from the +//! `target_account_at_bridged_chain` to the `source_account_at_bridged_chain`, is sent over the bridge; +//! 3) when transfer message is delivered and dispatched, the pallet receives notification; +//! 4) if message has been successfully dispatched, the `target_account_at_bridged_chain` sends the message +//! that would transfer `source_balance_at_this_chain` tokens to his `target_account_at_this_chain` +//! account; +//! 5) if message dispatch has failed, the `source_account_at_this_chain` may submit the `cancel_swap` +//! transaction and return his `source_balance_at_this_chain` back to his account. +//! +//! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special +//! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion. + +use bp_messages::{ + source_chain::{MessagesBridge, OnDeliveryConfirmed}, + DeliveredMessages, LaneId, MessageNonce, +}; +use bp_runtime::{messages::DispatchFeePayment, ChainId}; +use bp_token_swap::{TokenSwap, TokenSwapType}; +use codec::{Decode, Encode}; +use frame_support::{ + fail, + traits::{Currency, ExistenceRequirement}, + RuntimeDebug, +}; +use sp_core::H256; +use sp_io::hashing::blake2_256; +use sp_runtime::traits::{Convert, Saturating}; + +#[cfg(test)] +mod mock; + +/// Pending token swap state. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub enum TokenSwapState { + /// The swap has been started using the `start_claim` call, but we have no proof that it has + /// happened at the Bridged chain. + Started, + /// The swap has happened at the Bridged chain and may be claimed by the Bridged chain party using + /// the `claim_swap` call. + Confirmed, + /// The swap has failed at the Bridged chain and This chain party may cancel it using the + /// `cancel_swap` call. + Failed, +} + +pub use pallet::*; + +// comes from #[pallet::event] +#[allow(clippy::unused_unit)] +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type Event: From> + IsType<::Event>; + + /// Id of the bridge with the Bridged chain. + type BridgeChainId: Get; + /// The identifier of outbound message lane on This chain used to send token transfer + /// messages to the Bridged chain. + /// + /// It is highly recommended to use dedicated lane for every instance of token swap + /// pallet. Messages delivery confirmation callback is implemented in the way that + /// for every confirmed message, there is (at least) a storage read. Which mean, + /// that if pallet will see unrelated confirmations, it'll just burn storage-read + /// weight, achieving nothing. + type OutboundMessageLaneId: Get; + /// Messages bridge with Bridged chain. + type MessagesBridge: MessagesBridge< + Self::AccountId, + >::Balance, + MessagePayloadOf, + >; + /// Message delivery and dispatch fee for the tokens transfer message heading to the Bridged chain. + type MessageDeliveryAndDispatchFee: Get<>::Balance>; + + /// This chain Currency used in the tokens swap. + type ThisCurrency: Currency; + /// Converter from raw hash (derived from swap) to This chain account. + type FromSwapToThisAccountIdConverter: Convert; + + /// Tokens balance type at the Bridged chain. + type BridgedBalance: Parameter; + /// Account identifier type at the Bridged chain. + type BridgedAccountId: Parameter; + /// Account public key type at the Bridged chain. + type BridgedAccountPublic: Parameter; + /// Account signature type at the Bridged chain. + type BridgedAccountSignature: Parameter; + /// Converter from raw hash (derived from Bridged chain account) to This chain account. + type FromBridgedToThisAccountIdConverter: Convert; + } + + /// SCALE-encoded `Currency::transfer` call on the bridged chain. + pub type RawBridgedTransferCall = Vec; + /// Bridge message payload used by the pallet. + pub type MessagePayloadOf = bp_message_dispatch::MessagePayload< + ::AccountId, + >::BridgedAccountPublic, + >::BridgedAccountSignature, + RawBridgedTransferCall, + >; + /// Type of `TokenSwap` used by the pallet. + pub type TokenSwapOf = TokenSwap< + BlockNumberFor, + <>::ThisCurrency as Currency<::AccountId>>::Balance, + ::AccountId, + >::BridgedBalance, + >::BridgedAccountId, + >; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet {} + + #[pallet::call] + impl, I: 'static> Pallet { + /// Start token swap procedure. + /// + /// The dispatch origin for this call must be exactly the `swap.source_account_at_this_chain` account. + /// + /// Method arguments are: + /// + /// - `swap` - token swap intention; + /// - `target_public_at_bridged_chain` - the public key of the `swap.target_account_at_bridged_chain` + /// account used to verify `bridged_currency_transfer_signature`; + /// - `bridged_currency_transfer` - the SCALE-encoded tokens transfer call at the Bridged chain; + /// - `bridged_currency_transfer_signature` - the signature of the `swap.target_account_at_bridged_chain` + /// for the message returned by the `pallet_bridge_dispatch::account_ownership_digest()` function call. + /// + /// The `source_account_at_this_chain` MUST have enough balance to cover both token swap and message + /// transfer. Message fee may be estimated using corresponding `OutboundLaneApi` of This runtime. + /// + /// **WARNING**: the submitter of this transaction is responsible for verifying: + /// + /// 1) that the `bridged_currency_transfer` represents a valid token transfer call that transfers + /// `swap.target_balance_at_bridged_chain` to his `source_account_at_bridged_chain` account; + /// 2) that either the `source_account_at_bridged_chain` already exists, or the + /// `swap.target_balance_at_bridged_chain` is above existential deposit of the Bridged chain; + /// 3) the `target_public_at_bridged_chain` matches the `swap.target_account_at_bridged_chain`; + /// 4) the `bridged_currency_transfer_signature` is valid and generated by the owner of the + /// `target_public_at_bridged_chain` account (read more about [`CallOrigin::TargetAccount`]). + /// + /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. Violating other + /// rules will lead to losing message fees for this and other transactions + losing fees for message + /// transfer. + #[pallet::weight(0)] + pub fn create_swap( + origin: OriginFor, + swap: TokenSwapOf, + target_public_at_bridged_chain: T::BridgedAccountPublic, + bridged_chain_spec_version: u32, + bridged_currency_transfer: RawBridgedTransferCall, + bridged_currency_transfer_weight: Weight, + bridged_currency_transfer_signature: T::BridgedAccountSignature, + ) -> DispatchResultWithPostInfo { + // ensure that the `origin` is the same account that is mentioned in the `swap` intention + let origin_account = ensure_signed(origin)?; + ensure!( + origin_account == swap.source_account_at_this_chain, + Error::::MismatchedSwapSourceOrigin, + ); + + // we can't exchange less than existential deposit (the temporary `swap_account` account + // won't be created then) + // + // the same can also happen with the `swap.bridged_balance`, but we can't check it + // here (without additional knowledge of the Bridged chain). So it is the `origin` + // responsibility to check that the swap is valid. + ensure!( + swap.source_balance_at_this_chain >= T::ThisCurrency::minimum_balance(), + Error::::TooLowBalanceOnThisChain, + ); + + // if the swap is replay-protected, then we need to ensure that we have not yet passed the + // specified block yet + match swap.swap_type { + TokenSwapType::TemporaryTargetAccountAtBridgedChain => (), + TokenSwapType::LockClaimUntilBlock(block_number, _) => ensure!( + block_number >= frame_system::Pallet::::block_number(), + Error::::SwapPeriodIsFinished, + ), + } + + let swap_account = swap_account_id::(&swap); + frame_support::storage::with_transaction(|| { + // funds are transferred from This account to the temporary Swap account + let message_delivery_and_dispatch_fee = T::MessageDeliveryAndDispatchFee::get(); + let transfer_result = T::ThisCurrency::transfer( + &swap.source_account_at_this_chain, + &swap_account, + // saturating_add is ok, or we have the chain where single holder owns all tokens + swap.source_balance_at_this_chain + .saturating_add(message_delivery_and_dispatch_fee), + // if we'll allow account to die, then he'll be unable to `cancel_claim` + // if something won't work + ExistenceRequirement::KeepAlive, + ); + if let Err(err) = transfer_result { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to transfer This chain tokens for the swap {:?} to Swap account ({:?}): {:?}", + swap, + swap_account, + err, + ); + + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::FailedToTransferToSwapAccount.into() + )); + } + + // the transfer message is sent over the bridge. The message is supposed to be a + // `Currency::transfer` call on the bridged chain, but no checks are made - it is + // the transaction submitter to ensure it is valid. + let send_message_result = T::MessagesBridge::send_message( + swap_account.clone(), + T::OutboundMessageLaneId::get(), + bp_message_dispatch::MessagePayload { + spec_version: bridged_chain_spec_version, + weight: bridged_currency_transfer_weight, + origin: bp_message_dispatch::CallOrigin::TargetAccount( + swap_account, + target_public_at_bridged_chain, + bridged_currency_transfer_signature, + ), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: bridged_currency_transfer, + }, + message_delivery_and_dispatch_fee, + ); + let transfer_message_nonce = match send_message_result { + Ok(transfer_message_nonce) => transfer_message_nonce, + Err(err) => { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to send token transfer message for swap {:?} to the Bridged chain: {:?}", + swap, + err, + ); + + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::FailedToSendTransferMessage.into(), + )); + } + }; + + // remember that we have started the swap + let swap_hash = swap.using_encoded(blake2_256).into(); + let insert_swap_result = PendingSwaps::::try_mutate(swap_hash, |maybe_state| { + if maybe_state.is_some() { + return Err(()); + } + + *maybe_state = Some(TokenSwapState::Started); + Ok(()) + }); + if insert_swap_result.is_err() { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to start token swap {:?}: the swap is already started", + swap, + ); + + return sp_runtime::TransactionOutcome::Rollback(Err(Error::::SwapAlreadyStarted.into())); + } + + // remember that we're waiting for the transfer message delivery confirmation + PendingMessages::::insert(transfer_message_nonce, swap_hash); + + // finally - emit the event + Self::deposit_event(Event::SwapStarted(swap_hash, transfer_message_nonce)); + + sp_runtime::TransactionOutcome::Commit(Ok(().into())) + }) + } + + /// Claim previously reserved `source_balance_at_this_chain` by `target_account_at_this_chain`. + /// + /// **WARNING**: the correct way to call this function is to call it over the messages bridge with + /// dispatch origin set to `pallet_bridge_dispatch::CallOrigin::SourceAccount(target_account_at_bridged_chain)`. + /// + /// This should be called only when successful transfer confirmation has been received. + #[pallet::weight(0)] + pub fn claim_swap(origin: OriginFor, swap: TokenSwapOf) -> DispatchResultWithPostInfo { + // ensure that the `origin` is controlled by the `swap.target_account_at_bridged_chain` + let origin_account = ensure_signed(origin)?; + let target_account_at_this_chain = target_account_at_this_chain::(&swap); + ensure!( + origin_account == target_account_at_this_chain, + Error::::InvalidClaimant, + ); + + // ensure that the swap is confirmed + let swap_hash = swap.using_encoded(blake2_256).into(); + let swap_state = PendingSwaps::::get(swap_hash); + match swap_state { + Some(TokenSwapState::Started) => fail!(Error::::SwapIsPending), + Some(TokenSwapState::Confirmed) => { + let is_claim_allowed = match swap.swap_type { + TokenSwapType::TemporaryTargetAccountAtBridgedChain => true, + TokenSwapType::LockClaimUntilBlock(block_number, _) => { + block_number < frame_system::Pallet::::block_number() + } + }; + + ensure!(is_claim_allowed, Error::::SwapIsTemporaryLocked); + } + Some(TokenSwapState::Failed) => fail!(Error::::SwapIsFailed), + None => fail!(Error::::SwapIsInactive), + } + + complete_claim::(swap, swap_hash, origin_account, Event::SwapClaimed(swap_hash)) + } + + /// Return previously reserved `source_balance_at_this_chain` back to the `source_account_at_this_chain`. + /// + /// This should be called only when transfer has failed at Bridged chain and we have received + /// notification about thate. + #[pallet::weight(0)] + pub fn cancel_swap(origin: OriginFor, swap: TokenSwapOf) -> DispatchResultWithPostInfo { + // ensure that the `origin` is the same account that is mentioned in the `swap` intention + let origin_account = ensure_signed(origin)?; + ensure!( + origin_account == swap.source_account_at_this_chain, + Error::::MismatchedSwapSourceOrigin, + ); + + // ensure that the swap has failed + let swap_hash = swap.using_encoded(blake2_256).into(); + let swap_state = PendingSwaps::::get(swap_hash); + match swap_state { + Some(TokenSwapState::Started) => fail!(Error::::SwapIsPending), + Some(TokenSwapState::Confirmed) => fail!(Error::::SwapIsConfirmed), + Some(TokenSwapState::Failed) => { + // we allow cancelling swap even before lock period is over - the `source_account_at_this_chain` + // has already paid for nothing and it is up to him to decide whether he want to try again + } + None => fail!(Error::::SwapIsInactive), + } + + complete_claim::(swap, swap_hash, origin_account, Event::SwapCancelled(swap_hash)) + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event, I: 'static = ()> { + /// Tokens swap has been started and message has been sent to the bridged message. + /// + /// The payload is the swap hash and the transfer message nonce. + SwapStarted(H256, MessageNonce), + /// Token swap has been claimed. + SwapClaimed(H256), + /// Token swap has been cancelled. + SwapCancelled(H256), + } + + #[pallet::error] + pub enum Error { + /// The account that has submitted the `start_claim` doesn't match the `TokenSwap::source_account_at_this_chain`. + MismatchedSwapSourceOrigin, + /// The swap balance in This chain tokens is below existential deposit and can't be made. + TooLowBalanceOnThisChain, + /// Transfer from This chain account to temporary Swap account has failed. + FailedToTransferToSwapAccount, + /// Transfer from the temporary Swap account to the derived account of Bridged account has failed. + FailedToTransferFromSwapAccount, + /// The message to transfer tokens on Target chain can't be sent. + FailedToSendTransferMessage, + /// The same swap is already started. + SwapAlreadyStarted, + /// Swap outcome is not yet received. + SwapIsPending, + /// Someone is trying to claim swap that has failed. + SwapIsFailed, + /// Claiming swap is not allowed. + /// + /// Now the only possible case when you may get this error, is when you're trying to claim swap with + /// `TokenSwapType::LockClaimUntilBlock` before lock period is over. + SwapIsTemporaryLocked, + /// Swap period is finished and you can not restart it. + /// + /// Now the only possible case when you may get this error, is when you're trying to start swap with + /// `TokenSwapType::LockClaimUntilBlock` after lock period is over. + SwapPeriodIsFinished, + /// Someone is trying to cancel swap that has been confirmed. + SwapIsConfirmed, + /// Someone is trying to claim/cancel swap that is either not started or already claimed/cancelled. + SwapIsInactive, + /// The swap claimant is invalid. + InvalidClaimant, + } + + /// Pending token swaps states. + #[pallet::storage] + pub type PendingSwaps, I: 'static = ()> = StorageMap<_, Identity, H256, TokenSwapState>; + + /// Pending transfer messages. + #[pallet::storage] + pub type PendingMessages, I: 'static = ()> = StorageMap<_, Identity, MessageNonce, H256>; + + impl, I: 'static> OnDeliveryConfirmed for Pallet { + fn on_messages_delivered(lane: &LaneId, delivered_messages: &DeliveredMessages) -> Weight { + // we're only interested in our lane messages + if *lane != T::OutboundMessageLaneId::get() { + return 0; + } + + // so now we're dealing with our lane messages. Ideally we'll have dedicated lane + // and every message from `delivered_messages` is actually our transfer message. + // But it may be some shared lane (which is not recommended). + let mut reads = 0; + let mut writes = 0; + for message_nonce in delivered_messages.begin..=delivered_messages.end { + reads += 1; + if let Some(swap_hash) = PendingMessages::::take(message_nonce) { + writes += 1; + PendingSwaps::::insert( + swap_hash, + if delivered_messages.message_dispatch_result(message_nonce) { + TokenSwapState::Confirmed + } else { + TokenSwapState::Failed + }, + ); + } + } + + ::DbWeight::get().reads_writes(reads, writes) + } + } + + /// Returns temporary account id used to lock funds during swap on This chain. + pub(crate) fn swap_account_id, I: 'static>(swap: &TokenSwapOf) -> T::AccountId { + T::FromSwapToThisAccountIdConverter::convert(swap.using_encoded(blake2_256).into()) + } + + /// Expected target account representation on This chain (aka `target_account_at_this_chain`). + pub(crate) fn target_account_at_this_chain, I: 'static>(swap: &TokenSwapOf) -> T::AccountId { + T::FromBridgedToThisAccountIdConverter::convert(bp_runtime::derive_account_id( + T::BridgeChainId::get(), + bp_runtime::SourceAccount::Account(swap.target_account_at_bridged_chain.clone()), + )) + } + + /// Complete claim with given outcome. + pub(crate) fn complete_claim, I: 'static>( + swap: TokenSwapOf, + swap_hash: H256, + destination_account: T::AccountId, + event: Event, + ) -> DispatchResultWithPostInfo { + let swap_account = swap_account_id::(&swap); + frame_support::storage::with_transaction(|| { + // funds are transferred from the temporary Swap account to the destination account + let transfer_result = T::ThisCurrency::transfer( + &swap_account, + &destination_account, + swap.source_balance_at_this_chain, + ExistenceRequirement::AllowDeath, + ); + if let Err(err) = transfer_result { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to transfer This chain tokens for the swap {:?} from the Swap account {:?} to {:?}: {:?}", + swap, + swap_account, + destination_account, + err, + ); + + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::FailedToTransferFromSwapAccount.into() + )); + } + + // forget about swap + PendingSwaps::::remove(swap_hash); + + // finally - emit the event + Pallet::::deposit_event(event); + + sp_runtime::TransactionOutcome::Commit(Ok(().into())) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use frame_support::{assert_noop, assert_ok}; + + const CAN_START_BLOCK_NUMBER: u64 = 10; + const CAN_CLAIM_BLOCK_NUMBER: u64 = CAN_START_BLOCK_NUMBER + 1; + + const BRIDGED_CHAIN_ACCOUNT_PUBLIC: BridgedAccountPublic = 1; + const BRIDGED_CHAIN_ACCOUNT_SIGNATURE: BridgedAccountSignature = 2; + const BRIDGED_CHAIN_ACCOUNT: BridgedAccountId = 3; + const BRIDGED_CHAIN_SPEC_VERSION: u32 = 4; + const BRIDGED_CHAIN_CALL_WEIGHT: Balance = 5; + + fn test_swap() -> TokenSwapOf { + bp_token_swap::TokenSwap { + swap_type: TokenSwapType::LockClaimUntilBlock(CAN_START_BLOCK_NUMBER, 0.into()), + source_balance_at_this_chain: 100, + source_account_at_this_chain: THIS_CHAIN_ACCOUNT, + target_balance_at_bridged_chain: 200, + target_account_at_bridged_chain: BRIDGED_CHAIN_ACCOUNT, + } + } + + fn test_swap_hash() -> H256 { + test_swap().using_encoded(blake2_256).into() + } + + fn test_transfer() -> RawBridgedTransferCall { + vec![OK_TRANSFER_CALL] + } + + fn start_test_swap() { + assert_ok!(Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + )); + } + + fn receive_test_swap_confirmation(success: bool) { + Pallet::::on_messages_delivered( + &OutboundMessageLaneId::get(), + &DeliveredMessages::new(MESSAGE_NONCE, success), + ); + } + + #[test] + fn create_swap_fails_if_origin_is_incorrect() { + run_test(|| { + assert_noop!( + Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT + 1), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + ), + Error::::MismatchedSwapSourceOrigin + ); + }); + } + + #[test] + fn create_swap_fails_if_this_chain_balance_is_below_existential_deposit() { + run_test(|| { + let mut swap = test_swap(); + swap.source_balance_at_this_chain = ExistentialDeposit::get() - 1; + assert_noop!( + Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + swap, + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + ), + Error::::TooLowBalanceOnThisChain + ); + }); + } + + #[test] + fn create_swap_fails_if_currency_transfer_to_swap_account_fails() { + run_test(|| { + let mut swap = test_swap(); + swap.source_balance_at_this_chain = THIS_CHAIN_ACCOUNT_BALANCE + 1; + assert_noop!( + Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + swap, + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + ), + Error::::FailedToTransferToSwapAccount + ); + }); + } + + #[test] + fn create_swap_fails_if_send_message_fails() { + run_test(|| { + let mut transfer = test_transfer(); + transfer[0] = BAD_TRANSFER_CALL; + assert_noop!( + Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + transfer, + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + ), + Error::::FailedToSendTransferMessage + ); + }); + } + + #[test] + fn create_swap_fails_if_swap_is_active() { + run_test(|| { + assert_ok!(Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + )); + + assert_noop!( + Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + ), + Error::::SwapAlreadyStarted + ); + }); + } + + #[test] + fn create_swap_fails_if_trying_to_start_swap_after_lock_period_is_finished() { + run_test(|| { + frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER + 1); + assert_noop!( + Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + ), + Error::::SwapPeriodIsFinished + ); + }); + } + + #[test] + fn create_swap_succeeds_if_trying_to_start_swap_at_lock_period_end() { + run_test(|| { + frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER); + assert_ok!(Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + )); + }); + } + + #[test] + fn create_swap_succeeds() { + run_test(|| { + frame_system::Pallet::::set_block_number(1); + frame_system::Pallet::::reset_events(); + + assert_ok!(Pallet::::create_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap(), + BRIDGED_CHAIN_ACCOUNT_PUBLIC, + BRIDGED_CHAIN_SPEC_VERSION, + test_transfer(), + BRIDGED_CHAIN_CALL_WEIGHT, + BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + )); + + let swap_hash = test_swap_hash(); + assert_eq!( + PendingSwaps::::get(swap_hash), + Some(TokenSwapState::Started) + ); + assert_eq!(PendingMessages::::get(MESSAGE_NONCE), Some(swap_hash)); + assert_eq!( + pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), + test_swap().source_balance_at_this_chain + MessageDeliveryAndDispatchFee::get(), + ); + assert!( + frame_system::Pallet::::events() + .iter() + .any(|e| e.event + == crate::mock::Event::TokenSwap(crate::Event::SwapStarted(swap_hash, MESSAGE_NONCE,))), + "Missing SwapStarted event: {:?}", + frame_system::Pallet::::events(), + ); + }); + } + + #[test] + fn claim_swap_fails_if_origin_is_incorrect() { + run_test(|| { + assert_noop!( + Pallet::::claim_swap( + Origin::signed(1 + target_account_at_this_chain::(&test_swap())), + test_swap(), + ), + Error::::InvalidClaimant + ); + }); + } + + #[test] + fn claim_swap_fails_if_swap_is_pending() { + run_test(|| { + PendingSwaps::::insert(test_swap_hash(), TokenSwapState::Started); + + assert_noop!( + Pallet::::claim_swap( + Origin::signed(target_account_at_this_chain::(&test_swap())), + test_swap(), + ), + Error::::SwapIsPending + ); + }); + } + + #[test] + fn claim_swap_fails_if_swap_is_failed() { + run_test(|| { + PendingSwaps::::insert(test_swap_hash(), TokenSwapState::Failed); + + assert_noop!( + Pallet::::claim_swap( + Origin::signed(target_account_at_this_chain::(&test_swap())), + test_swap(), + ), + Error::::SwapIsFailed + ); + }); + } + + #[test] + fn claim_swap_fails_if_swap_is_inactive() { + run_test(|| { + assert_noop!( + Pallet::::claim_swap( + Origin::signed(target_account_at_this_chain::(&test_swap())), + test_swap(), + ), + Error::::SwapIsInactive + ); + }); + } + + #[test] + fn claim_swap_fails_if_currency_transfer_from_swap_account_fails() { + run_test(|| { + frame_system::Pallet::::set_block_number(CAN_CLAIM_BLOCK_NUMBER); + PendingSwaps::::insert(test_swap_hash(), TokenSwapState::Confirmed); + + assert_noop!( + Pallet::::claim_swap( + Origin::signed(target_account_at_this_chain::(&test_swap())), + test_swap(), + ), + Error::::FailedToTransferFromSwapAccount + ); + }); + } + + #[test] + fn claim_swap_fails_before_lock_period_is_completed() { + run_test(|| { + start_test_swap(); + receive_test_swap_confirmation(true); + + frame_system::Pallet::::set_block_number(CAN_CLAIM_BLOCK_NUMBER - 1); + + assert_noop!( + Pallet::::claim_swap( + Origin::signed(target_account_at_this_chain::(&test_swap())), + test_swap(), + ), + Error::::SwapIsTemporaryLocked + ); + }); + } + + #[test] + fn claim_swap_succeeds() { + run_test(|| { + start_test_swap(); + receive_test_swap_confirmation(true); + + frame_system::Pallet::::set_block_number(CAN_CLAIM_BLOCK_NUMBER); + frame_system::Pallet::::reset_events(); + + assert_ok!(Pallet::::claim_swap( + Origin::signed(target_account_at_this_chain::(&test_swap())), + test_swap(), + )); + + let swap_hash = test_swap_hash(); + assert_eq!(PendingSwaps::::get(swap_hash), None); + assert_eq!( + pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), + 0, + ); + assert_eq!( + pallet_balances::Pallet::::free_balance(&target_account_at_this_chain::( + &test_swap() + ),), + test_swap().source_balance_at_this_chain, + ); + assert!( + frame_system::Pallet::::events() + .iter() + .any(|e| e.event == crate::mock::Event::TokenSwap(crate::Event::SwapClaimed(swap_hash,))), + "Missing SwapClaimed event: {:?}", + frame_system::Pallet::::events(), + ); + }); + } + + #[test] + fn cancel_swap_fails_if_origin_is_incorrect() { + run_test(|| { + start_test_swap(); + receive_test_swap_confirmation(false); + + assert_noop!( + Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap()), + Error::::MismatchedSwapSourceOrigin + ); + }); + } + + #[test] + fn cancel_swap_fails_if_swap_is_pending() { + run_test(|| { + start_test_swap(); + + assert_noop!( + Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Error::::SwapIsPending + ); + }); + } + + #[test] + fn cancel_swap_fails_if_swap_is_confirmed() { + run_test(|| { + start_test_swap(); + receive_test_swap_confirmation(true); + + assert_noop!( + Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Error::::SwapIsConfirmed + ); + }); + } + + #[test] + fn cancel_swap_fails_if_swap_is_inactive() { + run_test(|| { + assert_noop!( + Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Error::::SwapIsInactive + ); + }); + } + + #[test] + fn cancel_swap_fails_if_currency_transfer_from_swap_account_fails() { + run_test(|| { + start_test_swap(); + receive_test_swap_confirmation(false); + let _ = pallet_balances::Pallet::::slash( + &swap_account_id::(&test_swap()), + test_swap().source_balance_at_this_chain, + ); + + assert_noop!( + Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Error::::FailedToTransferFromSwapAccount + ); + }); + } + + #[test] + fn cancel_swap_succeeds() { + run_test(|| { + start_test_swap(); + receive_test_swap_confirmation(false); + + frame_system::Pallet::::set_block_number(1); + frame_system::Pallet::::reset_events(); + + assert_ok!(Pallet::::cancel_swap( + Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + )); + + let swap_hash = test_swap_hash(); + assert_eq!(PendingSwaps::::get(swap_hash), None); + assert_eq!( + pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), + 0, + ); + assert_eq!( + pallet_balances::Pallet::::free_balance(&THIS_CHAIN_ACCOUNT), + THIS_CHAIN_ACCOUNT_BALANCE - MessageDeliveryAndDispatchFee::get(), + ); + assert!( + frame_system::Pallet::::events() + .iter() + .any(|e| e.event == crate::mock::Event::TokenSwap(crate::Event::SwapCancelled(swap_hash,))), + "Missing SwapCancelled event: {:?}", + frame_system::Pallet::::events(), + ); + }); + } + + #[test] + fn messages_delivery_confirmations_are_accepted() { + run_test(|| { + start_test_swap(); + assert_eq!( + PendingMessages::::get(MESSAGE_NONCE), + Some(test_swap_hash()) + ); + assert_eq!( + PendingSwaps::::get(test_swap_hash()), + Some(TokenSwapState::Started) + ); + + // when unrelated messages are delivered + let mut messages = DeliveredMessages::new(MESSAGE_NONCE - 2, true); + messages.note_dispatched_message(false); + Pallet::::on_messages_delivered(&OutboundMessageLaneId::get(), &messages); + assert_eq!( + PendingMessages::::get(MESSAGE_NONCE), + Some(test_swap_hash()) + ); + assert_eq!( + PendingSwaps::::get(test_swap_hash()), + Some(TokenSwapState::Started) + ); + + // when message we're interested in is accompanied by a bunch of other messages + let mut messages = DeliveredMessages::new(MESSAGE_NONCE - 1, false); + messages.note_dispatched_message(true); + messages.note_dispatched_message(false); + Pallet::::on_messages_delivered(&OutboundMessageLaneId::get(), &messages); + assert_eq!(PendingMessages::::get(MESSAGE_NONCE), None); + assert_eq!( + PendingSwaps::::get(test_swap_hash()), + Some(TokenSwapState::Confirmed) + ); + }); + } +} diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs new file mode 100644 index 0000000000000..c91933cce419b --- /dev/null +++ b/modules/token-swap/src/mock.rs @@ -0,0 +1,174 @@ +// 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 . + +use crate as pallet_bridge_token_swap; +use crate::MessagePayloadOf; + +use bp_messages::{source_chain::MessagesBridge, LaneId, MessageNonce}; +use bp_runtime::ChainId; +use frame_support::weights::Weight; +use sp_core::H256; +use sp_runtime::{ + testing::Header as SubstrateHeader, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, +}; + +pub type AccountId = u64; +pub type Balance = u64; +pub type Block = frame_system::mocking::MockBlock; +pub type BridgedAccountId = u64; +pub type BridgedAccountPublic = u64; +pub type BridgedAccountSignature = u64; +pub type BridgedBalance = u64; +pub type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + +pub const OK_TRANSFER_CALL: u8 = 1; +pub const BAD_TRANSFER_CALL: u8 = 2; +pub const MESSAGE_NONCE: MessageNonce = 3; + +pub const THIS_CHAIN_ACCOUNT: AccountId = 1; +pub const THIS_CHAIN_ACCOUNT_BALANCE: Balance = 100_000; + +frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Event}, + TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event}, + } +} + +frame_support::parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Config for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = Call; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = SubstrateHeader; + type Event = Event; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type SS58Prefix = (); + type OnSetCode = (); +} + +frame_support::parameter_types! { + pub const ExistentialDeposit: u64 = 10; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for TestRuntime { + type MaxLocks = (); + type Balance = Balance; + type DustRemoval = (); + type Event = Event; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = frame_system::Pallet; + type WeightInfo = (); + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +frame_support::parameter_types! { + pub const BridgeChainId: ChainId = *b"inst"; + pub const OutboundMessageLaneId: LaneId = *b"lane"; + pub const MessageDeliveryAndDispatchFee: Balance = 1; +} + +impl pallet_bridge_token_swap::Config for TestRuntime { + type Event = Event; + + type BridgeChainId = BridgeChainId; + type OutboundMessageLaneId = OutboundMessageLaneId; + type MessagesBridge = TestMessagesBridge; + type MessageDeliveryAndDispatchFee = MessageDeliveryAndDispatchFee; + + type ThisCurrency = pallet_balances::Pallet; + type FromSwapToThisAccountIdConverter = TestAccountConverter; + + type BridgedBalance = BridgedBalance; + type BridgedAccountId = BridgedAccountId; + type BridgedAccountPublic = BridgedAccountPublic; + type BridgedAccountSignature = BridgedAccountSignature; + type FromBridgedToThisAccountIdConverter = TestAccountConverter; +} + +pub struct TestMessagesBridge; + +impl MessagesBridge> for TestMessagesBridge { + type Error = (); + + fn send_message( + sender: AccountId, + lane: LaneId, + message: MessagePayloadOf, + delivery_and_dispatch_fee: Balance, + ) -> Result { + assert_ne!(sender, THIS_CHAIN_ACCOUNT); + assert_eq!(lane, OutboundMessageLaneId::get()); + assert_eq!(delivery_and_dispatch_fee, MessageDeliveryAndDispatchFee::get()); + match message.call[0] { + OK_TRANSFER_CALL => Ok(MESSAGE_NONCE), + BAD_TRANSFER_CALL => Err(()), + _ => unreachable!(), + } + } +} + +pub struct TestAccountConverter; + +impl sp_runtime::traits::Convert for TestAccountConverter { + fn convert(hash: H256) -> AccountId { + hash.to_low_u64_ne() + } +} + +/// Run pallet test. +pub fn run_test(test: impl FnOnce() -> T) -> T { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![(THIS_CHAIN_ACCOUNT, THIS_CHAIN_ACCOUNT_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(test) +} diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index a1ec0f19b4ffe..d4fd3d9b27f29 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -135,6 +135,22 @@ pub trait MessageDeliveryAndDispatchPayment { } } +/// Messages bridge API to be used from other pallets. +pub trait MessagesBridge { + /// Error type. + type Error: Debug; + + /// Send message over the bridge. + /// + /// Returns unique message nonce or error if send has failed. + fn send_message( + sender: AccountId, + lane: LaneId, + message: Payload, + delivery_and_dispatch_fee: Balance, + ) -> Result; +} + /// Handler for messages delivery confirmation. pub trait OnDeliveryConfirmed { /// Called when we receive confirmation that our messages have been delivered to the diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml new file mode 100644 index 0000000000000..4245a5363fd90 --- /dev/null +++ b/primitives/token-swap/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "bp-token-swap" +description = "Primitives of the pallet-bridge-token-swap pallet" +version = "0.1.0" +authors = ["Parity Technologies "] +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 } + +# 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 } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "sp-core/std", +] diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs new file mode 100644 index 0000000000000..e5575e73b0ed4 --- /dev/null +++ b/primitives/token-swap/src/lib.rs @@ -0,0 +1,64 @@ +// 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 . + +use codec::{Decode, Encode}; +use frame_support::RuntimeDebug; +use sp_core::U256; + +/// Token swap type. +/// +/// Different swap types give a different guarantees regarding possible swap +/// replay protection. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub enum TokenSwapType { + /// The `target_account_at_bridged_chain` is temporary and only have funds for single swap. + /// + /// ***WARNING**: if `target_account_at_bridged_chain` still exists after the swap has been + /// completed (either by claiming or cancelling), the `source_account_at_this_chain` will be able + /// to restart the swap again and repeat the swap until `target_account_at_bridged_chain` depletes. + TemporaryTargetAccountAtBridgedChain, + /// This swap type prevents `source_account_at_this_chain` from restarting the swap after it has + /// been completed. There are two consequences: + /// + /// 1) the `source_account_at_this_chain` won't be able to call `start_swap` after given ; + /// 2) the `target_account_at_bridged_chain` won't be able to call `claim_swap` (over the bridge) before + /// block ``. + /// + /// The second element is the nonce of the swap. You must care about its uniqueness if you're + /// planning to perform another swap with exactly the same parameters (i.e. same amount, same accounts, + /// same `ThisBlockNumber`) to avoid collisions. + LockClaimUntilBlock(ThisBlockNumber, U256), +} + +/// An intention to swap `source_balance_at_this_chain` owned by `source_account_at_this_chain` +/// to `target_balance_at_bridged_chain` owned by `target_account_at_bridged_chain`. +/// +/// **IMPORTANT NOTE**: this structure is always the same during single token swap. So even +/// when chain changes, the meaning of This and Bridged are still used to point to the same chains. +/// This chain is always the chain where swap has been started. And the Bridged chain is the other chain. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct TokenSwap { + /// The type of the swap. + pub swap_type: TokenSwapType, + /// This chain balance to be swapped with `target_balance_at_bridged_chain`. + pub source_balance_at_this_chain: ThisBalance, + /// Account id of the party acting at This chain and owning the `source_account_at_this_chain`. + pub source_account_at_this_chain: ThisAccountId, + /// Bridged chain balance to be swapped with `source_balance_at_this_chain`. + pub target_balance_at_bridged_chain: BridgedBalance, + /// Account id of the party acting at the Bridged chain and owning the `target_balance_at_bridged_chain`. + pub target_account_at_bridged_chain: BridgedAccountId, +} From 38eb160d4c655968dedf9a60a87e866880224e28 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 2 Aug 2021 15:53:19 +0300 Subject: [PATCH 0527/1210] fix typo (#1080) --- modules/token-swap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index a1306c2505595..4694781f09372 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -362,7 +362,7 @@ pub mod pallet { /// Return previously reserved `source_balance_at_this_chain` back to the `source_account_at_this_chain`. /// /// This should be called only when transfer has failed at Bridged chain and we have received - /// notification about thate. + /// notification about that. #[pallet::weight(0)] pub fn cancel_swap(origin: OriginFor, swap: TokenSwapOf) -> DispatchResultWithPostInfo { // ensure that the `origin` is the same account that is mentioned in the `swap` intention From 8782dc577a1c01a5df6e3315772d54af83130fe0 Mon Sep 17 00:00:00 2001 From: Hernando Castano Date: Thu, 5 Aug 2021 15:37:39 -0400 Subject: [PATCH 0528/1210] Make CI happy again (#1086) * Appease `cargo-spellcheck` * Increase logging for `cargo-spellcheck` * Fix config file name --- bin/millau/node/src/cli.rs | 2 +- bin/rialto/node/src/cli.rs | 2 +- modules/ethereum/src/lib.rs | 2 +- modules/grandpa/src/lib.rs | 2 +- modules/token-swap/src/lib.rs | 2 +- relays/bin-ethereum/src/rpc_errors.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 49f4fc092fac0..086def633c598 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -32,7 +32,7 @@ pub enum Subcommand { /// Key management CLI utilities Key(sc_cli::KeySubcommand), - /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. + /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. Verify(sc_cli::VerifyCmd), /// Generate a seed that provides a vanity address. diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 49f4fc092fac0..086def633c598 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -32,7 +32,7 @@ pub enum Subcommand { /// Key management CLI utilities Key(sc_cli::KeySubcommand), - /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key. + /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. Verify(sc_cli::VerifyCmd), /// Generate a seed that provides a vanity address. diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ebb36edbe54d6..6c9f9d23c0ff6 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -111,7 +111,7 @@ pub struct StoredHeader { pub struct ValidatorsSet { /// Validators of this set. pub validators: Vec

, - /// Hash of the block where this set has been signalled. None if this is the first set. + /// Hash of the block where this set has been signaled. None if this is the first set. pub signal_block: Option, /// Hash of the block where this set has been enacted. pub enact_block: HeaderId, diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 6c25968630e27..96a58aa8a5b22 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -567,7 +567,7 @@ pub(crate) fn find_scheduled_change(header: &H) -> Option( header: &H, diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 4694781f09372..dde25d8cb2b09 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -379,7 +379,7 @@ pub mod pallet { Some(TokenSwapState::Started) => fail!(Error::::SwapIsPending), Some(TokenSwapState::Confirmed) => fail!(Error::::SwapIsConfirmed), Some(TokenSwapState::Failed) => { - // we allow cancelling swap even before lock period is over - the `source_account_at_this_chain` + // we allow canceling swap even before lock period is over - the `source_account_at_this_chain` // has already paid for nothing and it is up to him to decide whether he want to try again } None => fail!(Error::::SwapIsInactive), diff --git a/relays/bin-ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs index 27b233135f325..06307bcf39c2b 100644 --- a/relays/bin-ethereum/src/rpc_errors.rs +++ b/relays/bin-ethereum/src/rpc_errors.rs @@ -25,7 +25,7 @@ use relay_utils::MaybeConnectionError; pub enum RpcError { /// The arguments to the RPC method failed to serialize. Serialization(serde_json::Error), - /// An error occured when interacting with an Ethereum node. + /// An error occurred when interacting with an Ethereum node. Ethereum(EthereumNodeError), /// An error occured when interacting with a Substrate node. Substrate(SubstrateNodeError), From d4cdf767a0f646a787945001573a1a9d61ff4960 Mon Sep 17 00:00:00 2001 From: Hector Bulgarini Date: Fri, 6 Aug 2021 10:23:09 -0300 Subject: [PATCH 0529/1210] Change ChainSpec::from_genesis for Rialto and Millau chains to reflect the chain names. (#1079) * Changing chain_spec of Rialto and Millau chains to retrieve their respective name * Adding development as well * Addressing PR feedback Co-authored-by: Svyatoslav Nikolsky --- bin/millau/node/src/chain_spec.rs | 8 ++++---- bin/rialto/node/src/chain_spec.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 2c50897b965ed..5c11f07df2033 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -81,8 +81,8 @@ impl Alternative { ); match self { Alternative::Development => ChainSpec::from_genesis( - "Development", - "dev", + "Millau Development", + "millau_dev", sc_service::ChainType::Development, || { testnet_genesis( @@ -107,8 +107,8 @@ impl Alternative { None, ), Alternative::LocalTestnet => ChainSpec::from_genesis( - "Local Testnet", - "local_testnet", + "Millau Local", + "millau_local", sc_service::ChainType::Local, || { testnet_genesis( diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 31cd533c3131d..a0d9a89ce150a 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -82,8 +82,8 @@ impl Alternative { ); match self { Alternative::Development => ChainSpec::from_genesis( - "Development", - "dev", + "Rialto Development", + "rialto_dev", sc_service::ChainType::Development, || { testnet_genesis( @@ -108,8 +108,8 @@ impl Alternative { None, ), Alternative::LocalTestnet => ChainSpec::from_genesis( - "Local Testnet", - "local_testnet", + "Rialto Local", + "rialto_local", sc_service::ChainType::Local, || { testnet_genesis( From f0c7b90c707f61fe1747cc251f511f93af623520 Mon Sep 17 00:00:00 2001 From: Hector Bulgarini Date: Fri, 6 Aug 2021 10:24:08 -0300 Subject: [PATCH 0530/1210] Bridge/This Chain Ids should be exposed as constants on pallet level. (#1085) * Adding BridgedChainId constant to message pallet * Addressing PR feedback --- bin/millau/node/src/chain_spec.rs | 5 +---- bin/millau/runtime/src/lib.rs | 2 ++ bin/rialto/node/src/chain_spec.rs | 5 +---- bin/rialto/runtime/src/lib.rs | 2 ++ modules/messages/src/lib.rs | 8 +++++++- modules/messages/src/mock.rs | 2 ++ 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 5c11f07df2033..846dfa69302fd 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -70,10 +70,7 @@ impl Alternative { let properties = Some( serde_json::json!({ "tokenDecimals": 9, - "tokenSymbol": "MLAU", - "bridgeIds": { - "Rialto": bp_runtime::RIALTO_CHAIN_ID, - } + "tokenSymbol": "MLAU" }) .as_object() .expect("Map given; qed") diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8d9f5edcf1baa..cc004b8629703 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -362,6 +362,7 @@ parameter_types! { pub const GetDeliveryConfirmationTransactionFee: Balance = bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; + pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; } /// Instance of the messages pallet used to relay messages to/from Rialto chain. @@ -397,6 +398,7 @@ impl pallet_bridge_messages::Config for Runtime { type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; + type BridgedChainId = BridgedChainId; } construct_runtime!( diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index a0d9a89ce150a..99645e14cba4c 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -71,10 +71,7 @@ impl Alternative { let properties = Some( json!({ "tokenDecimals": 9, - "tokenSymbol": "RLT", - "bridgeIds": { - "Millau": bp_runtime::MILLAU_CHAIN_ID, - } + "tokenSymbol": "RLT" }) .as_object() .expect("Map given; qed") diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 3a40139d6d938..a1b36dd05945e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -490,6 +490,7 @@ parameter_types! { pub const GetDeliveryConfirmationTransactionFee: Balance = bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; + pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; } /// Instance of the messages pallet used to relay messages to/from Millau chain. @@ -524,6 +525,7 @@ impl pallet_bridge_messages::Config for Runtime { type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; + type BridgedChainId = BridgedChainId; } construct_runtime!( diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 842c28bd4b7d3..8f7a6c8b7121a 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -54,7 +54,7 @@ use bp_messages::{ total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, }; -use bp_runtime::Size; +use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; use frame_support::{ decl_error, decl_event, decl_module, decl_storage, @@ -161,6 +161,9 @@ pub trait Config: frame_system::Config { Self::InboundMessageFee, DispatchPayload = Self::InboundPayload, >; + + /// Chain Id for the bridged chain. + type BridgedChainId: Get; } /// Shortcut to messages proof type for Config. @@ -255,6 +258,9 @@ decl_module! { /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; + /// Gets the chain id value from the instance. + const BridgedChainId: ChainId = T::BridgedChainId::get(); + /// Ensure runtime invariants. fn on_runtime_upgrade() -> Weight { let reads = T::MessageDeliveryAndDispatchPayment::initialize( diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index f2a42ab55e49f..77a421b3411ae 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -142,6 +142,7 @@ parameter_types! { pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; pub storage TokenConversionRate: FixedU128 = 1.into(); + pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; } #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)] @@ -181,6 +182,7 @@ impl Config for TestRuntime { type SourceHeaderChain = TestSourceHeaderChain; type MessageDispatch = TestMessageDispatch; + type BridgedChainId = TestBridgedChainId; } impl Size for TestPayload { From be1a0eeceba0445c870888a5ebf706987c1636c2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 11 Aug 2021 11:32:09 +0300 Subject: [PATCH 0531/1210] Migrate dispatch pallet to frame v2 (#1089) * pallet-bridge-dispatch -> frame v2 * fix metadata --- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/src/messages.rs | 5 +- modules/dispatch/src/lib.rs | 177 ++++++++++++---------- 4 files changed, 96 insertions(+), 90 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 2ebf17686f91e..5b3d08688c826 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -69,7 +69,7 @@ pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDi WithRialtoMessageBridge, crate::Runtime, pallet_balances::Pallet, - pallet_bridge_dispatch::DefaultInstance, + (), >; /// Millau <-> Rialto message bridge. diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 15e1d52f25525..ac79d8eca6b68 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -63,7 +63,7 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi WithMillauMessageBridge, crate::Runtime, pallet_balances::Pallet, - pallet_bridge_dispatch::DefaultInstance, + (), >; /// Messages proof for Millau -> Rialto messages. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 08ef582993e6b..974920c528cce 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -492,15 +492,12 @@ pub mod target { for FromBridgedChainMessageDispatch where BalanceOf>: Saturating + FixedPointOperand, - ThisDispatchInstance: frame_support::traits::Instance, + ThisDispatchInstance: 'static, ThisRuntime: pallet_bridge_dispatch::Config + pallet_transaction_payment::Config, ::OnChargeTransaction: pallet_transaction_payment::OnChargeTransaction>>, ThisCurrency: Currency>, Balance = BalanceOf>>, - >::Event: From< - pallet_bridge_dispatch::RawEvent<(LaneId, MessageNonce), AccountIdOf>, ThisDispatchInstance>, - >, pallet_bridge_dispatch::Pallet: bp_message_dispatch::MessageDispatch< AccountIdOf>, (LaneId, MessageNonce), diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index b27295481a2c7..c68f064e9d12e 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -26,116 +26,124 @@ // Generated by `decl_event!` #![allow(clippy::unused_unit)] -use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion, Weight}; +use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion}; use bp_runtime::{ derive_account_id, messages::{DispatchFeePayment, MessageDispatchResult}, ChainId, SourceAccount, }; -use codec::{Decode, Encode}; +use codec::Encode; use frame_support::{ - decl_event, decl_module, decl_storage, - dispatch::{Dispatchable, Parameter}, + dispatch::Dispatchable, ensure, traits::{Filter, Get}, weights::{extract_actual_weight, GetDispatchInfo}, }; use frame_system::RawOrigin; -use sp_runtime::{ - traits::{BadOrigin, Convert, IdentifyAccount, MaybeDisplay, MaybeSerializeDeserialize, Member, Verify}, - DispatchResult, -}; -use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; - -/// The module configuration trait. -pub trait Config: frame_system::Config { - /// The overarching event type. - type Event: From> + Into<::Event>; - /// Id of the message. Whenever message is passed to the dispatch module, it emits - /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if - /// it comes from the messages module. - type MessageId: Parameter; - /// Type of account ID on source chain. - type SourceChainAccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; - /// Type of account public key on target chain. - type TargetChainAccountPublic: Parameter + IdentifyAccount; - /// Type of signature that may prove that the message has been signed by - /// owner of `TargetChainAccountPublic`. - type TargetChainSignature: Parameter + Verify; - /// The overarching dispatch call type. - type Call: Parameter - + GetDispatchInfo - + Dispatchable< - Origin = ::Origin, - PostInfo = frame_support::dispatch::PostDispatchInfo, - >; - /// Pre-dispatch filter for incoming calls. - /// - /// The pallet will filter all incoming calls right before they're dispatched. If this filter - /// rejects the call, special event (`Event::MessageCallRejected`) is emitted. - type CallFilter: Filter<>::Call>; - /// The type that is used to wrap the `Self::Call` when it is moved over bridge. - /// - /// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure - /// that all other stuff (like `spec_version`) is ok. If we would try to decode - /// `Call` which has been encoded using previous `spec_version`, then we might end - /// up with decoding error, instead of `MessageVersionSpecMismatch`. - type EncodedCall: Decode + Encode + Into>::Call, ()>>; - /// A type which can be turned into an AccountId from a 256-bit hash. - /// - /// Used when deriving target chain AccountIds from source chain AccountIds. - type AccountIdConverter: sp_runtime::traits::Convert; -} +use sp_runtime::traits::{BadOrigin, Convert, IdentifyAccount, MaybeDisplay, Verify}; +use sp_std::{fmt::Debug, prelude::*}; -decl_storage! { - trait Store for Pallet, I: Instance = DefaultInstance> as Dispatch {} -} +pub use pallet::*; -decl_event!( - pub enum Event where - >::MessageId, - AccountId = ::AccountId, - { +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type Event: From> + IsType<::Event>; + /// Id of the message. Whenever message is passed to the dispatch module, it emits + /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if + /// it comes from the messages module. + type MessageId: Parameter; + /// Type of account ID on source chain. + type SourceChainAccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; + /// Type of account public key on target chain. + type TargetChainAccountPublic: Parameter + IdentifyAccount; + /// Type of signature that may prove that the message has been signed by + /// owner of `TargetChainAccountPublic`. + type TargetChainSignature: Parameter + Verify; + /// The overarching dispatch call type. + type Call: Parameter + + GetDispatchInfo + + Dispatchable< + Origin = ::Origin, + PostInfo = frame_support::dispatch::PostDispatchInfo, + >; + /// Pre-dispatch filter for incoming calls. + /// + /// The pallet will filter all incoming calls right before they're dispatched. If this filter + /// rejects the call, special event (`Event::MessageCallRejected`) is emitted. + type CallFilter: Filter<>::Call>; + /// The type that is used to wrap the `Self::Call` when it is moved over bridge. + /// + /// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure + /// that all other stuff (like `spec_version`) is ok. If we would try to decode + /// `Call` which has been encoded using previous `spec_version`, then we might end + /// up with decoding error, instead of `MessageVersionSpecMismatch`. + type EncodedCall: Decode + Encode + Into>::Call, ()>>; + /// A type which can be turned into an AccountId from a 256-bit hash. + /// + /// Used when deriving target chain AccountIds from source chain AccountIds. + type AccountIdConverter: sp_runtime::traits::Convert; + } + + type MessageIdOf = >::MessageId; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet {} + + #[pallet::call] + impl, I: 'static> Pallet {} + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + #[pallet::metadata(::AccountId = "AccountId", MessageIdOf = "MessageId")] + pub enum Event, I: 'static = ()> { /// Message has been rejected before reaching dispatch. - MessageRejected(ChainId, MessageId), + MessageRejected(ChainId, MessageIdOf), /// Message has been rejected by dispatcher because of spec version mismatch. /// Last two arguments are: expected and passed spec version. - MessageVersionSpecMismatch(ChainId, MessageId, SpecVersion, SpecVersion), + MessageVersionSpecMismatch(ChainId, MessageIdOf, SpecVersion, SpecVersion), /// Message has been rejected by dispatcher because of weight mismatch. /// Last two arguments are: expected and passed call weight. - MessageWeightMismatch(ChainId, MessageId, Weight, Weight), + MessageWeightMismatch(ChainId, MessageIdOf, Weight, Weight), /// Message signature mismatch. - MessageSignatureMismatch(ChainId, MessageId), + MessageSignatureMismatch(ChainId, MessageIdOf), /// We have failed to decode Call from the message. - MessageCallDecodeFailed(ChainId, MessageId), + MessageCallDecodeFailed(ChainId, MessageIdOf), /// The call from the message has been rejected by the call filter. - MessageCallRejected(ChainId, MessageId), + MessageCallRejected(ChainId, MessageIdOf), /// The origin account has failed to pay fee for dispatching the message. - MessageDispatchPaymentFailed(ChainId, MessageId, AccountId, Weight), + MessageDispatchPaymentFailed( + ChainId, + MessageIdOf, + ::AccountId, + Weight, + ), /// Message has been dispatched with given result. - MessageDispatched(ChainId, MessageId, DispatchResult), + MessageDispatched(ChainId, MessageIdOf, DispatchResult), /// Phantom member, never used. Needed to handle multiple pallet instances. _Dummy(PhantomData), } -); - -decl_module! { - /// Call Dispatch FRAME Pallet. - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { - /// Deposit one of this module's events by using the default implementation. - fn deposit_event() = default; - } } -impl, I: Instance> MessageDispatch for Pallet { +impl, I: 'static> MessageDispatch for Pallet { type Message = MessagePayload; - fn dispatch_weight(message: &Self::Message) -> Weight { + fn dispatch_weight(message: &Self::Message) -> bp_message_dispatch::Weight { message.weight } - fn dispatch Result<(), ()>>( + fn dispatch Result<(), ()>>( source_chain: ChainId, target_chain: ChainId, id: T::MessageId, @@ -152,7 +160,7 @@ impl, I: Instance> MessageDispatch for source_chain, id, ); - Self::deposit_event(RawEvent::MessageRejected(source_chain, id)); + Self::deposit_event(Event::MessageRejected(source_chain, id)); return MessageDispatchResult { dispatch_result: false, unspent_weight: 0, @@ -177,7 +185,7 @@ impl, I: Instance> MessageDispatch for expected_version, message.spec_version, ); - Self::deposit_event(RawEvent::MessageVersionSpecMismatch( + Self::deposit_event(Event::MessageVersionSpecMismatch( source_chain, id, expected_version, @@ -196,7 +204,7 @@ impl, I: Instance> MessageDispatch for source_chain, id, ); - Self::deposit_event(RawEvent::MessageCallDecodeFailed(source_chain, id)); + Self::deposit_event(Event::MessageCallDecodeFailed(source_chain, id)); return dispatch_result; } }; @@ -228,7 +236,7 @@ impl, I: Instance> MessageDispatch for target_account, target_signature, ); - Self::deposit_event(RawEvent::MessageSignatureMismatch(source_chain, id)); + Self::deposit_event(Event::MessageSignatureMismatch(source_chain, id)); return dispatch_result; } @@ -252,7 +260,7 @@ impl, I: Instance> MessageDispatch for id, call, ); - Self::deposit_event(RawEvent::MessageCallRejected(source_chain, id)); + Self::deposit_event(Event::MessageCallRejected(source_chain, id)); return dispatch_result; } @@ -270,7 +278,7 @@ impl, I: Instance> MessageDispatch for expected_weight, message.weight, ); - Self::deposit_event(RawEvent::MessageWeightMismatch( + Self::deposit_event(Event::MessageWeightMismatch( source_chain, id, expected_weight, @@ -289,7 +297,7 @@ impl, I: Instance> MessageDispatch for id, message.weight, ); - Self::deposit_event(RawEvent::MessageDispatchPaymentFailed( + Self::deposit_event(Event::MessageDispatchPaymentFailed( source_chain, id, origin_account, @@ -319,7 +327,7 @@ impl, I: Instance> MessageDispatch for result, ); - Self::deposit_event(RawEvent::MessageDispatched( + Self::deposit_event(Event::MessageDispatched( source_chain, id, result.map(drop).map_err(|e| e.error), @@ -397,6 +405,7 @@ mod tests { #![allow(clippy::from_over_into)] use super::*; + use codec::Decode; use frame_support::{parameter_types, weights::Weight}; use frame_system::{EventRecord, Phase}; use sp_core::H256; From 0f1d4c1412a43b18ec30e149c59877a2a8af09a1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 Aug 2021 16:59:12 +0300 Subject: [PATCH 0532/1210] migrate eth PoA pallet to frame v2 (#1091) --- bin/rialto/runtime/src/exchange.rs | 2 +- bin/rialto/runtime/src/lib.rs | 1 + modules/ethereum/src/benchmarking.rs | 12 +- modules/ethereum/src/finality.rs | 1 - modules/ethereum/src/import.rs | 6 +- modules/ethereum/src/lib.rs | 415 +++++++++++++++------------ modules/ethereum/src/mock.rs | 9 +- modules/ethereum/src/test_utils.rs | 12 +- modules/ethereum/src/validators.rs | 4 +- modules/ethereum/src/verification.rs | 16 +- 10 files changed, 260 insertions(+), 218 deletions(-) diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index e259856f37559..cdb9d9db62e09 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -128,7 +128,7 @@ impl MaybeLockFundsTransaction for EthTransaction { /// Prepares everything required to bench claim of funds locked by given transaction. #[cfg(feature = "runtime-benchmarks")] -pub(crate) fn prepare_environment_for_claim, I: frame_support::traits::Instance>( +pub(crate) fn prepare_environment_for_claim, I: 'static>( transactions: &[(RawTransaction, RawTransactionReceipt)], ) -> bp_eth_poa::H256 { use bp_eth_poa::compute_merkle_root; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a1b36dd05945e..1a34061592ebc 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1102,6 +1102,7 @@ impl_runtime_apis! { } } + add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa); add_benchmark!( params, batches, diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 960dbe9afec24..98dbd04e2a829 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -22,10 +22,10 @@ use crate::test_utils::{ }; use bp_eth_poa::{compute_merkle_root, U256}; -use frame_benchmarking::benchmarks_instance; +use frame_benchmarking::benchmarks_instance_pallet; use frame_system::RawOrigin; -benchmarks_instance! { +benchmarks_instance_pallet! { // Benchmark `import_unsigned_header` extrinsic with the best possible conditions: // * Parent header is finalized. // * New header doesn't require receipts. @@ -153,7 +153,7 @@ benchmarks_instance! { let validators = validators(num_validators); // Want to prune eligible blocks between [0, n) - BlocksToPrune::::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: n as u64, }); @@ -172,8 +172,8 @@ benchmarks_instance! { let storage = BridgeStorage::::new(); let max_pruned: u64 = (n - 1) as _; assert_eq!(storage.best_block().0.number, (n + 1) as u64); - assert!(HeadersByNumber::::get(&0).is_none()); - assert!(HeadersByNumber::::get(&max_pruned).is_none()); + assert!(HeadersByNumber::::get(&0).is_none()); + assert!(HeadersByNumber::::get(&max_pruned).is_none()); } // The goal of this bench is to import a block which contains a transaction receipt. The receipt @@ -216,7 +216,7 @@ benchmarks_instance! { } } -fn initialize_bench, I: Instance>(num_validators: usize) -> AuraHeader { +fn initialize_bench, I: 'static>(num_validators: usize) -> AuraHeader { // Initialize storage with some initial header let initial_header = build_genesis_header(&validator(0)); let initial_difficulty = initial_header.difficulty; diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 25f1ecdb2c3df..934db0430ab8c 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -284,7 +284,6 @@ mod tests { use super::*; use crate::mock::{insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime}; use crate::{BridgeStorage, FinalityCache, HeaderToImport}; - use frame_support::StorageMap; const TOTAL_VALIDATORS: usize = 5; diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 89ee39f7b3c41..2668ebf9244c1 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -176,9 +176,7 @@ mod tests { validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; - use crate::DefaultInstance; use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; - use frame_support::{StorageMap, StorageValue}; use secp256k1::SecretKey; const TOTAL_VALIDATORS: usize = 3; @@ -367,7 +365,7 @@ mod tests { step += 3; } assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 11, oldest_block_to_keep: 14, @@ -394,7 +392,7 @@ mod tests { .unwrap(); assert_eq!(finalized_blocks, expected_blocks); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 15, oldest_block_to_keep: 15, diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 6c9f9d23c0ff6..ee55b236dd53c 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -21,14 +21,8 @@ use crate::finality::{CachedFinalityVotes, FinalityVotes}; use bp_eth_poa::{Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; use codec::{Decode, Encode}; -use frame_support::{decl_module, decl_storage, traits::Get}; -use sp_runtime::{ - transaction_validity::{ - InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionSource, TransactionValidity, - UnknownTransaction, ValidTransaction, - }, - RuntimeDebug, -}; +use frame_support::traits::Get; +use sp_runtime::RuntimeDebug; use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; pub use validators::{ValidatorsConfiguration, ValidatorsSource}; @@ -369,34 +363,53 @@ impl OnHeadersSubmitted for () { fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {} } -/// The module configuration trait. -pub trait Config: frame_system::Config { - /// Aura configuration. - type AuraConfiguration: Get; - /// Validators configuration. - type ValidatorsConfiguration: Get; +pub use pallet::*; - /// Interval (in blocks) for for finality votes caching. - /// If None, cache is disabled. - /// - /// Ideally, this should either be None (when we are sure that there won't - /// be any significant finalization delays), or something that is bit larger - /// than average finalization delay. - type FinalityVotesCachingInterval: Get>; - /// Headers pruning strategy. - type PruningStrategy: PruningStrategy; - /// Header timestamp verification against current on-chain time. - type ChainTime: ChainTime; - - /// Handler for headers submission result. - type OnHeadersSubmitted: OnHeadersSubmitted; -} +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// Aura configuration. + type AuraConfiguration: Get; + /// Validators configuration. + type ValidatorsConfiguration: Get; + + /// Interval (in blocks) for for finality votes caching. + /// If None, cache is disabled. + /// + /// Ideally, this should either be None (when we are sure that there won't + /// be any significant finalization delays), or something that is bit larger + /// than average finalization delay. + type FinalityVotesCachingInterval: Get>; + /// Headers pruning strategy. + type PruningStrategy: PruningStrategy; + /// Header timestamp verification against current on-chain time. + type ChainTime: ChainTime; + + /// Handler for headers submission result. + type OnHeadersSubmitted: OnHeadersSubmitted; + } -decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet {} + + #[pallet::call] + impl, I: 'static> Pallet { /// Import single Aura header. Requires transaction to be **UNSIGNED**. - #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_unsigned_header(origin, header: AuraHeader, receipts: Option>) { + #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + pub fn import_unsigned_header( + origin: OriginFor, + header: AuraHeader, + receipts: Option>, + ) -> DispatchResult { frame_system::ensure_none(origin)?; import::import_header( @@ -408,7 +421,10 @@ decl_module! { header, &T::ChainTime::default(), receipts, - ).map_err(|e| e.msg())?; + ) + .map_err(|e| e.msg())?; + + Ok(()) } /// Import Aura chain headers in a single **SIGNED** transaction. @@ -417,8 +433,11 @@ decl_module! { /// /// This should be used with caution - passing too many headers could lead to /// enormous block production/import time. - #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_signed_headers(origin, headers_with_receipts: Vec<(AuraHeader, Option>)>) { + #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + pub fn import_signed_headers( + origin: OriginFor, + headers_with_receipts: Vec<(AuraHeader, Option>)>, + ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; let mut finalized_headers = BTreeMap::new(); let import_result = import::import_headers( @@ -435,77 +454,147 @@ decl_module! { // if we have finalized some headers, we will reward their submitters even // if current submitter has provided some invalid headers for (f_submitter, f_count) in finalized_headers { - T::OnHeadersSubmitted::on_valid_headers_finalized( - f_submitter, - f_count, - ); + T::OnHeadersSubmitted::on_valid_headers_finalized(f_submitter, f_count); } // now track/penalize current submitter for providing new headers match import_result { - Ok((useful, useless)) => - T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), + Ok((useful, useless)) => T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), Err(error) => { // even though we may have accept some headers, we do not want to reward someone // who provides invalid headers T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter); return Err(error.msg().into()); - }, + } + } + + Ok(()) + } + } + + #[pallet::validate_unsigned] + impl, I: 'static> ValidateUnsigned for Pallet { + type Call = Call; + + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { + match *call { + Self::Call::import_unsigned_header(ref header, ref receipts) => { + let accept_result = verification::accept_aura_header_into_pool( + &BridgeStorage::::new(), + &T::AuraConfiguration::get(), + &T::ValidatorsConfiguration::get(), + &pool_configuration(), + header, + &T::ChainTime::default(), + receipts.as_ref(), + ); + + match accept_result { + Ok((requires, provides)) => Ok(ValidTransaction { + priority: TransactionPriority::max_value(), + requires, + provides, + longevity: TransactionLongevity::max_value(), + propagate: true, + }), + // UnsignedTooFarInTheFuture is the special error code used to limit + // number of transactions in the pool - we do not want to ban transaction + // in this case (see verification.rs for details) + Err(error::Error::UnsignedTooFarInTheFuture) => { + UnknownTransaction::Custom(error::Error::UnsignedTooFarInTheFuture.code()).into() + } + Err(error) => InvalidTransaction::Custom(error.code()).into(), + } + } + _ => InvalidTransaction::Call.into(), } } } -} -decl_storage! { - trait Store for Pallet, I: Instance = DefaultInstance> as Bridge { - /// Best known block. - BestBlock: (HeaderId, U256); - /// Best finalized block. - FinalizedBlock: HeaderId; - /// Range of blocks that we want to prune. - BlocksToPrune: PruningRange; - /// Map of imported headers by hash. - Headers: map hasher(identity) H256 => Option>; - /// Map of imported header hashes by number. - HeadersByNumber: map hasher(blake2_128_concat) u64 => Option>; - /// Map of cached finality data by header hash. - FinalityCache: map hasher(identity) H256 => Option>; - /// The ID of next validator set. - NextValidatorsSetId: u64; - /// Map of validators sets by their id. - ValidatorsSets: map hasher(twox_64_concat) u64 => Option; - /// Validators sets reference count. Each header that is authored by this set increases - /// the reference count. When we prune this header, we decrease the reference count. - /// When it reaches zero, we are free to prune validator set as well. - ValidatorsSetsRc: map hasher(twox_64_concat) u64 => Option; - /// Map of validators set changes scheduled by given header. - ScheduledChanges: map hasher(identity) H256 => Option; + /// Best known block. + #[pallet::storage] + pub(super) type BestBlock, I: 'static = ()> = StorageValue<_, (HeaderId, U256), ValueQuery>; + + /// Best finalized block. + #[pallet::storage] + pub(super) type FinalizedBlock, I: 'static = ()> = StorageValue<_, HeaderId, ValueQuery>; + + /// Range of blocks that we want to prune. + #[pallet::storage] + pub(super) type BlocksToPrune, I: 'static = ()> = StorageValue<_, PruningRange, ValueQuery>; + + /// Map of imported headers by hash. + #[pallet::storage] + pub(super) type Headers, I: 'static = ()> = StorageMap<_, Identity, H256, StoredHeader>; + + /// Map of imported header hashes by number. + #[pallet::storage] + pub(super) type HeadersByNumber, I: 'static = ()> = StorageMap<_, Blake2_128Concat, u64, Vec>; + + /// Map of cached finality data by header hash. + #[pallet::storage] + pub(super) type FinalityCache, I: 'static = ()> = + StorageMap<_, Identity, H256, FinalityVotes>; + + /// The ID of next validator set. + #[pallet::storage] + pub(super) type NextValidatorsSetId, I: 'static = ()> = StorageValue<_, u64, ValueQuery>; + + /// Map of validators sets by their id. + #[pallet::storage] + pub(super) type ValidatorsSets, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, ValidatorsSet>; + + /// Validators sets reference count. Each header that is authored by this set increases + /// the reference count. When we prune this header, we decrease the reference count. + /// When it reaches zero, we are free to prune validator set as well. + #[pallet::storage] + pub(super) type ValidatorsSetsRc, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, u64>; + + /// Map of validators set changes scheduled by given header. + #[pallet::storage] + pub(super) type ScheduledChanges, I: 'static = ()> = + StorageMap<_, Identity, H256, AuraScheduledChange>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + /// PoA header to start with. + pub initial_header: AuraHeader, + /// Initial PoA chain difficulty. + pub initial_difficulty: U256, + /// Initial PoA validators set. + pub initial_validators: Vec
, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + initial_header: Default::default(), + initial_difficulty: Default::default(), + initial_validators: Default::default(), + } + } } - add_extra_genesis { - config(initial_header): AuraHeader; - config(initial_difficulty): U256; - config(initial_validators): Vec
; - build(|config| { + + #[pallet::genesis_build] + impl, I: 'static> GenesisBuild for GenesisConfig { + fn build(&self) { // the initial blocks should be selected so that: // 1) it doesn't signal validators changes; // 2) there are no scheduled validators changes from previous blocks; // 3) (implied) all direct children of initial block are authored by the same validators set. assert!( - !config.initial_validators.is_empty(), + !self.initial_validators.is_empty(), "Initial validators set can't be empty", ); - initialize_storage::( - &config.initial_header, - config.initial_difficulty, - &config.initial_validators, - ); - }) + initialize_storage::(&self.initial_header, self.initial_difficulty, &self.initial_validators); + } } } -impl, I: Instance> Pallet { +impl, I: 'static> Pallet { /// Returns number and hash of the best block known to the bridge module. /// The caller should only submit `import_header` transaction that makes /// (or leads to making) other header the best one. @@ -542,49 +631,11 @@ impl, I: Instance> Pallet { } } -impl, I: Instance> frame_support::unsigned::ValidateUnsigned for Pallet { - type Call = Call; - - fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { - match *call { - Self::Call::import_unsigned_header(ref header, ref receipts) => { - let accept_result = verification::accept_aura_header_into_pool( - &BridgeStorage::::new(), - &T::AuraConfiguration::get(), - &T::ValidatorsConfiguration::get(), - &pool_configuration(), - header, - &T::ChainTime::default(), - receipts.as_ref(), - ); - - match accept_result { - Ok((requires, provides)) => Ok(ValidTransaction { - priority: TransactionPriority::max_value(), - requires, - provides, - longevity: TransactionLongevity::max_value(), - propagate: true, - }), - // UnsignedTooFarInTheFuture is the special error code used to limit - // number of transactions in the pool - we do not want to ban transaction - // in this case (see verification.rs for details) - Err(error::Error::UnsignedTooFarInTheFuture) => { - UnknownTransaction::Custom(error::Error::UnsignedTooFarInTheFuture.code()).into() - } - Err(error) => InvalidTransaction::Custom(error.code()).into(), - } - } - _ => InvalidTransaction::Call.into(), - } - } -} - /// Runtime bridge storage. #[derive(Default)] -pub struct BridgeStorage(sp_std::marker::PhantomData<(T, I)>); +pub struct BridgeStorage(sp_std::marker::PhantomData<(T, I)>); -impl, I: Instance> BridgeStorage { +impl, I: 'static> BridgeStorage { /// Create new BridgeStorage. pub fn new() -> Self { BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default()) @@ -592,7 +643,7 @@ impl, I: Instance> BridgeStorage { /// Prune old blocks. fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) { - let pruning_range = BlocksToPrune::::get(); + let pruning_range = BlocksToPrune::::get(); let mut new_pruning_range = pruning_range.clone(); // update oldest block we want to keep @@ -611,7 +662,7 @@ impl, I: Instance> BridgeStorage { } // read hashes of blocks with given number and try to prune these blocks - let blocks_at_number = HeadersByNumber::::take(number); + let blocks_at_number = HeadersByNumber::::take(number); if let Some(mut blocks_at_number) = blocks_at_number { self.prune_blocks_by_hashes( &mut max_blocks_to_prune, @@ -622,7 +673,7 @@ impl, I: Instance> BridgeStorage { // if we haven't pruned all blocks, remember unpruned if !blocks_at_number.is_empty() { - HeadersByNumber::::insert(number, blocks_at_number); + HeadersByNumber::::insert(number, blocks_at_number); break; } } @@ -638,7 +689,7 @@ impl, I: Instance> BridgeStorage { // update pruning range in storage if pruning_range != new_pruning_range { - BlocksToPrune::::put(new_pruning_range); + BlocksToPrune::::put(new_pruning_range); } } @@ -651,7 +702,7 @@ impl, I: Instance> BridgeStorage { blocks_at_number: &mut Vec, ) { // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::::contains_key) { + if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::::contains_key) { return; } @@ -665,10 +716,10 @@ impl, I: Instance> BridgeStorage { hash, ); - ScheduledChanges::::remove(hash); + ScheduledChanges::::remove(hash); FinalityCache::::remove(hash); if let Some(header) = header { - ValidatorsSetsRc::::mutate(header.next_validators_set_id, |rc| match *rc { + ValidatorsSetsRc::::mutate(header.next_validators_set_id, |rc| match *rc { Some(rc) if rc > 1 => Some(rc - 1), _ => None, }); @@ -683,15 +734,15 @@ impl, I: Instance> BridgeStorage { } } -impl, I: Instance> Storage for BridgeStorage { +impl, I: 'static> Storage for BridgeStorage { type Submitter = T::AccountId; fn best_block(&self) -> (HeaderId, U256) { - BestBlock::::get() + BestBlock::::get() } fn finalized_block(&self) -> HeaderId { - FinalizedBlock::::get() + FinalizedBlock::::get() } fn header(&self, hash: &H256) -> Option<(AuraHeader, Option)> { @@ -750,9 +801,9 @@ impl, I: Instance> Storage for BridgeStorage { parent_hash: &H256, ) -> Option> { Headers::::get(parent_hash).map(|parent_header| { - let validators_set = ValidatorsSets::::get(parent_header.next_validators_set_id) + let validators_set = ValidatorsSets::::get(parent_header.next_validators_set_id) .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); - let parent_scheduled_change = ScheduledChanges::::get(parent_hash); + let parent_scheduled_change = ScheduledChanges::::get(parent_hash); ImportContext { submitter, parent_hash: *parent_hash, @@ -767,15 +818,15 @@ impl, I: Instance> Storage for BridgeStorage { } fn scheduled_change(&self, hash: &H256) -> Option { - ScheduledChanges::::get(hash) + ScheduledChanges::::get(hash) } fn insert_header(&mut self, header: HeaderToImport) { if header.is_best { - BestBlock::::put((header.id, header.total_difficulty)); + BestBlock::::put((header.id, header.total_difficulty)); } if let Some(scheduled_change) = header.scheduled_change { - ScheduledChanges::::insert( + ScheduledChanges::::insert( &header.id.hash, AuraScheduledChange { validators: scheduled_change, @@ -785,12 +836,12 @@ impl, I: Instance> Storage for BridgeStorage { } let next_validators_set_id = match header.enacted_change { Some(enacted_change) => { - let next_validators_set_id = NextValidatorsSetId::::mutate(|set_id| { + let next_validators_set_id = NextValidatorsSetId::::mutate(|set_id| { let next_set_id = *set_id; *set_id += 1; next_set_id }); - ValidatorsSets::::insert( + ValidatorsSets::::insert( next_validators_set_id, ValidatorsSet { validators: enacted_change.validators, @@ -798,11 +849,11 @@ impl, I: Instance> Storage for BridgeStorage { signal_block: enacted_change.signal_block, }, ); - ValidatorsSetsRc::::insert(next_validators_set_id, 1); + ValidatorsSetsRc::::insert(next_validators_set_id, 1); next_validators_set_id } None => { - ValidatorsSetsRc::::mutate(header.context.validators_set_id, |rc| { + ValidatorsSetsRc::::mutate(header.context.validators_set_id, |rc| { *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); *rc }); @@ -826,7 +877,7 @@ impl, I: Instance> Storage for BridgeStorage { ); let last_signal_block = header.context.last_signal_block(); - HeadersByNumber::::append(header.id.number, header.id.hash); + HeadersByNumber::::append(header.id.number, header.id.hash); Headers::::insert( &header.id.hash, StoredHeader { @@ -844,7 +895,7 @@ impl, I: Instance> Storage for BridgeStorage { let finalized_number = finalized .as_ref() .map(|f| f.number) - .unwrap_or_else(|| FinalizedBlock::::get().number); + .unwrap_or_else(|| FinalizedBlock::::get().number); if let Some(finalized) = finalized { log::trace!( target: "runtime", @@ -853,7 +904,7 @@ impl, I: Instance> Storage for BridgeStorage { finalized.hash, ); - FinalizedBlock::::put(finalized); + FinalizedBlock::::put(finalized); } // and now prune headers if we need to @@ -863,7 +914,7 @@ impl, I: Instance> Storage for BridgeStorage { /// Initialize storage. #[cfg(any(feature = "std", feature = "runtime-benchmarks"))] -pub(crate) fn initialize_storage, I: Instance>( +pub(crate) fn initialize_storage, I: 'static>( initial_header: &AuraHeader, initial_difficulty: U256, initial_validators: &[Address], @@ -880,13 +931,13 @@ pub(crate) fn initialize_storage, I: Instance>( number: initial_header.number, hash: initial_hash, }; - BestBlock::::put((initial_id, initial_difficulty)); - FinalizedBlock::::put(initial_id); - BlocksToPrune::::put(PruningRange { + BestBlock::::put((initial_id, initial_difficulty)); + FinalizedBlock::::put(initial_id); + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: initial_header.number, oldest_block_to_keep: initial_header.number, }); - HeadersByNumber::::insert(initial_header.number, vec![initial_hash]); + HeadersByNumber::::insert(initial_header.number, vec![initial_hash]); Headers::::insert( initial_hash, StoredHeader { @@ -897,8 +948,8 @@ pub(crate) fn initialize_storage, I: Instance>( last_signal_block: None, }, ); - NextValidatorsSetId::::put(1); - ValidatorsSets::::insert( + NextValidatorsSetId::::put(1); + ValidatorsSets::::insert( 0, ValidatorsSet { validators: initial_validators.to_vec(), @@ -906,7 +957,7 @@ pub(crate) fn initialize_storage, I: Instance>( enact_block: initial_id, }, ); - ValidatorsSetsRc::::insert(0, 1); + ValidatorsSetsRc::::insert(0, 1); } /// Verify that transaction is included into given finalized block. @@ -1112,7 +1163,7 @@ pub(crate) mod tests { ); if i == 7 && j == 1 { - ScheduledChanges::::insert( + ScheduledChanges::::insert( hash, AuraScheduledChange { validators: validators_addresses(5), @@ -1121,7 +1172,7 @@ pub(crate) mod tests { ); } } - HeadersByNumber::::insert(i, headers_by_number); + HeadersByNumber::::insert(i, headers_by_number); } f(BridgeStorage::new()) @@ -1131,16 +1182,16 @@ pub(crate) mod tests { #[test] fn blocks_are_not_pruned_if_range_is_empty() { with_headers_to_prune(|storage| { - BlocksToPrune::::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5, }); // try to prune blocks [5; 10) storage.prune_blocks(0xFFFF, 10, 5); - assert_eq!(HeadersByNumber::::get(&5).unwrap().len(), 5); + assert_eq!(HeadersByNumber::::get(&5).unwrap().len(), 5); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5, @@ -1152,7 +1203,7 @@ pub(crate) mod tests { #[test] fn blocks_to_prune_never_shrinks_from_the_end() { with_headers_to_prune(|storage| { - BlocksToPrune::::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: 5, }); @@ -1160,7 +1211,7 @@ pub(crate) mod tests { // try to prune blocks [5; 10) storage.prune_blocks(0xFFFF, 10, 3); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5, @@ -1174,12 +1225,12 @@ pub(crate) mod tests { with_headers_to_prune(|storage| { // try to prune blocks [0; 10) storage.prune_blocks(0, 10, 10); - assert!(HeadersByNumber::::get(&0).is_some()); - assert!(HeadersByNumber::::get(&1).is_some()); - assert!(HeadersByNumber::::get(&2).is_some()); - assert!(HeadersByNumber::::get(&3).is_some()); + assert!(HeadersByNumber::::get(&0).is_some()); + assert!(HeadersByNumber::::get(&1).is_some()); + assert!(HeadersByNumber::::get(&2).is_some()); + assert!(HeadersByNumber::::get(&3).is_some()); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: 10, @@ -1194,13 +1245,13 @@ pub(crate) mod tests { // try to prune blocks [0; 10) storage.prune_blocks(7, 10, 10); // 1 headers with number = 0 is pruned (1 total) - assert!(HeadersByNumber::::get(&0).is_none()); + assert!(HeadersByNumber::::get(&0).is_none()); // 5 headers with number = 1 are pruned (6 total) - assert!(HeadersByNumber::::get(&1).is_none()); + assert!(HeadersByNumber::::get(&1).is_none()); // 1 header with number = 2 are pruned (7 total) - assert_eq!(HeadersByNumber::::get(&2).unwrap().len(), 4); + assert_eq!(HeadersByNumber::::get(&2).unwrap().len(), 4); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 2, oldest_block_to_keep: 10, @@ -1210,13 +1261,13 @@ pub(crate) mod tests { // try to prune blocks [2; 10) storage.prune_blocks(11, 10, 10); // 4 headers with number = 2 are pruned (4 total) - assert!(HeadersByNumber::::get(&2).is_none()); + assert!(HeadersByNumber::::get(&2).is_none()); // 5 headers with number = 3 are pruned (9 total) - assert!(HeadersByNumber::::get(&3).is_none()); + assert!(HeadersByNumber::::get(&3).is_none()); // 2 headers with number = 4 are pruned (11 total) - assert_eq!(HeadersByNumber::::get(&4).unwrap().len(), 3); + assert_eq!(HeadersByNumber::::get(&4).unwrap().len(), 3); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 4, oldest_block_to_keep: 10, @@ -1233,16 +1284,16 @@ pub(crate) mod tests { // and one of blocks#7 has scheduled change // => we won't prune any block#7 at all storage.prune_blocks(0xFFFF, 5, 10); - assert!(HeadersByNumber::::get(&0).is_none()); - assert!(HeadersByNumber::::get(&1).is_none()); - assert!(HeadersByNumber::::get(&2).is_none()); - assert!(HeadersByNumber::::get(&3).is_none()); - assert!(HeadersByNumber::::get(&4).is_none()); - assert!(HeadersByNumber::::get(&5).is_none()); - assert!(HeadersByNumber::::get(&6).is_none()); - assert_eq!(HeadersByNumber::::get(&7).unwrap().len(), 5); + assert!(HeadersByNumber::::get(&0).is_none()); + assert!(HeadersByNumber::::get(&1).is_none()); + assert!(HeadersByNumber::::get(&2).is_none()); + assert!(HeadersByNumber::::get(&3).is_none()); + assert!(HeadersByNumber::::get(&4).is_none()); + assert!(HeadersByNumber::::get(&5).is_none()); + assert!(HeadersByNumber::::get(&6).is_none()); + assert_eq!(HeadersByNumber::::get(&7).unwrap().len(), 5); assert_eq!( - BlocksToPrune::::get(), + BlocksToPrune::::get(), PruningRange { oldest_unpruned_block: 7, oldest_block_to_keep: 10, @@ -1272,7 +1323,7 @@ pub(crate) mod tests { assert!(FinalityCache::::get(&header_with_entry_hash).is_some()); // when we later prune this header, cache entry is removed - BlocksToPrune::::put(PruningRange { + BlocksToPrune::::put(PruningRange { oldest_unpruned_block: interval - 1, oldest_block_to_keep: interval - 1, }); @@ -1359,7 +1410,7 @@ pub(crate) mod tests { insert_header(&mut storage, header1s); // header1 is finalized - FinalizedBlock::::put(header1_id); + FinalizedBlock::::put(header1_id); // trying to get finality votes when importing header2 -> header1 succeeds assert!( diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 35c093f36387c..90c143dc932ff 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -23,7 +23,7 @@ pub use bp_eth_poa::signatures::secret_to_address; use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy}; use bp_eth_poa::{Address, AuraHeader, H256, U256}; -use frame_support::{parameter_types, weights::Weight}; +use frame_support::{parameter_types, traits::GenesisBuild, weights::Weight}; use secp256k1::SecretKey; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -146,13 +146,12 @@ pub fn run_test_with_genesis( ) -> T { let validators = validators(total_validators); let addresses = validators_addresses(total_validators); - sp_io::TestExternalities::new( - CrateGenesisConfig { + sp_io::TestExternalities::from( + GenesisBuild::::build_storage(&CrateGenesisConfig { initial_header: genesis.clone(), initial_difficulty: 0.into(), initial_validators: addresses.clone(), - } - .build_storage::() + }) .unwrap(), ) .execute_with(|| { diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 853ad0930bb0d..bc41b2286f9e5 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -63,30 +63,28 @@ impl HeaderBuilder { /// Creates default header on top of test parent with given hash. #[cfg(test)] pub fn with_parent_hash(parent_hash: H256) -> Self { - Self::with_parent_hash_on_runtime::(parent_hash) + Self::with_parent_hash_on_runtime::(parent_hash) } /// Creates default header on top of test parent with given number. First parent is selected. #[cfg(test)] pub fn with_parent_number(parent_number: u64) -> Self { - Self::with_parent_number_on_runtime::(parent_number) + Self::with_parent_number_on_runtime::(parent_number) } /// Creates default header on top of parent with given hash. - pub fn with_parent_hash_on_runtime, I: crate::Instance>(parent_hash: H256) -> Self { + pub fn with_parent_hash_on_runtime, I: 'static>(parent_hash: H256) -> Self { use crate::Headers; - use frame_support::StorageMap; let parent_header = Headers::::get(&parent_hash).unwrap().header; Self::with_parent(&parent_header) } /// Creates default header on top of parent with given number. First parent is selected. - pub fn with_parent_number_on_runtime, I: crate::Instance>(parent_number: u64) -> Self { + pub fn with_parent_number_on_runtime, I: 'static>(parent_number: u64) -> Self { use crate::HeadersByNumber; - use frame_support::StorageMap; - let parent_hash = HeadersByNumber::::get(parent_number).unwrap()[0]; + let parent_hash = HeadersByNumber::::get(parent_number).unwrap()[0]; Self::with_parent_hash_on_runtime::(parent_hash) } diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 7ec22a44391d2..e8102a527b288 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -276,10 +276,8 @@ impl ValidatorsSource { pub(crate) mod tests { use super::*; use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}; - use crate::DefaultInstance; use crate::{AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader}; use bp_eth_poa::compute_merkle_root; - use frame_support::StorageMap; const TOTAL_VALIDATORS: usize = 3; @@ -438,7 +436,7 @@ pub(crate) mod tests { }; Headers::::insert(id100.hash, header100); if let Some(scheduled_at) = scheduled_at { - ScheduledChanges::::insert(scheduled_at.hash, scheduled_change); + ScheduledChanges::::insert(scheduled_at.hash, scheduled_change); } validators.finalize_validators_change(&storage, &finalized_blocks) diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 638da68af46ad..06aa4906fb4d6 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -375,13 +375,11 @@ mod tests { validators_change_receipt, AccountId, ConstChainTime, HeaderBuilder, TestRuntime, GAS_LIMIT, }; use crate::validators::ValidatorsSource; - use crate::DefaultInstance; use crate::{ pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, ScheduledChanges, ValidatorsSet, ValidatorsSets, }; use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256}; - use frame_support::{StorageMap, StorageValue}; use hex_literal::hex; use secp256k1::SecretKey; use sp_runtime::transaction_validity::TransactionTag; @@ -418,7 +416,7 @@ mod tests { let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators); insert_header(&mut storage, block3); - FinalizedBlock::::put(block2_id); + FinalizedBlock::::put(block2_id); let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); @@ -436,21 +434,21 @@ mod tests { } fn change_validators_set_at(number: u64, finalized_set: Vec
, signalled_set: Option>) { - let set_id = NextValidatorsSetId::::get(); - NextValidatorsSetId::::put(set_id + 1); - ValidatorsSets::::insert( + let set_id = NextValidatorsSetId::::get(); + NextValidatorsSetId::::put(set_id + 1); + ValidatorsSets::::insert( set_id, ValidatorsSet { validators: finalized_set, signal_block: None, enact_block: HeaderId { number: 0, - hash: HeadersByNumber::::get(&0).unwrap()[0], + hash: HeadersByNumber::::get(&0).unwrap()[0], }, }, ); - let header_hash = HeadersByNumber::::get(&number).unwrap()[0]; + let header_hash = HeadersByNumber::::get(&number).unwrap()[0]; let mut header = Headers::::get(&header_hash).unwrap(); header.next_validators_set_id = set_id; if let Some(signalled_set) = signalled_set { @@ -458,7 +456,7 @@ mod tests { number: header.header.number - 1, hash: header.header.parent_hash, }); - ScheduledChanges::::insert( + ScheduledChanges::::insert( header.header.parent_hash, AuraScheduledChange { validators: signalled_set, From a8be2c4f2f0c3152e96f66c8289805e6040682ab Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 Aug 2021 16:59:20 +0300 Subject: [PATCH 0533/1210] migrate pallet-shift-session-manager to frame v2 (#1090) --- modules/shift-session-manager/src/lib.rs | 35 ++++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 0d867657afa9d..eef336ffd8d6d 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -19,22 +19,33 @@ #![cfg_attr(not(feature = "std"), no_std)] -use frame_support::{decl_module, decl_storage}; use sp_std::prelude::*; -/// The module configuration trait. -pub trait Config: pallet_session::Config {} +pub use pallet::*; -decl_module! { - /// Shift session manager pallet. - pub struct Module for enum Call where origin: T::Origin {} -} +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -decl_storage! { - trait Store for Pallet as ShiftSessionManager { - /// Validators of first two sessions. - InitialValidators: Option>; - } + #[pallet::config] + #[pallet::disable_frame_system_supertrait_check] + pub trait Config: pallet_session::Config {} + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData); + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::call] + impl Pallet {} + + /// Validators of first two sessions. + #[pallet::storage] + pub(super) type InitialValidators = StorageValue<_, Vec>; } impl pallet_session::SessionManager for Pallet { From f8782a14931d5de3db01b7e609114bebe6e630aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 27 Aug 2021 05:31:56 +0200 Subject: [PATCH 0534/1210] Update high-level-overview.md (#1093) Update outdated GRANDPA pallet docs. --- docs/high-level-overview.md | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 2fc210ed7a56e..2642c20c86abb 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -48,27 +48,15 @@ High level sequence charts of the process can be found in [a separate document]( ### Substrate (GRANDPA) Header Sync -The header sync pallet (`pallet-substrate-bridge`) is an on-chain light client for chains which use -GRANDPA finality. It is part of the target chain's runtime, and accepts headers from the source -chain. Its main goals are to accept valid headers, track GRANDPA finality set changes, and verify -GRANDPA finality proofs (a.k.a justifications). +The header sync pallet (`pallet-bridge-grandpa`) is an on-chain light client for chains which use +GRANDPA finality. It is part of the target chain's runtime, and accepts finality proofs from the source +chain. Verify GRANDPA finality proofs (a.k.a justifications) and track GRANDPA finality set changes. The pallet does not care about what block production mechanism is used for the source chain -(e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. Due to this it is possible for -the pallet to import (but not necessarily finalize) headers which are _not_ valid according to the -source chain's block production mechanism. +(e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. In fact the pallet does not +necessarily store all produced headers, we only import headers with valid GRANDPA justifications. -The pallet has support for tracking forks and uses the longest chain rule to determine what the -canonical chain is. The pallet allows headers to be imported on a different fork from the canonical -one as long as the headers being imported don't conflict with already finalized headers (for -example, it will not allow importing a header at a lower height than the best finalized header). - -When tracking authority set changes, the pallet - unlike the full GRANDPA protocol - does not -support tracking multiple authority set changes across forks. Each fork can have at most one pending -authority set change. This is done to prevent DoS attacks if GRANDPA on the source chain were to -stall for a long time (the pallet would have to do a lot of expensive ancestry checks to catch up). - -Referer to the [pallet documentation](../modules/substrate/src/lib.rs) for more details. +Referer to the [pallet documentation](../modules/grandpa/src/lib.rs) for more details. #### Header Relayer strategy From bb547aa4c0d2198956883835757b5c5f245cdca6 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Fri, 27 Aug 2021 17:23:25 +0800 Subject: [PATCH 0535/1210] Common crate for substrate-relay (#1082) * lib-substrate-relay * pass to build * remove unused file * clippy && tests * Changed follow suggestions * License * Make changes follow suggested * docs * fix fmt --- relays/bin-substrate/Cargo.toml | 6 +- .../src/chains/millau_headers_to_rialto.rs | 36 +++++++--- .../src/chains/millau_messages_to_rialto.rs | 68 +++++++++++-------- relays/bin-substrate/src/chains/mod.rs | 32 ++------- .../src/chains/rialto_headers_to_millau.rs | 37 +++++++--- .../src/chains/rialto_messages_to_millau.rs | 68 +++++++++++-------- .../src/chains/rococo_headers_to_wococo.rs | 49 +++++++++---- .../src/chains/rococo_messages_to_wococo.rs | 66 ++++++++++-------- .../src/chains/westend_headers_to_millau.rs | 42 +++++++++--- .../src/chains/wococo_headers_to_rococo.rs | 50 ++++++++++---- .../src/chains/wococo_messages_to_rococo.rs | 65 ++++++++++-------- relays/bin-substrate/src/cli/init_bridge.rs | 2 +- relays/bin-substrate/src/cli/relay_headers.rs | 8 ++- .../src/cli/relay_headers_and_messages.rs | 21 +++--- .../bin-substrate/src/cli/relay_messages.rs | 8 ++- relays/bin-substrate/src/main.rs | 7 -- relays/lib-substrate-relay/Cargo.toml | 51 ++++++++++++++ .../src/finality_pipeline.rs | 16 +++-- .../src/finality_target.rs | 27 +++++--- .../src/headers_initialize.rs | 0 relays/lib-substrate-relay/src/helpers.rs | 41 +++++++++++ relays/lib-substrate-relay/src/lib.rs | 28 ++++++++ .../src/messages_lane.rs | 28 ++++---- .../src/messages_source.rs | 65 +++++++++++------- .../src/messages_target.rs | 64 ++++++++++------- .../src/on_demand_headers.rs | 51 ++++++-------- 26 files changed, 618 insertions(+), 318 deletions(-) create mode 100644 relays/lib-substrate-relay/Cargo.toml rename relays/{bin-substrate => lib-substrate-relay}/src/finality_pipeline.rs (92%) rename relays/{bin-substrate => lib-substrate-relay}/src/finality_target.rs (75%) rename relays/{bin-substrate => lib-substrate-relay}/src/headers_initialize.rs (100%) create mode 100644 relays/lib-substrate-relay/src/helpers.rs create mode 100644 relays/lib-substrate-relay/src/lib.rs rename relays/{bin-substrate => lib-substrate-relay}/src/messages_lane.rs (94%) rename relays/{bin-substrate => lib-substrate-relay}/src/messages_source.rs (89%) rename relays/{bin-substrate => lib-substrate-relay}/src/messages_target.rs (85%) rename relays/{bin-substrate => lib-substrate-relay}/src/on_demand_headers.rs (91%) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 7b731e3cd707a..85d8d7dd51fa3 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -14,7 +14,6 @@ futures = "0.3.12" hex = "0.4" log = "0.4.14" num-format = "0.4" -num-traits = "0.2" paste = "1.0" structopt = "0.3" strum = { version = "0.21.0", features = ["derive"] } @@ -33,9 +32,7 @@ bp-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-grandpa = { version = "0.14.0" } finality-relay = { path = "../finality" } -headers-relay = { path = "../headers" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-messages = { path = "../../modules/messages" } @@ -49,6 +46,7 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } rialto-runtime = { path = "../../bin/rialto/runtime" } +substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies @@ -64,3 +62,5 @@ hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempdir = "0.3" +finality-grandpa = { version = "0.14.0" } + diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 58f0620b0764b..5be5083f5bbb8 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -16,25 +16,40 @@ //! Millau-to-Rialto headers sync entrypoint. -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; -use sp_core::{Bytes, Pair}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Millau-to-Rialto finality sync pipeline. -pub(crate) type MillauFinalityToRialto = SubstrateFinalityToSubstrate; +pub(crate) type FinalityPipelineMillauToRialto = SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub(crate) struct MillauFinalityToRialto { + finality_pipeline: FinalityPipelineMillauToRialto, +} + +impl MillauFinalityToRialto { + pub fn new(target_client: Client, target_sign: RialtoSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelineMillauToRialto::new(target_client, target_sign), + } + } +} impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { + type FinalitySyncPipeline = FinalityPipelineMillauToRialto; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; type TargetChain = Rialto; fn transactions_author(&self) -> bp_rialto::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( @@ -45,8 +60,13 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { ) -> Bytes { let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof).into(); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Rialto::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + transaction_nonce, + call, + ); Bytes(transaction.encode()) } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 05ff36be1f922..93662a9d6fa9d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -16,31 +16,39 @@ //! Millau-to-Rialto messages sync entrypoint. -use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, -}; -use crate::messages_source::SubstrateMessagesSource; -use crate::messages_target::SubstrateMessagesTarget; +use std::{ops::RangeInclusive, time::Duration}; + +use codec::Encode; +use frame_support::dispatch::GetDispatchInfo; +use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; -use sp_core::{Bytes, Pair}; -use std::{ops::RangeInclusive, time::Duration}; +use substrate_relay_helper::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, +}; +use substrate_relay_helper::messages_source::SubstrateMessagesSource; +use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Millau-to-Rialto message lane. -pub type MillauMessagesToRialto = +pub type MessageLaneMillauMessagesToRialto = SubstrateMessageLaneToSubstrate; +#[derive(Clone)] +pub struct MillauMessagesToRialto { + message_lane: MessageLaneMillauMessagesToRialto, +} + impl SubstrateMessageLane for MillauMessagesToRialto { + type MessageLane = MessageLaneMillauMessagesToRialto; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; @@ -58,21 +66,22 @@ impl SubstrateMessageLane for MillauMessagesToRialto { type TargetChain = Rialto; fn source_transactions_author(&self) -> bp_millau::AccountId { - (*self.source_sign.public().as_array_ref()).into() + (*self.message_lane.source_sign.public().as_array_ref()).into() } fn make_messages_receiving_proof_transaction( &self, transaction_nonce: ::Index, _generated_at_block: RialtoHeaderId, - proof: ::MessagesReceivingProof, + proof: ::MessagesReceivingProof, ) -> Bytes { let (relayers_state, proof) = proof; let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.source_client.genesis_hash(); + let transaction = + Millau::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -85,7 +94,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } fn target_transactions_author(&self) -> bp_rialto::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.message_lane.target_sign.public().as_array_ref()).into() } fn make_messages_delivery_transaction( @@ -93,7 +102,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { transaction_nonce: ::Index, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, - proof: ::MessagesProof, + proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { @@ -103,15 +112,16 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } = proof; let messages_count = nonces_end - nonces_start + 1; let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof( - self.relayer_id_at_source.clone(), + self.message_lane.relayer_id_at_source.clone(), proof, messages_count as _, dispatch_weight, ) .into(); let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.target_client.genesis_hash(); + let transaction = + Rialto::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", @@ -142,11 +152,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; let lane = MillauMessagesToRialto { - source_client: source_client.clone(), - source_sign: params.source_sign, - target_client: params.target_client.clone(), - target_sign: params.target_sign, - relayer_id_at_source: relayer_id_at_millau, + message_lane: SubstrateMessageLaneToSubstrate { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_millau, + }, }; // 2/3 is reserved for proofs and tx overhead @@ -166,7 +178,7 @@ pub async fn run( Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ Relayer mode: {:?}", - lane.relayer_id_at_source, + lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, @@ -175,7 +187,7 @@ pub async fn run( let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< - MillauMessagesToRialto, + ::MessageLane, >(&lane_id)), params.metrics_params, source_client.clone(), @@ -223,7 +235,7 @@ pub(crate) fn add_standalone_metrics( metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - crate::messages_lane::add_standalone_metrics::( + substrate_relay_helper::messages_lane::add_standalone_metrics::( metrics_prefix, metrics_params, source_client, diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 9aec7d19d2582..d2b72d4448372 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -41,7 +41,7 @@ pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = "bitcoin"; /// The identifier of token, which value is associated with Millau token value by relayer. pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "wrapped-bitcoin"; -use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams, PrometheusError, Registry}; +use relay_utils::metrics::MetricsParams; pub(crate) fn add_polkadot_kusama_price_metrics( prefix: Option, @@ -50,33 +50,15 @@ pub(crate) fn add_polkadot_kusama_price_metrics Kusama // relays, but we want to test metrics/dashboards in advance Ok(relay_utils::relay_metrics(prefix, params) - .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "polkadot"))? - .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "kusama"))? + .standalone_metric(|registry, prefix| { + substrate_relay_helper::helpers::token_price_metric(registry, prefix, "polkadot") + })? + .standalone_metric(|registry, prefix| { + substrate_relay_helper::helpers::token_price_metric(registry, prefix, "kusama") + })? .into_params()) } -/// Creates standalone token price metric. -pub(crate) fn token_price_metric( - registry: &Registry, - prefix: Option<&str>, - token_id: &str, -) -> Result { - FloatJsonValueMetric::new( - registry, - prefix, - format!( - "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", - token_id - ), - format!("$.{}.btc", token_id), - format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), - format!( - "Rate used to convert from {} to some BASE tokens", - token_id.to_uppercase() - ), - ) -} - #[cfg(test)] mod tests { use crate::cli::{encode_call, send_message}; diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 39295c89433e8..2604e79983155 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -16,25 +16,41 @@ //! Rialto-to-Millau headers sync entrypoint. -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Chain, TransactionSignScheme}; -use sp_core::{Bytes, Pair}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Rialto-to-Millau finality sync pipeline. -pub(crate) type RialtoFinalityToMillau = SubstrateFinalityToSubstrate; +pub(crate) type FinalityPipelineRialtoFinalityToMillau = + SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub struct RialtoFinalityToMillau { + finality_pipeline: FinalityPipelineRialtoFinalityToMillau, +} + +impl RialtoFinalityToMillau { + pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelineRialtoFinalityToMillau::new(target_client, target_sign), + } + } +} impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { + type FinalitySyncPipeline = FinalityPipelineRialtoFinalityToMillau; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; type TargetChain = Millau; fn transactions_author(&self) -> bp_millau::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( @@ -49,8 +65,13 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { >::submit_finality_proof(header.into_inner(), proof) .into(); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Millau::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + transaction_nonce, + call, + ); Bytes(transaction.encode()) } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 0aec33a339a3f..2b7f32f2d43da 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -16,31 +16,39 @@ //! Rialto-to-Millau messages sync entrypoint. -use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, -}; -use crate::messages_source::SubstrateMessagesSource; -use crate::messages_target::SubstrateMessagesTarget; +use std::{ops::RangeInclusive, time::Duration}; + +use codec::Encode; +use frame_support::dispatch::GetDispatchInfo; +use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; -use sp_core::{Bytes, Pair}; -use std::{ops::RangeInclusive, time::Duration}; +use substrate_relay_helper::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, +}; +use substrate_relay_helper::messages_source::SubstrateMessagesSource; +use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Rialto-to-Millau message lane. -pub type RialtoMessagesToMillau = +pub type MessageLaneRialtoMessagesToMillau = SubstrateMessageLaneToSubstrate; +#[derive(Clone)] +pub struct RialtoMessagesToMillau { + message_lane: MessageLaneRialtoMessagesToMillau, +} + impl SubstrateMessageLane for RialtoMessagesToMillau { + type MessageLane = MessageLaneRialtoMessagesToMillau; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; @@ -58,21 +66,22 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { type TargetChain = Millau; fn source_transactions_author(&self) -> bp_rialto::AccountId { - (*self.source_sign.public().as_array_ref()).into() + (*self.message_lane.source_sign.public().as_array_ref()).into() } fn make_messages_receiving_proof_transaction( &self, transaction_nonce: ::Index, _generated_at_block: MillauHeaderId, - proof: ::MessagesReceivingProof, + proof: ::MessagesReceivingProof, ) -> Bytes { let (relayers_state, proof) = proof; let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Rialto::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.source_client.genesis_hash(); + let transaction = + Rialto::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -85,7 +94,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } fn target_transactions_author(&self) -> bp_millau::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.message_lane.target_sign.public().as_array_ref()).into() } fn make_messages_delivery_transaction( @@ -93,7 +102,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { transaction_nonce: ::Index, _generated_at_header: RialtoHeaderId, _nonces: RangeInclusive, - proof: ::MessagesProof, + proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { @@ -103,15 +112,16 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } = proof; let messages_count = nonces_end - nonces_start + 1; let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof( - self.relayer_id_at_source.clone(), + self.message_lane.relayer_id_at_source.clone(), proof, messages_count as _, dispatch_weight, ) .into(); let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.target_client.genesis_hash(); + let transaction = + Millau::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", @@ -142,11 +152,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; let lane = RialtoMessagesToMillau { - source_client: source_client.clone(), - source_sign: params.source_sign, - target_client: params.target_client.clone(), - target_sign: params.target_sign, - relayer_id_at_source: relayer_id_at_rialto, + message_lane: SubstrateMessageLaneToSubstrate { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_rialto, + }, }; // 2/3 is reserved for proofs and tx overhead @@ -165,7 +177,7 @@ pub async fn run( Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ Relayer mode: {:?}", - lane.relayer_id_at_source, + lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, @@ -174,7 +186,7 @@ pub async fn run( let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< - RialtoMessagesToMillau, + ::MessageLane, >(&lane_id)), params.metrics_params, source_client.clone(), @@ -222,7 +234,7 @@ pub(crate) fn add_standalone_metrics( metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - crate::messages_lane::add_standalone_metrics::( + substrate_relay_helper::messages_lane::add_standalone_metrics::( metrics_prefix, metrics_params, source_client, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 026c918bec494..38bb54ddbc384 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -16,43 +16,63 @@ //! Rococo-to-Wococo headers sync entrypoint. -use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; -use sp_core::{Bytes, Pair}; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; /// Rococo-to-Wococo finality sync pipeline. -pub(crate) type RococoFinalityToWococo = SubstrateFinalityToSubstrate; +pub(crate) type FinalityPipelineRococoFinalityToWococo = + SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub(crate) struct RococoFinalityToWococo { + finality_pipeline: FinalityPipelineRococoFinalityToWococo, +} + +impl RococoFinalityToWococo { + pub fn new(target_client: Client, target_sign: WococoSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelineRococoFinalityToWococo::new(target_client, target_sign), + } + } +} impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { + type FinalitySyncPipeline = FinalityPipelineRococoFinalityToWococo; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; type TargetChain = Wococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(Some(finality_relay::metrics_prefix::()), params) + crate::chains::add_polkadot_kusama_price_metrics::( + Some(finality_relay::metrics_prefix::()), + params, + ) } fn start_relay_guards(&self) { relay_substrate_client::guard::abort_on_spec_version_change( - self.target_client.clone(), + self.finality_pipeline.target_client.clone(), bp_wococo::VERSION.spec_version, ); relay_substrate_client::guard::abort_when_account_balance_decreased( - self.target_client.clone(), + self.finality_pipeline.target_client.clone(), self.transactions_author(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } fn transactions_author(&self) -> bp_wococo::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( @@ -64,8 +84,13 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(header.into_inner(), proof), ); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Wococo::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + transaction_nonce, + call, + ); Bytes(transaction.encode()) } diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 080fa3b0491b7..043e6c89e441d 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -16,30 +16,38 @@ //! Rococo-to-Wococo messages sync entrypoint. -use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, -}; -use crate::messages_source::SubstrateMessagesSource; -use crate::messages_target::SubstrateMessagesTarget; +use std::{ops::RangeInclusive, time::Duration}; + +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use codec::Encode; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; -use sp_core::{Bytes, Pair}; -use std::{ops::RangeInclusive, time::Duration}; +use substrate_relay_helper::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, +}; +use substrate_relay_helper::messages_source::SubstrateMessagesSource; +use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Rococo-to-Wococo message lane. -pub type RococoMessagesToWococo = +pub type MessageLaneRococoMessagesToWococo = SubstrateMessageLaneToSubstrate; +#[derive(Clone)] +pub struct RococoMessagesToWococo { + message_lane: MessageLaneRococoMessagesToWococo, +} + impl SubstrateMessageLane for RococoMessagesToWococo { + type MessageLane = MessageLaneRococoMessagesToWococo; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; @@ -57,14 +65,14 @@ impl SubstrateMessageLane for RococoMessagesToWococo { type TargetChain = Wococo; fn source_transactions_author(&self) -> bp_rococo::AccountId { - (*self.source_sign.public().as_array_ref()).into() + (*self.message_lane.source_sign.public().as_array_ref()).into() } fn make_messages_receiving_proof_transaction( &self, transaction_nonce: ::Index, _generated_at_block: WococoHeaderId, - proof: ::MessagesReceivingProof, + proof: ::MessagesReceivingProof, ) -> Bytes { let (relayers_state, proof) = proof; let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( @@ -73,8 +81,9 @@ impl SubstrateMessageLane for RococoMessagesToWococo { relayers_state, ), ); - let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Rococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.source_client.genesis_hash(); + let transaction = + Rococo::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Wococo -> Rococo confirmation transaction. Weight: /{}, size: {}/{}", @@ -86,7 +95,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { } fn target_transactions_author(&self) -> bp_wococo::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.message_lane.target_sign.public().as_array_ref()).into() } fn make_messages_delivery_transaction( @@ -94,7 +103,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { transaction_nonce: ::Index, _generated_at_header: RococoHeaderId, _nonces: RangeInclusive, - proof: ::MessagesProof, + proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { @@ -106,14 +115,15 @@ impl SubstrateMessageLane for RococoMessagesToWococo { let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof( - self.relayer_id_at_source.clone(), + self.message_lane.relayer_id_at_source.clone(), proof, messages_count as _, dispatch_weight, ), ); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.target_client.genesis_hash(); + let transaction = + Wococo::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rococo -> Wococo delivery transaction. Weight: /{}, size: {}/{}", @@ -151,11 +161,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; let lane = RococoMessagesToWococo { - source_client: source_client.clone(), - source_sign: params.source_sign, - target_client: params.target_client.clone(), - target_sign: params.target_sign, - relayer_id_at_source: relayer_id_at_rococo, + message_lane: SubstrateMessageLaneToSubstrate { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_rococo, + }, }; // 2/3 is reserved for proofs and tx overhead @@ -180,7 +192,7 @@ pub async fn run( Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ Relayer mode: {:?}", - lane.relayer_id_at_source, + lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, @@ -189,7 +201,7 @@ pub async fn run( let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< - RococoMessagesToWococo, + ::MessageLane, >(&lane_id)), params.metrics_params, source_client.clone(), @@ -237,7 +249,7 @@ pub(crate) fn add_standalone_metrics( metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - crate::messages_lane::add_standalone_metrics::( + substrate_relay_helper::messages_lane::add_standalone_metrics::( metrics_prefix, metrics_params, source_client, diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index f0395dc10d8d9..9fdf8b1a81bb6 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -16,30 +16,49 @@ //! Westend-to-Millau headers sync entrypoint. -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; -use sp_core::{Bytes, Pair}; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Westend-to-Millau finality sync pipeline. -pub(crate) type WestendFinalityToMillau = SubstrateFinalityToSubstrate; +pub(crate) type FinalityPipelineWestendFinalityToMillau = + SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub(crate) struct WestendFinalityToMillau { + finality_pipeline: FinalityPipelineWestendFinalityToMillau, +} + +impl WestendFinalityToMillau { + pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelineWestendFinalityToMillau::new(target_client, target_sign), + } + } +} impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { + type FinalitySyncPipeline = FinalityPipelineWestendFinalityToMillau; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; type TargetChain = Millau; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(Some(finality_relay::metrics_prefix::()), params) + crate::chains::add_polkadot_kusama_price_metrics::( + Some(finality_relay::metrics_prefix::()), + params, + ) } fn transactions_author(&self) -> bp_millau::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( @@ -54,8 +73,13 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { >::submit_finality_proof(header.into_inner(), proof) .into(); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Millau::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Millau::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + transaction_nonce, + call, + ); Bytes(transaction.encode()) } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index d23266c6491f2..a65bfd7624447 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -16,15 +16,15 @@ //! Wococo-to-Rococo headers sync entrypoint. -use crate::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; -use codec::Encode; use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; -use sp_core::{Bytes, Pair}; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -34,31 +34,50 @@ use sp_core::{Bytes, Pair}; pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000; /// Wococo-to-Rococo finality sync pipeline. -pub(crate) type WococoFinalityToRococo = SubstrateFinalityToSubstrate; +pub(crate) type FinalityPipelineWococoFinalityToRococo = + SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub(crate) struct WococoFinalityToRococo { + finality_pipeline: FinalityPipelineWococoFinalityToRococo, +} + +impl WococoFinalityToRococo { + pub fn new(target_client: Client, target_sign: RococoSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelineWococoFinalityToRococo::new(target_client, target_sign), + } + } +} impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { + type FinalitySyncPipeline = FinalityPipelineWococoFinalityToRococo; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; type TargetChain = Rococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(Some(finality_relay::metrics_prefix::()), params) + crate::chains::add_polkadot_kusama_price_metrics::( + Some(finality_relay::metrics_prefix::()), + params, + ) } fn start_relay_guards(&self) { relay_substrate_client::guard::abort_on_spec_version_change( - self.target_client.clone(), + self.finality_pipeline.target_client.clone(), bp_rococo::VERSION.spec_version, ); relay_substrate_client::guard::abort_when_account_balance_decreased( - self.target_client.clone(), + self.finality_pipeline.target_client.clone(), self.transactions_author(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } fn transactions_author(&self) -> bp_rococo::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() } fn make_submit_finality_proof_transaction( @@ -70,8 +89,13 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof), ); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Rococo::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + transaction_nonce, + call, + ); Bytes(transaction.encode()) } @@ -79,10 +103,12 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { #[cfg(test)] mod tests { - use super::*; use frame_support::weights::WeightToFeePolynomial; + use pallet_bridge_grandpa::weights::WeightInfo; + use super::*; + #[test] fn maximal_balance_decrease_per_day_is_sane() { // Rococo/Wococo GRANDPA pallet weights. They're now using Rialto weights => using `RialtoWeight` is justified. diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index b36088388ffe7..d068dc2f11b55 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -16,30 +16,37 @@ //! Wococo-to-Rococo messages sync entrypoint. -use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, -}; -use crate::messages_source::SubstrateMessagesSource; -use crate::messages_target::SubstrateMessagesTarget; +use std::{ops::RangeInclusive, time::Duration}; + +use codec::Encode; +use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use codec::Encode; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; -use sp_core::{Bytes, Pair}; -use std::{ops::RangeInclusive, time::Duration}; +use substrate_relay_helper::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, +}; +use substrate_relay_helper::messages_source::SubstrateMessagesSource; +use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Wococo-to-Rococo message lane. -pub type WococoMessagesToRococo = +pub type MessageLaneWococoMessagesToRococo = SubstrateMessageLaneToSubstrate; +#[derive(Clone)] +pub struct WococoMessagesToRococo { + message_lane: MessageLaneWococoMessagesToRococo, +} + impl SubstrateMessageLane for WococoMessagesToRococo { + type MessageLane = MessageLaneWococoMessagesToRococo; const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; @@ -57,14 +64,14 @@ impl SubstrateMessageLane for WococoMessagesToRococo { type TargetChain = Rococo; fn source_transactions_author(&self) -> bp_wococo::AccountId { - (*self.source_sign.public().as_array_ref()).into() + (*self.message_lane.source_sign.public().as_array_ref()).into() } fn make_messages_receiving_proof_transaction( &self, transaction_nonce: ::Index, _generated_at_block: RococoHeaderId, - proof: ::MessagesReceivingProof, + proof: ::MessagesReceivingProof, ) -> Bytes { let (relayers_state, proof) = proof; let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( @@ -73,8 +80,9 @@ impl SubstrateMessageLane for WococoMessagesToRococo { relayers_state, ), ); - let genesis_hash = *self.source_client.genesis_hash(); - let transaction = Wococo::sign_transaction(genesis_hash, &self.source_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.source_client.genesis_hash(); + let transaction = + Wococo::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Rococo -> Wococo confirmation transaction. Weight: /{}, size: {}/{}", @@ -86,7 +94,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { } fn target_transactions_author(&self) -> bp_rococo::AccountId { - (*self.target_sign.public().as_array_ref()).into() + (*self.message_lane.target_sign.public().as_array_ref()).into() } fn make_messages_delivery_transaction( @@ -94,7 +102,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { transaction_nonce: ::Index, _generated_at_header: WococoHeaderId, _nonces: RangeInclusive, - proof: ::MessagesProof, + proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { @@ -106,14 +114,15 @@ impl SubstrateMessageLane for WococoMessagesToRococo { let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof( - self.relayer_id_at_source.clone(), + self.message_lane.relayer_id_at_source.clone(), proof, messages_count as _, dispatch_weight, ), ); - let genesis_hash = *self.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction(genesis_hash, &self.target_sign, transaction_nonce, call); + let genesis_hash = *self.message_lane.target_client.genesis_hash(); + let transaction = + Rococo::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); log::trace!( target: "bridge", "Prepared Wococo -> Rococo delivery transaction. Weight: /{}, size: {}/{}", @@ -151,11 +160,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; let lane = WococoMessagesToRococo { - source_client: source_client.clone(), - source_sign: params.source_sign, - target_client: params.target_client.clone(), - target_sign: params.target_sign, - relayer_id_at_source: relayer_id_at_wococo, + message_lane: SubstrateMessageLaneToSubstrate { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_wococo, + }, }; // 2/3 is reserved for proofs and tx overhead @@ -180,7 +191,7 @@ pub async fn run( Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ Relayer mode: {:?}", - lane.relayer_id_at_source, + lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, @@ -189,7 +200,7 @@ pub async fn run( let (metrics_params, metrics_values) = add_standalone_metrics( Some(messages_relay::message_lane_loop::metrics_prefix::< - WococoMessagesToRococo, + ::MessageLane, >(&lane_id)), params.metrics_params, source_client.clone(), @@ -237,7 +248,7 @@ pub(crate) fn add_standalone_metrics( metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - crate::messages_lane::add_standalone_metrics::( + substrate_relay_helper::messages_lane::add_standalone_metrics::( metrics_prefix, metrics_params, source_client, diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 647978e430a81..846d3a575ea5b 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -141,7 +141,7 @@ impl InitBridge { let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; - crate::headers_initialize::initialize( + substrate_relay_helper::headers_initialize::initialize( source_client, target_client.clone(), target_sign.public().into(), diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 0f699ff9787b4..404e571c2c9c0 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -14,11 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; -use crate::finality_pipeline::SubstrateFinalitySyncPipeline; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::finality_pipeline::SubstrateFinalitySyncPipeline; + +use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; + /// Start headers relayer process. #[derive(StructOpt)] pub struct RelayHeaders { @@ -102,7 +104,7 @@ impl RelayHeaders { let finality = Finality::new(target_client.clone(), target_sign); finality.start_relay_guards(); - crate::finality_pipeline::run( + substrate_relay_helper::finality_pipeline::run( finality, source_client, target_client, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 04ee1a6bc2c67..4747939085938 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -22,16 +22,17 @@ //! 2) add `declare_bridge_options!(...)` for the bridge; //! 3) add bridge support to the `select_bridge! { ... }` macro. -use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}; -use crate::declare_chain_options; -use crate::messages_lane::MessagesRelayParams; -use crate::on_demand_headers::OnDemandHeadersRelay; - use futures::{FutureExt, TryFutureExt}; -use relay_utils::metrics::MetricsParams; use structopt::StructOpt; use strum::VariantNames; +use relay_utils::metrics::MetricsParams; +use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane}; +use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay; + +use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}; +use crate::declare_chain_options; + /// Start headers+messages relayer process. #[derive(StructOpt)] pub enum RelayHeadersAndMessages { @@ -195,7 +196,9 @@ impl RelayHeadersAndMessages { lane_id: lane, relayer_mode, metrics_params: metrics_params.clone().disable().metrics_prefix( - messages_relay::message_lane_loop::metrics_prefix::(&lane), + messages_relay::message_lane_loop::metrics_prefix::< + ::MessageLane, + >(&lane), ), }) .map_err(|e| anyhow::format_err!("{}", e)) @@ -210,7 +213,9 @@ impl RelayHeadersAndMessages { lane_id: lane, relayer_mode, metrics_params: metrics_params.clone().disable().metrics_prefix( - messages_relay::message_lane_loop::metrics_prefix::(&lane), + messages_relay::message_lane_loop::metrics_prefix::< + ::MessageLane, + >(&lane), ), }) .map_err(|e| anyhow::format_err!("{}", e)) diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index afd59c7a3a167..0f89e9843f161 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -14,15 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +use substrate_relay_helper::messages_lane::MessagesRelayParams; + use crate::cli::bridge::FullBridge; use crate::cli::{ HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; -use crate::messages_lane::MessagesRelayParams; use crate::select_full_bridge; -use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; /// Relayer operating mode. #[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq)] diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index d119042b0d8dc..13db6beefa6a0 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -20,13 +20,6 @@ mod chains; mod cli; -mod finality_pipeline; -mod finality_target; -mod headers_initialize; -mod messages_lane; -mod messages_source; -mod messages_target; -mod on_demand_headers; fn main() { let command = cli::parse_args(); diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml new file mode 100644 index 0000000000000..944a2d3479e4c --- /dev/null +++ b/relays/lib-substrate-relay/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "substrate-relay-helper" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +anyhow = "1.0" +async-std = "1.9.0" +async-trait = "0.1.42" +codec = { package = "parity-scale-codec", version = "2.2.0" } +futures = "0.3.12" +num-format = "0.4" +num-traits = "0.2" +log = "0.4.14" + + +# Bridge dependencies + +bp-header-chain = { path = "../../primitives/header-chain" } +bridge-runtime-common = { path = "../../bin/runtime-common" } + +finality-grandpa = { version = "0.14.0" } +finality-relay = { path = "../finality" } +relay-utils = { path = "../utils" } +headers-relay = { path = "../headers" } +messages-relay = { path = "../messages" } +relay-substrate-client = { path = "../client-substrate" } + +pallet-bridge-messages = { path = "../../modules/messages" } + +bp-runtime = { path = "../../primitives/runtime" } +bp-messages = { path = "../../primitives/messages" } + + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[dev-dependencies] +relay-millau-client = { path = "../client-millau" } +relay-rialto-client = { path = "../client-rialto" } +bp-rialto = { path = "../../primitives/chain-rialto" } +bp-millau = { path = "../../primitives/chain-millau" } +rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/bin-substrate/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs similarity index 92% rename from relays/bin-substrate/src/finality_pipeline.rs rename to relays/lib-substrate-relay/src/finality_pipeline.rs index 2013ec646b252..deb83d4ea9b99 100644 --- a/relays/bin-substrate/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -34,7 +34,9 @@ pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(120); pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; /// Headers sync pipeline for Substrate <-> Substrate relays. -pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { +pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { + type FinalitySyncPipeline: FinalitySyncPipeline; + /// Name of the runtime method that returns id of best finalized source header at target chain. const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; @@ -60,8 +62,8 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { fn make_submit_finality_proof_transaction( &self, transaction_nonce: ::Index, - header: Self::Header, - proof: Self::FinalityProof, + header: ::Header, + proof: ::FinalityProof, ) -> Bytes; } @@ -69,9 +71,9 @@ pub trait SubstrateFinalitySyncPipeline: FinalitySyncPipeline { #[derive(Clone)] pub struct SubstrateFinalityToSubstrate { /// Client for the target chain. - pub(crate) target_client: Client, + pub target_client: Client, /// Data required to sign target chain transactions. - pub(crate) target_sign: TargetSign, + pub target_sign: TargetSign, /// Unused generic arguments dump. _marker: PhantomData, } @@ -123,12 +125,12 @@ pub async fn run( metrics_params: MetricsParams, ) -> anyhow::Result<()> where - P: SubstrateFinalitySyncPipeline< + P: SubstrateFinalitySyncPipeline, + P::FinalitySyncPipeline: FinalitySyncPipeline< Hash = HashOf, Number = BlockNumberOf, Header = SyncHeader, FinalityProof = GrandpaJustification, - TargetChain = TargetChain, >, SourceChain: Clone + Chain, BlockNumberOf: BlockNumberBase, diff --git a/relays/bin-substrate/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs similarity index 75% rename from relays/bin-substrate/src/finality_target.rs rename to relays/lib-substrate-relay/src/finality_target.rs index 6c4c384d11a60..bcf09b1a6d324 100644 --- a/relays/bin-substrate/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -22,7 +22,7 @@ use crate::finality_pipeline::SubstrateFinalitySyncPipeline; use async_trait::async_trait; use codec::Decode; -use finality_relay::TargetClient; +use finality_relay::{FinalitySyncPipeline, TargetClient}; use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_utils::relay_loop::Client as RelayClient; @@ -58,28 +58,35 @@ impl RelayClient for SubstrateFinali } #[async_trait] -impl TargetClient

for SubstrateFinalityTarget +impl TargetClient for SubstrateFinalityTarget where C: Chain, - P::Number: Decode, - P::Hash: Decode, P: SubstrateFinalitySyncPipeline, + ::Number: Decode, + ::Hash: Decode, { - async fn best_finalized_source_block_number(&self) -> Result { + async fn best_finalized_source_block_number( + &self, + ) -> Result<::Number, SubstrateError> { // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay self.client.ensure_synced().await?; - Ok(crate::messages_source::read_client_state::( - &self.client, - P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, - ) + Ok(crate::messages_source::read_client_state::< + C, + ::Hash, + ::Number, + >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) .await? .best_finalized_peer_at_best_self .0) } - async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), SubstrateError> { + async fn submit_finality_proof( + &self, + header: ::Header, + proof: ::FinalityProof, + ) -> Result<(), SubstrateError> { let transactions_author = self.pipeline.transactions_author(); let pipeline = self.pipeline.clone(); self.client diff --git a/relays/bin-substrate/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs similarity index 100% rename from relays/bin-substrate/src/headers_initialize.rs rename to relays/lib-substrate-relay/src/headers_initialize.rs diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs new file mode 100644 index 0000000000000..91d551140c2de --- /dev/null +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -0,0 +1,41 @@ +// 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 . + +//! Substrate relay helpers + +use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, Registry}; + +/// Creates standalone token price metric. +pub fn token_price_metric( + registry: &Registry, + prefix: Option<&str>, + token_id: &str, +) -> Result { + FloatJsonValueMetric::new( + registry, + prefix, + format!( + "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", + token_id + ), + format!("$.{}.btc", token_id), + format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), + format!( + "Rate used to convert from {} to some BASE tokens", + token_id.to_uppercase() + ), + ) +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs new file mode 100644 index 0000000000000..32eaa2276e1a1 --- /dev/null +++ b/relays/lib-substrate-relay/src/lib.rs @@ -0,0 +1,28 @@ +// 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 . + +//! The library of substrate relay. contains some public codes to provide to substrate relay. + +#![warn(missing_docs)] + +pub mod finality_pipeline; +pub mod finality_target; +pub mod headers_initialize; +pub mod helpers; +pub mod messages_lane; +pub mod messages_source; +pub mod messages_target; +pub mod on_demand_headers; diff --git a/relays/bin-substrate/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs similarity index 94% rename from relays/bin-substrate/src/messages_lane.rs rename to relays/lib-substrate-relay/src/messages_lane.rs index cea43058d8ed5..fae07c33b3c14 100644 --- a/relays/bin-substrate/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -56,7 +56,9 @@ pub struct MessagesRelayParams { } /// Message sync pipeline for Substrate <-> Substrate relays. -pub trait SubstrateMessageLane: MessageLane { +pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { + type MessageLane: MessageLane; + /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; /// Name of the runtime method that returns latest generated nonce at the source chain. @@ -88,9 +90,9 @@ pub trait SubstrateMessageLane: MessageLane { fn make_messages_delivery_transaction( &self, transaction_nonce: ::Index, - generated_at_header: SourceHeaderIdOf, + generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, - proof: Self::MessagesProof, + proof: ::MessagesProof, ) -> Bytes; /// Returns id of account that we're using to sign transactions at source chain (delivery proof). @@ -100,8 +102,8 @@ pub trait SubstrateMessageLane: MessageLane { fn make_messages_receiving_proof_transaction( &self, transaction_nonce: ::Index, - generated_at_header: TargetHeaderIdOf, - proof: Self::MessagesReceivingProof, + generated_at_header: TargetHeaderIdOf, + proof: ::MessagesReceivingProof, ) -> Bytes; } @@ -109,15 +111,15 @@ pub trait SubstrateMessageLane: MessageLane { #[derive(Debug)] pub struct SubstrateMessageLaneToSubstrate { /// Client for the source Substrate chain. - pub(crate) source_client: Client, + pub source_client: Client, /// Parameters required to sign transactions for source chain. - pub(crate) source_sign: SourceSignParams, + pub source_sign: SourceSignParams, /// Client for the target Substrate chain. - pub(crate) target_client: Client, + pub target_client: Client, /// Parameters required to sign transactions for target chain. - pub(crate) target_sign: TargetSignParams, + pub target_sign: TargetSignParams, /// Account id of relayer at the source chain. - pub(crate) relayer_id_at_source: Source::AccountId, + pub relayer_id_at_source: Source::AccountId, } impl Clone @@ -261,14 +263,14 @@ pub fn add_standalone_metrics( } if let Some(source_chain_token_id) = source_chain_token_id { metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = crate::chains::token_price_metric(registry, prefix, source_chain_token_id)?; + let metric = crate::helpers::token_price_metric(registry, prefix, source_chain_token_id)?; source_to_base_conversion_rate = Some(metric.shared_value_ref()); Ok(metric) })?; } if let Some(target_chain_token_id) = target_chain_token_id { metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = crate::chains::token_price_metric(registry, prefix, target_chain_token_id)?; + let metric = crate::helpers::token_price_metric(registry, prefix, target_chain_token_id)?; target_to_base_conversion_rate = Some(metric.shared_value_ref()); Ok(metric) })?; @@ -276,8 +278,8 @@ pub fn add_standalone_metrics( Ok(( metrics_params.into_params(), StandaloneMessagesMetrics { - source_to_base_conversion_rate, target_to_base_conversion_rate, + source_to_base_conversion_rate, }, )) } diff --git a/relays/bin-substrate/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs similarity index 89% rename from relays/bin-substrate/src/messages_source.rs rename to relays/lib-substrate-relay/src/messages_source.rs index 6792848e4a70b..279b2c45e0fa8 100644 --- a/relays/bin-substrate/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -30,6 +30,7 @@ use bridge_runtime_common::messages::{ }; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight}; +use messages_relay::message_lane::MessageLane; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ @@ -107,42 +108,49 @@ where } #[async_trait] -impl SourceClient

for SubstrateMessagesSource +impl SourceClient for SubstrateMessagesSource where - SC: Chain, + SC: Chain< + Hash = ::SourceHeaderHash, + BlockNumber = ::SourceHeaderNumber, + Balance = ::SourceChainBalance, + >, SC::Hash: Copy, SC::BlockNumber: Copy, SC::Balance: Decode + Bounded, SC::Header: DeserializeOwned, SC::Index: DeserializeOwned, SC::BlockNumber: BlockNumberBase, - TC: Chain, - P: SubstrateMessageLane< + TC: Chain< + Hash = ::TargetHeaderHash, + BlockNumber = ::TargetHeaderNumber, + >, + P: SubstrateMessageLane, + P::MessageLane: MessageLane< MessagesProof = SubstrateMessagesProof, MessagesReceivingProof = SubstrateMessagesReceivingProof, - SourceChain = SC, - TargetChain = TC, >, - P::TargetHeaderNumber: Decode, - P::TargetHeaderHash: Decode, + ::TargetHeaderNumber: Decode, + ::TargetHeaderHash: Decode, I: Send + Sync + Instance, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver self.client.ensure_synced().await?; - read_client_state::<_, P::TargetHeaderHash, P::TargetHeaderNumber>( - &self.client, - P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE, - ) + read_client_state::< + _, + ::TargetHeaderHash, + ::TargetHeaderNumber, + >(&self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE) .await } async fn latest_generated_nonce( &self, - id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, MessageNonce), SubstrateError> { + id: SourceHeaderIdOf, + ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -158,8 +166,8 @@ where async fn latest_confirmed_received_nonce( &self, - id: SourceHeaderIdOf

, - ) -> Result<(SourceHeaderIdOf

, MessageNonce), SubstrateError> { + id: SourceHeaderIdOf, + ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -175,9 +183,9 @@ where async fn generated_message_details( &self, - id: SourceHeaderIdOf

, + id: SourceHeaderIdOf, nonces: RangeInclusive, - ) -> Result, SubstrateError> { + ) -> Result::SourceChainBalance>, SubstrateError> { let encoded_response = self .client .state_call( @@ -195,10 +203,17 @@ where async fn prove_messages( &self, - id: SourceHeaderIdOf

, + id: SourceHeaderIdOf, nonces: RangeInclusive, proof_parameters: MessageProofParameters, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), SubstrateError> { + ) -> Result< + ( + SourceHeaderIdOf, + RangeInclusive, + ::MessagesProof, + ), + SubstrateError, + > { let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { @@ -230,8 +245,8 @@ where async fn submit_messages_receiving_proof( &self, - generated_at_block: TargetHeaderIdOf

, - proof: P::MessagesReceivingProof, + generated_at_block: TargetHeaderIdOf, + proof: ::MessagesReceivingProof, ) -> Result<(), SubstrateError> { let lane = self.lane.clone(); self.client @@ -242,13 +257,13 @@ where Ok(()) } - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

) { + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { target_to_source_headers_relay.require_finalized_header(id).await; } } - async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance { + async fn estimate_confirmation_transaction(&self) -> ::SourceChainBalance { self.client .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( Zero::zero(), diff --git a/relays/bin-substrate/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs similarity index 85% rename from relays/bin-substrate/src/messages_target.rs rename to relays/lib-substrate-relay/src/messages_target.rs index 666bfc48c2a71..4cafcc4866fcc 100644 --- a/relays/bin-substrate/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -30,6 +30,7 @@ use bridge_runtime_common::messages::{ }; use codec::{Decode, Encode}; use frame_support::{traits::Instance, weights::Weight}; +use messages_relay::message_lane::MessageLane; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, @@ -110,42 +111,49 @@ where } #[async_trait] -impl TargetClient

for SubstrateMessagesTarget +impl TargetClient for SubstrateMessagesTarget where - SC: Chain, + SC: Chain< + Hash = ::SourceHeaderHash, + BlockNumber = ::SourceHeaderNumber, + Balance = ::SourceChainBalance, + >, SC::Balance: TryFrom + Bounded, - TC: Chain, + TC: Chain< + Hash = ::TargetHeaderHash, + BlockNumber = ::TargetHeaderNumber, + >, TC::Hash: Copy, TC::BlockNumber: Copy, TC::Header: DeserializeOwned, TC::Index: DeserializeOwned, ::Number: BlockNumberBase, - P: SubstrateMessageLane< + P: SubstrateMessageLane, + P::MessageLane: MessageLane< MessagesProof = SubstrateMessagesProof, MessagesReceivingProof = SubstrateMessagesReceivingProof, - SourceChain = SC, - TargetChain = TC, >, - P::SourceHeaderNumber: Decode, - P::SourceHeaderHash: Decode, + ::SourceHeaderNumber: Decode, + ::SourceHeaderHash: Decode, I: Send + Sync + Instance, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver self.client.ensure_synced().await?; - read_client_state::<_, P::SourceHeaderHash, P::SourceHeaderNumber>( - &self.client, - P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET, - ) + read_client_state::< + _, + ::SourceHeaderHash, + ::SourceHeaderNumber, + >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) .await } async fn latest_received_nonce( &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, MessageNonce), SubstrateError> { + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -161,8 +169,8 @@ where async fn latest_confirmed_received_nonce( &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, MessageNonce), SubstrateError> { + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( @@ -178,8 +186,8 @@ where async fn unrewarded_relayers_state( &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, UnrewardedRelayersState), SubstrateError> { + id: TargetHeaderIdOf, + ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), SubstrateError> { let encoded_response = self .client .state_call( @@ -195,8 +203,14 @@ where async fn prove_messages_receiving( &self, - id: TargetHeaderIdOf

, - ) -> Result<(TargetHeaderIdOf

, P::MessagesReceivingProof), SubstrateError> { + id: TargetHeaderIdOf, + ) -> Result< + ( + TargetHeaderIdOf, + ::MessagesReceivingProof, + ), + SubstrateError, + > { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); let proof = self @@ -215,9 +229,9 @@ where async fn submit_messages_proof( &self, - generated_at_header: SourceHeaderIdOf

, + generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, - proof: P::MessagesProof, + proof: ::MessagesProof, ) -> Result, SubstrateError> { let lane = self.lane.clone(); let nonces_clone = nonces.clone(); @@ -229,7 +243,7 @@ where Ok(nonces) } - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

) { + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { source_to_target_headers_relay.require_finalized_header(id).await; } @@ -240,7 +254,7 @@ where nonces: RangeInclusive, total_dispatch_weight: Weight, total_size: u32, - ) -> Result { + ) -> Result<::SourceChainBalance, SubstrateError> { let conversion_rate = self .metric_values .target_to_source_conversion_rate() diff --git a/relays/bin-substrate/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs similarity index 91% rename from relays/bin-substrate/src/on_demand_headers.rs rename to relays/lib-substrate-relay/src/on_demand_headers.rs index 4a2b04328b862..74166b89e74ca 100644 --- a/relays/bin-substrate/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -16,27 +16,28 @@ //! On-demand Substrate -> Substrate headers relay. -use crate::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, STALL_TIMEOUT, -}; -use crate::finality_target::SubstrateFinalityTarget; +use std::fmt::Debug; use async_std::sync::{Arc, Mutex}; -use bp_header_chain::justification::GrandpaJustification; +use futures::{select, FutureExt}; +use num_traits::{CheckedSub, One, Zero}; + use finality_relay::{ FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader, TargetClient as FinalityTargetClient, }; -use futures::{select, FutureExt}; -use num_traits::{CheckedSub, One, Zero}; use relay_substrate_client::{ finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef}, - BlockNumberOf, Chain, Client, HashOf, HeaderIdOf, SyncHeader, + Chain, Client, HeaderIdOf, SyncHeader, }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, MaybeConnectionError, }; -use std::fmt::Debug; + +use crate::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, STALL_TIMEOUT, +}; +use crate::finality_target::SubstrateFinalityTarget; /// On-demand Substrate <-> Substrate headers relay. /// @@ -52,10 +53,10 @@ pub struct OnDemandHeadersRelay { impl OnDemandHeadersRelay { /// Create new on-demand headers relay. - pub fn new( + pub fn new( source_client: Client, target_client: Client, - pipeline: SubstrateFinalityToSubstrate, + pipeline: P, maximal_headers_difference: SourceChain::BlockNumber, ) -> Self where @@ -64,15 +65,10 @@ impl OnDemandHeadersRelay { TargetChain: Chain + Debug, TargetChain::BlockNumber: BlockNumberBase, TargetSign: Clone + Send + Sync + 'static, - SubstrateFinalityToSubstrate: SubstrateFinalitySyncPipeline< - Hash = HashOf, - Number = BlockNumberOf, - Header = SyncHeader, - FinalityProof = GrandpaJustification, + P: SubstrateFinalitySyncPipeline< + FinalitySyncPipeline = SubstrateFinalityToSubstrate, TargetChain = TargetChain, >, - SubstrateFinalityTarget>: - FinalityTargetClient>, { let required_header_number = Arc::new(Mutex::new(Zero::zero())); let this = OnDemandHeadersRelay { @@ -111,10 +107,11 @@ impl OnDemandHeadersRelay { } /// Background task that is responsible for starting headers relay. -async fn background_task( +async fn background_task( source_client: Client, target_client: Client, - pipeline: SubstrateFinalityToSubstrate, + // pipeline: SubstrateFinalityToSubstrate, + pipeline: P, maximal_headers_difference: SourceChain::BlockNumber, required_header_number: RequiredHeaderNumberRef, ) where @@ -123,15 +120,10 @@ async fn background_task( TargetChain: Chain + Debug, TargetChain::BlockNumber: BlockNumberBase, TargetSign: Clone + Send + Sync + 'static, - SubstrateFinalityToSubstrate: SubstrateFinalitySyncPipeline< - Hash = HashOf, - Number = BlockNumberOf, - Header = SyncHeader, - FinalityProof = GrandpaJustification, + P: SubstrateFinalitySyncPipeline< + FinalitySyncPipeline = SubstrateFinalityToSubstrate, TargetChain = TargetChain, >, - SubstrateFinalityTarget>: - FinalityTargetClient>, { let relay_task_name = on_demand_headers_relay_name::(); let mut finality_source = SubstrateFinalitySource::< @@ -373,8 +365,9 @@ async fn best_finalized_source_header_at_target Result as RelayClient>::Error> where - SubstrateFinalityTarget: FinalityTargetClient

, - P: FinalitySyncPipeline, + SubstrateFinalityTarget: FinalityTargetClient, + P: SubstrateFinalitySyncPipeline, + P::FinalitySyncPipeline: FinalitySyncPipeline, { finality_target .best_finalized_source_block_number() From 2b53e4d2d6d63bb94c0f23a81d0cd7bc699598ec Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 Aug 2021 11:48:13 +0300 Subject: [PATCH 0536/1210] Add missing docs (#1095) * added missing docs * added .cargo to gitignore --- relays/lib-substrate-relay/src/finality_pipeline.rs | 1 + relays/lib-substrate-relay/src/messages_lane.rs | 3 +++ relays/lib-substrate-relay/src/messages_source.rs | 5 +++++ 3 files changed, 9 insertions(+) diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index deb83d4ea9b99..2dc9a6394767f 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -35,6 +35,7 @@ pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; /// Headers sync pipeline for Substrate <-> Substrate relays. pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { + /// Pipeline for syncing finalized Source chain headers to Target chain. type FinalitySyncPipeline: FinalitySyncPipeline; /// Name of the runtime method that returns id of best finalized source header at target chain. diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index fae07c33b3c14..15b75ae945480 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Tools for supporting message lanes between two Substrate-based chains. + use crate::messages_source::SubstrateMessagesProof; use crate::messages_target::SubstrateMessagesReceivingProof; use crate::on_demand_headers::OnDemandHeadersRelay; @@ -57,6 +59,7 @@ pub struct MessagesRelayParams { /// Message sync pipeline for Substrate <-> Substrate relays. pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { + /// Underlying generic message lane. type MessageLane: MessageLane; /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 279b2c45e0fa8..08e4964de747c 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -298,6 +298,11 @@ fn prepare_dummy_messages_delivery_proof() -> SubstrateMes ) } +/// Read best blocks from given client. +/// +/// This function assumes that the chain that is followed by the `self_client` has +/// bridge GRANDPA pallet deployed and it provides `best_finalized_header_id_method_name` +/// runtime API to read best finalized Bridged chain header. pub async fn read_client_state( self_client: &Client, best_finalized_header_id_method_name: &str, From 90fbf8ce7409b2bef36d162c08b2fad05bcf5036 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 Aug 2021 12:19:20 +0300 Subject: [PATCH 0537/1210] upgrade currency exchange pallet to frame v2 (#1097) --- modules/currency-exchange/src/benchmarking.rs | 12 +- modules/currency-exchange/src/lib.rs | 152 ++++++++++-------- 2 files changed, 89 insertions(+), 75 deletions(-) diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index 574ae93f6ee0c..db8b2256c8074 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -18,12 +18,10 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{ - Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Instance, Pallet as CurrencyExchangePallet, -}; +use super::{Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Pallet as CurrencyExchangePallet}; use sp_std::prelude::*; -use frame_benchmarking::{account, benchmarks_instance}; +use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_system::RawOrigin; const SEED: u32 = 0; @@ -31,7 +29,7 @@ const WORST_TX_SIZE_FACTOR: u32 = 1000; const WORST_PROOF_SIZE_FACTOR: u32 = 1000; /// Pallet we're benchmarking here. -pub struct Pallet, I: Instance>(CurrencyExchangePallet); +pub struct Pallet, I: 'static>(CurrencyExchangePallet); /// Proof benchmarking parameters. pub struct ProofParams { @@ -48,14 +46,14 @@ pub struct ProofParams { } /// Config that must be implemented by runtime. -pub trait Config: CurrencyExchangeConfig { +pub trait Config: CurrencyExchangeConfig { /// Prepare proof for importing exchange transaction. fn make_proof( proof_params: ProofParams, ) -> <>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof; } -benchmarks_instance! { +benchmarks_instance_pallet! { // Benchmark `import_peer_transaction` extrinsic with the best possible conditions: // * Proof is the transaction itself. // * Transaction has minimal size. diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 9a8af5ba5016f..290e1a9bc9526 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -22,8 +22,7 @@ use bp_currency_exchange::{ CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, }; use bp_header_chain::InclusionProofVerifier; -use frame_support::{decl_error, decl_module, decl_storage, ensure}; -use sp_runtime::DispatchResult; +use frame_support::ensure; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; @@ -34,61 +33,53 @@ pub trait OnTransactionSubmitted { fn on_valid_transaction_submitted(submitter: AccountId); } -/// The module configuration trait -pub trait Config: frame_system::Config { - /// Handler for transaction submission result. - type OnTransactionSubmitted: OnTransactionSubmitted; - /// Represents the blockchain that we'll be exchanging currency with. - type PeerBlockchain: InclusionProofVerifier; - /// Peer blockchain transaction parser. - type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< - Transaction = ::Transaction, - >; - /// Map between blockchains recipients. - type RecipientsMap: RecipientsMap< - PeerRecipient = ::Recipient, - Recipient = Self::AccountId, - >; - /// This blockchain currency amount type. - type Amount; - /// Converter from peer blockchain currency type into current blockchain currency type. - type CurrencyConverter: CurrencyConverter< - SourceAmount = ::Amount, - TargetAmount = Self::Amount, - >; - /// Something that could grant money. - type DepositInto: DepositInto; -} +pub use pallet::*; -decl_error! { - pub enum Error for Pallet, I: Instance> { - /// Invalid peer blockchain transaction provided. - InvalidTransaction, - /// Peer transaction has invalid amount. - InvalidAmount, - /// Peer transaction has invalid recipient. - InvalidRecipient, - /// Cannot map from peer recipient to this blockchain recipient. - FailedToMapRecipients, - /// Failed to convert from peer blockchain currency to this blockchain currency. - FailedToConvertCurrency, - /// Deposit has failed. - DepositFailed, - /// Deposit has partially failed (changes to recipient account were made). - DepositPartiallyFailed, - /// Transaction is not finalized. - UnfinalizedTransaction, - /// Transaction funds are already claimed. - AlreadyClaimed, +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// Handler for transaction submission result. + type OnTransactionSubmitted: OnTransactionSubmitted; + /// Represents the blockchain that we'll be exchanging currency with. + type PeerBlockchain: InclusionProofVerifier; + /// Peer blockchain transaction parser. + type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< + Transaction = ::Transaction, + >; + /// Map between blockchains recipients. + type RecipientsMap: RecipientsMap< + PeerRecipient = ::Recipient, + Recipient = Self::AccountId, + >; + /// This blockchain currency amount type. + type Amount; + /// Converter from peer blockchain currency type into current blockchain currency type. + type CurrencyConverter: CurrencyConverter< + SourceAmount = ::Amount, + TargetAmount = Self::Amount, + >; + /// Something that could grant money. + type DepositInto: DepositInto; } -} -decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet {} + + #[pallet::call] + impl, I: 'static> Pallet { /// Imports lock fund transaction of the peer blockchain. - #[weight = 0] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) + #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_peer_transaction( - origin, + origin: OriginFor, proof: <>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, ) -> DispatchResult { let submitter = frame_system::ensure_signed(origin)?; @@ -122,16 +113,41 @@ decl_module! { Ok(()) } } -} -decl_storage! { - trait Store for Pallet, I: Instance = DefaultInstance> as Bridge { - /// All transfers that have already been claimed. - Transfers: map hasher(blake2_128_concat) ::Id => (); + #[pallet::error] + pub enum Error { + /// Invalid peer blockchain transaction provided. + InvalidTransaction, + /// Peer transaction has invalid amount. + InvalidAmount, + /// Peer transaction has invalid recipient. + InvalidRecipient, + /// Cannot map from peer recipient to this blockchain recipient. + FailedToMapRecipients, + /// Failed to convert from peer blockchain currency to this blockchain currency. + FailedToConvertCurrency, + /// Deposit has failed. + DepositFailed, + /// Deposit has partially failed (changes to recipient account were made). + DepositPartiallyFailed, + /// Transaction is not finalized. + UnfinalizedTransaction, + /// Transaction funds are already claimed. + AlreadyClaimed, } + + /// All transfers that have already been claimed. + #[pallet::storage] + pub(super) type Transfers, I: 'static = ()> = StorageMap< + _, + Blake2_128Concat, + ::Id, + (), + ValueQuery, + >; } -impl, I: Instance> Pallet { +impl, I: 'static> Pallet { /// Returns true if currency exchange module is able to import given transaction proof in /// its current state. pub fn filter_transaction_proof( @@ -151,7 +167,7 @@ impl, I: Instance> Pallet { } } -impl, I: Instance> From for Error { +impl, I: 'static> From for Error { fn from(error: ExchangeError) -> Self { match error { ExchangeError::InvalidTransaction => Error::InvalidTransaction, @@ -170,7 +186,7 @@ impl OnTransactionSubmitted for () { } /// Exchange deposit details. -struct DepositDetails, I: Instance> { +struct DepositDetails, I: 'static> { /// Transfer id. pub transfer_id: ::Id, /// Transfer recipient. @@ -181,7 +197,7 @@ struct DepositDetails, I: Instance> { /// Verify and parse transaction proof, preparing everything required for importing /// this transaction proof. -fn prepare_deposit_details, I: Instance>( +fn prepare_deposit_details, I: 'static>( proof: &<>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, ) -> Result, Error> { // ensure that transaction is included in finalized block that we know of @@ -238,7 +254,7 @@ mod tests { impl OnTransactionSubmitted for DummyTransactionSubmissionHandler { fn on_valid_transaction_submitted(submitter: AccountId) { - Transfers::::insert(submitter, ()); + Transfers::::insert(submitter, ()); } } @@ -394,7 +410,7 @@ mod tests { new_test_ext().execute_with(|| { assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (false, transaction(0))), - Error::::UnfinalizedTransaction, + Error::::UnfinalizedTransaction, ); }); } @@ -407,7 +423,7 @@ mod tests { Origin::signed(SUBMITTER), (true, transaction(INVALID_TRANSACTION_ID)), ), - Error::::InvalidTransaction, + Error::::InvalidTransaction, ); }); } @@ -421,7 +437,7 @@ mod tests { Origin::signed(SUBMITTER), (true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)), ), - Error::::AlreadyClaimed, + Error::::AlreadyClaimed, ); }); } @@ -433,7 +449,7 @@ mod tests { transaction.recipient = UNKNOWN_RECIPIENT_ID; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToMapRecipients, + Error::::FailedToMapRecipients, ); }); } @@ -445,7 +461,7 @@ mod tests { transaction.amount = INVALID_AMOUNT; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToConvertCurrency, + Error::::FailedToConvertCurrency, ); }); } @@ -457,7 +473,7 @@ mod tests { transaction.amount = MAX_DEPOSIT_AMOUNT + 1; assert_noop!( Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::DepositFailed, + Error::::DepositFailed, ); }); } From 9a11fb7fbf11a03cf98fa9e48d56acd21b44ad67 Mon Sep 17 00:00:00 2001 From: Ignacio Palacios Date: Wed, 1 Sep 2021 14:22:40 +0800 Subject: [PATCH 0538/1210] README fix (#1100) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e71563705df28..fe568dd220403 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ Finally, we can run the message relayers. ```bash ./deployments/local-scripts/relay-messages-millau-to-rialto.sh -./deployments/local-scripts/relay-messages-millau-to-rialto.sh +./deployments/local-scripts/relay-messages-rialto-to-millau.sh ``` You will also see the message lane relayers listening for new messages. From 84c7e385dfe356026c715a5d7ad833e62aaca84e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Sep 2021 11:49:09 +0300 Subject: [PATCH 0539/1210] [BREAKING] Migrate messages pallet to frame v2 (#1088) * get rid of frame_support::traits::Instance usage in messaging * migrate messages pallet to frame v2 * fix benchmarks * remove dummy event + add Parameter to metadata * review * typo --- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 2 +- bin/rialto/runtime/src/lib.rs | 17 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/src/messages.rs | 20 +- bin/runtime-common/src/messages_api.rs | 3 +- modules/messages/src/benchmarking.rs | 20 +- modules/messages/src/inbound_lane.rs | 4 +- modules/messages/src/lib.rs | 840 +++++++++--------- primitives/chain-millau/src/lib.rs | 3 + primitives/chain-rialto/src/lib.rs | 3 + primitives/chain-rococo/src/lib.rs | 3 + primitives/chain-wococo/src/lib.rs | 3 + .../src/chains/millau_messages_to_rialto.rs | 12 +- .../src/chains/rialto_messages_to_millau.rs | 12 +- .../src/chains/rococo_messages_to_wococo.rs | 20 +- .../src/chains/wococo_messages_to_rococo.rs | 20 +- relays/client-rococo/src/runtime.rs | 3 - relays/client-wococo/src/runtime.rs | 3 - .../lib-substrate-relay/src/messages_lane.rs | 5 + .../src/messages_source.rs | 34 +- .../src/messages_target.rs | 29 +- 24 files changed, 528 insertions(+), 536 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 846dfa69302fd..583510fc34b4f 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -136,7 +136,7 @@ impl Alternative { get_account_id_from_seed::("Harry//stash"), pallet_bridge_messages::Pallet::< millau_runtime::Runtime, - pallet_bridge_messages::DefaultInstance, + millau_runtime::WithRialtoMessagesInstance, >::relayer_fund_account_id(), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Alice"), diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index cc004b8629703..ed7580906f570 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -366,7 +366,7 @@ parameter_types! { } /// Instance of the messages pallet used to relay messages to/from Rialto chain. -pub type WithRialtoMessagesInstance = pallet_bridge_messages::DefaultInstance; +pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 5b3d08688c826..34b3b231c8124 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -80,10 +80,10 @@ impl MessageBridge for WithRialtoMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; type BridgedChain = Rialto; - type BridgedMessagesInstance = crate::WithRialtoMessagesInstance; fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 99645e14cba4c..60b1af24e3921 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -137,7 +137,7 @@ impl Alternative { get_account_id_from_seed::("Harry//stash"), pallet_bridge_messages::Pallet::< rialto_runtime::Runtime, - pallet_bridge_messages::DefaultInstance, + rialto_runtime::WithMillauMessagesInstance, >::relayer_fund_account_id(), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Alice"), diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 1a34061592ebc..75ba22389a2e7 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -494,7 +494,7 @@ parameter_types! { } /// Instance of the messages pallet used to relay messages to/from Millau chain. -pub type WithMillauMessagesInstance = pallet_bridge_messages::DefaultInstance; +pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; @@ -1021,14 +1021,12 @@ impl_runtime_apis! { Self::endow_account(&rialto_public.clone().into_account()); } - let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key::< - ::BridgedMessagesInstance, - >( + let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key( + ::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, message_key.nonce, ).0; - let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key::< - ::BridgedMessagesInstance, - >( + let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key( + ::BRIDGED_MESSAGES_PALLET_NAME, &lane_id, ).0; @@ -1074,9 +1072,8 @@ impl_runtime_apis! { prepare_message_delivery_proof::( params, - |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key::< - ::BridgedMessagesInstance, - >( + |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key( + ::BRIDGED_MESSAGES_PALLET_NAME, &lane_id, ).0, |state_root| bp_millau::Header::new( diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index ac79d8eca6b68..bb24a95f9ccba 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -80,10 +80,10 @@ impl MessageBridge for WithMillauMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; type ThisChain = Rialto; type BridgedChain = Millau; - type BridgedMessagesInstance = crate::WithMillauMessagesInstance; fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 974920c528cce..a7591b2e57e6e 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -32,7 +32,7 @@ use bp_runtime::{ }; use codec::{Decode, Encode}; use frame_support::{ - traits::{Currency, ExistenceRequirement, Instance}, + traits::{Currency, ExistenceRequirement}, weights::{Weight, WeightToFeePolynomial}, RuntimeDebug, }; @@ -53,13 +53,15 @@ pub trait MessageBridge { const THIS_CHAIN_ID: ChainId; /// Identifier of the Bridged chain. const BRIDGED_CHAIN_ID: ChainId; + /// Name of the paired messages pallet instance at the Bridged chain. + /// + /// Should be the name that is used in the `construct_runtime!()` macro. + const BRIDGED_MESSAGES_PALLET_NAME: &'static str; /// This chain in context of message bridge. type ThisChain: ThisChainWithMessages; /// Bridged chain in context of message bridge. type BridgedChain: BridgedChainWithMessages; - /// Instance of the `pallet-bridge-messages` pallet at the Bridged chain. - type BridgedMessagesInstance: Instance; /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; @@ -391,7 +393,7 @@ pub mod source { // Messages delivery proof is just proof of single storage key read => any error // is fatal. let storage_inbound_lane_data_key = - pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&lane); + pallet_bridge_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane); let raw_inbound_lane_data = storage .read_value(storage_inbound_lane_data_key.0.as_ref()) .map_err(|_| "Failed to read inbound lane state from storage proof")? @@ -563,7 +565,6 @@ pub mod target { ) -> Result>>>, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - ThisRuntime: pallet_bridge_messages::Config, HashOf>: Into>::BridgedChain>>, { @@ -628,14 +629,15 @@ pub mod target { { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { let storage_outbound_lane_data_key = - pallet_bridge_messages::storage_keys::outbound_lane_data_key::(lane_id); + pallet_bridge_messages::storage_keys::outbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, lane_id); self.storage .read_value(storage_outbound_lane_data_key.0.as_ref()) .ok()? } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - let storage_message_key = pallet_bridge_messages::storage_keys::message_key::( + let storage_message_key = pallet_bridge_messages::storage_keys::message_key( + B::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, message_key.nonce, ); @@ -745,10 +747,10 @@ mod tests { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = *b"this"; const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = ThisChain; type BridgedChain = BridgedChain; - type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance; fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) @@ -763,10 +765,10 @@ mod tests { const RELAYER_FEE_PERCENT: u32 = 20; const THIS_CHAIN_ID: ChainId = *b"brdg"; const BRIDGED_CHAIN_ID: ChainId = *b"this"; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = BridgedChain; type BridgedChain = ThisChain; - type BridgedMessagesInstance = pallet_bridge_messages::DefaultInstance; fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { unreachable!() diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index d0f4180b5c143..b09a88e627959 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -20,7 +20,6 @@ use crate::messages::{source::FromThisChainMessagePayload, MessageBridge}; use bp_messages::{LaneId, MessageDetails, MessageNonce}; use codec::Decode; -use frame_support::traits::Instance; use sp_std::vec::Vec; /// Implementation of the `To*OutboundLaneApi::message_details`. @@ -31,7 +30,7 @@ pub fn outbound_message_details( ) -> Vec> where Runtime: pallet_bridge_messages::Config, - MessagesPalletInstance: Instance, + MessagesPalletInstance: 'static, BridgeConfig: MessageBridge, { (begin..=end) diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index e2a3237eb064c..4adf073191bc7 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -19,7 +19,7 @@ use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH; use crate::{ inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, outbound_lane::ReceivalConfirmationResult, - Call, Instance, + Call, }; use bp_messages::{ @@ -27,7 +27,7 @@ use bp_messages::{ MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::messages::DispatchFeePayment; -use frame_benchmarking::{account, benchmarks_instance}; +use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; use sp_std::{ @@ -43,7 +43,7 @@ pub const MESSAGE_FEE: u64 = 100_000_000_000; const SEED: u32 = 0; /// Pallet we're benchmarking here. -pub struct Pallet, I: crate::Instance>(crate::Pallet); +pub struct Pallet, I: 'static>(crate::Pallet); /// Proof size requirements. pub enum ProofSize { @@ -91,7 +91,7 @@ pub struct MessageDeliveryProofParams { } /// Trait that must be implemented by runtime. -pub trait Config: crate::Config { +pub trait Config: crate::Config { /// Lane id to use in benchmarks. fn bench_lane_id() -> LaneId { Default::default() @@ -123,7 +123,7 @@ pub trait Config: crate::Config { fn is_message_dispatched(nonce: MessageNonce) -> bool; } -benchmarks_instance! { +benchmarks_instance_pallet! { // // Benchmarks that are used directly by the runtime. // @@ -898,7 +898,7 @@ benchmarks_instance! { } } -fn send_regular_message, I: Instance>() { +fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); outbound_lane.send_message(MessageData { payload: vec![], @@ -906,7 +906,7 @@ fn send_regular_message, I: Instance>() { }); } -fn send_regular_message_with_payload, I: Instance>(payload: Vec) { +fn send_regular_message_with_payload, I: 'static>(payload: Vec) { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); outbound_lane.send_message(MessageData { payload, @@ -914,7 +914,7 @@ fn send_regular_message_with_payload, I: Instance>(payload: Vec }); } -fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { +fn confirm_message_delivery, I: 'static>(nonce: MessageNonce) { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); let latest_received_nonce = outbound_lane.data().latest_received_nonce; let mut relayers = VecDeque::with_capacity((nonce - latest_received_nonce) as usize); @@ -930,7 +930,7 @@ fn confirm_message_delivery, I: Instance>(nonce: MessageNonce) { )); } -fn receive_messages, I: Instance>(nonce: MessageNonce) { +fn receive_messages, I: 'static>(nonce: MessageNonce) { let mut inbound_lane_storage = inbound_lane_storage::(T::bench_lane_id()); inbound_lane_storage.set_data(InboundLaneData { relayers: vec![UnrewardedRelayer { @@ -943,7 +943,7 @@ fn receive_messages, I: Instance>(nonce: MessageNonce) { }); } -fn ensure_relayer_rewarded, I: Instance>(relayer_id: &T::AccountId, old_balance: &T::OutboundMessageFee) { +fn ensure_relayer_rewarded, I: 'static>(relayer_id: &T::AccountId, old_balance: &T::OutboundMessageFee) { let new_balance = T::account_balance(relayer_id); assert!( new_balance > *old_balance, diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 83d17dc3c06c2..ae5de1c15214e 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -179,11 +179,11 @@ mod tests { dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C, }, - DefaultInstance, RuntimeInboundLaneStorage, + RuntimeInboundLaneStorage, }; fn receive_regular_message( - lane: &mut InboundLane>, + lane: &mut InboundLane>, nonce: MessageNonce, ) { assert_eq!( diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 8f7a6c8b7121a..7c6bacfb66da0 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -56,15 +56,8 @@ use bp_messages::{ }; use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; -use frame_support::{ - decl_error, decl_event, decl_module, decl_storage, - dispatch::DispatchResultWithPostInfo, - ensure, fail, - traits::Get, - weights::{DispatchClass, Pays, PostDispatchInfo, Weight}, - Parameter, StorageMap, -}; -use frame_system::{ensure_signed, RawOrigin}; +use frame_support::{fail, traits::Get, weights::PostDispatchInfo}; +use frame_system::RawOrigin; use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::BadOrigin; use sp_std::{cell::RefCell, cmp::PartialOrd, marker::PhantomData, prelude::*}; @@ -82,223 +75,158 @@ pub mod benchmarking; #[cfg(test)] mod mock; -/// The module configuration trait -pub trait Config: frame_system::Config { - // General types - - /// They are overarching event type. - type Event: From> + Into<::Event>; - /// Benchmarks results from runtime we're plugged into. - type WeightInfo: WeightInfoExt; - /// Pallet parameter that is opaque to the pallet itself, but may be used by the runtime - /// for integrating the pallet. - /// - /// All pallet parameters may only be updated either by the root, or by the pallet owner. - type Parameter: MessagesParameter; - - /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs - /// whenever new message is sent. The reason is that if you want to use lane, you should - /// be ready to pay for its maintenance. - type MaxMessagesToPruneAtOnce: Get; - /// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the - /// relayer has delivered messages, but either confirmations haven't been delivered back to the - /// source chain, or we haven't received reward confirmations yet. - /// - /// This constant limits maximal number of entries in the `InboundLaneData::relayers`. Keep - /// in mind that the same relayer account may take several (non-consecutive) entries in this - /// set. - type MaxUnrewardedRelayerEntriesAtInboundLane: Get; - /// Maximal number of unconfirmed messages at inbound lane. Unconfirmed means that the - /// message has been delivered, but either confirmations haven't been delivered back to the - /// source chain, or we haven't received reward confirmations for these messages yet. - /// - /// This constant limits difference between last message from last entry of the - /// `InboundLaneData::relayers` and first message at the first entry. - /// - /// There is no point of making this parameter lesser than MaxUnrewardedRelayerEntriesAtInboundLane, - /// because then maximal number of relayer entries will be limited by maximal number of messages. - /// - /// This value also represents maximal number of messages in single delivery transaction. Transaction - /// that is declaring more messages than this value, will be rejected. Even if these messages are - /// from different lanes. - type MaxUnconfirmedMessagesAtInboundLane: Get; - - /// Payload type of outbound messages. This payload is dispatched on the bridged chain. - type OutboundPayload: Parameter + Size; - /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Default + From + PartialOrd + Parameter + SaturatingAdd + Zero; - - /// Payload type of inbound messages. This payload is dispatched on this chain. - type InboundPayload: Decode; - /// Message fee type of inbound messages. This fee is paid on the bridged chain. - type InboundMessageFee: Decode; - /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the bridged chain. - type InboundRelayer: Parameter; - - /// A type which can be turned into an AccountId from a 256-bit hash. - /// - /// Used when deriving the shared relayer fund account. - type AccountIdConverter: sp_runtime::traits::Convert; - - // Types that are used by outbound_lane (on source chain). - - /// Target header chain. - type TargetHeaderChain: TargetHeaderChain; - /// Message payload verifier. - type LaneMessageVerifier: LaneMessageVerifier; - /// Message delivery payment. - type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment; - /// Handler for delivered messages. - type OnDeliveryConfirmed: OnDeliveryConfirmed; - - // Types that are used by inbound_lane (on target chain). - - /// Source header chain, as it is represented on target chain. - type SourceHeaderChain: SourceHeaderChain; - /// Message dispatch. - type MessageDispatch: MessageDispatch< - Self::AccountId, - Self::InboundMessageFee, - DispatchPayload = Self::InboundPayload, - >; - - /// Chain Id for the bridged chain. - type BridgedChainId: Get; -} - -/// Shortcut to messages proof type for Config. -type MessagesProofOf = - <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; -/// Shortcut to messages delivery proof type for Config. -type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< - >::OutboundPayload, - ::AccountId, ->>::MessagesDeliveryProof; - -decl_error! { - pub enum Error for Pallet, I: Instance> { - /// All pallet operations are halted. - Halted, - /// Message has been treated as invalid by chain verifier. - MessageRejectedByChainVerifier, - /// Message has been treated as invalid by lane verifier. - MessageRejectedByLaneVerifier, - /// Submitter has failed to pay fee for delivering and dispatching messages. - FailedToWithdrawMessageFee, - /// The transaction brings too many messages. - TooManyMessagesInTheProof, - /// Invalid messages has been submitted. - InvalidMessagesProof, - /// Invalid messages delivery proof has been submitted. - InvalidMessagesDeliveryProof, - /// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane). - InvalidUnrewardedRelayers, - /// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call. - InvalidUnrewardedRelayersState, - /// The message someone is trying to work with (i.e. increase fee) is already-delivered. - MessageIsAlreadyDelivered, - /// The message someone is trying to work with (i.e. increase fee) is not yet sent. - MessageIsNotYetSent, - /// The number of actually confirmed messages is going to be larger than the number of messages in the proof. - /// This may mean that this or bridged chain storage is corrupted. - TryingToConfirmMoreMessagesThanExpected, - } -} +pub use pallet::*; -decl_storage! { - trait Store for Pallet, I: Instance = DefaultInstance> as BridgeMessages { - /// Optional pallet owner. - /// - /// Pallet owner has a right to halt all pallet operations and then resume it. If it is - /// `None`, then there are no direct ways to halt/resume pallet operations, but other - /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt - /// flag directly or call the `halt_operations`). - pub PalletOwner get(fn module_owner): Option; - /// The current operating mode of the pallet. - /// - /// Depending on the mode either all, some, or no transactions will be allowed. - pub PalletOperatingMode get(fn operating_mode) config(): OperatingMode; - /// Map of lane id => inbound lane data. - pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData; - /// Map of lane id => outbound lane data. - pub OutboundLanes: map hasher(blake2_128_concat) LaneId => OutboundLaneData; - /// All queued outbound messages. - pub OutboundMessages: map hasher(blake2_128_concat) MessageKey => Option>; - } - add_extra_genesis { - config(phantom): sp_std::marker::PhantomData; - config(owner): Option; - build(|config| { - if let Some(ref owner) = config.owner { - >::put(owner); - } - }) - } -} +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -decl_event!( - pub enum Event - where - AccountId = ::AccountId, - Parameter = >::Parameter, - { - /// Pallet parameter has been updated. - ParameterUpdated(Parameter), - /// Message has been accepted and is waiting to be delivered. - MessageAccepted(LaneId, MessageNonce), - /// Messages in the inclusive range have been delivered to the bridged chain. - MessagesDelivered(LaneId, DeliveredMessages), - /// Phantom member, never used. - Dummy(PhantomData<(AccountId, I)>), - } -); + #[pallet::config] + pub trait Config: frame_system::Config { + // General types -decl_module! { - pub struct Module, I: Instance = DefaultInstance> for enum Call where origin: T::Origin { - /// Deposit one of this module's events by using the default implementation. - fn deposit_event() = default; + /// The overarching event type. + type Event: From> + IsType<::Event>; + /// Benchmarks results from runtime we're plugged into. + type WeightInfo: WeightInfoExt; /// Gets the chain id value from the instance. - const BridgedChainId: ChainId = T::BridgedChainId::get(); - + #[pallet::constant] + type BridgedChainId: Get; + /// Pallet parameter that is opaque to the pallet itself, but may be used by the runtime + /// for integrating the pallet. + /// + /// All pallet parameters may only be updated either by the root, or by the pallet owner. + type Parameter: MessagesParameter; + + /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs + /// whenever new message is sent. The reason is that if you want to use lane, you should + /// be ready to pay for its maintenance. + type MaxMessagesToPruneAtOnce: Get; + /// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the + /// relayer has delivered messages, but either confirmations haven't been delivered back to the + /// source chain, or we haven't received reward confirmations yet. + /// + /// This constant limits maximal number of entries in the `InboundLaneData::relayers`. Keep + /// in mind that the same relayer account may take several (non-consecutive) entries in this + /// set. + type MaxUnrewardedRelayerEntriesAtInboundLane: Get; + /// Maximal number of unconfirmed messages at inbound lane. Unconfirmed means that the + /// message has been delivered, but either confirmations haven't been delivered back to the + /// source chain, or we haven't received reward confirmations for these messages yet. + /// + /// This constant limits difference between last message from last entry of the + /// `InboundLaneData::relayers` and first message at the first entry. + /// + /// There is no point of making this parameter lesser than MaxUnrewardedRelayerEntriesAtInboundLane, + /// because then maximal number of relayer entries will be limited by maximal number of messages. + /// + /// This value also represents maximal number of messages in single delivery transaction. Transaction + /// that is declaring more messages than this value, will be rejected. Even if these messages are + /// from different lanes. + type MaxUnconfirmedMessagesAtInboundLane: Get; + + /// Payload type of outbound messages. This payload is dispatched on the bridged chain. + type OutboundPayload: Parameter + Size; + /// Message fee type of outbound messages. This fee is paid on this chain. + type OutboundMessageFee: Default + From + PartialOrd + Parameter + SaturatingAdd + Zero; + + /// Payload type of inbound messages. This payload is dispatched on this chain. + type InboundPayload: Decode; + /// Message fee type of inbound messages. This fee is paid on the bridged chain. + type InboundMessageFee: Decode; + /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the bridged chain. + type InboundRelayer: Parameter; + + /// A type which can be turned into an AccountId from a 256-bit hash. + /// + /// Used when deriving the shared relayer fund account. + type AccountIdConverter: sp_runtime::traits::Convert; + + // Types that are used by outbound_lane (on source chain). + + /// Target header chain. + type TargetHeaderChain: TargetHeaderChain; + /// Message payload verifier. + type LaneMessageVerifier: LaneMessageVerifier; + /// Message delivery payment. + type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< + Self::AccountId, + Self::OutboundMessageFee, + >; + /// Handler for delivered messages. + type OnDeliveryConfirmed: OnDeliveryConfirmed; + + // Types that are used by inbound_lane (on target chain). + + /// Source header chain, as it is represented on target chain. + type SourceHeaderChain: SourceHeaderChain; + /// Message dispatch. + type MessageDispatch: MessageDispatch< + Self::AccountId, + Self::InboundMessageFee, + DispatchPayload = Self::InboundPayload, + >; + } + + /// Shortcut to messages proof type for Config. + type MessagesProofOf = + <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; + /// Shortcut to messages delivery proof type for Config. + type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< + >::OutboundPayload, + ::AccountId, + >>::MessagesDeliveryProof; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet { /// Ensure runtime invariants. fn on_runtime_upgrade() -> Weight { - let reads = T::MessageDeliveryAndDispatchPayment::initialize( - &Self::relayer_fund_account_id() - ); + let reads = T::MessageDeliveryAndDispatchPayment::initialize(&Self::relayer_fund_account_id()); T::DbWeight::get().reads(reads as u64) } + } + #[pallet::call] + impl, I: 'static> Pallet { /// Change `PalletOwner`. /// /// May only be called either by root, or by `PalletOwner`. - #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn set_owner(origin, new_owner: Option) { + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { ensure_owner_or_root::(origin)?; match new_owner { Some(new_owner) => { PalletOwner::::put(&new_owner); log::info!(target: "runtime::bridge-messages", "Setting pallet Owner to: {:?}", new_owner); - }, + } None => { PalletOwner::::kill(); log::info!(target: "runtime::bridge-messages", "Removed Owner of pallet."); - }, + } } + Ok(()) } /// Halt or resume all/some pallet operations. /// /// May only be called either by root, or by `PalletOwner`. - #[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)] - pub fn set_operating_mode(origin, operating_mode: OperatingMode) { + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_operating_mode(origin: OriginFor, operating_mode: OperatingMode) -> DispatchResult { ensure_owner_or_root::(origin)?; - >::put(operating_mode); + PalletOperatingMode::::put(operating_mode); log::info!( target: "runtime::bridge-messages", "Setting messages pallet operating mode to {:?}.", operating_mode, ); + Ok(()) } /// Update pallet parameter. @@ -306,17 +234,18 @@ decl_module! { /// May only be called either by root, or by `PalletOwner`. /// /// The weight is: single read for permissions check + 2 writes for parameter value and event. - #[weight = (T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational)] - pub fn update_pallet_parameter(origin, parameter: T::Parameter) { + #[pallet::weight((T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational))] + pub fn update_pallet_parameter(origin: OriginFor, parameter: T::Parameter) -> DispatchResult { ensure_owner_or_root::(origin)?; parameter.save(); - Self::deposit_event(RawEvent::ParameterUpdated(parameter)); + Self::deposit_event(Event::ParameterUpdated(parameter)); + Ok(()) } /// Send message over lane. - #[weight = T::WeightInfo::send_message_weight(payload)] + #[pallet::weight(T::WeightInfo::send_message_weight(payload))] pub fn send_message( - origin, + origin: OriginFor, lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -328,17 +257,16 @@ decl_module! { let mut actual_weight = T::WeightInfo::send_message_weight(&payload); // let's first check if message can be delivered to target chain - T::TargetHeaderChain::verify_message(&payload) - .map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Message to lane {:?} is rejected by target chain: {:?}", - lane_id, - err, - ); + T::TargetHeaderChain::verify_message(&payload).map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Message to lane {:?} is rejected by target chain: {:?}", + lane_id, + err, + ); - Error::::MessageRejectedByChainVerifier - })?; + Error::::MessageRejectedByChainVerifier + })?; // now let's enforce any additional lane rules let mut lane = outbound_lane::(lane_id); @@ -348,7 +276,8 @@ decl_module! { &lane_id, &lane.data(), &payload, - ).map_err(|err| { + ) + .map_err(|err| { log::trace!( target: "runtime::bridge-messages", "Message to lane {:?} is rejected by lane verifier: {:?}", @@ -364,7 +293,8 @@ decl_module! { &submitter, &delivery_and_dispatch_fee, &Self::relayer_fund_account_id(), - ).map_err(|err| { + ) + .map_err(|err| { log::trace!( target: "runtime::bridge-messages", "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", @@ -402,7 +332,7 @@ decl_module! { encoded_payload_len, ); - Self::deposit_event(RawEvent::MessageAccepted(lane_id, nonce)); + Self::deposit_event(Event::MessageAccepted(lane_id, nonce)); Ok(PostDispatchInfo { actual_weight: Some(actual_weight), @@ -411,9 +341,9 @@ decl_module! { } /// Pay additional fee for the message. - #[weight = T::WeightInfo::maximal_increase_message_fee()] + #[pallet::weight(T::WeightInfo::maximal_increase_message_fee())] pub fn increase_message_fee( - origin, + origin: OriginFor, lane_id: LaneId, nonce: MessageNonce, additional_fee: T::OutboundMessageFee, @@ -425,8 +355,14 @@ decl_module! { // if someone tries to pay for not-yet-sent message, we're rejeting this intention, or // we're risking to have mess in the storage let lane = outbound_lane::(lane_id); - ensure!(nonce > lane.data().latest_received_nonce, Error::::MessageIsAlreadyDelivered); - ensure!(nonce <= lane.data().latest_generated_nonce, Error::::MessageIsNotYetSent); + ensure!( + nonce > lane.data().latest_received_nonce, + Error::::MessageIsAlreadyDelivered + ); + ensure!( + nonce <= lane.data().latest_generated_nonce, + Error::::MessageIsNotYetSent + ); // withdraw additional fee from submitter let submitter = origin.into().map_err(|_| BadOrigin)?; @@ -434,7 +370,8 @@ decl_module! { &submitter, &additional_fee, &Self::relayer_fund_account_id(), - ).map_err(|err| { + ) + .map_err(|err| { log::trace!( target: "runtime::bridge-messages", "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", @@ -478,9 +415,9 @@ decl_module! { /// The weight of the call assumes that the transaction always brings outbound lane /// state update. Because of that, the submitter (relayer) has no benefit of not including /// this data in the transaction, so reward confirmations lags should be minimal. - #[weight = T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight)] + #[pallet::weight(T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight))] pub fn receive_messages_proof( - origin, + origin: OriginFor, relayer_id_at_bridged_chain: T::InboundRelayer, proof: MessagesProofOf, messages_count: u32, @@ -505,11 +442,7 @@ decl_module! { // // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible // to get pre-computed value (and it has been already computed by the executive). - let declared_weight = T::WeightInfo::receive_messages_proof_weight( - &proof, - messages_count, - dispatch_weight, - ); + let declared_weight = T::WeightInfo::receive_messages_proof_weight(&proof, messages_count, dispatch_weight); let mut actual_weight = declared_weight; // verify messages proof && convert proof into messages @@ -518,15 +451,15 @@ decl_module! { T::InboundMessageFee, T::InboundPayload, >(proof, messages_count) - .map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Rejecting invalid messages proof: {:?}", - err, - ); + .map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Rejecting invalid messages proof: {:?}", + err, + ); - Error::::InvalidMessagesProof - })?; + Error::::InvalidMessagesProof + })?; // dispatch messages and (optionally) update lane(s) state(s) let mut total_messages = 0; @@ -582,27 +515,28 @@ decl_module! { let (unspent_weight, refund_pay_dispatch_fee) = match receival_result { ReceivalResult::Dispatched(dispatch_result) => { valid_messages += 1; - (dispatch_result.unspent_weight, !dispatch_result.dispatch_fee_paid_during_dispatch) - }, + ( + dispatch_result.unspent_weight, + !dispatch_result.dispatch_fee_paid_during_dispatch, + ) + } ReceivalResult::InvalidNonce - | ReceivalResult::TooManyUnrewardedRelayers - | ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), + | ReceivalResult::TooManyUnrewardedRelayers + | ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), }; let unspent_weight = sp_std::cmp::min(unspent_weight, dispatch_weight); dispatch_weight_left -= dispatch_weight - unspent_weight; - actual_weight = actual_weight - .saturating_sub(unspent_weight) - .saturating_sub( - // delivery call weight formula assumes that the fee is paid at - // this (target) chain. If the message is prepaid at the source - // chain, let's refund relayer with this extra cost. - if refund_pay_dispatch_fee { - T::WeightInfo::pay_inbound_dispatch_fee_overhead() - } else { - 0 - } - ); + actual_weight = actual_weight.saturating_sub(unspent_weight).saturating_sub( + // delivery call weight formula assumes that the fee is paid at + // this (target) chain. If the message is prepaid at the source + // chain, let's refund relayer with this extra cost. + if refund_pay_dispatch_fee { + T::WeightInfo::pay_inbound_dispatch_fee_overhead() + } else { + 0 + }, + ); } } @@ -622,13 +556,13 @@ decl_module! { } /// Receive messages delivery proof from bridged chain. - #[weight = T::WeightInfo::receive_messages_delivery_proof_weight( + #[pallet::weight(T::WeightInfo::receive_messages_delivery_proof_weight( proof, relayers_state, T::DbWeight::get(), - )] + ))] pub fn receive_messages_delivery_proof( - origin, + origin: OriginFor, proof: MessagesDeliveryProofOf, relayers_state: UnrewardedRelayersState, ) -> DispatchResultWithPostInfo { @@ -644,11 +578,8 @@ decl_module! { // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible // to get pre-computed value (and it has been already computed by the executive). let single_message_callback_overhead = T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); - let declared_weight = T::WeightInfo::receive_messages_delivery_proof_weight( - &proof, - &relayers_state, - T::DbWeight::get(), - ); + let declared_weight = + T::WeightInfo::receive_messages_delivery_proof_weight(&proof, &relayers_state, T::DbWeight::get()); let mut actual_weight = declared_weight; let confirmation_relayer = ensure_signed(origin)?; @@ -665,8 +596,8 @@ decl_module! { // verify that the relayer has declared correct `lane_data::relayers` state // (we only care about total number of entries and messages, because this affects call weight) ensure!( - total_unrewarded_messages(&lane_data.relayers) - .unwrap_or(MessageNonce::MAX) == relayers_state.total_messages + total_unrewarded_messages(&lane_data.relayers).unwrap_or(MessageNonce::MAX) + == relayers_state.total_messages && lane_data.relayers.len() as MessageNonce == relayers_state.unrewarded_relayer_entries, Error::::InvalidUnrewardedRelayersState ); @@ -675,43 +606,38 @@ decl_module! { let mut lane = outbound_lane::(lane_id); let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); - let confirmed_messages = match lane.confirm_delivery( - relayers_state.total_messages, - last_delivered_nonce, - &lane_data.relayers, - ) { - ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages), - ReceivalConfirmationResult::NoNewConfirmations => None, - ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(to_confirm_messages_count) => { - log::trace!( - target: "runtime::bridge-messages", - "Messages delivery proof contains too many messages to confirm: {} vs declared {}", - to_confirm_messages_count, - relayers_state.total_messages, - ); + let confirmed_messages = + match lane.confirm_delivery(relayers_state.total_messages, last_delivered_nonce, &lane_data.relayers) { + ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages), + ReceivalConfirmationResult::NoNewConfirmations => None, + ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(to_confirm_messages_count) => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery proof contains too many messages to confirm: {} vs declared {}", + to_confirm_messages_count, + relayers_state.total_messages, + ); - fail!(Error::::TryingToConfirmMoreMessagesThanExpected); - }, - error => { - log::trace!( - target: "runtime::bridge-messages", - "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", - error, - ); + fail!(Error::::TryingToConfirmMoreMessagesThanExpected); + } + error => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", + error, + ); - fail!(Error::::InvalidUnrewardedRelayers); - }, - }; + fail!(Error::::InvalidUnrewardedRelayers); + } + }; if let Some(confirmed_messages) = confirmed_messages { // handle messages delivery confirmation - let preliminary_callback_overhead = relayers_state.total_messages.saturating_mul( - single_message_callback_overhead - ); - let actual_callback_weight = T::OnDeliveryConfirmed::on_messages_delivered( - &lane_id, - &confirmed_messages, - ); + let preliminary_callback_overhead = relayers_state + .total_messages + .saturating_mul(single_message_callback_overhead); + let actual_callback_weight = + T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); match preliminary_callback_overhead.checked_sub(actual_callback_weight) { Some(difference) if difference == 0 => (), Some(difference) => { @@ -724,7 +650,7 @@ decl_module! { difference, ); actual_weight -= difference; - }, + } None => { debug_assert!(false, "The delivery confirmation callback is wrong"); log::trace!( @@ -739,7 +665,7 @@ decl_module! { // emit 'delivered' event let received_range = confirmed_messages.begin..=confirmed_messages.end; - Self::deposit_event(RawEvent::MessagesDelivered(lane_id, confirmed_messages)); + Self::deposit_event(Event::MessagesDelivered(lane_id, confirmed_messages)); // remember to reward relayers that have delivered messages // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain @@ -751,10 +677,8 @@ decl_module! { // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); for nonce in nonce_begin..nonce_end + 1 { - let message_data = OutboundMessages::::get(MessageKey { - lane_id, - nonce, - }).expect("message was just confirmed; we never prune unconfirmed messages; qed"); + let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) + .expect("message was just confirmed; we never prune unconfirmed messages; qed"); relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); relayer_reward.messages += 1; } @@ -784,102 +708,199 @@ decl_module! { }) } } -} -impl, I: Instance> Pallet { - /// Get stored data of the outbound message with given nonce. - pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option> { - OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + #[pallet::metadata(T::Parameter = "Parameter")] + pub enum Event, I: 'static = ()> { + /// Pallet parameter has been updated. + ParameterUpdated(T::Parameter), + /// Message has been accepted and is waiting to be delivered. + MessageAccepted(LaneId, MessageNonce), + /// Messages in the inclusive range have been delivered to the bridged chain. + MessagesDelivered(LaneId, DeliveredMessages), } - /// Get nonce of the latest generated message at given outbound lane. - pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_generated_nonce + #[pallet::error] + pub enum Error { + /// All pallet operations are halted. + Halted, + /// Message has been treated as invalid by chain verifier. + MessageRejectedByChainVerifier, + /// Message has been treated as invalid by lane verifier. + MessageRejectedByLaneVerifier, + /// Submitter has failed to pay fee for delivering and dispatching messages. + FailedToWithdrawMessageFee, + /// The transaction brings too many messages. + TooManyMessagesInTheProof, + /// Invalid messages has been submitted. + InvalidMessagesProof, + /// Invalid messages delivery proof has been submitted. + InvalidMessagesDeliveryProof, + /// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane). + InvalidUnrewardedRelayers, + /// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call. + InvalidUnrewardedRelayersState, + /// The message someone is trying to work with (i.e. increase fee) is already-delivered. + MessageIsAlreadyDelivered, + /// The message someone is trying to work with (i.e. increase fee) is not yet sent. + MessageIsNotYetSent, + /// The number of actually confirmed messages is going to be larger than the number of messages in the proof. + /// This may mean that this or bridged chain storage is corrupted. + TryingToConfirmMoreMessagesThanExpected, } - /// Get nonce of the latest confirmed message at given outbound lane. - pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_received_nonce + /// Optional pallet owner. + /// + /// Pallet owner has a right to halt all pallet operations and then resume it. If it is + /// `None`, then there are no direct ways to halt/resume pallet operations, but other + /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt + /// flag directly or call the `halt_operations`). + #[pallet::storage] + #[pallet::getter(fn module_owner)] + pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId>; + + /// The current operating mode of the pallet. + /// + /// Depending on the mode either all, some, or no transactions will be allowed. + #[pallet::storage] + #[pallet::getter(fn operating_mode)] + pub type PalletOperatingMode, I: 'static = ()> = StorageValue<_, OperatingMode, ValueQuery>; + + /// Map of lane id => inbound lane data. + #[pallet::storage] + pub type InboundLanes, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, LaneId, InboundLaneData, ValueQuery>; + + /// Map of lane id => outbound lane data. + #[pallet::storage] + pub type OutboundLanes, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, LaneId, OutboundLaneData, ValueQuery>; + + /// All queued outbound messages. + #[pallet::storage] + pub type OutboundMessages, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, MessageKey, MessageData>; + + #[pallet::genesis_config] + pub struct GenesisConfig, I: 'static = ()> { + /// Initial pallet operating mode. + pub operating_mode: OperatingMode, + /// Initial pallet owner. + pub owner: Option, + /// Dummy marker. + pub phantom: sp_std::marker::PhantomData, + } + + #[cfg(feature = "std")] + impl, I: 'static> Default for GenesisConfig { + fn default() -> Self { + Self { + operating_mode: Default::default(), + owner: Default::default(), + phantom: Default::default(), + } + } } - /// Get nonce of the latest received message at given inbound lane. - pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_delivered_nonce() + #[pallet::genesis_build] + impl, I: 'static> GenesisBuild for GenesisConfig { + fn build(&self) { + PalletOperatingMode::::put(&self.operating_mode); + if let Some(ref owner) = self.owner { + PalletOwner::::put(owner); + } + } } - /// Get nonce of the latest confirmed message at given inbound lane. - pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_confirmed_nonce - } + impl, I: 'static> Pallet { + /// Get stored data of the outbound message with given nonce. + pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option> { + OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) + } - /// Get state of unrewarded relayers set. - pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { - let relayers = InboundLanes::::get(&lane).relayers; - bp_messages::UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + /// Get nonce of the latest generated message at given outbound lane. + pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { + OutboundLanes::::get(&lane).latest_generated_nonce } - } - /// AccountId of the shared relayer fund account. - /// - /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending - /// on the implementation it can be used to store relayers rewards. - /// See [InstantCurrencyPayments] for a concrete implementation. - pub fn relayer_fund_account_id() -> T::AccountId { - use sp_runtime::traits::Convert; - let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); - T::AccountIdConverter::convert(encoded_id) + /// Get nonce of the latest confirmed message at given outbound lane. + pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { + OutboundLanes::::get(&lane).latest_received_nonce + } + + /// Get nonce of the latest received message at given inbound lane. + pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { + InboundLanes::::get(&lane).last_delivered_nonce() + } + + /// Get nonce of the latest confirmed message at given inbound lane. + pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { + InboundLanes::::get(&lane).last_confirmed_nonce + } + + /// Get state of unrewarded relayers set. + pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { + let relayers = InboundLanes::::get(&lane).relayers; + bp_messages::UnrewardedRelayersState { + unrewarded_relayer_entries: relayers.len() as _, + messages_in_oldest_entry: relayers + .front() + .map(|entry| 1 + entry.messages.end - entry.messages.begin) + .unwrap_or(0), + total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + } + } + + /// AccountId of the shared relayer fund account. + /// + /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending + /// on the implementation it can be used to store relayers rewards. + /// See [InstantCurrencyPayments] for a concrete implementation. + pub fn relayer_fund_account_id() -> T::AccountId { + use sp_runtime::traits::Convert; + let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); + T::AccountIdConverter::convert(encoded_id) + } } } /// Getting storage keys for messages and lanes states. These keys are normally used when building /// messages and lanes states proofs. -/// -/// Keep in mind that all functions in this module are **NOT** using passed `T` argument, so any -/// runtime can be passed. E.g. if you're verifying proof from Runtime1 in Runtime2, you only have -/// access to Runtime2 and you may pass it to the functions, where required. This is because our -/// maps are not using any Runtime-specific data in the keys. -/// -/// On the other side, passing correct instance is required. So if proof has been crafted by the -/// Instance1, you should verify it using Instance1. This is inconvenient if you're using different -/// instances on different sides of the bridge. I.e. in Runtime1 it is Instance2, but on Runtime2 -/// it is Instance42. But there's no other way, but to craft this key manually (which is what I'm -/// trying to avoid here) - by using strings like "Instance2", "OutboundMessages", etc. pub mod storage_keys { use super::*; - use frame_support::{traits::Instance, StorageHasher}; + use frame_support::StorageHasher; use sp_core::storage::StorageKey; /// Storage key of the outbound message in the runtime storage. - pub fn message_key(lane: &LaneId, nonce: MessageNonce) -> StorageKey { - storage_map_final_key::("OutboundMessages", &MessageKey { lane_id: *lane, nonce }.encode()) + pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { + storage_map_final_key( + pallet_prefix, + "OutboundMessages", + &MessageKey { lane_id: *lane, nonce }.encode(), + ) } /// Storage key of the outbound message lane state in the runtime storage. - pub fn outbound_lane_data_key(lane: &LaneId) -> StorageKey { - storage_map_final_key::("OutboundLanes", lane) + pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { + storage_map_final_key(pallet_prefix, "OutboundLanes", lane) } /// Storage key of the inbound message lane state in the runtime storage. - pub fn inbound_lane_data_key(lane: &LaneId) -> StorageKey { - storage_map_final_key::("InboundLanes", lane) + pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { + storage_map_final_key(pallet_prefix, "InboundLanes", lane) } /// This is a copypaste of the `frame_support::storage::generator::StorageMap::storage_map_final_key`. - fn storage_map_final_key(map_name: &str, key: &[u8]) -> StorageKey { - let module_prefix_hashed = frame_support::Twox128::hash(I::PREFIX.as_bytes()); + fn storage_map_final_key(pallet_prefix: &str, map_name: &str, key: &[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 key_hashed = frame_support::Blake2_128Concat::hash(key); let mut final_key = - Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); + Vec::with_capacity(pallet_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); - final_key.extend_from_slice(&module_prefix_hashed[..]); + 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()); @@ -888,7 +909,7 @@ pub mod storage_keys { } /// Ensure that the origin is either root, or `PalletOwner`. -fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result<(), BadOrigin> { +fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), Ok(RawOrigin::Signed(ref signer)) if Some(signer) == Pallet::::module_owner().as_ref() => Ok(()), @@ -897,8 +918,8 @@ fn ensure_owner_or_root, I: Instance>(origin: T::Origin) -> Result< } /// Ensure that the pallet is in normal operational mode. -fn ensure_normal_operating_mode, I: Instance>() -> Result<(), Error> { - if PalletOperatingMode::::get() != OperatingMode::Normal { +fn ensure_normal_operating_mode, I: 'static>() -> Result<(), Error> { + if PalletOperatingMode::::get() != OperatingMode::Normal { Err(Error::::Halted) } else { Ok(()) @@ -906,8 +927,8 @@ fn ensure_normal_operating_mode, I: Instance>() -> Result<(), Error } /// Ensure that the pallet is not halted. -fn ensure_not_halted, I: Instance>() -> Result<(), Error> { - if PalletOperatingMode::::get() == OperatingMode::Halted { +fn ensure_not_halted, I: 'static>() -> Result<(), Error> { + if PalletOperatingMode::::get() == OperatingMode::Halted { Err(Error::::Halted) } else { Ok(()) @@ -915,12 +936,12 @@ fn ensure_not_halted, I: Instance>() -> Result<(), Error> { } /// Creates new inbound lane object, backed by runtime storage. -fn inbound_lane, I: Instance>(lane_id: LaneId) -> InboundLane> { +fn inbound_lane, I: 'static>(lane_id: LaneId) -> InboundLane> { InboundLane::new(inbound_lane_storage::(lane_id)) } /// Creates new runtime inbound lane storage. -fn inbound_lane_storage, I: Instance>(lane_id: LaneId) -> RuntimeInboundLaneStorage { +fn inbound_lane_storage, I: 'static>(lane_id: LaneId) -> RuntimeInboundLaneStorage { RuntimeInboundLaneStorage { lane_id, cached_data: RefCell::new(None), @@ -929,7 +950,7 @@ fn inbound_lane_storage, I: Instance>(lane_id: LaneId) -> RuntimeIn } /// Creates new outbound lane object, backed by runtime storage. -fn outbound_lane, I: Instance>(lane_id: LaneId) -> OutboundLane> { +fn outbound_lane, I: 'static>(lane_id: LaneId) -> OutboundLane> { OutboundLane::new(RuntimeOutboundLaneStorage { lane_id, _phantom: Default::default(), @@ -937,13 +958,13 @@ fn outbound_lane, I: Instance>(lane_id: LaneId) -> OutboundLane, I = DefaultInstance> { +struct RuntimeInboundLaneStorage, I: 'static = ()> { lane_id: LaneId, cached_data: RefCell>>, _phantom: PhantomData, } -impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage { +impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage { type MessageFee = T::InboundMessageFee; type Relayer = T::InboundRelayer; @@ -983,12 +1004,12 @@ impl, I: Instance> InboundLaneStorage for RuntimeInboundLaneStorage } /// Runtime outbound lane storage. -struct RuntimeOutboundLaneStorage { +struct RuntimeOutboundLaneStorage { lane_id: LaneId, _phantom: PhantomData<(T, I)>, } -impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStorage { +impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage { type MessageFee = T::OutboundMessageFee; fn id(&self) -> LaneId { @@ -996,11 +1017,11 @@ impl, I: Instance> OutboundLaneStorage for RuntimeOutboundLaneStora } fn data(&self) -> OutboundLaneData { - OutboundLanes::::get(&self.lane_id) + OutboundLanes::::get(&self.lane_id) } fn set_data(&mut self, data: OutboundLaneData) { - OutboundLanes::::insert(&self.lane_id, data) + OutboundLanes::::insert(&self.lane_id, data) } #[cfg(test)] @@ -1063,7 +1084,7 @@ mod tests { PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; - use frame_support::{assert_noop, assert_ok}; + use frame_support::{assert_noop, assert_ok, weights::Weight}; use frame_system::{EventRecord, Pallet as System, Phase}; use hex_literal::hex; use sp_runtime::DispatchError; @@ -1076,7 +1097,7 @@ mod tests { fn send_regular_message() -> Weight { get_ready_for_events(); - let message_nonce = outbound_lane::(TEST_LANE_ID) + let message_nonce = outbound_lane::(TEST_LANE_ID) .data() .latest_generated_nonce + 1; @@ -1095,7 +1116,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, message_nonce)), + event: TestEvent::Messages(Event::MessageAccepted(TEST_LANE_ID, message_nonce)), topics: vec![], }], ); @@ -1138,10 +1159,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(RawEvent::MessagesDelivered( - TEST_LANE_ID, - DeliveredMessages::new(1, true), - )), + event: TestEvent::Messages(Event::MessagesDelivered(TEST_LANE_ID, DeliveredMessages::new(1, true),)), topics: vec![], }], ); @@ -1242,7 +1260,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(RawEvent::ParameterUpdated(parameter)), + event: TestEvent::Messages(Event::ParameterUpdated(parameter)), topics: vec![], }], ); @@ -1266,7 +1284,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(RawEvent::ParameterUpdated(parameter)), + event: TestEvent::Messages(Event::ParameterUpdated(parameter)), topics: vec![], }], ); @@ -1327,7 +1345,7 @@ mod tests { // send message first to be able to check that delivery_proof fails later send_regular_message(); - PalletOperatingMode::::put(OperatingMode::Halted); + PalletOperatingMode::::put(OperatingMode::Halted); assert_noop!( Pallet::::send_message( @@ -1336,12 +1354,12 @@ mod tests { REGULAR_PAYLOAD, REGULAR_PAYLOAD.declared_weight, ), - Error::::Halted, + Error::::Halted, ); assert_noop!( Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1,), - Error::::Halted, + Error::::Halted, ); assert_noop!( @@ -1352,7 +1370,7 @@ mod tests { 1, REGULAR_PAYLOAD.declared_weight, ), - Error::::Halted, + Error::::Halted, ); assert_noop!( @@ -1371,7 +1389,7 @@ mod tests { total_messages: 1, }, ), - Error::::Halted, + Error::::Halted, ); }); } @@ -1382,7 +1400,7 @@ mod tests { // send message first to be able to check that delivery_proof fails later send_regular_message(); - PalletOperatingMode::::put(OperatingMode::RejectingOutboundMessages); + PalletOperatingMode::::put(OperatingMode::RejectingOutboundMessages); assert_noop!( Pallet::::send_message( @@ -1391,7 +1409,7 @@ mod tests { REGULAR_PAYLOAD, REGULAR_PAYLOAD.declared_weight, ), - Error::::Halted, + Error::::Halted, ); assert_ok!(Pallet::::increase_message_fee( @@ -1445,7 +1463,7 @@ mod tests { PAYLOAD_REJECTED_BY_TARGET_CHAIN, PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight ), - Error::::MessageRejectedByChainVerifier, + Error::::MessageRejectedByChainVerifier, ); }); } @@ -1456,7 +1474,7 @@ mod tests { // messages with zero fee are rejected by lane verifier assert_noop!( Pallet::::send_message(Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 0), - Error::::MessageRejectedByLaneVerifier, + Error::::MessageRejectedByLaneVerifier, ); }); } @@ -1472,7 +1490,7 @@ mod tests { REGULAR_PAYLOAD, REGULAR_PAYLOAD.declared_weight ), - Error::::FailedToWithdrawMessageFee, + Error::::FailedToWithdrawMessageFee, ); }); } @@ -1496,7 +1514,7 @@ mod tests { fn receive_messages_proof_updates_confirmed_message_nonce() { run_test(|| { // say we have received 10 messages && last confirmed message is 8 - InboundLanes::::insert( + InboundLanes::::insert( TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 8, @@ -1573,14 +1591,14 @@ mod tests { fn receive_messages_proof_rejects_invalid_proof() { run_test(|| { assert_noop!( - Pallet::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Err(()).into(), 1, 0, ), - Error::::InvalidMessagesProof, + Error::::InvalidMessagesProof, ); }); } @@ -1589,14 +1607,14 @@ mod tests { fn receive_messages_proof_rejects_proof_with_too_many_messages() { run_test(|| { assert_noop!( - Pallet::::receive_messages_proof( + Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), u32::MAX, 0, ), - Error::::TooManyMessagesInTheProof, + Error::::TooManyMessagesInTheProof, ); }); } @@ -1608,7 +1626,7 @@ mod tests { receive_messages_delivery_proof(); assert_eq!( - OutboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, + OutboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, 1, ); }); @@ -1696,7 +1714,7 @@ mod tests { TestMessagesDeliveryProof(Err(())), Default::default(), ), - Error::::InvalidMessagesDeliveryProof, + Error::::InvalidMessagesDeliveryProof, ); }); } @@ -1726,7 +1744,7 @@ mod tests { ..Default::default() }, ), - Error::::InvalidUnrewardedRelayersState, + Error::::InvalidUnrewardedRelayersState, ); // when number of messages is invalid @@ -1751,7 +1769,7 @@ mod tests { ..Default::default() }, ), - Error::::InvalidUnrewardedRelayersState, + Error::::InvalidUnrewardedRelayersState, ); }); } @@ -1762,7 +1780,7 @@ mod tests { let mut invalid_message = message(1, REGULAR_PAYLOAD); invalid_message.data.payload = Vec::new(); - assert_ok!(Pallet::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![invalid_message]).into(), @@ -1783,7 +1801,7 @@ mod tests { let mut invalid_message = message(2, REGULAR_PAYLOAD); invalid_message.data.payload = Vec::new(); - assert_ok!(Pallet::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, Ok(vec![ @@ -1807,7 +1825,7 @@ mod tests { fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted messages proofs. - let storage_key = storage_keys::message_key::(&*b"test", 42).0; + let storage_key = storage_keys::message_key("BridgeMessages", &*b"test", 42).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), @@ -1820,7 +1838,7 @@ mod tests { fn outbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted outbound lane state proofs. - let storage_key = storage_keys::outbound_lane_data_key::(&*b"test").0; + let storage_key = storage_keys::outbound_lane_data_key("BridgeMessages", &*b"test").0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), @@ -1833,7 +1851,7 @@ mod tests { fn inbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking all // previously crafted inbound lane state proofs. - let storage_key = storage_keys::inbound_lane_data_key::(&*b"test").0; + let storage_key = storage_keys::inbound_lane_data_key("BridgeMessages", &*b"test").0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), @@ -1849,7 +1867,7 @@ mod tests { let message2 = message(2, message_payload(0, Weight::MAX / 2)); let message3 = message(3, message_payload(0, Weight::MAX / 2)); - assert_ok!(Pallet::::receive_messages_proof( + assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, // this may cause overflow if source chain storage is invalid @@ -1868,8 +1886,8 @@ mod tests { receive_messages_delivery_proof(); assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), - Error::::MessageIsAlreadyDelivered, + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Error::::MessageIsAlreadyDelivered, ); }); } @@ -1878,8 +1896,8 @@ mod tests { fn increase_message_fee_fails_if_message_is_not_yet_sent() { run_test(|| { assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), - Error::::MessageIsNotYetSent, + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Error::::MessageIsNotYetSent, ); }); } @@ -1892,8 +1910,8 @@ mod tests { TestMessageDeliveryAndDispatchPayment::reject_payments(); assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), - Error::::FailedToWithdrawMessageFee, + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Error::::FailedToWithdrawMessageFee, ); }); } @@ -1903,7 +1921,7 @@ mod tests { run_test(|| { send_regular_message(); - assert_ok!(Pallet::::increase_message_fee( + assert_ok!(Pallet::::increase_message_fee( Origin::signed(1), TEST_LANE_ID, 1, @@ -2120,7 +2138,7 @@ mod tests { ))), UnrewardedRelayersState::default(), ), - Error::::TryingToConfirmMoreMessagesThanExpected, + Error::::TryingToConfirmMoreMessagesThanExpected, ); }); } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index d9f4fd51f9696..34d59ce2ef9a0 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -245,6 +245,9 @@ pub fn max_extrinsic_size() -> u32 { *BlockLength::get().max.get(DispatchClass::Normal) } +/// Name of the With-Rialto messages pallet instance in the Millau runtime. +pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; + /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 10eac7deb8f54..57fe5d4bfa542 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -214,6 +214,9 @@ pub fn max_extrinsic_size() -> u32 { *BlockLength::get().max.get(DispatchClass::Normal) } +/// Name of the With-Millau messages pallet instance in the Millau runtime. +pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; + /// Name of the `RialtoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_finalized"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index d76ec8e679d31..2d5769a39c2f3 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -72,6 +72,9 @@ pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the With-Wococo messages pallet instance in the Rococo runtime. +pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; + /// Name of the `RococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; /// Name of the `RococoFinalityApi::is_known_header` runtime method. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index e0d49ffe85506..b846e00321fd0 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -37,6 +37,9 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the With-Rococo messages pallet instance in the Wococo runtime. +pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; + /// Name of the `WococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; /// Name of the `WococoFinalityApi::is_known_header` runtime method. diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 93662a9d6fa9d..6b861c28d4dc0 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -23,7 +23,6 @@ use frame_support::dispatch::GetDispatchInfo; use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; -use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; @@ -62,6 +61,9 @@ impl SubstrateMessageLane for MillauMessagesToRialto { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; + type SourceChain = Millau; type TargetChain = Rialto; @@ -135,12 +137,10 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } /// Millau node as messages source. -type MillauSourceClient = - SubstrateMessagesSource; +type MillauSourceClient = SubstrateMessagesSource; /// Rialto node as messages target. -type RialtoTargetClient = - SubstrateMessagesTarget; +type RialtoTargetClient = SubstrateMessagesTarget; /// Run Millau-to-Rialto messages sync. pub async fn run( @@ -212,14 +212,12 @@ pub async fn run( source_client.clone(), lane.clone(), lane_id, - RIALTO_CHAIN_ID, params.target_to_source_headers_relay, ), RialtoTargetClient::new( params.target_client, lane, lane_id, - MILLAU_CHAIN_ID, metrics_values, params.source_to_target_headers_relay, ), diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 2b7f32f2d43da..f2ee1f82f583f 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -23,7 +23,6 @@ use frame_support::dispatch::GetDispatchInfo; use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; -use bp_runtime::{MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; @@ -62,6 +61,9 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; + type SourceChain = Rialto; type TargetChain = Millau; @@ -135,12 +137,10 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } /// Rialto node as messages source. -type RialtoSourceClient = - SubstrateMessagesSource; +type RialtoSourceClient = SubstrateMessagesSource; /// Millau node as messages target. -type MillauTargetClient = - SubstrateMessagesTarget; +type MillauTargetClient = SubstrateMessagesTarget; /// Run Rialto-to-Millau messages sync. pub async fn run( @@ -211,14 +211,12 @@ pub async fn run( source_client.clone(), lane.clone(), lane_id, - MILLAU_CHAIN_ID, params.target_to_source_headers_relay, ), MillauTargetClient::new( params.target_client, lane, lane_id, - RIALTO_CHAIN_ID, metrics_values, params.source_to_target_headers_relay, ), diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 043e6c89e441d..3abedc0ca3895 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -22,7 +22,6 @@ use codec::Encode; use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; -use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; @@ -61,6 +60,9 @@ impl SubstrateMessageLane for RococoMessagesToWococo { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; + type SourceChain = Rococo; type TargetChain = Wococo; @@ -136,20 +138,10 @@ impl SubstrateMessageLane for RococoMessagesToWococo { } /// Rococo node as messages source. -type RococoSourceClient = SubstrateMessagesSource< - Rococo, - Wococo, - RococoMessagesToWococo, - relay_rococo_client::runtime::WithWococoMessagesInstance, ->; +type RococoSourceClient = SubstrateMessagesSource; /// Wococo node as messages target. -type WococoTargetClient = SubstrateMessagesTarget< - Rococo, - Wococo, - RococoMessagesToWococo, - relay_wococo_client::runtime::WithRococoMessagesInstance, ->; +type WococoTargetClient = SubstrateMessagesTarget; /// Run Rococo-to-Wococo messages sync. pub async fn run( @@ -226,14 +218,12 @@ pub async fn run( source_client.clone(), lane.clone(), lane_id, - WOCOCO_CHAIN_ID, params.target_to_source_headers_relay, ), WococoTargetClient::new( params.target_client, lane, lane_id, - ROCOCO_CHAIN_ID, metrics_values, params.source_to_target_headers_relay, ), diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index d068dc2f11b55..d4cff289e2233 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -22,7 +22,6 @@ use codec::Encode; use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; -use bp_runtime::{ROCOCO_CHAIN_ID, WOCOCO_CHAIN_ID}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; @@ -60,6 +59,9 @@ impl SubstrateMessageLane for WococoMessagesToRococo { const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; + type SourceChain = Wococo; type TargetChain = Rococo; @@ -135,20 +137,10 @@ impl SubstrateMessageLane for WococoMessagesToRococo { } /// Wococo node as messages source. -type WococoSourceClient = SubstrateMessagesSource< - Wococo, - Rococo, - WococoMessagesToRococo, - relay_wococo_client::runtime::WithRococoMessagesInstance, ->; +type WococoSourceClient = SubstrateMessagesSource; /// Rococo node as messages target. -type RococoTargetClient = SubstrateMessagesTarget< - Wococo, - Rococo, - WococoMessagesToRococo, - relay_rococo_client::runtime::WithWococoMessagesInstance, ->; +type RococoTargetClient = SubstrateMessagesTarget; /// Run Wococo-to-Rococo messages sync. pub async fn run( @@ -225,14 +217,12 @@ pub async fn run( source_client.clone(), lane.clone(), lane_id, - ROCOCO_CHAIN_ID, params.target_to_source_headers_relay, ), RococoTargetClient::new( params.target_client, lane, lane_id, - WOCOCO_CHAIN_ID, metrics_values, params.source_to_target_headers_relay, ), diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index 77d10529bf2d6..0a8187b1f0504 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -22,9 +22,6 @@ use bp_runtime::Chain; use codec::{Decode, Encode}; use frame_support::weights::Weight; -/// Instance of messages pallet that is used to bridge with Wococo chain. -pub type WithWococoMessagesInstance = pallet_bridge_messages::Instance1; - /// Unchecked Rococo extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index e3e7ce7b31dd6..6a2f7e401ac2f 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -22,9 +22,6 @@ use bp_runtime::Chain; use codec::{Decode, Encode}; use frame_support::weights::Weight; -/// Instance of messages pallet that is used to bridge with Rococo chain. -pub type WithRococoMessagesInstance = pallet_bridge_messages::DefaultInstance; - /// Unchecked Wococo extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 15b75ae945480..c859e0f9e277f 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -81,6 +81,11 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Name of the runtime method that returns id of best finalized target header at source chain. const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str; + /// Name of the messages pallet as it is declared in the `construct_runtime!()` at source chain. + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str; + /// Name of the messages pallet as it is declared in the `construct_runtime!()` at target chain. + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str; + /// Source chain. type SourceChain: Chain; /// Target chain. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 08e4964de747c..a442ebfb444c3 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -24,12 +24,12 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::{messages::DispatchFeePayment, ChainId}; +use bp_runtime::messages::DispatchFeePayment; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::{Decode, Encode}; -use frame_support::{traits::Instance, weights::Weight}; +use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, @@ -42,7 +42,7 @@ use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, Hea use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use std::{marker::PhantomData, ops::RangeInclusive}; +use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and @@ -50,55 +50,47 @@ use std::{marker::PhantomData, ops::RangeInclusive}; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { +pub struct SubstrateMessagesSource { client: Client, lane: P, lane_id: LaneId, - instance: ChainId, target_to_source_headers_relay: Option>, - _phantom: PhantomData, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource { /// Create new Substrate headers source. pub fn new( client: Client, lane: P, lane_id: LaneId, - instance: ChainId, target_to_source_headers_relay: Option>, ) -> Self { SubstrateMessagesSource { client, lane, lane_id, - instance, target_to_source_headers_relay, - _phantom: Default::default(), } } } -impl Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource { fn clone(&self) -> Self { Self { client: self.client.clone(), lane: self.lane.clone(), lane_id: self.lane_id, - instance: self.instance, target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), - _phantom: Default::default(), } } } #[async_trait] -impl RelayClient for SubstrateMessagesSource +impl RelayClient for SubstrateMessagesSource where SC: Chain, TC: Chain, P: SubstrateMessageLane, - I: Send + Sync + Instance, { type Error = SubstrateError; @@ -108,7 +100,7 @@ where } #[async_trait] -impl SourceClient for SubstrateMessagesSource +impl SourceClient for SubstrateMessagesSource where SC: Chain< Hash = ::SourceHeaderHash, @@ -132,7 +124,6 @@ where >, ::TargetHeaderNumber: Decode, ::TargetHeaderHash: Decode, - I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because @@ -217,12 +208,17 @@ where let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { - let message_key = pallet_bridge_messages::storage_keys::message_key::(&self.lane_id, message_nonce); + let message_key = pallet_bridge_messages::storage_keys::message_key( + P::MESSAGE_PALLET_NAME_AT_SOURCE, + &self.lane_id, + message_nonce, + ); storage_keys.push(message_key); message_nonce += 1; } if proof_parameters.outbound_state_proof_required { - storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key::( + storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key( + P::MESSAGE_PALLET_NAME_AT_SOURCE, &self.lane_id, )); } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 4cafcc4866fcc..1db8345931937 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -24,12 +24,11 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::ChainId; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::{Decode, Encode}; -use frame_support::{traits::Instance, weights::Weight}; +use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, @@ -40,7 +39,7 @@ use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, FixedPointNumber, FixedU128}; -use std::{convert::TryFrom, marker::PhantomData, ops::RangeInclusive}; +use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. pub type SubstrateMessagesReceivingProof = ( @@ -49,23 +48,20 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { +pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, - instance: ChainId, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, - _phantom: PhantomData, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget { /// Create new Substrate headers target. pub fn new( client: Client, lane: P, lane_id: LaneId, - instance: ChainId, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, ) -> Self { @@ -73,35 +69,30 @@ impl SubstrateMessagesTarget Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget { fn clone(&self) -> Self { Self { client: self.client.clone(), lane: self.lane.clone(), lane_id: self.lane_id, - instance: self.instance, metric_values: self.metric_values.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), - _phantom: Default::default(), } } } #[async_trait] -impl RelayClient for SubstrateMessagesTarget +impl RelayClient for SubstrateMessagesTarget where SC: Chain, TC: Chain, P: SubstrateMessageLane, - I: Send + Sync + Instance, { type Error = SubstrateError; @@ -111,7 +102,7 @@ where } #[async_trait] -impl TargetClient for SubstrateMessagesTarget +impl TargetClient for SubstrateMessagesTarget where SC: Chain< Hash = ::SourceHeaderHash, @@ -135,7 +126,6 @@ where >, ::SourceHeaderNumber: Decode, ::SourceHeaderHash: Decode, - I: Send + Sync + Instance, { async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because @@ -212,7 +202,10 @@ where SubstrateError, > { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; - let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key::(&self.lane_id); + let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key( + P::MESSAGE_PALLET_NAME_AT_TARGET, + &self.lane_id, + ); let proof = self .client .prove_storage(vec![inbound_data_key], id.1) From 441720e7b140ff0419daabf301ae17860570b00b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Sep 2021 11:51:57 +0300 Subject: [PATCH 0540/1210] Stored conversion rate updater (#1005) * update conversion rate: initial commit * Rialto=Polkadot && Millau=Kusama + actually update conversion rates * update deployment scripts and readme * allow non-zero difference between stored and real rates * dummy commit * Revert "dummy commit" This reverts commit a438198180a8385feeaaca60c9d2da0950465215. * clippy * #[allow(clippy::float_cmp)] in conversion rate update * dummy * Revert "dummy" This reverts commit 90cd6e47cda56f655e94dbef76138e6cc58d664a. * spell * shared_value_ref() -> get() * Revert "shared_value_ref() -> get()" This reverts commit 20aa30de6a59b2099cfba3e9676e71200b7bb468. --- bin/millau/node/src/chain_spec.rs | 9 +- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 9 +- bin/rialto/runtime/src/lib.rs | 2 +- .../src/chains/millau_messages_to_rialto.rs | 30 +++ relays/bin-substrate/src/chains/mod.rs | 4 +- .../src/chains/rialto_messages_to_millau.rs | 30 +++ relays/bin-substrate/src/cli/mod.rs | 28 +++ .../src/cli/relay_headers_and_messages.rs | 105 ++++++++- .../src/metrics/float_storage_value.rs | 37 +-- .../src/conversion_rate_update.rs | 210 ++++++++++++++++++ relays/lib-substrate-relay/src/lib.rs | 1 + .../lib-substrate-relay/src/messages_lane.rs | 21 +- 13 files changed, 464 insertions(+), 24 deletions(-) create mode 100644 relays/lib-substrate-relay/src/conversion_rate_update.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 583510fc34b4f..66ce0e23118e1 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -16,8 +16,8 @@ use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, - SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeRialtoMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, + GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -134,6 +134,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("RialtoMessagesOwner"), pallet_bridge_messages::Pallet::< millau_runtime::Runtime, millau_runtime::WithRialtoMessagesInstance, @@ -208,6 +209,10 @@ fn testnet_genesis( owner: Some(get_account_id_from_seed::("George")), ..Default::default() }, + bridge_rialto_messages: BridgeRialtoMessagesConfig { + owner: Some(get_account_id_from_seed::("RialtoMessagesOwner")), + ..Default::default() + }, } } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index ed7580906f570..9bbdf3a937249 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -407,7 +407,7 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event}, + BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 60b1af24e3921..977ee179461e3 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -16,8 +16,8 @@ use bp_rialto::derive_account_from_millau_id; use rialto_runtime::{ - AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig, - SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig, BridgeRialtoPoaConfig, + GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; use sp_consensus_babe::AuthorityId as BabeId; @@ -135,6 +135,7 @@ impl Alternative { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("MillauMessagesOwner"), pallet_bridge_messages::Pallet::< rialto_runtime::Runtime, rialto_runtime::WithMillauMessagesInstance, @@ -205,6 +206,10 @@ fn testnet_genesis( .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), }, + bridge_millau_messages: BridgeMillauMessagesConfig { + owner: Some(get_account_id_from_seed::("MillauMessagesOwner")), + ..Default::default() + }, } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 75ba22389a2e7..2899d18d14027 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -559,7 +559,7 @@ construct_runtime!( // Millau bridge modules. BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, - BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event}, + BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, } ); diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 6b861c28d4dc0..b63d57aeb7801 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -245,3 +245,33 @@ pub(crate) fn add_standalone_metrics( )), ) } + +/// Update Rialto -> Millau conversion rate, stored in Millau runtime storage. +pub(crate) async fn update_rialto_to_millau_conversion_rate( + client: Client, + signer: ::AccountKeyPair, + updated_rate: f64, +) -> anyhow::Result<()> { + let genesis_hash = *client.genesis_hash(); + let signer_id = (*signer.public().as_array_ref()).into(); + client + .submit_signed_extrinsic(signer_id, move |transaction_nonce| { + Bytes( + Millau::sign_transaction( + genesis_hash, + &signer, + transaction_nonce, + millau_runtime::MessagesCall::update_pallet_parameter( + millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( + sp_runtime::FixedU128::from_float(updated_rate), + ), + ) + .into(), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|err| anyhow::format_err!("{:?}", err)) +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index d2b72d4448372..8a9cb780b4a74 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -37,9 +37,9 @@ mod wococo; // Rialto as BTC and Millau as wBTC (only in relayer). /// The identifier of token, which value is associated with Rialto token value by relayer. -pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = "bitcoin"; +pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = "polkadot"; /// The identifier of token, which value is associated with Millau token value by relayer. -pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "wrapped-bitcoin"; +pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "kusama"; use relay_utils::metrics::MetricsParams; diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index f2ee1f82f583f..1f861d1bb506d 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -244,3 +244,33 @@ pub(crate) fn add_standalone_metrics( )), ) } + +/// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage. +pub(crate) async fn update_millau_to_rialto_conversion_rate( + client: Client, + signer: ::AccountKeyPair, + updated_rate: f64, +) -> anyhow::Result<()> { + let genesis_hash = *client.genesis_hash(); + let signer_id = (*signer.public().as_array_ref()).into(); + client + .submit_signed_extrinsic(signer_id, move |transaction_nonce| { + Bytes( + Rialto::sign_transaction( + genesis_hash, + &signer, + transaction_nonce, + rialto_runtime::MessagesCall::update_pallet_parameter( + rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( + sp_runtime::FixedU128::from_float(updated_rate), + ), + ) + .into(), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|err| anyhow::format_err!("{:?}", err)) +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index d108c71f7b44d..832b53087743d 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -391,6 +391,17 @@ macro_rules! declare_chain_options { pub [<$chain_prefix _signer_password_file>]: Option, } + #[doc = "Parameters required to sign transaction on behalf of owner of the messages pallet at " $chain "."] + #[derive(StructOpt, Debug, PartialEq, Eq)] + pub struct [<$chain MessagesPalletOwnerSigningParams>] { + #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _messages_pallet_owner>]: Option, + #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _messages_pallet_owner_password>]: Option, + } + impl [<$chain SigningParams>] { /// Parse signing params into chain-specific KeyPair. pub fn to_keypair(&self) -> anyhow::Result { @@ -433,6 +444,23 @@ macro_rules! declare_chain_options { } } + #[allow(dead_code)] + impl [<$chain MessagesPalletOwnerSigningParams>] { + /// Parse signing params into chain-specific KeyPair. + pub fn to_keypair(&self) -> anyhow::Result> { + use sp_core::crypto::Pair; + + let [<$chain_prefix _messages_pallet_owner>] = match self.[<$chain_prefix _messages_pallet_owner>] { + Some(ref messages_pallet_owner) => messages_pallet_owner, + None => return Ok(None), + }; + Chain::KeyPair::from_string( + [<$chain_prefix _messages_pallet_owner>], + self.[<$chain_prefix _messages_pallet_owner_password>].as_deref() + ).map_err(|e| anyhow::format_err!("{:?}", e)).map(Some) + } + } + impl [<$chain ConnectionParams>] { /// Convert connection params into Substrate client. pub async fn to_client( diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 4747939085938..a2f0d236a9652 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -26,6 +26,7 @@ use futures::{FutureExt, TryFutureExt}; use structopt::StructOpt; use strum::VariantNames; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; use relay_utils::metrics::MetricsParams; use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane}; use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay; @@ -33,6 +34,14 @@ use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay; use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}; use crate::declare_chain_options; +/// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. +/// +/// If it is zero, then transaction will be submitted every time we see difference between +/// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1), +/// then rational relayers may stop relaying messages because they were submitted using +/// lesser conversion rate. +const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; + /// Start headers+messages relayer process. #[derive(StructOpt)] pub enum RelayHeadersAndMessages { @@ -68,9 +77,13 @@ macro_rules! declare_bridge_options { #[structopt(flatten)] left_sign: [<$chain1 SigningParams>], #[structopt(flatten)] + left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>], + #[structopt(flatten)] right: [<$chain2 ConnectionParams>], #[structopt(flatten)] right_sign: [<$chain2 SigningParams>], + #[structopt(flatten)] + right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], } #[allow(unreachable_patterns)] @@ -106,9 +119,11 @@ macro_rules! select_bridge { use crate::chains::millau_messages_to_rialto::{ add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, + update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, }; use crate::chains::rialto_messages_to_millau::{ add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, }; $generic @@ -135,6 +150,22 @@ macro_rules! select_bridge { add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, }; + async fn update_right_to_left_conversion_rate( + _client: Client, + _signer: ::AccountKeyPair, + _updated_rate: f64, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) + } + + async fn update_left_to_right_conversion_rate( + _client: Client, + _signer: ::AccountKeyPair, + _updated_rate: f64, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) + } + $generic } } @@ -158,16 +189,86 @@ impl RelayHeadersAndMessages { let left_client = params.left.to_client::().await?; let left_sign = params.left_sign.to_keypair::()?; + let left_messages_pallet_owner = params.left_messages_pallet_owner.to_keypair::()?; let right_client = params.right.to_client::().await?; let right_sign = params.right_sign.to_keypair::()?; + let right_messages_pallet_owner = params.right_messages_pallet_owner.to_keypair::()?; let lanes = params.shared.lane; let relayer_mode = params.shared.relayer_mode.into(); + const METRIC_IS_SOME_PROOF: &str = "it is `None` when metric has been already registered; \ + this is the command entrypoint, so nothing has been registered yet; \ + qed"; + let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); - let (metrics_params, _) = add_left_to_right_standalone_metrics(None, metrics_params, left_client.clone())?; - let (metrics_params, _) = add_right_to_left_standalone_metrics(None, metrics_params, right_client.clone())?; + let (metrics_params, left_to_right_metrics) = + add_left_to_right_standalone_metrics(None, metrics_params, left_client.clone())?; + let (metrics_params, right_to_left_metrics) = + add_right_to_left_standalone_metrics(None, metrics_params, right_client.clone())?; + if let Some(left_messages_pallet_owner) = left_messages_pallet_owner { + let left_client = left_client.clone(); + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( + left_to_right_metrics + .target_to_source_conversion_rate + .expect(METRIC_IS_SOME_PROOF), + left_to_right_metrics + .target_to_base_conversion_rate + .clone() + .expect(METRIC_IS_SOME_PROOF), + left_to_right_metrics + .source_to_base_conversion_rate + .clone() + .expect(METRIC_IS_SOME_PROOF), + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + move |new_rate| { + log::info!( + target: "bridge", + "Going to update {} -> {} (on {}) conversion rate to {}.", + Right::NAME, + Left::NAME, + Left::NAME, + new_rate, + ); + update_right_to_left_conversion_rate( + left_client.clone(), + left_messages_pallet_owner.clone(), + new_rate, + ) + }, + ); + } + if let Some(right_messages_pallet_owner) = right_messages_pallet_owner { + let right_client = right_client.clone(); + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( + right_to_left_metrics + .target_to_source_conversion_rate + .expect(METRIC_IS_SOME_PROOF), + left_to_right_metrics + .source_to_base_conversion_rate + .expect(METRIC_IS_SOME_PROOF), + left_to_right_metrics + .target_to_base_conversion_rate + .expect(METRIC_IS_SOME_PROOF), + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + move |new_rate| { + log::info!( + target: "bridge", + "Going to update {} -> {} (on {}) conversion rate to {}.", + Left::NAME, + Right::NAME, + Right::NAME, + new_rate, + ); + update_left_to_right_conversion_rate( + right_client.clone(), + right_messages_pallet_owner.clone(), + new_rate, + ) + }, + ); + } let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index f3ba8988eea4a..e598885227892 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -17,9 +17,12 @@ use crate::chain::Chain; use crate::client::Client; +use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use codec::Decode; -use relay_utils::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; +use relay_utils::metrics::{ + metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64, +}; use sp_core::storage::StorageKey; use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; use std::time::Duration; @@ -34,6 +37,7 @@ pub struct FloatStorageValueMetric { storage_key: StorageKey, maybe_default_value: Option, metric: Gauge, + shared_value_ref: F64SharedRef, } impl FloatStorageValueMetric { @@ -47,13 +51,20 @@ impl FloatStorageValueMetric { name: String, help: String, ) -> Result { + let shared_value_ref = Arc::new(RwLock::new(None)); Ok(FloatStorageValueMetric { client, storage_key, maybe_default_value, metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + shared_value_ref, }) } + + /// Get shared reference to metric value. + pub fn shared_value_ref(&self) -> F64SharedRef { + self.shared_value_ref.clone() + } } #[async_trait] @@ -66,17 +77,17 @@ where } async fn update(&self) { - relay_utils::metrics::set_gauge_value( - &self.metric, - self.client - .storage_value::(self.storage_key.clone()) - .await - .map(|maybe_storage_value| { - maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { - storage_value.into_inner().unique_saturated_into() as f64 - / T::DIV.unique_saturated_into() as f64 - }) - }), - ); + let value = self + .client + .storage_value::(self.storage_key.clone()) + .await + .map(|maybe_storage_value| { + maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { + storage_value.into_inner().unique_saturated_into() as f64 / T::DIV.unique_saturated_into() as f64 + }) + }) + .map_err(drop); + relay_utils::metrics::set_gauge_value(&self.metric, value); + *self.shared_value_ref.write().await = value.ok().and_then(|x| x); } } diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs new file mode 100644 index 0000000000000..ee02672b483c5 --- /dev/null +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -0,0 +1,210 @@ +// 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 . + +//! Tools for updating conversion rate that is stored in the runtime storage. + +use relay_utils::metrics::F64SharedRef; +use std::{future::Future, time::Duration}; + +/// Duration between updater wakeups. +const SLEEP_DURATION: Duration = Duration::from_secs(60); + +/// Update-conversion-rate transaction status. +#[derive(Debug, Clone, Copy, PartialEq)] +enum TransactionStatus { + /// We have not submitted any transaction recently. + Idle, + /// We have recently submitted transaction that should update conversion rate. + Submitted(f64), +} + +/// Run infinite conversion rate updater loop. +/// +/// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens * Rate`. +pub fn run_conversion_rate_update_loop< + SubmitConversionRateFuture: Future> + Send + 'static, +>( + left_to_right_stored_conversion_rate: F64SharedRef, + left_to_base_conversion_rate: F64SharedRef, + right_to_base_conversion_rate: F64SharedRef, + max_difference_ratio: f64, + submit_conversion_rate: impl Fn(f64) -> SubmitConversionRateFuture + Send + 'static, +) { + async_std::task::spawn(async move { + let mut transaction_status = TransactionStatus::Idle; + loop { + async_std::task::sleep(SLEEP_DURATION).await; + let maybe_new_conversion_rate = maybe_select_new_conversion_rate( + &mut transaction_status, + &left_to_right_stored_conversion_rate, + &left_to_base_conversion_rate, + &right_to_base_conversion_rate, + max_difference_ratio, + ) + .await; + if let Some((prev_conversion_rate, new_conversion_rate)) = maybe_new_conversion_rate { + let submit_conversion_rate_future = submit_conversion_rate(new_conversion_rate); + match submit_conversion_rate_future.await { + Ok(()) => { + transaction_status = TransactionStatus::Submitted(prev_conversion_rate); + } + Err(error) => { + log::trace!(target: "bridge", "Failed to submit conversion rate update transaction: {:?}", error); + } + } + } + } + }); +} + +/// Select new conversion rate to submit to the node. +async fn maybe_select_new_conversion_rate( + transaction_status: &mut TransactionStatus, + left_to_right_stored_conversion_rate: &F64SharedRef, + left_to_base_conversion_rate: &F64SharedRef, + right_to_base_conversion_rate: &F64SharedRef, + max_difference_ratio: f64, +) -> Option<(f64, f64)> { + let left_to_right_stored_conversion_rate = (*left_to_right_stored_conversion_rate.read().await)?; + match *transaction_status { + TransactionStatus::Idle => (), + TransactionStatus::Submitted(previous_left_to_right_stored_conversion_rate) => { + // we can't compare float values from different sources directly, so we only care whether the + // stored rate has been changed or not. If it has been changed, then we assume that our proposal + // has been accepted. + // + // float comparison is ok here, because we compare same-origin (stored in runtime storage) values + // and if they are different, it means that the value has actually been updated + #[allow(clippy::float_cmp)] + if previous_left_to_right_stored_conversion_rate == left_to_right_stored_conversion_rate { + // the rate has not been changed => we won't submit any transactions until it is accepted, + // or the rate is changed by someone else + return None; + } + + *transaction_status = TransactionStatus::Idle; + } + } + + let left_to_base_conversion_rate = (*left_to_base_conversion_rate.read().await)?; + let right_to_base_conversion_rate = (*right_to_base_conversion_rate.read().await)?; + let actual_left_to_right_conversion_rate = right_to_base_conversion_rate / left_to_base_conversion_rate; + + let rate_difference = (actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs(); + let rate_difference_ratio = rate_difference / left_to_right_stored_conversion_rate; + if rate_difference_ratio < max_difference_ratio { + return None; + } + + Some(( + left_to_right_stored_conversion_rate, + actual_left_to_right_conversion_rate, + )) +} + +#[cfg(test)] +mod tests { + use super::*; + use async_std::sync::{Arc, RwLock}; + + fn test_maybe_select_new_conversion_rate( + mut transaction_status: TransactionStatus, + stored_conversion_rate: Option, + left_to_base_conversion_rate: Option, + right_to_base_conversion_rate: Option, + max_difference_ratio: f64, + ) -> (Option<(f64, f64)>, TransactionStatus) { + let stored_conversion_rate = Arc::new(RwLock::new(stored_conversion_rate)); + let left_to_base_conversion_rate = Arc::new(RwLock::new(left_to_base_conversion_rate)); + let right_to_base_conversion_rate = Arc::new(RwLock::new(right_to_base_conversion_rate)); + let result = async_std::task::block_on(maybe_select_new_conversion_rate( + &mut transaction_status, + &stored_conversion_rate, + &left_to_base_conversion_rate, + &right_to_base_conversion_rate, + max_difference_ratio, + )); + (result, transaction_status) + } + + #[test] + fn rate_is_not_updated_when_transaction_is_submitted() { + assert_eq!( + test_maybe_select_new_conversion_rate( + TransactionStatus::Submitted(10.0), + Some(10.0), + Some(1.0), + Some(1.0), + 0.0 + ), + (None, TransactionStatus::Submitted(10.0)), + ); + } + + #[test] + fn transaction_state_is_changed_to_idle_when_stored_rate_shanges() { + assert_eq!( + test_maybe_select_new_conversion_rate( + TransactionStatus::Submitted(1.0), + Some(10.0), + Some(1.0), + Some(1.0), + 100.0 + ), + (None, TransactionStatus::Idle), + ); + } + + #[test] + fn transaction_is_not_submitted_when_left_to_base_rate_is_unknown() { + assert_eq!( + test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(10.0), None, Some(1.0), 0.0), + (None, TransactionStatus::Idle), + ); + } + + #[test] + fn transaction_is_not_submitted_when_right_to_base_rate_is_unknown() { + assert_eq!( + test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(10.0), Some(1.0), None, 0.0), + (None, TransactionStatus::Idle), + ); + } + + #[test] + fn transaction_is_not_submitted_when_stored_rate_is_unknown() { + assert_eq!( + test_maybe_select_new_conversion_rate(TransactionStatus::Idle, None, Some(1.0), Some(1.0), 0.0), + (None, TransactionStatus::Idle), + ); + } + + #[test] + fn transaction_is_not_submitted_when_difference_is_below_threshold() { + assert_eq!( + test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(1.0), Some(1.0), Some(1.01), 0.02), + (None, TransactionStatus::Idle), + ); + } + + #[test] + fn transaction_is_submitted_when_difference_is_above_threshold() { + assert_eq!( + test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(1.0), Some(1.0), Some(1.03), 0.02), + (Some((1.0, 1.03)), TransactionStatus::Idle), + ); + } +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 32eaa2276e1a1..380bcfef2db5f 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -18,6 +18,7 @@ #![warn(missing_docs)] +pub mod conversion_rate_update; pub mod finality_pipeline; pub mod finality_target; pub mod headers_initialize; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index c859e0f9e277f..0b648e8cc8329 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -20,6 +20,7 @@ use crate::messages_source::SubstrateMessagesProof; use crate::messages_target::SubstrateMessagesReceivingProof; use crate::on_demand_headers::OnDemandHeadersRelay; +use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; @@ -58,6 +59,7 @@ pub struct MessagesRelayParams { } /// Message sync pipeline for Substrate <-> Substrate relays. +#[async_trait] pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Underlying generic message lane. type MessageLane: MessageLane; @@ -211,6 +213,8 @@ pub struct StandaloneMessagesMetrics { pub target_to_base_conversion_rate: Option, /// Shared reference to the actual source -> chain token conversion rate. pub source_to_base_conversion_rate: Option, + /// Shared reference to the stored (in the source chain runtime storage) target -> source chain conversion rate. + pub target_to_source_conversion_rate: Option, } impl StandaloneMessagesMetrics { @@ -218,7 +222,7 @@ impl StandaloneMessagesMetrics { pub async fn target_to_source_conversion_rate(&self) -> Option { let target_to_base_conversion_rate = (*self.target_to_base_conversion_rate.as_ref()?.read().await)?; let source_to_base_conversion_rate = (*self.source_to_base_conversion_rate.as_ref()?.read().await)?; - Some(target_to_base_conversion_rate / source_to_base_conversion_rate) + Some(source_to_base_conversion_rate / target_to_base_conversion_rate) } } @@ -231,6 +235,7 @@ pub fn add_standalone_metrics( target_chain_token_id: Option<&str>, target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + let mut target_to_source_conversion_rate = None; let mut source_to_base_conversion_rate = None; let mut target_to_base_conversion_rate = None; let mut metrics_params = @@ -266,6 +271,7 @@ pub fn add_standalone_metrics( P::SourceChain::NAME ), )?; + target_to_source_conversion_rate = Some(metric.shared_value_ref()); Ok(metric) })?; } @@ -288,6 +294,7 @@ pub fn add_standalone_metrics( StandaloneMessagesMetrics { target_to_base_conversion_rate, source_to_base_conversion_rate, + target_to_source_conversion_rate, }, )) } @@ -295,6 +302,7 @@ pub fn add_standalone_metrics( #[cfg(test)] mod tests { use super::*; + use async_std::sync::{Arc, RwLock}; type RialtoToMillauMessagesWeights = pallet_bridge_messages::weights::RialtoWeight; @@ -314,4 +322,15 @@ mod tests { (782, 216_583_333_334), ); } + + #[async_std::test] + async fn target_to_source_conversion_rate_works() { + let metrics = StandaloneMessagesMetrics { + target_to_base_conversion_rate: Some(Arc::new(RwLock::new(Some(183.15)))), + source_to_base_conversion_rate: Some(Arc::new(RwLock::new(Some(12.32)))), + target_to_source_conversion_rate: None, // we don't care + }; + + assert_eq!(metrics.target_to_source_conversion_rate().await, Some(12.32 / 183.15),); + } } From ff42bdc116a4880a31c0b141b311384c36e96435 Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 1 Sep 2021 16:52:35 +0800 Subject: [PATCH 0541/1210] Remove unnessary deps (#1101) --- modules/messages/Cargo.toml | 2 -- modules/messages/src/weights_ext.rs | 9 +++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index a2febf50af3b5..0cb14764f3bd6 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -17,7 +17,6 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } -bp-rialto = { path = "../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies @@ -41,7 +40,6 @@ std = [ "bp-message-dispatch/std", "bp-messages/std", "bp-runtime/std", - "bp-rialto/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index b17be922f5dbb..c88ec47d72b9d 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -29,6 +29,11 @@ pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128; /// we're checking here would fit 1KB. const SIGNED_EXTENSIONS_SIZE: u32 = 1024; +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie. +/// Some reserve is reserved to account future chain growth. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + /// Ensure that weights from `WeightInfoExt` implementation are looking correct. pub fn ensure_weights_are_correct( expected_default_message_delivery_tx_weight: Weight, @@ -344,12 +349,12 @@ pub trait WeightInfoExt: WeightInfo { impl WeightInfoExt for () { fn expected_extra_storage_proof_size() -> u32 { - bp_rialto::EXTRA_STORAGE_PROOF_SIZE + EXTRA_STORAGE_PROOF_SIZE } } impl WeightInfoExt for crate::weights::RialtoWeight { fn expected_extra_storage_proof_size() -> u32 { - bp_rialto::EXTRA_STORAGE_PROOF_SIZE + EXTRA_STORAGE_PROOF_SIZE } } From 26ad6f8466795aef5e3663a6e64874418c500cf2 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Wed, 1 Sep 2021 13:18:45 +0100 Subject: [PATCH 0542/1210] Remove unused deps (#1102) * remove unused dev deps * Removing unused deps --- bin/millau/node/Cargo.toml | 4 +--- bin/millau/runtime/Cargo.toml | 1 - bin/rialto/node/Cargo.toml | 3 --- modules/dispatch/Cargo.toml | 11 +++++------ modules/shift-session-manager/Cargo.toml | 11 +++++------ primitives/runtime/Cargo.toml | 16 ++++++---------- relays/bin-ethereum/Cargo.toml | 8 -------- relays/bin-substrate/Cargo.toml | 4 ---- relays/client-ethereum/Cargo.toml | 1 - relays/client-kusama/Cargo.toml | 11 ----------- relays/client-millau/Cargo.toml | 2 -- relays/client-polkadot/Cargo.toml | 11 ----------- relays/client-rialto/Cargo.toml | 2 -- relays/client-rococo/Cargo.toml | 4 ---- relays/client-substrate/Cargo.toml | 2 -- relays/client-westend/Cargo.toml | 5 ----- relays/client-wococo/Cargo.toml | 4 ---- relays/lib-substrate-relay/Cargo.toml | 4 ---- 18 files changed, 17 insertions(+), 87 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 8c6d32402ac24..18d301d354c87 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -16,8 +16,7 @@ serde_json = "1.0.59" # Bridge dependencies -bp-messages = { path = "../../../primitives/messages" } -bp-millau= { path = "../../../primitives/chain-millau" } +bp-millau = { path = "../../../primitives/chain-millau" } bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } pallet-bridge-messages = { path = "../../../modules/messages" } @@ -45,7 +44,6 @@ sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "mast sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index cb24864660d66..f79ab15b54f4e 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } -hex-literal = "0.3" serde = { version = "1.0.124", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 437f4d3c5ba91..99c9eb80d140a 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -16,7 +16,6 @@ serde_json = "1.0.59" # Bridge dependencies -bp-messages = { path = "../../../primitives/messages" } bp-runtime = { path = "../../../primitives/runtime" } bp-rialto = { path = "../../../primitives/chain-rialto" } pallet-bridge-messages = { path = "../../../modules/messages" } @@ -42,12 +41,10 @@ sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 6ba291fc8ffce..94b19305ab3c9 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -17,15 +17,14 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { 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-std = { 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 } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } -serde = "1.0" [features] default = ["std"] diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 5f58a7a50225f..d42cb4341a616 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -11,16 +11,15 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-staking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-staking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -serde = "1.0" [features] default = ["std"] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 967df63e2e2eb..f27235a1b20b3 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -13,17 +13,13 @@ 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 } +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"] diff --git a/relays/bin-ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml index 26f89c7cec324..baf927b42a4f6 100644 --- a/relays/bin-ethereum/Cargo.toml +++ b/relays/bin-ethereum/Cargo.toml @@ -6,13 +6,11 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -ansi_term = "0.12" anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } codec = { package = "parity-scale-codec", version = "2.2.0" } -env_logger = "0.8.3" ethabi = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } ethabi-contract = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } ethabi-derive = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } @@ -22,9 +20,7 @@ hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.14" num-traits = "0.2" -serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.64" -time = "0.2" # Bridge dependencies @@ -32,7 +28,6 @@ bp-currency-exchange = { path = "../../primitives/currency-exchange" } bp-eth-poa = { path = "../../primitives/ethereum-poa" } exchange-relay = { path = "../exchange" } headers-relay = { path = "../headers" } -messages-relay = { path = "../messages" } relay-ethereum-client = { path = "../client-ethereum" } relay-rialto-client = { path = "../client-rialto" } relay-substrate-client = { path = "../client-substrate" } @@ -41,9 +36,6 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 85d8d7dd51fa3..bec9bbab68b80 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" async-std = "1.9.0" -async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "2.2.0" } futures = "0.3.12" hex = "0.4" @@ -52,9 +51,7 @@ substrate-relay-helper = { path = "../lib-substrate-relay" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] @@ -63,4 +60,3 @@ pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempdir = "0.3" finality-grandpa = { version = "0.14.0" } - diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 53add5cf58a65..4ce90cc783bcd 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" bp-eth-poa = { path = "../../primitives/ethereum-poa" } -codec = { package = "parity-scale-codec", version = "2.2.0" } headers-relay = { path = "../headers" } hex-literal = "0.3" jsonrpsee-proc-macros = "0.2" diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index cd15834a873fb..1092f73d5b755 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -6,20 +6,9 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies bp-kusama = { path = "../../primitives/chain-kusama" } - -# Substrate Dependencies - -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 342c6dc07fca9..49d9dade154c2 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -7,7 +7,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } @@ -22,5 +21,4 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 05228a59514c5..261f0bee385e9 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -6,20 +6,9 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies bp-polkadot = { path = "../../primitives/chain-polkadot" } - -# Substrate Dependencies - -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 4c43268d4d2d4..3132b26d27fc1 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -7,7 +7,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } @@ -22,5 +21,4 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index e0a20da778452..1ce781be72ebc 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -7,7 +7,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } @@ -24,9 +23,6 @@ pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 9b8a6f21e3fe4..78d7a6ddc620b 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -19,7 +19,6 @@ tokio = "1.8" # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } bp-runtime = { path = "../../primitives/runtime" } finality-relay = { path = "../finality" } headers-relay = { path = "../headers" } @@ -38,7 +37,6 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 68b70c8f59b0a..24b05c4f4836b 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -7,7 +7,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } @@ -17,9 +16,5 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 5d9e6ed4bd4da..13786c0247f80 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -7,7 +7,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0" } -headers-relay = { path = "../headers" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } @@ -24,9 +23,6 @@ pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 944a2d3479e4c..8a341c45ad62e 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,6 @@ async-std = "1.9.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "2.2.0" } futures = "0.3.12" -num-format = "0.4" num-traits = "0.2" log = "0.4.14" @@ -24,7 +23,6 @@ bridge-runtime-common = { path = "../../bin/runtime-common" } finality-grandpa = { version = "0.14.0" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } -headers-relay = { path = "../headers" } messages-relay = { path = "../messages" } relay-substrate-client = { path = "../client-substrate" } @@ -40,8 +38,6 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] relay-millau-client = { path = "../client-millau" } From 34670d8c2c79ce4d6aa560e23b0e29ad0d24d1c0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 2 Sep 2021 10:55:57 +0300 Subject: [PATCH 0543/1210] Emit mortal transactions from relay (#1073) * mortal relay transactions * sign block hash for mortal transactions * TransactionEraOf * add explanation * enable mortal transactions for Westend -> Millau headers relay * clippy * spellcheck --- primitives/polkadot-core/src/lib.rs | 18 ++++---- primitives/runtime/src/chain.rs | 8 +++- primitives/runtime/src/lib.rs | 44 ++++++++++++++++++- relays/bin-ethereum/src/rialto_client.rs | 6 ++- .../src/chains/millau_headers_to_rialto.rs | 2 + .../src/chains/millau_messages_to_rialto.rs | 18 ++++++-- relays/bin-substrate/src/chains/mod.rs | 2 + .../src/chains/rialto_headers_to_millau.rs | 2 + .../src/chains/rialto_messages_to_millau.rs | 18 ++++++-- .../src/chains/rococo_headers_to_wococo.rs | 2 + .../src/chains/rococo_messages_to_wococo.rs | 18 ++++++-- .../src/chains/westend_headers_to_millau.rs | 2 + .../src/chains/wococo_headers_to_rococo.rs | 2 + .../src/chains/wococo_messages_to_rococo.rs | 18 ++++++-- relays/bin-substrate/src/cli/init_bridge.rs | 1 + relays/bin-substrate/src/cli/mod.rs | 31 +++++++++++++ relays/bin-substrate/src/cli/relay_headers.rs | 2 + .../src/cli/relay_headers_and_messages.rs | 4 ++ relays/bin-substrate/src/cli/send_message.rs | 3 +- relays/client-millau/src/lib.rs | 5 ++- relays/client-rialto/src/lib.rs | 5 ++- relays/client-rococo/src/lib.rs | 9 +--- relays/client-substrate/src/chain.rs | 1 + relays/client-substrate/src/client.rs | 11 +++-- relays/client-substrate/src/lib.rs | 15 ++++++- relays/client-westend/src/lib.rs | 9 +--- relays/client-wococo/src/lib.rs | 9 +--- .../src/finality_pipeline.rs | 20 +++++++-- .../src/finality_target.rs | 24 ++++++++-- .../src/headers_initialize.rs | 2 +- .../src/messages_source.rs | 2 +- .../src/messages_target.rs | 2 +- .../src/on_demand_headers.rs | 7 ++- 33 files changed, 249 insertions(+), 73 deletions(-) diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 4744e29492714..ab4e0f5947f25 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -235,26 +235,26 @@ impl parity_scale_codec::Decode for SignedExtensions { impl SignedExtensions { pub fn new( version: sp_version::RuntimeVersion, - era: sp_runtime::generic::Era, + era: bp_runtime::TransactionEraOf, genesis_hash: Hash, nonce: Nonce, tip: Balance, ) -> Self { Self { encode_payload: ( - (), // spec version - (), // tx version - (), // genesis - era, // era - nonce.into(), // nonce (compact encoding) - (), // Check weight - tip.into(), // transaction payment / tip (compact encoding) + (), // spec version + (), // tx version + (), // genesis + era.frame_era(), // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + tip.into(), // transaction payment / tip (compact encoding) ), additional_signed: ( version.spec_version, version.transaction_version, genesis_hash, - genesis_hash, + era.signed_payload(genesis_hash), (), (), (), diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index cb19c6e72681d..270e2d7b2fcb9 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -42,7 +42,10 @@ pub trait Chain: Send + Sync + 'static { + FromStr + MaybeMallocSizeOf + AsPrimitive - + Default; + + Default + // original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but + // `sp_runtime::generic::Era` requires block number -> `u64` conversion. + + Into; /// 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` @@ -85,3 +88,6 @@ pub type HasherOf = ::Hasher; /// Header type used by the chain. pub type HeaderOf = ::Header; + +/// Transaction era used by the chain. +pub type TransactionEraOf = crate::TransactionEra, HashOf>; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index ed915b7288640..fa1586c792c7d 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -19,11 +19,12 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Encode; +use frame_support::RuntimeDebug; 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 chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, TransactionEraOf}; pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; #[cfg(feature = "std")] @@ -138,3 +139,44 @@ impl Size for PreComputedSize { u32::try_from(self.0).unwrap_or(u32::MAX) } } + +/// Era of specific transaction. +#[derive(RuntimeDebug, Clone, Copy)] +pub enum TransactionEra { + /// Transaction is immortal. + Immortal, + /// Transaction is valid for given number of blocks, starting from given block. + Mortal(BlockNumber, BlockHash, u32), +} + +impl, BlockHash: Copy> TransactionEra { + /// Prepare transaction era, based on mortality period and current best block number. + pub fn new(best_block_number: BlockNumber, best_block_hash: BlockHash, mortality_period: Option) -> Self { + mortality_period + .map(|mortality_period| TransactionEra::Mortal(best_block_number, best_block_hash, 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_number, _, period) => { + sp_runtime::generic::Era::mortal(period as _, header_number.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_hash, _) => header_hash, + } + } +} diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index 311bc9edbc706..b340c4d82a4a2 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -157,11 +157,12 @@ impl SubmitEthereumHeaders for SubstrateClient { let ids = headers.iter().map(|header| header.id()).collect(); let genesis_hash = *self.genesis_hash(); let submission_result = async { - self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |transaction_nonce| { + self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |_, transaction_nonce| { Bytes( Rialto::sign_transaction( genesis_hash, ¶ms, + relay_substrate_client::TransactionEra::immortal(), transaction_nonce, instance.build_signed_header_call(headers), ) @@ -259,11 +260,12 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { let genesis_hash = *self.genesis_hash(); - self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |transaction_nonce| { + self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |_, transaction_nonce| { Bytes( Rialto::sign_transaction( genesis_hash, ¶ms, + relay_substrate_client::TransactionEra::immortal(), transaction_nonce, instance.build_currency_exchange_call(proof), ) diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 5be5083f5bbb8..75d7b49c40f3d 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -54,6 +54,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { fn make_submit_finality_proof_transaction( &self, + era: bp_runtime::TransactionEraOf, transaction_nonce: ::Index, header: MillauSyncHeader, proof: GrandpaJustification, @@ -64,6 +65,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { let transaction = Rialto::sign_transaction( genesis_hash, &self.finality_pipeline.target_sign, + era, transaction_nonce, call, ); diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index b63d57aeb7801..6fbce3d3149f9 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -82,8 +82,13 @@ impl SubstrateMessageLane for MillauMessagesToRialto { millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = - Millau::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); + let transaction = Millau::sign_transaction( + genesis_hash, + &self.message_lane.source_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -122,8 +127,13 @@ impl SubstrateMessageLane for MillauMessagesToRialto { .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = - Rialto::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); + let transaction = Rialto::sign_transaction( + genesis_hash, + &self.message_lane.target_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 8a9cb780b4a74..0d655698c5e1d 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -214,6 +214,7 @@ mod tests { let rialto_tx = Rialto::sign_transaction( Default::default(), &sp_keyring::AccountKeyring::Alice.pair(), + relay_substrate_client::TransactionEra::immortal(), 0, rialto_call.clone(), ); @@ -232,6 +233,7 @@ mod tests { let millau_tx = Millau::sign_transaction( Default::default(), &sp_keyring::AccountKeyring::Alice.pair(), + relay_substrate_client::TransactionEra::immortal(), 0, millau_call.clone(), ); diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 2604e79983155..69b750c542c46 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -55,6 +55,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { fn make_submit_finality_proof_transaction( &self, + era: bp_runtime::TransactionEraOf, transaction_nonce: ::Index, header: RialtoSyncHeader, proof: GrandpaJustification, @@ -69,6 +70,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { let transaction = Millau::sign_transaction( genesis_hash, &self.finality_pipeline.target_sign, + era, transaction_nonce, call, ); diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 1f861d1bb506d..986b7519e1775 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -82,8 +82,13 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = - Rialto::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); + let transaction = Rialto::sign_transaction( + genesis_hash, + &self.message_lane.source_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", @@ -122,8 +127,13 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = - Millau::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); + let transaction = Millau::sign_transaction( + genesis_hash, + &self.message_lane.target_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 38bb54ddbc384..3cacce9a48b2e 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -77,6 +77,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { fn make_submit_finality_proof_transaction( &self, + era: bp_runtime::TransactionEraOf, transaction_nonce: ::Index, header: RococoSyncHeader, proof: GrandpaJustification, @@ -88,6 +89,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { let transaction = Wococo::sign_transaction( genesis_hash, &self.finality_pipeline.target_sign, + era, transaction_nonce, call, ); diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 3abedc0ca3895..7cc4d0f7250c6 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -84,8 +84,13 @@ impl SubstrateMessageLane for RococoMessagesToWococo { ), ); let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = - Rococo::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); + let transaction = Rococo::sign_transaction( + genesis_hash, + &self.message_lane.source_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Wococo -> Rococo confirmation transaction. Weight: /{}, size: {}/{}", @@ -124,8 +129,13 @@ impl SubstrateMessageLane for RococoMessagesToWococo { ), ); let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = - Wococo::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); + let transaction = Wococo::sign_transaction( + genesis_hash, + &self.message_lane.target_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Rococo -> Wococo delivery transaction. Weight: /{}, size: {}/{}", diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 9fdf8b1a81bb6..20464b99bfdee 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -63,6 +63,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { fn make_submit_finality_proof_transaction( &self, + era: bp_runtime::TransactionEraOf, transaction_nonce: ::Index, header: WestendSyncHeader, proof: GrandpaJustification, @@ -77,6 +78,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { let transaction = Millau::sign_transaction( genesis_hash, &self.finality_pipeline.target_sign, + era, transaction_nonce, call, ); diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index a65bfd7624447..4bb5b15fe047b 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -82,6 +82,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { fn make_submit_finality_proof_transaction( &self, + era: bp_runtime::TransactionEraOf, transaction_nonce: ::Index, header: WococoSyncHeader, proof: GrandpaJustification, @@ -93,6 +94,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { let transaction = Rococo::sign_transaction( genesis_hash, &self.finality_pipeline.target_sign, + era, transaction_nonce, call, ); diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index d4cff289e2233..16a8858ac98f4 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -83,8 +83,13 @@ impl SubstrateMessageLane for WococoMessagesToRococo { ), ); let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = - Wococo::sign_transaction(genesis_hash, &self.message_lane.source_sign, transaction_nonce, call); + let transaction = Wococo::sign_transaction( + genesis_hash, + &self.message_lane.source_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Rococo -> Wococo confirmation transaction. Weight: /{}, size: {}/{}", @@ -123,8 +128,13 @@ impl SubstrateMessageLane for WococoMessagesToRococo { ), ); let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = - Rococo::sign_transaction(genesis_hash, &self.message_lane.target_sign, transaction_nonce, call); + let transaction = Rococo::sign_transaction( + genesis_hash, + &self.message_lane.target_sign, + relay_substrate_client::TransactionEra::immortal(), + transaction_nonce, + call, + ); log::trace!( target: "bridge", "Prepared Wococo -> Rococo delivery transaction. Weight: /{}, size: {}/{}", diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 846d3a575ea5b..76bc5aa273970 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -150,6 +150,7 @@ impl InitBridge { Target::sign_transaction( *target_client.genesis_hash(), &target_sign, + relay_substrate_client::TransactionEra::immortal(), transaction_nonce, encode_init_bridge(initialization_data), ) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 832b53087743d..c02f6b51306c3 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -389,6 +389,10 @@ macro_rules! declare_chain_options { #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] #[structopt(long)] pub [<$chain_prefix _signer_password_file>]: Option, + + #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] + #[structopt(long)] + pub [<$chain_prefix _transactions_mortality>]: Option, } #[doc = "Parameters required to sign transaction on behalf of owner of the messages pallet at " $chain "."] @@ -403,6 +407,25 @@ macro_rules! declare_chain_options { } impl [<$chain SigningParams>] { + /// Return transactions mortality. + #[allow(dead_code)] + pub fn transactions_mortality(&self) -> anyhow::Result> { + self.[<$chain_prefix _transactions_mortality>] + .map(|transactions_mortality| { + if !(4..=65536).contains(&transactions_mortality) + || !transactions_mortality.is_power_of_two() + { + Err(anyhow::format_err!( + "Transactions mortality {} is not a power of two in a [4; 65536] range", + transactions_mortality, + )) + } else { + Ok(transactions_mortality) + } + }) + .transpose() + } + /// Parse signing params into chain-specific KeyPair. pub fn to_keypair(&self) -> anyhow::Result { let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { @@ -550,6 +573,8 @@ mod tests { target_signer_file: None, target_signer_password_file: None, + + target_transactions_mortality: None, } .to_keypair::() .map(|p| p.public()) @@ -565,6 +590,8 @@ mod tests { target_signer_file: Some(suri_file_path.clone()), target_signer_password_file: Some(password_file_path.clone()), + + target_transactions_mortality: None, } .to_keypair::() .map(|p| p.public()) @@ -580,6 +607,8 @@ mod tests { target_signer_file: Some(suri_file_path.clone()), target_signer_password_file: Some(password_file_path.clone()), + + target_transactions_mortality: None, } .to_keypair::() .map(|p| p.public()) @@ -595,6 +624,8 @@ mod tests { target_signer_file: Some(suri_file_path), target_signer_password_file: Some(password_file_path), + + target_transactions_mortality: None, } .to_keypair::() .map(|p| p.public()) diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 404e571c2c9c0..0e527eb5b9152 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -99,6 +99,7 @@ impl RelayHeaders { select_bridge!(self.bridge, { let source_client = self.source.to_client::().await?; let target_client = self.target.to_client::().await?; + let target_transactions_mortality = self.target_sign.target_transactions_mortality; let target_sign = self.target_sign.to_keypair::()?; let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; let finality = Finality::new(target_client.clone(), target_sign); @@ -109,6 +110,7 @@ impl RelayHeaders { source_client, target_client, self.only_mandatory_headers, + target_transactions_mortality, metrics_params, ) .await diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index a2f0d236a9652..236b2b964b776 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -188,9 +188,11 @@ impl RelayHeadersAndMessages { let params: Params = self.into(); let left_client = params.left.to_client::().await?; + let left_transactions_mortality = params.left_sign.transactions_mortality()?; let left_sign = params.left_sign.to_keypair::()?; let left_messages_pallet_owner = params.left_messages_pallet_owner.to_keypair::()?; let right_client = params.right.to_client::().await?; + let right_transactions_mortality = params.right_sign.transactions_mortality()?; let right_sign = params.right_sign.to_keypair::()?; let right_messages_pallet_owner = params.right_messages_pallet_owner.to_keypair::()?; @@ -273,12 +275,14 @@ impl RelayHeadersAndMessages { let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), right_client.clone(), + right_transactions_mortality, LeftToRightFinality::new(right_client.clone(), right_sign.clone()), MAX_MISSING_LEFT_HEADERS_AT_RIGHT, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::new( right_client.clone(), left_client.clone(), + left_transactions_mortality, RightToLeftFinality::new(left_client.clone(), left_sign.clone()), MAX_MISSING_RIGHT_HEADERS_AT_LEFT, ); diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 6259c85b50ce4..75c3118eb49f2 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -178,10 +178,11 @@ impl SendMessage { let source_genesis_hash = *source_client.genesis_hash(); source_client - .submit_signed_extrinsic(source_sign.public().into(), move |transaction_nonce| { + .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { let signed_source_call = Source::sign_transaction( source_genesis_hash, &source_sign, + relay_substrate_client::TransactionEra::immortal(), transaction_nonce, send_message_call, ) diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index ac4368392c163..ce1ab870141f5 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -66,6 +66,7 @@ impl TransactionSignScheme for Millau { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, + era: relay_substrate_client::TransactionEraOf, signer_nonce: ::Index, call: ::Call, ) -> Self::SignedTransaction { @@ -75,7 +76,7 @@ impl TransactionSignScheme for Millau { frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckEra::::from(era.frame_era()), frame_system::CheckNonce::::from(signer_nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), @@ -84,7 +85,7 @@ impl TransactionSignScheme for Millau { millau_runtime::VERSION.spec_version, millau_runtime::VERSION.transaction_version, genesis_hash, - genesis_hash, + era.signed_payload(genesis_hash), (), (), (), diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 646d7629238c3..aaa62eea0e7f3 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -66,6 +66,7 @@ impl TransactionSignScheme for Rialto { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, + era: relay_substrate_client::TransactionEraOf, signer_nonce: ::Index, call: ::Call, ) -> Self::SignedTransaction { @@ -75,7 +76,7 @@ impl TransactionSignScheme for Rialto { frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(sp_runtime::generic::Era::Immortal), + frame_system::CheckEra::::from(era.frame_era()), frame_system::CheckNonce::::from(signer_nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), @@ -84,7 +85,7 @@ impl TransactionSignScheme for Rialto { rialto_runtime::VERSION.spec_version, rialto_runtime::VERSION.transaction_version, genesis_hash, - genesis_hash, + era.signed_payload(genesis_hash), (), (), (), diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 4d4812e459c75..25c10999c66a5 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -68,18 +68,13 @@ impl TransactionSignScheme for Rococo { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, + era: relay_substrate_client::TransactionEraOf, signer_nonce: ::Index, call: ::Call, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( call, - bp_rococo::SignedExtensions::new( - bp_rococo::VERSION, - sp_runtime::generic::Era::Immortal, - genesis_hash, - signer_nonce, - 0, - ), + bp_rococo::SignedExtensions::new(bp_rococo::VERSION, era, genesis_hash, signer_nonce, 0), ) .expect("SignedExtension never fails."); diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 03cbaef2d81af..39d122a72bac0 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -107,6 +107,7 @@ pub trait TransactionSignScheme { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, + era: bp_runtime::TransactionEraOf, signer_nonce: ::Index, call: ::Call, ) -> Self::SignedTransaction; diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 8164501348f47..b63e7f30a6cc2 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -18,7 +18,7 @@ use crate::chain::{Chain, ChainWithBalances}; use crate::rpc::Substrate; -use crate::{ConnectionParams, Error, Result}; +use crate::{ConnectionParams, Error, HeaderIdOf, Result}; use async_std::sync::{Arc, Mutex}; use codec::Decode; @@ -29,8 +29,9 @@ use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBui use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; -use relay_utils::relay_loop::RECONNECT_DELAY; +use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; use sp_core::{storage::StorageKey, Bytes}; +use sp_runtime::traits::Header as HeaderT; use sp_trie::StorageProof; use sp_version::RuntimeVersion; use std::{convert::TryFrom, future::Future}; @@ -293,12 +294,14 @@ impl Client { pub async fn submit_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(C::Index) -> Bytes + Send + 'static, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, ) -> Result { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let best_header = self.best_header().await?; + let best_header_id = HeaderId(*best_header.number(), best_header.hash()); self.jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(transaction_nonce); + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); let tx_hash = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 44895dcdc6e4b..2648fc4ff27fa 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -29,11 +29,13 @@ pub mod guard; pub mod headers_source; pub mod metrics; +use std::time::Duration; + pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme}; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use crate::sync_header::SyncHeader; -pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf}; +pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, TransactionEra, TransactionEraOf}; /// Header id used by the chain. pub type HeaderIdOf = relay_utils::HeaderId, BlockNumberOf>; @@ -58,3 +60,14 @@ impl Default for ConnectionParams { } } } + +/// Returns stall timeout for relay loop. +/// +/// Relay considers himself stalled if he has submitted transaction to the node, but it has not +/// been mined for this period. +/// +/// Returns `None` if mortality period is `None` +pub fn transaction_stall_timeout(mortality_period: Option, average_block_interval: Duration) -> Option { + // 1 extra block for transaction to reach the pool && 1 for relayer to awake after it is mined + mortality_period.map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1)) +} diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index b2347da502e5a..fefab00c5615f 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -66,18 +66,13 @@ impl TransactionSignScheme for Westend { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, + era: relay_substrate_client::TransactionEraOf, signer_nonce: ::Index, call: ::Call, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( call, - bp_westend::SignedExtensions::new( - bp_westend::VERSION, - sp_runtime::generic::Era::Immortal, - genesis_hash, - signer_nonce, - 0, - ), + bp_westend::SignedExtensions::new(bp_westend::VERSION, era, genesis_hash, signer_nonce, 0), ) .expect("SignedExtension never fails."); diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 3ef55223b527e..4b3bdd7d84d14 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -68,18 +68,13 @@ impl TransactionSignScheme for Wococo { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, + era: bp_runtime::TransactionEraOf, signer_nonce: ::Index, call: ::Call, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( call, - bp_wococo::SignedExtensions::new( - bp_wococo::VERSION, - sp_runtime::generic::Era::Immortal, - genesis_hash, - signer_nonce, - 0, - ), + bp_wococo::SignedExtensions::new(bp_wococo::VERSION, era, genesis_hash, signer_nonce, 0), ) .expect("SignedExtension never fails."); diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 2dc9a6394767f..73a346f21766e 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -25,8 +25,14 @@ use relay_utils::{metrics::MetricsParams, BlockNumberBase}; use sp_core::Bytes; use std::{fmt::Debug, marker::PhantomData, time::Duration}; -/// Default synchronization loop timeout. -pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(120); +/// Default synchronization loop timeout. If transactions generated by relay are immortal, then +/// this timeout is used. +/// +/// There are no any strict requirements on block time in Substrate. But we assume here that all +/// Substrate-based chains will be designed to produce relatively fast (compared to slowest +/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine +/// transaction, or remove it from the pool. +pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); /// Default limit of recent finality proofs. /// /// Finality delay of 4096 blocks is unlikely to happen in practice in @@ -62,6 +68,7 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Make submit header transaction. fn make_submit_finality_proof_transaction( &self, + era: bp_runtime::TransactionEraOf, transaction_nonce: ::Index, header: ::Header, proof: ::FinalityProof, @@ -123,6 +130,7 @@ pub async fn run( source_client: Client, target_client: Client, only_mandatory_headers: bool, + transactions_mortality: Option, metrics_params: MetricsParams, ) -> anyhow::Result<()> where @@ -146,11 +154,15 @@ where finality_relay::run( FinalitySource::new(source_client, None), - SubstrateFinalityTarget::new(target_client, pipeline), + SubstrateFinalityTarget::new(target_client, pipeline, transactions_mortality), FinalitySyncParams { tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, - stall_timeout: STALL_TIMEOUT, + stall_timeout: relay_substrate_client::transaction_stall_timeout( + transactions_mortality, + TargetChain::AVERAGE_BLOCK_INTERVAL, + ) + .unwrap_or(STALL_TIMEOUT), only_mandatory_headers, }, metrics_params, diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index bcf09b1a6d324..5db7d080ab1b8 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -30,12 +30,17 @@ use relay_utils::relay_loop::Client as RelayClient; pub struct SubstrateFinalityTarget { client: Client, pipeline: P, + transactions_mortality: Option, } impl SubstrateFinalityTarget { /// Create new Substrate headers target. - pub fn new(client: Client, pipeline: P) -> Self { - SubstrateFinalityTarget { client, pipeline } + pub fn new(client: Client, pipeline: P, transactions_mortality: Option) -> Self { + SubstrateFinalityTarget { + client, + pipeline, + transactions_mortality, + } } } @@ -44,6 +49,7 @@ impl Clone for SubstrateFinalityTarg SubstrateFinalityTarget { client: self.client.clone(), pipeline: self.pipeline.clone(), + transactions_mortality: self.transactions_mortality, } } } @@ -89,9 +95,19 @@ where ) -> Result<(), SubstrateError> { let transactions_author = self.pipeline.transactions_author(); let pipeline = self.pipeline.clone(); + let transactions_mortality = self.transactions_mortality; self.client - .submit_signed_extrinsic(transactions_author, move |transaction_nonce| { - pipeline.make_submit_finality_proof_transaction(transaction_nonce, header, proof) + .submit_signed_extrinsic(transactions_author, move |best_block_id, transaction_nonce| { + pipeline.make_submit_finality_proof_transaction( + relay_substrate_client::TransactionEra::new( + best_block_id.0, + best_block_id.1, + transactions_mortality, + ), + transaction_nonce, + header, + proof, + ) }) .await .map(drop) diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index d3a78028e0e72..4a7a0798bbf62 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -88,7 +88,7 @@ async fn do_initialize( ); let initialization_tx_hash = target_client - .submit_signed_extrinsic(target_transactions_signer, move |transaction_nonce| { + .submit_signed_extrinsic(target_transactions_signer, move |_, transaction_nonce| { prepare_initialize_transaction(transaction_nonce, initialization_data) }) .await diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index a442ebfb444c3..3924c6d3a5b78 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -246,7 +246,7 @@ where ) -> Result<(), SubstrateError> { let lane = self.lane.clone(); self.client - .submit_signed_extrinsic(self.lane.source_transactions_author(), move |transaction_nonce| { + .submit_signed_extrinsic(self.lane.source_transactions_author(), move |_, transaction_nonce| { lane.make_messages_receiving_proof_transaction(transaction_nonce, generated_at_block, proof) }) .await?; diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 1db8345931937..3b8e749a602e8 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -229,7 +229,7 @@ where let lane = self.lane.clone(); let nonces_clone = nonces.clone(); self.client - .submit_signed_extrinsic(self.lane.target_transactions_author(), move |transaction_nonce| { + .submit_signed_extrinsic(self.lane.target_transactions_author(), move |_, transaction_nonce| { lane.make_messages_delivery_transaction(transaction_nonce, generated_at_header, nonces_clone, proof) }) .await?; diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 74166b89e74ca..2f8441dbfc986 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -56,6 +56,7 @@ impl OnDemandHeadersRelay { pub fn new( source_client: Client, target_client: Client, + target_transactions_mortality: Option, pipeline: P, maximal_headers_difference: SourceChain::BlockNumber, ) -> Self @@ -79,6 +80,7 @@ impl OnDemandHeadersRelay { background_task( source_client, target_client, + target_transactions_mortality, pipeline, maximal_headers_difference, required_header_number, @@ -110,7 +112,7 @@ impl OnDemandHeadersRelay { async fn background_task( source_client: Client, target_client: Client, - // pipeline: SubstrateFinalityToSubstrate, + target_transactions_mortality: Option, pipeline: P, maximal_headers_difference: SourceChain::BlockNumber, required_header_number: RequiredHeaderNumberRef, @@ -130,7 +132,8 @@ async fn background_task( _, SubstrateFinalityToSubstrate, >::new(source_client.clone(), Some(required_header_number.clone())); - let mut finality_target = SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone()); + let mut finality_target = + SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone(), target_transactions_mortality); let mut latest_non_mandatory_at_source = Zero::zero(); let mut restart_relay = true; From d70f5fe834db75cb38cf7032c400d9c2a80aee1a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 2 Sep 2021 13:15:34 +0300 Subject: [PATCH 0544/1210] fix compilation (#1107) --- relays/bin-substrate/src/chains/millau_messages_to_rialto.rs | 3 ++- relays/bin-substrate/src/chains/rialto_messages_to_millau.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 6fbce3d3149f9..8f621eeca71bd 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -265,11 +265,12 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( let genesis_hash = *client.genesis_hash(); let signer_id = (*signer.public().as_array_ref()).into(); client - .submit_signed_extrinsic(signer_id, move |transaction_nonce| { + .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { Bytes( Millau::sign_transaction( genesis_hash, &signer, + relay_substrate_client::TransactionEra::immortal(), transaction_nonce, millau_runtime::MessagesCall::update_pallet_parameter( millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 986b7519e1775..f0ec60864db67 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -264,11 +264,12 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( let genesis_hash = *client.genesis_hash(); let signer_id = (*signer.public().as_array_ref()).into(); client - .submit_signed_extrinsic(signer_id, move |transaction_nonce| { + .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { Bytes( Rialto::sign_transaction( genesis_hash, &signer, + relay_substrate_client::TransactionEra::immortal(), transaction_nonce, rialto_runtime::MessagesCall::update_pallet_parameter( rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( From 674e8e6af91831a8c66af8612b6e256f274139e5 Mon Sep 17 00:00:00 2001 From: Antonio Dropulic <59646584+antonio-dropulic@users.noreply.github.com> Date: Thu, 2 Sep 2021 16:53:17 +0200 Subject: [PATCH 0545/1210] Refactor substrate messages source and substrate messages target (#1105) * Remove redundant generic parameters from SubstrateMessagesSource * Remove redundant generic parameters from SubstrateMessagesTarget * use uniform alias naming * use aliases instead of fully quallified syntax * pr feedback --- .../src/chains/millau_messages_to_rialto.rs | 4 +- .../src/chains/rialto_messages_to_millau.rs | 4 +- .../src/chains/rococo_messages_to_wococo.rs | 4 +- .../src/chains/wococo_messages_to_rococo.rs | 4 +- relays/client-substrate/src/chain.rs | 5 ++ relays/client-substrate/src/lib.rs | 2 +- .../src/messages_source.rs | 55 ++++++------ .../src/messages_target.rs | 87 ++++++++++--------- 8 files changed, 84 insertions(+), 81 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 8f621eeca71bd..4195e452d9e0d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -147,10 +147,10 @@ impl SubstrateMessageLane for MillauMessagesToRialto { } /// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; +type MillauSourceClient = SubstrateMessagesSource; /// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; +type RialtoTargetClient = SubstrateMessagesTarget; /// Run Millau-to-Rialto messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index f0ec60864db67..6fc7ee5b0828c 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -147,10 +147,10 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { } /// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource; +type RialtoSourceClient = SubstrateMessagesSource; /// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget; +type MillauTargetClient = SubstrateMessagesTarget; /// Run Rialto-to-Millau messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 7cc4d0f7250c6..9fa06770523e9 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -148,10 +148,10 @@ impl SubstrateMessageLane for RococoMessagesToWococo { } /// Rococo node as messages source. -type RococoSourceClient = SubstrateMessagesSource; +type RococoSourceClient = SubstrateMessagesSource; /// Wococo node as messages target. -type WococoTargetClient = SubstrateMessagesTarget; +type WococoTargetClient = SubstrateMessagesTarget; /// Run Rococo-to-Wococo messages sync. pub async fn run( diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 16a8858ac98f4..6e03d752f0003 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -147,10 +147,10 @@ impl SubstrateMessageLane for WococoMessagesToRococo { } /// Wococo node as messages source. -type WococoSourceClient = SubstrateMessagesSource; +type WococoSourceClient = SubstrateMessagesSource; /// Rococo node as messages target. -type RococoTargetClient = SubstrateMessagesTarget; +type RococoTargetClient = SubstrateMessagesTarget; /// Run Wococo-to-Rococo messages sync. pub async fn run( diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 39d122a72bac0..7bc5f711f0605 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -79,6 +79,11 @@ pub trait Chain: ChainBase + Clone { + std::convert::TryFrom; } +/// Balance type used by the chain +pub type BalanceOf = ::Balance; +/// Index type used by the chain +pub type IndexOf = ::Index; + /// Substrate-based chain with `frame_system::Config::AccountData` set to /// the `pallet_balances::AccountData`. pub trait ChainWithBalances: Chain { diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 2648fc4ff27fa..6aa319c036773 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -31,7 +31,7 @@ pub mod metrics; use std::time::Duration; -pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme}; +pub use crate::chain::{BalanceOf, BlockWithJustification, Chain, ChainWithBalances, IndexOf, TransactionSignScheme}; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use crate::sync_header::SyncHeader; diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 3924c6d3a5b78..9a98b9b1d48c3 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -38,7 +38,9 @@ use messages_relay::{ }, }; use num_traits::{Bounded, Zero}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf}; +use relay_substrate_client::{ + BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, IndexOf, +}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; @@ -50,20 +52,20 @@ use std::ops::RangeInclusive; pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); /// Substrate client as Substrate messages source. -pub struct SubstrateMessagesSource { - client: Client, +pub struct SubstrateMessagesSource { + client: Client, lane: P, lane_id: LaneId, - target_to_source_headers_relay: Option>, + target_to_source_headers_relay: Option>, } -impl SubstrateMessagesSource { +impl SubstrateMessagesSource

{ /// Create new Substrate headers source. pub fn new( - client: Client, + client: Client, lane: P, lane_id: LaneId, - target_to_source_headers_relay: Option>, + target_to_source_headers_relay: Option>, ) -> Self { SubstrateMessagesSource { client, @@ -74,7 +76,7 @@ impl SubstrateMessagesSource Clone for SubstrateMessagesSource { +impl Clone for SubstrateMessagesSource

{ fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -86,12 +88,7 @@ impl Clone for SubstrateMessagesS } #[async_trait] -impl RelayClient for SubstrateMessagesSource -where - SC: Chain, - TC: Chain, - P: SubstrateMessageLane, -{ +impl RelayClient for SubstrateMessagesSource

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { @@ -100,27 +97,27 @@ where } #[async_trait] -impl SourceClient for SubstrateMessagesSource +impl

SourceClient for SubstrateMessagesSource

where - SC: Chain< + P: SubstrateMessageLane, + P::SourceChain: Chain< Hash = ::SourceHeaderHash, BlockNumber = ::SourceHeaderNumber, Balance = ::SourceChainBalance, >, - SC::Hash: Copy, - SC::BlockNumber: Copy, - SC::Balance: Decode + Bounded, - SC::Header: DeserializeOwned, - SC::Index: DeserializeOwned, - SC::BlockNumber: BlockNumberBase, - TC: Chain< + BalanceOf: Decode + Bounded, + IndexOf: DeserializeOwned, + HashOf: Copy, + BlockNumberOf: BlockNumberBase + Copy, + HeaderOf: DeserializeOwned, + P::TargetChain: Chain< Hash = ::TargetHeaderHash, BlockNumber = ::TargetHeaderNumber, >, - P: SubstrateMessageLane, + P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, + MessagesProof = SubstrateMessagesProof, + MessagesReceivingProof = SubstrateMessagesReceivingProof, >, ::TargetHeaderNumber: Decode, ::TargetHeaderHash: Decode, @@ -186,7 +183,7 @@ where ) .await?; - make_message_details_map::( + make_message_details_map::( Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?, nonces, ) @@ -264,10 +261,10 @@ where .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( Zero::zero(), HeaderId(Default::default(), Default::default()), - prepare_dummy_messages_delivery_proof::(), + prepare_dummy_messages_delivery_proof::(), )) .await - .unwrap_or_else(|_| SC::Balance::max_value()) + .unwrap_or_else(|_| BalanceOf::::max_value()) } } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 3b8e749a602e8..8e460769156ad 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -24,6 +24,7 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; + use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -35,10 +36,12 @@ use messages_relay::{ message_lane_loop::{TargetClient, TargetClientState}, }; use num_traits::{Bounded, Zero}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf}; +use relay_substrate_client::{ + BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, +}; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; -use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, FixedPointNumber, FixedU128}; +use sp_runtime::{DeserializeOwned, FixedPointNumber, FixedU128}; use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. @@ -48,22 +51,22 @@ pub type SubstrateMessagesReceivingProof = ( ); /// Substrate client as Substrate messages target. -pub struct SubstrateMessagesTarget { - client: Client, +pub struct SubstrateMessagesTarget { + client: Client, lane: P, lane_id: LaneId, metric_values: StandaloneMessagesMetrics, - source_to_target_headers_relay: Option>, + source_to_target_headers_relay: Option>, } -impl SubstrateMessagesTarget { +impl SubstrateMessagesTarget

{ /// Create new Substrate headers target. pub fn new( - client: Client, + client: Client, lane: P, lane_id: LaneId, metric_values: StandaloneMessagesMetrics, - source_to_target_headers_relay: Option>, + source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { client, @@ -75,7 +78,7 @@ impl SubstrateMessagesTarget Clone for SubstrateMessagesTarget { +impl Clone for SubstrateMessagesTarget

{ fn clone(&self) -> Self { Self { client: self.client.clone(), @@ -88,12 +91,7 @@ impl Clone for SubstrateMessagesT } #[async_trait] -impl RelayClient for SubstrateMessagesTarget -where - SC: Chain, - TC: Chain, - P: SubstrateMessageLane, -{ +impl RelayClient for SubstrateMessagesTarget

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { @@ -102,27 +100,28 @@ where } #[async_trait] -impl TargetClient for SubstrateMessagesTarget +impl

TargetClient for SubstrateMessagesTarget

where - SC: Chain< + P: SubstrateMessageLane, + P::SourceChain: Chain< Hash = ::SourceHeaderHash, BlockNumber = ::SourceHeaderNumber, Balance = ::SourceChainBalance, >, - SC::Balance: TryFrom + Bounded, - TC: Chain< + BalanceOf: TryFrom<::Balance> + Bounded, + P::TargetChain: Chain< Hash = ::TargetHeaderHash, BlockNumber = ::TargetHeaderNumber, >, - TC::Hash: Copy, - TC::BlockNumber: Copy, - TC::Header: DeserializeOwned, - TC::Index: DeserializeOwned, - ::Number: BlockNumberBase, - P: SubstrateMessageLane, + IndexOf: DeserializeOwned, + HashOf: Copy, + BlockNumberOf: Copy, + HeaderOf: DeserializeOwned, + BlockNumberOf: BlockNumberBase, + P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, + MessagesProof = SubstrateMessagesProof, + MessagesReceivingProof = SubstrateMessagesReceivingProof, >, ::SourceHeaderNumber: Decode, ::SourceHeaderHash: Decode, @@ -255,29 +254,31 @@ where .ok_or_else(|| { SubstrateError::Custom(format!( "Failed to compute conversion rate from {} to {}", - TC::NAME, - SC::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME, )) })?; log::trace!( target: "bridge", "Using conversion rate {} when converting from {} tokens to {} tokens", conversion_rate, - TC::NAME, - SC::NAME + P::TargetChain::NAME, + P::SourceChain::NAME, ); - Ok(convert_target_tokens_to_source_tokens::( - FixedU128::from_float(conversion_rate), - self.client - .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( - Zero::zero(), - HeaderId(Default::default(), Default::default()), - nonces.clone(), - prepare_dummy_messages_proof::(nonces, total_dispatch_weight, total_size), - )) - .await - .unwrap_or_else(|_| TC::Balance::max_value()), - )) + Ok( + convert_target_tokens_to_source_tokens::( + FixedU128::from_float(conversion_rate), + self.client + .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( + Zero::zero(), + HeaderId(Default::default(), Default::default()), + nonces.clone(), + prepare_dummy_messages_proof::(nonces, total_dispatch_weight, total_size), + )) + .await + .unwrap_or_else(|_| ::Balance::max_value()), + ), + ) } } From 8fe749057f6f7d1bf8e689359c609665ff481c85 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 3 Sep 2021 18:55:56 +0300 Subject: [PATCH 0546/1210] Fix spellcheck (#1110) * fix spellcheck * invariants --- modules/ethereum/src/import.rs | 2 +- modules/grandpa/src/benchmarking.rs | 2 +- primitives/token-swap/src/lib.rs | 2 +- relays/bin-ethereum/src/rpc_errors.rs | 2 +- relays/headers/src/sync_types.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 2668ebf9244c1..9f93d8dcb2eb4 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -29,7 +29,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*}; /// If successful, returns tuple where first element is the number of useful headers /// we have imported and the second element is the number of useless headers (duplicate) /// we have NOT imported. -/// Returns error if fatal error has occured during import. Some valid headers may be +/// Returns error if fatal error has occurred during import. Some valid headers may be /// imported in this case. /// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/415) #[allow(clippy::too_many_arguments)] diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 02600201f7466..d2e73c529d0aa 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -63,7 +63,7 @@ const MAX_VALIDATOR_SET_SIZE: u32 = 1024; /// Returns number of first header to be imported. /// -/// Since we boostrap the pallet with `HeadersToKeep` already imported headers, +/// Since we bootstrap the pallet with `HeadersToKeep` already imported headers, /// this function computes the next expected header number to import. fn header_number, I: 'static, N: From>() -> N { (T::HeadersToKeep::get() + 1).into() diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index e5575e73b0ed4..5509d2b72c9ec 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -27,7 +27,7 @@ pub enum TokenSwapType { /// The `target_account_at_bridged_chain` is temporary and only have funds for single swap. /// /// ***WARNING**: if `target_account_at_bridged_chain` still exists after the swap has been - /// completed (either by claiming or cancelling), the `source_account_at_this_chain` will be able + /// completed (either by claiming or canceling), the `source_account_at_this_chain` will be able /// to restart the swap again and repeat the swap until `target_account_at_bridged_chain` depletes. TemporaryTargetAccountAtBridgedChain, /// This swap type prevents `source_account_at_this_chain` from restarting the swap after it has diff --git a/relays/bin-ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs index 06307bcf39c2b..f0f28b0c4062d 100644 --- a/relays/bin-ethereum/src/rpc_errors.rs +++ b/relays/bin-ethereum/src/rpc_errors.rs @@ -27,7 +27,7 @@ pub enum RpcError { Serialization(serde_json::Error), /// An error occurred when interacting with an Ethereum node. Ethereum(EthereumNodeError), - /// An error occured when interacting with a Substrate node. + /// An error occurred when interacting with a Substrate node. Substrate(SubstrateNodeError), /// Error running relay loop. SyncLoop(String), diff --git a/relays/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs index f6c36758b8d10..05ed25114ed08 100644 --- a/relays/headers/src/sync_types.rs +++ b/relays/headers/src/sync_types.rs @@ -159,7 +159,7 @@ pub struct SubmittedHeaders { /// IDs of ignored headers that we have decided not to submit (they are either rejected by /// target node immediately, or their descendants of incomplete headers). pub rejected: Vec, - /// Fatal target node error, if it has occured during submission. + /// Fatal target node error, if it has occurred during submission. pub fatal_error: Option, } From 25239b31a1036682954efb99874c36b133cf4fb0 Mon Sep 17 00:00:00 2001 From: bear <2630582710@qq.com> Date: Mon, 6 Sep 2021 14:05:10 +0800 Subject: [PATCH 0547/1210] Rename param and update comment (#1108) * Rename param in `confirm_delivery` * Fix typo * Update comment * Fix review issue --- modules/messages/src/inbound_lane.rs | 4 +--- modules/messages/src/lib.rs | 2 +- modules/messages/src/outbound_lane.rs | 16 ++++++++-------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index ae5de1c15214e..69eabc6ebd43d 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -136,9 +136,7 @@ impl InboundLane { return ReceivalResult::TooManyUnconfirmedMessages; } - // dispatch message before updating anything in the storage. If dispatch would panic, - // (which should not happen in the runtime) then we simply won't consider message as - // delivered (no changes to the inbound lane storage have been made). + // then, dispatch message let dispatch_result = P::dispatch( relayer_at_this_chain, DispatchMessage { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 7c6bacfb66da0..2db0de19d1423 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -352,7 +352,7 @@ pub mod pallet { // if someone tries to pay for already-delivered message, we're rejecting this intention // (otherwise this additional fee will be locked forever in relayers fund) // - // if someone tries to pay for not-yet-sent message, we're rejeting this intention, or + // if someone tries to pay for not-yet-sent message, we're rejecting this intention, or // we're risking to have mess in the storage let lane = outbound_lane::(lane_id); ensure!( diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 5888fa7fd7f85..1962e0282a8e7 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -101,40 +101,40 @@ impl OutboundLane { pub fn confirm_delivery( &mut self, max_allowed_messages: MessageNonce, - latest_received_nonce: MessageNonce, + latest_delivered_nonce: MessageNonce, relayers: &VecDeque>, ) -> ReceivalConfirmationResult { let mut data = self.storage.data(); - if latest_received_nonce <= data.latest_received_nonce { + if latest_delivered_nonce <= data.latest_received_nonce { return ReceivalConfirmationResult::NoNewConfirmations; } - if latest_received_nonce > data.latest_generated_nonce { + if latest_delivered_nonce > data.latest_generated_nonce { return ReceivalConfirmationResult::FailedToConfirmFutureMessages; } - if latest_received_nonce - data.latest_received_nonce > max_allowed_messages { + if latest_delivered_nonce - data.latest_received_nonce > max_allowed_messages { // that the relayer has declared correct number of messages that the proof contains (it is // checked outside of the function). But it may happen (but only if this/bridged chain storage is // corrupted, though) that the actual number of confirmed messages if larger than declared. // This would mean that 'reward loop' will take more time than the weight formula accounts, // so we can't allow that. return ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected( - latest_received_nonce - data.latest_received_nonce, + latest_delivered_nonce - data.latest_received_nonce, ); } let dispatch_results = - match extract_dispatch_results(data.latest_received_nonce, latest_received_nonce, relayers) { + match extract_dispatch_results(data.latest_received_nonce, latest_delivered_nonce, relayers) { Ok(dispatch_results) => dispatch_results, Err(extract_error) => return extract_error, }; let prev_latest_received_nonce = data.latest_received_nonce; - data.latest_received_nonce = latest_received_nonce; + data.latest_received_nonce = latest_delivered_nonce; self.storage.set_data(data); ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages { begin: prev_latest_received_nonce + 1, - end: latest_received_nonce, + end: latest_delivered_nonce, dispatch_results, }) } From 1aaebcedb95fb21bbef6c097f32294214399d1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 6 Sep 2021 10:40:50 +0200 Subject: [PATCH 0548/1210] Remove fund account checks from upgrade. (#1111) --- modules/messages/src/instant_payments.rs | 13 ++++--------- modules/messages/src/lib.rs | 9 --------- primitives/messages/src/source_chain.rs | 8 -------- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index 80bc32f294a6d..1c67c0446a3ba 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -57,20 +57,15 @@ where { type Error = &'static str; - fn initialize(relayer_fund_account: &T::AccountId) -> usize { - assert!( - frame_system::Pallet::::account_exists(relayer_fund_account), - "The relayer fund account ({:?}) must exist for the message lanes pallet to work correctly.", - relayer_fund_account, - ); - 1 - } - fn pay_delivery_and_dispatch_fee( submitter: &Sender, fee: &Currency::Balance, relayer_fund_account: &T::AccountId, ) -> Result<(), Self::Error> { + if !frame_system::Pallet::::account_exists(relayer_fund_account) { + return Err("The relayer fund account must exist for the message lanes pallet to work correctly."); + } + let root_account = RootAccount::get(); let account = match submitter { Sender::Signed(submitter) => submitter, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 2db0de19d1423..16ba1ced91a98 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -184,15 +184,6 @@ pub mod pallet { #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(PhantomData<(T, I)>); - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet { - /// Ensure runtime invariants. - fn on_runtime_upgrade() -> Weight { - let reads = T::MessageDeliveryAndDispatchPayment::initialize(&Self::relayer_fund_account_id()); - T::DbWeight::get().reads(reads as u64) - } - } - #[pallet::call] impl, I: 'static> Pallet { /// Change `PalletOwner`. diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index d4fd3d9b27f29..34d9487be6f6d 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -125,14 +125,6 @@ pub trait MessageDeliveryAndDispatchPayment { relayers_rewards: RelayersRewards, relayer_fund_account: &AccountId, ); - - /// Perform some initialization in externalities-provided environment. - /// - /// For instance you may ensure that particular required accounts or storage items are present. - /// Returns the number of storage reads performed. - fn initialize(_relayer_fund_account: &AccountId) -> usize { - 0 - } } /// Messages bridge API to be used from other pallets. From 3eb466a827fd743467523523f7379fb583780e8a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Sep 2021 12:04:33 +0300 Subject: [PATCH 0549/1210] Fix delivery transaction estimation used by rational relayer (#1109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix delivery transaction estimation in greedy relayer * fixed typo * improve logging * improve logging * fmt * fix compilation * fmt * Update relays/lib-substrate-relay/src/messages_target.rs Co-authored-by: Tomasz Drwięga * review Co-authored-by: Tomasz Drwięga --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- primitives/chain-kusama/Cargo.toml | 5 + primitives/chain-kusama/src/lib.rs | 19 ++ primitives/chain-millau/src/lib.rs | 5 +- primitives/chain-polkadot/Cargo.toml | 4 + primitives/chain-polkadot/src/lib.rs | 19 ++ primitives/chain-rialto/src/lib.rs | 5 +- primitives/chain-rococo/src/lib.rs | 9 +- primitives/chain-westend/Cargo.toml | 5 + primitives/chain-westend/src/lib.rs | 19 ++ primitives/chain-wococo/src/lib.rs | 2 +- .../src/chains/millau_messages_to_rialto.rs | 3 + .../src/chains/rialto_messages_to_millau.rs | 3 + .../src/chains/rococo_messages_to_wococo.rs | 3 + .../src/chains/wococo_messages_to_rococo.rs | 3 + relays/bin-substrate/src/cli/send_message.rs | 3 +- relays/client-kusama/src/lib.rs | 1 + relays/client-millau/src/lib.rs | 1 + relays/client-polkadot/src/lib.rs | 1 + relays/client-rialto/src/lib.rs | 1 + relays/client-rococo/src/lib.rs | 1 + relays/client-substrate/src/chain.rs | 7 +- relays/client-substrate/src/client.rs | 25 +- relays/client-substrate/src/guard.rs | 1 + relays/client-substrate/src/lib.rs | 4 +- relays/client-westend/src/lib.rs | 1 + relays/client-wococo/src/lib.rs | 1 + relays/lib-substrate-relay/Cargo.toml | 7 +- .../lib-substrate-relay/src/messages_lane.rs | 7 + .../src/messages_source.rs | 30 ++- .../src/messages_target.rs | 241 ++++++++++++++++-- .../src/on_demand_headers.rs | 6 +- relays/messages/src/message_lane_loop.rs | 2 + relays/messages/src/message_race_delivery.rs | 14 +- 35 files changed, 391 insertions(+), 71 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 9bbdf3a937249..1eb77ed75ea63 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -282,7 +282,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; - type WeightToFee = IdentityFee; + type WeightToFee = bp_millau::WeightToFee; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< Runtime, TargetBlockFullness, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 2899d18d14027..c13c0d78a1b40 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -414,7 +414,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; - type WeightToFee = IdentityFee; + type WeightToFee = bp_rialto::WeightToFee; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< Runtime, TargetBlockFullness, diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 70ff3b844df07..33102ea4f8871 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -7,13 +7,17 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +smallvec = "1.6" # Bridge Dependencies + bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -23,6 +27,7 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "sp-api/std", "sp-std/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index e5ab47259e54c..59bb486c90064 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -28,6 +29,24 @@ pub use bp_polkadot_core::*; /// Kusama Chain pub type Kusama = PolkadotLike; +// NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + const CENTS: Balance = 1_000_000_000_000 / 30_000; + // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + let p = CENTS; + let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); + smallvec::smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + // We use this to get the account on Kusama (target) which is derived from Polkadot's (source) // account. pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 34d59ce2ef9a0..cb732bccfa055 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -25,7 +25,7 @@ mod millau_hash; use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, }; use frame_system::limits; @@ -149,6 +149,9 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u64; +/// Weight-to-Fee type used by Millau. +pub type WeightToFee = IdentityFee; + /// Millau chain. #[derive(RuntimeDebug)] pub struct Millau; diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 22ded41b9145c..4d3be2ae477d7 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -7,14 +7,17 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +smallvec = "1.6" # Bridge Dependencies + bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -24,6 +27,7 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "sp-api/std", "sp-std/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index b0ba77c66ffc3..17c80e82b22c2 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -28,6 +29,24 @@ pub use bp_polkadot_core::*; /// Polkadot Chain pub type Polkadot = PolkadotLike; +// NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + const CENTS: Balance = 10_000_000_000 / 100; + // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + let p = CENTS; + let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); + smallvec::smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + // We use this to get the account on Polkadot (target) which is derived from Kusama's (source) // account. pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 57fe5d4bfa542..3c57b701b7166 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -23,7 +23,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; use frame_support::{ - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, Weight}, + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, }; use frame_system::limits; @@ -148,6 +148,9 @@ pub type Balance = u128; /// An instant or duration in time. pub type Moment = u64; +/// Weight-to-Fee type used by Rialto. +pub type WeightToFee = IdentityFee; + /// Rialto chain. #[derive(RuntimeDebug)] pub struct Rialto; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 2d5769a39c2f3..ce58e7ec9ab02 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -21,7 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; +use frame_support::weights::{Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -97,6 +97,13 @@ pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRococoInboundLa /// Name of the `FromRococoInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromRococoInboundLaneApi_unrewarded_relayers_state"; +/// Weight of pay-dispatch-fee operation for inbound messages at Rococo chain. +/// +/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` +/// call for your chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Rococo headers. /// diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 42a9e67a7174f..2fb8df091f557 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -8,14 +8,18 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } +smallvec = "1.6" # Bridge Dependencies + bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -28,6 +32,7 @@ std = [ "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "parity-scale-codec/std", "sp-api/std", "sp-runtime/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 4f8b9cccf4c75..595c41e443e59 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -22,6 +22,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; +use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -30,6 +31,24 @@ pub use bp_polkadot_core::*; /// Westend Chain pub type Westend = PolkadotLike; +// NOTE: This needs to be kept up to date with the Westend runtime found in the Polkadot repo. +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + const CENTS: Balance = 1_000_000_000_000 / 1_000; + // in Westend, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + let p = CENTS; + let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); + smallvec::smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; // NOTE: This needs to be kept up to date with the Westend runtime found in the Polkadot repo. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index b846e00321fd0..f962973d6c1c8 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -25,7 +25,7 @@ use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime -pub use bp_rococo::{WeightToFee, SESSION_LENGTH, VERSION}; +pub use bp_rococo::{WeightToFee, PAY_INBOUND_DISPATCH_FEE_WEIGHT, SESSION_LENGTH, VERSION}; /// Wococo Chain pub type Wococo = PolkadotLike; diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 4195e452d9e0d..51eb4e961b68a 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -24,6 +24,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; @@ -64,6 +65,8 @@ impl SubstrateMessageLane for MillauMessagesToRialto { const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + type SourceChain = Millau; type TargetChain = Rialto; diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 6fc7ee5b0828c..0ced49a0a3146 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -24,6 +24,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; @@ -64,6 +65,8 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + type SourceChain = Rialto; type TargetChain = Millau; diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 9fa06770523e9..51f89c0dbe6df 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -23,6 +23,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; use relay_substrate_client::{Chain, Client, TransactionSignScheme}; @@ -63,6 +64,8 @@ impl SubstrateMessageLane for RococoMessagesToWococo { const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + type SourceChain = Rococo; type TargetChain = Wococo; diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 6e03d752f0003..9bc13dec1440d 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -23,6 +23,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; use relay_substrate_client::{Chain, Client, TransactionSignScheme}; @@ -62,6 +63,8 @@ impl SubstrateMessageLane for WococoMessagesToRococo { const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + type SourceChain = Wococo; type TargetChain = Rococo; diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 75c3118eb49f2..5ab6b84c32df5 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -190,8 +190,9 @@ impl SendMessage { log::info!( target: "bridge", - "Sending message to {}. Size: {}. Dispatch weight: {}. Fee: {}", + "Sending message to {}. Lane: {:?}. Size: {}. Dispatch weight: {}. Fee: {}", Target::NAME, + lane, signed_source_call.len(), dispatch_weight, fee, diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 01869fb7b1c4b..0c94e73aecff6 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -44,6 +44,7 @@ impl Chain for Kusama { type SignedBlock = bp_kusama::SignedBlock; type Call = (); type Balance = bp_kusama::Balance; + type WeightToFee = bp_kusama::WeightToFee; } /// Kusama header type used in headers sync. diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index ce1ab870141f5..36430dd83dc21 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -47,6 +47,7 @@ impl Chain for Millau { type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::Call; type Balance = millau_runtime::Balance; + type WeightToFee = bp_millau::WeightToFee; } impl ChainWithBalances for Millau { diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 04ddce29d091d..dc5564cc17bb5 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -44,6 +44,7 @@ impl Chain for Polkadot { type SignedBlock = bp_polkadot::SignedBlock; type Call = (); type Balance = bp_polkadot::Balance; + type WeightToFee = bp_polkadot::WeightToFee; } /// Polkadot header type used in headers sync. diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index aaa62eea0e7f3..8024ab1fdce56 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -47,6 +47,7 @@ impl Chain for Rialto { type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::Call; type Balance = rialto_runtime::Balance; + type WeightToFee = bp_rialto::WeightToFee; } impl ChainWithBalances for Rialto { diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 25c10999c66a5..c419610dad05c 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -52,6 +52,7 @@ impl Chain for Rococo { type SignedBlock = bp_rococo::SignedBlock; type Call = crate::runtime::Call; type Balance = bp_rococo::Balance; + type WeightToFee = bp_rococo::WeightToFee; } impl ChainWithBalances for Rococo { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 7bc5f711f0605..81397e2c4ae30 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use bp_runtime::Chain as ChainBase; -use frame_support::Parameter; +use frame_support::{weights::WeightToFeePolynomial, Parameter}; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; use num_traits::{Bounded, CheckedSub, SaturatingAdd, Zero}; use sp_core::{storage::StorageKey, Pair}; @@ -77,12 +77,17 @@ pub trait Chain: ChainBase + Clone { + SaturatingAdd + Zero + std::convert::TryFrom; + + /// Type that is used by the chain, to convert from weight to fee. + type WeightToFee: WeightToFeePolynomial; } /// Balance type used by the chain pub type BalanceOf = ::Balance; /// Index type used by the chain pub type IndexOf = ::Index; +/// Weight-to-Fee type used by the chain +pub type WeightToFeeOf = ::WeightToFee; /// Substrate-based chain with `frame_system::Config::AccountData` set to /// the `pallet_balances::AccountData`. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index b63e7f30a6cc2..9fb778651b475 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -310,23 +310,24 @@ impl Client { } /// Estimate fee that will be spent on given extrinsic. - pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result { + pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result> { self.jsonrpsee_execute(move |client| async move { let fee_details = Substrate::::payment_query_fee_details(&*client, transaction, None).await?; let inclusion_fee = fee_details .inclusion_fee - .map(|inclusion_fee| { - InclusionFee { - base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - } - .inclusion_fee() + .map(|inclusion_fee| InclusionFee { + base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), + adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256()) + .unwrap_or_else(|_| C::Balance::max_value()), }) - .unwrap_or_else(Zero::zero); + .unwrap_or_else(|| InclusionFee { + base_fee: Zero::zero(), + len_fee: Zero::zero(), + adjusted_weight_fee: Zero::zero(), + }); Ok(inclusion_fee) }) .await diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 37a7c2aa275c5..f7df7dbb05c5b 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -194,6 +194,7 @@ mod tests { sp_runtime::generic::SignedBlock>; type Call = (); type Balance = u32; + type WeightToFee = frame_support::weights::IdentityFee; } impl ChainWithBalances for TestChain { diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 6aa319c036773..be1835df3227d 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -31,7 +31,9 @@ pub mod metrics; use std::time::Duration; -pub use crate::chain::{BalanceOf, BlockWithJustification, Chain, ChainWithBalances, IndexOf, TransactionSignScheme}; +pub use crate::chain::{ + BalanceOf, BlockWithJustification, Chain, ChainWithBalances, IndexOf, TransactionSignScheme, WeightToFeeOf, +}; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use crate::sync_header::SyncHeader; diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index fefab00c5615f..b33be7421cf44 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -50,6 +50,7 @@ impl Chain for Westend { type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; type Balance = bp_westend::Balance; + type WeightToFee = bp_westend::WeightToFee; } impl ChainWithBalances for Westend { diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 4b3bdd7d84d14..03cb4d71563f7 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -52,6 +52,7 @@ impl Chain for Wococo { type SignedBlock = bp_wococo::SignedBlock; type Call = crate::runtime::Call; type Balance = bp_wococo::Balance; + type WeightToFee = bp_wococo::WeightToFee; } impl ChainWithBalances for Wococo { diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 8a341c45ad62e..7ab81b786b5d0 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -40,8 +40,9 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] -relay-millau-client = { path = "../client-millau" } -relay-rialto-client = { path = "../client-rialto" } -bp-rialto = { path = "../../primitives/chain-rialto" } bp-millau = { path = "../../primitives/chain-millau" } +bp-rococo = { path = "../../primitives/chain-rococo" } +bp-wococo = { path = "../../primitives/chain-wococo" } +relay-rococo-client = { path = "../client-rococo" } +relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 0b648e8cc8329..4614a50883a02 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -88,6 +88,13 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Name of the messages pallet as it is declared in the `construct_runtime!()` at target chain. const MESSAGE_PALLET_NAME_AT_TARGET: &'static str; + /// Extra weight of the delivery transaction at the target chain, that is paid to cover + /// dispatch fee payment. + /// + /// If dispatch fee is paid at the source chain, then this weight is refunded by the + /// delivery transaction. + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight; + /// Source chain. type SourceChain: Chain; /// Target chain. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 9a98b9b1d48c3..d6e92d1e51c4f 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -24,7 +24,6 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::messages::DispatchFeePayment; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -43,7 +42,10 @@ use relay_substrate_client::{ }; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; -use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Header as HeaderT}, + DeserializeOwned, +}; use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything @@ -121,6 +123,7 @@ where >, ::TargetHeaderNumber: Decode, ::TargetHeaderHash: Decode, + ::SourceChainBalance: AtLeast32BitUnsigned, { async fn state(&self) -> Result, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because @@ -264,6 +267,7 @@ where prepare_dummy_messages_delivery_proof::(), )) .await + .map(|fee| fee.inclusion_fee()) .unwrap_or_else(|_| BalanceOf::::max_value()) } } @@ -397,7 +401,7 @@ fn make_message_details_map( dispatch_weight: details.dispatch_weight, size: details.size as _, reward: details.delivery_and_dispatch_fee, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + dispatch_fee_payment: details.dispatch_fee_payment, }, ); expected_nonce = details.nonce + 1; @@ -411,12 +415,12 @@ fn make_message_details_map( mod tests { use super::*; use bp_runtime::messages::DispatchFeePayment; - use relay_millau_client::Millau; - use relay_rialto_client::Rialto; + use relay_rococo_client::Rococo; + use relay_wococo_client::Wococo; fn message_details_from_rpc( nonces: RangeInclusive, - ) -> Vec> { + ) -> Vec> { nonces .into_iter() .map(|nonce| bp_messages::MessageDetails { @@ -432,7 +436,7 @@ mod tests { #[test] fn make_message_details_map_succeeds_if_no_messages_are_missing() { assert_eq!( - make_message_details_map::(message_details_from_rpc(1..=3), 1..=3,).unwrap(), + make_message_details_map::(message_details_from_rpc(1..=3), 1..=3,).unwrap(), vec![ ( 1, @@ -470,7 +474,7 @@ mod tests { #[test] fn make_message_details_map_succeeds_if_head_messages_are_missing() { assert_eq!( - make_message_details_map::(message_details_from_rpc(2..=3), 1..=3,).unwrap(), + make_message_details_map::(message_details_from_rpc(2..=3), 1..=3,).unwrap(), vec![ ( 2, @@ -501,7 +505,7 @@ mod tests { let mut message_details_from_rpc = message_details_from_rpc(1..=3); message_details_from_rpc.remove(1); assert!(matches!( - make_message_details_map::(message_details_from_rpc, 1..=3,), + make_message_details_map::(message_details_from_rpc, 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -509,7 +513,7 @@ mod tests { #[test] fn make_message_details_map_fails_if_tail_messages_are_missing() { assert!(matches!( - make_message_details_map::(message_details_from_rpc(1..=2), 1..=3,), + make_message_details_map::(message_details_from_rpc(1..=2), 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -517,15 +521,15 @@ mod tests { #[test] fn make_message_details_map_fails_if_all_messages_are_missing() { assert!(matches!( - make_message_details_map::(vec![], 1..=3), + make_message_details_map::(vec![], 1..=3), Err(SubstrateError::Custom(_)) )); } #[test] fn prepare_dummy_messages_delivery_proof_works() { - let expected_minimal_size = Rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Millau::STORAGE_PROOF_OVERHEAD; - let dummy_proof = prepare_dummy_messages_delivery_proof::(); + let expected_minimal_size = Wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Rococo::STORAGE_PROOF_OVERHEAD; + let dummy_proof = prepare_dummy_messages_delivery_proof::(); assert!( dummy_proof.1.encode().len() as u32 > expected_minimal_size, "Expected proof size at least {}. Got: {}", diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 8e460769156ad..20eb7a54b383d 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -29,7 +29,7 @@ use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::{Decode, Encode}; -use frame_support::weights::Weight; +use frame_support::weights::{Weight, WeightToFeePolynomial}; use messages_relay::message_lane::MessageLane; use messages_relay::{ message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, @@ -37,11 +37,11 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, + BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, WeightToFeeOf, }; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; -use sp_runtime::{DeserializeOwned, FixedPointNumber, FixedU128}; +use sp_runtime::{traits::Saturating, DeserializeOwned, FixedPointNumber, FixedU128}; use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. @@ -118,7 +118,6 @@ where BlockNumberOf: Copy, HeaderOf: DeserializeOwned, BlockNumberOf: BlockNumberBase, - P::MessageLane: MessageLane< MessagesProof = SubstrateMessagesProof, MessagesReceivingProof = SubstrateMessagesReceivingProof, @@ -244,6 +243,7 @@ where async fn estimate_delivery_transaction_in_source_tokens( &self, nonces: RangeInclusive, + total_prepaid_nonces: MessageNonce, total_dispatch_weight: Weight, total_size: u32, ) -> Result<::SourceChainBalance, SubstrateError> { @@ -258,27 +258,88 @@ where P::SourceChain::NAME, )) })?; + + // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. + let delivery_tx = self.lane.make_messages_delivery_transaction( + Zero::zero(), + HeaderId(Default::default(), Default::default()), + nonces.clone(), + prepare_dummy_messages_proof::(nonces.clone(), total_dispatch_weight, total_size), + ); + let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; + let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); + + // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch fee payment + // (Currency::transfer in regular deployment). But if message dispatch has already been paid + // at the Source chain, the delivery transaction will refund relayer with this additional cost. + // But `estimate_extrinsic_fee` obviously just returns pre-dispatch cost of the transaction. So + // if transaction delivers prepaid message, then it may happen that pre-dispatch cost is larger + // than reward and `Rational` relayer will refuse to deliver this message. + // + // The most obvious solution would be to deduct total weight of dispatch fee payments from the + // `total_dispatch_weight` and use regular `estimate_extrinsic_fee` call. But what if + // `total_dispatch_weight` is less than total dispatch fee payments weight? Weight is strictly + // positive, so we can't use this option. + // + // Instead we'll be directly using `WeightToFee` and `NextFeeMultiplier` of the Target chain. + // This requires more knowledge of the Target chain, but seems there's no better way to solve + // this now. + let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { + const WEIGHT_DIFFERENCE: Weight = 100; + + let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); + let larger_delivery_tx_fee = self + .client + .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( + Zero::zero(), + HeaderId(Default::default(), Default::default()), + nonces.clone(), + prepare_dummy_messages_proof::(nonces.clone(), larger_dispatch_weight, total_size), + )) + .await?; + + compute_prepaid_messages_refund::

( + total_prepaid_nonces, + compute_fee_multiplier::( + delivery_tx_fee.adjusted_weight_fee, + total_dispatch_weight, + larger_delivery_tx_fee.adjusted_weight_fee, + larger_dispatch_weight, + ), + ) + } else { + Zero::zero() + }; + + let delivery_fee_in_source_tokens = convert_target_tokens_to_source_tokens::( + FixedU128::from_float(conversion_rate), + inclusion_fee_in_target_tokens.saturating_sub(expected_refund_in_target_tokens), + ); + log::trace!( target: "bridge", - "Using conversion rate {} when converting from {} tokens to {} tokens", - conversion_rate, - P::TargetChain::NAME, - P::SourceChain::NAME, + "Estimated {} -> {} messages delivery transaction.\n\t\ + Total nonces: {:?}\n\t\ + Prepaid messages: {}\n\t\ + Total messages size: {}\n\t\ + Total messages dispatch weight: {}\n\t\ + Inclusion fee (in {1} tokens): {:?}\n\t\ + Expected refund (in {1} tokens): {:?}\n\t\ + {1} -> {0} conversion rate: {:?}\n\t\ + Expected delivery tx fee (in {0} tokens): {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + nonces, + total_prepaid_nonces, + total_size, + total_dispatch_weight, + inclusion_fee_in_target_tokens, + expected_refund_in_target_tokens, + conversion_rate, + delivery_fee_in_source_tokens, ); - Ok( - convert_target_tokens_to_source_tokens::( - FixedU128::from_float(conversion_rate), - self.client - .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( - Zero::zero(), - HeaderId(Default::default(), Default::default()), - nonces.clone(), - prepare_dummy_messages_proof::(nonces, total_dispatch_weight, total_size), - )) - .await - .unwrap_or_else(|_| ::Balance::max_value()), - ), - ) + + Ok(delivery_fee_in_source_tokens) } } @@ -316,17 +377,110 @@ where .unwrap_or_else(|_| SC::Balance::max_value()) } +/// Compute fee multiplier that is used by the chain, given couple of fees for transactions +/// that are only differ in dispatch weights. +/// +/// This function assumes that standard transaction payment pallet is used by the chain. +/// The only fee component that depends on dispatch weight is the `adjusted_weight_fee`. +/// +/// **WARNING**: this functions will only be accurate if weight-to-fee conversion function +/// is linear. For non-linear polynomials the error will grow with `weight_difference` growth. +/// So better to use smaller differences. +fn compute_fee_multiplier( + smaller_adjusted_weight_fee: BalanceOf, + smaller_tx_weight: Weight, + larger_adjusted_weight_fee: BalanceOf, + larger_tx_weight: Weight, +) -> FixedU128 { + let adjusted_weight_fee_difference = larger_adjusted_weight_fee.saturating_sub(smaller_adjusted_weight_fee); + let smaller_tx_unadjusted_weight_fee = WeightToFeeOf::::calc(&smaller_tx_weight); + let larger_tx_unadjusted_weight_fee = WeightToFeeOf::::calc(&larger_tx_weight); + FixedU128::saturating_from_rational( + adjusted_weight_fee_difference, + larger_tx_unadjusted_weight_fee.saturating_sub(smaller_tx_unadjusted_weight_fee), + ) +} + +/// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces` +/// messages has been paid at the source chain. +fn compute_prepaid_messages_refund( + total_prepaid_nonces: MessageNonce, + fee_multiplier: FixedU128, +) -> BalanceOf { + fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( + &P::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN.saturating_mul(total_prepaid_nonces), + )) +} + #[cfg(test)] mod tests { use super::*; - use relay_millau_client::Millau; - use relay_rialto_client::Rialto; + use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; + use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; + + #[derive(Clone)] + struct TestSubstrateMessageLane; + + impl SubstrateMessageLane for TestSubstrateMessageLane { + type MessageLane = crate::messages_lane::SubstrateMessageLaneToSubstrate< + Rococo, + RococoSigningParams, + Wococo, + WococoSigningParams, + >; + + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = ""; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = ""; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = ""; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = ""; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = ""; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = ""; + + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = ""; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = ""; + + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = 100_000; + + type SourceChain = Rococo; + type TargetChain = Wococo; + + fn source_transactions_author(&self) -> bp_rococo::AccountId { + unreachable!() + } + + fn make_messages_receiving_proof_transaction( + &self, + _transaction_nonce: ::Index, + _generated_at_block: TargetHeaderIdOf, + _proof: ::MessagesReceivingProof, + ) -> Bytes { + unreachable!() + } + + fn target_transactions_author(&self) -> bp_wococo::AccountId { + unreachable!() + } + + fn make_messages_delivery_transaction( + &self, + _transaction_nonce: ::Index, + _generated_at_header: SourceHeaderIdOf, + _nonces: RangeInclusive, + _proof: ::MessagesProof, + ) -> Bytes { + unreachable!() + } + } #[test] fn prepare_dummy_messages_proof_works() { const DISPATCH_WEIGHT: Weight = 1_000_000; const SIZE: u32 = 1_000; - let dummy_proof = prepare_dummy_messages_proof::(1..=10, DISPATCH_WEIGHT, SIZE); + let dummy_proof = prepare_dummy_messages_proof::(1..=10, DISPATCH_WEIGHT, SIZE); assert_eq!(dummy_proof.0, DISPATCH_WEIGHT); assert!( dummy_proof.1.encode().len() as u32 > SIZE, @@ -339,16 +493,47 @@ mod tests { #[test] fn convert_target_tokens_to_source_tokens_works() { assert_eq!( - convert_target_tokens_to_source_tokens::((150, 100).into(), 1_000), + convert_target_tokens_to_source_tokens::((150, 100).into(), 1_000), 1_500 ); assert_eq!( - convert_target_tokens_to_source_tokens::((50, 100).into(), 1_000), + convert_target_tokens_to_source_tokens::((50, 100).into(), 1_000), 500 ); assert_eq!( - convert_target_tokens_to_source_tokens::((100, 100).into(), 1_000), + convert_target_tokens_to_source_tokens::((100, 100).into(), 1_000), 1_000 ); } + + #[test] + fn compute_fee_multiplier_returns_sane_results() { + let multiplier = FixedU128::saturating_from_rational(1, 1000); + + let smaller_weight = 1_000_000; + let smaller_adjusted_weight_fee = multiplier.saturating_mul_int(WeightToFeeOf::::calc(&smaller_weight)); + + let larger_weight = smaller_weight + 200_000; + let larger_adjusted_weight_fee = multiplier.saturating_mul_int(WeightToFeeOf::::calc(&larger_weight)); + + assert_eq!( + compute_fee_multiplier::( + smaller_adjusted_weight_fee, + smaller_weight, + larger_adjusted_weight_fee, + larger_weight, + ), + multiplier, + ); + } + + #[test] + fn compute_prepaid_messages_refund_returns_sane_results() { + assert!( + compute_prepaid_messages_refund::( + 10, + FixedU128::saturating_from_rational(110, 100), + ) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN).into() + ); + } } diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 2f8441dbfc986..8973d4fe3ec08 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -420,10 +420,10 @@ fn on_demand_headers_relay_name() -> Str mod tests { use super::*; - type TestChain = relay_millau_client::Millau; + type TestChain = relay_rococo_client::Rococo; - const AT_SOURCE: Option = Some(10); - const AT_TARGET: Option = Some(1); + const AT_SOURCE: Option = Some(10); + const AT_TARGET: Option = Some(1); #[async_std::test] async fn mandatory_headers_scan_range_selects_range_if_too_many_headers_are_missing() { diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 84b0c72408dfa..049b6e7b5f799 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -210,6 +210,7 @@ pub trait TargetClient: RelayClient { async fn estimate_delivery_transaction_in_source_tokens( &self, nonces: RangeInclusive, + total_prepaid_nonces: MessageNonce, total_dispatch_weight: Weight, total_size: u32, ) -> Result; @@ -773,6 +774,7 @@ pub(crate) mod tests { async fn estimate_delivery_transaction_in_source_tokens( &self, nonces: RangeInclusive, + _total_prepaid_nonces: MessageNonce, total_dispatch_weight: Weight, total_size: u32, ) -> Result { diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 2e94bbee8b1c4..8a5f8d7df260d 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -561,6 +561,7 @@ async fn select_nonces_for_delivery_transaction( let mut selected_weight: Weight = 0; let mut selected_unpaid_weight: Weight = 0; + let mut selected_prepaid_nonces = 0; let mut selected_size: u32 = 0; let mut selected_count: MessageNonce = 0; let mut selected_reward = P::SourceChainBalance::zero(); @@ -570,6 +571,8 @@ async fn select_nonces_for_delivery_transaction( let mut total_confirmations_cost = P::SourceChainBalance::zero(); let mut total_cost = P::SourceChainBalance::zero(); + let hard_selected_begin_nonce = nonces_queue[nonces_queue_range.start].1.begin(); + // technically, multiple confirmations will be delivered in a single transaction, // meaning less loses for relayer. But here we don't know the final relayer yet, so // we're adding a separate transaction for every message. Normally, this cost is covered @@ -637,8 +640,12 @@ async fn select_nonces_for_delivery_transaction( // dispatch origin account AND reward is not covering this fee. // // So in the latter case we're not adding the dispatch weight to the delivery transaction weight. + let mut new_selected_prepaid_nonces = selected_prepaid_nonces; let new_selected_unpaid_weight = match details.dispatch_fee_payment { - DispatchFeePayment::AtSourceChain => selected_unpaid_weight.saturating_add(details.dispatch_weight), + DispatchFeePayment::AtSourceChain => { + new_selected_prepaid_nonces += 1; + selected_unpaid_weight.saturating_add(details.dispatch_weight) + } DispatchFeePayment::AtTargetChain => selected_unpaid_weight, }; @@ -651,7 +658,8 @@ async fn select_nonces_for_delivery_transaction( RelayerMode::Rational => { let delivery_transaction_cost = lane_target_client .estimate_delivery_transaction_in_source_tokens( - 0..=(new_selected_count as MessageNonce - 1), + hard_selected_begin_nonce..=(hard_selected_begin_nonce + index as MessageNonce), + new_selected_prepaid_nonces, new_selected_unpaid_weight, new_selected_size as u32, ) @@ -711,11 +719,11 @@ async fn select_nonces_for_delivery_transaction( hard_selected_count = index + 1; selected_weight = new_selected_weight; selected_unpaid_weight = new_selected_unpaid_weight; + selected_prepaid_nonces = new_selected_prepaid_nonces; selected_size = new_selected_size; selected_count = new_selected_count; } - let hard_selected_begin_nonce = nonces_queue[nonces_queue_range.start].1.begin(); if hard_selected_count != soft_selected_count { let hard_selected_end_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; let soft_selected_begin_nonce = hard_selected_begin_nonce; From 17ee2951e3104ac030c68da2a7c9549ca77c3d13 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Sep 2021 10:59:57 +0300 Subject: [PATCH 0550/1210] added missing constants to Kusama/Polkadot primitives (#1114) --- primitives/chain-kusama/src/lib.rs | 6 +++++ primitives/chain-polkadot/src/lib.rs | 6 +++++ primitives/polkadot-core/src/lib.rs | 37 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 59bb486c90064..af93d4108cc73 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -54,6 +54,12 @@ pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) AccountIdConverter::convert(encoded_id) } +/// Per-byte fee for Kusama transactions. +pub const TRANSACTION_BYTE_FEE: Balance = 10 * 1_000_000_000_000 / 30_000 / 1_000; + +/// Name of the With-Polkadot messages pallet instance in the Kusama runtime. +pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; + /// Name of the `KusamaFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; /// Name of the `KusamaFinalityApi::is_known_header` runtime method. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 17c80e82b22c2..938f3fec8d128 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -54,6 +54,12 @@ pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Per-byte fee for Polkadot transactions. +pub const TRANSACTION_BYTE_FEE: Balance = 10 * 10_000_000_000 / 100 / 1_000; + +/// Name of the With-Kusama messages pallet instance in the Polkadot runtime. +pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; + /// Name of the `PolkadotFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; /// Name of the `PolkadotFinalityApi::is_known_header` runtime method. diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index ab4e0f5947f25..5ad95ad477f43 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -138,6 +138,43 @@ pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; +// One important thing about weight-related constants here is that actually we may have +// different weights on different Polkadot-like chains. But now all deployments are +// almost the same, so we're exporting constants from this crate. + +/// Maximal weight of single message delivery confirmation transaction on Polkadot-like chain. +/// +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula +/// computation for the case when single message is confirmed. The result then must be rounded up to account possible +/// future runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; + +/// Increase of delivery transaction weight on Polkadot-like chain with every additional message byte. +/// +/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The +/// result then must be rounded up to account possible future runtime upgrades. +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; + +/// Maximal number of bytes, included in the signed Polkadot-like transaction apart from the encoded call itself. +/// +/// Can be computed by subtracting encoded call size from raw transaction size. +pub const TX_EXTRA_BYTES: u32 = 256; + +/// Weight of single regular message delivery transaction on Polkadot-like chain. +/// +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. +/// The message must have dispatch weight set to zero. The result then must be rounded up to account +/// possible future runtime upgrades. +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; + +/// Weight of pay-dispatch-fee operation for inbound messages at Polkadot-like chain. +/// +/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` +/// call for your chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; + /// Re-export `time_units` to make usage easier. pub use time_units::*; From 664b6b0a92fa6febbc2ed23a6cdedb4ab8d30433 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Sep 2021 11:33:39 +0300 Subject: [PATCH 0551/1210] Fix spelling (#1118) * I'm just trying to do my job * spelling --- modules/messages/src/inbound_lane.rs | 2 +- modules/messages/src/lib.rs | 2 +- primitives/chain-westend/src/lib.rs | 2 +- relays/client-rococo/src/runtime.rs | 2 +- relays/client-wococo/src/runtime.rs | 2 +- relays/finality/src/finality_loop.rs | 4 ++-- relays/lib-substrate-relay/src/conversion_rate_update.rs | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 69eabc6ebd43d..645174b6d750f 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -53,7 +53,7 @@ pub enum ReceivalResult { Dispatched(MessageDispatchResult), /// Message has invalid nonce and lane has rejected to accept this message. InvalidNonce, - /// There are too many unrewarded relayer entires at the lane. + /// There are too many unrewarded relayer entries at the lane. TooManyUnrewardedRelayers, /// There are too many unconfirmed messages at the lane. TooManyUnconfirmedMessages, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 16ba1ced91a98..2d55a84518afa 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1713,7 +1713,7 @@ mod tests { #[test] fn receive_messages_delivery_proof_rejects_proof_if_declared_relayers_state_is_invalid() { run_test(|| { - // when number of relayers entires is invalid + // when number of relayers entries is invalid assert_noop!( Pallet::::receive_messages_delivery_proof( Origin::signed(1), diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 595c41e443e59..0f430774307a5 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -65,7 +65,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// Westend Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Westend chain. -/// Ideally this code would be auto-generated from Metadata, because we want to +/// Ideally this code would be auto-generated from metadata, because we want to /// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. /// /// All entries here (like pretty much in the entire file) must be kept in sync with Westend diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index 0a8187b1f0504..d01f8a5dfd0f6 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -52,7 +52,7 @@ where /// Rococo Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from Metadata, because we want to +/// Ideally this code would be auto-generated from metadata, because we want to /// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. /// /// All entries here (like pretty much in the entire file) must be kept in sync with Rococo diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index 6a2f7e401ac2f..18fde4629a933 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -52,7 +52,7 @@ where /// Wococo Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from Metadata, because we want to +/// Ideally this code would be auto-generated from metadata, because we want to /// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. /// /// All entries here (like pretty much in the entire file) must be kept in sync with Rococo diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 4805e1536c4b4..9a2795802d079 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -49,10 +49,10 @@ pub struct FinalitySyncParams { /// to the target chain => bridge applications will run faster, but pallet storage may explode /// (but if pruning is there, then it's fine). pub tick: Duration, - /// Number of finality proofs to keep in internal buffer between loop wakeups. + /// Number of finality proofs to keep in internal buffer between loop iterations. /// /// While in "major syncing" state, we still read finality proofs from the stream. They're stored - /// in the internal buffer between loop wakeups. When we're close to the tip of the chain, we may + /// in the internal buffer between loop iterations. When we're close to the tip of the chain, we may /// meet finality delays if headers are not finalized frequently. So instead of waiting for next /// finality proof to appear in the stream, we may use existing proof from that buffer. pub recent_finality_proofs_limit: usize, diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index ee02672b483c5..3e32fe32458ee 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -19,7 +19,7 @@ use relay_utils::metrics::F64SharedRef; use std::{future::Future, time::Duration}; -/// Duration between updater wakeups. +/// Duration between updater iterations. const SLEEP_DURATION: Duration = Duration::from_secs(60); /// Update-conversion-rate transaction status. From f022fb93846e054ee5c0d5f75f8bc020e0311dc3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Sep 2021 12:52:18 +0300 Subject: [PATCH 0552/1210] fix spelling (#1119) --- modules/ethereum/src/lib.rs | 4 ++-- primitives/messages/src/source_chain.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ee55b236dd53c..e1239c049401b 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -218,8 +218,8 @@ impl ImportContext { &self.validators_set } - /// Returns reference to the latest block which has signalled change of validators set. - /// This may point to parent if parent has signalled change. + /// Returns reference to the latest block which has signaled change of validators set. + /// This may point to parent if parent has signaled change. pub fn last_signal_block(&self) -> Option { match self.parent_scheduled_change { Some(_) => Some(HeaderId { diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 34d9487be6f6d..03bd67a03fa2f 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -95,7 +95,7 @@ pub trait LaneMessageVerifier { /// submitter is paying (in source chain tokens/assets) for: /// /// 1) submit-message-transaction-fee itself. This fee is not included in the -/// `delivery_and_dispatch_fee` and is witheld by the regular transaction payment mechanism; +/// `delivery_and_dispatch_fee` and is withheld by the regular transaction payment mechanism; /// 2) message-delivery-transaction-fee. It is submitted to the target node by relayer; /// 3) message-dispatch fee. It is paid by relayer for processing message by target chain; /// 4) message-receiving-delivery-transaction-fee. It is submitted to the source node From a9f6ac4bd7e7428c247d6280c10b69c4eed3c787 Mon Sep 17 00:00:00 2001 From: bear <2630582710@qq.com> Date: Tue, 7 Sep 2021 17:52:30 +0800 Subject: [PATCH 0553/1210] Format code work (#1116) --- relays/messages/src/message_lane_loop.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 049b6e7b5f799..72c984d2990cc 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -125,6 +125,7 @@ pub trait SourceClient: RelayClient { &self, id: SourceHeaderIdOf

, ) -> Result<(SourceHeaderIdOf

, MessageNonce), Self::Error>; + /// Get nonce of the latest message, which receiving has been confirmed by the target chain. async fn latest_confirmed_received_nonce( &self, @@ -180,6 +181,7 @@ pub trait TargetClient: RelayClient { &self, id: TargetHeaderIdOf

, ) -> Result<(TargetHeaderIdOf

, MessageNonce), Self::Error>; + /// Get state of unrewarded relayers set at the inbound lane. async fn unrewarded_relayers_state( &self, From de4a758a21aec352f4a4ea44fbb665d682edab69 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Thu, 9 Sep 2021 14:22:21 +0800 Subject: [PATCH 0554/1210] Code Cleaning (#1124) * Remove Trailing Space * Correct Source Chain Name --- bin/millau/runtime/Cargo.toml | 52 ++++++++++++------------- bin/rialto/runtime/Cargo.toml | 52 ++++++++++++------------- bin/runtime-common/Cargo.toml | 14 +++---- modules/currency-exchange/Cargo.toml | 10 ++--- modules/ethereum/Cargo.toml | 12 +++--- modules/grandpa/Cargo.toml | 14 +++---- modules/messages/Cargo.toml | 12 +++--- modules/token-swap/Cargo.toml | 12 +++--- primitives/chain-kusama/Cargo.toml | 4 +- primitives/chain-millau/Cargo.toml | 16 ++++---- primitives/chain-polkadot/Cargo.toml | 4 +- primitives/chain-rialto/Cargo.toml | 12 +++--- primitives/chain-rialto/src/lib.rs | 2 +- primitives/chain-rococo/Cargo.toml | 4 +- primitives/chain-westend/Cargo.toml | 4 +- primitives/chain-wococo/Cargo.toml | 2 +- primitives/currency-exchange/Cargo.toml | 6 +-- primitives/ethereum-poa/Cargo.toml | 8 ++-- primitives/header-chain/Cargo.toml | 10 ++--- primitives/message-dispatch/Cargo.toml | 4 +- primitives/messages/Cargo.toml | 6 +-- primitives/polkadot-core/Cargo.toml | 6 +-- primitives/token-swap/Cargo.toml | 4 +- 23 files changed, 135 insertions(+), 135 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index f79ab15b54f4e..a1619d4d8d9e6 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -27,32 +27,32 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-consensus-aura = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-aura = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index d986a33f4b23e..b6e971eec005b 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -34,34 +34,34 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-consensus-babe = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-version = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 64d7227874262..9c98e55207d5d 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -23,13 +23,13 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f # Substrate dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -pallet-transaction-payment = { 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-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, optional = true } -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 } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment = { 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-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, optional = true } +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"] diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index 8f1f501591598..e842bf10dd533 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -18,11 +18,11 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 732f510548339..275747eb329a0 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -18,12 +18,12 @@ bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index da74faa87178a..020d24766dee1 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -21,16 +21,16 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-finality-grandpa = { 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-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 } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-finality-grandpa = { 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-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 } # Optional Benchmarking Dependencies bp-test-utils = { path = "../../primitives/test-utils", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } [dev-dependencies] sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 0cb14764f3bd6..cc0be45406556 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -21,12 +21,12 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] hex = "0.4" diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index 8a83a88503f38..bf3411ec06f20 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -21,12 +21,12 @@ pallet-bridge-dispatch = { path = "../dispatch", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } [dev-dependencies] pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 33102ea4f8871..4b26a2ba97c24 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -17,8 +17,8 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 3628f9092091a..c4f30aaf6b741 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -21,14 +21,14 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-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 } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { 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-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"] diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 4d3be2ae477d7..4877c6d5eaf26 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -17,8 +17,8 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index 7e039a40acd96..d16ac59484fb5 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -15,12 +15,12 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 3c57b701b7166..14edd1c227499 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -217,7 +217,7 @@ pub fn max_extrinsic_size() -> u32 { *BlockLength::get().max.get(DispatchClass::Normal) } -/// Name of the With-Millau messages pallet instance in the Millau runtime. +/// Name of the With-Millau messages pallet instance in the Rialto runtime. pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the `RialtoFinalityApi::best_finalized` runtime method. diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 15a81beeb1c19..dd0d9b37e42cd 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -16,8 +16,8 @@ bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 2fb8df091f557..7230ba359c420 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -19,8 +19,8 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { 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-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 3748e7535e32f..d99783695ad31 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -16,7 +16,7 @@ bp-rococo = { path = "../chain-rococo", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index 0e1fa451786d1..f47ab6e61b7a3 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -11,9 +11,9 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-std = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index a12b237029bfd..5843b041c5708 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -24,10 +24,10 @@ triehash = { version = "0.8.2", default-features = false } # Substrate Dependencies -sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] hex-literal = "0.2" diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 2c21184c93c41..ecd7c17341a14 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -13,11 +13,11 @@ serde = { version = "1.0", optional = true } # 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-finality-grandpa = { 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-std = { 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-finality-grandpa = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] assert_matches = "1.5" diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index f673a22fedb08..9553b50d99d7c 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -12,8 +12,8 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-std = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 3f0c3550190fd..2dc5ae8032f52 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -18,9 +18,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 4f0d73ae079dd..7801112c6ddab 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" , default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 4245a5363fd90..03f40438e0734 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -11,8 +11,8 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = # 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 } +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 } [features] default = ["std"] From 8f560b0db19cb1ff59ed2693a3d39042f90f1520 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Sep 2021 09:22:33 +0300 Subject: [PATCH 0555/1210] log max balance drop when sending message (#1117) --- relays/bin-substrate/src/cli/send_message.rs | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 5ab6b84c32df5..aa9a5970596c0 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -177,6 +177,18 @@ impl SendMessage { })?; let source_genesis_hash = *source_client.genesis_hash(); + let estimated_transaction_fee = source_client + .estimate_extrinsic_fee(Bytes( + Source::sign_transaction( + source_genesis_hash, + &source_sign, + relay_substrate_client::TransactionEra::immortal(), + 0, + send_message_call.clone(), + ) + .encode(), + )) + .await?; source_client .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { let signed_source_call = Source::sign_transaction( @@ -197,6 +209,15 @@ impl SendMessage { dispatch_weight, fee, ); + log::info!( + target: "bridge", + "The source account ({:?}) balance will be reduced by (at most) {} (message fee) + {} (tx fee ) = {} {} tokens", + AccountId32::from(source_sign.public()), + fee.0, + estimated_transaction_fee.inclusion_fee(), + fee.0.saturating_add(estimated_transaction_fee.inclusion_fee() as _), + Source::NAME, + ); log::info!( target: "bridge", "Signed {} Call: {:?}", From 43cce1beb103098fda146abd0f89b8de49205ab6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Sep 2021 10:26:10 +0300 Subject: [PATCH 0556/1210] Transactions resubmitter (#1083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * resubmit transactions: start * resubmit transactions: continue * enable resubmitter in deployments * clippy * spellcheck * Update relays/client-substrate/src/chain.rs Co-authored-by: Tomasz Drwięga * fix compilation * fix compilation Co-authored-by: Tomasz Drwięga --- primitives/polkadot-core/src/lib.rs | 15 + relays/bin-ethereum/src/rialto_client.rs | 8 +- relays/bin-substrate/Cargo.toml | 1 + .../src/chains/millau_headers_to_rialto.rs | 5 +- .../src/chains/millau_messages_to_rialto.rs | 24 +- relays/bin-substrate/src/chains/mod.rs | 8 +- .../src/chains/rialto_headers_to_millau.rs | 5 +- .../src/chains/rialto_messages_to_millau.rs | 24 +- .../src/chains/rococo_headers_to_wococo.rs | 5 +- .../src/chains/rococo_messages_to_wococo.rs | 8 +- .../src/chains/westend_headers_to_millau.rs | 5 +- .../src/chains/wococo_headers_to_rococo.rs | 5 +- .../src/chains/wococo_messages_to_rococo.rs | 8 +- relays/bin-substrate/src/cli/init_bridge.rs | 5 +- relays/bin-substrate/src/cli/mod.rs | 6 +- .../src/cli/resubmit_transactions.rs | 364 ++++++++++++++++++ relays/bin-substrate/src/cli/send_message.rs | 8 +- relays/client-millau/src/lib.rs | 41 +- relays/client-rialto/src/lib.rs | 41 +- relays/client-rococo/src/lib.rs | 33 +- relays/client-substrate/src/chain.rs | 60 ++- relays/client-substrate/src/client.rs | 56 ++- relays/client-substrate/src/error.rs | 11 + relays/client-substrate/src/lib.rs | 3 +- relays/client-substrate/src/rpc.rs | 2 + relays/client-westend/src/lib.rs | 40 +- relays/client-wococo/src/lib.rs | 33 +- relays/utils/src/relay_loop.rs | 9 + 28 files changed, 682 insertions(+), 151 deletions(-) create mode 100644 relays/bin-substrate/src/cli/resubmit_transactions.rs diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 5ad95ad477f43..3083112316fae 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -233,6 +233,9 @@ pub type Balance = u128; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic, Call, Signature, SignedExtensions>; +/// Account address, used by the Polkadot-like chain. +pub type Address = MultiAddress; + /// A type of the data encoded as part of the transaction. pub type SignedExtra = ( (), @@ -301,6 +304,18 @@ impl SignedExtensions { } } +impl SignedExtensions { + /// Return signer nonce, used to craft transaction. + pub fn nonce(&self) -> Nonce { + self.encode_payload.4.into() + } + + /// Return transaction tip. + pub fn tip(&self) -> Balance { + self.encode_payload.6.into() + } +} + impl sp_runtime::traits::SignedExtension for SignedExtensions where Call: parity_scale_codec::Codec + sp_std::fmt::Debug + Sync + Send + Clone + Eq + PartialEq, diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index b340c4d82a4a2..35518f5e19cc2 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -24,7 +24,7 @@ use codec::{Decode, Encode}; use headers_relay::sync_types::SubmittedHeaders; use relay_ethereum_client::types::HeaderId as EthereumHeaderId; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client as SubstrateClient, TransactionSignScheme}; +use relay_substrate_client::{Client as SubstrateClient, TransactionSignScheme, UnsignedTransaction}; use relay_utils::HeaderId; use sp_core::{crypto::Pair, Bytes}; use std::{collections::VecDeque, sync::Arc}; @@ -163,8 +163,7 @@ impl SubmitEthereumHeaders for SubstrateClient { genesis_hash, ¶ms, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - instance.build_signed_header_call(headers), + UnsignedTransaction::new(instance.build_signed_header_call(headers), transaction_nonce), ) .encode(), ) @@ -266,8 +265,7 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { genesis_hash, ¶ms, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - instance.build_currency_exchange_call(proof), + UnsignedTransaction::new(instance.build_currency_exchange_call(proof), transaction_nonce), ) .encode(), ) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index bec9bbab68b80..8689821351390 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -13,6 +13,7 @@ futures = "0.3.12" hex = "0.4" log = "0.4.14" num-format = "0.4" +num-traits = "0.2" paste = "1.0" structopt = "0.3" strum = { version = "0.21.0", features = ["derive"] } diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 75d7b49c40f3d..4fa9d83e586d7 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -22,7 +22,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Millau-to-Rialto finality sync pipeline. @@ -66,8 +66,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { genesis_hash, &self.finality_pipeline.target_sign, era, - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); Bytes(transaction.encode()) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 51eb4e961b68a..a4dedaed1ecae 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -28,7 +28,7 @@ use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use substrate_relay_helper::messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, @@ -89,8 +89,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { genesis_hash, &self.message_lane.source_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", @@ -134,8 +133,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { genesis_hash, &self.message_lane.target_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", @@ -274,13 +272,15 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( genesis_hash, &signer, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - millau_runtime::MessagesCall::update_pallet_parameter( - millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ), - ) - .into(), + UnsignedTransaction::new( + millau_runtime::MessagesCall::update_pallet_parameter( + millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( + sp_runtime::FixedU128::from_float(updated_rate), + ), + ) + .into(), + transaction_nonce, + ), ) .encode(), ) diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 0d655698c5e1d..6f8273a7fcbd9 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -67,7 +67,7 @@ mod tests { use frame_support::dispatch::GetDispatchInfo; use relay_millau_client::Millau; use relay_rialto_client::Rialto; - use relay_substrate_client::TransactionSignScheme; + use relay_substrate_client::{TransactionSignScheme, UnsignedTransaction}; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -215,8 +215,7 @@ mod tests { Default::default(), &sp_keyring::AccountKeyring::Alice.pair(), relay_substrate_client::TransactionEra::immortal(), - 0, - rialto_call.clone(), + UnsignedTransaction::new(rialto_call.clone(), 0), ); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); assert!( @@ -234,8 +233,7 @@ mod tests { Default::default(), &sp_keyring::AccountKeyring::Alice.pair(), relay_substrate_client::TransactionEra::immortal(), - 0, - millau_call.clone(), + UnsignedTransaction::new(millau_call.clone(), 0), ); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); assert!( diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 69b750c542c46..d2e0f5e663208 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -22,7 +22,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Rialto-to-Millau finality sync pipeline. @@ -71,8 +71,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { genesis_hash, &self.finality_pipeline.target_sign, era, - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); Bytes(transaction.encode()) diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 0ced49a0a3146..2e91c99488a03 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -28,7 +28,7 @@ use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use substrate_relay_helper::messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, @@ -89,8 +89,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { genesis_hash, &self.message_lane.source_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", @@ -134,8 +133,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { genesis_hash, &self.message_lane.target_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", @@ -273,13 +271,15 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( genesis_hash, &signer, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - rialto_runtime::MessagesCall::update_pallet_parameter( - rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ), - ) - .into(), + UnsignedTransaction::new( + rialto_runtime::MessagesCall::update_pallet_parameter( + rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( + sp_runtime::FixedU128::from_float(updated_rate), + ), + ) + .into(), + transaction_nonce, + ), ) .encode(), ) diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 3cacce9a48b2e..32eb988c894d5 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -21,7 +21,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; @@ -90,8 +90,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { genesis_hash, &self.finality_pipeline.target_sign, era, - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); Bytes(transaction.encode()) diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 51f89c0dbe6df..78ed93372df76 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -26,7 +26,7 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use substrate_relay_helper::messages_lane::{ @@ -91,8 +91,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { genesis_hash, &self.message_lane.source_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", @@ -136,8 +135,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { genesis_hash, &self.message_lane.target_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 20464b99bfdee..cb81e20699c9a 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -21,7 +21,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; @@ -79,8 +79,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { genesis_hash, &self.finality_pipeline.target_sign, era, - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); Bytes(transaction.encode()) diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 4bb5b15fe047b..883e54c9837b1 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -21,7 +21,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; @@ -95,8 +95,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { genesis_hash, &self.finality_pipeline.target_sign, era, - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); Bytes(transaction.encode()) diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 9bc13dec1440d..f02e2da1e69b8 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -26,7 +26,7 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use substrate_relay_helper::messages_lane::{ @@ -90,8 +90,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { genesis_hash, &self.message_lane.source_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", @@ -135,8 +134,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { genesis_hash, &self.message_lane.target_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - call, + UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( target: "bridge", diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 76bc5aa273970..81663ed429a94 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -18,7 +18,7 @@ use crate::cli::{SourceConnectionParams, TargetConnectionParams, TargetSigningPa use bp_header_chain::InitializationData; use bp_runtime::Chain as ChainBase; use codec::Encode; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; use sp_core::{Bytes, Pair}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -151,8 +151,7 @@ impl InitBridge { *target_client.genesis_hash(), &target_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - encode_init_bridge(initialization_data), + UnsignedTransaction::new(encode_init_bridge(initialization_data), transaction_nonce), ) .encode(), ) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index c02f6b51306c3..4831373eae19c 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -35,6 +35,7 @@ mod init_bridge; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; +mod resubmit_transactions; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -86,6 +87,8 @@ pub enum Command { EstimateFee(estimate_fee::EstimateFee), /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. DeriveAccount(derive_account::DeriveAccount), + /// Resubmit transactions with increased tip if they are stalled. + ResubmitTransactions(resubmit_transactions::ResubmitTransactions), } impl Command { @@ -116,6 +119,7 @@ impl Command { Self::EncodeMessage(arg) => arg.run().await?, Self::EstimateFee(arg) => arg.run().await?, Self::DeriveAccount(arg) => arg.run().await?, + Self::ResubmitTransactions(arg) => arg.run().await?, } Ok(()) } @@ -360,7 +364,7 @@ macro_rules! declare_chain_options { ($chain:ident, $chain_prefix:ident) => { paste::item! { #[doc = $chain " connection params."] - #[derive(StructOpt, Debug, PartialEq, Eq)] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] pub struct [<$chain ConnectionParams>] { #[doc = "Connect to " $chain " node at given host."] #[structopt(long, default_value = "127.0.0.1")] diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs new file mode 100644 index 0000000000000..ee9801b3fdc6a --- /dev/null +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -0,0 +1,364 @@ +// 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 . + +use crate::cli::{TargetConnectionParams, TargetSigningParams}; + +use codec::{Decode, Encode}; +use num_traits::{One, Zero}; +use relay_substrate_client::{BlockWithJustification, Chain, Client, Error as SubstrateError, TransactionSignScheme}; +use relay_utils::FailedClient; +use sp_core::Bytes; +use sp_runtime::{ + traits::{Hash, Header as HeaderT}, + transaction_validity::TransactionPriority, +}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +/// Start resubmit transactions process. +#[derive(StructOpt)] +pub struct ResubmitTransactions { + /// A bridge instance to relay headers for. + #[structopt(possible_values = RelayChain::VARIANTS, case_insensitive = true)] + chain: RelayChain, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, +} + +/// Chain, which transactions we're going to track && resubmit. +#[derive(Debug, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +pub enum RelayChain { + Millau, +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + RelayChain::Millau => { + type Target = relay_millau_client::Millau; + type TargetSign = relay_millau_client::Millau; + + const TIP_STEP: bp_millau::Balance = 1_000_000; + const TIP_LIMIT: bp_millau::Balance = 1_000_000_000; + + const STALLED_BLOCKS: bp_millau::BlockNumber = 5; + + $generic + } + } + }; +} + +impl ResubmitTransactions { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.chain, { + let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); + let client = self.target.to_client::().await?; + let key_pair = self.target_sign.to_keypair::()?; + + relay_utils::relay_loop((), client) + .run(relay_loop_name, move |_, client, _| { + run_until_connection_lost::( + client, + key_pair.clone(), + Context { + transaction: None, + stalled_for: Zero::zero(), + stalled_for_limit: STALLED_BLOCKS, + tip_step: TIP_STEP, + tip_limit: TIP_LIMIT, + }, + ) + }) + .await + }) + } +} + +#[derive(Debug, Default)] +struct Context { + /// Hash of the (potentially) stalled transaction. + transaction: Option, + /// This transaction is in pool for `stalled_for` wakeup intervals. + stalled_for: C::BlockNumber, + /// When `stalled_for` reaching this limit, transaction is considered stalled. + stalled_for_limit: C::BlockNumber, + /// Tip step interval. + tip_step: C::Balance, + /// Maximal tip. + tip_limit: C::Balance, +} + +impl Context { + /// Return true if transaction has stalled. + fn is_stalled(&self) -> bool { + self.stalled_for >= self.stalled_for_limit + } + + /// Forget stalled transaction. + fn clear(mut self) -> Self { + self.transaction = None; + self.stalled_for = Zero::zero(); + self + } + + /// Notice transaction from the transaction pool. + fn notice_transaction(mut self, transaction: C::Hash) -> Self { + if self.transaction == Some(transaction) { + self.stalled_for += One::one(); + } else { + self.transaction = Some(transaction); + self.stalled_for = One::one(); + } + self + } +} + +/// Run resubmit transactions loop. +async fn run_until_connection_lost>( + client: Client, + key_pair: S::AccountKeyPair, + mut context: Context, +) -> Result<(), FailedClient> { + loop { + async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; + + let result = run_loop_iteration::(client.clone(), key_pair.clone(), context).await; + context = match result { + Ok(context) => context, + Err(error) => { + log::error!( + target: "bridge", + "Resubmit {} transactions loop has failed with error: {:?}", + C::NAME, + error, + ); + return Err(FailedClient::Target); + } + }; + } +} + +/// Run single loop iteration. +async fn run_loop_iteration>( + client: Client, + key_pair: S::AccountKeyPair, + context: Context, +) -> Result, SubstrateError> { + let original_transaction = match lookup_signer_transaction::(&client, &key_pair).await? { + Some(original_transaction) => original_transaction, + None => { + log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); + return Ok(context); + } + }; + let original_transaction_hash = C::Hasher::hash(&original_transaction.encode()); + let context = context.notice_transaction(original_transaction_hash); + + if !context.is_stalled() { + log::trace!( + target: "bridge", + "{} transaction {:?} is not yet stalled ({:?}/{:?})", + C::NAME, + context.transaction, + context.stalled_for, + context.stalled_for_limit, + ); + return Ok(context); + } + + let (best_block, target_priority) = match read_previous_best_priority::(&client).await? { + Some((best_block, target_priority)) => (best_block, target_priority), + None => { + log::trace!(target: "bridge", "Failed to read priority of best {} transaction in its best block", C::NAME); + return Ok(context); + } + }; + + let (is_updated, updated_transaction) = select_transaction_tip::( + &client, + &key_pair, + best_block, + original_transaction, + context.tip_step, + context.tip_limit, + target_priority, + ) + .await?; + + if !is_updated { + log::trace!(target: "bridge", "{} transaction tip can not be updated. Reached limit?", C::NAME); + return Ok(context); + } + + let updated_transaction = updated_transaction.encode(); + let updated_transaction_hash = C::Hasher::hash(&updated_transaction); + client.submit_unsigned_extrinsic(Bytes(updated_transaction)).await?; + + log::info!( + target: "bridge", + "Replaced {} transaction {} with {} in txpool", + C::NAME, + original_transaction_hash, + updated_transaction_hash, + ); + + Ok(context.clear()) +} + +/// Search transaction pool for transaction, signed by given key pair. +async fn lookup_signer_transaction>( + client: &Client, + key_pair: &S::AccountKeyPair, +) -> Result, SubstrateError> { + let pending_transactions = client.pending_extrinsics().await?; + for pending_transaction in pending_transactions { + let pending_transaction = S::SignedTransaction::decode(&mut &pending_transaction.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; + if !S::is_signed_by(key_pair, &pending_transaction) { + continue; + } + + return Ok(Some(pending_transaction)); + } + + Ok(None) +} + +/// Read priority of best signed transaction of previous block. +async fn read_previous_best_priority>( + client: &Client, +) -> Result, SubstrateError> { + let best_header = client.best_header().await?; + let best_header_hash = best_header.hash(); + let best_block = client.get_block(Some(best_header_hash)).await?; + let best_transaction = best_block + .extrinsics() + .iter() + .filter_map(|xt| S::SignedTransaction::decode(&mut &xt[..]).ok()) + .find(|xt| S::is_signed(xt)); + match best_transaction { + Some(best_transaction) => Ok(Some(( + best_header_hash, + client + .validate_transaction(*best_header.parent_hash(), best_transaction) + .await?? + .priority, + ))), + None => Ok(None), + } +} + +/// Try to find appropriate tip for transaction so that its priority is larger than given. +async fn select_transaction_tip>( + client: &Client, + key_pair: &S::AccountKeyPair, + at_block: C::Hash, + tx: S::SignedTransaction, + tip_step: C::Balance, + tip_limit: C::Balance, + target_priority: TransactionPriority, +) -> Result<(bool, S::SignedTransaction), SubstrateError> { + let stx = format!("{:?}", tx); + let mut current_priority = client.validate_transaction(at_block, tx.clone()).await??.priority; + let mut unsigned_tx = S::parse_transaction(tx) + .ok_or_else(|| SubstrateError::Custom(format!("Failed to parse {} transaction {}", C::NAME, stx,)))?; + let old_tip = unsigned_tx.tip; + + while current_priority < target_priority { + let next_tip = unsigned_tx.tip + tip_step; + if next_tip > tip_limit { + break; + } + + log::trace!( + target: "bridge", + "{} transaction priority with tip={:?}: {}. Target priority: {}", + C::NAME, + unsigned_tx.tip, + current_priority, + target_priority, + ); + + unsigned_tx.tip = next_tip; + current_priority = client + .validate_transaction( + at_block, + S::sign_transaction( + *client.genesis_hash(), + key_pair, + relay_substrate_client::TransactionEra::immortal(), + unsigned_tx.clone(), + ), + ) + .await?? + .priority; + } + + log::debug!( + target: "bridge", + "{} transaction tip has changed from {:?} to {:?}", + C::NAME, + old_tip, + unsigned_tx.tip, + ); + + Ok(( + old_tip != unsigned_tx.tip, + S::sign_transaction( + *client.genesis_hash(), + key_pair, + relay_substrate_client::TransactionEra::immortal(), + unsigned_tx, + ), + )) +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_rialto_client::Rialto; + + #[test] + fn context_works() { + let mut context: Context = Context { + transaction: None, + stalled_for: Zero::zero(), + stalled_for_limit: 3, + tip_step: 100, + tip_limit: 1000, + }; + + // when transaction is noticed 2/3 times, it isn't stalled + context = context.notice_transaction(Default::default()); + assert!(!context.is_stalled()); + context = context.notice_transaction(Default::default()); + assert!(!context.is_stalled()); + + // when transaction is noticed for 3rd time in a row, it is considered stalled + context = context.notice_transaction(Default::default()); + assert!(context.is_stalled()); + + // and after we resubmit it, we forget previous transaction + context = context.clear(); + assert_eq!(context.transaction, None); + assert_eq!(context.stalled_for, 0); + } +} diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index aa9a5970596c0..ad02e126b0080 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -24,7 +24,7 @@ use crate::cli::{ use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; use std::fmt::Debug; @@ -183,8 +183,7 @@ impl SendMessage { source_genesis_hash, &source_sign, relay_substrate_client::TransactionEra::immortal(), - 0, - send_message_call.clone(), + UnsignedTransaction::new(send_message_call.clone(), 0), ) .encode(), )) @@ -195,8 +194,7 @@ impl SendMessage { source_genesis_hash, &source_sign, relay_substrate_client::TransactionEra::immortal(), - transaction_nonce, - send_message_call, + UnsignedTransaction::new(send_message_call, transaction_nonce), ) .encode(); diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 36430dd83dc21..eaf677634e1b8 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -16,8 +16,10 @@ //! Types used to connect to the Millau-Substrate chain. -use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use codec::{Compact, Decode, Encode}; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -67,20 +69,19 @@ impl TransactionSignScheme for Millau { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, - era: relay_substrate_client::TransactionEraOf, - signer_nonce: ::Index, - call: ::Call, + era: TransactionEraOf, + unsigned: UnsignedTransaction, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::from_raw( - call, + unsigned.call, ( frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(era.frame_era()), - frame_system::CheckNonce::::from(signer_nonce), + frame_system::CheckNonce::::from(unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), + pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), ), ( millau_runtime::VERSION.spec_version, @@ -98,6 +99,30 @@ impl TransactionSignScheme for Millau { millau_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == millau_runtime::Address::from(*signer.public().as_array_ref())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { + call: tx.function, + nonce: Compact::<::Index>::decode(&mut &extra.4.encode()[..]) + .ok()? + .into(), + tip: Compact::<::Balance>::decode(&mut &extra.6.encode()[..]) + .ok()? + .into(), + }) + } } /// Millau signing params. diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 8024ab1fdce56..459ea5bc4e94b 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -16,8 +16,10 @@ //! Types used to connect to the Rialto-Substrate chain. -use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use codec::{Compact, Decode, Encode}; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -67,20 +69,19 @@ impl TransactionSignScheme for Rialto { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, - era: relay_substrate_client::TransactionEraOf, - signer_nonce: ::Index, - call: ::Call, + era: TransactionEraOf, + unsigned: UnsignedTransaction, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::from_raw( - call, + unsigned.call, ( frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from(era.frame_era()), - frame_system::CheckNonce::::from(signer_nonce), + frame_system::CheckNonce::::from(unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), + pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), ), ( rialto_runtime::VERSION.spec_version, @@ -98,6 +99,30 @@ impl TransactionSignScheme for Rialto { rialto_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == rialto_runtime::Address::from(*signer.public().as_array_ref())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { + call: tx.function, + nonce: Compact::<::Index>::decode(&mut &extra.4.encode()[..]) + .ok()? + .into(), + tip: Compact::<::Balance>::decode(&mut &extra.6.encode()[..]) + .ok()? + .into(), + }) + } } /// Rialto signing params. diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index c419610dad05c..5694d183d7825 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -17,7 +17,9 @@ //! Types used to connect to the Rococo-Substrate chain. use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -69,13 +71,12 @@ impl TransactionSignScheme for Rococo { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, - era: relay_substrate_client::TransactionEraOf, - signer_nonce: ::Index, - call: ::Call, + era: TransactionEraOf, + unsigned: UnsignedTransaction, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( - call, - bp_rococo::SignedExtensions::new(bp_rococo::VERSION, era, genesis_hash, signer_nonce, 0), + unsigned.call, + bp_rococo::SignedExtensions::new(bp_rococo::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), ) .expect("SignedExtension never fails."); @@ -90,6 +91,26 @@ impl TransactionSignScheme for Rococo { extra, ) } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == bp_rococo::AccountId::from(*signer.public().as_array_ref()).into()) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { + call: tx.function, + nonce: extra.nonce(), + tip: extra.tip(), + }) + } } /// Rococo signing params. diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 81397e2c4ae30..627c01eb0edca 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bp_runtime::Chain as ChainBase; +use bp_runtime::{Chain as ChainBase, TransactionEraOf}; +use codec::{Codec, Encode}; use frame_support::{weights::WeightToFeePolynomial, Parameter}; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; use num_traits::{Bounded, CheckedSub, SaturatingAdd, Zero}; @@ -58,7 +59,7 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Dispatchable + Debug; + type Call: Clone + Dispatchable + Debug; /// Balance of an account in native tokens. /// /// The chain may support multiple tokens, but this particular type is for token that is used @@ -96,14 +97,47 @@ pub trait ChainWithBalances: Chain { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey; } +/// SCALE-encoded extrinsic. +pub type EncodedExtrinsic = Vec; + /// Block with justification. pub trait BlockWithJustification

{ /// Return block header. fn header(&self) -> Header; + /// Return encoded block extrinsics. + fn extrinsics(&self) -> Vec; /// Return block justification, if known. fn justification(&self) -> Option<&EncodedJustification>; } +/// Transaction before it is signed. +#[derive(Clone, Debug)] +pub struct UnsignedTransaction { + /// Runtime call of this transaction. + pub call: C::Call, + /// Transaction nonce. + pub nonce: C::Index, + /// Tip included into transaction. + pub tip: C::Balance, +} + +impl UnsignedTransaction { + /// Create new unsigned transaction with given call, nonce and zero tip. + pub fn new(call: C::Call, nonce: C::Index) -> Self { + Self { + call, + nonce, + tip: Zero::zero(), + } + } + + /// Set transaction tip. + pub fn tip(mut self, tip: C::Balance) -> Self { + self.tip = tip; + self + } +} + /// Substrate-based chain transactions signing scheme. pub trait TransactionSignScheme { /// Chain that this scheme is to be used. @@ -111,16 +145,26 @@ pub trait TransactionSignScheme { /// Type of key pairs used to sign transactions. type AccountKeyPair: Pair; /// Signed transaction. - type SignedTransaction; + type SignedTransaction: Clone + Debug + Codec + Send + 'static; /// Create transaction for given runtime call, signed by given account. fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, - era: bp_runtime::TransactionEraOf, - signer_nonce: ::Index, - call: ::Call, + era: TransactionEraOf, + unsigned: UnsignedTransaction, ) -> Self::SignedTransaction; + + /// Returns true if transaction is signed. + fn is_signed(tx: &Self::SignedTransaction) -> bool; + + /// Returns true if transaction is signed by given signer. + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool; + + /// Parse signed transaction into its unsigned part. + /// + /// Returns `None` if signed transaction has unsupported format. + fn parse_transaction(tx: Self::SignedTransaction) -> Option>; } impl BlockWithJustification for SignedBlock { @@ -128,6 +172,10 @@ impl BlockWithJustification for SignedBlock self.block.header().clone() } + fn extrinsics(&self) -> Vec { + self.block.extrinsics().iter().map(Encode::encode).collect() + } + fn justification(&self) -> Option<&EncodedJustification> { self.justifications .as_ref() diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 9fb778651b475..bd239a5a5f74a 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -21,7 +21,8 @@ use crate::rpc::Substrate; use crate::{ConnectionParams, Error, HeaderIdOf, Result}; use async_std::sync::{Arc, Mutex}; -use codec::Decode; +use async_trait::async_trait; +use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned}; @@ -31,12 +32,16 @@ use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::traits::Header as HeaderT; +use sp_runtime::{ + traits::Header as HeaderT, + transaction_validity::{TransactionSource, TransactionValidity}, +}; use sp_trie::StorageProof; use sp_version::RuntimeVersion; use std::{convert::TryFrom, future::Future}; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; +const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_validate_transaction"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// Opaque justifications subscription type. @@ -63,6 +68,18 @@ pub struct Client { submit_signed_extrinsic_lock: Arc>, } +#[async_trait] +impl relay_utils::relay_loop::Client for Client { + type Error = Error; + + async fn reconnect(&mut self) -> Result<()> { + let (tokio, client) = Self::build_client(self.params.clone()).await?; + self.tokio = tokio; + self.client = client; + Ok(()) + } +} + impl Clone for Client { fn clone(&self) -> Self { Client { @@ -125,14 +142,6 @@ impl Client { }) } - /// Reopen client connection. - pub async fn reconnect(&mut self) -> Result<()> { - let (tokio, client) = Self::build_client(self.params.clone()).await?; - self.tokio = tokio; - self.client = client; - Ok(()) - } - /// Build client to use in connection. async fn build_client(params: ConnectionParams) -> Result<(Arc, Arc)> { let tokio = tokio::runtime::Runtime::new()?; @@ -309,6 +318,33 @@ impl Client { .await } + /// Returns pending extrinsics from transaction pool. + pub async fn pending_extrinsics(&self) -> Result> { + self.jsonrpsee_execute( + move |client| async move { Ok(Substrate::::author_pending_extrinsics(&*client).await?) }, + ) + .await + } + + /// Validate transaction at given block state. + pub async fn validate_transaction( + &self, + at_block: C::Hash, + transaction: SignedTransaction, + ) -> Result { + self.jsonrpsee_execute(move |client| async move { + let call = SUB_API_TXPOOL_VALIDATE_TRANSACTION.to_string(); + let data = Bytes((TransactionSource::External, transaction, at_block).encode()); + + let encoded_response = Substrate::::state_call(&*client, call, data, Some(at_block)).await?; + let validity = + TransactionValidity::decode(&mut &encoded_response.0[..]).map_err(Error::ResponseParseFailed)?; + + Ok(validity) + }) + .await + } + /// Estimate fee that will be spent on given extrinsic. pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result> { self.jsonrpsee_execute(move |client| async move { diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index f06079ef5facf..187b4a1e633f5 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -19,6 +19,7 @@ use jsonrpsee_ws_client::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; +use sp_runtime::transaction_validity::TransactionValidityError; /// Result type used by Substrate client. pub type Result = std::result::Result; @@ -44,6 +45,8 @@ pub enum Error { ClientNotSynced(Health), /// An error has happened when we have tried to parse storage proof. StorageProofError(bp_runtime::StorageProofError), + /// The Substrate transaction is invalid. + TransactionInvalid(TransactionValidityError), /// Custom logic error. Custom(String), } @@ -59,6 +62,7 @@ impl std::error::Error for Error { Self::MissingMandatoryCodeEntry => None, Self::ClientNotSynced(_) => None, Self::StorageProofError(_) => None, + Self::TransactionInvalid(_) => None, Self::Custom(_) => None, } } @@ -82,6 +86,12 @@ impl From for Error { } } +impl From for Error { + fn from(error: TransactionValidityError) -> Self { + Error::TransactionInvalid(error) + } +} + impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( @@ -105,6 +115,7 @@ impl std::fmt::Display for Error { Self::MissingMandatoryCodeEntry => "Mandatory :code: entry is missing from runtime storage".into(), Self::StorageProofError(e) => format!("Error when parsing storage proof: {:?}", e), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), + Self::TransactionInvalid(e) => format!("Substrate transaction is invalid: {:?}", e), Self::Custom(e) => e.clone(), }; diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index be1835df3227d..b607b68f8b05a 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -32,7 +32,8 @@ pub mod metrics; use std::time::Duration; pub use crate::chain::{ - BalanceOf, BlockWithJustification, Chain, ChainWithBalances, IndexOf, TransactionSignScheme, WeightToFeeOf, + BalanceOf, BlockWithJustification, Chain, ChainWithBalances, IndexOf, TransactionSignScheme, UnsignedTransaction, + WeightToFeeOf, }; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index ddc8c92f77b4b..61d2562672d29 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -43,6 +43,8 @@ jsonrpsee_proc_macros::rpc_client_api! { fn system_account_next_index(account_id: C::AccountId) -> C::Index; #[rpc(method = "author_submitExtrinsic", positional_params)] fn author_submit_extrinsic(extrinsic: Bytes) -> C::Hash; + #[rpc(method = "author_pendingExtrinsics", positional_params)] + fn author_pending_extrinsics() -> Vec; #[rpc(method = "state_call", positional_params)] fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; #[rpc(method = "state_getStorage", positional_params)] diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index b33be7421cf44..726a699e3ce03 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,10 +16,8 @@ //! Types used to connect to the Westend chain. -use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances}; +use sp_core::storage::StorageKey; use std::time::Duration; /// Westend header id. @@ -58,37 +56,3 @@ impl ChainWithBalances for Westend { StorageKey(bp_westend::account_info_storage_key(account_id)) } } - -impl TransactionSignScheme for Westend { - type Chain = Westend; - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_westend::UncheckedExtrinsic; - - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: relay_substrate_client::TransactionEraOf, - signer_nonce: ::Index, - call: ::Call, - ) -> Self::SignedTransaction { - let raw_payload = SignedPayload::new( - call, - bp_westend::SignedExtensions::new(bp_westend::VERSION, era, genesis_hash, signer_nonce, 0), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - bp_westend::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - ) - } -} - -/// Westend signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 03cb4d71563f7..eac2aa841bcce 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -17,7 +17,9 @@ //! Types used to connect to the Wococo-Substrate chain. use codec::Encode; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, TransactionSignScheme}; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -69,13 +71,12 @@ impl TransactionSignScheme for Wococo { fn sign_transaction( genesis_hash: ::Hash, signer: &Self::AccountKeyPair, - era: bp_runtime::TransactionEraOf, - signer_nonce: ::Index, - call: ::Call, + era: TransactionEraOf, + unsigned: UnsignedTransaction, ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( - call, - bp_wococo::SignedExtensions::new(bp_wococo::VERSION, era, genesis_hash, signer_nonce, 0), + unsigned.call, + bp_wococo::SignedExtensions::new(bp_wococo::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), ) .expect("SignedExtension never fails."); @@ -90,6 +91,26 @@ impl TransactionSignScheme for Wococo { extra, ) } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == bp_wococo::AccountId::from(*signer.public().as_array_ref()).into()) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { + call: tx.function, + nonce: extra.nonce(), + tip: extra.tip(), + }) + } } /// Wococo signing params. diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 38b636a599c24..ef8ebf4e8a28d 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -34,6 +34,15 @@ pub trait Client: 'static + Clone + Send + Sync { async fn reconnect(&mut self) -> Result<(), Self::Error>; } +#[async_trait] +impl Client for () { + type Error = crate::StringifiedMaybeConnectionError; + + async fn reconnect(&mut self) -> Result<(), Self::Error> { + Ok(()) + } +} + /// Returns generic loop that may be customized and started. pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { Loop { From 76c94cefa6ddc7a9c5553d2a6837d1b0cf5d1c46 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Sep 2021 11:19:39 +0300 Subject: [PATCH 0557/1210] Move some associated types from relay_substrate_client::Chain to bp_runtime::Chain (#1087) * move some associated types from relay_substrate_client::Chain to bp_runtime::Chain * dummy commit * Revert "dummy commit" This reverts commit 81bc64aa092df115a7c68e7bb7ca5e83ec31fd20. --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- modules/grandpa/src/mock.rs | 7 +- modules/token-swap/src/lib.rs | 88 +++++++++++-------- modules/token-swap/src/mock.rs | 23 +++-- primitives/chain-millau/src/lib.rs | 8 ++ primitives/chain-rialto/src/lib.rs | 8 ++ primitives/polkadot-core/src/lib.rs | 5 ++ primitives/runtime/src/chain.rs | 65 ++++++++++++-- primitives/runtime/src/lib.rs | 5 +- .../src/chains/millau_headers_to_rialto.rs | 4 +- .../src/chains/millau_messages_to_rialto.rs | 6 +- .../src/chains/rialto_headers_to_millau.rs | 4 +- .../src/chains/rialto_messages_to_millau.rs | 6 +- .../src/chains/rococo_headers_to_wococo.rs | 4 +- .../src/chains/rococo_messages_to_wococo.rs | 6 +- .../src/chains/westend_headers_to_millau.rs | 4 +- .../src/chains/wococo_headers_to_rococo.rs | 4 +- .../src/chains/wococo_messages_to_rococo.rs | 6 +- relays/bin-substrate/src/cli/estimate_fee.rs | 3 +- relays/bin-substrate/src/cli/send_message.rs | 3 +- relays/client-kusama/src/lib.rs | 8 +- relays/client-millau/src/lib.rs | 15 ++-- relays/client-polkadot/src/lib.rs | 8 +- relays/client-rialto/src/lib.rs | 15 ++-- relays/client-rococo/src/lib.rs | 8 +- relays/client-substrate/src/chain.rs | 45 +--------- relays/client-substrate/src/guard.rs | 11 ++- relays/client-substrate/src/lib.rs | 7 +- relays/client-westend/src/lib.rs | 8 +- relays/client-wococo/src/lib.rs | 8 +- .../src/finality_pipeline.rs | 5 +- .../lib-substrate-relay/src/messages_lane.rs | 9 +- .../src/messages_target.rs | 6 +- 34 files changed, 254 insertions(+), 162 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1eb77ed75ea63..7469ebfec1734 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -89,7 +89,7 @@ pub type AccountIndex = u32; pub type Balance = bp_millau::Balance; /// Index of a transaction in the chain. -pub type Index = u32; +pub type Index = bp_millau::Index; /// A hash of some data used by the chain. pub type Hash = bp_millau::Hash; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index c13c0d78a1b40..8b46020a1bdf0 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -95,7 +95,7 @@ pub type AccountIndex = u32; pub type Balance = bp_rialto::Balance; /// Index of a transaction in the chain. -pub type Index = u32; +pub type Index = bp_rialto::Index; /// A hash of some data used by the chain. pub type Hash = bp_rialto::Hash; diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 20f5ea7bdf7a1..363594c35f33d 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -22,7 +22,7 @@ use frame_support::{construct_runtime, parameter_types, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, IdentityLookup}, - Perbill, + AnySignature, Perbill, }; pub type AccountId = u64; @@ -101,6 +101,11 @@ impl Chain for TestBridgedChain { type Hash = ::Hash; type Hasher = ::Hashing; type Header = ::Header; + + type AccountId = AccountId; + type Balance = u64; + type Index = u64; + type Signature = AnySignature; } pub fn run_test(test: impl FnOnce() -> T) -> T { diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index dde25d8cb2b09..206f040b96272 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -122,25 +122,30 @@ pub mod pallet { /// Converter from raw hash (derived from swap) to This chain account. type FromSwapToThisAccountIdConverter: Convert; - /// Tokens balance type at the Bridged chain. - type BridgedBalance: Parameter; - /// Account identifier type at the Bridged chain. - type BridgedAccountId: Parameter; - /// Account public key type at the Bridged chain. - type BridgedAccountPublic: Parameter; - /// Account signature type at the Bridged chain. - type BridgedAccountSignature: Parameter; + /// The chain we're bridged to. + type BridgedChain: bp_runtime::Chain; /// Converter from raw hash (derived from Bridged chain account) to This chain account. type FromBridgedToThisAccountIdConverter: Convert; } + /// Type of the Bridged chain. + pub type BridgedChainOf = >::BridgedChain; + /// Tokens balance type at the Bridged chain. + pub type BridgedBalanceOf = bp_runtime::BalanceOf>; + /// Account identifier type at the Bridged chain. + pub type BridgedAccountIdOf = bp_runtime::AccountIdOf>; + /// Account public key type at the Bridged chain. + pub type BridgedAccountPublicOf = bp_runtime::AccountPublicOf>; + /// Account signature type at the Bridged chain. + pub type BridgedAccountSignatureOf = bp_runtime::SignatureOf>; + /// SCALE-encoded `Currency::transfer` call on the bridged chain. pub type RawBridgedTransferCall = Vec; /// Bridge message payload used by the pallet. pub type MessagePayloadOf = bp_message_dispatch::MessagePayload< ::AccountId, - >::BridgedAccountPublic, - >::BridgedAccountSignature, + BridgedAccountPublicOf, + BridgedAccountSignatureOf, RawBridgedTransferCall, >; /// Type of `TokenSwap` used by the pallet. @@ -148,8 +153,8 @@ pub mod pallet { BlockNumberFor, <>::ThisCurrency as Currency<::AccountId>>::Balance, ::AccountId, - >::BridgedBalance, - >::BridgedAccountId, + BridgedBalanceOf, + BridgedAccountIdOf, >; #[pallet::pallet] @@ -160,7 +165,10 @@ pub mod pallet { impl, I: 'static> Hooks> for Pallet {} #[pallet::call] - impl, I: 'static> Pallet { + impl, I: 'static> Pallet + where + BridgedAccountPublicOf: Parameter, + { /// Start token swap procedure. /// /// The dispatch origin for this call must be exactly the `swap.source_account_at_this_chain` account. @@ -194,11 +202,11 @@ pub mod pallet { pub fn create_swap( origin: OriginFor, swap: TokenSwapOf, - target_public_at_bridged_chain: T::BridgedAccountPublic, + target_public_at_bridged_chain: BridgedAccountPublicOf, bridged_chain_spec_version: u32, bridged_currency_transfer: RawBridgedTransferCall, bridged_currency_transfer_weight: Weight, - bridged_currency_transfer_signature: T::BridgedAccountSignature, + bridged_currency_transfer_signature: BridgedAccountSignatureOf, ) -> DispatchResultWithPostInfo { // ensure that the `origin` is the same account that is mentioned in the `swap` intention let origin_account = ensure_signed(origin)?; @@ -541,12 +549,18 @@ mod tests { const CAN_START_BLOCK_NUMBER: u64 = 10; const CAN_CLAIM_BLOCK_NUMBER: u64 = CAN_START_BLOCK_NUMBER + 1; - const BRIDGED_CHAIN_ACCOUNT_PUBLIC: BridgedAccountPublic = 1; - const BRIDGED_CHAIN_ACCOUNT_SIGNATURE: BridgedAccountSignature = 2; const BRIDGED_CHAIN_ACCOUNT: BridgedAccountId = 3; const BRIDGED_CHAIN_SPEC_VERSION: u32 = 4; const BRIDGED_CHAIN_CALL_WEIGHT: Balance = 5; + fn bridged_chain_account_public() -> BridgedAccountPublic { + 1.into() + } + + fn bridged_chain_account_signature() -> BridgedAccountSignature { + sp_runtime::testing::TestSignature(2, Vec::new()) + } + fn test_swap() -> TokenSwapOf { bp_token_swap::TokenSwap { swap_type: TokenSwapType::LockClaimUntilBlock(CAN_START_BLOCK_NUMBER, 0.into()), @@ -569,11 +583,11 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), )); } @@ -591,11 +605,11 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), ), Error::::MismatchedSwapSourceOrigin ); @@ -611,11 +625,11 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), swap, - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), ), Error::::TooLowBalanceOnThisChain ); @@ -631,11 +645,11 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), swap, - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), ), Error::::FailedToTransferToSwapAccount ); @@ -651,11 +665,11 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, transfer, BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), ), Error::::FailedToSendTransferMessage ); @@ -668,22 +682,22 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), )); assert_noop!( Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), ), Error::::SwapAlreadyStarted ); @@ -698,11 +712,11 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), ), Error::::SwapPeriodIsFinished ); @@ -716,11 +730,11 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), )); }); } @@ -734,11 +748,11 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - BRIDGED_CHAIN_ACCOUNT_PUBLIC, + bridged_chain_account_public(), BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, - BRIDGED_CHAIN_ACCOUNT_SIGNATURE, + bridged_chain_account_signature(), )); let swap_hash = test_swap_hash(); diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index c91933cce419b..603db2adec7c8 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -31,8 +31,8 @@ pub type AccountId = u64; pub type Balance = u64; pub type Block = frame_system::mocking::MockBlock; pub type BridgedAccountId = u64; -pub type BridgedAccountPublic = u64; -pub type BridgedAccountSignature = u64; +pub type BridgedAccountPublic = sp_runtime::testing::UintAuthorityId; +pub type BridgedAccountSignature = sp_runtime::testing::TestSignature; pub type BridgedBalance = u64; pub type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -122,13 +122,24 @@ impl pallet_bridge_token_swap::Config for TestRuntime { type ThisCurrency = pallet_balances::Pallet; type FromSwapToThisAccountIdConverter = TestAccountConverter; - type BridgedBalance = BridgedBalance; - type BridgedAccountId = BridgedAccountId; - type BridgedAccountPublic = BridgedAccountPublic; - type BridgedAccountSignature = BridgedAccountSignature; + type BridgedChain = BridgedChain; type FromBridgedToThisAccountIdConverter = TestAccountConverter; } +pub struct BridgedChain; + +impl bp_runtime::Chain for BridgedChain { + type BlockNumber = u64; + type Hash = H256; + type Hasher = BlakeTwo256; + type Header = sp_runtime::generic::Header; + + type AccountId = BridgedAccountId; + type Balance = BridgedBalance; + type Index = u64; + type Signature = BridgedAccountSignature; +} + pub struct TestMessagesBridge; impl MessagesBridge> for TestMessagesBridge { diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index cb732bccfa055..b2bf5cf0b18ab 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -149,6 +149,9 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u64; +/// Index of a transaction in the chain. +pub type Index = u32; + /// Weight-to-Fee type used by Millau. pub type WeightToFee = IdentityFee; @@ -161,6 +164,11 @@ impl Chain for Millau { type Hash = Hash; type Hasher = Hasher; type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; } /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 14edd1c227499..b7b382f52bca6 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -148,6 +148,9 @@ pub type Balance = u128; /// An instant or duration in time. pub type Moment = u64; +/// Index of a transaction in the chain. +pub type Index = u32; + /// Weight-to-Fee type used by Rialto. pub type WeightToFee = IdentityFee; @@ -160,6 +163,11 @@ impl Chain for Rialto { type Hash = Hash; type Hasher = Hasher; type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; } /// Convert a 256-bit hash into an AccountId. diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 3083112316fae..9e8726734eeda 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -342,6 +342,11 @@ impl Chain for PolkadotLike { type Hash = Hash; type Hasher = Hasher; type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; } /// Convert a 256-bit hash into an AccountId. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 270e2d7b2fcb9..2d7325641bac5 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -15,12 +15,15 @@ // along with Parity Bridges Common. If not, see . 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 @@ -54,7 +57,7 @@ pub trait Chain: Send + Sync + 'static { type Hash: Parameter + Member + MaybeSerializeDeserialize - + sp_std::hash::Hash + + Hash + Ord + Copy + MaybeDisplay @@ -75,6 +78,39 @@ pub trait Chain: Send + Sync + 'static { // See here for more info: // https://crates.parity.io/sp_runtime/traits/trait.Header.html type Header: Parameter + HeaderT + 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; + /// 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. @@ -89,5 +125,20 @@ pub type HasherOf = ::Hasher; /// Header type used by the chain. pub type HeaderOf = ::Header; +/// Account id type used by the chain. +pub type AccountIdOf = ::AccountId; + +/// Balance type used by the chain. +pub type BalanceOf = ::Balance; + +/// Transaction index type used by the chain. +pub type IndexOf = ::Index; + +/// Signature type used by the chain. +pub type SignatureOf = ::Signature; + +/// Account public type used by the chain. +pub type AccountPublicOf = as Verify>::Signer; + /// Transaction era used by the chain. pub type TransactionEraOf = crate::TransactionEra, HashOf>; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index fa1586c792c7d..659d5c0aacb11 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -24,7 +24,10 @@ use sp_core::hash::H256; use sp_io::hashing::blake2_256; use sp_std::convert::TryFrom; -pub use chain::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, TransactionEraOf}; +pub use chain::{ + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, IndexOf, SignatureOf, + TransactionEraOf, +}; pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; #[cfg(feature = "std")] diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 4fa9d83e586d7..fa51200b6f879 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -22,7 +22,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Millau-to-Rialto finality sync pipeline. @@ -55,7 +55,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { fn make_submit_finality_proof_transaction( &self, era: bp_runtime::TransactionEraOf, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, header: MillauSyncHeader, proof: GrandpaJustification, ) -> Bytes { diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index a4dedaed1ecae..b0c63ff088365 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -28,7 +28,7 @@ use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use substrate_relay_helper::messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, @@ -76,7 +76,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { fn make_messages_receiving_proof_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_block: RialtoHeaderId, proof: ::MessagesReceivingProof, ) -> Bytes { @@ -108,7 +108,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { fn make_messages_delivery_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, proof: ::MessagesProof, diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index d2e0f5e663208..4f649702b7a3c 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -22,7 +22,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; /// Rialto-to-Millau finality sync pipeline. @@ -56,7 +56,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { fn make_submit_finality_proof_transaction( &self, era: bp_runtime::TransactionEraOf, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, header: RialtoSyncHeader, proof: GrandpaJustification, ) -> Bytes { diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 2e91c99488a03..0196329fb812d 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -28,7 +28,7 @@ use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use substrate_relay_helper::messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, @@ -76,7 +76,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { fn make_messages_receiving_proof_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_block: MillauHeaderId, proof: ::MessagesReceivingProof, ) -> Bytes { @@ -108,7 +108,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { fn make_messages_delivery_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_header: RialtoHeaderId, _nonces: RangeInclusive, proof: ::MessagesProof, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 32eb988c894d5..5d8cf255398c5 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -21,7 +21,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; @@ -78,7 +78,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { fn make_submit_finality_proof_transaction( &self, era: bp_runtime::TransactionEraOf, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, header: RococoSyncHeader, proof: GrandpaJustification, ) -> Bytes { diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 78ed93372df76..de2d8c7263e5c 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -26,7 +26,7 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use substrate_relay_helper::messages_lane::{ @@ -75,7 +75,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { fn make_messages_receiving_proof_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_block: WococoHeaderId, proof: ::MessagesReceivingProof, ) -> Bytes { @@ -109,7 +109,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { fn make_messages_delivery_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_header: RococoHeaderId, _nonces: RangeInclusive, proof: ::MessagesProof, diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index cb81e20699c9a..8501ff41868a0 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -21,7 +21,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; @@ -64,7 +64,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { fn make_submit_finality_proof_transaction( &self, era: bp_runtime::TransactionEraOf, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, header: WestendSyncHeader, proof: GrandpaJustification, ) -> Bytes { diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 883e54c9837b1..b3e98d65421ec 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -21,7 +21,7 @@ use sp_core::{Bytes, Pair}; use bp_header_chain::justification::GrandpaJustification; use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; @@ -83,7 +83,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { fn make_submit_finality_proof_transaction( &self, era: bp_runtime::TransactionEraOf, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, header: WococoSyncHeader, proof: GrandpaJustification, ) -> Bytes { diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index f02e2da1e69b8..035c8f3948365 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -26,7 +26,7 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use substrate_relay_helper::messages_lane::{ @@ -74,7 +74,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { fn make_messages_receiving_proof_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_block: RococoHeaderId, proof: ::MessagesReceivingProof, ) -> Bytes { @@ -108,7 +108,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { fn make_messages_delivery_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, _generated_at_header: WococoHeaderId, _nonces: RangeInclusive, proof: ::MessagesProof, diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 2fa7918fafd2d..7e4cbf5b6b8ff 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -17,6 +17,7 @@ use crate::cli::bridge::FullBridge; use crate::cli::{Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}; use crate::select_full_bridge; +use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -53,7 +54,7 @@ impl EstimateFee { let lane = lane.into(); let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; - let fee: ::Balance = + let fee: BalanceOf = estimate_message_delivery_and_dispatch_fee(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload) .await?; diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index ad02e126b0080..66c2f17755610 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -22,6 +22,7 @@ use crate::cli::{ TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::BalanceOf; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; @@ -159,7 +160,7 @@ impl SendMessage { let fee = match self.fee { Some(fee) => fee, None => Balance( - estimate_message_delivery_and_dispatch_fee::<::Balance, _, _>( + estimate_message_delivery_and_dispatch_fee::, _, _>( &source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 0c94e73aecff6..95a8596c97fbf 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -31,6 +31,11 @@ impl ChainBase for Kusama { type Hash = bp_kusama::Hash; type Hasher = bp_kusama::Hasher; type Header = bp_kusama::Header; + + type AccountId = bp_kusama::AccountId; + type Balance = bp_kusama::Balance; + type Index = bp_kusama::Nonce; + type Signature = bp_kusama::Signature; } impl Chain for Kusama { @@ -39,11 +44,8 @@ impl Chain for Kusama { const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = bp_kusama::AccountId; - type Index = bp_kusama::Nonce; type SignedBlock = bp_kusama::SignedBlock; type Call = (); - type Balance = bp_kusama::Balance; type WeightToFee = bp_kusama::WeightToFee; } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index eaf677634e1b8..aa20fe76cb765 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -18,7 +18,8 @@ use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -36,6 +37,11 @@ impl ChainBase for Millau { type Hash = millau_runtime::Hash; type Hasher = millau_runtime::Hashing; type Header = millau_runtime::Header; + + type AccountId = millau_runtime::AccountId; + type Balance = millau_runtime::Balance; + type Index = millau_runtime::Index; + type Signature = millau_runtime::Signature; } impl Chain for Millau { @@ -44,11 +50,8 @@ impl Chain for Millau { const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = millau_runtime::AccountId; - type Index = millau_runtime::Index; type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::Call; - type Balance = millau_runtime::Balance; type WeightToFee = bp_millau::WeightToFee; } @@ -115,10 +118,10 @@ impl TransactionSignScheme for Millau { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { call: tx.function, - nonce: Compact::<::Index>::decode(&mut &extra.4.encode()[..]) + nonce: Compact::>::decode(&mut &extra.4.encode()[..]) .ok()? .into(), - tip: Compact::<::Balance>::decode(&mut &extra.6.encode()[..]) + tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? .into(), }) diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index dc5564cc17bb5..5882d917bf2f5 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -31,6 +31,11 @@ impl ChainBase for Polkadot { type Hash = bp_polkadot::Hash; type Hasher = bp_polkadot::Hasher; type Header = bp_polkadot::Header; + + type AccountId = bp_polkadot::AccountId; + type Balance = bp_polkadot::Balance; + type Index = bp_polkadot::Nonce; + type Signature = bp_polkadot::Signature; } impl Chain for Polkadot { @@ -39,11 +44,8 @@ impl Chain for Polkadot { const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = bp_polkadot::AccountId; - type Index = bp_polkadot::Nonce; type SignedBlock = bp_polkadot::SignedBlock; type Call = (); - type Balance = bp_polkadot::Balance; type WeightToFee = bp_polkadot::WeightToFee; } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 459ea5bc4e94b..ed0cec314a7f7 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -18,7 +18,8 @@ use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -36,6 +37,11 @@ impl ChainBase for Rialto { type Hash = rialto_runtime::Hash; type Hasher = rialto_runtime::Hashing; type Header = rialto_runtime::Header; + + type AccountId = rialto_runtime::AccountId; + type Balance = rialto_runtime::Balance; + type Index = rialto_runtime::Index; + type Signature = rialto_runtime::Signature; } impl Chain for Rialto { @@ -44,11 +50,8 @@ impl Chain for Rialto { const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = rialto_runtime::AccountId; - type Index = rialto_runtime::Index; type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::Call; - type Balance = rialto_runtime::Balance; type WeightToFee = bp_rialto::WeightToFee; } @@ -115,10 +118,10 @@ impl TransactionSignScheme for Rialto { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { call: tx.function, - nonce: Compact::<::Index>::decode(&mut &extra.4.encode()[..]) + nonce: Compact::>::decode(&mut &extra.4.encode()[..]) .ok()? .into(), - tip: Compact::<::Balance>::decode(&mut &extra.6.encode()[..]) + tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? .into(), }) diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5694d183d7825..4d6e3b969c2a1 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -41,6 +41,11 @@ impl ChainBase for Rococo { type Hash = bp_rococo::Hash; type Hasher = bp_rococo::Hashing; type Header = bp_rococo::Header; + + type AccountId = bp_rococo::AccountId; + type Balance = bp_rococo::Balance; + type Index = bp_rococo::Nonce; + type Signature = bp_rococo::Signature; } impl Chain for Rococo { @@ -49,11 +54,8 @@ impl Chain for Rococo { const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = bp_rococo::AccountId; - type Index = bp_rococo::Index; type SignedBlock = bp_rococo::SignedBlock; type Call = crate::runtime::Call; - type Balance = bp_rococo::Balance; type WeightToFee = bp_rococo::WeightToFee; } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 627c01eb0edca..711cfd12f1ba8 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,17 +16,14 @@ use bp_runtime::{Chain as ChainBase, TransactionEraOf}; use codec::{Codec, Encode}; -use frame_support::{weights::WeightToFeePolynomial, Parameter}; +use frame_support::weights::WeightToFeePolynomial; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; -use num_traits::{Bounded, CheckedSub, SaturatingAdd, Zero}; +use num_traits::Zero; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, - traits::{ - AtLeast32Bit, AtLeast32BitUnsigned, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, - MaybeSerializeDeserialize, Member, - }, - EncodedJustification, FixedPointOperand, + traits::{Block as BlockT, Dispatchable, Member}, + EncodedJustification, }; use std::{fmt::Debug, time::Duration}; @@ -44,49 +41,15 @@ pub trait Chain: ChainBase + Clone { /// Maximal size (in bytes) of SCALE-encoded account id on this chain. const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32; - /// The user account identifier type for the runtime. - type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; - /// Index of a transaction used by the chain. - type Index: Parameter - + Member - + MaybeSerialize - + Debug - + Default - + MaybeDisplay - + DeserializeOwned - + AtLeast32Bit - + Copy; /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. type Call: Clone + Dispatchable + Debug; - /// 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 - + DeserializeOwned - + Clone - + Copy - + Bounded - + CheckedSub - + PartialOrd - + SaturatingAdd - + Zero - + std::convert::TryFrom; /// Type that is used by the chain, to convert from weight to fee. type WeightToFee: WeightToFeePolynomial; } -/// Balance type used by the chain -pub type BalanceOf = ::Balance; -/// Index type used by the chain -pub type IndexOf = ::Index; /// Weight-to-Fee type used by the chain pub type WeightToFeeOf = ::WeightToFee; diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index f7df7dbb05c5b..6c5bf16baa63c 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -165,6 +165,7 @@ impl Environment for Client { #[cfg(test)] mod tests { use super::*; + use frame_support::weights::IdentityFee; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, future::FutureExt, @@ -180,6 +181,11 @@ mod tests { type Hash = sp_core::H256; type Hasher = sp_runtime::traits::BlakeTwo256; type Header = sp_runtime::generic::Header; + + type AccountId = u32; + type Balance = u32; + type Index = u32; + type Signature = sp_runtime::testing::TestSignature; } impl Chain for TestChain { @@ -188,13 +194,10 @@ mod tests { const STORAGE_PROOF_OVERHEAD: u32 = 0; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; - type AccountId = u32; - type Index = u32; type SignedBlock = sp_runtime::generic::SignedBlock>; type Call = (); - type Balance = u32; - type WeightToFee = frame_support::weights::IdentityFee; + type WeightToFee = IdentityFee; } impl ChainWithBalances for TestChain { diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index b607b68f8b05a..07cf7d88f8858 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -32,13 +32,14 @@ pub mod metrics; use std::time::Duration; pub use crate::chain::{ - BalanceOf, BlockWithJustification, Chain, ChainWithBalances, IndexOf, TransactionSignScheme, UnsignedTransaction, - WeightToFeeOf, + BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme, UnsignedTransaction, WeightToFeeOf, }; pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; pub use crate::error::{Error, Result}; pub use crate::sync_header::SyncHeader; -pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, TransactionEra, TransactionEraOf}; +pub use bp_runtime::{ + BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, IndexOf, TransactionEra, TransactionEraOf, +}; /// Header id used by the chain. pub type HeaderIdOf = relay_utils::HeaderId, BlockNumberOf>; diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 726a699e3ce03..c719d6ea55364 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -35,6 +35,11 @@ impl ChainBase for Westend { type Hash = bp_westend::Hash; type Hasher = bp_westend::Hasher; type Header = bp_westend::Header; + + type AccountId = bp_westend::AccountId; + type Balance = bp_westend::Balance; + type Index = bp_westend::Nonce; + type Signature = bp_westend::Signature; } impl Chain for Westend { @@ -43,11 +48,8 @@ impl Chain for Westend { const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = bp_westend::AccountId; - type Index = bp_westend::Nonce; type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; - type Balance = bp_westend::Balance; type WeightToFee = bp_westend::WeightToFee; } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index eac2aa841bcce..e6a0c0649b7dd 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -41,6 +41,11 @@ impl ChainBase for Wococo { type Hash = bp_wococo::Hash; type Hasher = bp_wococo::Hashing; type Header = bp_wococo::Header; + + type AccountId = bp_wococo::AccountId; + type Balance = bp_wococo::Balance; + type Index = bp_wococo::Nonce; + type Signature = bp_wococo::Signature; } impl Chain for Wococo { @@ -49,11 +54,8 @@ impl Chain for Wococo { const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; - type AccountId = bp_wococo::AccountId; - type Index = bp_wococo::Index; type SignedBlock = bp_wococo::SignedBlock; type Call = crate::runtime::Call; - type Balance = bp_wococo::Balance; type WeightToFee = bp_wococo::WeightToFee; } diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 73a346f21766e..684aafa023daf 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -19,6 +19,7 @@ use crate::finality_target::SubstrateFinalityTarget; use bp_header_chain::justification::GrandpaJustification; +use bp_runtime::AccountIdOf; use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; use relay_substrate_client::{finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader}; use relay_utils::{metrics::MetricsParams, BlockNumberBase}; @@ -63,13 +64,13 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { fn start_relay_guards(&self) {} /// Returns id of account that we're using to sign transactions at target chain. - fn transactions_author(&self) -> ::AccountId; + fn transactions_author(&self) -> AccountIdOf; /// Make submit header transaction. fn make_submit_finality_proof_transaction( &self, era: bp_runtime::TransactionEraOf, - transaction_nonce: ::Index, + transaction_nonce: bp_runtime::IndexOf, header: ::Header, proof: ::FinalityProof, ) -> Bytes; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 4614a50883a02..f1f67d6c6e305 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -22,6 +22,7 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; +use bp_runtime::{AccountIdOf, IndexOf}; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; use relay_substrate_client::{ @@ -101,24 +102,24 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { type TargetChain: Chain; /// Returns id of account that we're using to sign transactions at target chain (messages proof). - fn target_transactions_author(&self) -> ::AccountId; + fn target_transactions_author(&self) -> AccountIdOf; /// Make messages delivery transaction. fn make_messages_delivery_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: ::MessagesProof, ) -> Bytes; /// Returns id of account that we're using to sign transactions at source chain (delivery proof). - fn source_transactions_author(&self) -> ::AccountId; + fn source_transactions_author(&self) -> AccountIdOf; /// Make messages receiving proof transaction. fn make_messages_receiving_proof_transaction( &self, - transaction_nonce: ::Index, + transaction_nonce: IndexOf, generated_at_header: TargetHeaderIdOf, proof: ::MessagesReceivingProof, ) -> Bytes; diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 20eb7a54b383d..ddf2282792ba0 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -108,7 +108,7 @@ where BlockNumber = ::SourceHeaderNumber, Balance = ::SourceChainBalance, >, - BalanceOf: TryFrom<::Balance> + Bounded, + BalanceOf: TryFrom> + Bounded, P::TargetChain: Chain< Hash = ::TargetHeaderHash, BlockNumber = ::TargetHeaderNumber, @@ -454,7 +454,7 @@ mod tests { fn make_messages_receiving_proof_transaction( &self, - _transaction_nonce: ::Index, + _transaction_nonce: IndexOf, _generated_at_block: TargetHeaderIdOf, _proof: ::MessagesReceivingProof, ) -> Bytes { @@ -467,7 +467,7 @@ mod tests { fn make_messages_delivery_transaction( &self, - _transaction_nonce: ::Index, + _transaction_nonce: IndexOf, _generated_at_header: SourceHeaderIdOf, _nonces: RangeInclusive, _proof: ::MessagesProof, From 21ed61c10eb2c4dd5e8008a1fb08dfd95a0e4fda Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Sep 2021 12:06:41 +0300 Subject: [PATCH 0558/1210] Increase pause before messages generation start (#1126) * increase pause before messages generation start * spelling --- relays/client-ethereum/src/lib.rs | 2 +- relays/client-substrate/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-ethereum/src/lib.rs b/relays/client-ethereum/src/lib.rs index 8b3c6d8f8e733..9443a5d24f416 100644 --- a/relays/client-ethereum/src/lib.rs +++ b/relays/client-ethereum/src/lib.rs @@ -32,7 +32,7 @@ pub mod types; /// Ethereum-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { - /// Websocket server hostname. + /// Websocket server host name. pub host: String, /// Websocket server TCP port. pub port: u16, diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 07cf7d88f8858..8415657060d70 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -47,7 +47,7 @@ pub type HeaderIdOf = relay_utils::HeaderId, BlockNumberOf>; /// Substrate-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { - /// Websocket server hostname. + /// Websocket server host name. pub host: String, /// Websocket server TCP port. pub port: u16, From 80e6013896b6fe02339a7a54b025ae56bdda78f1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Sep 2021 14:57:01 +0300 Subject: [PATCH 0559/1210] set fee for importing mandatory headers to zero (#1127) --- modules/grandpa/src/lib.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 96a58aa8a5b22..49a775077c4c3 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -164,12 +164,20 @@ pub mod pallet { let set_id = authority_set.set_id; verify_justification::(&justification, hash, *number, authority_set)?; - let _enacted = try_enact_authority_change::(&finality_target, set_id)?; + let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; >::mutate(|count| *count += 1); insert_header::(finality_target, hash); log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); - Ok(().into()) + // mandatory header is a header that changes authorities set. The pallet can't go further + // without importing this header. So every bridge MUST import mandatory headers. + // + // We don't want to charge extra costs for mandatory operations. So relayer is not paying + // fee for mandatory headers import transactions. + let is_mandatory_header = is_authorities_change_enacted; + let pays_fee = if is_mandatory_header { Pays::No } else { Pays::Yes }; + + Ok(pays_fee.into()) } /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. @@ -792,7 +800,13 @@ mod tests { fn succesfully_imports_header_with_valid_finality() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1)); + assert_ok!( + submit_finality_proof(1), + PostDispatchInfo { + actual_weight: None, + pays_fee: frame_support::weights::Pays::Yes, + }, + ); let header = test_header(1); assert_eq!(>::get(), header.hash()); @@ -889,11 +903,13 @@ mod tests { let justification = make_default_justification(&header); // Let's import our test header - assert_ok!(Pallet::::submit_finality_proof( - Origin::signed(1), - header.clone(), - justification - )); + assert_ok!( + Pallet::::submit_finality_proof(Origin::signed(1), header.clone(), justification), + PostDispatchInfo { + actual_weight: None, + pays_fee: frame_support::weights::Pays::No, + }, + ); // Make sure that our header is the best finalized assert_eq!(>::get(), header.hash()); From 5c544597d5320fe6633dba4c74bc4034e88cd57a Mon Sep 17 00:00:00 2001 From: Chevdor Date: Fri, 10 Sep 2021 10:17:14 +0200 Subject: [PATCH 0560/1210] chore: spellchecker fixes (#1130) --- primitives/runtime/src/lib.rs | 2 +- relays/lib-substrate-relay/src/finality_pipeline.rs | 2 +- relays/lib-substrate-relay/src/messages_source.rs | 2 +- relays/lib-substrate-relay/src/messages_target.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 659d5c0aacb11..4277af5e46174 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -148,7 +148,7 @@ impl Size for PreComputedSize { pub enum TransactionEra { /// Transaction is immortal. Immortal, - /// Transaction is valid for given number of blocks, starting from given block. + /// Transaction is valid for a given number of blocks, starting from given block. Mortal(BlockNumber, BlockHash, u32), } diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 684aafa023daf..8595ab2842b3d 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -30,7 +30,7 @@ use std::{fmt::Debug, marker::PhantomData, time::Duration}; /// this timeout is used. /// /// There are no any strict requirements on block time in Substrate. But we assume here that all -/// Substrate-based chains will be designed to produce relatively fast (compared to slowest +/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest /// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine /// transaction, or remove it from the pool. pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index d6e92d1e51c4f..4d3332d3271c9 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -299,7 +299,7 @@ fn prepare_dummy_messages_delivery_proof() -> SubstrateMes /// /// This function assumes that the chain that is followed by the `self_client` has /// bridge GRANDPA pallet deployed and it provides `best_finalized_header_id_method_name` -/// runtime API to read best finalized Bridged chain header. +/// runtime API to read the best finalized Bridged chain header. pub async fn read_client_state( self_client: &Client, best_finalized_header_id_method_name: &str, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index ddf2282792ba0..8ad41281bfdcc 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -377,7 +377,7 @@ where .unwrap_or_else(|_| SC::Balance::max_value()) } -/// Compute fee multiplier that is used by the chain, given couple of fees for transactions +/// Compute fee multiplier that is used by the chain, given a couple of fees for transactions /// that are only differ in dispatch weights. /// /// This function assumes that standard transaction payment pallet is used by the chain. From 82724133987578c8f30eb6c57578eafcd643c2cd Mon Sep 17 00:00:00 2001 From: Alexander <41779041+alvicsam@users.noreply.github.com> Date: Fri, 10 Sep 2021 17:58:44 +0200 Subject: [PATCH 0561/1210] Add local CI info to README (#1131) --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index fe568dd220403..41d7fec13d5b9 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,25 @@ cargo build --all cargo test --all ``` +Also you can build the repo with +[Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): + +```bash +docker pull paritytech/bridges-ci:production +mkdir ~/cache +chown 1000:1000 ~/cache #processes in the container runs as "nonroot" user with UID 1000 +docker run --rm -it -w /shellhere/parity-bridges-common \ + -v /home/$(whoami)/cache/:/cache/ \ + -v "$(pwd)":/shellhere/parity-bridges-common \ + -e CARGO_HOME=/cache/cargo/ \ + -e SCCACHE_DIR=/cache/sccache/ \ + -e CARGO_TARGET_DIR=/cache/target/ paritytech/bridges-ci:production cargo build --all +#artifacts can be found in ~/cache/target +``` + +If you want to reproduce other steps of CI process you can use the following +[guide](https://github.com/paritytech/scripts#reproduce-ci-locally). + If you need more information about setting up your development environment Substrate's [Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good resource. From 1617d4e131274f9145df6e235ae40cec5646bacd Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Sep 2021 09:26:36 +0300 Subject: [PATCH 0562/1210] add --mandatory-headers-only cli option to complex relay (#1129) --- relays/bin-substrate/src/cli/relay_headers_and_messages.rs | 5 +++++ relays/lib-substrate-relay/src/on_demand_headers.rs | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 236b2b964b776..956f46f18cb10 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -57,6 +57,9 @@ pub struct HeadersAndMessagesSharedParams { lane: Vec, #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] relayer_mode: RelayerMode, + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed. + #[structopt(long)] + only_mandatory_headers: bool, #[structopt(flatten)] prometheus_params: PrometheusParams, } @@ -278,6 +281,7 @@ impl RelayHeadersAndMessages { right_transactions_mortality, LeftToRightFinality::new(right_client.clone(), right_sign.clone()), MAX_MISSING_LEFT_HEADERS_AT_RIGHT, + params.shared.only_mandatory_headers, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::new( right_client.clone(), @@ -285,6 +289,7 @@ impl RelayHeadersAndMessages { left_transactions_mortality, RightToLeftFinality::new(left_client.clone(), left_sign.clone()), MAX_MISSING_RIGHT_HEADERS_AT_LEFT, + params.shared.only_mandatory_headers, ); // Need 2x capacity since we consider both directions for each lane diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 8973d4fe3ec08..885b3a788d9f4 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -59,6 +59,7 @@ impl OnDemandHeadersRelay { target_transactions_mortality: Option, pipeline: P, maximal_headers_difference: SourceChain::BlockNumber, + only_mandatory_headers: bool, ) -> Self where SourceChain: Chain + Debug, @@ -83,6 +84,7 @@ impl OnDemandHeadersRelay { target_transactions_mortality, pipeline, maximal_headers_difference, + only_mandatory_headers, required_header_number, ) .await; @@ -115,6 +117,7 @@ async fn background_task( target_transactions_mortality: Option, pipeline: P, maximal_headers_difference: SourceChain::BlockNumber, + only_mandatory_headers: bool, required_header_number: RequiredHeaderNumberRef, ) where SourceChain: Chain + Debug, @@ -230,7 +233,7 @@ async fn background_task( tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, - only_mandatory_headers: false, + only_mandatory_headers, }, MetricsParams::disabled(), futures::future::pending(), From c116a34207ce90fae5ccc062ae33a41380d84c89 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Sep 2021 13:35:41 +0300 Subject: [PATCH 0563/1210] fix transaction resubmitter limits for Millau -> Rialto transactions (#1135) --- .../bin-substrate/src/cli/resubmit_transactions.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index ee9801b3fdc6a..4fad160fee08c 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -54,8 +54,16 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type TargetSign = relay_millau_client::Millau; - const TIP_STEP: bp_millau::Balance = 1_000_000; - const TIP_LIMIT: bp_millau::Balance = 1_000_000_000; + // When large message is being sent from Millau to Rialto AND other transactions are blocking + // it from being mined, we'll see something like this in logs: + // + // Millau transaction priority with tip=0: 17800827994. Target priority: 526186677695 + // + // So since fee multiplier in Millau is `1` and `WeightToFee` is `IdentityFee`, then we need + // tip around `526186677695 - 17800827994 = 508_385_849_701`. Let's round it up to `1_000_000_000_000`. + + const TIP_STEP: bp_millau::Balance = 1_000_000_000; + const TIP_LIMIT: bp_millau::Balance = 1_000_000_000_000; const STALLED_BLOCKS: bp_millau::BlockNumber = 5; From e984059bf225ce62856f5d2709dfc3bf0046d669 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Sep 2021 14:00:13 +0300 Subject: [PATCH 0564/1210] Add parachain pallets to rialto runtime (#1053) * use BABE to author blocks on Rialto (previously: Aura) * removed extra script * use bp_rialto::Moment * fix tests * Babe should control session end * add parachain pallets to Rialto runtime * add parachain pallets to rialto runtime + add parachains inherent data provider to node * remove script again * fmt * allow unlicensed crates * spellcheck * fix compilation --- bin/rialto/node/Cargo.toml | 48 +- bin/rialto/node/src/chain_spec.rs | 101 ++- bin/rialto/node/src/cli.rs | 15 + bin/rialto/node/src/command.rs | 75 ++- bin/rialto/node/src/main.rs | 2 + bin/rialto/node/src/overseer.rs | 245 ++++++++ bin/rialto/node/src/parachains_db.rs | 99 +++ bin/rialto/node/src/service.rs | 649 +++++++++++++++----- bin/rialto/runtime/Cargo.toml | 12 + bin/rialto/runtime/src/lib.rs | 126 +++- bin/rialto/runtime/src/parachains.rs | 158 +++++ primitives/chain-rialto/src/lib.rs | 2 +- relays/bin-substrate/src/chains/rialto.rs | 6 +- relays/bin-substrate/src/cli/encode_call.rs | 2 +- relays/client-rialto/src/lib.rs | 4 +- 15 files changed, 1348 insertions(+), 196 deletions(-) create mode 100644 bin/rialto/node/src/overseer.rs create mode 100644 bin/rialto/node/src/parachains_db.rs create mode 100644 bin/rialto/runtime/src/parachains.rs diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 99c9eb80d140a..833cea604dc60 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,9 +10,13 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +futures = "0.3" jsonrpc-core = "15.1.0" +kvdb = "0.10" +kvdb-rocksdb = "0.12" structopt = "0.3.21" serde_json = "1.0.59" +thiserror = "1.0" # Bridge dependencies @@ -23,31 +27,73 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies - frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } + +# Polkadot (parachain) Dependencies + +polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-availability-bitfield-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-approval-voting = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-av-store = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-subsystem-util = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-statement-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 977ee179461e3..b77b1d6acf6be 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -15,11 +15,14 @@ // along with Parity Bridges Common. If not, see . use bp_rialto::derive_account_from_millau_id; +use polkadot_primitives::v1::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig, BridgeRialtoPoaConfig, - GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + GenesisConfig, GrandpaConfig, ParachainsConfigurationConfig, SessionConfig, SessionKeys, Signature, SudoConfig, + SystemConfig, WASM_BINARY, }; use serde_json::json; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; @@ -56,12 +59,24 @@ where AccountPublic::from(get_from_seed::(seed)).into_account() } -/// Helper function to generate an authority key for Babe -pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, BabeId, GrandpaId) { +/// Helper function to generate authority keys. +pub fn get_authority_keys_from_seed( + s: &str, +) -> ( + AccountId, + BabeId, + GrandpaId, + ValidatorId, + AssignmentId, + AuthorityDiscoveryId, +) { ( get_account_id_from_seed::(s), get_from_seed::(s), get_from_seed::(s), + get_from_seed::(s), + get_from_seed::(s), + get_from_seed::(s), ) } @@ -172,12 +187,31 @@ impl Alternative { } } -fn session_keys(babe: BabeId, grandpa: GrandpaId) -> SessionKeys { - SessionKeys { babe, grandpa } +fn session_keys( + babe: BabeId, + grandpa: GrandpaId, + para_validator: ValidatorId, + para_assignment: AssignmentId, + authority_discovery: AuthorityDiscoveryId, +) -> SessionKeys { + SessionKeys { + babe, + grandpa, + para_validator, + para_assignment, + authority_discovery, + } } fn testnet_genesis( - initial_authorities: Vec<(AccountId, BabeId, GrandpaId)>, + initial_authorities: Vec<( + AccountId, + BabeId, + GrandpaId, + ValidatorId, + AssignmentId, + AuthorityDiscoveryId, + )>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, @@ -203,9 +237,62 @@ fn testnet_genesis( session: SessionConfig { keys: initial_authorities .iter() - .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) + .map(|x| { + ( + x.0.clone(), + x.0.clone(), + session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()), + ) + }) .collect::>(), }, + authority_discovery: Default::default(), + hrmp: Default::default(), + // this configuration is exact copy of configuration from Polkadot repo + // (see /node/service/src/chain_spec.rs:default_parachains_host_configuration) + parachains_configuration: ParachainsConfigurationConfig { + config: polkadot_runtime_parachains::configuration::HostConfiguration { + validation_upgrade_frequency: 1u32, + validation_upgrade_delay: 1, + code_retention_period: 1200, + max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE, + max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE, + max_head_data_size: 32 * 1024, + group_rotation_frequency: 20, + chain_availability_period: 4, + thread_availability_period: 4, + max_upward_queue_count: 8, + max_upward_queue_size: 1024 * 1024, + max_downward_message_size: 1024, + // this is approximatelly 4ms. + // + // Same as `4 * frame_support::weights::WEIGHT_PER_MILLIS`. We don't bother with + // an import since that's a made up number and should be replaced with a constant + // obtained by benchmarking anyway. + ump_service_total_weight: 4 * 1_000_000_000, + max_upward_message_size: 1024 * 1024, + max_upward_message_num_per_candidate: 5, + hrmp_open_request_ttl: 5, + hrmp_sender_deposit: 0, + hrmp_recipient_deposit: 0, + hrmp_channel_max_capacity: 8, + hrmp_channel_max_total_size: 8 * 1024, + hrmp_max_parachain_inbound_channels: 4, + hrmp_max_parathread_inbound_channels: 4, + hrmp_channel_max_message_size: 1024 * 1024, + hrmp_max_parachain_outbound_channels: 4, + hrmp_max_parathread_outbound_channels: 4, + hrmp_max_message_num_per_candidate: 5, + dispute_period: 6, + no_show_slots: 2, + n_delay_tranches: 25, + needed_approvals: 2, + relay_vrf_modulo_samples: 2, + zeroth_delay_tranche_width: 0, + ..Default::default() + }, + }, + paras: Default::default(), bridge_millau_messages: BridgeMillauMessagesConfig { owner: Some(get_account_id_from_seed::("MillauMessagesOwner")), ..Default::default() diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 086def633c598..3f85a69a713fe 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -67,4 +67,19 @@ pub enum Subcommand { /// Benchmark runtime pallets. Benchmark(frame_benchmarking_cli::BenchmarkCmd), + + /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. + #[structopt(name = "prepare-worker", setting = structopt::clap::AppSettings::Hidden)] + PvfPrepareWorker(ValidationWorkerCommand), + + /// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary. + #[structopt(name = "execute-worker", setting = structopt::clap::AppSettings::Hidden)] + PvfExecuteWorker(ValidationWorkerCommand), +} + +/// Validation worker command. +#[derive(Debug, StructOpt)] +pub struct ValidationWorkerCommand { + /// The path to the validation host's socket. + pub socket_path: String, } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 226a21d841dfb..4fe40251e63b2 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -15,7 +15,6 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{Cli, Subcommand}; -use crate::service; use crate::service::new_partial; use rialto_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; @@ -78,7 +77,7 @@ pub fn run() -> sc_cli::Result<()> { if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -97,43 +96,43 @@ pub fn run() -> sc_cli::Result<()> { } Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { + runner.async_run(|mut config| { let PartialComponents { client, task_manager, import_queue, .. - } = new_partial(&config)?; + } = new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) } Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { + runner.async_run(|mut config| { let PartialComponents { client, task_manager, .. - } = new_partial(&config)?; + } = new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, config.database), task_manager)) }) } Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { + runner.async_run(|mut config| { let PartialComponents { client, task_manager, .. - } = new_partial(&config)?; + } = new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) } Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { + runner.async_run(|mut config| { let PartialComponents { client, task_manager, import_queue, .. - } = new_partial(&config)?; + } = new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) } @@ -143,32 +142,62 @@ pub fn run() -> sc_cli::Result<()> { } Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { + runner.async_run(|mut config| { let PartialComponents { client, task_manager, backend, .. - } = new_partial(&config)?; + } = new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, backend), task_manager)) }) } Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) + } + Some(Subcommand::PvfPrepareWorker(cmd)) => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_colors(false); + let _ = builder.init(); + + polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path); + Ok(()) + } + Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_colors(false); + let _ = builder.init(); + + polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path); + Ok(()) } None => { let runner = cli.create_runner(&cli.run)?; - runner - .run_node_until_exit(|config| async move { - match config.role { - Role::Light => Err(sc_service::Error::Other( - "Light client is not supported by this node".into(), - )), - _ => service::new_full(config), - } - }) - .map_err(sc_cli::Error::Service) + + // some parameters that are used by polkadot nodes, but that are not used by our binary + // let jaeger_agent = None; + // let grandpa_pause = None; + // let no_beefy = true; + // let telemetry_worker_handler = None; + // let is_collator = crate::service::IsCollator::No; + let overseer_gen = crate::overseer::RealOverseerGen; + runner.run_node_until_exit(|config| async move { + match config.role { + Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other( + "Light client is not supported by this node".into(), + ))), + _ => crate::service::build_full(config, overseer_gen) + .map(|full| full.task_manager) + .map_err(service_error), + } + }) } } } + +// We don't want to change 'service.rs' too much to ease future updates => it'll keep using +// its own error enum like original polkadot service does. +fn service_error(err: crate::service::Error) -> sc_cli::Error { + sc_cli::Error::Application(Box::new(err)) +} diff --git a/bin/rialto/node/src/main.rs b/bin/rialto/node/src/main.rs index f319d1437a98f..824814224e548 100644 --- a/bin/rialto/node/src/main.rs +++ b/bin/rialto/node/src/main.rs @@ -23,6 +23,8 @@ mod chain_spec; mod service; mod cli; mod command; +mod overseer; +mod parachains_db; /// Run the Rialto Node fn main() -> sc_cli::Result<()> { diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs new file mode 100644 index 0000000000000..f7aaef4b5d492 --- /dev/null +++ b/bin/rialto/node/src/overseer.rs @@ -0,0 +1,245 @@ +// 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 . + +//! This is almost 1:1 copy of `node/service/src/overseer.rs` file from Polkadot repository. +//! The only exception is that we don't support db upgrades => no `upgrade.rs` module. + +// this warning comes from `polkadot_overseer::AllSubsystems` type +#![allow(clippy::type_complexity)] + +use crate::service::Error; + +use polkadot_network_bridge::RequestMultiplexer; +use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; +use polkadot_node_core_av_store::Config as AvailabilityConfig; +use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; +use polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandler}; +use polkadot_primitives::v1::{Block, Hash, ParachainHost}; +use sc_authority_discovery::Service as AuthorityDiscoveryService; +use sc_client_api::AuxStore; +use sc_keystore::LocalKeystore; +use sp_api::ProvideRuntimeApi; +use sp_authority_discovery::AuthorityDiscoveryApi; +use sp_blockchain::HeaderBackend; +use sp_consensus_babe::BabeApi; +use sp_core::traits::SpawnNamed; +use std::sync::Arc; +use substrate_prometheus_endpoint::Registry; + +pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem; +pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem; +pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem; +pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem; +pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide}; +pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem; +pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem; +pub use polkadot_node_collation_generation::CollationGenerationSubsystem; +pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem; +pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem; +pub use polkadot_node_core_backing::CandidateBackingSubsystem; +pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem; +pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem; +pub use polkadot_node_core_chain_api::ChainApiSubsystem; +pub use polkadot_node_core_provisioner::ProvisioningSubsystem as ProvisionerSubsystem; +pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem; +pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem; + +/// Arguments passed for overseer construction. +pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> +where + RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, + RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + Spawner: 'static + SpawnNamed + Clone + Unpin, +{ + /// Set of initial relay chain leaves to track. + pub leaves: Vec, + /// The keystore to use for i.e. validator keys. + pub keystore: Arc, + /// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others. + pub runtime_client: Arc, + /// The underlying key value store for the parachains. + pub parachains_db: Arc, + /// Configuration for the availability store subsystem. + pub availability_config: AvailabilityConfig, + /// Configuration for the approval voting subsystem. + pub approval_voting_config: ApprovalVotingConfig, + /// Underlying network service implementation. + pub network_service: Arc>, + /// Underlying authority discovery service. + pub authority_discovery_service: AuthorityDiscoveryService, + /// A multiplexer to arbitrate incoming `IncomingRequest`s from the network. + pub request_multiplexer: RequestMultiplexer, + /// Prometheus registry, commonly used for production systems, less so for test. + pub registry: Option<&'a Registry>, + /// Task spawner to be used throughout the overseer and the APIs it provides. + pub spawner: Spawner, + /// Configuration for the candidate validation subsystem. + pub candidate_validation_config: CandidateValidationConfig, +} + +/// Create a default, unaltered set of subsystems. +/// +/// A convenience for usage with malus, to avoid +/// repetitive code across multiple behavior strain implementations. +pub fn create_default_subsystems( + OverseerGenArgs { + keystore, + runtime_client, + parachains_db, + availability_config, + approval_voting_config, + network_service, + authority_discovery_service, + request_multiplexer, + registry, + spawner, + candidate_validation_config, + .. + }: OverseerGenArgs, +) -> Result< + AllSubsystems< + CandidateValidationSubsystem, + CandidateBackingSubsystem, + StatementDistributionSubsystem, + AvailabilityDistributionSubsystem, + AvailabilityRecoverySubsystem, + BitfieldSigningSubsystem, + BitfieldDistributionSubsystem, + ProvisionerSubsystem, + RuntimeApiSubsystem, + AvailabilityStoreSubsystem, + NetworkBridgeSubsystem>, AuthorityDiscoveryService>, + ChainApiSubsystem, + CollationGenerationSubsystem, + CollatorProtocolSubsystem, + ApprovalDistributionSubsystem, + ApprovalVotingSubsystem, + GossipSupportSubsystem, + >, + Error, +> +where + RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, + RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + Spawner: 'static + SpawnNamed + Clone + Unpin, +{ + use polkadot_node_subsystem_util::metrics::Metrics; + + let all_subsystems = AllSubsystems { + availability_distribution: AvailabilityDistributionSubsystem::new( + keystore.clone(), + Metrics::register(registry)?, + ), + availability_recovery: AvailabilityRecoverySubsystem::with_chunks_only(), + availability_store: AvailabilityStoreSubsystem::new( + parachains_db.clone(), + availability_config, + Metrics::register(registry)?, + ), + bitfield_distribution: BitfieldDistributionSubsystem::new(Metrics::register(registry)?), + bitfield_signing: BitfieldSigningSubsystem::new( + spawner.clone(), + keystore.clone(), + Metrics::register(registry)?, + ), + candidate_backing: CandidateBackingSubsystem::new( + spawner.clone(), + keystore.clone(), + Metrics::register(registry)?, + ), + candidate_validation: CandidateValidationSubsystem::with_config( + candidate_validation_config, + Metrics::register(registry)?, + ), + chain_api: ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?), + collation_generation: CollationGenerationSubsystem::new(Metrics::register(registry)?), + collator_protocol: { + let side = ProtocolSide::Validator { + keystore: keystore.clone(), + eviction_policy: Default::default(), + metrics: Metrics::register(registry)?, + }; + CollatorProtocolSubsystem::new(side) + }, + network_bridge: NetworkBridgeSubsystem::new( + network_service.clone(), + authority_discovery_service, + request_multiplexer, + Box::new(network_service.clone()), + Metrics::register(registry)?, + ), + provisioner: ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?), + runtime_api: RuntimeApiSubsystem::new(runtime_client, Metrics::register(registry)?, spawner), + statement_distribution: StatementDistributionSubsystem::new(keystore.clone(), Metrics::register(registry)?), + approval_distribution: ApprovalDistributionSubsystem::new(Metrics::register(registry)?), + approval_voting: ApprovalVotingSubsystem::with_config( + approval_voting_config, + parachains_db, + keystore.clone(), + Box::new(network_service), + Metrics::register(registry)?, + ), + gossip_support: GossipSupportSubsystem::new(keystore), + }; + Ok(all_subsystems) +} + +/// Trait for the `fn` generating the overseer. +/// +/// Default behavior is to create an unmodified overseer, as `RealOverseerGen` +/// would do. +pub trait OverseerGen { + /// Overwrite the full generation of the overseer, including the subsystems. + fn generate( + &self, + args: OverseerGenArgs, + ) -> Result<(Overseer>, OverseerHandler), Error> + where + RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, + RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + Spawner: 'static + SpawnNamed + Clone + Unpin, + { + let gen = RealOverseerGen; + RealOverseerGen::generate::(&gen, args) + } + // It would be nice to make `create_subsystems` part of this trait, + // but the amount of generic arguments that would be required as + // as consequence make this rather annoying to implement and use. +} + +/// The regular set of subsystems. +pub struct RealOverseerGen; + +impl OverseerGen for RealOverseerGen { + fn generate( + &self, + args: OverseerGenArgs, + ) -> Result<(Overseer>, OverseerHandler), Error> + where + RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, + RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, + Spawner: 'static + SpawnNamed + Clone + Unpin, + { + let spawner = args.spawner.clone(); + let leaves = args.leaves.clone(); + let runtime_client = args.runtime_client.clone(); + let registry = args.registry; + + let all_subsystems = create_default_subsystems::(args)?; + + Overseer::new(leaves, all_subsystems, registry, runtime_client, spawner).map_err(|e| e.into()) + } +} diff --git a/bin/rialto/node/src/parachains_db.rs b/bin/rialto/node/src/parachains_db.rs new file mode 100644 index 0000000000000..aa70d45cd73b8 --- /dev/null +++ b/bin/rialto/node/src/parachains_db.rs @@ -0,0 +1,99 @@ +// 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 . + +//! This is almost 1:1 copy of `node/service/parachains_db/mod.rs` file from Polkadot repository. +//! The only exception is that we don't support db upgrades => no `upgrade.rs` module. + +use {kvdb::KeyValueDB, std::io, std::path::PathBuf, std::sync::Arc}; + +mod columns { + pub const NUM_COLUMNS: u32 = 3; + + pub const COL_AVAILABILITY_DATA: u32 = 0; + pub const COL_AVAILABILITY_META: u32 = 1; + pub const COL_APPROVAL_DATA: u32 = 2; +} + +/// Columns used by different subsystems. +#[derive(Debug, Clone)] +pub struct ColumnsConfig { + /// The column used by the av-store for data. + pub col_availability_data: u32, + /// The column used by the av-store for meta information. + pub col_availability_meta: u32, + /// The column used by approval voting for data. + pub col_approval_data: u32, +} + +/// The real columns used by the parachains DB. +pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig { + col_availability_data: columns::COL_AVAILABILITY_DATA, + col_availability_meta: columns::COL_AVAILABILITY_META, + col_approval_data: columns::COL_APPROVAL_DATA, +}; + +/// The cache size for each column, in megabytes. +#[derive(Debug, Clone)] +pub struct CacheSizes { + /// Cache used by availability data. + pub availability_data: usize, + /// Cache used by availability meta. + pub availability_meta: usize, + /// Cache used by approval data. + pub approval_data: usize, +} + +impl Default for CacheSizes { + fn default() -> Self { + CacheSizes { + availability_data: 25, + availability_meta: 1, + approval_data: 5, + } + } +} + +fn other_io_error(err: String) -> io::Error { + io::Error::new(io::ErrorKind::Other, err) +} + +/// Open the database on disk, creating it if it doesn't exist. +pub fn open_creating(root: PathBuf, cache_sizes: CacheSizes) -> io::Result> { + use kvdb_rocksdb::{Database, DatabaseConfig}; + + let path = root.join("parachains").join("db"); + + let mut db_config = DatabaseConfig::with_columns(columns::NUM_COLUMNS); + + let _ = db_config + .memory_budget + .insert(columns::COL_AVAILABILITY_DATA, cache_sizes.availability_data); + let _ = db_config + .memory_budget + .insert(columns::COL_AVAILABILITY_META, cache_sizes.availability_meta); + let _ = db_config + .memory_budget + .insert(columns::COL_APPROVAL_DATA, cache_sizes.approval_data); + + let path_str = path + .to_str() + .ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?; + + std::fs::create_dir_all(&path_str)?; + let db = Database::open(&db_config, path_str)?; + + Ok(Arc::new(db)) +} diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 77d63a68dd99e..71ab93d85893c 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -14,30 +14,36 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. - -// ===================================================================================== -// ===================================================================================== -// ===================================================================================== -// There's no easy way to update this file. Currently it is a merge of two files: -// 1) node-template/src/service.rs from Substrate repo; -// 2) node/service/src/lib.rs from Polkadot repo. -// -// The main things to notice when updating are: -// 1) we are using Babe for authoring blocks; -// 2) support for light client is dropped as we are not using it now. -// ===========================================s========================================== -// ===================================================================================== -// ===================================================================================== - +//! Rialto chain node service. +//! +//! The code is mostly copy of `service/src/lib.rs` file from Polkadot repository +//! without optional functions. + +// this warning comes from Error enum (sc_cli::Error in particular) && it isn't easy to use box there +#![allow(clippy::large_enum_variant)] +// this warning comes from `sc_service::PartialComponents` type +#![allow(clippy::type_complexity)] + +use crate::overseer::{OverseerGen, OverseerGenArgs}; + +use polkadot_network_bridge::RequestMultiplexer; +use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; +use polkadot_node_core_av_store::Config as AvailabilityConfig; +use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; +use polkadot_overseer::{BlockInfo, OverseerHandler}; +use polkadot_primitives::v1::BlockId; use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::ExecutorProvider; -use sc_consensus_babe::SlotProportion; -use sc_executor::native_executor_instance; -use sc_keystore::LocalKeystore; -use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; +use sc_executor::{native_executor_instance, NativeExecutionDispatch}; +use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; +use sc_service::{config::PrometheusConfig, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; +use sp_api::{ConstructRuntimeApi, HeaderT}; +use sp_blockchain::HeaderBackend; +use sp_consensus::SelectChain; +use sp_runtime::traits::{BlakeTwo256, Block as BlockT}; use std::{sync::Arc, time::Duration}; +use substrate_prometheus_endpoint::Registry; pub use sc_executor::NativeExecutor; @@ -49,34 +55,126 @@ native_executor_instance!( frame_benchmarking::benchmarking::HostFunctions, ); +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Io(#[from] std::io::Error), + + #[error(transparent)] + Cli(#[from] sc_cli::Error), + + #[error(transparent)] + Blockchain(#[from] sp_blockchain::Error), + + #[error(transparent)] + Consensus(#[from] sp_consensus::Error), + + #[error(transparent)] + Service(#[from] sc_service::Error), + + #[error(transparent)] + Telemetry(#[from] sc_telemetry::Error), + + #[error("Failed to create an overseer")] + Overseer(#[from] polkadot_overseer::SubsystemError), + + #[error(transparent)] + Prometheus(#[from] substrate_prometheus_endpoint::PrometheusError), + + #[error("Authorities require the real overseer implementation")] + AuthoritiesRequireRealOverseer, + + #[error("Creating a custom database is required for validators")] + DatabasePathRequired, +} + type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; type FullGrandpaBlockImport = sc_finality_grandpa::GrandpaBlockImport; +type FullTransactionPool = sc_transaction_pool::FullPool; +type FullBabeBlockImport = sc_consensus_babe::BabeBlockImport; +type FullBabeLink = sc_consensus_babe::BabeLink; +type FullGrandpaLink = sc_finality_grandpa::LinkHalf; + +/// A set of APIs that polkadot-like runtimes must implement. +/// +/// This is the copy of `polkadot_service::RuntimeApiCollection` with some APIs removed +/// (right now - MMR and BEEFY). +pub trait RequiredApiCollection: + sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::ApiExt + + sp_consensus_babe::BabeApi + + sp_finality_grandpa::GrandpaApi + + polkadot_primitives::v1::ParachainHost + + sp_block_builder::BlockBuilder + + frame_system_rpc_runtime_api::AccountNonceApi + + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + sp_api::Metadata + + sp_offchain::OffchainWorkerApi + + sp_session::SessionKeys + + sp_authority_discovery::AuthorityDiscoveryApi +where + >::StateBackend: sp_api::StateBackend, +{ +} + +impl RequiredApiCollection for Api +where + Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::ApiExt + + sp_consensus_babe::BabeApi + + sp_finality_grandpa::GrandpaApi + + polkadot_primitives::v1::ParachainHost + + sp_block_builder::BlockBuilder + + frame_system_rpc_runtime_api::AccountNonceApi + + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + sp_api::Metadata + + sp_offchain::OffchainWorkerApi + + sp_session::SessionKeys + + sp_authority_discovery::AuthorityDiscoveryApi, + >::StateBackend: sp_api::StateBackend, +{ +} + +// If we're using prometheus, use a registry with a prefix of `polkadot`. +fn set_prometheus_registry(config: &mut Configuration) -> Result<(), Error> { + if let Some(PrometheusConfig { registry, .. }) = config.prometheus_config.as_mut() { + *registry = Registry::new_custom(Some("polkadot".into()), None)?; + } + + Ok(()) +} -#[allow(clippy::type_complexity)] pub fn new_partial( - config: &Configuration, + config: &mut Configuration, ) -> Result< sc_service::PartialComponents< FullClient, FullBackend, FullSelectChain, sp_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, + FullTransactionPool, ( - FullGrandpaBlockImport, - sc_finality_grandpa::LinkHalf, - sc_consensus_babe::BabeBlockImport, - sc_consensus_babe::BabeLink, + impl Fn( + sc_rpc::DenyUnsafe, + sc_rpc::SubscriptionTaskExecutor, + ) -> jsonrpc_core::IoHandler, + (FullBabeBlockImport, FullGrandpaLink, FullBabeLink), + sc_finality_grandpa::SharedVoterState, + std::time::Duration, Option, ), >, - ServiceError, -> { - if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); - } + Error, +> +where + RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, + >::RuntimeApi: + RequiredApiCollection>, + Executor: NativeExecutionDispatch + 'static, +{ + set_prometheus_registry(config)?; let telemetry = config .telemetry_endpoints @@ -110,24 +208,23 @@ pub fn new_partial( client.clone(), ); - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import_with_authority_set_hard_forks( client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), + Vec::new(), telemetry.as_ref().map(|x| x.handle()), )?; let justification_import = grandpa_block_import.clone(); - let (babe_block_import, babe_link) = sc_consensus_babe::block_import( - sc_consensus_babe::Config::get_or_compute(&*client)?, - grandpa_block_import.clone(), - client.clone(), - )?; + let babe_config = sc_consensus_babe::Config::get_or_compute(&*client)?; + let (block_import, babe_link) = + sc_consensus_babe::block_import(babe_config.clone(), grandpa_block_import, client.clone())?; let slot_duration = babe_link.config().slot_duration(); let import_queue = sc_consensus_babe::import_queue( babe_link.clone(), - babe_block_import.clone(), + block_import.clone(), Some(Box::new(justification_import)), client.clone(), select_chain.clone(), @@ -147,61 +244,203 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; + let justification_stream = grandpa_link.justification_stream(); + let shared_authority_set = grandpa_link.shared_authority_set().clone(); + let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); + + let import_setup = (block_import, grandpa_link, babe_link); + let rpc_setup = shared_voter_state.clone(); + + let slot_duration = babe_config.slot_duration(); + + let rpc_extensions_builder = { + let client = client.clone(); + let transaction_pool = transaction_pool.clone(); + let backend = backend.clone(); + + move |deny_unsafe, + subscription_executor: sc_rpc::SubscriptionTaskExecutor| + -> jsonrpc_core::IoHandler { + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; + use substrate_frame_rpc_system::{FullSystem, SystemApi}; + + let backend = backend.clone(); + let client = client.clone(); + let pool = transaction_pool.clone(); + + let shared_voter_state = shared_voter_state.clone(); + + let finality_proof_provider = + GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); + + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with(SystemApi::to_delegate(FullSystem::new( + client.clone(), + pool, + deny_unsafe, + ))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client))); + io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( + shared_authority_set.clone(), + shared_voter_state, + justification_stream.clone(), + subscription_executor, + finality_proof_provider, + ))); + + io + } + }; + Ok(sc_service::PartialComponents { client, backend, task_manager, - import_queue, keystore_container, select_chain, + import_queue, transaction_pool, other: ( - grandpa_block_import, - grandpa_link, - babe_block_import, - babe_link, + rpc_extensions_builder, + import_setup, + rpc_setup, + slot_duration, telemetry, ), }) } -fn remote_keystore(_url: &str) -> Result, &'static str> { - // FIXME: here would the concrete keystore be built, - // must return a concrete type (NOT `LocalKeystore`) that - // implements `CryptoStore` and `SyncCryptoStore` - Err("Remote Keystore not supported.") +pub struct NewFull { + pub task_manager: TaskManager, + pub client: C, + pub overseer_handler: Option, + pub network: Arc::Hash>>, + pub rpc_handlers: sc_service::RpcHandlers, + pub backend: Arc, } -/// Builds a new service for a full client. -pub fn new_full(mut config: Configuration) -> Result { +/// The maximum number of active leaves we forward to the [`Overseer`] on startup. +const MAX_ACTIVE_LEAVES: usize = 4; + +/// Returns the active leaves the overseer should start with. +async fn active_leaves( + select_chain: &sc_consensus::LongestChain, + client: &FullClient, +) -> Result, Error> +where + RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, + >::RuntimeApi: + RequiredApiCollection>, + Executor: NativeExecutionDispatch + 'static, +{ + let best_block = select_chain.best_chain().await?; + + let mut leaves = select_chain + .leaves() + .await + .unwrap_or_default() + .into_iter() + .filter_map(|hash| { + let number = client.number(hash).ok()??; + + // Only consider leaves that are in maximum an uncle of the best block. + if number < best_block.number().saturating_sub(1) || hash == best_block.hash() { + return None; + } + + let parent_hash = client.header(&BlockId::Hash(hash)).ok()??.parent_hash; + + Some(BlockInfo { + hash, + parent_hash, + number, + }) + }) + .collect::>(); + + // Sort by block number and get the maximum number of leaves + leaves.sort_by_key(|b| b.number); + + leaves.push(BlockInfo { + hash: best_block.hash(), + parent_hash: *best_block.parent_hash(), + number: *best_block.number(), + }); + + Ok(leaves.into_iter().rev().take(MAX_ACTIVE_LEAVES).collect()) +} + +// Create a new full node. +pub fn new_full( + mut config: Configuration, + program_path: Option, + overseer_gen: impl OverseerGen, +) -> Result>, Error> +where + RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, + >::RuntimeApi: + RequiredApiCollection>, + Executor: NativeExecutionDispatch + 'static, +{ + let is_collator = false; + + let role = config.role.clone(); + let force_authoring = config.force_authoring; + let backoff_authoring_blocks = Some(sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default()); + + let disable_grandpa = config.disable_grandpa; + let name = config.network.node_name.clone(); + let sc_service::PartialComponents { client, backend, mut task_manager, - import_queue, - mut keystore_container, + keystore_container, select_chain, + import_queue, transaction_pool, - other: (_grandpa_block_import, grandpa_link, babe_block_import, babe_link, mut telemetry), - } = new_partial(&config)?; - - if let Some(url) = &config.keystore_remote { - match remote_keystore(url) { - Ok(k) => keystore_container.set_remote_keystore(k), - Err(e) => { - return Err(ServiceError::Other(format!( - "Error hooking up remote keystore for {}: {}", - url, e - ))) - } - }; - } + other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry), + } = new_partial(&mut config)?; + + let prometheus_registry = config.prometheus_registry().cloned(); + let shared_voter_state = rpc_setup; + let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; + + // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change + // anything in terms of behaviour, but makes the logs more consistent with the other + // Substrate nodes. config .network .extra_sets .push(sc_finality_grandpa::grandpa_peers_set_config()); + { + use polkadot_network_bridge::{peer_sets_info, IsAuthority}; + let is_authority = if role.is_authority() { + IsAuthority::Yes + } else { + IsAuthority::No + }; + config.network.extra_sets.extend(peer_sets_info(is_authority)); + } + + config + .network + .request_response_protocols + .push(sc_finality_grandpa_warp_sync::request_response_config_for_chain( + &config, + task_manager.spawn_handle(), + backend.clone(), + import_setup.1.shared_authority_set().clone(), + )); + let request_multiplexer = { + let (multiplexer, configs) = RequestMultiplexer::new(); + config.network.request_response_protocols.extend(configs); + multiplexer + }; + let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -213,75 +452,146 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); + let _ = + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } - let role = config.role.clone(); - let force_authoring = config.force_authoring; - let backoff_authoring_blocks: Option<()> = None; - let name = config.network.node_name.clone(); - let enable_grandpa = !config.disable_grandpa; - let prometheus_registry = config.prometheus_registry().cloned(); - - let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); - - let rpc_extensions_builder = { - use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; - - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; - use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; - use sc_rpc::DenyUnsafe; - use substrate_frame_rpc_system::{FullSystem, SystemApi}; - - let backend = backend.clone(); - let client = client.clone(); - let pool = transaction_pool.clone(); - - let justification_stream = grandpa_link.justification_stream(); - let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = shared_voter_state.clone(); + let parachains_db = crate::parachains_db::open_creating( + config.database.path().ok_or(Error::DatabasePathRequired)?.into(), + crate::parachains_db::CacheSizes::default(), + )?; - let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); + let availability_config = AvailabilityConfig { + col_data: crate::parachains_db::REAL_COLUMNS.col_availability_data, + col_meta: crate::parachains_db::REAL_COLUMNS.col_availability_meta, + }; - Box::new(move |_, subscription_executor| { - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(SystemApi::to_delegate(FullSystem::new( - client.clone(), - pool.clone(), - DenyUnsafe::No, - ))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( - client.clone(), - ))); - io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( - shared_authority_set.clone(), - shared_voter_state.clone(), - justification_stream.clone(), - subscription_executor, - finality_proof_provider.clone(), - ))); + let approval_voting_config = ApprovalVotingConfig { + col_data: crate::parachains_db::REAL_COLUMNS.col_approval_data, + slot_duration_millis: slot_duration.as_millis() as u64, + }; - io - }) + let candidate_validation_config = CandidateValidationConfig { + artifacts_cache_path: config + .database + .path() + .ok_or(Error::DatabasePathRequired)? + .join("pvf-artifacts"), + program_path: match program_path { + None => std::env::current_exe()?, + Some(p) => p, + }, }; - let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - network: network.clone(), + let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + config, + backend: backend.clone(), client: client.clone(), keystore: keystore_container.sync_keystore(), - task_manager: &mut task_manager, + network: network.clone(), + rpc_extensions_builder: Box::new(rpc_extensions_builder), transaction_pool: transaction_pool.clone(), - rpc_extensions_builder, + task_manager: &mut task_manager, on_demand: None, remote_blockchain: None, - backend, system_rpc_tx, - config, telemetry: telemetry.as_mut(), })?; + let (block_import, link_half, babe_link) = import_setup; + + let overseer_client = client.clone(); + let spawner = task_manager.spawn_handle(); + let active_leaves = futures::executor::block_on(active_leaves(&select_chain, &*client))?; + + let authority_discovery_service = if role.is_authority() || is_collator { + use futures::StreamExt; + use sc_network::Event; + + let authority_discovery_role = if role.is_authority() { + sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore()) + } else { + // don't publish our addresses when we're only a collator + sc_authority_discovery::Role::Discover + }; + let dht_event_stream = network.event_stream("authority-discovery").filter_map(|e| async move { + match e { + Event::Dht(e) => Some(e), + _ => None, + } + }); + let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config( + sc_authority_discovery::WorkerConfig { + publish_non_global_ips: auth_disc_publish_non_global_ips, + ..Default::default() + }, + client.clone(), + network.clone(), + Box::pin(dht_event_stream), + authority_discovery_role, + prometheus_registry.clone(), + ); + + task_manager + .spawn_handle() + .spawn("authority-discovery-worker", worker.run()); + Some(service) + } else { + None + }; + + // we'd say let overseer_handler = authority_discovery_service.map(|authority_discovery_service|, ...), + // but in that case we couldn't use ? to propagate errors + let local_keystore = keystore_container.local_keystore(); + let maybe_params = local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k))); + + let overseer_handler = if let Some((authority_discovery_service, keystore)) = maybe_params { + let (overseer, overseer_handler) = + overseer_gen.generate::(OverseerGenArgs { + leaves: active_leaves, + keystore, + runtime_client: overseer_client.clone(), + parachains_db, + availability_config, + approval_voting_config, + network_service: network.clone(), + authority_discovery_service, + request_multiplexer, + registry: prometheus_registry.as_ref(), + spawner, + candidate_validation_config, + })?; + let overseer_handler_clone = overseer_handler.clone(); + + task_manager.spawn_essential_handle().spawn_blocking( + "overseer", + Box::pin(async move { + use futures::{pin_mut, select, FutureExt}; + + let forward = polkadot_overseer::forward_events(overseer_client, overseer_handler_clone); + + let forward = forward.fuse(); + let overseer_fut = overseer.run().fuse(); + + pin_mut!(overseer_fut); + pin_mut!(forward); + + select! { + _ = forward => (), + _ = overseer_fut => (), + complete => (), + } + }), + ); + + Some(overseer_handler) + } else { + None + }; + if role.is_authority() { + let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + let proposer = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), @@ -290,85 +600,118 @@ pub fn new_full(mut config: Configuration) -> Result telemetry.as_ref().map(|x| x.handle()), ); - let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - + let client_clone = client.clone(); + let overseer_handler = overseer_handler + .as_ref() + .ok_or(Error::AuthoritiesRequireRealOverseer)? + .clone(); let slot_duration = babe_link.config().slot_duration(); let babe_config = sc_consensus_babe::BabeParams { keystore: keystore_container.sync_keystore(), - client, + client: client.clone(), select_chain, + block_import, env: proposer, - block_import: babe_block_import, sync_oracle: network.clone(), justification_sync_link: network.clone(), - create_inherent_data_providers: move |_parent, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) + create_inherent_data_providers: move |parent, ()| { + let client_clone = client_clone.clone(); + let overseer_handler = overseer_handler.clone(); + async move { + let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create( + &*client_clone, + overseer_handler, + parent, + ) + .await + .map_err(Box::new)?; + + let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider(&*client_clone, parent)?; + + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot, uncles, parachain)) + } }, force_authoring, backoff_authoring_blocks, babe_link, can_author_with, - block_proposal_slot_portion: SlotProportion::new(0.5), + block_proposal_slot_portion: sc_consensus_babe::SlotProportion::new(2f32 / 3f32), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), }; let babe = sc_consensus_babe::start_babe(babe_config)?; - task_manager - .spawn_essential_handle() - .spawn_blocking("babe-proposer", babe); + task_manager.spawn_essential_handle().spawn_blocking("babe", babe); } // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = if role.is_authority() { + let keystore_opt = if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; - let grandpa_config = sc_finality_grandpa::Config { - // FIXME #1578 make this available through chainspec - gossip_duration: Duration::from_millis(333), + let config = sc_finality_grandpa::Config { + // FIXME substrate#1578 make this available through chainspec + gossip_duration: Duration::from_millis(1000), justification_period: 512, name: Some(name), observer_enabled: false, - keystore, + keystore: keystore_opt, local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), }; + let enable_grandpa = !disable_grandpa; if enable_grandpa { // start the full GRANDPA voter - // NOTE: non-authorities could run the GRANDPA observer protocol, but at - // this point the full voter should provide better guarantees of block - // and vote data availability than the observer. The observer has not - // been tested extensively yet and having most nodes in a network run it - // could lead to finality stalls. + // NOTE: unlike in substrate we are currently running the full + // GRANDPA voter protocol for all full nodes (regardless of whether + // they're validators or not). at this point the full voter should + // provide better guarantees of block and vote data availability than + // the observer. + + // add a custom voting rule to temporarily stop voting for new blocks + // after the given pause block is finalized and restarting after the + // given delay. + let builder = sc_finality_grandpa::VotingRulesBuilder::default(); + + let voting_rule = builder.build(); let grandpa_config = sc_finality_grandpa::GrandpaParams { - config: grandpa_config, - link: grandpa_link, - network, - voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), + config, + link: link_half, + network: network.clone(), + voting_rule, prometheus_registry, shared_voter_state, telemetry: telemetry.as_ref().map(|x| x.handle()), }; - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. task_manager .spawn_essential_handle() .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); } network_starter.start_network(); - Ok(task_manager) + + Ok(NewFull { + task_manager, + client, + overseer_handler, + network, + rpc_handlers, + backend, + }) +} + +pub fn build_full(config: Configuration, overseer_gen: impl OverseerGen) -> Result>, Error> { + new_full(config, None, overseer_gen) } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index b6e971eec005b..4c0e51ad3c903 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -39,6 +39,7 @@ frame-executive = { git = "https://github.com/paritytech/substrate", branch = "m frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -49,6 +50,7 @@ pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = " pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -63,6 +65,11 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +# Polkadot (parachain) Dependencies + +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] libsecp256k1 = { version = "0.3.4", features = ["hmac"] } @@ -89,6 +96,7 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "log/std", + "pallet-authority-discovery/std", "pallet-babe/std", "pallet-balances/std", "pallet-bridge-currency-exchange/std", @@ -103,8 +111,12 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "polkadot-primitives/std", + "polkadot-runtime-common/std", + "polkadot-runtime-parachains/std", "serde", "sp-api/std", + "sp-authority-discovery/std", "sp-block-builder/std", "sp-consensus-babe/std", "sp-core/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8b46020a1bdf0..fd3b5c94245c6 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -36,6 +36,7 @@ pub mod exchange; pub mod benches; pub mod kovan; pub mod millau_messages; +pub mod parachains; pub mod rialto_poa; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; @@ -44,14 +45,15 @@ use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_deli use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; +use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}; +use sp_runtime::traits::{AccountIdLookup, Block as BlockT, NumberFor, OpaqueKeys}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; -use sp_std::prelude::*; +use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; @@ -127,6 +129,9 @@ impl_opaque_keys! { pub struct SessionKeys { pub babe: Babe, pub grandpa: Grandpa, + pub para_validator: Initializer, + pub para_assignment: SessionInfo, + pub authority_discovery: AuthorityDiscovery, } } @@ -168,7 +173,7 @@ impl frame_system::Config for Runtime { /// The aggregated dispatch type that is available for extrinsics. type Call = Call; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = IdentityLookup; + type Lookup = AccountIdLookup; /// The index type for storing how many extrinsics an account has signed. type Index = Index; /// The index type for blocks. @@ -220,7 +225,7 @@ pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = }; parameter_types! { - pub const EpochDuration: u64 = bp_rialto::time_units::EPOCH_DURATION_IN_SLOTS as u64; + pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64; pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK; } @@ -442,6 +447,8 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } +impl pallet_authority_discovery::Config for Runtime {} + parameter_types! { /// This is a pretty unscientific cap. /// @@ -545,6 +552,7 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, // Consensus support. + AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, @@ -560,11 +568,30 @@ construct_runtime!( BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + + // Parachain modules. + ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin}, + ParachainsConfiguration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config}, + Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage}, + Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, + ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent}, + Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Call, Storage}, + Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config}, + Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, + Dmp: polkadot_runtime_parachains::dmp::{Pallet, Call, Storage}, + Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event}, + Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, + SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Call, Storage}, + + // Parachain Onboarding Pallets + Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event}, + Slots: polkadot_runtime_common::slots::{Pallet, Call, Storage, Event}, + ParasSudoWrapper: polkadot_runtime_common::paras_sudo_wrapper::{Pallet, Call}, } ); /// The address format for describing accounts. -pub type Address = AccountId; +pub type Address = sp_runtime::MultiAddress; /// Block header type as expected by this runtime. pub type Header = generic::Header; /// Block type as expected by this runtime. @@ -769,6 +796,95 @@ impl_runtime_apis! { } } + impl polkadot_primitives::v1::ParachainHost for Runtime { + fn validators() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v1::validators::() + } + + fn validator_groups() -> ( + Vec>, + polkadot_primitives::v1::GroupRotationInfo, + ) { + polkadot_runtime_parachains::runtime_api_impl::v1::validator_groups::() + } + + fn availability_cores() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v1::availability_cores::() + } + + fn persisted_validation_data( + para_id: polkadot_primitives::v1::Id, + assumption: polkadot_primitives::v1::OccupiedCoreAssumption, + ) + -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::(para_id, assumption) + } + + fn check_validation_outputs( + para_id: polkadot_primitives::v1::Id, + outputs: polkadot_primitives::v1::CandidateCommitments, + ) -> bool { + polkadot_runtime_parachains::runtime_api_impl::v1::check_validation_outputs::(para_id, outputs) + } + + fn session_index_for_child() -> polkadot_primitives::v1::SessionIndex { + polkadot_runtime_parachains::runtime_api_impl::v1::session_index_for_child::() + } + + fn validation_code( + para_id: polkadot_primitives::v1::Id, + assumption: polkadot_primitives::v1::OccupiedCoreAssumption, + ) + -> Option { + polkadot_runtime_parachains::runtime_api_impl::v1::validation_code::(para_id, assumption) + } + + fn candidate_pending_availability( + para_id: polkadot_primitives::v1::Id, + ) -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v1::candidate_pending_availability::(para_id) + } + + fn candidate_events() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v1::candidate_events::(|ev| { + match ev { + Event::Inclusion(ev) => { + Some(ev) + } + _ => None, + } + }) + } + + fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v1::session_info::(index) + } + + fn dmq_contents( + recipient: polkadot_primitives::v1::Id, + ) -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v1::dmq_contents::(recipient) + } + + fn inbound_hrmp_channels_contents( + recipient: polkadot_primitives::v1::Id + ) -> BTreeMap>> { + polkadot_runtime_parachains::runtime_api_impl::v1::inbound_hrmp_channels_contents::(recipient) + } + + fn validation_code_by_hash( + hash: polkadot_primitives::v1::ValidationCodeHash, + ) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::(hash) + } + } + + impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { + fn authorities() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v1::relevant_authority_ids::() + } + } + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< Block, Balance, diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs new file mode 100644 index 0000000000000..47fc6722a19e1 --- /dev/null +++ b/bin/rialto/runtime/src/parachains.rs @@ -0,0 +1,158 @@ +// 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 . + +//! Parachains support in Rialto runtime. + +use crate::{ + AccountId, Balance, Balances, BlockNumber, Event, Origin, RandomnessCollectiveFlip, Registrar, Runtime, Slots, +}; + +use frame_support::{parameter_types, weights::Weight}; +use frame_system::EnsureRoot; +use polkadot_primitives::v1::ValidatorIndex; +use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; +use polkadot_runtime_parachains::configuration as parachains_configuration; +use polkadot_runtime_parachains::dmp as parachains_dmp; +use polkadot_runtime_parachains::hrmp as parachains_hrmp; +use polkadot_runtime_parachains::inclusion as parachains_inclusion; +use polkadot_runtime_parachains::initializer as parachains_initializer; +use polkadot_runtime_parachains::origin as parachains_origin; +use polkadot_runtime_parachains::paras as parachains_paras; +use polkadot_runtime_parachains::paras_inherent as parachains_paras_inherent; +use polkadot_runtime_parachains::scheduler as parachains_scheduler; +use polkadot_runtime_parachains::session_info as parachains_session_info; +use polkadot_runtime_parachains::shared as parachains_shared; +use polkadot_runtime_parachains::ump as parachains_ump; + +/// Special `RewardValidators` that does nothing ;) +pub struct RewardValidators; +impl polkadot_runtime_parachains::inclusion::RewardValidators for RewardValidators { + fn reward_backing(_: impl IntoIterator) {} + fn reward_bitfields(_: impl IntoIterator) {} +} + +// all required parachain modules from `polkadot-runtime-parachains` crate + +impl parachains_configuration::Config for Runtime {} + +impl parachains_dmp::Config for Runtime {} + +impl parachains_hrmp::Config for Runtime { + type Event = Event; + type Origin = Origin; + type Currency = Balances; +} + +impl parachains_inclusion::Config for Runtime { + type Event = Event; + type RewardValidators = RewardValidators; +} + +impl parachains_initializer::Config for Runtime { + type Randomness = RandomnessCollectiveFlip; + type ForceOrigin = EnsureRoot; +} + +impl parachains_origin::Config for Runtime {} + +impl parachains_paras::Config for Runtime { + type Origin = Origin; + type Event = Event; +} + +impl parachains_paras_inherent::Config for Runtime {} + +impl parachains_scheduler::Config for Runtime {} + +impl parachains_session_info::Config for Runtime {} + +impl parachains_shared::Config for Runtime {} + +parameter_types! { + pub const FirstMessageFactorPercent: u64 = 100; +} + +impl parachains_ump::Config for Runtime { + type Event = Event; + type UmpSink = (); + type FirstMessageFactorPercent = FirstMessageFactorPercent; +} + +// required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing + +parameter_types! { + pub const ParaDeposit: Balance = 0; + pub const DataDepositPerByte: Balance = 0; +} + +impl paras_registrar::Config for Runtime { + type Event = Event; + type Origin = Origin; + type Currency = Balances; + type OnSwap = Slots; + type ParaDeposit = ParaDeposit; + type DataDepositPerByte = DataDepositPerByte; + type WeightInfo = paras_registrar::TestWeightInfo; +} + +parameter_types! { + pub const LeasePeriod: BlockNumber = 10 * bp_rialto::MINUTES; +} + +impl slots::Config for Runtime { + type Event = Event; + type Currency = Balances; + type Registrar = Registrar; + type LeasePeriod = LeasePeriod; + type WeightInfo = slots::TestWeightInfo; +} + +impl paras_sudo_wrapper::Config for Runtime {} + +pub struct ZeroWeights; + +impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights { + fn reserve() -> Weight { + 0 + } + fn register() -> Weight { + 0 + } + fn force_register() -> Weight { + 0 + } + fn deregister() -> Weight { + 0 + } + fn swap() -> Weight { + 0 + } +} + +impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights { + fn force_lease() -> Weight { + 0 + } + fn manage_lease_period_start(_c: u32, _t: u32) -> Weight { + 0 + } + fn clear_all_leases() -> Weight { + 0 + } + fn trigger_onboard() -> Weight { + 0 + } +} diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index b7b382f52bca6..6ab3431e459e6 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -42,7 +42,7 @@ pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Number of bytes, included in the signed Rialto transaction apart from the encoded call itself. /// /// Can be computed by subtracting encoded call size from raw transaction size. -pub const TX_EXTRA_BYTES: u32 = 103; +pub const TX_EXTRA_BYTES: u32 = 104; /// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 995ae7ae0d6d0..2e27342baa3ee 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -40,9 +40,9 @@ impl CliEncodeCall for Rialto { Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), )), - Call::Transfer { recipient, amount } => { - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer(recipient.raw_id(), amount.0)) - } + Call::Transfer { recipient, amount } => rialto_runtime::Call::Balances( + rialto_runtime::BalancesCall::transfer(recipient.raw_id().into(), amount.0), + ), Call::BridgeSendMessage { lane, payload, diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 343b44c378627..d7a9f840b16a5 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -209,7 +209,7 @@ mod tests { // then assert_eq!( format!("{:?}", hex), - "0x0400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" + "0x040000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" ); } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index ed0cec314a7f7..f7ba2ca65cba8 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -100,7 +100,7 @@ impl TransactionSignScheme for Rialto { let signer: sp_runtime::MultiSigner = signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - rialto_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + rialto_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account().into(), signature.into(), extra) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -110,7 +110,7 @@ impl TransactionSignScheme for Rialto { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| *address == rialto_runtime::Address::from(*signer.public().as_array_ref())) + .map(|(address, _, _)| *address == rialto_runtime::Address::Id(signer.public().into())) .unwrap_or(false) } From 5b3ebcce02bd65aaca7d7fd4acff2ae8cbea8890 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 13 Sep 2021 12:50:30 -0300 Subject: [PATCH 0565/1210] calculate fee using full message payload (#1132) --- bin/runtime-common/src/messages.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index a7591b2e57e6e..f85cc47ecef08 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -74,9 +74,9 @@ pub trait ChainWithMessages { /// Accound id on the chain. type AccountId: Encode + Decode; /// Public key of the chain account that may be used to verify signatures. - type Signer: Decode; + type Signer: Encode + Decode; /// Signature type used on the chain. - type Signature: Decode; + type Signature: Encode + Decode; /// Type of weight that is used on the chain. This would almost always be a regular /// `frame_support::weight::Weight`. But since the meaning of weight on different chains /// may be different, the `WeightOf<>` construct is used to avoid confusion between @@ -341,7 +341,7 @@ pub mod source { // of the message dispatch in the delivery transaction cost let pay_dispatch_fee_at_target_chain = payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; let delivery_transaction = BridgedChain::::estimate_delivery_transaction( - &payload.call, + &payload.encode(), pay_dispatch_fee_at_target_chain, if pay_dispatch_fee_at_target_chain { 0.into() From 17b1ac58cd02d39c0410eb5a3c15a4dae58052ac Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 14 Sep 2021 04:16:19 -0300 Subject: [PATCH 0566/1210] Add tests for `Raw` and `BridgeSendMessage` enum `Call` variants (#1125) * add some missing tests to encode_call * fix tests --- relays/bin-substrate/src/cli/encode_call.rs | 60 +++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index d7a9f840b16a5..b5f80ffdcd3c2 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -189,6 +189,7 @@ pub(crate) fn compute_maximal_message_arguments_size( #[cfg(test)] mod tests { use super::*; + use crate::cli::send_message::SendMessage; #[test] fn should_encode_transfer_call() { @@ -276,4 +277,63 @@ mod tests { let info = err.info.unwrap(); assert!(info.contains(&"remark-payload".to_string()) | info.contains(&"remark-size".to_string())) } + + #[test] + fn should_encode_raw_call() { + // given + let mut encode_call = EncodeCall::from_iter(vec![ + "encode-call", + "rialto-to-millau", + "raw", + "040000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0", + ]); + + // when + let hex = encode_call.encode().unwrap(); + + // then + assert_eq!( + format!("{:?}", hex), + "0x040000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" + ); + } + + #[test] + fn should_encode_bridge_send_message_call() { + // given + let encode_message = SendMessage::from_iter(vec![ + "send-message", + "millau-to-rialto", + "--source-port", + "10946", + "--source-signer", + "//Alice", + "--target-signer", + "//Alice", + "--origin", + "Target", + "remark", + ]) + .encode_payload() + .unwrap(); + + let mut encode_call = EncodeCall::from_iter(vec![ + "encode-call", + "rialto-to-millau", + "bridge-send-message", + "--fee", + "12345", + "--payload", + format!("{:}", &HexBytes::encode(&encode_message)).as_str(), + ]); + + // when + let call_hex = encode_call.encode().unwrap(); + + // then + assert!(format!("{:?}", call_hex).starts_with( + "0x11030000000001000000b0d60f000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" + )) + } } From 593457e202228b12fefd598a7157f142183eead9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 15 Sep 2021 15:08:27 +0300 Subject: [PATCH 0567/1210] Integrate token swap pallet into Millau runtime (#1099) * integrate token swap pallet into Millau runtime * set OnDeliveryConfirmed callback in Millau runtime --- bin/millau/runtime/Cargo.toml | 2 + bin/millau/runtime/src/lib.rs | 52 ++++- bin/millau/runtime/src/rialto_messages.rs | 2 +- modules/messages/src/lib.rs | 219 +++++++++++------- modules/token-swap/Cargo.toml | 2 +- modules/token-swap/src/lib.rs | 37 ++- modules/token-swap/src/mock.rs | 14 +- primitives/messages/src/source_chain.rs | 2 +- primitives/token-swap/src/lib.rs | 2 + .../bin-substrate/src/cli/encode_message.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 2 +- 11 files changed, 214 insertions(+), 122 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index a1619d4d8d9e6..271ff3cc983e2 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -23,6 +23,7 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } +pallet-bridge-token-swap = { path = "../../../modules/token-swap", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies @@ -77,6 +78,7 @@ std = [ "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-bridge-token-swap/std", "pallet-grandpa/std", "pallet-randomness-collective-flip/std", "pallet-session/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7469ebfec1734..f02e257730065 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -362,7 +362,7 @@ parameter_types! { pub const GetDeliveryConfirmationTransactionFee: Balance = bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; - pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; + pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; } /// Instance of the messages pallet used to relay messages to/from Rialto chain. @@ -394,11 +394,31 @@ impl pallet_bridge_messages::Config for Runtime { GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; - type OnDeliveryConfirmed = (); + type OnDeliveryConfirmed = pallet_bridge_token_swap::Pallet; type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; - type BridgedChainId = BridgedChainId; + type BridgedChainId = RialtoChainId; +} + +parameter_types! { + pub const TokenSwapMessagesLane: bp_messages::LaneId = *b"swap"; +} + +/// Instance of the with-Rialto token swap pallet. +pub type WithRialtoTokenSwapInstance = (); + +impl pallet_bridge_token_swap::Config for Runtime { + type Event = Event; + + type BridgedChainId = RialtoChainId; + type OutboundMessageLaneId = TokenSwapMessagesLane; + type MessagesBridge = pallet_bridge_messages::Pallet; + type ThisCurrency = pallet_balances::Pallet; + type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; + + type BridgedChain = bp_rialto::Rialto; + type FromBridgedToThisAccountIdConverter = bp_millau::AccountIdConverter; } construct_runtime!( @@ -407,20 +427,30 @@ construct_runtime!( NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { - BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, - BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, - BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, System: frame_system::{Pallet, Call, Config, Storage, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + + // Must be before session. Aura: pallet_aura::{Pallet, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + + // Consensus support. Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, + + // Rialto bridge modules. + BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, + BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event}, + + // Westend bridge modules. + BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, } ); diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 34b3b231c8124..1bc15caa10565 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -108,7 +108,7 @@ impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] || *lane == crate::TokenSwapMessagesLane::get() } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 2d55a84518afa..335cc7f9608fc 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -56,7 +56,11 @@ use bp_messages::{ }; use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; -use frame_support::{fail, traits::Get, weights::PostDispatchInfo}; +use frame_support::{ + fail, + traits::Get, + weights::{Pays, PostDispatchInfo}, +}; use frame_system::RawOrigin; use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::BadOrigin; @@ -241,94 +245,13 @@ pub mod pallet { payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResultWithPostInfo { - ensure_normal_operating_mode::()?; - let submitter = origin.into().map_err(|_| BadOrigin)?; - - // initially, actual (post-dispatch) weight is equal to pre-dispatch weight - let mut actual_weight = T::WeightInfo::send_message_weight(&payload); - - // let's first check if message can be delivered to target chain - T::TargetHeaderChain::verify_message(&payload).map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Message to lane {:?} is rejected by target chain: {:?}", - lane_id, - err, - ); - - Error::::MessageRejectedByChainVerifier - })?; - - // now let's enforce any additional lane rules - let mut lane = outbound_lane::(lane_id); - T::LaneMessageVerifier::verify_message( - &submitter, - &delivery_and_dispatch_fee, - &lane_id, - &lane.data(), - &payload, - ) - .map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Message to lane {:?} is rejected by lane verifier: {:?}", - lane_id, - err, - ); - - Error::::MessageRejectedByLaneVerifier - })?; - - // let's withdraw delivery and dispatch fee from submitter - T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( - &submitter, - &delivery_and_dispatch_fee, - &Self::relayer_fund_account_id(), - ) - .map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", - lane_id, - submitter, - delivery_and_dispatch_fee, - err, - ); - - Error::::FailedToWithdrawMessageFee - })?; - - // finally, save message in outbound storage and emit event - let encoded_payload = payload.encode(); - let encoded_payload_len = encoded_payload.len(); - let nonce = lane.send_message(MessageData { - payload: encoded_payload, - fee: delivery_and_dispatch_fee, - }); - - // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages - // the cost of pruning every message is roughly single db write - // => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned - let max_messages_to_prune = T::MaxMessagesToPruneAtOnce::get(); - let pruned_messages = lane.prune_messages(max_messages_to_prune); - if let Some(extra_messages) = max_messages_to_prune.checked_sub(pruned_messages) { - actual_weight = actual_weight.saturating_sub(T::DbWeight::get().writes(extra_messages)); - } - - log::trace!( - target: "runtime::bridge-messages", - "Accepted message {} to lane {:?}. Message size: {:?}", - nonce, + crate::send_message::( + origin.into().map_err(|_| BadOrigin)?, lane_id, - encoded_payload_len, - ); - - Self::deposit_event(Event::MessageAccepted(lane_id, nonce)); - - Ok(PostDispatchInfo { - actual_weight: Some(actual_weight), - pays_fee: Pays::Yes, - }) + payload, + delivery_and_dispatch_fee, + ) + .map(|sent_message| sent_message.post_dispatch_info) } /// Pay additional fee for the message. @@ -899,6 +822,126 @@ pub mod storage_keys { } } +impl bp_messages::source_chain::MessagesBridge + for Pallet +where + T: Config, + I: 'static, +{ + type Error = sp_runtime::DispatchErrorWithPostInfo; + + fn send_message( + sender: bp_messages::source_chain::Sender, + lane: LaneId, + message: T::OutboundPayload, + delivery_and_dispatch_fee: T::OutboundMessageFee, + ) -> Result { + crate::send_message::(sender, lane, message, delivery_and_dispatch_fee) + .map(|sent_message| sent_message.nonce) + } +} + +/// Message that has been sent. +struct SentMessage { + /// Nonce of the message. + pub nonce: MessageNonce, + /// Post-dispatch call info. + pub post_dispatch_info: PostDispatchInfo, +} + +/// Function that actually sends message. +fn send_message, I: 'static>( + submitter: bp_messages::source_chain::Sender, + lane_id: LaneId, + payload: T::OutboundPayload, + delivery_and_dispatch_fee: T::OutboundMessageFee, +) -> sp_std::result::Result> { + ensure_normal_operating_mode::()?; + + // initially, actual (post-dispatch) weight is equal to pre-dispatch weight + let mut actual_weight = T::WeightInfo::send_message_weight(&payload); + + // let's first check if message can be delivered to target chain + T::TargetHeaderChain::verify_message(&payload).map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Message to lane {:?} is rejected by target chain: {:?}", + lane_id, + err, + ); + + Error::::MessageRejectedByChainVerifier + })?; + + // now let's enforce any additional lane rules + let mut lane = outbound_lane::(lane_id); + T::LaneMessageVerifier::verify_message(&submitter, &delivery_and_dispatch_fee, &lane_id, &lane.data(), &payload) + .map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Message to lane {:?} is rejected by lane verifier: {:?}", + lane_id, + err, + ); + + Error::::MessageRejectedByLaneVerifier + })?; + + // let's withdraw delivery and dispatch fee from submitter + T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( + &submitter, + &delivery_and_dispatch_fee, + &Pallet::::relayer_fund_account_id(), + ) + .map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", + lane_id, + submitter, + delivery_and_dispatch_fee, + err, + ); + + Error::::FailedToWithdrawMessageFee + })?; + + // finally, save message in outbound storage and emit event + let encoded_payload = payload.encode(); + let encoded_payload_len = encoded_payload.len(); + let nonce = lane.send_message(MessageData { + payload: encoded_payload, + fee: delivery_and_dispatch_fee, + }); + + // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages + // the cost of pruning every message is roughly single db write + // => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned + let max_messages_to_prune = T::MaxMessagesToPruneAtOnce::get(); + let pruned_messages = lane.prune_messages(max_messages_to_prune); + if let Some(extra_messages) = max_messages_to_prune.checked_sub(pruned_messages) { + actual_weight = actual_weight.saturating_sub(T::DbWeight::get().writes(extra_messages)); + } + + log::trace!( + target: "runtime::bridge-messages", + "Accepted message {} to lane {:?}. Message size: {:?}", + nonce, + lane_id, + encoded_payload_len, + ); + + Pallet::::deposit_event(Event::MessageAccepted(lane_id, nonce)); + + Ok(SentMessage { + nonce, + post_dispatch_info: PostDispatchInfo { + actual_weight: Some(actual_weight), + pays_fee: Pays::Yes, + }, + }) +} + /// Ensure that the origin is either root, or `PalletOwner`. fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index bf3411ec06f20..0266fd51f7691 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -26,7 +26,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 206f040b96272..3216c69029d3d 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -49,6 +49,8 @@ //! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special //! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion. +#![cfg_attr(not(feature = "std"), no_std)] + use bp_messages::{ source_chain::{MessagesBridge, OnDeliveryConfirmed}, DeliveredMessages, LaneId, MessageNonce, @@ -64,6 +66,7 @@ use frame_support::{ use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Convert, Saturating}; +use sp_std::vec::Vec; #[cfg(test)] mod mock; @@ -98,7 +101,7 @@ pub mod pallet { type Event: From> + IsType<::Event>; /// Id of the bridge with the Bridged chain. - type BridgeChainId: Get; + type BridgedChainId: Get; /// The identifier of outbound message lane on This chain used to send token transfer /// messages to the Bridged chain. /// @@ -114,8 +117,6 @@ pub mod pallet { >::Balance, MessagePayloadOf, >; - /// Message delivery and dispatch fee for the tokens transfer message heading to the Bridged chain. - type MessageDeliveryAndDispatchFee: Get<>::Balance>; /// This chain Currency used in the tokens swap. type ThisCurrency: Currency; @@ -128,6 +129,10 @@ pub mod pallet { type FromBridgedToThisAccountIdConverter: Convert; } + /// Tokens balance at This chain. + pub type ThisChainBalance = + <>::ThisCurrency as Currency<::AccountId>>::Balance; + /// Type of the Bridged chain. pub type BridgedChainOf = >::BridgedChain; /// Tokens balance type at the Bridged chain. @@ -151,7 +156,7 @@ pub mod pallet { /// Type of `TokenSwap` used by the pallet. pub type TokenSwapOf = TokenSwap< BlockNumberFor, - <>::ThisCurrency as Currency<::AccountId>>::Balance, + ThisChainBalance, ::AccountId, BridgedBalanceOf, BridgedAccountIdOf, @@ -203,6 +208,7 @@ pub mod pallet { origin: OriginFor, swap: TokenSwapOf, target_public_at_bridged_chain: BridgedAccountPublicOf, + swap_delivery_and_dispatch_fee: ThisChainBalance, bridged_chain_spec_version: u32, bridged_currency_transfer: RawBridgedTransferCall, bridged_currency_transfer_weight: Weight, @@ -239,13 +245,12 @@ pub mod pallet { let swap_account = swap_account_id::(&swap); frame_support::storage::with_transaction(|| { // funds are transferred from This account to the temporary Swap account - let message_delivery_and_dispatch_fee = T::MessageDeliveryAndDispatchFee::get(); let transfer_result = T::ThisCurrency::transfer( &swap.source_account_at_this_chain, &swap_account, // saturating_add is ok, or we have the chain where single holder owns all tokens swap.source_balance_at_this_chain - .saturating_add(message_delivery_and_dispatch_fee), + .saturating_add(swap_delivery_and_dispatch_fee), // if we'll allow account to die, then he'll be unable to `cancel_claim` // if something won't work ExistenceRequirement::KeepAlive, @@ -268,7 +273,7 @@ pub mod pallet { // `Currency::transfer` call on the bridged chain, but no checks are made - it is // the transaction submitter to ensure it is valid. let send_message_result = T::MessagesBridge::send_message( - swap_account.clone(), + bp_messages::source_chain::Sender::from(Some(swap_account.clone())), T::OutboundMessageLaneId::get(), bp_message_dispatch::MessagePayload { spec_version: bridged_chain_spec_version, @@ -281,7 +286,7 @@ pub mod pallet { dispatch_fee_payment: DispatchFeePayment::AtTargetChain, call: bridged_currency_transfer, }, - message_delivery_and_dispatch_fee, + swap_delivery_and_dispatch_fee, ); let transfer_message_nonce = match send_message_result { Ok(transfer_message_nonce) => transfer_message_nonce, @@ -493,7 +498,7 @@ pub mod pallet { /// Expected target account representation on This chain (aka `target_account_at_this_chain`). pub(crate) fn target_account_at_this_chain, I: 'static>(swap: &TokenSwapOf) -> T::AccountId { T::FromBridgedToThisAccountIdConverter::convert(bp_runtime::derive_account_id( - T::BridgeChainId::get(), + T::BridgedChainId::get(), bp_runtime::SourceAccount::Account(swap.target_account_at_bridged_chain.clone()), )) } @@ -584,6 +589,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -606,6 +612,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -626,6 +633,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), swap, bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -646,6 +654,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), swap, bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -666,6 +675,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, transfer, BRIDGED_CHAIN_CALL_WEIGHT, @@ -683,6 +693,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -694,6 +705,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -713,6 +725,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -731,6 +744,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -749,6 +763,7 @@ mod tests { Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), bridged_chain_account_public(), + SWAP_DELIVERY_AND_DISPATCH_FEE, BRIDGED_CHAIN_SPEC_VERSION, test_transfer(), BRIDGED_CHAIN_CALL_WEIGHT, @@ -763,7 +778,7 @@ mod tests { assert_eq!(PendingMessages::::get(MESSAGE_NONCE), Some(swap_hash)); assert_eq!( pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), - test_swap().source_balance_at_this_chain + MessageDeliveryAndDispatchFee::get(), + test_swap().source_balance_at_this_chain + SWAP_DELIVERY_AND_DISPATCH_FEE, ); assert!( frame_system::Pallet::::events() @@ -989,7 +1004,7 @@ mod tests { ); assert_eq!( pallet_balances::Pallet::::free_balance(&THIS_CHAIN_ACCOUNT), - THIS_CHAIN_ACCOUNT_BALANCE - MessageDeliveryAndDispatchFee::get(), + THIS_CHAIN_ACCOUNT_BALANCE - SWAP_DELIVERY_AND_DISPATCH_FEE, ); assert!( frame_system::Pallet::::events() diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index 603db2adec7c8..c95f413b726f7 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -43,6 +43,8 @@ pub const MESSAGE_NONCE: MessageNonce = 3; pub const THIS_CHAIN_ACCOUNT: AccountId = 1; pub const THIS_CHAIN_ACCOUNT_BALANCE: Balance = 100_000; +pub const SWAP_DELIVERY_AND_DISPATCH_FEE: Balance = 1; + frame_support::construct_runtime! { pub enum TestRuntime where Block = Block, @@ -106,18 +108,16 @@ impl pallet_balances::Config for TestRuntime { } frame_support::parameter_types! { - pub const BridgeChainId: ChainId = *b"inst"; + pub const BridgedChainId: ChainId = *b"inst"; pub const OutboundMessageLaneId: LaneId = *b"lane"; - pub const MessageDeliveryAndDispatchFee: Balance = 1; } impl pallet_bridge_token_swap::Config for TestRuntime { type Event = Event; - type BridgeChainId = BridgeChainId; + type BridgedChainId = BridgedChainId; type OutboundMessageLaneId = OutboundMessageLaneId; type MessagesBridge = TestMessagesBridge; - type MessageDeliveryAndDispatchFee = MessageDeliveryAndDispatchFee; type ThisCurrency = pallet_balances::Pallet; type FromSwapToThisAccountIdConverter = TestAccountConverter; @@ -146,14 +146,14 @@ impl MessagesBridge> for T type Error = (); fn send_message( - sender: AccountId, + sender: frame_system::RawOrigin, lane: LaneId, message: MessagePayloadOf, delivery_and_dispatch_fee: Balance, ) -> Result { - assert_ne!(sender, THIS_CHAIN_ACCOUNT); + assert_ne!(sender, frame_system::RawOrigin::Signed(THIS_CHAIN_ACCOUNT)); assert_eq!(lane, OutboundMessageLaneId::get()); - assert_eq!(delivery_and_dispatch_fee, MessageDeliveryAndDispatchFee::get()); + assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE); match message.call[0] { OK_TRANSFER_CALL => Ok(MESSAGE_NONCE), BAD_TRANSFER_CALL => Err(()), diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 03bd67a03fa2f..3b84562e9b4fd 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -136,7 +136,7 @@ pub trait MessagesBridge { /// /// Returns unique message nonce or error if send has failed. fn send_message( - sender: AccountId, + sender: Sender, lane: LaneId, message: Payload, delivery_and_dispatch_fee: Balance, diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index 5509d2b72c9ec..afdaa2497e899 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +#![cfg_attr(not(feature = "std"), no_std)] + use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_core::U256; diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index d002ab28f4996..a2e049f24f08e 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -102,6 +102,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x01000000b0d60f000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x01000000b0d60f000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 66c2f17755610..68b332b0696e0 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -323,7 +323,7 @@ mod tests { weight: 1038000, origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, - call: hex!("0401081234").to_vec(), + call: hex!("0001081234").to_vec(), } ); } From 8598c268af033fe85d0d7322afd67934f0c9f68d Mon Sep 17 00:00:00 2001 From: bear <2630582710@qq.com> Date: Thu, 16 Sep 2021 19:54:56 +0800 Subject: [PATCH 0568/1210] Add `OnMessageAccepted` callback (#1134) * Add `OnMessageAccepted` config type * Update actual weight * Add unit test * Update weight * Remove old comment & update wrong test data * Make ci happy * Add lane_id param * update test case * Make log info more readable * Use saturating_sub * Update docs --- bin/millau/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + modules/messages/src/lib.rs | 87 ++++++++++++++++++++++--- modules/messages/src/mock.rs | 34 +++++++++- modules/messages/src/weights_ext.rs | 13 +++- primitives/messages/src/source_chain.rs | 12 ++++ 6 files changed, 134 insertions(+), 14 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f02e257730065..69e993b7bb78d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -394,6 +394,7 @@ impl pallet_bridge_messages::Config for Runtime { GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; + type OnMessageAccepted = (); type OnDeliveryConfirmed = pallet_bridge_token_swap::Pallet; type SourceHeaderChain = crate::rialto_messages::Rialto; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index fd3b5c94245c6..52206a8cf1693 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -528,6 +528,7 @@ impl pallet_bridge_messages::Config for Runtime { GetDeliveryConfirmationTransactionFee, RootAccountForPayments, >; + type OnMessageAccepted = (); type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::millau_messages::Millau; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 335cc7f9608fc..6e1ce21a58509 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -48,7 +48,8 @@ use crate::weights::WeightInfo; use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, OnMessageAccepted, + RelayersRewards, TargetHeaderChain, }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, @@ -160,6 +161,8 @@ pub mod pallet { Self::AccountId, Self::OutboundMessageFee, >; + /// Handler for accepted messages. + type OnMessageAccepted: OnMessageAccepted; /// Handler for delivered messages. type OnDeliveryConfirmed: OnDeliveryConfirmed; @@ -238,7 +241,7 @@ pub mod pallet { } /// Send message over lane. - #[pallet::weight(T::WeightInfo::send_message_weight(payload))] + #[pallet::weight(T::WeightInfo::send_message_weight(payload, T::DbWeight::get()))] pub fn send_message( origin: OriginFor, lane_id: LaneId, @@ -557,19 +560,19 @@ pub mod pallet { Some(difference) => { log::trace!( target: "runtime::bridge-messages", - "Messages delivery callback has returned unspent weight to refund the submitter: \ + "T::OnDeliveryConfirmed callback has spent less weight than expected. Refunding: \ {} - {} = {}", preliminary_callback_overhead, actual_callback_weight, difference, ); - actual_weight -= difference; + actual_weight = actual_weight.saturating_sub(difference); } None => { - debug_assert!(false, "The delivery confirmation callback is wrong"); - log::trace!( + debug_assert!(false, "T::OnDeliveryConfirmed callback consumed too much weight."); + log::error!( target: "runtime::bridge-messages", - "Messages delivery callback has returned more weight that it may spent: \ + "T::OnDeliveryConfirmed callback has spent more weight that it is allowed to: \ {} vs {}", preliminary_callback_overhead, actual_callback_weight, @@ -859,7 +862,7 @@ fn send_message, I: 'static>( ensure_normal_operating_mode::()?; // initially, actual (post-dispatch) weight is equal to pre-dispatch weight - let mut actual_weight = T::WeightInfo::send_message_weight(&payload); + let mut actual_weight = T::WeightInfo::send_message_weight(&payload, T::DbWeight::get()); // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload).map_err(|err| { @@ -913,6 +916,36 @@ fn send_message, I: 'static>( payload: encoded_payload, fee: delivery_and_dispatch_fee, }); + // Guaranteed to be called outside only when the message is accepted. + // We assume that the maximum weight call back used is `single_message_callback_overhead`, so do not perform + // complex db operation in callback. If you want to, put these magic logic in outside pallet and control + // the weight there. + let single_message_callback_overhead = T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); + let actual_callback_weight = T::OnMessageAccepted::on_messages_accepted(&lane_id, &nonce); + match single_message_callback_overhead.checked_sub(actual_callback_weight) { + Some(difference) if difference == 0 => (), + Some(difference) => { + log::trace!( + target: "runtime::bridge-messages", + "T::OnMessageAccepted callback has spent less weight than expected. Refunding: \ + {} - {} = {}", + single_message_callback_overhead, + actual_callback_weight, + difference, + ); + actual_weight = actual_weight.saturating_sub(difference); + } + None => { + debug_assert!(false, "T::OnMessageAccepted callback consumed too much weight."); + log::error!( + target: "runtime::bridge-messages", + "T::OnMessageAccepted callback has spent more weight that it is allowed to: \ + {} vs {}", + single_message_callback_overhead, + actual_callback_weight, + ); + } + } // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages // the cost of pruning every message is roughly single db write @@ -1114,7 +1147,7 @@ mod tests { use crate::mock::{ message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, - TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, TestRuntime, TokenConversionRate, + TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, TestOnMessageAccepted, TestRuntime, TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; @@ -2259,4 +2292,40 @@ mod tests { ); }); } + + #[test] + fn message_accepted_callbacks_are_called() { + run_test(|| { + send_regular_message(); + TestOnMessageAccepted::ensure_called(&TEST_LANE_ID, &1); + }); + } + + #[test] + #[should_panic] + fn message_accepted_panics_in_debug_mode_if_callback_is_wrong() { + run_test(|| { + TestOnMessageAccepted::set_consumed_weight_per_message(crate::mock::DbWeight::get().reads_writes(2, 2)); + send_regular_message(); + }); + } + + #[test] + fn message_accepted_refunds_non_zero_weight() { + run_test(|| { + TestOnMessageAccepted::set_consumed_weight_per_message(crate::mock::DbWeight::get().writes(1)); + let actual_callback_weight = send_regular_message(); + let pre_dispatch_weight = ::WeightInfo::send_message_weight( + ®ULAR_PAYLOAD, + crate::mock::DbWeight::get(), + ); + let prune_weight = + crate::mock::DbWeight::get().writes(::MaxMessagesToPruneAtOnce::get()); + + assert_eq!( + pre_dispatch_weight.saturating_sub(actual_callback_weight), + crate::mock::DbWeight::get().reads(1).saturating_add(prune_weight) + ); + }); + } } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 77a421b3411ae..88ec92ff03241 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -22,8 +22,8 @@ use crate::Config; use bitvec::prelude::*; use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, RelayersRewards, Sender, - TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, OnMessageAccepted, + RelayersRewards, Sender, TargetHeaderChain, }, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, @@ -178,6 +178,7 @@ impl Config for TestRuntime { type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; + type OnMessageAccepted = TestOnMessageAccepted; type OnDeliveryConfirmed = (TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2); type SourceHeaderChain = TestSourceHeaderChain; @@ -356,6 +357,35 @@ impl MessageDeliveryAndDispatchPayment for TestMessag } } +#[derive(Debug)] +pub struct TestOnMessageAccepted; + +impl TestOnMessageAccepted { + /// Verify that the callback has been called when the message is accepted. + pub fn ensure_called(lane: &LaneId, message: &MessageNonce) { + let key = (b"TestOnMessageAccepted", lane, message).encode(); + assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); + } + + /// Set consumed weight returned by the callback. + pub fn set_consumed_weight_per_message(weight: Weight) { + frame_support::storage::unhashed::put(b"TestOnMessageAccepted_Weight", &weight); + } + + /// Get consumed weight returned by the callback. + pub fn get_consumed_weight_per_message() -> Option { + frame_support::storage::unhashed::get(b"TestOnMessageAccepted_Weight") + } +} + +impl OnMessageAccepted for TestOnMessageAccepted { + fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight { + let key = (b"TestOnMessageAccepted", lane, message).encode(); + frame_support::storage::unhashed::put(&key, &true); + Self::get_consumed_weight_per_message().unwrap_or_else(|| DbWeight::get().reads_writes(1, 1)) + } +} + /// First on-messages-delivered callback. #[derive(Debug)] pub struct TestOnDeliveryConfirmed1; diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index c88ec47d72b9d..297b03cfc17bb 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -189,11 +189,14 @@ pub trait WeightInfoExt: WeightInfo { // Functions that are directly mapped to extrinsics weights. /// Weight of message send extrinsic. - fn send_message_weight(message: &impl Size) -> Weight { + fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { let transaction_overhead = Self::send_message_overhead(); let message_size_overhead = Self::send_message_size_overhead(message.size_hint()); + let call_back_overhead = Self::single_message_callback_overhead(db_weight); - transaction_overhead.saturating_add(message_size_overhead) + transaction_overhead + .saturating_add(message_size_overhead) + .saturating_add(call_back_overhead) } /// Weight of message delivery extrinsic. @@ -341,7 +344,11 @@ pub trait WeightInfoExt: WeightInfo { Self::receive_single_message_proof().saturating_sub(Self::receive_single_prepaid_message_proof()) } - /// Returns pre-dispatch weight of single message delivery callback call. + /// Returns pre-dispatch weight of single callback call. + /// + /// When benchmarking the weight please take into consideration both the `OnMessageAccepted` and + /// `OnDeliveryConfirmed` callbacks. The method should return the greater of the two, because it's + /// used to estimate the weight in both contexts. fn single_message_callback_overhead(db_weight: RuntimeDbWeight) -> Weight { db_weight.reads_writes(1, 1) } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 3b84562e9b4fd..326ab4f0f8ccb 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -173,6 +173,18 @@ impl OnDeliveryConfirmed for Tuple { } } +/// Handler for messages have been accepted +pub trait OnMessageAccepted { + /// Called when a message has been accepted by message pallet. + fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight; +} + +impl OnMessageAccepted for () { + fn on_messages_accepted(_lane: &LaneId, _message: &MessageNonce) -> Weight { + 0 + } +} + /// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and /// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden. pub struct ForbidOutboundMessages; From 82079a4832784188068667cf93f5a79ff60a7d4c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 21 Sep 2021 16:53:37 +0300 Subject: [PATCH 0569/1210] Polkadot <> Kusama relayers (#1122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * relay headers between Kusama and Polkadot * relay messages between Kusama and Polkadot * complex Kusama <> Polkadot relayer * expose relayer_fund_account_id from messages pallet * create relayers fund accounts on Kusama/Polkadot + some more fixes * fmt * fix compilation * compilation + clippy * compilation * MAXIMAL_BALANCE_DECREASE_PER_DAY for K<>P header relays * fmt * deduplicate tests * Update modules/messages/src/lib.rs Co-authored-by: Tomasz Drwięga * extract storage_parameter_key function * other grumbles * fix * fmt Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/chain_spec.rs | 8 +- bin/rialto/node/src/chain_spec.rs | 8 +- modules/messages/src/benchmarking.rs | 10 +- modules/messages/src/lib.rs | 33 +- primitives/chain-kusama/Cargo.toml | 2 + primitives/chain-kusama/src/lib.rs | 25 ++ primitives/chain-polkadot/Cargo.toml | 2 + primitives/chain-polkadot/src/lib.rs | 25 ++ primitives/polkadot-core/src/lib.rs | 5 +- primitives/runtime/src/lib.rs | 16 +- relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/chains/kusama.rs | 101 ++++++ .../src/chains/kusama_headers_to_polkadot.rs | 158 +++++++++ .../src/chains/kusama_messages_to_polkadot.rs | 304 ++++++++++++++++++ relays/bin-substrate/src/chains/mod.rs | 10 +- relays/bin-substrate/src/chains/polkadot.rs | 101 ++++++ .../src/chains/polkadot_headers_to_kusama.rs | 125 +++++++ .../src/chains/polkadot_messages_to_kusama.rs | 303 +++++++++++++++++ .../src/chains/wococo_headers_to_rococo.rs | 33 +- relays/bin-substrate/src/cli/bridge.rs | 50 +++ relays/bin-substrate/src/cli/init_bridge.rs | 30 ++ relays/bin-substrate/src/cli/relay_headers.rs | 16 + .../src/cli/relay_headers_and_messages.rs | 161 +++++++++- relays/client-kusama/Cargo.toml | 15 + relays/client-kusama/src/lib.rs | 70 +++- relays/client-kusama/src/runtime.rs | 151 +++++++++ relays/client-polkadot/Cargo.toml | 15 + relays/client-polkadot/src/lib.rs | 70 +++- relays/client-polkadot/src/runtime.rs | 151 +++++++++ relays/client-rococo/Cargo.toml | 2 + relays/client-substrate/src/lib.rs | 3 +- 31 files changed, 1936 insertions(+), 68 deletions(-) create mode 100644 relays/bin-substrate/src/chains/kusama.rs create mode 100644 relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs create mode 100644 relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs create mode 100644 relays/bin-substrate/src/chains/polkadot.rs create mode 100644 relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs create mode 100644 relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs create mode 100644 relays/client-kusama/src/runtime.rs create mode 100644 relays/client-polkadot/src/runtime.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 66ce0e23118e1..28c8be330412a 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -135,10 +135,10 @@ impl Alternative { get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("RialtoMessagesOwner"), - pallet_bridge_messages::Pallet::< - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, - >::relayer_fund_account_id(), + pallet_bridge_messages::relayer_fund_account_id::< + bp_millau::AccountId, + bp_millau::AccountIdConverter, + >(), derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Alice"), )), diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index b77b1d6acf6be..394432151478f 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -151,10 +151,10 @@ impl Alternative { get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("MillauMessagesOwner"), - pallet_bridge_messages::Pallet::< - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, - >::relayer_fund_account_id(), + pallet_bridge_messages::relayer_fund_account_id::< + bp_rialto::AccountId, + bp_rialto::AccountIdConverter, + >(), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Alice"), )), diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 4adf073191bc7..d6ec00324493a 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -484,7 +484,7 @@ benchmarks_instance_pallet! { // // This is base benchmark for all other confirmations delivery benchmarks. receive_delivery_proof_for_single_message { - let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -524,7 +524,7 @@ benchmarks_instance_pallet! { // as `weight(receive_delivery_proof_for_two_messages_by_single_relayer) // - weight(receive_delivery_proof_for_single_message)`. receive_delivery_proof_for_two_messages_by_single_relayer { - let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -564,7 +564,7 @@ benchmarks_instance_pallet! { // as `weight(receive_delivery_proof_for_two_messages_by_two_relayers) // - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`. receive_delivery_proof_for_two_messages_by_two_relayers { - let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer1_id: T::AccountId = account("relayer1", 1, SEED); let relayer1_balance = T::account_balance(&relayer1_id); let relayer2_id: T::AccountId = account("relayer2", 2, SEED); @@ -811,7 +811,7 @@ benchmarks_instance_pallet! { .try_into() .expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large"); - let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); T::endow_account(&relayers_fund_id); @@ -854,7 +854,7 @@ benchmarks_instance_pallet! { .try_into() .expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large "); - let relayers_fund_id = crate::Pallet::::relayer_fund_account_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let confirmation_relayer_id = account("relayer", 0, SEED); let relayers: BTreeMap = (1..=i) .map(|j| { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 6e1ce21a58509..208d1d048cf4d 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -64,7 +64,8 @@ use frame_support::{ }; use frame_system::RawOrigin; use num_traits::{SaturatingAdd, Zero}; -use sp_runtime::traits::BadOrigin; +use sp_core::H256; +use sp_runtime::traits::{BadOrigin, Convert}; use sp_std::{cell::RefCell, cmp::PartialOrd, marker::PhantomData, prelude::*}; mod inbound_lane; @@ -286,16 +287,17 @@ pub mod pallet { T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( &submitter, &additional_fee, - &Self::relayer_fund_account_id(), + &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", + "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", submitter, additional_fee, lane_id, nonce, + relayer_fund_account_id::(), err, ); @@ -604,7 +606,7 @@ pub mod pallet { // if some new messages have been confirmed, reward relayers if !relayers_rewards.is_empty() { - let relayer_fund_account = Self::relayer_fund_account_id(); + let relayer_fund_account = relayer_fund_account_id::(); >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( &confirmation_relayer, relayers_rewards, @@ -768,17 +770,6 @@ pub mod pallet { total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), } } - - /// AccountId of the shared relayer fund account. - /// - /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending - /// on the implementation it can be used to store relayers rewards. - /// See [InstantCurrencyPayments] for a concrete implementation. - pub fn relayer_fund_account_id() -> T::AccountId { - use sp_runtime::traits::Convert; - let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); - T::AccountIdConverter::convert(encoded_id) - } } } @@ -825,6 +816,16 @@ pub mod storage_keys { } } +/// AccountId of the shared relayer fund account. +/// +/// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending +/// on the implementation it can be used to store relayers rewards. +/// See [`InstantCurrencyPayments`] for a concrete implementation. +pub fn relayer_fund_account_id>() -> AccountId { + let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); + AccountIdConverter::convert(encoded_id) +} + impl bp_messages::source_chain::MessagesBridge for Pallet where @@ -894,7 +895,7 @@ fn send_message, I: 'static>( T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( &submitter, &delivery_and_dispatch_fee, - &Pallet::::relayer_fund_account_id(), + &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 4b26a2ba97c24..061a89a7d877f 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -20,6 +20,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -30,4 +31,5 @@ std = [ "frame-support/std", "sp-api/std", "sp-std/std", + "sp-version/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index af93d4108cc73..4dec9cd2a0ece 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -23,12 +23,24 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; +use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; /// Kusama Chain pub type Kusama = PolkadotLike; +// NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("kusama"), + impl_name: sp_version::create_runtime_str!("parity-kusama"), + authoring_version: 2, + spec_version: 9100, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 5, +}; + // NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { @@ -57,9 +69,22 @@ pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) /// Per-byte fee for Kusama transactions. pub const TRANSACTION_BYTE_FEE: Balance = 10 * 1_000_000_000_000 / 30_000 / 1_000; +/// Existential deposit on Kusama. +pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; + +/// The target length of a session (how often authorities change) on Kusama measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. +pub const SESSION_LENGTH: BlockNumber = 1 * time_units::HOURS; + /// Name of the With-Polkadot messages pallet instance in the Kusama runtime. pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; +/// Name of the DOT->KSM conversion rate stored in the Kusama runtime. +pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = "PolkadotToKusamaConversionRate"; + /// Name of the `KusamaFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; /// Name of the `KusamaFinalityApi::is_known_header` runtime method. diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 4877c6d5eaf26..181b230d61dd6 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -20,6 +20,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -30,4 +31,5 @@ std = [ "frame-support/std", "sp-api/std", "sp-std/std", + "sp-version/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 938f3fec8d128..d32165e6b79e3 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -23,12 +23,24 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; use sp_std::prelude::*; +use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; /// Polkadot Chain pub type Polkadot = PolkadotLike; +// NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("polkadot"), + impl_name: sp_version::create_runtime_str!("parity-polkadot"), + authoring_version: 0, + spec_version: 9100, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 7, +}; + // NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { @@ -57,9 +69,22 @@ pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) - /// Per-byte fee for Polkadot transactions. pub const TRANSACTION_BYTE_FEE: Balance = 10 * 10_000_000_000 / 100 / 1_000; +/// Existential deposit on Polkadot. +pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; + +/// The target length of a session (how often authorities change) on Polkadot measured in of number of +/// blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. +pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; + /// Name of the With-Kusama messages pallet instance in the Polkadot runtime. pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; +/// Name of the KSM->DOT conversion rate stored in the Polkadot runtime. +pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = "KusamaToPolkadotConversionRate"; + /// Name of the `PolkadotFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; /// Name of the `PolkadotFinalityApi::is_known_header` runtime method. diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 9e8726734eeda..a36f7ae65240c 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -217,6 +217,9 @@ pub type AccountPublic = ::Signer; /// Id of account on Polkadot-like chains. pub type AccountId = ::AccountId; +/// Address of account on Polkadot-like chains. +pub type AccountAddress = MultiAddress; + /// Index of a transaction on the Polkadot-like chains. pub type Nonce = u32; @@ -231,7 +234,7 @@ pub type Balance = u128; /// Unchecked Extrinsic type. pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic, Call, Signature, SignedExtensions>; + generic::UncheckedExtrinsic>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 4277af5e46174..a439dbf9ff7dc 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -20,9 +20,9 @@ use codec::Encode; use frame_support::RuntimeDebug; -use sp_core::hash::H256; +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::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, IndexOf, SignatureOf, @@ -183,3 +183,15 @@ impl, BlockHash: Copy> TransactionEra StorageKey { + let mut buffer = Vec::with_capacity(1 + parameter_name.len() + 1 + 1); + buffer.push(':' as u8); + buffer.extend_from_slice(parameter_name.as_bytes()); + buffer.push(':' as u8); + buffer.push(0); + StorageKey(sp_io::hashing::twox_128(&buffer).to_vec()) +} diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 8689821351390..3a7f63d8489d3 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -52,6 +52,7 @@ substrate-relay-helper = { path = "../lib-substrate-relay" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs new file mode 100644 index 0000000000000..6c7711316626e --- /dev/null +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -0,0 +1,101 @@ +// 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 . + +use codec::Decode; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; +use relay_kusama_client::Kusama; +use sp_version::RuntimeVersion; + +use crate::cli::{ + bridge, + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; + +/// Weight of the `system::remark` call at Kusama. +/// +/// This weight is larger (x2) than actual weight at current Kusama runtime to avoid unsuccessful +/// calls in the future. But since it is used only in tests (and on test chains), this is ok. +pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; + +/// Id of Kusama token that is used to fetch token price. +pub(crate) const TOKEN_ID: &str = "kusama"; + +impl CliEncodeCall for Kusama { + fn max_extrinsic_size() -> u32 { + bp_kusama::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Remark { remark_payload, .. } => { + relay_kusama_client::runtime::Call::System(relay_kusama_client::runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::KUSAMA_TO_POLKADOT_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_kusama_client::runtime::Call::BridgePolkadotMessages( + relay_kusama_client::runtime::BridgePolkadotMessagesCall::send_message(lane.0, payload, fee.0), + ) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + _ => anyhow::bail!("Unsupported Kusama call: {:?}", call), + }) + } + + fn get_dispatch_info(call: &relay_kusama_client::runtime::Call) -> anyhow::Result { + match *call { + relay_kusama_client::runtime::Call::System(relay_kusama_client::runtime::SystemCall::remark(_)) => { + Ok(DispatchInfo { + weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }) + } + _ => anyhow::bail!("Unsupported Kusama call: {:?}", call), + } + } +} + +impl CliChain for Kusama { + const RUNTIME_VERSION: RuntimeVersion = bp_kusama::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + bp_kusama::max_extrinsic_weight() + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Kusama is not yet supported.".into()) + } +} diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs new file mode 100644 index 0000000000000..4e7703529e32d --- /dev/null +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -0,0 +1,158 @@ +// 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 . + +//! Kusama-to-Polkadot headers sync entrypoint. + +use codec::Encode; +use sp_core::{Bytes, Pair}; + +use bp_header_chain::justification::GrandpaJustification; +use relay_kusama_client::{Kusama, SyncHeader as KusamaSyncHeader}; +use relay_polkadot_client::{Polkadot, SigningParams as PolkadotSigningParams}; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use relay_utils::metrics::MetricsParams; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat +/// relay as gone wild. +/// +/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 21 DOT, +/// but let's round up to 30 DOT here. +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000; + +/// Kusama-to-Polkadot finality sync pipeline. +pub(crate) type FinalityPipelineKusamaFinalityToPolkadot = + SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub(crate) struct KusamaFinalityToPolkadot { + finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot, +} + +impl KusamaFinalityToPolkadot { + pub fn new(target_client: Client, target_sign: PolkadotSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot::new(target_client, target_sign), + } + } +} + +impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { + type FinalitySyncPipeline = FinalityPipelineKusamaFinalityToPolkadot; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + + type TargetChain = Polkadot; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::add_polkadot_kusama_price_metrics::( + Some(finality_relay::metrics_prefix::()), + params, + ) + } + + fn start_relay_guards(&self) { + relay_substrate_client::guard::abort_on_spec_version_change( + self.finality_pipeline.target_client.clone(), + bp_polkadot::VERSION.spec_version, + ); + relay_substrate_client::guard::abort_when_account_balance_decreased( + self.finality_pipeline.target_client.clone(), + self.transactions_author(), + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); + } + + fn transactions_author(&self) -> bp_polkadot::AccountId { + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + era: bp_runtime::TransactionEraOf, + transaction_nonce: bp_runtime::IndexOf, + header: KusamaSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof(header.into_inner(), proof), + ); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Polkadot::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + era, + UnsignedTransaction::new(call, transaction_nonce), + ); + + Bytes(transaction.encode()) + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + use frame_support::weights::WeightToFeePolynomial; + use pallet_bridge_grandpa::weights::WeightInfo; + + pub fn compute_maximal_balance_decrease_per_day(expected_source_headers_per_day: u32) -> B + where + B: From + std::ops::Mul, + W: WeightToFeePolynomial, + { + // we assume that the GRANDPA is not lagging here => ancestry length will be near to 0 (let's round up to 2) + const AVG_VOTES_ANCESTRIES_LEN: u32 = 2; + // let's assume number of validators is 1024 (more than on any existing well-known chain atm) + // => number of precommits is *2/3 + 1 + const AVG_PRECOMMITS_LEN: u32 = 1024 * 2 / 3 + 1; + + // GRANDPA pallet weights. We're now using Rialto weights everywhere. + // + // Using Rialto runtime is slightly incorrect, because `DbWeight` of other runtimes may differ + // from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is the same. + type GrandpaPalletWeights = pallet_bridge_grandpa::weights::RialtoWeight; + + // The following formula shall not be treated as super-accurate - guard is to protect from mad relays, + // not to protect from over-average loses. + + // increase number of headers a bit + let expected_source_headers_per_day = expected_source_headers_per_day * 110 / 100; + let single_source_header_submit_call_weight = + GrandpaPalletWeights::submit_finality_proof(AVG_VOTES_ANCESTRIES_LEN, AVG_PRECOMMITS_LEN); + // for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + adjusted fee + let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2; + let single_source_header_tx_cost = W::calc(&single_source_header_submit_tx_weight); + let maximal_expected_decrease = single_source_header_tx_cost * B::from(expected_source_headers_per_day); + + maximal_expected_decrease + } + + #[test] + fn maximal_balance_decrease_per_day_is_sane() { + // we expect Kusama -> Polkadot relay to be running in mandatory-headers-only mode + // => we expect single header for every Kusama session + let maximal_balance_decrease = compute_maximal_balance_decrease_per_day::< + bp_polkadot::Balance, + bp_polkadot::WeightToFee, + >(bp_kusama::DAYS / bp_kusama::SESSION_LENGTH + 1); + assert!( + MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, + "Maximal expected loss per day {} is larger than hardcoded {}", + maximal_balance_decrease, + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); + } +} diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs new file mode 100644 index 0000000000000..5b07e6d588a6c --- /dev/null +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -0,0 +1,304 @@ +// 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 . + +//! Kusama-to-Polkadot messages sync entrypoint. + +use std::{ops::RangeInclusive, time::Duration}; + +use codec::Encode; +use sp_core::{Bytes, Pair}; + +use bp_messages::MessageNonce; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use frame_support::weights::Weight; +use messages_relay::message_lane::MessageLane; +use relay_kusama_client::{HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams}; +use relay_polkadot_client::{HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_utils::metrics::MetricsParams; +use sp_runtime::{FixedPointNumber, FixedU128}; +use substrate_relay_helper::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, +}; +use substrate_relay_helper::messages_source::SubstrateMessagesSource; +use substrate_relay_helper::messages_target::SubstrateMessagesTarget; + +/// Kusama-to-Polkadot message lane. +pub type MessageLaneKusamaMessagesToPolkadot = + SubstrateMessageLaneToSubstrate; + +#[derive(Clone)] +pub struct KusamaMessagesToPolkadot { + message_lane: MessageLaneKusamaMessagesToPolkadot, +} + +impl SubstrateMessageLane for KusamaMessagesToPolkadot { + type MessageLane = MessageLaneKusamaMessagesToPolkadot; + + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; + + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; + + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + + type SourceChain = Kusama; + type TargetChain = Polkadot; + + fn source_transactions_author(&self) -> bp_kusama::AccountId { + (*self.message_lane.source_sign.public().as_array_ref()).into() + } + + fn make_messages_receiving_proof_transaction( + &self, + transaction_nonce: bp_runtime::IndexOf, + _generated_at_block: PolkadotHeaderId, + proof: ::MessagesReceivingProof, + ) -> Bytes { + let (relayers_state, proof) = proof; + let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof( + proof, + relayers_state, + ), + ); + let genesis_hash = *self.message_lane.source_client.genesis_hash(); + let transaction = Kusama::sign_transaction( + genesis_hash, + &self.message_lane.source_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(call, transaction_nonce), + ); + log::trace!( + target: "bridge", + "Prepared Polkadot -> Kusama confirmation transaction. Weight: /{}, size: {}/{}", + bp_kusama::max_extrinsic_weight(), + transaction.encode().len(), + bp_kusama::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_polkadot::AccountId { + (*self.message_lane.target_sign.public().as_array_ref()).into() + } + + fn make_messages_delivery_transaction( + &self, + transaction_nonce: bp_runtime::IndexOf, + _generated_at_header: KusamaHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Bytes { + let (dispatch_weight, proof) = proof; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; + + let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof( + self.message_lane.relayer_id_at_source.clone(), + proof, + messages_count as _, + dispatch_weight, + ), + ); + let genesis_hash = *self.message_lane.target_client.genesis_hash(); + let transaction = Polkadot::sign_transaction( + genesis_hash, + &self.message_lane.target_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(call, transaction_nonce), + ); + log::trace!( + target: "bridge", + "Prepared Kusama -> Polkadot delivery transaction. Weight: /{}, size: {}/{}", + bp_polkadot::max_extrinsic_weight(), + transaction.encode().len(), + bp_polkadot::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } +} + +/// Kusama node as messages source. +type KusamaSourceClient = SubstrateMessagesSource; + +/// Polkadot node as messages target. +type PolkadotTargetClient = SubstrateMessagesTarget; + +/// Run Kusama-to-Polkadot messages sync. +pub async fn run( + params: MessagesRelayParams, +) -> anyhow::Result<()> { + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_kusama = (*params.source_sign.public().as_array_ref()).into(); + + let lane_id = params.lane_id; + let source_client = params.source_client; + let lane = KusamaMessagesToPolkadot { + message_lane: SubstrateMessageLaneToSubstrate { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_kusama, + }, + }; + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_polkadot::max_extrinsic_size() / 3; + // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_polkadot::max_extrinsic_weight(), + bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( + max_messages_in_single_batch / 2, + max_messages_weight_in_single_batch / 2, + ); + + log::info!( + target: "bridge", + "Starting Kusama -> Polkadot messages relay.\n\t\ + Kusama relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}\n\t\ + Relayer mode: {:?}", + lane.message_lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + params.relayer_mode, + ); + + let (metrics_params, metrics_values) = add_standalone_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + ::MessageLane, + >(&lane_id)), + params.metrics_params, + source_client.clone(), + )?; + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Kusama::AVERAGE_BLOCK_INTERVAL, + target_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relayer_mode: params.relayer_mode, + }, + }, + KusamaSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + params.target_to_source_headers_relay, + ), + PolkadotTargetClient::new( + params.target_client, + lane, + lane_id, + metrics_values, + params.source_to_target_headers_relay, + ), + metrics_params, + futures::future::pending(), + ) + .await +} + +/// Add standalone metrics for the Kusama -> Polkadot messages loop. +pub(crate) fn add_standalone_metrics( + metrics_prefix: Option, + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + let polkadot_to_kusama_conversion_rate_key = + bp_runtime::storage_parameter_key(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME).0; + + substrate_relay_helper::messages_lane::add_standalone_metrics::( + metrics_prefix, + metrics_params, + source_client, + Some(crate::chains::polkadot::TOKEN_ID), + Some(crate::chains::kusama::TOKEN_ID), + Some(( + sp_core::storage::StorageKey(polkadot_to_kusama_conversion_rate_key), + // starting relay before this parameter will be set to some value may cause troubles + FixedU128::from_inner(FixedU128::DIV), + )), + ) +} + +/// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage. +pub(crate) async fn update_polkadot_to_kusama_conversion_rate( + client: Client, + signer: ::AccountKeyPair, + updated_rate: f64, +) -> anyhow::Result<()> { + let genesis_hash = *client.genesis_hash(); + let signer_id = (*signer.public().as_array_ref()).into(); + client + .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { + Bytes( + Kusama::sign_transaction( + genesis_hash, + &signer, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + relay_kusama_client::runtime::Call::BridgePolkadotMessages( + relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter( + relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate( + sp_runtime::FixedU128::from_float(updated_rate), + ) + ) + ), + transaction_nonce, + ), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|err| anyhow::format_err!("{:?}", err)) +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 6f8273a7fcbd9..4c02e9b1c98b2 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -16,8 +16,12 @@ //! Chain-specific relayer configuration. +pub mod kusama_headers_to_polkadot; +pub mod kusama_messages_to_polkadot; pub mod millau_headers_to_rialto; pub mod millau_messages_to_rialto; +pub mod polkadot_headers_to_kusama; +pub mod polkadot_messages_to_kusama; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; pub mod rococo_headers_to_wococo; @@ -26,7 +30,9 @@ pub mod westend_headers_to_millau; pub mod wococo_headers_to_rococo; pub mod wococo_messages_to_rococo; +mod kusama; mod millau; +mod polkadot; mod rialto; mod rococo; mod westend; @@ -37,9 +43,9 @@ mod wococo; // Rialto as BTC and Millau as wBTC (only in relayer). /// The identifier of token, which value is associated with Rialto token value by relayer. -pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = "polkadot"; +pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = polkadot::TOKEN_ID; /// The identifier of token, which value is associated with Millau token value by relayer. -pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = "kusama"; +pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = kusama::TOKEN_ID; use relay_utils::metrics::MetricsParams; diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs new file mode 100644 index 0000000000000..372bdb90efcb4 --- /dev/null +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -0,0 +1,101 @@ +// 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 . + +use codec::Decode; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; +use relay_polkadot_client::Polkadot; +use sp_version::RuntimeVersion; + +use crate::cli::{ + bridge, + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; + +/// Weight of the `system::remark` call at Polkadot. +/// +/// This weight is larger (x2) than actual weight at current Polkadot runtime to avoid unsuccessful +/// calls in the future. But since it is used only in tests (and on test chains), this is ok. +pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; + +/// Id of Polkadot token that is used to fetch token price. +pub(crate) const TOKEN_ID: &str = "polkadot"; + +impl CliEncodeCall for Polkadot { + fn max_extrinsic_size() -> u32 { + bp_polkadot::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Remark { remark_payload, .. } => { + relay_polkadot_client::runtime::Call::System(relay_polkadot_client::runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )) + } + Call::BridgeSendMessage { + lane, + payload, + fee, + bridge_instance_index, + } => match *bridge_instance_index { + bridge::POLKADOT_TO_KUSAMA_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_polkadot_client::runtime::Call::BridgeKusamaMessages( + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::send_message(lane.0, payload, fee.0), + ) + } + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, + _ => anyhow::bail!("Unsupported Polkadot call: {:?}", call), + }) + } + + fn get_dispatch_info(call: &relay_polkadot_client::runtime::Call) -> anyhow::Result { + match *call { + relay_polkadot_client::runtime::Call::System(relay_polkadot_client::runtime::SystemCall::remark(_)) => { + Ok(DispatchInfo { + weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }) + } + _ => anyhow::bail!("Unsupported Polkadot call: {:?}", call), + } + } +} + +impl CliChain for Polkadot { + const RUNTIME_VERSION: RuntimeVersion = bp_polkadot::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = (); + + fn ss58_format() -> u16 { + 42 + } + + fn max_extrinsic_weight() -> Weight { + bp_polkadot::max_extrinsic_weight() + } + + fn encode_message(_message: encode_message::MessagePayload) -> Result { + Err("Sending messages from Polkadot is not yet supported.".into()) + } +} diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs new file mode 100644 index 0000000000000..aee66b8a3f270 --- /dev/null +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -0,0 +1,125 @@ +// 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 . + +//! Polkadot-to-Kusama headers sync entrypoint. + +use codec::Encode; +use sp_core::{Bytes, Pair}; + +use bp_header_chain::justification::GrandpaJustification; +use relay_kusama_client::{Kusama, SigningParams as KusamaSigningParams}; +use relay_polkadot_client::{Polkadot, SyncHeader as PolkadotSyncHeader}; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use relay_utils::metrics::MetricsParams; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; + +/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat +/// relay as gone wild. +/// +/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 0.001 KSM, +/// but let's round up to 0.1 KSM here. +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000; + +/// Polkadot-to-Kusama finality sync pipeline. +pub(crate) type FinalityPipelinePolkadotFinalityToKusama = + SubstrateFinalityToSubstrate; + +#[derive(Clone, Debug)] +pub(crate) struct PolkadotFinalityToKusama { + finality_pipeline: FinalityPipelinePolkadotFinalityToKusama, +} + +impl PolkadotFinalityToKusama { + pub fn new(target_client: Client, target_sign: KusamaSigningParams) -> Self { + Self { + finality_pipeline: FinalityPipelinePolkadotFinalityToKusama::new(target_client, target_sign), + } + } +} + +impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { + type FinalitySyncPipeline = FinalityPipelinePolkadotFinalityToKusama; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; + + type TargetChain = Kusama; + + fn customize_metrics(params: MetricsParams) -> anyhow::Result { + crate::chains::add_polkadot_kusama_price_metrics::( + Some(finality_relay::metrics_prefix::()), + params, + ) + } + + fn start_relay_guards(&self) { + relay_substrate_client::guard::abort_on_spec_version_change( + self.finality_pipeline.target_client.clone(), + bp_kusama::VERSION.spec_version, + ); + relay_substrate_client::guard::abort_when_account_balance_decreased( + self.finality_pipeline.target_client.clone(), + self.transactions_author(), + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); + } + + fn transactions_author(&self) -> bp_kusama::AccountId { + (*self.finality_pipeline.target_sign.public().as_array_ref()).into() + } + + fn make_submit_finality_proof_transaction( + &self, + era: bp_runtime::TransactionEraOf, + transaction_nonce: bp_runtime::IndexOf, + header: PolkadotSyncHeader, + proof: GrandpaJustification, + ) -> Bytes { + let call = relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof(header.into_inner(), proof), + ); + let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); + let transaction = Kusama::sign_transaction( + genesis_hash, + &self.finality_pipeline.target_sign, + era, + UnsignedTransaction::new(call, transaction_nonce), + ); + + Bytes(transaction.encode()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::chains::kusama_headers_to_polkadot::tests::compute_maximal_balance_decrease_per_day; + + #[test] + fn maximal_balance_decrease_per_day_is_sane() { + // we expect Polkadot -> Kusama relay to be running in mandatory-headers-only mode + // => we expect single header for every Polkadot session + let maximal_balance_decrease = compute_maximal_balance_decrease_per_day::< + bp_kusama::Balance, + bp_kusama::WeightToFee, + >(bp_polkadot::DAYS / bp_polkadot::SESSION_LENGTH + 1); + assert!( + MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, + "Maximal expected loss per day {} is larger than hardcoded {}", + maximal_balance_decrease, + MAXIMAL_BALANCE_DECREASE_PER_DAY, + ); + } +} diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs new file mode 100644 index 0000000000000..092a02598d1b4 --- /dev/null +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -0,0 +1,303 @@ +// 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 . + +//! Polkadot-to-Kusama messages sync entrypoint. + +use std::{ops::RangeInclusive, time::Duration}; + +use codec::Encode; +use sp_core::{Bytes, Pair}; + +use bp_messages::MessageNonce; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; +use frame_support::weights::Weight; +use messages_relay::message_lane::MessageLane; +use relay_kusama_client::{HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams}; +use relay_polkadot_client::{HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_utils::metrics::MetricsParams; +use sp_runtime::{FixedPointNumber, FixedU128}; +use substrate_relay_helper::messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, +}; +use substrate_relay_helper::messages_source::SubstrateMessagesSource; +use substrate_relay_helper::messages_target::SubstrateMessagesTarget; + +/// Polkadot-to-Kusama message lane. +pub type MessageLanePolkadotMessagesToKusama = + SubstrateMessageLaneToSubstrate; + +#[derive(Clone)] +pub struct PolkadotMessagesToKusama { + message_lane: MessageLanePolkadotMessagesToKusama, +} + +impl SubstrateMessageLane for PolkadotMessagesToKusama { + type MessageLane = MessageLanePolkadotMessagesToKusama; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; + + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; + + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + + type SourceChain = Polkadot; + type TargetChain = Kusama; + + fn source_transactions_author(&self) -> bp_polkadot::AccountId { + (*self.message_lane.source_sign.public().as_array_ref()).into() + } + + fn make_messages_receiving_proof_transaction( + &self, + transaction_nonce: bp_runtime::IndexOf, + _generated_at_block: KusamaHeaderId, + proof: ::MessagesReceivingProof, + ) -> Bytes { + let (relayers_state, proof) = proof; + let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof( + proof, + relayers_state, + ), + ); + let genesis_hash = *self.message_lane.source_client.genesis_hash(); + let transaction = Polkadot::sign_transaction( + genesis_hash, + &self.message_lane.source_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(call, transaction_nonce), + ); + log::trace!( + target: "bridge", + "Prepared Kusama -> Polkadot confirmation transaction. Weight: /{}, size: {}/{}", + bp_polkadot::max_extrinsic_weight(), + transaction.encode().len(), + bp_polkadot::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } + + fn target_transactions_author(&self) -> bp_kusama::AccountId { + (*self.message_lane.target_sign.public().as_array_ref()).into() + } + + fn make_messages_delivery_transaction( + &self, + transaction_nonce: bp_runtime::IndexOf, + _generated_at_header: PolkadotHeaderId, + _nonces: RangeInclusive, + proof: ::MessagesProof, + ) -> Bytes { + let (dispatch_weight, proof) = proof; + let FromBridgedChainMessagesProof { + ref nonces_start, + ref nonces_end, + .. + } = proof; + let messages_count = nonces_end - nonces_start + 1; + + let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof( + self.message_lane.relayer_id_at_source.clone(), + proof, + messages_count as _, + dispatch_weight, + ), + ); + let genesis_hash = *self.message_lane.target_client.genesis_hash(); + let transaction = Kusama::sign_transaction( + genesis_hash, + &self.message_lane.target_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(call, transaction_nonce), + ); + log::trace!( + target: "bridge", + "Prepared Polkadot -> Kusama delivery transaction. Weight: /{}, size: {}/{}", + bp_kusama::max_extrinsic_weight(), + transaction.encode().len(), + bp_kusama::max_extrinsic_size(), + ); + Bytes(transaction.encode()) + } +} + +/// Polkadot node as messages source. +type PolkadotSourceClient = SubstrateMessagesSource; + +/// Kusama node as messages target. +type KusamaTargetClient = SubstrateMessagesTarget; + +/// Run Polkadot-to-Kusama messages sync. +pub async fn run( + params: MessagesRelayParams, +) -> anyhow::Result<()> { + let stall_timeout = Duration::from_secs(5 * 60); + let relayer_id_at_polkadot = (*params.source_sign.public().as_array_ref()).into(); + + let lane_id = params.lane_id; + let source_client = params.source_client; + let lane = PolkadotMessagesToKusama { + message_lane: SubstrateMessageLaneToSubstrate { + source_client: source_client.clone(), + source_sign: params.source_sign, + target_client: params.target_client.clone(), + target_sign: params.target_sign, + relayer_id_at_source: relayer_id_at_polkadot, + }, + }; + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = bp_kusama::max_extrinsic_size() / 3; + // we don't know exact weights of the Kusama runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + select_delivery_transaction_limits::>( + bp_kusama::max_extrinsic_weight(), + bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( + max_messages_in_single_batch / 2, + max_messages_weight_in_single_batch / 2, + ); + + log::info!( + target: "bridge", + "Starting Polkadot -> Kusama messages relay.\n\t\ + Polkadot relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}\n\t\ + Relayer mode: {:?}", + lane.message_lane.relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + params.relayer_mode, + ); + + let (metrics_params, metrics_values) = add_standalone_metrics( + Some(messages_relay::message_lane_loop::metrics_prefix::< + ::MessageLane, + >(&lane_id)), + params.metrics_params, + source_client.clone(), + )?; + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: lane_id, + source_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, + target_tick: Kusama::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relayer_mode: params.relayer_mode, + }, + }, + PolkadotSourceClient::new( + source_client.clone(), + lane.clone(), + lane_id, + params.target_to_source_headers_relay, + ), + KusamaTargetClient::new( + params.target_client, + lane, + lane_id, + metrics_values, + params.source_to_target_headers_relay, + ), + metrics_params, + futures::future::pending(), + ) + .await +} + +/// Add standalone metrics for the Polkadot -> Kusama messages loop. +pub(crate) fn add_standalone_metrics( + metrics_prefix: Option, + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + let kusama_to_polkadot_conversion_rate_key = + bp_runtime::storage_parameter_key(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME).0; + + substrate_relay_helper::messages_lane::add_standalone_metrics::( + metrics_prefix, + metrics_params, + source_client, + Some(crate::chains::kusama::TOKEN_ID), + Some(crate::chains::polkadot::TOKEN_ID), + Some(( + sp_core::storage::StorageKey(kusama_to_polkadot_conversion_rate_key), + // starting relay before this parameter will be set to some value may cause troubles + FixedU128::from_inner(FixedU128::DIV), + )), + ) +} + +/// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage. +pub(crate) async fn update_kusama_to_polkadot_conversion_rate( + client: Client, + signer: ::AccountKeyPair, + updated_rate: f64, +) -> anyhow::Result<()> { + let genesis_hash = *client.genesis_hash(); + let signer_id = (*signer.public().as_array_ref()).into(); + client + .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { + Bytes( + Polkadot::sign_transaction( + genesis_hash, + &signer, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + relay_polkadot_client::runtime::Call::BridgeKusamaMessages( + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter( + relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate( + sp_runtime::FixedU128::from_float(updated_rate), + ) + ) + ), + transaction_nonce, + ), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|err| anyhow::format_err!("{:?}", err)) +} diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index b3e98d65421ec..b06921bfd9cec 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -104,39 +104,18 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { #[cfg(test)] mod tests { - use frame_support::weights::WeightToFeePolynomial; - - use pallet_bridge_grandpa::weights::WeightInfo; - use super::*; + use crate::chains::kusama_headers_to_polkadot::tests::compute_maximal_balance_decrease_per_day; #[test] fn maximal_balance_decrease_per_day_is_sane() { - // Rococo/Wococo GRANDPA pallet weights. They're now using Rialto weights => using `RialtoWeight` is justified. - // - // Using Rialto runtime this is slightly incorrect, because `DbWeight` of Rococo/Wococo runtime may differ - // from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is the same. - type RococoGrandpaPalletWeights = pallet_bridge_grandpa::weights::RialtoWeight; - - // The following formula shall not be treated as super-accurate - guard is to protect from mad relays, - // not to protect from over-average loses. - // - // Worst case: we're submitting proof for every source header. Since we submit every header, the number of - // headers in ancestry proof is near to 0 (let's round up to 2). And the number of authorities is 1024, - // which is (now) larger than on any existing chain => normally there'll be ~1024*2/3+1 commits. - const AVG_VOTES_ANCESTRIES_LEN: u32 = 2; - const AVG_PRECOMMITS_LEN: u32 = 1024 * 2 / 3 + 1; - let number_of_source_headers_per_day: bp_wococo::Balance = bp_wococo::DAYS as _; - let single_source_header_submit_call_weight = - RococoGrandpaPalletWeights::submit_finality_proof(AVG_VOTES_ANCESTRIES_LEN, AVG_PRECOMMITS_LEN); - // for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + adjusted fee - let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2; - let single_source_header_tx_cost = bp_rococo::WeightToFee::calc(&single_source_header_submit_tx_weight); - let maximal_expected_decrease = single_source_header_tx_cost * number_of_source_headers_per_day; + // we expect Wococo -> Rococo relay to be running in all-headers mode + let maximal_balance_decrease = + compute_maximal_balance_decrease_per_day::(bp_wococo::DAYS); assert!( - MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_expected_decrease, + MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, "Maximal expected loss per day {} is larger than hardcoded {}", - maximal_expected_decrease, + maximal_balance_decrease, MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 30950b289f5fc..1af6142c53eca 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -24,6 +24,8 @@ pub enum FullBridge { RialtoToMillau, RococoToWococo, WococoToRococo, + KusamaToPolkadot, + PolkadotToKusama, } impl FullBridge { @@ -34,6 +36,8 @@ impl FullBridge { Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, Self::RococoToWococo => ROCOCO_TO_WOCOCO_INDEX, Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX, + Self::KusamaToPolkadot => KUSAMA_TO_POLKADOT_INDEX, + Self::PolkadotToKusama => POLKADOT_TO_KUSAMA_INDEX, } } } @@ -42,6 +46,8 @@ pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0; pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0; +pub const KUSAMA_TO_POLKADOT_INDEX: u8 = 0; +pub const POLKADOT_TO_KUSAMA_INDEX: u8 = 0; /// The macro allows executing bridge-specific code without going fully generic. /// @@ -138,6 +144,50 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest; + $generic + } + FullBridge::KusamaToPolkadot => { + type Source = relay_kusama_client::Kusama; + #[allow(dead_code)] + type Target = relay_polkadot_client::Polkadot; + + // Derive-account + #[allow(unused_imports)] + use bp_polkadot::derive_account_from_kusama_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::kusama_messages_to_polkadot::run as relay_messages; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_polkadot::TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use relay_kusama_client::runtime::kusama_to_polkadot_account_ownership_digest as account_ownership_digest; + + $generic + } + FullBridge::PolkadotToKusama => { + type Source = relay_polkadot_client::Polkadot; + #[allow(dead_code)] + type Target = relay_kusama_client::Kusama; + + // Derive-account + #[allow(unused_imports)] + use bp_kusama::derive_account_from_polkadot_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::polkadot_messages_to_kusama::run as relay_messages; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_kusama::TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + // Send-message + #[allow(unused_imports)] + use relay_polkadot_client::runtime::polkadot_to_kusama_account_ownership_digest as account_ownership_digest; + $generic } } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 81663ed429a94..3e464e6f54556 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -46,6 +46,8 @@ pub enum InitBridgeName { WestendToMillau, RococoToWococo, WococoToRococo, + KusamaToPolkadot, + PolkadotToKusama, } macro_rules! select_bridge { @@ -127,6 +129,34 @@ macro_rules! select_bridge { ) } + $generic + } + InitBridgeName::KusamaToPolkadot => { + type Source = relay_kusama_client::Kusama; + type Target = relay_polkadot_client::Polkadot; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize(init_data), + ) + } + + $generic + } + InitBridgeName::PolkadotToKusama => { + type Source = relay_polkadot_client::Polkadot; + type Target = relay_kusama_client::Kusama; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize(init_data), + ) + } + $generic } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 0e527eb5b9152..48e2d85efbcc3 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -49,6 +49,8 @@ pub enum RelayHeadersBridge { WestendToMillau, RococoToWococo, WococoToRococo, + KusamaToPolkadot, + PolkadotToKusama, } macro_rules! select_bridge { @@ -87,6 +89,20 @@ macro_rules! select_bridge { type Target = relay_rococo_client::Rococo; type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + $generic + } + RelayHeadersBridge::KusamaToPolkadot => { + type Source = relay_kusama_client::Kusama; + type Target = relay_polkadot_client::Polkadot; + type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; + + $generic + } + RelayHeadersBridge::PolkadotToKusama => { + type Source = relay_polkadot_client::Polkadot; + type Target = relay_kusama_client::Kusama; + type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; + $generic } } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 956f46f18cb10..c6a0983141131 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -26,8 +26,10 @@ use futures::{FutureExt, TryFutureExt}; use structopt::StructOpt; use strum::VariantNames; -use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use codec::Encode; +use relay_substrate_client::{AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; +use sp_core::{Bytes, Pair}; use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane}; use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay; @@ -47,6 +49,7 @@ const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), RococoWococo(RococoWococoHeadersAndMessages), + KusamaPolkadot(KusamaPolkadotHeadersAndMessages), } /// Parameters that have the same names across all bridges. @@ -57,6 +60,9 @@ pub struct HeadersAndMessagesSharedParams { lane: Vec, #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] relayer_mode: RelayerMode, + /// Create relayers fund accounts on both chains, if it does not exists yet. + #[structopt(long)] + create_relayers_fund_accounts: bool, /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed. #[structopt(long)] only_mandatory_headers: bool, @@ -89,7 +95,6 @@ macro_rules! declare_bridge_options { right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], } - #[allow(unreachable_patterns)] impl From for [<$chain1 $chain2 HeadersAndMessages>] { fn from(relay_params: RelayHeadersAndMessages) -> [<$chain1 $chain2 HeadersAndMessages>] { match relay_params { @@ -117,6 +122,9 @@ macro_rules! select_bridge { type LeftToRightMessages = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; type RightToLeftMessages = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; + type LeftAccountIdConverter = bp_millau::AccountIdConverter; + type RightAccountIdConverter = bp_rialto::AccountIdConverter; + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; @@ -129,6 +137,22 @@ macro_rules! select_bridge { update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, }; + async fn left_create_account( + _left_client: Client, + _left_sign: ::AccountKeyPair, + _account_id: AccountIdOf, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Account creation is not supported by this bridge")) + } + + async fn right_create_account( + _right_client: Client, + _right_sign: ::AccountKeyPair, + _account_id: AccountIdOf, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Account creation is not supported by this bridge")) + } + $generic } RelayHeadersAndMessages::RococoWococo(_) => { @@ -143,6 +167,9 @@ macro_rules! select_bridge { type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo; type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo; + type LeftAccountIdConverter = bp_rococo::AccountIdConverter; + type RightAccountIdConverter = bp_wococo::AccountIdConverter; + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; @@ -169,6 +196,113 @@ macro_rules! select_bridge { Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) } + async fn left_create_account( + _left_client: Client, + _left_sign: ::AccountKeyPair, + _account_id: AccountIdOf, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Account creation is not supported by this bridge")) + } + + async fn right_create_account( + _right_client: Client, + _right_sign: ::AccountKeyPair, + _account_id: AccountIdOf, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Account creation is not supported by this bridge")) + } + + $generic + } + RelayHeadersAndMessages::KusamaPolkadot(_) => { + type Params = KusamaPolkadotHeadersAndMessages; + + type Left = relay_kusama_client::Kusama; + type Right = relay_polkadot_client::Polkadot; + + type LeftToRightFinality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; + type RightToLeftFinality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; + + type LeftToRightMessages = crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot; + type RightToLeftMessages = crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama; + + type LeftAccountIdConverter = bp_kusama::AccountIdConverter; + type RightAccountIdConverter = bp_polkadot::AccountIdConverter; + + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_kusama::BlockNumber = bp_kusama::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = bp_polkadot::SESSION_LENGTH; + + use crate::chains::kusama_messages_to_polkadot::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, + update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, + }; + use crate::chains::polkadot_messages_to_kusama::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, + }; + + async fn left_create_account( + left_client: Client, + left_sign: ::AccountKeyPair, + account_id: AccountIdOf, + ) -> anyhow::Result<()> { + let left_genesis_hash = *left_client.genesis_hash(); + left_client + .submit_signed_extrinsic(left_sign.public().into(), move |_, transaction_nonce| { + Bytes( + Left::sign_transaction( + left_genesis_hash, + &left_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + relay_kusama_client::runtime::Call::Balances( + relay_kusama_client::runtime::BalancesCall::transfer( + bp_kusama::AccountAddress::Id(account_id), + bp_kusama::EXISTENTIAL_DEPOSIT.into(), + ), + ), + transaction_nonce, + ), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|e| anyhow::format_err!("{}", e)) + } + + async fn right_create_account( + right_client: Client, + right_sign: ::AccountKeyPair, + account_id: AccountIdOf, + ) -> anyhow::Result<()> { + let right_genesis_hash = *right_client.genesis_hash(); + right_client + .submit_signed_extrinsic(right_sign.public().into(), move |_, transaction_nonce| { + Bytes( + Right::sign_transaction( + right_genesis_hash, + &right_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + relay_polkadot_client::runtime::Call::Balances( + relay_polkadot_client::runtime::BalancesCall::transfer( + bp_polkadot::AccountAddress::Id(account_id), + bp_polkadot::EXISTENTIAL_DEPOSIT.into(), + ), + ), + transaction_nonce, + ), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|e| anyhow::format_err!("{}", e)) + } + $generic } } @@ -180,9 +314,12 @@ declare_chain_options!(Millau, millau); declare_chain_options!(Rialto, rialto); declare_chain_options!(Rococo, rococo); declare_chain_options!(Wococo, wococo); +declare_chain_options!(Kusama, kusama); +declare_chain_options!(Polkadot, polkadot); // All supported bridges. declare_bridge_options!(Millau, Rialto); declare_bridge_options!(Rococo, Wococo); +declare_bridge_options!(Kusama, Polkadot); impl RelayHeadersAndMessages { /// Run the command. @@ -275,6 +412,26 @@ impl RelayHeadersAndMessages { ); } + if params.shared.create_relayers_fund_accounts { + let relayer_fund_acount_id = + pallet_bridge_messages::relayer_fund_account_id::, LeftAccountIdConverter>(); + let relayers_fund_account_balance = + left_client.free_native_balance(relayer_fund_acount_id.clone()).await; + if let Err(relay_substrate_client::Error::AccountDoesNotExist) = relayers_fund_account_balance { + log::info!(target: "bridge", "Going to create relayers fund account at {}.", Left::NAME); + left_create_account(left_client.clone(), left_sign.clone(), relayer_fund_acount_id).await?; + } + + let relayer_fund_acount_id = + pallet_bridge_messages::relayer_fund_account_id::, RightAccountIdConverter>(); + let relayers_fund_account_balance = + right_client.free_native_balance(relayer_fund_acount_id.clone()).await; + if let Err(relay_substrate_client::Error::AccountDoesNotExist) = relayers_fund_account_balance { + log::info!(target: "bridge", "Going to create relayers fund account at {}.", Right::NAME); + right_create_account(right_client.clone(), right_sign.clone(), relayer_fund_acount_id).await?; + } + } + let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), right_client.clone(), diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 1092f73d5b755..33bbbeeacd99a 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -6,9 +6,24 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +codec = { package = "parity-scale-codec", version = "2.2.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-runtime = { path = "../../primitives/runtime" } +bridge-runtime-common = { path = "../../bin/runtime-common" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 95a8596c97fbf..608befaa9a363 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,9 +16,16 @@ //! Types used to connect to the Kusama chain. -use relay_substrate_client::{Chain, ChainBase}; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; +pub mod runtime; + /// Kusama header id. pub type HeaderId = relay_utils::HeaderId; @@ -45,9 +52,68 @@ impl Chain for Kusama { const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_kusama::SignedBlock; - type Call = (); + type Call = crate::runtime::Call; type WeightToFee = bp_kusama::WeightToFee; } +impl ChainWithBalances for Kusama { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_kusama::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for Kusama { + type Chain = Kusama; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; + + fn sign_transaction( + genesis_hash: ::Hash, + signer: &Self::AccountKeyPair, + era: TransactionEraOf, + unsigned: UnsignedTransaction, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_kusama::SignedExtensions::new(bp_kusama::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_kusama::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == bp_kusama::AccountId::from(*signer.public().as_array_ref()).into()) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { + call: tx.function, + nonce: extra.nonce(), + tip: extra.tip(), + }) + } +} + /// Kusama header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; + +/// Kusama signing params. +pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs new file mode 100644 index 0000000000000..4b490b2799b7e --- /dev/null +++ b/relays/client-kusama/src/runtime.rs @@ -0,0 +1,151 @@ +// 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 . + +//! Types that are specific to the Kusama runtime. + +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; +use bp_runtime::Chain; +use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; +use sp_runtime::FixedU128; + +/// Unchecked Kusama extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Polkadot account ownership digest from Kusama. +/// +/// The byte vector returned by this function should be signed with a Polkadot account private key. +/// This way, the owner of `kusama_account_id` on Kusama proves that the Polkadot account private key +/// is also under his control. +pub fn kusama_to_polkadot_account_ownership_digest( + polkadot_call: &Call, + kusama_account_id: AccountId, + polkadot_spec_version: SpecVersion, +) -> Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_dispatch::account_ownership_digest( + polkadot_call, + kusama_account_id, + polkadot_spec_version, + bp_runtime::KUSAMA_CHAIN_ID, + bp_runtime::POLKADOT_CHAIN_ID, + ) +} + +/// Kusama Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Kusama chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Kusama +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/kusama/src/lib.rs) +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Balances pallet. + #[codec(index = 4)] + Balances(BalancesCall), + /// Polkadot bridge pallet. + #[codec(index = 110)] + BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), + /// Polkadot messages pallet. + #[codec(index = 111)] + BridgePolkadotMessages(BridgePolkadotMessagesCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BalancesCall { + #[codec(index = 0)] + transfer(AccountAddress, Compact), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgePolkadotGrandpaCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgePolkadotMessagesCall { + #[codec(index = 2)] + update_pallet_parameter(BridgePolkadotMessagesParameter), + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_kusama::AccountId, + bp_polkadot::AccountId, + bp_polkadot::AccountPublic, + Vec, + >, + bp_kusama::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_polkadot::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + UnrewardedRelayersState, + ), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum BridgePolkadotMessagesParameter { + #[codec(index = 0)] + PolkadotToKusamaConversionRate(FixedU128), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 261f0bee385e9..663969da66a4c 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -6,9 +6,24 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +codec = { package = "parity-scale-codec", version = "2.2.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies +bp-header-chain = { path = "../../primitives/header-chain" } +bp-kusama = { path = "../../primitives/chain-kusama" } +bp-message-dispatch = { path = "../../primitives/message-dispatch" } +bp-messages = { path = "../../primitives/messages" } bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-runtime = { path = "../../primitives/runtime" } +bridge-runtime-common = { path = "../../bin/runtime-common" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 5882d917bf2f5..3ba84e05bff71 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,9 +16,16 @@ //! Types used to connect to the Polkadot chain. -use relay_substrate_client::{Chain, ChainBase}; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; +pub mod runtime; + /// Polkadot header id. pub type HeaderId = relay_utils::HeaderId; @@ -45,9 +52,68 @@ impl Chain for Polkadot { const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_polkadot::SignedBlock; - type Call = (); + type Call = crate::runtime::Call; type WeightToFee = bp_polkadot::WeightToFee; } +impl ChainWithBalances for Polkadot { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + StorageKey(bp_polkadot::account_info_storage_key(account_id)) + } +} + +impl TransactionSignScheme for Polkadot { + type Chain = Polkadot; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = crate::runtime::UncheckedExtrinsic; + + fn sign_transaction( + genesis_hash: ::Hash, + signer: &Self::AccountKeyPair, + era: TransactionEraOf, + unsigned: UnsignedTransaction, + ) -> Self::SignedTransaction { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_polkadot::SignedExtensions::new(bp_polkadot::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), + ) + .expect("SignedExtension never fails."); + + let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); + let signer: sp_runtime::MultiSigner = signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + bp_polkadot::UncheckedExtrinsic::new_signed( + call, + sp_runtime::MultiAddress::Id(signer.into_account()), + signature.into(), + extra, + ) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == bp_polkadot::AccountId::from(*signer.public().as_array_ref()).into()) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction { + call: tx.function, + nonce: extra.nonce(), + tip: extra.tip(), + }) + } +} + /// Polkadot header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; + +/// Polkadot signing params. +pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs new file mode 100644 index 0000000000000..63d0987d32315 --- /dev/null +++ b/relays/client-polkadot/src/runtime.rs @@ -0,0 +1,151 @@ +// 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 . + +//! Types that are specific to the Polkadot runtime. + +use bp_messages::{LaneId, UnrewardedRelayersState}; +use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; +use bp_runtime::Chain; +use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; +use sp_runtime::FixedU128; + +/// Unchecked Polkadot extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Kusama account ownership digest from Polkadot. +/// +/// The byte vector returned by this function should be signed with a Kusama account private key. +/// This way, the owner of `kusam_account_id` on Polkadot proves that the Kusama account private key +/// is also under his control. +pub fn polkadot_to_kusama_account_ownership_digest( + kusama_call: &Call, + kusam_account_id: AccountId, + kusama_spec_version: SpecVersion, +) -> Vec +where + Call: codec::Encode, + AccountId: codec::Encode, + SpecVersion: codec::Encode, +{ + pallet_bridge_dispatch::account_ownership_digest( + kusama_call, + kusam_account_id, + kusama_spec_version, + bp_runtime::POLKADOT_CHAIN_ID, + bp_runtime::KUSAMA_CHAIN_ID, + ) +} + +/// Polkadot Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Polkadot chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Polkadot +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: [link](https://github.com/paritytech/kusama/blob/master/runtime/kusam/src/lib.rs) +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Balances pallet. + #[codec(index = 5)] + Balances(BalancesCall), + /// Kusama bridge pallet. + #[codec(index = 110)] + BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), + /// Kusama messages pallet. + #[codec(index = 111)] + BridgeKusamaMessages(BridgeKusamaMessagesCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BalancesCall { + #[codec(index = 0)] + transfer(AccountAddress, Compact), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeKusamaGrandpaCall { + #[codec(index = 0)] + submit_finality_proof( + ::Header, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[allow(non_camel_case_types)] +pub enum BridgeKusamaMessagesCall { + #[codec(index = 2)] + update_pallet_parameter(BridgeKusamaMessagesParameter), + #[codec(index = 3)] + send_message( + LaneId, + bp_message_dispatch::MessagePayload< + bp_polkadot::AccountId, + bp_kusama::AccountId, + bp_kusama::AccountPublic, + Vec, + >, + bp_polkadot::Balance, + ), + #[codec(index = 5)] + receive_messages_proof( + bp_kusama::AccountId, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, + u32, + Weight, + ), + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + UnrewardedRelayersState, + ), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +pub enum BridgeKusamaMessagesParameter { + #[codec(index = 0)] + KusamaToPolkadotConversionRate(FixedU128), +} + +impl sp_runtime::traits::Dispatchable for Call { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 1ce781be72ebc..38ec9eb1887c0 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -11,6 +11,7 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies + bridge-runtime-common = { path = "../../bin/runtime-common" } bp-header-chain = { path = "../../primitives/header-chain" } bp-message-dispatch = { path = "../../primitives/message-dispatch" } @@ -23,6 +24,7 @@ pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies + frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 8415657060d70..173e58d386fc3 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -38,7 +38,8 @@ pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthori pub use crate::error::{Error, Result}; pub use crate::sync_header::SyncHeader; pub use bp_runtime::{ - BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, IndexOf, TransactionEra, TransactionEraOf, + AccountIdOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, IndexOf, TransactionEra, + TransactionEraOf, }; /// Header id used by the chain. From 42fdddfccf1ca87049b9ba55f9f3f390802eac6b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 21 Sep 2021 17:39:05 +0300 Subject: [PATCH 0570/1210] Relay subcommand that performs token RLT <> MLAU token swap (#1141) * token swap relay * token swap subcommand fixes * fmt * removed debug traces * removed commented code --- bin/millau/node/src/chain_spec.rs | 1 + bin/rialto/node/src/chain_spec.rs | 1 + modules/messages/src/lib.rs | 23 +- modules/token-swap/src/lib.rs | 60 +- primitives/chain-millau/src/lib.rs | 2 + primitives/runtime/src/lib.rs | 29 +- primitives/token-swap/src/lib.rs | 14 + relays/bin-substrate/Cargo.toml | 5 + relays/bin-substrate/src/cli/mod.rs | 4 + relays/bin-substrate/src/cli/swap_tokens.rs | 640 ++++++++++++++++++ relays/client-substrate/Cargo.toml | 2 + relays/client-substrate/src/chain.rs | 9 +- relays/client-substrate/src/client.rs | 155 +++-- relays/client-substrate/src/lib.rs | 9 +- .../src/metrics/float_storage_value.rs | 2 +- relays/client-substrate/src/rpc.rs | 2 +- 16 files changed, 861 insertions(+), 97 deletions(-) create mode 100644 relays/bin-substrate/src/cli/swap_tokens.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 28c8be330412a..ca47b39018d6f 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -135,6 +135,7 @@ impl Alternative { get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("RialtoMessagesOwner"), + get_account_id_from_seed::("WithRialtoTokenSwap"), pallet_bridge_messages::relayer_fund_account_id::< bp_millau::AccountId, bp_millau::AccountIdConverter, diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 394432151478f..be631109faf9e 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -151,6 +151,7 @@ impl Alternative { get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("MillauMessagesOwner"), + get_account_id_from_seed::("WithMillauTokenSwap"), pallet_bridge_messages::relayer_fund_account_id::< bp_rialto::AccountId, bp_rialto::AccountIdConverter, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 208d1d048cf4d..8e6f0969b5485 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -777,12 +777,11 @@ pub mod pallet { /// messages and lanes states proofs. pub mod storage_keys { use super::*; - use frame_support::StorageHasher; use sp_core::storage::StorageKey; /// Storage key of the outbound message in the runtime storage. pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { - storage_map_final_key( + bp_runtime::storage_map_final_key_blake2_128concat( pallet_prefix, "OutboundMessages", &MessageKey { lane_id: *lane, nonce }.encode(), @@ -791,28 +790,12 @@ pub mod storage_keys { /// Storage key of the outbound message lane state in the runtime storage. pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { - storage_map_final_key(pallet_prefix, "OutboundLanes", lane) + bp_runtime::storage_map_final_key_blake2_128concat(pallet_prefix, "OutboundLanes", lane) } /// Storage key of the inbound message lane state in the runtime storage. pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { - storage_map_final_key(pallet_prefix, "InboundLanes", lane) - } - - /// This is a copypaste of the `frame_support::storage::generator::StorageMap::storage_map_final_key`. - fn storage_map_final_key(pallet_prefix: &str, map_name: &str, key: &[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 key_hashed = frame_support::Blake2_128Concat::hash(key); - - 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) + bp_runtime::storage_map_final_key_blake2_128concat(pallet_prefix, "InboundLanes", lane) } } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 3216c69029d3d..61e4f1219ab6b 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -56,12 +56,11 @@ use bp_messages::{ DeliveredMessages, LaneId, MessageNonce, }; use bp_runtime::{messages::DispatchFeePayment, ChainId}; -use bp_token_swap::{TokenSwap, TokenSwapType}; -use codec::{Decode, Encode}; +use bp_token_swap::{TokenSwap, TokenSwapState, TokenSwapType}; +use codec::Encode; use frame_support::{ fail, traits::{Currency, ExistenceRequirement}, - RuntimeDebug, }; use sp_core::H256; use sp_io::hashing::blake2_256; @@ -71,22 +70,11 @@ use sp_std::vec::Vec; #[cfg(test)] mod mock; -/// Pending token swap state. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] -pub enum TokenSwapState { - /// The swap has been started using the `start_claim` call, but we have no proof that it has - /// happened at the Bridged chain. - Started, - /// The swap has happened at the Bridged chain and may be claimed by the Bridged chain party using - /// the `claim_swap` call. - Confirmed, - /// The swap has failed at the Bridged chain and This chain party may cancel it using the - /// `cancel_swap` call. - Failed, -} - pub use pallet::*; +/// Name of the `PendingSwaps` storage map. +pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; + // comes from #[pallet::event] #[allow(clippy::unused_unit)] #[frame_support::pallet] @@ -324,6 +312,13 @@ pub mod pallet { return sp_runtime::TransactionOutcome::Rollback(Err(Error::::SwapAlreadyStarted.into())); } + log::trace!( + target: "runtime::bridge-token-swap", + "The swap {:?} (hash {:?}) has been started", + swap, + swap_hash, + ); + // remember that we're waiting for the transfer message delivery confirmation PendingMessages::::insert(transfer_message_nonce, swap_hash); @@ -475,14 +470,21 @@ pub mod pallet { reads += 1; if let Some(swap_hash) = PendingMessages::::take(message_nonce) { writes += 1; - PendingSwaps::::insert( + + let token_swap_state = if delivered_messages.message_dispatch_result(message_nonce) { + TokenSwapState::Confirmed + } else { + TokenSwapState::Failed + }; + + log::trace!( + target: "runtime::bridge-token-swap", + "The dispatch of swap {:?} has been completed with {:?} status", swap_hash, - if delivered_messages.message_dispatch_result(message_nonce) { - TokenSwapState::Confirmed - } else { - TokenSwapState::Failed - }, + token_swap_state, ); + + PendingSwaps::::insert(swap_hash, token_swap_state); } } @@ -534,6 +536,18 @@ pub mod pallet { )); } + log::trace!( + target: "runtime::bridge-token-swap", + "The swap {:?} (hash {:?}) has been completed with {} status", + swap, + swap_hash, + match event { + Event::SwapClaimed(_) => "claimed", + Event::SwapCancelled(_) => "cancelled", + _ => "", + }, + ); + // forget about swap PendingSwaps::::remove(swap_hash); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index b2bf5cf0b18ab..e43e4f4bf5bd9 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -258,6 +258,8 @@ pub fn max_extrinsic_size() -> u32 { /// Name of the With-Rialto messages pallet instance in the Millau runtime. pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; +/// Name of the With-Rialto token swap pallet instance in the Millau runtime. +pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a439dbf9ff7dc..8d4e658b1e863 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Encode; -use frame_support::RuntimeDebug; +use frame_support::{RuntimeDebug, StorageHasher}; use sp_core::{hash::H256, storage::StorageKey}; use sp_io::hashing::blake2_256; use sp_std::{convert::TryFrom, vec::Vec}; @@ -184,6 +184,33 @@ impl, BlockHash: Copy> TransactionEra StorageKey { + storage_map_final_key_identity(pallet_prefix, map_name, &frame_support::Blake2_128Concat::hash(key)) +} + +/// This is a copypaste 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. /// /// Copypaste from `frame_support::parameter_types` macro diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index afdaa2497e899..13d6a596cbf3f 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -20,6 +20,20 @@ use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_core::U256; +/// Pending token swap state. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub enum TokenSwapState { + /// The swap has been started using the `start_claim` call, but we have no proof that it has + /// happened at the Bridged chain. + Started, + /// The swap has happened at the Bridged chain and may be claimed by the Bridged chain party using + /// the `claim_swap` call. + Confirmed, + /// The swap has failed at the Bridged chain and This chain party may cancel it using the + /// `cancel_swap` call. + Failed, +} + /// Token swap type. /// /// Different swap types give a different guarantees regarding possible swap diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 3a7f63d8489d3..6153fee1e569c 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -15,6 +15,7 @@ log = "0.4.14" num-format = "0.4" num-traits = "0.2" paste = "1.0" +rand = "0.8" structopt = "0.3" strum = { version = "0.21.0", features = ["derive"] } @@ -28,6 +29,7 @@ bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } +bp-token-swap = { path = "../../primitives/token-swap" } bp-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } @@ -35,7 +37,9 @@ bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } +pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } +pallet-bridge-token-swap = { path = "../../modules/token-swap" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } @@ -51,6 +55,7 @@ substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 4831373eae19c..ac072de3056f2 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -36,6 +36,7 @@ mod relay_headers; mod relay_headers_and_messages; mod relay_messages; mod resubmit_transactions; +mod swap_tokens; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -89,6 +90,8 @@ pub enum Command { DeriveAccount(derive_account::DeriveAccount), /// Resubmit transactions with increased tip if they are stalled. ResubmitTransactions(resubmit_transactions::ResubmitTransactions), + /// Swap tokens using token-swap bridge. + SwapTokens(swap_tokens::SwapTokens), } impl Command { @@ -120,6 +123,7 @@ impl Command { Self::EstimateFee(arg) => arg.run().await?, Self::DeriveAccount(arg) => arg.run().await?, Self::ResubmitTransactions(arg) => arg.run().await?, + Self::SwapTokens(arg) => arg.run().await?, } Ok(()) } diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs new file mode 100644 index 0000000000000..a7c5e0aee5b32 --- /dev/null +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -0,0 +1,640 @@ +// 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 . + +//! Tokens swap using token-swap bridge pallet. + +use codec::Encode; +use num_traits::One; +use rand::random; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +use frame_support::dispatch::GetDispatchInfo; +use relay_substrate_client::{ + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithBalances, Client, + Error as SubstrateError, HashOf, SignatureOf, Subscription, TransactionSignScheme, TransactionStatusOf, + UnsignedTransaction, +}; +use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, H256, U256}; +use sp_runtime::traits::{Convert, Header as HeaderT}; + +use crate::cli::{ + Balance, CliChain, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, +}; + +/// Swap tokens. +#[derive(StructOpt)] +pub struct SwapTokens { + /// A bridge instance to use in token swap. + #[structopt(possible_values = SwapTokensBridge::VARIANTS, case_insensitive = true)] + bridge: SwapTokensBridge, + + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + + #[structopt(subcommand)] + swap_type: TokenSwapType, + /// Source chain balance that source signer wants to swap. + #[structopt(long)] + source_balance: Balance, + /// Target chain balance that target signer wants to swap. + #[structopt(long)] + target_balance: Balance, +} + +/// Token swap type. +#[derive(StructOpt, Debug, PartialEq, Eq, Clone)] +pub enum TokenSwapType { + /// The `target_sign` is temporary and only have funds for single swap. + NoLock, + /// This swap type prevents `source_signer` from restarting the swap after it has been completed. + LockUntilBlock { + /// Number of blocks before the swap expires. + #[structopt(long)] + blocks_before_expire: u32, + /// Unique swap nonce. + #[structopt(long)] + swap_nonce: Option, + }, +} + +/// Swap tokens bridge. +#[derive(Debug, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +pub enum SwapTokensBridge { + /// Use token-swap pallet deployed at Millau to swap tokens with Rialto. + MillauToRialto, +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + SwapTokensBridge::MillauToRialto => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; + + type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; + + use bp_millau::{ + derive_account_from_rialto_id as derive_source_account_from_target_account, + TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, + WITH_RIALTO_TOKEN_SWAP_PALLET_NAME as TOKEN_SWAP_PALLET_NAME, + }; + use bp_rialto::{ + derive_account_from_millau_id as derive_target_account_from_source_account, + TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, + }; + + const SOURCE_CHAIN_ID: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; + const TARGET_CHAIN_ID: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; + + const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; + const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; + + const SOURCE_TO_TARGET_LANE_ID: bp_messages::LaneId = *b"swap"; + const TARGET_TO_SOURCE_LANE_ID: bp_messages::LaneId = [0, 0, 0, 0]; + + $generic + } + } + }; +} + +impl SwapTokens { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + let source_client = self.source.to_client::().await?; + let source_sign = self.source_sign.to_keypair::()?; + let target_client = self.target.to_client::().await?; + let target_sign = self.target_sign.to_keypair::()?; + + // names of variables in this function are matching names used by the `pallet-bridge-token-swap` + + // prepare token swap intention + let token_swap = self + .prepare_token_swap::(&source_client, &source_sign, &target_sign) + .await?; + + // group all accounts that will be used later + let accounts = TokenSwapAccounts { + source_account_at_bridged_chain: derive_target_account_from_source_account( + bp_runtime::SourceAccount::Account(token_swap.source_account_at_this_chain.clone()), + ), + target_account_at_this_chain: derive_source_account_from_target_account( + bp_runtime::SourceAccount::Account(token_swap.target_account_at_bridged_chain.clone()), + ), + source_account_at_this_chain: token_swap.source_account_at_this_chain.clone(), + target_account_at_bridged_chain: token_swap.target_account_at_bridged_chain.clone(), + swap_account: FromSwapToThisAccountIdConverter::convert(token_swap.using_encoded(blake2_256).into()), + }; + + // account balances are used to demonstrate what's happening :) + let initial_balances = read_account_balances(&accounts, &source_client, &target_client).await?; + + // before calling something that may fail, log what we're trying to do + log::info!(target: "bridge", "Starting swap: {:?}", token_swap); + log::info!(target: "bridge", "Swap accounts: {:?}", accounts); + log::info!(target: "bridge", "Initial account balances: {:?}", initial_balances); + + // + // Step 1: swap is created + // + + // prepare `Currency::transfer` call that will happen at the target chain + let bridged_currency_transfer: CallOf = pallet_balances::Call::transfer( + accounts.source_account_at_bridged_chain.clone().into(), + token_swap.target_balance_at_bridged_chain, + ) + .into(); + let bridged_currency_transfer_weight = bridged_currency_transfer.get_dispatch_info().weight; + + // sign message + let bridged_chain_spec_version = TARGET_SPEC_VERSION; + let signature_payload = pallet_bridge_dispatch::account_ownership_digest( + &bridged_currency_transfer, + &accounts.swap_account, + &bridged_chain_spec_version, + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + ); + let bridged_currency_transfer_signature: SignatureOf = target_sign.sign(&signature_payload).into(); + + // prepare `create_swap` call + let target_public_at_bridged_chain: AccountPublicOf = target_sign.public().into(); + let swap_delivery_and_dispatch_fee: BalanceOf = + crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( + &source_client, + ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, + SOURCE_TO_TARGET_LANE_ID, + bp_message_dispatch::MessagePayload { + spec_version: TARGET_SPEC_VERSION, + weight: bridged_currency_transfer_weight, + origin: bp_message_dispatch::CallOrigin::TargetAccount( + accounts.swap_account.clone(), + target_public_at_bridged_chain.clone(), + bridged_currency_transfer_signature.clone(), + ), + dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtTargetChain, + call: bridged_currency_transfer.encode(), + }, + ) + .await?; + let create_swap_call: CallOf = pallet_bridge_token_swap::Call::create_swap( + token_swap.clone(), + target_public_at_bridged_chain, + swap_delivery_and_dispatch_fee, + bridged_chain_spec_version, + bridged_currency_transfer.encode(), + bridged_currency_transfer_weight, + bridged_currency_transfer_signature, + ) + .into(); + + // start tokens swap + let source_genesis_hash = *source_client.genesis_hash(); + let create_swap_signer = source_sign.clone(); + let swap_created_at = wait_until_transaction_is_finalized::( + source_client + .submit_and_watch_signed_extrinsic( + accounts.source_account_at_this_chain.clone(), + move |_, transaction_nonce| { + Bytes( + Source::sign_transaction( + source_genesis_hash, + &create_swap_signer, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(create_swap_call, transaction_nonce), + ) + .encode(), + ) + }, + ) + .await?, + ) + .await?; + + // read state of swap after it has been created + let token_swap_hash: H256 = token_swap.using_encoded(blake2_256).into(); + let token_swap_storage_key = bp_runtime::storage_map_final_key_identity( + TOKEN_SWAP_PALLET_NAME, + pallet_bridge_token_swap::PENDING_SWAPS_MAP_NAME, + token_swap_hash.as_ref(), + ); + match read_token_swap_state(&source_client, swap_created_at, &token_swap_storage_key).await? { + Some(bp_token_swap::TokenSwapState::Started) => { + log::info!(target: "bridge", "Swap has been successfully started"); + let intermediate_balances = + read_account_balances(&accounts, &source_client, &target_client).await?; + log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); + } + Some(token_swap_state) => { + return Err(anyhow::format_err!( + "Fresh token swap has unexpected state: {:?}", + token_swap_state, + )) + } + None => return Err(anyhow::format_err!("Failed to start token swap")), + }; + + // + // Step 2: message is being relayed to the target chain and dispathed there + // + + // wait until message is dispatched at the target chain and dispatch result delivered back to source chain + let token_swap_state = wait_until_token_swap_state_is_changed( + &source_client, + &token_swap_storage_key, + bp_token_swap::TokenSwapState::Started, + ) + .await?; + let is_transfer_succeeded = match token_swap_state { + Some(bp_token_swap::TokenSwapState::Started) => { + unreachable!("wait_until_token_swap_state_is_changed only returns if state is not Started; qed",) + } + None => return Err(anyhow::format_err!("Fresh token swap has disappeared unexpectedly")), + Some(bp_token_swap::TokenSwapState::Confirmed) => { + log::info!( + target: "bridge", + "Transfer has been successfully dispatched at the target chain. Swap can be claimed", + ); + true + } + Some(bp_token_swap::TokenSwapState::Failed) => { + log::info!( + target: "bridge", + "Transfer has been dispatched with an error at the target chain. Swap can be cancelled", + ); + false + } + }; + + // by this time: (1) token swap account has been created and (2) if transfer has been successfully + // dispatched, both target chain balances have changed + let intermediate_balances = read_account_balances(&accounts, &source_client, &target_client).await?; + log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); + + // transfer has been dispatched, but we may need to wait until block where swap can be claimed/cancelled + if let bp_token_swap::TokenSwapType::LockClaimUntilBlock(ref last_available_block_number, _) = + token_swap.swap_type + { + wait_until_swap_unlocked( + &source_client, + last_available_block_number + BlockNumberOf::::one(), + ) + .await?; + } + + // + // Step 3: we may now claim or cancel the swap + // + + if is_transfer_succeeded { + log::info!(target: "bridge", "Claiming the swap swap"); + + // prepare `claim_swap` message that will be sent over the bridge + let claim_swap_call: CallOf = pallet_bridge_token_swap::Call::claim_swap(token_swap).into(); + let claim_swap_message = bp_message_dispatch::MessagePayload { + spec_version: SOURCE_SPEC_VERSION, + weight: claim_swap_call.get_dispatch_info().weight, + origin: bp_message_dispatch::CallOrigin::SourceAccount( + accounts.target_account_at_bridged_chain.clone(), + ), + dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, + call: claim_swap_call.encode(), + }; + let claim_swap_delivery_and_dispatch_fee: BalanceOf = + crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( + &target_client, + ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, + TARGET_TO_SOURCE_LANE_ID, + claim_swap_message.clone(), + ) + .await?; + let send_message_call: CallOf = pallet_bridge_messages::Call::send_message( + TARGET_TO_SOURCE_LANE_ID, + claim_swap_message, + claim_swap_delivery_and_dispatch_fee, + ) + .into(); + + // send `claim_swap` message + let target_genesis_hash = *target_client.genesis_hash(); + let _ = wait_until_transaction_is_finalized::( + target_client + .submit_and_watch_signed_extrinsic( + accounts.target_account_at_bridged_chain.clone(), + move |_, transaction_nonce| { + Bytes( + Target::sign_transaction( + target_genesis_hash, + &target_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(send_message_call, transaction_nonce), + ) + .encode(), + ) + }, + ) + .await?, + ) + .await?; + + // wait until swap state is updated + let token_swap_state = wait_until_token_swap_state_is_changed( + &source_client, + &token_swap_storage_key, + bp_token_swap::TokenSwapState::Confirmed, + ) + .await?; + if token_swap_state != None { + return Err(anyhow::format_err!( + "Confirmed token swap state has been changed to {:?} unexpectedly" + )); + } + } else { + log::info!(target: "bridge", "Cancelling the swap"); + let cancel_swap_call: CallOf = + pallet_bridge_token_swap::Call::cancel_swap(token_swap.clone()).into(); + let _ = wait_until_transaction_is_finalized::( + source_client + .submit_and_watch_signed_extrinsic( + accounts.source_account_at_this_chain.clone(), + move |_, transaction_nonce| { + Bytes( + Source::sign_transaction( + source_genesis_hash, + &source_sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(cancel_swap_call, transaction_nonce), + ) + .encode(), + ) + }, + ) + .await?, + ) + .await?; + } + + // print final balances + let final_balances = read_account_balances(&accounts, &source_client, &target_client).await?; + log::info!(target: "bridge", "Final account balances: {:?}", final_balances); + + Ok(()) + }) + } + + /// Prepare token swap intention. + async fn prepare_token_swap( + &self, + source_client: &Client, + source_sign: &Source::KeyPair, + target_sign: &Target::KeyPair, + ) -> anyhow::Result< + bp_token_swap::TokenSwap< + BlockNumberOf, + BalanceOf, + AccountIdOf, + BalanceOf, + AccountIdOf, + >, + > + where + AccountIdOf: From<::Public>, + AccountIdOf: From<::Public>, + BalanceOf: From, + BalanceOf: From, + { + // accounts that are directly controlled by participants + let source_account_at_this_chain: AccountIdOf = source_sign.public().into(); + let target_account_at_bridged_chain: AccountIdOf = target_sign.public().into(); + + // balances that we're going to swap + let source_balance_at_this_chain: BalanceOf = self.source_balance.cast().into(); + let target_balance_at_bridged_chain: BalanceOf = self.target_balance.cast().into(); + + // prepare token swap intention + Ok(bp_token_swap::TokenSwap { + swap_type: self.prepare_token_swap_type(&source_client).await?, + source_balance_at_this_chain, + source_account_at_this_chain: source_account_at_this_chain.clone(), + target_balance_at_bridged_chain, + target_account_at_bridged_chain: target_account_at_bridged_chain.clone(), + }) + } + + /// Prepare token swap type. + async fn prepare_token_swap_type( + &self, + source_client: &Client, + ) -> anyhow::Result>> { + match self.swap_type { + TokenSwapType::NoLock => Ok(bp_token_swap::TokenSwapType::TemporaryTargetAccountAtBridgedChain), + TokenSwapType::LockUntilBlock { + blocks_before_expire, + ref swap_nonce, + } => { + let blocks_before_expire: BlockNumberOf = blocks_before_expire.into(); + let current_source_block_number = *source_client.best_header().await?.number(); + Ok(bp_token_swap::TokenSwapType::LockClaimUntilBlock( + current_source_block_number + blocks_before_expire, + swap_nonce.unwrap_or_else(|| { + U256::from(random::()) + .overflowing_mul(U256::from(random::())) + .0 + }), + )) + } + } + } +} + +/// Accounts that are participating in the swap. +#[derive(Debug)] +struct TokenSwapAccounts { + source_account_at_this_chain: ThisAccountId, + source_account_at_bridged_chain: BridgedAccountId, + target_account_at_bridged_chain: BridgedAccountId, + target_account_at_this_chain: ThisAccountId, + swap_account: ThisAccountId, +} + +/// Swap accounts balances. +#[derive(Debug)] +struct TokenSwapBalances { + source_account_at_this_chain_balance: Option, + source_account_at_bridged_chain_balance: Option, + target_account_at_bridged_chain_balance: Option, + target_account_at_this_chain_balance: Option, + swap_account_balance: Option, +} + +/// Read swap accounts balances. +async fn read_account_balances( + accounts: &TokenSwapAccounts, AccountIdOf>, + source_client: &Client, + target_client: &Client, +) -> anyhow::Result, BalanceOf>> { + Ok(TokenSwapBalances { + source_account_at_this_chain_balance: read_account_balance( + &source_client, + &accounts.source_account_at_this_chain, + ) + .await?, + source_account_at_bridged_chain_balance: read_account_balance( + &target_client, + &accounts.source_account_at_bridged_chain, + ) + .await?, + target_account_at_bridged_chain_balance: read_account_balance( + &target_client, + &accounts.target_account_at_bridged_chain, + ) + .await?, + target_account_at_this_chain_balance: read_account_balance( + &source_client, + &accounts.target_account_at_this_chain, + ) + .await?, + swap_account_balance: read_account_balance(&source_client, &accounts.swap_account).await?, + }) +} + +/// Read account balance. +async fn read_account_balance( + client: &Client, + account: &AccountIdOf, +) -> anyhow::Result>> { + match client.free_native_balance(account.clone()).await { + Ok(balance) => Ok(Some(balance)), + Err(SubstrateError::AccountDoesNotExist) => Ok(None), + Err(error) => Err(anyhow::format_err!( + "Failed to read balance of {} account {:?}: {:?}", + C::NAME, + account, + error, + )), + } +} + +/// Wait until transaction is included into finalized block. +/// +/// Returns the hash of the finalized block with transaction. +async fn wait_until_transaction_is_finalized( + subscription: Subscription>, +) -> anyhow::Result> { + loop { + let transaction_status = subscription.next().await?; + match transaction_status { + Some(TransactionStatusOf::::FinalityTimeout(_)) + | Some(TransactionStatusOf::::Usurped(_)) + | Some(TransactionStatusOf::::Dropped) + | Some(TransactionStatusOf::::Invalid) + | None => { + return Err(anyhow::format_err!( + "We've been waiting for finalization of {} transaction, but it now has the {:?} status", + C::NAME, + transaction_status, + )) + } + Some(TransactionStatusOf::::Finalized(block_hash)) => { + log::trace!( + target: "bridge", + "{} transaction has been finalized at block {}", + C::NAME, + block_hash, + ); + return Ok(block_hash); + } + _ => { + log::trace!( + target: "bridge", + "Received intermediate status of {} transaction: {:?}", + C::NAME, + transaction_status, + ); + } + } + } +} + +/// Waits until token swap state is changed from `Started` to something else. +async fn wait_until_token_swap_state_is_changed( + client: &Client, + swap_state_storage_key: &StorageKey, + previous_token_swap_state: bp_token_swap::TokenSwapState, +) -> anyhow::Result> { + log::trace!(target: "bridge", "Waiting for token swap state change"); + loop { + async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; + + let best_block = client.best_finalized_header_number().await?; + let best_block_hash = client.block_hash_by_number(best_block).await?; + log::trace!(target: "bridge", "Inspecting {} block {}/{}", C::NAME, best_block, best_block_hash); + + let token_swap_state = read_token_swap_state(client, best_block_hash, swap_state_storage_key).await?; + match token_swap_state { + Some(new_token_swap_state) if new_token_swap_state == previous_token_swap_state => {} + _ => { + log::trace!( + target: "bridge", + "Token swap state has been changed from {:?} to {:?}", + previous_token_swap_state, + token_swap_state, + ); + return Ok(token_swap_state); + } + } + } +} + +/// Waits until swap can be claimed or cancelled. +async fn wait_until_swap_unlocked( + client: &Client, + required_block_number: BlockNumberOf, +) -> anyhow::Result<()> { + log::trace!(target: "bridge", "Waiting for token swap unlock"); + loop { + async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; + + let best_block = client.best_finalized_header_number().await?; + let best_block_hash = client.block_hash_by_number(best_block).await?; + if best_block >= required_block_number { + return Ok(()); + } + + log::trace!(target: "bridge", "Skipping {} block {}/{}", C::NAME, best_block, best_block_hash); + } +} + +/// Read state of the active token swap. +async fn read_token_swap_state( + client: &Client, + at_block: C::Hash, + swap_state_storage_key: &StorageKey, +) -> anyhow::Result> { + Ok(client + .storage_value(swap_state_storage_key.clone(), Some(at_block)) + .await?) +} diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 78d7a6ddc620b..807080dcc8fce 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -10,6 +10,7 @@ async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.2.0" } jsonrpsee-proc-macros = "0.2" +jsonrpsee-types = "0.2" jsonrpsee-ws-client = "0.2" log = "0.4.11" num-traits = "0.2" @@ -37,6 +38,7 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 711cfd12f1ba8..60fe63230a8d7 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bp_runtime::{Chain as ChainBase, TransactionEraOf}; +use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; use frame_support::weights::WeightToFeePolynomial; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; @@ -25,6 +25,7 @@ use sp_runtime::{ traits::{Block as BlockT, Dispatchable, Member}, EncodedJustification, }; +use sp_transaction_pool::TransactionStatus; use std::{fmt::Debug, time::Duration}; /// Substrate-based chain from minimal relay-client point of view. @@ -50,8 +51,12 @@ pub trait Chain: ChainBase + Clone { type WeightToFee: WeightToFeePolynomial; } -/// Weight-to-Fee type used by the chain +/// Call type used by the chain. +pub type CallOf = ::Call; +/// Weight-to-Fee type used by the chain. pub type WeightToFeeOf = ::WeightToFee; +/// Transaction status of the chain. +pub type TransactionStatusOf = TransactionStatus, HashOf>; /// Substrate-based chain with `frame_system::Config::AccountData` set to /// the `pallet_balances::AccountData`. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index bd239a5a5f74a..31f4a19d8ffaf 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -16,7 +16,7 @@ //! Substrate node client. -use crate::chain::{Chain, ChainWithBalances}; +use crate::chain::{Chain, ChainWithBalances, TransactionStatusOf}; use crate::rpc::Substrate; use crate::{ConnectionParams, Error, HeaderIdOf, Result}; @@ -31,7 +31,7 @@ use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; -use sp_core::{storage::StorageKey, Bytes}; +use sp_core::{storage::StorageKey, Bytes, Hasher}; use sp_runtime::{ traits::Header as HeaderT, transaction_validity::{TransactionSource, TransactionValidity}, @@ -45,7 +45,7 @@ const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_valida const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// Opaque justifications subscription type. -pub struct JustificationsSubscription(Mutex>>); +pub struct Subscription(Mutex>>); /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; @@ -190,6 +190,14 @@ impl Client { .await } + /// Return number of the best finalized block. + pub async fn best_finalized_header_number(&self) -> Result { + Ok(*self + .header_by_hash(self.best_finalized_header_hash().await?) + .await? + .number()) + } + /// Returns the best Substrate header. pub async fn best_header(&self) -> Result where @@ -243,9 +251,13 @@ impl Client { } /// Read value from runtime storage. - pub async fn storage_value(&self, storage_key: StorageKey) -> Result> { + pub async fn storage_value( + &self, + storage_key: StorageKey, + block_hash: Option, + ) -> Result> { self.jsonrpsee_execute(move |client| async move { - Substrate::::state_get_storage(&*client, storage_key) + Substrate::::state_get_storage(&*client, storage_key, block_hash) .await? .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) .transpose() @@ -260,7 +272,7 @@ impl Client { { self.jsonrpsee_execute(move |client| async move { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = Substrate::::state_get_storage(&*client, storage_key) + let encoded_account_data = Substrate::::state_get_storage(&*client, storage_key, None) .await? .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = @@ -318,6 +330,44 @@ impl Client { .await } + /// Does exactly the same as `submit_signed_extrinsic`, but keeps watching for extrinsic status + /// after submission. + pub async fn submit_and_watch_signed_extrinsic( + &self, + extrinsic_signer: C::AccountId, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + ) -> Result>> { + let _guard = self.submit_signed_extrinsic_lock.lock().await; + let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let best_header = self.best_header().await?; + let best_header_id = HeaderId(*best_header.number(), best_header.hash()); + let subscription = self + .jsonrpsee_execute(move |client| async move { + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); + let tx_hash = C::Hasher::hash(&extrinsic.0); + let subscription = client + .subscribe( + "author_submitAndWatchExtrinsic", + JsonRpcParams::Array(vec![ + jsonrpsee_types::to_json_value(extrinsic).map_err(|e| Error::RpcError(e.into()))? + ]), + "author_unwatchExtrinsic", + ) + .await?; + log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); + Ok(subscription) + }) + .await?; + let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); + self.tokio.spawn(Subscription::background_worker( + C::NAME.into(), + "extrinsic".into(), + subscription, + sender, + )); + Ok(Subscription(Mutex::new(receiver))) + } + /// Returns pending extrinsics from transaction pool. pub async fn pending_extrinsics(&self) -> Result> { self.jsonrpsee_execute( @@ -405,8 +455,8 @@ impl Client { } /// Return new justifications stream. - pub async fn subscribe_justifications(&self) -> Result { - let mut subscription = self + pub async fn subscribe_justifications(&self) -> Result> { + let subscription = self .jsonrpsee_execute(move |client| async move { Ok(client .subscribe( @@ -417,38 +467,14 @@ impl Client { .await?) }) .await?; - let (mut sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); - self.tokio.spawn(async move { - loop { - match subscription.next().await { - Ok(Some(justification)) => { - if sender.send(Some(justification)).await.is_err() { - break; - } - } - Ok(None) => { - log::trace!( - target: "bridge", - "{} justifications subscription stream has returned None. Stream needs to be restarted.", - C::NAME, - ); - let _ = sender.send(None).await; - break; - } - Err(e) => { - log::trace!( - target: "bridge", - "{} justifications subscription stream has returned '{:?}'. Stream needs to be restarted.", - C::NAME, - e, - ); - let _ = sender.send(None).await; - break; - } - } - } - }); - Ok(JustificationsSubscription(Mutex::new(receiver))) + let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); + self.tokio.spawn(Subscription::background_worker( + C::NAME.into(), + "justification".into(), + subscription, + sender, + )); + Ok(Subscription(Mutex::new(receiver))) } /// Execute jsonrpsee future in tokio context. @@ -465,11 +491,50 @@ impl Client { } } -impl JustificationsSubscription { - /// Return next justification from the subscription. - pub async fn next(&self) -> Result> { +impl Subscription { + /// Return next item from the subscription. + pub async fn next(&self) -> Result> { let mut receiver = self.0.lock().await; - let justification = receiver.next().await; - Ok(justification.unwrap_or(None)) + let item = receiver.next().await; + Ok(item.unwrap_or(None)) + } + + /// Background worker that is executed in tokio context as `jsonrpsee` requires. + async fn background_worker( + chain_name: String, + item_type: String, + mut subscription: jsonrpsee_types::Subscription, + mut sender: futures::channel::mpsc::Sender>, + ) { + loop { + match subscription.next().await { + Ok(Some(item)) => { + if sender.send(Some(item)).await.is_err() { + break; + } + } + Ok(None) => { + log::trace!( + target: "bridge", + "{} {} subscription stream has returned None. Stream needs to be restarted.", + chain_name, + item_type, + ); + let _ = sender.send(None).await; + break; + } + Err(e) => { + log::trace!( + target: "bridge", + "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", + chain_name, + item_type, + e, + ); + let _ = sender.send(None).await; + break; + } + } + } } } diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 173e58d386fc3..d801569df32fd 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -32,14 +32,15 @@ pub mod metrics; use std::time::Duration; pub use crate::chain::{ - BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme, UnsignedTransaction, WeightToFeeOf, + BlockWithJustification, CallOf, Chain, ChainWithBalances, TransactionSignScheme, TransactionStatusOf, + UnsignedTransaction, WeightToFeeOf, }; -pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet}; +pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}; pub use crate::error::{Error, Result}; pub use crate::sync_header::SyncHeader; pub use bp_runtime::{ - AccountIdOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, IndexOf, TransactionEra, - TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, IndexOf, SignatureOf, + TransactionEra, TransactionEraOf, }; /// Header id used by the chain. diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index e598885227892..1b9a3f824edc9 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -79,7 +79,7 @@ where async fn update(&self) { let value = self .client - .storage_value::(self.storage_key.clone()) + .storage_value::(self.storage_key.clone(), None) .await .map(|maybe_storage_value| { maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 61d2562672d29..efd45ebe43f36 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -48,7 +48,7 @@ jsonrpsee_proc_macros::rpc_client_api! { #[rpc(method = "state_call", positional_params)] fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; #[rpc(method = "state_getStorage", positional_params)] - fn state_get_storage(key: StorageKey) -> Option; + fn state_get_storage(key: StorageKey, at_block: Option) -> Option; #[rpc(method = "state_getReadProof", positional_params)] fn state_prove_storage(keys: Vec, hash: Option) -> ReadProof; #[rpc(method = "state_getRuntimeVersion", positional_params)] From d57d6192b6388c5ececc348cd1eccf6c42f115ce Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Sep 2021 10:17:25 +0300 Subject: [PATCH 0571/1210] Fix spelling (#1150) * fix spelling * Revert "fix spelling" This reverts commit 972bdac6c0c854f9c31e00aca005f228bb4ccbb1. * Revert "Revert "fix spelling"" This reverts commit 44ad4f06a322aafefdae34b59b94ef0729d0b6bb. --- modules/token-swap/src/lib.rs | 14 +++++++------- relays/bin-substrate/src/cli/swap_tokens.rs | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 61e4f1219ab6b..4c56ec5aa969d 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -393,7 +393,7 @@ pub mod pallet { None => fail!(Error::::SwapIsInactive), } - complete_claim::(swap, swap_hash, origin_account, Event::SwapCancelled(swap_hash)) + complete_claim::(swap, swap_hash, origin_account, Event::SwapCanceled(swap_hash)) } } @@ -406,8 +406,8 @@ pub mod pallet { SwapStarted(H256, MessageNonce), /// Token swap has been claimed. SwapClaimed(H256), - /// Token swap has been cancelled. - SwapCancelled(H256), + /// Token swap has been canceled. + SwapCanceled(H256), } #[pallet::error] @@ -440,7 +440,7 @@ pub mod pallet { SwapPeriodIsFinished, /// Someone is trying to cancel swap that has been confirmed. SwapIsConfirmed, - /// Someone is trying to claim/cancel swap that is either not started or already claimed/cancelled. + /// Someone is trying to claim/cancel swap that is either not started or already claimed/canceled. SwapIsInactive, /// The swap claimant is invalid. InvalidClaimant, @@ -543,7 +543,7 @@ pub mod pallet { swap_hash, match event { Event::SwapClaimed(_) => "claimed", - Event::SwapCancelled(_) => "cancelled", + Event::SwapCanceled(_) => "canceled", _ => "", }, ); @@ -1023,8 +1023,8 @@ mod tests { assert!( frame_system::Pallet::::events() .iter() - .any(|e| e.event == crate::mock::Event::TokenSwap(crate::Event::SwapCancelled(swap_hash,))), - "Missing SwapCancelled event: {:?}", + .any(|e| e.event == crate::mock::Event::TokenSwap(crate::Event::SwapCanceled(swap_hash,))), + "Missing SwapCanceled event: {:?}", frame_system::Pallet::::events(), ); }); diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index a7c5e0aee5b32..b9c44a4acc85e 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -283,7 +283,7 @@ impl SwapTokens { Some(bp_token_swap::TokenSwapState::Failed) => { log::info!( target: "bridge", - "Transfer has been dispatched with an error at the target chain. Swap can be cancelled", + "Transfer has been dispatched with an error at the target chain. Swap can be canceled", ); false } @@ -294,7 +294,7 @@ impl SwapTokens { let intermediate_balances = read_account_balances(&accounts, &source_client, &target_client).await?; log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); - // transfer has been dispatched, but we may need to wait until block where swap can be claimed/cancelled + // transfer has been dispatched, but we may need to wait until block where swap can be claimed/canceled if let bp_token_swap::TokenSwapType::LockClaimUntilBlock(ref last_available_block_number, _) = token_swap.swap_type { @@ -609,7 +609,7 @@ async fn wait_until_token_swap_state_is_changed( } } -/// Waits until swap can be claimed or cancelled. +/// Waits until swap can be claimed or canceled. async fn wait_until_swap_unlocked( client: &Client, required_block_number: BlockNumberOf, From 81a8da8dc4be5ea325ac02ed2f1298feb1d4ff4d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Sep 2021 13:20:10 +0300 Subject: [PATCH 0572/1210] Box large arguments of GRANDPA pallet (#1154) * box large arguments * benchmarks * fix --- bin/millau/runtime/src/lib.rs | 8 +++++ bin/rialto/runtime/src/lib.rs | 8 +++++ modules/grandpa/src/benchmarking.rs | 4 +-- modules/grandpa/src/lib.rs | 34 +++++++++++-------- primitives/header-chain/src/lib.rs | 3 +- .../src/chains/kusama_headers_to_polkadot.rs | 5 ++- .../src/chains/millau_headers_to_rialto.rs | 3 +- relays/bin-substrate/src/chains/mod.rs | 6 ++-- .../src/chains/polkadot_headers_to_kusama.rs | 5 ++- .../src/chains/rialto_headers_to_millau.rs | 2 +- .../src/chains/rococo_headers_to_wococo.rs | 5 ++- .../src/chains/westend_headers_to_millau.rs | 2 +- .../src/chains/wococo_headers_to_rococo.rs | 5 ++- relays/client-kusama/src/runtime.rs | 2 +- relays/client-polkadot/src/runtime.rs | 2 +- relays/client-rococo/src/runtime.rs | 2 +- relays/client-wococo/src/runtime.rs | 2 +- .../src/headers_initialize.rs | 2 +- 18 files changed, 67 insertions(+), 33 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 69e993b7bb78d..e395c378125af 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -750,4 +750,12 @@ mod tests { DbWeight::get(), ); } + + #[test] + fn call_size() { + // pallets that are (to be) used by polkadot runtime + const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests + assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); + assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); + } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 52206a8cf1693..bdbea8438b11b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1377,4 +1377,12 @@ mod tests { additional_amount }); } + + #[test] + fn call_size() { + // pallets that are (to be) used by polkadot runtime + const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests + assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); + assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); + } } diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index d2e73c529d0aa..1714024928dc5 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -80,7 +80,7 @@ fn prepare_benchmark_data, I: 'static>( .collect::>(); let init_data = InitializationData { - header: bp_test_utils::test_header(Zero::zero()), + header: Box::new(bp_test_utils::test_header(Zero::zero())), authority_list, set_id: TEST_GRANDPA_SET_ID, is_halted: false, @@ -109,7 +109,7 @@ benchmarks_instance_pallet! { let v in 1..MAX_VOTE_ANCESTRIES; let caller: T::AccountId = whitelisted_caller(); let (header, justification) = prepare_benchmark_data::(p, v); - }: submit_finality_proof(RawOrigin::Signed(caller), header, justification) + }: submit_finality_proof(RawOrigin::Signed(caller), Box::new(header), justification) verify { let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let expected_hash = header.hash(); diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 49a775077c4c3..f1599a5ebfbaf 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -46,7 +46,7 @@ use frame_support::{ensure, fail}; use frame_system::{ensure_signed, RawOrigin}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; -use sp_std::convert::TryInto; +use sp_std::{boxed::Box, convert::TryInto}; #[cfg(test)] mod mock; @@ -130,7 +130,7 @@ pub mod pallet { ))] pub fn submit_finality_proof( origin: OriginFor, - finality_target: BridgedHeader, + finality_target: Box>, justification: GrandpaJustification>, ) -> DispatchResultWithPostInfo { ensure_operational::()?; @@ -166,7 +166,7 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; >::mutate(|count| *count += 1); - insert_header::(finality_target, hash); + insert_header::(*finality_target, hash); log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); // mandatory header is a header that changes authorities set. The pallet can't go further @@ -471,7 +471,7 @@ pub mod pallet { let initial_hash = header.hash(); >::put(initial_hash); >::put(0); - insert_header::(header, initial_hash); + insert_header::(*header, initial_hash); let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); >::put(authority_set); @@ -598,7 +598,7 @@ pub(crate) fn find_forced_change( #[cfg(feature = "runtime-benchmarks")] pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader) { initialize_bridge::(InitializationData { - header, + header: Box::new(header), authority_list: sp_std::vec::Vec::new(), // we don't verify any proofs in external benchmarks set_id: 0, is_halted: false, @@ -628,7 +628,7 @@ mod tests { let genesis = test_header(0); let init_data = InitializationData { - header: genesis, + header: Box::new(genesis), authority_list: authority_list(), set_id: 1, is_halted: false, @@ -641,7 +641,7 @@ mod tests { let header = test_header(header.into()); let justification = make_default_justification(&header); - Pallet::::submit_finality_proof(Origin::signed(1), header, justification) + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification) } fn next_block() { @@ -828,7 +828,7 @@ mod tests { let justification = make_justification_for_header(params); assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), header, justification,), + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification,), >::InvalidJustification ); }) @@ -844,7 +844,7 @@ mod tests { justification.round = 42; assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), header, justification,), + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification,), >::InvalidJustification ); }) @@ -857,7 +857,7 @@ mod tests { let invalid_authority_list = vec![(ALICE.into(), u64::MAX), (BOB.into(), u64::MAX)]; let init_data = InitializationData { - header: genesis, + header: Box::new(genesis), authority_list: invalid_authority_list, set_id: 1, is_halted: false, @@ -869,7 +869,7 @@ mod tests { let justification = make_default_justification(&header); assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), header, justification,), + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification,), >::InvalidAuthoritySet ); }) @@ -904,7 +904,11 @@ mod tests { // Let's import our test header assert_ok!( - Pallet::::submit_finality_proof(Origin::signed(1), header.clone(), justification), + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header.clone()), + justification + ), PostDispatchInfo { actual_weight: None, pays_fee: frame_support::weights::Pays::No, @@ -938,7 +942,7 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), header, justification), + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification), >::UnsupportedScheduledChange ); }) @@ -959,7 +963,7 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), header, justification), + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification), >::UnsupportedScheduledChange ); }) @@ -1017,7 +1021,7 @@ mod tests { let mut invalid_justification = make_default_justification(&header); invalid_justification.round = 42; - Pallet::::submit_finality_proof(Origin::signed(1), header, invalid_justification) + Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), invalid_justification) }; initialize_substrate_bridge(); diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index adac6eb268802..f1eaa28d071f0 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -29,6 +29,7 @@ use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::RuntimeDebug; use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT}; +use sp_std::boxed::Box; pub mod justification; @@ -62,7 +63,7 @@ impl AuthoritySet { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct InitializationData { /// The header from which we should start syncing. - pub header: H, + pub header: Box, /// The initial authorities of the pallet. pub authority_list: AuthorityList, /// The ID of the initial authority set. diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index 4e7703529e32d..b3b7d956bcc51 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -88,7 +88,10 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { proof: GrandpaJustification, ) -> Bytes { let call = relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof(header.into_inner(), proof), + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof( + Box::new(header.into_inner()), + proof, + ), ); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); let transaction = Polkadot::sign_transaction( diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index fa51200b6f879..f0ea225485bd4 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -59,7 +59,8 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { header: MillauSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(header.into_inner(), proof).into(); + let call = + rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(Box::new(header.into_inner()), proof).into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); let transaction = Rialto::sign_transaction( diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 4c02e9b1c98b2..bdc4f2628ee56 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -278,11 +278,11 @@ mod rococo_tests { }; let actual = relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( - header.clone(), + Box::new(header.clone()), justification.clone(), ); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( - header, + Box::new(header), justification, ); @@ -327,7 +327,7 @@ mod westend_tests { let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof(header.clone(), justification.clone()); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( - header, + Box::new(header), justification, ); diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index aee66b8a3f270..c225b77d546aa 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -88,7 +88,10 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { proof: GrandpaJustification, ) -> Bytes { let call = relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof(header.into_inner(), proof), + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof( + Box::new(header.into_inner()), + proof, + ), ); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); let transaction = Kusama::sign_transaction( diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 4f649702b7a3c..df0f17d94431a 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -63,7 +63,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { let call = millau_runtime::BridgeGrandpaRialtoCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, - >::submit_finality_proof(header.into_inner(), proof) + >::submit_finality_proof(Box::new(header.into_inner()), proof) .into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 5d8cf255398c5..269dead8dc231 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -83,7 +83,10 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { proof: GrandpaJustification, ) -> Bytes { let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( - relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof(header.into_inner(), proof), + relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof( + Box::new(header.into_inner()), + proof, + ), ); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); let transaction = Wococo::sign_transaction( diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 8501ff41868a0..4a5e48b51eeab 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -71,7 +71,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { let call = millau_runtime::BridgeGrandpaWestendCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, - >::submit_finality_proof(header.into_inner(), proof) + >::submit_finality_proof(Box::new(header.into_inner()), proof) .into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index b06921bfd9cec..74152cdff6d41 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -88,7 +88,10 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { proof: GrandpaJustification, ) -> Bytes { let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( - relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof(header.into_inner(), proof), + relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( + Box::new(header.into_inner()), + proof, + ), ); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); let transaction = Rococo::sign_transaction( diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs index 4b490b2799b7e..f2145f5b02ff1 100644 --- a/relays/client-kusama/src/runtime.rs +++ b/relays/client-kusama/src/runtime.rs @@ -96,7 +96,7 @@ pub enum BalancesCall { pub enum BridgePolkadotGrandpaCall { #[codec(index = 0)] submit_finality_proof( - ::Header, + Box<::Header>, bp_header_chain::justification::GrandpaJustification<::Header>, ), #[codec(index = 1)] diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs index 63d0987d32315..1c5d42a00c222 100644 --- a/relays/client-polkadot/src/runtime.rs +++ b/relays/client-polkadot/src/runtime.rs @@ -96,7 +96,7 @@ pub enum BalancesCall { pub enum BridgeKusamaGrandpaCall { #[codec(index = 0)] submit_finality_proof( - ::Header, + Box<::Header>, bp_header_chain::justification::GrandpaJustification<::Header>, ), #[codec(index = 1)] diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index d01f8a5dfd0f6..b68aea985e772 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -85,7 +85,7 @@ pub enum SystemCall { pub enum BridgeGrandpaWococoCall { #[codec(index = 0)] submit_finality_proof( - ::Header, + Box<::Header>, bp_header_chain::justification::GrandpaJustification<::Header>, ), #[codec(index = 1)] diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index 18fde4629a933..daf20156d69e8 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -85,7 +85,7 @@ pub enum SystemCall { pub enum BridgeGrandpaRococoCall { #[codec(index = 0)] submit_finality_proof( - ::Header, + Box<::Header>, bp_header_chain::justification::GrandpaJustification<::Header>, ), #[codec(index = 1)] diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index 4a7a0798bbf62..4a3a16bbe1775 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -213,7 +213,7 @@ async fn prepare_initialization_data( } Ok(InitializationData { - header: initial_header, + header: Box::new(initial_header), authority_list: initial_authorities_set, set_id: if schedules_change { initial_authorities_set_id + 1 From 736fb6184f75097659e378d32d0b64df2be079f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 22 Sep 2021 12:20:22 +0200 Subject: [PATCH 0573/1210] Rename MessageId -> BridgeMessageId (#1152) --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- bin/runtime-common/src/messages.rs | 2 +- modules/dispatch/src/lib.rs | 38 +++++++++++++------------- primitives/message-dispatch/src/lib.rs | 4 +-- primitives/messages/src/lib.rs | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index e395c378125af..3aa42ef8bd2e4 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -211,7 +211,7 @@ impl pallet_aura::Config for Runtime { } impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; - type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); + type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; type CallFilter = (); type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index bdbea8438b11b..8e7f3f2e421f9 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -291,7 +291,7 @@ impl pallet_bridge_currency_exchange::Config for Runtime impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; - type MessageId = (bp_messages::LaneId, bp_messages::MessageNonce); + type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; type CallFilter = (); type EncodedCall = crate::millau_messages::FromMillauEncodedCall; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index f85cc47ecef08..3286d364c7e56 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -495,7 +495,7 @@ pub mod target { where BalanceOf>: Saturating + FixedPointOperand, ThisDispatchInstance: 'static, - ThisRuntime: pallet_bridge_dispatch::Config + ThisRuntime: pallet_bridge_dispatch::Config + pallet_transaction_payment::Config, ::OnChargeTransaction: pallet_transaction_payment::OnChargeTransaction>>, diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index c68f064e9d12e..b334d862d8577 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -58,7 +58,7 @@ pub mod pallet { /// Id of the message. Whenever message is passed to the dispatch module, it emits /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if /// it comes from the messages module. - type MessageId: Parameter; + type BridgeMessageId: Parameter; /// Type of account ID on source chain. type SourceChainAccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; /// Type of account public key on target chain. @@ -91,7 +91,7 @@ pub mod pallet { type AccountIdConverter: sp_runtime::traits::Convert; } - type MessageIdOf = >::MessageId; + type BridgeMessageIdOf = >::BridgeMessageId; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -105,37 +105,37 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(::AccountId = "AccountId", MessageIdOf = "MessageId")] + #[pallet::metadata(::AccountId = "AccountId", BridgeMessageIdOf = "BridgeMessageId")] pub enum Event, I: 'static = ()> { /// Message has been rejected before reaching dispatch. - MessageRejected(ChainId, MessageIdOf), + MessageRejected(ChainId, BridgeMessageIdOf), /// Message has been rejected by dispatcher because of spec version mismatch. /// Last two arguments are: expected and passed spec version. - MessageVersionSpecMismatch(ChainId, MessageIdOf, SpecVersion, SpecVersion), + MessageVersionSpecMismatch(ChainId, BridgeMessageIdOf, SpecVersion, SpecVersion), /// Message has been rejected by dispatcher because of weight mismatch. /// Last two arguments are: expected and passed call weight. - MessageWeightMismatch(ChainId, MessageIdOf, Weight, Weight), + MessageWeightMismatch(ChainId, BridgeMessageIdOf, Weight, Weight), /// Message signature mismatch. - MessageSignatureMismatch(ChainId, MessageIdOf), + MessageSignatureMismatch(ChainId, BridgeMessageIdOf), /// We have failed to decode Call from the message. - MessageCallDecodeFailed(ChainId, MessageIdOf), + MessageCallDecodeFailed(ChainId, BridgeMessageIdOf), /// The call from the message has been rejected by the call filter. - MessageCallRejected(ChainId, MessageIdOf), + MessageCallRejected(ChainId, BridgeMessageIdOf), /// The origin account has failed to pay fee for dispatching the message. MessageDispatchPaymentFailed( ChainId, - MessageIdOf, + BridgeMessageIdOf, ::AccountId, Weight, ), /// Message has been dispatched with given result. - MessageDispatched(ChainId, MessageIdOf, DispatchResult), + MessageDispatched(ChainId, BridgeMessageIdOf, DispatchResult), /// Phantom member, never used. Needed to handle multiple pallet instances. _Dummy(PhantomData), } } -impl, I: 'static> MessageDispatch for Pallet { +impl, I: 'static> MessageDispatch for Pallet { type Message = MessagePayload; @@ -146,7 +146,7 @@ impl, I: 'static> MessageDispatch for P fn dispatch Result<(), ()>>( source_chain: ChainId, target_chain: ChainId, - id: T::MessageId, + id: T::BridgeMessageId, message: Result, pay_dispatch_fee: P, ) -> MessageDispatchResult { @@ -416,7 +416,7 @@ mod tests { }; type AccountId = u64; - type MessageId = [u8; 4]; + type BridgeMessageId = [u8; 4]; const SOURCE_CHAIN_ID: ChainId = *b"srce"; const TARGET_CHAIN_ID: ChainId = *b"trgt"; @@ -502,7 +502,7 @@ mod tests { impl Config for TestRuntime { type Event = Event; - type MessageId = MessageId; + type BridgeMessageId = BridgeMessageId; type SourceChainAccountId = AccountId; type TargetChainAccountPublic = TestAccountPublic; type TargetChainSignature = TestSignature; @@ -542,7 +542,7 @@ mod tests { fn prepare_message( origin: CallOrigin, call: Call, - ) -> as MessageDispatch::MessageId>>::Message { + ) -> as MessageDispatch::BridgeMessageId>>::Message { MessagePayload { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, @@ -554,20 +554,20 @@ mod tests { fn prepare_root_message( call: Call, - ) -> as MessageDispatch::MessageId>>::Message { + ) -> as MessageDispatch::BridgeMessageId>>::Message { prepare_message(CallOrigin::SourceRoot, call) } fn prepare_target_message( call: Call, - ) -> as MessageDispatch::MessageId>>::Message { + ) -> as MessageDispatch::BridgeMessageId>>::Message { let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); prepare_message(origin, call) } fn prepare_source_message( call: Call, - ) -> as MessageDispatch::MessageId>>::Message { + ) -> as MessageDispatch::BridgeMessageId>>::Message { let origin = CallOrigin::SourceAccount(1); prepare_message(origin, call) } diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 65f9fc15dc233..794091c789194 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -34,7 +34,7 @@ pub type Weight = u64; pub type SpecVersion = u32; /// A generic trait to dispatch arbitrary messages delivered over the bridge. -pub trait MessageDispatch { +pub trait MessageDispatch { /// A type of the message to be dispatched. type Message: codec::Decode; @@ -60,7 +60,7 @@ pub trait MessageDispatch { fn dispatch Result<(), ()>>( source_chain: ChainId, target_chain: ChainId, - id: MessageId, + id: BridgeMessageId, message: Result, pay_dispatch_fee: P, ) -> MessageDispatchResult; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 9e1de98a9f6f9..f639cea933a0b 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -75,7 +75,7 @@ pub type LaneId = [u8; 4]; pub type MessageNonce = u64; /// Message id as a tuple. -pub type MessageId = (LaneId, MessageNonce); +pub type BridgeMessageId = (LaneId, MessageNonce); /// Opaque message payload. We only decode this payload when it is dispatched. pub type MessagePayload = Vec; From b328c1bfd44d2faa511493967fa14204c251fcc1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Sep 2021 00:13:12 +0300 Subject: [PATCH 0574/1210] Add rialto-parachain runtime and node (#1142) * Substrate: 63b32fbaa2764c0a8ee76b70cdfa0fcb59b7181f Polkadot: 7229ab87acf5bc5d4d10655ad1a9819a1e317442 Cumulus: d5284b0e78be3a18a3371103dd00449aceb082df * rialto parachain runtime * fixed tests * add node + bump refs (not compiling yet): Substrate: 630422d6108cbaaca893ab213dde69f3bdaa1f6b Polkadot: 7229ab87acf5bc5d4d10655ad1a9819a1e317442 Cumulus: 5af2990cfd3711f86c7cb8606b22364208a5c32d GrandpaBridgeGadget: c152c45ac331eb8ab40d956ab1d008d181810ef4 * fix compilation (collator is not working) * more fixes * fmt * spellcheck * fix warnings * fix compilation * fmt * trigger CI * trigger CI * Revert "trigger CI" This reverts commit a31f53cec47909817b31a48f3c9f1abd9321f72c. * benchmarks * fix benchmarks * fix again * Revert "Revert "trigger CI"" This reverts commit 1dea8b42ac8bca830dea982fd2613eb89d607a6c. * Revert "Revert "Revert "trigger CI""" This reverts commit 8fb74fa5eba483b7f6a3ce3e25a60757aef4c6bc. * try fix * lost lock file * spellcheck * try to disable sccache for cargo check * Revert "Revert "Revert "Revert "trigger CI"""" This reverts commit f157461482d4c1d19156715c4b1ee2acb169531b. * try to disable again * disable sccache for test --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/command.rs | 4 +- bin/millau/node/src/service.rs | 59 +- bin/millau/runtime/Cargo.toml | 2 +- bin/millau/runtime/src/lib.rs | 16 +- bin/rialto-parachain/node/Cargo.toml | 89 +++ bin/rialto-parachain/node/build.rs | 22 + bin/rialto-parachain/node/src/chain_spec.rs | 166 +++++ bin/rialto-parachain/node/src/cli.rs | 146 ++++ bin/rialto-parachain/node/src/command.rs | 414 +++++++++++ bin/rialto-parachain/node/src/lib.rs | 18 + bin/rialto-parachain/node/src/main.rs | 29 + bin/rialto-parachain/node/src/service.rs | 461 ++++++++++++ bin/rialto-parachain/runtime/Cargo.toml | 115 +++ bin/rialto-parachain/runtime/build.rs | 25 + bin/rialto-parachain/runtime/src/lib.rs | 682 ++++++++++++++++++ bin/rialto/node/Cargo.toml | 9 +- bin/rialto/node/src/chain_spec.rs | 8 +- bin/rialto/node/src/command.rs | 4 +- bin/rialto/node/src/overseer.rs | 127 +++- bin/rialto/node/src/parachains_db.rs | 10 +- bin/rialto/node/src/service.rs | 131 ++-- bin/rialto/runtime/Cargo.toml | 2 +- bin/rialto/runtime/src/lib.rs | 51 +- bin/rialto/runtime/src/parachains.rs | 1 + modules/currency-exchange/src/lib.rs | 2 +- modules/dispatch/src/lib.rs | 12 +- modules/ethereum/src/mock.rs | 2 +- modules/grandpa/src/mock.rs | 2 +- modules/messages/src/mock.rs | 2 +- modules/shift-session-manager/src/lib.rs | 2 +- modules/token-swap/src/mock.rs | 2 +- primitives/chain-millau/Cargo.toml | 4 +- primitives/messages/Cargo.toml | 2 +- relays/bin-substrate/src/cli/encode_call.rs | 2 +- .../bin-substrate/src/cli/encode_message.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 4 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 4 +- relays/client-substrate/src/guard.rs | 2 + relays/headers/src/sync.rs | 4 +- relays/headers/src/sync_loop.rs | 8 +- 43 files changed, 2504 insertions(+), 149 deletions(-) create mode 100644 bin/rialto-parachain/node/Cargo.toml create mode 100644 bin/rialto-parachain/node/build.rs create mode 100644 bin/rialto-parachain/node/src/chain_spec.rs create mode 100644 bin/rialto-parachain/node/src/cli.rs create mode 100644 bin/rialto-parachain/node/src/command.rs create mode 100644 bin/rialto-parachain/node/src/lib.rs create mode 100644 bin/rialto-parachain/node/src/main.rs create mode 100644 bin/rialto-parachain/node/src/service.rs create mode 100644 bin/rialto-parachain/runtime/Cargo.toml create mode 100644 bin/rialto-parachain/runtime/build.rs create mode 100644 bin/rialto-parachain/runtime/src/lib.rs diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 18d301d354c87..3307d6031dd49 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -jsonrpc-core = "15.1.0" +jsonrpc-core = "18.0" structopt = "0.3.21" serde_json = "1.0.59" diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index d73f9b1ac9b2c..61786452e03e7 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -79,7 +79,7 @@ pub fn run() -> sc_cli::Result<()> { if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -156,7 +156,7 @@ pub fn run() -> sc_cli::Result<()> { } Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } None => { let runner = cli.create_runner(&cli.run)?; diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 2373d0fbdc67b..3e8d16f596075 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -31,8 +31,7 @@ use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{ExecutorProvider, RemoteBackend}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; -use sc_executor::native_executor_instance; -pub use sc_executor::NativeExecutor; +pub use sc_executor::NativeElseWasmExecutor; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; @@ -41,15 +40,24 @@ use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; +type Executor = NativeElseWasmExecutor; + // Our native executor instance. -native_executor_instance!( - pub Executor, - millau_runtime::api::dispatch, - millau_runtime::native_version, - frame_benchmarking::benchmarking::HostFunctions, -); - -type FullClient = sc_service::TFullClient; +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + millau_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + millau_runtime::native_version() + } +} + +type FullClient = sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -61,7 +69,7 @@ pub fn new_partial( FullClient, FullBackend, FullSelectChain, - sp_consensus::DefaultImportQueue, + sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( sc_finality_grandpa::GrandpaBlockImport, @@ -86,9 +94,16 @@ pub fn new_partial( }) .transpose()?; + let executor = NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + ); + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, )?; let client = Arc::new(client); @@ -185,6 +200,10 @@ pub fn new_full(mut config: Configuration) -> Result .network .extra_sets .push(sc_finality_grandpa::grandpa_peers_set_config()); + let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( + backend.clone(), + grandpa_link.shared_authority_set().clone(), + )); let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -194,6 +213,7 @@ pub fn new_full(mut config: Configuration) -> Result import_queue, on_demand: None, block_announce_validator_builder: None, + warp_sync: Some(warp_sync), })?; if config.offchain_worker.enabled { @@ -244,7 +264,7 @@ pub fn new_full(mut config: Configuration) -> Result subscription_executor, finality_proof_provider.clone(), ))); - io + Ok(io) }) }; @@ -369,10 +389,17 @@ pub fn new_light(mut config: Configuration) -> Result }) .transpose()?; + let executor = NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + ); + let (client, backend, keystore_container, mut task_manager, on_demand) = sc_service::new_light_parts::( &config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, )?; let mut telemetry = telemetry.map(|(worker, telemetry)| { @@ -425,6 +452,11 @@ pub fn new_light(mut config: Configuration) -> Result telemetry: telemetry.as_ref().map(|x| x.handle()), })?; + let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( + backend.clone(), + grandpa_link.shared_authority_set().clone(), + )); + let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -433,6 +465,7 @@ pub fn new_light(mut config: Configuration) -> Result import_queue, on_demand: Some(on_demand.clone()), block_announce_validator_builder: None, + warp_sync: Some(warp_sync), })?; if config.offchain_worker.enabled { @@ -464,7 +497,7 @@ pub fn new_light(mut config: Configuration) -> Result transaction_pool, task_manager: &mut task_manager, on_demand: Some(on_demand), - rpc_extensions_builder: Box::new(|_, _| ()), + rpc_extensions_builder: Box::new(|_, _| Ok(())), config, client, keystore: keystore_container.sync_keystore(), diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 271ff3cc983e2..68d10168e4b6e 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.124", optional = true, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3aa42ef8bd2e4..ce3ca28d39984 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -156,7 +156,7 @@ parameter_types! { impl frame_system::Config for Runtime { /// The basic call filter to use in dispatchable. - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. @@ -206,14 +206,20 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} +parameter_types! { + pub const MaxAuthorities: u32 = 10; +} + impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; + type MaxAuthorities = MaxAuthorities; + type DisabledValidators = (); } impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; - type CallFilter = (); + type CallFilter = frame_support::traits::Everything; type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; type SourceChainAccountId = bp_rialto::AccountId; type TargetChainAccountPublic = MultiSigner; @@ -555,7 +561,7 @@ impl_runtime_apis! { } fn authorities() -> Vec { - Aura::authorities() + Aura::authorities().to_vec() } } @@ -584,6 +590,10 @@ impl_runtime_apis! { } impl fg_primitives::GrandpaApi for Runtime { + fn current_set_id() -> fg_primitives::SetId { + Grandpa::current_set_id() + } + fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml new file mode 100644 index 0000000000000..8adc998e47ee3 --- /dev/null +++ b/bin/rialto-parachain/node/Cargo.toml @@ -0,0 +1,89 @@ +[package] +name = "rialto-parachain-collator" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[build-dependencies] +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[[bin]] +name = 'rialto-parachain-collator' + +[features] +default = [] +runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] + +[dependencies] +derive_more = '0.99.2' +log = '0.4.14' +codec = { package = 'parity-scale-codec', version = '2.0.0' } +structopt = '0.3.8' +serde = { version = '1.0', features = ['derive'] } +hex-literal = '0.3.1' + +# RPC related Dependencies +jsonrpc-core = '18.0' + +# Local Dependencies +rialto-parachain-runtime = { path = '../runtime' } + +# Substrate Dependencies +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } + +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } + +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } + +## Substrate Client Dependencies +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ['wasmtime'] } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } + +## Substrate Primitive Dependencies +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } + +# Cumulus dependencies +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } + +# Polkadot dependencies +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } \ No newline at end of file diff --git a/bin/rialto-parachain/node/build.rs b/bin/rialto-parachain/node/build.rs new file mode 100644 index 0000000000000..8ba8a31e9a79f --- /dev/null +++ b/bin/rialto-parachain/node/build.rs @@ -0,0 +1,22 @@ +// 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 . + +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; + +fn main() { + generate_cargo_keys(); + rerun_if_git_head_changed(); +} diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs new file mode 100644 index 0000000000000..728c4a0a8ec8e --- /dev/null +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -0,0 +1,166 @@ +// Copyright 2020-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 . + +use cumulus_primitives_core::ParaId; +use rialto_parachain_runtime::{AccountId, AuraId, Signature}; +use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; +use sc_service::ChainType; +use serde::{Deserialize, Serialize}; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; + +/// Specialized `ChainSpec` for the normal parachain runtime. +pub type ChainSpec = sc_service::GenericChainSpec; + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// The extensions for the [`ChainSpec`]. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +#[serde(deny_unknown_fields)] +pub struct Extensions { + /// The relay chain of the Parachain. + pub relay_chain: String, + /// The id of the Parachain. + pub para_id: u32, +} + +impl Extensions { + /// Try to get the extension from the given `ChainSpec`. + pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> { + sc_chain_spec::get_extension(chain_spec.extensions()) + } +} + +type AccountPublic = ::Signer; + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +pub fn development_config(id: ParaId) -> ChainSpec { + // Give your base currency a unit name and decimal places + let mut properties = sc_chain_spec::Properties::new(); + properties.insert("tokenSymbol".into(), "UNIT".into()); + properties.insert("tokenDecimals".into(), 12.into()); + + ChainSpec::from_genesis( + // Name + "Development", + // ID + "dev", + ChainType::Local, + move || { + testnet_genesis( + get_account_id_from_seed::("Alice"), + vec![get_from_seed::("Alice"), get_from_seed::("Bob")], + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + ], + id, + ) + }, + vec![], + None, + None, + None, + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: id.into(), + }, + ) +} + +pub fn local_testnet_config(id: ParaId) -> ChainSpec { + // Give your base currency a unit name and decimal places + let mut properties = sc_chain_spec::Properties::new(); + properties.insert("tokenSymbol".into(), "UNIT".into()); + properties.insert("tokenDecimals".into(), 12.into()); + + ChainSpec::from_genesis( + // Name + "Local Testnet", + // ID + "local_testnet", + ChainType::Local, + move || { + testnet_genesis( + get_account_id_from_seed::("Alice"), + vec![get_from_seed::("Alice"), get_from_seed::("Bob")], + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + id, + ) + }, + Vec::new(), + None, + None, + None, + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: id.into(), + }, + ) +} + +fn testnet_genesis( + root_key: AccountId, + initial_authorities: Vec, + endowed_accounts: Vec, + id: ParaId, +) -> rialto_parachain_runtime::GenesisConfig { + rialto_parachain_runtime::GenesisConfig { + system: rialto_parachain_runtime::SystemConfig { + code: rialto_parachain_runtime::WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + changes_trie_config: Default::default(), + }, + balances: rialto_parachain_runtime::BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + }, + sudo: rialto_parachain_runtime::SudoConfig { key: root_key }, + parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, + aura: rialto_parachain_runtime::AuraConfig { + authorities: initial_authorities, + }, + aura_ext: Default::default(), + // parachain_system: Default::default(), + } +} diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs new file mode 100644 index 0000000000000..865d8eb92bea2 --- /dev/null +++ b/bin/rialto-parachain/node/src/cli.rs @@ -0,0 +1,146 @@ +// Copyright 2020-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 . + +use crate::chain_spec; +use cumulus_client_cli; +use sc_cli; +use std::path::PathBuf; +use structopt::StructOpt; + +/// Sub-commands supported by the collator. +#[derive(Debug, StructOpt)] +pub enum Subcommand { + /// Export the genesis state of the parachain. + #[structopt(name = "export-genesis-state")] + ExportGenesisState(ExportGenesisStateCommand), + + /// Export the genesis wasm of the parachain. + #[structopt(name = "export-genesis-wasm")] + ExportGenesisWasm(ExportGenesisWasmCommand), + + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), + + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), + + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), + + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), + + /// Remove the whole chain. + PurgeChain(cumulus_client_cli::PurgeChainCmd), + + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + + /// The custom benchmark subcommmand benchmarking runtime pallets. + #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), +} + +/// Command for exporting the genesis state of the parachain +#[derive(Debug, StructOpt)] +pub struct ExportGenesisStateCommand { + /// Output file name or stdout if unspecified. + #[structopt(parse(from_os_str))] + pub output: Option, + + /// Id of the parachain this state is for. + /// + /// Default: 100 + #[structopt(long, conflicts_with = "chain")] + pub parachain_id: Option, + + /// Write output in binary. Default is to write in hex. + #[structopt(short, long)] + pub raw: bool, + + /// The name of the chain for that the genesis state should be exported. + #[structopt(long, conflicts_with = "parachain-id")] + pub chain: Option, +} + +/// Command for exporting the genesis wasm file. +#[derive(Debug, StructOpt)] +pub struct ExportGenesisWasmCommand { + /// Output file name or stdout if unspecified. + #[structopt(parse(from_os_str))] + pub output: Option, + + /// Write output in binary. Default is to write in hex. + #[structopt(short, long)] + pub raw: bool, + + /// The name of the chain for that the genesis wasm file should be exported. + #[structopt(long)] + pub chain: Option, +} + +#[derive(Debug, StructOpt)] +#[structopt(settings = &[ + structopt::clap::AppSettings::GlobalVersion, + structopt::clap::AppSettings::ArgsNegateSubcommands, + structopt::clap::AppSettings::SubcommandsNegateReqs, +])] +pub struct Cli { + #[structopt(subcommand)] + pub subcommand: Option, + + #[structopt(flatten)] + pub run: cumulus_client_cli::RunCmd, + + /// Relaychain arguments + #[structopt(raw = true)] + pub relaychain_args: Vec, +} + +#[derive(Debug)] +pub struct RelayChainCli { + /// The actual relay chain cli object. + pub base: polkadot_cli::RunCmd, + + /// Optional chain id that should be passed to the relay chain. + pub chain_id: Option, + + /// The base path that should be used by the relay chain. + pub base_path: Option, +} + +impl RelayChainCli { + /// Parse the relay chain CLI parameters using the para chain `Configuration`. + pub fn new<'a>( + para_config: &sc_service::Configuration, + relay_chain_args: impl Iterator, + ) -> Self { + let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); + let chain_id = extension.map(|e| e.relay_chain.clone()); + let base_path = para_config + .base_path + .as_ref() + .map(|x| x.path().join("rialto-bridge-node")); + Self { + base_path, + chain_id, + base: polkadot_cli::RunCmd::from_iter(relay_chain_args), + } + } +} diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs new file mode 100644 index 0000000000000..a37673a5b9bcb --- /dev/null +++ b/bin/rialto-parachain/node/src/command.rs @@ -0,0 +1,414 @@ +// Copyright 2020-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 . + +use crate::{ + chain_spec, + cli::{Cli, RelayChainCli, Subcommand}, + service::{new_partial, ParachainRuntimeExecutor}, +}; +use codec::Encode; +use cumulus_client_service::genesis::generate_genesis_block; +use cumulus_primitives_core::ParaId; +use log::info; +use polkadot_parachain::primitives::AccountIdConversion; +use rialto_parachain_runtime::{Block, RuntimeApi}; +use sc_cli::{ + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, + RuntimeVersion, SharedParams, SubstrateCli, +}; +use sc_service::config::{BasePath, PrometheusConfig}; +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::traits::Block as BlockT; +use std::{io::Write, net::SocketAddr}; + +fn load_spec(id: &str, para_id: ParaId) -> std::result::Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config(para_id)), + "" | "local" => Box::new(chain_spec::local_testnet_config(para_id)), + path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + }) +} + +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Parachain Collator Template".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + format!( + "Parachain Collator Template\n\nThe command-line arguments provided first will be \ + passed to the parachain node, while the arguments provided after -- will be passed \ + to the relaychain node.\n\n\ + {} [parachain-args] -- [relaychain-args]", + Self::executable_name() + ) + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> std::result::Result, String> { + load_spec(id, self.run.parachain_id.unwrap_or(2000).into()) + } + + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &rialto_parachain_runtime::VERSION + } +} + +impl SubstrateCli for RelayChainCli { + fn impl_name() -> String { + "Parachain Collator Template".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + "Parachain Collator Template\n\nThe command-line arguments provided first will be \ + passed to the parachain node, while the arguments provided after -- will be passed \ + to the relaychain node.\n\n\ + parachain-collator [parachain-args] -- [relaychain-args]" + .into() + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into() + } + + fn copyright_start_year() -> i32 { + 2017 + } + + fn load_spec(&self, id: &str) -> std::result::Result, String> { + polkadot_cli::Cli::from_iter([RelayChainCli::executable_name().to_string()].iter()).load_spec(id) + } + + fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion { + polkadot_cli::Cli::native_runtime_version(chain_spec) + } +} + +fn extract_genesis_wasm(chain_spec: &Box) -> Result> { + let mut storage = chain_spec.build_storage()?; + + storage + .top + .remove(sp_core::storage::well_known_keys::CODE) + .ok_or_else(|| "Could not find wasm file in genesis state!".into()) +} + +macro_rules! construct_async_run { + (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ + let runner = $cli.create_runner($cmd)?; + runner.async_run(|$config| { + let $components = new_partial::< + RuntimeApi, + ParachainRuntimeExecutor, + _ + >( + &$config, + crate::service::parachain_build_import_queue, + )?; + let task_manager = $components.task_manager; + { $( $code )* }.map(|v| (v, task_manager)) + }) + }} +} + +/// Parse command line arguments into service configuration. +pub fn run() -> Result<()> { + let cli = Cli::from_args(); + sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom( + rialto_parachain_runtime::SS58Prefix::get() as u16, + )); + + match &cli.subcommand { + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + } + Some(Subcommand::CheckBlock(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, components.import_queue)) + }) + } + Some(Subcommand::ExportBlocks(cmd)) => { + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) + } + Some(Subcommand::ExportState(cmd)) => { + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) + } + Some(Subcommand::ImportBlocks(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, components.import_queue)) + }) + } + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| { + let polkadot_cli = RelayChainCli::new( + &config, + [RelayChainCli::executable_name().to_string()] + .iter() + .chain(cli.relaychain_args.iter()), + ); + + let polkadot_config = + SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) + .map_err(|err| format!("Relay chain argument error: {}", err))?; + + cmd.run(config, polkadot_config) + }) + } + Some(Subcommand::Revert(cmd)) => { + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, components.backend))) + } + Some(Subcommand::ExportGenesisState(params)) => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); + let _ = builder.init(); + + let block: Block = generate_genesis_block(&load_spec( + ¶ms.chain.clone().unwrap_or_default(), + params.parachain_id.expect("Missing ParaId").into(), + )?)?; + let raw_header = block.header().encode(); + let output_buf = if params.raw { + raw_header + } else { + format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() + }; + + if let Some(output) = ¶ms.output { + std::fs::write(output, output_buf)?; + } else { + std::io::stdout().write_all(&output_buf)?; + } + + Ok(()) + } + Some(Subcommand::ExportGenesisWasm(params)) => { + let mut builder = sc_cli::LoggerBuilder::new(""); + builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); + let _ = builder.init(); + + let raw_wasm_blob = extract_genesis_wasm(&cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; + let output_buf = if params.raw { + raw_wasm_blob + } else { + format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() + }; + + if let Some(output) = ¶ms.output { + std::fs::write(output, output_buf)?; + } else { + std::io::stdout().write_all(&output_buf)?; + } + + Ok(()) + } + Some(Subcommand::Benchmark(cmd)) => { + if cfg!(feature = "runtime-benchmarks") { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| cmd.run::(config)) + } else { + Err("Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into()) + } + } + None => { + let runner = cli.create_runner(&cli.run.normalize())?; + + runner.run_node_until_exit(|config| async move { + let para_id = chain_spec::Extensions::try_get(&*config.chain_spec).map(|e| e.para_id); + + let polkadot_cli = RelayChainCli::new( + &config, + [RelayChainCli::executable_name().to_string()] + .iter() + .chain(cli.relaychain_args.iter()), + ); + + let id = ParaId::from(cli.run.parachain_id.or(para_id).expect("Missing ParaId")); + + let parachain_account = AccountIdConversion::::into_account(&id); + + let block: Block = generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?; + let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); + + let polkadot_config = + SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) + .map_err(|err| format!("Relay chain argument error: {}", err))?; + + info!("Parachain id: {:?}", id); + info!("Parachain Account: {}", parachain_account); + info!("Parachain genesis state: {}", genesis_state); + info!( + "Is collating: {}", + if config.role.is_authority() { "yes" } else { "no" } + ); + + crate::service::start_node(config, polkadot_config, id) + .await + .map(|r| r.0) + .map_err(Into::into) + }) + } + } +} + +impl DefaultConfigurationValues for RelayChainCli { + fn p2p_listen_port() -> u16 { + 30334 + } + + fn rpc_ws_listen_port() -> u16 { + 9945 + } + + fn rpc_http_listen_port() -> u16 { + 9934 + } + + fn prometheus_listen_port() -> u16 { + 9616 + } +} + +impl CliConfiguration for RelayChainCli { + fn shared_params(&self) -> &SharedParams { + self.base.base.shared_params() + } + + fn import_params(&self) -> Option<&ImportParams> { + self.base.base.import_params() + } + + fn network_params(&self) -> Option<&NetworkParams> { + self.base.base.network_params() + } + + fn keystore_params(&self) -> Option<&KeystoreParams> { + self.base.base.keystore_params() + } + + fn base_path(&self) -> Result> { + Ok(self + .shared_params() + .base_path() + .or_else(|| self.base_path.clone().map(Into::into))) + } + + fn rpc_http(&self, default_listen_port: u16) -> Result> { + self.base.base.rpc_http(default_listen_port) + } + + fn rpc_ipc(&self) -> Result> { + self.base.base.rpc_ipc() + } + + fn rpc_ws(&self, default_listen_port: u16) -> Result> { + self.base.base.rpc_ws(default_listen_port) + } + + fn prometheus_config(&self, default_listen_port: u16) -> Result> { + self.base.base.prometheus_config(default_listen_port) + } + + fn init(&self) -> Result<()> { + unreachable!("PolkadotCli is never initialized; qed"); + } + + fn chain_id(&self, is_dev: bool) -> Result { + let chain_id = self.base.base.chain_id(is_dev)?; + + Ok(if chain_id.is_empty() { + self.chain_id.clone().unwrap_or_default() + } else { + chain_id + }) + } + + fn role(&self, is_dev: bool) -> Result { + self.base.base.role(is_dev) + } + + fn transaction_pool(&self) -> Result { + self.base.base.transaction_pool() + } + + fn state_cache_child_ratio(&self) -> Result> { + self.base.base.state_cache_child_ratio() + } + + fn rpc_methods(&self) -> Result { + self.base.base.rpc_methods() + } + + fn rpc_ws_max_connections(&self) -> Result> { + self.base.base.rpc_ws_max_connections() + } + + fn rpc_cors(&self, is_dev: bool) -> Result>> { + self.base.base.rpc_cors(is_dev) + } + + fn default_heap_pages(&self) -> Result> { + self.base.base.default_heap_pages() + } + + fn force_authoring(&self) -> Result { + self.base.base.force_authoring() + } + + fn disable_grandpa(&self) -> Result { + self.base.base.disable_grandpa() + } + + fn max_runtime_instances(&self) -> Result> { + self.base.base.max_runtime_instances() + } + + fn announce_block(&self) -> Result { + self.base.base.announce_block() + } + + fn telemetry_endpoints(&self, chain_spec: &Box) -> Result> { + self.base.base.telemetry_endpoints(chain_spec) + } +} diff --git a/bin/rialto-parachain/node/src/lib.rs b/bin/rialto-parachain/node/src/lib.rs new file mode 100644 index 0000000000000..3ec291596b719 --- /dev/null +++ b/bin/rialto-parachain/node/src/lib.rs @@ -0,0 +1,18 @@ +// Copyright 2020-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 . + +pub mod chain_spec; +pub mod service; diff --git a/bin/rialto-parachain/node/src/main.rs b/bin/rialto-parachain/node/src/main.rs new file mode 100644 index 0000000000000..2b4e0b438d1a9 --- /dev/null +++ b/bin/rialto-parachain/node/src/main.rs @@ -0,0 +1,29 @@ +// Copyright 2020-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 . + +//! Substrate Parachain Node Template CLI + +#![warn(missing_docs)] + +mod chain_spec; +#[macro_use] +mod service; +mod cli; +mod command; + +fn main() -> sc_cli::Result<()> { + command::run() +} diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs new file mode 100644 index 0000000000000..a812358edf363 --- /dev/null +++ b/bin/rialto-parachain/node/src/service.rs @@ -0,0 +1,461 @@ +// Copyright 2020-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 . + +// std +use std::sync::Arc; + +// Local Runtime Types +use rialto_parachain_runtime::RuntimeApi; + +// Cumulus Imports +use cumulus_client_consensus_aura::{build_aura_consensus, BuildAuraConsensusParams, SlotProportion}; +use cumulus_client_consensus_common::ParachainConsensus; +use cumulus_client_network::build_block_announce_validator; +use cumulus_client_service::{ + prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, +}; +use cumulus_primitives_core::ParaId; + +// Substrate Imports +use sc_client_api::ExecutorProvider; +use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; +use sc_network::NetworkService; +use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager}; +use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; +use sp_api::ConstructRuntimeApi; +use sp_consensus::SlotData; +use sp_keystore::SyncCryptoStorePtr; +use sp_runtime::traits::BlakeTwo256; +use substrate_prometheus_endpoint::Registry; + +// Runtime type overrides +type BlockNumber = u32; +type Header = sp_runtime::generic::Header; +pub type Block = sp_runtime::generic::Block; +type Hash = sp_core::H256; + +pub type ParachainRuntimeExecutor = ExecutorDispatch; + +// Our native executor instance. +pub struct ExecutorDispatch; + +impl NativeExecutionDispatch for ExecutorDispatch { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + rialto_parachain_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + rialto_parachain_runtime::native_version() + } +} + +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +pub fn new_partial( + config: &Configuration, + build_import_queue: BIQ, +) -> Result< + PartialComponents< + TFullClient>, + TFullBackend, + (), + sc_consensus::DefaultImportQueue>>, + sc_transaction_pool::FullPool>>, + (Option, Option), + >, + sc_service::Error, +> +where + RuntimeApi: ConstructRuntimeApi>> + + Send + + Sync + + 'static, + RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::Metadata + + sp_session::SessionKeys + + sp_api::ApiExt, Block>> + + sp_offchain::OffchainWorkerApi + + sp_block_builder::BlockBuilder, + sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, + Executor: NativeExecutionDispatch + 'static, + BIQ: FnOnce( + Arc>>, + &Configuration, + Option, + &TaskManager, + ) -> Result< + sc_consensus::DefaultImportQueue>>, + sc_service::Error, + >, +{ + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + + let executor = sc_executor::NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + ); + + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + &config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; + let client = Arc::new(client); + + let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); + + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", worker.run()); + telemetry + }); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); + + let import_queue = build_import_queue( + client.clone(), + config, + telemetry.as_ref().map(|telemetry| telemetry.handle()), + &task_manager, + )?; + + let params = PartialComponents { + backend, + client, + import_queue, + keystore_container, + task_manager, + transaction_pool, + select_chain: (), + other: (telemetry, telemetry_worker_handle), + }; + + Ok(params) +} + +/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. +/// +/// This is the actual implementation that is abstract over the executor and the runtime api. +#[sc_tracing::logging::prefix_logs_with("Parachain")] +async fn start_node_impl( + parachain_config: Configuration, + polkadot_config: Configuration, + id: ParaId, + rpc_ext_builder: RB, + build_import_queue: BIQ, + build_consensus: BIC, +) -> sc_service::error::Result<( + TaskManager, + Arc>>, +)> +where + RuntimeApi: ConstructRuntimeApi>> + + Send + + Sync + + 'static, + RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::Metadata + + sp_session::SessionKeys + + sp_api::ApiExt, Block>> + + sp_offchain::OffchainWorkerApi + + sp_block_builder::BlockBuilder + + cumulus_primitives_core::CollectCollationInfo, + sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, + Executor: NativeExecutionDispatch + 'static, + RB: Fn( + Arc>>, + ) -> jsonrpc_core::IoHandler + + Send + + 'static, + BIQ: FnOnce( + Arc>>, + &Configuration, + Option, + &TaskManager, + ) -> Result< + sc_consensus::DefaultImportQueue>>, + sc_service::Error, + >, + BIC: FnOnce( + Arc>>, + Option<&Registry>, + Option, + &TaskManager, + &polkadot_service::NewFull, + Arc>>>, + Arc>, + SyncCryptoStorePtr, + bool, + ) -> Result>, sc_service::Error>, +{ + if matches!(parachain_config.role, Role::Light) { + return Err("Light client not supported!".into()); + } + + let parachain_config = prepare_node_config(parachain_config); + + let params = new_partial::(¶chain_config, build_import_queue)?; + let (mut telemetry, telemetry_worker_handle) = params.other; + + let relay_chain_full_node = + cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle).map_err( + |e| match e { + polkadot_service::Error::Sub(x) => x, + s => format!("{}", s).into(), + }, + )?; + + let client = params.client.clone(); + let backend = params.backend.clone(); + let block_announce_validator = build_block_announce_validator( + relay_chain_full_node.client.clone(), + id, + Box::new(relay_chain_full_node.network.clone()), + relay_chain_full_node.backend.clone(), + ); + + let force_authoring = parachain_config.force_authoring; + let validator = parachain_config.role.is_authority(); + let prometheus_registry = parachain_config.prometheus_registry().cloned(); + let transaction_pool = params.transaction_pool.clone(); + let mut task_manager = params.task_manager; + let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); + let (network, system_rpc_tx, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { + config: ¶chain_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue: import_queue.clone(), + on_demand: None, + block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)), + warp_sync: None, + })?; + + let rpc_client = client.clone(); + let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone()))); + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + on_demand: None, + remote_blockchain: None, + rpc_extensions_builder, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + task_manager: &mut task_manager, + config: parachain_config, + keystore: params.keystore_container.sync_keystore(), + backend: backend.clone(), + network: network.clone(), + system_rpc_tx, + telemetry: telemetry.as_mut(), + })?; + + let announce_block = { + let network = network.clone(); + Arc::new(move |hash, data| network.announce_block(hash, data)) + }; + + if validator { + let parachain_consensus = build_consensus( + client.clone(), + prometheus_registry.as_ref(), + telemetry.as_ref().map(|t| t.handle()), + &task_manager, + &relay_chain_full_node, + transaction_pool, + network, + params.keystore_container.sync_keystore(), + force_authoring, + )?; + + let spawner = task_manager.spawn_handle(); + + let params = StartCollatorParams { + para_id: id, + block_status: client.clone(), + announce_block, + client: client.clone(), + task_manager: &mut task_manager, + relay_chain_full_node, + spawner, + parachain_consensus, + import_queue, + }; + + start_collator(params).await?; + } else { + let params = StartFullNodeParams { + client: client.clone(), + announce_block, + task_manager: &mut task_manager, + para_id: id, + relay_chain_full_node, + }; + + start_full_node(params)?; + } + + start_network.start_network(); + + Ok((task_manager, client)) +} + +/// Build the import queue for the the parachain runtime. +pub fn parachain_build_import_queue( + client: Arc>>, + config: &Configuration, + telemetry: Option, + task_manager: &TaskManager, +) -> Result< + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, + sc_service::Error, +> { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + + cumulus_client_consensus_aura::import_queue::( + cumulus_client_consensus_aura::ImportQueueParams { + block_import: client.clone(), + client: client.clone(), + create_inherent_data_providers: move |_, _| async move { + let time = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *time, + slot_duration.slot_duration(), + ); + + Ok((time, slot)) + }, + registry: config.prometheus_registry().clone(), + can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + spawner: &task_manager.spawn_essential_handle(), + telemetry, + }, + ) + .map_err(Into::into) +} + +/// Start a normal parachain node. +pub async fn start_node( + parachain_config: Configuration, + polkadot_config: Configuration, + id: ParaId, +) -> sc_service::error::Result<( + TaskManager, + Arc>>, +)> { + start_node_impl::( + parachain_config, + polkadot_config, + id, + |_| Default::default(), + parachain_build_import_queue, + |client, + prometheus_registry, + telemetry, + task_manager, + relay_chain_node, + transaction_pool, + sync_oracle, + keystore, + force_authoring| { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry.clone(), + telemetry.clone(), + ); + + let relay_chain_backend = relay_chain_node.backend.clone(); + let relay_chain_client = relay_chain_node.client.clone(); + Ok(build_aura_consensus::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + _, + _, + _, + _, + >(BuildAuraConsensusParams { + proposer_factory, + create_inherent_data_providers: move |_, (relay_parent, validation_data)| { + let parachain_inherent = + cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client( + relay_parent, + &relay_chain_client, + &*relay_chain_backend, + &validation_data, + id, + ); + async move { + let time = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *time, + slot_duration.slot_duration(), + ); + + let parachain_inherent = parachain_inherent.ok_or_else(|| { + Box::::from("Failed to create parachain inherent") + })?; + Ok((time, slot, parachain_inherent)) + } + }, + block_import: client.clone(), + relay_chain_client: relay_chain_node.client.clone(), + relay_chain_backend: relay_chain_node.backend.clone(), + para_client: client.clone(), + backoff_authoring_blocks: Option::<()>::None, + sync_oracle, + keystore, + force_authoring, + slot_duration, + // We got around 500ms for proposing + block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), + telemetry, + max_block_proposal_slot_portion: None, + })) + }, + ) + .await +} diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml new file mode 100644 index 0000000000000..09916f508b7bf --- /dev/null +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -0,0 +1,115 @@ +[package] +name = "rialto-parachain-runtime" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/parity-bridges-common/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[build-dependencies] +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[dependencies] +codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive']} +log = { version = "0.4.14", default-features = false } +serde = { version = '1.0', optional = true, features = ['derive'] } + +# Substrate Dependencies +## Substrate Primitive Dependencies +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-block-builder = { 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-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +## Substrate FRAME Dependencies +frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +## Substrate Pallet Dependencies +pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +# Cumulus Dependencies +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } + +# Polkadot Dependencies +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } + +[features] +default = ['std'] +runtime-benchmarks = [ + 'sp-runtime/runtime-benchmarks', + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system-benchmarking', + 'frame-system/runtime-benchmarks', + 'pallet-balances/runtime-benchmarks', + 'pallet-timestamp/runtime-benchmarks', +] +std = [ + "codec/std", + "serde", + "log/std", + "sp-api/std", + "sp-std/std", + "sp-io/std", + "sp-core/std", + "sp-runtime/std", + "sp-version/std", + "sp-offchain/std", + "sp-session/std", + "sp-block-builder/std", + "sp-transaction-pool/std", + "sp-inherents/std", + "frame-support/std", + "frame-executive/std", + "frame-system/std", + "pallet-balances/std", + "pallet-randomness-collective-flip/std", + "pallet-timestamp/std", + "pallet-sudo/std", + "pallet-transaction-payment/std", + "parachain-info/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-pallet-xcm/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "cumulus-primitives-utility/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", + "pallet-aura/std", + "sp-consensus-aura/std", +] diff --git a/bin/rialto-parachain/runtime/build.rs b/bin/rialto-parachain/runtime/build.rs new file mode 100644 index 0000000000000..65095bd1b7e9e --- /dev/null +++ b/bin/rialto-parachain/runtime/build.rs @@ -0,0 +1,25 @@ +// 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 . + +use substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs new file mode 100644 index 0000000000000..58f592bea8cef --- /dev/null +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -0,0 +1,682 @@ +// 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 . + +//! The Rialto parachain runtime. This can be compiled with `#[no_std]`, ready for Wasm. +//! +//! Originally a copypaste of runtime from https://github.com/substrate-developer-hub/substrate-parachain-template. + +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, +}; + +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +// A few exports that help ease life for downstream crates. +pub use frame_support::{ + construct_runtime, match_type, parameter_types, + traits::{Everything, IsInVec, Randomness}, + weights::{ + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + DispatchClass, IdentityFee, Weight, + }, + StorageValue, +}; +use frame_system::limits::{BlockLength, BlockWeights}; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_timestamp::Call as TimestampCall; +pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{MultiAddress, Perbill, Permill}; + +// Polkadot & XCM imports +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin, + FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentAsSuperuser, ParentIsDefault, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, +}; +use xcm_executor::{Config, XcmExecutor}; + +// /// Import the template pallet. +// pub use template; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; +/// Balance of an account. +pub type Balance = u128; +/// Index of a transaction in the chain. +pub type Index = u32; +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; +/// An index to a block. +pub type BlockNumber = u32; +/// The address format for describing accounts. +pub type Address = MultiAddress; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckSpecVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +/// Executive: handles dispatch to the various modules. +pub type Executive = + frame_executive::Executive, Runtime, AllPallets>; + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + } +} + +/// This runtime version. +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("template-parachain"), + impl_name: create_runtime_str!("template-parachain"), + authoring_version: 1, + spec_version: 1, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, +}; + +/// This determines the average expected block time that we are targeting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 12000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +// Unit = the base number of indivisible units for balances +pub const UNIT: Balance = 1_000_000_000_000; +pub const MILLIUNIT: Balance = 1_000_000_000; +pub const MICROUNIT: Balance = 1_000_000; + +// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. +pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +/// We assume that approximately 10 percent of the block weight is consumed by `on_initalize` handlers. +/// This is used to limit the maximal weight of a single extrinsic. +const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +/// We allow `Normal` extrinsics to fill up the block up to 75 percent, the rest can be used +/// by Operational extrinsics. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +/// We allow for 2 seconds of compute with a 12 second average block time. +const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND * 2; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub const Version: RuntimeVersion = VERSION; + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const SS58Prefix: u8 = 48; +} + +// Configure FRAME pallets to include in runtime. + +impl frame_system::Config for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Runtime version. + type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = (); + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the Unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 1 * MILLIUNIT; + pub const TransferFee: u128 = 1 * MILLIUNIT; + pub const CreationFee: u128 = 1 * MILLIUNIT; + pub const TransactionByteFee: u128 = 1 * MICROUNIT; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_transaction_payment::Config for Runtime { + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type TransactionByteFee = TransactionByteFee; + type WeightToFee = IdentityFee; + type FeeMultiplierUpdate = (); +} + +impl pallet_sudo::Config for Runtime { + type Call = Call; + type Event = Event; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type Event = Event; + type OnValidationData = (); + type SelfParaId = parachain_info::Pallet; + type OutboundXcmpMessageSource = XcmpQueue; + type DmpMessageHandler = DmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; +} + +impl parachain_info::Config for Runtime {} + +impl cumulus_pallet_aura_ext::Config for Runtime {} + +impl pallet_randomness_collective_flip::Config for Runtime {} + +parameter_types! { + pub const RelayLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsDefault, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting assets on this chain. +pub type LocalAssetTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with XCM `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToTransactDispatchOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognised. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognised. + SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = 1_000_000; + // One UNIT buys 1 second of weight. + pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); + pub const MaxInstructions: u32 = 100; + pub const MaxAuthorities: u32 = 100_000; +} + +match_type! { + pub type ParentOrParentsUnitPlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) } + }; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + AllowUnpaidExecutionFrom, + // ^^^ Parent & its unit plurality gets free execution +); + +pub struct XcmConfig; +impl Config for XcmConfig { + type Call = Call; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = NativeAsset; + type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of UNIT + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = UsingComponents, RelayLocation, AccountId, Balances, ()>; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = SignedToAccountId32; + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +impl pallet_xcm::Config for Runtime { + type Event = Event; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type Origin = Origin; + type Call = Call; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; + type VersionWrapper = (); +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = MaxAuthorities; +} + +// /// Configure the pallet template in pallets/template. +// impl template::Config for Runtime { +// type Event = Event; +// } + +// Create the runtime by composing the FRAME pallets that were previously configured. +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = generic::Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event}, + RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + + ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 20, + ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21, + + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 30, + + Aura: pallet_aura::{Pallet, Config}, + AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, + + // XCM helpers. + XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 50, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin} = 51, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 52, + DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 53, + + // //Template + // TemplatePallet: template::{Pallet, Call, Storage, Event}, + } +); + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + Runtime::metadata().into() + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic( + extrinsic: ::Extrinsic, + ) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_session::SessionKeys for Runtime { + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + SessionKeys::decode_into_raw_public_keys(&encoded) + } + + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities().to_vec() + } + } + + impl cumulus_primitives_core::CollectCollationInfo for Runtime { + fn collect_collation_info() -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info() + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + + use frame_system_benchmarking::Pallet as SystemBench; + impl frame_system_benchmarking::Config for Runtime {} + + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), + // Total Issuance + hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), + ]; + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + + add_benchmark!(params, batches, frame_system, SystemBench::); + add_benchmark!(params, batches, pallet_balances, Balances); + add_benchmark!(params, batches, pallet_timestamp, Timestamp); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } +} + +struct CheckInherents; + +impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { + fn check_inherents( + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + ) -> sp_inherents::CheckInherentsResult { + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); + + inherent_data.check_extrinsics(&block) + } +} + +cumulus_pallet_parachain_system::register_validate_block!( + Runtime = Runtime, + BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, + CheckInherents = CheckInherents, +); diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 833cea604dc60..08c72ce67632a 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] futures = "0.3" -jsonrpc-core = "15.1.0" +jsonrpc-core = "18.0" kvdb = "0.10" kvdb-rocksdb = "0.12" structopt = "0.3.21" @@ -44,7 +44,7 @@ sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } +#sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -76,6 +76,7 @@ polkadot-availability-bitfield-distribution = { git = "https://github.com/parity polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-dispute-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" } @@ -85,10 +86,14 @@ polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", b polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-dispute-participation = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-dispute-coordinator = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-network-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-subsystem-util = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index be631109faf9e..68a2928ed2890 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -18,8 +18,8 @@ use bp_rialto::derive_account_from_millau_id; use polkadot_primitives::v1::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig, BridgeRialtoPoaConfig, - GenesisConfig, GrandpaConfig, ParachainsConfigurationConfig, SessionConfig, SessionKeys, Signature, SudoConfig, - SystemConfig, WASM_BINARY, + ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, + WASM_BINARY, }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -251,7 +251,7 @@ fn testnet_genesis( hrmp: Default::default(), // this configuration is exact copy of configuration from Polkadot repo // (see /node/service/src/chain_spec.rs:default_parachains_host_configuration) - parachains_configuration: ParachainsConfigurationConfig { + configuration: ConfigurationConfig { config: polkadot_runtime_parachains::configuration::HostConfiguration { validation_upgrade_frequency: 1u32, validation_upgrade_delay: 1, @@ -273,7 +273,7 @@ fn testnet_genesis( ump_service_total_weight: 4 * 1_000_000_000, max_upward_message_size: 1024 * 1024, max_upward_message_num_per_candidate: 5, - hrmp_open_request_ttl: 5, + _hrmp_open_request_ttl: 5, hrmp_sender_deposit: 0, hrmp_recipient_deposit: 0, hrmp_channel_max_capacity: 8, diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 4fe40251e63b2..308cb10344410 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -77,7 +77,7 @@ pub fn run() -> sc_cli::Result<()> { if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -154,7 +154,7 @@ pub fn run() -> sc_cli::Result<()> { } Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } Some(Subcommand::PvfPrepareWorker(cmd)) => { let mut builder = sc_cli::LoggerBuilder::new(""); diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs index f7aaef4b5d492..ff82db8b0e57f 100644 --- a/bin/rialto/node/src/overseer.rs +++ b/bin/rialto/node/src/overseer.rs @@ -20,19 +20,22 @@ // this warning comes from `polkadot_overseer::AllSubsystems` type #![allow(clippy::type_complexity)] -use crate::service::Error; +use crate::service::{AuthorityDiscoveryApi, Error}; +use rialto_runtime::{opaque::Block, Hash}; -use polkadot_network_bridge::RequestMultiplexer; +use polkadot_availability_distribution::IncomingRequestReceivers; use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; use polkadot_node_core_av_store::Config as AvailabilityConfig; use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; -use polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandler}; -use polkadot_primitives::v1::{Block, Hash, ParachainHost}; +use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; +use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; +use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver}; +use polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandle}; +use polkadot_primitives::v1::ParachainHost; use sc_authority_discovery::Service as AuthorityDiscoveryService; use sc_client_api::AuxStore; use sc_keystore::LocalKeystore; use sp_api::ProvideRuntimeApi; -use sp_authority_discovery::AuthorityDiscoveryApi; use sp_blockchain::HeaderBackend; use sp_consensus_babe::BabeApi; use sp_core::traits::SpawnNamed; @@ -44,6 +47,7 @@ pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as Bit pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem; pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem; pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide}; +pub use polkadot_dispute_distribution::DisputeDistributionSubsystem; pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem; pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem; pub use polkadot_node_collation_generation::CollationGenerationSubsystem; @@ -53,6 +57,9 @@ pub use polkadot_node_core_backing::CandidateBackingSubsystem; pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem; pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem; pub use polkadot_node_core_chain_api::ChainApiSubsystem; +pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem; +pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem; +pub use polkadot_node_core_dispute_participation::DisputeParticipationSubsystem; pub use polkadot_node_core_provisioner::ProvisioningSubsystem as ProvisionerSubsystem; pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem; pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem; @@ -72,43 +79,58 @@ where pub runtime_client: Arc, /// The underlying key value store for the parachains. pub parachains_db: Arc, - /// Configuration for the availability store subsystem. - pub availability_config: AvailabilityConfig, - /// Configuration for the approval voting subsystem. - pub approval_voting_config: ApprovalVotingConfig, /// Underlying network service implementation. pub network_service: Arc>, /// Underlying authority discovery service. pub authority_discovery_service: AuthorityDiscoveryService, - /// A multiplexer to arbitrate incoming `IncomingRequest`s from the network. - pub request_multiplexer: RequestMultiplexer, + /// POV request receiver + pub pov_req_receiver: IncomingRequestReceiver, + pub chunk_req_receiver: IncomingRequestReceiver, + pub collation_req_receiver: IncomingRequestReceiver, + pub available_data_req_receiver: IncomingRequestReceiver, + pub statement_req_receiver: IncomingRequestReceiver, + pub dispute_req_receiver: IncomingRequestReceiver, /// Prometheus registry, commonly used for production systems, less so for test. pub registry: Option<&'a Registry>, /// Task spawner to be used throughout the overseer and the APIs it provides. pub spawner: Spawner, + /// Configuration for the approval voting subsystem. + pub approval_voting_config: ApprovalVotingConfig, + /// Configuration for the availability store subsystem. + pub availability_config: AvailabilityConfig, /// Configuration for the candidate validation subsystem. pub candidate_validation_config: CandidateValidationConfig, + /// Configuration for the chain selection subsystem. + pub chain_selection_config: ChainSelectionConfig, + /// Configuration for the dispute coordinator subsystem. + pub dispute_coordinator_config: DisputeCoordinatorConfig, } /// Create a default, unaltered set of subsystems. /// /// A convenience for usage with malus, to avoid /// repetitive code across multiple behavior strain implementations. -pub fn create_default_subsystems( +pub fn create_default_subsystems<'a, Spawner, RuntimeClient>( OverseerGenArgs { keystore, runtime_client, parachains_db, - availability_config, - approval_voting_config, network_service, authority_discovery_service, - request_multiplexer, + pov_req_receiver, + chunk_req_receiver, + available_data_req_receiver, + statement_req_receiver, + dispute_req_receiver, registry, spawner, + approval_voting_config, + availability_config, candidate_validation_config, + chain_selection_config, + dispute_coordinator_config, .. - }: OverseerGenArgs, + }: OverseerGenArgs<'a, Spawner, RuntimeClient>, ) -> Result< AllSubsystems< CandidateValidationSubsystem, @@ -128,6 +150,10 @@ pub fn create_default_subsystems( ApprovalDistributionSubsystem, ApprovalVotingSubsystem, GossipSupportSubsystem, + DisputeCoordinatorSubsystem, + DisputeParticipationSubsystem, + DisputeDistributionSubsystem, + ChainSelectionSubsystem, >, Error, > @@ -141,9 +167,16 @@ where let all_subsystems = AllSubsystems { availability_distribution: AvailabilityDistributionSubsystem::new( keystore.clone(), + IncomingRequestReceivers { + pov_req_receiver, + chunk_req_receiver, + }, + Metrics::register(registry)?, + ), + availability_recovery: AvailabilityRecoverySubsystem::with_chunks_only( + available_data_req_receiver, Metrics::register(registry)?, ), - availability_recovery: AvailabilityRecoverySubsystem::with_chunks_only(), availability_store: AvailabilityStoreSubsystem::new( parachains_db.clone(), availability_config, @@ -162,37 +195,51 @@ where ), candidate_validation: CandidateValidationSubsystem::with_config( candidate_validation_config, - Metrics::register(registry)?, + Metrics::register(registry)?, // candidate-validation metrics + Metrics::register(registry)?, // validation host metrics ), chain_api: ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?), collation_generation: CollationGenerationSubsystem::new(Metrics::register(registry)?), - collator_protocol: { - let side = ProtocolSide::Validator { - keystore: keystore.clone(), - eviction_policy: Default::default(), - metrics: Metrics::register(registry)?, - }; - CollatorProtocolSubsystem::new(side) - }, + collator_protocol: CollatorProtocolSubsystem::new(ProtocolSide::Validator { + keystore: keystore.clone(), + eviction_policy: Default::default(), + metrics: Metrics::register(registry)?, + }), network_bridge: NetworkBridgeSubsystem::new( network_service.clone(), - authority_discovery_service, - request_multiplexer, + authority_discovery_service.clone(), Box::new(network_service.clone()), Metrics::register(registry)?, ), provisioner: ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?), - runtime_api: RuntimeApiSubsystem::new(runtime_client, Metrics::register(registry)?, spawner), - statement_distribution: StatementDistributionSubsystem::new(keystore.clone(), Metrics::register(registry)?), + runtime_api: RuntimeApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?, spawner.clone()), + statement_distribution: StatementDistributionSubsystem::new( + keystore.clone(), + statement_req_receiver, + Metrics::register(registry)?, + ), approval_distribution: ApprovalDistributionSubsystem::new(Metrics::register(registry)?), approval_voting: ApprovalVotingSubsystem::with_config( approval_voting_config, - parachains_db, + parachains_db.clone(), + keystore.clone(), + Box::new(network_service.clone()), + Metrics::register(registry)?, + ), + gossip_support: GossipSupportSubsystem::new(keystore.clone()), + dispute_coordinator: DisputeCoordinatorSubsystem::new( + parachains_db.clone(), + dispute_coordinator_config, + keystore.clone(), + ), + dispute_participation: DisputeParticipationSubsystem::new(), + dispute_distribution: DisputeDistributionSubsystem::new( keystore.clone(), - Box::new(network_service), + dispute_req_receiver, + authority_discovery_service.clone(), Metrics::register(registry)?, ), - gossip_support: GossipSupportSubsystem::new(keystore), + chain_selection: ChainSelectionSubsystem::new(chain_selection_config, parachains_db), }; Ok(all_subsystems) } @@ -203,10 +250,10 @@ where /// would do. pub trait OverseerGen { /// Overwrite the full generation of the overseer, including the subsystems. - fn generate( + fn generate<'a, Spawner, RuntimeClient>( &self, - args: OverseerGenArgs, - ) -> Result<(Overseer>, OverseerHandler), Error> + args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, @@ -224,10 +271,10 @@ pub trait OverseerGen { pub struct RealOverseerGen; impl OverseerGen for RealOverseerGen { - fn generate( + fn generate<'a, Spawner, RuntimeClient>( &self, - args: OverseerGenArgs, - ) -> Result<(Overseer>, OverseerHandler), Error> + args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, @@ -236,7 +283,7 @@ impl OverseerGen for RealOverseerGen { let spawner = args.spawner.clone(); let leaves = args.leaves.clone(); let runtime_client = args.runtime_client.clone(); - let registry = args.registry; + let registry = args.registry.clone(); let all_subsystems = create_default_subsystems::(args)?; diff --git a/bin/rialto/node/src/parachains_db.rs b/bin/rialto/node/src/parachains_db.rs index aa70d45cd73b8..976191fc80788 100644 --- a/bin/rialto/node/src/parachains_db.rs +++ b/bin/rialto/node/src/parachains_db.rs @@ -20,11 +20,13 @@ use {kvdb::KeyValueDB, std::io, std::path::PathBuf, std::sync::Arc}; mod columns { - pub const NUM_COLUMNS: u32 = 3; + pub const NUM_COLUMNS: u32 = 5; pub const COL_AVAILABILITY_DATA: u32 = 0; pub const COL_AVAILABILITY_META: u32 = 1; pub const COL_APPROVAL_DATA: u32 = 2; + pub const COL_CHAIN_SELECTION_DATA: u32 = 3; + pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4; } /// Columns used by different subsystems. @@ -36,6 +38,10 @@ pub struct ColumnsConfig { pub col_availability_meta: u32, /// The column used by approval voting for data. pub col_approval_data: u32, + /// The column used by chain selection for data. + pub col_chain_selection_data: u32, + /// The column used by dispute coordinator for data. + pub col_dispute_coordinator_data: u32, } /// The real columns used by the parachains DB. @@ -43,6 +49,8 @@ pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig { col_availability_data: columns::COL_AVAILABILITY_DATA, col_availability_meta: columns::COL_AVAILABILITY_META, col_approval_data: columns::COL_APPROVAL_DATA, + col_chain_selection_data: columns::COL_CHAIN_SELECTION_DATA, + col_dispute_coordinator_data: columns::COL_DISPUTE_COORDINATOR_DATA, }; /// The cache size for each column, in megabytes. diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 71ab93d85893c..dd7aea1b9cba5 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -26,34 +26,51 @@ use crate::overseer::{OverseerGen, OverseerGenArgs}; -use polkadot_network_bridge::RequestMultiplexer; use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; use polkadot_node_core_av_store::Config as AvailabilityConfig; use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; -use polkadot_overseer::{BlockInfo, OverseerHandler}; +use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; +use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; +use polkadot_node_network_protocol::request_response::IncomingRequest; +use polkadot_overseer::BlockInfo; use polkadot_primitives::v1::BlockId; use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::ExecutorProvider; -use sc_executor::{native_executor_instance, NativeExecutionDispatch}; +use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; use sc_service::{config::PrometheusConfig, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_api::{ConstructRuntimeApi, HeaderT}; -use sp_blockchain::HeaderBackend; use sp_consensus::SelectChain; use sp_runtime::traits::{BlakeTwo256, Block as BlockT}; use std::{sync::Arc, time::Duration}; use substrate_prometheus_endpoint::Registry; -pub use sc_executor::NativeExecutor; +pub use { + polkadot_overseer::{Handle, Overseer, OverseerHandle}, + polkadot_primitives::v1::ParachainHost, + sc_client_api::AuxStore, + sp_authority_discovery::AuthorityDiscoveryApi, + sp_blockchain::HeaderBackend, + sp_consensus_babe::BabeApi, +}; + +pub type Executor = NativeElseWasmExecutor; // Our native executor instance. -native_executor_instance!( - pub Executor, - rialto_runtime::api::dispatch, - rialto_runtime::native_version, - frame_benchmarking::benchmarking::HostFunctions, -); +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + rialto_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + rialto_runtime::native_version() + } +} #[derive(thiserror::Error, Debug)] pub enum Error { @@ -153,13 +170,13 @@ pub fn new_partial( FullClient, FullBackend, FullSelectChain, - sp_consensus::DefaultImportQueue, + sc_consensus::DefaultImportQueue, FullTransactionPool, ( impl Fn( sc_rpc::DenyUnsafe, sc_rpc::SubscriptionTaskExecutor, - ) -> jsonrpc_core::IoHandler, + ) -> Result, sc_service::Error>, (FullBabeBlockImport, FullGrandpaLink, FullBabeLink), sc_finality_grandpa::SharedVoterState, std::time::Duration, @@ -172,7 +189,7 @@ where RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, >::RuntimeApi: RequiredApiCollection>, - Executor: NativeExecutionDispatch + 'static, + ExecutorDispatch: NativeExecutionDispatch + 'static, { set_prometheus_registry(config)?; @@ -187,9 +204,16 @@ where }) .transpose()?; + let executor = NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + ); + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, )?; let client = Arc::new(client); @@ -260,7 +284,7 @@ where move |deny_unsafe, subscription_executor: sc_rpc::SubscriptionTaskExecutor| - -> jsonrpc_core::IoHandler { + -> Result, sc_service::Error> { use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; use substrate_frame_rpc_system::{FullSystem, SystemApi}; @@ -289,7 +313,7 @@ where finality_proof_provider, ))); - io + Ok(io) } }; @@ -314,7 +338,7 @@ where pub struct NewFull { pub task_manager: TaskManager, pub client: C, - pub overseer_handler: Option, + pub overseer_handle: Option, pub network: Arc::Hash>>, pub rpc_handlers: sc_service::RpcHandlers, pub backend: Arc, @@ -332,7 +356,7 @@ where RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, >::RuntimeApi: RequiredApiCollection>, - Executor: NativeExecutionDispatch + 'static, + ExecutorDispatch: NativeExecutionDispatch + 'static, { let best_block = select_chain.best_chain().await?; @@ -381,7 +405,7 @@ where RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, >::RuntimeApi: RequiredApiCollection>, - Executor: NativeExecutionDispatch + 'static, + ExecutorDispatch: NativeExecutionDispatch + 'static, { let is_collator = false; @@ -426,20 +450,23 @@ where config.network.extra_sets.extend(peer_sets_info(is_authority)); } - config - .network - .request_response_protocols - .push(sc_finality_grandpa_warp_sync::request_response_config_for_chain( - &config, - task_manager.spawn_handle(), - backend.clone(), - import_setup.1.shared_authority_set().clone(), - )); - let request_multiplexer = { - let (multiplexer, configs) = RequestMultiplexer::new(); - config.network.request_response_protocols.extend(configs); - multiplexer - }; + let (pov_req_receiver, cfg) = IncomingRequest::get_config_receiver(); + config.network.request_response_protocols.push(cfg); + let (chunk_req_receiver, cfg) = IncomingRequest::get_config_receiver(); + config.network.request_response_protocols.push(cfg); + let (collation_req_receiver, cfg) = IncomingRequest::get_config_receiver(); + config.network.request_response_protocols.push(cfg); + let (available_data_req_receiver, cfg) = IncomingRequest::get_config_receiver(); + config.network.request_response_protocols.push(cfg); + let (statement_req_receiver, cfg) = IncomingRequest::get_config_receiver(); + config.network.request_response_protocols.push(cfg); + let (dispute_req_receiver, cfg) = IncomingRequest::get_config_receiver(); + config.network.request_response_protocols.push(cfg); + + let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( + backend.clone(), + import_setup.1.shared_authority_set().clone(), + )); let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, @@ -449,6 +476,7 @@ where import_queue, on_demand: None, block_announce_validator_builder: None, + warp_sync: Some(warp_sync), })?; if config.offchain_worker.enabled { @@ -483,6 +511,15 @@ where }, }; + let chain_selection_config = ChainSelectionConfig { + col_data: crate::parachains_db::REAL_COLUMNS.col_chain_selection_data, + stagnant_check_interval: polkadot_node_core_chain_selection::StagnantCheckInterval::never(), + }; + + let dispute_coordinator_config = DisputeCoordinatorConfig { + col_data: crate::parachains_db::REAL_COLUMNS.col_dispute_coordinator_data, + }; + let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { config, backend: backend.clone(), @@ -545,8 +582,8 @@ where let local_keystore = keystore_container.local_keystore(); let maybe_params = local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k))); - let overseer_handler = if let Some((authority_discovery_service, keystore)) = maybe_params { - let (overseer, overseer_handler) = + let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params { + let (overseer, overseer_handle) = overseer_gen.generate::(OverseerGenArgs { leaves: active_leaves, keystore, @@ -556,19 +593,27 @@ where approval_voting_config, network_service: network.clone(), authority_discovery_service, - request_multiplexer, registry: prometheus_registry.as_ref(), spawner, candidate_validation_config, + available_data_req_receiver, + chain_selection_config, + chunk_req_receiver, + collation_req_receiver, + dispute_coordinator_config, + dispute_req_receiver, + pov_req_receiver, + statement_req_receiver, })?; - let overseer_handler_clone = overseer_handler.clone(); + let handle = Handle::Connected(overseer_handle.clone()); + let handle_clone = handle.clone(); task_manager.spawn_essential_handle().spawn_blocking( "overseer", Box::pin(async move { use futures::{pin_mut, select, FutureExt}; - let forward = polkadot_overseer::forward_events(overseer_client, overseer_handler_clone); + let forward = polkadot_overseer::forward_events(overseer_client, handle_clone); let forward = forward.fuse(); let overseer_fut = overseer.run().fuse(); @@ -584,7 +629,7 @@ where }), ); - Some(overseer_handler) + Some(handle) } else { None }; @@ -601,7 +646,7 @@ where ); let client_clone = client.clone(); - let overseer_handler = overseer_handler + let overseer_handle = overseer_handle .as_ref() .ok_or(Error::AuthoritiesRequireRealOverseer)? .clone(); @@ -616,11 +661,11 @@ where justification_sync_link: network.clone(), create_inherent_data_providers: move |parent, ()| { let client_clone = client_clone.clone(); - let overseer_handler = overseer_handler.clone(); + let overseer_handle = overseer_handle.clone(); async move { let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create( &*client_clone, - overseer_handler, + overseer_handle, parent, ) .await @@ -705,7 +750,7 @@ where Ok(NewFull { task_manager, client, - overseer_handler, + overseer_handle, network, rpc_handlers, backend, diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 4c0e51ad3c903..8f4f4ef30e7ab 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -12,7 +12,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = hex-literal = "0.3" libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } -serde = { version = "1.0.124", optional = true, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8e7f3f2e421f9..b440000ae6b7b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -167,7 +167,7 @@ parameter_types! { impl frame_system::Config for Runtime { /// The basic call filter to use in dispatchable. - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. @@ -244,6 +244,7 @@ impl pallet_babe::Config for Runtime { >::IdentificationTuple; type HandleEquivocation = (); + type DisabledValidators = (); type WeightInfo = (); } @@ -293,7 +294,7 @@ impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); type Call = Call; - type CallFilter = (); + type CallFilter = frame_support::traits::Everything; type EncodedCall = crate::millau_messages::FromMillauEncodedCall; type SourceChainAccountId = bp_millau::AccountId; type TargetChainAccountPublic = MultiSigner; @@ -447,7 +448,13 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } -impl pallet_authority_discovery::Config for Runtime {} +parameter_types! { + pub const MaxAuthorities: u32 = 10; +} + +impl pallet_authority_discovery::Config for Runtime { + type MaxAuthorities = MaxAuthorities; +} parameter_types! { /// This is a pretty unscientific cap. @@ -572,17 +579,17 @@ construct_runtime!( // Parachain modules. ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin}, - ParachainsConfiguration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config}, + Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config}, Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage}, Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent}, - Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Call, Storage}, + Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage}, Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config}, Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, Dmp: polkadot_runtime_parachains::dmp::{Pallet, Call, Storage}, Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event}, - Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, - SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Call, Storage}, + Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, + SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, // Parachain Onboarding Pallets Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event}, @@ -911,6 +918,10 @@ impl_runtime_apis! { } impl fg_primitives::GrandpaApi for Runtime { + fn current_set_id() -> fg_primitives::SetId { + Grandpa::current_set_id() + } + fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } @@ -989,6 +1000,32 @@ impl_runtime_apis! { #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + + use pallet_bridge_currency_exchange::benchmarking::Pallet as BridgeCurrencyExchangeBench; + use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; + + let mut list = Vec::::new(); + + list_benchmark!(list, extra, pallet_bridge_eth_poa, BridgeRialtoPoa); + list_benchmark!( + list, + extra, + pallet_bridge_currency_exchange, BridgeCurrencyExchangeBench:: + ); + list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); + list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa); + + let storage_info = AllPalletsWithSystem::storage_info(); + + return (list, storage_info) + } + fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig, ) -> Result, sp_runtime::RuntimeString> { diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 47fc6722a19e1..ba7b01ea116e8 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -59,6 +59,7 @@ impl parachains_hrmp::Config for Runtime { impl parachains_inclusion::Config for Runtime { type Event = Event; type RewardValidators = RewardValidators; + type DisputesHandler = (); } impl parachains_initializer::Config for Runtime { diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 290e1a9bc9526..550467f5d6fe7 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -371,7 +371,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index b334d862d8577..698d3842a0cd1 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -36,7 +36,7 @@ use codec::Encode; use frame_support::{ dispatch::Dispatchable, ensure, - traits::{Filter, Get}, + traits::{Contains, Get}, weights::{extract_actual_weight, GetDispatchInfo}, }; use frame_system::RawOrigin; @@ -77,7 +77,7 @@ pub mod pallet { /// /// The pallet will filter all incoming calls right before they're dispatched. If this filter /// rejects the call, special event (`Event::MessageCallRejected`) is emitted. - type CallFilter: Filter<>::Call>; + type CallFilter: Contains<>::Call>; /// The type that is used to wrap the `Self::Call` when it is moved over bridge. /// /// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure @@ -252,7 +252,7 @@ impl, I: 'static> MessageDispatch }; // filter the call - if !T::CallFilter::filter(&call) { + if !T::CallFilter::contains(&call) { log::trace!( target: "runtime::bridge-dispatch", "Message {:?}/{:?}: the call ({:?}) is rejected by filter", @@ -491,7 +491,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); @@ -523,8 +523,8 @@ mod tests { pub struct TestCallFilter; - impl Filter for TestCallFilter { - fn filter(call: &Call) -> bool { + impl Contains for TestCallFilter { + fn contains(call: &Call) -> bool { !matches!(*call, Call::System(frame_system::Call::fill_block(_))) } } diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 90c143dc932ff..00c10d3cc3e0f 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -73,7 +73,7 @@ impl frame_system::Config for TestRuntime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 363594c35f33d..dcbae4e60f9bc 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -70,7 +70,7 @@ impl frame_system::Config for TestRuntime { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type DbWeight = (); type BlockWeights = (); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 88ec92ff03241..84496393d562d 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -112,7 +112,7 @@ impl frame_system::Config for TestRuntime { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index eef336ffd8d6d..011b50ad595dd 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -150,7 +150,7 @@ mod tests { type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index c95f413b726f7..ed5c1b7cee316 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -81,7 +81,7 @@ impl frame_system::Config for TestRuntime { type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); - type BaseCallFilter = (); + type BaseCallFilter = frame_support::traits::Everything; type SystemWeightInfo = (); type BlockWeights = (); type BlockLength = (); diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index c4f30aaf6b741..a0630fa8a9ff0 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -16,8 +16,8 @@ fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.5.1", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.10.0", default-features = false, features = ["primitive-types"] } -serde = { version = "1.0.101", optional = true, features = ["derive"] } +parity-util-mem = { version = "0.10", default-features = false, features = ["primitive-types"] } +serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 2dc5ae8032f52..af0dcf904f227 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bitvec = { version = "0.20", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" -serde = { version = "1.0.101", optional = true, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index b5f80ffdcd3c2..23ea4b80738ea 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -332,7 +332,7 @@ mod tests { // then assert!(format!("{:?}", call_hex).starts_with( - "0x11030000000001000000b0d60f000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + "0x11030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" )) } diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index a2e049f24f08e..36a4806976ef6 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -102,6 +102,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x01000000b0d60f000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x0100000010f108000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 68b332b0696e0..04ce386ef09a9 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -320,7 +320,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 1038000, + weight: 576000, origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, call: hex!("0001081234").to_vec(), @@ -360,7 +360,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 1038000, + weight: 576000, origin: CallOrigin::TargetAccount( sp_keyring::AccountKeyring::Alice.to_account_id(), sp_keyring::AccountKeyring::Bob.into(), diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 807080dcc8fce..90e775b784eb4 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -34,11 +34,11 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 60fe63230a8d7..84db77ec6dfd5 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -19,13 +19,13 @@ use codec::{Codec, Encode}; use frame_support::weights::WeightToFeePolynomial; use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; use num_traits::Zero; +use sc_transaction_pool_api::TransactionStatus; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, traits::{Block as BlockT, Dispatchable, Member}, EncodedJustification, }; -use sp_transaction_pool::TransactionStatus; use std::{fmt::Debug, time::Duration}; /// Substrate-based chain from minimal relay-client point of view. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 31f4a19d8ffaf..be483243df0be 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -18,7 +18,7 @@ use crate::chain::{Chain, ChainWithBalances, TransactionStatusOf}; use crate::rpc::Substrate; -use crate::{ConnectionParams, Error, HeaderIdOf, Result}; +use crate::{ConnectionParams, Error, HashOf, HeaderIdOf, Result}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; @@ -61,7 +61,7 @@ pub struct Client { /// Substrate RPC client. client: Arc, /// Genesis block hash. - genesis_hash: C::Hash, + genesis_hash: HashOf, /// If several tasks are submitting their transactions simultaneously using `submit_signed_extrinsic` /// method, they may get the same transaction nonce. So one of transactions will be rejected /// from the pool. This lock is here to prevent situations like that. diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 6c5bf16baa63c..093cc50f052a6 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -39,10 +39,12 @@ pub trait Environment: Send + Sync + 'static { fn now(&self) -> Instant { Instant::now() } + /// Sleep given amount of time. async fn sleep(&mut self, duration: Duration) { async_std::task::sleep(duration).await } + /// Abort current process. Called when guard condition check fails. async fn abort(&mut self) { std::process::abort(); diff --git a/relays/headers/src/sync.rs b/relays/headers/src/sync.rs index cd5ab0906fd54..7e3d9020290f4 100644 --- a/relays/headers/src/sync.rs +++ b/relays/headers/src/sync.rs @@ -131,13 +131,13 @@ impl HeadersSync

{ } // if queue is empty and best header on target is > than best header on source, - // then we shoud reorg + // then we shoud reorganization let best_queued_number = self.headers.best_queued_number(); if best_queued_number.is_zero() && source_best_number < target_best_header.0 { return Some(source_best_number); } - // we assume that there were no reorgs if we have already downloaded best header + // we assume that there were no reorganizations if we have already downloaded best header let best_downloaded_number = std::cmp::max( std::cmp::max(best_queued_number, self.headers.best_synced_number()), target_best_header.0, diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index c373f41520070..a557eca6a2306 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -38,13 +38,13 @@ use std::{ /// When we submit headers to target node, but see no updates of best /// source block known to target node during STALL_SYNC_TIMEOUT seconds, -/// we consider that our headers are rejected because there has been reorg in target chain. -/// This reorg could invalidate our knowledge about sync process (i.e. we have asked if -/// HeaderA is known to target, but then reorg happened and the answer is different +/// we consider that our headers are rejected because there has been reorganization in target chain. +/// This reorganization could invalidate our knowledge about sync process (i.e. we have asked if +/// HeaderA is known to target, but then reorganization happened and the answer is different /// now) => we need to reset sync. /// The other option is to receive **EVERY** best target header and check if it is /// direct child of previous best header. But: (1) subscription doesn't guarantee that -/// the subscriber will receive every best header (2) reorg won't always lead to sync +/// the subscriber will receive every best header (2) reorganization won't always lead to sync /// stall and restart is a heavy operation (we forget all in-memory headers). const STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(5 * 60); /// Delay after we have seen update of best source header at target node, From 19b2348a4369d3d80377d6bdc9cff30f9342b535 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Sep 2021 15:04:42 +0300 Subject: [PATCH 0575/1210] Fix/ignore clippy warnings (#1157) * fix/ignore clippy * --locked check && test * RUSTC_WRAPPER="" for clippy-nightly, check-nightly, test-nightly --- bin/rialto-parachain/node/src/cli.rs | 2 -- bin/rialto-parachain/node/src/command.rs | 10 +++++----- bin/rialto-parachain/node/src/service.rs | 10 ++++++---- bin/rialto-parachain/runtime/src/lib.rs | 10 +++++----- bin/rialto/node/src/overseer.rs | 22 ++++++++++----------- bin/rialto/node/src/service.rs | 2 +- modules/ethereum/src/lib.rs | 12 +---------- modules/token-swap/src/lib.rs | 1 + primitives/chain-kusama/src/lib.rs | 2 +- primitives/ethereum-poa/src/lib.rs | 2 ++ primitives/runtime/src/lib.rs | 4 ++-- relays/bin-substrate/src/cli/swap_tokens.rs | 16 +++++++++------ relays/headers/src/headers.rs | 9 --------- 13 files changed, 45 insertions(+), 57 deletions(-) diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 865d8eb92bea2..3a55da24d9092 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -15,8 +15,6 @@ // along with Parity Bridges Common. If not, see . use crate::chain_spec; -use cumulus_client_cli; -use sc_cli; use std::path::PathBuf; use structopt::StructOpt; diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index a37673a5b9bcb..a2cffd0fae74f 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -112,7 +112,7 @@ impl SubstrateCli for RelayChainCli { } fn load_spec(&self, id: &str) -> std::result::Result, String> { - polkadot_cli::Cli::from_iter([RelayChainCli::executable_name().to_string()].iter()).load_spec(id) + polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id) } fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion { @@ -120,7 +120,7 @@ impl SubstrateCli for RelayChainCli { } } -fn extract_genesis_wasm(chain_spec: &Box) -> Result> { +fn extract_genesis_wasm(chain_spec: &dyn sc_service::ChainSpec) -> Result> { let mut storage = chain_spec.build_storage()?; storage @@ -181,7 +181,7 @@ pub fn run() -> Result<()> { runner.sync_run(|config| { let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name().to_string()] + [RelayChainCli::executable_name()] .iter() .chain(cli.relaychain_args.iter()), ); @@ -225,7 +225,7 @@ pub fn run() -> Result<()> { builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); let _ = builder.init(); - let raw_wasm_blob = extract_genesis_wasm(&cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; + let raw_wasm_blob = extract_genesis_wasm(&*cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; let output_buf = if params.raw { raw_wasm_blob } else { @@ -259,7 +259,7 @@ pub fn run() -> Result<()> { let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name().to_string()] + [RelayChainCli::executable_name()] .iter() .chain(cli.relaychain_args.iter()), ); diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index a812358edf363..cbd10ca2aa218 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -68,6 +68,7 @@ impl NativeExecutionDispatch for ExecutorDispatch { /// /// Use this macro if you don't actually need the full service, but just the builder in order to /// be able to perform chain operations. +#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, build_import_queue: BIQ, @@ -123,7 +124,7 @@ where ); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - &config, + config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, )?; @@ -332,6 +333,7 @@ where } /// Build the import queue for the the parachain runtime. +#[allow(clippy::type_complexity)] pub fn parachain_build_import_queue( client: Arc>>, config: &Configuration, @@ -360,7 +362,7 @@ pub fn parachain_build_import_queue( Ok((time, slot)) }, - registry: config.prometheus_registry().clone(), + registry: config.prometheus_registry(), can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), spawner: &task_manager.spawn_essential_handle(), telemetry, @@ -399,7 +401,7 @@ pub async fn start_node( task_manager.spawn_handle(), client.clone(), transaction_pool, - prometheus_registry.clone(), + prometheus_registry, telemetry.clone(), ); @@ -444,7 +446,7 @@ pub async fn start_node( block_import: client.clone(), relay_chain_client: relay_chain_node.client.clone(), relay_chain_backend: relay_chain_node.backend.clone(), - para_client: client.clone(), + para_client: client, backoff_authoring_blocks: Option::<()>::None, sync_oracle, keystore, diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 58f592bea8cef..613c444a28f27 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -263,10 +263,10 @@ impl pallet_timestamp::Config for Runtime { } parameter_types! { - pub const ExistentialDeposit: u128 = 1 * MILLIUNIT; - pub const TransferFee: u128 = 1 * MILLIUNIT; - pub const CreationFee: u128 = 1 * MILLIUNIT; - pub const TransactionByteFee: u128 = 1 * MICROUNIT; + pub const ExistentialDeposit: u128 = MILLIUNIT; + pub const TransferFee: u128 = MILLIUNIT; + pub const CreationFee: u128 = MILLIUNIT; + pub const TransactionByteFee: u128 = MICROUNIT; pub const MaxLocks: u32 = 50; pub const MaxReserves: u32 = 50; } @@ -671,7 +671,7 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { .create_inherent_data() .expect("Could not create the timestamp inherent data"); - inherent_data.check_extrinsics(&block) + inherent_data.check_extrinsics(block) } } diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs index ff82db8b0e57f..3742bcdc8927d 100644 --- a/bin/rialto/node/src/overseer.rs +++ b/bin/rialto/node/src/overseer.rs @@ -110,7 +110,7 @@ where /// /// A convenience for usage with malus, to avoid /// repetitive code across multiple behavior strain implementations. -pub fn create_default_subsystems<'a, Spawner, RuntimeClient>( +pub fn create_default_subsystems( OverseerGenArgs { keystore, runtime_client, @@ -130,7 +130,7 @@ pub fn create_default_subsystems<'a, Spawner, RuntimeClient>( chain_selection_config, dispute_coordinator_config, .. - }: OverseerGenArgs<'a, Spawner, RuntimeClient>, + }: OverseerGenArgs<'_, Spawner, RuntimeClient>, ) -> Result< AllSubsystems< CandidateValidationSubsystem, @@ -212,7 +212,7 @@ where Metrics::register(registry)?, ), provisioner: ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?), - runtime_api: RuntimeApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?, spawner.clone()), + runtime_api: RuntimeApiSubsystem::new(runtime_client, Metrics::register(registry)?, spawner), statement_distribution: StatementDistributionSubsystem::new( keystore.clone(), statement_req_receiver, @@ -223,7 +223,7 @@ where approval_voting_config, parachains_db.clone(), keystore.clone(), - Box::new(network_service.clone()), + Box::new(network_service), Metrics::register(registry)?, ), gossip_support: GossipSupportSubsystem::new(keystore.clone()), @@ -234,9 +234,9 @@ where ), dispute_participation: DisputeParticipationSubsystem::new(), dispute_distribution: DisputeDistributionSubsystem::new( - keystore.clone(), + keystore, dispute_req_receiver, - authority_discovery_service.clone(), + authority_discovery_service, Metrics::register(registry)?, ), chain_selection: ChainSelectionSubsystem::new(chain_selection_config, parachains_db), @@ -250,9 +250,9 @@ where /// would do. pub trait OverseerGen { /// Overwrite the full generation of the overseer, including the subsystems. - fn generate<'a, Spawner, RuntimeClient>( + fn generate( &self, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, @@ -271,9 +271,9 @@ pub trait OverseerGen { pub struct RealOverseerGen; impl OverseerGen for RealOverseerGen { - fn generate<'a, Spawner, RuntimeClient>( + fn generate( &self, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, @@ -283,7 +283,7 @@ impl OverseerGen for RealOverseerGen { let spawner = args.spawner.clone(); let leaves = args.leaves.clone(); let runtime_client = args.runtime_client.clone(); - let registry = args.registry.clone(); + let registry = args.registry; let all_subsystems = create_default_subsystems::(args)?; diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index dd7aea1b9cba5..19743933c1eaf 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -605,7 +605,7 @@ where pov_req_receiver, statement_req_receiver, })?; - let handle = Handle::Connected(overseer_handle.clone()); + let handle = Handle::Connected(overseer_handle); let handle_clone = handle.clone(); task_manager.spawn_essential_handle().spawn_blocking( diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index e1239c049401b..88a35f365e40b 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -556,6 +556,7 @@ pub mod pallet { StorageMap<_, Identity, H256, AuraScheduledChange>; #[pallet::genesis_config] + #[cfg_attr(feature = "std", derive(Default))] pub struct GenesisConfig { /// PoA header to start with. pub initial_header: AuraHeader, @@ -565,17 +566,6 @@ pub mod pallet { pub initial_validators: Vec

, } - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - initial_header: Default::default(), - initial_difficulty: Default::default(), - initial_validators: Default::default(), - } - } - } - #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 4c56ec5aa969d..5528a25296d50 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -192,6 +192,7 @@ pub mod pallet { /// rules will lead to losing message fees for this and other transactions + losing fees for message /// transfer. #[pallet::weight(0)] + #[allow(clippy::too_many_arguments)] pub fn create_swap( origin: OriginFor, swap: TokenSwapOf, diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 4dec9cd2a0ece..f4c448e41c60f 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -77,7 +77,7 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. -pub const SESSION_LENGTH: BlockNumber = 1 * time_units::HOURS; +pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; /// Name of the With-Polkadot messages pallet instance in the Kusama runtime. pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index b2e00760c01d6..657038a25f33b 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -458,6 +458,8 @@ impl PartialEq for Bloom { } } +// there's no default for [_; 256], but clippy still complains +#[allow(clippy::derivable_impls)] impl Default for Bloom { fn default() -> Self { Bloom([0; 256]) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 8d4e658b1e863..aee894aceefca 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -216,9 +216,9 @@ pub fn storage_map_final_key_identity(pallet_prefix: &str, map_name: &str, key_h /// Copypaste 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(':' as u8); + buffer.push(b':'); buffer.extend_from_slice(parameter_name.as_bytes()); - buffer.push(':' as u8); + buffer.push(b':'); buffer.push(0); StorageKey(sp_io::hashing::twox_128(&buffer).to_vec()) } diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index b9c44a4acc85e..264b98e948ff9 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -16,6 +16,10 @@ //! Tokens swap using token-swap bridge pallet. +// TokenSwapBalances fields are never directly accessed, but the whole struct is printed +// to show token swap progress +#![allow(dead_code)] + use codec::Encode; use num_traits::One; use rand::random; @@ -436,7 +440,7 @@ impl SwapTokens { // prepare token swap intention Ok(bp_token_swap::TokenSwap { - swap_type: self.prepare_token_swap_type(&source_client).await?, + swap_type: self.prepare_token_swap_type(source_client).await?, source_balance_at_this_chain, source_account_at_this_chain: source_account_at_this_chain.clone(), target_balance_at_bridged_chain, @@ -498,26 +502,26 @@ async fn read_account_balances anyhow::Result, BalanceOf>> { Ok(TokenSwapBalances { source_account_at_this_chain_balance: read_account_balance( - &source_client, + source_client, &accounts.source_account_at_this_chain, ) .await?, source_account_at_bridged_chain_balance: read_account_balance( - &target_client, + target_client, &accounts.source_account_at_bridged_chain, ) .await?, target_account_at_bridged_chain_balance: read_account_balance( - &target_client, + target_client, &accounts.target_account_at_bridged_chain, ) .await?, target_account_at_this_chain_balance: read_account_balance( - &source_client, + source_client, &accounts.target_account_at_this_chain, ) .await?, - swap_account_balance: read_account_balance(&source_client, &accounts.swap_account).await?, + swap_account_balance: read_account_balance(source_client, &accounts.swap_account).await?, }) } diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs index b9095e1931099..d4f3d77d79cea 100644 --- a/relays/headers/src/headers.rs +++ b/relays/headers/src/headers.rs @@ -82,15 +82,6 @@ pub struct QueuedHeaders { prune_border: P::Number, } -/// Header completion data. -#[derive(Debug)] -struct HeaderCompletion { - /// Last time when we tried to upload completion data to target node, if ever. - pub last_upload_time: Option, - /// Completion data. - pub completion: Completion, -} - impl Default for QueuedHeaders

{ fn default() -> Self { QueuedHeaders { From 4bc23c1d4c6e222c149e9d5957ca2debae0b6016 Mon Sep 17 00:00:00 2001 From: hacpy Date: Fri, 24 Sep 2021 19:29:31 +0800 Subject: [PATCH 0576/1210] Match substrate's fmt (#1148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Alter gitlab. * Use substrate's rustfmt.toml * cargo +nightly fmt --all * Fix spellcheck. * cargo +nightly fmt --all * format. * Fix spellcheck and fmt * fmt? * Fix spellcheck Co-authored-by: Tomasz Drwięga --- bin/millau/node/src/chain_spec.rs | 21 +- bin/millau/node/src/command.rs | 65 +- bin/millau/node/src/service.rs | 247 ++++---- bin/millau/runtime/src/lib.rs | 71 ++- bin/millau/runtime/src/rialto_messages.rs | 58 +- bin/rialto-parachain/node/src/chain_spec.rs | 7 +- bin/rialto-parachain/node/src/cli.rs | 11 +- bin/rialto-parachain/node/src/command.rs | 100 +-- bin/rialto-parachain/node/src/service.rs | 123 ++-- bin/rialto-parachain/runtime/src/lib.rs | 40 +- bin/rialto/node/src/chain_spec.rs | 43 +- bin/rialto/node/src/command.rs | 71 +-- bin/rialto/node/src/overseer.rs | 22 +- bin/rialto/node/src/parachains_db.rs | 9 +- bin/rialto/node/src/service.rs | 210 +++---- bin/rialto/runtime/src/benches.rs | 3 +- bin/rialto/runtime/src/exchange.rs | 16 +- bin/rialto/runtime/src/kovan.rs | 31 +- bin/rialto/runtime/src/lib.rs | 122 ++-- bin/rialto/runtime/src/millau_messages.rs | 89 +-- bin/rialto/runtime/src/parachains.rs | 22 +- bin/rialto/runtime/src/rialto_poa.rs | 26 +- bin/runtime-common/src/messages.rs | 472 +++++++------- .../src/messages_benchmarking.rs | 32 +- modules/currency-exchange/src/benchmarking.rs | 9 +- modules/currency-exchange/src/lib.rs | 58 +- modules/dispatch/src/lib.rs | 341 ++++++---- modules/ethereum-contract-builtin/src/lib.rs | 46 +- modules/ethereum/src/benchmarking.rs | 4 +- modules/ethereum/src/error.rs | 3 +- modules/ethereum/src/finality.rs | 89 +-- modules/ethereum/src/import.rs | 96 ++- modules/ethereum/src/lib.rs | 191 +++--- modules/ethereum/src/mock.rs | 19 +- modules/ethereum/src/test_utils.rs | 29 +- modules/ethereum/src/validators.rs | 107 ++-- modules/ethereum/src/verification.rs | 218 ++++--- modules/grandpa/src/benchmarking.rs | 3 +- modules/grandpa/src/lib.rs | 189 +++--- modules/messages/src/benchmarking.rs | 33 +- modules/messages/src/inbound_lane.rs | 55 +- modules/messages/src/instant_payments.rs | 57 +- modules/messages/src/lib.rs | 595 ++++++++++-------- modules/messages/src/mock.rs | 78 +-- modules/messages/src/outbound_lane.rs | 85 ++- modules/messages/src/weights_ext.rs | 108 ++-- modules/shift-session-manager/src/lib.rs | 32 +- modules/token-swap/src/lib.rs | 289 +++++---- modules/token-swap/src/mock.rs | 4 +- primitives/chain-kusama/src/lib.rs | 25 +- primitives/chain-millau/src/lib.rs | 46 +- primitives/chain-polkadot/src/lib.rs | 29 +- primitives/chain-rialto/src/lib.rs | 43 +- primitives/chain-rococo/src/lib.rs | 34 +- primitives/chain-westend/src/lib.rs | 26 +- primitives/chain-wococo/src/lib.rs | 18 +- primitives/currency-exchange/src/lib.rs | 4 +- primitives/ethereum-poa/src/lib.rs | 53 +- primitives/ethereum-poa/src/signatures.rs | 17 +- primitives/header-chain/src/justification.rs | 57 +- primitives/header-chain/src/lib.rs | 12 +- .../tests/implementation_match.rs | 35 +- primitives/message-dispatch/src/lib.rs | 7 +- primitives/messages/src/lib.rs | 69 +- primitives/messages/src/source_chain.rs | 14 +- primitives/messages/src/target_chain.rs | 22 +- primitives/polkadot-core/src/lib.rs | 65 +- primitives/runtime/src/chain.rs | 16 +- primitives/runtime/src/lib.rs | 68 +- primitives/runtime/src/messages.rs | 4 +- primitives/runtime/src/storage_proof.rs | 8 +- primitives/test-utils/src/keyring.rs | 11 +- primitives/test-utils/src/lib.rs | 62 +- primitives/token-swap/src/lib.rs | 32 +- relays/bin-ethereum/src/ethereum_client.rs | 130 ++-- .../src/ethereum_deploy_contract.rs | 37 +- relays/bin-ethereum/src/ethereum_exchange.rs | 103 ++- .../src/ethereum_exchange_submit.rs | 21 +- relays/bin-ethereum/src/ethereum_sync_loop.rs | 81 +-- relays/bin-ethereum/src/instances.rs | 20 +- relays/bin-ethereum/src/main.rs | 119 ++-- relays/bin-ethereum/src/rialto_client.rs | 79 ++- .../bin-ethereum/src/substrate_sync_loop.rs | 30 +- relays/bin-ethereum/src/substrate_types.rs | 10 +- relays/bin-substrate/src/chains/kusama.rs | 60 +- .../src/chains/kusama_headers_to_polkadot.rs | 47 +- .../src/chains/kusama_messages_to_polkadot.rs | 72 ++- relays/bin-substrate/src/chains/millau.rs | 57 +- .../src/chains/millau_headers_to_rialto.rs | 21 +- .../src/chains/millau_messages_to_rialto.rs | 64 +- relays/bin-substrate/src/chains/mod.rs | 34 +- relays/bin-substrate/src/chains/polkadot.rs | 60 +- .../src/chains/polkadot_headers_to_kusama.rs | 16 +- .../src/chains/polkadot_messages_to_kusama.rs | 72 ++- relays/bin-substrate/src/chains/rialto.rs | 55 +- .../src/chains/rialto_headers_to_millau.rs | 12 +- .../src/chains/rialto_messages_to_millau.rs | 64 +- relays/bin-substrate/src/chains/rococo.rs | 60 +- .../src/chains/rococo_headers_to_wococo.rs | 12 +- .../src/chains/rococo_messages_to_wococo.rs | 63 +- relays/bin-substrate/src/chains/westend.rs | 4 +- .../src/chains/westend_headers_to_millau.rs | 12 +- relays/bin-substrate/src/chains/wococo.rs | 60 +- .../src/chains/wococo_headers_to_rococo.rs | 18 +- .../src/chains/wococo_messages_to_rococo.rs | 63 +- .../bin-substrate/src/cli/derive_account.rs | 12 +- relays/bin-substrate/src/cli/encode_call.rs | 63 +- .../bin-substrate/src/cli/encode_message.rs | 12 +- relays/bin-substrate/src/cli/estimate_fee.rs | 36 +- relays/bin-substrate/src/cli/init_bridge.rs | 42 +- relays/bin-substrate/src/cli/mod.rs | 33 +- relays/bin-substrate/src/cli/relay_headers.rs | 21 +- .../src/cli/relay_headers_and_messages.rs | 240 ++++--- .../bin-substrate/src/cli/relay_messages.rs | 14 +- .../src/cli/resubmit_transactions.rs | 45 +- relays/bin-substrate/src/cli/send_message.rs | 44 +- relays/bin-substrate/src/cli/swap_tokens.rs | 149 +++-- relays/client-ethereum/src/client.rs | 101 +-- relays/client-ethereum/src/error.rs | 8 +- relays/client-ethereum/src/lib.rs | 13 +- relays/client-ethereum/src/rpc.rs | 4 +- relays/client-ethereum/src/sign.rs | 6 +- relays/client-kusama/src/lib.rs | 21 +- relays/client-kusama/src/runtime.rs | 8 +- relays/client-millau/src/lib.rs | 19 +- relays/client-polkadot/src/lib.rs | 21 +- relays/client-polkadot/src/runtime.rs | 4 +- relays/client-rialto/src/lib.rs | 15 +- relays/client-rococo/src/lib.rs | 21 +- relays/client-rococo/src/runtime.rs | 4 +- relays/client-substrate/src/chain.rs | 6 +- relays/client-substrate/src/client.rs | 152 +++-- relays/client-substrate/src/error.rs | 14 +- .../client-substrate/src/finality_source.rs | 31 +- relays/client-substrate/src/guard.rs | 33 +- relays/client-substrate/src/headers_source.rs | 48 +- relays/client-substrate/src/lib.rs | 32 +- .../src/metrics/float_storage_value.rs | 6 +- .../src/metrics/storage_proof_overhead.rs | 31 +- relays/client-wococo/src/lib.rs | 21 +- relays/client-wococo/src/runtime.rs | 4 +- relays/exchange/src/exchange.rs | 255 ++++---- relays/exchange/src/exchange_loop.rs | 76 +-- relays/finality/src/finality_loop.rs | 137 ++-- relays/finality/src/finality_loop_tests.rs | 111 ++-- relays/finality/src/lib.rs | 4 +- relays/headers/src/headers.rs | 449 +++++++------ relays/headers/src/sync.rs | 46 +- relays/headers/src/sync_loop.rs | 59 +- relays/headers/src/sync_loop_metrics.rs | 9 +- relays/headers/src/sync_loop_tests.rs | 46 +- relays/headers/src/sync_types.rs | 22 +- .../src/conversion_rate_update.rs | 85 ++- .../src/finality_pipeline.rs | 19 +- .../src/finality_target.rs | 33 +- .../src/headers_initialize.rs | 68 +- relays/lib-substrate-relay/src/helpers.rs | 10 +- .../lib-substrate-relay/src/messages_lane.rs | 77 ++- .../src/messages_source.rs | 120 ++-- .../src/messages_target.rs | 128 ++-- .../src/on_demand_headers.rs | 134 ++-- relays/messages/src/message_lane.rs | 6 +- relays/messages/src/message_lane_loop.rs | 115 ++-- relays/messages/src/message_race_delivery.rs | 343 +++++----- relays/messages/src/message_race_loop.rs | 62 +- relays/messages/src/message_race_receiving.rs | 42 +- relays/messages/src/message_race_strategy.rs | 123 ++-- relays/messages/src/metrics.rs | 26 +- relays/utils/src/initialize.rs | 15 +- relays/utils/src/lib.rs | 15 +- relays/utils/src/metrics.rs | 28 +- relays/utils/src/metrics/float_json_value.rs | 16 +- relays/utils/src/metrics/global.rs | 19 +- relays/utils/src/relay_loop.rs | 53 +- 174 files changed, 6100 insertions(+), 4967 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index ca47b39018d6f..c32291fb38581 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -16,8 +16,9 @@ use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeRialtoMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, - GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BridgeRialtoMessagesConfig, BridgeWestendGrandpaConfig, + GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, + WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -190,12 +191,8 @@ fn testnet_genesis( balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, - aura: AuraConfig { - authorities: Vec::new(), - }, - grandpa: GrandpaConfig { - authorities: Vec::new(), - }, + aura: AuraConfig { authorities: Vec::new() }, + grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: root_key }, session: SessionConfig { keys: initial_authorities @@ -220,9 +217,7 @@ fn testnet_genesis( #[test] fn derived_dave_account_is_as_expected() { let dave = get_account_id_from_seed::("Dave"); - let derived: AccountId = derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); - assert_eq!( - derived.to_string(), - "5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string() - ); + let derived: AccountId = + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); + assert_eq!(derived.to_string(), "5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string()); } diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 61786452e03e7..4285ecaced516 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -14,9 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{Cli, Subcommand}; -use crate::service; -use crate::service::new_partial; +use crate::{ + cli::{Cli, Subcommand}, + service, + service::new_partial, +}; use millau_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; @@ -75,7 +77,7 @@ pub fn run() -> sc_cli::Result<()> { )); match &cli.subcommand { - Some(Subcommand::Benchmark(cmd)) => { + Some(Subcommand::Benchmark(cmd)) => if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; @@ -86,8 +88,7 @@ pub fn run() -> sc_cli::Result<()> { You can enable it with `--features runtime-benchmarks`." ); Ok(()) - } - } + }, Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), @@ -95,69 +96,53 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - } + }, Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = + new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) - } + }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, task_manager, .. - } = new_partial(&config)?; + let PartialComponents { client, task_manager, .. } = new_partial(&config)?; Ok((cmd.run(client, config.database), task_manager)) }) - } + }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, task_manager, .. - } = new_partial(&config)?; + let PartialComponents { client, task_manager, .. } = new_partial(&config)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) - } + }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = + new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) - } + }, Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.database)) - } + }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - backend, - .. - } = new_partial(&config)?; + let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; Ok((cmd.run(client, backend), task_manager)) }) - } + }, Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) - } + runner + .sync_run(|config| cmd.run::(config)) + }, None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { @@ -167,6 +152,6 @@ pub fn run() -> sc_cli::Result<()> { } .map_err(sc_cli::Error::Service) }) - } + }, } } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 3e8d16f596075..ce9cfc10ef101 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -21,8 +21,8 @@ // ===================================================================================== // UPDATE GUIDE: // 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); -// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom RPCs; -// 3) fix compilation errors; +// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom +// RPCs; 3) fix compilation errors; // 4) test :) // ===================================================================================== // ===================================================================================== @@ -57,7 +57,8 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } } -type FullClient = sc_service::TFullClient>; +type FullClient = + sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -72,7 +73,12 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport, + sc_finality_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullClient, + FullSelectChain, + >, sc_finality_grandpa::LinkHalf, Option, ), @@ -80,7 +86,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())); + return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())) } let telemetry = config @@ -100,11 +106,12 @@ pub fn new_partial( config.max_runtime_instances, ); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -131,26 +138,30 @@ pub fn new_partial( let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let import_queue = + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot)) + }, + spawner: &task_manager.spawn_essential_handle(), + can_author_with: sp_consensus::CanAuthorWithNativeVersion::new( + client.executor().clone(), + ), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; Ok(sc_service::PartialComponents { client, @@ -187,37 +198,39 @@ pub fn new_full(mut config: Configuration) -> Result if let Some(url) = &config.keystore_remote { match remote_keystore(url) { Ok(k) => keystore_container.set_remote_keystore(k), - Err(e) => { + Err(e) => return Err(ServiceError::Other(format!( "Error hooking up remote keystore for {}: {}", url, e - ))) - } + ))), }; } - config - .network - .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config()); + config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), )); - let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: None, - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; + let (network, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + warp_sync: Some(warp_sync), + })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); + sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); } let role = config.role.clone(); @@ -244,8 +257,10 @@ pub fn new_full(mut config: Configuration) -> Result let shared_authority_set = grandpa_link.shared_authority_set().clone(); let shared_voter_state = shared_voter_state.clone(); - let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( + backend, + Some(shared_authority_set.clone()), + ); Box::new(move |_, subscription_executor| { let mut io = jsonrpc_core::IoHandler::default(); @@ -292,37 +307,40 @@ pub fn new_full(mut config: Configuration) -> Result telemetry.as_ref().map(|x| x.handle()), ); - let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + let can_author_with = + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let raw_slot_duration = slot_duration.slot_duration(); - let aura = sc_consensus_aura::start_aura::(StartAuraParams { - slot_duration, - client, - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let aura = sc_consensus_aura::start_aura::( + StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( *timestamp, raw_slot_duration, ); - Ok((timestamp, slot)) + Ok((timestamp, slot)) + }, + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.sync_keystore(), + can_author_with, + sync_oracle: network.clone(), + justification_sync_link: network.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.sync_keystore(), - can_author_with, - sync_oracle: network.clone(), - justification_sync_link: network.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; + )?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. @@ -331,11 +349,8 @@ pub fn new_full(mut config: Configuration) -> Result // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = if role.is_authority() { - Some(keystore_container.sync_keystore()) - } else { - None - }; + let keystore = + if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; let grandpa_config = sc_finality_grandpa::Config { // FIXME #1578 make this available through chainspec @@ -367,9 +382,10 @@ pub fn new_full(mut config: Configuration) -> Result // the GRANDPA voter task is considered infallible, i.e. // if it fails we take down the service with it. - task_manager - .spawn_essential_handle() - .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); + task_manager.spawn_essential_handle().spawn_blocking( + "grandpa-voter", + sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, + ); } network_starter.start_network(); @@ -407,10 +423,7 @@ pub fn new_light(mut config: Configuration) -> Result telemetry }); - config - .network - .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config()); + config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); let select_chain = sc_consensus::LongestChain::new(backend.clone()); @@ -431,45 +444,53 @@ pub fn new_light(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import)), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let import_queue = + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import)), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::NeverCanAuthor, - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); + + Ok((timestamp, slot)) + }, + spawner: &task_manager.spawn_essential_handle(), + can_author_with: sp_consensus::NeverCanAuthor, + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + })?; let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), )); - let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; + let (network, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: Some(on_demand.clone()), + block_announce_validator_builder: None, + warp_sync: Some(warp_sync), + })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); + sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); } let enable_grandpa = !config.disable_grandpa; diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index ce3ca28d39984..698ad1e580465 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -34,15 +34,19 @@ pub mod rialto_messages; use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; -use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; -use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; +use bridge_runtime_common::messages::{ + source::estimate_message_dispatch_and_delivery_fee, MessageBridge, +}; +use pallet_grandpa::{ + fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, +}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, + traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; @@ -61,8 +65,9 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; -pub use pallet_bridge_grandpa::Call as BridgeGrandpaRialtoCall; -pub use pallet_bridge_grandpa::Call as BridgeGrandpaWestendCall; +pub use pallet_bridge_grandpa::{ + Call as BridgeGrandpaRialtoCall, Call as BridgeGrandpaWestendCall, +}; pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -138,10 +143,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -231,9 +233,12 @@ impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; type KeyOwnerProofSystem = (); - type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = - >::IdentificationTuple; + type KeyOwnerProof = + >::Proof; + type KeyOwnerIdentification = >::IdentificationTuple; type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); @@ -394,14 +399,16 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< - Runtime, - pallet_balances::Pallet, - GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, - >; + type MessageDeliveryAndDispatchPayment = + pallet_bridge_messages::instant_payments::InstantCurrencyPayments< + Runtime, + pallet_balances::Pallet, + GetDeliveryConfirmationTransactionFee, + RootAccountForPayments, + >; type OnMessageAccepted = (); - type OnDeliveryConfirmed = pallet_bridge_token_swap::Pallet; + type OnDeliveryConfirmed = + pallet_bridge_token_swap::Pallet; type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; @@ -488,8 +495,13 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPallets>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPallets, +>; impl_runtime_apis! { impl sp_api::Core for Runtime { @@ -742,15 +754,18 @@ mod tests { bp_millau::max_extrinsic_size(), bp_millau::max_extrinsic_weight(), max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()), + messages::target::maximal_incoming_message_dispatch_weight( + bp_millau::max_extrinsic_weight(), + ), ); - let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, - ) - .unwrap_or(u32::MAX); + let max_incoming_inbound_lane_data_proof_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, + ) + .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_millau::max_extrinsic_size(), bp_millau::max_extrinsic_weight(), diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 1bc15caa10565..37fc7715f989d 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -35,7 +35,8 @@ use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Initial value of `RialtoToMillauConversionRate` parameter. -pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = + FixedU128::from_inner(FixedU128::DIV); /// Initial value of `RialtoFeeMultiplier` parameter. pub const INITIAL_RIALTO_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); @@ -47,13 +48,16 @@ parameter_types! { } /// Message payload for Millau -> Rialto messages. -pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload; +pub type ToRialtoMessagePayload = + messages::source::FromThisChainMessagePayload; /// Message verifier for Millau -> Rialto messages. -pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier; +pub type ToRialtoMessageVerifier = + messages::source::FromThisChainMessageVerifier; /// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromRialtoMessagePayload = + messages::target::FromBridgedChainMessagePayload; /// Encoded Millau Call as it comes from Rialto. pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; @@ -62,7 +66,8 @@ pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessag type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Millau -> Rialto messages. -type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; +type ToRialtoMessagesDeliveryProof = + messages::source::FromBridgedChainMessagesDeliveryProof; /// Call-dispatch based message dispatch for Rialto -> Millau messages. pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< @@ -86,8 +91,10 @@ impl MessageBridge for WithRialtoMessageBridge { type BridgedChain = Rialto; fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { - bp_millau::Balance::try_from(RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance)) - .unwrap_or(bp_millau::Balance::MAX) + bp_millau::Balance::try_from( + RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance), + ) + .unwrap_or(bp_millau::Balance::MAX) } } @@ -108,7 +115,9 @@ impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] || *lane == crate::TokenSwapMessagesLane::get() + *lane == [0, 0, 0, 0] || + *lane == [0, 0, 0, 1] || + *lane == crate::TokenSwapMessagesLane::get() } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -167,12 +176,15 @@ impl messages::BridgedChainWithMessages for Rialto { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); + let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( + bp_rialto::max_extrinsic_weight(), + ); - // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` function + // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` + // function // - // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about - // minimal dispatch weight here + // this bridge may be used to deliver all kind of messages, so we're not making any + // assumptions about minimal dispatch weight here 0..=upper_limit } @@ -232,9 +244,11 @@ impl TargetHeaderChain for Rialto fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::( - proof, - ) + messages::source::verify_messages_delivery_proof::< + WithRialtoMessageBridge, + Runtime, + crate::RialtoGrandpaInstance, + >(proof) } } @@ -251,10 +265,11 @@ impl SourceHeaderChain for Rialto { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::( - proof, - messages_count, - ) + messages::target::verify_messages_proof::< + WithRialtoMessageBridge, + Runtime, + crate::RialtoGrandpaInstance, + >(proof, messages_count) } } @@ -268,9 +283,8 @@ pub enum MillauToRialtoMessagesParameter { impl MessagesParameter for MillauToRialtoMessagesParameter { fn save(&self) { match *self { - MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) => { - RialtoToMillauConversionRate::set(conversion_rate) - } + MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) => + RialtoToMillauConversionRate::set(conversion_rate), } } } diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 728c4a0a8ec8e..f93887a21e479 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -23,7 +23,8 @@ use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the normal parachain runtime. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = + sc_service::GenericChainSpec; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { @@ -157,9 +158,7 @@ fn testnet_genesis( }, sudo: rialto_parachain_runtime::SudoConfig { key: root_key }, parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, - aura: rialto_parachain_runtime::AuraConfig { - authorities: initial_authorities, - }, + aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), // parachain_system: Default::default(), } diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 3a55da24d9092..bc2238e2fd44e 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -131,14 +131,7 @@ impl RelayChainCli { ) -> Self { let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); - let base_path = para_config - .base_path - .as_ref() - .map(|x| x.path().join("rialto-bridge-node")); - Self { - base_path, - chain_id, - base: polkadot_cli::RunCmd::from_iter(relay_chain_args), - } + let base_path = para_config.base_path.as_ref().map(|x| x.path().join("rialto-bridge-node")); + Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) } } } diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index a2cffd0fae74f..eb9aba2c104ba 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -26,15 +26,18 @@ use log::info; use polkadot_parachain::primitives::AccountIdConversion; use rialto_parachain_runtime::{Block, RuntimeApi}; use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, - RuntimeVersion, SharedParams, SubstrateCli, + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, + NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_core::hexdisplay::HexDisplay; use sp_runtime::traits::Block as BlockT; use std::{io::Write, net::SocketAddr}; -fn load_spec(id: &str, para_id: ParaId) -> std::result::Result, String> { +fn load_spec( + id: &str, + para_id: ParaId, +) -> std::result::Result, String> { Ok(match id { "dev" => Box::new(chain_spec::development_config(para_id)), "" | "local" => Box::new(chain_spec::local_testnet_config(para_id)), @@ -158,44 +161,51 @@ pub fn run() -> Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - } + }, Some(Subcommand::CheckBlock(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - } + }, Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) - } + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, config.database) + )) + }, Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) - } + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, config.chain_spec) + )) + }, Some(Subcommand::ImportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - } + }, Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name()] - .iter() - .chain(cli.relaychain_args.iter()), + [RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()), ); - let polkadot_config = - SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + let polkadot_config = SubstrateCli::create_configuration( + &polkadot_cli, + &polkadot_cli, + config.tokio_handle.clone(), + ) + .map_err(|err| format!("Relay chain argument error: {}", err))?; cmd.run(config, polkadot_config) }) - } + }, Some(Subcommand::Revert(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, components.backend))) - } + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, components.backend) + )) + }, Some(Subcommand::ExportGenesisState(params)) => { let mut builder = sc_cli::LoggerBuilder::new(""); builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); @@ -219,13 +229,14 @@ pub fn run() -> Result<()> { } Ok(()) - } + }, Some(Subcommand::ExportGenesisWasm(params)) => { let mut builder = sc_cli::LoggerBuilder::new(""); builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); let _ = builder.init(); - let raw_wasm_blob = extract_genesis_wasm(&*cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; + let raw_wasm_blob = + extract_genesis_wasm(&*cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; let output_buf = if params.raw { raw_wasm_blob } else { @@ -239,8 +250,8 @@ pub fn run() -> Result<()> { } Ok(()) - } - Some(Subcommand::Benchmark(cmd)) => { + }, + Some(Subcommand::Benchmark(cmd)) => if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; @@ -249,46 +260,46 @@ pub fn run() -> Result<()> { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." .into()) - } - } + }, None => { let runner = cli.create_runner(&cli.run.normalize())?; runner.run_node_until_exit(|config| async move { - let para_id = chain_spec::Extensions::try_get(&*config.chain_spec).map(|e| e.para_id); + let para_id = + chain_spec::Extensions::try_get(&*config.chain_spec).map(|e| e.para_id); let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name()] - .iter() - .chain(cli.relaychain_args.iter()), + [RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()), ); let id = ParaId::from(cli.run.parachain_id.or(para_id).expect("Missing ParaId")); - let parachain_account = AccountIdConversion::::into_account(&id); + let parachain_account = + AccountIdConversion::::into_account(&id); - let block: Block = generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?; + let block: Block = + generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); - let polkadot_config = - SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + let polkadot_config = SubstrateCli::create_configuration( + &polkadot_cli, + &polkadot_cli, + config.tokio_handle.clone(), + ) + .map_err(|err| format!("Relay chain argument error: {}", err))?; info!("Parachain id: {:?}", id); info!("Parachain Account: {}", parachain_account); info!("Parachain genesis state: {}", genesis_state); - info!( - "Is collating: {}", - if config.role.is_authority() { "yes" } else { "no" } - ); + info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); crate::service::start_node(config, polkadot_config, id) .await .map(|r| r.0) .map_err(Into::into) }) - } + }, } } @@ -357,11 +368,7 @@ impl CliConfiguration for RelayChainCli { fn chain_id(&self, is_dev: bool) -> Result { let chain_id = self.base.base.chain_id(is_dev)?; - Ok(if chain_id.is_empty() { - self.chain_id.clone().unwrap_or_default() - } else { - chain_id - }) + Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) } fn role(&self, is_dev: bool) -> Result { @@ -408,7 +415,10 @@ impl CliConfiguration for RelayChainCli { self.base.base.announce_block() } - fn telemetry_endpoints(&self, chain_spec: &Box) -> Result> { + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> Result> { self.base.base.telemetry_endpoints(chain_spec) } } diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index cbd10ca2aa218..65a8e7bb65c57 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -21,7 +21,9 @@ use std::sync::Arc; use rialto_parachain_runtime::RuntimeApi; // Cumulus Imports -use cumulus_client_consensus_aura::{build_aura_consensus, BuildAuraConsensusParams, SlotProportion}; +use cumulus_client_consensus_aura::{ + build_aura_consensus, BuildAuraConsensusParams, SlotProportion, +}; use cumulus_client_consensus_common::ParachainConsensus; use cumulus_client_network::build_block_announce_validator; use cumulus_client_service::{ @@ -77,8 +79,14 @@ pub fn new_partial( TFullClient>, TFullBackend, (), - sc_consensus::DefaultImportQueue>>, - sc_transaction_pool::FullPool>>, + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, + sc_transaction_pool::FullPool< + Block, + TFullClient>, + >, (Option, Option), >, sc_service::Error, @@ -91,8 +99,10 @@ where RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys - + sp_api::ApiExt, Block>> - + sp_offchain::OffchainWorkerApi + + sp_api::ApiExt< + Block, + StateBackend = sc_client_api::StateBackendFor, Block>, + > + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder, sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, Executor: NativeExecutionDispatch + 'static, @@ -102,7 +112,10 @@ where Option, &TaskManager, ) -> Result< - sc_consensus::DefaultImportQueue>>, + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, sc_service::Error, >, { @@ -123,11 +136,12 @@ where config.max_runtime_instances, ); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); @@ -189,8 +203,10 @@ where RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys - + sp_api::ApiExt, Block>> - + sp_offchain::OffchainWorkerApi + + sp_api::ApiExt< + Block, + StateBackend = sc_client_api::StateBackendFor, Block>, + > + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder + cumulus_primitives_core::CollectCollationInfo, sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, @@ -206,7 +222,10 @@ where Option, &TaskManager, ) -> Result< - sc_consensus::DefaultImportQueue>>, + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, sc_service::Error, >, BIC: FnOnce( @@ -215,14 +234,19 @@ where Option, &TaskManager, &polkadot_service::NewFull, - Arc>>>, + Arc< + sc_transaction_pool::FullPool< + Block, + TFullClient>, + >, + >, Arc>, SyncCryptoStorePtr, bool, ) -> Result>, sc_service::Error>, { if matches!(parachain_config.role, Role::Light) { - return Err("Light client not supported!".into()); + return Err("Light client not supported!".into()) } let parachain_config = prepare_node_config(parachain_config); @@ -231,12 +255,11 @@ where let (mut telemetry, telemetry_worker_handle) = params.other; let relay_chain_full_node = - cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle).map_err( - |e| match e { + cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle) + .map_err(|e| match e { polkadot_service::Error::Sub(x) => x, s => format!("{}", s).into(), - }, - )?; + })?; let client = params.client.clone(); let backend = params.backend.clone(); @@ -253,16 +276,17 @@ where let transaction_pool = params.transaction_pool.clone(); let mut task_manager = params.task_manager; let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); - let (network, system_rpc_tx, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { - config: ¶chain_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue: import_queue.clone(), - on_demand: None, - block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)), - warp_sync: None, - })?; + let (network, system_rpc_tx, start_network) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: ¶chain_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue: import_queue.clone(), + on_demand: None, + block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)), + warp_sync: None, + })?; let rpc_client = client.clone(); let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone()))); @@ -348,26 +372,33 @@ pub fn parachain_build_import_queue( > { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - cumulus_client_consensus_aura::import_queue::( - cumulus_client_consensus_aura::ImportQueueParams { - block_import: client.clone(), - client: client.clone(), - create_inherent_data_providers: move |_, _| async move { - let time = sp_timestamp::InherentDataProvider::from_system_time(); + cumulus_client_consensus_aura::import_queue::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + _, + >(cumulus_client_consensus_aura::ImportQueueParams { + block_import: client.clone(), + client: client.clone(), + create_inherent_data_providers: move |_, _| async move { + let time = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( *time, slot_duration.slot_duration(), ); - Ok((time, slot)) - }, - registry: config.prometheus_registry(), - can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - spawner: &task_manager.spawn_essential_handle(), - telemetry, + Ok((time, slot)) }, - ) + registry: config.prometheus_registry(), + can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + spawner: &task_manager.spawn_essential_handle(), + telemetry, + }) .map_err(Into::into) } @@ -438,7 +469,9 @@ pub async fn start_node( ); let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from("Failed to create parachain inherent") + Box::::from( + "Failed to create parachain inherent", + ) })?; Ok((time, slot, parachain_inherent)) } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 613c444a28f27..93118e3c9dd3b 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -63,10 +63,11 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin, - FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, ParentAsSuperuser, ParentIsDefault, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, + EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, + ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; use xcm_executor::{Config, XcmExecutor}; @@ -110,8 +111,13 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPallets>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPallets, +>; impl_opaque_keys! { pub struct SessionKeys { @@ -159,14 +165,11 @@ pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } -/// We assume that approximately 10 percent of the block weight is consumed by `on_initalize` handlers. -/// This is used to limit the maximal weight of a single extrinsic. +/// We assume that approximately 10 percent of the block weight is consumed by `on_initalize` +/// handlers. This is used to limit the maximal weight of a single extrinsic. const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// We allow `Normal` extrinsics to fill up the block up to 75 percent, the rest can be used /// by Operational extrinsics. @@ -664,12 +667,13 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 68a2928ed2890..8c6b147f48204 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -17,9 +17,9 @@ use bp_rialto::derive_account_from_millau_id; use polkadot_primitives::v1::{AssignmentId, ValidatorId}; use rialto_runtime::{ - AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig, BridgeRialtoPoaConfig, - ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, - WASM_BINARY, + AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig, + BridgeRialtoPoaConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, + SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -62,14 +62,7 @@ where /// Helper function to generate authority keys. pub fn get_authority_keys_from_seed( s: &str, -) -> ( - AccountId, - BabeId, - GrandpaId, - ValidatorId, - AssignmentId, - AuthorityDiscoveryId, -) { +) -> (AccountId, BabeId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) { ( get_account_id_from_seed::(s), get_from_seed::(s), @@ -195,13 +188,7 @@ fn session_keys( para_assignment: AssignmentId, authority_discovery: AuthorityDiscoveryId, ) -> SessionKeys { - SessionKeys { - babe, - grandpa, - para_validator, - para_assignment, - authority_discovery, - } + SessionKeys { babe, grandpa, para_validator, para_assignment, authority_discovery } } fn testnet_genesis( @@ -231,9 +218,7 @@ fn testnet_genesis( }, bridge_rialto_poa: load_rialto_poa_bridge_config(), bridge_kovan: load_kovan_bridge_config(), - grandpa: GrandpaConfig { - authorities: Vec::new(), - }, + grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: root_key }, session: SessionConfig { keys: initial_authorities @@ -242,7 +227,13 @@ fn testnet_genesis( ( x.0.clone(), x.0.clone(), - session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()), + session_keys( + x.1.clone(), + x.2.clone(), + x.3.clone(), + x.4.clone(), + x.5.clone(), + ), ) }) .collect::>(), @@ -320,9 +311,7 @@ fn load_kovan_bridge_config() -> BridgeKovanConfig { #[test] fn derived_dave_account_is_as_expected() { let dave = get_account_id_from_seed::("Dave"); - let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); - assert_eq!( - derived.to_string(), - "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string() - ); + let derived: AccountId = + derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); + assert_eq!(derived.to_string(), "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string()); } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 308cb10344410..6f841a9d67f1d 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{Cli, Subcommand}; -use crate::service::new_partial; +use crate::{ + cli::{Cli, Subcommand}, + service::new_partial, +}; use rialto_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; @@ -73,7 +75,7 @@ pub fn run() -> sc_cli::Result<()> { )); match &cli.subcommand { - Some(Subcommand::Benchmark(cmd)) => { + Some(Subcommand::Benchmark(cmd)) => if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; @@ -84,8 +86,7 @@ pub fn run() -> sc_cli::Result<()> { You can enable it with `--features runtime-benchmarks`." ); Ok(()) - } - } + }, Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), @@ -93,69 +94,57 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - } + }, Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = new_partial(&mut config).map_err(service_error)?; + let PartialComponents { client, task_manager, import_queue, .. } = + new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) - } + }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { - client, task_manager, .. - } = new_partial(&mut config).map_err(service_error)?; + let PartialComponents { client, task_manager, .. } = + new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, config.database), task_manager)) }) - } + }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { - client, task_manager, .. - } = new_partial(&mut config).map_err(service_error)?; + let PartialComponents { client, task_manager, .. } = + new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) - } + }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = new_partial(&mut config).map_err(service_error)?; + let PartialComponents { client, task_manager, import_queue, .. } = + new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) - } + }, Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.database)) - } + }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { - client, - task_manager, - backend, - .. - } = new_partial(&mut config).map_err(service_error)?; + let PartialComponents { client, task_manager, backend, .. } = + new_partial(&mut config).map_err(service_error)?; Ok((cmd.run(client, backend), task_manager)) }) - } + }, Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) - } + runner.sync_run(|config| { + cmd.run::(config) + }) + }, Some(Subcommand::PvfPrepareWorker(cmd)) => { let mut builder = sc_cli::LoggerBuilder::new(""); builder.with_colors(false); @@ -163,7 +152,7 @@ pub fn run() -> sc_cli::Result<()> { polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path); Ok(()) - } + }, Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => { let mut builder = sc_cli::LoggerBuilder::new(""); builder.with_colors(false); @@ -171,7 +160,7 @@ pub fn run() -> sc_cli::Result<()> { polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path); Ok(()) - } + }, None => { let runner = cli.create_runner(&cli.run)?; @@ -192,7 +181,7 @@ pub fn run() -> sc_cli::Result<()> { .map_err(service_error), } }) - } + }, } } diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs index 3742bcdc8927d..1c381c1df8fdd 100644 --- a/bin/rialto/node/src/overseer.rs +++ b/bin/rialto/node/src/overseer.rs @@ -87,7 +87,8 @@ where pub pov_req_receiver: IncomingRequestReceiver, pub chunk_req_receiver: IncomingRequestReceiver, pub collation_req_receiver: IncomingRequestReceiver, - pub available_data_req_receiver: IncomingRequestReceiver, + pub available_data_req_receiver: + IncomingRequestReceiver, pub statement_req_receiver: IncomingRequestReceiver, pub dispute_req_receiver: IncomingRequestReceiver, /// Prometheus registry, commonly used for production systems, less so for test. @@ -143,7 +144,10 @@ pub fn create_default_subsystems( ProvisionerSubsystem, RuntimeApiSubsystem, AvailabilityStoreSubsystem, - NetworkBridgeSubsystem>, AuthorityDiscoveryService>, + NetworkBridgeSubsystem< + Arc>, + AuthorityDiscoveryService, + >, ChainApiSubsystem, CollationGenerationSubsystem, CollatorProtocolSubsystem, @@ -167,10 +171,7 @@ where let all_subsystems = AllSubsystems { availability_distribution: AvailabilityDistributionSubsystem::new( keystore.clone(), - IncomingRequestReceivers { - pov_req_receiver, - chunk_req_receiver, - }, + IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, Metrics::register(registry)?, ), availability_recovery: AvailabilityRecoverySubsystem::with_chunks_only( @@ -212,7 +213,11 @@ where Metrics::register(registry)?, ), provisioner: ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?), - runtime_api: RuntimeApiSubsystem::new(runtime_client, Metrics::register(registry)?, spawner), + runtime_api: RuntimeApiSubsystem::new( + runtime_client, + Metrics::register(registry)?, + spawner, + ), statement_distribution: StatementDistributionSubsystem::new( keystore.clone(), statement_req_receiver, @@ -287,6 +292,7 @@ impl OverseerGen for RealOverseerGen { let all_subsystems = create_default_subsystems::(args)?; - Overseer::new(leaves, all_subsystems, registry, runtime_client, spawner).map_err(|e| e.into()) + Overseer::new(leaves, all_subsystems, registry, runtime_client, spawner) + .map_err(|e| e.into()) } } diff --git a/bin/rialto/node/src/parachains_db.rs b/bin/rialto/node/src/parachains_db.rs index 976191fc80788..bf2052043c987 100644 --- a/bin/rialto/node/src/parachains_db.rs +++ b/bin/rialto/node/src/parachains_db.rs @@ -17,7 +17,8 @@ //! This is almost 1:1 copy of `node/service/parachains_db/mod.rs` file from Polkadot repository. //! The only exception is that we don't support db upgrades => no `upgrade.rs` module. -use {kvdb::KeyValueDB, std::io, std::path::PathBuf, std::sync::Arc}; +use kvdb::KeyValueDB; +use std::{io, path::PathBuf, sync::Arc}; mod columns { pub const NUM_COLUMNS: u32 = 5; @@ -66,11 +67,7 @@ pub struct CacheSizes { impl Default for CacheSizes { fn default() -> Self { - CacheSizes { - availability_data: 25, - availability_meta: 1, - approval_data: 5, - } + CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 } } } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 19743933c1eaf..8a2a38a59c60b 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -19,7 +19,8 @@ //! The code is mostly copy of `service/src/lib.rs` file from Polkadot repository //! without optional functions. -// this warning comes from Error enum (sc_cli::Error in particular) && it isn't easy to use box there +// this warning comes from Error enum (sc_cli::Error in particular) && it isn't easy to use box +// there #![allow(clippy::large_enum_variant)] // this warning comes from `sc_service::PartialComponents` type #![allow(clippy::type_complexity)] @@ -46,14 +47,12 @@ use sp_runtime::traits::{BlakeTwo256, Block as BlockT}; use std::{sync::Arc, time::Duration}; use substrate_prometheus_endpoint::Registry; -pub use { - polkadot_overseer::{Handle, Overseer, OverseerHandle}, - polkadot_primitives::v1::ParachainHost, - sc_client_api::AuxStore, - sp_authority_discovery::AuthorityDiscoveryApi, - sp_blockchain::HeaderBackend, - sp_consensus_babe::BabeApi, -}; +pub use polkadot_overseer::{Handle, Overseer, OverseerHandle}; +pub use polkadot_primitives::v1::ParachainHost; +pub use sc_client_api::AuxStore; +pub use sp_authority_discovery::AuthorityDiscoveryApi; +pub use sp_blockchain::HeaderBackend; +pub use sp_consensus_babe::BabeApi; pub type Executor = NativeElseWasmExecutor; @@ -108,9 +107,11 @@ pub enum Error { type FullClient = sc_service::TFullClient; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; -type FullGrandpaBlockImport = sc_finality_grandpa::GrandpaBlockImport; +type FullGrandpaBlockImport = + sc_finality_grandpa::GrandpaBlockImport; type FullTransactionPool = sc_transaction_pool::FullPool; -type FullBabeBlockImport = sc_consensus_babe::BabeBlockImport; +type FullBabeBlockImport = + sc_consensus_babe::BabeBlockImport; type FullBabeLink = sc_consensus_babe::BabeLink; type FullGrandpaLink = sc_finality_grandpa::LinkHalf; @@ -125,8 +126,11 @@ pub trait RequiredApiCollection: + sp_finality_grandpa::GrandpaApi + polkadot_primitives::v1::ParachainHost + sp_block_builder::BlockBuilder - + frame_system_rpc_runtime_api::AccountNonceApi - + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + frame_system_rpc_runtime_api::AccountNonceApi< + Block, + bp_rialto::AccountId, + rialto_runtime::Index, + > + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + sp_session::SessionKeys @@ -144,8 +148,11 @@ where + sp_finality_grandpa::GrandpaApi + polkadot_primitives::v1::ParachainHost + sp_block_builder::BlockBuilder - + frame_system_rpc_runtime_api::AccountNonceApi - + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + + frame_system_rpc_runtime_api::AccountNonceApi< + Block, + bp_rialto::AccountId, + rialto_runtime::Index, + > + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::Metadata + sp_offchain::OffchainWorkerApi + sp_session::SessionKeys @@ -210,11 +217,12 @@ where config.max_runtime_instances, ); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -232,13 +240,14 @@ where client.clone(), ); - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import_with_authority_set_hard_forks( - client.clone(), - &(client.clone() as Arc<_>), - select_chain.clone(), - Vec::new(), - telemetry.as_ref().map(|x| x.handle()), - )?; + let (grandpa_block_import, grandpa_link) = + sc_finality_grandpa::block_import_with_authority_set_hard_forks( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + Vec::new(), + telemetry.as_ref().map(|x| x.handle()), + )?; let justification_import = grandpa_block_import.clone(); let babe_config = sc_consensus_babe::Config::get_or_compute(&*client)?; @@ -255,10 +264,11 @@ where move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); + let slot = + sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + slot_duration, + ); Ok((timestamp, slot)) }, @@ -295,8 +305,10 @@ where let shared_voter_state = shared_voter_state.clone(); - let finality_proof_provider = - GrandpaFinalityProofProvider::new_for_service(backend, Some(shared_authority_set.clone())); + let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( + backend, + Some(shared_authority_set.clone()), + ); let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( @@ -325,13 +337,7 @@ where select_chain, import_queue, transaction_pool, - other: ( - rpc_extensions_builder, - import_setup, - rpc_setup, - slot_duration, - telemetry, - ), + other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, telemetry), }) } @@ -344,7 +350,7 @@ pub struct NewFull { pub backend: Arc, } -/// The maximum number of active leaves we forward to the [`Overseer`] on startup. +/// The maximum number of active leaves we forward to the [`Overseer`] on start up. const MAX_ACTIVE_LEAVES: usize = 4; /// Returns the active leaves the overseer should start with. @@ -370,16 +376,12 @@ where // Only consider leaves that are in maximum an uncle of the best block. if number < best_block.number().saturating_sub(1) || hash == best_block.hash() { - return None; + return None } let parent_hash = client.header(&BlockId::Hash(hash)).ok()??.parent_hash; - Some(BlockInfo { - hash, - parent_hash, - number, - }) + Some(BlockInfo { hash, parent_hash, number }) }) .collect::>(); @@ -411,7 +413,8 @@ where let role = config.role.clone(); let force_authoring = config.force_authoring; - let backoff_authoring_blocks = Some(sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default()); + let backoff_authoring_blocks = + Some(sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default()); let disable_grandpa = config.disable_grandpa; let name = config.network.node_name.clone(); @@ -435,18 +438,11 @@ where // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change // anything in terms of behaviour, but makes the logs more consistent with the other // Substrate nodes. - config - .network - .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config()); + config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); { use polkadot_network_bridge::{peer_sets_info, IsAuthority}; - let is_authority = if role.is_authority() { - IsAuthority::Yes - } else { - IsAuthority::No - }; + let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No }; config.network.extra_sets.extend(peer_sets_info(is_authority)); } @@ -468,20 +464,25 @@ where import_setup.1.shared_authority_set().clone(), )); - let (network, system_rpc_tx, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: None, - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; + let (network, system_rpc_tx, network_starter) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + on_demand: None, + block_announce_validator_builder: None, + warp_sync: Some(warp_sync), + })?; if config.offchain_worker.enabled { - let _ = - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); + let _ = sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); } let parachains_db = crate::parachains_db::open_creating( @@ -551,12 +552,13 @@ where // don't publish our addresses when we're only a collator sc_authority_discovery::Role::Discover }; - let dht_event_stream = network.event_stream("authority-discovery").filter_map(|e| async move { - match e { - Event::Dht(e) => Some(e), - _ => None, - } - }); + let dht_event_stream = + network.event_stream("authority-discovery").filter_map(|e| async move { + match e { + Event::Dht(e) => Some(e), + _ => None, + } + }); let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config( sc_authority_discovery::WorkerConfig { publish_non_global_ips: auth_disc_publish_non_global_ips, @@ -569,22 +571,22 @@ where prometheus_registry.clone(), ); - task_manager - .spawn_handle() - .spawn("authority-discovery-worker", worker.run()); + task_manager.spawn_handle().spawn("authority-discovery-worker", worker.run()); Some(service) } else { None }; - // we'd say let overseer_handler = authority_discovery_service.map(|authority_discovery_service|, ...), - // but in that case we couldn't use ? to propagate errors + // we'd say let overseer_handler = + // authority_discovery_service.map(|authority_discovery_service|, ...), but in that case we + // couldn't use ? to propagate errors let local_keystore = keystore_container.local_keystore(); - let maybe_params = local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k))); + let maybe_params = + local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k))); let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params { - let (overseer, overseer_handle) = - overseer_gen.generate::(OverseerGenArgs { + let (overseer, overseer_handle) = overseer_gen + .generate::(OverseerGenArgs { leaves: active_leaves, keystore, runtime_client: overseer_client.clone(), @@ -635,7 +637,8 @@ where }; if role.is_authority() { - let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); + let can_author_with = + sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let proposer = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), @@ -646,10 +649,8 @@ where ); let client_clone = client.clone(); - let overseer_handle = overseer_handle - .as_ref() - .ok_or(Error::AuthoritiesRequireRealOverseer)? - .clone(); + let overseer_handle = + overseer_handle.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone(); let slot_duration = babe_link.config().slot_duration(); let babe_config = sc_consensus_babe::BabeParams { keystore: keystore_container.sync_keystore(), @@ -671,7 +672,10 @@ where .await .map_err(Box::new)?; - let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider(&*client_clone, parent)?; + let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider( + &*client_clone, + parent, + )?; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); @@ -698,11 +702,8 @@ where // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore_opt = if role.is_authority() { - Some(keystore_container.sync_keystore()) - } else { - None - }; + let keystore_opt = + if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; let config = sc_finality_grandpa::Config { // FIXME substrate#1578 make this available through chainspec @@ -740,23 +741,20 @@ where telemetry: telemetry.as_ref().map(|x| x.handle()), }; - task_manager - .spawn_essential_handle() - .spawn_blocking("grandpa-voter", sc_finality_grandpa::run_grandpa_voter(grandpa_config)?); + task_manager.spawn_essential_handle().spawn_blocking( + "grandpa-voter", + sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, + ); } network_starter.start_network(); - Ok(NewFull { - task_manager, - client, - overseer_handle, - network, - rpc_handlers, - backend, - }) + Ok(NewFull { task_manager, client, overseer_handle, network, rpc_handlers, backend }) } -pub fn build_full(config: Configuration, overseer_gen: impl OverseerGen) -> Result>, Error> { +pub fn build_full( + config: Configuration, + overseer_gen: impl OverseerGen, +) -> Result>, Error> { new_full(config, None, overseer_gen) } diff --git a/bin/rialto/runtime/src/benches.rs b/bin/rialto/runtime/src/benches.rs index 86d6b8361c635..ce3f84069795a 100644 --- a/bin/rialto/runtime/src/benches.rs +++ b/bin/rialto/runtime/src/benches.rs @@ -22,7 +22,8 @@ use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource}; use sp_std::vec; pub use crate::kovan::{ - genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, PruningStrategy, + genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, + PruningStrategy, }; frame_support::parameter_types! { diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index cdb9d9db62e09..9f34707848fea 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -28,7 +28,8 @@ //! 5) receive tokens by providing proof-of-inclusion of PoA transaction. use bp_currency_exchange::{ - Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, Result as ExchangeResult, + Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, + Result as ExchangeResult, }; use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; use codec::{Decode, Encode}; @@ -87,7 +88,7 @@ impl MaybeLockFundsTransaction for EthTransaction { tx.unsigned.to, ); - return Err(ExchangeError::InvalidTransaction); + return Err(ExchangeError::InvalidTransaction) } let mut recipient_raw = sp_core::H256::default(); @@ -100,8 +101,8 @@ impl MaybeLockFundsTransaction for EthTransaction { len, ); - return Err(ExchangeError::InvalidRecipient); - } + return Err(ExchangeError::InvalidRecipient) + }, } let amount = tx.unsigned.value.low_u128(); @@ -112,7 +113,7 @@ impl MaybeLockFundsTransaction for EthTransaction { tx.unsigned.value, ); - return Err(ExchangeError::InvalidAmount); + return Err(ExchangeError::InvalidAmount) } Ok(LockFundsTransaction { @@ -213,10 +214,7 @@ mod tests { #[test] fn invalid_transaction_rejected() { - assert_eq!( - EthTransaction::parse(&Vec::new()), - Err(ExchangeError::InvalidTransaction), - ); + assert_eq!(EthTransaction::parse(&Vec::new()), Err(ExchangeError::InvalidTransaction),); } #[test] diff --git a/bin/rialto/runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs index 15c73fc6ea3f0..95b4f8c42f03b 100644 --- a/bin/rialto/runtime/src/kovan.rs +++ b/bin/rialto/runtime/src/kovan.rs @@ -21,8 +21,8 @@ use bp_header_chain::InclusionProofVerifier; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_eth_poa::{ - AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, ValidatorsConfiguration, - ValidatorsSource, + AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, + ValidatorsConfiguration, ValidatorsSource, }; use sp_std::prelude::*; @@ -102,11 +102,14 @@ pub fn genesis_header() -> AuraHeader { timestamp: 0, number: 0, author: Default::default(), - transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), + transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + .into(), + uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") + .into(), extra_data: vec![], state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + .into(), log_bloom: Default::default(), gas_used: Default::default(), gas_limit: 6000000.into(), @@ -114,8 +117,9 @@ pub fn genesis_header() -> AuraHeader { seal: vec![ vec![128], vec![ - 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], ], } @@ -153,12 +157,17 @@ impl InclusionProofVerifier for KovanBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { - let is_transaction_finalized = - crate::BridgeKovan::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + fn verify_transaction_inclusion_proof( + proof: &Self::TransactionInclusionProof, + ) -> Option { + let is_transaction_finalized = crate::BridgeKovan::verify_transaction_finalized( + proof.block, + proof.index, + &proof.proof, + ); if !is_transaction_finalized { - return None; + return None } proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index b440000ae6b7b..84908fd52bf0a 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -41,15 +41,19 @@ pub mod rialto_poa; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; -use bridge_runtime_common::messages::{source::estimate_message_dispatch_and_delivery_fee, MessageBridge}; -use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; +use bridge_runtime_common::messages::{ + source::estimate_message_dispatch_and_delivery_fee, MessageBridge, +}; +use pallet_grandpa::{ + fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, +}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::traits::{AccountIdLookup, Block as BlockT, NumberFor, OpaqueKeys}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, + traits::{AccountIdLookup, Block as BlockT, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; @@ -149,10 +153,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -238,10 +239,14 @@ impl pallet_babe::Config for Runtime { // equivocation related configuration - we don't expect any equivocations in our testnets type KeyOwnerProofSystem = (); - type KeyOwnerProof = - >::Proof; - type KeyOwnerIdentification = - >::IdentificationTuple; + type KeyOwnerProof = >::Proof; + type KeyOwnerIdentification = >::IdentificationTuple; type HandleEquivocation = (); type DisabledValidators = (); @@ -308,13 +313,18 @@ impl bp_currency_exchange::DepositInto for DepositInto { type Recipient = AccountId; type Amount = Balance; - fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> bp_currency_exchange::Result<()> { - // let balances module make all checks for us (it won't allow depositing lower than existential - // deposit, balance overflow, ...) - let deposited = as Currency>::deposit_creating(&recipient, amount); + fn deposit_into( + recipient: Self::Recipient, + amount: Self::Amount, + ) -> bp_currency_exchange::Result<()> { + // let balances module make all checks for us (it won't allow depositing lower than + // existential deposit, balance overflow, ...) + let deposited = as Currency>::deposit_creating( + &recipient, amount, + ); - // I'm dropping deposited here explicitly to illustrate the fact that it'll update `TotalIssuance` - // on drop + // I'm dropping deposited here explicitly to illustrate the fact that it'll update + // `TotalIssuance` on drop let deposited_amount = deposited.peek(); drop(deposited); @@ -332,7 +342,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { ); Ok(()) - } + }, _ if deposited_amount == 0 => { log::error!( target: "runtime", @@ -342,7 +352,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { ); Err(bp_currency_exchange::Error::DepositFailed) - } + }, _ => { log::error!( target: "runtime", @@ -354,7 +364,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { // we can't return DepositFailed error here, because storage changes were made Err(bp_currency_exchange::Error::DepositPartiallyFailed) - } + }, } } } @@ -363,9 +373,12 @@ impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; type KeyOwnerProofSystem = (); - type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = - >::IdentificationTuple; + type KeyOwnerProof = + >::Proof; + type KeyOwnerIdentification = >::IdentificationTuple; type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); @@ -529,12 +542,13 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< - Runtime, - pallet_balances::Pallet, - GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, - >; + type MessageDeliveryAndDispatchPayment = + pallet_bridge_messages::instant_payments::InstantCurrencyPayments< + Runtime, + pallet_balances::Pallet, + GetDeliveryConfirmationTransactionFee, + RootAccountForPayments, + >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -625,8 +639,13 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPallets>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPallets, +>; impl_runtime_apis! { impl sp_api::Core for Runtime { @@ -1277,8 +1296,8 @@ impl_runtime_apis! { /// Millau account ownership digest from Rialto. /// /// The byte vector returned by this function should be signed with a Millau account private key. -/// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private key -/// is also under his control. +/// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private +/// key is also under his control. pub fn rialto_to_millau_account_ownership_digest( millau_call: &Call, rialto_account_id: AccountId, @@ -1305,7 +1324,8 @@ mod tests { use bridge_runtime_common::messages; fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) { - let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::().unwrap().into(); + let mut ext: sp_io::TestExternalities = + SystemConfig::default().build_storage::().unwrap().into(); ext.execute_with(|| { // initially issuance is zero assert_eq!( @@ -1317,7 +1337,10 @@ mod tests { let account: AccountId = [1u8; 32].into(); let initial_amount = ExistentialDeposit::get(); let deposited = - as Currency>::deposit_creating(&account, initial_amount); + as Currency>::deposit_creating( + &account, + initial_amount, + ); drop(deposited); assert_eq!( as Currency>::total_issuance(), @@ -1358,15 +1381,18 @@ mod tests { bp_rialto::max_extrinsic_size(), bp_rialto::max_extrinsic_weight(), max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight(bp_rialto::max_extrinsic_weight()), + messages::target::maximal_incoming_message_dispatch_weight( + bp_rialto::max_extrinsic_weight(), + ), ); - let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, - ) - .unwrap_or(u32::MAX); + let max_incoming_inbound_lane_data_proof_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, + bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, + ) + .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_rialto::max_extrinsic_size(), bp_rialto::max_extrinsic_weight(), @@ -1381,7 +1407,9 @@ mod tests { fn deposit_into_existing_account_works() { run_deposit_into_test(|existing_account| { let initial_amount = - as Currency>::free_balance(&existing_account); + as Currency>::free_balance( + &existing_account, + ); let additional_amount = 10_000; >::DepositInto::deposit_into( existing_account.clone(), @@ -1389,7 +1417,9 @@ mod tests { ) .unwrap(); assert_eq!( - as Currency>::free_balance(&existing_account), + as Currency>::free_balance( + &existing_account + ), initial_amount + additional_amount, ); additional_amount @@ -1408,7 +1438,9 @@ mod tests { ) .unwrap(); assert_eq!( - as Currency>::free_balance(&new_account), + as Currency>::free_balance( + &new_account + ), initial_amount + additional_amount, ); additional_amount diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index bb24a95f9ccba..0342f5b48ab39 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -35,7 +35,8 @@ use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; /// Initial value of `MillauToRialtoConversionRate` parameter. -pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = + FixedU128::from_inner(FixedU128::DIV); /// Initial value of `MillauFeeMultiplier` parameter. pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); @@ -47,13 +48,16 @@ parameter_types! { } /// Message payload for Rialto -> Millau messages. -pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; +pub type ToMillauMessagePayload = + messages::source::FromThisChainMessagePayload; /// Message verifier for Rialto -> Millau messages. -pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; +pub type ToMillauMessageVerifier = + messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromMillauMessagePayload = + messages::target::FromBridgedChainMessagePayload; /// Encoded Rialto Call as it comes from Millau. pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; @@ -70,7 +74,8 @@ pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDi pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Rialto -> Millau messages. -pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; +pub type ToMillauMessagesDeliveryProof = + messages::source::FromBridgedChainMessagesDeliveryProof; /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] @@ -86,8 +91,10 @@ impl MessageBridge for WithMillauMessageBridge { type BridgedChain = Millau; fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { - bp_rialto::Balance::try_from(MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance)) - .unwrap_or(bp_rialto::Balance::MAX) + bp_rialto::Balance::try_from( + MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance), + ) + .unwrap_or(bp_rialto::Balance::MAX) } } @@ -167,12 +174,15 @@ impl messages::BridgedChainWithMessages for Millau { fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages::target::maximal_incoming_message_dispatch_weight(bp_millau::max_extrinsic_weight()); + let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( + bp_millau::max_extrinsic_weight(), + ); - // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` function + // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` + // function // - // this bridge may be used to deliver all kind of messages, so we're not making any assumptions about - // minimal dispatch weight here + // this bridge may be used to deliver all kind of messages, so we're not making any + // assumptions about minimal dispatch weight here 0..=upper_limit } @@ -232,9 +242,11 @@ impl TargetHeaderChain for Millau fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::( - proof, - ) + messages::source::verify_messages_delivery_proof::< + WithMillauMessageBridge, + Runtime, + crate::MillauGrandpaInstance, + >(proof) } } @@ -251,10 +263,11 @@ impl SourceHeaderChain for Millau { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::( - proof, - messages_count, - ) + messages::target::verify_messages_proof::< + WithMillauMessageBridge, + Runtime, + crate::MillauGrandpaInstance, + >(proof, messages_count) } } @@ -268,9 +281,8 @@ pub enum RialtoToMillauMessagesParameter { impl MessagesParameter for RialtoToMillauMessagesParameter { fn save(&self) { match *self { - RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => { - MillauToRialtoConversionRate::set(conversion_rate) - } + RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => + MillauToRialtoConversionRate::set(conversion_rate), } } } @@ -285,7 +297,9 @@ mod tests { MessageKey, }; use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount}; - use bridge_runtime_common::messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload}; + use bridge_runtime_common::messages::target::{ + FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload, + }; use frame_support::{ traits::Currency, weights::{GetDispatchInfo, WeightToFeePolynomial}, @@ -297,12 +311,15 @@ mod tests { // this test actually belongs to the `bridge-runtime-common` crate, but there we have no // mock runtime. Making another one there just for this test, given that both crates // live n single repo is an overkill - let mut ext: sp_io::TestExternalities = SystemConfig::default().build_storage::().unwrap().into(); + let mut ext: sp_io::TestExternalities = + SystemConfig::default().build_storage::().unwrap().into(); ext.execute_with(|| { let bridge = MILLAU_CHAIN_ID; let call: Call = SystemCall::remark(vec![]).into(); let dispatch_weight = call.get_dispatch_info().weight; - let dispatch_fee = ::WeightToFee::calc(&dispatch_weight); + let dispatch_fee = ::WeightToFee::calc( + &dispatch_weight, + ); assert!(dispatch_fee > 0); // create relayer account with minimal balance @@ -314,12 +331,13 @@ mod tests { ); // create dispatch account with minimal balance + dispatch fee - let dispatch_account = derive_account_id::<::SourceChainAccountId>( - bridge, - SourceAccount::Root, - ); + let dispatch_account = derive_account_id::< + ::SourceChainAccountId, + >(bridge, SourceAccount::Root); let dispatch_account = - ::AccountIdConverter::convert(dispatch_account); + ::AccountIdConverter::convert( + dispatch_account, + ); let _ = as Currency>::deposit_creating( &dispatch_account, initial_amount + dispatch_fee, @@ -329,10 +347,7 @@ mod tests { FromMillauMessageDispatch::dispatch( &relayer_account, DispatchMessage { - key: MessageKey { - lane_id: Default::default(), - nonce: 0, - }, + key: MessageKey { lane_id: Default::default(), nonce: 0 }, data: DispatchMessageData { payload: Ok(FromBridgedChainMessagePayload:: { spec_version: VERSION.spec_version, @@ -348,11 +363,15 @@ mod tests { // ensure that fee has been transferred from dispatch to relayer account assert_eq!( - as Currency>::free_balance(&relayer_account), + as Currency>::free_balance( + &relayer_account + ), initial_amount + dispatch_fee, ); assert_eq!( - as Currency>::free_balance(&dispatch_account), + as Currency>::free_balance( + &dispatch_account + ), initial_amount, ); }); diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index ba7b01ea116e8..20ce9c29ef2d1 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -17,25 +17,21 @@ //! Parachains support in Rialto runtime. use crate::{ - AccountId, Balance, Balances, BlockNumber, Event, Origin, RandomnessCollectiveFlip, Registrar, Runtime, Slots, + AccountId, Balance, Balances, BlockNumber, Event, Origin, RandomnessCollectiveFlip, Registrar, + Runtime, Slots, }; use frame_support::{parameter_types, weights::Weight}; use frame_system::EnsureRoot; use polkadot_primitives::v1::ValidatorIndex; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; -use polkadot_runtime_parachains::configuration as parachains_configuration; -use polkadot_runtime_parachains::dmp as parachains_dmp; -use polkadot_runtime_parachains::hrmp as parachains_hrmp; -use polkadot_runtime_parachains::inclusion as parachains_inclusion; -use polkadot_runtime_parachains::initializer as parachains_initializer; -use polkadot_runtime_parachains::origin as parachains_origin; -use polkadot_runtime_parachains::paras as parachains_paras; -use polkadot_runtime_parachains::paras_inherent as parachains_paras_inherent; -use polkadot_runtime_parachains::scheduler as parachains_scheduler; -use polkadot_runtime_parachains::session_info as parachains_session_info; -use polkadot_runtime_parachains::shared as parachains_shared; -use polkadot_runtime_parachains::ump as parachains_ump; +use polkadot_runtime_parachains::{ + configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp, + inclusion as parachains_inclusion, initializer as parachains_initializer, + origin as parachains_origin, paras as parachains_paras, + paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler, + session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump, +}; /// Special `RewardValidators` that does nothing ;) pub struct RewardValidators; diff --git a/bin/rialto/runtime/src/rialto_poa.rs b/bin/rialto/runtime/src/rialto_poa.rs index 9bc74a2ebaac6..865ef387d1b43 100644 --- a/bin/rialto/runtime/src/rialto_poa.rs +++ b/bin/rialto/runtime/src/rialto_poa.rs @@ -23,8 +23,8 @@ use bp_header_chain::InclusionProofVerifier; use frame_support::RuntimeDebug; use hex_literal::hex; use pallet_bridge_eth_poa::{ - AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, ValidatorsConfiguration, - ValidatorsSource, + AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, + ValidatorsConfiguration, ValidatorsSource, }; use sp_std::prelude::*; @@ -79,11 +79,14 @@ pub fn genesis_header() -> AuraHeader { timestamp: 0, number: 0, author: Default::default(), - transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").into(), + transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + .into(), + uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") + .into(), extra_data: vec![], state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), + receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + .into(), log_bloom: Default::default(), gas_used: Default::default(), gas_limit: 0x222222.into(), @@ -128,12 +131,17 @@ impl InclusionProofVerifier for RialtoBlockchain { type Transaction = RawTransaction; type TransactionInclusionProof = EthereumTransactionInclusionProof; - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { - let is_transaction_finalized = - crate::BridgeRialtoPoa::verify_transaction_finalized(proof.block, proof.index, &proof.proof); + fn verify_transaction_inclusion_proof( + proof: &Self::TransactionInclusionProof, + ) -> Option { + let is_transaction_finalized = crate::BridgeRialtoPoa::verify_transaction_finalized( + proof.block, + proof.index, + &proof.proof, + ); if !is_transaction_finalized { - return None; + return None } proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3286d364c7e56..ecca6e823c699 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -41,7 +41,10 @@ use sp_runtime::{ traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero}, FixedPointNumber, FixedPointOperand, FixedU128, }; -use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, vec::Vec}; +use sp_std::{ + cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, + vec::Vec, +}; use sp_trie::StorageProof; /// Bidirectional message bridge. @@ -64,7 +67,9 @@ pub trait MessageBridge { type BridgedChain: BridgedChainWithMessages; /// Convert Bridged chain balance into This chain balance. - fn bridged_balance_to_this_balance(bridged_balance: BalanceOf>) -> BalanceOf>; + fn bridged_balance_to_this_balance( + bridged_balance: BalanceOf>, + ) -> BalanceOf>; } /// Chain that has `pallet-bridge-messages` and `dispatch` modules. @@ -83,7 +88,14 @@ pub trait ChainWithMessages { /// different weights. type Weight: From + PartialOrd; /// Type of balances that is used on the chain. - type Balance: Encode + Decode + CheckedAdd + CheckedDiv + CheckedMul + PartialOrd + From + Copy; + type Balance: Encode + + Decode + + CheckedAdd + + CheckedDiv + + CheckedMul + + PartialOrd + + From + + Copy; } /// Message related transaction parameters estimation. @@ -138,7 +150,8 @@ pub trait BridgedChainWithMessages: ChainWithMessages { message_dispatch_weight: WeightOf, ) -> MessageTransaction>; - /// Returns minimal transaction fee that must be paid for given transaction at the Bridged chain. + /// Returns minimal transaction fee that must be paid for given transaction at the Bridged + /// chain. fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } @@ -158,10 +171,11 @@ type RawStorageProof = Vec>; /// Compute fee of transaction at runtime where regular transaction payment pallet is being used. /// -/// The value of `multiplier` parameter is the expected value of `pallet_transaction_payment::NextFeeMultiplier` -/// at the moment when transaction is submitted. If you're charging this payment in advance (and that's what -/// happens with delivery and confirmation transaction in this crate), then there's a chance that the actual -/// fee will be larger than what is paid in advance. So the value must be chosen carefully. +/// The value of `multiplier` parameter is the expected value of +/// `pallet_transaction_payment::NextFeeMultiplier` at the moment when transaction is submitted. If +/// you're charging this payment in advance (and that's what happens with delivery and confirmation +/// transaction in this crate), then there's a chance that the actual fee will be larger than what +/// is paid in advance. So the value must be chosen carefully. pub fn transaction_payment( base_extrinsic_weight: Weight, per_byte_fee: Balance, @@ -224,7 +238,8 @@ pub mod source { } /// 'Parsed' message delivery proof - inbound lane id and its state. - pub type ParsedMessagesDeliveryProofFromBridgedChain = (LaneId, InboundLaneData>>); + pub type ParsedMessagesDeliveryProofFromBridgedChain = + (LaneId, InboundLaneData>>); /// Message verifier that is doing all basic checks. /// @@ -236,19 +251,27 @@ pub mod source { /// Following checks are made: /// /// - message is rejected if its lane is currently blocked; - /// - message is rejected if there are too many pending (undelivered) messages at the outbound lane; - /// - check that the sender has rights to dispatch the call on target chain using provided dispatch origin; + /// - message is rejected if there are too many pending (undelivered) messages at the outbound + /// lane; + /// - check that the sender has rights to dispatch the call on target chain using provided + /// dispatch origin; /// - check that the sender has paid enough funds for both message delivery and dispatch. #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); pub(crate) const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; pub(crate) const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; - pub(crate) const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; - pub(crate) const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; + pub(crate) const BAD_ORIGIN: &str = + "Unable to match the source origin to expected target origin."; + pub(crate) const TOO_LOW_FEE: &str = + "Provided fee is below minimal threshold required by the lane."; - impl LaneMessageVerifier>, FromThisChainMessagePayload, BalanceOf>> - for FromThisChainMessageVerifier + impl + LaneMessageVerifier< + AccountIdOf>, + FromThisChainMessagePayload, + BalanceOf>, + > for FromThisChainMessageVerifier where B: MessageBridge, AccountIdOf>: PartialEq + Clone, @@ -264,7 +287,7 @@ pub mod source { ) -> Result<(), Self::Error> { // reject message if lane is blocked if !ThisChain::::is_outbound_lane_enabled(lane) { - return Err(OUTBOUND_LANE_DISABLED); + return Err(OUTBOUND_LANE_DISABLED) } // reject message if there are too many pending messages at this lane @@ -273,19 +296,20 @@ pub mod source { .latest_generated_nonce .saturating_sub(lane_outbound_data.latest_received_nonce); if pending_messages > max_pending_messages { - return Err(TOO_MANY_PENDING_MESSAGES); + return Err(TOO_MANY_PENDING_MESSAGES) } // Do the dispatch-specific check. We assume that the target chain uses // `Dispatch`, so we verify the message accordingly. - pallet_bridge_dispatch::verify_message_origin(submitter, payload).map_err(|_| BAD_ORIGIN)?; + pallet_bridge_dispatch::verify_message_origin(submitter, payload) + .map_err(|_| BAD_ORIGIN)?; let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; // compare with actual fee paid if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { - return Err(TOO_LOW_FEE); + return Err(TOO_LOW_FEE) } Ok(()) @@ -307,13 +331,13 @@ pub mod source { ) -> Result<(), &'static str> { let weight_limits = BridgedChain::::message_weight_limits(&payload.call); if !weight_limits.contains(&payload.weight.into()) { - return Err("Incorrect message weight declared"); + return Err("Incorrect message weight declared") } // The maximal size of extrinsic at Substrate-based chain depends on the - // `frame_system::Config::MaximumBlockLength` and `frame_system::Config::AvailableBlockRatio` - // constants. This check is here to be sure that the lane won't stuck because message is too - // large to fit into delivery transaction. + // `frame_system::Config::MaximumBlockLength` and + // `frame_system::Config::AvailableBlockRatio` constants. This check is here to be sure that + // the lane won't stuck because message is too large to fit into delivery transaction. // // **IMPORTANT NOTE**: the delivery transaction contains storage proof of the message, not // the message itself. The proof is always larger than the message. But unless chain state @@ -321,16 +345,17 @@ pub mod source { // transaction also contains signatures and signed extensions. Because of this, we reserve // 1/3 of the the maximal extrinsic weight for this data. if payload.call.len() > maximal_message_size::() as usize { - return Err("The message is too large to be sent over the lane"); + return Err("The message is too large to be sent over the lane") } Ok(()) } - /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged chain. + /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged + /// chain. /// - /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional conversions. - /// Returns `None` if overflow has happened. + /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional + /// conversions. Returns `None` if overflow has happened. pub fn estimate_message_dispatch_and_delivery_fee( payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, @@ -339,25 +364,23 @@ pub mod source { // // if we're going to pay dispatch fee at the target chain, then we don't include weight // of the message dispatch in the delivery transaction cost - let pay_dispatch_fee_at_target_chain = payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; + let pay_dispatch_fee_at_target_chain = + payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; let delivery_transaction = BridgedChain::::estimate_delivery_transaction( &payload.encode(), pay_dispatch_fee_at_target_chain, - if pay_dispatch_fee_at_target_chain { - 0.into() - } else { - payload.weight.into() - }, + if pay_dispatch_fee_at_target_chain { 0.into() } else { payload.weight.into() }, ); let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); // the fee (in This tokens) of all transactions that are made on This chain let confirmation_transaction = ThisChain::::estimate_delivery_confirmation_transaction(); - let confirmation_transaction_fee = ThisChain::::transaction_payment(confirmation_transaction); + let confirmation_transaction_fee = + ThisChain::::transaction_payment(confirmation_transaction); // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = - B::bridged_balance_to_this_balance(delivery_transaction_fee).checked_add(&confirmation_transaction_fee); + let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee) + .checked_add(&confirmation_transaction_fee); // before returning, add extra fee that is paid to the relayer (relayer interest) minimal_fee @@ -378,14 +401,14 @@ pub mod source { ) -> Result, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - HashOf>: - Into>::BridgedChain>>, + HashOf>: Into< + bp_runtime::HashOf< + >::BridgedChain, + >, + >, { - let FromBridgedChainMessagesDeliveryProof { - bridged_header_hash, - storage_proof, - lane, - } = proof; + let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = + proof; pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), @@ -470,14 +493,13 @@ pub mod target { impl FromBridgedChainEncodedMessageCall { /// Create encoded call. pub fn new(encoded_call: Vec) -> Self { - FromBridgedChainEncodedMessageCall { - encoded_call, - _marker: PhantomData::default(), - } + FromBridgedChainEncodedMessageCall { encoded_call, _marker: PhantomData::default() } } } - impl From> for Result { + impl From> + for Result + { fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) } @@ -495,16 +517,22 @@ pub mod target { where BalanceOf>: Saturating + FixedPointOperand, ThisDispatchInstance: 'static, - ThisRuntime: pallet_bridge_dispatch::Config - + pallet_transaction_payment::Config, + ThisRuntime: pallet_bridge_dispatch::Config< + ThisDispatchInstance, + BridgeMessageId = (LaneId, MessageNonce), + > + pallet_transaction_payment::Config, ::OnChargeTransaction: - pallet_transaction_payment::OnChargeTransaction>>, + pallet_transaction_payment::OnChargeTransaction< + ThisRuntime, + Balance = BalanceOf>, + >, ThisCurrency: Currency>, Balance = BalanceOf>>, - pallet_bridge_dispatch::Pallet: bp_message_dispatch::MessageDispatch< - AccountIdOf>, - (LaneId, MessageNonce), - Message = FromBridgedChainMessagePayload, - >, + pallet_bridge_dispatch::Pallet: + bp_message_dispatch::MessageDispatch< + AccountIdOf>, + (LaneId, MessageNonce), + Message = FromBridgedChainMessagePayload, + >, { type DispatchPayload = FromBridgedChainMessagePayload; @@ -526,8 +554,10 @@ pub mod target { message.data.payload.map_err(drop), |dispatch_origin, dispatch_weight| { let unadjusted_weight_fee = ThisRuntime::WeightToFee::calc(&dispatch_weight); - let fee_multiplier = pallet_transaction_payment::Pallet::::next_fee_multiplier(); - let adjusted_weight_fee = fee_multiplier.saturating_mul_int(unadjusted_weight_fee); + let fee_multiplier = + pallet_transaction_payment::Pallet::::next_fee_multiplier(); + let adjusted_weight_fee = + fee_multiplier.saturating_mul_int(unadjusted_weight_fee); if !adjusted_weight_fee.is_zero() { ThisCurrency::transfer( dispatch_origin, @@ -565,8 +595,11 @@ pub mod target { ) -> Result>>>, &'static str> where ThisRuntime: pallet_bridge_grandpa::Config, - HashOf>: - Into>::BridgedChain>>, + HashOf>: Into< + bp_runtime::HashOf< + >::BridgedChain, + >, + >, { verify_messages_proof_with_parser::( proof, @@ -601,12 +634,13 @@ pub mod target { fn from(err: MessageProofError) -> &'static str { match err { MessageProofError::Empty => "Messages proof is empty", - MessageProofError::MessagesCountMismatch => "Declared messages count doesn't match actual value", + MessageProofError::MessagesCountMismatch => + "Declared messages count doesn't match actual value", MessageProofError::MissingRequiredMessage => "Message is missing from the proof", - MessageProofError::FailedToDecodeMessage => "Failed to decode message from the proof", - MessageProofError::FailedToDecodeOutboundLaneState => { - "Failed to decode outbound lane data from the proof" - } + MessageProofError::FailedToDecodeMessage => + "Failed to decode message from the proof", + MessageProofError::FailedToDecodeOutboundLaneState => + "Failed to decode outbound lane data from the proof", MessageProofError::Custom(err) => err, } } @@ -629,10 +663,11 @@ pub mod target { { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { let storage_outbound_lane_data_key = - pallet_bridge_messages::storage_keys::outbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, lane_id); - self.storage - .read_value(storage_outbound_lane_data_key.0.as_ref()) - .ok()? + pallet_bridge_messages::storage_keys::outbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + lane_id, + ); + self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()? } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { @@ -652,7 +687,8 @@ pub mod target { build_parser: BuildParser, ) -> Result>>>, MessageProofError> where - BuildParser: FnOnce(HashOf>, RawStorageProof) -> Result, + BuildParser: + FnOnce(HashOf>, RawStorageProof) -> Result, Parser: MessageProofParser, { let FromBridgedChainMessagesProof { @@ -664,18 +700,19 @@ pub mod target { } = proof; // receiving proofs where end < begin is ok (if proof includes outbound lane state) - let messages_in_the_proof = if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { - // let's check that the user (relayer) has passed correct `messages_count` - // (this bounds maximal capacity of messages vec below) - let messages_in_the_proof = nonces_difference.saturating_add(1); - if messages_in_the_proof != MessageNonce::from(messages_count) { - return Err(MessageProofError::MessagesCountMismatch); - } + let messages_in_the_proof = + if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { + // let's check that the user (relayer) has passed correct `messages_count` + // (this bounds maximal capacity of messages vec below) + let messages_in_the_proof = nonces_difference.saturating_add(1); + if messages_in_the_proof != MessageNonce::from(messages_count) { + return Err(MessageProofError::MessagesCountMismatch) + } - messages_in_the_proof - } else { - 0 - }; + messages_in_the_proof + } else { + 0 + }; let parser = build_parser(bridged_header_hash, storage_proof)?; @@ -689,20 +726,15 @@ pub mod target { let raw_message_data = parser .read_raw_message(&message_key) .ok_or(MessageProofError::MissingRequiredMessage)?; - let message_data = MessageData::>>::decode(&mut &raw_message_data[..]) - .map_err(|_| MessageProofError::FailedToDecodeMessage)?; - messages.push(Message { - key: message_key, - data: message_data, - }); + let message_data = + MessageData::>>::decode(&mut &raw_message_data[..]) + .map_err(|_| MessageProofError::FailedToDecodeMessage)?; + messages.push(Message { key: message_key, data: message_data }); } // Now let's check if proof contains outbound lane state proof. It is optional, so we // simply ignore `read_value` errors and missing value. - let mut proved_lane_messages = ProvedLaneMessages { - lane_state: None, - messages, - }; + let mut proved_lane_messages = ProvedLaneMessages { lane_state: None, messages }; let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane); if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { proved_lane_messages.lane_state = Some( @@ -713,7 +745,7 @@ pub mod target { // Now we may actually check if the proof is empty or not. if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { - return Err(MessageProofError::Empty); + return Err(MessageProofError::Empty) } // We only support single lane messages in this schema @@ -739,7 +771,8 @@ mod tests { const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048; const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; - /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from BridgedChain; + /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from + /// BridgedChain; #[derive(Debug, PartialEq, Eq)] struct OnThisChainBridge; @@ -752,12 +785,15 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; - fn bridged_balance_to_this_balance(bridged_balance: BridgedChainBalance) -> ThisChainBalance { + fn bridged_balance_to_this_balance( + bridged_balance: BridgedChainBalance, + ) -> ThisChainBalance { ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) } } - /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from ThisChain; + /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from + /// ThisChain; #[derive(Debug, PartialEq, Eq)] struct OnBridgedChainBridge; @@ -892,7 +928,9 @@ mod tests { } fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { - ThisChainBalance(transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) + ThisChainBalance( + transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, + ) } } @@ -913,7 +951,9 @@ mod tests { unreachable!() } - fn transaction_payment(_transaction: MessageTransaction>) -> BalanceOf { + fn transaction_payment( + _transaction: MessageTransaction>, + ) -> BalanceOf { unreachable!() } } @@ -944,7 +984,9 @@ mod tests { unreachable!() } - fn transaction_payment(_transaction: MessageTransaction>) -> BalanceOf { + fn transaction_payment( + _transaction: MessageTransaction>, + ) -> BalanceOf { unreachable!() } } @@ -955,7 +997,8 @@ mod tests { } fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive { - let begin = std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); + let begin = + std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } @@ -971,7 +1014,9 @@ mod tests { } fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { - BridgedChainBalance(transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32) + BridgedChainBalance( + transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, + ) } } @@ -982,19 +1027,22 @@ mod tests { #[test] fn message_from_bridged_chain_is_decoded() { // the message is encoded on the bridged chain - let message_on_bridged_chain = source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: ThisChainCall::Transfer.encode(), - } - .encode(); + let message_on_bridged_chain = + source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: 100, + origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: ThisChainCall::Transfer.encode(), + } + .encode(); // and sent to this chain where it is decoded let message_on_this_chain = - target::FromBridgedChainMessagePayload::::decode(&mut &message_on_bridged_chain[..]) - .unwrap(); + target::FromBridgedChainMessagePayload::::decode( + &mut &message_on_bridged_chain[..], + ) + .unwrap(); assert_eq!( message_on_this_chain, target::FromBridgedChainMessagePayload:: { @@ -1013,7 +1061,8 @@ mod tests { const TEST_LANE_ID: &LaneId = b"test"; const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; - fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { + fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload + { source::FromThisChainMessagePayload:: { spec_version: 1, weight: 100, @@ -1042,11 +1091,14 @@ mod tests { // let's check if estimation is less than hardcoded, if dispatch is paid at target chain let mut payload_with_pay_on_target = regular_outbound_message_payload(); payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; - let fee_at_source = source::estimate_message_dispatch_and_delivery_fee::( - &payload_with_pay_on_target, - OnThisChainBridge::RELAYER_FEE_PERCENT, - ) - .expect("estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message"); + let fee_at_source = + source::estimate_message_dispatch_and_delivery_fee::( + &payload_with_pay_on_target, + OnThisChainBridge::RELAYER_FEE_PERCENT, + ) + .expect( + "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", + ); assert!( fee_at_source < EXPECTED_MINIMAL_FEE.into(), "Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}", @@ -1065,16 +1117,14 @@ mod tests { ), Err(source::TOO_LOW_FEE) ); - assert!( - source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(), - ); + assert!(source::FromThisChainMessageVerifier::::verify_message( + &Sender::Root, + &ThisChainBalance(1_000_000), + TEST_LANE_ID, + &test_lane_outbound_data(), + &payload, + ) + .is_ok(),); } #[test] @@ -1109,16 +1159,14 @@ mod tests { ), Err(source::BAD_ORIGIN) ); - assert!( - source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(), - ); + assert!(source::FromThisChainMessageVerifier::::verify_message( + &Sender::Root, + &ThisChainBalance(1_000_000), + TEST_LANE_ID, + &test_lane_outbound_data(), + &payload, + ) + .is_ok(),); } #[test] @@ -1143,16 +1191,14 @@ mod tests { ), Err(source::BAD_ORIGIN) ); - assert!( - source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(1)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(), - ); + assert!(source::FromThisChainMessageVerifier::::verify_message( + &Sender::Signed(ThisChainAccountId(1)), + &ThisChainBalance(1_000_000), + TEST_LANE_ID, + &test_lane_outbound_data(), + &payload, + ) + .is_ok(),); } #[test] @@ -1189,64 +1235,58 @@ mod tests { #[test] fn verify_chain_message_rejects_message_with_too_small_declared_weight() { - assert!( - source::verify_chain_message::(&source::FromThisChainMessagePayload::< - OnThisChainBridge, - > { + assert!(source::verify_chain_message::( + &source::FromThisChainMessagePayload:: { spec_version: 1, weight: 5, origin: bp_message_dispatch::CallOrigin::SourceRoot, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![1, 2, 3, 4, 5, 6], - },) - .is_err() - ); + }, + ) + .is_err()); } #[test] fn verify_chain_message_rejects_message_with_too_large_declared_weight() { - assert!( - source::verify_chain_message::(&source::FromThisChainMessagePayload::< - OnThisChainBridge, - > { + assert!(source::verify_chain_message::( + &source::FromThisChainMessagePayload:: { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, origin: bp_message_dispatch::CallOrigin::SourceRoot, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![1, 2, 3, 4, 5, 6], - },) - .is_err() - ); + }, + ) + .is_err()); } #[test] fn verify_chain_message_rejects_message_too_large_message() { - assert!( - source::verify_chain_message::(&source::FromThisChainMessagePayload::< - OnThisChainBridge, - > { + assert!(source::verify_chain_message::( + &source::FromThisChainMessagePayload:: { spec_version: 1, weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, origin: bp_message_dispatch::CallOrigin::SourceRoot, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, call: vec![0; source::maximal_message_size::() as usize + 1], - },) - .is_err() - ); + }, + ) + .is_err()); } #[test] fn verify_chain_message_accepts_maximal_message() { assert_eq!( - source::verify_chain_message::(&source::FromThisChainMessagePayload::< - OnThisChainBridge, - > { - spec_version: 1, - weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![0; source::maximal_message_size::() as _], - },), + source::verify_chain_message::( + &source::FromThisChainMessagePayload:: { + spec_version: 1, + weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, + origin: bp_message_dispatch::CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + call: vec![0; source::maximal_message_size::() as _], + }, + ), Ok(()), ); } @@ -1338,13 +1378,15 @@ mod tests { #[test] fn message_proof_is_rejected_if_required_message_is_missing() { assert_eq!( - target::verify_messages_proof_with_parser::(messages_proof(10), 10, |_, _| Ok( - TestMessageProofParser { + target::verify_messages_proof_with_parser::( + messages_proof(10), + 10, + |_, _| Ok(TestMessageProofParser { failing: false, messages: 1..=5, outbound_lane_data: None, - } - ),), + }), + ), Err(target::MessageProofError::MissingRequiredMessage), ); } @@ -1352,13 +1394,15 @@ mod tests { #[test] fn message_proof_is_rejected_if_message_decode_fails() { assert_eq!( - target::verify_messages_proof_with_parser::(messages_proof(10), 10, |_, _| Ok( - TestMessageProofParser { + target::verify_messages_proof_with_parser::( + messages_proof(10), + 10, + |_, _| Ok(TestMessageProofParser { failing: true, messages: 1..=10, outbound_lane_data: None, - } - ),), + }), + ), Err(target::MessageProofError::FailedToDecodeMessage), ); } @@ -1366,8 +1410,10 @@ mod tests { #[test] fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() { assert_eq!( - target::verify_messages_proof_with_parser::(messages_proof(0), 0, |_, _| Ok( - TestMessageProofParser { + target::verify_messages_proof_with_parser::( + messages_proof(0), + 0, + |_, _| Ok(TestMessageProofParser { failing: true, messages: no_messages_range(), outbound_lane_data: Some(OutboundLaneData { @@ -1375,8 +1421,8 @@ mod tests { latest_received_nonce: 1, latest_generated_nonce: 1, }), - } - ),), + }), + ), Err(target::MessageProofError::FailedToDecodeOutboundLaneState), ); } @@ -1384,13 +1430,15 @@ mod tests { #[test] fn message_proof_is_rejected_if_it_is_empty() { assert_eq!( - target::verify_messages_proof_with_parser::(messages_proof(0), 0, |_, _| Ok( - TestMessageProofParser { + target::verify_messages_proof_with_parser::( + messages_proof(0), + 0, + |_, _| Ok(TestMessageProofParser { failing: false, messages: no_messages_range(), outbound_lane_data: None, - } - ),), + }), + ), Err(target::MessageProofError::Empty), ); } @@ -1398,8 +1446,10 @@ mod tests { #[test] fn non_empty_message_proof_without_messages_is_accepted() { assert_eq!( - target::verify_messages_proof_with_parser::(messages_proof(0), 0, |_, _| Ok( - TestMessageProofParser { + target::verify_messages_proof_with_parser::( + messages_proof(0), + 0, + |_, _| Ok(TestMessageProofParser { failing: false, messages: no_messages_range(), outbound_lane_data: Some(OutboundLaneData { @@ -1407,8 +1457,8 @@ mod tests { latest_received_nonce: 1, latest_generated_nonce: 1, }), - } - ),), + }), + ), Ok(vec![( Default::default(), ProvedLaneMessages { @@ -1428,8 +1478,10 @@ mod tests { #[test] fn non_empty_message_proof_is_accepted() { assert_eq!( - target::verify_messages_proof_with_parser::(messages_proof(1), 1, |_, _| Ok( - TestMessageProofParser { + target::verify_messages_proof_with_parser::( + messages_proof(1), + 1, + |_, _| Ok(TestMessageProofParser { failing: false, messages: 1..=1, outbound_lane_data: Some(OutboundLaneData { @@ -1437,8 +1489,8 @@ mod tests { latest_received_nonce: 1, latest_generated_nonce: 1, }), - } - ),), + }), + ), Ok(vec![( Default::default(), ProvedLaneMessages { @@ -1448,14 +1500,8 @@ mod tests { latest_generated_nonce: 1, }), messages: vec![Message { - key: MessageKey { - lane_id: Default::default(), - nonce: 1 - }, - data: MessageData { - payload: 1u64.encode(), - fee: BridgedChainBalance(0) - }, + key: MessageKey { lane_id: Default::default(), nonce: 1 }, + data: MessageData { payload: 1u64.encode(), fee: BridgedChainBalance(0) }, }], }, )] @@ -1494,10 +1540,7 @@ mod tests { 10, FixedU128::zero(), |weight| weight, - MessageTransaction { - size: 50, - dispatch_weight: 777 - }, + MessageTransaction { size: 50, dispatch_weight: 777 }, ), 100 + 50 * 10, ); @@ -1513,10 +1556,7 @@ mod tests { 10, FixedU128::one(), |weight| weight, - MessageTransaction { - size: 50, - dispatch_weight: 777 - }, + MessageTransaction { size: 50, dispatch_weight: 777 }, ), 100 + 50 * 10 + 777, ); diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 3785f4a4607f0..217560e114344 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -20,8 +20,8 @@ #![cfg(feature = "runtime-benchmarks")] use crate::messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, AccountIdOf, BalanceOf, - BridgedChain, HashOf, MessageBridge, ThisChain, + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + AccountIdOf, BalanceOf, BridgedChain, HashOf, MessageBridge, ThisChain, }; use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload}; @@ -29,13 +29,16 @@ use bp_runtime::ChainId; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; use frame_support::weights::Weight; -use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams, ProofSize}; +use pallet_bridge_messages::benchmarking::{ + MessageDeliveryProofParams, MessageProofParams, ProofSize, +}; use sp_core::Hasher; use sp_runtime::traits::Header; use sp_std::prelude::*; use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut}; -/// Generate ed25519 signature to be used in `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. +/// Generate ed25519 signature to be used in +/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. /// /// Returns public key of the signer and the signature itself. pub fn ed25519_sign( @@ -47,8 +50,8 @@ pub fn ed25519_sign( ) -> ([u8; 32], [u8; 64]) { // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) let target_secret = SecretKey::from_bytes(&[ - 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, 197, 105, 123, 050, - 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, + 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, + 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, ]) .expect("harcoded key is valid"); let target_public: PublicKey = (&target_secret).into(); @@ -56,7 +59,8 @@ pub fn ed25519_sign( let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); - let target_pair = ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); + let target_pair = + ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); let signature_message = pallet_bridge_dispatch::account_ownership_digest( target_call, @@ -92,11 +96,8 @@ where MH: Fn(H::Out) -> ::Header, { // prepare Bridged chain storage with messages and (optionally) outbound lane state - let message_count = params - .message_nonces - .end() - .saturating_sub(*params.message_nonces.start()) - + 1; + let message_count = + params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1; let mut storage_keys = Vec::with_capacity(message_count as usize + 1); let mut root = Default::default(); let mut mdb = MemoryDB::default(); @@ -105,10 +106,7 @@ where // insert messages for nonce in params.message_nonces.clone() { - let message_key = MessageKey { - lane_id: params.lane, - nonce, - }; + let message_key = MessageKey { lane_id: params.lane, nonce }; let message_data = MessageData { fee: BalanceOf::>::from(0), payload: message_payload.clone(), @@ -220,7 +218,7 @@ fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: Proo .expect("record_all_keys should not fail in benchmarks"); let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); if size > minimal_trie_size as _ { - return root; + return root } let mut trie = TrieDBMut::::from_existing(mdb, &mut root) diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs index db8b2256c8074..813c1bfe884dd 100644 --- a/modules/currency-exchange/src/benchmarking.rs +++ b/modules/currency-exchange/src/benchmarking.rs @@ -18,7 +18,10 @@ //! So we are giving runtime opportunity to prepare environment and construct proof //! before invoking module calls. -use super::{Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, Pallet as CurrencyExchangePallet}; +use super::{ + Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, + Pallet as CurrencyExchangePallet, +}; use sp_std::prelude::*; use frame_benchmarking::{account, benchmarks_instance_pallet}; @@ -37,8 +40,8 @@ pub struct ProofParams { pub recipient: Recipient, /// When true, recipient must exists before import. pub recipient_exists: bool, - /// When 0, transaction should have minimal possible size. When this value has non-zero value n, - /// transaction size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. + /// When 0, transaction should have minimal possible size. When this value has non-zero value + /// n, transaction size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. pub transaction_size_factor: u32, /// When 0, proof should have minimal possible size. When this value has non-zero value n, /// proof size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs index 550467f5d6fe7..31b789dd97e73 100644 --- a/modules/currency-exchange/src/lib.rs +++ b/modules/currency-exchange/src/lib.rs @@ -19,7 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_currency_exchange::{ - CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, RecipientsMap, + CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, + RecipientsMap, }; use bp_header_chain::InclusionProofVerifier; use frame_support::ensure; @@ -92,7 +93,8 @@ pub mod pallet { { // if any changes were made to the storage, we can't just return error here, because // otherwise the same proof may be imported again - let deposit_result = T::DepositInto::deposit_into(deposit.recipient, deposit.amount); + let deposit_result = + T::DepositInto::deposit_into(deposit.recipient, deposit.amount); match deposit_result { Ok(_) => (), Err(ExchangeError::DepositPartiallyFailed) => (), @@ -160,7 +162,7 @@ impl, I: 'static> Pallet { err, ); - return false; + return false } true @@ -205,23 +207,16 @@ fn prepare_deposit_details, I: 'static>( .ok_or(Error::::UnfinalizedTransaction)?; // parse transaction - let transaction = - >::PeerMaybeLockFundsTransaction::parse(&transaction).map_err(Error::::from)?; + let transaction = >::PeerMaybeLockFundsTransaction::parse(&transaction) + .map_err(Error::::from)?; let transfer_id = transaction.id; - ensure!( - !Transfers::::contains_key(&transfer_id), - Error::::AlreadyClaimed - ); + ensure!(!Transfers::::contains_key(&transfer_id), Error::::AlreadyClaimed); // grant recipient let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; - Ok(DepositDetails { - transfer_id, - recipient, - amount, - }) + Ok(DepositDetails { transfer_id, recipient, amount }) } #[cfg(test)] @@ -231,7 +226,9 @@ mod tests { use super::*; use bp_currency_exchange::LockFundsTransaction; - use frame_support::{assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight}; + use frame_support::{ + assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight, + }; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -264,7 +261,9 @@ mod tests { type Transaction = RawTransaction; type TransactionInclusionProof = (bool, RawTransaction); - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option { + fn verify_transaction_inclusion_proof( + proof: &Self::TransactionInclusionProof, + ) -> Option { if proof.0 { Some(proof.1.clone()) } else { @@ -295,7 +294,9 @@ mod tests { type PeerRecipient = AccountId; type Recipient = AccountId; - fn map(peer_recipient: Self::PeerRecipient) -> bp_currency_exchange::Result { + fn map( + peer_recipient: Self::PeerRecipient, + ) -> bp_currency_exchange::Result { match peer_recipient { UNKNOWN_RECIPIENT_ID => Err(ExchangeError::FailedToMapRecipients), _ => Ok(peer_recipient * 10), @@ -323,10 +324,14 @@ mod tests { type Recipient = AccountId; type Amount = u64; - fn deposit_into(_recipient: Self::Recipient, amount: Self::Amount) -> bp_currency_exchange::Result<()> { + fn deposit_into( + _recipient: Self::Recipient, + amount: Self::Amount, + ) -> bp_currency_exchange::Result<()> { match amount { amount if amount < MAX_DEPOSIT_AMOUNT * 10 => Ok(()), - amount if amount == MAX_DEPOSIT_AMOUNT * 10 => Err(ExchangeError::DepositPartiallyFailed), + amount if amount == MAX_DEPOSIT_AMOUNT * 10 => + Err(ExchangeError::DepositPartiallyFailed), _ => Err(ExchangeError::DepositFailed), } } @@ -391,25 +396,22 @@ mod tests { } fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); sp_io::TestExternalities::new(t) } fn transaction(id: u64) -> RawTransaction { - RawTransaction { - id, - recipient: 1, - amount: 2, - } + RawTransaction { id, recipient: 1, amount: 2 } } #[test] fn unfinalized_transaction_rejected() { new_test_ext().execute_with(|| { assert_noop!( - Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (false, transaction(0))), + Exchange::import_peer_transaction( + Origin::signed(SUBMITTER), + (false, transaction(0)) + ), Error::::UnfinalizedTransaction, ); }); diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 698d3842a0cd1..3039c6e31654d 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -60,7 +60,13 @@ pub mod pallet { /// it comes from the messages module. type BridgeMessageId: Parameter; /// Type of account ID on source chain. - type SourceChainAccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; + type SourceChainAccountId: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + MaybeDisplay + + Ord + + Default; /// Type of account public key on target chain. type TargetChainAccountPublic: Parameter + IdentifyAccount; /// Type of signature that may prove that the message has been signed by @@ -75,8 +81,8 @@ pub mod pallet { >; /// Pre-dispatch filter for incoming calls. /// - /// The pallet will filter all incoming calls right before they're dispatched. If this filter - /// rejects the call, special event (`Event::MessageCallRejected`) is emitted. + /// The pallet will filter all incoming calls right before they're dispatched. If this + /// filter rejects the call, special event (`Event::MessageCallRejected`) is emitted. type CallFilter: Contains<>::Call>; /// The type that is used to wrap the `Self::Call` when it is moved over bridge. /// @@ -136,8 +142,12 @@ pub mod pallet { } impl, I: 'static> MessageDispatch for Pallet { - type Message = - MessagePayload; + type Message = MessagePayload< + T::SourceChainAccountId, + T::TargetChainAccountPublic, + T::TargetChainSignature, + T::EncodedCall, + >; fn dispatch_weight(message: &Self::Message) -> bp_message_dispatch::Weight { message.weight @@ -165,8 +175,8 @@ impl, I: 'static> MessageDispatch dispatch_result: false, unspent_weight: 0, dispatch_fee_paid_during_dispatch: false, - }; - } + } + }, }; // verify spec version @@ -191,7 +201,7 @@ impl, I: 'static> MessageDispatch expected_version, message.spec_version, )); - return dispatch_result; + return dispatch_result } // now that we have spec version checked, let's decode the call @@ -205,18 +215,19 @@ impl, I: 'static> MessageDispatch id, ); Self::deposit_event(Event::MessageCallDecodeFailed(source_chain, id)); - return dispatch_result; - } + return dispatch_result + }, }; // prepare dispatch origin let origin_account = match message.origin { CallOrigin::SourceRoot => { - let hex_id = derive_account_id::(source_chain, SourceAccount::Root); + let hex_id = + derive_account_id::(source_chain, SourceAccount::Root); let target_id = T::AccountIdConverter::convert(hex_id); log::trace!(target: "runtime::bridge-dispatch", "Root Account: {:?}", &target_id); target_id - } + }, CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { let digest = account_ownership_digest( &call, @@ -237,18 +248,19 @@ impl, I: 'static> MessageDispatch target_signature, ); Self::deposit_event(Event::MessageSignatureMismatch(source_chain, id)); - return dispatch_result; + return dispatch_result } log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account); target_account - } + }, CallOrigin::SourceAccount(source_account_id) => { - let hex_id = derive_account_id(source_chain, SourceAccount::Account(source_account_id)); + let hex_id = + derive_account_id(source_chain, SourceAccount::Account(source_account_id)); let target_id = T::AccountIdConverter::convert(hex_id); log::trace!(target: "runtime::bridge-dispatch", "Source Account: {:?}", &target_id); target_id - } + }, }; // filter the call @@ -261,7 +273,7 @@ impl, I: 'static> MessageDispatch call, ); Self::deposit_event(Event::MessageCallRejected(source_chain, id)); - return dispatch_result; + return dispatch_result } // verify weight @@ -284,12 +296,15 @@ impl, I: 'static> MessageDispatch expected_weight, message.weight, )); - return dispatch_result; + return dispatch_result } // pay dispatch fee right before dispatch - let pay_dispatch_fee_at_target_chain = message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; - if pay_dispatch_fee_at_target_chain && pay_dispatch_fee(&origin_account, message.weight).is_err() { + let pay_dispatch_fee_at_target_chain = + message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; + if pay_dispatch_fee_at_target_chain && + pay_dispatch_fee(&origin_account, message.weight).is_err() + { log::trace!( target: "runtime::bridge-dispatch", "Failed to pay dispatch fee for dispatching message {:?}/{:?} with weight {}", @@ -303,7 +318,7 @@ impl, I: 'static> MessageDispatch origin_account, message.weight, )); - return dispatch_result; + return dispatch_result } dispatch_result.dispatch_fee_paid_during_dispatch = pay_dispatch_fee_at_target_chain; @@ -343,9 +358,19 @@ impl, I: 'static> MessageDispatch /// For example, if a message is sent from a "regular" account on the source chain it will not be /// allowed to be dispatched as Root on the target chain. This is a useful check to do on the source /// chain _before_ sending a message whose dispatch will be rejected on the target chain. -pub fn verify_message_origin( +pub fn verify_message_origin< + SourceChainAccountId, + TargetChainAccountPublic, + TargetChainSignature, + Call, +>( sender_origin: &RawOrigin, - message: &MessagePayload, + message: &MessagePayload< + SourceChainAccountId, + TargetChainAccountPublic, + TargetChainSignature, + Call, + >, ) -> Result, BadOrigin> where SourceChainAccountId: PartialEq + Clone, @@ -354,21 +379,19 @@ where CallOrigin::SourceRoot => { ensure!(sender_origin == &RawOrigin::Root, BadOrigin); Ok(None) - } + }, CallOrigin::TargetAccount(ref source_account_id, _, _) => { - ensure!( - sender_origin == &RawOrigin::Signed(source_account_id.clone()), - BadOrigin - ); + ensure!(sender_origin == &RawOrigin::Signed(source_account_id.clone()), BadOrigin); Ok(Some(source_account_id.clone())) - } + }, CallOrigin::SourceAccount(ref source_account_id) => { ensure!( - sender_origin == &RawOrigin::Signed(source_account_id.clone()) || sender_origin == &RawOrigin::Root, + sender_origin == &RawOrigin::Signed(source_account_id.clone()) || + sender_origin == &RawOrigin::Root, BadOrigin ); Ok(Some(source_account_id.clone())) - } + }, } } @@ -533,16 +556,17 @@ mod tests { const TEST_WEIGHT: Weight = 1_000_000_000; fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); sp_io::TestExternalities::new(t) } fn prepare_message( origin: CallOrigin, call: Call, - ) -> as MessageDispatch::BridgeMessageId>>::Message { + ) -> as MessageDispatch< + AccountId, + ::BridgeMessageId, + >>::Message { MessagePayload { spec_version: TEST_SPEC_VERSION, weight: TEST_WEIGHT, @@ -554,20 +578,29 @@ mod tests { fn prepare_root_message( call: Call, - ) -> as MessageDispatch::BridgeMessageId>>::Message { + ) -> as MessageDispatch< + AccountId, + ::BridgeMessageId, + >>::Message { prepare_message(CallOrigin::SourceRoot, call) } fn prepare_target_message( call: Call, - ) -> as MessageDispatch::BridgeMessageId>>::Message { + ) -> as MessageDispatch< + AccountId, + ::BridgeMessageId, + >>::Message { let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); prepare_message(origin, call) } fn prepare_source_message( call: Call, - ) -> as MessageDispatch::BridgeMessageId>>::Message { + ) -> as MessageDispatch< + AccountId, + ::BridgeMessageId, + >>::Message { let origin = CallOrigin::SourceAccount(1); prepare_message(origin, call) } @@ -578,13 +611,20 @@ mod tests { let id = [0; 4]; const BAD_SPEC_VERSION: SpecVersion = 99; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System( + >::remark(vec![1, 2, 3]), + )); let weight = message.weight; message.spec_version = BAD_SPEC_VERSION; System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert_eq!(result.unspent_weight, weight); assert!(!result.dispatch_result); @@ -592,12 +632,14 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageVersionSpecMismatch( - SOURCE_CHAIN_ID, - id, - TEST_SPEC_VERSION, - BAD_SPEC_VERSION - )), + event: Event::Dispatch( + call_dispatch::Event::::MessageVersionSpecMismatch( + SOURCE_CHAIN_ID, + id, + TEST_SPEC_VERSION, + BAD_SPEC_VERSION + ) + ), topics: vec![], }], ); @@ -612,13 +654,16 @@ mod tests { let call_weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = 7; - assert!( - call_weight != 7, - "needed for test to actually trigger a weight mismatch" - ); + assert!(call_weight != 7, "needed for test to actually trigger a weight mismatch"); System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert_eq!(result.unspent_weight, 7); assert!(!result.dispatch_result); @@ -626,12 +671,14 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageWeightMismatch( - SOURCE_CHAIN_ID, - id, - call_weight, - 7, - )), + event: Event::Dispatch( + call_dispatch::Event::::MessageWeightMismatch( + SOURCE_CHAIN_ID, + id, + call_weight, + 7, + ) + ), topics: vec![], }], ); @@ -651,7 +698,13 @@ mod tests { let weight = message.weight; System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert_eq!(result.unspent_weight, weight); assert!(!result.dispatch_result); @@ -659,10 +712,12 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageSignatureMismatch( - SOURCE_CHAIN_ID, - id - )), + event: Event::Dispatch( + call_dispatch::Event::::MessageSignatureMismatch( + SOURCE_CHAIN_ID, + id + ) + ), topics: vec![], }], ); @@ -675,7 +730,13 @@ mod tests { let id = [0; 4]; System::set_block_number(1); - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Err(()), |_, _| unreachable!()); + Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Err(()), + |_, _| unreachable!(), + ); assert_eq!( System::events(), @@ -696,13 +757,20 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System( + >::remark(vec![1, 2, 3]), + )); let weight = message.weight; message.call.0 = vec![]; System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert_eq!(result.unspent_weight, weight); assert!(!result.dispatch_result); @@ -710,10 +778,12 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageCallDecodeFailed( - SOURCE_CHAIN_ID, - id - )), + event: Event::Dispatch( + call_dispatch::Event::::MessageCallDecodeFailed( + SOURCE_CHAIN_ID, + id + ) + ), topics: vec![], }], ); @@ -725,13 +795,21 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::fill_block(Perbill::from_percent(75))); + let call = Call::System(>::fill_block( + Perbill::from_percent(75), + )); let weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = weight; System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert_eq!(result.unspent_weight, weight); assert!(!result.dispatch_result); @@ -739,10 +817,12 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageCallRejected( - SOURCE_CHAIN_ID, - id - )), + event: Event::Dispatch( + call_dispatch::Event::::MessageCallRejected( + SOURCE_CHAIN_ID, + id + ) + ), topics: vec![], }], ); @@ -754,13 +834,17 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System( + >::remark(vec![1, 2, 3]), + )); let weight = message.weight; message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Err(())); + let result = + Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| { + Err(()) + }); assert_eq!(result.unspent_weight, weight); assert!(!result.dispatch_result); @@ -768,15 +852,17 @@ mod tests { System::events(), vec![EventRecord { phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageDispatchPaymentFailed( - SOURCE_CHAIN_ID, - id, - AccountIdConverter::convert(derive_account_id::( + event: Event::Dispatch( + call_dispatch::Event::::MessageDispatchPaymentFailed( SOURCE_CHAIN_ID, - SourceAccount::Root - )), - TEST_WEIGHT, - )), + id, + AccountIdConverter::convert(derive_account_id::( + SOURCE_CHAIN_ID, + SourceAccount::Root + )), + TEST_WEIGHT, + ) + ), topics: vec![], }], ); @@ -788,12 +874,19 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = - prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let mut message = prepare_root_message(Call::System( + >::remark(vec![1, 2, 3]), + )); message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| Ok(())); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| Ok(()), + ); assert!(result.dispatch_fee_paid_during_dispatch); assert!(result.dispatch_result); @@ -821,7 +914,13 @@ mod tests { let message = prepare_target_message(call); System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert!(!result.dispatch_fee_paid_during_dispatch); assert!(!result.dispatch_result); @@ -844,10 +943,18 @@ mod tests { fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { let id = [0; 4]; - let message = prepare_root_message(Call::System(>::remark(vec![1, 2, 3]))); + let message = prepare_root_message(Call::System( + >::remark(vec![1, 2, 3]), + )); System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert!(!result.dispatch_fee_paid_during_dispatch); assert!(result.dispatch_result); @@ -875,7 +982,13 @@ mod tests { let message = prepare_target_message(call); System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert!(!result.dispatch_fee_paid_during_dispatch); assert!(result.dispatch_result); @@ -903,7 +1016,13 @@ mod tests { let message = prepare_source_message(call); System::set_block_number(1); - let result = Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| unreachable!()); + let result = Dispatch::dispatch( + SOURCE_CHAIN_ID, + TARGET_CHAIN_ID, + id, + Ok(message), + |_, _| unreachable!(), + ); assert!(!result.dispatch_fee_paid_during_dispatch); assert!(result.dispatch_result); @@ -931,10 +1050,7 @@ mod tests { assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(None))); // when message is sent by some real account, CallOrigin::SourceRoot is not allowed - assert!(matches!( - verify_message_origin(&RawOrigin::Signed(1), &message), - Err(BadOrigin) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Signed(1), &message), Err(BadOrigin))); } #[test] @@ -943,23 +1059,14 @@ mod tests { let message = prepare_target_message(call); // When message is sent by Root, CallOrigin::TargetAccount is not allowed - assert!(matches!( - verify_message_origin(&RawOrigin::Root, &message), - Err(BadOrigin) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Err(BadOrigin))); // When message is sent by some other account, it is rejected - assert!(matches!( - verify_message_origin(&RawOrigin::Signed(2), &message), - Err(BadOrigin) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Signed(2), &message), Err(BadOrigin))); // When message is sent by a real account, it is allowed to have origin // CallOrigin::TargetAccount - assert!(matches!( - verify_message_origin(&RawOrigin::Signed(1), &message), - Ok(Some(1)) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Signed(1), &message), Ok(Some(1)))); } #[test] @@ -968,16 +1075,10 @@ mod tests { let message = prepare_source_message(call); // Sending a message from the expected origin account works - assert!(matches!( - verify_message_origin(&RawOrigin::Signed(1), &message), - Ok(Some(1)) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Signed(1), &message), Ok(Some(1)))); // If we send a message from a different account, it is rejected - assert!(matches!( - verify_message_origin(&RawOrigin::Signed(2), &message), - Err(BadOrigin) - )); + assert!(matches!(verify_message_origin(&RawOrigin::Signed(2), &message), Err(BadOrigin))); // The Root account is allowed to assume any expected origin account assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(Some(1)))); diff --git a/modules/ethereum-contract-builtin/src/lib.rs b/modules/ethereum-contract-builtin/src/lib.rs index 75004fd2a92f6..4a830f8e0a389 100644 --- a/modules/ethereum-contract-builtin/src/lib.rs +++ b/modules/ethereum-contract-builtin/src/lib.rs @@ -135,7 +135,9 @@ pub fn verify_substrate_finality_proof( ) -> Result<(), Error> { let best_set = AuthorityList::decode(&mut &*raw_best_set) .map_err(Error::BestSetDecode) - .and_then(|authorities| VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet)); + .and_then(|authorities| { + VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet) + }); log::debug!( target: "bridge-builtin", @@ -150,15 +152,16 @@ pub fn verify_substrate_finality_proof( let best_set = best_set?; - let verify_result = sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( - raw_finality_proof, - (finality_target_hash, finality_target_number), - best_set_id, - &best_set, - ) - .map_err(Box::new) - .map_err(Error::JustificationVerify) - .map(|_| ()); + let verify_result = + sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( + raw_finality_proof, + (finality_target_hash, finality_target_number), + best_set_id, + &best_set, + ) + .map_err(Box::new) + .map_err(Error::JustificationVerify) + .map(|_| ()); log::debug!( target: "bridge-builtin", @@ -202,10 +205,7 @@ mod tests { #[test] fn from_substrate_block_number_succeeds() { assert_eq!(from_substrate_block_number(0).unwrap(), U256::zero()); - assert_eq!( - from_substrate_block_number(std::u32::MAX).unwrap(), - U256::from(std::u32::MAX) - ); + assert_eq!(from_substrate_block_number(std::u32::MAX).unwrap(), U256::from(std::u32::MAX)); } #[test] @@ -285,10 +285,7 @@ mod tests { .parse() .unwrap(), number: 8, - signal: Some(ValidatorsSetSignal { - delay: 8, - validators: authorities.encode(), - }), + signal: Some(ValidatorsSetSignal { delay: 8, validators: authorities.encode() }), }, ); } @@ -296,13 +293,14 @@ mod tests { /// Number of the example block with justification. const EXAMPLE_JUSTIFIED_BLOCK_NUMBER: u32 = 8; /// Hash of the example block with justification. - const EXAMPLE_JUSTIFIED_BLOCK_HASH: &str = "a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775"; - /// Id of authorities set that have generated example justification. Could be computed by tracking - /// every set change in canonized headers. + const EXAMPLE_JUSTIFIED_BLOCK_HASH: &str = + "a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775"; + /// Id of authorities set that have generated example justification. Could be computed by + /// tracking every set change in canonized headers. const EXAMPLE_AUTHORITIES_SET_ID: u64 = 0; - /// Encoded authorities set that has generated example justification. Could be fetched from `ScheduledChange` - /// digest of the block that has scheduled this set OR by calling `GrandpaApi::grandpa_authorities()` at - /// appropriate block. + /// Encoded authorities set that has generated example justification. Could be fetched from + /// `ScheduledChange` digest of the block that has scheduled this set OR by calling + /// `GrandpaApi::grandpa_authorities()` at appropriate block. const EXAMPLE_AUTHORITIES_SET: &str = "1488dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f01000000000000005e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d901000000000000001dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b50100000000000000"; /// Example justification. Could be fetched by calling 'chain_getBlock' RPC. const EXAMPLE_JUSTIFICATION: &str = "2600000000000000a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000010a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000d66b4ceb57ef8bcbc955071b597c8c5d2adcfdbb009c73f8438d342670fdeca9ac60686cbd58105b10f51d0a64a8e73b2e5829b2eab3248a008c472852130b00439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234fa2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000f5730c14d3cd22b7661e2f5fcb3139dd5fef37f946314a441d01b40ce1200ef70d810525f23fd278b588cd67473c200bda83c338c407b479386aa83798e5970b5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000c78d6ec463f476461a695b4791d30e7626d16fdf72d7c252c2cad387495a97e8c2827ed4d5af853d6e05d31cb6fb7438c9481a7e9c6990d60a9bfaf6a6e1930988dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eea2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000052b4fc52d430286b3e2d650aa6e01b6ff4fae8b968893a62be789209eb97ee6e23780d3f5af7042d85bb48f1b202890b22724dfebce138826f66a5e00324320fd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae6900"; diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 98dbd04e2a829..268795d8a8336 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -17,8 +17,8 @@ use super::*; use crate::test_utils::{ - build_custom_header, build_genesis_header, insert_header, validator_utils::*, validators_change_receipt, - HeaderBuilder, + build_custom_header, build_genesis_header, insert_header, validator_utils::*, + validators_change_receipt, HeaderBuilder, }; use bp_eth_poa::{compute_merkle_root, U256}; diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs index ad798379da7dc..6fd376b01715f 100644 --- a/modules/ethereum/src/error.rs +++ b/modules/ethereum/src/error.rs @@ -85,7 +85,8 @@ impl Error { Error::InsufficientProof => "Header has insufficient proof", Error::InvalidDifficulty => "Header has invalid difficulty", Error::NotValidator => "Header is sealed by unexpected validator", - Error::MissingTransactionsReceipts => "The import operation requires transactions receipts", + Error::MissingTransactionsReceipts => + "The import operation requires transactions receipts", Error::RedundantTransactionsReceipts => "Redundant transactions receipts are provided", Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided", Error::UnsignedTooFarInTheFuture => "The unsigned header is too far in future", diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 934db0430ab8c..34b766f7e0219 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -14,18 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::error::Error; -use crate::Storage; +use crate::{error::Error, Storage}; use bp_eth_poa::{public_to_address, Address, AuraHeader, HeaderId, SealedEmptyStep, H256}; use codec::{Decode, Encode}; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_runtime::RuntimeDebug; -use sp_std::collections::{ - btree_map::{BTreeMap, Entry}, - btree_set::BTreeSet, - vec_deque::VecDeque, +use sp_std::{ + collections::{ + btree_map::{BTreeMap, Entry}, + btree_set::BTreeSet, + vec_deque::VecDeque, + }, + prelude::*, }; -use sp_std::prelude::*; /// Cached finality votes for given block. #[derive(RuntimeDebug)] @@ -116,17 +117,14 @@ pub fn finalize_blocks( ¤t_votes, ancestor.id.number >= two_thirds_majority_transition, ) { - break; + break } remove_signers_votes(&ancestor.signers, &mut current_votes); finalized_headers.push((ancestor.id, ancestor.submitter.clone())); } - Ok(FinalityEffects { - finalized_headers, - votes, - }) + Ok(FinalityEffects { finalized_headers, votes }) } /// Returns true if there are enough votes to treat this header as finalized. @@ -135,8 +133,8 @@ fn is_finalized( votes: &BTreeMap, requires_two_thirds_majority: bool, ) -> bool { - (!requires_two_thirds_majority && votes.len() * 2 > validators.len()) - || (requires_two_thirds_majority && votes.len() * 3 > validators.len() * 2) + (!requires_two_thirds_majority && votes.len() * 2 > validators.len()) || + (requires_two_thirds_majority && votes.len() * 3 > validators.len() * 2) } /// Prepare 'votes' of header and its ancestors' signers. @@ -151,12 +149,12 @@ pub(crate) fn prepare_votes( // if we have reached finalized block sibling, then we're trying // to switch finalized blocks if cached_votes.stopped_at_finalized_sibling { - return Err(Error::TryingToFinalizeSibling); + return Err(Error::TryingToFinalizeSibling) } // this fn can only work with single validators set if !validators.contains(&header.author) { - return Err(Error::NotValidator); + return Err(Error::NotValidator) } // now we have votes that were valid when some block B has been inserted @@ -171,7 +169,7 @@ pub(crate) fn prepare_votes( while let Some(old_ancestor) = votes.ancestry.pop_front() { if old_ancestor.id.number > best_finalized.number { votes.ancestry.push_front(old_ancestor); - break; + break } remove_signers_votes(&old_ancestor.signers, &mut votes.votes); @@ -180,7 +178,9 @@ pub(crate) fn prepare_votes( // add votes from new blocks let mut parent_empty_step_signers = empty_steps_signers(header); let mut unaccounted_ancestry = VecDeque::new(); - while let Some((ancestor_id, ancestor_submitter, ancestor)) = cached_votes.unaccounted_ancestry.pop_front() { + while let Some((ancestor_id, ancestor_submitter, ancestor)) = + cached_votes.unaccounted_ancestry.pop_front() + { let mut signers = empty_steps_signers(&ancestor); sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); signers.insert(ancestor.author); @@ -199,11 +199,9 @@ pub(crate) fn prepare_votes( let mut header_signers = BTreeSet::new(); header_signers.insert(header.author); *votes.votes.entry(header.author).or_insert(0) += 1; - votes.ancestry.push_back(FinalityAncestor { - id, - submitter, - signers: header_signers, - }); + votes + .ancestry + .push_back(FinalityAncestor { id, submitter, signers: header_signers }); Ok(votes) } @@ -217,7 +215,7 @@ fn add_signers_votes( ) -> Result<(), Error> { for signer in signers_to_add { if !validators.contains(signer) { - return Err(Error::NotValidator); + return Err(Error::NotValidator) } *votes.entry(*signer).or_insert(0) += 1; @@ -230,13 +228,12 @@ fn add_signers_votes( fn remove_signers_votes(signers_to_remove: &BTreeSet

, votes: &mut BTreeMap) { for signer in signers_to_remove { match votes.entry(*signer) { - Entry::Occupied(mut entry) => { + Entry::Occupied(mut entry) => if *entry.get() <= 1 { entry.remove(); } else { *entry.get_mut() -= 1; - } - } + }, Entry::Vacant(_) => unreachable!("we only remove signers that have been added; qed"), } } @@ -272,18 +269,19 @@ impl Default for CachedFinalityVotes { impl Default for FinalityVotes { fn default() -> Self { - FinalityVotes { - votes: BTreeMap::new(), - ancestry: VecDeque::new(), - } + FinalityVotes { votes: BTreeMap::new(), ancestry: VecDeque::new() } } } #[cfg(test)] mod tests { use super::*; - use crate::mock::{insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime}; - use crate::{BridgeStorage, FinalityCache, HeaderToImport}; + use crate::{ + mock::{ + insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime, + }, + BridgeStorage, FinalityCache, HeaderToImport, + }; const TOTAL_VALIDATORS: usize = 5; @@ -341,7 +339,8 @@ mod tests { storage.insert_header(header_to_import.clone()); // when header#2 is inserted, nothing is finalized (2 votes) - header_to_import.header = HeaderBuilder::with_parent_hash(id1.hash).sign_by(&validator(1)); + header_to_import.header = + HeaderBuilder::with_parent_hash(id1.hash).sign_by(&validator(1)); header_to_import.id = header_to_import.header.compute_id(); let id2 = header_to_import.header.compute_id(); assert_eq!( @@ -360,7 +359,8 @@ mod tests { storage.insert_header(header_to_import.clone()); // when header#3 is inserted, header#1 is finalized (3 votes) - header_to_import.header = HeaderBuilder::with_parent_hash(id2.hash).sign_by(&validator(2)); + header_to_import.header = + HeaderBuilder::with_parent_hash(id2.hash).sign_by(&validator(2)); header_to_import.id = header_to_import.header.compute_id(); let id3 = header_to_import.header.compute_id(); assert_eq!( @@ -390,7 +390,9 @@ mod tests { // 2) add votes from header#4 and header#5 let validators = validators_addresses(5); let headers = (1..6) - .map(|number| HeaderBuilder::with_number(number).sign_by(&validator(number as usize - 1))) + .map(|number| { + HeaderBuilder::with_number(number).sign_by(&validator(number as usize - 1)) + }) .collect::>(); let ancestry = headers .iter() @@ -405,9 +407,10 @@ mod tests { prepare_votes::<()>( CachedFinalityVotes { stopped_at_finalized_sibling: false, - unaccounted_ancestry: vec![(headers[3].compute_id(), None, headers[3].clone()),] - .into_iter() - .collect(), + unaccounted_ancestry: + vec![(headers[3].compute_id(), None, headers[3].clone()),] + .into_iter() + .collect(), votes: Some(FinalityVotes { votes: vec![(validators[0], 1), (validators[1], 1), (validators[2], 1),] .into_iter() @@ -445,7 +448,8 @@ mod tests { let mut ancestry = Vec::new(); let mut parent_hash = ctx.genesis.compute_hash(); for i in 1..10 { - let header = HeaderBuilder::with_parent_hash(parent_hash).sign_by(&validator((i - 1) / 3)); + let header = + HeaderBuilder::with_parent_hash(parent_hash).sign_by(&validator((i - 1) / 3)); let id = header.compute_id(); insert_header(&mut storage, header.clone()); hashes.push(id.hash); @@ -539,10 +543,7 @@ mod tests { fn prepare_votes_fails_when_finalized_sibling_is_in_ancestry() { assert_eq!( prepare_votes::<()>( - CachedFinalityVotes { - stopped_at_finalized_sibling: true, - ..Default::default() - }, + CachedFinalityVotes { stopped_at_finalized_sibling: true, ..Default::default() }, Default::default(), &validators_addresses(3).iter().collect(), Default::default(), diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 9f93d8dcb2eb4..3c99451ca8f18 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -14,11 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::error::Error; -use crate::finality::finalize_blocks; -use crate::validators::{Validators, ValidatorsConfiguration}; -use crate::verification::{is_importable_header, verify_aura_header}; -use crate::{AuraConfiguration, ChainTime, ChangeToEnact, PruningStrategy, Storage}; +use crate::{ + error::Error, + finality::finalize_blocks, + validators::{Validators, ValidatorsConfiguration}, + verification::{is_importable_header, verify_aura_header}, + AuraConfiguration, ChainTime, ChangeToEnact, PruningStrategy, Storage, +}; use bp_eth_poa::{AuraHeader, HeaderId, Receipt}; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; @@ -65,7 +67,7 @@ pub fn import_headers( } } useful += 1; - } + }, Err(Error::AncientHeader) | Err(Error::KnownHeader) => useless += 1, Err(error) => return Err(error), } @@ -103,7 +105,8 @@ pub fn import_header( // check if block schedules new validators let validators = Validators::new(validators_config); - let (scheduled_change, enacted_change) = validators.extract_validators_change(&header, receipts)?; + let (scheduled_change, enacted_change) = + validators.extract_validators_change(&header, receipts)?; // check if block finalizes some other blocks and corresponding scheduled validators let validators_set = import_context.validators_set(); @@ -117,11 +120,10 @@ pub fn import_header( aura_config.two_thirds_majority_transition, )?; let enacted_change = enacted_change - .map(|validators| ChangeToEnact { - signal_block: None, - validators, - }) - .or_else(|| validators.finalize_validators_change(storage, &finalized_blocks.finalized_headers)); + .map(|validators| ChangeToEnact { signal_block: None, validators }) + .or_else(|| { + validators.finalize_validators_change(storage, &finalized_blocks.finalized_headers) + }); // NOTE: we can't return Err() from anywhere below this line // (because otherwise we'll have inconsistent storage if transaction will fail) @@ -145,9 +147,7 @@ pub fn import_header( let new_best_finalized_block_id = finalized_blocks.finalized_headers.last().map(|(id, _)| *id); let pruning_upper_bound = pruning_strategy.pruning_upper_bound( new_best_block_id.number, - new_best_finalized_block_id - .map(|id| id.number) - .unwrap_or(finalized_id.number), + new_best_finalized_block_id.map(|id| id.number).unwrap_or(finalized_id.number), ); // now mark finalized headers && prune old headers @@ -171,12 +171,15 @@ pub fn header_import_requires_receipts( #[cfg(test)] mod tests { use super::*; - use crate::mock::{ - run_test, secret_to_address, test_aura_config, test_validators_config, validator, validators_addresses, - validators_change_receipt, HeaderBuilder, KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, + use crate::{ + mock::{ + run_test, secret_to_address, test_aura_config, test_validators_config, validator, + validators_addresses, validators_change_receipt, HeaderBuilder, + KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, + }, + validators::ValidatorsSource, + BlocksToPrune, BridgeStorage, Headers, PruningRange, }; - use crate::validators::ValidatorsSource; - use crate::{BlocksToPrune, BridgeStorage, Headers, PruningRange}; use secp256k1::SecretKey; const TOTAL_VALIDATORS: usize = 3; @@ -186,10 +189,7 @@ mod tests { run_test(TOTAL_VALIDATORS, |_| { let mut storage = BridgeStorage::::new(); storage.finalize_and_prune_headers( - Some(HeaderId { - number: 100, - ..Default::default() - }), + Some(HeaderId { number: 100, ..Default::default() }), 0, ); assert_eq!( @@ -281,8 +281,10 @@ mod tests { #[test] fn headers_are_pruned_during_import() { run_test(TOTAL_VALIDATORS, |ctx| { - let validators_config = - ValidatorsConfiguration::Single(ValidatorsSource::Contract([3; 20].into(), ctx.addresses.clone())); + let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( + [3; 20].into(), + ctx.addresses.clone(), + )); let validators = vec![validator(0), validator(1), validator(2)]; let mut storage = BridgeStorage::::new(); @@ -305,7 +307,8 @@ mod tests { ) .unwrap(); match i { - 2..=10 => assert_eq!(finalized_blocks, vec![(parent_id, Some(100))], "At {}", i,), + 2..=10 => + assert_eq!(finalized_blocks, vec![(parent_id, Some(100))], "At {}", i,), _ => assert_eq!(finalized_blocks, vec![], "At {}", i), } latest_block_id = rolling_last_block_id; @@ -339,8 +342,8 @@ mod tests { latest_block_id = rolling_last_block_id; // and now let's say validators 1 && 2 went offline - // => in the range 12-25 no blocks are finalized, but we still continue to prune old headers - // until header#11 is met. we can't prune #11, because it schedules change + // => in the range 12-25 no blocks are finalized, but we still continue to prune old + // headers until header#11 is met. we can't prune #11, because it schedules change let mut step = 56u64; let mut expected_blocks = vec![(header11.compute_id(), Some(101))]; for i in 12..25 { @@ -366,10 +369,7 @@ mod tests { } assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 11, - oldest_block_to_keep: 14, - }, + PruningRange { oldest_unpruned_block: 11, oldest_block_to_keep: 14 }, ); // now let's insert block signed by validator 1 @@ -393,10 +393,7 @@ mod tests { assert_eq!(finalized_blocks, expected_blocks); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 15, - oldest_block_to_keep: 15, - }, + PruningRange { oldest_unpruned_block: 15, oldest_block_to_keep: 15 }, ); }); } @@ -483,9 +480,7 @@ mod tests { let header1 = import_custom_block( &mut storage, &ctx.validators, - HeaderBuilder::with_parent_number(0) - .step(2) - .sign_by_set(&ctx.validators), + HeaderBuilder::with_parent_number(0).step(2).sign_by_set(&ctx.validators), ) .unwrap(); assert_eq!(storage.best_block().0, header1); @@ -495,9 +490,7 @@ mod tests { let header2 = import_custom_block( &mut storage, &ctx.validators, - HeaderBuilder::with_parent_number(1) - .step(3) - .sign_by_set(&ctx.validators), + HeaderBuilder::with_parent_number(1).step(3).sign_by_set(&ctx.validators), ) .unwrap(); assert_eq!(storage.best_block().0, header2); @@ -507,9 +500,7 @@ mod tests { let header3 = import_custom_block( &mut storage, &ctx.validators, - HeaderBuilder::with_parent_number(2) - .step(4) - .sign_by_set(&ctx.validators), + HeaderBuilder::with_parent_number(2).step(4).sign_by_set(&ctx.validators), ) .unwrap(); assert_eq!(storage.best_block().0, header3); @@ -552,19 +543,19 @@ mod tests { assert_eq!(storage.best_block().0, header5_1); assert_eq!(storage.finalized_block(), header1); - // when we import header4 { parent = header3 }, authored by validator[0], header2 is finalized + // when we import header4 { parent = header3 }, authored by validator[0], header2 is + // finalized let header4 = import_custom_block( &mut storage, &ctx.validators, - HeaderBuilder::with_parent_number(3) - .step(5) - .sign_by_set(&ctx.validators), + HeaderBuilder::with_parent_number(3).step(5).sign_by_set(&ctx.validators), ) .unwrap(); assert_eq!(storage.best_block().0, header5_1); assert_eq!(storage.finalized_block(), header2); - // when we import header5 { parent = header4 }, authored by validator[1], header3 is finalized + // when we import header5 { parent = header4 }, authored by validator[1], header3 is + // finalized let header5 = import_custom_block( &mut storage, &ctx.validators, @@ -576,7 +567,8 @@ mod tests { assert_eq!(storage.best_block().0, header5); assert_eq!(storage.finalized_block(), header3); - // import of header2'' { parent = header1 } fails, because it has number < best_finalized + // import of header2'' { parent = header1 } fails, because it has number < + // best_finalized assert_eq!( import_custom_block( &mut storage, diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 88a35f365e40b..6234a02cca13d 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -19,7 +19,9 @@ #![allow(clippy::large_enum_variant)] use crate::finality::{CachedFinalityVotes, FinalityVotes}; -use bp_eth_poa::{Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256}; +use bp_eth_poa::{ + Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256, +}; use codec::{Decode, Encode}; use frame_support::traits::Get; use sp_runtime::RuntimeDebug; @@ -222,10 +224,7 @@ impl ImportContext { /// This may point to parent if parent has signaled change. pub fn last_signal_block(&self) -> Option { match self.parent_scheduled_change { - Some(_) => Some(HeaderId { - number: self.parent_header.number, - hash: self.parent_hash, - }), + Some(_) => Some(HeaderId { number: self.parent_header.number, hash: self.parent_hash }), None => self.last_signal_block, } } @@ -313,8 +312,8 @@ pub trait PruningStrategy: Default { /// number greater than or equal to N even if strategy allows that. /// /// If your strategy allows pruning unfinalized blocks, this could lead to switch - /// between finalized forks (only if authorities are misbehaving). But since 50 percent plus one (or 2/3) - /// authorities are able to do whatever they want with the chain, this isn't considered + /// between finalized forks (only if authorities are misbehaving). But since 50 percent plus one + /// (or 2/3) authorities are able to do whatever they want with the chain, this isn't considered /// fatal. If your strategy only prunes finalized blocks, we'll never be able to finalize /// header that isn't descendant of current best finalized block. fn pruning_upper_bound(&mut self, best_number: u64, best_finalized_number: u64) -> u64; @@ -343,10 +342,10 @@ impl ChainTime for () { pub trait OnHeadersSubmitted { /// Called when valid headers have been submitted. /// - /// The submitter **must not** be rewarded for submitting valid headers, because greedy authority - /// could produce and submit multiple valid headers (without relaying them to other peers) and - /// get rewarded. Instead, the provider could track submitters and stop rewarding if too many - /// headers have been submitted without finalization. + /// The submitter **must not** be rewarded for submitting valid headers, because greedy + /// authority could produce and submit multiple valid headers (without relaying them to other + /// peers) and get rewarded. Instead, the provider could track submitters and stop rewarding if + /// too many headers have been submitted without finalization. fn on_valid_headers_submitted(submitter: AccountId, useful: u64, useless: u64); /// Called when invalid headers have been submitted. fn on_invalid_headers_submitted(submitter: AccountId); @@ -459,13 +458,14 @@ pub mod pallet { // now track/penalize current submitter for providing new headers match import_result { - Ok((useful, useless)) => T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), + Ok((useful, useless)) => + T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), Err(error) => { // even though we may have accept some headers, we do not want to reward someone // who provides invalid headers T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter); - return Err(error.msg().into()); - } + return Err(error.msg().into()) + }, } Ok(()) @@ -500,12 +500,13 @@ pub mod pallet { // UnsignedTooFarInTheFuture is the special error code used to limit // number of transactions in the pool - we do not want to ban transaction // in this case (see verification.rs for details) - Err(error::Error::UnsignedTooFarInTheFuture) => { - UnknownTransaction::Custom(error::Error::UnsignedTooFarInTheFuture.code()).into() - } + Err(error::Error::UnsignedTooFarInTheFuture) => UnknownTransaction::Custom( + error::Error::UnsignedTooFarInTheFuture.code(), + ) + .into(), Err(error) => InvalidTransaction::Custom(error.code()).into(), } - } + }, _ => InvalidTransaction::Call.into(), } } @@ -513,23 +514,28 @@ pub mod pallet { /// Best known block. #[pallet::storage] - pub(super) type BestBlock, I: 'static = ()> = StorageValue<_, (HeaderId, U256), ValueQuery>; + pub(super) type BestBlock, I: 'static = ()> = + StorageValue<_, (HeaderId, U256), ValueQuery>; /// Best finalized block. #[pallet::storage] - pub(super) type FinalizedBlock, I: 'static = ()> = StorageValue<_, HeaderId, ValueQuery>; + pub(super) type FinalizedBlock, I: 'static = ()> = + StorageValue<_, HeaderId, ValueQuery>; /// Range of blocks that we want to prune. #[pallet::storage] - pub(super) type BlocksToPrune, I: 'static = ()> = StorageValue<_, PruningRange, ValueQuery>; + pub(super) type BlocksToPrune, I: 'static = ()> = + StorageValue<_, PruningRange, ValueQuery>; /// Map of imported headers by hash. #[pallet::storage] - pub(super) type Headers, I: 'static = ()> = StorageMap<_, Identity, H256, StoredHeader>; + pub(super) type Headers, I: 'static = ()> = + StorageMap<_, Identity, H256, StoredHeader>; /// Map of imported header hashes by number. #[pallet::storage] - pub(super) type HeadersByNumber, I: 'static = ()> = StorageMap<_, Blake2_128Concat, u64, Vec>; + pub(super) type HeadersByNumber, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, u64, Vec>; /// Map of cached finality data by header hash. #[pallet::storage] @@ -538,17 +544,20 @@ pub mod pallet { /// The ID of next validator set. #[pallet::storage] - pub(super) type NextValidatorsSetId, I: 'static = ()> = StorageValue<_, u64, ValueQuery>; + pub(super) type NextValidatorsSetId, I: 'static = ()> = + StorageValue<_, u64, ValueQuery>; /// Map of validators sets by their id. #[pallet::storage] - pub(super) type ValidatorsSets, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, ValidatorsSet>; + pub(super) type ValidatorsSets, I: 'static = ()> = + StorageMap<_, Twox64Concat, u64, ValidatorsSet>; /// Validators sets reference count. Each header that is authored by this set increases /// the reference count. When we prune this header, we decrease the reference count. /// When it reaches zero, we are free to prune validator set as well. #[pallet::storage] - pub(super) type ValidatorsSetsRc, I: 'static = ()> = StorageMap<_, Twox64Concat, u64, u64>; + pub(super) type ValidatorsSetsRc, I: 'static = ()> = + StorageMap<_, Twox64Concat, u64, u64>; /// Map of validators set changes scheduled by given header. #[pallet::storage] @@ -572,14 +581,16 @@ pub mod pallet { // the initial blocks should be selected so that: // 1) it doesn't signal validators changes; // 2) there are no scheduled validators changes from previous blocks; - // 3) (implied) all direct children of initial block are authored by the same validators set. + // 3) (implied) all direct children of initial block are authored by the same validators + // set. - assert!( - !self.initial_validators.is_empty(), - "Initial validators set can't be empty", - ); + assert!(!self.initial_validators.is_empty(), "Initial validators set can't be empty",); - initialize_storage::(&self.initial_header, self.initial_difficulty, &self.initial_validators); + initialize_storage::( + &self.initial_header, + self.initial_difficulty, + &self.initial_validators, + ); } } } @@ -648,7 +659,7 @@ impl, I: 'static> BridgeStorage { for number in begin..end { // if we can't prune anything => break if max_blocks_to_prune == 0 { - break; + break } // read hashes of blocks with given number and try to prune these blocks @@ -664,7 +675,7 @@ impl, I: 'static> BridgeStorage { // if we haven't pruned all blocks, remember unpruned if !blocks_at_number.is_empty() { HeadersByNumber::::insert(number, blocks_at_number); - break; + break } } @@ -692,8 +703,10 @@ impl, I: 'static> BridgeStorage { blocks_at_number: &mut Vec, ) { // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number && blocks_at_number.iter().any(ScheduledChanges::::contains_key) { - return; + if number > finalized_number && + blocks_at_number.iter().any(ScheduledChanges::::contains_key) + { + return } // physically remove headers and (probably) obsolete validators sets @@ -718,7 +731,7 @@ impl, I: 'static> BridgeStorage { // check if we have already pruned too much headers in this call *max_blocks_to_prune -= 1; if *max_blocks_to_prune == 0 { - return; + return } } } @@ -749,21 +762,22 @@ impl, I: 'static> Storage for BridgeStorage { let mut current_id = *parent; loop { // if we have reached finalized block's sibling => stop with special signal - if current_id.number == best_finalized.number && current_id.hash != best_finalized.hash { + if current_id.number == best_finalized.number && current_id.hash != best_finalized.hash + { votes.stopped_at_finalized_sibling = true; - return votes; + return votes } // if we have reached target header => stop if stop_at(¤t_id.hash) { - return votes; + return votes } // if we have found cached votes => stop let cached_votes = FinalityCache::::get(¤t_id.hash); if let Some(cached_votes) = cached_votes { votes.votes = Some(cached_votes); - return votes; + return votes } // read next parent header id @@ -792,7 +806,9 @@ impl, I: 'static> Storage for BridgeStorage { ) -> Option> { Headers::::get(parent_hash).map(|parent_header| { let validators_set = ValidatorsSets::::get(parent_header.next_validators_set_id) - .expect("validators set is only pruned when last ref is pruned; there is a ref; qed"); + .expect( + "validators set is only pruned when last ref is pruned; there is a ref; qed", + ); let parent_scheduled_change = ScheduledChanges::::get(parent_hash); ImportContext { submitter, @@ -841,19 +857,20 @@ impl, I: 'static> Storage for BridgeStorage { ); ValidatorsSetsRc::::insert(next_validators_set_id, 1); next_validators_set_id - } + }, None => { ValidatorsSetsRc::::mutate(header.context.validators_set_id, |rc| { *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); *rc }); header.context.validators_set_id - } + }, }; let finality_votes_caching_interval = T::FinalityVotesCachingInterval::get(); if let Some(finality_votes_caching_interval) = finality_votes_caching_interval { - let cache_entry_required = header.id.number != 0 && header.id.number % finality_votes_caching_interval == 0; + let cache_entry_required = + header.id.number != 0 && header.id.number % finality_votes_caching_interval == 0; if cache_entry_required { FinalityCache::::insert(header.id.hash, header.finality_votes); } @@ -917,10 +934,7 @@ pub(crate) fn initialize_storage, I: 'static>( initial_hash, ); - let initial_id = HeaderId { - number: initial_header.number, - hash: initial_hash, - }; + let initial_id = HeaderId { number: initial_header.number, hash: initial_hash }; BestBlock::::put((initial_id, initial_difficulty)); FinalizedBlock::::put(initial_id); BlocksToPrune::::put(PruningRange { @@ -965,7 +979,7 @@ pub fn verify_transaction_finalized( proof.len(), ); - return false; + return false } let header = match storage.header(&block) { @@ -977,8 +991,8 @@ pub fn verify_transaction_finalized( block, ); - return false; - } + return false + }, }; let finalized = storage.finalized_block(); @@ -992,7 +1006,7 @@ pub fn verify_transaction_finalized( finalized.number, ); - return false; + return false } // check if header is actually finalized @@ -1010,7 +1024,7 @@ pub fn verify_transaction_finalized( finalized.hash, ); - return false; + return false } // verify that transaction is included in the block @@ -1022,7 +1036,7 @@ pub fn verify_transaction_finalized( computed_root, ); - return false; + return false } // verify that transaction receipt is included in the block @@ -1034,7 +1048,7 @@ pub fn verify_transaction_finalized( computed_root, ); - return false; + return false } // check that transaction has completed successfully @@ -1048,7 +1062,7 @@ pub fn verify_transaction_finalized( ); false - } + }, Err(err) => { log::trace!( target: "runtime", @@ -1057,23 +1071,24 @@ pub fn verify_transaction_finalized( ); false - } + }, } } /// Transaction pool configuration. fn pool_configuration() -> PoolConfiguration { - PoolConfiguration { - max_future_number_difference: 10, - } + PoolConfiguration { max_future_number_difference: 10 } } /// Return iterator of given header ancestors. -fn ancestry(storage: &'_ S, mut parent_hash: H256) -> impl Iterator + '_ { +fn ancestry( + storage: &'_ S, + mut parent_hash: H256, +) -> impl Iterator + '_ { sp_std::iter::from_fn(move || { let (header, _) = storage.header(&parent_hash)?; if header.number == 0 { - return None; + return None } let hash = parent_hash; @@ -1085,12 +1100,14 @@ fn ancestry(storage: &'_ S, mut parent_hash: H256) -> impl Iterator< #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::finality::FinalityAncestor; - use crate::mock::{ - genesis, insert_header, run_test, run_test_with_genesis, validators_addresses, HeaderBuilder, TestRuntime, - GAS_LIMIT, + use crate::{ + finality::FinalityAncestor, + mock::{ + genesis, insert_header, run_test, run_test_with_genesis, validators_addresses, + HeaderBuilder, TestRuntime, GAS_LIMIT, + }, + test_utils::validator_utils::*, }; - use crate::test_utils::validator_utils::*; use bp_eth_poa::compute_merkle_root; const TOTAL_VALIDATORS: usize = 3; @@ -1182,10 +1199,7 @@ pub(crate) mod tests { assert_eq!(HeadersByNumber::::get(&5).unwrap().len(), 5); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 5, - oldest_block_to_keep: 5, - }, + PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5 }, ); }); } @@ -1202,10 +1216,7 @@ pub(crate) mod tests { storage.prune_blocks(0xFFFF, 10, 3); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 5, - oldest_block_to_keep: 5, - }, + PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5 }, ); }); } @@ -1221,10 +1232,7 @@ pub(crate) mod tests { assert!(HeadersByNumber::::get(&3).is_some()); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 0, - oldest_block_to_keep: 10, - }, + PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: 10 }, ); }); } @@ -1242,10 +1250,7 @@ pub(crate) mod tests { assert_eq!(HeadersByNumber::::get(&2).unwrap().len(), 4); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 2, - oldest_block_to_keep: 10, - }, + PruningRange { oldest_unpruned_block: 2, oldest_block_to_keep: 10 }, ); // try to prune blocks [2; 10) @@ -1258,10 +1263,7 @@ pub(crate) mod tests { assert_eq!(HeadersByNumber::::get(&4).unwrap().len(), 3); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 4, - oldest_block_to_keep: 10, - }, + PruningRange { oldest_unpruned_block: 4, oldest_block_to_keep: 10 }, ); }); } @@ -1284,10 +1286,7 @@ pub(crate) mod tests { assert_eq!(HeadersByNumber::::get(&7).unwrap().len(), 5); assert_eq!( BlocksToPrune::::get(), - PruningRange { - oldest_unpruned_block: 7, - oldest_block_to_keep: 10, - }, + PruningRange { oldest_unpruned_block: 7, oldest_block_to_keep: 10 }, ); }); } @@ -1307,7 +1306,8 @@ pub(crate) mod tests { } // for header with number = interval, cache entry is created - let header_with_entry = HeaderBuilder::with_parent_number(interval - 1).sign_by_set(&ctx.validators); + let header_with_entry = + HeaderBuilder::with_parent_number(interval - 1).sign_by_set(&ctx.validators); let header_with_entry_hash = header_with_entry.compute_hash(); insert_header(&mut storage, header_with_entry); assert!(FinalityCache::::get(&header_with_entry_hash).is_some()); @@ -1354,10 +1354,7 @@ pub(crate) mod tests { let votes_at_3 = FinalityVotes { votes: vec![([42; 20].into(), 21)].into_iter().collect(), ancestry: vec![FinalityAncestor { - id: HeaderId { - number: 100, - hash: Default::default(), - }, + id: HeaderId { number: 100, hash: Default::default() }, ..Default::default() }] .into_iter() diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index 00c10d3cc3e0f..e0439444020c7 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -17,11 +17,15 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -pub use crate::test_utils::{insert_header, validator_utils::*, validators_change_receipt, HeaderBuilder, GAS_LIMIT}; +pub use crate::test_utils::{ + insert_header, validator_utils::*, validators_change_receipt, HeaderBuilder, GAS_LIMIT, +}; pub use bp_eth_poa::signatures::secret_to_address; -use crate::validators::{ValidatorsConfiguration, ValidatorsSource}; -use crate::{AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy}; +use crate::{ + validators::{ValidatorsConfiguration, ValidatorsSource}, + AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy, +}; use bp_eth_poa::{Address, AuraHeader, H256, U256}; use frame_support::{parameter_types, traits::GenesisBuild, weights::Weight}; use secp256k1::SecretKey; @@ -154,14 +158,7 @@ pub fn run_test_with_genesis( }) .unwrap(), ) - .execute_with(|| { - test(TestContext { - genesis, - total_validators, - validators, - addresses, - }) - }) + .execute_with(|| test(TestContext { genesis, total_validators, validators, addresses })) } /// Pruning strategy that keeps 10 headers behind best block. diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index bc41b2286f9e5..343c7b1cb3646 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -24,10 +24,10 @@ // Since this is test code it's fine that not everything is used #![allow(dead_code)] -use crate::finality::FinalityVotes; -use crate::validators::CHANGE_EVENT_HASH; -use crate::verification::calculate_score; -use crate::{Config, HeaderToImport, Storage}; +use crate::{ + finality::FinalityVotes, validators::CHANGE_EVENT_HASH, verification::calculate_score, Config, + HeaderToImport, Storage, +}; use bp_eth_poa::{ rlp_encode, @@ -130,10 +130,7 @@ impl HeaderBuilder { let sealed_empty_steps = empty_steps .iter() .map(|(author, step)| { - let mut empty_step = SealedEmptyStep { - step: *step, - signature: Default::default(), - }; + let mut empty_step = SealedEmptyStep { step: *step, signature: Default::default() }; let message = empty_step.message(&self.header.parent_hash); let signature: [u8; 65] = sign(author, message).into(); empty_step.signature = signature.into(); @@ -216,7 +213,11 @@ pub fn build_genesis_header(author: &SecretKey) -> AuraHeader { } /// Helper function for building a custom child header which has been signed by an authority. -pub fn build_custom_header(author: &SecretKey, previous: &AuraHeader, customize_header: F) -> AuraHeader +pub fn build_custom_header( + author: &SecretKey, + previous: &AuraHeader, + customize_header: F, +) -> AuraHeader where F: FnOnce(AuraHeader) -> AuraHeader, { @@ -232,7 +233,8 @@ pub fn insert_header(storage: &mut S, header: AuraHeader) { let id = header.compute_id(); let best_finalized = storage.finalized_block(); let import_context = storage.import_context(None, &header.parent_hash).unwrap(); - let parent_finality_votes = storage.cached_finality_votes(&header.parent_id().unwrap(), &best_finalized, |_| false); + let parent_finality_votes = + storage.cached_finality_votes(&header.parent_id().unwrap(), &best_finalized, |_| false); let finality_votes = crate::finality::prepare_votes( parent_finality_votes, best_finalized, @@ -284,9 +286,10 @@ pub fn validators_change_receipt(parent_hash: H256) -> Receipt { address: [3; 20].into(), topics: vec![CHANGE_EVENT_HASH.into(), parent_hash], data: vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, ], }], } diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index e8102a527b288..020e6fa796126 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -14,15 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::error::Error; -use crate::{ChangeToEnact, Storage}; +use crate::{error::Error, ChangeToEnact, Storage}; use bp_eth_poa::{Address, AuraHeader, HeaderId, LogEntry, Receipt, U256}; use sp_std::prelude::*; /// The hash of InitiateChange event of the validators set contract. pub(crate) const CHANGE_EVENT_HASH: &[u8; 32] = &[ - 0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, 0xd2, 0xc2, 0x28, - 0x1d, 0xf8, 0xd6, 0xea, 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89, + 0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, + 0xd2, 0xc2, 0x28, 0x1d, 0xf8, 0xd6, 0xea, 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89, ]; /// Where source of validators addresses come from. This covers the chain lifetime. @@ -104,7 +103,8 @@ impl<'a> Validators<'a> { if next_starts_at == header.number { match *next_source { ValidatorsSource::List(ref new_list) => return Ok((None, Some(new_list.clone()))), - ValidatorsSource::Contract(_, ref new_list) => return Ok((Some(new_list.clone()), None)), + ValidatorsSource::Contract(_, ref new_list) => + return Ok((Some(new_list.clone()), None)), } } @@ -128,12 +128,12 @@ impl<'a> Validators<'a> { .bloom(); if !header.log_bloom.contains(&expected_bloom) { - return Ok((None, None)); + return Ok((None, None)) } let receipts = receipts.ok_or(Error::MissingTransactionsReceipts)?; if header.check_receipts_root(&receipts).is_err() { - return Err(Error::TransactionsReceiptsMismatch); + return Err(Error::TransactionsReceiptsMismatch) } // iterate in reverse because only the _last_ change in a given @@ -145,24 +145,24 @@ impl<'a> Validators<'a> { .filter(|r| r.log_bloom.contains(&expected_bloom)) .flat_map(|r| r.logs.iter()) .filter(|l| { - l.address == *contract_address - && l.topics.len() == 2 && l.topics[0].as_fixed_bytes() == CHANGE_EVENT_HASH - && l.topics[1] == header.parent_hash + l.address == *contract_address && + l.topics.len() == 2 && l.topics[0].as_fixed_bytes() == CHANGE_EVENT_HASH && + l.topics[1] == header.parent_hash }) .filter_map(|l| { let data_len = l.data.len(); if data_len < 64 { - return None; + return None } let new_validators_len_u256 = U256::from_big_endian(&l.data[32..64]); let new_validators_len = new_validators_len_u256.low_u64(); if new_validators_len_u256 != new_validators_len.into() { - return None; + return None } if (data_len - 64) as u64 != new_validators_len.saturating_mul(32) { - return None; + return None } Some( @@ -216,12 +216,10 @@ impl<'a> Validators<'a> { } }) .and_then(|signal_block| { - storage - .scheduled_change(&signal_block.hash) - .map(|change| ChangeToEnact { - signal_block: Some(signal_block), - validators: change.validators, - }) + storage.scheduled_change(&signal_block.hash).map(|change| ChangeToEnact { + signal_block: Some(signal_block), + validators: change.validators, + }) }) } @@ -243,7 +241,11 @@ impl<'a> Validators<'a> { } /// Returns source of validators that should author the next header. - fn source_at_next_header(&self, header_source_index: usize, header_number: u64) -> (u64, &ValidatorsSource) { + fn source_at_next_header( + &self, + header_source_index: usize, + header_number: u64, + ) -> (u64, &ValidatorsSource) { match self.config { ValidatorsConfiguration::Single(ref source) => (0, source), ValidatorsConfiguration::Multi(ref sources) => { @@ -251,13 +253,13 @@ impl<'a> Validators<'a> { if next_source_index < sources.len() { let next_source = &sources[next_source_index]; if next_source.0 < header_number + 1 { - return (next_source.0, &next_source.1); + return (next_source.0, &next_source.1) } } let source = &sources[header_source_index]; (source.0, &source.1) - } + }, } } } @@ -275,8 +277,10 @@ impl ValidatorsSource { #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}; - use crate::{AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader}; + use crate::{ + mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}, + AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader, + }; use bp_eth_poa::compute_merkle_root; const TOTAL_VALIDATORS: usize = 3; @@ -290,10 +294,7 @@ pub(crate) mod tests { ]); let validators = Validators::new(&config); - assert_eq!( - validators.source_at(99), - (0, 0, &ValidatorsSource::List(vec![[1; 20].into()])), - ); + assert_eq!(validators.source_at(99), (0, 0, &ValidatorsSource::List(vec![[1; 20].into()])),); assert_eq!( validators.source_at_next_header(0, 99), (0, &ValidatorsSource::List(vec![[1; 20].into()])), @@ -321,12 +322,12 @@ pub(crate) mod tests { #[test] fn maybe_signals_validators_change_works() { // when contract is active, but bloom has no required bits set - let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); + let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( + Default::default(), + Vec::new(), + )); let validators = Validators::new(&config); - let mut header = AuraHeader { - number: u64::max_value(), - ..Default::default() - }; + let mut header = AuraHeader { number: u64::max_value(), ..Default::default() }; assert!(!validators.maybe_signals_validators_change(&header)); // when contract is active and bloom has required bits set @@ -347,10 +348,7 @@ pub(crate) mod tests { (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), ]); let validators = Validators::new(&config); - let mut header = AuraHeader { - number: 100, - ..Default::default() - }; + let mut header = AuraHeader { number: 100, ..Default::default() }; // when we're at the block that switches to list source assert_eq!( @@ -406,26 +404,20 @@ pub(crate) mod tests { fn try_finalize_with_scheduled_change(scheduled_at: Option) -> Option { run_test(TOTAL_VALIDATORS, |_| { - let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); + let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( + Default::default(), + Vec::new(), + )); let validators = Validators::new(&config); let storage = BridgeStorage::::new(); // when we're finailizing blocks 10...100 - let id10 = HeaderId { - number: 10, - hash: [10; 32].into(), - }; - let id100 = HeaderId { - number: 100, - hash: [100; 32].into(), - }; + let id10 = HeaderId { number: 10, hash: [10; 32].into() }; + let id100 = HeaderId { number: 100, hash: [100; 32].into() }; let finalized_blocks = vec![(id10, None), (id100, None)]; let header100 = StoredHeader:: { submitter: None, - header: AuraHeader { - number: 100, - ..Default::default() - }, + header: AuraHeader { number: 100, ..Default::default() }, total_difficulty: 0.into(), next_validators_set_id: 0, last_signal_block: scheduled_at, @@ -445,16 +437,10 @@ pub(crate) mod tests { #[test] fn finalize_validators_change_finalizes_scheduled_change() { - let id50 = HeaderId { - number: 50, - ..Default::default() - }; + let id50 = HeaderId { number: 50, ..Default::default() }; assert_eq!( try_finalize_with_scheduled_change(Some(id50)), - Some(ChangeToEnact { - signal_block: Some(id50), - validators: validators_addresses(1), - }), + Some(ChangeToEnact { signal_block: Some(id50), validators: validators_addresses(1) }), ); } @@ -465,10 +451,7 @@ pub(crate) mod tests { #[test] fn finalize_validators_change_does_not_finalize_changes_when_they_are_outside_of_range() { - let id5 = HeaderId { - number: 5, - ..Default::default() - }; + let id5 = HeaderId { number: 5, ..Default::default() }; assert_eq!(try_finalize_with_scheduled_change(Some(id5)), None,); } } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 06aa4906fb4d6..34ae9ad315432 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -14,11 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::error::Error; -use crate::validators::{Validators, ValidatorsConfiguration}; -use crate::{AuraConfiguration, AuraScheduledChange, ChainTime, ImportContext, PoolConfiguration, Storage}; +use crate::{ + error::Error, + validators::{Validators, ValidatorsConfiguration}, + AuraConfiguration, AuraScheduledChange, ChainTime, ImportContext, PoolConfiguration, Storage, +}; use bp_eth_poa::{ - public_to_address, step_validator, Address, AuraHeader, HeaderId, Receipt, SealedEmptyStep, H256, H520, U128, U256, + public_to_address, step_validator, Address, AuraHeader, HeaderId, Receipt, SealedEmptyStep, + H256, H520, U128, U256, }; use codec::Encode; use sp_io::crypto::secp256k1_ecdsa_recover; @@ -28,16 +31,19 @@ use sp_std::{vec, vec::Vec}; /// Pre-check to see if should try and import this header. /// Returns error if we should not try to import this block. /// Returns ID of passed header and best finalized header. -pub fn is_importable_header(storage: &S, header: &AuraHeader) -> Result<(HeaderId, HeaderId), Error> { +pub fn is_importable_header( + storage: &S, + header: &AuraHeader, +) -> Result<(HeaderId, HeaderId), Error> { // we never import any header that competes with finalized header let finalized_id = storage.finalized_block(); if header.number <= finalized_id.number { - return Err(Error::AncientHeader); + return Err(Error::AncientHeader) } // we never import any header with known hash let id = header.compute_id(); if storage.header(&id.hash).is_some() { - return Err(Error::KnownHeader); + return Err(Error::KnownHeader) } Ok((id, finalized_id)) @@ -64,7 +70,8 @@ pub fn accept_aura_header_into_pool( // we want to avoid having same headers twice in the pool // => we're strict about receipts here - if we need them, we require receipts to be Some, // otherwise we require receipts to be None - let receipts_required = Validators::new(validators_config).maybe_signals_validators_change(header); + let receipts_required = + Validators::new(validators_config).maybe_signals_validators_change(header); match (receipts_required, receipts.is_some()) { (true, false) => return Err(Error::MissingTransactionsReceipts), (false, true) => return Err(Error::RedundantTransactionsReceipts), @@ -78,7 +85,7 @@ pub fn accept_aura_header_into_pool( let (best_id, _) = storage.best_block(); let difference = header.number.saturating_sub(best_id.number); if difference > pool_config.max_future_number_difference { - return Err(Error::UnsignedTooFarInTheFuture); + return Err(Error::UnsignedTooFarInTheFuture) } // TODO: only accept new headers when we're at the tip of PoA chain @@ -104,11 +111,8 @@ pub fn accept_aura_header_into_pool( // since our parent is already in the storage, we do not require it // to be in the transaction pool - ( - vec![], - vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag], - ) - } + (vec![], vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag]) + }, None => { // we know nothing about parent header // => the best thing we can do is to believe that there are no forks in @@ -119,34 +123,37 @@ pub fn accept_aura_header_into_pool( "import context is None only when header is missing from the storage;\ best header is always in the storage; qed", ); - let validators_check_result = - validator_checks(config, &best_context.validators_set().validators, header, header_step); + let validators_check_result = validator_checks( + config, + &best_context.validators_set().validators, + header, + header_step, + ); if let Err(error) = validators_check_result { - find_next_validators_signal(storage, &best_context) - .ok_or(error) - .and_then(|next_validators| validator_checks(config, &next_validators, header, header_step))?; + find_next_validators_signal(storage, &best_context).ok_or(error).and_then( + |next_validators| { + validator_checks(config, &next_validators, header, header_step) + }, + )?; } // since our parent is missing from the storage, we **DO** require it // to be in the transaction pool // (- 1 can't underflow because there's always best block in the header) - let requires_header_number_and_hash_tag = HeaderId { - number: header.number - 1, - hash: header.parent_hash, - } - .encode(); + let requires_header_number_and_hash_tag = + HeaderId { number: header.number - 1, hash: header.parent_hash }.encode(); ( vec![requires_header_number_and_hash_tag], vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag], ) - } + }, }; // the heaviest, but rare operation - we do not want invalid receipts in the pool if let Some(receipts) = receipts { log::trace!(target: "runtime", "Got receipts! {:?}", receipts); if header.check_receipts_root(receipts).is_err() { - return Err(Error::TransactionsReceiptsMismatch); + return Err(Error::TransactionsReceiptsMismatch) } } @@ -189,32 +196,32 @@ fn contextless_checks( ) -> Result<(), Error> { let expected_seal_fields = expected_header_seal_fields(config, header); if header.seal.len() != expected_seal_fields { - return Err(Error::InvalidSealArity); + return Err(Error::InvalidSealArity) } if header.number >= u64::max_value() { - return Err(Error::RidiculousNumber); + return Err(Error::RidiculousNumber) } if header.gas_used > header.gas_limit { - return Err(Error::TooMuchGasUsed); + return Err(Error::TooMuchGasUsed) } if header.gas_limit < config.min_gas_limit { - return Err(Error::InvalidGasLimit); + return Err(Error::InvalidGasLimit) } if header.gas_limit > config.max_gas_limit { - return Err(Error::InvalidGasLimit); + return Err(Error::InvalidGasLimit) } if header.number != 0 && header.extra_data.len() as u64 > config.maximum_extra_data_size { - return Err(Error::ExtraDataOutOfBounds); + return Err(Error::ExtraDataOutOfBounds) } // we can't detect if block is from future in runtime // => let's only do an overflow check if header.timestamp > i32::max_value() as u64 { - return Err(Error::TimestampOverflow); + return Err(Error::TimestampOverflow) } if chain_time.is_timestamp_ahead(header.timestamp) { - return Err(Error::HeaderTimestampIsAhead); + return Err(Error::HeaderTimestampIsAhead) } Ok(()) @@ -233,15 +240,16 @@ fn contextual_checks( // Ensure header is from the step after context. if header_step == parent_step { - return Err(Error::DoubleVote); + return Err(Error::DoubleVote) } #[allow(clippy::suspicious_operation_groupings)] if header.number >= config.validate_step_transition && header_step < parent_step { - return Err(Error::DoubleVote); + return Err(Error::DoubleVote) } - // If empty step messages are enabled we will validate the messages in the seal, missing messages are not - // reported as there's no way to tell whether the empty step message was never sent or simply not included. + // If empty step messages are enabled we will validate the messages in the seal, missing + // messages are not reported as there's no way to tell whether the empty step message was never + // sent or simply not included. let empty_steps_len = match header.number >= config.empty_steps_transition { true => { let strict_empty_steps = header.number >= config.strict_empty_steps_transition; @@ -251,16 +259,16 @@ fn contextual_checks( for empty_step in empty_steps { if empty_step.step <= parent_step || empty_step.step >= header_step { - return Err(Error::InsufficientProof); + return Err(Error::InsufficientProof) } if !verify_empty_step(&header.parent_hash, &empty_step, validators) { - return Err(Error::InsufficientProof); + return Err(Error::InsufficientProof) } if strict_empty_steps { if empty_step.step <= prev_empty_step { - return Err(Error::InsufficientProof); + return Err(Error::InsufficientProof) } prev_empty_step = empty_step.step; @@ -268,7 +276,7 @@ fn contextual_checks( } empty_steps_len - } + }, false => 0, }; @@ -276,7 +284,7 @@ fn contextual_checks( if header.number >= config.validate_score_transition { let expected_difficulty = calculate_score(parent_step, header_step, empty_steps_len as _); if header.difficulty != expected_difficulty { - return Err(Error::InvalidDifficulty); + return Err(Error::InvalidDifficulty) } } @@ -292,16 +300,17 @@ fn validator_checks( ) -> Result<(), Error> { let expected_validator = *step_validator(validators, header_step); if header.author != expected_validator { - return Err(Error::NotValidator); + return Err(Error::NotValidator) } let validator_signature = header.signature().ok_or(Error::MissingSignature)?; let header_seal_hash = header .seal_hash(header.number >= config.empty_steps_transition) .ok_or(Error::MissingEmptySteps)?; - let is_invalid_proposer = !verify_signature(&expected_validator, &validator_signature, &header_seal_hash); + let is_invalid_proposer = + !verify_signature(&expected_validator, &validator_signature, &header_seal_hash); if is_invalid_proposer { - return Err(Error::NotValidator); + return Err(Error::NotValidator) } Ok(()) @@ -324,8 +333,13 @@ fn verify_empty_step(parent_hash: &H256, step: &SealedEmptyStep, validators: &[A } /// Chain scoring: total weight is sqrt(U256::max_value())*height - step -pub(crate) fn calculate_score(parent_step: u64, current_step: u64, current_empty_steps: usize) -> U256 { - U256::from(U128::max_value()) + U256::from(parent_step) - U256::from(current_step) + U256::from(current_empty_steps) +pub(crate) fn calculate_score( + parent_step: u64, + current_step: u64, + current_empty_steps: usize, +) -> U256 { + U256::from(U128::max_value()) + U256::from(parent_step) - U256::from(current_step) + + U256::from(current_empty_steps) } /// Verify that the signature over message has been produced by given validator. @@ -337,7 +351,10 @@ fn verify_signature(expected_validator: &Address, signature: &H520, message: &H2 } /// Find next unfinalized validators set change after finalized set. -fn find_next_validators_signal(storage: &S, context: &ImportContext) -> Option> { +fn find_next_validators_signal( + storage: &S, + context: &ImportContext, +) -> Option> { // that's the earliest block number we may met in following loop // it may be None if that's the first set let best_set_signal_block = context.validators_set().signal_block; @@ -352,14 +369,15 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< // next_current_block_hash points to the block that schedules next // change let current_scheduled_set = match current_set_signal_block { - Some(current_set_signal_block) if Some(¤t_set_signal_block) == best_set_signal_block.as_ref() => { - return next_scheduled_set.map(|scheduled_set| scheduled_set.validators) - } + Some(current_set_signal_block) + if Some(¤t_set_signal_block) == best_set_signal_block.as_ref() => + return next_scheduled_set.map(|scheduled_set| scheduled_set.validators), None => return next_scheduled_set.map(|scheduled_set| scheduled_set.validators), - Some(current_set_signal_block) => storage.scheduled_change(¤t_set_signal_block.hash).expect( - "header that is associated with this change is not pruned;\ + Some(current_set_signal_block) => + storage.scheduled_change(¤t_set_signal_block.hash).expect( + "header that is associated with this change is not pruned;\ scheduled changes are only removed when header is pruned; qed", - ), + ), }; current_set_signal_block = current_scheduled_set.prev_signal_block; @@ -370,13 +388,15 @@ fn find_next_validators_signal(storage: &S, context: &ImportContext< #[cfg(test)] mod tests { use super::*; - use crate::mock::{ - insert_header, run_test_with_genesis, test_aura_config, validator, validator_address, validators_addresses, - validators_change_receipt, AccountId, ConstChainTime, HeaderBuilder, TestRuntime, GAS_LIMIT, - }; - use crate::validators::ValidatorsSource; use crate::{ - pool_configuration, BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, + mock::{ + insert_header, run_test_with_genesis, test_aura_config, validator, validator_address, + validators_addresses, validators_change_receipt, AccountId, ConstChainTime, + HeaderBuilder, TestRuntime, GAS_LIMIT, + }, + pool_configuration, + validators::ValidatorsSource, + BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, ScheduledChanges, ValidatorsSet, ValidatorsSets, }; use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256}; @@ -391,7 +411,10 @@ mod tests { HeaderBuilder::genesis().step(GENESIS_STEP).sign_by(&validator(0)) } - fn verify_with_config(config: &AuraConfiguration, header: &AuraHeader) -> Result, Error> { + fn verify_with_config( + config: &AuraConfiguration, + header: &AuraHeader, + ) -> Result, Error> { run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { let storage = BridgeStorage::::new(); verify_aura_header(&storage, config, None, header, &ConstChainTime::default()) @@ -418,8 +441,10 @@ mod tests { FinalizedBlock::::put(block2_id); - let validators_config = - ValidatorsConfiguration::Single(ValidatorsSource::Contract(Default::default(), Vec::new())); + let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( + Default::default(), + Vec::new(), + )); let (header, receipts) = make_header(&validators); accept_aura_header_into_pool( &storage, @@ -433,7 +458,11 @@ mod tests { }) } - fn change_validators_set_at(number: u64, finalized_set: Vec
, signalled_set: Option>) { + fn change_validators_set_at( + number: u64, + finalized_set: Vec
, + signalled_set: Option>, + ) { let set_id = NextValidatorsSetId::::get(); NextValidatorsSetId::::put(set_id + 1); ValidatorsSets::::insert( @@ -458,10 +487,7 @@ mod tests { }); ScheduledChanges::::insert( header.header.parent_hash, - AuraScheduledChange { - validators: signalled_set, - prev_signal_block: None, - }, + AuraScheduledChange { validators: signalled_set, prev_signal_block: None }, ); } @@ -520,21 +546,15 @@ mod tests { config.max_gas_limit = 200.into(); // when limit is lower than expected - let header = HeaderBuilder::with_number(1) - .gas_limit(50.into()) - .sign_by(&validator(0)); + let header = HeaderBuilder::with_number(1).gas_limit(50.into()).sign_by(&validator(0)); assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); // when limit is larger than expected - let header = HeaderBuilder::with_number(1) - .gas_limit(250.into()) - .sign_by(&validator(0)); + let header = HeaderBuilder::with_number(1).gas_limit(250.into()).sign_by(&validator(0)); assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); // when limit is within expected range - let header = HeaderBuilder::with_number(1) - .gas_limit(150.into()) - .sign_by(&validator(0)); + let header = HeaderBuilder::with_number(1).gas_limit(150.into()).sign_by(&validator(0)); assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); } @@ -573,7 +593,8 @@ mod tests { // expected import context after verification let expect = ImportContext:: { submitter: None, - parent_hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3").into(), + parent_hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3") + .into(), parent_header: genesis(), parent_total_difficulty: U256::zero(), parent_scheduled_change: None, @@ -587,7 +608,8 @@ mod tests { signal_block: None, enact_block: HeaderId { number: 0, - hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3").into(), + hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3") + .into(), }, }, last_signal_block: None, @@ -729,7 +751,10 @@ mod tests { fn pool_verifies_known_blocks() { // when header is known assert_eq!( - default_accept_into_pool(|validators| (HeaderBuilder::with_parent_number(2).sign_by_set(validators), None)), + default_accept_into_pool(|validators| ( + HeaderBuilder::with_parent_number(2).sign_by_set(validators), + None + )), Err(Error::KnownHeader), ); } @@ -785,7 +810,10 @@ mod tests { fn pool_verifies_future_block_number() { // when header is too far from the future assert_eq!( - default_accept_into_pool(|validators| (HeaderBuilder::with_number(100).sign_by_set(validators), None),), + default_accept_into_pool(|validators| ( + HeaderBuilder::with_number(100).sign_by_set(validators), + None + ),), Err(Error::UnsignedTooFarInTheFuture), ); } @@ -811,7 +839,10 @@ mod tests { // (even if header will be considered invalid/duplicate later, we can use this signature // as a proof of malicious action by this validator) assert_eq!( - default_accept_into_pool(|_| (HeaderBuilder::with_number(8).step(8).sign_by(&validator(1)), None,)), + default_accept_into_pool(|_| ( + HeaderBuilder::with_number(8).step(8).sign_by(&validator(1)), + None, + )), Err(Error::NotValidator), ); } @@ -829,10 +860,7 @@ mod tests { // no tags are required vec![], // header provides two tags - vec![ - (4u64, validators_addresses(3)[1]).encode(), - (4u64, hash.unwrap()).encode(), - ], + vec![(4u64, validators_addresses(3)[1]).encode(), (4u64, hash.unwrap()).encode(),], )), ); } @@ -843,9 +871,8 @@ mod tests { let mut parent_id = None; assert_eq!( default_accept_into_pool(|validators| { - let header = HeaderBuilder::with_number(5) - .step(GENESIS_STEP + 5) - .sign_by_set(validators); + let header = + HeaderBuilder::with_number(5).step(GENESIS_STEP + 5).sign_by_set(validators); id = Some(header.compute_id()); parent_id = header.parent_id(); (header, None) @@ -881,7 +908,11 @@ mod tests { assert_eq!( default_accept_into_pool(|actual_validators| { // change finalized set at parent header + signal valid set at parent block - change_validators_set_at(3, validators_addresses(10), Some(validators_addresses(3))); + change_validators_set_at( + 3, + validators_addresses(10), + Some(validators_addresses(3)), + ); // header is signed using wrong set let header = HeaderBuilder::with_number(5) @@ -933,10 +964,7 @@ mod tests { // no tags are required vec![], // header provides two tags - vec![ - (4u64, validators_addresses(3)[1]).encode(), - (4u64, hash.unwrap()).encode(), - ], + vec![(4u64, validators_addresses(3)[1]).encode(), (4u64, hash.unwrap()).encode(),], )), ); } diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 1714024928dc5..46e1e41a87028 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -42,7 +42,8 @@ use crate::*; use bp_test_utils::{ - accounts, make_justification_for_header, JustificationGeneratorParams, TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, + accounts, make_justification_for_header, JustificationGeneratorParams, TEST_GRANDPA_ROUND, + TEST_GRANDPA_SET_ID, }; use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; use frame_support::traits::Get; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index f1599a5ebfbaf..279e23404a059 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -38,8 +38,7 @@ use crate::weights::WeightInfo; -use bp_header_chain::justification::GrandpaJustification; -use bp_header_chain::InitializationData; +use bp_header_chain::{justification::GrandpaJustification, InitializationData}; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use finality_grandpa::voter_set::VoterSet; use frame_support::{ensure, fail}; @@ -136,10 +135,7 @@ pub mod pallet { ensure_operational::()?; let _ = ensure_signed(origin)?; - ensure!( - Self::request_count() < T::MaxRequests::get(), - >::TooManyRequests - ); + ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); let (hash, number) = (finality_target.hash(), finality_target.number()); log::trace!(target: "runtime::bridge-grandpa", "Going to try and finalize header {:?}", finality_target); @@ -153,27 +149,29 @@ pub mod pallet { finality_target, ); fail!(>::NotInitialized); - } + }, }; // We do a quick check here to ensure that our header chain is making progress and isn't - // "travelling back in time" (which could be indicative of something bad, e.g a hard-fork). + // "travelling back in time" (which could be indicative of something bad, e.g a + // hard-fork). ensure!(best_finalized.number() < number, >::OldHeader); let authority_set = >::get(); let set_id = authority_set.set_id; verify_justification::(&justification, hash, *number, authority_set)?; - let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; + let is_authorities_change_enacted = + try_enact_authority_change::(&finality_target, set_id)?; >::mutate(|count| *count += 1); insert_header::(*finality_target, hash); log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); - // mandatory header is a header that changes authorities set. The pallet can't go further - // without importing this header. So every bridge MUST import mandatory headers. + // mandatory header is a header that changes authorities set. The pallet can't go + // further without importing this header. So every bridge MUST import mandatory headers. // - // We don't want to charge extra costs for mandatory operations. So relayer is not paying - // fee for mandatory headers import transactions. + // We don't want to charge extra costs for mandatory operations. So relayer is not + // paying fee for mandatory headers import transactions. let is_mandatory_header = is_authorities_change_enacted; let pays_fee = if is_mandatory_header { Pays::No } else { Pays::Yes }; @@ -183,8 +181,8 @@ pub mod pallet { /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. /// /// The initial configuration provided does not need to be the genesis header of the bridged - /// chain, it can be any arbitrary header. You can also provide the next scheduled set change - /// if it is already know. + /// chain, it can be any arbitrary header. You can also provide the next scheduled set + /// change if it is already know. /// /// This function is only allowed to be called from a trusted origin and writes to storage /// with practically no checks in terms of the validity of the data. It is important that @@ -213,17 +211,20 @@ pub mod pallet { /// /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResultWithPostInfo { + pub fn set_owner( + origin: OriginFor, + new_owner: Option, + ) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; match new_owner { Some(new_owner) => { PalletOwner::::put(&new_owner); log::info!(target: "runtime::bridge-grandpa", "Setting pallet Owner to: {:?}", new_owner); - } + }, None => { PalletOwner::::kill(); log::info!(target: "runtime::bridge-grandpa", "Removed Owner of pallet."); - } + }, } Ok(().into()) @@ -233,7 +234,10 @@ pub mod pallet { /// /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operational(origin: OriginFor, operational: bool) -> DispatchResultWithPostInfo { + pub fn set_operational( + origin: OriginFor, + operational: bool, + ) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; >::put(operational); @@ -260,11 +264,13 @@ pub mod pallet { /// Hash of the header used to bootstrap the pallet. #[pallet::storage] - pub(super) type InitialHash, I: 'static = ()> = StorageValue<_, BridgedBlockHash, ValueQuery>; + pub(super) type InitialHash, I: 'static = ()> = + StorageValue<_, BridgedBlockHash, ValueQuery>; /// Hash of the best finalized header. #[pallet::storage] - pub(super) type BestFinalized, I: 'static = ()> = StorageValue<_, BridgedBlockHash, ValueQuery>; + pub(super) type BestFinalized, I: 'static = ()> = + StorageValue<_, BridgedBlockHash, ValueQuery>; /// A ring buffer of imported hashes. Ordered by the insertion time. #[pallet::storage] @@ -273,7 +279,8 @@ pub mod pallet { /// Current ring buffer position. #[pallet::storage] - pub(super) type ImportedHashesPointer, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; + pub(super) type ImportedHashesPointer, I: 'static = ()> = + StorageValue<_, u32, ValueQuery>; /// Headers which have been imported into the pallet. #[pallet::storage] @@ -292,7 +299,8 @@ pub mod pallet { /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). #[pallet::storage] - pub(super) type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; + pub(super) type PalletOwner, I: 'static = ()> = + StorageValue<_, T::AccountId, OptionQuery>; /// If true, all pallet transactions are failed immediately. #[pallet::storage] @@ -309,10 +317,7 @@ pub mod pallet { #[cfg(feature = "std")] impl, I: 'static> Default for GenesisConfig { fn default() -> Self { - Self { - owner: None, - init_data: None, - } + Self { owner: None, init_data: None } } } @@ -419,29 +424,35 @@ pub mod pallet { ) -> Result<(), sp_runtime::DispatchError> { use bp_header_chain::justification::verify_justification; - let voter_set = VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; + let voter_set = + VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; let set_id = authority_set.set_id; - Ok( - verify_justification::>((hash, number), set_id, &voter_set, justification).map_err( - |e| { - log::error!( - target: "runtime::bridge-grandpa", - "Received invalid justification for {:?}: {:?}", - hash, - e, - ); - >::InvalidJustification - }, - )?, + Ok(verify_justification::>( + (hash, number), + set_id, + &voter_set, + justification, ) + .map_err(|e| { + log::error!( + target: "runtime::bridge-grandpa", + "Received invalid justification for {:?}: {:?}", + hash, + e, + ); + >::InvalidJustification + })?) } /// Import a previously verified header to the storage. /// /// Note this function solely takes care of updating the storage and pruning old entries, /// but does not verify the validity of such import. - pub(crate) fn insert_header, I: 'static>(header: BridgedHeader, hash: BridgedBlockHash) { + pub(crate) fn insert_header, I: 'static>( + header: BridgedHeader, + hash: BridgedBlockHash, + ) { let index = >::get(); let pruning = >::try_get(index); >::put(hash); @@ -461,12 +472,7 @@ pub mod pallet { pub(crate) fn initialize_bridge, I: 'static>( init_params: super::InitializationData>, ) { - let super::InitializationData { - header, - authority_list, - set_id, - is_halted, - } = init_params; + let super::InitializationData { header, authority_list, set_id, is_halted } = init_params; let initial_hash = header.hash(); >::put(initial_hash); @@ -506,7 +512,9 @@ pub mod pallet { fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) if Some(signer) == >::get().as_ref() => Ok(()), + Ok(RawOrigin::Signed(ref signer)) + if Some(signer) == >::get().as_ref() => + Ok(()), _ => Err(BadOrigin), } } @@ -553,14 +561,17 @@ impl, I: 'static> Pallet { parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, ) -> Result { let header = >::get(hash).ok_or(Error::::UnknownHeader)?; - let storage_proof_checker = bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) - .map_err(|_| Error::::StorageRootMismatch)?; + let storage_proof_checker = + bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) + .map_err(|_| Error::::StorageRootMismatch)?; Ok(parse(storage_proof_checker)) } } -pub(crate) fn find_scheduled_change(header: &H) -> Option> { +pub(crate) fn find_scheduled_change( + header: &H, +) -> Option> { use sp_runtime::generic::OpaqueDigestItemId; let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); @@ -599,7 +610,8 @@ pub(crate) fn find_forced_change( pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader) { initialize_bridge::(InitializationData { header: Box::new(header), - authority_list: sp_std::vec::Vec::new(), // we don't verify any proofs in external benchmarks + authority_list: sp_std::vec::Vec::new(), /* we don't verify any proofs in external + * benchmarks */ set_id: 0, is_halted: false, }); @@ -608,14 +620,15 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime}; + use crate::mock::{ + run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime, + }; use bp_test_utils::{ - authority_list, make_default_justification, make_justification_for_header, JustificationGeneratorParams, ALICE, - BOB, + authority_list, make_default_justification, make_justification_for_header, + JustificationGeneratorParams, ALICE, BOB, }; use codec::Encode; - use frame_support::weights::PostDispatchInfo; - use frame_support::{assert_err, assert_noop, assert_ok}; + use frame_support::{assert_err, assert_noop, assert_ok, weights::PostDispatchInfo}; use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { @@ -624,7 +637,10 @@ mod tests { fn init_with_origin( origin: Origin, - ) -> Result, sp_runtime::DispatchErrorWithPostInfo> { + ) -> Result< + InitializationData, + sp_runtime::DispatchErrorWithPostInfo, + > { let genesis = test_header(0); let init_data = InitializationData { @@ -641,7 +657,11 @@ mod tests { let header = test_header(header.into()); let justification = make_default_justification(&header); - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification) + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification, + ) } fn next_block() { @@ -653,10 +673,11 @@ mod tests { } fn change_log(delay: u64) -> Digest { - let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { - next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], - delay, - }); + let consensus_log = + ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], + delay, + }); Digest:: { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], @@ -821,14 +842,16 @@ mod tests { let header = test_header(1); - let params = JustificationGeneratorParams:: { - set_id: 2, - ..Default::default() - }; + let params = + JustificationGeneratorParams:: { set_id: 2, ..Default::default() }; let justification = make_justification_for_header(params); assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification,), + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification, + ), >::InvalidJustification ); }) @@ -844,7 +867,11 @@ mod tests { justification.round = 42; assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification,), + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification, + ), >::InvalidJustification ); }) @@ -869,7 +896,11 @@ mod tests { let justification = make_default_justification(&header); assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification,), + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification, + ), >::InvalidAuthoritySet ); }) @@ -942,7 +973,11 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification), + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification + ), >::UnsupportedScheduledChange ); }) @@ -963,7 +998,11 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), justification), + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification + ), >::UnsupportedScheduledChange ); }) @@ -1021,7 +1060,11 @@ mod tests { let mut invalid_justification = make_default_justification(&header); invalid_justification.round = 42; - Pallet::::submit_finality_proof(Origin::signed(1), Box::new(header), invalid_justification) + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + invalid_justification, + ) }; initialize_substrate_bridge(); diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index d6ec00324493a..788ccc070310e 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -16,15 +16,15 @@ //! Messages pallet benchmarking. -use crate::weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH; use crate::{ - inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, outbound_lane::ReceivalConfirmationResult, - Call, + inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, + outbound_lane::ReceivalConfirmationResult, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, }; use bp_messages::{ - source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, InboundLaneData, LaneId, - MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, + source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, + InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, + UnrewardedRelayersState, }; use bp_runtime::messages::DispatchFeePayment; use frame_benchmarking::{account, benchmarks_instance_pallet}; @@ -50,11 +50,11 @@ pub enum ProofSize { /// The proof is expected to be minimal. If value size may be changed, then it is expected to /// have given size. Minimal(u32), - /// The proof is expected to have at least given size and grow by increasing number of trie nodes - /// included in the proof. + /// The proof is expected to have at least given size and grow by increasing number of trie + /// nodes included in the proof. HasExtraNodes(u32), - /// The proof is expected to have at least given size and grow by increasing value that is stored - /// in the trie. + /// The proof is expected to have at least given size and grow by increasing value that is + /// stored in the trie. HasLargeLeaf(u32), } @@ -900,18 +900,12 @@ benchmarks_instance_pallet! { fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { - payload: vec![], - fee: MESSAGE_FEE.into(), - }); + outbound_lane.send_message(MessageData { payload: vec![], fee: MESSAGE_FEE.into() }); } fn send_regular_message_with_payload, I: 'static>(payload: Vec) { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { - payload, - fee: MESSAGE_FEE.into(), - }); + outbound_lane.send_message(MessageData { payload, fee: MESSAGE_FEE.into() }); } fn confirm_message_delivery, I: 'static>(nonce: MessageNonce) { @@ -943,7 +937,10 @@ fn receive_messages, I: 'static>(nonce: MessageNonce) { }); } -fn ensure_relayer_rewarded, I: 'static>(relayer_id: &T::AccountId, old_balance: &T::OutboundMessageFee) { +fn ensure_relayer_rewarded, I: 'static>( + relayer_id: &T::AccountId, + old_balance: &T::OutboundMessageFee, +) { let new_balance = T::account_balance(relayer_id); assert!( new_balance > *old_balance, diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 645174b6d750f..00875bb878a82 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -18,7 +18,8 @@ use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, UnrewardedRelayer, + DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, + UnrewardedRelayer, }; use bp_runtime::messages::MessageDispatchResult; use frame_support::RuntimeDebug; @@ -71,16 +72,19 @@ impl InboundLane { } /// Receive state of the corresponding outbound lane. - pub fn receive_state_update(&mut self, outbound_lane_data: OutboundLaneData) -> Option { + pub fn receive_state_update( + &mut self, + outbound_lane_data: OutboundLaneData, + ) -> Option { let mut data = self.storage.data(); let last_delivered_nonce = data.last_delivered_nonce(); if outbound_lane_data.latest_received_nonce > last_delivered_nonce { // this is something that should never happen if proofs are correct - return None; + return None } if outbound_lane_data.latest_received_nonce <= data.last_confirmed_nonce { - return None; + return None } let new_confirmed_nonce = outbound_lane_data.latest_received_nonce; @@ -95,7 +99,8 @@ impl InboundLane { data.relayers.pop_front(); } // Secondly, update the next record with lower nonce equal to new confirmed nonce if needed. - // Note: There will be max. 1 record to update as we don't allow messages from relayers to overlap. + // Note: There will be max. 1 record to update as we don't allow messages from relayers to + // overlap. match data.relayers.front_mut() { Some(entry) if entry.messages.begin < new_confirmed_nonce => { entry.messages.dispatch_results = entry @@ -103,8 +108,8 @@ impl InboundLane { .dispatch_results .split_off((new_confirmed_nonce + 1 - entry.messages.begin) as _); entry.messages.begin = new_confirmed_nonce + 1; - } - _ => {} + }, + _ => {}, } self.storage.set_data(data); @@ -122,28 +127,25 @@ impl InboundLane { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { - return ReceivalResult::InvalidNonce; + return ReceivalResult::InvalidNonce } // if there are more unrewarded relayer entries than we may accept, reject this message if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() { - return ReceivalResult::TooManyUnrewardedRelayers; + return ReceivalResult::TooManyUnrewardedRelayers } // if there are more unconfirmed messages than we may accept, reject this message let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce); if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { - return ReceivalResult::TooManyUnconfirmedMessages; + return ReceivalResult::TooManyUnconfirmedMessages } // then, dispatch message let dispatch_result = P::dispatch( relayer_at_this_chain, DispatchMessage { - key: MessageKey { - lane_id: self.storage.id(), - nonce, - }, + key: MessageKey { lane_id: self.storage.id(), nonce }, data: message_data, }, ); @@ -153,7 +155,7 @@ impl InboundLane { Some(entry) if entry.relayer == *relayer_at_bridged_chain => { entry.messages.note_dispatched_message(dispatch_result.dispatch_result); false - } + }, _ => true, }; if push_new { @@ -174,8 +176,9 @@ mod tests { use crate::{ inbound_lane, mock::{ - dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch, TestRuntime, - REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C, + dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch, + TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + TEST_RELAYER_C, }, RuntimeInboundLaneStorage, }; @@ -284,16 +287,10 @@ mod tests { let mut seed_storage_data = lane.storage.data(); // Prepare data seed_storage_data.last_confirmed_nonce = 0; - seed_storage_data - .relayers - .push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A)); + seed_storage_data.relayers.push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A)); // Simulate messages batch (2, 3, 4) from relayer #2 - seed_storage_data - .relayers - .push_back(unrewarded_relayer(2, 4, TEST_RELAYER_B)); - seed_storage_data - .relayers - .push_back(unrewarded_relayer(5, 5, TEST_RELAYER_C)); + seed_storage_data.relayers.push_back(unrewarded_relayer(2, 4, TEST_RELAYER_B)); + seed_storage_data.relayers.push_back(unrewarded_relayer(5, 5, TEST_RELAYER_C)); lane.storage.set_data(seed_storage_data); // Check assert_eq!( @@ -335,7 +332,8 @@ mod tests { fn fails_to_receive_messages_above_unrewarded_relayer_entries_limit_per_lane() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let max_nonce = ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); + let max_nonce = + ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); for current_nonce in 1..max_nonce + 1 { assert_eq!( lane.receive_message::( @@ -374,7 +372,8 @@ mod tests { fn fails_to_receive_messages_above_unconfirmed_messages_limit_per_lane() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); + let max_nonce = + ::MaxUnconfirmedMessagesAtInboundLane::get(); for current_nonce in 1..=max_nonce { assert_eq!( lane.receive_message::( diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index 1c67c0446a3ba..4933901c26708 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -46,7 +46,8 @@ pub struct InstantCurrencyPayments _phantom: sp_std::marker::PhantomData<(T, Currency, GetConfirmationFee, RootAccount)>, } -impl MessageDeliveryAndDispatchPayment +impl + MessageDeliveryAndDispatchPayment for InstantCurrencyPayments where T: frame_system::Config, @@ -118,26 +119,31 @@ fn pay_relayers_rewards( // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee // from relayer reward. // - // If confirmation fee has been increased (or if it was the only component of message fee), - // then messages relayer may receive zero reward. + // If confirmation fee has been increased (or if it was the only component of message + // fee), then messages relayer may receive zero reward. let mut confirmation_reward = confirmation_fee.saturating_mul(reward.messages.into()); if confirmation_reward > relayer_reward { confirmation_reward = relayer_reward; } relayer_reward = relayer_reward.saturating_sub(confirmation_reward); - confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(confirmation_reward); + confirmation_relayer_reward = + confirmation_relayer_reward.saturating_add(confirmation_reward); } else { // If delivery confirmation is submitted by this relayer, let's add confirmation fee // from other relayers to this relayer reward. confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward); - continue; + continue } pay_relayer_reward::(relayer_fund_account, &relayer, relayer_reward); } // finally - pay reward to confirmation relayer - pay_relayer_reward::(relayer_fund_account, confirmation_relayer, confirmation_relayer_reward); + pay_relayer_reward::( + relayer_fund_account, + confirmation_relayer, + confirmation_relayer_reward, + ); } /// Transfer funds from relayers fund account to given relayer. @@ -150,7 +156,7 @@ fn pay_relayer_reward( Currency: CurrencyT, { if reward.is_zero() { - return; + return } let pay_result = Currency::transfer( @@ -193,20 +199,8 @@ mod tests { fn relayers_rewards() -> RelayersRewards { vec![ - ( - RELAYER_1, - RelayerRewards { - reward: 100, - messages: 2, - }, - ), - ( - RELAYER_2, - RelayerRewards { - reward: 100, - messages: 3, - }, - ), + (RELAYER_1, RelayerRewards { reward: 100, messages: 2 }), + (RELAYER_2, RelayerRewards { reward: 100, messages: 3 }), ] .into_iter() .collect() @@ -215,7 +209,12 @@ mod tests { #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { - pay_relayers_rewards::(&RELAYER_2, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 10); + pay_relayers_rewards::( + &RELAYER_2, + relayers_rewards(), + &RELAYERS_FUND_ACCOUNT, + 10, + ); assert_eq!(Balances::free_balance(&RELAYER_1), 80); assert_eq!(Balances::free_balance(&RELAYER_2), 120); @@ -225,7 +224,12 @@ mod tests { #[test] fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { run_test(|| { - pay_relayers_rewards::(&RELAYER_3, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 10); + pay_relayers_rewards::( + &RELAYER_3, + relayers_rewards(), + &RELAYERS_FUND_ACCOUNT, + 10, + ); assert_eq!(Balances::free_balance(&RELAYER_1), 80); assert_eq!(Balances::free_balance(&RELAYER_2), 70); @@ -236,7 +240,12 @@ mod tests { #[test] fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { run_test(|| { - pay_relayers_rewards::(&RELAYER_3, relayers_rewards(), &RELAYERS_FUND_ACCOUNT, 1000); + pay_relayers_rewards::( + &RELAYER_3, + relayers_rewards(), + &RELAYERS_FUND_ACCOUNT, + 1000, + ); assert_eq!(Balances::free_balance(&RELAYER_1), 0); assert_eq!(Balances::free_balance(&RELAYER_2), 0); diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 8e6f0969b5485..c5ce27bb7258a 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -38,22 +38,27 @@ #![allow(clippy::unused_unit)] pub use crate::weights_ext::{ - ensure_able_to_receive_confirmation, ensure_able_to_receive_message, ensure_weights_are_correct, WeightInfoExt, - EXPECTED_DEFAULT_MESSAGE_LENGTH, + ensure_able_to_receive_confirmation, ensure_able_to_receive_message, + ensure_weights_are_correct, WeightInfoExt, EXPECTED_DEFAULT_MESSAGE_LENGTH, }; -use crate::inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult}; -use crate::outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult}; -use crate::weights::WeightInfo; +use crate::{ + inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult}, + outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult}, + weights::WeightInfo, +}; use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, OnMessageAccepted, - RelayersRewards, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, + OnMessageAccepted, RelayersRewards, TargetHeaderChain, + }, + target_chain::{ + DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, - target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, - OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState, + total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, + MessageNonce, OperatingMode, OutboundLaneData, Parameter as MessagesParameter, + UnrewardedRelayersState, }; use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; @@ -112,8 +117,8 @@ pub mod pallet { /// be ready to pay for its maintenance. type MaxMessagesToPruneAtOnce: Get; /// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the - /// relayer has delivered messages, but either confirmations haven't been delivered back to the - /// source chain, or we haven't received reward confirmations yet. + /// relayer has delivered messages, but either confirmations haven't been delivered back to + /// the source chain, or we haven't received reward confirmations yet. /// /// This constant limits maximal number of entries in the `InboundLaneData::relayers`. Keep /// in mind that the same relayer account may take several (non-consecutive) entries in this @@ -126,12 +131,13 @@ pub mod pallet { /// This constant limits difference between last message from last entry of the /// `InboundLaneData::relayers` and first message at the first entry. /// - /// There is no point of making this parameter lesser than MaxUnrewardedRelayerEntriesAtInboundLane, - /// because then maximal number of relayer entries will be limited by maximal number of messages. + /// There is no point of making this parameter lesser than + /// MaxUnrewardedRelayerEntriesAtInboundLane, because then maximal number of relayer entries + /// will be limited by maximal number of messages. /// - /// This value also represents maximal number of messages in single delivery transaction. Transaction - /// that is declaring more messages than this value, will be rejected. Even if these messages are - /// from different lanes. + /// This value also represents maximal number of messages in single delivery transaction. + /// Transaction that is declaring more messages than this value, will be rejected. Even if + /// these messages are from different lanes. type MaxUnconfirmedMessagesAtInboundLane: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. @@ -143,7 +149,8 @@ pub mod pallet { type InboundPayload: Decode; /// Message fee type of inbound messages. This fee is paid on the bridged chain. type InboundMessageFee: Decode; - /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the bridged chain. + /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the + /// bridged chain. type InboundRelayer: Parameter; /// A type which can be turned into an AccountId from a 256-bit hash. @@ -156,7 +163,11 @@ pub mod pallet { /// Target header chain. type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. - type LaneMessageVerifier: LaneMessageVerifier; + type LaneMessageVerifier: LaneMessageVerifier< + Self::AccountId, + Self::OutboundPayload, + Self::OutboundMessageFee, + >; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< Self::AccountId, @@ -180,13 +191,15 @@ pub mod pallet { } /// Shortcut to messages proof type for Config. - type MessagesProofOf = - <>::SourceHeaderChain as SourceHeaderChain<>::InboundMessageFee>>::MessagesProof; + type MessagesProofOf = <>::SourceHeaderChain as SourceHeaderChain< + >::InboundMessageFee, + >>::MessagesProof; /// Shortcut to messages delivery proof type for Config. - type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< - >::OutboundPayload, - ::AccountId, - >>::MessagesDeliveryProof; + type MessagesDeliveryProofOf = + <>::TargetHeaderChain as TargetHeaderChain< + >::OutboundPayload, + ::AccountId, + >>::MessagesDeliveryProof; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -204,11 +217,11 @@ pub mod pallet { Some(new_owner) => { PalletOwner::::put(&new_owner); log::info!(target: "runtime::bridge-messages", "Setting pallet Owner to: {:?}", new_owner); - } + }, None => { PalletOwner::::kill(); log::info!(target: "runtime::bridge-messages", "Removed Owner of pallet."); - } + }, } Ok(()) } @@ -217,7 +230,10 @@ pub mod pallet { /// /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operating_mode(origin: OriginFor, operating_mode: OperatingMode) -> DispatchResult { + pub fn set_operating_mode( + origin: OriginFor, + operating_mode: OperatingMode, + ) -> DispatchResult { ensure_owner_or_root::(origin)?; PalletOperatingMode::::put(operating_mode); log::info!( @@ -232,9 +248,13 @@ pub mod pallet { /// /// May only be called either by root, or by `PalletOwner`. /// - /// The weight is: single read for permissions check + 2 writes for parameter value and event. + /// The weight is: single read for permissions check + 2 writes for parameter value and + /// event. #[pallet::weight((T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational))] - pub fn update_pallet_parameter(origin: OriginFor, parameter: T::Parameter) -> DispatchResult { + pub fn update_pallet_parameter( + origin: OriginFor, + parameter: T::Parameter, + ) -> DispatchResult { ensure_owner_or_root::(origin)?; parameter.save(); Self::deposit_event(Event::ParameterUpdated(parameter)); @@ -310,9 +330,9 @@ pub mod pallet { // saturating_add is fine here - overflow here means that someone controls all // chain funds, which shouldn't ever happen + `pay_delivery_and_dispatch_fee` // above will fail before we reach here - let message_data = message_data - .as_mut() - .expect("the message is sent and not yet delivered; so it is in the storage; qed"); + let message_data = message_data.as_mut().expect( + "the message is sent and not yet delivered; so it is in the storage; qed", + ); message_data.fee = message_data.fee.saturating_add(&additional_fee); message_data.payload.len() }); @@ -323,10 +343,7 @@ pub mod pallet { T::WeightInfo::increase_message_fee(message_size as _), ); - Ok(PostDispatchInfo { - actual_weight: Some(actual_weight), - pays_fee: Pays::Yes, - }) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } /// Receive messages proof from bridged chain. @@ -354,14 +371,18 @@ pub mod pallet { // why do we need to know the weight of this (`receive_messages_proof`) call? Because // we may want to return some funds for not-dispatching (or partially dispatching) some // messages to the call origin (relayer). And this is done by returning actual weight - // from the call. But we only know dispatch weight of every messages. So to refund relayer - // because we have not dispatched Message, we need to: + // from the call. But we only know dispatch weight of every messages. So to refund + // relayer because we have not dispatched Message, we need to: // // ActualWeight = DeclaredWeight - Message.DispatchWeight // // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible // to get pre-computed value (and it has been already computed by the executive). - let declared_weight = T::WeightInfo::receive_messages_proof_weight(&proof, messages_count, dispatch_weight); + let declared_weight = T::WeightInfo::receive_messages_proof_weight( + &proof, + messages_count, + dispatch_weight, + ); let mut actual_weight = declared_weight; // verify messages proof && convert proof into messages @@ -402,9 +423,9 @@ pub mod pallet { for message in lane_data.messages { debug_assert_eq!(message.key.lane_id, lane_id); - // ensure that relayer has declared enough weight for dispatching next message on - // this lane. We can't dispatch lane messages out-of-order, so if declared weight - // is not enough, let's move to next lane + // ensure that relayer has declared enough weight for dispatching next message + // on this lane. We can't dispatch lane messages out-of-order, so if declared + // weight is not enough, let's move to next lane let dispatch_weight = T::MessageDispatch::dispatch_weight(&message); if dispatch_weight > dispatch_weight_left { log::trace!( @@ -414,7 +435,7 @@ pub mod pallet { dispatch_weight, dispatch_weight_left, ); - break; + break } total_messages += 1; @@ -438,10 +459,10 @@ pub mod pallet { dispatch_result.unspent_weight, !dispatch_result.dispatch_fee_paid_during_dispatch, ) - } - ReceivalResult::InvalidNonce - | ReceivalResult::TooManyUnrewardedRelayers - | ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), + }, + ReceivalResult::InvalidNonce | + ReceivalResult::TooManyUnrewardedRelayers | + ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), }; let unspent_weight = sp_std::cmp::min(unspent_weight, dispatch_weight); @@ -468,10 +489,7 @@ pub mod pallet { declared_weight, ); - Ok(PostDispatchInfo { - actual_weight: Some(actual_weight), - pays_fee: Pays::Yes, - }) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } /// Receive messages delivery proof from bridged chain. @@ -487,74 +505,87 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { ensure_not_halted::()?; - // why do we need to know the weight of this (`receive_messages_delivery_proof`) call? Because - // we may want to return some funds for messages that are not processed by the delivery callback, - // or if their actual processing weight is less than accounted by weight formula. - // So to refund relayer, we need to: + // why do we need to know the weight of this (`receive_messages_delivery_proof`) call? + // Because we may want to return some funds for messages that are not processed by the + // delivery callback, or if their actual processing weight is less than accounted by + // weight formula. So to refund relayer, we need to: // // ActualWeight = DeclaredWeight - UnspentCallbackWeight // // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible // to get pre-computed value (and it has been already computed by the executive). - let single_message_callback_overhead = T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); - let declared_weight = - T::WeightInfo::receive_messages_delivery_proof_weight(&proof, &relayers_state, T::DbWeight::get()); + let single_message_callback_overhead = + T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); + let declared_weight = T::WeightInfo::receive_messages_delivery_proof_weight( + &proof, + &relayers_state, + T::DbWeight::get(), + ); let mut actual_weight = declared_weight; let confirmation_relayer = ensure_signed(origin)?; - let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Rejecting invalid messages delivery proof: {:?}", - err, - ); + let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof) + .map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Rejecting invalid messages delivery proof: {:?}", + err, + ); - Error::::InvalidMessagesDeliveryProof - })?; + Error::::InvalidMessagesDeliveryProof + })?; // verify that the relayer has declared correct `lane_data::relayers` state - // (we only care about total number of entries and messages, because this affects call weight) + // (we only care about total number of entries and messages, because this affects call + // weight) ensure!( - total_unrewarded_messages(&lane_data.relayers).unwrap_or(MessageNonce::MAX) - == relayers_state.total_messages - && lane_data.relayers.len() as MessageNonce == relayers_state.unrewarded_relayer_entries, + total_unrewarded_messages(&lane_data.relayers).unwrap_or(MessageNonce::MAX) == + relayers_state.total_messages && + lane_data.relayers.len() as MessageNonce == + relayers_state.unrewarded_relayer_entries, Error::::InvalidUnrewardedRelayersState ); // mark messages as delivered let mut lane = outbound_lane::(lane_id); - let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); + let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = + RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); - let confirmed_messages = - match lane.confirm_delivery(relayers_state.total_messages, last_delivered_nonce, &lane_data.relayers) { - ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => Some(confirmed_messages), - ReceivalConfirmationResult::NoNewConfirmations => None, - ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(to_confirm_messages_count) => { - log::trace!( - target: "runtime::bridge-messages", - "Messages delivery proof contains too many messages to confirm: {} vs declared {}", - to_confirm_messages_count, - relayers_state.total_messages, - ); + let confirmed_messages = match lane.confirm_delivery( + relayers_state.total_messages, + last_delivered_nonce, + &lane_data.relayers, + ) { + ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => + Some(confirmed_messages), + ReceivalConfirmationResult::NoNewConfirmations => None, + ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected( + to_confirm_messages_count, + ) => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery proof contains too many messages to confirm: {} vs declared {}", + to_confirm_messages_count, + relayers_state.total_messages, + ); - fail!(Error::::TryingToConfirmMoreMessagesThanExpected); - } - error => { - log::trace!( - target: "runtime::bridge-messages", - "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", - error, - ); + fail!(Error::::TryingToConfirmMoreMessagesThanExpected); + }, + error => { + log::trace!( + target: "runtime::bridge-messages", + "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", + error, + ); - fail!(Error::::InvalidUnrewardedRelayers); - } - }; + fail!(Error::::InvalidUnrewardedRelayers); + }, + }; if let Some(confirmed_messages) = confirmed_messages { // handle messages delivery confirmation - let preliminary_callback_overhead = relayers_state - .total_messages - .saturating_mul(single_message_callback_overhead); + let preliminary_callback_overhead = + relayers_state.total_messages.saturating_mul(single_message_callback_overhead); let actual_callback_weight = T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); match preliminary_callback_overhead.checked_sub(actual_callback_weight) { @@ -569,9 +600,12 @@ pub mod pallet { difference, ); actual_weight = actual_weight.saturating_sub(difference); - } + }, None => { - debug_assert!(false, "T::OnDeliveryConfirmed callback consumed too much weight."); + debug_assert!( + false, + "T::OnDeliveryConfirmed callback consumed too much weight." + ); log::error!( target: "runtime::bridge-messages", "T::OnDeliveryConfirmed callback has spent more weight that it is allowed to: \ @@ -579,7 +613,7 @@ pub mod pallet { preliminary_callback_overhead, actual_callback_weight, ); - } + }, } // emit 'delivered' event @@ -587,18 +621,27 @@ pub mod pallet { Self::deposit_event(Event::MessagesDelivered(lane_id, confirmed_messages)); // remember to reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain + // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the + // bridged chain for entry in lane_data.relayers { - let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); + let nonce_begin = + sp_std::cmp::max(entry.messages.begin, *received_range.start()); let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); // loop won't proceed if current entry is ahead of received range (begin > end). - // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged + // chain let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); for nonce in nonce_begin..nonce_end + 1 { - let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) - .expect("message was just confirmed; we never prune unconfirmed messages; qed"); - relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); + let message_data = OutboundMessages::::get(MessageKey { + lane_id, + nonce, + }) + .expect( + "message was just confirmed; we never prune unconfirmed messages; qed", + ); + relayer_reward.reward = + relayer_reward.reward.saturating_add(&message_data.fee); relayer_reward.messages += 1; } } @@ -606,7 +649,8 @@ pub mod pallet { // if some new messages have been confirmed, reward relayers if !relayers_rewards.is_empty() { - let relayer_fund_account = relayer_fund_account_id::(); + let relayer_fund_account = + relayer_fund_account_id::(); >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( &confirmation_relayer, relayers_rewards, @@ -621,10 +665,7 @@ pub mod pallet { lane_id, ); - Ok(PostDispatchInfo { - actual_weight: Some(actual_weight), - pays_fee: Pays::Yes, - }) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } } @@ -658,14 +699,15 @@ pub mod pallet { InvalidMessagesDeliveryProof, /// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane). InvalidUnrewardedRelayers, - /// The relayer has declared invalid unrewarded relayers state in the `receive_messages_delivery_proof` call. + /// The relayer has declared invalid unrewarded relayers state in the + /// `receive_messages_delivery_proof` call. InvalidUnrewardedRelayersState, /// The message someone is trying to work with (i.e. increase fee) is already-delivered. MessageIsAlreadyDelivered, /// The message someone is trying to work with (i.e. increase fee) is not yet sent. MessageIsNotYetSent, - /// The number of actually confirmed messages is going to be larger than the number of messages in the proof. - /// This may mean that this or bridged chain storage is corrupted. + /// The number of actually confirmed messages is going to be larger than the number of + /// messages in the proof. This may mean that this or bridged chain storage is corrupted. TryingToConfirmMoreMessagesThanExpected, } @@ -684,7 +726,8 @@ pub mod pallet { /// Depending on the mode either all, some, or no transactions will be allowed. #[pallet::storage] #[pallet::getter(fn operating_mode)] - pub type PalletOperatingMode, I: 'static = ()> = StorageValue<_, OperatingMode, ValueQuery>; + pub type PalletOperatingMode, I: 'static = ()> = + StorageValue<_, OperatingMode, ValueQuery>; /// Map of lane id => inbound lane data. #[pallet::storage] @@ -734,7 +777,10 @@ pub mod pallet { impl, I: 'static> Pallet { /// Get stored data of the outbound message with given nonce. - pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option> { + pub fn outbound_message_data( + lane: LaneId, + nonce: MessageNonce, + ) -> Option> { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } @@ -759,7 +805,9 @@ pub mod pallet { } /// Get state of unrewarded relayers set. - pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { + pub fn inbound_unrewarded_relayers_state( + lane: bp_messages::LaneId, + ) -> bp_messages::UnrewardedRelayersState { let relayers = InboundLanes::::get(&lane).relayers; bp_messages::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, @@ -804,13 +852,18 @@ pub mod storage_keys { /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending /// on the implementation it can be used to store relayers rewards. /// See [`InstantCurrencyPayments`] for a concrete implementation. -pub fn relayer_fund_account_id>() -> AccountId { +pub fn relayer_fund_account_id>( +) -> AccountId { let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); AccountIdConverter::convert(encoded_id) } -impl bp_messages::source_chain::MessagesBridge - for Pallet +impl + bp_messages::source_chain::MessagesBridge< + T::AccountId, + T::OutboundMessageFee, + T::OutboundPayload, + > for Pallet where T: Config, I: 'static, @@ -862,17 +915,23 @@ fn send_message, I: 'static>( // now let's enforce any additional lane rules let mut lane = outbound_lane::(lane_id); - T::LaneMessageVerifier::verify_message(&submitter, &delivery_and_dispatch_fee, &lane_id, &lane.data(), &payload) - .map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Message to lane {:?} is rejected by lane verifier: {:?}", - lane_id, - err, - ); + T::LaneMessageVerifier::verify_message( + &submitter, + &delivery_and_dispatch_fee, + &lane_id, + &lane.data(), + &payload, + ) + .map_err(|err| { + log::trace!( + target: "runtime::bridge-messages", + "Message to lane {:?} is rejected by lane verifier: {:?}", + lane_id, + err, + ); - Error::::MessageRejectedByLaneVerifier - })?; + Error::::MessageRejectedByLaneVerifier + })?; // let's withdraw delivery and dispatch fee from submitter T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( @@ -896,15 +955,14 @@ fn send_message, I: 'static>( // finally, save message in outbound storage and emit event let encoded_payload = payload.encode(); let encoded_payload_len = encoded_payload.len(); - let nonce = lane.send_message(MessageData { - payload: encoded_payload, - fee: delivery_and_dispatch_fee, - }); + let nonce = + lane.send_message(MessageData { payload: encoded_payload, fee: delivery_and_dispatch_fee }); // Guaranteed to be called outside only when the message is accepted. - // We assume that the maximum weight call back used is `single_message_callback_overhead`, so do not perform - // complex db operation in callback. If you want to, put these magic logic in outside pallet and control - // the weight there. - let single_message_callback_overhead = T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); + // We assume that the maximum weight call back used is `single_message_callback_overhead`, so do + // not perform complex db operation in callback. If you want to, put these magic logic in + // outside pallet and control the weight there. + let single_message_callback_overhead = + T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); let actual_callback_weight = T::OnMessageAccepted::on_messages_accepted(&lane_id, &nonce); match single_message_callback_overhead.checked_sub(actual_callback_weight) { Some(difference) if difference == 0 => (), @@ -918,7 +976,7 @@ fn send_message, I: 'static>( difference, ); actual_weight = actual_weight.saturating_sub(difference); - } + }, None => { debug_assert!(false, "T::OnMessageAccepted callback consumed too much weight."); log::error!( @@ -928,7 +986,7 @@ fn send_message, I: 'static>( single_message_callback_overhead, actual_callback_weight, ); - } + }, } // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages @@ -963,7 +1021,9 @@ fn send_message, I: 'static>( fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) if Some(signer) == Pallet::::module_owner().as_ref() => Ok(()), + Ok(RawOrigin::Signed(ref signer)) + if Some(signer) == Pallet::::module_owner().as_ref() => + Ok(()), _ => Err(BadOrigin), } } @@ -987,12 +1047,16 @@ fn ensure_not_halted, I: 'static>() -> Result<(), Error> { } /// Creates new inbound lane object, backed by runtime storage. -fn inbound_lane, I: 'static>(lane_id: LaneId) -> InboundLane> { +fn inbound_lane, I: 'static>( + lane_id: LaneId, +) -> InboundLane> { InboundLane::new(inbound_lane_storage::(lane_id)) } /// Creates new runtime inbound lane storage. -fn inbound_lane_storage, I: 'static>(lane_id: LaneId) -> RuntimeInboundLaneStorage { +fn inbound_lane_storage, I: 'static>( + lane_id: LaneId, +) -> RuntimeInboundLaneStorage { RuntimeInboundLaneStorage { lane_id, cached_data: RefCell::new(None), @@ -1001,11 +1065,10 @@ fn inbound_lane_storage, I: 'static>(lane_id: LaneId) -> RuntimeInb } /// Creates new outbound lane object, backed by runtime storage. -fn outbound_lane, I: 'static>(lane_id: LaneId) -> OutboundLane> { - OutboundLane::new(RuntimeOutboundLaneStorage { - lane_id, - _phantom: Default::default(), - }) +fn outbound_lane, I: 'static>( + lane_id: LaneId, +) -> OutboundLane> { + OutboundLane::new(RuntimeOutboundLaneStorage { lane_id, _phantom: Default::default() }) } /// Runtime inbound lane storage. @@ -1041,7 +1104,7 @@ impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage< we have no recursive borrows; qed", ) = Some(data.clone()); data - } + }, } } @@ -1077,27 +1140,19 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag #[cfg(test)] fn message(&self, nonce: &MessageNonce) -> Option> { - OutboundMessages::::get(MessageKey { - lane_id: self.lane_id, - nonce: *nonce, - }) + OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce }) } - fn save_message(&mut self, nonce: MessageNonce, mesage_data: MessageData) { - OutboundMessages::::insert( - MessageKey { - lane_id: self.lane_id, - nonce, - }, - mesage_data, - ); + fn save_message( + &mut self, + nonce: MessageNonce, + mesage_data: MessageData, + ) { + OutboundMessages::::insert(MessageKey { lane_id: self.lane_id, nonce }, mesage_data); } fn remove_message(&mut self, nonce: &MessageNonce) { - OutboundMessages::::remove(MessageKey { - lane_id: self.lane_id, - nonce: *nonce, - }); + OutboundMessages::::remove(MessageKey { lane_id: self.lane_id, nonce: *nonce }); } } @@ -1130,9 +1185,10 @@ mod tests { use super::*; use crate::mock::{ message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin, - TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, - TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, TestOnMessageAccepted, TestRuntime, TokenConversionRate, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, + TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, + TestOnMessageAccepted, TestRuntime, TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, + REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use frame_support::{assert_noop, assert_ok, weights::Weight}; @@ -1148,10 +1204,8 @@ mod tests { fn send_regular_message() -> Weight { get_ready_for_events(); - let message_nonce = outbound_lane::(TEST_LANE_ID) - .data() - .latest_generated_nonce - + 1; + let message_nonce = + outbound_lane::(TEST_LANE_ID).data().latest_generated_nonce + 1; let weight = Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, @@ -1210,7 +1264,10 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(Event::MessagesDelivered(TEST_LANE_ID, DeliveredMessages::new(1, true),)), + event: TestEvent::Messages(Event::MessagesDelivered( + TEST_LANE_ID, + DeliveredMessages::new(1, true), + )), topics: vec![], }], ); @@ -1373,7 +1430,8 @@ mod tests { // 1:1 conversion that we use by default for testnets let rialto_token = 1u64; - let rialto_token_in_millau_tokens = TokenConversionRate::get().saturating_mul_int(rialto_token); + let rialto_token_in_millau_tokens = + TokenConversionRate::get().saturating_mul_int(rialto_token); assert_eq!(rialto_token_in_millau_tokens, 1); // let's say conversion rate is 1:1.7 @@ -1431,7 +1489,9 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, - relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), }, ))), UnrewardedRelayersState { @@ -1484,7 +1544,9 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, - relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), }, ))), UnrewardedRelayersState { @@ -1524,7 +1586,12 @@ mod tests { run_test(|| { // messages with zero fee are rejected by lane verifier assert_noop!( - Pallet::::send_message(Origin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 0), + Pallet::::send_message( + Origin::signed(1), + TEST_LANE_ID, + REGULAR_PAYLOAD, + 0 + ), Error::::MessageRejectedByLaneVerifier, ); }); @@ -1587,11 +1654,10 @@ mod tests { ); // message proof includes outbound lane state with latest confirmed message updated to 9 - let mut message_proof: TestMessagesProof = Ok(vec![message(11, REGULAR_PAYLOAD)]).into(); - message_proof.result.as_mut().unwrap()[0].1.lane_state = Some(OutboundLaneData { - latest_received_nonce: 9, - ..Default::default() - }); + let mut message_proof: TestMessagesProof = + Ok(vec![message(11, REGULAR_PAYLOAD)]).into(); + message_proof.result.as_mut().unwrap()[0].1.lane_state = + Some(OutboundLaneData { latest_received_nonce: 9, ..Default::default() }); assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), @@ -1705,7 +1771,9 @@ mod tests { TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { - relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), ..Default::default() } ))), @@ -1715,16 +1783,11 @@ mod tests { ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( - TEST_RELAYER_A, - 1000 - )); - assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid( - TEST_RELAYER_B, - 2000 - )); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1000)); + assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 2000)); - // this reports delivery of both message 1 and message 2 => reward is paid only to TEST_RELAYER_B + // this reports delivery of both message 1 and message 2 => reward is paid only to + // TEST_RELAYER_B assert_ok!(Pallet::::receive_messages_delivery_proof( Origin::signed(1), TestMessagesDeliveryProof(Ok(( @@ -1745,14 +1808,8 @@ mod tests { ..Default::default() }, )); - assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid( - TEST_RELAYER_A, - 1000 - )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid( - TEST_RELAYER_B, - 2000 - )); + assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1000)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 2000)); }); } @@ -1839,10 +1896,7 @@ mod tests { 0, // weight may be zero in this case (all messages are improperly encoded) ),); - assert_eq!( - InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), - 1, - ); + assert_eq!(InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), 1,); }); } @@ -1855,27 +1909,22 @@ mod tests { assert_ok!(Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, - Ok(vec![ - message(1, REGULAR_PAYLOAD), - invalid_message, - message(3, REGULAR_PAYLOAD), - ]) + Ok( + vec![message(1, REGULAR_PAYLOAD), invalid_message, message(3, REGULAR_PAYLOAD),] + ) .into(), 3, REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight, ),); - assert_eq!( - InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), - 3, - ); + assert_eq!(InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), 3,); }); } #[test] fn storage_message_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking all - // previously crafted messages proofs. + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted messages proofs. let storage_key = storage_keys::message_key("BridgeMessages", &*b"test", 42).0; assert_eq!( storage_key, @@ -1887,8 +1936,8 @@ mod tests { #[test] fn outbound_lane_data_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking all - // previously crafted outbound lane state proofs. + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted outbound lane state proofs. let storage_key = storage_keys::outbound_lane_data_key("BridgeMessages", &*b"test").0; assert_eq!( storage_key, @@ -1900,8 +1949,8 @@ mod tests { #[test] fn inbound_lane_data_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking all - // previously crafted inbound lane state proofs. + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted inbound lane state proofs. let storage_key = storage_keys::inbound_lane_data_key("BridgeMessages", &*b"test").0; assert_eq!( storage_key, @@ -1937,7 +1986,12 @@ mod tests { receive_messages_delivery_proof(); assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Pallet::::increase_message_fee( + Origin::signed(1), + TEST_LANE_ID, + 1, + 100, + ), Error::::MessageIsAlreadyDelivered, ); }); @@ -1947,7 +2001,12 @@ mod tests { fn increase_message_fee_fails_if_message_is_not_yet_sent() { run_test(|| { assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Pallet::::increase_message_fee( + Origin::signed(1), + TEST_LANE_ID, + 1, + 100, + ), Error::::MessageIsNotYetSent, ); }); @@ -1961,7 +2020,12 @@ mod tests { TestMessageDeliveryAndDispatchPayment::reject_payments(); assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 100,), + Pallet::::increase_message_fee( + Origin::signed(1), + TEST_LANE_ID, + 1, + 100, + ), Error::::FailedToWithdrawMessageFee, ); }); @@ -1995,11 +2059,12 @@ mod tests { payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid; let proof = Ok(vec![message(nonce, payload)]).into(); let messages_count = 1; - let pre_dispatch_weight = ::WeightInfo::receive_messages_proof_weight( - &proof, - messages_count, - REGULAR_PAYLOAD.declared_weight, - ); + let pre_dispatch_weight = + ::WeightInfo::receive_messages_proof_weight( + &proof, + messages_count, + REGULAR_PAYLOAD.declared_weight, + ); let post_dispatch_weight = Pallet::::receive_messages_proof( Origin::signed(1), TEST_RELAYER_A, @@ -2023,7 +2088,8 @@ mod tests { assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight); // when dispatch is returning `unspent_weight > declared_weight` - let (pre, post) = submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false); + let (pre, post) = + submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false); assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight); // when there's no unspent weight @@ -2122,16 +2188,20 @@ mod tests { total_messages: 3, ..Default::default() }; - let pre_dispatch_weight = ::WeightInfo::receive_messages_delivery_proof_weight( - &proof, - &relayers_state, - crate::mock::DbWeight::get(), - ); - let post_dispatch_weight = - Pallet::::receive_messages_delivery_proof(Origin::signed(1), proof, relayers_state) - .expect("confirmation has failed") - .actual_weight - .expect("receive_messages_delivery_proof always returns Some"); + let pre_dispatch_weight = + ::WeightInfo::receive_messages_delivery_proof_weight( + &proof, + &relayers_state, + crate::mock::DbWeight::get(), + ); + let post_dispatch_weight = Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + proof, + relayers_state, + ) + .expect("confirmation has failed") + .actual_weight + .expect("receive_messages_delivery_proof always returns Some"); (pre_dispatch_weight, post_dispatch_weight) } @@ -2146,7 +2216,9 @@ mod tests { #[test] fn receive_messages_delivery_proof_refunds_non_zero_weight() { run_test(|| { - TestOnDeliveryConfirmed1::set_consumed_weight_per_message(crate::mock::DbWeight::get().writes(1)); + TestOnDeliveryConfirmed1::set_consumed_weight_per_message( + crate::mock::DbWeight::get().writes(1), + ); let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery(); assert_eq!( @@ -2160,13 +2232,16 @@ mod tests { #[should_panic] fn receive_messages_panics_in_debug_mode_if_callback_is_wrong() { run_test(|| { - TestOnDeliveryConfirmed1::set_consumed_weight_per_message(crate::mock::DbWeight::get().reads_writes(2, 2)); + TestOnDeliveryConfirmed1::set_consumed_weight_per_message( + crate::mock::DbWeight::get().reads_writes(2, 2), + ); confirm_3_messages_delivery() }); } #[test] - fn receive_messages_delivery_proof_rejects_proof_if_trying_to_confirm_more_messages_than_expected() { + fn receive_messages_delivery_proof_rejects_proof_if_trying_to_confirm_more_messages_than_expected( + ) { run_test(|| { // send message first to be able to check that delivery_proof fails later send_regular_message(); @@ -2182,10 +2257,7 @@ mod tests { Origin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, - InboundLaneData { - last_confirmed_nonce: 1, - relayers: Default::default(), - }, + InboundLaneData { last_confirmed_nonce: 1, relayers: Default::default() }, ))), UnrewardedRelayersState::default(), ), @@ -2215,15 +2287,17 @@ mod tests { 100, )); - let small_weight = Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1) - .expect("increase_message_fee has failed") - .actual_weight - .expect("increase_message_fee always returns Some"); + let small_weight = + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1) + .expect("increase_message_fee has failed") + .actual_weight + .expect("increase_message_fee always returns Some"); - let large_weight = Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 2, 1) - .expect("increase_message_fee has failed") - .actual_weight - .expect("increase_message_fee always returns Some"); + let large_weight = + Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 2, 1) + .expect("increase_message_fee has failed") + .actual_weight + .expect("increase_message_fee always returns Some"); assert!( large_weight > small_weight, @@ -2272,7 +2346,8 @@ mod tests { let weight_when_max_messages_are_pruned = send_regular_message(); assert_eq!( weight_when_max_messages_are_pruned, - when_zero_messages_are_pruned + crate::mock::DbWeight::get().writes(max_messages_to_prune), + when_zero_messages_are_pruned + + crate::mock::DbWeight::get().writes(max_messages_to_prune), ); }); } @@ -2289,7 +2364,9 @@ mod tests { #[should_panic] fn message_accepted_panics_in_debug_mode_if_callback_is_wrong() { run_test(|| { - TestOnMessageAccepted::set_consumed_weight_per_message(crate::mock::DbWeight::get().reads_writes(2, 2)); + TestOnMessageAccepted::set_consumed_weight_per_message( + crate::mock::DbWeight::get().reads_writes(2, 2), + ); send_regular_message(); }); } @@ -2297,14 +2374,16 @@ mod tests { #[test] fn message_accepted_refunds_non_zero_weight() { run_test(|| { - TestOnMessageAccepted::set_consumed_weight_per_message(crate::mock::DbWeight::get().writes(1)); + TestOnMessageAccepted::set_consumed_weight_per_message( + crate::mock::DbWeight::get().writes(1), + ); let actual_callback_weight = send_regular_message(); let pre_dispatch_weight = ::WeightInfo::send_message_weight( ®ULAR_PAYLOAD, crate::mock::DbWeight::get(), ); - let prune_weight = - crate::mock::DbWeight::get().writes(::MaxMessagesToPruneAtOnce::get()); + let prune_weight = crate::mock::DbWeight::get() + .writes(::MaxMessagesToPruneAtOnce::get()); assert_eq!( pre_dispatch_weight.saturating_sub(actual_callback_weight), diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 84496393d562d..330cfef4cdea0 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -22,12 +22,14 @@ use crate::Config; use bitvec::prelude::*; use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, OnMessageAccepted, - RelayersRewards, Sender, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, + OnMessageAccepted, RelayersRewards, Sender, TargetHeaderChain, }, - target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, - DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, - Parameter as MessagesParameter, UnrewardedRelayer, + target_chain::{ + DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, + }, + DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, + OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayer, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -53,8 +55,8 @@ pub struct TestPayload { pub declared_weight: Weight, /// Message dispatch result. /// - /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, but for test - /// purposes we'll be making it larger than `declared_weight` sometimes. + /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, + /// but for test purposes we'll be making it larger than `declared_weight` sometimes. pub dispatch_result: MessageDispatchResult, /// Extra bytes that affect payload size. pub extra: Vec, @@ -153,7 +155,8 @@ pub enum TestMessagesParameter { impl MessagesParameter for TestMessagesParameter { fn save(&self) { match *self { - TestMessagesParameter::TokenConversionRate(conversion_rate) => TokenConversionRate::set(&conversion_rate), + TestMessagesParameter::TokenConversionRate(conversion_rate) => + TokenConversionRate::set(&conversion_rate), } } } @@ -235,14 +238,12 @@ impl From>, ()>> for TestMessagesProof { fn from(result: Result>, ()>) -> Self { Self { result: result.map(|messages| { - let mut messages_by_lane: BTreeMap>> = - BTreeMap::new(); + let mut messages_by_lane: BTreeMap< + LaneId, + ProvedLaneMessages>, + > = BTreeMap::new(); for message in messages { - messages_by_lane - .entry(message.key.lane_id) - .or_default() - .messages - .push(message); + messages_by_lane.entry(message.key.lane_id).or_default().messages.push(message); } messages_by_lane.into_iter().collect() }), @@ -318,7 +319,8 @@ impl TestMessageDeliveryAndDispatchPayment { /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - frame_support::storage::unhashed::get(b":message-fee:") == Some((Sender::Signed(submitter), fee)) + frame_support::storage::unhashed::get(b":message-fee:") == + Some((Sender::Signed(submitter), fee)) } /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is @@ -329,7 +331,9 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { +impl MessageDeliveryAndDispatchPayment + for TestMessageDeliveryAndDispatchPayment +{ type Error = &'static str; fn pay_delivery_and_dispatch_fee( @@ -338,7 +342,7 @@ impl MessageDeliveryAndDispatchPayment for TestMessag _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) { - return Err(TEST_ERROR); + return Err(TEST_ERROR) } frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee)); @@ -382,7 +386,8 @@ impl OnMessageAccepted for TestOnMessageAccepted { fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight { let key = (b"TestOnMessageAccepted", lane, message).encode(); frame_support::storage::unhashed::put(&key, &true); - Self::get_consumed_weight_per_message().unwrap_or_else(|| DbWeight::get().reads_writes(1, 1)) + Self::get_consumed_weight_per_message() + .unwrap_or_else(|| DbWeight::get().reads_writes(1, 1)) } } @@ -451,10 +456,7 @@ impl SourceHeaderChain for TestSourceHeaderChain { proof: Self::MessagesProof, _messages_count: u32, ) -> Result>, Self::Error> { - proof - .result - .map(|proof| proof.into_iter().collect()) - .map_err(|_| TEST_ERROR) + proof.result.map(|proof| proof.into_iter().collect()).map_err(|_| TEST_ERROR) } } @@ -485,31 +487,17 @@ impl MessageDispatch for TestMessageDispatch { /// Return test lane message with given nonce and payload. pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message { - Message { - key: MessageKey { - lane_id: TEST_LANE_ID, - nonce, - }, - data: message_data(payload), - } + Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, data: message_data(payload) } } /// Constructs message payload using given arguments and zero unspent weight. pub const fn message_payload(id: u64, declared_weight: Weight) -> TestPayload { - TestPayload { - id, - declared_weight, - dispatch_result: dispatch_result(0), - extra: Vec::new(), - } + TestPayload { id, declared_weight, dispatch_result: dispatch_result(0), extra: Vec::new() } } /// Return message data with valid fee for given payload. pub fn message_data(payload: TestPayload) -> MessageData { - MessageData { - payload: payload.encode(), - fee: 1, - } + MessageData { payload: payload.encode(), fee: 1 } } /// Returns message dispatch result with given unspent weight. @@ -543,14 +531,10 @@ pub fn unrewarded_relayer( /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(ENDOWED_ACCOUNT, 1_000_000)] } + .assimilate_storage(&mut t) .unwrap(); - pallet_balances::GenesisConfig:: { - balances: vec![(ENDOWED_ACCOUNT, 1_000_000)], - } - .assimilate_storage(&mut t) - .unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(test) } diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 1962e0282a8e7..c05437596db82 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -18,7 +18,8 @@ use bitvec::prelude::*; use bp_messages::{ - DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, + DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, + UnrewardedRelayer, }; use frame_support::RuntimeDebug; use sp_std::collections::vec_deque::VecDeque; @@ -57,11 +58,11 @@ pub enum ReceivalConfirmationResult { /// The unrewarded relayers vec contains an empty entry. May be a result of invalid bridged /// chain storage. EmptyUnrewardedRelayerEntry, - /// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid bridged - /// chain storage. + /// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid + /// bridged chain storage. NonConsecutiveUnrewardedRelayerEntries, - /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May be - /// a result of invalid bridged chain storage. + /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May + /// be a result of invalid bridged chain storage. InvalidNumberOfDispatchResults, /// The chain has more messages that need to be confirmed than there is in the proof. TryingToConfirmMoreMessagesThanExpected(MessageNonce), @@ -106,27 +107,30 @@ impl OutboundLane { ) -> ReceivalConfirmationResult { let mut data = self.storage.data(); if latest_delivered_nonce <= data.latest_received_nonce { - return ReceivalConfirmationResult::NoNewConfirmations; + return ReceivalConfirmationResult::NoNewConfirmations } if latest_delivered_nonce > data.latest_generated_nonce { - return ReceivalConfirmationResult::FailedToConfirmFutureMessages; + return ReceivalConfirmationResult::FailedToConfirmFutureMessages } if latest_delivered_nonce - data.latest_received_nonce > max_allowed_messages { - // that the relayer has declared correct number of messages that the proof contains (it is - // checked outside of the function). But it may happen (but only if this/bridged chain storage is - // corrupted, though) that the actual number of confirmed messages if larger than declared. - // This would mean that 'reward loop' will take more time than the weight formula accounts, - // so we can't allow that. + // that the relayer has declared correct number of messages that the proof contains (it + // is checked outside of the function). But it may happen (but only if this/bridged + // chain storage is corrupted, though) that the actual number of confirmed messages if + // larger than declared. This would mean that 'reward loop' will take more time than the + // weight formula accounts, so we can't allow that. return ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected( latest_delivered_nonce - data.latest_received_nonce, - ); + ) } - let dispatch_results = - match extract_dispatch_results(data.latest_received_nonce, latest_delivered_nonce, relayers) { - Ok(dispatch_results) => dispatch_results, - Err(extract_error) => return extract_error, - }; + let dispatch_results = match extract_dispatch_results( + data.latest_received_nonce, + latest_delivered_nonce, + relayers, + ) { + Ok(dispatch_results) => dispatch_results, + Err(extract_error) => return extract_error, + }; let prev_latest_received_nonce = data.latest_received_nonce; data.latest_received_nonce = latest_delivered_nonce; @@ -146,7 +150,9 @@ impl OutboundLane { let mut pruned_messages = 0; let mut anything_changed = false; let mut data = self.storage.data(); - while pruned_messages < max_messages_to_prune && data.oldest_unpruned_nonce <= data.latest_received_nonce { + while pruned_messages < max_messages_to_prune && + data.oldest_unpruned_nonce <= data.latest_received_nonce + { self.storage.remove_message(&data.oldest_unpruned_nonce); anything_changed = true; @@ -171,9 +177,10 @@ fn extract_dispatch_results( latest_received_nonce: MessageNonce, relayers: &VecDeque>, ) -> Result { - // the only caller of this functions checks that the prev_latest_received_nonce..=latest_received_nonce - // is valid, so we're ready to accept messages in this range - // => with_capacity call must succeed here or we'll be unable to receive confirmations at all + // the only caller of this functions checks that the + // prev_latest_received_nonce..=latest_received_nonce is valid, so we're ready to accept + // messages in this range => with_capacity call must succeed here or we'll be unable to receive + // confirmations at all let mut received_dispatch_result = BitVec::with_capacity((latest_received_nonce - prev_latest_received_nonce + 1) as _); let mut last_entry_end: Option = None; @@ -181,43 +188,48 @@ fn extract_dispatch_results( // unrewarded relayer entry must have at least 1 unconfirmed message // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end < entry.messages.begin { - return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry); + return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry) } // every entry must confirm range of messages that follows previous entry range // (guaranteed by the `InboundLane::receive_message()`) if let Some(last_entry_end) = last_entry_end { let expected_entry_begin = last_entry_end.checked_add(1); if expected_entry_begin != Some(entry.messages.begin) { - return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries); + return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries) } } last_entry_end = Some(entry.messages.end); // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { - // technically this will be detected in the next loop iteration as `InvalidNumberOfDispatchResults` - // but to guarantee safety of loop operations below this is detected now - return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages); + // technically this will be detected in the next loop iteration as + // `InvalidNumberOfDispatchResults` but to guarantee safety of loop operations below + // this is detected now + return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages) } // entry must have single dispatch result for every message // (guaranteed by the `InboundLane::receive_message()`) - if entry.messages.dispatch_results.len() as MessageNonce != entry.messages.end - entry.messages.begin + 1 { - return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults); + if entry.messages.dispatch_results.len() as MessageNonce != + entry.messages.end - entry.messages.begin + 1 + { + return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults) } // now we know that the entry is valid // => let's check if it brings new confirmations - let new_messages_begin = sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1); + let new_messages_begin = + sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1); let new_messages_end = sp_std::cmp::min(entry.messages.end, latest_received_nonce); let new_messages_range = new_messages_begin..=new_messages_end; if new_messages_range.is_empty() { - continue; + continue } // now we know that entry brings new confirmations // => let's extract dispatch results received_dispatch_result.extend_from_bitslice( - &entry.messages.dispatch_results[(new_messages_begin - entry.messages.begin) as usize..], + &entry.messages.dispatch_results + [(new_messages_begin - entry.messages.begin) as usize..], ); } @@ -228,12 +240,17 @@ fn extract_dispatch_results( mod tests { use super::*; use crate::{ - mock::{message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID}, + mock::{ + message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD, + TEST_LANE_ID, + }, outbound_lane, }; use sp_std::ops::RangeInclusive; - fn unrewarded_relayers(nonces: RangeInclusive) -> VecDeque> { + fn unrewarded_relayers( + nonces: RangeInclusive, + ) -> VecDeque> { vec![unrewarded_relayer(*nonces.start(), *nonces.end(), 0)] .into_iter() .collect() diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 297b03cfc17bb..fef09c6cebe57 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -25,8 +25,8 @@ use frame_support::weights::{RuntimeDbWeight, Weight}; /// Size of the message being delivered in benchmarks. pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128; -/// We assume that size of signed extensions on all our chains and size of all 'small' arguments of calls -/// we're checking here would fit 1KB. +/// We assume that size of signed extensions on all our chains and size of all 'small' arguments of +/// calls we're checking here would fit 1KB. const SIGNED_EXTENSIONS_SIZE: u32 = 1024; /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at @@ -54,12 +54,15 @@ pub fn ensure_weights_are_correct( // verify that the hardcoded value covers `receive_messages_proof` weight let actual_single_regular_message_delivery_tx_weight = W::receive_messages_proof_weight( - &PreComputedSize((EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize), + &PreComputedSize( + (EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize, + ), 1, 0, ); assert!( - actual_single_regular_message_delivery_tx_weight <= expected_default_message_delivery_tx_weight, + actual_single_regular_message_delivery_tx_weight <= + expected_default_message_delivery_tx_weight, "Default message delivery transaction weight {} is larger than expected weight {}", actual_single_regular_message_delivery_tx_weight, expected_default_message_delivery_tx_weight, @@ -91,7 +94,8 @@ pub fn ensure_weights_are_correct( db_weight, ); assert!( - actual_messages_delivery_confirmation_tx_weight <= expected_messages_delivery_confirmation_tx_weight, + actual_messages_delivery_confirmation_tx_weight <= + expected_messages_delivery_confirmation_tx_weight, "Messages delivery confirmation transaction weight {} is larger than expected weight {}", actual_messages_delivery_confirmation_tx_weight, expected_messages_delivery_confirmation_tx_weight, @@ -115,7 +119,8 @@ pub fn ensure_able_to_receive_message( max_incoming_message_dispatch_weight: Weight, ) { // verify that we're able to receive proof of maximal-size message - let max_delivery_transaction_size = max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE); + let max_delivery_transaction_size = + max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE); assert!( max_delivery_transaction_size <= max_extrinsic_size, "Size of maximal message delivery transaction {} + {} is larger than maximal possible transaction size {}", @@ -126,7 +131,9 @@ pub fn ensure_able_to_receive_message( // verify that we're able to receive proof of maximal-size message with maximal dispatch weight let max_delivery_transaction_dispatch_weight = W::receive_messages_proof_weight( - &PreComputedSize((max_incoming_message_proof_size + W::expected_extra_storage_proof_size()) as usize), + &PreComputedSize( + (max_incoming_message_proof_size + W::expected_extra_storage_proof_size()) as usize, + ), 1, max_incoming_message_dispatch_weight, ); @@ -158,7 +165,8 @@ pub fn ensure_able_to_receive_confirmation( max_extrinsic_size, ); - // verify that we're able to reward maximal number of relayers that have delivered maximal number of messages + // verify that we're able to reward maximal number of relayers that have delivered maximal + // number of messages let max_confirmation_transaction_dispatch_weight = W::receive_messages_delivery_proof_weight( &PreComputedSize(max_inbound_lane_data_proof_size_from_peer_chain as usize), &UnrewardedRelayersState { @@ -200,10 +208,15 @@ pub trait WeightInfoExt: WeightInfo { } /// Weight of message delivery extrinsic. - fn receive_messages_proof_weight(proof: &impl Size, messages_count: u32, dispatch_weight: Weight) -> Weight { + fn receive_messages_proof_weight( + proof: &impl Size, + messages_count: u32, + dispatch_weight: Weight, + ) -> Weight { // basic components of extrinsic weight let transaction_overhead = Self::receive_messages_proof_overhead(); - let outbound_state_delivery_weight = Self::receive_messages_proof_outbound_lane_state_overhead(); + let outbound_state_delivery_weight = + Self::receive_messages_proof_outbound_lane_state_overhead(); let messages_delivery_weight = Self::receive_messages_proof_messages_overhead(MessageNonce::from(messages_count)); let messages_dispatch_weight = dispatch_weight; @@ -213,8 +226,9 @@ pub trait WeightInfoExt: WeightInfo { .saturating_mul(messages_count.saturating_sub(1)) .saturating_add(Self::expected_extra_storage_proof_size()); let actual_proof_size = proof.size_hint(); - let proof_size_overhead = - Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size)); + let proof_size_overhead = Self::storage_proof_size_overhead( + actual_proof_size.saturating_sub(expected_proof_size), + ); transaction_overhead .saturating_add(outbound_state_delivery_weight) @@ -231,17 +245,21 @@ pub trait WeightInfoExt: WeightInfo { ) -> Weight { // basic components of extrinsic weight let transaction_overhead = Self::receive_messages_delivery_proof_overhead(); - let messages_overhead = Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages); - let relayers_overhead = - Self::receive_messages_delivery_proof_relayers_overhead(relayers_state.unrewarded_relayer_entries); + let messages_overhead = + Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages); + let relayers_overhead = Self::receive_messages_delivery_proof_relayers_overhead( + relayers_state.unrewarded_relayer_entries, + ); // proof size overhead weight let expected_proof_size = Self::expected_extra_storage_proof_size(); let actual_proof_size = proof.size_hint(); - let proof_size_overhead = - Self::storage_proof_size_overhead(actual_proof_size.saturating_sub(expected_proof_size)); + let proof_size_overhead = Self::storage_proof_size_overhead( + actual_proof_size.saturating_sub(expected_proof_size), + ); - // and cost of calling `OnDeliveryConfirmed::on_messages_delivered()` for every confirmed message + // and cost of calling `OnDeliveryConfirmed::on_messages_delivered()` for every confirmed + // message let callback_overhead = relayers_state .total_messages .saturating_mul(Self::single_message_callback_overhead(db_weight)); @@ -260,22 +278,26 @@ pub trait WeightInfoExt: WeightInfo { Self::send_minimal_message_worst_case() } - /// Returns weight that needs to be accounted when message of given size is sent (`send_message`). + /// Returns weight that needs to be accounted when message of given size is sent + /// (`send_message`). fn send_message_size_overhead(message_size: u32) -> Weight { let message_size_in_kb = (1024u64 + message_size as u64) / 1024; - let single_kb_weight = (Self::send_16_kb_message_worst_case() - Self::send_1_kb_message_worst_case()) / 15; + let single_kb_weight = + (Self::send_16_kb_message_worst_case() - Self::send_1_kb_message_worst_case()) / 15; message_size_in_kb * single_kb_weight } /// Returns weight overhead of message delivery transaction (`receive_messages_proof`). fn receive_messages_proof_overhead() -> Weight { - let weight_of_two_messages_and_two_tx_overheads = Self::receive_single_message_proof().saturating_mul(2); + let weight_of_two_messages_and_two_tx_overheads = + Self::receive_single_message_proof().saturating_mul(2); let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof(); - weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead) + weight_of_two_messages_and_two_tx_overheads + .saturating_sub(weight_of_two_messages_and_single_tx_overhead) } - /// Returns weight that needs to be accounted when receiving given a number of messages with message - /// delivery transaction (`receive_messages_proof`). + /// Returns weight that needs to be accounted when receiving given a number of messages with + /// message delivery transaction (`receive_messages_proof`). fn receive_messages_proof_messages_overhead(messages: MessageNonce) -> Weight { let weight_of_two_messages_and_single_tx_overhead = Self::receive_two_messages_proof(); let weight_of_single_message_and_single_tx_overhead = Self::receive_single_message_proof(); @@ -284,27 +306,31 @@ pub trait WeightInfoExt: WeightInfo { .saturating_mul(messages as Weight) } - /// Returns weight that needs to be accounted when message delivery transaction (`receive_messages_proof`) - /// is carrying outbound lane state proof. + /// Returns weight that needs to be accounted when message delivery transaction + /// (`receive_messages_proof`) is carrying outbound lane state proof. fn receive_messages_proof_outbound_lane_state_overhead() -> Weight { - let weight_of_single_message_and_lane_state = Self::receive_single_message_proof_with_outbound_lane_state(); + let weight_of_single_message_and_lane_state = + Self::receive_single_message_proof_with_outbound_lane_state(); let weight_of_single_message = Self::receive_single_message_proof(); weight_of_single_message_and_lane_state.saturating_sub(weight_of_single_message) } - /// Returns weight overhead of delivery confirmation transaction (`receive_messages_delivery_proof`). + /// Returns weight overhead of delivery confirmation transaction + /// (`receive_messages_delivery_proof`). fn receive_messages_delivery_proof_overhead() -> Weight { let weight_of_two_messages_and_two_tx_overheads = Self::receive_delivery_proof_for_single_message().saturating_mul(2); let weight_of_two_messages_and_single_tx_overhead = Self::receive_delivery_proof_for_two_messages_by_single_relayer(); - weight_of_two_messages_and_two_tx_overheads.saturating_sub(weight_of_two_messages_and_single_tx_overhead) + weight_of_two_messages_and_two_tx_overheads + .saturating_sub(weight_of_two_messages_and_single_tx_overhead) } /// Returns weight that needs to be accounted when receiving confirmations for given a number of /// messages with delivery confirmation transaction (`receive_messages_delivery_proof`). fn receive_messages_delivery_proof_messages_overhead(messages: MessageNonce) -> Weight { - let weight_of_two_messages = Self::receive_delivery_proof_for_two_messages_by_single_relayer(); + let weight_of_two_messages = + Self::receive_delivery_proof_for_two_messages_by_single_relayer(); let weight_of_single_message = Self::receive_delivery_proof_for_single_message(); weight_of_two_messages .saturating_sub(weight_of_single_message) @@ -314,7 +340,8 @@ pub trait WeightInfoExt: WeightInfo { /// Returns weight that needs to be accounted when receiving confirmations for given a number of /// relayers entries with delivery confirmation transaction (`receive_messages_delivery_proof`). fn receive_messages_delivery_proof_relayers_overhead(relayers: MessageNonce) -> Weight { - let weight_of_two_messages_by_two_relayers = Self::receive_delivery_proof_for_two_messages_by_two_relayers(); + let weight_of_two_messages_by_two_relayers = + Self::receive_delivery_proof_for_two_messages_by_two_relayers(); let weight_of_two_messages_by_single_relayer = Self::receive_delivery_proof_for_two_messages_by_single_relayer(); weight_of_two_messages_by_two_relayers @@ -322,8 +349,8 @@ pub trait WeightInfoExt: WeightInfo { .saturating_mul(relayers as Weight) } - /// Returns weight that needs to be accounted when storage proof of given size is received (either in - /// `receive_messages_proof` or `receive_messages_delivery_proof`). + /// Returns weight that needs to be accounted when storage proof of given size is received + /// (either in `receive_messages_proof` or `receive_messages_delivery_proof`). /// /// **IMPORTANT**: this overhead is already included in the 'base' transaction cost - e.g. proof /// size depends on messages count or number of entries in the unrewarded relayers set. So this @@ -332,23 +359,26 @@ pub trait WeightInfoExt: WeightInfo { /// is less than that cost). fn storage_proof_size_overhead(proof_size: u32) -> Weight { let proof_size_in_bytes = proof_size as Weight; - let byte_weight = - (Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024); + let byte_weight = (Self::receive_single_message_proof_16_kb() - + Self::receive_single_message_proof_1_kb()) / + (15 * 1024); proof_size_in_bytes * byte_weight } /// Returns weight of the pay-dispatch-fee operation for inbound messages. /// - /// This function may return zero if runtime doesn't support pay-dispatch-fee-at-target-chain option. + /// This function may return zero if runtime doesn't support pay-dispatch-fee-at-target-chain + /// option. fn pay_inbound_dispatch_fee_overhead() -> Weight { - Self::receive_single_message_proof().saturating_sub(Self::receive_single_prepaid_message_proof()) + Self::receive_single_message_proof() + .saturating_sub(Self::receive_single_prepaid_message_proof()) } /// Returns pre-dispatch weight of single callback call. /// /// When benchmarking the weight please take into consideration both the `OnMessageAccepted` and - /// `OnDeliveryConfirmed` callbacks. The method should return the greater of the two, because it's - /// used to estimate the weight in both contexts. + /// `OnDeliveryConfirmed` callbacks. The method should return the greater of the two, because + /// it's used to estimate the weight in both contexts. fn single_message_callback_overhead(db_weight: RuntimeDbWeight) -> Weight { db_weight.reads_writes(1, 1) } diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 011b50ad595dd..511cbaa1cbeb6 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -54,7 +54,7 @@ impl pallet_session::SessionManager for Pallet { fn new_session(session_index: sp_staking::SessionIndex) -> Option> { // we don't want to add even more fields to genesis config => just return None if session_index == 0 || session_index == 1 { - return None; + return None } // the idea that on first call (i.e. when session 1 ends) we're reading current @@ -101,13 +101,17 @@ mod tests { #![allow(clippy::from_over_into)] use super::*; - use frame_support::sp_io::TestExternalities; - use frame_support::sp_runtime::{ - testing::{Header, UintAuthorityId}, - traits::{BlakeTwo256, ConvertInto, IdentityLookup}, - Perbill, RuntimeAppPublic, + use frame_support::{ + parameter_types, + sp_io::TestExternalities, + sp_runtime::{ + testing::{Header, UintAuthorityId}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, + Perbill, RuntimeAppPublic, + }, + weights::Weight, + BasicExternalities, }; - use frame_support::{parameter_types, weights::Weight, BasicExternalities}; use sp_core::H256; type AccountId = u64; @@ -183,17 +187,21 @@ mod tests { impl pallet_session::SessionHandler for TestSessionHandler { const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; - fn on_genesis_session(_validators: &[(AccountId, Ks)]) {} + fn on_genesis_session(_validators: &[(AccountId, Ks)]) { + } - fn on_new_session(_: bool, _: &[(AccountId, Ks)], _: &[(AccountId, Ks)]) {} + fn on_new_session( + _: bool, + _: &[(AccountId, Ks)], + _: &[(AccountId, Ks)], + ) { + } fn on_disabled(_: usize) {} } fn new_test_ext() -> TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); let keys = vec![ (1, 1, UintAuthorityId(1)), diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 5528a25296d50..9469df3aaceeb 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -22,29 +22,30 @@ //! //! There are four accounts participating in the swap: //! -//! 1) account of This chain that has signed the `create_swap` transaction and has balance on This chain. -//! We'll be referring to this account as `source_account_at_this_chain`; -//! 2) account of the Bridged chain that is sending the `claim_swap` message from the Bridged to This chain. -//! This account has balance on Bridged chain and is willing to swap these tokens to This chain tokens of -//! the `source_account_at_this_chain`. We'll be referring to this account as `target_account_at_bridged_chain`; -//! 3) account of the Bridged chain that is indirectly controlled by the `source_account_at_this_chain`. We'll be -//! referring this account as `source_account_at_bridged_chain`; -//! 4) account of This chain that is indirectly controlled by the `target_account_at_bridged_chain`. We'll be -//! referring this account as `target_account_at_this_chain`. +//! 1) account of This chain that has signed the `create_swap` transaction and has balance on This +//! chain. We'll be referring to this account as `source_account_at_this_chain`; +//! 2) account of the Bridged chain that is sending the `claim_swap` message from the Bridged to +//! This chain. This account has balance on Bridged chain and is willing to swap these tokens to +//! This chain tokens of the `source_account_at_this_chain`. We'll be referring to this account +//! as `target_account_at_bridged_chain`; 3) account of the Bridged chain that is indirectly +//! controlled by the `source_account_at_this_chain`. We'll be referring this account as +//! `source_account_at_bridged_chain`; 4) account of This chain that is indirectly controlled by the +//! `target_account_at_bridged_chain`. We'll be referring this account as +//! `target_account_at_this_chain`. //! -//! So the tokens swap is an intention of `source_account_at_this_chain` to swap his `source_balance_at_this_chain` -//! tokens to the `target_balance_at_bridged_chain` tokens owned by `target_account_at_bridged_chain`. The swap -//! process goes as follows: +//! So the tokens swap is an intention of `source_account_at_this_chain` to swap his +//! `source_balance_at_this_chain` tokens to the `target_balance_at_bridged_chain` tokens owned by +//! `target_account_at_bridged_chain`. The swap process goes as follows: //! -//! 1) the `source_account_at_this_chain` account submits the `create_swap` transaction on This chain; -//! 2) the tokens transfer message that would transfer `target_balance_at_bridged_chain` tokens from the -//! `target_account_at_bridged_chain` to the `source_account_at_bridged_chain`, is sent over the bridge; -//! 3) when transfer message is delivered and dispatched, the pallet receives notification; -//! 4) if message has been successfully dispatched, the `target_account_at_bridged_chain` sends the message -//! that would transfer `source_balance_at_this_chain` tokens to his `target_account_at_this_chain` -//! account; -//! 5) if message dispatch has failed, the `source_account_at_this_chain` may submit the `cancel_swap` -//! transaction and return his `source_balance_at_this_chain` back to his account. +//! 1) the `source_account_at_this_chain` account submits the `create_swap` transaction on This +//! chain; 2) the tokens transfer message that would transfer `target_balance_at_bridged_chain` +//! tokens from the `target_account_at_bridged_chain` to the `source_account_at_bridged_chain`, +//! is sent over the bridge; 3) when transfer message is delivered and dispatched, the pallet +//! receives notification; 4) if message has been successfully dispatched, the +//! `target_account_at_bridged_chain` sends the message that would transfer +//! `source_balance_at_this_chain` tokens to his `target_account_at_this_chain` account; +//! 5) if message dispatch has failed, the `source_account_at_this_chain` may submit the +//! `cancel_swap` transaction and return his `source_balance_at_this_chain` back to his account. //! //! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special //! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion. @@ -118,8 +119,9 @@ pub mod pallet { } /// Tokens balance at This chain. - pub type ThisChainBalance = - <>::ThisCurrency as Currency<::AccountId>>::Balance; + pub type ThisChainBalance = <>::ThisCurrency as Currency< + ::AccountId, + >>::Balance; /// Type of the Bridged chain. pub type BridgedChainOf = >::BridgedChain; @@ -164,33 +166,40 @@ pub mod pallet { { /// Start token swap procedure. /// - /// The dispatch origin for this call must be exactly the `swap.source_account_at_this_chain` account. + /// The dispatch origin for this call must be exactly the + /// `swap.source_account_at_this_chain` account. /// /// Method arguments are: /// /// - `swap` - token swap intention; - /// - `target_public_at_bridged_chain` - the public key of the `swap.target_account_at_bridged_chain` - /// account used to verify `bridged_currency_transfer_signature`; - /// - `bridged_currency_transfer` - the SCALE-encoded tokens transfer call at the Bridged chain; - /// - `bridged_currency_transfer_signature` - the signature of the `swap.target_account_at_bridged_chain` - /// for the message returned by the `pallet_bridge_dispatch::account_ownership_digest()` function call. + /// - `target_public_at_bridged_chain` - the public key of the + /// `swap.target_account_at_bridged_chain` account used to verify + /// `bridged_currency_transfer_signature`; + /// - `bridged_currency_transfer` - the SCALE-encoded tokens transfer call at the Bridged + /// chain; + /// - `bridged_currency_transfer_signature` - the signature of the + /// `swap.target_account_at_bridged_chain` for the message returned by the + /// `pallet_bridge_dispatch::account_ownership_digest()` function call. /// - /// The `source_account_at_this_chain` MUST have enough balance to cover both token swap and message - /// transfer. Message fee may be estimated using corresponding `OutboundLaneApi` of This runtime. + /// The `source_account_at_this_chain` MUST have enough balance to cover both token swap and + /// message transfer. Message fee may be estimated using corresponding `OutboundLaneApi` of + /// This runtime. /// /// **WARNING**: the submitter of this transaction is responsible for verifying: /// - /// 1) that the `bridged_currency_transfer` represents a valid token transfer call that transfers - /// `swap.target_balance_at_bridged_chain` to his `source_account_at_bridged_chain` account; - /// 2) that either the `source_account_at_bridged_chain` already exists, or the - /// `swap.target_balance_at_bridged_chain` is above existential deposit of the Bridged chain; - /// 3) the `target_public_at_bridged_chain` matches the `swap.target_account_at_bridged_chain`; - /// 4) the `bridged_currency_transfer_signature` is valid and generated by the owner of the - /// `target_public_at_bridged_chain` account (read more about [`CallOrigin::TargetAccount`]). + /// 1) that the `bridged_currency_transfer` represents a valid token transfer call that + /// transfers `swap.target_balance_at_bridged_chain` to his + /// `source_account_at_bridged_chain` account; 2) that either the + /// `source_account_at_bridged_chain` already exists, or the + /// `swap.target_balance_at_bridged_chain` is above existential deposit of the Bridged + /// chain; 3) the `target_public_at_bridged_chain` matches the + /// `swap.target_account_at_bridged_chain`; 4) the `bridged_currency_transfer_signature` is + /// valid and generated by the owner of the `target_public_at_bridged_chain` account + /// (read more about [`CallOrigin::TargetAccount`]). /// - /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. Violating other - /// rules will lead to losing message fees for this and other transactions + losing fees for message - /// transfer. + /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. + /// Violating other rules will lead to losing message fees for this and other transactions + + /// losing fees for message transfer. #[pallet::weight(0)] #[allow(clippy::too_many_arguments)] pub fn create_swap( @@ -203,7 +212,8 @@ pub mod pallet { bridged_currency_transfer_weight: Weight, bridged_currency_transfer_signature: BridgedAccountSignatureOf, ) -> DispatchResultWithPostInfo { - // ensure that the `origin` is the same account that is mentioned in the `swap` intention + // ensure that the `origin` is the same account that is mentioned in the `swap` + // intention let origin_account = ensure_signed(origin)?; ensure!( origin_account == swap.source_account_at_this_chain, @@ -221,8 +231,8 @@ pub mod pallet { Error::::TooLowBalanceOnThisChain, ); - // if the swap is replay-protected, then we need to ensure that we have not yet passed the - // specified block yet + // if the swap is replay-protected, then we need to ensure that we have not yet passed + // the specified block yet match swap.swap_type { TokenSwapType::TemporaryTargetAccountAtBridgedChain => (), TokenSwapType::LockClaimUntilBlock(block_number, _) => ensure!( @@ -237,7 +247,8 @@ pub mod pallet { let transfer_result = T::ThisCurrency::transfer( &swap.source_account_at_this_chain, &swap_account, - // saturating_add is ok, or we have the chain where single holder owns all tokens + // saturating_add is ok, or we have the chain where single holder owns all + // tokens swap.source_balance_at_this_chain .saturating_add(swap_delivery_and_dispatch_fee), // if we'll allow account to die, then he'll be unable to `cancel_claim` @@ -254,8 +265,8 @@ pub mod pallet { ); return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferToSwapAccount.into() - )); + Error::::FailedToTransferToSwapAccount.into(), + )) } // the transfer message is sent over the bridge. The message is supposed to be a @@ -289,20 +300,21 @@ pub mod pallet { return sp_runtime::TransactionOutcome::Rollback(Err( Error::::FailedToSendTransferMessage.into(), - )); - } + )) + }, }; // remember that we have started the swap let swap_hash = swap.using_encoded(blake2_256).into(); - let insert_swap_result = PendingSwaps::::try_mutate(swap_hash, |maybe_state| { - if maybe_state.is_some() { - return Err(()); - } - - *maybe_state = Some(TokenSwapState::Started); - Ok(()) - }); + let insert_swap_result = + PendingSwaps::::try_mutate(swap_hash, |maybe_state| { + if maybe_state.is_some() { + return Err(()) + } + + *maybe_state = Some(TokenSwapState::Started); + Ok(()) + }); if insert_swap_result.is_err() { log::error!( target: "runtime::bridge-token-swap", @@ -310,7 +322,9 @@ pub mod pallet { swap, ); - return sp_runtime::TransactionOutcome::Rollback(Err(Error::::SwapAlreadyStarted.into())); + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::SwapAlreadyStarted.into(), + )) } log::trace!( @@ -330,21 +344,23 @@ pub mod pallet { }) } - /// Claim previously reserved `source_balance_at_this_chain` by `target_account_at_this_chain`. + /// Claim previously reserved `source_balance_at_this_chain` by + /// `target_account_at_this_chain`. /// - /// **WARNING**: the correct way to call this function is to call it over the messages bridge with - /// dispatch origin set to `pallet_bridge_dispatch::CallOrigin::SourceAccount(target_account_at_bridged_chain)`. + /// **WARNING**: the correct way to call this function is to call it over the messages + /// bridge with dispatch origin set to + /// `pallet_bridge_dispatch::CallOrigin::SourceAccount(target_account_at_bridged_chain)`. /// /// This should be called only when successful transfer confirmation has been received. #[pallet::weight(0)] - pub fn claim_swap(origin: OriginFor, swap: TokenSwapOf) -> DispatchResultWithPostInfo { + pub fn claim_swap( + origin: OriginFor, + swap: TokenSwapOf, + ) -> DispatchResultWithPostInfo { // ensure that the `origin` is controlled by the `swap.target_account_at_bridged_chain` let origin_account = ensure_signed(origin)?; let target_account_at_this_chain = target_account_at_this_chain::(&swap); - ensure!( - origin_account == target_account_at_this_chain, - Error::::InvalidClaimant, - ); + ensure!(origin_account == target_account_at_this_chain, Error::::InvalidClaimant,); // ensure that the swap is confirmed let swap_hash = swap.using_encoded(blake2_256).into(); @@ -354,13 +370,12 @@ pub mod pallet { Some(TokenSwapState::Confirmed) => { let is_claim_allowed = match swap.swap_type { TokenSwapType::TemporaryTargetAccountAtBridgedChain => true, - TokenSwapType::LockClaimUntilBlock(block_number, _) => { - block_number < frame_system::Pallet::::block_number() - } + TokenSwapType::LockClaimUntilBlock(block_number, _) => + block_number < frame_system::Pallet::::block_number(), }; ensure!(is_claim_allowed, Error::::SwapIsTemporaryLocked); - } + }, Some(TokenSwapState::Failed) => fail!(Error::::SwapIsFailed), None => fail!(Error::::SwapIsInactive), } @@ -368,13 +383,18 @@ pub mod pallet { complete_claim::(swap, swap_hash, origin_account, Event::SwapClaimed(swap_hash)) } - /// Return previously reserved `source_balance_at_this_chain` back to the `source_account_at_this_chain`. + /// Return previously reserved `source_balance_at_this_chain` back to the + /// `source_account_at_this_chain`. /// - /// This should be called only when transfer has failed at Bridged chain and we have received - /// notification about that. + /// This should be called only when transfer has failed at Bridged chain and we have + /// received notification about that. #[pallet::weight(0)] - pub fn cancel_swap(origin: OriginFor, swap: TokenSwapOf) -> DispatchResultWithPostInfo { - // ensure that the `origin` is the same account that is mentioned in the `swap` intention + pub fn cancel_swap( + origin: OriginFor, + swap: TokenSwapOf, + ) -> DispatchResultWithPostInfo { + // ensure that the `origin` is the same account that is mentioned in the `swap` + // intention let origin_account = ensure_signed(origin)?; ensure!( origin_account == swap.source_account_at_this_chain, @@ -388,9 +408,10 @@ pub mod pallet { Some(TokenSwapState::Started) => fail!(Error::::SwapIsPending), Some(TokenSwapState::Confirmed) => fail!(Error::::SwapIsConfirmed), Some(TokenSwapState::Failed) => { - // we allow canceling swap even before lock period is over - the `source_account_at_this_chain` - // has already paid for nothing and it is up to him to decide whether he want to try again - } + // we allow canceling swap even before lock period is over - the + // `source_account_at_this_chain` has already paid for nothing and it is up to + // him to decide whether he want to try again + }, None => fail!(Error::::SwapIsInactive), } @@ -413,13 +434,15 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// The account that has submitted the `start_claim` doesn't match the `TokenSwap::source_account_at_this_chain`. + /// The account that has submitted the `start_claim` doesn't match the + /// `TokenSwap::source_account_at_this_chain`. MismatchedSwapSourceOrigin, /// The swap balance in This chain tokens is below existential deposit and can't be made. TooLowBalanceOnThisChain, /// Transfer from This chain account to temporary Swap account has failed. FailedToTransferToSwapAccount, - /// Transfer from the temporary Swap account to the derived account of Bridged account has failed. + /// Transfer from the temporary Swap account to the derived account of Bridged account has + /// failed. FailedToTransferFromSwapAccount, /// The message to transfer tokens on Target chain can't be sent. FailedToSendTransferMessage, @@ -431,17 +454,18 @@ pub mod pallet { SwapIsFailed, /// Claiming swap is not allowed. /// - /// Now the only possible case when you may get this error, is when you're trying to claim swap with - /// `TokenSwapType::LockClaimUntilBlock` before lock period is over. + /// Now the only possible case when you may get this error, is when you're trying to claim + /// swap with `TokenSwapType::LockClaimUntilBlock` before lock period is over. SwapIsTemporaryLocked, /// Swap period is finished and you can not restart it. /// - /// Now the only possible case when you may get this error, is when you're trying to start swap with - /// `TokenSwapType::LockClaimUntilBlock` after lock period is over. + /// Now the only possible case when you may get this error, is when you're trying to start + /// swap with `TokenSwapType::LockClaimUntilBlock` after lock period is over. SwapPeriodIsFinished, /// Someone is trying to cancel swap that has been confirmed. SwapIsConfirmed, - /// Someone is trying to claim/cancel swap that is either not started or already claimed/canceled. + /// Someone is trying to claim/cancel swap that is either not started or already + /// claimed/canceled. SwapIsInactive, /// The swap claimant is invalid. InvalidClaimant, @@ -449,17 +473,19 @@ pub mod pallet { /// Pending token swaps states. #[pallet::storage] - pub type PendingSwaps, I: 'static = ()> = StorageMap<_, Identity, H256, TokenSwapState>; + pub type PendingSwaps, I: 'static = ()> = + StorageMap<_, Identity, H256, TokenSwapState>; /// Pending transfer messages. #[pallet::storage] - pub type PendingMessages, I: 'static = ()> = StorageMap<_, Identity, MessageNonce, H256>; + pub type PendingMessages, I: 'static = ()> = + StorageMap<_, Identity, MessageNonce, H256>; impl, I: 'static> OnDeliveryConfirmed for Pallet { fn on_messages_delivered(lane: &LaneId, delivered_messages: &DeliveredMessages) -> Weight { // we're only interested in our lane messages if *lane != T::OutboundMessageLaneId::get() { - return 0; + return 0 } // so now we're dealing with our lane messages. Ideally we'll have dedicated lane @@ -472,11 +498,12 @@ pub mod pallet { if let Some(swap_hash) = PendingMessages::::take(message_nonce) { writes += 1; - let token_swap_state = if delivered_messages.message_dispatch_result(message_nonce) { - TokenSwapState::Confirmed - } else { - TokenSwapState::Failed - }; + let token_swap_state = + if delivered_messages.message_dispatch_result(message_nonce) { + TokenSwapState::Confirmed + } else { + TokenSwapState::Failed + }; log::trace!( target: "runtime::bridge-token-swap", @@ -494,12 +521,16 @@ pub mod pallet { } /// Returns temporary account id used to lock funds during swap on This chain. - pub(crate) fn swap_account_id, I: 'static>(swap: &TokenSwapOf) -> T::AccountId { + pub(crate) fn swap_account_id, I: 'static>( + swap: &TokenSwapOf, + ) -> T::AccountId { T::FromSwapToThisAccountIdConverter::convert(swap.using_encoded(blake2_256).into()) } /// Expected target account representation on This chain (aka `target_account_at_this_chain`). - pub(crate) fn target_account_at_this_chain, I: 'static>(swap: &TokenSwapOf) -> T::AccountId { + pub(crate) fn target_account_at_this_chain, I: 'static>( + swap: &TokenSwapOf, + ) -> T::AccountId { T::FromBridgedToThisAccountIdConverter::convert(bp_runtime::derive_account_id( T::BridgedChainId::get(), bp_runtime::SourceAccount::Account(swap.target_account_at_bridged_chain.clone()), @@ -533,8 +564,8 @@ pub mod pallet { ); return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferFromSwapAccount.into() - )); + Error::::FailedToTransferFromSwapAccount.into(), + )) } log::trace!( @@ -786,20 +817,21 @@ mod tests { )); let swap_hash = test_swap_hash(); - assert_eq!( - PendingSwaps::::get(swap_hash), - Some(TokenSwapState::Started) - ); + assert_eq!(PendingSwaps::::get(swap_hash), Some(TokenSwapState::Started)); assert_eq!(PendingMessages::::get(MESSAGE_NONCE), Some(swap_hash)); assert_eq!( - pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), + pallet_balances::Pallet::::free_balance(&swap_account_id::< + TestRuntime, + (), + >(&test_swap())), test_swap().source_balance_at_this_chain + SWAP_DELIVERY_AND_DISPATCH_FEE, ); assert!( - frame_system::Pallet::::events() - .iter() - .any(|e| e.event - == crate::mock::Event::TokenSwap(crate::Event::SwapStarted(swap_hash, MESSAGE_NONCE,))), + frame_system::Pallet::::events().iter().any(|e| e.event == + crate::mock::Event::TokenSwap(crate::Event::SwapStarted( + swap_hash, + MESSAGE_NONCE, + ))), "Missing SwapStarted event: {:?}", frame_system::Pallet::::events(), ); @@ -811,7 +843,9 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed(1 + target_account_at_this_chain::(&test_swap())), + Origin::signed( + 1 + target_account_at_this_chain::(&test_swap()) + ), test_swap(), ), Error::::InvalidClaimant @@ -913,19 +947,21 @@ mod tests { let swap_hash = test_swap_hash(); assert_eq!(PendingSwaps::::get(swap_hash), None); assert_eq!( - pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), + pallet_balances::Pallet::::free_balance(&swap_account_id::< + TestRuntime, + (), + >(&test_swap())), 0, ); assert_eq!( - pallet_balances::Pallet::::free_balance(&target_account_at_this_chain::( - &test_swap() - ),), + pallet_balances::Pallet::::free_balance( + &target_account_at_this_chain::(&test_swap()), + ), test_swap().source_balance_at_this_chain, ); assert!( - frame_system::Pallet::::events() - .iter() - .any(|e| e.event == crate::mock::Event::TokenSwap(crate::Event::SwapClaimed(swap_hash,))), + frame_system::Pallet::::events().iter().any(|e| e.event == + crate::mock::Event::TokenSwap(crate::Event::SwapClaimed(swap_hash,))), "Missing SwapClaimed event: {:?}", frame_system::Pallet::::events(), ); @@ -939,7 +975,10 @@ mod tests { receive_test_swap_confirmation(false); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap()), + Pallet::::cancel_swap( + Origin::signed(THIS_CHAIN_ACCOUNT + 1), + test_swap() + ), Error::::MismatchedSwapSourceOrigin ); }); @@ -1014,7 +1053,10 @@ mod tests { let swap_hash = test_swap_hash(); assert_eq!(PendingSwaps::::get(swap_hash), None); assert_eq!( - pallet_balances::Pallet::::free_balance(&swap_account_id::(&test_swap())), + pallet_balances::Pallet::::free_balance(&swap_account_id::< + TestRuntime, + (), + >(&test_swap())), 0, ); assert_eq!( @@ -1022,9 +1064,8 @@ mod tests { THIS_CHAIN_ACCOUNT_BALANCE - SWAP_DELIVERY_AND_DISPATCH_FEE, ); assert!( - frame_system::Pallet::::events() - .iter() - .any(|e| e.event == crate::mock::Event::TokenSwap(crate::Event::SwapCanceled(swap_hash,))), + frame_system::Pallet::::events().iter().any(|e| e.event == + crate::mock::Event::TokenSwap(crate::Event::SwapCanceled(swap_hash,))), "Missing SwapCanceled event: {:?}", frame_system::Pallet::::events(), ); @@ -1047,7 +1088,10 @@ mod tests { // when unrelated messages are delivered let mut messages = DeliveredMessages::new(MESSAGE_NONCE - 2, true); messages.note_dispatched_message(false); - Pallet::::on_messages_delivered(&OutboundMessageLaneId::get(), &messages); + Pallet::::on_messages_delivered( + &OutboundMessageLaneId::get(), + &messages, + ); assert_eq!( PendingMessages::::get(MESSAGE_NONCE), Some(test_swap_hash()) @@ -1061,7 +1105,10 @@ mod tests { let mut messages = DeliveredMessages::new(MESSAGE_NONCE - 1, false); messages.note_dispatched_message(true); messages.note_dispatched_message(false); - Pallet::::on_messages_delivered(&OutboundMessageLaneId::get(), &messages); + Pallet::::on_messages_delivered( + &OutboundMessageLaneId::get(), + &messages, + ); assert_eq!(PendingMessages::::get(MESSAGE_NONCE), None); assert_eq!( PendingSwaps::::get(test_swap_hash()), diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index ed5c1b7cee316..16894d9850ba0 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -172,9 +172,7 @@ impl sp_runtime::traits::Convert for TestAccountConverter { /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(THIS_CHAIN_ACCOUNT, THIS_CHAIN_ACCOUNT_BALANCE)], } diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index f4c448e41c60f..9a6eb66d22865 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -21,7 +21,9 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; +use frame_support::weights::{ + WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, +}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -83,29 +85,36 @@ pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; /// Name of the DOT->KSM conversion rate stored in the Kusama runtime. -pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = "PolkadotToKusamaConversionRate"; +pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = + "PolkadotToKusamaConversionRate"; /// Name of the `KusamaFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; /// Name of the `KusamaFinalityApi::is_known_header` runtime method. pub const IS_KNOWN_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_is_known_header"; -/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; /// Name of the `ToKusamaOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD: &str = "ToKusamaOutboundLaneApi_latest_generated_nonce"; +pub const TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD: &str = + "ToKusamaOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToKusamaOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = "ToKusamaOutboundLaneApi_latest_received_nonce"; +pub const TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToKusamaOutboundLaneApi_latest_received_nonce"; /// Name of the `FromKusamaInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = "FromKusamaInboundLaneApi_latest_received_nonce"; +pub const FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromKusamaInboundLaneApi_latest_received_nonce"; /// Name of the `FromKusamaInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromKusamaInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromKusamaInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromKusamaInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = "FromKusamaInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = + "FromKusamaInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Kusama headers. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index e43e4f4bf5bd9..950c82d5224bb 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -30,9 +30,8 @@ use frame_support::{ }; use frame_system::limits; use sp_core::Hasher as HasherT; -use sp_runtime::traits::Convert; use sp_runtime::{ - traits::{IdentifyAccount, Verify}, + traits::{Convert, IdentifyAccount, Verify}, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -77,29 +76,32 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; /// Weight of single regular message delivery transaction on Millau chain. /// /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. -/// The message must have dispatch weight set to zero. The result then must be rounded up to account -/// possible future runtime upgrades. +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` +/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be +/// rounded up to account possible future runtime upgrades. pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// Increase of delivery transaction weight on Millau chain with every additional message byte. /// -/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The -/// result then must be rounded up to account possible future runtime upgrades. +/// This value is a result of +/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then +/// must be rounded up to account possible future runtime upgrades. pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Millau chain. /// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula computation -/// for the case when single message is confirmed. The result then must be rounded up to account possible future -/// runtime upgrades. +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` +/// weight formula computation for the case when single message is confirmed. The result then must +/// be rounded up to account possible future runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; /// Weight of pay-dispatch-fee operation for inbound messages at Millau chain. /// -/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` -/// call for your chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +/// This value corresponds to the result of +/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your +/// chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery +/// transactions cheaper. pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; /// The target length of a session (how often authorities change) on Millau measured in of number of @@ -264,22 +266,28 @@ pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; -/// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; /// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; +pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToMillauOutboundLaneApi_latest_received_nonce"; /// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_generated_nonce"; +pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = + "ToMillauOutboundLaneApi_latest_generated_nonce"; /// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_received_nonce"; +pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromMillauInboundLaneApi_latest_received_nonce"; /// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromMillauInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = + "FromMillauInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Millau headers. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index d32165e6b79e3..26bad1ea8656d 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -21,7 +21,9 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; +use frame_support::weights::{ + WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, +}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -72,8 +74,8 @@ pub const TRANSACTION_BYTE_FEE: Balance = 10 * 10_000_000_000 / 100 / 1_000; /// Existential deposit on Polkadot. pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; -/// The target length of a session (how often authorities change) on Polkadot measured in of number of -/// blocks. +/// The target length of a session (how often authorities change) on Polkadot measured in of number +/// of blocks. /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. @@ -83,29 +85,36 @@ pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; /// Name of the KSM->DOT conversion rate stored in the Polkadot runtime. -pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = "KusamaToPolkadotConversionRate"; +pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = + "KusamaToPolkadotConversionRate"; /// Name of the `PolkadotFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; /// Name of the `PolkadotFinalityApi::is_known_header` runtime method. pub const IS_KNOWN_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_is_known_header"; -/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; /// Name of the `ToPolkadotOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD: &str = "ToPolkadotOutboundLaneApi_latest_generated_nonce"; +pub const TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD: &str = + "ToPolkadotOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToPolkadotOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = "ToPolkadotOutboundLaneApi_latest_received_nonce"; +pub const TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToPolkadotOutboundLaneApi_latest_received_nonce"; /// Name of the `FromPolkadotInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = "FromPolkadotInboundLaneApi_latest_received_nonce"; +pub const FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromPolkadotInboundLaneApi_latest_received_nonce"; /// Name of the `FromPolkadotInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromPolkadotInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromPolkadotInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromPolkadotInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_POLKADOT_UNREWARDED_RELAYERS_STATE: &str = "FromPolkadotInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_POLKADOT_UNREWARDED_RELAYERS_STATE: &str = + "FromPolkadotInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Polkadot headers. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 6ab3431e459e6..1ded7651cceca 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -68,29 +68,32 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; /// Weight of single regular message delivery transaction on Rialto chain. /// /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. -/// The message must have dispatch weight set to zero. The result then must be rounded up to account -/// possible future runtime upgrades. +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` +/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be +/// rounded up to account possible future runtime upgrades. pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// Increase of delivery transaction weight on Rialto chain with every additional message byte. /// -/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The -/// result then must be rounded up to account possible future runtime upgrades. +/// This value is a result of +/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then +/// must be rounded up to account possible future runtime upgrades. pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; /// Maximal weight of single message delivery confirmation transaction on Rialto chain. /// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula computation -/// for the case when single message is confirmed. The result then must be rounded up to account possible future -/// runtime upgrades. +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` +/// weight formula computation for the case when single message is confirmed. The result then must +/// be rounded up to account possible future runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; /// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. /// -/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` -/// call for your chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +/// This value corresponds to the result of +/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your +/// chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery +/// transactions cheaper. pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; /// The target length of a session (how often authorities change) on Rialto measured in of number of @@ -231,22 +234,28 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the `RialtoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_finalized"; -/// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; /// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_generated_nonce"; +pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = + "ToRialtoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; +pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToRialtoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_received_nonce"; +pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromRialtoInboundLaneApi_latest_received_nonce"; /// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromRialtoInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = + "FromRialtoInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Rialto headers. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index ce58e7ec9ab02..d6d97fdc5f4ef 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -21,7 +21,9 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use frame_support::weights::{Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; +use frame_support::weights::{ + Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, +}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -30,8 +32,8 @@ pub use bp_polkadot_core::*; /// Rococo Chain pub type Rococo = PolkadotLike; -/// The target length of a session (how often authorities change) on Westend measured in of number of -/// blocks. +/// The target length of a session (how often authorities change) on Westend measured in of number +/// of blocks. /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. @@ -80,28 +82,36 @@ pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_fi /// Name of the `RococoFinalityApi::is_known_header` runtime method. pub const IS_KNOWN_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_is_known_header"; -/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; /// Name of the `ToRococoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToRococoOutboundLaneApi_latest_generated_nonce"; +pub const TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD: &str = + "ToRococoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToRococoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRococoOutboundLaneApi_latest_received_nonce"; +pub const TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToRococoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromRococoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromRococoInboundLaneApi_latest_received_nonce"; +pub const FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromRococoInboundLaneApi_latest_received_nonce"; /// Name of the `FromRococoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRococoInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromRococoInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromRococoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromRococoInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = + "FromRococoInboundLaneApi_unrewarded_relayers_state"; /// Weight of pay-dispatch-fee operation for inbound messages at Rococo chain. /// -/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` -/// call for your chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +/// This value corresponds to the result of +/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your +/// chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery +/// transactions cheaper. pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; sp_api::decl_runtime_apis! { diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 0f430774307a5..480a5e56dd4c8 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -22,7 +22,9 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use bp_runtime::Chain; -use frame_support::weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; +use frame_support::weights::{ + WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, +}; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -114,25 +116,31 @@ pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_ /// Name of the `WestendFinalityApi::is_known_header` runtime method. pub const IS_KNOWN_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_is_known_header"; -/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_WESTEND_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToWestendOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToWestendOutboundLaneApi::message_details` runtime method. pub const TO_WESTEND_MESSAGE_DETAILS_METHOD: &str = "ToWestendOutboundLaneApi_message_details"; /// Name of the `ToWestendOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_WESTEND_LATEST_GENERATED_NONCE_METHOD: &str = "ToWestendOutboundLaneApi_latest_generated_nonce"; +pub const TO_WESTEND_LATEST_GENERATED_NONCE_METHOD: &str = + "ToWestendOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToWestendOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = "ToWestendOutboundLaneApi_latest_received_nonce"; +pub const TO_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToWestendOutboundLaneApi_latest_received_nonce"; /// Name of the `FromWestendInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = "FromWestendInboundLaneApi_latest_received_nonce"; +pub const FROM_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromWestendInboundLaneApi_latest_received_nonce"; /// Name of the `FromWestendInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_WESTEND_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWestendInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_WESTEND_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromWestendInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromWestendInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_WESTEND_UNREWARDED_RELAYERS_STATE: &str = "FromWestendInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_WESTEND_UNREWARDED_RELAYERS_STATE: &str = + "FromWestendInboundLaneApi_unrewarded_relayers_state"; -/// The target length of a session (how often authorities change) on Westend measured in of number of -/// blocks. +/// The target length of a session (how often authorities change) on Westend measured in of number +/// of blocks. /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index f962973d6c1c8..fe2ce3a309a6b 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -45,22 +45,28 @@ pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_fi /// Name of the `WococoFinalityApi::is_known_header` runtime method. pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_header"; -/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime method. +/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime +/// method. pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; /// Name of the `ToWococoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_generated_nonce"; +pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = + "ToWococoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_received_nonce"; +pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = + "ToWococoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromWococoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_received_nonce"; +pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = + "FromWococoInboundLaneApi_latest_received_nonce"; /// Name of the `FromWococoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_confirmed_nonce"; +pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = + "FromWococoInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromWococoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromWococoInboundLaneApi_unrewarded_relayers_state"; +pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = + "FromWococoInboundLaneApi_unrewarded_relayers_state"; sp_api::decl_runtime_apis! { /// API for querying information about the finalized Wococo headers. diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index c85a9d4ff7d2b..a3bdbbb2f42fb 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -71,7 +71,9 @@ pub trait MaybeLockFundsTransaction { /// Parse lock funds transaction of the peer blockchain. Returns None if /// transaction format is unknown, or it isn't a lock funds transaction. - fn parse(tx: &Self::Transaction) -> Result>; + fn parse( + tx: &Self::Transaction, + ) -> Result>; } /// Map that maps recipients from peer blockchain to this blockchain recipients. diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index 657038a25f33b..c63cf2b8f65c9 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -185,10 +185,7 @@ pub struct SealedEmptyStep { impl AuraHeader { /// Compute id of this header. pub fn compute_id(&self) -> HeaderId { - HeaderId { - number: self.number, - hash: self.compute_hash(), - } + HeaderId { number: self.number, hash: self.compute_hash() } } /// Compute hash of this header (keccak of the RLP with seal). @@ -198,10 +195,9 @@ impl AuraHeader { /// Get id of this header' parent. Returns None if this is genesis header. pub fn parent_id(&self) -> Option { - self.number.checked_sub(1).map(|parent_number| HeaderId { - number: parent_number, - hash: self.parent_hash, - }) + self.number + .checked_sub(1) + .map(|parent_number| HeaderId { number: parent_number, hash: self.parent_hash }) } /// Check if passed transactions receipts are matching receipts root in this header. @@ -238,7 +234,7 @@ impl AuraHeader { let mut message = self.compute_hash().as_bytes().to_vec(); message.extend_from_slice(self.seal.get(2)?); keccak_256(&message).into() - } + }, false => keccak_256(&self.rlp(false)).into(), }) } @@ -255,9 +251,7 @@ impl AuraHeader { /// Extracts the empty steps from the header seal. pub fn empty_steps(&self) -> Option> { - self.seal - .get(2) - .and_then(|x| Rlp::new(x).as_list::().ok()) + self.seal.get(2).and_then(|x| Rlp::new(x).as_list::().ok()) } /// Returns header RLP with or without seals. @@ -368,15 +362,15 @@ impl Receipt { match self.outcome { TransactionOutcome::Unknown => { s.begin_list(3); - } + }, TransactionOutcome::StateRoot(ref root) => { s.begin_list(4); s.append(root); - } + }, TransactionOutcome::StatusCode(ref status_code) => { s.begin_list(4); s.append(status_code); - } + }, } s.append(&self.gas_used); s.append(&EthBloom::from(self.log_bloom.0)); @@ -428,13 +422,13 @@ impl Decodable for SealedEmptyStep { impl LogEntry { /// Calculates the bloom of this log entry. pub fn bloom(&self) -> Bloom { - let eth_bloom = - self.topics - .iter() - .fold(EthBloom::from(BloomInput::Raw(self.address.as_bytes())), |mut b, t| { - b.accrue(BloomInput::Raw(t.as_bytes())); - b - }); + let eth_bloom = self.topics.iter().fold( + EthBloom::from(BloomInput::Raw(self.address.as_bytes())), + |mut b, t| { + b.accrue(BloomInput::Raw(t.as_bytes())); + b + }, + ); Bloom(*eth_bloom.data()) } } @@ -498,14 +492,12 @@ pub fn transaction_decode_rlp(raw_tx: &[u8]) -> Result Address { /// Check ethereum merkle proof. /// Returns Ok(computed-root) if check succeeds. /// Returns Err(computed-root) if check fails. -fn check_merkle_proof>(expected_root: H256, items: impl Iterator) -> Result { +fn check_merkle_proof>( + expected_root: H256, + items: impl Iterator, +) -> Result { let computed_root = compute_merkle_root(items); if computed_root == expected_root { Ok(computed_root) diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs index a4e076f2200c6..aaa5a980b2e20 100644 --- a/primitives/ethereum-poa/src/signatures.rs +++ b/primitives/ethereum-poa/src/signatures.rs @@ -23,8 +23,8 @@ pub use secp256k1::SecretKey; use crate::{ - public_to_address, rlp_encode, step_validator, Address, AuraHeader, RawTransaction, UnsignedTransaction, H256, - H520, U256, + public_to_address, rlp_encode, step_validator, Address, AuraHeader, RawTransaction, + UnsignedTransaction, H256, H520, U256, }; use secp256k1::{Message, PublicKey}; @@ -80,7 +80,8 @@ impl SignTransaction for UnsignedTransaction { /// Return author's signature over given message. pub fn sign(author: &SecretKey, message: H256) -> H520 { - let (signature, recovery_id) = secp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); + let (signature, recovery_id) = + secp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); let mut raw_signature = [0u8; 65]; raw_signature[..64].copy_from_slice(&signature.serialize()); raw_signature[64] = recovery_id.serialize(); @@ -116,10 +117,7 @@ mod tests { let raw_tx = unsigned.clone().sign_by(&signer, Some(42)); assert_eq!( transaction_decode_rlp(&raw_tx), - Ok(Transaction { - sender: signer_address, - unsigned, - }), + Ok(Transaction { sender: signer_address, unsigned }), ); // case2: without chain_id replay protection + contract creation @@ -134,10 +132,7 @@ mod tests { let raw_tx = unsigned.clone().sign_by(&signer, None); assert_eq!( transaction_decode_rlp(&raw_tx), - Ok(Transaction { - sender: signer_address, - unsigned, - }), + Ok(Transaction { sender: signer_address, unsigned }), ); } } diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 760369fe0d870..2d092496e8d54 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -24,8 +24,10 @@ use finality_grandpa::voter_set::VoterSet; use frame_support::RuntimeDebug; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::traits::Header as HeaderT; -use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet}; -use sp_std::prelude::*; +use sp_std::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + prelude::*, +}; /// A GRANDPA Justification is a proof that a given header was finalized /// at a certain height and with a certain set of authorities. @@ -37,7 +39,8 @@ pub struct GrandpaJustification { /// The round (voting period) this justification is valid for. pub round: u64, /// The set of votes for the chain which is to be finalized. - pub commit: finality_grandpa::Commit, + pub commit: + finality_grandpa::Commit, /// A proof that the chain of blocks in the commit are related to each other. pub votes_ancestries: Vec
, } @@ -57,7 +60,8 @@ pub enum Error { InvalidJustificationTarget, /// The authority has provided an invalid signature. InvalidAuthoritySignature, - /// The justification contains precommit for header that is not a descendant of the commit header. + /// The justification contains precommit for header that is not a descendant of the commit + /// header. PrecommitIsNotCommitDescendant, /// The cumulative weight of all votes in the justification is not enough to justify commit /// header finalization. @@ -87,7 +91,7 @@ where { // ensure that it is justification for the expected header if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { - return Err(Error::InvalidJustificationTarget); + return Err(Error::InvalidJustificationTarget) } let mut chain = AncestryChain::new(&justification.votes_ancestries); @@ -99,30 +103,32 @@ where let authority_info = match authorities_set.get(&signed.id) { Some(authority_info) => authority_info, None => { - // just ignore precommit from unknown authority as `finality_grandpa::import_precommit` does - continue; - } + // just ignore precommit from unknown authority as + // `finality_grandpa::import_precommit` does + continue + }, }; // check if authority has already voted in the same round. // // there's a lot of code in `validate_commit` and `import_precommit` functions inside - // `finality-grandpa` crate (mostly related to reporing equivocations). But the only thing that we - // care about is that only first vote from the authority is accepted + // `finality-grandpa` crate (mostly related to reporing equivocations). But the only thing + // that we care about is that only first vote from the authority is accepted if !votes.insert(signed.id.clone()) { - continue; + continue } // everything below this line can't just `continue`, because state is already altered // all precommits must be for block higher than the target if signed.precommit.target_number < justification.commit.target_number { - return Err(Error::PrecommitIsNotCommitDescendant); + return Err(Error::PrecommitIsNotCommitDescendant) } // all precommits must be for target block descendents - chain = chain.ensure_descendant(&justification.commit.target_hash, &signed.precommit.target_hash)?; - // since we know now that the precommit target is the descendant of the justification target, - // we may increase 'weight' of the justification target + chain = chain + .ensure_descendant(&justification.commit.target_hash, &signed.precommit.target_hash)?; + // since we know now that the precommit target is the descendant of the justification + // target, we may increase 'weight' of the justification target // // there's a lot of code in the `VoteGraph::insert` method inside `finality-grandpa` crate, // but in the end it is only used to find GHOST, which we don't care about. The only thing @@ -144,13 +150,13 @@ where authorities_set_id, &mut signature_buffer, ) { - return Err(Error::InvalidAuthoritySignature); + return Err(Error::InvalidAuthoritySignature) } } // check that there are no extra headers in the justification if !chain.unvisited.is_empty() { - return Err(Error::ExtraHeadersInVotesAncestries); + return Err(Error::ExtraHeadersInVotesAncestries) } // check that the cumulative weight of validators voted for the justification target (or one @@ -186,7 +192,8 @@ impl AncestryChain
{ AncestryChain { parents, unvisited } } - /// Returns `Err(_)` if `precommit_target` is a descendant of the `commit_target` block and `Ok(_)` otherwise. + /// Returns `Err(_)` if `precommit_target` is a descendant of the `commit_target` block and + /// `Ok(_)` otherwise. pub fn ensure_descendant( mut self, commit_target: &Header::Hash, @@ -195,22 +202,22 @@ impl AncestryChain
{ let mut current_hash = *precommit_target; loop { if current_hash == *commit_target { - break; + break } let is_visited_before = !self.unvisited.remove(¤t_hash); current_hash = match self.parents.get(¤t_hash) { Some(parent_hash) => { if is_visited_before { - // `Some(parent_hash)` means that the `current_hash` is in the `parents` container - // `is_visited_before` means that it has been visited before in some of previous calls - // => since we assume that previous call has finished with `true`, this also will - // be finished with `true` - return Ok(self); + // `Some(parent_hash)` means that the `current_hash` is in the `parents` + // container `is_visited_before` means that it has been visited before in + // some of previous calls => since we assume that previous call has finished + // with `true`, this also will be finished with `true` + return Ok(self) } *parent_hash - } + }, None => return Err(Error::PrecommitIsNotCommitDescendant), }; } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index f1eaa28d071f0..66dd42e148298 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -20,15 +20,11 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Codec, Decode, Encode, EncodeLike}; -use core::clone::Clone; -use core::cmp::Eq; -use core::default::Default; -use core::fmt::Debug; +use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; -use sp_runtime::RuntimeDebug; -use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT}; +use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT, RuntimeDebug}; use sp_std::boxed::Box; pub mod justification; @@ -82,7 +78,9 @@ pub trait InclusionProofVerifier { /// Verify that transaction is a part of given block. /// /// Returns Some(transaction) if proof is valid and None otherwise. - fn verify_transaction_inclusion_proof(proof: &Self::TransactionInclusionProof) -> Option; + fn verify_transaction_inclusion_proof( + proof: &Self::TransactionInclusionProof, + ) -> Option; } /// A trait for pallets which want to keep track of finalized headers from a bridged chain. diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index 0b55c19035287..51275bbd645e5 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -23,8 +23,8 @@ use assert_matches::assert_matches; use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; use bp_test_utils::{ - header_id, make_justification_for_header, signed_precommit, test_header, Account, JustificationGeneratorParams, - ALICE, BOB, CHARLIE, DAVE, EVE, TEST_GRANDPA_SET_ID, + header_id, make_justification_for_header, signed_precommit, test_header, Account, + JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, TEST_GRANDPA_SET_ID, }; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; @@ -44,18 +44,22 @@ impl AncestryChain { } impl finality_grandpa::Chain for AncestryChain { - fn ancestry(&self, base: TestHash, block: TestHash) -> Result, finality_grandpa::Error> { + fn ancestry( + &self, + base: TestHash, + block: TestHash, + ) -> Result, finality_grandpa::Error> { let mut route = Vec::new(); let mut current_hash = block; loop { if current_hash == base { - break; + break } match self.0.parents.get(¤t_hash).cloned() { Some(parent_hash) => { current_hash = parent_hash; route.push(current_hash); - } + }, _ => return Err(finality_grandpa::Error::NotDescendent), } } @@ -81,14 +85,11 @@ fn minimal_accounts_set() -> Vec<(Account, AuthorityWeight)> { vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1)] } -/// Get a minimal subset of GRANDPA authorities that have enough cumulative vote weight to justify a header finality. +/// Get a minimal subset of GRANDPA authorities that have enough cumulative vote weight to justify a +/// header finality. pub fn minimal_voter_set() -> VoterSet { - VoterSet::new( - minimal_accounts_set() - .iter() - .map(|(id, w)| (AuthorityId::from(*id), *w)), - ) - .unwrap() + VoterSet::new(minimal_accounts_set().iter().map(|(id, w)| (AuthorityId::from(*id), *w))) + .unwrap() } /// Make a valid GRANDPA justification with sensible defaults. @@ -174,14 +175,8 @@ fn same_result_when_justification_contains_duplicate_vote() { let mut justification = make_default_justification(&test_header(1)); // the justification may contain exactly the same vote (i.e. same precommit and same signature) // multiple times && it isn't treated as an error by original implementation - justification - .commit - .precommits - .push(justification.commit.precommits[0].clone()); - justification - .commit - .precommits - .push(justification.commit.precommits[0].clone()); + justification.commit.precommits.push(justification.commit.precommits[0].clone()); + justification.commit.precommits.push(justification.commit.precommits[0].clone()); // our implementation succeeds assert_eq!( diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 794091c789194..5f39197b11751 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -112,7 +112,12 @@ pub enum CallOrigin { +pub struct MessagePayload< + SourceChainAccountId, + TargetChainAccountPublic, + TargetChainSignature, + Call, +> { /// Runtime specification version. We only dispatch messages that have the same /// runtime version. Otherwise we risk to misinterpret encoded calls. pub spec_version: SpecVersion, diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index f639cea933a0b..3cf07f6be9a02 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -110,22 +110,23 @@ pub struct Message { /// Inbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct InboundLaneData { - /// Identifiers of relayers and messages that they have delivered to this lane (ordered by message nonce). + /// Identifiers of relayers and messages that they have delivered to this lane (ordered by + /// message nonce). /// /// This serves as a helper storage item, to allow the source chain to easily pay rewards /// to the relayers who successfully delivered messages to the target chain (inbound lane). /// /// It is guaranteed to have at most N entries, where N is configured at the module level. /// If there are N entries in this vec, then: - /// 1) all incoming messages are rejected if they're missing corresponding `proof-of(outbound-lane.state)`; - /// 2) all incoming messages are rejected if `proof-of(outbound-lane.state).last_delivered_nonce` is - /// equal to `self.last_confirmed_nonce`. - /// Given what is said above, all nonces in this queue are in range: - /// `(self.last_confirmed_nonce; self.last_delivered_nonce()]`. + /// 1) all incoming messages are rejected if they're missing corresponding + /// `proof-of(outbound-lane.state)`; 2) all incoming messages are rejected if + /// `proof-of(outbound-lane.state).last_delivered_nonce` is equal to + /// `self.last_confirmed_nonce`. Given what is said above, all nonces in this queue are in + /// range: `(self.last_confirmed_nonce; self.last_delivered_nonce()]`. /// /// When a relayer sends a single message, both of MessageNonces are the same. - /// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the highest nonce. - /// Multiple dispatches from the same relayer are allowed. + /// When relayer sends messages in a batch, the first arg is the lowest nonce, second arg the + /// highest nonce. Multiple dispatches from the same relayer are allowed. pub relayers: VecDeque>, /// Nonce of the last message that @@ -141,10 +142,7 @@ pub struct InboundLaneData { impl Default for InboundLaneData { fn default() -> Self { - InboundLaneData { - relayers: VecDeque::new(), - last_confirmed_nonce: 0, - } + InboundLaneData { relayers: VecDeque::new(), last_confirmed_nonce: 0 } } } @@ -153,12 +151,17 @@ impl InboundLaneData { /// size of each entry. /// /// Returns `None` if size overflows `u32` limits. - pub fn encoded_size_hint(relayer_id_encoded_size: u32, relayers_entries: u32, messages_count: u32) -> Option { + pub fn encoded_size_hint( + relayer_id_encoded_size: u32, + relayers_entries: u32, + messages_count: u32, + ) -> Option { let message_nonce_size = 8; let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; let dispatch_results_per_byte = 8; - let dispatch_result_size = sp_std::cmp::max(relayers_entries, messages_count / dispatch_results_per_byte); + let dispatch_result_size = + sp_std::cmp::max(relayers_entries, messages_count / dispatch_results_per_byte); relayers_size .checked_add(message_nonce_size) .and_then(|result| result.checked_add(dispatch_result_size)) @@ -193,8 +196,8 @@ pub type DispatchResultsBitVec = BitVec; /// Unrewarded relayer entry stored in the inbound lane data. /// -/// This struct represents a continuous range of messages that have been delivered by the same relayer -/// and whose confirmations are still pending. +/// This struct represents a continuous range of messages that have been delivered by the same +/// relayer and whose confirmations are still pending. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct UnrewardedRelayer { /// Identifier of the relayer. @@ -217,7 +220,8 @@ pub struct DeliveredMessages { } impl DeliveredMessages { - /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given dispatch result. + /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given + /// dispatch result. pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { DeliveredMessages { begin: nonce, @@ -277,8 +281,8 @@ pub struct UnrewardedRelayersState { /// Outbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] pub struct OutboundLaneData { - /// Nonce of the oldest message that we haven't yet pruned. May point to not-yet-generated message if - /// all sent messages are already pruned. + /// Nonce of the oldest message that we haven't yet pruned. May point to not-yet-generated + /// message if all sent messages are already pruned. pub oldest_unpruned_nonce: MessageNonce, /// Nonce of the latest message, received by bridged chain. pub latest_received_nonce: MessageNonce, @@ -289,7 +293,8 @@ pub struct OutboundLaneData { impl Default for OutboundLaneData { fn default() -> Self { OutboundLaneData { - // it is 1 because we're pruning everything in [oldest_unpruned_nonce; latest_received_nonce] + // it is 1 because we're pruning everything in [oldest_unpruned_nonce; + // latest_received_nonce] oldest_unpruned_nonce: 1, latest_received_nonce: 0, latest_generated_nonce: 0, @@ -300,7 +305,9 @@ impl Default for OutboundLaneData { /// Returns total number of messages in the `InboundLaneData::relayers` vector. /// /// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`). -pub fn total_unrewarded_messages(relayers: &VecDeque>) -> Option { +pub fn total_unrewarded_messages( + relayers: &VecDeque>, +) -> Option { match (relayers.front(), relayers.back()) { (Some(front), Some(back)) => { if let Some(difference) = back.messages.end.checked_sub(front.messages.begin) { @@ -308,7 +315,7 @@ pub fn total_unrewarded_messages(relayers: &VecDeque Some(0), } } @@ -322,10 +329,7 @@ mod tests { assert_eq!( total_unrewarded_messages( &vec![ - UnrewardedRelayer { - relayer: 1, - messages: DeliveredMessages::new(0, true) - }, + UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0, true) }, UnrewardedRelayer { relayer: 2, messages: DeliveredMessages::new(MessageNonce::MAX, true) @@ -349,7 +353,11 @@ mod tests { (13u8, 128u8), ]; for (relayer_entries, messages_count) in test_cases { - let expected_size = InboundLaneData::::encoded_size_hint(1, relayer_entries as _, messages_count as _); + let expected_size = InboundLaneData::::encoded_size_hint( + 1, + relayer_entries as _, + messages_count as _, + ); let actual_size = InboundLaneData { relayers: (1u8..=relayer_entries) .map(|i| { @@ -383,11 +391,8 @@ mod tests { #[test] fn message_dispatch_result_works() { - let delivered_messages = DeliveredMessages { - begin: 100, - end: 150, - dispatch_results: bitvec![Msb0, u8; 1; 151], - }; + let delivered_messages = + DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![Msb0, u8; 1; 151] }; assert!(!delivered_messages.contains_message(99)); assert!(delivered_messages.contains_message(100)); diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 326ab4f0f8ccb..dbe6a5922158d 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -81,7 +81,8 @@ pub trait LaneMessageVerifier { /// Error type. type Error: Debug + Into<&'static str>; - /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the lane. + /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the + /// lane. fn verify_message( submitter: &Sender, delivery_and_dispatch_fee: &Fee, @@ -190,7 +191,8 @@ impl OnMessageAccepted for () { pub struct ForbidOutboundMessages; /// Error message that is used in `ForbidOutboundMessages` implementation. -const ALL_OUTBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all outbound messages"; +const ALL_OUTBOUND_MESSAGES_REJECTED: &str = + "This chain is configured to reject all outbound messages"; impl TargetHeaderChain for ForbidOutboundMessages { type Error = &'static str; @@ -208,7 +210,9 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier for ForbidOutboundMessages { +impl LaneMessageVerifier + for ForbidOutboundMessages +{ type Error = &'static str; fn verify_message( @@ -222,7 +226,9 @@ impl LaneMessageVerifier for F } } -impl MessageDeliveryAndDispatchPayment for ForbidOutboundMessages { +impl MessageDeliveryAndDispatchPayment + for ForbidOutboundMessages +{ type Error = &'static str; fn pay_delivery_and_dispatch_fee( diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 38ce9e800da43..e3f458ac8fce5 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -111,23 +111,19 @@ pub trait MessageDispatch { impl Default for ProvedLaneMessages { fn default() -> Self { - ProvedLaneMessages { - lane_state: None, - messages: Vec::new(), - } + ProvedLaneMessages { lane_state: None, messages: Vec::new() } } } impl From> for DispatchMessage { fn from(message: Message) -> Self { - DispatchMessage { - key: message.key, - data: message.data.into(), - } + DispatchMessage { key: message.key, data: message.data.into() } } } -impl From> for DispatchMessageData { +impl From> + for DispatchMessageData +{ fn from(data: MessageData) -> Self { DispatchMessageData { payload: DispatchPayload::decode(&mut &data.payload[..]), @@ -141,7 +137,8 @@ impl From> for DispatchMessageDat pub struct ForbidInboundMessages; /// Error message that is used in `ForbidOutboundMessages` implementation. -const ALL_INBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all inbound messages"; +const ALL_INBOUND_MESSAGES_REJECTED: &str = + "This chain is configured to reject all inbound messages"; impl SourceHeaderChain for ForbidInboundMessages { type Error = &'static str; @@ -162,7 +159,10 @@ impl MessageDispatch for ForbidInboundMessages { Weight::MAX } - fn dispatch(_: &AccountId, _: DispatchMessage) -> MessageDispatchResult { + fn dispatch( + _: &AccountId, + _: DispatchMessage, + ) -> MessageDispatchResult { MessageDispatchResult { dispatch_result: false, unspent_weight: 0, diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index a36f7ae65240c..8f5fab60ab3ff 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -76,8 +76,9 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; -/// All Polkadot-like chains assume that an on-initialize consumes 1 percent of the weight on average, -/// hence a single extrinsic will not be allowed to consume more than `AvailableBlockRatio - 1 percent`. +/// All Polkadot-like chains assume that an on-initialize consumes 1 percent of the weight on +/// average, hence a single extrinsic will not be allowed to consume more than +/// `AvailableBlockRatio - 1 percent`. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(1); @@ -113,7 +114,8 @@ parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can use. +/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can +/// use. pub fn max_extrinsic_weight() -> Weight { BlockWeights::get() .get(DispatchClass::Normal) @@ -144,18 +146,21 @@ pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; /// Maximal weight of single message delivery confirmation transaction on Polkadot-like chain. /// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` weight formula -/// computation for the case when single message is confirmed. The result then must be rounded up to account possible -/// future runtime upgrades. +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` +/// weight formula computation for the case when single message is confirmed. The result then must +/// be rounded up to account possible future runtime upgrades. pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; -/// Increase of delivery transaction weight on Polkadot-like chain with every additional message byte. +/// Increase of delivery transaction weight on Polkadot-like chain with every additional message +/// byte. /// -/// This value is a result of `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The -/// result then must be rounded up to account possible future runtime upgrades. +/// This value is a result of +/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then +/// must be rounded up to account possible future runtime upgrades. pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; -/// Maximal number of bytes, included in the signed Polkadot-like transaction apart from the encoded call itself. +/// Maximal number of bytes, included in the signed Polkadot-like transaction apart from the encoded +/// call itself. /// /// Can be computed by subtracting encoded call size from raw transaction size. pub const TX_EXTRA_BYTES: u32 = 256; @@ -163,16 +168,18 @@ pub const TX_EXTRA_BYTES: u32 = 256; /// Weight of single regular message delivery transaction on Polkadot-like chain. /// /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` bytes is delivered. -/// The message must have dispatch weight set to zero. The result then must be rounded up to account -/// possible future runtime upgrades. +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` +/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be +/// rounded up to account possible future runtime upgrades. pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// Weight of pay-dispatch-fee operation for inbound messages at Polkadot-like chain. /// -/// This value corresponds to the result of `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` -/// call for your chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery transactions cheaper. +/// This value corresponds to the result of +/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your +/// chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery +/// transactions cheaper. pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; /// Re-export `time_units` to make usage easier. @@ -240,15 +247,7 @@ pub type UncheckedExtrinsic = pub type Address = MultiAddress; /// A type of the data encoded as part of the transaction. -pub type SignedExtra = ( - (), - (), - (), - sp_runtime::generic::Era, - Compact, - (), - Compact, -); +pub type SignedExtra = ((), (), (), sp_runtime::generic::Era, Compact, (), Compact); /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). @@ -270,7 +269,9 @@ impl parity_scale_codec::Encode for SignedExtensions { } impl parity_scale_codec::Decode for SignedExtensions { - fn decode(_input: &mut I) -> Result { + fn decode( + _input: &mut I, + ) -> Result { unimplemented!("SignedExtensions are never meant to be decoded, they are only used to create transaction"); } } @@ -331,7 +332,9 @@ where type AdditionalSigned = AdditionalSigned; type Pre = (); - fn additional_signed(&self) -> Result { + fn additional_signed( + &self, + ) -> Result { Ok(self.additional_signed) } } @@ -372,7 +375,9 @@ pub fn account_info_storage_key(id: &AccountId) -> Vec { let storage_prefix_hashed = Twox128::hash(b"Account"); let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash); - let mut final_key = Vec::with_capacity(module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len()); + let mut final_key = Vec::with_capacity( + module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len(), + ); final_key.extend_from_slice(&module_prefix_hashed[..]); final_key.extend_from_slice(&storage_prefix_hashed[..]); @@ -400,8 +405,8 @@ mod tests { #[test] fn should_generate_storage_key() { let acc = [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, ] .into(); let key = account_info_storage_key(&acc); diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 2d7325641bac5..e24694bf8b0f8 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -18,8 +18,8 @@ use frame_support::Parameter; 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, + AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, + MaybeMallocSizeOf, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify, }, FixedPointOperand, }; @@ -77,10 +77,18 @@ 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 + MaybeSerializeDeserialize; + type Header: Parameter + + HeaderT + + MaybeSerializeDeserialize; /// The user account identifier type for the runtime. - type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default; + 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 diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index aee894aceefca..fe3309c83bf41 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -25,8 +25,8 @@ use sp_io::hashing::blake2_256; use sp_std::{convert::TryFrom, vec::Vec}; pub use chain::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, IndexOf, SignatureOf, - TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, + IndexOf, SignatureOf, TransactionEraOf, }; pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; @@ -72,8 +72,9 @@ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-deriva /// /// 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. @@ -103,8 +104,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() } @@ -113,8 +116,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() } @@ -154,9 +157,15 @@ pub enum TransactionEra { impl, BlockHash: Copy> TransactionEra { /// Prepare transaction era, based on mortality period and current best block number. - pub fn new(best_block_number: BlockNumber, best_block_hash: BlockHash, mortality_period: Option) -> Self { + pub fn new( + best_block_number: BlockNumber, + best_block_hash: BlockHash, + mortality_period: Option, + ) -> Self { mortality_period - .map(|mortality_period| TransactionEra::Mortal(best_block_number, best_block_hash, mortality_period)) + .map(|mortality_period| { + TransactionEra::Mortal(best_block_number, best_block_hash, mortality_period) + }) .unwrap_or(TransactionEra::Immortal) } @@ -169,9 +178,8 @@ impl, BlockHash: Copy> TransactionEra sp_runtime::generic::Era { match *self { TransactionEra::Immortal => sp_runtime::generic::Era::immortal(), - TransactionEra::Mortal(header_number, _, period) => { - sp_runtime::generic::Era::mortal(period as _, header_number.into()) - } + TransactionEra::Mortal(header_number, _, period) => + sp_runtime::generic::Era::mortal(period as _, header_number.into()), } } @@ -184,25 +192,40 @@ impl, BlockHash: Copy> TransactionEra StorageKey { - storage_map_final_key_identity(pallet_prefix, map_name, &frame_support::Blake2_128Concat::hash(key)) +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), + ) } -/// This is a copypaste of the `frame_support::storage::generator::StorageMap::storage_map_final_key` -/// for `Identity` maps. +/// This is a copypaste 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 { +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()); + 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[..]); @@ -211,7 +234,8 @@ pub fn storage_map_final_key_identity(pallet_prefix: &str, map_name: &str, key_h StorageKey(final_key) } -/// This is how a storage key of storage parameter (`parameter_types! { storage Param: bool = false; }`) is computed. +/// This is how a storage key of storage parameter (`parameter_types! { storage Param: bool = false; +/// }`) is computed. /// /// Copypaste from `frame_support::parameter_types` macro pub fn storage_parameter_key(parameter_name: &str) -> StorageKey { diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index 1b00c10fa4930..c351d771cf871 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -50,7 +50,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, } diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index d70be93b1d251..9cc5b48ebd913 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -42,7 +42,7 @@ where pub fn new(root: H::Out, proof: StorageProof) -> Result { 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>, Error> { - read_trie_value::, _>(&self.db, &self.root, key).map_err(|_| Error::StorageValueUnavailable) + read_trie_value::, _>(&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 = >::new(root, proof.clone()).unwrap(); + let checker = + >::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)); diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index b83678cae5e51..059d6eb5be4f1 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -45,7 +45,8 @@ impl Account { let data = self.0.encode(); let mut bytes = [0_u8; 32]; bytes[0..data.len()].copy_from_slice(&*data); - SecretKey::from_bytes(&bytes).expect("A static array of the correct length is a known good.") + SecretKey::from_bytes(&bytes) + .expect("A static array of the correct length is a known good.") } pub fn pair(&self) -> Keypair { @@ -57,7 +58,8 @@ impl Account { let public = self.public(); pair[32..].copy_from_slice(&public.to_bytes()); - Keypair::from_bytes(&pair).expect("We expect the SecretKey to be good, so this must also be good.") + Keypair::from_bytes(&pair) + .expect("We expect the SecretKey to be good, so this must also be good.") } pub fn sign(&self, msg: &[u8]) -> Signature { @@ -79,10 +81,7 @@ pub fn voter_set() -> VoterSet { /// Convenience function to get a list of Grandpa authorities. pub fn authority_list() -> AuthorityList { - test_keyring() - .iter() - .map(|(id, w)| (AuthorityId::from(*id), *w)) - .collect() + test_keyring().iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect() } /// Get the corresponding identities from the keyring for the "standard" authority set. diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 83aac614ab809..9e044ed472dd7 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -21,8 +21,7 @@ use bp_header_chain::justification::GrandpaJustification; use codec::Encode; use sp_application_crypto::TryFrom; -use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; -use sp_finality_grandpa::{AuthoritySignature, SetId}; +use sp_finality_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId}; use sp_runtime::traits::{Header as HeaderT, One, Zero}; use sp_std::prelude::*; @@ -72,10 +71,7 @@ impl Default for JustificationGeneratorParams { /// Make a valid GRANDPA justification with sensible defaults pub fn make_default_justification(header: &H) -> GrandpaJustification { - let params = JustificationGeneratorParams:: { - header: header.clone(), - ..Default::default() - }; + let params = JustificationGeneratorParams:: { header: header.clone(), ..Default::default() }; make_justification_for_header(params) } @@ -89,15 +85,11 @@ pub fn make_default_justification(header: &H) -> GrandpaJustificatio /// /// Note: This needs at least three authorities or else the verifier will complain about /// being given an invalid commit. -pub fn make_justification_for_header(params: JustificationGeneratorParams) -> GrandpaJustification { - let JustificationGeneratorParams { - header, - round, - set_id, - authorities, - mut ancestors, - forks, - } = params; +pub fn make_justification_for_header( + params: JustificationGeneratorParams, +) -> GrandpaJustification { + let JustificationGeneratorParams { header, round, set_id, authorities, mut ancestors, forks } = + params; let (target_hash, target_number) = (header.hash(), *header.number()); let mut votes_ancestries = vec![]; let mut precommits = vec![]; @@ -144,11 +136,7 @@ pub fn make_justification_for_header(params: JustificationGeneratorP GrandpaJustification { round, - commit: finality_grandpa::Commit { - target_hash, - target_number, - precommits, - }, + commit: finality_grandpa::Commit { target_hash, target_number, precommits }, votes_ancestries, } } @@ -165,10 +153,7 @@ fn generate_chain(fork_id: u32, depth: u32, ancestor: &H) -> Vec // Modifying the digest so headers at the same height but in different forks have different // hashes - header - .digest_mut() - .logs - .push(sp_runtime::DigestItem::Other(fork_id.encode())); + header.digest_mut().logs.push(sp_runtime::DigestItem::Other(fork_id.encode())); headers.push(header); } @@ -183,29 +168,26 @@ pub fn signed_precommit( round: u64, set_id: SetId, ) -> finality_grandpa::SignedPrecommit { - let precommit = finality_grandpa::Precommit { - target_hash: target.0, - target_number: target.1, - }; + let precommit = finality_grandpa::Precommit { target_hash: target.0, target_number: target.1 }; - let encoded = - sp_finality_grandpa::localized_payload(round, set_id, &finality_grandpa::Message::Precommit(precommit.clone())); + let encoded = sp_finality_grandpa::localized_payload( + round, + set_id, + &finality_grandpa::Message::Precommit(precommit.clone()), + ); let signature = signer.sign(&encoded); let raw_signature: Vec = signature.to_bytes().into(); - // Need to wrap our signature and id types that they match what our `SignedPrecommit` is expecting + // Need to wrap our signature and id types that they match what our `SignedPrecommit` is + // expecting let signature = AuthoritySignature::try_from(raw_signature).expect( "We know our Keypair is good, so our signature must also be good.", ); let id = (*signer).into(); - finality_grandpa::SignedPrecommit { - precommit, - signature, - id, - } + finality_grandpa::SignedPrecommit { precommit, signature, id } } /// Get a header for testing. @@ -213,13 +195,7 @@ pub fn signed_precommit( /// The correct parent hash will be used if given a non-zero header. pub fn test_header(number: H::Number) -> H { let default = |num| { - H::new( - num, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ) + H::new(num, Default::default(), Default::default(), Default::default(), Default::default()) }; let mut header = default(number); diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index 13d6a596cbf3f..336e3263f09d9 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -26,8 +26,8 @@ pub enum TokenSwapState { /// The swap has been started using the `start_claim` call, but we have no proof that it has /// happened at the Bridged chain. Started, - /// The swap has happened at the Bridged chain and may be claimed by the Bridged chain party using - /// the `claim_swap` call. + /// The swap has happened at the Bridged chain and may be claimed by the Bridged chain party + /// using the `claim_swap` call. Confirmed, /// The swap has failed at the Bridged chain and This chain party may cancel it using the /// `cancel_swap` call. @@ -43,19 +43,20 @@ pub enum TokenSwapType { /// The `target_account_at_bridged_chain` is temporary and only have funds for single swap. /// /// ***WARNING**: if `target_account_at_bridged_chain` still exists after the swap has been - /// completed (either by claiming or canceling), the `source_account_at_this_chain` will be able - /// to restart the swap again and repeat the swap until `target_account_at_bridged_chain` depletes. + /// completed (either by claiming or canceling), the `source_account_at_this_chain` will be + /// able to restart the swap again and repeat the swap until `target_account_at_bridged_chain` + /// depletes. TemporaryTargetAccountAtBridgedChain, - /// This swap type prevents `source_account_at_this_chain` from restarting the swap after it has - /// been completed. There are two consequences: + /// This swap type prevents `source_account_at_this_chain` from restarting the swap after it + /// has been completed. There are two consequences: /// - /// 1) the `source_account_at_this_chain` won't be able to call `start_swap` after given ; - /// 2) the `target_account_at_bridged_chain` won't be able to call `claim_swap` (over the bridge) before - /// block ``. + /// 1) the `source_account_at_this_chain` won't be able to call `start_swap` after given + /// ; 2) the `target_account_at_bridged_chain` won't be able to call + /// `claim_swap` (over the bridge) before block ``. /// /// The second element is the nonce of the swap. You must care about its uniqueness if you're - /// planning to perform another swap with exactly the same parameters (i.e. same amount, same accounts, - /// same `ThisBlockNumber`) to avoid collisions. + /// planning to perform another swap with exactly the same parameters (i.e. same amount, same + /// accounts, same `ThisBlockNumber`) to avoid collisions. LockClaimUntilBlock(ThisBlockNumber, U256), } @@ -64,9 +65,11 @@ pub enum TokenSwapType { /// /// **IMPORTANT NOTE**: this structure is always the same during single token swap. So even /// when chain changes, the meaning of This and Bridged are still used to point to the same chains. -/// This chain is always the chain where swap has been started. And the Bridged chain is the other chain. +/// This chain is always the chain where swap has been started. And the Bridged chain is the other +/// chain. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] -pub struct TokenSwap { +pub struct TokenSwap +{ /// The type of the swap. pub swap_type: TokenSwapType, /// This chain balance to be swapped with `target_balance_at_bridged_chain`. @@ -75,6 +78,7 @@ pub struct TokenSwap. -use crate::rpc_errors::RpcError; -use crate::substrate_sync_loop::QueuedRialtoHeader; +use crate::{rpc_errors::RpcError, substrate_sync_loop::QueuedRialtoHeader}; use async_trait::async_trait; use bp_eth_poa::signatures::secret_to_address; @@ -60,7 +59,10 @@ pub trait EthereumHighLevelRpc { ) -> SubmittedHeaders; /// Returns ids of incomplete Substrate headers. - async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult>; + async fn incomplete_substrate_headers( + &self, + contract_address: Address, + ) -> RpcResult>; /// Complete Substrate header. async fn complete_substrate_header( @@ -104,7 +106,7 @@ impl EthereumHighLevelRpc for EthereumClient { let hash = rialto_runtime::Hash::decode(&mut &raw_hash[..])?; if number != number.low_u32().into() { - return Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)); + return Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)) } Ok(HeaderId(number.low_u32(), hash)) @@ -138,31 +140,28 @@ impl EthereumHighLevelRpc for EthereumClient { let address: Address = secret_to_address(¶ms.signer); let nonce = match self.account_nonce(address).await { Ok(nonce) => nonce, - Err(error) => { + Err(error) => return SubmittedHeaders { submitted: Vec::new(), incomplete: Vec::new(), rejected: headers.iter().rev().map(|header| header.id()).collect(), fatal_error: Some(error.into()), - } - } + }, }; // submit headers. Note that we're cloning self here. It is ok, because // cloning `jsonrpsee::Client` only clones reference to background threads submit_substrate_headers( - EthereumHeadersSubmitter { - client: self.clone(), - params, - contract_address, - nonce, - }, + EthereumHeadersSubmitter { client: self.clone(), params, contract_address, nonce }, headers, ) .await } - async fn incomplete_substrate_headers(&self, contract_address: Address) -> RpcResult> { + async fn incomplete_substrate_headers( + &self, + contract_address: Address, + ) -> RpcResult> { let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); let call_request = CallRequest { to: Some(contract_address), @@ -173,13 +172,14 @@ impl EthereumHighLevelRpc for EthereumClient { let call_result = self.eth_call(call_request).await?; // Q: Is is correct to call these "incomplete_ids"? - let (incomplete_headers_numbers, incomplete_headers_hashes) = call_decoder.decode(&call_result.0)?; + let (incomplete_headers_numbers, incomplete_headers_hashes) = + call_decoder.decode(&call_result.0)?; let incomplete_ids = incomplete_headers_numbers .into_iter() .zip(incomplete_headers_hashes) .filter_map(|(number, hash)| { if number != number.low_u32().into() { - return None; + return None } Some(HeaderId(number.low_u32(), hash)) @@ -202,7 +202,11 @@ impl EthereumHighLevelRpc for EthereumClient { Some(contract_address), None, false, - bridge_contract::functions::import_finality_proof::encode_input(id.0, id.1, justification), + bridge_contract::functions::import_finality_proof::encode_input( + id.0, + id.1, + justification, + ), ) .await?; @@ -263,7 +267,7 @@ impl HeadersBatch { ) -> Result<(Self, Vec), ()> { if headers.len() != ids.len() { log::error!(target: "bridge", "Collection size mismatch ({} vs {})", headers.len(), ids.len()); - return Err(()); + return Err(()) } let header1 = headers.pop().ok_or(())?; @@ -276,27 +280,14 @@ impl HeadersBatch { submitting_ids.extend(ids.pop().iter()); } - Ok(( - Self { - header1, - header2, - header3, - header4, - }, - submitting_ids, - )) + Ok((Self { header1, header2, header3, header4 }, submitting_ids)) } /// Returns unified array of headers. /// /// The first element is always `Some`. fn headers(&self) -> [Option<&QueuedRialtoHeader>; HEADERS_BATCH] { - [ - Some(&self.header1), - self.header2.as_ref(), - self.header3.as_ref(), - self.header4.as_ref(), - ] + [Some(&self.header1), self.header2.as_ref(), self.header3.as_ref(), self.header4.as_ref()] } /// Encodes all headers. If header is not present an empty vector will be returned. @@ -323,9 +314,10 @@ impl HeadersBatch { /// or when `idx > HEADERS_BATCH`. pub fn split_off(&mut self, idx: usize) -> Result<(), ()> { if idx == 0 || idx > HEADERS_BATCH { - return Err(()); + return Err(()) } - let mut vals: [_; HEADERS_BATCH] = [&mut None, &mut self.header2, &mut self.header3, &mut self.header4]; + let mut vals: [_; HEADERS_BATCH] = + [&mut None, &mut self.header2, &mut self.header3, &mut self.header4]; for val in vals.iter_mut().skip(idx) { **val = None; } @@ -359,7 +351,8 @@ struct EthereumHeadersSubmitter { impl HeadersSubmitter for EthereumHeadersSubmitter { async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult { let [h1, h2, h3, h4] = headers.encode(); - let (encoded_call, call_decoder) = bridge_contract::functions::is_incomplete_headers::call(h1, h2, h3, h4); + let (encoded_call, call_decoder) = + bridge_contract::functions::is_incomplete_headers::call(h1, h2, h3, h4); let call_request = CallRequest { to: Some(self.contract_address), data: Some(encoded_call.into()), @@ -369,7 +362,7 @@ impl HeadersSubmitter for EthereumHeadersSubmitter { let call_result = self.client.eth_call(call_request).await?; let incomplete_index: U256 = call_decoder.decode(&call_result.0)?; if incomplete_index > HEADERS_BATCH.into() { - return Err(RpcError::Ethereum(EthereumNodeError::InvalidIncompleteIndex)); + return Err(RpcError::Ethereum(EthereumNodeError::InvalidIncompleteIndex)) } Ok(incomplete_index.low_u32() as _) @@ -407,17 +400,21 @@ async fn submit_substrate_headers( headers.reverse(); while !headers.is_empty() { - let (headers, submitting_ids) = - HeadersBatch::pop_from(&mut headers, &mut ids).expect("Headers and ids are not empty; qed"); + let (headers, submitting_ids) = HeadersBatch::pop_from(&mut headers, &mut ids) + .expect("Headers and ids are not empty; qed"); - submitted_headers.fatal_error = - submit_substrate_headers_batch(&mut header_submitter, &mut submitted_headers, submitting_ids, headers) - .await; + submitted_headers.fatal_error = submit_substrate_headers_batch( + &mut header_submitter, + &mut submitted_headers, + submitting_ids, + headers, + ) + .await; if submitted_headers.fatal_error.is_some() { ids.reverse(); submitted_headers.rejected.extend(ids); - break; + break } } @@ -436,9 +433,11 @@ async fn submit_substrate_headers_batch( // if parent of first header is either incomplete, or rejected, we assume that contract // will reject this header as well let parent_id = headers.header1.parent_id(); - if submitted_headers.rejected.contains(&parent_id) || submitted_headers.incomplete.contains(&parent_id) { + if submitted_headers.rejected.contains(&parent_id) || + submitted_headers.incomplete.contains(&parent_id) + { submitted_headers.rejected.extend(ids); - return None; + return None } // check if headers are incomplete @@ -450,11 +449,11 @@ async fn submit_substrate_headers_batch( // contract has rejected all headers => we do not want to submit it submitted_headers.rejected.extend(ids); if error.is_connection_error() { - return Some(error); + return Some(error) } else { - return None; + return None } - } + }, }; // Modify `ids` and `headers` to only contain values that are going to be accepted. @@ -477,12 +476,12 @@ async fn submit_substrate_headers_batch( submitted_headers.submitted.extend(submitted); submitted_headers.rejected.extend(rejected); None - } + }, Err(error) => { submitted_headers.rejected.extend(submitted); submitted_headers.rejected.extend(rejected); Some(error) - } + }, } } @@ -521,11 +520,7 @@ mod tests { number, Default::default(), Default::default(), - if number == 0 { - Default::default() - } else { - header(number - 1).id().1 - }, + if number == 0 { Default::default() } else { header(number - 1).id().1 }, Default::default(), ) .into(), @@ -535,10 +530,7 @@ mod tests { #[test] fn descendants_of_incomplete_headers_are_not_submitted() { let submitted_headers = async_std::task::block_on(submit_substrate_headers( - TestHeadersSubmitter { - incomplete: vec![header(5).id()], - failed: vec![], - }, + TestHeadersSubmitter { incomplete: vec![header(5).id()], failed: vec![] }, vec![header(5), header(6)], )); assert_eq!(submitted_headers.submitted, vec![header(5).id()]); @@ -550,19 +542,8 @@ mod tests { #[test] fn headers_after_fatal_error_are_not_submitted() { let submitted_headers = async_std::task::block_on(submit_substrate_headers( - TestHeadersSubmitter { - incomplete: vec![], - failed: vec![header(9).id()], - }, - vec![ - header(5), - header(6), - header(7), - header(8), - header(9), - header(10), - header(11), - ], + TestHeadersSubmitter { incomplete: vec![], failed: vec![header(9).id()] }, + vec![header(5), header(6), header(7), header(8), header(9), header(10), header(11)], )); assert_eq!( submitted_headers.submitted, @@ -583,10 +564,7 @@ mod tests { let (headers, ids) = HeadersBatch::pop_from(&mut init_headers, &mut init_ids).unwrap(); assert_eq!(init_headers, vec![header(5)]); assert_eq!(init_ids, vec![header(5).id()]); - assert_eq!( - ids, - vec![header(1).id(), header(2).id(), header(3).id(), header(4).id()] - ); + assert_eq!(ids, vec![header(1).id(), header(2).id(), header(3).id(), header(4).id()]); headers } diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs index 3f9076f6db229..d7006a9c673cf 100644 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -14,17 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_client::{bridge_contract, EthereumHighLevelRpc}; -use crate::rpc_errors::RpcError; +use crate::{ + ethereum_client::{bridge_contract, EthereumHighLevelRpc}, + rpc_errors::RpcError, +}; use codec::{Decode, Encode}; use num_traits::Zero; use relay_ethereum_client::{ - Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, + Client as EthereumClient, ConnectionParams as EthereumConnectionParams, + SigningParams as EthereumSigningParams, }; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto}; use relay_substrate_client::{ - Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, OpaqueGrandpaAuthoritiesSet, + Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, + OpaqueGrandpaAuthoritiesSet, }; use relay_utils::HeaderId; @@ -102,19 +106,18 @@ async fn prepare_initial_header( sub_initial_header: Option>, ) -> Result<(RialtoHeaderId, Vec), String> { match sub_initial_header { - Some(raw_initial_header) => match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) { - Ok(initial_header) => Ok(( - HeaderId(initial_header.number, initial_header.hash()), - raw_initial_header, - )), - Err(error) => Err(format!("Error decoding initial header: {}", error)), - }, + Some(raw_initial_header) => + match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) { + Ok(initial_header) => + Ok((HeaderId(initial_header.number, initial_header.hash()), raw_initial_header)), + Err(error) => Err(format!("Error decoding initial header: {}", error)), + }, None => { let initial_header = sub_client.header_by_number(Zero::zero()).await; initial_header .map(|header| (HeaderId(Zero::zero(), header.hash()), header.encode())) .map_err(|error| format!("Error reading Substrate genesis header: {:?}", error)) - } + }, } } @@ -129,7 +132,8 @@ async fn prepare_initial_authorities_set( None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await, }; - initial_authorities_set.map_err(|error| format!("Error reading GRANDPA authorities set: {:?}", error)) + initial_authorities_set + .map_err(|error| format!("Error reading GRANDPA authorities set: {:?}", error)) } /// Deploy bridge contract to Ethereum chain. @@ -147,7 +151,12 @@ async fn deploy_bridge_contract( None, None, false, - bridge_contract::constructor(contract_code, initial_header, initial_set_id, initial_authorities), + bridge_contract::constructor( + contract_code, + initial_header, + initial_set_id, + initial_authorities, + ), ) .await .map_err(|error| format!("Error deploying contract: {:?}", error)) diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index 73a107cb40655..6262c44c18d2c 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -16,28 +16,34 @@ //! Relaying proofs of PoA -> Substrate exchange transactions. -use crate::instances::BridgeInstance; -use crate::rialto_client::{SubmitEthereumExchangeTransactionProof, SubstrateHighLevelRpc}; -use crate::rpc_errors::RpcError; -use crate::substrate_types::into_substrate_ethereum_receipt; +use crate::{ + instances::BridgeInstance, + rialto_client::{SubmitEthereumExchangeTransactionProof, SubstrateHighLevelRpc}, + rpc_errors::RpcError, + substrate_types::into_substrate_ethereum_receipt, +}; use async_trait::async_trait; use bp_currency_exchange::MaybeLockFundsTransaction; -use exchange_relay::exchange::{ - relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, - TransactionProofPipeline, +use exchange_relay::{ + exchange::{ + relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, + TransactionProofPipeline, + }, + exchange_loop::{run as run_loop, InMemoryStorage}, }; -use exchange_relay::exchange_loop::{run as run_loop, InMemoryStorage}; use relay_ethereum_client::{ types::{ HeaderId as EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, - Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, HEADER_ID_PROOF, + Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, + HEADER_ID_PROOF, }, Client as EthereumClient, ConnectionParams as EthereumConnectionParams, }; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{ - Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, + Chain as SubstrateChain, Client as SubstrateClient, + ConnectionParams as SubstrateConnectionParams, }; use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId}; use rialto_runtime::exchange::EthereumTransactionInclusionProof; @@ -111,12 +117,7 @@ impl SourceBlock for EthereumSourceBlock { } fn transactions(&self) -> Vec { - self.0 - .transactions - .iter() - .cloned() - .map(EthereumSourceTransaction) - .collect() + self.0.transactions.iter().cloned().map(EthereumSourceTransaction).collect() } } @@ -178,13 +179,12 @@ impl SourceClient for EthereumTransactionsSource { }; // we need transaction to be mined => check if it is included in the block - let (eth_header_id, eth_tx_index) = match (eth_tx.block_number, eth_tx.block_hash, eth_tx.transaction_index) { - (Some(block_number), Some(block_hash), Some(transaction_index)) => ( - HeaderId(block_number.as_u64(), block_hash), - transaction_index.as_u64() as _, - ), - _ => return Ok(None), - }; + let (eth_header_id, eth_tx_index) = + match (eth_tx.block_number, eth_tx.block_hash, eth_tx.transaction_index) { + (Some(block_number), Some(block_hash), Some(transaction_index)) => + (HeaderId(block_number.as_u64(), block_hash), transaction_index.as_u64() as _), + _ => return Ok(None), + }; Ok(Some((eth_header_id, eth_tx_index))) } @@ -194,9 +194,11 @@ impl SourceClient for EthereumTransactionsSource { block: &EthereumSourceBlock, tx_index: usize, ) -> Result { - const TRANSACTION_HAS_RAW_FIELD_PROOF: &str = "RPC level checks that transactions from Ethereum\ + const TRANSACTION_HAS_RAW_FIELD_PROOF: &str = + "RPC level checks that transactions from Ethereum\ node are having `raw` field; qed"; - const BLOCK_HAS_HASH_FIELD_PROOF: &str = "RPC level checks that block has `hash` field; qed"; + const BLOCK_HAS_HASH_FIELD_PROOF: &str = + "RPC level checks that block has `hash` field; qed"; let mut transaction_proof = Vec::with_capacity(block.0.transactions.len()); for tx in &block.0.transactions { @@ -266,12 +268,15 @@ impl TargetClient for SubstrateTransactionsTarget { self.client.best_ethereum_finalized_block().await } - async fn filter_transaction_proof(&self, proof: &EthereumTransactionInclusionProof) -> Result { + async fn filter_transaction_proof( + &self, + proof: &EthereumTransactionInclusionProof, + ) -> Result { // let's try to parse transaction locally let (raw_tx, raw_tx_receipt) = &proof.proof[proof.index as usize]; let parse_result = rialto_runtime::exchange::EthTransaction::parse(raw_tx); if parse_result.is_err() { - return Ok(false); + return Ok(false) } // now let's check if transaction is successful @@ -285,8 +290,12 @@ impl TargetClient for SubstrateTransactionsTarget { self.client.verify_exchange_transaction_proof(proof.clone()).await } - async fn submit_transaction_proof(&self, proof: EthereumTransactionInclusionProof) -> Result<(), RpcError> { - let (sign_params, bridge_instance) = (self.sign_params.clone(), self.bridge_instance.clone()); + async fn submit_transaction_proof( + &self, + proof: EthereumTransactionInclusionProof, + ) -> Result<(), RpcError> { + let (sign_params, bridge_instance) = + (self.sign_params.clone(), self.bridge_instance.clone()); self.client .submit_exchange_transaction_proof(sign_params, bridge_instance, proof) .await @@ -311,9 +320,10 @@ pub async fn run(params: EthereumExchangeParams) { err, ), } - } + }, ExchangeRelayMode::Auto(eth_start_with_block_number) => { - let result = run_auto_transactions_relay_loop(params, eth_start_with_block_number).await; + let result = + run_auto_transactions_relay_loop(params, eth_start_with_block_number).await; if let Err(err) = result { log::error!( target: "bridge", @@ -321,23 +331,18 @@ pub async fn run(params: EthereumExchangeParams) { err, ); } - } + }, } } /// Run single transaction proof relay and stop. -async fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_hash: H256) -> Result<(), String> { - let EthereumExchangeParams { - eth_params, - sub_params, - sub_sign, - instance, - .. - } = params; +async fn run_single_transaction_relay( + params: EthereumExchangeParams, + eth_tx_hash: H256, +) -> Result<(), String> { + let EthereumExchangeParams { eth_params, sub_params, sub_sign, instance, .. } = params; - let eth_client = EthereumClient::try_connect(eth_params) - .await - .map_err(RpcError::Ethereum)?; + let eth_client = EthereumClient::try_connect(eth_params).await.map_err(RpcError::Ethereum)?; let sub_client = SubstrateClient::::try_connect(sub_params) .await .map_err(RpcError::Substrate)?; @@ -357,12 +362,7 @@ async fn run_auto_transactions_relay_loop( eth_start_with_block_number: Option, ) -> anyhow::Result<()> { let EthereumExchangeParams { - eth_params, - sub_params, - sub_sign, - metrics_params, - instance, - .. + eth_params, sub_params, sub_sign, metrics_params, instance, .. } = params; let eth_client = EthereumClient::new(eth_params).await; @@ -370,7 +370,7 @@ async fn run_auto_transactions_relay_loop( let eth_start_with_block_number = match eth_start_with_block_number { Some(eth_start_with_block_number) => eth_start_with_block_number, - None => { + None => sub_client .best_ethereum_finalized_block() .await @@ -380,8 +380,7 @@ async fn run_auto_transactions_relay_loop( err ) })? - .0 - } + .0, }; run_loop( diff --git a/relays/bin-ethereum/src/ethereum_exchange_submit.rs b/relays/bin-ethereum/src/ethereum_exchange_submit.rs index 602d4f14e4f0b..75bdf0e577aa2 100644 --- a/relays/bin-ethereum/src/ethereum_exchange_submit.rs +++ b/relays/bin-ethereum/src/ethereum_exchange_submit.rs @@ -22,7 +22,8 @@ use bp_eth_poa::{ }; use relay_ethereum_client::{ types::{CallRequest, U256}, - Client as EthereumClient, ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, + Client as EthereumClient, ConnectionParams as EthereumConnectionParams, + SigningParams as EthereumSigningParams, }; use rialto_runtime::exchange::LOCK_FUNDS_ADDRESS; @@ -43,13 +44,8 @@ pub struct EthereumExchangeSubmitParams { /// Submit single Ethereum -> Substrate exchange transaction. pub async fn run(params: EthereumExchangeSubmitParams) { - let EthereumExchangeSubmitParams { - eth_params, - eth_sign, - eth_nonce, - eth_amount, - sub_recipient, - } = params; + let EthereumExchangeSubmitParams { eth_params, eth_sign, eth_nonce, eth_amount, sub_recipient } = + params; let result: Result<_, String> = async move { let eth_client = EthereumClient::try_connect(eth_params) @@ -83,9 +79,8 @@ pub async fn run(params: EthereumExchangeSubmitParams) { value: eth_amount, payload: sub_recipient_encoded.to_vec(), }; - let eth_tx_signed = eth_tx_unsigned - .clone() - .sign_by(ð_sign.signer, Some(eth_sign.chain_id)); + let eth_tx_signed = + eth_tx_unsigned.clone().sign_by(ð_sign.signer, Some(eth_sign.chain_id)); eth_client .submit_transaction(eth_tx_signed) .await @@ -102,13 +97,13 @@ pub async fn run(params: EthereumExchangeSubmitParams) { "Exchange transaction has been submitted to Ethereum node: {:?}", eth_tx_unsigned, ); - } + }, Err(err) => { log::error!( target: "bridge", "Error submitting exchange transaction to Ethereum node: {}", err, ); - } + }, } } diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs index c4a5f5102a733..ee5f8a4600ece 100644 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -16,11 +16,13 @@ //! Ethereum PoA -> Rialto-Substrate synchronization. -use crate::ethereum_client::EthereumHighLevelRpc; -use crate::instances::BridgeInstance; -use crate::rialto_client::{SubmitEthereumHeaders, SubstrateHighLevelRpc}; -use crate::rpc_errors::RpcError; -use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; +use crate::{ + ethereum_client::EthereumHighLevelRpc, + instances::BridgeInstance, + rialto_client::{SubmitEthereumHeaders, SubstrateHighLevelRpc}, + rpc_errors::RpcError, + substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}, +}; use async_trait::async_trait; use codec::Encode; @@ -35,12 +37,12 @@ use relay_ethereum_client::{ }; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{ - Chain as SubstrateChain, Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, + Chain as SubstrateChain, Client as SubstrateClient, + ConnectionParams as SubstrateConnectionParams, }; use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; -use std::fmt::Debug; -use std::{collections::HashSet, sync::Arc, time::Duration}; +use std::{collections::HashSet, fmt::Debug, sync::Arc, time::Duration}; pub mod consts { use super::*; @@ -57,7 +59,8 @@ pub mod consts { pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128; /// Max Ethereum headers count we want to have in 'submitted' state. pub const MAX_SUBMITTED_HEADERS: usize = 128; - /// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). + /// Max depth of in-memory headers in all states. Past this depth they will be forgotten + /// (pruned). pub const PRUNE_DEPTH: u32 = 4096; } @@ -106,8 +109,8 @@ impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { type Completion = (); fn estimate_size(source: &QueuedHeader) -> usize { - into_substrate_ethereum_header(source.header()).encode().len() - + into_substrate_ethereum_receipts(source.extra()) + into_substrate_ethereum_header(source.header()).encode().len() + + into_substrate_ethereum_receipts(source.extra()) .map(|extra| extra.encode().len()) .unwrap_or(0) } @@ -148,22 +151,17 @@ impl SourceClient for EthereumHeadersSource { } async fn header_by_hash(&self, hash: HeaderHash) -> Result { - self.client - .header_by_hash(hash) - .await - .map(Into::into) - .map_err(Into::into) + self.client.header_by_hash(hash).await.map(Into::into).map_err(Into::into) } async fn header_by_number(&self, number: u64) -> Result { - self.client - .header_by_number(number) - .await - .map(Into::into) - .map_err(Into::into) + self.client.header_by_number(number).await.map(Into::into).map_err(Into::into) } - async fn header_completion(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, Option<()>), RpcError> { + async fn header_completion( + &self, + id: EthereumHeaderId, + ) -> Result<(EthereumHeaderId, Option<()>), RpcError> { Ok((id, None)) } @@ -172,9 +170,7 @@ impl SourceClient for EthereumHeadersSource { id: EthereumHeaderId, header: QueuedEthereumHeader, ) -> Result<(EthereumHeaderId, Vec), RpcError> { - self.client - .transaction_receipts(id, header.header().transactions.clone()) - .await + self.client.transaction_receipts(id, header.header().transactions.clone()).await } } @@ -197,12 +193,7 @@ impl SubstrateHeadersTarget { sign_params: RialtoSigningParams, bridge_instance: Arc, ) -> Self { - Self { - client, - sign_transactions, - sign_params, - bridge_instance, - } + Self { client, sign_transactions, sign_params, bridge_instance } } } @@ -225,16 +216,19 @@ impl TargetClient for SubstrateHeadersTarget { self.client.best_ethereum_block().await } - async fn is_known_header(&self, id: EthereumHeaderId) -> Result<(EthereumHeaderId, bool), RpcError> { + async fn is_known_header( + &self, + id: EthereumHeaderId, + ) -> Result<(EthereumHeaderId, bool), RpcError> { Ok((id, self.client.ethereum_header_known(id).await?)) } - async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { - let (sign_params, bridge_instance, sign_transactions) = ( - self.sign_params.clone(), - self.bridge_instance.clone(), - self.sign_transactions, - ); + async fn submit_headers( + &self, + headers: Vec, + ) -> SubmittedHeaders { + let (sign_params, bridge_instance, sign_transactions) = + (self.sign_params.clone(), self.bridge_instance.clone(), self.sign_transactions); self.client .submit_ethereum_headers(sign_params, bridge_instance, headers, sign_transactions) .await @@ -245,11 +239,18 @@ impl TargetClient for SubstrateHeadersTarget { } #[allow(clippy::unit_arg)] - async fn complete_header(&self, id: EthereumHeaderId, _completion: ()) -> Result { + async fn complete_header( + &self, + id: EthereumHeaderId, + _completion: (), + ) -> Result { Ok(id) } - async fn requires_extra(&self, header: QueuedEthereumHeader) -> Result<(EthereumHeaderId, bool), RpcError> { + async fn requires_extra( + &self, + header: QueuedEthereumHeader, + ) -> Result<(EthereumHeaderId, bool), RpcError> { // we can minimize number of receipts_check calls by checking header // logs bloom here, but it may give us false positives (when authorities // source is contract, we never need any logs) diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs index 2ade8632a92c0..90d736fa251d7 100644 --- a/relays/bin-ethereum/src/instances.rs +++ b/relays/bin-ethereum/src/instances.rs @@ -18,16 +18,18 @@ //! synchronizing a Substrate chain which can include multiple instances of the bridge pallet we //! must somehow decide which of the instances to sync. //! -//! Note that each instance of the bridge pallet is coupled with an instance of the currency exchange -//! pallet. We must also have a way to create `Call`s for the correct currency exchange instance. +//! Note that each instance of the bridge pallet is coupled with an instance of the currency +//! exchange pallet. We must also have a way to create `Call`s for the correct currency exchange +//! instance. //! //! This module helps by preparing the correct `Call`s for each of the different pallet instances. -use crate::ethereum_sync_loop::QueuedEthereumHeader; -use crate::substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}; +use crate::{ + ethereum_sync_loop::QueuedEthereumHeader, + substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}, +}; -use rialto_runtime::exchange::EthereumTransactionInclusionProof as Proof; -use rialto_runtime::Call; +use rialto_runtime::{exchange::EthereumTransactionInclusionProof as Proof, Call}; /// Interface for `Calls` which are needed to correctly sync the bridge. /// @@ -73,7 +75,8 @@ impl BridgeInstance for RialtoPoA { } fn build_currency_exchange_call(&self, proof: Proof) -> Call { - let pallet_call = rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + let pallet_call = + rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); rialto_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call) } } @@ -109,7 +112,8 @@ impl BridgeInstance for Kovan { } fn build_currency_exchange_call(&self, proof: Proof) -> Call { - let pallet_call = rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + let pallet_call = + rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); rialto_runtime::Call::BridgeKovanCurrencyExchange(pallet_call) } } diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index bcdae353d3dc4..cb64dc40d935e 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -43,7 +43,9 @@ use sp_core::crypto::Pair; use substrate_sync_loop::SubstrateSyncParams; use headers_relay::sync::HeadersSyncParams; -use relay_ethereum_client::{ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams}; +use relay_ethereum_client::{ + ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, +}; use relay_rialto_client::SigningParams as RialtoSigningParams; use relay_substrate_client::ConnectionParams as SubstrateConnectionParams; use std::sync::Arc; @@ -64,79 +66,83 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { Ok(ethereum_sync_params) => ethereum_sync_params, Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); - return; - } + return + }, }) .await .is_err() { log::error!(target: "bridge", "Unable to get Substrate genesis block for Ethereum sync."); }; - } + }, ("sub-to-eth", Some(sub_to_eth_matches)) => { log::info!(target: "bridge", "Starting SUB ➡ ETH relay."); if substrate_sync_loop::run(match substrate_sync_params(sub_to_eth_matches) { Ok(substrate_sync_params) => substrate_sync_params, Err(err) => { log::error!(target: "bridge", "Error parsing parameters: {}", err); - return; - } + return + }, }) .await .is_err() { log::error!(target: "bridge", "Unable to get Substrate genesis block for Substrate sync."); }; - } + }, ("eth-deploy-contract", Some(eth_deploy_matches)) => { log::info!(target: "bridge", "Deploying ETH contracts."); - ethereum_deploy_contract::run(match ethereum_deploy_contract_params(eth_deploy_matches) { - Ok(ethereum_deploy_params) => ethereum_deploy_params, - Err(err) => { - log::error!(target: "bridge", "Error during contract deployment: {}", err); - return; - } - }) + ethereum_deploy_contract::run( + match ethereum_deploy_contract_params(eth_deploy_matches) { + Ok(ethereum_deploy_params) => ethereum_deploy_params, + Err(err) => { + log::error!(target: "bridge", "Error during contract deployment: {}", err); + return + }, + }, + ) .await; - } + }, ("eth-submit-exchange-tx", Some(eth_exchange_submit_matches)) => { log::info!(target: "bridge", "Submitting ETH ➡ SUB exchange transaction."); - ethereum_exchange_submit::run(match ethereum_exchange_submit_params(eth_exchange_submit_matches) { - Ok(eth_exchange_submit_params) => eth_exchange_submit_params, - Err(err) => { - log::error!(target: "bridge", "Error submitting Eethereum exchange transaction: {}", err); - return; - } - }) + ethereum_exchange_submit::run( + match ethereum_exchange_submit_params(eth_exchange_submit_matches) { + Ok(eth_exchange_submit_params) => eth_exchange_submit_params, + Err(err) => { + log::error!(target: "bridge", "Error submitting Eethereum exchange transaction: {}", err); + return + }, + }, + ) .await; - } + }, ("eth-exchange-sub", Some(eth_exchange_matches)) => { log::info!(target: "bridge", "Starting ETH ➡ SUB exchange transactions relay."); ethereum_exchange::run(match ethereum_exchange_params(eth_exchange_matches) { Ok(eth_exchange_params) => eth_exchange_params, Err(err) => { log::error!(target: "bridge", "Error relaying Ethereum transactions proofs: {}", err); - return; - } + return + }, }) .await; - } + }, ("", _) => { log::error!(target: "bridge", "No subcommand specified"); - } + }, _ => unreachable!("all possible subcommands are checked above; qed"), } } -fn ethereum_connection_params(matches: &clap::ArgMatches) -> Result { +fn ethereum_connection_params( + matches: &clap::ArgMatches, +) -> Result { let mut params = EthereumConnectionParams::default(); if let Some(eth_host) = matches.value_of("eth-host") { params.host = eth_host.into(); } if let Some(eth_port) = matches.value_of("eth-port") { - params.port = eth_port - .parse() - .map_err(|e| format!("Failed to parse eth-port: {}", e))?; + params.port = eth_port.parse().map_err(|e| format!("Failed to parse eth-port: {}", e))?; } Ok(params) } @@ -144,9 +150,10 @@ fn ethereum_connection_params(matches: &clap::ArgMatches) -> Result Result { let mut params = EthereumSigningParams::default(); if let Some(eth_signer) = matches.value_of("eth-signer") { - params.signer = - SecretKey::parse_slice(&hex::decode(eth_signer).map_err(|e| format!("Failed to parse eth-signer: {}", e))?) - .map_err(|e| format!("Invalid eth-signer: {}", e))?; + params.signer = SecretKey::parse_slice( + &hex::decode(eth_signer).map_err(|e| format!("Failed to parse eth-signer: {}", e))?, + ) + .map_err(|e| format!("Invalid eth-signer: {}", e))?; } if let Some(eth_chain_id) = matches.value_of("eth-chain-id") { params.chain_id = eth_chain_id @@ -156,15 +163,15 @@ fn ethereum_signing_params(matches: &clap::ArgMatches) -> Result Result { +fn substrate_connection_params( + matches: &clap::ArgMatches, +) -> Result { let mut params = SubstrateConnectionParams::default(); if let Some(sub_host) = matches.value_of("sub-host") { params.host = sub_host.into(); } if let Some(sub_port) = matches.value_of("sub-port") { - params.port = sub_port - .parse() - .map_err(|e| format!("Failed to parse sub-port: {}", e))?; + params.port = sub_port.parse().map_err(|e| format!("Failed to parse sub-port: {}", e))?; } Ok(params) } @@ -199,7 +206,7 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result sync_params.target_tx_mode = TargetTransactionMode::Backup, Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), None => sync_params.target_tx_mode = TargetTransactionMode::Signed, @@ -252,10 +259,14 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result Result { - let eth_contract_code = parse_hex_argument(matches, "eth-contract-code")?.unwrap_or_else(|| { - hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")).expect("code is hardcoded, thus valid; qed") - }); +fn ethereum_deploy_contract_params( + matches: &clap::ArgMatches, +) -> Result { + let eth_contract_code = + parse_hex_argument(matches, "eth-contract-code")?.unwrap_or_else(|| { + hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")) + .expect("code is hardcoded, thus valid; qed") + }); let sub_initial_authorities_set_id = matches .value_of("sub-authorities-set-id") .map(|set| { @@ -281,7 +292,9 @@ fn ethereum_deploy_contract_params(matches: &clap::ArgMatches) -> Result Result { +fn ethereum_exchange_submit_params( + matches: &clap::ArgMatches, +) -> Result { let eth_nonce = matches .value_of("eth-nonce") .map(|eth_nonce| { @@ -293,9 +306,7 @@ fn ethereum_exchange_submit_params(matches: &clap::ArgMatches) -> Result Result Result Result { let mode = match matches.value_of("eth-tx-hash") { Some(eth_tx_hash) => ethereum_exchange::ExchangeRelayMode::Single( - eth_tx_hash - .parse() - .map_err(|e| format!("Failed to parse eth-tx-hash: {}", e))?, + eth_tx_hash.parse().map_err(|e| format!("Failed to parse eth-tx-hash: {}", e))?, ), None => ethereum_exchange::ExchangeRelayMode::Auto( matches @@ -372,7 +382,7 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result Result { if matches.is_present("no-prometheus") { - return Ok(None.into()); + return Ok(None.into()) } let mut metrics_params = MetricsAddress::default(); @@ -405,9 +415,8 @@ fn instance_params(matches: &clap::ArgMatches) -> Result fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> Result>, String> { match matches.value_of(arg) { - Some(value) => Ok(Some( - hex::decode(value).map_err(|e| format!("Failed to parse {}: {}", arg, e))?, - )), + Some(value) => + Ok(Some(hex::decode(value).map_err(|e| format!("Failed to parse {}: {}", arg, e))?)), None => Ok(None), } } diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs index 35518f5e19cc2..1dadf9f7ddff5 100644 --- a/relays/bin-ethereum/src/rialto_client.rs +++ b/relays/bin-ethereum/src/rialto_client.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::ethereum_sync_loop::QueuedEthereumHeader; -use crate::instances::BridgeInstance; -use crate::rpc_errors::RpcError; +use crate::{ + ethereum_sync_loop::QueuedEthereumHeader, instances::BridgeInstance, rpc_errors::RpcError, +}; use async_trait::async_trait; use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; @@ -24,7 +24,9 @@ use codec::{Decode, Encode}; use headers_relay::sync_types::SubmittedHeaders; use relay_ethereum_client::types::HeaderId as EthereumHeaderId; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client as SubstrateClient, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{ + Client as SubstrateClient, TransactionSignScheme, UnsignedTransaction, +}; use relay_utils::HeaderId; use sp_core::{crypto::Pair, Bytes}; use std::{collections::VecDeque, sync::Arc}; @@ -33,7 +35,8 @@ const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoPoAHeaderApi_is_import_req const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoPoAHeaderApi_is_known_block"; const ETH_API_BEST_BLOCK: &str = "RialtoPoAHeaderApi_best_block"; const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoPoAHeaderApi_finalized_block"; -const EXCH_API_FILTER_TRANSACTION_PROOF: &str = "RialtoCurrencyExchangeApi_filter_transaction_proof"; +const EXCH_API_FILTER_TRANSACTION_PROOF: &str = + "RialtoCurrencyExchangeApi_filter_transaction_proof"; type RpcResult = std::result::Result; @@ -58,7 +61,8 @@ impl SubstrateHighLevelRpc for SubstrateClient { let data = Bytes(Vec::new()); let encoded_response = self.state_call(call, data, None).await?; - let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + let decoded_response: (u64, bp_eth_poa::H256) = + Decode::decode(&mut &encoded_response.0[..])?; let best_header_id = HeaderId(decoded_response.0, decoded_response.1); Ok(best_header_id) @@ -69,7 +73,8 @@ impl SubstrateHighLevelRpc for SubstrateClient { let data = Bytes(Vec::new()); let encoded_response = self.state_call(call, data, None).await?; - let decoded_response: (u64, bp_eth_poa::H256) = Decode::decode(&mut &encoded_response.0[..])?; + let decoded_response: (u64, bp_eth_poa::H256) = + Decode::decode(&mut &encoded_response.0[..])?; let best_header_id = HeaderId(decoded_response.0, decoded_response.1); Ok(best_header_id) @@ -157,17 +162,23 @@ impl SubmitEthereumHeaders for SubstrateClient { let ids = headers.iter().map(|header| header.id()).collect(); let genesis_hash = *self.genesis_hash(); let submission_result = async { - self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |_, transaction_nonce| { - Bytes( - Rialto::sign_transaction( - genesis_hash, - ¶ms, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(instance.build_signed_header_call(headers), transaction_nonce), + self.submit_signed_extrinsic( + (*params.public().as_array_ref()).into(), + move |_, transaction_nonce| { + Bytes( + Rialto::sign_transaction( + genesis_hash, + ¶ms, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + instance.build_signed_header_call(headers), + transaction_nonce, + ), + ) + .encode(), ) - .encode(), - ) - }) + }, + ) .await?; Ok(()) } @@ -209,8 +220,8 @@ impl SubmitEthereumHeaders for SubstrateClient { submitted_headers.rejected.push(id); submitted_headers.rejected.extend(ids); submitted_headers.fatal_error = Some(error.into()); - break; - } + break + }, } } @@ -259,23 +270,31 @@ impl SubmitEthereumExchangeTransactionProof for SubstrateClient { proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, ) -> RpcResult<()> { let genesis_hash = *self.genesis_hash(); - self.submit_signed_extrinsic((*params.public().as_array_ref()).into(), move |_, transaction_nonce| { - Bytes( - Rialto::sign_transaction( - genesis_hash, - ¶ms, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(instance.build_currency_exchange_call(proof), transaction_nonce), + self.submit_signed_extrinsic( + (*params.public().as_array_ref()).into(), + move |_, transaction_nonce| { + Bytes( + Rialto::sign_transaction( + genesis_hash, + ¶ms, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + instance.build_currency_exchange_call(proof), + transaction_nonce, + ), + ) + .encode(), ) - .encode(), - ) - }) + }, + ) .await?; Ok(()) } } /// Create unsigned Substrate transaction for submitting Ethereum header. -fn create_unsigned_submit_transaction(call: rialto_runtime::Call) -> rialto_runtime::UncheckedExtrinsic { +fn create_unsigned_submit_transaction( + call: rialto_runtime::Call, +) -> rialto_runtime::UncheckedExtrinsic { rialto_runtime::UncheckedExtrinsic::new_unsigned(call) } diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs index 7924661244767..4b5bd4fa7326c 100644 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -16,8 +16,7 @@ //! Rialto-Substrate -> Ethereum PoA synchronization. -use crate::ethereum_client::EthereumHighLevelRpc; -use crate::rpc_errors::RpcError; +use crate::{ethereum_client::EthereumHighLevelRpc, rpc_errors::RpcError}; use async_trait::async_trait; use codec::Encode; @@ -38,8 +37,7 @@ use relay_substrate_client::{ use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; use sp_runtime::EncodedJustification; -use std::fmt::Debug; -use std::{collections::HashSet, time::Duration}; +use std::{collections::HashSet, fmt::Debug, time::Duration}; pub mod consts { use super::*; @@ -50,7 +48,8 @@ pub mod consts { pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; /// Max Ethereum headers count we want to have in 'submitted' state. pub const MAX_SUBMITTED_HEADERS: usize = 4; - /// Max depth of in-memory headers in all states. Past this depth they will be forgotten (pruned). + /// Max depth of in-memory headers in all states. Past this depth they will be forgotten + /// (pruned). pub const PRUNE_DEPTH: u32 = 256; } @@ -110,11 +109,7 @@ struct EthereumHeadersTarget { impl EthereumHeadersTarget { fn new(client: EthereumClient, contract: Address, sign_params: EthereumSigningParams) -> Self { - Self { - client, - contract, - sign_params, - } + Self { client, contract, sign_params } } } @@ -137,11 +132,17 @@ impl TargetClient for EthereumHeadersTarget { self.client.best_substrate_block(self.contract).await } - async fn is_known_header(&self, id: RialtoHeaderId) -> Result<(RialtoHeaderId, bool), RpcError> { + async fn is_known_header( + &self, + id: RialtoHeaderId, + ) -> Result<(RialtoHeaderId, bool), RpcError> { self.client.substrate_header_known(self.contract, id).await } - async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { + async fn submit_headers( + &self, + headers: Vec, + ) -> SubmittedHeaders { self.client .submit_substrate_headers(self.sign_params.clone(), self.contract, headers) .await @@ -161,7 +162,10 @@ impl TargetClient for EthereumHeadersTarget { .await } - async fn requires_extra(&self, header: QueuedRialtoHeader) -> Result<(RialtoHeaderId, bool), RpcError> { + async fn requires_extra( + &self, + header: QueuedRialtoHeader, + ) -> Result<(RialtoHeaderId, bool), RpcError> { Ok((header.header().id(), false)) } } diff --git a/relays/bin-ethereum/src/substrate_types.rs b/relays/bin-ethereum/src/substrate_types.rs index af68d7e028555..f9e6c29c6a650 100644 --- a/relays/bin-ethereum/src/substrate_types.rs +++ b/relays/bin-ethereum/src/substrate_types.rs @@ -17,11 +17,12 @@ //! Converting between Ethereum headers and bridge module types. use bp_eth_poa::{ - AuraHeader as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, Receipt as SubstrateEthereumReceipt, - TransactionOutcome as SubstrateEthereumTransactionOutcome, + AuraHeader as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, + Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, }; use relay_ethereum_client::types::{ - Header as EthereumHeader, Receipt as EthereumReceipt, HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, + Header as EthereumHeader, Receipt as EthereumReceipt, + HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, }; /// Convert Ethereum header into Ethereum header for Substrate. @@ -68,7 +69,8 @@ pub fn into_substrate_ethereum_receipt(receipt: &EthereumReceipt) -> SubstrateEt }) .collect(), outcome: match (receipt.status, receipt.root) { - (Some(status), None) => SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), + (Some(status), None) => + SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), _ => SubstrateEthereumTransactionOutcome::Unknown, }, diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 6c7711316626e..f0c11f6abb83f 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -41,41 +41,41 @@ impl CliEncodeCall for Kusama { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { - Call::Remark { remark_payload, .. } => { - relay_kusama_client::runtime::Call::System(relay_kusama_client::runtime::SystemCall::remark( + Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( + relay_kusama_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )) - } - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::KUSAMA_TO_POLKADOT_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::send_message(lane.0, payload, fee.0), - ) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index ), - }, + ), + Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => + match *bridge_instance_index { + bridge::KUSAMA_TO_POLKADOT_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_kusama_client::runtime::Call::BridgePolkadotMessages( + relay_kusama_client::runtime::BridgePolkadotMessagesCall::send_message( + lane.0, payload, fee.0, + ), + ) + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, _ => anyhow::bail!("Unsupported Kusama call: {:?}", call), }) } - fn get_dispatch_info(call: &relay_kusama_client::runtime::Call) -> anyhow::Result { + fn get_dispatch_info( + call: &relay_kusama_client::runtime::Call, + ) -> anyhow::Result { match *call { - relay_kusama_client::runtime::Call::System(relay_kusama_client::runtime::SystemCall::remark(_)) => { - Ok(DispatchInfo { - weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }) - } + relay_kusama_client::runtime::Call::System( + relay_kusama_client::runtime::SystemCall::remark(_), + ) => Ok(DispatchInfo { + weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }), _ => anyhow::bail!("Unsupported Kusama call: {:?}", call), } } @@ -95,7 +95,9 @@ impl CliChain for Kusama { bp_kusama::max_extrinsic_weight() } - fn encode_message(_message: encode_message::MessagePayload) -> Result { + fn encode_message( + _message: encode_message::MessagePayload, + ) -> Result { Err("Sending messages from Kusama is not yet supported.".into()) } } diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index b3b7d956bcc51..1e3cd2ec7d889 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -24,13 +24,15 @@ use relay_kusama_client::{Kusama, SyncHeader as KusamaSyncHeader}; use relay_polkadot_client::{Polkadot, SigningParams as PolkadotSigningParams}; use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. /// -/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 21 DOT, -/// but let's round up to 30 DOT here. +/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 21 +/// DOT, but let's round up to 30 DOT here. pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000; /// Kusama-to-Polkadot finality sync pipeline. @@ -45,7 +47,10 @@ pub(crate) struct KusamaFinalityToPolkadot { impl KusamaFinalityToPolkadot { pub fn new(target_client: Client, target_sign: PolkadotSigningParams) -> Self { Self { - finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot::new(target_client, target_sign), + finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot::new( + target_client, + target_sign, + ), } } } @@ -53,7 +58,8 @@ impl KusamaFinalityToPolkadot { impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { type FinalitySyncPipeline = FinalityPipelineKusamaFinalityToPolkadot; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; type TargetChain = Polkadot; @@ -116,29 +122,36 @@ pub(crate) mod tests { B: From + std::ops::Mul, W: WeightToFeePolynomial, { - // we assume that the GRANDPA is not lagging here => ancestry length will be near to 0 (let's round up to 2) + // we assume that the GRANDPA is not lagging here => ancestry length will be near to 0 + // (let's round up to 2) const AVG_VOTES_ANCESTRIES_LEN: u32 = 2; - // let's assume number of validators is 1024 (more than on any existing well-known chain atm) - // => number of precommits is *2/3 + 1 + // let's assume number of validators is 1024 (more than on any existing well-known chain + // atm) => number of precommits is *2/3 + 1 const AVG_PRECOMMITS_LEN: u32 = 1024 * 2 / 3 + 1; // GRANDPA pallet weights. We're now using Rialto weights everywhere. // - // Using Rialto runtime is slightly incorrect, because `DbWeight` of other runtimes may differ - // from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is the same. - type GrandpaPalletWeights = pallet_bridge_grandpa::weights::RialtoWeight; + // Using Rialto runtime is slightly incorrect, because `DbWeight` of other runtimes may + // differ from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is + // the same. + type GrandpaPalletWeights = + pallet_bridge_grandpa::weights::RialtoWeight; - // The following formula shall not be treated as super-accurate - guard is to protect from mad relays, - // not to protect from over-average loses. + // The following formula shall not be treated as super-accurate - guard is to protect from + // mad relays, not to protect from over-average loses. // increase number of headers a bit let expected_source_headers_per_day = expected_source_headers_per_day * 110 / 100; - let single_source_header_submit_call_weight = - GrandpaPalletWeights::submit_finality_proof(AVG_VOTES_ANCESTRIES_LEN, AVG_PRECOMMITS_LEN); - // for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + adjusted fee + let single_source_header_submit_call_weight = GrandpaPalletWeights::submit_finality_proof( + AVG_VOTES_ANCESTRIES_LEN, + AVG_PRECOMMITS_LEN, + ); + // for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + + // adjusted fee let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2; let single_source_header_tx_cost = W::calc(&single_source_header_submit_tx_weight); - let maximal_expected_decrease = single_source_header_tx_cost * B::from(expected_source_headers_per_day); + let maximal_expected_decrease = + single_source_header_tx_cost * B::from(expected_source_headers_per_day); maximal_expected_decrease } diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 5b07e6d588a6c..e006532d978a4 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -25,17 +25,23 @@ use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; -use relay_kusama_client::{HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams}; -use relay_polkadot_client::{HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams}; +use relay_kusama_client::{ + HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, +}; +use relay_polkadot_client::{ + HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, +}; use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use sp_runtime::{FixedPointNumber, FixedU128}; -use substrate_relay_helper::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, +use substrate_relay_helper::{ + messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, + SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + }, + messages_source::SubstrateMessagesSource, + messages_target::SubstrateMessagesTarget, }; -use substrate_relay_helper::messages_source::SubstrateMessagesSource; -use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Kusama-to-Polkadot message lane. pub type MessageLaneKusamaMessagesToPolkadot = @@ -49,24 +55,32 @@ pub struct KusamaMessagesToPolkadot { impl SubstrateMessageLane for KusamaMessagesToPolkadot { type MessageLane = MessageLaneKusamaMessagesToPolkadot; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = + bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = + bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = + bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = + bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = + bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; type SourceChain = Kusama; type TargetChain = Polkadot; @@ -117,11 +131,7 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { - ref nonces_start, - ref nonces_end, - .. - } = proof; + let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( @@ -180,14 +190,14 @@ pub async fn run( // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using // weights from Rialto and then simply dividing it by x2. let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::< + pallet_bridge_messages::weights::RialtoWeight, + >( bp_polkadot::max_extrinsic_weight(), bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( - max_messages_in_single_batch / 2, - max_messages_weight_in_single_batch / 2, - ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); log::info!( target: "bridge", @@ -219,8 +229,10 @@ pub async fn run( reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_unrewarded_relayer_entries_at_target: + bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: + bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, @@ -252,8 +264,10 @@ pub(crate) fn add_standalone_metrics( metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - let polkadot_to_kusama_conversion_rate_key = - bp_runtime::storage_parameter_key(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME).0; + let polkadot_to_kusama_conversion_rate_key = bp_runtime::storage_parameter_key( + bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME, + ) + .0; substrate_relay_helper::messages_lane::add_standalone_metrics::( metrics_prefix, diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 7a86455df939f..004e4c740a473 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -37,31 +37,26 @@ impl CliEncodeCall for Millau { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, - Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )), + Call::Remark { remark_payload, .. } => + millau_runtime::Call::System(millau_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )), Call::Transfer { recipient, amount } => millau_runtime::Call::Balances( millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount.cast()), ), - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - millau_runtime::Call::BridgeRialtoMessages(millau_runtime::MessagesCall::send_message( - lane.0, - payload, - fee.cast(), - )) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }, + Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => + match *bridge_instance_index { + bridge::MILLAU_TO_RIALTO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + millau_runtime::Call::BridgeRialtoMessages( + millau_runtime::MessagesCall::send_message(lane.0, payload, fee.cast()), + ) + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, }) } @@ -74,7 +69,12 @@ impl CliChain for Millau { const RUNTIME_VERSION: RuntimeVersion = millau_runtime::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload>; + type MessagePayload = MessagePayload< + bp_millau::AccountId, + bp_rialto::AccountSigner, + bp_rialto::Signature, + Vec, + >; fn ss58_format() -> u16 { millau_runtime::SS58Prefix::get() as u16 @@ -85,7 +85,9 @@ impl CliChain for Millau { } // TODO [#854|#843] support multiple bridges? - fn encode_message(message: encode_message::MessagePayload) -> Result { + fn encode_message( + message: encode_message::MessagePayload, + ) -> Result { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), @@ -96,7 +98,10 @@ impl CliChain for Millau { sender.enforce_chain::(); let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::(&mut call, bridge::MILLAU_TO_RIALTO_INDEX); + encode_call::preprocess_call::( + &mut call, + bridge::MILLAU_TO_RIALTO_INDEX, + ); let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; @@ -107,7 +112,7 @@ impl CliChain for Millau { &call, DispatchFeePayment::AtSourceChain, )) - } + }, } } } diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index f0ea225485bd4..e1dc19594f4f2 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -23,10 +23,13 @@ use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; /// Millau-to-Rialto finality sync pipeline. -pub(crate) type FinalityPipelineMillauToRialto = SubstrateFinalityToSubstrate; +pub(crate) type FinalityPipelineMillauToRialto = + SubstrateFinalityToSubstrate; #[derive(Clone, Debug)] pub(crate) struct MillauFinalityToRialto { @@ -35,16 +38,15 @@ pub(crate) struct MillauFinalityToRialto { impl MillauFinalityToRialto { pub fn new(target_client: Client, target_sign: RialtoSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineMillauToRialto::new(target_client, target_sign), - } + Self { finality_pipeline: FinalityPipelineMillauToRialto::new(target_client, target_sign) } } } impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { type FinalitySyncPipeline = FinalityPipelineMillauToRialto; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; type TargetChain = Rialto; @@ -59,8 +61,11 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { header: MillauSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = - rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof(Box::new(header.into_inner()), proof).into(); + let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof( + Box::new(header.into_inner()), + proof, + ) + .into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); let transaction = Rialto::sign_transaction( diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index b0c63ff088365..7682f32e608e4 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -26,16 +26,22 @@ use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; -use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; +use relay_millau_client::{ + HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, +}; +use relay_rialto_client::{ + HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, +}; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, +use substrate_relay_helper::{ + messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, + SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + }, + messages_source::SubstrateMessagesSource, + messages_target::SubstrateMessagesTarget, }; -use substrate_relay_helper::messages_source::SubstrateMessagesSource; -use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Millau-to-Rialto message lane. pub type MessageLaneMillauMessagesToRialto = @@ -49,23 +55,30 @@ pub struct MillauMessagesToRialto { impl SubstrateMessageLane for MillauMessagesToRialto { type MessageLane = MessageLaneMillauMessagesToRialto; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = + bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = + bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; type SourceChain = Millau; type TargetChain = Rialto; @@ -82,7 +95,8 @@ impl SubstrateMessageLane for MillauMessagesToRialto { ) -> Bytes { let (relayers_state, proof) = proof; let call: millau_runtime::Call = - millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); + millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state) + .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.source_client.genesis_hash(); let transaction = Millau::sign_transaction( @@ -114,11 +128,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { - ref nonces_start, - ref nonces_end, - .. - } = proof; + let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof( self.message_lane.relayer_id_at_source.clone(), @@ -176,7 +186,9 @@ pub async fn run( let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3; // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::< + pallet_bridge_messages::weights::RialtoWeight, + >( bp_rialto::max_extrinsic_weight(), bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); @@ -211,8 +223,10 @@ pub async fn run( reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_unrewarded_relayer_entries_at_target: + bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: + bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, @@ -251,7 +265,9 @@ pub(crate) fn add_standalone_metrics( Some(crate::chains::MILLAU_ASSOCIATED_TOKEN_ID), Some(crate::chains::RIALTO_ASSOCIATED_TOKEN_ID), Some(( - sp_core::storage::StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), + sp_core::storage::StorageKey( + millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec(), + ), millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, )), ) diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index bdc4f2628ee56..ea7c9754ec72a 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -38,9 +38,9 @@ mod rococo; mod westend; mod wococo; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we want to -// test our code that is intended to work with real-value chains. So to keep it close to 1:1, we'll be treating -// Rialto as BTC and Millau as wBTC (only in relayer). +// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we +// want to test our code that is intended to work with real-value chains. So to keep it close to +// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). /// The identifier of token, which value is associated with Rialto token value by relayer. pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = polkadot::TOKEN_ID; @@ -53,8 +53,8 @@ pub(crate) fn add_polkadot_kusama_price_metrics, params: MetricsParams, ) -> anyhow::Result { - // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama - // relays, but we want to test metrics/dashboards in advance + // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> + // Kusama relays, but we want to test metrics/dashboards in advance Ok(relay_utils::relay_metrics(prefix, params) .standalone_metric(|registry, prefix| { substrate_relay_helper::helpers::token_price_metric(registry, prefix, "polkadot") @@ -92,7 +92,8 @@ mod tests { rialto_runtime::VERSION.spec_version, ); - let rialto_signer = relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); + let rialto_signer = + relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); let signature = rialto_signer.sign(&digest); assert!(signature.verify(&digest[..], &rialto_signer.public())); @@ -113,7 +114,8 @@ mod tests { millau_runtime::VERSION.spec_version, ); - let millau_signer = relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); + let millau_signer = + relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); let signature = millau_signer.sign(&digest); assert!(signature.verify(&digest[..], &millau_signer.public())); @@ -128,7 +130,8 @@ mod tests { bp_millau::max_extrinsic_size(), ); - let call: millau_runtime::Call = millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); + let call: millau_runtime::Call = + millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, @@ -164,8 +167,9 @@ mod tests { fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() { use rialto_runtime::millau_messages::Millau; - let maximal_dispatch_weight = - send_message::compute_maximal_message_dispatch_weight(bp_millau::max_extrinsic_weight()); + let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( + bp_millau::max_extrinsic_weight(), + ); let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); let payload = send_message::message_payload( @@ -191,8 +195,9 @@ mod tests { fn maximal_weight_fill_block_to_rialto_is_generated_correctly() { use millau_runtime::rialto_messages::Rialto; - let maximal_dispatch_weight = - send_message::compute_maximal_message_dispatch_weight(bp_rialto::max_extrinsic_weight()); + let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( + bp_rialto::max_extrinsic_weight(), + ); let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); let payload = send_message::message_payload( @@ -325,7 +330,10 @@ mod westend_tests { votes_ancestries: vec![], }; - let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof(header.clone(), justification.clone()); + let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof( + header.clone(), + justification.clone(), + ); let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( Box::new(header), justification, diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 372bdb90efcb4..6baeb50c14a35 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -41,41 +41,41 @@ impl CliEncodeCall for Polkadot { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { - Call::Remark { remark_payload, .. } => { - relay_polkadot_client::runtime::Call::System(relay_polkadot_client::runtime::SystemCall::remark( + Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( + relay_polkadot_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )) - } - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::POLKADOT_TO_KUSAMA_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::send_message(lane.0, payload, fee.0), - ) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index ), - }, + ), + Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => + match *bridge_instance_index { + bridge::POLKADOT_TO_KUSAMA_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_polkadot_client::runtime::Call::BridgeKusamaMessages( + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::send_message( + lane.0, payload, fee.0, + ), + ) + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, _ => anyhow::bail!("Unsupported Polkadot call: {:?}", call), }) } - fn get_dispatch_info(call: &relay_polkadot_client::runtime::Call) -> anyhow::Result { + fn get_dispatch_info( + call: &relay_polkadot_client::runtime::Call, + ) -> anyhow::Result { match *call { - relay_polkadot_client::runtime::Call::System(relay_polkadot_client::runtime::SystemCall::remark(_)) => { - Ok(DispatchInfo { - weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }) - } + relay_polkadot_client::runtime::Call::System( + relay_polkadot_client::runtime::SystemCall::remark(_), + ) => Ok(DispatchInfo { + weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }), _ => anyhow::bail!("Unsupported Polkadot call: {:?}", call), } } @@ -95,7 +95,9 @@ impl CliChain for Polkadot { bp_polkadot::max_extrinsic_weight() } - fn encode_message(_message: encode_message::MessagePayload) -> Result { + fn encode_message( + _message: encode_message::MessagePayload, + ) -> Result { Err("Sending messages from Polkadot is not yet supported.".into()) } } diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index c225b77d546aa..603d5ba3aa779 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -24,13 +24,15 @@ use relay_kusama_client::{Kusama, SigningParams as KusamaSigningParams}; use relay_polkadot_client::{Polkadot, SyncHeader as PolkadotSyncHeader}; use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. /// -/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 0.001 KSM, -/// but let's round up to 0.1 KSM here. +/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 0.001 +/// KSM, but let's round up to 0.1 KSM here. pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000; /// Polkadot-to-Kusama finality sync pipeline. @@ -45,7 +47,10 @@ pub(crate) struct PolkadotFinalityToKusama { impl PolkadotFinalityToKusama { pub fn new(target_client: Client, target_sign: KusamaSigningParams) -> Self { Self { - finality_pipeline: FinalityPipelinePolkadotFinalityToKusama::new(target_client, target_sign), + finality_pipeline: FinalityPipelinePolkadotFinalityToKusama::new( + target_client, + target_sign, + ), } } } @@ -53,7 +58,8 @@ impl PolkadotFinalityToKusama { impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { type FinalitySyncPipeline = FinalityPipelinePolkadotFinalityToKusama; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; type TargetChain = Kusama; diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 092a02598d1b4..71943af44da36 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -25,17 +25,23 @@ use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; -use relay_kusama_client::{HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams}; -use relay_polkadot_client::{HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams}; +use relay_kusama_client::{ + HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, +}; +use relay_polkadot_client::{ + HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, +}; use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use sp_runtime::{FixedPointNumber, FixedU128}; -use substrate_relay_helper::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, +use substrate_relay_helper::{ + messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, + SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + }, + messages_source::SubstrateMessagesSource, + messages_target::SubstrateMessagesTarget, }; -use substrate_relay_helper::messages_source::SubstrateMessagesSource; -use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Polkadot-to-Kusama message lane. pub type MessageLanePolkadotMessagesToKusama = @@ -48,24 +54,32 @@ pub struct PolkadotMessagesToKusama { impl SubstrateMessageLane for PolkadotMessagesToKusama { type MessageLane = MessageLanePolkadotMessagesToKusama; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = + bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = + bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = + bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = + bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; + const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = + bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = + bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; type SourceChain = Polkadot; type TargetChain = Kusama; @@ -116,11 +130,7 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { - ref nonces_start, - ref nonces_end, - .. - } = proof; + let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( @@ -179,14 +189,14 @@ pub async fn run( // we don't know exact weights of the Kusama runtime. So to guess weights we'll be using // weights from Rialto and then simply dividing it by x2. let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::< + pallet_bridge_messages::weights::RialtoWeight, + >( bp_kusama::max_extrinsic_weight(), bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( - max_messages_in_single_batch / 2, - max_messages_weight_in_single_batch / 2, - ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); log::info!( target: "bridge", @@ -218,8 +228,10 @@ pub async fn run( reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_unrewarded_relayer_entries_at_target: + bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: + bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, @@ -251,8 +263,10 @@ pub(crate) fn add_standalone_metrics( metrics_params: MetricsParams, source_client: Client, ) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - let kusama_to_polkadot_conversion_rate_key = - bp_runtime::storage_parameter_key(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME).0; + let kusama_to_polkadot_conversion_rate_key = bp_runtime::storage_parameter_key( + bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME, + ) + .0; substrate_relay_helper::messages_lane::add_standalone_metrics::( metrics_prefix, diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 2e27342baa3ee..0575896d97fdb 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -37,29 +37,26 @@ impl CliEncodeCall for Rialto { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, - Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )), + Call::Remark { remark_payload, .. } => + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + )), Call::Transfer { recipient, amount } => rialto_runtime::Call::Balances( rialto_runtime::BalancesCall::transfer(recipient.raw_id().into(), amount.0), ), - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - rialto_runtime::Call::BridgeMillauMessages(rialto_runtime::MessagesCall::send_message( - lane.0, payload, fee.0, - )) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }, + Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => + match *bridge_instance_index { + bridge::RIALTO_TO_MILLAU_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + rialto_runtime::Call::BridgeMillauMessages( + rialto_runtime::MessagesCall::send_message(lane.0, payload, fee.0), + ) + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, }) } @@ -72,7 +69,12 @@ impl CliChain for Rialto { const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload>; + type MessagePayload = MessagePayload< + bp_rialto::AccountId, + bp_millau::AccountSigner, + bp_millau::Signature, + Vec, + >; fn ss58_format() -> u16 { rialto_runtime::SS58Prefix::get() as u16 @@ -82,7 +84,9 @@ impl CliChain for Rialto { bp_rialto::max_extrinsic_weight() } - fn encode_message(message: encode_message::MessagePayload) -> Result { + fn encode_message( + message: encode_message::MessagePayload, + ) -> Result { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), @@ -93,7 +97,10 @@ impl CliChain for Rialto { sender.enforce_chain::(); let spec_version = Target::RUNTIME_VERSION.spec_version; let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::(&mut call, bridge::RIALTO_TO_MILLAU_INDEX); + encode_call::preprocess_call::( + &mut call, + bridge::RIALTO_TO_MILLAU_INDEX, + ); let call = Target::encode_call(&call).map_err(|e| e.to_string())?; let weight = call.get_dispatch_info().weight; @@ -104,7 +111,7 @@ impl CliChain for Rialto { &call, DispatchFeePayment::AtSourceChain, )) - } + }, } } } diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index df0f17d94431a..79ce6160b87f6 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -23,7 +23,9 @@ use bp_header_chain::justification::GrandpaJustification; use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; /// Rialto-to-Millau finality sync pipeline. pub(crate) type FinalityPipelineRialtoFinalityToMillau = @@ -37,7 +39,10 @@ pub struct RialtoFinalityToMillau { impl RialtoFinalityToMillau { pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { Self { - finality_pipeline: FinalityPipelineRialtoFinalityToMillau::new(target_client, target_sign), + finality_pipeline: FinalityPipelineRialtoFinalityToMillau::new( + target_client, + target_sign, + ), } } } @@ -45,7 +50,8 @@ impl RialtoFinalityToMillau { impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { type FinalitySyncPipeline = FinalityPipelineRialtoFinalityToMillau; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; type TargetChain = Millau; diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 0196329fb812d..529f14b84a3da 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -26,16 +26,22 @@ use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; -use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; +use relay_millau_client::{ + HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, +}; +use relay_rialto_client::{ + HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, +}; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, +use substrate_relay_helper::{ + messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, + SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + }, + messages_source::SubstrateMessagesSource, + messages_target::SubstrateMessagesTarget, }; -use substrate_relay_helper::messages_source::SubstrateMessagesSource; -use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Rialto-to-Millau message lane. pub type MessageLaneRialtoMessagesToMillau = @@ -49,23 +55,30 @@ pub struct RialtoMessagesToMillau { impl SubstrateMessageLane for RialtoMessagesToMillau { type MessageLane = MessageLaneRialtoMessagesToMillau; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = + bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = + bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = + bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; type SourceChain = Rialto; type TargetChain = Millau; @@ -82,7 +95,8 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { ) -> Bytes { let (relayers_state, proof) = proof; let call: rialto_runtime::Call = - rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state).into(); + rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state) + .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.source_client.genesis_hash(); let transaction = Rialto::sign_transaction( @@ -114,11 +128,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { - ref nonces_start, - ref nonces_end, - .. - } = proof; + let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof( self.message_lane.relayer_id_at_source.clone(), @@ -175,7 +185,9 @@ pub async fn run( // 2/3 is reserved for proofs and tx overhead let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3; let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::< + pallet_bridge_messages::weights::RialtoWeight, + >( bp_millau::max_extrinsic_weight(), bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); @@ -210,8 +222,10 @@ pub async fn run( reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_unrewarded_relayer_entries_at_target: + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: + bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, @@ -250,7 +264,9 @@ pub(crate) fn add_standalone_metrics( Some(crate::chains::RIALTO_ASSOCIATED_TOKEN_ID), Some(crate::chains::MILLAU_ASSOCIATED_TOKEN_ID), Some(( - sp_core::storage::StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), + sp_core::storage::StorageKey( + rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec(), + ), rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, )), ) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index ec34d9cd33fc7..ddd0b6cc13b12 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -38,41 +38,41 @@ impl CliEncodeCall for Rococo { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { - Call::Remark { remark_payload, .. } => { - relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark( + Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( + relay_rococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )) - } - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::ROCOCO_TO_WOCOCO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message(lane.0, payload, fee.0), - ) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index ), - }, + ), + Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => + match *bridge_instance_index { + bridge::ROCOCO_TO_WOCOCO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_rococo_client::runtime::Call::BridgeMessagesWococo( + relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message( + lane.0, payload, fee.0, + ), + ) + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, _ => anyhow::bail!("The call is not supported"), }) } - fn get_dispatch_info(call: &relay_rococo_client::runtime::Call) -> anyhow::Result { + fn get_dispatch_info( + call: &relay_rococo_client::runtime::Call, + ) -> anyhow::Result { match *call { - relay_rococo_client::runtime::Call::System(relay_rococo_client::runtime::SystemCall::remark(_)) => { - Ok(DispatchInfo { - weight: SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }) - } + relay_rococo_client::runtime::Call::System( + relay_rococo_client::runtime::SystemCall::remark(_), + ) => Ok(DispatchInfo { + weight: SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }), _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), } } @@ -92,7 +92,9 @@ impl CliChain for Rococo { bp_wococo::max_extrinsic_weight() } - fn encode_message(_message: encode_message::MessagePayload) -> Result { + fn encode_message( + _message: encode_message::MessagePayload, + ) -> Result { Err("Sending messages from Rococo is not yet supported.".into()) } } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 269dead8dc231..25fd97a90bab9 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -24,7 +24,9 @@ use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; @@ -40,7 +42,10 @@ pub(crate) struct RococoFinalityToWococo { impl RococoFinalityToWococo { pub fn new(target_client: Client, target_sign: WococoSigningParams) -> Self { Self { - finality_pipeline: FinalityPipelineRococoFinalityToWococo::new(target_client, target_sign), + finality_pipeline: FinalityPipelineRococoFinalityToWococo::new( + target_client, + target_sign, + ), } } } @@ -48,7 +53,8 @@ impl RococoFinalityToWococo { impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { type FinalitySyncPipeline = FinalityPipelineRococoFinalityToWococo; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; type TargetChain = Wococo; diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index de2d8c7263e5c..e26adcb9a27b1 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -25,16 +25,22 @@ use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; -use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; +use relay_rococo_client::{ + HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, +}; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; -use substrate_relay_helper::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, +use relay_wococo_client::{ + HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, +}; +use substrate_relay_helper::{ + messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, + SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + }, + messages_source::SubstrateMessagesSource, + messages_target::SubstrateMessagesTarget, }; -use substrate_relay_helper::messages_source::SubstrateMessagesSource; -use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Rococo-to-Wococo message lane. pub type MessageLaneRococoMessagesToWococo = @@ -48,23 +54,30 @@ pub struct RococoMessagesToWococo { impl SubstrateMessageLane for RococoMessagesToWococo { type MessageLane = MessageLaneRococoMessagesToWococo; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = + bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = + bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = + bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = + bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; type SourceChain = Rococo; type TargetChain = Wococo; @@ -115,11 +128,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { - ref nonces_start, - ref nonces_end, - .. - } = proof; + let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( @@ -178,14 +187,14 @@ pub async fn run( // we don't know exact weights of the Wococo runtime. So to guess weights we'll be using // weights from Rialto and then simply dividing it by x2. let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::< + pallet_bridge_messages::weights::RialtoWeight, + >( bp_wococo::max_extrinsic_weight(), bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( - max_messages_in_single_batch / 2, - max_messages_weight_in_single_batch / 2, - ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); log::info!( target: "bridge", @@ -217,8 +226,10 @@ pub async fn run( reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_unrewarded_relayer_entries_at_target: + bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: + bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 27621472d6d99..586e6ffd95760 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -35,7 +35,9 @@ impl CliChain for Westend { 0 } - fn encode_message(_message: encode_message::MessagePayload) -> Result { + fn encode_message( + _message: encode_message::MessagePayload, + ) -> Result { Err("Sending messages from Westend is not yet supported.".into()) } } diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 4a5e48b51eeab..1ea8fc7dd794e 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -24,7 +24,9 @@ use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; /// Westend-to-Millau finality sync pipeline. pub(crate) type FinalityPipelineWestendFinalityToMillau = @@ -38,7 +40,10 @@ pub(crate) struct WestendFinalityToMillau { impl WestendFinalityToMillau { pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { Self { - finality_pipeline: FinalityPipelineWestendFinalityToMillau::new(target_client, target_sign), + finality_pipeline: FinalityPipelineWestendFinalityToMillau::new( + target_client, + target_sign, + ), } } } @@ -46,7 +51,8 @@ impl WestendFinalityToMillau { impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type FinalitySyncPipeline = FinalityPipelineWestendFinalityToMillau; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; type TargetChain = Millau; diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 9b944d781685d..fbdbcf868c7c4 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -32,41 +32,41 @@ impl CliEncodeCall for Wococo { fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { - Call::Remark { remark_payload, .. } => { - relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark( + Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( + relay_wococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )) - } - Call::BridgeSendMessage { - lane, - payload, - fee, - bridge_instance_index, - } => match *bridge_instance_index { - bridge::WOCOCO_TO_ROCOCO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message(lane.0, payload, fee.0), - ) - } - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index ), - }, + ), + Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => + match *bridge_instance_index { + bridge::WOCOCO_TO_ROCOCO_INDEX => { + let payload = Decode::decode(&mut &*payload.0)?; + relay_wococo_client::runtime::Call::BridgeMessagesRococo( + relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message( + lane.0, payload, fee.0, + ), + ) + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }, _ => anyhow::bail!("The call is not supported"), }) } - fn get_dispatch_info(call: &relay_wococo_client::runtime::Call) -> anyhow::Result { + fn get_dispatch_info( + call: &relay_wococo_client::runtime::Call, + ) -> anyhow::Result { match *call { - relay_wococo_client::runtime::Call::System(relay_wococo_client::runtime::SystemCall::remark(_)) => { - Ok(DispatchInfo { - weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }) - } + relay_wococo_client::runtime::Call::System( + relay_wococo_client::runtime::SystemCall::remark(_), + ) => Ok(DispatchInfo { + weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }), _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), } } @@ -86,7 +86,9 @@ impl CliChain for Wococo { bp_wococo::max_extrinsic_weight() } - fn encode_message(_message: encode_message::MessagePayload) -> Result { + fn encode_message( + _message: encode_message::MessagePayload, + ) -> Result { Err("Sending messages from Wococo is not yet supported.".into()) } } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 74152cdff6d41..8e11698c1bb66 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -24,7 +24,9 @@ use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate}; +use substrate_relay_helper::finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, +}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -45,7 +47,10 @@ pub(crate) struct WococoFinalityToRococo { impl WococoFinalityToRococo { pub fn new(target_client: Client, target_sign: RococoSigningParams) -> Self { Self { - finality_pipeline: FinalityPipelineWococoFinalityToRococo::new(target_client, target_sign), + finality_pipeline: FinalityPipelineWococoFinalityToRococo::new( + target_client, + target_sign, + ), } } } @@ -53,7 +58,8 @@ impl WococoFinalityToRococo { impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { type FinalitySyncPipeline = FinalityPipelineWococoFinalityToRococo; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; type TargetChain = Rococo; @@ -113,8 +119,10 @@ mod tests { #[test] fn maximal_balance_decrease_per_day_is_sane() { // we expect Wococo -> Rococo relay to be running in all-headers mode - let maximal_balance_decrease = - compute_maximal_balance_decrease_per_day::(bp_wococo::DAYS); + let maximal_balance_decrease = compute_maximal_balance_decrease_per_day::< + bp_kusama::Balance, + bp_kusama::WeightToFee, + >(bp_wococo::DAYS); assert!( MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, "Maximal expected loss per day {} is larger than hardcoded {}", diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 035c8f3948365..4d1fc4f0d815b 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -25,16 +25,22 @@ use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; use messages_relay::message_lane::MessageLane; -use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; +use relay_rococo_client::{ + HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, +}; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; -use substrate_relay_helper::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, - SubstrateMessageLaneToSubstrate, +use relay_wococo_client::{ + HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, +}; +use substrate_relay_helper::{ + messages_lane::{ + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, + SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + }, + messages_source::SubstrateMessagesSource, + messages_target::SubstrateMessagesTarget, }; -use substrate_relay_helper::messages_source::SubstrateMessagesSource; -use substrate_relay_helper::messages_target::SubstrateMessagesTarget; /// Wococo-to-Rococo message lane. pub type MessageLaneWococoMessagesToRococo = @@ -47,23 +53,30 @@ pub struct WococoMessagesToRococo { impl SubstrateMessageLane for WococoMessagesToRococo { type MessageLane = MessageLaneWococoMessagesToRococo; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = + bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; + const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = + bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; + const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = + bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; + const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = + bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = + bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; type SourceChain = Wococo; type TargetChain = Rococo; @@ -114,11 +127,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { proof: ::MessagesProof, ) -> Bytes { let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { - ref nonces_start, - ref nonces_end, - .. - } = proof; + let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( @@ -177,14 +186,14 @@ pub async fn run( // we don't know exact weights of the Rococo runtime. So to guess weights we'll be using // weights from Rialto and then simply dividing it by x2. let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::>( + select_delivery_transaction_limits::< + pallet_bridge_messages::weights::RialtoWeight, + >( bp_rococo::max_extrinsic_weight(), bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = ( - max_messages_in_single_batch / 2, - max_messages_weight_in_single_batch / 2, - ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); log::info!( target: "bridge", @@ -216,8 +225,10 @@ pub async fn run( reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + max_unrewarded_relayer_entries_at_target: + bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + max_unconfirmed_nonces_at_target: + bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs index 1903d42c1fcb0..5b809eb69f222 100644 --- a/relays/bin-substrate/src/cli/derive_account.rs +++ b/relays/bin-substrate/src/cli/derive_account.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{bridge::FullBridge, AccountId}; -use crate::select_full_bridge; +use crate::{ + cli::{bridge::FullBridge, AccountId}, + select_full_bridge, +}; use relay_substrate_client::Chain; use structopt::StructOpt; use strum::VariantNames; @@ -55,11 +57,7 @@ impl DeriveAccount { select_full_bridge!(self.bridge, { let (account, derived_account) = self.derive_account(); println!("Source address:\n{} ({})", account, Source::NAME); - println!( - "->Corresponding (derived) address:\n{} ({})", - derived_account, - Target::NAME, - ); + println!("->Corresponding (derived) address:\n{} ({})", derived_account, Target::NAME,); Ok(()) }) diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 23ea4b80738ea..5973faab569e0 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -14,9 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::bridge::FullBridge; -use crate::cli::{AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId}; -use crate::select_full_bridge; +use crate::{ + cli::{ + bridge::FullBridge, AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, + }, + select_full_bridge, +}; use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -126,31 +129,30 @@ pub(crate) fn preprocess_call {} - Call::Remark { - ref remark_size, - ref mut remark_payload, - } => { + Call::Raw { .. } => {}, + Call::Remark { ref remark_size, ref mut remark_payload } => if remark_payload.is_none() { *remark_payload = Some(HexBytes(generate_remark_payload( remark_size, - compute_maximal_message_arguments_size(Source::max_extrinsic_size(), Target::max_extrinsic_size()), + compute_maximal_message_arguments_size( + Source::max_extrinsic_size(), + Target::max_extrinsic_size(), + ), ))); - } - } + }, Call::Transfer { ref mut recipient, .. } => { recipient.enforce_chain::(); - } - Call::BridgeSendMessage { - ref mut bridge_instance_index, - .. - } => { + }, + Call::BridgeSendMessage { ref mut bridge_instance_index, .. } => { *bridge_instance_index = bridge_instance; - } + }, }; } -fn generate_remark_payload(remark_size: &Option>, maximal_allowed_size: u32) -> Vec { +fn generate_remark_payload( + remark_size: &Option>, + maximal_allowed_size: u32, +) -> Vec { match remark_size { Some(ExplicitOrMaximal::Explicit(remark_size)) => vec![0; *remark_size], Some(ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], @@ -172,9 +174,11 @@ pub(crate) fn compute_maximal_message_arguments_size( ) -> u32 { // assume that both signed extensions and other arguments fit 1KB let service_tx_bytes_on_source_chain = 1024; - let maximal_source_extrinsic_size = maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; - let maximal_call_size = - bridge_runtime_common::messages::target::maximal_incoming_message_size(maximal_target_extrinsic_size); + let maximal_source_extrinsic_size = + maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; + let maximal_call_size = bridge_runtime_common::messages::target::maximal_incoming_message_size( + maximal_target_extrinsic_size, + ); let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { maximal_source_extrinsic_size } else { @@ -217,7 +221,8 @@ mod tests { #[test] fn should_encode_remark_with_default_payload() { // given - let mut encode_call = EncodeCall::from_iter(vec!["encode-call", "rialto-to-millau", "remark"]); + let mut encode_call = + EncodeCall::from_iter(vec!["encode-call", "rialto-to-millau", "remark"]); // when let hex = encode_call.encode().unwrap(); @@ -247,8 +252,13 @@ mod tests { #[test] fn should_encode_remark_with_size() { // given - let mut encode_call = - EncodeCall::from_iter(vec!["encode-call", "rialto-to-millau", "remark", "--remark-size", "12"]); + let mut encode_call = EncodeCall::from_iter(vec![ + "encode-call", + "rialto-to-millau", + "remark", + "--remark-size", + "12", + ]); // when let hex = encode_call.encode().unwrap(); @@ -275,7 +285,10 @@ mod tests { assert_eq!(err.kind, structopt::clap::ErrorKind::ArgumentConflict); let info = err.info.unwrap(); - assert!(info.contains(&"remark-payload".to_string()) | info.contains(&"remark-size".to_string())) + assert!( + info.contains(&"remark-payload".to_string()) | + info.contains(&"remark-size".to_string()) + ) } #[test] diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 36a4806976ef6..98e1269aa68e6 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}; -use crate::select_full_bridge; +use crate::{ + cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}, + select_full_bridge, +}; use structopt::StructOpt; use strum::VariantNames; @@ -52,7 +54,8 @@ impl EncodeMessage { /// Run the command. pub fn encode(self) -> anyhow::Result { select_full_bridge!(self.bridge, { - let payload = Source::encode_message(self.payload).map_err(|e| anyhow::format_err!("{}", e))?; + let payload = + Source::encode_message(self.payload).map_err(|e| anyhow::format_err!("{}", e))?; Ok(HexBytes::encode(&payload)) }) } @@ -74,7 +77,8 @@ mod tests { fn should_encode_raw_message() { // given let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"; - let encode_message = EncodeMessage::from_iter(vec!["encode-message", "rialto-to-millau", "raw", msg]); + let encode_message = + EncodeMessage::from_iter(vec!["encode-message", "rialto-to-millau", "raw", msg]); // when let hex = encode_message.encode().unwrap(); diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 7e4cbf5b6b8ff..d063ce544cd24 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::bridge::FullBridge; -use crate::cli::{Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}; -use crate::select_full_bridge; +use crate::{ + cli::{bridge::FullBridge, Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}, + select_full_bridge, +}; use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; @@ -42,21 +43,21 @@ pub struct EstimateFee { impl EstimateFee { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - let Self { - source, - bridge, - lane, - payload, - } = self; + let Self { source, bridge, lane, payload } = self; select_full_bridge!(bridge, { let source_client = source.to_client::().await?; let lane = lane.into(); - let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; + let payload = + Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; - let fee: BalanceOf = - estimate_message_delivery_and_dispatch_fee(&source_client, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload) - .await?; + let fee: BalanceOf = estimate_message_delivery_and_dispatch_fee( + &source_client, + ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; log::info!(target: "bridge", "Fee: {:?}", Balance(fee as _)); println!("{}", fee); @@ -74,10 +75,11 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee = - Decode::decode(&mut &encoded_response.0[..]).map_err(relay_substrate_client::Error::ResponseParseFailed)?; - let fee = decoded_response - .ok_or_else(|| anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())))?; + let decoded_response: Option = Decode::decode(&mut &encoded_response.0[..]) + .map_err(relay_substrate_client::Error::ResponseParseFailed)?; + let fee = decoded_response.ok_or_else(|| { + anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())) + })?; Ok(fee) } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 3e464e6f54556..f1c957f5e217d 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -67,7 +67,7 @@ macro_rules! select_bridge { } $generic - } + }, InitBridgeName::RialtoToMillau => { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; @@ -83,7 +83,7 @@ macro_rules! select_bridge { } $generic - } + }, InitBridgeName::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; @@ -91,9 +91,10 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - // at Westend -> Millau initialization we're not using sudo, because otherwise our deployments - // may fail, because we need to initialize both Rialto -> Millau and Westend -> Millau bridge. - // => since there's single possible sudo account, one of transaction may fail with duplicate nonce error + // at Westend -> Millau initialization we're not using sudo, because otherwise + // our deployments may fail, because we need to initialize both Rialto -> Millau + // and Westend -> Millau bridge. => since there's single possible sudo account, + // one of transaction may fail with duplicate nonce error millau_runtime::BridgeGrandpaWestendCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, @@ -102,7 +103,7 @@ macro_rules! select_bridge { } $generic - } + }, InitBridgeName::RococoToWococo => { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; @@ -111,12 +112,14 @@ macro_rules! select_bridge { init_data: InitializationData<::Header>, ) -> ::Call { relay_wococo_client::runtime::Call::BridgeGrandpaRococo( - relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), + relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize( + init_data, + ), ) } $generic - } + }, InitBridgeName::WococoToRococo => { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; @@ -125,12 +128,14 @@ macro_rules! select_bridge { init_data: InitializationData<::Header>, ) -> ::Call { relay_rococo_client::runtime::Call::BridgeGrandpaWococo( - relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize(init_data), + relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize( + init_data, + ), ) } $generic - } + }, InitBridgeName::KusamaToPolkadot => { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; @@ -139,12 +144,14 @@ macro_rules! select_bridge { init_data: InitializationData<::Header>, ) -> ::Call { relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize(init_data), + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize( + init_data, + ), ) } $generic - } + }, InitBridgeName::PolkadotToKusama => { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; @@ -153,12 +160,14 @@ macro_rules! select_bridge { init_data: InitializationData<::Header>, ) -> ::Call { relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize(init_data), + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize( + init_data, + ), ) } $generic - } + }, } }; } @@ -181,7 +190,10 @@ impl InitBridge { *target_client.genesis_hash(), &target_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(encode_init_bridge(initialization_data), transaction_nonce), + UnsignedTransaction::new( + encode_init_bridge(initialization_data), + transaction_nonce, + ), ) .encode(), ) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index ac072de3056f2..97998a33d35bf 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -86,7 +86,8 @@ pub enum Command { EncodeMessage(encode_message::EncodeMessage), /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. EstimateFee(estimate_fee::EstimateFee), - /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. + /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target + /// chain. DeriveAccount(derive_account::DeriveAccount), /// Resubmit transactions with increased tip if they are stalled. ResubmitTransactions(resubmit_transactions::ResubmitTransactions), @@ -100,12 +101,15 @@ impl Command { use relay_utils::initialize::{initialize_logger, initialize_relay}; match self { - Self::RelayHeaders(_) | Self::RelayMessages(_) | Self::RelayHeadersAndMessages(_) | Self::InitBridge(_) => { + Self::RelayHeaders(_) | + Self::RelayMessages(_) | + Self::RelayHeadersAndMessages(_) | + Self::InitBridge(_) => { initialize_relay(); - } + }, _ => { initialize_logger(false); - } + }, } } @@ -195,10 +199,7 @@ const SS58_FORMAT_PROOF: &str = "u16 -> Ss58Format is infallible; qed"; impl AccountId { /// Create new SS58-formatted address from raw account id. pub fn from_raw(account: sp_runtime::AccountId32) -> Self { - Self { - account, - ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF), - } + Self { account, ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF) } } /// Enforces formatting account to be for given [`CliChain`] type. @@ -236,7 +237,7 @@ pub trait CliChain: relay_substrate_client::Chain { /// Chain's current version of the runtime. const RUNTIME_VERSION: sp_version::RuntimeVersion; - /// Crypto keypair type used to send messages. + /// Crypto KeyPair type used to send messages. /// /// In case of chains supporting multiple cryptos, pick one used by the CLI. type KeyPair: sp_core::crypto::Pair; @@ -250,7 +251,9 @@ pub trait CliChain: relay_substrate_client::Chain { fn ss58_format() -> u16; /// Construct message payload to be sent over the bridge. - fn encode_message(message: crate::cli::encode_message::MessagePayload) -> Result; + fn encode_message( + message: crate::cli::encode_message::MessagePayload, + ) -> Result; /// Maximal extrinsic weight (from the runtime). fn max_extrinsic_weight() -> Weight; @@ -352,7 +355,7 @@ where fn from_str(s: &str) -> Result { if s.to_lowercase() == "max" { - return Ok(ExplicitOrMaximal::Maximal); + return Ok(ExplicitOrMaximal::Maximal) } V::from_str(s) @@ -531,10 +534,7 @@ mod tests { let expected = vec![rialto1, rialto2, millau1, millau2]; // when - let parsed = expected - .iter() - .map(|s| AccountId::from_str(s).unwrap()) - .collect::>(); + let parsed = expected.iter().map(|s| AccountId::from_str(s).unwrap()).collect::>(); let actual = parsed.iter().map(|a| format!("{}", a)).collect::>(); @@ -563,7 +563,8 @@ mod tests { let alice = sp_core::sr25519::Pair::from_string(ALICE, Some(ALICE_PASSWORD)).unwrap(); let bob = sp_core::sr25519::Pair::from_string(BOB, Some(BOB_PASSWORD)).unwrap(); - let bob_with_alice_password = sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); + let bob_with_alice_password = + sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); let temp_dir = tempdir::TempDir::new("reads_suri_from_file").unwrap(); let mut suri_file_path = temp_dir.path().to_path_buf(); diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 48e2d85efbcc3..e90c663bb33a0 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -19,7 +19,9 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::finality_pipeline::SubstrateFinalitySyncPipeline; -use crate::cli::{PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; +use crate::cli::{ + PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, +}; /// Start headers relayer process. #[derive(StructOpt)] @@ -27,7 +29,8 @@ pub struct RelayHeaders { /// A bridge instance to relay headers for. #[structopt(possible_values = RelayHeadersBridge::VARIANTS, case_insensitive = true)] bridge: RelayHeadersBridge, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed. + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. #[structopt(long)] only_mandatory_headers: bool, #[structopt(flatten)] @@ -62,49 +65,49 @@ macro_rules! select_bridge { type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; $generic - } + }, RelayHeadersBridge::RialtoToMillau => { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; $generic - } + }, RelayHeadersBridge::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; $generic - } + }, RelayHeadersBridge::RococoToWococo => { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; $generic - } + }, RelayHeadersBridge::WococoToRococo => { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; $generic - } + }, RelayHeadersBridge::KusamaToPolkadot => { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; $generic - } + }, RelayHeadersBridge::PolkadotToKusama => { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; $generic - } + }, } }; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index c6a0983141131..303acf3f125d6 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -27,14 +27,20 @@ use structopt::StructOpt; use strum::VariantNames; use codec::Encode; -use relay_substrate_client::{AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{ + AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, +}; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; -use substrate_relay_helper::messages_lane::{MessagesRelayParams, SubstrateMessageLane}; -use substrate_relay_helper::on_demand_headers::OnDemandHeadersRelay; +use substrate_relay_helper::{ + messages_lane::{MessagesRelayParams, SubstrateMessageLane}, + on_demand_headers::OnDemandHeadersRelay, +}; -use crate::cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}; -use crate::declare_chain_options; +use crate::{ + cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}, + declare_chain_options, +}; /// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. /// @@ -63,16 +69,17 @@ pub struct HeadersAndMessagesSharedParams { /// Create relayers fund accounts on both chains, if it does not exists yet. #[structopt(long)] create_relayers_fund_accounts: bool, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) are relayed. + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. #[structopt(long)] only_mandatory_headers: bool, #[structopt(flatten)] prometheus_params: PrometheusParams, } -// The reason behind this macro is that 'normal' relays are using source and target chains terminology, -// which is unusable for both-way relays (if you're relaying headers from Rialto to Millau and from -// Millau to Rialto, then which chain is source?). +// The reason behind this macro is that 'normal' relays are using source and target chains +// terminology, which is unusable for both-way relays (if you're relaying headers from Rialto to +// Millau and from Millau to Rialto, then which chain is source?). macro_rules! declare_bridge_options { ($chain1:ident, $chain2:ident) => { paste::item! { @@ -116,25 +123,35 @@ macro_rules! select_bridge { type Left = relay_millau_client::Millau; type Right = relay_rialto_client::Rialto; - type LeftToRightFinality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; - type RightToLeftFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; + type LeftToRightFinality = + crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; + type RightToLeftFinality = + crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; - type LeftToRightMessages = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; - type RightToLeftMessages = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; + type LeftToRightMessages = + crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; + type RightToLeftMessages = + crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; type LeftAccountIdConverter = bp_millau::AccountIdConverter; type RightAccountIdConverter = bp_rialto::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = + bp_millau::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = + bp_rialto::SESSION_LENGTH; - use crate::chains::millau_messages_to_rialto::{ - add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, - update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, - }; - use crate::chains::rialto_messages_to_millau::{ - add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, - update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, + use crate::chains::{ + millau_messages_to_rialto::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, + run as left_to_right_messages, + update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, + }, + rialto_messages_to_millau::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, + run as right_to_left_messages, + update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, + }, }; async fn left_create_account( @@ -154,30 +171,40 @@ macro_rules! select_bridge { } $generic - } + }, RelayHeadersAndMessages::RococoWococo(_) => { type Params = RococoWococoHeadersAndMessages; type Left = relay_rococo_client::Rococo; type Right = relay_wococo_client::Wococo; - type LeftToRightFinality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; - type RightToLeftFinality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + type LeftToRightFinality = + crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; + type RightToLeftFinality = + crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; - type LeftToRightMessages = crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo; - type RightToLeftMessages = crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo; + type LeftToRightMessages = + crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo; + type RightToLeftMessages = + crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo; type LeftAccountIdConverter = bp_rococo::AccountIdConverter; type RightAccountIdConverter = bp_wococo::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = + bp_rococo::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = + bp_wococo::SESSION_LENGTH; - use crate::chains::rococo_messages_to_wococo::{ - add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, - }; - use crate::chains::wococo_messages_to_rococo::{ - add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + use crate::chains::{ + rococo_messages_to_wococo::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, + run as left_to_right_messages, + }, + wococo_messages_to_rococo::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, + run as right_to_left_messages, + }, }; async fn update_right_to_left_conversion_rate( @@ -213,32 +240,42 @@ macro_rules! select_bridge { } $generic - } + }, RelayHeadersAndMessages::KusamaPolkadot(_) => { type Params = KusamaPolkadotHeadersAndMessages; type Left = relay_kusama_client::Kusama; type Right = relay_polkadot_client::Polkadot; - type LeftToRightFinality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; - type RightToLeftFinality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; + type LeftToRightFinality = + crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; + type RightToLeftFinality = + crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; - type LeftToRightMessages = crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot; - type RightToLeftMessages = crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama; + type LeftToRightMessages = + crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot; + type RightToLeftMessages = + crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama; type LeftAccountIdConverter = bp_kusama::AccountIdConverter; type RightAccountIdConverter = bp_polkadot::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_kusama::BlockNumber = bp_kusama::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = bp_polkadot::SESSION_LENGTH; + const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_kusama::BlockNumber = + bp_kusama::SESSION_LENGTH; + const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = + bp_polkadot::SESSION_LENGTH; - use crate::chains::kusama_messages_to_polkadot::{ - add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, - update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, - }; - use crate::chains::polkadot_messages_to_kusama::{ - add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, - update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, + use crate::chains::{ + kusama_messages_to_polkadot::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, + run as left_to_right_messages, + update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, + }, + polkadot_messages_to_kusama::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, + run as right_to_left_messages, + update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, + }, }; async fn left_create_account( @@ -248,25 +285,24 @@ macro_rules! select_bridge { ) -> anyhow::Result<()> { let left_genesis_hash = *left_client.genesis_hash(); left_client - .submit_signed_extrinsic(left_sign.public().into(), move |_, transaction_nonce| { - Bytes( - Left::sign_transaction( - left_genesis_hash, - &left_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_kusama_client::runtime::Call::Balances( - relay_kusama_client::runtime::BalancesCall::transfer( - bp_kusama::AccountAddress::Id(account_id), - bp_kusama::EXISTENTIAL_DEPOSIT.into(), + .submit_signed_extrinsic( + left_sign.public().into(), + move |_, transaction_nonce| { + Bytes( + Left::sign_transaction(left_genesis_hash, &left_sign, relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + relay_kusama_client::runtime::Call::Balances( + relay_kusama_client::runtime::BalancesCall::transfer( + bp_kusama::AccountAddress::Id(account_id), + bp_kusama::EXISTENTIAL_DEPOSIT.into(), + ), ), + transaction_nonce, ), - transaction_nonce, - ), + ).encode() ) - .encode(), - ) - }) + }, + ) .await .map(drop) .map_err(|e| anyhow::format_err!("{}", e)) @@ -279,32 +315,31 @@ macro_rules! select_bridge { ) -> anyhow::Result<()> { let right_genesis_hash = *right_client.genesis_hash(); right_client - .submit_signed_extrinsic(right_sign.public().into(), move |_, transaction_nonce| { - Bytes( - Right::sign_transaction( - right_genesis_hash, - &right_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_polkadot_client::runtime::Call::Balances( - relay_polkadot_client::runtime::BalancesCall::transfer( - bp_polkadot::AccountAddress::Id(account_id), - bp_polkadot::EXISTENTIAL_DEPOSIT.into(), + .submit_signed_extrinsic( + right_sign.public().into(), + move |_, transaction_nonce| { + Bytes( + Right::sign_transaction(right_genesis_hash, &right_sign, relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + relay_polkadot_client::runtime::Call::Balances( + relay_polkadot_client::runtime::BalancesCall::transfer( + bp_polkadot::AccountAddress::Id(account_id), + bp_polkadot::EXISTENTIAL_DEPOSIT.into(), + ), ), + transaction_nonce, ), - transaction_nonce, - ), + ).encode() ) - .encode(), - ) - }) + }, + ) .await .map(drop) .map_err(|e| anyhow::format_err!("{}", e)) } $generic - } + }, } }; } @@ -330,16 +365,19 @@ impl RelayHeadersAndMessages { let left_client = params.left.to_client::().await?; let left_transactions_mortality = params.left_sign.transactions_mortality()?; let left_sign = params.left_sign.to_keypair::()?; - let left_messages_pallet_owner = params.left_messages_pallet_owner.to_keypair::()?; + let left_messages_pallet_owner = + params.left_messages_pallet_owner.to_keypair::()?; let right_client = params.right.to_client::().await?; let right_transactions_mortality = params.right_sign.transactions_mortality()?; let right_sign = params.right_sign.to_keypair::()?; - let right_messages_pallet_owner = params.right_messages_pallet_owner.to_keypair::()?; + let right_messages_pallet_owner = + params.right_messages_pallet_owner.to_keypair::()?; let lanes = params.shared.lane; let relayer_mode = params.shared.relayer_mode.into(); - const METRIC_IS_SOME_PROOF: &str = "it is `None` when metric has been already registered; \ + const METRIC_IS_SOME_PROOF: &str = + "it is `None` when metric has been already registered; \ this is the command entrypoint, so nothing has been registered yet; \ qed"; @@ -413,22 +451,40 @@ impl RelayHeadersAndMessages { } if params.shared.create_relayers_fund_accounts { - let relayer_fund_acount_id = - pallet_bridge_messages::relayer_fund_account_id::, LeftAccountIdConverter>(); + let relayer_fund_acount_id = pallet_bridge_messages::relayer_fund_account_id::< + AccountIdOf, + LeftAccountIdConverter, + >(); let relayers_fund_account_balance = left_client.free_native_balance(relayer_fund_acount_id.clone()).await; - if let Err(relay_substrate_client::Error::AccountDoesNotExist) = relayers_fund_account_balance { + if let Err(relay_substrate_client::Error::AccountDoesNotExist) = + relayers_fund_account_balance + { log::info!(target: "bridge", "Going to create relayers fund account at {}.", Left::NAME); - left_create_account(left_client.clone(), left_sign.clone(), relayer_fund_acount_id).await?; + left_create_account( + left_client.clone(), + left_sign.clone(), + relayer_fund_acount_id, + ) + .await?; } - let relayer_fund_acount_id = - pallet_bridge_messages::relayer_fund_account_id::, RightAccountIdConverter>(); + let relayer_fund_acount_id = pallet_bridge_messages::relayer_fund_account_id::< + AccountIdOf, + RightAccountIdConverter, + >(); let relayers_fund_account_balance = right_client.free_native_balance(relayer_fund_acount_id.clone()).await; - if let Err(relay_substrate_client::Error::AccountDoesNotExist) = relayers_fund_account_balance { + if let Err(relay_substrate_client::Error::AccountDoesNotExist) = + relayers_fund_account_balance + { log::info!(target: "bridge", "Going to create relayers fund account at {}.", Right::NAME); - right_create_account(right_client.clone(), right_sign.clone(), relayer_fund_acount_id).await?; + right_create_account( + right_client.clone(), + right_sign.clone(), + relayer_fund_acount_id, + ) + .await?; } } diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 0f89e9843f161..3ccf53348d611 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -19,12 +19,13 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::messages_lane::MessagesRelayParams; -use crate::cli::bridge::FullBridge; -use crate::cli::{ - HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, - TargetSigningParams, +use crate::{ + cli::{ + bridge::FullBridge, HexLaneId, PrometheusParams, SourceConnectionParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, + }, + select_full_bridge, }; -use crate::select_full_bridge; /// Relayer operating mode. #[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq)] @@ -32,7 +33,8 @@ use crate::select_full_bridge; pub enum RelayerMode { /// The relayer doesn't care about rewards. Altruistic, - /// The relayer will deliver all messages and confirmations as long as he's not losing any funds. + /// The relayer will deliver all messages and confirmations as long as he's not losing any + /// funds. Rational, } diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 4fad160fee08c..03a9c114b0b12 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -18,7 +18,9 @@ use crate::cli::{TargetConnectionParams, TargetSigningParams}; use codec::{Decode, Encode}; use num_traits::{One, Zero}; -use relay_substrate_client::{BlockWithJustification, Chain, Client, Error as SubstrateError, TransactionSignScheme}; +use relay_substrate_client::{ + BlockWithJustification, Chain, Client, Error as SubstrateError, TransactionSignScheme, +}; use relay_utils::FailedClient; use sp_core::Bytes; use sp_runtime::{ @@ -54,13 +56,15 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type TargetSign = relay_millau_client::Millau; - // When large message is being sent from Millau to Rialto AND other transactions are blocking - // it from being mined, we'll see something like this in logs: + // When large message is being sent from Millau to Rialto AND other transactions are + // blocking it from being mined, we'll see something like this in logs: // - // Millau transaction priority with tip=0: 17800827994. Target priority: 526186677695 + // Millau transaction priority with tip=0: 17800827994. Target priority: + // 526186677695 // - // So since fee multiplier in Millau is `1` and `WeightToFee` is `IdentityFee`, then we need - // tip around `526186677695 - 17800827994 = 508_385_849_701`. Let's round it up to `1_000_000_000_000`. + // So since fee multiplier in Millau is `1` and `WeightToFee` is `IdentityFee`, then + // we need tip around `526186677695 - 17800827994 = 508_385_849_701`. Let's round it + // up to `1_000_000_000_000`. const TIP_STEP: bp_millau::Balance = 1_000_000_000; const TIP_LIMIT: bp_millau::Balance = 1_000_000_000_000; @@ -68,7 +72,7 @@ macro_rules! select_bridge { const STALLED_BLOCKS: bp_millau::BlockNumber = 5; $generic - } + }, } }; } @@ -158,8 +162,8 @@ async fn run_until_connection_lost C::NAME, error, ); - return Err(FailedClient::Target); - } + return Err(FailedClient::Target) + }, }; } } @@ -174,8 +178,8 @@ async fn run_loop_iteration>( Some(original_transaction) => original_transaction, None => { log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); - return Ok(context); - } + return Ok(context) + }, }; let original_transaction_hash = C::Hasher::hash(&original_transaction.encode()); let context = context.notice_transaction(original_transaction_hash); @@ -189,15 +193,15 @@ async fn run_loop_iteration>( context.stalled_for, context.stalled_for_limit, ); - return Ok(context); + return Ok(context) } let (best_block, target_priority) = match read_previous_best_priority::(&client).await? { Some((best_block, target_priority)) => (best_block, target_priority), None => { log::trace!(target: "bridge", "Failed to read priority of best {} transaction in its best block", C::NAME); - return Ok(context); - } + return Ok(context) + }, }; let (is_updated, updated_transaction) = select_transaction_tip::( @@ -213,7 +217,7 @@ async fn run_loop_iteration>( if !is_updated { log::trace!(target: "bridge", "{} transaction tip can not be updated. Reached limit?", C::NAME); - return Ok(context); + return Ok(context) } let updated_transaction = updated_transaction.encode(); @@ -241,10 +245,10 @@ async fn lookup_signer_transaction let pending_transaction = S::SignedTransaction::decode(&mut &pending_transaction.0[..]) .map_err(SubstrateError::ResponseParseFailed)?; if !S::is_signed_by(key_pair, &pending_transaction) { - continue; + continue } - return Ok(Some(pending_transaction)); + return Ok(Some(pending_transaction)) } Ok(None) @@ -286,14 +290,15 @@ async fn select_transaction_tip>( ) -> Result<(bool, S::SignedTransaction), SubstrateError> { let stx = format!("{:?}", tx); let mut current_priority = client.validate_transaction(at_block, tx.clone()).await??.priority; - let mut unsigned_tx = S::parse_transaction(tx) - .ok_or_else(|| SubstrateError::Custom(format!("Failed to parse {} transaction {}", C::NAME, stx,)))?; + let mut unsigned_tx = S::parse_transaction(tx).ok_or_else(|| { + SubstrateError::Custom(format!("Failed to parse {} transaction {}", C::NAME, stx,)) + })?; let old_tip = unsigned_tx.tip; while current_priority < target_priority { let next_tip = unsigned_tx.tip + tip_step; if next_tip > tip_limit { - break; + break } log::trace!( diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 04ce386ef09a9..3e77ad8342927 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::bridge::FullBridge; -use crate::cli::encode_call::{self, CliEncodeCall}; -use crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee; use crate::cli::{ - Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, - TargetSigningParams, + bridge::FullBridge, + encode_call::{self, CliEncodeCall}, + estimate_fee::estimate_message_delivery_and_dispatch_fee, + Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, + SourceSigningParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_runtime::BalanceOf; @@ -77,7 +77,8 @@ pub struct SendMessage { /// Dispatch weight of the message. If not passed, determined automatically. #[structopt(long)] dispatch_weight: Option>, - /// Delivery and dispatch fee in source chain base currency units. If not passed, determined automatically. + /// Delivery and dispatch fee in source chain base currency units. If not passed, determined + /// automatically. #[structopt(long)] fee: Option, /// Message type. @@ -138,7 +139,7 @@ impl SendMessage { target_origin_public.into(), digest_signature.into(), ) - } + }, }, &target_call, *dispatch_fee_payment, @@ -238,10 +239,7 @@ fn prepare_call_dispatch_weight( weight_from_pre_dispatch_call: ExplicitOrMaximal, maximal_allowed_weight: Weight, ) -> Weight { - match user_specified_dispatch_weight - .clone() - .unwrap_or(weight_from_pre_dispatch_call) - { + match user_specified_dispatch_weight.clone().unwrap_or(weight_from_pre_dispatch_call) { ExplicitOrMaximal::Explicit(weight) => weight, ExplicitOrMaximal::Maximal => maximal_allowed_weight, } @@ -272,24 +270,14 @@ where log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); // re-pack to return `Vec` - let MessagePayload { - spec_version, - weight, - origin, - dispatch_fee_payment, - call, - } = payload; - MessagePayload { - spec_version, - weight, - origin, - dispatch_fee_payment, - call: call.0, - } + let MessagePayload { spec_version, weight, origin, dispatch_fee_payment, call } = payload; + MessagePayload { spec_version, weight, origin, dispatch_fee_payment, call: call.0 } } pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { - bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight) + bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight( + maximal_extrinsic_weight, + ) } #[cfg(test)] @@ -321,7 +309,9 @@ mod tests { MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, weight: 576000, - origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), + origin: CallOrigin::SourceAccount( + sp_keyring::AccountKeyring::Alice.to_account_id() + ), dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, call: hex!("0001081234").to_vec(), } diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 264b98e948ff9..d18d37efc3d20 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -28,15 +28,16 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; use frame_support::dispatch::GetDispatchInfo; use relay_substrate_client::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithBalances, Client, - Error as SubstrateError, HashOf, SignatureOf, Subscription, TransactionSignScheme, TransactionStatusOf, - UnsignedTransaction, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithBalances, + Client, Error as SubstrateError, HashOf, SignatureOf, Subscription, TransactionSignScheme, + TransactionStatusOf, UnsignedTransaction, }; use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, H256, U256}; use sp_runtime::traits::{Convert, Header as HeaderT}; use crate::cli::{ - Balance, CliChain, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, + Balance, CliChain, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, + TargetSigningParams, }; /// Swap tokens. @@ -71,7 +72,8 @@ pub struct SwapTokens { pub enum TokenSwapType { /// The `target_sign` is temporary and only have funds for single swap. NoLock, - /// This swap type prevents `source_signer` from restarting the swap after it has been completed. + /// This swap type prevents `source_signer` from restarting the swap after it has been + /// completed. LockUntilBlock { /// Number of blocks before the swap expires. #[structopt(long)] @@ -119,7 +121,7 @@ macro_rules! select_bridge { const TARGET_TO_SOURCE_LANE_ID: bp_messages::LaneId = [0, 0, 0, 0]; $generic - } + }, } }; } @@ -133,7 +135,8 @@ impl SwapTokens { let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; - // names of variables in this function are matching names used by the `pallet-bridge-token-swap` + // names of variables in this function are matching names used by the + // `pallet-bridge-token-swap` // prepare token swap intention let token_swap = self @@ -143,18 +146,25 @@ impl SwapTokens { // group all accounts that will be used later let accounts = TokenSwapAccounts { source_account_at_bridged_chain: derive_target_account_from_source_account( - bp_runtime::SourceAccount::Account(token_swap.source_account_at_this_chain.clone()), + bp_runtime::SourceAccount::Account( + token_swap.source_account_at_this_chain.clone(), + ), ), target_account_at_this_chain: derive_source_account_from_target_account( - bp_runtime::SourceAccount::Account(token_swap.target_account_at_bridged_chain.clone()), + bp_runtime::SourceAccount::Account( + token_swap.target_account_at_bridged_chain.clone(), + ), ), source_account_at_this_chain: token_swap.source_account_at_this_chain.clone(), target_account_at_bridged_chain: token_swap.target_account_at_bridged_chain.clone(), - swap_account: FromSwapToThisAccountIdConverter::convert(token_swap.using_encoded(blake2_256).into()), + swap_account: FromSwapToThisAccountIdConverter::convert( + token_swap.using_encoded(blake2_256).into(), + ), }; // account balances are used to demonstrate what's happening :) - let initial_balances = read_account_balances(&accounts, &source_client, &target_client).await?; + let initial_balances = + read_account_balances(&accounts, &source_client, &target_client).await?; // before calling something that may fail, log what we're trying to do log::info!(target: "bridge", "Starting swap: {:?}", token_swap); @@ -171,7 +181,8 @@ impl SwapTokens { token_swap.target_balance_at_bridged_chain, ) .into(); - let bridged_currency_transfer_weight = bridged_currency_transfer.get_dispatch_info().weight; + let bridged_currency_transfer_weight = + bridged_currency_transfer.get_dispatch_info().weight; // sign message let bridged_chain_spec_version = TARGET_SPEC_VERSION; @@ -182,10 +193,12 @@ impl SwapTokens { SOURCE_CHAIN_ID, TARGET_CHAIN_ID, ); - let bridged_currency_transfer_signature: SignatureOf = target_sign.sign(&signature_payload).into(); + let bridged_currency_transfer_signature: SignatureOf = + target_sign.sign(&signature_payload).into(); // prepare `create_swap` call - let target_public_at_bridged_chain: AccountPublicOf = target_sign.public().into(); + let target_public_at_bridged_chain: AccountPublicOf = + target_sign.public().into(); let swap_delivery_and_dispatch_fee: BalanceOf = crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( &source_client, @@ -199,7 +212,8 @@ impl SwapTokens { target_public_at_bridged_chain.clone(), bridged_currency_transfer_signature.clone(), ), - dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtTargetChain, + dispatch_fee_payment: + bp_runtime::messages::DispatchFeePayment::AtTargetChain, call: bridged_currency_transfer.encode(), }, ) @@ -245,19 +259,20 @@ impl SwapTokens { pallet_bridge_token_swap::PENDING_SWAPS_MAP_NAME, token_swap_hash.as_ref(), ); - match read_token_swap_state(&source_client, swap_created_at, &token_swap_storage_key).await? { + match read_token_swap_state(&source_client, swap_created_at, &token_swap_storage_key) + .await? + { Some(bp_token_swap::TokenSwapState::Started) => { log::info!(target: "bridge", "Swap has been successfully started"); let intermediate_balances = read_account_balances(&accounts, &source_client, &target_client).await?; log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); - } - Some(token_swap_state) => { + }, + Some(token_swap_state) => return Err(anyhow::format_err!( "Fresh token swap has unexpected state: {:?}", token_swap_state, - )) - } + )), None => return Err(anyhow::format_err!("Failed to start token swap")), }; @@ -265,7 +280,8 @@ impl SwapTokens { // Step 2: message is being relayed to the target chain and dispathed there // - // wait until message is dispatched at the target chain and dispatch result delivered back to source chain + // wait until message is dispatched at the target chain and dispatch result delivered + // back to source chain let token_swap_state = wait_until_token_swap_state_is_changed( &source_client, &token_swap_storage_key, @@ -275,32 +291,37 @@ impl SwapTokens { let is_transfer_succeeded = match token_swap_state { Some(bp_token_swap::TokenSwapState::Started) => { unreachable!("wait_until_token_swap_state_is_changed only returns if state is not Started; qed",) - } - None => return Err(anyhow::format_err!("Fresh token swap has disappeared unexpectedly")), + }, + None => + return Err(anyhow::format_err!("Fresh token swap has disappeared unexpectedly")), Some(bp_token_swap::TokenSwapState::Confirmed) => { log::info!( target: "bridge", "Transfer has been successfully dispatched at the target chain. Swap can be claimed", ); true - } + }, Some(bp_token_swap::TokenSwapState::Failed) => { log::info!( target: "bridge", "Transfer has been dispatched with an error at the target chain. Swap can be canceled", ); false - } + }, }; - // by this time: (1) token swap account has been created and (2) if transfer has been successfully - // dispatched, both target chain balances have changed - let intermediate_balances = read_account_balances(&accounts, &source_client, &target_client).await?; + // by this time: (1) token swap account has been created and (2) if transfer has been + // successfully dispatched, both target chain balances have changed + let intermediate_balances = + read_account_balances(&accounts, &source_client, &target_client).await?; log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); - // transfer has been dispatched, but we may need to wait until block where swap can be claimed/canceled - if let bp_token_swap::TokenSwapType::LockClaimUntilBlock(ref last_available_block_number, _) = - token_swap.swap_type + // transfer has been dispatched, but we may need to wait until block where swap can be + // claimed/canceled + if let bp_token_swap::TokenSwapType::LockClaimUntilBlock( + ref last_available_block_number, + _, + ) = token_swap.swap_type { wait_until_swap_unlocked( &source_client, @@ -317,7 +338,8 @@ impl SwapTokens { log::info!(target: "bridge", "Claiming the swap swap"); // prepare `claim_swap` message that will be sent over the bridge - let claim_swap_call: CallOf = pallet_bridge_token_swap::Call::claim_swap(token_swap).into(); + let claim_swap_call: CallOf = + pallet_bridge_token_swap::Call::claim_swap(token_swap).into(); let claim_swap_message = bp_message_dispatch::MessagePayload { spec_version: SOURCE_SPEC_VERSION, weight: claim_swap_call.get_dispatch_info().weight, @@ -354,7 +376,10 @@ impl SwapTokens { target_genesis_hash, &target_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(send_message_call, transaction_nonce), + UnsignedTransaction::new( + send_message_call, + transaction_nonce, + ), ) .encode(), ) @@ -374,7 +399,7 @@ impl SwapTokens { if token_swap_state != None { return Err(anyhow::format_err!( "Confirmed token swap state has been changed to {:?} unexpectedly" - )); + )) } } else { log::info!(target: "bridge", "Cancelling the swap"); @@ -390,7 +415,10 @@ impl SwapTokens { source_genesis_hash, &source_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(cancel_swap_call, transaction_nonce), + UnsignedTransaction::new( + cancel_swap_call, + transaction_nonce, + ), ) .encode(), ) @@ -402,7 +430,8 @@ impl SwapTokens { } // print final balances - let final_balances = read_account_balances(&accounts, &source_client, &target_client).await?; + let final_balances = + read_account_balances(&accounts, &source_client, &target_client).await?; log::info!(target: "bridge", "Final account balances: {:?}", final_balances); Ok(()) @@ -454,22 +483,18 @@ impl SwapTokens { source_client: &Client, ) -> anyhow::Result>> { match self.swap_type { - TokenSwapType::NoLock => Ok(bp_token_swap::TokenSwapType::TemporaryTargetAccountAtBridgedChain), - TokenSwapType::LockUntilBlock { - blocks_before_expire, - ref swap_nonce, - } => { + TokenSwapType::NoLock => + Ok(bp_token_swap::TokenSwapType::TemporaryTargetAccountAtBridgedChain), + TokenSwapType::LockUntilBlock { blocks_before_expire, ref swap_nonce } => { let blocks_before_expire: BlockNumberOf = blocks_before_expire.into(); let current_source_block_number = *source_client.best_header().await?.number(); Ok(bp_token_swap::TokenSwapType::LockClaimUntilBlock( current_source_block_number + blocks_before_expire, swap_nonce.unwrap_or_else(|| { - U256::from(random::()) - .overflowing_mul(U256::from(random::())) - .0 + U256::from(random::()).overflowing_mul(U256::from(random::())).0 }), )) - } + }, } } } @@ -551,17 +576,16 @@ async fn wait_until_transaction_is_finalized( loop { let transaction_status = subscription.next().await?; match transaction_status { - Some(TransactionStatusOf::::FinalityTimeout(_)) - | Some(TransactionStatusOf::::Usurped(_)) - | Some(TransactionStatusOf::::Dropped) - | Some(TransactionStatusOf::::Invalid) - | None => { + Some(TransactionStatusOf::::FinalityTimeout(_)) | + Some(TransactionStatusOf::::Usurped(_)) | + Some(TransactionStatusOf::::Dropped) | + Some(TransactionStatusOf::::Invalid) | + None => return Err(anyhow::format_err!( "We've been waiting for finalization of {} transaction, but it now has the {:?} status", C::NAME, transaction_status, - )) - } + )), Some(TransactionStatusOf::::Finalized(block_hash)) => { log::trace!( target: "bridge", @@ -569,8 +593,8 @@ async fn wait_until_transaction_is_finalized( C::NAME, block_hash, ); - return Ok(block_hash); - } + return Ok(block_hash) + }, _ => { log::trace!( target: "bridge", @@ -578,7 +602,7 @@ async fn wait_until_transaction_is_finalized( C::NAME, transaction_status, ); - } + }, } } } @@ -597,9 +621,10 @@ async fn wait_until_token_swap_state_is_changed( let best_block_hash = client.block_hash_by_number(best_block).await?; log::trace!(target: "bridge", "Inspecting {} block {}/{}", C::NAME, best_block, best_block_hash); - let token_swap_state = read_token_swap_state(client, best_block_hash, swap_state_storage_key).await?; + let token_swap_state = + read_token_swap_state(client, best_block_hash, swap_state_storage_key).await?; match token_swap_state { - Some(new_token_swap_state) if new_token_swap_state == previous_token_swap_state => {} + Some(new_token_swap_state) if new_token_swap_state == previous_token_swap_state => {}, _ => { log::trace!( target: "bridge", @@ -607,8 +632,8 @@ async fn wait_until_token_swap_state_is_changed( previous_token_swap_state, token_swap_state, ); - return Ok(token_swap_state); - } + return Ok(token_swap_state) + }, } } } @@ -625,7 +650,7 @@ async fn wait_until_swap_unlocked( let best_block = client.best_finalized_header_number().await?; let best_block_hash = client.block_hash_by_number(best_block).await?; if best_block >= required_block_number { - return Ok(()); + return Ok(()) } log::trace!(target: "bridge", "Skipping {} block {}/{}", C::NAME, best_block, best_block_hash); @@ -638,7 +663,5 @@ async fn read_token_swap_state( at_block: C::Hash, swap_state_storage_key: &StorageKey, ) -> anyhow::Result> { - Ok(client - .storage_value(swap_state_storage_key.clone(), Some(at_block)) - .await?) + Ok(client.storage_value(swap_state_storage_key.clone(), Some(at_block)).await?) } diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs index c82dddcf36ee8..48b7c9386f353 100644 --- a/relays/client-ethereum/src/client.rs +++ b/relays/client-ethereum/src/client.rs @@ -14,12 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::rpc::Ethereum; -use crate::types::{ - Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, SyncState, Transaction, - TransactionHash, H256, U256, +use crate::{ + rpc::Ethereum, + types::{ + Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, + SyncState, Transaction, TransactionHash, H256, U256, + }, + ConnectionParams, Error, Result, }; -use crate::{ConnectionParams, Error, Result}; use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; use relay_utils::relay_loop::RECONNECT_DELAY; @@ -57,15 +59,17 @@ impl Client { } } - /// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been established - /// or error otherwise. + /// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been + /// established or error otherwise. pub async fn try_connect(params: ConnectionParams) -> Result { let (tokio, client) = Self::build_client(¶ms).await?; Ok(Self { tokio, client, params }) } /// Build client to use in connection. - async fn build_client(params: &ConnectionParams) -> Result<(Arc, Arc)> { + async fn build_client( + params: &ConnectionParams, + ) -> Result<(Arc, Arc)> { let tokio = tokio::runtime::Runtime::new()?; let uri = format!("ws://{}:{}", params.host, params.port); let client = tokio @@ -90,13 +94,14 @@ impl Client { match Ethereum::syncing(&*client).await? { SyncState::NotSyncing => Ok(()), SyncState::Syncing(syncing) => { - let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block); + let missing_headers = + syncing.highest_block.saturating_sub(syncing.current_block); if missing_headers > MAJOR_SYNC_BLOCKS.into() { - return Err(Error::ClientNotSynced(missing_headers)); + return Err(Error::ClientNotSynced(missing_headers)) } Ok(()) - } + }, } }) .await @@ -104,21 +109,26 @@ impl Client { /// Estimate gas usage for the given call. pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { - self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::estimate_gas(&*client, call_request).await?) }) - .await + self.jsonrpsee_execute(move |client| async move { + Ok(Ethereum::estimate_gas(&*client, call_request).await?) + }) + .await } /// Retrieve number of the best known block from the Ethereum node. pub async fn best_block_number(&self) -> Result { - self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::block_number(&*client).await?.as_u64()) }) - .await + self.jsonrpsee_execute(move |client| async move { + Ok(Ethereum::block_number(&*client).await?.as_u64()) + }) + .await } /// Retrieve number of the best known block from the Ethereum node. pub async fn header_by_number(&self, block_number: u64) -> Result
{ self.jsonrpsee_execute(move |client| async move { let get_full_tx_objects = false; - let header = Ethereum::get_block_by_number(&*client, block_number, get_full_tx_objects).await?; + let header = + Ethereum::get_block_by_number(&*client, block_number, get_full_tx_objects).await?; match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { true => Ok(header), false => Err(Error::IncompleteHeader), @@ -141,19 +151,28 @@ impl Client { } /// Retrieve block header and its transactions by its number from Ethereum node. - pub async fn header_by_number_with_transactions(&self, number: u64) -> Result { + pub async fn header_by_number_with_transactions( + &self, + number: u64, + ) -> Result { self.jsonrpsee_execute(move |client| async move { let get_full_tx_objects = true; - let header = Ethereum::get_block_by_number_with_transactions(&*client, number, get_full_tx_objects).await?; - - let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + let header = Ethereum::get_block_by_number_with_transactions( + &*client, + number, + get_full_tx_objects, + ) + .await?; + + let is_complete_header = + header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); if !is_complete_header { - return Err(Error::IncompleteHeader); + return Err(Error::IncompleteHeader) } let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); if !is_complete_transactions { - return Err(Error::IncompleteTransaction); + return Err(Error::IncompleteTransaction) } Ok(header) @@ -162,19 +181,25 @@ impl Client { } /// Retrieve block header and its transactions by its hash from Ethereum node. - pub async fn header_by_hash_with_transactions(&self, hash: H256) -> Result { + pub async fn header_by_hash_with_transactions( + &self, + hash: H256, + ) -> Result { self.jsonrpsee_execute(move |client| async move { let get_full_tx_objects = true; - let header = Ethereum::get_block_by_hash_with_transactions(&*client, hash, get_full_tx_objects).await?; + let header = + Ethereum::get_block_by_hash_with_transactions(&*client, hash, get_full_tx_objects) + .await?; - let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); + let is_complete_header = + header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); if !is_complete_header { - return Err(Error::IncompleteHeader); + return Err(Error::IncompleteHeader) } let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); if !is_complete_transactions { - return Err(Error::IncompleteTransaction); + return Err(Error::IncompleteTransaction) } Ok(header) @@ -184,8 +209,10 @@ impl Client { /// Retrieve transaction by its hash from Ethereum node. pub async fn transaction_by_hash(&self, hash: H256) -> Result> { - self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::transaction_by_hash(&*client, hash).await?) }) - .await + self.jsonrpsee_execute(move |client| async move { + Ok(Ethereum::transaction_by_hash(&*client, hash).await?) + }) + .await } /// Retrieve transaction receipt by transaction hash. @@ -198,9 +225,9 @@ impl Client { /// Get the nonce of the given account. pub async fn account_nonce(&self, address: Address) -> Result { - self.jsonrpsee_execute( - move |client| async move { Ok(Ethereum::get_transaction_count(&*client, address).await?) }, - ) + self.jsonrpsee_execute(move |client| async move { + Ok(Ethereum::get_transaction_count(&*client, address).await?) + }) .await } @@ -219,8 +246,10 @@ impl Client { /// Call Ethereum smart contract. pub async fn eth_call(&self, call_transaction: CallRequest) -> Result { - self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::call(&*client, call_transaction).await?) }) - .await + self.jsonrpsee_execute(move |client| async move { + Ok(Ethereum::call(&*client, call_transaction).await?) + }) + .await } /// Execute jsonrpsee future in tokio context. @@ -231,8 +260,6 @@ impl Client { T: Send + 'static, { let client = self.client.clone(); - self.tokio - .spawn(async move { make_jsonrpsee_future(client).await }) - .await? + self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? } } diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index 3650fd2fd9aad..f3c832cd40066 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -73,10 +73,10 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::RpcError(RpcError::Transport(_)) - | Error::RpcError(RpcError::Internal(_)) - | Error::RpcError(RpcError::RestartNeeded(_)) - | Error::ClientNotSynced(_), + Error::RpcError(RpcError::Transport(_)) | + Error::RpcError(RpcError::Internal(_)) | + Error::RpcError(RpcError::RestartNeeded(_)) | + Error::ClientNotSynced(_), ) } } diff --git a/relays/client-ethereum/src/lib.rs b/relays/client-ethereum/src/lib.rs index 9443a5d24f416..fa4877f8e5cfc 100644 --- a/relays/client-ethereum/src/lib.rs +++ b/relays/client-ethereum/src/lib.rs @@ -23,9 +23,11 @@ mod error; mod rpc; mod sign; -pub use crate::client::Client; -pub use crate::error::{Error, Result}; -pub use crate::sign::{sign_and_submit_transaction, SigningParams}; +pub use crate::{ + client::Client, + error::{Error, Result}, + sign::{sign_and_submit_transaction, SigningParams}, +}; pub mod types; @@ -40,9 +42,6 @@ pub struct ConnectionParams { impl Default for ConnectionParams { fn default() -> Self { - ConnectionParams { - host: "localhost".into(), - port: 8546, - } + ConnectionParams { host: "localhost".into(), port: 8546 } } } diff --git a/relays/client-ethereum/src/rpc.rs b/relays/client-ethereum/src/rpc.rs index 0fb81f7655a46..2479338b1015c 100644 --- a/relays/client-ethereum/src/rpc.rs +++ b/relays/client-ethereum/src/rpc.rs @@ -17,8 +17,8 @@ //! Ethereum node RPC interface. use crate::types::{ - Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SyncState, Transaction, TransactionHash, - H256, U256, U64, + Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SyncState, Transaction, + TransactionHash, H256, U256, U64, }; jsonrpsee_proc_macros::rpc_client_api! { diff --git a/relays/client-ethereum/src/sign.rs b/relays/client-ethereum/src/sign.rs index da1dbc4842e4a..0d9a8d032ee2e 100644 --- a/relays/client-ethereum/src/sign.rs +++ b/relays/client-ethereum/src/sign.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::types::{Address, CallRequest, U256}; -use crate::{Client, Result}; +use crate::{ + types::{Address, CallRequest, U256}, + Client, Result, +}; use bp_eth_poa::signatures::{secret_to_address, SignTransaction}; use hex_literal::hex; use secp256k1::SecretKey; diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 608befaa9a363..a93726620ff61 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -18,7 +18,8 @@ use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -75,7 +76,13 @@ impl TransactionSignScheme for Kusama { ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( unsigned.call, - bp_kusama::SignedExtensions::new(bp_kusama::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), + bp_kusama::SignedExtensions::new( + bp_kusama::VERSION, + era, + genesis_hash, + unsigned.nonce, + unsigned.tip, + ), ) .expect("SignedExtension never fails."); @@ -98,17 +105,15 @@ impl TransactionSignScheme for Kusama { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| *address == bp_kusama::AccountId::from(*signer.public().as_array_ref()).into()) + .map(|(address, _, _)| { + *address == bp_kusama::AccountId::from(*signer.public().as_array_ref()).into() + }) .unwrap_or(false) } fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { - call: tx.function, - nonce: extra.nonce(), - tip: extra.tip(), - }) + Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) } } diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs index f2145f5b02ff1..702ce3d385466 100644 --- a/relays/client-kusama/src/runtime.rs +++ b/relays/client-kusama/src/runtime.rs @@ -29,8 +29,8 @@ pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; /// Polkadot account ownership digest from Kusama. /// /// The byte vector returned by this function should be signed with a Polkadot account private key. -/// This way, the owner of `kusama_account_id` on Kusama proves that the Polkadot account private key -/// is also under his control. +/// This way, the owner of `kusama_account_id` on Kusama proves that the Polkadot account private +/// key is also under his control. pub fn kusama_to_polkadot_account_ownership_digest( polkadot_call: &Call, kusama_account_id: AccountId, @@ -128,7 +128,9 @@ pub enum BridgePolkadotMessagesCall { ), #[codec(index = 6)] receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + bp_polkadot::Hash, + >, UnrewardedRelayersState, ), } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index aa20fe76cb765..3f1aba1f3b372 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -18,8 +18,8 @@ use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -100,7 +100,12 @@ impl TransactionSignScheme for Millau { let signer: sp_runtime::MultiSigner = signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - millau_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account(), signature.into(), extra) + millau_runtime::UncheckedExtrinsic::new_signed( + call, + signer.into_account(), + signature.into(), + extra, + ) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -110,7 +115,9 @@ impl TransactionSignScheme for Millau { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| *address == millau_runtime::Address::from(*signer.public().as_array_ref())) + .map(|(address, _, _)| { + *address == millau_runtime::Address::from(*signer.public().as_array_ref()) + }) .unwrap_or(false) } @@ -118,9 +125,7 @@ impl TransactionSignScheme for Millau { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { call: tx.function, - nonce: Compact::>::decode(&mut &extra.4.encode()[..]) - .ok()? - .into(), + nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? .into(), diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 3ba84e05bff71..e6ceabf583e0b 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -18,7 +18,8 @@ use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -75,7 +76,13 @@ impl TransactionSignScheme for Polkadot { ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot::SignedExtensions::new(bp_polkadot::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), + bp_polkadot::SignedExtensions::new( + bp_polkadot::VERSION, + era, + genesis_hash, + unsigned.nonce, + unsigned.tip, + ), ) .expect("SignedExtension never fails."); @@ -98,17 +105,15 @@ impl TransactionSignScheme for Polkadot { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| *address == bp_polkadot::AccountId::from(*signer.public().as_array_ref()).into()) + .map(|(address, _, _)| { + *address == bp_polkadot::AccountId::from(*signer.public().as_array_ref()).into() + }) .unwrap_or(false) } fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { - call: tx.function, - nonce: extra.nonce(), - tip: extra.tip(), - }) + Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) } } diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs index 1c5d42a00c222..e21b27f6d3dea 100644 --- a/relays/client-polkadot/src/runtime.rs +++ b/relays/client-polkadot/src/runtime.rs @@ -128,7 +128,9 @@ pub enum BridgeKusamaMessagesCall { ), #[codec(index = 6)] receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + bp_kusama::Hash, + >, UnrewardedRelayersState, ), } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index f7ba2ca65cba8..42ed8bce3bd9b 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -18,8 +18,8 @@ use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -100,7 +100,12 @@ impl TransactionSignScheme for Rialto { let signer: sp_runtime::MultiSigner = signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - rialto_runtime::UncheckedExtrinsic::new_signed(call, signer.into_account().into(), signature.into(), extra) + rialto_runtime::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + ) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -118,9 +123,7 @@ impl TransactionSignScheme for Rialto { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { call: tx.function, - nonce: Compact::>::decode(&mut &extra.4.encode()[..]) - .ok()? - .into(), + nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? .into(), diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 4d6e3b969c2a1..ad61e3cfd6437 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -18,7 +18,8 @@ use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -78,7 +79,13 @@ impl TransactionSignScheme for Rococo { ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( unsigned.call, - bp_rococo::SignedExtensions::new(bp_rococo::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), + bp_rococo::SignedExtensions::new( + bp_rococo::VERSION, + era, + genesis_hash, + unsigned.nonce, + unsigned.tip, + ), ) .expect("SignedExtension never fails."); @@ -101,17 +108,15 @@ impl TransactionSignScheme for Rococo { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| *address == bp_rococo::AccountId::from(*signer.public().as_array_ref()).into()) + .map(|(address, _, _)| { + *address == bp_rococo::AccountId::from(*signer.public().as_array_ref()).into() + }) .unwrap_or(false) } fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { - call: tx.function, - nonce: extra.nonce(), - tip: extra.tip(), - }) + Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) } } diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index b68aea985e772..a82aa81a792cc 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -115,7 +115,9 @@ pub enum BridgeMessagesWococoCall { ), #[codec(index = 6)] receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + bp_wococo::Hash, + >, UnrewardedRelayersState, ), } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 84db77ec6dfd5..c3d4e30452423 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -92,11 +92,7 @@ pub struct UnsignedTransaction { impl UnsignedTransaction { /// Create new unsigned transaction with given call, nonce and zero tip. pub fn new(call: C::Call, nonce: C::Index) -> Self { - Self { - call, - nonce, - tip: Zero::zero(), - } + Self { call, nonce, tip: Zero::zero() } } /// Set transaction tip. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index be483243df0be..ca197867bc4b2 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -16,17 +16,21 @@ //! Substrate node client. -use crate::chain::{Chain, ChainWithBalances, TransactionStatusOf}; -use crate::rpc::Substrate; -use crate::{ConnectionParams, Error, HashOf, HeaderIdOf, Result}; +use crate::{ + chain::{Chain, ChainWithBalances, TransactionStatusOf}, + rpc::Substrate, + ConnectionParams, Error, HashOf, HeaderIdOf, Result, +}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; -use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned}; -use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; +use jsonrpsee_ws_client::{ + traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned, WsClient as RpcClient, + WsClientBuilder as RpcClientBuilder, +}; use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; @@ -62,9 +66,10 @@ pub struct Client { client: Arc, /// Genesis block hash. genesis_hash: HashOf, - /// If several tasks are submitting their transactions simultaneously using `submit_signed_extrinsic` - /// method, they may get the same transaction nonce. So one of transactions will be rejected - /// from the pool. This lock is here to prevent situations like that. + /// If several tasks are submitting their transactions simultaneously using + /// `submit_signed_extrinsic` method, they may get the same transaction nonce. So one of + /// transactions will be rejected from the pool. This lock is here to prevent situations like + /// that. submit_signed_extrinsic_lock: Arc>, } @@ -94,9 +99,7 @@ impl Clone for Client { impl std::fmt::Debug for Client { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("Client") - .field("genesis_hash", &self.genesis_hash) - .finish() + fmt.debug_struct("Client").field("genesis_hash", &self.genesis_hash).finish() } } @@ -130,7 +133,9 @@ impl Client { let number: C::BlockNumber = Zero::zero(); let genesis_hash_client = client.clone(); let genesis_hash = tokio - .spawn(async move { Substrate::::chain_get_block_hash(&*genesis_hash_client, number).await }) + .spawn(async move { + Substrate::::chain_get_block_hash(&*genesis_hash_client, number).await + }) .await??; Ok(Self { @@ -143,7 +148,9 @@ impl Client { } /// Build client to use in connection. - async fn build_client(params: ConnectionParams) -> Result<(Arc, Arc)> { + async fn build_client( + params: ConnectionParams, + ) -> Result<(Arc, Arc)> { let tokio = tokio::runtime::Runtime::new()?; let uri = format!( "{}://{}:{}", @@ -186,16 +193,15 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { - self.jsonrpsee_execute(|client| async move { Ok(Substrate::::chain_get_finalized_head(&*client).await?) }) - .await + self.jsonrpsee_execute(|client| async move { + Ok(Substrate::::chain_get_finalized_head(&*client).await?) + }) + .await } /// Return number of the best finalized block. pub async fn best_finalized_header_number(&self) -> Result { - Ok(*self - .header_by_hash(self.best_finalized_header_hash().await?) - .await? - .number()) + Ok(*self.header_by_hash(self.best_finalized_header_hash().await?).await?.number()) } /// Returns the best Substrate header. @@ -203,15 +209,17 @@ impl Client { where C::Header: DeserializeOwned, { - self.jsonrpsee_execute(|client| async move { Ok(Substrate::::chain_get_header(&*client, None).await?) }) - .await + self.jsonrpsee_execute(|client| async move { + Ok(Substrate::::chain_get_header(&*client, None).await?) + }) + .await } /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { - self.jsonrpsee_execute( - move |client| async move { Ok(Substrate::::chain_get_block(&*client, block_hash).await?) }, - ) + self.jsonrpsee_execute(move |client| async move { + Ok(Substrate::::chain_get_block(&*client, block_hash).await?) + }) .await } @@ -246,8 +254,10 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { - self.jsonrpsee_execute(move |client| async move { Ok(Substrate::::state_runtime_version(&*client).await?) }) - .await + self.jsonrpsee_execute(move |client| async move { + Ok(Substrate::::state_runtime_version(&*client).await?) + }) + .await } /// Read value from runtime storage. @@ -259,7 +269,9 @@ impl Client { self.jsonrpsee_execute(move |client| async move { Substrate::::state_get_storage(&*client, storage_key, block_hash) .await? - .map(|encoded_value| T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed)) + .map(|encoded_value| { + T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed) + }) .transpose() }) .await @@ -272,12 +284,14 @@ impl Client { { self.jsonrpsee_execute(move |client| async move { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = Substrate::::state_get_storage(&*client, storage_key, None) - .await? - .ok_or(Error::AccountDoesNotExist)?; - let decoded_account_data = - AccountInfo::>::decode(&mut &encoded_account_data.0[..]) - .map_err(Error::ResponseParseFailed)?; + let encoded_account_data = + Substrate::::state_get_storage(&*client, storage_key, None) + .await? + .ok_or(Error::AccountDoesNotExist)?; + let decoded_account_data = AccountInfo::>::decode( + &mut &encoded_account_data.0[..], + ) + .map_err(Error::ResponseParseFailed)?; Ok(decoded_account_data.data.free) }) .await @@ -348,9 +362,8 @@ impl Client { let subscription = client .subscribe( "author_submitAndWatchExtrinsic", - JsonRpcParams::Array(vec![ - jsonrpsee_types::to_json_value(extrinsic).map_err(|e| Error::RpcError(e.into()))? - ]), + JsonRpcParams::Array(vec![jsonrpsee_types::to_json_value(extrinsic) + .map_err(|e| Error::RpcError(e.into()))?]), "author_unwatchExtrinsic", ) .await?; @@ -370,9 +383,9 @@ impl Client { /// Returns pending extrinsics from transaction pool. pub async fn pending_extrinsics(&self) -> Result> { - self.jsonrpsee_execute( - move |client| async move { Ok(Substrate::::author_pending_extrinsics(&*client).await?) }, - ) + self.jsonrpsee_execute(move |client| async move { + Ok(Substrate::::author_pending_extrinsics(&*client).await?) + }) .await } @@ -386,9 +399,10 @@ impl Client { let call = SUB_API_TXPOOL_VALIDATE_TRANSACTION.to_string(); let data = Bytes((TransactionSource::External, transaction, at_block).encode()); - let encoded_response = Substrate::::state_call(&*client, call, data, Some(at_block)).await?; - let validity = - TransactionValidity::decode(&mut &encoded_response.0[..]).map_err(Error::ResponseParseFailed)?; + let encoded_response = + Substrate::::state_call(&*client, call, data, Some(at_block)).await?; + let validity = TransactionValidity::decode(&mut &encoded_response.0[..]) + .map_err(Error::ResponseParseFailed)?; Ok(validity) }) @@ -396,9 +410,13 @@ impl Client { } /// Estimate fee that will be spent on given extrinsic. - pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result> { + pub async fn estimate_extrinsic_fee( + &self, + transaction: Bytes, + ) -> Result> { self.jsonrpsee_execute(move |client| async move { - let fee_details = Substrate::::payment_query_fee_details(&*client, transaction, None).await?; + let fee_details = + Substrate::::payment_query_fee_details(&*client, transaction, None).await?; let inclusion_fee = fee_details .inclusion_fee .map(|inclusion_fee| InclusionFee { @@ -406,8 +424,10 @@ impl Client { .unwrap_or_else(|_| C::Balance::max_value()), len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) .unwrap_or_else(|_| C::Balance::max_value()), - adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), + adjusted_weight_fee: C::Balance::try_from( + inclusion_fee.adjusted_weight_fee.into_u256(), + ) + .unwrap_or_else(|_| C::Balance::max_value()), }) .unwrap_or_else(|| InclusionFee { base_fee: Zero::zero(), @@ -420,12 +440,16 @@ impl Client { } /// Get the GRANDPA authority set at given block. - pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result { + pub async fn grandpa_authorities_set( + &self, + block: C::Hash, + ) -> Result { self.jsonrpsee_execute(move |client| async move { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); - let encoded_response = Substrate::::state_call(&*client, call, data, Some(block)).await?; + let encoded_response = + Substrate::::state_call(&*client, call, data, Some(block)).await?; let authority_list = encoded_response.0; Ok(authority_list) @@ -434,7 +458,12 @@ impl Client { } /// Execute runtime call at given block. - pub async fn state_call(&self, method: String, data: Bytes, at_block: Option) -> Result { + pub async fn state_call( + &self, + method: String, + data: Bytes, + at_block: Option, + ) -> Result { self.jsonrpsee_execute(move |client| async move { Substrate::::state_call(&*client, method, data, at_block) .await @@ -444,7 +473,11 @@ impl Client { } /// Returns storage proof of given storage keys. - pub async fn prove_storage(&self, keys: Vec, at_block: C::Hash) -> Result { + pub async fn prove_storage( + &self, + keys: Vec, + at_block: C::Hash, + ) -> Result { self.jsonrpsee_execute(move |client| async move { Substrate::::state_prove_storage(&*client, keys, Some(at_block)) .await @@ -485,9 +518,7 @@ impl Client { T: Send + 'static, { let client = self.client.clone(); - self.tokio - .spawn(async move { make_jsonrpsee_future(client).await }) - .await? + self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? } } @@ -508,11 +539,10 @@ impl Subscription { ) { loop { match subscription.next().await { - Ok(Some(item)) => { + Ok(Some(item)) => if sender.send(Some(item)).await.is_err() { - break; - } - } + break + }, Ok(None) => { log::trace!( target: "bridge", @@ -521,8 +551,8 @@ impl Subscription { item_type, ); let _ = sender.send(None).await; - break; - } + break + }, Err(e) => { log::trace!( target: "bridge", @@ -532,8 +562,8 @@ impl Subscription { e, ); let _ = sender.send(None).await; - break; - } + break + }, } } } diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 187b4a1e633f5..d3444516429be 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -96,10 +96,10 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::RpcError(RpcError::Transport(_)) - | Error::RpcError(RpcError::Internal(_)) - | Error::RpcError(RpcError::RestartNeeded(_)) - | Error::ClientNotSynced(_), + Error::RpcError(RpcError::Transport(_)) | + Error::RpcError(RpcError::Internal(_)) | + Error::RpcError(RpcError::RestartNeeded(_)) | + Error::ClientNotSynced(_), ) } } @@ -110,9 +110,11 @@ impl std::fmt::Display for Error { Self::Io(e) => e.to_string(), Self::RpcError(e) => e.to_string(), Self::ResponseParseFailed(e) => e.to_string(), - Self::UninitializedBridgePallet => "The Substrate bridge pallet has not been initialized yet.".into(), + Self::UninitializedBridgePallet => + "The Substrate bridge pallet has not been initialized yet.".into(), Self::AccountDoesNotExist => "Account does not exist on the chain".into(), - Self::MissingMandatoryCodeEntry => "Mandatory :code: entry is missing from runtime storage".into(), + Self::MissingMandatoryCodeEntry => + "Mandatory :code: entry is missing from runtime storage".into(), Self::StorageProofError(e) => format!("Error when parsing storage proof: {:?}", e), Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), Self::TransactionInvalid(e) => format!("Substrate transaction is invalid: {:?}", e), diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 81a98d2f1e9c6..0059429dcb418 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -16,10 +16,12 @@ //! Default generic implementation of finality source for basic Substrate client. -use crate::chain::{BlockWithJustification, Chain}; -use crate::client::Client; -use crate::error::Error; -use crate::sync_header::SyncHeader; +use crate::{ + chain::{BlockWithJustification, Chain}, + client::Client, + error::Error, + sync_header::SyncHeader, +}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; @@ -43,12 +45,11 @@ pub struct FinalitySource { impl FinalitySource { /// Create new headers source using given client. - pub fn new(client: Client, maximal_header_number: Option>) -> Self { - FinalitySource { - client, - maximal_header_number, - _phantom: Default::default(), - } + pub fn new( + client: Client, + maximal_header_number: Option>, + ) -> Self { + FinalitySource { client, maximal_header_number, _phantom: Default::default() } } /// Returns reference to the underlying RPC client. @@ -122,7 +123,9 @@ where let justification = signed_block .justification() - .map(|raw_justification| GrandpaJustification::::decode(&mut raw_justification.as_slice())) + .map(|raw_justification| { + GrandpaJustification::::decode(&mut raw_justification.as_slice()) + }) .transpose() .map_err(Error::ResponseParseFailed)?; @@ -155,11 +158,11 @@ where Ok(j) => j, Err(err) => { log_error(format!("decode failed with error {:?}", err)); - continue; - } + continue + }, }; - return Some((justification, subscription)); + return Some((justification, subscription)) } }, ) diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 093cc50f052a6..b6ec83f98408c 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -52,7 +52,10 @@ pub trait Environment: Send + Sync + 'static { } /// Abort when runtime spec version is different from specified. -pub fn abort_on_spec_version_change(mut env: impl Environment, expected_spec_version: u32) { +pub fn abort_on_spec_version_change( + mut env: impl Environment, + expected_spec_version: u32, +) { async_std::task::spawn(async move { loop { let actual_spec_version = env.runtime_version().await; @@ -68,7 +71,7 @@ pub fn abort_on_spec_version_change(mut env: impl Environm ); env.abort().await; - } + }, Err(error) => log::warn!( target: "bridge-guard", "Failed to read {} runtime version: {:?}. Relay may need to be stopped manually", @@ -83,7 +86,8 @@ pub fn abort_on_spec_version_change(mut env: impl Environm } /// Abort if, during 24 hours, free balance of given account is decreased at least by given value. -/// Other components may increase (or decrease) balance of account and it WILL affect logic of the guard. +/// Other components may increase (or decrease) balance of account and it WILL affect logic of the +/// guard. pub fn abort_when_account_balance_decreased( mut env: impl Environment, account_id: C::AccountId, @@ -129,7 +133,7 @@ pub fn abort_when_account_balance_decreased( env.abort().await; } - } + }, Err(error) => { log::warn!( target: "bridge-guard", @@ -138,7 +142,7 @@ pub fn abort_when_account_balance_decreased( account_id, error, ); - } + }, }; env.sleep(conditions_check_delay::()).await; @@ -158,9 +162,7 @@ impl Environment for Client { } async fn free_native_balance(&mut self, account: C::AccountId) -> Result { - Client::::free_native_balance(self, account) - .await - .map_err(|e| e.to_string()) + Client::::free_native_balance(self, account).await.map_err(|e| e.to_string()) } } @@ -196,8 +198,9 @@ mod tests { const STORAGE_PROOF_OVERHEAD: u32 = 0; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; - type SignedBlock = - sp_runtime::generic::SignedBlock>; + type SignedBlock = sp_runtime::generic::SignedBlock< + sp_runtime::generic::Block, + >; type Call = (); type WeightToFee = IdentityFee; } @@ -257,10 +260,7 @@ mod tests { // client responds with wrong version runtime_version_tx - .send(RuntimeVersion { - spec_version: 42, - ..Default::default() - }) + .send(RuntimeVersion { spec_version: 42, ..Default::default() }) .await .unwrap(); @@ -292,10 +292,7 @@ mod tests { // client responds with the same version runtime_version_tx - .send(RuntimeVersion { - spec_version: 42, - ..Default::default() - }) + .send(RuntimeVersion { spec_version: 42, ..Default::default() }) .await .unwrap(); diff --git a/relays/client-substrate/src/headers_source.rs b/relays/client-substrate/src/headers_source.rs index 3dfcb220de453..e3839bf2c8ba1 100644 --- a/relays/client-substrate/src/headers_source.rs +++ b/relays/client-substrate/src/headers_source.rs @@ -16,9 +16,11 @@ //! Default generic implementation of headers source for basic Substrate client. -use crate::chain::{BlockWithJustification, Chain}; -use crate::client::Client; -use crate::error::Error; +use crate::{ + chain::{BlockWithJustification, Chain}, + client::Client, + error::Error, +}; use async_trait::async_trait; use headers_relay::{ @@ -38,19 +40,13 @@ pub struct HeadersSource { impl HeadersSource { /// Create new headers source using given client. pub fn new(client: Client) -> Self { - HeadersSource { - client, - _phantom: Default::default(), - } + HeadersSource { client, _phantom: Default::default() } } } impl Clone for HeadersSource { fn clone(&self) -> Self { - HeadersSource { - client: self.client.clone(), - _phantom: Default::default(), - } + HeadersSource { client: self.client.clone(), _phantom: Default::default() } } } @@ -69,7 +65,12 @@ where C: Chain, C::BlockNumber: relay_utils::BlockNumberBase, C::Header: Into, - P: HeadersSyncPipeline, + P: HeadersSyncPipeline< + Extra = (), + Completion = EncodedJustification, + Hash = C::Hash, + Number = C::BlockNumber, + >, P::Header: SourceHeader, { async fn best_block_number(&self) -> Result { @@ -79,22 +80,17 @@ where } async fn header_by_hash(&self, hash: P::Hash) -> Result { - self.client - .header_by_hash(hash) - .await - .map(Into::into) - .map_err(Into::into) + self.client.header_by_hash(hash).await.map(Into::into).map_err(Into::into) } async fn header_by_number(&self, number: P::Number) -> Result { - self.client - .header_by_number(number) - .await - .map(Into::into) - .map_err(Into::into) + self.client.header_by_number(number).await.map(Into::into).map_err(Into::into) } - async fn header_completion(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, Option), Error> { + async fn header_completion( + &self, + id: HeaderIdOf

, + ) -> Result<(HeaderIdOf

, Option), Error> { let hash = id.1; let signed_block = self.client.get_block(Some(hash)).await?; let grandpa_justification = signed_block.justification().cloned(); @@ -102,7 +98,11 @@ where Ok((id, grandpa_justification)) } - async fn header_extra(&self, id: HeaderIdOf

, _header: QueuedHeader

) -> Result<(HeaderIdOf

, ()), Error> { + async fn header_extra( + &self, + id: HeaderIdOf

, + _header: QueuedHeader

, + ) -> Result<(HeaderIdOf

, ()), Error> { Ok((id, ())) } } diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index d801569df32fd..634bdcdca196e 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -31,16 +31,18 @@ pub mod metrics; use std::time::Duration; -pub use crate::chain::{ - BlockWithJustification, CallOf, Chain, ChainWithBalances, TransactionSignScheme, TransactionStatusOf, - UnsignedTransaction, WeightToFeeOf, +pub use crate::{ + chain::{ + BlockWithJustification, CallOf, Chain, ChainWithBalances, TransactionSignScheme, + TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, + }, + client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, + error::{Error, Result}, + sync_header::SyncHeader, }; -pub use crate::client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}; -pub use crate::error::{Error, Result}; -pub use crate::sync_header::SyncHeader; pub use bp_runtime::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, IndexOf, SignatureOf, - TransactionEra, TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, + IndexOf, SignatureOf, TransactionEra, TransactionEraOf, }; /// Header id used by the chain. @@ -59,11 +61,7 @@ pub struct ConnectionParams { impl Default for ConnectionParams { fn default() -> Self { - ConnectionParams { - host: "localhost".into(), - port: 9944, - secure: false, - } + ConnectionParams { host: "localhost".into(), port: 9944, secure: false } } } @@ -73,7 +71,11 @@ impl Default for ConnectionParams { /// been mined for this period. /// /// Returns `None` if mortality period is `None` -pub fn transaction_stall_timeout(mortality_period: Option, average_block_interval: Duration) -> Option { +pub fn transaction_stall_timeout( + mortality_period: Option, + average_block_interval: Duration, +) -> Option { // 1 extra block for transaction to reach the pool && 1 for relayer to awake after it is mined - mortality_period.map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1)) + mortality_period + .map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1)) } diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index 1b9a3f824edc9..f591a7a98105e 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -14,8 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::chain::Chain; -use crate::client::Client; +use crate::{chain::Chain, client::Client}; use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; @@ -83,7 +82,8 @@ where .await .map(|maybe_storage_value| { maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { - storage_value.into_inner().unique_saturated_into() as f64 / T::DIV.unique_saturated_into() as f64 + storage_value.into_inner().unique_saturated_into() as f64 / + T::DIV.unique_saturated_into() as f64 }) }) .map_err(drop); diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs index 526fe1e048bfc..c3b69c32f5728 100644 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::chain::Chain; -use crate::client::Client; -use crate::error::Error; +use crate::{chain::Chain, client::Client, error::Error}; use async_trait::async_trait; -use relay_utils::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, U64}; +use relay_utils::metrics::{ + metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, U64, +}; use sp_core::storage::StorageKey; use sp_runtime::traits::Header as HeaderT; use sp_storage::well_known_keys::CODE; @@ -40,10 +40,7 @@ pub struct StorageProofOverheadMetric { impl Clone for StorageProofOverheadMetric { fn clone(&self) -> Self { - StorageProofOverheadMetric { - client: self.client.clone(), - metric: self.metric.clone(), - } + StorageProofOverheadMetric { client: self.client.clone(), metric: self.metric.clone() } } } @@ -73,15 +70,15 @@ impl StorageProofOverheadMetric { .await?; let storage_proof_size: usize = storage_proof.clone().iter_nodes().map(|n| n.len()).sum(); - let storage_value_reader = - bp_runtime::StorageProofChecker::::new(*best_header.state_root(), storage_proof) - .map_err(Error::StorageProofError)?; - let maybe_encoded_storage_value = storage_value_reader - .read_value(CODE) - .map_err(Error::StorageProofError)?; - let encoded_storage_value_size = maybe_encoded_storage_value - .ok_or(Error::MissingMandatoryCodeEntry)? - .len(); + let storage_value_reader = bp_runtime::StorageProofChecker::::new( + *best_header.state_root(), + storage_proof, + ) + .map_err(Error::StorageProofError)?; + let maybe_encoded_storage_value = + storage_value_reader.read_value(CODE).map_err(Error::StorageProofError)?; + let encoded_storage_value_size = + maybe_encoded_storage_value.ok_or(Error::MissingMandatoryCodeEntry)?.len(); Ok(storage_proof_size - encoded_storage_value_size) } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index e6a0c0649b7dd..d61915ec12370 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -18,7 +18,8 @@ use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -78,7 +79,13 @@ impl TransactionSignScheme for Wococo { ) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( unsigned.call, - bp_wococo::SignedExtensions::new(bp_wococo::VERSION, era, genesis_hash, unsigned.nonce, unsigned.tip), + bp_wococo::SignedExtensions::new( + bp_wococo::VERSION, + era, + genesis_hash, + unsigned.nonce, + unsigned.tip, + ), ) .expect("SignedExtension never fails."); @@ -101,17 +108,15 @@ impl TransactionSignScheme for Wococo { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| *address == bp_wococo::AccountId::from(*signer.public().as_array_ref()).into()) + .map(|(address, _, _)| { + *address == bp_wococo::AccountId::from(*signer.public().as_array_ref()).into() + }) .unwrap_or(false) } fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { - call: tx.function, - nonce: extra.nonce(), - tip: extra.tip(), - }) + Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) } } diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index daf20156d69e8..c4835372306e5 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -115,7 +115,9 @@ pub enum BridgeMessagesRococoCall { ), #[codec(index = 6)] receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof, + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + bp_rococo::Hash, + >, UnrewardedRelayersState, ), } diff --git a/relays/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs index b87b99ee4207e..b48a094ee3d5d 100644 --- a/relays/exchange/src/exchange.rs +++ b/relays/exchange/src/exchange.rs @@ -18,7 +18,8 @@ use async_trait::async_trait; use relay_utils::{ - relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, StringifiedMaybeConnectionError, + relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, + StringifiedMaybeConnectionError, }; use std::{ fmt::{Debug, Display}, @@ -96,12 +97,18 @@ pub trait SourceClient: RelayClient { async fn block_by_hash(&self, hash: BlockHashOf

) -> Result; /// Get canonical block by number. async fn block_by_number(&self, number: BlockNumberOf

) -> Result; - /// Return block + index where transaction has been **mined**. May return `Ok(None)` if transaction - /// is unknown to the source node. - async fn transaction_block(&self, hash: &TransactionHashOf

) - -> Result, usize)>, Self::Error>; + /// Return block + index where transaction has been **mined**. May return `Ok(None)` if + /// transaction is unknown to the source node. + async fn transaction_block( + &self, + hash: &TransactionHashOf

, + ) -> Result, usize)>, Self::Error>; /// Prepare transaction proof. - async fn transaction_proof(&self, block: &P::Block, tx_index: usize) -> Result; + async fn transaction_proof( + &self, + block: &P::Block, + tx_index: usize, + ) -> Result; } /// Target client API. @@ -116,9 +123,13 @@ pub trait TargetClient: RelayClient { /// Returns best finalized header id. async fn best_finalized_header_id(&self) -> Result, Self::Error>; /// Returns `Ok(true)` if transaction proof is need to be relayed. - async fn filter_transaction_proof(&self, proof: &P::TransactionProof) -> Result; + async fn filter_transaction_proof( + &self, + proof: &P::TransactionProof, + ) -> Result; /// Submits transaction proof to the target node. - async fn submit_transaction_proof(&self, proof: P::TransactionProof) -> Result<(), Self::Error>; + async fn submit_transaction_proof(&self, proof: P::TransactionProof) + -> Result<(), Self::Error>; } /// Block transaction statistics. @@ -154,27 +165,28 @@ pub async fn relay_block_transactions( for (source_tx_index, source_tx) in transactions_to_process { let result = async { let source_tx_id = format!("{}/{}", source_block.id().1, source_tx_index); - let source_tx_proof = - prepare_transaction_proof(source_client, &source_tx_id, source_block, source_tx_index) - .await - .map_err(|e| (FailedClient::Source, e))?; + let source_tx_proof = prepare_transaction_proof( + source_client, + &source_tx_id, + source_block, + source_tx_index, + ) + .await + .map_err(|e| (FailedClient::Source, e))?; let needs_to_be_relayed = - target_client - .filter_transaction_proof(&source_tx_proof) - .await - .map_err(|err| { - ( - FailedClient::Target, - StringifiedMaybeConnectionError::new( - err.is_connection_error(), - format!("Transaction filtering has failed with {:?}", err), - ), - ) - })?; + target_client.filter_transaction_proof(&source_tx_proof).await.map_err(|err| { + ( + FailedClient::Target, + StringifiedMaybeConnectionError::new( + err.is_connection_error(), + format!("Transaction filtering has failed with {:?}", err), + ), + ) + })?; if !needs_to_be_relayed { - return Ok(false); + return Ok(false) } relay_ready_transaction_proof(target_client, &source_tx_id, source_tx_proof) @@ -191,13 +203,14 @@ pub async fn relay_block_transactions( // Option#1 may seems better, but: // 1) we do not track if transaction is mined (without an error) by the target node; // 2) error could be irrecoverable (e.g. when block is already pruned by bridge module or tx - // has invalid format) && we'll end up in infinite loop of retrying the same transaction proof. + // has invalid format) && we'll end up in infinite loop of retrying the same transaction + // proof. // // So we're going with option#2 here (the only exception are connection errors). match result { Ok(false) => { relayed_transactions.processed += 1; - } + }, Ok(true) => { log::info!( target: "bridge", @@ -209,7 +222,7 @@ pub async fn relay_block_transactions( relayed_transactions.processed += 1; relayed_transactions.relayed += 1; - } + }, Err((failed_client, err)) => { log::error!( target: "bridge", @@ -226,12 +239,12 @@ pub async fn relay_block_transactions( ); if err.is_connection_error() { - return Err((failed_client, relayed_transactions)); + return Err((failed_client, relayed_transactions)) } relayed_transactions.processed += 1; relayed_transactions.failed += 1; - } + }, } } @@ -245,7 +258,8 @@ pub async fn relay_single_transaction_proof( source_tx_hash: TransactionHashOf

, ) -> Result<(), String> { // wait for transaction and header on source node - let (source_header_id, source_tx_index) = wait_transaction_mined(source_client, &source_tx_hash).await?; + let (source_header_id, source_tx_index) = + wait_transaction_mined(source_client, &source_tx_hash).await?; let source_block = source_client.block_by_hash(source_header_id.1.clone()).await; let source_block = source_block.map_err(|err| { format!( @@ -302,20 +316,17 @@ async fn relay_ready_transaction_proof( source_tx_id: &str, source_tx_proof: P::TransactionProof, ) -> Result<(), StringifiedMaybeConnectionError> { - target_client - .submit_transaction_proof(source_tx_proof) - .await - .map_err(|err| { - StringifiedMaybeConnectionError::new( - err.is_connection_error(), - format!( - "Error submitting transaction {} proof to {} node: {:?}", - source_tx_id, - P::TARGET_NAME, - err, - ), - ) - }) + target_client.submit_transaction_proof(source_tx_proof).await.map_err(|err| { + StringifiedMaybeConnectionError::new( + err.is_connection_error(), + format!( + "Error submitting transaction {} proof to {} node: {:?}", + source_tx_id, + P::TARGET_NAME, + err, + ), + ) + }) } /// Wait until transaction is mined by source node. @@ -324,14 +335,15 @@ async fn wait_transaction_mined( source_tx_hash: &TransactionHashOf

, ) -> Result<(HeaderId

, usize), String> { loop { - let source_header_and_tx = source_client.transaction_block(source_tx_hash).await.map_err(|err| { - format!( - "Error retrieving transaction {} from {} node: {:?}", - source_tx_hash, - P::SOURCE_NAME, - err, - ) - })?; + let source_header_and_tx = + source_client.transaction_block(source_tx_hash).await.map_err(|err| { + format!( + "Error retrieving transaction {} from {} node: {:?}", + source_tx_hash, + P::SOURCE_NAME, + err, + ) + })?; match source_header_and_tx { Some((source_header_id, source_tx)) => { log::info!( @@ -341,8 +353,8 @@ async fn wait_transaction_mined( P::SOURCE_NAME, ); - return Ok((source_header_id, source_tx)); - } + return Ok((source_header_id, source_tx)) + }, None => { log::info!( target: "bridge", @@ -352,7 +364,7 @@ async fn wait_transaction_mined( ); source_client.tick().await; - } + }, } } } @@ -363,15 +375,16 @@ async fn wait_header_imported( source_header_id: &HeaderId

, ) -> Result<(), String> { loop { - let is_header_known = target_client.is_header_known(source_header_id).await.map_err(|err| { - format!( - "Failed to check existence of header {}/{} on {} node: {:?}", - source_header_id.0, - source_header_id.1, - P::TARGET_NAME, - err, - ) - })?; + let is_header_known = + target_client.is_header_known(source_header_id).await.map_err(|err| { + format!( + "Failed to check existence of header {}/{} on {} node: {:?}", + source_header_id.0, + source_header_id.1, + P::TARGET_NAME, + err, + ) + })?; match is_header_known { true => { log::info!( @@ -382,8 +395,8 @@ async fn wait_header_imported( P::TARGET_NAME, ); - return Ok(()); - } + return Ok(()) + }, false => { log::info!( target: "bridge", @@ -394,7 +407,7 @@ async fn wait_header_imported( ); target_client.tick().await; - } + }, } } } @@ -405,10 +418,8 @@ async fn wait_header_finalized( source_header_id: &HeaderId

, ) -> Result<(), String> { loop { - let is_header_finalized = target_client - .is_header_finalized(source_header_id) - .await - .map_err(|err| { + let is_header_finalized = + target_client.is_header_finalized(source_header_id).await.map_err(|err| { format!( "Failed to check finality of header {}/{} on {} node: {:?}", source_header_id.0, @@ -427,8 +438,8 @@ async fn wait_header_finalized( P::TARGET_NAME, ); - return Ok(()); - } + return Ok(()) + }, false => { log::info!( target: "bridge", @@ -439,7 +450,7 @@ async fn wait_header_finalized( ); target_client.tick().await; - } + }, } } } @@ -582,15 +593,22 @@ pub(crate) mod tests { self.data.lock().block.clone() } - async fn transaction_block(&self, _: &TestTransactionHash) -> Result, TestError> { + async fn transaction_block( + &self, + _: &TestTransactionHash, + ) -> Result, TestError> { self.data.lock().transaction_block.clone() } - async fn transaction_proof(&self, block: &TestBlock, index: usize) -> Result { + async fn transaction_proof( + &self, + block: &TestBlock, + index: usize, + ) -> Result { let tx_hash = block.1[index].hash(); let proof_error = self.data.lock().proofs_to_fail.get(&tx_hash).cloned(); if let Some(err) = proof_error { - return Err(err); + return Err(err) } Ok(TestTransactionProof(tx_hash)) @@ -653,19 +671,32 @@ pub(crate) mod tests { self.data.lock().best_finalized_header_id.clone() } - async fn filter_transaction_proof(&self, proof: &TestTransactionProof) -> Result { + async fn filter_transaction_proof( + &self, + proof: &TestTransactionProof, + ) -> Result { Ok(self.data.lock().transactions_to_accept.contains(&proof.0)) } - async fn submit_transaction_proof(&self, proof: TestTransactionProof) -> Result<(), TestError> { + async fn submit_transaction_proof( + &self, + proof: TestTransactionProof, + ) -> Result<(), TestError> { self.data.lock().submitted_proofs.push(proof); Ok(()) } } - fn ensure_relay_single_success(source: &TestTransactionsSource, target: &TestTransactionsTarget) { + fn ensure_relay_single_success( + source: &TestTransactionsSource, + target: &TestTransactionsTarget, + ) { assert_eq!( - async_std::task::block_on(relay_single_transaction_proof(source, target, test_transaction_hash(0),)), + async_std::task::block_on(relay_single_transaction_proof( + source, + target, + test_transaction_hash(0), + )), Ok(()), ); assert_eq!( @@ -782,11 +813,7 @@ pub(crate) mod tests { let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - target - .data - .lock() - .transactions_to_accept - .remove(&test_transaction_hash(0)); + target.data.lock().transactions_to_accept.remove(&test_transaction_hash(0)); ensure_relay_single_success(&source, &target) } @@ -814,25 +841,14 @@ pub(crate) mod tests { let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); // let's only accept tx#1 - target - .data - .lock() - .transactions_to_accept - .remove(&test_transaction_hash(0)); - target - .data - .lock() - .transactions_to_accept - .insert(test_transaction_hash(1)); + target.data.lock().transactions_to_accept.remove(&test_transaction_hash(0)); + target.data.lock().transactions_to_accept.insert(test_transaction_hash(1)); - let relayed_transactions = test_relay_block_transactions(&source, &target, Default::default()); + let relayed_transactions = + test_relay_block_transactions(&source, &target, Default::default()); assert_eq!( relayed_transactions, - Ok(RelayedBlockTransactions { - processed: 3, - relayed: 1, - failed: 0, - }), + Ok(RelayedBlockTransactions { processed: 3, relayed: 1, failed: 0 }), ); assert_eq!( target.data.lock().submitted_proofs, @@ -852,14 +868,11 @@ pub(crate) mod tests { .proofs_to_fail .insert(test_transaction_hash(0), TestError(false)); - let relayed_transactions = test_relay_block_transactions(&source, &target, Default::default()); + let relayed_transactions = + test_relay_block_transactions(&source, &target, Default::default()); assert_eq!( relayed_transactions, - Ok(RelayedBlockTransactions { - processed: 3, - relayed: 0, - failed: 1, - }), + Ok(RelayedBlockTransactions { processed: 3, relayed: 0, failed: 1 }), ); assert_eq!(target.data.lock().submitted_proofs, vec![],); } @@ -876,14 +889,11 @@ pub(crate) mod tests { .proofs_to_fail .insert(test_transaction_hash(1), TestError(true)); - let relayed_transactions = test_relay_block_transactions(&source, &target, Default::default()); + let relayed_transactions = + test_relay_block_transactions(&source, &target, Default::default()); assert_eq!( relayed_transactions, - Err(RelayedBlockTransactions { - processed: 1, - relayed: 1, - failed: 0, - }), + Err(RelayedBlockTransactions { processed: 1, relayed: 1, failed: 0 }), ); assert_eq!( target.data.lock().submitted_proofs, @@ -893,20 +903,13 @@ pub(crate) mod tests { // now do not fail on tx#2 source.data.lock().proofs_to_fail.clear(); // and also relay tx#3 - target - .data - .lock() - .transactions_to_accept - .insert(test_transaction_hash(2)); + target.data.lock().transactions_to_accept.insert(test_transaction_hash(2)); - let relayed_transactions = test_relay_block_transactions(&source, &target, relayed_transactions.unwrap_err()); + let relayed_transactions = + test_relay_block_transactions(&source, &target, relayed_transactions.unwrap_err()); assert_eq!( relayed_transactions, - Ok(RelayedBlockTransactions { - processed: 3, - relayed: 2, - failed: 0, - }), + Ok(RelayedBlockTransactions { processed: 3, relayed: 2, failed: 0 }), ); assert_eq!( target.data.lock().submitted_proofs, diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 0c13f1b5e5259..2b19a30e21244 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -16,11 +16,13 @@ //! Relaying proofs of exchange transactions. -use crate::exchange::{ - relay_block_transactions, BlockNumberOf, RelayedBlockTransactions, SourceClient, TargetClient, - TransactionProofPipeline, +use crate::{ + exchange::{ + relay_block_transactions, BlockNumberOf, RelayedBlockTransactions, SourceClient, + TargetClient, TransactionProofPipeline, + }, + exchange_loop_metrics::ExchangeLoopMetrics, }; -use crate::exchange_loop_metrics::ExchangeLoopMetrics; use backoff::backoff::Backoff; use futures::{future::FutureExt, select}; @@ -58,13 +60,13 @@ pub struct InMemoryStorage { impl InMemoryStorage { /// Created new in-memory storage with given best processed block number. pub fn new(best_processed_header_number: BlockNumber) -> Self { - InMemoryStorage { - best_processed_header_number, - } + InMemoryStorage { best_processed_header_number } } } -impl TransactionProofsRelayStorage for InMemoryStorage { +impl TransactionProofsRelayStorage + for InMemoryStorage +{ type BlockNumber = BlockNumber; fn state(&self) -> TransactionProofsRelayState { @@ -140,12 +142,11 @@ async fn run_until_connection_lost( if let Err((is_connection_error, failed_client)) = iteration_result { if is_connection_error { - return Err(failed_client); + return Err(failed_client) } - let retry_timeout = retry_backoff - .next_backoff() - .unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY); + let retry_timeout = + retry_backoff.next_backoff().unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY); select! { _ = async_std::task::sleep(retry_timeout).fuse() => {}, _ = exit_signal => return Ok(()), @@ -181,7 +182,7 @@ async fn run_loop_iteration( ); best_finalized_header_id - } + }, Err(err) => { log::error!( target: "bridge", @@ -191,14 +192,20 @@ async fn run_loop_iteration( err, ); - return Err((err.is_connection_error(), FailedClient::Target)); - } + return Err((err.is_connection_error(), FailedClient::Target)) + }, }; loop { // if we already have some finalized block body, try to relay its transactions if let Some((block, relayed_transactions)) = current_finalized_block.take() { - let result = relay_block_transactions(source_client, target_client, &block, relayed_transactions).await; + let result = relay_block_transactions( + source_client, + target_client, + &block, + relayed_transactions, + ) + .await; match result { Ok(relayed_transactions) => { @@ -212,7 +219,8 @@ async fn run_loop_iteration( relayed_transactions.failed, ); - state.best_processed_header_number = state.best_processed_header_number + One::one(); + state.best_processed_header_number = + state.best_processed_header_number + One::one(); storage.set_state(state); if let Some(exchange_loop_metrics) = exchange_loop_metrics { @@ -224,11 +232,11 @@ async fn run_loop_iteration( } // we have just updated state => proceed to next block retrieval - } + }, Err((failed_client, relayed_transactions)) => { *current_finalized_block = Some((block, relayed_transactions)); - return Err((true, failed_client)); - } + return Err((true, failed_client)) + }, } } @@ -242,8 +250,8 @@ async fn run_loop_iteration( *current_finalized_block = Some((block, RelayedBlockTransactions::default())); // we have received new finalized block => go back to relay its transactions - continue; - } + continue + }, Err(err) => { log::error!( target: "bridge", @@ -253,13 +261,13 @@ async fn run_loop_iteration( err, ); - return Err((err.is_connection_error(), FailedClient::Source)); - } + return Err((err.is_connection_error(), FailedClient::Source)) + }, } } // there are no any transactions we need to relay => wait for new data - return Ok(()); + return Ok(()) } } @@ -267,17 +275,16 @@ async fn run_loop_iteration( mod tests { use super::*; use crate::exchange::tests::{ - test_next_block, test_next_block_id, test_transaction_hash, TestTransactionProof, TestTransactionsSource, - TestTransactionsTarget, + test_next_block, test_next_block_id, test_transaction_hash, TestTransactionProof, + TestTransactionsSource, TestTransactionsTarget, }; use futures::{future::FutureExt, stream::StreamExt}; #[test] fn exchange_loop_is_able_to_relay_proofs() { - let storage = InMemoryStorage { - best_processed_header_number: 0, - }; - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no target ticks allowed"))); + let storage = InMemoryStorage { best_processed_header_number: 0 }; + let target = + TestTransactionsTarget::new(Box::new(|_| unreachable!("no target ticks allowed"))); let target_data = target.data.clone(); let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); @@ -295,11 +302,8 @@ mod tests { (true, false) => { data.block = Ok(test_next_block()); target_data.lock().best_finalized_header_id = Ok(test_next_block_id()); - target_data - .lock() - .transactions_to_accept - .insert(test_transaction_hash(1)); - } + target_data.lock().transactions_to_accept.insert(test_transaction_hash(1)); + }, _ => (), } })); diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 9a2795802d079..adfd3927de898 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -43,18 +43,19 @@ pub struct FinalitySyncParams { /// `min(source_block_time, target_block_time)`. /// /// This parameter may be used to limit transactions rate. Increase the value && you'll get - /// infrequent updates => sparse headers => potential slow down of bridge applications, but pallet storage - /// won't be super large. Decrease the value to near `source_block_time` and you'll get - /// transaction for (almost) every block of the source chain => all source headers will be known - /// to the target chain => bridge applications will run faster, but pallet storage may explode - /// (but if pruning is there, then it's fine). + /// infrequent updates => sparse headers => potential slow down of bridge applications, but + /// pallet storage won't be super large. Decrease the value to near `source_block_time` and + /// you'll get transaction for (almost) every block of the source chain => all source headers + /// will be known to the target chain => bridge applications will run faster, but pallet + /// storage may explode (but if pruning is there, then it's fine). pub tick: Duration, /// Number of finality proofs to keep in internal buffer between loop iterations. /// - /// While in "major syncing" state, we still read finality proofs from the stream. They're stored - /// in the internal buffer between loop iterations. When we're close to the tip of the chain, we may - /// meet finality delays if headers are not finalized frequently. So instead of waiting for next - /// finality proof to appear in the stream, we may use existing proof from that buffer. + /// While in "major syncing" state, we still read finality proofs from the stream. They're + /// stored in the internal buffer between loop iterations. When we're close to the tip of the + /// chain, we may meet finality delays if headers are not finalized frequently. So instead of + /// waiting for next finality proof to appear in the stream, we may use existing proof from + /// that buffer. pub recent_finality_proofs_limit: usize, /// Timeout before we treat our transactions as lost and restart the whole sync process. pub stall_timeout: Duration, @@ -89,10 +90,15 @@ pub trait TargetClient: RelayClient { async fn best_finalized_source_block_number(&self) -> Result; /// Submit header finality proof. - async fn submit_finality_proof(&self, header: P::Header, proof: P::FinalityProof) -> Result<(), Self::Error>; + async fn submit_finality_proof( + &self, + header: P::Header, + proof: P::FinalityProof, + ) -> Result<(), Self::Error>; } -/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop. +/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs +/// sync loop. pub fn metrics_prefix() -> String { format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) } @@ -127,15 +133,11 @@ pub async fn run( /// Unjustified headers container. Ordered by header number. pub(crate) type UnjustifiedHeaders = Vec; /// Finality proofs container. Ordered by target header number. -pub(crate) type FinalityProofs

= Vec<( -

::Number, -

::FinalityProof, -)>; +pub(crate) type FinalityProofs

= + Vec<(

::Number,

::FinalityProof)>; /// Reference to finality proofs container. -pub(crate) type FinalityProofsRef<'a, P> = &'a [( -

::Number, -

::FinalityProof, -)]; +pub(crate) type FinalityProofsRef<'a, P> = + &'a [(

::Number,

::FinalityProof)]; /// Error that may happen inside finality synchronization loop. #[derive(Debug)] @@ -186,10 +188,7 @@ pub(crate) struct RestartableFinalityProofsStream { #[cfg(test)] impl From for RestartableFinalityProofsStream { fn from(stream: S) -> Self { - RestartableFinalityProofsStream { - needs_restart: false, - stream: Box::pin(stream), - } + RestartableFinalityProofsStream { needs_restart: false, stream: Box::pin(stream) } } } @@ -260,14 +259,12 @@ async fn run_until_connection_lost( last_transaction = updated_last_transaction; retry_backoff.reset(); sync_params.tick - } + }, Err(error) => { log::error!(target: "bridge", "Finality sync loop iteration has failed with error: {:?}", error); error.fail_if_connection_error()?; - retry_backoff - .next_backoff() - .unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) - } + retry_backoff.next_backoff().unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) + }, }; if finality_proofs_stream.needs_restart { log::warn!(target: "bridge", "{} finality proofs stream is being restarted", P::SOURCE_NAME); @@ -297,10 +294,8 @@ where TC: TargetClient

, { // read best source headers ids from source and target nodes - let best_number_at_source = source_client - .best_finalized_block_number() - .await - .map_err(Error::Source)?; + let best_number_at_source = + source_client.best_finalized_block_number().await.map_err(Error::Source)?; let best_number_at_target = target_client .best_finalized_source_block_number() .await @@ -309,7 +304,8 @@ where metrics_sync.update_best_block_at_source(best_number_at_source); metrics_sync.update_best_block_at_target(best_number_at_target); } - *state.progress = print_sync_progress::

(*state.progress, best_number_at_source, best_number_at_target); + *state.progress = + print_sync_progress::

(*state.progress, best_number_at_source, best_number_at_target); // if we have already submitted header, then we just need to wait for it // if we're waiting too much, then we believe our transaction has been lost and restart sync @@ -324,9 +320,9 @@ where P::TARGET_NAME, ); - return Err(Error::Stalled); + return Err(Error::Stalled) } else { - return Ok(Some(last_transaction)); + return Ok(Some(last_transaction)) } } @@ -343,10 +339,8 @@ where .await? { Some((header, justification)) => { - let new_transaction = Transaction { - time: Instant::now(), - submitted_header_number: header.number(), - }; + let new_transaction = + Transaction { time: Instant::now(), submitted_header_number: header.number() }; log::debug!( target: "bridge", @@ -361,7 +355,7 @@ where .await .map_err(Error::Target)?; Ok(Some(new_transaction)) - } + }, None => Ok(None), } } @@ -398,15 +392,15 @@ where ) .await?; let (mut unjustified_headers, mut selected_finality_proof) = match selected_finality_proof { - SelectedFinalityProof::Mandatory(header, finality_proof) => return Ok(Some((header, finality_proof))), + SelectedFinalityProof::Mandatory(header, finality_proof) => + return Ok(Some((header, finality_proof))), _ if sync_params.only_mandatory_headers => { // we are not reading finality proofs from the stream, so eventually it'll break // but we don't care about transient proofs at all, so it is acceptable - return Ok(None); - } - SelectedFinalityProof::Regular(unjustified_headers, header, finality_proof) => { - (unjustified_headers, Some((header, finality_proof))) - } + return Ok(None) + }, + SelectedFinalityProof::Regular(unjustified_headers, header, finality_proof) => + (unjustified_headers, Some((header, finality_proof))), SelectedFinalityProof::None(unjustified_headers) => (unjustified_headers, None), }; @@ -451,7 +445,11 @@ pub(crate) enum SelectedFinalityProof { /// Otherwise, `SelectedFinalityProof::None` is returned. /// /// Unless we have found mandatory header, all missing headers are collected and returned. -pub(crate) async fn read_missing_headers, TC: TargetClient

>( +pub(crate) async fn read_missing_headers< + P: FinalitySyncPipeline, + SC: SourceClient

, + TC: TargetClient

, +>( source_client: &SC, _target_client: &TC, best_number_at_source: P::Number, @@ -470,17 +468,17 @@ pub(crate) async fn read_missing_headers { log::trace!(target: "bridge", "Header {:?} is mandatory", header_number); - return Ok(SelectedFinalityProof::Mandatory(header, finality_proof)); - } + return Ok(SelectedFinalityProof::Mandatory(header, finality_proof)) + }, (true, None) => return Err(Error::MissingMandatoryFinalityProof(header.number())), (false, Some(finality_proof)) => { log::trace!(target: "bridge", "Header {:?} has persistent finality proof", header_number); unjustified_headers.clear(); selected_finality_proof = Some((header, finality_proof)); - } + }, (false, None) => { unjustified_headers.push(header); - } + }, } header_number = header_number + One::one(); @@ -493,7 +491,10 @@ pub(crate) async fn read_missing_headers>( +pub(crate) fn read_finality_proofs_from_stream< + P: FinalitySyncPipeline, + FPS: Stream, +>( finality_proofs_stream: &mut RestartableFinalityProofsStream, recent_finality_proofs: &mut FinalityProofs

, ) { @@ -506,8 +507,8 @@ pub(crate) fn read_finality_proofs_from_stream finality_proof, Some(None) => { finality_proofs_stream.needs_restart = true; - break; - } + break + }, None => break, }; @@ -547,7 +548,7 @@ pub(crate) fn select_better_recent_finality_proof( P::SOURCE_NAME, selected_finality_proof.as_ref().map(|(h, _)| h.number()), ); - return selected_finality_proof; + return selected_finality_proof } const NOT_EMPTY_PROOF: &str = "we have checked that the vec is not empty; qed"; @@ -569,7 +570,8 @@ pub(crate) fn select_better_recent_finality_proof( let selected_finality_proof_index = recent_finality_proofs .binary_search_by_key(intersection.end(), |(number, _)| *number) .unwrap_or_else(|index| index.saturating_sub(1)); - let (selected_header_number, finality_proof) = &recent_finality_proofs[selected_finality_proof_index]; + let (selected_header_number, finality_proof) = + &recent_finality_proofs[selected_finality_proof_index]; let has_selected_finality_proof = intersection.contains(selected_header_number); log::trace!( target: "bridge", @@ -585,7 +587,7 @@ pub(crate) fn select_better_recent_finality_proof( if has_selected_finality_proof { "improved" } else { "failed" }, ); if !has_selected_finality_proof { - return selected_finality_proof; + return selected_finality_proof } // now remove all obsolete headers and extract selected header @@ -601,20 +603,15 @@ pub(crate) fn prune_recent_finality_proofs( recent_finality_proofs: &mut FinalityProofs

, recent_finality_proofs_limit: usize, ) { - let position = - recent_finality_proofs.binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number); + let position = recent_finality_proofs + .binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number); // remove all obsolete elements - *recent_finality_proofs = recent_finality_proofs.split_off( - position - .map(|position| position + 1) - .unwrap_or_else(|position| position), - ); + *recent_finality_proofs = recent_finality_proofs + .split_off(position.map(|position| position + 1).unwrap_or_else(|position| position)); // now - limit vec by size - let split_index = recent_finality_proofs - .len() - .saturating_sub(recent_finality_proofs_limit); + let split_index = recent_finality_proofs.len().saturating_sub(recent_finality_proofs_limit); *recent_finality_proofs = recent_finality_proofs.split_off(split_index); } @@ -626,15 +623,15 @@ fn print_sync_progress( let (prev_time, prev_best_number_at_target) = progress_context; let now = Instant::now(); - let need_update = now - prev_time > Duration::from_secs(10) - || prev_best_number_at_target + let need_update = now - prev_time > Duration::from_secs(10) || + prev_best_number_at_target .map(|prev_best_number_at_target| { best_number_at_target.saturating_sub(prev_best_number_at_target) > 10.into() }) .unwrap_or(true); if !need_update { - return (prev_time, prev_best_number_at_target); + return (prev_time, prev_best_number_at_target) } log::info!( diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index e7e0cdb39fb35..915b7ee6766ef 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -18,17 +18,21 @@ #![cfg(test)] -use crate::finality_loop::{ - prune_recent_finality_proofs, read_finality_proofs_from_stream, run, select_better_recent_finality_proof, - select_header_to_submit, FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, - TargetClient, +use crate::{ + finality_loop::{ + prune_recent_finality_proofs, read_finality_proofs_from_stream, run, + select_better_recent_finality_proof, select_header_to_submit, FinalityProofs, + FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, TargetClient, + }, + FinalityProof, FinalitySyncPipeline, SourceHeader, }; -use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; use async_trait::async_trait; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; -use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, MaybeConnectionError}; +use relay_utils::{ + metrics::MetricsParams, relay_loop::Client as RelayClient, MaybeConnectionError, +}; use std::{collections::HashMap, pin::Pin, sync::Arc, time::Duration}; type IsMandatory = bool; @@ -121,10 +125,7 @@ impl SourceClient for TestSourceClient { ) -> Result<(TestSourceHeader, Option), TestError> { let mut data = self.data.lock(); (self.on_method_call)(&mut *data); - data.source_headers - .get(&number) - .cloned() - .ok_or(TestError::NonConnection) + data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) } async fn finality_proofs(&self) -> Result { @@ -157,7 +158,11 @@ impl TargetClient for TestTargetClient { Ok(data.target_best_block_number) } - async fn submit_finality_proof(&self, header: TestSourceHeader, proof: TestFinalityProof) -> Result<(), TestError> { + async fn submit_finality_proof( + &self, + header: TestSourceHeader, + proof: TestFinalityProof, + ) -> Result<(), TestError> { let mut data = self.data.lock(); (self.on_method_call)(&mut *data); data.target_best_block_number = header.number(); @@ -171,11 +176,12 @@ fn prepare_test_clients( state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, source_headers: HashMap)>, ) -> (TestSourceClient, TestTargetClient) { - let internal_state_function: Arc = Arc::new(move |data| { - if state_function(data) { - exit_sender.unbounded_send(()).unwrap(); - } - }); + let internal_state_function: Arc = + Arc::new(move |data| { + if state_function(data) { + exit_sender.unbounded_send(()).unwrap(); + } + }); let clients_data = Arc::new(Mutex::new(ClientsData { source_best_block_number: 10, source_headers, @@ -189,14 +195,13 @@ fn prepare_test_clients( on_method_call: internal_state_function.clone(), data: clients_data.clone(), }, - TestTargetClient { - on_method_call: internal_state_function, - data: clients_data, - }, + TestTargetClient { on_method_call: internal_state_function, data: clients_data }, ) } -fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static) -> ClientsData { +fn run_sync_loop( + state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, +) -> ClientsData { let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); let (source_client, target_client) = prepare_test_clients( exit_sender, @@ -234,12 +239,13 @@ fn run_sync_loop(state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync #[test] fn finality_sync_loop_works() { let client_data = run_sync_loop(|data| { - // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, because - // header#8 has persistent finality proof && it is mandatory => it is submitted - // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, because - // there are no more persistent finality proofs + // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, + // because header#8 has persistent finality proof && it is mandatory => it is submitted + // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, + // because there are no more persistent finality proofs // - // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from the stream + // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from + // the stream if data.target_best_block_number == 9 { data.source_best_block_number = 14; data.source_headers.insert(11, (TestSourceHeader(false, 11), None)); @@ -287,10 +293,7 @@ fn run_only_mandatory_headers_mode_test( vec![ (6, (TestSourceHeader(false, 6), Some(TestFinalityProof(6)))), (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), - ( - 8, - (TestSourceHeader(has_mandatory_headers, 8), Some(TestFinalityProof(8))), - ), + (8, (TestSourceHeader(has_mandatory_headers, 8), Some(TestFinalityProof(8)))), (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), (10, (TestSourceHeader(false, 10), Some(TestFinalityProof(10)))), ] @@ -357,7 +360,8 @@ fn select_better_recent_finality_proof_works() { Some((TestSourceHeader(false, 2), TestFinalityProof(2))), ); - // if there's no intersection between recent finality proofs and unjustified headers, nothing is changed + // if there's no intersection between recent finality proofs and unjustified headers, nothing is + // changed let mut unjustified_headers = vec![TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; assert_eq!( select_better_recent_finality_proof::( @@ -368,13 +372,10 @@ fn select_better_recent_finality_proof_works() { Some((TestSourceHeader(false, 2), TestFinalityProof(2))), ); - // if there's intersection between recent finality proofs and unjustified headers, but there are no - // proofs in this intersection, nothing is changed - let mut unjustified_headers = vec![ - TestSourceHeader(false, 8), - TestSourceHeader(false, 9), - TestSourceHeader(false, 10), - ]; + // if there's intersection between recent finality proofs and unjustified headers, but there are + // no proofs in this intersection, nothing is changed + let mut unjustified_headers = + vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; assert_eq!( select_better_recent_finality_proof::( &[(7, TestFinalityProof(7)), (11, TestFinalityProof(11))], @@ -385,22 +386,15 @@ fn select_better_recent_finality_proof_works() { ); assert_eq!( unjustified_headers, - vec![ - TestSourceHeader(false, 8), - TestSourceHeader(false, 9), - TestSourceHeader(false, 10) - ] + vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)] ); // if there's intersection between recent finality proofs and unjustified headers and there's // a proof in this intersection: // - this better (last from intersection) proof is selected; // - 'obsolete' unjustified headers are pruned. - let mut unjustified_headers = vec![ - TestSourceHeader(false, 8), - TestSourceHeader(false, 9), - TestSourceHeader(false, 10), - ]; + let mut unjustified_headers = + vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; assert_eq!( select_better_recent_finality_proof::( &[(7, TestFinalityProof(7)), (9, TestFinalityProof(9))], @@ -416,7 +410,10 @@ fn read_finality_proofs_from_stream_works() { // when stream is currently empty, nothing is changed let mut recent_finality_proofs = vec![(1, TestFinalityProof(1))]; let mut stream = futures::stream::pending().into(); - read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); + read_finality_proofs_from_stream::( + &mut stream, + &mut recent_finality_proofs, + ); assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1))]); assert!(!stream.needs_restart); @@ -424,20 +421,20 @@ fn read_finality_proofs_from_stream_works() { let mut stream = futures::stream::iter(vec![TestFinalityProof(4)]) .chain(futures::stream::pending()) .into(); - read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); - assert_eq!( - recent_finality_proofs, - vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] + read_finality_proofs_from_stream::( + &mut stream, + &mut recent_finality_proofs, ); + assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))]); assert!(!stream.needs_restart); // when stream has ended, we'll need to restart it let mut stream = futures::stream::empty().into(); - read_finality_proofs_from_stream::(&mut stream, &mut recent_finality_proofs); - assert_eq!( - recent_finality_proofs, - vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] + read_finality_proofs_from_stream::( + &mut stream, + &mut recent_finality_proofs, ); + assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))]); assert!(stream.needs_restart); } diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index 64ec5bed05005..78ef33f1b376b 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -19,7 +19,9 @@ //! are still submitted to the target node, but are treated as auxiliary data as we are not trying //! to submit all source headers to the target node. -pub use crate::finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}; +pub use crate::finality_loop::{ + metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient, +}; use bp_header_chain::FinalityProof; use std::fmt::Debug; diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs index d4f3d77d79cea..8d67c1cf48574 100644 --- a/relays/headers/src/headers.rs +++ b/relays/headers/src/headers.rs @@ -20,22 +20,33 @@ //! may stay until source/target chain state isn't updated. When a header reaches the //! `ready` sub-queue, it may be submitted to the target chain. -use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader}; +use crate::sync_types::{ + HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader, +}; use linked_hash_map::LinkedHashMap; use num_traits::{One, Zero}; use relay_utils::HeaderId; use std::{ - collections::{btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, HashSet}, + collections::{ + btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, + HashSet, + }, time::{Duration, Instant}, }; -type HeadersQueue

= - BTreeMap<

::Number, HashMap<

::Hash, QueuedHeader

>>; -type SyncedChildren

= - BTreeMap<

::Number, HashMap<

::Hash, HashSet>>>; -type KnownHeaders

= - BTreeMap<

::Number, HashMap<

::Hash, HeaderStatus>>; +type HeadersQueue

= BTreeMap< +

::Number, + HashMap<

::Hash, QueuedHeader

>, +>; +type SyncedChildren

= BTreeMap< +

::Number, + HashMap<

::Hash, HashSet>>, +>; +type KnownHeaders

= BTreeMap< +

::Number, + HashMap<

::Hash, HeaderStatus>, +>; /// We're trying to fetch completion data for single header at this interval. const RETRY_FETCH_COMPLETION_INTERVAL: Duration = Duration::from_secs(20); @@ -113,35 +124,31 @@ impl QueuedHeaders

{ pub fn headers_in_status(&self, status: HeaderStatus) -> usize { match status { HeaderStatus::Unknown | HeaderStatus::Synced => 0, - HeaderStatus::MaybeOrphan => self - .maybe_orphan - .values() - .fold(0, |total, headers| total + headers.len()), - HeaderStatus::Orphan => self.orphan.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::MaybeExtra => self - .maybe_extra - .values() - .fold(0, |total, headers| total + headers.len()), - HeaderStatus::Extra => self.extra.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Ready => self.ready.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Incomplete => self.incomplete.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Submitted => self.submitted.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeOrphan => + self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Orphan => + self.orphan.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::MaybeExtra => + self.maybe_extra.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Extra => + self.extra.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Ready => + self.ready.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Incomplete => + self.incomplete.values().fold(0, |total, headers| total + headers.len()), + HeaderStatus::Submitted => + self.submitted.values().fold(0, |total, headers| total + headers.len()), } } /// Returns number of headers that are currently in the queue. pub fn total_headers(&self) -> usize { - self.maybe_orphan - .values() - .fold(0, |total, headers| total + headers.len()) - + self.orphan.values().fold(0, |total, headers| total + headers.len()) - + self - .maybe_extra - .values() - .fold(0, |total, headers| total + headers.len()) - + self.extra.values().fold(0, |total, headers| total + headers.len()) - + self.ready.values().fold(0, |total, headers| total + headers.len()) - + self.incomplete.values().fold(0, |total, headers| total + headers.len()) + self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()) + + self.orphan.values().fold(0, |total, headers| total + headers.len()) + + self.maybe_extra.values().fold(0, |total, headers| total + headers.len()) + + self.extra.values().fold(0, |total, headers| total + headers.len()) + + self.ready.values().fold(0, |total, headers| total + headers.len()) + + self.incomplete.values().fold(0, |total, headers| total + headers.len()) } /// Returns number of best block in the queue. @@ -157,8 +164,16 @@ impl QueuedHeaders

{ std::cmp::max( self.ready.keys().next_back().cloned().unwrap_or_else(Zero::zero), std::cmp::max( - self.incomplete.keys().next_back().cloned().unwrap_or_else(Zero::zero), - self.submitted.keys().next_back().cloned().unwrap_or_else(Zero::zero), + self.incomplete + .keys() + .next_back() + .cloned() + .unwrap_or_else(Zero::zero), + self.submitted + .keys() + .next_back() + .cloned() + .unwrap_or_else(Zero::zero), ), ), ), @@ -226,7 +241,7 @@ impl QueuedHeaders

{ id, status, ); - return; + return } if id.0 < self.prune_border { @@ -236,7 +251,7 @@ impl QueuedHeaders

{ P::SOURCE_NAME, id, ); - return; + return } let parent_id = header.parent_id(); @@ -247,20 +262,20 @@ impl QueuedHeaders

{ HeaderStatus::Unknown | HeaderStatus::MaybeOrphan => { insert_header(&mut self.maybe_orphan, id, header); HeaderStatus::MaybeOrphan - } + }, HeaderStatus::Orphan => { insert_header(&mut self.orphan, id, header); HeaderStatus::Orphan - } - HeaderStatus::MaybeExtra - | HeaderStatus::Extra - | HeaderStatus::Ready - | HeaderStatus::Incomplete - | HeaderStatus::Submitted - | HeaderStatus::Synced => { + }, + HeaderStatus::MaybeExtra | + HeaderStatus::Extra | + HeaderStatus::Ready | + HeaderStatus::Incomplete | + HeaderStatus::Submitted | + HeaderStatus::Synced => { insert_header(&mut self.maybe_extra, id, header); HeaderStatus::MaybeExtra - } + }, }; self.known_headers.entry(id.0).or_default().insert(id.1, status); @@ -288,7 +303,7 @@ impl QueuedHeaders

{ HeaderStatus::Orphan, id, ); - return; + return } move_header_descendants::

( @@ -351,8 +366,8 @@ impl QueuedHeaders

{ id, ); - return; - } + return + }, }; // do not remove from `incomplete_headers` here, because otherwise we'll miss @@ -414,14 +429,20 @@ impl QueuedHeaders

{ } /// Marks given headers incomplete. - pub fn add_incomplete_headers(&mut self, make_header_incomplete: bool, new_incomplete_headers: Vec>) { + pub fn add_incomplete_headers( + &mut self, + make_header_incomplete: bool, + new_incomplete_headers: Vec>, + ) { for new_incomplete_header in new_incomplete_headers { if make_header_incomplete { self.header_synced(&new_incomplete_header); } - let move_origins = select_synced_children::

(&self.synced_children, &new_incomplete_header); - let move_origins = move_origins.into_iter().chain(std::iter::once(new_incomplete_header)); + let move_origins = + select_synced_children::

(&self.synced_children, &new_incomplete_header); + let move_origins = + move_origins.into_iter().chain(std::iter::once(new_incomplete_header)); for move_origin in move_origins { move_header_descendants::

( &mut [&mut self.ready, &mut self.submitted], @@ -450,7 +471,9 @@ impl QueuedHeaders

{ // are moved from Ready/Submitted to Incomplete queue let new_incomplete_headers = ids .iter() - .filter(|id| !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id)) + .filter(|id| { + !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id) + }) .cloned() .collect::>(); self.add_incomplete_headers(true, new_incomplete_headers); @@ -468,8 +491,10 @@ impl QueuedHeaders

{ // sub2eth rejects H if H.Parent is incomplete // sub2sub allows 'syncing' headers like that // => let's check if there are some synced children of just completed header - let move_origins = select_synced_children::

(&self.synced_children, &just_completed_header); - let move_origins = move_origins.into_iter().chain(std::iter::once(just_completed_header)); + let move_origins = + select_synced_children::

(&self.synced_children, &just_completed_header); + let move_origins = + move_origins.into_iter().chain(std::iter::once(just_completed_header)); for move_origin in move_origins { move_header_descendants::

( &mut [&mut self.incomplete], @@ -500,7 +525,8 @@ impl QueuedHeaders

{ pub fn incomplete_header(&mut self) -> Option> { queued_incomplete_header(&mut self.incomplete_headers, |last_fetch_time| { let retry = match *last_fetch_time { - Some(last_fetch_time) => last_fetch_time.elapsed() > RETRY_FETCH_COMPLETION_INTERVAL, + Some(last_fetch_time) => + last_fetch_time.elapsed() > RETRY_FETCH_COMPLETION_INTERVAL, None => true, }; @@ -521,7 +547,7 @@ impl QueuedHeaders

{ /// Prune and never accept headers before this block. pub fn prune(&mut self, prune_border: P::Number) { if prune_border <= self.prune_border { - return; + return } prune_queue(&mut self.maybe_orphan, prune_border); @@ -570,10 +596,10 @@ impl QueuedHeaders

{ match header { Some(header) => { let parent_id = header.header().parent_id(); - self.incomplete_headers.contains_key(&parent_id) - || self.completion_data.contains_key(&parent_id) - || self.status(&parent_id) == HeaderStatus::Incomplete - } + self.incomplete_headers.contains_key(&parent_id) || + self.completion_data.contains_key(&parent_id) || + self.status(&parent_id) == HeaderStatus::Incomplete + }, None => false, } } @@ -603,12 +629,8 @@ impl QueuedHeaders

{ .expect("header has a given status; given queue has the header; qed"); // remember ids of all the children of the current header - let synced_children_entry = self - .synced_children - .entry(current.0) - .or_default() - .entry(current.1) - .or_default(); + let synced_children_entry = + self.synced_children.entry(current.0).or_default().entry(current.1).or_default(); let all_queues = [ &self.maybe_orphan, &self.orphan, @@ -624,7 +646,9 @@ impl QueuedHeaders

{ .map(|potential_children| { potential_children .values() - .filter(|potential_child| potential_child.header().parent_id() == current) + .filter(|potential_child| { + potential_child.header().parent_id() == current + }) .map(|child| child.id()) .collect::>() }) @@ -661,12 +685,19 @@ impl QueuedHeaders

{ } /// Insert header to the queue. -fn insert_header(queue: &mut HeadersQueue

, id: HeaderIdOf

, header: QueuedHeader

) { +fn insert_header( + queue: &mut HeadersQueue

, + id: HeaderIdOf

, + header: QueuedHeader

, +) { queue.entry(id.0).or_default().insert(id.1, header); } /// Remove header from the queue. -fn remove_header(queue: &mut HeadersQueue

, id: &HeaderIdOf

) -> Option> { +fn remove_header( + queue: &mut HeadersQueue

, + id: &HeaderIdOf

, +) -> Option> { let mut headers_at = match queue.entry(id.0) { BTreeMapEntry::Occupied(headers_at) => headers_at, BTreeMapEntry::Vacant(_) => return None, @@ -680,7 +711,10 @@ fn remove_header(queue: &mut HeadersQueue

, id: &Heade } /// Get header from the queue. -fn header<'a, P: HeadersSyncPipeline>(queue: &'a HeadersQueue

, id: &HeaderIdOf

) -> Option<&'a QueuedHeader

> { +fn header<'a, P: HeadersSyncPipeline>( + queue: &'a HeadersQueue

, + id: &HeaderIdOf

, +) -> Option<&'a QueuedHeader

> { queue.get(&id.0).and_then(|by_hash| by_hash.get(&id.1)) } @@ -799,11 +833,7 @@ fn oldest_headers( queue: &HeadersQueue

, mut f: impl FnMut(&QueuedHeader

) -> bool, ) -> Option>> { - let result = queue - .values() - .flat_map(|h| h.values()) - .take_while(|h| f(h)) - .collect::>(); + let result = queue.values().flat_map(|h| h.values()).take_while(|h| f(h)).collect::>(); if result.is_empty() { None } else { @@ -817,7 +847,10 @@ fn prune_queue(queue: &mut HeadersQueue

, prune_border } /// Forget all known headers with number less than given. -fn prune_known_headers(known_headers: &mut KnownHeaders

, prune_border: P::Number) { +fn prune_known_headers( + known_headers: &mut KnownHeaders

, + prune_border: P::Number, +) { let new_known_headers = known_headers.split_off(&prune_border); for (pruned_number, pruned_headers) in &*known_headers { for pruned_hash in pruned_headers.keys() { @@ -848,8 +881,8 @@ fn queued_incomplete_header( map: &mut LinkedHashMap, filter: impl FnMut(&mut T) -> bool, ) -> Option<(Id, &T)> { - // TODO (#84): headers that have been just appended to the end of the queue would have to wait until - // all previous headers will be retried + // TODO (#84): headers that have been just appended to the end of the queue would have to wait + // until all previous headers will be retried let retry_old_header = map .front() @@ -857,9 +890,10 @@ fn queued_incomplete_header( .and_then(|key| map.get_mut(&key).map(filter)) .unwrap_or(false); if retry_old_header { - let (header_key, header) = map.pop_front().expect("we have checked that front() exists; qed"); + let (header_key, header) = + map.pop_front().expect("we have checked that front() exists; qed"); map.insert(header_key, header); - return map.back().map(|(id, data)| (id.clone(), data)); + return map.back().map(|(id, data)| (id.clone(), data)) } None @@ -868,15 +902,15 @@ fn queued_incomplete_header( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::sync_loop_tests::{TestHash, TestHeader, TestHeaderId, TestHeadersSyncPipeline, TestNumber}; - use crate::sync_types::QueuedHeader; + use crate::{ + sync_loop_tests::{ + TestHash, TestHeader, TestHeaderId, TestHeadersSyncPipeline, TestNumber, + }, + sync_types::QueuedHeader, + }; pub(crate) fn header(number: TestNumber) -> QueuedHeader { - QueuedHeader::new(TestHeader { - number, - hash: hash(number), - parent_hash: hash(number - 1), - }) + QueuedHeader::new(TestHeader { number, hash: hash(number), parent_hash: hash(number - 1) }) } pub(crate) fn hash(number: TestNumber) -> TestHash { @@ -891,34 +925,41 @@ pub(crate) mod tests { fn total_headers_works() { // total headers just sums up number of headers in every queue let mut queue = QueuedHeaders::::default(); - queue.maybe_orphan.entry(1).or_default().insert( - hash(1), - QueuedHeader::::new(Default::default()), - ); - queue.maybe_orphan.entry(1).or_default().insert( - hash(2), - QueuedHeader::::new(Default::default()), - ); - queue.maybe_orphan.entry(2).or_default().insert( - hash(3), - QueuedHeader::::new(Default::default()), - ); - queue.orphan.entry(3).or_default().insert( - hash(4), - QueuedHeader::::new(Default::default()), - ); - queue.maybe_extra.entry(4).or_default().insert( - hash(5), - QueuedHeader::::new(Default::default()), - ); - queue.ready.entry(5).or_default().insert( - hash(6), - QueuedHeader::::new(Default::default()), - ); - queue.incomplete.entry(6).or_default().insert( - hash(7), - QueuedHeader::::new(Default::default()), - ); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(1), QueuedHeader::::new(Default::default())); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(2), QueuedHeader::::new(Default::default())); + queue + .maybe_orphan + .entry(2) + .or_default() + .insert(hash(3), QueuedHeader::::new(Default::default())); + queue + .orphan + .entry(3) + .or_default() + .insert(hash(4), QueuedHeader::::new(Default::default())); + queue + .maybe_extra + .entry(4) + .or_default() + .insert(hash(5), QueuedHeader::::new(Default::default())); + queue + .ready + .entry(5) + .or_default() + .insert(hash(6), QueuedHeader::::new(Default::default())); + queue + .incomplete + .entry(6) + .or_default() + .insert(hash(7), QueuedHeader::::new(Default::default())); assert_eq!(queue.total_headers(), 7); } @@ -926,48 +967,56 @@ pub(crate) mod tests { fn best_queued_number_works() { // initially there are headers in MaybeOrphan queue only let mut queue = QueuedHeaders::::default(); - queue.maybe_orphan.entry(1).or_default().insert( - hash(1), - QueuedHeader::::new(Default::default()), - ); - queue.maybe_orphan.entry(1).or_default().insert( - hash(2), - QueuedHeader::::new(Default::default()), - ); - queue.maybe_orphan.entry(3).or_default().insert( - hash(3), - QueuedHeader::::new(Default::default()), - ); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(1), QueuedHeader::::new(Default::default())); + queue + .maybe_orphan + .entry(1) + .or_default() + .insert(hash(2), QueuedHeader::::new(Default::default())); + queue + .maybe_orphan + .entry(3) + .or_default() + .insert(hash(3), QueuedHeader::::new(Default::default())); assert_eq!(queue.best_queued_number(), 3); // and then there's better header in Orphan - queue.orphan.entry(10).or_default().insert( - hash(10), - QueuedHeader::::new(Default::default()), - ); + queue + .orphan + .entry(10) + .or_default() + .insert(hash(10), QueuedHeader::::new(Default::default())); assert_eq!(queue.best_queued_number(), 10); // and then there's better header in MaybeExtra - queue.maybe_extra.entry(20).or_default().insert( - hash(20), - QueuedHeader::::new(Default::default()), - ); + queue + .maybe_extra + .entry(20) + .or_default() + .insert(hash(20), QueuedHeader::::new(Default::default())); assert_eq!(queue.best_queued_number(), 20); // and then there's better header in Ready - queue.ready.entry(30).or_default().insert( - hash(30), - QueuedHeader::::new(Default::default()), - ); + queue + .ready + .entry(30) + .or_default() + .insert(hash(30), QueuedHeader::::new(Default::default())); assert_eq!(queue.best_queued_number(), 30); // and then there's better header in MaybeOrphan again - queue.maybe_orphan.entry(40).or_default().insert( - hash(40), - QueuedHeader::::new(Default::default()), - ); + queue + .maybe_orphan + .entry(40) + .or_default() + .insert(hash(40), QueuedHeader::::new(Default::default())); assert_eq!(queue.best_queued_number(), 40); // and then there's some header in Incomplete - queue.incomplete.entry(50).or_default().insert( - hash(50), - QueuedHeader::::new(Default::default()), - ); + queue + .incomplete + .entry(50) + .or_default() + .insert(hash(50), QueuedHeader::::new(Default::default())); assert_eq!(queue.best_queued_number(), 50); } @@ -977,11 +1026,7 @@ pub(crate) mod tests { let mut queue = QueuedHeaders::::default(); assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); // and status is read from the KnownHeaders - queue - .known_headers - .entry(10) - .or_default() - .insert(hash(10), HeaderStatus::Ready); + queue.known_headers.entry(10).or_default().insert(hash(10), HeaderStatus::Ready); assert_eq!(queue.status(&id(10)), HeaderStatus::Ready); } @@ -990,22 +1035,13 @@ pub(crate) mod tests { // initially we have oldest header #10 let mut queue = QueuedHeaders::::default(); queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); - assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, - hash(100) - ); + assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(100)); // inserting #20 changes nothing queue.maybe_orphan.entry(20).or_default().insert(hash(1), header(101)); - assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, - hash(100) - ); + assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(100)); // inserting #5 makes it oldest queue.maybe_orphan.entry(5).or_default().insert(hash(1), header(102)); - assert_eq!( - queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, - hash(102) - ); + assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(102)); } #[test] @@ -1091,11 +1127,7 @@ pub(crate) mod tests { .entry(100) .or_default() .insert(hash(100), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(100) - .or_default() - .insert(hash(100), header(100)); + queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); queue .known_headers .entry(99) @@ -1108,17 +1140,9 @@ pub(crate) mod tests { .or_default() .insert(hash(98), HeaderStatus::MaybeExtra); queue.maybe_extra.entry(98).or_default().insert(hash(98), header(98)); - queue - .known_headers - .entry(97) - .or_default() - .insert(hash(97), HeaderStatus::Extra); + queue.known_headers.entry(97).or_default().insert(hash(97), HeaderStatus::Extra); queue.extra.entry(97).or_default().insert(hash(97), header(97)); - queue - .known_headers - .entry(96) - .or_default() - .insert(hash(96), HeaderStatus::Ready); + queue.known_headers.entry(96).or_default().insert(hash(96), HeaderStatus::Ready); queue.ready.entry(96).or_default().insert(hash(96), header(96)); queue.target_best_header_response(&id(100)); @@ -1137,31 +1161,19 @@ pub(crate) mod tests { // children of synced headers are stored assert_eq!( vec![id(97)], - queue.synced_children[&96][&hash(96)] - .iter() - .cloned() - .collect::>() + queue.synced_children[&96][&hash(96)].iter().cloned().collect::>() ); assert_eq!( vec![id(98)], - queue.synced_children[&97][&hash(97)] - .iter() - .cloned() - .collect::>() + queue.synced_children[&97][&hash(97)].iter().cloned().collect::>() ); assert_eq!( vec![id(99)], - queue.synced_children[&98][&hash(98)] - .iter() - .cloned() - .collect::>() + queue.synced_children[&98][&hash(98)].iter().cloned().collect::>() ); assert_eq!( vec![id(100)], - queue.synced_children[&99][&hash(99)] - .iter() - .cloned() - .collect::>() + queue.synced_children[&99][&hash(99)].iter().cloned().collect::>() ); assert_eq!(0, queue.synced_children[&100][&hash(100)].len()); } @@ -1185,11 +1197,7 @@ pub(crate) mod tests { .entry(102) .or_default() .insert(hash(102), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(102) - .or_default() - .insert(hash(102), header(102)); + queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); queue .known_headers .entry(103) @@ -1221,11 +1229,7 @@ pub(crate) mod tests { .entry(100) .or_default() .insert(hash(100), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(100) - .or_default() - .insert(hash(100), header(100)); + queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); queue .known_headers .entry(101) @@ -1237,11 +1241,7 @@ pub(crate) mod tests { .entry(102) .or_default() .insert(hash(102), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(102) - .or_default() - .insert(hash(102), header(102)); + queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); queue.maybe_orphan_response(&id(99), true); // then all headers (#100..#103) are moved to the MaybeExtra queue @@ -1266,21 +1266,13 @@ pub(crate) mod tests { .entry(100) .or_default() .insert(hash(100), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(100) - .or_default() - .insert(hash(100), header(100)); + queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); queue .known_headers .entry(101) .or_default() .insert(hash(101), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(101) - .or_default() - .insert(hash(101), header(101)); + queue.maybe_orphan.entry(101).or_default().insert(hash(101), header(101)); queue.maybe_orphan_response(&id(99), false); // then all headers (#100..#101) are moved to the Orphan queue @@ -1395,7 +1387,9 @@ pub(crate) mod tests { queue.incomplete_headers.clear(); queue.incomplete_headers.insert( id(100), - Some(Instant::now() - RETRY_FETCH_COMPLETION_INTERVAL - RETRY_FETCH_COMPLETION_INTERVAL), + Some( + Instant::now() - RETRY_FETCH_COMPLETION_INTERVAL - RETRY_FETCH_COMPLETION_INTERVAL, + ), ); assert_eq!(queue.incomplete_header(), Some(id(100))); } @@ -1551,11 +1545,7 @@ pub(crate) mod tests { .entry(104) .or_default() .insert(hash(104), HeaderStatus::MaybeOrphan); - queue - .maybe_orphan - .entry(104) - .or_default() - .insert(hash(104), header(104)); + queue.maybe_orphan.entry(104).or_default().insert(hash(104), header(104)); queue .known_headers .entry(103) @@ -1624,7 +1614,8 @@ pub(crate) mod tests { fn incomplete_headers_are_still_incomplete_after_advance() { let mut queue = QueuedHeaders::::default(); - // relay#1 knows that header#100 is incomplete && it has headers 101..104 in incomplete queue + // relay#1 knows that header#100 is incomplete && it has headers 101..104 in incomplete + // queue queue.incomplete_headers.insert(id(100), None); queue.incomplete.entry(101).or_default().insert(hash(101), header(101)); queue.incomplete.entry(102).or_default().insert(hash(102), header(102)); @@ -1656,8 +1647,8 @@ pub(crate) mod tests { .or_default() .insert(hash(104), HeaderStatus::Incomplete); - // let's say relay#2 completes header#100 and then submits header#101+header#102 and it turns - // out that header#102 is also incomplete + // let's say relay#2 completes header#100 and then submits header#101+header#102 and it + // turns out that header#102 is also incomplete queue.incomplete_headers_response(vec![id(102)].into_iter().collect()); // then the header#103 and the header#104 must have Incomplete status diff --git a/relays/headers/src/sync.rs b/relays/headers/src/sync.rs index 7e3d9020290f4..012b63f0dc59c 100644 --- a/relays/headers/src/sync.rs +++ b/relays/headers/src/sync.rs @@ -19,8 +19,10 @@ //! to submit to the target chain? The context makes decisions basing on parameters //! passed using `HeadersSyncParams` structure. -use crate::headers::QueuedHeaders; -use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader}; +use crate::{ + headers::QueuedHeaders, + sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader}, +}; use num_traits::{One, Saturating, Zero}; /// Common sync params. @@ -121,20 +123,21 @@ impl HeadersSync

{ // if we haven't received best header from source node yet, there's nothing we can download let source_best_number = self.source_best_number?; - // if we haven't received known best header from target node yet, there's nothing we can download + // if we haven't received known best header from target node yet, there's nothing we can + // download let target_best_header = self.target_best_header.as_ref()?; // if there's too many headers in the queue, stop downloading let in_memory_headers = self.headers.total_headers(); if in_memory_headers >= self.params.max_future_headers_to_download { - return None; + return None } // if queue is empty and best header on target is > than best header on source, // then we shoud reorganization let best_queued_number = self.headers.best_queued_number(); if best_queued_number.is_zero() && source_best_number < target_best_header.0 { - return Some(source_best_number); + return Some(source_best_number) } // we assume that there were no reorganizations if we have already downloaded best header @@ -143,14 +146,14 @@ impl HeadersSync

{ target_best_header.0, ); if best_downloaded_number >= source_best_number { - return None; + return None } // download new header Some(best_downloaded_number + One::one()) } - /// Selech orphan header to download. + /// Select orphan header to download. pub fn select_orphan_header_to_download(&self) -> Option<&QueuedHeader

> { let orphan_header = self.headers.header(HeaderStatus::Orphan)?; @@ -159,7 +162,7 @@ impl HeadersSync

{ // => let's avoid fetching duplicate headers let parent_id = orphan_header.parent_id(); if self.headers.status(&parent_id) != HeaderStatus::Unknown { - return None; + return None } Some(orphan_header) @@ -169,12 +172,12 @@ impl HeadersSync

{ pub fn select_headers_to_submit(&self, stalled: bool) -> Option>> { // maybe we have paused new headers submit? if self.pause_submit { - return None; + return None } // if we operate in backup mode, we only submit headers when sync has stalled if self.params.target_tx_mode == TargetTransactionMode::Backup && !stalled { - return None; + return None } let headers_in_submit_status = self.headers.headers_in_status(HeaderStatus::Submitted); @@ -187,15 +190,17 @@ impl HeadersSync

{ let mut total_headers = 0; self.headers.headers(HeaderStatus::Ready, |header| { if total_headers == headers_to_submit_count { - return false; + return false } if total_headers == self.params.max_headers_in_single_submit { - return false; + return false } let encoded_size = P::estimate_size(header); - if total_headers != 0 && total_size + encoded_size > self.params.max_headers_size_in_single_submit { - return false; + if total_headers != 0 && + total_size + encoded_size > self.params.max_headers_size_in_single_submit + { + return false } total_size += encoded_size; @@ -228,15 +233,14 @@ impl HeadersSync

{ // early return if it is still the same if self.target_best_header == Some(best_header) { - return false; + return false } // remember that this header is now known to the Substrate runtime self.headers.target_best_header_response(&best_header); // prune ancient headers - self.headers - .prune(best_header.0.saturating_sub(self.params.prune_depth.into())); + self.headers.prune(best_header.0.saturating_sub(self.params.prune_depth.into())); // finally remember the best header itself self.target_best_header = Some(best_header); @@ -281,9 +285,11 @@ impl HeadersSync

{ #[cfg(test)] pub mod tests { use super::*; - use crate::headers::tests::{header, id}; - use crate::sync_loop_tests::{TestHash, TestHeadersSyncPipeline, TestNumber}; - use crate::sync_types::HeaderStatus; + use crate::{ + headers::tests::{header, id}, + sync_loop_tests::{TestHash, TestHeadersSyncPipeline, TestNumber}, + sync_types::HeaderStatus, + }; use relay_utils::HeaderId; fn side_hash(number: TestNumber) -> TestHash { diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index a557eca6a2306..d54a445d7f0e5 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -16,9 +16,11 @@ //! Entrypoint for running headers synchronization loop. -use crate::sync::{HeadersSync, HeadersSyncParams}; -use crate::sync_loop_metrics::SyncLoopMetrics; -use crate::sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}; +use crate::{ + sync::{HeadersSync, HeadersSyncParams}, + sync_loop_metrics::SyncLoopMetrics, + sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, +}; use async_trait::async_trait; use futures::{future::FutureExt, stream::StreamExt}; @@ -66,8 +68,10 @@ pub trait SourceClient: RelayClient { async fn header_by_number(&self, number: P::Number) -> Result; /// Get completion data by header hash. - async fn header_completion(&self, id: HeaderIdOf

) - -> Result<(HeaderIdOf

, Option), Self::Error>; + async fn header_completion( + &self, + id: HeaderIdOf

, + ) -> Result<(HeaderIdOf

, Option), Self::Error>; /// Get extra data by header hash. async fn header_extra( @@ -84,20 +88,32 @@ pub trait TargetClient: RelayClient { async fn best_header_id(&self) -> Result, Self::Error>; /// Returns true if header is known to the target node. - async fn is_known_header(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, bool), Self::Error>; + async fn is_known_header( + &self, + id: HeaderIdOf

, + ) -> Result<(HeaderIdOf

, bool), Self::Error>; /// Submit headers. - async fn submit_headers(&self, headers: Vec>) -> SubmittedHeaders, Self::Error>; + async fn submit_headers( + &self, + headers: Vec>, + ) -> SubmittedHeaders, Self::Error>; /// Returns ID of headers that require to be 'completed' before children can be submitted. async fn incomplete_headers_ids(&self) -> Result>, Self::Error>; /// Submit completion data for header. - async fn complete_header(&self, id: HeaderIdOf

, completion: P::Completion) - -> Result, Self::Error>; + async fn complete_header( + &self, + id: HeaderIdOf

, + completion: P::Completion, + ) -> Result, Self::Error>; /// Returns true if header requires extra data to be submitted. - async fn requires_extra(&self, header: QueuedHeader

) -> Result<(HeaderIdOf

, bool), Self::Error>; + async fn requires_extra( + &self, + header: QueuedHeader

, + ) -> Result<(HeaderIdOf

, bool), Self::Error>; } /// Synchronization maintain procedure. @@ -110,7 +126,8 @@ pub trait SyncMaintain: 'static + Clone + Send + Sync { impl SyncMaintain

for () {} -/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop. +/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs +/// sync loop. pub fn metrics_prefix() -> String { format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) } @@ -480,7 +497,8 @@ async fn run_until_connection_lost>( id, ); - target_complete_header_future.set(target_client.complete_header(id, completion.clone()).fuse()); + target_complete_header_future + .set(target_client.complete_header(id, completion.clone()).fuse()); } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeExtra) { log::debug!( target: "bridge", @@ -501,8 +519,8 @@ async fn run_until_connection_lost>( ); target_existence_status_future.set(target_client.is_known_header(parent_id).fuse()); - } else if let Some(headers) = - sync.select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) + } else if let Some(headers) = sync + .select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) { log::debug!( target: "bridge", @@ -580,7 +598,7 @@ async fn run_until_connection_lost>( P::SOURCE_NAME, P::TARGET_NAME, ); - return Ok(()); + return Ok(()) } log::debug!( @@ -616,15 +634,14 @@ fn print_sync_progress( let now_time = Instant::now(); let (now_best_header, now_target_header) = eth_sync.status(); - let need_update = now_time - prev_time > Duration::from_secs(10) - || match (prev_best_header, now_best_header) { - (Some(prev_best_header), Some(now_best_header)) => { - now_best_header.0.saturating_sub(prev_best_header) > 10.into() - } + let need_update = now_time - prev_time > Duration::from_secs(10) || + match (prev_best_header, now_best_header) { + (Some(prev_best_header), Some(now_best_header)) => + now_best_header.0.saturating_sub(prev_best_header) > 10.into(), _ => false, }; if !need_update { - return (prev_time, prev_best_header, prev_target_header); + return (prev_time, prev_best_header, prev_target_header) } log::info!( diff --git a/relays/headers/src/sync_loop_metrics.rs b/relays/headers/src/sync_loop_metrics.rs index 37dae11340428..1c558c25de9d5 100644 --- a/relays/headers/src/sync_loop_metrics.rs +++ b/relays/headers/src/sync_loop_metrics.rs @@ -16,8 +16,10 @@ //! Metrics for headers synchronization relay loop. -use crate::sync::HeadersSync; -use crate::sync_types::{HeaderStatus, HeadersSyncPipeline}; +use crate::{ + sync::HeadersSync, + sync_types::{HeaderStatus, HeadersSyncPipeline}, +}; use num_traits::Zero; use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; @@ -78,7 +80,8 @@ impl SyncLoopMetrics { pub fn update(&self, sync: &HeadersSync

) { let headers = sync.headers(); let source_best_number = sync.source_best_number().unwrap_or_else(Zero::zero); - let target_best_number = sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); + let target_best_number = + sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); self.update_best_block_at_source(source_best_number); self.update_best_block_at_target(target_best_number); diff --git a/relays/headers/src/sync_loop_tests.rs b/relays/headers/src/sync_loop_tests.rs index 3347c4d0d3bd0..f100998ca83f9 100644 --- a/relays/headers/src/sync_loop_tests.rs +++ b/relays/headers/src/sync_loop_tests.rs @@ -16,16 +16,18 @@ #![cfg(test)] -use crate::sync_loop::{run, SourceClient, TargetClient}; -use crate::sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}; +use crate::{ + sync_loop::{run, SourceClient, TargetClient}, + sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, +}; use async_trait::async_trait; use backoff::backoff::Backoff; use futures::{future::FutureExt, stream::StreamExt}; use parking_lot::Mutex; use relay_utils::{ - metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, retry_backoff, HeaderId, - MaybeConnectionError, + metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, + retry_backoff, HeaderId, MaybeConnectionError, }; use std::{ collections::{HashMap, HashSet}, @@ -166,7 +168,10 @@ impl SourceClient for Source { data.header_by_number.get(&number).cloned().ok_or(TestError(false)) } - async fn header_completion(&self, id: TestHeaderId) -> Result<(TestHeaderId, Option), TestError> { + async fn header_completion( + &self, + id: TestHeaderId, + ) -> Result<(TestHeaderId, Option), TestError> { let mut data = self.data.lock(); (self.on_method_call)(SourceMethod::HeaderCompletion(id), &mut *data); if data.provides_completion { @@ -264,7 +269,10 @@ impl TargetClient for Target { .unwrap_or(Ok((id, false))) } - async fn submit_headers(&self, headers: Vec) -> SubmittedHeaders { + async fn submit_headers( + &self, + headers: Vec, + ) -> SubmittedHeaders { let mut data = self.data.lock(); (self.on_method_call)(TargetMethod::SubmitHeaders(headers.clone()), &mut *data); data.submitted_headers @@ -287,14 +295,21 @@ impl TargetClient for Target { } } - async fn complete_header(&self, id: TestHeaderId, completion: TestCompletion) -> Result { + async fn complete_header( + &self, + id: TestHeaderId, + completion: TestCompletion, + ) -> Result { let mut data = self.data.lock(); (self.on_method_call)(TargetMethod::CompleteHeader(id, completion), &mut *data); data.completed_headers.insert(id.1, completion); Ok(id) } - async fn requires_extra(&self, header: TestQueuedHeader) -> Result<(TestHeaderId, bool), TestError> { + async fn requires_extra( + &self, + header: TestQueuedHeader, + ) -> Result<(TestHeaderId, bool), TestError> { let mut data = self.data.lock(); (self.on_method_call)(TargetMethod::RequiresExtra(header.clone()), &mut *data); if data.requires_extra { @@ -321,11 +336,7 @@ fn test_header(number: TestNumber) -> TestHeader { TestHeader { hash: id.1, number: id.0, - parent_hash: if number == 0 { - TestHash::default() - } else { - test_id(number - 1).1 - }, + parent_hash: if number == 0 { TestHash::default() } else { test_id(number - 1).1 }, } } @@ -467,18 +478,15 @@ fn run_sync_loop_test(params: SyncLoopTestParams) { let target_requires_extra = params.target_requires_extra; let target_requires_completion = params.target_requires_completion; let stop_at = params.stop_at; - let source = Source::new( - params.best_source_header.id(), - params.headers_on_source, - move |method, _| { + let source = + Source::new(params.best_source_header.id(), params.headers_on_source, move |method, _| { if !target_requires_extra { source_reject_extra(&method); } if !target_requires_completion { source_reject_completion(&method); } - }, - ); + }); let target = Target::new( params.best_target_header.id(), params.headers_on_target.into_iter().map(|header| header.id()).collect(), diff --git a/relays/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs index 05ed25114ed08..8d93e8bf49fbe 100644 --- a/relays/headers/src/sync_types.rs +++ b/relays/headers/src/sync_types.rs @@ -50,7 +50,14 @@ pub trait HeadersSyncPipeline: 'static + Clone + Send + Sync { const TARGET_NAME: &'static str; /// Headers we're syncing are identified by this hash. - type Hash: Eq + Clone + Copy + Send + Sync + std::fmt::Debug + std::fmt::Display + std::hash::Hash; + type Hash: Eq + + Clone + + Copy + + Send + + Sync + + std::fmt::Debug + + std::fmt::Display + + std::hash::Hash; /// Headers we're syncing are identified by this number. type Number: relay_utils::BlockNumberBase; /// Type of header that we're syncing. @@ -77,7 +84,8 @@ pub trait HeadersSyncPipeline: 'static + Clone + Send + Sync { } /// A HeaderId for `HeaderSyncPipeline`. -pub type HeaderIdOf

= HeaderId<

::Hash,

::Number>; +pub type HeaderIdOf

= + HeaderId<

::Hash,

::Number>; /// Header that we're receiving from source node. pub trait SourceHeader: Clone + std::fmt::Debug + PartialEq + Send + Sync { @@ -153,8 +161,8 @@ impl QueuedHeader

{ pub struct SubmittedHeaders { /// IDs of headers that have been submitted to target node. pub submitted: Vec, - /// IDs of incomplete headers. These headers were submitted (so this id is also in `submitted` vec), - /// but all descendants are not. + /// IDs of incomplete headers. These headers were submitted (so this id is also in `submitted` + /// vec), but all descendants are not. pub incomplete: Vec, /// IDs of ignored headers that we have decided not to submit (they are either rejected by /// target node immediately, or their descendants of incomplete headers). @@ -180,10 +188,6 @@ impl std::fmt::Display for SubmittedHeaders Right conversion rate, used as `RightTokens = LeftTokens * Rate`. +/// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens * +/// Rate`. pub fn run_conversion_rate_update_loop< SubmitConversionRateFuture: Future> + Send + 'static, >( @@ -60,10 +61,10 @@ pub fn run_conversion_rate_update_loop< match submit_conversion_rate_future.await { Ok(()) => { transaction_status = TransactionStatus::Submitted(prev_conversion_rate); - } + }, Err(error) => { log::trace!(target: "bridge", "Failed to submit conversion rate update transaction: {:?}", error); - } + }, } } } @@ -78,41 +79,43 @@ async fn maybe_select_new_conversion_rate( right_to_base_conversion_rate: &F64SharedRef, max_difference_ratio: f64, ) -> Option<(f64, f64)> { - let left_to_right_stored_conversion_rate = (*left_to_right_stored_conversion_rate.read().await)?; + let left_to_right_stored_conversion_rate = + (*left_to_right_stored_conversion_rate.read().await)?; match *transaction_status { TransactionStatus::Idle => (), TransactionStatus::Submitted(previous_left_to_right_stored_conversion_rate) => { - // we can't compare float values from different sources directly, so we only care whether the - // stored rate has been changed or not. If it has been changed, then we assume that our proposal - // has been accepted. + // we can't compare float values from different sources directly, so we only care + // whether the stored rate has been changed or not. If it has been changed, then we + // assume that our proposal has been accepted. // - // float comparison is ok here, because we compare same-origin (stored in runtime storage) values - // and if they are different, it means that the value has actually been updated + // float comparison is ok here, because we compare same-origin (stored in runtime + // storage) values and if they are different, it means that the value has actually been + // updated #[allow(clippy::float_cmp)] - if previous_left_to_right_stored_conversion_rate == left_to_right_stored_conversion_rate { - // the rate has not been changed => we won't submit any transactions until it is accepted, - // or the rate is changed by someone else - return None; + if previous_left_to_right_stored_conversion_rate == left_to_right_stored_conversion_rate + { + // the rate has not been changed => we won't submit any transactions until it is + // accepted, or the rate is changed by someone else + return None } *transaction_status = TransactionStatus::Idle; - } + }, } let left_to_base_conversion_rate = (*left_to_base_conversion_rate.read().await)?; let right_to_base_conversion_rate = (*right_to_base_conversion_rate.read().await)?; - let actual_left_to_right_conversion_rate = right_to_base_conversion_rate / left_to_base_conversion_rate; + let actual_left_to_right_conversion_rate = + right_to_base_conversion_rate / left_to_base_conversion_rate; - let rate_difference = (actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs(); + let rate_difference = + (actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs(); let rate_difference_ratio = rate_difference / left_to_right_stored_conversion_rate; if rate_difference_ratio < max_difference_ratio { - return None; + return None } - Some(( - left_to_right_stored_conversion_rate, - actual_left_to_right_conversion_rate, - )) + Some((left_to_right_stored_conversion_rate, actual_left_to_right_conversion_rate)) } #[cfg(test)] @@ -171,7 +174,13 @@ mod tests { #[test] fn transaction_is_not_submitted_when_left_to_base_rate_is_unknown() { assert_eq!( - test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(10.0), None, Some(1.0), 0.0), + test_maybe_select_new_conversion_rate( + TransactionStatus::Idle, + Some(10.0), + None, + Some(1.0), + 0.0 + ), (None, TransactionStatus::Idle), ); } @@ -179,7 +188,13 @@ mod tests { #[test] fn transaction_is_not_submitted_when_right_to_base_rate_is_unknown() { assert_eq!( - test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(10.0), Some(1.0), None, 0.0), + test_maybe_select_new_conversion_rate( + TransactionStatus::Idle, + Some(10.0), + Some(1.0), + None, + 0.0 + ), (None, TransactionStatus::Idle), ); } @@ -187,7 +202,13 @@ mod tests { #[test] fn transaction_is_not_submitted_when_stored_rate_is_unknown() { assert_eq!( - test_maybe_select_new_conversion_rate(TransactionStatus::Idle, None, Some(1.0), Some(1.0), 0.0), + test_maybe_select_new_conversion_rate( + TransactionStatus::Idle, + None, + Some(1.0), + Some(1.0), + 0.0 + ), (None, TransactionStatus::Idle), ); } @@ -195,7 +216,13 @@ mod tests { #[test] fn transaction_is_not_submitted_when_difference_is_below_threshold() { assert_eq!( - test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(1.0), Some(1.0), Some(1.01), 0.02), + test_maybe_select_new_conversion_rate( + TransactionStatus::Idle, + Some(1.0), + Some(1.0), + Some(1.01), + 0.02 + ), (None, TransactionStatus::Idle), ); } @@ -203,7 +230,13 @@ mod tests { #[test] fn transaction_is_submitted_when_difference_is_above_threshold() { assert_eq!( - test_maybe_select_new_conversion_rate(TransactionStatus::Idle, Some(1.0), Some(1.0), Some(1.03), 0.02), + test_maybe_select_new_conversion_rate( + TransactionStatus::Idle, + Some(1.0), + Some(1.0), + Some(1.03), + 0.02 + ), (Some((1.0, 1.03)), TransactionStatus::Idle), ); } diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 8595ab2842b3d..cca9e5196b3ca 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -21,7 +21,9 @@ use crate::finality_target::SubstrateFinalityTarget; use bp_header_chain::justification::GrandpaJustification; use bp_runtime::AccountIdOf; use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; -use relay_substrate_client::{finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader}; +use relay_substrate_client::{ + finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader, +}; use relay_utils::{metrics::MetricsParams, BlockNumberBase}; use sp_core::Bytes; use std::{fmt::Debug, marker::PhantomData, time::Duration}; @@ -97,14 +99,12 @@ impl Debug } } -impl SubstrateFinalityToSubstrate { +impl + SubstrateFinalityToSubstrate +{ /// Create new Substrate-to-Substrate headers pipeline. pub fn new(target_client: Client, target_sign: TargetSign) -> Self { - SubstrateFinalityToSubstrate { - target_client, - target_sign, - _marker: Default::default(), - } + SubstrateFinalityToSubstrate { target_client, target_sign, _marker: Default::default() } } } @@ -157,7 +157,10 @@ where FinalitySource::new(source_client, None), SubstrateFinalityTarget::new(target_client, pipeline, transactions_mortality), FinalitySyncParams { - tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), + tick: std::cmp::max( + SourceChain::AVERAGE_BLOCK_INTERVAL, + TargetChain::AVERAGE_BLOCK_INTERVAL, + ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: relay_substrate_client::transaction_stall_timeout( transactions_mortality, diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index 5db7d080ab1b8..1353eec87278a 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -36,11 +36,7 @@ pub struct SubstrateFinalityTarget { impl SubstrateFinalityTarget { /// Create new Substrate headers target. pub fn new(client: Client, pipeline: P, transactions_mortality: Option) -> Self { - SubstrateFinalityTarget { - client, - pipeline, - transactions_mortality, - } + SubstrateFinalityTarget { client, pipeline, transactions_mortality } } } @@ -97,18 +93,21 @@ where let pipeline = self.pipeline.clone(); let transactions_mortality = self.transactions_mortality; self.client - .submit_signed_extrinsic(transactions_author, move |best_block_id, transaction_nonce| { - pipeline.make_submit_finality_proof_transaction( - relay_substrate_client::TransactionEra::new( - best_block_id.0, - best_block_id.1, - transactions_mortality, - ), - transaction_nonce, - header, - proof, - ) - }) + .submit_signed_extrinsic( + transactions_author, + move |best_block_id, transaction_nonce| { + pipeline.make_submit_finality_proof_transaction( + relay_substrate_client::TransactionEra::new( + best_block_id.0, + best_block_id.1, + transactions_mortality, + ), + transaction_nonce, + header, + proof, + ) + }, + ) .await .map(drop) } diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index 4a3a16bbe1775..00397434a0d7e 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -21,10 +21,10 @@ //! and authorities set from source to target chain. The headers sync starts //! with this header. -use bp_header_chain::InitializationData; use bp_header_chain::{ find_grandpa_authorities_scheduled_change, justification::{verify_justification, GrandpaJustification}, + InitializationData, }; use codec::Decode; use finality_grandpa::voter_set::VoterSet; @@ -103,31 +103,30 @@ async fn prepare_initialization_data( // In ideal world we just need to get best finalized header and then to read GRANDPA authorities // set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at this header. // - // But now there are problems with this approach - `CurrentSetId` may return invalid value. So here - // we're waiting for the next justification, read the authorities set and then try to figure out - // the set id with bruteforce. - let justifications = source_client - .subscribe_justifications() - .await - .map_err(|err| format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err))?; + // But now there are problems with this approach - `CurrentSetId` may return invalid value. So + // here we're waiting for the next justification, read the authorities set and then try to + // figure out the set id with bruteforce. + let justifications = source_client.subscribe_justifications().await.map_err(|err| { + format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err) + })?; // Read next justification - the header that it finalizes will be used as initial header. let justification = justifications .next() .await .map_err(|err| err.to_string()) - .and_then(|justification| justification.ok_or_else(|| "stream has ended unexpectedly".into())) + .and_then(|justification| { + justification.ok_or_else(|| "stream has ended unexpectedly".into()) + }) .map_err(|err| { - format!( - "Failed to read {} justification from the stream: {}", - SourceChain::NAME, - err, - ) + format!("Failed to read {} justification from the stream: {}", SourceChain::NAME, err,) })?; // Read initial header. - let justification: GrandpaJustification = Decode::decode(&mut &justification.0[..]) - .map_err(|err| format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err))?; + let justification: GrandpaJustification = + Decode::decode(&mut &justification.0[..]).map_err(|err| { + format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err) + })?; let (initial_header_hash, initial_header_number) = (justification.commit.target_hash, justification.commit.target_number); @@ -140,7 +139,8 @@ async fn prepare_initialization_data( ); // Read GRANDPA authorities set at initial header. - let initial_authorities_set = source_authorities_set(&source_client, initial_header_hash).await?; + let initial_authorities_set = + source_authorities_set(&source_client, initial_header_hash).await?; log::trace!(target: "bridge", "Selected {} initial authorities set: {:?}", SourceChain::NAME, initial_authorities_set, @@ -159,7 +159,8 @@ async fn prepare_initialization_data( ); let schedules_change = scheduled_change.is_some(); if schedules_change { - authorities_for_verification = source_authorities_set(&source_client, *initial_header.parent_hash()).await?; + authorities_for_verification = + source_authorities_set(&source_client, *initial_header.parent_hash()).await?; log::trace!( target: "bridge", "Selected {} header is scheduling GRANDPA authorities set changes. Using previous set: {:?}", @@ -171,13 +172,14 @@ async fn prepare_initialization_data( // Now let's try to guess authorities set id by verifying justification. let mut initial_authorities_set_id = 0; let mut min_possible_block_number = SourceChain::BlockNumber::zero(); - let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()).ok_or_else(|| { - format!( - "Read invalid {} authorities set: {:?}", - SourceChain::NAME, - authorities_for_verification, - ) - })?; + let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()) + .ok_or_else(|| { + format!( + "Read invalid {} authorities set: {:?}", + SourceChain::NAME, + authorities_for_verification, + ) + })?; loop { log::trace!( target: "bridge", "Trying {} GRANDPA authorities set id: {}", @@ -194,21 +196,21 @@ async fn prepare_initialization_data( .is_ok(); if is_valid_set_id { - break; + break } initial_authorities_set_id += 1; min_possible_block_number += One::one(); if min_possible_block_number > initial_header_number { - // there can't be more authorities set changes than headers => if we have reached `initial_block_number` - // and still have not found correct value of `initial_authorities_set_id`, then something - // else is broken => fail + // there can't be more authorities set changes than headers => if we have reached + // `initial_block_number` and still have not found correct value of + // `initial_authorities_set_id`, then something else is broken => fail return Err(format!( "Failed to guess initial {} GRANDPA authorities set id: checked all\ possible ids in range [0; {}]", SourceChain::NAME, initial_header_number - )); + )) } } @@ -244,10 +246,8 @@ async fn source_authorities_set( source_client: &Client, header_hash: SourceChain::Hash, ) -> Result { - let raw_authorities_set = source_client - .grandpa_authorities_set(header_hash) - .await - .map_err(|err| { + let raw_authorities_set = + source_client.grandpa_authorities_set(header_hash).await.map_err(|err| { format!( "Failed to retrive {} GRANDPA authorities set at header {}: {:?}", SourceChain::NAME, diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index 91d551140c2de..01f881998ad00 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -27,15 +27,9 @@ pub fn token_price_metric( FloatJsonValueMetric::new( registry, prefix, - format!( - "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", - token_id - ), + format!("https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", token_id), format!("$.{}.btc", token_id), format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), - format!( - "Rate used to convert from {} to some BASE tokens", - token_id.to_uppercase() - ), + format!("Rate used to convert from {} to some BASE tokens", token_id.to_uppercase()), ) } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index f1f67d6c6e305..973f52d60a38b 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -16,9 +16,10 @@ //! Tools for supporting message lanes between two Substrate-based chains. -use crate::messages_source::SubstrateMessagesProof; -use crate::messages_target::SubstrateMessagesReceivingProof; -use crate::on_demand_headers::OnDemandHeadersRelay; +use crate::{ + messages_source::SubstrateMessagesProof, messages_target::SubstrateMessagesReceivingProof, + on_demand_headers::OnDemandHeadersRelay, +}; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; @@ -65,18 +66,22 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Underlying generic message lane. type MessageLane: MessageLane; - /// Name of the runtime method that returns dispatch weight of outbound messages at the source chain. + /// Name of the runtime method that returns dispatch weight of outbound messages at the source + /// chain. const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; /// Name of the runtime method that returns latest generated nonce at the source chain. const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns latest received (confirmed) nonce at the the source chain. + /// Name of the runtime method that returns latest received (confirmed) nonce at the the source + /// chain. const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; /// Name of the runtime method that returns latest received nonce at the target chain. const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the target chain. + /// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the + /// target chain. const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; - /// Number of the runtime method that returns state of "unrewarded relayers" set at the target chain. + /// Number of the runtime method that returns state of "unrewarded relayers" set at the target + /// chain. const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str; /// Name of the runtime method that returns id of best finalized source header at target chain. @@ -101,7 +106,8 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Target chain. type TargetChain: Chain; - /// Returns id of account that we're using to sign transactions at target chain (messages proof). + /// Returns id of account that we're using to sign transactions at target chain (messages + /// proof). fn target_transactions_author(&self) -> AccountIdOf; /// Make messages delivery transaction. @@ -113,7 +119,8 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { proof: ::MessagesProof, ) -> Bytes; - /// Returns id of account that we're using to sign transactions at source chain (delivery proof). + /// Returns id of account that we're using to sign transactions at source chain (delivery + /// proof). fn source_transactions_author(&self) -> AccountIdOf; /// Make messages receiving proof transaction. @@ -127,7 +134,12 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Substrate-to-Substrate message lane. #[derive(Debug)] -pub struct SubstrateMessageLaneToSubstrate { +pub struct SubstrateMessageLaneToSubstrate< + Source: Chain, + SourceSignParams, + Target: Chain, + TargetSignParams, +> { /// Client for the source Substrate chain. pub source_client: Client, /// Parameters required to sign transactions for source chain. @@ -194,8 +206,8 @@ pub fn select_delivery_transaction_limits, /// Shared reference to the actual source -> chain token conversion rate. pub source_to_base_conversion_rate: Option, - /// Shared reference to the stored (in the source chain runtime storage) target -> source chain conversion rate. + /// Shared reference to the stored (in the source chain runtime storage) target -> source chain + /// conversion rate. pub target_to_source_conversion_rate: Option, } impl StandaloneMessagesMetrics { /// Return conversion rate from target to source tokens. pub async fn target_to_source_conversion_rate(&self) -> Option { - let target_to_base_conversion_rate = (*self.target_to_base_conversion_rate.as_ref()?.read().await)?; - let source_to_base_conversion_rate = (*self.source_to_base_conversion_rate.as_ref()?.read().await)?; + let target_to_base_conversion_rate = + (*self.target_to_base_conversion_rate.as_ref()?.read().await)?; + let source_to_base_conversion_rate = + (*self.source_to_base_conversion_rate.as_ref()?.read().await)?; Some(source_to_base_conversion_rate / target_to_base_conversion_rate) } } @@ -246,8 +261,8 @@ pub fn add_standalone_metrics( let mut target_to_source_conversion_rate = None; let mut source_to_base_conversion_rate = None; let mut target_to_base_conversion_rate = None; - let mut metrics_params = - relay_utils::relay_metrics(metrics_prefix, metrics_params).standalone_metric(|registry, prefix| { + let mut metrics_params = relay_utils::relay_metrics(metrics_prefix, metrics_params) + .standalone_metric(|registry, prefix| { StorageProofOverheadMetric::new( registry, prefix, @@ -256,8 +271,10 @@ pub fn add_standalone_metrics( format!("{} storage proof overhead", P::SourceChain::NAME), ) })?; - if let Some((target_to_source_conversion_rate_storage_key, initial_target_to_source_conversion_rate)) = - target_to_source_conversion_rate_params + if let Some(( + target_to_source_conversion_rate_storage_key, + initial_target_to_source_conversion_rate, + )) = target_to_source_conversion_rate_params { metrics_params = metrics_params.standalone_metric(|registry, prefix| { let metric = FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( @@ -285,14 +302,16 @@ pub fn add_standalone_metrics( } if let Some(source_chain_token_id) = source_chain_token_id { metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = crate::helpers::token_price_metric(registry, prefix, source_chain_token_id)?; + let metric = + crate::helpers::token_price_metric(registry, prefix, source_chain_token_id)?; source_to_base_conversion_rate = Some(metric.shared_value_ref()); Ok(metric) })?; } if let Some(target_chain_token_id) = target_chain_token_id { metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = crate::helpers::token_price_metric(registry, prefix, target_chain_token_id)?; + let metric = + crate::helpers::token_price_metric(registry, prefix, target_chain_token_id)?; target_to_base_conversion_rate = Some(metric.shared_value_ref()); Ok(metric) })?; @@ -312,19 +331,21 @@ mod tests { use super::*; use async_std::sync::{Arc, RwLock}; - type RialtoToMillauMessagesWeights = pallet_bridge_messages::weights::RialtoWeight; + type RialtoToMillauMessagesWeights = + pallet_bridge_messages::weights::RialtoWeight; #[test] fn select_delivery_transaction_limits_works() { - let (max_count, max_weight) = select_delivery_transaction_limits::( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); + let (max_count, max_weight) = + select_delivery_transaction_limits::( + bp_millau::max_extrinsic_weight(), + bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + ); assert_eq!( (max_count, max_weight), // We don't actually care about these values, so feel free to update them whenever test - // fails. The only thing to do before that is to ensure that new values looks sane: i.e. weight - // reserved for messages dispatch allows dispatch of non-trivial messages. + // fails. The only thing to do before that is to ensure that new values looks sane: + // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. (782, 216_583_333_334), diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 4d3332d3271c9..c450144a9f6e9 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -18,9 +18,10 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. -use crate::messages_lane::SubstrateMessageLane; -use crate::messages_target::SubstrateMessagesReceivingProof; -use crate::on_demand_headers::OnDemandHeadersRelay; +use crate::{ + messages_lane::SubstrateMessageLane, messages_target::SubstrateMessagesReceivingProof, + on_demand_headers::OnDemandHeadersRelay, +}; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; @@ -29,16 +30,17 @@ use bridge_runtime_common::messages::{ }; use codec::{Decode, Encode}; use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; use messages_relay::{ - message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState, + ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, + SourceClientState, }, }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, IndexOf, + BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, + IndexOf, }; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; @@ -69,12 +71,7 @@ impl SubstrateMessagesSource

{ lane_id: LaneId, target_to_source_headers_relay: Option>, ) -> Self { - SubstrateMessagesSource { - client, - lane, - lane_id, - target_to_source_headers_relay, - } + SubstrateMessagesSource { client, lane, lane_id, target_to_source_headers_relay } } } @@ -150,8 +147,8 @@ where Some(id.1), ) .await?; - let latest_generated_nonce: MessageNonce = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + let latest_generated_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_generated_nonce)) } @@ -167,8 +164,8 @@ where Some(id.1), ) .await?; - let latest_received_nonce: MessageNonce = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_received_nonce)) } @@ -176,7 +173,10 @@ where &self, id: SourceHeaderIdOf, nonces: RangeInclusive, - ) -> Result::SourceChainBalance>, SubstrateError> { + ) -> Result< + MessageDetailsMap<::SourceChainBalance>, + SubstrateError, + > { let encoded_response = self .client .state_call( @@ -187,7 +187,8 @@ where .await?; make_message_details_map::( - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?, + Decode::decode(&mut &encoded_response.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?, nonces, ) } @@ -205,7 +206,8 @@ where ), SubstrateError, > { - let mut storage_keys = Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); + let mut storage_keys = + Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { let message_key = pallet_bridge_messages::storage_keys::message_key( @@ -223,12 +225,7 @@ where )); } - let proof = self - .client - .prove_storage(storage_keys, id.1) - .await? - .iter_nodes() - .collect(); + let proof = self.client.prove_storage(storage_keys, id.1).await?.iter_nodes().collect(); let proof = FromBridgedChainMessagesProof { bridged_header_hash: id.1, storage_proof: proof, @@ -246,9 +243,16 @@ where ) -> Result<(), SubstrateError> { let lane = self.lane.clone(); self.client - .submit_signed_extrinsic(self.lane.source_transactions_author(), move |_, transaction_nonce| { - lane.make_messages_receiving_proof_transaction(transaction_nonce, generated_at_block, proof) - }) + .submit_signed_extrinsic( + self.lane.source_transactions_author(), + move |_, transaction_nonce| { + lane.make_messages_receiving_proof_transaction( + transaction_nonce, + generated_at_block, + proof, + ) + }, + ) .await?; Ok(()) } @@ -259,7 +263,9 @@ where } } - async fn estimate_confirmation_transaction(&self) -> ::SourceChainBalance { + async fn estimate_confirmation_transaction( + &self, + ) -> ::SourceChainBalance { self.client .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( Zero::zero(), @@ -276,10 +282,14 @@ where /// /// We don't care about proof actually being the valid proof, because its validity doesn't /// affect the call weight - we only care about its size. -fn prepare_dummy_messages_delivery_proof() -> SubstrateMessagesReceivingProof { - let single_message_confirmation_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint(SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1, 1) - .unwrap_or(u32::MAX); +fn prepare_dummy_messages_delivery_proof( +) -> SubstrateMessagesReceivingProof { + let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( + SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + 1, + 1, + ) + .unwrap_or(u32::MAX); let proof_size = TC::STORAGE_PROOF_OVERHEAD.saturating_add(single_message_confirmation_size); ( UnrewardedRelayersState { @@ -303,7 +313,10 @@ fn prepare_dummy_messages_delivery_proof() -> SubstrateMes pub async fn read_client_state( self_client: &Client, best_finalized_header_id_method_name: &str, -) -> Result, HeaderId>, SubstrateError> +) -> Result< + ClientState, HeaderId>, + SubstrateError, +> where SelfChain: Chain, SelfChain::Header: DeserializeOwned, @@ -313,8 +326,10 @@ where { // let's read our state first: we need best finalized header hash on **this** chain let self_best_finalized_header_hash = self_client.best_finalized_header_hash().await?; - let self_best_finalized_header = self_client.header_by_hash(self_best_finalized_header_hash).await?; - let self_best_finalized_id = HeaderId(*self_best_finalized_header.number(), self_best_finalized_header_hash); + let self_best_finalized_header = + self_client.header_by_hash(self_best_finalized_header_hash).await?; + let self_best_finalized_id = + HeaderId(*self_best_finalized_header.number(), self_best_finalized_header_hash); // now let's read our best header on **this** chain let self_best_header = self_client.best_header().await?; @@ -330,11 +345,10 @@ where ) .await?; let decoded_best_finalized_peer_on_self: (BridgedHeaderNumber, BridgedHeaderHash) = - Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]).map_err(SubstrateError::ResponseParseFailed)?; - let peer_on_self_best_finalized_id = HeaderId( - decoded_best_finalized_peer_on_self.0, - decoded_best_finalized_peer_on_self.1, - ); + Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; + let peer_on_self_best_finalized_id = + HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); Ok(ClientState { best_self: self_best_id, @@ -358,16 +372,14 @@ fn make_message_details_map( // this is actually prevented by external logic if nonces.is_empty() { - return Ok(weights_map); + return Ok(weights_map) } // check if last nonce is missing - loop below is not checking this - let last_nonce_is_missing = weights - .last() - .map(|details| details.nonce != *nonces.end()) - .unwrap_or(true); + let last_nonce_is_missing = + weights.last().map(|details| details.nonce != *nonces.end()).unwrap_or(true); if last_nonce_is_missing { - return make_missing_nonce_error(*nonces.end()); + return make_missing_nonce_error(*nonces.end()) } let mut expected_nonce = *nonces.start(); @@ -379,20 +391,21 @@ fn make_message_details_map( (false, true) => { // this may happen if some messages were already pruned from the source node // - // this is not critical error and will be auto-resolved by messages lane (and target node) + // this is not critical error and will be auto-resolved by messages lane (and target + // node) log::info!( target: "bridge", "Some messages are missing from the {} node: {:?}. Target node may be out of sync?", C::NAME, expected_nonce..details.nonce, ); - } + }, (false, false) => { // some nonces are missing from the middle/tail of the range // // this is critical error, because we can't miss any nonces - return make_missing_nonce_error(expected_nonce); - } + return make_missing_nonce_error(expected_nonce) + }, } weights_map.insert( @@ -528,7 +541,8 @@ mod tests { #[test] fn prepare_dummy_messages_delivery_proof_works() { - let expected_minimal_size = Wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Rococo::STORAGE_PROOF_OVERHEAD; + let expected_minimal_size = + Wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Rococo::STORAGE_PROOF_OVERHEAD; let dummy_proof = prepare_dummy_messages_delivery_proof::(); assert!( dummy_proof.1.encode().len() as u32 > expected_minimal_size, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 8ad41281bfdcc..f7b911f2c023a 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -18,9 +18,11 @@ //! runtime that implements `HeaderApi` to allow bridging with //! chain. -use crate::messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}; -use crate::messages_source::{read_client_state, SubstrateMessagesProof}; -use crate::on_demand_headers::OnDemandHeadersRelay; +use crate::{ + messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}, + messages_source::{read_client_state, SubstrateMessagesProof}, + on_demand_headers::OnDemandHeadersRelay, +}; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; @@ -30,14 +32,14 @@ use bridge_runtime_common::messages::{ }; use codec::{Decode, Encode}; use frame_support::weights::{Weight, WeightToFeePolynomial}; -use messages_relay::message_lane::MessageLane; use messages_relay::{ - message_lane::{SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, WeightToFeeOf, + BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, + WeightToFeeOf, }; use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; use sp_core::Bytes; @@ -45,10 +47,8 @@ use sp_runtime::{traits::Saturating, DeserializeOwned, FixedPointNumber, FixedU1 use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. -pub type SubstrateMessagesReceivingProof = ( - UnrewardedRelayersState, - FromBridgedChainMessagesDeliveryProof>, -); +pub type SubstrateMessagesReceivingProof = + (UnrewardedRelayersState, FromBridgedChainMessagesDeliveryProof>); /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { @@ -150,8 +150,8 @@ where Some(id.1), ) .await?; - let latest_received_nonce: MessageNonce = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_received_nonce)) } @@ -167,8 +167,8 @@ where Some(id.1), ) .await?; - let latest_received_nonce: MessageNonce = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; Ok((id, latest_received_nonce)) } @@ -185,7 +185,8 @@ where ) .await?; let unrewarded_relayers_state: UnrewardedRelayersState = - Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?; + Decode::decode(&mut &encoded_response.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; Ok((id, unrewarded_relayers_state)) } @@ -193,10 +194,7 @@ where &self, id: TargetHeaderIdOf, ) -> Result< - ( - TargetHeaderIdOf, - ::MessagesReceivingProof, - ), + (TargetHeaderIdOf, ::MessagesReceivingProof), SubstrateError, > { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; @@ -227,9 +225,17 @@ where let lane = self.lane.clone(); let nonces_clone = nonces.clone(); self.client - .submit_signed_extrinsic(self.lane.target_transactions_author(), move |_, transaction_nonce| { - lane.make_messages_delivery_transaction(transaction_nonce, generated_at_header, nonces_clone, proof) - }) + .submit_signed_extrinsic( + self.lane.target_transactions_author(), + move |_, transaction_nonce| { + lane.make_messages_delivery_transaction( + transaction_nonce, + generated_at_header, + nonces_clone, + proof, + ) + }, + ) .await?; Ok(nonces) } @@ -247,11 +253,8 @@ where total_dispatch_weight: Weight, total_size: u32, ) -> Result<::SourceChainBalance, SubstrateError> { - let conversion_rate = self - .metric_values - .target_to_source_conversion_rate() - .await - .ok_or_else(|| { + let conversion_rate = + self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| { SubstrateError::Custom(format!( "Failed to compute conversion rate from {} to {}", P::TargetChain::NAME, @@ -264,26 +267,31 @@ where Zero::zero(), HeaderId(Default::default(), Default::default()), nonces.clone(), - prepare_dummy_messages_proof::(nonces.clone(), total_dispatch_weight, total_size), + prepare_dummy_messages_proof::( + nonces.clone(), + total_dispatch_weight, + total_size, + ), ); let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); - // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch fee payment - // (Currency::transfer in regular deployment). But if message dispatch has already been paid - // at the Source chain, the delivery transaction will refund relayer with this additional cost. - // But `estimate_extrinsic_fee` obviously just returns pre-dispatch cost of the transaction. So - // if transaction delivers prepaid message, then it may happen that pre-dispatch cost is larger - // than reward and `Rational` relayer will refuse to deliver this message. + // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch + // fee payment (Currency::transfer in regular deployment). But if message dispatch has + // already been paid at the Source chain, the delivery transaction will refund relayer with + // this additional cost. But `estimate_extrinsic_fee` obviously just returns pre-dispatch + // cost of the transaction. So if transaction delivers prepaid message, then it may happen + // that pre-dispatch cost is larger than reward and `Rational` relayer will refuse to + // deliver this message. // - // The most obvious solution would be to deduct total weight of dispatch fee payments from the - // `total_dispatch_weight` and use regular `estimate_extrinsic_fee` call. But what if - // `total_dispatch_weight` is less than total dispatch fee payments weight? Weight is strictly - // positive, so we can't use this option. + // The most obvious solution would be to deduct total weight of dispatch fee payments from + // the `total_dispatch_weight` and use regular `estimate_extrinsic_fee` call. But what if + // `total_dispatch_weight` is less than total dispatch fee payments weight? Weight is + // strictly positive, so we can't use this option. // - // Instead we'll be directly using `WeightToFee` and `NextFeeMultiplier` of the Target chain. - // This requires more knowledge of the Target chain, but seems there's no better way to solve - // this now. + // Instead we'll be directly using `WeightToFee` and `NextFeeMultiplier` of the Target + // chain. This requires more knowledge of the Target chain, but seems there's no better way + // to solve this now. let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { const WEIGHT_DIFFERENCE: Weight = 100; @@ -294,7 +302,11 @@ where Zero::zero(), HeaderId(Default::default(), Default::default()), nonces.clone(), - prepare_dummy_messages_proof::(nonces.clone(), larger_dispatch_weight, total_size), + prepare_dummy_messages_proof::( + nonces.clone(), + larger_dispatch_weight, + total_size, + ), )) .await?; @@ -311,10 +323,11 @@ where Zero::zero() }; - let delivery_fee_in_source_tokens = convert_target_tokens_to_source_tokens::( - FixedU128::from_float(conversion_rate), - inclusion_fee_in_target_tokens.saturating_sub(expected_refund_in_target_tokens), - ); + let delivery_fee_in_source_tokens = + convert_target_tokens_to_source_tokens::( + FixedU128::from_float(conversion_rate), + inclusion_fee_in_target_tokens.saturating_sub(expected_refund_in_target_tokens), + ); log::trace!( target: "bridge", @@ -356,7 +369,10 @@ fn prepare_dummy_messages_proof( total_dispatch_weight, FromBridgedChainMessagesProof { bridged_header_hash: Default::default(), - storage_proof: vec![vec![0; SC::STORAGE_PROOF_OVERHEAD.saturating_add(total_size) as usize]], + storage_proof: vec![vec![ + 0; + SC::STORAGE_PROOF_OVERHEAD.saturating_add(total_size) as usize + ]], lane: Default::default(), nonces_start: *nonces.start(), nonces_end: *nonces.end(), @@ -373,8 +389,10 @@ fn convert_target_tokens_to_source_tokens( where SC::Balance: TryFrom, { - SC::Balance::try_from(target_to_source_conversion_rate.saturating_mul_int(target_transaction_fee)) - .unwrap_or_else(|_| SC::Balance::max_value()) + SC::Balance::try_from( + target_to_source_conversion_rate.saturating_mul_int(target_transaction_fee), + ) + .unwrap_or_else(|_| SC::Balance::max_value()) } /// Compute fee multiplier that is used by the chain, given a couple of fees for transactions @@ -392,7 +410,8 @@ fn compute_fee_multiplier( larger_adjusted_weight_fee: BalanceOf, larger_tx_weight: Weight, ) -> FixedU128 { - let adjusted_weight_fee_difference = larger_adjusted_weight_fee.saturating_sub(smaller_adjusted_weight_fee); + let adjusted_weight_fee_difference = + larger_adjusted_weight_fee.saturating_sub(smaller_adjusted_weight_fee); let smaller_tx_unadjusted_weight_fee = WeightToFeeOf::::calc(&smaller_tx_weight); let larger_tx_unadjusted_weight_fee = WeightToFeeOf::::calc(&larger_tx_weight); FixedU128::saturating_from_rational( @@ -511,10 +530,12 @@ mod tests { let multiplier = FixedU128::saturating_from_rational(1, 1000); let smaller_weight = 1_000_000; - let smaller_adjusted_weight_fee = multiplier.saturating_mul_int(WeightToFeeOf::::calc(&smaller_weight)); + let smaller_adjusted_weight_fee = + multiplier.saturating_mul_int(WeightToFeeOf::::calc(&smaller_weight)); let larger_weight = smaller_weight + 200_000; - let larger_adjusted_weight_fee = multiplier.saturating_mul_int(WeightToFeeOf::::calc(&larger_weight)); + let larger_adjusted_weight_fee = + multiplier.saturating_mul_int(WeightToFeeOf::::calc(&larger_weight)); assert_eq!( compute_fee_multiplier::( @@ -533,7 +554,8 @@ mod tests { compute_prepaid_messages_refund::( 10, FixedU128::saturating_from_rational(110, 100), - ) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN).into() + ) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN) + .into() ); } } diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 885b3a788d9f4..4dad20579a90d 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -31,18 +31,23 @@ use relay_substrate_client::{ Chain, Client, HeaderIdOf, SyncHeader, }; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, + MaybeConnectionError, }; -use crate::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, STALL_TIMEOUT, +use crate::{ + finality_pipeline::{ + SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, + STALL_TIMEOUT, + }, + finality_target::SubstrateFinalityTarget, }; -use crate::finality_target::SubstrateFinalityTarget; /// On-demand Substrate <-> Substrate headers relay. /// -/// This relay may be requested to sync more headers, whenever some other relay (e.g. messages relay) needs -/// it to continue its regular work. When enough headers are relayed, on-demand stops syncing headers. +/// This relay may be requested to sync more headers, whenever some other relay (e.g. messages +/// relay) needs it to continue its regular work. When enough headers are relayed, on-demand stops +/// syncing headers. #[derive(Clone)] pub struct OnDemandHeadersRelay { /// Relay task name. @@ -68,7 +73,11 @@ impl OnDemandHeadersRelay { TargetChain::BlockNumber: BlockNumberBase, TargetSign: Clone + Send + Sync + 'static, P: SubstrateFinalitySyncPipeline< - FinalitySyncPipeline = SubstrateFinalityToSubstrate, + FinalitySyncPipeline = SubstrateFinalityToSubstrate< + SourceChain, + TargetChain, + TargetSign, + >, TargetChain = TargetChain, >, { @@ -135,8 +144,11 @@ async fn background_task( _, SubstrateFinalityToSubstrate, >::new(source_client.clone(), Some(required_header_number.clone())); - let mut finality_target = - SubstrateFinalityTarget::new(target_client.clone(), pipeline.clone(), target_transactions_mortality); + let mut finality_target = SubstrateFinalityTarget::new( + target_client.clone(), + pipeline.clone(), + target_transactions_mortality, + ); let mut latest_non_mandatory_at_source = Zero::zero(); let mut restart_relay = true; @@ -163,12 +175,16 @@ async fn background_task( &mut finality_target, ) .await; - continue; + continue } // read best finalized source header number from target - let best_finalized_source_header_at_target = - best_finalized_source_header_at_target::(&finality_target, &relay_task_name).await; + let best_finalized_source_header_at_target = best_finalized_source_header_at_target::< + SourceChain, + _, + _, + >(&finality_target, &relay_task_name) + .await; if matches!(best_finalized_source_header_at_target, Err(ref e) if e.is_connection_error()) { relay_utils::relay_loop::reconnect_failed_client( FailedClient::Target, @@ -177,11 +193,12 @@ async fn background_task( &mut finality_target, ) .await; - continue; + continue } // submit mandatory header if some headers are missing - let best_finalized_source_header_at_target_fmt = format!("{:?}", best_finalized_source_header_at_target); + let best_finalized_source_header_at_target_fmt = + format!("{:?}", best_finalized_source_header_at_target); let mandatory_scan_range = mandatory_headers_scan_range::( best_finalized_source_header_at_source.ok(), best_finalized_source_header_at_target.ok(), @@ -207,8 +224,8 @@ async fn background_task( // there are no (or we don't need to relay them) mandatory headers in the range // => to avoid scanning the same headers over and over again, remember that latest_non_mandatory_at_source = mandatory_scan_range.1; - } - Err(e) => { + }, + Err(e) => if e.is_connection_error() { relay_utils::relay_loop::reconnect_failed_client( FailedClient::Source, @@ -217,9 +234,8 @@ async fn background_task( &mut finality_target, ) .await; - continue; - } - } + continue + }, } } @@ -230,7 +246,10 @@ async fn background_task( finality_source.clone(), finality_target.clone(), FinalitySyncParams { - tick: std::cmp::max(SourceChain::AVERAGE_BLOCK_INTERVAL, TargetChain::AVERAGE_BLOCK_INTERVAL), + tick: std::cmp::max( + SourceChain::AVERAGE_BLOCK_INTERVAL, + TargetChain::AVERAGE_BLOCK_INTERVAL, + ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, only_mandatory_headers, @@ -279,12 +298,12 @@ async fn mandatory_headers_scan_range( .checked_sub(&best_finalized_source_header_at_target) .unwrap_or_else(Zero::zero); if current_headers_difference <= maximal_headers_difference { - return None; + return None } // if relay is already asked to sync headers, don't do anything yet if required_header_number > best_finalized_source_header_at_target { - return None; + return None } Some(( @@ -293,7 +312,8 @@ async fn mandatory_headers_scan_range( )) } -/// Try to find mandatory header in the inclusive headers range and, if one is found, ask to relay it. +/// Try to find mandatory header in the inclusive headers range and, if one is found, ask to relay +/// it. /// /// Returns `true` if header was found and (asked to be) relayed and `false` otherwise. async fn relay_mandatory_header_from_range( @@ -308,7 +328,8 @@ where P: FinalitySyncPipeline, { // search for mandatory header first - let mandatory_source_header_number = find_mandatory_header_in_range(finality_source, range).await?; + let mandatory_source_header_number = + find_mandatory_header_in_range(finality_source, range).await?; // if there are no mandatory headers - we have nothing to do let mandatory_source_header_number = match mandatory_source_header_number { @@ -320,7 +341,7 @@ where // less than our `mandatory_source_header_number` before logging anything let mut required_header_number = required_header_number.lock().await; if *required_header_number >= mandatory_source_header_number { - return Ok(false); + return Ok(false) } log::trace!( @@ -348,19 +369,16 @@ where SubstrateFinalitySource: FinalitySourceClient

, P: FinalitySyncPipeline, { - finality_source - .on_chain_best_finalized_block_number() - .await - .map_err(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from source in {} relay: {:?}", - relay_task_name, - error, - ); + finality_source.on_chain_best_finalized_block_number().await.map_err(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from source in {} relay: {:?}", + relay_task_name, + error, + ); - error - }) + error + }) } /// Read best finalized source block number from target client. @@ -375,19 +393,16 @@ where P: SubstrateFinalitySyncPipeline, P::FinalitySyncPipeline: FinalitySyncPipeline, { - finality_target - .best_finalized_source_block_number() - .await - .map_err(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from target in {} relay: {:?}", - relay_task_name, - error, - ); + finality_target.best_finalized_source_block_number().await.map_err(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from target in {} relay: {:?}", + relay_task_name, + error, + ); - error - }) + error + }) } /// Read first mandatory header in given inclusive range. @@ -403,9 +418,10 @@ where { let mut current = range.0; while current <= range.1 { - let header: SyncHeader = finality_source.client().header_by_number(current).await?.into(); + let header: SyncHeader = + finality_source.client().header_by_number(current).await?.into(); if header.is_mandatory() { - return Ok(Some(current)); + return Ok(Some(current)) } current += One::one(); @@ -431,7 +447,13 @@ mod tests { #[async_std::test] async fn mandatory_headers_scan_range_selects_range_if_too_many_headers_are_missing() { assert_eq!( - mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, 5, &Arc::new(Mutex::new(0))).await, + mandatory_headers_scan_range::( + AT_SOURCE, + AT_TARGET, + 5, + &Arc::new(Mutex::new(0)) + ) + .await, Some((AT_TARGET.unwrap() + 1, AT_SOURCE.unwrap())), ); } @@ -439,7 +461,13 @@ mod tests { #[async_std::test] async fn mandatory_headers_scan_range_selects_nothing_if_enough_headers_are_relayed() { assert_eq!( - mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, 10, &Arc::new(Mutex::new(0))).await, + mandatory_headers_scan_range::( + AT_SOURCE, + AT_TARGET, + 10, + &Arc::new(Mutex::new(0)) + ) + .await, None, ); } diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs index d03d40759731f..2b2d8029fc74b 100644 --- a/relays/messages/src/message_lane.rs +++ b/relays/messages/src/message_lane.rs @@ -61,7 +61,9 @@ pub trait MessageLane: 'static + Clone + Send + Sync { } /// Source header id within given one-way message lane. -pub type SourceHeaderIdOf

= HeaderId<

::SourceHeaderHash,

::SourceHeaderNumber>; +pub type SourceHeaderIdOf

= + HeaderId<

::SourceHeaderHash,

::SourceHeaderNumber>; /// Target header id within given one-way message lane. -pub type TargetHeaderIdOf

= HeaderId<

::TargetHeaderHash,

::TargetHeaderNumber>; +pub type TargetHeaderIdOf

= + HeaderId<

::TargetHeaderHash,

::TargetHeaderNumber>; diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 72c984d2990cc..595d241bf3014 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -24,10 +24,12 @@ //! finalized header. I.e. when talking about headers in lane context, we //! only care about finalized headers. -use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use crate::message_race_delivery::run as run_message_delivery_race; -use crate::message_race_receiving::run as run_message_receiving_race; -use crate::metrics::MessageLaneLoopMetrics; +use crate::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_race_delivery::run as run_message_delivery_race, + message_race_receiving::run as run_message_receiving_race, + metrics::MessageLaneLoopMetrics, +}; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; @@ -64,20 +66,22 @@ pub struct Params { pub enum RelayerMode { /// The relayer doesn't care about rewards. Altruistic, - /// The relayer will deliver all messages and confirmations as long as he's not losing any funds. + /// The relayer will deliver all messages and confirmations as long as he's not losing any + /// funds. Rational, } /// Message delivery race parameters. #[derive(Debug, Clone)] pub struct MessageDeliveryParams { - /// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number of entries - /// in the `InboundLaneData::relayers` set, all new messages will be rejected until reward payment will - /// be proved (by including outbound lane state to the message delivery transaction). + /// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number + /// of entries in the `InboundLaneData::relayers` set, all new messages will be rejected until + /// reward payment will be proved (by including outbound lane state to the message delivery + /// transaction). pub max_unrewarded_relayer_entries_at_target: MessageNonce, - /// Message delivery race will stop delivering messages if there are `max_unconfirmed_nonces_at_target` - /// unconfirmed nonces on the target node. The race would continue once they're confirmed by the - /// receiving race. + /// Message delivery race will stop delivering messages if there are + /// `max_unconfirmed_nonces_at_target` unconfirmed nonces on the target node. The race would + /// continue once they're confirmed by the receiving race. pub max_unconfirmed_nonces_at_target: MessageNonce, /// Maximal number of relayed messages in single delivery transaction. pub max_messages_in_single_batch: MessageNonce, @@ -103,7 +107,8 @@ pub struct MessageDetails { } /// Messages details map. -pub type MessageDetailsMap = BTreeMap>; +pub type MessageDetailsMap = + BTreeMap>; /// Message delivery race proof parameters. #[derive(Debug, PartialEq)] @@ -225,7 +230,8 @@ pub struct ClientState { pub best_self: SelfHeaderId, /// Best finalized header id of this chain. pub best_finalized_self: SelfHeaderId, - /// Best finalized header id of the peer chain read at the best block of this chain (at `best_finalized_self`). + /// Best finalized header id of the peer chain read at the best block of this chain (at + /// `best_finalized_self`). pub best_finalized_peer_at_best_self: PeerHeaderId, } @@ -244,14 +250,10 @@ pub struct ClientsState { pub target: Option>, } -/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs sync loop. +/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs +/// sync loop. pub fn metrics_prefix(lane: &LaneId) -> String { - format!( - "{}_to_{}_MessageLane_{}", - P::SOURCE_NAME, - P::TARGET_NAME, - hex::encode(lane) - ) + format!("{}_to_{}_MessageLane_{}", P::SOURCE_NAME, P::TARGET_NAME, hex::encode(lane)) } /// Run message lane service loop. @@ -270,22 +272,20 @@ pub async fn run( .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? .expose() .await? - .run( - metrics_prefix::

(¶ms.lane), - move |source_client, target_client, metrics| { - run_until_connection_lost( - params.clone(), - source_client, - target_client, - metrics, - exit_signal.clone(), - ) - }, - ) + .run(metrics_prefix::

(¶ms.lane), move |source_client, target_client, metrics| { + run_until_connection_lost( + params.clone(), + source_client, + target_client, + metrics, + exit_signal.clone(), + ) + }) .await } -/// Run one-way message delivery loop until connection with target or source node is lost, or exit signal is received. +/// Run one-way message delivery loop until connection with target or source node is lost, or exit +/// signal is received. async fn run_until_connection_lost, TC: TargetClient

>( params: Params, source_client: SC, @@ -557,7 +557,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { - return Err(TestError); + return Err(TestError) } Ok(data.source_state.clone()) } @@ -569,7 +569,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_source_fails { - return Err(TestError); + return Err(TestError) } Ok((id, data.source_latest_generated_nonce)) } @@ -609,11 +609,7 @@ pub(crate) mod tests { nonces: RangeInclusive, proof_parameters: MessageProofParameters, ) -> Result< - ( - SourceHeaderIdOf, - RangeInclusive, - TestMessagesProof, - ), + (SourceHeaderIdOf, RangeInclusive, TestMessagesProof), TestError, > { let mut data = self.data.lock(); @@ -694,7 +690,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError); + return Err(TestError) } Ok(data.target_state.clone()) } @@ -706,7 +702,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError); + return Err(TestError) } Ok((id, data.target_latest_received_nonce)) } @@ -732,7 +728,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError); + return Err(TestError) } Ok((id, data.target_latest_confirmed_received_nonce)) } @@ -753,14 +749,15 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut *data); if data.is_target_fails { - return Err(TestError); + return Err(TestError) } data.target_state.best_self = HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); data.target_state.best_finalized_self = data.target_state.best_self; data.target_latest_received_nonce = *proof.0.end(); if let Some(target_latest_confirmed_received_nonce) = proof.1 { - data.target_latest_confirmed_received_nonce = target_latest_confirmed_received_nonce; + data.target_latest_confirmed_received_nonce = + target_latest_confirmed_received_nonce; } data.submitted_messages_proofs.push(proof); Ok(nonces) @@ -780,11 +777,9 @@ pub(crate) mod tests { total_dispatch_weight: Weight, total_size: u32, ) -> Result { - Ok( - BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) - + total_dispatch_weight - + total_size as TestSourceChainBalance, - ) + Ok(BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) + + total_dispatch_weight + + total_size as TestSourceChainBalance) } } @@ -797,14 +792,8 @@ pub(crate) mod tests { async_std::task::block_on(async { let data = Arc::new(Mutex::new(data)); - let source_client = TestSourceClient { - data: data.clone(), - tick: source_tick, - }; - let target_client = TestTargetClient { - data: data.clone(), - tick: target_tick, - }; + let source_client = TestSourceClient { data: data.clone(), tick: source_tick }; + let target_client = TestTargetClient { data: data.clone(), tick: target_tick }; let _ = run( Params { lane: [0, 0, 0, 0], @@ -907,7 +896,10 @@ pub(crate) mod tests { data.source_state.best_finalized_self = data.source_state.best_self; // headers relay must only be started when we need new target headers at source node if data.target_to_source_header_required.is_some() { - assert!(data.source_state.best_finalized_peer_at_best_self.0 < data.target_state.best_self.0); + assert!( + data.source_state.best_finalized_peer_at_best_self.0 < + data.target_state.best_self.0 + ); data.target_to_source_header_required = None; } // syncing target headers -> source chain @@ -924,7 +916,10 @@ pub(crate) mod tests { data.target_state.best_finalized_self = data.target_state.best_self; // headers relay must only be started when we need new source headers at target node if data.source_to_target_header_required.is_some() { - assert!(data.target_state.best_finalized_peer_at_best_self.0 < data.source_state.best_self.0); + assert!( + data.target_state.best_finalized_peer_at_best_self.0 < + data.source_state.best_self.0 + ); data.source_to_target_header_required = None; } // syncing source headers -> target chain diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 8a5f8d7df260d..3433b683d7a77 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -13,18 +13,20 @@ //! Message delivery race delivers proof-of-messages from "lane.source" to "lane.target". -use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use crate::message_lane_loop::{ - MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, RelayerMode, - SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, - TargetClientState, +use crate::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane_loop::{ + MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, RelayerMode, + SourceClient as MessageLaneSourceClient, SourceClientState, + TargetClient as MessageLaneTargetClient, TargetClientState, + }, + message_race_loop::{ + MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, + TargetClient, TargetClientNonces, + }, + message_race_strategy::{BasicStrategy, SourceRangesQueue}, + metrics::MessageLaneLoopMetrics, }; -use crate::message_race_loop::{ - MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient, - TargetClientNonces, -}; -use crate::message_race_strategy::{BasicStrategy, SourceRangesQueue}; -use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; @@ -66,7 +68,8 @@ pub async fn run( MessageDeliveryStrategy:: { lane_source_client: source_client, lane_target_client: target_client, - max_unrewarded_relayer_entries_at_target: params.max_unrewarded_relayer_entries_at_target, + max_unrewarded_relayer_entries_at_target: params + .max_unrewarded_relayer_entries_at_target, max_unconfirmed_nonces_at_target: params.max_unconfirmed_nonces_at_target, max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, @@ -121,8 +124,10 @@ where at_block: SourceHeaderIdOf

, prev_latest_nonce: MessageNonce, ) -> Result<(SourceHeaderIdOf

, SourceClientNonces), Self::Error> { - let (at_block, latest_generated_nonce) = self.client.latest_generated_nonce(at_block).await?; - let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; + let (at_block, latest_generated_nonce) = + self.client.latest_generated_nonce(at_block).await?; + let (at_block, latest_confirmed_nonce) = + self.client.latest_confirmed_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { metrics_msg.update_source_latest_generated_nonce::

(latest_generated_nonce); @@ -131,7 +136,10 @@ where let new_nonces = if latest_generated_nonce > prev_latest_nonce { self.client - .generated_message_details(at_block.clone(), prev_latest_nonce + 1..=latest_generated_nonce) + .generated_message_details( + at_block.clone(), + prev_latest_nonce + 1..=latest_generated_nonce, + ) .await? } else { MessageDetailsMap::new() @@ -139,10 +147,7 @@ where Ok(( at_block, - SourceClientNonces { - new_nonces, - confirmed_nonce: Some(latest_confirmed_nonce), - }, + SourceClientNonces { new_nonces, confirmed_nonce: Some(latest_confirmed_nonce) }, )) } @@ -151,7 +156,8 @@ where at_block: SourceHeaderIdOf

, nonces: RangeInclusive, proof_parameters: Self::ProofParameters, - ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> { + ) -> Result<(SourceHeaderIdOf

, RangeInclusive, P::MessagesProof), Self::Error> + { self.client.prove_messages(at_block, nonces, proof_parameters).await } } @@ -180,10 +186,13 @@ where &self, at_block: TargetHeaderIdOf

, update_metrics: bool, - ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> { + ) -> Result<(TargetHeaderIdOf

, TargetClientNonces), Self::Error> + { let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; - let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; - let (at_block, unrewarded_relayers) = self.client.unrewarded_relayers_state(at_block).await?; + let (at_block, latest_confirmed_nonce) = + self.client.latest_confirmed_received_nonce(at_block).await?; + let (at_block, unrewarded_relayers) = + self.client.unrewarded_relayers_state(at_block).await?; if update_metrics { if let Some(metrics_msg) = self.metrics_msg.as_ref() { @@ -210,9 +219,7 @@ where nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result, Self::Error> { - self.client - .submit_messages_proof(generated_at_block, nonces, proof) - .await + self.client.submit_messages_proof(generated_at_block, nonces, proof).await } } @@ -245,7 +252,8 @@ struct MessageDeliveryStrategy { max_messages_size_in_single_batch: u32, /// Relayer operating mode. relayer_mode: RelayerMode, - /// Latest confirmed nonces at the source client + the header id where we have first met this nonce. + /// Latest confirmed nonces at the source client + the header id where we have first met this + /// nonce. latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, /// Target nonces from the source client. target_nonces: Option>, @@ -269,23 +277,11 @@ impl std::fmt::Debug for MessageDeliveryStrategy) -> Option> { - let header_required_for_messages_delivery = self.strategy.required_source_header_at_target(current_best); + fn required_source_header_at_target( + &self, + current_best: &SourceHeaderIdOf

, + ) -> Option> { + let header_required_for_messages_delivery = + self.strategy.required_source_header_at_target(current_best); let header_required_for_reward_confirmations_delivery = self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone()); match ( @@ -371,10 +371,7 @@ where self.target_nonces = Some(target_nonces); self.strategy.best_target_nonces_updated( - TargetClientNonces { - latest_nonce: nonces.latest_nonce, - nonces_data: (), - }, + TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () }, race_state, ) } @@ -399,14 +396,12 @@ where } if let Some(ref mut target_nonces) = self.target_nonces { - target_nonces.latest_nonce = std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); + target_nonces.latest_nonce = + std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); } self.strategy.finalized_target_nonces_updated( - TargetClientNonces { - latest_nonce: nonces.latest_nonce, - nonces_data: (), - }, + TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () }, race_state, ) } @@ -428,12 +423,15 @@ where // There's additional condition in the message delivery race: target would reject messages // if there are too much unconfirmed messages at the inbound lane. - // The receiving race is responsible to deliver confirmations back to the source chain. So if - // there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. + // The receiving race is responsible to deliver confirmations back to the source chain. So + // if there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. let latest_received_nonce_at_target = target_nonces.latest_nonce; - let confirmations_missing = latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); + let confirmations_missing = + latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); match confirmations_missing { - Some(confirmations_missing) if confirmations_missing >= self.max_unconfirmed_nonces_at_target => { + Some(confirmations_missing) + if confirmations_missing >= self.max_unconfirmed_nonces_at_target => + { log::debug!( target: "bridge", "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ @@ -445,50 +443,55 @@ where self.max_unconfirmed_nonces_at_target, ); - return None; + return None } _ => (), } - // Ok - we may have new nonces to deliver. But target may still reject new messages, because we haven't - // notified it that (some) messages have been confirmed. So we may want to include updated - // `source.latest_confirmed` in the proof. + // Ok - we may have new nonces to deliver. But target may still reject new messages, because + // we haven't notified it that (some) messages have been confirmed. So we may want to + // include updated `source.latest_confirmed` in the proof. // - // Important note: we're including outbound state lane proof whenever there are unconfirmed nonces - // on the target chain. Other strategy is to include it only if it's absolutely necessary. + // Important note: we're including outbound state lane proof whenever there are unconfirmed + // nonces on the target chain. Other strategy is to include it only if it's absolutely + // necessary. let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce; - let outbound_state_proof_required = latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; + let outbound_state_proof_required = + latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; // The target node would also reject messages if there are too many entries in the // "unrewarded relayers" set. If we are unable to prove new rewards to the target node, then // we should wait for confirmations race. let unrewarded_relayer_entries_limit_reached = - target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries - >= self.max_unrewarded_relayer_entries_at_target; + target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries >= + self.max_unrewarded_relayer_entries_at_target; if unrewarded_relayer_entries_limit_reached { // so there are already too many unrewarded relayer entries in the set // - // => check if we can prove enough rewards. If not, we should wait for more rewards to be paid + // => check if we can prove enough rewards. If not, we should wait for more rewards to + // be paid let number_of_rewards_being_proved = latest_confirmed_nonce_at_source.saturating_sub(latest_confirmed_nonce_at_target); - let enough_rewards_being_proved = number_of_rewards_being_proved - >= target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry; + let enough_rewards_being_proved = number_of_rewards_being_proved >= + target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry; if !enough_rewards_being_proved { - return None; + return None } } - // If we're here, then the confirmations race did its job && sending side now knows that messages - // have been delivered. Now let's select nonces that we want to deliver. + // If we're here, then the confirmations race did its job && sending side now knows that + // messages have been delivered. Now let's select nonces that we want to deliver. // // We may deliver at most: // - // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_target) + // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - + // latest_confirmed_nonce_at_target) // - // messages in the batch. But since we're including outbound state proof in the batch, then it - // may be increased to: + // messages in the batch. But since we're including outbound state proof in the batch, then + // it may be increased to: // - // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - latest_confirmed_nonce_at_source) + // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - + // latest_confirmed_nonce_at_source) let future_confirmed_nonce_at_target = if outbound_state_proof_required { latest_confirmed_nonce_at_source } else { @@ -505,7 +508,8 @@ where let lane_source_client = self.lane_source_client.clone(); let lane_target_client = self.lane_target_client.clone(); - let maximal_source_queue_index = self.strategy.maximal_available_source_queue_index(race_state)?; + let maximal_source_queue_index = + self.strategy.maximal_available_source_queue_index(race_state)?; let previous_total_dispatch_weight = self.total_queued_dispatch_weight(); let source_queue = self.strategy.source_queue(); let range_end = select_nonces_for_delivery_transaction( @@ -529,10 +533,7 @@ where Some(( selected_nonces, - MessageProofParameters { - outbound_state_proof_required, - dispatch_weight, - }, + MessageProofParameters { outbound_state_proof_required, dispatch_weight }, )) } } @@ -595,9 +596,9 @@ async fn select_nonces_for_delivery_transaction( // limit messages in the batch by weight let new_selected_weight = match selected_weight.checked_add(details.dispatch_weight) { - Some(new_selected_weight) if new_selected_weight <= max_messages_weight_in_single_batch => { - new_selected_weight - } + Some(new_selected_weight) + if new_selected_weight <= max_messages_weight_in_single_batch => + new_selected_weight, new_selected_weight if selected_count == 0 => { log::warn!( target: "bridge", @@ -607,13 +608,14 @@ async fn select_nonces_for_delivery_transaction( max_messages_weight_in_single_batch, ); new_selected_weight.unwrap_or(Weight::MAX) - } + }, _ => break, }; // limit messages in the batch by size let new_selected_size = match selected_size.checked_add(details.size) { - Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => new_selected_size, + Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => + new_selected_size, new_selected_size if selected_count == 0 => { log::warn!( target: "bridge", @@ -623,14 +625,14 @@ async fn select_nonces_for_delivery_transaction( max_messages_size_in_single_batch, ); new_selected_size.unwrap_or(u32::MAX) - } + }, _ => break, }; // limit number of messages in the batch let new_selected_count = selected_count + 1; if new_selected_count > max_messages_in_this_batch { - break; + break } // If dispatch fee has been paid at the source chain, it means that it is **relayer** who's @@ -639,13 +641,14 @@ async fn select_nonces_for_delivery_transaction( // If dispatch fee is paid at the target chain, it means that it'll be withdrawn from the // dispatch origin account AND reward is not covering this fee. // - // So in the latter case we're not adding the dispatch weight to the delivery transaction weight. + // So in the latter case we're not adding the dispatch weight to the delivery transaction + // weight. let mut new_selected_prepaid_nonces = selected_prepaid_nonces; let new_selected_unpaid_weight = match details.dispatch_fee_payment { DispatchFeePayment::AtSourceChain => { new_selected_prepaid_nonces += 1; selected_unpaid_weight.saturating_add(details.dispatch_weight) - } + }, DispatchFeePayment::AtTargetChain => selected_unpaid_weight, }; @@ -654,11 +657,12 @@ async fn select_nonces_for_delivery_transaction( match relayer_mode { RelayerMode::Altruistic => { soft_selected_count = index + 1; - } + }, RelayerMode::Rational => { let delivery_transaction_cost = lane_target_client .estimate_delivery_transaction_in_source_tokens( - hard_selected_begin_nonce..=(hard_selected_begin_nonce + index as MessageNonce), + hard_selected_begin_nonce..= + (hard_selected_begin_nonce + index as MessageNonce), new_selected_prepaid_nonces, new_selected_unpaid_weight, new_selected_size as u32, @@ -678,7 +682,8 @@ async fn select_nonces_for_delivery_transaction( let is_total_reward_less_than_cost = total_reward < total_cost; let prev_total_cost = total_cost; let prev_total_reward = total_reward; - total_confirmations_cost = total_confirmations_cost.saturating_add(&confirmation_transaction_cost); + total_confirmations_cost = + total_confirmations_cost.saturating_add(&confirmation_transaction_cost); total_reward = total_reward.saturating_add(&details.reward); total_cost = total_confirmations_cost.saturating_add(&delivery_transaction_cost); if !is_total_reward_less_than_cost && total_reward < total_cost { @@ -713,7 +718,7 @@ async fn select_nonces_for_delivery_transaction( selected_reward = total_reward; selected_cost = total_cost; } - } + }, } hard_selected_count = index + 1; @@ -725,9 +730,11 @@ async fn select_nonces_for_delivery_transaction( } if hard_selected_count != soft_selected_count { - let hard_selected_end_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; + let hard_selected_end_nonce = + hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; let soft_selected_begin_nonce = hard_selected_begin_nonce; - let soft_selected_end_nonce = soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; + let soft_selected_end_nonce = + soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; log::warn!( target: "bridge", "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy ({:?}) it has selected \ @@ -785,9 +792,9 @@ mod tests { use super::*; use crate::message_lane_loop::{ tests::{ - header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance, TestSourceClient, - TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, BASE_MESSAGE_DELIVERY_TRANSACTION_COST, - CONFIRMATION_TRANSACTION_COST, + header_id, TestMessageLane, TestMessagesProof, TestSourceChainBalance, + TestSourceClient, TestSourceHeaderId, TestTargetClient, TestTargetHeaderId, + BASE_MESSAGE_DELIVERY_TRANSACTION_COST, CONFIRMATION_TRANSACTION_COST, }, MessageDetails, }; @@ -795,13 +802,14 @@ mod tests { const DEFAULT_DISPATCH_WEIGHT: Weight = 1; const DEFAULT_SIZE: u32 = 1; - const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST - + BASE_MESSAGE_DELIVERY_TRANSACTION_COST - + DEFAULT_DISPATCH_WEIGHT - + (DEFAULT_SIZE as TestSourceChainBalance); + const DEFAULT_REWARD: TestSourceChainBalance = CONFIRMATION_TRANSACTION_COST + + BASE_MESSAGE_DELIVERY_TRANSACTION_COST + + DEFAULT_DISPATCH_WEIGHT + + (DEFAULT_SIZE as TestSourceChainBalance); type TestRaceState = RaceState; - type TestStrategy = MessageDeliveryStrategy; + type TestStrategy = + MessageDeliveryStrategy; fn source_nonces( new_nonces: RangeInclusive, @@ -863,14 +871,12 @@ mod tests { strategy: BasicStrategy::new(), }; - race_strategy - .strategy - .source_nonces_updated(header_id(1), source_nonces(20..=23, 19, DEFAULT_REWARD, AtSourceChain)); + race_strategy.strategy.source_nonces_updated( + header_id(1), + source_nonces(20..=23, 19, DEFAULT_REWARD, AtSourceChain), + ); - let target_nonces = TargetClientNonces { - latest_nonce: 19, - nonces_data: (), - }; + let target_nonces = TargetClientNonces { latest_nonce: 19, nonces_data: () }; race_strategy .strategy .best_target_nonces_updated(target_nonces.clone(), &mut race_state); @@ -890,7 +896,9 @@ mod tests { #[test] fn weights_map_works_as_nonces_range() { - fn build_map(range: RangeInclusive) -> MessageDetailsMap { + fn build_map( + range: RangeInclusive, + ) -> MessageDetailsMap { range .map(|idx| { ( @@ -937,7 +945,8 @@ mod tests { // we need to wait until confirmations will be delivered by receiving race strategy.latest_confirmed_nonces_at_source = vec![( header_id(1), - strategy.target_nonces.as_ref().unwrap().latest_nonce - strategy.max_unconfirmed_nonces_at_target, + strategy.target_nonces.as_ref().unwrap().latest_nonce - + strategy.max_unconfirmed_nonces_at_target, )] .into_iter() .collect(); @@ -945,13 +954,16 @@ mod tests { } #[async_std::test] - async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() { + async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() + { let (state, mut strategy) = prepare_strategy(); // if there are new confirmed nonces on source, we want to relay this information // to target to prune rewards queue - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + let prev_confirmed_nonce_at_source = + strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = + prev_confirmed_nonce_at_source - 1; assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=23), proof_parameters(true, 4))) @@ -965,8 +977,10 @@ mod tests { // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, // we need to wait until rewards will be paid { - let mut unrewarded_relayers = &mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers; - unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; + let mut unrewarded_relayers = + &mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers; + unrewarded_relayers.unrewarded_relayer_entries = + strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 4; } assert_eq!(strategy.select_nonces_to_deliver(state).await, None); @@ -979,12 +993,14 @@ mod tests { // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, // we need to prove at least `messages_in_oldest_entry` rewards - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + let prev_confirmed_nonce_at_source = + strategy.latest_confirmed_nonces_at_source.back().unwrap().1; { let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; - unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; + unrewarded_relayers.unrewarded_relayer_entries = + strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 4; } assert_eq!(strategy.select_nonces_to_deliver(state).await, None); @@ -996,12 +1012,14 @@ mod tests { // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, // we need to prove at least `messages_in_oldest_entry` rewards - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + let prev_confirmed_nonce_at_source = + strategy.latest_confirmed_nonces_at_source.back().unwrap().1; { let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 3; let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; - unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; + unrewarded_relayers.unrewarded_relayer_entries = + strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 3; } assert_eq!( @@ -1023,15 +1041,13 @@ mod tests { } #[async_std::test] - async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight() { + async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_weight( + ) { let (state, mut strategy) = prepare_strategy(); - // first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4) - strategy.strategy.source_queue_mut()[0] - .1 - .get_mut(&20) - .unwrap() - .dispatch_weight = 10; + // first message doesn't fit in the batch, because it has weight (10) that overflows max + // weight (4) + strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().dispatch_weight = 10; assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=20), proof_parameters(false, 10))) @@ -1051,10 +1067,12 @@ mod tests { } #[async_std::test] - async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size() { + async fn message_delivery_strategy_accepts_single_message_even_if_its_weight_overflows_maximal_size( + ) { let (state, mut strategy) = prepare_strategy(); - // first message doesn't fit in the batch, because it has weight (10) that overflows max weight (4) + // first message doesn't fit in the batch, because it has weight (10) that overflows max + // weight (4) strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().size = 10; assert_eq!( strategy.select_nonces_to_deliver(state).await, @@ -1066,7 +1084,8 @@ mod tests { async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_is_upper_limit() { let (state, mut strategy) = prepare_strategy(); - // not all queued messages may fit in the batch, because batch has max number of messages limit + // not all queued messages may fit in the batch, because batch has max number of messages + // limit strategy.max_messages_in_single_batch = 3; assert_eq!( strategy.select_nonces_to_deliver(state).await, @@ -1075,16 +1094,18 @@ mod tests { } #[async_std::test] - async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces() { + async fn message_delivery_strategy_limits_batch_by_messages_count_when_there_are_unconfirmed_nonces( + ) { let (state, mut strategy) = prepare_strategy(); // 1 delivery confirmation from target to source is still missing, so we may only // relay 3 new messages - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; - strategy.latest_confirmed_nonces_at_source = vec![(header_id(1), prev_confirmed_nonce_at_source - 1)] - .into_iter() - .collect(); - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + let prev_confirmed_nonce_at_source = + strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + strategy.latest_confirmed_nonces_at_source = + vec![(header_id(1), prev_confirmed_nonce_at_source - 1)].into_iter().collect(); + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = + prev_confirmed_nonce_at_source - 1; assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) @@ -1099,30 +1120,35 @@ mod tests { // // => so we can't deliver more than 3 messages let (mut state, mut strategy) = prepare_strategy(); - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + let prev_confirmed_nonce_at_source = + strategy.latest_confirmed_nonces_at_source.back().unwrap().1; strategy.latest_confirmed_nonces_at_source = vec![ (header_id(1), prev_confirmed_nonce_at_source - 1), (header_id(2), prev_confirmed_nonce_at_source), ] .into_iter() .collect(); - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = + prev_confirmed_nonce_at_source - 1; state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) ); - // the same situation, but the header 2 is known to the target node, so we may deliver reward confirmation + // the same situation, but the header 2 is known to the target node, so we may deliver + // reward confirmation let (mut state, mut strategy) = prepare_strategy(); - let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; + let prev_confirmed_nonce_at_source = + strategy.latest_confirmed_nonces_at_source.back().unwrap().1; strategy.latest_confirmed_nonces_at_source = vec![ (header_id(1), prev_confirmed_nonce_at_source - 1), (header_id(2), prev_confirmed_nonce_at_source), ] .into_iter() .collect(); - strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; + strategy.target_nonces.as_mut().unwrap().nonces_data.confirmed_nonce = + prev_confirmed_nonce_at_source - 1; state.best_finalized_source_header_id_at_source = Some(header_id(2)); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); assert_eq!( @@ -1136,8 +1162,9 @@ mod tests { // let's prepare situation when: // - all messages [20; 23] have been generated at source block#1; let (mut state, mut strategy) = prepare_strategy(); - // - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because of unrewarded - // relayers vector capacity; + // + // - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because + // of unrewarded relayers vector capacity; strategy.max_unconfirmed_nonces_at_target = 2; assert_eq!( strategy.select_nonces_to_deliver(state.clone()).await, @@ -1158,19 +1185,15 @@ mod tests { &mut state, ); assert_eq!(strategy.select_nonces_to_deliver(state).await, None); + // // - messages [1; 10] receiving confirmation has been delivered at source block#2; strategy.source_nonces_updated( header_id(2), - SourceClientNonces { - new_nonces: MessageDetailsMap::new(), - confirmed_nonce: Some(21), - }, + SourceClientNonces { new_nonces: MessageDetailsMap::new(), confirmed_nonce: Some(21) }, ); + // // - so now we'll need to relay source block#11 to be able to accept messages [11; 20]. - assert_eq!( - strategy.required_source_header_at_target(&header_id(1)), - Some(header_id(2)) - ); + assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2))); } #[async_std::test] @@ -1233,8 +1256,8 @@ mod tests { // so now we have: // - 20..=23 with reward = cost - // - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT` from the - // cost, so it should be fine; + // - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT` + // from the cost, so it should be fine; // => when MSG#24 fee is paid at the target chain, strategy shall select all 20..=24 // => when MSG#25 fee is paid at the source chain, strategy shall only select 20..=23 strategy.select_nonces_to_deliver(state).await @@ -1255,11 +1278,11 @@ mod tests { // Real scenario that has happened on test deployments: // 1) relayer witnessed M1 at block 1 => it has separate entry in the `source_queue` // 2) relayer witnessed M2 at block 2 => it has separate entry in the `source_queue` - // 3) if block 2 is known to the target node, then both M1 and M2 are selected for single delivery, - // even though weight(M1+M2) > larger than largest allowed weight + // 3) if block 2 is known to the target node, then both M1 and M2 are selected for single + // delivery, even though weight(M1+M2) > larger than largest allowed weight // - // This was happening because selector (`select_nonces_for_delivery_transaction`) has been called - // for every `source_queue` entry separately without preserving any context. + // This was happening because selector (`select_nonces_for_delivery_transaction`) has been + // called for every `source_queue` entry separately without preserving any context. let (mut state, mut strategy) = prepare_strategy(); let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, AtSourceChain); strategy.strategy.source_nonces_updated(header_id(2), nonces); diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 399f871980497..a7254f70ee4a4 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -54,10 +54,12 @@ pub trait MessageRace { } /// State of race source client. -type SourceClientState

= ClientState<

::SourceHeaderId,

::TargetHeaderId>; +type SourceClientState

= + ClientState<

::SourceHeaderId,

::TargetHeaderId>; /// State of race target client. -type TargetClientState

= ClientState<

::TargetHeaderId,

::SourceHeaderId>; +type TargetClientState

= + ClientState<

::TargetHeaderId,

::SourceHeaderId>; /// Inclusive nonces range. pub trait NoncesRange: Debug + Sized { @@ -155,7 +157,10 @@ pub trait RaceStrategy: Debug { /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; /// Return id of source header that is required to be on target to continue synchronization. - fn required_source_header_at_target(&self, current_best: &SourceHeaderId) -> Option; + fn required_source_header_at_target( + &self, + current_best: &SourceHeaderId, + ) -> Option; /// Return the best nonce at source node. /// /// `Some` is returned only if we are sure that the value is greater or equal @@ -167,7 +172,11 @@ pub trait RaceStrategy: Debug { fn best_at_target(&self) -> Option; /// Called when nonces are updated at source node of the race. - fn source_nonces_updated(&mut self, at_block: SourceHeaderId, nonces: SourceClientNonces); + fn source_nonces_updated( + &mut self, + at_block: SourceHeaderId, + nonces: SourceClientNonces, + ); /// Called when best nonces are updated at target node of the race. fn best_target_nonces_updated( &mut self, @@ -430,8 +439,10 @@ pub async fn run, TC: TargetClient

>( strategy, ); - return Err(FailedClient::Both); - } else if race_state.nonces_to_submit.is_none() && race_state.nonces_submitted.is_none() && strategy.is_empty() + return Err(FailedClient::Both) + } else if race_state.nonces_to_submit.is_none() && + race_state.nonces_submitted.is_none() && + strategy.is_empty() { stall_countdown = Instant::now(); } @@ -439,7 +450,8 @@ pub async fn run, TC: TargetClient

>( if source_client_is_online { source_client_is_online = false; - let nonces_to_deliver = select_nonces_to_deliver(race_state.clone(), &mut strategy).await; + let nonces_to_deliver = + select_nonces_to_deliver(race_state.clone(), &mut strategy).await; let best_at_source = strategy.best_at_source(); if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { @@ -451,9 +463,7 @@ pub async fn run, TC: TargetClient

>( at_block, ); source_generate_proof.set( - race_source - .generate_proof(at_block, nonces_range, proof_parameters) - .fuse(), + race_source.generate_proof(at_block, nonces_range, proof_parameters).fuse(), ); } else if source_nonces_required && best_at_source.is_some() { log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); @@ -516,7 +526,9 @@ pub async fn run, TC: TargetClient

>( } } -impl Default for RaceState { +impl Default + for RaceState +{ fn default() -> Self { RaceState { best_finalized_source_header_id_at_source: None, @@ -539,7 +551,7 @@ where let need_update = now_time.saturating_duration_since(prev_time) > Duration::from_secs(10); if !need_update { - return prev_time; + return prev_time } let now_best_nonce_at_source = strategy.best_at_source(); @@ -569,11 +581,7 @@ where .select_nonces_to_deliver(race_state) .await .map(|(nonces_range, proof_parameters)| { - ( - best_finalized_source_header_id_at_best_target, - nonces_range, - proof_parameters, - ) + (best_finalized_source_header_id_at_best_target, nonces_range, proof_parameters) }) } @@ -592,8 +600,14 @@ mod tests { // target node only knows about source' BEST_AT_TARGET block // source node has BEST_AT_SOURCE > BEST_AT_TARGET block let mut race_state = RaceState::<_, _, ()> { - best_finalized_source_header_id_at_source: Some(HeaderId(BEST_AT_SOURCE, BEST_AT_SOURCE)), - best_finalized_source_header_id_at_best_target: Some(HeaderId(BEST_AT_TARGET, BEST_AT_TARGET)), + best_finalized_source_header_id_at_source: Some(HeaderId( + BEST_AT_SOURCE, + BEST_AT_SOURCE, + )), + best_finalized_source_header_id_at_best_target: Some(HeaderId( + BEST_AT_TARGET, + BEST_AT_TARGET, + )), best_target_header_id: Some(HeaderId(0, 0)), best_finalized_target_header_id: Some(HeaderId(0, 0)), nonces_to_submit: None, @@ -604,16 +618,10 @@ mod tests { let mut strategy = BasicStrategy::new(); strategy.source_nonces_updated( HeaderId(GENERATED_AT, GENERATED_AT), - SourceClientNonces { - new_nonces: 0..=10, - confirmed_nonce: None, - }, + SourceClientNonces { new_nonces: 0..=10, confirmed_nonce: None }, ); strategy.best_target_nonces_updated( - TargetClientNonces { - latest_nonce: 5u64, - nonces_data: (), - }, + TargetClientNonces { latest_nonce: 5u64, nonces_data: () }, &mut race_state, ); diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index f9ac61352fbd1..5aa36cbd9c6dc 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -13,16 +13,19 @@ //! Message receiving race delivers proof-of-messages-delivery from "lane.target" to "lane.source". -use crate::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use crate::message_lane_loop::{ - SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, - TargetClientState, +use crate::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_lane_loop::{ + SourceClient as MessageLaneSourceClient, SourceClientState, + TargetClient as MessageLaneTargetClient, TargetClientState, + }, + message_race_loop::{ + MessageRace, NoncesRange, SourceClient, SourceClientNonces, TargetClient, + TargetClientNonces, + }, + message_race_strategy::BasicStrategy, + metrics::MessageLaneLoopMetrics, }; -use crate::message_race_loop::{ - MessageRace, NoncesRange, SourceClient, SourceClientNonces, TargetClient, TargetClientNonces, -}; -use crate::message_race_strategy::BasicStrategy; -use crate::metrics::MessageLaneLoopMetrics; use async_trait::async_trait; use bp_messages::MessageNonce; @@ -129,11 +132,7 @@ where nonces: RangeInclusive, _proof_parameters: Self::ProofParameters, ) -> Result< - ( - TargetHeaderIdOf

, - RangeInclusive, - P::MessagesReceivingProof, - ), + (TargetHeaderIdOf

, RangeInclusive, P::MessagesReceivingProof), Self::Error, > { self.client @@ -168,19 +167,14 @@ where at_block: SourceHeaderIdOf

, update_metrics: bool, ) -> Result<(SourceHeaderIdOf

, TargetClientNonces<()>), Self::Error> { - let (at_block, latest_confirmed_nonce) = self.client.latest_confirmed_received_nonce(at_block).await?; + let (at_block, latest_confirmed_nonce) = + self.client.latest_confirmed_received_nonce(at_block).await?; if update_metrics { if let Some(metrics_msg) = self.metrics_msg.as_ref() { metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); } } - Ok(( - at_block, - TargetClientNonces { - latest_nonce: latest_confirmed_nonce, - nonces_data: (), - }, - )) + Ok((at_block, TargetClientNonces { latest_nonce: latest_confirmed_nonce, nonces_data: () })) } async fn submit_proof( @@ -189,9 +183,7 @@ where nonces: RangeInclusive, proof: P::MessagesReceivingProof, ) -> Result, Self::Error> { - self.client - .submit_messages_receiving_proof(generated_at_block, proof) - .await?; + self.client.submit_messages_receiving_proof(generated_at_block, proof).await?; Ok(nonces) } } diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index bc04ad5bcd9bc..9b9091b979f66 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -17,7 +17,9 @@ //! 2) new nonces may be proved to target node (i.e. they have appeared at the //! block, which is known to the target node). -use crate::message_race_loop::{NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces}; +use crate::message_race_loop::{ + NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces, +}; use async_trait::async_trait; use bp_messages::MessageNonce; @@ -40,15 +42,29 @@ pub struct BasicStrategy< > { /// All queued nonces. source_queue: SourceRangesQueue, - /// The best nonce known to target node (at its best block). `None` if it has not been received yet. + /// The best nonce known to target node (at its best block). `None` if it has not been received + /// yet. best_target_nonce: Option, /// Unused generic types dump. _phantom: PhantomData<(TargetHeaderNumber, TargetHeaderHash, Proof)>, } -impl - BasicStrategy -where +impl< + SourceHeaderNumber, + SourceHeaderHash, + TargetHeaderNumber, + TargetHeaderHash, + SourceNoncesRange, + Proof, + > + BasicStrategy< + SourceHeaderNumber, + SourceHeaderHash, + TargetHeaderNumber, + TargetHeaderHash, + SourceNoncesRange, + Proof, + > where SourceHeaderHash: Clone, SourceHeaderNumber: Clone + Ord, SourceNoncesRange: NoncesRange, @@ -79,9 +95,9 @@ where /// Returns index of the latest source queue entry, that may be delivered to the target node. /// - /// Returns `None` if no entries may be delivered. All entries before and including the `Some(_)` - /// index are guaranteed to be witnessed at source blocks that are known to be finalized at the - /// target node. + /// Returns `None` if no entries may be delivered. All entries before and including the + /// `Some(_)` index are guaranteed to be witnessed at source blocks that are known to be + /// finalized at the target node. pub fn maximal_available_source_queue_index( &self, race_state: RaceState< @@ -95,12 +111,12 @@ where // if we have already selected nonces that we want to submit, do nothing if race_state.nonces_to_submit.is_some() { - return None; + return None } // if we already submitted some nonces, do nothing if race_state.nonces_submitted.is_some() { - return None; + return None } // 1) we want to deliver all nonces, starting from `target_nonce + 1` @@ -124,17 +140,34 @@ where while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { if let Some(range_to_requeue) = queued_range.greater_than(nonce) { self.source_queue.push_front((queued_at, range_to_requeue)); - break; + break } } } } #[async_trait] -impl - RaceStrategy, HeaderId, Proof> - for BasicStrategy -where +impl< + SourceHeaderNumber, + SourceHeaderHash, + TargetHeaderNumber, + TargetHeaderHash, + SourceNoncesRange, + Proof, + > + RaceStrategy< + HeaderId, + HeaderId, + Proof, + > + for BasicStrategy< + SourceHeaderNumber, + SourceHeaderHash, + TargetHeaderNumber, + TargetHeaderHash, + SourceNoncesRange, + Proof, + > where SourceHeaderHash: Clone + Debug + Send, SourceHeaderNumber: Clone + Ord + Debug + Send, SourceNoncesRange: NoncesRange + Debug + Send, @@ -162,7 +195,8 @@ where fn best_at_source(&self) -> Option { let best_in_queue = self.source_queue.back().map(|(_, range)| range.end()); match (best_in_queue, self.best_target_nonce) { - (Some(best_in_queue), Some(best_target_nonce)) if best_in_queue > best_target_nonce => Some(best_in_queue), + (Some(best_in_queue), Some(best_target_nonce)) if best_in_queue > best_target_nonce => + Some(best_in_queue), (_, Some(best_target_nonce)) => Some(best_target_nonce), (_, None) => None, } @@ -205,18 +239,17 @@ where if let Some(best_target_nonce) = self.best_target_nonce { if nonce < best_target_nonce { - return; + return } } while let Some(true) = self.source_queue.front().map(|(_, range)| range.begin() <= nonce) { - let maybe_subrange = self - .source_queue - .pop_front() - .and_then(|(at_block, range)| range.greater_than(nonce).map(|subrange| (at_block, subrange))); + let maybe_subrange = self.source_queue.pop_front().and_then(|(at_block, range)| { + range.greater_than(nonce).map(|subrange| (at_block, subrange)) + }); if let Some((at_block, subrange)) = maybe_subrange { self.source_queue.push_front((at_block, subrange)); - break; + break } } @@ -238,10 +271,8 @@ where race_state.nonces_submitted = None; } - self.best_target_nonce = Some(std::cmp::max( - self.best_target_nonce.unwrap_or(nonces.latest_nonce), - nonce, - )); + self.best_target_nonce = + Some(std::cmp::max(self.best_target_nonce.unwrap_or(nonces.latest_nonce), nonce)); } fn finalized_target_nonces_updated( @@ -278,9 +309,12 @@ where #[cfg(test)] mod tests { use super::*; - use crate::message_lane::MessageLane; - use crate::message_lane_loop::tests::{ - header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, TestSourceHeaderNumber, + use crate::{ + message_lane::MessageLane, + message_lane_loop::tests::{ + header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, + TestSourceHeaderNumber, + }, }; type SourceNoncesRange = RangeInclusive; @@ -295,17 +329,11 @@ mod tests { >; fn source_nonces(new_nonces: SourceNoncesRange) -> SourceClientNonces { - SourceClientNonces { - new_nonces, - confirmed_nonce: None, - } + SourceClientNonces { new_nonces, confirmed_nonce: None } } fn target_nonces(latest_nonce: MessageNonce) -> TargetClientNonces<()> { - TargetClientNonces { - latest_nonce, - nonces_data: (), - } + TargetClientNonces { latest_nonce, nonces_data: () } } #[test] @@ -420,18 +448,12 @@ mod tests { strategy.source_nonces_updated(header_id(5), source_nonces(7..=8)); state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); - assert_eq!( - strategy.select_nonces_to_deliver(state.clone()).await, - Some((1..=6, ())) - ); + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((1..=6, ()))); strategy.best_target_nonces_updated(target_nonces(6), &mut state); assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); state.best_finalized_source_header_id_at_best_target = Some(header_id(5)); - assert_eq!( - strategy.select_nonces_to_deliver(state.clone()).await, - Some((7..=8, ())) - ); + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((7..=8, ()))); strategy.best_target_nonces_updated(target_nonces(8), &mut state); assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); } @@ -471,16 +493,17 @@ mod tests { strategy.source_nonces_updated(header_id(3), source_nonces(7..=9)); fn source_queue_nonces( - source_queue: &SourceRangesQueue, + source_queue: &SourceRangesQueue< + TestSourceHeaderHash, + TestSourceHeaderNumber, + SourceNoncesRange, + >, ) -> Vec { source_queue.iter().flat_map(|(_, range)| range.clone()).collect() } strategy.remove_le_nonces_from_source_queue(1); - assert_eq!( - source_queue_nonces(&strategy.source_queue), - vec![2, 3, 4, 5, 6, 7, 8, 9], - ); + assert_eq!(source_queue_nonces(&strategy.source_queue), vec![2, 3, 4, 5, 6, 7, 8, 9],); strategy.remove_le_nonces_from_source_queue(5); assert_eq!(source_queue_nonces(&strategy.source_queue), vec![6, 7, 8, 9],); diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 8f115170523b4..8d6e480722e66 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -16,8 +16,10 @@ //! Metrics for message lane relay loop. -use crate::message_lane::MessageLane; -use crate::message_lane_loop::{SourceClientState, TargetClientState}; +use crate::{ + message_lane::MessageLane, + message_lane_loop::{SourceClientState, TargetClientState}, +}; use bp_messages::MessageNonce; use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; @@ -81,28 +83,40 @@ impl MessageLaneLoopMetrics { } /// Update latest generated nonce at source. - pub fn update_source_latest_generated_nonce(&self, source_latest_generated_nonce: MessageNonce) { + pub fn update_source_latest_generated_nonce( + &self, + source_latest_generated_nonce: MessageNonce, + ) { self.lane_state_nonces .with_label_values(&["source_latest_generated"]) .set(source_latest_generated_nonce); } /// Update the latest confirmed nonce at source. - pub fn update_source_latest_confirmed_nonce(&self, source_latest_confirmed_nonce: MessageNonce) { + pub fn update_source_latest_confirmed_nonce( + &self, + source_latest_confirmed_nonce: MessageNonce, + ) { self.lane_state_nonces .with_label_values(&["source_latest_confirmed"]) .set(source_latest_confirmed_nonce); } /// Update the latest received nonce at target. - pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: MessageNonce) { + pub fn update_target_latest_received_nonce( + &self, + target_latest_generated_nonce: MessageNonce, + ) { self.lane_state_nonces .with_label_values(&["target_latest_received"]) .set(target_latest_generated_nonce); } /// Update the latest confirmed nonce at target. - pub fn update_target_latest_confirmed_nonce(&self, target_latest_confirmed_nonce: MessageNonce) { + pub fn update_target_latest_confirmed_nonce( + &self, + target_latest_confirmed_nonce: MessageNonce, + ) { self.lane_state_nonces .with_label_values(&["target_latest_confirmed"]) .set(target_latest_confirmed_nonce); diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index b87937923bd4e..8c13a4d61cb3a 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -62,14 +62,7 @@ pub fn initialize_logger(with_timestamp: bool) { let log_level = color_level(record.level()); let log_target = color_target(record.target()); - writeln!( - buf, - "{}{} {} {}", - loop_name_prefix(), - log_level, - log_target, - record.args(), - ) + writeln!(buf, "{}{} {} {}", loop_name_prefix(), log_level, log_target, record.args(),) }); } @@ -81,12 +74,14 @@ pub(crate) fn initialize_loop(loop_name: String) { LOOP_NAME.with(|g_loop_name| *g_loop_name.borrow_mut() = loop_name); } -/// Returns loop name prefix to use in logs. The prefix is initialized with the `initialize_loop` call. +/// Returns loop name prefix to use in logs. The prefix is initialized with the `initialize_loop` +/// call. fn loop_name_prefix() -> String { // try_with to avoid panic outside of async-std task context LOOP_NAME .try_with(|loop_name| { - // using borrow is ok here, because loop is only initialized once (=> borrow_mut will only be called once) + // using borrow is ok here, because loop is only initialized once (=> borrow_mut will + // only be called once) let loop_name = loop_name.borrow(); if loop_name.is_empty() { String::new() diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 446e00cd23e67..deec1d688a7de 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -168,12 +168,12 @@ pub fn format_ids(mut ids: impl ExactSizeIterator { let id0 = ids.next().expect(NTH_PROOF); let id_last = ids.last().expect(NTH_PROOF); format!("{}:[{:?} ... {:?}]", len, id0, id_last) - } + }, } } @@ -220,7 +220,10 @@ impl ProcessFutureResult { /// Returns Ok(true) if future has succeeded. /// Returns Ok(false) if future has failed with non-connection error. /// Returns Err if future is `ConnectionFailed`. - pub fn fail_if_connection_error(self, failed_client: FailedClient) -> Result { + pub fn fail_if_connection_error( + self, + failed_client: FailedClient, + ) -> Result { match self { ProcessFutureResult::Success => Ok(true), ProcessFutureResult::Failed => Ok(false), @@ -247,7 +250,7 @@ where on_success(result); retry_backoff.reset(); ProcessFutureResult::Success - } + }, Err(error) if error.is_connection_error() => { log::error!( target: "bridge", @@ -259,7 +262,7 @@ where retry_backoff.reset(); go_offline_future.set(go_offline(CONNECTION_ERROR_DELAY).fuse()); ProcessFutureResult::ConnectionFailed - } + }, Err(error) => { let retry_delay = retry_backoff.next_backoff().unwrap_or(CONNECTION_ERROR_DELAY); log::error!( @@ -272,6 +275,6 @@ where go_offline_future.set(go_offline(retry_delay).fuse()); ProcessFutureResult::Failed - } + }, } } diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 4855dba8ea246..5c796071c6d5b 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -82,21 +82,14 @@ pub trait StandaloneMetrics: Metrics { impl Default for MetricsAddress { fn default() -> Self { - MetricsAddress { - host: "127.0.0.1".into(), - port: 9616, - } + MetricsAddress { host: "127.0.0.1".into(), port: 9616 } } } impl MetricsParams { /// Creates metrics params so that metrics are not exposed. pub fn disabled() -> Self { - MetricsParams { - address: None, - registry: None, - metrics_prefix: None, - } + MetricsParams { address: None, registry: None, metrics_prefix: None } } /// Do not expose metrics. @@ -114,11 +107,7 @@ impl MetricsParams { impl From> for MetricsParams { fn from(address: Option) -> Self { - MetricsParams { - address, - registry: None, - metrics_prefix: None, - } + MetricsParams { address, registry: None, metrics_prefix: None } } } @@ -134,7 +123,10 @@ pub fn metric_name(prefix: Option<&str>, name: &str) -> String { /// Set value of gauge metric. /// /// If value is `Ok(None)` or `Err(_)`, metric would have default value. -pub fn set_gauge_value, E: Debug>(gauge: &Gauge, value: Result, E>) { +pub fn set_gauge_value, E: Debug>( + gauge: &Gauge, + value: Result, E>, +) { gauge.set(match value { Ok(Some(value)) => { log::trace!( @@ -144,7 +136,7 @@ pub fn set_gauge_value, E: Debug>(gauge: &G value, ); value - } + }, Ok(None) => { log::warn!( target: "bridge-metrics", @@ -152,7 +144,7 @@ pub fn set_gauge_value, E: Debug>(gauge: &G gauge.desc().first().map(|d| &d.fq_name), ); Default::default() - } + }, Err(error) => { log::warn!( target: "bridge-metrics", @@ -161,6 +153,6 @@ pub fn set_gauge_value, E: Debug>(gauge: &G error, ); Default::default() - } + }, }) } diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index c610ac04dc97d..a57cc5a77f579 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; +use crate::metrics::{ + metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64, +}; use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; @@ -100,18 +102,12 @@ impl StandaloneMetrics for FloatJsonValueMetric { /// Parse HTTP service response. fn parse_service_response(json_path: &str, response: &str) -> Result { let json = serde_json::from_str(response).map_err(|err| { - format!( - "Failed to parse HTTP service response: {:?}. Response: {:?}", - err, response, - ) + format!("Failed to parse HTTP service response: {:?}. Response: {:?}", err, response,) })?; let mut selector = jsonpath_lib::selector(&json); let maybe_selected_value = selector(json_path).map_err(|err| { - format!( - "Failed to select value from response: {:?}. Response: {:?}", - err, response, - ) + format!("Failed to select value from response: {:?}. Response: {:?}", err, response,) })?; let selected_value = maybe_selected_value .first() @@ -121,7 +117,7 @@ fn parse_service_response(json_path: &str, response: &str) -> Result { log::warn!( target: "bridge-metrics", "Failed to refresh process information. Metrics may show obsolete values", ); - } + }, } } diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index ef8ebf4e8a28d..49047a8810d6f 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{Metrics, MetricsAddress, MetricsParams, PrometheusError, StandaloneMetrics}; -use crate::{FailedClient, MaybeConnectionError}; +use crate::{ + metrics::{Metrics, MetricsAddress, MetricsParams, PrometheusError, StandaloneMetrics}, + FailedClient, MaybeConnectionError, +}; use async_trait::async_trait; use std::{fmt::Debug, future::Future, net::SocketAddr, time::Duration}; @@ -45,15 +47,11 @@ impl Client for () { /// Returns generic loop that may be customized and started. pub fn relay_loop(source_client: SC, target_client: TC) -> Loop { - Loop { - reconnect_delay: RECONNECT_DELAY, - source_client, - target_client, - loop_metric: None, - } + Loop { reconnect_delay: RECONNECT_DELAY, source_client, target_client, loop_metric: None } } -/// Returns generic relay loop metrics that may be customized and used in one or several relay loops. +/// Returns generic relay loop metrics that may be customized and used in one or several relay +/// loops. pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetrics<(), (), ()> { LoopMetrics { relay_loop: Loop { @@ -94,7 +92,11 @@ impl Loop { } /// Start building loop metrics using given prefix. - pub fn with_metrics(self, prefix: Option, params: MetricsParams) -> LoopMetrics { + pub fn with_metrics( + self, + prefix: Option, + params: MetricsParams, + ) -> LoopMetrics { LoopMetrics { relay_loop: Loop { reconnect_delay: self.reconnect_delay, @@ -111,8 +113,8 @@ impl Loop { /// Run relay loop. /// - /// This function represents an outer loop, which in turn calls provided `run_loop` function to do - /// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, + /// This function represents an outer loop, which in turn calls provided `run_loop` function to + /// do actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, /// target or both) and calls `run_loop` again. pub async fn run(mut self, loop_name: String, run_loop: R) -> anyhow::Result<()> where @@ -127,20 +129,20 @@ impl Loop { loop { let loop_metric = self.loop_metric.clone(); - let future_result = run_loop(self.source_client.clone(), self.target_client.clone(), loop_metric); + let future_result = + run_loop(self.source_client.clone(), self.target_client.clone(), loop_metric); let result = future_result.await; match result { Ok(()) => break, - Err(failed_client) => { + Err(failed_client) => reconnect_failed_client( failed_client, self.reconnect_delay, &mut self.source_client, &mut self.target_client, ) - .await - } + .await, } log::debug!(target: "bridge", "Restarting relay loop"); @@ -177,8 +179,8 @@ impl LoopMetrics { self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, ) -> anyhow::Result { - // since standalone metrics are updating themselves, we may just ignore the fact that the same - // standalone metric is exposed by several loops && only spawn single metric + // since standalone metrics are updating themselves, we may just ignore the fact that the + // same standalone metric is exposed by several loops && only spawn single metric match create_metric(&self.registry, self.metrics_prefix.as_deref()) { Ok(standalone_metrics) => standalone_metrics.spawn(), Err(PrometheusError::AlreadyReg) => (), @@ -252,8 +254,8 @@ pub async fn reconnect_failed_client( reconnect_delay.as_secs(), error, ); - continue; - } + continue + }, } } if failed_client == FailedClient::Both || failed_client == FailedClient::Target { @@ -266,12 +268,12 @@ pub async fn reconnect_failed_client( reconnect_delay.as_secs(), error, ); - continue; - } + continue + }, } } - break; + break } } @@ -280,8 +282,9 @@ fn create_metrics_registry(prefix: Option) -> Registry { match prefix { Some(prefix) => { assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); - Registry::new_custom(Some(prefix), None).expect("only fails if prefix is empty; prefix is not empty; qed") - } + Registry::new_custom(Some(prefix), None) + .expect("only fails if prefix is empty; prefix is not empty; qed") + }, None => Registry::new(), } } From 7da700d7bbdeceb4ff6278a4beb8174bf5d620f2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 24 Sep 2021 17:47:57 +0300 Subject: [PATCH 0577/1210] fix clippy warning (#1163) --- .../bin-substrate/src/chains/kusama_headers_to_polkadot.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index 1e3cd2ec7d889..ea362bd202b1d 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -150,10 +150,7 @@ pub(crate) mod tests { // adjusted fee let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2; let single_source_header_tx_cost = W::calc(&single_source_header_submit_tx_weight); - let maximal_expected_decrease = - single_source_header_tx_cost * B::from(expected_source_headers_per_day); - - maximal_expected_decrease + single_source_header_tx_cost * B::from(expected_source_headers_per_day) } #[test] From 04ef2a882310ccadc60fbee053fef09734fea573 Mon Sep 17 00:00:00 2001 From: bear <2630582710@qq.com> Date: Mon, 27 Sep 2021 15:45:12 +0800 Subject: [PATCH 0578/1210] Move calculation relayer reward into `MessageDeliveryAndDispatchPayment` (#1153) * Refactor logic * Thanks svyatonik help, it compile * Fix failed unit test * Remove compile warning * Rename * Return result in pay_relayers_rewards * Fix runtime compile issue * Use MessageNonce * Fix review issue * Missing u64 replacement * Revert return type changes * Fix merge issue * Remove useless clone --- bin/millau/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + modules/messages/src/instant_payments.rs | 71 ++++++++++++++++++------ modules/messages/src/lib.rs | 46 ++++----------- modules/messages/src/mock.rs | 17 ++++-- primitives/messages/src/source_chain.rs | 15 ++++- 6 files changed, 93 insertions(+), 58 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 698ad1e580465..d97a82d625009 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -402,6 +402,7 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, + (), pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, RootAccountForPayments, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 84908fd52bf0a..51a5a8957cbd8 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -545,6 +545,7 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, + (), pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, RootAccountForPayments, diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index 4933901c26708..c145687af994f 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -19,15 +19,17 @@ //! The payment is first transferred to a special `relayers-fund` account and only transferred //! to the actual relayer in case confirmation is received. +use crate::OutboundMessages; + use bp_messages::{ source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, - MessageNonce, + LaneId, MessageKey, MessageNonce, UnrewardedRelayer, }; use codec::Encode; use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; -use num_traits::Zero; +use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::Saturating; -use sp_std::fmt::Debug; +use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; /// Instant message payments made in given currency. /// @@ -42,16 +44,17 @@ use sp_std::fmt::Debug; /// to the relayer account. /// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they /// can receive the payment. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(T, Currency, GetConfirmationFee, RootAccount)>, +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee, RootAccount)>, } -impl +impl MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments + for InstantCurrencyPayments where - T: frame_system::Config, - Currency: CurrencyT, + T: frame_system::Config + crate::Config, + I: 'static, + Currency: CurrencyT, Currency::Balance: From, GetConfirmationFee: Get, RootAccount: Get>, @@ -86,17 +89,53 @@ where } fn pay_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, - relayers_rewards: RelayersRewards, + received_range: &RangeInclusive, relayer_fund_account: &T::AccountId, ) { - pay_relayers_rewards::( - confirmation_relayer, - relayers_rewards, - relayer_fund_account, - GetConfirmationFee::get(), - ); + let relayers_rewards = + cal_relayers_rewards::(lane_id, messages_relayers, received_range); + if !relayers_rewards.is_empty() { + pay_relayers_rewards::( + confirmation_relayer, + relayers_rewards, + relayer_fund_account, + GetConfirmationFee::get(), + ); + } + } +} + +/// Calculate the relayers rewards +pub(crate) fn cal_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, + received_range: &RangeInclusive, +) -> RelayersRewards +where + T: frame_system::Config + crate::Config, + I: 'static, +{ + // remember to reward relayers that have delivered messages + // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain + let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); + for entry in messages_relayers { + let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); + let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); + + // loop won't proceed if current entry is ahead of received range (begin > end). + // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); + for nonce in nonce_begin..nonce_end + 1 { + let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) + .expect("message was just confirmed; we never prune unconfirmed messages; qed"); + relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); + relayer_reward.messages += 1; + } } + relayers_rewards } /// Pay rewards to given relayers, optionally rewarding confirmation relayer. diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index c5ce27bb7258a..ce56fc3f87a79 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -51,7 +51,7 @@ use crate::{ use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, RelayersRewards, TargetHeaderChain, + OnMessageAccepted, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -143,7 +143,13 @@ pub mod pallet { /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter + Size; /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Default + From + PartialOrd + Parameter + SaturatingAdd + Zero; + type OutboundMessageFee: Default + + From + + PartialOrd + + Parameter + + SaturatingAdd + + Zero + + Copy; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; @@ -548,8 +554,6 @@ pub mod pallet { // mark messages as delivered let mut lane = outbound_lane::(lane_id); - let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = - RelayersRewards::new(); let last_delivered_nonce = lane_data.last_delivered_nonce(); let confirmed_messages = match lane.confirm_delivery( relayers_state.total_messages, @@ -620,40 +624,14 @@ pub mod pallet { let received_range = confirmed_messages.begin..=confirmed_messages.end; Self::deposit_event(Event::MessagesDelivered(lane_id, confirmed_messages)); - // remember to reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the - // bridged chain - for entry in lane_data.relayers { - let nonce_begin = - sp_std::cmp::max(entry.messages.begin, *received_range.start()); - let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); - - // loop won't proceed if current entry is ahead of received range (begin > end). - // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged - // chain - let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); - for nonce in nonce_begin..nonce_end + 1 { - let message_data = OutboundMessages::::get(MessageKey { - lane_id, - nonce, - }) - .expect( - "message was just confirmed; we never prune unconfirmed messages; qed", - ); - relayer_reward.reward = - relayer_reward.reward.saturating_add(&message_data.fee); - relayer_reward.messages += 1; - } - } - } - - // if some new messages have been confirmed, reward relayers - if !relayers_rewards.is_empty() { + // if some new messages have been confirmed, reward relayers let relayer_fund_account = relayer_fund_account_id::(); >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( + lane_id, + lane_data.relayers, &confirmation_relayer, - relayers_rewards, + &received_range, &relayer_fund_account, ); } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 330cfef4cdea0..5cc905d912124 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -17,13 +17,13 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::Config; +use crate::{instant_payments::cal_relayers_rewards, Config}; use bitvec::prelude::*; use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, RelayersRewards, Sender, TargetHeaderChain, + OnMessageAccepted, Sender, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -43,7 +43,10 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, FixedU128, Perbill, }; -use std::collections::BTreeMap; +use std::{ + collections::{BTreeMap, VecDeque}, + ops::RangeInclusive, +}; pub type AccountId = u64; pub type Balance = u64; @@ -350,11 +353,15 @@ impl MessageDeliveryAndDispatchPayment } fn pay_relayers_rewards( + lane_id: LaneId, + message_relayers: VecDeque>, _confirmation_relayer: &AccountId, - relayers_rewards: RelayersRewards, + received_range: &RangeInclusive, _relayer_fund_account: &AccountId, ) { - for (relayer, reward) in relayers_rewards { + let relayers_rewards = + cal_relayers_rewards::(lane_id, message_relayers, received_range); + for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward.reward).encode(); frame_support::storage::unhashed::put(&key, &true); } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index dbe6a5922158d..1745180f94cc6 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -18,9 +18,14 @@ use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; +use crate::UnrewardedRelayer; use bp_runtime::Size; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; -use sp_std::{collections::btree_map::BTreeMap, fmt::Debug}; +use sp_std::{ + collections::{btree_map::BTreeMap, vec_deque::VecDeque}, + fmt::Debug, + ops::RangeInclusive, +}; /// The sender of the message on the source chain. pub type Sender = frame_system::RawOrigin; @@ -122,8 +127,10 @@ pub trait MessageDeliveryAndDispatchPayment { /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is /// a relayer that has submitted delivery confirmation transaction. fn pay_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, confirmation_relayer: &AccountId, - relayers_rewards: RelayersRewards, + received_range: &RangeInclusive, relayer_fund_account: &AccountId, ); } @@ -240,8 +247,10 @@ impl MessageDeliveryAndDispatchPayment } fn pay_relayers_rewards( + _lane_id: LaneId, + _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, - _relayers_rewards: RelayersRewards, + _received_range: &RangeInclusive, _relayer_fund_account: &AccountId, ) { } From 74169c045ddc0b0ac742ff4450a91b086f20130a Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 27 Sep 2021 09:20:42 -0300 Subject: [PATCH 0579/1210] add some basic tests for swap tokens (#1164) --- relays/bin-substrate/src/cli/swap_tokens.rs | 132 +++++++++++++++++++- 1 file changed, 130 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index d18d37efc3d20..7d7d7ce56e64b 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -41,7 +41,7 @@ use crate::cli::{ }; /// Swap tokens. -#[derive(StructOpt)] +#[derive(StructOpt, Debug, PartialEq)] pub struct SwapTokens { /// A bridge instance to use in token swap. #[structopt(possible_values = SwapTokensBridge::VARIANTS, case_insensitive = true)] @@ -85,7 +85,7 @@ pub enum TokenSwapType { } /// Swap tokens bridge. -#[derive(Debug, EnumString, EnumVariantNames)] +#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] #[strum(serialize_all = "kebab_case")] pub enum SwapTokensBridge { /// Use token-swap pallet deployed at Millau to swap tokens with Rialto. @@ -665,3 +665,131 @@ async fn read_token_swap_state( ) -> anyhow::Result> { Ok(client.storage_value(swap_state_storage_key.clone(), Some(at_block)).await?) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn swap_tokens_millau_to_rialto_no_lock() { + let swap_tokens = SwapTokens::from_iter(vec![ + "swap-tokens", + "millau-to-rialto", + "--source-host", + "127.0.0.1", + "--source-port", + "9000", + "--source-signer", + "//Alice", + "--source-balance", + "8000000000", + "--target-host", + "127.0.0.1", + "--target-port", + "9001", + "--target-signer", + "//Bob", + "--target-balance", + "9000000000", + "no-lock", + ]); + + assert_eq!( + swap_tokens, + SwapTokens { + bridge: SwapTokensBridge::MillauToRialto, + source: SourceConnectionParams { + source_host: "127.0.0.1".into(), + source_port: 9000, + source_secure: false, + }, + source_sign: SourceSigningParams { + source_signer: Some("//Alice".into()), + source_signer_password: None, + source_signer_file: None, + source_signer_password_file: None, + source_transactions_mortality: None, + }, + target: TargetConnectionParams { + target_host: "127.0.0.1".into(), + target_port: 9001, + target_secure: false, + }, + target_sign: TargetSigningParams { + target_signer: Some("//Bob".into()), + target_signer_password: None, + target_signer_file: None, + target_signer_password_file: None, + target_transactions_mortality: None, + }, + swap_type: TokenSwapType::NoLock, + source_balance: Balance(8000000000), + target_balance: Balance(9000000000), + } + ); + } + + #[test] + fn swap_tokens_millau_to_rialto_lock_until() { + let swap_tokens = SwapTokens::from_iter(vec![ + "swap-tokens", + "millau-to-rialto", + "--source-host", + "127.0.0.1", + "--source-port", + "9000", + "--source-signer", + "//Alice", + "--source-balance", + "8000000000", + "--target-host", + "127.0.0.1", + "--target-port", + "9001", + "--target-signer", + "//Bob", + "--target-balance", + "9000000000", + "lock-until-block", + "--blocks-before-expire", + "1", + ]); + + assert_eq!( + swap_tokens, + SwapTokens { + bridge: SwapTokensBridge::MillauToRialto, + source: SourceConnectionParams { + source_host: "127.0.0.1".into(), + source_port: 9000, + source_secure: false, + }, + source_sign: SourceSigningParams { + source_signer: Some("//Alice".into()), + source_signer_password: None, + source_signer_file: None, + source_signer_password_file: None, + source_transactions_mortality: None, + }, + target: TargetConnectionParams { + target_host: "127.0.0.1".into(), + target_port: 9001, + target_secure: false, + }, + target_sign: TargetSigningParams { + target_signer: Some("//Bob".into()), + target_signer_password: None, + target_signer_file: None, + target_signer_password_file: None, + target_transactions_mortality: None, + }, + swap_type: TokenSwapType::LockUntilBlock { + blocks_before_expire: 1, + swap_nonce: None, + }, + source_balance: Balance(8000000000), + target_balance: Balance(9000000000), + } + ); + } +} From 423dbf6e5260acb5223c59d40eb225cc9048a253 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 27 Sep 2021 12:24:38 +0000 Subject: [PATCH 0580/1210] Upgrade `jsonrpsee` to v0.3 (#1051) * Upgrade `jsonrpsee` to v0.3 * whitespace * fmt Co-authored-by: Svyatoslav Nikolsky --- modules/ethereum/src/import.rs | 5 +++-- relays/bin-ethereum/src/ethereum_deploy_contract.rs | 5 +++-- relays/client-ethereum/Cargo.toml | 4 ++-- relays/client-ethereum/src/error.rs | 12 +++++++----- relays/client-substrate/Cargo.toml | 5 ++--- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 7 +++++-- relays/client-substrate/src/error.rs | 12 +++++++----- relays/client-substrate/src/finality_source.rs | 3 ++- 9 files changed, 32 insertions(+), 23 deletions(-) diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 3c99451ca8f18..31e8642d51096 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -307,8 +307,9 @@ mod tests { ) .unwrap(); match i { - 2..=10 => - assert_eq!(finalized_blocks, vec![(parent_id, Some(100))], "At {}", i,), + 2..=10 => { + assert_eq!(finalized_blocks, vec![(parent_id, Some(100))], "At {}", i,) + }, _ => assert_eq!(finalized_blocks, vec![], "At {}", i), } latest_block_id = rolling_last_block_id; diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs index d7006a9c673cf..9eecc1a12f517 100644 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -106,12 +106,13 @@ async fn prepare_initial_header( sub_initial_header: Option>, ) -> Result<(RialtoHeaderId, Vec), String> { match sub_initial_header { - Some(raw_initial_header) => + Some(raw_initial_header) => { match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) { Ok(initial_header) => Ok((HeaderId(initial_header.number, initial_header.hash()), raw_initial_header)), Err(error) => Err(format!("Error decoding initial header: {}", error)), - }, + } + }, None => { let initial_header = sub_client.header_by_number(Zero::zero()).await; initial_header diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 4ce90cc783bcd..6d56eb94dbd71 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -10,8 +10,8 @@ async-std = "1.6.5" bp-eth-poa = { path = "../../primitives/ethereum-poa" } headers-relay = { path = "../headers" } hex-literal = "0.3" -jsonrpsee-proc-macros = "0.2" -jsonrpsee-ws-client = "0.2" +jsonrpsee-proc-macros = "0.3.1" +jsonrpsee-ws-client = "0.3.1" libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index f3c832cd40066..23a9138e12085 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -18,7 +18,7 @@ use crate::types::U256; -use jsonrpsee_ws_client::Error as RpcError; +use jsonrpsee_ws_client::types::Error as RpcError; use relay_utils::MaybeConnectionError; /// Result type used by Ethereum client. @@ -73,10 +73,12 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::RpcError(RpcError::Transport(_)) | - Error::RpcError(RpcError::Internal(_)) | - Error::RpcError(RpcError::RestartNeeded(_)) | - Error::ClientNotSynced(_), + Error::RpcError(RpcError::Transport(_)) + // right now if connection to the ws server is dropped (after it is already established), + // we're getting this error + | Error::RpcError(RpcError::Internal(_)) + | Error::RpcError(RpcError::RestartNeeded(_)) + | Error::ClientNotSynced(_), ) } } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 90e775b784eb4..7d82e365e2f17 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,9 +9,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" codec = { package = "parity-scale-codec", version = "2.2.0" } -jsonrpsee-proc-macros = "0.2" -jsonrpsee-types = "0.2" -jsonrpsee-ws-client = "0.2" +jsonrpsee-proc-macros = "0.3.1" +jsonrpsee-ws-client = "0.3.1" log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index c3d4e30452423..75789ce37f308 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -17,7 +17,7 @@ use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; use frame_support::weights::WeightToFeePolynomial; -use jsonrpsee_ws_client::{DeserializeOwned, Serialize}; +use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; use sp_core::{storage::StorageKey, Pair}; diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index ca197867bc4b2..fd69dd255e6da 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -28,8 +28,11 @@ use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; use jsonrpsee_ws_client::{ - traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned, WsClient as RpcClient, - WsClientBuilder as RpcClientBuilder, + types::{ + self as jsonrpsee_types, traits::SubscriptionClient, v2::params::JsonRpcParams, + DeserializeOwned, + }, + WsClient as RpcClient, WsClientBuilder as RpcClientBuilder, }; use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index d3444516429be..c3cd236b948c5 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -16,7 +16,7 @@ //! Substrate node RPC errors. -use jsonrpsee_ws_client::Error as RpcError; +use jsonrpsee_ws_client::types::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; use sp_runtime::transaction_validity::TransactionValidityError; @@ -96,10 +96,12 @@ impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( *self, - Error::RpcError(RpcError::Transport(_)) | - Error::RpcError(RpcError::Internal(_)) | - Error::RpcError(RpcError::RestartNeeded(_)) | - Error::ClientNotSynced(_), + Error::RpcError(RpcError::Transport(_)) + // right now if connection to the ws server is dropped (after it is already established), + // we're getting this error + | Error::RpcError(RpcError::Internal(_)) + | Error::RpcError(RpcError::RestartNeeded(_)) + | Error::ClientNotSynced(_), ) } } diff --git a/relays/client-substrate/src/finality_source.rs b/relays/client-substrate/src/finality_source.rs index 0059429dcb418..98526de178cb3 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/client-substrate/src/finality_source.rs @@ -151,8 +151,9 @@ where .await .map_err(|err| log_error(err.to_string())) .ok()??; + let decoded_justification = - GrandpaJustification::::decode(&mut &next_justification.0[..]); + GrandpaJustification::::decode(&mut &next_justification[..]); let justification = match decoded_justification { Ok(j) => j, From da865b6db9e8797eb539b950469403a2e93d7805 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Sep 2021 15:35:50 +0300 Subject: [PATCH 0581/1210] fix spelling (#1167) --- modules/ethereum/src/verification.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index 34ae9ad315432..af7b33fc80bbb 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -332,7 +332,7 @@ fn verify_empty_step(parent_hash: &H256, step: &SealedEmptyStep, validators: &[A verify_signature(&expected_validator, &step.signature, &message) } -/// Chain scoring: total weight is sqrt(U256::max_value())*height - step +/// Chain scoring: total `weight is sqrt(U256::max_value())*height - step`. pub(crate) fn calculate_score( parent_step: u64, current_step: u64, From f239ea8e460be57f8f5771174d2006c722498683 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Sep 2021 15:56:19 +0300 Subject: [PATCH 0582/1210] copypasted -> copied (#1168) --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto-parachain/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- primitives/runtime/src/lib.rs | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d97a82d625009..7385e8ecec894 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -283,7 +283,7 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; - // values for following parameters are copypasted from polkadot repo, but it is fine + // values for following parameters are copied from polkadot repo, but it is fine // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 93118e3c9dd3b..15911d6fc4134 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -16,7 +16,7 @@ //! The Rialto parachain runtime. This can be compiled with `#[no_std]`, ready for Wasm. //! -//! Originally a copypaste of runtime from https://github.com/substrate-developer-hub/substrate-parachain-template. +//! Originally a copy of runtime from https://github.com/substrate-developer-hub/substrate-parachain-template. #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 51a5a8957cbd8..90a4dbd5087e0 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -423,7 +423,7 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; - // values for following parameters are copypasted from polkadot repo, but it is fine + // values for following parameters are copied from polkadot repo, but it is fine // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index fe3309c83bf41..63fc2393e7836 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -192,7 +192,7 @@ impl, BlockHash: Copy> TransactionEra StorageKey { let mut buffer = Vec::with_capacity(1 + parameter_name.len() + 1 + 1); buffer.push(b':'); From ba937d23c7119460cb3422570d79ebb486be0465 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 8 Oct 2021 12:35:11 +0300 Subject: [PATCH 0583/1210] Token swap pallet benchmarks (#1174) * token swap benchmarks * spellcheck --- bin/millau/node/Cargo.toml | 5 +- bin/millau/runtime/Cargo.toml | 11 +- bin/millau/runtime/src/lib.rs | 65 ++++++++ modules/grandpa/src/weights.rs | 6 +- modules/messages/src/lib.rs | 31 ++-- modules/messages/src/weights.rs | 6 +- modules/token-swap/Cargo.toml | 6 + modules/token-swap/src/benchmarking.rs | 188 ++++++++++++++++++++++++ modules/token-swap/src/lib.rs | 50 +++++-- modules/token-swap/src/mock.rs | 10 +- modules/token-swap/src/weights.rs | 93 ++++++++++++ modules/token-swap/src/weights_ext.rs | 42 ++++++ primitives/messages/src/source_chain.rs | 30 +++- primitives/runtime/src/lib.rs | 6 + 14 files changed, 500 insertions(+), 49 deletions(-) create mode 100644 modules/token-swap/src/benchmarking.rs create mode 100644 modules/token-swap/src/weights.rs create mode 100644 modules/token-swap/src/weights_ext.rs diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3307d6031dd49..b650bd478a62b 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -54,9 +54,6 @@ frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", bran [features] default = [] - -# TODO: https://github.com/paritytech/parity-bridges-common/issues/390 -# I've left the feature flag here to test our CI configuration runtime-benchmarks = [ - # "millau-runtime/runtime-benchmarks", + "millau-runtime/runtime-benchmarks", ] diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 68d10168e4b6e..7e2a5491f5b15 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -8,6 +8,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } @@ -28,6 +29,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -102,6 +104,9 @@ std = [ "sp-trie/std", "sp-version/std", ] -# TODO: https://github.com/paritytech/parity-bridges-common/issues/390 -# I've left the feature flag here to test our CI configuration -runtime-benchmarks = [] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-bridge-token-swap/runtime-benchmarks", +] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7385e8ecec894..161816c2d940e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -425,10 +425,14 @@ pub type WithRialtoTokenSwapInstance = (); impl pallet_bridge_token_swap::Config for Runtime { type Event = Event; + type WeightInfo = (); type BridgedChainId = RialtoChainId; type OutboundMessageLaneId = TokenSwapMessagesLane; + #[cfg(not(feature = "runtime-benchmarks"))] type MessagesBridge = pallet_bridge_messages::Pallet; + #[cfg(feature = "runtime-benchmarks")] + type MessagesBridge = bp_messages::source_chain::NoopMessagesBridge; type ThisCurrency = pallet_balances::Pallet; type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; @@ -704,6 +708,67 @@ impl_runtime_apis! { BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane) } } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + + let mut list = Vec::::new(); + + list_benchmark!(list, extra, pallet_bridge_token_swap, BridgeRialtoTokenSwap); + + let storage_info = AllPalletsWithSystem::storage_info(); + + return (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig, + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; + + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), + // Caller 0 Account + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), + ]; + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + + use pallet_bridge_token_swap::benchmarking::Config as TokenSwapConfig; + + impl TokenSwapConfig for Runtime { + fn initialize_environment() { + let relayers_fund_account = pallet_bridge_messages::relayer_fund_account_id::< + bp_millau::AccountId, + bp_millau::AccountIdConverter, + >(); + pallet_balances::Pallet::::make_free_balance_be( + &relayers_fund_account, + Balance::MAX / 100, + ); + } + } + + add_benchmark!(params, batches, pallet_bridge_token_swap, BridgeRialtoTokenSwap); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } } /// Rialto account ownership digest from Millau. diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 18d88049f16a8..c0cce2c5258d1 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for pallet_bridge_grandpa +//! Autogenerated weights for `pallet_bridge_grandpa` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 //! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20 @@ -46,12 +46,12 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_bridge_grandpa. +/// Weight functions needed for `pallet_bridge_grandpa`. pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; } -/// Weights for pallet_bridge_grandpa using the Rialto node and recommended hardware. +/// Weights for `pallet_bridge_grandpa` using the Rialto node and recommended hardware. pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index ce56fc3f87a79..8d2e239781cbb 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -51,7 +51,7 @@ use crate::{ use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, TargetHeaderChain, + OnMessageAccepted, SendMessageArtifacts, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -281,7 +281,10 @@ pub mod pallet { payload, delivery_and_dispatch_fee, ) - .map(|sent_message| sent_message.post_dispatch_info) + .map(|sent_message| PostDispatchInfo { + actual_weight: Some(sent_message.weight), + pays_fee: Pays::Yes, + }) } /// Pay additional fee for the message. @@ -853,27 +856,21 @@ where lane: LaneId, message: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, - ) -> Result { + ) -> Result { crate::send_message::(sender, lane, message, delivery_and_dispatch_fee) - .map(|sent_message| sent_message.nonce) } } -/// Message that has been sent. -struct SentMessage { - /// Nonce of the message. - pub nonce: MessageNonce, - /// Post-dispatch call info. - pub post_dispatch_info: PostDispatchInfo, -} - /// Function that actually sends message. fn send_message, I: 'static>( submitter: bp_messages::source_chain::Sender, lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, -) -> sp_std::result::Result> { +) -> sp_std::result::Result< + SendMessageArtifacts, + sp_runtime::DispatchErrorWithPostInfo, +> { ensure_normal_operating_mode::()?; // initially, actual (post-dispatch) weight is equal to pre-dispatch weight @@ -986,13 +983,7 @@ fn send_message, I: 'static>( Pallet::::deposit_event(Event::MessageAccepted(lane_id, nonce)); - Ok(SentMessage { - nonce, - post_dispatch_info: PostDispatchInfo { - actual_weight: Some(actual_weight), - pays_fee: Pays::Yes, - }, - }) + Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } /// Ensure that the origin is either root, or `PalletOwner`. diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index b3028c8fcc4f2..9dce11168fbbc 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for pallet_bridge_messages +//! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 //! DATE: 2021-06-18, STEPS: [50, ], REPEAT: 20 @@ -46,7 +46,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_bridge_messages. +/// Weight functions needed for `pallet_bridge_messages`. pub trait WeightInfo { fn send_minimal_message_worst_case() -> Weight; fn send_1_kb_message_worst_case() -> Weight; @@ -71,7 +71,7 @@ pub trait WeightInfo { fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } -/// Weights for pallet_bridge_messages using the Rialto node and recommended hardware. +/// Weights for `pallet_bridge_messages` using the Rialto node and recommended hardware. pub struct RialtoWeight(PhantomData); impl WeightInfo for RialtoWeight { fn send_minimal_message_worst_case() -> Weight { diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index 0266fd51f7691..b68eed6d59e08 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -18,9 +18,11 @@ bp-messages = { path = "../../primitives/messages", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } bp-token-swap = { path = "../../primitives/token-swap", default-features = false } pallet-bridge-dispatch = { path = "../dispatch", default-features = false } +pallet-bridge-messages = { path = "../messages", default-features = false } # Substrate Dependencies +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -43,9 +45,13 @@ std = [ "frame-system/std", "log/std", "pallet-bridge-dispatch/std", + "pallet-bridge-messages/std", "serde", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", ] +runtime-benchmarks = [ + "frame-benchmarking", +] diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs new file mode 100644 index 0000000000000..0dd8922d157f4 --- /dev/null +++ b/modules/token-swap/src/benchmarking.rs @@ -0,0 +1,188 @@ +// 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 . + +//! Token-swap pallet benchmarking. + +use crate::{ + swap_account_id, target_account_at_this_chain, BridgedAccountIdOf, BridgedAccountPublicOf, + BridgedAccountSignatureOf, BridgedBalanceOf, Call, Pallet, ThisChainBalance, TokenSwapOf, +}; + +use bp_token_swap::{TokenSwap, TokenSwapState, TokenSwapType}; +use codec::Encode; +use frame_benchmarking::{account, benchmarks_instance_pallet}; +use frame_support::{traits::Currency, Parameter}; +use frame_system::RawOrigin; +use sp_core::H256; +use sp_io::hashing::blake2_256; +use sp_runtime::traits::Bounded; +use sp_std::vec::Vec; + +const SEED: u32 = 0; + +/// Trait that must be implemented by runtime. +pub trait Config: crate::Config { + /// Initialize environment for token swap. + fn initialize_environment(); +} + +benchmarks_instance_pallet! { + where_clause { + where + BridgedAccountPublicOf: Default + Parameter, + BridgedAccountSignatureOf: Default, + } + + // + // Benchmarks that are used directly by the runtime. + // + + // Benchmark `create_swap` extrinsic. + // + // This benchmark assumes that message is **NOT** actually sent. Instead we're using `send_message_weight` + // from the `WeightInfoExt` trait. + // + // There aren't any factors that affect `create_swap` performance, so everything + // is straightforward here. + create_swap { + T::initialize_environment(); + + let sender = funded_account::("source_account_at_this_chain", 0); + let swap: TokenSwapOf = test_swap::(sender.clone(), true); + let target_public_at_bridged_chain = target_public_at_bridged_chain::(); + let swap_delivery_and_dispatch_fee = swap_delivery_and_dispatch_fee::(); + let bridged_chain_spec_version = 0; + let bridged_currency_transfer = Vec::new(); + let bridged_currency_transfer_weight = 0; + let bridged_currency_transfer_signature = bridged_currency_transfer_signature::(); + }: create_swap( + RawOrigin::Signed(sender.clone()), + swap, + target_public_at_bridged_chain, + swap_delivery_and_dispatch_fee, + bridged_chain_spec_version, + bridged_currency_transfer, + bridged_currency_transfer_weight, + bridged_currency_transfer_signature + ) + verify { + assert!(crate::PendingSwaps::::contains_key(test_swap_hash::(sender, true))); + } + + // Benchmark `claim_swap` extrinsic with the worst possible conditions: + // + // * swap is locked until some block, so current block number is read. + claim_swap { + T::initialize_environment(); + + let sender: T::AccountId = account("source_account_at_this_chain", 0, SEED); + crate::PendingSwaps::::insert( + test_swap_hash::(sender.clone(), false), + TokenSwapState::Confirmed, + ); + + let swap: TokenSwapOf = test_swap::(sender.clone(), false); + let claimer = target_account_at_this_chain::(&swap); + let token_swap_account = swap_account_id::(&swap); + T::ThisCurrency::make_free_balance_be(&token_swap_account, ThisChainBalance::::max_value()); + }: claim_swap(RawOrigin::Signed(claimer), swap) + verify { + assert!(!crate::PendingSwaps::::contains_key(test_swap_hash::(sender, false))); + } + + // Benchmark `cancel_swap` extrinsic with the worst possible conditions: + // + // * swap is locked until some block, so current block number is read. + cancel_swap { + T::initialize_environment(); + + let sender: T::AccountId = account("source_account_at_this_chain", 0, SEED); + crate::PendingSwaps::::insert( + test_swap_hash::(sender.clone(), false), + TokenSwapState::Failed, + ); + + let swap: TokenSwapOf = test_swap::(sender.clone(), false); + let token_swap_account = swap_account_id::(&swap); + T::ThisCurrency::make_free_balance_be(&token_swap_account, ThisChainBalance::::max_value()); + + }: cancel_swap(RawOrigin::Signed(sender.clone()), swap) + verify { + assert!(!crate::PendingSwaps::::contains_key(test_swap_hash::(sender, false))); + } +} + +/// Returns test token swap. +fn test_swap, I: 'static>(sender: T::AccountId, is_create: bool) -> TokenSwapOf { + TokenSwap { + swap_type: TokenSwapType::LockClaimUntilBlock( + if is_create { 10u32.into() } else { 0u32.into() }, + 0.into(), + ), + source_balance_at_this_chain: source_balance_to_swap::(), + source_account_at_this_chain: sender, + target_balance_at_bridged_chain: target_balance_to_swap::(), + target_account_at_bridged_chain: target_account_at_bridged_chain::(), + } +} + +/// Returns test token swap hash. +fn test_swap_hash, I: 'static>(sender: T::AccountId, is_create: bool) -> H256 { + test_swap::(sender, is_create).using_encoded(blake2_256).into() +} + +/// Account that has some balance. +fn funded_account, I: 'static>(name: &'static str, index: u32) -> T::AccountId { + let account: T::AccountId = account(name, index, SEED); + T::ThisCurrency::make_free_balance_be(&account, ThisChainBalance::::max_value()); + account +} + +/// Currency transfer message fee. +fn swap_delivery_and_dispatch_fee, I: 'static>() -> ThisChainBalance { + ThisChainBalance::::max_value() / 4u32.into() +} + +/// Balance at the source chain that we're going to swap. +fn source_balance_to_swap, I: 'static>() -> ThisChainBalance { + ThisChainBalance::::max_value() / 2u32.into() +} + +/// Balance at the target chain that we're going to swap. +fn target_balance_to_swap, I: 'static>() -> BridgedBalanceOf { + BridgedBalanceOf::::max_value() / 2u32.into() +} + +/// Public key of `target_account_at_bridged_chain`. +fn target_public_at_bridged_chain, I: 'static>() -> BridgedAccountPublicOf +where + BridgedAccountPublicOf: Default, +{ + Default::default() +} + +/// Signature of `target_account_at_bridged_chain` over message. +fn bridged_currency_transfer_signature, I: 'static>() -> BridgedAccountSignatureOf +where + BridgedAccountSignatureOf: Default, +{ + Default::default() +} + +/// Account at the bridged chain that is participating in the swap. +fn target_account_at_bridged_chain, I: 'static>() -> BridgedAccountIdOf { + Default::default() +} diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 9469df3aaceeb..3a49d431c7786 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -62,15 +62,25 @@ use codec::Encode; use frame_support::{ fail, traits::{Currency, ExistenceRequirement}, + weights::PostDispatchInfo, }; use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Convert, Saturating}; use sp_std::vec::Vec; +use weights::WeightInfo; + +pub use weights_ext::WeightInfoExt; #[cfg(test)] mod mock; +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + +pub mod weights; +pub mod weights_ext; + pub use pallet::*; /// Name of the `PendingSwaps` storage map. @@ -88,6 +98,8 @@ pub mod pallet { pub trait Config: frame_system::Config { /// The overarching event type. type Event: From> + IsType<::Event>; + /// Benchmarks results from runtime we're plugged into. + type WeightInfo: WeightInfoExt; /// Id of the bridge with the Bridged chain. type BridgedChainId: Get; @@ -200,7 +212,13 @@ pub mod pallet { /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. /// Violating other rules will lead to losing message fees for this and other transactions + /// losing fees for message transfer. - #[pallet::weight(0)] + #[pallet::weight( + T::WeightInfo::create_swap() + .saturating_add(T::WeightInfo::send_message_weight( + &&bridged_currency_transfer[..], + T::DbWeight::get(), + )) + )] #[allow(clippy::too_many_arguments)] pub fn create_swap( origin: OriginFor, @@ -220,6 +238,9 @@ pub mod pallet { Error::::MismatchedSwapSourceOrigin, ); + // remember weight components + let base_weight = T::WeightInfo::create_swap(); + // we can't exchange less than existential deposit (the temporary `swap_account` account // won't be created then) // @@ -242,7 +263,7 @@ pub mod pallet { } let swap_account = swap_account_id::(&swap); - frame_support::storage::with_transaction(|| { + let actual_send_message_weight = frame_support::storage::with_transaction(|| { // funds are transferred from This account to the temporary Swap account let transfer_result = T::ThisCurrency::transfer( &swap.source_account_at_this_chain, @@ -265,7 +286,7 @@ pub mod pallet { ); return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferToSwapAccount.into(), + Error::::FailedToTransferToSwapAccount, )) } @@ -288,8 +309,8 @@ pub mod pallet { }, swap_delivery_and_dispatch_fee, ); - let transfer_message_nonce = match send_message_result { - Ok(transfer_message_nonce) => transfer_message_nonce, + let sent_message = match send_message_result { + Ok(sent_message) => sent_message, Err(err) => { log::error!( target: "runtime::bridge-token-swap", @@ -299,7 +320,7 @@ pub mod pallet { ); return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToSendTransferMessage.into(), + Error::::FailedToSendTransferMessage, )) }, }; @@ -323,7 +344,7 @@ pub mod pallet { ); return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::SwapAlreadyStarted.into(), + Error::::SwapAlreadyStarted, )) } @@ -335,12 +356,17 @@ pub mod pallet { ); // remember that we're waiting for the transfer message delivery confirmation - PendingMessages::::insert(transfer_message_nonce, swap_hash); + PendingMessages::::insert(sent_message.nonce, swap_hash); // finally - emit the event - Self::deposit_event(Event::SwapStarted(swap_hash, transfer_message_nonce)); + Self::deposit_event(Event::SwapStarted(swap_hash, sent_message.nonce)); + + sp_runtime::TransactionOutcome::Commit(Ok(sent_message.weight)) + })?; - sp_runtime::TransactionOutcome::Commit(Ok(().into())) + Ok(PostDispatchInfo { + actual_weight: Some(base_weight.saturating_add(actual_send_message_weight)), + pays_fee: Pays::Yes, }) } @@ -352,7 +378,7 @@ pub mod pallet { /// `pallet_bridge_dispatch::CallOrigin::SourceAccount(target_account_at_bridged_chain)`. /// /// This should be called only when successful transfer confirmation has been received. - #[pallet::weight(0)] + #[pallet::weight(T::WeightInfo::claim_swap())] pub fn claim_swap( origin: OriginFor, swap: TokenSwapOf, @@ -388,7 +414,7 @@ pub mod pallet { /// /// This should be called only when transfer has failed at Bridged chain and we have /// received notification about that. - #[pallet::weight(0)] + #[pallet::weight(T::WeightInfo::cancel_swap())] pub fn cancel_swap( origin: OriginFor, swap: TokenSwapOf, diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index 16894d9850ba0..63edb323e1a4c 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -17,7 +17,10 @@ use crate as pallet_bridge_token_swap; use crate::MessagePayloadOf; -use bp_messages::{source_chain::MessagesBridge, LaneId, MessageNonce}; +use bp_messages::{ + source_chain::{MessagesBridge, SendMessageArtifacts}, + LaneId, MessageNonce, +}; use bp_runtime::ChainId; use frame_support::weights::Weight; use sp_core::H256; @@ -114,6 +117,7 @@ frame_support::parameter_types! { impl pallet_bridge_token_swap::Config for TestRuntime { type Event = Event; + type WeightInfo = (); type BridgedChainId = BridgedChainId; type OutboundMessageLaneId = OutboundMessageLaneId; @@ -150,12 +154,12 @@ impl MessagesBridge> for T lane: LaneId, message: MessagePayloadOf, delivery_and_dispatch_fee: Balance, - ) -> Result { + ) -> Result { assert_ne!(sender, frame_system::RawOrigin::Signed(THIS_CHAIN_ACCOUNT)); assert_eq!(lane, OutboundMessageLaneId::get()); assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE); match message.call[0] { - OK_TRANSFER_CALL => Ok(MESSAGE_NONCE), + OK_TRANSFER_CALL => Ok(SendMessageArtifacts { nonce: MESSAGE_NONCE, weight: 0 }), BAD_TRANSFER_CALL => Err(()), _ => unreachable!(), } diff --git a/modules/token-swap/src/weights.rs b/modules/token-swap/src/weights.rs new file mode 100644 index 0000000000000..06cb6b85cf336 --- /dev/null +++ b/modules/token-swap/src/weights.rs @@ -0,0 +1,93 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_token_swap` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-10-06, STEPS: 50, REPEAT: 20 +//! LOW RANGE: [], HIGH RANGE: [] +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled +//! CHAIN: Some("dev"), DB CACHE: 128 + +// Executed Command: +// target/release/millau-bridge-node +// benchmark +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_bridge_token_swap +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./modules/token-swap/src/weights.rs +// --template=./.maintain/millau-weight-template.hbs + +#![allow(clippy::all)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for `pallet_bridge_token_swap`. +pub trait WeightInfo { + fn create_swap() -> Weight; + fn claim_swap() -> Weight; + fn cancel_swap() -> Weight; +} + +/// Weights for `pallet_bridge_token_swap` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { + fn create_swap() -> Weight { + (116_040_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) + } + fn claim_swap() -> Weight { + (102_882_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn cancel_swap() -> Weight { + (99_434_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn create_swap() -> Weight { + (116_040_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + } + fn claim_swap() -> Weight { + (102_882_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn cancel_swap() -> Weight { + (99_434_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } +} diff --git a/modules/token-swap/src/weights_ext.rs b/modules/token-swap/src/weights_ext.rs new file mode 100644 index 0000000000000..2d27c76cbe685 --- /dev/null +++ b/modules/token-swap/src/weights_ext.rs @@ -0,0 +1,42 @@ +// 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 . + +//! Weight-related utilities. + +use crate::weights::WeightInfo; + +use bp_runtime::Size; +use frame_support::weights::{RuntimeDbWeight, Weight}; + +/// Extended weight info. +pub trait WeightInfoExt: WeightInfo { + // Functions that are directly mapped to extrinsics weights. + + /// Weight of message send extrinsic. + fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight; +} + +impl WeightInfoExt for () { + fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { + <() as pallet_bridge_messages::WeightInfoExt>::send_message_weight(message, db_weight) + } +} + +impl WeightInfoExt for crate::weights::MillauWeight { + fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { + <() as pallet_bridge_messages::WeightInfoExt>::send_message_weight(message, db_weight) + } +} diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 1745180f94cc6..1ff05abf131ea 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -135,6 +135,15 @@ pub trait MessageDeliveryAndDispatchPayment { ); } +/// Send message artifacts. +#[derive(RuntimeDebug, PartialEq)] +pub struct SendMessageArtifacts { + /// Nonce of the message. + pub nonce: MessageNonce, + /// Actual weight of send message call. + pub weight: Weight, +} + /// Messages bridge API to be used from other pallets. pub trait MessagesBridge { /// Error type. @@ -148,7 +157,26 @@ pub trait MessagesBridge { lane: LaneId, message: Payload, delivery_and_dispatch_fee: Balance, - ) -> Result; + ) -> Result; +} + +/// Bridge that does nothing when message is being sent. +#[derive(RuntimeDebug, PartialEq)] +pub struct NoopMessagesBridge; + +impl MessagesBridge + for NoopMessagesBridge +{ + type Error = &'static str; + + fn send_message( + _sender: Sender, + _lane: LaneId, + _message: Payload, + _delivery_and_dispatch_fee: Balance, + ) -> Result { + Ok(SendMessageArtifacts { nonce: 0, weight: 0 }) + } } /// Handler for messages delivery confirmation. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 63fc2393e7836..9a3470a2570c3 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -131,6 +131,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 From dfcca0aa085f0b21b1500cf9eeebab0fca080357 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 8 Oct 2021 12:54:39 +0300 Subject: [PATCH 0584/1210] Register-parachain subcommand of substrate-relay (#1170) * register parachain relay subcommand * revert cargo patch * added basic test * fmt --- bin/rialto-parachain/runtime/Cargo.toml | 5 + bin/rialto-parachain/runtime/src/lib.rs | 66 +--- primitives/chain-rialto-parachain/Cargo.toml | 36 ++ primitives/chain-rialto-parachain/src/lib.rs | 128 +++++++ primitives/chain-rialto/src/lib.rs | 6 + primitives/runtime/src/lib.rs | 10 + relays/bin-substrate/Cargo.toml | 10 + relays/bin-substrate/src/chains/mod.rs | 1 + .../src/chains/rialto_parachain.rs | 82 +++++ relays/bin-substrate/src/cli/mod.rs | 7 + .../src/cli/register_parachain.rs | 343 ++++++++++++++++++ relays/bin-substrate/src/cli/swap_tokens.rs | 2 +- relays/client-rialto-parachain/Cargo.toml | 21 ++ relays/client-rialto-parachain/src/lib.rs | 51 +++ relays/client-substrate/src/client.rs | 26 +- 15 files changed, 732 insertions(+), 62 deletions(-) create mode 100644 primitives/chain-rialto-parachain/Cargo.toml create mode 100644 primitives/chain-rialto-parachain/src/lib.rs create mode 100644 relays/bin-substrate/src/chains/rialto_parachain.rs create mode 100644 relays/bin-substrate/src/cli/register_parachain.rs create mode 100644 relays/client-rialto-parachain/Cargo.toml create mode 100644 relays/client-rialto-parachain/src/lib.rs diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 09916f508b7bf..d12e4326711d9 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -15,6 +15,10 @@ codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = log = { version = "0.4.14", default-features = false } serde = { version = '1.0', optional = true, features = ['derive'] } +# Bridge depedencies + +bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } + # Substrate Dependencies ## Substrate Primitive Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -77,6 +81,7 @@ runtime-benchmarks = [ 'pallet-timestamp/runtime-benchmarks', ] std = [ + "bp-rialto-parachain/std", "codec/std", "serde", "log/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 15911d6fc4134..bf55f08eb4b96 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -30,9 +30,9 @@ use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + traits::{AccountIdLookup, Block as BlockT}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, MultiSignature, + ApplyExtrinsicResult, }; use sp_std::prelude::*; @@ -50,7 +50,7 @@ pub use frame_support::{ }, StorageValue, }; -use frame_system::limits::{BlockLength, BlockWeights}; +pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -58,6 +58,11 @@ pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::BuildStorage; pub use sp_runtime::{MultiAddress, Perbill, Permill}; +pub use bp_rialto_parachain::{ + AccountId, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher as Hashing, Header, + Index, Signature, MAXIMUM_BLOCK_WEIGHT, +}; + // Polkadot & XCM imports use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; @@ -71,26 +76,8 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -// /// Import the template pallet. -// pub use template; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; -/// Balance of an account. -pub type Balance = u128; -/// Index of a transaction in the chain. -pub type Index = u32; -/// A hash of some data used by the chain. -pub type Hash = sp_core::H256; -/// An index to a block. -pub type BlockNumber = u32; /// The address format for describing accounts. pub type Address = MultiAddress; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; /// Block type as expected by this runtime. pub type Block = generic::Block; /// A Block signed with a Justification @@ -168,38 +155,9 @@ pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } -/// We assume that approximately 10 percent of the block weight is consumed by `on_initalize` -/// handlers. This is used to limit the maximal weight of a single extrinsic. -const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); -/// We allow `Normal` extrinsics to fill up the block up to 75 percent, the rest can be used -/// by Operational extrinsics. -const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// We allow for 2 seconds of compute with a 12 second average block time. -const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND * 2; - parameter_types! { pub const BlockHashCount: BlockNumber = 250; pub const Version: RuntimeVersion = VERSION; - pub RuntimeBlockLength: BlockLength = - BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() - .base_block(BlockExecutionWeight::get()) - .for_class(DispatchClass::all(), |weights| { - weights.base_extrinsic = ExtrinsicBaseWeight::get(); - }) - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Operational transactions have some extra reserved space, so that they - // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT - ); - }) - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); pub const SS58Prefix: u8 = 48; } @@ -219,9 +177,9 @@ impl frame_system::Config for Runtime { /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. - type Hashing = BlakeTwo256; + type Hashing = Hashing; /// The header type. - type Header = generic::Header; + type Header = generic::Header; /// The ubiquitous event type. type Event = Event; /// The ubiquitous origin type. @@ -244,9 +202,9 @@ impl frame_system::Config for Runtime { /// Weight information for the extrinsics of this pallet. type SystemWeightInfo = (); /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; + type BlockWeights = BlockWeights; /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; + type BlockLength = BlockLength; /// This is used as an identifier of the chain. 42 is the generic substrate prefix. type SS58Prefix = SS58Prefix; /// The action to take on a Runtime Upgrade diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml new file mode 100644 index 0000000000000..034188631b8cd --- /dev/null +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "bp-rialto-parachain" +description = "Primitives of Rialto parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-messages/std", + "bp-runtime/std", + "frame-support/std", + "frame-system/std", + "sp-api/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs new file mode 100644 index 0000000000000..826f6d39bd7f7 --- /dev/null +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -0,0 +1,128 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] +// Runtime-generated DecodeLimit::decode_all_With_depth_limit +#![allow(clippy::unnecessary_mut_passed)] + +use bp_runtime::Chain; +use frame_support::{ + weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, + RuntimeDebug, +}; +use frame_system::limits; +use sp_core::Hasher as HasherT; +use sp_runtime::{ + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, MultiSigner, Perbill, +}; + +/// Maximal weight of single Rialto parachain block. +/// +/// This represents two seconds of compute assuming a target block time of six seconds. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; + +/// Represents the average portion of a block's weight that will be used by an +/// `on_initialize()` runtime call. +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); + +/// Represents the portion of a block that will be used by Normal extrinsics. +pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +/// Block number type used in Rialto. +pub type BlockNumber = u32; + +/// Hash type used in Rialto. +pub type Hash = ::Out; + +/// The type of object that can produce hashes on Rialto. +pub type Hasher = BlakeTwo256; + +/// The header type used by Rialto. +pub type Header = sp_runtime::generic::Header; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// Balance of an account. +pub type Balance = u128; + +/// An instant or duration in time. +pub type Moment = u64; + +/// Index of a transaction in the parachain. +pub type Index = u32; + +/// Weight-to-Fee type used by Rialto parachain. +pub type WeightToFee = IdentityFee; + +/// Rialto parachain. +#[derive(RuntimeDebug)] +pub struct RialtoParachain; + +impl Chain for RialtoParachain { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; +} + +frame_support::parameter_types! { + pub BlockLength: limits::BlockLength = + limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() + // Allowance for Normal class + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + // Allowance for Operational class + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Extra reserved space for Operational class + weights.reserved = Some(MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + // By default Mandatory class is not limited at all. + // This parameter is used to derive maximal size of a single extrinsic. + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); +} + +/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. +pub fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) +} + +/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. +pub fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) +} diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 1ded7651cceca..6c4e48301e3bb 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -231,6 +231,12 @@ pub fn max_extrinsic_size() -> u32 { /// Name of the With-Millau messages pallet instance in the Rialto runtime. pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; +/// Name of the parachain registrar pallet in the Rialto runtime. +pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; + +/// Name of the parachains pallet in the Rialto runtime. +pub const PARAS_PALLET_NAME: &str = "Paras"; + /// Name of the `RialtoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_finalized"; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 9a3470a2570c3..9ee15df1a9839 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -28,6 +28,7 @@ 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")] @@ -216,6 +217,15 @@ pub fn storage_map_final_key_blake2_128concat( ) } +/// +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. /// diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 6153fee1e569c..0f9e2792139fa 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -28,6 +28,7 @@ bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } +bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-token-swap = { path = "../../primitives/token-swap" } bp-wococo = { path = "../../primitives/chain-wococo" } @@ -44,11 +45,13 @@ relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } relay-rialto-client = { path = "../client-rialto" } +relay-rialto-parachain-client = { path = "../client-rialto-parachain" } relay-rococo-client = { path = "../client-rococo" } relay-wococo-client = { path = "../client-wococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } +rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } rialto-runtime = { path = "../../bin/rialto/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } @@ -61,6 +64,13 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } +# Polkadot Dependencies + +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } + [dev-dependencies] hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index ea7c9754ec72a..1e5e549d519a9 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -34,6 +34,7 @@ mod kusama; mod millau; mod polkadot; mod rialto; +mod rialto_parachain; mod rococo; mod westend; mod wococo; diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs new file mode 100644 index 0000000000000..f81bc61b859a8 --- /dev/null +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -0,0 +1,82 @@ +// 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 . + +//! Rialto parachain specification for CLI. + +use crate::cli::{ + encode_call::{Call, CliEncodeCall}, + encode_message, CliChain, +}; +use bp_message_dispatch::MessagePayload; +use codec::Decode; +use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use relay_rialto_parachain_client::RialtoParachain; +use sp_version::RuntimeVersion; + +impl CliEncodeCall for RialtoParachain { + fn max_extrinsic_size() -> u32 { + bp_rialto_parachain::max_extrinsic_size() + } + + fn encode_call(call: &Call) -> anyhow::Result { + Ok(match call { + Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Remark { remark_payload, .. } => rialto_parachain_runtime::Call::System( + rialto_parachain_runtime::SystemCall::remark( + remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + ), + ), + Call::Transfer { recipient, amount } => rialto_parachain_runtime::Call::Balances( + rialto_parachain_runtime::BalancesCall::transfer( + recipient.raw_id().into(), + amount.0, + ), + ), + Call::BridgeSendMessage { .. } => + anyhow::bail!("Bridge messages are not (yet) supported here",), + }) + } + + fn get_dispatch_info(call: &rialto_parachain_runtime::Call) -> anyhow::Result { + Ok(call.get_dispatch_info()) + } +} + +impl CliChain for RialtoParachain { + const RUNTIME_VERSION: RuntimeVersion = rialto_parachain_runtime::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = MessagePayload< + bp_rialto_parachain::AccountId, + bp_millau::AccountSigner, + bp_millau::Signature, + Vec, + >; + + fn ss58_format() -> u16 { + rialto_parachain_runtime::SS58Prefix::get() as u16 + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto_parachain::max_extrinsic_weight() + } + + fn encode_message( + _message: encode_message::MessagePayload, + ) -> Result { + Err("Not supported".into()) + } +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 97998a33d35bf..b50fd20ea94fd 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -32,6 +32,7 @@ pub(crate) mod send_message; mod derive_account; mod init_bridge; +mod register_parachain; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; @@ -93,6 +94,8 @@ pub enum Command { ResubmitTransactions(resubmit_transactions::ResubmitTransactions), /// Swap tokens using token-swap bridge. SwapTokens(swap_tokens::SwapTokens), + /// Register parachain. + RegisterParachain(register_parachain::RegisterParachain), } impl Command { @@ -128,6 +131,7 @@ impl Command { Self::DeriveAccount(arg) => arg.run().await?, Self::ResubmitTransactions(arg) => arg.run().await?, Self::SwapTokens(arg) => arg.run().await?, + Self::RegisterParachain(arg) => arg.run().await?, } Ok(()) } @@ -438,6 +442,7 @@ macro_rules! declare_chain_options { } /// Parse signing params into chain-specific KeyPair. + #[allow(dead_code)] pub fn to_keypair(&self) -> anyhow::Result { let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { (Some(suri), _) => suri.to_owned(), @@ -515,6 +520,8 @@ macro_rules! declare_chain_options { declare_chain_options!(Source, source); declare_chain_options!(Target, target); +declare_chain_options!(Relaychain, relaychain); +declare_chain_options!(Parachain, parachain); #[cfg(test)] mod tests { diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs new file mode 100644 index 0000000000000..00e98e419e5b7 --- /dev/null +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -0,0 +1,343 @@ +// 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 . + +use crate::cli::{ + swap_tokens::wait_until_transaction_is_finalized, Balance, ParachainConnectionParams, + RelaychainConnectionParams, RelaychainSigningParams, +}; + +use codec::Encode; +use num_traits::Zero; +use polkadot_parachain::primitives::{ + HeadData as ParaHeadData, Id as ParaId, ValidationCode as ParaValidationCode, +}; +use polkadot_runtime_common::{ + paras_registrar::Call as ParaRegistrarCall, slots::Call as ParaSlotsCall, +}; +use polkadot_runtime_parachains::paras::ParaLifecycle; +use relay_substrate_client::{ + AccountIdOf, CallOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, +}; +use rialto_runtime::SudoCall; +use sp_core::{ + storage::{well_known_keys::CODE, StorageKey}, + Bytes, Pair, +}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; + +/// Name of the `NextFreeParaId` value in the `polkadot_runtime_common::paras_registrar` pallet. +const NEXT_FREE_PARA_ID_STORAGE_NAME: &str = "NextFreeParaId"; +/// Name of the `ParaLifecycles` map in the `polkadot_runtime_parachains::paras` pallet. +const PARAS_LIFECYCLES_STORAGE_NAME: &str = "ParaLifecycles"; + +/// Register parachain. +#[derive(StructOpt, Debug, PartialEq)] +pub struct RegisterParachain { + /// A parachain to register. + #[structopt(possible_values = Parachain::VARIANTS, case_insensitive = true)] + parachain: Parachain, + /// Parachain deposit. + #[structopt(long, default_value = "0")] + deposit: Balance, + /// Lease begin. + #[structopt(long, default_value = "0")] + lease_begin: u32, + /// Lease end. + #[structopt(long, default_value = "256")] + lease_end: u32, + #[structopt(flatten)] + relay_connection: RelaychainConnectionParams, + #[structopt(flatten)] + relay_sign: RelaychainSigningParams, + #[structopt(flatten)] + para_connection: ParachainConnectionParams, +} + +/// Parachain to register. +#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] +#[strum(serialize_all = "kebab_case")] +pub enum Parachain { + RialtoParachain, +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + Parachain::RialtoParachain => { + type Relaychain = relay_rialto_client::Rialto; + type Parachain = relay_rialto_parachain_client::RialtoParachain; + + use bp_rialto::{PARAS_PALLET_NAME, PARAS_REGISTRAR_PALLET_NAME}; + + $generic + }, + } + }; +} + +impl RegisterParachain { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.parachain, { + let relay_client = self.relay_connection.to_client::().await?; + let relay_sign = self.relay_sign.to_keypair::()?; + let para_client = self.para_connection.to_client::().await?; + + // hopefully we're the only actor that is registering parachain right now + // => read next parachain id + let para_id_key = bp_runtime::storage_value_final_key( + PARAS_REGISTRAR_PALLET_NAME.as_bytes(), + NEXT_FREE_PARA_ID_STORAGE_NAME.as_bytes(), + ); + let para_id: ParaId = relay_client + .storage_value(StorageKey(para_id_key.to_vec()), None) + .await? + .unwrap_or(polkadot_primitives::v1::LOWEST_PUBLIC_ID) + .max(polkadot_primitives::v1::LOWEST_PUBLIC_ID); + log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); + + // step 1: reserve a parachain id + let relay_genesis_hash = *relay_client.genesis_hash(); + let relay_sudo_account: AccountIdOf = relay_sign.public().clone().into(); + let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve().into(); + let reserve_parachain_signer = relay_sign.clone(); + wait_until_transaction_is_finalized::( + relay_client + .submit_and_watch_signed_extrinsic( + relay_sudo_account.clone(), + move |_, transaction_nonce| { + Bytes( + Relaychain::sign_transaction( + relay_genesis_hash, + &reserve_parachain_signer, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + reserve_parachain_id_call, + transaction_nonce, + ), + ) + .encode(), + ) + }, + ) + .await?, + ) + .await?; + log::info!(target: "bridge", "Reserved parachain id: {:?}", para_id); + + // step 2: register parathread + let para_genesis_header = para_client.header_by_number(Zero::zero()).await?; + let para_code = para_client + .raw_storage_value(StorageKey(CODE.to_vec()), Some(para_genesis_header.hash())) + .await? + .ok_or_else(|| { + anyhow::format_err!("Cannot fetch validation code of {}", Parachain::NAME) + })? + .0; + log::info!( + target: "bridge", + "Going to register parachain {:?}: genesis len = {} code len = {}", + para_id, + para_genesis_header.encode().len(), + para_code.len(), + ); + let register_parathread_call: CallOf = ParaRegistrarCall::register( + para_id, + ParaHeadData(para_genesis_header.encode()), + ParaValidationCode(para_code), + ) + .into(); + let register_parathread_signer = relay_sign.clone(); + wait_until_transaction_is_finalized::( + relay_client + .submit_and_watch_signed_extrinsic( + relay_sudo_account.clone(), + move |_, transaction_nonce| { + Bytes( + Relaychain::sign_transaction( + relay_genesis_hash, + ®ister_parathread_signer, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new( + register_parathread_call, + transaction_nonce, + ), + ) + .encode(), + ) + }, + ) + .await?, + ) + .await?; + log::info!(target: "bridge", "Registered parachain: {:?}. Waiting for onboarding", para_id); + + // wait until parathread is onboarded + let para_state_key = bp_runtime::storage_map_final_key_twox64_concat( + PARAS_PALLET_NAME, + PARAS_LIFECYCLES_STORAGE_NAME, + ¶_id.encode(), + ); + wait_para_state( + &relay_client, + ¶_state_key.0, + &[ParaLifecycle::Onboarding, ParaLifecycle::Parathread], + ParaLifecycle::Parathread, + ) + .await?; + + // step 3: force parachain leases + let lease_begin = self.lease_begin; + let lease_end = self.lease_end; + let para_deposit = self.deposit.cast().into(); + log::info!( + target: "bridge", + "Going to force leases of parachain {:?}: [{}; {}]", + para_id, + lease_begin, + lease_end, + ); + let force_lease_call: CallOf = SudoCall::sudo(Box::new( + ParaSlotsCall::force_lease( + para_id, + relay_sudo_account.clone(), + para_deposit, + lease_begin, + lease_end, + ) + .into(), + )) + .into(); + let force_lease_signer = relay_sign.clone(); + relay_client + .submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { + Bytes( + Relaychain::sign_transaction( + relay_genesis_hash, + &force_lease_signer, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(force_lease_call, transaction_nonce), + ) + .encode(), + ) + }) + .await?; + log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); + + // wait until parachain is onboarded + wait_para_state( + &relay_client, + ¶_state_key.0, + &[ + ParaLifecycle::Onboarding, + ParaLifecycle::UpgradingParathread, + ParaLifecycle::Parathread, + ], + ParaLifecycle::Parachain, + ) + .await?; + + Ok(()) + }) + } +} + +/// Wait until parachain state is changed. +async fn wait_para_state( + relay_client: &Client, + para_state_key: &[u8], + from_states: &[ParaLifecycle], + to_state: ParaLifecycle, +) -> anyhow::Result<()> { + loop { + let para_state: ParaLifecycle = relay_client + .storage_value(StorageKey(para_state_key.to_vec()), None) + .await? + .ok_or_else(|| { + anyhow::format_err!( + "Cannot fetch next free parachain lifecycle from the runtime storage of {}", + Relaychain::NAME, + ) + })?; + if !from_states.contains(¶_state) { + return Err(anyhow::format_err!("Invalid parachain lifecycle: {:?}", para_state)) + } + if para_state == to_state { + log::info!(target: "bridge", "Parachain state is now: {:?}", to_state); + return Ok(()) + } + + log::info!(target: "bridge", "Parachain state: {:?}. Waiting for {:?}", para_state, to_state); + async_std::task::sleep(Relaychain::AVERAGE_BLOCK_INTERVAL).await; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn register_rialto_parachain() { + let register_parachain = RegisterParachain::from_iter(vec![ + "register-parachain", + "rialto-parachain", + "--parachain-host", + "127.0.0.1", + "--parachain-port", + "11949", + "--relaychain-host", + "127.0.0.1", + "--relaychain-port", + "9944", + "--relaychain-signer", + "//Alice", + "--deposit", + "42", + "--lease-begin", + "100", + "--lease-end", + "200", + ]); + + assert_eq!( + register_parachain, + RegisterParachain { + parachain: Parachain::RialtoParachain, + deposit: Balance(42), + lease_begin: 100, + lease_end: 200, + relay_connection: RelaychainConnectionParams { + relaychain_host: "127.0.0.1".into(), + relaychain_port: 9944, + relaychain_secure: false, + }, + relay_sign: RelaychainSigningParams { + relaychain_signer: Some("//Alice".into()), + relaychain_signer_password: None, + relaychain_signer_file: None, + relaychain_signer_password_file: None, + relaychain_transactions_mortality: None, + }, + para_connection: ParachainConnectionParams { + parachain_host: "127.0.0.1".into(), + parachain_port: 11949, + parachain_secure: false, + }, + } + ); + } +} diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 7d7d7ce56e64b..01eb3fbb4f528 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -570,7 +570,7 @@ async fn read_account_balance( /// Wait until transaction is included into finalized block. /// /// Returns the hash of the finalized block with transaction. -async fn wait_until_transaction_is_finalized( +pub(crate) async fn wait_until_transaction_is_finalized( subscription: Subscription>, ) -> anyhow::Result> { loop { diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml new file mode 100644 index 0000000000000..e4518c6877652 --- /dev/null +++ b/relays/client-rialto-parachain/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "relay-rialto-parachain-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + +# Bridge dependencies + +bp-rialto = { path = "../../primitives/chain-rialto" } +rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } + +# Substrate Dependencies + +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs new file mode 100644 index 0000000000000..ca299a0eeb78b --- /dev/null +++ b/relays/client-rialto-parachain/src/lib.rs @@ -0,0 +1,51 @@ +// 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 . + +//! Types used to connect to the Rialto-Substrate chain. + +use relay_substrate_client::{Chain, ChainBase}; +use std::time::Duration; + +/// Rialto header id. +pub type HeaderId = + relay_utils::HeaderId; + +/// Rialto parachain definition +#[derive(Debug, Clone, Copy)] +pub struct RialtoParachain; + +impl ChainBase for RialtoParachain { + type BlockNumber = rialto_parachain_runtime::BlockNumber; + type Hash = rialto_parachain_runtime::Hash; + type Hasher = rialto_parachain_runtime::Hashing; + type Header = rialto_parachain_runtime::Header; + + type AccountId = rialto_parachain_runtime::AccountId; + type Balance = rialto_parachain_runtime::Balance; + type Index = rialto_parachain_runtime::Index; + type Signature = rialto_parachain_runtime::Signature; +} + +impl Chain for RialtoParachain { + const NAME: &'static str = "RialtoParachain"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); + const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; + + type SignedBlock = rialto_parachain_runtime::SignedBlock; + type Call = rialto_parachain_runtime::Call; + type WeightToFee = bp_rialto::WeightToFee; +} diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index fd69dd255e6da..1902875c93810 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -38,7 +38,10 @@ use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; -use sp_core::{storage::StorageKey, Bytes, Hasher}; +use sp_core::{ + storage::{StorageData, StorageKey}, + Bytes, Hasher, +}; use sp_runtime::{ traits::Header as HeaderT, transaction_validity::{TransactionSource, TransactionValidity}, @@ -269,13 +272,22 @@ impl Client { storage_key: StorageKey, block_hash: Option, ) -> Result> { + self.raw_storage_value(storage_key, block_hash) + .await? + .map(|encoded_value| { + T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed) + }) + .transpose() + } + + /// Read raw value from runtime storage. + pub async fn raw_storage_value( + &self, + storage_key: StorageKey, + block_hash: Option, + ) -> Result> { self.jsonrpsee_execute(move |client| async move { - Substrate::::state_get_storage(&*client, storage_key, block_hash) - .await? - .map(|encoded_value| { - T::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed) - }) - .transpose() + Ok(Substrate::::state_get_storage(&*client, storage_key, block_hash).await?) }) .await } From 31e4000e2424581f70c8de3fa86a8159c2bf6c80 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 11 Oct 2021 17:20:08 +0300 Subject: [PATCH 0585/1210] fix checks order when registering parachain (#1177) --- relays/bin-substrate/src/cli/register_parachain.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 00e98e419e5b7..4f15bbec86c00 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -273,13 +273,13 @@ async fn wait_para_state( Relaychain::NAME, ) })?; - if !from_states.contains(¶_state) { - return Err(anyhow::format_err!("Invalid parachain lifecycle: {:?}", para_state)) - } if para_state == to_state { log::info!(target: "bridge", "Parachain state is now: {:?}", to_state); return Ok(()) } + if !from_states.contains(¶_state) { + return Err(anyhow::format_err!("Invalid parachain lifecycle: {:?}", para_state)) + } log::info!(target: "bridge", "Parachain state: {:?}. Waiting for {:?}", para_state, to_state); async_std::task::sleep(Relaychain::AVERAGE_BLOCK_INTERVAL).await; From 1599b4dd37e899db81de22bcf8d46c8c5a1fc722 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 15 Oct 2021 10:42:55 +0300 Subject: [PATCH 0586/1210] Resubmit transactions strategy for Polkadot/Kusama (#1175) * resubmit strategy for Polkadot/Kusama * spellcheck * fmt --- .../src/cli/resubmit_transactions.rs | 279 +++++++++++++++--- 1 file changed, 230 insertions(+), 49 deletions(-) diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 03a9c114b0b12..d20cff17f6331 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{TargetConnectionParams, TargetSigningParams}; +use crate::cli::{Balance, TargetConnectionParams, TargetSigningParams}; use codec::{Decode, Encode}; use num_traits::{One, Zero}; use relay_substrate_client::{ - BlockWithJustification, Chain, Client, Error as SubstrateError, TransactionSignScheme, + BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderOf, TransactionSignScheme, }; use relay_utils::FailedClient; use sp_core::Bytes; @@ -40,6 +40,19 @@ pub struct ResubmitTransactions { target: TargetConnectionParams, #[structopt(flatten)] target_sign: TargetSigningParams, + /// Number of blocks we see before considering queued transaction as stalled. + #[structopt(long, default_value = "5")] + stalled_blocks: u32, + /// Tip limit. We'll never submit transaction with larger tip. + #[structopt(long)] + tip_limit: Balance, + /// Tip increase step. We'll be checking updated transaction priority by increasing its tip by + /// this step. + #[structopt(long)] + tip_step: Balance, + /// Priority selection strategy. + #[structopt(subcommand)] + strategy: PrioritySelectionStrategy, } /// Chain, which transactions we're going to track && resubmit. @@ -47,6 +60,28 @@ pub struct ResubmitTransactions { #[strum(serialize_all = "kebab_case")] pub enum RelayChain { Millau, + Kusama, + Polkadot, +} + +/// Strategy to use for priority selection. +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] +pub enum PrioritySelectionStrategy { + /// Strategy selects tip that changes transaction priority to be better than priority of + /// the first transaction of previous block. + /// + /// It only makes sense to use this strategy for Millau transactions. Millau has transactions + /// that are close to block limits, so if there are any other queued transactions, 'large' + /// transaction won't fit the block && will be postponed. To avoid this, we change its priority + /// to some large value, making it best transaction => it'll be 'mined' first. + MakeItBestTransaction, + /// Strategy selects tip that changes transaction priority to be better than priority of + /// selected queued transaction. + /// + /// When we first see stalled transaction, we make it better than worst 1/4 of queued + /// transactions. If it is still stalled, we'll make it better than 1/3 of queued transactions, + /// ... + MakeItBetterThanQueuedTransaction, } macro_rules! select_bridge { @@ -56,20 +91,17 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type TargetSign = relay_millau_client::Millau; - // When large message is being sent from Millau to Rialto AND other transactions are - // blocking it from being mined, we'll see something like this in logs: - // - // Millau transaction priority with tip=0: 17800827994. Target priority: - // 526186677695 - // - // So since fee multiplier in Millau is `1` and `WeightToFee` is `IdentityFee`, then - // we need tip around `526186677695 - 17800827994 = 508_385_849_701`. Let's round it - // up to `1_000_000_000_000`. - - const TIP_STEP: bp_millau::Balance = 1_000_000_000; - const TIP_LIMIT: bp_millau::Balance = 1_000_000_000_000; + $generic + }, + RelayChain::Kusama => { + type Target = relay_kusama_client::Kusama; + type TargetSign = relay_kusama_client::Kusama; - const STALLED_BLOCKS: bp_millau::BlockNumber = 5; + $generic + }, + RelayChain::Polkadot => { + type Target = relay_polkadot_client::Polkadot; + type TargetSign = relay_polkadot_client::Polkadot; $generic }, @@ -91,11 +123,20 @@ impl ResubmitTransactions { client, key_pair.clone(), Context { + strategy: self.strategy, + best_header: HeaderOf::::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), transaction: None, + resubmitted: 0, stalled_for: Zero::zero(), - stalled_for_limit: STALLED_BLOCKS, - tip_step: TIP_STEP, - tip_limit: TIP_LIMIT, + stalled_for_limit: self.stalled_blocks.into(), + tip_step: self.tip_step.cast().into(), + tip_limit: self.tip_limit.cast().into(), }, ) }) @@ -104,10 +145,32 @@ impl ResubmitTransactions { } } -#[derive(Debug, Default)] +impl PrioritySelectionStrategy { + /// Select target priority. + async fn select_target_priority>( + &self, + client: &Client, + context: &Context, + ) -> Result, SubstrateError> { + match *self { + PrioritySelectionStrategy::MakeItBestTransaction => + read_previous_block_best_priority::(client, context).await, + PrioritySelectionStrategy::MakeItBetterThanQueuedTransaction => + select_priority_from_queue::(client, context).await, + } + } +} + +#[derive(Debug)] struct Context { + /// Priority selection strategy. + strategy: PrioritySelectionStrategy, + /// Best known block header. + best_header: C::Header, /// Hash of the (potentially) stalled transaction. transaction: Option, + /// How many times we have resubmitted this `transaction`? + resubmitted: u32, /// This transaction is in pool for `stalled_for` wakeup intervals. stalled_for: C::BlockNumber, /// When `stalled_for` reaching this limit, transaction is considered stalled. @@ -124,10 +187,11 @@ impl Context { self.stalled_for >= self.stalled_for_limit } - /// Forget stalled transaction. - fn clear(mut self) -> Self { - self.transaction = None; + /// Notice resubmitted transaction. + fn notice_resubmitted_transaction(mut self, transaction: C::Hash) -> Self { + self.transaction = Some(transaction); self.stalled_for = Zero::zero(); + self.resubmitted += 1; self } @@ -138,6 +202,7 @@ impl Context { } else { self.transaction = Some(transaction); self.stalled_for = One::one(); + self.resubmitted = 0; } self } @@ -172,8 +237,12 @@ async fn run_until_connection_lost async fn run_loop_iteration>( client: Client, key_pair: S::AccountKeyPair, - context: Context, + mut context: Context, ) -> Result, SubstrateError> { + // correct best header is required for all other actions + context.best_header = client.best_header().await?; + + // check if there's queued transaction, signed by given author let original_transaction = match lookup_signer_transaction::(&client, &key_pair).await? { Some(original_transaction) => original_transaction, None => { @@ -184,6 +253,7 @@ async fn run_loop_iteration>( let original_transaction_hash = C::Hasher::hash(&original_transaction.encode()); let context = context.notice_transaction(original_transaction_hash); + // if transaction hasn't been mined for `stalled_blocks`, we'll need to resubmit it if !context.is_stalled() { log::trace!( target: "bridge", @@ -196,18 +266,21 @@ async fn run_loop_iteration>( return Ok(context) } - let (best_block, target_priority) = match read_previous_best_priority::(&client).await? { - Some((best_block, target_priority)) => (best_block, target_priority), - None => { - log::trace!(target: "bridge", "Failed to read priority of best {} transaction in its best block", C::NAME); - return Ok(context) - }, - }; + // select priority for updated transaction + let target_priority = + match context.strategy.select_target_priority::(&client, &context).await? { + Some(target_priority) => target_priority, + None => { + log::trace!(target: "bridge", "Failed to select target priority"); + return Ok(context) + }, + }; - let (is_updated, updated_transaction) = select_transaction_tip::( + // update transaction tip + let (is_updated, updated_transaction) = update_transaction_tip::( &client, &key_pair, - best_block, + context.best_header.hash(), original_transaction, context.tip_step, context.tip_limit, @@ -232,7 +305,7 @@ async fn run_loop_iteration>( updated_transaction_hash, ); - Ok(context.clear()) + Ok(context.notice_resubmitted_transaction(updated_transaction_hash)) } /// Search transaction pool for transaction, signed by given key pair. @@ -255,31 +328,73 @@ async fn lookup_signer_transaction } /// Read priority of best signed transaction of previous block. -async fn read_previous_best_priority>( +async fn read_previous_block_best_priority>( client: &Client, -) -> Result, SubstrateError> { - let best_header = client.best_header().await?; - let best_header_hash = best_header.hash(); - let best_block = client.get_block(Some(best_header_hash)).await?; + context: &Context, +) -> Result, SubstrateError> { + let best_block = client.get_block(Some(context.best_header.hash())).await?; let best_transaction = best_block .extrinsics() .iter() .filter_map(|xt| S::SignedTransaction::decode(&mut &xt[..]).ok()) .find(|xt| S::is_signed(xt)); match best_transaction { - Some(best_transaction) => Ok(Some(( - best_header_hash, + Some(best_transaction) => Ok(Some( client - .validate_transaction(*best_header.parent_hash(), best_transaction) + .validate_transaction(*context.best_header.parent_hash(), best_transaction) .await?? .priority, - ))), + )), None => Ok(None), } } +/// Select priority of some queued transaction. +async fn select_priority_from_queue>( + client: &Client, + context: &Context, +) -> Result, SubstrateError> { + // select transaction from the queue + let queued_transactions = client.pending_extrinsics().await?; + let selected_transaction = match select_transaction_from_queue(queued_transactions, context) { + Some(selected_transaction) => selected_transaction, + None => return Ok(None), + }; + + let selected_transaction = S::SignedTransaction::decode(&mut &selected_transaction[..]) + .map_err(SubstrateError::ResponseParseFailed)?; + let target_priority = client + .validate_transaction(context.best_header.hash(), selected_transaction) + .await?? + .priority; + Ok(Some(target_priority)) +} + +/// Select transaction with target priority from the vec of queued transactions. +fn select_transaction_from_queue( + mut queued_transactions: Vec, + context: &Context, +) -> Option { + if queued_transactions.is_empty() { + return None + } + + // the more times we resubmit transaction (`context.resubmitted`), the closer we move + // to the front of the transaction queue + let total_transactions = queued_transactions.len(); + let resubmitted_factor = context.resubmitted; + let divisor = + 1usize.saturating_add(1usize.checked_shl(resubmitted_factor).unwrap_or(usize::MAX)); + let transactions_to_skip = total_transactions / divisor; + + Some( + queued_transactions + .swap_remove(std::cmp::min(total_transactions - 1, transactions_to_skip)), + ) +} + /// Try to find appropriate tip for transaction so that its priority is larger than given. -async fn select_transaction_tip>( +async fn update_transaction_tip>( client: &Client, key_pair: &S::AccountKeyPair, at_block: C::Hash, @@ -347,31 +462,97 @@ async fn select_transaction_tip>( #[cfg(test)] mod tests { use super::*; + use bp_rialto::Hash; use relay_rialto_client::Rialto; - #[test] - fn context_works() { - let mut context: Context = Context { + fn context() -> Context { + Context { + strategy: PrioritySelectionStrategy::MakeItBestTransaction, + best_header: HeaderOf::::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), transaction: None, + resubmitted: 0, stalled_for: Zero::zero(), stalled_for_limit: 3, tip_step: 100, tip_limit: 1000, - }; + } + } + + #[test] + fn context_works() { + let mut context = context(); // when transaction is noticed 2/3 times, it isn't stalled context = context.notice_transaction(Default::default()); assert!(!context.is_stalled()); + assert_eq!(context.stalled_for, 1); + assert_eq!(context.resubmitted, 0); context = context.notice_transaction(Default::default()); assert!(!context.is_stalled()); + assert_eq!(context.stalled_for, 2); + assert_eq!(context.resubmitted, 0); // when transaction is noticed for 3rd time in a row, it is considered stalled context = context.notice_transaction(Default::default()); assert!(context.is_stalled()); + assert_eq!(context.stalled_for, 3); + assert_eq!(context.resubmitted, 0); // and after we resubmit it, we forget previous transaction - context = context.clear(); - assert_eq!(context.transaction, None); + context = context.notice_resubmitted_transaction(Hash::from([1; 32])); + assert_eq!(context.transaction, Some(Hash::from([1; 32]))); + assert_eq!(context.resubmitted, 1); assert_eq!(context.stalled_for, 0); } + + #[test] + fn select_transaction_from_queue_works_with_empty_queue() { + assert_eq!(select_transaction_from_queue(vec![], &context()), None); + } + + #[test] + fn select_transaction_from_queue_works() { + let mut context = context(); + let queued_transactions = vec![ + Bytes(vec![1]), + Bytes(vec![2]), + Bytes(vec![3]), + Bytes(vec![4]), + Bytes(vec![5]), + Bytes(vec![6]), + ]; + + // when we resubmit tx for the first time, 1/2 of queue is skipped + assert_eq!( + select_transaction_from_queue(queued_transactions.clone(), &context), + Some(Bytes(vec![4])), + ); + + // when we resubmit tx for the second time, 1/3 of queue is skipped + context = context.notice_resubmitted_transaction(Hash::from([1; 32])); + assert_eq!( + select_transaction_from_queue(queued_transactions.clone(), &context), + Some(Bytes(vec![3])), + ); + + // when we resubmit tx for the third time, 1/5 of queue is skipped + context = context.notice_resubmitted_transaction(Hash::from([2; 32])); + assert_eq!( + select_transaction_from_queue(queued_transactions.clone(), &context), + Some(Bytes(vec![2])), + ); + + // when we resubmit tx for the second time, 1/9 of queue is skipped + context = context.notice_resubmitted_transaction(Hash::from([3; 32])); + assert_eq!( + select_transaction_from_queue(queued_transactions.clone(), &context), + Some(Bytes(vec![1])), + ); + } } From 86bb56e43839a258ab64e8bea8e1eb361009de72 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Sat, 16 Oct 2021 12:57:44 +0300 Subject: [PATCH 0587/1210] additional log in finality relay + rephrase "failed" (#1182) --- relays/finality/src/finality_loop.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index adfd3927de898..c64c9d629bf05 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -484,6 +484,14 @@ pub(crate) async fn read_missing_headers< header_number = header_number + One::one(); } + log::trace!( + target: "bridge", + "Read {} {} headers. Selected finality proof for header: {:?}", + best_number_at_source.saturating_sub(best_number_at_target), + P::SOURCE_NAME, + selected_finality_proof.as_ref().map(|(header, _)| header), + ); + Ok(match selected_finality_proof { Some((header, proof)) => SelectedFinalityProof::Regular(unjustified_headers, header, proof), None => SelectedFinalityProof::None(unjustified_headers), @@ -584,7 +592,7 @@ pub(crate) fn select_better_recent_finality_proof( buffered_range_begin, buffered_range_end, selected_header_number, - if has_selected_finality_proof { "improved" } else { "failed" }, + if has_selected_finality_proof { "improved" } else { "not improved" }, ); if !has_selected_finality_proof { return selected_finality_proof From 1c163122bb11c996ade5c447ee8474b80098c408 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 18 Oct 2021 11:51:19 +0300 Subject: [PATCH 0588/1210] fix/ignore cargo deny issues (#1183) --- bin/rialto/runtime/Cargo.toml | 4 ++-- bin/rialto/runtime/src/exchange.rs | 2 +- modules/ethereum/Cargo.toml | 4 ++-- modules/ethereum/src/import.rs | 2 +- modules/ethereum/src/mock.rs | 2 +- modules/ethereum/src/test_utils.rs | 2 +- modules/ethereum/src/verification.rs | 2 +- primitives/ethereum-poa/Cargo.toml | 2 +- primitives/ethereum-poa/src/signatures.rs | 6 +++--- relays/bin-ethereum/Cargo.toml | 2 +- relays/bin-ethereum/src/main.rs | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/bin-substrate/src/cli/mod.rs | 2 +- relays/client-ethereum/Cargo.toml | 2 +- relays/client-ethereum/src/sign.rs | 2 +- 15 files changed, 19 insertions(+), 19 deletions(-) diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 8f4f4ef30e7ab..d44d8797e34f8 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } hex-literal = "0.3" -libsecp256k1 = { version = "0.3.4", optional = true, default-features = false, features = ["hmac"] } +libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true, features = ["derive"] } @@ -72,7 +72,7 @@ polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", bran polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] -libsecp256k1 = { version = "0.3.4", features = ["hmac"] } +libsecp256k1 = { version = "0.7", features = ["hmac"] } [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index 9f34707848fea..f940287ff76a2 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -162,7 +162,7 @@ pub(crate) fn prepare_ethereum_transaction( // chain id is 0x11 // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 let chain_id = 0x11; - let signer = secp256k1::SecretKey::parse(&hex!( + let signer = libsecp256k1::SecretKey::parse(&hex!( "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" )) .unwrap(); diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index 275747eb329a0..ce890fa2abb78 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"], optional = true } +libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"], optional = true } log = { version = "0.4.14", default-features = false } serde = { version = "1.0", optional = true } @@ -26,7 +26,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -libsecp256k1 = { version = "0.3.4", features = ["hmac"] } +libsecp256k1 = { version = "0.7", features = ["hmac"] } hex-literal = "0.3" [features] diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs index 31e8642d51096..3777432457770 100644 --- a/modules/ethereum/src/import.rs +++ b/modules/ethereum/src/import.rs @@ -180,7 +180,7 @@ mod tests { validators::ValidatorsSource, BlocksToPrune, BridgeStorage, Headers, PruningRange, }; - use secp256k1::SecretKey; + use libsecp256k1::SecretKey; const TOTAL_VALIDATORS: usize = 3; diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs index e0439444020c7..877f7a9dc11f8 100644 --- a/modules/ethereum/src/mock.rs +++ b/modules/ethereum/src/mock.rs @@ -28,7 +28,7 @@ use crate::{ }; use bp_eth_poa::{Address, AuraHeader, H256, U256}; use frame_support::{parameter_types, traits::GenesisBuild, weights::Weight}; -use secp256k1::SecretKey; +use libsecp256k1::SecretKey; use sp_runtime::{ testing::Header as SubstrateHeader, traits::{BlakeTwo256, IdentityLookup}, diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs index 343c7b1cb3646..414445f3aaccb 100644 --- a/modules/ethereum/src/test_utils.rs +++ b/modules/ethereum/src/test_utils.rs @@ -34,7 +34,7 @@ use bp_eth_poa::{ signatures::{secret_to_address, sign, SignHeader}, Address, AuraHeader, Bloom, Receipt, SealedEmptyStep, H256, U256, }; -use secp256k1::SecretKey; +use libsecp256k1::SecretKey; use sp_std::prelude::*; /// Gas limit valid in test environment. diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index af7b33fc80bbb..c708a6ba2d0b3 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -401,7 +401,7 @@ mod tests { }; use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256}; use hex_literal::hex; - use secp256k1::SecretKey; + use libsecp256k1::SecretKey; use sp_runtime::transaction_validity::TransactionTag; const GENESIS_STEP: u64 = 42; diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index 5843b041c5708..e7acd80eff23d 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -13,7 +13,7 @@ fixed-hash = { version = "0.7", default-features = false } hash-db = { version = "0.15.2", default-features = false } impl-rlp = { version = "0.3", default-features = false } impl-serde = { version = "0.3.1", optional = true } -libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } +libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"] } parity-bytes = { version = "0.1", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } primitive-types = { version = "0.10", default-features = false, features = ["codec", "rlp"] } diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs index aaa5a980b2e20..26371f2166ad5 100644 --- a/primitives/ethereum-poa/src/signatures.rs +++ b/primitives/ethereum-poa/src/signatures.rs @@ -20,14 +20,14 @@ //! Used for testing and benchmarking. // reexport to avoid direct secp256k1 deps by other crates -pub use secp256k1::SecretKey; +pub use libsecp256k1::SecretKey; use crate::{ public_to_address, rlp_encode, step_validator, Address, AuraHeader, RawTransaction, UnsignedTransaction, H256, H520, U256, }; -use secp256k1::{Message, PublicKey}; +use libsecp256k1::{Message, PublicKey}; /// Utilities for signing headers. pub trait SignHeader { @@ -81,7 +81,7 @@ impl SignTransaction for UnsignedTransaction { /// Return author's signature over given message. pub fn sign(author: &SecretKey, message: H256) -> H520 { let (signature, recovery_id) = - secp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); + libsecp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); let mut raw_signature = [0u8; 65]; raw_signature[..64].copy_from_slice(&signature.serialize()); raw_signature[64] = recovery_id.serialize(); diff --git a/relays/bin-ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml index baf927b42a4f6..080608a26f8c6 100644 --- a/relays/bin-ethereum/Cargo.toml +++ b/relays/bin-ethereum/Cargo.toml @@ -17,7 +17,7 @@ ethabi-derive = { git = "https://github.com/svyatonik/ethabi.git", branch = "bum futures = "0.3.12" hex = "0.4" hex-literal = "0.3" -libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } +libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"] } log = "0.4.14" num-traits = "0.2" serde_json = "1.0.64" diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index cb64dc40d935e..86b749872913e 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -34,11 +34,11 @@ use ethereum_sync_loop::EthereumSyncParams; use headers_relay::sync::TargetTransactionMode; use hex_literal::hex; use instances::{BridgeInstance, Kovan, RialtoPoA}; +use libsecp256k1::SecretKey; use relay_utils::{ initialize::initialize_relay, metrics::{MetricsAddress, MetricsParams}, }; -use secp256k1::SecretKey; use sp_core::crypto::Pair; use substrate_sync_loop::SubstrateSyncParams; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 0f9e2792139fa..a28c61262f403 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -75,5 +75,5 @@ polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -tempdir = "0.3" +tempfile = "3.2" finality-grandpa = { version = "0.14.0" } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index b50fd20ea94fd..c35c2b87dd8fb 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -573,7 +573,7 @@ mod tests { let bob_with_alice_password = sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); - let temp_dir = tempdir::TempDir::new("reads_suri_from_file").unwrap(); + let temp_dir = tempfile::tempdir().unwrap(); let mut suri_file_path = temp_dir.path().to_path_buf(); let mut password_file_path = temp_dir.path().to_path_buf(); suri_file_path.push("suri"); diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 6d56eb94dbd71..4263055d01b4e 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -12,7 +12,7 @@ headers-relay = { path = "../headers" } hex-literal = "0.3" jsonrpsee-proc-macros = "0.3.1" jsonrpsee-ws-client = "0.3.1" -libsecp256k1 = { version = "0.3.4", default-features = false, features = ["hmac"] } +libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"] } log = "0.4.11" relay-utils = { path = "../utils" } tokio = "1.8" diff --git a/relays/client-ethereum/src/sign.rs b/relays/client-ethereum/src/sign.rs index 0d9a8d032ee2e..86ddcc871c40e 100644 --- a/relays/client-ethereum/src/sign.rs +++ b/relays/client-ethereum/src/sign.rs @@ -20,7 +20,7 @@ use crate::{ }; use bp_eth_poa::signatures::{secret_to_address, SignTransaction}; use hex_literal::hex; -use secp256k1::SecretKey; +use libsecp256k1::SecretKey; /// Ethereum signing params. #[derive(Clone, Debug)] From 43942b57b991cbed1a5d9492f948f11361e59cbf Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 20 Oct 2021 14:56:13 +0300 Subject: [PATCH 0589/1210] replace collective flip with babe randomness in Rialto (#1188) * replace collective flip with babe randomness in Rialto * fmt * fix test --- bin/rialto/runtime/Cargo.toml | 2 -- bin/rialto/runtime/src/lib.rs | 3 --- bin/rialto/runtime/src/parachains.rs | 7 ++----- relays/bin-substrate/src/cli/encode_call.rs | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index d44d8797e34f8..8f532448d4080 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -43,7 +43,6 @@ pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -105,7 +104,6 @@ std = [ "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-grandpa/std", - "pallet-randomness-collective-flip/std", "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 90a4dbd5087e0..11e67c1f6267e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -216,8 +216,6 @@ impl frame_system::Config for Runtime { type OnSetCode = (); } -impl pallet_randomness_collective_flip::Config for Runtime {} - /// The BABE epoch configuration at genesis. pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = sp_consensus_babe::BabeEpochConfiguration { @@ -579,7 +577,6 @@ construct_runtime!( Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, // Eth-PoA chains bridge modules. BridgeRialtoPoa: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 20ce9c29ef2d1..a84723a725770 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -16,10 +16,7 @@ //! Parachains support in Rialto runtime. -use crate::{ - AccountId, Balance, Balances, BlockNumber, Event, Origin, RandomnessCollectiveFlip, Registrar, - Runtime, Slots, -}; +use crate::{AccountId, Balance, Balances, BlockNumber, Event, Origin, Registrar, Runtime, Slots}; use frame_support::{parameter_types, weights::Weight}; use frame_system::EnsureRoot; @@ -59,7 +56,7 @@ impl parachains_inclusion::Config for Runtime { } impl parachains_initializer::Config for Runtime { - type Randomness = RandomnessCollectiveFlip; + type Randomness = pallet_babe::RandomnessFromOneEpochAgo; type ForceOrigin = EnsureRoot; } diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 5973faab569e0..f496f78b29d2b 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -345,7 +345,7 @@ mod tests { // then assert!(format!("{:?}", call_hex).starts_with( - "0x11030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + "0x10030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" )) } From 41864de0a6675dbd043cc89945e4e7d54a51701f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 21 Oct 2021 15:29:49 +0300 Subject: [PATCH 0590/1210] Limit max call size of Rialto/Millau runtimes (#1187) * max call size <= 230 bytes * fix benchmarks --- bin/millau/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/lib.rs | 4 +- modules/ethereum/src/benchmarking.rs | 10 +- modules/ethereum/src/lib.rs | 6 +- modules/token-swap/src/benchmarking.rs | 35 ++-- modules/token-swap/src/lib.rs | 195 +++++++++----------- primitives/token-swap/Cargo.toml | 2 + primitives/token-swap/src/lib.rs | 26 ++- relays/bin-ethereum/src/instances.rs | 4 +- relays/bin-substrate/src/cli/swap_tokens.rs | 14 +- 10 files changed, 159 insertions(+), 141 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 161816c2d940e..4e43868fe86e3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -844,9 +844,7 @@ mod tests { #[test] fn call_size() { - // pallets that are (to be) used by polkadot runtime const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests - assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); - assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); + assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 11e67c1f6267e..9e70dae32efaa 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1447,9 +1447,7 @@ mod tests { #[test] fn call_size() { - // pallets that are (to be) used by polkadot runtime const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests - assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); - assert!(core::mem::size_of::>() <= MAX_CALL_SIZE); + assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs index 268795d8a8336..511cbcac1ade9 100644 --- a/modules/ethereum/src/benchmarking.rs +++ b/modules/ethereum/src/benchmarking.rs @@ -46,7 +46,7 @@ benchmarks_instance_pallet! { header }, ); - }: import_unsigned_header(RawOrigin::None, header, None) + }: import_unsigned_header(RawOrigin::None, Box::new(header), None) verify { let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, 1); @@ -91,7 +91,7 @@ benchmarks_instance_pallet! { // Need to make sure that the header we're going to import hasn't been inserted // into storage already let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); - }: import_unsigned_header(RawOrigin::None, header, None) + }: import_unsigned_header(RawOrigin::None, Box::new(header), None) verify { let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); @@ -132,7 +132,7 @@ benchmarks_instance_pallet! { // Need to make sure that the header we're going to import hasn't been inserted // into storage already let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); - }: import_unsigned_header(RawOrigin::None, header, None) + }: import_unsigned_header(RawOrigin::None, Box::new(header), None) verify { let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); @@ -167,7 +167,7 @@ benchmarks_instance_pallet! { } let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators); - }: import_unsigned_header(RawOrigin::None, header, None) + }: import_unsigned_header(RawOrigin::None, Box::new(header), None) verify { let storage = BridgeStorage::::new(); let max_pruned: u64 = (n - 1) as _; @@ -209,7 +209,7 @@ benchmarks_instance_pallet! { header }, ); - }: import_unsigned_header(RawOrigin::None, header, Some(receipts)) + }: import_unsigned_header(RawOrigin::None, Box::new(header), Some(receipts)) verify { let storage = BridgeStorage::::new(); assert_eq!(storage.best_block().0.number, 2); diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index 6234a02cca13d..ad2382a949001 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -25,7 +25,7 @@ use bp_eth_poa::{ use codec::{Decode, Encode}; use frame_support::traits::Get; use sp_runtime::RuntimeDebug; -use sp_std::{cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; +use sp_std::{boxed::Box, cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; pub use validators::{ValidatorsConfiguration, ValidatorsSource}; @@ -406,7 +406,7 @@ pub mod pallet { #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) pub fn import_unsigned_header( origin: OriginFor, - header: AuraHeader, + header: Box, receipts: Option>, ) -> DispatchResult { frame_system::ensure_none(origin)?; @@ -417,7 +417,7 @@ pub mod pallet { &T::AuraConfiguration::get(), &T::ValidatorsConfiguration::get(), None, - header, + *header, &T::ChainTime::default(), receipts, ) diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs index 0dd8922d157f4..bbc544a8b91df 100644 --- a/modules/token-swap/src/benchmarking.rs +++ b/modules/token-swap/src/benchmarking.rs @@ -18,10 +18,11 @@ use crate::{ swap_account_id, target_account_at_this_chain, BridgedAccountIdOf, BridgedAccountPublicOf, - BridgedAccountSignatureOf, BridgedBalanceOf, Call, Pallet, ThisChainBalance, TokenSwapOf, + BridgedAccountSignatureOf, BridgedBalanceOf, Call, Pallet, ThisChainBalance, + TokenSwapCreationOf, TokenSwapOf, }; -use bp_token_swap::{TokenSwap, TokenSwapState, TokenSwapType}; +use bp_token_swap::{TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType}; use codec::Encode; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Currency, Parameter}; @@ -62,21 +63,11 @@ benchmarks_instance_pallet! { let sender = funded_account::("source_account_at_this_chain", 0); let swap: TokenSwapOf = test_swap::(sender.clone(), true); - let target_public_at_bridged_chain = target_public_at_bridged_chain::(); - let swap_delivery_and_dispatch_fee = swap_delivery_and_dispatch_fee::(); - let bridged_chain_spec_version = 0; - let bridged_currency_transfer = Vec::new(); - let bridged_currency_transfer_weight = 0; - let bridged_currency_transfer_signature = bridged_currency_transfer_signature::(); + let swap_creation: TokenSwapCreationOf = test_swap_creation::(); }: create_swap( RawOrigin::Signed(sender.clone()), swap, - target_public_at_bridged_chain, - swap_delivery_and_dispatch_fee, - bridged_chain_spec_version, - bridged_currency_transfer, - bridged_currency_transfer_weight, - bridged_currency_transfer_signature + Box::new(swap_creation) ) verify { assert!(crate::PendingSwaps::::contains_key(test_swap_hash::(sender, true))); @@ -144,6 +135,22 @@ fn test_swap_hash, I: 'static>(sender: T::AccountId, is_create: boo test_swap::(sender, is_create).using_encoded(blake2_256).into() } +/// Returns test token swap creation params. +fn test_swap_creation, I: 'static>() -> TokenSwapCreationOf +where + BridgedAccountPublicOf: Default, + BridgedAccountSignatureOf: Default, +{ + TokenSwapCreation { + target_public_at_bridged_chain: target_public_at_bridged_chain::(), + swap_delivery_and_dispatch_fee: swap_delivery_and_dispatch_fee::(), + bridged_chain_spec_version: 0, + bridged_currency_transfer: Vec::new(), + bridged_currency_transfer_weight: 0, + bridged_currency_transfer_signature: bridged_currency_transfer_signature::(), + } +} + /// Account that has some balance. fn funded_account, I: 'static>(name: &'static str, index: u32) -> T::AccountId { let account: T::AccountId = account(name, index, SEED); diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 3a49d431c7786..60ca1221dd07e 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -23,29 +23,39 @@ //! There are four accounts participating in the swap: //! //! 1) account of This chain that has signed the `create_swap` transaction and has balance on This -//! chain. We'll be referring to this account as `source_account_at_this_chain`; +//! chain. We'll be referring to this account as `source_account_at_this_chain`; +//! //! 2) account of the Bridged chain that is sending the `claim_swap` message from the Bridged to -//! This chain. This account has balance on Bridged chain and is willing to swap these tokens to -//! This chain tokens of the `source_account_at_this_chain`. We'll be referring to this account -//! as `target_account_at_bridged_chain`; 3) account of the Bridged chain that is indirectly -//! controlled by the `source_account_at_this_chain`. We'll be referring this account as -//! `source_account_at_bridged_chain`; 4) account of This chain that is indirectly controlled by the -//! `target_account_at_bridged_chain`. We'll be referring this account as -//! `target_account_at_this_chain`. +//! This chain. This account has balance on Bridged chain and is willing to swap these tokens to +//! This chain tokens of the `source_account_at_this_chain`. We'll be referring to this account +//! as `target_account_at_bridged_chain`; +//! +//! 3) account of the Bridged chain that is indirectly controlled by the +//! `source_account_at_this_chain`. We'll be referring this account as +//! `source_account_at_bridged_chain`; +//! +//! 4) account of This chain that is indirectly controlled by the `target_account_at_bridged_chain`. +//! We'll be referring this account as `target_account_at_this_chain`. //! //! So the tokens swap is an intention of `source_account_at_this_chain` to swap his //! `source_balance_at_this_chain` tokens to the `target_balance_at_bridged_chain` tokens owned by //! `target_account_at_bridged_chain`. The swap process goes as follows: //! //! 1) the `source_account_at_this_chain` account submits the `create_swap` transaction on This -//! chain; 2) the tokens transfer message that would transfer `target_balance_at_bridged_chain` -//! tokens from the `target_account_at_bridged_chain` to the `source_account_at_bridged_chain`, -//! is sent over the bridge; 3) when transfer message is delivered and dispatched, the pallet -//! receives notification; 4) if message has been successfully dispatched, the -//! `target_account_at_bridged_chain` sends the message that would transfer -//! `source_balance_at_this_chain` tokens to his `target_account_at_this_chain` account; +//! chain; +//! +//! 2) the tokens transfer message that would transfer `target_balance_at_bridged_chain` +//! tokens from the `target_account_at_bridged_chain` to the `source_account_at_bridged_chain`, +//! is sent over the bridge; +//! +//! 3) when transfer message is delivered and dispatched, the pallet receives notification; +//! +//! 4) if message has been successfully dispatched, the `target_account_at_bridged_chain` sends the +//! message that would transfer `source_balance_at_this_chain` tokens to his +//! `target_account_at_this_chain` account; +//! //! 5) if message dispatch has failed, the `source_account_at_this_chain` may submit the -//! `cancel_swap` transaction and return his `source_balance_at_this_chain` back to his account. +//! `cancel_swap` transaction and return his `source_balance_at_this_chain` back to his account. //! //! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special //! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion. @@ -57,7 +67,9 @@ use bp_messages::{ DeliveredMessages, LaneId, MessageNonce, }; use bp_runtime::{messages::DispatchFeePayment, ChainId}; -use bp_token_swap::{TokenSwap, TokenSwapState, TokenSwapType}; +use bp_token_swap::{ + RawBridgedTransferCall, TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType, +}; use codec::Encode; use frame_support::{ fail, @@ -67,7 +79,7 @@ use frame_support::{ use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Convert, Saturating}; -use sp_std::vec::Vec; +use sp_std::boxed::Box; use weights::WeightInfo; pub use weights_ext::WeightInfoExt; @@ -146,8 +158,6 @@ pub mod pallet { /// Account signature type at the Bridged chain. pub type BridgedAccountSignatureOf = bp_runtime::SignatureOf>; - /// SCALE-encoded `Currency::transfer` call on the bridged chain. - pub type RawBridgedTransferCall = Vec; /// Bridge message payload used by the pallet. pub type MessagePayloadOf = bp_message_dispatch::MessagePayload< ::AccountId, @@ -163,6 +173,12 @@ pub mod pallet { BridgedBalanceOf, BridgedAccountIdOf, >; + /// Type of `TokenSwapCreation` used by the pallet. + pub type TokenSwapCreationOf = TokenSwapCreation< + BridgedAccountPublicOf, + ThisChainBalance, + BridgedAccountSignatureOf, + >; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -184,14 +200,7 @@ pub mod pallet { /// Method arguments are: /// /// - `swap` - token swap intention; - /// - `target_public_at_bridged_chain` - the public key of the - /// `swap.target_account_at_bridged_chain` account used to verify - /// `bridged_currency_transfer_signature`; - /// - `bridged_currency_transfer` - the SCALE-encoded tokens transfer call at the Bridged - /// chain; - /// - `bridged_currency_transfer_signature` - the signature of the - /// `swap.target_account_at_bridged_chain` for the message returned by the - /// `pallet_bridge_dispatch::account_ownership_digest()` function call. + /// - `swap_creation_params` - additional parameters required to start tokens swap. /// /// The `source_account_at_this_chain` MUST have enough balance to cover both token swap and /// message transfer. Message fee may be estimated using corresponding `OutboundLaneApi` of @@ -199,15 +208,20 @@ pub mod pallet { /// /// **WARNING**: the submitter of this transaction is responsible for verifying: /// - /// 1) that the `bridged_currency_transfer` represents a valid token transfer call that - /// transfers `swap.target_balance_at_bridged_chain` to his - /// `source_account_at_bridged_chain` account; 2) that either the - /// `source_account_at_bridged_chain` already exists, or the - /// `swap.target_balance_at_bridged_chain` is above existential deposit of the Bridged - /// chain; 3) the `target_public_at_bridged_chain` matches the - /// `swap.target_account_at_bridged_chain`; 4) the `bridged_currency_transfer_signature` is - /// valid and generated by the owner of the `target_public_at_bridged_chain` account - /// (read more about [`CallOrigin::TargetAccount`]). + /// 1) that the `swap_creation_params.bridged_currency_transfer` represents a valid token + /// transfer call that transfers `swap.target_balance_at_bridged_chain` to his + /// `swap.source_account_at_bridged_chain` account; + /// + /// 2) that either the `swap.source_account_at_bridged_chain` already exists, or the + /// `swap.target_balance_at_bridged_chain` is above existential deposit of the Bridged + /// chain; + /// + /// 3) the `swap_creation_params.target_public_at_bridged_chain` matches the + /// `swap.target_account_at_bridged_chain`; + /// + /// 4) the `bridged_currency_transfer_signature` is valid and generated by the owner of + /// the `swap_creation_params.target_public_at_bridged_chain` account (read more + /// about [`CallOrigin::TargetAccount`]). /// /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. /// Violating other rules will lead to losing message fees for this and other transactions + @@ -215,21 +229,24 @@ pub mod pallet { #[pallet::weight( T::WeightInfo::create_swap() .saturating_add(T::WeightInfo::send_message_weight( - &&bridged_currency_transfer[..], + &&swap_creation_params.bridged_currency_transfer[..], T::DbWeight::get(), )) )] - #[allow(clippy::too_many_arguments)] pub fn create_swap( origin: OriginFor, swap: TokenSwapOf, - target_public_at_bridged_chain: BridgedAccountPublicOf, - swap_delivery_and_dispatch_fee: ThisChainBalance, - bridged_chain_spec_version: u32, - bridged_currency_transfer: RawBridgedTransferCall, - bridged_currency_transfer_weight: Weight, - bridged_currency_transfer_signature: BridgedAccountSignatureOf, + swap_creation_params: Box>, ) -> DispatchResultWithPostInfo { + let TokenSwapCreation { + target_public_at_bridged_chain, + swap_delivery_and_dispatch_fee, + bridged_chain_spec_version, + bridged_currency_transfer, + bridged_currency_transfer_weight, + bridged_currency_transfer_signature, + } = *swap_creation_params; + // ensure that the `origin` is the same account that is mentioned in the `swap` // intention let origin_account = ensure_signed(origin)?; @@ -648,6 +665,17 @@ mod tests { } } + fn test_swap_creation() -> TokenSwapCreationOf { + TokenSwapCreation { + target_public_at_bridged_chain: bridged_chain_account_public(), + swap_delivery_and_dispatch_fee: SWAP_DELIVERY_AND_DISPATCH_FEE, + bridged_chain_spec_version: BRIDGED_CHAIN_SPEC_VERSION, + bridged_currency_transfer: test_transfer(), + bridged_currency_transfer_weight: BRIDGED_CHAIN_CALL_WEIGHT, + bridged_currency_transfer_signature: bridged_chain_account_signature(), + } + } + fn test_swap_hash() -> H256 { test_swap().using_encoded(blake2_256).into() } @@ -660,12 +688,14 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(TokenSwapCreation { + target_public_at_bridged_chain: bridged_chain_account_public(), + swap_delivery_and_dispatch_fee: SWAP_DELIVERY_AND_DISPATCH_FEE, + bridged_chain_spec_version: BRIDGED_CHAIN_SPEC_VERSION, + bridged_currency_transfer: test_transfer(), + bridged_currency_transfer_weight: BRIDGED_CHAIN_CALL_WEIGHT, + bridged_currency_transfer_signature: bridged_chain_account_signature(), + }), )); } @@ -683,12 +713,7 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), ), Error::::MismatchedSwapSourceOrigin ); @@ -704,12 +729,7 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), swap, - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), ), Error::::TooLowBalanceOnThisChain ); @@ -725,12 +745,7 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), swap, - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), ), Error::::FailedToTransferToSwapAccount ); @@ -742,16 +757,13 @@ mod tests { run_test(|| { let mut transfer = test_transfer(); transfer[0] = BAD_TRANSFER_CALL; + let mut swap_creation = test_swap_creation(); + swap_creation.bridged_currency_transfer = transfer; assert_noop!( Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - transfer, - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(swap_creation), ), Error::::FailedToSendTransferMessage ); @@ -764,24 +776,14 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), )); assert_noop!( Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), ), Error::::SwapAlreadyStarted ); @@ -796,12 +798,7 @@ mod tests { Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), ), Error::::SwapPeriodIsFinished ); @@ -815,12 +812,7 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), )); }); } @@ -834,12 +826,7 @@ mod tests { assert_ok!(Pallet::::create_swap( Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), - bridged_chain_account_public(), - SWAP_DELIVERY_AND_DISPATCH_FEE, - BRIDGED_CHAIN_SPEC_VERSION, - test_transfer(), - BRIDGED_CHAIN_CALL_WEIGHT, - bridged_chain_account_signature(), + Box::new(test_swap_creation()), )); let swap_hash = test_swap_hash(); diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 03f40438e0734..dd42f4e4a0c91 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -13,6 +13,7 @@ codec = { package = "parity-scale-codec", version = "2.0.0", default-features = 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -20,4 +21,5 @@ std = [ "codec/std", "frame-support/std", "sp-core/std", + "sp-std/std", ] diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index 336e3263f09d9..48aaeb38c3b4b 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -17,8 +17,9 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode}; -use frame_support::RuntimeDebug; +use frame_support::{weights::Weight, RuntimeDebug}; use sp_core::U256; +use sp_std::vec::Vec; /// Pending token swap state. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] @@ -82,3 +83,26 @@ pub struct TokenSwap; + +/// Token swap creation parameters. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct TokenSwapCreation { + /// Public key of the `target_account_at_bridged_chain` account used to verify + /// `bridged_currency_transfer_signature`. + pub target_public_at_bridged_chain: BridgedAccountPublic, + /// Fee that the `source_account_at_this_chain` is ready to pay for the tokens + /// transfer message delivery and dispatch. + pub swap_delivery_and_dispatch_fee: ThisChainBalance, + /// Specification version of the Bridged chain. + pub bridged_chain_spec_version: u32, + /// SCALE-encoded tokens transfer call at the Bridged chain. + pub bridged_currency_transfer: RawBridgedTransferCall, + /// Dispatch weight of the tokens transfer call at the Bridged chain. + pub bridged_currency_transfer_weight: Weight, + /// The signature of the `target_account_at_bridged_chain` for the message + /// returned by the `pallet_bridge_dispatch::account_ownership_digest()` function call. + pub bridged_currency_transfer_signature: BridgedAccountSignature, +} diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs index 90d736fa251d7..3f2ebf825be77 100644 --- a/relays/bin-ethereum/src/instances.rs +++ b/relays/bin-ethereum/src/instances.rs @@ -67,7 +67,7 @@ impl BridgeInstance for RialtoPoA { fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(header.header()), + Box::new(into_substrate_ethereum_header(header.header())), into_substrate_ethereum_receipts(header.extra()), ); @@ -104,7 +104,7 @@ impl BridgeInstance for Kovan { fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - into_substrate_ethereum_header(header.header()), + Box::new(into_substrate_ethereum_header(header.header())), into_substrate_ethereum_receipts(header.extra()), ); diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 01eb3fbb4f528..9f4b3ba698fd7 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -220,12 +220,14 @@ impl SwapTokens { .await?; let create_swap_call: CallOf = pallet_bridge_token_swap::Call::create_swap( token_swap.clone(), - target_public_at_bridged_chain, - swap_delivery_and_dispatch_fee, - bridged_chain_spec_version, - bridged_currency_transfer.encode(), - bridged_currency_transfer_weight, - bridged_currency_transfer_signature, + Box::new(bp_token_swap::TokenSwapCreation { + target_public_at_bridged_chain, + swap_delivery_and_dispatch_fee, + bridged_chain_spec_version, + bridged_currency_transfer: bridged_currency_transfer.encode(), + bridged_currency_transfer_weight, + bridged_currency_transfer_signature, + }), ) .into(); From e614606323af28b9651974211abf2643dc58ba89 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 22 Oct 2021 13:15:50 +0300 Subject: [PATCH 0591/1210] Unify error enums in substrate and ethereum clients with `thiserror` (#1094) * Unify error enums in substrate and ethereum clients with `thiserror` Related to https://github.com/paritytech/parity-bridges-common/issues/857 * Add license pre-amble * rustfmt * Fix spelling --- relays/bin-ethereum/Cargo.toml | 1 + relays/bin-ethereum/src/error.rs | 38 +++++++ .../src/ethereum_deploy_contract.rs | 16 +-- relays/bin-ethereum/src/ethereum_exchange.rs | 6 +- .../src/ethereum_exchange_submit.rs | 11 +- relays/bin-ethereum/src/main.rs | 60 ++++++----- relays/bin-ethereum/src/rpc_errors.rs | 38 ++----- relays/bin-substrate/src/chains/kusama.rs | 4 +- .../src/chains/kusama_messages_to_polkadot.rs | 1 + relays/bin-substrate/src/chains/millau.rs | 7 +- .../src/chains/millau_messages_to_rialto.rs | 1 + relays/bin-substrate/src/chains/polkadot.rs | 4 +- .../src/chains/polkadot_messages_to_kusama.rs | 1 + relays/bin-substrate/src/chains/rialto.rs | 7 +- .../src/chains/rialto_messages_to_millau.rs | 1 + .../src/chains/rialto_parachain.rs | 4 +- relays/bin-substrate/src/chains/rococo.rs | 5 +- .../src/chains/rococo_messages_to_wococo.rs | 1 + relays/bin-substrate/src/chains/westend.rs | 5 +- relays/bin-substrate/src/chains/wococo.rs | 5 +- .../src/chains/wococo_messages_to_rococo.rs | 1 + relays/bin-substrate/src/cli/mod.rs | 2 +- .../src/cli/resubmit_transactions.rs | 1 + relays/client-ethereum/Cargo.toml | 1 + relays/client-ethereum/src/error.rs | 49 +++------ relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/error.rs | 83 +++------------ relays/client-substrate/src/guard.rs | 36 +++++-- relays/exchange/Cargo.toml | 1 + relays/exchange/src/error.rs | 66 ++++++++++++ relays/exchange/src/exchange.rs | 100 +++++++----------- relays/exchange/src/exchange_loop.rs | 5 +- relays/exchange/src/lib.rs | 1 + relays/finality/Cargo.toml | 1 - relays/finality/src/finality_loop.rs | 2 +- relays/headers/Cargo.toml | 1 - relays/headers/src/sync_loop.rs | 2 +- relays/lib-substrate-relay/Cargo.toml | 1 + relays/lib-substrate-relay/src/error.rs | 58 ++++++++++ .../src/headers_initialize.rs | 87 ++++++--------- relays/lib-substrate-relay/src/lib.rs | 1 + relays/messages/Cargo.toml | 1 - relays/messages/src/message_lane_loop.rs | 2 +- relays/utils/Cargo.toml | 1 + relays/utils/src/error.rs | 46 ++++++++ relays/utils/src/lib.rs | 16 ++- relays/utils/src/metrics/float_json_value.rs | 59 +++++------ relays/utils/src/relay_loop.rs | 22 ++-- 48 files changed, 482 insertions(+), 381 deletions(-) create mode 100644 relays/bin-ethereum/src/error.rs create mode 100644 relays/exchange/src/error.rs create mode 100644 relays/lib-substrate-relay/src/error.rs create mode 100644 relays/utils/src/error.rs diff --git a/relays/bin-ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml index 080608a26f8c6..610dee2c3ce99 100644 --- a/relays/bin-ethereum/Cargo.toml +++ b/relays/bin-ethereum/Cargo.toml @@ -21,6 +21,7 @@ libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"] log = "0.4.14" num-traits = "0.2" serde_json = "1.0.64" +thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/bin-ethereum/src/error.rs b/relays/bin-ethereum/src/error.rs new file mode 100644 index 0000000000000..61ae2a9a498dc --- /dev/null +++ b/relays/bin-ethereum/src/error.rs @@ -0,0 +1,38 @@ +// Copyright 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 . + +use crate::rpc_errors::RpcError; +use thiserror::Error; + +/// Result type used by PoA relay. +pub type Result = std::result::Result; + +/// Ethereum PoA relay errors. +#[derive(Error, Debug)] +pub enum Error { + /// Failed to decode initial header. + #[error("Error decoding initial header: {0}")] + DecodeInitialHeader(codec::Error), + /// RPC error. + #[error("{0}")] + Rpc(#[from] RpcError), + /// Failed to read genesis header. + #[error("Error reading Substrate genesis header: {0:?}")] + ReadGenesisHeader(relay_substrate_client::Error), + /// Failed to read initial GRANDPA authorities. + #[error("Error reading GRANDPA authorities set: {0:?}")] + ReadAuthorities(relay_substrate_client::Error), + /// Failed to deploy bridge contract to Ethereum chain. + #[error("Error deploying contract: {0:?}")] + DeployContract(RpcError), +} diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs index 9eecc1a12f517..cbe2762263a6f 100644 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::{ + error::{Error, Result}, ethereum_client::{bridge_contract, EthereumHighLevelRpc}, rpc_errors::RpcError, }; @@ -104,20 +105,20 @@ pub async fn run(params: EthereumDeployContractParams) { async fn prepare_initial_header( sub_client: &SubstrateClient, sub_initial_header: Option>, -) -> Result<(RialtoHeaderId, Vec), String> { +) -> Result<(RialtoHeaderId, Vec)> { match sub_initial_header { Some(raw_initial_header) => { match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) { Ok(initial_header) => Ok((HeaderId(initial_header.number, initial_header.hash()), raw_initial_header)), - Err(error) => Err(format!("Error decoding initial header: {}", error)), + Err(error) => Err(Error::DecodeInitialHeader(error)), } }, None => { let initial_header = sub_client.header_by_number(Zero::zero()).await; initial_header .map(|header| (HeaderId(Zero::zero(), header.hash()), header.encode())) - .map_err(|error| format!("Error reading Substrate genesis header: {:?}", error)) + .map_err(|error| Error::ReadGenesisHeader(error)) }, } } @@ -127,14 +128,13 @@ async fn prepare_initial_authorities_set( sub_client: &SubstrateClient, sub_initial_header_hash: rialto_runtime::Hash, sub_initial_authorities_set: Option>, -) -> Result { +) -> Result { let initial_authorities_set = match sub_initial_authorities_set { Some(initial_authorities_set) => Ok(initial_authorities_set), None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await, }; - initial_authorities_set - .map_err(|error| format!("Error reading GRANDPA authorities set: {:?}", error)) + initial_authorities_set.map_err(|error| Error::ReadAuthorities(error)) } /// Deploy bridge contract to Ethereum chain. @@ -145,7 +145,7 @@ async fn deploy_bridge_contract( initial_header: Vec, initial_set_id: u64, initial_authorities: Vec, -) -> Result<(), String> { +) -> Result<()> { eth_client .submit_ethereum_transaction( params, @@ -160,5 +160,5 @@ async fn deploy_bridge_contract( ), ) .await - .map_err(|error| format!("Error deploying contract: {:?}", error)) + .map_err(|error| Error::DeployContract(error)) } diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs index 6262c44c18d2c..90d9a23835d46 100644 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/relays/bin-ethereum/src/ethereum_exchange.rs @@ -339,7 +339,7 @@ pub async fn run(params: EthereumExchangeParams) { async fn run_single_transaction_relay( params: EthereumExchangeParams, eth_tx_hash: H256, -) -> Result<(), String> { +) -> anyhow::Result<()> { let EthereumExchangeParams { eth_params, sub_params, sub_sign, instance, .. } = params; let eth_client = EthereumClient::try_connect(eth_params).await.map_err(RpcError::Ethereum)?; @@ -354,7 +354,9 @@ async fn run_single_transaction_relay( bridge_instance: instance, }; - relay_single_transaction_proof(&source, &target, eth_tx_hash).await + relay_single_transaction_proof(&source, &target, eth_tx_hash) + .await + .map_err(Into::into) } async fn run_auto_transactions_relay_loop( diff --git a/relays/bin-ethereum/src/ethereum_exchange_submit.rs b/relays/bin-ethereum/src/ethereum_exchange_submit.rs index 75bdf0e577aa2..f68a21e594e06 100644 --- a/relays/bin-ethereum/src/ethereum_exchange_submit.rs +++ b/relays/bin-ethereum/src/ethereum_exchange_submit.rs @@ -16,6 +16,7 @@ //! Submitting Ethereum -> Substrate exchange transactions. +use anyhow::anyhow; use bp_eth_poa::{ signatures::{secret_to_address, SignTransaction}, UnsignedTransaction, @@ -47,10 +48,10 @@ pub async fn run(params: EthereumExchangeSubmitParams) { let EthereumExchangeSubmitParams { eth_params, eth_sign, eth_nonce, eth_amount, sub_recipient } = params; - let result: Result<_, String> = async move { + let result: anyhow::Result<_> = async move { let eth_client = EthereumClient::try_connect(eth_params) .await - .map_err(|err| format!("error connecting to Ethereum node: {:?}", err))?; + .map_err(|err| anyhow!("error connecting to Ethereum node: {:?}", err))?; let eth_signer_address = secret_to_address(ð_sign.signer); let sub_recipient_encoded = sub_recipient; @@ -59,7 +60,7 @@ pub async fn run(params: EthereumExchangeSubmitParams) { None => eth_client .account_nonce(eth_signer_address) .await - .map_err(|err| format!("error fetching acount nonce: {:?}", err))?, + .map_err(|err| anyhow!("error fetching acount nonce: {:?}", err))?, }; let gas = eth_client .estimate_gas(CallRequest { @@ -70,7 +71,7 @@ pub async fn run(params: EthereumExchangeSubmitParams) { ..Default::default() }) .await - .map_err(|err| format!("error estimating gas requirements: {:?}", err))?; + .map_err(|err| anyhow!("error estimating gas requirements: {:?}", err))?; let eth_tx_unsigned = UnsignedTransaction { nonce, gas_price: eth_sign.gas_price, @@ -84,7 +85,7 @@ pub async fn run(params: EthereumExchangeSubmitParams) { eth_client .submit_transaction(eth_tx_signed) .await - .map_err(|err| format!("error submitting transaction: {:?}", err))?; + .map_err(|err| anyhow!("error submitting transaction: {:?}", err))?; Ok(eth_tx_unsigned) } diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs index 86b749872913e..99e1b48968d79 100644 --- a/relays/bin-ethereum/src/main.rs +++ b/relays/bin-ethereum/src/main.rs @@ -16,6 +16,7 @@ #![recursion_limit = "1024"] +mod error; mod ethereum_client; mod ethereum_deploy_contract; mod ethereum_exchange; @@ -27,6 +28,7 @@ mod rpc_errors; mod substrate_sync_loop; mod substrate_types; +use anyhow::anyhow; use ethereum_deploy_contract::EthereumDeployContractParams; use ethereum_exchange::EthereumExchangeParams; use ethereum_exchange_submit::EthereumExchangeSubmitParams; @@ -136,58 +138,58 @@ async fn run_command(matches: &clap::ArgMatches<'_>) { fn ethereum_connection_params( matches: &clap::ArgMatches, -) -> Result { +) -> anyhow::Result { let mut params = EthereumConnectionParams::default(); if let Some(eth_host) = matches.value_of("eth-host") { params.host = eth_host.into(); } if let Some(eth_port) = matches.value_of("eth-port") { - params.port = eth_port.parse().map_err(|e| format!("Failed to parse eth-port: {}", e))?; + params.port = eth_port.parse().map_err(|e| anyhow!("Failed to parse eth-port: {}", e))?; } Ok(params) } -fn ethereum_signing_params(matches: &clap::ArgMatches) -> Result { +fn ethereum_signing_params(matches: &clap::ArgMatches) -> anyhow::Result { let mut params = EthereumSigningParams::default(); if let Some(eth_signer) = matches.value_of("eth-signer") { params.signer = SecretKey::parse_slice( - &hex::decode(eth_signer).map_err(|e| format!("Failed to parse eth-signer: {}", e))?, + &hex::decode(eth_signer).map_err(|e| anyhow!("Failed to parse eth-signer: {}", e))?, ) - .map_err(|e| format!("Invalid eth-signer: {}", e))?; + .map_err(|e| anyhow!("Invalid eth-signer: {}", e))?; } if let Some(eth_chain_id) = matches.value_of("eth-chain-id") { params.chain_id = eth_chain_id .parse::() - .map_err(|e| format!("Failed to parse eth-chain-id: {}", e))?; + .map_err(|e| anyhow!("Failed to parse eth-chain-id: {}", e))?; } Ok(params) } fn substrate_connection_params( matches: &clap::ArgMatches, -) -> Result { +) -> anyhow::Result { let mut params = SubstrateConnectionParams::default(); if let Some(sub_host) = matches.value_of("sub-host") { params.host = sub_host.into(); } if let Some(sub_port) = matches.value_of("sub-port") { - params.port = sub_port.parse().map_err(|e| format!("Failed to parse sub-port: {}", e))?; + params.port = sub_port.parse().map_err(|e| anyhow!("Failed to parse sub-port: {}", e))?; } Ok(params) } -fn rialto_signing_params(matches: &clap::ArgMatches) -> Result { +fn rialto_signing_params(matches: &clap::ArgMatches) -> anyhow::Result { let mut params = sp_keyring::AccountKeyring::Alice.pair(); if let Some(sub_signer) = matches.value_of("sub-signer") { let sub_signer_password = matches.value_of("sub-signer-password"); params = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) - .map_err(|e| format!("Failed to parse sub-signer: {:?}", e))?; + .map_err(|e| anyhow!("Failed to parse sub-signer: {:?}", e))?; } Ok(params) } -fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result { +fn ethereum_sync_params(matches: &clap::ArgMatches) -> anyhow::Result { use crate::ethereum_sync_loop::consts::*; let mut sync_params = HeadersSyncParams { @@ -208,7 +210,7 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result sync_params.target_tx_mode = TargetTransactionMode::Backup, - Some(mode) => return Err(format!("Invalid sub-tx-mode: {}", mode)), + Some(mode) => return Err(anyhow!("Invalid sub-tx-mode: {}", mode)), None => sync_params.target_tx_mode = TargetTransactionMode::Signed, } @@ -226,12 +228,12 @@ fn ethereum_sync_params(matches: &clap::ArgMatches) -> Result Result { +fn substrate_sync_params(matches: &clap::ArgMatches) -> anyhow::Result { use crate::substrate_sync_loop::consts::*; let eth_contract_address: relay_ethereum_client::types::Address = if let Some(eth_contract) = matches.value_of("eth-contract") { - eth_contract.parse().map_err(|e| format!("{}", e))? + eth_contract.parse()? } else { "731a10897d267e19b34503ad902d0a29173ba4b1" .parse() @@ -261,7 +263,7 @@ fn substrate_sync_params(matches: &clap::ArgMatches) -> Result Result { +) -> anyhow::Result { let eth_contract_code = parse_hex_argument(matches, "eth-contract-code")?.unwrap_or_else(|| { hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")) @@ -271,7 +273,7 @@ fn ethereum_deploy_contract_params( .value_of("sub-authorities-set-id") .map(|set| { set.parse() - .map_err(|e| format!("Failed to parse sub-authorities-set-id: {}", e)) + .map_err(|e| anyhow!("Failed to parse sub-authorities-set-id: {}", e)) }) .transpose()?; let sub_initial_authorities_set = parse_hex_argument(matches, "sub-authorities-set")?; @@ -294,19 +296,19 @@ fn ethereum_deploy_contract_params( fn ethereum_exchange_submit_params( matches: &clap::ArgMatches, -) -> Result { +) -> anyhow::Result { let eth_nonce = matches .value_of("eth-nonce") .map(|eth_nonce| { relay_ethereum_client::types::U256::from_dec_str(eth_nonce) - .map_err(|e| format!("Failed to parse eth-nonce: {}", e)) + .map_err(|e| anyhow!("Failed to parse eth-nonce: {}", e)) }) .transpose()?; let eth_amount = matches .value_of("eth-amount") .map(|eth_amount| { - eth_amount.parse().map_err(|e| format!("Failed to parse eth-amount: {}", e)) + eth_amount.parse().map_err(|e| anyhow!("Failed to parse eth-amount: {}", e)) }) .transpose()? .unwrap_or_else(|| { @@ -331,7 +333,7 @@ fn ethereum_exchange_submit_params( Ok(sub_recipient) } }) - .map_err(|e| format!("Failed to parse sub-recipient: {}", e))? + .map_err(|e| anyhow!("Failed to parse sub-recipient: {}", e))? } else { default_recepient }; @@ -349,10 +351,10 @@ fn ethereum_exchange_submit_params( Ok(params) } -fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result { +fn ethereum_exchange_params(matches: &clap::ArgMatches) -> anyhow::Result { let mode = match matches.value_of("eth-tx-hash") { Some(eth_tx_hash) => ethereum_exchange::ExchangeRelayMode::Single( - eth_tx_hash.parse().map_err(|e| format!("Failed to parse eth-tx-hash: {}", e))?, + eth_tx_hash.parse().map_err(|e| anyhow!("Failed to parse eth-tx-hash: {}", e))?, ), None => ethereum_exchange::ExchangeRelayMode::Auto( matches @@ -360,7 +362,7 @@ fn ethereum_exchange_params(matches: &clap::ArgMatches) -> Result Result Result { +fn metrics_params(matches: &clap::ArgMatches) -> anyhow::Result { if matches.is_present("no-prometheus") { return Ok(None.into()) } @@ -393,18 +395,18 @@ fn metrics_params(matches: &clap::ArgMatches) -> Result { if let Some(prometheus_port) = matches.value_of("prometheus-port") { metrics_params.port = prometheus_port .parse() - .map_err(|e| format!("Failed to parse prometheus-port: {}", e))?; + .map_err(|e| anyhow!("Failed to parse prometheus-port: {}", e))?; } Ok(Some(metrics_params).into()) } -fn instance_params(matches: &clap::ArgMatches) -> Result, String> { +fn instance_params(matches: &clap::ArgMatches) -> anyhow::Result> { let instance = if let Some(instance) = matches.value_of("sub-pallet-instance") { match instance.to_lowercase().as_str() { "rialto" => Arc::new(RialtoPoA) as Arc, "kovan" => Arc::new(Kovan), - _ => return Err("Unsupported bridge pallet instance".to_string()), + _ => return Err(anyhow!("Unsupported bridge pallet instance")), } } else { unreachable!("CLI config enforces a default instance, can never be None") @@ -413,10 +415,10 @@ fn instance_params(matches: &clap::ArgMatches) -> Result Ok(instance) } -fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> Result>, String> { +fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> anyhow::Result>> { match matches.value_of(arg) { Some(value) => - Ok(Some(hex::decode(value).map_err(|e| format!("Failed to parse {}: {}", arg, e))?)), + Ok(Some(hex::decode(value).map_err(|e| anyhow!("Failed to parse {}: {}", arg, e))?)), None => Ok(None), } } diff --git a/relays/bin-ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs index f0f28b0c4062d..e91bc363839b6 100644 --- a/relays/bin-ethereum/src/rpc_errors.rs +++ b/relays/bin-ethereum/src/rpc_errors.rs @@ -17,48 +17,30 @@ use relay_ethereum_client::Error as EthereumNodeError; use relay_substrate_client::Error as SubstrateNodeError; use relay_utils::MaybeConnectionError; +use thiserror::Error; /// Contains common errors that can occur when /// interacting with a Substrate or Ethereum node /// through RPC. -#[derive(Debug)] +#[derive(Debug, Error)] pub enum RpcError { /// The arguments to the RPC method failed to serialize. - Serialization(serde_json::Error), + #[error("RPC arguments serialization failed: {0}")] + Serialization(#[from] serde_json::Error), /// An error occurred when interacting with an Ethereum node. - Ethereum(EthereumNodeError), + #[error("Ethereum node error: {0}")] + Ethereum(#[from] EthereumNodeError), /// An error occurred when interacting with a Substrate node. - Substrate(SubstrateNodeError), + #[error("Substrate node error: {0}")] + Substrate(#[from] SubstrateNodeError), /// Error running relay loop. + #[error("{0}")] SyncLoop(String), } impl From for String { fn from(err: RpcError) -> Self { - match err { - RpcError::Serialization(e) => e.to_string(), - RpcError::Ethereum(e) => e.to_string(), - RpcError::Substrate(e) => e.to_string(), - RpcError::SyncLoop(e) => e, - } - } -} - -impl From for RpcError { - fn from(err: serde_json::Error) -> Self { - Self::Serialization(err) - } -} - -impl From for RpcError { - fn from(err: EthereumNodeError) -> Self { - Self::Ethereum(err) - } -} - -impl From for RpcError { - fn from(err: SubstrateNodeError) -> Self { - Self::Substrate(err) + format!("{}", err) } } diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index f0c11f6abb83f..9e5351672dada 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -97,7 +97,7 @@ impl CliChain for Kusama { fn encode_message( _message: encode_message::MessagePayload, - ) -> Result { - Err("Sending messages from Kusama is not yet supported.".into()) + ) -> anyhow::Result { + anyhow::bail!("Sending messages from Kusama is not yet supported.") } } diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index e006532d978a4..40e03ef266847 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -256,6 +256,7 @@ pub async fn run( futures::future::pending(), ) .await + .map_err(Into::into) } /// Add standalone metrics for the Kusama -> Polkadot messages loop. diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 004e4c740a473..55b16b7786b73 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -23,6 +23,7 @@ use crate::cli::{ send_message::{self, DispatchFeePayment}, CliChain, }; +use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; @@ -87,10 +88,10 @@ impl CliChain for Millau { // TODO [#854|#843] support multiple bridges? fn encode_message( message: encode_message::MessagePayload, - ) -> Result { + ) -> anyhow::Result { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Millau's MessagePayload: {:?}", e)), + .map_err(|e| anyhow!("Failed to decode Millau's MessagePayload: {:?}", e)), encode_message::MessagePayload::Call { mut call, mut sender } => { type Source = Millau; type Target = relay_rialto_client::Rialto; @@ -102,7 +103,7 @@ impl CliChain for Millau { &mut call, bridge::MILLAU_TO_RIALTO_INDEX, ); - let call = Target::encode_call(&call).map_err(|e| e.to_string())?; + let call = Target::encode_call(&call)?; let weight = call.get_dispatch_info().weight; Ok(send_message::message_payload( diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 7682f32e608e4..9c56e8bd3d404 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -250,6 +250,7 @@ pub async fn run( futures::future::pending(), ) .await + .map_err(Into::into) } /// Add standalone metrics for the Millau -> Rialto messages loop. diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 6baeb50c14a35..55d17e46f13bb 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -97,7 +97,7 @@ impl CliChain for Polkadot { fn encode_message( _message: encode_message::MessagePayload, - ) -> Result { - Err("Sending messages from Polkadot is not yet supported.".into()) + ) -> anyhow::Result { + anyhow::bail!("Sending messages from Polkadot is not yet supported.") } } diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 71943af44da36..31e8b710e348e 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -255,6 +255,7 @@ pub async fn run( futures::future::pending(), ) .await + .map_err(Into::into) } /// Add standalone metrics for the Polkadot -> Kusama messages loop. diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 0575896d97fdb..837957bb87a1b 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -23,6 +23,7 @@ use crate::cli::{ send_message::{self, DispatchFeePayment}, CliChain, }; +use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; @@ -86,10 +87,10 @@ impl CliChain for Rialto { fn encode_message( message: encode_message::MessagePayload, - ) -> Result { + ) -> anyhow::Result { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| format!("Failed to decode Rialto's MessagePayload: {:?}", e)), + .map_err(|e| anyhow!("Failed to decode Rialto's MessagePayload: {:?}", e)), encode_message::MessagePayload::Call { mut call, mut sender } => { type Source = Rialto; type Target = relay_millau_client::Millau; @@ -101,7 +102,7 @@ impl CliChain for Rialto { &mut call, bridge::RIALTO_TO_MILLAU_INDEX, ); - let call = Target::encode_call(&call).map_err(|e| e.to_string())?; + let call = Target::encode_call(&call)?; let weight = call.get_dispatch_info().weight; Ok(send_message::message_payload( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 529f14b84a3da..99960cd00f5a0 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -249,6 +249,7 @@ pub async fn run( futures::future::pending(), ) .await + .map_err(Into::into) } /// Add standalone metrics for the Rialto -> Millau messages loop. diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index f81bc61b859a8..4c9f63bbe41f6 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -76,7 +76,7 @@ impl CliChain for RialtoParachain { fn encode_message( _message: encode_message::MessagePayload, - ) -> Result { - Err("Not supported".into()) + ) -> anyhow::Result { + anyhow::bail!("Not supported") } } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index ddd0b6cc13b12..4df60f89faa21 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; @@ -94,7 +95,7 @@ impl CliChain for Rococo { fn encode_message( _message: encode_message::MessagePayload, - ) -> Result { - Err("Sending messages from Rococo is not yet supported.".into()) + ) -> anyhow::Result { + Err(anyhow!("Sending messages from Rococo is not yet supported.")) } } diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index e26adcb9a27b1..65eda19c6ef18 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -253,6 +253,7 @@ pub async fn run( futures::future::pending(), ) .await + .map_err(Into::into) } /// Add standalone metrics for the Rococo -> Wococo messages loop. diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 586e6ffd95760..a42e4805512ca 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -17,6 +17,7 @@ //! Westend chain specification for CLI. use crate::cli::{encode_message, CliChain}; +use anyhow::anyhow; use frame_support::weights::Weight; use relay_westend_client::Westend; use sp_version::RuntimeVersion; @@ -37,7 +38,7 @@ impl CliChain for Westend { fn encode_message( _message: encode_message::MessagePayload, - ) -> Result { - Err("Sending messages from Westend is not yet supported.".into()) + ) -> anyhow::Result { + Err(anyhow!("Sending messages from Westend is not yet supported.")) } } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index fbdbcf868c7c4..328397d14ba7c 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_wococo_client::Wococo; @@ -88,7 +89,7 @@ impl CliChain for Wococo { fn encode_message( _message: encode_message::MessagePayload, - ) -> Result { - Err("Sending messages from Wococo is not yet supported.".into()) + ) -> anyhow::Result { + Err(anyhow!("Sending messages from Wococo is not yet supported.")) } } diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 4d1fc4f0d815b..d380e6c29a4cb 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -252,6 +252,7 @@ pub async fn run( futures::future::pending(), ) .await + .map_err(Into::into) } /// Add standalone metrics for the Wococo -> Rococo messages loop. diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index c35c2b87dd8fb..f1180059b9949 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -257,7 +257,7 @@ pub trait CliChain: relay_substrate_client::Chain { /// Construct message payload to be sent over the bridge. fn encode_message( message: crate::cli::encode_message::MessagePayload, - ) -> Result; + ) -> anyhow::Result; /// Maximal extrinsic weight (from the runtime). fn max_extrinsic_weight() -> Weight; diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index d20cff17f6331..1091048b3ba00 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -141,6 +141,7 @@ impl ResubmitTransactions { ) }) .await + .map_err(Into::into) }) } } diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml index 4263055d01b4e..171988a32533b 100644 --- a/relays/client-ethereum/Cargo.toml +++ b/relays/client-ethereum/Cargo.toml @@ -17,3 +17,4 @@ log = "0.4.11" relay-utils = { path = "../utils" } tokio = "1.8" web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "bump-deps" } +thiserror = "1.0.26" diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs index 23a9138e12085..6323b708fc024 100644 --- a/relays/client-ethereum/src/error.rs +++ b/relays/client-ethereum/src/error.rs @@ -20,49 +20,47 @@ use crate::types::U256; use jsonrpsee_ws_client::types::Error as RpcError; use relay_utils::MaybeConnectionError; +use thiserror::Error; /// Result type used by Ethereum client. pub type Result = std::result::Result; /// Errors that can occur only when interacting with /// an Ethereum node through RPC. -#[derive(Debug)] +#[derive(Debug, Error)] pub enum Error { /// IO error. - Io(std::io::Error), + #[error("IO error: {0}")] + Io(#[from] std::io::Error), /// An error that can occur when making an HTTP request to /// an JSON-RPC client. - RpcError(RpcError), + #[error("RPC error: {0}")] + RpcError(#[from] RpcError), /// Failed to parse response. + #[error("Response parse failed: {0}")] ResponseParseFailed(String), /// We have received a header with missing fields. + #[error("Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom).")] IncompleteHeader, /// We have received a transaction missing a `raw` field. + #[error("Incomplete Ethereum Transaction (missing required field - raw).")] IncompleteTransaction, /// An invalid Substrate block number was received from /// an Ethereum node. + #[error("Received an invalid Substrate block from Ethereum Node.")] InvalidSubstrateBlockNumber, /// An invalid index has been received from an Ethereum node. + #[error("Received an invalid incomplete index from Ethereum Node.")] InvalidIncompleteIndex, /// The client we're connected to is not synced, so we can't rely on its state. Contains /// number of unsynced headers. + #[error("Ethereum client is not synced: syncing {0} headers.")] ClientNotSynced(U256), /// Custom logic error. + #[error("{0}")] Custom(String), } -impl From for Error { - fn from(error: RpcError) -> Self { - Error::RpcError(error) - } -} - -impl From for Error { - fn from(error: std::io::Error) -> Self { - Error::Io(error) - } -} - impl From for Error { fn from(error: tokio::task::JoinError) -> Self { Error::Custom(format!("Failed to wait tokio task: {}", error)) @@ -82,24 +80,3 @@ impl MaybeConnectionError for Error { ) } } - -impl ToString for Error { - fn to_string(&self) -> String { - match self { - Self::Io(e) => e.to_string(), - Self::RpcError(e) => e.to_string(), - Self::ResponseParseFailed(e) => e.to_string(), - Self::IncompleteHeader => { - "Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom)" - .to_string() - } - Self::IncompleteTransaction => "Incomplete Ethereum Transaction (missing required field - raw)".to_string(), - Self::InvalidSubstrateBlockNumber => "Received an invalid Substrate block from Ethereum Node".to_string(), - Self::InvalidIncompleteIndex => "Received an invalid incomplete index from Ethereum Node".to_string(), - Self::ClientNotSynced(missing_headers) => { - format!("Ethereum client is not synced: syncing {} headers", missing_headers) - } - Self::Custom(ref e) => e.clone(), - } - } -} diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 7d82e365e2f17..6a1173581e7a7 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,6 +15,7 @@ log = "0.4.11" num-traits = "0.2" rand = "0.7" tokio = "1.8" +thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index c3cd236b948c5..33b9b22a03efe 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -20,78 +20,54 @@ use jsonrpsee_ws_client::types::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; use sp_runtime::transaction_validity::TransactionValidityError; +use thiserror::Error; /// Result type used by Substrate client. pub type Result = std::result::Result; /// Errors that can occur only when interacting with /// a Substrate node through RPC. -#[derive(Debug)] +#[derive(Error, Debug)] pub enum Error { /// IO error. - Io(std::io::Error), + #[error("IO error: {0}")] + Io(#[from] std::io::Error), /// An error that can occur when making a request to /// an JSON-RPC server. - RpcError(RpcError), + #[error("RPC error: {0}")] + RpcError(#[from] RpcError), /// The response from the server could not be SCALE decoded. - ResponseParseFailed(codec::Error), + #[error("Response parse failed: {0}")] + ResponseParseFailed(#[from] codec::Error), /// The Substrate bridge pallet has not yet been initialized. + #[error("The Substrate bridge pallet has not been initialized yet.")] UninitializedBridgePallet, /// Account does not exist on the chain. + #[error("Account does not exist on the chain.")] AccountDoesNotExist, /// Runtime storage is missing mandatory ":code:" entry. + #[error("Mandatory :code: entry is missing from runtime storage.")] MissingMandatoryCodeEntry, /// The client we're connected to is not synced, so we can't rely on its state. + #[error("Substrate client is not synced {0}.")] ClientNotSynced(Health), /// An error has happened when we have tried to parse storage proof. + #[error("Error when parsing storage proof: {0:?}.")] StorageProofError(bp_runtime::StorageProofError), /// The Substrate transaction is invalid. - TransactionInvalid(TransactionValidityError), + #[error("Substrate transaction is invalid: {0:?}")] + TransactionInvalid(#[from] TransactionValidityError), /// Custom logic error. + #[error("{0}")] Custom(String), } -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - Self::Io(ref e) => Some(e), - Self::RpcError(ref e) => Some(e), - Self::ResponseParseFailed(ref e) => Some(e), - Self::UninitializedBridgePallet => None, - Self::AccountDoesNotExist => None, - Self::MissingMandatoryCodeEntry => None, - Self::ClientNotSynced(_) => None, - Self::StorageProofError(_) => None, - Self::TransactionInvalid(_) => None, - Self::Custom(_) => None, - } - } -} - -impl From for Error { - fn from(error: RpcError) -> Self { - Error::RpcError(error) - } -} - -impl From for Error { - fn from(error: std::io::Error) -> Self { - Error::Io(error) - } -} - impl From for Error { fn from(error: tokio::task::JoinError) -> Self { Error::Custom(format!("Failed to wait tokio task: {}", error)) } } -impl From for Error { - fn from(error: TransactionValidityError) -> Self { - Error::TransactionInvalid(error) - } -} - impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { matches!( @@ -105,30 +81,3 @@ impl MaybeConnectionError for Error { ) } } - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let s = match self { - Self::Io(e) => e.to_string(), - Self::RpcError(e) => e.to_string(), - Self::ResponseParseFailed(e) => e.to_string(), - Self::UninitializedBridgePallet => - "The Substrate bridge pallet has not been initialized yet.".into(), - Self::AccountDoesNotExist => "Account does not exist on the chain".into(), - Self::MissingMandatoryCodeEntry => - "Mandatory :code: entry is missing from runtime storage".into(), - Self::StorageProofError(e) => format!("Error when parsing storage proof: {:?}", e), - Self::ClientNotSynced(health) => format!("Substrate client is not synced: {}", health), - Self::TransactionInvalid(e) => format!("Substrate transaction is invalid: {:?}", e), - Self::Custom(e) => e.clone(), - }; - - write!(f, "{}", s) - } -} - -impl From for String { - fn from(error: Error) -> String { - error.to_string() - } -} diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index b6ec83f98408c..a064e36234007 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -17,23 +17,30 @@ //! Pallet provides a set of guard functions that are running in background threads //! and are aborting process if some condition fails. -use crate::{Chain, ChainWithBalances, Client}; +use crate::{error::Error, Chain, ChainWithBalances, Client}; use async_trait::async_trait; use num_traits::CheckedSub; use sp_version::RuntimeVersion; use std::{ collections::VecDeque, + fmt::Display, time::{Duration, Instant}, }; /// Guards environment. #[async_trait] pub trait Environment: Send + Sync + 'static { + /// Error type. + type Error: Display + Send + Sync + 'static; + /// Return current runtime version. - async fn runtime_version(&mut self) -> Result; + async fn runtime_version(&mut self) -> Result; /// Return free native balance of the account on the chain. - async fn free_native_balance(&mut self, account: C::AccountId) -> Result; + async fn free_native_balance( + &mut self, + account: C::AccountId, + ) -> Result; /// Return current time. fn now(&self) -> Instant { @@ -74,7 +81,7 @@ pub fn abort_on_spec_version_change( }, Err(error) => log::warn!( target: "bridge-guard", - "Failed to read {} runtime version: {:?}. Relay may need to be stopped manually", + "Failed to read {} runtime version: {}. Relay may need to be stopped manually", C::NAME, error, ), @@ -137,7 +144,7 @@ pub fn abort_when_account_balance_decreased( Err(error) => { log::warn!( target: "bridge-guard", - "Failed to read {} account {:?} balance: {:?}. Relay may need to be stopped manually", + "Failed to read {} account {:?} balance: {}. Relay may need to be stopped manually", C::NAME, account_id, error, @@ -157,12 +164,17 @@ fn conditions_check_delay() -> Duration { #[async_trait] impl Environment for Client { - async fn runtime_version(&mut self) -> Result { - Client::::runtime_version(self).await.map_err(|e| e.to_string()) + type Error = Error; + + async fn runtime_version(&mut self) -> Result { + Client::::runtime_version(self).await } - async fn free_native_balance(&mut self, account: C::AccountId) -> Result { - Client::::free_native_balance(self, account).await.map_err(|e| e.to_string()) + async fn free_native_balance( + &mut self, + account: C::AccountId, + ) -> Result { + Client::::free_native_balance(self, account).await } } @@ -220,11 +232,13 @@ mod tests { #[async_trait] impl Environment for TestEnvironment { - async fn runtime_version(&mut self) -> Result { + type Error = Error; + + async fn runtime_version(&mut self) -> Result { Ok(self.runtime_version_rx.next().await.unwrap_or_default()) } - async fn free_native_balance(&mut self, _account: u32) -> Result { + async fn free_native_balance(&mut self, _account: u32) -> Result { Ok(self.free_native_balance_rx.next().await.unwrap_or_default()) } diff --git a/relays/exchange/Cargo.toml b/relays/exchange/Cargo.toml index b8bb8481f616d..f08c40325ec71 100644 --- a/relays/exchange/Cargo.toml +++ b/relays/exchange/Cargo.toml @@ -15,3 +15,4 @@ log = "0.4.11" num-traits = "0.2" parking_lot = "0.11.0" relay-utils = { path = "../utils" } +thiserror = "1.0.26" diff --git a/relays/exchange/src/error.rs b/relays/exchange/src/error.rs new file mode 100644 index 0000000000000..aa5c427a9efbd --- /dev/null +++ b/relays/exchange/src/error.rs @@ -0,0 +1,66 @@ +// 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 . + +//! Exchange-relay errors. + +use crate::exchange::{BlockHashOf, BlockNumberOf, TransactionHashOf}; + +use relay_utils::MaybeConnectionError; +use std::fmt::{Debug, Display}; +use thiserror::Error; + +/// Error type given pipeline. +pub type ErrorOf

= Error, BlockNumberOf

, TransactionHashOf

>; + +/// Exchange-relay error type. +#[derive(Error, Debug)] +pub enum Error { + /// Failed to check finality of the requested header on the target node. + #[error("Failed to check finality of header {0}/{1} on {2} node: {3:?}")] + Finality(HeaderNumber, Hash, &'static str, anyhow::Error), + /// Error retrieving block from the source node. + #[error("Error retrieving block {0} from {1} node: {2:?}")] + RetrievingBlock(Hash, &'static str, anyhow::Error), + /// Error retrieving transaction from the source node. + #[error("Error retrieving transaction {0} from {1} node: {2:?}")] + RetrievingTransaction(SourceTxHash, &'static str, anyhow::Error), + /// Failed to check existence of header from the target node. + #[error("Failed to check existence of header {0}/{1} on {2} node: {3:?}")] + CheckHeaderExistence(HeaderNumber, Hash, &'static str, anyhow::Error), + /// Failed to prepare proof for the transaction from the source node. + #[error("Error building transaction {0} proof on {1} node: {2:?}")] + BuildTransactionProof(String, &'static str, anyhow::Error, bool), + /// Failed to submit the transaction proof to the target node. + #[error("Error submitting transaction {0} proof to {1} node: {2:?}")] + SubmitTransactionProof(String, &'static str, anyhow::Error, bool), + /// Transaction filtering failed. + #[error("Transaction filtering has failed with {0:?}")] + TransactionFiltering(anyhow::Error, bool), + /// Utilities/metrics error. + #[error("{0}")] + Utils(#[from] relay_utils::Error), +} + +impl MaybeConnectionError for Error { + fn is_connection_error(&self) -> bool { + match *self { + Self::BuildTransactionProof(_, _, _, b) => b, + Self::SubmitTransactionProof(_, _, _, b) => b, + Self::TransactionFiltering(_, b) => b, + _ => false, + } + } +} diff --git a/relays/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs index b48a094ee3d5d..b4538d2636cec 100644 --- a/relays/exchange/src/exchange.rs +++ b/relays/exchange/src/exchange.rs @@ -16,11 +16,11 @@ //! Relaying proofs of exchange transaction. +use crate::error::{Error, ErrorOf}; + +use anyhow::anyhow; use async_trait::async_trait; -use relay_utils::{ - relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, - StringifiedMaybeConnectionError, -}; +use relay_utils::{relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError}; use std::{ fmt::{Debug, Display}, string::ToString, @@ -67,7 +67,7 @@ pub trait SourceBlock: 'static + Send + Sync { /// Transaction that is participating in exchange. pub trait SourceTransaction: 'static + Send { /// Transaction hash type. - type Hash: Debug + Display; + type Hash: Debug + Display + Clone; /// Return transaction hash. fn hash(&self) -> Self::Hash; @@ -117,7 +117,7 @@ pub trait TargetClient: RelayClient { /// Sleep until exchange-related data is (probably) updated. async fn tick(&self); /// Returns `Ok(true)` if header is known to the target node. - async fn is_header_known(&self, id: &HeaderId

) -> Result; + async fn is_header_known(&self, id: &HeaderId

) -> std::result::Result; /// Returns `Ok(true)` if header is finalized by the target node. async fn is_header_finalized(&self, id: &HeaderId

) -> Result; /// Returns best finalized header id. @@ -178,9 +178,9 @@ pub async fn relay_block_transactions( target_client.filter_transaction_proof(&source_tx_proof).await.map_err(|err| { ( FailedClient::Target, - StringifiedMaybeConnectionError::new( + Error::TransactionFiltering( + anyhow!("{:?}", err), err.is_connection_error(), - format!("Transaction filtering has failed with {:?}", err), ), ) })?; @@ -256,20 +256,14 @@ pub async fn relay_single_transaction_proof( source_client: &impl SourceClient

, target_client: &impl TargetClient

, source_tx_hash: TransactionHashOf

, -) -> Result<(), String> { +) -> Result<(), ErrorOf

> { // wait for transaction and header on source node let (source_header_id, source_tx_index) = wait_transaction_mined(source_client, &source_tx_hash).await?; let source_block = source_client.block_by_hash(source_header_id.1.clone()).await; let source_block = source_block.map_err(|err| { - format!( - "Error retrieving block {} from {} node: {:?}", - source_header_id.1, - P::SOURCE_NAME, - err, - ) + Error::RetrievingBlock(source_header_id.1.clone(), P::SOURCE_NAME, anyhow!("{:?}", err)) })?; - // wait for transaction and header on target node wait_header_imported(target_client, &source_header_id).await?; wait_header_finalized(target_client, &source_header_id).await?; @@ -280,11 +274,10 @@ pub async fn relay_single_transaction_proof( target_client, &source_tx_id, prepare_transaction_proof(source_client, &source_tx_id, &source_block, source_tx_index) - .await - .map_err(|err| err.to_string())?, + .await?, ) .await - .map_err(|err| err.to_string()) + .map_err(Into::into) } /// Prepare transaction proof. @@ -293,19 +286,16 @@ async fn prepare_transaction_proof( source_tx_id: &str, source_block: &P::Block, source_tx_index: usize, -) -> Result { +) -> Result> { source_client .transaction_proof(source_block, source_tx_index) .await .map_err(|err| { - StringifiedMaybeConnectionError::new( + Error::BuildTransactionProof( + source_tx_id.to_owned(), + P::SOURCE_NAME, + anyhow!("{:?}", err), err.is_connection_error(), - format!( - "Error building transaction {} proof on {} node: {:?}", - source_tx_id, - P::SOURCE_NAME, - err, - ), ) }) } @@ -315,16 +305,13 @@ async fn relay_ready_transaction_proof( target_client: &impl TargetClient

, source_tx_id: &str, source_tx_proof: P::TransactionProof, -) -> Result<(), StringifiedMaybeConnectionError> { +) -> Result<(), ErrorOf

> { target_client.submit_transaction_proof(source_tx_proof).await.map_err(|err| { - StringifiedMaybeConnectionError::new( + Error::SubmitTransactionProof( + source_tx_id.to_owned(), + P::TARGET_NAME, + anyhow!("{:?}", err), err.is_connection_error(), - format!( - "Error submitting transaction {} proof to {} node: {:?}", - source_tx_id, - P::TARGET_NAME, - err, - ), ) }) } @@ -333,15 +320,14 @@ async fn relay_ready_transaction_proof( async fn wait_transaction_mined( source_client: &impl SourceClient

, source_tx_hash: &TransactionHashOf

, -) -> Result<(HeaderId

, usize), String> { +) -> Result<(HeaderId

, usize), ErrorOf

> { loop { let source_header_and_tx = source_client.transaction_block(source_tx_hash).await.map_err(|err| { - format!( - "Error retrieving transaction {} from {} node: {:?}", - source_tx_hash, + Error::RetrievingTransaction( + source_tx_hash.clone(), P::SOURCE_NAME, - err, + anyhow!("{:?}", err), ) })?; match source_header_and_tx { @@ -373,16 +359,15 @@ async fn wait_transaction_mined( async fn wait_header_imported( target_client: &impl TargetClient

, source_header_id: &HeaderId

, -) -> Result<(), String> { +) -> Result<(), ErrorOf

> { loop { let is_header_known = target_client.is_header_known(source_header_id).await.map_err(|err| { - format!( - "Failed to check existence of header {}/{} on {} node: {:?}", + Error::CheckHeaderExistence( source_header_id.0, - source_header_id.1, + source_header_id.1.clone(), P::TARGET_NAME, - err, + anyhow!("{:?}", err), ) })?; match is_header_known { @@ -416,16 +401,15 @@ async fn wait_header_imported( async fn wait_header_finalized( target_client: &impl TargetClient

, source_header_id: &HeaderId

, -) -> Result<(), String> { +) -> Result<(), ErrorOf

> { loop { let is_header_finalized = target_client.is_header_finalized(source_header_id).await.map_err(|err| { - format!( - "Failed to check finality of header {}/{} on {} node: {:?}", + Error::Finality( source_header_id.0, - source_header_id.1, + source_header_id.1.clone(), P::TARGET_NAME, - err, + anyhow!("{:?}", err), ) })?; match is_header_finalized { @@ -691,14 +675,12 @@ pub(crate) mod tests { source: &TestTransactionsSource, target: &TestTransactionsTarget, ) { - assert_eq!( - async_std::task::block_on(relay_single_transaction_proof( - source, - target, - test_transaction_hash(0), - )), - Ok(()), - ); + assert!(async_std::task::block_on(relay_single_transaction_proof( + source, + target, + test_transaction_hash(0) + )) + .is_ok()); assert_eq!( target.data.lock().submitted_proofs, vec![TestTransactionProof(test_transaction_hash(0))], @@ -711,7 +693,7 @@ pub(crate) mod tests { &target, test_transaction_hash(0), )) - .is_err(),); + .is_err()); assert!(target.data.lock().submitted_proofs.is_empty()); } diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 2b19a30e21244..84f4f9261163c 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -17,6 +17,7 @@ //! Relaying proofs of exchange transactions. use crate::{ + error::Error, exchange::{ relay_block_transactions, BlockNumberOf, RelayedBlockTransactions, SourceClient, TargetClient, TransactionProofPipeline, @@ -24,6 +25,7 @@ use crate::{ exchange_loop_metrics::ExchangeLoopMetrics, }; +use crate::error::ErrorOf; use backoff::backoff::Backoff; use futures::{future::FutureExt, select}; use num_traits::One; @@ -92,7 +94,7 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> anyhow::Result<()> { +) -> Result<(), ErrorOf

> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) @@ -111,6 +113,7 @@ pub async fn run( ) }) .await + .map_err(Error::Utils) } /// Run proofs synchronization. diff --git a/relays/exchange/src/lib.rs b/relays/exchange/src/lib.rs index 370f085b4bf7c..d167e5aa398ee 100644 --- a/relays/exchange/src/lib.rs +++ b/relays/exchange/src/lib.rs @@ -21,6 +21,7 @@ #![warn(missing_docs)] +pub mod error; pub mod exchange; pub mod exchange_loop; pub mod exchange_loop_metrics; diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 3ecda234db3ef..944da9837ffcb 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -7,7 +7,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" [dependencies] -anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index c64c9d629bf05..1b1327ffde590 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -110,7 +110,7 @@ pub async fn run( sync_params: FinalitySyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> anyhow::Result<()> { +) -> Result<(), relay_utils::Error> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) diff --git a/relays/headers/Cargo.toml b/relays/headers/Cargo.toml index 8eda40e9356f8..31d3166a99781 100644 --- a/relays/headers/Cargo.toml +++ b/relays/headers/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index d54a445d7f0e5..419211835aa8e 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -143,7 +143,7 @@ pub async fn run>( sync_params: HeadersSyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> anyhow::Result<()> { +) -> Result<(), relay_utils::Error> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 7ab81b786b5d0..5be28bccfb3bb 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" +thiserror = "1.0.26" async-std = "1.9.0" async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "2.2.0" } diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs new file mode 100644 index 0000000000000..802499503563d --- /dev/null +++ b/relays/lib-substrate-relay/src/error.rs @@ -0,0 +1,58 @@ +// 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 . + +//! Relay errors. + +use relay_substrate_client as client; +use sp_finality_grandpa::AuthorityList; +use sp_runtime::traits::MaybeDisplay; +use std::fmt::Debug; +use thiserror::Error; + +/// Relay errors. +#[derive(Error, Debug)] +pub enum Error { + /// Failed to submit signed extrinsic from to the target chain. + #[error("Failed to submit {0} transaction: {1:?}")] + SubmitTransaction(&'static str, client::Error), + /// Failed subscribe to justification stream of the source chain. + #[error("Failed to subscribe to {0} justifications: {1:?}")] + Subscribe(&'static str, client::Error), + /// Failed subscribe to read justification from the source chain (client error). + #[error("Failed to read {0} justification from the stream: {1}")] + ReadJustification(&'static str, client::Error), + /// Failed subscribe to read justification from the source chain (stream ended). + #[error("Failed to read {0} justification from the stream: stream has ended unexpectedly")] + ReadJustificationStreamEnded(&'static str), + /// Failed subscribe to decode justification from the source chain. + #[error("Failed to decode {0} justification: {1:?}")] + DecodeJustification(&'static str, codec::Error), + /// GRANDPA authorities read from the source chain are invalid. + #[error("Read invalid {0} authorities set: {1:?}")] + ReadInvalidAuthorities(&'static str, AuthorityList), + /// Failed to guess initial GRANDPA authorities at the given header of the source chain. + #[error("Failed to guess initial {0} GRANDPA authorities set id: checked all possible ids in range [0; {1}]")] + GuessInitialAuthorities(&'static str, HeaderNumber), + /// Failed to retrieve GRANDPA authorities at the given header from the source chain. + #[error("Failed to retrive {0} GRANDPA authorities set at header {1}: {2:?}")] + RetrieveAuthorities(&'static str, Hash, client::Error), + /// Failed to decode GRANDPA authorities at the given header of the source chain. + #[error("Failed to decode {0} GRANDPA authorities set at header {1}: {2:?}")] + DecodeAuthorities(&'static str, Hash, codec::Error), + /// Failed to retrieve header by the hash from the source chain. + #[error("Failed to retrieve {0} header with hash {1}: {:?}")] + RetrieveHeader(&'static str, Hash, client::Error), +} diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index 00397434a0d7e..ca82f50942ab3 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -21,6 +21,8 @@ //! and authorities set from source to target chain. The headers sync starts //! with this header. +use crate::error::Error; + use bp_header_chain::{ find_grandpa_authorities_scheduled_change, justification::{verify_justification, GrandpaJustification}, @@ -32,7 +34,7 @@ use num_traits::{One, Zero}; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; -use sp_runtime::traits::Header as HeaderT; +use sp_runtime::traits::{Header as HeaderT, Header}; /// Submit headers-bridge initialization transaction. pub async fn initialize( @@ -77,7 +79,7 @@ async fn do_initialize( prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + Send + 'static, -) -> Result { +) -> Result::Number>> { let initialization_data = prepare_initialization_data(source_client).await?; log::info!( target: "bridge", @@ -92,41 +94,40 @@ async fn do_initialize( prepare_initialize_transaction(transaction_nonce, initialization_data) }) .await - .map_err(|err| format!("Failed to submit {} transaction: {:?}", TargetChain::NAME, err))?; + .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; Ok(initialization_tx_hash) } /// Prepare initialization data for the GRANDPA verifier pallet. async fn prepare_initialization_data( source_client: Client, -) -> Result, String> { +) -> Result< + InitializationData, + Error::Number>, +> { // In ideal world we just need to get best finalized header and then to read GRANDPA authorities // set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at this header. // // But now there are problems with this approach - `CurrentSetId` may return invalid value. So // here we're waiting for the next justification, read the authorities set and then try to // figure out the set id with bruteforce. - let justifications = source_client.subscribe_justifications().await.map_err(|err| { - format!("Failed to subscribe to {} justifications: {:?}", SourceChain::NAME, err) - })?; - + let justifications = source_client + .subscribe_justifications() + .await + .map_err(|err| Error::Subscribe(SourceChain::NAME, err))?; // Read next justification - the header that it finalizes will be used as initial header. let justification = justifications .next() .await - .map_err(|err| err.to_string()) + .map_err(|e| Error::ReadJustification(SourceChain::NAME, e)) .and_then(|justification| { - justification.ok_or_else(|| "stream has ended unexpectedly".into()) - }) - .map_err(|err| { - format!("Failed to read {} justification from the stream: {}", SourceChain::NAME, err,) + justification.ok_or_else(|| Error::ReadJustificationStreamEnded(SourceChain::NAME)) })?; // Read initial header. let justification: GrandpaJustification = - Decode::decode(&mut &justification.0[..]).map_err(|err| { - format!("Failed to decode {} justification: {:?}", SourceChain::NAME, err) - })?; + Decode::decode(&mut &justification.0[..]) + .map_err(|err| Error::DecodeJustification(SourceChain::NAME, err))?; let (initial_header_hash, initial_header_number) = (justification.commit.target_hash, justification.commit.target_number); @@ -174,11 +175,7 @@ async fn prepare_initialization_data( let mut min_possible_block_number = SourceChain::BlockNumber::zero(); let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()) .ok_or_else(|| { - format!( - "Read invalid {} authorities set: {:?}", - SourceChain::NAME, - authorities_for_verification, - ) + Error::ReadInvalidAuthorities(SourceChain::NAME, authorities_for_verification) })?; loop { log::trace!( @@ -205,12 +202,7 @@ async fn prepare_initialization_data( // there can't be more authorities set changes than headers => if we have reached // `initial_block_number` and still have not found correct value of // `initial_authorities_set_id`, then something else is broken => fail - return Err(format!( - "Failed to guess initial {} GRANDPA authorities set id: checked all\ - possible ids in range [0; {}]", - SourceChain::NAME, - initial_header_number - )) + return Err(Error::GuessInitialAuthorities(SourceChain::NAME, initial_header_number)) } } @@ -230,37 +222,24 @@ async fn prepare_initialization_data( async fn source_header( source_client: &Client, header_hash: SourceChain::Hash, -) -> Result { - source_client.header_by_hash(header_hash).await.map_err(|err| { - format!( - "Failed to retrive {} header with hash {}: {:?}", - SourceChain::NAME, - header_hash, - err, - ) - }) +) -> Result::Number>> +{ + source_client + .header_by_hash(header_hash) + .await + .map_err(|err| Error::RetrieveHeader(SourceChain::NAME, header_hash, err)) } /// Read GRANDPA authorities set at given header. async fn source_authorities_set( source_client: &Client, header_hash: SourceChain::Hash, -) -> Result { - let raw_authorities_set = - source_client.grandpa_authorities_set(header_hash).await.map_err(|err| { - format!( - "Failed to retrive {} GRANDPA authorities set at header {}: {:?}", - SourceChain::NAME, - header_hash, - err, - ) - })?; - GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..]).map_err(|err| { - format!( - "Failed to decode {} GRANDPA authorities set at header {}: {:?}", - SourceChain::NAME, - header_hash, - err, - ) - }) +) -> Result::Number>> +{ + let raw_authorities_set = source_client + .grandpa_authorities_set(header_hash) + .await + .map_err(|err| Error::RetrieveAuthorities(SourceChain::NAME, header_hash, err))?; + GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..]) + .map_err(|err| Error::DecodeAuthorities(SourceChain::NAME, header_hash, err)) } diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 380bcfef2db5f..dac6b8caa8e5c 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -19,6 +19,7 @@ #![warn(missing_docs)] pub mod conversion_rate_update; +pub mod error; pub mod finality_pipeline; pub mod finality_target; pub mod headers_initialize; diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 8fc0e7c4f19e6..ea5d46845c5a3 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -anyhow = "1.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" futures = "0.3.5" diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 595d241bf3014..bfd1a2b94082b 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -263,7 +263,7 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: MetricsParams, exit_signal: impl Future + Send + 'static, -) -> anyhow::Result<()> { +) -> Result<(), relay_utils::Error> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ea5f33b77e85b..652ff54002833 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,6 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.15" time = "0.2" +thiserror = "1.0.26" # Substrate dependencies diff --git a/relays/utils/src/error.rs b/relays/utils/src/error.rs new file mode 100644 index 0000000000000..2e4128feb072a --- /dev/null +++ b/relays/utils/src/error.rs @@ -0,0 +1,46 @@ +// 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 . + +use std::net::AddrParseError; +use thiserror::Error; + +/// Result type used by relay utilities. +pub type Result = std::result::Result; + +/// Relay utilities errors. +#[derive(Error, Debug)] +pub enum Error { + /// Failed to request a float value from HTTP service. + #[error("Failed to fetch token price from remote server: {0}")] + FetchTokenPrice(#[source] anyhow::Error), + /// Failed to parse the response from HTTP service. + #[error("Failed to parse HTTP service response: {0:?}. Response: {1:?}")] + ParseHttp(serde_json::Error, String), + /// Failed to select response value from the JSON response. + #[error("Failed to select value from response: {0:?}. Response: {1:?}")] + SelectResponseValue(jsonpath_lib::JsonPathError, String), + /// Failed to parse float value from the selected value. + #[error( + "Failed to parse float value {0:?} from response. It is assumed to be positive and normal" + )] + ParseFloat(f64), + /// Couldn't found value in the JSON response. + #[error("Missing required value from response: {0:?}")] + MissingResponseValue(String), + /// Invalid host address was used for exposing Prometheus metrics. + #[error("Invalid host {0} is used to expose Prometheus metrics: {1}")] + ExposingMetricsInvalidHost(String, AddrParseError), + /// Prometheus error. + #[error("{0}")] + Prometheus(#[from] substrate_prometheus_endpoint::prometheus::Error), +} diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index deec1d688a7de..936e9ba68156a 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -16,11 +16,13 @@ //! Utilities used by different relays. +pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::future::FutureExt; use std::time::Duration; +use thiserror::Error; /// Max delay after connection-unrelated error happened before we'll try the /// same request again. @@ -29,6 +31,7 @@ pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); /// reconnection again. pub const CONNECTION_ERROR_DELAY: Duration = Duration::from_secs(10); +pub mod error; pub mod initialize; pub mod metrics; pub mod relay_loop; @@ -111,11 +114,13 @@ pub trait MaybeConnectionError { } /// Stringified error that may be either connection-related or not. -#[derive(Debug)] +#[derive(Error, Debug)] pub enum StringifiedMaybeConnectionError { /// The error is connection-related error. + #[error("{0}")] Connection(String), /// The error is connection-unrelated error. + #[error("{0}")] NonConnection(String), } @@ -139,15 +144,6 @@ impl MaybeConnectionError for StringifiedMaybeConnectionError { } } -impl ToString for StringifiedMaybeConnectionError { - fn to_string(&self) -> String { - match *self { - StringifiedMaybeConnectionError::Connection(ref err) => err.clone(), - StringifiedMaybeConnectionError::NonConnection(ref err) => err.clone(), - } - } -} - /// Exponential backoff for connection-unrelated errors retries. pub fn retry_backoff() -> ExponentialBackoff { ExponentialBackoff { diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index a57cc5a77f579..9404695c1c305 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -14,8 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{ - metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64, +use crate::{ + error::{self, Error}, + metrics::{ + metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, + F64, + }, }; use async_std::sync::{Arc, RwLock}; @@ -61,27 +65,18 @@ impl FloatJsonValueMetric { self.shared_value_ref.clone() } - /// Read value from HTTP service. - async fn read_value(&self) -> Result { + /// Request value from HTTP service. + async fn request_value(&self) -> anyhow::Result { use isahc::{AsyncReadResponseExt, HttpClient, Request}; - fn map_isahc_err(err: impl std::fmt::Display) -> String { - format!("Failed to fetch token price from remote server: {}", err) - } - - let request = Request::get(&self.url) - .header("Accept", "application/json") - .body(()) - .map_err(map_isahc_err)?; - let raw_response = HttpClient::new() - .map_err(map_isahc_err)? - .send_async(request) - .await - .map_err(map_isahc_err)? - .text() - .await - .map_err(map_isahc_err)?; + let request = Request::get(&self.url).header("Accept", "application/json").body(())?; + let raw_response = HttpClient::new()?.send_async(request).await?.text().await?; + Ok(raw_response) + } + /// Read value from HTTP service. + async fn read_value(&self) -> error::Result { + let raw_response = self.request_value().await.map_err(Error::FetchTokenPrice)?; parse_service_response(&self.json_path, &raw_response) } } @@ -94,30 +89,26 @@ impl StandaloneMetrics for FloatJsonValueMetric { async fn update(&self) { let value = self.read_value().await; - crate::metrics::set_gauge_value(&self.metric, value.clone().map(Some)); - *self.shared_value_ref.write().await = value.ok(); + let maybe_ok = value.as_ref().ok().copied(); + crate::metrics::set_gauge_value(&self.metric, value.map(Some)); + *self.shared_value_ref.write().await = maybe_ok; } } /// Parse HTTP service response. -fn parse_service_response(json_path: &str, response: &str) -> Result { - let json = serde_json::from_str(response).map_err(|err| { - format!("Failed to parse HTTP service response: {:?}. Response: {:?}", err, response,) - })?; +fn parse_service_response(json_path: &str, response: &str) -> error::Result { + let json = + serde_json::from_str(response).map_err(|err| Error::ParseHttp(err, response.to_owned()))?; let mut selector = jsonpath_lib::selector(&json); - let maybe_selected_value = selector(json_path).map_err(|err| { - format!("Failed to select value from response: {:?}. Response: {:?}", err, response,) - })?; + let maybe_selected_value = + selector(json_path).map_err(|err| Error::SelectResponseValue(err, response.to_owned()))?; let selected_value = maybe_selected_value .first() .and_then(|v| v.as_f64()) - .ok_or_else(|| format!("Missing required value from response: {:?}", response,))?; + .ok_or_else(|| Error::MissingResponseValue(response.to_owned()))?; if !selected_value.is_normal() || selected_value < 0.0 { - return Err(format!( - "Failed to parse float value {:?} from response. It is assumed to be positive and normal", - selected_value, - )) + return Err(Error::ParseFloat(selected_value)) } Ok(selected_value) diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 49047a8810d6f..4898185a150b8 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::{ + error::Error, metrics::{Metrics, MetricsAddress, MetricsParams, PrometheusError, StandaloneMetrics}, FailedClient, MaybeConnectionError, }; @@ -116,7 +117,7 @@ impl Loop { /// This function represents an outer loop, which in turn calls provided `run_loop` function to /// do actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, /// target or both) and calls `run_loop` again. - pub async fn run(mut self, loop_name: String, run_loop: R) -> anyhow::Result<()> + pub async fn run(mut self, loop_name: String, run_loop: R) -> Result<(), Error> where R: 'static + Send + Fn(SC, TC, Option) -> F, F: 'static + Send + Future>, @@ -162,7 +163,7 @@ impl LoopMetrics { pub fn loop_metric( self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> anyhow::Result> { + ) -> Result, Error> { let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref())?; Ok(LoopMetrics { @@ -178,13 +179,13 @@ impl LoopMetrics { pub fn standalone_metric( self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> anyhow::Result { + ) -> Result { // since standalone metrics are updating themselves, we may just ignore the fact that the // same standalone metric is exposed by several loops && only spawn single metric match create_metric(&self.registry, self.metrics_prefix.as_deref()) { Ok(standalone_metrics) => standalone_metrics.spawn(), Err(PrometheusError::AlreadyReg) => (), - Err(e) => anyhow::bail!(e), + Err(e) => return Err(e.into()), } Ok(self) @@ -202,16 +203,13 @@ impl LoopMetrics { /// Expose metrics using address passed at creation. /// /// If passed `address` is `None`, metrics are not exposed. - pub async fn expose(self) -> anyhow::Result> { + pub async fn expose(self) -> Result, Error> { if let Some(address) = self.address { let socket_addr = SocketAddr::new( - address.host.parse().map_err(|err| { - anyhow::format_err!( - "Invalid host {} is used to expose Prometheus metrics: {}", - address.host, - err, - ) - })?, + address + .host + .parse() + .map_err(|err| Error::ExposingMetricsInvalidHost(address.host.clone(), err))?, address.port, ); From a9fb0ddb1fcffdac618c01799bdd556648bc996a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 25 Oct 2021 12:08:14 +0300 Subject: [PATCH 0592/1210] cargo +nightly fmt --all (#1192) --- bin/millau/runtime/src/lib.rs | 4 +--- modules/ethereum/src/validators.rs | 1 + modules/ethereum/src/verification.rs | 1 + modules/token-swap/src/lib.rs | 1 + relays/bin-substrate/src/chains/mod.rs | 18 ++++++++++-------- .../src/chains/rialto_headers_to_millau.rs | 2 +- .../src/chains/westend_headers_to_millau.rs | 2 +- relays/bin-substrate/src/cli/init_bridge.rs | 4 ++-- .../src/cli/register_parachain.rs | 2 +- .../src/cli/resubmit_transactions.rs | 6 +++--- .../src/headers_initialize.rs | 16 +++++++--------- relays/messages/src/message_race_delivery.rs | 2 +- 12 files changed, 30 insertions(+), 29 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4e43868fe86e3..92d1c8614d23e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -65,9 +65,7 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; -pub use pallet_bridge_grandpa::{ - Call as BridgeGrandpaRialtoCall, Call as BridgeGrandpaWestendCall, -}; +pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs index 020e6fa796126..fd010d52c39de 100644 --- a/modules/ethereum/src/validators.rs +++ b/modules/ethereum/src/validators.rs @@ -132,6 +132,7 @@ impl<'a> Validators<'a> { } let receipts = receipts.ok_or(Error::MissingTransactionsReceipts)?; + #[allow(clippy::question_mark)] if header.check_receipts_root(&receipts).is_err() { return Err(Error::TransactionsReceiptsMismatch) } diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs index c708a6ba2d0b3..053ce4d0fea4d 100644 --- a/modules/ethereum/src/verification.rs +++ b/modules/ethereum/src/verification.rs @@ -152,6 +152,7 @@ pub fn accept_aura_header_into_pool( // the heaviest, but rare operation - we do not want invalid receipts in the pool if let Some(receipts) = receipts { log::trace!(target: "runtime", "Got receipts! {:?}", receipts); + #[allow(clippy::question_mark)] if header.check_receipts_root(receipts).is_err() { return Err(Error::TransactionsReceiptsMismatch) } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 60ca1221dd07e..43fa13ba4bdb8 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -226,6 +226,7 @@ pub mod pallet { /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. /// Violating other rules will lead to losing message fees for this and other transactions + /// losing fees for message transfer. + #[allow(clippy::boxed_local)] #[pallet::weight( T::WeightInfo::create_swap() .saturating_add(T::WeightInfo::send_message_weight( diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 1e5e549d519a9..2cbe3fe614622 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -287,10 +287,11 @@ mod rococo_tests { Box::new(header.clone()), justification.clone(), ); - let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( - Box::new(header), - justification, - ); + let expected = + millau_runtime::BridgeGrandpaCall::::submit_finality_proof( + Box::new(header), + justification, + ); // when let actual_encoded = actual.encode(); @@ -335,10 +336,11 @@ mod westend_tests { header.clone(), justification.clone(), ); - let expected = millau_runtime::BridgeGrandpaRialtoCall::::submit_finality_proof( - Box::new(header), - justification, - ); + let expected = + millau_runtime::BridgeGrandpaCall::::submit_finality_proof( + Box::new(header), + justification, + ); // when let actual_encoded = actual.encode(); diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 79ce6160b87f6..f4a2f1efe781a 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -66,7 +66,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { header: RialtoSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = millau_runtime::BridgeGrandpaRialtoCall::< + let call = millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, >::submit_finality_proof(Box::new(header.into_inner()), proof) diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 1ea8fc7dd794e..41b76283e2024 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -74,7 +74,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { header: WestendSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = millau_runtime::BridgeGrandpaWestendCall::< + let call = millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, >::submit_finality_proof(Box::new(header.into_inner()), proof) diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index f1c957f5e217d..bdabc0177d990 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -75,7 +75,7 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - let initialize_call = millau_runtime::BridgeGrandpaRialtoCall::< + let initialize_call = millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, >::initialize(init_data); @@ -95,7 +95,7 @@ macro_rules! select_bridge { // our deployments may fail, because we need to initialize both Rialto -> Millau // and Westend -> Millau bridge. => since there's single possible sudo account, // one of transaction may fail with duplicate nonce error - millau_runtime::BridgeGrandpaWestendCall::< + millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, >::initialize(init_data) diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 4f15bbec86c00..7d7622ef488ea 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -112,7 +112,7 @@ impl RegisterParachain { // step 1: reserve a parachain id let relay_genesis_hash = *relay_client.genesis_hash(); - let relay_sudo_account: AccountIdOf = relay_sign.public().clone().into(); + let relay_sudo_account: AccountIdOf = relay_sign.public().into(); let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve().into(); let reserve_parachain_signer = relay_sign.clone(); wait_until_transaction_is_finalized::( diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 1091048b3ba00..66728622d755d 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -134,9 +134,9 @@ impl ResubmitTransactions { transaction: None, resubmitted: 0, stalled_for: Zero::zero(), - stalled_for_limit: self.stalled_blocks.into(), - tip_step: self.tip_step.cast().into(), - tip_limit: self.tip_limit.cast().into(), + stalled_for_limit: self.stalled_blocks as _, + tip_step: self.tip_step.cast() as _, + tip_limit: self.tip_limit.cast() as _, }, ) }) diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index ca82f50942ab3..2e802c4cb2150 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -34,7 +34,7 @@ use num_traits::{One, Zero}; use relay_substrate_client::{Chain, Client}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; -use sp_runtime::traits::{Header as HeaderT, Header}; +use sp_runtime::traits::Header as HeaderT; /// Submit headers-bridge initialization transaction. pub async fn initialize( @@ -79,7 +79,7 @@ async fn do_initialize( prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + Send + 'static, -) -> Result::Number>> { +) -> Result::Number>> { let initialization_data = prepare_initialization_data(source_client).await?; log::info!( target: "bridge", @@ -103,7 +103,7 @@ async fn prepare_initialization_data( source_client: Client, ) -> Result< InitializationData, - Error::Number>, + Error::Number>, > { // In ideal world we just need to get best finalized header and then to read GRANDPA authorities // set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at this header. @@ -121,7 +121,7 @@ async fn prepare_initialization_data( .await .map_err(|e| Error::ReadJustification(SourceChain::NAME, e)) .and_then(|justification| { - justification.ok_or_else(|| Error::ReadJustificationStreamEnded(SourceChain::NAME)) + justification.ok_or(Error::ReadJustificationStreamEnded(SourceChain::NAME)) })?; // Read initial header. @@ -174,9 +174,7 @@ async fn prepare_initialization_data( let mut initial_authorities_set_id = 0; let mut min_possible_block_number = SourceChain::BlockNumber::zero(); let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()) - .ok_or_else(|| { - Error::ReadInvalidAuthorities(SourceChain::NAME, authorities_for_verification) - })?; + .ok_or(Error::ReadInvalidAuthorities(SourceChain::NAME, authorities_for_verification))?; loop { log::trace!( target: "bridge", "Trying {} GRANDPA authorities set id: {}", @@ -222,7 +220,7 @@ async fn prepare_initialization_data( async fn source_header( source_client: &Client, header_hash: SourceChain::Hash, -) -> Result::Number>> +) -> Result::Number>> { source_client .header_by_hash(header_hash) @@ -234,7 +232,7 @@ async fn source_header( async fn source_authorities_set( source_client: &Client, header_hash: SourceChain::Hash, -) -> Result::Number>> +) -> Result::Number>> { let raw_authorities_set = source_client .grandpa_authorities_set(header_hash) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 3433b683d7a77..4fd721dae5977 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -444,7 +444,7 @@ where ); return None - } + }, _ => (), } From a6d6ee52a4fa4eb984890d6708ca9404a87a9b2d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 25 Oct 2021 13:24:36 +0300 Subject: [PATCH 0593/1210] Bump dependencies (#1180) * substrate: d0f6c1c60da22e04dd25c2eca46ebfe6f1571af0 polkadot: dd4b2e6a34a08a01b876d14641e99e7011be3463 cumulus: 9379cd6c1863ea846ad6c6a8cbbc99848dd5d693 * fmt * fixed lost refs * spelling * benckhmarks * fmt --- bin/millau/node/src/service.rs | 2 + bin/millau/runtime/Cargo.toml | 2 + bin/millau/runtime/src/lib.rs | 6 +- bin/millau/runtime/src/rialto_messages.rs | 3 +- bin/rialto-parachain/runtime/Cargo.toml | 4 +- bin/rialto-parachain/runtime/src/lib.rs | 4 +- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/chain_spec.rs | 1 - bin/rialto/node/src/overseer.rs | 151 ++++++++++-------- bin/rialto/node/src/service.rs | 100 ++++++------ bin/rialto/runtime/Cargo.toml | 2 + bin/rialto/runtime/src/exchange.rs | 5 +- bin/rialto/runtime/src/lib.rs | 20 ++- bin/rialto/runtime/src/millau_messages.rs | 5 +- bin/rialto/runtime/src/parachains.rs | 8 +- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages.rs | 5 +- modules/currency-exchange/Cargo.toml | 2 + modules/dispatch/Cargo.toml | 2 + modules/dispatch/src/lib.rs | 60 ++++--- modules/ethereum/Cargo.toml | 2 + modules/ethereum/src/finality.rs | 5 +- modules/ethereum/src/lib.rs | 11 +- modules/grandpa/Cargo.toml | 3 + modules/grandpa/src/mock.rs | 5 +- modules/messages/Cargo.toml | 2 + modules/messages/src/lib.rs | 1 - modules/messages/src/mock.rs | 9 +- modules/shift-session-manager/Cargo.toml | 2 + modules/shift-session-manager/src/lib.rs | 4 +- modules/token-swap/Cargo.toml | 2 + primitives/chain-kusama/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 2 + primitives/chain-millau/src/lib.rs | 3 +- primitives/chain-millau/src/millau_hash.rs | 3 +- primitives/chain-polkadot/Cargo.toml | 2 +- primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 4 +- primitives/chain-westend/src/lib.rs | 35 +--- primitives/currency-exchange/Cargo.toml | 2 + primitives/currency-exchange/src/lib.rs | 5 +- primitives/ethereum-poa/Cargo.toml | 2 + primitives/ethereum-poa/src/lib.rs | 13 +- primitives/header-chain/Cargo.toml | 2 + primitives/header-chain/src/justification.rs | 3 +- primitives/header-chain/src/lib.rs | 9 +- primitives/message-dispatch/Cargo.toml | 2 + primitives/message-dispatch/src/lib.rs | 5 +- primitives/messages/Cargo.toml | 2 + primitives/messages/src/lib.rs | 19 +-- primitives/messages/src/target_chain.rs | 3 +- primitives/polkadot-core/Cargo.toml | 2 + primitives/polkadot-core/src/lib.rs | 12 +- primitives/runtime/Cargo.toml | 2 + primitives/runtime/src/messages.rs | 5 +- primitives/token-swap/Cargo.toml | 2 + primitives/token-swap/src/lib.rs | 9 +- relays/bin-ethereum/src/instances.rs | 32 ++-- relays/bin-substrate/src/chains/millau.rs | 20 ++- .../src/chains/millau_headers_to_rialto.rs | 8 +- .../src/chains/millau_messages_to_rialto.rs | 16 +- relays/bin-substrate/src/chains/mod.rs | 40 +++-- relays/bin-substrate/src/chains/rialto.rs | 20 ++- .../src/chains/rialto_headers_to_millau.rs | 5 +- .../src/chains/rialto_messages_to_millau.rs | 16 +- .../src/chains/rialto_parachain.rs | 14 +- .../src/chains/westend_headers_to_millau.rs | 5 +- relays/bin-substrate/src/cli/init_bridge.rs | 19 ++- .../src/cli/register_parachain.rs | 35 ++-- relays/bin-substrate/src/cli/swap_tokens.rs | 33 ++-- relays/client-kusama/Cargo.toml | 1 + relays/client-kusama/src/runtime.rs | 13 +- relays/client-polkadot/Cargo.toml | 1 + relays/client-polkadot/src/runtime.rs | 13 +- relays/client-rococo/Cargo.toml | 1 + relays/client-rococo/src/runtime.rs | 9 +- relays/client-wococo/Cargo.toml | 1 + relays/client-wococo/src/runtime.rs | 9 +- 78 files changed, 514 insertions(+), 380 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index ce9cfc10ef101..b8d42f9c7ed34 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -210,6 +210,7 @@ pub fn new_full(mut config: Configuration) -> Result let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), + vec![], )); let (network, system_rpc_tx, network_starter) = @@ -470,6 +471,7 @@ pub fn new_light(mut config: Configuration) -> Result let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), + vec![], )); let (network, system_rpc_tx, network_starter) = diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 7e2a5491f5b15..c8d7f0a159582 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -89,6 +90,7 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "scale-info/std", "serde", "sp-api/std", "sp-block-builder/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 92d1c8614d23e..4e486c267010d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -240,6 +240,7 @@ impl pallet_grandpa::Config for Runtime { type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); + type MaxAuthorities = MaxAuthorities; } parameter_types! { @@ -281,6 +282,7 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; + pub const OperationalFeeMultiplier: u8 = 5; // values for following parameters are copied from polkadot repo, but it is fine // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); @@ -291,6 +293,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = bp_millau::WeightToFee; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< Runtime, @@ -320,7 +323,6 @@ impl pallet_session::Config for Runtime { type SessionManager = pallet_shift_session_manager::Pallet; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - type DisabledValidatorsThreshold = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); } @@ -523,7 +525,7 @@ impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 37fc7715f989d..6d9677c45cf91 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -31,6 +31,7 @@ use frame_support::{ weights::{DispatchClass, Weight}, RuntimeDebug, }; +use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; @@ -274,7 +275,7 @@ impl SourceHeaderChain for Rialto { } /// Millau -> Rialto message lane pallet parameters. -#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] +#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum MillauToRialtoMessagesParameter { /// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`. RialtoToMillauConversionRate(FixedU128), diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index d12e4326711d9..20ce70aba8f6b 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -13,6 +13,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive']} log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = '1.0', optional = true, features = ['derive'] } # Bridge depedencies @@ -83,8 +84,9 @@ runtime-benchmarks = [ std = [ "bp-rialto-parachain/std", "codec/std", - "serde", "log/std", + "scale-info/std", + "serde", "sp-api/std", "sp-std/std", "sp-io/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index bf55f08eb4b96..5b71674b7fe9b 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -228,6 +228,7 @@ parameter_types! { pub const TransferFee: u128 = MILLIUNIT; pub const CreationFee: u128 = MILLIUNIT; pub const TransactionByteFee: u128 = MICROUNIT; + pub const OperationalFeeMultiplier: u8 = 5; pub const MaxLocks: u32 = 50; pub const MaxReserves: u32 = 50; } @@ -249,6 +250,7 @@ impl pallet_balances::Config for Runtime { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -486,7 +488,7 @@ impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 08c72ce67632a..75be9bcd9fb7d 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -14,6 +14,7 @@ futures = "0.3" jsonrpc-core = "18.0" kvdb = "0.10" kvdb-rocksdb = "0.12" +lru = "0.7" structopt = "0.3.21" serde_json = "1.0.59" thiserror = "1.0" diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 8c6b147f48204..3ccfa13e74acb 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -264,7 +264,6 @@ fn testnet_genesis( ump_service_total_weight: 4 * 1_000_000_000, max_upward_message_size: 1024 * 1024, max_upward_message_num_per_candidate: 5, - _hrmp_open_request_ttl: 5, hrmp_sender_deposit: 0, hrmp_recipient_deposit: 0, hrmp_channel_max_capacity: 8, diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs index 1c381c1df8fdd..0139f3cdf835d 100644 --- a/bin/rialto/node/src/overseer.rs +++ b/bin/rialto/node/src/overseer.rs @@ -23,6 +23,7 @@ use crate::service::{AuthorityDiscoveryApi, Error}; use rialto_runtime::{opaque::Block, Hash}; +use lru::LruCache; use polkadot_availability_distribution::IncomingRequestReceivers; use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; use polkadot_node_core_av_store::Config as AvailabilityConfig; @@ -30,7 +31,10 @@ use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver}; -use polkadot_overseer::{AllSubsystems, BlockInfo, Overseer, OverseerHandle}; +use polkadot_overseer::{ + metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder, + OverseerConnector, OverseerHandle, +}; use polkadot_primitives::v1::ParachainHost; use sc_authority_discovery::Service as AuthorityDiscoveryService; use sc_client_api::AuxStore; @@ -107,12 +111,11 @@ where pub dispute_coordinator_config: DisputeCoordinatorConfig, } -/// Create a default, unaltered set of subsystems. -/// -/// A convenience for usage with malus, to avoid -/// repetitive code across multiple behavior strain implementations. -pub fn create_default_subsystems( +/// Obtain a prepared `OverseerBuilder`, that is initialized +/// with all default values. +pub fn prepared_overseer_builder<'a, Spawner, RuntimeClient>( OverseerGenArgs { + leaves, keystore, runtime_client, parachains_db, @@ -120,6 +123,7 @@ pub fn create_default_subsystems( authority_discovery_service, pov_req_receiver, chunk_req_receiver, + collation_req_receiver: _, available_data_req_receiver, statement_req_receiver, dispute_req_receiver, @@ -130,10 +134,11 @@ pub fn create_default_subsystems( candidate_validation_config, chain_selection_config, dispute_coordinator_config, - .. - }: OverseerGenArgs<'_, Spawner, RuntimeClient>, + }: OverseerGenArgs<'a, Spawner, RuntimeClient>, ) -> Result< - AllSubsystems< + OverseerBuilder< + Spawner, + Arc, CandidateValidationSubsystem, CandidateBackingSubsystem, StatementDistributionSubsystem, @@ -153,7 +158,7 @@ pub fn create_default_subsystems( CollatorProtocolSubsystem, ApprovalDistributionSubsystem, ApprovalVotingSubsystem, - GossipSupportSubsystem, + GossipSupportSubsystem, DisputeCoordinatorSubsystem, DisputeParticipationSubsystem, DisputeDistributionSubsystem, @@ -167,86 +172,104 @@ where Spawner: 'static + SpawnNamed + Clone + Unpin, { use polkadot_node_subsystem_util::metrics::Metrics; + use std::iter::FromIterator; + + let metrics = ::register(registry)?; - let all_subsystems = AllSubsystems { - availability_distribution: AvailabilityDistributionSubsystem::new( + let builder = Overseer::builder() + .availability_distribution(AvailabilityDistributionSubsystem::new( keystore.clone(), IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, Metrics::register(registry)?, - ), - availability_recovery: AvailabilityRecoverySubsystem::with_chunks_only( + )) + .availability_recovery(AvailabilityRecoverySubsystem::with_chunks_only( available_data_req_receiver, Metrics::register(registry)?, - ), - availability_store: AvailabilityStoreSubsystem::new( + )) + .availability_store(AvailabilityStoreSubsystem::new( parachains_db.clone(), availability_config, Metrics::register(registry)?, - ), - bitfield_distribution: BitfieldDistributionSubsystem::new(Metrics::register(registry)?), - bitfield_signing: BitfieldSigningSubsystem::new( + )) + .bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?)) + .bitfield_signing(BitfieldSigningSubsystem::new( spawner.clone(), keystore.clone(), Metrics::register(registry)?, - ), - candidate_backing: CandidateBackingSubsystem::new( + )) + .candidate_backing(CandidateBackingSubsystem::new( spawner.clone(), keystore.clone(), Metrics::register(registry)?, - ), - candidate_validation: CandidateValidationSubsystem::with_config( + )) + .candidate_validation(CandidateValidationSubsystem::with_config( candidate_validation_config, Metrics::register(registry)?, // candidate-validation metrics Metrics::register(registry)?, // validation host metrics - ), - chain_api: ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?), - collation_generation: CollationGenerationSubsystem::new(Metrics::register(registry)?), - collator_protocol: CollatorProtocolSubsystem::new(ProtocolSide::Validator { + )) + .chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?)) + .collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?)) + .collator_protocol(CollatorProtocolSubsystem::new(ProtocolSide::Validator { keystore: keystore.clone(), eviction_policy: Default::default(), metrics: Metrics::register(registry)?, - }), - network_bridge: NetworkBridgeSubsystem::new( + })) + .network_bridge(NetworkBridgeSubsystem::new( network_service.clone(), authority_discovery_service.clone(), Box::new(network_service.clone()), Metrics::register(registry)?, - ), - provisioner: ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?), - runtime_api: RuntimeApiSubsystem::new( - runtime_client, + )) + .provisioner(ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?)) + .runtime_api(RuntimeApiSubsystem::new( + runtime_client.clone(), Metrics::register(registry)?, - spawner, - ), - statement_distribution: StatementDistributionSubsystem::new( + spawner.clone(), + )) + .statement_distribution(StatementDistributionSubsystem::new( keystore.clone(), statement_req_receiver, Metrics::register(registry)?, - ), - approval_distribution: ApprovalDistributionSubsystem::new(Metrics::register(registry)?), - approval_voting: ApprovalVotingSubsystem::with_config( + )) + .approval_distribution(ApprovalDistributionSubsystem::new(Metrics::register(registry)?)) + .approval_voting(ApprovalVotingSubsystem::with_config( approval_voting_config, parachains_db.clone(), keystore.clone(), - Box::new(network_service), + Box::new(network_service.clone()), Metrics::register(registry)?, - ), - gossip_support: GossipSupportSubsystem::new(keystore.clone()), - dispute_coordinator: DisputeCoordinatorSubsystem::new( + )) + .gossip_support(GossipSupportSubsystem::new( + keystore.clone(), + authority_discovery_service.clone(), + )) + .dispute_coordinator(DisputeCoordinatorSubsystem::new( parachains_db.clone(), dispute_coordinator_config, keystore.clone(), - ), - dispute_participation: DisputeParticipationSubsystem::new(), - dispute_distribution: DisputeDistributionSubsystem::new( - keystore, + Metrics::register(registry)?, + )) + .dispute_participation(DisputeParticipationSubsystem::new()) + .dispute_distribution(DisputeDistributionSubsystem::new( + keystore.clone(), dispute_req_receiver, - authority_discovery_service, + authority_discovery_service.clone(), Metrics::register(registry)?, - ), - chain_selection: ChainSelectionSubsystem::new(chain_selection_config, parachains_db), - }; - Ok(all_subsystems) + )) + .chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db)) + .leaves(Vec::from_iter( + leaves + .into_iter() + .map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)), + )) + .activation_external_listeners(Default::default()) + .span_per_active_leaf(Default::default()) + .active_leaves(Default::default()) + .supports_parachains(runtime_client) + .known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE)) + .metrics(metrics) + .spawner(spawner); + Ok(builder) } /// Trait for the `fn` generating the overseer. @@ -255,9 +278,10 @@ where /// would do. pub trait OverseerGen { /// Overwrite the full generation of the overseer, including the subsystems. - fn generate( + fn generate<'a, Spawner, RuntimeClient>( &self, - args: OverseerGenArgs<'_, Spawner, RuntimeClient>, + connector: OverseerConnector, + args: OverseerGenArgs<'a, Spawner, RuntimeClient>, ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, @@ -265,34 +289,31 @@ pub trait OverseerGen { Spawner: 'static + SpawnNamed + Clone + Unpin, { let gen = RealOverseerGen; - RealOverseerGen::generate::(&gen, args) + RealOverseerGen::generate::(&gen, connector, args) } // It would be nice to make `create_subsystems` part of this trait, // but the amount of generic arguments that would be required as // as consequence make this rather annoying to implement and use. } +use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE; + /// The regular set of subsystems. pub struct RealOverseerGen; impl OverseerGen for RealOverseerGen { - fn generate( + fn generate<'a, Spawner, RuntimeClient>( &self, - args: OverseerGenArgs<'_, Spawner, RuntimeClient>, + connector: OverseerConnector, + args: OverseerGenArgs<'a, Spawner, RuntimeClient>, ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, Spawner: 'static + SpawnNamed + Clone + Unpin, { - let spawner = args.spawner.clone(); - let leaves = args.leaves.clone(); - let runtime_client = args.runtime_client.clone(); - let registry = args.registry; - - let all_subsystems = create_default_subsystems::(args)?; - - Overseer::new(leaves, all_subsystems, registry, runtime_client, spawner) + prepared_overseer_builder(args)? + .build_with_connector(connector) .map_err(|e| e.into()) } } diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 8a2a38a59c60b..6e9eb8a62e46f 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -33,7 +33,7 @@ use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; use polkadot_node_network_protocol::request_response::IncomingRequest; -use polkadot_overseer::BlockInfo; +use polkadot_overseer::{BlockInfo, OverseerConnector}; use polkadot_primitives::v1::BlockId; use rialto_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::ExecutorProvider; @@ -47,7 +47,7 @@ use sp_runtime::traits::{BlakeTwo256, Block as BlockT}; use std::{sync::Arc, time::Duration}; use substrate_prometheus_endpoint::Registry; -pub use polkadot_overseer::{Handle, Overseer, OverseerHandle}; +pub use polkadot_overseer::Handle; pub use polkadot_primitives::v1::ParachainHost; pub use sc_client_api::AuxStore; pub use sp_authority_discovery::AuthorityDiscoveryApi; @@ -432,6 +432,8 @@ where let prometheus_registry = config.prometheus_registry().cloned(); + let overseer_connector = OverseerConnector::default(); + let shared_voter_state = rpc_setup; let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; @@ -462,6 +464,7 @@ where let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), import_setup.1.shared_authority_set().clone(), + vec![], )); let (network, system_rpc_tx, network_starter) = @@ -586,50 +589,55 @@ where let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params { let (overseer, overseer_handle) = overseer_gen - .generate::(OverseerGenArgs { - leaves: active_leaves, - keystore, - runtime_client: overseer_client.clone(), - parachains_db, - availability_config, - approval_voting_config, - network_service: network.clone(), - authority_discovery_service, - registry: prometheus_registry.as_ref(), - spawner, - candidate_validation_config, - available_data_req_receiver, - chain_selection_config, - chunk_req_receiver, - collation_req_receiver, - dispute_coordinator_config, - dispute_req_receiver, - pov_req_receiver, - statement_req_receiver, - })?; - let handle = Handle::Connected(overseer_handle); - let handle_clone = handle.clone(); - - task_manager.spawn_essential_handle().spawn_blocking( - "overseer", - Box::pin(async move { - use futures::{pin_mut, select, FutureExt}; - - let forward = polkadot_overseer::forward_events(overseer_client, handle_clone); - - let forward = forward.fuse(); - let overseer_fut = overseer.run().fuse(); - - pin_mut!(overseer_fut); - pin_mut!(forward); - - select! { - _ = forward => (), - _ = overseer_fut => (), - complete => (), - } - }), - ); + .generate::( + overseer_connector, + OverseerGenArgs { + leaves: active_leaves, + keystore, + runtime_client: overseer_client.clone(), + parachains_db, + availability_config, + approval_voting_config, + network_service: network.clone(), + authority_discovery_service, + registry: prometheus_registry.as_ref(), + spawner, + candidate_validation_config, + available_data_req_receiver, + chain_selection_config, + chunk_req_receiver, + collation_req_receiver, + dispute_coordinator_config, + dispute_req_receiver, + pov_req_receiver, + statement_req_receiver, + }, + )?; + let handle = Handle::new(overseer_handle.clone()); + + { + let handle = handle.clone(); + task_manager.spawn_essential_handle().spawn_blocking( + "overseer", + Box::pin(async move { + use futures::{pin_mut, select, FutureExt}; + + let forward = polkadot_overseer::forward_events(overseer_client, handle); + + let forward = forward.fuse(); + let overseer_fut = overseer.run().fuse(); + + pin_mut!(overseer_fut); + pin_mut!(forward); + + select! { + _ = forward => (), + _ = overseer_fut => (), + complete => (), + } + }), + ); + } Some(handle) } else { diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 8f532448d4080..c0be917c2bccc 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = hex-literal = "0.3" libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -112,6 +113,7 @@ std = [ "polkadot-primitives/std", "polkadot-runtime-common/std", "polkadot-runtime-parachains/std", + "scale-info/std", "serde", "sp-api/std", "sp-authority-discovery/std", diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs index f940287ff76a2..4e18053e52e36 100644 --- a/bin/rialto/runtime/src/exchange.rs +++ b/bin/rialto/runtime/src/exchange.rs @@ -35,13 +35,14 @@ use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use hex_literal::hex; +use scale_info::TypeInfo; use sp_std::vec::Vec; /// Ethereum address where locked PoA funds must be sent to. pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); /// Ethereum transaction inclusion proof. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct EthereumTransactionInclusionProof { /// Hash of the block with transaction. pub block: sp_core::H256, @@ -58,7 +59,7 @@ pub struct EthereumTransactionInclusionProof { /// transactions included into finalized blocks. This is obviously true /// for any existing eth-like chain (that keep current TX format), because /// otherwise transaction can be replayed over and over. -#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub struct EthereumTransactionTag { /// Account that has locked funds. pub account: [u8; 20], diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9e70dae32efaa..bf5a8b36ec195 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -226,11 +226,13 @@ pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = parameter_types! { pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64; pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK; + pub const MaxAuthorities: u32 = 10; } impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; + type MaxAuthorities = MaxAuthorities; // session module is the trigger type EpochChangeTrigger = pallet_babe::ExternalTrigger; @@ -370,6 +372,7 @@ impl bp_currency_exchange::DepositInto for DepositInto { impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; + type MaxAuthorities = MaxAuthorities; type KeyOwnerProofSystem = (); type KeyOwnerProof = >::Proof; @@ -421,6 +424,7 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; + pub const OperationalFeeMultiplier: u8 = 5; // values for following parameters are copied from polkadot repo, but it is fine // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); @@ -431,6 +435,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type TransactionByteFee = TransactionByteFee; + type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = bp_rialto::WeightToFee; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< Runtime, @@ -454,15 +459,10 @@ impl pallet_session::Config for Runtime { type SessionManager = pallet_shift_session_manager::Pallet; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - type DisabledValidatorsThreshold = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); } -parameter_types! { - pub const MaxAuthorities: u32 = 10; -} - impl pallet_authority_discovery::Config for Runtime { type MaxAuthorities = MaxAuthorities; } @@ -662,7 +662,7 @@ impl_runtime_apis! { impl sp_api::Metadata for Runtime { fn metadata() -> OpaqueMetadata { - Runtime::metadata().into() + OpaqueMetadata::new(Runtime::metadata().into()) } } @@ -783,7 +783,7 @@ impl_runtime_apis! { slot_duration: Babe::slot_duration(), epoch_length: EpochDuration::get(), c: BABE_GENESIS_EPOCH_CONFIG.c, - genesis_authorities: Babe::authorities(), + genesis_authorities: Babe::authorities().to_vec(), randomness: Babe::randomness(), allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots, } @@ -902,6 +902,10 @@ impl_runtime_apis! { ) -> Option { polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::(hash) } + + fn on_chain_votes() -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v1::on_chain_votes::() + } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { @@ -1172,7 +1176,7 @@ impl_runtime_apis! { MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], _ => vec![], }; - let call = Call::System(SystemCall::remark(remark)); + let call = Call::System(SystemCall::remark { remark }); let call_weight = call.get_dispatch_info().weight; let millau_account_id: bp_millau::AccountId = Default::default(); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 0342f5b48ab39..13a1c6b06ec21 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -31,6 +31,7 @@ use frame_support::{ weights::{DispatchClass, Weight}, RuntimeDebug, }; +use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::{convert::TryFrom, ops::RangeInclusive}; @@ -272,7 +273,7 @@ impl SourceHeaderChain for Millau { } /// Rialto -> Millau message lane pallet parameters. -#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq)] +#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum RialtoToMillauMessagesParameter { /// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`. MillauToRialtoConversionRate(FixedU128), @@ -315,7 +316,7 @@ mod tests { SystemConfig::default().build_storage::().unwrap().into(); ext.execute_with(|| { let bridge = MILLAU_CHAIN_ID; - let call: Call = SystemCall::remark(vec![]).into(); + let call: Call = SystemCall::remark { remark: vec![] }.into(); let dispatch_weight = call.get_dispatch_info().weight; let dispatch_fee = ::WeightToFee::calc( &dispatch_weight, diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index a84723a725770..9a2f85460153c 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -39,7 +39,9 @@ impl polkadot_runtime_parachains::inclusion::RewardValidators for RewardValidato // all required parachain modules from `polkadot-runtime-parachains` crate -impl parachains_configuration::Config for Runtime {} +impl parachains_configuration::Config for Runtime { + type WeightInfo = parachains_configuration::TestWeightInfo; +} impl parachains_dmp::Config for Runtime {} @@ -58,6 +60,7 @@ impl parachains_inclusion::Config for Runtime { impl parachains_initializer::Config for Runtime { type Randomness = pallet_babe::RandomnessFromOneEpochAgo; type ForceOrigin = EnsureRoot; + type WeightInfo = (); } impl parachains_origin::Config for Runtime {} @@ -65,6 +68,7 @@ impl parachains_origin::Config for Runtime {} impl parachains_paras::Config for Runtime { type Origin = Origin; type Event = Event; + type WeightInfo = parachains_paras::TestWeightInfo; } impl parachains_paras_inherent::Config for Runtime {} @@ -83,6 +87,7 @@ impl parachains_ump::Config for Runtime { type Event = Event; type UmpSink = (); type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = EnsureRoot; } // required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing @@ -112,6 +117,7 @@ impl slots::Config for Runtime { type Registrar = Registrar; type LeasePeriod = LeasePeriod; type WeightInfo = slots::TestWeightInfo; + type LeaseOffset = (); } impl paras_sudo_wrapper::Config for Runtime {} diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 9c98e55207d5d..0ae642ba55898 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Bridge dependencies @@ -44,6 +45,7 @@ std = [ "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-transaction-payment/std", + "scale-info/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index ecca6e823c699..7c9bb685ae6c1 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -37,6 +37,7 @@ use frame_support::{ RuntimeDebug, }; use hash_db::Hasher; +use scale_info::TypeInfo; use sp_runtime::{ traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero}, FixedPointNumber, FixedPointOperand, FixedU128, @@ -216,7 +217,7 @@ pub mod source { /// - hash of finalized header; /// - storage proof of inbound lane state; /// - lane id. - #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct FromBridgedChainMessagesDeliveryProof { /// Hash of the bridge header the proof is for. pub bridged_header_hash: BridgedHeaderHash, @@ -456,7 +457,7 @@ pub mod target { /// - storage proof of messages and (optionally) outbound lane state; /// - lane id; /// - nonces (inclusive range) of messages which are included in this proof. - #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug)] + #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] pub struct FromBridgedChainMessagesProof { /// Hash of the finalized bridged header the proof is for. pub bridged_header_hash: BridgedHeaderHash, diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml index e842bf10dd533..dc06a342cc8e6 100644 --- a/modules/currency-exchange/Cargo.toml +++ b/modules/currency-exchange/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -38,6 +39,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "scale-info/std", "serde", "sp-runtime/std", "sp-std/std", diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 94b19305ab3c9..7a8a34ab4c0ea 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Bridge dependencies @@ -34,6 +35,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "scale-info/std", "sp-core/std", "sp-runtime/std", "sp-std/std", diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index 3039c6e31654d..f467bab0d9464 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -22,7 +22,6 @@ //! a successful dispatch an event is emitted. #![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] // Generated by `decl_event!` #![allow(clippy::unused_unit)] @@ -111,7 +110,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(::AccountId = "AccountId", BridgeMessageIdOf = "BridgeMessageId")] pub enum Event, I: 'static = ()> { /// Message has been rejected before reaching dispatch. MessageRejected(ChainId, BridgeMessageIdOf), @@ -431,6 +429,7 @@ mod tests { use codec::Decode; use frame_support::{parameter_types, weights::Weight}; use frame_system::{EventRecord, Phase}; + use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ testing::Header, @@ -444,7 +443,7 @@ mod tests { const SOURCE_CHAIN_ID: ChainId = *b"srce"; const TARGET_CHAIN_ID: ChainId = *b"trgt"; - #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct TestAccountPublic(AccountId); impl IdentifyAccount for TestAccountPublic { @@ -455,7 +454,7 @@ mod tests { } } - #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] + #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct TestSignature(AccountId); impl Verify for TestSignature { @@ -548,7 +547,7 @@ mod tests { impl Contains for TestCallFilter { fn contains(call: &Call) -> bool { - !matches!(*call, Call::System(frame_system::Call::fill_block(_))) + !matches!(*call, Call::System(frame_system::Call::fill_block { .. })) } } @@ -611,9 +610,9 @@ mod tests { let id = [0; 4]; const BAD_SPEC_VERSION: SpecVersion = 99; - let mut message = prepare_root_message(Call::System( - >::remark(vec![1, 2, 3]), - )); + let mut message = prepare_root_message(Call::System(frame_system::Call::remark { + remark: vec![1, 2, 3], + })); let weight = message.weight; message.spec_version = BAD_SPEC_VERSION; @@ -650,7 +649,7 @@ mod tests { fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::remark(vec![1, 2, 3])); + let call = Call::System(frame_system::Call::remark { remark: vec![1, 2, 3] }); let call_weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = 7; @@ -693,7 +692,7 @@ mod tests { let call_origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(99)); let message = prepare_message( call_origin, - Call::System(>::remark(vec![1, 2, 3])), + Call::System(frame_system::Call::remark { remark: vec![1, 2, 3] }), ); let weight = message.weight; @@ -757,9 +756,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = prepare_root_message(Call::System( - >::remark(vec![1, 2, 3]), - )); + let mut message = prepare_root_message(Call::System(frame_system::Call::remark { + remark: vec![1, 2, 3], + })); let weight = message.weight; message.call.0 = vec![]; @@ -795,9 +794,8 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::fill_block( - Perbill::from_percent(75), - )); + let call = + Call::System(frame_system::Call::fill_block { ratio: Perbill::from_percent(75) }); let weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = weight; @@ -834,9 +832,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = prepare_root_message(Call::System( - >::remark(vec![1, 2, 3]), - )); + let mut message = prepare_root_message(Call::System(frame_system::Call::remark { + remark: vec![1, 2, 3], + })); let weight = message.weight; message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; @@ -874,9 +872,9 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let mut message = prepare_root_message(Call::System( - >::remark(vec![1, 2, 3]), - )); + let mut message = prepare_root_message(Call::System(frame_system::Call::remark { + remark: vec![1, 2, 3], + })); message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; System::set_block_number(1); @@ -910,7 +908,7 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::set_heap_pages(1)); + let call = Call::System(frame_system::Call::set_heap_pages { pages: 1 }); let message = prepare_target_message(call); System::set_block_number(1); @@ -943,9 +941,9 @@ mod tests { fn should_dispatch_bridge_message_from_root_origin() { new_test_ext().execute_with(|| { let id = [0; 4]; - let message = prepare_root_message(Call::System( - >::remark(vec![1, 2, 3]), - )); + let message = prepare_root_message(Call::System(frame_system::Call::remark { + remark: vec![1, 2, 3], + })); System::set_block_number(1); let result = Dispatch::dispatch( @@ -978,7 +976,7 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::remark { remark: vec![] }); let message = prepare_target_message(call); System::set_block_number(1); @@ -1012,7 +1010,7 @@ mod tests { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::remark { remark: vec![] }); let message = prepare_source_message(call); System::set_block_number(1); @@ -1043,7 +1041,7 @@ mod tests { #[test] fn origin_is_checked_when_verifying_sending_message_using_source_root_account() { - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::remark { remark: vec![] }); let message = prepare_root_message(call); // When message is sent by Root, CallOrigin::SourceRoot is allowed @@ -1055,7 +1053,7 @@ mod tests { #[test] fn origin_is_checked_when_verifying_sending_message_using_target_account() { - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::remark { remark: vec![] }); let message = prepare_target_message(call); // When message is sent by Root, CallOrigin::TargetAccount is not allowed @@ -1071,7 +1069,7 @@ mod tests { #[test] fn origin_is_checked_when_verifying_sending_message_using_source_account() { - let call = Call::System(>::remark(vec![])); + let call = Call::System(frame_system::Call::remark { remark: vec![] }); let message = prepare_source_message(call); // Sending a message from the expected origin account works diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml index ce890fa2abb78..baa9336118079 100644 --- a/modules/ethereum/Cargo.toml +++ b/modules/ethereum/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"], optional = true } log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -38,6 +39,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "scale-info/std", "serde", "sp-io/std", "sp-runtime/std", diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs index 34b766f7e0219..fe8841fcc044f 100644 --- a/modules/ethereum/src/finality.rs +++ b/modules/ethereum/src/finality.rs @@ -17,6 +17,7 @@ use crate::{error::Error, Storage}; use bp_eth_poa::{public_to_address, Address, AuraHeader, HeaderId, SealedEmptyStep, H256}; use codec::{Decode, Encode}; +use scale_info::TypeInfo; use sp_io::crypto::secp256k1_ecdsa_recover; use sp_runtime::RuntimeDebug; use sp_std::{ @@ -55,7 +56,7 @@ pub struct FinalityEffects { } /// Finality votes for given block. -#[derive(RuntimeDebug, Decode, Encode)] +#[derive(RuntimeDebug, Decode, Encode, TypeInfo)] #[cfg_attr(test, derive(Clone, PartialEq))] pub struct FinalityVotes { /// Number of votes per each validator. @@ -66,7 +67,7 @@ pub struct FinalityVotes { } /// Information about block ancestor that is used in computations. -#[derive(RuntimeDebug, Decode, Encode)] +#[derive(RuntimeDebug, Decode, Encode, TypeInfo)] #[cfg_attr(test, derive(Clone, Default, PartialEq))] pub struct FinalityAncestor { /// Bock id. diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs index ad2382a949001..4224818ad96c6 100644 --- a/modules/ethereum/src/lib.rs +++ b/modules/ethereum/src/lib.rs @@ -24,6 +24,7 @@ use bp_eth_poa::{ }; use codec::{Decode, Encode}; use frame_support::traits::Get; +use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; use sp_std::{boxed::Box, cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; @@ -81,7 +82,7 @@ pub struct PoolConfiguration { } /// Block header as it is stored in the runtime storage. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub struct StoredHeader { /// Submitter of this header. May be `None` if header has been submitted /// using unsigned transaction. @@ -102,7 +103,7 @@ pub struct StoredHeader { } /// Validators set as it is stored in the runtime storage. -#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] #[cfg_attr(test, derive(Clone))] pub struct ValidatorsSet { /// Validators of this set. @@ -114,7 +115,7 @@ pub struct ValidatorsSet { } /// Validators set change as it is stored in the runtime storage. -#[derive(Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] #[cfg_attr(test, derive(Clone))] pub struct AuraScheduledChange { /// Validators of this set. @@ -158,7 +159,7 @@ pub struct ChangeToEnact { } /// Blocks range that we want to prune. -#[derive(Encode, Decode, Default, RuntimeDebug, Clone, PartialEq)] +#[derive(Encode, Decode, Default, RuntimeDebug, Clone, PartialEq, TypeInfo)] struct PruningRange { /// Number of the oldest unpruned block(s). This might be the block that we do not /// want to prune now (then it is equal to `oldest_block_to_keep`), or block that we @@ -478,7 +479,7 @@ pub mod pallet { fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { match *call { - Self::Call::import_unsigned_header(ref header, ref receipts) => { + Self::Call::import_unsigned_header { ref header, ref receipts } => { let accept_result = verification::accept_aura_header_into_pool( &BridgeStorage::::new(), &T::AuraConfiguration::get(), diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 020d24766dee1..e36b43585b9b6 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = finality-grandpa = { version = "0.14.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -33,6 +34,7 @@ bp-test-utils = { path = "../../primitives/test-utils", default-features = false frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } [dev-dependencies] +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] @@ -47,6 +49,7 @@ std = [ "frame-system/std", "log/std", "num-traits/std", + "scale-info/std", "serde", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index dcbae4e60f9bc..183a567791563 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -19,10 +19,11 @@ use bp_runtime::Chain; use frame_support::{construct_runtime, parameter_types, weights::Weight}; +use sp_core::sr25519::Signature; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, IdentityLookup}, - AnySignature, Perbill, + Perbill, }; pub type AccountId = u64; @@ -105,7 +106,7 @@ impl Chain for TestBridgedChain { type AccountId = AccountId; type Balance = u64; type Index = u64; - type Signature = AnySignature; + type Signature = Signature; } pub fn run_test(test: impl FnOnce() -> T) -> T { diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index cc0be45406556..6d52b899ea2bc 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -11,6 +11,7 @@ bitvec = { version = "0.20", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -45,6 +46,7 @@ std = [ "frame-system/std", "log/std", "num-traits/std", + "scale-info/std", "serde", "sp-core/std", "sp-runtime/std", diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 8d2e239781cbb..119869d81e982 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -652,7 +652,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(T::Parameter = "Parameter")] pub enum Event, I: 'static = ()> { /// Pallet parameter has been updated. ParameterUpdated(T::Parameter), diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 5cc905d912124..a333c95bb58b8 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -37,6 +37,7 @@ use frame_support::{ parameter_types, weights::{RuntimeDbWeight, Weight}, }; +use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -50,7 +51,7 @@ use std::{ pub type AccountId = u64; pub type Balance = u64; -#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq)] +#[derive(Decode, Encode, Clone, Debug, PartialEq, Eq, TypeInfo)] pub struct TestPayload { /// Field that may be used to identify messages. pub id: u64, @@ -150,7 +151,7 @@ parameter_types! { pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; } -#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)] +#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum TestMessagesParameter { TokenConversionRate(FixedU128), } @@ -226,7 +227,7 @@ pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = message_payload(1, 50) pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages>)>; /// Test messages proof. -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq)] +#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct TestMessagesProof { pub result: Result, } @@ -255,7 +256,7 @@ impl From>, ()>> for TestMessagesProof { } /// Messages delivery proof used in tests. -#[derive(Debug, Encode, Decode, Eq, Clone, PartialEq)] +#[derive(Debug, Encode, Decode, Eq, Clone, PartialEq, TypeInfo)] pub struct TestMessagesDeliveryProof(pub Result<(LaneId, InboundLaneData), ()>); impl Size for TestMessagesDeliveryProof { diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index d42cb4341a616..9e3e15fddf897 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies @@ -28,6 +29,7 @@ std = [ "frame-support/std", "frame-system/std", "pallet-session/std", + "scale-info/std", "sp-staking/std", "sp-std/std", ] diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 511cbaa1cbeb6..06d0b3fb0f8d4 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -109,6 +109,7 @@ mod tests { traits::{BlakeTwo256, ConvertInto, IdentityLookup}, Perbill, RuntimeAppPublic, }, + traits::GenesisBuild, weights::Weight, BasicExternalities, }; @@ -177,7 +178,6 @@ mod tests { type SessionManager = (); type SessionHandler = TestSessionHandler; type Keys = UintAuthorityId; - type DisabledValidatorsThreshold = (); type WeightInfo = (); } @@ -197,7 +197,7 @@ mod tests { ) { } - fn on_disabled(_: usize) {} + fn on_disabled(_: u32) {} } fn new_test_ext() -> TestExternalities { diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index b68eed6d59e08..a6103f688c424 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } log = { version = "0.4.14", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -46,6 +47,7 @@ std = [ "log/std", "pallet-bridge-dispatch/std", "pallet-bridge-messages/std", + "scale-info/std", "serde", "sp-core/std", "sp-io/std", diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 061a89a7d877f..6ff860357c7c4 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.6" +smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index a0630fa8a9ff0..f1e17fe96f5ac 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -17,6 +17,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.5.1", default-features = false } impl-serde = { version = "0.3.1", optional = true } parity-util-mem = { version = "0.10", default-features = false, features = ["primitive-types"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Based Dependencies @@ -42,6 +43,7 @@ std = [ "impl-codec/std", "impl-serde", "parity-util-mem/std", + "scale-info/std", "serde", "sp-api/std", "sp-core/std", diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 950c82d5224bb..0092f7092bc0d 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -29,6 +29,7 @@ use frame_support::{ Parameter, RuntimeDebug, }; use frame_system::limits; +use scale_info::TypeInfo; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{Convert, IdentifyAccount, Verify}, @@ -174,7 +175,7 @@ impl Chain for Millau { } /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. -#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct BlakeTwoAndKeccak256; diff --git a/primitives/chain-millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs index 936791217af18..11968b2f28267 100644 --- a/primitives/chain-millau/src/millau_hash.rs +++ b/primitives/chain-millau/src/millau_hash.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use parity_util_mem::MallocSizeOf; +use scale_info::TypeInfo; use sp_runtime::traits::CheckEqual; // `sp_core::H512` can't be used, because it doesn't implement `CheckEqual`, which is required @@ -22,7 +23,7 @@ use sp_runtime::traits::CheckEqual; fixed_hash::construct_fixed_hash! { /// Hash type used in Millau chain. - #[derive(MallocSizeOf)] + #[derive(MallocSizeOf, TypeInfo)] pub struct MillauHash(64); } diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 181b230d61dd6..917c7f9747839 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.6" +smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index dd0d9b37e42cd..6e1189b05f363 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } -smallvec = "1.6" +smallvec = "1.7" # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 7230ba359c420..4fd1652744ed6 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -8,7 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } -smallvec = "1.6" +scale-info = { version = "1.0", default-features = false, features = ["derive"] } +smallvec = "1.7" # Bridge Dependencies @@ -34,6 +35,7 @@ std = [ "bp-runtime/std", "frame-support/std", "parity-scale-codec/std", + "scale-info/std", "sp-api/std", "sp-runtime/std", "sp-std/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 480a5e56dd4c8..8beb897f59a15 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -21,10 +21,10 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use bp_runtime::Chain; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use scale_info::TypeInfo; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -51,8 +51,6 @@ impl WeightToFeePolynomial for WeightToFee { } } -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - // NOTE: This needs to be kept up to date with the Westend runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("westend"), @@ -66,32 +64,11 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// Westend Runtime `Call` enum. /// -/// The enum represents a subset of possible `Call`s we can send to Westend chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Westend -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/westend/src/lib.rs) -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -pub enum Call { - /// Rococo bridge pallet. - #[codec(index = 40)] - BridgeGrandpaRococo(BridgeGrandpaRococoCall), -} - -#[derive(parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaRococoCall { - #[codec(index = 0)] - submit_finality_proof( - ::Header, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} +/// We are not currently submitting any Westend transactions => it is empty. +#[derive( + parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone, TypeInfo, +)] +pub enum Call {} impl sp_runtime::traits::Dispatchable for Call { type Origin = (); diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml index f47ab6e61b7a3..165891f0c6b1d 100644 --- a/primitives/currency-exchange/Cargo.toml +++ b/primitives/currency-exchange/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies @@ -20,6 +21,7 @@ default = ["std"] std = [ "codec/std", "frame-support/std", + "scale-info/std", "sp-api/std", "sp-std/std", ] diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs index a3bdbbb2f42fb..1a30915b1cbfa 100644 --- a/primitives/currency-exchange/src/lib.rs +++ b/primitives/currency-exchange/src/lib.rs @@ -22,6 +22,7 @@ use codec::{Decode, Encode, EncodeLike}; use frame_support::{Parameter, RuntimeDebug}; +use scale_info::TypeInfo; use sp_api::decl_runtime_apis; use sp_std::marker::PhantomData; @@ -48,7 +49,7 @@ pub enum Error { pub type Result = sp_std::result::Result; /// Peer blockchain lock funds transaction. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct LockFundsTransaction { /// Something that uniquely identifies this transfer. pub id: TransferId, @@ -63,7 +64,7 @@ pub trait MaybeLockFundsTransaction { /// Transaction type. type Transaction; /// Identifier that uniquely identifies this transfer. - type Id: Decode + Encode + EncodeLike + sp_std::fmt::Debug; + type Id: Decode + Encode + TypeInfo + EncodeLike + sp_std::fmt::Debug; /// Peer recipient type. type Recipient; /// Peer currency amount type. diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml index e7acd80eff23d..71f071bbf0e6d 100644 --- a/primitives/ethereum-poa/Cargo.toml +++ b/primitives/ethereum-poa/Cargo.toml @@ -18,6 +18,7 @@ parity-bytes = { version = "0.1", default-features = false } plain_hasher = { version = "0.2.2", default-features = false } primitive-types = { version = "0.10", default-features = false, features = ["codec", "rlp"] } rlp = { version = "0.5", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } serde-big-array = { version = "0.2", optional = true } triehash = { version = "0.8.2", default-features = false } @@ -47,6 +48,7 @@ std = [ "primitive-types/std", "primitive-types/serde", "rlp/std", + "scale-info/std", "serde/std", "serde-big-array", "sp-api/std", diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs index c63cf2b8f65c9..58f5731e52222 100644 --- a/primitives/ethereum-poa/src/lib.rs +++ b/primitives/ethereum-poa/src/lib.rs @@ -28,6 +28,7 @@ use codec::{Decode, Encode}; use ethbloom::{Bloom as EthBloom, Input as BloomInput}; use fixed_hash::construct_fixed_hash; use rlp::{Decodable, DecoderError, Rlp, RlpStream}; +use scale_info::TypeInfo; use sp_io::hashing::keccak_256; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; @@ -57,7 +58,7 @@ pub type Address = H160; pub mod signatures; /// Complete header id. -#[derive(Encode, Decode, Default, RuntimeDebug, PartialEq, Clone, Copy)] +#[derive(Encode, Decode, Default, RuntimeDebug, PartialEq, Clone, Copy, TypeInfo)] pub struct HeaderId { /// Header number. pub number: u64, @@ -66,7 +67,7 @@ pub struct HeaderId { } /// An Aura header. -#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct AuraHeader { /// Parent block hash. @@ -129,7 +130,7 @@ pub struct UnsignedTransaction { } /// Information describing execution of a transaction. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub struct Receipt { /// The total gas used in the block following execution of the transaction. pub gas_used: U256, @@ -142,7 +143,7 @@ pub struct Receipt { } /// Transaction outcome store in the receipt. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub enum TransactionOutcome { /// Status and state root are unknown under EIP-98 rules. Unknown, @@ -153,7 +154,7 @@ pub enum TransactionOutcome { } /// A record of execution for a `LOG` operation. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] +#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] pub struct LogEntry { /// The address of the contract executing at the point of the `LOG` operation. pub address: Address, @@ -164,7 +165,7 @@ pub struct LogEntry { } /// Logs bloom. -#[derive(Clone, Encode, Decode)] +#[derive(Clone, Encode, Decode, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Bloom(#[cfg_attr(feature = "std", serde(with = "BigArray"))] [u8; 256]); diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index ecd7c17341a14..b75a41a4b2e59 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } finality-grandpa = { version = "0.14.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Substrate Dependencies @@ -30,6 +31,7 @@ std = [ "finality-grandpa/std", "serde/std", "frame-support/std", + "scale-info/std", "sp-core/std", "sp-finality-grandpa/std", "sp-runtime/std", diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 2d092496e8d54..9f8e9662ea0f0 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -22,6 +22,7 @@ use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use frame_support::RuntimeDebug; +use scale_info::TypeInfo; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::traits::Header as HeaderT; use sp_std::{ @@ -34,7 +35,7 @@ use sp_std::{ /// /// This particular proof is used to prove that headers on a bridged chain /// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] pub struct GrandpaJustification { /// The round (voting period) this justification is valid for. pub round: u64, diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 66dd42e148298..5feb30aec3eee 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -21,6 +21,7 @@ use codec::{Codec, Decode, Encode, EncodeLike}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; +use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; @@ -32,11 +33,11 @@ pub mod justification; /// A type that can be used as a parameter in a dispatchable function. /// /// When using `decl_module` all arguments for call functions must implement this trait. -pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug {} -impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug {} +pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug + TypeInfo {} +impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug + TypeInfo {} /// A GRANDPA Authority List and ID. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone)] +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct AuthoritySet { /// List of GRANDPA authorities for the current round. @@ -55,7 +56,7 @@ impl AuthoritySet { /// Data required for initializing the bridge pallet. /// /// The bridge needs to know where to start its sync from, and this provides that initial context. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone)] +#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct InitializationData { /// The header from which we should start syncing. diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 9553b50d99d7c..9897b3199781d 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies @@ -21,5 +22,6 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", + "scale-info/std", "sp-std/std", ] diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs index 5f39197b11751..07e448ee7ae62 100644 --- a/primitives/message-dispatch/src/lib.rs +++ b/primitives/message-dispatch/src/lib.rs @@ -25,6 +25,7 @@ use bp_runtime::{ }; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; +use scale_info::TypeInfo; use sp_std::prelude::*; /// Message dispatch weight. @@ -71,7 +72,7 @@ pub trait MessageDispatch { /// The source chain can (and should) verify that the message can be dispatched on the target chain /// with a particular origin given the source chain's origin. This can be done with the /// `verify_message_origin()` function. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub enum CallOrigin { /// Call is sent by the Root origin on the source chain. On the target chain it is dispatched /// from a derived account. @@ -111,7 +112,7 @@ pub enum CallOrigin; /// Message key (unique message identifier) as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct MessageKey { /// ID of the message lane. pub lane_id: LaneId, @@ -90,7 +91,7 @@ pub struct MessageKey { } /// Message data as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct MessageData { /// Message payload. pub payload: MessagePayload, @@ -99,7 +100,7 @@ pub struct MessageData { } /// Message as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub struct Message { /// Message key. pub key: MessageKey, @@ -108,7 +109,7 @@ pub struct Message { } /// Inbound lane data. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct InboundLaneData { /// Identifiers of relayers and messages that they have delivered to this lane (ordered by /// message nonce). @@ -198,7 +199,7 @@ pub type DispatchResultsBitVec = BitVec; /// /// This struct represents a continuous range of messages that have been delivered by the same /// relayer and whose confirmations are still pending. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct UnrewardedRelayer { /// Identifier of the relayer. pub relayer: RelayerId, @@ -207,7 +208,7 @@ pub struct UnrewardedRelayer { } /// Delivered messages with their dispatch result. -#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct DeliveredMessages { /// Nonce of the first message that has been delivered (inclusive). pub begin: MessageNonce, @@ -267,7 +268,7 @@ impl DeliveredMessages { } /// Gist of `InboundLaneData::relayers` field used by runtime APIs. -#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct UnrewardedRelayersState { /// Number of entries in the `InboundLaneData::relayers` set. pub unrewarded_relayer_entries: MessageNonce, @@ -279,7 +280,7 @@ pub struct UnrewardedRelayersState { } /// Outbound lane data. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct OutboundLaneData { /// Nonce of the oldest message that we haven't yet pruned. May point to not-yet-generated /// message if all sent messages are already pruned. diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index e3f458ac8fce5..a84ea7af907de 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -21,13 +21,14 @@ use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; +use scale_info::TypeInfo; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*}; /// Proved messages from the source chain. pub type ProvedMessages = BTreeMap>; /// Proved messages from single lane of the source chain. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq)] +#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct ProvedLaneMessages { /// Optional outbound lane state. pub lane_state: Option, diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 7801112c6ddab..f05edd0d91ba3 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Bridge Dependencies @@ -35,6 +36,7 @@ std = [ "frame-support/std", "frame-system/std", "parity-scale-codec/std", + "scale-info/std", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 8f5fab60ab3ff..38e43d312b5d4 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -29,6 +29,7 @@ use frame_support::{ }; use frame_system::limits; use parity_scale_codec::Compact; +use scale_info::{StaticTypeInfo, TypeInfo}; use sp_core::Hasher as HasherT; use sp_runtime::{ generic, @@ -255,7 +256,7 @@ pub type AdditionalSigned = (u32, u32, Hash, Hash, (), (), ()); /// A simplified version of signed extensions meant for producing signed transactions /// and signed payload in the client code. -#[derive(PartialEq, Eq, Clone, RuntimeDebug)] +#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] pub struct SignedExtensions { encode_payload: SignedExtra, additional_signed: AdditionalSigned, @@ -322,7 +323,14 @@ impl SignedExtensions { impl sp_runtime::traits::SignedExtension for SignedExtensions where - Call: parity_scale_codec::Codec + sp_std::fmt::Debug + Sync + Send + Clone + Eq + PartialEq, + Call: parity_scale_codec::Codec + + sp_std::fmt::Debug + + Sync + + Send + + Clone + + Eq + + PartialEq + + StaticTypeInfo, Call: Dispatchable, { const IDENTIFIER: &'static str = "Not needed."; diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index f27235a1b20b3..944f84a6c6835 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" 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 @@ -28,6 +29,7 @@ std = [ "frame-support/std", "hash-db/std", "num-traits/std", + "scale-info/std", "sp-core/std", "sp-io/std", "sp-runtime/std", diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index c351d771cf871..7a6687c18b776 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -18,9 +18,10 @@ use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; +use scale_info::TypeInfo; /// Where message dispatch fee is paid? -#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq, TypeInfo)] pub enum DispatchFeePayment { /// The dispatch fee is paid at the source chain. AtSourceChain, @@ -34,7 +35,7 @@ pub enum DispatchFeePayment { } /// Message dispatch result. -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq)] +#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] pub struct MessageDispatchResult { /// Dispatch result flag. This flag is relayed back to the source chain and, generally /// speaking, may bring any (that fits in single bit) information from the dispatcher at diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index dd42f4e4a0c91..4b16c3567ea6e 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Substrate Dependencies @@ -20,6 +21,7 @@ default = ["std"] std = [ "codec/std", "frame-support/std", + "scale-info/std", "sp-core/std", "sp-std/std", ] diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index 48aaeb38c3b4b..d46389e86891d 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -18,11 +18,12 @@ use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; +use scale_info::TypeInfo; use sp_core::U256; use sp_std::vec::Vec; /// Pending token swap state. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub enum TokenSwapState { /// The swap has been started using the `start_claim` call, but we have no proof that it has /// happened at the Bridged chain. @@ -39,7 +40,7 @@ pub enum TokenSwapState { /// /// Different swap types give a different guarantees regarding possible swap /// replay protection. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub enum TokenSwapType { /// The `target_account_at_bridged_chain` is temporary and only have funds for single swap. /// @@ -68,7 +69,7 @@ pub enum TokenSwapType { /// when chain changes, the meaning of This and Bridged are still used to point to the same chains. /// This chain is always the chain where swap has been started. And the Bridged chain is the other /// chain. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct TokenSwap { /// The type of the swap. @@ -88,7 +89,7 @@ pub struct TokenSwap; /// Token swap creation parameters. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct TokenSwapCreation { /// Public key of the `target_account_at_bridged_chain` account used to verify /// `bridged_currency_transfer_signature`. diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs index 3f2ebf825be77..74feb1da320d4 100644 --- a/relays/bin-ethereum/src/instances.rs +++ b/relays/bin-ethereum/src/instances.rs @@ -50,8 +50,8 @@ pub struct RialtoPoA; impl BridgeInstance for RialtoPoA { fn build_signed_header_call(&self, headers: Vec) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers( - headers + let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers { + headers_with_receipts: headers .into_iter() .map(|header| { ( @@ -60,23 +60,23 @@ impl BridgeInstance for RialtoPoA { ) }) .collect(), - ); + }; rialto_runtime::Call::BridgeRialtoPoa(pallet_call) } fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - Box::new(into_substrate_ethereum_header(header.header())), - into_substrate_ethereum_receipts(header.extra()), - ); + let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header { + header: Box::new(into_substrate_ethereum_header(header.header())), + receipts: into_substrate_ethereum_receipts(header.extra()), + }; rialto_runtime::Call::BridgeRialtoPoa(pallet_call) } fn build_currency_exchange_call(&self, proof: Proof) -> Call { let pallet_call = - rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction { proof }; rialto_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call) } } @@ -87,8 +87,8 @@ pub struct Kovan; impl BridgeInstance for Kovan { fn build_signed_header_call(&self, headers: Vec) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers( - headers + let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers { + headers_with_receipts: headers .into_iter() .map(|header| { ( @@ -97,23 +97,23 @@ impl BridgeInstance for Kovan { ) }) .collect(), - ); + }; rialto_runtime::Call::BridgeKovan(pallet_call) } fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header( - Box::new(into_substrate_ethereum_header(header.header())), - into_substrate_ethereum_receipts(header.extra()), - ); + let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header { + header: Box::new(into_substrate_ethereum_header(header.header())), + receipts: into_substrate_ethereum_receipts(header.extra()), + }; rialto_runtime::Call::BridgeKovan(pallet_call) } fn build_currency_exchange_call(&self, proof: Proof) -> Call { let pallet_call = - rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction(proof); + rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction { proof }; rialto_runtime::Call::BridgeKovanCurrencyExchange(pallet_call) } } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 55b16b7786b73..1dbeab9a90498 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -39,18 +39,24 @@ impl CliEncodeCall for Millau { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, Call::Remark { remark_payload, .. } => - millau_runtime::Call::System(millau_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )), - Call::Transfer { recipient, amount } => millau_runtime::Call::Balances( - millau_runtime::BalancesCall::transfer(recipient.raw_id(), amount.cast()), - ), + millau_runtime::Call::System(millau_runtime::SystemCall::remark { + remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + }), + Call::Transfer { recipient, amount } => + millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer { + dest: recipient.raw_id(), + value: amount.cast(), + }), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::MILLAU_TO_RIALTO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; millau_runtime::Call::BridgeRialtoMessages( - millau_runtime::MessagesCall::send_message(lane.0, payload, fee.cast()), + millau_runtime::MessagesCall::send_message { + lane_id: lane.0, + payload, + delivery_and_dispatch_fee: fee.cast(), + }, ) }, _ => anyhow::bail!( diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index e1dc19594f4f2..14a0430f6a918 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -61,10 +61,10 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { header: MillauSyncHeader, proof: GrandpaJustification, ) -> Bytes { - let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ) + let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof, + } .into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 9c56e8bd3d404..612fd96d0fcaa 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -95,7 +95,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { ) -> Bytes { let (relayers_state, proof) = proof; let call: millau_runtime::Call = - millau_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state) + millau_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.source_client.genesis_hash(); @@ -130,12 +130,12 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; - let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), + let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof { + relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), proof, - messages_count as _, + messages_count: messages_count as _, dispatch_weight, - ) + } .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.target_client.genesis_hash(); @@ -290,11 +290,11 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( &signer, relay_substrate_client::TransactionEra::immortal(), UnsignedTransaction::new( - millau_runtime::MessagesCall::update_pallet_parameter( - millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( + millau_runtime::MessagesCall::update_pallet_parameter { + parameter: millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), - ) + } .into(), transaction_nonce, ), diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 2cbe3fe614622..a96d46d9ecc8d 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -82,7 +82,8 @@ mod tests { fn millau_signature_is_valid_on_rialto() { let millau_sign = relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); - let call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); + let call = + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); let millau_public: bp_millau::AccountSigner = millau_sign.public().into(); let millau_account_id: bp_millau::AccountId = millau_public.into_account(); @@ -104,7 +105,8 @@ mod tests { fn rialto_signature_is_valid_on_millau() { let rialto_sign = relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); - let call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); + let call = + millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); let rialto_public: bp_rialto::AccountSigner = rialto_sign.public().into(); let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); @@ -132,7 +134,8 @@ mod tests { ); let call: millau_runtime::Call = - millau_runtime::SystemCall::remark(vec![42; maximal_remark_size as _]).into(); + millau_runtime::SystemCall::remark { remark: vec![42; maximal_remark_size as _] } + .into(); let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, @@ -143,7 +146,8 @@ mod tests { assert_eq!(Millau::verify_message(&payload), Ok(())); let call: millau_runtime::Call = - millau_runtime::SystemCall::remark(vec![42; (maximal_remark_size + 1) as _]).into(); + millau_runtime::SystemCall::remark { remark: vec![42; (maximal_remark_size + 1) as _] } + .into(); let payload = send_message::message_payload( Default::default(), call.get_dispatch_info().weight, @@ -171,7 +175,8 @@ mod tests { let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( bp_millau::max_extrinsic_weight(), ); - let call: millau_runtime::Call = rialto_runtime::SystemCall::remark(vec![]).into(); + let call: millau_runtime::Call = + rialto_runtime::SystemCall::remark { remark: vec![] }.into(); let payload = send_message::message_payload( Default::default(), @@ -199,7 +204,8 @@ mod tests { let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( bp_rialto::max_extrinsic_weight(), ); - let call: rialto_runtime::Call = millau_runtime::SystemCall::remark(vec![]).into(); + let call: rialto_runtime::Call = + millau_runtime::SystemCall::remark { remark: vec![] }.into(); let payload = send_message::message_payload( Default::default(), @@ -222,7 +228,8 @@ mod tests { #[test] fn rialto_tx_extra_bytes_constant_is_correct() { - let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark(vec![])); + let rialto_call = + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); let rialto_tx = Rialto::sign_transaction( Default::default(), &sp_keyring::AccountKeyring::Alice.pair(), @@ -240,7 +247,8 @@ mod tests { #[test] fn millau_tx_extra_bytes_constant_is_correct() { - let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark(vec![])); + let millau_call = + millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); let millau_tx = Millau::sign_transaction( Default::default(), &sp_keyring::AccountKeyring::Alice.pair(), @@ -288,10 +296,10 @@ mod rococo_tests { justification.clone(), ); let expected = - millau_runtime::BridgeGrandpaCall::::submit_finality_proof( - Box::new(header), + millau_runtime::BridgeGrandpaCall::::submit_finality_proof { + finality_target: Box::new(header), justification, - ); + }; // when let actual_encoded = actual.encode(); @@ -332,15 +340,15 @@ mod westend_tests { votes_ancestries: vec![], }; - let actual = bp_westend::BridgeGrandpaRococoCall::submit_finality_proof( - header.clone(), + let actual = relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof( + Box::new(header.clone()), justification.clone(), ); let expected = - millau_runtime::BridgeGrandpaCall::::submit_finality_proof( - Box::new(header), + millau_runtime::BridgeGrandpaCall::::submit_finality_proof { + finality_target: Box::new(header), justification, - ); + }; // when let actual_encoded = actual.encode(); diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 837957bb87a1b..4c1a0166ed3b2 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -39,18 +39,24 @@ impl CliEncodeCall for Rialto { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, Call::Remark { remark_payload, .. } => - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - )), - Call::Transfer { recipient, amount } => rialto_runtime::Call::Balances( - rialto_runtime::BalancesCall::transfer(recipient.raw_id().into(), amount.0), - ), + rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { + remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + }), + Call::Transfer { recipient, amount } => + rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer { + dest: recipient.raw_id().into(), + value: amount.0, + }), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::RIALTO_TO_MILLAU_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; rialto_runtime::Call::BridgeMillauMessages( - rialto_runtime::MessagesCall::send_message(lane.0, payload, fee.0), + rialto_runtime::MessagesCall::send_message { + lane_id: lane.0, + payload, + delivery_and_dispatch_fee: fee.0, + }, ) }, _ => anyhow::bail!( diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index f4a2f1efe781a..7e76f403c55aa 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -69,7 +69,10 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { let call = millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, - >::submit_finality_proof(Box::new(header.into_inner()), proof) + >::submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof, + } .into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 99960cd00f5a0..35f0852dcb67d 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -95,7 +95,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { ) -> Bytes { let (relayers_state, proof) = proof; let call: rialto_runtime::Call = - rialto_runtime::MessagesCall::receive_messages_delivery_proof(proof, relayers_state) + rialto_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.source_client.genesis_hash(); @@ -130,12 +130,12 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let (dispatch_weight, proof) = proof; let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; let messages_count = nonces_end - nonces_start + 1; - let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), + let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof { + relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), proof, - messages_count as _, + messages_count: messages_count as _, dispatch_weight, - ) + } .into(); let call_weight = call.get_dispatch_info().weight; let genesis_hash = *self.message_lane.target_client.genesis_hash(); @@ -289,11 +289,11 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( &signer, relay_substrate_client::TransactionEra::immortal(), UnsignedTransaction::new( - rialto_runtime::MessagesCall::update_pallet_parameter( - rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( + rialto_runtime::MessagesCall::update_pallet_parameter { + parameter: rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), - ) + } .into(), transaction_nonce, ), diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 4c9f63bbe41f6..edd4ca3628540 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -35,15 +35,15 @@ impl CliEncodeCall for RialtoParachain { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, Call::Remark { remark_payload, .. } => rialto_parachain_runtime::Call::System( - rialto_parachain_runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - ), + rialto_parachain_runtime::SystemCall::remark { + remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), + }, ), Call::Transfer { recipient, amount } => rialto_parachain_runtime::Call::Balances( - rialto_parachain_runtime::BalancesCall::transfer( - recipient.raw_id().into(), - amount.0, - ), + rialto_parachain_runtime::BalancesCall::transfer { + dest: recipient.raw_id().into(), + value: amount.0, + }, ), Call::BridgeSendMessage { .. } => anyhow::bail!("Bridge messages are not (yet) supported here",), diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 41b76283e2024..64d8ba4d889d7 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -77,7 +77,10 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { let call = millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, - >::submit_finality_proof(Box::new(header.into_inner()), proof) + >::submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof, + } .into(); let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index bdabc0177d990..ffda0b1200884 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -60,9 +60,12 @@ macro_rules! select_bridge { fn encode_init_bridge( init_data: InitializationData<::Header>, ) -> ::Call { - rialto_runtime::SudoCall::sudo(Box::new( - rialto_runtime::BridgeGrandpaMillauCall::initialize(init_data).into(), - )) + rialto_runtime::SudoCall::sudo { + call: Box::new( + rialto_runtime::BridgeGrandpaMillauCall::initialize { init_data } + .into(), + ), + } .into() } @@ -78,8 +81,10 @@ macro_rules! select_bridge { let initialize_call = millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, - >::initialize(init_data); - millau_runtime::SudoCall::sudo(Box::new(initialize_call.into())).into() + >::initialize { + init_data, + }; + millau_runtime::SudoCall::sudo { call: Box::new(initialize_call.into()) }.into() } $generic @@ -98,7 +103,9 @@ macro_rules! select_bridge { millau_runtime::BridgeGrandpaCall::< millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, - >::initialize(init_data) + >::initialize { + init_data, + } .into() } diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 7d7622ef488ea..fecc431148ebd 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -113,7 +113,8 @@ impl RegisterParachain { // step 1: reserve a parachain id let relay_genesis_hash = *relay_client.genesis_hash(); let relay_sudo_account: AccountIdOf = relay_sign.public().into(); - let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve().into(); + let reserve_parachain_id_call: CallOf = + ParaRegistrarCall::reserve {}.into(); let reserve_parachain_signer = relay_sign.clone(); wait_until_transaction_is_finalized::( relay_client @@ -155,11 +156,11 @@ impl RegisterParachain { para_genesis_header.encode().len(), para_code.len(), ); - let register_parathread_call: CallOf = ParaRegistrarCall::register( - para_id, - ParaHeadData(para_genesis_header.encode()), - ParaValidationCode(para_code), - ) + let register_parathread_call: CallOf = ParaRegistrarCall::register { + id: para_id, + genesis_head: ParaHeadData(para_genesis_header.encode()), + validation_code: ParaValidationCode(para_code), + } .into(); let register_parathread_signer = relay_sign.clone(); wait_until_transaction_is_finalized::( @@ -211,16 +212,18 @@ impl RegisterParachain { lease_begin, lease_end, ); - let force_lease_call: CallOf = SudoCall::sudo(Box::new( - ParaSlotsCall::force_lease( - para_id, - relay_sudo_account.clone(), - para_deposit, - lease_begin, - lease_end, - ) - .into(), - )) + let force_lease_call: CallOf = SudoCall::sudo { + call: Box::new( + ParaSlotsCall::force_lease { + para: para_id, + leaser: relay_sudo_account.clone(), + amount: para_deposit, + period_begin: lease_begin, + period_count: lease_end.saturating_sub(lease_begin).saturating_add(1), + } + .into(), + ), + } .into(); let force_lease_signer = relay_sign.clone(); relay_client diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 9f4b3ba698fd7..aa3996aa41364 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -176,10 +176,10 @@ impl SwapTokens { // // prepare `Currency::transfer` call that will happen at the target chain - let bridged_currency_transfer: CallOf = pallet_balances::Call::transfer( - accounts.source_account_at_bridged_chain.clone().into(), - token_swap.target_balance_at_bridged_chain, - ) + let bridged_currency_transfer: CallOf = pallet_balances::Call::transfer { + dest: accounts.source_account_at_bridged_chain.clone().into(), + value: token_swap.target_balance_at_bridged_chain, + } .into(); let bridged_currency_transfer_weight = bridged_currency_transfer.get_dispatch_info().weight; @@ -218,9 +218,9 @@ impl SwapTokens { }, ) .await?; - let create_swap_call: CallOf = pallet_bridge_token_swap::Call::create_swap( - token_swap.clone(), - Box::new(bp_token_swap::TokenSwapCreation { + let create_swap_call: CallOf = pallet_bridge_token_swap::Call::create_swap { + swap: token_swap.clone(), + swap_creation_params: Box::new(bp_token_swap::TokenSwapCreation { target_public_at_bridged_chain, swap_delivery_and_dispatch_fee, bridged_chain_spec_version, @@ -228,7 +228,7 @@ impl SwapTokens { bridged_currency_transfer_weight, bridged_currency_transfer_signature, }), - ) + } .into(); // start tokens swap @@ -341,7 +341,7 @@ impl SwapTokens { // prepare `claim_swap` message that will be sent over the bridge let claim_swap_call: CallOf = - pallet_bridge_token_swap::Call::claim_swap(token_swap).into(); + pallet_bridge_token_swap::Call::claim_swap { swap: token_swap }.into(); let claim_swap_message = bp_message_dispatch::MessagePayload { spec_version: SOURCE_SPEC_VERSION, weight: claim_swap_call.get_dispatch_info().weight, @@ -359,12 +359,13 @@ impl SwapTokens { claim_swap_message.clone(), ) .await?; - let send_message_call: CallOf = pallet_bridge_messages::Call::send_message( - TARGET_TO_SOURCE_LANE_ID, - claim_swap_message, - claim_swap_delivery_and_dispatch_fee, - ) - .into(); + let send_message_call: CallOf = + pallet_bridge_messages::Call::send_message { + lane_id: TARGET_TO_SOURCE_LANE_ID, + payload: claim_swap_message, + delivery_and_dispatch_fee: claim_swap_delivery_and_dispatch_fee, + } + .into(); // send `claim_swap` message let target_genesis_hash = *target_client.genesis_hash(); @@ -406,7 +407,7 @@ impl SwapTokens { } else { log::info!(target: "bridge", "Cancelling the swap"); let cancel_swap_call: CallOf = - pallet_bridge_token_swap::Call::cancel_swap(token_swap.clone()).into(); + pallet_bridge_token_swap::Call::cancel_swap { swap: token_swap.clone() }.into(); let _ = wait_until_transaction_is_finalized::( source_client .submit_and_watch_signed_extrinsic( diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 33bbbeeacd99a..a48d82f641b70 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.2.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } +scale-info = { version = "1.0", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs index 702ce3d385466..6d0ab5462d7c8 100644 --- a/relays/client-kusama/src/runtime.rs +++ b/relays/client-kusama/src/runtime.rs @@ -21,6 +21,7 @@ use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; use bp_runtime::Chain; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; +use scale_info::TypeInfo; use sp_runtime::FixedU128; /// Unchecked Kusama extrinsic. @@ -61,7 +62,7 @@ where /// /// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/kusama/src/lib.rs) #[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { /// System pallet. #[codec(index = 0)] @@ -77,21 +78,21 @@ pub enum Call { BridgePolkadotMessages(BridgePolkadotMessagesCall), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum SystemCall { #[codec(index = 1)] remark(Vec), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BalancesCall { #[codec(index = 0)] transfer(AccountAddress, Compact), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgePolkadotGrandpaCall { #[codec(index = 0)] @@ -103,7 +104,7 @@ pub enum BridgePolkadotGrandpaCall { initialize(bp_header_chain::InitializationData<::Header>), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgePolkadotMessagesCall { #[codec(index = 2)] @@ -135,7 +136,7 @@ pub enum BridgePolkadotMessagesCall { ), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum BridgePolkadotMessagesParameter { #[codec(index = 0)] PolkadotToKusamaConversionRate(FixedU128), diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 663969da66a4c..ff77486579411 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.2.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } +scale-info = { version = "1.0", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs index e21b27f6d3dea..8b125a37843c8 100644 --- a/relays/client-polkadot/src/runtime.rs +++ b/relays/client-polkadot/src/runtime.rs @@ -21,6 +21,7 @@ use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; use bp_runtime::Chain; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; +use scale_info::TypeInfo; use sp_runtime::FixedU128; /// Unchecked Polkadot extrinsic. @@ -61,7 +62,7 @@ where /// /// See: [link](https://github.com/paritytech/kusama/blob/master/runtime/kusam/src/lib.rs) #[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { /// System pallet. #[codec(index = 0)] @@ -77,21 +78,21 @@ pub enum Call { BridgeKusamaMessages(BridgeKusamaMessagesCall), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum SystemCall { #[codec(index = 1)] remark(Vec), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BalancesCall { #[codec(index = 0)] transfer(AccountAddress, Compact), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeKusamaGrandpaCall { #[codec(index = 0)] @@ -103,7 +104,7 @@ pub enum BridgeKusamaGrandpaCall { initialize(bp_header_chain::InitializationData<::Header>), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeKusamaMessagesCall { #[codec(index = 2)] @@ -135,7 +136,7 @@ pub enum BridgeKusamaMessagesCall { ), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum BridgeKusamaMessagesParameter { #[codec(index = 0)] KusamaToPolkadotConversionRate(FixedU128), diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 38ec9eb1887c0..28e97d3bf0cec 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.2.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } +scale-info = { version = "1.0", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index a82aa81a792cc..effe6e5c60a9d 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -21,6 +21,7 @@ use bp_polkadot_core::PolkadotLike; use bp_runtime::Chain; use codec::{Decode, Encode}; use frame_support::weights::Weight; +use scale_info::TypeInfo; /// Unchecked Rococo extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; @@ -60,7 +61,7 @@ where /// /// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { /// System pallet. #[codec(index = 0)] @@ -73,14 +74,14 @@ pub enum Call { BridgeMessagesWococo(BridgeMessagesWococoCall), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum SystemCall { #[codec(index = 1)] remark(Vec), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeGrandpaWococoCall { #[codec(index = 0)] @@ -92,7 +93,7 @@ pub enum BridgeGrandpaWococoCall { initialize(bp_header_chain::InitializationData<::Header>), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeMessagesWococoCall { #[codec(index = 3)] diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 13786c0247f80..ea46c3c898bbb 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.2.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } +scale-info = { version = "1.0", default-features = false, features = ["derive"] } # Bridge dependencies bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index c4835372306e5..91d32d1aa76f7 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -21,6 +21,7 @@ use bp_polkadot_core::PolkadotLike; use bp_runtime::Chain; use codec::{Decode, Encode}; use frame_support::weights::Weight; +use scale_info::TypeInfo; /// Unchecked Wococo extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; @@ -60,7 +61,7 @@ where /// /// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { /// System pallet. #[codec(index = 0)] @@ -73,14 +74,14 @@ pub enum Call { BridgeMessagesRococo(BridgeMessagesRococoCall), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum SystemCall { #[codec(index = 1)] remark(Vec), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeGrandpaRococoCall { #[codec(index = 0)] @@ -92,7 +93,7 @@ pub enum BridgeGrandpaRococoCall { initialize(bp_header_chain::InitializationData<::Header>), } -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeMessagesRococoCall { #[codec(index = 3)] From 5ab7b90ecbe3912ad235ac42ded71a454931f177 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 25 Oct 2021 13:24:48 +0300 Subject: [PATCH 0594/1210] Message transactions mortality (#1191) * transactions mortality in message and complex relays * logging + enable in test deployments * spellcheck * fmt --- primitives/runtime/src/lib.rs | 19 ++++++----- .../src/chains/kusama_messages_to_polkadot.rs | 32 +++++++++++++++--- .../src/chains/millau_messages_to_rialto.rs | 32 +++++++++++++++--- .../src/chains/polkadot_messages_to_kusama.rs | 32 +++++++++++++++--- .../src/chains/rialto_messages_to_millau.rs | 32 +++++++++++++++--- .../src/chains/rococo_messages_to_wococo.rs | 32 +++++++++++++++--- .../src/chains/wococo_messages_to_rococo.rs | 32 +++++++++++++++--- .../src/cli/relay_headers_and_messages.rs | 4 +++ .../bin-substrate/src/cli/relay_messages.rs | 4 +++ relays/client-substrate/src/lib.rs | 33 +++++++++++++++++-- relays/lib-substrate-relay/Cargo.toml | 1 - .../src/finality_pipeline.rs | 16 +++------ .../src/finality_target.rs | 3 +- relays/lib-substrate-relay/src/lib.rs | 11 +++++++ .../lib-substrate-relay/src/messages_lane.rs | 12 +++++++ .../src/messages_source.rs | 4 ++- .../src/messages_target.rs | 7 +++- .../src/on_demand_headers.rs | 2 +- relays/utils/Cargo.toml | 4 +++ relays/utils/src/lib.rs | 5 +-- 20 files changed, 253 insertions(+), 64 deletions(-) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 9ee15df1a9839..460f1b19dfe3f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -69,6 +69,10 @@ 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(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 @@ -159,20 +163,17 @@ pub enum TransactionEra { /// Transaction is immortal. Immortal, /// Transaction is valid for a given number of blocks, starting from given block. - Mortal(BlockNumber, BlockHash, u32), + Mortal(HeaderId, u32), } impl, BlockHash: Copy> TransactionEra { /// Prepare transaction era, based on mortality period and current best block number. pub fn new( - best_block_number: BlockNumber, - best_block_hash: BlockHash, + best_block_id: HeaderId, mortality_period: Option, ) -> Self { mortality_period - .map(|mortality_period| { - TransactionEra::Mortal(best_block_number, best_block_hash, mortality_period) - }) + .map(|mortality_period| TransactionEra::Mortal(best_block_id, mortality_period)) .unwrap_or(TransactionEra::Immortal) } @@ -185,8 +186,8 @@ impl, BlockHash: Copy> TransactionEra sp_runtime::generic::Era { match *self { TransactionEra::Immortal => sp_runtime::generic::Era::immortal(), - TransactionEra::Mortal(header_number, _, period) => - sp_runtime::generic::Era::mortal(period as _, header_number.into()), + TransactionEra::Mortal(header_id, period) => + sp_runtime::generic::Era::mortal(period as _, header_id.0.into()), } } @@ -194,7 +195,7 @@ impl, BlockHash: Copy> TransactionEra BlockHash { match *self { TransactionEra::Immortal => genesis_hash, - TransactionEra::Mortal(_, header_hash, _) => header_hash, + TransactionEra::Mortal(header_id, _) => header_id.1, } } } diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 40e03ef266847..86e2e22cd9094 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -16,7 +16,7 @@ //! Kusama-to-Polkadot messages sync entrypoint. -use std::{ops::RangeInclusive, time::Duration}; +use std::ops::RangeInclusive; use codec::Encode; use sp_core::{Bytes, Pair}; @@ -41,6 +41,7 @@ use substrate_relay_helper::{ }, messages_source::SubstrateMessagesSource, messages_target::SubstrateMessagesTarget, + STALL_TIMEOUT, }; /// Kusama-to-Polkadot message lane. @@ -91,6 +92,7 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { fn make_messages_receiving_proof_transaction( &self, + best_block_id: KusamaHeaderId, transaction_nonce: bp_runtime::IndexOf, _generated_at_block: PolkadotHeaderId, proof: ::MessagesReceivingProof, @@ -106,7 +108,10 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { let transaction = Kusama::sign_transaction( genesis_hash, &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.source_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -125,6 +130,7 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { fn make_messages_delivery_transaction( &self, + best_block_id: PolkadotHeaderId, transaction_nonce: bp_runtime::IndexOf, _generated_at_header: KusamaHeaderId, _nonces: RangeInclusive, @@ -146,7 +152,10 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { let transaction = Polkadot::sign_transaction( genesis_hash, &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.target_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -170,7 +179,13 @@ type PolkadotTargetClient = SubstrateMessagesTarget; pub async fn run( params: MessagesRelayParams, ) -> anyhow::Result<()> { - let stall_timeout = Duration::from_secs(5 * 60); + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transactions_mortality, + params.target_transactions_mortality, + Kusama::AVERAGE_BLOCK_INTERVAL, + Polkadot::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let relayer_id_at_kusama = (*params.source_sign.public().as_array_ref()).into(); let lane_id = params.lane_id; @@ -179,8 +194,10 @@ pub async fn run( message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, + source_transactions_mortality: params.source_transactions_mortality, target_client: params.target_client.clone(), target_sign: params.target_sign, + target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_kusama, }, }; @@ -206,12 +223,17 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}", + Relayer mode: {:?}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.relayer_mode, + params.source_transactions_mortality, + params.target_transactions_mortality, + stall_timeout, ); let (metrics_params, metrics_values) = add_standalone_metrics( diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 612fd96d0fcaa..570a3449752b3 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -16,7 +16,7 @@ //! Millau-to-Rialto messages sync entrypoint. -use std::{ops::RangeInclusive, time::Duration}; +use std::ops::RangeInclusive; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; @@ -41,6 +41,7 @@ use substrate_relay_helper::{ }, messages_source::SubstrateMessagesSource, messages_target::SubstrateMessagesTarget, + STALL_TIMEOUT, }; /// Millau-to-Rialto message lane. @@ -89,6 +90,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { fn make_messages_receiving_proof_transaction( &self, + best_block_id: MillauHeaderId, transaction_nonce: IndexOf, _generated_at_block: RialtoHeaderId, proof: ::MessagesReceivingProof, @@ -102,7 +104,10 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let transaction = Millau::sign_transaction( genesis_hash, &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.source_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -122,6 +127,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { fn make_messages_delivery_transaction( &self, + best_block_id: RialtoHeaderId, transaction_nonce: IndexOf, _generated_at_header: MillauHeaderId, _nonces: RangeInclusive, @@ -142,7 +148,10 @@ impl SubstrateMessageLane for MillauMessagesToRialto { let transaction = Rialto::sign_transaction( genesis_hash, &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.target_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -167,7 +176,13 @@ type RialtoTargetClient = SubstrateMessagesTarget; pub async fn run( params: MessagesRelayParams, ) -> anyhow::Result<()> { - let stall_timeout = Duration::from_secs(5 * 60); + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transactions_mortality, + params.target_transactions_mortality, + Millau::AVERAGE_BLOCK_INTERVAL, + Rialto::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); let lane_id = params.lane_id; @@ -176,8 +191,10 @@ pub async fn run( message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, + source_transactions_mortality: params.source_transactions_mortality, target_client: params.target_client.clone(), target_sign: params.target_sign, + target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_millau, }, }; @@ -200,12 +217,17 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}", + Relayer mode: {:?}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.relayer_mode, + params.source_transactions_mortality, + params.target_transactions_mortality, + stall_timeout, ); let (metrics_params, metrics_values) = add_standalone_metrics( diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 31e8b710e348e..8af62bc80b1f2 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -16,7 +16,7 @@ //! Polkadot-to-Kusama messages sync entrypoint. -use std::{ops::RangeInclusive, time::Duration}; +use std::ops::RangeInclusive; use codec::Encode; use sp_core::{Bytes, Pair}; @@ -41,6 +41,7 @@ use substrate_relay_helper::{ }, messages_source::SubstrateMessagesSource, messages_target::SubstrateMessagesTarget, + STALL_TIMEOUT, }; /// Polkadot-to-Kusama message lane. @@ -90,6 +91,7 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { fn make_messages_receiving_proof_transaction( &self, + best_block_id: PolkadotHeaderId, transaction_nonce: bp_runtime::IndexOf, _generated_at_block: KusamaHeaderId, proof: ::MessagesReceivingProof, @@ -105,7 +107,10 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { let transaction = Polkadot::sign_transaction( genesis_hash, &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.source_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -124,6 +129,7 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { fn make_messages_delivery_transaction( &self, + best_block_id: KusamaHeaderId, transaction_nonce: bp_runtime::IndexOf, _generated_at_header: PolkadotHeaderId, _nonces: RangeInclusive, @@ -145,7 +151,10 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { let transaction = Kusama::sign_transaction( genesis_hash, &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.target_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -169,7 +178,13 @@ type KusamaTargetClient = SubstrateMessagesTarget; pub async fn run( params: MessagesRelayParams, ) -> anyhow::Result<()> { - let stall_timeout = Duration::from_secs(5 * 60); + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transactions_mortality, + params.target_transactions_mortality, + Polkadot::AVERAGE_BLOCK_INTERVAL, + Kusama::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let relayer_id_at_polkadot = (*params.source_sign.public().as_array_ref()).into(); let lane_id = params.lane_id; @@ -178,8 +193,10 @@ pub async fn run( message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, + source_transactions_mortality: params.source_transactions_mortality, target_client: params.target_client.clone(), target_sign: params.target_sign, + target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_polkadot, }, }; @@ -205,12 +222,17 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}", + Relayer mode: {:?}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.relayer_mode, + params.source_transactions_mortality, + params.target_transactions_mortality, + stall_timeout, ); let (metrics_params, metrics_values) = add_standalone_metrics( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 35f0852dcb67d..f85a5e760e631 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -16,7 +16,7 @@ //! Rialto-to-Millau messages sync entrypoint. -use std::{ops::RangeInclusive, time::Duration}; +use std::ops::RangeInclusive; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; @@ -41,6 +41,7 @@ use substrate_relay_helper::{ }, messages_source::SubstrateMessagesSource, messages_target::SubstrateMessagesTarget, + STALL_TIMEOUT, }; /// Rialto-to-Millau message lane. @@ -89,6 +90,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { fn make_messages_receiving_proof_transaction( &self, + best_block_id: RialtoHeaderId, transaction_nonce: IndexOf, _generated_at_block: MillauHeaderId, proof: ::MessagesReceivingProof, @@ -102,7 +104,10 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let transaction = Rialto::sign_transaction( genesis_hash, &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.source_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -122,6 +127,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { fn make_messages_delivery_transaction( &self, + best_block_id: MillauHeaderId, transaction_nonce: IndexOf, _generated_at_header: RialtoHeaderId, _nonces: RangeInclusive, @@ -142,7 +148,10 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { let transaction = Millau::sign_transaction( genesis_hash, &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.target_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -167,7 +176,13 @@ type MillauTargetClient = SubstrateMessagesTarget; pub async fn run( params: MessagesRelayParams, ) -> anyhow::Result<()> { - let stall_timeout = Duration::from_secs(5 * 60); + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transactions_mortality, + params.target_transactions_mortality, + Rialto::AVERAGE_BLOCK_INTERVAL, + Millau::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); let lane_id = params.lane_id; @@ -176,8 +191,10 @@ pub async fn run( message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, + source_transactions_mortality: params.source_transactions_mortality, target_client: params.target_client.clone(), target_sign: params.target_sign, + target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_rialto, }, }; @@ -199,12 +216,17 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}", + Relayer mode: {:?}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.relayer_mode, + params.source_transactions_mortality, + params.target_transactions_mortality, + stall_timeout, ); let (metrics_params, metrics_values) = add_standalone_metrics( diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 65eda19c6ef18..7f9a2eb98f0e0 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -16,7 +16,7 @@ //! Rococo-to-Wococo messages sync entrypoint. -use std::{ops::RangeInclusive, time::Duration}; +use std::ops::RangeInclusive; use codec::Encode; use sp_core::{Bytes, Pair}; @@ -40,6 +40,7 @@ use substrate_relay_helper::{ }, messages_source::SubstrateMessagesSource, messages_target::SubstrateMessagesTarget, + STALL_TIMEOUT, }; /// Rococo-to-Wococo message lane. @@ -88,6 +89,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { fn make_messages_receiving_proof_transaction( &self, + best_block_id: RococoHeaderId, transaction_nonce: IndexOf, _generated_at_block: WococoHeaderId, proof: ::MessagesReceivingProof, @@ -103,7 +105,10 @@ impl SubstrateMessageLane for RococoMessagesToWococo { let transaction = Rococo::sign_transaction( genesis_hash, &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.source_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -122,6 +127,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { fn make_messages_delivery_transaction( &self, + best_block_id: WococoHeaderId, transaction_nonce: IndexOf, _generated_at_header: RococoHeaderId, _nonces: RangeInclusive, @@ -143,7 +149,10 @@ impl SubstrateMessageLane for RococoMessagesToWococo { let transaction = Wococo::sign_transaction( genesis_hash, &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.target_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -167,7 +176,13 @@ type WococoTargetClient = SubstrateMessagesTarget; pub async fn run( params: MessagesRelayParams, ) -> anyhow::Result<()> { - let stall_timeout = Duration::from_secs(5 * 60); + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transactions_mortality, + params.target_transactions_mortality, + Rococo::AVERAGE_BLOCK_INTERVAL, + Wococo::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); let lane_id = params.lane_id; @@ -176,8 +191,10 @@ pub async fn run( message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, + source_transactions_mortality: params.source_transactions_mortality, target_client: params.target_client.clone(), target_sign: params.target_sign, + target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_rococo, }, }; @@ -203,12 +220,17 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}", + Relayer mode: {:?}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.relayer_mode, + params.source_transactions_mortality, + params.target_transactions_mortality, + stall_timeout, ); let (metrics_params, metrics_values) = add_standalone_metrics( diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index d380e6c29a4cb..420b946506095 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -16,7 +16,7 @@ //! Wococo-to-Rococo messages sync entrypoint. -use std::{ops::RangeInclusive, time::Duration}; +use std::ops::RangeInclusive; use codec::Encode; use sp_core::{Bytes, Pair}; @@ -40,6 +40,7 @@ use substrate_relay_helper::{ }, messages_source::SubstrateMessagesSource, messages_target::SubstrateMessagesTarget, + STALL_TIMEOUT, }; /// Wococo-to-Rococo message lane. @@ -87,6 +88,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { fn make_messages_receiving_proof_transaction( &self, + best_block_id: WococoHeaderId, transaction_nonce: IndexOf, _generated_at_block: RococoHeaderId, proof: ::MessagesReceivingProof, @@ -102,7 +104,10 @@ impl SubstrateMessageLane for WococoMessagesToRococo { let transaction = Wococo::sign_transaction( genesis_hash, &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.source_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -121,6 +126,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { fn make_messages_delivery_transaction( &self, + best_block_id: WococoHeaderId, transaction_nonce: IndexOf, _generated_at_header: WococoHeaderId, _nonces: RangeInclusive, @@ -142,7 +148,10 @@ impl SubstrateMessageLane for WococoMessagesToRococo { let transaction = Rococo::sign_transaction( genesis_hash, &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::immortal(), + relay_substrate_client::TransactionEra::new( + best_block_id, + self.message_lane.target_transactions_mortality, + ), UnsignedTransaction::new(call, transaction_nonce), ); log::trace!( @@ -166,7 +175,13 @@ type RococoTargetClient = SubstrateMessagesTarget; pub async fn run( params: MessagesRelayParams, ) -> anyhow::Result<()> { - let stall_timeout = Duration::from_secs(5 * 60); + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transactions_mortality, + params.target_transactions_mortality, + Wococo::AVERAGE_BLOCK_INTERVAL, + Rococo::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); let lane_id = params.lane_id; @@ -175,8 +190,10 @@ pub async fn run( message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, + source_transactions_mortality: params.source_transactions_mortality, target_client: params.target_client.clone(), target_sign: params.target_sign, + target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_wococo, }, }; @@ -202,12 +219,17 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}", + Relayer mode: {:?}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.relayer_mode, + params.source_transactions_mortality, + params.target_transactions_mortality, + stall_timeout, ); let (metrics_params, metrics_values) = add_standalone_metrics( diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 303acf3f125d6..92343288ede15 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -512,8 +512,10 @@ impl RelayHeadersAndMessages { let left_to_right_messages = left_to_right_messages(MessagesRelayParams { source_client: left_client.clone(), source_sign: left_sign.clone(), + source_transactions_mortality: left_transactions_mortality.clone(), target_client: right_client.clone(), target_sign: right_sign.clone(), + target_transactions_mortality: right_transactions_mortality.clone(), source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, @@ -529,8 +531,10 @@ impl RelayHeadersAndMessages { let right_to_left_messages = right_to_left_messages(MessagesRelayParams { source_client: right_client.clone(), source_sign: right_sign.clone(), + source_transactions_mortality: right_transactions_mortality.clone(), target_client: left_client.clone(), target_sign: left_sign.clone(), + target_transactions_mortality: left_transactions_mortality.clone(), source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 3ccf53348d611..fd6875cc2a0f4 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -76,14 +76,18 @@ impl RelayMessages { select_full_bridge!(self.bridge, { let source_client = self.source.to_client::().await?; let source_sign = self.source_sign.to_keypair::()?; + let source_transactions_mortality = self.source_sign.transactions_mortality()?; let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; + let target_transactions_mortality = self.target_sign.transactions_mortality()?; relay_messages(MessagesRelayParams { source_client, source_sign, + source_transactions_mortality, target_client, target_sign, + target_transactions_mortality, source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: self.lane.into(), diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 634bdcdca196e..1f6606ea287c3 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -69,13 +69,40 @@ impl Default for ConnectionParams { /// /// Relay considers himself stalled if he has submitted transaction to the node, but it has not /// been mined for this period. -/// -/// Returns `None` if mortality period is `None` pub fn transaction_stall_timeout( mortality_period: Option, average_block_interval: Duration, -) -> Option { + default_stall_timeout: Duration, +) -> Duration { // 1 extra block for transaction to reach the pool && 1 for relayer to awake after it is mined mortality_period .map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1)) + .unwrap_or(default_stall_timeout) +} + +/// Returns stall timeout for relay loop that submit transactions to two chains. +/// +/// Bidirectional relay may have two active transactions. Even if one of them has been spoiled, we +/// can't just restart the loop - the other transaction may still be alive and we'll be submitting +/// duplicate transaction, which may result in funds loss. So we'll be selecting maximal mortality +/// for choosing loop stall timeout. +pub fn bidirectional_transaction_stall_timeout( + left_mortality_period: Option, + right_mortality_period: Option, + left_average_block_interval: Duration, + right_average_block_interval: Duration, + default_stall_timeout: Duration, +) -> Duration { + std::cmp::max( + transaction_stall_timeout( + left_mortality_period, + left_average_block_interval, + default_stall_timeout, + ), + transaction_stall_timeout( + right_mortality_period, + right_average_block_interval, + default_stall_timeout, + ), + ) } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 5be28bccfb3bb..5bee10856daa3 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -32,7 +32,6 @@ pallet-bridge-messages = { path = "../../modules/messages" } bp-runtime = { path = "../../primitives/runtime" } bp-messages = { path = "../../primitives/messages" } - # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index cca9e5196b3ca..cdfbb3354d274 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -16,7 +16,7 @@ //! Substrate-to-Substrate headers sync entrypoint. -use crate::finality_target::SubstrateFinalityTarget; +use crate::{finality_target::SubstrateFinalityTarget, STALL_TIMEOUT}; use bp_header_chain::justification::GrandpaJustification; use bp_runtime::AccountIdOf; @@ -26,16 +26,8 @@ use relay_substrate_client::{ }; use relay_utils::{metrics::MetricsParams, BlockNumberBase}; use sp_core::Bytes; -use std::{fmt::Debug, marker::PhantomData, time::Duration}; +use std::{fmt::Debug, marker::PhantomData}; -/// Default synchronization loop timeout. If transactions generated by relay are immortal, then -/// this timeout is used. -/// -/// There are no any strict requirements on block time in Substrate. But we assume here that all -/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest -/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine -/// transaction, or remove it from the pool. -pub(crate) const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); /// Default limit of recent finality proofs. /// /// Finality delay of 4096 blocks is unlikely to happen in practice in @@ -165,8 +157,8 @@ where stall_timeout: relay_substrate_client::transaction_stall_timeout( transactions_mortality, TargetChain::AVERAGE_BLOCK_INTERVAL, - ) - .unwrap_or(STALL_TIMEOUT), + STALL_TIMEOUT, + ), only_mandatory_headers, }, metrics_params, diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index 1353eec87278a..f50bd103f4300 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -98,8 +98,7 @@ where move |best_block_id, transaction_nonce| { pipeline.make_submit_finality_proof_transaction( relay_substrate_client::TransactionEra::new( - best_block_id.0, - best_block_id.1, + best_block_id, transactions_mortality, ), transaction_nonce, diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index dac6b8caa8e5c..cc066bf501ac6 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -18,6 +18,8 @@ #![warn(missing_docs)] +use std::time::Duration; + pub mod conversion_rate_update; pub mod error; pub mod finality_pipeline; @@ -28,3 +30,12 @@ pub mod messages_lane; pub mod messages_source; pub mod messages_target; pub mod on_demand_headers; + +/// Default relay loop stall timeout. If transactions generated by relay are immortal, then +/// this timeout is used. +/// +/// There are no any strict requirements on block time in Substrate. But we assume here that all +/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest +/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine +/// transaction, or remove it from the pool. +pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 973f52d60a38b..876b2c2f25728 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -44,10 +44,14 @@ pub struct MessagesRelayParams { pub source_client: Client, /// Sign parameters for messages source chain. pub source_sign: SS, + /// Mortality of source transactions. + pub source_transactions_mortality: Option, /// Messages target client. pub target_client: Client, /// Sign parameters for messages target chain. pub target_sign: TS, + /// Mortality of target transactions. + pub target_transactions_mortality: Option, /// Optional on-demand source to target headers relay. pub source_to_target_headers_relay: Option>, /// Optional on-demand target to source headers relay. @@ -113,6 +117,7 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Make messages delivery transaction. fn make_messages_delivery_transaction( &self, + best_block_id: TargetHeaderIdOf, transaction_nonce: IndexOf, generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, @@ -126,6 +131,7 @@ pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { /// Make messages receiving proof transaction. fn make_messages_receiving_proof_transaction( &self, + best_block_id: SourceHeaderIdOf, transaction_nonce: IndexOf, generated_at_header: TargetHeaderIdOf, proof: ::MessagesReceivingProof, @@ -144,10 +150,14 @@ pub struct SubstrateMessageLaneToSubstrate< pub source_client: Client, /// Parameters required to sign transactions for source chain. pub source_sign: SourceSignParams, + /// Source transactions mortality. + pub source_transactions_mortality: Option, /// Client for the target Substrate chain. pub target_client: Client, /// Parameters required to sign transactions for target chain. pub target_sign: TargetSignParams, + /// Target transactions mortality. + pub target_transactions_mortality: Option, /// Account id of relayer at the source chain. pub relayer_id_at_source: Source::AccountId, } @@ -159,8 +169,10 @@ impl ::SourceChainBalance { self.client .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( + HeaderId(Default::default(), Default::default()), Zero::zero(), HeaderId(Default::default(), Default::default()), prepare_dummy_messages_delivery_proof::(), diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index f7b911f2c023a..6f95ffd12f09c 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -227,8 +227,9 @@ where self.client .submit_signed_extrinsic( self.lane.target_transactions_author(), - move |_, transaction_nonce| { + move |best_block_id, transaction_nonce| { lane.make_messages_delivery_transaction( + best_block_id, transaction_nonce, generated_at_header, nonces_clone, @@ -264,6 +265,7 @@ where // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. let delivery_tx = self.lane.make_messages_delivery_transaction( + HeaderId(Default::default(), Default::default()), Zero::zero(), HeaderId(Default::default(), Default::default()), nonces.clone(), @@ -299,6 +301,7 @@ where let larger_delivery_tx_fee = self .client .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( + HeaderId(Default::default(), Default::default()), Zero::zero(), HeaderId(Default::default(), Default::default()), nonces.clone(), @@ -473,6 +476,7 @@ mod tests { fn make_messages_receiving_proof_transaction( &self, + _best_block_id: SourceHeaderIdOf, _transaction_nonce: IndexOf, _generated_at_block: TargetHeaderIdOf, _proof: ::MessagesReceivingProof, @@ -486,6 +490,7 @@ mod tests { fn make_messages_delivery_transaction( &self, + _best_block_id: TargetHeaderIdOf, _transaction_nonce: IndexOf, _generated_at_header: SourceHeaderIdOf, _nonces: RangeInclusive, diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 4dad20579a90d..ee141866eb97d 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -38,9 +38,9 @@ use relay_utils::{ use crate::{ finality_pipeline::{ SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, - STALL_TIMEOUT, }, finality_target::SubstrateFinalityTarget, + STALL_TIMEOUT, }; /// On-demand Substrate <-> Substrate headers relay. diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 652ff54002833..a08c3b3d688df 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -22,6 +22,10 @@ sysinfo = "0.15" time = "0.2" thiserror = "1.0.26" +# Bridge dependencies + +bp-runtime = { path = "../../primitives/runtime" } + # Substrate dependencies substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 936e9ba68156a..a335be791242c 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -16,6 +16,7 @@ //! Utilities used by different relays. +pub use bp_runtime::HeaderId; pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; @@ -103,10 +104,6 @@ macro_rules! bail_on_arg_error { }; } -/// Ethereum header Id. -#[derive(Debug, Default, Clone, Copy, Eq, Hash, PartialEq)] -pub struct HeaderId(pub Number, pub Hash); - /// Error type that can signal connection errors. pub trait MaybeConnectionError { /// Returns true if error (maybe) represents connection error. From a0e62b006fb4b158030d2fe11fa606a22c14845c Mon Sep 17 00:00:00 2001 From: bear <2630582710@qq.com> Date: Tue, 2 Nov 2021 20:44:04 +0800 Subject: [PATCH 0595/1210] Expose some const value and type (#1186) * change const value visable * Add docs * Update docs * Update docs 2 * Fix ci * Fix spell check --- bin/runtime-common/src/messages.rs | 43 +++++++++++++++++++----------- relays/utils/src/error.rs | 2 +- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 7c9bb685ae6c1..b34cbb85540d4 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -156,16 +156,24 @@ pub trait BridgedChainWithMessages: ChainWithMessages { fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; } -pub(crate) type ThisChain = ::ThisChain; -pub(crate) type BridgedChain = ::BridgedChain; -pub(crate) type HashOf = ::Hash; -pub(crate) type AccountIdOf = ::AccountId; -pub(crate) type SignerOf = ::Signer; -pub(crate) type SignatureOf = ::Signature; -pub(crate) type WeightOf = ::Weight; -pub(crate) type BalanceOf = ::Balance; - -pub(crate) type CallOf = ::Call; +/// This chain in context of message bridge. +pub type ThisChain = ::ThisChain; +/// Bridged chain in context of message bridge. +pub type BridgedChain = ::BridgedChain; +/// Hash used on the chain. +pub type HashOf = ::Hash; +/// Account id used on the chain. +pub type AccountIdOf = ::AccountId; +/// Public key of the chain account that may be used to verify signature. +pub type SignerOf = ::Signer; +/// Signature type used on the chain. +pub type SignatureOf = ::Signature; +/// Type of weight that used on the chain. +pub type WeightOf = ::Weight; +/// Type of balances that is used on the chain. +pub type BalanceOf = ::Balance; +/// Type of call that is used on this chain. +pub type CallOf = ::Call; /// Raw storage proof type (just raw trie nodes). type RawStorageProof = Vec>; @@ -260,12 +268,15 @@ pub mod source { #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); - pub(crate) const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; - pub(crate) const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; - pub(crate) const BAD_ORIGIN: &str = - "Unable to match the source origin to expected target origin."; - pub(crate) const TOO_LOW_FEE: &str = - "Provided fee is below minimal threshold required by the lane."; + /// The error message returned from LaneMessageVerifier when outbound lane is disabled. + pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; + /// The error message returned from LaneMessageVerifier when too many pending messages at the + /// lane. + pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; + /// The error message returned from LaneMessageVerifier when call origin is mismatch. + pub const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; + /// The error message returned from LaneMessageVerifier when the message fee is too low. + pub const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; impl LaneMessageVerifier< diff --git a/relays/utils/src/error.rs b/relays/utils/src/error.rs index 2e4128feb072a..26f1d0cacefd8 100644 --- a/relays/utils/src/error.rs +++ b/relays/utils/src/error.rs @@ -26,7 +26,7 @@ pub enum Error { /// Failed to parse the response from HTTP service. #[error("Failed to parse HTTP service response: {0:?}. Response: {1:?}")] ParseHttp(serde_json::Error, String), - /// Failed to select response value from the JSON response. + /// Failed to select response value from the Json response. #[error("Failed to select value from response: {0:?}. Response: {1:?}")] SelectResponseValue(jsonpath_lib::JsonPathError, String), /// Failed to parse float value from the selected value. From 2e4a934e954057b2e950a60ce3a0aa58085e2934 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 4 Nov 2021 15:59:20 +0300 Subject: [PATCH 0596/1210] fix clippy things (#1200) --- bin/rialto/node/src/overseer.rs | 18 +++++++++--------- bin/rialto/node/src/service.rs | 2 +- .../src/ethereum_deploy_contract.rs | 6 +++--- .../src/cli/relay_headers_and_messages.rs | 8 ++++---- .../src/cli/resubmit_transactions.rs | 2 +- relays/exchange/src/exchange_loop.rs | 4 ++-- relays/finality/src/finality_loop.rs | 4 ++-- relays/headers/src/sync_loop.rs | 4 ++-- relays/messages/src/message_lane_loop.rs | 4 ++-- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs index 0139f3cdf835d..17f7edce2a319 100644 --- a/bin/rialto/node/src/overseer.rs +++ b/bin/rialto/node/src/overseer.rs @@ -113,7 +113,7 @@ where /// Obtain a prepared `OverseerBuilder`, that is initialized /// with all default values. -pub fn prepared_overseer_builder<'a, Spawner, RuntimeClient>( +pub fn prepared_overseer_builder( OverseerGenArgs { leaves, keystore, @@ -134,7 +134,7 @@ pub fn prepared_overseer_builder<'a, Spawner, RuntimeClient>( candidate_validation_config, chain_selection_config, dispute_coordinator_config, - }: OverseerGenArgs<'a, Spawner, RuntimeClient>, + }: OverseerGenArgs<'_, Spawner, RuntimeClient>, ) -> Result< OverseerBuilder< Spawner, @@ -236,7 +236,7 @@ where approval_voting_config, parachains_db.clone(), keystore.clone(), - Box::new(network_service.clone()), + Box::new(network_service), Metrics::register(registry)?, )) .gossip_support(GossipSupportSubsystem::new( @@ -251,9 +251,9 @@ where )) .dispute_participation(DisputeParticipationSubsystem::new()) .dispute_distribution(DisputeDistributionSubsystem::new( - keystore.clone(), + keystore, dispute_req_receiver, - authority_discovery_service.clone(), + authority_discovery_service, Metrics::register(registry)?, )) .chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db)) @@ -278,10 +278,10 @@ where /// would do. pub trait OverseerGen { /// Overwrite the full generation of the overseer, including the subsystems. - fn generate<'a, Spawner, RuntimeClient>( + fn generate( &self, connector: OverseerConnector, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, @@ -302,10 +302,10 @@ use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE; pub struct RealOverseerGen; impl OverseerGen for RealOverseerGen { - fn generate<'a, Spawner, RuntimeClient>( + fn generate( &self, connector: OverseerConnector, - args: OverseerGenArgs<'a, Spawner, RuntimeClient>, + args: OverseerGenArgs<'_, Spawner, RuntimeClient>, ) -> Result<(Overseer>, OverseerHandle), Error> where RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index 6e9eb8a62e46f..e2e811eaa67f4 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -613,7 +613,7 @@ where statement_req_receiver, }, )?; - let handle = Handle::new(overseer_handle.clone()); + let handle = Handle::new(overseer_handle); { let handle = handle.clone(); diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs index cbe2762263a6f..76a75b062ecbc 100644 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ b/relays/bin-ethereum/src/ethereum_deploy_contract.rs @@ -118,7 +118,7 @@ async fn prepare_initial_header( let initial_header = sub_client.header_by_number(Zero::zero()).await; initial_header .map(|header| (HeaderId(Zero::zero(), header.hash()), header.encode())) - .map_err(|error| Error::ReadGenesisHeader(error)) + .map_err(Error::ReadGenesisHeader) }, } } @@ -134,7 +134,7 @@ async fn prepare_initial_authorities_set( None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await, }; - initial_authorities_set.map_err(|error| Error::ReadAuthorities(error)) + initial_authorities_set.map_err(Error::ReadAuthorities) } /// Deploy bridge contract to Ethereum chain. @@ -160,5 +160,5 @@ async fn deploy_bridge_contract( ), ) .await - .map_err(|error| Error::DeployContract(error)) + .map_err(Error::DeployContract) } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 92343288ede15..748b68e33c4d8 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -512,10 +512,10 @@ impl RelayHeadersAndMessages { let left_to_right_messages = left_to_right_messages(MessagesRelayParams { source_client: left_client.clone(), source_sign: left_sign.clone(), - source_transactions_mortality: left_transactions_mortality.clone(), + source_transactions_mortality: left_transactions_mortality, target_client: right_client.clone(), target_sign: right_sign.clone(), - target_transactions_mortality: right_transactions_mortality.clone(), + target_transactions_mortality: right_transactions_mortality, source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, @@ -531,10 +531,10 @@ impl RelayHeadersAndMessages { let right_to_left_messages = right_to_left_messages(MessagesRelayParams { source_client: right_client.clone(), source_sign: right_sign.clone(), - source_transactions_mortality: right_transactions_mortality.clone(), + source_transactions_mortality: right_transactions_mortality, target_client: left_client.clone(), target_sign: left_sign.clone(), - target_transactions_mortality: left_transactions_mortality.clone(), + target_transactions_mortality: left_transactions_mortality, source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 66728622d755d..64663d7e8ec02 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -552,7 +552,7 @@ mod tests { // when we resubmit tx for the second time, 1/9 of queue is skipped context = context.notice_resubmitted_transaction(Hash::from([3; 32])); assert_eq!( - select_transaction_from_queue(queued_transactions.clone(), &context), + select_transaction_from_queue(queued_transactions, &context), Some(Bytes(vec![1])), ); } diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs index 84f4f9261163c..84d216f43968f 100644 --- a/relays/exchange/src/exchange_loop.rs +++ b/relays/exchange/src/exchange_loop.rs @@ -99,8 +99,8 @@ pub async fn run( relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) - .loop_metric(|registry, prefix| ExchangeLoopMetrics::new(registry, prefix))? - .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? + .loop_metric(ExchangeLoopMetrics::new)? + .standalone_metric(GlobalMetrics::new)? .expose() .await? .run(metrics_prefix::

(), move |source_client, target_client, metrics| { diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 1b1327ffde590..191d183837931 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -114,8 +114,8 @@ pub async fn run( let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) - .loop_metric(|registry, prefix| SyncLoopMetrics::new(registry, prefix))? - .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? + .loop_metric(SyncLoopMetrics::new)? + .standalone_metric(GlobalMetrics::new)? .expose() .await? .run(metrics_prefix::

(), move |source_client, target_client, metrics| { diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs index 419211835aa8e..da8d23dc39dec 100644 --- a/relays/headers/src/sync_loop.rs +++ b/relays/headers/src/sync_loop.rs @@ -147,8 +147,8 @@ pub async fn run>( let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) - .loop_metric(|registry, prefix| SyncLoopMetrics::new(registry, prefix))? - .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? + .loop_metric(SyncLoopMetrics::new)? + .standalone_metric(GlobalMetrics::new)? .expose() .await? .run(metrics_prefix::

(), move |source_client, target_client, metrics| { diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index bfd1a2b94082b..e727794aa81cd 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -268,8 +268,8 @@ pub async fn run( relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) .with_metrics(Some(metrics_prefix::

(¶ms.lane)), metrics_params) - .loop_metric(|registry, prefix| MessageLaneLoopMetrics::new(registry, prefix))? - .standalone_metric(|registry, prefix| GlobalMetrics::new(registry, prefix))? + .loop_metric(MessageLaneLoopMetrics::new)? + .standalone_metric(GlobalMetrics::new)? .expose() .await? .run(metrics_prefix::

(¶ms.lane), move |source_client, target_client, metrics| { From ba5d4d79384c3a39d13675c2bae88e2716d68f39 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Tue, 9 Nov 2021 17:01:06 +0800 Subject: [PATCH 0597/1210] Custom relay strategy (#1198) * Add relayer strategy * Add default relayer strategy * default relayer strategy * expose relayer strategy * fix compile * fix compile * docs * Rename Relayer to Relay, keep RelayerDecide * split `DefaultRelayerStrategy` into `AltruisticRelayerStrategy` and `RationalRelayerStrategy` * Remove relayer mode * Remove unused import * Rename `RelayerStrategy` to `RelayStrategy` * Add missing docs * clippy * clippy * clippy * clippy * Revert `relayer_mode` and add `MixStrategy` * Add `EnforcementStrategy` * fix bug and simplify relay strategy * Update message_lane_loop.rs * Update messages_target.rs * clippy * clippy * clippy * clippy * clippy * clippy * clippy * fix test * fix test * test test test fix test --- .../src/chains/kusama_messages_to_polkadot.rs | 20 +- .../src/chains/millau_messages_to_rialto.rs | 14 +- .../src/chains/polkadot_messages_to_kusama.rs | 14 +- .../src/chains/rialto_messages_to_millau.rs | 14 +- .../src/chains/rococo_messages_to_wococo.rs | 14 +- .../src/chains/wococo_messages_to_rococo.rs | 14 +- .../src/cli/relay_headers_and_messages.rs | 6 +- .../bin-substrate/src/cli/relay_messages.rs | 5 +- .../lib-substrate-relay/src/messages_lane.rs | 11 +- relays/messages/src/lib.rs | 1 + relays/messages/src/message_lane_loop.rs | 53 ++- relays/messages/src/message_race_delivery.rs | 343 +++--------------- .../src/relay_strategy/altruistic_strategy.rs | 45 +++ .../relay_strategy/enforcement_strategy.rs | 219 +++++++++++ .../src/relay_strategy/mix_strategy.rs | 40 ++ relays/messages/src/relay_strategy/mod.rs | 123 +++++++ .../src/relay_strategy/rational_strategy.rs | 122 +++++++ 17 files changed, 714 insertions(+), 344 deletions(-) create mode 100644 relays/messages/src/relay_strategy/altruistic_strategy.rs create mode 100644 relays/messages/src/relay_strategy/enforcement_strategy.rs create mode 100644 relays/messages/src/relay_strategy/mix_strategy.rs create mode 100644 relays/messages/src/relay_strategy/mod.rs create mode 100644 relays/messages/src/relay_strategy/rational_strategy.rs diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 86e2e22cd9094..9c9dee150dc46 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -19,12 +19,13 @@ use std::ops::RangeInclusive; use codec::Encode; +use frame_support::weights::Weight; use sp_core::{Bytes, Pair}; +use sp_runtime::{FixedPointNumber, FixedU128}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_kusama_client::{ HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, }; @@ -33,7 +34,6 @@ use relay_polkadot_client::{ }; use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; use relay_utils::metrics::MetricsParams; -use sp_runtime::{FixedPointNumber, FixedU128}; use substrate_relay_helper::{ messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, @@ -177,7 +177,13 @@ type PolkadotTargetClient = SubstrateMessagesTarget; /// Run Kusama-to-Polkadot messages sync. pub async fn run( - params: MessagesRelayParams, + params: MessagesRelayParams< + Kusama, + KusamaSigningParams, + Polkadot, + PolkadotSigningParams, + MixStrategy, + >, ) -> anyhow::Result<()> { let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( params.source_transactions_mortality, @@ -223,14 +229,12 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}\n\t\ Tx mortality: {:?}/{:?}\n\t\ Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, - params.relayer_mode, params.source_transactions_mortality, params.target_transactions_mortality, stall_timeout, @@ -258,7 +262,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, }, }, KusamaSourceClient::new( @@ -332,7 +336,7 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( transaction_nonce, ), ) - .encode(), + .encode(), ) }) .await diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 570a3449752b3..3661eb78c19f9 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -25,7 +25,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_millau_client::{ HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, }; @@ -174,7 +174,13 @@ type RialtoTargetClient = SubstrateMessagesTarget; /// Run Millau-to-Rialto messages sync. pub async fn run( - params: MessagesRelayParams, + params: MessagesRelayParams< + Millau, + MillauSigningParams, + Rialto, + RialtoSigningParams, + MixStrategy, + >, ) -> anyhow::Result<()> { let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( params.source_transactions_mortality, @@ -217,14 +223,12 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}\n\t\ Tx mortality: {:?}/{:?}\n\t\ Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, - params.relayer_mode, params.source_transactions_mortality, params.target_transactions_mortality, stall_timeout, @@ -252,7 +256,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, }, }, MillauSourceClient::new( diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 8af62bc80b1f2..b1595665fb255 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -24,7 +24,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_kusama_client::{ HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, }; @@ -176,7 +176,13 @@ type KusamaTargetClient = SubstrateMessagesTarget; /// Run Polkadot-to-Kusama messages sync. pub async fn run( - params: MessagesRelayParams, + params: MessagesRelayParams< + Polkadot, + PolkadotSigningParams, + Kusama, + KusamaSigningParams, + MixStrategy, + >, ) -> anyhow::Result<()> { let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( params.source_transactions_mortality, @@ -222,14 +228,12 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}\n\t\ Tx mortality: {:?}/{:?}\n\t\ Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, - params.relayer_mode, params.source_transactions_mortality, params.target_transactions_mortality, stall_timeout, @@ -257,7 +261,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, }, }, PolkadotSourceClient::new( diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index f85a5e760e631..50ebf264e1a49 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -25,7 +25,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_millau_client::{ HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, }; @@ -174,7 +174,13 @@ type MillauTargetClient = SubstrateMessagesTarget; /// Run Rialto-to-Millau messages sync. pub async fn run( - params: MessagesRelayParams, + params: MessagesRelayParams< + Rialto, + RialtoSigningParams, + Millau, + MillauSigningParams, + MixStrategy, + >, ) -> anyhow::Result<()> { let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( params.source_transactions_mortality, @@ -216,14 +222,12 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}\n\t\ Tx mortality: {:?}/{:?}\n\t\ Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, - params.relayer_mode, params.source_transactions_mortality, params.target_transactions_mortality, stall_timeout, @@ -251,7 +255,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, }, }, RialtoSourceClient::new( diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 7f9a2eb98f0e0..523d8c4908597 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -24,7 +24,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_rococo_client::{ HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, }; @@ -174,7 +174,13 @@ type WococoTargetClient = SubstrateMessagesTarget; /// Run Rococo-to-Wococo messages sync. pub async fn run( - params: MessagesRelayParams, + params: MessagesRelayParams< + Rococo, + RococoSigningParams, + Wococo, + WococoSigningParams, + MixStrategy, + >, ) -> anyhow::Result<()> { let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( params.source_transactions_mortality, @@ -220,14 +226,12 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}\n\t\ Tx mortality: {:?}/{:?}\n\t\ Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, - params.relayer_mode, params.source_transactions_mortality, params.target_transactions_mortality, stall_timeout, @@ -255,7 +259,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, }, }, RococoSourceClient::new( diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 420b946506095..893aeb607ab70 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -24,7 +24,7 @@ use sp_core::{Bytes, Pair}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; use relay_rococo_client::{ HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, }; @@ -173,7 +173,13 @@ type RococoTargetClient = SubstrateMessagesTarget; /// Run Wococo-to-Rococo messages sync. pub async fn run( - params: MessagesRelayParams, + params: MessagesRelayParams< + Wococo, + WococoSigningParams, + Rococo, + RococoSigningParams, + MixStrategy, + >, ) -> anyhow::Result<()> { let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( params.source_transactions_mortality, @@ -219,14 +225,12 @@ pub async fn run( Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Relayer mode: {:?}\n\t\ Tx mortality: {:?}/{:?}\n\t\ Stall timeout: {:?}", lane.message_lane.relayer_id_at_source, max_messages_in_single_batch, max_messages_size_in_single_batch, max_messages_weight_in_single_batch, - params.relayer_mode, params.source_transactions_mortality, params.target_transactions_mortality, stall_timeout, @@ -254,7 +258,7 @@ pub async fn run( max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, }, }, WococoSourceClient::new( diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 748b68e33c4d8..076331112a21f 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -27,6 +27,7 @@ use structopt::StructOpt; use strum::VariantNames; use codec::Encode; +use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, }; @@ -375,6 +376,7 @@ impl RelayHeadersAndMessages { let lanes = params.shared.lane; let relayer_mode = params.shared.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); const METRIC_IS_SOME_PROOF: &str = "it is `None` when metric has been already registered; \ @@ -519,12 +521,12 @@ impl RelayHeadersAndMessages { source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, - relayer_mode, metrics_params: metrics_params.clone().disable().metrics_prefix( messages_relay::message_lane_loop::metrics_prefix::< ::MessageLane, >(&lane), ), + relay_strategy: relay_strategy.clone(), }) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); @@ -538,12 +540,12 @@ impl RelayHeadersAndMessages { source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, - relayer_mode, metrics_params: metrics_params.clone().disable().metrics_prefix( messages_relay::message_lane_loop::metrics_prefix::< ::MessageLane, >(&lane), ), + relay_strategy: relay_strategy.clone(), }) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index fd6875cc2a0f4..4b2e0c975602a 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -17,6 +17,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use messages_relay::relay_strategy::MixStrategy; use substrate_relay_helper::messages_lane::MessagesRelayParams; use crate::{ @@ -80,6 +81,8 @@ impl RelayMessages { let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; let target_transactions_mortality = self.target_sign.transactions_mortality()?; + let relayer_mode = self.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); relay_messages(MessagesRelayParams { source_client, @@ -91,8 +94,8 @@ impl RelayMessages { source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: self.lane.into(), - relayer_mode: self.relayer_mode.into(), metrics_params: self.prometheus_params.into(), + relay_strategy, }) .await .map_err(|e| anyhow::format_err!("{}", e)) diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 876b2c2f25728..5e9564cf95e3c 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -25,7 +25,10 @@ use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{AccountIdOf, IndexOf}; use frame_support::weights::Weight; -use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; +use messages_relay::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + relay_strategy::RelayStrategy, +}; use relay_substrate_client::{ metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, BlockNumberOf, Chain, Client, HashOf, @@ -39,7 +42,7 @@ use sp_runtime::FixedU128; use std::ops::RangeInclusive; /// Substrate <-> Substrate messages relay parameters. -pub struct MessagesRelayParams { +pub struct MessagesRelayParams { /// Messages source client. pub source_client: Client, /// Sign parameters for messages source chain. @@ -58,10 +61,10 @@ pub struct MessagesRelayParams { pub target_to_source_headers_relay: Option>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, - /// Relayer operating mode. - pub relayer_mode: messages_relay::message_lane_loop::RelayerMode, /// Metrics parameters. pub metrics_params: MetricsParams, + /// Relay strategy + pub relay_strategy: Strategy, } /// Message sync pipeline for Substrate <-> Substrate relays. diff --git a/relays/messages/src/lib.rs b/relays/messages/src/lib.rs index 861091ab20506..c9e460300342f 100644 --- a/relays/messages/src/lib.rs +++ b/relays/messages/src/lib.rs @@ -29,6 +29,7 @@ mod metrics; pub mod message_lane; pub mod message_lane_loop; +pub mod relay_strategy; mod message_race_delivery; mod message_race_loop; diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index e727794aa81cd..2de644091ef2f 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -24,17 +24,13 @@ //! finalized header. I.e. when talking about headers in lane context, we //! only care about finalized headers. -use crate::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_race_delivery::run as run_message_delivery_race, - message_race_receiving::run as run_message_receiving_race, - metrics::MessageLaneLoopMetrics, -}; +use std::{collections::BTreeMap, fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; use async_trait::async_trait; +use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; + use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use bp_runtime::messages::DispatchFeePayment; -use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use relay_utils::{ interval, metrics::{GlobalMetrics, MetricsParams}, @@ -42,11 +38,18 @@ use relay_utils::{ relay_loop::Client as RelayClient, retry_backoff, FailedClient, }; -use std::{collections::BTreeMap, fmt::Debug, future::Future, ops::RangeInclusive, time::Duration}; + +use crate::{ + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, + message_race_delivery::run as run_message_delivery_race, + message_race_receiving::run as run_message_receiving_race, + metrics::MessageLaneLoopMetrics, + relay_strategy::RelayStrategy, +}; /// Message lane loop configuration params. #[derive(Debug, Clone)] -pub struct Params { +pub struct Params { /// Id of lane this loop is servicing. pub lane: LaneId, /// Interval at which we ask target node about its updates. @@ -58,7 +61,7 @@ pub struct Params { /// The loop will auto-restart if there has been no updates during this period. pub stall_timeout: Duration, /// Message delivery race parameters. - pub delivery_params: MessageDeliveryParams, + pub delivery_params: MessageDeliveryParams, } /// Relayer operating mode. @@ -73,7 +76,7 @@ pub enum RelayerMode { /// Message delivery race parameters. #[derive(Debug, Clone)] -pub struct MessageDeliveryParams { +pub struct MessageDeliveryParams { /// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number /// of entries in the `InboundLaneData::relayers` set, all new messages will be rejected until /// reward payment will be proved (by including outbound lane state to the message delivery @@ -89,8 +92,8 @@ pub struct MessageDeliveryParams { pub max_messages_weight_in_single_batch: Weight, /// Maximal cumulative size of relayed messages in single delivery transaction. pub max_messages_size_in_single_batch: u32, - /// Relayer operating mode. - pub relayer_mode: RelayerMode, + /// Relay strategy + pub relay_strategy: Strategy, } /// Message details. @@ -257,8 +260,8 @@ pub fn metrics_prefix(lane: &LaneId) -> String { } /// Run message lane service loop. -pub async fn run( - params: Params, +pub async fn run( + params: Params, source_client: impl SourceClient

, target_client: impl TargetClient

, metrics_params: MetricsParams, @@ -286,8 +289,13 @@ pub async fn run( /// Run one-way message delivery loop until connection with target or source node is lost, or exit /// signal is received. -async fn run_until_connection_lost, TC: TargetClient

>( - params: Params, +async fn run_until_connection_lost< + P: MessageLane, + Strategy: RelayStrategy, + SC: SourceClient

, + TC: TargetClient

, +>( + params: Params, source_client: SC, target_client: TC, metrics_msg: Option, @@ -449,11 +457,16 @@ async fn run_until_connection_lost, TC: Targ #[cfg(test)] pub(crate) mod tests { - use super::*; + use std::sync::Arc; + use futures::stream::StreamExt; use parking_lot::Mutex; + use relay_utils::{HeaderId, MaybeConnectionError}; - use std::sync::Arc; + + use crate::relay_strategy::AltruisticStrategy; + + use super::*; pub fn header_id(number: TestSourceHeaderNumber) -> TestSourceHeaderId { HeaderId(number, number) @@ -807,7 +820,7 @@ pub(crate) mod tests { max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: 4, max_messages_size_in_single_batch: 4, - relayer_mode: RelayerMode::Altruistic, + relay_strategy: AltruisticStrategy, }, }, source_client, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 4fd721dae5977..1cd2cbd267185 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -13,10 +13,18 @@ //! Message delivery race delivers proof-of-messages from "lane.source" to "lane.target". +use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; + +use async_trait::async_trait; +use futures::stream::FusedStream; + +use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; +use relay_utils::FailedClient; + use crate::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, RelayerMode, + MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }, @@ -24,32 +32,20 @@ use crate::{ MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient, TargetClientNonces, }, - message_race_strategy::{BasicStrategy, SourceRangesQueue}, + message_race_strategy::BasicStrategy, metrics::MessageLaneLoopMetrics, -}; - -use async_trait::async_trait; -use bp_messages::{MessageNonce, UnrewardedRelayersState, Weight}; -use bp_runtime::messages::DispatchFeePayment; -use futures::stream::FusedStream; -use num_traits::{SaturatingAdd, Zero}; -use relay_utils::FailedClient; -use std::{ - collections::VecDeque, - marker::PhantomData, - ops::{Range, RangeInclusive}, - time::Duration, + relay_strategy::{EnforcementStrategy, RelayMessagesBatchReference, RelayStrategy}, }; /// Run message delivery race. -pub async fn run( +pub async fn run( source_client: impl MessageLaneSourceClient

, source_state_updates: impl FusedStream>, target_client: impl MessageLaneTargetClient

, target_state_updates: impl FusedStream>, stall_timeout: Duration, metrics_msg: Option, - params: MessageDeliveryParams, + params: MessageDeliveryParams, ) -> Result<(), FailedClient> { crate::message_race_loop::run( MessageDeliveryRaceSource { @@ -65,7 +61,7 @@ pub async fn run( }, target_state_updates, stall_timeout, - MessageDeliveryStrategy:: { + MessageDeliveryStrategy:: { lane_source_client: source_client, lane_target_client: target_client, max_unrewarded_relayer_entries_at_target: params @@ -74,7 +70,7 @@ pub async fn run( max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, max_messages_size_in_single_batch: params.max_messages_size_in_single_batch, - relayer_mode: params.relayer_mode, + relay_strategy: params.relay_strategy, latest_confirmed_nonces_at_source: VecDeque::new(), target_nonces: None, strategy: BasicStrategy::new(), @@ -235,7 +231,7 @@ struct DeliveryRaceTargetNoncesData { } /// Messages delivery strategy. -struct MessageDeliveryStrategy { +struct MessageDeliveryStrategy { /// The client that is connected to the message lane source node. lane_source_client: SC, /// The client that is connected to the message lane target node. @@ -251,7 +247,7 @@ struct MessageDeliveryStrategy { /// Maximal messages size in the single delivery transaction. max_messages_size_in_single_batch: u32, /// Relayer operating mode. - relayer_mode: RelayerMode, + relay_strategy: Strategy, /// Latest confirmed nonces at the source client + the header id where we have first met this /// nonce. latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, @@ -270,7 +266,9 @@ type MessageDeliveryStrategyBase

= BasicStrategy<

::MessagesProof, >; -impl std::fmt::Debug for MessageDeliveryStrategy { +impl std::fmt::Debug + for MessageDeliveryStrategy +{ fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { fmt.debug_struct("MessageDeliveryStrategy") .field( @@ -288,7 +286,7 @@ impl std::fmt::Debug for MessageDeliveryStrategy MessageDeliveryStrategy { +impl MessageDeliveryStrategy { /// Returns total weight of all undelivered messages. fn total_queued_dispatch_weight(&self) -> Weight { self.strategy @@ -300,8 +298,9 @@ impl MessageDeliveryStrategy { } #[async_trait] -impl RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> - for MessageDeliveryStrategy +impl + RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> + for MessageDeliveryStrategy where P: MessageLane, SC: MessageLaneSourceClient

, @@ -504,7 +503,6 @@ where let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; let max_messages_size_in_single_batch = self.max_messages_size_in_single_batch; - let relayer_mode = self.relayer_mode; let lane_source_client = self.lane_source_client.clone(); let lane_target_client = self.lane_target_client.clone(); @@ -512,17 +510,19 @@ where self.strategy.maximal_available_source_queue_index(race_state)?; let previous_total_dispatch_weight = self.total_queued_dispatch_weight(); let source_queue = self.strategy.source_queue(); - let range_end = select_nonces_for_delivery_transaction( - relayer_mode, - max_nonces, + + let reference = RelayMessagesBatchReference { + max_messages_in_this_batch: max_nonces, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - lane_source_client.clone(), - lane_target_client.clone(), - source_queue, - 0..maximal_source_queue_index + 1, - ) - .await?; + lane_source_client: lane_source_client.clone(), + lane_target_client: lane_target_client.clone(), + nonces_queue: source_queue.clone(), + nonces_queue_range: 0..maximal_source_queue_index + 1, + }; + + let strategy = EnforcementStrategy::new(self.relay_strategy.clone()); + let range_end = strategy.decide(reference).await?; let range_begin = source_queue[0].1.begin(); let selected_nonces = range_begin..=range_end; @@ -538,236 +538,6 @@ where } } -/// From given set of source nonces, that are ready to be delivered, select nonces -/// to fit into single delivery transaction. -/// -/// The function returns last nonce that must be delivered to the target chain. -#[allow(clippy::too_many_arguments)] -async fn select_nonces_for_delivery_transaction( - relayer_mode: RelayerMode, - max_messages_in_this_batch: MessageNonce, - max_messages_weight_in_single_batch: Weight, - max_messages_size_in_single_batch: u32, - lane_source_client: impl MessageLaneSourceClient

, - lane_target_client: impl MessageLaneTargetClient

, - nonces_queue: &SourceRangesQueue< - P::SourceHeaderHash, - P::SourceHeaderNumber, - MessageDetailsMap, - >, - nonces_queue_range: Range, -) -> Option { - let mut hard_selected_count = 0; - let mut soft_selected_count = 0; - - let mut selected_weight: Weight = 0; - let mut selected_unpaid_weight: Weight = 0; - let mut selected_prepaid_nonces = 0; - let mut selected_size: u32 = 0; - let mut selected_count: MessageNonce = 0; - let mut selected_reward = P::SourceChainBalance::zero(); - let mut selected_cost = P::SourceChainBalance::zero(); - - let mut total_reward = P::SourceChainBalance::zero(); - let mut total_confirmations_cost = P::SourceChainBalance::zero(); - let mut total_cost = P::SourceChainBalance::zero(); - - let hard_selected_begin_nonce = nonces_queue[nonces_queue_range.start].1.begin(); - - // technically, multiple confirmations will be delivered in a single transaction, - // meaning less loses for relayer. But here we don't know the final relayer yet, so - // we're adding a separate transaction for every message. Normally, this cost is covered - // by the message sender. Probably reconsider this? - let confirmation_transaction_cost = if relayer_mode != RelayerMode::Altruistic { - lane_source_client.estimate_confirmation_transaction().await - } else { - Zero::zero() - }; - - let all_ready_nonces = nonces_queue - .range(nonces_queue_range.clone()) - .flat_map(|(_, ready_nonces)| ready_nonces.iter()) - .enumerate(); - for (index, (nonce, details)) in all_ready_nonces { - // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` - // and `max_messages_size_in_single_batch`, we may still try to submit transaction - // with single message if message overflows these limits. The worst case would be if - // transaction will be rejected by the target runtime, but at least we have tried. - - // limit messages in the batch by weight - let new_selected_weight = match selected_weight.checked_add(details.dispatch_weight) { - Some(new_selected_weight) - if new_selected_weight <= max_messages_weight_in_single_batch => - new_selected_weight, - new_selected_weight if selected_count == 0 => { - log::warn!( - target: "bridge", - "Going to submit message delivery transaction with declared dispatch \ - weight {:?} that overflows maximal configured weight {}", - new_selected_weight, - max_messages_weight_in_single_batch, - ); - new_selected_weight.unwrap_or(Weight::MAX) - }, - _ => break, - }; - - // limit messages in the batch by size - let new_selected_size = match selected_size.checked_add(details.size) { - Some(new_selected_size) if new_selected_size <= max_messages_size_in_single_batch => - new_selected_size, - new_selected_size if selected_count == 0 => { - log::warn!( - target: "bridge", - "Going to submit message delivery transaction with message \ - size {:?} that overflows maximal configured size {}", - new_selected_size, - max_messages_size_in_single_batch, - ); - new_selected_size.unwrap_or(u32::MAX) - }, - _ => break, - }; - - // limit number of messages in the batch - let new_selected_count = selected_count + 1; - if new_selected_count > max_messages_in_this_batch { - break - } - - // If dispatch fee has been paid at the source chain, it means that it is **relayer** who's - // paying for dispatch at the target chain AND reward must cover this dispatch fee. - // - // If dispatch fee is paid at the target chain, it means that it'll be withdrawn from the - // dispatch origin account AND reward is not covering this fee. - // - // So in the latter case we're not adding the dispatch weight to the delivery transaction - // weight. - let mut new_selected_prepaid_nonces = selected_prepaid_nonces; - let new_selected_unpaid_weight = match details.dispatch_fee_payment { - DispatchFeePayment::AtSourceChain => { - new_selected_prepaid_nonces += 1; - selected_unpaid_weight.saturating_add(details.dispatch_weight) - }, - DispatchFeePayment::AtTargetChain => selected_unpaid_weight, - }; - - // now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT - // to deliver it? It depends on the relayer strategy. - match relayer_mode { - RelayerMode::Altruistic => { - soft_selected_count = index + 1; - }, - RelayerMode::Rational => { - let delivery_transaction_cost = lane_target_client - .estimate_delivery_transaction_in_source_tokens( - hard_selected_begin_nonce..= - (hard_selected_begin_nonce + index as MessageNonce), - new_selected_prepaid_nonces, - new_selected_unpaid_weight, - new_selected_size as u32, - ) - .await - .map_err(|err| { - log::debug!( - target: "bridge", - "Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery", - err, - ); - }) - .ok()?; - - // if it is the first message that makes reward less than cost, let's log it - // if this message makes batch profitable again, let's log it - let is_total_reward_less_than_cost = total_reward < total_cost; - let prev_total_cost = total_cost; - let prev_total_reward = total_reward; - total_confirmations_cost = - total_confirmations_cost.saturating_add(&confirmation_transaction_cost); - total_reward = total_reward.saturating_add(&details.reward); - total_cost = total_confirmations_cost.saturating_add(&delivery_transaction_cost); - if !is_total_reward_less_than_cost && total_reward < total_cost { - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ - total reward {:?}->{:?}", - nonce, - details.reward, - prev_total_cost, - total_cost, - prev_total_reward, - total_reward, - ); - } else if is_total_reward_less_than_cost && total_reward >= total_cost { - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ - equal to the total reward {:?}->{:?} (again)", - nonce, - details.reward, - prev_total_cost, - total_cost, - prev_total_reward, - total_reward, - ); - } - - // Rational relayer never want to lose his funds - if total_reward >= total_cost { - soft_selected_count = index + 1; - selected_reward = total_reward; - selected_cost = total_cost; - } - }, - } - - hard_selected_count = index + 1; - selected_weight = new_selected_weight; - selected_unpaid_weight = new_selected_unpaid_weight; - selected_prepaid_nonces = new_selected_prepaid_nonces; - selected_size = new_selected_size; - selected_count = new_selected_count; - } - - if hard_selected_count != soft_selected_count { - let hard_selected_end_nonce = - hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; - let soft_selected_begin_nonce = hard_selected_begin_nonce; - let soft_selected_end_nonce = - soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; - log::warn!( - target: "bridge", - "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy ({:?}) it has selected \ - nonces [{:?}; {:?}].", - hard_selected_begin_nonce, - hard_selected_end_nonce, - relayer_mode, - soft_selected_begin_nonce, - soft_selected_end_nonce, - ); - - hard_selected_count = soft_selected_count; - } - - if hard_selected_count != 0 { - if relayer_mode != RelayerMode::Altruistic { - log::trace!( - target: "bridge", - "Expected reward from delivering nonces [{:?}; {:?}] is: {:?} - {:?} = {:?}", - hard_selected_begin_nonce, - hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1, - selected_reward, - selected_cost, - selected_reward - selected_cost, - ); - } - - Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1) - } else { - None - } -} - impl NoncesRange for MessageDetailsMap { fn begin(&self) -> MessageNonce { self.keys().next().cloned().unwrap_or_default() @@ -789,16 +559,21 @@ impl NoncesRange for MessageDetailsMap; type TestStrategy = - MessageDeliveryStrategy; + MessageDeliveryStrategy; fn source_nonces( new_nonces: RangeInclusive, @@ -848,7 +623,6 @@ mod tests { }; let mut race_strategy = TestStrategy { - relayer_mode: RelayerMode::Altruistic, max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, @@ -869,11 +643,12 @@ mod tests { }, }), strategy: BasicStrategy::new(), + relay_strategy: MixStrategy::new(RelayerMode::Altruistic), }; race_strategy.strategy.source_nonces_updated( header_id(1), - source_nonces(20..=23, 19, DEFAULT_REWARD, AtSourceChain), + source_nonces(20..=23, 19, DEFAULT_REWARD, DispatchFeePayment::AtSourceChain), ); let target_nonces = TargetClientNonces { latest_nonce: 19, nonces_data: () }; @@ -907,7 +682,7 @@ mod tests { dispatch_weight: idx, size: idx as _, reward: idx as _, - dispatch_fee_payment: AtSourceChain, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, ) }) @@ -1199,7 +974,7 @@ mod tests { #[async_std::test] async fn rational_relayer_is_delivering_messages_if_cost_is_equal_to_reward() { let (state, mut strategy) = prepare_strategy(); - strategy.relayer_mode = RelayerMode::Rational; + strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); // so now we have: // - 20..=23 with reward = cost @@ -1217,11 +992,11 @@ mod tests { 24..=25, 19, DEFAULT_REWARD - BASE_MESSAGE_DELIVERY_TRANSACTION_COST, - AtSourceChain, + DispatchFeePayment::AtSourceChain, ); strategy.strategy.source_nonces_updated(header_id(2), nonces); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - strategy.relayer_mode = RelayerMode::Rational; + strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); // so now we have: // - 20..=23 with reward = cost @@ -1252,7 +1027,7 @@ mod tests { strategy.max_messages_in_single_batch = 100; strategy.max_messages_weight_in_single_batch = 100; strategy.max_messages_size_in_single_batch = 100; - strategy.relayer_mode = RelayerMode::Rational; + strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); // so now we have: // - 20..=23 with reward = cost @@ -1264,11 +1039,11 @@ mod tests { } assert_eq!( - test_with_dispatch_fee_payment(AtTargetChain).await, + test_with_dispatch_fee_payment(DispatchFeePayment::AtTargetChain).await, Some(((20..=24), proof_parameters(false, 5))) ); assert_eq!( - test_with_dispatch_fee_payment(AtSourceChain).await, + test_with_dispatch_fee_payment(DispatchFeePayment::AtSourceChain).await, Some(((20..=23), proof_parameters(false, 4))) ); } @@ -1284,7 +1059,7 @@ mod tests { // This was happening because selector (`select_nonces_for_delivery_transaction`) has been // called for every `source_queue` entry separately without preserving any context. let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, AtSourceChain); + let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, DispatchFeePayment::AtSourceChain); strategy.strategy.source_nonces_updated(header_id(2), nonces); strategy.max_unrewarded_relayer_entries_at_target = 100; strategy.max_unconfirmed_nonces_at_target = 100; diff --git a/relays/messages/src/relay_strategy/altruistic_strategy.rs b/relays/messages/src/relay_strategy/altruistic_strategy.rs new file mode 100644 index 0000000000000..f932b796b0dee --- /dev/null +++ b/relays/messages/src/relay_strategy/altruistic_strategy.rs @@ -0,0 +1,45 @@ +// 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 . + +//! Altruistic relay strategy + +use async_trait::async_trait; + +use crate::{ + message_lane::MessageLane, + message_lane_loop::{ + SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, + }, + relay_strategy::{RelayReference, RelayStrategy}, +}; + +/// The relayer doesn't care about rewards. +#[derive(Clone)] +pub struct AltruisticStrategy; + +#[async_trait] +impl RelayStrategy for AltruisticStrategy { + async fn decide< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + _reference: &mut RelayReference, + ) -> bool { + true + } +} diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/relay_strategy/enforcement_strategy.rs new file mode 100644 index 0000000000000..042c05bec00ad --- /dev/null +++ b/relays/messages/src/relay_strategy/enforcement_strategy.rs @@ -0,0 +1,219 @@ +// 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 . + +//! enforcement strategy + +use num_traits::Zero; + +use bp_messages::{MessageNonce, Weight}; +use bp_runtime::messages::DispatchFeePayment; + +use crate::{ + message_lane::MessageLane, + message_lane_loop::{ + MessageDetails, SourceClient as MessageLaneSourceClient, + TargetClient as MessageLaneTargetClient, + }, + message_race_loop::NoncesRange, + relay_strategy::{RelayMessagesBatchReference, RelayReference, RelayStrategy}, +}; + +/// Do hard check and run soft check strategy +#[derive(Clone)] +pub struct EnforcementStrategy { + strategy: Strategy, +} + +impl EnforcementStrategy { + pub fn new(strategy: Strategy) -> Self { + Self { strategy } + } +} + +impl EnforcementStrategy { + pub async fn decide< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: RelayMessagesBatchReference, + ) -> Option { + let mut hard_selected_count = 0; + let mut soft_selected_count = 0; + + let mut selected_weight: Weight = 0; + let mut selected_count: MessageNonce = 0; + + let hard_selected_begin_nonce = + reference.nonces_queue[reference.nonces_queue_range.start].1.begin(); + + // relay reference + let mut relay_reference = RelayReference { + lane_source_client: reference.lane_source_client.clone(), + lane_target_client: reference.lane_target_client.clone(), + + selected_reward: P::SourceChainBalance::zero(), + selected_cost: P::SourceChainBalance::zero(), + selected_size: 0, + + total_reward: P::SourceChainBalance::zero(), + total_confirmations_cost: P::SourceChainBalance::zero(), + total_cost: P::SourceChainBalance::zero(), + + hard_selected_begin_nonce, + selected_prepaid_nonces: 0, + selected_unpaid_weight: 0, + + index: 0, + nonce: 0, + details: MessageDetails { + dispatch_weight: 0, + size: 0, + reward: P::SourceChainBalance::zero(), + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + }, + }; + + let all_ready_nonces = reference + .nonces_queue + .range(reference.nonces_queue_range.clone()) + .flat_map(|(_, ready_nonces)| ready_nonces.iter()) + .enumerate(); + for (index, (nonce, details)) in all_ready_nonces { + relay_reference.index = index; + relay_reference.nonce = *nonce; + relay_reference.details = *details; + + // Since we (hopefully) have some reserves in `max_messages_weight_in_single_batch` + // and `max_messages_size_in_single_batch`, we may still try to submit transaction + // with single message if message overflows these limits. The worst case would be if + // transaction will be rejected by the target runtime, but at least we have tried. + + // limit messages in the batch by weight + let new_selected_weight = match selected_weight.checked_add(details.dispatch_weight) { + Some(new_selected_weight) + if new_selected_weight <= reference.max_messages_weight_in_single_batch => + new_selected_weight, + new_selected_weight if selected_count == 0 => { + log::warn!( + target: "bridge", + "Going to submit message delivery transaction with declared dispatch \ + weight {:?} that overflows maximal configured weight {}", + new_selected_weight, + reference.max_messages_weight_in_single_batch, + ); + new_selected_weight.unwrap_or(Weight::MAX) + }, + _ => break, + }; + + // limit messages in the batch by size + let new_selected_size = match relay_reference.selected_size.checked_add(details.size) { + Some(new_selected_size) + if new_selected_size <= reference.max_messages_size_in_single_batch => + new_selected_size, + new_selected_size if selected_count == 0 => { + log::warn!( + target: "bridge", + "Going to submit message delivery transaction with message \ + size {:?} that overflows maximal configured size {}", + new_selected_size, + reference.max_messages_size_in_single_batch, + ); + new_selected_size.unwrap_or(u32::MAX) + }, + _ => break, + }; + + // limit number of messages in the batch + let new_selected_count = selected_count + 1; + if new_selected_count > reference.max_messages_in_this_batch { + break + } + relay_reference.selected_size = new_selected_size; + + // If dispatch fee has been paid at the source chain, it means that it is **relayer** + // who's paying for dispatch at the target chain AND reward must cover this dispatch + // fee. + // + // If dispatch fee is paid at the target chain, it means that it'll be withdrawn from + // the dispatch origin account AND reward is not covering this fee. + // + // So in the latter case we're not adding the dispatch weight to the delivery + // transaction weight. + let mut new_selected_prepaid_nonces = relay_reference.selected_prepaid_nonces; + let new_selected_unpaid_weight = match details.dispatch_fee_payment { + DispatchFeePayment::AtSourceChain => { + new_selected_prepaid_nonces += 1; + relay_reference.selected_unpaid_weight.saturating_add(details.dispatch_weight) + }, + DispatchFeePayment::AtTargetChain => relay_reference.selected_unpaid_weight, + }; + relay_reference.selected_prepaid_nonces = new_selected_prepaid_nonces; + relay_reference.selected_unpaid_weight = new_selected_unpaid_weight; + + // now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT + // to deliver it? It depends on the relayer strategy. + if self.strategy.decide(&mut relay_reference).await { + soft_selected_count = index + 1; + } + + hard_selected_count = index + 1; + selected_weight = new_selected_weight; + selected_count = new_selected_count; + } + + if hard_selected_count != soft_selected_count { + let hard_selected_end_nonce = + hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; + let soft_selected_begin_nonce = hard_selected_begin_nonce; + let soft_selected_end_nonce = + soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; + log::warn!( + target: "bridge", + "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy it has selected \ + nonces [{:?}; {:?}].", + hard_selected_begin_nonce, + hard_selected_end_nonce, + soft_selected_begin_nonce, + soft_selected_end_nonce, + ); + + hard_selected_count = soft_selected_count; + } + + if hard_selected_count != 0 { + if relay_reference.selected_reward != P::SourceChainBalance::zero() && + relay_reference.selected_cost != P::SourceChainBalance::zero() + { + log::trace!( + target: "bridge", + "Expected reward from delivering nonces [{:?}; {:?}] is: {:?} - {:?} = {:?}", + hard_selected_begin_nonce, + hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1, + &relay_reference.selected_reward, + &relay_reference.selected_cost, + relay_reference.selected_reward - relay_reference.selected_cost, + ); + } + + Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1) + } else { + None + } + } +} diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs new file mode 100644 index 0000000000000..ef472e9c35052 --- /dev/null +++ b/relays/messages/src/relay_strategy/mix_strategy.rs @@ -0,0 +1,40 @@ +use async_trait::async_trait; + +use crate::{ + message_lane::MessageLane, + message_lane_loop::{ + RelayerMode, SourceClient as MessageLaneSourceClient, + TargetClient as MessageLaneTargetClient, + }, + relay_strategy::{AltruisticStrategy, RationalStrategy, RelayReference, RelayStrategy}, +}; + +/// The relayer doesn't care about rewards. +#[derive(Clone)] +pub struct MixStrategy { + relayer_mode: RelayerMode, +} + +impl MixStrategy { + /// Create mix strategy instance + pub fn new(relayer_mode: RelayerMode) -> Self { + Self { relayer_mode } + } +} + +#[async_trait] +impl RelayStrategy for MixStrategy { + async fn decide< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: &mut RelayReference, + ) -> bool { + match self.relayer_mode { + RelayerMode::Altruistic => AltruisticStrategy.decide(reference).await, + RelayerMode::Rational => RationalStrategy.decide(reference).await, + } + } +} diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs new file mode 100644 index 0000000000000..3e4eef8975dd8 --- /dev/null +++ b/relays/messages/src/relay_strategy/mod.rs @@ -0,0 +1,123 @@ +// 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 . + +//! Relayer strategy + +use std::ops::Range; + +use async_trait::async_trait; + +use bp_messages::{MessageNonce, Weight}; + +use crate::{ + message_lane::MessageLane, + message_lane_loop::{ + MessageDetails, MessageDetailsMap, SourceClient as MessageLaneSourceClient, + TargetClient as MessageLaneTargetClient, + }, + message_race_strategy::SourceRangesQueue, +}; + +pub(crate) use self::enforcement_strategy::*; +pub use self::{altruistic_strategy::*, mix_strategy::*, rational_strategy::*}; + +mod altruistic_strategy; +mod enforcement_strategy; +mod mix_strategy; +mod rational_strategy; + +/// Relayer strategy trait +#[async_trait] +pub trait RelayStrategy: 'static + Clone + Send + Sync { + /// The relayer decide how to process nonce by reference. + /// From given set of source nonces, that are ready to be delivered, select nonces + /// to fit into single delivery transaction. + /// + /// The function returns last nonce that must be delivered to the target chain. + async fn decide< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: &mut RelayReference, + ) -> bool; +} + +/// Reference data for participating in relay +pub struct RelayReference< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, +> { + /// The client that is connected to the message lane source node. + pub lane_source_client: SourceClient, + /// The client that is connected to the message lane target node. + pub lane_target_client: TargetClient, + /// Current block reward summary + pub selected_reward: P::SourceChainBalance, + /// Current block cost summary + pub selected_cost: P::SourceChainBalance, + /// Messages size summary + pub selected_size: u32, + + /// Current block reward summary + pub total_reward: P::SourceChainBalance, + /// All confirmations cost + pub total_confirmations_cost: P::SourceChainBalance, + /// Current block cost summary + pub total_cost: P::SourceChainBalance, + + /// Hard check begin nonce + pub hard_selected_begin_nonce: MessageNonce, + /// Count prepaid nonces + pub selected_prepaid_nonces: MessageNonce, + /// Unpaid nonces weight summary + pub selected_unpaid_weight: Weight, + + /// Index by all ready nonces + pub index: usize, + /// Current nonce + pub nonce: MessageNonce, + /// Current nonce details + pub details: MessageDetails, +} + +/// Relay reference data +pub struct RelayMessagesBatchReference< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, +> { + /// Maximal number of relayed messages in single delivery transaction. + pub max_messages_in_this_batch: MessageNonce, + /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. + pub max_messages_weight_in_single_batch: Weight, + /// Maximal cumulative size of relayed messages in single delivery transaction. + pub max_messages_size_in_single_batch: u32, + /// The client that is connected to the message lane source node. + pub lane_source_client: SourceClient, + /// The client that is connected to the message lane target node. + pub lane_target_client: TargetClient, + /// Source queue. + pub nonces_queue: SourceRangesQueue< + P::SourceHeaderHash, + P::SourceHeaderNumber, + MessageDetailsMap, + >, + /// Source queue range + pub nonces_queue_range: Range, +} diff --git a/relays/messages/src/relay_strategy/rational_strategy.rs b/relays/messages/src/relay_strategy/rational_strategy.rs new file mode 100644 index 0000000000000..dc408ffd49e25 --- /dev/null +++ b/relays/messages/src/relay_strategy/rational_strategy.rs @@ -0,0 +1,122 @@ +// 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 . + +//! Rational relay strategy + +use async_trait::async_trait; +use num_traits::SaturatingAdd; + +use bp_messages::MessageNonce; + +use crate::{ + message_lane::MessageLane, + message_lane_loop::{ + SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, + }, + relay_strategy::{RelayReference, RelayStrategy}, +}; + +/// The relayer will deliver all messages and confirmations as long as he's not losing any +/// funds. +#[derive(Clone)] +pub struct RationalStrategy; + +#[async_trait] +impl RelayStrategy for RationalStrategy { + async fn decide< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: &mut RelayReference, + ) -> bool { + // technically, multiple confirmations will be delivered in a single transaction, + // meaning less loses for relayer. But here we don't know the final relayer yet, so + // we're adding a separate transaction for every message. Normally, this cost is covered + // by the message sender. Probably reconsider this? + let confirmation_transaction_cost = + reference.lane_source_client.estimate_confirmation_transaction().await; + + let delivery_transaction_cost = match reference + .lane_target_client + .estimate_delivery_transaction_in_source_tokens( + reference.hard_selected_begin_nonce..= + (reference.hard_selected_begin_nonce + reference.index as MessageNonce), + reference.selected_prepaid_nonces, + reference.selected_unpaid_weight, + reference.selected_size as u32, + ) + .await + { + Ok(v) => v, + Err(err) => { + log::debug!( + target: "bridge", + "Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery", + err, + ); + return false + }, + }; + + // if it is the first message that makes reward less than cost, let's log it + // if this message makes batch profitable again, let's log it + let is_total_reward_less_than_cost = reference.total_reward < reference.total_cost; + let prev_total_cost = reference.total_cost; + let prev_total_reward = reference.total_reward; + reference.total_confirmations_cost = reference + .total_confirmations_cost + .saturating_add(&confirmation_transaction_cost); + reference.total_reward = reference.total_reward.saturating_add(&reference.details.reward); + reference.total_cost = + reference.total_confirmations_cost.saturating_add(&delivery_transaction_cost); + if !is_total_reward_less_than_cost && reference.total_reward < reference.total_cost { + log::debug!( + target: "bridge", + "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ + total reward {:?}->{:?}", + reference.nonce, + reference.details.reward, + prev_total_cost, + reference.total_cost, + prev_total_reward, + reference.total_reward, + ); + } else if is_total_reward_less_than_cost && reference.total_reward >= reference.total_cost { + log::debug!( + target: "bridge", + "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ + equal to the total reward {:?}->{:?} (again)", + reference.nonce, + reference.details.reward, + prev_total_cost, + reference.total_cost, + prev_total_reward, + reference.total_reward, + ); + } + + // Rational relayer never want to lose his funds + if reference.total_reward >= reference.total_cost { + reference.selected_reward = reference.total_reward; + reference.selected_cost = reference.total_cost; + return true + } + + false + } +} From 682318a15e3c5c975ec4cbe5021aaf7db065171e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 9 Nov 2021 12:58:04 +0300 Subject: [PATCH 0598/1210] add missing license header (#1204) --- .../src/relay_strategy/mix_strategy.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs index ef472e9c35052..a267d8ca5f5a8 100644 --- a/relays/messages/src/relay_strategy/mix_strategy.rs +++ b/relays/messages/src/relay_strategy/mix_strategy.rs @@ -1,3 +1,21 @@ +// 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 . + +//! Adapter for using `enum RelayerMode` in a context which requires `RelayStrategy`. + use async_trait::async_trait; use crate::{ @@ -9,7 +27,7 @@ use crate::{ relay_strategy::{AltruisticStrategy, RationalStrategy, RelayReference, RelayStrategy}, }; -/// The relayer doesn't care about rewards. +/// `RelayerMode` adapter. #[derive(Clone)] pub struct MixStrategy { relayer_mode: RelayerMode, From 18a6919f07dc04ff68239f8fef318356747a3d5e Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Thu, 11 Nov 2021 21:29:22 +0800 Subject: [PATCH 0599/1210] Add `AtLeast32BitUnsigned` for MessageLance::SourceChainBalance (#1207) --- relays/messages/Cargo.toml | 2 ++ relays/messages/src/message_lane.rs | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index ea5d46845c5a3..b11f00b957a42 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -19,3 +19,5 @@ parking_lot = "0.11.0" bp-messages = { path = "../../primitives/messages" } bp-runtime = { path = "../../primitives/runtime" } relay-utils = { path = "../utils" } + +sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/messages/src/message_lane.rs b/relays/messages/src/message_lane.rs index 2b2d8029fc74b..5c9728ad93abd 100644 --- a/relays/messages/src/message_lane.rs +++ b/relays/messages/src/message_lane.rs @@ -21,6 +21,7 @@ use num_traits::{SaturatingAdd, Zero}; use relay_utils::{BlockNumberBase, HeaderId}; +use sp_arithmetic::traits::AtLeast32BitUnsigned; use std::{fmt::Debug, ops::Sub}; /// One-way message lane. @@ -40,7 +41,8 @@ pub trait MessageLane: 'static + Clone + Send + Sync { /// 1) pay transaction fees; /// 2) pay message delivery and dispatch fee; /// 3) pay relayer rewards. - type SourceChainBalance: Clone + type SourceChainBalance: AtLeast32BitUnsigned + + Clone + Copy + Debug + PartialOrd From 84613c15f6259a9458e7e3112a067d50a45bd546 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu <31917973+acatangiu@users.noreply.github.com> Date: Mon, 15 Nov 2021 16:14:08 +0200 Subject: [PATCH 0600/1210] Remove unused PoA<>Substrate bridge (#1210) * Decouple the PoA bridge code from Rialto * Remove Rialto PoA bridge code * Remove relays/bin-ethereum code * Remove relays/client-ethereum code * Remove modules/ethereum code * Remove modules/ethereum-contract-builtin code * Remove PoA bridge documentation * Remove primitives/ethereum-poa code * Decouple Rialto from currency-exchange * Fix building with runtime-benchmarks * Fix should_encode_bridge_send_message_call test Because we removed some runtime modules/pallets, the substrate2substrate bridge pallet has a different index within the runtime so its calls have a different encoding. Update the test to use the new encoding. * Update readme - no more PoA bridge * Remove deployments/bridges/poa-rialto Also removes: - deployments/networks/eth-poa.yml - deployments/networks/OpenEthereum.Dockerfile * Remove deployments/dev/poa-config * Update deployments readme - no more PoA bridge * Remove eth-related scripts Deletes: - deployments/networks/eth-poa.yml - scripts/run-openethereum-node.sh * Remove poa-relay from gitlab-ci * Dockerfiles to use substrate-relay as default * Remove modules/currency-exchange code * Remove primitives/currency-exchange code Signed-off-by: acatangiu --- README.md | 7 +- bin/rialto/node/src/chain_spec.rs | 24 +- bin/rialto/runtime/Cargo.toml | 10 - bin/rialto/runtime/src/benches.rs | 38 - bin/rialto/runtime/src/exchange.rs | 259 --- bin/rialto/runtime/src/kovan.rs | 201 --- bin/rialto/runtime/src/lib.rs | 308 ---- bin/rialto/runtime/src/rialto_poa.rs | 183 -- modules/currency-exchange/Cargo.toml | 50 - modules/currency-exchange/src/benchmarking.rs | 135 -- modules/currency-exchange/src/lib.rs | 514 ------ modules/ethereum-contract-builtin/Cargo.toml | 28 - modules/ethereum-contract-builtin/src/lib.rs | 372 ---- modules/ethereum/Cargo.toml | 51 - modules/ethereum/src/benchmarking.rs | 270 --- modules/ethereum/src/error.rs | 102 -- modules/ethereum/src/finality.rs | 557 ------ modules/ethereum/src/import.rs | 600 ------- modules/ethereum/src/lib.rs | 1572 ----------------- modules/ethereum/src/mock.rs | 188 -- modules/ethereum/src/test_utils.rs | 322 ---- modules/ethereum/src/validators.rs | 458 ----- modules/ethereum/src/verification.rs | 972 ---------- primitives/currency-exchange/Cargo.toml | 27 - primitives/currency-exchange/src/lib.rs | 153 -- primitives/ethereum-poa/Cargo.toml | 59 - primitives/ethereum-poa/src/lib.rs | 732 -------- primitives/ethereum-poa/src/signatures.rs | 138 -- relays/bin-ethereum/Cargo.toml | 42 - relays/bin-ethereum/README.md | 7 - .../res/substrate-bridge-abi.json | 167 -- .../res/substrate-bridge-bytecode.hex | 1 - .../res/substrate-bridge-metadata.txt | 5 - relays/bin-ethereum/src/cli.yml | 166 -- relays/bin-ethereum/src/error.rs | 38 - relays/bin-ethereum/src/ethereum_client.rs | 631 ------- .../src/ethereum_deploy_contract.rs | 164 -- relays/bin-ethereum/src/ethereum_exchange.rs | 402 ----- .../src/ethereum_exchange_submit.rs | 110 -- relays/bin-ethereum/src/ethereum_sync_loop.rs | 299 ---- relays/bin-ethereum/src/instances.rs | 119 -- relays/bin-ethereum/src/main.rs | 424 ----- relays/bin-ethereum/src/rialto_client.rs | 300 ---- relays/bin-ethereum/src/rpc_errors.rs | 67 - .../bin-ethereum/src/substrate_sync_loop.rs | 204 --- relays/bin-ethereum/src/substrate_types.rs | 78 - relays/bin-substrate/src/cli/encode_call.rs | 2 +- relays/client-ethereum/Cargo.toml | 20 - relays/client-ethereum/src/client.rs | 265 --- relays/client-ethereum/src/error.rs | 82 - relays/client-ethereum/src/lib.rs | 47 - relays/client-ethereum/src/rpc.rs | 51 - relays/client-ethereum/src/sign.rs | 87 - relays/client-ethereum/src/types.rs | 80 - 54 files changed, 7 insertions(+), 12181 deletions(-) delete mode 100644 bin/rialto/runtime/src/benches.rs delete mode 100644 bin/rialto/runtime/src/exchange.rs delete mode 100644 bin/rialto/runtime/src/kovan.rs delete mode 100644 bin/rialto/runtime/src/rialto_poa.rs delete mode 100644 modules/currency-exchange/Cargo.toml delete mode 100644 modules/currency-exchange/src/benchmarking.rs delete mode 100644 modules/currency-exchange/src/lib.rs delete mode 100644 modules/ethereum-contract-builtin/Cargo.toml delete mode 100644 modules/ethereum-contract-builtin/src/lib.rs delete mode 100644 modules/ethereum/Cargo.toml delete mode 100644 modules/ethereum/src/benchmarking.rs delete mode 100644 modules/ethereum/src/error.rs delete mode 100644 modules/ethereum/src/finality.rs delete mode 100644 modules/ethereum/src/import.rs delete mode 100644 modules/ethereum/src/lib.rs delete mode 100644 modules/ethereum/src/mock.rs delete mode 100644 modules/ethereum/src/test_utils.rs delete mode 100644 modules/ethereum/src/validators.rs delete mode 100644 modules/ethereum/src/verification.rs delete mode 100644 primitives/currency-exchange/Cargo.toml delete mode 100644 primitives/currency-exchange/src/lib.rs delete mode 100644 primitives/ethereum-poa/Cargo.toml delete mode 100644 primitives/ethereum-poa/src/lib.rs delete mode 100644 primitives/ethereum-poa/src/signatures.rs delete mode 100644 relays/bin-ethereum/Cargo.toml delete mode 100644 relays/bin-ethereum/README.md delete mode 100644 relays/bin-ethereum/res/substrate-bridge-abi.json delete mode 100644 relays/bin-ethereum/res/substrate-bridge-bytecode.hex delete mode 100644 relays/bin-ethereum/res/substrate-bridge-metadata.txt delete mode 100644 relays/bin-ethereum/src/cli.yml delete mode 100644 relays/bin-ethereum/src/error.rs delete mode 100644 relays/bin-ethereum/src/ethereum_client.rs delete mode 100644 relays/bin-ethereum/src/ethereum_deploy_contract.rs delete mode 100644 relays/bin-ethereum/src/ethereum_exchange.rs delete mode 100644 relays/bin-ethereum/src/ethereum_exchange_submit.rs delete mode 100644 relays/bin-ethereum/src/ethereum_sync_loop.rs delete mode 100644 relays/bin-ethereum/src/instances.rs delete mode 100644 relays/bin-ethereum/src/main.rs delete mode 100644 relays/bin-ethereum/src/rialto_client.rs delete mode 100644 relays/bin-ethereum/src/rpc_errors.rs delete mode 100644 relays/bin-ethereum/src/substrate_sync_loop.rs delete mode 100644 relays/bin-ethereum/src/substrate_types.rs delete mode 100644 relays/client-ethereum/Cargo.toml delete mode 100644 relays/client-ethereum/src/client.rs delete mode 100644 relays/client-ethereum/src/error.rs delete mode 100644 relays/client-ethereum/src/lib.rs delete mode 100644 relays/client-ethereum/src/rpc.rs delete mode 100644 relays/client-ethereum/src/sign.rs delete mode 100644 relays/client-ethereum/src/types.rs diff --git a/README.md b/README.md index 41d7fec13d5b9..ac3e49b94c6a6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ These components include Substrate pallets for syncing headers, passing arbitrar as libraries for building relayers to provide cross-chain communication capabilities. Three bridge nodes are also available. The nodes can be used to run test networks which bridge other -Substrate chains or Ethereum Proof-of-Authority chains. +Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 @@ -38,7 +38,7 @@ cargo build --all cargo test --all ``` -Also you can build the repo with +Also you can build the repo with [Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): ```bash @@ -54,7 +54,7 @@ docker run --rm -it -w /shellhere/parity-bridges-common \ #artifacts can be found in ~/cache/target ``` -If you want to reproduce other steps of CI process you can use the following +If you want to reproduce other steps of CI process you can use the following [guide](https://github.com/paritytech/scripts#reproduce-ci-locally). If you need more information about setting up your development environment Substrate's @@ -104,7 +104,6 @@ the `relays` which are used to pass messages between chains. ├── diagrams // Pretty pictures of the project architecture │ └── ... ├── modules // Substrate Runtime Modules (a.k.a Pallets) -│ ├── ethereum // Ethereum PoA Header Sync Module │ ├── grandpa // On-Chain GRANDPA Light Client │ ├── messages // Cross Chain Message Passing │ ├── dispatch // Target Chain Message Execution diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 3ccfa13e74acb..49f77c9bc6a84 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -17,9 +17,9 @@ use bp_rialto::derive_account_from_millau_id; use polkadot_primitives::v1::{AssignmentId, ValidatorId}; use rialto_runtime::{ - AccountId, BabeConfig, BalancesConfig, BridgeKovanConfig, BridgeMillauMessagesConfig, - BridgeRialtoPoaConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, - SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, BabeConfig, BalancesConfig, BridgeMillauMessagesConfig, ConfigurationConfig, + GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, + WASM_BINARY, }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -216,8 +216,6 @@ fn testnet_genesis( authorities: Vec::new(), epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), }, - bridge_rialto_poa: load_rialto_poa_bridge_config(), - bridge_kovan: load_kovan_bridge_config(), grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: root_key }, session: SessionConfig { @@ -291,22 +289,6 @@ fn testnet_genesis( } } -fn load_rialto_poa_bridge_config() -> BridgeRialtoPoaConfig { - BridgeRialtoPoaConfig { - initial_header: rialto_runtime::rialto_poa::genesis_header(), - initial_difficulty: 0.into(), - initial_validators: rialto_runtime::rialto_poa::genesis_validators(), - } -} - -fn load_kovan_bridge_config() -> BridgeKovanConfig { - BridgeKovanConfig { - initial_header: rialto_runtime::kovan::genesis_header(), - initial_difficulty: 0.into(), - initial_validators: rialto_runtime::kovan::genesis_validators(), - } -} - #[test] fn derived_dave_account_is_as_expected() { let dave = get_account_id_from_seed::("Dave"); diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index c0be917c2bccc..36dc436ddca61 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -17,8 +17,6 @@ serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies -bp-currency-exchange = { path = "../../../primitives/currency-exchange", default-features = false } -bp-eth-poa = { path = "../../../primitives/ethereum-poa", default-features = false } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } @@ -26,9 +24,7 @@ bp-millau = { path = "../../../primitives/chain-millau", default-features = fals bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-currency-exchange = { path = "../../../modules/currency-exchange", default-features = false } pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } -pallet-bridge-eth-poa = { path = "../../../modules/ethereum", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } @@ -80,8 +76,6 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ - "bp-currency-exchange/std", - "bp-eth-poa/std", "bp-header-chain/std", "bp-message-dispatch/std", "bp-messages/std", @@ -99,9 +93,7 @@ std = [ "pallet-authority-discovery/std", "pallet-babe/std", "pallet-balances/std", - "pallet-bridge-currency-exchange/std", "pallet-bridge-dispatch/std", - "pallet-bridge-eth-poa/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-grandpa/std", @@ -137,8 +129,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "libsecp256k1", - "pallet-bridge-currency-exchange/runtime-benchmarks", - "pallet-bridge-eth-poa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/bin/rialto/runtime/src/benches.rs b/bin/rialto/runtime/src/benches.rs deleted file mode 100644 index ce3f84069795a..0000000000000 --- a/bin/rialto/runtime/src/benches.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020-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 . - -//! We want to use a different validator configuration for benchmarking than what's used in Kovan -//! or in our Rialto test network. However, we can't configure a new validator set on the fly which -//! means we need to wire the runtime together like this - -use pallet_bridge_eth_poa::{ValidatorsConfiguration, ValidatorsSource}; -use sp_std::vec; - -pub use crate::kovan::{ - genesis_header, genesis_validators, BridgeAuraConfiguration, FinalityVotesCachingInterval, - PruningStrategy, -}; - -frame_support::parameter_types! { - pub BridgeValidatorsConfiguration: pallet_bridge_eth_poa::ValidatorsConfiguration = bench_validator_config(); -} - -fn bench_validator_config() -> ValidatorsConfiguration { - ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(vec![[1; 20].into()])), - (1, ValidatorsSource::Contract([3; 20].into(), vec![[1; 20].into()])), - ]) -} diff --git a/bin/rialto/runtime/src/exchange.rs b/bin/rialto/runtime/src/exchange.rs deleted file mode 100644 index 4e18053e52e36..0000000000000 --- a/bin/rialto/runtime/src/exchange.rs +++ /dev/null @@ -1,259 +0,0 @@ -// 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 . - -//! Support for PoA -> Substrate native tokens exchange. -//! -//! If you want to exchange native PoA tokens for native Substrate -//! chain tokens, you need to: -//! 1) send some PoA tokens to `LOCK_FUNDS_ADDRESS` address on PoA chain. Data field of -//! the transaction must be SCALE-encoded id of Substrate account that will receive -//! funds on Substrate chain; -//! 2) wait until the 'lock funds' transaction is mined on PoA chain; -//! 3) wait until the block containing the 'lock funds' transaction is finalized on PoA chain; -//! 4) wait until the required PoA header and its finality are provided -//! to the PoA -> Substrate bridge module (it can be provided by you); -//! 5) receive tokens by providing proof-of-inclusion of PoA transaction. - -use bp_currency_exchange::{ - Error as ExchangeError, LockFundsTransaction, MaybeLockFundsTransaction, - Result as ExchangeResult, -}; -use bp_eth_poa::{transaction_decode_rlp, RawTransaction, RawTransactionReceipt}; -use codec::{Decode, Encode}; -use frame_support::RuntimeDebug; -use hex_literal::hex; -use scale_info::TypeInfo; -use sp_std::vec::Vec; - -/// Ethereum address where locked PoA funds must be sent to. -pub const LOCK_FUNDS_ADDRESS: [u8; 20] = hex!("DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); - -/// Ethereum transaction inclusion proof. -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)] -pub struct EthereumTransactionInclusionProof { - /// Hash of the block with transaction. - pub block: sp_core::H256, - /// Index of the transaction within the block. - pub index: u64, - /// The proof itself (right now it is all RLP-encoded transactions of the block + - /// RLP-encoded receipts of all transactions of the block). - pub proof: Vec<(RawTransaction, RawTransactionReceipt)>, -} - -/// We uniquely identify transfer by the pair (sender, nonce). -/// -/// The assumption is that this pair will never appear more than once in -/// transactions included into finalized blocks. This is obviously true -/// for any existing eth-like chain (that keep current TX format), because -/// otherwise transaction can be replayed over and over. -#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct EthereumTransactionTag { - /// Account that has locked funds. - pub account: [u8; 20], - /// Lock transaction nonce. - pub nonce: sp_core::U256, -} - -/// Ethereum transaction from runtime perspective. -pub struct EthTransaction; - -impl MaybeLockFundsTransaction for EthTransaction { - type Transaction = RawTransaction; - type Id = EthereumTransactionTag; - type Recipient = crate::AccountId; - type Amount = crate::Balance; - - fn parse( - raw_tx: &Self::Transaction, - ) -> ExchangeResult> { - let tx = transaction_decode_rlp(raw_tx).map_err(|_| ExchangeError::InvalidTransaction)?; - - // we only accept transactions sending funds directly to the pre-configured address - if tx.unsigned.to != Some(LOCK_FUNDS_ADDRESS.into()) { - log::trace!( - target: "runtime", - "Failed to parse fund locks transaction. Invalid peer recipient: {:?}", - tx.unsigned.to, - ); - - return Err(ExchangeError::InvalidTransaction) - } - - let mut recipient_raw = sp_core::H256::default(); - match tx.unsigned.payload.len() { - 32 => recipient_raw.as_fixed_bytes_mut().copy_from_slice(&tx.unsigned.payload), - len => { - log::trace!( - target: "runtime", - "Failed to parse fund locks transaction. Invalid recipient length: {}", - len, - ); - - return Err(ExchangeError::InvalidRecipient) - }, - } - let amount = tx.unsigned.value.low_u128(); - - if tx.unsigned.value != amount.into() { - log::trace!( - target: "runtime", - "Failed to parse fund locks transaction. Invalid amount: {}", - tx.unsigned.value, - ); - - return Err(ExchangeError::InvalidAmount) - } - - Ok(LockFundsTransaction { - id: EthereumTransactionTag { - account: *tx.sender.as_fixed_bytes(), - nonce: tx.unsigned.nonce, - }, - recipient: crate::AccountId::from(*recipient_raw.as_fixed_bytes()), - amount, - }) - } -} - -/// Prepares everything required to bench claim of funds locked by given transaction. -#[cfg(feature = "runtime-benchmarks")] -pub(crate) fn prepare_environment_for_claim, I: 'static>( - transactions: &[(RawTransaction, RawTransactionReceipt)], -) -> bp_eth_poa::H256 { - use bp_eth_poa::compute_merkle_root; - use pallet_bridge_eth_poa::{ - test_utils::{insert_dummy_header, validator_utils::validator, HeaderBuilder}, - BridgeStorage, Storage, - }; - - let mut storage = BridgeStorage::::new(); - let header = HeaderBuilder::with_parent_number_on_runtime::(0) - .transactions_root(compute_merkle_root(transactions.iter().map(|(tx, _)| tx))) - .receipts_root(compute_merkle_root(transactions.iter().map(|(_, receipt)| receipt))) - .sign_by(&validator(0)); - let header_id = header.compute_id(); - insert_dummy_header(&mut storage, header); - storage.finalize_and_prune_headers(Some(header_id), 0); - - header_id.hash -} - -/// Prepare signed ethereum lock-funds transaction. -#[cfg(any(feature = "runtime-benchmarks", test))] -pub(crate) fn prepare_ethereum_transaction( - recipient: &crate::AccountId, - editor: impl Fn(&mut bp_eth_poa::UnsignedTransaction), -) -> (RawTransaction, RawTransactionReceipt) { - use bp_eth_poa::{signatures::SignTransaction, Receipt, TransactionOutcome}; - - // prepare tx for OpenEthereum private dev chain: - // chain id is 0x11 - // sender secret is 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 - let chain_id = 0x11; - let signer = libsecp256k1::SecretKey::parse(&hex!( - "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" - )) - .unwrap(); - let recipient_raw: &[u8; 32] = recipient.as_ref(); - let mut eth_tx = bp_eth_poa::UnsignedTransaction { - nonce: 0.into(), - to: Some(LOCK_FUNDS_ADDRESS.into()), - value: 100.into(), - gas: 100_000.into(), - gas_price: 100_000.into(), - payload: recipient_raw.to_vec(), - }; - editor(&mut eth_tx); - ( - eth_tx.sign_by(&signer, Some(chain_id)), - Receipt { - outcome: TransactionOutcome::StatusCode(1), - gas_used: Default::default(), - log_bloom: Default::default(), - logs: Vec::new(), - } - .rlp(), - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - - fn ferdie() -> crate::AccountId { - hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c").into() - } - - #[test] - fn valid_transaction_accepted() { - assert_eq!( - EthTransaction::parse(&prepare_ethereum_transaction(&ferdie(), |_| {}).0), - Ok(LockFundsTransaction { - id: EthereumTransactionTag { - account: hex!("00a329c0648769a73afac7f9381e08fb43dbea72"), - nonce: 0.into(), - }, - recipient: ferdie(), - amount: 100, - }), - ); - } - - #[test] - fn invalid_transaction_rejected() { - assert_eq!(EthTransaction::parse(&Vec::new()), Err(ExchangeError::InvalidTransaction),); - } - - #[test] - fn transaction_with_invalid_peer_recipient_rejected() { - assert_eq!( - EthTransaction::parse( - &prepare_ethereum_transaction(&ferdie(), |tx| { - tx.to = None; - }) - .0 - ), - Err(ExchangeError::InvalidTransaction), - ); - } - - #[test] - fn transaction_with_invalid_recipient_rejected() { - assert_eq!( - EthTransaction::parse( - &prepare_ethereum_transaction(&ferdie(), |tx| { - tx.payload.clear(); - }) - .0 - ), - Err(ExchangeError::InvalidRecipient), - ); - } - - #[test] - fn transaction_with_invalid_amount_rejected() { - assert_eq!( - EthTransaction::parse( - &prepare_ethereum_transaction(&ferdie(), |tx| { - tx.value = sp_core::U256::from(u128::max_value()) + sp_core::U256::from(1); - }) - .0 - ), - Err(ExchangeError::InvalidAmount), - ); - } -} diff --git a/bin/rialto/runtime/src/kovan.rs b/bin/rialto/runtime/src/kovan.rs deleted file mode 100644 index 95b4f8c42f03b..0000000000000 --- a/bin/rialto/runtime/src/kovan.rs +++ /dev/null @@ -1,201 +0,0 @@ -// 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 . - -use crate::exchange::EthereumTransactionInclusionProof; - -use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; -use bp_header_chain::InclusionProofVerifier; -use frame_support::RuntimeDebug; -use hex_literal::hex; -use pallet_bridge_eth_poa::{ - AuraConfiguration, ChainTime as TChainTime, PruningStrategy as BridgePruningStrategy, - ValidatorsConfiguration, ValidatorsSource, -}; -use sp_std::prelude::*; - -frame_support::parameter_types! { - pub const FinalityVotesCachingInterval: Option = Some(16); - pub BridgeAuraConfiguration: AuraConfiguration = - kovan_aura_configuration(); - pub BridgeValidatorsConfiguration: ValidatorsConfiguration = - kovan_validators_configuration(); -} - -/// Max number of finalized headers to keep. It is equivalent of around 24 hours of -/// finalized blocks on current Kovan chain. -const FINALIZED_HEADERS_TO_KEEP: u64 = 20_000; - -/// Aura engine configuration for Kovan chain. -pub fn kovan_aura_configuration() -> AuraConfiguration { - AuraConfiguration { - empty_steps_transition: u64::max_value(), - strict_empty_steps_transition: 0, - validate_step_transition: 0x16e360, - validate_score_transition: 0x41a3c4, - two_thirds_majority_transition: u64::max_value(), - min_gas_limit: 0x1388.into(), - max_gas_limit: U256::max_value(), - maximum_extra_data_size: 0x20, - } -} - -/// Validators configuration for Kovan chain. -pub fn kovan_validators_configuration() -> ValidatorsConfiguration { - ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(genesis_validators())), - ( - 10960440, - ValidatorsSource::List(vec![ - hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(), - hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(), - hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(), - ]), - ), - ( - 10960500, - ValidatorsSource::Contract( - hex!("aE71807C1B0a093cB1547b682DC78316D945c9B8").into(), - vec![ - hex!("d05f7478c6aa10781258c5cc8b4f385fc8fa989c").into(), - hex!("03801efb0efe2a25ede5dd3a003ae880c0292e4d").into(), - hex!("a4df255ecf08bbf2c28055c65225c9a9847abd94").into(), - hex!("596e8221a30bfe6e7eff67fee664a01c73ba3c56").into(), - hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(), - ], - ), - ), - ]) -} - -/// Genesis validators set of Kovan chain. -pub fn genesis_validators() -> Vec

{ - vec![ - hex!("00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED").into(), - hex!("00427feae2419c15b89d1c21af10d1b6650a4d3d").into(), - hex!("4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c").into(), - hex!("0020ee4Be0e2027d76603cB751eE069519bA81A1").into(), - hex!("0010f94b296a852aaac52ea6c5ac72e03afd032d").into(), - hex!("007733a1FE69CF3f2CF989F81C7b4cAc1693387A").into(), - hex!("00E6d2b931F55a3f1701c7389d592a7778897879").into(), - hex!("00e4a10650e5a6D6001C38ff8E64F97016a1645c").into(), - hex!("00a0a24b9f0e5ec7aa4c7389b8302fd0123194de").into(), - ] -} - -/// Genesis header of the Kovan chain. -pub fn genesis_header() -> AuraHeader { - AuraHeader { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - .into(), - uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") - .into(), - extra_data: vec![], - state_root: hex!("2480155b48a1cea17d67dbfdfaafe821c1d19cdd478c5358e8ec56dec24502b2").into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - .into(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 6000000.into(), - difficulty: 131072.into(), - seal: vec![ - vec![128], - vec![ - 184, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ], - ], - } -} - -/// Kovan headers pruning strategy. -/// -/// We do not prune unfinalized headers because exchange module only accepts -/// claims from finalized headers. And if we're pruning unfinalized headers, then -/// some claims may never be accepted. -#[derive(Default, RuntimeDebug)] -pub struct PruningStrategy; - -impl BridgePruningStrategy for PruningStrategy { - fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { - best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP) - } -} - -/// PoA Header timestamp verification against `Timestamp` pallet. -#[derive(Default, RuntimeDebug)] -pub struct ChainTime; - -impl TChainTime for ChainTime { - fn is_timestamp_ahead(&self, timestamp: u64) -> bool { - let now = super::Timestamp::now(); - timestamp > now - } -} - -/// The Kovan Blockchain as seen by the runtime. -pub struct KovanBlockchain; - -impl InclusionProofVerifier for KovanBlockchain { - type Transaction = RawTransaction; - type TransactionInclusionProof = EthereumTransactionInclusionProof; - - fn verify_transaction_inclusion_proof( - proof: &Self::TransactionInclusionProof, - ) -> Option { - let is_transaction_finalized = crate::BridgeKovan::verify_transaction_finalized( - proof.block, - proof.index, - &proof.proof, - ); - - if !is_transaction_finalized { - return None - } - - proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn pruning_strategy_keeps_enough_headers() { - assert_eq!( - PruningStrategy::default().pruning_upper_bound(100_000, 10_000), - 0, - "10_000 <= 20_000 => nothing should be pruned yet", - ); - - assert_eq!( - PruningStrategy::default().pruning_upper_bound(100_000, 20_000), - 0, - "20_000 <= 20_000 => nothing should be pruned yet", - ); - - assert_eq!( - PruningStrategy::default().pruning_upper_bound(100_000, 30_000), - 10_000, - "20_000 <= 30_000 => we're ready to prune first 10_000 headers", - ); - } -} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index bf5a8b36ec195..aae9aa21c2fa5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -30,14 +30,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod exchange; - -#[cfg(feature = "runtime-benchmarks")] -pub mod benches; -pub mod kovan; pub mod millau_messages; pub mod parachains; -pub mod rialto_poa; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; @@ -72,8 +66,6 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; -pub use pallet_bridge_currency_exchange::Call as BridgeCurrencyExchangeCall; -pub use pallet_bridge_eth_poa::Call as BridgeEthPoACall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall; pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_sudo::Call as SudoCall; @@ -253,48 +245,6 @@ impl pallet_babe::Config for Runtime { type WeightInfo = (); } -type RialtoPoA = pallet_bridge_eth_poa::Instance1; -impl pallet_bridge_eth_poa::Config for Runtime { - type AuraConfiguration = rialto_poa::BridgeAuraConfiguration; - type FinalityVotesCachingInterval = rialto_poa::FinalityVotesCachingInterval; - type ValidatorsConfiguration = rialto_poa::BridgeValidatorsConfiguration; - type PruningStrategy = rialto_poa::PruningStrategy; - type ChainTime = rialto_poa::ChainTime; - type OnHeadersSubmitted = (); -} - -type Kovan = pallet_bridge_eth_poa::Instance2; -impl pallet_bridge_eth_poa::Config for Runtime { - type AuraConfiguration = kovan::BridgeAuraConfiguration; - type FinalityVotesCachingInterval = kovan::FinalityVotesCachingInterval; - type ValidatorsConfiguration = kovan::BridgeValidatorsConfiguration; - type PruningStrategy = kovan::PruningStrategy; - type ChainTime = kovan::ChainTime; - type OnHeadersSubmitted = (); -} - -type RialtoCurrencyExchange = pallet_bridge_currency_exchange::Instance1; -impl pallet_bridge_currency_exchange::Config for Runtime { - type OnTransactionSubmitted = (); - type PeerBlockchain = rialto_poa::RialtoBlockchain; - type PeerMaybeLockFundsTransaction = exchange::EthTransaction; - type RecipientsMap = bp_currency_exchange::IdentityRecipients; - type Amount = Balance; - type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter; - type DepositInto = DepositInto; -} - -type KovanCurrencyExchange = pallet_bridge_currency_exchange::Instance2; -impl pallet_bridge_currency_exchange::Config for Runtime { - type OnTransactionSubmitted = (); - type PeerBlockchain = kovan::KovanBlockchain; - type PeerMaybeLockFundsTransaction = exchange::EthTransaction; - type RecipientsMap = bp_currency_exchange::IdentityRecipients; - type Amount = Balance; - type CurrencyConverter = bp_currency_exchange::IdentityCurrencyConverter; - type DepositInto = DepositInto; -} - impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); @@ -307,68 +257,6 @@ impl pallet_bridge_dispatch::Config for Runtime { type AccountIdConverter = bp_rialto::AccountIdConverter; } -pub struct DepositInto; - -impl bp_currency_exchange::DepositInto for DepositInto { - type Recipient = AccountId; - type Amount = Balance; - - fn deposit_into( - recipient: Self::Recipient, - amount: Self::Amount, - ) -> bp_currency_exchange::Result<()> { - // let balances module make all checks for us (it won't allow depositing lower than - // existential deposit, balance overflow, ...) - let deposited = as Currency>::deposit_creating( - &recipient, amount, - ); - - // I'm dropping deposited here explicitly to illustrate the fact that it'll update - // `TotalIssuance` on drop - let deposited_amount = deposited.peek(); - drop(deposited); - - // we have 3 cases here: - // - deposited == amount: success - // - deposited == 0: deposit has failed and no changes to storage were made - // - deposited != 0: (should never happen in practice) deposit has been partially completed - match deposited_amount { - _ if deposited_amount == amount => { - log::trace!( - target: "runtime", - "Deposited {} to {:?}", - amount, - recipient, - ); - - Ok(()) - }, - _ if deposited_amount == 0 => { - log::error!( - target: "runtime", - "Deposit of {} to {:?} has failed", - amount, - recipient, - ); - - Err(bp_currency_exchange::Error::DepositFailed) - }, - _ => { - log::error!( - target: "runtime", - "Deposit of {} to {:?} has partially competed. {} has been deposited", - amount, - recipient, - deposited_amount, - ); - - // we can't return DepositFailed error here, because storage changes were made - Err(bp_currency_exchange::Error::DepositPartiallyFailed) - }, - } - } -} - impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; @@ -578,12 +466,6 @@ construct_runtime!( Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, - // Eth-PoA chains bridge modules. - BridgeRialtoPoa: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, - BridgeKovan: pallet_bridge_eth_poa::::{Pallet, Call, Config, Storage, ValidateUnsigned}, - BridgeRialtoCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, - BridgeKovanCurrencyExchange: pallet_bridge_currency_exchange::::{Pallet, Call}, - // Millau bridge modules. BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, @@ -693,46 +575,6 @@ impl_runtime_apis! { } } - impl bp_eth_poa::RialtoPoAHeaderApi for Runtime { - fn best_block() -> (u64, bp_eth_poa::H256) { - let best_block = BridgeRialtoPoa::best_block(); - (best_block.number, best_block.hash) - } - - fn finalized_block() -> (u64, bp_eth_poa::H256) { - let finalized_block = BridgeRialtoPoa::finalized_block(); - (finalized_block.number, finalized_block.hash) - } - - fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool { - BridgeRialtoPoa::is_import_requires_receipts(header) - } - - fn is_known_block(hash: bp_eth_poa::H256) -> bool { - BridgeRialtoPoa::is_known_block(hash) - } - } - - impl bp_eth_poa::KovanHeaderApi for Runtime { - fn best_block() -> (u64, bp_eth_poa::H256) { - let best_block = BridgeKovan::best_block(); - (best_block.number, best_block.hash) - } - - fn finalized_block() -> (u64, bp_eth_poa::H256) { - let finalized_block = BridgeKovan::finalized_block(); - (finalized_block.number, finalized_block.hash) - } - - fn is_import_requires_receipts(header: bp_eth_poa::AuraHeader) -> bool { - BridgeKovan::is_import_requires_receipts(header) - } - - fn is_known_block(hash: bp_eth_poa::H256) -> bool { - BridgeKovan::is_known_block(hash) - } - } - impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { let header = BridgeMillauGrandpa::best_finalized(); @@ -744,18 +586,6 @@ impl_runtime_apis! { } } - impl bp_currency_exchange::RialtoCurrencyExchangeApi for Runtime { - fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { - BridgeRialtoCurrencyExchange::filter_transaction_proof(&proof) - } - } - - impl bp_currency_exchange::KovanCurrencyExchangeApi for Runtime { - fn filter_transaction_proof(proof: exchange::EthereumTransactionInclusionProof) -> bool { - BridgeKovanCurrencyExchange::filter_transaction_proof(&proof) - } - } - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { fn validate_transaction( source: TransactionSource, @@ -1028,17 +858,10 @@ impl_runtime_apis! { use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; - use pallet_bridge_currency_exchange::benchmarking::Pallet as BridgeCurrencyExchangeBench; use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; let mut list = Vec::::new(); - list_benchmark!(list, extra, pallet_bridge_eth_poa, BridgeRialtoPoa); - list_benchmark!( - list, - extra, - pallet_bridge_currency_exchange, BridgeCurrencyExchangeBench:: - ); list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa); @@ -1068,46 +891,6 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - use pallet_bridge_currency_exchange::benchmarking::{ - Pallet as BridgeCurrencyExchangeBench, - Config as BridgeCurrencyExchangeConfig, - ProofParams as BridgeCurrencyExchangeProofParams, - }; - - impl BridgeCurrencyExchangeConfig for Runtime { - fn make_proof( - proof_params: BridgeCurrencyExchangeProofParams, - ) -> crate::exchange::EthereumTransactionInclusionProof { - use bp_currency_exchange::DepositInto; - - if proof_params.recipient_exists { - >::DepositInto::deposit_into( - proof_params.recipient.clone(), - ExistentialDeposit::get(), - ).unwrap(); - } - - let (transaction, receipt) = crate::exchange::prepare_ethereum_transaction( - &proof_params.recipient, - |tx| { - // our runtime only supports transactions where data is exactly 32 bytes long - // (receiver key) - // => we are ignoring `transaction_size_factor` here - tx.value = (ExistentialDeposit::get() * 10).into(); - }, - ); - let transactions = sp_std::iter::repeat((transaction, receipt)) - .take(1 + proof_params.proof_size_factor as usize) - .collect::>(); - let block_hash = crate::exchange::prepare_environment_for_claim::(&transactions); - crate::exchange::EthereumTransactionInclusionProof { - block: block_hash, - index: 0, - proof: transactions, - } - } - } - use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use bp_runtime::messages::DispatchFeePayment; use bridge_runtime_common::messages; @@ -1274,13 +1057,6 @@ impl_runtime_apis! { } } - add_benchmark!(params, batches, pallet_bridge_eth_poa, BridgeRialtoPoa); - add_benchmark!( - params, - batches, - pallet_bridge_currency_exchange, - BridgeCurrencyExchangeBench:: - ); add_benchmark!( params, batches, @@ -1322,48 +1098,8 @@ where #[cfg(test)] mod tests { use super::*; - use bp_currency_exchange::DepositInto; use bridge_runtime_common::messages; - fn run_deposit_into_test(test: impl Fn(AccountId) -> Balance) { - let mut ext: sp_io::TestExternalities = - SystemConfig::default().build_storage::().unwrap().into(); - ext.execute_with(|| { - // initially issuance is zero - assert_eq!( - as Currency>::total_issuance(), - 0, - ); - - // create account - let account: AccountId = [1u8; 32].into(); - let initial_amount = ExistentialDeposit::get(); - let deposited = - as Currency>::deposit_creating( - &account, - initial_amount, - ); - drop(deposited); - assert_eq!( - as Currency>::total_issuance(), - initial_amount, - ); - assert_eq!( - as Currency>::free_balance(&account), - initial_amount, - ); - - // run test - let total_issuance_change = test(account); - - // check that total issuance has changed by `run_deposit_into_test` - assert_eq!( - as Currency>::total_issuance(), - initial_amount + total_issuance_change, - ); - }); - } - #[test] fn ensure_rialto_message_lane_weights_are_correct() { type Weights = pallet_bridge_messages::weights::RialtoWeight; @@ -1405,50 +1141,6 @@ mod tests { ); } - #[test] - fn deposit_into_existing_account_works() { - run_deposit_into_test(|existing_account| { - let initial_amount = - as Currency>::free_balance( - &existing_account, - ); - let additional_amount = 10_000; - >::DepositInto::deposit_into( - existing_account.clone(), - additional_amount, - ) - .unwrap(); - assert_eq!( - as Currency>::free_balance( - &existing_account - ), - initial_amount + additional_amount, - ); - additional_amount - }); - } - - #[test] - fn deposit_into_new_account_works() { - run_deposit_into_test(|_| { - let initial_amount = 0; - let additional_amount = ExistentialDeposit::get() + 10_000; - let new_account: AccountId = [42u8; 32].into(); - >::DepositInto::deposit_into( - new_account.clone(), - additional_amount, - ) - .unwrap(); - assert_eq!( - as Currency>::free_balance( - &new_account - ), - initial_amount + additional_amount, - ); - additional_amount - }); - } - #[test] fn call_size() { const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests diff --git a/bin/rialto/runtime/src/rialto_poa.rs b/bin/rialto/runtime/src/rialto_poa.rs deleted file mode 100644 index 865ef387d1b43..0000000000000 --- a/bin/rialto/runtime/src/rialto_poa.rs +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2020-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 . - -//! Configuration parameters for the Rialto PoA chain. - -use crate::exchange::EthereumTransactionInclusionProof; - -use bp_eth_poa::{Address, AuraHeader, RawTransaction, U256}; -use bp_header_chain::InclusionProofVerifier; -use frame_support::RuntimeDebug; -use hex_literal::hex; -use pallet_bridge_eth_poa::{ - AuraConfiguration, ChainTime as TChainTime, PruningStrategy as TPruningStrategy, - ValidatorsConfiguration, ValidatorsSource, -}; -use sp_std::prelude::*; - -frame_support::parameter_types! { - pub const FinalityVotesCachingInterval: Option = Some(8); - pub BridgeAuraConfiguration: AuraConfiguration = - aura_configuration(); - pub BridgeValidatorsConfiguration: ValidatorsConfiguration = - validators_configuration(); -} - -/// Max number of finalized headers to keep. -const FINALIZED_HEADERS_TO_KEEP: u64 = 5_000; - -/// Aura engine configuration for Rialto chain. -pub fn aura_configuration() -> AuraConfiguration { - AuraConfiguration { - empty_steps_transition: 0xfffffffff, - strict_empty_steps_transition: 0, - validate_step_transition: 0, - validate_score_transition: 0, - two_thirds_majority_transition: u64::max_value(), - min_gas_limit: 0x1388.into(), - max_gas_limit: U256::max_value(), - maximum_extra_data_size: 0x20, - } -} - -/// Validators configuration for Rialto PoA chain. -pub fn validators_configuration() -> ValidatorsConfiguration { - ValidatorsConfiguration::Single(ValidatorsSource::List(genesis_validators())) -} - -/// Genesis validators set of Rialto PoA chain. -pub fn genesis_validators() -> Vec
{ - vec![ - hex!("005e714f896a8b7cede9d38688c1a81de72a58e4").into(), - hex!("007594304039c2937a12220338aab821d819f5a4").into(), - hex!("004e7a39907f090e19b0b80a277e77b72b22e269").into(), - ] -} - -/// Genesis header of the Rialto PoA chain. -/// -/// To obtain genesis header from a running node, invoke: -/// ```bash -/// $ http localhost:8545 jsonrpc=2.0 id=1 method=eth_getBlockByNumber params:='["earliest", false]' -v -/// ``` -pub fn genesis_header() -> AuraHeader { - AuraHeader { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - .into(), - uncles_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") - .into(), - extra_data: vec![], - state_root: hex!("a992d04c791620ed7ed96555a80cf0568355bb4bee2656f46899a4372f25f248").into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - .into(), - log_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 0x222222.into(), - difficulty: 0x20000.into(), - seal: vec![vec![0x80], { - let mut vec = vec![0xb8, 0x41]; - vec.resize(67, 0); - vec - }], - } -} - -/// Rialto PoA headers pruning strategy. -/// -/// We do not prune unfinalized headers because exchange module only accepts -/// claims from finalized headers. And if we're pruning unfinalized headers, then -/// some claims may never be accepted. -#[derive(Default, RuntimeDebug)] -pub struct PruningStrategy; - -impl TPruningStrategy for PruningStrategy { - fn pruning_upper_bound(&mut self, _best_number: u64, best_finalized_number: u64) -> u64 { - best_finalized_number.saturating_sub(FINALIZED_HEADERS_TO_KEEP) - } -} - -/// ChainTime provider -#[derive(Default)] -pub struct ChainTime; - -impl TChainTime for ChainTime { - fn is_timestamp_ahead(&self, timestamp: u64) -> bool { - let now = super::Timestamp::now(); - timestamp > now - } -} - -/// The Rialto PoA Blockchain as seen by the runtime. -pub struct RialtoBlockchain; - -impl InclusionProofVerifier for RialtoBlockchain { - type Transaction = RawTransaction; - type TransactionInclusionProof = EthereumTransactionInclusionProof; - - fn verify_transaction_inclusion_proof( - proof: &Self::TransactionInclusionProof, - ) -> Option { - let is_transaction_finalized = crate::BridgeRialtoPoa::verify_transaction_finalized( - proof.block, - proof.index, - &proof.proof, - ); - - if !is_transaction_finalized { - return None - } - - proof.proof.get(proof.index as usize).map(|(tx, _)| tx.clone()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn genesis_hash_matches() { - assert_eq!( - genesis_header().compute_hash(), - hex!("1468e1a0fa20d30025a5a0f87e1cced4fdc393b84b7d2850b11ca5863db482cb").into(), - ); - } - - #[test] - fn pruning_strategy_keeps_enough_headers() { - assert_eq!( - PruningStrategy::default().pruning_upper_bound(100_000, 1_000), - 0, - "1_000 <= 5_000 => nothing should be pruned yet", - ); - - assert_eq!( - PruningStrategy::default().pruning_upper_bound(100_000, 5_000), - 0, - "5_000 <= 5_000 => nothing should be pruned yet", - ); - - assert_eq!( - PruningStrategy::default().pruning_upper_bound(100_000, 10_000), - 5_000, - "5_000 <= 10_000 => we're ready to prune first 5_000 headers", - ); - } -} diff --git a/modules/currency-exchange/Cargo.toml b/modules/currency-exchange/Cargo.toml deleted file mode 100644 index dc06a342cc8e6..0000000000000 --- a/modules/currency-exchange/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -name = "pallet-bridge-currency-exchange" -description = "A Substrate Runtime module that accepts 'lock funds' transactions from a peer chain and grants an equivalent amount to a the appropriate Substrate account." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } - -# Bridge dependencies - -bp-currency-exchange = { path = "../../primitives/currency-exchange", default-features = false } -bp-header-chain = { path = "../../primitives/header-chain", default-features = false } - -# Substrate Dependencies - -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } - -[dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } - -[features] -default = ["std"] -std = [ - "bp-currency-exchange/std", - "bp-header-chain/std", - "codec/std", - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "serde", - "sp-runtime/std", - "sp-std/std", -] -runtime-benchmarks = [ - "frame-benchmarking", - "sp-std", -] diff --git a/modules/currency-exchange/src/benchmarking.rs b/modules/currency-exchange/src/benchmarking.rs deleted file mode 100644 index 813c1bfe884dd..0000000000000 --- a/modules/currency-exchange/src/benchmarking.rs +++ /dev/null @@ -1,135 +0,0 @@ -// 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 . - -//! Exchange module complexity is mostly determined by callbacks, defined by runtime. -//! So we are giving runtime opportunity to prepare environment and construct proof -//! before invoking module calls. - -use super::{ - Call, Config as CurrencyExchangeConfig, InclusionProofVerifier, - Pallet as CurrencyExchangePallet, -}; -use sp_std::prelude::*; - -use frame_benchmarking::{account, benchmarks_instance_pallet}; -use frame_system::RawOrigin; - -const SEED: u32 = 0; -const WORST_TX_SIZE_FACTOR: u32 = 1000; -const WORST_PROOF_SIZE_FACTOR: u32 = 1000; - -/// Pallet we're benchmarking here. -pub struct Pallet, I: 'static>(CurrencyExchangePallet); - -/// Proof benchmarking parameters. -pub struct ProofParams { - /// Funds recipient. - pub recipient: Recipient, - /// When true, recipient must exists before import. - pub recipient_exists: bool, - /// When 0, transaction should have minimal possible size. When this value has non-zero value - /// n, transaction size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. - pub transaction_size_factor: u32, - /// When 0, proof should have minimal possible size. When this value has non-zero value n, - /// proof size should be (if possible) near to MIN_SIZE + n * SIZE_FACTOR. - pub proof_size_factor: u32, -} - -/// Config that must be implemented by runtime. -pub trait Config: CurrencyExchangeConfig { - /// Prepare proof for importing exchange transaction. - fn make_proof( - proof_params: ProofParams, - ) -> <>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof; -} - -benchmarks_instance_pallet! { - // Benchmark `import_peer_transaction` extrinsic with the best possible conditions: - // * Proof is the transaction itself. - // * Transaction has minimal size. - // * Recipient account exists. - import_peer_transaction_best_case { - let i in 1..100; - - let recipient: T::AccountId = account("recipient", i, SEED); - let proof = T::make_proof(ProofParams { - recipient: recipient.clone(), - recipient_exists: true, - transaction_size_factor: 0, - proof_size_factor: 0, - }); - }: import_peer_transaction(RawOrigin::Signed(recipient), proof) - - // Benchmark `import_peer_transaction` extrinsic when recipient account does not exists. - import_peer_transaction_when_recipient_does_not_exists { - let i in 1..100; - - let recipient: T::AccountId = account("recipient", i, SEED); - let proof = T::make_proof(ProofParams { - recipient: recipient.clone(), - recipient_exists: false, - transaction_size_factor: 0, - proof_size_factor: 0, - }); - }: import_peer_transaction(RawOrigin::Signed(recipient), proof) - - // Benchmark `import_peer_transaction` when transaction size increases. - import_peer_transaction_when_transaction_size_increases { - let i in 1..100; - let n in 1..WORST_TX_SIZE_FACTOR; - - let recipient: T::AccountId = account("recipient", i, SEED); - let proof = T::make_proof(ProofParams { - recipient: recipient.clone(), - recipient_exists: true, - transaction_size_factor: n, - proof_size_factor: 0, - }); - }: import_peer_transaction(RawOrigin::Signed(recipient), proof) - - // Benchmark `import_peer_transaction` when proof size increases. - import_peer_transaction_when_proof_size_increases { - let i in 1..100; - let n in 1..WORST_PROOF_SIZE_FACTOR; - - let recipient: T::AccountId = account("recipient", i, SEED); - let proof = T::make_proof(ProofParams { - recipient: recipient.clone(), - recipient_exists: true, - transaction_size_factor: 0, - proof_size_factor: n, - }); - }: import_peer_transaction(RawOrigin::Signed(recipient), proof) - - // Benchmark `import_peer_transaction` extrinsic with the worst possible conditions: - // * Proof is large. - // * Transaction has large size. - // * Recipient account does not exists. - import_peer_transaction_worst_case { - let i in 1..100; - let m in WORST_TX_SIZE_FACTOR..WORST_TX_SIZE_FACTOR+1; - let n in WORST_PROOF_SIZE_FACTOR..WORST_PROOF_SIZE_FACTOR+1; - - let recipient: T::AccountId = account("recipient", i, SEED); - let proof = T::make_proof(ProofParams { - recipient: recipient.clone(), - recipient_exists: false, - transaction_size_factor: m, - proof_size_factor: n, - }); - }: import_peer_transaction(RawOrigin::Signed(recipient), proof) - -} diff --git a/modules/currency-exchange/src/lib.rs b/modules/currency-exchange/src/lib.rs deleted file mode 100644 index 31b789dd97e73..0000000000000 --- a/modules/currency-exchange/src/lib.rs +++ /dev/null @@ -1,514 +0,0 @@ -// 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 . - -//! Runtime module that allows tokens exchange between two bridged chains. - -#![cfg_attr(not(feature = "std"), no_std)] - -use bp_currency_exchange::{ - CurrencyConverter, DepositInto, Error as ExchangeError, MaybeLockFundsTransaction, - RecipientsMap, -}; -use bp_header_chain::InclusionProofVerifier; -use frame_support::ensure; - -#[cfg(feature = "runtime-benchmarks")] -pub mod benchmarking; - -/// Called when transaction is submitted to the exchange module. -pub trait OnTransactionSubmitted { - /// Called when valid transaction is submitted and accepted by the module. - fn on_valid_transaction_submitted(submitter: AccountId); -} - -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config] - pub trait Config: frame_system::Config { - /// Handler for transaction submission result. - type OnTransactionSubmitted: OnTransactionSubmitted; - /// Represents the blockchain that we'll be exchanging currency with. - type PeerBlockchain: InclusionProofVerifier; - /// Peer blockchain transaction parser. - type PeerMaybeLockFundsTransaction: MaybeLockFundsTransaction< - Transaction = ::Transaction, - >; - /// Map between blockchains recipients. - type RecipientsMap: RecipientsMap< - PeerRecipient = ::Recipient, - Recipient = Self::AccountId, - >; - /// This blockchain currency amount type. - type Amount; - /// Converter from peer blockchain currency type into current blockchain currency type. - type CurrencyConverter: CurrencyConverter< - SourceAmount = ::Amount, - TargetAmount = Self::Amount, - >; - /// Something that could grant money. - type DepositInto: DepositInto; - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(PhantomData<(T, I)>); - - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet {} - - #[pallet::call] - impl, I: 'static> Pallet { - /// Imports lock fund transaction of the peer blockchain. - #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_peer_transaction( - origin: OriginFor, - proof: <>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, - ) -> DispatchResult { - let submitter = frame_system::ensure_signed(origin)?; - - // verify and parse transaction proof - let deposit = prepare_deposit_details::(&proof)?; - - // make sure to update the mapping if we deposit successfully to avoid double spending, - // i.e. whenever `deposit_into` is successful we MUST update `Transfers`. - { - // if any changes were made to the storage, we can't just return error here, because - // otherwise the same proof may be imported again - let deposit_result = - T::DepositInto::deposit_into(deposit.recipient, deposit.amount); - match deposit_result { - Ok(_) => (), - Err(ExchangeError::DepositPartiallyFailed) => (), - Err(error) => return Err(Error::::from(error).into()), - } - Transfers::::insert(&deposit.transfer_id, ()) - } - - // reward submitter for providing valid message - T::OnTransactionSubmitted::on_valid_transaction_submitted(submitter); - - log::trace!( - target: "runtime", - "Completed currency exchange: {:?}", - deposit.transfer_id, - ); - - Ok(()) - } - } - - #[pallet::error] - pub enum Error { - /// Invalid peer blockchain transaction provided. - InvalidTransaction, - /// Peer transaction has invalid amount. - InvalidAmount, - /// Peer transaction has invalid recipient. - InvalidRecipient, - /// Cannot map from peer recipient to this blockchain recipient. - FailedToMapRecipients, - /// Failed to convert from peer blockchain currency to this blockchain currency. - FailedToConvertCurrency, - /// Deposit has failed. - DepositFailed, - /// Deposit has partially failed (changes to recipient account were made). - DepositPartiallyFailed, - /// Transaction is not finalized. - UnfinalizedTransaction, - /// Transaction funds are already claimed. - AlreadyClaimed, - } - - /// All transfers that have already been claimed. - #[pallet::storage] - pub(super) type Transfers, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - ::Id, - (), - ValueQuery, - >; -} - -impl, I: 'static> Pallet { - /// Returns true if currency exchange module is able to import given transaction proof in - /// its current state. - pub fn filter_transaction_proof( - proof: &::TransactionInclusionProof, - ) -> bool { - if let Err(err) = prepare_deposit_details::(proof) { - log::trace!( - target: "runtime", - "Can't accept exchange transaction: {:?}", - err, - ); - - return false - } - - true - } -} - -impl, I: 'static> From for Error { - fn from(error: ExchangeError) -> Self { - match error { - ExchangeError::InvalidTransaction => Error::InvalidTransaction, - ExchangeError::InvalidAmount => Error::InvalidAmount, - ExchangeError::InvalidRecipient => Error::InvalidRecipient, - ExchangeError::FailedToMapRecipients => Error::FailedToMapRecipients, - ExchangeError::FailedToConvertCurrency => Error::FailedToConvertCurrency, - ExchangeError::DepositFailed => Error::DepositFailed, - ExchangeError::DepositPartiallyFailed => Error::DepositPartiallyFailed, - } - } -} - -impl OnTransactionSubmitted for () { - fn on_valid_transaction_submitted(_: AccountId) {} -} - -/// Exchange deposit details. -struct DepositDetails, I: 'static> { - /// Transfer id. - pub transfer_id: ::Id, - /// Transfer recipient. - pub recipient: ::Recipient, - /// Transfer amount. - pub amount: ::TargetAmount, -} - -/// Verify and parse transaction proof, preparing everything required for importing -/// this transaction proof. -fn prepare_deposit_details, I: 'static>( - proof: &<>::PeerBlockchain as InclusionProofVerifier>::TransactionInclusionProof, -) -> Result, Error> { - // ensure that transaction is included in finalized block that we know of - let transaction = >::PeerBlockchain::verify_transaction_inclusion_proof(proof) - .ok_or(Error::::UnfinalizedTransaction)?; - - // parse transaction - let transaction = >::PeerMaybeLockFundsTransaction::parse(&transaction) - .map_err(Error::::from)?; - let transfer_id = transaction.id; - ensure!(!Transfers::::contains_key(&transfer_id), Error::::AlreadyClaimed); - - // grant recipient - let recipient = T::RecipientsMap::map(transaction.recipient).map_err(Error::::from)?; - let amount = T::CurrencyConverter::convert(transaction.amount).map_err(Error::::from)?; - - Ok(DepositDetails { transfer_id, recipient, amount }) -} - -#[cfg(test)] -mod tests { - // From construct_runtime macro - #![allow(clippy::from_over_into)] - - use super::*; - use bp_currency_exchange::LockFundsTransaction; - use frame_support::{ - assert_noop, assert_ok, construct_runtime, parameter_types, weights::Weight, - }; - use sp_core::H256; - use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, - }; - - type AccountId = u64; - - const INVALID_TRANSACTION_ID: u64 = 100; - const ALREADY_CLAIMED_TRANSACTION_ID: u64 = 101; - const UNKNOWN_RECIPIENT_ID: u64 = 0; - const INVALID_AMOUNT: u64 = 0; - const MAX_DEPOSIT_AMOUNT: u64 = 1000; - const SUBMITTER: u64 = 2000; - - type RawTransaction = LockFundsTransaction; - - pub struct DummyTransactionSubmissionHandler; - - impl OnTransactionSubmitted for DummyTransactionSubmissionHandler { - fn on_valid_transaction_submitted(submitter: AccountId) { - Transfers::::insert(submitter, ()); - } - } - - pub struct DummyBlockchain; - - impl InclusionProofVerifier for DummyBlockchain { - type Transaction = RawTransaction; - type TransactionInclusionProof = (bool, RawTransaction); - - fn verify_transaction_inclusion_proof( - proof: &Self::TransactionInclusionProof, - ) -> Option { - if proof.0 { - Some(proof.1.clone()) - } else { - None - } - } - } - - pub struct DummyTransaction; - - impl MaybeLockFundsTransaction for DummyTransaction { - type Transaction = RawTransaction; - type Id = u64; - type Recipient = AccountId; - type Amount = u64; - - fn parse(tx: &Self::Transaction) -> bp_currency_exchange::Result { - match tx.id { - INVALID_TRANSACTION_ID => Err(ExchangeError::InvalidTransaction), - _ => Ok(tx.clone()), - } - } - } - - pub struct DummyRecipientsMap; - - impl RecipientsMap for DummyRecipientsMap { - type PeerRecipient = AccountId; - type Recipient = AccountId; - - fn map( - peer_recipient: Self::PeerRecipient, - ) -> bp_currency_exchange::Result { - match peer_recipient { - UNKNOWN_RECIPIENT_ID => Err(ExchangeError::FailedToMapRecipients), - _ => Ok(peer_recipient * 10), - } - } - } - - pub struct DummyCurrencyConverter; - - impl CurrencyConverter for DummyCurrencyConverter { - type SourceAmount = u64; - type TargetAmount = u64; - - fn convert(amount: Self::SourceAmount) -> bp_currency_exchange::Result { - match amount { - INVALID_AMOUNT => Err(ExchangeError::FailedToConvertCurrency), - _ => Ok(amount * 10), - } - } - } - - pub struct DummyDepositInto; - - impl DepositInto for DummyDepositInto { - type Recipient = AccountId; - type Amount = u64; - - fn deposit_into( - _recipient: Self::Recipient, - amount: Self::Amount, - ) -> bp_currency_exchange::Result<()> { - match amount { - amount if amount < MAX_DEPOSIT_AMOUNT * 10 => Ok(()), - amount if amount == MAX_DEPOSIT_AMOUNT * 10 => - Err(ExchangeError::DepositPartiallyFailed), - _ => Err(ExchangeError::DepositFailed), - } - } - } - - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - type Block = frame_system::mocking::MockBlock; - use crate as pallet_bridge_currency_exchange; - - construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Exchange: pallet_bridge_currency_exchange::{Pallet}, - } - } - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl frame_system::Config for TestRuntime { - type Origin = Origin; - type Index = u64; - type Call = Call; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type SS58Prefix = (); - type OnSetCode = (); - } - - impl Config for TestRuntime { - type OnTransactionSubmitted = DummyTransactionSubmissionHandler; - type PeerBlockchain = DummyBlockchain; - type PeerMaybeLockFundsTransaction = DummyTransaction; - type RecipientsMap = DummyRecipientsMap; - type Amount = u64; - type CurrencyConverter = DummyCurrencyConverter; - type DepositInto = DummyDepositInto; - } - - fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - sp_io::TestExternalities::new(t) - } - - fn transaction(id: u64) -> RawTransaction { - RawTransaction { id, recipient: 1, amount: 2 } - } - - #[test] - fn unfinalized_transaction_rejected() { - new_test_ext().execute_with(|| { - assert_noop!( - Exchange::import_peer_transaction( - Origin::signed(SUBMITTER), - (false, transaction(0)) - ), - Error::::UnfinalizedTransaction, - ); - }); - } - - #[test] - fn invalid_transaction_rejected() { - new_test_ext().execute_with(|| { - assert_noop!( - Exchange::import_peer_transaction( - Origin::signed(SUBMITTER), - (true, transaction(INVALID_TRANSACTION_ID)), - ), - Error::::InvalidTransaction, - ); - }); - } - - #[test] - fn claimed_transaction_rejected() { - new_test_ext().execute_with(|| { - ::Transfers::insert(ALREADY_CLAIMED_TRANSACTION_ID, ()); - assert_noop!( - Exchange::import_peer_transaction( - Origin::signed(SUBMITTER), - (true, transaction(ALREADY_CLAIMED_TRANSACTION_ID)), - ), - Error::::AlreadyClaimed, - ); - }); - } - - #[test] - fn transaction_with_unknown_recipient_rejected() { - new_test_ext().execute_with(|| { - let mut transaction = transaction(0); - transaction.recipient = UNKNOWN_RECIPIENT_ID; - assert_noop!( - Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToMapRecipients, - ); - }); - } - - #[test] - fn transaction_with_invalid_amount_rejected() { - new_test_ext().execute_with(|| { - let mut transaction = transaction(0); - transaction.amount = INVALID_AMOUNT; - assert_noop!( - Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::FailedToConvertCurrency, - ); - }); - } - - #[test] - fn transaction_with_invalid_deposit_rejected() { - new_test_ext().execute_with(|| { - let mut transaction = transaction(0); - transaction.amount = MAX_DEPOSIT_AMOUNT + 1; - assert_noop!( - Exchange::import_peer_transaction(Origin::signed(SUBMITTER), (true, transaction)), - Error::::DepositFailed, - ); - }); - } - - #[test] - fn valid_transaction_accepted_even_if_deposit_partially_fails() { - new_test_ext().execute_with(|| { - let mut transaction = transaction(0); - transaction.amount = MAX_DEPOSIT_AMOUNT; - assert_ok!(Exchange::import_peer_transaction( - Origin::signed(SUBMITTER), - (true, transaction), - ),); - - // ensure that the transfer has been marked as completed - assert!(::Transfers::contains_key(0u64)); - // ensure that submitter has been rewarded - assert!(::Transfers::contains_key(SUBMITTER)); - }); - } - - #[test] - fn valid_transaction_accepted() { - new_test_ext().execute_with(|| { - assert_ok!(Exchange::import_peer_transaction( - Origin::signed(SUBMITTER), - (true, transaction(0)), - ),); - - // ensure that the transfer has been marked as completed - assert!(::Transfers::contains_key(0u64)); - // ensure that submitter has been rewarded - assert!(::Transfers::contains_key(SUBMITTER)); - }); - } -} diff --git a/modules/ethereum-contract-builtin/Cargo.toml b/modules/ethereum-contract-builtin/Cargo.toml deleted file mode 100644 index ffb98bc6bd85e..0000000000000 --- a/modules/ethereum-contract-builtin/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "ethereum-contract-builtin" -description = "Small crate that helps Solidity contract to verify finality proof." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } -ethereum-types = "0.12.0" -finality-grandpa = "0.14.0" -hex = "0.4" -log = "0.4.14" - -# Runtime/chain specific dependencies - -rialto-runtime = { path = "../../bin/rialto/runtime" } - -# Substrate Dependencies - -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } - -[dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/ethereum-contract-builtin/src/lib.rs b/modules/ethereum-contract-builtin/src/lib.rs deleted file mode 100644 index 4a830f8e0a389..0000000000000 --- a/modules/ethereum-contract-builtin/src/lib.rs +++ /dev/null @@ -1,372 +0,0 @@ -// 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 . - -use codec::{Decode, Encode}; -use ethereum_types::U256; -use finality_grandpa::voter_set::VoterSet; -use rialto_runtime::{Block, BlockNumber, Hash, Header as RuntimeHeader}; -use sp_blockchain::Error as ClientError; -use sp_finality_grandpa::{AuthorityList, ConsensusLog, GRANDPA_ENGINE_ID}; - -/// Builtin errors. -#[derive(Debug)] -pub enum Error { - /// Failed to decode block number. - BlockNumberDecode, - /// Failed to decode Substrate header. - HeaderDecode(codec::Error), - /// Failed to decode the best voters set. - BestSetDecode(codec::Error), - /// The best voters set is invalid. - InvalidBestSet, - /// Failed to decode finality proof. - FinalityProofDecode(codec::Error), - /// Failed to verify justification. - JustificationVerify(Box), -} - -/// Substrate header. -#[derive(Debug, PartialEq)] -pub struct Header { - /// Header hash. - pub hash: Hash, - /// Parent header hash. - pub parent_hash: Hash, - /// Header number. - pub number: BlockNumber, - /// GRANDPA validators change signal. - pub signal: Option, -} - -/// GRANDPA validators set change signal. -#[derive(Debug, PartialEq)] -pub struct ValidatorsSetSignal { - /// Signal delay. - pub delay: BlockNumber, - /// New validators set. - pub validators: Vec, -} - -/// Convert from U256 to BlockNumber. Fails if `U256` value isn't fitting within `BlockNumber` -/// limits (the runtime referenced by this module uses u32 as `BlockNumber`). -pub fn to_substrate_block_number(number: U256) -> Result { - let substrate_block_number = match number == number.low_u32().into() { - true => Ok(number.low_u32()), - false => Err(Error::BlockNumberDecode), - }; - - log::trace!( - target: "bridge-builtin", - "Parsed Substrate block number from {}: {:?}", - number, - substrate_block_number, - ); - - substrate_block_number -} - -/// Convert from BlockNumber to U256. -pub fn from_substrate_block_number(number: BlockNumber) -> Result { - Ok(U256::from(number as u64)) -} - -/// Parse Substrate header. -pub fn parse_substrate_header(raw_header: &[u8]) -> Result { - let substrate_header = RuntimeHeader::decode(&mut &*raw_header) - .map(|header| Header { - hash: header.hash(), - parent_hash: header.parent_hash, - number: header.number, - signal: sp_runtime::traits::Header::digest(&header) - .log(|log| { - log.as_consensus().and_then(|(engine_id, log)| { - if engine_id == GRANDPA_ENGINE_ID { - Some(log) - } else { - None - } - }) - }) - .and_then(|log| ConsensusLog::decode(&mut &*log).ok()) - .and_then(|log| match log { - ConsensusLog::ScheduledChange(scheduled_change) => Some(ValidatorsSetSignal { - delay: scheduled_change.delay, - validators: scheduled_change.next_authorities.encode(), - }), - _ => None, - }), - }) - .map_err(Error::HeaderDecode); - - log::debug!( - target: "bridge-builtin", - "Parsed Substrate header {}: {:?}", - if substrate_header.is_ok() { - format!("<{}-bytes-blob>", raw_header.len()) - } else { - hex::encode(raw_header) - }, - substrate_header, - ); - - substrate_header -} - -/// Verify GRANDPA finality proof. -pub fn verify_substrate_finality_proof( - finality_target_number: BlockNumber, - finality_target_hash: Hash, - best_set_id: u64, - raw_best_set: &[u8], - raw_finality_proof: &[u8], -) -> Result<(), Error> { - let best_set = AuthorityList::decode(&mut &*raw_best_set) - .map_err(Error::BestSetDecode) - .and_then(|authorities| { - VoterSet::new(authorities.into_iter()).ok_or(Error::InvalidBestSet) - }); - - log::debug!( - target: "bridge-builtin", - "Parsed Substrate authorities set {}: {:?}", - if best_set.is_ok() { - format!("<{}-bytes-blob>", raw_best_set.len()) - } else { - hex::encode(raw_best_set) - }, - best_set, - ); - - let best_set = best_set?; - - let verify_result = - sc_finality_grandpa::GrandpaJustification::::decode_and_verify_finalizes( - raw_finality_proof, - (finality_target_hash, finality_target_number), - best_set_id, - &best_set, - ) - .map_err(Box::new) - .map_err(Error::JustificationVerify) - .map(|_| ()); - - log::debug!( - target: "bridge-builtin", - "Verified Substrate finality proof {}: {:?}", - if verify_result.is_ok() { - format!("<{}-bytes-blob>", raw_finality_proof.len()) - } else { - hex::encode(raw_finality_proof) - }, - verify_result, - ); - - verify_result -} - -#[cfg(test)] -mod tests { - use super::*; - use rialto_runtime::DigestItem; - use sp_core::crypto::Public; - use sp_finality_grandpa::{AuthorityId, ScheduledChange}; - use sp_runtime::generic::Digest; - - #[test] - fn to_substrate_block_number_succeeds() { - assert_eq!(to_substrate_block_number(U256::zero()).unwrap(), 0); - assert_eq!( - to_substrate_block_number(U256::from(std::u32::MAX as u64)).unwrap(), - 0xFFFFFFFF - ); - } - - #[test] - fn to_substrate_block_number_fails() { - assert!(matches!( - to_substrate_block_number(U256::from(std::u32::MAX as u64 + 1)), - Err(Error::BlockNumberDecode) - )); - } - - #[test] - fn from_substrate_block_number_succeeds() { - assert_eq!(from_substrate_block_number(0).unwrap(), U256::zero()); - assert_eq!(from_substrate_block_number(std::u32::MAX).unwrap(), U256::from(std::u32::MAX)); - } - - #[test] - fn substrate_header_without_signal_parsed() { - let raw_header = RuntimeHeader { - parent_hash: [0u8; 32].into(), - number: 0, - state_root: "b2fc47904df5e355c6ab476d89fbc0733aeddbe302f0b94ba4eea9283f7e89e7" - .parse() - .unwrap(), - extrinsics_root: "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314" - .parse() - .unwrap(), - digest: Default::default(), - } - .encode(); - assert_eq!( - raw_header, - hex::decode("000000000000000000000000000000000000000000000000000000000000000000b2fc47904df5e355c6ab476d89fbc0733aeddbe302f0b94ba4eea9283f7e89e703170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131400").unwrap(), - ); - - assert_eq!( - parse_substrate_header(&raw_header).unwrap(), - Header { - hash: "afbbeb92bf6ff14f60bdef0aa89f043dd403659ae82665238810ace0d761f6d0" - .parse() - .unwrap(), - parent_hash: Default::default(), - number: 0, - signal: None, - }, - ); - } - - #[test] - fn substrate_header_with_signal_parsed() { - let authorities = vec![ - (AuthorityId::from_slice(&[1; 32]), 101), - (AuthorityId::from_slice(&[3; 32]), 103), - ]; - let mut digest = Digest::default(); - digest.push(DigestItem::Consensus( - GRANDPA_ENGINE_ID, - ConsensusLog::ScheduledChange(ScheduledChange { - next_authorities: authorities.clone(), - delay: 8, - }) - .encode(), - )); - - let raw_header = RuntimeHeader { - parent_hash: "c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b" - .parse() - .unwrap(), - number: 8, - state_root: "822d6b412033aa9ac8e1722918eec5f25633529225754b3d4149982f5cacd4aa" - .parse() - .unwrap(), - extrinsics_root: "e7b07c0ce2799416ce7877b9cefc7f596bea5e8813bb2a0abf760414073ca928" - .parse() - .unwrap(), - digest, - } - .encode(); - assert_eq!( - raw_header, - hex::decode("c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b20822d6b412033aa9ac8e1722918eec5f25633529225754b3d4149982f5cacd4aae7b07c0ce2799416ce7877b9cefc7f596bea5e8813bb2a0abf760414073ca928040446524e4b59010108010101010101010101010101010101010101010101010101010101010101010165000000000000000303030303030303030303030303030303030303030303030303030303030303670000000000000008000000").unwrap(), - ); - - assert_eq!( - parse_substrate_header(&raw_header).unwrap(), - Header { - hash: "3dfebb280bd87a4640f89d7f2adecd62b88148747bff5b63af6e1634ee37a56e" - .parse() - .unwrap(), - parent_hash: "c0ac300d4005141ea690f3df593e049739c227316eb7f05052f3ee077388b68b" - .parse() - .unwrap(), - number: 8, - signal: Some(ValidatorsSetSignal { delay: 8, validators: authorities.encode() }), - }, - ); - } - - /// Number of the example block with justification. - const EXAMPLE_JUSTIFIED_BLOCK_NUMBER: u32 = 8; - /// Hash of the example block with justification. - const EXAMPLE_JUSTIFIED_BLOCK_HASH: &str = - "a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f343775"; - /// Id of authorities set that have generated example justification. Could be computed by - /// tracking every set change in canonized headers. - const EXAMPLE_AUTHORITIES_SET_ID: u64 = 0; - /// Encoded authorities set that has generated example justification. Could be fetched from - /// `ScheduledChange` digest of the block that has scheduled this set OR by calling - /// `GrandpaApi::grandpa_authorities()` at appropriate block. - const EXAMPLE_AUTHORITIES_SET: &str = "1488dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f01000000000000005e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d901000000000000001dfe3e22cc0d45c70779c1095f7489a8ef3cf52d62fbd8c2fa38c9f1723502b50100000000000000"; - /// Example justification. Could be fetched by calling 'chain_getBlock' RPC. - const EXAMPLE_JUSTIFICATION: &str = "2600000000000000a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000010a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000d66b4ceb57ef8bcbc955071b597c8c5d2adcfdbb009c73f8438d342670fdeca9ac60686cbd58105b10f51d0a64a8e73b2e5829b2eab3248a008c472852130b00439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234fa2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000f5730c14d3cd22b7661e2f5fcb3139dd5fef37f946314a441d01b40ce1200ef70d810525f23fd278b588cd67473c200bda83c338c407b479386aa83798e5970b5e639b43e0052c47447dac87d6fd2b6ec50bdd4d0f614e4299c665249bbd09d9a2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f34377508000000c78d6ec463f476461a695b4791d30e7626d16fdf72d7c252c2cad387495a97e8c2827ed4d5af853d6e05d31cb6fb7438c9481a7e9c6990d60a9bfaf6a6e1930988dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eea2f45892db86b2ad133ce57d81b7e4375bb7035ce9883e6b68c358164f3437750800000052b4fc52d430286b3e2d650aa6e01b6ff4fae8b968893a62be789209eb97ee6e23780d3f5af7042d85bb48f1b202890b22724dfebce138826f66a5e00324320fd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae6900"; - - #[test] - fn substrate_header_parse_fails() { - assert!(matches!(parse_substrate_header(&[]), Err(_))); - } - - #[test] - fn verify_substrate_finality_proof_succeeds() { - verify_substrate_finality_proof( - EXAMPLE_JUSTIFIED_BLOCK_NUMBER, - EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), - EXAMPLE_AUTHORITIES_SET_ID, - &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), - &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), - ) - .unwrap(); - } - - #[test] - fn verify_substrate_finality_proof_fails_when_wrong_block_is_finalized() { - verify_substrate_finality_proof( - 4, - Default::default(), - EXAMPLE_AUTHORITIES_SET_ID, - &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), - &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), - ) - .unwrap_err(); - } - - #[test] - fn verify_substrate_finality_proof_fails_when_wrong_set_is_provided() { - verify_substrate_finality_proof( - EXAMPLE_JUSTIFIED_BLOCK_NUMBER, - EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), - EXAMPLE_AUTHORITIES_SET_ID, - &hex::decode("deadbeef").unwrap(), - &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), - ) - .unwrap_err(); - } - - #[test] - fn verify_substrate_finality_proof_fails_when_wrong_set_id_is_provided() { - verify_substrate_finality_proof( - EXAMPLE_JUSTIFIED_BLOCK_NUMBER, - EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), - 42, - &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), - &hex::decode(EXAMPLE_JUSTIFICATION).unwrap(), - ) - .unwrap_err(); - } - - #[test] - fn verify_substrate_finality_proof_fails_when_wrong_proof_is_provided() { - verify_substrate_finality_proof( - EXAMPLE_JUSTIFIED_BLOCK_NUMBER, - EXAMPLE_JUSTIFIED_BLOCK_HASH.parse().unwrap(), - 0, - &hex::decode(EXAMPLE_AUTHORITIES_SET).unwrap(), - &hex::decode("deadbeef").unwrap(), - ) - .unwrap_err(); - } -} diff --git a/modules/ethereum/Cargo.toml b/modules/ethereum/Cargo.toml deleted file mode 100644 index baa9336118079..0000000000000 --- a/modules/ethereum/Cargo.toml +++ /dev/null @@ -1,51 +0,0 @@ -[package] -name = "pallet-bridge-eth-poa" -description = "A Substrate Runtime module that is able to verify PoA headers and their finality." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"], optional = true } -log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } - -# Bridge dependencies - -bp-eth-poa = { path = "../../primitives/ethereum-poa", default-features = false } - -# Substrate Dependencies - -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[dev-dependencies] -libsecp256k1 = { version = "0.7", features = ["hmac"] } -hex-literal = "0.3" - -[features] -default = ["std"] -std = [ - "bp-eth-poa/std", - "codec/std", - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "serde", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] -runtime-benchmarks = [ - "frame-benchmarking", - "libsecp256k1", -] diff --git a/modules/ethereum/src/benchmarking.rs b/modules/ethereum/src/benchmarking.rs deleted file mode 100644 index 511cbcac1ade9..0000000000000 --- a/modules/ethereum/src/benchmarking.rs +++ /dev/null @@ -1,270 +0,0 @@ -// 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 . - -use super::*; - -use crate::test_utils::{ - build_custom_header, build_genesis_header, insert_header, validator_utils::*, - validators_change_receipt, HeaderBuilder, -}; - -use bp_eth_poa::{compute_merkle_root, U256}; -use frame_benchmarking::benchmarks_instance_pallet; -use frame_system::RawOrigin; - -benchmarks_instance_pallet! { - // Benchmark `import_unsigned_header` extrinsic with the best possible conditions: - // * Parent header is finalized. - // * New header doesn't require receipts. - // * Nothing is finalized by new header. - // * Nothing is pruned by new header. - import_unsigned_header_best_case { - let n in 1..1000; - - let num_validators = 2; - let initial_header = initialize_bench::(num_validators); - - // prepare header to be inserted - let header = build_custom_header( - &validator(1), - &initial_header, - |mut header| { - header.gas_limit = header.gas_limit + U256::from(n); - header - }, - ); - }: import_unsigned_header(RawOrigin::None, Box::new(header), None) - verify { - let storage = BridgeStorage::::new(); - assert_eq!(storage.best_block().0.number, 1); - assert_eq!(storage.finalized_block().number, 0); - } - - // Our goal with this bench is to try and see the effect that finalizing difference ranges of - // blocks has on our import time. As such we need to make sure that we keep the number of - // validators fixed while changing the number blocks finalized (the complexity parameter) by - // importing the last header. - // - // One important thing to keep in mind is that the runtime provides a finality cache in order to - // reduce the overhead of header finalization. However, this is only triggered every 16 blocks. - import_unsigned_finality { - // Our complexity parameter, n, will represent the number of blocks imported before - // finalization. - let n in 1..7; - - let mut storage = BridgeStorage::::new(); - let num_validators: u32 = 2; - let initial_header = initialize_bench::(num_validators as usize); - - // Since we only have two validators we need to make sure the number of blocks is even to - // make sure the right validator signs the final block - let num_blocks = 2 * n; - let mut headers = Vec::new(); - let mut parent = initial_header.clone(); - - // Import a bunch of headers without any verification, will ensure that they're not - // finalized prematurely - for i in 1..=num_blocks { - let header = HeaderBuilder::with_parent(&parent).sign_by(&validator(0)); - let id = header.compute_id(); - insert_header(&mut storage, header.clone()); - headers.push(header.clone()); - parent = header; - } - - let last_header = headers.last().unwrap().clone(); - let last_authority = validator(1); - - // Need to make sure that the header we're going to import hasn't been inserted - // into storage already - let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); - }: import_unsigned_header(RawOrigin::None, Box::new(header), None) - verify { - let storage = BridgeStorage::::new(); - assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); - assert_eq!(storage.finalized_block().number, num_blocks as u64); - } - - // Basically the exact same as `import_unsigned_finality` but with a different range for the - // complexity parameter. In this bench we use a larger range of blocks to see how performance - // changes when the finality cache kicks in (>16 blocks). - import_unsigned_finality_with_cache { - // Our complexity parameter, n, will represent the number of blocks imported before - // finalization. - let n in 7..100; - - let mut storage = BridgeStorage::::new(); - let num_validators: u32 = 2; - let initial_header = initialize_bench::(num_validators as usize); - - // Since we only have two validators we need to make sure the number of blocks is even to - // make sure the right validator signs the final block - let num_blocks = 2 * n; - let mut headers = Vec::new(); - let mut parent = initial_header.clone(); - - // Import a bunch of headers without any verification, will ensure that they're not - // finalized prematurely - for i in 1..=num_blocks { - let header = HeaderBuilder::with_parent(&parent).sign_by(&validator(0)); - let id = header.compute_id(); - insert_header(&mut storage, header.clone()); - headers.push(header.clone()); - parent = header; - } - - let last_header = headers.last().unwrap().clone(); - let last_authority = validator(1); - - // Need to make sure that the header we're going to import hasn't been inserted - // into storage already - let header = HeaderBuilder::with_parent(&last_header).sign_by(&last_authority); - }: import_unsigned_header(RawOrigin::None, Box::new(header), None) - verify { - let storage = BridgeStorage::::new(); - assert_eq!(storage.best_block().0.number, (num_blocks + 1) as u64); - assert_eq!(storage.finalized_block().number, num_blocks as u64); - } - - // A block import may trigger a pruning event, which adds extra work to the import progress. - // In this bench we trigger a pruning event in order to see how much extra time is spent by the - // runtime dealing with it. In the Ethereum Pallet, we're limited pruning to eight blocks in a - // single import, as dictated by MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT. - import_unsigned_pruning { - let n in 1..MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT as u32; - - let mut storage = BridgeStorage::::new(); - - let num_validators = 3; - let initial_header = initialize_bench::(num_validators as usize); - let validators = validators(num_validators); - - // Want to prune eligible blocks between [0, n) - BlocksToPrune::::put(PruningRange { - oldest_unpruned_block: 0, - oldest_block_to_keep: n as u64, - }); - - let mut parent = initial_header; - for i in 1..=n { - let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators); - let id = header.compute_id(); - insert_header(&mut storage, header.clone()); - parent = header; - } - - let header = HeaderBuilder::with_parent(&parent).sign_by_set(&validators); - }: import_unsigned_header(RawOrigin::None, Box::new(header), None) - verify { - let storage = BridgeStorage::::new(); - let max_pruned: u64 = (n - 1) as _; - assert_eq!(storage.best_block().0.number, (n + 1) as u64); - assert!(HeadersByNumber::::get(&0).is_none()); - assert!(HeadersByNumber::::get(&max_pruned).is_none()); - } - - // The goal of this bench is to import a block which contains a transaction receipt. The receipt - // will contain a validator set change. Verifying the receipt root is an expensive operation to - // do, which is why we're interested in benchmarking it. - import_unsigned_with_receipts { - let n in 1..100; - - let mut storage = BridgeStorage::::new(); - - let num_validators = 1; - let initial_header = initialize_bench::(num_validators as usize); - - let mut receipts = vec![]; - for i in 1..=n { - let receipt = validators_change_receipt(Default::default()); - receipts.push(receipt) - } - let encoded_receipts = receipts.iter().map(|r| r.rlp()); - - // We need this extra header since this is what signals a validator set transition. This - // will ensure that the next header is within the "Contract" window - let header1 = HeaderBuilder::with_parent(&initial_header).sign_by(&validator(0)); - insert_header(&mut storage, header1.clone()); - - let header = build_custom_header( - &validator(0), - &header1, - |mut header| { - // Logs Bloom signals a change in validator set - header.log_bloom = (&[0xff; 256]).into(); - header.receipts_root = compute_merkle_root(encoded_receipts); - header - }, - ); - }: import_unsigned_header(RawOrigin::None, Box::new(header), Some(receipts)) - verify { - let storage = BridgeStorage::::new(); - assert_eq!(storage.best_block().0.number, 2); - } -} - -fn initialize_bench, I: 'static>(num_validators: usize) -> AuraHeader { - // Initialize storage with some initial header - let initial_header = build_genesis_header(&validator(0)); - let initial_difficulty = initial_header.difficulty; - let initial_validators = validators_addresses(num_validators as usize); - - initialize_storage::(&initial_header, initial_difficulty, &initial_validators); - - initial_header -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::{run_test, TestRuntime}; - use frame_support::assert_ok; - - #[test] - fn insert_unsigned_header_best_case() { - run_test(1, |_| { - assert_ok!(test_benchmark_import_unsigned_header_best_case::()); - }); - } - - #[test] - fn insert_unsigned_header_finality() { - run_test(1, |_| { - assert_ok!(test_benchmark_import_unsigned_finality::()); - }); - } - - #[test] - fn insert_unsigned_header_finality_with_cache() { - run_test(1, |_| { - assert_ok!(test_benchmark_import_unsigned_finality_with_cache::()); - }); - } - - #[test] - fn insert_unsigned_header_pruning() { - run_test(1, |_| { - assert_ok!(test_benchmark_import_unsigned_pruning::()); - }); - } - - #[test] - fn insert_unsigned_header_receipts() { - run_test(1, |_| { - assert_ok!(test_benchmark_import_unsigned_with_receipts::()); - }); - } -} diff --git a/modules/ethereum/src/error.rs b/modules/ethereum/src/error.rs deleted file mode 100644 index 6fd376b01715f..0000000000000 --- a/modules/ethereum/src/error.rs +++ /dev/null @@ -1,102 +0,0 @@ -// 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 . - -use sp_runtime::RuntimeDebug; - -/// Header import error. -#[derive(Clone, Copy, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq))] -pub enum Error { - /// The header is beyond last finalized and can not be imported. - AncientHeader = 0, - /// The header is already imported. - KnownHeader = 1, - /// Seal has an incorrect format. - InvalidSealArity = 2, - /// Block number isn't sensible. - RidiculousNumber = 3, - /// Block has too much gas used. - TooMuchGasUsed = 4, - /// Gas limit header field is invalid. - InvalidGasLimit = 5, - /// Extra data is of an invalid length. - ExtraDataOutOfBounds = 6, - /// Timestamp header overflowed. - TimestampOverflow = 7, - /// The parent header is missing from the blockchain. - MissingParentBlock = 8, - /// The header step is missing from the header. - MissingStep = 9, - /// The header signature is missing from the header. - MissingSignature = 10, - /// Empty steps are missing from the header. - MissingEmptySteps = 11, - /// The same author issued different votes at the same step. - DoubleVote = 12, - /// Validation proof insufficient. - InsufficientProof = 13, - /// Difficulty header field is invalid. - InvalidDifficulty = 14, - /// The received block is from an incorrect proposer. - NotValidator = 15, - /// Missing transaction receipts for the operation. - MissingTransactionsReceipts = 16, - /// Redundant transaction receipts are provided. - RedundantTransactionsReceipts = 17, - /// Provided transactions receipts are not matching the header. - TransactionsReceiptsMismatch = 18, - /// Can't accept unsigned header from the far future. - UnsignedTooFarInTheFuture = 19, - /// Trying to finalize sibling of finalized block. - TryingToFinalizeSibling = 20, - /// Header timestamp is ahead of on-chain timestamp - HeaderTimestampIsAhead = 21, -} - -impl Error { - pub fn msg(&self) -> &'static str { - match *self { - Error::AncientHeader => "Header is beyound last finalized and can not be imported", - Error::KnownHeader => "Header is already imported", - Error::InvalidSealArity => "Header has an incorrect seal", - Error::RidiculousNumber => "Header has too large number", - Error::TooMuchGasUsed => "Header has too much gas used", - Error::InvalidGasLimit => "Header has invalid gas limit", - Error::ExtraDataOutOfBounds => "Header has too large extra data", - Error::TimestampOverflow => "Header has too large timestamp", - Error::MissingParentBlock => "Header has unknown parent hash", - Error::MissingStep => "Header is missing step seal", - Error::MissingSignature => "Header is missing signature seal", - Error::MissingEmptySteps => "Header is missing empty steps seal", - Error::DoubleVote => "Header has invalid step in seal", - Error::InsufficientProof => "Header has insufficient proof", - Error::InvalidDifficulty => "Header has invalid difficulty", - Error::NotValidator => "Header is sealed by unexpected validator", - Error::MissingTransactionsReceipts => - "The import operation requires transactions receipts", - Error::RedundantTransactionsReceipts => "Redundant transactions receipts are provided", - Error::TransactionsReceiptsMismatch => "Invalid transactions receipts provided", - Error::UnsignedTooFarInTheFuture => "The unsigned header is too far in future", - Error::TryingToFinalizeSibling => "Trying to finalize sibling of finalized block", - Error::HeaderTimestampIsAhead => "Header timestamp is ahead of on-chain timestamp", - } - } - - /// Return unique error code. - pub fn code(&self) -> u8 { - *self as u8 - } -} diff --git a/modules/ethereum/src/finality.rs b/modules/ethereum/src/finality.rs deleted file mode 100644 index fe8841fcc044f..0000000000000 --- a/modules/ethereum/src/finality.rs +++ /dev/null @@ -1,557 +0,0 @@ -// 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 . - -use crate::{error::Error, Storage}; -use bp_eth_poa::{public_to_address, Address, AuraHeader, HeaderId, SealedEmptyStep, H256}; -use codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_io::crypto::secp256k1_ecdsa_recover; -use sp_runtime::RuntimeDebug; -use sp_std::{ - collections::{ - btree_map::{BTreeMap, Entry}, - btree_set::BTreeSet, - vec_deque::VecDeque, - }, - prelude::*, -}; - -/// Cached finality votes for given block. -#[derive(RuntimeDebug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct CachedFinalityVotes { - /// True if we have stopped at best finalized block' sibling. This means - /// that we are trying to finalize block from fork that has forked before - /// best finalized. - pub stopped_at_finalized_sibling: bool, - /// Header ancestors that were read while we have been searching for - /// cached votes entry. The newest header has index 0. - pub unaccounted_ancestry: VecDeque<(HeaderId, Option, AuraHeader)>, - /// Cached finality votes, if they have been found. The associated - /// header is not included into `unaccounted_ancestry`. - pub votes: Option>, -} - -/// Finality effects. -#[derive(RuntimeDebug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct FinalityEffects { - /// Finalized headers. - pub finalized_headers: Vec<(HeaderId, Option)>, - /// Finality votes used in computation. - pub votes: FinalityVotes, -} - -/// Finality votes for given block. -#[derive(RuntimeDebug, Decode, Encode, TypeInfo)] -#[cfg_attr(test, derive(Clone, PartialEq))] -pub struct FinalityVotes { - /// Number of votes per each validator. - pub votes: BTreeMap, - /// Ancestry blocks with the oldest ancestors at the beginning and newest at the - /// end of the queue. - pub ancestry: VecDeque>, -} - -/// Information about block ancestor that is used in computations. -#[derive(RuntimeDebug, Decode, Encode, TypeInfo)] -#[cfg_attr(test, derive(Clone, Default, PartialEq))] -pub struct FinalityAncestor { - /// Bock id. - pub id: HeaderId, - /// Block submitter. - pub submitter: Option, - /// Validators that have signed this block and empty steps on top - /// of this block. - pub signers: BTreeSet
, -} - -/// Tries to finalize blocks when given block is imported. -/// -/// Returns numbers and hashes of finalized blocks in ascending order. -pub fn finalize_blocks( - storage: &S, - best_finalized: HeaderId, - header_validators: (HeaderId, &[Address]), - id: HeaderId, - submitter: Option<&S::Submitter>, - header: &AuraHeader, - two_thirds_majority_transition: u64, -) -> Result, Error> { - // compute count of voters for every unfinalized block in ancestry - let validators = header_validators.1.iter().collect(); - let votes = prepare_votes( - header - .parent_id() - .map(|parent_id| { - storage.cached_finality_votes(&parent_id, &best_finalized, |hash| { - *hash == header_validators.0.hash || *hash == best_finalized.hash - }) - }) - .unwrap_or_default(), - best_finalized, - &validators, - id, - header, - submitter.cloned(), - )?; - - // now let's iterate in reverse order && find just finalized blocks - let mut finalized_headers = Vec::new(); - let mut current_votes = votes.votes.clone(); - for ancestor in &votes.ancestry { - if !is_finalized( - &validators, - ¤t_votes, - ancestor.id.number >= two_thirds_majority_transition, - ) { - break - } - - remove_signers_votes(&ancestor.signers, &mut current_votes); - finalized_headers.push((ancestor.id, ancestor.submitter.clone())); - } - - Ok(FinalityEffects { finalized_headers, votes }) -} - -/// Returns true if there are enough votes to treat this header as finalized. -fn is_finalized( - validators: &BTreeSet<&Address>, - votes: &BTreeMap, - requires_two_thirds_majority: bool, -) -> bool { - (!requires_two_thirds_majority && votes.len() * 2 > validators.len()) || - (requires_two_thirds_majority && votes.len() * 3 > validators.len() * 2) -} - -/// Prepare 'votes' of header and its ancestors' signers. -pub(crate) fn prepare_votes( - mut cached_votes: CachedFinalityVotes, - best_finalized: HeaderId, - validators: &BTreeSet<&Address>, - id: HeaderId, - header: &AuraHeader, - submitter: Option, -) -> Result, Error> { - // if we have reached finalized block sibling, then we're trying - // to switch finalized blocks - if cached_votes.stopped_at_finalized_sibling { - return Err(Error::TryingToFinalizeSibling) - } - - // this fn can only work with single validators set - if !validators.contains(&header.author) { - return Err(Error::NotValidator) - } - - // now we have votes that were valid when some block B has been inserted - // things may have changed a bit, but we do not need to read anything else - // from the db, because we have ancestry - // so the only thing we need to do is: - // 1) remove votes from blocks that have been finalized after B has been inserted; - // 2) add votes from B descendants - let mut votes = cached_votes.votes.unwrap_or_default(); - - // remove votes from finalized blocks - while let Some(old_ancestor) = votes.ancestry.pop_front() { - if old_ancestor.id.number > best_finalized.number { - votes.ancestry.push_front(old_ancestor); - break - } - - remove_signers_votes(&old_ancestor.signers, &mut votes.votes); - } - - // add votes from new blocks - let mut parent_empty_step_signers = empty_steps_signers(header); - let mut unaccounted_ancestry = VecDeque::new(); - while let Some((ancestor_id, ancestor_submitter, ancestor)) = - cached_votes.unaccounted_ancestry.pop_front() - { - let mut signers = empty_steps_signers(&ancestor); - sp_std::mem::swap(&mut signers, &mut parent_empty_step_signers); - signers.insert(ancestor.author); - - add_signers_votes(validators, &signers, &mut votes.votes)?; - - unaccounted_ancestry.push_front(FinalityAncestor { - id: ancestor_id, - submitter: ancestor_submitter, - signers, - }); - } - votes.ancestry.extend(unaccounted_ancestry); - - // add votes from block itself - let mut header_signers = BTreeSet::new(); - header_signers.insert(header.author); - *votes.votes.entry(header.author).or_insert(0) += 1; - votes - .ancestry - .push_back(FinalityAncestor { id, submitter, signers: header_signers }); - - Ok(votes) -} - -/// Increase count of 'votes' for every passed signer. -/// Fails if at least one of signers is not in the `validators` set. -fn add_signers_votes( - validators: &BTreeSet<&Address>, - signers_to_add: &BTreeSet
, - votes: &mut BTreeMap, -) -> Result<(), Error> { - for signer in signers_to_add { - if !validators.contains(signer) { - return Err(Error::NotValidator) - } - - *votes.entry(*signer).or_insert(0) += 1; - } - - Ok(()) -} - -/// Decrease 'votes' count for every passed signer. -fn remove_signers_votes(signers_to_remove: &BTreeSet
, votes: &mut BTreeMap) { - for signer in signers_to_remove { - match votes.entry(*signer) { - Entry::Occupied(mut entry) => - if *entry.get() <= 1 { - entry.remove(); - } else { - *entry.get_mut() -= 1; - }, - Entry::Vacant(_) => unreachable!("we only remove signers that have been added; qed"), - } - } -} - -/// Returns unique set of empty steps signers. -fn empty_steps_signers(header: &AuraHeader) -> BTreeSet
{ - header - .empty_steps() - .into_iter() - .flatten() - .filter_map(|step| empty_step_signer(&step, &header.parent_hash)) - .collect::>() -} - -/// Returns author of empty step signature. -fn empty_step_signer(empty_step: &SealedEmptyStep, parent_hash: &H256) -> Option
{ - let message = empty_step.message(parent_hash); - secp256k1_ecdsa_recover(empty_step.signature.as_fixed_bytes(), message.as_fixed_bytes()) - .ok() - .map(|public| public_to_address(&public)) -} - -impl Default for CachedFinalityVotes { - fn default() -> Self { - CachedFinalityVotes { - stopped_at_finalized_sibling: false, - unaccounted_ancestry: VecDeque::new(), - votes: None, - } - } -} - -impl Default for FinalityVotes { - fn default() -> Self { - FinalityVotes { votes: BTreeMap::new(), ancestry: VecDeque::new() } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::{ - insert_header, run_test, validator, validators_addresses, HeaderBuilder, TestRuntime, - }, - BridgeStorage, FinalityCache, HeaderToImport, - }; - - const TOTAL_VALIDATORS: usize = 5; - - #[test] - fn verifies_header_author() { - run_test(TOTAL_VALIDATORS, |_| { - assert_eq!( - finalize_blocks( - &BridgeStorage::::new(), - Default::default(), - (Default::default(), &[]), - Default::default(), - None, - &AuraHeader::default(), - 0, - ), - Err(Error::NotValidator), - ); - }); - } - - #[test] - fn finalize_blocks_works() { - run_test(TOTAL_VALIDATORS, |ctx| { - // let's say we have 5 validators (we need 'votes' from 3 validators to achieve - // finality) - let mut storage = BridgeStorage::::new(); - - // when header#1 is inserted, nothing is finalized (1 vote) - let header1 = HeaderBuilder::with_parent(&ctx.genesis).sign_by(&validator(0)); - let id1 = header1.compute_id(); - let mut header_to_import = HeaderToImport { - context: storage.import_context(None, &header1.parent_hash).unwrap(), - is_best: true, - id: id1, - header: header1, - total_difficulty: 0.into(), - enacted_change: None, - scheduled_change: None, - finality_votes: Default::default(), - }; - assert_eq!( - finalize_blocks( - &storage, - ctx.genesis.compute_id(), - (Default::default(), &ctx.addresses), - id1, - None, - &header_to_import.header, - u64::max_value(), - ) - .map(|eff| eff.finalized_headers), - Ok(Vec::new()), - ); - storage.insert_header(header_to_import.clone()); - - // when header#2 is inserted, nothing is finalized (2 votes) - header_to_import.header = - HeaderBuilder::with_parent_hash(id1.hash).sign_by(&validator(1)); - header_to_import.id = header_to_import.header.compute_id(); - let id2 = header_to_import.header.compute_id(); - assert_eq!( - finalize_blocks( - &storage, - ctx.genesis.compute_id(), - (Default::default(), &ctx.addresses), - id2, - None, - &header_to_import.header, - u64::max_value(), - ) - .map(|eff| eff.finalized_headers), - Ok(Vec::new()), - ); - storage.insert_header(header_to_import.clone()); - - // when header#3 is inserted, header#1 is finalized (3 votes) - header_to_import.header = - HeaderBuilder::with_parent_hash(id2.hash).sign_by(&validator(2)); - header_to_import.id = header_to_import.header.compute_id(); - let id3 = header_to_import.header.compute_id(); - assert_eq!( - finalize_blocks( - &storage, - ctx.genesis.compute_id(), - (Default::default(), &ctx.addresses), - id3, - None, - &header_to_import.header, - u64::max_value(), - ) - .map(|eff| eff.finalized_headers), - Ok(vec![(id1, None)]), - ); - storage.insert_header(header_to_import); - }); - } - - #[test] - fn cached_votes_are_updated_with_ancestry() { - // we're inserting header#5 - // cached votes are from header#3 - // header#4 has finalized header#1 and header#2 - // => when inserting header#5, we need to: - // 1) remove votes from header#1 and header#2 - // 2) add votes from header#4 and header#5 - let validators = validators_addresses(5); - let headers = (1..6) - .map(|number| { - HeaderBuilder::with_number(number).sign_by(&validator(number as usize - 1)) - }) - .collect::>(); - let ancestry = headers - .iter() - .map(|header| FinalityAncestor { - id: header.compute_id(), - signers: vec![header.author].into_iter().collect(), - ..Default::default() - }) - .collect::>(); - let header5 = headers[4].clone(); - assert_eq!( - prepare_votes::<()>( - CachedFinalityVotes { - stopped_at_finalized_sibling: false, - unaccounted_ancestry: - vec![(headers[3].compute_id(), None, headers[3].clone()),] - .into_iter() - .collect(), - votes: Some(FinalityVotes { - votes: vec![(validators[0], 1), (validators[1], 1), (validators[2], 1),] - .into_iter() - .collect(), - ancestry: ancestry[..3].iter().cloned().collect(), - }), - }, - headers[1].compute_id(), - &validators.iter().collect(), - header5.compute_id(), - &header5, - None, - ) - .unwrap(), - FinalityVotes { - votes: vec![(validators[2], 1), (validators[3], 1), (validators[4], 1),] - .into_iter() - .collect(), - ancestry: ancestry[2..].iter().cloned().collect(), - }, - ); - } - - #[test] - fn prepare_votes_respects_finality_cache() { - run_test(TOTAL_VALIDATORS, |ctx| { - // we need signatures of 3 validators to finalize block - let mut storage = BridgeStorage::::new(); - - // headers 1..3 are signed by validator#0 - // headers 4..6 are signed by validator#1 - // headers 7..9 are signed by validator#2 - let mut hashes = Vec::new(); - let mut headers = Vec::new(); - let mut ancestry = Vec::new(); - let mut parent_hash = ctx.genesis.compute_hash(); - for i in 1..10 { - let header = - HeaderBuilder::with_parent_hash(parent_hash).sign_by(&validator((i - 1) / 3)); - let id = header.compute_id(); - insert_header(&mut storage, header.clone()); - hashes.push(id.hash); - ancestry.push(FinalityAncestor { - id: header.compute_id(), - submitter: None, - signers: vec![header.author].into_iter().collect(), - }); - headers.push(header); - parent_hash = id.hash; - } - - // when we're inserting header#7 and last finalized header is 0: - // check that votes at #7 are computed correctly without cache - let expected_votes_at_7 = FinalityVotes { - votes: vec![(ctx.addresses[0], 3), (ctx.addresses[1], 3), (ctx.addresses[2], 1)] - .into_iter() - .collect(), - ancestry: ancestry[..7].iter().cloned().collect(), - }; - let id7 = headers[6].compute_id(); - assert_eq!( - prepare_votes( - storage.cached_finality_votes( - &headers.get(5).unwrap().compute_id(), - &ctx.genesis.compute_id(), - |_| false, - ), - Default::default(), - &ctx.addresses.iter().collect(), - id7, - headers.get(6).unwrap(), - None, - ) - .unwrap(), - expected_votes_at_7, - ); - - // cached votes at #5 - let expected_votes_at_5 = FinalityVotes { - votes: vec![(ctx.addresses[0], 3), (ctx.addresses[1], 2)].into_iter().collect(), - ancestry: ancestry[..5].iter().cloned().collect(), - }; - FinalityCache::::insert(hashes[4], expected_votes_at_5); - - // when we're inserting header#7 and last finalized header is 0: - // check that votes at #7 are computed correctly with cache - assert_eq!( - prepare_votes( - storage.cached_finality_votes( - &headers.get(5).unwrap().compute_id(), - &ctx.genesis.compute_id(), - |_| false, - ), - Default::default(), - &ctx.addresses.iter().collect(), - id7, - headers.get(6).unwrap(), - None, - ) - .unwrap(), - expected_votes_at_7, - ); - - // when we're inserting header#7 and last finalized header is 3: - // check that votes at #7 are computed correctly with cache - let expected_votes_at_7 = FinalityVotes { - votes: vec![(ctx.addresses[1], 3), (ctx.addresses[2], 1)].into_iter().collect(), - ancestry: ancestry[3..7].iter().cloned().collect(), - }; - assert_eq!( - prepare_votes( - storage.cached_finality_votes( - &headers.get(5).unwrap().compute_id(), - &headers.get(2).unwrap().compute_id(), - |hash| *hash == hashes[2], - ), - headers[2].compute_id(), - &ctx.addresses.iter().collect(), - id7, - headers.get(6).unwrap(), - None, - ) - .unwrap(), - expected_votes_at_7, - ); - }); - } - - #[test] - fn prepare_votes_fails_when_finalized_sibling_is_in_ancestry() { - assert_eq!( - prepare_votes::<()>( - CachedFinalityVotes { stopped_at_finalized_sibling: true, ..Default::default() }, - Default::default(), - &validators_addresses(3).iter().collect(), - Default::default(), - &Default::default(), - None, - ), - Err(Error::TryingToFinalizeSibling), - ); - } -} diff --git a/modules/ethereum/src/import.rs b/modules/ethereum/src/import.rs deleted file mode 100644 index 3777432457770..0000000000000 --- a/modules/ethereum/src/import.rs +++ /dev/null @@ -1,600 +0,0 @@ -// 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 . - -use crate::{ - error::Error, - finality::finalize_blocks, - validators::{Validators, ValidatorsConfiguration}, - verification::{is_importable_header, verify_aura_header}, - AuraConfiguration, ChainTime, ChangeToEnact, PruningStrategy, Storage, -}; -use bp_eth_poa::{AuraHeader, HeaderId, Receipt}; -use sp_std::{collections::btree_map::BTreeMap, prelude::*}; - -/// Imports a bunch of headers and updates blocks finality. -/// -/// Transactions receipts must be provided if `header_import_requires_receipts()` -/// has returned true. -/// If successful, returns tuple where first element is the number of useful headers -/// we have imported and the second element is the number of useless headers (duplicate) -/// we have NOT imported. -/// Returns error if fatal error has occurred during import. Some valid headers may be -/// imported in this case. -/// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/415) -#[allow(clippy::too_many_arguments)] -pub fn import_headers( - storage: &mut S, - pruning_strategy: &mut PS, - aura_config: &AuraConfiguration, - validators_config: &ValidatorsConfiguration, - submitter: Option, - headers: Vec<(AuraHeader, Option>)>, - chain_time: &CT, - finalized_headers: &mut BTreeMap, -) -> Result<(u64, u64), Error> { - let mut useful = 0; - let mut useless = 0; - for (header, receipts) in headers { - let import_result = import_header( - storage, - pruning_strategy, - aura_config, - validators_config, - submitter.clone(), - header, - chain_time, - receipts, - ); - - match import_result { - Ok((_, finalized)) => { - for (_, submitter) in finalized { - if let Some(submitter) = submitter { - *finalized_headers.entry(submitter).or_default() += 1; - } - } - useful += 1; - }, - Err(Error::AncientHeader) | Err(Error::KnownHeader) => useless += 1, - Err(error) => return Err(error), - } - } - - Ok((useful, useless)) -} - -/// A vector of finalized headers and their submitters. -pub type FinalizedHeaders = Vec<(HeaderId, Option<::Submitter>)>; - -/// Imports given header and updates blocks finality (if required). -/// -/// Transactions receipts must be provided if `header_import_requires_receipts()` -/// has returned true. -/// -/// Returns imported block id and list of all finalized headers. -/// TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/415) -#[allow(clippy::too_many_arguments)] -pub fn import_header( - storage: &mut S, - pruning_strategy: &mut PS, - aura_config: &AuraConfiguration, - validators_config: &ValidatorsConfiguration, - submitter: Option, - header: AuraHeader, - chain_time: &CT, - receipts: Option>, -) -> Result<(HeaderId, FinalizedHeaders), Error> { - // first check that we are able to import this header at all - let (header_id, finalized_id) = is_importable_header(storage, &header)?; - - // verify header - let import_context = verify_aura_header(storage, aura_config, submitter, &header, chain_time)?; - - // check if block schedules new validators - let validators = Validators::new(validators_config); - let (scheduled_change, enacted_change) = - validators.extract_validators_change(&header, receipts)?; - - // check if block finalizes some other blocks and corresponding scheduled validators - let validators_set = import_context.validators_set(); - let finalized_blocks = finalize_blocks( - storage, - finalized_id, - (validators_set.enact_block, &validators_set.validators), - header_id, - import_context.submitter(), - &header, - aura_config.two_thirds_majority_transition, - )?; - let enacted_change = enacted_change - .map(|validators| ChangeToEnact { signal_block: None, validators }) - .or_else(|| { - validators.finalize_validators_change(storage, &finalized_blocks.finalized_headers) - }); - - // NOTE: we can't return Err() from anywhere below this line - // (because otherwise we'll have inconsistent storage if transaction will fail) - - // and finally insert the block - let (best_id, best_total_difficulty) = storage.best_block(); - let total_difficulty = import_context.total_difficulty() + header.difficulty; - let is_best = total_difficulty > best_total_difficulty; - storage.insert_header(import_context.into_import_header( - is_best, - header_id, - header, - total_difficulty, - enacted_change, - scheduled_change, - finalized_blocks.votes, - )); - - // compute upper border of updated pruning range - let new_best_block_id = if is_best { header_id } else { best_id }; - let new_best_finalized_block_id = finalized_blocks.finalized_headers.last().map(|(id, _)| *id); - let pruning_upper_bound = pruning_strategy.pruning_upper_bound( - new_best_block_id.number, - new_best_finalized_block_id.map(|id| id.number).unwrap_or(finalized_id.number), - ); - - // now mark finalized headers && prune old headers - storage.finalize_and_prune_headers(new_best_finalized_block_id, pruning_upper_bound); - - Ok((header_id, finalized_blocks.finalized_headers)) -} - -/// Returns true if transactions receipts are required to import given header. -pub fn header_import_requires_receipts( - storage: &S, - validators_config: &ValidatorsConfiguration, - header: &AuraHeader, -) -> bool { - is_importable_header(storage, header) - .map(|_| Validators::new(validators_config)) - .map(|validators| validators.maybe_signals_validators_change(header)) - .unwrap_or(false) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::{ - run_test, secret_to_address, test_aura_config, test_validators_config, validator, - validators_addresses, validators_change_receipt, HeaderBuilder, - KeepSomeHeadersBehindBest, TestRuntime, GAS_LIMIT, - }, - validators::ValidatorsSource, - BlocksToPrune, BridgeStorage, Headers, PruningRange, - }; - use libsecp256k1::SecretKey; - - const TOTAL_VALIDATORS: usize = 3; - - #[test] - fn rejects_finalized_block_competitors() { - run_test(TOTAL_VALIDATORS, |_| { - let mut storage = BridgeStorage::::new(); - storage.finalize_and_prune_headers( - Some(HeaderId { number: 100, ..Default::default() }), - 0, - ); - assert_eq!( - import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &test_validators_config(), - None, - Default::default(), - &(), - None, - ), - Err(Error::AncientHeader), - ); - }); - } - - #[test] - fn rejects_known_header() { - run_test(TOTAL_VALIDATORS, |ctx| { - let mut storage = BridgeStorage::::new(); - let header = HeaderBuilder::with_parent(&ctx.genesis).sign_by(&validator(1)); - assert_eq!( - import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &test_validators_config(), - None, - header.clone(), - &(), - None, - ) - .map(|_| ()), - Ok(()), - ); - assert_eq!( - import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &test_validators_config(), - None, - header, - &(), - None, - ) - .map(|_| ()), - Err(Error::KnownHeader), - ); - }); - } - - #[test] - fn import_header_works() { - run_test(TOTAL_VALIDATORS, |ctx| { - let validators_config = ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(ctx.addresses.clone())), - (1, ValidatorsSource::List(validators_addresses(2))), - ]); - let mut storage = BridgeStorage::::new(); - let header = HeaderBuilder::with_parent(&ctx.genesis).sign_by(&validator(1)); - let hash = header.compute_hash(); - assert_eq!( - import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &validators_config, - None, - header, - &(), - None - ) - .map(|_| ()), - Ok(()), - ); - - // check that new validators will be used for next header - let imported_header = Headers::::get(&hash).unwrap(); - assert_eq!( - imported_header.next_validators_set_id, - 1, // new set is enacted from config - ); - }); - } - - #[test] - fn headers_are_pruned_during_import() { - run_test(TOTAL_VALIDATORS, |ctx| { - let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( - [3; 20].into(), - ctx.addresses.clone(), - )); - let validators = vec![validator(0), validator(1), validator(2)]; - let mut storage = BridgeStorage::::new(); - - // header [0..11] are finalizing blocks [0; 9] - // => since we want to keep 10 finalized blocks, we aren't pruning anything - let mut latest_block_id = Default::default(); - for i in 1..11 { - let header = HeaderBuilder::with_parent_number(i - 1).sign_by_set(&validators); - let parent_id = header.parent_id().unwrap(); - - let (rolling_last_block_id, finalized_blocks) = import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &validators_config, - Some(100), - header, - &(), - None, - ) - .unwrap(); - match i { - 2..=10 => { - assert_eq!(finalized_blocks, vec![(parent_id, Some(100))], "At {}", i,) - }, - _ => assert_eq!(finalized_blocks, vec![], "At {}", i), - } - latest_block_id = rolling_last_block_id; - } - assert!(storage.header(&ctx.genesis.compute_hash()).is_some()); - - // header 11 finalizes headers [10] AND schedules change - // => we prune header#0 - let header11 = HeaderBuilder::with_parent_number(10) - .log_bloom((&[0xff; 256]).into()) - .receipts_root( - "ead6c772ba0083bbff497ba0f4efe47c199a2655401096c21ab7450b6c466d97" - .parse() - .unwrap(), - ) - .sign_by_set(&validators); - let parent_id = header11.parent_id().unwrap(); - let (rolling_last_block_id, finalized_blocks) = import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &validators_config, - Some(101), - header11.clone(), - &(), - Some(vec![validators_change_receipt(latest_block_id.hash)]), - ) - .unwrap(); - assert_eq!(finalized_blocks, vec![(parent_id, Some(100))],); - assert!(storage.header(&ctx.genesis.compute_hash()).is_none()); - latest_block_id = rolling_last_block_id; - - // and now let's say validators 1 && 2 went offline - // => in the range 12-25 no blocks are finalized, but we still continue to prune old - // headers until header#11 is met. we can't prune #11, because it schedules change - let mut step = 56u64; - let mut expected_blocks = vec![(header11.compute_id(), Some(101))]; - for i in 12..25 { - let header = HeaderBuilder::with_parent_hash(latest_block_id.hash) - .difficulty(i.into()) - .step(step) - .sign_by_set(&validators); - expected_blocks.push((header.compute_id(), Some(102))); - let (rolling_last_block_id, finalized_blocks) = import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &validators_config, - Some(102), - header, - &(), - None, - ) - .unwrap(); - assert_eq!(finalized_blocks, vec![],); - latest_block_id = rolling_last_block_id; - step += 3; - } - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 11, oldest_block_to_keep: 14 }, - ); - - // now let's insert block signed by validator 1 - // => blocks 11..24 are finalized and blocks 11..14 are pruned - step -= 2; - let header = HeaderBuilder::with_parent_hash(latest_block_id.hash) - .difficulty(25.into()) - .step(step) - .sign_by_set(&validators); - let (_, finalized_blocks) = import_header( - &mut storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &validators_config, - Some(103), - header, - &(), - None, - ) - .unwrap(); - assert_eq!(finalized_blocks, expected_blocks); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 15, oldest_block_to_keep: 15 }, - ); - }); - } - - fn import_custom_block( - storage: &mut S, - validators: &[SecretKey], - header: AuraHeader, - ) -> Result { - let id = header.compute_id(); - import_header( - storage, - &mut KeepSomeHeadersBehindBest::default(), - &test_aura_config(), - &ValidatorsConfiguration::Single(ValidatorsSource::Contract( - [0; 20].into(), - validators.iter().map(secret_to_address).collect(), - )), - None, - header, - &(), - None, - ) - .map(|_| id) - } - - #[test] - fn import_of_non_best_block_may_finalize_blocks() { - run_test(TOTAL_VALIDATORS, |ctx| { - let mut storage = BridgeStorage::::new(); - - // insert headers (H1, validator1), (H2, validator1), (H3, validator1) - // making H3 the best header, without finalizing anything (we need 2 signatures) - let mut expected_best_block = Default::default(); - for i in 1..4 { - let step = 1 + i * TOTAL_VALIDATORS as u64; - expected_best_block = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(i - 1) - .step(step) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - } - let (best_block, best_difficulty) = storage.best_block(); - assert_eq!(best_block, expected_best_block); - assert_eq!(storage.finalized_block(), ctx.genesis.compute_id()); - - // insert headers (H1', validator1), (H2', validator2), finalizing H2, even though H3 - // has better difficulty than H2' (because there are more steps involved) - let mut expected_finalized_block = Default::default(); - let mut parent_hash = ctx.genesis.compute_hash(); - for i in 1..3 { - let step = i; - let id = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_hash(parent_hash) - .step(step) - .gas_limit((GAS_LIMIT + 1).into()) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - parent_hash = id.hash; - if i == 1 { - expected_finalized_block = id; - } - } - let (new_best_block, new_best_difficulty) = storage.best_block(); - assert_eq!(new_best_block, expected_best_block); - assert_eq!(new_best_difficulty, best_difficulty); - assert_eq!(storage.finalized_block(), expected_finalized_block); - }); - } - - #[test] - fn append_to_unfinalized_fork_fails() { - const VALIDATORS: u64 = 5; - run_test(VALIDATORS as usize, |ctx| { - let mut storage = BridgeStorage::::new(); - - // header1, authored by validator[2] is best common block between two competing forks - let header1 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(0).step(2).sign_by_set(&ctx.validators), - ) - .unwrap(); - assert_eq!(storage.best_block().0, header1); - assert_eq!(storage.finalized_block().number, 0); - - // validator[3] has authored header2 (nothing is finalized yet) - let header2 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(1).step(3).sign_by_set(&ctx.validators), - ) - .unwrap(); - assert_eq!(storage.best_block().0, header2); - assert_eq!(storage.finalized_block().number, 0); - - // validator[4] has authored header3 (header1 is finalized) - let header3 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(2).step(4).sign_by_set(&ctx.validators), - ) - .unwrap(); - assert_eq!(storage.best_block().0, header3); - assert_eq!(storage.finalized_block(), header1); - - // validator[4] has authored 4 blocks: header2'...header5' (header1 is still finalized) - let header2_1 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(1) - .gas_limit((GAS_LIMIT + 1).into()) - .step(4) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - let header3_1 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_hash(header2_1.hash) - .step(4 + VALIDATORS) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - let header4_1 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_hash(header3_1.hash) - .step(4 + VALIDATORS * 2) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - let header5_1 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_hash(header4_1.hash) - .step(4 + VALIDATORS * 3) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - assert_eq!(storage.best_block().0, header5_1); - assert_eq!(storage.finalized_block(), header1); - - // when we import header4 { parent = header3 }, authored by validator[0], header2 is - // finalized - let header4 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(3).step(5).sign_by_set(&ctx.validators), - ) - .unwrap(); - assert_eq!(storage.best_block().0, header5_1); - assert_eq!(storage.finalized_block(), header2); - - // when we import header5 { parent = header4 }, authored by validator[1], header3 is - // finalized - let header5 = import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_hash(header4.hash) - .step(6) - .sign_by_set(&ctx.validators), - ) - .unwrap(); - assert_eq!(storage.best_block().0, header5); - assert_eq!(storage.finalized_block(), header3); - - // import of header2'' { parent = header1 } fails, because it has number < - // best_finalized - assert_eq!( - import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(1) - .gas_limit((GAS_LIMIT + 1).into()) - .step(3) - .sign_by_set(&ctx.validators) - ), - Err(Error::AncientHeader), - ); - - // import of header6' should also fail because we're trying to append to fork thas - // has forked before finalized block - assert_eq!( - import_custom_block( - &mut storage, - &ctx.validators, - HeaderBuilder::with_parent_number(5) - .gas_limit((GAS_LIMIT + 1).into()) - .step(5 + VALIDATORS * 4) - .sign_by_set(&ctx.validators), - ), - Err(Error::TryingToFinalizeSibling), - ); - }); - } -} diff --git a/modules/ethereum/src/lib.rs b/modules/ethereum/src/lib.rs deleted file mode 100644 index 4224818ad96c6..0000000000000 --- a/modules/ethereum/src/lib.rs +++ /dev/null @@ -1,1572 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// Runtime-generated enums -#![allow(clippy::large_enum_variant)] - -use crate::finality::{CachedFinalityVotes, FinalityVotes}; -use bp_eth_poa::{ - Address, AuraHeader, HeaderId, RawTransaction, RawTransactionReceipt, Receipt, H256, U256, -}; -use codec::{Decode, Encode}; -use frame_support::traits::Get; -use scale_info::TypeInfo; -use sp_runtime::RuntimeDebug; -use sp_std::{boxed::Box, cmp::Ord, collections::btree_map::BTreeMap, prelude::*}; - -pub use validators::{ValidatorsConfiguration, ValidatorsSource}; - -mod error; -mod finality; -mod import; -mod validators; -mod verification; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -#[cfg(test)] -mod mock; - -#[cfg(any(feature = "runtime-benchmarks", test))] -pub mod test_utils; - -/// Maximal number of blocks we're pruning in single import call. -const MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT: u64 = 8; - -/// Authority round engine configuration parameters. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug)] -pub struct AuraConfiguration { - /// Empty step messages transition block. - pub empty_steps_transition: u64, - /// Transition block to strict empty steps validation. - pub strict_empty_steps_transition: u64, - /// Monotonic step validation transition block. - pub validate_step_transition: u64, - /// Chain score validation transition block. - pub validate_score_transition: u64, - /// First block for which a 2/3 quorum (instead of 1/2) is required. - pub two_thirds_majority_transition: u64, - /// Minimum gas limit. - pub min_gas_limit: U256, - /// Maximum gas limit. - pub max_gas_limit: U256, - /// Maximum size of extra data. - pub maximum_extra_data_size: u64, -} - -/// Transaction pool configuration. -/// -/// This is used to limit number of unsigned headers transactions in -/// the pool. We never use it to verify signed transactions. -pub struct PoolConfiguration { - /// Maximal difference between number of header from unsigned transaction - /// and current best block. This must be selected with caution - the more - /// is the difference, the more (potentially invalid) transactions could be - /// accepted to the pool and mined later (filling blocks with spam). - pub max_future_number_difference: u64, -} - -/// Block header as it is stored in the runtime storage. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct StoredHeader { - /// Submitter of this header. May be `None` if header has been submitted - /// using unsigned transaction. - pub submitter: Option, - /// The block header itself. - pub header: AuraHeader, - /// Total difficulty of the chain. - pub total_difficulty: U256, - /// The ID of set of validators that is expected to produce direct descendants of - /// this block. If header enacts new set, this would be the new set. Otherwise - /// this is the set that has produced the block itself. - /// The hash is the hash of block where validators set has been enacted. - pub next_validators_set_id: u64, - /// Hash of the last block which has **SCHEDULED** validators set change. - /// Note that signal doesn't mean that the set has been (or ever will be) enacted. - /// Note that the header may already be pruned. - pub last_signal_block: Option, -} - -/// Validators set as it is stored in the runtime storage. -#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(test, derive(Clone))] -pub struct ValidatorsSet { - /// Validators of this set. - pub validators: Vec
, - /// Hash of the block where this set has been signaled. None if this is the first set. - pub signal_block: Option, - /// Hash of the block where this set has been enacted. - pub enact_block: HeaderId, -} - -/// Validators set change as it is stored in the runtime storage. -#[derive(Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(test, derive(Clone))] -pub struct AuraScheduledChange { - /// Validators of this set. - pub validators: Vec
, - /// Hash of the block which has emitted previous validators change signal. - pub prev_signal_block: Option, -} - -/// Header that we're importing. -#[derive(RuntimeDebug)] -#[cfg_attr(test, derive(Clone, PartialEq))] -pub struct HeaderToImport { - /// Header import context, - pub context: ImportContext, - /// Should we consider this header as best? - pub is_best: bool, - /// The id of the header. - pub id: HeaderId, - /// The header itself. - pub header: AuraHeader, - /// Total chain difficulty at the header. - pub total_difficulty: U256, - /// New validators set and the hash of block where it has been scheduled (if applicable). - /// Some if set is is enacted by this header. - pub enacted_change: Option, - /// Validators set scheduled change, if happened at the header. - pub scheduled_change: Option>, - /// Finality votes at this header. - pub finality_votes: FinalityVotes, -} - -/// Header that we're importing. -#[derive(RuntimeDebug)] -#[cfg_attr(test, derive(Clone, PartialEq))] -pub struct ChangeToEnact { - /// The id of the header where change has been scheduled. - /// None if it is a first set within current `ValidatorsSource`. - pub signal_block: Option, - /// Validators set that is enacted. - pub validators: Vec
, -} - -/// Blocks range that we want to prune. -#[derive(Encode, Decode, Default, RuntimeDebug, Clone, PartialEq, TypeInfo)] -struct PruningRange { - /// Number of the oldest unpruned block(s). This might be the block that we do not - /// want to prune now (then it is equal to `oldest_block_to_keep`), or block that we - /// were unable to prune for whatever reason (i.e. if it isn't finalized yet and has - /// scheduled validators set change). - pub oldest_unpruned_block: u64, - /// Number of the oldest block(s) that we want to keep. We want to prune blocks in range - /// [ `oldest_unpruned_block`; `oldest_block_to_keep` ). - pub oldest_block_to_keep: u64, -} - -/// Header import context. -/// -/// The import context contains information needed by the header verification -/// pipeline which is not directly part of the header being imported. This includes -/// information relating to its parent, and the current validator set (which -/// provide _context_ for the current header). -#[derive(RuntimeDebug)] -#[cfg_attr(test, derive(Clone, PartialEq))] -pub struct ImportContext { - submitter: Option, - parent_hash: H256, - parent_header: AuraHeader, - parent_total_difficulty: U256, - parent_scheduled_change: Option, - validators_set_id: u64, - validators_set: ValidatorsSet, - last_signal_block: Option, -} - -impl ImportContext { - /// Returns reference to header submitter (if known). - pub fn submitter(&self) -> Option<&Submitter> { - self.submitter.as_ref() - } - - /// Returns reference to parent header. - pub fn parent_header(&self) -> &AuraHeader { - &self.parent_header - } - - /// Returns total chain difficulty at parent block. - pub fn total_difficulty(&self) -> &U256 { - &self.parent_total_difficulty - } - - /// Returns the validator set change if the parent header has signaled a change. - pub fn parent_scheduled_change(&self) -> Option<&AuraScheduledChange> { - self.parent_scheduled_change.as_ref() - } - - /// Returns id of the set of validators. - pub fn validators_set_id(&self) -> u64 { - self.validators_set_id - } - - /// Returns reference to validators set for the block we're going to import. - pub fn validators_set(&self) -> &ValidatorsSet { - &self.validators_set - } - - /// Returns reference to the latest block which has signaled change of validators set. - /// This may point to parent if parent has signaled change. - pub fn last_signal_block(&self) -> Option { - match self.parent_scheduled_change { - Some(_) => Some(HeaderId { number: self.parent_header.number, hash: self.parent_hash }), - None => self.last_signal_block, - } - } - - /// Converts import context into header we're going to import. - #[allow(clippy::too_many_arguments)] - pub fn into_import_header( - self, - is_best: bool, - id: HeaderId, - header: AuraHeader, - total_difficulty: U256, - enacted_change: Option, - scheduled_change: Option>, - finality_votes: FinalityVotes, - ) -> HeaderToImport { - HeaderToImport { - context: self, - is_best, - id, - header, - total_difficulty, - enacted_change, - scheduled_change, - finality_votes, - } - } -} - -/// The storage that is used by the client. -/// -/// Storage modification must be discarded if block import has failed. -pub trait Storage { - /// Header submitter identifier. - type Submitter: Clone + Ord; - - /// Get best known block and total chain difficulty. - fn best_block(&self) -> (HeaderId, U256); - /// Get last finalized block. - fn finalized_block(&self) -> HeaderId; - /// Get imported header by its hash. - /// - /// Returns header and its submitter (if known). - fn header(&self, hash: &H256) -> Option<(AuraHeader, Option)>; - /// Returns latest cached finality votes (if any) for block ancestors, starting - /// from `parent_hash` block and stopping at genesis block, best finalized block - /// or block where `stop_at` returns true. - fn cached_finality_votes( - &self, - parent: &HeaderId, - best_finalized: &HeaderId, - stop_at: impl Fn(&H256) -> bool, - ) -> CachedFinalityVotes; - /// Get header import context by parent header hash. - fn import_context( - &self, - submitter: Option, - parent_hash: &H256, - ) -> Option>; - /// Get new validators that are scheduled by given header and hash of the previous - /// block that has scheduled change. - fn scheduled_change(&self, hash: &H256) -> Option; - /// Insert imported header. - fn insert_header(&mut self, header: HeaderToImport); - /// Finalize given block and schedules pruning of all headers - /// with number < prune_end. - /// - /// The headers in the pruning range could be either finalized, or not. - /// It is the storage duty to ensure that unfinalized headers that have - /// scheduled changes won't be pruned until they or their competitors - /// are finalized. - fn finalize_and_prune_headers(&mut self, finalized: Option, prune_end: u64); -} - -/// Headers pruning strategy. -pub trait PruningStrategy: Default { - /// Return upper bound (exclusive) of headers pruning range. - /// - /// Every value that is returned from this function, must be greater or equal to the - /// previous value. Otherwise it will be ignored (we can't revert pruning). - /// - /// Pallet may prune both finalized and unfinalized blocks. But it can't give any - /// guarantees on when it will happen. Example: if some unfinalized block at height N - /// has scheduled validators set change, then the module won't prune any blocks with - /// number greater than or equal to N even if strategy allows that. - /// - /// If your strategy allows pruning unfinalized blocks, this could lead to switch - /// between finalized forks (only if authorities are misbehaving). But since 50 percent plus one - /// (or 2/3) authorities are able to do whatever they want with the chain, this isn't considered - /// fatal. If your strategy only prunes finalized blocks, we'll never be able to finalize - /// header that isn't descendant of current best finalized block. - fn pruning_upper_bound(&mut self, best_number: u64, best_finalized_number: u64) -> u64; -} - -/// ChainTime represents the runtime on-chain time -pub trait ChainTime: Default { - /// Is a header timestamp ahead of the current on-chain time. - /// - /// Check whether `timestamp` is ahead (i.e greater than) the current on-chain - /// time. If so, return `true`, `false` otherwise. - fn is_timestamp_ahead(&self, timestamp: u64) -> bool; -} - -/// ChainTime implementation for the empty type. -/// -/// This implementation will allow a runtime without the timestamp pallet to use -/// the empty type as its ChainTime associated type. -impl ChainTime for () { - fn is_timestamp_ahead(&self, _: u64) -> bool { - false - } -} - -/// Callbacks for header submission rewards/penalties. -pub trait OnHeadersSubmitted { - /// Called when valid headers have been submitted. - /// - /// The submitter **must not** be rewarded for submitting valid headers, because greedy - /// authority could produce and submit multiple valid headers (without relaying them to other - /// peers) and get rewarded. Instead, the provider could track submitters and stop rewarding if - /// too many headers have been submitted without finalization. - fn on_valid_headers_submitted(submitter: AccountId, useful: u64, useless: u64); - /// Called when invalid headers have been submitted. - fn on_invalid_headers_submitted(submitter: AccountId); - /// Called when earlier submitted headers have been finalized. - /// - /// finalized is the number of headers that submitter has submitted and which - /// have been finalized. - fn on_valid_headers_finalized(submitter: AccountId, finalized: u64); -} - -impl OnHeadersSubmitted for () { - fn on_valid_headers_submitted(_submitter: AccountId, _useful: u64, _useless: u64) {} - fn on_invalid_headers_submitted(_submitter: AccountId) {} - fn on_valid_headers_finalized(_submitter: AccountId, _finalized: u64) {} -} - -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config] - pub trait Config: frame_system::Config { - /// Aura configuration. - type AuraConfiguration: Get; - /// Validators configuration. - type ValidatorsConfiguration: Get; - - /// Interval (in blocks) for for finality votes caching. - /// If None, cache is disabled. - /// - /// Ideally, this should either be None (when we are sure that there won't - /// be any significant finalization delays), or something that is bit larger - /// than average finalization delay. - type FinalityVotesCachingInterval: Get>; - /// Headers pruning strategy. - type PruningStrategy: PruningStrategy; - /// Header timestamp verification against current on-chain time. - type ChainTime: ChainTime; - - /// Handler for headers submission result. - type OnHeadersSubmitted: OnHeadersSubmitted; - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(PhantomData<(T, I)>); - - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet {} - - #[pallet::call] - impl, I: 'static> Pallet { - /// Import single Aura header. Requires transaction to be **UNSIGNED**. - #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_unsigned_header( - origin: OriginFor, - header: Box, - receipts: Option>, - ) -> DispatchResult { - frame_system::ensure_none(origin)?; - - import::import_header( - &mut BridgeStorage::::new(), - &mut T::PruningStrategy::default(), - &T::AuraConfiguration::get(), - &T::ValidatorsConfiguration::get(), - None, - *header, - &T::ChainTime::default(), - receipts, - ) - .map_err(|e| e.msg())?; - - Ok(()) - } - - /// Import Aura chain headers in a single **SIGNED** transaction. - /// Ignores non-fatal errors (like when known header is provided), rewards - /// for successful headers import and penalizes for fatal errors. - /// - /// This should be used with caution - passing too many headers could lead to - /// enormous block production/import time. - #[pallet::weight(0)] // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - pub fn import_signed_headers( - origin: OriginFor, - headers_with_receipts: Vec<(AuraHeader, Option>)>, - ) -> DispatchResult { - let submitter = frame_system::ensure_signed(origin)?; - let mut finalized_headers = BTreeMap::new(); - let import_result = import::import_headers( - &mut BridgeStorage::::new(), - &mut T::PruningStrategy::default(), - &T::AuraConfiguration::get(), - &T::ValidatorsConfiguration::get(), - Some(submitter.clone()), - headers_with_receipts, - &T::ChainTime::default(), - &mut finalized_headers, - ); - - // if we have finalized some headers, we will reward their submitters even - // if current submitter has provided some invalid headers - for (f_submitter, f_count) in finalized_headers { - T::OnHeadersSubmitted::on_valid_headers_finalized(f_submitter, f_count); - } - - // now track/penalize current submitter for providing new headers - match import_result { - Ok((useful, useless)) => - T::OnHeadersSubmitted::on_valid_headers_submitted(submitter, useful, useless), - Err(error) => { - // even though we may have accept some headers, we do not want to reward someone - // who provides invalid headers - T::OnHeadersSubmitted::on_invalid_headers_submitted(submitter); - return Err(error.msg().into()) - }, - } - - Ok(()) - } - } - - #[pallet::validate_unsigned] - impl, I: 'static> ValidateUnsigned for Pallet { - type Call = Call; - - fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { - match *call { - Self::Call::import_unsigned_header { ref header, ref receipts } => { - let accept_result = verification::accept_aura_header_into_pool( - &BridgeStorage::::new(), - &T::AuraConfiguration::get(), - &T::ValidatorsConfiguration::get(), - &pool_configuration(), - header, - &T::ChainTime::default(), - receipts.as_ref(), - ); - - match accept_result { - Ok((requires, provides)) => Ok(ValidTransaction { - priority: TransactionPriority::max_value(), - requires, - provides, - longevity: TransactionLongevity::max_value(), - propagate: true, - }), - // UnsignedTooFarInTheFuture is the special error code used to limit - // number of transactions in the pool - we do not want to ban transaction - // in this case (see verification.rs for details) - Err(error::Error::UnsignedTooFarInTheFuture) => UnknownTransaction::Custom( - error::Error::UnsignedTooFarInTheFuture.code(), - ) - .into(), - Err(error) => InvalidTransaction::Custom(error.code()).into(), - } - }, - _ => InvalidTransaction::Call.into(), - } - } - } - - /// Best known block. - #[pallet::storage] - pub(super) type BestBlock, I: 'static = ()> = - StorageValue<_, (HeaderId, U256), ValueQuery>; - - /// Best finalized block. - #[pallet::storage] - pub(super) type FinalizedBlock, I: 'static = ()> = - StorageValue<_, HeaderId, ValueQuery>; - - /// Range of blocks that we want to prune. - #[pallet::storage] - pub(super) type BlocksToPrune, I: 'static = ()> = - StorageValue<_, PruningRange, ValueQuery>; - - /// Map of imported headers by hash. - #[pallet::storage] - pub(super) type Headers, I: 'static = ()> = - StorageMap<_, Identity, H256, StoredHeader>; - - /// Map of imported header hashes by number. - #[pallet::storage] - pub(super) type HeadersByNumber, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, u64, Vec>; - - /// Map of cached finality data by header hash. - #[pallet::storage] - pub(super) type FinalityCache, I: 'static = ()> = - StorageMap<_, Identity, H256, FinalityVotes>; - - /// The ID of next validator set. - #[pallet::storage] - pub(super) type NextValidatorsSetId, I: 'static = ()> = - StorageValue<_, u64, ValueQuery>; - - /// Map of validators sets by their id. - #[pallet::storage] - pub(super) type ValidatorsSets, I: 'static = ()> = - StorageMap<_, Twox64Concat, u64, ValidatorsSet>; - - /// Validators sets reference count. Each header that is authored by this set increases - /// the reference count. When we prune this header, we decrease the reference count. - /// When it reaches zero, we are free to prune validator set as well. - #[pallet::storage] - pub(super) type ValidatorsSetsRc, I: 'static = ()> = - StorageMap<_, Twox64Concat, u64, u64>; - - /// Map of validators set changes scheduled by given header. - #[pallet::storage] - pub(super) type ScheduledChanges, I: 'static = ()> = - StorageMap<_, Identity, H256, AuraScheduledChange>; - - #[pallet::genesis_config] - #[cfg_attr(feature = "std", derive(Default))] - pub struct GenesisConfig { - /// PoA header to start with. - pub initial_header: AuraHeader, - /// Initial PoA chain difficulty. - pub initial_difficulty: U256, - /// Initial PoA validators set. - pub initial_validators: Vec
, - } - - #[pallet::genesis_build] - impl, I: 'static> GenesisBuild for GenesisConfig { - fn build(&self) { - // the initial blocks should be selected so that: - // 1) it doesn't signal validators changes; - // 2) there are no scheduled validators changes from previous blocks; - // 3) (implied) all direct children of initial block are authored by the same validators - // set. - - assert!(!self.initial_validators.is_empty(), "Initial validators set can't be empty",); - - initialize_storage::( - &self.initial_header, - self.initial_difficulty, - &self.initial_validators, - ); - } - } -} - -impl, I: 'static> Pallet { - /// Returns number and hash of the best block known to the bridge module. - /// The caller should only submit `import_header` transaction that makes - /// (or leads to making) other header the best one. - pub fn best_block() -> HeaderId { - BridgeStorage::::new().best_block().0 - } - - /// Returns number and hash of the best finalized block known to the bridge module. - pub fn finalized_block() -> HeaderId { - BridgeStorage::::new().finalized_block() - } - - /// Returns true if the import of given block requires transactions receipts. - pub fn is_import_requires_receipts(header: AuraHeader) -> bool { - import::header_import_requires_receipts( - &BridgeStorage::::new(), - &T::ValidatorsConfiguration::get(), - &header, - ) - } - - /// Returns true if header is known to the runtime. - pub fn is_known_block(hash: H256) -> bool { - BridgeStorage::::new().header(&hash).is_some() - } - - /// Verify that transaction is included into given finalized block. - pub fn verify_transaction_finalized( - block: H256, - tx_index: u64, - proof: &[(RawTransaction, RawTransactionReceipt)], - ) -> bool { - crate::verify_transaction_finalized(&BridgeStorage::::new(), block, tx_index, proof) - } -} - -/// Runtime bridge storage. -#[derive(Default)] -pub struct BridgeStorage(sp_std::marker::PhantomData<(T, I)>); - -impl, I: 'static> BridgeStorage { - /// Create new BridgeStorage. - pub fn new() -> Self { - BridgeStorage(sp_std::marker::PhantomData::<(T, I)>::default()) - } - - /// Prune old blocks. - fn prune_blocks(&self, mut max_blocks_to_prune: u64, finalized_number: u64, prune_end: u64) { - let pruning_range = BlocksToPrune::::get(); - let mut new_pruning_range = pruning_range.clone(); - - // update oldest block we want to keep - if prune_end > new_pruning_range.oldest_block_to_keep { - new_pruning_range.oldest_block_to_keep = prune_end; - } - - // start pruning blocks - let begin = new_pruning_range.oldest_unpruned_block; - let end = new_pruning_range.oldest_block_to_keep; - log::trace!(target: "runtime", "Pruning blocks in range [{}..{})", begin, end); - for number in begin..end { - // if we can't prune anything => break - if max_blocks_to_prune == 0 { - break - } - - // read hashes of blocks with given number and try to prune these blocks - let blocks_at_number = HeadersByNumber::::take(number); - if let Some(mut blocks_at_number) = blocks_at_number { - self.prune_blocks_by_hashes( - &mut max_blocks_to_prune, - finalized_number, - number, - &mut blocks_at_number, - ); - - // if we haven't pruned all blocks, remember unpruned - if !blocks_at_number.is_empty() { - HeadersByNumber::::insert(number, blocks_at_number); - break - } - } - - // we have pruned all headers at number - new_pruning_range.oldest_unpruned_block = number + 1; - log::trace!( - target: "runtime", - "Oldest unpruned PoA header is now: {}", - new_pruning_range.oldest_unpruned_block, - ); - } - - // update pruning range in storage - if pruning_range != new_pruning_range { - BlocksToPrune::::put(new_pruning_range); - } - } - - /// Prune old blocks with given hashes. - fn prune_blocks_by_hashes( - &self, - max_blocks_to_prune: &mut u64, - finalized_number: u64, - number: u64, - blocks_at_number: &mut Vec, - ) { - // ensure that unfinalized headers we want to prune do not have scheduled changes - if number > finalized_number && - blocks_at_number.iter().any(ScheduledChanges::::contains_key) - { - return - } - - // physically remove headers and (probably) obsolete validators sets - while let Some(hash) = blocks_at_number.pop() { - let header = Headers::::take(&hash); - log::trace!( - target: "runtime", - "Pruning PoA header: ({}, {})", - number, - hash, - ); - - ScheduledChanges::::remove(hash); - FinalityCache::::remove(hash); - if let Some(header) = header { - ValidatorsSetsRc::::mutate(header.next_validators_set_id, |rc| match *rc { - Some(rc) if rc > 1 => Some(rc - 1), - _ => None, - }); - } - - // check if we have already pruned too much headers in this call - *max_blocks_to_prune -= 1; - if *max_blocks_to_prune == 0 { - return - } - } - } -} - -impl, I: 'static> Storage for BridgeStorage { - type Submitter = T::AccountId; - - fn best_block(&self) -> (HeaderId, U256) { - BestBlock::::get() - } - - fn finalized_block(&self) -> HeaderId { - FinalizedBlock::::get() - } - - fn header(&self, hash: &H256) -> Option<(AuraHeader, Option)> { - Headers::::get(hash).map(|header| (header.header, header.submitter)) - } - - fn cached_finality_votes( - &self, - parent: &HeaderId, - best_finalized: &HeaderId, - stop_at: impl Fn(&H256) -> bool, - ) -> CachedFinalityVotes { - let mut votes = CachedFinalityVotes::default(); - let mut current_id = *parent; - loop { - // if we have reached finalized block's sibling => stop with special signal - if current_id.number == best_finalized.number && current_id.hash != best_finalized.hash - { - votes.stopped_at_finalized_sibling = true; - return votes - } - - // if we have reached target header => stop - if stop_at(¤t_id.hash) { - return votes - } - - // if we have found cached votes => stop - let cached_votes = FinalityCache::::get(¤t_id.hash); - if let Some(cached_votes) = cached_votes { - votes.votes = Some(cached_votes); - return votes - } - - // read next parent header id - let header = match Headers::::get(¤t_id.hash) { - Some(header) if header.header.number != 0 => header, - _ => return votes, - }; - let parent_id = header.header.parent_id().expect( - "only returns None at genesis header;\ - the header is proved to have number > 0;\ - qed", - ); - - votes - .unaccounted_ancestry - .push_back((current_id, header.submitter, header.header)); - - current_id = parent_id; - } - } - - fn import_context( - &self, - submitter: Option, - parent_hash: &H256, - ) -> Option> { - Headers::::get(parent_hash).map(|parent_header| { - let validators_set = ValidatorsSets::::get(parent_header.next_validators_set_id) - .expect( - "validators set is only pruned when last ref is pruned; there is a ref; qed", - ); - let parent_scheduled_change = ScheduledChanges::::get(parent_hash); - ImportContext { - submitter, - parent_hash: *parent_hash, - parent_header: parent_header.header, - parent_total_difficulty: parent_header.total_difficulty, - parent_scheduled_change, - validators_set_id: parent_header.next_validators_set_id, - validators_set, - last_signal_block: parent_header.last_signal_block, - } - }) - } - - fn scheduled_change(&self, hash: &H256) -> Option { - ScheduledChanges::::get(hash) - } - - fn insert_header(&mut self, header: HeaderToImport) { - if header.is_best { - BestBlock::::put((header.id, header.total_difficulty)); - } - if let Some(scheduled_change) = header.scheduled_change { - ScheduledChanges::::insert( - &header.id.hash, - AuraScheduledChange { - validators: scheduled_change, - prev_signal_block: header.context.last_signal_block, - }, - ); - } - let next_validators_set_id = match header.enacted_change { - Some(enacted_change) => { - let next_validators_set_id = NextValidatorsSetId::::mutate(|set_id| { - let next_set_id = *set_id; - *set_id += 1; - next_set_id - }); - ValidatorsSets::::insert( - next_validators_set_id, - ValidatorsSet { - validators: enacted_change.validators, - enact_block: header.id, - signal_block: enacted_change.signal_block, - }, - ); - ValidatorsSetsRc::::insert(next_validators_set_id, 1); - next_validators_set_id - }, - None => { - ValidatorsSetsRc::::mutate(header.context.validators_set_id, |rc| { - *rc = Some(rc.map(|rc| rc + 1).unwrap_or(1)); - *rc - }); - header.context.validators_set_id - }, - }; - - let finality_votes_caching_interval = T::FinalityVotesCachingInterval::get(); - if let Some(finality_votes_caching_interval) = finality_votes_caching_interval { - let cache_entry_required = - header.id.number != 0 && header.id.number % finality_votes_caching_interval == 0; - if cache_entry_required { - FinalityCache::::insert(header.id.hash, header.finality_votes); - } - } - - log::trace!( - target: "runtime", - "Inserting PoA header: ({}, {})", - header.header.number, - header.id.hash, - ); - - let last_signal_block = header.context.last_signal_block(); - HeadersByNumber::::append(header.id.number, header.id.hash); - Headers::::insert( - &header.id.hash, - StoredHeader { - submitter: header.context.submitter, - header: header.header, - total_difficulty: header.total_difficulty, - next_validators_set_id, - last_signal_block, - }, - ); - } - - fn finalize_and_prune_headers(&mut self, finalized: Option, prune_end: u64) { - // remember just finalized block - let finalized_number = finalized - .as_ref() - .map(|f| f.number) - .unwrap_or_else(|| FinalizedBlock::::get().number); - if let Some(finalized) = finalized { - log::trace!( - target: "runtime", - "Finalizing PoA header: ({}, {})", - finalized.number, - finalized.hash, - ); - - FinalizedBlock::::put(finalized); - } - - // and now prune headers if we need to - self.prune_blocks(MAX_BLOCKS_TO_PRUNE_IN_SINGLE_IMPORT, finalized_number, prune_end); - } -} - -/// Initialize storage. -#[cfg(any(feature = "std", feature = "runtime-benchmarks"))] -pub(crate) fn initialize_storage, I: 'static>( - initial_header: &AuraHeader, - initial_difficulty: U256, - initial_validators: &[Address], -) { - let initial_hash = initial_header.compute_hash(); - log::trace!( - target: "runtime", - "Initializing bridge with PoA header: ({}, {})", - initial_header.number, - initial_hash, - ); - - let initial_id = HeaderId { number: initial_header.number, hash: initial_hash }; - BestBlock::::put((initial_id, initial_difficulty)); - FinalizedBlock::::put(initial_id); - BlocksToPrune::::put(PruningRange { - oldest_unpruned_block: initial_header.number, - oldest_block_to_keep: initial_header.number, - }); - HeadersByNumber::::insert(initial_header.number, vec![initial_hash]); - Headers::::insert( - initial_hash, - StoredHeader { - submitter: None, - header: initial_header.clone(), - total_difficulty: initial_difficulty, - next_validators_set_id: 0, - last_signal_block: None, - }, - ); - NextValidatorsSetId::::put(1); - ValidatorsSets::::insert( - 0, - ValidatorsSet { - validators: initial_validators.to_vec(), - signal_block: None, - enact_block: initial_id, - }, - ); - ValidatorsSetsRc::::insert(0, 1); -} - -/// Verify that transaction is included into given finalized block. -pub fn verify_transaction_finalized( - storage: &S, - block: H256, - tx_index: u64, - proof: &[(RawTransaction, RawTransactionReceipt)], -) -> bool { - if tx_index >= proof.len() as _ { - log::trace!( - target: "runtime", - "Tx finality check failed: transaction index ({}) is larger than number of transactions ({})", - tx_index, - proof.len(), - ); - - return false - } - - let header = match storage.header(&block) { - Some((header, _)) => header, - None => { - log::trace!( - target: "runtime", - "Tx finality check failed: can't find header in the storage: {}", - block, - ); - - return false - }, - }; - let finalized = storage.finalized_block(); - - // if header is not yet finalized => return - if header.number > finalized.number { - log::trace!( - target: "runtime", - "Tx finality check failed: header {}/{} is not finalized. Best finalized: {}", - header.number, - block, - finalized.number, - ); - - return false - } - - // check if header is actually finalized - let is_finalized = match header.number < finalized.number { - true => ancestry(storage, finalized.hash) - .skip_while(|(_, ancestor)| ancestor.number > header.number) - .any(|(ancestor_hash, _)| ancestor_hash == block), - false => block == finalized.hash, - }; - if !is_finalized { - log::trace!( - target: "runtime", - "Tx finality check failed: header {} is not finalized: no canonical path to best finalized block {}", - block, - finalized.hash, - ); - - return false - } - - // verify that transaction is included in the block - if let Err(computed_root) = header.check_transactions_root(proof.iter().map(|(tx, _)| tx)) { - log::trace!( - target: "runtime", - "Tx finality check failed: transactions root mismatch. Expected: {}, computed: {}", - header.transactions_root, - computed_root, - ); - - return false - } - - // verify that transaction receipt is included in the block - if let Err(computed_root) = header.check_raw_receipts_root(proof.iter().map(|(_, r)| r)) { - log::trace!( - target: "runtime", - "Tx finality check failed: receipts root mismatch. Expected: {}, computed: {}", - header.receipts_root, - computed_root, - ); - - return false - } - - // check that transaction has completed successfully - let is_successful_raw_receipt = Receipt::is_successful_raw_receipt(&proof[tx_index as usize].1); - match is_successful_raw_receipt { - Ok(true) => true, - Ok(false) => { - log::trace!( - target: "runtime", - "Tx finality check failed: receipt shows that transaction has failed", - ); - - false - }, - Err(err) => { - log::trace!( - target: "runtime", - "Tx finality check failed: receipt check has failed: {}", - err, - ); - - false - }, - } -} - -/// Transaction pool configuration. -fn pool_configuration() -> PoolConfiguration { - PoolConfiguration { max_future_number_difference: 10 } -} - -/// Return iterator of given header ancestors. -fn ancestry( - storage: &'_ S, - mut parent_hash: H256, -) -> impl Iterator + '_ { - sp_std::iter::from_fn(move || { - let (header, _) = storage.header(&parent_hash)?; - if header.number == 0 { - return None - } - - let hash = parent_hash; - parent_hash = header.parent_hash; - Some((hash, header)) - }) -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::{ - finality::FinalityAncestor, - mock::{ - genesis, insert_header, run_test, run_test_with_genesis, validators_addresses, - HeaderBuilder, TestRuntime, GAS_LIMIT, - }, - test_utils::validator_utils::*, - }; - use bp_eth_poa::compute_merkle_root; - - const TOTAL_VALIDATORS: usize = 3; - - fn example_tx() -> Vec { - vec![42] - } - - fn example_tx_receipt(success: bool) -> Vec { - Receipt { - // the only thing that we care of: - outcome: bp_eth_poa::TransactionOutcome::StatusCode(if success { 1 } else { 0 }), - gas_used: Default::default(), - log_bloom: Default::default(), - logs: Vec::new(), - } - .rlp() - } - - fn example_header_with_failed_receipt() -> AuraHeader { - HeaderBuilder::with_parent(&example_header()) - .transactions_root(compute_merkle_root(vec![example_tx()].into_iter())) - .receipts_root(compute_merkle_root(vec![example_tx_receipt(false)].into_iter())) - .sign_by(&validator(0)) - } - - fn example_header() -> AuraHeader { - HeaderBuilder::with_parent(&example_header_parent()) - .transactions_root(compute_merkle_root(vec![example_tx()].into_iter())) - .receipts_root(compute_merkle_root(vec![example_tx_receipt(true)].into_iter())) - .sign_by(&validator(0)) - } - - fn example_header_parent() -> AuraHeader { - HeaderBuilder::with_parent(&genesis()) - .transactions_root(compute_merkle_root(vec![example_tx()].into_iter())) - .receipts_root(compute_merkle_root(vec![example_tx_receipt(true)].into_iter())) - .sign_by(&validator(0)) - } - - fn with_headers_to_prune(f: impl Fn(BridgeStorage) -> T) -> T { - run_test(TOTAL_VALIDATORS, |ctx| { - for i in 1..10 { - let mut headers_by_number = Vec::with_capacity(5); - for j in 0..5 { - let header = HeaderBuilder::with_parent_number(i - 1) - .gas_limit((GAS_LIMIT + j).into()) - .sign_by_set(&ctx.validators); - let hash = header.compute_hash(); - headers_by_number.push(hash); - Headers::::insert( - hash, - StoredHeader { - submitter: None, - header, - total_difficulty: 0.into(), - next_validators_set_id: 0, - last_signal_block: None, - }, - ); - - if i == 7 && j == 1 { - ScheduledChanges::::insert( - hash, - AuraScheduledChange { - validators: validators_addresses(5), - prev_signal_block: None, - }, - ); - } - } - HeadersByNumber::::insert(i, headers_by_number); - } - - f(BridgeStorage::new()) - }) - } - - #[test] - fn blocks_are_not_pruned_if_range_is_empty() { - with_headers_to_prune(|storage| { - BlocksToPrune::::put(PruningRange { - oldest_unpruned_block: 5, - oldest_block_to_keep: 5, - }); - - // try to prune blocks [5; 10) - storage.prune_blocks(0xFFFF, 10, 5); - assert_eq!(HeadersByNumber::::get(&5).unwrap().len(), 5); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5 }, - ); - }); - } - - #[test] - fn blocks_to_prune_never_shrinks_from_the_end() { - with_headers_to_prune(|storage| { - BlocksToPrune::::put(PruningRange { - oldest_unpruned_block: 0, - oldest_block_to_keep: 5, - }); - - // try to prune blocks [5; 10) - storage.prune_blocks(0xFFFF, 10, 3); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 5, oldest_block_to_keep: 5 }, - ); - }); - } - - #[test] - fn blocks_are_not_pruned_if_limit_is_zero() { - with_headers_to_prune(|storage| { - // try to prune blocks [0; 10) - storage.prune_blocks(0, 10, 10); - assert!(HeadersByNumber::::get(&0).is_some()); - assert!(HeadersByNumber::::get(&1).is_some()); - assert!(HeadersByNumber::::get(&2).is_some()); - assert!(HeadersByNumber::::get(&3).is_some()); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 0, oldest_block_to_keep: 10 }, - ); - }); - } - - #[test] - fn blocks_are_pruned_if_limit_is_non_zero() { - with_headers_to_prune(|storage| { - // try to prune blocks [0; 10) - storage.prune_blocks(7, 10, 10); - // 1 headers with number = 0 is pruned (1 total) - assert!(HeadersByNumber::::get(&0).is_none()); - // 5 headers with number = 1 are pruned (6 total) - assert!(HeadersByNumber::::get(&1).is_none()); - // 1 header with number = 2 are pruned (7 total) - assert_eq!(HeadersByNumber::::get(&2).unwrap().len(), 4); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 2, oldest_block_to_keep: 10 }, - ); - - // try to prune blocks [2; 10) - storage.prune_blocks(11, 10, 10); - // 4 headers with number = 2 are pruned (4 total) - assert!(HeadersByNumber::::get(&2).is_none()); - // 5 headers with number = 3 are pruned (9 total) - assert!(HeadersByNumber::::get(&3).is_none()); - // 2 headers with number = 4 are pruned (11 total) - assert_eq!(HeadersByNumber::::get(&4).unwrap().len(), 3); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 4, oldest_block_to_keep: 10 }, - ); - }); - } - - #[test] - fn pruning_stops_on_unfainalized_block_with_scheduled_change() { - with_headers_to_prune(|storage| { - // try to prune blocks [0; 10) - // last finalized block is 5 - // and one of blocks#7 has scheduled change - // => we won't prune any block#7 at all - storage.prune_blocks(0xFFFF, 5, 10); - assert!(HeadersByNumber::::get(&0).is_none()); - assert!(HeadersByNumber::::get(&1).is_none()); - assert!(HeadersByNumber::::get(&2).is_none()); - assert!(HeadersByNumber::::get(&3).is_none()); - assert!(HeadersByNumber::::get(&4).is_none()); - assert!(HeadersByNumber::::get(&5).is_none()); - assert!(HeadersByNumber::::get(&6).is_none()); - assert_eq!(HeadersByNumber::::get(&7).unwrap().len(), 5); - assert_eq!( - BlocksToPrune::::get(), - PruningRange { oldest_unpruned_block: 7, oldest_block_to_keep: 10 }, - ); - }); - } - - #[test] - fn finality_votes_are_cached() { - run_test(TOTAL_VALIDATORS, |ctx| { - let mut storage = BridgeStorage::::new(); - let interval = ::FinalityVotesCachingInterval::get().unwrap(); - - // for all headers with number < interval, cache entry is not created - for i in 1..interval { - let header = HeaderBuilder::with_parent_number(i - 1).sign_by_set(&ctx.validators); - let id = header.compute_id(); - insert_header(&mut storage, header); - assert_eq!(FinalityCache::::get(&id.hash), None); - } - - // for header with number = interval, cache entry is created - let header_with_entry = - HeaderBuilder::with_parent_number(interval - 1).sign_by_set(&ctx.validators); - let header_with_entry_hash = header_with_entry.compute_hash(); - insert_header(&mut storage, header_with_entry); - assert!(FinalityCache::::get(&header_with_entry_hash).is_some()); - - // when we later prune this header, cache entry is removed - BlocksToPrune::::put(PruningRange { - oldest_unpruned_block: interval - 1, - oldest_block_to_keep: interval - 1, - }); - storage.finalize_and_prune_headers(None, interval + 1); - assert_eq!(FinalityCache::::get(&header_with_entry_hash), None); - }); - } - - #[test] - fn cached_finality_votes_finds_entry() { - run_test(TOTAL_VALIDATORS, |ctx| { - // insert 5 headers - let mut storage = BridgeStorage::::new(); - let mut headers = Vec::new(); - for i in 1..5 { - let header = HeaderBuilder::with_parent_number(i - 1).sign_by_set(&ctx.validators); - headers.push(header.clone()); - insert_header(&mut storage, header); - } - - // when inserting header#6, entry isn't found - let id5 = headers.last().unwrap().compute_id(); - assert_eq!( - storage.cached_finality_votes(&id5, &genesis().compute_id(), |_| false), - CachedFinalityVotes { - stopped_at_finalized_sibling: false, - unaccounted_ancestry: headers - .iter() - .map(|header| (header.compute_id(), None, header.clone(),)) - .rev() - .collect(), - votes: None, - }, - ); - - // let's now create entry at #3 - let hash3 = headers[2].compute_hash(); - let votes_at_3 = FinalityVotes { - votes: vec![([42; 20].into(), 21)].into_iter().collect(), - ancestry: vec![FinalityAncestor { - id: HeaderId { number: 100, hash: Default::default() }, - ..Default::default() - }] - .into_iter() - .collect(), - }; - FinalityCache::::insert(hash3, votes_at_3.clone()); - - // searching at #6 again => entry is found - assert_eq!( - storage.cached_finality_votes(&id5, &genesis().compute_id(), |_| false), - CachedFinalityVotes { - stopped_at_finalized_sibling: false, - unaccounted_ancestry: headers - .iter() - .skip(3) - .map(|header| (header.compute_id(), None, header.clone(),)) - .rev() - .collect(), - votes: Some(votes_at_3), - }, - ); - }); - } - - #[test] - fn cached_finality_votes_stops_at_finalized_sibling() { - run_test(TOTAL_VALIDATORS, |ctx| { - let mut storage = BridgeStorage::::new(); - - // insert header1 - let header1 = HeaderBuilder::with_parent_number(0).sign_by_set(&ctx.validators); - let header1_id = header1.compute_id(); - insert_header(&mut storage, header1); - - // insert header1' - sibling of header1 - let header1s = HeaderBuilder::with_parent_number(0) - .gas_limit((GAS_LIMIT + 1).into()) - .sign_by_set(&ctx.validators); - let header1s_id = header1s.compute_id(); - insert_header(&mut storage, header1s); - - // header1 is finalized - FinalizedBlock::::put(header1_id); - - // trying to get finality votes when importing header2 -> header1 succeeds - assert!( - !storage - .cached_finality_votes(&header1_id, &genesis().compute_id(), |_| false) - .stopped_at_finalized_sibling - ); - - // trying to get finality votes when importing header2s -> header1s fails - assert!( - storage - .cached_finality_votes(&header1s_id, &header1_id, |_| false) - .stopped_at_finalized_sibling - ); - }); - } - - #[test] - fn verify_transaction_finalized_works_for_best_finalized_header() { - run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - assert!(verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(true))], - )); - }); - } - - #[test] - fn verify_transaction_finalized_works_for_best_finalized_header_ancestor() { - run_test(TOTAL_VALIDATORS, |_| { - let mut storage = BridgeStorage::::new(); - insert_header(&mut storage, example_header_parent()); - insert_header(&mut storage, example_header()); - storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); - assert!(verify_transaction_finalized( - &storage, - example_header_parent().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(true))], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_proof_with_missing_tx() { - run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - assert!(!verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 1, - &[], - ),); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_unknown_header() { - run_test(TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - assert!(!verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 1, - &[], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_unfinalized_header() { - run_test(TOTAL_VALIDATORS, |_| { - let mut storage = BridgeStorage::::new(); - insert_header(&mut storage, example_header_parent()); - insert_header(&mut storage, example_header()); - assert!(!verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(true))], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_finalized_header_sibling() { - run_test(TOTAL_VALIDATORS, |_| { - let mut finalized_header_sibling = example_header(); - finalized_header_sibling.timestamp = 1; - let finalized_header_sibling_hash = finalized_header_sibling.compute_hash(); - - let mut storage = BridgeStorage::::new(); - insert_header(&mut storage, example_header_parent()); - insert_header(&mut storage, example_header()); - insert_header(&mut storage, finalized_header_sibling); - storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); - assert!(!verify_transaction_finalized( - &storage, - finalized_header_sibling_hash, - 0, - &[(example_tx(), example_tx_receipt(true))], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_finalized_header_uncle() { - run_test(TOTAL_VALIDATORS, |_| { - let mut finalized_header_uncle = example_header_parent(); - finalized_header_uncle.timestamp = 1; - let finalized_header_uncle_hash = finalized_header_uncle.compute_hash(); - - let mut storage = BridgeStorage::::new(); - insert_header(&mut storage, example_header_parent()); - insert_header(&mut storage, finalized_header_uncle); - insert_header(&mut storage, example_header()); - storage.finalize_and_prune_headers(Some(example_header().compute_id()), 0); - assert!(!verify_transaction_finalized( - &storage, - finalized_header_uncle_hash, - 0, - &[(example_tx(), example_tx_receipt(true))], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_invalid_transactions_in_proof() { - run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - assert!(!verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[ - (example_tx(), example_tx_receipt(true)), - (example_tx(), example_tx_receipt(true)) - ], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_invalid_receipts_in_proof() { - run_test_with_genesis(example_header(), TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - assert!(!verify_transaction_finalized( - &storage, - example_header().compute_hash(), - 0, - &[(example_tx(), vec![42])], - )); - }); - } - - #[test] - fn verify_transaction_finalized_rejects_failed_transaction() { - run_test_with_genesis(example_header_with_failed_receipt(), TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - assert!(!verify_transaction_finalized( - &storage, - example_header_with_failed_receipt().compute_hash(), - 0, - &[(example_tx(), example_tx_receipt(false))], - )); - }); - } -} diff --git a/modules/ethereum/src/mock.rs b/modules/ethereum/src/mock.rs deleted file mode 100644 index 877f7a9dc11f8..0000000000000 --- a/modules/ethereum/src/mock.rs +++ /dev/null @@ -1,188 +0,0 @@ -// 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 . - -// From construct_runtime macro -#![allow(clippy::from_over_into)] - -pub use crate::test_utils::{ - insert_header, validator_utils::*, validators_change_receipt, HeaderBuilder, GAS_LIMIT, -}; -pub use bp_eth_poa::signatures::secret_to_address; - -use crate::{ - validators::{ValidatorsConfiguration, ValidatorsSource}, - AuraConfiguration, ChainTime, Config, GenesisConfig as CrateGenesisConfig, PruningStrategy, -}; -use bp_eth_poa::{Address, AuraHeader, H256, U256}; -use frame_support::{parameter_types, traits::GenesisBuild, weights::Weight}; -use libsecp256k1::SecretKey; -use sp_runtime::{ - testing::Header as SubstrateHeader, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, -}; - -pub type AccountId = u64; - -type Block = frame_system::mocking::MockBlock; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - -use crate as pallet_ethereum; - -frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Ethereum: pallet_ethereum::{Pallet, Call}, - } -} - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - -impl frame_system::Config for TestRuntime { - type Origin = Origin; - type Index = u64; - type Call = Call; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = SubstrateHeader; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type SS58Prefix = (); - type OnSetCode = (); -} - -parameter_types! { - pub const TestFinalityVotesCachingInterval: Option = Some(16); - pub TestAuraConfiguration: AuraConfiguration = test_aura_config(); - pub TestValidatorsConfiguration: ValidatorsConfiguration = test_validators_config(); -} - -impl Config for TestRuntime { - type AuraConfiguration = TestAuraConfiguration; - type ValidatorsConfiguration = TestValidatorsConfiguration; - type FinalityVotesCachingInterval = TestFinalityVotesCachingInterval; - type PruningStrategy = KeepSomeHeadersBehindBest; - type ChainTime = ConstChainTime; - type OnHeadersSubmitted = (); -} - -/// Test context. -pub struct TestContext { - /// Initial (genesis) header. - pub genesis: AuraHeader, - /// Number of initial validators. - pub total_validators: usize, - /// Secret keys of validators, ordered by validator index. - pub validators: Vec, - /// Addresses of validators, ordered by validator index. - pub addresses: Vec
, -} - -/// Aura configuration that is used in tests by default. -pub fn test_aura_config() -> AuraConfiguration { - AuraConfiguration { - empty_steps_transition: u64::max_value(), - strict_empty_steps_transition: 0, - validate_step_transition: 0x16e360, - validate_score_transition: 0x41a3c4, - two_thirds_majority_transition: u64::max_value(), - min_gas_limit: 0x1388.into(), - max_gas_limit: U256::max_value(), - maximum_extra_data_size: 0x20, - } -} - -/// Validators configuration that is used in tests by default. -pub fn test_validators_config() -> ValidatorsConfiguration { - ValidatorsConfiguration::Single(ValidatorsSource::List(validators_addresses(3))) -} - -/// Genesis header that is used in tests by default. -pub fn genesis() -> AuraHeader { - HeaderBuilder::genesis().sign_by(&validator(0)) -} - -/// Run test with default genesis header. -pub fn run_test(total_validators: usize, test: impl FnOnce(TestContext) -> T) -> T { - run_test_with_genesis(genesis(), total_validators, test) -} - -/// Run test with default genesis header. -pub fn run_test_with_genesis( - genesis: AuraHeader, - total_validators: usize, - test: impl FnOnce(TestContext) -> T, -) -> T { - let validators = validators(total_validators); - let addresses = validators_addresses(total_validators); - sp_io::TestExternalities::from( - GenesisBuild::::build_storage(&CrateGenesisConfig { - initial_header: genesis.clone(), - initial_difficulty: 0.into(), - initial_validators: addresses.clone(), - }) - .unwrap(), - ) - .execute_with(|| test(TestContext { genesis, total_validators, validators, addresses })) -} - -/// Pruning strategy that keeps 10 headers behind best block. -pub struct KeepSomeHeadersBehindBest(pub u64); - -impl Default for KeepSomeHeadersBehindBest { - fn default() -> KeepSomeHeadersBehindBest { - KeepSomeHeadersBehindBest(10) - } -} - -impl PruningStrategy for KeepSomeHeadersBehindBest { - fn pruning_upper_bound(&mut self, best_number: u64, _: u64) -> u64 { - best_number.saturating_sub(self.0) - } -} - -/// Constant chain time -#[derive(Default)] -pub struct ConstChainTime; - -impl ChainTime for ConstChainTime { - fn is_timestamp_ahead(&self, timestamp: u64) -> bool { - let now = i32::max_value() as u64 / 2; - timestamp > now - } -} diff --git a/modules/ethereum/src/test_utils.rs b/modules/ethereum/src/test_utils.rs deleted file mode 100644 index 414445f3aaccb..0000000000000 --- a/modules/ethereum/src/test_utils.rs +++ /dev/null @@ -1,322 +0,0 @@ -// 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 . - -//! Utilities for testing and benchmarking the Ethereum Bridge Pallet. -//! -//! Although the name implies that it is used by tests, it shouldn't be be used _directly_ by tests. -//! Instead these utilities should be used by the Mock runtime, which in turn is used by tests. -//! -//! On the other hand, they may be used directly by the benchmark module. - -// Since this is test code it's fine that not everything is used -#![allow(dead_code)] - -use crate::{ - finality::FinalityVotes, validators::CHANGE_EVENT_HASH, verification::calculate_score, Config, - HeaderToImport, Storage, -}; - -use bp_eth_poa::{ - rlp_encode, - signatures::{secret_to_address, sign, SignHeader}, - Address, AuraHeader, Bloom, Receipt, SealedEmptyStep, H256, U256, -}; -use libsecp256k1::SecretKey; -use sp_std::prelude::*; - -/// Gas limit valid in test environment. -pub const GAS_LIMIT: u64 = 0x2000; - -/// Test header builder. -pub struct HeaderBuilder { - header: AuraHeader, - parent_header: AuraHeader, -} - -impl HeaderBuilder { - /// Creates default genesis header. - pub fn genesis() -> Self { - let current_step = 0u64; - Self { - header: AuraHeader { - gas_limit: GAS_LIMIT.into(), - seal: vec![bp_eth_poa::rlp_encode(¤t_step).to_vec(), vec![]], - ..Default::default() - }, - parent_header: Default::default(), - } - } - - /// Creates default header on top of test parent with given hash. - #[cfg(test)] - pub fn with_parent_hash(parent_hash: H256) -> Self { - Self::with_parent_hash_on_runtime::(parent_hash) - } - - /// Creates default header on top of test parent with given number. First parent is selected. - #[cfg(test)] - pub fn with_parent_number(parent_number: u64) -> Self { - Self::with_parent_number_on_runtime::(parent_number) - } - - /// Creates default header on top of parent with given hash. - pub fn with_parent_hash_on_runtime, I: 'static>(parent_hash: H256) -> Self { - use crate::Headers; - - let parent_header = Headers::::get(&parent_hash).unwrap().header; - Self::with_parent(&parent_header) - } - - /// Creates default header on top of parent with given number. First parent is selected. - pub fn with_parent_number_on_runtime, I: 'static>(parent_number: u64) -> Self { - use crate::HeadersByNumber; - - let parent_hash = HeadersByNumber::::get(parent_number).unwrap()[0]; - Self::with_parent_hash_on_runtime::(parent_hash) - } - - /// Creates default header on top of non-existent parent. - #[cfg(test)] - pub fn with_number(number: u64) -> Self { - Self::with_parent(&AuraHeader { - number: number - 1, - seal: vec![bp_eth_poa::rlp_encode(&(number - 1)).to_vec(), vec![]], - ..Default::default() - }) - } - - /// Creates default header on top of given parent. - pub fn with_parent(parent_header: &AuraHeader) -> Self { - let parent_step = parent_header.step().unwrap(); - let current_step = parent_step + 1; - Self { - header: AuraHeader { - parent_hash: parent_header.compute_hash(), - number: parent_header.number + 1, - gas_limit: GAS_LIMIT.into(), - seal: vec![bp_eth_poa::rlp_encode(¤t_step).to_vec(), vec![]], - difficulty: calculate_score(parent_step, current_step, 0), - ..Default::default() - }, - parent_header: parent_header.clone(), - } - } - - /// Update step of this header. - pub fn step(mut self, step: u64) -> Self { - let parent_step = self.parent_header.step(); - self.header.seal[0] = rlp_encode(&step).to_vec(); - self.header.difficulty = parent_step - .map(|parent_step| calculate_score(parent_step, step, 0)) - .unwrap_or_default(); - self - } - - /// Adds empty steps to this header. - pub fn empty_steps(mut self, empty_steps: &[(&SecretKey, u64)]) -> Self { - let sealed_empty_steps = empty_steps - .iter() - .map(|(author, step)| { - let mut empty_step = SealedEmptyStep { step: *step, signature: Default::default() }; - let message = empty_step.message(&self.header.parent_hash); - let signature: [u8; 65] = sign(author, message).into(); - empty_step.signature = signature.into(); - empty_step - }) - .collect::>(); - - // by default in test configuration headers are generated without empty steps seal - if self.header.seal.len() < 3 { - self.header.seal.push(Vec::new()); - } - - self.header.seal[2] = SealedEmptyStep::rlp_of(&sealed_empty_steps); - self - } - - /// Update difficulty field of this header. - pub fn difficulty(mut self, difficulty: U256) -> Self { - self.header.difficulty = difficulty; - self - } - - /// Update extra data field of this header. - pub fn extra_data(mut self, extra_data: Vec) -> Self { - self.header.extra_data = extra_data; - self - } - - /// Update gas limit field of this header. - pub fn gas_limit(mut self, gas_limit: U256) -> Self { - self.header.gas_limit = gas_limit; - self - } - - /// Update gas used field of this header. - pub fn gas_used(mut self, gas_used: U256) -> Self { - self.header.gas_used = gas_used; - self - } - - /// Update log bloom field of this header. - pub fn log_bloom(mut self, log_bloom: Bloom) -> Self { - self.header.log_bloom = log_bloom; - self - } - - /// Update receipts root field of this header. - pub fn receipts_root(mut self, receipts_root: H256) -> Self { - self.header.receipts_root = receipts_root; - self - } - - /// Update timestamp field of this header. - pub fn timestamp(mut self, timestamp: u64) -> Self { - self.header.timestamp = timestamp; - self - } - - /// Update transactions root field of this header. - pub fn transactions_root(mut self, transactions_root: H256) -> Self { - self.header.transactions_root = transactions_root; - self - } - - /// Signs header by given author. - pub fn sign_by(self, author: &SecretKey) -> AuraHeader { - self.header.sign_by(author) - } - - /// Signs header by given authors set. - pub fn sign_by_set(self, authors: &[SecretKey]) -> AuraHeader { - self.header.sign_by_set(authors) - } -} - -/// Helper function for getting a genesis header which has been signed by an authority. -pub fn build_genesis_header(author: &SecretKey) -> AuraHeader { - let genesis = HeaderBuilder::genesis(); - genesis.header.sign_by(author) -} - -/// Helper function for building a custom child header which has been signed by an authority. -pub fn build_custom_header( - author: &SecretKey, - previous: &AuraHeader, - customize_header: F, -) -> AuraHeader -where - F: FnOnce(AuraHeader) -> AuraHeader, -{ - let new_header = HeaderBuilder::with_parent(previous); - let custom_header = customize_header(new_header.header); - custom_header.sign_by(author) -} - -/// Insert unverified header into storage. -/// -/// This function assumes that the header is signed by validator from the current set. -pub fn insert_header(storage: &mut S, header: AuraHeader) { - let id = header.compute_id(); - let best_finalized = storage.finalized_block(); - let import_context = storage.import_context(None, &header.parent_hash).unwrap(); - let parent_finality_votes = - storage.cached_finality_votes(&header.parent_id().unwrap(), &best_finalized, |_| false); - let finality_votes = crate::finality::prepare_votes( - parent_finality_votes, - best_finalized, - &import_context.validators_set().validators.iter().collect(), - id, - &header, - None, - ) - .unwrap(); - - storage.insert_header(HeaderToImport { - context: storage.import_context(None, &header.parent_hash).unwrap(), - is_best: true, - id, - header, - total_difficulty: 0.into(), - enacted_change: None, - scheduled_change: None, - finality_votes, - }); -} - -/// Insert unverified header into storage. -/// -/// No assumptions about header author are made. The cost is that finality votes cache -/// is filled incorrectly, so this function shall not be used if you're going to insert -/// (or import) header descendants. -pub fn insert_dummy_header(storage: &mut S, header: AuraHeader) { - storage.insert_header(HeaderToImport { - context: storage.import_context(None, &header.parent_hash).unwrap(), - is_best: true, - id: header.compute_id(), - header, - total_difficulty: 0.into(), - enacted_change: None, - scheduled_change: None, - finality_votes: FinalityVotes::default(), - }); -} - -pub fn validators_change_receipt(parent_hash: H256) -> Receipt { - use bp_eth_poa::{LogEntry, TransactionOutcome}; - - Receipt { - gas_used: 0.into(), - log_bloom: (&[0xff; 256]).into(), - outcome: TransactionOutcome::Unknown, - logs: vec![LogEntry { - address: [3; 20].into(), - topics: vec![CHANGE_EVENT_HASH.into(), parent_hash], - data: vec![ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - ], - }], - } -} - -pub mod validator_utils { - use super::*; - - /// Return key pair of given test validator. - pub fn validator(index: usize) -> SecretKey { - let mut raw_secret = [0u8; 32]; - raw_secret[..8].copy_from_slice(&(index + 1).to_le_bytes()); - SecretKey::parse(&raw_secret).unwrap() - } - - /// Return key pairs of all test validators. - pub fn validators(count: usize) -> Vec { - (0..count).map(validator).collect() - } - - /// Return address of test validator. - pub fn validator_address(index: usize) -> Address { - secret_to_address(&validator(index)) - } - - /// Return addresses of all test validators. - pub fn validators_addresses(count: usize) -> Vec
{ - (0..count).map(validator_address).collect() - } -} diff --git a/modules/ethereum/src/validators.rs b/modules/ethereum/src/validators.rs deleted file mode 100644 index fd010d52c39de..0000000000000 --- a/modules/ethereum/src/validators.rs +++ /dev/null @@ -1,458 +0,0 @@ -// 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 . - -use crate::{error::Error, ChangeToEnact, Storage}; -use bp_eth_poa::{Address, AuraHeader, HeaderId, LogEntry, Receipt, U256}; -use sp_std::prelude::*; - -/// The hash of InitiateChange event of the validators set contract. -pub(crate) const CHANGE_EVENT_HASH: &[u8; 32] = &[ - 0x55, 0x25, 0x2f, 0xa6, 0xee, 0xe4, 0x74, 0x1b, 0x4e, 0x24, 0xa7, 0x4a, 0x70, 0xe9, 0xc1, 0x1f, - 0xd2, 0xc2, 0x28, 0x1d, 0xf8, 0xd6, 0xea, 0x13, 0x12, 0x6f, 0xf8, 0x45, 0xf7, 0x82, 0x5c, 0x89, -]; - -/// Where source of validators addresses come from. This covers the chain lifetime. -pub enum ValidatorsConfiguration { - /// There's a single source for the whole chain lifetime. - Single(ValidatorsSource), - /// Validators source changes at given blocks. The blocks are ordered - /// by the block number. - Multi(Vec<(u64, ValidatorsSource)>), -} - -/// Where validators addresses come from. -/// -/// This source is valid within some blocks range. The blocks range could -/// cover multiple epochs - i.e. the validators that are authoring blocks -/// within this range could change, but the source itself can not. -#[cfg_attr(any(test, feature = "runtime-benchmarks"), derive(Debug, PartialEq))] -pub enum ValidatorsSource { - /// The validators addresses are hardcoded and never change. - List(Vec
), - /// The validators addresses are determined by the validators set contract - /// deployed at given address. The contract must implement the `ValidatorSet` - /// interface. Additionally, the initial validators set must be provided. - Contract(Address, Vec
), -} - -/// A short hand for optional validators change. -pub type ValidatorsChange = Option>; - -/// Validators manager. -pub struct Validators<'a> { - config: &'a ValidatorsConfiguration, -} - -impl<'a> Validators<'a> { - /// Creates new validators manager using given configuration. - pub fn new(config: &'a ValidatorsConfiguration) -> Self { - Self { config } - } - - /// Returns true if header (probabilistically) signals validators change and - /// the caller needs to provide transactions receipts to import the header. - pub fn maybe_signals_validators_change(&self, header: &AuraHeader) -> bool { - let (_, _, source) = self.source_at(header.number); - - // if we are taking validators set from the fixed list, there's always - // single epoch - // => we never require transactions receipts - let contract_address = match source { - ValidatorsSource::List(_) => return false, - ValidatorsSource::Contract(contract_address, _) => contract_address, - }; - - // else we need to check logs bloom and if it has required bits set, it means - // that the contract has (probably) emitted epoch change event - let expected_bloom = LogEntry { - address: *contract_address, - topics: vec![CHANGE_EVENT_HASH.into(), header.parent_hash], - data: Vec::new(), // irrelevant for bloom. - } - .bloom(); - - header.log_bloom.contains(&expected_bloom) - } - - /// Extracts validators change signal from the header. - /// - /// Returns tuple where first element is the change scheduled by this header - /// (i.e. this change is only applied starting from the block that has finalized - /// current block). The second element is the immediately applied change. - pub fn extract_validators_change( - &self, - header: &AuraHeader, - receipts: Option>, - ) -> Result<(ValidatorsChange, ValidatorsChange), Error> { - // let's first check if new source is starting from this header - let (source_index, _, source) = self.source_at(header.number); - let (next_starts_at, next_source) = self.source_at_next_header(source_index, header.number); - if next_starts_at == header.number { - match *next_source { - ValidatorsSource::List(ref new_list) => return Ok((None, Some(new_list.clone()))), - ValidatorsSource::Contract(_, ref new_list) => - return Ok((Some(new_list.clone()), None)), - } - } - - // else deal with previous source - // - // if we are taking validators set from the fixed list, there's always - // single epoch - // => we never require transactions receipts - let contract_address = match source { - ValidatorsSource::List(_) => return Ok((None, None)), - ValidatorsSource::Contract(contract_address, _) => contract_address, - }; - - // else we need to check logs bloom and if it has required bits set, it means - // that the contract has (probably) emitted epoch change event - let expected_bloom = LogEntry { - address: *contract_address, - topics: vec![CHANGE_EVENT_HASH.into(), header.parent_hash], - data: Vec::new(), // irrelevant for bloom. - } - .bloom(); - - if !header.log_bloom.contains(&expected_bloom) { - return Ok((None, None)) - } - - let receipts = receipts.ok_or(Error::MissingTransactionsReceipts)?; - #[allow(clippy::question_mark)] - if header.check_receipts_root(&receipts).is_err() { - return Err(Error::TransactionsReceiptsMismatch) - } - - // iterate in reverse because only the _last_ change in a given - // block actually has any effect - Ok(( - receipts - .iter() - .rev() - .filter(|r| r.log_bloom.contains(&expected_bloom)) - .flat_map(|r| r.logs.iter()) - .filter(|l| { - l.address == *contract_address && - l.topics.len() == 2 && l.topics[0].as_fixed_bytes() == CHANGE_EVENT_HASH && - l.topics[1] == header.parent_hash - }) - .filter_map(|l| { - let data_len = l.data.len(); - if data_len < 64 { - return None - } - - let new_validators_len_u256 = U256::from_big_endian(&l.data[32..64]); - let new_validators_len = new_validators_len_u256.low_u64(); - if new_validators_len_u256 != new_validators_len.into() { - return None - } - - if (data_len - 64) as u64 != new_validators_len.saturating_mul(32) { - return None - } - - Some( - l.data[64..] - .chunks(32) - .map(|chunk| { - let mut new_validator = Address::default(); - new_validator.as_mut().copy_from_slice(&chunk[12..32]); - new_validator - }) - .collect(), - ) - }) - .next(), - None, - )) - } - - /// Finalize changes when blocks are finalized. - pub fn finalize_validators_change( - &self, - storage: &S, - finalized_blocks: &[(HeaderId, Option)], - ) -> Option { - // if we haven't finalized any blocks, no changes may be finalized - let newest_finalized_id = match finalized_blocks.last().map(|(id, _)| id) { - Some(last_finalized_id) => last_finalized_id, - None => return None, - }; - let oldest_finalized_id = finalized_blocks - .first() - .map(|(id, _)| id) - .expect("finalized_blocks is not empty; qed"); - - // try to directly go to the header that has scheduled last change - // - // if we're unable to create import context for some block, it means - // that the header has already been pruned => it and its ancestors had - // no scheduled changes - // - // if we're unable to find scheduled changes for some block, it means - // that these changes have been finalized already - storage - .import_context(None, &newest_finalized_id.hash) - .and_then(|context| context.last_signal_block()) - .and_then(|signal_block| { - if signal_block.number >= oldest_finalized_id.number { - Some(signal_block) - } else { - None - } - }) - .and_then(|signal_block| { - storage.scheduled_change(&signal_block.hash).map(|change| ChangeToEnact { - signal_block: Some(signal_block), - validators: change.validators, - }) - }) - } - - /// Returns source of validators that should author the header. - fn source_at(&self, header_number: u64) -> (usize, u64, &ValidatorsSource) { - match self.config { - ValidatorsConfiguration::Single(ref source) => (0, 0, source), - ValidatorsConfiguration::Multi(ref sources) => sources - .iter() - .rev() - .enumerate() - .find(|(_, &(begin, _))| begin < header_number) - .map(|(i, (begin, source))| (sources.len() - 1 - i, *begin, source)) - .expect( - "there's always entry for the initial block;\ - we do not touch any headers with number < initial block number; qed", - ), - } - } - - /// Returns source of validators that should author the next header. - fn source_at_next_header( - &self, - header_source_index: usize, - header_number: u64, - ) -> (u64, &ValidatorsSource) { - match self.config { - ValidatorsConfiguration::Single(ref source) => (0, source), - ValidatorsConfiguration::Multi(ref sources) => { - let next_source_index = header_source_index + 1; - if next_source_index < sources.len() { - let next_source = &sources[next_source_index]; - if next_source.0 < header_number + 1 { - return (next_source.0, &next_source.1) - } - } - - let source = &sources[header_source_index]; - (source.0, &source.1) - }, - } - } -} - -impl ValidatorsSource { - /// Returns initial validators set. - pub fn initial_epoch_validators(&self) -> Vec
{ - match self { - ValidatorsSource::List(ref list) => list.clone(), - ValidatorsSource::Contract(_, ref list) => list.clone(), - } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::{ - mock::{run_test, validators_addresses, validators_change_receipt, TestRuntime}, - AuraScheduledChange, BridgeStorage, Headers, ScheduledChanges, StoredHeader, - }; - use bp_eth_poa::compute_merkle_root; - - const TOTAL_VALIDATORS: usize = 3; - - #[test] - fn source_at_works() { - let config = ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(vec![[1; 20].into()])), - (100, ValidatorsSource::List(vec![[2; 20].into()])), - (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), - ]); - let validators = Validators::new(&config); - - assert_eq!(validators.source_at(99), (0, 0, &ValidatorsSource::List(vec![[1; 20].into()])),); - assert_eq!( - validators.source_at_next_header(0, 99), - (0, &ValidatorsSource::List(vec![[1; 20].into()])), - ); - - assert_eq!( - validators.source_at(100), - (0, 0, &ValidatorsSource::List(vec![[1; 20].into()])), - ); - assert_eq!( - validators.source_at_next_header(0, 100), - (100, &ValidatorsSource::List(vec![[2; 20].into()])), - ); - - assert_eq!( - validators.source_at(200), - (1, 100, &ValidatorsSource::List(vec![[2; 20].into()])), - ); - assert_eq!( - validators.source_at_next_header(1, 200), - (200, &ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), - ); - } - - #[test] - fn maybe_signals_validators_change_works() { - // when contract is active, but bloom has no required bits set - let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( - Default::default(), - Vec::new(), - )); - let validators = Validators::new(&config); - let mut header = AuraHeader { number: u64::max_value(), ..Default::default() }; - assert!(!validators.maybe_signals_validators_change(&header)); - - // when contract is active and bloom has required bits set - header.log_bloom = (&[0xff; 256]).into(); - assert!(validators.maybe_signals_validators_change(&header)); - - // when list is active and bloom has required bits set - let config = ValidatorsConfiguration::Single(ValidatorsSource::List(vec![[42; 20].into()])); - let validators = Validators::new(&config); - assert!(!validators.maybe_signals_validators_change(&header)); - } - - #[test] - fn extract_validators_change_works() { - let config = ValidatorsConfiguration::Multi(vec![ - (0, ValidatorsSource::List(vec![[1; 20].into()])), - (100, ValidatorsSource::List(vec![[2; 20].into()])), - (200, ValidatorsSource::Contract([3; 20].into(), vec![[3; 20].into()])), - ]); - let validators = Validators::new(&config); - let mut header = AuraHeader { number: 100, ..Default::default() }; - - // when we're at the block that switches to list source - assert_eq!( - validators.extract_validators_change(&header, None), - Ok((None, Some(vec![[2; 20].into()]))), - ); - - // when we're inside list range - header.number = 150; - assert_eq!(validators.extract_validators_change(&header, None), Ok((None, None)),); - - // when we're at the block that switches to contract source - header.number = 200; - assert_eq!( - validators.extract_validators_change(&header, None), - Ok((Some(vec![[3; 20].into()]), None)), - ); - - // when we're inside contract range and logs bloom signals change - // but we have no receipts - header.number = 250; - header.log_bloom = (&[0xff; 256]).into(); - assert_eq!( - validators.extract_validators_change(&header, None), - Err(Error::MissingTransactionsReceipts), - ); - - // when we're inside contract range and logs bloom signals change - // but there's no change in receipts - header.receipts_root = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - .parse() - .unwrap(); - assert_eq!( - validators.extract_validators_change(&header, Some(Vec::new())), - Ok((None, None)), - ); - - // when we're inside contract range and logs bloom signals change - // and there's change in receipts - let receipts = vec![validators_change_receipt(Default::default())]; - header.receipts_root = compute_merkle_root(receipts.iter().map(|r| r.rlp())); - assert_eq!( - validators.extract_validators_change(&header, Some(receipts)), - Ok((Some(vec![[7; 20].into()]), None)), - ); - - // when incorrect receipts root passed - assert_eq!( - validators.extract_validators_change(&header, Some(Vec::new())), - Err(Error::TransactionsReceiptsMismatch), - ); - } - - fn try_finalize_with_scheduled_change(scheduled_at: Option) -> Option { - run_test(TOTAL_VALIDATORS, |_| { - let config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( - Default::default(), - Vec::new(), - )); - let validators = Validators::new(&config); - let storage = BridgeStorage::::new(); - - // when we're finailizing blocks 10...100 - let id10 = HeaderId { number: 10, hash: [10; 32].into() }; - let id100 = HeaderId { number: 100, hash: [100; 32].into() }; - let finalized_blocks = vec![(id10, None), (id100, None)]; - let header100 = StoredHeader:: { - submitter: None, - header: AuraHeader { number: 100, ..Default::default() }, - total_difficulty: 0.into(), - next_validators_set_id: 0, - last_signal_block: scheduled_at, - }; - let scheduled_change = AuraScheduledChange { - validators: validators_addresses(1), - prev_signal_block: None, - }; - Headers::::insert(id100.hash, header100); - if let Some(scheduled_at) = scheduled_at { - ScheduledChanges::::insert(scheduled_at.hash, scheduled_change); - } - - validators.finalize_validators_change(&storage, &finalized_blocks) - }) - } - - #[test] - fn finalize_validators_change_finalizes_scheduled_change() { - let id50 = HeaderId { number: 50, ..Default::default() }; - assert_eq!( - try_finalize_with_scheduled_change(Some(id50)), - Some(ChangeToEnact { signal_block: Some(id50), validators: validators_addresses(1) }), - ); - } - - #[test] - fn finalize_validators_change_does_not_finalize_when_changes_are_not_scheduled() { - assert_eq!(try_finalize_with_scheduled_change(None), None,); - } - - #[test] - fn finalize_validators_change_does_not_finalize_changes_when_they_are_outside_of_range() { - let id5 = HeaderId { number: 5, ..Default::default() }; - assert_eq!(try_finalize_with_scheduled_change(Some(id5)), None,); - } -} diff --git a/modules/ethereum/src/verification.rs b/modules/ethereum/src/verification.rs deleted file mode 100644 index 053ce4d0fea4d..0000000000000 --- a/modules/ethereum/src/verification.rs +++ /dev/null @@ -1,972 +0,0 @@ -// 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 . - -use crate::{ - error::Error, - validators::{Validators, ValidatorsConfiguration}, - AuraConfiguration, AuraScheduledChange, ChainTime, ImportContext, PoolConfiguration, Storage, -}; -use bp_eth_poa::{ - public_to_address, step_validator, Address, AuraHeader, HeaderId, Receipt, SealedEmptyStep, - H256, H520, U128, U256, -}; -use codec::Encode; -use sp_io::crypto::secp256k1_ecdsa_recover; -use sp_runtime::transaction_validity::TransactionTag; -use sp_std::{vec, vec::Vec}; - -/// Pre-check to see if should try and import this header. -/// Returns error if we should not try to import this block. -/// Returns ID of passed header and best finalized header. -pub fn is_importable_header( - storage: &S, - header: &AuraHeader, -) -> Result<(HeaderId, HeaderId), Error> { - // we never import any header that competes with finalized header - let finalized_id = storage.finalized_block(); - if header.number <= finalized_id.number { - return Err(Error::AncientHeader) - } - // we never import any header with known hash - let id = header.compute_id(); - if storage.header(&id.hash).is_some() { - return Err(Error::KnownHeader) - } - - Ok((id, finalized_id)) -} - -/// Try to accept unsigned aura header into transaction pool. -/// -/// Returns required and provided tags. -pub fn accept_aura_header_into_pool( - storage: &S, - config: &AuraConfiguration, - validators_config: &ValidatorsConfiguration, - pool_config: &PoolConfiguration, - header: &AuraHeader, - chain_time: &CT, - receipts: Option<&Vec>, -) -> Result<(Vec, Vec), Error> { - // check if we can verify further - let (header_id, _) = is_importable_header(storage, header)?; - - // we can always do contextless checks - contextless_checks(config, header, chain_time)?; - - // we want to avoid having same headers twice in the pool - // => we're strict about receipts here - if we need them, we require receipts to be Some, - // otherwise we require receipts to be None - let receipts_required = - Validators::new(validators_config).maybe_signals_validators_change(header); - match (receipts_required, receipts.is_some()) { - (true, false) => return Err(Error::MissingTransactionsReceipts), - (false, true) => return Err(Error::RedundantTransactionsReceipts), - _ => (), - } - - // we do not want to have all future headers in the pool at once - // => if we see header with number > maximal ever seen header number + LIMIT, - // => we consider this transaction invalid, but only at this moment (we do not want to ban it) - // => let's mark it as Unknown transaction - let (best_id, _) = storage.best_block(); - let difference = header.number.saturating_sub(best_id.number); - if difference > pool_config.max_future_number_difference { - return Err(Error::UnsignedTooFarInTheFuture) - } - - // TODO: only accept new headers when we're at the tip of PoA chain - // https://github.com/paritytech/parity-bridges-common/issues/38 - - // we want to see at most one header with given number from single authority - // => every header is providing tag (block_number + authority) - // => since only one tx in the pool can provide the same tag, they're auto-deduplicated - let provides_number_and_authority_tag = (header.number, header.author).encode(); - - // we want to see several 'future' headers in the pool at once, but we may not have access to - // previous headers here - // => we can at least 'verify' that headers comprise a chain by providing and requiring - // tag (header.number, header.hash) - let provides_header_number_and_hash_tag = header_id.encode(); - - // depending on whether parent header is available, we either perform full or 'shortened' check - let context = storage.import_context(None, &header.parent_hash); - let tags = match context { - Some(context) => { - let header_step = contextual_checks(config, &context, None, header)?; - validator_checks(config, &context.validators_set().validators, header, header_step)?; - - // since our parent is already in the storage, we do not require it - // to be in the transaction pool - (vec![], vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag]) - }, - None => { - // we know nothing about parent header - // => the best thing we can do is to believe that there are no forks in - // PoA chain AND that the header is produced either by previous, or next - // scheduled validators set change - let header_step = header.step().ok_or(Error::MissingStep)?; - let best_context = storage.import_context(None, &best_id.hash).expect( - "import context is None only when header is missing from the storage;\ - best header is always in the storage; qed", - ); - let validators_check_result = validator_checks( - config, - &best_context.validators_set().validators, - header, - header_step, - ); - if let Err(error) = validators_check_result { - find_next_validators_signal(storage, &best_context).ok_or(error).and_then( - |next_validators| { - validator_checks(config, &next_validators, header, header_step) - }, - )?; - } - - // since our parent is missing from the storage, we **DO** require it - // to be in the transaction pool - // (- 1 can't underflow because there's always best block in the header) - let requires_header_number_and_hash_tag = - HeaderId { number: header.number - 1, hash: header.parent_hash }.encode(); - ( - vec![requires_header_number_and_hash_tag], - vec![provides_number_and_authority_tag, provides_header_number_and_hash_tag], - ) - }, - }; - - // the heaviest, but rare operation - we do not want invalid receipts in the pool - if let Some(receipts) = receipts { - log::trace!(target: "runtime", "Got receipts! {:?}", receipts); - #[allow(clippy::question_mark)] - if header.check_receipts_root(receipts).is_err() { - return Err(Error::TransactionsReceiptsMismatch) - } - } - - Ok(tags) -} - -/// Verify header by Aura rules. -pub fn verify_aura_header( - storage: &S, - config: &AuraConfiguration, - submitter: Option, - header: &AuraHeader, - chain_time: &CT, -) -> Result, Error> { - // let's do the lightest check first - contextless_checks(config, header, chain_time)?; - - // the rest of checks requires access to the parent header - let context = storage.import_context(submitter, &header.parent_hash).ok_or_else(|| { - log::warn!( - target: "runtime", - "Missing parent PoA block: ({:?}, {})", - header.number.checked_sub(1), - header.parent_hash, - ); - - Error::MissingParentBlock - })?; - let header_step = contextual_checks(config, &context, None, header)?; - validator_checks(config, &context.validators_set().validators, header, header_step)?; - - Ok(context) -} - -/// Perform basic checks that only require header itself. -fn contextless_checks( - config: &AuraConfiguration, - header: &AuraHeader, - chain_time: &CT, -) -> Result<(), Error> { - let expected_seal_fields = expected_header_seal_fields(config, header); - if header.seal.len() != expected_seal_fields { - return Err(Error::InvalidSealArity) - } - if header.number >= u64::max_value() { - return Err(Error::RidiculousNumber) - } - if header.gas_used > header.gas_limit { - return Err(Error::TooMuchGasUsed) - } - if header.gas_limit < config.min_gas_limit { - return Err(Error::InvalidGasLimit) - } - if header.gas_limit > config.max_gas_limit { - return Err(Error::InvalidGasLimit) - } - if header.number != 0 && header.extra_data.len() as u64 > config.maximum_extra_data_size { - return Err(Error::ExtraDataOutOfBounds) - } - - // we can't detect if block is from future in runtime - // => let's only do an overflow check - if header.timestamp > i32::max_value() as u64 { - return Err(Error::TimestampOverflow) - } - - if chain_time.is_timestamp_ahead(header.timestamp) { - return Err(Error::HeaderTimestampIsAhead) - } - - Ok(()) -} - -/// Perform checks that require access to parent header. -fn contextual_checks( - config: &AuraConfiguration, - context: &ImportContext, - validators_override: Option<&[Address]>, - header: &AuraHeader, -) -> Result { - let validators = validators_override.unwrap_or_else(|| &context.validators_set().validators); - let header_step = header.step().ok_or(Error::MissingStep)?; - let parent_step = context.parent_header().step().ok_or(Error::MissingStep)?; - - // Ensure header is from the step after context. - if header_step == parent_step { - return Err(Error::DoubleVote) - } - #[allow(clippy::suspicious_operation_groupings)] - if header.number >= config.validate_step_transition && header_step < parent_step { - return Err(Error::DoubleVote) - } - - // If empty step messages are enabled we will validate the messages in the seal, missing - // messages are not reported as there's no way to tell whether the empty step message was never - // sent or simply not included. - let empty_steps_len = match header.number >= config.empty_steps_transition { - true => { - let strict_empty_steps = header.number >= config.strict_empty_steps_transition; - let empty_steps = header.empty_steps().ok_or(Error::MissingEmptySteps)?; - let empty_steps_len = empty_steps.len(); - let mut prev_empty_step = 0; - - for empty_step in empty_steps { - if empty_step.step <= parent_step || empty_step.step >= header_step { - return Err(Error::InsufficientProof) - } - - if !verify_empty_step(&header.parent_hash, &empty_step, validators) { - return Err(Error::InsufficientProof) - } - - if strict_empty_steps { - if empty_step.step <= prev_empty_step { - return Err(Error::InsufficientProof) - } - - prev_empty_step = empty_step.step; - } - } - - empty_steps_len - }, - false => 0, - }; - - // Validate chain score. - if header.number >= config.validate_score_transition { - let expected_difficulty = calculate_score(parent_step, header_step, empty_steps_len as _); - if header.difficulty != expected_difficulty { - return Err(Error::InvalidDifficulty) - } - } - - Ok(header_step) -} - -/// Check that block is produced by expected validator. -fn validator_checks( - config: &AuraConfiguration, - validators: &[Address], - header: &AuraHeader, - header_step: u64, -) -> Result<(), Error> { - let expected_validator = *step_validator(validators, header_step); - if header.author != expected_validator { - return Err(Error::NotValidator) - } - - let validator_signature = header.signature().ok_or(Error::MissingSignature)?; - let header_seal_hash = header - .seal_hash(header.number >= config.empty_steps_transition) - .ok_or(Error::MissingEmptySteps)?; - let is_invalid_proposer = - !verify_signature(&expected_validator, &validator_signature, &header_seal_hash); - if is_invalid_proposer { - return Err(Error::NotValidator) - } - - Ok(()) -} - -/// Returns expected number of seal fields in the header. -fn expected_header_seal_fields(config: &AuraConfiguration, header: &AuraHeader) -> usize { - if header.number != u64::max_value() && header.number >= config.empty_steps_transition { - 3 - } else { - 2 - } -} - -/// Verify single sealed empty step. -fn verify_empty_step(parent_hash: &H256, step: &SealedEmptyStep, validators: &[Address]) -> bool { - let expected_validator = *step_validator(validators, step.step); - let message = step.message(parent_hash); - verify_signature(&expected_validator, &step.signature, &message) -} - -/// Chain scoring: total `weight is sqrt(U256::max_value())*height - step`. -pub(crate) fn calculate_score( - parent_step: u64, - current_step: u64, - current_empty_steps: usize, -) -> U256 { - U256::from(U128::max_value()) + U256::from(parent_step) - U256::from(current_step) + - U256::from(current_empty_steps) -} - -/// Verify that the signature over message has been produced by given validator. -fn verify_signature(expected_validator: &Address, signature: &H520, message: &H256) -> bool { - secp256k1_ecdsa_recover(signature.as_fixed_bytes(), message.as_fixed_bytes()) - .map(|public| public_to_address(&public)) - .map(|address| *expected_validator == address) - .unwrap_or(false) -} - -/// Find next unfinalized validators set change after finalized set. -fn find_next_validators_signal( - storage: &S, - context: &ImportContext, -) -> Option> { - // that's the earliest block number we may met in following loop - // it may be None if that's the first set - let best_set_signal_block = context.validators_set().signal_block; - - // if parent schedules validators set change, then it may be our set - // else we'll start with last known change - let mut current_set_signal_block = context.last_signal_block(); - let mut next_scheduled_set: Option = None; - - loop { - // if we have reached block that signals finalized change, then - // next_current_block_hash points to the block that schedules next - // change - let current_scheduled_set = match current_set_signal_block { - Some(current_set_signal_block) - if Some(¤t_set_signal_block) == best_set_signal_block.as_ref() => - return next_scheduled_set.map(|scheduled_set| scheduled_set.validators), - None => return next_scheduled_set.map(|scheduled_set| scheduled_set.validators), - Some(current_set_signal_block) => - storage.scheduled_change(¤t_set_signal_block.hash).expect( - "header that is associated with this change is not pruned;\ - scheduled changes are only removed when header is pruned; qed", - ), - }; - - current_set_signal_block = current_scheduled_set.prev_signal_block; - next_scheduled_set = Some(current_scheduled_set); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::{ - insert_header, run_test_with_genesis, test_aura_config, validator, validator_address, - validators_addresses, validators_change_receipt, AccountId, ConstChainTime, - HeaderBuilder, TestRuntime, GAS_LIMIT, - }, - pool_configuration, - validators::ValidatorsSource, - BridgeStorage, FinalizedBlock, Headers, HeadersByNumber, NextValidatorsSetId, - ScheduledChanges, ValidatorsSet, ValidatorsSets, - }; - use bp_eth_poa::{compute_merkle_root, rlp_encode, TransactionOutcome, H520, U256}; - use hex_literal::hex; - use libsecp256k1::SecretKey; - use sp_runtime::transaction_validity::TransactionTag; - - const GENESIS_STEP: u64 = 42; - const TOTAL_VALIDATORS: usize = 3; - - fn genesis() -> AuraHeader { - HeaderBuilder::genesis().step(GENESIS_STEP).sign_by(&validator(0)) - } - - fn verify_with_config( - config: &AuraConfiguration, - header: &AuraHeader, - ) -> Result, Error> { - run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { - let storage = BridgeStorage::::new(); - verify_aura_header(&storage, config, None, header, &ConstChainTime::default()) - }) - } - - fn default_verify(header: &AuraHeader) -> Result, Error> { - verify_with_config(&test_aura_config(), header) - } - - fn default_accept_into_pool( - mut make_header: impl FnMut(&[SecretKey]) -> (AuraHeader, Option>), - ) -> Result<(Vec, Vec), Error> { - run_test_with_genesis(genesis(), TOTAL_VALIDATORS, |_| { - let validators = vec![validator(0), validator(1), validator(2)]; - let mut storage = BridgeStorage::::new(); - let block1 = HeaderBuilder::with_parent_number(0).sign_by_set(&validators); - insert_header(&mut storage, block1); - let block2 = HeaderBuilder::with_parent_number(1).sign_by_set(&validators); - let block2_id = block2.compute_id(); - insert_header(&mut storage, block2); - let block3 = HeaderBuilder::with_parent_number(2).sign_by_set(&validators); - insert_header(&mut storage, block3); - - FinalizedBlock::::put(block2_id); - - let validators_config = ValidatorsConfiguration::Single(ValidatorsSource::Contract( - Default::default(), - Vec::new(), - )); - let (header, receipts) = make_header(&validators); - accept_aura_header_into_pool( - &storage, - &test_aura_config(), - &validators_config, - &pool_configuration(), - &header, - &(), - receipts.as_ref(), - ) - }) - } - - fn change_validators_set_at( - number: u64, - finalized_set: Vec
, - signalled_set: Option>, - ) { - let set_id = NextValidatorsSetId::::get(); - NextValidatorsSetId::::put(set_id + 1); - ValidatorsSets::::insert( - set_id, - ValidatorsSet { - validators: finalized_set, - signal_block: None, - enact_block: HeaderId { - number: 0, - hash: HeadersByNumber::::get(&0).unwrap()[0], - }, - }, - ); - - let header_hash = HeadersByNumber::::get(&number).unwrap()[0]; - let mut header = Headers::::get(&header_hash).unwrap(); - header.next_validators_set_id = set_id; - if let Some(signalled_set) = signalled_set { - header.last_signal_block = Some(HeaderId { - number: header.header.number - 1, - hash: header.header.parent_hash, - }); - ScheduledChanges::::insert( - header.header.parent_hash, - AuraScheduledChange { validators: signalled_set, prev_signal_block: None }, - ); - } - - Headers::::insert(header_hash, header); - } - - #[test] - fn verifies_seal_count() { - // when there are no seals at all - let mut header = AuraHeader::default(); - assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); - - // when there's single seal (we expect 2 or 3 seals) - header.seal = vec![vec![]]; - assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); - - // when there's 3 seals (we expect 2 by default) - header.seal = vec![vec![], vec![], vec![]]; - assert_eq!(default_verify(&header), Err(Error::InvalidSealArity)); - - // when there's 2 seals - header.seal = vec![vec![], vec![]]; - assert_ne!(default_verify(&header), Err(Error::InvalidSealArity)); - } - - #[test] - fn verifies_header_number() { - // when number is u64::max_value() - let header = HeaderBuilder::with_number(u64::max_value()).sign_by(&validator(0)); - assert_eq!(default_verify(&header), Err(Error::RidiculousNumber)); - - // when header is < u64::max_value() - let header = HeaderBuilder::with_number(u64::max_value() - 1).sign_by(&validator(0)); - assert_ne!(default_verify(&header), Err(Error::RidiculousNumber)); - } - - #[test] - fn verifies_gas_used() { - // when gas used is larger than gas limit - let header = HeaderBuilder::with_number(1) - .gas_used((GAS_LIMIT + 1).into()) - .sign_by(&validator(0)); - assert_eq!(default_verify(&header), Err(Error::TooMuchGasUsed)); - - // when gas used is less than gas limit - let header = HeaderBuilder::with_number(1) - .gas_used((GAS_LIMIT - 1).into()) - .sign_by(&validator(0)); - assert_ne!(default_verify(&header), Err(Error::TooMuchGasUsed)); - } - - #[test] - fn verifies_gas_limit() { - let mut config = test_aura_config(); - config.min_gas_limit = 100.into(); - config.max_gas_limit = 200.into(); - - // when limit is lower than expected - let header = HeaderBuilder::with_number(1).gas_limit(50.into()).sign_by(&validator(0)); - assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); - - // when limit is larger than expected - let header = HeaderBuilder::with_number(1).gas_limit(250.into()).sign_by(&validator(0)); - assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); - - // when limit is within expected range - let header = HeaderBuilder::with_number(1).gas_limit(150.into()).sign_by(&validator(0)); - assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidGasLimit)); - } - - #[test] - fn verifies_extra_data_len() { - // when extra data is too large - let header = HeaderBuilder::with_number(1) - .extra_data(std::iter::repeat(42).take(1000).collect::>()) - .sign_by(&validator(0)); - assert_eq!(default_verify(&header), Err(Error::ExtraDataOutOfBounds)); - - // when extra data size is OK - let header = HeaderBuilder::with_number(1) - .extra_data(std::iter::repeat(42).take(10).collect::>()) - .sign_by(&validator(0)); - assert_ne!(default_verify(&header), Err(Error::ExtraDataOutOfBounds)); - } - - #[test] - fn verifies_timestamp() { - // when timestamp overflows i32 - let header = HeaderBuilder::with_number(1) - .timestamp(i32::max_value() as u64 + 1) - .sign_by(&validator(0)); - assert_eq!(default_verify(&header), Err(Error::TimestampOverflow)); - - // when timestamp doesn't overflow i32 - let header = HeaderBuilder::with_number(1) - .timestamp(i32::max_value() as u64) - .sign_by(&validator(0)); - assert_ne!(default_verify(&header), Err(Error::TimestampOverflow)); - } - - #[test] - fn verifies_chain_time() { - // expected import context after verification - let expect = ImportContext:: { - submitter: None, - parent_hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3") - .into(), - parent_header: genesis(), - parent_total_difficulty: U256::zero(), - parent_scheduled_change: None, - validators_set_id: 0, - validators_set: ValidatorsSet { - validators: vec![ - hex!("dc5b20847f43d67928f49cd4f85d696b5a7617b5").into(), - hex!("897df33a7b3c62ade01e22c13d48f98124b4480f").into(), - hex!("05c987b34c6ef74e0c7e69c6e641120c24164c2d").into(), - ], - signal_block: None, - enact_block: HeaderId { - number: 0, - hash: hex!("6e41bff05578fc1db17f6816117969b07d2217f1f9039d8116a82764335991d3") - .into(), - }, - }, - last_signal_block: None, - }; - - // header is behind - let header = HeaderBuilder::with_parent(&genesis()) - .timestamp(i32::max_value() as u64 / 2 - 100) - .sign_by(&validator(1)); - assert_eq!(default_verify(&header).unwrap(), expect); - - // header is ahead - let header = HeaderBuilder::with_parent(&genesis()) - .timestamp(i32::max_value() as u64 / 2 + 100) - .sign_by(&validator(1)); - assert_eq!(default_verify(&header), Err(Error::HeaderTimestampIsAhead)); - - // header has same timestamp as ConstChainTime - let header = HeaderBuilder::with_parent(&genesis()) - .timestamp(i32::max_value() as u64 / 2) - .sign_by(&validator(1)); - assert_eq!(default_verify(&header).unwrap(), expect); - } - - #[test] - fn verifies_parent_existence() { - // when there's no parent in the storage - let header = HeaderBuilder::with_number(1).sign_by(&validator(0)); - assert_eq!(default_verify(&header), Err(Error::MissingParentBlock)); - - // when parent is in the storage - let header = HeaderBuilder::with_parent(&genesis()).sign_by(&validator(0)); - assert_ne!(default_verify(&header), Err(Error::MissingParentBlock)); - } - - #[test] - fn verifies_step() { - // when step is missing from seals - let mut header = AuraHeader { - seal: vec![vec![], vec![]], - gas_limit: test_aura_config().min_gas_limit, - parent_hash: genesis().compute_hash(), - ..Default::default() - }; - assert_eq!(default_verify(&header), Err(Error::MissingStep)); - - // when step is the same as for the parent block - header.seal[0] = rlp_encode(&42u64).to_vec(); - assert_eq!(default_verify(&header), Err(Error::DoubleVote)); - - // when step is OK - header.seal[0] = rlp_encode(&43u64).to_vec(); - assert_ne!(default_verify(&header), Err(Error::DoubleVote)); - - // now check with validate_step check enabled - let mut config = test_aura_config(); - config.validate_step_transition = 0; - - // when step is lesser that for the parent block - header.seal[0] = rlp_encode(&40u64).to_vec(); - header.seal = vec![vec![40], vec![]]; - assert_eq!(verify_with_config(&config, &header), Err(Error::DoubleVote)); - - // when step is OK - header.seal[0] = rlp_encode(&44u64).to_vec(); - assert_ne!(verify_with_config(&config, &header), Err(Error::DoubleVote)); - } - - #[test] - fn verifies_empty_step() { - let mut config = test_aura_config(); - config.empty_steps_transition = 0; - - // when empty step duplicates parent step - let header = HeaderBuilder::with_parent(&genesis()) - .empty_steps(&[(&validator(0), GENESIS_STEP)]) - .step(GENESIS_STEP + 3) - .sign_by(&validator(3)); - assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); - - // when empty step signature check fails - let header = HeaderBuilder::with_parent(&genesis()) - .empty_steps(&[(&validator(100), GENESIS_STEP + 1)]) - .step(GENESIS_STEP + 3) - .sign_by(&validator(3)); - assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); - - // when we are accepting strict empty steps and they come not in order - config.strict_empty_steps_transition = 0; - let header = HeaderBuilder::with_parent(&genesis()) - .empty_steps(&[(&validator(2), GENESIS_STEP + 2), (&validator(1), GENESIS_STEP + 1)]) - .step(GENESIS_STEP + 3) - .sign_by(&validator(3)); - assert_eq!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); - - // when empty steps are OK - let header = HeaderBuilder::with_parent(&genesis()) - .empty_steps(&[(&validator(1), GENESIS_STEP + 1), (&validator(2), GENESIS_STEP + 2)]) - .step(GENESIS_STEP + 3) - .sign_by(&validator(3)); - assert_ne!(verify_with_config(&config, &header), Err(Error::InsufficientProof)); - } - - #[test] - fn verifies_chain_score() { - let mut config = test_aura_config(); - config.validate_score_transition = 0; - - // when chain score is invalid - let header = HeaderBuilder::with_parent(&genesis()) - .difficulty(100.into()) - .sign_by(&validator(0)); - assert_eq!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); - - // when chain score is accepted - let header = HeaderBuilder::with_parent(&genesis()).sign_by(&validator(0)); - assert_ne!(verify_with_config(&config, &header), Err(Error::InvalidDifficulty)); - } - - #[test] - fn verifies_validator() { - let good_header = HeaderBuilder::with_parent(&genesis()).sign_by(&validator(1)); - - // when header author is invalid - let mut header = good_header.clone(); - header.author = Default::default(); - assert_eq!(default_verify(&header), Err(Error::NotValidator)); - - // when header signature is invalid - let mut header = good_header.clone(); - header.seal[1] = rlp_encode(&H520::default()).to_vec(); - assert_eq!(default_verify(&header), Err(Error::NotValidator)); - - // when everything is OK - assert_eq!(default_verify(&good_header).map(|_| ()), Ok(())); - } - - #[test] - fn pool_verifies_known_blocks() { - // when header is known - assert_eq!( - default_accept_into_pool(|validators| ( - HeaderBuilder::with_parent_number(2).sign_by_set(validators), - None - )), - Err(Error::KnownHeader), - ); - } - - #[test] - fn pool_verifies_ancient_blocks() { - // when header number is less than finalized - assert_eq!( - default_accept_into_pool(|validators| ( - HeaderBuilder::with_parent_number(1) - .gas_limit((GAS_LIMIT + 1).into()) - .sign_by_set(validators), - None, - ),), - Err(Error::AncientHeader), - ); - } - - #[test] - fn pool_rejects_headers_without_required_receipts() { - assert_eq!( - default_accept_into_pool(|_| ( - AuraHeader { - number: 20_000_000, - seal: vec![vec![], vec![]], - gas_limit: test_aura_config().min_gas_limit, - log_bloom: (&[0xff; 256]).into(), - ..Default::default() - }, - None, - ),), - Err(Error::MissingTransactionsReceipts), - ); - } - - #[test] - fn pool_rejects_headers_with_redundant_receipts() { - assert_eq!( - default_accept_into_pool(|validators| ( - HeaderBuilder::with_parent_number(3).sign_by_set(validators), - Some(vec![Receipt { - gas_used: 1.into(), - log_bloom: (&[0xff; 256]).into(), - logs: vec![], - outcome: TransactionOutcome::Unknown, - }]), - ),), - Err(Error::RedundantTransactionsReceipts), - ); - } - - #[test] - fn pool_verifies_future_block_number() { - // when header is too far from the future - assert_eq!( - default_accept_into_pool(|validators| ( - HeaderBuilder::with_number(100).sign_by_set(validators), - None - ),), - Err(Error::UnsignedTooFarInTheFuture), - ); - } - - #[test] - fn pool_performs_full_verification_when_parent_is_known() { - // if parent is known, then we'll execute contextual_checks, which - // checks for DoubleVote - assert_eq!( - default_accept_into_pool(|validators| ( - HeaderBuilder::with_parent_number(3) - .step(GENESIS_STEP + 3) - .sign_by_set(validators), - None, - ),), - Err(Error::DoubleVote), - ); - } - - #[test] - fn pool_performs_validators_checks_when_parent_is_unknown() { - // if parent is unknown, then we still need to check if header has required signature - // (even if header will be considered invalid/duplicate later, we can use this signature - // as a proof of malicious action by this validator) - assert_eq!( - default_accept_into_pool(|_| ( - HeaderBuilder::with_number(8).step(8).sign_by(&validator(1)), - None, - )), - Err(Error::NotValidator), - ); - } - - #[test] - fn pool_verifies_header_with_known_parent() { - let mut hash = None; - assert_eq!( - default_accept_into_pool(|validators| { - let header = HeaderBuilder::with_parent_number(3).sign_by_set(validators); - hash = Some(header.compute_hash()); - (header, None) - }), - Ok(( - // no tags are required - vec![], - // header provides two tags - vec![(4u64, validators_addresses(3)[1]).encode(), (4u64, hash.unwrap()).encode(),], - )), - ); - } - - #[test] - fn pool_verifies_header_with_unknown_parent() { - let mut id = None; - let mut parent_id = None; - assert_eq!( - default_accept_into_pool(|validators| { - let header = - HeaderBuilder::with_number(5).step(GENESIS_STEP + 5).sign_by_set(validators); - id = Some(header.compute_id()); - parent_id = header.parent_id(); - (header, None) - }), - Ok(( - // parent tag required - vec![parent_id.unwrap().encode()], - // header provides two tags - vec![(5u64, validator_address(2)).encode(), id.unwrap().encode(),], - )), - ); - } - - #[test] - fn pool_uses_next_validators_set_when_finalized_fails() { - assert_eq!( - default_accept_into_pool(|actual_validators| { - // change finalized set at parent header - change_validators_set_at(3, validators_addresses(1), None); - - // header is signed using wrong set - let header = HeaderBuilder::with_number(5) - .step(GENESIS_STEP + 2) - .sign_by_set(actual_validators); - - (header, None) - }), - Err(Error::NotValidator), - ); - - let mut id = None; - let mut parent_id = None; - assert_eq!( - default_accept_into_pool(|actual_validators| { - // change finalized set at parent header + signal valid set at parent block - change_validators_set_at( - 3, - validators_addresses(10), - Some(validators_addresses(3)), - ); - - // header is signed using wrong set - let header = HeaderBuilder::with_number(5) - .step(GENESIS_STEP + 2) - .sign_by_set(actual_validators); - id = Some(header.compute_id()); - parent_id = header.parent_id(); - - (header, None) - }), - Ok(( - // parent tag required - vec![parent_id.unwrap().encode(),], - // header provides two tags - vec![(5u64, validator_address(2)).encode(), id.unwrap().encode(),], - )), - ); - } - - #[test] - fn pool_rejects_headers_with_invalid_receipts() { - assert_eq!( - default_accept_into_pool(|validators| { - let header = HeaderBuilder::with_parent_number(3) - .log_bloom((&[0xff; 256]).into()) - .sign_by_set(validators); - (header, Some(vec![validators_change_receipt(Default::default())])) - }), - Err(Error::TransactionsReceiptsMismatch), - ); - } - - #[test] - fn pool_accepts_headers_with_valid_receipts() { - let mut hash = None; - let receipts = vec![validators_change_receipt(Default::default())]; - let receipts_root = compute_merkle_root(receipts.iter().map(|r| r.rlp())); - - assert_eq!( - default_accept_into_pool(|validators| { - let header = HeaderBuilder::with_parent_number(3) - .log_bloom((&[0xff; 256]).into()) - .receipts_root(receipts_root) - .sign_by_set(validators); - hash = Some(header.compute_hash()); - (header, Some(receipts.clone())) - }), - Ok(( - // no tags are required - vec![], - // header provides two tags - vec![(4u64, validators_addresses(3)[1]).encode(), (4u64, hash.unwrap()).encode(),], - )), - ); - } -} diff --git a/primitives/currency-exchange/Cargo.toml b/primitives/currency-exchange/Cargo.toml deleted file mode 100644 index 165891f0c6b1d..0000000000000 --- a/primitives/currency-exchange/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "bp-currency-exchange" -description = "Primitives of currency exchange module." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-support/std", - "scale-info/std", - "sp-api/std", - "sp-std/std", -] diff --git a/primitives/currency-exchange/src/lib.rs b/primitives/currency-exchange/src/lib.rs deleted file mode 100644 index 1a30915b1cbfa..0000000000000 --- a/primitives/currency-exchange/src/lib.rs +++ /dev/null @@ -1,153 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] -// Generated by `DecodeLimit::decode_with_depth_limit` -#![allow(clippy::unnecessary_mut_passed)] - -use codec::{Decode, Encode, EncodeLike}; -use frame_support::{Parameter, RuntimeDebug}; -use scale_info::TypeInfo; -use sp_api::decl_runtime_apis; -use sp_std::marker::PhantomData; - -/// All errors that may happen during exchange. -#[derive(RuntimeDebug, PartialEq)] -pub enum Error { - /// Invalid peer blockchain transaction provided. - InvalidTransaction, - /// Peer transaction has invalid amount. - InvalidAmount, - /// Peer transaction has invalid recipient. - InvalidRecipient, - /// Cannot map from peer recipient to this blockchain recipient. - FailedToMapRecipients, - /// Failed to convert from peer blockchain currency to this blockchain currency. - FailedToConvertCurrency, - /// Deposit has failed. - DepositFailed, - /// Deposit has partially failed (changes to recipient account were made). - DepositPartiallyFailed, -} - -/// Result of all exchange operations. -pub type Result = sp_std::result::Result; - -/// Peer blockchain lock funds transaction. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct LockFundsTransaction { - /// Something that uniquely identifies this transfer. - pub id: TransferId, - /// Funds recipient on the peer chain. - pub recipient: Recipient, - /// Amount of the locked funds. - pub amount: Amount, -} - -/// Peer blockchain transaction that may represent lock funds transaction. -pub trait MaybeLockFundsTransaction { - /// Transaction type. - type Transaction; - /// Identifier that uniquely identifies this transfer. - type Id: Decode + Encode + TypeInfo + EncodeLike + sp_std::fmt::Debug; - /// Peer recipient type. - type Recipient; - /// Peer currency amount type. - type Amount; - - /// Parse lock funds transaction of the peer blockchain. Returns None if - /// transaction format is unknown, or it isn't a lock funds transaction. - fn parse( - tx: &Self::Transaction, - ) -> Result>; -} - -/// Map that maps recipients from peer blockchain to this blockchain recipients. -pub trait RecipientsMap { - /// Peer blockchain recipient type. - type PeerRecipient; - /// Current blockchain recipient type. - type Recipient; - - /// Lookup current blockchain recipient by peer blockchain recipient. - fn map(peer_recipient: Self::PeerRecipient) -> Result; -} - -/// Conversion between two currencies. -pub trait CurrencyConverter { - /// Type of the source currency amount. - type SourceAmount; - /// Type of the target currency amount. - type TargetAmount; - - /// Covert from source to target currency. - fn convert(amount: Self::SourceAmount) -> Result; -} - -/// Currency deposit. -pub trait DepositInto { - /// Recipient type. - type Recipient; - /// Currency amount type. - type Amount; - - /// Grant some money to given account. - fn deposit_into(recipient: Self::Recipient, amount: Self::Amount) -> Result<()>; -} - -/// Recipients map which is used when accounts ids are the same on both chains. -#[derive(Debug)] -pub struct IdentityRecipients(PhantomData); - -impl RecipientsMap for IdentityRecipients { - type PeerRecipient = AccountId; - type Recipient = AccountId; - - fn map(peer_recipient: Self::PeerRecipient) -> Result { - Ok(peer_recipient) - } -} - -/// Currency converter which is used when currency is the same on both chains. -#[derive(Debug)] -pub struct IdentityCurrencyConverter(PhantomData); - -impl CurrencyConverter for IdentityCurrencyConverter { - type SourceAmount = Amount; - type TargetAmount = Amount; - - fn convert(currency: Self::SourceAmount) -> Result { - Ok(currency) - } -} - -decl_runtime_apis! { - /// API for Rialto exchange transactions submitters. - pub trait RialtoCurrencyExchangeApi { - /// Returns true if currency exchange module is able to import transaction proof in - /// its current state. - fn filter_transaction_proof(proof: Proof) -> bool; - } - - /// API for Kovan exchange transactions submitters. - pub trait KovanCurrencyExchangeApi { - /// Returns true if currency exchange module is able to import transaction proof in - /// its current state. - fn filter_transaction_proof(proof: Proof) -> bool; - } -} diff --git a/primitives/ethereum-poa/Cargo.toml b/primitives/ethereum-poa/Cargo.toml deleted file mode 100644 index 71f071bbf0e6d..0000000000000 --- a/primitives/ethereum-poa/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "bp-eth-poa" -description = "Primitives of Ethereum PoA Bridge module." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -ethbloom = { version = "0.10.0", default-features = false, features = ["rlp"] } -fixed-hash = { version = "0.7", default-features = false } -hash-db = { version = "0.15.2", default-features = false } -impl-rlp = { version = "0.3", default-features = false } -impl-serde = { version = "0.3.1", optional = true } -libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac", "static-context"] } -parity-bytes = { version = "0.1", default-features = false } -plain_hasher = { version = "0.2.2", default-features = false } -primitive-types = { version = "0.10", default-features = false, features = ["codec", "rlp"] } -rlp = { version = "0.5", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } -serde-big-array = { version = "0.2", optional = true } -triehash = { version = "0.8.2", default-features = false } - -# Substrate Dependencies - -sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[dev-dependencies] -hex-literal = "0.2" - -[features] -default = ["std"] -std = [ - "codec/std", - "ethbloom/std", - "fixed-hash/std", - "hash-db/std", - "impl-rlp/std", - "impl-serde", - "libsecp256k1/std", - "parity-bytes/std", - "plain_hasher/std", - "primitive-types/std", - "primitive-types/serde", - "rlp/std", - "scale-info/std", - "serde/std", - "serde-big-array", - "sp-api/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "triehash/std", -] diff --git a/primitives/ethereum-poa/src/lib.rs b/primitives/ethereum-poa/src/lib.rs deleted file mode 100644 index 58f5731e52222..0000000000000 --- a/primitives/ethereum-poa/src/lib.rs +++ /dev/null @@ -1,732 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] -// Generated by `DecodeLimit::decode_with_depth_limit` -#![allow(clippy::unnecessary_mut_passed)] - -pub use parity_bytes::Bytes; -pub use primitive_types::{H160, H256, H512, U128, U256}; -pub use rlp::encode as rlp_encode; - -use codec::{Decode, Encode}; -use ethbloom::{Bloom as EthBloom, Input as BloomInput}; -use fixed_hash::construct_fixed_hash; -use rlp::{Decodable, DecoderError, Rlp, RlpStream}; -use scale_info::TypeInfo; -use sp_io::hashing::keccak_256; -use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; - -use impl_rlp::impl_fixed_hash_rlp; -#[cfg(feature = "std")] -use impl_serde::impl_fixed_hash_serde; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -#[cfg(feature = "std")] -use serde_big_array::big_array; - -construct_fixed_hash! { pub struct H520(65); } -impl_fixed_hash_rlp!(H520, 65); -#[cfg(feature = "std")] -impl_fixed_hash_serde!(H520, 65); - -/// Raw (RLP-encoded) ethereum transaction. -pub type RawTransaction = Vec; - -/// Raw (RLP-encoded) ethereum transaction receipt. -pub type RawTransactionReceipt = Vec; - -/// An ethereum address. -pub type Address = H160; - -pub mod signatures; - -/// Complete header id. -#[derive(Encode, Decode, Default, RuntimeDebug, PartialEq, Clone, Copy, TypeInfo)] -pub struct HeaderId { - /// Header number. - pub number: u64, - /// Header hash. - pub hash: H256, -} - -/// An Aura header. -#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct AuraHeader { - /// Parent block hash. - pub parent_hash: H256, - /// Block timestamp. - pub timestamp: u64, - /// Block number. - pub number: u64, - /// Block author. - pub author: Address, - - /// Transactions root. - pub transactions_root: H256, - /// Block uncles hash. - pub uncles_hash: H256, - /// Block extra data. - pub extra_data: Bytes, - - /// State root. - pub state_root: H256, - /// Block receipts root. - pub receipts_root: H256, - /// Block bloom. - pub log_bloom: Bloom, - /// Gas used for contracts execution. - pub gas_used: U256, - /// Block gas limit. - pub gas_limit: U256, - - /// Block difficulty. - pub difficulty: U256, - /// Vector of post-RLP-encoded fields. - pub seal: Vec, -} - -/// Parsed ethereum transaction. -#[derive(PartialEq, RuntimeDebug)] -pub struct Transaction { - /// Sender address. - pub sender: Address, - /// Unsigned portion of ethereum transaction. - pub unsigned: UnsignedTransaction, -} - -/// Unsigned portion of ethereum transaction. -#[derive(Clone, PartialEq, RuntimeDebug)] -pub struct UnsignedTransaction { - /// Sender nonce. - pub nonce: U256, - /// Gas price. - pub gas_price: U256, - /// Gas limit. - pub gas: U256, - /// Transaction destination address. None if it is contract creation transaction. - pub to: Option
, - /// Value. - pub value: U256, - /// Associated data. - pub payload: Bytes, -} - -/// Information describing execution of a transaction. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct Receipt { - /// The total gas used in the block following execution of the transaction. - pub gas_used: U256, - /// The OR-wide combination of all logs' blooms for this transaction. - pub log_bloom: Bloom, - /// The logs stemming from this transaction. - pub logs: Vec, - /// Transaction outcome. - pub outcome: TransactionOutcome, -} - -/// Transaction outcome store in the receipt. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub enum TransactionOutcome { - /// Status and state root are unknown under EIP-98 rules. - Unknown, - /// State root is known. Pre EIP-98 and EIP-658 rules. - StateRoot(H256), - /// Status code is known. EIP-658 rules. - StatusCode(u8), -} - -/// A record of execution for a `LOG` operation. -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct LogEntry { - /// The address of the contract executing at the point of the `LOG` operation. - pub address: Address, - /// The topics associated with the `LOG` operation. - pub topics: Vec, - /// The data associated with the `LOG` operation. - pub data: Bytes, -} - -/// Logs bloom. -#[derive(Clone, Encode, Decode, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Bloom(#[cfg_attr(feature = "std", serde(with = "BigArray"))] [u8; 256]); - -#[cfg(feature = "std")] -big_array! { BigArray; } - -/// An empty step message that is included in a seal, the only difference is that it doesn't include -/// the `parent_hash` in order to save space. The included signature is of the original empty step -/// message, which can be reconstructed by using the parent hash of the block in which this sealed -/// empty message is included. -pub struct SealedEmptyStep { - /// Signature of the original message author. - pub signature: H520, - /// The step this message is generated for. - pub step: u64, -} - -impl AuraHeader { - /// Compute id of this header. - pub fn compute_id(&self) -> HeaderId { - HeaderId { number: self.number, hash: self.compute_hash() } - } - - /// Compute hash of this header (keccak of the RLP with seal). - pub fn compute_hash(&self) -> H256 { - keccak_256(&self.rlp(true)).into() - } - - /// Get id of this header' parent. Returns None if this is genesis header. - pub fn parent_id(&self) -> Option { - self.number - .checked_sub(1) - .map(|parent_number| HeaderId { number: parent_number, hash: self.parent_hash }) - } - - /// Check if passed transactions receipts are matching receipts root in this header. - /// Returns Ok(computed-root) if check succeeds. - /// Returns Err(computed-root) if check fails. - pub fn check_receipts_root(&self, receipts: &[Receipt]) -> Result { - check_merkle_proof(self.receipts_root, receipts.iter().map(|r| r.rlp())) - } - - /// Check if passed raw transactions receipts are matching receipts root in this header. - /// Returns Ok(computed-root) if check succeeds. - /// Returns Err(computed-root) if check fails. - pub fn check_raw_receipts_root<'a>( - &self, - receipts: impl IntoIterator, - ) -> Result { - check_merkle_proof(self.receipts_root, receipts.into_iter()) - } - - /// Check if passed transactions are matching transactions root in this header. - /// Returns Ok(computed-root) if check succeeds. - /// Returns Err(computed-root) if check fails. - pub fn check_transactions_root<'a>( - &self, - transactions: impl IntoIterator, - ) -> Result { - check_merkle_proof(self.transactions_root, transactions.into_iter()) - } - - /// Gets the seal hash of this header. - pub fn seal_hash(&self, include_empty_steps: bool) -> Option { - Some(match include_empty_steps { - true => { - let mut message = self.compute_hash().as_bytes().to_vec(); - message.extend_from_slice(self.seal.get(2)?); - keccak_256(&message).into() - }, - false => keccak_256(&self.rlp(false)).into(), - }) - } - - /// Get step this header is generated for. - pub fn step(&self) -> Option { - self.seal.get(0).map(|x| Rlp::new(x)).and_then(|x| x.as_val().ok()) - } - - /// Get header author' signature. - pub fn signature(&self) -> Option { - self.seal.get(1).and_then(|x| Rlp::new(x).as_val().ok()) - } - - /// Extracts the empty steps from the header seal. - pub fn empty_steps(&self) -> Option> { - self.seal.get(2).and_then(|x| Rlp::new(x).as_list::().ok()) - } - - /// Returns header RLP with or without seals. - fn rlp(&self, with_seal: bool) -> Bytes { - let mut s = RlpStream::new(); - if with_seal { - s.begin_list(13 + self.seal.len()); - } else { - s.begin_list(13); - } - - s.append(&self.parent_hash); - s.append(&self.uncles_hash); - s.append(&self.author); - s.append(&self.state_root); - s.append(&self.transactions_root); - s.append(&self.receipts_root); - s.append(&EthBloom::from(self.log_bloom.0)); - s.append(&self.difficulty); - s.append(&self.number); - s.append(&self.gas_limit); - s.append(&self.gas_used); - s.append(&self.timestamp); - s.append(&self.extra_data); - - if with_seal { - for b in &self.seal { - s.append_raw(b, 1); - } - } - - s.out().to_vec() - } -} - -impl UnsignedTransaction { - /// Decode unsigned portion of raw transaction RLP. - pub fn decode_rlp(raw_tx: &[u8]) -> Result { - let tx_rlp = Rlp::new(raw_tx); - let to = tx_rlp.at(3)?; - Ok(UnsignedTransaction { - nonce: tx_rlp.val_at(0)?, - gas_price: tx_rlp.val_at(1)?, - gas: tx_rlp.val_at(2)?, - to: match to.is_empty() { - false => Some(to.as_val()?), - true => None, - }, - value: tx_rlp.val_at(4)?, - payload: tx_rlp.val_at(5)?, - }) - } - - /// Returns message that has to be signed to sign this transaction. - pub fn message(&self, chain_id: Option) -> H256 { - keccak_256(&self.rlp(chain_id)).into() - } - - /// Returns unsigned transaction RLP. - pub fn rlp(&self, chain_id: Option) -> Bytes { - let mut stream = RlpStream::new_list(if chain_id.is_some() { 9 } else { 6 }); - self.rlp_to(chain_id, &mut stream); - stream.out().to_vec() - } - - /// Encode to given RLP stream. - pub fn rlp_to(&self, chain_id: Option, stream: &mut RlpStream) { - stream.append(&self.nonce); - stream.append(&self.gas_price); - stream.append(&self.gas); - match self.to { - Some(to) => stream.append(&to), - None => stream.append(&""), - }; - stream.append(&self.value); - stream.append(&self.payload); - if let Some(chain_id) = chain_id { - stream.append(&chain_id); - stream.append(&0u8); - stream.append(&0u8); - } - } -} - -impl Receipt { - /// Decode status from raw transaction receipt RLP. - pub fn is_successful_raw_receipt(raw_receipt: &[u8]) -> Result { - let rlp = Rlp::new(raw_receipt); - if rlp.item_count()? == 3 { - // no outcome - invalid tx? - Ok(false) - } else { - let first = rlp.at(0)?; - if first.is_data() && first.data()?.len() <= 1 { - // EIP-658 transaction - status of successful transaction is 1 - let status: u8 = first.as_val()?; - Ok(status == 1) - } else { - // pre-EIP-658 transaction - we do not support this kind of transactions - Ok(false) - } - } - } - - /// Returns receipt RLP. - pub fn rlp(&self) -> Bytes { - let mut s = RlpStream::new(); - match self.outcome { - TransactionOutcome::Unknown => { - s.begin_list(3); - }, - TransactionOutcome::StateRoot(ref root) => { - s.begin_list(4); - s.append(root); - }, - TransactionOutcome::StatusCode(ref status_code) => { - s.begin_list(4); - s.append(status_code); - }, - } - s.append(&self.gas_used); - s.append(&EthBloom::from(self.log_bloom.0)); - - s.begin_list(self.logs.len()); - for log in &self.logs { - s.begin_list(3); - s.append(&log.address); - s.begin_list(log.topics.len()); - for topic in &log.topics { - s.append(topic); - } - s.append(&log.data); - } - - s.out().to_vec() - } -} - -impl SealedEmptyStep { - /// Returns message that has to be signed by the validator. - pub fn message(&self, parent_hash: &H256) -> H256 { - let mut message = RlpStream::new_list(2); - message.append(&self.step); - message.append(parent_hash); - keccak_256(&message.out()).into() - } - - /// Returns RLP for the vector of empty steps (we only do encoding in tests). - pub fn rlp_of(empty_steps: &[SealedEmptyStep]) -> Bytes { - let mut s = RlpStream::new(); - s.begin_list(empty_steps.len()); - for empty_step in empty_steps { - s.begin_list(2).append(&empty_step.signature).append(&empty_step.step); - } - s.out().to_vec() - } -} - -impl Decodable for SealedEmptyStep { - fn decode(rlp: &Rlp) -> Result { - let signature: H520 = rlp.val_at(0)?; - let step = rlp.val_at(1)?; - - Ok(SealedEmptyStep { signature, step }) - } -} - -impl LogEntry { - /// Calculates the bloom of this log entry. - pub fn bloom(&self) -> Bloom { - let eth_bloom = self.topics.iter().fold( - EthBloom::from(BloomInput::Raw(self.address.as_bytes())), - |mut b, t| { - b.accrue(BloomInput::Raw(t.as_bytes())); - b - }, - ); - Bloom(*eth_bloom.data()) - } -} - -impl Bloom { - /// Returns true if this bloom has all bits from the other set. - pub fn contains(&self, other: &Bloom) -> bool { - self.0.iter().zip(other.0.iter()).all(|(l, r)| (l & r) == *r) - } -} - -impl<'a> From<&'a [u8; 256]> for Bloom { - fn from(buffer: &'a [u8; 256]) -> Bloom { - Bloom(*buffer) - } -} - -impl PartialEq for Bloom { - fn eq(&self, other: &Bloom) -> bool { - self.0.iter().zip(other.0.iter()).all(|(l, r)| l == r) - } -} - -// there's no default for [_; 256], but clippy still complains -#[allow(clippy::derivable_impls)] -impl Default for Bloom { - fn default() -> Self { - Bloom([0; 256]) - } -} - -#[cfg(feature = "std")] -impl std::fmt::Debug for Bloom { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.debug_struct("Bloom").finish() - } -} - -/// Decode Ethereum transaction. -pub fn transaction_decode_rlp(raw_tx: &[u8]) -> Result { - // parse transaction fields - let unsigned = UnsignedTransaction::decode_rlp(raw_tx)?; - let tx_rlp = Rlp::new(raw_tx); - let v: u64 = tx_rlp.val_at(6)?; - let r: U256 = tx_rlp.val_at(7)?; - let s: U256 = tx_rlp.val_at(8)?; - - // reconstruct signature - let mut signature = [0u8; 65]; - let (chain_id, v) = match v { - v if v == 27u64 => (None, 0), - v if v == 28u64 => (None, 1), - v if v >= 35u64 => (Some((v - 35) / 2), ((v - 1) % 2) as u8), - _ => (None, 4), - }; - r.to_big_endian(&mut signature[0..32]); - s.to_big_endian(&mut signature[32..64]); - signature[64] = v; - - // reconstruct message that has been signed - let message = unsigned.message(chain_id); - - // recover tx sender - let sender_public = - sp_io::crypto::secp256k1_ecdsa_recover(&signature, message.as_fixed_bytes()) - .map_err(|_| rlp::DecoderError::Custom("Failed to recover transaction sender"))?; - let sender_address = public_to_address(&sender_public); - - Ok(Transaction { sender: sender_address, unsigned }) -} - -/// Convert public key into corresponding ethereum address. -pub fn public_to_address(public: &[u8; 64]) -> Address { - let hash = keccak_256(public); - let mut result = Address::zero(); - result.as_bytes_mut().copy_from_slice(&hash[12..]); - result -} - -/// Check ethereum merkle proof. -/// Returns Ok(computed-root) if check succeeds. -/// Returns Err(computed-root) if check fails. -fn check_merkle_proof>( - expected_root: H256, - items: impl Iterator, -) -> Result { - let computed_root = compute_merkle_root(items); - if computed_root == expected_root { - Ok(computed_root) - } else { - Err(computed_root) - } -} - -/// Compute ethereum merkle root. -pub fn compute_merkle_root>(items: impl Iterator) -> H256 { - struct Keccak256Hasher; - - impl hash_db::Hasher for Keccak256Hasher { - type Out = H256; - type StdHasher = plain_hasher::PlainHasher; - const LENGTH: usize = 32; - fn hash(x: &[u8]) -> Self::Out { - keccak_256(x).into() - } - } - - triehash::ordered_trie_root::(items) -} - -/// Get validator that should author the block at given step. -pub fn step_validator(header_validators: &[T], header_step: u64) -> &T { - &header_validators[(header_step % header_validators.len() as u64) as usize] -} - -sp_api::decl_runtime_apis! { - /// API for querying information about headers from the Rialto Bridge Pallet - pub trait RialtoPoAHeaderApi { - /// Returns number and hash of the best block known to the bridge module. - /// - /// The caller should only submit an `import_header` transaction that makes - /// (or leads to making) other header the best one. - fn best_block() -> (u64, H256); - /// Returns number and hash of the best finalized block known to the bridge module. - fn finalized_block() -> (u64, H256); - /// Returns true if the import of given block requires transactions receipts. - fn is_import_requires_receipts(header: AuraHeader) -> bool; - /// Returns true if header is known to the runtime. - fn is_known_block(hash: H256) -> bool; - } - - /// API for querying information about headers from the Kovan Bridge Pallet - pub trait KovanHeaderApi { - /// Returns number and hash of the best block known to the bridge module. - /// - /// The caller should only submit an `import_header` transaction that makes - /// (or leads to making) other header the best one. - fn best_block() -> (u64, H256); - /// Returns number and hash of the best finalized block known to the bridge module. - fn finalized_block() -> (u64, H256); - /// Returns true if the import of given block requires transactions receipts. - fn is_import_requires_receipts(header: AuraHeader) -> bool; - /// Returns true if header is known to the runtime. - fn is_known_block(hash: H256) -> bool; - } -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - - #[test] - fn transfer_transaction_decode_works() { - // value transfer transaction - // https://etherscan.io/tx/0xb9d4ad5408f53eac8627f9ccd840ba8fb3469d55cd9cc2a11c6e049f1eef4edd - // https://etherscan.io/getRawTx?tx=0xb9d4ad5408f53eac8627f9ccd840ba8fb3469d55cd9cc2a11c6e049f1eef4edd - let raw_tx = hex!("f86c0a85046c7cfe0083016dea94d1310c1e038bc12865d3d3997275b3e4737c6302880b503be34d9fe80080269fc7eaaa9c21f59adf8ad43ed66cf5ef9ee1c317bd4d32cd65401e7aaca47cfaa0387d79c65b90be6260d09dcfb780f29dd8133b9b1ceb20b83b7e442b4bfc30cb"); - assert_eq!( - transaction_decode_rlp(&raw_tx), - Ok(Transaction { - sender: hex!("67835910d32600471f388a137bbff3eb07993c04").into(), - unsigned: UnsignedTransaction { - nonce: 10.into(), - gas_price: 19000000000u64.into(), - gas: 93674.into(), - to: Some(hex!("d1310c1e038bc12865d3d3997275b3e4737c6302").into()), - value: 815217380000000000_u64.into(), - payload: Default::default(), - } - }), - ); - - // Kovan value transfer transaction - // https://kovan.etherscan.io/tx/0x3b4b7bd41c1178045ccb4753aa84c1ef9864b4d712fa308b228917cd837915da - // https://kovan.etherscan.io/getRawTx?tx=0x3b4b7bd41c1178045ccb4753aa84c1ef9864b4d712fa308b228917cd837915da - let raw_tx = hex!("f86a822816808252089470c1ccde719d6f477084f07e4137ab0e55f8369f8930cf46e92063afd8008078a00e4d1f4d8aa992bda3c105ff3d6e9b9acbfd99facea00985e2131029290adbdca028ea29a46a4b66ec65b454f0706228e3768cb0ecf755f67c50ddd472f11d5994"); - assert_eq!( - transaction_decode_rlp(&raw_tx), - Ok(Transaction { - sender: hex!("faadface3fbd81ce37b0e19c0b65ff4234148132").into(), - unsigned: UnsignedTransaction { - nonce: 10262.into(), - gas_price: 0.into(), - gas: 21000.into(), - to: Some(hex!("70c1ccde719d6f477084f07e4137ab0e55f8369f").into()), - value: 900379597077600000000_u128.into(), - payload: Default::default(), - }, - }), - ); - } - - #[test] - fn payload_transaction_decode_works() { - // contract call transaction - // https://etherscan.io/tx/0xdc2b996b4d1d6922bf6dba063bfd70913279cb6170967c9bb80252aeb061cf65 - // https://etherscan.io/getRawTx?tx=0xdc2b996b4d1d6922bf6dba063bfd70913279cb6170967c9bb80252aeb061cf65 - let raw_tx = hex!("f8aa76850430e234008301500094dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b4025a0964e023999621dc3d4d831c43c71f7555beb6d1192dee81a3674b3f57e310f21a00f229edd86f841d1ee4dc48cc16667e2283817b1d39bae16ced10cd206ae4fd4"); - assert_eq!( - transaction_decode_rlp(&raw_tx), - Ok(Transaction { - sender: hex!("2b9a4d37bdeecdf994c4c9ad7f3cf8dc632f7d70").into(), - unsigned: UnsignedTransaction { - nonce: 118.into(), - gas_price: 18000000000u64.into(), - gas: 86016.into(), - to: Some(hex!("dac17f958d2ee523a2206206994597c13d831ec7").into()), - value: 0.into(), - payload: hex!("a9059cbb000000000000000000000000e08f35f66867a454835b25118f1e490e7f9e9a7400000000000000000000000000000000000000000000000000000000004c4b40").to_vec(), - }, - }), - ); - - // Kovan contract call transaction - // https://kovan.etherscan.io/tx/0x2904b4451d23665492239016b78da052d40d55fdebc7304b38e53cf6a37322cf - // https://kovan.etherscan.io/getRawTx?tx=0x2904b4451d23665492239016b78da052d40d55fdebc7304b38e53cf6a37322cf - let raw_tx = hex!("f8ac8302200b843b9aca00830271009484dd11eb2a29615303d18149c0dbfa24167f896680b844a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b600000000000000000000000000000000000000000000000000000000000027101ba0ce126d2cca81f5e245f292ff84a0d915c0a4ac52af5c51219db1e5d36aa8da35a0045298b79dac631907403888f9b04c2ab5509fe0cc31785276d30a40b915fcf9"); - assert_eq!( - transaction_decode_rlp(&raw_tx), - Ok(Transaction { - sender: hex!("617da121abf03d4c1af572f5a4e313e26bef7bdc").into(), - unsigned: UnsignedTransaction { - nonce: 139275.into(), - gas_price: 1000000000.into(), - gas: 160000.into(), - to: Some(hex!("84dd11eb2a29615303d18149c0dbfa24167f8966").into()), - value: 0.into(), - payload: hex!("a9059cbb00000000000000000000000001503dfc5ad81bf630d83697e98601871bb211b60000000000000000000000000000000000000000000000000000000000002710").to_vec(), - }, - }), - ); - } - - #[test] - fn is_successful_raw_receipt_works() { - assert!(Receipt::is_successful_raw_receipt(&[]).is_err()); - - assert_eq!( - Receipt::is_successful_raw_receipt( - &Receipt { - outcome: TransactionOutcome::Unknown, - gas_used: Default::default(), - log_bloom: Default::default(), - logs: Vec::new(), - } - .rlp() - ), - Ok(false), - ); - assert_eq!( - Receipt::is_successful_raw_receipt( - &Receipt { - outcome: TransactionOutcome::StateRoot(Default::default()), - gas_used: Default::default(), - log_bloom: Default::default(), - logs: Vec::new(), - } - .rlp() - ), - Ok(false), - ); - assert_eq!( - Receipt::is_successful_raw_receipt( - &Receipt { - outcome: TransactionOutcome::StatusCode(0), - gas_used: Default::default(), - log_bloom: Default::default(), - logs: Vec::new(), - } - .rlp() - ), - Ok(false), - ); - assert_eq!( - Receipt::is_successful_raw_receipt( - &Receipt { - outcome: TransactionOutcome::StatusCode(1), - gas_used: Default::default(), - log_bloom: Default::default(), - logs: Vec::new(), - } - .rlp() - ), - Ok(true), - ); - } - - #[test] - fn is_successful_raw_receipt_with_empty_data() { - let mut stream = RlpStream::new(); - stream.begin_list(4); - stream.append_empty_data(); - stream.append(&1u64); - stream.append(&2u64); - stream.append(&3u64); - - assert_eq!(Receipt::is_successful_raw_receipt(&stream.out()), Ok(false),); - } -} diff --git a/primitives/ethereum-poa/src/signatures.rs b/primitives/ethereum-poa/src/signatures.rs deleted file mode 100644 index 26371f2166ad5..0000000000000 --- a/primitives/ethereum-poa/src/signatures.rs +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2020-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 . -// - -//! Helpers related to signatures. -//! -//! Used for testing and benchmarking. - -// reexport to avoid direct secp256k1 deps by other crates -pub use libsecp256k1::SecretKey; - -use crate::{ - public_to_address, rlp_encode, step_validator, Address, AuraHeader, RawTransaction, - UnsignedTransaction, H256, H520, U256, -}; - -use libsecp256k1::{Message, PublicKey}; - -/// Utilities for signing headers. -pub trait SignHeader { - /// Signs header by given author. - fn sign_by(self, author: &SecretKey) -> AuraHeader; - /// Signs header by given authors set. - fn sign_by_set(self, authors: &[SecretKey]) -> AuraHeader; -} - -/// Utilities for signing transactions. -pub trait SignTransaction { - /// Sign transaction by given author. - fn sign_by(self, author: &SecretKey, chain_id: Option) -> RawTransaction; -} - -impl SignHeader for AuraHeader { - fn sign_by(mut self, author: &SecretKey) -> Self { - self.author = secret_to_address(author); - - let message = self.seal_hash(false).unwrap(); - let signature = sign(author, message); - self.seal[1] = rlp_encode(&signature).to_vec(); - self - } - - fn sign_by_set(self, authors: &[SecretKey]) -> Self { - let step = self.step().unwrap(); - let author = step_validator(authors, step); - self.sign_by(author) - } -} - -impl SignTransaction for UnsignedTransaction { - fn sign_by(self, author: &SecretKey, chain_id: Option) -> RawTransaction { - let message = self.message(chain_id); - let signature = sign(author, message); - let signature_r = U256::from_big_endian(&signature.as_fixed_bytes()[..32][..]); - let signature_s = U256::from_big_endian(&signature.as_fixed_bytes()[32..64][..]); - let signature_v = signature.as_fixed_bytes()[64] as u64; - let signature_v = signature_v + if let Some(n) = chain_id { 35 + n * 2 } else { 27 }; - - let mut stream = rlp::RlpStream::new_list(9); - self.rlp_to(None, &mut stream); - stream.append(&signature_v); - stream.append(&signature_r); - stream.append(&signature_s); - stream.out().to_vec() - } -} - -/// Return author's signature over given message. -pub fn sign(author: &SecretKey, message: H256) -> H520 { - let (signature, recovery_id) = - libsecp256k1::sign(&Message::parse(message.as_fixed_bytes()), author); - let mut raw_signature = [0u8; 65]; - raw_signature[..64].copy_from_slice(&signature.serialize()); - raw_signature[64] = recovery_id.serialize(); - raw_signature.into() -} - -/// Returns address corresponding to given secret key. -pub fn secret_to_address(secret: &SecretKey) -> Address { - let public = PublicKey::from_secret_key(secret); - let mut raw_public = [0u8; 64]; - raw_public.copy_from_slice(&public.serialize()[1..]); - public_to_address(&raw_public) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{transaction_decode_rlp, Transaction}; - - #[test] - fn transaction_signed_properly() { - // case1: with chain_id replay protection + to - let signer = SecretKey::parse(&[1u8; 32]).unwrap(); - let signer_address = secret_to_address(&signer); - let unsigned = UnsignedTransaction { - nonce: 100.into(), - gas_price: 200.into(), - gas: 300.into(), - to: Some([42u8; 20].into()), - value: 400.into(), - payload: vec![1, 2, 3], - }; - let raw_tx = unsigned.clone().sign_by(&signer, Some(42)); - assert_eq!( - transaction_decode_rlp(&raw_tx), - Ok(Transaction { sender: signer_address, unsigned }), - ); - - // case2: without chain_id replay protection + contract creation - let unsigned = UnsignedTransaction { - nonce: 100.into(), - gas_price: 200.into(), - gas: 300.into(), - to: None, - value: 400.into(), - payload: vec![1, 2, 3], - }; - let raw_tx = unsigned.clone().sign_by(&signer, None); - assert_eq!( - transaction_decode_rlp(&raw_tx), - Ok(Transaction { sender: signer_address, unsigned }), - ); - } -} diff --git a/relays/bin-ethereum/Cargo.toml b/relays/bin-ethereum/Cargo.toml deleted file mode 100644 index 610dee2c3ce99..0000000000000 --- a/relays/bin-ethereum/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "ethereum-poa-relay" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -anyhow = "1.0" -async-std = "1.9.0" -async-trait = "0.1.42" -clap = { version = "2.33.3", features = ["yaml"] } -codec = { package = "parity-scale-codec", version = "2.2.0" } -ethabi = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } -ethabi-contract = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } -ethabi-derive = { git = "https://github.com/svyatonik/ethabi.git", branch = "bump-deps" } -futures = "0.3.12" -hex = "0.4" -hex-literal = "0.3" -libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"] } -log = "0.4.14" -num-traits = "0.2" -serde_json = "1.0.64" -thiserror = "1.0.26" - -# Bridge dependencies - -bp-currency-exchange = { path = "../../primitives/currency-exchange" } -bp-eth-poa = { path = "../../primitives/ethereum-poa" } -exchange-relay = { path = "../exchange" } -headers-relay = { path = "../headers" } -relay-ethereum-client = { path = "../client-ethereum" } -relay-rialto-client = { path = "../client-rialto" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } -rialto-runtime = { path = "../../bin/rialto/runtime" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-ethereum/README.md b/relays/bin-ethereum/README.md deleted file mode 100644 index 9fe2f623fd05a..0000000000000 --- a/relays/bin-ethereum/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# PoA <> Substrate Bridge - -**DISCLAIMER:** *we recommend not using the bridge in "production" (to bridge significant amounts) just yet. -it's missing a code audit and should still be considered alpha. we can't rule out that there are bugs that might result in loss of the bridged amounts. -we'll update this disclaimer once that changes* - -These docs are very incomplete yet. Describe high-level goals here in the (near) future. diff --git a/relays/bin-ethereum/res/substrate-bridge-abi.json b/relays/bin-ethereum/res/substrate-bridge-abi.json deleted file mode 100644 index b7d7b4b9152cd..0000000000000 --- a/relays/bin-ethereum/res/substrate-bridge-abi.json +++ /dev/null @@ -1,167 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "rawInitialHeader", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "initialValidatorsSetId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "initialValidatorsSet", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "inputs": [], - "name": "bestKnownHeader", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "finalityTargetNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "finalityTargetHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "rawFinalityProof", - "type": "bytes" - } - ], - "name": "importFinalityProof", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "rawHeader1", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawHeader2", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawHeader3", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawHeader4", - "type": "bytes" - } - ], - "name": "importHeaders", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "incompleteHeaders", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "rawHeader1", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawHeader2", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawHeader3", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawHeader4", - "type": "bytes" - } - ], - "name": "isIncompleteHeaders", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "headerHash", - "type": "bytes32" - } - ], - "name": "isKnownHeader", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/relays/bin-ethereum/res/substrate-bridge-bytecode.hex b/relays/bin-ethereum/res/substrate-bridge-bytecode.hex deleted file mode 100644 index 6dd6a33046f6c..0000000000000 --- a/relays/bin-ethereum/res/substrate-bridge-bytecode.hex +++ /dev/null @@ -1 +0,0 @@ -60806040523480156200001157600080fd5b5060405162001af838038062001af8833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82516401000000008111828201881017156200008957600080fd5b82525081516020918201929091019080838360005b83811015620000b85781810151838201526020016200009e565b50505050905090810190601f168015620000e65780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200010f57600080fd5b9083019060208201858111156200012557600080fd5b82516401000000008111828201881017156200014057600080fd5b82525081516020918201929091019080838360005b838110156200016f57818101518382015260200162000155565b50505050905090810190601f1680156200019d5780820380516001836020036101000a031916815260200191505b50604052505050620001ae620003d5565b620001c2846001600160e01b03620002dc16565b805160008181556002918255604080840180516001908155825160e08101845281815260208088015181830190815293518286019081526080808a0151606085019081526001600160401b038e169185019190915260a0840188905260c084018890528951885260078352959096208251815460ff191690151517815593519284019290925593519482019490945590518051949550919390926200026f9260038501929101906200040a565b506080820151600482810180546001600160401b03199081166001600160401b039485161790915560a0850151600585015560c09094015160069093019290925560038054909316908616179091558251620002d1919060208501906200040a565b5050505050620004af565b620002e6620003d5565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa6200031c57600080fd5b84519b5083519a50825199508151985080519750505050505050506060816001600160401b03811180156200035057600080fd5b506040519080825280601f01601f1916602001820160405280156200037c576020820181803683370190505b5090508115620003a85787516020890160208301848184846011600019fa620003a457600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200044d57805160ff19168380011785556200047d565b828001600101855582156200047d579182015b828111156200047d57825182559160200191906001019062000460565b506200048b9291506200048f565b5090565b620004ac91905b808211156200048b576000815560010162000496565b90565b61163980620004bf6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063374c2c26146100675780636a742c0914610108578063871ebe181461033d578063d96a2deb1461036e578063e8ffbe841461038f578063fae71ae8146105d4575b600080fd5b61006f610684565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100b357818101518382015260200161009b565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156100f25781810151838201526020016100da565b5050505090500194505050505060405180910390f35b61033b6004803603608081101561011e57600080fd5b810190602081018135600160201b81111561013857600080fd5b82018360208201111561014a57600080fd5b803590602001918460018302840111600160201b8311171561016b57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156101bd57600080fd5b8201836020820111156101cf57600080fd5b803590602001918460018302840111600160201b831117156101f057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561024257600080fd5b82018360208201111561025457600080fd5b803590602001918460018302840111600160201b8311171561027557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156102c757600080fd5b8201836020820111156102d957600080fd5b803590602001918460018302840111600160201b831117156102fa57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610789945050505050565b005b61035a6004803603602081101561035357600080fd5b50356107e5565b604080519115158252519081900360200190f35b6103766107fd565b6040805192835260208301919091528051918290030190f35b6105c2600480360360808110156103a557600080fd5b810190602081018135600160201b8111156103bf57600080fd5b8201836020820111156103d157600080fd5b803590602001918460018302840111600160201b831117156103f257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561044457600080fd5b82018360208201111561045657600080fd5b803590602001918460018302840111600160201b8311171561047757600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156104c957600080fd5b8201836020820111156104db57600080fd5b803590602001918460018302840111600160201b831117156104fc57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561054e57600080fd5b82018360208201111561056057600080fd5b803590602001918460018302840111600160201b8311171561058157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610815945050505050565b60408051918252519081900360200190f35b61033b600480360360608110156105ea57600080fd5b813591602081013591810190606081016040820135600160201b81111561061057600080fd5b82018360208201111561062257600080fd5b803590602001918460018302840111600160201b8311171561064357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610b28945050505050565b6005546060908190818167ffffffffffffffff811180156106a457600080fd5b506040519080825280602002602001820160405280156106ce578160200160208202803683370190505b50905060005b828110156107295760076000600583815481106106ed57fe5b906000526020600020015481526020019081526020016000206002015482828151811061071657fe5b60209081029190910101526001016106d4565b508060058080548060200260200160405190810160405280929190818152602001828054801561077857602002820191906000526020600020905b815481526020019060010190808311610764575b505050505090509350935050509091565b61079284610d8d565b61079b576107df565b8251156107b4576107ab83610d8d565b6107b4576107df565b8151156107cd576107c482610d8d565b6107cd576107df565b8051156107df576107dd81610d8d565b505b50505050565b60008181526007602052604090205460ff165b919050565b60008054808252600760205260409091206002015491565b600061081f611454565b61082886610f0e565b9050610832611489565b602082810151600090815260078252604090819020815160e081018352815460ff1615158152600180830154828601526002808401548386015260038401805486516101009482161594909402600019011691909104601f81018790048702830187019095528482529194929360608601939192918301828280156108f85780601f106108cd576101008083540402835291602001916108f8565b820191906000526020600020905b8154815290600101906020018083116108db57829003601f168201915b5050509183525050600482015467ffffffffffffffff1660208201526005820154604082015260069091015460609091015290506000806109398484611001565b945050505091506000600681111561094d57fe5b82600681111561095957fe5b146109ab576040805162461bcd60e51b815260206004820152601860248201527f43616e277420696d706f727420616e7920686561646572730000000000000000604482015290519081900360640190fd5b83604001518114156109c4576001945050505050610b20565b87516109d7576000945050505050610b20565b6109df611489565b6109e98585611171565b90506109f3611454565b6109fc8a610f0e565b90506000610a0a8284611001565b9450505050508160400151811415610a2c576002975050505050505050610b20565b8951610a42576000975050505050505050610b20565b610a4a611489565b610a548388611171565b9050610a5e611454565b610a678c610f0e565b90506000610a758284611001565b9450505050508160400151811415610a9a5760039a5050505050505050505050610b20565b8b51610ab35760009a5050505050505050505050610b20565b610abb611489565b610ac5838b611171565b9050610acf611454565b610ad88e610f0e565b90506000610ae68284611001565b9450505050508160400151811415610b0e5760049d5050505050505050505050505050610b20565b60009d50505050505050505050505050505b949350505050565b6000828152600760205260409020600201548314610b775760405162461bcd60e51b815260040180806020018281038252602f8152602001806115d5602f913960400191505060405180910390fd5b60028054600354600480546040805160206101006001851615026000190190931696909604601f81018390048302870183019091528086529394600094610c28948a948a9467ffffffffffffffff90921693929091830182828015610c1d5780601f10610bf257610100808354040283529160200191610c1d565b820191906000526020600020905b815481529060010190602001808311610c0057829003601f168201915b5050505050876111d0565b600081815260076020526040902060028281558101546001559091505b828214610d8557506000818152600760209081526040808320600181015460069093529220549092908015610d07576005546000199182019181018214610cd357600060056001830381548110610c9857fe5b906000526020600020015490508060058481548110610cb357fe5b600091825260208083209091019290925591825260069052604090208290555b6005805480610cde57fe5b600082815260208082208301600019908101839055909201909255848252600690526040812055505b826006015483600201541415610d7e57600583015460009081526007602052604090206003805467ffffffffffffffff198116600167ffffffffffffffff92831681019092161782559082018054610d759260049291600261010092821615929092026000190116046114c4565b50505050610d85565b5050610c45565b505050505050565b600080610d98611454565b6000806000610da687611312565b9398509196509450925090506000856006811115610dc057fe5b14610dd3576000955050505050506107f8565b604084015181148015610e27576005805486516001820180845560009384527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0909201558651825260066020526040909120555b6040805160e0810182526001808252602088810151818401908152898501518486019081526080808c01516060870190815267ffffffffffffffff8c169187019190915260a086018a905260c086018990528b51600090815260078552969096208551815460ff1916901515178155915193820193909355915160028301559251805192939192610ebe9260038501920190611549565b50608082015160048201805467ffffffffffffffff191667ffffffffffffffff90921691909117905560a0820151600582015560c090910151600690910155935160005550509015949350505050565b610f16611454565b60008060008060008651602088016040516020810160208101602081016020810160a08588886010600019fa610f4b57600080fd5b84519b5083519a508251995081519850805197505050505050505060608167ffffffffffffffff81118015610f7f57600080fd5b506040519080825280601f01601f191660200182016040528015610faa576020820181803683370190505b5090508115610fd45787516020890160208301848184846011600019fa610fd057600080fd5b5050505b6040805160a081018252968752602087019590955293850192909252606084015250608082015292915050565b600061100b611454565b83516000908152600760205260408120548190819060ff161561103d5750600193508592506000915081905080611167565b60015487604001511161105f5750600293508592506000915081905080611167565b8551158061107857506001876040015103866040015114155b156110925750600393508592506000915081905080611167565b60c0860151158015906110ac575085604001518660c00151145b156110d3578660200151600254146110d35750600493508592506000915081905080611167565b60808087015160a088015160c0890151928a01515191929091156111585767ffffffffffffffff838116141561111d57506005965088955060009450849350839250611167915050565b8960400151811061114257506006965088955060009450849350839250611167915050565b50508751606089015160408a0151600190930192015b60009750899650919450925090505b9295509295909350565b611179611489565b506040805160e08101825260018082528451602083015293820151909301908301526060818101519083015260808082015167ffffffffffffffff169083015260a0808201519083015260c0908101519082015290565b600060608686868686604051602001808681526020018581526020018467ffffffffffffffff1667ffffffffffffffff1681526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561124357818101518382015260200161122b565b50505050905090810190601f1680156112705780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156112a357818101518382015260200161128b565b50505050905090810190601f1680156112d05780820380516001836020036101000a031916815260200191505b50975050505050505050604051602081830303815290604052905080516020820160008083836012600019fa61130557600080fd5b5095979650505050505050565b600061131c611454565b6000806000611329611454565b61133287610f0e565b905061133c611489565b602082810151600090815260078252604090819020815160e081018352815460ff1615158152600180830154828601526002808401548386015260038401805486516101009482161594909402600019011691909104601f81018790048702830187019095528482529194929360608601939192918301828280156114025780601f106113d757610100808354040283529160200191611402565b820191906000526020600020905b8154815290600101906020018083116113e557829003601f168201915b5050509183525050600482015467ffffffffffffffff1660208201526005820154604082015260069091015460609091015290506114408282611001565b939c929b5090995097509095509350505050565b6040518060a0016040528060008019168152602001600080191681526020016000815260200160008152602001606081525090565b6040805160e0810182526000808252602082018190529181018290526060808201526080810182905260a0810182905260c081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114fd5780548555611539565b8280016001018555821561153957600052602060002091601f016020900482015b8281111561153957825482559160010191906001019061151e565b506115459291506115b7565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061158a57805160ff1916838001178555611539565b82800160010185558215611539579182015b8281111561153957825182559160200191906001019061159c565b6115d191905b8082111561154557600081556001016115bd565b9056fe4d697373696e672066696e616c69747920746172676574206865616465722066726f6d207468652073746f72616765a2646970667358221220edcaec08f93f74ce5be00b81da5d6b2276138571a33f1cfdca50e5047f854e6e64736f6c63430006060033 \ No newline at end of file diff --git a/relays/bin-ethereum/res/substrate-bridge-metadata.txt b/relays/bin-ethereum/res/substrate-bridge-metadata.txt deleted file mode 100644 index 13b7daa9a8b8b..0000000000000 --- a/relays/bin-ethereum/res/substrate-bridge-metadata.txt +++ /dev/null @@ -1,5 +0,0 @@ -Last Change Date: 2020-07-30 -Solc version: 0.6.6+commit.6c089d02.Linux.g++ -Source hash (keccak256): 0xea5d6d744f69157adc2857166792aca139c0b5b186ba89c1011358fbcad90d7e -Source gist: https://github.com/svyatonik/substrate-bridge-sol/blob/6456d3e016c95cd5e6d5e817c23e9e69e739aa78/substrate-bridge.sol -Compiler flags used (command to produce the file): `docker run -i ethereum/solc:0.6.6 --optimize --bin - < substrate-bridge.sol` \ No newline at end of file diff --git a/relays/bin-ethereum/src/cli.yml b/relays/bin-ethereum/src/cli.yml deleted file mode 100644 index 78971787c0e2b..0000000000000 --- a/relays/bin-ethereum/src/cli.yml +++ /dev/null @@ -1,166 +0,0 @@ -name: ethsub-bridge -version: "0.1.0" -author: Parity Technologies -about: Parity Ethereum (PoA) <-> Substrate bridge -subcommands: - - eth-to-sub: - about: Synchronize headers from Ethereum node to Substrate node. - args: - - eth-host: ð-host - long: eth-host - value_name: ETH_HOST - help: Connect to Ethereum node websocket server at given host. - takes_value: true - - eth-port: ð-port - long: eth-port - value_name: ETH_PORT - help: Connect to Ethereum node websocket server at given port. - takes_value: true - - sub-host: &sub-host - long: sub-host - value_name: SUB_HOST - help: Connect to Substrate node websocket server at given host. - takes_value: true - - sub-port: &sub-port - long: sub-port - value_name: SUB_PORT - help: Connect to Substrate node websocket server at given port. - takes_value: true - - sub-tx-mode: - long: sub-tx-mode - value_name: MODE - help: Submit headers using signed (default) or unsigned transactions. Third mode - backup - submits signed transactions only when we believe that sync has stalled. - takes_value: true - possible_values: - - signed - - unsigned - - backup - - sub-signer: &sub-signer - long: sub-signer - value_name: SUB_SIGNER - help: The SURI of secret key to use when transactions are submitted to the Substrate node. - - sub-signer-password: &sub-signer-password - long: sub-signer-password - value_name: SUB_SIGNER_PASSWORD - help: The password for the SURI of secret key to use when transactions are submitted to the Substrate node. - - sub-pallet-instance: &sub-pallet-instance - long: instance - short: i - value_name: PALLET_INSTANCE - help: The instance of the bridge pallet the relay should follow. - takes_value: true - case_insensitive: true - possible_values: - - Rialto - - Kovan - default_value: Rialto - - no-prometheus: &no-prometheus - long: no-prometheus - help: Do not expose a Prometheus metric endpoint. - - prometheus-host: &prometheus-host - long: prometheus-host - value_name: PROMETHEUS_HOST - help: Expose Prometheus endpoint at given interface. - - prometheus-port: &prometheus-port - long: prometheus-port - value_name: PROMETHEUS_PORT - help: Expose Prometheus endpoint at given port. - - sub-to-eth: - about: Synchronize headers from Substrate node to Ethereum node. - args: - - eth-host: *eth-host - - eth-port: *eth-port - - eth-contract: - long: eth-contract - value_name: ETH_CONTRACT - help: Address of deployed bridge contract. - takes_value: true - - eth-chain-id: ð-chain-id - long: eth-chain-id - value_name: ETH_CHAIN_ID - help: Chain ID to use for signing. - - eth-signer: ð-signer - long: eth-signer - value_name: ETH_SIGNER - help: Hex-encoded secret to use when transactions are submitted to the Ethereum node. - - sub-host: *sub-host - - sub-port: *sub-port - - no-prometheus: *no-prometheus - - prometheus-host: *prometheus-host - - prometheus-port: *prometheus-port - - eth-deploy-contract: - about: Deploy Bridge contract on Ethereum node. - args: - - eth-host: *eth-host - - eth-port: *eth-port - - eth-signer: *eth-signer - - eth-chain-id: *eth-chain-id - - eth-contract-code: - long: eth-contract-code - value_name: ETH_CONTRACT_CODE - help: Bytecode of bridge contract. - takes_value: true - - sub-host: *sub-host - - sub-port: *sub-port - - sub-authorities-set-id: - long: sub-authorities-set-id - value_name: SUB_AUTHORITIES_SET_ID - help: ID of initial GRANDPA authorities set. - takes_value: true - - sub-authorities-set: - long: sub-authorities-set - value_name: SUB_AUTHORITIES_SET - help: Encoded initial GRANDPA authorities set. - takes_value: true - - sub-initial-header: - long: sub-initial-header - value_name: SUB_INITIAL_HEADER - help: Encoded initial Substrate header. - takes_value: true - - eth-submit-exchange-tx: - about: Submit lock funds transaction to Ethereum node. - args: - - eth-host: *eth-host - - eth-port: *eth-port - - eth-nonce: - long: eth-nonce - value_name: ETH_NONCE - help: Nonce that have to be used when building transaction. If not specified, read from PoA node. - takes_value: true - - eth-signer: *eth-signer - - eth-chain-id: *eth-chain-id - - eth-amount: - long: eth-amount - value_name: ETH_AMOUNT - help: Amount of ETH to lock (in wei). - takes_value: true - - sub-recipient: - long: sub-recipient - value_name: SUB_RECIPIENT - help: Hex-encoded Public key of funds recipient in Substrate chain. - takes_value: true - - eth-exchange-sub: - about: Submit proof of PoA lock funds transaction to Substrate node. - args: - - eth-host: *eth-host - - eth-port: *eth-port - - eth-start-with-block: - long: eth-start-with-block - value_name: ETH_START_WITH_BLOCK - help: Auto-relay transactions starting with given block number. If not specified, starts with best finalized Ethereum block (known to Substrate node) transactions. - takes_value: true - conflicts_with: - - eth-tx-hash - - eth-tx-hash: - long: eth-tx-hash - value_name: ETH_TX_HASH - help: Hash of the lock funds transaction. - takes_value: true - - sub-host: *sub-host - - sub-port: *sub-port - - sub-signer: *sub-signer - - sub-signer-password: *sub-signer-password - - sub-pallet-instance: *sub-pallet-instance - - no-prometheus: *no-prometheus - - prometheus-host: *prometheus-host - - prometheus-port: *prometheus-port diff --git a/relays/bin-ethereum/src/error.rs b/relays/bin-ethereum/src/error.rs deleted file mode 100644 index 61ae2a9a498dc..0000000000000 --- a/relays/bin-ethereum/src/error.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 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 . - -use crate::rpc_errors::RpcError; -use thiserror::Error; - -/// Result type used by PoA relay. -pub type Result = std::result::Result; - -/// Ethereum PoA relay errors. -#[derive(Error, Debug)] -pub enum Error { - /// Failed to decode initial header. - #[error("Error decoding initial header: {0}")] - DecodeInitialHeader(codec::Error), - /// RPC error. - #[error("{0}")] - Rpc(#[from] RpcError), - /// Failed to read genesis header. - #[error("Error reading Substrate genesis header: {0:?}")] - ReadGenesisHeader(relay_substrate_client::Error), - /// Failed to read initial GRANDPA authorities. - #[error("Error reading GRANDPA authorities set: {0:?}")] - ReadAuthorities(relay_substrate_client::Error), - /// Failed to deploy bridge contract to Ethereum chain. - #[error("Error deploying contract: {0:?}")] - DeployContract(RpcError), -} diff --git a/relays/bin-ethereum/src/ethereum_client.rs b/relays/bin-ethereum/src/ethereum_client.rs deleted file mode 100644 index 75ed57fea1634..0000000000000 --- a/relays/bin-ethereum/src/ethereum_client.rs +++ /dev/null @@ -1,631 +0,0 @@ -// 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 . - -use crate::{rpc_errors::RpcError, substrate_sync_loop::QueuedRialtoHeader}; - -use async_trait::async_trait; -use bp_eth_poa::signatures::secret_to_address; -use codec::{Decode, Encode}; -use ethabi::FunctionOutputDecoder; -use headers_relay::sync_types::SubmittedHeaders; -use relay_ethereum_client::{ - sign_and_submit_transaction, - types::{Address, CallRequest, HeaderId as EthereumHeaderId, Receipt, H256, U256}, - Client as EthereumClient, Error as EthereumNodeError, SigningParams as EthereumSigningParams, -}; -use relay_rialto_client::HeaderId as RialtoHeaderId; -use relay_utils::{HeaderId, MaybeConnectionError}; -use sp_runtime::EncodedJustification; -use std::collections::HashSet; - -// to encode/decode contract calls -ethabi_contract::use_contract!(bridge_contract, "res/substrate-bridge-abi.json"); - -type RpcResult = std::result::Result; - -/// A trait which contains methods that work by using multiple low-level RPCs, or more complicated -/// interactions involving, for example, an Ethereum contract. -#[async_trait] -pub trait EthereumHighLevelRpc { - /// Returns the best Substrate block that PoA chain knows of. - async fn best_substrate_block(&self, contract_address: Address) -> RpcResult; - - /// Returns true if Substrate header is known to Ethereum node. - async fn substrate_header_known( - &self, - contract_address: Address, - id: RialtoHeaderId, - ) -> RpcResult<(RialtoHeaderId, bool)>; - - /// Submits Substrate headers to Ethereum contract. - async fn submit_substrate_headers( - &self, - params: EthereumSigningParams, - contract_address: Address, - headers: Vec, - ) -> SubmittedHeaders; - - /// Returns ids of incomplete Substrate headers. - async fn incomplete_substrate_headers( - &self, - contract_address: Address, - ) -> RpcResult>; - - /// Complete Substrate header. - async fn complete_substrate_header( - &self, - params: EthereumSigningParams, - contract_address: Address, - id: RialtoHeaderId, - justification: EncodedJustification, - ) -> RpcResult; - - /// Submit ethereum transaction. - async fn submit_ethereum_transaction( - &self, - params: &EthereumSigningParams, - contract_address: Option
, - nonce: Option, - double_gas: bool, - encoded_call: Vec, - ) -> RpcResult<()>; - - /// Retrieve transactions receipts for given block. - async fn transaction_receipts( - &self, - id: EthereumHeaderId, - transactions: Vec, - ) -> RpcResult<(EthereumHeaderId, Vec)>; -} - -#[async_trait] -impl EthereumHighLevelRpc for EthereumClient { - async fn best_substrate_block(&self, contract_address: Address) -> RpcResult { - let (encoded_call, call_decoder) = bridge_contract::functions::best_known_header::call(); - let call_request = CallRequest { - to: Some(contract_address), - data: Some(encoded_call.into()), - ..Default::default() - }; - - let call_result = self.eth_call(call_request).await?; - let (number, raw_hash) = call_decoder.decode(&call_result.0)?; - let hash = rialto_runtime::Hash::decode(&mut &raw_hash[..])?; - - if number != number.low_u32().into() { - return Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)) - } - - Ok(HeaderId(number.low_u32(), hash)) - } - - async fn substrate_header_known( - &self, - contract_address: Address, - id: RialtoHeaderId, - ) -> RpcResult<(RialtoHeaderId, bool)> { - let (encoded_call, call_decoder) = bridge_contract::functions::is_known_header::call(id.1); - let call_request = CallRequest { - to: Some(contract_address), - data: Some(encoded_call.into()), - ..Default::default() - }; - - let call_result = self.eth_call(call_request).await?; - let is_known_block = call_decoder.decode(&call_result.0)?; - - Ok((id, is_known_block)) - } - - async fn submit_substrate_headers( - &self, - params: EthereumSigningParams, - contract_address: Address, - headers: Vec, - ) -> SubmittedHeaders { - // read nonce of signer - let address: Address = secret_to_address(¶ms.signer); - let nonce = match self.account_nonce(address).await { - Ok(nonce) => nonce, - Err(error) => - return SubmittedHeaders { - submitted: Vec::new(), - incomplete: Vec::new(), - rejected: headers.iter().rev().map(|header| header.id()).collect(), - fatal_error: Some(error.into()), - }, - }; - - // submit headers. Note that we're cloning self here. It is ok, because - // cloning `jsonrpsee::Client` only clones reference to background threads - submit_substrate_headers( - EthereumHeadersSubmitter { client: self.clone(), params, contract_address, nonce }, - headers, - ) - .await - } - - async fn incomplete_substrate_headers( - &self, - contract_address: Address, - ) -> RpcResult> { - let (encoded_call, call_decoder) = bridge_contract::functions::incomplete_headers::call(); - let call_request = CallRequest { - to: Some(contract_address), - data: Some(encoded_call.into()), - ..Default::default() - }; - - let call_result = self.eth_call(call_request).await?; - - // Q: Is is correct to call these "incomplete_ids"? - let (incomplete_headers_numbers, incomplete_headers_hashes) = - call_decoder.decode(&call_result.0)?; - let incomplete_ids = incomplete_headers_numbers - .into_iter() - .zip(incomplete_headers_hashes) - .filter_map(|(number, hash)| { - if number != number.low_u32().into() { - return None - } - - Some(HeaderId(number.low_u32(), hash)) - }) - .collect(); - - Ok(incomplete_ids) - } - - async fn complete_substrate_header( - &self, - params: EthereumSigningParams, - contract_address: Address, - id: RialtoHeaderId, - justification: EncodedJustification, - ) -> RpcResult { - let _ = self - .submit_ethereum_transaction( - ¶ms, - Some(contract_address), - None, - false, - bridge_contract::functions::import_finality_proof::encode_input( - id.0, - id.1, - justification, - ), - ) - .await?; - - Ok(id) - } - - async fn submit_ethereum_transaction( - &self, - params: &EthereumSigningParams, - contract_address: Option
, - nonce: Option, - double_gas: bool, - encoded_call: Vec, - ) -> RpcResult<()> { - sign_and_submit_transaction(self, params, contract_address, nonce, double_gas, encoded_call) - .await - .map_err(Into::into) - } - - async fn transaction_receipts( - &self, - id: EthereumHeaderId, - transactions: Vec, - ) -> RpcResult<(EthereumHeaderId, Vec)> { - let mut transaction_receipts = Vec::with_capacity(transactions.len()); - for transaction in transactions { - let transaction_receipt = self.transaction_receipt(transaction).await?; - transaction_receipts.push(transaction_receipt); - } - Ok((id, transaction_receipts)) - } -} - -/// Max number of headers which can be sent to Solidity contract. -pub const HEADERS_BATCH: usize = 4; - -/// Substrate headers to send to the Ethereum light client. -/// -/// The Solidity contract can only accept a fixed number of headers in one go. -/// This struct is meant to encapsulate this limitation. -#[derive(Debug)] -#[cfg_attr(test, derive(Clone))] -pub struct HeadersBatch { - pub header1: QueuedRialtoHeader, - pub header2: Option, - pub header3: Option, - pub header4: Option, -} - -impl HeadersBatch { - /// Create new headers from given header & ids collections. - /// - /// This method will pop `HEADERS_BATCH` items from both collections - /// and construct `Headers` object and a vector of `RialtoHeaderId`s. - pub fn pop_from( - headers: &mut Vec, - ids: &mut Vec, - ) -> Result<(Self, Vec), ()> { - if headers.len() != ids.len() { - log::error!(target: "bridge", "Collection size mismatch ({} vs {})", headers.len(), ids.len()); - return Err(()) - } - - let header1 = headers.pop().ok_or(())?; - let header2 = headers.pop(); - let header3 = headers.pop(); - let header4 = headers.pop(); - - let mut submitting_ids = Vec::with_capacity(HEADERS_BATCH); - for _ in 0..HEADERS_BATCH { - submitting_ids.extend(ids.pop().iter()); - } - - Ok((Self { header1, header2, header3, header4 }, submitting_ids)) - } - - /// Returns unified array of headers. - /// - /// The first element is always `Some`. - fn headers(&self) -> [Option<&QueuedRialtoHeader>; HEADERS_BATCH] { - [Some(&self.header1), self.header2.as_ref(), self.header3.as_ref(), self.header4.as_ref()] - } - - /// Encodes all headers. If header is not present an empty vector will be returned. - pub fn encode(&self) -> [Vec; HEADERS_BATCH] { - let encode = |h: &QueuedRialtoHeader| h.header().encode(); - let headers = self.headers(); - [ - headers[0].map(encode).unwrap_or_default(), - headers[1].map(encode).unwrap_or_default(), - headers[2].map(encode).unwrap_or_default(), - headers[3].map(encode).unwrap_or_default(), - ] - } - /// Returns number of contained headers. - pub fn len(&self) -> usize { - let is_set = |h: &Option<&QueuedRialtoHeader>| if h.is_some() { 1 } else { 0 }; - self.headers().iter().map(is_set).sum() - } - - /// Remove headers starting from `idx` (0-based) from this collection. - /// - /// The collection will be left with `[0, idx)` headers. - /// Returns `Err` when `idx == 0`, since `Headers` must contain at least one header, - /// or when `idx > HEADERS_BATCH`. - pub fn split_off(&mut self, idx: usize) -> Result<(), ()> { - if idx == 0 || idx > HEADERS_BATCH { - return Err(()) - } - let mut vals: [_; HEADERS_BATCH] = - [&mut None, &mut self.header2, &mut self.header3, &mut self.header4]; - for val in vals.iter_mut().skip(idx) { - **val = None; - } - Ok(()) - } -} - -/// Substrate headers submitter API. -#[async_trait] -trait HeadersSubmitter { - /// Returns Ok(0) if all given not-yet-imported headers are complete. - /// Returns Ok(index != 0) where index is 1-based index of first header that is incomplete. - /// - /// Returns Err(()) if contract has rejected headers. This means that the contract is - /// unable to import first header (e.g. it may already be imported). - async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult; - - /// Submit given headers to Ethereum node. - async fn submit_headers(&mut self, headers: HeadersBatch) -> RpcResult<()>; -} - -/// Implementation of Substrate headers submitter that sends headers to running Ethereum node. -struct EthereumHeadersSubmitter { - client: EthereumClient, - params: EthereumSigningParams, - contract_address: Address, - nonce: U256, -} - -#[async_trait] -impl HeadersSubmitter for EthereumHeadersSubmitter { - async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult { - let [h1, h2, h3, h4] = headers.encode(); - let (encoded_call, call_decoder) = - bridge_contract::functions::is_incomplete_headers::call(h1, h2, h3, h4); - let call_request = CallRequest { - to: Some(self.contract_address), - data: Some(encoded_call.into()), - ..Default::default() - }; - - let call_result = self.client.eth_call(call_request).await?; - let incomplete_index: U256 = call_decoder.decode(&call_result.0)?; - if incomplete_index > HEADERS_BATCH.into() { - return Err(RpcError::Ethereum(EthereumNodeError::InvalidIncompleteIndex)) - } - - Ok(incomplete_index.low_u32() as _) - } - - async fn submit_headers(&mut self, headers: HeadersBatch) -> RpcResult<()> { - let [h1, h2, h3, h4] = headers.encode(); - let result = self - .client - .submit_ethereum_transaction( - &self.params, - Some(self.contract_address), - Some(self.nonce), - false, - bridge_contract::functions::import_headers::encode_input(h1, h2, h3, h4), - ) - .await; - - if result.is_ok() { - self.nonce += U256::one(); - } - - result - } -} - -/// Submit multiple Substrate headers. -async fn submit_substrate_headers( - mut header_submitter: impl HeadersSubmitter, - mut headers: Vec, -) -> SubmittedHeaders { - let mut submitted_headers = SubmittedHeaders::default(); - - let mut ids = headers.iter().map(|header| header.id()).rev().collect::>(); - headers.reverse(); - - while !headers.is_empty() { - let (headers, submitting_ids) = HeadersBatch::pop_from(&mut headers, &mut ids) - .expect("Headers and ids are not empty; qed"); - - submitted_headers.fatal_error = submit_substrate_headers_batch( - &mut header_submitter, - &mut submitted_headers, - submitting_ids, - headers, - ) - .await; - - if submitted_headers.fatal_error.is_some() { - ids.reverse(); - submitted_headers.rejected.extend(ids); - break - } - } - - submitted_headers -} - -/// Submit 4 Substrate headers in single PoA transaction. -async fn submit_substrate_headers_batch( - header_submitter: &mut impl HeadersSubmitter, - submitted_headers: &mut SubmittedHeaders, - mut ids: Vec, - mut headers: HeadersBatch, -) -> Option { - debug_assert_eq!(ids.len(), headers.len(),); - - // if parent of first header is either incomplete, or rejected, we assume that contract - // will reject this header as well - let parent_id = headers.header1.parent_id(); - if submitted_headers.rejected.contains(&parent_id) || - submitted_headers.incomplete.contains(&parent_id) - { - submitted_headers.rejected.extend(ids); - return None - } - - // check if headers are incomplete - let incomplete_header_index = match header_submitter.is_headers_incomplete(&headers).await { - // All headers valid - Ok(0) => None, - Ok(incomplete_header_index) => Some(incomplete_header_index), - Err(error) => { - // contract has rejected all headers => we do not want to submit it - submitted_headers.rejected.extend(ids); - if error.is_connection_error() { - return Some(error) - } else { - return None - } - }, - }; - - // Modify `ids` and `headers` to only contain values that are going to be accepted. - let rejected = if let Some(idx) = incomplete_header_index { - let len = std::cmp::min(idx, ids.len()); - headers - .split_off(len) - .expect("len > 0, the case where all headers are valid is converted to None; qed"); - ids.split_off(len) - } else { - Vec::new() - }; - let submitted = ids; - let submit_result = header_submitter.submit_headers(headers).await; - match submit_result { - Ok(_) => { - if incomplete_header_index.is_some() { - submitted_headers.incomplete.extend(submitted.iter().last().cloned()); - } - submitted_headers.submitted.extend(submitted); - submitted_headers.rejected.extend(rejected); - None - }, - Err(error) => { - submitted_headers.rejected.extend(submitted); - submitted_headers.rejected.extend(rejected); - Some(error) - }, - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sp_runtime::traits::Header; - - struct TestHeadersSubmitter { - incomplete: Vec, - failed: Vec, - } - - #[async_trait] - impl HeadersSubmitter for TestHeadersSubmitter { - async fn is_headers_incomplete(&self, headers: &HeadersBatch) -> RpcResult { - if self.incomplete.iter().any(|i| i.0 == headers.header1.id().0) { - Ok(1) - } else { - Ok(0) - } - } - - async fn submit_headers(&mut self, headers: HeadersBatch) -> RpcResult<()> { - if self.failed.iter().any(|i| i.0 == headers.header1.id().0) { - Err(RpcError::Ethereum(EthereumNodeError::InvalidSubstrateBlockNumber)) - } else { - Ok(()) - } - } - } - - fn header(number: rialto_runtime::BlockNumber) -> QueuedRialtoHeader { - QueuedRialtoHeader::new( - rialto_runtime::Header::new( - number, - Default::default(), - Default::default(), - if number == 0 { Default::default() } else { header(number - 1).id().1 }, - Default::default(), - ) - .into(), - ) - } - - #[test] - fn descendants_of_incomplete_headers_are_not_submitted() { - let submitted_headers = async_std::task::block_on(submit_substrate_headers( - TestHeadersSubmitter { incomplete: vec![header(5).id()], failed: vec![] }, - vec![header(5), header(6)], - )); - assert_eq!(submitted_headers.submitted, vec![header(5).id()]); - assert_eq!(submitted_headers.incomplete, vec![header(5).id()]); - assert_eq!(submitted_headers.rejected, vec![header(6).id()]); - assert!(submitted_headers.fatal_error.is_none()); - } - - #[test] - fn headers_after_fatal_error_are_not_submitted() { - let submitted_headers = async_std::task::block_on(submit_substrate_headers( - TestHeadersSubmitter { incomplete: vec![], failed: vec![header(9).id()] }, - vec![header(5), header(6), header(7), header(8), header(9), header(10), header(11)], - )); - assert_eq!( - submitted_headers.submitted, - vec![header(5).id(), header(6).id(), header(7).id(), header(8).id()] - ); - assert_eq!(submitted_headers.incomplete, vec![]); - assert_eq!( - submitted_headers.rejected, - vec![header(9).id(), header(10).id(), header(11).id(),] - ); - assert!(submitted_headers.fatal_error.is_some()); - } - - fn headers_batch() -> HeadersBatch { - let mut init_headers = vec![header(1), header(2), header(3), header(4), header(5)]; - init_headers.reverse(); - let mut init_ids = init_headers.iter().map(|h| h.id()).collect(); - let (headers, ids) = HeadersBatch::pop_from(&mut init_headers, &mut init_ids).unwrap(); - assert_eq!(init_headers, vec![header(5)]); - assert_eq!(init_ids, vec![header(5).id()]); - assert_eq!(ids, vec![header(1).id(), header(2).id(), header(3).id(), header(4).id()]); - headers - } - - #[test] - fn headers_batch_len() { - let headers = headers_batch(); - assert_eq!(headers.len(), 4); - } - - #[test] - fn headers_batch_encode() { - let headers = headers_batch(); - assert_eq!( - headers.encode(), - [ - header(1).header().encode(), - header(2).header().encode(), - header(3).header().encode(), - header(4).header().encode(), - ] - ); - } - - #[test] - fn headers_batch_split_off() { - // given - let mut headers = headers_batch(); - - // when - assert!(headers.split_off(0).is_err()); - assert_eq!(headers.header1, header(1)); - assert!(headers.header2.is_some()); - assert!(headers.header3.is_some()); - assert!(headers.header4.is_some()); - - // when - let mut h = headers.clone(); - h.split_off(1).unwrap(); - assert!(h.header2.is_none()); - assert!(h.header3.is_none()); - assert!(h.header4.is_none()); - - // when - let mut h = headers.clone(); - h.split_off(2).unwrap(); - assert!(h.header2.is_some()); - assert!(h.header3.is_none()); - assert!(h.header4.is_none()); - - // when - let mut h = headers.clone(); - h.split_off(3).unwrap(); - assert!(h.header2.is_some()); - assert!(h.header3.is_some()); - assert!(h.header4.is_none()); - - // when - let mut h = headers; - h.split_off(4).unwrap(); - assert!(h.header2.is_some()); - assert!(h.header3.is_some()); - assert!(h.header4.is_some()); - } -} diff --git a/relays/bin-ethereum/src/ethereum_deploy_contract.rs b/relays/bin-ethereum/src/ethereum_deploy_contract.rs deleted file mode 100644 index 76a75b062ecbc..0000000000000 --- a/relays/bin-ethereum/src/ethereum_deploy_contract.rs +++ /dev/null @@ -1,164 +0,0 @@ -// 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 . - -use crate::{ - error::{Error, Result}, - ethereum_client::{bridge_contract, EthereumHighLevelRpc}, - rpc_errors::RpcError, -}; - -use codec::{Decode, Encode}; -use num_traits::Zero; -use relay_ethereum_client::{ - Client as EthereumClient, ConnectionParams as EthereumConnectionParams, - SigningParams as EthereumSigningParams, -}; -use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto}; -use relay_substrate_client::{ - Client as SubstrateClient, ConnectionParams as SubstrateConnectionParams, - OpaqueGrandpaAuthoritiesSet, -}; -use relay_utils::HeaderId; - -/// Ethereum synchronization parameters. -#[derive(Debug)] -pub struct EthereumDeployContractParams { - /// Ethereum connection params. - pub eth_params: EthereumConnectionParams, - /// Ethereum signing params. - pub eth_sign: EthereumSigningParams, - /// Ethereum contract bytecode. - pub eth_contract_code: Vec, - /// Substrate connection params. - pub sub_params: SubstrateConnectionParams, - /// Initial authorities set id. - pub sub_initial_authorities_set_id: Option, - /// Initial authorities set. - pub sub_initial_authorities_set: Option>, - /// Initial header. - pub sub_initial_header: Option>, -} - -/// Deploy Bridge contract on Ethereum chain. -pub async fn run(params: EthereumDeployContractParams) { - let EthereumDeployContractParams { - eth_params, - eth_sign, - sub_params, - sub_initial_authorities_set_id, - sub_initial_authorities_set, - sub_initial_header, - eth_contract_code, - } = params; - - let result = async move { - let eth_client = EthereumClient::try_connect(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::try_connect(sub_params).await.map_err(RpcError::Substrate)?; - - let (initial_header_id, initial_header) = prepare_initial_header(&sub_client, sub_initial_header).await?; - let initial_set_id = sub_initial_authorities_set_id.unwrap_or(0); - let initial_set = prepare_initial_authorities_set( - &sub_client, - initial_header_id.1, - sub_initial_authorities_set, - ).await?; - - log::info!( - target: "bridge", - "Deploying Ethereum contract.\r\n\tInitial header: {:?}\r\n\tInitial header id: {:?}\r\n\tInitial header encoded: {}\r\n\tInitial authorities set ID: {}\r\n\tInitial authorities set: {}", - initial_header, - initial_header_id, - hex::encode(&initial_header), - initial_set_id, - hex::encode(&initial_set), - ); - - deploy_bridge_contract( - ð_client, - ð_sign, - eth_contract_code, - initial_header, - initial_set_id, - initial_set, - ).await - }.await; - - if let Err(error) = result { - log::error!(target: "bridge", "{}", error); - } -} - -/// Prepare initial header. -async fn prepare_initial_header( - sub_client: &SubstrateClient, - sub_initial_header: Option>, -) -> Result<(RialtoHeaderId, Vec)> { - match sub_initial_header { - Some(raw_initial_header) => { - match rialto_runtime::Header::decode(&mut &raw_initial_header[..]) { - Ok(initial_header) => - Ok((HeaderId(initial_header.number, initial_header.hash()), raw_initial_header)), - Err(error) => Err(Error::DecodeInitialHeader(error)), - } - }, - None => { - let initial_header = sub_client.header_by_number(Zero::zero()).await; - initial_header - .map(|header| (HeaderId(Zero::zero(), header.hash()), header.encode())) - .map_err(Error::ReadGenesisHeader) - }, - } -} - -/// Prepare initial GRANDPA authorities set. -async fn prepare_initial_authorities_set( - sub_client: &SubstrateClient, - sub_initial_header_hash: rialto_runtime::Hash, - sub_initial_authorities_set: Option>, -) -> Result { - let initial_authorities_set = match sub_initial_authorities_set { - Some(initial_authorities_set) => Ok(initial_authorities_set), - None => sub_client.grandpa_authorities_set(sub_initial_header_hash).await, - }; - - initial_authorities_set.map_err(Error::ReadAuthorities) -} - -/// Deploy bridge contract to Ethereum chain. -async fn deploy_bridge_contract( - eth_client: &EthereumClient, - params: &EthereumSigningParams, - contract_code: Vec, - initial_header: Vec, - initial_set_id: u64, - initial_authorities: Vec, -) -> Result<()> { - eth_client - .submit_ethereum_transaction( - params, - None, - None, - false, - bridge_contract::constructor( - contract_code, - initial_header, - initial_set_id, - initial_authorities, - ), - ) - .await - .map_err(Error::DeployContract) -} diff --git a/relays/bin-ethereum/src/ethereum_exchange.rs b/relays/bin-ethereum/src/ethereum_exchange.rs deleted file mode 100644 index 90d9a23835d46..0000000000000 --- a/relays/bin-ethereum/src/ethereum_exchange.rs +++ /dev/null @@ -1,402 +0,0 @@ -// 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 . - -//! Relaying proofs of PoA -> Substrate exchange transactions. - -use crate::{ - instances::BridgeInstance, - rialto_client::{SubmitEthereumExchangeTransactionProof, SubstrateHighLevelRpc}, - rpc_errors::RpcError, - substrate_types::into_substrate_ethereum_receipt, -}; - -use async_trait::async_trait; -use bp_currency_exchange::MaybeLockFundsTransaction; -use exchange_relay::{ - exchange::{ - relay_single_transaction_proof, SourceBlock, SourceClient, SourceTransaction, TargetClient, - TransactionProofPipeline, - }, - exchange_loop::{run as run_loop, InMemoryStorage}, -}; -use relay_ethereum_client::{ - types::{ - HeaderId as EthereumHeaderId, HeaderWithTransactions as EthereumHeaderWithTransactions, - Transaction as EthereumTransaction, TransactionHash as EthereumTransactionHash, H256, - HEADER_ID_PROOF, - }, - Client as EthereumClient, ConnectionParams as EthereumConnectionParams, -}; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - Chain as SubstrateChain, Client as SubstrateClient, - ConnectionParams as SubstrateConnectionParams, -}; -use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId}; -use rialto_runtime::exchange::EthereumTransactionInclusionProof; -use std::{sync::Arc, time::Duration}; - -/// Interval at which we ask Ethereum node for updates. -const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); - -/// Exchange relay mode. -#[derive(Debug)] -pub enum ExchangeRelayMode { - /// Relay single transaction and quit. - Single(EthereumTransactionHash), - /// Auto-relay transactions starting with given block. - Auto(Option), -} - -/// PoA exchange transaction relay params. -pub struct EthereumExchangeParams { - /// Ethereum connection params. - pub eth_params: EthereumConnectionParams, - /// Substrate connection params. - pub sub_params: SubstrateConnectionParams, - /// Substrate signing params. - pub sub_sign: RialtoSigningParams, - /// Relay working mode. - pub mode: ExchangeRelayMode, - /// Metrics parameters. - pub metrics_params: MetricsParams, - /// Instance of the bridge pallet being synchronized. - pub instance: Arc, -} - -impl std::fmt::Debug for EthereumExchangeParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("EthereumExchangeParams") - .field("eth_params", &self.eth_params) - .field("sub_params", &self.sub_params) - .field("sub_sign", &sp_core::Pair::public(&self.sub_sign)) - .field("mode", &self.mode) - .field("metrics_params", &self.metrics_params) - .field("instance", &self.instance) - .finish() - } -} - -/// Ethereum to Substrate exchange pipeline. -struct EthereumToSubstrateExchange; - -impl TransactionProofPipeline for EthereumToSubstrateExchange { - const SOURCE_NAME: &'static str = "Ethereum"; - const TARGET_NAME: &'static str = "Substrate"; - - type Block = EthereumSourceBlock; - type TransactionProof = EthereumTransactionInclusionProof; -} - -/// Ethereum source block. -struct EthereumSourceBlock(EthereumHeaderWithTransactions); - -impl SourceBlock for EthereumSourceBlock { - type Hash = H256; - type Number = u64; - type Transaction = EthereumSourceTransaction; - - fn id(&self) -> EthereumHeaderId { - HeaderId( - self.0.number.expect(HEADER_ID_PROOF).as_u64(), - self.0.hash.expect(HEADER_ID_PROOF), - ) - } - - fn transactions(&self) -> Vec { - self.0.transactions.iter().cloned().map(EthereumSourceTransaction).collect() - } -} - -/// Ethereum source transaction. -struct EthereumSourceTransaction(EthereumTransaction); - -impl SourceTransaction for EthereumSourceTransaction { - type Hash = EthereumTransactionHash; - - fn hash(&self) -> Self::Hash { - self.0.hash - } -} - -/// Ethereum node as transactions proof source. -#[derive(Clone)] -struct EthereumTransactionsSource { - client: EthereumClient, -} - -#[async_trait] -impl RelayClient for EthereumTransactionsSource { - type Error = RpcError; - - async fn reconnect(&mut self) -> Result<(), RpcError> { - self.client.reconnect().await.map_err(Into::into) - } -} - -#[async_trait] -impl SourceClient for EthereumTransactionsSource { - async fn tick(&self) { - async_std::task::sleep(ETHEREUM_TICK_INTERVAL).await; - } - - async fn block_by_hash(&self, hash: H256) -> Result { - self.client - .header_by_hash_with_transactions(hash) - .await - .map(EthereumSourceBlock) - .map_err(Into::into) - } - - async fn block_by_number(&self, number: u64) -> Result { - self.client - .header_by_number_with_transactions(number) - .await - .map(EthereumSourceBlock) - .map_err(Into::into) - } - - async fn transaction_block( - &self, - hash: &EthereumTransactionHash, - ) -> Result, RpcError> { - let eth_tx = match self.client.transaction_by_hash(*hash).await? { - Some(eth_tx) => eth_tx, - None => return Ok(None), - }; - - // we need transaction to be mined => check if it is included in the block - let (eth_header_id, eth_tx_index) = - match (eth_tx.block_number, eth_tx.block_hash, eth_tx.transaction_index) { - (Some(block_number), Some(block_hash), Some(transaction_index)) => - (HeaderId(block_number.as_u64(), block_hash), transaction_index.as_u64() as _), - _ => return Ok(None), - }; - - Ok(Some((eth_header_id, eth_tx_index))) - } - - async fn transaction_proof( - &self, - block: &EthereumSourceBlock, - tx_index: usize, - ) -> Result { - const TRANSACTION_HAS_RAW_FIELD_PROOF: &str = - "RPC level checks that transactions from Ethereum\ - node are having `raw` field; qed"; - const BLOCK_HAS_HASH_FIELD_PROOF: &str = - "RPC level checks that block has `hash` field; qed"; - - let mut transaction_proof = Vec::with_capacity(block.0.transactions.len()); - for tx in &block.0.transactions { - let raw_tx_receipt = self - .client - .transaction_receipt(tx.hash) - .await - .map(|receipt| into_substrate_ethereum_receipt(&receipt)) - .map(|receipt| receipt.rlp())?; - let raw_tx = tx.raw.clone().expect(TRANSACTION_HAS_RAW_FIELD_PROOF).0; - transaction_proof.push((raw_tx, raw_tx_receipt)); - } - - Ok(EthereumTransactionInclusionProof { - block: block.0.hash.expect(BLOCK_HAS_HASH_FIELD_PROOF), - index: tx_index as _, - proof: transaction_proof, - }) - } -} - -/// Substrate node as transactions proof target. -#[derive(Clone)] -struct SubstrateTransactionsTarget { - client: SubstrateClient, - sign_params: RialtoSigningParams, - bridge_instance: Arc, -} - -#[async_trait] -impl RelayClient for SubstrateTransactionsTarget { - type Error = RpcError; - - async fn reconnect(&mut self) -> Result<(), RpcError> { - Ok(self.client.reconnect().await?) - } -} - -#[async_trait] -impl TargetClient for SubstrateTransactionsTarget { - async fn tick(&self) { - async_std::task::sleep(Rialto::AVERAGE_BLOCK_INTERVAL).await; - } - - async fn is_header_known(&self, id: &EthereumHeaderId) -> Result { - self.client.ethereum_header_known(*id).await - } - - async fn is_header_finalized(&self, id: &EthereumHeaderId) -> Result { - // we check if header is finalized by simple comparison of the header number and - // number of best finalized PoA header known to Substrate node. - // - // this may lead to failure in tx proof import if PoA reorganization has happened - // after we have checked that our tx has been included into given block - // - // the fix is easy, but since this code is mostly developed for demonstration purposes, - // I'm leaving this KISS-based design here - let best_finalized_ethereum_block = self.client.best_ethereum_finalized_block().await?; - Ok(id.0 <= best_finalized_ethereum_block.0) - } - - async fn best_finalized_header_id(&self) -> Result { - // we can't continue to relay exchange proofs if Substrate node is out of sync, because - // it may have already received (some of) proofs that we're going to relay - self.client.ensure_synced().await?; - - self.client.best_ethereum_finalized_block().await - } - - async fn filter_transaction_proof( - &self, - proof: &EthereumTransactionInclusionProof, - ) -> Result { - // let's try to parse transaction locally - let (raw_tx, raw_tx_receipt) = &proof.proof[proof.index as usize]; - let parse_result = rialto_runtime::exchange::EthTransaction::parse(raw_tx); - if parse_result.is_err() { - return Ok(false) - } - - // now let's check if transaction is successful - match bp_eth_poa::Receipt::is_successful_raw_receipt(raw_tx_receipt) { - Ok(true) => (), - _ => return Ok(false), - } - - // seems that transaction is relayable - let's check if runtime is able to import it - // (we can't if e.g. header is pruned or there's some issue with tx data) - self.client.verify_exchange_transaction_proof(proof.clone()).await - } - - async fn submit_transaction_proof( - &self, - proof: EthereumTransactionInclusionProof, - ) -> Result<(), RpcError> { - let (sign_params, bridge_instance) = - (self.sign_params.clone(), self.bridge_instance.clone()); - self.client - .submit_exchange_transaction_proof(sign_params, bridge_instance, proof) - .await - } -} - -/// Relay exchange transaction proof(s) to Substrate node. -pub async fn run(params: EthereumExchangeParams) { - match params.mode { - ExchangeRelayMode::Single(eth_tx_hash) => { - let result = run_single_transaction_relay(params, eth_tx_hash).await; - match result { - Ok(_) => log::info!( - target: "bridge", - "Ethereum transaction {} proof has been successfully submitted to Substrate node", - eth_tx_hash, - ), - Err(err) => log::error!( - target: "bridge", - "Error submitting Ethereum transaction {} proof to Substrate node: {}", - eth_tx_hash, - err, - ), - } - }, - ExchangeRelayMode::Auto(eth_start_with_block_number) => { - let result = - run_auto_transactions_relay_loop(params, eth_start_with_block_number).await; - if let Err(err) = result { - log::error!( - target: "bridge", - "Error auto-relaying Ethereum transactions proofs to Substrate node: {}", - err, - ); - } - }, - } -} - -/// Run single transaction proof relay and stop. -async fn run_single_transaction_relay( - params: EthereumExchangeParams, - eth_tx_hash: H256, -) -> anyhow::Result<()> { - let EthereumExchangeParams { eth_params, sub_params, sub_sign, instance, .. } = params; - - let eth_client = EthereumClient::try_connect(eth_params).await.map_err(RpcError::Ethereum)?; - let sub_client = SubstrateClient::::try_connect(sub_params) - .await - .map_err(RpcError::Substrate)?; - - let source = EthereumTransactionsSource { client: eth_client }; - let target = SubstrateTransactionsTarget { - client: sub_client, - sign_params: sub_sign, - bridge_instance: instance, - }; - - relay_single_transaction_proof(&source, &target, eth_tx_hash) - .await - .map_err(Into::into) -} - -async fn run_auto_transactions_relay_loop( - params: EthereumExchangeParams, - eth_start_with_block_number: Option, -) -> anyhow::Result<()> { - let EthereumExchangeParams { - eth_params, sub_params, sub_sign, metrics_params, instance, .. - } = params; - - let eth_client = EthereumClient::new(eth_params).await; - let sub_client = SubstrateClient::::new(sub_params).await; - - let eth_start_with_block_number = match eth_start_with_block_number { - Some(eth_start_with_block_number) => eth_start_with_block_number, - None => - sub_client - .best_ethereum_finalized_block() - .await - .map_err(|err| { - anyhow::format_err!( - "Error retrieving best finalized Ethereum block from Substrate node: {:?}", - err - ) - })? - .0, - }; - - run_loop( - InMemoryStorage::new(eth_start_with_block_number), - EthereumTransactionsSource { client: eth_client }, - SubstrateTransactionsTarget { - client: sub_client, - sign_params: sub_sign, - bridge_instance: instance, - }, - metrics_params, - futures::future::pending(), - ) - .await?; - - Ok(()) -} diff --git a/relays/bin-ethereum/src/ethereum_exchange_submit.rs b/relays/bin-ethereum/src/ethereum_exchange_submit.rs deleted file mode 100644 index f68a21e594e06..0000000000000 --- a/relays/bin-ethereum/src/ethereum_exchange_submit.rs +++ /dev/null @@ -1,110 +0,0 @@ -// 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 . - -//! Submitting Ethereum -> Substrate exchange transactions. - -use anyhow::anyhow; -use bp_eth_poa::{ - signatures::{secret_to_address, SignTransaction}, - UnsignedTransaction, -}; -use relay_ethereum_client::{ - types::{CallRequest, U256}, - Client as EthereumClient, ConnectionParams as EthereumConnectionParams, - SigningParams as EthereumSigningParams, -}; -use rialto_runtime::exchange::LOCK_FUNDS_ADDRESS; - -/// Ethereum exchange transaction params. -#[derive(Debug)] -pub struct EthereumExchangeSubmitParams { - /// Ethereum connection params. - pub eth_params: EthereumConnectionParams, - /// Ethereum signing params. - pub eth_sign: EthereumSigningParams, - /// Ethereum signer nonce. - pub eth_nonce: Option, - /// Amount of Ethereum tokens to lock. - pub eth_amount: U256, - /// Funds recipient on Substrate side. - pub sub_recipient: [u8; 32], -} - -/// Submit single Ethereum -> Substrate exchange transaction. -pub async fn run(params: EthereumExchangeSubmitParams) { - let EthereumExchangeSubmitParams { eth_params, eth_sign, eth_nonce, eth_amount, sub_recipient } = - params; - - let result: anyhow::Result<_> = async move { - let eth_client = EthereumClient::try_connect(eth_params) - .await - .map_err(|err| anyhow!("error connecting to Ethereum node: {:?}", err))?; - - let eth_signer_address = secret_to_address(ð_sign.signer); - let sub_recipient_encoded = sub_recipient; - let nonce = match eth_nonce { - Some(eth_nonce) => eth_nonce, - None => eth_client - .account_nonce(eth_signer_address) - .await - .map_err(|err| anyhow!("error fetching acount nonce: {:?}", err))?, - }; - let gas = eth_client - .estimate_gas(CallRequest { - from: Some(eth_signer_address), - to: Some(LOCK_FUNDS_ADDRESS.into()), - value: Some(eth_amount), - data: Some(sub_recipient_encoded.to_vec().into()), - ..Default::default() - }) - .await - .map_err(|err| anyhow!("error estimating gas requirements: {:?}", err))?; - let eth_tx_unsigned = UnsignedTransaction { - nonce, - gas_price: eth_sign.gas_price, - gas, - to: Some(LOCK_FUNDS_ADDRESS.into()), - value: eth_amount, - payload: sub_recipient_encoded.to_vec(), - }; - let eth_tx_signed = - eth_tx_unsigned.clone().sign_by(ð_sign.signer, Some(eth_sign.chain_id)); - eth_client - .submit_transaction(eth_tx_signed) - .await - .map_err(|err| anyhow!("error submitting transaction: {:?}", err))?; - - Ok(eth_tx_unsigned) - } - .await; - - match result { - Ok(eth_tx_unsigned) => { - log::info!( - target: "bridge", - "Exchange transaction has been submitted to Ethereum node: {:?}", - eth_tx_unsigned, - ); - }, - Err(err) => { - log::error!( - target: "bridge", - "Error submitting exchange transaction to Ethereum node: {}", - err, - ); - }, - } -} diff --git a/relays/bin-ethereum/src/ethereum_sync_loop.rs b/relays/bin-ethereum/src/ethereum_sync_loop.rs deleted file mode 100644 index ee5f8a4600ece..0000000000000 --- a/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ /dev/null @@ -1,299 +0,0 @@ -// 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 . - -//! Ethereum PoA -> Rialto-Substrate synchronization. - -use crate::{ - ethereum_client::EthereumHighLevelRpc, - instances::BridgeInstance, - rialto_client::{SubmitEthereumHeaders, SubstrateHighLevelRpc}, - rpc_errors::RpcError, - substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}, -}; - -use async_trait::async_trait; -use codec::Encode; -use headers_relay::{ - sync::{HeadersSyncParams, TargetTransactionMode}, - sync_loop::{SourceClient, TargetClient}, - sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, -}; -use relay_ethereum_client::{ - types::{HeaderHash, HeaderId as EthereumHeaderId, Receipt, SyncHeader as Header}, - Client as EthereumClient, ConnectionParams as EthereumConnectionParams, -}; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - Chain as SubstrateChain, Client as SubstrateClient, - ConnectionParams as SubstrateConnectionParams, -}; -use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; - -use std::{collections::HashSet, fmt::Debug, sync::Arc, time::Duration}; - -pub mod consts { - use super::*; - - /// Interval at which we check new Ethereum headers when we are synced/almost synced. - pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(10); - /// Max number of headers in single submit transaction. - pub const MAX_HEADERS_IN_SINGLE_SUBMIT: usize = 32; - /// Max total size of headers in single submit transaction. This only affects signed - /// submissions, when several headers are submitted at once. 4096 is the maximal **expected** - /// size of the Ethereum header + transactions receipts (if they're required). - pub const MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT: usize = MAX_HEADERS_IN_SINGLE_SUBMIT * 4096; - /// Max Ethereum headers we want to have in all 'before-submitted' states. - pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 128; - /// Max Ethereum headers count we want to have in 'submitted' state. - pub const MAX_SUBMITTED_HEADERS: usize = 128; - /// Max depth of in-memory headers in all states. Past this depth they will be forgotten - /// (pruned). - pub const PRUNE_DEPTH: u32 = 4096; -} - -/// Ethereum synchronization parameters. -pub struct EthereumSyncParams { - /// Ethereum connection params. - pub eth_params: EthereumConnectionParams, - /// Substrate connection params. - pub sub_params: SubstrateConnectionParams, - /// Substrate signing params. - pub sub_sign: RialtoSigningParams, - /// Synchronization parameters. - pub sync_params: HeadersSyncParams, - /// Metrics parameters. - pub metrics_params: MetricsParams, - /// Instance of the bridge pallet being synchronized. - pub instance: Arc, -} - -impl Debug for EthereumSyncParams { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("EthereumSyncParams") - .field("eth_params", &self.eth_params) - .field("sub_params", &self.sub_params) - .field("sub_sign", &sp_core::Pair::public(&self.sub_sign)) - .field("sync_params", &self.sync_params) - .field("metrics_params", &self.metrics_params) - .field("instance", &self.instance) - .finish() - } -} - -/// Ethereum synchronization pipeline. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct EthereumHeadersSyncPipeline; - -impl HeadersSyncPipeline for EthereumHeadersSyncPipeline { - const SOURCE_NAME: &'static str = "Ethereum"; - const TARGET_NAME: &'static str = "Substrate"; - - type Hash = HeaderHash; - type Number = u64; - type Header = Header; - type Extra = Vec; - type Completion = (); - - fn estimate_size(source: &QueuedHeader) -> usize { - into_substrate_ethereum_header(source.header()).encode().len() + - into_substrate_ethereum_receipts(source.extra()) - .map(|extra| extra.encode().len()) - .unwrap_or(0) - } -} - -/// Queued ethereum header ID. -pub type QueuedEthereumHeader = QueuedHeader; - -/// Ethereum client as headers source. -#[derive(Clone)] -struct EthereumHeadersSource { - /// Ethereum node client. - client: EthereumClient, -} - -impl EthereumHeadersSource { - fn new(client: EthereumClient) -> Self { - Self { client } - } -} - -#[async_trait] -impl RelayClient for EthereumHeadersSource { - type Error = RpcError; - - async fn reconnect(&mut self) -> Result<(), RpcError> { - self.client.reconnect().await.map_err(Into::into) - } -} - -#[async_trait] -impl SourceClient for EthereumHeadersSource { - async fn best_block_number(&self) -> Result { - // we **CAN** continue to relay headers if Ethereum node is out of sync, because - // Substrate node may be missing headers that are already available at the Ethereum - - self.client.best_block_number().await.map_err(Into::into) - } - - async fn header_by_hash(&self, hash: HeaderHash) -> Result { - self.client.header_by_hash(hash).await.map(Into::into).map_err(Into::into) - } - - async fn header_by_number(&self, number: u64) -> Result { - self.client.header_by_number(number).await.map(Into::into).map_err(Into::into) - } - - async fn header_completion( - &self, - id: EthereumHeaderId, - ) -> Result<(EthereumHeaderId, Option<()>), RpcError> { - Ok((id, None)) - } - - async fn header_extra( - &self, - id: EthereumHeaderId, - header: QueuedEthereumHeader, - ) -> Result<(EthereumHeaderId, Vec), RpcError> { - self.client.transaction_receipts(id, header.header().transactions.clone()).await - } -} - -#[derive(Clone)] -struct SubstrateHeadersTarget { - /// Substrate node client. - client: SubstrateClient, - /// Whether we want to submit signed (true), or unsigned (false) transactions. - sign_transactions: bool, - /// Substrate signing params. - sign_params: RialtoSigningParams, - /// Bridge instance used in Ethereum to Substrate sync. - bridge_instance: Arc, -} - -impl SubstrateHeadersTarget { - fn new( - client: SubstrateClient, - sign_transactions: bool, - sign_params: RialtoSigningParams, - bridge_instance: Arc, - ) -> Self { - Self { client, sign_transactions, sign_params, bridge_instance } - } -} - -#[async_trait] -impl RelayClient for SubstrateHeadersTarget { - type Error = RpcError; - - async fn reconnect(&mut self) -> Result<(), RpcError> { - Ok(self.client.reconnect().await?) - } -} - -#[async_trait] -impl TargetClient for SubstrateHeadersTarget { - async fn best_header_id(&self) -> Result { - // we can't continue to relay headers if Substrate node is out of sync, because - // it may have already received (some of) headers that we're going to relay - self.client.ensure_synced().await?; - - self.client.best_ethereum_block().await - } - - async fn is_known_header( - &self, - id: EthereumHeaderId, - ) -> Result<(EthereumHeaderId, bool), RpcError> { - Ok((id, self.client.ethereum_header_known(id).await?)) - } - - async fn submit_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders { - let (sign_params, bridge_instance, sign_transactions) = - (self.sign_params.clone(), self.bridge_instance.clone(), self.sign_transactions); - self.client - .submit_ethereum_headers(sign_params, bridge_instance, headers, sign_transactions) - .await - } - - async fn incomplete_headers_ids(&self) -> Result, RpcError> { - Ok(HashSet::new()) - } - - #[allow(clippy::unit_arg)] - async fn complete_header( - &self, - id: EthereumHeaderId, - _completion: (), - ) -> Result { - Ok(id) - } - - async fn requires_extra( - &self, - header: QueuedEthereumHeader, - ) -> Result<(EthereumHeaderId, bool), RpcError> { - // we can minimize number of receipts_check calls by checking header - // logs bloom here, but it may give us false positives (when authorities - // source is contract, we never need any logs) - let id = header.header().id(); - let sub_eth_header = into_substrate_ethereum_header(header.header()); - Ok((id, self.client.ethereum_receipts_required(sub_eth_header).await?)) - } -} - -/// Run Ethereum headers synchronization. -pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { - let EthereumSyncParams { - eth_params, - sub_params, - sub_sign, - sync_params, - metrics_params, - instance, - } = params; - - let eth_client = EthereumClient::new(eth_params).await; - let sub_client = SubstrateClient::::new(sub_params).await; - - let sign_sub_transactions = match sync_params.target_tx_mode { - TargetTransactionMode::Signed | TargetTransactionMode::Backup => true, - TargetTransactionMode::Unsigned => false, - }; - - let source = EthereumHeadersSource::new(eth_client); - let target = SubstrateHeadersTarget::new(sub_client, sign_sub_transactions, sub_sign, instance); - - headers_relay::sync_loop::run( - source, - consts::ETHEREUM_TICK_INTERVAL, - target, - Rialto::AVERAGE_BLOCK_INTERVAL, - (), - sync_params, - metrics_params, - futures::future::pending(), - ) - .await - .map_err(|e| RpcError::SyncLoop(e.to_string()))?; - - Ok(()) -} diff --git a/relays/bin-ethereum/src/instances.rs b/relays/bin-ethereum/src/instances.rs deleted file mode 100644 index 74feb1da320d4..0000000000000 --- a/relays/bin-ethereum/src/instances.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2020-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 . - -//! The PoA Bridge Pallet provides a way to include multiple instances of itself in a runtime. When -//! synchronizing a Substrate chain which can include multiple instances of the bridge pallet we -//! must somehow decide which of the instances to sync. -//! -//! Note that each instance of the bridge pallet is coupled with an instance of the currency -//! exchange pallet. We must also have a way to create `Call`s for the correct currency exchange -//! instance. -//! -//! This module helps by preparing the correct `Call`s for each of the different pallet instances. - -use crate::{ - ethereum_sync_loop::QueuedEthereumHeader, - substrate_types::{into_substrate_ethereum_header, into_substrate_ethereum_receipts}, -}; - -use rialto_runtime::{exchange::EthereumTransactionInclusionProof as Proof, Call}; - -/// Interface for `Calls` which are needed to correctly sync the bridge. -/// -/// Each instance of the bridge and currency exchange pallets in the bridge runtime requires similar -/// but slightly different `Call` in order to be synchronized. -pub trait BridgeInstance: Send + Sync + std::fmt::Debug { - /// Used to build a `Call` for importing signed headers to a Substrate runtime. - fn build_signed_header_call(&self, headers: Vec) -> Call; - /// Used to build a `Call` for importing an unsigned header to a Substrate runtime. - fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call; - /// Used to build a `Call` for importing peer transactions to a Substrate runtime. - fn build_currency_exchange_call(&self, proof: Proof) -> Call; -} - -/// Corresponds to the Rialto instance used in the bridge runtime. -#[derive(Default, Clone, Debug)] -pub struct RialtoPoA; - -impl BridgeInstance for RialtoPoA { - fn build_signed_header_call(&self, headers: Vec) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers { - headers_with_receipts: headers - .into_iter() - .map(|header| { - ( - into_substrate_ethereum_header(header.header()), - into_substrate_ethereum_receipts(header.extra()), - ) - }) - .collect(), - }; - - rialto_runtime::Call::BridgeRialtoPoa(pallet_call) - } - - fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header { - header: Box::new(into_substrate_ethereum_header(header.header())), - receipts: into_substrate_ethereum_receipts(header.extra()), - }; - - rialto_runtime::Call::BridgeRialtoPoa(pallet_call) - } - - fn build_currency_exchange_call(&self, proof: Proof) -> Call { - let pallet_call = - rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction { proof }; - rialto_runtime::Call::BridgeRialtoCurrencyExchange(pallet_call) - } -} - -/// Corresponds to the Kovan instance used in the bridge runtime. -#[derive(Default, Clone, Debug)] -pub struct Kovan; - -impl BridgeInstance for Kovan { - fn build_signed_header_call(&self, headers: Vec) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_signed_headers { - headers_with_receipts: headers - .into_iter() - .map(|header| { - ( - into_substrate_ethereum_header(header.header()), - into_substrate_ethereum_receipts(header.extra()), - ) - }) - .collect(), - }; - - rialto_runtime::Call::BridgeKovan(pallet_call) - } - - fn build_unsigned_header_call(&self, header: QueuedEthereumHeader) -> Call { - let pallet_call = rialto_runtime::BridgeEthPoACall::import_unsigned_header { - header: Box::new(into_substrate_ethereum_header(header.header())), - receipts: into_substrate_ethereum_receipts(header.extra()), - }; - - rialto_runtime::Call::BridgeKovan(pallet_call) - } - - fn build_currency_exchange_call(&self, proof: Proof) -> Call { - let pallet_call = - rialto_runtime::BridgeCurrencyExchangeCall::import_peer_transaction { proof }; - rialto_runtime::Call::BridgeKovanCurrencyExchange(pallet_call) - } -} diff --git a/relays/bin-ethereum/src/main.rs b/relays/bin-ethereum/src/main.rs deleted file mode 100644 index 99e1b48968d79..0000000000000 --- a/relays/bin-ethereum/src/main.rs +++ /dev/null @@ -1,424 +0,0 @@ -// 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 . - -#![recursion_limit = "1024"] - -mod error; -mod ethereum_client; -mod ethereum_deploy_contract; -mod ethereum_exchange; -mod ethereum_exchange_submit; -mod ethereum_sync_loop; -mod instances; -mod rialto_client; -mod rpc_errors; -mod substrate_sync_loop; -mod substrate_types; - -use anyhow::anyhow; -use ethereum_deploy_contract::EthereumDeployContractParams; -use ethereum_exchange::EthereumExchangeParams; -use ethereum_exchange_submit::EthereumExchangeSubmitParams; -use ethereum_sync_loop::EthereumSyncParams; -use headers_relay::sync::TargetTransactionMode; -use hex_literal::hex; -use instances::{BridgeInstance, Kovan, RialtoPoA}; -use libsecp256k1::SecretKey; -use relay_utils::{ - initialize::initialize_relay, - metrics::{MetricsAddress, MetricsParams}, -}; -use sp_core::crypto::Pair; -use substrate_sync_loop::SubstrateSyncParams; - -use headers_relay::sync::HeadersSyncParams; -use relay_ethereum_client::{ - ConnectionParams as EthereumConnectionParams, SigningParams as EthereumSigningParams, -}; -use relay_rialto_client::SigningParams as RialtoSigningParams; -use relay_substrate_client::ConnectionParams as SubstrateConnectionParams; -use std::sync::Arc; - -fn main() { - initialize_relay(); - - let yaml = clap::load_yaml!("cli.yml"); - let matches = clap::App::from_yaml(yaml).get_matches(); - async_std::task::block_on(run_command(&matches)); -} - -async fn run_command(matches: &clap::ArgMatches<'_>) { - match matches.subcommand() { - ("eth-to-sub", Some(eth_to_sub_matches)) => { - log::info!(target: "bridge", "Starting ETH ➡ SUB relay."); - if ethereum_sync_loop::run(match ethereum_sync_params(eth_to_sub_matches) { - Ok(ethereum_sync_params) => ethereum_sync_params, - Err(err) => { - log::error!(target: "bridge", "Error parsing parameters: {}", err); - return - }, - }) - .await - .is_err() - { - log::error!(target: "bridge", "Unable to get Substrate genesis block for Ethereum sync."); - }; - }, - ("sub-to-eth", Some(sub_to_eth_matches)) => { - log::info!(target: "bridge", "Starting SUB ➡ ETH relay."); - if substrate_sync_loop::run(match substrate_sync_params(sub_to_eth_matches) { - Ok(substrate_sync_params) => substrate_sync_params, - Err(err) => { - log::error!(target: "bridge", "Error parsing parameters: {}", err); - return - }, - }) - .await - .is_err() - { - log::error!(target: "bridge", "Unable to get Substrate genesis block for Substrate sync."); - }; - }, - ("eth-deploy-contract", Some(eth_deploy_matches)) => { - log::info!(target: "bridge", "Deploying ETH contracts."); - ethereum_deploy_contract::run( - match ethereum_deploy_contract_params(eth_deploy_matches) { - Ok(ethereum_deploy_params) => ethereum_deploy_params, - Err(err) => { - log::error!(target: "bridge", "Error during contract deployment: {}", err); - return - }, - }, - ) - .await; - }, - ("eth-submit-exchange-tx", Some(eth_exchange_submit_matches)) => { - log::info!(target: "bridge", "Submitting ETH ➡ SUB exchange transaction."); - ethereum_exchange_submit::run( - match ethereum_exchange_submit_params(eth_exchange_submit_matches) { - Ok(eth_exchange_submit_params) => eth_exchange_submit_params, - Err(err) => { - log::error!(target: "bridge", "Error submitting Eethereum exchange transaction: {}", err); - return - }, - }, - ) - .await; - }, - ("eth-exchange-sub", Some(eth_exchange_matches)) => { - log::info!(target: "bridge", "Starting ETH ➡ SUB exchange transactions relay."); - ethereum_exchange::run(match ethereum_exchange_params(eth_exchange_matches) { - Ok(eth_exchange_params) => eth_exchange_params, - Err(err) => { - log::error!(target: "bridge", "Error relaying Ethereum transactions proofs: {}", err); - return - }, - }) - .await; - }, - ("", _) => { - log::error!(target: "bridge", "No subcommand specified"); - }, - _ => unreachable!("all possible subcommands are checked above; qed"), - } -} - -fn ethereum_connection_params( - matches: &clap::ArgMatches, -) -> anyhow::Result { - let mut params = EthereumConnectionParams::default(); - if let Some(eth_host) = matches.value_of("eth-host") { - params.host = eth_host.into(); - } - if let Some(eth_port) = matches.value_of("eth-port") { - params.port = eth_port.parse().map_err(|e| anyhow!("Failed to parse eth-port: {}", e))?; - } - Ok(params) -} - -fn ethereum_signing_params(matches: &clap::ArgMatches) -> anyhow::Result { - let mut params = EthereumSigningParams::default(); - if let Some(eth_signer) = matches.value_of("eth-signer") { - params.signer = SecretKey::parse_slice( - &hex::decode(eth_signer).map_err(|e| anyhow!("Failed to parse eth-signer: {}", e))?, - ) - .map_err(|e| anyhow!("Invalid eth-signer: {}", e))?; - } - if let Some(eth_chain_id) = matches.value_of("eth-chain-id") { - params.chain_id = eth_chain_id - .parse::() - .map_err(|e| anyhow!("Failed to parse eth-chain-id: {}", e))?; - } - Ok(params) -} - -fn substrate_connection_params( - matches: &clap::ArgMatches, -) -> anyhow::Result { - let mut params = SubstrateConnectionParams::default(); - if let Some(sub_host) = matches.value_of("sub-host") { - params.host = sub_host.into(); - } - if let Some(sub_port) = matches.value_of("sub-port") { - params.port = sub_port.parse().map_err(|e| anyhow!("Failed to parse sub-port: {}", e))?; - } - Ok(params) -} - -fn rialto_signing_params(matches: &clap::ArgMatches) -> anyhow::Result { - let mut params = sp_keyring::AccountKeyring::Alice.pair(); - - if let Some(sub_signer) = matches.value_of("sub-signer") { - let sub_signer_password = matches.value_of("sub-signer-password"); - params = sp_core::sr25519::Pair::from_string(sub_signer, sub_signer_password) - .map_err(|e| anyhow!("Failed to parse sub-signer: {:?}", e))?; - } - Ok(params) -} - -fn ethereum_sync_params(matches: &clap::ArgMatches) -> anyhow::Result { - use crate::ethereum_sync_loop::consts::*; - - let mut sync_params = HeadersSyncParams { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - max_headers_in_single_submit: MAX_HEADERS_IN_SINGLE_SUBMIT, - max_headers_size_in_single_submit: MAX_HEADERS_SIZE_IN_SINGLE_SUBMIT, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - }; - - match matches.value_of("sub-tx-mode") { - Some("signed") => sync_params.target_tx_mode = TargetTransactionMode::Signed, - Some("unsigned") => { - sync_params.target_tx_mode = TargetTransactionMode::Unsigned; - - // tx pool won't accept too much unsigned transactions - sync_params.max_headers_in_submitted_status = 10; - }, - Some("backup") => sync_params.target_tx_mode = TargetTransactionMode::Backup, - Some(mode) => return Err(anyhow!("Invalid sub-tx-mode: {}", mode)), - None => sync_params.target_tx_mode = TargetTransactionMode::Signed, - } - - let params = EthereumSyncParams { - eth_params: ethereum_connection_params(matches)?, - sub_params: substrate_connection_params(matches)?, - sub_sign: rialto_signing_params(matches)?, - metrics_params: metrics_params(matches)?, - instance: instance_params(matches)?, - sync_params, - }; - - log::debug!(target: "bridge", "Ethereum sync params: {:?}", params); - - Ok(params) -} - -fn substrate_sync_params(matches: &clap::ArgMatches) -> anyhow::Result { - use crate::substrate_sync_loop::consts::*; - - let eth_contract_address: relay_ethereum_client::types::Address = - if let Some(eth_contract) = matches.value_of("eth-contract") { - eth_contract.parse()? - } else { - "731a10897d267e19b34503ad902d0a29173ba4b1" - .parse() - .expect("address is hardcoded, thus valid; qed") - }; - - let params = SubstrateSyncParams { - sub_params: substrate_connection_params(matches)?, - eth_params: ethereum_connection_params(matches)?, - eth_sign: ethereum_signing_params(matches)?, - metrics_params: metrics_params(matches)?, - sync_params: HeadersSyncParams { - max_future_headers_to_download: MAX_FUTURE_HEADERS_TO_DOWNLOAD, - max_headers_in_submitted_status: MAX_SUBMITTED_HEADERS, - max_headers_in_single_submit: MAX_SUBMITTED_HEADERS, - max_headers_size_in_single_submit: std::usize::MAX, - prune_depth: PRUNE_DEPTH, - target_tx_mode: TargetTransactionMode::Signed, - }, - eth_contract_address, - }; - - log::debug!(target: "bridge", "Substrate sync params: {:?}", params); - - Ok(params) -} - -fn ethereum_deploy_contract_params( - matches: &clap::ArgMatches, -) -> anyhow::Result { - let eth_contract_code = - parse_hex_argument(matches, "eth-contract-code")?.unwrap_or_else(|| { - hex::decode(include_str!("../res/substrate-bridge-bytecode.hex")) - .expect("code is hardcoded, thus valid; qed") - }); - let sub_initial_authorities_set_id = matches - .value_of("sub-authorities-set-id") - .map(|set| { - set.parse() - .map_err(|e| anyhow!("Failed to parse sub-authorities-set-id: {}", e)) - }) - .transpose()?; - let sub_initial_authorities_set = parse_hex_argument(matches, "sub-authorities-set")?; - let sub_initial_header = parse_hex_argument(matches, "sub-initial-header")?; - - let params = EthereumDeployContractParams { - eth_params: ethereum_connection_params(matches)?, - eth_sign: ethereum_signing_params(matches)?, - sub_params: substrate_connection_params(matches)?, - sub_initial_authorities_set_id, - sub_initial_authorities_set, - sub_initial_header, - eth_contract_code, - }; - - log::debug!(target: "bridge", "Deploy params: {:?}", params); - - Ok(params) -} - -fn ethereum_exchange_submit_params( - matches: &clap::ArgMatches, -) -> anyhow::Result { - let eth_nonce = matches - .value_of("eth-nonce") - .map(|eth_nonce| { - relay_ethereum_client::types::U256::from_dec_str(eth_nonce) - .map_err(|e| anyhow!("Failed to parse eth-nonce: {}", e)) - }) - .transpose()?; - - let eth_amount = matches - .value_of("eth-amount") - .map(|eth_amount| { - eth_amount.parse().map_err(|e| anyhow!("Failed to parse eth-amount: {}", e)) - }) - .transpose()? - .unwrap_or_else(|| { - // This is in Wei, represents 1 ETH - 1_000_000_000_000_000_000_u64.into() - }); - - // This is the well-known Substrate account of Ferdie - let default_recepient = - hex!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c"); - - let sub_recipient = if let Some(sub_recipient) = matches.value_of("sub-recipient") { - hex::decode(&sub_recipient) - .map_err(|err| err.to_string()) - .and_then(|vsub_recipient| { - let expected_len = default_recepient.len(); - if expected_len != vsub_recipient.len() { - Err(format!("invalid length. Expected {} bytes", expected_len)) - } else { - let mut sub_recipient = default_recepient; - sub_recipient.copy_from_slice(&vsub_recipient[..expected_len]); - Ok(sub_recipient) - } - }) - .map_err(|e| anyhow!("Failed to parse sub-recipient: {}", e))? - } else { - default_recepient - }; - - let params = EthereumExchangeSubmitParams { - eth_params: ethereum_connection_params(matches)?, - eth_sign: ethereum_signing_params(matches)?, - eth_nonce, - eth_amount, - sub_recipient, - }; - - log::debug!(target: "bridge", "Submit Ethereum exchange tx params: {:?}", params); - - Ok(params) -} - -fn ethereum_exchange_params(matches: &clap::ArgMatches) -> anyhow::Result { - let mode = match matches.value_of("eth-tx-hash") { - Some(eth_tx_hash) => ethereum_exchange::ExchangeRelayMode::Single( - eth_tx_hash.parse().map_err(|e| anyhow!("Failed to parse eth-tx-hash: {}", e))?, - ), - None => ethereum_exchange::ExchangeRelayMode::Auto( - matches - .value_of("eth-start-with-block") - .map(|eth_start_with_block| { - eth_start_with_block - .parse() - .map_err(|e| anyhow!("Failed to parse eth-start-with-block: {}", e)) - }) - .transpose()?, - ), - }; - - let params = EthereumExchangeParams { - eth_params: ethereum_connection_params(matches)?, - sub_params: substrate_connection_params(matches)?, - sub_sign: rialto_signing_params(matches)?, - metrics_params: metrics_params(matches)?, - instance: instance_params(matches)?, - mode, - }; - - log::debug!(target: "bridge", "Ethereum exchange params: {:?}", params); - - Ok(params) -} - -fn metrics_params(matches: &clap::ArgMatches) -> anyhow::Result { - if matches.is_present("no-prometheus") { - return Ok(None.into()) - } - - let mut metrics_params = MetricsAddress::default(); - - if let Some(prometheus_host) = matches.value_of("prometheus-host") { - metrics_params.host = prometheus_host.into(); - } - if let Some(prometheus_port) = matches.value_of("prometheus-port") { - metrics_params.port = prometheus_port - .parse() - .map_err(|e| anyhow!("Failed to parse prometheus-port: {}", e))?; - } - - Ok(Some(metrics_params).into()) -} - -fn instance_params(matches: &clap::ArgMatches) -> anyhow::Result> { - let instance = if let Some(instance) = matches.value_of("sub-pallet-instance") { - match instance.to_lowercase().as_str() { - "rialto" => Arc::new(RialtoPoA) as Arc, - "kovan" => Arc::new(Kovan), - _ => return Err(anyhow!("Unsupported bridge pallet instance")), - } - } else { - unreachable!("CLI config enforces a default instance, can never be None") - }; - - Ok(instance) -} - -fn parse_hex_argument(matches: &clap::ArgMatches, arg: &str) -> anyhow::Result>> { - match matches.value_of(arg) { - Some(value) => - Ok(Some(hex::decode(value).map_err(|e| anyhow!("Failed to parse {}: {}", arg, e))?)), - None => Ok(None), - } -} diff --git a/relays/bin-ethereum/src/rialto_client.rs b/relays/bin-ethereum/src/rialto_client.rs deleted file mode 100644 index 1dadf9f7ddff5..0000000000000 --- a/relays/bin-ethereum/src/rialto_client.rs +++ /dev/null @@ -1,300 +0,0 @@ -// 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 . - -use crate::{ - ethereum_sync_loop::QueuedEthereumHeader, instances::BridgeInstance, rpc_errors::RpcError, -}; - -use async_trait::async_trait; -use bp_eth_poa::AuraHeader as SubstrateEthereumHeader; -use codec::{Decode, Encode}; -use headers_relay::sync_types::SubmittedHeaders; -use relay_ethereum_client::types::HeaderId as EthereumHeaderId; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - Client as SubstrateClient, TransactionSignScheme, UnsignedTransaction, -}; -use relay_utils::HeaderId; -use sp_core::{crypto::Pair, Bytes}; -use std::{collections::VecDeque, sync::Arc}; - -const ETH_API_IMPORT_REQUIRES_RECEIPTS: &str = "RialtoPoAHeaderApi_is_import_requires_receipts"; -const ETH_API_IS_KNOWN_BLOCK: &str = "RialtoPoAHeaderApi_is_known_block"; -const ETH_API_BEST_BLOCK: &str = "RialtoPoAHeaderApi_best_block"; -const ETH_API_BEST_FINALIZED_BLOCK: &str = "RialtoPoAHeaderApi_finalized_block"; -const EXCH_API_FILTER_TRANSACTION_PROOF: &str = - "RialtoCurrencyExchangeApi_filter_transaction_proof"; - -type RpcResult = std::result::Result; - -/// A trait which contains methods that work by using multiple low-level RPCs, or more complicated -/// interactions involving, for example, an Ethereum bridge module. -#[async_trait] -pub trait SubstrateHighLevelRpc { - /// Returns the best Ethereum block that Substrate runtime knows of. - async fn best_ethereum_block(&self) -> RpcResult; - /// Returns best finalized Ethereum block that Substrate runtime knows of. - async fn best_ethereum_finalized_block(&self) -> RpcResult; - /// Returns whether transactions receipts are required for Ethereum header submission. - async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult; - /// Returns whether the given Ethereum header is known to the Substrate runtime. - async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult; -} - -#[async_trait] -impl SubstrateHighLevelRpc for SubstrateClient { - async fn best_ethereum_block(&self) -> RpcResult { - let call = ETH_API_BEST_BLOCK.to_string(); - let data = Bytes(Vec::new()); - - let encoded_response = self.state_call(call, data, None).await?; - let decoded_response: (u64, bp_eth_poa::H256) = - Decode::decode(&mut &encoded_response.0[..])?; - - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); - Ok(best_header_id) - } - - async fn best_ethereum_finalized_block(&self) -> RpcResult { - let call = ETH_API_BEST_FINALIZED_BLOCK.to_string(); - let data = Bytes(Vec::new()); - - let encoded_response = self.state_call(call, data, None).await?; - let decoded_response: (u64, bp_eth_poa::H256) = - Decode::decode(&mut &encoded_response.0[..])?; - - let best_header_id = HeaderId(decoded_response.0, decoded_response.1); - Ok(best_header_id) - } - - async fn ethereum_receipts_required(&self, header: SubstrateEthereumHeader) -> RpcResult { - let call = ETH_API_IMPORT_REQUIRES_RECEIPTS.to_string(); - let data = Bytes(header.encode()); - - let encoded_response = self.state_call(call, data, None).await?; - let receipts_required: bool = Decode::decode(&mut &encoded_response.0[..])?; - - Ok(receipts_required) - } - - // The Substrate module could prune old headers. So this function could return false even - // if header is synced. And we'll mark corresponding Ethereum header as Orphan. - // - // But when we read the best header from Substrate next time, we will know that - // there's a better header. This Orphan will either be marked as synced, or - // eventually pruned. - async fn ethereum_header_known(&self, header_id: EthereumHeaderId) -> RpcResult { - let call = ETH_API_IS_KNOWN_BLOCK.to_string(); - let data = Bytes(header_id.1.encode()); - - let encoded_response = self.state_call(call, data, None).await?; - let is_known_block: bool = Decode::decode(&mut &encoded_response.0[..])?; - - Ok(is_known_block) - } -} - -/// A trait for RPC calls which are used to submit Ethereum headers to a Substrate -/// runtime. These are typically calls which use a combination of other low-level RPC -/// calls. -#[async_trait] -pub trait SubmitEthereumHeaders { - /// Submits Ethereum header to Substrate runtime. - async fn submit_ethereum_headers( - &self, - params: RialtoSigningParams, - instance: Arc, - headers: Vec, - sign_transactions: bool, - ) -> SubmittedHeaders; - - /// Submits signed Ethereum header to Substrate runtime. - async fn submit_signed_ethereum_headers( - &self, - params: RialtoSigningParams, - instance: Arc, - headers: Vec, - ) -> SubmittedHeaders; - - /// Submits unsigned Ethereum header to Substrate runtime. - async fn submit_unsigned_ethereum_headers( - &self, - instance: Arc, - headers: Vec, - ) -> SubmittedHeaders; -} - -#[async_trait] -impl SubmitEthereumHeaders for SubstrateClient { - async fn submit_ethereum_headers( - &self, - params: RialtoSigningParams, - instance: Arc, - headers: Vec, - sign_transactions: bool, - ) -> SubmittedHeaders { - if sign_transactions { - self.submit_signed_ethereum_headers(params, instance, headers).await - } else { - self.submit_unsigned_ethereum_headers(instance, headers).await - } - } - - async fn submit_signed_ethereum_headers( - &self, - params: RialtoSigningParams, - instance: Arc, - headers: Vec, - ) -> SubmittedHeaders { - let ids = headers.iter().map(|header| header.id()).collect(); - let genesis_hash = *self.genesis_hash(); - let submission_result = async { - self.submit_signed_extrinsic( - (*params.public().as_array_ref()).into(), - move |_, transaction_nonce| { - Bytes( - Rialto::sign_transaction( - genesis_hash, - ¶ms, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - instance.build_signed_header_call(headers), - transaction_nonce, - ), - ) - .encode(), - ) - }, - ) - .await?; - Ok(()) - } - .await; - - match submission_result { - Ok(_) => SubmittedHeaders { - submitted: ids, - incomplete: Vec::new(), - rejected: Vec::new(), - fatal_error: None, - }, - Err(error) => SubmittedHeaders { - submitted: Vec::new(), - incomplete: Vec::new(), - rejected: ids, - fatal_error: Some(error), - }, - } - } - - async fn submit_unsigned_ethereum_headers( - &self, - instance: Arc, - headers: Vec, - ) -> SubmittedHeaders { - let mut ids = headers.iter().map(|header| header.id()).collect::>(); - let mut submitted_headers = SubmittedHeaders::default(); - - for header in headers { - let id = ids.pop_front().expect("both collections have same size; qed"); - - let call = instance.build_unsigned_header_call(header); - let transaction = create_unsigned_submit_transaction(call); - - match self.submit_unsigned_extrinsic(Bytes(transaction.encode())).await { - Ok(_) => submitted_headers.submitted.push(id), - Err(error) => { - submitted_headers.rejected.push(id); - submitted_headers.rejected.extend(ids); - submitted_headers.fatal_error = Some(error.into()); - break - }, - } - } - - submitted_headers - } -} - -/// A trait for RPC calls which are used to submit proof of Ethereum exchange transaction to a -/// Substrate runtime. These are typically calls which use a combination of other low-level RPC -/// calls. -#[async_trait] -pub trait SubmitEthereumExchangeTransactionProof { - /// Pre-verify Ethereum exchange transaction proof. - async fn verify_exchange_transaction_proof( - &self, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult; - /// Submits Ethereum exchange transaction proof to Substrate runtime. - async fn submit_exchange_transaction_proof( - &self, - params: RialtoSigningParams, - instance: Arc, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult<()>; -} - -#[async_trait] -impl SubmitEthereumExchangeTransactionProof for SubstrateClient { - async fn verify_exchange_transaction_proof( - &self, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult { - let call = EXCH_API_FILTER_TRANSACTION_PROOF.to_string(); - let data = Bytes(proof.encode()); - - let encoded_response = self.state_call(call, data, None).await?; - let is_allowed: bool = Decode::decode(&mut &encoded_response.0[..])?; - - Ok(is_allowed) - } - - async fn submit_exchange_transaction_proof( - &self, - params: RialtoSigningParams, - instance: Arc, - proof: rialto_runtime::exchange::EthereumTransactionInclusionProof, - ) -> RpcResult<()> { - let genesis_hash = *self.genesis_hash(); - self.submit_signed_extrinsic( - (*params.public().as_array_ref()).into(), - move |_, transaction_nonce| { - Bytes( - Rialto::sign_transaction( - genesis_hash, - ¶ms, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - instance.build_currency_exchange_call(proof), - transaction_nonce, - ), - ) - .encode(), - ) - }, - ) - .await?; - Ok(()) - } -} - -/// Create unsigned Substrate transaction for submitting Ethereum header. -fn create_unsigned_submit_transaction( - call: rialto_runtime::Call, -) -> rialto_runtime::UncheckedExtrinsic { - rialto_runtime::UncheckedExtrinsic::new_unsigned(call) -} diff --git a/relays/bin-ethereum/src/rpc_errors.rs b/relays/bin-ethereum/src/rpc_errors.rs deleted file mode 100644 index e91bc363839b6..0000000000000 --- a/relays/bin-ethereum/src/rpc_errors.rs +++ /dev/null @@ -1,67 +0,0 @@ -// 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 . - -use relay_ethereum_client::Error as EthereumNodeError; -use relay_substrate_client::Error as SubstrateNodeError; -use relay_utils::MaybeConnectionError; -use thiserror::Error; - -/// Contains common errors that can occur when -/// interacting with a Substrate or Ethereum node -/// through RPC. -#[derive(Debug, Error)] -pub enum RpcError { - /// The arguments to the RPC method failed to serialize. - #[error("RPC arguments serialization failed: {0}")] - Serialization(#[from] serde_json::Error), - /// An error occurred when interacting with an Ethereum node. - #[error("Ethereum node error: {0}")] - Ethereum(#[from] EthereumNodeError), - /// An error occurred when interacting with a Substrate node. - #[error("Substrate node error: {0}")] - Substrate(#[from] SubstrateNodeError), - /// Error running relay loop. - #[error("{0}")] - SyncLoop(String), -} - -impl From for String { - fn from(err: RpcError) -> Self { - format!("{}", err) - } -} - -impl From for RpcError { - fn from(err: ethabi::Error) -> Self { - Self::Ethereum(EthereumNodeError::ResponseParseFailed(format!("{}", err))) - } -} - -impl MaybeConnectionError for RpcError { - fn is_connection_error(&self) -> bool { - match self { - RpcError::Ethereum(ref error) => error.is_connection_error(), - RpcError::Substrate(ref error) => error.is_connection_error(), - _ => false, - } - } -} - -impl From for RpcError { - fn from(err: codec::Error) -> Self { - Self::Substrate(SubstrateNodeError::ResponseParseFailed(err)) - } -} diff --git a/relays/bin-ethereum/src/substrate_sync_loop.rs b/relays/bin-ethereum/src/substrate_sync_loop.rs deleted file mode 100644 index 4b5bd4fa7326c..0000000000000 --- a/relays/bin-ethereum/src/substrate_sync_loop.rs +++ /dev/null @@ -1,204 +0,0 @@ -// 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 . - -//! Rialto-Substrate -> Ethereum PoA synchronization. - -use crate::{ethereum_client::EthereumHighLevelRpc, rpc_errors::RpcError}; - -use async_trait::async_trait; -use codec::Encode; -use headers_relay::{ - sync::HeadersSyncParams, - sync_loop::TargetClient, - sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, -}; -use relay_ethereum_client::{ - types::Address, Client as EthereumClient, ConnectionParams as EthereumConnectionParams, - SigningParams as EthereumSigningParams, -}; -use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{ - headers_source::HeadersSource, Chain as SubstrateChain, Client as SubstrateClient, - ConnectionParams as SubstrateConnectionParams, -}; -use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient}; -use sp_runtime::EncodedJustification; - -use std::{collections::HashSet, fmt::Debug, time::Duration}; - -pub mod consts { - use super::*; - - /// Interval at which we check new Ethereum blocks. - pub const ETHEREUM_TICK_INTERVAL: Duration = Duration::from_secs(5); - /// Max Ethereum headers we want to have in all 'before-submitted' states. - pub const MAX_FUTURE_HEADERS_TO_DOWNLOAD: usize = 8; - /// Max Ethereum headers count we want to have in 'submitted' state. - pub const MAX_SUBMITTED_HEADERS: usize = 4; - /// Max depth of in-memory headers in all states. Past this depth they will be forgotten - /// (pruned). - pub const PRUNE_DEPTH: u32 = 256; -} - -/// Substrate synchronization parameters. -#[derive(Debug)] -pub struct SubstrateSyncParams { - /// Substrate connection params. - pub sub_params: SubstrateConnectionParams, - /// Ethereum connection params. - pub eth_params: EthereumConnectionParams, - /// Ethereum signing params. - pub eth_sign: EthereumSigningParams, - /// Ethereum bridge contract address. - pub eth_contract_address: Address, - /// Synchronization parameters. - pub sync_params: HeadersSyncParams, - /// Metrics parameters. - pub metrics_params: MetricsParams, -} - -/// Substrate synchronization pipeline. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct SubstrateHeadersSyncPipeline; - -impl HeadersSyncPipeline for SubstrateHeadersSyncPipeline { - const SOURCE_NAME: &'static str = "Substrate"; - const TARGET_NAME: &'static str = "Ethereum"; - - type Hash = rialto_runtime::Hash; - type Number = rialto_runtime::BlockNumber; - type Header = RialtoSyncHeader; - type Extra = (); - type Completion = EncodedJustification; - - fn estimate_size(source: &QueuedHeader) -> usize { - source.header().encode().len() - } -} - -/// Queued substrate header ID. -pub type QueuedRialtoHeader = QueuedHeader; - -/// Rialto node as headers source. -type SubstrateHeadersSource = HeadersSource; - -/// Ethereum client as Substrate headers target. -#[derive(Clone)] -struct EthereumHeadersTarget { - /// Ethereum node client. - client: EthereumClient, - /// Bridge contract address. - contract: Address, - /// Ethereum signing params. - sign_params: EthereumSigningParams, -} - -impl EthereumHeadersTarget { - fn new(client: EthereumClient, contract: Address, sign_params: EthereumSigningParams) -> Self { - Self { client, contract, sign_params } - } -} - -#[async_trait] -impl RelayClient for EthereumHeadersTarget { - type Error = RpcError; - - async fn reconnect(&mut self) -> Result<(), RpcError> { - self.client.reconnect().await.map_err(Into::into) - } -} - -#[async_trait] -impl TargetClient for EthereumHeadersTarget { - async fn best_header_id(&self) -> Result { - // we can't continue to relay headers if Ethereum node is out of sync, because - // it may have already received (some of) headers that we're going to relay - self.client.ensure_synced().await?; - - self.client.best_substrate_block(self.contract).await - } - - async fn is_known_header( - &self, - id: RialtoHeaderId, - ) -> Result<(RialtoHeaderId, bool), RpcError> { - self.client.substrate_header_known(self.contract, id).await - } - - async fn submit_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders { - self.client - .submit_substrate_headers(self.sign_params.clone(), self.contract, headers) - .await - } - - async fn incomplete_headers_ids(&self) -> Result, RpcError> { - self.client.incomplete_substrate_headers(self.contract).await - } - - async fn complete_header( - &self, - id: RialtoHeaderId, - completion: EncodedJustification, - ) -> Result { - self.client - .complete_substrate_header(self.sign_params.clone(), self.contract, id, completion) - .await - } - - async fn requires_extra( - &self, - header: QueuedRialtoHeader, - ) -> Result<(RialtoHeaderId, bool), RpcError> { - Ok((header.header().id(), false)) - } -} - -/// Run Substrate headers synchronization. -pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { - let SubstrateSyncParams { - sub_params, - eth_params, - eth_sign, - eth_contract_address, - sync_params, - metrics_params, - } = params; - - let eth_client = EthereumClient::new(eth_params).await; - let sub_client = SubstrateClient::::new(sub_params).await; - - let target = EthereumHeadersTarget::new(eth_client, eth_contract_address, eth_sign); - let source = SubstrateHeadersSource::new(sub_client); - - headers_relay::sync_loop::run( - source, - Rialto::AVERAGE_BLOCK_INTERVAL, - target, - consts::ETHEREUM_TICK_INTERVAL, - (), - sync_params, - metrics_params, - futures::future::pending(), - ) - .await - .map_err(|e| RpcError::SyncLoop(e.to_string()))?; - - Ok(()) -} diff --git a/relays/bin-ethereum/src/substrate_types.rs b/relays/bin-ethereum/src/substrate_types.rs deleted file mode 100644 index f9e6c29c6a650..0000000000000 --- a/relays/bin-ethereum/src/substrate_types.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2020-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 . - -//! Converting between Ethereum headers and bridge module types. - -use bp_eth_poa::{ - AuraHeader as SubstrateEthereumHeader, LogEntry as SubstrateEthereumLogEntry, - Receipt as SubstrateEthereumReceipt, TransactionOutcome as SubstrateEthereumTransactionOutcome, -}; -use relay_ethereum_client::types::{ - Header as EthereumHeader, Receipt as EthereumReceipt, - HEADER_ID_PROOF as ETHEREUM_HEADER_ID_PROOF, -}; - -/// Convert Ethereum header into Ethereum header for Substrate. -pub fn into_substrate_ethereum_header(header: &EthereumHeader) -> SubstrateEthereumHeader { - SubstrateEthereumHeader { - parent_hash: header.parent_hash, - timestamp: header.timestamp.as_u64(), - number: header.number.expect(ETHEREUM_HEADER_ID_PROOF).as_u64(), - author: header.author, - transactions_root: header.transactions_root, - uncles_hash: header.uncles_hash, - extra_data: header.extra_data.0.clone(), - state_root: header.state_root, - receipts_root: header.receipts_root, - log_bloom: header.logs_bloom.unwrap_or_default().data().into(), - gas_used: header.gas_used, - gas_limit: header.gas_limit, - difficulty: header.difficulty, - seal: header.seal_fields.iter().map(|s| s.0.clone()).collect(), - } -} - -/// Convert Ethereum transactions receipts into Ethereum transactions receipts for Substrate. -pub fn into_substrate_ethereum_receipts( - receipts: &Option>, -) -> Option> { - receipts - .as_ref() - .map(|receipts| receipts.iter().map(into_substrate_ethereum_receipt).collect()) -} - -/// Convert Ethereum transactions receipt into Ethereum transactions receipt for Substrate. -pub fn into_substrate_ethereum_receipt(receipt: &EthereumReceipt) -> SubstrateEthereumReceipt { - SubstrateEthereumReceipt { - gas_used: receipt.cumulative_gas_used, - log_bloom: receipt.logs_bloom.data().into(), - logs: receipt - .logs - .iter() - .map(|log_entry| SubstrateEthereumLogEntry { - address: log_entry.address, - topics: log_entry.topics.clone(), - data: log_entry.data.0.clone(), - }) - .collect(), - outcome: match (receipt.status, receipt.root) { - (Some(status), None) => - SubstrateEthereumTransactionOutcome::StatusCode(status.as_u64() as u8), - (None, Some(root)) => SubstrateEthereumTransactionOutcome::StateRoot(root), - _ => SubstrateEthereumTransactionOutcome::Unknown, - }, - } -} diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index f496f78b29d2b..ca0e6dd8abff1 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -345,7 +345,7 @@ mod tests { // then assert!(format!("{:?}", call_hex).starts_with( - "0x10030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + "0x0c030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" )) } diff --git a/relays/client-ethereum/Cargo.toml b/relays/client-ethereum/Cargo.toml deleted file mode 100644 index 171988a32533b..0000000000000 --- a/relays/client-ethereum/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "relay-ethereum-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -async-std = "1.6.5" -bp-eth-poa = { path = "../../primitives/ethereum-poa" } -headers-relay = { path = "../headers" } -hex-literal = "0.3" -jsonrpsee-proc-macros = "0.3.1" -jsonrpsee-ws-client = "0.3.1" -libsecp256k1 = { version = "0.7", default-features = false, features = ["hmac"] } -log = "0.4.11" -relay-utils = { path = "../utils" } -tokio = "1.8" -web3 = { git = "https://github.com/svyatonik/rust-web3.git", branch = "bump-deps" } -thiserror = "1.0.26" diff --git a/relays/client-ethereum/src/client.rs b/relays/client-ethereum/src/client.rs deleted file mode 100644 index 48b7c9386f353..0000000000000 --- a/relays/client-ethereum/src/client.rs +++ /dev/null @@ -1,265 +0,0 @@ -// 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 . - -use crate::{ - rpc::Ethereum, - types::{ - Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, - SyncState, Transaction, TransactionHash, H256, U256, - }, - ConnectionParams, Error, Result, -}; - -use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}; -use relay_utils::relay_loop::RECONNECT_DELAY; -use std::{future::Future, sync::Arc}; - -/// Number of headers missing from the Ethereum node for us to consider node not synced. -const MAJOR_SYNC_BLOCKS: u64 = 5; - -/// The client used to interact with an Ethereum node through RPC. -#[derive(Clone)] -pub struct Client { - tokio: Arc, - params: ConnectionParams, - client: Arc, -} - -impl Client { - /// Create a new Ethereum RPC Client. - /// - /// This function will keep connecting to given Ethereum node until connection is established - /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. - pub async fn new(params: ConnectionParams) -> Self { - loop { - match Self::try_connect(params.clone()).await { - Ok(client) => return client, - Err(error) => log::error!( - target: "bridge", - "Failed to connect to Ethereum node: {:?}. Going to retry in {}s", - error, - RECONNECT_DELAY.as_secs(), - ), - } - - async_std::task::sleep(RECONNECT_DELAY).await; - } - } - - /// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been - /// established or error otherwise. - pub async fn try_connect(params: ConnectionParams) -> Result { - let (tokio, client) = Self::build_client(¶ms).await?; - Ok(Self { tokio, client, params }) - } - - /// Build client to use in connection. - async fn build_client( - params: &ConnectionParams, - ) -> Result<(Arc, Arc)> { - let tokio = tokio::runtime::Runtime::new()?; - let uri = format!("ws://{}:{}", params.host, params.port); - let client = tokio - .spawn(async move { RpcClientBuilder::default().build(&uri).await }) - .await??; - Ok((Arc::new(tokio), Arc::new(client))) - } - - /// Reopen client connection. - pub async fn reconnect(&mut self) -> Result<()> { - let (tokio, client) = Self::build_client(&self.params).await?; - self.tokio = tokio; - self.client = client; - Ok(()) - } -} - -impl Client { - /// Returns true if client is connected to at least one peer and is in synced state. - pub async fn ensure_synced(&self) -> Result<()> { - self.jsonrpsee_execute(move |client| async move { - match Ethereum::syncing(&*client).await? { - SyncState::NotSyncing => Ok(()), - SyncState::Syncing(syncing) => { - let missing_headers = - syncing.highest_block.saturating_sub(syncing.current_block); - if missing_headers > MAJOR_SYNC_BLOCKS.into() { - return Err(Error::ClientNotSynced(missing_headers)) - } - - Ok(()) - }, - } - }) - .await - } - - /// Estimate gas usage for the given call. - pub async fn estimate_gas(&self, call_request: CallRequest) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(Ethereum::estimate_gas(&*client, call_request).await?) - }) - .await - } - - /// Retrieve number of the best known block from the Ethereum node. - pub async fn best_block_number(&self) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(Ethereum::block_number(&*client).await?.as_u64()) - }) - .await - } - - /// Retrieve number of the best known block from the Ethereum node. - pub async fn header_by_number(&self, block_number: u64) -> Result
{ - self.jsonrpsee_execute(move |client| async move { - let get_full_tx_objects = false; - let header = - Ethereum::get_block_by_number(&*client, block_number, get_full_tx_objects).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(Error::IncompleteHeader), - } - }) - .await - } - - /// Retrieve block header by its hash from Ethereum node. - pub async fn header_by_hash(&self, hash: H256) -> Result
{ - self.jsonrpsee_execute(move |client| async move { - let get_full_tx_objects = false; - let header = Ethereum::get_block_by_hash(&*client, hash, get_full_tx_objects).await?; - match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() { - true => Ok(header), - false => Err(Error::IncompleteHeader), - } - }) - .await - } - - /// Retrieve block header and its transactions by its number from Ethereum node. - pub async fn header_by_number_with_transactions( - &self, - number: u64, - ) -> Result { - self.jsonrpsee_execute(move |client| async move { - let get_full_tx_objects = true; - let header = Ethereum::get_block_by_number_with_transactions( - &*client, - number, - get_full_tx_objects, - ) - .await?; - - let is_complete_header = - header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); - if !is_complete_header { - return Err(Error::IncompleteHeader) - } - - let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); - if !is_complete_transactions { - return Err(Error::IncompleteTransaction) - } - - Ok(header) - }) - .await - } - - /// Retrieve block header and its transactions by its hash from Ethereum node. - pub async fn header_by_hash_with_transactions( - &self, - hash: H256, - ) -> Result { - self.jsonrpsee_execute(move |client| async move { - let get_full_tx_objects = true; - let header = - Ethereum::get_block_by_hash_with_transactions(&*client, hash, get_full_tx_objects) - .await?; - - let is_complete_header = - header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some(); - if !is_complete_header { - return Err(Error::IncompleteHeader) - } - - let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some()); - if !is_complete_transactions { - return Err(Error::IncompleteTransaction) - } - - Ok(header) - }) - .await - } - - /// Retrieve transaction by its hash from Ethereum node. - pub async fn transaction_by_hash(&self, hash: H256) -> Result> { - self.jsonrpsee_execute(move |client| async move { - Ok(Ethereum::transaction_by_hash(&*client, hash).await?) - }) - .await - } - - /// Retrieve transaction receipt by transaction hash. - pub async fn transaction_receipt(&self, transaction_hash: H256) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(Ethereum::get_transaction_receipt(&*client, transaction_hash).await?) - }) - .await - } - - /// Get the nonce of the given account. - pub async fn account_nonce(&self, address: Address) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(Ethereum::get_transaction_count(&*client, address).await?) - }) - .await - } - - /// Submit an Ethereum transaction. - /// - /// The transaction must already be signed before sending it through this method. - pub async fn submit_transaction(&self, signed_raw_tx: SignedRawTx) -> Result { - self.jsonrpsee_execute(move |client| async move { - let transaction = Bytes(signed_raw_tx); - let tx_hash = Ethereum::submit_transaction(&*client, transaction).await?; - log::trace!(target: "bridge", "Sent transaction to Ethereum node: {:?}", tx_hash); - Ok(tx_hash) - }) - .await - } - - /// Call Ethereum smart contract. - pub async fn eth_call(&self, call_transaction: CallRequest) -> Result { - self.jsonrpsee_execute(move |client| async move { - Ok(Ethereum::call(&*client, call_transaction).await?) - }) - .await - } - - /// Execute jsonrpsee future in tokio context. - async fn jsonrpsee_execute(&self, make_jsonrpsee_future: MF) -> Result - where - MF: FnOnce(Arc) -> F + Send + 'static, - F: Future> + Send, - T: Send + 'static, - { - let client = self.client.clone(); - self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? - } -} diff --git a/relays/client-ethereum/src/error.rs b/relays/client-ethereum/src/error.rs deleted file mode 100644 index 6323b708fc024..0000000000000 --- a/relays/client-ethereum/src/error.rs +++ /dev/null @@ -1,82 +0,0 @@ -// 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 . - -//! Ethereum node RPC errors. - -use crate::types::U256; - -use jsonrpsee_ws_client::types::Error as RpcError; -use relay_utils::MaybeConnectionError; -use thiserror::Error; - -/// Result type used by Ethereum client. -pub type Result = std::result::Result; - -/// Errors that can occur only when interacting with -/// an Ethereum node through RPC. -#[derive(Debug, Error)] -pub enum Error { - /// IO error. - #[error("IO error: {0}")] - Io(#[from] std::io::Error), - /// An error that can occur when making an HTTP request to - /// an JSON-RPC client. - #[error("RPC error: {0}")] - RpcError(#[from] RpcError), - /// Failed to parse response. - #[error("Response parse failed: {0}")] - ResponseParseFailed(String), - /// We have received a header with missing fields. - #[error("Incomplete Ethereum Header Received (missing some of required fields - hash, number, logs_bloom).")] - IncompleteHeader, - /// We have received a transaction missing a `raw` field. - #[error("Incomplete Ethereum Transaction (missing required field - raw).")] - IncompleteTransaction, - /// An invalid Substrate block number was received from - /// an Ethereum node. - #[error("Received an invalid Substrate block from Ethereum Node.")] - InvalidSubstrateBlockNumber, - /// An invalid index has been received from an Ethereum node. - #[error("Received an invalid incomplete index from Ethereum Node.")] - InvalidIncompleteIndex, - /// The client we're connected to is not synced, so we can't rely on its state. Contains - /// number of unsynced headers. - #[error("Ethereum client is not synced: syncing {0} headers.")] - ClientNotSynced(U256), - /// Custom logic error. - #[error("{0}")] - Custom(String), -} - -impl From for Error { - fn from(error: tokio::task::JoinError) -> Self { - Error::Custom(format!("Failed to wait tokio task: {}", error)) - } -} - -impl MaybeConnectionError for Error { - fn is_connection_error(&self) -> bool { - matches!( - *self, - Error::RpcError(RpcError::Transport(_)) - // right now if connection to the ws server is dropped (after it is already established), - // we're getting this error - | Error::RpcError(RpcError::Internal(_)) - | Error::RpcError(RpcError::RestartNeeded(_)) - | Error::ClientNotSynced(_), - ) - } -} diff --git a/relays/client-ethereum/src/lib.rs b/relays/client-ethereum/src/lib.rs deleted file mode 100644 index fa4877f8e5cfc..0000000000000 --- a/relays/client-ethereum/src/lib.rs +++ /dev/null @@ -1,47 +0,0 @@ -// 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 . - -//! Tools to interact with (Open) Ethereum node using RPC methods. - -#![warn(missing_docs)] - -mod client; -mod error; -mod rpc; -mod sign; - -pub use crate::{ - client::Client, - error::{Error, Result}, - sign::{sign_and_submit_transaction, SigningParams}, -}; - -pub mod types; - -/// Ethereum-over-websocket connection params. -#[derive(Debug, Clone)] -pub struct ConnectionParams { - /// Websocket server host name. - pub host: String, - /// Websocket server TCP port. - pub port: u16, -} - -impl Default for ConnectionParams { - fn default() -> Self { - ConnectionParams { host: "localhost".into(), port: 8546 } - } -} diff --git a/relays/client-ethereum/src/rpc.rs b/relays/client-ethereum/src/rpc.rs deleted file mode 100644 index 2479338b1015c..0000000000000 --- a/relays/client-ethereum/src/rpc.rs +++ /dev/null @@ -1,51 +0,0 @@ -// 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 . - -//! Ethereum node RPC interface. - -use crate::types::{ - Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SyncState, Transaction, - TransactionHash, H256, U256, U64, -}; - -jsonrpsee_proc_macros::rpc_client_api! { - pub(crate) Ethereum { - #[rpc(method = "eth_syncing", positional_params)] - fn syncing() -> SyncState; - #[rpc(method = "eth_estimateGas", positional_params)] - fn estimate_gas(call_request: CallRequest) -> U256; - #[rpc(method = "eth_blockNumber", positional_params)] - fn block_number() -> U64; - #[rpc(method = "eth_getBlockByNumber", positional_params)] - fn get_block_by_number(block_number: U64, full_tx_objs: bool) -> Header; - #[rpc(method = "eth_getBlockByHash", positional_params)] - fn get_block_by_hash(hash: H256, full_tx_objs: bool) -> Header; - #[rpc(method = "eth_getBlockByNumber", positional_params)] - fn get_block_by_number_with_transactions(number: U64, full_tx_objs: bool) -> HeaderWithTransactions; - #[rpc(method = "eth_getBlockByHash", positional_params)] - fn get_block_by_hash_with_transactions(hash: H256, full_tx_objs: bool) -> HeaderWithTransactions; - #[rpc(method = "eth_getTransactionByHash", positional_params)] - fn transaction_by_hash(hash: H256) -> Option; - #[rpc(method = "eth_getTransactionReceipt", positional_params)] - fn get_transaction_receipt(transaction_hash: H256) -> Receipt; - #[rpc(method = "eth_getTransactionCount", positional_params)] - fn get_transaction_count(address: Address) -> U256; - #[rpc(method = "eth_submitTransaction", positional_params)] - fn submit_transaction(transaction: Bytes) -> TransactionHash; - #[rpc(method = "eth_call", positional_params)] - fn call(transaction_call: CallRequest) -> Bytes; - } -} diff --git a/relays/client-ethereum/src/sign.rs b/relays/client-ethereum/src/sign.rs deleted file mode 100644 index 86ddcc871c40e..0000000000000 --- a/relays/client-ethereum/src/sign.rs +++ /dev/null @@ -1,87 +0,0 @@ -// 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 . - -use crate::{ - types::{Address, CallRequest, U256}, - Client, Result, -}; -use bp_eth_poa::signatures::{secret_to_address, SignTransaction}; -use hex_literal::hex; -use libsecp256k1::SecretKey; - -/// Ethereum signing params. -#[derive(Clone, Debug)] -pub struct SigningParams { - /// Ethereum chain id. - pub chain_id: u64, - /// Ethereum transactions signer. - pub signer: SecretKey, - /// Gas price we agree to pay. - pub gas_price: U256, -} - -impl Default for SigningParams { - fn default() -> Self { - SigningParams { - chain_id: 0x11, // Parity dev chain - // account that has a lot of ether when we run instant seal engine - // address: 0x00a329c0648769a73afac7f9381e08fb43dbea72 - // secret: 0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7 - signer: SecretKey::parse(&hex!( - "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7" - )) - .expect("secret is hardcoded, thus valid; qed"), - gas_price: 8_000_000_000u64.into(), // 8 Gwei - } - } -} - -/// Sign and submit transaction using given Ethereum client. -pub async fn sign_and_submit_transaction( - client: &Client, - params: &SigningParams, - contract_address: Option
, - nonce: Option, - double_gas: bool, - encoded_call: Vec, -) -> Result<()> { - let nonce = if let Some(n) = nonce { - n - } else { - let address: Address = secret_to_address(¶ms.signer); - client.account_nonce(address).await? - }; - - let call_request = CallRequest { - to: contract_address, - data: Some(encoded_call.clone().into()), - ..Default::default() - }; - let gas = client.estimate_gas(call_request).await?; - - let raw_transaction = bp_eth_poa::UnsignedTransaction { - nonce, - to: contract_address, - value: U256::zero(), - gas: if double_gas { gas.saturating_mul(2.into()) } else { gas }, - gas_price: params.gas_price, - payload: encoded_call, - } - .sign_by(¶ms.signer, Some(params.chain_id)); - - let _ = client.submit_transaction(raw_transaction).await?; - Ok(()) -} diff --git a/relays/client-ethereum/src/types.rs b/relays/client-ethereum/src/types.rs deleted file mode 100644 index f589474aff1be..0000000000000 --- a/relays/client-ethereum/src/types.rs +++ /dev/null @@ -1,80 +0,0 @@ -// 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 . - -//! Common types that are used in relay <-> Ethereum node communications. - -use headers_relay::sync_types::SourceHeader; - -pub use web3::types::{Address, Bytes, CallRequest, SyncState, H256, U128, U256, U64}; - -/// When header is just received from the Ethereum node, we check that it has -/// both number and hash fields filled. -pub const HEADER_ID_PROOF: &str = "checked on retrieval; qed"; - -/// Ethereum transaction hash type. -pub type HeaderHash = H256; - -/// Ethereum transaction hash type. -pub type TransactionHash = H256; - -/// Ethereum transaction type. -pub type Transaction = web3::types::Transaction; - -/// Ethereum header type. -pub type Header = web3::types::Block; - -/// Ethereum header type used in headers sync. -#[derive(Clone, Debug, PartialEq)] -pub struct SyncHeader(Header); - -impl std::ops::Deref for SyncHeader { - type Target = Header; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// Ethereum header with transactions type. -pub type HeaderWithTransactions = web3::types::Block; - -/// Ethereum transaction receipt type. -pub type Receipt = web3::types::TransactionReceipt; - -/// Ethereum header ID. -pub type HeaderId = relay_utils::HeaderId; - -/// A raw Ethereum transaction that's been signed. -pub type SignedRawTx = Vec; - -impl From
for SyncHeader { - fn from(header: Header) -> Self { - Self(header) - } -} - -impl SourceHeader for SyncHeader { - fn id(&self) -> HeaderId { - relay_utils::HeaderId( - self.number.expect(HEADER_ID_PROOF).as_u64(), - self.hash.expect(HEADER_ID_PROOF), - ) - } - - fn parent_id(&self) -> HeaderId { - relay_utils::HeaderId(self.number.expect(HEADER_ID_PROOF).as_u64() - 1, self.parent_hash) - } -} From b87763b4ddc3eebd5daf08827ad23490960b4231 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu <31917973+acatangiu@users.noreply.github.com> Date: Tue, 16 Nov 2021 18:55:03 +0200 Subject: [PATCH 0601/1210] Remove unused `relays/headers` (#1216) * Decouple `relays/client-substrate` from `headers_relay` * Remove `blocks_in_state` from `SyncLoopMetrics` This metric was only relevant for PoA <> Substrate bridge. * Move `sync_loop_metrics.rs` to `relays/finality` * Remove unused `SyncLoopMetrics::update()` * Hook up SyncLoopMetrics to finality_loop * Delete now unused `relays/headers` Signed-off-by: acatangiu --- relays/client-substrate/Cargo.toml | 1 - relays/client-substrate/src/headers_source.rs | 108 -- relays/client-substrate/src/lib.rs | 1 - relays/client-substrate/src/sync_header.rs | 20 +- relays/finality/Cargo.toml | 1 - relays/finality/src/finality_loop.rs | 5 +- relays/finality/src/lib.rs | 1 + .../src/sync_loop_metrics.rs | 51 - relays/headers/Cargo.toml | 17 - relays/headers/src/headers.rs | 1703 ----------------- relays/headers/src/lib.rs | 33 - relays/headers/src/sync.rs | 529 ----- relays/headers/src/sync_loop.rs | 654 ------- relays/headers/src/sync_loop_tests.rs | 602 ------ relays/headers/src/sync_types.rs | 193 -- 15 files changed, 5 insertions(+), 3914 deletions(-) delete mode 100644 relays/client-substrate/src/headers_source.rs rename relays/{headers => finality}/src/sync_loop_metrics.rs (53%) delete mode 100644 relays/headers/Cargo.toml delete mode 100644 relays/headers/src/headers.rs delete mode 100644 relays/headers/src/lib.rs delete mode 100644 relays/headers/src/sync.rs delete mode 100644 relays/headers/src/sync_loop.rs delete mode 100644 relays/headers/src/sync_loop_tests.rs delete mode 100644 relays/headers/src/sync_types.rs diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 6a1173581e7a7..2eb07fdcde467 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -22,7 +22,6 @@ thiserror = "1.0.26" bp-header-chain = { path = "../../primitives/header-chain" } bp-runtime = { path = "../../primitives/runtime" } finality-relay = { path = "../finality" } -headers-relay = { path = "../headers" } relay-utils = { path = "../utils" } # Substrate Dependencies diff --git a/relays/client-substrate/src/headers_source.rs b/relays/client-substrate/src/headers_source.rs deleted file mode 100644 index e3839bf2c8ba1..0000000000000 --- a/relays/client-substrate/src/headers_source.rs +++ /dev/null @@ -1,108 +0,0 @@ -// 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 . - -//! Default generic implementation of headers source for basic Substrate client. - -use crate::{ - chain::{BlockWithJustification, Chain}, - client::Client, - error::Error, -}; - -use async_trait::async_trait; -use headers_relay::{ - sync_loop::SourceClient, - sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, -}; -use relay_utils::relay_loop::Client as RelayClient; -use sp_runtime::{traits::Header as HeaderT, EncodedJustification}; -use std::marker::PhantomData; - -/// Substrate node as headers source. -pub struct HeadersSource { - client: Client, - _phantom: PhantomData

, -} - -impl HeadersSource { - /// Create new headers source using given client. - pub fn new(client: Client) -> Self { - HeadersSource { client, _phantom: Default::default() } - } -} - -impl Clone for HeadersSource { - fn clone(&self) -> Self { - HeadersSource { client: self.client.clone(), _phantom: Default::default() } - } -} - -#[async_trait] -impl RelayClient for HeadersSource { - type Error = Error; - - async fn reconnect(&mut self) -> Result<(), Error> { - self.client.reconnect().await - } -} - -#[async_trait] -impl SourceClient

for HeadersSource -where - C: Chain, - C::BlockNumber: relay_utils::BlockNumberBase, - C::Header: Into, - P: HeadersSyncPipeline< - Extra = (), - Completion = EncodedJustification, - Hash = C::Hash, - Number = C::BlockNumber, - >, - P::Header: SourceHeader, -{ - async fn best_block_number(&self) -> Result { - // we **CAN** continue to relay headers if source node is out of sync, because - // target node may be missing headers that are already available at the source - Ok(*self.client.best_header().await?.number()) - } - - async fn header_by_hash(&self, hash: P::Hash) -> Result { - self.client.header_by_hash(hash).await.map(Into::into).map_err(Into::into) - } - - async fn header_by_number(&self, number: P::Number) -> Result { - self.client.header_by_number(number).await.map(Into::into).map_err(Into::into) - } - - async fn header_completion( - &self, - id: HeaderIdOf

, - ) -> Result<(HeaderIdOf

, Option), Error> { - let hash = id.1; - let signed_block = self.client.get_block(Some(hash)).await?; - let grandpa_justification = signed_block.justification().cloned(); - - Ok((id, grandpa_justification)) - } - - async fn header_extra( - &self, - id: HeaderIdOf

, - _header: QueuedHeader

, - ) -> Result<(HeaderIdOf

, ()), Error> { - Ok((id, ())) - } -} diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 1f6606ea287c3..51ddf852b9b6f 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -26,7 +26,6 @@ mod sync_header; pub mod finality_source; pub mod guard; -pub mod headers_source; pub mod metrics; use std::time::Duration; diff --git a/relays/client-substrate/src/sync_header.rs b/relays/client-substrate/src/sync_header.rs index 0b74dee690f21..ed3de6289ce01 100644 --- a/relays/client-substrate/src/sync_header.rs +++ b/relays/client-substrate/src/sync_header.rs @@ -16,13 +16,10 @@ use bp_header_chain::find_grandpa_authorities_scheduled_change; use finality_relay::SourceHeader as FinalitySourceHeader; -use headers_relay::sync_types::SourceHeader; -use num_traits::{CheckedSub, One}; -use relay_utils::HeaderId; use sp_runtime::traits::Header as HeaderT; /// Generic wrapper for `sp_runtime::traits::Header` based headers, that -/// implements `headers_relay::sync_types::SourceHeader` and may be used in headers sync directly. +/// implements `finality_relay::SourceHeader` and may be used in headers sync directly. #[derive(Clone, Debug, PartialEq)] pub struct SyncHeader

(Header); @@ -47,21 +44,6 @@ impl
From
for SyncHeader
{ } } -impl SourceHeader for SyncHeader
{ - fn id(&self) -> HeaderId { - relay_utils::HeaderId(*self.0.number(), self.hash()) - } - - fn parent_id(&self) -> HeaderId { - relay_utils::HeaderId( - self.number() - .checked_sub(&One::one()) - .expect("should never be called for genesis header"), - *self.parent_hash(), - ) - } -} - impl FinalitySourceHeader for SyncHeader
{ fn number(&self) -> Header::Number { *self.0.number() diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 944da9837ffcb..645ac10775baf 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -12,7 +12,6 @@ async-trait = "0.1.40" backoff = "0.2" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.5" -headers-relay = { path = "../headers" } log = "0.4.11" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 191d183837931..8fad11bf370c1 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -19,12 +19,13 @@ //! is the mandatory headers, which we always submit to the target node. For such headers, we //! assume that the persistent proof either exists, or will eventually become available. -use crate::{FinalityProof, FinalitySyncPipeline, SourceHeader}; +use crate::{ + sync_loop_metrics::SyncLoopMetrics, FinalityProof, FinalitySyncPipeline, SourceHeader, +}; use async_trait::async_trait; use backoff::backoff::Backoff; use futures::{select, Future, FutureExt, Stream, StreamExt}; -use headers_relay::sync_loop_metrics::SyncLoopMetrics; use num_traits::{One, Saturating}; use relay_utils::{ metrics::{GlobalMetrics, MetricsParams}, diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index 78ef33f1b376b..6421d13b787c8 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -28,6 +28,7 @@ use std::fmt::Debug; mod finality_loop; mod finality_loop_tests; +mod sync_loop_metrics; /// Finality proofs synchronization pipeline. pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { diff --git a/relays/headers/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs similarity index 53% rename from relays/headers/src/sync_loop_metrics.rs rename to relays/finality/src/sync_loop_metrics.rs index 1c558c25de9d5..1e4d910926ec8 100644 --- a/relays/headers/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -16,12 +16,6 @@ //! Metrics for headers synchronization relay loop. -use crate::{ - sync::HeadersSync, - sync_types::{HeaderStatus, HeadersSyncPipeline}, -}; - -use num_traits::Zero; use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; /// Headers sync metrics. @@ -29,8 +23,6 @@ use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusErro pub struct SyncLoopMetrics { /// Best syncing headers at "source" and "target" nodes. best_block_numbers: GaugeVec, - /// Number of headers in given states (see `HeaderStatus`). - blocks_in_state: GaugeVec, } impl SyncLoopMetrics { @@ -47,16 +39,6 @@ impl SyncLoopMetrics { )?, registry, )?, - blocks_in_state: register( - GaugeVec::new( - Opts::new( - metric_name(prefix, "blocks_in_state"), - "Number of blocks in given state", - ), - &["state"], - )?, - registry, - )?, }) } } @@ -75,37 +57,4 @@ impl SyncLoopMetrics { .with_label_values(&["target"]) .set(target_best_number.into()); } - - /// Update metrics. - pub fn update(&self, sync: &HeadersSync

) { - let headers = sync.headers(); - let source_best_number = sync.source_best_number().unwrap_or_else(Zero::zero); - let target_best_number = - sync.target_best_header().map(|id| id.0).unwrap_or_else(Zero::zero); - - self.update_best_block_at_source(source_best_number); - self.update_best_block_at_target(target_best_number); - - self.blocks_in_state - .with_label_values(&["maybe_orphan"]) - .set(headers.headers_in_status(HeaderStatus::MaybeOrphan) as _); - self.blocks_in_state - .with_label_values(&["orphan"]) - .set(headers.headers_in_status(HeaderStatus::Orphan) as _); - self.blocks_in_state - .with_label_values(&["maybe_extra"]) - .set(headers.headers_in_status(HeaderStatus::MaybeExtra) as _); - self.blocks_in_state - .with_label_values(&["extra"]) - .set(headers.headers_in_status(HeaderStatus::Extra) as _); - self.blocks_in_state - .with_label_values(&["ready"]) - .set(headers.headers_in_status(HeaderStatus::Ready) as _); - self.blocks_in_state - .with_label_values(&["incomplete"]) - .set(headers.headers_in_status(HeaderStatus::Incomplete) as _); - self.blocks_in_state - .with_label_values(&["submitted"]) - .set(headers.headers_in_status(HeaderStatus::Submitted) as _); - } } diff --git a/relays/headers/Cargo.toml b/relays/headers/Cargo.toml deleted file mode 100644 index 31d3166a99781..0000000000000 --- a/relays/headers/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "headers-relay" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -async-std = "1.6.5" -async-trait = "0.1.40" -backoff = "0.2" -futures = "0.3.5" -linked-hash-map = "0.5.3" -log = "0.4.11" -num-traits = "0.2" -parking_lot = "0.11.0" -relay-utils = { path = "../utils" } diff --git a/relays/headers/src/headers.rs b/relays/headers/src/headers.rs deleted file mode 100644 index 8d67c1cf48574..0000000000000 --- a/relays/headers/src/headers.rs +++ /dev/null @@ -1,1703 +0,0 @@ -// 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 . - -//! Headers queue - the intermediate buffer that is filled when headers are read -//! from the source chain. Headers are removed from the queue once they become -//! known to the target chain. Inside, there are several sub-queues, where headers -//! may stay until source/target chain state isn't updated. When a header reaches the -//! `ready` sub-queue, it may be submitted to the target chain. - -use crate::sync_types::{ - HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SourceHeader, -}; - -use linked_hash_map::LinkedHashMap; -use num_traits::{One, Zero}; -use relay_utils::HeaderId; -use std::{ - collections::{ - btree_map::Entry as BTreeMapEntry, hash_map::Entry as HashMapEntry, BTreeMap, HashMap, - HashSet, - }, - time::{Duration, Instant}, -}; - -type HeadersQueue

= BTreeMap< -

::Number, - HashMap<

::Hash, QueuedHeader

>, ->; -type SyncedChildren

= BTreeMap< -

::Number, - HashMap<

::Hash, HashSet>>, ->; -type KnownHeaders

= BTreeMap< -

::Number, - HashMap<

::Hash, HeaderStatus>, ->; - -/// We're trying to fetch completion data for single header at this interval. -const RETRY_FETCH_COMPLETION_INTERVAL: Duration = Duration::from_secs(20); - -/// Headers queue. -#[derive(Debug)] -pub struct QueuedHeaders { - /// Headers that are received from source node, but we (native sync code) have - /// never seen their parents. So we need to check if we can/should submit this header. - maybe_orphan: HeadersQueue

, - /// Headers that are received from source node, and we (native sync code) have - /// checked that Substrate runtime doesn't know their parents. So we need to submit parents - /// first. - orphan: HeadersQueue

, - /// Headers that are ready to be submitted to target node, but we need to check - /// whether submission requires extra data to be provided. - maybe_extra: HeadersQueue

, - /// Headers that are ready to be submitted to target node, but we need to retrieve - /// extra data first. - extra: HeadersQueue

, - /// Headers that are ready to be submitted to target node. - ready: HeadersQueue

, - /// Headers that are ready to be submitted to target node, but their ancestor is incomplete. - /// Thus we're waiting for these ancestors to be completed first. - /// Note that the incomplete header itself is synced and it isn't in this queue. - incomplete: HeadersQueue

, - /// Headers that are (we believe) currently submitted to target node by our, - /// not-yet mined transactions. - submitted: HeadersQueue

, - /// Synced headers children. We need it to support case when header is synced, but some of - /// its parents are incomplete. - synced_children: SyncedChildren

, - /// Pointers to all headers that we ever seen and we believe we can touch in the future. - known_headers: KnownHeaders

, - /// Headers that are waiting for completion data from source node. Mapped (and auto-sorted - /// by) to the last fetch time. - incomplete_headers: LinkedHashMap, Option>, - /// Headers that are waiting to be completed at target node. Auto-sorted by insertion time. - completion_data: LinkedHashMap, P::Completion>, - /// Best synced block number. - best_synced_number: P::Number, - /// Pruned blocks border. We do not store or accept any blocks with number less than - /// this number. - prune_border: P::Number, -} - -impl Default for QueuedHeaders

{ - fn default() -> Self { - QueuedHeaders { - maybe_orphan: HeadersQueue::new(), - orphan: HeadersQueue::new(), - maybe_extra: HeadersQueue::new(), - extra: HeadersQueue::new(), - ready: HeadersQueue::new(), - incomplete: HeadersQueue::new(), - submitted: HeadersQueue::new(), - synced_children: SyncedChildren::

::new(), - known_headers: KnownHeaders::

::new(), - incomplete_headers: LinkedHashMap::new(), - completion_data: LinkedHashMap::new(), - best_synced_number: Zero::zero(), - prune_border: Zero::zero(), - } - } -} - -impl QueuedHeaders

{ - /// Returns prune border. - #[cfg(test)] - pub fn prune_border(&self) -> P::Number { - self.prune_border - } - - /// Returns number of headers that are currently in given queue. - pub fn headers_in_status(&self, status: HeaderStatus) -> usize { - match status { - HeaderStatus::Unknown | HeaderStatus::Synced => 0, - HeaderStatus::MaybeOrphan => - self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Orphan => - self.orphan.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::MaybeExtra => - self.maybe_extra.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Extra => - self.extra.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Ready => - self.ready.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Incomplete => - self.incomplete.values().fold(0, |total, headers| total + headers.len()), - HeaderStatus::Submitted => - self.submitted.values().fold(0, |total, headers| total + headers.len()), - } - } - - /// Returns number of headers that are currently in the queue. - pub fn total_headers(&self) -> usize { - self.maybe_orphan.values().fold(0, |total, headers| total + headers.len()) + - self.orphan.values().fold(0, |total, headers| total + headers.len()) + - self.maybe_extra.values().fold(0, |total, headers| total + headers.len()) + - self.extra.values().fold(0, |total, headers| total + headers.len()) + - self.ready.values().fold(0, |total, headers| total + headers.len()) + - self.incomplete.values().fold(0, |total, headers| total + headers.len()) - } - - /// Returns number of best block in the queue. - pub fn best_queued_number(&self) -> P::Number { - std::cmp::max( - self.maybe_orphan.keys().next_back().cloned().unwrap_or_else(Zero::zero), - std::cmp::max( - self.orphan.keys().next_back().cloned().unwrap_or_else(Zero::zero), - std::cmp::max( - self.maybe_extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), - std::cmp::max( - self.extra.keys().next_back().cloned().unwrap_or_else(Zero::zero), - std::cmp::max( - self.ready.keys().next_back().cloned().unwrap_or_else(Zero::zero), - std::cmp::max( - self.incomplete - .keys() - .next_back() - .cloned() - .unwrap_or_else(Zero::zero), - self.submitted - .keys() - .next_back() - .cloned() - .unwrap_or_else(Zero::zero), - ), - ), - ), - ), - ), - ) - } - - /// Returns number of best synced block we have ever seen. It is either less - /// than `best_queued_number()`, or points to last synced block if queue is empty. - pub fn best_synced_number(&self) -> P::Number { - self.best_synced_number - } - - /// Returns synchronization status of the header. - pub fn status(&self, id: &HeaderIdOf

) -> HeaderStatus { - self.known_headers - .get(&id.0) - .and_then(|x| x.get(&id.1)) - .cloned() - .unwrap_or(HeaderStatus::Unknown) - } - - /// Get the oldest header from given queue. - pub fn header(&self, status: HeaderStatus) -> Option<&QueuedHeader

> { - match status { - HeaderStatus::Unknown | HeaderStatus::Synced => None, - HeaderStatus::MaybeOrphan => oldest_header(&self.maybe_orphan), - HeaderStatus::Orphan => oldest_header(&self.orphan), - HeaderStatus::MaybeExtra => oldest_header(&self.maybe_extra), - HeaderStatus::Extra => oldest_header(&self.extra), - HeaderStatus::Ready => oldest_header(&self.ready), - HeaderStatus::Incomplete => oldest_header(&self.incomplete), - HeaderStatus::Submitted => oldest_header(&self.submitted), - } - } - - /// Get the oldest headers from given queue until functor will return false. - pub fn headers( - &self, - status: HeaderStatus, - f: impl FnMut(&QueuedHeader

) -> bool, - ) -> Option>> { - match status { - HeaderStatus::Unknown | HeaderStatus::Synced => None, - HeaderStatus::MaybeOrphan => oldest_headers(&self.maybe_orphan, f), - HeaderStatus::Orphan => oldest_headers(&self.orphan, f), - HeaderStatus::MaybeExtra => oldest_headers(&self.maybe_extra, f), - HeaderStatus::Extra => oldest_headers(&self.extra, f), - HeaderStatus::Ready => oldest_headers(&self.ready, f), - HeaderStatus::Incomplete => oldest_headers(&self.incomplete, f), - HeaderStatus::Submitted => oldest_headers(&self.submitted, f), - } - } - - /// Appends new header, received from the source node, to the queue. - pub fn header_response(&mut self, header: P::Header) { - let id = header.id(); - let status = self.status(&id); - if status != HeaderStatus::Unknown { - log::debug!( - target: "bridge", - "Ignoring new {} header: {:?}. Status is {:?}.", - P::SOURCE_NAME, - id, - status, - ); - return - } - - if id.0 < self.prune_border { - log::debug!( - target: "bridge", - "Ignoring ancient new {} header: {:?}.", - P::SOURCE_NAME, - id, - ); - return - } - - let parent_id = header.parent_id(); - let parent_status = self.status(&parent_id); - let header = QueuedHeader::new(header); - - let status = match parent_status { - HeaderStatus::Unknown | HeaderStatus::MaybeOrphan => { - insert_header(&mut self.maybe_orphan, id, header); - HeaderStatus::MaybeOrphan - }, - HeaderStatus::Orphan => { - insert_header(&mut self.orphan, id, header); - HeaderStatus::Orphan - }, - HeaderStatus::MaybeExtra | - HeaderStatus::Extra | - HeaderStatus::Ready | - HeaderStatus::Incomplete | - HeaderStatus::Submitted | - HeaderStatus::Synced => { - insert_header(&mut self.maybe_extra, id, header); - HeaderStatus::MaybeExtra - }, - }; - - self.known_headers.entry(id.0).or_default().insert(id.1, status); - log::debug!( - target: "bridge", - "Queueing new {} header: {:?}. Queue: {:?}.", - P::SOURCE_NAME, - id, - status, - ); - } - - /// Receive the best header from the target node. - pub fn target_best_header_response(&mut self, id: &HeaderIdOf

) { - self.header_synced(id) - } - - /// Receive target node response for MaybeOrphan request. - pub fn maybe_orphan_response(&mut self, id: &HeaderIdOf

, response: bool) { - if !response { - move_header_descendants::

( - &mut [&mut self.maybe_orphan], - &mut self.orphan, - &mut self.known_headers, - HeaderStatus::Orphan, - id, - ); - return - } - - move_header_descendants::

( - &mut [&mut self.maybe_orphan, &mut self.orphan], - &mut self.maybe_extra, - &mut self.known_headers, - HeaderStatus::MaybeExtra, - id, - ); - } - - /// Receive target node response for MaybeExtra request. - pub fn maybe_extra_response(&mut self, id: &HeaderIdOf

, response: bool) { - let (destination_status, destination_queue) = if response { - (HeaderStatus::Extra, &mut self.extra) - } else if self.is_parent_incomplete(id) { - (HeaderStatus::Incomplete, &mut self.incomplete) - } else { - (HeaderStatus::Ready, &mut self.ready) - }; - - move_header( - &mut self.maybe_extra, - destination_queue, - &mut self.known_headers, - destination_status, - id, - |header| header, - ); - } - - /// Receive extra from source node. - pub fn extra_response(&mut self, id: &HeaderIdOf

, extra: P::Extra) { - let (destination_status, destination_queue) = if self.is_parent_incomplete(id) { - (HeaderStatus::Incomplete, &mut self.incomplete) - } else { - (HeaderStatus::Ready, &mut self.ready) - }; - - // move header itself from extra to ready queue - move_header( - &mut self.extra, - destination_queue, - &mut self.known_headers, - destination_status, - id, - |header| header.set_extra(extra), - ); - } - - /// Receive completion response from source node. - pub fn completion_response(&mut self, id: &HeaderIdOf

, completion: Option) { - let completion = match completion { - Some(completion) => completion, - None => { - log::debug!( - target: "bridge", - "{} Node is still missing completion data for header: {:?}. Will retry later.", - P::SOURCE_NAME, - id, - ); - - return - }, - }; - - // do not remove from `incomplete_headers` here, because otherwise we'll miss - // completion 'notification' - // this could lead to duplicate completion retrieval (if completion transaction isn't mined - // for too long) - // - // instead, we're moving entry to the end of the queue, so that completion data won't be - // refetched instantly - if self.incomplete_headers.remove(id).is_some() { - log::debug!( - target: "bridge", - "Received completion data from {} for header: {:?}", - P::SOURCE_NAME, - id, - ); - - self.completion_data.insert(*id, completion); - self.incomplete_headers.insert(*id, Some(Instant::now())); - } - } - - /// When header is submitted to target node. - pub fn headers_submitted(&mut self, ids: Vec>) { - for id in ids { - move_header( - &mut self.ready, - &mut self.submitted, - &mut self.known_headers, - HeaderStatus::Submitted, - &id, - |header| header, - ); - } - } - - /// When header completion data is sent to target node. - pub fn header_completed(&mut self, id: &HeaderIdOf

) { - if self.completion_data.remove(id).is_some() { - log::debug!( - target: "bridge", - "Sent completion data to {} for header: {:?}", - P::TARGET_NAME, - id, - ); - - // transaction can be dropped by target chain nodes => it would never be mined - // - // in current implementation the sync loop would wait for some time && if best - // **source** header won't change on **target** node, then the sync will be restarted - // => we'll resubmit the same completion data again (the same is true for submitted - // headers) - // - // the other option would be to track emitted transactions at least on target node, - // but it won't give us 100% guarantee anyway - // - // => we're just dropping completion data just after it has been submitted - } - } - - /// Marks given headers incomplete. - pub fn add_incomplete_headers( - &mut self, - make_header_incomplete: bool, - new_incomplete_headers: Vec>, - ) { - for new_incomplete_header in new_incomplete_headers { - if make_header_incomplete { - self.header_synced(&new_incomplete_header); - } - - let move_origins = - select_synced_children::

(&self.synced_children, &new_incomplete_header); - let move_origins = - move_origins.into_iter().chain(std::iter::once(new_incomplete_header)); - for move_origin in move_origins { - move_header_descendants::

( - &mut [&mut self.ready, &mut self.submitted], - &mut self.incomplete, - &mut self.known_headers, - HeaderStatus::Incomplete, - &move_origin, - ); - } - - if make_header_incomplete { - log::debug!( - target: "bridge", - "Scheduling completion data retrieval for header: {:?}", - new_incomplete_header, - ); - - self.incomplete_headers.insert(new_incomplete_header, None); - } - } - } - - /// When incomplete headers ids are received from target node. - pub fn incomplete_headers_response(&mut self, ids: HashSet>) { - // all new incomplete headers are marked Synced and all their descendants - // are moved from Ready/Submitted to Incomplete queue - let new_incomplete_headers = ids - .iter() - .filter(|id| { - !self.incomplete_headers.contains_key(id) && !self.completion_data.contains_key(id) - }) - .cloned() - .collect::>(); - self.add_incomplete_headers(true, new_incomplete_headers); - - // for all headers that were incompleted previously, but now are completed, we move - // all descendants from incomplete to ready - let just_completed_headers = self - .incomplete_headers - .keys() - .chain(self.completion_data.keys()) - .filter(|id| !ids.contains(id)) - .cloned() - .collect::>(); - for just_completed_header in just_completed_headers { - // sub2eth rejects H if H.Parent is incomplete - // sub2sub allows 'syncing' headers like that - // => let's check if there are some synced children of just completed header - let move_origins = - select_synced_children::

(&self.synced_children, &just_completed_header); - let move_origins = - move_origins.into_iter().chain(std::iter::once(just_completed_header)); - for move_origin in move_origins { - move_header_descendants::

( - &mut [&mut self.incomplete], - &mut self.ready, - &mut self.known_headers, - HeaderStatus::Ready, - &move_origin, - ); - } - - log::debug!( - target: "bridge", - "Completion data is no longer required for header: {:?}", - just_completed_header, - ); - - self.incomplete_headers.remove(&just_completed_header); - self.completion_data.remove(&just_completed_header); - } - } - - /// Returns true if given header requires completion data. - pub fn requires_completion_data(&self, id: &HeaderIdOf

) -> bool { - self.incomplete_headers.contains_key(id) - } - - /// Returns id of the header for which we want to fetch completion data. - pub fn incomplete_header(&mut self) -> Option> { - queued_incomplete_header(&mut self.incomplete_headers, |last_fetch_time| { - let retry = match *last_fetch_time { - Some(last_fetch_time) => - last_fetch_time.elapsed() > RETRY_FETCH_COMPLETION_INTERVAL, - None => true, - }; - - if retry { - *last_fetch_time = Some(Instant::now()); - } - - retry - }) - .map(|(id, _)| id) - } - - /// Returns header completion data to upload to target node. - pub fn header_to_complete(&mut self) -> Option<(HeaderIdOf

, &P::Completion)> { - queued_incomplete_header(&mut self.completion_data, |_| true) - } - - /// Prune and never accept headers before this block. - pub fn prune(&mut self, prune_border: P::Number) { - if prune_border <= self.prune_border { - return - } - - prune_queue(&mut self.maybe_orphan, prune_border); - prune_queue(&mut self.orphan, prune_border); - prune_queue(&mut self.maybe_extra, prune_border); - prune_queue(&mut self.extra, prune_border); - prune_queue(&mut self.ready, prune_border); - prune_queue(&mut self.submitted, prune_border); - prune_queue(&mut self.incomplete, prune_border); - self.synced_children = self.synced_children.split_off(&prune_border); - prune_known_headers::

(&mut self.known_headers, prune_border); - self.prune_border = prune_border; - } - - /// Forgets all ever known headers. - pub fn clear(&mut self) { - self.maybe_orphan.clear(); - self.orphan.clear(); - self.maybe_extra.clear(); - self.extra.clear(); - self.ready.clear(); - self.incomplete.clear(); - self.submitted.clear(); - self.synced_children.clear(); - self.known_headers.clear(); - self.best_synced_number = Zero::zero(); - self.prune_border = Zero::zero(); - } - - /// Returns true if parent of this header is either incomplete or waiting for - /// its own incomplete ancestor to be completed. - fn is_parent_incomplete(&self, id: &HeaderIdOf

) -> bool { - let status = self.status(id); - let header = match status { - HeaderStatus::MaybeOrphan => header(&self.maybe_orphan, id), - HeaderStatus::Orphan => header(&self.orphan, id), - HeaderStatus::MaybeExtra => header(&self.maybe_extra, id), - HeaderStatus::Extra => header(&self.extra, id), - HeaderStatus::Ready => header(&self.ready, id), - HeaderStatus::Incomplete => header(&self.incomplete, id), - HeaderStatus::Submitted => header(&self.submitted, id), - HeaderStatus::Unknown => return false, - HeaderStatus::Synced => return false, - }; - - match header { - Some(header) => { - let parent_id = header.header().parent_id(); - self.incomplete_headers.contains_key(&parent_id) || - self.completion_data.contains_key(&parent_id) || - self.status(&parent_id) == HeaderStatus::Incomplete - }, - None => false, - } - } - - /// When we receive new Synced header from target node. - fn header_synced(&mut self, id: &HeaderIdOf

) { - // update best synced block number - self.best_synced_number = std::cmp::max(self.best_synced_number, id.0); - - // all ancestors of this header are now synced => let's remove them from - // queues - let mut current = *id; - let mut id_processed = false; - let mut previous_current = None; - loop { - let header = match self.status(¤t) { - HeaderStatus::Unknown => break, - HeaderStatus::MaybeOrphan => remove_header(&mut self.maybe_orphan, ¤t), - HeaderStatus::Orphan => remove_header(&mut self.orphan, ¤t), - HeaderStatus::MaybeExtra => remove_header(&mut self.maybe_extra, ¤t), - HeaderStatus::Extra => remove_header(&mut self.extra, ¤t), - HeaderStatus::Ready => remove_header(&mut self.ready, ¤t), - HeaderStatus::Incomplete => remove_header(&mut self.incomplete, ¤t), - HeaderStatus::Submitted => remove_header(&mut self.submitted, ¤t), - HeaderStatus::Synced => break, - } - .expect("header has a given status; given queue has the header; qed"); - - // remember ids of all the children of the current header - let synced_children_entry = - self.synced_children.entry(current.0).or_default().entry(current.1).or_default(); - let all_queues = [ - &self.maybe_orphan, - &self.orphan, - &self.maybe_extra, - &self.extra, - &self.ready, - &self.incomplete, - &self.submitted, - ]; - for queue in &all_queues { - let children_from_queue = queue - .get(&(current.0 + One::one())) - .map(|potential_children| { - potential_children - .values() - .filter(|potential_child| { - potential_child.header().parent_id() == current - }) - .map(|child| child.id()) - .collect::>() - }) - .unwrap_or_default(); - synced_children_entry.extend(children_from_queue); - } - if let Some(previous_current) = previous_current { - synced_children_entry.insert(previous_current); - } - - set_header_status::

(&mut self.known_headers, ¤t, HeaderStatus::Synced); - - previous_current = Some(current); - current = header.parent_id(); - id_processed = true; - } - - // remember that the header itself is synced - // (condition is here to avoid duplicate log messages) - if !id_processed { - set_header_status::

(&mut self.known_headers, id, HeaderStatus::Synced); - } - - // now let's move all descendants from maybe_orphan && orphan queues to - // maybe_extra queue - move_header_descendants::

( - &mut [&mut self.maybe_orphan, &mut self.orphan], - &mut self.maybe_extra, - &mut self.known_headers, - HeaderStatus::MaybeExtra, - id, - ); - } -} - -/// Insert header to the queue. -fn insert_header( - queue: &mut HeadersQueue

, - id: HeaderIdOf

, - header: QueuedHeader

, -) { - queue.entry(id.0).or_default().insert(id.1, header); -} - -/// Remove header from the queue. -fn remove_header( - queue: &mut HeadersQueue

, - id: &HeaderIdOf

, -) -> Option> { - let mut headers_at = match queue.entry(id.0) { - BTreeMapEntry::Occupied(headers_at) => headers_at, - BTreeMapEntry::Vacant(_) => return None, - }; - - let header = headers_at.get_mut().remove(&id.1); - if headers_at.get().is_empty() { - headers_at.remove(); - } - header -} - -/// Get header from the queue. -fn header<'a, P: HeadersSyncPipeline>( - queue: &'a HeadersQueue

, - id: &HeaderIdOf

, -) -> Option<&'a QueuedHeader

> { - queue.get(&id.0).and_then(|by_hash| by_hash.get(&id.1)) -} - -/// Move header from source to destination queue. -/// -/// Returns ID of parent header, if header has been moved, or None otherwise. -fn move_header( - source_queue: &mut HeadersQueue

, - destination_queue: &mut HeadersQueue

, - known_headers: &mut KnownHeaders

, - destination_status: HeaderStatus, - id: &HeaderIdOf

, - prepare: impl FnOnce(QueuedHeader

) -> QueuedHeader

, -) -> Option> { - let header = match remove_header(source_queue, id) { - Some(header) => prepare(header), - None => return None, - }; - - let parent_id = header.header().parent_id(); - destination_queue.entry(id.0).or_default().insert(id.1, header); - set_header_status::

(known_headers, id, destination_status); - - Some(parent_id) -} - -/// Move all descendant headers from the source to destination queue. -fn move_header_descendants( - source_queues: &mut [&mut HeadersQueue

], - destination_queue: &mut HeadersQueue

, - known_headers: &mut KnownHeaders

, - destination_status: HeaderStatus, - id: &HeaderIdOf

, -) { - let mut current_number = id.0 + One::one(); - let mut current_parents = HashSet::new(); - current_parents.insert(id.1); - - while !current_parents.is_empty() { - let mut next_parents = HashSet::new(); - for source_queue in source_queues.iter_mut() { - let mut source_entry = match source_queue.entry(current_number) { - BTreeMapEntry::Occupied(source_entry) => source_entry, - BTreeMapEntry::Vacant(_) => continue, - }; - - let mut headers_to_move = Vec::new(); - let children_at_number = source_entry.get().keys().cloned().collect::>(); - for key in children_at_number { - let entry = match source_entry.get_mut().entry(key) { - HashMapEntry::Occupied(entry) => entry, - HashMapEntry::Vacant(_) => unreachable!("iterating existing keys; qed"), - }; - - if current_parents.contains(&entry.get().header().parent_id().1) { - let header_to_move = entry.remove(); - let header_to_move_id = header_to_move.id(); - headers_to_move.push((header_to_move_id, header_to_move)); - set_header_status::

(known_headers, &header_to_move_id, destination_status); - } - } - - if source_entry.get().is_empty() { - source_entry.remove(); - } - - next_parents.extend(headers_to_move.iter().map(|(id, _)| id.1)); - - destination_queue - .entry(current_number) - .or_default() - .extend(headers_to_move.into_iter().map(|(id, h)| (id.1, h))) - } - - current_number = current_number + One::one(); - std::mem::swap(&mut current_parents, &mut next_parents); - } -} - -/// Selects (recursive) all synced children of given header. -fn select_synced_children( - synced_children: &SyncedChildren

, - id: &HeaderIdOf

, -) -> Vec> { - let mut result = Vec::new(); - let mut current_parents = HashSet::new(); - current_parents.insert(*id); - - while !current_parents.is_empty() { - let mut next_parents = HashSet::new(); - for current_parent in ¤t_parents { - let current_parent_synced_children = synced_children - .get(¤t_parent.0) - .and_then(|by_number_entry| by_number_entry.get(¤t_parent.1)); - if let Some(current_parent_synced_children) = current_parent_synced_children { - for current_parent_synced_child in current_parent_synced_children { - result.push(*current_parent_synced_child); - next_parents.insert(*current_parent_synced_child); - } - } - } - - let _ = std::mem::replace(&mut current_parents, next_parents); - } - - result -} - -/// Return oldest header from the queue. -fn oldest_header(queue: &HeadersQueue

) -> Option<&QueuedHeader

> { - queue.values().flat_map(|h| h.values()).next() -} - -/// Return oldest headers from the queue until functor will return false. -fn oldest_headers( - queue: &HeadersQueue

, - mut f: impl FnMut(&QueuedHeader

) -> bool, -) -> Option>> { - let result = queue.values().flat_map(|h| h.values()).take_while(|h| f(h)).collect::>(); - if result.is_empty() { - None - } else { - Some(result) - } -} - -/// Forget all headers with number less than given. -fn prune_queue(queue: &mut HeadersQueue

, prune_border: P::Number) { - *queue = queue.split_off(&prune_border); -} - -/// Forget all known headers with number less than given. -fn prune_known_headers( - known_headers: &mut KnownHeaders

, - prune_border: P::Number, -) { - let new_known_headers = known_headers.split_off(&prune_border); - for (pruned_number, pruned_headers) in &*known_headers { - for pruned_hash in pruned_headers.keys() { - log::debug!(target: "bridge", "Pruning header {:?}.", HeaderId(*pruned_number, *pruned_hash)); - } - } - *known_headers = new_known_headers; -} - -/// Change header status. -fn set_header_status( - known_headers: &mut KnownHeaders

, - id: &HeaderIdOf

, - status: HeaderStatus, -) { - log::debug!( - target: "bridge", - "{} header {:?} is now {:?}", - P::SOURCE_NAME, - id, - status, - ); - *known_headers.entry(id.0).or_default().entry(id.1).or_insert(status) = status; -} - -/// Returns queued incomplete header with maximal elapsed time since last update. -fn queued_incomplete_header( - map: &mut LinkedHashMap, - filter: impl FnMut(&mut T) -> bool, -) -> Option<(Id, &T)> { - // TODO (#84): headers that have been just appended to the end of the queue would have to wait - // until all previous headers will be retried - - let retry_old_header = map - .front() - .map(|(key, _)| key.clone()) - .and_then(|key| map.get_mut(&key).map(filter)) - .unwrap_or(false); - if retry_old_header { - let (header_key, header) = - map.pop_front().expect("we have checked that front() exists; qed"); - map.insert(header_key, header); - return map.back().map(|(id, data)| (id.clone(), data)) - } - - None -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::{ - sync_loop_tests::{ - TestHash, TestHeader, TestHeaderId, TestHeadersSyncPipeline, TestNumber, - }, - sync_types::QueuedHeader, - }; - - pub(crate) fn header(number: TestNumber) -> QueuedHeader { - QueuedHeader::new(TestHeader { number, hash: hash(number), parent_hash: hash(number - 1) }) - } - - pub(crate) fn hash(number: TestNumber) -> TestHash { - number - } - - pub(crate) fn id(number: TestNumber) -> TestHeaderId { - HeaderId(number, hash(number)) - } - - #[test] - fn total_headers_works() { - // total headers just sums up number of headers in every queue - let mut queue = QueuedHeaders::::default(); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(1), QueuedHeader::::new(Default::default())); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(2), QueuedHeader::::new(Default::default())); - queue - .maybe_orphan - .entry(2) - .or_default() - .insert(hash(3), QueuedHeader::::new(Default::default())); - queue - .orphan - .entry(3) - .or_default() - .insert(hash(4), QueuedHeader::::new(Default::default())); - queue - .maybe_extra - .entry(4) - .or_default() - .insert(hash(5), QueuedHeader::::new(Default::default())); - queue - .ready - .entry(5) - .or_default() - .insert(hash(6), QueuedHeader::::new(Default::default())); - queue - .incomplete - .entry(6) - .or_default() - .insert(hash(7), QueuedHeader::::new(Default::default())); - assert_eq!(queue.total_headers(), 7); - } - - #[test] - fn best_queued_number_works() { - // initially there are headers in MaybeOrphan queue only - let mut queue = QueuedHeaders::::default(); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(1), QueuedHeader::::new(Default::default())); - queue - .maybe_orphan - .entry(1) - .or_default() - .insert(hash(2), QueuedHeader::::new(Default::default())); - queue - .maybe_orphan - .entry(3) - .or_default() - .insert(hash(3), QueuedHeader::::new(Default::default())); - assert_eq!(queue.best_queued_number(), 3); - // and then there's better header in Orphan - queue - .orphan - .entry(10) - .or_default() - .insert(hash(10), QueuedHeader::::new(Default::default())); - assert_eq!(queue.best_queued_number(), 10); - // and then there's better header in MaybeExtra - queue - .maybe_extra - .entry(20) - .or_default() - .insert(hash(20), QueuedHeader::::new(Default::default())); - assert_eq!(queue.best_queued_number(), 20); - // and then there's better header in Ready - queue - .ready - .entry(30) - .or_default() - .insert(hash(30), QueuedHeader::::new(Default::default())); - assert_eq!(queue.best_queued_number(), 30); - // and then there's better header in MaybeOrphan again - queue - .maybe_orphan - .entry(40) - .or_default() - .insert(hash(40), QueuedHeader::::new(Default::default())); - assert_eq!(queue.best_queued_number(), 40); - // and then there's some header in Incomplete - queue - .incomplete - .entry(50) - .or_default() - .insert(hash(50), QueuedHeader::::new(Default::default())); - assert_eq!(queue.best_queued_number(), 50); - } - - #[test] - fn status_works() { - // all headers are unknown initially - let mut queue = QueuedHeaders::::default(); - assert_eq!(queue.status(&id(10)), HeaderStatus::Unknown); - // and status is read from the KnownHeaders - queue.known_headers.entry(10).or_default().insert(hash(10), HeaderStatus::Ready); - assert_eq!(queue.status(&id(10)), HeaderStatus::Ready); - } - - #[test] - fn header_works() { - // initially we have oldest header #10 - let mut queue = QueuedHeaders::::default(); - queue.maybe_orphan.entry(10).or_default().insert(hash(1), header(100)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(100)); - // inserting #20 changes nothing - queue.maybe_orphan.entry(20).or_default().insert(hash(1), header(101)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(100)); - // inserting #5 makes it oldest - queue.maybe_orphan.entry(5).or_default().insert(hash(1), header(102)); - assert_eq!(queue.header(HeaderStatus::MaybeOrphan).unwrap().header().hash, hash(102)); - } - - #[test] - fn header_response_works() { - // when parent is Synced, we insert to MaybeExtra - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Synced); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - - // when parent is Ready, we insert to MaybeExtra - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Ready); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - - // when parent is Receipts, we insert to MaybeExtra - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Extra); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - - // when parent is MaybeExtra, we insert to MaybeExtra - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeExtra); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeExtra); - - // when parent is Orphan, we insert to Orphan - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Orphan); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::Orphan); - - // when parent is MaybeOrphan, we insert to MaybeOrphan - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeOrphan); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); - - // when parent is unknown, we insert to MaybeOrphan - let mut queue = QueuedHeaders::::default(); - queue.header_response(header(101).header().clone()); - assert_eq!(queue.status(&id(101)), HeaderStatus::MaybeOrphan); - } - - #[test] - fn ancestors_are_synced_on_substrate_best_header_response() { - // let's say someone else has submitted transaction to bridge that changes - // its best block to #100. At this time we have: - // #100 in MaybeOrphan - // #99 in Orphan - // #98 in MaybeExtra - // #97 in Receipts - // #96 in Ready - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue - .known_headers - .entry(99) - .or_default() - .insert(hash(99), HeaderStatus::Orphan); - queue.orphan.entry(99).or_default().insert(hash(99), header(99)); - queue - .known_headers - .entry(98) - .or_default() - .insert(hash(98), HeaderStatus::MaybeExtra); - queue.maybe_extra.entry(98).or_default().insert(hash(98), header(98)); - queue.known_headers.entry(97).or_default().insert(hash(97), HeaderStatus::Extra); - queue.extra.entry(97).or_default().insert(hash(97), header(97)); - queue.known_headers.entry(96).or_default().insert(hash(96), HeaderStatus::Ready); - queue.ready.entry(96).or_default().insert(hash(96), header(96)); - queue.target_best_header_response(&id(100)); - - // then the #100 and all ancestors of #100 (#96..#99) are treated as synced - assert!(queue.maybe_orphan.is_empty()); - assert!(queue.orphan.is_empty()); - assert!(queue.maybe_extra.is_empty()); - assert!(queue.extra.is_empty()); - assert!(queue.ready.is_empty()); - assert_eq!(queue.known_headers.len(), 5); - assert!(queue - .known_headers - .values() - .all(|s| s.values().all(|s| *s == HeaderStatus::Synced))); - - // children of synced headers are stored - assert_eq!( - vec![id(97)], - queue.synced_children[&96][&hash(96)].iter().cloned().collect::>() - ); - assert_eq!( - vec![id(98)], - queue.synced_children[&97][&hash(97)].iter().cloned().collect::>() - ); - assert_eq!( - vec![id(99)], - queue.synced_children[&98][&hash(98)].iter().cloned().collect::>() - ); - assert_eq!( - vec![id(100)], - queue.synced_children[&99][&hash(99)].iter().cloned().collect::>() - ); - assert_eq!(0, queue.synced_children[&100][&hash(100)].len()); - } - - #[test] - fn descendants_are_moved_on_substrate_best_header_response() { - // let's say someone else has submitted transaction to bridge that changes - // its best block to #100. At this time we have: - // #101 in Orphan - // #102 in MaybeOrphan - // #103 in Orphan - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Orphan); - queue.orphan.entry(101).or_default().insert(hash(101), header(101)); - queue - .known_headers - .entry(102) - .or_default() - .insert(hash(102), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); - queue - .known_headers - .entry(103) - .or_default() - .insert(hash(103), HeaderStatus::Orphan); - queue.orphan.entry(103).or_default().insert(hash(103), header(103)); - queue.target_best_header_response(&id(100)); - - // all descendants are moved to MaybeExtra - assert!(queue.maybe_orphan.is_empty()); - assert!(queue.orphan.is_empty()); - assert_eq!(queue.maybe_extra.len(), 3); - assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeExtra); - assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeExtra); - assert_eq!(queue.known_headers[&103][&hash(103)], HeaderStatus::MaybeExtra); - } - - #[test] - fn positive_maybe_orphan_response_works() { - // let's say we have: - // #100 in MaybeOrphan - // #101 in Orphan - // #102 in MaybeOrphan - // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) - // and the response is: YES, #99 is known to the Substrate runtime - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Orphan); - queue.orphan.entry(101).or_default().insert(hash(101), header(101)); - queue - .known_headers - .entry(102) - .or_default() - .insert(hash(102), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(102).or_default().insert(hash(102), header(102)); - queue.maybe_orphan_response(&id(99), true); - - // then all headers (#100..#103) are moved to the MaybeExtra queue - assert!(queue.orphan.is_empty()); - assert!(queue.maybe_orphan.is_empty()); - assert_eq!(queue.maybe_extra.len(), 3); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::MaybeExtra); - assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::MaybeExtra); - assert_eq!(queue.known_headers[&102][&hash(102)], HeaderStatus::MaybeExtra); - } - - #[test] - fn negative_maybe_orphan_response_works() { - // let's say we have: - // #100 in MaybeOrphan - // #101 in MaybeOrphan - // and we have asked for MaybeOrphan status of #100.parent (i.e. #99) - // and the response is: NO, #99 is NOT known to the Substrate runtime - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(100).or_default().insert(hash(100), header(100)); - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(101).or_default().insert(hash(101), header(101)); - queue.maybe_orphan_response(&id(99), false); - - // then all headers (#100..#101) are moved to the Orphan queue - assert!(queue.maybe_orphan.is_empty()); - assert_eq!(queue.orphan.len(), 2); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Orphan); - assert_eq!(queue.known_headers[&101][&hash(101)], HeaderStatus::Orphan); - } - - #[test] - fn positive_maybe_extra_response_works() { - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeExtra); - queue.maybe_extra.entry(100).or_default().insert(hash(100), header(100)); - queue.maybe_extra_response(&id(100), true); - assert!(queue.maybe_extra.is_empty()); - assert_eq!(queue.extra.len(), 1); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Extra); - } - - #[test] - fn negative_maybe_extra_response_works() { - // when parent header is complete - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::MaybeExtra); - queue.maybe_extra.entry(100).or_default().insert(hash(100), header(100)); - queue.maybe_extra_response(&id(100), false); - assert!(queue.maybe_extra.is_empty()); - assert_eq!(queue.ready.len(), 1); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); - - // when parent header is incomplete - queue.incomplete_headers.insert(id(200), None); - queue - .known_headers - .entry(201) - .or_default() - .insert(hash(201), HeaderStatus::MaybeExtra); - queue.maybe_extra.entry(201).or_default().insert(hash(201), header(201)); - queue.maybe_extra_response(&id(201), false); - assert!(queue.maybe_extra.is_empty()); - assert_eq!(queue.incomplete.len(), 1); - assert_eq!(queue.known_headers[&201][&hash(201)], HeaderStatus::Incomplete); - } - - #[test] - fn receipts_response_works() { - // when parent header is complete - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Extra); - queue.extra.entry(100).or_default().insert(hash(100), header(100)); - queue.extra_response(&id(100), 100_100); - assert!(queue.extra.is_empty()); - assert_eq!(queue.ready.len(), 1); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Ready); - - // when parent header is incomplete - queue.incomplete_headers.insert(id(200), None); - queue - .known_headers - .entry(201) - .or_default() - .insert(hash(201), HeaderStatus::Extra); - queue.extra.entry(201).or_default().insert(hash(201), header(201)); - queue.extra_response(&id(201), 201_201); - assert!(queue.extra.is_empty()); - assert_eq!(queue.incomplete.len(), 1); - assert_eq!(queue.known_headers[&201][&hash(201)], HeaderStatus::Incomplete); - } - - #[test] - fn header_submitted_works() { - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Ready); - queue.ready.entry(100).or_default().insert(hash(100), header(100)); - queue.headers_submitted(vec![id(100)]); - assert!(queue.ready.is_empty()); - assert_eq!(queue.known_headers[&100][&hash(100)], HeaderStatus::Submitted); - } - - #[test] - fn incomplete_header_works() { - let mut queue = QueuedHeaders::::default(); - - // nothing to complete if queue is empty - assert_eq!(queue.incomplete_header(), None); - - // when there's new header to complete => ask for completion data - queue.incomplete_headers.insert(id(100), None); - assert_eq!(queue.incomplete_header(), Some(id(100))); - - // we have just asked for completion data => nothing to request - assert_eq!(queue.incomplete_header(), None); - - // enough time have passed => ask again - queue.incomplete_headers.clear(); - queue.incomplete_headers.insert( - id(100), - Some( - Instant::now() - RETRY_FETCH_COMPLETION_INTERVAL - RETRY_FETCH_COMPLETION_INTERVAL, - ), - ); - assert_eq!(queue.incomplete_header(), Some(id(100))); - } - - #[test] - fn completion_response_works() { - let mut queue = QueuedHeaders::::default(); - queue.incomplete_headers.insert(id(100), None); - queue.incomplete_headers.insert(id(200), Some(Instant::now())); - queue.incomplete_headers.insert(id(300), Some(Instant::now())); - - // when header isn't incompete, nothing changes - queue.completion_response(&id(400), None); - assert_eq!(queue.incomplete_headers.len(), 3); - assert_eq!(queue.completion_data.len(), 0); - assert_eq!(queue.header_to_complete(), None); - - // when response is None, nothing changes - queue.completion_response(&id(100), None); - assert_eq!(queue.incomplete_headers.len(), 3); - assert_eq!(queue.completion_data.len(), 0); - assert_eq!(queue.header_to_complete(), None); - - // when response is Some, we're scheduling completion - queue.completion_response(&id(200), Some(200_200)); - assert_eq!(queue.completion_data.len(), 1); - assert!(queue.completion_data.contains_key(&id(200))); - assert_eq!(queue.header_to_complete(), Some((id(200), &200_200))); - assert_eq!( - queue.incomplete_headers.keys().collect::>(), - vec![&id(100), &id(300), &id(200)], - ); - } - - #[test] - fn header_completed_works() { - let mut queue = QueuedHeaders::::default(); - queue.completion_data.insert(id(100), 100_100); - - // when unknown header is completed - queue.header_completed(&id(200)); - assert_eq!(queue.completion_data.len(), 1); - - // when known header is completed - queue.header_completed(&id(100)); - assert_eq!(queue.completion_data.len(), 0); - } - - #[test] - fn incomplete_headers_response_works() { - let mut queue = QueuedHeaders::::default(); - - // when we have already submitted #101 and #102 is ready - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Submitted); - queue.submitted.entry(101).or_default().insert(hash(101), header(101)); - queue - .known_headers - .entry(102) - .or_default() - .insert(hash(102), HeaderStatus::Ready); - queue.submitted.entry(102).or_default().insert(hash(102), header(102)); - - // AND now we know that the #100 is incomplete - queue.incomplete_headers_response(vec![id(100)].into_iter().collect()); - - // => #101 and #102 are moved to the Incomplete and #100 is now synced - assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(101)), HeaderStatus::Incomplete); - assert_eq!(queue.status(&id(102)), HeaderStatus::Incomplete); - assert_eq!(queue.submitted.len(), 0); - assert_eq!(queue.ready.len(), 0); - assert!(queue.incomplete.entry(101).or_default().contains_key(&hash(101))); - assert!(queue.incomplete.entry(102).or_default().contains_key(&hash(102))); - assert!(queue.incomplete_headers.contains_key(&id(100))); - assert!(queue.completion_data.is_empty()); - - // and then header #100 is no longer incomplete - queue.incomplete_headers_response(vec![].into_iter().collect()); - - // => #101 and #102 are moved to the Ready queue and #100 if now forgotten - assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(101)), HeaderStatus::Ready); - assert_eq!(queue.status(&id(102)), HeaderStatus::Ready); - assert_eq!(queue.incomplete.len(), 0); - assert_eq!(queue.submitted.len(), 0); - assert!(queue.ready.entry(101).or_default().contains_key(&hash(101))); - assert!(queue.ready.entry(102).or_default().contains_key(&hash(102))); - assert!(queue.incomplete_headers.is_empty()); - assert!(queue.completion_data.is_empty()); - } - - #[test] - fn is_parent_incomplete_works() { - let mut queue = QueuedHeaders::::default(); - - // when we do not know header itself - assert!(!queue.is_parent_incomplete(&id(50))); - - // when we do not know parent - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Incomplete); - queue.incomplete.entry(100).or_default().insert(hash(100), header(100)); - assert!(!queue.is_parent_incomplete(&id(100))); - - // when parent is inside incomplete queue (i.e. some other ancestor is actually incomplete) - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Submitted); - queue.submitted.entry(101).or_default().insert(hash(101), header(101)); - assert!(queue.is_parent_incomplete(&id(101))); - - // when parent is the incomplete header and we do not have completion data - queue.incomplete_headers.insert(id(199), None); - queue - .known_headers - .entry(200) - .or_default() - .insert(hash(200), HeaderStatus::Submitted); - queue.submitted.entry(200).or_default().insert(hash(200), header(200)); - assert!(queue.is_parent_incomplete(&id(200))); - - // when parent is the incomplete header and we have completion data - queue.completion_data.insert(id(299), 299_299); - queue - .known_headers - .entry(300) - .or_default() - .insert(hash(300), HeaderStatus::Submitted); - queue.submitted.entry(300).or_default().insert(hash(300), header(300)); - assert!(queue.is_parent_incomplete(&id(300))); - } - - #[test] - fn prune_works() { - let mut queue = QueuedHeaders::::default(); - queue - .known_headers - .entry(105) - .or_default() - .insert(hash(105), HeaderStatus::Incomplete); - queue.incomplete.entry(105).or_default().insert(hash(105), header(105)); - queue - .known_headers - .entry(104) - .or_default() - .insert(hash(104), HeaderStatus::MaybeOrphan); - queue.maybe_orphan.entry(104).or_default().insert(hash(104), header(104)); - queue - .known_headers - .entry(103) - .or_default() - .insert(hash(103), HeaderStatus::Orphan); - queue.orphan.entry(103).or_default().insert(hash(103), header(103)); - queue - .known_headers - .entry(102) - .or_default() - .insert(hash(102), HeaderStatus::MaybeExtra); - queue.maybe_extra.entry(102).or_default().insert(hash(102), header(102)); - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Extra); - queue.extra.entry(101).or_default().insert(hash(101), header(101)); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Ready); - queue.ready.entry(100).or_default().insert(hash(100), header(100)); - queue - .synced_children - .entry(100) - .or_default() - .insert(hash(100), vec![id(101)].into_iter().collect()); - queue - .synced_children - .entry(102) - .or_default() - .insert(hash(102), vec![id(102)].into_iter().collect()); - - queue.prune(102); - - assert_eq!(queue.ready.len(), 0); - assert_eq!(queue.extra.len(), 0); - assert_eq!(queue.maybe_extra.len(), 1); - assert_eq!(queue.orphan.len(), 1); - assert_eq!(queue.maybe_orphan.len(), 1); - assert_eq!(queue.incomplete.len(), 1); - assert_eq!(queue.synced_children.len(), 1); - assert_eq!(queue.known_headers.len(), 4); - - queue.prune(110); - - assert_eq!(queue.ready.len(), 0); - assert_eq!(queue.extra.len(), 0); - assert_eq!(queue.maybe_extra.len(), 0); - assert_eq!(queue.orphan.len(), 0); - assert_eq!(queue.maybe_orphan.len(), 0); - assert_eq!(queue.incomplete.len(), 0); - assert_eq!(queue.synced_children.len(), 0); - assert_eq!(queue.known_headers.len(), 0); - - queue.header_response(header(109).header().clone()); - assert_eq!(queue.known_headers.len(), 0); - - queue.header_response(header(110).header().clone()); - assert_eq!(queue.known_headers.len(), 1); - } - - #[test] - fn incomplete_headers_are_still_incomplete_after_advance() { - let mut queue = QueuedHeaders::::default(); - - // relay#1 knows that header#100 is incomplete && it has headers 101..104 in incomplete - // queue - queue.incomplete_headers.insert(id(100), None); - queue.incomplete.entry(101).or_default().insert(hash(101), header(101)); - queue.incomplete.entry(102).or_default().insert(hash(102), header(102)); - queue.incomplete.entry(103).or_default().insert(hash(103), header(103)); - queue.incomplete.entry(104).or_default().insert(hash(104), header(104)); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Synced); - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Incomplete); - queue - .known_headers - .entry(102) - .or_default() - .insert(hash(102), HeaderStatus::Incomplete); - queue - .known_headers - .entry(103) - .or_default() - .insert(hash(103), HeaderStatus::Incomplete); - queue - .known_headers - .entry(104) - .or_default() - .insert(hash(104), HeaderStatus::Incomplete); - - // let's say relay#2 completes header#100 and then submits header#101+header#102 and it - // turns out that header#102 is also incomplete - queue.incomplete_headers_response(vec![id(102)].into_iter().collect()); - - // then the header#103 and the header#104 must have Incomplete status - assert_eq!(queue.status(&id(101)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(102)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(103)), HeaderStatus::Incomplete); - assert_eq!(queue.status(&id(104)), HeaderStatus::Incomplete); - } - - #[test] - fn incomplete_headers_response_moves_synced_headers() { - let mut queue = QueuedHeaders::::default(); - - // we have submitted two headers - 100 and 101. 102 is ready - queue.submitted.entry(100).or_default().insert(hash(100), header(100)); - queue.submitted.entry(101).or_default().insert(hash(101), header(101)); - queue.ready.entry(102).or_default().insert(hash(102), header(102)); - queue - .known_headers - .entry(100) - .or_default() - .insert(hash(100), HeaderStatus::Submitted); - queue - .known_headers - .entry(101) - .or_default() - .insert(hash(101), HeaderStatus::Submitted); - queue - .known_headers - .entry(102) - .or_default() - .insert(hash(102), HeaderStatus::Ready); - - // both headers are accepted - queue.target_best_header_response(&id(101)); - - // but header 100 is incomplete - queue.incomplete_headers_response(vec![id(100)].into_iter().collect()); - assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(101)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(102)), HeaderStatus::Incomplete); - assert!(queue.incomplete_headers.contains_key(&id(100))); - assert!(queue.incomplete[&102].contains_key(&hash(102))); - - // when header 100 is completed, 101 is synced and 102 is ready - queue.incomplete_headers_response(HashSet::new()); - assert_eq!(queue.status(&id(100)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(101)), HeaderStatus::Synced); - assert_eq!(queue.status(&id(102)), HeaderStatus::Ready); - assert!(queue.ready[&102].contains_key(&hash(102))); - } -} diff --git a/relays/headers/src/lib.rs b/relays/headers/src/lib.rs deleted file mode 100644 index 8946355921f0d..0000000000000 --- a/relays/headers/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -// 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 . - -//! Relaying source chain headers to target chain. This module provides entrypoint -//! that starts reading new headers from source chain and submit these headers as -//! module/contract transactions to the target chain. Pallet/contract on the target -//! chain is a light-client of the source chain. All other trustless bridge -//! applications are built using this light-client, so running headers-relay is -//! essential for running all other bridge applications. - -// required for futures::select! -#![recursion_limit = "1024"] -#![warn(missing_docs)] - -pub mod headers; -pub mod sync; -pub mod sync_loop; -pub mod sync_loop_metrics; -pub mod sync_loop_tests; -pub mod sync_types; diff --git a/relays/headers/src/sync.rs b/relays/headers/src/sync.rs deleted file mode 100644 index 012b63f0dc59c..0000000000000 --- a/relays/headers/src/sync.rs +++ /dev/null @@ -1,529 +0,0 @@ -// 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 . - -//! Headers synchronization context. This structure wraps headers queue and is -//! able to choose: which headers to read from the source chain? Which headers -//! to submit to the target chain? The context makes decisions basing on parameters -//! passed using `HeadersSyncParams` structure. - -use crate::{ - headers::QueuedHeaders, - sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader}, -}; -use num_traits::{One, Saturating, Zero}; - -/// Common sync params. -#[derive(Debug, Clone)] -pub struct HeadersSyncParams { - /// Maximal number of ethereum headers to pre-download. - pub max_future_headers_to_download: usize, - /// Maximal number of active (we believe) submit header transactions. - pub max_headers_in_submitted_status: usize, - /// Maximal number of headers in single submit request. - pub max_headers_in_single_submit: usize, - /// Maximal total headers size in single submit request. - pub max_headers_size_in_single_submit: usize, - /// We only may store and accept (from Ethereum node) headers that have - /// number >= than "best_substrate_header.number" - "prune_depth". - pub prune_depth: u32, - /// Target transactions mode. - pub target_tx_mode: TargetTransactionMode, -} - -/// Target transaction mode. -#[derive(Debug, PartialEq, Clone)] -pub enum TargetTransactionMode { - /// Submit new headers using signed transactions. - Signed, - /// Submit new headers using unsigned transactions. - Unsigned, - /// Submit new headers using signed transactions, but only when we - /// believe that sync has stalled. - Backup, -} - -/// Headers synchronization context. -#[derive(Debug)] -pub struct HeadersSync { - /// Synchronization parameters. - params: HeadersSyncParams, - /// The best header number known to source node. - source_best_number: Option, - /// The best header known to target node. - target_best_header: Option>, - /// Headers queue. - headers: QueuedHeaders

, - /// Pause headers submission. - pause_submit: bool, -} - -impl HeadersSync

{ - /// Creates new headers synchronizer. - pub fn new(params: HeadersSyncParams) -> Self { - HeadersSync { - headers: QueuedHeaders::default(), - params, - source_best_number: None, - target_best_header: None, - pause_submit: false, - } - } - - /// Return best header number known to source node. - pub fn source_best_number(&self) -> Option { - self.source_best_number - } - - /// The best header known to target node. - pub fn target_best_header(&self) -> Option> { - self.target_best_header - } - - /// Returns true if we have synced almost all known headers. - pub fn is_almost_synced(&self) -> bool { - match self.source_best_number { - Some(source_best_number) => self - .target_best_header - .map(|best| source_best_number.saturating_sub(best.0) < 4.into()) - .unwrap_or(false), - None => true, - } - } - - /// Returns synchronization status. - pub fn status(&self) -> (&Option>, &Option) { - (&self.target_best_header, &self.source_best_number) - } - - /// Returns reference to the headers queue. - pub fn headers(&self) -> &QueuedHeaders

{ - &self.headers - } - - /// Returns mutable reference to the headers queue. - pub fn headers_mut(&mut self) -> &mut QueuedHeaders

{ - &mut self.headers - } - - /// Select header that needs to be downloaded from the source node. - pub fn select_new_header_to_download(&self) -> Option { - // if we haven't received best header from source node yet, there's nothing we can download - let source_best_number = self.source_best_number?; - - // if we haven't received known best header from target node yet, there's nothing we can - // download - let target_best_header = self.target_best_header.as_ref()?; - - // if there's too many headers in the queue, stop downloading - let in_memory_headers = self.headers.total_headers(); - if in_memory_headers >= self.params.max_future_headers_to_download { - return None - } - - // if queue is empty and best header on target is > than best header on source, - // then we shoud reorganization - let best_queued_number = self.headers.best_queued_number(); - if best_queued_number.is_zero() && source_best_number < target_best_header.0 { - return Some(source_best_number) - } - - // we assume that there were no reorganizations if we have already downloaded best header - let best_downloaded_number = std::cmp::max( - std::cmp::max(best_queued_number, self.headers.best_synced_number()), - target_best_header.0, - ); - if best_downloaded_number >= source_best_number { - return None - } - - // download new header - Some(best_downloaded_number + One::one()) - } - - /// Select orphan header to download. - pub fn select_orphan_header_to_download(&self) -> Option<&QueuedHeader

> { - let orphan_header = self.headers.header(HeaderStatus::Orphan)?; - - // we consider header orphan until we'll find it ancestor that is known to the target node - // => we may get orphan header while we ask target node whether it knows its parent - // => let's avoid fetching duplicate headers - let parent_id = orphan_header.parent_id(); - if self.headers.status(&parent_id) != HeaderStatus::Unknown { - return None - } - - Some(orphan_header) - } - - /// Select headers that need to be submitted to the target node. - pub fn select_headers_to_submit(&self, stalled: bool) -> Option>> { - // maybe we have paused new headers submit? - if self.pause_submit { - return None - } - - // if we operate in backup mode, we only submit headers when sync has stalled - if self.params.target_tx_mode == TargetTransactionMode::Backup && !stalled { - return None - } - - let headers_in_submit_status = self.headers.headers_in_status(HeaderStatus::Submitted); - let headers_to_submit_count = self - .params - .max_headers_in_submitted_status - .checked_sub(headers_in_submit_status)?; - - let mut total_size = 0; - let mut total_headers = 0; - self.headers.headers(HeaderStatus::Ready, |header| { - if total_headers == headers_to_submit_count { - return false - } - if total_headers == self.params.max_headers_in_single_submit { - return false - } - - let encoded_size = P::estimate_size(header); - if total_headers != 0 && - total_size + encoded_size > self.params.max_headers_size_in_single_submit - { - return false - } - - total_size += encoded_size; - total_headers += 1; - - true - }) - } - - /// Receive new target header number from the source node. - pub fn source_best_header_number_response(&mut self, best_header_number: P::Number) { - log::debug!( - target: "bridge", - "Received best header number from {} node: {}", - P::SOURCE_NAME, - best_header_number, - ); - self.source_best_number = Some(best_header_number); - } - - /// Receive new best header from the target node. - /// Returns true if it is different from the previous block known to us. - pub fn target_best_header_response(&mut self, best_header: HeaderIdOf

) -> bool { - log::debug!( - target: "bridge", - "Received best known header from {}: {:?}", - P::TARGET_NAME, - best_header, - ); - - // early return if it is still the same - if self.target_best_header == Some(best_header) { - return false - } - - // remember that this header is now known to the Substrate runtime - self.headers.target_best_header_response(&best_header); - - // prune ancient headers - self.headers.prune(best_header.0.saturating_sub(self.params.prune_depth.into())); - - // finally remember the best header itself - self.target_best_header = Some(best_header); - - // we are ready to submit headers again - if self.pause_submit { - log::debug!( - target: "bridge", - "Ready to submit {} headers to {} node again!", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - - self.pause_submit = false; - } - - true - } - - /// Pause headers submit until best header will be updated on target node. - pub fn pause_submit(&mut self) { - log::debug!( - target: "bridge", - "Stopping submitting {} headers to {} node. Waiting for {} submitted headers to be accepted", - P::SOURCE_NAME, - P::TARGET_NAME, - self.headers.headers_in_status(HeaderStatus::Submitted), - ); - - self.pause_submit = true; - } - - /// Restart synchronization. - pub fn restart(&mut self) { - self.source_best_number = None; - self.target_best_header = None; - self.headers.clear(); - self.pause_submit = false; - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - use crate::{ - headers::tests::{header, id}, - sync_loop_tests::{TestHash, TestHeadersSyncPipeline, TestNumber}, - sync_types::HeaderStatus, - }; - use relay_utils::HeaderId; - - fn side_hash(number: TestNumber) -> TestHash { - 1000 + number - } - - pub fn default_sync_params() -> HeadersSyncParams { - HeadersSyncParams { - max_future_headers_to_download: 128, - max_headers_in_submitted_status: 128, - max_headers_in_single_submit: 32, - max_headers_size_in_single_submit: 131_072, - prune_depth: 4096, - target_tx_mode: TargetTransactionMode::Signed, - } - } - - #[test] - fn select_new_header_to_download_works() { - let mut eth_sync = HeadersSync::::new(default_sync_params()); - - // both best && target headers are unknown - assert_eq!(eth_sync.select_new_header_to_download(), None); - - // best header is known, target header is unknown - eth_sync.target_best_header = Some(HeaderId(0, Default::default())); - assert_eq!(eth_sync.select_new_header_to_download(), None); - - // target header is known, best header is unknown - eth_sync.target_best_header = None; - eth_sync.source_best_number = Some(100); - assert_eq!(eth_sync.select_new_header_to_download(), None); - - // when our best block has the same number as the target - eth_sync.target_best_header = Some(HeaderId(100, Default::default())); - assert_eq!(eth_sync.select_new_header_to_download(), None); - - // when we actually need a new header - eth_sync.source_best_number = Some(101); - assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); - - // when we have to reorganize to longer fork - eth_sync.source_best_number = Some(100); - eth_sync.target_best_header = Some(HeaderId(200, Default::default())); - assert_eq!(eth_sync.select_new_header_to_download(), Some(100)); - - // when there are too many headers scheduled for submitting - for i in 1..1000 { - eth_sync.headers.header_response(header(i).header().clone()); - } - assert_eq!(eth_sync.select_new_header_to_download(), None); - } - - #[test] - fn select_new_header_to_download_works_with_empty_queue() { - let mut eth_sync = HeadersSync::::new(default_sync_params()); - eth_sync.source_best_header_number_response(100); - - // when queue is not empty => everything goes as usually - eth_sync.target_best_header_response(header(10).id()); - eth_sync.headers_mut().header_response(header(11).header().clone()); - eth_sync.headers_mut().maybe_extra_response(&header(11).id(), false); - assert_eq!(eth_sync.select_new_header_to_download(), Some(12)); - - // but then queue is drained - eth_sync.headers_mut().target_best_header_response(&header(11).id()); - - // even though it's empty, we know that header#11 is synced - assert_eq!(eth_sync.headers().best_queued_number(), 0); - assert_eq!(eth_sync.headers().best_synced_number(), 11); - assert_eq!(eth_sync.select_new_header_to_download(), Some(12)); - } - - #[test] - fn sync_without_reorgs_works() { - let mut eth_sync = HeadersSync::new(default_sync_params()); - eth_sync.params.max_headers_in_submitted_status = 1; - - // ethereum reports best header #102 - eth_sync.source_best_header_number_response(102); - - // substrate reports that it is at block #100 - eth_sync.target_best_header_response(id(100)); - - // block #101 is downloaded first - assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); - eth_sync.headers.header_response(header(101).header().clone()); - - // now header #101 is ready to be submitted - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(101))); - eth_sync.headers.maybe_extra_response(&id(101), false); - assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(101))); - assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); - - // and header #102 is ready to be downloaded - assert_eq!(eth_sync.select_new_header_to_download(), Some(102)); - eth_sync.headers.header_response(header(102).header().clone()); - - // receive submission confirmation - eth_sync.headers.headers_submitted(vec![id(101)]); - - // we have nothing to submit because previous header hasn't been confirmed yet - // (and we allow max 1 submit transaction in the wild) - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(102))); - eth_sync.headers.maybe_extra_response(&id(102), false); - assert_eq!(eth_sync.headers.header(HeaderStatus::Ready), Some(&header(102))); - assert_eq!(eth_sync.select_headers_to_submit(false), None); - - // substrate reports that it has imported block #101 - eth_sync.target_best_header_response(id(101)); - - // and we are ready to submit #102 - assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(102)])); - eth_sync.headers.headers_submitted(vec![id(102)]); - - // substrate reports that it has imported block #102 - eth_sync.target_best_header_response(id(102)); - - // and we have nothing to download - assert_eq!(eth_sync.select_new_header_to_download(), None); - } - - #[test] - fn sync_with_orphan_headers_work() { - let mut eth_sync = HeadersSync::new(default_sync_params()); - - // ethereum reports best header #102 - eth_sync.source_best_header_number_response(102); - - // substrate reports that it is at block #100, but it isn't part of best chain - eth_sync.target_best_header_response(HeaderId(100, side_hash(100))); - - // block #101 is downloaded first - assert_eq!(eth_sync.select_new_header_to_download(), Some(101)); - eth_sync.headers.header_response(header(101).header().clone()); - - // we can't submit header #101, because its parent status is unknown - assert_eq!(eth_sync.select_headers_to_submit(false), None); - - // instead we are trying to determine status of its parent (#100) - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeOrphan), Some(&header(101))); - - // and the status is still unknown - eth_sync.headers.maybe_orphan_response(&id(100), false); - - // so we consider #101 orphaned now && will download its parent - #100 - assert_eq!(eth_sync.headers.header(HeaderStatus::Orphan), Some(&header(101))); - eth_sync.headers.header_response(header(100).header().clone()); - - // #101 is now Orphan and #100 is MaybeOrphan => we do not want to retrieve - // header #100 again - assert_eq!(eth_sync.headers.header(HeaderStatus::Orphan), Some(&header(101))); - assert_eq!(eth_sync.select_orphan_header_to_download(), None); - - // we can't submit header #100, because its parent status is unknown - assert_eq!(eth_sync.select_headers_to_submit(false), None); - - // instead we are trying to determine status of its parent (#99) - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeOrphan), Some(&header(100))); - - // and the status is known, so we move previously orphaned #100 and #101 to ready queue - eth_sync.headers.maybe_orphan_response(&id(99), true); - - // and we are ready to submit #100 - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(100))); - eth_sync.headers.maybe_extra_response(&id(100), false); - assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(100)])); - eth_sync.headers.headers_submitted(vec![id(100)]); - - // and we are ready to submit #101 - assert_eq!(eth_sync.headers.header(HeaderStatus::MaybeExtra), Some(&header(101))); - eth_sync.headers.maybe_extra_response(&id(101), false); - assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); - eth_sync.headers.headers_submitted(vec![id(101)]); - } - - #[test] - fn pruning_happens_on_target_best_header_response() { - let mut eth_sync = HeadersSync::::new(default_sync_params()); - eth_sync.params.prune_depth = 50; - eth_sync.target_best_header_response(id(100)); - assert_eq!(eth_sync.headers.prune_border(), 50); - } - - #[test] - fn only_submitting_headers_in_backup_mode_when_stalled() { - let mut eth_sync = HeadersSync::new(default_sync_params()); - eth_sync.params.target_tx_mode = TargetTransactionMode::Backup; - - // ethereum reports best header #102 - eth_sync.source_best_header_number_response(102); - - // substrate reports that it is at block #100 - eth_sync.target_best_header_response(id(100)); - - // block #101 is downloaded first - eth_sync.headers.header_response(header(101).header().clone()); - eth_sync.headers.maybe_extra_response(&id(101), false); - - // ensure that headers are not submitted when sync is not stalled - assert_eq!(eth_sync.select_headers_to_submit(false), None); - - // ensure that headers are not submitted when sync is stalled - assert_eq!(eth_sync.select_headers_to_submit(true), Some(vec![&header(101)])); - } - - #[test] - fn does_not_select_new_headers_to_submit_when_submit_is_paused() { - let mut eth_sync = HeadersSync::new(default_sync_params()); - eth_sync.params.max_headers_in_submitted_status = 1; - - // ethereum reports best header #102 and substrate is at #100 - eth_sync.source_best_header_number_response(102); - eth_sync.target_best_header_response(id(100)); - - // let's prepare #101 and #102 for submitting - eth_sync.headers.header_response(header(101).header().clone()); - eth_sync.headers.maybe_extra_response(&id(101), false); - eth_sync.headers.header_response(header(102).header().clone()); - eth_sync.headers.maybe_extra_response(&id(102), false); - - // when submit is not paused, we're ready to submit #101 - assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(101)])); - - // when submit is paused, we're not ready to submit anything - eth_sync.pause_submit(); - assert_eq!(eth_sync.select_headers_to_submit(false), None); - - // if best header on substrate node isn't updated, we still not submitting anything - eth_sync.target_best_header_response(id(100)); - assert_eq!(eth_sync.select_headers_to_submit(false), None); - - // but after it is actually updated, we are ready to submit - eth_sync.target_best_header_response(id(101)); - assert_eq!(eth_sync.select_headers_to_submit(false), Some(vec![&header(102)])); - } -} diff --git a/relays/headers/src/sync_loop.rs b/relays/headers/src/sync_loop.rs deleted file mode 100644 index da8d23dc39dec..0000000000000 --- a/relays/headers/src/sync_loop.rs +++ /dev/null @@ -1,654 +0,0 @@ -// 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 . - -//! Entrypoint for running headers synchronization loop. - -use crate::{ - sync::{HeadersSync, HeadersSyncParams}, - sync_loop_metrics::SyncLoopMetrics, - sync_types::{HeaderIdOf, HeaderStatus, HeadersSyncPipeline, QueuedHeader, SubmittedHeaders}, -}; - -use async_trait::async_trait; -use futures::{future::FutureExt, stream::StreamExt}; -use num_traits::{Saturating, Zero}; -use relay_utils::{ - format_ids, interval, - metrics::{GlobalMetrics, MetricsParams}, - process_future_result, - relay_loop::Client as RelayClient, - retry_backoff, FailedClient, MaybeConnectionError, StringifiedMaybeConnectionError, -}; -use std::{ - collections::HashSet, - future::Future, - time::{Duration, Instant}, -}; - -/// When we submit headers to target node, but see no updates of best -/// source block known to target node during STALL_SYNC_TIMEOUT seconds, -/// we consider that our headers are rejected because there has been reorganization in target chain. -/// This reorganization could invalidate our knowledge about sync process (i.e. we have asked if -/// HeaderA is known to target, but then reorganization happened and the answer is different -/// now) => we need to reset sync. -/// The other option is to receive **EVERY** best target header and check if it is -/// direct child of previous best header. But: (1) subscription doesn't guarantee that -/// the subscriber will receive every best header (2) reorganization won't always lead to sync -/// stall and restart is a heavy operation (we forget all in-memory headers). -const STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(5 * 60); -/// Delay after we have seen update of best source header at target node, -/// for us to treat sync stalled. ONLY when relay operates in backup mode. -const BACKUP_STALL_SYNC_TIMEOUT: Duration = Duration::from_secs(10 * 60); -/// Interval between calling sync maintain procedure. -const MAINTAIN_INTERVAL: Duration = Duration::from_secs(30); - -/// Source client trait. -#[async_trait] -pub trait SourceClient: RelayClient { - /// Get best block number. - async fn best_block_number(&self) -> Result; - - /// Get header by hash. - async fn header_by_hash(&self, hash: P::Hash) -> Result; - - /// Get canonical header by number. - async fn header_by_number(&self, number: P::Number) -> Result; - - /// Get completion data by header hash. - async fn header_completion( - &self, - id: HeaderIdOf

, - ) -> Result<(HeaderIdOf

, Option), Self::Error>; - - /// Get extra data by header hash. - async fn header_extra( - &self, - id: HeaderIdOf

, - header: QueuedHeader

, - ) -> Result<(HeaderIdOf

, P::Extra), Self::Error>; -} - -/// Target client trait. -#[async_trait] -pub trait TargetClient: RelayClient { - /// Returns ID of the best header known to the target node. - async fn best_header_id(&self) -> Result, Self::Error>; - - /// Returns true if header is known to the target node. - async fn is_known_header( - &self, - id: HeaderIdOf

, - ) -> Result<(HeaderIdOf

, bool), Self::Error>; - - /// Submit headers. - async fn submit_headers( - &self, - headers: Vec>, - ) -> SubmittedHeaders, Self::Error>; - - /// Returns ID of headers that require to be 'completed' before children can be submitted. - async fn incomplete_headers_ids(&self) -> Result>, Self::Error>; - - /// Submit completion data for header. - async fn complete_header( - &self, - id: HeaderIdOf

, - completion: P::Completion, - ) -> Result, Self::Error>; - - /// Returns true if header requires extra data to be submitted. - async fn requires_extra( - &self, - header: QueuedHeader

, - ) -> Result<(HeaderIdOf

, bool), Self::Error>; -} - -/// Synchronization maintain procedure. -#[async_trait] -pub trait SyncMaintain: 'static + Clone + Send + Sync { - /// Run custom maintain procedures. This is guaranteed to be called when both source and target - /// clients are unoccupied. - async fn maintain(&self, _sync: &mut HeadersSync

) {} -} - -impl SyncMaintain

for () {} - -/// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs -/// sync loop. -pub fn metrics_prefix() -> String { - format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) -} - -/// Run headers synchronization. -#[allow(clippy::too_many_arguments)] -pub async fn run>( - source_client: impl SourceClient

, - source_tick: Duration, - target_client: TC, - target_tick: Duration, - sync_maintain: impl SyncMaintain

, - sync_params: HeadersSyncParams, - metrics_params: MetricsParams, - exit_signal: impl Future + 'static + Send, -) -> Result<(), relay_utils::Error> { - let exit_signal = exit_signal.shared(); - relay_utils::relay_loop(source_client, target_client) - .with_metrics(Some(metrics_prefix::

()), metrics_params) - .loop_metric(SyncLoopMetrics::new)? - .standalone_metric(GlobalMetrics::new)? - .expose() - .await? - .run(metrics_prefix::

(), move |source_client, target_client, metrics| { - run_until_connection_lost( - source_client, - source_tick, - target_client, - target_tick, - sync_maintain.clone(), - sync_params.clone(), - metrics, - exit_signal.clone(), - ) - }) - .await -} - -/// Run headers synchronization. -#[allow(clippy::too_many_arguments)] -async fn run_until_connection_lost>( - source_client: impl SourceClient

, - source_tick: Duration, - target_client: TC, - target_tick: Duration, - sync_maintain: impl SyncMaintain

, - sync_params: HeadersSyncParams, - metrics_sync: Option, - exit_signal: impl Future + Send, -) -> Result<(), FailedClient> { - let mut progress_context = (Instant::now(), None, None); - - let mut sync = HeadersSync::

::new(sync_params); - let mut stall_countdown = None; - let mut last_update_time = Instant::now(); - - let mut source_retry_backoff = retry_backoff(); - let mut source_client_is_online = false; - let mut source_best_block_number_required = false; - let source_best_block_number_future = source_client.best_block_number().fuse(); - let source_new_header_future = futures::future::Fuse::terminated(); - let source_orphan_header_future = futures::future::Fuse::terminated(); - let source_extra_future = futures::future::Fuse::terminated(); - let source_completion_future = futures::future::Fuse::terminated(); - let source_go_offline_future = futures::future::Fuse::terminated(); - let source_tick_stream = interval(source_tick).fuse(); - - let mut target_retry_backoff = retry_backoff(); - let mut target_client_is_online = false; - let mut target_best_block_required = false; - let mut target_incomplete_headers_required = true; - let target_best_block_future = target_client.best_header_id().fuse(); - let target_incomplete_headers_future = futures::future::Fuse::terminated(); - let target_extra_check_future = futures::future::Fuse::terminated(); - let target_existence_status_future = futures::future::Fuse::terminated(); - let target_submit_header_future = futures::future::Fuse::terminated(); - let target_complete_header_future = futures::future::Fuse::terminated(); - let target_go_offline_future = futures::future::Fuse::terminated(); - let target_tick_stream = interval(target_tick).fuse(); - - let mut maintain_required = false; - let maintain_stream = interval(MAINTAIN_INTERVAL).fuse(); - - let exit_signal = exit_signal.fuse(); - - futures::pin_mut!( - source_best_block_number_future, - source_new_header_future, - source_orphan_header_future, - source_extra_future, - source_completion_future, - source_go_offline_future, - source_tick_stream, - target_best_block_future, - target_incomplete_headers_future, - target_extra_check_future, - target_existence_status_future, - target_submit_header_future, - target_complete_header_future, - target_go_offline_future, - target_tick_stream, - maintain_stream, - exit_signal - ); - - loop { - futures::select! { - source_best_block_number = source_best_block_number_future => { - source_best_block_number_required = false; - - source_client_is_online = process_future_result( - source_best_block_number, - &mut source_retry_backoff, - |source_best_block_number| sync.source_best_header_number_response(source_best_block_number), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving best header number from {}", P::SOURCE_NAME), - ).fail_if_connection_error(FailedClient::Source)?; - }, - source_new_header = source_new_header_future => { - source_client_is_online = process_future_result( - source_new_header, - &mut source_retry_backoff, - |source_new_header| sync.headers_mut().header_response(source_new_header), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving header from {} node", P::SOURCE_NAME), - ).fail_if_connection_error(FailedClient::Source)?; - }, - source_orphan_header = source_orphan_header_future => { - source_client_is_online = process_future_result( - source_orphan_header, - &mut source_retry_backoff, - |source_orphan_header| sync.headers_mut().header_response(source_orphan_header), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving orphan header from {} node", P::SOURCE_NAME), - ).fail_if_connection_error(FailedClient::Source)?; - }, - source_extra = source_extra_future => { - source_client_is_online = process_future_result( - source_extra, - &mut source_retry_backoff, - |(header, extra)| sync.headers_mut().extra_response(&header, extra), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving extra data from {} node", P::SOURCE_NAME), - ).fail_if_connection_error(FailedClient::Source)?; - }, - source_completion = source_completion_future => { - source_client_is_online = process_future_result( - source_completion, - &mut source_retry_backoff, - |(header, completion)| sync.headers_mut().completion_response(&header, completion), - &mut source_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving completion data from {} node", P::SOURCE_NAME), - ).fail_if_connection_error(FailedClient::Source)?; - }, - _ = source_go_offline_future => { - source_client_is_online = true; - }, - _ = source_tick_stream.next() => { - if sync.is_almost_synced() { - source_best_block_number_required = true; - } - }, - target_best_block = target_best_block_future => { - target_best_block_required = false; - - target_client_is_online = process_future_result( - target_best_block, - &mut target_retry_backoff, - |target_best_block| { - let head_updated = sync.target_best_header_response(target_best_block); - if head_updated { - last_update_time = Instant::now(); - } - match head_updated { - // IF head is updated AND there are still our transactions: - // => restart stall countdown timer - true if sync.headers().headers_in_status(HeaderStatus::Submitted) != 0 => - stall_countdown = Some(Instant::now()), - // IF head is updated AND there are no our transactions: - // => stop stall countdown timer - true => stall_countdown = None, - // IF head is not updated AND stall countdown is not yet completed - // => do nothing - false if stall_countdown - .map(|stall_countdown| stall_countdown.elapsed() < STALL_SYNC_TIMEOUT) - .unwrap_or(true) - => (), - // IF head is not updated AND stall countdown has completed - // => restart sync - false => { - log::info!( - target: "bridge", - "Sync has stalled. Restarting {} headers synchronization.", - P::SOURCE_NAME, - ); - stall_countdown = None; - sync.restart(); - }, - } - }, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving best known {} header from {} node", P::SOURCE_NAME, P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - }, - incomplete_headers_ids = target_incomplete_headers_future => { - target_incomplete_headers_required = false; - - target_client_is_online = process_future_result( - incomplete_headers_ids, - &mut target_retry_backoff, - |incomplete_headers_ids| sync.headers_mut().incomplete_headers_response(incomplete_headers_ids), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving incomplete headers from {} node", P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - }, - target_existence_status = target_existence_status_future => { - target_client_is_online = process_future_result( - target_existence_status, - &mut target_retry_backoff, - |(target_header, target_existence_status)| sync - .headers_mut() - .maybe_orphan_response(&target_header, target_existence_status), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving existence status from {} node", P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - }, - submitted_headers = target_submit_header_future => { - // following line helps Rust understand the type of `submitted_headers` :/ - let submitted_headers: SubmittedHeaders, TC::Error> = submitted_headers; - let submitted_headers_str = format!("{}", submitted_headers); - let all_headers_rejected = submitted_headers.submitted.is_empty() - && submitted_headers.incomplete.is_empty(); - let has_submitted_headers = sync.headers().headers_in_status(HeaderStatus::Submitted) != 0; - - let maybe_fatal_error = match submitted_headers.fatal_error { - Some(fatal_error) => Err(StringifiedMaybeConnectionError::new( - fatal_error.is_connection_error(), - format!("{:?}", fatal_error), - )), - None if all_headers_rejected && !has_submitted_headers => - Err(StringifiedMaybeConnectionError::new(false, "All headers were rejected".into())), - None => Ok(()), - }; - - let no_fatal_error = maybe_fatal_error.is_ok(); - target_client_is_online = process_future_result( - maybe_fatal_error, - &mut target_retry_backoff, - |_| {}, - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error submitting headers to {} node", P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - - log::debug!(target: "bridge", "Header submit result: {}", submitted_headers_str); - - sync.headers_mut().headers_submitted(submitted_headers.submitted); - sync.headers_mut().add_incomplete_headers(false, submitted_headers.incomplete); - - // when there's no fatal error, but node has rejected all our headers we may - // want to pause until our submitted headers will be accepted - if no_fatal_error && all_headers_rejected && has_submitted_headers { - sync.pause_submit(); - } - }, - target_complete_header_result = target_complete_header_future => { - target_client_is_online = process_future_result( - target_complete_header_result, - &mut target_retry_backoff, - |completed_header| sync.headers_mut().header_completed(&completed_header), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error completing headers at {}", P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - }, - target_extra_check_result = target_extra_check_future => { - target_client_is_online = process_future_result( - target_extra_check_result, - &mut target_retry_backoff, - |(header, extra_check_result)| sync - .headers_mut() - .maybe_extra_response(&header, extra_check_result), - &mut target_go_offline_future, - async_std::task::sleep, - || format!("Error retrieving receipts requirement from {} node", P::TARGET_NAME), - ).fail_if_connection_error(FailedClient::Target)?; - }, - _ = target_go_offline_future => { - target_client_is_online = true; - }, - _ = target_tick_stream.next() => { - target_best_block_required = true; - target_incomplete_headers_required = true; - }, - - _ = maintain_stream.next() => { - maintain_required = true; - }, - _ = exit_signal => { - return Ok(()); - } - } - - // update metrics - if let Some(ref metrics_sync) = metrics_sync { - metrics_sync.update(&sync); - } - - // print progress - progress_context = print_sync_progress(progress_context, &sync); - - // run maintain procedures - if maintain_required && source_client_is_online && target_client_is_online { - log::debug!(target: "bridge", "Maintaining headers sync loop"); - maintain_required = false; - sync_maintain.maintain(&mut sync).await; - } - - // If the target client is accepting requests we update the requests that - // we want it to run - if !maintain_required && target_client_is_online { - // NOTE: Is is important to reset this so that we only have one - // request being processed by the client at a time. This prevents - // race conditions like receiving two transactions with the same - // nonce from the client. - target_client_is_online = false; - - // The following is how we prioritize requests: - // - // 1. Get best block - // - Stops us from downloading or submitting new blocks - // - Only called rarely - // - // 2. Get incomplete headers - // - Stops us from submitting new blocks - // - Only called rarely - // - // 3. Get complete headers - // - Stops us from submitting new blocks - // - // 4. Check if we need extra data from source - // - Stops us from downloading or submitting new blocks - // - // 5. Check existence of header - // - Stops us from submitting new blocks - // - // 6. Submit header - - if target_best_block_required { - log::debug!(target: "bridge", "Asking {} about best block", P::TARGET_NAME); - target_best_block_future.set(target_client.best_header_id().fuse()); - } else if target_incomplete_headers_required { - log::debug!(target: "bridge", "Asking {} about incomplete headers", P::TARGET_NAME); - target_incomplete_headers_future.set(target_client.incomplete_headers_ids().fuse()); - } else if let Some((id, completion)) = sync.headers_mut().header_to_complete() { - log::debug!( - target: "bridge", - "Going to complete header: {:?}", - id, - ); - - target_complete_header_future - .set(target_client.complete_header(id, completion.clone()).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeExtra) { - log::debug!( - target: "bridge", - "Checking if header submission requires extra: {:?}", - header.id(), - ); - - target_extra_check_future.set(target_client.requires_extra(header.clone()).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::MaybeOrphan) { - // for MaybeOrphan we actually ask for parent' header existence - let parent_id = header.parent_id(); - - log::debug!( - target: "bridge", - "Asking {} node for existence of: {:?}", - P::TARGET_NAME, - parent_id, - ); - - target_existence_status_future.set(target_client.is_known_header(parent_id).fuse()); - } else if let Some(headers) = sync - .select_headers_to_submit(last_update_time.elapsed() > BACKUP_STALL_SYNC_TIMEOUT) - { - log::debug!( - target: "bridge", - "Submitting {} header(s) to {} node: {:?}", - headers.len(), - P::TARGET_NAME, - format_ids(headers.iter().map(|header| header.id())), - ); - - let headers = headers.into_iter().cloned().collect(); - target_submit_header_future.set(target_client.submit_headers(headers).fuse()); - - // remember that we have submitted some headers - if stall_countdown.is_none() { - stall_countdown = Some(Instant::now()); - } - } else { - target_client_is_online = true; - } - } - - // If the source client is accepting requests we update the requests that - // we want it to run - if !maintain_required && source_client_is_online { - // NOTE: Is is important to reset this so that we only have one - // request being processed by the client at a time. This prevents - // race conditions like receiving two transactions with the same - // nonce from the client. - source_client_is_online = false; - - // The following is how we prioritize requests: - // - // 1. Get best block - // - Stops us from downloading or submitting new blocks - // - Only called rarely - // - // 2. Download completion data - // - Stops us from submitting new blocks - // - // 3. Download extra data - // - Stops us from submitting new blocks - // - // 4. Download missing headers - // - Stops us from downloading or submitting new blocks - // - // 5. Downloading new headers - - if source_best_block_number_required { - log::debug!(target: "bridge", "Asking {} node about best block number", P::SOURCE_NAME); - source_best_block_number_future.set(source_client.best_block_number().fuse()); - } else if let Some(id) = sync.headers_mut().incomplete_header() { - log::debug!( - target: "bridge", - "Retrieving completion data for header: {:?}", - id, - ); - source_completion_future.set(source_client.header_completion(id).fuse()); - } else if let Some(header) = sync.headers().header(HeaderStatus::Extra) { - let id = header.id(); - log::debug!( - target: "bridge", - "Retrieving extra data for header: {:?}", - id, - ); - source_extra_future.set(source_client.header_extra(id, header.clone()).fuse()); - } else if let Some(header) = sync.select_orphan_header_to_download() { - // for Orphan we actually ask for parent' header - let parent_id = header.parent_id(); - - // if we have end up with orphan header#0, then we are misconfigured - if parent_id.0.is_zero() { - log::error!( - target: "bridge", - "Misconfiguration. Genesis {} header is considered orphan by {} node", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - return Ok(()) - } - - log::debug!( - target: "bridge", - "Going to download orphan header from {} node: {:?}", - P::SOURCE_NAME, - parent_id, - ); - - source_orphan_header_future.set(source_client.header_by_hash(parent_id.1).fuse()); - } else if let Some(id) = sync.select_new_header_to_download() { - log::debug!( - target: "bridge", - "Going to download new header from {} node: {:?}", - P::SOURCE_NAME, - id, - ); - - source_new_header_future.set(source_client.header_by_number(id).fuse()); - } else { - source_client_is_online = true; - } - } - } -} - -/// Print synchronization progress. -fn print_sync_progress( - progress_context: (Instant, Option, Option), - eth_sync: &HeadersSync

, -) -> (Instant, Option, Option) { - let (prev_time, prev_best_header, prev_target_header) = progress_context; - let now_time = Instant::now(); - let (now_best_header, now_target_header) = eth_sync.status(); - - let need_update = now_time - prev_time > Duration::from_secs(10) || - match (prev_best_header, now_best_header) { - (Some(prev_best_header), Some(now_best_header)) => - now_best_header.0.saturating_sub(prev_best_header) > 10.into(), - _ => false, - }; - if !need_update { - return (prev_time, prev_best_header, prev_target_header) - } - - log::info!( - target: "bridge", - "Synced {:?} of {:?} headers", - now_best_header.map(|id| id.0), - now_target_header, - ); - (now_time, (*now_best_header).map(|id| id.0), *now_target_header) -} diff --git a/relays/headers/src/sync_loop_tests.rs b/relays/headers/src/sync_loop_tests.rs deleted file mode 100644 index f100998ca83f9..0000000000000 --- a/relays/headers/src/sync_loop_tests.rs +++ /dev/null @@ -1,602 +0,0 @@ -// 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 . - -#![cfg(test)] - -use crate::{ - sync_loop::{run, SourceClient, TargetClient}, - sync_types::{HeadersSyncPipeline, QueuedHeader, SourceHeader, SubmittedHeaders}, -}; - -use async_trait::async_trait; -use backoff::backoff::Backoff; -use futures::{future::FutureExt, stream::StreamExt}; -use parking_lot::Mutex; -use relay_utils::{ - metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, - retry_backoff, HeaderId, MaybeConnectionError, -}; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, - time::Duration, -}; - -pub type TestNumber = u64; -pub type TestHash = u64; -pub type TestHeaderId = HeaderId; -pub type TestExtra = u64; -pub type TestCompletion = u64; -pub type TestQueuedHeader = QueuedHeader; - -#[derive(Default, Debug, Clone, PartialEq)] -pub struct TestHeader { - pub hash: TestHash, - pub number: TestNumber, - pub parent_hash: TestHash, -} - -impl SourceHeader for TestHeader { - fn id(&self) -> TestHeaderId { - HeaderId(self.number, self.hash) - } - - fn parent_id(&self) -> TestHeaderId { - HeaderId(self.number - 1, self.parent_hash) - } -} - -#[derive(Debug, Clone)] -struct TestError(bool); - -impl MaybeConnectionError for TestError { - fn is_connection_error(&self) -> bool { - self.0 - } -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct TestHeadersSyncPipeline; - -impl HeadersSyncPipeline for TestHeadersSyncPipeline { - const SOURCE_NAME: &'static str = "Source"; - const TARGET_NAME: &'static str = "Target"; - - type Hash = TestHash; - type Number = TestNumber; - type Header = TestHeader; - type Extra = TestExtra; - type Completion = TestCompletion; - - fn estimate_size(_: &TestQueuedHeader) -> usize { - 0 - } -} - -enum SourceMethod { - BestBlockNumber, - HeaderByHash(TestHash), - HeaderByNumber(TestNumber), - HeaderCompletion(TestHeaderId), - HeaderExtra(TestHeaderId, TestQueuedHeader), -} - -#[derive(Clone)] -struct Source { - data: Arc>, - on_method_call: Arc, -} - -struct SourceData { - best_block_number: Result, - header_by_hash: HashMap, - header_by_number: HashMap, - provides_completion: bool, - provides_extra: bool, -} - -impl Source { - pub fn new( - best_block_id: TestHeaderId, - headers: Vec<(bool, TestHeader)>, - on_method_call: impl Fn(SourceMethod, &mut SourceData) + Send + Sync + 'static, - ) -> Self { - Source { - data: Arc::new(Mutex::new(SourceData { - best_block_number: Ok(best_block_id.0), - header_by_hash: headers - .iter() - .map(|(_, header)| (header.hash, header.clone())) - .collect(), - header_by_number: headers - .iter() - .filter_map(|(is_canonical, header)| { - if *is_canonical { - Some((header.hash, header.clone())) - } else { - None - } - }) - .collect(), - provides_completion: true, - provides_extra: true, - })), - on_method_call: Arc::new(on_method_call), - } - } -} - -#[async_trait] -impl RelayClient for Source { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - unimplemented!() - } -} - -#[async_trait] -impl SourceClient for Source { - async fn best_block_number(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(SourceMethod::BestBlockNumber, &mut *data); - data.best_block_number.clone() - } - - async fn header_by_hash(&self, hash: TestHash) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(SourceMethod::HeaderByHash(hash), &mut *data); - data.header_by_hash.get(&hash).cloned().ok_or(TestError(false)) - } - - async fn header_by_number(&self, number: TestNumber) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(SourceMethod::HeaderByNumber(number), &mut *data); - data.header_by_number.get(&number).cloned().ok_or(TestError(false)) - } - - async fn header_completion( - &self, - id: TestHeaderId, - ) -> Result<(TestHeaderId, Option), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(SourceMethod::HeaderCompletion(id), &mut *data); - if data.provides_completion { - Ok((id, Some(test_completion(id)))) - } else { - Ok((id, None)) - } - } - - async fn header_extra( - &self, - id: TestHeaderId, - header: TestQueuedHeader, - ) -> Result<(TestHeaderId, TestExtra), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(SourceMethod::HeaderExtra(id, header), &mut *data); - if data.provides_extra { - Ok((id, test_extra(id))) - } else { - Err(TestError(false)) - } - } -} - -enum TargetMethod { - BestHeaderId, - IsKnownHeader(TestHeaderId), - SubmitHeaders(Vec), - IncompleteHeadersIds, - CompleteHeader(TestHeaderId, TestCompletion), - RequiresExtra(TestQueuedHeader), -} - -#[derive(Clone)] -struct Target { - data: Arc>, - on_method_call: Arc, -} - -struct TargetData { - best_header_id: Result, - is_known_header_by_hash: HashMap, - submitted_headers: HashMap, - submit_headers_result: Option>, - completed_headers: HashMap, - requires_completion: bool, - requires_extra: bool, -} - -impl Target { - pub fn new( - best_header_id: TestHeaderId, - headers: Vec, - on_method_call: impl Fn(TargetMethod, &mut TargetData) + Send + Sync + 'static, - ) -> Self { - Target { - data: Arc::new(Mutex::new(TargetData { - best_header_id: Ok(best_header_id), - is_known_header_by_hash: headers.iter().map(|header| (header.1, true)).collect(), - submitted_headers: HashMap::new(), - submit_headers_result: None, - completed_headers: HashMap::new(), - requires_completion: false, - requires_extra: false, - })), - on_method_call: Arc::new(on_method_call), - } - } -} - -#[async_trait] -impl RelayClient for Target { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - unimplemented!() - } -} - -#[async_trait] -impl TargetClient for Target { - async fn best_header_id(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(TargetMethod::BestHeaderId, &mut *data); - data.best_header_id.clone() - } - - async fn is_known_header(&self, id: TestHeaderId) -> Result<(TestHeaderId, bool), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(TargetMethod::IsKnownHeader(id), &mut *data); - data.is_known_header_by_hash - .get(&id.1) - .cloned() - .map(|is_known_header| Ok((id, is_known_header))) - .unwrap_or(Ok((id, false))) - } - - async fn submit_headers( - &self, - headers: Vec, - ) -> SubmittedHeaders { - let mut data = self.data.lock(); - (self.on_method_call)(TargetMethod::SubmitHeaders(headers.clone()), &mut *data); - data.submitted_headers - .extend(headers.iter().map(|header| (header.id().1, header.clone()))); - data.submit_headers_result.take().expect("test must accept headers") - } - - async fn incomplete_headers_ids(&self) -> Result, TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(TargetMethod::IncompleteHeadersIds, &mut *data); - if data.requires_completion { - Ok(data - .submitted_headers - .iter() - .filter(|(hash, _)| !data.completed_headers.contains_key(hash)) - .map(|(_, header)| header.id()) - .collect()) - } else { - Ok(HashSet::new()) - } - } - - async fn complete_header( - &self, - id: TestHeaderId, - completion: TestCompletion, - ) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(TargetMethod::CompleteHeader(id, completion), &mut *data); - data.completed_headers.insert(id.1, completion); - Ok(id) - } - - async fn requires_extra( - &self, - header: TestQueuedHeader, - ) -> Result<(TestHeaderId, bool), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(TargetMethod::RequiresExtra(header.clone()), &mut *data); - if data.requires_extra { - Ok((header.id(), true)) - } else { - Ok((header.id(), false)) - } - } -} - -fn test_tick() -> Duration { - // in ideal world that should have been Duration::from_millis(0), because we do not want - // to sleep in tests at all, but that could lead to `select! {}` always waking on tick - // => not doing actual job - Duration::from_millis(10) -} - -fn test_id(number: TestNumber) -> TestHeaderId { - HeaderId(number, number) -} - -fn test_header(number: TestNumber) -> TestHeader { - let id = test_id(number); - TestHeader { - hash: id.1, - number: id.0, - parent_hash: if number == 0 { TestHash::default() } else { test_id(number - 1).1 }, - } -} - -fn test_forked_id(number: TestNumber, forked_from: TestNumber) -> TestHeaderId { - const FORK_OFFSET: TestNumber = 1000; - - if number == forked_from { - HeaderId(number, number) - } else { - HeaderId(number, FORK_OFFSET + number) - } -} - -fn test_forked_header(number: TestNumber, forked_from: TestNumber) -> TestHeader { - let id = test_forked_id(number, forked_from); - TestHeader { - hash: id.1, - number: id.0, - parent_hash: if number == 0 { - TestHash::default() - } else { - test_forked_id(number - 1, forked_from).1 - }, - } -} - -fn test_completion(id: TestHeaderId) -> TestCompletion { - id.0 -} - -fn test_extra(id: TestHeaderId) -> TestExtra { - id.0 -} - -fn source_reject_completion(method: &SourceMethod) { - if let SourceMethod::HeaderCompletion(_) = method { - unreachable!("HeaderCompletion request is not expected") - } -} - -fn source_reject_extra(method: &SourceMethod) { - if let SourceMethod::HeaderExtra(_, _) = method { - unreachable!("HeaderExtra request is not expected") - } -} - -fn target_accept_all_headers(method: &TargetMethod, data: &mut TargetData, requires_extra: bool) { - if let TargetMethod::SubmitHeaders(ref submitted) = method { - assert_eq!(submitted.iter().all(|header| header.extra().is_some()), requires_extra,); - - data.submit_headers_result = Some(SubmittedHeaders { - submitted: submitted.iter().map(|header| header.id()).collect(), - ..Default::default() - }); - } -} - -fn target_signal_exit_when_header_submitted( - method: &TargetMethod, - header_id: TestHeaderId, - exit_signal: &futures::channel::mpsc::UnboundedSender<()>, -) { - if let TargetMethod::SubmitHeaders(ref submitted) = method { - if submitted.iter().any(|header| header.id() == header_id) { - exit_signal.unbounded_send(()).unwrap(); - } - } -} - -fn target_signal_exit_when_header_completed( - method: &TargetMethod, - header_id: TestHeaderId, - exit_signal: &futures::channel::mpsc::UnboundedSender<()>, -) { - if let TargetMethod::CompleteHeader(completed_id, _) = method { - if *completed_id == header_id { - exit_signal.unbounded_send(()).unwrap(); - } - } -} - -fn run_backoff_test(result: Result<(), TestError>) -> (Duration, Duration) { - let mut backoff = retry_backoff(); - - // no randomness in tests (otherwise intervals may overlap => asserts are failing) - backoff.randomization_factor = 0f64; - - // increase backoff's current interval - let interval1 = backoff.next_backoff().unwrap(); - let interval2 = backoff.next_backoff().unwrap(); - assert!(interval2 > interval1); - - // successful future result leads to backoff's reset - let go_offline_future = futures::future::Fuse::terminated(); - futures::pin_mut!(go_offline_future); - - process_future_result( - result, - &mut backoff, - |_| {}, - &mut go_offline_future, - async_std::task::sleep, - || "Test error".into(), - ); - - (interval2, backoff.next_backoff().unwrap()) -} - -#[test] -fn process_future_result_resets_backoff_on_success() { - let (interval2, interval_after_reset) = run_backoff_test(Ok(())); - assert!(interval2 > interval_after_reset); -} - -#[test] -fn process_future_result_resets_backoff_on_connection_error() { - let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(true))); - assert!(interval2 > interval_after_reset); -} - -#[test] -fn process_future_result_does_not_reset_backoff_on_non_connection_error() { - let (interval2, interval_after_reset) = run_backoff_test(Err(TestError(false))); - assert!(interval2 < interval_after_reset); -} - -struct SyncLoopTestParams { - best_source_header: TestHeader, - headers_on_source: Vec<(bool, TestHeader)>, - best_target_header: TestHeader, - headers_on_target: Vec, - target_requires_extra: bool, - target_requires_completion: bool, - stop_at: TestHeaderId, -} - -fn run_sync_loop_test(params: SyncLoopTestParams) { - let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); - let target_requires_extra = params.target_requires_extra; - let target_requires_completion = params.target_requires_completion; - let stop_at = params.stop_at; - let source = - Source::new(params.best_source_header.id(), params.headers_on_source, move |method, _| { - if !target_requires_extra { - source_reject_extra(&method); - } - if !target_requires_completion { - source_reject_completion(&method); - } - }); - let target = Target::new( - params.best_target_header.id(), - params.headers_on_target.into_iter().map(|header| header.id()).collect(), - move |method, data| { - target_accept_all_headers(&method, data, target_requires_extra); - if target_requires_completion { - target_signal_exit_when_header_completed(&method, stop_at, &exit_sender); - } else { - target_signal_exit_when_header_submitted(&method, stop_at, &exit_sender); - } - }, - ); - target.data.lock().requires_extra = target_requires_extra; - target.data.lock().requires_completion = target_requires_completion; - - let _ = async_std::task::block_on(run( - source, - test_tick(), - target, - test_tick(), - (), - crate::sync::tests::default_sync_params(), - MetricsParams::disabled(), - exit_receiver.into_future().map(|(_, _)| ()), - )); -} - -#[test] -fn sync_loop_is_able_to_synchronize_single_header() { - run_sync_loop_test(SyncLoopTestParams { - best_source_header: test_header(1), - headers_on_source: vec![(true, test_header(1))], - best_target_header: test_header(0), - headers_on_target: vec![test_header(0)], - target_requires_extra: false, - target_requires_completion: false, - stop_at: test_id(1), - }); -} - -#[test] -fn sync_loop_is_able_to_synchronize_single_header_with_extra() { - run_sync_loop_test(SyncLoopTestParams { - best_source_header: test_header(1), - headers_on_source: vec![(true, test_header(1))], - best_target_header: test_header(0), - headers_on_target: vec![test_header(0)], - target_requires_extra: true, - target_requires_completion: false, - stop_at: test_id(1), - }); -} - -#[test] -fn sync_loop_is_able_to_synchronize_single_header_with_completion() { - run_sync_loop_test(SyncLoopTestParams { - best_source_header: test_header(1), - headers_on_source: vec![(true, test_header(1))], - best_target_header: test_header(0), - headers_on_target: vec![test_header(0)], - target_requires_extra: false, - target_requires_completion: true, - stop_at: test_id(1), - }); -} - -#[test] -fn sync_loop_is_able_to_reorganize_from_shorter_fork() { - run_sync_loop_test(SyncLoopTestParams { - best_source_header: test_header(3), - headers_on_source: vec![ - (true, test_header(1)), - (true, test_header(2)), - (true, test_header(3)), - (false, test_forked_header(1, 0)), - (false, test_forked_header(2, 0)), - ], - best_target_header: test_forked_header(2, 0), - headers_on_target: vec![test_header(0), test_forked_header(1, 0), test_forked_header(2, 0)], - target_requires_extra: false, - target_requires_completion: false, - stop_at: test_id(3), - }); -} - -#[test] -fn sync_loop_is_able_to_reorganize_from_longer_fork() { - run_sync_loop_test(SyncLoopTestParams { - best_source_header: test_header(3), - headers_on_source: vec![ - (true, test_header(1)), - (true, test_header(2)), - (true, test_header(3)), - (false, test_forked_header(1, 0)), - (false, test_forked_header(2, 0)), - (false, test_forked_header(3, 0)), - (false, test_forked_header(4, 0)), - (false, test_forked_header(5, 0)), - ], - best_target_header: test_forked_header(5, 0), - headers_on_target: vec![ - test_header(0), - test_forked_header(1, 0), - test_forked_header(2, 0), - test_forked_header(3, 0), - test_forked_header(4, 0), - test_forked_header(5, 0), - ], - target_requires_extra: false, - target_requires_completion: false, - stop_at: test_id(3), - }); -} diff --git a/relays/headers/src/sync_types.rs b/relays/headers/src/sync_types.rs deleted file mode 100644 index 8d93e8bf49fbe..0000000000000 --- a/relays/headers/src/sync_types.rs +++ /dev/null @@ -1,193 +0,0 @@ -// 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 . - -//! Types that are used by headers synchronization components. - -use relay_utils::{format_ids, HeaderId}; -use std::{ops::Deref, sync::Arc}; - -/// Ethereum header synchronization status. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum HeaderStatus { - /// Header is unknown. - Unknown, - /// Header is in MaybeOrphan queue. - MaybeOrphan, - /// Header is in Orphan queue. - Orphan, - /// Header is in MaybeExtra queue. - MaybeExtra, - /// Header is in Extra queue. - Extra, - /// Header is in Ready queue. - Ready, - /// Header is in Incomplete queue. - Incomplete, - /// Header has been recently submitted to the target node. - Submitted, - /// Header is known to the target node. - Synced, -} - -/// Headers synchronization pipeline. -pub trait HeadersSyncPipeline: 'static + Clone + Send + Sync { - /// Name of the headers source. - const SOURCE_NAME: &'static str; - /// Name of the headers target. - const TARGET_NAME: &'static str; - - /// Headers we're syncing are identified by this hash. - type Hash: Eq - + Clone - + Copy - + Send - + Sync - + std::fmt::Debug - + std::fmt::Display - + std::hash::Hash; - /// Headers we're syncing are identified by this number. - type Number: relay_utils::BlockNumberBase; - /// Type of header that we're syncing. - type Header: SourceHeader; - /// Type of extra data for the header that we're receiving from the source node: - /// 1) extra data is required for some headers; - /// 2) target node may answer if it'll require extra data before header is submitted; - /// 3) extra data available since the header creation time; - /// 4) header and extra data are submitted in single transaction. - /// - /// Example: Ethereum transactions receipts. - type Extra: Clone + Send + Sync + PartialEq + std::fmt::Debug; - /// Type of data required to 'complete' header that we're receiving from the source node: - /// 1) completion data is required for some headers; - /// 2) target node can't answer if it'll require completion data before header is accepted; - /// 3) completion data may be generated after header generation; - /// 4) header and completion data are submitted in separate transactions. - /// - /// Example: Substrate GRANDPA justifications. - type Completion: Clone + Send + Sync + std::fmt::Debug; - - /// Function used to estimate size of target-encoded header. - fn estimate_size(source: &QueuedHeader) -> usize; -} - -/// A HeaderId for `HeaderSyncPipeline`. -pub type HeaderIdOf

= - HeaderId<

::Hash,

::Number>; - -/// Header that we're receiving from source node. -pub trait SourceHeader: Clone + std::fmt::Debug + PartialEq + Send + Sync { - /// Returns ID of header. - fn id(&self) -> HeaderId; - /// Returns ID of parent header. - /// - /// Panics if called for genesis header. - fn parent_id(&self) -> HeaderId; -} - -/// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug, PartialEq)] -pub struct QueuedHeader(Arc>); - -impl QueuedHeader

{ - /// Creates new queued header. - pub fn new(header: P::Header) -> Self { - QueuedHeader(Arc::new(QueuedHeaderData { header, extra: None })) - } - - /// Set associated extra data. - pub fn set_extra(self, extra: P::Extra) -> Self { - QueuedHeader(Arc::new(QueuedHeaderData { - header: Arc::try_unwrap(self.0) - .map(|data| data.header) - .unwrap_or_else(|data| data.header.clone()), - extra: Some(extra), - })) - } -} - -impl Deref for QueuedHeader

{ - type Target = QueuedHeaderData

; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// Header how it's stored in the synchronization queue. -#[derive(Clone, Debug, Default, PartialEq)] -pub struct QueuedHeaderData { - header: P::Header, - extra: Option, -} - -impl QueuedHeader

{ - /// Returns ID of header. - pub fn id(&self) -> HeaderId { - self.header.id() - } - - /// Returns ID of parent header. - pub fn parent_id(&self) -> HeaderId { - self.header.parent_id() - } - - /// Returns reference to header. - pub fn header(&self) -> &P::Header { - &self.header - } - - /// Returns reference to associated extra data. - pub fn extra(&self) -> &Option { - &self.extra - } -} - -/// Headers submission result. -#[derive(Debug)] -#[cfg_attr(test, derive(PartialEq))] -pub struct SubmittedHeaders { - /// IDs of headers that have been submitted to target node. - pub submitted: Vec, - /// IDs of incomplete headers. These headers were submitted (so this id is also in `submitted` - /// vec), but all descendants are not. - pub incomplete: Vec, - /// IDs of ignored headers that we have decided not to submit (they are either rejected by - /// target node immediately, or their descendants of incomplete headers). - pub rejected: Vec, - /// Fatal target node error, if it has occurred during submission. - pub fatal_error: Option, -} - -impl Default for SubmittedHeaders { - fn default() -> Self { - SubmittedHeaders { - submitted: Vec::new(), - incomplete: Vec::new(), - rejected: Vec::new(), - fatal_error: None, - } - } -} - -impl std::fmt::Display for SubmittedHeaders { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let submitted = format_ids(self.submitted.iter()); - let incomplete = format_ids(self.incomplete.iter()); - let rejected = format_ids(self.rejected.iter()); - - write!(f, "Submitted: {}, Incomplete: {}, Rejected: {}", submitted, incomplete, rejected) - } -} From 79237972aee9b37b62a6412c2974901b3c9edae3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 17 Nov 2021 15:01:19 +0300 Subject: [PATCH 0602/1210] remove abandoned exchange relay (#1217) --- relays/exchange/Cargo.toml | 18 - relays/exchange/src/error.rs | 66 -- relays/exchange/src/exchange.rs | 904 ------------------- relays/exchange/src/exchange_loop.rs | 322 ------- relays/exchange/src/exchange_loop_metrics.rs | 97 -- relays/exchange/src/lib.rs | 27 - 6 files changed, 1434 deletions(-) delete mode 100644 relays/exchange/Cargo.toml delete mode 100644 relays/exchange/src/error.rs delete mode 100644 relays/exchange/src/exchange.rs delete mode 100644 relays/exchange/src/exchange_loop.rs delete mode 100644 relays/exchange/src/exchange_loop_metrics.rs delete mode 100644 relays/exchange/src/lib.rs diff --git a/relays/exchange/Cargo.toml b/relays/exchange/Cargo.toml deleted file mode 100644 index f08c40325ec71..0000000000000 --- a/relays/exchange/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "exchange-relay" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -anyhow = "1.0" -async-std = "1.6.5" -async-trait = "0.1.40" -backoff = "0.2" -futures = "0.3.5" -log = "0.4.11" -num-traits = "0.2" -parking_lot = "0.11.0" -relay-utils = { path = "../utils" } -thiserror = "1.0.26" diff --git a/relays/exchange/src/error.rs b/relays/exchange/src/error.rs deleted file mode 100644 index aa5c427a9efbd..0000000000000 --- a/relays/exchange/src/error.rs +++ /dev/null @@ -1,66 +0,0 @@ -// 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 . - -//! Exchange-relay errors. - -use crate::exchange::{BlockHashOf, BlockNumberOf, TransactionHashOf}; - -use relay_utils::MaybeConnectionError; -use std::fmt::{Debug, Display}; -use thiserror::Error; - -/// Error type given pipeline. -pub type ErrorOf

= Error, BlockNumberOf

, TransactionHashOf

>; - -/// Exchange-relay error type. -#[derive(Error, Debug)] -pub enum Error { - /// Failed to check finality of the requested header on the target node. - #[error("Failed to check finality of header {0}/{1} on {2} node: {3:?}")] - Finality(HeaderNumber, Hash, &'static str, anyhow::Error), - /// Error retrieving block from the source node. - #[error("Error retrieving block {0} from {1} node: {2:?}")] - RetrievingBlock(Hash, &'static str, anyhow::Error), - /// Error retrieving transaction from the source node. - #[error("Error retrieving transaction {0} from {1} node: {2:?}")] - RetrievingTransaction(SourceTxHash, &'static str, anyhow::Error), - /// Failed to check existence of header from the target node. - #[error("Failed to check existence of header {0}/{1} on {2} node: {3:?}")] - CheckHeaderExistence(HeaderNumber, Hash, &'static str, anyhow::Error), - /// Failed to prepare proof for the transaction from the source node. - #[error("Error building transaction {0} proof on {1} node: {2:?}")] - BuildTransactionProof(String, &'static str, anyhow::Error, bool), - /// Failed to submit the transaction proof to the target node. - #[error("Error submitting transaction {0} proof to {1} node: {2:?}")] - SubmitTransactionProof(String, &'static str, anyhow::Error, bool), - /// Transaction filtering failed. - #[error("Transaction filtering has failed with {0:?}")] - TransactionFiltering(anyhow::Error, bool), - /// Utilities/metrics error. - #[error("{0}")] - Utils(#[from] relay_utils::Error), -} - -impl MaybeConnectionError for Error { - fn is_connection_error(&self) -> bool { - match *self { - Self::BuildTransactionProof(_, _, _, b) => b, - Self::SubmitTransactionProof(_, _, _, b) => b, - Self::TransactionFiltering(_, b) => b, - _ => false, - } - } -} diff --git a/relays/exchange/src/exchange.rs b/relays/exchange/src/exchange.rs deleted file mode 100644 index b4538d2636cec..0000000000000 --- a/relays/exchange/src/exchange.rs +++ /dev/null @@ -1,904 +0,0 @@ -// 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 . - -//! Relaying proofs of exchange transaction. - -use crate::error::{Error, ErrorOf}; - -use anyhow::anyhow; -use async_trait::async_trait; -use relay_utils::{relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError}; -use std::{ - fmt::{Debug, Display}, - string::ToString, -}; - -/// Transaction proof pipeline. -pub trait TransactionProofPipeline: 'static { - /// Name of the transaction proof source. - const SOURCE_NAME: &'static str; - /// Name of the transaction proof target. - const TARGET_NAME: &'static str; - - /// Block type. - type Block: SourceBlock; - /// Transaction inclusion proof type. - type TransactionProof: 'static + Send + Sync; -} - -/// Block that is participating in exchange. -pub trait SourceBlock: 'static + Send + Sync { - /// Block hash type. - type Hash: 'static + Clone + Send + Sync + Debug + Display; - /// Block number type. - type Number: 'static - + Debug - + Display - + Clone - + Copy - + Send - + Sync - + Into - + std::cmp::Ord - + std::ops::Add - + num_traits::One; - /// Block transaction. - type Transaction: SourceTransaction; - - /// Return hash of the block. - fn id(&self) -> relay_utils::HeaderId; - /// Return block transactions iterator. - fn transactions(&self) -> Vec; -} - -/// Transaction that is participating in exchange. -pub trait SourceTransaction: 'static + Send { - /// Transaction hash type. - type Hash: Debug + Display + Clone; - - /// Return transaction hash. - fn hash(&self) -> Self::Hash; -} - -/// Block hash for given pipeline. -pub type BlockHashOf

= <

::Block as SourceBlock>::Hash; - -/// Block number for given pipeline. -pub type BlockNumberOf

= <

::Block as SourceBlock>::Number; - -/// Transaction hash for given pipeline. -pub type TransactionOf

= <

::Block as SourceBlock>::Transaction; - -/// Transaction hash for given pipeline. -pub type TransactionHashOf

= as SourceTransaction>::Hash; - -/// Header id. -pub type HeaderId

= relay_utils::HeaderId, BlockNumberOf

>; - -/// Source client API. -#[async_trait] -pub trait SourceClient: RelayClient { - /// Sleep until exchange-related data is (probably) updated. - async fn tick(&self); - /// Get block by hash. - async fn block_by_hash(&self, hash: BlockHashOf

) -> Result; - /// Get canonical block by number. - async fn block_by_number(&self, number: BlockNumberOf

) -> Result; - /// Return block + index where transaction has been **mined**. May return `Ok(None)` if - /// transaction is unknown to the source node. - async fn transaction_block( - &self, - hash: &TransactionHashOf

, - ) -> Result, usize)>, Self::Error>; - /// Prepare transaction proof. - async fn transaction_proof( - &self, - block: &P::Block, - tx_index: usize, - ) -> Result; -} - -/// Target client API. -#[async_trait] -pub trait TargetClient: RelayClient { - /// Sleep until exchange-related data is (probably) updated. - async fn tick(&self); - /// Returns `Ok(true)` if header is known to the target node. - async fn is_header_known(&self, id: &HeaderId

) -> std::result::Result; - /// Returns `Ok(true)` if header is finalized by the target node. - async fn is_header_finalized(&self, id: &HeaderId

) -> Result; - /// Returns best finalized header id. - async fn best_finalized_header_id(&self) -> Result, Self::Error>; - /// Returns `Ok(true)` if transaction proof is need to be relayed. - async fn filter_transaction_proof( - &self, - proof: &P::TransactionProof, - ) -> Result; - /// Submits transaction proof to the target node. - async fn submit_transaction_proof(&self, proof: P::TransactionProof) - -> Result<(), Self::Error>; -} - -/// Block transaction statistics. -#[derive(Debug, Default)] -#[cfg_attr(test, derive(PartialEq))] -pub struct RelayedBlockTransactions { - /// Total number of transactions processed (either relayed or ignored) so far. - pub processed: usize, - /// Total number of transactions successfully relayed so far. - pub relayed: usize, - /// Total number of transactions that we have failed to relay so far. - pub failed: usize, -} - -/// Relay all suitable transactions from single block. -/// -/// If connection error occurs, returns Err with number of successfully processed transactions. -/// If some other error occurs, it is ignored and other transactions are processed. -/// -/// All transaction-level traces are written by this function. This function is not tracing -/// any information about block. -pub async fn relay_block_transactions( - source_client: &impl SourceClient

, - target_client: &impl TargetClient

, - source_block: &P::Block, - mut relayed_transactions: RelayedBlockTransactions, -) -> Result { - let transactions_to_process = source_block - .transactions() - .into_iter() - .enumerate() - .skip(relayed_transactions.processed); - for (source_tx_index, source_tx) in transactions_to_process { - let result = async { - let source_tx_id = format!("{}/{}", source_block.id().1, source_tx_index); - let source_tx_proof = prepare_transaction_proof( - source_client, - &source_tx_id, - source_block, - source_tx_index, - ) - .await - .map_err(|e| (FailedClient::Source, e))?; - - let needs_to_be_relayed = - target_client.filter_transaction_proof(&source_tx_proof).await.map_err(|err| { - ( - FailedClient::Target, - Error::TransactionFiltering( - anyhow!("{:?}", err), - err.is_connection_error(), - ), - ) - })?; - - if !needs_to_be_relayed { - return Ok(false) - } - - relay_ready_transaction_proof(target_client, &source_tx_id, source_tx_proof) - .await - .map(|_| true) - .map_err(|e| (FailedClient::Target, e)) - } - .await; - - // We have two options here: - // 1) retry with the same transaction later; - // 2) report error and proceed with next transaction. - // - // Option#1 may seems better, but: - // 1) we do not track if transaction is mined (without an error) by the target node; - // 2) error could be irrecoverable (e.g. when block is already pruned by bridge module or tx - // has invalid format) && we'll end up in infinite loop of retrying the same transaction - // proof. - // - // So we're going with option#2 here (the only exception are connection errors). - match result { - Ok(false) => { - relayed_transactions.processed += 1; - }, - Ok(true) => { - log::info!( - target: "bridge", - "{} transaction {} proof has been successfully submitted to {} node", - P::SOURCE_NAME, - source_tx.hash(), - P::TARGET_NAME, - ); - - relayed_transactions.processed += 1; - relayed_transactions.relayed += 1; - }, - Err((failed_client, err)) => { - log::error!( - target: "bridge", - "Error relaying {} transaction {} proof to {} node: {}. {}", - P::SOURCE_NAME, - source_tx.hash(), - P::TARGET_NAME, - err.to_string(), - if err.is_connection_error() { - "Going to retry after delay..." - } else { - "You may need to submit proof of this transaction manually" - }, - ); - - if err.is_connection_error() { - return Err((failed_client, relayed_transactions)) - } - - relayed_transactions.processed += 1; - relayed_transactions.failed += 1; - }, - } - } - - Ok(relayed_transactions) -} - -/// Relay single transaction proof. -pub async fn relay_single_transaction_proof( - source_client: &impl SourceClient

, - target_client: &impl TargetClient

, - source_tx_hash: TransactionHashOf

, -) -> Result<(), ErrorOf

> { - // wait for transaction and header on source node - let (source_header_id, source_tx_index) = - wait_transaction_mined(source_client, &source_tx_hash).await?; - let source_block = source_client.block_by_hash(source_header_id.1.clone()).await; - let source_block = source_block.map_err(|err| { - Error::RetrievingBlock(source_header_id.1.clone(), P::SOURCE_NAME, anyhow!("{:?}", err)) - })?; - // wait for transaction and header on target node - wait_header_imported(target_client, &source_header_id).await?; - wait_header_finalized(target_client, &source_header_id).await?; - - // and finally - prepare and submit transaction proof to target node - let source_tx_id = format!("{}", source_tx_hash); - relay_ready_transaction_proof( - target_client, - &source_tx_id, - prepare_transaction_proof(source_client, &source_tx_id, &source_block, source_tx_index) - .await?, - ) - .await - .map_err(Into::into) -} - -/// Prepare transaction proof. -async fn prepare_transaction_proof( - source_client: &impl SourceClient

, - source_tx_id: &str, - source_block: &P::Block, - source_tx_index: usize, -) -> Result> { - source_client - .transaction_proof(source_block, source_tx_index) - .await - .map_err(|err| { - Error::BuildTransactionProof( - source_tx_id.to_owned(), - P::SOURCE_NAME, - anyhow!("{:?}", err), - err.is_connection_error(), - ) - }) -} - -/// Relay prepared proof of transaction. -async fn relay_ready_transaction_proof( - target_client: &impl TargetClient

, - source_tx_id: &str, - source_tx_proof: P::TransactionProof, -) -> Result<(), ErrorOf

> { - target_client.submit_transaction_proof(source_tx_proof).await.map_err(|err| { - Error::SubmitTransactionProof( - source_tx_id.to_owned(), - P::TARGET_NAME, - anyhow!("{:?}", err), - err.is_connection_error(), - ) - }) -} - -/// Wait until transaction is mined by source node. -async fn wait_transaction_mined( - source_client: &impl SourceClient

, - source_tx_hash: &TransactionHashOf

, -) -> Result<(HeaderId

, usize), ErrorOf

> { - loop { - let source_header_and_tx = - source_client.transaction_block(source_tx_hash).await.map_err(|err| { - Error::RetrievingTransaction( - source_tx_hash.clone(), - P::SOURCE_NAME, - anyhow!("{:?}", err), - ) - })?; - match source_header_and_tx { - Some((source_header_id, source_tx)) => { - log::info!( - target: "bridge", - "Transaction {} is retrieved from {} node. Continuing...", - source_tx_hash, - P::SOURCE_NAME, - ); - - return Ok((source_header_id, source_tx)) - }, - None => { - log::info!( - target: "bridge", - "Waiting for transaction {} to be mined by {} node...", - source_tx_hash, - P::SOURCE_NAME, - ); - - source_client.tick().await; - }, - } - } -} - -/// Wait until target node imports required header. -async fn wait_header_imported( - target_client: &impl TargetClient

, - source_header_id: &HeaderId

, -) -> Result<(), ErrorOf

> { - loop { - let is_header_known = - target_client.is_header_known(source_header_id).await.map_err(|err| { - Error::CheckHeaderExistence( - source_header_id.0, - source_header_id.1.clone(), - P::TARGET_NAME, - anyhow!("{:?}", err), - ) - })?; - match is_header_known { - true => { - log::info!( - target: "bridge", - "Header {}/{} is known to {} node. Continuing.", - source_header_id.0, - source_header_id.1, - P::TARGET_NAME, - ); - - return Ok(()) - }, - false => { - log::info!( - target: "bridge", - "Waiting for header {}/{} to be imported by {} node...", - source_header_id.0, - source_header_id.1, - P::TARGET_NAME, - ); - - target_client.tick().await; - }, - } - } -} - -/// Wait until target node finalizes required header. -async fn wait_header_finalized( - target_client: &impl TargetClient

, - source_header_id: &HeaderId

, -) -> Result<(), ErrorOf

> { - loop { - let is_header_finalized = - target_client.is_header_finalized(source_header_id).await.map_err(|err| { - Error::Finality( - source_header_id.0, - source_header_id.1.clone(), - P::TARGET_NAME, - anyhow!("{:?}", err), - ) - })?; - match is_header_finalized { - true => { - log::info!( - target: "bridge", - "Header {}/{} is finalizd by {} node. Continuing.", - source_header_id.0, - source_header_id.1, - P::TARGET_NAME, - ); - - return Ok(()) - }, - false => { - log::info!( - target: "bridge", - "Waiting for header {}/{} to be finalized by {} node...", - source_header_id.0, - source_header_id.1, - P::TARGET_NAME, - ); - - target_client.tick().await; - }, - } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - - use parking_lot::Mutex; - use relay_utils::HeaderId; - use std::{ - collections::{HashMap, HashSet}, - sync::Arc, - }; - - pub fn test_block_id() -> TestHeaderId { - HeaderId(1, 1) - } - - pub fn test_next_block_id() -> TestHeaderId { - HeaderId(2, 2) - } - - pub fn test_transaction_hash(tx_index: u64) -> TestTransactionHash { - 200 + tx_index - } - - pub fn test_transaction(tx_index: u64) -> TestTransaction { - TestTransaction(test_transaction_hash(tx_index)) - } - - pub fn test_block() -> TestBlock { - TestBlock(test_block_id(), vec![test_transaction(0)]) - } - - pub fn test_next_block() -> TestBlock { - TestBlock(test_next_block_id(), vec![test_transaction(1)]) - } - - pub type TestBlockNumber = u64; - pub type TestBlockHash = u64; - pub type TestTransactionHash = u64; - pub type TestHeaderId = HeaderId; - - #[derive(Debug, Clone, PartialEq)] - pub struct TestError(pub bool); - - impl MaybeConnectionError for TestError { - fn is_connection_error(&self) -> bool { - self.0 - } - } - - pub struct TestTransactionProofPipeline; - - impl TransactionProofPipeline for TestTransactionProofPipeline { - const SOURCE_NAME: &'static str = "TestSource"; - const TARGET_NAME: &'static str = "TestTarget"; - - type Block = TestBlock; - type TransactionProof = TestTransactionProof; - } - - #[derive(Debug, Clone)] - pub struct TestBlock(pub TestHeaderId, pub Vec); - - impl SourceBlock for TestBlock { - type Hash = TestBlockHash; - type Number = TestBlockNumber; - type Transaction = TestTransaction; - - fn id(&self) -> TestHeaderId { - self.0 - } - - fn transactions(&self) -> Vec { - self.1.clone() - } - } - - #[derive(Debug, Clone)] - pub struct TestTransaction(pub TestTransactionHash); - - impl SourceTransaction for TestTransaction { - type Hash = TestTransactionHash; - - fn hash(&self) -> Self::Hash { - self.0 - } - } - - #[derive(Debug, Clone, PartialEq)] - pub struct TestTransactionProof(pub TestTransactionHash); - - #[derive(Clone)] - pub struct TestTransactionsSource { - pub on_tick: Arc, - pub data: Arc>, - } - - pub struct TestTransactionsSourceData { - pub block: Result, - pub transaction_block: Result, TestError>, - pub proofs_to_fail: HashMap, - } - - impl TestTransactionsSource { - pub fn new(on_tick: Box) -> Self { - Self { - on_tick: Arc::new(on_tick), - data: Arc::new(Mutex::new(TestTransactionsSourceData { - block: Ok(test_block()), - transaction_block: Ok(Some((test_block_id(), 0))), - proofs_to_fail: HashMap::new(), - })), - } - } - } - - #[async_trait] - impl RelayClient for TestTransactionsSource { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - Ok(()) - } - } - - #[async_trait] - impl SourceClient for TestTransactionsSource { - async fn tick(&self) { - (self.on_tick)(&mut *self.data.lock()) - } - - async fn block_by_hash(&self, _: TestBlockHash) -> Result { - self.data.lock().block.clone() - } - - async fn block_by_number(&self, _: TestBlockNumber) -> Result { - self.data.lock().block.clone() - } - - async fn transaction_block( - &self, - _: &TestTransactionHash, - ) -> Result, TestError> { - self.data.lock().transaction_block.clone() - } - - async fn transaction_proof( - &self, - block: &TestBlock, - index: usize, - ) -> Result { - let tx_hash = block.1[index].hash(); - let proof_error = self.data.lock().proofs_to_fail.get(&tx_hash).cloned(); - if let Some(err) = proof_error { - return Err(err) - } - - Ok(TestTransactionProof(tx_hash)) - } - } - - #[derive(Clone)] - pub struct TestTransactionsTarget { - pub on_tick: Arc, - pub data: Arc>, - } - - pub struct TestTransactionsTargetData { - pub is_header_known: Result, - pub is_header_finalized: Result, - pub best_finalized_header_id: Result, - pub transactions_to_accept: HashSet, - pub submitted_proofs: Vec, - } - - impl TestTransactionsTarget { - pub fn new(on_tick: Box) -> Self { - Self { - on_tick: Arc::new(on_tick), - data: Arc::new(Mutex::new(TestTransactionsTargetData { - is_header_known: Ok(true), - is_header_finalized: Ok(true), - best_finalized_header_id: Ok(test_block_id()), - transactions_to_accept: vec![test_transaction_hash(0)].into_iter().collect(), - submitted_proofs: Vec::new(), - })), - } - } - } - - #[async_trait] - impl RelayClient for TestTransactionsTarget { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - Ok(()) - } - } - - #[async_trait] - impl TargetClient for TestTransactionsTarget { - async fn tick(&self) { - (self.on_tick)(&mut *self.data.lock()) - } - - async fn is_header_known(&self, _: &TestHeaderId) -> Result { - self.data.lock().is_header_known.clone() - } - - async fn is_header_finalized(&self, _: &TestHeaderId) -> Result { - self.data.lock().is_header_finalized.clone() - } - - async fn best_finalized_header_id(&self) -> Result { - self.data.lock().best_finalized_header_id.clone() - } - - async fn filter_transaction_proof( - &self, - proof: &TestTransactionProof, - ) -> Result { - Ok(self.data.lock().transactions_to_accept.contains(&proof.0)) - } - - async fn submit_transaction_proof( - &self, - proof: TestTransactionProof, - ) -> Result<(), TestError> { - self.data.lock().submitted_proofs.push(proof); - Ok(()) - } - } - - fn ensure_relay_single_success( - source: &TestTransactionsSource, - target: &TestTransactionsTarget, - ) { - assert!(async_std::task::block_on(relay_single_transaction_proof( - source, - target, - test_transaction_hash(0) - )) - .is_ok()); - assert_eq!( - target.data.lock().submitted_proofs, - vec![TestTransactionProof(test_transaction_hash(0))], - ); - } - - fn ensure_relay_single_failure(source: TestTransactionsSource, target: TestTransactionsTarget) { - assert!(async_std::task::block_on(relay_single_transaction_proof( - &source, - &target, - test_transaction_hash(0), - )) - .is_err()); - assert!(target.data.lock().submitted_proofs.is_empty()); - } - - #[test] - fn ready_transaction_proof_relayed_immediately() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - ensure_relay_single_success(&source, &target) - } - - #[test] - fn relay_transaction_proof_waits_for_transaction_to_be_mined() { - let source = TestTransactionsSource::new(Box::new(|source_data| { - assert_eq!(source_data.transaction_block, Ok(None)); - source_data.transaction_block = Ok(Some((test_block_id(), 0))); - })); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - // transaction is not yet mined, but will be available after first wait (tick) - source.data.lock().transaction_block = Ok(None); - - ensure_relay_single_success(&source, &target) - } - - #[test] - fn relay_transaction_fails_when_transaction_retrieval_fails() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - source.data.lock().transaction_block = Err(TestError(false)); - - ensure_relay_single_failure(source, target) - } - - #[test] - fn relay_transaction_fails_when_proof_retrieval_fails() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - source - .data - .lock() - .proofs_to_fail - .insert(test_transaction_hash(0), TestError(false)); - - ensure_relay_single_failure(source, target) - } - - #[test] - fn relay_transaction_proof_waits_for_header_to_be_imported() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|target_data| { - assert_eq!(target_data.is_header_known, Ok(false)); - target_data.is_header_known = Ok(true); - })); - - // header is not yet imported, but will be available after first wait (tick) - target.data.lock().is_header_known = Ok(false); - - ensure_relay_single_success(&source, &target) - } - - #[test] - fn relay_transaction_proof_fails_when_is_header_known_fails() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - target.data.lock().is_header_known = Err(TestError(false)); - - ensure_relay_single_failure(source, target) - } - - #[test] - fn relay_transaction_proof_waits_for_header_to_be_finalized() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|target_data| { - assert_eq!(target_data.is_header_finalized, Ok(false)); - target_data.is_header_finalized = Ok(true); - })); - - // header is not yet finalized, but will be available after first wait (tick) - target.data.lock().is_header_finalized = Ok(false); - - ensure_relay_single_success(&source, &target) - } - - #[test] - fn relay_transaction_proof_fails_when_is_header_finalized_fails() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - target.data.lock().is_header_finalized = Err(TestError(false)); - - ensure_relay_single_failure(source, target) - } - - #[test] - fn relay_transaction_proof_fails_when_target_node_rejects_proof() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - target.data.lock().transactions_to_accept.remove(&test_transaction_hash(0)); - - ensure_relay_single_success(&source, &target) - } - - fn test_relay_block_transactions( - source: &TestTransactionsSource, - target: &TestTransactionsTarget, - pre_relayed: RelayedBlockTransactions, - ) -> Result { - async_std::task::block_on(relay_block_transactions( - source, - target, - &TestBlock( - test_block_id(), - vec![test_transaction(0), test_transaction(1), test_transaction(2)], - ), - pre_relayed, - )) - .map_err(|(_, transactions)| transactions) - } - - #[test] - fn relay_block_transactions_process_all_transactions() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - // let's only accept tx#1 - target.data.lock().transactions_to_accept.remove(&test_transaction_hash(0)); - target.data.lock().transactions_to_accept.insert(test_transaction_hash(1)); - - let relayed_transactions = - test_relay_block_transactions(&source, &target, Default::default()); - assert_eq!( - relayed_transactions, - Ok(RelayedBlockTransactions { processed: 3, relayed: 1, failed: 0 }), - ); - assert_eq!( - target.data.lock().submitted_proofs, - vec![TestTransactionProof(test_transaction_hash(1))], - ); - } - - #[test] - fn relay_block_transactions_ignores_transaction_failure() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - // let's reject proof for tx#0 - source - .data - .lock() - .proofs_to_fail - .insert(test_transaction_hash(0), TestError(false)); - - let relayed_transactions = - test_relay_block_transactions(&source, &target, Default::default()); - assert_eq!( - relayed_transactions, - Ok(RelayedBlockTransactions { processed: 3, relayed: 0, failed: 1 }), - ); - assert_eq!(target.data.lock().submitted_proofs, vec![],); - } - - #[test] - fn relay_block_transactions_fails_on_connection_error() { - let source = TestTransactionsSource::new(Box::new(|_| unreachable!("no ticks allowed"))); - let target = TestTransactionsTarget::new(Box::new(|_| unreachable!("no ticks allowed"))); - - // fail with connection error when preparing proof for tx#1 - source - .data - .lock() - .proofs_to_fail - .insert(test_transaction_hash(1), TestError(true)); - - let relayed_transactions = - test_relay_block_transactions(&source, &target, Default::default()); - assert_eq!( - relayed_transactions, - Err(RelayedBlockTransactions { processed: 1, relayed: 1, failed: 0 }), - ); - assert_eq!( - target.data.lock().submitted_proofs, - vec![TestTransactionProof(test_transaction_hash(0))], - ); - - // now do not fail on tx#2 - source.data.lock().proofs_to_fail.clear(); - // and also relay tx#3 - target.data.lock().transactions_to_accept.insert(test_transaction_hash(2)); - - let relayed_transactions = - test_relay_block_transactions(&source, &target, relayed_transactions.unwrap_err()); - assert_eq!( - relayed_transactions, - Ok(RelayedBlockTransactions { processed: 3, relayed: 2, failed: 0 }), - ); - assert_eq!( - target.data.lock().submitted_proofs, - vec![ - TestTransactionProof(test_transaction_hash(0)), - TestTransactionProof(test_transaction_hash(2)) - ], - ); - } -} diff --git a/relays/exchange/src/exchange_loop.rs b/relays/exchange/src/exchange_loop.rs deleted file mode 100644 index 84d216f43968f..0000000000000 --- a/relays/exchange/src/exchange_loop.rs +++ /dev/null @@ -1,322 +0,0 @@ -// 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 . - -//! Relaying proofs of exchange transactions. - -use crate::{ - error::Error, - exchange::{ - relay_block_transactions, BlockNumberOf, RelayedBlockTransactions, SourceClient, - TargetClient, TransactionProofPipeline, - }, - exchange_loop_metrics::ExchangeLoopMetrics, -}; - -use crate::error::ErrorOf; -use backoff::backoff::Backoff; -use futures::{future::FutureExt, select}; -use num_traits::One; -use relay_utils::{ - metrics::{GlobalMetrics, MetricsParams}, - retry_backoff, FailedClient, MaybeConnectionError, -}; -use std::future::Future; - -/// Transactions proofs relay state. -#[derive(Debug)] -pub struct TransactionProofsRelayState { - /// Number of last header we have processed so far. - pub best_processed_header_number: BlockNumber, -} - -/// Transactions proofs relay storage. -pub trait TransactionProofsRelayStorage: 'static + Clone + Send + Sync { - /// Associated block number. - type BlockNumber: 'static + Send + Sync; - - /// Get relay state. - fn state(&self) -> TransactionProofsRelayState; - /// Update relay state. - fn set_state(&mut self, state: &TransactionProofsRelayState); -} - -/// In-memory storage for auto-relay loop. -#[derive(Debug, Clone)] -pub struct InMemoryStorage { - best_processed_header_number: BlockNumber, -} - -impl InMemoryStorage { - /// Created new in-memory storage with given best processed block number. - pub fn new(best_processed_header_number: BlockNumber) -> Self { - InMemoryStorage { best_processed_header_number } - } -} - -impl TransactionProofsRelayStorage - for InMemoryStorage -{ - type BlockNumber = BlockNumber; - - fn state(&self) -> TransactionProofsRelayState { - TransactionProofsRelayState { - best_processed_header_number: self.best_processed_header_number, - } - } - - fn set_state(&mut self, state: &TransactionProofsRelayState) { - self.best_processed_header_number = state.best_processed_header_number; - } -} - -/// Return prefix that will be used by default to expose Prometheus metrics of the exchange loop. -pub fn metrics_prefix() -> String { - format!("{}_to_{}_Exchange", P::SOURCE_NAME, P::TARGET_NAME) -} - -/// Run proofs synchronization. -pub async fn run( - storage: impl TransactionProofsRelayStorage>, - source_client: impl SourceClient

, - target_client: impl TargetClient

, - metrics_params: MetricsParams, - exit_signal: impl Future + 'static + Send, -) -> Result<(), ErrorOf

> { - let exit_signal = exit_signal.shared(); - - relay_utils::relay_loop(source_client, target_client) - .with_metrics(Some(metrics_prefix::

()), metrics_params) - .loop_metric(ExchangeLoopMetrics::new)? - .standalone_metric(GlobalMetrics::new)? - .expose() - .await? - .run(metrics_prefix::

(), move |source_client, target_client, metrics| { - run_until_connection_lost( - storage.clone(), - source_client, - target_client, - metrics, - exit_signal.clone(), - ) - }) - .await - .map_err(Error::Utils) -} - -/// Run proofs synchronization. -async fn run_until_connection_lost( - mut storage: impl TransactionProofsRelayStorage>, - source_client: impl SourceClient

, - target_client: impl TargetClient

, - metrics_exch: Option, - exit_signal: impl Future + Send, -) -> Result<(), FailedClient> { - let mut retry_backoff = retry_backoff(); - let mut state = storage.state(); - let mut current_finalized_block = None; - - let exit_signal = exit_signal.fuse(); - - futures::pin_mut!(exit_signal); - - loop { - let iteration_result = run_loop_iteration( - &mut storage, - &source_client, - &target_client, - &mut state, - &mut current_finalized_block, - metrics_exch.as_ref(), - ) - .await; - - if let Err((is_connection_error, failed_client)) = iteration_result { - if is_connection_error { - return Err(failed_client) - } - - let retry_timeout = - retry_backoff.next_backoff().unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY); - select! { - _ = async_std::task::sleep(retry_timeout).fuse() => {}, - _ = exit_signal => return Ok(()), - } - } else { - retry_backoff.reset(); - - select! { - _ = source_client.tick().fuse() => {}, - _ = exit_signal => return Ok(()), - } - } - } -} - -/// Run exchange loop until we need to break. -async fn run_loop_iteration( - storage: &mut impl TransactionProofsRelayStorage>, - source_client: &impl SourceClient

, - target_client: &impl TargetClient

, - state: &mut TransactionProofsRelayState>, - current_finalized_block: &mut Option<(P::Block, RelayedBlockTransactions)>, - exchange_loop_metrics: Option<&ExchangeLoopMetrics>, -) -> Result<(), (bool, FailedClient)> { - let best_finalized_header_id = match target_client.best_finalized_header_id().await { - Ok(best_finalized_header_id) => { - log::debug!( - target: "bridge", - "Got best finalized {} block from {} node: {:?}", - P::SOURCE_NAME, - P::TARGET_NAME, - best_finalized_header_id, - ); - - best_finalized_header_id - }, - Err(err) => { - log::error!( - target: "bridge", - "Failed to retrieve best {} header id from {} node: {:?}. Going to retry...", - P::SOURCE_NAME, - P::TARGET_NAME, - err, - ); - - return Err((err.is_connection_error(), FailedClient::Target)) - }, - }; - - loop { - // if we already have some finalized block body, try to relay its transactions - if let Some((block, relayed_transactions)) = current_finalized_block.take() { - let result = relay_block_transactions( - source_client, - target_client, - &block, - relayed_transactions, - ) - .await; - - match result { - Ok(relayed_transactions) => { - log::info!( - target: "bridge", - "Relay has processed {} block #{}. Total/Relayed/Failed transactions: {}/{}/{}", - P::SOURCE_NAME, - state.best_processed_header_number, - relayed_transactions.processed, - relayed_transactions.relayed, - relayed_transactions.failed, - ); - - state.best_processed_header_number = - state.best_processed_header_number + One::one(); - storage.set_state(state); - - if let Some(exchange_loop_metrics) = exchange_loop_metrics { - exchange_loop_metrics.update::

( - state.best_processed_header_number, - best_finalized_header_id.0, - relayed_transactions, - ); - } - - // we have just updated state => proceed to next block retrieval - }, - Err((failed_client, relayed_transactions)) => { - *current_finalized_block = Some((block, relayed_transactions)); - return Err((true, failed_client)) - }, - } - } - - // we may need to retrieve finalized block body from source node - if best_finalized_header_id.0 > state.best_processed_header_number { - let next_block_number = state.best_processed_header_number + One::one(); - let result = source_client.block_by_number(next_block_number).await; - - match result { - Ok(block) => { - *current_finalized_block = Some((block, RelayedBlockTransactions::default())); - - // we have received new finalized block => go back to relay its transactions - continue - }, - Err(err) => { - log::error!( - target: "bridge", - "Failed to retrieve canonical block #{} from {} node: {:?}. Going to retry...", - next_block_number, - P::SOURCE_NAME, - err, - ); - - return Err((err.is_connection_error(), FailedClient::Source)) - }, - } - } - - // there are no any transactions we need to relay => wait for new data - return Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::exchange::tests::{ - test_next_block, test_next_block_id, test_transaction_hash, TestTransactionProof, - TestTransactionsSource, TestTransactionsTarget, - }; - use futures::{future::FutureExt, stream::StreamExt}; - - #[test] - fn exchange_loop_is_able_to_relay_proofs() { - let storage = InMemoryStorage { best_processed_header_number: 0 }; - let target = - TestTransactionsTarget::new(Box::new(|_| unreachable!("no target ticks allowed"))); - let target_data = target.data.clone(); - let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); - - let source = TestTransactionsSource::new(Box::new(move |data| { - let transaction1_relayed = target_data - .lock() - .submitted_proofs - .contains(&TestTransactionProof(test_transaction_hash(0))); - let transaction2_relayed = target_data - .lock() - .submitted_proofs - .contains(&TestTransactionProof(test_transaction_hash(1))); - match (transaction1_relayed, transaction2_relayed) { - (true, true) => exit_sender.unbounded_send(()).unwrap(), - (true, false) => { - data.block = Ok(test_next_block()); - target_data.lock().best_finalized_header_id = Ok(test_next_block_id()); - target_data.lock().transactions_to_accept.insert(test_transaction_hash(1)); - }, - _ => (), - } - })); - - let _ = async_std::task::block_on(run( - storage, - source, - target, - MetricsParams::disabled(), - exit_receiver.into_future().map(|(_, _)| ()), - )); - } -} diff --git a/relays/exchange/src/exchange_loop_metrics.rs b/relays/exchange/src/exchange_loop_metrics.rs deleted file mode 100644 index 82d3e649d4319..0000000000000 --- a/relays/exchange/src/exchange_loop_metrics.rs +++ /dev/null @@ -1,97 +0,0 @@ -// 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 . - -//! Metrics for currency-exchange relay loop. - -use crate::exchange::{BlockNumberOf, RelayedBlockTransactions, TransactionProofPipeline}; -use relay_utils::metrics::{ - metric_name, register, Counter, CounterVec, GaugeVec, Opts, PrometheusError, Registry, U64, -}; - -/// Exchange transactions relay metrics. -#[derive(Clone)] -pub struct ExchangeLoopMetrics { - /// Best finalized block numbers - "processed" and "known". - best_block_numbers: GaugeVec, - /// Number of processed blocks ("total"). - processed_blocks: Counter, - /// Number of processed transactions ("total", "relayed" and "failed"). - processed_transactions: CounterVec, -} - -impl ExchangeLoopMetrics { - /// Create and register exchange loop metrics. - pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { - Ok(ExchangeLoopMetrics { - best_block_numbers: register( - GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best finalized block numbers", - ), - &["type"], - )?, - registry, - )?, - processed_blocks: register( - Counter::new( - metric_name(prefix, "processed_blocks"), - "Total number of processed blocks", - )?, - registry, - )?, - processed_transactions: register( - CounterVec::new( - Opts::new( - metric_name(prefix, "processed_transactions"), - "Total number of processed transactions", - ), - &["type"], - )?, - registry, - )?, - }) - } -} - -impl ExchangeLoopMetrics { - /// Update metrics when single block is relayed. - pub fn update( - &self, - best_processed_block_number: BlockNumberOf

, - best_known_block_number: BlockNumberOf

, - relayed_transactions: RelayedBlockTransactions, - ) { - self.best_block_numbers - .with_label_values(&["processed"]) - .set(best_processed_block_number.into()); - self.best_block_numbers - .with_label_values(&["known"]) - .set(best_known_block_number.into()); - - self.processed_blocks.inc(); - - self.processed_transactions - .with_label_values(&["total"]) - .inc_by(relayed_transactions.processed as _); - self.processed_transactions - .with_label_values(&["relayed"]) - .inc_by(relayed_transactions.relayed as _); - self.processed_transactions - .with_label_values(&["failed"]) - .inc_by(relayed_transactions.failed as _); - } -} diff --git a/relays/exchange/src/lib.rs b/relays/exchange/src/lib.rs deleted file mode 100644 index d167e5aa398ee..0000000000000 --- a/relays/exchange/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -// 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 . - -//! Relaying [`currency-exchange`](../pallet_bridge_currency_exchange/index.html) application -//! specific data. Currency exchange application allows exchanging tokens between bridged chains. -//! This module provides entrypoints for crafting and submitting (single and multiple) -//! proof-of-exchange-at-source-chain transaction(s) to target chain. - -#![warn(missing_docs)] - -pub mod error; -pub mod exchange; -pub mod exchange_loop; -pub mod exchange_loop_metrics; From 4551e80c727a94fa3e841cdc9da4007ee61e167f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 22 Nov 2021 15:38:42 +0300 Subject: [PATCH 0603/1210] Unify metric names (#1209) * unify metric names * refactor standalone metrics * headers sync metrics * post-merge fix * fix compilation * fmt * fix dashboards * fix local dashboards * update Rococo/Wococo runtime version * remove commented code * fixed grumbles * fmt * fixed widget names --- primitives/chain-rococo/src/lib.rs | 2 +- relays/bin-substrate/src/chains/kusama.rs | 13 + .../src/chains/kusama_headers_to_polkadot.rs | 5 +- .../src/chains/kusama_messages_to_polkadot.rs | 50 ++-- relays/bin-substrate/src/chains/millau.rs | 17 ++ .../src/chains/millau_messages_to_rialto.rs | 47 ++-- relays/bin-substrate/src/chains/mod.rs | 27 +- relays/bin-substrate/src/chains/polkadot.rs | 13 + .../src/chains/polkadot_headers_to_kusama.rs | 5 +- .../src/chains/polkadot_messages_to_kusama.rs | 50 ++-- relays/bin-substrate/src/chains/rialto.rs | 17 ++ .../src/chains/rialto_messages_to_millau.rs | 47 ++-- .../src/chains/rococo_headers_to_wococo.rs | 5 +- .../src/chains/rococo_messages_to_wococo.rs | 36 ++- .../src/chains/westend_headers_to_millau.rs | 5 +- .../src/chains/wococo_headers_to_rococo.rs | 5 +- .../src/chains/wococo_messages_to_rococo.rs | 36 ++- relays/bin-substrate/src/cli/relay_headers.rs | 3 + .../src/cli/relay_headers_and_messages.rs | 102 ++++---- .../bin-substrate/src/cli/relay_messages.rs | 1 + .../src/metrics/float_storage_value.rs | 18 +- .../src/metrics/storage_proof_overhead.rs | 20 +- relays/finality/src/finality_loop.rs | 10 +- relays/finality/src/sync_loop_metrics.rs | 30 ++- relays/lib-substrate-relay/src/helpers.rs | 10 +- .../lib-substrate-relay/src/messages_lane.rs | 238 +++++++++++------- .../src/messages_target.rs | 4 +- relays/messages/src/message_lane_loop.rs | 10 +- relays/messages/src/metrics.rs | 40 +-- relays/utils/src/metrics.rs | 38 +-- relays/utils/src/metrics/float_json_value.rs | 16 +- relays/utils/src/metrics/global.rs | 44 ++-- relays/utils/src/relay_loop.rs | 60 +---- 33 files changed, 509 insertions(+), 515 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index d6d97fdc5f4ef..b3bbc91976dac 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -44,7 +44,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), authoring_version: 0, - spec_version: 9004, + spec_version: 9100, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 9e5351672dada..b12d23f2a56dc 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -17,6 +17,8 @@ use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; +use sp_core::storage::StorageKey; +use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ @@ -101,3 +103,14 @@ impl CliChain for Kusama { anyhow::bail!("Sending messages from Kusama is not yet supported.") } } + +/// Storage key and initial value of Polkadot -> Kusama conversion rate. +pub(crate) fn polkadot_to_kusama_conversion_rate_params() -> (StorageKey, FixedU128) { + ( + bp_runtime::storage_parameter_key( + bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME, + ), + // starting relay before this parameter will be set to some value may cause troubles + FixedU128::from_inner(FixedU128::DIV), + ) +} diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index ea362bd202b1d..ce631ef41e0ac 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -64,10 +64,7 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { type TargetChain = Polkadot; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::( - Some(finality_relay::metrics_prefix::()), - params, - ) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn start_relay_guards(&self) { diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 9c9dee150dc46..32133adc3e54b 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -21,7 +21,6 @@ use std::ops::RangeInclusive; use codec::Encode; use frame_support::weights::Weight; use sp_core::{Bytes, Pair}; -use sp_runtime::{FixedPointNumber, FixedU128}; use bp_messages::MessageNonce; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; @@ -33,7 +32,6 @@ use relay_polkadot_client::{ HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, }; use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; use substrate_relay_helper::{ messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, @@ -196,12 +194,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; + let target_client = params.target_client; let lane = KusamaMessagesToPolkadot { message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, source_transactions_mortality: params.source_transactions_mortality, - target_client: params.target_client.clone(), + target_client: target_client.clone(), target_sign: params.target_sign, target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_kusama, @@ -240,13 +239,10 @@ pub async fn run( stall_timeout, ); - let (metrics_params, metrics_values) = add_standalone_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane_id)), - params.metrics_params, - source_client.clone(), - )?; + let standalone_metrics = params + .standalone_metrics + .map(Ok) + .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -272,41 +268,31 @@ pub async fn run( params.target_to_source_headers_relay, ), PolkadotTargetClient::new( - params.target_client, + target_client, lane, lane_id, - metrics_values, + standalone_metrics.clone(), params.source_to_target_headers_relay, ), - metrics_params, + standalone_metrics.register_and_spawn(params.metrics_params)?, futures::future::pending(), ) .await .map_err(Into::into) } -/// Add standalone metrics for the Kusama -> Polkadot messages loop. -pub(crate) fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, +/// Create standalone metrics for the Kusama -> Polkadot messages loop. +pub(crate) fn standalone_metrics( source_client: Client, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - let polkadot_to_kusama_conversion_rate_key = bp_runtime::storage_parameter_key( - bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME, - ) - .0; - - substrate_relay_helper::messages_lane::add_standalone_metrics::( - metrics_prefix, - metrics_params, + target_client: Client, +) -> anyhow::Result> { + substrate_relay_helper::messages_lane::standalone_metrics( source_client, - Some(crate::chains::polkadot::TOKEN_ID), + target_client, Some(crate::chains::kusama::TOKEN_ID), - Some(( - sp_core::storage::StorageKey(polkadot_to_kusama_conversion_rate_key), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - )), + Some(crate::chains::polkadot::TOKEN_ID), + Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), + Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), ) } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 1dbeab9a90498..755d7cc4430a4 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -28,8 +28,17 @@ use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use relay_millau_client::Millau; +use sp_core::storage::StorageKey; +use sp_runtime::FixedU128; use sp_version::RuntimeVersion; +// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we +// want to test our code that is intended to work with real-value chains. So to keep it close to +// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). + +/// The identifier of token, which value is associated with Millau token value by relayer. +pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::kusama::TOKEN_ID; + impl CliEncodeCall for Millau { fn max_extrinsic_size() -> u32 { bp_millau::max_extrinsic_size() @@ -123,3 +132,11 @@ impl CliChain for Millau { } } } + +/// Storage key and initial value of Rialto -> Millau conversion rate. +pub(crate) fn rialto_to_millau_conversion_rate_params() -> (StorageKey, FixedU128) { + ( + StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), + millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, + ) +} diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 3661eb78c19f9..c4179eea330f1 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -33,7 +33,6 @@ use relay_rialto_client::{ HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, }; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; use substrate_relay_helper::{ messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, @@ -193,12 +192,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; + let target_client = params.target_client; let lane = MillauMessagesToRialto { message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, source_transactions_mortality: params.source_transactions_mortality, - target_client: params.target_client.clone(), + target_client: target_client.clone(), target_sign: params.target_sign, target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_millau, @@ -234,13 +234,10 @@ pub async fn run( stall_timeout, ); - let (metrics_params, metrics_values) = add_standalone_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane_id)), - params.metrics_params, - source_client.clone(), - )?; + let standalone_metrics = params + .standalone_metrics + .map(Ok) + .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -266,37 +263,31 @@ pub async fn run( params.target_to_source_headers_relay, ), RialtoTargetClient::new( - params.target_client, + target_client, lane, lane_id, - metrics_values, + standalone_metrics.clone(), params.source_to_target_headers_relay, ), - metrics_params, + standalone_metrics.register_and_spawn(params.metrics_params)?, futures::future::pending(), ) .await .map_err(Into::into) } -/// Add standalone metrics for the Millau -> Rialto messages loop. -pub(crate) fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, +/// Create standalone metrics for the Millau -> Rialto messages loop. +pub(crate) fn standalone_metrics( source_client: Client, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - substrate_relay_helper::messages_lane::add_standalone_metrics::( - metrics_prefix, - metrics_params, + target_client: Client, +) -> anyhow::Result> { + substrate_relay_helper::messages_lane::standalone_metrics( source_client, - Some(crate::chains::MILLAU_ASSOCIATED_TOKEN_ID), - Some(crate::chains::RIALTO_ASSOCIATED_TOKEN_ID), - Some(( - sp_core::storage::StorageKey( - millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec(), - ), - millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, - )), + target_client, + Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), + Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), + Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), + Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), ) } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index a96d46d9ecc8d..e9cb2d9b737f1 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -39,31 +39,16 @@ mod rococo; mod westend; mod wococo; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Rialto token value by relayer. -pub(crate) const RIALTO_ASSOCIATED_TOKEN_ID: &str = polkadot::TOKEN_ID; -/// The identifier of token, which value is associated with Millau token value by relayer. -pub(crate) const MILLAU_ASSOCIATED_TOKEN_ID: &str = kusama::TOKEN_ID; - -use relay_utils::metrics::MetricsParams; +use relay_utils::metrics::{MetricsParams, StandaloneMetric}; pub(crate) fn add_polkadot_kusama_price_metrics( - prefix: Option, params: MetricsParams, ) -> anyhow::Result { - // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> - // Kusama relays, but we want to test metrics/dashboards in advance - Ok(relay_utils::relay_metrics(prefix, params) - .standalone_metric(|registry, prefix| { - substrate_relay_helper::helpers::token_price_metric(registry, prefix, "polkadot") - })? - .standalone_metric(|registry, prefix| { - substrate_relay_helper::helpers::token_price_metric(registry, prefix, "kusama") - })? - .into_params()) + substrate_relay_helper::helpers::token_price_metric(polkadot::TOKEN_ID)? + .register_and_spawn(¶ms.registry)?; + substrate_relay_helper::helpers::token_price_metric(kusama::TOKEN_ID)? + .register_and_spawn(¶ms.registry)?; + Ok(params) } #[cfg(test)] diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 55d17e46f13bb..7b6256d1749f8 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -17,6 +17,8 @@ use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; +use sp_core::storage::StorageKey; +use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ @@ -101,3 +103,14 @@ impl CliChain for Polkadot { anyhow::bail!("Sending messages from Polkadot is not yet supported.") } } + +/// Storage key and initial value of Kusama -> Polkadot conversion rate. +pub(crate) fn kusama_to_polkadot_conversion_rate_params() -> (StorageKey, FixedU128) { + ( + bp_runtime::storage_parameter_key( + bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME, + ), + // starting relay before this parameter will be set to some value may cause troubles + FixedU128::from_inner(FixedU128::DIV), + ) +} diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index 603d5ba3aa779..b1948b234cc31 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -64,10 +64,7 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { type TargetChain = Kusama; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::( - Some(finality_relay::metrics_prefix::()), - params, - ) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn start_relay_guards(&self) { diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index b1595665fb255..bc7f222430922 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -32,8 +32,6 @@ use relay_polkadot_client::{ HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, }; use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use sp_runtime::{FixedPointNumber, FixedU128}; use substrate_relay_helper::{ messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, @@ -195,12 +193,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; + let target_client = params.target_client; let lane = PolkadotMessagesToKusama { message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, source_transactions_mortality: params.source_transactions_mortality, - target_client: params.target_client.clone(), + target_client: target_client.clone(), target_sign: params.target_sign, target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_polkadot, @@ -239,13 +238,10 @@ pub async fn run( stall_timeout, ); - let (metrics_params, metrics_values) = add_standalone_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane_id)), - params.metrics_params, - source_client.clone(), - )?; + let standalone_metrics = params + .standalone_metrics + .map(Ok) + .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -271,41 +267,31 @@ pub async fn run( params.target_to_source_headers_relay, ), KusamaTargetClient::new( - params.target_client, + target_client, lane, lane_id, - metrics_values, + standalone_metrics.clone(), params.source_to_target_headers_relay, ), - metrics_params, + standalone_metrics.register_and_spawn(params.metrics_params)?, futures::future::pending(), ) .await .map_err(Into::into) } -/// Add standalone metrics for the Polkadot -> Kusama messages loop. -pub(crate) fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, +/// Create standalone metrics for the Polkadot -> Kusama messages loop. +pub(crate) fn standalone_metrics( source_client: Client, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - let kusama_to_polkadot_conversion_rate_key = bp_runtime::storage_parameter_key( - bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME, - ) - .0; - - substrate_relay_helper::messages_lane::add_standalone_metrics::( - metrics_prefix, - metrics_params, + target_client: Client, +) -> anyhow::Result> { + substrate_relay_helper::messages_lane::standalone_metrics( source_client, - Some(crate::chains::kusama::TOKEN_ID), + target_client, Some(crate::chains::polkadot::TOKEN_ID), - Some(( - sp_core::storage::StorageKey(kusama_to_polkadot_conversion_rate_key), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - )), + Some(crate::chains::kusama::TOKEN_ID), + Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), + Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), ) } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 4c1a0166ed3b2..2d873a24ba7af 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -28,8 +28,17 @@ use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; use relay_rialto_client::Rialto; +use sp_core::storage::StorageKey; +use sp_runtime::FixedU128; use sp_version::RuntimeVersion; +// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we +// want to test our code that is intended to work with real-value chains. So to keep it close to +// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). + +/// The identifier of token, which value is associated with Rialto token value by relayer. +pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::polkadot::TOKEN_ID; + impl CliEncodeCall for Rialto { fn max_extrinsic_size() -> u32 { bp_rialto::max_extrinsic_size() @@ -122,3 +131,11 @@ impl CliChain for Rialto { } } } + +/// Storage key and initial value of Millau -> Rialto conversion rate. +pub(crate) fn millau_to_rialto_conversion_rate_params() -> (StorageKey, FixedU128) { + ( + StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), + rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, + ) +} diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 50ebf264e1a49..774da017df0c1 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -33,7 +33,6 @@ use relay_rialto_client::{ HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, }; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; use substrate_relay_helper::{ messages_lane::{ select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, @@ -193,12 +192,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; + let target_client = params.target_client; let lane = RialtoMessagesToMillau { message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, source_transactions_mortality: params.source_transactions_mortality, - target_client: params.target_client.clone(), + target_client: target_client.clone(), target_sign: params.target_sign, target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_rialto, @@ -233,13 +233,10 @@ pub async fn run( stall_timeout, ); - let (metrics_params, metrics_values) = add_standalone_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane_id)), - params.metrics_params, - source_client.clone(), - )?; + let standalone_metrics = params + .standalone_metrics + .map(Ok) + .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -265,37 +262,31 @@ pub async fn run( params.target_to_source_headers_relay, ), MillauTargetClient::new( - params.target_client, + target_client, lane, lane_id, - metrics_values, + standalone_metrics.clone(), params.source_to_target_headers_relay, ), - metrics_params, + standalone_metrics.register_and_spawn(params.metrics_params)?, futures::future::pending(), ) .await .map_err(Into::into) } -/// Add standalone metrics for the Rialto -> Millau messages loop. -pub(crate) fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, +/// Create standalone metrics for the Rialto -> Millau messages loop. +pub(crate) fn standalone_metrics( source_client: Client, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - substrate_relay_helper::messages_lane::add_standalone_metrics::( - metrics_prefix, - metrics_params, + target_client: Client, +) -> anyhow::Result> { + substrate_relay_helper::messages_lane::standalone_metrics( source_client, - Some(crate::chains::RIALTO_ASSOCIATED_TOKEN_ID), - Some(crate::chains::MILLAU_ASSOCIATED_TOKEN_ID), - Some(( - sp_core::storage::StorageKey( - rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec(), - ), - rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, - )), + target_client, + Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), + Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), + Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), + Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), ) } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 25fd97a90bab9..ec98cec1ec1e9 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -59,10 +59,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { type TargetChain = Wococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::( - Some(finality_relay::metrics_prefix::()), - params, - ) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn start_relay_guards(&self) { diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 523d8c4908597..d6c9040e1277b 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -29,7 +29,6 @@ use relay_rococo_client::{ HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, }; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; use relay_wococo_client::{ HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, }; @@ -193,12 +192,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; + let target_client = params.target_client; let lane = RococoMessagesToWococo { message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, source_transactions_mortality: params.source_transactions_mortality, - target_client: params.target_client.clone(), + target_client: target_client.clone(), target_sign: params.target_sign, target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_rococo, @@ -237,13 +237,10 @@ pub async fn run( stall_timeout, ); - let (metrics_params, metrics_values) = add_standalone_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane_id)), - params.metrics_params, - source_client.clone(), - )?; + let standalone_metrics = params + .standalone_metrics + .map(Ok) + .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -269,29 +266,28 @@ pub async fn run( params.target_to_source_headers_relay, ), WococoTargetClient::new( - params.target_client, + target_client, lane, lane_id, - metrics_values, + standalone_metrics.clone(), params.source_to_target_headers_relay, ), - metrics_params, + standalone_metrics.register_and_spawn(params.metrics_params)?, futures::future::pending(), ) .await .map_err(Into::into) } -/// Add standalone metrics for the Rococo -> Wococo messages loop. -pub(crate) fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, +/// Create standalone metrics for the Rococo -> Wococo messages loop. +pub(crate) fn standalone_metrics( source_client: Client, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - substrate_relay_helper::messages_lane::add_standalone_metrics::( - metrics_prefix, - metrics_params, + target_client: Client, +) -> anyhow::Result> { + substrate_relay_helper::messages_lane::standalone_metrics( source_client, + target_client, + None, None, None, None, diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 64d8ba4d889d7..211aa9da9bfe3 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -57,10 +57,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type TargetChain = Millau; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::( - Some(finality_relay::metrics_prefix::()), - params, - ) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn transactions_author(&self) -> bp_millau::AccountId { diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 8e11698c1bb66..fe17976d06a86 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -64,10 +64,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { type TargetChain = Rococo; fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::( - Some(finality_relay::metrics_prefix::()), - params, - ) + crate::chains::add_polkadot_kusama_price_metrics::(params) } fn start_relay_guards(&self) { diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 893aeb607ab70..dcba89e43f05c 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -29,7 +29,6 @@ use relay_rococo_client::{ HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, }; use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; use relay_wococo_client::{ HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, }; @@ -192,12 +191,13 @@ pub async fn run( let lane_id = params.lane_id; let source_client = params.source_client; + let target_client = params.target_client; let lane = WococoMessagesToRococo { message_lane: SubstrateMessageLaneToSubstrate { source_client: source_client.clone(), source_sign: params.source_sign, source_transactions_mortality: params.source_transactions_mortality, - target_client: params.target_client.clone(), + target_client: target_client.clone(), target_sign: params.target_sign, target_transactions_mortality: params.target_transactions_mortality, relayer_id_at_source: relayer_id_at_wococo, @@ -236,13 +236,10 @@ pub async fn run( stall_timeout, ); - let (metrics_params, metrics_values) = add_standalone_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane_id)), - params.metrics_params, - source_client.clone(), - )?; + let standalone_metrics = params + .standalone_metrics + .map(Ok) + .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -268,29 +265,28 @@ pub async fn run( params.target_to_source_headers_relay, ), RococoTargetClient::new( - params.target_client, + target_client, lane, lane_id, - metrics_values, + standalone_metrics.clone(), params.source_to_target_headers_relay, ), - metrics_params, + standalone_metrics.register_and_spawn(params.metrics_params)?, futures::future::pending(), ) .await .map_err(Into::into) } -/// Add standalone metrics for the Wococo -> Rococo messages loop. -pub(crate) fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, +/// Create standalone metrics for the Wococo -> Rococo messages loop. +pub(crate) fn standalone_metrics( source_client: Client, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - substrate_relay_helper::messages_lane::add_standalone_metrics::( - metrics_prefix, - metrics_params, + target_client: Client, +) -> anyhow::Result> { + substrate_relay_helper::messages_lane::standalone_metrics( source_client, + target_client, + None, None, None, None, diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index e90c663bb33a0..82c55965a991a 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -17,6 +17,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality_pipeline::SubstrateFinalitySyncPipeline; use crate::cli::{ @@ -121,6 +122,8 @@ impl RelayHeaders { let target_transactions_mortality = self.target_sign.target_transactions_mortality; let target_sign = self.target_sign.to_keypair::()?; let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + let finality = Finality::new(target_client.clone(), target_sign); finality.start_relay_guards(); diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 076331112a21f..9d76a0296fb2c 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -34,8 +34,7 @@ use relay_substrate_client::{ use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ - messages_lane::{MessagesRelayParams, SubstrateMessageLane}, - on_demand_headers::OnDemandHeadersRelay, + messages_lane::MessagesRelayParams, on_demand_headers::OnDemandHeadersRelay, }; use crate::{ @@ -129,11 +128,6 @@ macro_rules! select_bridge { type RightToLeftFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; - type LeftToRightMessages = - crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; - type RightToLeftMessages = - crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; - type LeftAccountIdConverter = bp_millau::AccountIdConverter; type RightAccountIdConverter = bp_rialto::AccountIdConverter; @@ -144,12 +138,11 @@ macro_rules! select_bridge { use crate::chains::{ millau_messages_to_rialto::{ - add_standalone_metrics as add_left_to_right_standalone_metrics, + standalone_metrics as left_to_right_standalone_metrics, run as left_to_right_messages, update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, }, rialto_messages_to_millau::{ - add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, }, @@ -184,11 +177,6 @@ macro_rules! select_bridge { type RightToLeftFinality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; - type LeftToRightMessages = - crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo; - type RightToLeftMessages = - crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo; - type LeftAccountIdConverter = bp_rococo::AccountIdConverter; type RightAccountIdConverter = bp_wococo::AccountIdConverter; @@ -199,11 +187,10 @@ macro_rules! select_bridge { use crate::chains::{ rococo_messages_to_wococo::{ - add_standalone_metrics as add_left_to_right_standalone_metrics, + standalone_metrics as left_to_right_standalone_metrics, run as left_to_right_messages, }, wococo_messages_to_rococo::{ - add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, }, }; @@ -253,11 +240,6 @@ macro_rules! select_bridge { type RightToLeftFinality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; - type LeftToRightMessages = - crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot; - type RightToLeftMessages = - crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama; - type LeftAccountIdConverter = bp_kusama::AccountIdConverter; type RightAccountIdConverter = bp_polkadot::AccountIdConverter; @@ -268,12 +250,11 @@ macro_rules! select_bridge { use crate::chains::{ kusama_messages_to_polkadot::{ - add_standalone_metrics as add_left_to_right_standalone_metrics, + standalone_metrics as left_to_right_standalone_metrics, run as left_to_right_messages, update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, }, polkadot_messages_to_kusama::{ - add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, }, @@ -378,31 +359,39 @@ impl RelayHeadersAndMessages { let relayer_mode = params.shared.relayer_mode.into(); let relay_strategy = MixStrategy::new(relayer_mode); - const METRIC_IS_SOME_PROOF: &str = - "it is `None` when metric has been already registered; \ - this is the command entrypoint, so nothing has been registered yet; \ - qed"; - + // create metrics registry and register standalone metrics let metrics_params: MetricsParams = params.shared.prometheus_params.into(); - let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); - let (metrics_params, left_to_right_metrics) = - add_left_to_right_standalone_metrics(None, metrics_params, left_client.clone())?; - let (metrics_params, right_to_left_metrics) = - add_right_to_left_standalone_metrics(None, metrics_params, right_client.clone())?; + let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); + let left_to_right_metrics = + left_to_right_standalone_metrics(left_client.clone(), right_client.clone())?; + let right_to_left_metrics = left_to_right_metrics.clone().reverse(); + + // start conversion rate update loops for left/right chains if let Some(left_messages_pallet_owner) = left_messages_pallet_owner { let left_client = left_client.clone(); + let format_err = || { + anyhow::format_err!( + "Cannon run conversion rate updater: {} -> {}", + Right::NAME, + Left::NAME + ) + }; substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( left_to_right_metrics .target_to_source_conversion_rate - .expect(METRIC_IS_SOME_PROOF), + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), left_to_right_metrics .target_to_base_conversion_rate - .clone() - .expect(METRIC_IS_SOME_PROOF), + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), left_to_right_metrics .source_to_base_conversion_rate - .clone() - .expect(METRIC_IS_SOME_PROOF), + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, move |new_rate| { log::info!( @@ -423,16 +412,29 @@ impl RelayHeadersAndMessages { } if let Some(right_messages_pallet_owner) = right_messages_pallet_owner { let right_client = right_client.clone(); + let format_err = || { + anyhow::format_err!( + "Cannon run conversion rate updater: {} -> {}", + Left::NAME, + Right::NAME + ) + }; substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( right_to_left_metrics .target_to_source_conversion_rate - .expect(METRIC_IS_SOME_PROOF), + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), left_to_right_metrics .source_to_base_conversion_rate - .expect(METRIC_IS_SOME_PROOF), + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), left_to_right_metrics .target_to_base_conversion_rate - .expect(METRIC_IS_SOME_PROOF), + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, move |new_rate| { log::info!( @@ -452,6 +454,7 @@ impl RelayHeadersAndMessages { ); } + // optionally, create relayers fund account if params.shared.create_relayers_fund_accounts { let relayer_fund_acount_id = pallet_bridge_messages::relayer_fund_account_id::< AccountIdOf, @@ -490,6 +493,7 @@ impl RelayHeadersAndMessages { } } + // start on-demand header relays let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), right_client.clone(), @@ -521,11 +525,8 @@ impl RelayHeadersAndMessages { source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, - metrics_params: metrics_params.clone().disable().metrics_prefix( - messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane), - ), + metrics_params: metrics_params.clone().disable(), + standalone_metrics: Some(left_to_right_metrics.clone()), relay_strategy: relay_strategy.clone(), }) .map_err(|e| anyhow::format_err!("{}", e)) @@ -540,11 +541,8 @@ impl RelayHeadersAndMessages { source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, - metrics_params: metrics_params.clone().disable().metrics_prefix( - messages_relay::message_lane_loop::metrics_prefix::< - ::MessageLane, - >(&lane), - ), + metrics_params: metrics_params.clone().disable(), + standalone_metrics: Some(right_to_left_metrics.clone()), relay_strategy: relay_strategy.clone(), }) .map_err(|e| anyhow::format_err!("{}", e)) @@ -554,7 +552,7 @@ impl RelayHeadersAndMessages { message_relays.push(right_to_left_messages); } - relay_utils::relay_metrics(None, metrics_params) + relay_utils::relay_metrics(metrics_params) .expose() .await .map_err(|e| anyhow::format_err!("{}", e))?; diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 4b2e0c975602a..e47abfc5d94e3 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -95,6 +95,7 @@ impl RelayMessages { target_to_source_headers_relay: None, lane_id: self.lane.into(), metrics_params: self.prometheus_params.into(), + standalone_metrics: None, relay_strategy, }) .await diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index f591a7a98105e..7dccf82b6f8e4 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -20,7 +20,8 @@ use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use codec::Decode; use relay_utils::metrics::{ - metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64, + metric_name, register, F64SharedRef, Gauge, Metric, PrometheusError, Registry, + StandaloneMetric, F64, }; use sp_core::storage::StorageKey; use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; @@ -42,8 +43,6 @@ pub struct FloatStorageValueMetric { impl FloatStorageValueMetric { /// Create new metric. pub fn new( - registry: &Registry, - prefix: Option<&str>, client: Client, storage_key: StorageKey, maybe_default_value: Option, @@ -55,7 +54,7 @@ impl FloatStorageValueMetric { client, storage_key, maybe_default_value, - metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + metric: Gauge::new(metric_name(None, &name), help)?, shared_value_ref, }) } @@ -66,8 +65,17 @@ impl FloatStorageValueMetric { } } +impl Metric for FloatStorageValueMetric +where + T: 'static + Decode + Send + Sync + FixedPointNumber, +{ + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.metric.clone(), registry).map(drop) + } +} + #[async_trait] -impl StandaloneMetrics for FloatStorageValueMetric +impl StandaloneMetric for FloatStorageValueMetric where T: 'static + Decode + Send + Sync + FixedPointNumber, { diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs index c3b69c32f5728..f1c770ed228e7 100644 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -18,7 +18,7 @@ use crate::{chain::Chain, client::Client, error::Error}; use async_trait::async_trait; use relay_utils::metrics::{ - metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, U64, + metric_name, register, Gauge, Metric, PrometheusError, Registry, StandaloneMetric, U64, }; use sp_core::storage::StorageKey; use sp_runtime::traits::Header as HeaderT; @@ -46,16 +46,10 @@ impl Clone for StorageProofOverheadMetric { impl StorageProofOverheadMetric { /// Create new metric instance with given name and help. - pub fn new( - registry: &Registry, - prefix: Option<&str>, - client: Client, - name: String, - help: String, - ) -> Result { + pub fn new(client: Client, name: String, help: String) -> Result { Ok(StorageProofOverheadMetric { client, - metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + metric: Gauge::new(metric_name(None, &name), help)?, }) } @@ -84,8 +78,14 @@ impl StorageProofOverheadMetric { } } +impl Metric for StorageProofOverheadMetric { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.metric.clone(), registry).map(drop) + } +} + #[async_trait] -impl StandaloneMetrics for StorageProofOverheadMetric { +impl StandaloneMetric for StorageProofOverheadMetric { fn update_interval(&self) -> Duration { C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 8fad11bf370c1..320b44d310f0b 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -28,9 +28,8 @@ use backoff::backoff::Backoff; use futures::{select, Future, FutureExt, Stream, StreamExt}; use num_traits::{One, Saturating}; use relay_utils::{ - metrics::{GlobalMetrics, MetricsParams}, - relay_loop::Client as RelayClient, - retry_backoff, FailedClient, MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, retry_backoff, FailedClient, + MaybeConnectionError, }; use std::{ pin::Pin, @@ -114,9 +113,8 @@ pub async fn run( ) -> Result<(), relay_utils::Error> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) - .with_metrics(Some(metrics_prefix::

()), metrics_params) - .loop_metric(SyncLoopMetrics::new)? - .standalone_metric(GlobalMetrics::new)? + .with_metrics(metrics_params) + .loop_metric(SyncLoopMetrics::new(Some(&metrics_prefix::

()))?)? .expose() .await? .run(metrics_prefix::

(), move |source_client, target_client, metrics| { diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs index 1e4d910926ec8..1f65dac17c05e 100644 --- a/relays/finality/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -16,7 +16,9 @@ //! Metrics for headers synchronization relay loop. -use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; +use relay_utils::metrics::{ + metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, +}; /// Headers sync metrics. #[derive(Clone)] @@ -27,23 +29,18 @@ pub struct SyncLoopMetrics { impl SyncLoopMetrics { /// Create and register headers loop metrics. - pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + pub fn new(prefix: Option<&str>) -> Result { Ok(SyncLoopMetrics { - best_block_numbers: register( - GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best block numbers on source and target nodes", - ), - &["node"], - )?, - registry, + best_block_numbers: GaugeVec::new( + Opts::new( + metric_name(prefix, "best_block_numbers"), + "Best block numbers on source and target nodes", + ), + &["node"], )?, }) } -} -impl SyncLoopMetrics { /// Update best block number at source. pub fn update_best_block_at_source>(&self, source_best_number: Number) { self.best_block_numbers @@ -58,3 +55,10 @@ impl SyncLoopMetrics { .set(target_best_number.into()); } } + +impl Metric for SyncLoopMetrics { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.best_block_numbers.clone(), registry)?; + Ok(()) + } +} diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index 01f881998ad00..f95a8e0aba3ab 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -16,17 +16,11 @@ //! Substrate relay helpers -use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, Registry}; +use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError}; /// Creates standalone token price metric. -pub fn token_price_metric( - registry: &Registry, - prefix: Option<&str>, - token_id: &str, -) -> Result { +pub fn token_price_metric(token_id: &str) -> Result { FloatJsonValueMetric::new( - registry, - prefix, format!("https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", token_id), format!("$.{}.btc", token_id), format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 5e9564cf95e3c..6cadb64754a51 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -34,7 +34,9 @@ use relay_substrate_client::{ BlockNumberOf, Chain, Client, HashOf, }; use relay_utils::{ - metrics::{F64SharedRef, MetricsParams}, + metrics::{ + FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, + }, BlockNumberBase, }; use sp_core::{storage::StorageKey, Bytes}; @@ -63,6 +65,8 @@ pub struct MessagesRelayParams>, /// Relay strategy pub relay_strategy: Strategy, } @@ -241,110 +245,155 @@ pub fn select_delivery_transaction_limits chain token conversion rate. - pub target_to_base_conversion_rate: Option, - /// Shared reference to the actual source -> chain token conversion rate. - pub source_to_base_conversion_rate: Option, - /// Shared reference to the stored (in the source chain runtime storage) target -> source chain - /// conversion rate. - pub target_to_source_conversion_rate: Option, +pub struct StandaloneMessagesMetrics { + /// Global metrics. + pub global: GlobalMetrics, + /// Storage chain proof overhead metric. + pub source_storage_proof_overhead: StorageProofOverheadMetric, + /// Target chain proof overhead metric. + pub target_storage_proof_overhead: StorageProofOverheadMetric, + /// Source tokens to base conversion rate metric. + pub source_to_base_conversion_rate: Option, + /// Target tokens to base conversion rate metric. + pub target_to_base_conversion_rate: Option, + /// Source tokens to target tokens conversion rate metric. This rate is stored by the target + /// chain. + pub source_to_target_conversion_rate: + Option>, + /// Target tokens to source tokens conversion rate metric. This rate is stored by the source + /// chain. + pub target_to_source_conversion_rate: + Option>, } -impl StandaloneMessagesMetrics { +impl StandaloneMessagesMetrics { + /// Swap source and target sides. + pub fn reverse(self) -> StandaloneMessagesMetrics { + StandaloneMessagesMetrics { + global: self.global, + source_storage_proof_overhead: self.target_storage_proof_overhead, + target_storage_proof_overhead: self.source_storage_proof_overhead, + source_to_base_conversion_rate: self.target_to_base_conversion_rate, + target_to_base_conversion_rate: self.source_to_base_conversion_rate, + source_to_target_conversion_rate: self.target_to_source_conversion_rate, + target_to_source_conversion_rate: self.source_to_target_conversion_rate, + } + } + + /// Register all metrics in the registry. + pub fn register_and_spawn( + self, + metrics: MetricsParams, + ) -> Result { + self.global.register_and_spawn(&metrics.registry)?; + self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + if let Some(m) = self.source_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_source_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + Ok(metrics) + } + /// Return conversion rate from target to source tokens. pub async fn target_to_source_conversion_rate(&self) -> Option { - let target_to_base_conversion_rate = - (*self.target_to_base_conversion_rate.as_ref()?.read().await)?; - let source_to_base_conversion_rate = - (*self.source_to_base_conversion_rate.as_ref()?.read().await)?; - Some(source_to_base_conversion_rate / target_to_base_conversion_rate) + Self::compute_target_to_source_conversion_rate( + *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, + *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, + ) + } + + /// Return conversion rate from target to source tokens, given conversion rates from + /// target/source tokens to some base token. + fn compute_target_to_source_conversion_rate( + target_to_base_conversion_rate: Option, + source_to_base_conversion_rate: Option, + ) -> Option { + Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) } } -/// Add general standalone metrics for the message lane relay loop. -pub fn add_standalone_metrics( - metrics_prefix: Option, - metrics_params: MetricsParams, - source_client: Client, +/// Create standalone metrics for the message lane relay loop. +/// +/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) +/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). +pub fn standalone_metrics( + source_client: Client, + target_client: Client, source_chain_token_id: Option<&str>, target_chain_token_id: Option<&str>, + source_to_target_conversion_rate_params: Option<(StorageKey, FixedU128)>, target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, -) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { - let mut target_to_source_conversion_rate = None; - let mut source_to_base_conversion_rate = None; - let mut target_to_base_conversion_rate = None; - let mut metrics_params = relay_utils::relay_metrics(metrics_prefix, metrics_params) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), - format!("{} storage proof overhead", P::SourceChain::NAME), - ) - })?; - if let Some(( - target_to_source_conversion_rate_storage_key, - initial_target_to_source_conversion_rate, - )) = target_to_source_conversion_rate_params - { - metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - registry, - prefix, - source_client, - target_to_source_conversion_rate_storage_key, - Some(initial_target_to_source_conversion_rate), - format!( - "{}_{}_to_{}_conversion_rate", - P::SourceChain::NAME, - P::TargetChain::NAME, - P::SourceChain::NAME - ), - format!( - "{} to {} tokens conversion rate (used by {})", - P::TargetChain::NAME, - P::SourceChain::NAME, - P::SourceChain::NAME - ), - )?; - target_to_source_conversion_rate = Some(metric.shared_value_ref()); - Ok(metric) - })?; - } - if let Some(source_chain_token_id) = source_chain_token_id { - metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = - crate::helpers::token_price_metric(registry, prefix, source_chain_token_id)?; - source_to_base_conversion_rate = Some(metric.shared_value_ref()); - Ok(metric) - })?; - } - if let Some(target_chain_token_id) = target_chain_token_id { - metrics_params = metrics_params.standalone_metric(|registry, prefix| { - let metric = - crate::helpers::token_price_metric(registry, prefix, target_chain_token_id)?; - target_to_base_conversion_rate = Some(metric.shared_value_ref()); - Ok(metric) - })?; - } - Ok(( - metrics_params.into_params(), - StandaloneMessagesMetrics { - target_to_base_conversion_rate, - source_to_base_conversion_rate, - target_to_source_conversion_rate, - }, - )) +) -> anyhow::Result> { + Ok(StandaloneMessagesMetrics { + global: GlobalMetrics::new()?, + source_storage_proof_overhead: StorageProofOverheadMetric::new( + source_client.clone(), + format!("{}_storage_proof_overhead", SC::NAME.to_lowercase()), + format!("{} storage proof overhead", SC::NAME), + )?, + target_storage_proof_overhead: StorageProofOverheadMetric::new( + target_client.clone(), + format!("{}_storage_proof_overhead", TC::NAME.to_lowercase()), + format!("{} storage proof overhead", TC::NAME), + )?, + source_to_base_conversion_rate: source_chain_token_id + .map(|source_chain_token_id| { + crate::helpers::token_price_metric(source_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_base_conversion_rate: target_chain_token_id + .map(|target_chain_token_id| { + crate::helpers::token_price_metric(target_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + source_to_target_conversion_rate: source_to_target_conversion_rate_params + .map(|(key, rate)| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + target_client, + key, + Some(rate), + format!("{}_{}_to_{}_conversion_rate", TC::NAME, SC::NAME, TC::NAME), + format!( + "{} to {} tokens conversion rate (used by {})", + SC::NAME, + TC::NAME, + TC::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_source_conversion_rate: target_to_source_conversion_rate_params + .map(|(key, rate)| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + source_client, + key, + Some(rate), + format!("{}_{}_to_{}_conversion_rate", SC::NAME, TC::NAME, SC::NAME), + format!( + "{} to {} tokens conversion rate (used by {})", + TC::NAME, + SC::NAME, + SC::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + }) } #[cfg(test)] mod tests { use super::*; - use async_std::sync::{Arc, RwLock}; type RialtoToMillauMessagesWeights = pallet_bridge_messages::weights::RialtoWeight; @@ -369,12 +418,9 @@ mod tests { #[async_std::test] async fn target_to_source_conversion_rate_works() { - let metrics = StandaloneMessagesMetrics { - target_to_base_conversion_rate: Some(Arc::new(RwLock::new(Some(183.15)))), - source_to_base_conversion_rate: Some(Arc::new(RwLock::new(Some(12.32)))), - target_to_source_conversion_rate: None, // we don't care - }; - - assert_eq!(metrics.target_to_source_conversion_rate().await, Some(12.32 / 183.15),); + assert_eq!( + StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), + Some(12.32 / 183.15), + ); } } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 6f95ffd12f09c..eafc6bd3fc5f7 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -55,7 +55,7 @@ pub struct SubstrateMessagesTarget { client: Client, lane: P, lane_id: LaneId, - metric_values: StandaloneMessagesMetrics, + metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, } @@ -65,7 +65,7 @@ impl SubstrateMessagesTarget

{ client: Client, lane: P, lane_id: LaneId, - metric_values: StandaloneMessagesMetrics, + metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 2de644091ef2f..6cdb2b1aa5aee 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -32,10 +32,7 @@ use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use bp_runtime::messages::DispatchFeePayment; use relay_utils::{ - interval, - metrics::{GlobalMetrics, MetricsParams}, - process_future_result, - relay_loop::Client as RelayClient, + interval, metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, retry_backoff, FailedClient, }; @@ -270,9 +267,8 @@ pub async fn run( let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) - .with_metrics(Some(metrics_prefix::

(¶ms.lane)), metrics_params) - .loop_metric(MessageLaneLoopMetrics::new)? - .standalone_metric(GlobalMetrics::new)? + .with_metrics(metrics_params) + .loop_metric(MessageLaneLoopMetrics::new(Some(&metrics_prefix::

(¶ms.lane)))?)? .expose() .await? .run(metrics_prefix::

(¶ms.lane), move |source_client, target_client, metrics| { diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 8d6e480722e66..eac2f703692a1 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -22,7 +22,9 @@ use crate::{ }; use bp_messages::MessageNonce; -use relay_utils::metrics::{metric_name, register, GaugeVec, Opts, PrometheusError, Registry, U64}; +use relay_utils::metrics::{ + metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, +}; /// Message lane relay metrics. /// @@ -38,30 +40,22 @@ pub struct MessageLaneLoopMetrics { impl MessageLaneLoopMetrics { /// Create and register messages loop metrics. - pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + pub fn new(prefix: Option<&str>) -> Result { Ok(MessageLaneLoopMetrics { - best_block_numbers: register( - GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best finalized block numbers", - ), - &["type"], - )?, - registry, + best_block_numbers: GaugeVec::new( + Opts::new( + metric_name(prefix, "best_block_numbers"), + "Best finalized block numbers", + ), + &["type"], )?, - lane_state_nonces: register( - GaugeVec::new( - Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), - &["type"], - )?, - registry, + lane_state_nonces: GaugeVec::new( + Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), + &["type"], )?, }) } -} -impl MessageLaneLoopMetrics { /// Update source client state metrics. pub fn update_source_state(&self, source_client_state: SourceClientState

) { self.best_block_numbers @@ -122,3 +116,11 @@ impl MessageLaneLoopMetrics { .set(target_latest_confirmed_nonce); } } + +impl Metric for MessageLaneLoopMetrics { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.best_block_numbers.clone(), registry)?; + register(self.lane_state_nonces.clone(), registry)?; + Ok(()) + } +} diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 5c796071c6d5b..805fe70bfe858 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -46,28 +46,38 @@ pub struct MetricsParams { /// Interface and TCP port to be used when exposing Prometheus metrics. pub address: Option, /// Metrics registry. May be `Some(_)` if several components share the same endpoint. - pub registry: Option, - /// Prefix that must be used in metric names. - pub metrics_prefix: Option, + pub registry: Registry, } -/// Metrics API. -pub trait Metrics: Clone + Send + Sync + 'static {} - -impl Metrics for T {} +/// Metric API. +pub trait Metric: Clone + Send + Sync + 'static { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError>; +} -/// Standalone metrics API. +/// Standalone metric API. /// /// Metrics of this kind know how to update themselves, so we may just spawn and forget the /// asynchronous self-update task. #[async_trait] -pub trait StandaloneMetrics: Metrics { +pub trait StandaloneMetric: Metric { /// Update metric values. async fn update(&self); /// Metrics update interval. fn update_interval(&self) -> Duration; + /// Register and spawn metric. Metric is only spawned if it is registered for the first time. + fn register_and_spawn(self, registry: &Registry) -> Result<(), PrometheusError> { + match self.register(registry) { + Ok(()) => { + self.spawn(); + Ok(()) + }, + Err(PrometheusError::AlreadyReg) => Ok(()), + Err(e) => Err(e), + } + } + /// Spawn the self update task that will keep update metric value at given intervals. fn spawn(self) { async_std::task::spawn(async move { @@ -89,7 +99,7 @@ impl Default for MetricsAddress { impl MetricsParams { /// Creates metrics params so that metrics are not exposed. pub fn disabled() -> Self { - MetricsParams { address: None, registry: None, metrics_prefix: None } + MetricsParams { address: None, registry: Registry::new() } } /// Do not expose metrics. @@ -97,17 +107,11 @@ impl MetricsParams { self.address = None; self } - - /// Set prefix to use in metric names. - pub fn metrics_prefix(mut self, prefix: String) -> Self { - self.metrics_prefix = Some(prefix); - self - } } impl From> for MetricsParams { fn from(address: Option) -> Self { - MetricsParams { address, registry: None, metrics_prefix: None } + MetricsParams { address, registry: Registry::new() } } } diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index 9404695c1c305..7535cbef9863f 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -17,8 +17,8 @@ use crate::{ error::{self, Error}, metrics::{ - metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, - F64, + metric_name, register, F64SharedRef, Gauge, Metric, PrometheusError, Registry, + StandaloneMetric, F64, }, }; @@ -44,8 +44,6 @@ pub struct FloatJsonValueMetric { impl FloatJsonValueMetric { /// Create new metric instance with given name and help. pub fn new( - registry: &Registry, - prefix: Option<&str>, url: String, json_path: String, name: String, @@ -55,7 +53,7 @@ impl FloatJsonValueMetric { Ok(FloatJsonValueMetric { url, json_path, - metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + metric: Gauge::new(metric_name(None, &name), help)?, shared_value_ref, }) } @@ -81,8 +79,14 @@ impl FloatJsonValueMetric { } } +impl Metric for FloatJsonValueMetric { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.metric.clone(), registry).map(drop) + } +} + #[async_trait] -impl StandaloneMetrics for FloatJsonValueMetric { +impl StandaloneMetric for FloatJsonValueMetric { fn update_interval(&self) -> Duration { UPDATE_INTERVAL } diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs index 7746690a0c72c..df90a2c482347 100644 --- a/relays/utils/src/metrics/global.rs +++ b/relays/utils/src/metrics/global.rs @@ -17,8 +17,8 @@ //! Global system-wide Prometheus metrics exposed by relays. use crate::metrics::{ - metric_name, register, Gauge, GaugeVec, Opts, PrometheusError, Registry, StandaloneMetrics, - F64, U64, + metric_name, register, Gauge, GaugeVec, Metric, Opts, PrometheusError, Registry, + StandaloneMetric, F64, U64, }; use async_std::sync::{Arc, Mutex}; @@ -40,36 +40,36 @@ pub struct GlobalMetrics { impl GlobalMetrics { /// Create and register global metrics. - pub fn new(registry: &Registry, prefix: Option<&str>) -> Result { + pub fn new() -> Result { Ok(GlobalMetrics { system: Arc::new(Mutex::new(System::new_with_specifics(RefreshKind::everything()))), - system_average_load: register( - GaugeVec::new( - Opts::new(metric_name(prefix, "system_average_load"), "System load average"), - &["over"], - )?, - registry, + system_average_load: GaugeVec::new( + Opts::new(metric_name(None, "system_average_load"), "System load average"), + &["over"], )?, - process_cpu_usage_percentage: register( - Gauge::new( - metric_name(prefix, "process_cpu_usage_percentage"), - "Process CPU usage", - )?, - registry, + process_cpu_usage_percentage: Gauge::new( + metric_name(None, "process_cpu_usage_percentage"), + "Process CPU usage", )?, - process_memory_usage_bytes: register( - Gauge::new( - metric_name(prefix, "process_memory_usage_bytes"), - "Process memory (resident set size) usage", - )?, - registry, + process_memory_usage_bytes: Gauge::new( + metric_name(None, "process_memory_usage_bytes"), + "Process memory (resident set size) usage", )?, }) } } +impl Metric for GlobalMetrics { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.system_average_load.clone(), registry)?; + register(self.process_cpu_usage_percentage.clone(), registry)?; + register(self.process_memory_usage_bytes.clone(), registry)?; + Ok(()) + } +} + #[async_trait] -impl StandaloneMetrics for GlobalMetrics { +impl StandaloneMetric for GlobalMetrics { async fn update(&self) { // update system-wide metrics let mut system = self.system.lock().await; diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 4898185a150b8..a992aaaf57ee5 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -16,7 +16,7 @@ use crate::{ error::Error, - metrics::{Metrics, MetricsAddress, MetricsParams, PrometheusError, StandaloneMetrics}, + metrics::{Metric, MetricsAddress, MetricsParams}, FailedClient, MaybeConnectionError, }; @@ -53,7 +53,7 @@ pub fn relay_loop(source_client: SC, target_client: TC) -> Loop, params: MetricsParams) -> LoopMetrics<(), (), ()> { +pub fn relay_metrics(params: MetricsParams) -> LoopMetrics<(), (), ()> { LoopMetrics { relay_loop: Loop { reconnect_delay: RECONNECT_DELAY, @@ -62,8 +62,7 @@ pub fn relay_metrics(prefix: Option, params: MetricsParams) -> LoopMetri loop_metric: None, }, address: params.address, - registry: params.registry.unwrap_or_else(|| create_metrics_registry(prefix)), - metrics_prefix: params.metrics_prefix, + registry: params.registry, loop_metric: None, } } @@ -81,7 +80,6 @@ pub struct LoopMetrics { relay_loop: Loop, address: Option, registry: Registry, - metrics_prefix: Option, loop_metric: Option, } @@ -93,11 +91,7 @@ impl Loop { } /// Start building loop metrics using given prefix. - pub fn with_metrics( - self, - prefix: Option, - params: MetricsParams, - ) -> LoopMetrics { + pub fn with_metrics(self, params: MetricsParams) -> LoopMetrics { LoopMetrics { relay_loop: Loop { reconnect_delay: self.reconnect_delay, @@ -106,8 +100,7 @@ impl Loop { loop_metric: None, }, address: params.address, - registry: params.registry.unwrap_or_else(|| create_metrics_registry(prefix)), - metrics_prefix: params.metrics_prefix, + registry: params.registry, loop_metric: None, } } @@ -160,44 +153,23 @@ impl LoopMetrics { /// Add relay loop metrics. /// /// Loop metrics will be passed to the loop callback. - pub fn loop_metric( + pub fn loop_metric( self, - create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, + metric: NewLM, ) -> Result, Error> { - let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref())?; + metric.register(&self.registry)?; Ok(LoopMetrics { relay_loop: self.relay_loop, address: self.address, registry: self.registry, - metrics_prefix: self.metrics_prefix, - loop_metric: Some(loop_metric), + loop_metric: Some(metric), }) } - /// Add standalone metrics. - pub fn standalone_metric( - self, - create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> Result { - // since standalone metrics are updating themselves, we may just ignore the fact that the - // same standalone metric is exposed by several loops && only spawn single metric - match create_metric(&self.registry, self.metrics_prefix.as_deref()) { - Ok(standalone_metrics) => standalone_metrics.spawn(), - Err(PrometheusError::AlreadyReg) => (), - Err(e) => return Err(e.into()), - } - - Ok(self) - } - /// Convert into `MetricsParams` structure so that metrics registry may be extended later. pub fn into_params(self) -> MetricsParams { - MetricsParams { - address: self.address, - registry: Some(self.registry), - metrics_prefix: self.metrics_prefix, - } + MetricsParams { address: self.address, registry: self.registry } } /// Expose metrics using address passed at creation. @@ -274,15 +246,3 @@ pub async fn reconnect_failed_client( break } } - -/// Create new registry with global metrics. -fn create_metrics_registry(prefix: Option) -> Registry { - match prefix { - Some(prefix) => { - assert!(!prefix.is_empty(), "Metrics prefix can not be empty"); - Registry::new_custom(Some(prefix), None) - .expect("only fails if prefix is empty; prefix is not empty; qed") - }, - None => Registry::new(), - } -} From 5290e7f1350fa9f10bf8b17559974e1509ad2990 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 24 Nov 2021 14:13:27 +0300 Subject: [PATCH 0604/1210] fixed set_operational in GRANDPA pallet (#1226) --- modules/grandpa/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 279e23404a059..4e57a45292d3a 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -239,7 +239,7 @@ pub mod pallet { operational: bool, ) -> DispatchResultWithPostInfo { ensure_owner_or_root::(origin)?; - >::put(operational); + >::put(!operational); if operational { log::info!(target: "runtime::bridge-grandpa", "Resuming pallet operations."); @@ -804,9 +804,13 @@ mod tests { #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { - >::put(true); + initialize_substrate_bridge(); + + assert_ok!(Pallet::::set_operational(Origin::root(), false)); + assert_noop!(submit_finality_proof(1), Error::::Halted); - assert_noop!(submit_finality_proof(1), Error::::Halted,); + assert_ok!(Pallet::::set_operational(Origin::root(), true)); + assert_ok!(submit_finality_proof(1)); }) } From fe7587d26fe3f2902fadb053f06d44ff0e9a1423 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Tue, 30 Nov 2021 19:47:25 +0800 Subject: [PATCH 0605/1210] Add mut support (#1232) --- relays/messages/src/message_race_delivery.rs | 2 +- relays/messages/src/relay_strategy/altruistic_strategy.rs | 2 +- relays/messages/src/relay_strategy/enforcement_strategy.rs | 2 +- relays/messages/src/relay_strategy/mix_strategy.rs | 2 +- relays/messages/src/relay_strategy/mod.rs | 2 +- relays/messages/src/relay_strategy/rational_strategy.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 1cd2cbd267185..dc994364f1787 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -521,7 +521,7 @@ where nonces_queue_range: 0..maximal_source_queue_index + 1, }; - let strategy = EnforcementStrategy::new(self.relay_strategy.clone()); + let mut strategy = EnforcementStrategy::new(self.relay_strategy.clone()); let range_end = strategy.decide(reference).await?; let range_begin = source_queue[0].1.begin(); diff --git a/relays/messages/src/relay_strategy/altruistic_strategy.rs b/relays/messages/src/relay_strategy/altruistic_strategy.rs index f932b796b0dee..d6fec7f1297b3 100644 --- a/relays/messages/src/relay_strategy/altruistic_strategy.rs +++ b/relays/messages/src/relay_strategy/altruistic_strategy.rs @@ -37,7 +37,7 @@ impl RelayStrategy for AltruisticStrategy { SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, >( - &self, + &mut self, _reference: &mut RelayReference, ) -> bool { true diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/relay_strategy/enforcement_strategy.rs index 042c05bec00ad..1e9ef5bdbf818 100644 --- a/relays/messages/src/relay_strategy/enforcement_strategy.rs +++ b/relays/messages/src/relay_strategy/enforcement_strategy.rs @@ -49,7 +49,7 @@ impl EnforcementStrategy { SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, >( - &self, + &mut self, reference: RelayMessagesBatchReference, ) -> Option { let mut hard_selected_count = 0; diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs index a267d8ca5f5a8..4ac7fe1d0ed06 100644 --- a/relays/messages/src/relay_strategy/mix_strategy.rs +++ b/relays/messages/src/relay_strategy/mix_strategy.rs @@ -47,7 +47,7 @@ impl RelayStrategy for MixStrategy { SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, >( - &self, + &mut self, reference: &mut RelayReference, ) -> bool { match self.relayer_mode { diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs index 3e4eef8975dd8..d902bd93e5cf9 100644 --- a/relays/messages/src/relay_strategy/mod.rs +++ b/relays/messages/src/relay_strategy/mod.rs @@ -52,7 +52,7 @@ pub trait RelayStrategy: 'static + Clone + Send + Sync { SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, >( - &self, + &mut self, reference: &mut RelayReference, ) -> bool; } diff --git a/relays/messages/src/relay_strategy/rational_strategy.rs b/relays/messages/src/relay_strategy/rational_strategy.rs index dc408ffd49e25..fd0a1ffafc8b9 100644 --- a/relays/messages/src/relay_strategy/rational_strategy.rs +++ b/relays/messages/src/relay_strategy/rational_strategy.rs @@ -41,7 +41,7 @@ impl RelayStrategy for RationalStrategy { SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, >( - &self, + &mut self, reference: &mut RelayReference, ) -> bool { // technically, multiple confirmations will be delivered in a single transaction, From e0d38b71c52dca0a37aa18a01727c845f055e23f Mon Sep 17 00:00:00 2001 From: Antonio Dropulic Date: Tue, 30 Nov 2021 14:43:43 +0100 Subject: [PATCH 0606/1210] update dependencies (#1229) --- bin/millau/node/src/chain_spec.rs | 1 - bin/millau/node/src/command.rs | 10 +- bin/millau/node/src/service.rs | 186 +++----------------- bin/millau/runtime/src/lib.rs | 3 - bin/rialto-parachain/node/src/chain_spec.rs | 1 - bin/rialto-parachain/node/src/cli.rs | 3 + bin/rialto-parachain/node/src/command.rs | 6 +- bin/rialto-parachain/node/src/service.rs | 5 +- bin/rialto/node/Cargo.toml | 1 - bin/rialto/node/src/chain_spec.rs | 1 - bin/rialto/node/src/command.rs | 2 +- bin/rialto/node/src/overseer.rs | 5 +- bin/rialto/node/src/service.rs | 13 +- bin/rialto/runtime/src/lib.rs | 10 +- bin/rialto/runtime/src/parachains.rs | 4 +- modules/grandpa/src/lib.rs | 16 +- modules/grandpa/src/mock.rs | 1 - relays/bin-substrate/src/cli/swap_tokens.rs | 3 +- 18 files changed, 60 insertions(+), 211 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index c32291fb38581..05496bb64f639 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -186,7 +186,6 @@ fn testnet_genesis( GenesisConfig { system: SystemConfig { code: WASM_BINARY.expect("Millau development WASM not available").to_vec(), - changes_trie_config: Default::default(), }, balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 4285ecaced516..4dbf9575dfec7 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -20,7 +20,7 @@ use crate::{ service::new_partial, }; use millau_runtime::{Block, RuntimeApi}; -use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; +use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; impl SubstrateCli for Cli { @@ -72,7 +72,7 @@ impl SubstrateCli for Cli { pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); // make sure to set correct crypto version. - sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom( + sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom( millau_runtime::SS58Prefix::get() as u16, )); @@ -146,11 +146,7 @@ pub fn run() -> sc_cli::Result<()> { None => { let runner = cli.create_runner(&cli.run)?; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => service::new_light(config), - _ => service::new_full(config), - } - .map_err(sc_cli::Error::Service) + service::new_full(config).map_err(sc_cli::Error::Service) }) }, } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index b8d42f9c7ed34..4085982494b8a 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -29,10 +29,10 @@ // ===================================================================================== use millau_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::{ExecutorProvider, RemoteBackend}; +use sc_client_api::ExecutorProvider; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; - +use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; @@ -40,13 +40,16 @@ use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; -type Executor = NativeElseWasmExecutor; - // Our native executor instance. pub struct ExecutorDispatch; impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + /// Only enable the benchmarking host functions when we actually want to benchmark. + #[cfg(feature = "runtime-benchmarks")] type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + /// Otherwise we only use the default Substrate host functions. + #[cfg(not(feature = "runtime-benchmarks"))] + type ExtendHostFunctions = (); fn dispatch(method: &str, data: &[u8]) -> Option> { millau_runtime::api::dispatch(method, data) @@ -62,7 +65,6 @@ type FullClient = type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; -#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, ) -> Result< @@ -86,7 +88,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())) + return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) } let telemetry = config @@ -107,15 +109,15 @@ pub fn new_partial( ); let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, + sc_service::new_full_parts::( + &config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); telemetry }); @@ -175,7 +177,7 @@ pub fn new_partial( }) } -fn remote_keystore(_url: &str) -> Result, &'static str> { +fn remote_keystore(_url: &String) -> Result, &'static str> { // FIXME: here would the concrete keystore be built, // must return a concrete type (NOT `LocalKeystore`) that // implements `CryptoStore` and `SyncCryptoStore` @@ -210,7 +212,7 @@ pub fn new_full(mut config: Configuration) -> Result let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), - vec![], + Vec::default(), )); let (network, system_rpc_tx, network_starter) = @@ -220,7 +222,6 @@ pub fn new_full(mut config: Configuration) -> Result transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, - on_demand: None, block_announce_validator_builder: None, warp_sync: Some(warp_sync), })?; @@ -240,7 +241,7 @@ pub fn new_full(mut config: Configuration) -> Result let name = config.network.node_name.clone(); let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); - let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); + let shared_voter_state = SharedVoterState::empty(); let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; @@ -291,8 +292,6 @@ pub fn new_full(mut config: Configuration) -> Result task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), rpc_extensions_builder, - on_demand: None, - remote_blockchain: None, backend, system_rpc_tx, config, @@ -317,17 +316,18 @@ pub fn new_full(mut config: Configuration) -> Result let aura = sc_consensus_aura::start_aura::( StartAuraParams { slot_duration, - client, + client: client.clone(), select_chain, block_import, proposer_factory, create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - raw_slot_duration, - ); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + *timestamp, + raw_slot_duration, + ); Ok((timestamp, slot)) }, @@ -345,7 +345,9 @@ pub fn new_full(mut config: Configuration) -> Result // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. - task_manager.spawn_essential_handle().spawn_blocking("aura", aura); + task_manager + .spawn_essential_handle() + .spawn_blocking("aura", Some("block-authoring"), aura); } // if the node isn't actively participating in consensus then it doesn't @@ -385,6 +387,7 @@ pub fn new_full(mut config: Configuration) -> Result // if it fails we take down the service with it. task_manager.spawn_essential_handle().spawn_blocking( "grandpa-voter", + None, sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, ); } @@ -392,144 +395,3 @@ pub fn new_full(mut config: Configuration) -> Result network_starter.start_network(); Ok(task_manager) } - -/// Builds a new service for a light client. -pub fn new_light(mut config: Configuration) -> Result { - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - ); - - let (client, backend, keystore_container, mut task_manager, on_demand) = - sc_service::new_light_parts::( - &config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - - let mut telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); - telemetry - }); - - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light( - config.transaction_pool.clone(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - on_demand.clone(), - )); - - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( - client.clone(), - &(client.clone() as Arc<_>), - select_chain, - telemetry.as_ref().map(|x| x.handle()), - )?; - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); - - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import)), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::NeverCanAuthor, - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - })?; - - let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - grandpa_link.shared_authority_set().clone(), - vec![], - )); - - let (network, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - on_demand: Some(on_demand.clone()), - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; - - if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); - } - - let enable_grandpa = !config.disable_grandpa; - if enable_grandpa { - let name = config.network.node_name.clone(); - - let config = sc_finality_grandpa::Config { - gossip_duration: std::time::Duration::from_millis(333), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore: None, - local_role: config.role.clone(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - task_manager.spawn_handle().spawn_blocking( - "grandpa-observer", - sc_finality_grandpa::run_grandpa_observer(config, grandpa_link, network.clone())?, - ); - } - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - remote_blockchain: Some(backend.remote_blockchain()), - transaction_pool, - task_manager: &mut task_manager, - on_demand: Some(on_demand), - rpc_extensions_builder: Box::new(|_, _| Ok(())), - config, - client, - keystore: keystore_container.sync_keystore(), - backend, - network, - system_rpc_tx, - telemetry: telemetry.as_mut(), - })?; - - network_starter.start_network(); - Ok(task_manager) -} diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4e486c267010d..b713211b1e489 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -100,9 +100,6 @@ pub type Hash = bp_millau::Hash; /// Hashing algorithm used by the chain. pub type Hashing = bp_millau::Hasher; -/// Digest item type. -pub type DigestItem = generic::DigestItem; - /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index f93887a21e479..52012423fb716 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -151,7 +151,6 @@ fn testnet_genesis( code: rialto_parachain_runtime::WASM_BINARY .expect("WASM binary was not build, please build it!") .to_vec(), - changes_trie_config: Default::default(), }, balances: rialto_parachain_runtime::BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index bc2238e2fd44e..78c05f90c8800 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -103,6 +103,9 @@ pub struct Cli { #[structopt(subcommand)] pub subcommand: Option, + #[structopt(long)] + pub parachain_id: Option, + #[structopt(flatten)] pub run: cumulus_client_cli::RunCmd, diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index eb9aba2c104ba..e4f52cc026a7e 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -77,7 +77,7 @@ impl SubstrateCli for Cli { } fn load_spec(&self, id: &str) -> std::result::Result, String> { - load_spec(id, self.run.parachain_id.unwrap_or(2000).into()) + load_spec(id, self.parachain_id.unwrap_or(2000).into()) } fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { @@ -153,7 +153,7 @@ macro_rules! construct_async_run { /// Parse command line arguments into service configuration. pub fn run() -> Result<()> { let cli = Cli::from_args(); - sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom( + sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom( rialto_parachain_runtime::SS58Prefix::get() as u16, )); @@ -273,7 +273,7 @@ pub fn run() -> Result<()> { [RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()), ); - let id = ParaId::from(cli.run.parachain_id.or(para_id).expect("Missing ParaId")); + let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); let parachain_account = AccountIdConversion::::into_account(&id); diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 65a8e7bb65c57..bd3afca307449 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -147,7 +147,7 @@ where let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); telemetry }); @@ -283,7 +283,6 @@ where transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue: import_queue.clone(), - on_demand: None, block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)), warp_sync: None, })?; @@ -292,8 +291,6 @@ where let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone()))); sc_service::spawn_tasks(sc_service::SpawnTasksParams { - on_demand: None, - remote_blockchain: None, rpc_extensions_builder, client: client.clone(), transaction_pool: transaction_pool.clone(), diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 75be9bcd9fb7d..fd76fbf9a6170 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -88,7 +88,6 @@ polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/pol polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-dispute-participation = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 49f77c9bc6a84..cadacad72da97 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -207,7 +207,6 @@ fn testnet_genesis( GenesisConfig { system: SystemConfig { code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(), - changes_trie_config: Default::default(), }, balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 6f841a9d67f1d..7be615a57760c 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -70,7 +70,7 @@ impl SubstrateCli for Cli { /// Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); - sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::Custom( + sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom( rialto_runtime::SS58Prefix::get() as u16, )); diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs index 17f7edce2a319..9a7025e77c9b4 100644 --- a/bin/rialto/node/src/overseer.rs +++ b/bin/rialto/node/src/overseer.rs @@ -63,8 +63,7 @@ pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem; pub use polkadot_node_core_chain_api::ChainApiSubsystem; pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem; pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem; -pub use polkadot_node_core_dispute_participation::DisputeParticipationSubsystem; -pub use polkadot_node_core_provisioner::ProvisioningSubsystem as ProvisionerSubsystem; +pub use polkadot_node_core_provisioner::ProvisionerSubsystem; pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem; pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem; @@ -160,7 +159,6 @@ pub fn prepared_overseer_builder( ApprovalVotingSubsystem, GossipSupportSubsystem, DisputeCoordinatorSubsystem, - DisputeParticipationSubsystem, DisputeDistributionSubsystem, ChainSelectionSubsystem, >, @@ -249,7 +247,6 @@ where keystore.clone(), Metrics::register(registry)?, )) - .dispute_participation(DisputeParticipationSubsystem::new()) .dispute_distribution(DisputeDistributionSubsystem::new( keystore, dispute_req_receiver, diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index e2e811eaa67f4..fb774d86cca93 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -226,7 +226,7 @@ where let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", worker.run()); + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); telemetry }); @@ -474,7 +474,6 @@ where transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue, - on_demand: None, block_announce_validator_builder: None, warp_sync: Some(warp_sync), })?; @@ -533,8 +532,6 @@ where rpc_extensions_builder: Box::new(rpc_extensions_builder), transaction_pool: transaction_pool.clone(), task_manager: &mut task_manager, - on_demand: None, - remote_blockchain: None, system_rpc_tx, telemetry: telemetry.as_mut(), })?; @@ -574,7 +571,9 @@ where prometheus_registry.clone(), ); - task_manager.spawn_handle().spawn("authority-discovery-worker", worker.run()); + task_manager + .spawn_handle() + .spawn("authority-discovery-worker", None, worker.run()); Some(service) } else { None @@ -619,6 +618,7 @@ where let handle = handle.clone(); task_manager.spawn_essential_handle().spawn_blocking( "overseer", + None, Box::pin(async move { use futures::{pin_mut, select, FutureExt}; @@ -705,7 +705,7 @@ where }; let babe = sc_consensus_babe::start_babe(babe_config)?; - task_manager.spawn_essential_handle().spawn_blocking("babe", babe); + task_manager.spawn_essential_handle().spawn_blocking("babe", None, babe); } // if the node isn't actively participating in consensus then it doesn't @@ -751,6 +751,7 @@ where task_manager.spawn_essential_handle().spawn_blocking( "grandpa-voter", + None, sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, ); } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index aae9aa21c2fa5..5e7e47490d58d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -101,9 +101,6 @@ pub type Hash = bp_rialto::Hash; /// Hashing algorithm used by the chain. pub type Hashing = bp_rialto::Hasher; -/// Digest item type. -pub type DigestItem = generic::DigestItem; - /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades @@ -675,6 +672,13 @@ impl_runtime_apis! { polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::(para_id, assumption) } + fn assumed_validation_data( + para_id: polkadot_primitives::v1::Id, + expected_persisted_validation_data_hash: Hash, + ) -> Option<(polkadot_primitives::v1::PersistedValidationData, polkadot_primitives::v1::ValidationCodeHash)> { + polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::(para_id, expected_persisted_validation_data_hash) + } + fn check_validation_outputs( para_id: polkadot_primitives::v1::Id, outputs: polkadot_primitives::v1::CandidateCommitments, diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 9a2f85460153c..332a3387ac69a 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -71,7 +71,9 @@ impl parachains_paras::Config for Runtime { type WeightInfo = parachains_paras::TestWeightInfo; } -impl parachains_paras_inherent::Config for Runtime {} +impl parachains_paras_inherent::Config for Runtime { + type WeightInfo = parachains_paras_inherent::TestWeightInfo; +} impl parachains_scheduler::Config for Runtime {} diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 4e57a45292d3a..cbc85da30259f 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -620,9 +620,7 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader #[cfg(test)] mod tests { use super::*; - use crate::mock::{ - run_test, test_header, Origin, TestHash, TestHeader, TestNumber, TestRuntime, - }; + use crate::mock::{run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime}; use bp_test_utils::{ authority_list, make_default_justification, make_justification_for_header, JustificationGeneratorParams, ALICE, BOB, @@ -672,19 +670,17 @@ mod tests { let _ = Pallet::::on_initialize(current_number); } - fn change_log(delay: u64) -> Digest { + fn change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], delay, }); - Digest:: { - logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], - } + Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] } } - fn forced_change_log(delay: u64) -> Digest { + fn forced_change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ForcedChange( delay, sp_finality_grandpa::ScheduledChange { @@ -693,9 +689,7 @@ mod tests { }, ); - Digest:: { - logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())], - } + Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] } } #[test] diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 183a567791563..f8b5e269323f9 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -29,7 +29,6 @@ use sp_runtime::{ pub type AccountId = u64; pub type TestHeader = crate::BridgedHeader; pub type TestNumber = crate::BridgedBlockNumber; -pub type TestHash = crate::BridgedBlockHash; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index aa3996aa41364..dbe46f4690709 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -401,7 +401,8 @@ impl SwapTokens { .await?; if token_swap_state != None { return Err(anyhow::format_err!( - "Confirmed token swap state has been changed to {:?} unexpectedly" + "Confirmed token swap state has been changed to {:?} unexpectedly", + token_swap_state )) } } else { From 8c8d6d4ea15febfbbf2bfd2fc78fc7db3e13b2cb Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 30 Nov 2021 17:59:10 +0200 Subject: [PATCH 0607/1210] Integrate BEEFY with Rialto & Millau runtimes (#1227) * Add Beefy pallet to Rialto runtime * Add Beefy gadget to Rialto node * Add MMR pallet to Rialto runtime * Add Beefy pallet to Millau runtime * Add Beefy gadget to Millau node * Add MMR pallet to Millau runtime * Add pallet_beefy_mmr to Millau runtime * Add pallet_beefy_mmr to Rialto runtime * Implement MMR and BEEFY APIs in Rialto * fix unit tests - should_encode_bridge_send_message_call() tests for new runtime encoding resulted from newly added pallets. - runtime size_of::() slightly increased from newly added pallets. * fix grumbles * tighten clippy allowances * fix more grumbles * Add MMR RPC to Rialto and Millau nodes Also implement MmrApi in Millau runtime. * rialto: use upstream polkadot_client::RuntimeApiCollection --- bin/millau/node/Cargo.toml | 4 + bin/millau/node/src/chain_spec.rs | 21 ++-- bin/millau/node/src/service.rs | 42 ++++++-- bin/millau/runtime/Cargo.toml | 9 ++ bin/millau/runtime/src/lib.rs | 90 +++++++++++++++- bin/rialto/node/Cargo.toml | 9 ++ bin/rialto/node/src/chain_spec.rs | 16 ++- bin/rialto/node/src/service.rs | 111 +++++++++----------- bin/rialto/runtime/Cargo.toml | 10 ++ bin/rialto/runtime/src/lib.rs | 94 ++++++++++++++++- relays/bin-substrate/src/cli/encode_call.rs | 2 +- 11 files changed, 322 insertions(+), 86 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index b650bd478a62b..c4438d0cef3ee 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -23,9 +23,13 @@ pallet-bridge-messages = { path = "../../../modules/messages" } # Substrate Dependencies +beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" } +beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 05496bb64f639..fbfca8692fcb4 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -14,11 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use beefy_primitives::crypto::AuthorityId as BeefyId; use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BridgeRialtoMessagesConfig, BridgeWestendGrandpaConfig, - GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, - WASM_BINARY, + AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, + BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, + Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -57,10 +58,11 @@ where } /// Helper function to generate an authority key for Aura -pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { +pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, BeefyId, GrandpaId) { ( get_account_id_from_seed::(s), get_from_seed::(s), + get_from_seed::(s), get_from_seed::(s), ) } @@ -173,12 +175,12 @@ impl Alternative { } } -fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { - SessionKeys { aura, grandpa } +fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys { + SessionKeys { aura, beefy, grandpa } } fn testnet_genesis( - initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, + initial_authorities: Vec<(AccountId, AuraId, BeefyId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, @@ -191,12 +193,15 @@ fn testnet_genesis( balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, aura: AuraConfig { authorities: Vec::new() }, + beefy: BeefyConfig { authorities: Vec::new() }, grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: root_key }, session: SessionConfig { keys: initial_authorities .iter() - .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) + .map(|x| { + (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone(), x.3.clone())) + }) .collect::>(), }, bridge_westend_grandpa: BridgeWestendGrandpaConfig { diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 4085982494b8a..b01c0bfca9069 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -21,9 +21,10 @@ // ===================================================================================== // UPDATE GUIDE: // 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); -// 2) the only thing to keep from old code, is `rpc_extensions_builder` - we use our own custom -// RPCs; 3) fix compilation errors; -// 4) test :) +// 2) from old code keep `rpc_extensions_builder` - we use our own custom RPCs; +// 3) from old code keep the Beefy gadget; +// 4) fix compilation errors; +// 5) test :) // ===================================================================================== // ===================================================================================== // ===================================================================================== @@ -209,6 +210,7 @@ pub fn new_full(mut config: Configuration) -> Result } config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); + config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config()); let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -242,6 +244,8 @@ pub fn new_full(mut config: Configuration) -> Result let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); let shared_voter_state = SharedVoterState::empty(); + let (signed_commitment_sender, signed_commitment_stream) = + beefy_gadget::notification::BeefySignedCommitmentStream::channel(); let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; @@ -264,7 +268,7 @@ pub fn new_full(mut config: Configuration) -> Result Some(shared_authority_set.clone()), ); - Box::new(move |_, subscription_executor| { + Box::new(move |_, subscription_executor: sc_rpc::SubscriptionTaskExecutor| { let mut io = jsonrpc_core::IoHandler::default(); io.extend_with(SystemApi::to_delegate(FullSystem::new( client.clone(), @@ -278,9 +282,18 @@ pub fn new_full(mut config: Configuration) -> Result shared_authority_set.clone(), shared_voter_state.clone(), justification_stream.clone(), - subscription_executor, + subscription_executor.clone(), finality_proof_provider.clone(), ))); + io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( + beefy_gadget_rpc::BeefyRpcHandler::new( + signed_commitment_stream.clone(), + subscription_executor, + ), + )); + io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new( + client.clone(), + ))); Ok(io) }) }; @@ -292,7 +305,7 @@ pub fn new_full(mut config: Configuration) -> Result task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), rpc_extensions_builder, - backend, + backend: backend.clone(), system_rpc_tx, config, telemetry: telemetry.as_mut(), @@ -355,6 +368,23 @@ pub fn new_full(mut config: Configuration) -> Result let keystore = if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; + let beefy_params = beefy_gadget::BeefyParams { + client, + backend, + key_store: keystore.clone(), + network: network.clone(), + signed_commitment_sender, + min_block_delta: 4, + prometheus_registry: prometheus_registry.clone(), + }; + + // Start the BEEFY bridge gadget. + task_manager.spawn_essential_handle().spawn_blocking( + "beefy-gadget", + None, + beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params), + ); + let grandpa_config = sc_finality_grandpa::Config { // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index c8d7f0a159582..13195b95194ba 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -30,6 +30,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies +beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -37,7 +38,11 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -64,6 +69,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ + "beefy-primitives/std", "bp-header-chain/std", "bp-messages/std", "bp-millau/std", @@ -78,11 +84,14 @@ std = [ "frame-system/std", "pallet-aura/std", "pallet-balances/std", + "pallet-beefy/std", + "pallet-beefy-mmr/std", "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-token-swap/std", "pallet-grandpa/std", + "pallet-mmr/std", "pallet-randomness-collective-flip/std", "pallet-session/std", "pallet-shift-session-manager/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b713211b1e489..288ff9a47d601 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -34,19 +34,23 @@ pub mod rialto_messages; use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; +use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bridge_runtime_common::messages::{ source::estimate_message_dispatch_and_delivery_fee, MessageBridge, }; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; +use pallet_mmr_primitives::{ + DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, +}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{Block as BlockT, IdentityLookup, NumberFor, OpaqueKeys}, + traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; @@ -120,6 +124,7 @@ pub mod opaque { impl_opaque_keys! { pub struct SessionKeys { pub aura: Aura, + pub beefy: Beefy, pub grandpa: Grandpa, } } @@ -212,6 +217,11 @@ impl pallet_aura::Config for Runtime { type MaxAuthorities = MaxAuthorities; type DisabledValidators = (); } + +impl pallet_beefy::Config for Runtime { + type BeefyId = BeefyId; +} + impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); @@ -240,6 +250,40 @@ impl pallet_grandpa::Config for Runtime { type MaxAuthorities = MaxAuthorities; } +type MmrHash = ::Output; + +impl pallet_mmr::Config for Runtime { + const INDEXING_PREFIX: &'static [u8] = b"mmr"; + type Hashing = Keccak256; + type Hash = MmrHash; + type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; + type WeightInfo = (); + type LeafData = pallet_beefy_mmr::Pallet; +} + +parameter_types! { + /// Version of the produced MMR leaf. + /// + /// The version consists of two parts; + /// - `major` (3 bits) + /// - `minor` (5 bits) + /// + /// `major` should be updated only if decoding the previous MMR Leaf format from the payload + /// is not possible (i.e. backward incompatible change). + /// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE + /// encoding does not prevent old leafs from being decoded. + /// + /// Hence we expect `major` to be changed really rarely (think never). + /// See [`MmrLeafVersion`] type documentation for more details. + pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0); +} + +impl pallet_beefy_mmr::Config for Runtime { + type LeafVersion = LeafVersion; + type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; + type ParachainHeads = (); +} + parameter_types! { pub const MinimumPeriod: u64 = bp_millau::SLOT_DURATION / 2; } @@ -459,6 +503,11 @@ construct_runtime!( ShiftSessionManager: pallet_shift_session_manager::{Pallet}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, + // BEEFY Bridges support. + Beefy: pallet_beefy::{Pallet, Storage, Config}, + Mmr: pallet_mmr::{Pallet, Storage}, + MmrLeaf: pallet_beefy_mmr::{Pallet, Storage}, + // Rialto bridge modules. BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, @@ -603,6 +652,45 @@ impl_runtime_apis! { } } + impl beefy_primitives::BeefyApi for Runtime { + fn validator_set() -> ValidatorSet { + Beefy::validator_set() + } + } + + impl pallet_mmr_primitives::MmrApi for Runtime { + fn generate_proof(leaf_index: u64) + -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> + { + Mmr::generate_proof(leaf_index) + .map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof)) + } + + fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) + -> Result<(), MmrError> + { + pub type Leaf = < + ::LeafData as LeafDataProvider + >::LeafData; + + let leaf: Leaf = leaf + .into_opaque_leaf() + .try_decode() + .ok_or(MmrError::Verify)?; + Mmr::verify_leaf(leaf, proof) + } + + fn verify_proof_stateless( + root: MmrHash, + leaf: EncodableOpaqueLeaf, + proof: MmrProof + ) -> Result<(), MmrError> { + type MmrHashing = ::Hashing; + let node = DataOrHash::Data(leaf.into_opaque_leaf()); + pallet_mmr::verify_leaf_proof::(root, node, proof) + } + } + impl fg_primitives::GrandpaApi for Runtime { fn current_set_id() -> fg_primitives::SetId { Grandpa::current_set_id() diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index fd76fbf9a6170..2795f2eecaecc 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -28,10 +28,15 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies +beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" } +beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -70,6 +75,10 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } +# Polkadot Dependencies + +polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" } + # Polkadot (parachain) Dependencies polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index cadacad72da97..fb18a35a6af0e 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,12 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use beefy_primitives::crypto::AuthorityId as BeefyId; use bp_rialto::derive_account_from_millau_id; use polkadot_primitives::v1::{AssignmentId, ValidatorId}; use rialto_runtime::{ - AccountId, BabeConfig, BalancesConfig, BridgeMillauMessagesConfig, ConfigurationConfig, - GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, - WASM_BINARY, + AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, + ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, + SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -62,10 +63,11 @@ where /// Helper function to generate authority keys. pub fn get_authority_keys_from_seed( s: &str, -) -> (AccountId, BabeId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) { +) -> (AccountId, BabeId, BeefyId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) { ( get_account_id_from_seed::(s), get_from_seed::(s), + get_from_seed::(s), get_from_seed::(s), get_from_seed::(s), get_from_seed::(s), @@ -183,18 +185,20 @@ impl Alternative { fn session_keys( babe: BabeId, + beefy: BeefyId, grandpa: GrandpaId, para_validator: ValidatorId, para_assignment: AssignmentId, authority_discovery: AuthorityDiscoveryId, ) -> SessionKeys { - SessionKeys { babe, grandpa, para_validator, para_assignment, authority_discovery } + SessionKeys { babe, beefy, grandpa, para_validator, para_assignment, authority_discovery } } fn testnet_genesis( initial_authorities: Vec<( AccountId, BabeId, + BeefyId, GrandpaId, ValidatorId, AssignmentId, @@ -215,6 +219,7 @@ fn testnet_genesis( authorities: Vec::new(), epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), }, + beefy: BeefyConfig { authorities: Vec::new() }, grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: root_key }, session: SessionConfig { @@ -230,6 +235,7 @@ fn testnet_genesis( x.3.clone(), x.4.clone(), x.5.clone(), + x.6.clone(), ), ) }) diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs index fb774d86cca93..3349b09edb9f6 100644 --- a/bin/rialto/node/src/service.rs +++ b/bin/rialto/node/src/service.rs @@ -17,16 +17,11 @@ //! Rialto chain node service. //! //! The code is mostly copy of `service/src/lib.rs` file from Polkadot repository -//! without optional functions. - -// this warning comes from Error enum (sc_cli::Error in particular) && it isn't easy to use box -// there -#![allow(clippy::large_enum_variant)] -// this warning comes from `sc_service::PartialComponents` type -#![allow(clippy::type_complexity)] +//! without optional functions, and with BEEFY added on top. use crate::overseer::{OverseerGen, OverseerGenArgs}; +use polkadot_client::RuntimeApiCollection; use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; use polkadot_node_core_av_store::Config as AvailabilityConfig; use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; @@ -43,7 +38,7 @@ use sc_service::{config::PrometheusConfig, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_api::{ConstructRuntimeApi, HeaderT}; use sp_consensus::SelectChain; -use sp_runtime::traits::{BlakeTwo256, Block as BlockT}; +use sp_runtime::traits::Block as BlockT; use std::{sync::Arc, time::Duration}; use substrate_prometheus_endpoint::Registry; @@ -115,52 +110,6 @@ type FullBabeBlockImport = type FullBabeLink = sc_consensus_babe::BabeLink; type FullGrandpaLink = sc_finality_grandpa::LinkHalf; -/// A set of APIs that polkadot-like runtimes must implement. -/// -/// This is the copy of `polkadot_service::RuntimeApiCollection` with some APIs removed -/// (right now - MMR and BEEFY). -pub trait RequiredApiCollection: - sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::ApiExt - + sp_consensus_babe::BabeApi - + sp_finality_grandpa::GrandpaApi - + polkadot_primitives::v1::ParachainHost - + sp_block_builder::BlockBuilder - + frame_system_rpc_runtime_api::AccountNonceApi< - Block, - bp_rialto::AccountId, - rialto_runtime::Index, - > + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi - + sp_api::Metadata - + sp_offchain::OffchainWorkerApi - + sp_session::SessionKeys - + sp_authority_discovery::AuthorityDiscoveryApi -where - >::StateBackend: sp_api::StateBackend, -{ -} - -impl RequiredApiCollection for Api -where - Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::ApiExt - + sp_consensus_babe::BabeApi - + sp_finality_grandpa::GrandpaApi - + polkadot_primitives::v1::ParachainHost - + sp_block_builder::BlockBuilder - + frame_system_rpc_runtime_api::AccountNonceApi< - Block, - bp_rialto::AccountId, - rialto_runtime::Index, - > + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi - + sp_api::Metadata - + sp_offchain::OffchainWorkerApi - + sp_session::SessionKeys - + sp_authority_discovery::AuthorityDiscoveryApi, - >::StateBackend: sp_api::StateBackend, -{ -} - // If we're using prometheus, use a registry with a prefix of `polkadot`. fn set_prometheus_registry(config: &mut Configuration) -> Result<(), Error> { if let Some(PrometheusConfig { registry, .. }) = config.prometheus_config.as_mut() { @@ -170,6 +119,8 @@ fn set_prometheus_registry(config: &mut Configuration) -> Result<(), Error> { Ok(()) } +// Needed here for complex return type while `impl Trait` in type aliases is unstable. +#[allow(clippy::type_complexity)] pub fn new_partial( config: &mut Configuration, ) -> Result< @@ -184,7 +135,12 @@ pub fn new_partial( sc_rpc::DenyUnsafe, sc_rpc::SubscriptionTaskExecutor, ) -> Result, sc_service::Error>, - (FullBabeBlockImport, FullGrandpaLink, FullBabeLink), + ( + FullBabeBlockImport, + FullGrandpaLink, + FullBabeLink, + beefy_gadget::notification::BeefySignedCommitmentSender, + ), sc_finality_grandpa::SharedVoterState, std::time::Duration, Option, @@ -195,7 +151,7 @@ pub fn new_partial( where RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, >::RuntimeApi: - RequiredApiCollection>, + RuntimeApiCollection>, ExecutorDispatch: NativeExecutionDispatch + 'static, { set_prometheus_registry(config)?; @@ -282,7 +238,10 @@ where let shared_authority_set = grandpa_link.shared_authority_set().clone(); let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); - let import_setup = (block_import, grandpa_link, babe_link); + let (signed_commitment_sender, signed_commitment_stream) = + beefy_gadget::notification::BeefySignedCommitmentStream::channel(); + + let import_setup = (block_import, grandpa_link, babe_link, signed_commitment_sender); let rpc_setup = shared_voter_state.clone(); let slot_duration = babe_config.slot_duration(); @@ -316,14 +275,23 @@ where pool, deny_unsafe, ))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( + client.clone(), + ))); io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( shared_authority_set.clone(), shared_voter_state, justification_stream.clone(), - subscription_executor, + subscription_executor.clone(), finality_proof_provider, ))); + io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( + beefy_gadget_rpc::BeefyRpcHandler::new( + signed_commitment_stream.clone(), + subscription_executor, + ), + )); + io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new(client))); Ok(io) } @@ -361,7 +329,7 @@ async fn active_leaves( where RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, >::RuntimeApi: - RequiredApiCollection>, + RuntimeApiCollection>, ExecutorDispatch: NativeExecutionDispatch + 'static, { let best_block = select_chain.best_chain().await?; @@ -406,7 +374,7 @@ pub fn new_full( where RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, >::RuntimeApi: - RequiredApiCollection>, + RuntimeApiCollection>, ExecutorDispatch: NativeExecutionDispatch + 'static, { let is_collator = false; @@ -442,6 +410,8 @@ where // Substrate nodes. config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); + config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config()); + { use polkadot_network_bridge::{peer_sets_info, IsAuthority}; let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No }; @@ -536,7 +506,7 @@ where telemetry: telemetry.as_mut(), })?; - let (block_import, link_half, babe_link) = import_setup; + let (block_import, link_half, babe_link, signed_commitment_sender) = import_setup; let overseer_client = client.clone(); let spawner = task_manager.spawn_handle(); @@ -713,6 +683,23 @@ where let keystore_opt = if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; + let beefy_params = beefy_gadget::BeefyParams { + client: client.clone(), + backend: backend.clone(), + key_store: keystore_opt.clone(), + network: network.clone(), + signed_commitment_sender, + min_block_delta: 2, + prometheus_registry: prometheus_registry.clone(), + }; + + // Start the BEEFY bridge gadget. + task_manager.spawn_essential_handle().spawn_blocking( + "beefy-gadget", + None, + beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params), + ); + let config = sc_finality_grandpa::Config { // FIXME substrate#1578 make this available through chainspec gossip_duration: Duration::from_millis(1000), diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 36dc436ddca61..3c4ec1ebce1c4 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -31,6 +31,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies +beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -39,7 +40,11 @@ frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate" pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -76,6 +81,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ + "beefy-primitives/std", "bp-header-chain/std", "bp-message-dispatch/std", "bp-messages/std", @@ -93,10 +99,14 @@ std = [ "pallet-authority-discovery/std", "pallet-babe/std", "pallet-balances/std", + "pallet-beefy/std", + "pallet-beefy-mmr/std", "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-grandpa/std", + "pallet-mmr/std", + "pallet-mmr-primitives/std", "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5e7e47490d58d..0987184c73aa4 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -35,19 +35,23 @@ pub mod parachains; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; +use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bridge_runtime_common::messages::{ source::estimate_message_dispatch_and_delivery_fee, MessageBridge, }; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; +use pallet_mmr_primitives::{ + DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, +}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT, NumberFor, OpaqueKeys}, + traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; @@ -122,6 +126,7 @@ impl_opaque_keys! { pub struct SessionKeys { pub babe: Babe, pub grandpa: Grandpa, + pub beefy: Beefy, pub para_validator: Initializer, pub para_assignment: SessionInfo, pub authority_discovery: AuthorityDiscovery, @@ -242,6 +247,10 @@ impl pallet_babe::Config for Runtime { type WeightInfo = (); } +impl pallet_beefy::Config for Runtime { + type BeefyId = BeefyId; +} + impl pallet_bridge_dispatch::Config for Runtime { type Event = Event; type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); @@ -270,6 +279,38 @@ impl pallet_grandpa::Config for Runtime { type WeightInfo = (); } +impl pallet_mmr::Config for Runtime { + const INDEXING_PREFIX: &'static [u8] = b"mmr"; + type Hashing = Keccak256; + type Hash = ::Output; + type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; + type WeightInfo = (); + type LeafData = pallet_beefy_mmr::Pallet; +} + +parameter_types! { + /// Version of the produced MMR leaf. + /// + /// The version consists of two parts; + /// - `major` (3 bits) + /// - `minor` (5 bits) + /// + /// `major` should be updated only if decoding the previous MMR Leaf format from the payload + /// is not possible (i.e. backward incompatible change). + /// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE + /// encoding does not prevent old leafs from being decoded. + /// + /// Hence we expect `major` to be changed really rarely (think never). + /// See [`MmrLeafVersion`] type documentation for more details. + pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0); +} + +impl pallet_beefy_mmr::Config for Runtime { + type LeafVersion = LeafVersion; + type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; + type ParachainHeads = (); +} + parameter_types! { pub const MinimumPeriod: u64 = bp_rialto::SLOT_DURATION / 2; } @@ -463,6 +504,11 @@ construct_runtime!( Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, + // BEEFY Bridges support. + Beefy: pallet_beefy::{Pallet, Storage, Config}, + Mmr: pallet_mmr::{Pallet, Storage}, + MmrLeaf: pallet_beefy_mmr::{Pallet, Storage}, + // Millau bridge modules. BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, @@ -572,6 +618,45 @@ impl_runtime_apis! { } } + impl beefy_primitives::BeefyApi for Runtime { + fn validator_set() -> ValidatorSet { + Beefy::validator_set() + } + } + + impl pallet_mmr_primitives::MmrApi for Runtime { + fn generate_proof(leaf_index: u64) + -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> + { + Mmr::generate_proof(leaf_index) + .map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof)) + } + + fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) + -> Result<(), MmrError> + { + pub type Leaf = < + ::LeafData as LeafDataProvider + >::LeafData; + + let leaf: Leaf = leaf + .into_opaque_leaf() + .try_decode() + .ok_or(MmrError::Verify)?; + Mmr::verify_leaf(leaf, proof) + } + + fn verify_proof_stateless( + root: Hash, + leaf: EncodableOpaqueLeaf, + proof: MmrProof + ) -> Result<(), MmrError> { + type MmrHashing = ::Hashing; + let node = DataOrHash::Data(leaf.into_opaque_leaf()); + pallet_mmr::verify_leaf_proof::(root, node, proof) + } + } + impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { let header = BridgeMillauGrandpa::best_finalized(); @@ -1147,7 +1232,10 @@ mod tests { #[test] fn call_size() { - const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests - assert!(core::mem::size_of::() <= MAX_CALL_SIZE); + const DOT_MAX_CALL_SZ: usize = 230; + assert!(core::mem::size_of::>() <= DOT_MAX_CALL_SZ); + // FIXME: get this down to 230. https://github.com/paritytech/grandpa-bridge-gadget/issues/359 + const BEEFY_MAX_CALL_SZ: usize = 232; + assert!(core::mem::size_of::>() <= BEEFY_MAX_CALL_SZ); } } diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index ca0e6dd8abff1..e17854662e5c4 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -345,7 +345,7 @@ mod tests { // then assert!(format!("{:?}", call_hex).starts_with( - "0x0c030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + "0x0f030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" )) } From 44748dae22da9f28ebd66e0aac2e1c3866666bf9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Dec 2021 15:57:21 +0300 Subject: [PATCH 0608/1210] Fix storage parameter name computation (#1238) * fixed storage_parameter_key * added test for storage_parameter_key --- primitives/runtime/Cargo.toml | 3 +++ primitives/runtime/src/lib.rs | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 944f84a6c6835..7cc165fb4e9c4 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -22,6 +22,9 @@ sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = " 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] +hex-literal = "0.3" + [features] default = ["std"] std = [ diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 460f1b19dfe3f..051dc1f43c002 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -256,10 +256,22 @@ pub fn storage_map_final_key_identity( /// /// 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); + let mut buffer = Vec::with_capacity(1 + parameter_name.len() + 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()) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn storage_parameter_key_works() { + assert_eq!( + storage_parameter_key("MillauToRialtoConversionRate"), + StorageKey(hex_literal::hex!("58942375551bb0af1682f72786b59d04").to_vec()), + ); + } +} From d728c298b086ea77d1ca3d820c7ee35ccb4f9f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 3 Dec 2021 10:34:45 +0100 Subject: [PATCH 0609/1210] Enable offchain indexing for Rialto/Millau nodes (#1239) * Enable off-chain indexing for Rialto & Millau nodes * cargo fmt --all * cargo +nightly fmt --all * fmt is weird. --- relays/bin-substrate/src/chains/rialto_parachain.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index edd4ca3628540..9adcad2231961 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -45,8 +45,9 @@ impl CliEncodeCall for RialtoParachain { value: amount.0, }, ), - Call::BridgeSendMessage { .. } => - anyhow::bail!("Bridge messages are not (yet) supported here",), + Call::BridgeSendMessage { .. } => { + anyhow::bail!("Bridge messages are not (yet) supported here",) + }, }) } From 2ecca1bed12f218c3cd86577d352a1526f0b5582 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 3 Dec 2021 12:41:47 +0300 Subject: [PATCH 0610/1210] Update Rococo/Wococo version + prepare relay for Rococo<>Wococo bridge (#1241) * update Rococo version + create relayers fund account * start finality relay guards when complex relay is started --- primitives/chain-rococo/src/lib.rs | 5 +- primitives/chain-wococo/src/lib.rs | 4 +- .../src/cli/relay_headers_and_messages.rs | 157 +++++++++++------- relays/client-rococo/src/runtime.rs | 14 +- relays/client-wococo/src/runtime.rs | 14 +- 5 files changed, 124 insertions(+), 70 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index b3bbc91976dac..f4ee452119b1d 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -44,7 +44,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), authoring_version: 0, - spec_version: 9100, + spec_version: 9130, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, @@ -105,6 +105,9 @@ pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromRococoInboundLaneApi_unrewarded_relayers_state"; +/// Existential deposit on Rococo. +pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; + /// Weight of pay-dispatch-fee operation for inbound messages at Rococo chain. /// /// This value corresponds to the result of diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index fe2ce3a309a6b..14489351b828e 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -25,7 +25,9 @@ use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime -pub use bp_rococo::{WeightToFee, PAY_INBOUND_DISPATCH_FEE_WEIGHT, SESSION_LENGTH, VERSION}; +pub use bp_rococo::{ + WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, SESSION_LENGTH, VERSION, +}; /// Wococo Chain pub type Wococo = PolkadotLike; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 9d76a0296fb2c..7755df39ed554 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -29,12 +29,13 @@ use strum::VariantNames; use codec::Encode; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ - AccountIdOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, CallOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ - messages_lane::MessagesRelayParams, on_demand_headers::OnDemandHeadersRelay, + finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, + on_demand_headers::OnDemandHeadersRelay, }; use crate::{ @@ -138,8 +139,8 @@ macro_rules! select_bridge { use crate::chains::{ millau_messages_to_rialto::{ - standalone_metrics as left_to_right_standalone_metrics, run as left_to_right_messages, + standalone_metrics as left_to_right_standalone_metrics, update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, }, rialto_messages_to_millau::{ @@ -187,12 +188,10 @@ macro_rules! select_bridge { use crate::chains::{ rococo_messages_to_wococo::{ - standalone_metrics as left_to_right_standalone_metrics, run as left_to_right_messages, + standalone_metrics as left_to_right_standalone_metrics, }, - wococo_messages_to_rococo::{ - run as right_to_left_messages, - }, + wococo_messages_to_rococo::run as right_to_left_messages, }; async fn update_right_to_left_conversion_rate( @@ -212,19 +211,39 @@ macro_rules! select_bridge { } async fn left_create_account( - _left_client: Client, - _left_sign: ::AccountKeyPair, - _account_id: AccountIdOf, + left_client: Client, + left_sign: ::AccountKeyPair, + account_id: AccountIdOf, ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) + submit_signed_extrinsic( + left_client, + left_sign, + relay_rococo_client::runtime::Call::Balances( + relay_rococo_client::runtime::BalancesCall::transfer( + bp_rococo::AccountAddress::Id(account_id), + bp_rococo::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } async fn right_create_account( - _right_client: Client, - _right_sign: ::AccountKeyPair, - _account_id: AccountIdOf, + right_client: Client, + right_sign: ::AccountKeyPair, + account_id: AccountIdOf, ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) + submit_signed_extrinsic( + right_client, + right_sign, + relay_wococo_client::runtime::Call::Balances( + relay_wococo_client::runtime::BalancesCall::transfer( + bp_wococo::AccountAddress::Id(account_id), + bp_wococo::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } $generic @@ -250,8 +269,8 @@ macro_rules! select_bridge { use crate::chains::{ kusama_messages_to_polkadot::{ - standalone_metrics as left_to_right_standalone_metrics, run as left_to_right_messages, + standalone_metrics as left_to_right_standalone_metrics, update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, }, polkadot_messages_to_kusama::{ @@ -265,29 +284,17 @@ macro_rules! select_bridge { left_sign: ::AccountKeyPair, account_id: AccountIdOf, ) -> anyhow::Result<()> { - let left_genesis_hash = *left_client.genesis_hash(); - left_client - .submit_signed_extrinsic( - left_sign.public().into(), - move |_, transaction_nonce| { - Bytes( - Left::sign_transaction(left_genesis_hash, &left_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_kusama_client::runtime::Call::Balances( - relay_kusama_client::runtime::BalancesCall::transfer( - bp_kusama::AccountAddress::Id(account_id), - bp_kusama::EXISTENTIAL_DEPOSIT.into(), - ), - ), - transaction_nonce, - ), - ).encode() - ) - }, - ) - .await - .map(drop) - .map_err(|e| anyhow::format_err!("{}", e)) + submit_signed_extrinsic( + left_client, + left_sign, + relay_kusama_client::runtime::Call::Balances( + relay_kusama_client::runtime::BalancesCall::transfer( + bp_kusama::AccountAddress::Id(account_id), + bp_kusama::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } async fn right_create_account( @@ -295,29 +302,17 @@ macro_rules! select_bridge { right_sign: ::AccountKeyPair, account_id: AccountIdOf, ) -> anyhow::Result<()> { - let right_genesis_hash = *right_client.genesis_hash(); - right_client - .submit_signed_extrinsic( - right_sign.public().into(), - move |_, transaction_nonce| { - Bytes( - Right::sign_transaction(right_genesis_hash, &right_sign, relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( - relay_polkadot_client::runtime::Call::Balances( - relay_polkadot_client::runtime::BalancesCall::transfer( - bp_polkadot::AccountAddress::Id(account_id), - bp_polkadot::EXISTENTIAL_DEPOSIT.into(), - ), - ), - transaction_nonce, - ), - ).encode() - ) - }, - ) - .await - .map(drop) - .map_err(|e| anyhow::format_err!("{}", e)) + submit_signed_extrinsic( + right_client, + right_sign, + relay_polkadot_client::runtime::Call::Balances( + relay_polkadot_client::runtime::BalancesCall::transfer( + bp_polkadot::AccountAddress::Id(account_id), + bp_polkadot::EXISTENTIAL_DEPOSIT.into(), + ), + ), + ) + .await } $generic @@ -494,11 +489,17 @@ impl RelayHeadersAndMessages { } // start on-demand header relays + let left_to_right_finality = + LeftToRightFinality::new(right_client.clone(), right_sign.clone()); + let right_to_left_finality = + RightToLeftFinality::new(left_client.clone(), left_sign.clone()); + left_to_right_finality.start_relay_guards(); + right_to_left_finality.start_relay_guards(); let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), right_client.clone(), right_transactions_mortality, - LeftToRightFinality::new(right_client.clone(), right_sign.clone()), + left_to_right_finality, MAX_MISSING_LEFT_HEADERS_AT_RIGHT, params.shared.only_mandatory_headers, ); @@ -506,7 +507,7 @@ impl RelayHeadersAndMessages { right_client.clone(), left_client.clone(), left_transactions_mortality, - RightToLeftFinality::new(left_client.clone(), left_sign.clone()), + right_to_left_finality, MAX_MISSING_RIGHT_HEADERS_AT_LEFT, params.shared.only_mandatory_headers, ); @@ -561,3 +562,31 @@ impl RelayHeadersAndMessages { }) } } + +/// Sign and submit transaction with given call to the chain. +async fn submit_signed_extrinsic>( + client: Client, + sign: C::AccountKeyPair, + call: CallOf, +) -> anyhow::Result<()> +where + AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, + CallOf: Send, +{ + let genesis_hash = *client.genesis_hash(); + client + .submit_signed_extrinsic(sign.public().into(), move |_, transaction_nonce| { + Bytes( + C::sign_transaction( + genesis_hash, + &sign, + relay_substrate_client::TransactionEra::immortal(), + UnsignedTransaction::new(call, transaction_nonce), + ) + .encode(), + ) + }) + .await + .map(drop) + .map_err(|e| anyhow::format_err!("{}", e)) +} diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index effe6e5c60a9d..df69b0a6a9c34 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -17,9 +17,9 @@ //! Types that are specific to the Rococo runtime. use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::PolkadotLike; +use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; use bp_runtime::Chain; -use codec::{Decode, Encode}; +use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use scale_info::TypeInfo; @@ -66,6 +66,9 @@ pub enum Call { /// System pallet. #[codec(index = 0)] System(SystemCall), + /// Balances pallet. + #[codec(index = 4)] + Balances(BalancesCall), /// Wococo bridge pallet. #[codec(index = 41)] BridgeGrandpaWococo(BridgeGrandpaWococoCall), @@ -81,6 +84,13 @@ pub enum SystemCall { remark(Vec), } +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BalancesCall { + #[codec(index = 0)] + transfer(AccountAddress, Compact), +} + #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeGrandpaWococoCall { diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index 91d32d1aa76f7..38a40abd21208 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -17,9 +17,9 @@ //! Types that are specific to the Wococo runtime. use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::PolkadotLike; +use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; use bp_runtime::Chain; -use codec::{Decode, Encode}; +use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use scale_info::TypeInfo; @@ -66,6 +66,9 @@ pub enum Call { /// System pallet. #[codec(index = 0)] System(SystemCall), + /// Balances pallet. + #[codec(index = 4)] + Balances(BalancesCall), /// Rococo bridge pallet. #[codec(index = 40)] BridgeGrandpaRococo(BridgeGrandpaRococoCall), @@ -81,6 +84,13 @@ pub enum SystemCall { remark(Vec), } +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BalancesCall { + #[codec(index = 0)] + transfer(AccountAddress, Compact), +} + #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeGrandpaRococoCall { From bf4fbdf6d1778b5e4fa0defa8f8a145ff54292c3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 3 Dec 2021 14:43:33 +0300 Subject: [PATCH 0611/1210] Refactor finality relay helpers (#1220) * refactor finality relay helper definitions * add missing doc * removed commented code * fmt * disable rustfmt for macro * move best_finalized method const to relay chain def --- bin/millau/runtime/src/lib.rs | 8 - bin/rialto/runtime/src/lib.rs | 4 - primitives/chain-kusama/src/lib.rs | 4 - primitives/chain-millau/src/lib.rs | 2 - primitives/chain-polkadot/src/lib.rs | 4 - primitives/chain-rialto/src/lib.rs | 2 - primitives/chain-rococo/src/lib.rs | 4 - primitives/chain-westend/src/lib.rs | 4 - primitives/chain-wococo/src/lib.rs | 4 - primitives/runtime/src/chain.rs | 3 +- .../src/chains/kusama_headers_to_polkadot.rs | 91 ++----- .../src/chains/millau_headers_to_rialto.rs | 67 +----- relays/bin-substrate/src/chains/mod.rs | 12 - .../src/chains/polkadot_headers_to_kusama.rs | 91 ++----- .../src/chains/rialto_headers_to_millau.rs | 75 +----- .../src/chains/rococo_headers_to_wococo.rs | 91 ++----- .../src/chains/westend_headers_to_millau.rs | 80 +------ .../src/chains/wococo_headers_to_rococo.rs | 91 ++----- relays/bin-substrate/src/cli/relay_headers.rs | 16 +- .../src/cli/relay_headers_and_messages.rs | 34 ++- relays/client-kusama/src/lib.rs | 2 + relays/client-millau/src/lib.rs | 2 + relays/client-polkadot/src/lib.rs | 2 + relays/client-rialto-parachain/src/lib.rs | 2 + relays/client-rialto/src/lib.rs | 2 + relays/client-rococo/src/lib.rs | 2 + relays/client-substrate/src/chain.rs | 12 +- relays/client-substrate/src/guard.rs | 1 + relays/client-substrate/src/lib.rs | 5 +- relays/client-westend/src/lib.rs | 2 + relays/client-wococo/src/lib.rs | 2 + relays/lib-substrate-relay/Cargo.toml | 1 + .../src/finality_pipeline.rs | 222 ++++++++++-------- .../src/finality_source.rs | 90 +++---- .../src/finality_target.rs | 100 ++++---- relays/lib-substrate-relay/src/lib.rs | 1 + .../src/on_demand_headers.rs | 159 +++++-------- 37 files changed, 473 insertions(+), 821 deletions(-) rename relays/{client-substrate => lib-substrate-relay}/src/finality_source.rs (66%) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 288ff9a47d601..25cf48b6f7077 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -731,10 +731,6 @@ impl_runtime_apis! { let header = BridgeRialtoGrandpa::best_finalized(); (header.number, header.hash()) } - - fn is_known_header(hash: bp_rialto::Hash) -> bool { - BridgeRialtoGrandpa::is_known_header(hash) - } } impl bp_westend::WestendFinalityApi for Runtime { @@ -742,10 +738,6 @@ impl_runtime_apis! { let header = BridgeWestendGrandpa::best_finalized(); (header.number, header.hash()) } - - fn is_known_header(hash: bp_westend::Hash) -> bool { - BridgeWestendGrandpa::is_known_header(hash) - } } impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0987184c73aa4..7b9de28aa914a 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -662,10 +662,6 @@ impl_runtime_apis! { let header = BridgeMillauGrandpa::best_finalized(); (header.number, header.hash()) } - - fn is_known_header(hash: bp_millau::Hash) -> bool { - BridgeMillauGrandpa::is_known_header(hash) - } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 9a6eb66d22865..f52d03f9f2be3 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -90,8 +90,6 @@ pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the `KusamaFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; -/// Name of the `KusamaFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_is_known_header"; /// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -124,8 +122,6 @@ sp_api::decl_runtime_apis! { pub trait KusamaFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Kusama chain. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 0092f7092bc0d..ba68467021348 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -298,8 +298,6 @@ sp_api::decl_runtime_apis! { pub trait MillauFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Millau chain. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 26bad1ea8656d..36d15ea6e426a 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -90,8 +90,6 @@ pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the `PolkadotFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; -/// Name of the `PolkadotFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_is_known_header"; /// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -124,8 +122,6 @@ sp_api::decl_runtime_apis! { pub trait PolkadotFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Polkadot chain. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 6c4e48301e3bb..3a0f7045c0888 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -271,8 +271,6 @@ sp_api::decl_runtime_apis! { pub trait RialtoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Rialto chain. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index f4ee452119b1d..e5b3647f32bc7 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -79,8 +79,6 @@ pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; /// Name of the `RococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; -/// Name of the `RococoFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_is_known_header"; /// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -125,8 +123,6 @@ sp_api::decl_runtime_apis! { pub trait RococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Rococo chain. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 8beb897f59a15..ffc0bf0fca109 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -90,8 +90,6 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - /// Name of the `WestendFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; -/// Name of the `WestendFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_is_known_header"; /// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -131,8 +129,6 @@ sp_api::decl_runtime_apis! { pub trait WestendFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Westend chain. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 14489351b828e..b16dff388c248 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -44,8 +44,6 @@ pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; /// Name of the `WococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; -/// Name of the `WococoFinalityApi::is_known_header` runtime method. -pub const IS_KNOWN_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_is_known_header"; /// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime /// method. @@ -78,8 +76,6 @@ sp_api::decl_runtime_apis! { pub trait WococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); - /// Returns true if the header is known to the runtime. - fn is_known_header(hash: Hash) -> bool; } /// Outbound message lane API for messages that are sent to Wococo chain. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index e24694bf8b0f8..e963b633b7f56 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use frame_support::Parameter; -use num_traits::{AsPrimitive, Bounded, CheckedSub, SaturatingAdd, Zero}; +use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ traits::{ AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, @@ -46,6 +46,7 @@ pub trait Chain: Send + Sync + 'static { + MaybeMallocSizeOf + AsPrimitive + Default + + Saturating // original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but // `sp_runtime::generic::Era` requires block number -> `u64` conversion. + Into; diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index ce631ef41e0ac..afa22aec9e470 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -16,17 +16,8 @@ //! Kusama-to-Polkadot headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_kusama_client::{Kusama, SyncHeader as KusamaSyncHeader}; -use relay_polkadot_client::{Polkadot, SigningParams as PolkadotSigningParams}; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; +use sp_core::Pair; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -35,77 +26,37 @@ use substrate_relay_helper::finality_pipeline::{ /// DOT, but let's round up to 30 DOT here. pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000; -/// Kusama-to-Polkadot finality sync pipeline. -pub(crate) type FinalityPipelineKusamaFinalityToPolkadot = - SubstrateFinalityToSubstrate; - +/// Description of Kusama -> Polkadot finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct KusamaFinalityToPolkadot { - finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot, -} - -impl KusamaFinalityToPolkadot { - pub fn new(target_client: Client, target_sign: PolkadotSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineKusamaFinalityToPolkadot::new( - target_client, - target_sign, - ), - } - } -} +pub struct KusamaFinalityToPolkadot; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + KusamaFinalityToPolkadot, + KusamaFinalityToPolkadotCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa, + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof +); impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { - type FinalitySyncPipeline = FinalityPipelineKusamaFinalityToPolkadot; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; + type SourceChain = relay_kusama_client::Kusama; + type TargetChain = relay_polkadot_client::Polkadot; - type TargetChain = Polkadot; - - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } + type SubmitFinalityProofCallBuilder = KusamaFinalityToPolkadotCallBuilder; + type TransactionSignScheme = relay_polkadot_client::Polkadot; - fn start_relay_guards(&self) { + fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + ) { relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), + target_client.clone(), bp_polkadot::VERSION.spec_version, ); relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + target_client.clone(), + transaction_params.transactions_signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } - - fn transactions_author(&self) -> bp_polkadot::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: bp_runtime::IndexOf, - header: KusamaSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } } #[cfg(test)] diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 14a0430f6a918..584f0a9bb1d8b 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -16,65 +16,22 @@ //! Millau-to-Rialto headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_millau_client::{Millau, SyncHeader as MillauSyncHeader}; -use relay_rialto_client::{Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, + DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }; -/// Millau-to-Rialto finality sync pipeline. -pub(crate) type FinalityPipelineMillauToRialto = - SubstrateFinalityToSubstrate; - +/// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct MillauFinalityToRialto { - finality_pipeline: FinalityPipelineMillauToRialto, -} - -impl MillauFinalityToRialto { - pub fn new(target_client: Client, target_sign: RialtoSigningParams) -> Self { - Self { finality_pipeline: FinalityPipelineMillauToRialto::new(target_client, target_sign) } - } -} +pub struct MillauFinalityToRialto; impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { - type FinalitySyncPipeline = FinalityPipelineMillauToRialto; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - - type TargetChain = Rialto; - - fn transactions_author(&self) -> bp_rialto::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: MillauSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = rialto_runtime::BridgeGrandpaMillauCall::submit_finality_proof { - finality_target: Box::new(header.into_inner()), - justification: proof, - } - .into(); - - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } + type SourceChain = relay_millau_client::Millau; + type TargetChain = relay_rialto_client::Rialto; + + type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::MillauGrandpaInstance, + >; + type TransactionSignScheme = relay_rialto_client::Rialto; } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index e9cb2d9b737f1..1bc0115b5b05e 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -39,18 +39,6 @@ mod rococo; mod westend; mod wococo; -use relay_utils::metrics::{MetricsParams, StandaloneMetric}; - -pub(crate) fn add_polkadot_kusama_price_metrics( - params: MetricsParams, -) -> anyhow::Result { - substrate_relay_helper::helpers::token_price_metric(polkadot::TOKEN_ID)? - .register_and_spawn(¶ms.registry)?; - substrate_relay_helper::helpers::token_price_metric(kusama::TOKEN_ID)? - .register_and_spawn(¶ms.registry)?; - Ok(params) -} - #[cfg(test)] mod tests { use crate::cli::{encode_call, send_message}; diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index b1948b234cc31..695e0ec3ee6b1 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -16,17 +16,8 @@ //! Polkadot-to-Kusama headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_kusama_client::{Kusama, SigningParams as KusamaSigningParams}; -use relay_polkadot_client::{Polkadot, SyncHeader as PolkadotSyncHeader}; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; +use sp_core::Pair; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -35,77 +26,37 @@ use substrate_relay_helper::finality_pipeline::{ /// KSM, but let's round up to 0.1 KSM here. pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000; -/// Polkadot-to-Kusama finality sync pipeline. -pub(crate) type FinalityPipelinePolkadotFinalityToKusama = - SubstrateFinalityToSubstrate; - +/// Description of Polkadot -> Kusama finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct PolkadotFinalityToKusama { - finality_pipeline: FinalityPipelinePolkadotFinalityToKusama, -} - -impl PolkadotFinalityToKusama { - pub fn new(target_client: Client, target_sign: KusamaSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelinePolkadotFinalityToKusama::new( - target_client, - target_sign, - ), - } - } -} +pub struct PolkadotFinalityToKusama; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + PolkadotFinalityToKusama, + PolkadotFinalityToKusamaCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotGrandpa, + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof +); impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { - type FinalitySyncPipeline = FinalityPipelinePolkadotFinalityToKusama; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - - type TargetChain = Kusama; + type SourceChain = relay_polkadot_client::Polkadot; + type TargetChain = relay_kusama_client::Kusama; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } + type SubmitFinalityProofCallBuilder = PolkadotFinalityToKusamaCallBuilder; + type TransactionSignScheme = relay_kusama_client::Kusama; - fn start_relay_guards(&self) { + fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + ) { relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), + target_client.clone(), bp_kusama::VERSION.spec_version, ); relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + target_client.clone(), + transaction_params.transactions_signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } - - fn transactions_author(&self) -> bp_kusama::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: bp_runtime::IndexOf, - header: PolkadotSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } } #[cfg(test)] diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 7e76f403c55aa..a433f3562a703 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -16,73 +16,22 @@ //! Rialto-to-Millau headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_rialto_client::{Rialto, SyncHeader as RialtoSyncHeader}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, + DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }; -/// Rialto-to-Millau finality sync pipeline. -pub(crate) type FinalityPipelineRialtoFinalityToMillau = - SubstrateFinalityToSubstrate; - +/// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] -pub struct RialtoFinalityToMillau { - finality_pipeline: FinalityPipelineRialtoFinalityToMillau, -} - -impl RialtoFinalityToMillau { - pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineRialtoFinalityToMillau::new( - target_client, - target_sign, - ), - } - } -} +pub struct RialtoFinalityToMillau; impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { - type FinalitySyncPipeline = FinalityPipelineRialtoFinalityToMillau; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - - type TargetChain = Millau; - - fn transactions_author(&self) -> bp_millau::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: RialtoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >::submit_finality_proof { - finality_target: Box::new(header.into_inner()), - justification: proof, - } - .into(); - - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } + type SourceChain = relay_rialto_client::Rialto; + type TargetChain = relay_millau_client::Millau; + + type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::RialtoGrandpaInstance, + >; + type TransactionSignScheme = relay_millau_client::Millau; } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index ec98cec1ec1e9..0b6608b99becd 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -16,89 +16,40 @@ //! Rococo-to-Wococo headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_rococo_client::{Rococo, SyncHeader as RococoSyncHeader}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; - use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; -/// Rococo-to-Wococo finality sync pipeline. -pub(crate) type FinalityPipelineRococoFinalityToWococo = - SubstrateFinalityToSubstrate; +use sp_core::Pair; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +/// Description of Rococo -> Wococo finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct RococoFinalityToWococo { - finality_pipeline: FinalityPipelineRococoFinalityToWococo, -} - -impl RococoFinalityToWococo { - pub fn new(target_client: Client, target_sign: WococoSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineRococoFinalityToWococo::new( - target_client, - target_sign, - ), - } - } -} +pub struct RococoFinalityToWococo; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + RococoFinalityToWococo, + RococoFinalityToWococoCallBuilder, + relay_wococo_client::runtime::Call::BridgeGrandpaRococo, + relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof +); impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { - type FinalitySyncPipeline = FinalityPipelineRococoFinalityToWococo; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - - type TargetChain = Wococo; + type SourceChain = relay_rococo_client::Rococo; + type TargetChain = relay_wococo_client::Wococo; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } + type SubmitFinalityProofCallBuilder = RococoFinalityToWococoCallBuilder; + type TransactionSignScheme = relay_wococo_client::Wococo; - fn start_relay_guards(&self) { + fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + ) { relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), + target_client.clone(), bp_wococo::VERSION.spec_version, ); relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + target_client.clone(), + transaction_params.transactions_signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } - - fn transactions_author(&self) -> bp_wococo::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: RococoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_wococo_client::runtime::Call::BridgeGrandpaRococo( - relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } } diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 211aa9da9bfe3..2ec20a027ff5f 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -16,78 +16,22 @@ //! Westend-to-Millau headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_millau_client::{Millau, SigningParams as MillauSigningParams}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use relay_westend_client::{SyncHeader as WestendSyncHeader, Westend}; use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, + DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }; -/// Westend-to-Millau finality sync pipeline. -pub(crate) type FinalityPipelineWestendFinalityToMillau = - SubstrateFinalityToSubstrate; - +/// Description of Westend -> Millau finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct WestendFinalityToMillau { - finality_pipeline: FinalityPipelineWestendFinalityToMillau, -} - -impl WestendFinalityToMillau { - pub fn new(target_client: Client, target_sign: MillauSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineWestendFinalityToMillau::new( - target_client, - target_sign, - ), - } - } -} +pub struct WestendFinalityToMillau; impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { - type FinalitySyncPipeline = FinalityPipelineWestendFinalityToMillau; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; - - type TargetChain = Millau; - - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } - - fn transactions_author(&self) -> bp_millau::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: WestendSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >::submit_finality_proof { - finality_target: Box::new(header.into_inner()), - justification: proof, - } - .into(); - - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } + type SourceChain = relay_westend_client::Westend; + type TargetChain = relay_millau_client::Millau; + + type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WestendGrandpaInstance, + >; + type TransactionSignScheme = relay_millau_client::Millau; } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index fe17976d06a86..276a5b84da306 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -16,17 +16,8 @@ //! Wococo-to-Rococo headers sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_header_chain::justification::GrandpaJustification; -use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_utils::metrics::MetricsParams; -use relay_wococo_client::{SyncHeader as WococoSyncHeader, Wococo}; -use substrate_relay_helper::finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, -}; +use sp_core::Pair; +use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -35,77 +26,37 @@ use substrate_relay_helper::finality_pipeline::{ /// Note that this is in plancks, so this corresponds to `1500 UNITS`. pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000; -/// Wococo-to-Rococo finality sync pipeline. -pub(crate) type FinalityPipelineWococoFinalityToRococo = - SubstrateFinalityToSubstrate; - +/// Description of Wococo -> Rococo finalized headers bridge. #[derive(Clone, Debug)] -pub(crate) struct WococoFinalityToRococo { - finality_pipeline: FinalityPipelineWococoFinalityToRococo, -} - -impl WococoFinalityToRococo { - pub fn new(target_client: Client, target_sign: RococoSigningParams) -> Self { - Self { - finality_pipeline: FinalityPipelineWococoFinalityToRococo::new( - target_client, - target_sign, - ), - } - } -} +pub struct WococoFinalityToRococo; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + WococoFinalityToRococo, + WococoFinalityToRococoCallBuilder, + relay_rococo_client::runtime::Call::BridgeGrandpaWococo, + relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof +); impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { - type FinalitySyncPipeline = FinalityPipelineWococoFinalityToRococo; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - - type TargetChain = Rococo; + type SourceChain = relay_wococo_client::Wococo; + type TargetChain = relay_rococo_client::Rococo; - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - crate::chains::add_polkadot_kusama_price_metrics::(params) - } + type SubmitFinalityProofCallBuilder = WococoFinalityToRococoCallBuilder; + type TransactionSignScheme = relay_rococo_client::Rococo; - fn start_relay_guards(&self) { + fn start_relay_guards( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + ) { relay_substrate_client::guard::abort_on_spec_version_change( - self.finality_pipeline.target_client.clone(), + target_client.clone(), bp_rococo::VERSION.spec_version, ); relay_substrate_client::guard::abort_when_account_balance_decreased( - self.finality_pipeline.target_client.clone(), - self.transactions_author(), + target_client.clone(), + transaction_params.transactions_signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } - - fn transactions_author(&self) -> bp_rococo::AccountId { - (*self.finality_pipeline.target_sign.public().as_array_ref()).into() - } - - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: IndexOf, - header: WococoSyncHeader, - proof: GrandpaJustification, - ) -> Bytes { - let call = relay_rococo_client::runtime::Call::BridgeGrandpaWococo( - relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( - Box::new(header.into_inner()), - proof, - ), - ); - let genesis_hash = *self.finality_pipeline.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.finality_pipeline.target_sign, - era, - UnsignedTransaction::new(call, transaction_nonce), - ); - - Bytes(transaction.encode()) - } } #[cfg(test)] diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 82c55965a991a..a8179478f810a 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -121,18 +121,22 @@ impl RelayHeaders { let target_client = self.target.to_client::().await?; let target_transactions_mortality = self.target_sign.target_transactions_mortality; let target_sign = self.target_sign.to_keypair::()?; - let metrics_params = Finality::customize_metrics(self.prometheus_params.into())?; + + let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - let finality = Finality::new(target_client.clone(), target_sign); - finality.start_relay_guards(); + let target_transactions_params = + substrate_relay_helper::finality_pipeline::TransactionParams { + transactions_signer: target_sign, + transactions_mortality: target_transactions_mortality, + }; + Finality::start_relay_guards(&target_client, &target_transactions_params); - substrate_relay_helper::finality_pipeline::run( - finality, + substrate_relay_helper::finality_pipeline::run::( source_client, target_client, self.only_mandatory_headers, - target_transactions_mortality, + target_transactions_params, metrics_params, ) .await diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 7755df39ed554..86b2fbfb4d1b4 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -489,25 +489,35 @@ impl RelayHeadersAndMessages { } // start on-demand header relays - let left_to_right_finality = - LeftToRightFinality::new(right_client.clone(), right_sign.clone()); - let right_to_left_finality = - RightToLeftFinality::new(left_client.clone(), left_sign.clone()); - left_to_right_finality.start_relay_guards(); - right_to_left_finality.start_relay_guards(); - let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( + let left_to_right_transaction_params = + substrate_relay_helper::finality_pipeline::TransactionParams { + transactions_mortality: right_transactions_mortality, + transactions_signer: right_sign.clone(), + }; + let right_to_left_transaction_params = + substrate_relay_helper::finality_pipeline::TransactionParams { + transactions_mortality: left_transactions_mortality, + transactions_signer: left_sign.clone(), + }; + LeftToRightFinality::start_relay_guards( + &right_client, + &left_to_right_transaction_params, + ); + RightToLeftFinality::start_relay_guards( + &left_client, + &right_to_left_transaction_params, + ); + let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( left_client.clone(), right_client.clone(), - right_transactions_mortality, - left_to_right_finality, + left_to_right_transaction_params, MAX_MISSING_LEFT_HEADERS_AT_RIGHT, params.shared.only_mandatory_headers, ); - let right_to_left_on_demand_headers = OnDemandHeadersRelay::new( + let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::( right_client.clone(), left_client.clone(), - left_transactions_mortality, - right_to_left_finality, + right_to_left_transaction_params, MAX_MISSING_RIGHT_HEADERS_AT_LEFT, params.shared.only_mandatory_headers, ); diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index a93726620ff61..b1ea0f5fefbf7 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -48,6 +48,8 @@ impl ChainBase for Kusama { impl Chain for Kusama { const NAME: &'static str = "Kusama"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 3f1aba1f3b372..e7ee54afb0846 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -46,6 +46,8 @@ impl ChainBase for Millau { impl Chain for Millau { const NAME: &'static str = "Millau"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index e6ceabf583e0b..e5c7f62fa1724 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -48,6 +48,8 @@ impl ChainBase for Polkadot { impl Chain for Polkadot { const NAME: &'static str = "Polkadot"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index ca299a0eeb78b..b34154393a1b1 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -41,6 +41,8 @@ impl ChainBase for RialtoParachain { impl Chain for RialtoParachain { const NAME: &'static str = "RialtoParachain"; + // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 42ed8bce3bd9b..60c6e9388b69b 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -46,6 +46,8 @@ impl ChainBase for Rialto { impl Chain for Rialto { const NAME: &'static str = "Rialto"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index ad61e3cfd6437..7ee51730e9961 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -51,6 +51,8 @@ impl ChainBase for Rococo { impl Chain for Rococo { const NAME: &'static str = "Rococo"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 75789ce37f308..97063c15c8606 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -32,6 +32,13 @@ use std::{fmt::Debug, time::Duration}; pub trait Chain: ChainBase + Clone { /// Chain name. const NAME: &'static str; + /// Name of the runtime API method that is returning best known finalized header number + /// and hash (as tuple). + /// + /// Keep in mind that this method is normally provided by the other chain, which is + /// bridged with this chain. + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str; + /// Average block interval. /// /// How often blocks are produced on that chain. It's suggested to set this value @@ -45,7 +52,7 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Clone + Dispatchable + Debug; + type Call: Clone + Dispatchable + Debug + Send; /// Type that is used by the chain, to convert from weight to fee. type WeightToFee: WeightToFeePolynomial; @@ -102,6 +109,9 @@ impl UnsignedTransaction { } } +/// Account key pair used by transactions signing scheme. +pub type AccountKeyPairOf = ::AccountKeyPair; + /// Substrate-based chain transactions signing scheme. pub trait TransactionSignScheme { /// Chain that this scheme is to be used. diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index a064e36234007..93b76bdf9f07e 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -206,6 +206,7 @@ mod tests { impl Chain for TestChain { const NAME: &'static str = "Test"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); const STORAGE_PROOF_OVERHEAD: u32 = 0; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 51ddf852b9b6f..f03b79228bf08 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -24,7 +24,6 @@ mod error; mod rpc; mod sync_header; -pub mod finality_source; pub mod guard; pub mod metrics; @@ -32,8 +31,8 @@ use std::time::Duration; pub use crate::{ chain::{ - BlockWithJustification, CallOf, Chain, ChainWithBalances, TransactionSignScheme, - TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, + AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, + TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, }, client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index c719d6ea55364..6d43aa837b29b 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -44,6 +44,8 @@ impl ChainBase for Westend { impl Chain for Westend { const NAME: &'static str = "Westend"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index d61915ec12370..a15ff469991b1 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -51,6 +51,8 @@ impl ChainBase for Wococo { impl Chain for Wococo { const NAME: &'static str = "Wococo"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 5bee10856daa3..89d03803b35f6 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -27,6 +27,7 @@ relay-utils = { path = "../utils" } messages-relay = { path = "../messages" } relay-substrate-client = { path = "../client-substrate" } +pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } bp-runtime = { path = "../../primitives/runtime" } diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index cdfbb3354d274..1266ed59ed00e 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -14,18 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Substrate-to-Substrate headers sync entrypoint. +//! Types and functions intended to ease adding of new Substrate -> Substrate +//! finality proofs synchronization pipelines. -use crate::{finality_target::SubstrateFinalityTarget, STALL_TIMEOUT}; +use crate::{finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget}; use bp_header_chain::justification::GrandpaJustification; -use bp_runtime::AccountIdOf; -use finality_relay::{FinalitySyncParams, FinalitySyncPipeline}; +use finality_relay::FinalitySyncPipeline; +use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - finality_source::FinalitySource, BlockNumberOf, Chain, Client, HashOf, SyncHeader, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, + HashOf, HeaderOf, SyncHeader, TransactionSignScheme, }; -use relay_utils::{metrics::MetricsParams, BlockNumberBase}; -use sp_core::Bytes; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; use std::{fmt::Debug, marker::PhantomData}; /// Default limit of recent finality proofs. @@ -34,130 +36,152 @@ use std::{fmt::Debug, marker::PhantomData}; /// Substrate+GRANDPA based chains (good to know). pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; -/// Headers sync pipeline for Substrate <-> Substrate relays. -pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { - /// Pipeline for syncing finalized Source chain headers to Target chain. - type FinalitySyncPipeline: FinalitySyncPipeline; - - /// Name of the runtime method that returns id of best finalized source header at target chain. - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; +/// Submit-finality-proofs transaction creation parameters. +#[derive(Clone, Debug)] +pub struct TransactionParams { + /// Transactions author. + pub transactions_signer: TS, + /// Transactions mortality. + pub transactions_mortality: Option, +} - /// Chain with GRANDPA bridge pallet. +/// Substrate -> Substrate finality proofs synchronization pipeline. +pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { + /// Headers of this chain are submitted to the `TargetChain`. + type SourceChain: Chain; + /// Headers of the `SourceChain` are submitted to this chain. type TargetChain: Chain; - /// Customize metrics exposed by headers sync loop. - fn customize_metrics(params: MetricsParams) -> anyhow::Result { - Ok(params) + /// How submit finality proof call is built? + type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder; + /// Scheme used to sign target chain transactions. + type TransactionSignScheme: TransactionSignScheme; + + /// Add relay guards if required. + fn start_relay_guards( + _target_client: &Client, + _transaction_params: &TransactionParams>, + ) { } +} - /// Start finality relay guards. - /// - /// Different finality bridges may have different set of guards - e.g. on ephemeral chains we - /// don't need a version guards, on test chains we don't care that much about relayer account - /// balance, ... So the implementation is left to the specific bridges. - fn start_relay_guards(&self) {} - - /// Returns id of account that we're using to sign transactions at target chain. - fn transactions_author(&self) -> AccountIdOf; - - /// Make submit header transaction. - fn make_submit_finality_proof_transaction( - &self, - era: bp_runtime::TransactionEraOf, - transaction_nonce: bp_runtime::IndexOf, - header: ::Header, - proof: ::FinalityProof, - ) -> Bytes; +/// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`. +#[derive(Clone, Debug)] +pub struct FinalitySyncPipelineAdapter { + _phantom: PhantomData

, } -/// Substrate-to-Substrate finality proof pipeline. -#[derive(Clone)] -pub struct SubstrateFinalityToSubstrate { - /// Client for the target chain. - pub target_client: Client, - /// Data required to sign target chain transactions. - pub target_sign: TargetSign, - /// Unused generic arguments dump. - _marker: PhantomData, +impl FinalitySyncPipeline for FinalitySyncPipelineAdapter

{ + const SOURCE_NAME: &'static str = P::SourceChain::NAME; + const TARGET_NAME: &'static str = P::TargetChain::NAME; + + type Hash = HashOf; + type Number = BlockNumberOf; + type Header = relay_substrate_client::SyncHeader>; + type FinalityProof = GrandpaJustification>; } -impl Debug - for SubstrateFinalityToSubstrate -{ - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.debug_struct("SubstrateFinalityToSubstrate") - .field("target_client", &self.target_client) - .finish() - } +/// Different ways of building `submit_finality_proof` calls. +pub trait SubmitFinalityProofCallBuilder { + /// Given source chain header and its finality proofs, build call of `submit_finality_proof` + /// function of bridge GRANDPA module at the target chain. + fn build_submit_finality_proof_call( + header: SyncHeader>, + proof: GrandpaJustification>, + ) -> CallOf; } -impl - SubstrateFinalityToSubstrate -{ - /// Create new Substrate-to-Substrate headers pipeline. - pub fn new(target_client: Client, target_sign: TargetSign) -> Self { - SubstrateFinalityToSubstrate { target_client, target_sign, _marker: Default::default() } - } +/// Building `submit_finality_proof` call when you have direct access to the target +/// chain runtime. +pub struct DirectSubmitFinalityProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, } -impl FinalitySyncPipeline - for SubstrateFinalityToSubstrate +impl SubmitFinalityProofCallBuilder

for DirectSubmitFinalityProofCallBuilder where - SourceChain: Clone + Chain + Debug, - BlockNumberOf: BlockNumberBase, - TargetChain: Clone + Chain + Debug, - TargetSign: 'static + Clone + Send + Sync, + P: SubstrateFinalitySyncPipeline, + R: BridgeGrandpaConfig, + I: 'static, + R::BridgedChain: bp_runtime::Chain

>, + CallOf: From>, { - const SOURCE_NAME: &'static str = SourceChain::NAME; - const TARGET_NAME: &'static str = TargetChain::NAME; + fn build_submit_finality_proof_call( + header: SyncHeader>, + proof: GrandpaJustification>, + ) -> CallOf { + BridgeGrandpaCall::::submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof, + } + .into() + } +} - type Hash = HashOf; - type Number = BlockNumberOf; - type Header = SyncHeader; - type FinalityProof = GrandpaJustification; +/// Macro that generates `SubmitFinalityProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of target chain runtime. In this case you +/// should provide "name" of the call variant for the bridge GRANDPA calls and the "name" of +/// the variant for the `submit_finality_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_submit_finality_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => { + pub struct $mocked_builder; + + impl $crate::finality_pipeline::SubmitFinalityProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_submit_finality_proof_call( + header: relay_substrate_client::SyncHeader< + relay_substrate_client::HeaderOf< + <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain + > + >, + proof: bp_header_chain::justification::GrandpaJustification< + relay_substrate_client::HeaderOf< + <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain + > + >, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::TargetChain + > { + $bridge_grandpa($submit_finality_proof(Box::new(header.into_inner()), proof)) + } + } + }; } -/// Run Substrate-to-Substrate finality sync. -pub async fn run( - pipeline: P, - source_client: Client, - target_client: Client, +/// Run Substrate-to-Substrate finality sync loop. +pub async fn run( + source_client: Client, + target_client: Client, only_mandatory_headers: bool, - transactions_mortality: Option, + transaction_params: TransactionParams>, metrics_params: MetricsParams, ) -> anyhow::Result<()> where - P: SubstrateFinalitySyncPipeline, - P::FinalitySyncPipeline: FinalitySyncPipeline< - Hash = HashOf, - Number = BlockNumberOf, - Header = SyncHeader, - FinalityProof = GrandpaJustification, - >, - SourceChain: Clone + Chain, - BlockNumberOf: BlockNumberBase, - TargetChain: Clone + Chain, + AccountIdOf: From< as Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { log::info!( target: "bridge", "Starting {} -> {} finality proof relay", - SourceChain::NAME, - TargetChain::NAME, + P::SourceChain::NAME, + P::TargetChain::NAME, ); finality_relay::run( - FinalitySource::new(source_client, None), - SubstrateFinalityTarget::new(target_client, pipeline, transactions_mortality), - FinalitySyncParams { + SubstrateFinalitySource::

::new(source_client, None), + SubstrateFinalityTarget::

::new(target_client, transaction_params.clone()), + finality_relay::FinalitySyncParams { tick: std::cmp::max( - SourceChain::AVERAGE_BLOCK_INTERVAL, - TargetChain::AVERAGE_BLOCK_INTERVAL, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, - stall_timeout: relay_substrate_client::transaction_stall_timeout( - transactions_mortality, - TargetChain::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, + stall_timeout: transaction_stall_timeout( + transaction_params.transactions_mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + crate::STALL_TIMEOUT, ), only_mandatory_headers, }, diff --git a/relays/client-substrate/src/finality_source.rs b/relays/lib-substrate-relay/src/finality_source.rs similarity index 66% rename from relays/client-substrate/src/finality_source.rs rename to relays/lib-substrate-relay/src/finality_source.rs index 98526de178cb3..804d3212930d4 100644 --- a/relays/client-substrate/src/finality_source.rs +++ b/relays/lib-substrate-relay/src/finality_source.rs @@ -16,49 +16,59 @@ //! Default generic implementation of finality source for basic Substrate client. -use crate::{ - chain::{BlockWithJustification, Chain}, - client::Client, - error::Error, - sync_header::SyncHeader, -}; +use crate::finality_pipeline::{FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; use codec::Decode; -use finality_relay::{FinalitySyncPipeline, SourceClient, SourceHeader}; +use finality_relay::SourceClient; use futures::stream::{unfold, Stream, StreamExt}; +use relay_substrate_client::{ + BlockNumberOf, BlockWithJustification, Chain, Client, Error, HeaderOf, +}; use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::traits::Header as HeaderT; -use std::{marker::PhantomData, pin::Pin}; +use std::pin::Pin; /// Shared updatable reference to the maximal header number that we want to sync from the source. pub type RequiredHeaderNumberRef = Arc::BlockNumber>>; +/// Substrate finality proofs stream. +pub type SubstrateFinalityProofsStream

= Pin< + Box< + dyn Stream< + Item = GrandpaJustification< + HeaderOf<

::SourceChain>, + >, + > + Send, + >, +>; + /// Substrate node as finality source. -pub struct FinalitySource { - client: Client, - maximal_header_number: Option>, - _phantom: PhantomData

, +pub struct SubstrateFinalitySource { + client: Client, + maximal_header_number: Option>, } -impl FinalitySource { +impl SubstrateFinalitySource

{ /// Create new headers source using given client. pub fn new( - client: Client, - maximal_header_number: Option>, + client: Client, + maximal_header_number: Option>, ) -> Self { - FinalitySource { client, maximal_header_number, _phantom: Default::default() } + SubstrateFinalitySource { client, maximal_header_number } } /// Returns reference to the underlying RPC client. - pub fn client(&self) -> &Client { + pub fn client(&self) -> &Client { &self.client } /// Returns best finalized block number. - pub async fn on_chain_best_finalized_block_number(&self) -> Result { + pub async fn on_chain_best_finalized_block_number( + &self, + ) -> Result, Error> { // we **CAN** continue to relay finality proofs if source node is out of sync, because // target node may be missing proofs that are already available at the source let finalized_header_hash = self.client.best_finalized_header_hash().await?; @@ -67,18 +77,17 @@ impl FinalitySource { } } -impl Clone for FinalitySource { +impl Clone for SubstrateFinalitySource

{ fn clone(&self) -> Self { - FinalitySource { + SubstrateFinalitySource { client: self.client.clone(), maximal_header_number: self.maximal_header_number.clone(), - _phantom: Default::default(), } } } #[async_trait] -impl RelayClient for FinalitySource { +impl RelayClient for SubstrateFinalitySource

{ type Error = Error; async fn reconnect(&mut self) -> Result<(), Error> { @@ -87,21 +96,12 @@ impl RelayClient for FinalitySource { } #[async_trait] -impl SourceClient

for FinalitySource -where - C: Chain, - C::BlockNumber: relay_utils::BlockNumberBase, - P: FinalitySyncPipeline< - Hash = C::Hash, - Number = C::BlockNumber, - Header = SyncHeader, - FinalityProof = GrandpaJustification, - >, - P::Header: SourceHeader, +impl SourceClient> + for SubstrateFinalitySource

{ - type FinalityProofsStream = Pin> + Send>>; + type FinalityProofsStream = SubstrateFinalityProofsStream

; - async fn best_finalized_block_number(&self) -> Result { + async fn best_finalized_block_number(&self) -> Result, Error> { let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?; // never return block number larger than requested. This way we'll never sync headers // past `maximal_header_number` @@ -116,15 +116,23 @@ where async fn header_and_finality_proof( &self, - number: P::Number, - ) -> Result<(P::Header, Option), Error> { + number: BlockNumberOf, + ) -> Result< + ( + relay_substrate_client::SyncHeader>, + Option>>, + ), + Error, + > { let header_hash = self.client.block_hash_by_number(number).await?; let signed_block = self.client.get_block(Some(header_hash)).await?; let justification = signed_block .justification() .map(|raw_justification| { - GrandpaJustification::::decode(&mut raw_justification.as_slice()) + GrandpaJustification::>::decode( + &mut raw_justification.as_slice(), + ) }) .transpose() .map_err(Error::ResponseParseFailed)?; @@ -141,7 +149,7 @@ where log::error!( target: "bridge", "Failed to read justification target from the {} justifications stream: {:?}", - P::SOURCE_NAME, + P::SourceChain::NAME, err, ); }; @@ -153,7 +161,9 @@ where .ok()??; let decoded_justification = - GrandpaJustification::::decode(&mut &next_justification[..]); + GrandpaJustification::>::decode( + &mut &next_justification[..], + ); let justification = match decoded_justification { Ok(j) => j, diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index f50bd103f4300..adfe12ab35b8e 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -15,70 +15,78 @@ // along with Parity Bridges Common. If not, see . //! Substrate client as Substrate finality proof target. The chain we connect to should have -//! runtime that implements `FinalityApi` to allow bridging with -//! chain. +//! bridge GRANDPA pallet deployed and provide `FinalityApi` to allow bridging +//! with chain. -use crate::finality_pipeline::SubstrateFinalitySyncPipeline; +use crate::finality_pipeline::{ + FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, + TransactionParams, +}; use async_trait::async_trait; -use codec::Decode; -use finality_relay::{FinalitySyncPipeline, TargetClient}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError}; +use bp_header_chain::justification::GrandpaJustification; +use codec::Encode; +use finality_relay::TargetClient; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error, HashOf, HeaderOf, + SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; use relay_utils::relay_loop::Client as RelayClient; +use sp_core::{Bytes, Pair}; /// Substrate client as Substrate finality target. -pub struct SubstrateFinalityTarget { - client: Client, - pipeline: P, - transactions_mortality: Option, +pub struct SubstrateFinalityTarget { + client: Client, + transaction_params: TransactionParams>, } -impl SubstrateFinalityTarget { +impl SubstrateFinalityTarget

{ /// Create new Substrate headers target. - pub fn new(client: Client, pipeline: P, transactions_mortality: Option) -> Self { - SubstrateFinalityTarget { client, pipeline, transactions_mortality } + pub fn new( + client: Client, + transaction_params: TransactionParams>, + ) -> Self { + SubstrateFinalityTarget { client, transaction_params } } } -impl Clone for SubstrateFinalityTarget { +impl Clone for SubstrateFinalityTarget

{ fn clone(&self) -> Self { SubstrateFinalityTarget { client: self.client.clone(), - pipeline: self.pipeline.clone(), - transactions_mortality: self.transactions_mortality, + transaction_params: self.transaction_params.clone(), } } } #[async_trait] -impl RelayClient for SubstrateFinalityTarget { - type Error = SubstrateError; +impl RelayClient for SubstrateFinalityTarget

{ + type Error = Error; - async fn reconnect(&mut self) -> Result<(), SubstrateError> { + async fn reconnect(&mut self) -> Result<(), Error> { self.client.reconnect().await } } #[async_trait] -impl TargetClient for SubstrateFinalityTarget +impl TargetClient> + for SubstrateFinalityTarget

where - C: Chain, - P: SubstrateFinalitySyncPipeline, - ::Number: Decode, - ::Hash: Decode, + AccountIdOf: From< as Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { async fn best_finalized_source_block_number( &self, - ) -> Result<::Number, SubstrateError> { + ) -> Result, Error> { // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay self.client.ensure_synced().await?; Ok(crate::messages_source::read_client_state::< - C, - ::Hash, - ::Number, - >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) + P::TargetChain, + HashOf, + BlockNumberOf, + >(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD) .await? .best_finalized_peer_at_best_self .0) @@ -86,24 +94,28 @@ where async fn submit_finality_proof( &self, - header: ::Header, - proof: ::FinalityProof, - ) -> Result<(), SubstrateError> { - let transactions_author = self.pipeline.transactions_author(); - let pipeline = self.pipeline.clone(); - let transactions_mortality = self.transactions_mortality; + header: SyncHeader>, + proof: GrandpaJustification>, + ) -> Result<(), Error> { + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let call = + P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); self.client .submit_signed_extrinsic( - transactions_author, + self.transaction_params.transactions_signer.public().into(), move |best_block_id, transaction_nonce| { - pipeline.make_submit_finality_proof_transaction( - relay_substrate_client::TransactionEra::new( - best_block_id, - transactions_mortality, - ), - transaction_nonce, - header, - proof, + Bytes( + P::TransactionSignScheme::sign_transaction( + genesis_hash, + &transaction_params.transactions_signer, + TransactionEra::new( + best_block_id, + transaction_params.transactions_mortality, + ), + UnsignedTransaction::new(call, transaction_nonce), + ) + .encode(), ) }, ) diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index cc066bf501ac6..1c62ddaa9a7ee 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -23,6 +23,7 @@ use std::time::Duration; pub mod conversion_rate_update; pub mod error; pub mod finality_pipeline; +pub mod finality_source; pub mod finality_target; pub mod headers_initialize; pub mod helpers; diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index ee141866eb97d..5a170d5cbf8bf 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -16,29 +16,24 @@ //! On-demand Substrate -> Substrate headers relay. -use std::fmt::Debug; - use async_std::sync::{Arc, Mutex}; use futures::{select, FutureExt}; use num_traits::{CheckedSub, One, Zero}; -use finality_relay::{ - FinalitySyncParams, FinalitySyncPipeline, SourceClient as FinalitySourceClient, SourceHeader, - TargetClient as FinalityTargetClient, -}; +use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient}; use relay_substrate_client::{ - finality_source::{FinalitySource as SubstrateFinalitySource, RequiredHeaderNumberRef}, - Chain, Client, HeaderIdOf, SyncHeader, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderIdOf, HeaderOf, SyncHeader, + TransactionSignScheme, }; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, - MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, }; use crate::{ finality_pipeline::{ - SubstrateFinalitySyncPipeline, SubstrateFinalityToSubstrate, RECENT_FINALITY_PROOFS_LIMIT, + SubstrateFinalitySyncPipeline, TransactionParams, RECENT_FINALITY_PROOFS_LIMIT, }, + finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, finality_target::SubstrateFinalityTarget, STALL_TIMEOUT, }; @@ -58,40 +53,28 @@ pub struct OnDemandHeadersRelay { impl OnDemandHeadersRelay { /// Create new on-demand headers relay. - pub fn new( - source_client: Client, - target_client: Client, - target_transactions_mortality: Option, - pipeline: P, - maximal_headers_difference: SourceChain::BlockNumber, + pub fn new>( + source_client: Client, + target_client: Client, + target_transaction_params: TransactionParams>, + maximal_headers_difference: BlockNumberOf, only_mandatory_headers: bool, ) -> Self where - SourceChain: Chain + Debug, - SourceChain::BlockNumber: BlockNumberBase, - TargetChain: Chain + Debug, - TargetChain::BlockNumber: BlockNumberBase, - TargetSign: Clone + Send + Sync + 'static, - P: SubstrateFinalitySyncPipeline< - FinalitySyncPipeline = SubstrateFinalityToSubstrate< - SourceChain, - TargetChain, - TargetSign, - >, - TargetChain = TargetChain, - >, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { let required_header_number = Arc::new(Mutex::new(Zero::zero())); let this = OnDemandHeadersRelay { - relay_task_name: on_demand_headers_relay_name::(), + relay_task_name: on_demand_headers_relay_name::(), required_header_number: required_header_number.clone(), }; async_std::task::spawn(async move { - background_task( + background_task::

( source_client, target_client, - target_transactions_mortality, - pipeline, + target_transaction_params, maximal_headers_difference, only_mandatory_headers, required_header_number, @@ -120,35 +103,25 @@ impl OnDemandHeadersRelay { } /// Background task that is responsible for starting headers relay. -async fn background_task( - source_client: Client, - target_client: Client, - target_transactions_mortality: Option, - pipeline: P, - maximal_headers_difference: SourceChain::BlockNumber, +async fn background_task( + source_client: Client, + target_client: Client, + target_transaction_params: TransactionParams>, + maximal_headers_difference: BlockNumberOf, only_mandatory_headers: bool, - required_header_number: RequiredHeaderNumberRef, + required_header_number: RequiredHeaderNumberRef, ) where - SourceChain: Chain + Debug, - SourceChain::BlockNumber: BlockNumberBase, - TargetChain: Chain + Debug, - TargetChain::BlockNumber: BlockNumberBase, - TargetSign: Clone + Send + Sync + 'static, - P: SubstrateFinalitySyncPipeline< - FinalitySyncPipeline = SubstrateFinalityToSubstrate, - TargetChain = TargetChain, - >, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { - let relay_task_name = on_demand_headers_relay_name::(); - let mut finality_source = SubstrateFinalitySource::< - _, - SubstrateFinalityToSubstrate, - >::new(source_client.clone(), Some(required_header_number.clone())); - let mut finality_target = SubstrateFinalityTarget::new( - target_client.clone(), - pipeline.clone(), - target_transactions_mortality, + let relay_task_name = on_demand_headers_relay_name::(); + let mut finality_source = SubstrateFinalitySource::

::new( + source_client.clone(), + Some(required_header_number.clone()), ); + let mut finality_target = + SubstrateFinalityTarget::new(target_client.clone(), target_transaction_params); let mut latest_non_mandatory_at_source = Zero::zero(); let mut restart_relay = true; @@ -157,7 +130,7 @@ async fn background_task( loop { select! { - _ = async_std::task::sleep(TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, + _ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, _ = finality_relay_task => { // this should never happen in practice given the current code restart_relay = true; @@ -179,12 +152,8 @@ async fn background_task( } // read best finalized source header number from target - let best_finalized_source_header_at_target = best_finalized_source_header_at_target::< - SourceChain, - _, - _, - >(&finality_target, &relay_task_name) - .await; + let best_finalized_source_header_at_target = + best_finalized_source_header_at_target::

(&finality_target, &relay_task_name).await; if matches!(best_finalized_source_header_at_target, Err(ref e) if e.is_connection_error()) { relay_utils::relay_loop::reconnect_failed_client( FailedClient::Target, @@ -199,7 +168,7 @@ async fn background_task( // submit mandatory header if some headers are missing let best_finalized_source_header_at_target_fmt = format!("{:?}", best_finalized_source_header_at_target); - let mandatory_scan_range = mandatory_headers_scan_range::( + let mandatory_scan_range = mandatory_headers_scan_range::( best_finalized_source_header_at_source.ok(), best_finalized_source_header_at_target.ok(), maximal_headers_difference, @@ -247,8 +216,8 @@ async fn background_task( finality_target.clone(), FinalitySyncParams { tick: std::cmp::max( - SourceChain::AVERAGE_BLOCK_INTERVAL, - TargetChain::AVERAGE_BLOCK_INTERVAL, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: STALL_TIMEOUT, @@ -316,17 +285,13 @@ async fn mandatory_headers_scan_range( /// it. /// /// Returns `true` if header was found and (asked to be) relayed and `false` otherwise. -async fn relay_mandatory_header_from_range( - finality_source: &SubstrateFinalitySource, - required_header_number: &RequiredHeaderNumberRef, +async fn relay_mandatory_header_from_range( + finality_source: &SubstrateFinalitySource

, + required_header_number: &RequiredHeaderNumberRef, best_finalized_source_header_at_target: String, - range: (SourceChain::BlockNumber, SourceChain::BlockNumber), + range: (BlockNumberOf, BlockNumberOf), relay_task_name: &str, -) -> Result -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ +) -> Result { // search for mandatory header first let mandatory_source_header_number = find_mandatory_header_in_range(finality_source, range).await?; @@ -347,7 +312,7 @@ where log::trace!( target: "bridge", "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the mandatory {}", - SourceChain::NAME, + P::SourceChain::NAME, relay_task_name, best_finalized_source_header_at_target, range.1, @@ -361,14 +326,10 @@ where /// Read best finalized source block number from source client. /// /// Returns `None` if we have failed to read the number. -async fn best_finalized_source_header_at_source( - finality_source: &SubstrateFinalitySource, +async fn best_finalized_source_header_at_source( + finality_source: &SubstrateFinalitySource

, relay_task_name: &str, -) -> Result -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ +) -> Result, relay_substrate_client::Error> { finality_source.on_chain_best_finalized_block_number().await.map_err(|error| { log::error!( target: "bridge", @@ -384,14 +345,14 @@ where /// Read best finalized source block number from target client. /// /// Returns `None` if we have failed to read the number. -async fn best_finalized_source_header_at_target( - finality_target: &SubstrateFinalityTarget, +async fn best_finalized_source_header_at_target( + finality_target: &SubstrateFinalityTarget

, relay_task_name: &str, -) -> Result as RelayClient>::Error> +) -> Result, as RelayClient>::Error> where - SubstrateFinalityTarget: FinalityTargetClient, - P: SubstrateFinalitySyncPipeline, - P::FinalitySyncPipeline: FinalitySyncPipeline, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, { finality_target.best_finalized_source_block_number().await.map_err(|error| { log::error!( @@ -408,17 +369,13 @@ where /// Read first mandatory header in given inclusive range. /// /// Returns `Ok(None)` if there were no mandatory headers in the range. -async fn find_mandatory_header_in_range( - finality_source: &SubstrateFinalitySource, - range: (SourceChain::BlockNumber, SourceChain::BlockNumber), -) -> Result, relay_substrate_client::Error> -where - SubstrateFinalitySource: FinalitySourceClient

, - P: FinalitySyncPipeline, -{ +async fn find_mandatory_header_in_range( + finality_source: &SubstrateFinalitySource

, + range: (BlockNumberOf, BlockNumberOf), +) -> Result>, relay_substrate_client::Error> { let mut current = range.0; while current <= range.1 { - let header: SyncHeader = + let header: SyncHeader> = finality_source.client().header_by_number(current).await?.into(); if header.is_mandatory() { return Ok(Some(current)) From 1b6685fc33289215544644fb2eef0eb2d8f7edd1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Dec 2021 11:46:08 +0300 Subject: [PATCH 0612/1210] Fix transactions mortality (#1196) * added lost stall timeout fix * use best_block.parent() to start mortal tx era * fmt * Revert "revert messages transactions mortality" This reverts commit 77776357dafdfa80dcb3ec307d76fcfd0d5195bb. --- relays/client-substrate/src/client.rs | 14 ++++++++++++-- .../lib-substrate-relay/src/on_demand_headers.rs | 6 +++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 1902875c93810..443c80598c76e 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -34,7 +34,7 @@ use jsonrpsee_ws_client::{ }, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder, }; -use num_traits::{Bounded, Zero}; +use num_traits::{Bounded, CheckedSub, One, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; @@ -349,7 +349,17 @@ impl Client { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; let best_header = self.best_header().await?; - let best_header_id = HeaderId(*best_header.number(), best_header.hash()); + + // By using parent of best block here, we are protecing again best-block reorganizations. + // E.g. transaction my have been submitted when the best block was `A[num=100]`. Then it has + // been changed to `B[num=100]`. Hash of `A` has been included into transaction signature + // payload. So when signature will be checked, the check will fail and transaction will be + // dropped from the pool. + let best_header_id = match best_header.number().checked_sub(&One::one()) { + Some(parent_block_number) => HeaderId(parent_block_number, *best_header.parent_hash()), + None => HeaderId(*best_header.number(), best_header.hash()), + }; + self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); let tx_hash = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 5a170d5cbf8bf..5f98d1441d64e 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -220,7 +220,11 @@ async fn background_task( P::TargetChain::AVERAGE_BLOCK_INTERVAL, ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, - stall_timeout: STALL_TIMEOUT, + stall_timeout: relay_substrate_client::transaction_stall_timeout( + target_transactions_mortality, + TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ), only_mandatory_headers, }, MetricsParams::disabled(), From e9d71427aa5fb4ff30762de776df0e51a1efbcdb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Dec 2021 15:22:37 +0300 Subject: [PATCH 0613/1210] post-merge build fix (#1243) --- relays/lib-substrate-relay/src/on_demand_headers.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 5f98d1441d64e..1bd0b0b729c48 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -116,6 +116,7 @@ async fn background_task( P::TransactionSignScheme: TransactionSignScheme, { let relay_task_name = on_demand_headers_relay_name::(); + let target_transactions_mortality = target_transaction_params.transactions_mortality; let mut finality_source = SubstrateFinalitySource::

::new( source_client.clone(), Some(required_header_number.clone()), @@ -222,7 +223,7 @@ async fn background_task( recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: relay_substrate_client::transaction_stall_timeout( target_transactions_mortality, - TargetChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, STALL_TIMEOUT, ), only_mandatory_headers, From 573da0c3dc02e49ecc215eec145f7a8d76072e47 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Dec 2021 16:46:25 +0300 Subject: [PATCH 0614/1210] Refactor message relay helpers (#1234) * refactor message relay helpers * single standalone_metrics function * fixed tests * clippy + fmt * removed commented code * add calls tracing * fix spelling * cargo fmt * -commented code * fix build again * post-merge build fix * clippy + fmt --- bin/millau/node/src/service.rs | 7 +- bin/millau/runtime/src/lib.rs | 25 +- bin/millau/runtime/src/rialto_messages.rs | 8 +- bin/rialto/runtime/src/lib.rs | 25 +- bin/rialto/runtime/src/millau_messages.rs | 8 +- modules/grandpa/src/mock.rs | 7 + modules/token-swap/src/mock.rs | 7 + primitives/chain-kusama/src/lib.rs | 4 +- primitives/chain-millau/src/lib.rs | 36 +- primitives/chain-polkadot/src/lib.rs | 4 +- primitives/chain-rialto-parachain/src/lib.rs | 24 +- primitives/chain-rialto/src/lib.rs | 37 +- primitives/chain-rococo/src/lib.rs | 4 +- primitives/chain-wococo/src/lib.rs | 4 +- primitives/polkadot-core/src/lib.rs | 29 +- primitives/runtime/src/chain.rs | 7 +- relays/bin-substrate/src/chains/kusama.rs | 24 - .../src/chains/kusama_headers_to_polkadot.rs | 4 +- .../src/chains/kusama_messages_to_polkadot.rs | 297 +------- relays/bin-substrate/src/chains/millau.rs | 27 +- .../src/chains/millau_messages_to_rialto.rs | 291 +------- relays/bin-substrate/src/chains/mod.rs | 13 +- relays/bin-substrate/src/chains/polkadot.rs | 24 - .../src/chains/polkadot_headers_to_kusama.rs | 4 +- .../src/chains/polkadot_messages_to_kusama.rs | 296 +------- relays/bin-substrate/src/chains/rialto.rs | 27 +- .../src/chains/rialto_messages_to_millau.rs | 290 +------- .../src/chains/rialto_parachain.rs | 10 +- relays/bin-substrate/src/chains/rococo.rs | 12 +- .../src/chains/rococo_headers_to_wococo.rs | 4 +- .../src/chains/rococo_messages_to_wococo.rs | 295 +------- relays/bin-substrate/src/chains/westend.rs | 5 - relays/bin-substrate/src/chains/wococo.rs | 14 +- .../src/chains/wococo_headers_to_rococo.rs | 4 +- .../src/chains/wococo_messages_to_rococo.rs | 293 +------- relays/bin-substrate/src/cli/bridge.rs | 12 +- relays/bin-substrate/src/cli/encode_call.rs | 3 - relays/bin-substrate/src/cli/mod.rs | 4 - relays/bin-substrate/src/cli/relay_headers.rs | 9 +- .../src/cli/relay_headers_and_messages.rs | 73 +- .../bin-substrate/src/cli/relay_messages.rs | 16 +- relays/bin-substrate/src/cli/send_message.rs | 2 +- relays/client-kusama/src/lib.rs | 39 +- relays/client-millau/Cargo.toml | 1 + relays/client-millau/src/lib.rs | 38 +- relays/client-polkadot/src/lib.rs | 39 +- relays/client-rialto-parachain/src/lib.rs | 10 + relays/client-rialto/Cargo.toml | 1 + relays/client-rialto/src/lib.rs | 38 +- relays/client-rococo/src/lib.rs | 39 +- relays/client-rococo/src/runtime.rs | 4 +- relays/client-substrate/Cargo.toml | 2 + relays/client-substrate/src/chain.rs | 54 +- relays/client-substrate/src/guard.rs | 10 +- relays/client-substrate/src/lib.rs | 3 +- relays/client-westend/Cargo.toml | 1 + relays/client-westend/src/lib.rs | 10 + relays/client-wococo/src/lib.rs | 39 +- relays/client-wococo/src/runtime.rs | 4 +- relays/lib-substrate-relay/Cargo.toml | 1 + .../src/finality_pipeline.rs | 18 +- .../src/finality_target.rs | 15 +- relays/lib-substrate-relay/src/lib.rs | 10 + .../lib-substrate-relay/src/messages_lane.rs | 673 ++++++++++-------- .../src/messages_metrics.rs | 199 ++++++ .../src/messages_source.rs | 151 ++-- .../src/messages_target.rs | 243 +++---- .../src/on_demand_headers.rs | 8 +- 68 files changed, 1484 insertions(+), 2455 deletions(-) create mode 100644 relays/lib-substrate-relay/src/messages_metrics.rs diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index b01c0bfca9069..36e1b948752a1 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -66,6 +66,7 @@ type FullClient = type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; +#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, ) -> Result< @@ -89,7 +90,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other(format!("Remote Keystores are not supported."))) + return Err(ServiceError::Other("Remote Keystores are not supported.".into())) } let telemetry = config @@ -111,7 +112,7 @@ pub fn new_partial( let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - &config, + config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, )?; @@ -178,7 +179,7 @@ pub fn new_partial( }) } -fn remote_keystore(_url: &String) -> Result, &'static str> { +fn remote_keystore(_url: &str) -> Result, &'static str> { // FIXME: here would the concrete keystore be built, // must return a concrete type (NOT `LocalKeystore`) that // implements `CryptoStore` and `SyncCryptoStore` diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 25cf48b6f7077..be186569961db 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -407,9 +407,9 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Millau => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; @@ -875,6 +875,7 @@ where #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; use bridge_runtime_common::messages; #[test] @@ -891,30 +892,30 @@ mod tests { ); let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_millau::max_extrinsic_size()), + messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), ); pallet_bridge_messages::ensure_able_to_receive_message::( - bp_millau::max_extrinsic_size(), - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), max_incoming_message_proof_size, messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ), ); let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_millau::max_extrinsic_size(), - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, DbWeight::get(), ); } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 6d9677c45cf91..d46ab4ca042a5 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -23,7 +23,7 @@ use bp_messages::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -86,7 +86,7 @@ impl MessageBridge for WithRialtoMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; type BridgedChain = Rialto; @@ -172,13 +172,13 @@ impl messages::ChainWithMessages for Rialto { impl messages::BridgedChainWithMessages for Rialto { fn maximal_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() + bp_rialto::Rialto::max_extrinsic_size() } fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ); // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 7b9de28aa914a..59be1186b4093 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -434,9 +434,9 @@ impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE; + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE; + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Rialto => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; @@ -1183,6 +1183,7 @@ where #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; use bridge_runtime_common::messages; #[test] @@ -1198,30 +1199,30 @@ mod tests { ); let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_rialto::max_extrinsic_size()), + messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), ); pallet_bridge_messages::ensure_able_to_receive_message::( - bp_rialto::max_extrinsic_size(), - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), max_incoming_message_proof_size, messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ), ); let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE as _, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE as _, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_rialto::max_extrinsic_size(), - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, DbWeight::get(), ); } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 13a1c6b06ec21..05935c90ea107 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -23,7 +23,7 @@ use bp_messages::{ target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; use codec::{Decode, Encode}; use frame_support::{ @@ -86,7 +86,7 @@ impl MessageBridge for WithMillauMessageBridge { const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; type ThisChain = Rialto; type BridgedChain = Millau; @@ -170,13 +170,13 @@ impl messages::ChainWithMessages for Millau { impl messages::BridgedChainWithMessages for Millau { fn maximal_extrinsic_size() -> u32 { - bp_millau::max_extrinsic_size() + bp_millau::Millau::max_extrinsic_size() } fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { // we don't want to relay too large messages + keep reserve for future upgrades let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ); // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index f8b5e269323f9..37d93df779bf7 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -106,6 +106,13 @@ impl Chain for TestBridgedChain { type Balance = u64; type Index = u64; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } pub fn run_test(test: impl FnOnce() -> T) -> T { diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index 63edb323e1a4c..2c24e282af629 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -142,6 +142,13 @@ impl bp_runtime::Chain for BridgedChain { type Balance = BridgedBalance; type Index = u64; type Signature = BridgedAccountSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } pub struct TestMessagesBridge; diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index f52d03f9f2be3..046323aa70091 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -81,8 +81,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; -/// Name of the With-Polkadot messages pallet instance in the Kusama runtime. -pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; +/// Name of the With-Kusama messages pallet instance that is deployed at bridged chains. +pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; /// Name of the DOT->KSM conversion rate stored in the Kusama runtime. pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index ba68467021348..4b2b043ed1229 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -68,11 +68,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal number of unrewarded relayer entries in Millau confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 1024; +/// Maximal number of unconfirmed messages in Millau confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; /// Weight of single regular message delivery transaction on Millau chain. /// @@ -172,6 +172,17 @@ impl Chain for Millau { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. @@ -246,21 +257,12 @@ frame_support::parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} +/// Name of the With-Millau messages pallet instance that is deployed at bridged chains. +pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} +/// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. +pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; -/// Name of the With-Rialto messages pallet instance in the Millau runtime. -pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; /// Name of the With-Rialto token swap pallet instance in the Millau runtime. pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 36d15ea6e426a..6989e6d2b641a 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -81,8 +81,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; -/// Name of the With-Kusama messages pallet instance in the Polkadot runtime. -pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; +/// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains. +pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; /// Name of the KSM->DOT conversion rate stored in the Polkadot runtime. pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 826f6d39bd7f7..786226cf93c99 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -92,6 +92,17 @@ impl Chain for RialtoParachain { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } frame_support::parameter_types! { @@ -113,16 +124,3 @@ frame_support::parameter_types! { .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); } - -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 3a0f7045c0888..d994b2f03f634 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -59,11 +59,11 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 128; +/// Maximal number of unconfirmed messages in Rialto confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Weight of single regular message delivery transaction on Rialto chain. /// @@ -171,6 +171,17 @@ impl Chain for Rialto { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Convert a 256-bit hash into an AccountId. @@ -215,21 +226,11 @@ frame_support::parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Millau chain can use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Millau chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} +/// Name of the With-Rialto messages pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; -/// Name of the With-Millau messages pallet instance in the Rialto runtime. -pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; +/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto runtime. +pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; /// Name of the parachain registrar pallet in the Rialto runtime. pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index e5b3647f32bc7..aca238358e187 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -74,8 +74,8 @@ pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Name of the With-Wococo messages pallet instance in the Rococo runtime. -pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; +/// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. +pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; /// Name of the `RococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index b16dff388c248..20541d99a6ae5 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -39,8 +39,8 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } -/// Name of the With-Rococo messages pallet instance in the Wococo runtime. -pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; +/// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. +pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; /// Name of the `WococoFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 38e43d312b5d4..0dc7c54835b9c 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -115,31 +115,17 @@ parameter_types! { .build_or_panic(); } -/// Get the maximum weight (compute time) that a Normal extrinsic on the Polkadot-like chain can -/// use. -pub fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) -} - -/// Get the maximum length in bytes that a Normal extrinsic on the Polkadot-like chain requires. -pub fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) -} - // TODO [#78] may need to be updated after https://github.com/paritytech/parity-bridges-common/issues/78 /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; /// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE: MessageNonce = 128; +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; // TODO [#438] should be selected keeping in mind: // finality delay on both chains + reward payout cost + messages throughput. /// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE: MessageNonce = 8192; +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192; // One important thing about weight-related constants here is that actually we may have // different weights on different Polkadot-like chains. But now all deployments are @@ -361,6 +347,17 @@ impl Chain for PolkadotLike { type Balance = Balance; type Index = Index; type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } } /// Convert a 256-bit hash into an AccountId. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index e963b633b7f56..9dfe6216a7cac 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use frame_support::Parameter; +use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ traits::{ @@ -120,6 +120,11 @@ pub trait Chain: Send + Sync + 'static { + Copy; /// Signature type, used on this chain. type Signature: Parameter + Verify; + + /// Get the maximum size (in bytes) of a Normal extrinsic at this chain. + fn max_extrinsic_size() -> u32; + /// Get the maximum weight (compute time) that a Normal extrinsic at this chain can use. + fn max_extrinsic_weight() -> Weight; } /// Block number used by the chain. diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index b12d23f2a56dc..10afbdd8a5a4d 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -17,8 +17,6 @@ use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; -use sp_core::storage::StorageKey; -use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ @@ -33,14 +31,7 @@ use crate::cli::{ /// calls in the future. But since it is used only in tests (and on test chains), this is ok. pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; -/// Id of Kusama token that is used to fetch token price. -pub(crate) const TOKEN_ID: &str = "kusama"; - impl CliEncodeCall for Kusama { - fn max_extrinsic_size() -> u32 { - bp_kusama::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( @@ -93,24 +84,9 @@ impl CliChain for Kusama { 42 } - fn max_extrinsic_weight() -> Weight { - bp_kusama::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { anyhow::bail!("Sending messages from Kusama is not yet supported.") } } - -/// Storage key and initial value of Polkadot -> Kusama conversion rate. -pub(crate) fn polkadot_to_kusama_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - bp_runtime::storage_parameter_key( - bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME, - ), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - ) -} diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index afa22aec9e470..c36c336718c0d 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -17,7 +17,7 @@ //! Kusama-to-Polkadot headers sync entrypoint. use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 32133adc3e54b..6a8780a34aad0 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -16,284 +16,49 @@ //! Kusama-to-Polkadot messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; use frame_support::weights::Weight; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_kusama_client::{ - HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, -}; -use relay_polkadot_client::{ - HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, -}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Kusama-to-Polkadot message lane. -pub type MessageLaneKusamaMessagesToPolkadot = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct KusamaMessagesToPolkadot { - message_lane: MessageLaneKusamaMessagesToPolkadot, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_kusama_client::Kusama; +use relay_polkadot_client::Polkadot; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Kusama -> Polkadot messages bridge. +#[derive(Clone, Debug)] +pub struct KusamaMessagesToPolkadot; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + KusamaMessagesToPolkadot, + KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + KusamaMessagesToPolkadot, + KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for KusamaMessagesToPolkadot { - type MessageLane = MessageLaneKusamaMessagesToPolkadot; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = - bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = - bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Kusama; type TargetChain = Polkadot; - fn source_transactions_author(&self) -> bp_kusama::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: KusamaHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_block: PolkadotHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Polkadot -> Kusama confirmation transaction. Weight: /{}, size: {}/{}", - bp_kusama::max_extrinsic_weight(), - transaction.encode().len(), - bp_kusama::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_polkadot::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type SourceTransactionSignScheme = Kusama; + type TargetTransactionSignScheme = Polkadot; - fn make_messages_delivery_transaction( - &self, - best_block_id: PolkadotHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_header: KusamaHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - - let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Kusama -> Polkadot delivery transaction. Weight: /{}, size: {}/{}", - bp_polkadot::max_extrinsic_weight(), - transaction.encode().len(), - bp_polkadot::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Kusama node as messages source. -type KusamaSourceClient = SubstrateMessagesSource; - -/// Polkadot node as messages target. -type PolkadotTargetClient = SubstrateMessagesTarget; - -/// Run Kusama-to-Polkadot messages sync. -pub async fn run( - params: MessagesRelayParams< - Kusama, - KusamaSigningParams, - Polkadot, - PolkadotSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Kusama::AVERAGE_BLOCK_INTERVAL, - Polkadot::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_kusama = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = KusamaMessagesToPolkadot { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_kusama, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_polkadot::max_extrinsic_size() / 3; - // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_polkadot::max_extrinsic_weight(), - bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Kusama -> Polkadot messages relay.\n\t\ - Kusama relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Kusama::AVERAGE_BLOCK_INTERVAL, - target_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_polkadot::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_polkadot::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - KusamaSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - PolkadotTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Kusama -> Polkadot messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::kusama::TOKEN_ID), - Some(crate::chains::polkadot::TOKEN_ID), - Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), - Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), - ) + type RelayStrategy = MixStrategy; } /// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage. diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 755d7cc4430a4..3d599c2e54513 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -26,24 +26,11 @@ use crate::cli::{ use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_millau_client::Millau; -use sp_core::storage::StorageKey; -use sp_runtime::FixedU128; use sp_version::RuntimeVersion; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Millau token value by relayer. -pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::kusama::TOKEN_ID; - impl CliEncodeCall for Millau { - fn max_extrinsic_size() -> u32 { - bp_millau::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, @@ -96,10 +83,6 @@ impl CliChain for Millau { millau_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_millau::max_extrinsic_weight() - } - // TODO [#854|#843] support multiple bridges? fn encode_message( message: encode_message::MessagePayload, @@ -132,11 +115,3 @@ impl CliChain for Millau { } } } - -/// Storage key and initial value of Rialto -> Millau conversion rate. -pub(crate) fn rialto_to_millau_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), - millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, - ) -} diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index c4179eea330f1..4acc7fdd2ff8d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -16,279 +16,46 @@ //! Millau-to-Rialto messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_millau_client::{ - HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, -}; -use relay_rialto_client::{ - HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, }; -/// Millau-to-Rialto message lane. -pub type MessageLaneMillauMessagesToRialto = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct MillauMessagesToRialto { - message_lane: MessageLaneMillauMessagesToRialto, -} +/// Description of Millau -> Rialto messages bridge. +#[derive(Clone, Debug)] +pub struct MillauMessagesToRialto; impl SubstrateMessageLane for MillauMessagesToRialto { - type MessageLane = MessageLaneMillauMessagesToRialto; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Millau; type TargetChain = Rialto; - fn source_transactions_author(&self) -> bp_millau::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: MillauHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: RialtoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call: millau_runtime::Call = - millau_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rialto -> Millau confirmation transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_millau::max_extrinsic_weight(), - transaction.encode().len(), - bp_millau::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_rialto::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: RialtoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: MillauHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - let call: rialto_runtime::Call = rialto_runtime::MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count: messages_count as _, - dispatch_weight, - } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Millau -> Rialto delivery transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_rialto::max_extrinsic_weight(), - transaction.encode().len(), - bp_rialto::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Millau node as messages source. -type MillauSourceClient = SubstrateMessagesSource; - -/// Rialto node as messages target. -type RialtoTargetClient = SubstrateMessagesTarget; - -/// Run Millau-to-Rialto messages sync. -pub async fn run( - params: MessagesRelayParams< - Millau, - MillauSigningParams, - Rialto, - RialtoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Millau::AVERAGE_BLOCK_INTERVAL, - Rialto::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = MillauMessagesToRialto { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_millau, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_rialto::max_extrinsic_size() / 3; - // TODO: use Millau weights after https://github.com/paritytech/parity-bridges-common/issues/390 - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_rialto::max_extrinsic_weight(), - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - - log::info!( - target: "bridge", - "Starting Millau -> Rialto messages relay.\n\t\ - Millau relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Millau::AVERAGE_BLOCK_INTERVAL, - target_tick: Rialto::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_rialto::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_rialto::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - MillauSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - RialtoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Millau -> Rialto messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), - Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), - Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), - Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), - ) + type SourceTransactionSignScheme = Millau; + type TargetTransactionSignScheme = Rialto; + + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + >; + + type RelayStrategy = MixStrategy; } /// Update Rialto -> Millau conversion rate, stored in Millau runtime storage. diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 1bc0115b5b05e..3f2f5633a03b0 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -43,6 +43,7 @@ mod wococo; mod tests { use crate::cli::{encode_call, send_message}; use bp_messages::source_chain::TargetHeaderChain; + use bp_runtime::Chain as _; use codec::Encode; use frame_support::dispatch::GetDispatchInfo; use relay_millau_client::Millau; @@ -102,8 +103,8 @@ mod tests { use rialto_runtime::millau_messages::Millau; let maximal_remark_size = encode_call::compute_maximal_message_arguments_size( - bp_rialto::max_extrinsic_size(), - bp_millau::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_size(), ); let call: millau_runtime::Call = @@ -135,8 +136,8 @@ mod tests { fn maximal_size_remark_to_rialto_is_generated_correctly() { assert!( bridge_runtime_common::messages::target::maximal_incoming_message_size( - bp_rialto::max_extrinsic_size() - ) > bp_millau::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_size() + ) > bp_millau::Millau::max_extrinsic_size(), "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", ) } @@ -146,7 +147,7 @@ mod tests { use rialto_runtime::millau_messages::Millau; let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_millau::max_extrinsic_weight(), + bp_millau::Millau::max_extrinsic_weight(), ); let call: millau_runtime::Call = rialto_runtime::SystemCall::remark { remark: vec![] }.into(); @@ -175,7 +176,7 @@ mod tests { use millau_runtime::rialto_messages::Rialto; let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_rialto::max_extrinsic_weight(), + bp_rialto::Rialto::max_extrinsic_weight(), ); let call: rialto_runtime::Call = millau_runtime::SystemCall::remark { remark: vec![] }.into(); diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 7b6256d1749f8..8c31792a5430a 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -17,8 +17,6 @@ use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; -use sp_core::storage::StorageKey; -use sp_runtime::{FixedPointNumber, FixedU128}; use sp_version::RuntimeVersion; use crate::cli::{ @@ -33,14 +31,7 @@ use crate::cli::{ /// calls in the future. But since it is used only in tests (and on test chains), this is ok. pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; -/// Id of Polkadot token that is used to fetch token price. -pub(crate) const TOKEN_ID: &str = "polkadot"; - impl CliEncodeCall for Polkadot { - fn max_extrinsic_size() -> u32 { - bp_polkadot::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( @@ -93,24 +84,9 @@ impl CliChain for Polkadot { 42 } - fn max_extrinsic_weight() -> Weight { - bp_polkadot::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { anyhow::bail!("Sending messages from Polkadot is not yet supported.") } } - -/// Storage key and initial value of Kusama -> Polkadot conversion rate. -pub(crate) fn kusama_to_polkadot_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - bp_runtime::storage_parameter_key( - bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME, - ), - // starting relay before this parameter will be set to some value may cause troubles - FixedU128::from_inner(FixedU128::DIV), - ) -} diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index 695e0ec3ee6b1..5f65d658b90cb 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -17,7 +17,7 @@ //! Polkadot-to-Kusama headers sync entrypoint. use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index bc7f222430922..12ebdde15cb5b 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -16,283 +16,49 @@ //! Polkadot-to-Kusama messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_kusama_client::{ - HeaderId as KusamaHeaderId, Kusama, SigningParams as KusamaSigningParams, -}; -use relay_polkadot_client::{ - HeaderId as PolkadotHeaderId, Polkadot, SigningParams as PolkadotSigningParams, -}; -use relay_substrate_client::{Chain, Client, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Polkadot-to-Kusama message lane. -pub type MessageLanePolkadotMessagesToKusama = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct PolkadotMessagesToKusama { - message_lane: MessageLanePolkadotMessagesToKusama, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_kusama_client::Kusama; +use relay_polkadot_client::Polkadot; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Polkadot -> Kusama messages bridge. +#[derive(Clone, Debug)] +pub struct PolkadotMessagesToKusama; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + PolkadotMessagesToKusama, + PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + PolkadotMessagesToKusama, + PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for PolkadotMessagesToKusama { - type MessageLane = MessageLanePolkadotMessagesToKusama; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = - bp_polkadot::WITH_KUSAMA_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = - bp_kusama::WITH_POLKADOT_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Polkadot; type TargetChain = Kusama; - fn source_transactions_author(&self) -> bp_polkadot::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: PolkadotHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_block: KusamaHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Polkadot::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Kusama -> Polkadot confirmation transaction. Weight: /{}, size: {}/{}", - bp_polkadot::max_extrinsic_weight(), - transaction.encode().len(), - bp_polkadot::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_kusama::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: KusamaHeaderId, - transaction_nonce: bp_runtime::IndexOf, - _generated_at_header: PolkadotHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; + type SourceTransactionSignScheme = Polkadot; + type TargetTransactionSignScheme = Kusama; - let call = relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Kusama::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Polkadot -> Kusama delivery transaction. Weight: /{}, size: {}/{}", - bp_kusama::max_extrinsic_weight(), - transaction.encode().len(), - bp_kusama::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Polkadot node as messages source. -type PolkadotSourceClient = SubstrateMessagesSource; - -/// Kusama node as messages target. -type KusamaTargetClient = SubstrateMessagesTarget; - -/// Run Polkadot-to-Kusama messages sync. -pub async fn run( - params: MessagesRelayParams< - Polkadot, - PolkadotSigningParams, - Kusama, - KusamaSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Polkadot::AVERAGE_BLOCK_INTERVAL, - Kusama::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_polkadot = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = PolkadotMessagesToKusama { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_polkadot, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_kusama::max_extrinsic_size() / 3; - // we don't know exact weights of the Kusama runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_kusama::max_extrinsic_weight(), - bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Polkadot -> Kusama messages relay.\n\t\ - Polkadot relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Polkadot::AVERAGE_BLOCK_INTERVAL, - target_tick: Kusama::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_kusama::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_kusama::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - PolkadotSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - KusamaTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Polkadot -> Kusama messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::polkadot::TOKEN_ID), - Some(crate::chains::kusama::TOKEN_ID), - Some(crate::chains::kusama::polkadot_to_kusama_conversion_rate_params()), - Some(crate::chains::polkadot::kusama_to_polkadot_conversion_rate_params()), - ) + type RelayStrategy = MixStrategy; } /// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage. diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 2d873a24ba7af..8931c5112da80 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -26,24 +26,11 @@ use crate::cli::{ use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_client::Rialto; -use sp_core::storage::StorageKey; -use sp_runtime::FixedU128; use sp_version::RuntimeVersion; -// Millau/Rialto tokens have no any real value, so the conversion rate we use is always 1:1. But we -// want to test our code that is intended to work with real-value chains. So to keep it close to -// 1:1, we'll be treating Rialto as BTC and Millau as wBTC (only in relayer). - -/// The identifier of token, which value is associated with Rialto token value by relayer. -pub(crate) const ASSOCIATED_TOKEN_ID: &str = crate::chains::polkadot::TOKEN_ID; - impl CliEncodeCall for Rialto { - fn max_extrinsic_size() -> u32 { - bp_rialto::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, @@ -96,10 +83,6 @@ impl CliChain for Rialto { rialto_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_rialto::max_extrinsic_weight() - } - fn encode_message( message: encode_message::MessagePayload, ) -> anyhow::Result { @@ -131,11 +114,3 @@ impl CliChain for Rialto { } } } - -/// Storage key and initial value of Millau -> Rialto conversion rate. -pub(crate) fn millau_to_rialto_conversion_rate_params() -> (StorageKey, FixedU128) { - ( - StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), - rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, - ) -} diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 774da017df0c1..b6e85a7dec79f 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -16,278 +16,46 @@ //! Rialto-to-Millau messages sync entrypoint. -use std::ops::RangeInclusive; - use codec::Encode; -use frame_support::dispatch::GetDispatchInfo; use sp_core::{Bytes, Pair}; -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_millau_client::{ - HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams, -}; -use relay_rialto_client::{ - HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, }; -/// Rialto-to-Millau message lane. -pub type MessageLaneRialtoMessagesToMillau = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct RialtoMessagesToMillau { - message_lane: MessageLaneRialtoMessagesToMillau, -} +/// Description of Rialto -> Millau messages bridge. +#[derive(Clone, Debug)] +pub struct RialtoMessagesToMillau; impl SubstrateMessageLane for RialtoMessagesToMillau { - type MessageLane = MessageLaneRialtoMessagesToMillau; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rialto::WITH_MILLAU_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_millau::WITH_RIALTO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); type SourceChain = Rialto; type TargetChain = Millau; - fn source_transactions_author(&self) -> bp_rialto::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: RialtoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: MillauHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call: rialto_runtime::Call = - rialto_runtime::MessagesCall::receive_messages_delivery_proof { proof, relayers_state } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Rialto::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Millau -> Rialto confirmation transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_rialto::max_extrinsic_weight(), - transaction.encode().len(), - bp_rialto::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_millau::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: MillauHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: RialtoHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - let call: millau_runtime::Call = millau_runtime::MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count: messages_count as _, - dispatch_weight, - } - .into(); - let call_weight = call.get_dispatch_info().weight; - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Millau::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rialto -> Millau delivery transaction. Weight: {}/{}, size: {}/{}", - call_weight, - bp_millau::max_extrinsic_weight(), - transaction.encode().len(), - bp_millau::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Rialto node as messages source. -type RialtoSourceClient = SubstrateMessagesSource; - -/// Millau node as messages target. -type MillauTargetClient = SubstrateMessagesTarget; - -/// Run Rialto-to-Millau messages sync. -pub async fn run( - params: MessagesRelayParams< - Rialto, - RialtoSigningParams, - Millau, - MillauSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Rialto::AVERAGE_BLOCK_INTERVAL, - Millau::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = RialtoMessagesToMillau { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_rialto, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_millau::max_extrinsic_size() / 3; - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - - log::info!( - target: "bridge", - "Starting Rialto -> Millau messages relay.\n\t\ - Rialto relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Rialto::AVERAGE_BLOCK_INTERVAL, - target_tick: Millau::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_millau::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - RialtoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - MillauTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} - -/// Create standalone metrics for the Rialto -> Millau messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - Some(crate::chains::rialto::ASSOCIATED_TOKEN_ID), - Some(crate::chains::millau::ASSOCIATED_TOKEN_ID), - Some(crate::chains::millau::rialto_to_millau_conversion_rate_params()), - Some(crate::chains::rialto::millau_to_rialto_conversion_rate_params()), - ) + type SourceTransactionSignScheme = Rialto; + type TargetTransactionSignScheme = Millau; + + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + >; + + type RelayStrategy = MixStrategy; } /// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage. diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 9adcad2231961..da400a4dafd87 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -22,15 +22,11 @@ use crate::cli::{ }; use bp_message_dispatch::MessagePayload; use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo, Weight}; +use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_parachain_client::RialtoParachain; use sp_version::RuntimeVersion; impl CliEncodeCall for RialtoParachain { - fn max_extrinsic_size() -> u32 { - bp_rialto_parachain::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Raw { data } => Decode::decode(&mut &*data.0)?, @@ -71,10 +67,6 @@ impl CliChain for RialtoParachain { rialto_parachain_runtime::SS58Prefix::get() as u16 } - fn max_extrinsic_weight() -> Weight { - bp_rialto_parachain::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 4df60f89faa21..ef49899ec791d 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -33,10 +33,6 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Rococo { - fn max_extrinsic_size() -> u32 { - bp_rococo::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( @@ -48,8 +44,8 @@ impl CliEncodeCall for Rococo { match *bridge_instance_index { bridge::ROCOCO_TO_WOCOCO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; - relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::send_message( + relay_rococo_client::runtime::Call::BridgeWococoMessages( + relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message( lane.0, payload, fee.0, ), ) @@ -89,10 +85,6 @@ impl CliChain for Rococo { 42 } - fn max_extrinsic_weight() -> Weight { - bp_wococo::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index 0b6608b99becd..d0f1896db89f9 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -19,7 +19,7 @@ use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Description of Rococo -> Wococo finalized headers bridge. #[derive(Clone, Debug)] @@ -48,7 +48,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index d6c9040e1277b..a85789bb1bed2 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -16,280 +16,41 @@ //! Rococo-to-Wococo messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_rococo_client::{ - HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_wococo_client::{ - HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, -}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; - -/// Rococo-to-Wococo message lane. -pub type MessageLaneRococoMessagesToWococo = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct RococoMessagesToWococo { - message_lane: MessageLaneRococoMessagesToWococo, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_rococo_client::Rococo; +use relay_wococo_client::Wococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Rococo -> Wococo messages bridge. +#[derive(Clone, Debug)] +pub struct RococoMessagesToWococo; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + RococoMessagesToWococo, + RococoMessagesToWococoReceiveMessagesProofCallBuilder, + relay_wococo_client::runtime::Call::BridgeRococoMessages, + relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + RococoMessagesToWococo, + RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder, + relay_rococo_client::runtime::Call::BridgeWococoMessages, + relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for RococoMessagesToWococo { - type MessageLane = MessageLaneRococoMessagesToWococo; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; type SourceChain = Rococo; type TargetChain = Wococo; - fn source_transactions_author(&self) -> bp_rococo::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: RococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: WococoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Wococo -> Rococo confirmation transaction. Weight: /{}, size: {}/{}", - bp_rococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_rococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } + type SourceTransactionSignScheme = Rococo; + type TargetTransactionSignScheme = Wococo; - fn target_transactions_author(&self) -> bp_wococo::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } - - fn make_messages_delivery_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: RococoHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - - let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rococo -> Wococo delivery transaction. Weight: /{}, size: {}/{}", - bp_wococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_wococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Rococo node as messages source. -type RococoSourceClient = SubstrateMessagesSource; - -/// Wococo node as messages target. -type WococoTargetClient = SubstrateMessagesTarget; - -/// Run Rococo-to-Wococo messages sync. -pub async fn run( - params: MessagesRelayParams< - Rococo, - RococoSigningParams, - Wococo, - WococoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Rococo::AVERAGE_BLOCK_INTERVAL, - Wococo::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = RococoMessagesToWococo { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_rococo, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_wococo::max_extrinsic_size() / 3; - // we don't know exact weights of the Wococo runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_wococo::max_extrinsic_weight(), - bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Rococo -> Wococo messages relay.\n\t\ - Rococo relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Rococo::AVERAGE_BLOCK_INTERVAL, - target_tick: Wococo::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_wococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_wococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - RococoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - WococoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = RococoMessagesToWococoReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Rococo -> Wococo messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - None, - None, - None, - None, - ) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index a42e4805512ca..5a3dd9956dc9b 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -18,7 +18,6 @@ use crate::cli::{encode_message, CliChain}; use anyhow::anyhow; -use frame_support::weights::Weight; use relay_westend_client::Westend; use sp_version::RuntimeVersion; @@ -32,10 +31,6 @@ impl CliChain for Westend { 42 } - fn max_extrinsic_weight() -> Weight { - 0 - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 328397d14ba7c..2acc8af484567 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -16,7 +16,7 @@ use anyhow::anyhow; use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; +use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use relay_wococo_client::Wococo; use sp_version::RuntimeVersion; @@ -27,10 +27,6 @@ use crate::cli::{ }; impl CliEncodeCall for Wococo { - fn max_extrinsic_size() -> u32 { - bp_wococo::max_extrinsic_size() - } - fn encode_call(call: &Call) -> anyhow::Result { Ok(match call { Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( @@ -42,8 +38,8 @@ impl CliEncodeCall for Wococo { match *bridge_instance_index { bridge::WOCOCO_TO_ROCOCO_INDEX => { let payload = Decode::decode(&mut &*payload.0)?; - relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::send_message( + relay_wococo_client::runtime::Call::BridgeRococoMessages( + relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message( lane.0, payload, fee.0, ), ) @@ -83,10 +79,6 @@ impl CliChain for Wococo { 42 } - fn max_extrinsic_weight() -> Weight { - bp_wococo::max_extrinsic_weight() - } - fn encode_message( _message: encode_message::MessagePayload, ) -> anyhow::Result { diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 276a5b84da306..2d8795fc83ddd 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -17,7 +17,7 @@ //! Wococo-to-Rococo headers sync entrypoint. use sp_core::Pair; -use substrate_relay_helper::finality_pipeline::{SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -53,7 +53,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { ); relay_substrate_client::guard::abort_when_account_balance_decreased( target_client.clone(), - transaction_params.transactions_signer.public().into(), + transaction_params.signer.public().into(), MAXIMAL_BALANCE_DECREASE_PER_DAY, ); } diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index dcba89e43f05c..7c599e413946d 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -16,279 +16,42 @@ //! Wococo-to-Rococo messages sync entrypoint. -use std::ops::RangeInclusive; - -use codec::Encode; -use sp_core::{Bytes, Pair}; - -use bp_messages::MessageNonce; -use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use frame_support::weights::Weight; -use messages_relay::{message_lane::MessageLane, relay_strategy::MixStrategy}; -use relay_rococo_client::{ - HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams, -}; -use relay_substrate_client::{Chain, Client, IndexOf, TransactionSignScheme, UnsignedTransaction}; -use relay_wococo_client::{ - HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo, -}; -use substrate_relay_helper::{ - messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, - SubstrateMessageLane, SubstrateMessageLaneToSubstrate, - }, - messages_source::SubstrateMessagesSource, - messages_target::SubstrateMessagesTarget, - STALL_TIMEOUT, -}; -/// Wococo-to-Rococo message lane. -pub type MessageLaneWococoMessagesToRococo = - SubstrateMessageLaneToSubstrate; - -#[derive(Clone)] -pub struct WococoMessagesToRococo { - message_lane: MessageLaneWococoMessagesToRococo, -} +use messages_relay::relay_strategy::MixStrategy; +use relay_rococo_client::Rococo; +use relay_wococo_client::Wococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +/// Description of Wococo -> Rococo messages bridge. +#[derive(Clone, Debug)] +pub struct WococoMessagesToRococo; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + WococoMessagesToRococo, + WococoMessagesToRococoReceiveMessagesProofCallBuilder, + relay_rococo_client::runtime::Call::BridgeWococoMessages, + relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof +); +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + WococoMessagesToRococo, + WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder, + relay_wococo_client::runtime::Call::BridgeRococoMessages, + relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof +); impl SubstrateMessageLane for WococoMessagesToRococo { - type MessageLane = MessageLaneWococoMessagesToRococo; - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = - bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = - bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = bp_wococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = bp_rococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = - bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; type SourceChain = Wococo; type TargetChain = Rococo; - fn source_transactions_author(&self) -> bp_wococo::AccountId { - (*self.message_lane.source_sign.public().as_array_ref()).into() - } - - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_block: RococoHeaderId, - proof: ::MessagesReceivingProof, - ) -> Bytes { - let (relayers_state, proof) = proof; - let call = relay_wococo_client::runtime::Call::BridgeMessagesRococo( - relay_wococo_client::runtime::BridgeMessagesRococoCall::receive_messages_delivery_proof( - proof, - relayers_state, - ), - ); - let genesis_hash = *self.message_lane.source_client.genesis_hash(); - let transaction = Wococo::sign_transaction( - genesis_hash, - &self.message_lane.source_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.source_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Rococo -> Wococo confirmation transaction. Weight: /{}, size: {}/{}", - bp_wococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_wococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } - - fn target_transactions_author(&self) -> bp_rococo::AccountId { - (*self.message_lane.target_sign.public().as_array_ref()).into() - } + type SourceTransactionSignScheme = Wococo; + type TargetTransactionSignScheme = Rococo; - fn make_messages_delivery_transaction( - &self, - best_block_id: WococoHeaderId, - transaction_nonce: IndexOf, - _generated_at_header: WococoHeaderId, - _nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes { - let (dispatch_weight, proof) = proof; - let FromBridgedChainMessagesProof { ref nonces_start, ref nonces_end, .. } = proof; - let messages_count = nonces_end - nonces_start + 1; - - let call = relay_rococo_client::runtime::Call::BridgeMessagesWococo( - relay_rococo_client::runtime::BridgeMessagesWococoCall::receive_messages_proof( - self.message_lane.relayer_id_at_source.clone(), - proof, - messages_count as _, - dispatch_weight, - ), - ); - let genesis_hash = *self.message_lane.target_client.genesis_hash(); - let transaction = Rococo::sign_transaction( - genesis_hash, - &self.message_lane.target_sign, - relay_substrate_client::TransactionEra::new( - best_block_id, - self.message_lane.target_transactions_mortality, - ), - UnsignedTransaction::new(call, transaction_nonce), - ); - log::trace!( - target: "bridge", - "Prepared Wococo -> Rococo delivery transaction. Weight: /{}, size: {}/{}", - bp_rococo::max_extrinsic_weight(), - transaction.encode().len(), - bp_rococo::max_extrinsic_size(), - ); - Bytes(transaction.encode()) - } -} - -/// Wococo node as messages source. -type WococoSourceClient = SubstrateMessagesSource; - -/// Rococo node as messages target. -type RococoTargetClient = SubstrateMessagesTarget; - -/// Run Wococo-to-Rococo messages sync. -pub async fn run( - params: MessagesRelayParams< - Wococo, - WococoSigningParams, - Rococo, - RococoSigningParams, - MixStrategy, - >, -) -> anyhow::Result<()> { - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transactions_mortality, - params.target_transactions_mortality, - Wococo::AVERAGE_BLOCK_INTERVAL, - Rococo::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); - - let lane_id = params.lane_id; - let source_client = params.source_client; - let target_client = params.target_client; - let lane = WococoMessagesToRococo { - message_lane: SubstrateMessageLaneToSubstrate { - source_client: source_client.clone(), - source_sign: params.source_sign, - source_transactions_mortality: params.source_transactions_mortality, - target_client: target_client.clone(), - target_sign: params.target_sign, - target_transactions_mortality: params.target_transactions_mortality, - relayer_id_at_source: relayer_id_at_wococo, - }, - }; - - // 2/3 is reserved for proofs and tx overhead - let max_messages_size_in_single_batch = bp_rococo::max_extrinsic_size() / 3; - // we don't know exact weights of the Rococo runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits::< - pallet_bridge_messages::weights::RialtoWeight, - >( - bp_rococo::max_extrinsic_weight(), - bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - ); - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - - log::info!( - target: "bridge", - "Starting Wococo -> Rococo messages relay.\n\t\ - Wococo relayer account id: {:?}\n\t\ - Max messages in single transaction: {}\n\t\ - Max messages size in single transaction: {}\n\t\ - Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ - Stall timeout: {:?}", - lane.message_lane.relayer_id_at_source, - max_messages_in_single_batch, - max_messages_size_in_single_batch, - max_messages_weight_in_single_batch, - params.source_transactions_mortality, - params.target_transactions_mortality, - stall_timeout, - ); - - let standalone_metrics = params - .standalone_metrics - .map(Ok) - .unwrap_or_else(|| standalone_metrics(source_client.clone(), target_client.clone()))?; - messages_relay::message_lane_loop::run( - messages_relay::message_lane_loop::Params { - lane: lane_id, - source_tick: Wococo::AVERAGE_BLOCK_INTERVAL, - target_tick: Rococo::AVERAGE_BLOCK_INTERVAL, - reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, - delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { - max_unrewarded_relayer_entries_at_target: - bp_rococo::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, - max_unconfirmed_nonces_at_target: - bp_rococo::MAX_UNCONFIRMED_MESSAGES_AT_INBOUND_LANE, - max_messages_in_single_batch, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, - }, - }, - WococoSourceClient::new( - source_client.clone(), - lane.clone(), - lane_id, - params.target_to_source_headers_relay, - ), - RococoTargetClient::new( - target_client, - lane, - lane_id, - standalone_metrics.clone(), - params.source_to_target_headers_relay, - ), - standalone_metrics.register_and_spawn(params.metrics_params)?, - futures::future::pending(), - ) - .await - .map_err(Into::into) -} + type ReceiveMessagesProofCallBuilder = WococoMessagesToRococoReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder; -/// Create standalone metrics for the Wococo -> Rococo messages loop. -pub(crate) fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - substrate_relay_helper::messages_lane::standalone_metrics( - source_client, - target_client, - None, - None, - None, - None, - ) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 1af6142c53eca..2eb836a84a753 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -68,7 +68,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::millau_messages_to_rialto::run as relay_messages; + use crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -90,7 +90,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rialto_messages_to_millau::run as relay_messages; + use crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -113,7 +113,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rococo_messages_to_wococo::run as relay_messages; + use crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -135,7 +135,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::wococo_messages_to_rococo::run as relay_messages; + use crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -157,7 +157,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::kusama_messages_to_polkadot::run as relay_messages; + use crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -179,7 +179,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::polkadot_messages_to_kusama::run as relay_messages; + use crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index e17854662e5c4..8be04a88ff753 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -84,9 +84,6 @@ pub enum Call { } pub trait CliEncodeCall: Chain { - /// Maximal size (in bytes) of any extrinsic (from the runtime). - fn max_extrinsic_size() -> u32; - /// Encode a CLI call. fn encode_call(call: &Call) -> anyhow::Result; diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index f1180059b9949..ae167334d8292 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -20,7 +20,6 @@ use std::convert::TryInto; use bp_messages::LaneId; use codec::{Decode, Encode}; -use frame_support::weights::Weight; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; @@ -258,9 +257,6 @@ pub trait CliChain: relay_substrate_client::Chain { fn encode_message( message: crate::cli::encode_message::MessagePayload, ) -> anyhow::Result; - - /// Maximal extrinsic weight (from the runtime). - fn max_extrinsic_weight() -> Weight; } /// Lane id. diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index a8179478f810a..43def352a4d1d 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -125,11 +125,10 @@ impl RelayHeaders { let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - let target_transactions_params = - substrate_relay_helper::finality_pipeline::TransactionParams { - transactions_signer: target_sign, - transactions_mortality: target_transactions_mortality, - }; + let target_transactions_params = substrate_relay_helper::TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }; Finality::start_relay_guards(&target_client, &target_transactions_params); substrate_relay_helper::finality_pipeline::run::( diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 86b2fbfb4d1b4..112d2f419bda3 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -35,7 +35,7 @@ use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, - on_demand_headers::OnDemandHeadersRelay, + on_demand_headers::OnDemandHeadersRelay, TransactionParams, }; use crate::{ @@ -139,13 +139,12 @@ macro_rules! select_bridge { use crate::chains::{ millau_messages_to_rialto::{ - run as left_to_right_messages, - standalone_metrics as left_to_right_standalone_metrics, update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, + MillauMessagesToRialto as LeftToRightMessageLane, }, rialto_messages_to_millau::{ - run as right_to_left_messages, update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, + RialtoMessagesToMillau as RightToLeftMessageLane, }, }; @@ -187,11 +186,8 @@ macro_rules! select_bridge { bp_wococo::SESSION_LENGTH; use crate::chains::{ - rococo_messages_to_wococo::{ - run as left_to_right_messages, - standalone_metrics as left_to_right_standalone_metrics, - }, - wococo_messages_to_rococo::run as right_to_left_messages, + rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane, + wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, }; async fn update_right_to_left_conversion_rate( @@ -269,13 +265,12 @@ macro_rules! select_bridge { use crate::chains::{ kusama_messages_to_polkadot::{ - run as left_to_right_messages, - standalone_metrics as left_to_right_standalone_metrics, update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, + KusamaMessagesToPolkadot as LeftToRightMessageLane, }, polkadot_messages_to_kusama::{ - run as right_to_left_messages, update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, + PolkadotMessagesToKusama as RightToLeftMessageLane, }, }; @@ -358,7 +353,9 @@ impl RelayHeadersAndMessages { let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); let left_to_right_metrics = - left_to_right_standalone_metrics(left_client.clone(), right_client.clone())?; + substrate_relay_helper::messages_metrics::standalone_metrics::< + LeftToRightMessageLane, + >(left_client.clone(), right_client.clone())?; let right_to_left_metrics = left_to_right_metrics.clone().reverse(); // start conversion rate update loops for left/right chains @@ -489,16 +486,14 @@ impl RelayHeadersAndMessages { } // start on-demand header relays - let left_to_right_transaction_params = - substrate_relay_helper::finality_pipeline::TransactionParams { - transactions_mortality: right_transactions_mortality, - transactions_signer: right_sign.clone(), - }; - let right_to_left_transaction_params = - substrate_relay_helper::finality_pipeline::TransactionParams { - transactions_mortality: left_transactions_mortality, - transactions_signer: left_sign.clone(), - }; + let left_to_right_transaction_params = TransactionParams { + mortality: right_transactions_mortality, + signer: right_sign.clone(), + }; + let right_to_left_transaction_params = TransactionParams { + mortality: left_transactions_mortality, + signer: left_sign.clone(), + }; LeftToRightFinality::start_relay_guards( &right_client, &left_to_right_transaction_params, @@ -526,13 +521,19 @@ impl RelayHeadersAndMessages { let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { let lane = lane.into(); - let left_to_right_messages = left_to_right_messages(MessagesRelayParams { + let left_to_right_messages = substrate_relay_helper::messages_lane::run::< + LeftToRightMessageLane, + >(MessagesRelayParams { source_client: left_client.clone(), - source_sign: left_sign.clone(), - source_transactions_mortality: left_transactions_mortality, + source_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, target_client: right_client.clone(), - target_sign: right_sign.clone(), - target_transactions_mortality: right_transactions_mortality, + target_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), lane_id: lane, @@ -542,13 +543,19 @@ impl RelayHeadersAndMessages { }) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); - let right_to_left_messages = right_to_left_messages(MessagesRelayParams { + let right_to_left_messages = substrate_relay_helper::messages_lane::run::< + RightToLeftMessageLane, + >(MessagesRelayParams { source_client: right_client.clone(), - source_sign: right_sign.clone(), - source_transactions_mortality: right_transactions_mortality, + source_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, target_client: left_client.clone(), - target_sign: left_sign.clone(), - target_transactions_mortality: left_transactions_mortality, + target_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), lane_id: lane, diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index e47abfc5d94e3..45087fad5eb3f 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -18,7 +18,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use messages_relay::relay_strategy::MixStrategy; -use substrate_relay_helper::messages_lane::MessagesRelayParams; +use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; use crate::{ cli::{ @@ -84,13 +84,17 @@ impl RelayMessages { let relayer_mode = self.relayer_mode.into(); let relay_strategy = MixStrategy::new(relayer_mode); - relay_messages(MessagesRelayParams { + substrate_relay_helper::messages_lane::run::(MessagesRelayParams { source_client, - source_sign, - source_transactions_mortality, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, target_client, - target_sign, - target_transactions_mortality, + target_transaction_params: TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }, source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: self.lane.into(), diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 3e77ad8342927..5c403f6c23a95 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -22,7 +22,7 @@ use crate::cli::{ SourceSigningParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; -use bp_runtime::BalanceOf; +use bp_runtime::{BalanceOf, Chain as _}; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index b1ea0f5fefbf7..861816bb67390 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Kusama chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -44,10 +46,19 @@ impl ChainBase for Kusama { type Balance = bp_kusama::Balance; type Index = bp_kusama::Nonce; type Signature = bp_kusama::Signature; + + fn max_extrinsic_size() -> u32 { + bp_kusama::Kusama::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_kusama::Kusama::max_extrinsic_weight() + } } impl Chain for Kusama { const NAME: &'static str = "Kusama"; + const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -59,6 +70,30 @@ impl Chain for Kusama { type WeightToFee = bp_kusama::WeightToFee; } +impl ChainWithMessages for Kusama { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_kusama::account_info_storage_key(account_id)) diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 49d9dade154c2..da3d4e7fe1d6c 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Supported Chains +bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } millau-runtime = { path = "../../bin/millau/runtime" } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index e7ee54afb0846..96a046ef5cdc2 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -16,9 +16,11 @@ //! Types used to connect to the Millau-Substrate chain. +use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -42,10 +44,44 @@ impl ChainBase for Millau { type Balance = millau_runtime::Balance; type Index = millau_runtime::Index; type Signature = millau_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_millau::Millau::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_millau::Millau::max_extrinsic_weight() + } +} + +impl ChainWithMessages for Millau { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); } impl Chain for Millau { const NAME: &'static str = "Millau"; + // Rialto token has no value, but we associate it with KSM token + const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index e5c7f62fa1724..d468206f9d5ea 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Polkadot chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -44,10 +46,19 @@ impl ChainBase for Polkadot { type Balance = bp_polkadot::Balance; type Index = bp_polkadot::Nonce; type Signature = bp_polkadot::Signature; + + fn max_extrinsic_size() -> u32 { + bp_polkadot::Polkadot::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_polkadot::Polkadot::max_extrinsic_weight() + } } impl Chain for Polkadot { const NAME: &'static str = "Polkadot"; + const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -59,6 +70,30 @@ impl Chain for Polkadot { type WeightToFee = bp_polkadot::WeightToFee; } +impl ChainWithMessages for Polkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_polkadot::account_info_storage_key(account_id)) diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index b34154393a1b1..65bf46f660cc7 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Rialto-Substrate chain. +use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase}; use std::time::Duration; @@ -37,10 +38,19 @@ impl ChainBase for RialtoParachain { type Balance = rialto_parachain_runtime::Balance; type Index = rialto_parachain_runtime::Index; type Signature = rialto_parachain_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rialto::Rialto::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::Rialto::max_extrinsic_weight() + } } impl Chain for RialtoParachain { const NAME: &'static str = "RialtoParachain"; + const TOKEN_ID: Option<&'static str> = None; // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 3132b26d27fc1..483812ca80885 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies +bp-messages = { path = "../../primitives/messages" } bp-rialto = { path = "../../primitives/chain-rialto" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 60c6e9388b69b..80e3c2c7ae748 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -16,9 +16,11 @@ //! Types used to connect to the Rialto-Substrate chain. +use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; +use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, IndexOf, TransactionEraOf, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -42,10 +44,20 @@ impl ChainBase for Rialto { type Balance = rialto_runtime::Balance; type Index = rialto_runtime::Index; type Signature = rialto_runtime::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rialto::Rialto::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rialto::Rialto::max_extrinsic_weight() + } } impl Chain for Rialto { const NAME: &'static str = "Rialto"; + // Rialto token has no value, but we associate it with DOT token + const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); @@ -57,6 +69,30 @@ impl Chain for Rialto { type WeightToFee = bp_rialto::WeightToFee; } +impl ChainWithMessages for Rialto { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Rialto { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 7ee51730e9961..ee17e62dcd71f 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Rococo-Substrate chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -47,10 +49,19 @@ impl ChainBase for Rococo { type Balance = bp_rococo::Balance; type Index = bp_rococo::Nonce; type Signature = bp_rococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_rococo::Rococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rococo::Rococo::max_extrinsic_weight() + } } impl Chain for Rococo { const NAME: &'static str = "Rococo"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -62,6 +73,30 @@ impl Chain for Rococo { type WeightToFee = bp_rococo::WeightToFee; } +impl ChainWithMessages for Rococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_rococo::account_info_storage_key(account_id)) diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index df69b0a6a9c34..b13808059964a 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -74,7 +74,7 @@ pub enum Call { BridgeGrandpaWococo(BridgeGrandpaWococoCall), /// Wococo messages pallet. #[codec(index = 44)] - BridgeMessagesWococo(BridgeMessagesWococoCall), + BridgeWococoMessages(BridgeWococoMessagesCall), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -105,7 +105,7 @@ pub enum BridgeGrandpaWococoCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] -pub enum BridgeMessagesWococoCall { +pub enum BridgeWococoMessagesCall { #[codec(index = 3)] send_message( LaneId, diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 2eb07fdcde467..eacaa929a94da 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -20,7 +20,9 @@ thiserror = "1.0.26" # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } bp-runtime = { path = "../../primitives/runtime" } +pallet-bridge-messages = { path = "../../modules/messages" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 97063c15c8606..6b62e699b7ef4 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -14,9 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_messages::MessageNonce; use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; -use frame_support::weights::WeightToFeePolynomial; +use frame_support::weights::{Weight, WeightToFeePolynomial}; use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; @@ -32,6 +33,11 @@ use std::{fmt::Debug, time::Duration}; pub trait Chain: ChainBase + Clone { /// Chain name. const NAME: &'static str; + /// Identifier of the basic token of the chain (if applicable). + /// + /// This identifier is used to fetch token price. In case of testnets, you may either + /// set it to `None`, or associate testnet with one of the existing tokens. + const TOKEN_ID: Option<&'static str>; /// Name of the runtime API method that is returning best known finalized header number /// and hash (as tuple). /// @@ -52,12 +58,56 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Clone + Dispatchable + Debug + Send; + type Call: Clone + Codec + Dispatchable + Debug + Send; /// Type that is used by the chain, to convert from weight to fee. type WeightToFee: WeightToFeePolynomial; } +/// Substrate-based chain with messaging support from minimal relay-client point of view. +pub trait ChainWithMessages: Chain { + /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed + /// at some other chain to bridge with this `ChainWithMessages`. + /// + /// We assume that all chains that are bridging with this `ChainWithMessages` are using + /// the same name. + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str; + + /// Name of the `ToOutboundLaneApi::message_details` runtime API method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; + /// Name of the `ToOutboundLaneApi::latest_generated_nonce` runtime API + /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str; + /// Name of the `ToOutboundLaneApi::latest_received_nonce` runtime API + /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; + + /// Name of the `FromInboundLaneApi::latest_received_nonce` runtime method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; + /// Name of the `FromInboundLaneApi::latest_confirmed_nonce` runtime method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str; + /// Name of the `FromInboundLaneApi::unrewarded_relayers_state` runtime + /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str; + + /// Additional weight of the dispatch fee payment if dispatch is paid at the target chain + /// and this `ChainWithMessages` is the target chain. + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight; + + /// Maximal number of unrewarded relayers in a single confirmation transaction at this + /// `ChainWithMessages`. + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce; + /// Maximal number of unconfirmed messages in a single confirmation transaction at this + /// `ChainWithMessages`. + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; + + /// Weights of message pallet calls. + type WeightInfo: pallet_bridge_messages::WeightInfoExt; +} + /// Call type used by the chain. pub type CallOf = ::Call; /// Weight-to-Fee type used by the chain. diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 93b76bdf9f07e..c31482eec3967 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -181,7 +181,7 @@ impl Environment for Client { #[cfg(test)] mod tests { use super::*; - use frame_support::weights::IdentityFee; + use frame_support::weights::{IdentityFee, Weight}; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, future::FutureExt, @@ -202,10 +202,18 @@ mod tests { type Balance = u32; type Index = u32; type Signature = sp_runtime::testing::TestSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } } impl Chain for TestChain { const NAME: &'static str = "Test"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); const STORAGE_PROOF_OVERHEAD: u32 = 0; diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index f03b79228bf08..56a6c981fcb18 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -32,7 +32,8 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, + ChainWithMessages, TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, + WeightToFeeOf, }, client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 24b05c4f4836b..9bbb0b6fb13f5 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -16,5 +16,6 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 6d43aa837b29b..004cb5476be7e 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Westend chain. +use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -40,10 +41,19 @@ impl ChainBase for Westend { type Balance = bp_westend::Balance; type Index = bp_westend::Nonce; type Signature = bp_westend::Signature; + + fn max_extrinsic_size() -> u32 { + bp_westend::Westend::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_westend::Westend::max_extrinsic_weight() + } } impl Chain for Westend { const NAME: &'static str = "Westend"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index a15ff469991b1..e9bdfd834a91e 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,10 +16,12 @@ //! Types used to connect to the Wococo-Substrate chain. +use bp_messages::MessageNonce; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, TransactionEraOf, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -47,10 +49,19 @@ impl ChainBase for Wococo { type Balance = bp_wococo::Balance; type Index = bp_wococo::Nonce; type Signature = bp_wococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_wococo::Wococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_wococo::Wococo::max_extrinsic_weight() + } } impl Chain for Wococo { const NAME: &'static str = "Wococo"; + const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -62,6 +73,30 @@ impl Chain for Wococo { type WeightToFee = bp_wococo::WeightToFee; } +impl ChainWithMessages for Wococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; + const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; + const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; + const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = + bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_wococo::account_info_storage_key(account_id)) diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index 38a40abd21208..b28e053086b16 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -74,7 +74,7 @@ pub enum Call { BridgeGrandpaRococo(BridgeGrandpaRococoCall), /// Rococo messages pallet. #[codec(index = 43)] - BridgeMessagesRococo(BridgeMessagesRococoCall), + BridgeRococoMessages(BridgeRococoMessagesCall), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -105,7 +105,7 @@ pub enum BridgeGrandpaRococoCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] -pub enum BridgeMessagesRococoCall { +pub enum BridgeRococoMessagesCall { #[codec(index = 3)] send_message( LaneId, diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 89d03803b35f6..1224d8143938c 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -42,6 +42,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master [dev-dependencies] bp-millau = { path = "../../primitives/chain-millau" } +bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } relay-rococo-client = { path = "../client-rococo" } diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 1266ed59ed00e..87e50be03932c 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -17,7 +17,10 @@ //! Types and functions intended to ease adding of new Substrate -> Substrate //! finality proofs synchronization pipelines. -use crate::{finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget}; +use crate::{ + finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget, + TransactionParams, +}; use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; @@ -36,15 +39,6 @@ use std::{fmt::Debug, marker::PhantomData}; /// Substrate+GRANDPA based chains (good to know). pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; -/// Submit-finality-proofs transaction creation parameters. -#[derive(Clone, Debug)] -pub struct TransactionParams { - /// Transactions author. - pub transactions_signer: TS, - /// Transactions mortality. - pub transactions_mortality: Option, -} - /// Substrate -> Substrate finality proofs synchronization pipeline. pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. @@ -67,7 +61,7 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`. #[derive(Clone, Debug)] -pub struct FinalitySyncPipelineAdapter { +pub(crate) struct FinalitySyncPipelineAdapter { _phantom: PhantomData

, } @@ -179,7 +173,7 @@ where ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, stall_timeout: transaction_stall_timeout( - transaction_params.transactions_mortality, + transaction_params.mortality, P::TargetChain::AVERAGE_BLOCK_INTERVAL, crate::STALL_TIMEOUT, ), diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index adfe12ab35b8e..5daf6c7538a36 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -18,8 +18,10 @@ //! bridge GRANDPA pallet deployed and provide `FinalityApi` to allow bridging //! with chain. -use crate::finality_pipeline::{ - FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, +use crate::{ + finality_pipeline::{ + FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, + }, TransactionParams, }; @@ -103,16 +105,13 @@ where P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); self.client .submit_signed_extrinsic( - self.transaction_params.transactions_signer.public().into(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { Bytes( P::TransactionSignScheme::sign_transaction( genesis_hash, - &transaction_params.transactions_signer, - TransactionEra::new( - best_block_id, - transaction_params.transactions_mortality, - ), + &transaction_params.signer, + TransactionEra::new(best_block_id, transaction_params.mortality), UnsignedTransaction::new(call, transaction_nonce), ) .encode(), diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 1c62ddaa9a7ee..c27aa7b708fd5 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -28,6 +28,7 @@ pub mod finality_target; pub mod headers_initialize; pub mod helpers; pub mod messages_lane; +pub mod messages_metrics; pub mod messages_source; pub mod messages_target; pub mod on_demand_headers; @@ -40,3 +41,12 @@ pub mod on_demand_headers; /// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine /// transaction, or remove it from the pool. pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); + +/// Transaction creation parameters. +#[derive(Clone, Debug)] +pub struct TransactionParams { + /// Transactions author. + pub signer: TS, + /// Transactions mortality. + pub mortality: Option, +} diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 6cadb64754a51..4742ce6e48296 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -17,194 +17,396 @@ //! Tools for supporting message lanes between two Substrate-based chains. use crate::{ - messages_source::SubstrateMessagesProof, messages_target::SubstrateMessagesReceivingProof, + messages_metrics::StandaloneMessagesMetrics, + messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, + messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, STALL_TIMEOUT, }; -use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, IndexOf}; -use frame_support::weights::Weight; -use messages_relay::{ - message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - relay_strategy::RelayStrategy, +use bp_runtime::{AccountIdOf, Chain as _}; +use bridge_runtime_common::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; +use codec::Encode; +use frame_support::weights::{GetDispatchInfo, Weight}; +use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; +use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - BlockNumberOf, Chain, Client, HashOf, + AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, Client, HashOf, + TransactionSignScheme, }; -use relay_utils::{ - metrics::{ - FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, - }, - BlockNumberBase, -}; -use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::FixedU128; -use std::ops::RangeInclusive; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; +use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; + +/// Substrate -> Substrate messages synchronization pipeline. +pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { + /// Name of the source -> target tokens conversion rate parameter name. + /// + /// The parameter is stored at the target chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + /// Name of the target -> source tokens conversion rate parameter name. + /// + /// The parameter is stored at the source chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + + /// Messages of this chain are relayed to the `TargetChain`. + type SourceChain: ChainWithMessages; + /// Messages from the `SourceChain` are dispatched on this chain. + type TargetChain: ChainWithMessages; + + /// Scheme used to sign source chain transactions. + type SourceTransactionSignScheme: TransactionSignScheme; + /// Scheme used to sign target chain transactions. + type TargetTransactionSignScheme: TransactionSignScheme; + + /// How receive messages proof call is built? + type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder; + /// How receive messages delivery proof call is built? + type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; + + /// Message relay strategy. + type RelayStrategy: RelayStrategy; +} + +/// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. +#[derive(Clone, Debug)] +pub(crate) struct MessageLaneAdapter { + _phantom: PhantomData

, +} + +impl MessageLane for MessageLaneAdapter

{ + const SOURCE_NAME: &'static str = P::SourceChain::NAME; + const TARGET_NAME: &'static str = P::TargetChain::NAME; + + type MessagesProof = SubstrateMessagesProof; + type MessagesReceivingProof = SubstrateMessagesDeliveryProof; + + type SourceChainBalance = BalanceOf; + type SourceHeaderNumber = BlockNumberOf; + type SourceHeaderHash = HashOf; + + type TargetHeaderNumber = BlockNumberOf; + type TargetHeaderHash = HashOf; +} /// Substrate <-> Substrate messages relay parameters. -pub struct MessagesRelayParams { +pub struct MessagesRelayParams { /// Messages source client. - pub source_client: Client, - /// Sign parameters for messages source chain. - pub source_sign: SS, - /// Mortality of source transactions. - pub source_transactions_mortality: Option, + pub source_client: Client, + /// Source transaction params. + pub source_transaction_params: + TransactionParams>, /// Messages target client. - pub target_client: Client, - /// Sign parameters for messages target chain. - pub target_sign: TS, - /// Mortality of target transactions. - pub target_transactions_mortality: Option, + pub target_client: Client, + /// Target transaction params. + pub target_transaction_params: + TransactionParams>, /// Optional on-demand source to target headers relay. - pub source_to_target_headers_relay: Option>, + pub source_to_target_headers_relay: Option>, /// Optional on-demand target to source headers relay. - pub target_to_source_headers_relay: Option>, + pub target_to_source_headers_relay: Option>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, /// Metrics parameters. pub metrics_params: MetricsParams, /// Pre-registered standalone metrics. - pub standalone_metrics: Option>, - /// Relay strategy - pub relay_strategy: Strategy, + pub standalone_metrics: Option>, + /// Relay strategy. + pub relay_strategy: P::RelayStrategy, } -/// Message sync pipeline for Substrate <-> Substrate relays. -#[async_trait] -pub trait SubstrateMessageLane: 'static + Clone + Send + Sync { - /// Underlying generic message lane. - type MessageLane: MessageLane; - - /// Name of the runtime method that returns dispatch weight of outbound messages at the source - /// chain. - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the runtime method that returns latest generated nonce at the source chain. - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns latest received (confirmed) nonce at the the source - /// chain. - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - - /// Name of the runtime method that returns latest received nonce at the target chain. - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str; - /// Name of the runtime method that returns the latest confirmed (reward-paid) nonce at the - /// target chain. - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str; - /// Number of the runtime method that returns state of "unrewarded relayers" set at the target - /// chain. - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str; - - /// Name of the runtime method that returns id of best finalized source header at target chain. - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str; - /// Name of the runtime method that returns id of best finalized target header at source chain. - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str; - - /// Name of the messages pallet as it is declared in the `construct_runtime!()` at source chain. - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str; - /// Name of the messages pallet as it is declared in the `construct_runtime!()` at target chain. - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str; - - /// Extra weight of the delivery transaction at the target chain, that is paid to cover - /// dispatch fee payment. - /// - /// If dispatch fee is paid at the source chain, then this weight is refunded by the - /// delivery transaction. - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight; - - /// Source chain. - type SourceChain: Chain; - /// Target chain. - type TargetChain: Chain; - - /// Returns id of account that we're using to sign transactions at target chain (messages - /// proof). - fn target_transactions_author(&self) -> AccountIdOf; - - /// Make messages delivery transaction. - fn make_messages_delivery_transaction( - &self, - best_block_id: TargetHeaderIdOf, - transaction_nonce: IndexOf, - generated_at_header: SourceHeaderIdOf, - nonces: RangeInclusive, - proof: ::MessagesProof, - ) -> Bytes; - - /// Returns id of account that we're using to sign transactions at source chain (delivery - /// proof). - fn source_transactions_author(&self) -> AccountIdOf; - - /// Make messages receiving proof transaction. - fn make_messages_receiving_proof_transaction( - &self, - best_block_id: SourceHeaderIdOf, - transaction_nonce: IndexOf, - generated_at_header: TargetHeaderIdOf, - proof: ::MessagesReceivingProof, - ) -> Bytes; +/// Run Substrate-to-Substrate messages sync loop. +pub async fn run(params: MessagesRelayParams

) -> anyhow::Result<()> +where + AccountIdOf: + From< as Pair>::Public>, + AccountIdOf: + From< as Pair>::Public>, + BalanceOf: TryFrom>, + P::SourceTransactionSignScheme: TransactionSignScheme, + P::TargetTransactionSignScheme: TransactionSignScheme, +{ + let source_client = params.source_client; + let target_client = params.target_client; + let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( + params.source_transaction_params.mortality, + params.target_transaction_params.mortality, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); + let relayer_id_at_source: AccountIdOf = + params.source_transaction_params.signer.public().into(); + + // 2/3 is reserved for proofs and tx overhead + let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3; + // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using + // weights from Rialto and then simply dividing it by x2. + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + crate::messages_lane::select_delivery_transaction_limits::< + ::WeightInfo, + >( + P::TargetChain::max_extrinsic_weight(), + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + ); + let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = + (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); + + let standalone_metrics = params.standalone_metrics.map(Ok).unwrap_or_else(|| { + crate::messages_metrics::standalone_metrics::

( + source_client.clone(), + target_client.clone(), + ) + })?; + + log::info!( + target: "bridge", + "Starting {} -> {} messages relay.\n\t\ + {} relayer account id: {:?}\n\t\ + Max messages in single transaction: {}\n\t\ + Max messages size in single transaction: {}\n\t\ + Max messages weight in single transaction: {}\n\t\ + Tx mortality: {:?}/{:?}\n\t\ + Stall timeout: {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME, + relayer_id_at_source, + max_messages_in_single_batch, + max_messages_size_in_single_batch, + max_messages_weight_in_single_batch, + params.source_transaction_params.mortality, + params.target_transaction_params.mortality, + stall_timeout, + ); + + messages_relay::message_lane_loop::run( + messages_relay::message_lane_loop::Params { + lane: params.lane_id, + source_tick: P::SourceChain::AVERAGE_BLOCK_INTERVAL, + target_tick: P::TargetChain::AVERAGE_BLOCK_INTERVAL, + reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, + stall_timeout, + delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { + max_unrewarded_relayer_entries_at_target: + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_nonces_at_target: + P::SourceChain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + max_messages_in_single_batch, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + relay_strategy: params.relay_strategy, + }, + }, + SubstrateMessagesSource::

::new( + source_client, + params.lane_id, + params.source_transaction_params, + params.target_to_source_headers_relay, + ), + SubstrateMessagesTarget::

::new( + target_client, + params.lane_id, + relayer_id_at_source, + params.target_transaction_params, + standalone_metrics.clone(), + params.source_to_target_headers_relay, + ), + standalone_metrics.register_and_spawn(params.metrics_params)?, + futures::future::pending(), + ) + .await + .map_err(Into::into) +} + +/// Different ways of building `receive_messages_proof` calls. +pub trait ReceiveMessagesProofCallBuilder { + /// Given messages proof, build call of `receive_messages_proof` function of bridge + /// messages module at the target chain. + fn build_receive_messages_proof_call( + relayer_id_at_source: AccountIdOf, + proof: SubstrateMessagesProof, + messages_count: u32, + dispatch_weight: Weight, + trace_call: bool, + ) -> CallOf; } -/// Substrate-to-Substrate message lane. -#[derive(Debug)] -pub struct SubstrateMessageLaneToSubstrate< - Source: Chain, - SourceSignParams, - Target: Chain, - TargetSignParams, -> { - /// Client for the source Substrate chain. - pub source_client: Client, - /// Parameters required to sign transactions for source chain. - pub source_sign: SourceSignParams, - /// Source transactions mortality. - pub source_transactions_mortality: Option, - /// Client for the target Substrate chain. - pub target_client: Client, - /// Parameters required to sign transactions for target chain. - pub target_sign: TargetSignParams, - /// Target transactions mortality. - pub target_transactions_mortality: Option, - /// Account id of relayer at the source chain. - pub relayer_id_at_source: Source::AccountId, +/// Building `receive_messages_proof` call when you have direct access to the target +/// chain runtime. +pub struct DirectReceiveMessagesProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, } -impl Clone - for SubstrateMessageLaneToSubstrate +impl ReceiveMessagesProofCallBuilder

for DirectReceiveMessagesProofCallBuilder +where + P: SubstrateMessageLane, + R: BridgeMessagesConfig>, + I: 'static, + R::SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< + R::InboundMessageFee, + MessagesProof = FromBridgedChainMessagesProof>, + >, + CallOf: From> + GetDispatchInfo, { - fn clone(&self) -> Self { - Self { - source_client: self.source_client.clone(), - source_sign: self.source_sign.clone(), - source_transactions_mortality: self.source_transactions_mortality, - target_client: self.target_client.clone(), - target_sign: self.target_sign.clone(), - target_transactions_mortality: self.target_transactions_mortality, - relayer_id_at_source: self.relayer_id_at_source.clone(), + fn build_receive_messages_proof_call( + relayer_id_at_source: AccountIdOf, + proof: SubstrateMessagesProof, + messages_count: u32, + dispatch_weight: Weight, + trace_call: bool, + ) -> CallOf { + let call: CallOf = BridgeMessagesCall::::receive_messages_proof { + relayer_id_at_bridged_chain: relayer_id_at_source, + proof: proof.1, + messages_count, + dispatch_weight, + } + .into(); + if trace_call { + // this trace isn't super-accurate, because limits are for transactions and we + // have a call here, but it provides required information + log::trace!( + target: "bridge", + "Prepared {} -> {} messages delivery call. Weight: {}/{}, size: {}/{}", + P::SourceChain::NAME, + P::TargetChain::NAME, + call.get_dispatch_info().weight, + P::TargetChain::max_extrinsic_weight(), + call.encode().len(), + P::TargetChain::max_extrinsic_size(), + ); } + call } } -impl MessageLane - for SubstrateMessageLaneToSubstrate -where - SourceSignParams: Clone + Send + Sync + 'static, - TargetSignParams: Clone + Send + Sync + 'static, - BlockNumberOf: BlockNumberBase, - BlockNumberOf: BlockNumberBase, -{ - const SOURCE_NAME: &'static str = Source::NAME; - const TARGET_NAME: &'static str = Target::NAME; +/// Macro that generates `ReceiveMessagesProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of target chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls and the "name" of +/// the variant for the `receive_messages_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_receive_message_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_proof:path) => { + pub struct $mocked_builder; + + impl $crate::messages_lane::ReceiveMessagesProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_receive_messages_proof_call( + relayer_id_at_source: relay_substrate_client::AccountIdOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + >, + proof: $crate::messages_source::SubstrateMessagesProof< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + >, + messages_count: u32, + dispatch_weight: Weight, + _trace_call: bool, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain + > { + $bridge_messages($receive_messages_proof( + relayer_id_at_source, + proof.1, + messages_count, + dispatch_weight, + )) + } + } + }; +} + +/// Different ways of building `receive_messages_delivery_proof` calls. +pub trait ReceiveMessagesDeliveryProofCallBuilder { + /// Given messages delivery proof, build call of `receive_messages_delivery_proof` function of + /// bridge messages module at the source chain. + fn build_receive_messages_delivery_proof_call( + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, + ) -> CallOf; +} - type MessagesProof = SubstrateMessagesProof; - type MessagesReceivingProof = SubstrateMessagesReceivingProof; +/// Building `receive_messages_delivery_proof` call when you have direct access to the source +/// chain runtime. +pub struct DirectReceiveMessagesDeliveryProofCallBuilder { + _phantom: PhantomData<(P, R, I)>, +} - type SourceChainBalance = Source::Balance; - type SourceHeaderNumber = BlockNumberOf; - type SourceHeaderHash = HashOf; +impl ReceiveMessagesDeliveryProofCallBuilder

+ for DirectReceiveMessagesDeliveryProofCallBuilder +where + P: SubstrateMessageLane, + R: BridgeMessagesConfig, + I: 'static, + R::TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain< + R::OutboundPayload, + R::AccountId, + MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof>, + >, + CallOf: From> + GetDispatchInfo, +{ + fn build_receive_messages_delivery_proof_call( + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, + ) -> CallOf { + let call: CallOf = + BridgeMessagesCall::::receive_messages_delivery_proof { + proof: proof.1, + relayers_state: proof.0, + } + .into(); + if trace_call { + // this trace isn't super-accurate, because limits are for transactions and we + // have a call here, but it provides required information + log::trace!( + target: "bridge", + "Prepared {} -> {} delivery confirmation transaction. Weight: {}/{}, size: {}/{}", + P::TargetChain::NAME, + P::SourceChain::NAME, + call.get_dispatch_info().weight, + P::SourceChain::max_extrinsic_weight(), + call.encode().len(), + P::SourceChain::max_extrinsic_size(), + ); + } + call + } +} - type TargetHeaderNumber = BlockNumberOf; - type TargetHeaderHash = HashOf; +/// Macro that generates `ReceiveMessagesDeliveryProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of source chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls and the "name" of +/// the variant for the `receive_messages_delivery_proof` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_receive_message_delivery_proof_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_delivery_proof:path) => { + pub struct $mocked_builder; + + impl $crate::messages_lane::ReceiveMessagesDeliveryProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_receive_messages_delivery_proof_call( + proof: $crate::messages_target::SubstrateMessagesDeliveryProof< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain + >, + _trace_call: bool, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain + > { + $bridge_messages($receive_messages_delivery_proof(proof.1, proof.0)) + } + } + }; } /// Returns maximal number of messages and their maximal cumulative dispatch weight, based @@ -245,155 +447,10 @@ pub fn select_delivery_transaction_limits { - /// Global metrics. - pub global: GlobalMetrics, - /// Storage chain proof overhead metric. - pub source_storage_proof_overhead: StorageProofOverheadMetric, - /// Target chain proof overhead metric. - pub target_storage_proof_overhead: StorageProofOverheadMetric, - /// Source tokens to base conversion rate metric. - pub source_to_base_conversion_rate: Option, - /// Target tokens to base conversion rate metric. - pub target_to_base_conversion_rate: Option, - /// Source tokens to target tokens conversion rate metric. This rate is stored by the target - /// chain. - pub source_to_target_conversion_rate: - Option>, - /// Target tokens to source tokens conversion rate metric. This rate is stored by the source - /// chain. - pub target_to_source_conversion_rate: - Option>, -} - -impl StandaloneMessagesMetrics { - /// Swap source and target sides. - pub fn reverse(self) -> StandaloneMessagesMetrics { - StandaloneMessagesMetrics { - global: self.global, - source_storage_proof_overhead: self.target_storage_proof_overhead, - target_storage_proof_overhead: self.source_storage_proof_overhead, - source_to_base_conversion_rate: self.target_to_base_conversion_rate, - target_to_base_conversion_rate: self.source_to_base_conversion_rate, - source_to_target_conversion_rate: self.target_to_source_conversion_rate, - target_to_source_conversion_rate: self.source_to_target_conversion_rate, - } - } - - /// Register all metrics in the registry. - pub fn register_and_spawn( - self, - metrics: MetricsParams, - ) -> Result { - self.global.register_and_spawn(&metrics.registry)?; - self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - if let Some(m) = self.source_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_source_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - Ok(metrics) - } - - /// Return conversion rate from target to source tokens. - pub async fn target_to_source_conversion_rate(&self) -> Option { - Self::compute_target_to_source_conversion_rate( - *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - ) - } - - /// Return conversion rate from target to source tokens, given conversion rates from - /// target/source tokens to some base token. - fn compute_target_to_source_conversion_rate( - target_to_base_conversion_rate: Option, - source_to_base_conversion_rate: Option, - ) -> Option { - Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) - } -} - -/// Create standalone metrics for the message lane relay loop. -/// -/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) -/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). -pub fn standalone_metrics( - source_client: Client, - target_client: Client, - source_chain_token_id: Option<&str>, - target_chain_token_id: Option<&str>, - source_to_target_conversion_rate_params: Option<(StorageKey, FixedU128)>, - target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, -) -> anyhow::Result> { - Ok(StandaloneMessagesMetrics { - global: GlobalMetrics::new()?, - source_storage_proof_overhead: StorageProofOverheadMetric::new( - source_client.clone(), - format!("{}_storage_proof_overhead", SC::NAME.to_lowercase()), - format!("{} storage proof overhead", SC::NAME), - )?, - target_storage_proof_overhead: StorageProofOverheadMetric::new( - target_client.clone(), - format!("{}_storage_proof_overhead", TC::NAME.to_lowercase()), - format!("{} storage proof overhead", TC::NAME), - )?, - source_to_base_conversion_rate: source_chain_token_id - .map(|source_chain_token_id| { - crate::helpers::token_price_metric(source_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_base_conversion_rate: target_chain_token_id - .map(|target_chain_token_id| { - crate::helpers::token_price_metric(target_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - source_to_target_conversion_rate: source_to_target_conversion_rate_params - .map(|(key, rate)| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - target_client, - key, - Some(rate), - format!("{}_{}_to_{}_conversion_rate", TC::NAME, SC::NAME, TC::NAME), - format!( - "{} to {} tokens conversion rate (used by {})", - SC::NAME, - TC::NAME, - TC::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_source_conversion_rate: target_to_source_conversion_rate_params - .map(|(key, rate)| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - source_client, - key, - Some(rate), - format!("{}_{}_to_{}_conversion_rate", SC::NAME, TC::NAME, SC::NAME), - format!( - "{} to {} tokens conversion rate (used by {})", - TC::NAME, - SC::NAME, - SC::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - }) -} - #[cfg(test)] mod tests { use super::*; + use bp_runtime::Chain; type RialtoToMillauMessagesWeights = pallet_bridge_messages::weights::RialtoWeight; @@ -402,8 +459,8 @@ mod tests { fn select_delivery_transaction_limits_works() { let (max_count, max_weight) = select_delivery_transaction_limits::( - bp_millau::max_extrinsic_weight(), - bp_millau::MAX_UNREWARDED_RELAYER_ENTRIES_AT_INBOUND_LANE, + bp_millau::Millau::max_extrinsic_weight(), + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, ); assert_eq!( (max_count, max_weight), @@ -415,12 +472,4 @@ mod tests { (782, 216_583_333_334), ); } - - #[async_std::test] - async fn target_to_source_conversion_rate_works() { - assert_eq!( - StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), - Some(12.32 / 183.15), - ); - } } diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs new file mode 100644 index 0000000000000..54eef6c0ae81e --- /dev/null +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -0,0 +1,199 @@ +// 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 . + +//! Tools for supporting message lanes between two Substrate-based chains. + +use crate::messages_lane::SubstrateMessageLane; + +use num_traits::One; +use relay_substrate_client::{ + metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, + Chain, Client, +}; +use relay_utils::metrics::{ + FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, +}; +use sp_runtime::FixedU128; +use std::fmt::Debug; + +/// Shared references to the standalone metrics of the message lane relay loop. +#[derive(Debug, Clone)] +pub struct StandaloneMessagesMetrics { + /// Global metrics. + pub global: GlobalMetrics, + /// Storage chain proof overhead metric. + pub source_storage_proof_overhead: StorageProofOverheadMetric, + /// Target chain proof overhead metric. + pub target_storage_proof_overhead: StorageProofOverheadMetric, + /// Source tokens to base conversion rate metric. + pub source_to_base_conversion_rate: Option, + /// Target tokens to base conversion rate metric. + pub target_to_base_conversion_rate: Option, + /// Source tokens to target tokens conversion rate metric. This rate is stored by the target + /// chain. + pub source_to_target_conversion_rate: + Option>, + /// Target tokens to source tokens conversion rate metric. This rate is stored by the source + /// chain. + pub target_to_source_conversion_rate: + Option>, +} + +impl StandaloneMessagesMetrics { + /// Swap source and target sides. + pub fn reverse(self) -> StandaloneMessagesMetrics { + StandaloneMessagesMetrics { + global: self.global, + source_storage_proof_overhead: self.target_storage_proof_overhead, + target_storage_proof_overhead: self.source_storage_proof_overhead, + source_to_base_conversion_rate: self.target_to_base_conversion_rate, + target_to_base_conversion_rate: self.source_to_base_conversion_rate, + source_to_target_conversion_rate: self.target_to_source_conversion_rate, + target_to_source_conversion_rate: self.source_to_target_conversion_rate, + } + } + + /// Register all metrics in the registry. + pub fn register_and_spawn( + self, + metrics: MetricsParams, + ) -> Result { + self.global.register_and_spawn(&metrics.registry)?; + self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; + if let Some(m) = self.source_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_base_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_to_source_conversion_rate { + m.register_and_spawn(&metrics.registry)?; + } + Ok(metrics) + } + + /// Return conversion rate from target to source tokens. + pub async fn target_to_source_conversion_rate(&self) -> Option { + Self::compute_target_to_source_conversion_rate( + *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, + *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, + ) + } + + /// Return conversion rate from target to source tokens, given conversion rates from + /// target/source tokens to some base token. + fn compute_target_to_source_conversion_rate( + target_to_base_conversion_rate: Option, + source_to_base_conversion_rate: Option, + ) -> Option { + Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) + } +} + +/// Create standalone metrics for the message lane relay loop. +/// +/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) +/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). +/// We assume that either conversion rate parameters have values in the storage, or they are +/// initialized with 1:1. +pub fn standalone_metrics( + source_client: Client, + target_client: Client, +) -> anyhow::Result> { + Ok(StandaloneMessagesMetrics { + global: GlobalMetrics::new()?, + source_storage_proof_overhead: StorageProofOverheadMetric::new( + source_client.clone(), + format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::SourceChain::NAME), + )?, + target_storage_proof_overhead: StorageProofOverheadMetric::new( + target_client.clone(), + format!("{}_storage_proof_overhead", P::TargetChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::TargetChain::NAME), + )?, + source_to_base_conversion_rate: P::SourceChain::TOKEN_ID + .map(|source_chain_token_id| { + crate::helpers::token_price_metric(source_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_base_conversion_rate: P::TargetChain::TOKEN_ID + .map(|target_chain_token_id| { + crate::helpers::token_price_metric(target_chain_token_id).map(Some) + }) + .unwrap_or(Ok(None))?, + source_to_target_conversion_rate: P::SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + target_client, + key, + Some(FixedU128::one()), + format!( + "{}_{}_to_{}_conversion_rate", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::TargetChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::TargetChain::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_to_source_conversion_rate: P::TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + source_client, + key, + Some(FixedU128::one()), + format!( + "{}_{}_to_{}_conversion_rate", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::SourceChain::NAME + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[async_std::test] + async fn target_to_source_conversion_rate_works() { + assert_eq!( + StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), + Some(12.32 / 183.15), + ); + } +} diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 5f066296e7e71..1947f526a01f5 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -19,8 +19,12 @@ //! chain. use crate::{ - messages_lane::SubstrateMessageLane, messages_target::SubstrateMessagesReceivingProof, + messages_lane::{ + MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, + }, + messages_target::SubstrateMessagesDeliveryProof, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, }; use async_trait::async_trait; @@ -39,15 +43,13 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, - IndexOf, -}; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; -use sp_core::Bytes; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Header as HeaderT}, - DeserializeOwned, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme, + UnsignedTransaction, }; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything @@ -58,8 +60,8 @@ pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof { client: Client, - lane: P, lane_id: LaneId, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, } @@ -67,11 +69,16 @@ impl SubstrateMessagesSource

{ /// Create new Substrate headers source. pub fn new( client: Client, - lane: P, lane_id: LaneId, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, ) -> Self { - SubstrateMessagesSource { client, lane, lane_id, target_to_source_headers_relay } + SubstrateMessagesSource { + client, + lane_id, + transaction_params, + target_to_source_headers_relay, + } } } @@ -79,8 +86,8 @@ impl Clone for SubstrateMessagesSource

{ fn clone(&self) -> Self { Self { client: self.client.clone(), - lane: self.lane.clone(), lane_id: self.lane_id, + transaction_params: self.transaction_params.clone(), target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), } } @@ -96,53 +103,33 @@ impl RelayClient for SubstrateMessagesSource

{ } #[async_trait] -impl

SourceClient for SubstrateMessagesSource

+impl SourceClient> for SubstrateMessagesSource

where - P: SubstrateMessageLane, - P::SourceChain: Chain< - Hash = ::SourceHeaderHash, - BlockNumber = ::SourceHeaderNumber, - Balance = ::SourceChainBalance, - >, - BalanceOf: Decode + Bounded, - IndexOf: DeserializeOwned, - HashOf: Copy, - BlockNumberOf: BlockNumberBase + Copy, - HeaderOf: DeserializeOwned, - P::TargetChain: Chain< - Hash = ::TargetHeaderHash, - BlockNumber = ::TargetHeaderNumber, - >, - - P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - >, - ::TargetHeaderNumber: Decode, - ::TargetHeaderHash: Decode, - ::SourceChainBalance: AtLeast32BitUnsigned, + AccountIdOf: + From< as Pair>::Public>, + P::SourceTransactionSignScheme: TransactionSignScheme, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver self.client.ensure_synced().await?; read_client_state::< _, - ::TargetHeaderHash, - ::TargetHeaderNumber, - >(&self.client, P::BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE) + as MessageLane>::TargetHeaderHash, + as MessageLane>::TargetHeaderNumber, + >(&self.client, P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD) .await } async fn latest_generated_nonce( &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { + id: SourceHeaderIdOf>, + ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD.into(), + P::TargetChain::TO_CHAIN_LATEST_GENERATED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -154,12 +141,12 @@ where async fn latest_confirmed_received_nonce( &self, - id: SourceHeaderIdOf, - ) -> Result<(SourceHeaderIdOf, MessageNonce), SubstrateError> { + id: SourceHeaderIdOf>, + ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + P::TargetChain::TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -171,16 +158,16 @@ where async fn generated_message_details( &self, - id: SourceHeaderIdOf, + id: SourceHeaderIdOf>, nonces: RangeInclusive, ) -> Result< - MessageDetailsMap<::SourceChainBalance>, + MessageDetailsMap< as MessageLane>::SourceChainBalance>, SubstrateError, > { let encoded_response = self .client .state_call( - P::OUTBOUND_LANE_MESSAGE_DETAILS_METHOD.into(), + P::TargetChain::TO_CHAIN_MESSAGE_DETAILS_METHOD.into(), Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), Some(id.1), ) @@ -195,14 +182,14 @@ where async fn prove_messages( &self, - id: SourceHeaderIdOf, + id: SourceHeaderIdOf>, nonces: RangeInclusive, proof_parameters: MessageProofParameters, ) -> Result< ( - SourceHeaderIdOf, + SourceHeaderIdOf>, RangeInclusive, - ::MessagesProof, + as MessageLane>::MessagesProof, ), SubstrateError, > { @@ -211,7 +198,7 @@ where let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { let message_key = pallet_bridge_messages::storage_keys::message_key( - P::MESSAGE_PALLET_NAME_AT_SOURCE, + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, message_nonce, ); @@ -220,7 +207,7 @@ where } if proof_parameters.outbound_state_proof_required { storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key( - P::MESSAGE_PALLET_NAME_AT_SOURCE, + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, )); } @@ -238,19 +225,22 @@ where async fn submit_messages_receiving_proof( &self, - generated_at_block: TargetHeaderIdOf, - proof: ::MessagesReceivingProof, + _generated_at_block: TargetHeaderIdOf>, + proof: as MessageLane>::MessagesReceivingProof, ) -> Result<(), SubstrateError> { - let lane = self.lane.clone(); + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); self.client .submit_signed_extrinsic( - self.lane.source_transactions_author(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - lane.make_messages_receiving_proof_transaction( + make_messages_delivery_proof_transaction::

( + &genesis_hash, + &transaction_params, best_block_id, transaction_nonce, - generated_at_block, proof, + true, ) }, ) @@ -258,7 +248,7 @@ where Ok(()) } - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { + async fn require_target_header_on_source(&self, id: TargetHeaderIdOf>) { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { target_to_source_headers_relay.require_finalized_header(id).await; } @@ -266,13 +256,15 @@ where async fn estimate_confirmation_transaction( &self, - ) -> ::SourceChainBalance { + ) -> as MessageLane>::SourceChainBalance { self.client - .estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction( + .estimate_extrinsic_fee(make_messages_delivery_proof_transaction::

( + self.client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), prepare_dummy_messages_delivery_proof::(), + false, )) .await .map(|fee| fee.inclusion_fee()) @@ -280,12 +272,39 @@ where } } +/// Make messages delivery proof transaction from given proof. +fn make_messages_delivery_proof_transaction( + source_genesis_hash: &HashOf, + source_transaction_params: &TransactionParams>, + source_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + proof: SubstrateMessagesDeliveryProof, + trace_call: bool, +) -> Bytes +where + P::SourceTransactionSignScheme: TransactionSignScheme, +{ + let call = + P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( + proof, trace_call, + ); + Bytes( + P::SourceTransactionSignScheme::sign_transaction( + *source_genesis_hash, + &source_transaction_params.signer, + TransactionEra::new(source_best_block_id, source_transaction_params.mortality), + UnsignedTransaction::new(call, transaction_nonce), + ) + .encode(), + ) +} + /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. /// /// We don't care about proof actually being the valid proof, because its validity doesn't /// affect the call weight - we only care about its size. fn prepare_dummy_messages_delivery_proof( -) -> SubstrateMessagesReceivingProof { +) -> SubstrateMessagesDeliveryProof { let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index eafc6bd3fc5f7..3cbe0181d7507 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -19,14 +19,15 @@ //! chain. use crate::{ - messages_lane::{StandaloneMessagesMetrics, SubstrateMessageLane}, + messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, + messages_metrics::StandaloneMessagesMetrics, messages_source::{read_client_state, SubstrateMessagesProof}, on_demand_headers::OnDemandHeadersRelay, + TransactionParams, }; use async_trait::async_trait; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; - use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -38,23 +39,25 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - BalanceOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderOf, IndexOf, - WeightToFeeOf, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme, + UnsignedTransaction, WeightToFeeOf, }; -use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId}; -use sp_core::Bytes; -use sp_runtime::{traits::Saturating, DeserializeOwned, FixedPointNumber, FixedU128}; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. -pub type SubstrateMessagesReceivingProof = +pub type SubstrateMessagesDeliveryProof = (UnrewardedRelayersState, FromBridgedChainMessagesDeliveryProof>); /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { client: Client, - lane: P, lane_id: LaneId, + relayer_id_at_source: AccountIdOf, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, } @@ -63,15 +66,17 @@ impl SubstrateMessagesTarget

{ /// Create new Substrate headers target. pub fn new( client: Client, - lane: P, lane_id: LaneId, + relayer_id_at_source: AccountIdOf, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { client, - lane, lane_id, + relayer_id_at_source, + transaction_params, metric_values, source_to_target_headers_relay, } @@ -82,8 +87,9 @@ impl Clone for SubstrateMessagesTarget

{ fn clone(&self) -> Self { Self { client: self.client.clone(), - lane: self.lane.clone(), lane_id: self.lane_id, + relayer_id_at_source: self.relayer_id_at_source.clone(), + transaction_params: self.transaction_params.clone(), metric_values: self.metric_values.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), } @@ -100,52 +106,34 @@ impl RelayClient for SubstrateMessagesTarget

{ } #[async_trait] -impl

TargetClient for SubstrateMessagesTarget

+impl TargetClient> for SubstrateMessagesTarget

where - P: SubstrateMessageLane, - P::SourceChain: Chain< - Hash = ::SourceHeaderHash, - BlockNumber = ::SourceHeaderNumber, - Balance = ::SourceChainBalance, - >, - BalanceOf: TryFrom> + Bounded, - P::TargetChain: Chain< - Hash = ::TargetHeaderHash, - BlockNumber = ::TargetHeaderNumber, - >, - IndexOf: DeserializeOwned, - HashOf: Copy, - BlockNumberOf: Copy, - HeaderOf: DeserializeOwned, - BlockNumberOf: BlockNumberBase, - P::MessageLane: MessageLane< - MessagesProof = SubstrateMessagesProof, - MessagesReceivingProof = SubstrateMessagesReceivingProof, - >, - ::SourceHeaderNumber: Decode, - ::SourceHeaderHash: Decode, + AccountIdOf: + From< as Pair>::Public>, + P::TargetTransactionSignScheme: TransactionSignScheme, + BalanceOf: TryFrom>, { - async fn state(&self) -> Result, SubstrateError> { + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver self.client.ensure_synced().await?; read_client_state::< _, - ::SourceHeaderHash, - ::SourceHeaderNumber, - >(&self.client, P::BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET) + as MessageLane>::SourceHeaderHash, + as MessageLane>::SourceHeaderNumber, + >(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD) .await } async fn latest_received_nonce( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD.into(), + P::SourceChain::FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -157,12 +145,12 @@ where async fn latest_confirmed_received_nonce( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, MessageNonce), SubstrateError> { + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { let encoded_response = self .client .state_call( - P::INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD.into(), + P::SourceChain::FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -174,12 +162,13 @@ where async fn unrewarded_relayers_state( &self, - id: TargetHeaderIdOf, - ) -> Result<(TargetHeaderIdOf, UnrewardedRelayersState), SubstrateError> { + id: TargetHeaderIdOf>, + ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> + { let encoded_response = self .client .state_call( - P::INBOUND_LANE_UNREWARDED_RELAYERS_STATE.into(), + P::SourceChain::FROM_CHAIN_UNREWARDED_RELAYERS_STATE.into(), Bytes(self.lane_id.encode()), Some(id.1), ) @@ -192,14 +181,17 @@ where async fn prove_messages_receiving( &self, - id: TargetHeaderIdOf, + id: TargetHeaderIdOf>, ) -> Result< - (TargetHeaderIdOf, ::MessagesReceivingProof), + ( + TargetHeaderIdOf>, + as MessageLane>::MessagesReceivingProof, + ), SubstrateError, > { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key( - P::MESSAGE_PALLET_NAME_AT_TARGET, + P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, ); let proof = self @@ -218,22 +210,27 @@ where async fn submit_messages_proof( &self, - generated_at_header: SourceHeaderIdOf, + _generated_at_header: SourceHeaderIdOf>, nonces: RangeInclusive, - proof: ::MessagesProof, + proof: as MessageLane>::MessagesProof, ) -> Result, SubstrateError> { - let lane = self.lane.clone(); + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let relayer_id_at_source = self.relayer_id_at_source.clone(); let nonces_clone = nonces.clone(); self.client .submit_signed_extrinsic( - self.lane.target_transactions_author(), + self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - lane.make_messages_delivery_transaction( + make_messages_delivery_transaction::

( + &genesis_hash, + &transaction_params, best_block_id, transaction_nonce, - generated_at_header, + relayer_id_at_source, nonces_clone, proof, + true, ) }, ) @@ -241,7 +238,7 @@ where Ok(nonces) } - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { + async fn require_source_header_on_target(&self, id: SourceHeaderIdOf>) { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { source_to_target_headers_relay.require_finalized_header(id).await; } @@ -253,7 +250,7 @@ where total_prepaid_nonces: MessageNonce, total_dispatch_weight: Weight, total_size: u32, - ) -> Result<::SourceChainBalance, SubstrateError> { + ) -> Result< as MessageLane>::SourceChainBalance, SubstrateError> { let conversion_rate = self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| { SubstrateError::Custom(format!( @@ -264,16 +261,19 @@ where })?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. - let delivery_tx = self.lane.make_messages_delivery_transaction( + let delivery_tx = make_messages_delivery_transaction::

( + self.client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), + Default::default(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), total_dispatch_weight, total_size, ), + false, ); let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); @@ -300,20 +300,23 @@ where let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); let larger_delivery_tx_fee = self .client - .estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction( + .estimate_extrinsic_fee(make_messages_delivery_transaction::

( + self.client.genesis_hash(), + &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - HeaderId(Default::default(), Default::default()), + Default::default(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), larger_dispatch_weight, total_size, ), + false, )) .await?; - compute_prepaid_messages_refund::

( + compute_prepaid_messages_refund::( total_prepaid_nonces, compute_fee_multiplier::( delivery_tx_fee.adjusted_weight_fee, @@ -359,6 +362,41 @@ where } } +/// Make messages delivery transaction from given proof. +#[allow(clippy::too_many_arguments)] +fn make_messages_delivery_transaction( + target_genesis_hash: &HashOf, + target_transaction_params: &TransactionParams>, + target_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + relayer_id_at_source: AccountIdOf, + nonces: RangeInclusive, + proof: SubstrateMessagesProof, + trace_call: bool, +) -> Bytes +where + P::TargetTransactionSignScheme: TransactionSignScheme, +{ + let messages_count = nonces.end() - nonces.start() + 1; + let dispatch_weight = proof.0; + let call = P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( + relayer_id_at_source, + proof, + messages_count as _, + dispatch_weight, + trace_call, + ); + Bytes( + P::TargetTransactionSignScheme::sign_transaction( + *target_genesis_hash, + &target_transaction_params.signer, + TransactionEra::new(target_best_block_id, target_transaction_params.mortality), + UnsignedTransaction::new(call, transaction_nonce), + ) + .encode(), + ) +} + /// Prepare 'dummy' messages proof that will compose the delivery transaction. /// /// We don't care about proof actually being the valid proof, because its validity doesn't @@ -425,80 +463,20 @@ fn compute_fee_multiplier( /// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces` /// messages has been paid at the source chain. -fn compute_prepaid_messages_refund( +fn compute_prepaid_messages_refund( total_prepaid_nonces: MessageNonce, fee_multiplier: FixedU128, -) -> BalanceOf { - fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( - &P::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN.saturating_mul(total_prepaid_nonces), +) -> BalanceOf { + fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( + &C::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN.saturating_mul(total_prepaid_nonces), )) } #[cfg(test)] mod tests { use super::*; - use relay_rococo_client::{Rococo, SigningParams as RococoSigningParams}; - use relay_wococo_client::{SigningParams as WococoSigningParams, Wococo}; - - #[derive(Clone)] - struct TestSubstrateMessageLane; - - impl SubstrateMessageLane for TestSubstrateMessageLane { - type MessageLane = crate::messages_lane::SubstrateMessageLaneToSubstrate< - Rococo, - RococoSigningParams, - Wococo, - WococoSigningParams, - >; - - const OUTBOUND_LANE_MESSAGE_DETAILS_METHOD: &'static str = ""; - const OUTBOUND_LANE_LATEST_GENERATED_NONCE_METHOD: &'static str = ""; - const OUTBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; - - const INBOUND_LANE_LATEST_RECEIVED_NONCE_METHOD: &'static str = ""; - const INBOUND_LANE_LATEST_CONFIRMED_NONCE_METHOD: &'static str = ""; - const INBOUND_LANE_UNREWARDED_RELAYERS_STATE: &'static str = ""; - - const BEST_FINALIZED_SOURCE_HEADER_ID_AT_TARGET: &'static str = ""; - const BEST_FINALIZED_TARGET_HEADER_ID_AT_SOURCE: &'static str = ""; - - const MESSAGE_PALLET_NAME_AT_SOURCE: &'static str = ""; - const MESSAGE_PALLET_NAME_AT_TARGET: &'static str = ""; - - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN: Weight = 100_000; - - type SourceChain = Rococo; - type TargetChain = Wococo; - - fn source_transactions_author(&self) -> bp_rococo::AccountId { - unreachable!() - } - - fn make_messages_receiving_proof_transaction( - &self, - _best_block_id: SourceHeaderIdOf, - _transaction_nonce: IndexOf, - _generated_at_block: TargetHeaderIdOf, - _proof: ::MessagesReceivingProof, - ) -> Bytes { - unreachable!() - } - - fn target_transactions_author(&self) -> bp_wococo::AccountId { - unreachable!() - } - - fn make_messages_delivery_transaction( - &self, - _best_block_id: TargetHeaderIdOf, - _transaction_nonce: IndexOf, - _generated_at_header: SourceHeaderIdOf, - _nonces: RangeInclusive, - _proof: ::MessagesProof, - ) -> Bytes { - unreachable!() - } - } + use relay_rococo_client::Rococo; + use relay_wococo_client::Wococo; #[test] fn prepare_dummy_messages_proof_works() { @@ -556,11 +534,10 @@ mod tests { #[test] fn compute_prepaid_messages_refund_returns_sane_results() { assert!( - compute_prepaid_messages_refund::( + compute_prepaid_messages_refund::( 10, FixedU128::saturating_from_rational(110, 100), - ) > (10 * TestSubstrateMessageLane::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_TARGET_CHAIN) - .into() + ) > (10 * Wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into() ); } } diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 1bd0b0b729c48..d66aaba549e28 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -30,12 +30,10 @@ use relay_utils::{ }; use crate::{ - finality_pipeline::{ - SubstrateFinalitySyncPipeline, TransactionParams, RECENT_FINALITY_PROOFS_LIMIT, - }, + finality_pipeline::{SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT}, finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, finality_target::SubstrateFinalityTarget, - STALL_TIMEOUT, + TransactionParams, STALL_TIMEOUT, }; /// On-demand Substrate <-> Substrate headers relay. @@ -116,7 +114,7 @@ async fn background_task( P::TransactionSignScheme: TransactionSignScheme, { let relay_task_name = on_demand_headers_relay_name::(); - let target_transactions_mortality = target_transaction_params.transactions_mortality; + let target_transactions_mortality = target_transaction_params.mortality; let mut finality_source = SubstrateFinalitySource::

::new( source_client.clone(), Some(required_header_number.clone()), From 7581e68f6f30632a0636b3660a3cc01f32daafe3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Dec 2021 13:39:05 +0300 Subject: [PATCH 0615/1210] Use same endowed accounts set on dev/local chains (#1244) * use same accounts set on dev/local chains * run altruistic relayers in local demo scripts --- bin/millau/node/src/chain_spec.rs | 102 +++++++++++++++--------------- bin/rialto/node/src/chain_spec.rs | 102 +++++++++++++++--------------- 2 files changed, 102 insertions(+), 102 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index fbfca8692fcb4..ad424ba463c8e 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -88,15 +88,7 @@ impl Alternative { testnet_genesis( vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - ], + endowed_accounts(), true, ) }, @@ -120,48 +112,7 @@ impl Alternative { get_authority_keys_from_seed("Eve"), ], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Harry"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("Harry//stash"), - get_account_id_from_seed::("RialtoMessagesOwner"), - get_account_id_from_seed::("WithRialtoTokenSwap"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_millau::AccountId, - bp_millau::AccountIdConverter, - >(), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Charlie"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Eve"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Ferdie"), - )), - ], + endowed_accounts(), true, ) }, @@ -175,6 +126,55 @@ impl Alternative { } } +/// We're using the same set of endowed accounts on all Millau chains (dev/local) to make +/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, +/// accounts used by relayers in our test deployments, accounts used for demonstration +/// purposes), are all available on these chains. +fn endowed_accounts() -> Vec { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Harry"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("RialtoMessagesOwner"), + get_account_id_from_seed::("WithRialtoTokenSwap"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_millau::AccountId, + bp_millau::AccountIdConverter, + >(), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Alice"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Charlie"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Eve"), + )), + derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Ferdie"), + )), + ] +} + fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys { SessionKeys { aura, beefy, grandpa } } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index fb18a35a6af0e..527b5c051d535 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -96,15 +96,7 @@ impl Alternative { testnet_genesis( vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - ], + endowed_accounts(), true, ) }, @@ -128,48 +120,7 @@ impl Alternative { get_authority_keys_from_seed("Eve"), ], get_account_id_from_seed::("Alice"), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Harry"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("Harry//stash"), - get_account_id_from_seed::("MillauMessagesOwner"), - get_account_id_from_seed::("WithMillauTokenSwap"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_rialto::AccountId, - bp_rialto::AccountIdConverter, - >(), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Charlie"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Eve"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Ferdie"), - )), - ], + endowed_accounts(), true, ) }, @@ -183,6 +134,55 @@ impl Alternative { } } +/// We're using the same set of endowed accounts on all Millau chains (dev/local) to make +/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, +/// accounts used by relayers in our test deployments, accounts used for demonstration +/// purposes), are all available on these chains. +fn endowed_accounts() -> Vec { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Harry"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("MillauMessagesOwner"), + get_account_id_from_seed::("WithMillauTokenSwap"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_rialto::AccountId, + bp_rialto::AccountIdConverter, + >(), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Alice"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Bob"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Charlie"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Dave"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Eve"), + )), + derive_account_from_millau_id(bp_runtime::SourceAccount::Account( + get_account_id_from_seed::("Ferdie"), + )), + ] +} + fn session_keys( babe: BabeId, beefy: BeefyId, From 848a28605538de634987a1b8202b026e138788f9 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 8 Dec 2021 08:27:24 +0200 Subject: [PATCH 0616/1210] runtimes: fix call_size() test (#1245) Signed-off-by: acatangiu --- bin/millau/runtime/src/lib.rs | 9 +++++++++ bin/rialto/runtime/src/lib.rs | 19 ++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index be186569961db..4400191d940c9 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -922,6 +922,15 @@ mod tests { #[test] fn call_size() { + const BRIDGES_PALLETS_MAX_CALL_SIZE: usize = 200; + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE + ); + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE + ); const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 59be1186b4093..8619cbade7934 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1229,10 +1229,19 @@ mod tests { #[test] fn call_size() { - const DOT_MAX_CALL_SZ: usize = 230; - assert!(core::mem::size_of::>() <= DOT_MAX_CALL_SZ); - // FIXME: get this down to 230. https://github.com/paritytech/grandpa-bridge-gadget/issues/359 - const BEEFY_MAX_CALL_SZ: usize = 232; - assert!(core::mem::size_of::>() <= BEEFY_MAX_CALL_SZ); + const BRIDGES_PALLETS_MAX_CALL_SIZE: usize = 200; + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE + ); + assert!( + core::mem::size_of::>() <= + BRIDGES_PALLETS_MAX_CALL_SIZE + ); + // Largest inner Call is `pallet_session::Call` with a size of 224 bytes. This size is a + // result of large `SessionKeys` struct. + // Total size of Rialto runtime Call is 232. + const MAX_CALL_SIZE: usize = 232; + assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } From e014f8f9a8a19b82e1fe70bf79763f0f5853198b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 13 Dec 2021 21:12:17 +0100 Subject: [PATCH 0617/1210] Bump relay version to 1.0.0 (#1249) --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a28c61262f403..843340817e403 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-relay" -version = "0.1.0" +version = "1.0.0" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" From 1c56417d368f3fbd8986c647c22b440e399bd17c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Dec 2021 13:47:32 +0300 Subject: [PATCH 0618/1210] Add missing RPC APIs to rialto parachain node (#1250) * add missing RPC APIs to rialto parachain node * spellcheck --- bin/rialto-parachain/node/src/service.rs | 33 ++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index bd3afca307449..54e626e0ead19 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -14,6 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Rialto parachain node service. +//! +//! The code is mostly copy of `polkadot-parachains/src/service.rs` file from Cumulus +//! repository with some parts removed. We have added two RPC extensions to the original +//! service: `pallet_transaction_payment_rpc::TransactionPaymentApi` and +//! `substrate_frame_rpc_system::SystemApi`. + // std use std::sync::Arc; @@ -212,7 +219,14 @@ where sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, Executor: NativeExecutionDispatch + 'static, RB: Fn( + sc_rpc_api::DenyUnsafe, Arc>>, + Arc< + sc_transaction_pool::FullPool< + Block, + TFullClient>, + >, + >, ) -> jsonrpc_core::IoHandler + Send + 'static, @@ -288,7 +302,10 @@ where })?; let rpc_client = client.clone(); - let rpc_extensions_builder = Box::new(move |_, _| Ok(rpc_ext_builder(rpc_client.clone()))); + let rpc_transaction_pool = transaction_pool.clone(); + let rpc_extensions_builder = Box::new(move |deny_unsafe, _| { + Ok(rpc_ext_builder(deny_unsafe, rpc_client.clone(), rpc_transaction_pool.clone())) + }); sc_service::spawn_tasks(sc_service::SpawnTasksParams { rpc_extensions_builder, @@ -412,7 +429,19 @@ pub async fn start_node( parachain_config, polkadot_config, id, - |_| Default::default(), + |deny_unsafe, client, pool| { + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; + use substrate_frame_rpc_system::{FullSystem, SystemApi}; + + let mut io = jsonrpc_core::IoHandler::default(); + io.extend_with(SystemApi::to_delegate(FullSystem::new( + client.clone(), + pool, + deny_unsafe, + ))); + io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client))); + io + }, parachain_build_import_queue, |client, prometheus_registry, From d09c5c26fcee506bf4cbd042ecdf300ac117daf3 Mon Sep 17 00:00:00 2001 From: fewensa <37804932+fewensa@users.noreply.github.com> Date: Thu, 16 Dec 2021 20:55:01 +0800 Subject: [PATCH 0619/1210] Change submit transaction spec_version and transaction_version query from chain (#1248) * The `spec_version` and `transaction_version` query from chain * fix compile * Lint * Custom spec_version and transaction_version * runtime version params struct opt * runtime version cli * cli params * Add missing types defined * fix compile * debug cli * clippy * clippy * Query spec_version and transaction_version same times * Fix vars * Wrap option * Wrap option * Try fix ci * Change follow suggestions --- primitives/polkadot-core/src/lib.rs | 7 +- .../src/chains/kusama_messages_to_polkadot.rs | 17 ++-- .../src/chains/millau_messages_to_rialto.rs | 17 ++-- relays/bin-substrate/src/chains/mod.rs | 30 ++++--- .../src/chains/polkadot_messages_to_kusama.rs | 17 ++-- .../src/chains/rialto_messages_to_millau.rs | 17 ++-- relays/bin-substrate/src/cli/bridge.rs | 30 +++++++ relays/bin-substrate/src/cli/estimate_fee.rs | 9 +- relays/bin-substrate/src/cli/init_bridge.rs | 50 +++++++++-- relays/bin-substrate/src/cli/mod.rs | 61 ++++++++++++- .../src/cli/register_parachain.rs | 71 ++++++++++----- relays/bin-substrate/src/cli/relay_headers.rs | 32 ++++++- .../src/cli/relay_headers_and_messages.rs | 36 ++++++-- .../bin-substrate/src/cli/relay_messages.rs | 4 +- .../src/cli/resubmit_transactions.rs | 40 ++++++--- relays/bin-substrate/src/cli/send_message.rs | 34 ++++--- relays/bin-substrate/src/cli/swap_tokens.rs | 90 +++++++++++++------ relays/client-kusama/src/lib.rs | 28 +++--- relays/client-millau/src/lib.rs | 29 +++--- relays/client-polkadot/src/lib.rs | 28 +++--- relays/client-rialto/src/lib.rs | 29 +++--- relays/client-rococo/src/lib.rs | 28 +++--- relays/client-substrate/src/chain.rs | 25 ++++-- relays/client-substrate/src/client.rs | 29 ++++++ relays/client-substrate/src/lib.rs | 15 +++- relays/client-wococo/src/lib.rs | 28 +++--- .../src/finality_target.rs | 15 ++-- .../src/messages_source.rs | 29 ++++-- .../src/messages_target.rs | 29 ++++-- 29 files changed, 600 insertions(+), 274 deletions(-) diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 0dc7c54835b9c..8be9cc17daca5 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -265,7 +265,8 @@ impl parity_scale_codec::Decode for SignedExtensions { impl SignedExtensions { pub fn new( - version: sp_version::RuntimeVersion, + spec_version: u32, + transaction_version: u32, era: bp_runtime::TransactionEraOf, genesis_hash: Hash, nonce: Nonce, @@ -282,8 +283,8 @@ impl SignedExtensions { tip.into(), // transaction payment / tip (compact encoding) ), additional_signed: ( - version.spec_version, - version.transaction_version, + spec_version, + transaction_version, genesis_hash, era.signed_payload(genesis_hash), (), diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 6a8780a34aad0..82a3206b0d916 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -23,7 +23,7 @@ use sp_core::{Bytes, Pair}; use messages_relay::relay_strategy::MixStrategy; use relay_kusama_client::Kusama; use relay_polkadot_client::Polkadot; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::SubstrateMessageLane; /// Description of Kusama -> Polkadot messages bridge. @@ -69,14 +69,17 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( ) -> anyhow::Result<()> { let genesis_hash = *client.genesis_hash(); let signer_id = (*signer.public().as_array_ref()).into(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { Bytes( - Kusama::sign_transaction( + Kusama::sign_transaction(SignParam { + spec_version, + transaction_version, genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( relay_kusama_client::runtime::Call::BridgePolkadotMessages( relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter( relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate( @@ -86,8 +89,8 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( ), transaction_nonce, ), - ) - .encode(), + }) + .encode(), ) }) .await diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 4acc7fdd2ff8d..a496602943554 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -22,7 +22,7 @@ use sp_core::{Bytes, Pair}; use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::{ DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane, @@ -66,23 +66,26 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( ) -> anyhow::Result<()> { let genesis_hash = *client.genesis_hash(); let signer_id = (*signer.public().as_array_ref()).into(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { Bytes( - Millau::sign_transaction( + Millau::sign_transaction(SignParam { + spec_version, + transaction_version, genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( millau_runtime::MessagesCall::update_pallet_parameter { parameter: millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), } - .into(), + .into(), transaction_nonce, ), - ) + }) .encode(), ) }) diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 3f2f5633a03b0..e2a7a9a2b1eb7 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -48,7 +48,7 @@ mod tests { use frame_support::dispatch::GetDispatchInfo; use relay_millau_client::Millau; use relay_rialto_client::Rialto; - use relay_substrate_client::{TransactionSignScheme, UnsignedTransaction}; + use relay_substrate_client::{SignParam, TransactionSignScheme, UnsignedTransaction}; use sp_core::Pair; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -204,12 +204,14 @@ mod tests { fn rialto_tx_extra_bytes_constant_is_correct() { let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); - let rialto_tx = Rialto::sign_transaction( - Default::default(), - &sp_keyring::AccountKeyring::Alice.pair(), - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(rialto_call.clone(), 0), - ); + let rialto_tx = Rialto::sign_transaction(SignParam { + spec_version: 1, + transaction_version: 1, + genesis_hash: Default::default(), + signer: sp_keyring::AccountKeyring::Alice.pair(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(rialto_call.clone(), 0), + }); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); assert!( bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, @@ -223,12 +225,14 @@ mod tests { fn millau_tx_extra_bytes_constant_is_correct() { let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); - let millau_tx = Millau::sign_transaction( - Default::default(), - &sp_keyring::AccountKeyring::Alice.pair(), - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(millau_call.clone(), 0), - ); + let millau_tx = Millau::sign_transaction(SignParam { + spec_version: 0, + transaction_version: 0, + genesis_hash: Default::default(), + signer: sp_keyring::AccountKeyring::Alice.pair(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(millau_call.clone(), 0), + }); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); assert!( bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 12ebdde15cb5b..5eeb0df3f1288 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -23,7 +23,7 @@ use frame_support::weights::Weight; use messages_relay::relay_strategy::MixStrategy; use relay_kusama_client::Kusama; use relay_polkadot_client::Polkadot; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::SubstrateMessageLane; /// Description of Polkadot -> Kusama messages bridge. @@ -69,14 +69,17 @@ pub(crate) async fn update_kusama_to_polkadot_conversion_rate( ) -> anyhow::Result<()> { let genesis_hash = *client.genesis_hash(); let signer_id = (*signer.public().as_array_ref()).into(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { Bytes( - Polkadot::sign_transaction( + Polkadot::sign_transaction(SignParam { + spec_version, + transaction_version, genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( relay_polkadot_client::runtime::Call::BridgeKusamaMessages( relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter( relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate( @@ -85,8 +88,8 @@ pub(crate) async fn update_kusama_to_polkadot_conversion_rate( ) ), transaction_nonce, - ), - ) + ) + }) .encode(), ) }) diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index b6e85a7dec79f..4c7ad8e621913 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -22,7 +22,7 @@ use sp_core::{Bytes, Pair}; use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::{Client, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::{ DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane, @@ -66,14 +66,17 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( ) -> anyhow::Result<()> { let genesis_hash = *client.genesis_hash(); let signer_id = (*signer.public().as_array_ref()).into(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { Bytes( - Rialto::sign_transaction( + Rialto::sign_transaction(SignParam { + spec_version, + transaction_version, genesis_hash, - &signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( rialto_runtime::MessagesCall::update_pallet_parameter { parameter: rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( sp_runtime::FixedU128::from_float(updated_rate), @@ -81,8 +84,8 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( } .into(), transaction_nonce, - ), - ) + ) + }) .encode(), ) }) diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 2eb836a84a753..ea16c92c9203a 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -77,6 +77,11 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use millau_runtime::millau_to_rialto_account_ownership_digest as account_ownership_digest; + #[allow(dead_code)] + const SOURCE_RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); + #[allow(dead_code)] + const TARGET_RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); + $generic } FullBridge::RialtoToMillau => { @@ -100,6 +105,11 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest; + #[allow(dead_code)] + const SOURCE_RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); + #[allow(dead_code)] + const TARGET_RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); + $generic } FullBridge::RococoToWococo => { @@ -122,6 +132,11 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_rococo_client::runtime::rococo_to_wococo_account_ownership_digest as account_ownership_digest; + #[allow(dead_code)] + const SOURCE_RUNTIME_VERSION: Option = Some(bp_rococo::VERSION); + #[allow(dead_code)] + const TARGET_RUNTIME_VERSION: Option = Some(bp_wococo::VERSION); + $generic } FullBridge::WococoToRococo => { @@ -144,6 +159,11 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest; + #[allow(dead_code)] + const SOURCE_RUNTIME_VERSION: Option = Some(bp_wococo::VERSION); + #[allow(dead_code)] + const TARGET_RUNTIME_VERSION: Option = Some(bp_rococo::VERSION); + $generic } FullBridge::KusamaToPolkadot => { @@ -166,6 +186,11 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_kusama_client::runtime::kusama_to_polkadot_account_ownership_digest as account_ownership_digest; + #[allow(dead_code)] + const SOURCE_RUNTIME_VERSION: Option = Some(bp_kusama::VERSION); + #[allow(dead_code)] + const TARGET_RUNTIME_VERSION: Option = Some(bp_polkadot::VERSION); + $generic } FullBridge::PolkadotToKusama => { @@ -188,6 +213,11 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_polkadot_client::runtime::polkadot_to_kusama_account_ownership_digest as account_ownership_digest; + #[allow(dead_code)] + const SOURCE_RUNTIME_VERSION: Option = Some(bp_polkadot::VERSION); + #[allow(dead_code)] + const TARGET_RUNTIME_VERSION: Option = Some(bp_kusama::VERSION); + $generic } } diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index d063ce544cd24..18e7341fc9658 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -46,7 +46,7 @@ impl EstimateFee { let Self { source, bridge, lane, payload } = self; select_full_bridge!(bridge, { - let source_client = source.to_client::().await?; + let source_client = source.to_client::(SOURCE_RUNTIME_VERSION).await?; let lane = lane.into(); let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; @@ -86,7 +86,7 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; + const SOURCE_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -74,6 +78,10 @@ macro_rules! select_bridge { InitBridgeName::RialtoToMillau => { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; + const SOURCE_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -92,6 +100,10 @@ macro_rules! select_bridge { InitBridgeName::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_westend::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -114,6 +126,10 @@ macro_rules! select_bridge { InitBridgeName::RococoToWococo => { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_rococo::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_wococo::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -130,6 +146,10 @@ macro_rules! select_bridge { InitBridgeName::WococoToRococo => { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_wococo::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_rococo::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -146,6 +166,10 @@ macro_rules! select_bridge { InitBridgeName::KusamaToPolkadot => { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_kusama::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_polkadot::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -162,6 +186,10 @@ macro_rules! select_bridge { InitBridgeName::PolkadotToKusama => { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_polkadot::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_kusama::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -183,25 +211,29 @@ impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let target_client = self.target.to_client::().await?; + let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; + let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; let target_sign = self.target_sign.to_keypair::()?; + let (spec_version, transaction_version) = + target_client.simple_runtime_version().await?; substrate_relay_helper::headers_initialize::initialize( source_client, target_client.clone(), target_sign.public().into(), move |transaction_nonce, initialization_data| { Bytes( - Target::sign_transaction( - *target_client.genesis_hash(), - &target_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *target_client.genesis_hash(), + signer: target_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( encode_init_bridge(initialization_data), transaction_nonce, ), - ) + }) .encode(), ) }, diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index ae167334d8292..2a087e59b62a6 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -18,10 +18,13 @@ use std::convert::TryInto; -use bp_messages::LaneId; use codec::{Decode, Encode}; +use relay_substrate_client::ChainRuntimeVersion; use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; +use strum::{EnumString, EnumVariantNames}; + +use bp_messages::LaneId; pub(crate) mod bridge; pub(crate) mod encode_call; @@ -364,6 +367,17 @@ where } } +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, EnumString, EnumVariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + /// Create chain-specific set of configuration objects: connection parameters, /// signing parameters and bridge initialization parameters. #[macro_export] @@ -382,6 +396,23 @@ macro_rules! declare_chain_options { #[doc = "Use secure websocket connection."] #[structopt(long)] pub [<$chain_prefix _secure>]: bool, + #[doc = "Custom runtime version"] + #[structopt(flatten)] + pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], + } + + #[doc = $chain " runtime version params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain RuntimeVersionParams>] { + #[doc = "The type of runtime version for chain " $chain] + #[structopt(long, default_value = "Bundle")] + pub [<$chain_prefix _version_mode>]: RuntimeVersionType, + #[doc = "The custom sepc_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _spec_version>]: Option, + #[doc = "The custom transaction_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _transaction_version>]: Option, } #[doc = $chain " signing params."] @@ -500,11 +531,36 @@ macro_rules! declare_chain_options { /// Convert connection params into Substrate client. pub async fn to_client( &self, + bundle_runtime_version: Option ) -> anyhow::Result> { + let runtime_version_params = &self.[<$chain_prefix _runtime_version>]; + let chain_runtime_version = match runtime_version_params.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let except_spec_version = runtime_version_params.[<$chain_prefix _spec_version>] + .ok_or(anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let except_transaction_version = runtime_version_params.[<$chain_prefix _transaction_version>] + .ok_or(anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + except_spec_version, + except_transaction_version + ) + } + RuntimeVersionType::Bundle => { + match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom( + runtime_version.spec_version, + runtime_version.transaction_version + ), + None => ChainRuntimeVersion::Auto + } + } + }; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { host: self.[<$chain_prefix _host>].clone(), port: self.[<$chain_prefix _port>], secure: self.[<$chain_prefix _secure>], + chain_runtime_version, }) .await ) @@ -521,9 +577,10 @@ declare_chain_options!(Parachain, parachain); #[cfg(test)] mod tests { - use sp_core::Pair; use std::str::FromStr; + use sp_core::Pair; + use super::*; #[test] diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index fecc431148ebd..57e0517a56601 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -29,7 +29,7 @@ use polkadot_runtime_common::{ }; use polkadot_runtime_parachains::paras::ParaLifecycle; use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, CallOf, Chain, Client, SignParam, TransactionSignScheme, UnsignedTransaction, }; use rialto_runtime::SudoCall; use sp_core::{ @@ -83,6 +83,11 @@ macro_rules! select_bridge { use bp_rialto::{PARAS_PALLET_NAME, PARAS_REGISTRAR_PALLET_NAME}; + const RELAY_CHAIN_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); + const PARA_CHAIN_RUNTIME_VERSION: Option = + Some(rialto_parachain_runtime::VERSION); + $generic }, } @@ -93,9 +98,13 @@ impl RegisterParachain { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.parachain, { - let relay_client = self.relay_connection.to_client::().await?; + let relay_client = self + .relay_connection + .to_client::(RELAY_CHAIN_RUNTIME_VERSION) + .await?; let relay_sign = self.relay_sign.to_keypair::()?; - let para_client = self.para_connection.to_client::().await?; + let para_client = + self.para_connection.to_client::(PARA_CHAIN_RUNTIME_VERSION).await?; // hopefully we're the only actor that is registering parachain right now // => read next parachain id @@ -116,21 +125,24 @@ impl RegisterParachain { let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve {}.into(); let reserve_parachain_signer = relay_sign.clone(); + let (spec_version, transaction_version) = relay_client.simple_runtime_version().await?; wait_until_transaction_is_finalized::( relay_client .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { Bytes( - Relaychain::sign_transaction( - relay_genesis_hash, - &reserve_parachain_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + Relaychain::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: reserve_parachain_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( reserve_parachain_id_call, transaction_nonce, ), - ) + }) .encode(), ) }, @@ -169,15 +181,17 @@ impl RegisterParachain { relay_sudo_account.clone(), move |_, transaction_nonce| { Bytes( - Relaychain::sign_transaction( - relay_genesis_hash, - ®ister_parathread_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + Relaychain::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: register_parathread_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( register_parathread_call, transaction_nonce, ), - ) + }) .encode(), ) }, @@ -229,12 +243,14 @@ impl RegisterParachain { relay_client .submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { Bytes( - Relaychain::sign_transaction( - relay_genesis_hash, - &force_lease_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(force_lease_call, transaction_nonce), - ) + Relaychain::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: force_lease_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(force_lease_call, transaction_nonce), + }) .encode(), ) }) @@ -292,6 +308,9 @@ async fn wait_para_state( #[cfg(test)] mod tests { use super::*; + use crate::cli::{ + ParachainRuntimeVersionParams, RelaychainRuntimeVersionParams, RuntimeVersionType, + }; #[test] fn register_rialto_parachain() { @@ -327,6 +346,11 @@ mod tests { relaychain_host: "127.0.0.1".into(), relaychain_port: 9944, relaychain_secure: false, + relaychain_runtime_version: RelaychainRuntimeVersionParams { + relaychain_version_mode: RuntimeVersionType::Bundle, + relaychain_spec_version: None, + relaychain_transaction_version: None, + } }, relay_sign: RelaychainSigningParams { relaychain_signer: Some("//Alice".into()), @@ -339,6 +363,11 @@ mod tests { parachain_host: "127.0.0.1".into(), parachain_port: 11949, parachain_secure: false, + parachain_runtime_version: ParachainRuntimeVersionParams { + parachain_version_mode: RuntimeVersionType::Bundle, + parachain_spec_version: None, + parachain_transaction_version: None, + } }, } ); diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 43def352a4d1d..4b17a56819c80 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -64,6 +64,10 @@ macro_rules! select_bridge { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; + const SOURCE_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); $generic }, @@ -71,6 +75,10 @@ macro_rules! select_bridge { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; + const SOURCE_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); $generic }, @@ -78,6 +86,10 @@ macro_rules! select_bridge { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_westend::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); $generic }, @@ -85,6 +97,10 @@ macro_rules! select_bridge { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_rococo::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_wococo::VERSION); $generic }, @@ -92,6 +108,10 @@ macro_rules! select_bridge { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_wococo::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_rococo::VERSION); $generic }, @@ -99,6 +119,10 @@ macro_rules! select_bridge { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_kusama::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_polkadot::VERSION); $generic }, @@ -106,6 +130,10 @@ macro_rules! select_bridge { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; + const SOURCE_RUNTIME_VERSION: Option = + Some(bp_polkadot::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(bp_kusama::VERSION); $generic }, @@ -117,8 +145,8 @@ impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let target_client = self.target.to_client::().await?; + let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; + let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; let target_transactions_mortality = self.target_sign.target_transactions_mortality; let target_sign = self.target_sign.to_keypair::()?; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 112d2f419bda3..3804513acdb7a 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -29,7 +29,8 @@ use strum::VariantNames; use codec::Encode; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, Client, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, CallOf, Chain, ChainRuntimeVersion, Client, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; @@ -39,7 +40,7 @@ use substrate_relay_helper::{ }; use crate::{ - cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams}, + cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams, RuntimeVersionType}, declare_chain_options, }; @@ -136,6 +137,10 @@ macro_rules! select_bridge { bp_millau::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; + const LEFT_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); + const RIGHT_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); use crate::chains::{ millau_messages_to_rialto::{ @@ -185,6 +190,11 @@ macro_rules! select_bridge { const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; + const LEFT_RUNTIME_VERSION: Option = + Some(bp_rococo::VERSION); + const RIGHT_RUNTIME_VERSION: Option = + Some(bp_wococo::VERSION); + use crate::chains::{ rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane, wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, @@ -263,6 +273,11 @@ macro_rules! select_bridge { const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = bp_polkadot::SESSION_LENGTH; + const LEFT_RUNTIME_VERSION: Option = + Some(bp_kusama::VERSION); + const RIGHT_RUNTIME_VERSION: Option = + Some(bp_polkadot::VERSION); + use crate::chains::{ kusama_messages_to_polkadot::{ update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, @@ -334,12 +349,12 @@ impl RelayHeadersAndMessages { select_bridge!(self, { let params: Params = self.into(); - let left_client = params.left.to_client::().await?; + let left_client = params.left.to_client::(LEFT_RUNTIME_VERSION).await?; let left_transactions_mortality = params.left_sign.transactions_mortality()?; let left_sign = params.left_sign.to_keypair::()?; let left_messages_pallet_owner = params.left_messages_pallet_owner.to_keypair::()?; - let right_client = params.right.to_client::().await?; + let right_client = params.right.to_client::(RIGHT_RUNTIME_VERSION).await?; let right_transactions_mortality = params.right_sign.transactions_mortality()?; let right_sign = params.right_sign.to_keypair::()?; let right_messages_pallet_owner = @@ -591,15 +606,18 @@ where CallOf: Send, { let genesis_hash = *client.genesis_hash(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(sign.public().into(), move |_, transaction_nonce| { Bytes( - C::sign_transaction( + C::sign_transaction(SignParam { + spec_version, + transaction_version, genesis_hash, - &sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(call, transaction_nonce), - ) + signer: sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(call, transaction_nonce), + }) .encode(), ) }) diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 45087fad5eb3f..521d00d50a91f 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -75,10 +75,10 @@ impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_full_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; + let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; let source_sign = self.source_sign.to_keypair::()?; let source_transactions_mortality = self.source_sign.transactions_mortality()?; - let target_client = self.target.to_client::().await?; + let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; let target_sign = self.target_sign.to_keypair::()?; let target_transactions_mortality = self.target_sign.transactions_mortality()?; let relayer_mode = self.relayer_mode.into(); diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 64663d7e8ec02..8b021df86372d 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -19,7 +19,8 @@ use crate::cli::{Balance, TargetConnectionParams, TargetSigningParams}; use codec::{Decode, Encode}; use num_traits::{One, Zero}; use relay_substrate_client::{ - BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderOf, TransactionSignScheme, + BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderOf, SignParam, + TransactionSignScheme, }; use relay_utils::FailedClient; use sp_core::Bytes; @@ -90,18 +91,24 @@ macro_rules! select_bridge { RelayChain::Millau => { type Target = relay_millau_client::Millau; type TargetSign = relay_millau_client::Millau; + const TARGET_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); $generic }, RelayChain::Kusama => { type Target = relay_kusama_client::Kusama; type TargetSign = relay_kusama_client::Kusama; + const TARGET_RUNTIME_VERSION: Option = + Some(bp_kusama::VERSION); $generic }, RelayChain::Polkadot => { type Target = relay_polkadot_client::Polkadot; type TargetSign = relay_polkadot_client::Polkadot; + const TARGET_RUNTIME_VERSION: Option = + Some(bp_polkadot::VERSION); $generic }, @@ -114,7 +121,7 @@ impl ResubmitTransactions { pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.chain, { let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); - let client = self.target.to_client::().await?; + let client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; let key_pair = self.target_sign.to_keypair::()?; relay_utils::relay_loop((), client) @@ -411,6 +418,7 @@ async fn update_transaction_tip>( })?; let old_tip = unsigned_tx.tip; + let (spec_version, transaction_version) = client.simple_runtime_version().await?; while current_priority < target_priority { let next_tip = unsigned_tx.tip + tip_step; if next_tip > tip_limit { @@ -430,12 +438,14 @@ async fn update_transaction_tip>( current_priority = client .validate_transaction( at_block, - S::sign_transaction( - *client.genesis_hash(), - key_pair, - relay_substrate_client::TransactionEra::immortal(), - unsigned_tx.clone(), - ), + S::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *client.genesis_hash(), + signer: key_pair.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: unsigned_tx.clone(), + }), ) .await?? .priority; @@ -451,12 +461,14 @@ async fn update_transaction_tip>( Ok(( old_tip != unsigned_tx.tip, - S::sign_transaction( - *client.genesis_hash(), - key_pair, - relay_substrate_client::TransactionEra::immortal(), - unsigned_tx, - ), + S::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *client.genesis_hash(), + signer: key_pair.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: unsigned_tx, + }), )) } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 5c403f6c23a95..52eab9c64ec98 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -25,7 +25,7 @@ use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_runtime::{BalanceOf, Chain as _}; use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{Chain, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; use std::fmt::Debug; @@ -154,7 +154,7 @@ impl SendMessage { crate::select_full_bridge!(self.bridge, { let payload = self.encode_payload()?; - let source_client = self.source.to_client::().await?; + let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; let source_sign = self.source_sign.to_keypair::()?; let lane = self.lane.clone().into(); @@ -179,25 +179,31 @@ impl SendMessage { })?; let source_genesis_hash = *source_client.genesis_hash(); + let (spec_version, transaction_version) = + source_client.simple_runtime_version().await?; let estimated_transaction_fee = source_client .estimate_extrinsic_fee(Bytes( - Source::sign_transaction( - source_genesis_hash, - &source_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(send_message_call.clone(), 0), - ) + Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), + }) .encode(), )) .await?; source_client .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { - let signed_source_call = Source::sign_transaction( - source_genesis_hash, - &source_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(send_message_call, transaction_nonce), - ) + let signed_source_call = Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), + }) .encode(); log::info!( diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index dbe46f4690709..18f4c1a46bc38 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -29,8 +29,8 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; use frame_support::dispatch::GetDispatchInfo; use relay_substrate_client::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithBalances, - Client, Error as SubstrateError, HashOf, SignatureOf, Subscription, TransactionSignScheme, - TransactionStatusOf, UnsignedTransaction, + Client, Error as SubstrateError, HashOf, SignParam, SignatureOf, Subscription, + TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, }; use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, H256, U256}; use sp_runtime::traits::{Convert, Header as HeaderT}; @@ -98,6 +98,13 @@ macro_rules! select_bridge { SwapTokensBridge::MillauToRialto => { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; + const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; + const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; + + const SOURCE_RUNTIME_VERSION: Option = + Some(millau_runtime::VERSION); + const TARGET_RUNTIME_VERSION: Option = + Some(rialto_runtime::VERSION); type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; @@ -114,9 +121,6 @@ macro_rules! select_bridge { const SOURCE_CHAIN_ID: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; const TARGET_CHAIN_ID: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; - const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; - const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; - const SOURCE_TO_TARGET_LANE_ID: bp_messages::LaneId = *b"swap"; const TARGET_TO_SOURCE_LANE_ID: bp_messages::LaneId = [0, 0, 0, 0]; @@ -130,9 +134,9 @@ impl SwapTokens { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; + let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; let source_sign = self.source_sign.to_keypair::()?; - let target_client = self.target.to_client::().await?; + let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; let target_sign = self.target_sign.to_keypair::()?; // names of variables in this function are matching names used by the @@ -234,18 +238,25 @@ impl SwapTokens { // start tokens swap let source_genesis_hash = *source_client.genesis_hash(); let create_swap_signer = source_sign.clone(); + let (spec_version, transaction_version) = + source_client.simple_runtime_version().await?; let swap_created_at = wait_until_transaction_is_finalized::( source_client .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { Bytes( - Source::sign_transaction( - source_genesis_hash, - &create_swap_signer, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new(create_swap_call, transaction_nonce), - ) + Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: create_swap_signer, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + create_swap_call, + transaction_nonce, + ), + }) .encode(), ) }, @@ -369,21 +380,25 @@ impl SwapTokens { // send `claim_swap` message let target_genesis_hash = *target_client.genesis_hash(); + let (spec_version, transaction_version) = + target_client.simple_runtime_version().await?; let _ = wait_until_transaction_is_finalized::( target_client .submit_and_watch_signed_extrinsic( accounts.target_account_at_bridged_chain.clone(), move |_, transaction_nonce| { Bytes( - Target::sign_transaction( - target_genesis_hash, - &target_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: target_genesis_hash, + signer: target_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( send_message_call, transaction_nonce, ), - ) + }) .encode(), ) }, @@ -409,21 +424,25 @@ impl SwapTokens { log::info!(target: "bridge", "Cancelling the swap"); let cancel_swap_call: CallOf = pallet_bridge_token_swap::Call::cancel_swap { swap: token_swap.clone() }.into(); + let (spec_version, transaction_version) = + source_client.simple_runtime_version().await?; let _ = wait_until_transaction_is_finalized::( source_client .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { Bytes( - Source::sign_transaction( - source_genesis_hash, - &source_sign, - relay_substrate_client::TransactionEra::immortal(), - UnsignedTransaction::new( + Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( cancel_swap_call, transaction_nonce, ), - ) + }) .encode(), ) }, @@ -673,6 +692,7 @@ async fn read_token_swap_state( #[cfg(test)] mod tests { use super::*; + use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; #[test] fn swap_tokens_millau_to_rialto_no_lock() { @@ -706,6 +726,11 @@ mod tests { source_host: "127.0.0.1".into(), source_port: 9000, source_secure: false, + source_runtime_version: SourceRuntimeVersionParams { + source_version_mode: RuntimeVersionType::Bundle, + source_spec_version: None, + source_transaction_version: None, + } }, source_sign: SourceSigningParams { source_signer: Some("//Alice".into()), @@ -718,6 +743,11 @@ mod tests { target_host: "127.0.0.1".into(), target_port: 9001, target_secure: false, + target_runtime_version: TargetRuntimeVersionParams { + target_version_mode: RuntimeVersionType::Bundle, + target_spec_version: None, + target_transaction_version: None, + } }, target_sign: TargetSigningParams { target_signer: Some("//Bob".into()), @@ -767,6 +797,11 @@ mod tests { source_host: "127.0.0.1".into(), source_port: 9000, source_secure: false, + source_runtime_version: SourceRuntimeVersionParams { + source_version_mode: RuntimeVersionType::Bundle, + source_spec_version: None, + source_transaction_version: None, + } }, source_sign: SourceSigningParams { source_signer: Some("//Alice".into()), @@ -779,6 +814,11 @@ mod tests { target_host: "127.0.0.1".into(), target_port: 9001, target_secure: false, + target_runtime_version: TargetRuntimeVersionParams { + target_version_mode: RuntimeVersionType::Bundle, + target_spec_version: None, + target_transaction_version: None, + } }, target_sign: TargetSigningParams { target_signer: Some("//Bob".into()), diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 861816bb67390..1054995d65534 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -105,26 +105,22 @@ impl TransactionSignScheme for Kusama { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_kusama::SignedExtensions::new( - bp_kusama::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + param.spec_version, + param.transaction_version, + param.era, + param.genesis_hash, + param.unsigned.nonce, + param.unsigned.tip, ), ) .expect("SignedExtension never fails."); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); bp_kusama::UncheckedExtrinsic::new_signed( diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 96a046ef5cdc2..392f3fe118c53 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -20,7 +20,7 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -107,35 +107,30 @@ impl TransactionSignScheme for Millau { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = millau_runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { let raw_payload = SignedPayload::from_raw( - unsigned.call, + param.unsigned.call.clone(), ( frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era.frame_era()), - frame_system::CheckNonce::::from(unsigned.nonce), + frame_system::CheckEra::::from(param.era.frame_era()), + frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), + pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), ), ( - millau_runtime::VERSION.spec_version, - millau_runtime::VERSION.transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), + param.spec_version, + param.transaction_version, + param.genesis_hash, + param.era.signed_payload(param.genesis_hash), (), (), (), ), ); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); millau_runtime::UncheckedExtrinsic::new_signed( diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index d468206f9d5ea..bcdee223a9490 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -105,26 +105,22 @@ impl TransactionSignScheme for Polkadot { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_polkadot::SignedExtensions::new( - bp_polkadot::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + param.spec_version, + param.transaction_version, + param.era, + param.genesis_hash, + param.unsigned.nonce, + param.unsigned.tip, ), ) .expect("SignedExtension never fails."); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); bp_polkadot::UncheckedExtrinsic::new_signed( diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 80e3c2c7ae748..f11e735077e42 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -20,7 +20,7 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, TransactionEraOf, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -107,35 +107,30 @@ impl TransactionSignScheme for Rialto { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { let raw_payload = SignedPayload::from_raw( - unsigned.call, + param.unsigned.call.clone(), ( frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(era.frame_era()), - frame_system::CheckNonce::::from(unsigned.nonce), + frame_system::CheckEra::::from(param.era.frame_era()), + frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), + pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), ), ( - rialto_runtime::VERSION.spec_version, - rialto_runtime::VERSION.transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), + param.spec_version, + param.transaction_version, + param.genesis_hash, + param.era.signed_payload(param.genesis_hash), (), (), (), ), ); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); rialto_runtime::UncheckedExtrinsic::new_signed( diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index ee17e62dcd71f..124e3d49447ee 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -108,26 +108,22 @@ impl TransactionSignScheme for Rococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_rococo::SignedExtensions::new( - bp_rococo::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + param.spec_version, + param.transaction_version, + param.era, + param.genesis_hash, + param.unsigned.nonce, + param.unsigned.tip, ), ) .expect("SignedExtension never fails."); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); bp_rococo::UncheckedExtrinsic::new_signed( diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 6b62e699b7ef4..f447c50ccd9a9 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -172,12 +172,9 @@ pub trait TransactionSignScheme { type SignedTransaction: Clone + Debug + Codec + Send + 'static; /// Create transaction for given runtime call, signed by given account. - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction; + fn sign_transaction(param: SignParam) -> Self::SignedTransaction + where + Self: Sized; /// Returns true if transaction is signed. fn is_signed(tx: &Self::SignedTransaction) -> bool; @@ -191,6 +188,22 @@ pub trait TransactionSignScheme { fn parse_transaction(tx: Self::SignedTransaction) -> Option>; } +/// Sign transaction parameters +pub struct SignParam { + /// Version of the runtime specification. + pub spec_version: u32, + /// Transaction version + pub transaction_version: u32, + /// Hash of the genesis block. + pub genesis_hash: ::Hash, + /// Signer account + pub signer: T::AccountKeyPair, + /// Transaction era used by the chain. + pub era: TransactionEraOf, + /// Transaction before it is signed. + pub unsigned: UnsignedTransaction, +} + impl BlockWithJustification for SignedBlock { fn header(&self) -> Block::Header { self.block.header().clone() diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 443c80598c76e..74bf481d54806 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -60,6 +60,17 @@ pub struct Subscription(Mutex>>); /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; +/// Chain runtime version in client +#[derive(Clone, Debug)] +pub enum ChainRuntimeVersion { + /// Auto query from chain. + Auto, + /// Custom runtime version, defined by user. + /// the first is `spec_version` + /// the second is `transaction_version` + Custom(u32, u32), +} + /// Substrate client type. /// /// Cloning `Client` is a cheap operation. @@ -77,6 +88,8 @@ pub struct Client { /// transactions will be rejected from the pool. This lock is here to prevent situations like /// that. submit_signed_extrinsic_lock: Arc>, + /// Saved chain runtime version + chain_runtime_version: ChainRuntimeVersion, } #[async_trait] @@ -99,6 +112,7 @@ impl Clone for Client { client: self.client.clone(), genesis_hash: self.genesis_hash, submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(), + chain_runtime_version: self.chain_runtime_version.clone(), } } } @@ -144,12 +158,14 @@ impl Client { }) .await??; + let chain_runtime_version = params.chain_runtime_version.clone(); Ok(Self { tokio, params, client, genesis_hash, submit_signed_extrinsic_lock: Arc::new(Mutex::new(())), + chain_runtime_version, }) } @@ -178,6 +194,19 @@ impl Client { } impl Client { + /// Return simple runtime version, only include `spec_version` and `transaction_version`. + pub async fn simple_runtime_version(&self) -> Result<(u32, u32)> { + let (spec_version, transaction_version) = match self.chain_runtime_version { + ChainRuntimeVersion::Auto => { + let runtime_version = self.runtime_version().await?; + (runtime_version.spec_version, runtime_version.transaction_version) + }, + ChainRuntimeVersion::Custom(spec_version, transaction_version) => + (spec_version, transaction_version), + }; + Ok((spec_version, transaction_version)) + } + /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { self.jsonrpsee_execute(|client| async move { diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 56a6c981fcb18..dc005506be33c 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -32,10 +32,10 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithMessages, TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, - WeightToFeeOf, + ChainWithMessages, SignParam, TransactionSignScheme, TransactionStatusOf, + UnsignedTransaction, WeightToFeeOf, }, - client::{Client, OpaqueGrandpaAuthoritiesSet, Subscription}, + client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, sync_header::SyncHeader, }; @@ -56,11 +56,18 @@ pub struct ConnectionParams { pub port: u16, /// Use secure websocket connection. pub secure: bool, + /// Defined chain runtime version + pub chain_runtime_version: ChainRuntimeVersion, } impl Default for ConnectionParams { fn default() -> Self { - ConnectionParams { host: "localhost".into(), port: 9944, secure: false } + ConnectionParams { + host: "localhost".into(), + port: 9944, + secure: false, + chain_runtime_version: ChainRuntimeVersion::Auto, + } } } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index e9bdfd834a91e..97d749eb87795 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, TransactionEraOf, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -108,26 +108,22 @@ impl TransactionSignScheme for Wococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction( - genesis_hash: ::Hash, - signer: &Self::AccountKeyPair, - era: TransactionEraOf, - unsigned: UnsignedTransaction, - ) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Self::SignedTransaction { let raw_payload = SignedPayload::new( - unsigned.call, + param.unsigned.call.clone(), bp_wococo::SignedExtensions::new( - bp_wococo::VERSION, - era, - genesis_hash, - unsigned.nonce, - unsigned.tip, + param.spec_version, + param.transaction_version, + param.era, + param.genesis_hash, + param.unsigned.nonce, + param.unsigned.tip, ), ) .expect("SignedExtension never fails."); - let signature = raw_payload.using_encoded(|payload| signer.sign(payload)); - let signer: sp_runtime::MultiSigner = signer.public().into(); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); bp_wococo::UncheckedExtrinsic::new_signed( diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index 5daf6c7538a36..918c633d7420a 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -31,7 +31,7 @@ use codec::Encode; use finality_relay::TargetClient; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error, HashOf, HeaderOf, - SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, + SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::{Bytes, Pair}; @@ -103,17 +103,20 @@ where let transaction_params = self.transaction_params.clone(); let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { Bytes( - P::TransactionSignScheme::sign_transaction( + P::TransactionSignScheme::sign_transaction(SignParam { + spec_version, + transaction_version, genesis_hash, - &transaction_params.signer, - TransactionEra::new(best_block_id, transaction_params.mortality), - UnsignedTransaction::new(call, transaction_nonce), - ) + signer: transaction_params.signer.clone(), + era: TransactionEra::new(best_block_id, transaction_params.mortality), + unsigned: UnsignedTransaction::new(call, transaction_nonce), + }) .encode(), ) }, diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 1947f526a01f5..8519da7ae2720 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -44,8 +44,8 @@ use messages_relay::{ use num_traits::{Bounded, Zero}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme, - UnsignedTransaction, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + TransactionSignScheme, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -230,11 +230,14 @@ where ) -> Result<(), SubstrateError> { let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { make_messages_delivery_proof_transaction::

( + spec_version, + transaction_version, &genesis_hash, &transaction_params, best_block_id, @@ -257,8 +260,14 @@ where async fn estimate_confirmation_transaction( &self, ) -> as MessageLane>::SourceChainBalance { + let runtime_version = match self.client.runtime_version().await { + Ok(v) => v, + Err(_) => return BalanceOf::::max_value(), + }; self.client .estimate_extrinsic_fee(make_messages_delivery_proof_transaction::

( + runtime_version.spec_version, + runtime_version.transaction_version, self.client.genesis_hash(), &self.transaction_params, HeaderId(Default::default(), Default::default()), @@ -274,6 +283,8 @@ where /// Make messages delivery proof transaction from given proof. fn make_messages_delivery_proof_transaction( + spec_version: u32, + transaction_version: u32, source_genesis_hash: &HashOf, source_transaction_params: &TransactionParams>, source_best_block_id: HeaderIdOf, @@ -289,12 +300,14 @@ where proof, trace_call, ); Bytes( - P::SourceTransactionSignScheme::sign_transaction( - *source_genesis_hash, - &source_transaction_params.signer, - TransactionEra::new(source_best_block_id, source_transaction_params.mortality), - UnsignedTransaction::new(call, transaction_nonce), - ) + P::SourceTransactionSignScheme::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *source_genesis_hash, + signer: source_transaction_params.signer.clone(), + era: TransactionEra::new(source_best_block_id, source_transaction_params.mortality), + unsigned: UnsignedTransaction::new(call, transaction_nonce), + }) .encode(), ) } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 3cbe0181d7507..f896b63d4a678 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -40,8 +40,8 @@ use messages_relay::{ use num_traits::{Bounded, Zero}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, TransactionEra, TransactionSignScheme, - UnsignedTransaction, WeightToFeeOf, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + TransactionSignScheme, UnsignedTransaction, WeightToFeeOf, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -218,11 +218,14 @@ where let transaction_params = self.transaction_params.clone(); let relayer_id_at_source = self.relayer_id_at_source.clone(); let nonces_clone = nonces.clone(); + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { make_messages_delivery_transaction::

( + spec_version, + transaction_version, &genesis_hash, &transaction_params, best_block_id, @@ -260,8 +263,11 @@ where )) })?; + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. let delivery_tx = make_messages_delivery_transaction::

( + spec_version, + transaction_version, self.client.genesis_hash(), &self.transaction_params, HeaderId(Default::default(), Default::default()), @@ -297,10 +303,13 @@ where let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { const WEIGHT_DIFFERENCE: Weight = 100; + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); let larger_delivery_tx_fee = self .client .estimate_extrinsic_fee(make_messages_delivery_transaction::

( + spec_version, + transaction_version, self.client.genesis_hash(), &self.transaction_params, HeaderId(Default::default(), Default::default()), @@ -365,6 +374,8 @@ where /// Make messages delivery transaction from given proof. #[allow(clippy::too_many_arguments)] fn make_messages_delivery_transaction( + spec_version: u32, + transaction_version: u32, target_genesis_hash: &HashOf, target_transaction_params: &TransactionParams>, target_best_block_id: HeaderIdOf, @@ -387,12 +398,14 @@ where trace_call, ); Bytes( - P::TargetTransactionSignScheme::sign_transaction( - *target_genesis_hash, - &target_transaction_params.signer, - TransactionEra::new(target_best_block_id, target_transaction_params.mortality), - UnsignedTransaction::new(call, transaction_nonce), - ) + P::TargetTransactionSignScheme::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *target_genesis_hash, + signer: target_transaction_params.signer.clone(), + era: TransactionEra::new(target_best_block_id, target_transaction_params.mortality), + unsigned: UnsignedTransaction::new(call, transaction_nonce), + }) .encode(), ) } From 6130d2c282c9a9eed132ef66e110ed339efb1176 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 17 Dec 2021 13:29:51 +0300 Subject: [PATCH 0620/1210] move storage keys computation to primitivs (#1254) --- bin/rialto/runtime/src/lib.rs | 5 +- bin/runtime-common/src/messages.rs | 13 ++- modules/messages/Cargo.toml | 2 - modules/messages/src/lib.rs | 89 ++++----------- modules/token-swap/src/lib.rs | 13 ++- primitives/messages/Cargo.toml | 6 ++ primitives/messages/src/lib.rs | 1 + primitives/messages/src/storage_keys.rs | 102 ++++++++++++++++++ primitives/runtime/src/lib.rs | 35 +----- primitives/token-swap/Cargo.toml | 11 ++ primitives/token-swap/src/lib.rs | 17 ++- primitives/token-swap/src/storage_keys.rs | 51 +++++++++ .../src/cli/register_parachain.rs | 3 +- relays/bin-substrate/src/cli/swap_tokens.rs | 9 +- .../src/messages_source.rs | 4 +- .../src/messages_target.rs | 2 +- 16 files changed, 240 insertions(+), 123 deletions(-) create mode 100644 primitives/messages/src/storage_keys.rs create mode 100644 primitives/token-swap/src/storage_keys.rs diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8619cbade7934..de86deb907b30 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -1030,14 +1030,13 @@ impl_runtime_apis! { params: MessageProofParams, ) -> (millau_messages::FromMillauMessagesProof, Weight) { use crate::millau_messages::WithMillauMessageBridge; - use bp_messages::MessageKey; + use bp_messages::{MessageKey, storage_keys}; use bridge_runtime_common::{ messages::MessageBridge, messages_benchmarking::{ed25519_sign, prepare_message_proof}, }; use codec::Encode; use frame_support::weights::GetDispatchInfo; - use pallet_bridge_messages::storage_keys; use sp_runtime::traits::{Header, IdentifyAccount}; let remark = match params.size { @@ -1115,7 +1114,7 @@ impl_runtime_apis! { prepare_message_delivery_proof::( params, - |lane_id| pallet_bridge_messages::storage_keys::inbound_lane_data_key( + |lane_id| bp_messages::storage_keys::inbound_lane_data_key( ::BRIDGED_MESSAGES_PALLET_NAME, &lane_id, ).0, diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index b34cbb85540d4..dd03379ce5d5d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -428,7 +428,7 @@ pub mod source { // Messages delivery proof is just proof of single storage key read => any error // is fatal. let storage_inbound_lane_data_key = - pallet_bridge_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane); + bp_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane); let raw_inbound_lane_data = storage .read_value(storage_inbound_lane_data_key.0.as_ref()) .map_err(|_| "Failed to read inbound lane state from storage proof")? @@ -674,16 +674,15 @@ pub mod target { B: MessageBridge, { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { - let storage_outbound_lane_data_key = - pallet_bridge_messages::storage_keys::outbound_lane_data_key( - B::BRIDGED_MESSAGES_PALLET_NAME, - lane_id, - ); + let storage_outbound_lane_data_key = bp_messages::storage_keys::outbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + lane_id, + ); self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()? } fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - let storage_message_key = pallet_bridge_messages::storage_keys::message_key( + let storage_message_key = bp_messages::storage_keys::message_key( B::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, message_key.nonce, diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 6d52b899ea2bc..47fb4323bc1ab 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -30,8 +30,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -hex = "0.4" -hex-literal = "0.3" sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 119869d81e982..20b5570794a48 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -801,32 +801,6 @@ pub mod pallet { } } -/// Getting storage keys for messages and lanes states. These keys are normally used when building -/// messages and lanes states proofs. -pub mod storage_keys { - use super::*; - use sp_core::storage::StorageKey; - - /// Storage key of the outbound message in the runtime storage. - pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { - bp_runtime::storage_map_final_key_blake2_128concat( - pallet_prefix, - "OutboundMessages", - &MessageKey { lane_id: *lane, nonce }.encode(), - ) - } - - /// Storage key of the outbound message lane state in the runtime storage. - pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { - bp_runtime::storage_map_final_key_blake2_128concat(pallet_prefix, "OutboundLanes", lane) - } - - /// Storage key of the inbound message lane state in the runtime storage. - pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { - bp_runtime::storage_map_final_key_blake2_128concat(pallet_prefix, "InboundLanes", lane) - } -} - /// AccountId of the shared relayer fund account. /// /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending @@ -1159,9 +1133,8 @@ mod tests { REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; - use frame_support::{assert_noop, assert_ok, weights::Weight}; + use frame_support::{assert_noop, assert_ok, storage::generator::StorageMap, weights::Weight}; use frame_system::{EventRecord, Pallet as System, Phase}; - use hex_literal::hex; use sp_runtime::DispatchError; fn get_ready_for_events() { @@ -1889,45 +1862,6 @@ mod tests { }); } - #[test] - fn storage_message_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking - // all previously crafted messages proofs. - let storage_key = storage_keys::message_key("BridgeMessages", &*b"test", 42).0; - assert_eq!( - storage_key, - hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } - - #[test] - fn outbound_lane_data_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking - // all previously crafted outbound lane state proofs. - let storage_key = storage_keys::outbound_lane_data_key("BridgeMessages", &*b"test").0; - assert_eq!( - storage_key, - hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } - - #[test] - fn inbound_lane_data_key_computed_properly() { - // If this test fails, then something has been changed in module storage that is breaking - // all previously crafted inbound lane state proofs. - let storage_key = storage_keys::inbound_lane_data_key("BridgeMessages", &*b"test").0; - assert_eq!( - storage_key, - hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } - #[test] fn actual_dispatch_weight_does_not_overlow() { run_test(|| { @@ -2359,4 +2293,25 @@ mod tests { ); }); } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + OutboundMessages::::storage_map_final_key(MessageKey { + lane_id: TEST_LANE_ID, + nonce: 42 + }), + bp_messages::storage_keys::message_key("Messages", &TEST_LANE_ID, 42).0, + ); + + assert_eq!( + OutboundLanes::::storage_map_final_key(TEST_LANE_ID), + bp_messages::storage_keys::outbound_lane_data_key("Messages", &TEST_LANE_ID).0, + ); + + assert_eq!( + InboundLanes::::storage_map_final_key(TEST_LANE_ID), + bp_messages::storage_keys::inbound_lane_data_key("Messages", &TEST_LANE_ID).0, + ); + } } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 43fa13ba4bdb8..59db89b6fd513 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -95,9 +95,6 @@ pub mod weights_ext; pub use pallet::*; -/// Name of the `PendingSwaps` storage map. -pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; - // comes from #[pallet::event] #[allow(clippy::unused_unit)] #[frame_support::pallet] @@ -639,7 +636,7 @@ pub mod pallet { mod tests { use super::*; use crate::mock::*; - use frame_support::{assert_noop, assert_ok}; + use frame_support::{assert_noop, assert_ok, storage::generator::StorageMap}; const CAN_START_BLOCK_NUMBER: u64 = 10; const CAN_CLAIM_BLOCK_NUMBER: u64 = CAN_START_BLOCK_NUMBER + 1; @@ -1130,4 +1127,12 @@ mod tests { ); }); } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + PendingSwaps::::storage_map_final_key(test_swap_hash()), + bp_token_swap::storage_keys::pending_swaps_key("TokenSwap", test_swap_hash()).0, + ); + } } diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 95dca2bea67b8..5afa25fb301cd 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -21,8 +21,13 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +hex = "0.4" +hex-literal = "0.3" + [features] default = ["std"] std = [ @@ -32,5 +37,6 @@ std = [ "frame-system/std", "scale-info/std", "serde", + "sp-core/std", "sp-std/std" ] diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index abefe8d789b87..691ed57794db7 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -30,6 +30,7 @@ use scale_info::TypeInfo; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; +pub mod storage_keys; pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in related crates. diff --git a/primitives/messages/src/storage_keys.rs b/primitives/messages/src/storage_keys.rs new file mode 100644 index 0000000000000..3e8dc672541b6 --- /dev/null +++ b/primitives/messages/src/storage_keys.rs @@ -0,0 +1,102 @@ +// 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 . + +//! Storage keys of bridge messages pallet. + +/// Name of the `OutboundMessages` storage map. +pub const OUTBOUND_MESSAGES_MAP_NAME: &str = "OutboundMessages"; +/// Name of the `OutboundLanes` storage map. +pub const OUTBOUND_LANES_MAP_NAME: &str = "OutboundLanes"; +/// Name of the `InboundLanes` storage map. +pub const INBOUND_LANES_MAP_NAME: &str = "InboundLanes"; + +use crate::{LaneId, MessageKey, MessageNonce}; + +use codec::Encode; +use frame_support::Blake2_128Concat; +use sp_core::storage::StorageKey; + +/// Storage key of the outbound message in the runtime storage. +pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + OUTBOUND_MESSAGES_MAP_NAME, + &MessageKey { lane_id: *lane, nonce }.encode(), + ) +} + +/// Storage key of the outbound message lane state in the runtime storage. +pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + OUTBOUND_LANES_MAP_NAME, + lane, + ) +} + +/// Storage key of the inbound message lane state in the runtime storage. +pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + INBOUND_LANES_MAP_NAME, + lane, + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn storage_message_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted messages proofs. + let storage_key = message_key("BridgeMessages", &*b"test", 42).0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + + #[test] + fn outbound_lane_data_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted outbound lane state proofs. + let storage_key = outbound_lane_data_key("BridgeMessages", &*b"test").0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + + #[test] + fn inbound_lane_data_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // all previously crafted inbound lane state proofs. + let storage_key = inbound_lane_data_key("BridgeMessages", &*b"test").0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 051dc1f43c002..c01e7bb305a7f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -201,47 +201,22 @@ impl, BlockHash: Copy> TransactionEra( 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 key_hashed = H::hash(key); 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(), + pallet_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.as_ref().len(), ); final_key.extend_from_slice(&pallet_prefix_hashed[..]); diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 4b16c3567ea6e..4048ef5288b4f 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -10,18 +10,29 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } +# Bridge Dependencies + +bp-runtime = { path = "../runtime", 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +hex = "0.4" +hex-literal = "0.3" + [features] default = ["std"] std = [ + "bp-runtime/std", "codec/std", "frame-support/std", "scale-info/std", "sp-core/std", + "sp-io/std", "sp-std/std", ] diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs index d46389e86891d..79363e5477a44 100644 --- a/primitives/token-swap/src/lib.rs +++ b/primitives/token-swap/src/lib.rs @@ -16,10 +16,13 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub mod storage_keys; + use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; -use sp_core::U256; +use sp_core::{H256, U256}; +use sp_io::hashing::blake2_256; use sp_std::vec::Vec; /// Pending token swap state. @@ -85,6 +88,18 @@ pub struct TokenSwap + TokenSwap +where + TokenSwap: + Encode, +{ + /// Returns hash, used to identify this token swap. + pub fn hash(&self) -> H256 { + self.using_encoded(blake2_256).into() + } +} + /// SCALE-encoded `Currency::transfer` call on the bridged chain. pub type RawBridgedTransferCall = Vec; diff --git a/primitives/token-swap/src/storage_keys.rs b/primitives/token-swap/src/storage_keys.rs new file mode 100644 index 0000000000000..d0aafc0d5c273 --- /dev/null +++ b/primitives/token-swap/src/storage_keys.rs @@ -0,0 +1,51 @@ +// 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 . + +//! Storage keys of bridge token swap pallet. + +use frame_support::Identity; +use sp_core::{storage::StorageKey, H256}; + +/// Name of the `PendingSwaps` storage map. +pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; + +/// Storage key of `PendingSwaps` value with given token swap hash. +pub fn pending_swaps_key(pallet_prefix: &str, token_swap_hash: H256) -> StorageKey { + bp_runtime::storage_map_final_key::( + pallet_prefix, + PENDING_SWAPS_MAP_NAME, + token_swap_hash.as_ref(), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn pending_swaps_key_computed_properly() { + // If this test fails, then something has been changed in module storage that may break + // all previous swaps. + let storage_key = pending_swaps_key("BridgeTokenSwap", [42u8; 32].into()).0; + assert_eq!( + storage_key, + hex!("76276da64e7a4f454760eedeb4bad11adca2227fef56ad07cc424f1f5d128b9a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } +} diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 57e0517a56601..d42e10d708fb6 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -20,6 +20,7 @@ use crate::cli::{ }; use codec::Encode; +use frame_support::Twox64Concat; use num_traits::Zero; use polkadot_parachain::primitives::{ HeadData as ParaHeadData, Id as ParaId, ValidationCode as ParaValidationCode, @@ -202,7 +203,7 @@ impl RegisterParachain { log::info!(target: "bridge", "Registered parachain: {:?}. Waiting for onboarding", para_id); // wait until parathread is onboarded - let para_state_key = bp_runtime::storage_map_final_key_twox64_concat( + let para_state_key = bp_runtime::storage_map_final_key::( PARAS_PALLET_NAME, PARAS_LIFECYCLES_STORAGE_NAME, ¶_id.encode(), diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 18f4c1a46bc38..16ec0d6a6fa16 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -32,7 +32,7 @@ use relay_substrate_client::{ Client, Error as SubstrateError, HashOf, SignParam, SignatureOf, Subscription, TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, }; -use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, H256, U256}; +use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, U256}; use sp_runtime::traits::{Convert, Header as HeaderT}; use crate::cli::{ @@ -266,11 +266,10 @@ impl SwapTokens { .await?; // read state of swap after it has been created - let token_swap_hash: H256 = token_swap.using_encoded(blake2_256).into(); - let token_swap_storage_key = bp_runtime::storage_map_final_key_identity( + let token_swap_hash = token_swap.hash(); + let token_swap_storage_key = bp_token_swap::storage_keys::pending_swaps_key( TOKEN_SWAP_PALLET_NAME, - pallet_bridge_token_swap::PENDING_SWAPS_MAP_NAME, - token_swap_hash.as_ref(), + token_swap_hash, ); match read_token_swap_state(&source_client, swap_created_at, &token_swap_storage_key) .await? diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 8519da7ae2720..8ed05335649a9 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -197,7 +197,7 @@ where Vec::with_capacity(nonces.end().saturating_sub(*nonces.start()) as usize + 1); let mut message_nonce = *nonces.start(); while message_nonce <= *nonces.end() { - let message_key = pallet_bridge_messages::storage_keys::message_key( + let message_key = bp_messages::storage_keys::message_key( P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, message_nonce, @@ -206,7 +206,7 @@ where message_nonce += 1; } if proof_parameters.outbound_state_proof_required { - storage_keys.push(pallet_bridge_messages::storage_keys::outbound_lane_data_key( + storage_keys.push(bp_messages::storage_keys::outbound_lane_data_key( P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, )); diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index f896b63d4a678..7e7722bb575eb 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -190,7 +190,7 @@ where SubstrateError, > { let (id, relayers_state) = self.unrewarded_relayers_state(id).await?; - let inbound_data_key = pallet_bridge_messages::storage_keys::inbound_lane_data_key( + let inbound_data_key = bp_messages::storage_keys::inbound_lane_data_key( P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, ); From 575ed32d129b5f70bb12728c6204263f4b61dcd0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 17 Dec 2021 16:54:29 +0300 Subject: [PATCH 0621/1210] override conversion rate in estimate-message-fee RPC (#1189) --- bin/millau/runtime/src/lib.rs | 4 +- bin/millau/runtime/src/rialto_messages.rs | 13 ++++-- bin/rialto/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 13 ++++-- bin/runtime-common/src/messages.rs | 46 ++++++++++++++++--- primitives/chain-kusama/Cargo.toml | 2 + primitives/chain-kusama/src/lib.rs | 2 + primitives/chain-millau/src/lib.rs | 3 +- primitives/chain-polkadot/Cargo.toml | 2 + primitives/chain-polkadot/src/lib.rs | 2 + primitives/chain-rialto/src/lib.rs | 3 +- primitives/chain-rococo/src/lib.rs | 2 + primitives/chain-westend/Cargo.toml | 2 - primitives/chain-westend/src/lib.rs | 48 -------------------- primitives/chain-wococo/src/lib.rs | 2 + relays/bin-substrate/src/cli/estimate_fee.rs | 8 +++- 16 files changed, 85 insertions(+), 71 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4400191d940c9..f5dbab4e044a0 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -52,7 +52,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -744,10 +744,12 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToRialtoMessagePayload, + rialto_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithRialtoMessageBridge::RELAYER_FEE_PERCENT, + rialto_to_this_conversion_rate, ).ok() } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index d46ab4ca042a5..294b463084de1 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -91,11 +91,14 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; - fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { - bp_millau::Balance::try_from( - RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance), - ) - .unwrap_or(bp_millau::Balance::MAX) + fn bridged_balance_to_this_balance( + bridged_balance: bp_rialto::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_millau::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| RialtoToMillauConversionRate::get()); + bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_millau::Balance::MAX) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index de86deb907b30..e6097adadb884 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -53,7 +53,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -892,10 +892,12 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToMillauMessagePayload, + millau_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithMillauMessageBridge::RELAYER_FEE_PERCENT, + millau_to_this_conversion_rate, ).ok() } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 05935c90ea107..c6c382b43d298 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -91,11 +91,14 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; - fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { - bp_rialto::Balance::try_from( - MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance), - ) - .unwrap_or(bp_rialto::Balance::MAX) + fn bridged_balance_to_this_balance( + bridged_balance: bp_millau::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_rialto::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| MillauToRialtoConversionRate::get()); + bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_rialto::Balance::MAX) } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index dd03379ce5d5d..f88ed2f4af9c4 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -70,6 +70,7 @@ pub trait MessageBridge { /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance( bridged_balance: BalanceOf>, + bridged_to_this_conversion_rate_override: Option, ) -> BalanceOf>; } @@ -316,8 +317,11 @@ pub mod source { pallet_bridge_dispatch::verify_message_origin(submitter, payload) .map_err(|_| BAD_ORIGIN)?; - let minimal_fee_in_this_tokens = - estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; + let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( + payload, + B::RELAYER_FEE_PERCENT, + None, + )?; // compare with actual fee paid if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { @@ -371,6 +375,7 @@ pub mod source { pub fn estimate_message_dispatch_and_delivery_fee( payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, + bridged_to_this_conversion_rate: Option, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain // @@ -391,8 +396,11 @@ pub mod source { ThisChain::::transaction_payment(confirmation_transaction); // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee) - .checked_add(&confirmation_transaction_fee); + let minimal_fee = B::bridged_balance_to_this_balance( + delivery_transaction_fee, + bridged_to_this_conversion_rate, + ) + .checked_add(&confirmation_transaction_fee); // before returning, add extra fee that is paid to the relayer (relayer interest) minimal_fee @@ -798,8 +806,12 @@ mod tests { fn bridged_balance_to_this_balance( bridged_balance: BridgedChainBalance, + bridged_to_this_conversion_rate_override: Option, ) -> ThisChainBalance { - ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) + let conversion_rate = bridged_to_this_conversion_rate_override + .map(|r| r.to_float() as u32) + .unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE); + ThisChainBalance(bridged_balance.0 * conversion_rate) } } @@ -817,7 +829,10 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { + fn bridged_balance_to_this_balance( + _this_balance: ThisChainBalance, + _bridged_to_this_conversion_rate_override: Option, + ) -> BridgedChainBalance { unreachable!() } } @@ -1095,6 +1110,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ), Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); @@ -1106,6 +1122,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload_with_pay_on_target, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ) .expect( "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", @@ -1572,4 +1589,21 @@ mod tests { 100 + 50 * 10 + 777, ); } + + #[test] + fn conversion_rate_override_works() { + let payload = regular_outbound_message_payload(); + let regular_fee = source::estimate_message_dispatch_and_delivery_fee::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + None, + ); + let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)), + ); + + assert!(regular_fee < overrided_fee); + } } diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 6ff860357c7c4..8d2f0e98a0117 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 046323aa70091..2d798504b756d 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -141,6 +142,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + kusama_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 4b2b043ed1229..45c18b72482d4 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -33,7 +33,7 @@ use scale_info::TypeInfo; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; use sp_trie::{trie_types::Layout, TrieConfiguration}; @@ -319,6 +319,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + millau_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 917c7f9747839..710ed55e68c11 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 6989e6d2b641a..9f8b0ba3103d8 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -141,6 +142,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + polkadot_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index d994b2f03f634..a6bf07c0ec786 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -30,7 +30,7 @@ use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -291,6 +291,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + rialto_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index aca238358e187..94ec3af91e412 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -142,6 +143,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + rococo_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 4fd1652744ed6..cc2e912cea57f 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -14,7 +14,6 @@ smallvec = "1.7" # Bridge Dependencies bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -30,7 +29,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master default = ["std"] std = [ "bp-header-chain/std", - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index ffc0bf0fca109..37fe274fd3310 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -20,7 +20,6 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -130,51 +129,4 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); } - - /// Outbound message lane API for messages that are sent to Westend chain. - /// - /// This API is implemented by runtimes that are sending messages to Westend chain, not the - /// Westend runtime itself. - pub trait ToWestendOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Westend from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API for messages sent by Westend chain. - /// - /// This API is implemented by runtimes that are receiving messages from Westend chain, not the - /// Westend runtime itself. - pub trait FromWestendInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 20541d99a6ae5..6f586ae3fc3f9 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use sp_runtime::FixedU128; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -95,6 +96,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + wococo_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 18e7341fc9658..42ae354564feb 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -21,6 +21,7 @@ use crate::{ use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; +use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; @@ -72,8 +73,13 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee anyhow::Result { + let conversion_rate_override: Option = None; let encoded_response = client - .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .state_call( + estimate_fee_method.into(), + (lane, payload, conversion_rate_override).encode().into(), + None, + ) .await?; let decoded_response: Option = Decode::decode(&mut &encoded_response.0[..]) .map_err(relay_substrate_client::Error::ResponseParseFailed)?; From 39e5453cdf257829d660318873adcc2b99b0a99c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 21 Dec 2021 13:43:34 +0300 Subject: [PATCH 0622/1210] read latest_generated_nonce directly from storage (#1260) --- bin/millau/runtime/src/lib.rs | 4 ---- bin/rialto/runtime/src/lib.rs | 4 ---- primitives/chain-kusama/src/lib.rs | 5 ---- primitives/chain-millau/src/lib.rs | 5 ---- primitives/chain-polkadot/src/lib.rs | 5 ---- primitives/chain-rialto/src/lib.rs | 5 ---- primitives/chain-rococo/src/lib.rs | 5 ---- primitives/chain-westend/src/lib.rs | 23 ------------------- primitives/chain-wococo/src/lib.rs | 5 ---- relays/client-kusama/src/lib.rs | 2 -- relays/client-millau/src/lib.rs | 2 -- relays/client-polkadot/src/lib.rs | 2 -- relays/client-rialto/src/lib.rs | 2 -- relays/client-rococo/src/lib.rs | 2 -- relays/client-substrate/src/chain.rs | 3 --- relays/client-wococo/src/lib.rs | 2 -- .../src/messages_source.rs | 20 ++++++++++------ 17 files changed, 13 insertions(+), 83 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f5dbab4e044a0..8234b30ca1ec6 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -768,10 +768,6 @@ impl_runtime_apis! { fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { BridgeRialtoMessages::outbound_latest_received_nonce(lane) } - - fn latest_generated_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::outbound_latest_generated_nonce(lane) - } } impl bp_rialto::FromRialtoInboundLaneApi for Runtime { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e6097adadb884..e1e2b785b7154 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -916,10 +916,6 @@ impl_runtime_apis! { fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { BridgeMillauMessages::outbound_latest_received_nonce(lane) } - - fn latest_generated_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::outbound_latest_generated_nonce(lane) - } } impl bp_millau::FromMillauInboundLaneApi for Runtime { diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 2d798504b756d..fc09bfcb8e273 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -98,9 +98,6 @@ pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; -/// Name of the `ToKusamaOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD: &str = - "ToKusamaOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToKusamaOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = "ToKusamaOutboundLaneApi_latest_received_nonce"; @@ -156,8 +153,6 @@ sp_api::decl_runtime_apis! { ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Kusama chain. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 45c18b72482d4..df212509ada27 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -278,9 +278,6 @@ pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_mess /// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = "ToMillauOutboundLaneApi_latest_received_nonce"; -/// Name of the `ToMillauOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_MILLAU_LATEST_GENERATED_NONCE_METHOD: &str = - "ToMillauOutboundLaneApi_latest_generated_nonce"; /// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -333,8 +330,6 @@ sp_api::decl_runtime_apis! { ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Millau chain. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 9f8b0ba3103d8..51a4966534903 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -98,9 +98,6 @@ pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; -/// Name of the `ToPolkadotOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD: &str = - "ToPolkadotOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToPolkadotOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = "ToPolkadotOutboundLaneApi_latest_received_nonce"; @@ -156,8 +153,6 @@ sp_api::decl_runtime_apis! { ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Polkadot chain. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index a6bf07c0ec786..39310a48efcbd 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -247,9 +247,6 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; -/// Name of the `ToRialtoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_RIALTO_LATEST_GENERATED_NONCE_METHOD: &str = - "ToRialtoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRialtoOutboundLaneApi_latest_received_nonce"; @@ -305,8 +302,6 @@ sp_api::decl_runtime_apis! { ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Rialto chain. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 94ec3af91e412..a71be097daf08 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -87,9 +87,6 @@ pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; -/// Name of the `ToRococoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD: &str = - "ToRococoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToRococoOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToRococoOutboundLaneApi_latest_received_nonce"; @@ -157,8 +154,6 @@ sp_api::decl_runtime_apis! { ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Rococo chain. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 37fe274fd3310..268eea43ce63a 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -90,29 +90,6 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - /// Name of the `WestendFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; -/// Name of the `ToWestendOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_WESTEND_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToWestendOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToWestendOutboundLaneApi::message_details` runtime method. -pub const TO_WESTEND_MESSAGE_DETAILS_METHOD: &str = "ToWestendOutboundLaneApi_message_details"; -/// Name of the `ToWestendOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_WESTEND_LATEST_GENERATED_NONCE_METHOD: &str = - "ToWestendOutboundLaneApi_latest_generated_nonce"; -/// Name of the `ToWestendOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToWestendOutboundLaneApi_latest_received_nonce"; - -/// Name of the `FromWestendInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_WESTEND_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromWestendInboundLaneApi_latest_received_nonce"; -/// Name of the `FromWestendInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_WESTEND_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromWestendInboundLaneApi_latest_confirmed_nonce"; -/// Name of the `FromWestendInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_WESTEND_UNREWARDED_RELAYERS_STATE: &str = - "FromWestendInboundLaneApi_unrewarded_relayers_state"; - /// The target length of a session (how often authorities change) on Westend measured in of number /// of blocks. /// diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 6f586ae3fc3f9..617688e8e45a2 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -52,9 +52,6 @@ pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; -/// Name of the `ToWococoOutboundLaneApi::latest_generated_nonce` runtime method. -pub const TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD: &str = - "ToWococoOutboundLaneApi_latest_generated_nonce"; /// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method. pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = "ToWococoOutboundLaneApi_latest_received_nonce"; @@ -110,8 +107,6 @@ sp_api::decl_runtime_apis! { ) -> Vec>; /// Returns nonce of the latest message, received by bridged chain. fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Wococo chain. diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 1054995d65534..bdd7b74ffbf48 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -75,8 +75,6 @@ impl ChainWithMessages for Kusama { bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_GENERATED_NONCE_METHOD; const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 392f3fe118c53..3b441e9a0e716 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -59,8 +59,6 @@ impl ChainWithMessages for Millau { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_GENERATED_NONCE_METHOD; const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index bcdee223a9490..ca23fe3199794 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -75,8 +75,6 @@ impl ChainWithMessages for Polkadot { bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_GENERATED_NONCE_METHOD; const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index f11e735077e42..b3a3bd1eaf3d0 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -74,8 +74,6 @@ impl ChainWithMessages for Rialto { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_rialto::TO_RIALTO_LATEST_GENERATED_NONCE_METHOD; const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 124e3d49447ee..794e82efb038a 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Rococo { bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_rococo::TO_ROCOCO_LATEST_GENERATED_NONCE_METHOD; const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index f447c50ccd9a9..48dcc481325d1 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -76,9 +76,6 @@ pub trait ChainWithMessages: Chain { /// Name of the `ToOutboundLaneApi::message_details` runtime API method. /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the `ToOutboundLaneApi::latest_generated_nonce` runtime API - /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str; /// Name of the `ToOutboundLaneApi::latest_received_nonce` runtime API /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 97d749eb87795..1b634930dba1d 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Wococo { bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_GENERATED_NONCE_METHOD: &'static str = - bp_wococo::TO_WOCOCO_LATEST_GENERATED_NONCE_METHOD; const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 8ed05335649a9..4918635550adc 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -28,7 +28,10 @@ use crate::{ }; use async_trait::async_trait; -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{ + storage_keys::outbound_lane_data_key, LaneId, MessageNonce, OutboundLaneData, + UnrewardedRelayersState, +}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -126,16 +129,19 @@ where &self, id: SourceHeaderIdOf>, ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { - let encoded_response = self + let outbound_lane_data: Option = self .client - .state_call( - P::TargetChain::TO_CHAIN_LATEST_GENERATED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), + .storage_value( + outbound_lane_data_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), Some(id.1), ) .await?; - let latest_generated_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + // lane data missing from the storage is fine until first message is sent + let latest_generated_nonce = + outbound_lane_data.map(|data| data.latest_generated_nonce).unwrap_or(0); Ok((id, latest_generated_nonce)) } From abc7fd8900b0a343c426ce88604ac601c7ce3361 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Dec 2021 11:53:53 +0300 Subject: [PATCH 0623/1210] bump rococo version (#1263) --- primitives/chain-rococo/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a71be097daf08..5d95e7f1d1cc0 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -43,9 +43,9 @@ pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v1.6"), + impl_name: sp_version::create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 9130, + spec_version: 9140, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, From 3b728871d7b917ebfb1989ba2ac791014988ed53 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Dec 2021 12:50:39 +0300 Subject: [PATCH 0624/1210] remove OutboundLaneApi::latest_received_nonce (#1262) --- bin/millau/runtime/src/lib.rs | 4 ---- bin/rialto/runtime/src/lib.rs | 4 ---- modules/messages/src/lib.rs | 5 ----- primitives/chain-kusama/src/lib.rs | 5 ----- primitives/chain-millau/src/lib.rs | 5 ----- primitives/chain-polkadot/src/lib.rs | 5 ----- primitives/chain-rialto/src/lib.rs | 5 ----- primitives/chain-rococo/src/lib.rs | 5 ----- primitives/chain-wococo/src/lib.rs | 5 ----- relays/client-kusama/src/lib.rs | 2 -- relays/client-millau/src/lib.rs | 2 -- relays/client-polkadot/src/lib.rs | 2 -- relays/client-rialto/src/lib.rs | 2 -- relays/client-rococo/src/lib.rs | 2 -- relays/client-substrate/src/chain.rs | 3 --- relays/client-wococo/src/lib.rs | 2 -- relays/lib-substrate-relay/src/messages_source.rs | 15 +++++++++------ 17 files changed, 9 insertions(+), 64 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8234b30ca1ec6..81477245b564a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -764,10 +764,6 @@ impl_runtime_apis! { WithRialtoMessageBridge, >(lane, begin, end) } - - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::outbound_latest_received_nonce(lane) - } } impl bp_rialto::FromRialtoInboundLaneApi for Runtime { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e1e2b785b7154..1574535b895dd 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -912,10 +912,6 @@ impl_runtime_apis! { WithMillauMessageBridge, >(lane, begin, end) } - - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::outbound_latest_received_nonce(lane) - } } impl bp_millau::FromMillauInboundLaneApi for Runtime { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 20b5570794a48..6f1a432e09d2b 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -769,11 +769,6 @@ pub mod pallet { OutboundLanes::::get(&lane).latest_generated_nonce } - /// Get nonce of the latest confirmed message at given outbound lane. - pub fn outbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_received_nonce - } - /// Get nonce of the latest received message at given inbound lane. pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { InboundLanes::::get(&lane).last_delivered_nonce() diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index fc09bfcb8e273..63c76282dbe44 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -98,9 +98,6 @@ pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; -/// Name of the `ToKusamaOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToKusamaOutboundLaneApi_latest_received_nonce"; /// Name of the `FromKusamaInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -151,8 +148,6 @@ sp_api::decl_runtime_apis! { begin: MessageNonce, end: MessageNonce, ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Kusama chain. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index df212509ada27..9b1e2a9e69c35 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -275,9 +275,6 @@ pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; -/// Name of the `ToMillauOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToMillauOutboundLaneApi_latest_received_nonce"; /// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -328,8 +325,6 @@ sp_api::decl_runtime_apis! { begin: MessageNonce, end: MessageNonce, ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Millau chain. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 51a4966534903..4ba961e6dd57c 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -98,9 +98,6 @@ pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; -/// Name of the `ToPolkadotOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToPolkadotOutboundLaneApi_latest_received_nonce"; /// Name of the `FromPolkadotInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -151,8 +148,6 @@ sp_api::decl_runtime_apis! { begin: MessageNonce, end: MessageNonce, ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Polkadot chain. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 39310a48efcbd..2061ae0461cab 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -247,9 +247,6 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; -/// Name of the `ToRialtoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToRialtoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -300,8 +297,6 @@ sp_api::decl_runtime_apis! { begin: MessageNonce, end: MessageNonce, ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Rialto chain. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 5d95e7f1d1cc0..0593b0d8a1a20 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -87,9 +87,6 @@ pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; -/// Name of the `ToRococoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToRococoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromRococoInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -152,8 +149,6 @@ sp_api::decl_runtime_apis! { begin: MessageNonce, end: MessageNonce, ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Rococo chain. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 617688e8e45a2..ae4dd3864351f 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -52,9 +52,6 @@ pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; -/// Name of the `ToWococoOutboundLaneApi::latest_received_nonce` runtime method. -pub const TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "ToWococoOutboundLaneApi_latest_received_nonce"; /// Name of the `FromWococoInboundLaneApi::latest_received_nonce` runtime method. pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = @@ -105,8 +102,6 @@ sp_api::decl_runtime_apis! { begin: MessageNonce, end: MessageNonce, ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; } /// Inbound message lane API for messages sent by Wococo chain. diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index bdd7b74ffbf48..b6a1e1acf29e3 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -75,8 +75,6 @@ impl ChainWithMessages for Kusama { bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::TO_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 3b441e9a0e716..609e8d76d7366 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -59,8 +59,6 @@ impl ChainWithMessages for Millau { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::TO_MILLAU_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index ca23fe3199794..1ec34988b9be2 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -75,8 +75,6 @@ impl ChainWithMessages for Polkadot { bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index b3a3bd1eaf3d0..5a917a966087f 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -74,8 +74,6 @@ impl ChainWithMessages for Rialto { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::TO_RIALTO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 794e82efb038a..aa52fbc6b7e0d 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Rococo { bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rococo::TO_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 48dcc481325d1..aa3be46424178 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -76,9 +76,6 @@ pub trait ChainWithMessages: Chain { /// Name of the `ToOutboundLaneApi::message_details` runtime API method. /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the `ToOutboundLaneApi::latest_received_nonce` runtime API - /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; /// Name of the `FromInboundLaneApi::latest_received_nonce` runtime method. /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 1b634930dba1d..1f7c27c9bdf8a 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Wococo { bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_wococo::TO_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 4918635550adc..87296457f8a2b 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -149,16 +149,19 @@ where &self, id: SourceHeaderIdOf>, ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { - let encoded_response = self + let outbound_lane_data: Option = self .client - .state_call( - P::TargetChain::TO_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), + .storage_value( + outbound_lane_data_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), Some(id.1), ) .await?; - let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + // lane data missing from the storage is fine until first message is sent + let latest_received_nonce = + outbound_lane_data.map(|data| data.latest_received_nonce).unwrap_or(0); Ok((id, latest_received_nonce)) } From ff9a25331980a100e570adfacb0ce56c314332d5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Dec 2021 14:28:39 +0300 Subject: [PATCH 0625/1210] verify that GRANDPA pallet is not initialized before submitting initialization transaction (#1267) * verify that GRANDPA pallet is not initialized before submitting initialization transaction * spelling --- modules/grandpa/src/lib.rs | 13 ++++- primitives/chain-kusama/src/lib.rs | 2 + primitives/chain-millau/src/lib.rs | 2 + primitives/chain-polkadot/src/lib.rs | 2 + primitives/chain-rialto/src/lib.rs | 2 + primitives/chain-rococo/src/lib.rs | 2 + primitives/chain-westend/src/lib.rs | 3 ++ primitives/chain-wococo/src/lib.rs | 2 + primitives/header-chain/Cargo.toml | 7 +++ primitives/header-chain/src/lib.rs | 1 + primitives/header-chain/src/storage_keys.rs | 52 +++++++++++++++++++ relays/client-kusama/src/lib.rs | 8 ++- relays/client-millau/src/lib.rs | 8 ++- relays/client-polkadot/src/lib.rs | 9 +++- relays/client-rialto/src/lib.rs | 8 ++- relays/client-rococo/src/lib.rs | 8 ++- relays/client-substrate/src/chain.rs | 14 +++++ relays/client-substrate/src/lib.rs | 2 +- relays/client-westend/src/lib.rs | 7 ++- relays/client-wococo/src/lib.rs | 8 ++- relays/lib-substrate-relay/src/error.rs | 3 ++ .../src/headers_initialize.rs | 43 ++++++++++++--- 22 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 primitives/header-chain/src/storage_keys.rs diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index cbc85da30259f..1dadc58fe8688 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -626,7 +626,10 @@ mod tests { JustificationGeneratorParams, ALICE, BOB, }; use codec::Encode; - use frame_support::{assert_err, assert_noop, assert_ok, weights::PostDispatchInfo}; + use frame_support::{ + assert_err, assert_noop, assert_ok, storage::generator::StorageValue, + weights::PostDispatchInfo, + }; use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { @@ -1145,4 +1148,12 @@ mod tests { ); }) } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + BestFinalized::::storage_value_final_key().to_vec(), + bp_header_chain::storage_keys::best_finalized_hash_key("Grandpa").0, + ); + } } diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 63c76282dbe44..44cb7f009b539 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -82,6 +82,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; +/// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; /// Name of the With-Kusama messages pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 9b1e2a9e69c35..143772145bf4e 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -257,6 +257,8 @@ frame_support::parameter_types! { .build_or_panic(); } +/// Name of the With-Millau GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_MILLAU_GRANDPA_PALLET_NAME: &str = "BridgeMillauGrandpa"; /// Name of the With-Millau messages pallet instance that is deployed at bridged chains. pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 4ba961e6dd57c..9d5e18b4b8d5d 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -82,6 +82,8 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; +/// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; /// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 2061ae0461cab..79b0bf05a1686 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -226,6 +226,8 @@ frame_support::parameter_types! { .build_or_panic(); } +/// Name of the With-Rialto GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_GRANDPA_PALLET_NAME: &str = "BridgeRialtoGrandpa"; /// Name of the With-Rialto messages pallet instance that is deployed at bridged chains. pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 0593b0d8a1a20..868982b8ef42f 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -75,6 +75,8 @@ pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; /// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 268eea43ce63a..68bc22c7cdcb6 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -87,6 +87,9 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the With-Westend GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; + /// Name of the `WestendFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index ae4dd3864351f..5ebbde9d0034e 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -40,6 +40,8 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. +pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; /// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index b75a41a4b2e59..d4a7d30f90f6a 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -12,6 +12,10 @@ finality-grandpa = { version = "0.14.0", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } +# Bridge dependencies + +bp-runtime = { path = "../runtime", default-features = false } + # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -23,10 +27,13 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [dev-dependencies] assert_matches = "1.5" bp-test-utils = { path = "../test-utils" } +hex = "0.4" +hex-literal = "0.3" [features] default = ["std"] std = [ + "bp-runtime/std", "codec/std", "finality-grandpa/std", "serde/std", diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5feb30aec3eee..28949f28de5d8 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -29,6 +29,7 @@ use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT, Runtime use sp_std::boxed::Box; pub mod justification; +pub mod storage_keys; /// A type that can be used as a parameter in a dispatchable function. /// diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs new file mode 100644 index 0000000000000..460dbb8dc4d0e --- /dev/null +++ b/primitives/header-chain/src/storage_keys.rs @@ -0,0 +1,52 @@ +// 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 . + +//! Storage keys of bridge GRANDPA pallet. + +/// Name of the `BestFinalized` storage map. +pub const BEST_FINALIZED_MAP_NAME: &str = "BestFinalized"; + +use sp_core::storage::StorageKey; + +/// Storage key of the best finalized header hash value in the runtime storage. +pub fn best_finalized_hash_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + BEST_FINALIZED_MAP_NAME.as_bytes(), + ) + .to_vec(), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn best_finalized_hash_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // compatibility with previous pallet. + let storage_key = best_finalized_hash_key("BridgeGrandpa").0; + assert_eq!( + storage_key, + hex!("0b06f475eddb98cf933a12262e0388dea4ebafdd473c549fdb24c5c991c5591c").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } +} diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index b6a1e1acf29e3..78dd70b297c24 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -70,6 +70,10 @@ impl Chain for Kusama { type WeightToFee = bp_kusama::WeightToFee; } +impl ChainWithGrandpa for Kusama { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME; +} + impl ChainWithMessages for Kusama { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 609e8d76d7366..b1f14992d802e 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, SignParam, - TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, IndexOf, + SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -54,6 +54,10 @@ impl ChainBase for Millau { } } +impl ChainWithGrandpa for Millau { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME; +} + impl ChainWithMessages for Millau { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 1ec34988b9be2..cc3077c58245c 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -70,6 +70,11 @@ impl Chain for Polkadot { type WeightToFee = bp_polkadot::WeightToFee; } +impl ChainWithGrandpa for Polkadot { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME; +} + impl ChainWithMessages for Polkadot { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 5a917a966087f..8b1c1351d3aa5 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithMessages, IndexOf, SignParam, - TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, IndexOf, + SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -69,6 +69,10 @@ impl Chain for Rialto { type WeightToFee = bp_rialto::WeightToFee; } +impl ChainWithGrandpa for Rialto { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME; +} + impl ChainWithMessages for Rialto { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index aa52fbc6b7e0d..b125c63478d1b 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -73,6 +73,10 @@ impl Chain for Rococo { type WeightToFee = bp_rococo::WeightToFee; } +impl ChainWithGrandpa for Rococo { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rococo::WITH_ROCOCO_GRANDPA_PALLET_NAME; +} + impl ChainWithMessages for Rococo { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index aa3be46424178..b78a03dc7327c 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -64,6 +64,20 @@ pub trait Chain: ChainBase + Clone { type WeightToFee: WeightToFeePolynomial; } +/// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of +/// view. +/// +/// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement +/// this trait. +pub trait ChainWithGrandpa: Chain { + /// Name of the bridge GRANDPA pallet (used in `construct_runtime` macro call) that is deployed + /// at some other chain to bridge with this `ChainWithGrandpa`. + /// + /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using + /// the same name. + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str; +} + /// Substrate-based chain with messaging support from minimal relay-client point of view. pub trait ChainWithMessages: Chain { /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index dc005506be33c..b3a7ec414190f 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -32,7 +32,7 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithMessages, SignParam, TransactionSignScheme, TransactionStatusOf, + ChainWithGrandpa, ChainWithMessages, SignParam, TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, }, client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 004cb5476be7e..caf0c010c56ae 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Westend chain. use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -65,6 +65,11 @@ impl Chain for Westend { type WeightToFee = bp_westend::WeightToFee; } +impl ChainWithGrandpa for Westend { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + bp_westend::WITH_WESTEND_GRANDPA_PALLET_NAME; +} + impl ChainWithBalances for Westend { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_westend::account_info_storage_key(account_id)) diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 1f7c27c9bdf8a..4825a060101fa 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, SignParam, TransactionSignScheme, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, + TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -73,6 +73,10 @@ impl Chain for Wococo { type WeightToFee = bp_wococo::WeightToFee; } +impl ChainWithGrandpa for Wococo { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_wococo::WITH_WOCOCO_GRANDPA_PALLET_NAME; +} + impl ChainWithMessages for Wococo { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs index 802499503563d..9402d55e37981 100644 --- a/relays/lib-substrate-relay/src/error.rs +++ b/relays/lib-substrate-relay/src/error.rs @@ -55,4 +55,7 @@ pub enum Error { /// Failed to retrieve header by the hash from the source chain. #[error("Failed to retrieve {0} header with hash {1}: {:?}")] RetrieveHeader(&'static str, Hash, client::Error), + /// Failed to retrieve best finalized source header hash from the target chain. + #[error("Failed to retrieve best finalized {0} header from the target chain: {1}")] + RetrieveBestFinalizedHeaderHash(&'static str, client::Error), } diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index 2e802c4cb2150..8713663dd8296 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -31,13 +31,13 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use relay_substrate_client::{Chain, Client}; +use relay_substrate_client::{BlockNumberOf, Chain, ChainWithGrandpa, Client, HashOf}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; use sp_runtime::traits::Header as HeaderT; /// Submit headers-bridge initialization transaction. -pub async fn initialize( +pub async fn initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, @@ -54,13 +54,14 @@ pub async fn initialize( .await; match result { - Ok(tx_hash) => log::info!( + Ok(Some(tx_hash)) => log::info!( target: "bridge", "Successfully submitted {}-headers bridge initialization transaction to {}: {:?}", SourceChain::NAME, TargetChain::NAME, tx_hash, ), + Ok(None) => (), Err(err) => log::error!( target: "bridge", "Failed to submit {}-headers bridge initialization transaction to {}: {:?}", @@ -72,14 +73,28 @@ pub async fn initialize( } /// Craft and submit initialization transaction, returning any error that may occur. -async fn do_initialize( +async fn do_initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + Send + 'static, -) -> Result::Number>> { +) -> Result< + Option, + Error::Number>, +> { + let is_initialized = is_initialized::(&target_client).await?; + if is_initialized { + log::info!( + target: "bridge", + "{}-headers bridge at {} is already initialized. Skipping", + SourceChain::NAME, + TargetChain::NAME, + ); + return Ok(None) + } + let initialization_data = prepare_initialization_data(source_client).await?; log::info!( target: "bridge", @@ -95,7 +110,23 @@ async fn do_initialize( }) .await .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; - Ok(initialization_tx_hash) + Ok(Some(initialization_tx_hash)) +} + +/// Returns `Ok(true)` if bridge has already been initialized. +async fn is_initialized( + target_client: &Client, +) -> Result, BlockNumberOf>> { + Ok(target_client + .raw_storage_value( + bp_header_chain::storage_keys::best_finalized_hash_key( + SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME, + ), + None, + ) + .await + .map_err(|err| Error::RetrieveBestFinalizedHeaderHash(SourceChain::NAME, err))? + .is_some()) } /// Prepare initialization data for the GRANDPA verifier pallet. From ebaa49ac1f37b9a74de3581370e00306aec91691 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Dec 2021 17:18:43 +0300 Subject: [PATCH 0626/1210] Replace InboundLaneApi::latest_received_nonce with direct storage read (#1269) * remove inbound_latest_received_nonce * Update relays/lib-substrate-relay/src/messages_target.rs Co-authored-by: Adrian Catangiu --- bin/millau/runtime/src/lib.rs | 4 --- bin/rialto/runtime/src/lib.rs | 4 --- modules/messages/src/benchmarking.rs | 28 +++++++++---------- modules/messages/src/lib.rs | 10 ------- primitives/chain-kusama/src/lib.rs | 5 ---- primitives/chain-millau/src/lib.rs | 5 ---- primitives/chain-polkadot/src/lib.rs | 5 ---- primitives/chain-rialto/src/lib.rs | 5 ---- primitives/chain-rococo/src/lib.rs | 5 ---- primitives/chain-wococo/src/lib.rs | 5 ---- relays/client-kusama/src/lib.rs | 2 -- relays/client-millau/src/lib.rs | 2 -- relays/client-polkadot/src/lib.rs | 2 -- relays/client-rialto/src/lib.rs | 2 -- relays/client-rococo/src/lib.rs | 2 -- relays/client-substrate/src/chain.rs | 3 -- relays/client-wococo/src/lib.rs | 2 -- .../src/messages_target.rs | 20 ++++++++----- 18 files changed, 27 insertions(+), 84 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 81477245b564a..2e40b6949709c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -767,10 +767,6 @@ impl_runtime_apis! { } impl bp_rialto::FromRialtoInboundLaneApi for Runtime { - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::inbound_latest_received_nonce(lane) - } - fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { BridgeRialtoMessages::inbound_latest_confirmed_nonce(lane) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 1574535b895dd..0bb998046240b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -915,10 +915,6 @@ impl_runtime_apis! { } impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn latest_received_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::inbound_latest_received_nonce(lane) - } - fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { BridgeMillauMessages::inbound_latest_confirmed_nonce(lane) } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 788ccc070310e..2074c55980bdd 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -155,7 +155,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -192,7 +192,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -229,7 +229,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -297,7 +297,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -331,7 +331,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 22, ); assert!(T::is_message_dispatched(22)); @@ -369,7 +369,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert_eq!( @@ -405,7 +405,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -439,7 +439,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -472,7 +472,7 @@ benchmarks_instance_pallet! { }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); assert!(T::is_message_dispatched(21)); @@ -634,7 +634,7 @@ benchmarks_instance_pallet! { }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) verify { assert_eq!( - crate::Pallet::::outbound_latest_generated_nonce(T::bench_lane_id()), + crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, T::MaxMessagesToPruneAtOnce::get() + 1, ); } @@ -674,7 +674,7 @@ benchmarks_instance_pallet! { ) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 20 + i as MessageNonce, ); } @@ -712,7 +712,7 @@ benchmarks_instance_pallet! { ) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); } @@ -750,7 +750,7 @@ benchmarks_instance_pallet! { ) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); } @@ -794,7 +794,7 @@ benchmarks_instance_pallet! { ) verify { assert_eq!( - crate::Pallet::::inbound_latest_received_nonce(T::bench_lane_id()), + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 20 + i as MessageNonce, ); assert_eq!( diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 6f1a432e09d2b..09298013a5b6c 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -764,16 +764,6 @@ pub mod pallet { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } - /// Get nonce of the latest generated message at given outbound lane. - pub fn outbound_latest_generated_nonce(lane: LaneId) -> MessageNonce { - OutboundLanes::::get(&lane).latest_generated_nonce - } - - /// Get nonce of the latest received message at given inbound lane. - pub fn inbound_latest_received_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_delivered_nonce() - } - /// Get nonce of the latest confirmed message at given inbound lane. pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { InboundLanes::::get(&lane).last_confirmed_nonce diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 44cb7f009b539..f15486e0a7749 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -101,9 +101,6 @@ pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; -/// Name of the `FromKusamaInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromKusamaInboundLaneApi_latest_received_nonce"; /// Name of the `FromKusamaInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromKusamaInboundLaneApi_latest_confirmed_nonce"; @@ -157,8 +154,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the /// Kusama runtime itself. pub trait FromKusamaInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 143772145bf4e..0a9790a096eea 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -278,9 +278,6 @@ pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; -/// Name of the `FromMillauInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromMillauInboundLaneApi_latest_received_nonce"; /// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromMillauInboundLaneApi_latest_confirmed_nonce"; @@ -334,8 +331,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Millau chain, not the /// Millau runtime itself. pub trait FromMillauInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 9d5e18b4b8d5d..635525fc7f5c5 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -101,9 +101,6 @@ pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; -/// Name of the `FromPolkadotInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromPolkadotInboundLaneApi_latest_received_nonce"; /// Name of the `FromPolkadotInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromPolkadotInboundLaneApi_latest_confirmed_nonce"; @@ -157,8 +154,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the /// Polkadot runtime itself. pub trait FromPolkadotInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 79b0bf05a1686..6c0a678f50142 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -250,9 +250,6 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; -/// Name of the `FromRialtoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromRialtoInboundLaneApi_latest_received_nonce"; /// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRialtoInboundLaneApi_latest_confirmed_nonce"; @@ -306,8 +303,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the /// Rialto runtime itself. pub trait FromRialtoInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 868982b8ef42f..2397ea17e96ed 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -90,9 +90,6 @@ pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; -/// Name of the `FromRococoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromRococoInboundLaneApi_latest_received_nonce"; /// Name of the `FromRococoInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromRococoInboundLaneApi_latest_confirmed_nonce"; @@ -158,8 +155,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the /// Rococo runtime itself. pub trait FromRococoInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 5ebbde9d0034e..d0a1c71c0f72c 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -55,9 +55,6 @@ pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; -/// Name of the `FromWococoInboundLaneApi::latest_received_nonce` runtime method. -pub const FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD: &str = - "FromWococoInboundLaneApi_latest_received_nonce"; /// Name of the `FromWococoInboundLaneApi::latest_onfirmed_nonce` runtime method. pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = "FromWococoInboundLaneApi_latest_confirmed_nonce"; @@ -111,8 +108,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the /// Wococo runtime itself. pub trait FromWococoInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; /// Nonce of the latest message that has been confirmed to the bridged chain. fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 78dd70b297c24..55e8169941fdd 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -79,8 +79,6 @@ impl ChainWithMessages for Kusama { bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index b1f14992d802e..908ffc929c5d8 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -63,8 +63,6 @@ impl ChainWithMessages for Millau { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_millau::FROM_MILLAU_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index cc3077c58245c..fbe1ffae08805 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -80,8 +80,6 @@ impl ChainWithMessages for Polkadot { bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 8b1c1351d3aa5..61065b352fcbe 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Rialto { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index b125c63478d1b..7319b3f2eeb40 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -82,8 +82,6 @@ impl ChainWithMessages for Rococo { bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index b78a03dc7327c..d11e732d317e6 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -91,9 +91,6 @@ pub trait ChainWithMessages: Chain { /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the `FromInboundLaneApi::latest_received_nonce` runtime method. - /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str; /// Name of the `FromInboundLaneApi::latest_confirmed_nonce` runtime method. /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 4825a060101fa..a6f6d734dd396 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -82,8 +82,6 @@ impl ChainWithMessages for Wococo { bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_LATEST_RECEIVED_NONCE_METHOD; const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 7e7722bb575eb..cdd25c64e58c5 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -27,7 +27,10 @@ use crate::{ }; use async_trait::async_trait; -use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{ + storage_keys::inbound_lane_data_key, InboundLaneData, LaneId, MessageNonce, + UnrewardedRelayersState, +}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -130,16 +133,19 @@ where &self, id: TargetHeaderIdOf>, ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { - let encoded_response = self + let inbound_lane_data: Option>> = self .client - .state_call( - P::SourceChain::FROM_CHAIN_LATEST_RECEIVED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), + .storage_value( + inbound_lane_data_key( + P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), Some(id.1), ) .await?; - let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + // lane data missing from the storage is fine until first message is received + let latest_received_nonce = + inbound_lane_data.map(|data| data.last_delivered_nonce()).unwrap_or(0); Ok((id, latest_received_nonce)) } From 6ba7a7a74800333d8ad7ec2bf04a8024da57b56b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Dec 2021 13:30:30 +0300 Subject: [PATCH 0627/1210] Revert "override conversion rate in estimate-message-fee RPC (#1189)" (#1275) This reverts commit 575ed32d129b5f70bb12728c6204263f4b61dcd0. --- bin/millau/runtime/src/lib.rs | 4 +- bin/millau/runtime/src/rialto_messages.rs | 13 ++---- bin/rialto/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 13 ++---- bin/runtime-common/src/messages.rs | 46 +++---------------- primitives/chain-kusama/Cargo.toml | 2 - primitives/chain-kusama/src/lib.rs | 2 - primitives/chain-millau/src/lib.rs | 3 +- primitives/chain-polkadot/Cargo.toml | 2 - primitives/chain-polkadot/src/lib.rs | 2 - primitives/chain-rialto/src/lib.rs | 3 +- primitives/chain-rococo/src/lib.rs | 2 - primitives/chain-westend/Cargo.toml | 2 + primitives/chain-westend/src/lib.rs | 48 ++++++++++++++++++++ primitives/chain-wococo/src/lib.rs | 2 - relays/bin-substrate/src/cli/estimate_fee.rs | 8 +--- 16 files changed, 71 insertions(+), 85 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2e40b6949709c..b4a80659ab544 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -52,7 +52,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -744,12 +744,10 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToRialtoMessagePayload, - rialto_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithRialtoMessageBridge::RELAYER_FEE_PERCENT, - rialto_to_this_conversion_rate, ).ok() } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 294b463084de1..d46ab4ca042a5 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -91,14 +91,11 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; - fn bridged_balance_to_this_balance( - bridged_balance: bp_rialto::Balance, - bridged_to_this_conversion_rate_override: Option, - ) -> bp_millau::Balance { - let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(|| RialtoToMillauConversionRate::get()); - bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) - .unwrap_or(bp_millau::Balance::MAX) + fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { + bp_millau::Balance::try_from( + RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance), + ) + .unwrap_or(bp_millau::Balance::MAX) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0bb998046240b..ab5318a4f7648 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -53,7 +53,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -892,12 +892,10 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToMillauMessagePayload, - millau_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithMillauMessageBridge::RELAYER_FEE_PERCENT, - millau_to_this_conversion_rate, ).ok() } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index c6c382b43d298..05935c90ea107 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -91,14 +91,11 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; - fn bridged_balance_to_this_balance( - bridged_balance: bp_millau::Balance, - bridged_to_this_conversion_rate_override: Option, - ) -> bp_rialto::Balance { - let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(|| MillauToRialtoConversionRate::get()); - bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) - .unwrap_or(bp_rialto::Balance::MAX) + fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { + bp_rialto::Balance::try_from( + MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance), + ) + .unwrap_or(bp_rialto::Balance::MAX) } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index f88ed2f4af9c4..dd03379ce5d5d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -70,7 +70,6 @@ pub trait MessageBridge { /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance( bridged_balance: BalanceOf>, - bridged_to_this_conversion_rate_override: Option, ) -> BalanceOf>; } @@ -317,11 +316,8 @@ pub mod source { pallet_bridge_dispatch::verify_message_origin(submitter, payload) .map_err(|_| BAD_ORIGIN)?; - let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( - payload, - B::RELAYER_FEE_PERCENT, - None, - )?; + let minimal_fee_in_this_tokens = + estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; // compare with actual fee paid if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { @@ -375,7 +371,6 @@ pub mod source { pub fn estimate_message_dispatch_and_delivery_fee( payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, - bridged_to_this_conversion_rate: Option, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain // @@ -396,11 +391,8 @@ pub mod source { ThisChain::::transaction_payment(confirmation_transaction); // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = B::bridged_balance_to_this_balance( - delivery_transaction_fee, - bridged_to_this_conversion_rate, - ) - .checked_add(&confirmation_transaction_fee); + let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee) + .checked_add(&confirmation_transaction_fee); // before returning, add extra fee that is paid to the relayer (relayer interest) minimal_fee @@ -806,12 +798,8 @@ mod tests { fn bridged_balance_to_this_balance( bridged_balance: BridgedChainBalance, - bridged_to_this_conversion_rate_override: Option, ) -> ThisChainBalance { - let conversion_rate = bridged_to_this_conversion_rate_override - .map(|r| r.to_float() as u32) - .unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE); - ThisChainBalance(bridged_balance.0 * conversion_rate) + ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) } } @@ -829,10 +817,7 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn bridged_balance_to_this_balance( - _this_balance: ThisChainBalance, - _bridged_to_this_conversion_rate_override: Option, - ) -> BridgedChainBalance { + fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { unreachable!() } } @@ -1110,7 +1095,6 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload, OnThisChainBridge::RELAYER_FEE_PERCENT, - None, ), Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); @@ -1122,7 +1106,6 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload_with_pay_on_target, OnThisChainBridge::RELAYER_FEE_PERCENT, - None, ) .expect( "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", @@ -1589,21 +1572,4 @@ mod tests { 100 + 50 * 10 + 777, ); } - - #[test] - fn conversion_rate_override_works() { - let payload = regular_outbound_message_payload(); - let regular_fee = source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ); - let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)), - ); - - assert!(regular_fee < overrided_fee); - } } diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 8d2f0e98a0117..6ff860357c7c4 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -19,7 +19,6 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -31,7 +30,6 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", - "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index f15486e0a7749..362e46d1eddf7 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -24,7 +24,6 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; -use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -135,7 +134,6 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, - kusama_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 0a9790a096eea..2f51320dc8381 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -33,7 +33,7 @@ use scale_info::TypeInfo; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{Convert, IdentifyAccount, Verify}, - FixedU128, MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; use sp_trie::{trie_types::Layout, TrieConfiguration}; @@ -312,7 +312,6 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, - millau_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 710ed55e68c11..917c7f9747839 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -19,7 +19,6 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -31,7 +30,6 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", - "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 635525fc7f5c5..16c9a76bfd9e2 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -24,7 +24,6 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; -use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -135,7 +134,6 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, - polkadot_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 6c0a678f50142..4fd7cbb463a26 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -30,7 +30,7 @@ use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, - FixedU128, MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -284,7 +284,6 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, - rialto_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 2397ea17e96ed..222279e391dcf 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -24,7 +24,6 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; -use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -136,7 +135,6 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, - rococo_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index cc2e912cea57f..4fd1652744ed6 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -14,6 +14,7 @@ smallvec = "1.7" # Bridge Dependencies bp-header-chain = { path = "../header-chain", default-features = false } +bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -29,6 +30,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master default = ["std"] std = [ "bp-header-chain/std", + "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 68bc22c7cdcb6..fe804f93f7d75 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -20,6 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] +use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -109,4 +110,51 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); } + + /// Outbound message lane API for messages that are sent to Westend chain. + /// + /// This API is implemented by runtimes that are sending messages to Westend chain, not the + /// Westend runtime itself. + pub trait ToWestendOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to Westend from this chain. + /// + /// Please keep in mind that this method returns the lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + ) -> Option; + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn message_details( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec>; + /// Returns nonce of the latest message, received by bridged chain. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Returns nonce of the latest message, generated by given lane. + fn latest_generated_nonce(lane: LaneId) -> MessageNonce; + } + + /// Inbound message lane API for messages sent by Westend chain. + /// + /// This API is implemented by runtimes that are receiving messages from Westend chain, not the + /// Westend runtime itself. + pub trait FromWestendInboundLaneApi { + /// Returns nonce of the latest message, received by given lane. + fn latest_received_nonce(lane: LaneId) -> MessageNonce; + /// Nonce of the latest message that has been confirmed to the bridged chain. + fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; + /// State of the unrewarded relayers set at given lane. + fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; + } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index d0a1c71c0f72c..90eed6e33f727 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -21,7 +21,6 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; -use sp_runtime::FixedU128; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -89,7 +88,6 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, - wococo_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 42ae354564feb..18e7341fc9658 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -21,7 +21,6 @@ use crate::{ use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; -use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; @@ -73,13 +72,8 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee anyhow::Result { - let conversion_rate_override: Option = None; let encoded_response = client - .state_call( - estimate_fee_method.into(), - (lane, payload, conversion_rate_override).encode().into(), - None, - ) + .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) .await?; let decoded_response: Option = Decode::decode(&mut &encoded_response.0[..]) .map_err(relay_substrate_client::Error::ResponseParseFailed)?; From 7f10a117cc481759fe2a5ec7d0655a5bbe50a5a2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 10 Jan 2022 18:34:38 +0300 Subject: [PATCH 0628/1210] Move benchmarks from Rialto to Millau (#1277) * move brnchmarks from Rialto to Millau * fix limits test --- bin/millau/runtime/Cargo.toml | 7 + bin/millau/runtime/src/lib.rs | 212 +++++++++++++++- bin/millau/runtime/src/rialto_messages.rs | 4 +- bin/rialto/runtime/src/lib.rs | 240 +----------------- modules/grandpa/src/weights.rs | 26 +- modules/messages/src/weights.rs | 182 ++++++------- modules/messages/src/weights_ext.rs | 2 +- modules/token-swap/src/benchmarking.rs | 2 +- modules/token-swap/src/weights.rs | 14 +- primitives/chain-millau/src/lib.rs | 2 +- primitives/chain-rialto/src/lib.rs | 2 +- .../src/chains/kusama_headers_to_polkadot.rs | 2 +- .../lib-substrate-relay/src/messages_lane.rs | 4 +- 13 files changed, 329 insertions(+), 370 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 13195b95194ba..4fe2f72a962c5 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,12 +10,14 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } scale-info = { version = "1.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } +bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } @@ -71,6 +73,7 @@ default = ["std"] std = [ "beefy-primitives/std", "bp-header-chain/std", + "bp-message-dispatch/std", "bp-messages/std", "bp-millau/std", "bp-rialto/std", @@ -116,8 +119,12 @@ std = [ "sp-version/std", ] runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", "frame-benchmarking", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "libsecp256k1", + "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-token-swap/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b4a80659ab544..4d6ecd8ba3895 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -374,12 +374,26 @@ parameter_types! { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. pub const MaxRequests: u32 = 50; +} - // Number of headers to keep. - // - // Assuming the worst case of every header being finalized, we will keep headers for at least a - // week. - pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32; +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + /// Number of headers to keep in benchmarks. + /// + /// In benchmarks we always populate with full number of `HeadersToKeep` to make sure that + /// pruning is taken into account. + /// + /// Note: This is lower than regular value, to speed up benchmarking setup. + pub const HeadersToKeep: u32 = 1024; +} + +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + /// Number of headers to keep. + /// + /// Assuming the worst case of every header being finalized, we will keep headers at least for a + /// week. + pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; } pub type RialtoGrandpaInstance = (); @@ -388,8 +402,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. - type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; @@ -398,8 +411,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - // TODO [#391]: Use weights generated for the Millau runtime instead of Rialto ones. - type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -422,8 +434,7 @@ pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; + type WeightInfo = pallet_bridge_messages::weights::MillauWeight; type Parameter = rialto_messages::MillauToRialtoMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -783,9 +794,13 @@ impl_runtime_apis! { use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; + use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; + let mut list = Vec::::new(); list_benchmark!(list, extra, pallet_bridge_token_swap, BridgeRialtoTokenSwap); + list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); + list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); let storage_info = AllPalletsWithSystem::storage_info(); @@ -813,6 +828,171 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); + use bp_runtime::messages::DispatchFeePayment; + use bridge_runtime_common::messages; + use pallet_bridge_messages::benchmarking::{ + Pallet as MessagesBench, + Config as MessagesConfig, + MessageDeliveryProofParams, + MessageParams, + MessageProofParams, + ProofSize as MessagesProofSize, + }; + use rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; + + impl MessagesConfig for Runtime { + fn maximal_message_size() -> u32 { + messages::source::maximal_message_size::() + } + + fn bridged_relayer_id() -> Self::InboundRelayer { + Default::default() + } + + fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { + pallet_balances::Pallet::::free_balance(account) + } + + fn endow_account(account: &Self::AccountId) { + pallet_balances::Pallet::::make_free_balance_be( + account, + Balance::MAX / 100, + ); + } + + fn prepare_outbound_message( + params: MessageParams, + ) -> (rialto_messages::ToRialtoMessagePayload, Balance) { + let message_payload = vec![0; params.size as usize]; + let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount( + params.sender_account, + ); + + let message = ToRialtoMessagePayload { + spec_version: 0, + weight: params.size as _, + origin: dispatch_origin, + call: message_payload, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + }; + (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) + } + + fn prepare_message_proof( + params: MessageProofParams, + ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { + use bp_messages::{MessageKey, storage_keys}; + use bridge_runtime_common::{ + messages::MessageBridge, + messages_benchmarking::{ed25519_sign, prepare_message_proof}, + }; + use codec::Encode; + use frame_support::weights::GetDispatchInfo; + use rialto_messages::WithRialtoMessageBridge; + use sp_runtime::traits::{Header, IdentifyAccount}; + + let remark = match params.size { + MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }; + let call = Call::System(SystemCall::remark { remark }); + let call_weight = call.get_dispatch_info().weight; + + let rialto_account_id: bp_rialto::AccountId = Default::default(); + let (millau_raw_public, millau_raw_signature) = ed25519_sign( + &call, + &rialto_account_id, + VERSION.spec_version, + bp_runtime::RIALTO_CHAIN_ID, + bp_runtime::MILLAU_CHAIN_ID, + ); + let millau_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(millau_raw_public)); + let millau_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( + millau_raw_signature, + )); + + if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { + Self::endow_account(&millau_public.clone().into_account()); + } + + let make_rialto_message_key = |message_key: MessageKey| storage_keys::message_key( + ::BRIDGED_MESSAGES_PALLET_NAME, + &message_key.lane_id, message_key.nonce, + ).0; + let make_rialto_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key( + ::BRIDGED_MESSAGES_PALLET_NAME, + &lane_id, + ).0; + + let make_rialto_header = |state_root| bp_rialto::Header::new( + 0, + Default::default(), + state_root, + Default::default(), + Default::default(), + ); + + let dispatch_fee_payment = params.dispatch_fee_payment.clone(); + prepare_message_proof::( + params, + make_rialto_message_key, + make_rialto_outbound_lane_data_key, + make_rialto_header, + call_weight, + bp_message_dispatch::MessagePayload { + spec_version: VERSION.spec_version, + weight: call_weight, + origin: bp_message_dispatch::CallOrigin::< + bp_rialto::AccountId, + MultiSigner, + Signature, + >::TargetAccount( + rialto_account_id, + millau_public, + millau_signature, + ), + dispatch_fee_payment, + call: call.encode(), + }.encode(), + ) + } + + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> rialto_messages::ToRialtoMessagesDeliveryProof { + use bridge_runtime_common::messages_benchmarking::prepare_message_delivery_proof; + use rialto_messages::WithRialtoMessageBridge; + use sp_runtime::traits::Header; + + prepare_message_delivery_proof::( + params, + |lane_id| bp_messages::storage_keys::inbound_lane_data_key( + ::BRIDGED_MESSAGES_PALLET_NAME, + &lane_id, + ).0, + |state_root| bp_rialto::Header::new( + 0, + Default::default(), + state_root, + Default::default(), + Default::default(), + ), + ) + } + + fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool { + frame_system::Pallet::::events() + .into_iter() + .map(|event_record| event_record.event) + .any(|event| matches!( + event, + Event::BridgeDispatch(pallet_bridge_dispatch::Event::::MessageDispatched( + _, ([0, 0, 0, 0], nonce_from_event), _, + )) if nonce_from_event == nonce + )) + } + } + use pallet_bridge_token_swap::benchmarking::Config as TokenSwapConfig; impl TokenSwapConfig for Runtime { @@ -828,6 +1008,13 @@ impl_runtime_apis! { } } + add_benchmark!( + params, + batches, + pallet_bridge_messages, + MessagesBench:: + ); + add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); add_benchmark!(params, batches, pallet_bridge_token_swap, BridgeRialtoTokenSwap); if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } @@ -868,8 +1055,7 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { - // TODO: https://github.com/paritytech/parity-bridges-common/issues/390 - type Weights = pallet_bridge_messages::weights::RialtoWeight; + type Weights = pallet_bridge_messages::weights::MillauWeight; pallet_bridge_messages::ensure_weights_are_correct::( bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index d46ab4ca042a5..4403c423c2c1f 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -64,10 +64,10 @@ pub type FromRialtoMessagePayload = pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; /// Messages proof for Rialto -> Millau messages. -type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; +pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; /// Messages delivery proof for Millau -> Rialto messages. -type ToRialtoMessagesDeliveryProof = +pub type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; /// Call-dispatch based message dispatch for Rialto -> Millau messages. diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index ab5318a4f7648..a68de93069519 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -399,21 +399,7 @@ parameter_types! { /// Note that once this is hit the pallet will essentially throttle incoming requests down to one /// call per block. pub const MaxRequests: u32 = 50; -} - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - /// Number of headers to keep in benchmarks. - /// - /// In benchmarks we always populate with full number of `HeadersToKeep` to make sure that - /// pruning is taken into account. - /// - /// Note: This is lower than regular value, to speed up benchmarking setup. - pub const HeadersToKeep: u32 = 1024; -} -#[cfg(not(feature = "runtime-benchmarks"))] -parameter_types! { /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a @@ -426,7 +412,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type WeightInfo = pallet_bridge_grandpa::weights::RialtoWeight; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -449,7 +435,7 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_messages::weights::RialtoWeight; + type WeightInfo = pallet_bridge_messages::weights::MillauWeight; type Parameter = millau_messages::RialtoToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -921,226 +907,6 @@ impl_runtime_apis! { BridgeMillauMessages::inbound_unrewarded_relayers_state(lane) } } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn benchmark_metadata(extra: bool) -> ( - Vec, - Vec, - ) { - use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; - use frame_support::traits::StorageInfoTrait; - - use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; - - let mut list = Vec::::new(); - - list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); - list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeMillauGrandpa); - - let storage_info = AllPalletsWithSystem::storage_info(); - - return (list, storage_info) - } - - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig, - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; - - let whitelist: Vec = vec![ - // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), - // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), - // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), - // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), - // Caller 0 Account - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), - ]; - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - - use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; - use bp_runtime::messages::DispatchFeePayment; - use bridge_runtime_common::messages; - use pallet_bridge_messages::benchmarking::{ - Pallet as MessagesBench, - Config as MessagesConfig, - MessageDeliveryProofParams, - MessageParams, - MessageProofParams, - ProofSize as MessagesProofSize, - }; - - impl MessagesConfig for Runtime { - fn maximal_message_size() -> u32 { - messages::source::maximal_message_size::() - } - - fn bridged_relayer_id() -> Self::InboundRelayer { - Default::default() - } - - fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { - pallet_balances::Pallet::::free_balance(account) - } - - fn endow_account(account: &Self::AccountId) { - pallet_balances::Pallet::::make_free_balance_be( - account, - Balance::MAX / 100, - ); - } - - fn prepare_outbound_message( - params: MessageParams, - ) -> (millau_messages::ToMillauMessagePayload, Balance) { - let message_payload = vec![0; params.size as usize]; - let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount( - params.sender_account, - ); - - let message = ToMillauMessagePayload { - spec_version: 0, - weight: params.size as _, - origin: dispatch_origin, - call: message_payload, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }; - (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) - } - - fn prepare_message_proof( - params: MessageProofParams, - ) -> (millau_messages::FromMillauMessagesProof, Weight) { - use crate::millau_messages::WithMillauMessageBridge; - use bp_messages::{MessageKey, storage_keys}; - use bridge_runtime_common::{ - messages::MessageBridge, - messages_benchmarking::{ed25519_sign, prepare_message_proof}, - }; - use codec::Encode; - use frame_support::weights::GetDispatchInfo; - use sp_runtime::traits::{Header, IdentifyAccount}; - - let remark = match params.size { - MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }; - let call = Call::System(SystemCall::remark { remark }); - let call_weight = call.get_dispatch_info().weight; - - let millau_account_id: bp_millau::AccountId = Default::default(); - let (rialto_raw_public, rialto_raw_signature) = ed25519_sign( - &call, - &millau_account_id, - VERSION.spec_version, - bp_runtime::MILLAU_CHAIN_ID, - bp_runtime::RIALTO_CHAIN_ID, - ); - let rialto_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(rialto_raw_public)); - let rialto_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( - rialto_raw_signature, - )); - - if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { - Self::endow_account(&rialto_public.clone().into_account()); - } - - let make_millau_message_key = |message_key: MessageKey| storage_keys::message_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &message_key.lane_id, message_key.nonce, - ).0; - let make_millau_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &lane_id, - ).0; - - let make_millau_header = |state_root| bp_millau::Header::new( - 0, - Default::default(), - state_root, - Default::default(), - Default::default(), - ); - - let dispatch_fee_payment = params.dispatch_fee_payment.clone(); - prepare_message_proof::( - params, - make_millau_message_key, - make_millau_outbound_lane_data_key, - make_millau_header, - call_weight, - bp_message_dispatch::MessagePayload { - spec_version: VERSION.spec_version, - weight: call_weight, - origin: bp_message_dispatch::CallOrigin::< - bp_millau::AccountId, - MultiSigner, - Signature, - >::TargetAccount( - millau_account_id, - rialto_public, - rialto_signature, - ), - dispatch_fee_payment, - call: call.encode(), - }.encode(), - ) - } - - fn prepare_message_delivery_proof( - params: MessageDeliveryProofParams, - ) -> millau_messages::ToMillauMessagesDeliveryProof { - use crate::millau_messages::WithMillauMessageBridge; - use bridge_runtime_common::{messages_benchmarking::prepare_message_delivery_proof}; - use sp_runtime::traits::Header; - - prepare_message_delivery_proof::( - params, - |lane_id| bp_messages::storage_keys::inbound_lane_data_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &lane_id, - ).0, - |state_root| bp_millau::Header::new( - 0, - Default::default(), - state_root, - Default::default(), - Default::default(), - ), - ) - } - - fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool { - frame_system::Pallet::::events() - .into_iter() - .map(|event_record| event_record.event) - .any(|event| matches!( - event, - Event::BridgeDispatch(pallet_bridge_dispatch::Event::::MessageDispatched( - _, ([0, 0, 0, 0], nonce_from_event), _, - )) if nonce_from_event == nonce - )) - } - } - - add_benchmark!( - params, - batches, - pallet_bridge_messages, - MessagesBench:: - ); - add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeMillauGrandpa); - - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } - Ok(batches) - } - } } /// Millau account ownership digest from Rialto. @@ -1175,7 +941,7 @@ mod tests { #[test] fn ensure_rialto_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::RialtoWeight; + type Weights = pallet_bridge_messages::weights::MillauWeight; pallet_bridge_messages::ensure_weights_are_correct::( bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index c0cce2c5258d1..2c4660160a004 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -16,14 +16,14 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-03, STEPS: [50, ], REPEAT: 20 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// target/release/rialto-bridge-node +// target/release/millau-bridge-node // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/grandpa/src/weights.rs -// --template=./.maintain/rialto-weight-template.hbs +// --template=./.maintain/millau-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] @@ -51,13 +51,13 @@ pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; } -/// Weights for `pallet_bridge_grandpa` using the Rialto node and recommended hardware. -pub struct RialtoWeight(PhantomData); -impl WeightInfo for RialtoWeight { +/// Weights for `pallet_bridge_grandpa` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (0 as Weight) - .saturating_add((59_692_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((6_876_000 as Weight).saturating_mul(v as Weight)) + (115_651_000 as Weight) + .saturating_add((61_465_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((3_438_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -66,9 +66,9 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (0 as Weight) - .saturating_add((59_692_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((6_876_000 as Weight).saturating_mul(v as Weight)) + (115_651_000 as Weight) + .saturating_add((61_465_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((3_438_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 9dce11168fbbc..7c5df201f985d 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -16,14 +16,14 @@ //! Autogenerated weights for `pallet_bridge_messages` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-06-18, STEPS: [50, ], REPEAT: 20 +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: -// target/release/rialto-bridge-node +// target/release/millau-bridge-node // benchmark // --chain=dev // --steps=50 @@ -34,7 +34,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/messages/src/weights.rs -// --template=./.maintain/rialto-weight-template.hbs +// --template=./.maintain/millau-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] @@ -71,120 +71,120 @@ pub trait WeightInfo { fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } -/// Weights for `pallet_bridge_messages` using the Rialto node and recommended hardware. -pub struct RialtoWeight(PhantomData); -impl WeightInfo for RialtoWeight { +/// Weights for `pallet_bridge_messages` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { fn send_minimal_message_worst_case() -> Weight { - (159_305_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (117_480_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (164_394_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (128_391_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (223_521_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (149_149_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (6_781_470_000 as Weight) + (6_015_058_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn increase_message_fee(i: u32) -> Weight { - (114_963_000 as Weight) - .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (206_769_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (179_892_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (343_982_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (291_793_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (223_738_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (192_191_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (235_369_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (202_104_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (510_338_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (357_144_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (141_536_000 as Weight) + (122_648_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (128_805_000 as Weight) + (107_631_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (137_143_000 as Weight) + (113_885_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (193_108_000 as Weight) + (155_151_000 as Weight) .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (133_632_000 as Weight) - .saturating_add((4_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (0 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { - (0 as Weight) - .saturating_add((145_006_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (56_209_000 as Weight) + .saturating_add((109_502_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (486_301_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (0 as Weight) + .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (178_139_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (50_281_000 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((150_844_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) + (70_297_000 as Weight) + .saturating_add((110_892_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (113_140_000 as Weight) - .saturating_add((7_656_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((8_016_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (97_424_000 as Weight) - .saturating_add((63_128_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((50_981_000 as Weight).saturating_mul(i as Weight)) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(T::DbWeight::get().writes(3 as Weight)) @@ -195,116 +195,116 @@ impl WeightInfo for RialtoWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (159_305_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (117_480_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (164_394_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (128_391_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (223_521_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (149_149_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (6_781_470_000 as Weight) + (6_015_058_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn increase_message_fee(i: u32) -> Weight { - (114_963_000 as Weight) - .saturating_add((6_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof() -> Weight { - (206_769_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (179_892_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_two_messages_proof() -> Weight { - (343_982_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (291_793_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (223_738_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (192_191_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (235_369_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (202_104_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (510_338_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (357_144_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (141_536_000 as Weight) + (122_648_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (128_805_000 as Weight) + (107_631_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (137_143_000 as Weight) + (113_885_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (193_108_000 as Weight) + (155_151_000 as Weight) .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn send_messages_of_various_lengths(i: u32) -> Weight { - (133_632_000 as Weight) - .saturating_add((4_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (0 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(12 as Weight)) } fn receive_multiple_messages_proof(i: u32) -> Weight { - (0 as Weight) - .saturating_add((145_006_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (56_209_000 as Weight) + .saturating_add((109_502_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (486_301_000 as Weight) - .saturating_add((10_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (0 as Weight) + .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (178_139_000 as Weight) - .saturating_add((7_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (50_281_000 as Weight) + .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (0 as Weight) - .saturating_add((150_844_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + (70_297_000 as Weight) + .saturating_add((110_892_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (113_140_000 as Weight) - .saturating_add((7_656_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((8_016_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (97_424_000 as Weight) - .saturating_add((63_128_000 as Weight).saturating_mul(i as Weight)) + (0 as Weight) + .saturating_add((50_981_000 as Weight).saturating_mul(i as Weight)) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index fef09c6cebe57..483a22eda1d6b 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -390,7 +390,7 @@ impl WeightInfoExt for () { } } -impl WeightInfoExt for crate::weights::RialtoWeight { +impl WeightInfoExt for crate::weights::MillauWeight { fn expected_extra_storage_proof_size() -> u32 { EXTRA_STORAGE_PROOF_SIZE } diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs index bbc544a8b91df..6ca35f5f39470 100644 --- a/modules/token-swap/src/benchmarking.rs +++ b/modules/token-swap/src/benchmarking.rs @@ -30,7 +30,7 @@ use frame_system::RawOrigin; use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::Bounded; -use sp_std::vec::Vec; +use sp_std::{boxed::Box, vec::Vec}; const SEED: u32 = 0; diff --git a/modules/token-swap/src/weights.rs b/modules/token-swap/src/weights.rs index 06cb6b85cf336..51c5d99de9c5c 100644 --- a/modules/token-swap/src/weights.rs +++ b/modules/token-swap/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_token_swap` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-10-06, STEPS: 50, REPEAT: 20 +//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 128 @@ -57,17 +57,17 @@ pub trait WeightInfo { pub struct MillauWeight(PhantomData); impl WeightInfo for MillauWeight { fn create_swap() -> Weight { - (116_040_000 as Weight) + (90_368_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn claim_swap() -> Weight { - (102_882_000 as Weight) + (88_397_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn cancel_swap() -> Weight { - (99_434_000 as Weight) + (91_253_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -76,17 +76,17 @@ impl WeightInfo for MillauWeight { // For backwards compatibility and tests impl WeightInfo for () { fn create_swap() -> Weight { - (116_040_000 as Weight) + (90_368_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } fn claim_swap() -> Weight { - (102_882_000 as Weight) + (88_397_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn cancel_swap() -> Weight { - (99_434_000 as Weight) + (91_253_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 2f51320dc8381..6a8bbd3e336fc 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -103,7 +103,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// chain. Don't put too much reserve there, because it is used to **decrease** /// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery /// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; /// The target length of a session (how often authorities change) on Millau measured in of number of /// blocks. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 4fd7cbb463a26..b995410a6565b 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -94,7 +94,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// chain. Don't put too much reserve there, because it is used to **decrease** /// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery /// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; /// The target length of a session (how often authorities change) on Rialto measured in of number of /// blocks. diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index c36c336718c0d..13d9f12141f6d 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -83,7 +83,7 @@ pub(crate) mod tests { // differ from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is // the same. type GrandpaPalletWeights = - pallet_bridge_grandpa::weights::RialtoWeight; + pallet_bridge_grandpa::weights::MillauWeight; // The following formula shall not be treated as super-accurate - guard is to protect from // mad relays, not to protect from over-average loses. diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 4742ce6e48296..87146be4896cc 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -453,7 +453,7 @@ mod tests { use bp_runtime::Chain; type RialtoToMillauMessagesWeights = - pallet_bridge_messages::weights::RialtoWeight; + pallet_bridge_messages::weights::MillauWeight; #[test] fn select_delivery_transaction_limits_works() { @@ -469,7 +469,7 @@ mod tests { // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (782, 216_583_333_334), + (958, 216_583_333_334), ); } } From b62bf8b483184e363af64796a3ba5d43e7df01fb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 11 Jan 2022 16:00:26 +0300 Subject: [PATCH 0629/1210] removed extra messages benchmarks (#1279) --- modules/messages/README.md | 5 +- modules/messages/src/benchmarking.rs | 301 +-------------------------- modules/messages/src/weights.rs | 97 --------- 3 files changed, 3 insertions(+), 400 deletions(-) diff --git a/modules/messages/README.md b/modules/messages/README.md index 062a966fad70a..2dc5629684242 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -294,9 +294,8 @@ Where: *\* - In all benchmarks all received messages are dispatched and their dispatch cost is near to zero* *\*\* - Trie leafs are assumed to have minimal values. The proof is derived from the minimal proof -by including more trie nodes. That's because according to `receive_message_proofs_with_large_leaf` -and `receive_message_proofs_with_extra_nodes` benchmarks, increasing proof by including more nodes -has slightly larger impact on performance than increasing values stored in leafs*. +by including more trie nodes. That's because according to our additioal benchmarks, increasing proof +by including more nodes has slightly larger impact on performance than increasing values stored in leafs*. #### Weight formula diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 2074c55980bdd..f396365699f4b 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -30,12 +30,7 @@ use bp_runtime::messages::DispatchFeePayment; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; -use sp_std::{ - collections::{btree_map::BTreeMap, vec_deque::VecDeque}, - convert::TryInto, - ops::RangeInclusive, - prelude::*, -}; +use sp_std::{collections::vec_deque::VecDeque, convert::TryInto, ops::RangeInclusive, prelude::*}; /// Fee paid by submitter for single message delivery. pub const MESSAGE_FEE: u64 = 100_000_000_000; @@ -602,300 +597,6 @@ benchmarks_instance_pallet! { ensure_relayer_rewarded::(&relayer1_id, &relayer1_balance); ensure_relayer_rewarded::(&relayer2_id, &relayer2_balance); } - - // - // Benchmarks for manual checks. - // - - // Benchmark `send_message` extrinsic with following conditions: - // * outbound lane already has state, so it needs to be read and decoded; - // * relayers fund account does not exists (in practice it needs to exist in production environment); - // * maximal number of messages is being pruned during the call; - // * message size varies from minimal to maximal for the target chain. - // - // Results of this benchmark may be used to check how message size affects `send_message` performance. - send_messages_of_various_lengths { - let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); - - let lane_id = T::bench_lane_id(); - let sender = account("sender", 0, SEED); - T::endow_account(&sender); - - // 'send' messages that are to be pruned when our message is sent - for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { - send_regular_message::(); - } - confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - - let (payload, fee) = T::prepare_outbound_message(MessageParams { - size: i as _, - sender_account: sender.clone(), - }); - }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) - verify { - assert_eq!( - crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, - T::MaxMessagesToPruneAtOnce::get() + 1, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // This benchmarks gives us an approximation of single message delivery weight. It is similar to the - // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. So it may be used - // to verify that the other approximation is correct. - receive_multiple_messages_proof { - let i in 1..64; - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = i as _; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=(20 + i as MessageNonce), - outbound_lane_data: None, - size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), - 20 + i as MessageNonce, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // Results of this benchmark may be used to check how proof size affects `receive_message_proof` performance. - receive_message_proofs_with_extra_nodes { - let i in 0..T::maximal_message_size(); - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = 1u32; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=21, - outbound_lane_data: None, - size: ProofSize::HasExtraNodes(i as _), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), - 21, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // Results of this benchmark may be used to check how message size affects `receive_message_proof` performance. - receive_message_proofs_with_large_leaf { - let i in 0..T::maximal_message_size(); - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = 1u32; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=21, - outbound_lane_data: None, - size: ProofSize::HasLargeLeaf(i as _), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), - 21, - ); - } - - // Benchmark `receive_messages_proof` extrinsic with multiple minimal-weight messages and following conditions: - // * proof includes outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher. - // - // This benchmarks gives us an approximation of outbound lane state delivery weight. It is similar to the - // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. - // So it may be used to verify that the other approximation is correct. - receive_multiple_messages_proof_with_outbound_lane_state { - let i in 1..128; - - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - let messages_count = i as _; - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=20 + i as MessageNonce, - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 21, - latest_received_nonce: 20, - latest_generated_nonce: 21, - }), - size: ProofSize::Minimal(0), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }); - }: receive_messages_proof( - RawOrigin::Signed(relayer_id_on_target), - relayer_id_on_source, - proof, - messages_count, - dispatch_weight - ) - verify { - assert_eq!( - crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), - 20 + i as MessageNonce, - ); - assert_eq!( - crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), - 20, - ); - } - - // Benchmark `receive_messages_delivery_proof` extrinsic where single relayer delivers multiple messages. - receive_delivery_proof_for_multiple_messages_by_single_relayer { - // there actually should be used value of `MaxUnrewardedRelayerEntriesAtInboundLane` from the bridged - // chain, but we're more interested in additional weight/message than in max weight - let i in 1..T::MaxUnrewardedRelayerEntriesAtInboundLane::get() - .try_into() - .expect("Value of MaxUnrewardedRelayerEntriesAtInboundLane is too large"); - - let relayers_fund_id = crate::relayer_fund_account_id::(); - let relayer_id: T::AccountId = account("relayer", 0, SEED); - let relayer_balance = T::account_balance(&relayer_id); - T::endow_account(&relayers_fund_id); - - // send messages that we're going to confirm - for _ in 1..=i { - send_regular_message::(); - } - - let relayers_state = UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - messages_in_oldest_entry: 1, - total_messages: i as MessageNonce, - }; - let mut delivered_messages = DeliveredMessages::new(1, true); - for nonce in 2..=i { - delivered_messages.note_dispatched_message(true); - } - let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: T::bench_lane_id(), - inbound_lane_data: InboundLaneData { - relayers: vec![UnrewardedRelayer { - relayer: relayer_id.clone(), - messages: delivered_messages, - }].into_iter().collect(), - last_confirmed_nonce: 0, - }, - size: ProofSize::Minimal(0), - }); - }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) - verify { - ensure_relayer_rewarded::(&relayer_id, &relayer_balance); - } - - // Benchmark `receive_messages_delivery_proof` extrinsic where every relayer delivers single messages. - receive_delivery_proof_for_multiple_messages_by_multiple_relayers { - // there actually should be used value of `MaxUnconfirmedMessagesAtInboundLane` from the bridged - // chain, but we're more interested in additional weight/message than in max weight - let i in 1..T::MaxUnconfirmedMessagesAtInboundLane::get() - .try_into() - .expect("Value of MaxUnconfirmedMessagesAtInboundLane is too large "); - - let relayers_fund_id = crate::relayer_fund_account_id::(); - let confirmation_relayer_id = account("relayer", 0, SEED); - let relayers: BTreeMap = (1..=i) - .map(|j| { - let relayer_id = account("relayer", j + 1, SEED); - let relayer_balance = T::account_balance(&relayer_id); - (relayer_id, relayer_balance) - }) - .collect(); - T::endow_account(&relayers_fund_id); - - // send messages that we're going to confirm - for _ in 1..=i { - send_regular_message::(); - } - - let relayers_state = UnrewardedRelayersState { - unrewarded_relayer_entries: i as MessageNonce, - messages_in_oldest_entry: 1, - total_messages: i as MessageNonce, - }; - let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { - lane: T::bench_lane_id(), - inbound_lane_data: InboundLaneData { - relayers: relayers - .keys() - .enumerate() - .map(|(j, relayer)| UnrewardedRelayer { - relayer: relayer.clone(), - messages: DeliveredMessages::new(j as MessageNonce + 1, true), - }) - .collect(), - last_confirmed_nonce: 0, - }, - size: ProofSize::Minimal(0), - }); - }: receive_messages_delivery_proof(RawOrigin::Signed(confirmation_relayer_id), proof, relayers_state) - verify { - for (relayer_id, prev_balance) in relayers { - ensure_relayer_rewarded::(&relayer_id, &prev_balance); - } - } } fn send_regular_message, I: 'static>() { diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 7c5df201f985d..462f768a08b38 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -62,13 +62,6 @@ pub trait WeightInfo { fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; - fn send_messages_of_various_lengths(i: u32) -> Weight; - fn receive_multiple_messages_proof(i: u32) -> Weight; - fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight; - fn receive_message_proofs_with_large_leaf(i: u32) -> Weight; - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight; - fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight; - fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight; } /// Weights for `pallet_bridge_messages` using the Millau node and recommended hardware. @@ -145,51 +138,6 @@ impl WeightInfo for MillauWeight { .saturating_add(T::DbWeight::get().reads(8 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } - fn send_messages_of_various_lengths(i: u32) -> Weight { - (0 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) - } - fn receive_multiple_messages_proof(i: u32) -> Weight { - (56_209_000 as Weight) - .saturating_add((109_502_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (0 as Weight) - .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (50_281_000 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (70_297_000 as Weight) - .saturating_add((110_892_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (0 as Weight) - .saturating_add((8_016_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (0 as Weight) - .saturating_add((50_981_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) - } } // For backwards compatibility and tests @@ -265,49 +213,4 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(8 as Weight)) .saturating_add(RocksDbWeight::get().writes(4 as Weight)) } - fn send_messages_of_various_lengths(i: u32) -> Weight { - (0 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) - } - fn receive_multiple_messages_proof(i: u32) -> Weight { - (56_209_000 as Weight) - .saturating_add((109_502_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_extra_nodes(i: u32) -> Weight { - (0 as Weight) - .saturating_add((5_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_message_proofs_with_large_leaf(i: u32) -> Weight { - (50_281_000 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_multiple_messages_proof_with_outbound_lane_state(i: u32) -> Weight { - (70_297_000 as Weight) - .saturating_add((110_892_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_single_relayer(i: u32) -> Weight { - (0 as Weight) - .saturating_add((8_016_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(i as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_delivery_proof_for_multiple_messages_by_multiple_relayers(i: u32) -> Weight { - (0 as Weight) - .saturating_add((50_981_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(i as Weight))) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(i as Weight))) - } } From 9b8502701b3ab8e38697aff7eda1d9aef1e8d7c1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 12 Jan 2022 10:19:46 +0300 Subject: [PATCH 0630/1210] do not start spec_version guard when version mode is set to auto (#1278) --- relays/bin-substrate/Cargo.toml | 1 + .../src/chains/kusama_headers_to_polkadot.rs | 29 +++++------ .../src/chains/polkadot_headers_to_kusama.rs | 29 +++++------ .../src/chains/rococo_headers_to_wococo.rs | 29 +++++------ .../src/chains/wococo_headers_to_rococo.rs | 29 +++++------ relays/bin-substrate/src/cli/mod.rs | 10 ++++ relays/bin-substrate/src/cli/relay_headers.rs | 7 ++- .../src/cli/relay_headers_and_messages.rs | 8 +++- relays/client-substrate/src/guard.rs | 15 ++++++ .../src/finality_guards.rs | 48 +++++++++++++++++++ .../src/finality_pipeline.rs | 8 +++- relays/lib-substrate-relay/src/lib.rs | 1 + 12 files changed, 153 insertions(+), 61 deletions(-) create mode 100644 relays/lib-substrate-relay/src/finality_guards.rs diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 843340817e403..86c1cedf375dd 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" async-std = "1.9.0" +async-trait = "0.1.42" codec = { package = "parity-scale-codec", version = "2.2.0" } futures = "0.3.12" hex = "0.4" diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index 13d9f12141f6d..f3a2d553045f7 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -16,7 +16,8 @@ //! Kusama-to-Polkadot headers sync entrypoint. -use sp_core::Pair; +use async_trait::async_trait; +use relay_polkadot_client::Polkadot; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat @@ -36,26 +37,26 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof ); +#[async_trait] impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { type SourceChain = relay_kusama_client::Kusama; - type TargetChain = relay_polkadot_client::Polkadot; + type TargetChain = Polkadot; type SubmitFinalityProofCallBuilder = KusamaFinalityToPolkadotCallBuilder; - type TransactionSignScheme = relay_polkadot_client::Polkadot; + type TransactionSignScheme = Polkadot; - fn start_relay_guards( - target_client: &relay_substrate_client::Client, + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, transaction_params: &TransactionParams, - ) { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - bp_polkadot::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - target_client.clone(), - transaction_params.signer.public().into(), + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); + ) + .await } } diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index 5f65d658b90cb..27bcb2457896d 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -16,7 +16,8 @@ //! Polkadot-to-Kusama headers sync entrypoint. -use sp_core::Pair; +use async_trait::async_trait; +use relay_kusama_client::Kusama; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat @@ -36,26 +37,26 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof ); +#[async_trait] impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { type SourceChain = relay_polkadot_client::Polkadot; - type TargetChain = relay_kusama_client::Kusama; + type TargetChain = Kusama; type SubmitFinalityProofCallBuilder = PolkadotFinalityToKusamaCallBuilder; - type TransactionSignScheme = relay_kusama_client::Kusama; + type TransactionSignScheme = Kusama; - fn start_relay_guards( - target_client: &relay_substrate_client::Client, + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, transaction_params: &TransactionParams, - ) { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - bp_kusama::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - target_client.clone(), - transaction_params.signer.public().into(), + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); + ) + .await } } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index d0f1896db89f9..bb66a7422d370 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -18,7 +18,8 @@ use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; -use sp_core::Pair; +use async_trait::async_trait; +use relay_wococo_client::Wococo; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Description of Rococo -> Wococo finalized headers bridge. @@ -31,25 +32,25 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof ); +#[async_trait] impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { type SourceChain = relay_rococo_client::Rococo; - type TargetChain = relay_wococo_client::Wococo; + type TargetChain = Wococo; type SubmitFinalityProofCallBuilder = RococoFinalityToWococoCallBuilder; - type TransactionSignScheme = relay_wococo_client::Wococo; + type TransactionSignScheme = Wococo; - fn start_relay_guards( - target_client: &relay_substrate_client::Client, + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, transaction_params: &TransactionParams, - ) { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - bp_wococo::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - target_client.clone(), - transaction_params.signer.public().into(), + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); + ) + .await } } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index 2d8795fc83ddd..a7bff5951882e 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -16,7 +16,8 @@ //! Wococo-to-Rococo headers sync entrypoint. -use sp_core::Pair; +use async_trait::async_trait; +use relay_rococo_client::Rococo; use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat @@ -36,26 +37,26 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof ); +#[async_trait] impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { type SourceChain = relay_wococo_client::Wococo; - type TargetChain = relay_rococo_client::Rococo; + type TargetChain = Rococo; type SubmitFinalityProofCallBuilder = WococoFinalityToRococoCallBuilder; - type TransactionSignScheme = relay_rococo_client::Rococo; + type TransactionSignScheme = Rococo; - fn start_relay_guards( - target_client: &relay_substrate_client::Client, + async fn start_relay_guards( + target_client: &relay_substrate_client::Client, transaction_params: &TransactionParams, - ) { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - bp_rococo::VERSION.spec_version, - ); - relay_substrate_client::guard::abort_when_account_balance_decreased( - target_client.clone(), - transaction_params.signer.public().into(), + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + substrate_relay_helper::finality_guards::start::( + target_client, + transaction_params, + enable_version_guard, MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); + ) + .await } } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 2a087e59b62a6..1ff46fdbb8462 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -528,6 +528,16 @@ macro_rules! declare_chain_options { } impl [<$chain ConnectionParams>] { + /// Returns `true` if version guard can be started. + /// + /// There's no reason to run version guard when version mode is set to `Auto`. It can + /// lead to relay shutdown when chain is upgraded, even though we have explicitly + /// said that we don't want to shutdown. + #[allow(dead_code)] + pub fn can_start_version_guard(&self) -> bool { + self.[<$chain_prefix _runtime_version>].[<$chain_prefix _version_mode>] != RuntimeVersionType::Auto + } + /// Convert connection params into Substrate client. pub async fn to_client( &self, diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 4b17a56819c80..e3c7fe76d3c37 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -157,7 +157,12 @@ impl RelayHeaders { signer: target_sign, mortality: target_transactions_mortality, }; - Finality::start_relay_guards(&target_client, &target_transactions_params); + Finality::start_relay_guards( + &target_client, + &target_transactions_params, + self.target.can_start_version_guard(), + ) + .await?; substrate_relay_helper::finality_pipeline::run::( source_client, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 3804513acdb7a..212eb9c6a0c6f 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -512,11 +512,15 @@ impl RelayHeadersAndMessages { LeftToRightFinality::start_relay_guards( &right_client, &left_to_right_transaction_params, - ); + params.right.can_start_version_guard(), + ) + .await?; RightToLeftFinality::start_relay_guards( &left_client, &right_to_left_transaction_params, - ); + params.left.can_start_version_guard(), + ) + .await?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( left_client.clone(), right_client.clone(), diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index c31482eec3967..359a3f69d8a36 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -64,6 +64,13 @@ pub fn abort_on_spec_version_change( expected_spec_version: u32, ) { async_std::task::spawn(async move { + log::info!( + target: "bridge-guard", + "Starting spec_version guard for {}. Expected spec_version: {}", + C::NAME, + expected_spec_version, + ); + loop { let actual_spec_version = env.runtime_version().await; match actual_spec_version { @@ -103,6 +110,14 @@ pub fn abort_when_account_balance_decreased( const DAY: Duration = Duration::from_secs(60 * 60 * 24); async_std::task::spawn(async move { + log::info!( + target: "bridge-guard", + "Starting balance guard for {}/{:?}. Maximal decrease: {:?}", + C::NAME, + account_id, + maximal_decrease, + ); + let mut balances = VecDeque::new(); loop { diff --git a/relays/lib-substrate-relay/src/finality_guards.rs b/relays/lib-substrate-relay/src/finality_guards.rs new file mode 100644 index 0000000000000..a3e69afe1b1d9 --- /dev/null +++ b/relays/lib-substrate-relay/src/finality_guards.rs @@ -0,0 +1,48 @@ +// 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 . + +//! Tools for starting guards of finality relays. + +use crate::TransactionParams; + +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, ChainWithBalances, TransactionSignScheme, +}; +use sp_core::Pair; + +/// Start finality relay guards. +pub async fn start>( + target_client: &relay_substrate_client::Client, + transaction_params: &TransactionParams, + enable_version_guard: bool, + maximal_balance_decrease_per_day: C::Balance, +) -> relay_substrate_client::Result<()> +where + AccountIdOf: From< as Pair>::Public>, +{ + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.0, + ); + } + relay_substrate_client::guard::abort_when_account_balance_decreased( + target_client.clone(), + transaction_params.signer.public().into(), + maximal_balance_decrease_per_day, + ); + Ok(()) +} diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 87e50be03932c..07a1279ef4603 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -22,6 +22,7 @@ use crate::{ TransactionParams, }; +use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; @@ -40,6 +41,7 @@ use std::{fmt::Debug, marker::PhantomData}; pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; /// Substrate -> Substrate finality proofs synchronization pipeline. +#[async_trait] pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. type SourceChain: Chain; @@ -52,10 +54,12 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { type TransactionSignScheme: TransactionSignScheme; /// Add relay guards if required. - fn start_relay_guards( + async fn start_relay_guards( _target_client: &Client, _transaction_params: &TransactionParams>, - ) { + _enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + Ok(()) } } diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index c27aa7b708fd5..27d91147c2ddc 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -22,6 +22,7 @@ use std::time::Duration; pub mod conversion_rate_update; pub mod error; +pub mod finality_guards; pub mod finality_pipeline; pub mod finality_source; pub mod finality_target; From 788c90398b94f364e2fb4fed918531621b8db8a8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 Jan 2022 15:05:24 +0300 Subject: [PATCH 0631/1210] move "common" code of messages pallet benchmarks helpers to the common library (#1281) --- bin/millau/runtime/src/lib.rs | 111 +----- bin/runtime-common/Cargo.toml | 6 + bin/runtime-common/src/messages.rs | 2 +- .../src/messages_benchmarking.rs | 356 ++++++++++++------ modules/messages/src/benchmarking.rs | 4 + 5 files changed, 259 insertions(+), 220 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4d6ecd8ba3895..5734517f1578d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -828,7 +828,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - use bp_runtime::messages::DispatchFeePayment; + use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof, prepare_message_proof, prepare_outbound_message}; use bridge_runtime_common::messages; use pallet_bridge_messages::benchmarking::{ Pallet as MessagesBench, @@ -836,9 +836,8 @@ impl_runtime_apis! { MessageDeliveryProofParams, MessageParams, MessageProofParams, - ProofSize as MessagesProofSize, }; - use rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; + use rialto_messages::WithRialtoMessageBridge; impl MessagesConfig for Runtime { fn maximal_message_size() -> u32 { @@ -863,120 +862,24 @@ impl_runtime_apis! { fn prepare_outbound_message( params: MessageParams, ) -> (rialto_messages::ToRialtoMessagePayload, Balance) { - let message_payload = vec![0; params.size as usize]; - let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount( - params.sender_account, - ); - - let message = ToRialtoMessagePayload { - spec_version: 0, - weight: params.size as _, - origin: dispatch_origin, - call: message_payload, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }; - (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) + prepare_outbound_message::(params) } fn prepare_message_proof( params: MessageProofParams, ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { - use bp_messages::{MessageKey, storage_keys}; - use bridge_runtime_common::{ - messages::MessageBridge, - messages_benchmarking::{ed25519_sign, prepare_message_proof}, - }; - use codec::Encode; - use frame_support::weights::GetDispatchInfo; - use rialto_messages::WithRialtoMessageBridge; - use sp_runtime::traits::{Header, IdentifyAccount}; - - let remark = match params.size { - MessagesProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }; - let call = Call::System(SystemCall::remark { remark }); - let call_weight = call.get_dispatch_info().weight; - - let rialto_account_id: bp_rialto::AccountId = Default::default(); - let (millau_raw_public, millau_raw_signature) = ed25519_sign( - &call, - &rialto_account_id, - VERSION.spec_version, - bp_runtime::RIALTO_CHAIN_ID, - bp_runtime::MILLAU_CHAIN_ID, - ); - let millau_public = MultiSigner::Ed25519(sp_core::ed25519::Public::from_raw(millau_raw_public)); - let millau_signature = MultiSignature::Ed25519(sp_core::ed25519::Signature::from_raw( - millau_raw_signature, - )); - - if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { - Self::endow_account(&millau_public.clone().into_account()); - } - - let make_rialto_message_key = |message_key: MessageKey| storage_keys::message_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &message_key.lane_id, message_key.nonce, - ).0; - let make_rialto_outbound_lane_data_key = |lane_id| storage_keys::outbound_lane_data_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &lane_id, - ).0; - - let make_rialto_header = |state_root| bp_rialto::Header::new( - 0, - Default::default(), - state_root, - Default::default(), - Default::default(), - ); - - let dispatch_fee_payment = params.dispatch_fee_payment.clone(); - prepare_message_proof::( + prepare_message_proof::( params, - make_rialto_message_key, - make_rialto_outbound_lane_data_key, - make_rialto_header, - call_weight, - bp_message_dispatch::MessagePayload { - spec_version: VERSION.spec_version, - weight: call_weight, - origin: bp_message_dispatch::CallOrigin::< - bp_rialto::AccountId, - MultiSigner, - Signature, - >::TargetAccount( - rialto_account_id, - millau_public, - millau_signature, - ), - dispatch_fee_payment, - call: call.encode(), - }.encode(), + &VERSION, + Balance::MAX / 100, ) } fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> rialto_messages::ToRialtoMessagesDeliveryProof { - use bridge_runtime_common::messages_benchmarking::prepare_message_delivery_proof; - use rialto_messages::WithRialtoMessageBridge; - use sp_runtime::traits::Header; - - prepare_message_delivery_proof::( + prepare_message_delivery_proof::( params, - |lane_id| bp_messages::storage_keys::inbound_lane_data_key( - ::BRIDGED_MESSAGES_PALLET_NAME, - &lane_id, - ).0, - |state_root| bp_rialto::Header::new( - 0, - Default::default(), - state_root, - Default::default(), - Default::default(), - ), ) } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 0ae642ba55898..ed3bb32d17060 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -25,12 +25,15 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-transaction-payment = { 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-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, optional = true } 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 } +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } [features] default = ["std"] @@ -54,7 +57,10 @@ std = [ ] runtime-benchmarks = [ "ed25519-dalek/u64_backend", + "frame-system", + "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "sp-state-machine", + "sp-version", ] diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index dd03379ce5d5d..47fb1c48f4384 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -176,7 +176,7 @@ pub type BalanceOf = ::Balance; pub type CallOf = ::Call; /// Raw storage proof type (just raw trie nodes). -type RawStorageProof = Vec>; +pub type RawStorageProof = Vec>; /// Compute fee of transaction at runtime where regular transaction payment pallet is being used. /// diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 217560e114344..1b14ee30aee82 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -20,162 +20,164 @@ #![cfg(feature = "runtime-benchmarks")] use crate::messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - AccountIdOf, BalanceOf, BridgedChain, HashOf, MessageBridge, ThisChain, + source::{FromBridgedChainMessagesDeliveryProof, FromThisChainMessagePayload}, + target::FromBridgedChainMessagesProof, + AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, RawStorageProof, + SignatureOf, SignerOf, ThisChain, }; -use bp_messages::{LaneId, MessageData, MessageKey, MessagePayload}; -use bp_runtime::ChainId; +use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; +use bp_runtime::{messages::DispatchFeePayment, ChainId}; use codec::Encode; use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; -use frame_support::weights::Weight; +use frame_support::{ + traits::Currency, + weights::{GetDispatchInfo, Weight}, +}; use pallet_bridge_messages::benchmarking::{ - MessageDeliveryProofParams, MessageProofParams, ProofSize, + MessageDeliveryProofParams, MessageParams, MessageProofParams, ProofSize, }; use sp_core::Hasher; -use sp_runtime::traits::Header; -use sp_std::prelude::*; +use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; +use sp_std::{fmt::Debug, prelude::*}; use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut}; +use sp_version::RuntimeVersion; -/// Generate ed25519 signature to be used in -/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. -/// -/// Returns public key of the signer and the signature itself. -pub fn ed25519_sign( - target_call: &impl Encode, - source_account_id: &impl Encode, - target_spec_version: u32, - source_chain_id: ChainId, - target_chain_id: ChainId, -) -> ([u8; 32], [u8; 64]) { - // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) - let target_secret = SecretKey::from_bytes(&[ - 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, - 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, - ]) - .expect("harcoded key is valid"); - let target_public: PublicKey = (&target_secret).into(); - - let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; - target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); - target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); - let target_pair = - ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); - - let signature_message = pallet_bridge_dispatch::account_ownership_digest( - target_call, - source_account_id, - target_spec_version, - source_chain_id, - target_chain_id, - ); - let target_origin_signature = target_pair - .try_sign(&signature_message) - .expect("Ed25519 try_sign should not fail in benchmarks"); +/// Prepare outbound message for the `send_message` call. +pub fn prepare_outbound_message( + params: MessageParams>>, +) -> (FromThisChainMessagePayload, BalanceOf>) +where + B: MessageBridge, + BalanceOf>: From, +{ + let message_payload = vec![0; params.size as usize]; + let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount(params.sender_account); - (target_public.to_bytes(), target_origin_signature.to_bytes()) + let message = FromThisChainMessagePayload:: { + spec_version: 0, + weight: params.size as _, + origin: dispatch_origin, + call: message_payload, + dispatch_fee_payment: DispatchFeePayment::AtSourceChain, + }; + (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) } /// Prepare proof of messages for the `receive_messages_proof` call. -pub fn prepare_message_proof( +/// +/// In addition to returning valid messages proof, environment is prepared to verify this message +/// proof. +pub fn prepare_message_proof( params: MessageProofParams, - make_bridged_message_storage_key: MM, - make_bridged_outbound_lane_data_key: ML, - make_bridged_header: MH, - message_dispatch_weight: Weight, - message_payload: MessagePayload, + version: &RuntimeVersion, + endow_amount: BalanceOf>, ) -> (FromBridgedChainMessagesProof>>, Weight) where + R: frame_system::Config>> + + pallet_balances::Config>> + + pallet_bridge_grandpa::Config, + R::BridgedChain: bp_runtime::Chain

, B: MessageBridge, - H: Hasher, - R: pallet_bridge_grandpa::Config, + BI: 'static, FI: 'static, - ::Hash: Into>>, - MM: Fn(MessageKey) -> Vec, - ML: Fn(LaneId) -> Vec, - MH: Fn(H::Out) -> ::Header, + BH: Header>>, + BHH: Hasher>>, + AccountIdOf>: From<[u8; 32]>, + BalanceOf>: Debug + MaybeSerializeDeserialize, + CallOf>: From> + GetDispatchInfo, + HashOf>: Copy + Default, + SignatureOf>: From, + SignerOf>: Clone + + From + + IdentifyAccount>>, { - // prepare Bridged chain storage with messages and (optionally) outbound lane state - let message_count = - params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1; - let mut storage_keys = Vec::with_capacity(message_count as usize + 1); - let mut root = Default::default(); - let mut mdb = MemoryDB::default(); - { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + // we'll be dispatching the same call at This chain + let remark = match params.size { + ProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }; + let call: CallOf> = frame_system::Call::remark { remark }.into(); + let call_weight = call.get_dispatch_info().weight; - // insert messages - for nonce in params.message_nonces.clone() { - let message_key = MessageKey { lane_id: params.lane, nonce }; - let message_data = MessageData { - fee: BalanceOf::>::from(0), - payload: message_payload.clone(), - }; - let storage_key = make_bridged_message_storage_key(message_key); - trie.insert(&storage_key, &message_data.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - storage_keys.push(storage_key); - } + // message payload needs to be signed, because we use `TargetAccount` call origin + // (which is 'heaviest' to verify) + let bridged_account_id: AccountIdOf> = [0u8; 32].into(); + let (this_raw_public, this_raw_signature) = ed25519_sign( + &call, + &bridged_account_id, + version.spec_version, + B::BRIDGED_CHAIN_ID, + B::THIS_CHAIN_ID, + ); + let this_public: SignerOf> = + sp_core::ed25519::Public::from_raw(this_raw_public).into(); + let this_signature: SignatureOf> = + sp_core::ed25519::Signature::from_raw(this_raw_signature).into(); - // insert outbound lane state - if let Some(outbound_lane_data) = params.outbound_lane_data { - let storage_key = make_bridged_outbound_lane_data_key(params.lane); - trie.insert(&storage_key, &outbound_lane_data.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - storage_keys.push(storage_key); - } + // if dispatch fee is paid at this chain, endow relayer account + if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { + pallet_balances::Pallet::::make_free_balance_be( + &this_public.clone().into_account(), + endow_amount, + ); } - root = grow_trie(root, &mut mdb, params.size); - // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); - let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + // prepare message payload that is stored in the Bridged chain storage + let message_payload = bp_message_dispatch::MessagePayload { + spec_version: version.spec_version, + weight: call_weight, + origin: bp_message_dispatch::CallOrigin::< + AccountIdOf>, + SignerOf>, + SignatureOf>, + >::TargetAccount(bridged_account_id, this_public, this_signature), + dispatch_fee_payment: params.dispatch_fee_payment.clone(), + call: call.encode(), + } + .encode(); - // prepare Bridged chain header and insert it into the Substrate pallet - let bridged_header = make_bridged_header(root); - let bridged_header_hash = bridged_header.hash(); - pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + // finally - prepare storage proof and update environment + let (state_root, storage_proof) = + prepare_messages_storage_proof::(¶ms, message_payload); + let bridged_header_hash = insert_bridged_chain_header::(state_root); ( FromBridgedChainMessagesProof { - bridged_header_hash: bridged_header_hash.into(), + bridged_header_hash, storage_proof, lane: params.lane, nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - message_dispatch_weight - .checked_mul(message_count) + call_weight + .checked_mul( + params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1, + ) .expect("too many messages requested by benchmark"), ) } /// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. -pub fn prepare_message_delivery_proof( +pub fn prepare_message_delivery_proof( params: MessageDeliveryProofParams>>, - make_bridged_inbound_lane_data_key: ML, - make_bridged_header: MH, ) -> FromBridgedChainMessagesDeliveryProof>> where - B: MessageBridge, - H: Hasher, R: pallet_bridge_grandpa::Config, + R::BridgedChain: bp_runtime::Chain
, FI: 'static, - ::Hash: Into>>, - ML: Fn(LaneId) -> Vec, - MH: Fn(H::Out) -> ::Header, + B: MessageBridge, + BH: Header>>, + BHH: Hasher>>, + HashOf>: Copy + Default, { // prepare Bridged chain storage with inbound lane state - let storage_key = make_bridged_inbound_lane_data_key(params.lane); + let storage_key = + storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, ¶ms.lane).0; let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); @@ -183,16 +185,14 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) .map_err(|_| "record_all_keys has failed") .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - // prepare Bridged chain header and insert it into the Substrate pallet - let bridged_header = make_bridged_header(root); - let bridged_header_hash = bridged_header.hash(); - pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + // finally insert header with given state root to our storage + let bridged_header_hash = insert_bridged_chain_header::(root); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), @@ -201,6 +201,132 @@ where } } +/// Prepare storage proof of given messages. +/// +/// Returns state trie root and nodes with prepared messages. +fn prepare_messages_storage_proof( + params: &MessageProofParams, + message_payload: MessagePayload, +) -> (HashOf>, RawStorageProof) +where + B: MessageBridge, + BHH: Hasher>>, + HashOf>: Copy + Default, +{ + // prepare Bridged chain storage with messages and (optionally) outbound lane state + let message_count = + params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1; + let mut storage_keys = Vec::with_capacity(message_count as usize + 1); + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + + // insert messages + for nonce in params.message_nonces.clone() { + let message_key = MessageKey { lane_id: params.lane, nonce }; + let message_data = MessageData { + fee: BalanceOf::>::from(0), + payload: message_payload.clone(), + }; + let storage_key = storage_keys::message_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &message_key.lane_id, + message_key.nonce, + ) + .0; + trie.insert(&storage_key, &message_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + + // insert outbound lane state + if let Some(ref outbound_lane_data) = params.outbound_lane_data { + let storage_key = + storage_keys::outbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, ¶ms.lane) + .0; + trie.insert(&storage_key, &outbound_lane_data.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + } + root = grow_trie(root, &mut mdb, params.size); + + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); + let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + (root, storage_proof) +} + +/// Insert Bridged chain header with given state root into storage of GRANDPA pallet at This chain. +fn insert_bridged_chain_header( + state_root: HashOf>, +) -> HashOf> +where + R: pallet_bridge_grandpa::Config, + R::BridgedChain: bp_runtime::Chain
, + FI: 'static, + B: MessageBridge, + BH: Header>>, + HashOf>: Default, +{ + let bridged_header = BH::new( + Zero::zero(), + Default::default(), + state_root, + Default::default(), + Default::default(), + ); + let bridged_header_hash = bridged_header.hash(); + pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + bridged_header_hash +} + +/// Generate ed25519 signature to be used in +/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. +/// +/// Returns public key of the signer and the signature itself. +fn ed25519_sign( + target_call: &impl Encode, + source_account_id: &impl Encode, + target_spec_version: u32, + source_chain_id: ChainId, + target_chain_id: ChainId, +) -> ([u8; 32], [u8; 64]) { + // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) + let target_secret = SecretKey::from_bytes(&[ + 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, + 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, + ]) + .expect("harcoded key is valid"); + let target_public: PublicKey = (&target_secret).into(); + + let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; + target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); + target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); + let target_pair = + ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); + + let signature_message = pallet_bridge_dispatch::account_ownership_digest( + target_call, + source_account_id, + target_spec_version, + source_chain_id, + target_chain_id, + ); + let target_origin_signature = target_pair + .try_sign(&signature_message) + .expect("Ed25519 try_sign should not fail in benchmarks"); + + (target_public.to_bytes(), target_origin_signature.to_bytes()) +} + /// Populate trie with dummy keys+values until trie has at least given size. fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: ProofSize) -> H::Out { let (iterations, leaf_size, minimal_trie_size) = match trie_size { diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index f396365699f4b..392e28176b823 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -41,6 +41,7 @@ const SEED: u32 = 0; pub struct Pallet, I: 'static>(crate::Pallet); /// Proof size requirements. +#[derive(Clone, Copy, Debug)] pub enum ProofSize { /// The proof is expected to be minimal. If value size may be changed, then it is expected to /// have given size. @@ -54,6 +55,7 @@ pub enum ProofSize { } /// Benchmark-specific message parameters. +#[derive(Debug)] pub struct MessageParams { /// Size of the message payload. pub size: u32, @@ -62,6 +64,7 @@ pub struct MessageParams { } /// Benchmark-specific message proof parameters. +#[derive(Debug)] pub struct MessageProofParams { /// Id of the lane. pub lane: LaneId, @@ -76,6 +79,7 @@ pub struct MessageProofParams { } /// Benchmark-specific message delivery proof parameters. +#[derive(Debug)] pub struct MessageDeliveryProofParams { /// Id of the lane. pub lane: LaneId, From bd0469e878caa5a0bc3fd921f12650d08c8ebbd7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 Jan 2022 15:08:21 +0300 Subject: [PATCH 0632/1210] replace latest_confirmed_nonce runtime APIs with direct storage reads (#1282) --- bin/millau/runtime/src/lib.rs | 4 -- bin/rialto/runtime/src/lib.rs | 4 -- modules/messages/src/benchmarking.rs | 11 ++-- modules/messages/src/lib.rs | 5 -- primitives/chain-kusama/src/lib.rs | 5 -- primitives/chain-millau/src/lib.rs | 5 -- primitives/chain-polkadot/src/lib.rs | 5 -- primitives/chain-rialto/src/lib.rs | 5 -- primitives/chain-rococo/src/lib.rs | 5 -- primitives/chain-westend/Cargo.toml | 2 - primitives/chain-westend/src/lib.rs | 48 ----------------- primitives/chain-wococo/src/lib.rs | 5 -- relays/client-kusama/src/lib.rs | 2 - relays/client-millau/src/lib.rs | 2 - relays/client-polkadot/src/lib.rs | 2 - relays/client-rialto/src/lib.rs | 2 - relays/client-rococo/src/lib.rs | 2 - relays/client-substrate/src/chain.rs | 3 -- relays/client-wococo/src/lib.rs | 2 - .../src/messages_source.rs | 50 +++++++++--------- .../src/messages_target.rs | 51 ++++++++++--------- 21 files changed, 57 insertions(+), 163 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 5734517f1578d..33839614e75cf 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -776,10 +776,6 @@ impl_runtime_apis! { } impl bp_rialto::FromRialtoInboundLaneApi for Runtime { - fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeRialtoMessages::inbound_latest_confirmed_nonce(lane) - } - fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index a68de93069519..5f940bb58e07f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -899,10 +899,6 @@ impl_runtime_apis! { } impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn latest_confirmed_nonce(lane: bp_messages::LaneId) -> bp_messages::MessageNonce { - BridgeMillauMessages::inbound_latest_confirmed_nonce(lane) - } - fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { BridgeMillauMessages::inbound_unrewarded_relayers_state(lane) } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 392e28176b823..288ef4b2e8187 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -367,14 +367,9 @@ benchmarks_instance_pallet! { }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { - assert_eq!( - crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), - 21, - ); - assert_eq!( - crate::Pallet::::inbound_latest_confirmed_nonce(T::bench_lane_id()), - 20, - ); + let lane_state = crate::InboundLanes::::get(&T::bench_lane_id()); + assert_eq!(lane_state.last_delivered_nonce(), 21); + assert_eq!(lane_state.last_confirmed_nonce, 20); assert!(T::is_message_dispatched(21)); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 09298013a5b6c..53694e6ee2368 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -764,11 +764,6 @@ pub mod pallet { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } - /// Get nonce of the latest confirmed message at given inbound lane. - pub fn inbound_latest_confirmed_nonce(lane: LaneId) -> MessageNonce { - InboundLanes::::get(&lane).last_confirmed_nonce - } - /// Get state of unrewarded relayers set. pub fn inbound_unrewarded_relayers_state( lane: bp_messages::LaneId, diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 362e46d1eddf7..0f25ac710de65 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -100,9 +100,6 @@ pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; -/// Name of the `FromKusamaInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromKusamaInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromKusamaInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = "FromKusamaInboundLaneApi_unrewarded_relayers_state"; @@ -152,8 +149,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the /// Kusama runtime itself. pub trait FromKusamaInboundLaneApi { - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 6a8bbd3e336fc..2e671e901c368 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -278,9 +278,6 @@ pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; -/// Name of the `FromMillauInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromMillauInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = "FromMillauInboundLaneApi_unrewarded_relayers_state"; @@ -330,8 +327,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Millau chain, not the /// Millau runtime itself. pub trait FromMillauInboundLaneApi { - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 16c9a76bfd9e2..19cf1a797062d 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -100,9 +100,6 @@ pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; -/// Name of the `FromPolkadotInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromPolkadotInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromPolkadotInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_POLKADOT_UNREWARDED_RELAYERS_STATE: &str = "FromPolkadotInboundLaneApi_unrewarded_relayers_state"; @@ -152,8 +149,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the /// Polkadot runtime itself. pub trait FromPolkadotInboundLaneApi { - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index b995410a6565b..c6cb1bceb87f8 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -250,9 +250,6 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; -/// Name of the `FromRialtoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromRialtoInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = "FromRialtoInboundLaneApi_unrewarded_relayers_state"; @@ -302,8 +299,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the /// Rialto runtime itself. pub trait FromRialtoInboundLaneApi { - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 222279e391dcf..d485e916cf825 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -89,9 +89,6 @@ pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; -/// Name of the `FromRococoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromRococoInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromRococoInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromRococoInboundLaneApi_unrewarded_relayers_state"; @@ -153,8 +150,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the /// Rococo runtime itself. pub trait FromRococoInboundLaneApi { - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 4fd1652744ed6..cc2e912cea57f 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -14,7 +14,6 @@ smallvec = "1.7" # Bridge Dependencies bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -30,7 +29,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master default = ["std"] std = [ "bp-header-chain/std", - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index fe804f93f7d75..68bc22c7cdcb6 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -20,7 +20,6 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -110,51 +109,4 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); } - - /// Outbound message lane API for messages that are sent to Westend chain. - /// - /// This API is implemented by runtimes that are sending messages to Westend chain, not the - /// Westend runtime itself. - pub trait ToWestendOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Westend from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - /// Returns nonce of the latest message, received by bridged chain. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Returns nonce of the latest message, generated by given lane. - fn latest_generated_nonce(lane: LaneId) -> MessageNonce; - } - - /// Inbound message lane API for messages sent by Westend chain. - /// - /// This API is implemented by runtimes that are receiving messages from Westend chain, not the - /// Westend runtime itself. - pub trait FromWestendInboundLaneApi { - /// Returns nonce of the latest message, received by given lane. - fn latest_received_nonce(lane: LaneId) -> MessageNonce; - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 90eed6e33f727..4f715c3994aae 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -54,9 +54,6 @@ pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; -/// Name of the `FromWococoInboundLaneApi::latest_onfirmed_nonce` runtime method. -pub const FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD: &str = - "FromWococoInboundLaneApi_latest_confirmed_nonce"; /// Name of the `FromWococoInboundLaneApi::unrewarded_relayers_state` runtime method. pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = "FromWococoInboundLaneApi_unrewarded_relayers_state"; @@ -106,8 +103,6 @@ sp_api::decl_runtime_apis! { /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the /// Wococo runtime itself. pub trait FromWococoInboundLaneApi { - /// Nonce of the latest message that has been confirmed to the bridged chain. - fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce; /// State of the unrewarded relayers set at given lane. fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 55e8169941fdd..982bf88d82a96 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -79,8 +79,6 @@ impl ChainWithMessages for Kusama { bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 908ffc929c5d8..3c159907f7d00 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -63,8 +63,6 @@ impl ChainWithMessages for Millau { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_millau::FROM_MILLAU_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index fbe1ffae08805..6671b8c7228fc 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -80,8 +80,6 @@ impl ChainWithMessages for Polkadot { bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 61065b352fcbe..4062a36b0d747 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Rialto { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rialto::FROM_RIALTO_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 7319b3f2eeb40..56ca95606a8e7 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -82,8 +82,6 @@ impl ChainWithMessages for Rococo { bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index d11e732d317e6..75f2fdeb3e906 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -91,9 +91,6 @@ pub trait ChainWithMessages: Chain { /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the `FromInboundLaneApi::latest_confirmed_nonce` runtime method. - /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str; /// Name of the `FromInboundLaneApi::unrewarded_relayers_state` runtime /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index a6f6d734dd396..fd45fc0dc186f 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -82,8 +82,6 @@ impl ChainWithMessages for Wococo { bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_LATEST_CONFIRMED_NONCE_METHOD; const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 87296457f8a2b..80da24910222c 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -83,6 +83,22 @@ impl SubstrateMessagesSource

{ target_to_source_headers_relay, } } + + /// Read outbound lane state from the on-chain storage at given block. + async fn outbound_lane_data( + &self, + id: SourceHeaderIdOf>, + ) -> Result, SubstrateError> { + self.client + .storage_value( + outbound_lane_data_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), + Some(id.1), + ) + .await + } } impl Clone for SubstrateMessagesSource

{ @@ -129,19 +145,12 @@ where &self, id: SourceHeaderIdOf>, ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { - let outbound_lane_data: Option = self - .client - .storage_value( - outbound_lane_data_key( - P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, - &self.lane_id, - ), - Some(id.1), - ) - .await?; // lane data missing from the storage is fine until first message is sent - let latest_generated_nonce = - outbound_lane_data.map(|data| data.latest_generated_nonce).unwrap_or(0); + let latest_generated_nonce = self + .outbound_lane_data(id) + .await? + .map(|data| data.latest_generated_nonce) + .unwrap_or(0); Ok((id, latest_generated_nonce)) } @@ -149,19 +158,12 @@ where &self, id: SourceHeaderIdOf>, ) -> Result<(SourceHeaderIdOf>, MessageNonce), SubstrateError> { - let outbound_lane_data: Option = self - .client - .storage_value( - outbound_lane_data_key( - P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, - &self.lane_id, - ), - Some(id.1), - ) - .await?; // lane data missing from the storage is fine until first message is sent - let latest_received_nonce = - outbound_lane_data.map(|data| data.latest_received_nonce).unwrap_or(0); + let latest_received_nonce = self + .outbound_lane_data(id) + .await? + .map(|data| data.latest_received_nonce) + .unwrap_or(0); Ok((id, latest_received_nonce)) } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index cdd25c64e58c5..26d376cd5efed 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -84,6 +84,22 @@ impl SubstrateMessagesTarget

{ source_to_target_headers_relay, } } + + /// Read inbound lane state from the on-chain storage at given block. + async fn inbound_lane_data( + &self, + id: TargetHeaderIdOf>, + ) -> Result>>, SubstrateError> { + self.client + .storage_value( + inbound_lane_data_key( + P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + ), + Some(id.1), + ) + .await + } } impl Clone for SubstrateMessagesTarget

{ @@ -133,19 +149,12 @@ where &self, id: TargetHeaderIdOf>, ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { - let inbound_lane_data: Option>> = self - .client - .storage_value( - inbound_lane_data_key( - P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, - &self.lane_id, - ), - Some(id.1), - ) - .await?; // lane data missing from the storage is fine until first message is received - let latest_received_nonce = - inbound_lane_data.map(|data| data.last_delivered_nonce()).unwrap_or(0); + let latest_received_nonce = self + .inbound_lane_data(id) + .await? + .map(|data| data.last_delivered_nonce()) + .unwrap_or(0); Ok((id, latest_received_nonce)) } @@ -153,17 +162,13 @@ where &self, id: TargetHeaderIdOf>, ) -> Result<(TargetHeaderIdOf>, MessageNonce), SubstrateError> { - let encoded_response = self - .client - .state_call( - P::SourceChain::FROM_CHAIN_LATEST_CONFIRMED_NONCE_METHOD.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let latest_received_nonce: MessageNonce = Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; - Ok((id, latest_received_nonce)) + // lane data missing from the storage is fine until first message is received + let last_confirmed_nonce = self + .inbound_lane_data(id) + .await? + .map(|data| data.last_confirmed_nonce) + .unwrap_or(0); + Ok((id, last_confirmed_nonce)) } async fn unrewarded_relayers_state( From c68b9f73f4e1102fb067debd0fced0b4e6e29cf3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 Jan 2022 16:42:36 +0300 Subject: [PATCH 0633/1210] reuse polkadot-service code (#1273) --- bin/rialto/node/Cargo.toml | 30 +- bin/rialto/node/src/chain_spec.rs | 7 +- bin/rialto/node/src/command.rs | 75 ++- bin/rialto/node/src/main.rs | 4 - bin/rialto/node/src/overseer.rs | 316 ----------- bin/rialto/node/src/parachains_db.rs | 104 ---- bin/rialto/node/src/service.rs | 756 --------------------------- 7 files changed, 56 insertions(+), 1236 deletions(-) delete mode 100644 bin/rialto/node/src/overseer.rs delete mode 100644 bin/rialto/node/src/parachains_db.rs delete mode 100644 bin/rialto/node/src/service.rs diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 2795f2eecaecc..77694e552acbf 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -50,7 +50,6 @@ sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -#sc-finality-grandpa-warp-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -77,37 +76,10 @@ substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate # Polkadot Dependencies -polkadot-client = { git = "https://github.com/paritytech/polkadot", branch = "master" } - -# Polkadot (parachain) Dependencies - -polkadot-approval-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-availability-bitfield-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-availability-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-availability-recovery = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-collator-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-dispute-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-gossip-support = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-network-bridge = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-collation-generation = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-approval-voting = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-av-store = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-backing = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-bitfield-signing = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-candidate-validation = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-chain-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-chain-selection = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-parachains-inherent = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-provisioner = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-runtime-api = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-core-dispute-coordinator = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-network-protocol = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-node-subsystem-util = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-overseer = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-statement-distribution = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 527b5c051d535..7e08e635317bf 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -30,7 +30,8 @@ use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = + sc_service::GenericChainSpec; /// The chain specification option. This is expected to come in from the CLI and /// is little more than one of a number of alternatives which can easily be converted @@ -104,7 +105,7 @@ impl Alternative { None, None, properties, - None, + Default::default(), ), Alternative::LocalTestnet => ChainSpec::from_genesis( "Rialto Local", @@ -128,7 +129,7 @@ impl Alternative { None, None, properties, - None, + Default::default(), ), } } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 7be615a57760c..1d81de2cb0c4d 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -14,13 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - cli::{Cli, Subcommand}, - service::new_partial, -}; +use crate::cli::{Cli, Subcommand}; use rialto_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; -use sc_service::PartialComponents; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -67,6 +63,21 @@ impl SubstrateCli for Cli { } } +// Rialto native executor instance. +pub struct ExecutorDispatch; + +impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + rialto_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + rialto_runtime::native_version() + } +} + /// Parse and run command line arguments pub fn run() -> sc_cli::Result<()> { let cli = Cli::from_args(); @@ -79,7 +90,7 @@ pub fn run() -> sc_cli::Result<()> { if cfg!(feature = "runtime-benchmarks") { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -98,32 +109,32 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, import_queue, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, import_queue, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, _, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, config.database), task_manager)) }) }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, _, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, import_queue, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, _, import_queue, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -134,16 +145,14 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|mut config| { - let PartialComponents { client, task_manager, backend, .. } = - new_partial(&mut config).map_err(service_error)?; + let (client, backend, _, task_manager) = + polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; Ok((cmd.run(client, backend), task_manager)) }) }, Some(Subcommand::Inspect(cmd)) => { let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| { - cmd.run::(config) - }) + runner.sync_run(|config| cmd.run::(config)) }, Some(Subcommand::PvfPrepareWorker(cmd)) => { let mut builder = sc_cli::LoggerBuilder::new(""); @@ -170,15 +179,33 @@ pub fn run() -> sc_cli::Result<()> { // let no_beefy = true; // let telemetry_worker_handler = None; // let is_collator = crate::service::IsCollator::No; - let overseer_gen = crate::overseer::RealOverseerGen; + let overseer_gen = polkadot_service::overseer::RealOverseerGen; runner.run_node_until_exit(|config| async move { match config.role { Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other( "Light client is not supported by this node".into(), ))), - _ => crate::service::build_full(config, overseer_gen) - .map(|full| full.task_manager) - .map_err(service_error), + _ => { + let is_collator = polkadot_service::IsCollator::No; + let grandpa_pause = None; + let enable_beefy = true; + let jaeger_agent = None; + let telemetry_worker_handle = None; + let program_path = None; + + polkadot_service::new_full::( + config, + is_collator, + grandpa_pause, + enable_beefy, + jaeger_agent, + telemetry_worker_handle, + program_path, + overseer_gen, + ) + .map(|full| full.task_manager) + .map_err(service_error) + }, } }) }, @@ -187,6 +214,6 @@ pub fn run() -> sc_cli::Result<()> { // We don't want to change 'service.rs' too much to ease future updates => it'll keep using // its own error enum like original polkadot service does. -fn service_error(err: crate::service::Error) -> sc_cli::Error { +fn service_error(err: polkadot_service::Error) -> sc_cli::Error { sc_cli::Error::Application(Box::new(err)) } diff --git a/bin/rialto/node/src/main.rs b/bin/rialto/node/src/main.rs index 824814224e548..6dea84a309b26 100644 --- a/bin/rialto/node/src/main.rs +++ b/bin/rialto/node/src/main.rs @@ -19,12 +19,8 @@ #![warn(missing_docs)] mod chain_spec; -#[macro_use] -mod service; mod cli; mod command; -mod overseer; -mod parachains_db; /// Run the Rialto Node fn main() -> sc_cli::Result<()> { diff --git a/bin/rialto/node/src/overseer.rs b/bin/rialto/node/src/overseer.rs deleted file mode 100644 index 9a7025e77c9b4..0000000000000 --- a/bin/rialto/node/src/overseer.rs +++ /dev/null @@ -1,316 +0,0 @@ -// 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 . - -//! This is almost 1:1 copy of `node/service/src/overseer.rs` file from Polkadot repository. -//! The only exception is that we don't support db upgrades => no `upgrade.rs` module. - -// this warning comes from `polkadot_overseer::AllSubsystems` type -#![allow(clippy::type_complexity)] - -use crate::service::{AuthorityDiscoveryApi, Error}; -use rialto_runtime::{opaque::Block, Hash}; - -use lru::LruCache; -use polkadot_availability_distribution::IncomingRequestReceivers; -use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; -use polkadot_node_core_av_store::Config as AvailabilityConfig; -use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; -use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; -use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; -use polkadot_node_network_protocol::request_response::{v1 as request_v1, IncomingRequestReceiver}; -use polkadot_overseer::{ - metrics::Metrics as OverseerMetrics, BlockInfo, MetricsTrait, Overseer, OverseerBuilder, - OverseerConnector, OverseerHandle, -}; -use polkadot_primitives::v1::ParachainHost; -use sc_authority_discovery::Service as AuthorityDiscoveryService; -use sc_client_api::AuxStore; -use sc_keystore::LocalKeystore; -use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_consensus_babe::BabeApi; -use sp_core::traits::SpawnNamed; -use std::sync::Arc; -use substrate_prometheus_endpoint::Registry; - -pub use polkadot_approval_distribution::ApprovalDistribution as ApprovalDistributionSubsystem; -pub use polkadot_availability_bitfield_distribution::BitfieldDistribution as BitfieldDistributionSubsystem; -pub use polkadot_availability_distribution::AvailabilityDistributionSubsystem; -pub use polkadot_availability_recovery::AvailabilityRecoverySubsystem; -pub use polkadot_collator_protocol::{CollatorProtocolSubsystem, ProtocolSide}; -pub use polkadot_dispute_distribution::DisputeDistributionSubsystem; -pub use polkadot_gossip_support::GossipSupport as GossipSupportSubsystem; -pub use polkadot_network_bridge::NetworkBridge as NetworkBridgeSubsystem; -pub use polkadot_node_collation_generation::CollationGenerationSubsystem; -pub use polkadot_node_core_approval_voting::ApprovalVotingSubsystem; -pub use polkadot_node_core_av_store::AvailabilityStoreSubsystem; -pub use polkadot_node_core_backing::CandidateBackingSubsystem; -pub use polkadot_node_core_bitfield_signing::BitfieldSigningSubsystem; -pub use polkadot_node_core_candidate_validation::CandidateValidationSubsystem; -pub use polkadot_node_core_chain_api::ChainApiSubsystem; -pub use polkadot_node_core_chain_selection::ChainSelectionSubsystem; -pub use polkadot_node_core_dispute_coordinator::DisputeCoordinatorSubsystem; -pub use polkadot_node_core_provisioner::ProvisionerSubsystem; -pub use polkadot_node_core_runtime_api::RuntimeApiSubsystem; -pub use polkadot_statement_distribution::StatementDistribution as StatementDistributionSubsystem; - -/// Arguments passed for overseer construction. -pub struct OverseerGenArgs<'a, Spawner, RuntimeClient> -where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, -{ - /// Set of initial relay chain leaves to track. - pub leaves: Vec, - /// The keystore to use for i.e. validator keys. - pub keystore: Arc, - /// Runtime client generic, providing the `ProvieRuntimeApi` trait besides others. - pub runtime_client: Arc, - /// The underlying key value store for the parachains. - pub parachains_db: Arc, - /// Underlying network service implementation. - pub network_service: Arc>, - /// Underlying authority discovery service. - pub authority_discovery_service: AuthorityDiscoveryService, - /// POV request receiver - pub pov_req_receiver: IncomingRequestReceiver, - pub chunk_req_receiver: IncomingRequestReceiver, - pub collation_req_receiver: IncomingRequestReceiver, - pub available_data_req_receiver: - IncomingRequestReceiver, - pub statement_req_receiver: IncomingRequestReceiver, - pub dispute_req_receiver: IncomingRequestReceiver, - /// Prometheus registry, commonly used for production systems, less so for test. - pub registry: Option<&'a Registry>, - /// Task spawner to be used throughout the overseer and the APIs it provides. - pub spawner: Spawner, - /// Configuration for the approval voting subsystem. - pub approval_voting_config: ApprovalVotingConfig, - /// Configuration for the availability store subsystem. - pub availability_config: AvailabilityConfig, - /// Configuration for the candidate validation subsystem. - pub candidate_validation_config: CandidateValidationConfig, - /// Configuration for the chain selection subsystem. - pub chain_selection_config: ChainSelectionConfig, - /// Configuration for the dispute coordinator subsystem. - pub dispute_coordinator_config: DisputeCoordinatorConfig, -} - -/// Obtain a prepared `OverseerBuilder`, that is initialized -/// with all default values. -pub fn prepared_overseer_builder( - OverseerGenArgs { - leaves, - keystore, - runtime_client, - parachains_db, - network_service, - authority_discovery_service, - pov_req_receiver, - chunk_req_receiver, - collation_req_receiver: _, - available_data_req_receiver, - statement_req_receiver, - dispute_req_receiver, - registry, - spawner, - approval_voting_config, - availability_config, - candidate_validation_config, - chain_selection_config, - dispute_coordinator_config, - }: OverseerGenArgs<'_, Spawner, RuntimeClient>, -) -> Result< - OverseerBuilder< - Spawner, - Arc, - CandidateValidationSubsystem, - CandidateBackingSubsystem, - StatementDistributionSubsystem, - AvailabilityDistributionSubsystem, - AvailabilityRecoverySubsystem, - BitfieldSigningSubsystem, - BitfieldDistributionSubsystem, - ProvisionerSubsystem, - RuntimeApiSubsystem, - AvailabilityStoreSubsystem, - NetworkBridgeSubsystem< - Arc>, - AuthorityDiscoveryService, - >, - ChainApiSubsystem, - CollationGenerationSubsystem, - CollatorProtocolSubsystem, - ApprovalDistributionSubsystem, - ApprovalVotingSubsystem, - GossipSupportSubsystem, - DisputeCoordinatorSubsystem, - DisputeDistributionSubsystem, - ChainSelectionSubsystem, - >, - Error, -> -where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, -{ - use polkadot_node_subsystem_util::metrics::Metrics; - use std::iter::FromIterator; - - let metrics = ::register(registry)?; - - let builder = Overseer::builder() - .availability_distribution(AvailabilityDistributionSubsystem::new( - keystore.clone(), - IncomingRequestReceivers { pov_req_receiver, chunk_req_receiver }, - Metrics::register(registry)?, - )) - .availability_recovery(AvailabilityRecoverySubsystem::with_chunks_only( - available_data_req_receiver, - Metrics::register(registry)?, - )) - .availability_store(AvailabilityStoreSubsystem::new( - parachains_db.clone(), - availability_config, - Metrics::register(registry)?, - )) - .bitfield_distribution(BitfieldDistributionSubsystem::new(Metrics::register(registry)?)) - .bitfield_signing(BitfieldSigningSubsystem::new( - spawner.clone(), - keystore.clone(), - Metrics::register(registry)?, - )) - .candidate_backing(CandidateBackingSubsystem::new( - spawner.clone(), - keystore.clone(), - Metrics::register(registry)?, - )) - .candidate_validation(CandidateValidationSubsystem::with_config( - candidate_validation_config, - Metrics::register(registry)?, // candidate-validation metrics - Metrics::register(registry)?, // validation host metrics - )) - .chain_api(ChainApiSubsystem::new(runtime_client.clone(), Metrics::register(registry)?)) - .collation_generation(CollationGenerationSubsystem::new(Metrics::register(registry)?)) - .collator_protocol(CollatorProtocolSubsystem::new(ProtocolSide::Validator { - keystore: keystore.clone(), - eviction_policy: Default::default(), - metrics: Metrics::register(registry)?, - })) - .network_bridge(NetworkBridgeSubsystem::new( - network_service.clone(), - authority_discovery_service.clone(), - Box::new(network_service.clone()), - Metrics::register(registry)?, - )) - .provisioner(ProvisionerSubsystem::new(spawner.clone(), (), Metrics::register(registry)?)) - .runtime_api(RuntimeApiSubsystem::new( - runtime_client.clone(), - Metrics::register(registry)?, - spawner.clone(), - )) - .statement_distribution(StatementDistributionSubsystem::new( - keystore.clone(), - statement_req_receiver, - Metrics::register(registry)?, - )) - .approval_distribution(ApprovalDistributionSubsystem::new(Metrics::register(registry)?)) - .approval_voting(ApprovalVotingSubsystem::with_config( - approval_voting_config, - parachains_db.clone(), - keystore.clone(), - Box::new(network_service), - Metrics::register(registry)?, - )) - .gossip_support(GossipSupportSubsystem::new( - keystore.clone(), - authority_discovery_service.clone(), - )) - .dispute_coordinator(DisputeCoordinatorSubsystem::new( - parachains_db.clone(), - dispute_coordinator_config, - keystore.clone(), - Metrics::register(registry)?, - )) - .dispute_distribution(DisputeDistributionSubsystem::new( - keystore, - dispute_req_receiver, - authority_discovery_service, - Metrics::register(registry)?, - )) - .chain_selection(ChainSelectionSubsystem::new(chain_selection_config, parachains_db)) - .leaves(Vec::from_iter( - leaves - .into_iter() - .map(|BlockInfo { hash, parent_hash: _, number }| (hash, number)), - )) - .activation_external_listeners(Default::default()) - .span_per_active_leaf(Default::default()) - .active_leaves(Default::default()) - .supports_parachains(runtime_client) - .known_leaves(LruCache::new(KNOWN_LEAVES_CACHE_SIZE)) - .metrics(metrics) - .spawner(spawner); - Ok(builder) -} - -/// Trait for the `fn` generating the overseer. -/// -/// Default behavior is to create an unmodified overseer, as `RealOverseerGen` -/// would do. -pub trait OverseerGen { - /// Overwrite the full generation of the overseer, including the subsystems. - fn generate( - &self, - connector: OverseerConnector, - args: OverseerGenArgs<'_, Spawner, RuntimeClient>, - ) -> Result<(Overseer>, OverseerHandle), Error> - where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, - { - let gen = RealOverseerGen; - RealOverseerGen::generate::(&gen, connector, args) - } - // It would be nice to make `create_subsystems` part of this trait, - // but the amount of generic arguments that would be required as - // as consequence make this rather annoying to implement and use. -} - -use polkadot_overseer::KNOWN_LEAVES_CACHE_SIZE; - -/// The regular set of subsystems. -pub struct RealOverseerGen; - -impl OverseerGen for RealOverseerGen { - fn generate( - &self, - connector: OverseerConnector, - args: OverseerGenArgs<'_, Spawner, RuntimeClient>, - ) -> Result<(Overseer>, OverseerHandle), Error> - where - RuntimeClient: 'static + ProvideRuntimeApi + HeaderBackend + AuxStore, - RuntimeClient::Api: ParachainHost + BabeApi + AuthorityDiscoveryApi, - Spawner: 'static + SpawnNamed + Clone + Unpin, - { - prepared_overseer_builder(args)? - .build_with_connector(connector) - .map_err(|e| e.into()) - } -} diff --git a/bin/rialto/node/src/parachains_db.rs b/bin/rialto/node/src/parachains_db.rs deleted file mode 100644 index bf2052043c987..0000000000000 --- a/bin/rialto/node/src/parachains_db.rs +++ /dev/null @@ -1,104 +0,0 @@ -// 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 . - -//! This is almost 1:1 copy of `node/service/parachains_db/mod.rs` file from Polkadot repository. -//! The only exception is that we don't support db upgrades => no `upgrade.rs` module. - -use kvdb::KeyValueDB; -use std::{io, path::PathBuf, sync::Arc}; - -mod columns { - pub const NUM_COLUMNS: u32 = 5; - - pub const COL_AVAILABILITY_DATA: u32 = 0; - pub const COL_AVAILABILITY_META: u32 = 1; - pub const COL_APPROVAL_DATA: u32 = 2; - pub const COL_CHAIN_SELECTION_DATA: u32 = 3; - pub const COL_DISPUTE_COORDINATOR_DATA: u32 = 4; -} - -/// Columns used by different subsystems. -#[derive(Debug, Clone)] -pub struct ColumnsConfig { - /// The column used by the av-store for data. - pub col_availability_data: u32, - /// The column used by the av-store for meta information. - pub col_availability_meta: u32, - /// The column used by approval voting for data. - pub col_approval_data: u32, - /// The column used by chain selection for data. - pub col_chain_selection_data: u32, - /// The column used by dispute coordinator for data. - pub col_dispute_coordinator_data: u32, -} - -/// The real columns used by the parachains DB. -pub const REAL_COLUMNS: ColumnsConfig = ColumnsConfig { - col_availability_data: columns::COL_AVAILABILITY_DATA, - col_availability_meta: columns::COL_AVAILABILITY_META, - col_approval_data: columns::COL_APPROVAL_DATA, - col_chain_selection_data: columns::COL_CHAIN_SELECTION_DATA, - col_dispute_coordinator_data: columns::COL_DISPUTE_COORDINATOR_DATA, -}; - -/// The cache size for each column, in megabytes. -#[derive(Debug, Clone)] -pub struct CacheSizes { - /// Cache used by availability data. - pub availability_data: usize, - /// Cache used by availability meta. - pub availability_meta: usize, - /// Cache used by approval data. - pub approval_data: usize, -} - -impl Default for CacheSizes { - fn default() -> Self { - CacheSizes { availability_data: 25, availability_meta: 1, approval_data: 5 } - } -} - -fn other_io_error(err: String) -> io::Error { - io::Error::new(io::ErrorKind::Other, err) -} - -/// Open the database on disk, creating it if it doesn't exist. -pub fn open_creating(root: PathBuf, cache_sizes: CacheSizes) -> io::Result> { - use kvdb_rocksdb::{Database, DatabaseConfig}; - - let path = root.join("parachains").join("db"); - - let mut db_config = DatabaseConfig::with_columns(columns::NUM_COLUMNS); - - let _ = db_config - .memory_budget - .insert(columns::COL_AVAILABILITY_DATA, cache_sizes.availability_data); - let _ = db_config - .memory_budget - .insert(columns::COL_AVAILABILITY_META, cache_sizes.availability_meta); - let _ = db_config - .memory_budget - .insert(columns::COL_APPROVAL_DATA, cache_sizes.approval_data); - - let path_str = path - .to_str() - .ok_or_else(|| other_io_error(format!("Bad database path: {:?}", path)))?; - - std::fs::create_dir_all(&path_str)?; - let db = Database::open(&db_config, path_str)?; - - Ok(Arc::new(db)) -} diff --git a/bin/rialto/node/src/service.rs b/bin/rialto/node/src/service.rs deleted file mode 100644 index 3349b09edb9f6..0000000000000 --- a/bin/rialto/node/src/service.rs +++ /dev/null @@ -1,756 +0,0 @@ -// 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 . - -//! Rialto chain node service. -//! -//! The code is mostly copy of `service/src/lib.rs` file from Polkadot repository -//! without optional functions, and with BEEFY added on top. - -use crate::overseer::{OverseerGen, OverseerGenArgs}; - -use polkadot_client::RuntimeApiCollection; -use polkadot_node_core_approval_voting::Config as ApprovalVotingConfig; -use polkadot_node_core_av_store::Config as AvailabilityConfig; -use polkadot_node_core_candidate_validation::Config as CandidateValidationConfig; -use polkadot_node_core_chain_selection::Config as ChainSelectionConfig; -use polkadot_node_core_dispute_coordinator::Config as DisputeCoordinatorConfig; -use polkadot_node_network_protocol::request_response::IncomingRequest; -use polkadot_overseer::{BlockInfo, OverseerConnector}; -use polkadot_primitives::v1::BlockId; -use rialto_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::ExecutorProvider; -use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; -use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; -use sc_service::{config::PrometheusConfig, Configuration, TaskManager}; -use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_api::{ConstructRuntimeApi, HeaderT}; -use sp_consensus::SelectChain; -use sp_runtime::traits::Block as BlockT; -use std::{sync::Arc, time::Duration}; -use substrate_prometheus_endpoint::Registry; - -pub use polkadot_overseer::Handle; -pub use polkadot_primitives::v1::ParachainHost; -pub use sc_client_api::AuxStore; -pub use sp_authority_discovery::AuthorityDiscoveryApi; -pub use sp_blockchain::HeaderBackend; -pub use sp_consensus_babe::BabeApi; - -pub type Executor = NativeElseWasmExecutor; - -// Our native executor instance. -pub struct ExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - rialto_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - rialto_runtime::native_version() - } -} - -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error(transparent)] - Io(#[from] std::io::Error), - - #[error(transparent)] - Cli(#[from] sc_cli::Error), - - #[error(transparent)] - Blockchain(#[from] sp_blockchain::Error), - - #[error(transparent)] - Consensus(#[from] sp_consensus::Error), - - #[error(transparent)] - Service(#[from] sc_service::Error), - - #[error(transparent)] - Telemetry(#[from] sc_telemetry::Error), - - #[error("Failed to create an overseer")] - Overseer(#[from] polkadot_overseer::SubsystemError), - - #[error(transparent)] - Prometheus(#[from] substrate_prometheus_endpoint::PrometheusError), - - #[error("Authorities require the real overseer implementation")] - AuthoritiesRequireRealOverseer, - - #[error("Creating a custom database is required for validators")] - DatabasePathRequired, -} - -type FullClient = sc_service::TFullClient; -type FullBackend = sc_service::TFullBackend; -type FullSelectChain = sc_consensus::LongestChain; -type FullGrandpaBlockImport = - sc_finality_grandpa::GrandpaBlockImport; -type FullTransactionPool = sc_transaction_pool::FullPool; -type FullBabeBlockImport = - sc_consensus_babe::BabeBlockImport; -type FullBabeLink = sc_consensus_babe::BabeLink; -type FullGrandpaLink = sc_finality_grandpa::LinkHalf; - -// If we're using prometheus, use a registry with a prefix of `polkadot`. -fn set_prometheus_registry(config: &mut Configuration) -> Result<(), Error> { - if let Some(PrometheusConfig { registry, .. }) = config.prometheus_config.as_mut() { - *registry = Registry::new_custom(Some("polkadot".into()), None)?; - } - - Ok(()) -} - -// Needed here for complex return type while `impl Trait` in type aliases is unstable. -#[allow(clippy::type_complexity)] -pub fn new_partial( - config: &mut Configuration, -) -> Result< - sc_service::PartialComponents< - FullClient, - FullBackend, - FullSelectChain, - sc_consensus::DefaultImportQueue, - FullTransactionPool, - ( - impl Fn( - sc_rpc::DenyUnsafe, - sc_rpc::SubscriptionTaskExecutor, - ) -> Result, sc_service::Error>, - ( - FullBabeBlockImport, - FullGrandpaLink, - FullBabeLink, - beefy_gadget::notification::BeefySignedCommitmentSender, - ), - sc_finality_grandpa::SharedVoterState, - std::time::Duration, - Option, - ), - >, - Error, -> -where - RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, - >::RuntimeApi: - RuntimeApiCollection>, - ExecutorDispatch: NativeExecutionDispatch + 'static, -{ - set_prometheus_registry(config)?; - - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - ); - - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - let client = Arc::new(client); - - let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", None, worker.run()); - telemetry - }); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let (grandpa_block_import, grandpa_link) = - sc_finality_grandpa::block_import_with_authority_set_hard_forks( - client.clone(), - &(client.clone() as Arc<_>), - select_chain.clone(), - Vec::new(), - telemetry.as_ref().map(|x| x.handle()), - )?; - let justification_import = grandpa_block_import.clone(); - - let babe_config = sc_consensus_babe::Config::get_or_compute(&*client)?; - let (block_import, babe_link) = - sc_consensus_babe::block_import(babe_config.clone(), grandpa_block_import, client.clone())?; - - let slot_duration = babe_link.config().slot_duration(); - let import_queue = sc_consensus_babe::import_queue( - babe_link.clone(), - block_import.clone(), - Some(Box::new(justification_import)), - client.clone(), - select_chain.clone(), - move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot)) - }, - &task_manager.spawn_essential_handle(), - config.prometheus_registry(), - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), - telemetry.as_ref().map(|x| x.handle()), - )?; - - let justification_stream = grandpa_link.justification_stream(); - let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = sc_finality_grandpa::SharedVoterState::empty(); - - let (signed_commitment_sender, signed_commitment_stream) = - beefy_gadget::notification::BeefySignedCommitmentStream::channel(); - - let import_setup = (block_import, grandpa_link, babe_link, signed_commitment_sender); - let rpc_setup = shared_voter_state.clone(); - - let slot_duration = babe_config.slot_duration(); - - let rpc_extensions_builder = { - let client = client.clone(); - let transaction_pool = transaction_pool.clone(); - let backend = backend.clone(); - - move |deny_unsafe, - subscription_executor: sc_rpc::SubscriptionTaskExecutor| - -> Result, sc_service::Error> { - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; - use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; - use substrate_frame_rpc_system::{FullSystem, SystemApi}; - - let backend = backend.clone(); - let client = client.clone(); - let pool = transaction_pool.clone(); - - let shared_voter_state = shared_voter_state.clone(); - - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( - backend, - Some(shared_authority_set.clone()), - ); - - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(SystemApi::to_delegate(FullSystem::new( - client.clone(), - pool, - deny_unsafe, - ))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( - client.clone(), - ))); - io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( - shared_authority_set.clone(), - shared_voter_state, - justification_stream.clone(), - subscription_executor.clone(), - finality_proof_provider, - ))); - io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( - beefy_gadget_rpc::BeefyRpcHandler::new( - signed_commitment_stream.clone(), - subscription_executor, - ), - )); - io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new(client))); - - Ok(io) - } - }; - - Ok(sc_service::PartialComponents { - client, - backend, - task_manager, - keystore_container, - select_chain, - import_queue, - transaction_pool, - other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, telemetry), - }) -} - -pub struct NewFull { - pub task_manager: TaskManager, - pub client: C, - pub overseer_handle: Option, - pub network: Arc::Hash>>, - pub rpc_handlers: sc_service::RpcHandlers, - pub backend: Arc, -} - -/// The maximum number of active leaves we forward to the [`Overseer`] on start up. -const MAX_ACTIVE_LEAVES: usize = 4; - -/// Returns the active leaves the overseer should start with. -async fn active_leaves( - select_chain: &sc_consensus::LongestChain, - client: &FullClient, -) -> Result, Error> -where - RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, - >::RuntimeApi: - RuntimeApiCollection>, - ExecutorDispatch: NativeExecutionDispatch + 'static, -{ - let best_block = select_chain.best_chain().await?; - - let mut leaves = select_chain - .leaves() - .await - .unwrap_or_default() - .into_iter() - .filter_map(|hash| { - let number = client.number(hash).ok()??; - - // Only consider leaves that are in maximum an uncle of the best block. - if number < best_block.number().saturating_sub(1) || hash == best_block.hash() { - return None - } - - let parent_hash = client.header(&BlockId::Hash(hash)).ok()??.parent_hash; - - Some(BlockInfo { hash, parent_hash, number }) - }) - .collect::>(); - - // Sort by block number and get the maximum number of leaves - leaves.sort_by_key(|b| b.number); - - leaves.push(BlockInfo { - hash: best_block.hash(), - parent_hash: *best_block.parent_hash(), - number: *best_block.number(), - }); - - Ok(leaves.into_iter().rev().take(MAX_ACTIVE_LEAVES).collect()) -} - -// Create a new full node. -pub fn new_full( - mut config: Configuration, - program_path: Option, - overseer_gen: impl OverseerGen, -) -> Result>, Error> -where - RuntimeApi: ConstructRuntimeApi + Send + Sync + 'static, - >::RuntimeApi: - RuntimeApiCollection>, - ExecutorDispatch: NativeExecutionDispatch + 'static, -{ - let is_collator = false; - - let role = config.role.clone(); - let force_authoring = config.force_authoring; - let backoff_authoring_blocks = - Some(sc_consensus_slots::BackoffAuthoringOnFinalizedHeadLagging::default()); - - let disable_grandpa = config.disable_grandpa; - let name = config.network.node_name.clone(); - - let sc_service::PartialComponents { - client, - backend, - mut task_manager, - keystore_container, - select_chain, - import_queue, - transaction_pool, - other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry), - } = new_partial(&mut config)?; - - let prometheus_registry = config.prometheus_registry().cloned(); - - let overseer_connector = OverseerConnector::default(); - - let shared_voter_state = rpc_setup; - let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht; - - // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change - // anything in terms of behaviour, but makes the logs more consistent with the other - // Substrate nodes. - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); - - config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config()); - - { - use polkadot_network_bridge::{peer_sets_info, IsAuthority}; - let is_authority = if role.is_authority() { IsAuthority::Yes } else { IsAuthority::No }; - config.network.extra_sets.extend(peer_sets_info(is_authority)); - } - - let (pov_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (chunk_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (collation_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (available_data_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (statement_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - let (dispute_req_receiver, cfg) = IncomingRequest::get_config_receiver(); - config.network.request_response_protocols.push(cfg); - - let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - import_setup.1.shared_authority_set().clone(), - vec![], - )); - - let (network, system_rpc_tx, network_starter) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - block_announce_validator_builder: None, - warp_sync: Some(warp_sync), - })?; - - if config.offchain_worker.enabled { - let _ = sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); - } - - let parachains_db = crate::parachains_db::open_creating( - config.database.path().ok_or(Error::DatabasePathRequired)?.into(), - crate::parachains_db::CacheSizes::default(), - )?; - - let availability_config = AvailabilityConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_availability_data, - col_meta: crate::parachains_db::REAL_COLUMNS.col_availability_meta, - }; - - let approval_voting_config = ApprovalVotingConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_approval_data, - slot_duration_millis: slot_duration.as_millis() as u64, - }; - - let candidate_validation_config = CandidateValidationConfig { - artifacts_cache_path: config - .database - .path() - .ok_or(Error::DatabasePathRequired)? - .join("pvf-artifacts"), - program_path: match program_path { - None => std::env::current_exe()?, - Some(p) => p, - }, - }; - - let chain_selection_config = ChainSelectionConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_chain_selection_data, - stagnant_check_interval: polkadot_node_core_chain_selection::StagnantCheckInterval::never(), - }; - - let dispute_coordinator_config = DisputeCoordinatorConfig { - col_data: crate::parachains_db::REAL_COLUMNS.col_dispute_coordinator_data, - }; - - let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - config, - backend: backend.clone(), - client: client.clone(), - keystore: keystore_container.sync_keystore(), - network: network.clone(), - rpc_extensions_builder: Box::new(rpc_extensions_builder), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - system_rpc_tx, - telemetry: telemetry.as_mut(), - })?; - - let (block_import, link_half, babe_link, signed_commitment_sender) = import_setup; - - let overseer_client = client.clone(); - let spawner = task_manager.spawn_handle(); - let active_leaves = futures::executor::block_on(active_leaves(&select_chain, &*client))?; - - let authority_discovery_service = if role.is_authority() || is_collator { - use futures::StreamExt; - use sc_network::Event; - - let authority_discovery_role = if role.is_authority() { - sc_authority_discovery::Role::PublishAndDiscover(keystore_container.keystore()) - } else { - // don't publish our addresses when we're only a collator - sc_authority_discovery::Role::Discover - }; - let dht_event_stream = - network.event_stream("authority-discovery").filter_map(|e| async move { - match e { - Event::Dht(e) => Some(e), - _ => None, - } - }); - let (worker, service) = sc_authority_discovery::new_worker_and_service_with_config( - sc_authority_discovery::WorkerConfig { - publish_non_global_ips: auth_disc_publish_non_global_ips, - ..Default::default() - }, - client.clone(), - network.clone(), - Box::pin(dht_event_stream), - authority_discovery_role, - prometheus_registry.clone(), - ); - - task_manager - .spawn_handle() - .spawn("authority-discovery-worker", None, worker.run()); - Some(service) - } else { - None - }; - - // we'd say let overseer_handler = - // authority_discovery_service.map(|authority_discovery_service|, ...), but in that case we - // couldn't use ? to propagate errors - let local_keystore = keystore_container.local_keystore(); - let maybe_params = - local_keystore.and_then(move |k| authority_discovery_service.map(|a| (a, k))); - - let overseer_handle = if let Some((authority_discovery_service, keystore)) = maybe_params { - let (overseer, overseer_handle) = overseer_gen - .generate::( - overseer_connector, - OverseerGenArgs { - leaves: active_leaves, - keystore, - runtime_client: overseer_client.clone(), - parachains_db, - availability_config, - approval_voting_config, - network_service: network.clone(), - authority_discovery_service, - registry: prometheus_registry.as_ref(), - spawner, - candidate_validation_config, - available_data_req_receiver, - chain_selection_config, - chunk_req_receiver, - collation_req_receiver, - dispute_coordinator_config, - dispute_req_receiver, - pov_req_receiver, - statement_req_receiver, - }, - )?; - let handle = Handle::new(overseer_handle); - - { - let handle = handle.clone(); - task_manager.spawn_essential_handle().spawn_blocking( - "overseer", - None, - Box::pin(async move { - use futures::{pin_mut, select, FutureExt}; - - let forward = polkadot_overseer::forward_events(overseer_client, handle); - - let forward = forward.fuse(); - let overseer_fut = overseer.run().fuse(); - - pin_mut!(overseer_fut); - pin_mut!(forward); - - select! { - _ = forward => (), - _ = overseer_fut => (), - complete => (), - } - }), - ); - } - - Some(handle) - } else { - None - }; - - if role.is_authority() { - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - - let proposer = sc_basic_authorship::ProposerFactory::new( - task_manager.spawn_handle(), - client.clone(), - transaction_pool, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|x| x.handle()), - ); - - let client_clone = client.clone(); - let overseer_handle = - overseer_handle.as_ref().ok_or(Error::AuthoritiesRequireRealOverseer)?.clone(); - let slot_duration = babe_link.config().slot_duration(); - let babe_config = sc_consensus_babe::BabeParams { - keystore: keystore_container.sync_keystore(), - client: client.clone(), - select_chain, - block_import, - env: proposer, - sync_oracle: network.clone(), - justification_sync_link: network.clone(), - create_inherent_data_providers: move |parent, ()| { - let client_clone = client_clone.clone(); - let overseer_handle = overseer_handle.clone(); - async move { - let parachain = polkadot_node_core_parachains_inherent::ParachainsInherentDataProvider::create( - &*client_clone, - overseer_handle, - parent, - ) - .await - .map_err(Box::new)?; - - let uncles = sc_consensus_uncles::create_uncles_inherent_data_provider( - &*client_clone, - parent, - )?; - - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_babe::inherents::InherentDataProvider::from_timestamp_and_duration( - *timestamp, - slot_duration, - ); - - Ok((timestamp, slot, uncles, parachain)) - } - }, - force_authoring, - backoff_authoring_blocks, - babe_link, - can_author_with, - block_proposal_slot_portion: sc_consensus_babe::SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - let babe = sc_consensus_babe::start_babe(babe_config)?; - task_manager.spawn_essential_handle().spawn_blocking("babe", None, babe); - } - - // if the node isn't actively participating in consensus then it doesn't - // need a keystore, regardless of which protocol we use below. - let keystore_opt = - if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; - - let beefy_params = beefy_gadget::BeefyParams { - client: client.clone(), - backend: backend.clone(), - key_store: keystore_opt.clone(), - network: network.clone(), - signed_commitment_sender, - min_block_delta: 2, - prometheus_registry: prometheus_registry.clone(), - }; - - // Start the BEEFY bridge gadget. - task_manager.spawn_essential_handle().spawn_blocking( - "beefy-gadget", - None, - beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params), - ); - - let config = sc_finality_grandpa::Config { - // FIXME substrate#1578 make this available through chainspec - gossip_duration: Duration::from_millis(1000), - justification_period: 512, - name: Some(name), - observer_enabled: false, - keystore: keystore_opt, - local_role: role, - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - let enable_grandpa = !disable_grandpa; - if enable_grandpa { - // start the full GRANDPA voter - // NOTE: unlike in substrate we are currently running the full - // GRANDPA voter protocol for all full nodes (regardless of whether - // they're validators or not). at this point the full voter should - // provide better guarantees of block and vote data availability than - // the observer. - - // add a custom voting rule to temporarily stop voting for new blocks - // after the given pause block is finalized and restarting after the - // given delay. - let builder = sc_finality_grandpa::VotingRulesBuilder::default(); - - let voting_rule = builder.build(); - let grandpa_config = sc_finality_grandpa::GrandpaParams { - config, - link: link_half, - network: network.clone(), - voting_rule, - prometheus_registry, - shared_voter_state, - telemetry: telemetry.as_ref().map(|x| x.handle()), - }; - - task_manager.spawn_essential_handle().spawn_blocking( - "grandpa-voter", - None, - sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, - ); - } - - network_starter.start_network(); - - Ok(NewFull { task_manager, client, overseer_handle, network, rpc_handlers, backend }) -} - -pub fn build_full( - config: Configuration, - overseer_gen: impl OverseerGen, -) -> Result>, Error> { - new_full(config, None, overseer_gen) -} From f5ffa8cab96c0d0001bcb96b165dc05bb48c4e66 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 14 Jan 2022 14:10:37 +0300 Subject: [PATCH 0634/1210] support version mode cli options in send-message subcommand (#1284) --- relays/bin-substrate/src/cli/encode_call.rs | 5 +- relays/bin-substrate/src/cli/mod.rs | 85 +++++++++++++------- relays/bin-substrate/src/cli/send_message.rs | 38 +++++---- 3 files changed, 85 insertions(+), 43 deletions(-) diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 8be04a88ff753..b409cf383ed7c 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -308,8 +308,8 @@ mod tests { ); } - #[test] - fn should_encode_bridge_send_message_call() { + #[async_std::test] + async fn should_encode_bridge_send_message_call() { // given let encode_message = SendMessage::from_iter(vec![ "send-message", @@ -325,6 +325,7 @@ mod tests { "remark", ]) .encode_payload() + .await .unwrap(); let mut encode_call = EncodeCall::from_iter(vec![ diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 1ff46fdbb8462..ae169f773eff6 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -240,7 +240,7 @@ impl AccountId { /// /// Used to abstract away CLI commands. pub trait CliChain: relay_substrate_client::Chain { - /// Chain's current version of the runtime. + /// Current version of the chain runtime, known to relay. const RUNTIME_VERSION: sp_version::RuntimeVersion; /// Crypto KeyPair type used to send messages. @@ -368,7 +368,7 @@ where } #[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, EnumString, EnumVariantNames)] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)] pub enum RuntimeVersionType { /// Auto query version from chain Auto, @@ -391,7 +391,7 @@ macro_rules! declare_chain_options { #[structopt(long, default_value = "127.0.0.1")] pub [<$chain_prefix _host>]: String, #[doc = "Connect to " $chain " node websocket server at given port."] - #[structopt(long)] + #[structopt(long, default_value = "9944")] pub [<$chain_prefix _port>]: u16, #[doc = "Use secure websocket connection."] #[structopt(long)] @@ -402,7 +402,7 @@ macro_rules! declare_chain_options { } #[doc = $chain " runtime version params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] pub struct [<$chain RuntimeVersionParams>] { #[doc = "The type of runtime version for chain " $chain] #[structopt(long, default_value = "Bundle")] @@ -543,29 +543,9 @@ macro_rules! declare_chain_options { &self, bundle_runtime_version: Option ) -> anyhow::Result> { - let runtime_version_params = &self.[<$chain_prefix _runtime_version>]; - let chain_runtime_version = match runtime_version_params.[<$chain_prefix _version_mode>] { - RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, - RuntimeVersionType::Custom => { - let except_spec_version = runtime_version_params.[<$chain_prefix _spec_version>] - .ok_or(anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; - let except_transaction_version = runtime_version_params.[<$chain_prefix _transaction_version>] - .ok_or(anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; - ChainRuntimeVersion::Custom( - except_spec_version, - except_transaction_version - ) - } - RuntimeVersionType::Bundle => { - match bundle_runtime_version { - Some(runtime_version) => ChainRuntimeVersion::Custom( - runtime_version.spec_version, - runtime_version.transaction_version - ), - None => ChainRuntimeVersion::Auto - } - } - }; + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(bundle_runtime_version)?; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { host: self.[<$chain_prefix _host>].clone(), port: self.[<$chain_prefix _port>], @@ -575,6 +555,57 @@ macro_rules! declare_chain_options { .await ) } + + /// Return selected `chain_spec` version. + /// + /// This function only connects to the node if version mode is set to `Auto`. + #[allow(dead_code)] + pub async fn selected_chain_spec_version( + &self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(bundle_runtime_version.clone())?; + Ok(match chain_runtime_version { + ChainRuntimeVersion::Auto => self + .to_client::(bundle_runtime_version) + .await? + .simple_runtime_version() + .await? + .0, + ChainRuntimeVersion::Custom(spec_version, _) => spec_version, + }) + } + } + + impl [<$chain RuntimeVersionParams>] { + /// Converts self into `ChainRuntimeVersion`. + pub fn into_runtime_version( + self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + Ok(match self.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let except_spec_version = self.[<$chain_prefix _spec_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let except_transaction_version = self.[<$chain_prefix _transaction_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + except_spec_version, + except_transaction_version + ) + }, + RuntimeVersionType::Bundle => match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom( + runtime_version.spec_version, + runtime_version.transaction_version + ), + None => ChainRuntimeVersion::Auto + }, + }) + } } } }; diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 52eab9c64ec98..2d81576de3dd2 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -19,7 +19,7 @@ use crate::cli::{ encode_call::{self, CliEncodeCall}, estimate_fee::estimate_message_delivery_and_dispatch_fee, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, - SourceSigningParams, TargetSigningParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; use bp_runtime::{BalanceOf, Chain as _}; @@ -88,10 +88,16 @@ pub struct SendMessage { /// `SourceAccount`. #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] origin: Origins, + + // Normally we don't need to connect to the target chain to send message. But for testing + // we may want to use **actual** `spec_version` of the target chain when composing a message. + // Then we'll need to read version from the target chain node. + #[structopt(flatten)] + target: TargetConnectionParams, } impl SendMessage { - pub fn encode_payload( + pub async fn encode_payload( &mut self, ) -> anyhow::Result>> { crate::select_full_bridge!(self.bridge, { @@ -110,6 +116,10 @@ impl SendMessage { encode_call::preprocess_call::(message, bridge.bridge_instance_index()); let target_call = Target::encode_call(message)?; + let target_spec_version = self + .target + .selected_chain_spec_version::(Some(Target::RUNTIME_VERSION)) + .await?; let payload = { let target_call_weight = prepare_call_dispatch_weight( @@ -121,7 +131,7 @@ impl SendMessage { let source_account_id = source_sender_public.into_account(); message_payload( - Target::RUNTIME_VERSION.spec_version, + target_spec_version, target_call_weight, match origin { Origins::Source => CallOrigin::SourceAccount(source_account_id), @@ -130,7 +140,7 @@ impl SendMessage { let digest = account_ownership_digest( &target_call, source_account_id.clone(), - Target::RUNTIME_VERSION.spec_version, + target_spec_version, ); let target_origin_public = target_sign.public(); let digest_signature = target_sign.sign(&digest); @@ -152,7 +162,7 @@ impl SendMessage { /// Run the command. pub async fn run(mut self) -> anyhow::Result<()> { crate::select_full_bridge!(self.bridge, { - let payload = self.encode_payload()?; + let payload = self.encode_payload().await?; let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; let source_sign = self.source_sign.to_keypair::()?; @@ -291,8 +301,8 @@ mod tests { use super::*; use hex_literal::hex; - #[test] - fn send_remark_rialto_to_millau() { + #[async_std::test] + async fn send_remark_rialto_to_millau() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -307,7 +317,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then assert_eq!( @@ -324,8 +334,8 @@ mod tests { ); } - #[test] - fn send_remark_millau_to_rialto() { + #[async_std::test] + async fn send_remark_millau_to_rialto() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -344,7 +354,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then // Since signatures are randomized we extract it from here and only check the rest. @@ -388,8 +398,8 @@ mod tests { assert!(send_message.is_ok()); } - #[test] - fn accepts_non_default_dispatch_fee_payment() { + #[async_std::test] + async fn accepts_non_default_dispatch_fee_payment() { // given let mut send_message = SendMessage::from_iter(vec![ "send-message", @@ -404,7 +414,7 @@ mod tests { ]); // when - let payload = send_message.encode_payload().unwrap(); + let payload = send_message.encode_payload().await.unwrap(); // then assert_eq!( From 3955b84320ba260a744b04e7b6e998eceb424cc9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 18 Jan 2022 17:07:06 +0300 Subject: [PATCH 0635/1210] when GRANDPA pallet is halted, relay shall not submit finality transactions (#1288) --- modules/grandpa/src/lib.rs | 5 +++ primitives/header-chain/src/storage_keys.rs | 32 +++++++++++++++++-- relays/client-substrate/src/error.rs | 3 ++ .../src/finality_pipeline.rs | 6 ++-- .../src/finality_target.rs | 21 ++++++++++-- .../lib-substrate-relay/src/messages_lane.rs | 16 ++++++++-- 6 files changed, 71 insertions(+), 12 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 1dadc58fe8688..31b5280bb039a 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -1151,6 +1151,11 @@ mod tests { #[test] fn storage_keys_computed_properly() { + assert_eq!( + IsHalted::::storage_value_final_key().to_vec(), + bp_header_chain::storage_keys::is_halted_key("Grandpa").0, + ); + assert_eq!( BestFinalized::::storage_value_final_key().to_vec(), bp_header_chain::storage_keys::best_finalized_hash_key("Grandpa").0, diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs index 460dbb8dc4d0e..e123703eed50e 100644 --- a/primitives/header-chain/src/storage_keys.rs +++ b/primitives/header-chain/src/storage_keys.rs @@ -16,17 +16,30 @@ //! Storage keys of bridge GRANDPA pallet. -/// Name of the `BestFinalized` storage map. -pub const BEST_FINALIZED_MAP_NAME: &str = "BestFinalized"; +/// Name of the `IsHalted` storage value. +pub const IS_HALTED_VALUE_NAME: &str = "IsHalted"; +/// Name of the `BestFinalized` storage value. +pub const BEST_FINALIZED_VALUE_NAME: &str = "BestFinalized"; use sp_core::storage::StorageKey; +/// Storage key of the `IsHalted` flag in the runtime storage. +pub fn is_halted_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + IS_HALTED_VALUE_NAME.as_bytes(), + ) + .to_vec(), + ) +} + /// Storage key of the best finalized header hash value in the runtime storage. pub fn best_finalized_hash_key(pallet_prefix: &str) -> StorageKey { StorageKey( bp_runtime::storage_value_final_key( pallet_prefix.as_bytes(), - BEST_FINALIZED_MAP_NAME.as_bytes(), + BEST_FINALIZED_VALUE_NAME.as_bytes(), ) .to_vec(), ) @@ -37,6 +50,19 @@ mod tests { use super::*; use hex_literal::hex; + #[test] + fn is_halted_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // compatibility with previous pallet. + let storage_key = is_halted_key("BridgeGrandpa").0; + assert_eq!( + storage_key, + hex!("0b06f475eddb98cf933a12262e0388de9611a984bbd04e2fd39f97bbc006115f").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + #[test] fn best_finalized_hash_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 33b9b22a03efe..309531dd26099 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -51,6 +51,9 @@ pub enum Error { /// The client we're connected to is not synced, so we can't rely on its state. #[error("Substrate client is not synced {0}.")] ClientNotSynced(Health), + /// The bridge pallet is halted and all transactions will be rejected. + #[error("Bridge pallet is halted.")] + BridgePalletIsHalted, /// An error has happened when we have tried to parse storage proof. #[error("Error when parsing storage proof: {0:?}.")] StorageProofError(bp_runtime::StorageProofError), diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 07a1279ef4603..84fb8661016b0 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -27,8 +27,8 @@ use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, - HashOf, HeaderOf, SyncHeader, TransactionSignScheme, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, + ChainWithGrandpa, Client, HashOf, HeaderOf, SyncHeader, TransactionSignScheme, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; @@ -44,7 +44,7 @@ pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; #[async_trait] pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. - type SourceChain: Chain; + type SourceChain: ChainWithGrandpa; /// Headers of the `SourceChain` are submitted to this chain. type TargetChain: Chain; diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index 918c633d7420a..9a92c88a234a9 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -26,12 +26,12 @@ use crate::{ }; use async_trait::async_trait; -use bp_header_chain::justification::GrandpaJustification; +use bp_header_chain::{justification::GrandpaJustification, storage_keys::is_halted_key}; use codec::Encode; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error, HashOf, HeaderOf, - SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, ChainWithGrandpa, Client, Error, HashOf, + HeaderOf, SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::{Bytes, Pair}; @@ -50,6 +50,19 @@ impl SubstrateFinalityTarget

{ ) -> Self { SubstrateFinalityTarget { client, transaction_params } } + + /// Ensure that the GRANDPA pallet at target chain is active. + async fn ensure_pallet_active(&self) -> Result<(), Error> { + let is_halted = self + .client + .storage_value(is_halted_key(P::SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME), None) + .await?; + if is_halted.unwrap_or(false) { + Err(Error::BridgePalletIsHalted) + } else { + Ok(()) + } + } } impl Clone for SubstrateFinalityTarget

{ @@ -83,6 +96,8 @@ where // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay self.client.ensure_synced().await?; + // we can't relay finality if GRANDPA pallet at target chain is halted + self.ensure_pallet_active().await?; Ok(crate::messages_source::read_client_state::< P::TargetChain, diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 87146be4896cc..380d1c9624f32 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -34,8 +34,8 @@ use frame_support::weights::{GetDispatchInfo, Weight}; use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ - AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, Client, HashOf, - TransactionSignScheme, + transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, + ChainWithMessages, Client, HashOf, TransactionSignScheme, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; @@ -173,7 +173,7 @@ where Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?}/{:?}\n\t\ + Tx mortality: {:?} (~{}m)/{:?} (~{}m)\n\t\ Stall timeout: {:?}", P::SourceChain::NAME, P::TargetChain::NAME, @@ -183,7 +183,17 @@ where max_messages_size_in_single_batch, max_messages_weight_in_single_batch, params.source_transaction_params.mortality, + transaction_stall_timeout( + params.source_transaction_params.mortality, + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ).as_secs_f64() / 60.0f64, params.target_transaction_params.mortality, + transaction_stall_timeout( + params.target_transaction_params.mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ).as_secs_f64() / 60.0f64, stall_timeout, ); From 360b89d280fd96850bede96e1a23618cb22f7a45 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 19 Jan 2022 10:00:40 +0300 Subject: [PATCH 0636/1210] when messages pallet is halted, relay shall not submit messages delivery/confirmation transactions (#1289) --- modules/messages/src/lib.rs | 11 ++++++- primitives/messages/src/storage_keys.rs | 26 ++++++++++++++++ .../src/messages_source.rs | 30 +++++++++++++++++-- .../src/messages_target.rs | 9 +++++- 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 53694e6ee2368..66bfecd2592b2 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1113,7 +1113,11 @@ mod tests { REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; - use frame_support::{assert_noop, assert_ok, storage::generator::StorageMap, weights::Weight}; + use frame_support::{ + assert_noop, assert_ok, + storage::generator::{StorageMap, StorageValue}, + weights::Weight, + }; use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; @@ -2276,6 +2280,11 @@ mod tests { #[test] fn storage_keys_computed_properly() { + assert_eq!( + PalletOperatingMode::::storage_value_final_key().to_vec(), + bp_messages::storage_keys::operating_mode_key("Messages").0, + ); + assert_eq!( OutboundMessages::::storage_map_final_key(MessageKey { lane_id: TEST_LANE_ID, diff --git a/primitives/messages/src/storage_keys.rs b/primitives/messages/src/storage_keys.rs index 3e8dc672541b6..19494b8b8527e 100644 --- a/primitives/messages/src/storage_keys.rs +++ b/primitives/messages/src/storage_keys.rs @@ -16,6 +16,8 @@ //! Storage keys of bridge messages pallet. +/// Name of the `OPERATING_MODE_VALUE_NAME` storage value. +pub const OPERATING_MODE_VALUE_NAME: &str = "PalletOperatingMode"; /// Name of the `OutboundMessages` storage map. pub const OUTBOUND_MESSAGES_MAP_NAME: &str = "OutboundMessages"; /// Name of the `OutboundLanes` storage map. @@ -29,6 +31,17 @@ use codec::Encode; use frame_support::Blake2_128Concat; use sp_core::storage::StorageKey; +/// Storage key of the `PalletOperatingMode` value in the runtime storage. +pub fn operating_mode_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + OPERATING_MODE_VALUE_NAME.as_bytes(), + ) + .to_vec(), + ) +} + /// Storage key of the outbound message in the runtime storage. pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey { bp_runtime::storage_map_final_key::( @@ -61,6 +74,19 @@ mod tests { use super::*; use hex_literal::hex; + #[test] + fn operating_mode_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is possibly + // breaking all existing message relays. + let storage_key = operating_mode_key("BridgeMessages").0; + assert_eq!( + storage_key, + hex!("dd16c784ebd3390a9bc0357c7511ed010f4cf0917788d791142ff6c1f216e7b3").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + #[test] fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 80da24910222c..de2306be3fef4 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -29,8 +29,8 @@ use crate::{ use async_trait::async_trait; use bp_messages::{ - storage_keys::outbound_lane_data_key, LaneId, MessageNonce, OutboundLaneData, - UnrewardedRelayersState, + storage_keys::{operating_mode_key, outbound_lane_data_key}, + LaneId, MessageNonce, OperatingMode, OutboundLaneData, UnrewardedRelayersState, }; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, @@ -99,6 +99,11 @@ impl SubstrateMessagesSource

{ ) .await } + + /// Ensure that the messages pallet at source chain is active. + async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> { + ensure_messages_pallet_active::(&self.client).await + } } impl Clone for SubstrateMessagesSource

{ @@ -132,6 +137,8 @@ where // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver self.client.ensure_synced().await?; + // we can't relay confirmations if messages pallet at source chain is halted + self.ensure_pallet_active().await?; read_client_state::< _, @@ -292,6 +299,25 @@ where } } +/// Ensure that the messages pallet at source chain is active. +pub(crate) async fn ensure_messages_pallet_active( + client: &Client, +) -> Result<(), SubstrateError> +where + AtChain: ChainWithMessages, + WithChain: ChainWithMessages, +{ + let operating_mode = client + .storage_value(operating_mode_key(WithChain::WITH_CHAIN_MESSAGES_PALLET_NAME), None) + .await?; + let is_halted = operating_mode == Some(OperatingMode::Halted); + if is_halted { + Err(SubstrateError::BridgePalletIsHalted) + } else { + Ok(()) + } +} + /// Make messages delivery proof transaction from given proof. fn make_messages_delivery_proof_transaction( spec_version: u32, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 26d376cd5efed..f973cef897357 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -21,7 +21,7 @@ use crate::{ messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, messages_metrics::StandaloneMessagesMetrics, - messages_source::{read_client_state, SubstrateMessagesProof}, + messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, on_demand_headers::OnDemandHeadersRelay, TransactionParams, }; @@ -100,6 +100,11 @@ impl SubstrateMessagesTarget

{ ) .await } + + /// Ensure that the messages pallet at target chain is active. + async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> { + ensure_messages_pallet_active::(&self.client).await + } } impl Clone for SubstrateMessagesTarget

{ @@ -136,6 +141,8 @@ where // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver self.client.ensure_synced().await?; + // we can't relay messages if messages pallet at target chain is halted + self.ensure_pallet_active().await?; read_client_state::< _, From 81bfc9c389bdf68fa94a94fac7bc74e27e23f4b6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 21 Jan 2022 14:50:41 +0300 Subject: [PATCH 0637/1210] Relay balance metrics (#1291) * relay balance metrics * convert balance to "main" tokens in balance metrics * add balances widgets to maintenance dashboard --- .../src/cli/relay_headers_and_messages.rs | 22 +++- relays/client-substrate/Cargo.toml | 3 +- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 9 ++ .../src/metrics/float_storage_value.rs | 80 ++++++++---- relays/client-substrate/src/metrics/mod.rs | 2 +- relays/client-substrate/src/rpc.rs | 2 + relays/lib-substrate-relay/Cargo.toml | 2 + .../src/messages_metrics.rs | 123 ++++++++++++++++-- 9 files changed, 202 insertions(+), 43 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 212eb9c6a0c6f..11220af3e7e8f 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -374,7 +374,7 @@ impl RelayHeadersAndMessages { let right_to_left_metrics = left_to_right_metrics.clone().reverse(); // start conversion rate update loops for left/right chains - if let Some(left_messages_pallet_owner) = left_messages_pallet_owner { + if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { let left_client = left_client.clone(); let format_err = || { anyhow::format_err!( @@ -417,7 +417,7 @@ impl RelayHeadersAndMessages { }, ); } - if let Some(right_messages_pallet_owner) = right_messages_pallet_owner { + if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { let right_client = right_client.clone(); let format_err = || { anyhow::format_err!( @@ -500,6 +500,24 @@ impl RelayHeadersAndMessages { } } + // add balance-related metrics + let metrics_params = + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + left_client.clone(), + metrics_params, + Some(left_sign.public().into()), + left_messages_pallet_owner.map(|kp| kp.public().into()), + ) + .await?; + let metrics_params = + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + right_client.clone(), + metrics_params, + Some(right_sign.public().into()), + right_messages_pallet_owner.map(|kp| kp.public().into()), + ) + .await?; + // start on-demand header relays let left_to_right_transaction_params = TransactionParams { mortality: right_transactions_mortality, diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index eacaa929a94da..b6a702829faea 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -33,9 +33,10 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 75f2fdeb3e906..24b0127f3a7c0 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -117,7 +117,7 @@ pub type WeightToFeeOf = ::WeightToFee; /// Transaction status of the chain. pub type TransactionStatusOf = TransactionStatus, HashOf>; -/// Substrate-based chain with `frame_system::Config::AccountData` set to +/// Substrate-based chain with `AccountData` generic argument of `frame_system::AccountInfo` set to /// the `pallet_balances::AccountData`. pub trait ChainWithBalances: Chain { /// Return runtime storage key for getting `frame_system::AccountInfo` of given account. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 74bf481d54806..685f938d18a43 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -541,6 +541,15 @@ impl Client { .await } + /// Return `tokenDecimals` property from the set of chain properties. + pub async fn token_decimals(&self) -> Result> { + self.jsonrpsee_execute(move |client| async move { + let system_properties = Substrate::::system_properties(&*client).await?; + Ok(system_properties.get("tokenDecimals").and_then(|v| v.as_u64())) + }) + .await + } + /// Return new justifications stream. pub async fn subscribe_justifications(&self) -> Result> { let subscription = self diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/relays/client-substrate/src/metrics/float_storage_value.rs index 7dccf82b6f8e4..7bb92693b38d2 100644 --- a/relays/client-substrate/src/metrics/float_storage_value.rs +++ b/relays/client-substrate/src/metrics/float_storage_value.rs @@ -14,48 +14,84 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{chain::Chain, client::Client}; +use crate::{chain::Chain, client::Client, Error as SubstrateError}; use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use codec::Decode; +use num_traits::One; use relay_utils::metrics::{ metric_name, register, F64SharedRef, Gauge, Metric, PrometheusError, Registry, StandaloneMetric, F64, }; -use sp_core::storage::StorageKey; -use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber}; -use std::time::Duration; +use sp_core::storage::{StorageData, StorageKey}; +use sp_runtime::{traits::UniqueSaturatedInto, FixedPointNumber, FixedU128}; +use std::{marker::PhantomData, time::Duration}; /// Storage value update interval (in blocks). const UPDATE_INTERVAL_IN_BLOCKS: u32 = 5; +/// Fied-point storage value and the way it is decoded from the raw storage value. +pub trait FloatStorageValue: 'static + Clone + Send + Sync { + /// Type of the value. + type Value: FixedPointNumber; + /// Try to decode value from the raw storage value. + fn decode( + &self, + maybe_raw_value: Option, + ) -> Result, SubstrateError>; +} + +/// Implementation of `FloatStorageValue` that expects encoded `FixedU128` value and returns `1` if +/// value is missing from the storage. +#[derive(Clone, Debug, Default)] +pub struct FixedU128OrOne; + +impl FloatStorageValue for FixedU128OrOne { + type Value = FixedU128; + + fn decode( + &self, + maybe_raw_value: Option, + ) -> Result, SubstrateError> { + maybe_raw_value + .map(|raw_value| { + FixedU128::decode(&mut &raw_value.0[..]) + .map_err(SubstrateError::ResponseParseFailed) + .map(Some) + }) + .unwrap_or_else(|| Ok(Some(FixedU128::one()))) + } +} + /// Metric that represents fixed-point runtime storage value as float gauge. #[derive(Clone, Debug)] -pub struct FloatStorageValueMetric { +pub struct FloatStorageValueMetric { + value_converter: V, client: Client, storage_key: StorageKey, - maybe_default_value: Option, metric: Gauge, shared_value_ref: F64SharedRef, + _phantom: PhantomData, } -impl FloatStorageValueMetric { +impl FloatStorageValueMetric { /// Create new metric. pub fn new( + value_converter: V, client: Client, storage_key: StorageKey, - maybe_default_value: Option, name: String, help: String, ) -> Result { let shared_value_ref = Arc::new(RwLock::new(None)); Ok(FloatStorageValueMetric { + value_converter, client, storage_key, - maybe_default_value, metric: Gauge::new(metric_name(None, &name), help)?, shared_value_ref, + _phantom: Default::default(), }) } @@ -65,20 +101,14 @@ impl FloatStorageValueMetric { } } -impl Metric for FloatStorageValueMetric -where - T: 'static + Decode + Send + Sync + FixedPointNumber, -{ +impl Metric for FloatStorageValueMetric { fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { register(self.metric.clone(), registry).map(drop) } } #[async_trait] -impl StandaloneMetric for FloatStorageValueMetric -where - T: 'static + Decode + Send + Sync + FixedPointNumber, -{ +impl StandaloneMetric for FloatStorageValueMetric { fn update_interval(&self) -> Duration { C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS } @@ -86,16 +116,18 @@ where async fn update(&self) { let value = self .client - .storage_value::(self.storage_key.clone(), None) + .raw_storage_value(self.storage_key.clone(), None) .await - .map(|maybe_storage_value| { - maybe_storage_value.or(self.maybe_default_value).map(|storage_value| { - storage_value.into_inner().unique_saturated_into() as f64 / - T::DIV.unique_saturated_into() as f64 + .and_then(|maybe_storage_value| { + self.value_converter.decode(maybe_storage_value).map(|maybe_fixed_point_value| { + maybe_fixed_point_value.map(|fixed_point_value| { + fixed_point_value.into_inner().unique_saturated_into() as f64 / + V::Value::DIV.unique_saturated_into() as f64 + }) }) }) - .map_err(drop); - relay_utils::metrics::set_gauge_value(&self.metric, value); + .map_err(|e| e.to_string()); + relay_utils::metrics::set_gauge_value(&self.metric, value.clone()); *self.shared_value_ref.write().await = value.ok().and_then(|x| x); } } diff --git a/relays/client-substrate/src/metrics/mod.rs b/relays/client-substrate/src/metrics/mod.rs index 177e2a709cf2d..3b63099e00036 100644 --- a/relays/client-substrate/src/metrics/mod.rs +++ b/relays/client-substrate/src/metrics/mod.rs @@ -16,7 +16,7 @@ //! Contains several Substrate-specific metrics that may be exposed by relay. -pub use float_storage_value::FloatStorageValueMetric; +pub use float_storage_value::{FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric}; pub use storage_proof_overhead::StorageProofOverheadMetric; mod float_storage_value; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index efd45ebe43f36..b792347d7a2ba 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -31,6 +31,8 @@ jsonrpsee_proc_macros::rpc_client_api! { pub(crate) Substrate { #[rpc(method = "system_health", positional_params)] fn system_health() -> Health; + #[rpc(method = "system_properties", positional_params)] + fn system_properties() -> sc_chain_spec::Properties; #[rpc(method = "chain_getHeader", positional_params)] fn chain_get_header(block_hash: Option) -> C::Header; #[rpc(method = "chain_getFinalizedHead", positional_params)] diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 1224d8143938c..5733e398f37dd 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -36,6 +36,8 @@ bp-messages = { path = "../../primitives/messages" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 54eef6c0ae81e..d2206094fe7cd 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -18,16 +18,21 @@ use crate::messages_lane::SubstrateMessageLane; -use num_traits::One; +use codec::Decode; +use frame_system::AccountInfo; +use pallet_balances::AccountData; use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - Chain, Client, + metrics::{ + FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric, StorageProofOverheadMetric, + }, + AccountIdOf, BalanceOf, Chain, ChainWithBalances, Client, Error as SubstrateError, IndexOf, }; use relay_utils::metrics::{ FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, }; -use sp_runtime::FixedU128; -use std::fmt::Debug; +use sp_core::storage::StorageData; +use sp_runtime::{FixedPointNumber, FixedU128}; +use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; /// Shared references to the standalone metrics of the message lane relay loop. #[derive(Debug, Clone)] @@ -44,12 +49,10 @@ pub struct StandaloneMessagesMetrics { pub target_to_base_conversion_rate: Option, /// Source tokens to target tokens conversion rate metric. This rate is stored by the target /// chain. - pub source_to_target_conversion_rate: - Option>, + pub source_to_target_conversion_rate: Option>, /// Target tokens to source tokens conversion rate metric. This rate is stored by the source /// chain. - pub target_to_source_conversion_rate: - Option>, + pub target_to_source_conversion_rate: Option>, } impl StandaloneMessagesMetrics { @@ -104,7 +107,7 @@ impl StandaloneMessagesMetrics { } } -/// Create standalone metrics for the message lane relay loop. +/// Create symmetric standalone metrics for the message lane relay loop. /// /// All metrics returned by this function are exposed by loops that are serving given lane (`P`) /// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). @@ -139,10 +142,10 @@ pub fn standalone_metrics( source_to_target_conversion_rate: P::SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME .map(bp_runtime::storage_parameter_key) .map(|key| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + FloatStorageValueMetric::new( + FixedU128OrOne::default(), target_client, key, - Some(FixedU128::one()), format!( "{}_{}_to_{}_conversion_rate", P::TargetChain::NAME, @@ -162,10 +165,10 @@ pub fn standalone_metrics( target_to_source_conversion_rate: P::TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME .map(bp_runtime::storage_parameter_key) .map(|key| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + FloatStorageValueMetric::new( + FixedU128OrOne::default(), source_client, key, - Some(FixedU128::one()), format!( "{}_{}_to_{}_conversion_rate", P::SourceChain::NAME, @@ -185,6 +188,90 @@ pub fn standalone_metrics( }) } +/// Add relay accounts balance metrics. +pub async fn add_relay_balances_metrics( + client: Client, + metrics: MetricsParams, + relay_account_id: Option>, + messages_pallet_owner_account_id: Option>, +) -> anyhow::Result +where + BalanceOf: Into + std::fmt::Debug, +{ + if relay_account_id.is_none() && messages_pallet_owner_account_id.is_none() { + return Ok(metrics) + } + + let token_decimals = client.token_decimals().await?.ok_or_else(|| { + SubstrateError::Custom(format!("Missing token decimals from {} system properties", C::NAME)) + })?; + let token_decimals = u32::try_from(token_decimals).map_err(|e| { + anyhow::format_err!( + "Token decimals value ({}) of {} doesn't fit into u32: {:?}", + token_decimals, + C::NAME, + e, + ) + })?; + if let Some(relay_account_id) = relay_account_id { + let relay_account_balance_metric = FloatStorageValueMetric::new( + FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, + client.clone(), + C::account_info_storage_key(&relay_account_id), + format!("at_{}_relay_balance", C::NAME), + format!("Balance of the relay account at the {}", C::NAME), + )?; + relay_account_balance_metric.register_and_spawn(&metrics.registry)?; + } + if let Some(messages_pallet_owner_account_id) = messages_pallet_owner_account_id { + let pallet_owner_account_balance_metric = FloatStorageValueMetric::new( + FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, + client.clone(), + C::account_info_storage_key(&messages_pallet_owner_account_id), + format!("at_{}_messages_pallet_owner_balance", C::NAME), + format!("Balance of the messages pallet owner at the {}", C::NAME), + )?; + pallet_owner_account_balance_metric.register_and_spawn(&metrics.registry)?; + } + Ok(metrics) +} + +/// Adapter for `FloatStorageValueMetric` to decode account free balance. +#[derive(Clone, Debug)] +struct FreeAccountBalance { + token_decimals: u32, + _phantom: PhantomData, +} + +impl FloatStorageValue for FreeAccountBalance +where + C: Chain, + BalanceOf: Into, +{ + type Value = FixedU128; + + fn decode( + &self, + maybe_raw_value: Option, + ) -> Result, SubstrateError> { + maybe_raw_value + .map(|raw_value| { + AccountInfo::, AccountData>>::decode(&mut &raw_value.0[..]) + .map_err(SubstrateError::ResponseParseFailed) + .map(|account_data| { + convert_to_token_balance(account_data.data.free.into(), self.token_decimals) + }) + }) + .transpose() + } +} + +/// Convert from raw `u128` balance (nominated in smallest chain token units) to the float regular +/// tokens value. +fn convert_to_token_balance(balance: u128, token_decimals: u32) -> FixedU128 { + FixedU128::from_inner(balance.saturating_mul(FixedU128::DIV / 10u128.pow(token_decimals))) +} + #[cfg(test)] mod tests { use super::*; @@ -196,4 +283,12 @@ mod tests { Some(12.32 / 183.15), ); } + + #[test] + fn token_decimals_used_properly() { + let plancks = 425_000_000_000; + let token_decimals = 10; + let dots = convert_to_token_balance(plancks, token_decimals); + assert_eq!(dots, FixedU128::saturating_from_rational(425, 10)); + } } From 9bd99ddad20cb900d8e492106635015abf7a28d7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 27 Jan 2022 15:42:26 +0300 Subject: [PATCH 0638/1210] Bump Substrate/Polkadot/Cumulus refs (#1295) Substrate: 31d90c202d6df9ce3837ee55587b604619a912ba Polkadot: 60df3c55c711c2872872d6220f98b2611340e051 Cumulus: a9630551c2cd877952ab769c862af4c81b0ccd3c --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/chain_spec.rs | 4 +- bin/millau/node/src/cli.rs | 7 +- bin/millau/node/src/service.rs | 45 +++++-- bin/millau/runtime/src/lib.rs | 8 +- bin/rialto-parachain/node/Cargo.toml | 4 +- bin/rialto-parachain/node/src/chain_spec.rs | 4 +- bin/rialto-parachain/node/src/cli.rs | 50 ++++---- bin/rialto-parachain/node/src/command.rs | 31 ++++- bin/rialto-parachain/node/src/service.rs | 121 ++++++++---------- bin/rialto-parachain/runtime/src/lib.rs | 17 ++- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/node/src/chain_spec.rs | 18 ++- bin/rialto/node/src/cli.rs | 13 +- bin/rialto/runtime/src/lib.rs | 56 ++++---- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/parachains.rs | 23 +++- .../src/messages_benchmarking.rs | 18 +-- modules/dispatch/src/lib.rs | 8 +- modules/grandpa/src/lib.rs | 1 + modules/grandpa/src/mock.rs | 1 + modules/messages/src/instant_payments.rs | 2 +- modules/messages/src/lib.rs | 3 + modules/messages/src/mock.rs | 1 + modules/shift-session-manager/src/lib.rs | 2 + modules/token-swap/src/benchmarking.rs | 24 ++-- modules/token-swap/src/lib.rs | 1 + modules/token-swap/src/mock.rs | 1 + primitives/chain-kusama/src/lib.rs | 1 + primitives/chain-millau/src/lib.rs | 22 ++-- primitives/chain-polkadot/src/lib.rs | 1 + primitives/chain-rialto/src/lib.rs | 4 +- primitives/chain-rococo/src/lib.rs | 1 + primitives/chain-westend/src/lib.rs | 1 + .../header-chain/tests/justification.rs | 3 +- primitives/polkadot-core/src/lib.rs | 15 ++- primitives/runtime/src/chain.rs | 8 +- primitives/runtime/src/storage_proof.rs | 26 ++-- primitives/test-utils/src/keyring.rs | 3 +- relays/bin-substrate/src/cli/encode_call.rs | 2 +- .../bin-substrate/src/cli/encode_message.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 4 +- .../src/messages_target.rs | 4 +- 43 files changed, 334 insertions(+), 232 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index c4438d0cef3ee..12a10ad6c22c8 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,8 +10,8 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +clap = { version = "3.0", features = ["derive"] } jsonrpc-core = "18.0" -structopt = "0.3.21" serde_json = "1.0.59" # Bridge dependencies diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index ad424ba463c8e..a7e3c7c877183 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -95,6 +95,7 @@ impl Alternative { vec![], None, None, + None, properties, None, ), @@ -119,6 +120,7 @@ impl Alternative { vec![], None, None, + None, properties, None, ), @@ -195,7 +197,7 @@ fn testnet_genesis( aura: AuraConfig { authorities: Vec::new() }, beefy: BeefyConfig { authorities: Vec::new() }, grandpa: GrandpaConfig { authorities: Vec::new() }, - sudo: SudoConfig { key: root_key }, + sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { keys: initial_authorities .iter() diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 086def633c598..c3c3d134e3411 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use clap::Parser; use sc_cli::RunCmd; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct Cli { #[structopt(subcommand)] pub subcommand: Option, @@ -27,9 +27,10 @@ pub struct Cli { } /// Possible subcommands of the main binary. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Key management CLI utilities + #[clap(subcommand)] Key(sc_cli::KeySubcommand), /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 36e1b948752a1..db64af878ff32 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -30,7 +30,7 @@ // ===================================================================================== use millau_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::ExecutorProvider; +use sc_client_api::{BlockBackend, ExecutorProvider}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; use sc_finality_grandpa::SharedVoterState; @@ -108,6 +108,7 @@ pub fn new_partial( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = @@ -210,8 +211,27 @@ pub fn new_full(mut config: Configuration) -> Result }; } - config.network.extra_sets.push(sc_finality_grandpa::grandpa_peers_set_config()); - config.network.extra_sets.push(beefy_gadget::beefy_peers_set_config()); + // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change + // anything in terms of behaviour, but makes the logs more consistent with the other + // Substrate nodes. + let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); + config + .network + .extra_sets + .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + + let beefy_protocol_name = beefy_gadget::protocol_standard_name( + &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), + &config.chain_spec, + ); + config + .network + .extra_sets + .push(beefy_gadget::beefy_peers_set_config(beefy_protocol_name.clone())); + let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -245,8 +265,10 @@ pub fn new_full(mut config: Configuration) -> Result let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); let shared_voter_state = SharedVoterState::empty(); - let (signed_commitment_sender, signed_commitment_stream) = - beefy_gadget::notification::BeefySignedCommitmentStream::channel(); + let (beefy_commitment_link, beefy_commitment_stream) = + beefy_gadget::notification::BeefySignedCommitmentStream::::channel(); + let (beefy_best_block_link, beefy_best_block_stream) = + beefy_gadget::notification::BeefyBestBlockStream::::channel(); let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; @@ -287,10 +309,12 @@ pub fn new_full(mut config: Configuration) -> Result finality_proof_provider.clone(), ))); io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( - beefy_gadget_rpc::BeefyRpcHandler::new( - signed_commitment_stream.clone(), + beefy_gadget_rpc::BeefyRpcHandler::::new( + beefy_commitment_stream.clone(), + beefy_best_block_stream.clone(), subscription_executor, - ), + ) + .map_err(|e| sc_service::Error::Other(format!("{}", e)))?, )); io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new( client.clone(), @@ -374,9 +398,11 @@ pub fn new_full(mut config: Configuration) -> Result backend, key_store: keystore.clone(), network: network.clone(), - signed_commitment_sender, + signed_commitment_sender: beefy_commitment_link, + beefy_best_block_sender: beefy_best_block_link, min_block_delta: 4, prometheus_registry: prometheus_registry.clone(), + protocol_name: beefy_protocol_name, }; // Start the BEEFY bridge gadget. @@ -395,6 +421,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore, local_role: role, telemetry: telemetry.as_ref().map(|x| x.handle()), + protocol_name: grandpa_protocol_name, }; if enable_grandpa { diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 33839614e75cf..e0c3903621709 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -138,6 +138,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 0, }; /// The version information used to identify this runtime when compiled natively. @@ -204,6 +205,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_randomness_collective_flip::Config for Runtime {} @@ -562,7 +564,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_runtime_apis! { @@ -664,7 +666,7 @@ impl_runtime_apis! { } impl beefy_primitives::BeefyApi for Runtime { - fn validator_set() -> ValidatorSet { + fn validator_set() -> Option> { Beefy::validator_set() } } @@ -841,7 +843,7 @@ impl_runtime_apis! { } fn bridged_relayer_id() -> Self::InboundRelayer { - Default::default() + [0u8; 32].into() } fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 8adc998e47ee3..975d551b888c8 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -18,10 +18,10 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] +clap = { version = "3.0", features = ["derive"] } derive_more = '0.99.2' log = '0.4.14' codec = { package = 'parity-scale-codec', version = '2.0.0' } -structopt = '0.3.8' serde = { version = '1.0', features = ['derive'] } hex-literal = '0.3.1' @@ -80,6 +80,8 @@ cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-local = { git = "https://github.com/paritytech/cumulus", branch = "master" } # Polkadot dependencies polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 52012423fb716..6a8e751677df7 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -89,6 +89,7 @@ pub fn development_config(id: ParaId) -> ChainSpec { None, None, None, + None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! para_id: id.into(), @@ -133,6 +134,7 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec { None, None, None, + None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! para_id: id.into(), @@ -155,7 +157,7 @@ fn testnet_genesis( balances: rialto_parachain_runtime::BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }, - sudo: rialto_parachain_runtime::SudoConfig { key: root_key }, + sudo: rialto_parachain_runtime::SudoConfig { key: Some(root_key) }, parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 78c05f90c8800..7abb72cb876cd 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -15,18 +15,18 @@ // along with Parity Bridges Common. If not, see . use crate::chain_spec; +use clap::{AppSettings, Parser}; use std::path::PathBuf; -use structopt::StructOpt; /// Sub-commands supported by the collator. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Export the genesis state of the parachain. - #[structopt(name = "export-genesis-state")] + #[clap(name = "export-genesis-state")] ExportGenesisState(ExportGenesisStateCommand), /// Export the genesis wasm of the parachain. - #[structopt(name = "export-genesis-wasm")] + #[clap(name = "export-genesis-wasm")] ExportGenesisWasm(ExportGenesisWasmCommand), /// Build a chain specification. @@ -51,66 +51,66 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// The custom benchmark subcommmand benchmarking runtime pallets. - #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")] + #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } /// Command for exporting the genesis state of the parachain -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ExportGenesisStateCommand { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Id of the parachain this state is for. /// /// Default: 100 - #[structopt(long, conflicts_with = "chain")] + #[clap(long, conflicts_with = "chain")] pub parachain_id: Option, /// Write output in binary. Default is to write in hex. - #[structopt(short, long)] + #[clap(short, long)] pub raw: bool, /// The name of the chain for that the genesis state should be exported. - #[structopt(long, conflicts_with = "parachain-id")] + #[clap(long, conflicts_with = "parachain-id")] pub chain: Option, } /// Command for exporting the genesis wasm file. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ExportGenesisWasmCommand { /// Output file name or stdout if unspecified. - #[structopt(parse(from_os_str))] + #[clap(parse(from_os_str))] pub output: Option, /// Write output in binary. Default is to write in hex. - #[structopt(short, long)] + #[clap(short, long)] pub raw: bool, /// The name of the chain for that the genesis wasm file should be exported. - #[structopt(long)] + #[clap(long)] pub chain: Option, } -#[derive(Debug, StructOpt)] -#[structopt(settings = &[ - structopt::clap::AppSettings::GlobalVersion, - structopt::clap::AppSettings::ArgsNegateSubcommands, - structopt::clap::AppSettings::SubcommandsNegateReqs, -])] +#[derive(Debug, Parser)] +#[clap(setting( + AppSettings::PropagateVersion | + AppSettings::ArgsNegateSubcommands | + AppSettings::SubcommandsNegateReqs, +))] pub struct Cli { - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Option, - #[structopt(long)] + #[clap(long)] pub parachain_id: Option, - #[structopt(flatten)] + #[clap(flatten)] pub run: cumulus_client_cli::RunCmd, /// Relaychain arguments - #[structopt(raw = true)] + #[clap(raw = true)] pub relaychain_args: Vec, } @@ -135,6 +135,6 @@ impl RelayChainCli { let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("rialto-bridge-node")); - Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) } + Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } } } diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index e4f52cc026a7e..9a69042a80342 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -211,10 +211,12 @@ pub fn run() -> Result<()> { builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); let _ = builder.init(); - let block: Block = generate_genesis_block(&load_spec( + let spec = load_spec( ¶ms.chain.clone().unwrap_or_default(), params.parachain_id.expect("Missing ParaId").into(), - )?)?; + )?; + let state_version = Cli::native_runtime_version(&spec).state_version(); + let block: Block = generate_genesis_block(&spec, state_version)?; let raw_header = block.header().encode(); let output_buf = if params.raw { raw_header @@ -278,8 +280,10 @@ pub fn run() -> Result<()> { let parachain_account = AccountIdConversion::::into_account(&id); - let block: Block = - generate_genesis_block(&config.chain_spec).map_err(|e| format!("{:?}", e))?; + let state_version = + RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); + let block: Block = generate_genesis_block(&config.chain_spec, state_version) + .map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); let polkadot_config = SubstrateCli::create_configuration( @@ -357,11 +361,24 @@ impl CliConfiguration for RelayChainCli { self.base.base.rpc_ws(default_listen_port) } - fn prometheus_config(&self, default_listen_port: u16) -> Result> { - self.base.base.prometheus_config(default_listen_port) + fn prometheus_config( + &self, + default_listen_port: u16, + chain_spec: &Box, + ) -> Result> { + self.base.base.prometheus_config(default_listen_port, chain_spec) } - fn init(&self) -> Result<()> { + fn init( + &self, + _support_url: &String, + _impl_version: &String, + _logger_hook: F, + _config: &sc_service::Configuration, + ) -> Result<()> + where + F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), + { unreachable!("PolkadotCli is never initialized; qed"); } diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 54e626e0ead19..61f705086e997 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -22,21 +22,21 @@ //! `substrate_frame_rpc_system::SystemApi`. // std -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; // Local Runtime Types use rialto_parachain_runtime::RuntimeApi; // Cumulus Imports -use cumulus_client_consensus_aura::{ - build_aura_consensus, BuildAuraConsensusParams, SlotProportion, -}; +use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; use cumulus_client_consensus_common::ParachainConsensus; -use cumulus_client_network::build_block_announce_validator; +use cumulus_client_network::BlockAnnounceValidator; use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; +use cumulus_relay_chain_interface::RelayChainInterface; +use cumulus_relay_chain_local::build_relay_chain_interface; // Substrate Imports use sc_client_api::ExecutorProvider; @@ -141,6 +141,7 @@ where config.wasm_method, config.default_heap_pages, config.max_runtime_instances, + config.runtime_cache_size, ); let (client, backend, keystore_container, task_manager) = @@ -247,7 +248,7 @@ where Option<&Registry>, Option, &TaskManager, - &polkadot_service::NewFull, + Arc, Arc< sc_transaction_pool::FullPool< Block, @@ -268,8 +269,9 @@ where let params = new_partial::(¶chain_config, build_import_queue)?; let (mut telemetry, telemetry_worker_handle) = params.other; - let relay_chain_full_node = - cumulus_client_service::build_polkadot_full_node(polkadot_config, telemetry_worker_handle) + let mut task_manager = params.task_manager; + let (relay_chain_interface, collator_key) = + build_relay_chain_interface(polkadot_config, telemetry_worker_handle, &mut task_manager) .map_err(|e| match e { polkadot_service::Error::Sub(x) => x, s => format!("{}", s).into(), @@ -277,18 +279,12 @@ where let client = params.client.clone(); let backend = params.backend.clone(); - let block_announce_validator = build_block_announce_validator( - relay_chain_full_node.client.clone(), - id, - Box::new(relay_chain_full_node.network.clone()), - relay_chain_full_node.backend.clone(), - ); + let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id); let force_authoring = parachain_config.force_authoring; let validator = parachain_config.role.is_authority(); let prometheus_registry = parachain_config.prometheus_registry().cloned(); let transaction_pool = params.transaction_pool.clone(); - let mut task_manager = params.task_manager; let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); let (network, system_rpc_tx, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { @@ -297,7 +293,9 @@ where transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), import_queue: import_queue.clone(), - block_announce_validator_builder: Some(Box::new(|_| block_announce_validator)), + block_announce_validator_builder: Some(Box::new(|_| { + Box::new(block_announce_validator) + })), warp_sync: None, })?; @@ -325,13 +323,15 @@ where Arc::new(move |hash, data| network.announce_block(hash, data)) }; + let relay_chain_slot_duration = Duration::from_secs(6); + if validator { let parachain_consensus = build_consensus( client.clone(), prometheus_registry.as_ref(), telemetry.as_ref().map(|t| t.handle()), &task_manager, - &relay_chain_full_node, + relay_chain_interface.clone(), transaction_pool, network, params.keystore_container.sync_keystore(), @@ -346,10 +346,12 @@ where announce_block, client: client.clone(), task_manager: &mut task_manager, - relay_chain_full_node, + relay_chain_interface, spawner, parachain_consensus, import_queue, + collator_key, + relay_chain_slot_duration, }; start_collator(params).await?; @@ -359,7 +361,9 @@ where announce_block, task_manager: &mut task_manager, para_id: id, - relay_chain_full_node, + relay_chain_interface, + relay_chain_slot_duration, + import_queue, }; start_full_node(params)?; @@ -447,7 +451,7 @@ pub async fn start_node( prometheus_registry, telemetry, task_manager, - relay_chain_node, + relay_chain_interface, transaction_pool, sync_oracle, keystore, @@ -462,60 +466,47 @@ pub async fn start_node( telemetry.clone(), ); - let relay_chain_backend = relay_chain_node.backend.clone(); - let relay_chain_client = relay_chain_node.client.clone(); - Ok(build_aura_consensus::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - _, - _, - _, - _, - >(BuildAuraConsensusParams { - proposer_factory, - create_inherent_data_providers: move |_, (relay_parent, validation_data)| { - let parachain_inherent = - cumulus_primitives_parachain_inherent::ParachainInherentData::create_at_with_client( + Ok(AuraConsensus::build::( + BuildAuraConsensusParams { + proposer_factory, + create_inherent_data_providers: move |_, (relay_parent, validation_data)| { + let relay_chain_interface = relay_chain_interface.clone(); + async move { + let parachain_inherent = + cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( relay_parent, - &relay_chain_client, - &*relay_chain_backend, + &relay_chain_interface, &validation_data, id, - ); - async move { - let time = sp_timestamp::InherentDataProvider::from_system_time(); + ).await; + let time = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( *time, slot_duration.slot_duration(), ); - let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) - })?; - Ok((time, slot, parachain_inherent)) - } + let parachain_inherent = parachain_inherent.ok_or_else(|| { + Box::::from( + "Failed to create parachain inherent", + ) + })?; + Ok((time, slot, parachain_inherent)) + } + }, + block_import: client.clone(), + para_client: client, + backoff_authoring_blocks: Option::<()>::None, + sync_oracle, + keystore, + force_authoring, + slot_duration, + // We got around 500ms for proposing + block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), + telemetry, + max_block_proposal_slot_portion: None, }, - block_import: client.clone(), - relay_chain_client: relay_chain_node.client.clone(), - relay_chain_backend: relay_chain_node.backend.clone(), - para_client: client, - backoff_authoring_blocks: Option::<()>::None, - sync_oracle, - keystore, - force_authoring, - slot_duration, - // We got around 500ms for proposing - block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), - telemetry, - max_block_proposal_slot_portion: None, - })) + )) }, ) .await diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 5b71674b7fe9b..e499c89f13acd 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -50,7 +50,7 @@ pub use frame_support::{ }, StorageValue, }; -pub use frame_system::Call as SystemCall; +pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -70,7 +70,7 @@ use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, - ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; @@ -103,7 +103,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_opaque_keys! { @@ -122,6 +122,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 0, }; /// This determines the average expected block time that we are targeting. @@ -209,6 +210,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The action to take on a Runtime Upgrade type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -267,7 +269,7 @@ parameter_types! { impl cumulus_pallet_parachain_system::Config for Runtime { type Event = Event; - type OnValidationData = (); + type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; type DmpMessageHandler = DmpQueue; @@ -294,7 +296,7 @@ parameter_types! { /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsDefault, + ParentIsPreset, // Sibling parachain origins convert to AccountId via the `ParaId::into`. SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. @@ -420,6 +422,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; type VersionWrapper = (); + type ExecuteOverweightOrigin = EnsureRoot; } impl cumulus_pallet_dmp_queue::Config for Runtime { @@ -554,8 +557,8 @@ impl_runtime_apis! { } impl cumulus_primitives_core::CollectCollationInfo for Runtime { - fn collect_collation_info() -> cumulus_primitives_core::CollationInfo { - ParachainSystem::collect_collation_info() + fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info(header) } } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 77694e552acbf..6c7bce4d4e0f0 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,12 +10,12 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +clap = { version = "3.0", features = ["derive"] } futures = "0.3" jsonrpc-core = "18.0" kvdb = "0.10" kvdb-rocksdb = "0.12" lru = "0.7" -structopt = "0.3.21" serde_json = "1.0.59" thiserror = "1.0" diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 7e08e635317bf..6bfacba83a1e1 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -104,6 +104,7 @@ impl Alternative { vec![], None, None, + None, properties, Default::default(), ), @@ -128,6 +129,7 @@ impl Alternative { vec![], None, None, + None, properties, Default::default(), ), @@ -222,7 +224,7 @@ fn testnet_genesis( }, beefy: BeefyConfig { authorities: Vec::new() }, grandpa: GrandpaConfig { authorities: Vec::new() }, - sudo: SudoConfig { key: root_key }, + sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { keys: initial_authorities .iter() @@ -248,8 +250,8 @@ fn testnet_genesis( // (see /node/service/src/chain_spec.rs:default_parachains_host_configuration) configuration: ConfigurationConfig { config: polkadot_runtime_parachains::configuration::HostConfiguration { - validation_upgrade_frequency: 1u32, - validation_upgrade_delay: 1, + validation_upgrade_cooldown: 2u32, + validation_upgrade_delay: 2, code_retention_period: 1200, max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE, max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE, @@ -259,13 +261,8 @@ fn testnet_genesis( thread_availability_period: 4, max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, - max_downward_message_size: 1024, - // this is approximatelly 4ms. - // - // Same as `4 * frame_support::weights::WEIGHT_PER_MILLIS`. We don't bother with - // an import since that's a made up number and should be replaced with a constant - // obtained by benchmarking anyway. - ump_service_total_weight: 4 * 1_000_000_000, + max_downward_message_size: 1024 * 1024, + ump_service_total_weight: 100_000_000_000, max_upward_message_size: 1024 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, @@ -284,6 +281,7 @@ fn testnet_genesis( needed_approvals: 2, relay_vrf_modulo_samples: 2, zeroth_delay_tranche_width: 0, + minimum_validation_upgrade_delay: 5, ..Default::default() }, }, diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 3f85a69a713fe..20155a1469e46 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use clap::{AppSettings, Parser}; use sc_cli::RunCmd; -use structopt::StructOpt; -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct Cli { #[structopt(subcommand)] pub subcommand: Option, @@ -27,9 +27,10 @@ pub struct Cli { } /// Possible subcommands of the main binary. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { /// Key management CLI utilities + #[clap(subcommand)] Key(sc_cli::KeySubcommand), /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. @@ -69,16 +70,16 @@ pub enum Subcommand { Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. - #[structopt(name = "prepare-worker", setting = structopt::clap::AppSettings::Hidden)] + #[clap(name = "prepare-worker", setting = AppSettings::Hidden)] PvfPrepareWorker(ValidationWorkerCommand), /// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary. - #[structopt(name = "execute-worker", setting = structopt::clap::AppSettings::Hidden)] + #[clap(name = "execute-worker", setting = AppSettings::Hidden)] PvfExecuteWorker(ValidationWorkerCommand), } /// Validation worker command. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ValidationWorkerCommand { /// The path to the validation host's socket. pub socket_path: String, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5f940bb58e07f..42d2d880e06eb 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -142,6 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, + state_version: 1, }; /// The version information used to identify this runtime when compiled natively. @@ -208,6 +209,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; /// The set code logic, just the default since we're not a parachain. type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } /// The BABE epoch configuration at genesis. @@ -553,7 +555,7 @@ pub type Executive = frame_executive::Executive< Block, frame_system::ChainContext, Runtime, - AllPallets, + AllPalletsWithSystem, >; impl_runtime_apis! { @@ -605,7 +607,7 @@ impl_runtime_apis! { } impl beefy_primitives::BeefyApi for Runtime { - fn validator_set() -> ValidatorSet { + fn validator_set() -> Option> { Beefy::validator_set() } } @@ -715,15 +717,12 @@ impl_runtime_apis! { } } - impl polkadot_primitives::v1::ParachainHost for Runtime { + impl polkadot_primitives::v2::ParachainHost for Runtime { fn validators() -> Vec { polkadot_runtime_parachains::runtime_api_impl::v1::validators::() } - fn validator_groups() -> ( - Vec>, - polkadot_primitives::v1::GroupRotationInfo, - ) { + fn validator_groups() -> (Vec>, polkadot_primitives::v1::GroupRotationInfo) { polkadot_runtime_parachains::runtime_api_impl::v1::validator_groups::() } @@ -731,10 +730,7 @@ impl_runtime_apis! { polkadot_runtime_parachains::runtime_api_impl::v1::availability_cores::() } - fn persisted_validation_data( - para_id: polkadot_primitives::v1::Id, - assumption: polkadot_primitives::v1::OccupiedCoreAssumption, - ) + fn persisted_validation_data(para_id: polkadot_primitives::v1::Id, assumption: polkadot_primitives::v1::OccupiedCoreAssumption) -> Option> { polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::(para_id, assumption) } @@ -743,7 +739,10 @@ impl_runtime_apis! { para_id: polkadot_primitives::v1::Id, expected_persisted_validation_data_hash: Hash, ) -> Option<(polkadot_primitives::v1::PersistedValidationData, polkadot_primitives::v1::ValidationCodeHash)> { - polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::(para_id, expected_persisted_validation_data_hash) + polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::( + para_id, + expected_persisted_validation_data_hash, + ) } fn check_validation_outputs( @@ -757,17 +756,12 @@ impl_runtime_apis! { polkadot_runtime_parachains::runtime_api_impl::v1::session_index_for_child::() } - fn validation_code( - para_id: polkadot_primitives::v1::Id, - assumption: polkadot_primitives::v1::OccupiedCoreAssumption, - ) + fn validation_code(para_id: polkadot_primitives::v1::Id, assumption: polkadot_primitives::v1::OccupiedCoreAssumption) -> Option { polkadot_runtime_parachains::runtime_api_impl::v1::validation_code::(para_id, assumption) } - fn candidate_pending_availability( - para_id: polkadot_primitives::v1::Id, - ) -> Option> { + fn candidate_pending_availability(para_id: polkadot_primitives::v1::Id) -> Option> { polkadot_runtime_parachains::runtime_api_impl::v1::candidate_pending_availability::(para_id) } @@ -782,13 +776,11 @@ impl_runtime_apis! { }) } - fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option { + fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option { polkadot_runtime_parachains::runtime_api_impl::v1::session_info::(index) } - fn dmq_contents( - recipient: polkadot_primitives::v1::Id, - ) -> Vec> { + fn dmq_contents(recipient: polkadot_primitives::v1::Id) -> Vec> { polkadot_runtime_parachains::runtime_api_impl::v1::dmq_contents::(recipient) } @@ -798,15 +790,27 @@ impl_runtime_apis! { polkadot_runtime_parachains::runtime_api_impl::v1::inbound_hrmp_channels_contents::(recipient) } - fn validation_code_by_hash( - hash: polkadot_primitives::v1::ValidationCodeHash, - ) -> Option { + fn validation_code_by_hash(hash: polkadot_primitives::v1::ValidationCodeHash) -> Option { polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::(hash) } fn on_chain_votes() -> Option> { polkadot_runtime_parachains::runtime_api_impl::v1::on_chain_votes::() } + + fn submit_pvf_check_statement(stmt: polkadot_primitives::v2::PvfCheckStatement, signature: polkadot_primitives::v1::ValidatorSignature) { + polkadot_runtime_parachains::runtime_api_impl::v1::submit_pvf_check_statement::(stmt, signature) + } + + fn pvfs_require_precheck() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v1::pvfs_require_precheck::() + } + + fn validation_code_hash(para_id: polkadot_primitives::v1::Id, assumption: polkadot_primitives::v1::OccupiedCoreAssumption) + -> Option + { + polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_hash::(para_id, assumption) + } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 05935c90ea107..22d11c68be20b 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -316,7 +316,7 @@ mod tests { SystemConfig::default().build_storage::().unwrap().into(); ext.execute_with(|| { let bridge = MILLAU_CHAIN_ID; - let call: Call = SystemCall::remark { remark: vec![] }.into(); + let call: Call = SystemCall::set_heap_pages { pages: 64 }.into(); let dispatch_weight = call.get_dispatch_info().weight; let dispatch_fee = ::WeightToFee::calc( &dispatch_weight, diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 332a3387ac69a..9a316ef0e2a78 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -16,7 +16,10 @@ //! Parachains support in Rialto runtime. -use crate::{AccountId, Balance, Balances, BlockNumber, Event, Origin, Registrar, Runtime, Slots}; +use crate::{ + AccountId, Babe, Balance, Balances, BlockNumber, Call, Event, Origin, Registrar, Runtime, + Slots, UncheckedExtrinsic, +}; use frame_support::{parameter_types, weights::Weight}; use frame_system::EnsureRoot; @@ -29,6 +32,15 @@ use polkadot_runtime_parachains::{ paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler, session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump, }; +use sp_runtime::transaction_validity::TransactionPriority; + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + Call: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = Call; +} /// Special `RewardValidators` that does nothing ;) pub struct RewardValidators; @@ -49,6 +61,7 @@ impl parachains_hrmp::Config for Runtime { type Event = Event; type Origin = Origin; type Currency = Balances; + type WeightInfo = parachains_hrmp::TestWeightInfo; } impl parachains_inclusion::Config for Runtime { @@ -65,10 +78,15 @@ impl parachains_initializer::Config for Runtime { impl parachains_origin::Config for Runtime {} +parameter_types! { + pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); +} + impl parachains_paras::Config for Runtime { - type Origin = Origin; type Event = Event; type WeightInfo = parachains_paras::TestWeightInfo; + type UnsignedPriority = ParasUnsignedPriority; + type NextSessionRotation = Babe; } impl parachains_paras_inherent::Config for Runtime { @@ -120,6 +138,7 @@ impl slots::Config for Runtime { type LeasePeriod = LeasePeriod; type WeightInfo = slots::TestWeightInfo; type LeaseOffset = (); + type ForceOrigin = EnsureRoot; } impl paras_sudo_wrapper::Config for Runtime {} diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 1b14ee30aee82..12c270d8666fd 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -40,7 +40,7 @@ use pallet_bridge_messages::benchmarking::{ use sp_core::Hasher; use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; use sp_std::{fmt::Debug, prelude::*}; -use sp_trie::{record_all_keys, trie_types::TrieDBMut, Layout, MemoryDB, Recorder, TrieMut}; +use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; use sp_version::RuntimeVersion; /// Prepare outbound message for the `send_message` call. @@ -177,7 +177,7 @@ where let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); @@ -186,7 +186,7 @@ where // generate storage proof to be delivered to This chain let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) .map_err(|_| "record_all_keys has failed") .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); @@ -220,7 +220,7 @@ where let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMut::::new(&mut mdb, &mut root); + let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); // insert messages for nonce in params.message_nonces.clone() { @@ -256,7 +256,7 @@ where // generate storage proof to be delivered to This chain let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) .map_err(|_| "record_all_keys has failed") .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); @@ -339,7 +339,7 @@ fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: Proo loop { // generate storage proof to be delivered to This chain let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(mdb, &root, &mut proof_recorder) + record_all_keys::, _>(mdb, &root, &mut proof_recorder) .map_err(|_| "record_all_keys has failed") .expect("record_all_keys should not fail in benchmarks"); let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); @@ -347,9 +347,9 @@ fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: Proo return root } - let mut trie = TrieDBMut::::from_existing(mdb, &mut root) - .map_err(|_| "TrieDBMut::from_existing has failed") - .expect("TrieDBMut::from_existing should not fail in benchmarks"); + let mut trie = TrieDBMutV1::::from_existing(mdb, &mut root) + .map_err(|_| "TrieDBMutV1::from_existing has failed") + .expect("TrieDBMutV1::from_existing should not fail in benchmarks"); for _ in 0..iterations { trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) .map_err(|_| "TrieMut::insert has failed") diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs index f467bab0d9464..1e030b7332059 100644 --- a/modules/dispatch/src/lib.rs +++ b/modules/dispatch/src/lib.rs @@ -64,8 +64,7 @@ pub mod pallet { + MaybeSerializeDeserialize + Debug + MaybeDisplay - + Ord - + Default; + + Ord; /// Type of account public key on target chain. type TargetChainAccountPublic: Parameter + IdentifyAccount; /// Type of signature that may prove that the message has been signed by @@ -520,6 +519,7 @@ mod tests { type DbWeight = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl Config for TestRuntime { @@ -649,11 +649,11 @@ mod tests { fn should_fail_on_weight_mismatch() { new_test_ext().execute_with(|| { let id = [0; 4]; - let call = Call::System(frame_system::Call::remark { remark: vec![1, 2, 3] }); + let call = Call::System(frame_system::Call::set_heap_pages { pages: 42 }); let call_weight = call.get_dispatch_info().weight; let mut message = prepare_root_message(call); message.weight = 7; - assert!(call_weight != 7, "needed for test to actually trigger a weight mismatch"); + assert!(call_weight > 7, "needed for test to actually trigger a weight mismatch"); System::set_block_number(1); let result = Dispatch::dispatch( diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 31b5280bb039a..a8267e65eb3b7 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -101,6 +101,7 @@ pub mod pallet { } #[pallet::pallet] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 37d93df779bf7..bfc749d5230c6 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -77,6 +77,7 @@ impl frame_system::Config for TestRuntime { type BlockLength = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index c145687af994f..d67b82ade8d2d 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -145,7 +145,7 @@ fn pay_relayers_rewards( relayer_fund_account: &AccountId, confirmation_fee: Currency::Balance, ) where - AccountId: Debug + Default + Encode + PartialEq, + AccountId: Debug + Encode + PartialEq, Currency: CurrencyT, Currency::Balance: From, { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 66bfecd2592b2..f37dc88481e8d 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -209,6 +209,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::call] @@ -2116,6 +2117,7 @@ mod tests { #[test] #[should_panic] + #[cfg(debug_assertions)] fn receive_messages_panics_in_debug_mode_if_callback_is_wrong() { run_test(|| { TestOnDeliveryConfirmed1::set_consumed_weight_per_message( @@ -2248,6 +2250,7 @@ mod tests { #[test] #[should_panic] + #[cfg(debug_assertions)] fn message_accepted_panics_in_debug_mode_if_callback_is_wrong() { run_test(|| { TestOnMessageAccepted::set_consumed_weight_per_message( diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index a333c95bb58b8..ef5081472279b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -125,6 +125,7 @@ impl frame_system::Config for TestRuntime { type DbWeight = DbWeight; type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 06d0b3fb0f8d4..9cf84412575a8 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -35,6 +35,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData); #[pallet::hooks] @@ -162,6 +163,7 @@ mod tests { type DbWeight = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs index 6ca35f5f39470..c68fb6b64283c 100644 --- a/modules/token-swap/src/benchmarking.rs +++ b/modules/token-swap/src/benchmarking.rs @@ -23,13 +23,13 @@ use crate::{ }; use bp_token_swap::{TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType}; -use codec::Encode; +use codec::{Decode, Encode}; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Currency, Parameter}; use frame_system::RawOrigin; use sp_core::H256; use sp_io::hashing::blake2_256; -use sp_runtime::traits::Bounded; +use sp_runtime::traits::{Bounded, TrailingZeroInput}; use sp_std::{boxed::Box, vec::Vec}; const SEED: u32 = 0; @@ -43,8 +43,8 @@ pub trait Config: crate::Config { benchmarks_instance_pallet! { where_clause { where - BridgedAccountPublicOf: Default + Parameter, - BridgedAccountSignatureOf: Default, + BridgedAccountPublicOf: Decode + Parameter, + BridgedAccountSignatureOf: Decode, } // @@ -138,8 +138,8 @@ fn test_swap_hash, I: 'static>(sender: T::AccountId, is_create: boo /// Returns test token swap creation params. fn test_swap_creation, I: 'static>() -> TokenSwapCreationOf where - BridgedAccountPublicOf: Default, - BridgedAccountSignatureOf: Default, + BridgedAccountPublicOf: Decode, + BridgedAccountSignatureOf: Decode, { TokenSwapCreation { target_public_at_bridged_chain: target_public_at_bridged_chain::(), @@ -176,20 +176,22 @@ fn target_balance_to_swap, I: 'static>() -> BridgedBalanceOf /// Public key of `target_account_at_bridged_chain`. fn target_public_at_bridged_chain, I: 'static>() -> BridgedAccountPublicOf where - BridgedAccountPublicOf: Default, + BridgedAccountPublicOf: Decode, { - Default::default() + BridgedAccountPublicOf::::decode(&mut TrailingZeroInput::zeroes()) + .expect("failed to decode `BridgedAccountPublicOf` from zeroes") } /// Signature of `target_account_at_bridged_chain` over message. fn bridged_currency_transfer_signature, I: 'static>() -> BridgedAccountSignatureOf where - BridgedAccountSignatureOf: Default, + BridgedAccountSignatureOf: Decode, { - Default::default() + BridgedAccountSignatureOf::::decode(&mut TrailingZeroInput::zeroes()) + .expect("failed to decode `BridgedAccountSignatureOf` from zeroes") } /// Account at the bridged chain that is participating in the swap. fn target_account_at_bridged_chain, I: 'static>() -> BridgedAccountIdOf { - Default::default() + account("target_account_at_bridged_chain", 0, SEED) } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 59db89b6fd513..32fd2db3c7cb0 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -179,6 +179,7 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index 2c24e282af629..78b8a3381d3a8 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -91,6 +91,7 @@ impl frame_system::Config for TestRuntime { type DbWeight = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } frame_support::parameter_types! { diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 0f25ac710de65..3fa3993a98a1e 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -41,6 +41,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 5, + state_version: 0, }; // NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 2e671e901c368..d83b4ea433a71 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -30,13 +30,13 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; -use sp_core::Hasher as HasherT; +use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ traits::{Convert, IdentifyAccount, Verify}, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; -use sp_trie::{trie_types::Layout, TrieConfiguration}; +use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -206,12 +206,18 @@ impl sp_core::Hasher for BlakeTwoAndKeccak256 { impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { type Output = MillauHash; - fn trie_root(input: Vec<(Vec, Vec)>) -> Self::Output { - Layout::::trie_root(input) + fn trie_root(input: Vec<(Vec, Vec)>, state_version: StateVersion) -> Self::Output { + match state_version { + StateVersion::V0 => LayoutV0::::trie_root(input), + StateVersion::V1 => LayoutV1::::trie_root(input), + } } - fn ordered_trie_root(input: Vec>) -> Self::Output { - Layout::::ordered_trie_root(input) + fn ordered_trie_root(input: Vec>, state_version: StateVersion) -> Self::Output { + match state_version { + StateVersion::V0 => LayoutV0::::ordered_trie_root(input), + StateVersion::V1 => LayoutV1::::ordered_trie_root(input), + } } } @@ -340,9 +346,9 @@ mod tests { #[test] fn maximal_account_size_does_not_overflow_constant() { assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::default().encode().len(), + AccountId::from([0u8; 32]).encode().len(), MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, ); } diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 19cf1a797062d..31141a25dcf0e 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -41,6 +41,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 7, + state_version: 0, }; // NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index c6cb1bceb87f8..0adb703c13670 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -312,9 +312,9 @@ mod tests { #[test] fn maximal_account_size_does_not_overflow_constant() { assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::default().encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::default().encode().len(), + AccountId::from([0u8; 32]).encode().len(), MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, ); } diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index d485e916cf825..9a7ac9da67da0 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -48,6 +48,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, + state_version: 0, }; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 68bc22c7cdcb6..91f4a61e47e80 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -59,6 +59,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 5, + state_version: 0, }; /// Westend Runtime `Call` enum. diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 85846c6d50f95..5b4981a0f69a8 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -136,7 +136,8 @@ fn justification_with_invalid_commit_rejected() { #[test] fn justification_with_invalid_authority_signature_rejected() { let mut justification = make_default_justification::(&test_header(1)); - justification.commit.precommits[0].signature = Default::default(); + justification.commit.precommits[0].signature = + sp_core::crypto::UncheckedFrom::unchecked_from([1u8; 64]); assert_eq!( verify_justification::( diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 8be9cc17daca5..50e8423437405 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -33,7 +33,8 @@ use scale_info::{StaticTypeInfo, TypeInfo}; use sp_core::Hasher as HasherT; use sp_runtime::{ generic, - traits::{BlakeTwo256, IdentifyAccount, Verify}, + traits::{BlakeTwo256, DispatchInfoOf, IdentifyAccount, Verify}, + transaction_validity::TransactionValidityError, MultiAddress, MultiSignature, OpaqueExtrinsic, }; use sp_std::prelude::Vec; @@ -332,6 +333,16 @@ where ) -> Result { Ok(self.additional_signed) } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, + ) -> Result { + Ok(self.validate(who, call, info, len).map(|_| ())?) + } } /// Polkadot-like chain. @@ -399,7 +410,7 @@ mod tests { #[test] fn maximal_encoded_account_id_size_is_correct() { - let actual_size = AccountId::default().encode().len(); + let actual_size = AccountId::from([0u8; 32]).encode().len(); assert!( actual_size <= MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize, "Actual size of encoded account id for Polkadot-like chains ({}) is larger than expected {}", diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 9dfe6216a7cac..30e754b5702fc 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -83,13 +83,7 @@ pub trait Chain: Send + Sync + 'static { + MaybeSerializeDeserialize; /// The user account identifier type for the runtime. - type AccountId: Parameter - + Member - + MaybeSerializeDeserialize - + Debug - + MaybeDisplay - + Ord - + Default; + type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord; /// Balance of an account in native tokens. /// /// The chain may support multiple tokens, but this particular type is for token that is used diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 9cc5b48ebd913..177b0f8664e4c 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -19,7 +19,7 @@ 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}; +use sp_trie::{read_trie_value, LayoutV1, 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 @@ -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>, Error> { - read_trie_value::, _>(&self.db, &self.root, key) + // LayoutV1 or LayoutV0 is identical for proof that only read values. + read_trie_value::, _>(&self.db, &self.root, key) .map_err(|_| Error::StorageValueUnavailable) } } @@ -70,15 +71,20 @@ pub enum Error { pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; + let state_version = sp_runtime::StateVersion::default(); + // construct storage proof - let backend = >::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 backend = >::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]))]), + ], + state_version, + )); + let root = backend.storage_root(std::iter::empty(), state_version).0; let proof = StorageProof::new( prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) .unwrap() diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index 059d6eb5be4f1..2436d79339236 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -19,7 +19,6 @@ use codec::Encode; use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; use finality_grandpa::voter_set::VoterSet; -use sp_application_crypto::Public; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; @@ -70,7 +69,7 @@ impl Account { impl From for AuthorityId { fn from(p: Account) -> Self { - AuthorityId::from_slice(&p.public().to_bytes()) + sp_application_crypto::UncheckedFrom::unchecked_from(p.public().to_bytes()) } } diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index b409cf383ed7c..707e78378302f 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -343,7 +343,7 @@ mod tests { // then assert!(format!("{:?}", call_hex).starts_with( - "0x0f030000000001000000381409000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ + "0x0f030000000001000000000000000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" )) } diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 98e1269aa68e6..ee77fc4a46efe 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -106,6 +106,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x0100000010f108000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x01000000000000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 2d81576de3dd2..e3597f766b740 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -324,7 +324,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 576000, + weight: 0, origin: CallOrigin::SourceAccount( sp_keyring::AccountKeyring::Alice.to_account_id() ), @@ -366,7 +366,7 @@ mod tests { payload, MessagePayload { spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 576000, + weight: 0, origin: CallOrigin::TargetAccount( sp_keyring::AccountKeyring::Alice.to_account_id(), sp_keyring::AccountKeyring::Bob.into(), diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index f973cef897357..5336e065a92b0 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -290,7 +290,7 @@ where &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - Default::default(), + self.relayer_id_at_source.clone(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), @@ -332,7 +332,7 @@ where &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), - Default::default(), + self.relayer_id_at_source.clone(), nonces.clone(), prepare_dummy_messages_proof::( nonces.clone(), From 46122ceeffd368bbf5b265fad3adad10a2d24061 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 31 Jan 2022 14:43:53 +0300 Subject: [PATCH 0639/1210] bump chain spec versions (#1297) --- primitives/chain-kusama/src/lib.rs | 4 ++-- primitives/chain-polkadot/src/lib.rs | 4 ++-- primitives/chain-westend/src/lib.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 3fa3993a98a1e..953da9f4f0948 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -37,10 +37,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("kusama"), impl_name: sp_version::create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 9100, + spec_version: 9140, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 5, + transaction_version: 8, state_version: 0, }; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 31141a25dcf0e..02c201b72052d 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -37,10 +37,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("polkadot"), impl_name: sp_version::create_runtime_str!("parity-polkadot"), authoring_version: 0, - spec_version: 9100, + spec_version: 9140, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 7, + transaction_version: 9, state_version: 0, }; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 91f4a61e47e80..af0ad27c9bc10 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -55,10 +55,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("westend"), impl_name: sp_version::create_runtime_str!("parity-westend"), authoring_version: 2, - spec_version: 51, + spec_version: 9140, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 5, + transaction_version: 8, state_version: 0, }; From 4e020566f2ecab0b8a783ed021a6ec997f626c30 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 31 Jan 2022 14:44:04 +0300 Subject: [PATCH 0640/1210] Fix ss58 prefixes of Polkadot, Kusama and Westend used by relay (#1298) * fix ss58 prefixes of Polkadot, Kusama and Westend * fmt --- relays/bin-substrate/src/chains/kusama.rs | 5 ++++- relays/bin-substrate/src/chains/polkadot.rs | 5 ++++- relays/bin-substrate/src/chains/westend.rs | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 10afbdd8a5a4d..5a65426c9dc1d 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -81,7 +81,10 @@ impl CliChain for Kusama { type MessagePayload = (); fn ss58_format() -> u16 { - 42 + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::KusamaAccount, + ) + .into() } fn encode_message( diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 8c31792a5430a..16d44f46873f9 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -81,7 +81,10 @@ impl CliChain for Polkadot { type MessagePayload = (); fn ss58_format() -> u16 { - 42 + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::PolkadotAccount, + ) + .into() } fn encode_message( diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 5a3dd9956dc9b..8d3b5db9ab37f 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -28,7 +28,10 @@ impl CliChain for Westend { type MessagePayload = (); fn ss58_format() -> u16 { - 42 + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::SubstrateAccount, + ) + .into() } fn encode_message( From c3cf8b3533b938cd39275d28748b246e3c7a4b6d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 31 Jan 2022 14:44:11 +0300 Subject: [PATCH 0641/1210] Use raw balance value if tokenDecimals property is missing (#1299) * use raw balance value if tokenDecimals property is missing * fmt --- .../lib-substrate-relay/src/messages_metrics.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index d2206094fe7cd..00686ac4fd589 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -202,9 +202,20 @@ where return Ok(metrics) } - let token_decimals = client.token_decimals().await?.ok_or_else(|| { - SubstrateError::Custom(format!("Missing token decimals from {} system properties", C::NAME)) - })?; + // if `tokenDecimals` is missing from system properties, we'll be using + let token_decimals = client + .token_decimals() + .await? + .map(|token_decimals| { + log::info!(target: "bridge", "Read `tokenDecimals` for {}: {}", C::NAME, token_decimals); + token_decimals + }) + .unwrap_or_else(|| { + // turns out it is normal not to have this property - e.g. when polkadot binary is + // started using `polkadot-local` chain. Let's use minimal nominal here + log::info!(target: "bridge", "Using default (zero) `tokenDecimals` value for {}", C::NAME); + 0 + }); let token_decimals = u32::try_from(token_decimals).map_err(|e| { anyhow::format_err!( "Token decimals value ({}) of {} doesn't fit into u32: {:?}", From f99e79f8847409f76c7a9cf9cb8a96fdfc6335b3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 1 Feb 2022 11:05:03 +0300 Subject: [PATCH 0642/1210] fix session length of Rococo and Wococo (#1304) --- primitives/chain-rococo/src/lib.rs | 4 ++-- primitives/chain-wococo/src/lib.rs | 11 +++++++--- relays/bin-substrate/Cargo.toml | 2 +- .../src/on_demand_headers.rs | 22 +++++++++++++++++-- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 9a7ac9da67da0..a47f0277ef545 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -32,12 +32,12 @@ pub use bp_polkadot_core::*; /// Rococo Chain pub type Rococo = PolkadotLike; -/// The target length of a session (how often authorities change) on Westend measured in of number +/// The target length of a session (how often authorities change) on Rococo measured in of number /// of blocks. /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. -pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; +pub const SESSION_LENGTH: BlockNumber = 1 * time_units::HOURS; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 4f715c3994aae..a05a2ad46a933 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -25,13 +25,18 @@ use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime -pub use bp_rococo::{ - WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, SESSION_LENGTH, VERSION, -}; +pub use bp_rococo::{WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, VERSION}; /// Wococo Chain pub type Wococo = PolkadotLike; +/// The target length of a session (how often authorities change) on Wococo measured in of number +/// of blocks. +/// +/// Note that since this is a target sessions may change before/after this time depending on network +/// conditions. +pub const SESSION_LENGTH: BlockNumber = 1 * time_units::MINUTES; + // We use this to get the account on Wococo (target) which is derived from Rococo's (source) // account. pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 86c1cedf375dd..0bfff98d18655 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-relay" -version = "1.0.0" +version = "1.0.1" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index d66aaba549e28..2e8a6db7983c6 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -192,8 +192,25 @@ async fn background_task( // there are no (or we don't need to relay them) mandatory headers in the range // => to avoid scanning the same headers over and over again, remember that latest_non_mandatory_at_source = mandatory_scan_range.1; + + log::trace!( + target: "bridge", + "No mandatory {} headers in the range {:?} of {} relay", + P::SourceChain::NAME, + mandatory_scan_range, + relay_task_name, + ); }, - Err(e) => + Err(e) => { + log::warn!( + target: "bridge", + "Failed to scan mandatory {} headers range in {} relay (range: {:?}): {:?}", + P::SourceChain::NAME, + relay_task_name, + mandatory_scan_range, + e, + ); + if e.is_connection_error() { relay_utils::relay_loop::reconnect_failed_client( FailedClient::Source, @@ -203,7 +220,8 @@ async fn background_task( ) .await; continue - }, + } + }, } } From 6211a515598837c5e8e5d2a4786b009a2abcb69a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 2 Feb 2022 14:31:53 +0300 Subject: [PATCH 0643/1210] Fix mandatory headers scanning in on-demand relay (#1306) * more logging in on-demand headerss * remove `maximal_headers_difference` concept from on-demand-relay * another leftover from previous on-demand version * removed extra log * fmt --- .../src/cli/relay_headers_and_messages.rs | 16 ---- .../src/on_demand_headers.rs | 92 +++++++++---------- 2 files changed, 44 insertions(+), 64 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 11220af3e7e8f..4a4d24964fc5e 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -133,10 +133,6 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_millau::AccountIdConverter; type RightAccountIdConverter = bp_rialto::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = - bp_millau::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = - bp_rialto::SESSION_LENGTH; const LEFT_RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); const RIGHT_RUNTIME_VERSION: Option = @@ -185,11 +181,6 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_rococo::AccountIdConverter; type RightAccountIdConverter = bp_wococo::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = - bp_rococo::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = - bp_wococo::SESSION_LENGTH; - const LEFT_RUNTIME_VERSION: Option = Some(bp_rococo::VERSION); const RIGHT_RUNTIME_VERSION: Option = @@ -268,11 +259,6 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_kusama::AccountIdConverter; type RightAccountIdConverter = bp_polkadot::AccountIdConverter; - const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_kusama::BlockNumber = - bp_kusama::SESSION_LENGTH; - const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_polkadot::BlockNumber = - bp_polkadot::SESSION_LENGTH; - const LEFT_RUNTIME_VERSION: Option = Some(bp_kusama::VERSION); const RIGHT_RUNTIME_VERSION: Option = @@ -543,14 +529,12 @@ impl RelayHeadersAndMessages { left_client.clone(), right_client.clone(), left_to_right_transaction_params, - MAX_MISSING_LEFT_HEADERS_AT_RIGHT, params.shared.only_mandatory_headers, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::( right_client.clone(), left_client.clone(), right_to_left_transaction_params, - MAX_MISSING_RIGHT_HEADERS_AT_LEFT, params.shared.only_mandatory_headers, ); diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 2e8a6db7983c6..9a6a062d7d8e0 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -18,7 +18,7 @@ use async_std::sync::{Arc, Mutex}; use futures::{select, FutureExt}; -use num_traits::{CheckedSub, One, Zero}; +use num_traits::{One, Zero}; use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient}; use relay_substrate_client::{ @@ -55,7 +55,6 @@ impl OnDemandHeadersRelay { source_client: Client, target_client: Client, target_transaction_params: TransactionParams>, - maximal_headers_difference: BlockNumberOf, only_mandatory_headers: bool, ) -> Self where @@ -73,7 +72,6 @@ impl OnDemandHeadersRelay { source_client, target_client, target_transaction_params, - maximal_headers_difference, only_mandatory_headers, required_header_number, ) @@ -105,7 +103,6 @@ async fn background_task( source_client: Client, target_client: Client, target_transaction_params: TransactionParams>, - maximal_headers_difference: BlockNumberOf, only_mandatory_headers: bool, required_header_number: RequiredHeaderNumberRef, ) where @@ -165,15 +162,28 @@ async fn background_task( } // submit mandatory header if some headers are missing + let best_finalized_source_header_at_source_fmt = + format!("{:?}", best_finalized_source_header_at_source); let best_finalized_source_header_at_target_fmt = format!("{:?}", best_finalized_source_header_at_target); + let required_header_number_value = *required_header_number.lock().await; let mandatory_scan_range = mandatory_headers_scan_range::( best_finalized_source_header_at_source.ok(), best_finalized_source_header_at_target.ok(), - maximal_headers_difference, - &required_header_number, + required_header_number_value, ) .await; + + log::trace!( + target: "bridge", + "Mandatory headers scan range in {}: ({:?}, {:?}, {:?}) -> {:?}", + relay_task_name, + required_header_number_value, + best_finalized_source_header_at_source_fmt, + best_finalized_source_header_at_target_fmt, + mandatory_scan_range, + ); + if let Some(mandatory_scan_range) = mandatory_scan_range { let relay_mandatory_header_result = relay_mandatory_header_from_range( &finality_source, @@ -227,6 +237,25 @@ async fn background_task( // start/restart relay if restart_relay { + let stall_timeout = relay_substrate_client::transaction_stall_timeout( + target_transactions_mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); + + log::info!( + target: "bridge", + "Starting {} relay\n\t\ + Only mandatory headers: {}\n\t\ + Tx mortality: {:?} (~{}m)\n\t\ + Stall timeout: {:?}", + relay_task_name, + only_mandatory_headers, + target_transactions_mortality, + stall_timeout.as_secs_f64() / 60.0f64, + stall_timeout, + ); + finality_relay_task.set( finality_relay::run( finality_source.clone(), @@ -237,11 +266,7 @@ async fn background_task( P::TargetChain::AVERAGE_BLOCK_INTERVAL, ), recent_finality_proofs_limit: RECENT_FINALITY_PROOFS_LIMIT, - stall_timeout: relay_substrate_client::transaction_stall_timeout( - target_transactions_mortality, - P::TargetChain::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ), + stall_timeout, only_mandatory_headers, }, MetricsParams::disabled(), @@ -260,11 +285,8 @@ async fn background_task( async fn mandatory_headers_scan_range( best_finalized_source_header_at_source: Option, best_finalized_source_header_at_target: Option, - maximal_headers_difference: C::BlockNumber, - required_header_number: &RequiredHeaderNumberRef, + required_header_number: BlockNumberOf, ) -> Option<(C::BlockNumber, C::BlockNumber)> { - let required_header_number = *required_header_number.lock().await; - // if we have been unable to read header number from the target, then let's assume // that it is the same as required header number. Otherwise we risk submitting // unneeded transactions @@ -276,23 +298,8 @@ async fn mandatory_headers_scan_range( let best_finalized_source_header_at_source = best_finalized_source_header_at_source.unwrap_or(best_finalized_source_header_at_target); - // if there are too many source headers missing from the target node, sync mandatory - // headers to target - // - // why do we need that? When complex headers+messages relay is used, it'll normally only relay - // headers when there are undelivered messages/confirmations. But security model of the - // `pallet-bridge-grandpa` module relies on the fact that headers are synced in real-time and - // that it'll see authorities-change header before unbonding period will end for previous - // authorities set. - let current_headers_difference = best_finalized_source_header_at_source - .checked_sub(&best_finalized_source_header_at_target) - .unwrap_or_else(Zero::zero); - if current_headers_difference <= maximal_headers_difference { - return None - } - - // if relay is already asked to sync headers, don't do anything yet - if required_header_number > best_finalized_source_header_at_target { + // if relay is already asked to sync more headers than we have at source, don't do anything yet + if required_header_number >= best_finalized_source_header_at_source { return None } @@ -423,29 +430,18 @@ mod tests { const AT_TARGET: Option = Some(1); #[async_std::test] - async fn mandatory_headers_scan_range_selects_range_if_too_many_headers_are_missing() { + async fn mandatory_headers_scan_range_selects_range_if_some_headers_are_missing() { assert_eq!( - mandatory_headers_scan_range::( - AT_SOURCE, - AT_TARGET, - 5, - &Arc::new(Mutex::new(0)) - ) - .await, + mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, 0,).await, Some((AT_TARGET.unwrap() + 1, AT_SOURCE.unwrap())), ); } #[async_std::test] - async fn mandatory_headers_scan_range_selects_nothing_if_enough_headers_are_relayed() { + async fn mandatory_headers_scan_range_selects_nothing_if_already_queued() { assert_eq!( - mandatory_headers_scan_range::( - AT_SOURCE, - AT_TARGET, - 10, - &Arc::new(Mutex::new(0)) - ) - .await, + mandatory_headers_scan_range::(AT_SOURCE, AT_TARGET, AT_SOURCE.unwrap(),) + .await, None, ); } From d9c8b4391050a204e0cd228e6859b06c42f9c00e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 3 Feb 2022 16:03:44 +0300 Subject: [PATCH 0644/1210] increase relay balance guard limits for Polkadot<>Kusama bridge (#1308) --- .../src/chains/kusama_headers_to_polkadot.rs | 9 +++++++-- .../src/chains/polkadot_headers_to_kusama.rs | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index f3a2d553045f7..0c0ba2272c7e9 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -24,8 +24,13 @@ use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, T /// relay as gone wild. /// /// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 21 -/// DOT, but let's round up to 30 DOT here. -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 30_000_000_000; +/// DOT, and initial value of this constant was rounded up to 30 DOT. But for actual Kusama <> +/// Polkadot deployment we'll be using the same account for delivering finality (free for mandatory +/// headers) and messages. It means that we can't predict maximal loss. But to protect funds against +/// relay/deployment issues, let's limit it so something that is much larger than this estimation - +/// e.g. to 100 DOT. +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1307 +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100 * 10_000_000_000; /// Description of Kusama -> Polkadot finalized headers bridge. #[derive(Clone, Debug)] diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index 27bcb2457896d..6d118b07caa5b 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -24,8 +24,13 @@ use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, T /// relay as gone wild. /// /// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 0.001 -/// KSM, but let's round up to 0.1 KSM here. -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100_000_000_000; +/// KSM, and initial value of this constant was rounded up to 0.1 KSM. But for actual Kusama <> +/// Polkadot deployment we'll be using the same account for delivering finality (free for mandatory +/// headers) and messages. It means that we can't predict maximal loss. But to protect funds against +/// relay/deployment issues, let's limit it so something that is much larger than this estimation - +/// e.g. to 2 KSM. +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1307 +pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_kusama::Balance = 2 * 1_000_000_000_000; /// Description of Polkadot -> Kusama finalized headers bridge. #[derive(Clone, Debug)] From dd1d646b9f35cb3be18248e8447f596c84322521 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 4 Feb 2022 12:48:56 +0300 Subject: [PATCH 0645/1210] fix benchmarks before using it in Polkadot/Kusama/Rococo runtimes (#1309) --- bin/millau/runtime/src/lib.rs | 2 +- .../src/messages_benchmarking.rs | 7 +++--- modules/messages/src/benchmarking.rs | 23 ++++++++++++++----- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index e0c3903621709..67ac2abfe8391 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -860,7 +860,7 @@ impl_runtime_apis! { fn prepare_outbound_message( params: MessageParams, ) -> (rialto_messages::ToRialtoMessagePayload, Balance) { - prepare_outbound_message::(params) + (prepare_outbound_message::(params), Self::message_fee()) } fn prepare_message_proof( diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 12c270d8666fd..b55442855c953 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -46,7 +46,7 @@ use sp_version::RuntimeVersion; /// Prepare outbound message for the `send_message` call. pub fn prepare_outbound_message( params: MessageParams>>, -) -> (FromThisChainMessagePayload, BalanceOf>) +) -> FromThisChainMessagePayload where B: MessageBridge, BalanceOf>: From, @@ -54,14 +54,13 @@ where let message_payload = vec![0; params.size as usize]; let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount(params.sender_account); - let message = FromThisChainMessagePayload:: { + FromThisChainMessagePayload:: { spec_version: 0, weight: params.size as _, origin: dispatch_origin, call: message_payload, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - }; - (message, pallet_bridge_messages::benchmarking::MESSAGE_FEE.into()) + } } /// Prepare proof of messages for the `receive_messages_proof` call. diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 288ef4b2e8187..c0ad31460b693 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -32,9 +32,6 @@ use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; use sp_std::{collections::vec_deque::VecDeque, convert::TryInto, ops::RangeInclusive, prelude::*}; -/// Fee paid by submitter for single message delivery. -pub const MESSAGE_FEE: u64 = 100_000_000_000; - const SEED: u32 = 0; /// Pallet we're benchmarking here. @@ -103,6 +100,10 @@ pub trait Config: crate::Config { fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee; /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); + /// Fee paid by submitter for single message delivery. + fn message_fee() -> Self::OutboundMessageFee { + 100_000_000_000_000.into() + } /// Prepare message to send over lane. fn prepare_outbound_message( params: MessageParams, @@ -138,8 +139,10 @@ benchmarks_instance_pallet! { // added. send_minimal_message_worst_case { let lane_id = T::bench_lane_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -169,8 +172,10 @@ benchmarks_instance_pallet! { // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_1_kb_message_worst_case { let lane_id = T::bench_lane_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -206,8 +211,10 @@ benchmarks_instance_pallet! { // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_16_kb_message_worst_case { let lane_id = T::bench_lane_id(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -239,8 +246,10 @@ benchmarks_instance_pallet! { // // Result of this benchmark is directly used by weight formula of the call. maximal_increase_message_fee { + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 42, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); let additional_fee = T::account_balance(&sender); let lane_id = T::bench_lane_id(); @@ -258,8 +267,10 @@ benchmarks_instance_pallet! { increase_message_fee { let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); + let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 42, SEED); T::endow_account(&sender); + T::endow_account(&relayers_fund_id); let additional_fee = T::account_balance(&sender); let lane_id = T::bench_lane_id(); @@ -506,7 +517,7 @@ benchmarks_instance_pallet! { verify { assert_eq!( T::account_balance(&relayer_id), - relayer_balance + MESSAGE_FEE.into(), + relayer_balance + T::message_fee(), ); } @@ -600,12 +611,12 @@ benchmarks_instance_pallet! { fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { payload: vec![], fee: MESSAGE_FEE.into() }); + outbound_lane.send_message(MessageData { payload: vec![], fee: T::message_fee() }); } fn send_regular_message_with_payload, I: 'static>(payload: Vec) { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { payload, fee: MESSAGE_FEE.into() }); + outbound_lane.send_message(MessageData { payload, fee: T::message_fee() }); } fn confirm_message_delivery, I: 'static>(nonce: MessageNonce) { From b5372283e14e0da05cf387eab7a90c662ae894a3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 4 Feb 2022 17:28:57 +0300 Subject: [PATCH 0646/1210] Endow relayer account at target chain in message benchmarks (#1310) * endow relayer account at target chain in message benchmarks * pick another line --- .../src/messages_benchmarking.rs | 32 +++++++++++++++---- modules/messages/src/benchmarking.rs | 6 ++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index b55442855c953..7c9f50e8ea0ce 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -43,6 +43,29 @@ use sp_std::{fmt::Debug, prelude::*}; use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; use sp_version::RuntimeVersion; +/// Return this chain account, used to dispatch message. +pub fn dispatch_account() -> AccountIdOf> +where + B: MessageBridge, + SignerOf>: + From + IdentifyAccount>>, +{ + let this_raw_public = PublicKey::from(&dispatch_account_secret()); + let this_public: SignerOf> = + sp_core::ed25519::Public::from_raw(this_raw_public.to_bytes()).into(); + this_public.into_account() +} + +/// Return public key of this chain account, used to dispatch message. +pub fn dispatch_account_secret() -> SecretKey { + // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) + SecretKey::from_bytes(&[ + 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, + 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, + ]) + .expect("harcoded key is valid") +} + /// Prepare outbound message for the `send_message` call. pub fn prepare_outbound_message( params: MessageParams>>, @@ -82,6 +105,7 @@ where FI: 'static, BH: Header>>, BHH: Hasher>>, + AccountIdOf>: PartialEq + sp_std::fmt::Debug, AccountIdOf>: From<[u8; 32]>, BalanceOf>: Debug + MaybeSerializeDeserialize, CallOf>: From> + GetDispatchInfo, @@ -116,6 +140,7 @@ where // if dispatch fee is paid at this chain, endow relayer account if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { + assert_eq!(this_public.clone().into_account(), dispatch_account::()); pallet_balances::Pallet::::make_free_balance_be( &this_public.clone().into_account(), endow_amount, @@ -298,12 +323,7 @@ fn ed25519_sign( source_chain_id: ChainId, target_chain_id: ChainId, ) -> ([u8; 32], [u8; 64]) { - // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) - let target_secret = SecretKey::from_bytes(&[ - 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, - 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, - ]) - .expect("harcoded key is valid"); + let target_secret = dispatch_account_secret(); let target_public: PublicKey = (&target_secret).into(); let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index c0ad31460b693..46a8150d034bd 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -293,6 +293,7 @@ benchmarks_instance_pallet! { receive_single_message_proof { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -327,6 +328,7 @@ benchmarks_instance_pallet! { receive_two_messages_proof { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -361,6 +363,7 @@ benchmarks_instance_pallet! { receive_single_message_proof_with_outbound_lane_state { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -396,6 +399,7 @@ benchmarks_instance_pallet! { receive_single_message_proof_1_kb { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -430,6 +434,7 @@ benchmarks_instance_pallet! { receive_single_message_proof_16_kb { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); @@ -463,6 +468,7 @@ benchmarks_instance_pallet! { receive_single_prepaid_message_proof { let relayer_id_on_source = T::bridged_relayer_id(); let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); // mark messages 1..=20 as delivered receive_messages::(20); From 364e9dd0e76d89be67b81d4ab36dd22eb59105a0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 7 Feb 2022 17:37:28 +0300 Subject: [PATCH 0647/1210] expose fee multiplier metrics in messages relay (#1312) --- primitives/chain-kusama/src/lib.rs | 5 + primitives/chain-polkadot/src/lib.rs | 7 +- primitives/runtime/src/lib.rs | 31 +++++- .../src/chains/kusama_messages_to_polkadot.rs | 10 ++ .../src/chains/millau_messages_to_rialto.rs | 5 + .../src/chains/polkadot_messages_to_kusama.rs | 10 ++ .../src/chains/rialto_messages_to_millau.rs | 5 + .../src/chains/rococo_messages_to_wococo.rs | 5 + .../src/chains/wococo_messages_to_rococo.rs | 5 + relays/lib-substrate-relay/Cargo.toml | 1 + .../lib-substrate-relay/src/messages_lane.rs | 22 +++- .../src/messages_metrics.rs | 104 +++++++++++++++++- 12 files changed, 203 insertions(+), 7 deletions(-) diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 953da9f4f0948..f5ed359a60689 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -87,9 +87,14 @@ pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; /// Name of the With-Kusama messages pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; +/// Name of the transaction payment pallet at the Kusama runtime. +pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; + /// Name of the DOT->KSM conversion rate stored in the Kusama runtime. pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = "PolkadotToKusamaConversionRate"; +/// Name of the Polkadot fee multiplier parameter, stored in the Polkadot runtime. +pub const POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME: &str = "PolkadotFeeMultiplier"; /// Name of the `KusamaFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 02c201b72052d..2983e7f2ce6b9 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -87,9 +87,14 @@ pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; /// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; -/// Name of the KSM->DOT conversion rate stored in the Polkadot runtime. +/// Name of the transaction payment pallet at the Polkadot runtime. +pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; + +/// Name of the KSM->DOT conversion rate parameter, stored in the Polkadot runtime. pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = "KusamaToPolkadotConversionRate"; +/// Name of the Kusama fee multiplier parameter, stored in the Polkadot runtime. +pub const KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME: &str = "KusamaFeeMultiplier"; /// Name of the `PolkadotFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index c01e7bb305a7f..f69afca4c0851 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -22,7 +22,7 @@ use codec::Encode; use frame_support::{RuntimeDebug, StorageHasher}; use sp_core::{hash::H256, storage::StorageKey}; use sp_io::hashing::blake2_256; -use sp_std::{convert::TryFrom, vec::Vec}; +use sp_std::{convert::TryFrom, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, @@ -229,7 +229,7 @@ pub fn storage_map_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 +/// 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); buffer.push(b':'); @@ -238,6 +238,20 @@ pub fn storage_parameter_key(parameter_name: &str) -> StorageKey { StorageKey(sp_io::hashing::twox_128(&buffer).to_vec()) } +/// This is how a storage key of storage value is computed. +/// +/// Copied from `frame_support::storage::storage_prefix`. +pub fn storage_value_key(pallet_prefix: &str, value_name: &str) -> StorageKey { + let pallet_hash = sp_io::hashing::twox_128(pallet_prefix.as_bytes()); + let storage_hash = sp_io::hashing::twox_128(value_name.as_bytes()); + + let mut final_key = vec![0u8; 32]; + final_key[..16].copy_from_slice(&pallet_hash); + final_key[16..].copy_from_slice(&storage_hash); + + StorageKey(final_key) +} + #[cfg(test)] mod tests { use super::*; @@ -249,4 +263,17 @@ mod tests { StorageKey(hex_literal::hex!("58942375551bb0af1682f72786b59d04").to_vec()), ); } + + #[test] + fn storage_value_key_works() { + assert_eq!( + storage_value_key("PalletTransactionPayment", "NextFeeMultiplier"), + StorageKey( + hex_literal::hex!( + "f0e954dfcca51a255ab12c60c789256a3f2edf3bdf381debe331ab7446addfdc" + ) + .to_vec() + ), + ); + } } diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 82a3206b0d916..5c0b91d8ffe35 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -48,6 +48,16 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME); + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME); + + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_kusama::TRANSACTION_PAYMENT_PALLET_NAME); + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_polkadot::TRANSACTION_PAYMENT_PALLET_NAME); + type SourceChain = Kusama; type TargetChain = Polkadot; diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index a496602943554..906141e2f2be7 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -38,6 +38,11 @@ impl SubstrateMessageLane for MillauMessagesToRialto { const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + type SourceChain = Millau; type TargetChain = Rialto; diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 5eeb0df3f1288..65b1ce9b06dc8 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -48,6 +48,16 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_kusama::POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME); + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_polkadot::KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME); + + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_polkadot::TRANSACTION_PAYMENT_PALLET_NAME); + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_kusama::TRANSACTION_PAYMENT_PALLET_NAME); + type SourceChain = Polkadot; type TargetChain = Kusama; diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 4c7ad8e621913..4a570050f4eb8 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -38,6 +38,11 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + type SourceChain = Rialto; type TargetChain = Millau; diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index a85789bb1bed2..48e41d02da4e0 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -42,6 +42,11 @@ impl SubstrateMessageLane for RococoMessagesToWococo { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + type SourceChain = Rococo; type TargetChain = Wococo; diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 7c599e413946d..33d7d9adfcc42 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -43,6 +43,11 @@ impl SubstrateMessageLane for WococoMessagesToRococo { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + type SourceChain = Wococo; type TargetChain = Rococo; diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 5733e398f37dd..482aa8d947edb 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -47,6 +47,7 @@ bp-millau = { path = "../../primitives/chain-millau" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } relay-rococo-client = { path = "../client-rococo" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 380d1c9624f32..a88b9441cd1ee 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -43,19 +43,37 @@ use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; /// Substrate -> Substrate messages synchronization pipeline. pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { - /// Name of the source -> target tokens conversion rate parameter name. + /// Name of the source -> target tokens conversion rate parameter. /// /// The parameter is stored at the target chain and the storage key is computed using /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed /// to be 1. const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; - /// Name of the target -> source tokens conversion rate parameter name. + /// Name of the target -> source tokens conversion rate parameter. /// /// The parameter is stored at the source chain and the storage key is computed using /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed /// to be 1. const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; + /// Name of the source chain fee multiplier parameter. + /// + /// The parameter is stored at the target chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str>; + /// Name of the target chain fee multiplier parameter. + /// + /// The parameter is stored at the source chain and the storage key is computed using + /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed + /// to be 1. + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str>; + + /// Name of the transaction payment pallet, deployed at the source chain. + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; + /// Name of the transaction payment pallet, deployed at the target chain. + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; + /// Messages of this chain are relayed to the `TargetChain`. type SourceChain: ChainWithMessages; /// Messages from the `SourceChain` are dispatched on this chain. diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 00686ac4fd589..9e303cebc1d7b 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -34,6 +34,9 @@ use sp_core::storage::StorageData; use sp_runtime::{FixedPointNumber, FixedU128}; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; +/// Name of the `NextFeeMultiplier` storage value within the transaction payment pallet. +const NEXT_FEE_MULTIPLIER_VALUE_NAME: &str = "NextFeeMultiplier"; + /// Shared references to the standalone metrics of the message lane relay loop. #[derive(Debug, Clone)] pub struct StandaloneMessagesMetrics { @@ -53,6 +56,15 @@ pub struct StandaloneMessagesMetrics { /// Target tokens to source tokens conversion rate metric. This rate is stored by the source /// chain. pub target_to_source_conversion_rate: Option>, + + /// Actual source chain fee multiplier. + pub source_fee_multiplier: Option>, + /// Source chain fee multiplier, stored at the target chain. + pub source_fee_multiplier_at_target: Option>, + /// Actual target chain fee multiplier. + pub target_fee_multiplier: Option>, + /// Target chain fee multiplier, stored at the target chain. + pub target_fee_multiplier_at_source: Option>, } impl StandaloneMessagesMetrics { @@ -66,6 +78,10 @@ impl StandaloneMessagesMetrics { target_to_base_conversion_rate: self.source_to_base_conversion_rate, source_to_target_conversion_rate: self.target_to_source_conversion_rate, target_to_source_conversion_rate: self.source_to_target_conversion_rate, + source_fee_multiplier: self.target_fee_multiplier, + source_fee_multiplier_at_target: self.target_fee_multiplier_at_source, + target_fee_multiplier: self.source_fee_multiplier, + target_fee_multiplier_at_source: self.source_fee_multiplier_at_target, } } @@ -86,6 +102,18 @@ impl StandaloneMessagesMetrics { if let Some(m) = self.target_to_source_conversion_rate { m.register_and_spawn(&metrics.registry)?; } + if let Some(m) = self.source_fee_multiplier { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.source_fee_multiplier_at_target { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_fee_multiplier { + m.register_and_spawn(&metrics.registry)?; + } + if let Some(m) = self.target_fee_multiplier_at_source { + m.register_and_spawn(&metrics.registry)?; + } Ok(metrics) } @@ -144,7 +172,7 @@ pub fn standalone_metrics( .map(|key| { FloatStorageValueMetric::new( FixedU128OrOne::default(), - target_client, + target_client.clone(), key, format!( "{}_{}_to_{}_conversion_rate", @@ -167,7 +195,7 @@ pub fn standalone_metrics( .map(|key| { FloatStorageValueMetric::new( FixedU128OrOne::default(), - source_client, + source_client.clone(), key, format!( "{}_{}_to_{}_conversion_rate", @@ -185,6 +213,68 @@ pub fn standalone_metrics( .map(Some) }) .unwrap_or(Ok(None))?, + source_fee_multiplier: P::AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME + .map(|pallet| bp_runtime::storage_value_key(pallet, NEXT_FEE_MULTIPLIER_VALUE_NAME)) + .map(|key| { + log::trace!(target: "bridge", "{}_fee_multiplier", P::SourceChain::NAME); + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + source_client.clone(), + key, + format!("{}_fee_multiplier", P::SourceChain::NAME,), + format!("{} fee multiplier", P::SourceChain::NAME,), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + source_fee_multiplier_at_target: P::SOURCE_FEE_MULTIPLIER_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + target_client.clone(), + key, + format!("{}_{}_fee_multiplier", P::TargetChain::NAME, P::SourceChain::NAME,), + format!( + "{} fee multiplier stored at {}", + P::SourceChain::NAME, + P::TargetChain::NAME, + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_fee_multiplier: P::AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME + .map(|pallet| bp_runtime::storage_value_key(pallet, NEXT_FEE_MULTIPLIER_VALUE_NAME)) + .map(|key| { + log::trace!(target: "bridge", "{}_fee_multiplier", P::TargetChain::NAME); + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + target_client, + key, + format!("{}_fee_multiplier", P::TargetChain::NAME,), + format!("{} fee multiplier", P::TargetChain::NAME,), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, + target_fee_multiplier_at_source: P::TARGET_FEE_MULTIPLIER_PARAMETER_NAME + .map(bp_runtime::storage_parameter_key) + .map(|key| { + FloatStorageValueMetric::new( + FixedU128OrOne::default(), + source_client, + key, + format!("{}_{}_fee_multiplier", P::SourceChain::NAME, P::TargetChain::NAME,), + format!( + "{} fee multiplier stored at {}", + P::TargetChain::NAME, + P::SourceChain::NAME, + ), + ) + .map(Some) + }) + .unwrap_or(Ok(None))?, }) } @@ -286,6 +376,8 @@ fn convert_to_token_balance(balance: u128, token_decimals: u32) -> FixedU128 { #[cfg(test)] mod tests { use super::*; + use frame_support::storage::generator::StorageValue; + use sp_core::storage::StorageKey; #[async_std::test] async fn target_to_source_conversion_rate_works() { @@ -302,4 +394,12 @@ mod tests { let dots = convert_to_token_balance(plancks, token_decimals); assert_eq!(dots, FixedU128::saturating_from_rational(425, 10)); } + + #[test] + fn next_fee_multiplier_storage_key_is_correct() { + assert_eq!( + bp_runtime::storage_value_key("TransactionPayment", NEXT_FEE_MULTIPLIER_VALUE_NAME), + StorageKey(pallet_transaction_payment::NextFeeMultiplier::::storage_value_final_key().to_vec()), + ); + } } From 18d806987684804a37dc4bb263a8a3e95097131f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 7 Feb 2022 17:46:03 +0300 Subject: [PATCH 0648/1210] Fix issues from cargo deny (#1311) * update libp2p-core (RUSTSEC-2022-0009) * update thread_local (RUSTSEC-2022-0006) * time 0.2 -> time 0.3 * ignore RUSTSEC-2021-0130 * proper migration to time 0.3 * fix clippy? * Revert "fix clippy?" This reverts commit 53bc289631769071848e43976871304782486fed. --- relays/utils/Cargo.toml | 2 +- relays/utils/src/initialize.rs | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index a08c3b3d688df..7996ba72f87bb 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -19,7 +19,7 @@ log = "0.4.11" num-traits = "0.2" serde_json = "1.0" sysinfo = "0.15" -time = "0.2" +time = { version = "0.3", features = ["formatting", "local-offset", "std"] } thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index 8c13a4d61cb3a..ad69a766e6236 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -29,15 +29,21 @@ pub fn initialize_relay() { /// Initialize Relay logger instance. pub fn initialize_logger(with_timestamp: bool) { + let format = time::format_description::parse( + "[year]-[month]-[day] \ + [hour repr:24]:[minute]:[second] [offset_hour sign:mandatory]", + ) + .expect("static format string is valid"); + let mut builder = env_logger::Builder::new(); builder.filter_level(log::LevelFilter::Warn); builder.filter_module("bridge", log::LevelFilter::Info); builder.parse_default_env(); if with_timestamp { builder.format(move |buf, record| { - let timestamp = time::OffsetDateTime::try_now_local() - .unwrap_or_else(|_| time::OffsetDateTime::now_utc()) - .format("%Y-%m-%d %H:%M:%S %z"); + let timestamp = time::OffsetDateTime::now_local() + .unwrap_or_else(|_| time::OffsetDateTime::now_utc()); + let timestamp = timestamp.format(&format).unwrap_or_else(|_| timestamp.to_string()); let log_level = color_level(record.level()); let log_target = color_target(record.target()); From d3aedbad42400634aee02112c0784fa0605a8d2d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 11 Feb 2022 11:06:53 +0300 Subject: [PATCH 0649/1210] Add some tests to check integrity of chain constants + bridge configuration (#1316) * add some tests to check integrity of chain constants + bridge configuration * try to use named parameters where possible --- bin/millau/runtime/Cargo.toml | 4 + bin/millau/runtime/src/lib.rs | 43 --- bin/millau/runtime/src/rialto_messages.rs | 104 +++++++ bin/rialto/runtime/Cargo.toml | 2 + bin/rialto/runtime/src/lib.rs | 43 --- bin/rialto/runtime/src/millau_messages.rs | 104 ++++++- bin/runtime-common/Cargo.toml | 5 + bin/runtime-common/src/integrity.rs | 331 ++++++++++++++++++++++ bin/runtime-common/src/lib.rs | 3 + modules/grandpa/src/lib.rs | 2 +- 10 files changed, 550 insertions(+), 91 deletions(-) create mode 100644 bin/runtime-common/src/integrity.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 4fe2f72a962c5..b7bed40a5d17c 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -65,6 +65,10 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } +static_assertions = "1.1" + [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 67ac2abfe8391..b578cb7217b8c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -951,49 +951,6 @@ where #[cfg(test)] mod tests { use super::*; - use bp_runtime::Chain; - use bridge_runtime_common::messages; - - #[test] - fn ensure_millau_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::MillauWeight; - - pallet_bridge_messages::ensure_weights_are_correct::( - bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, - DbWeight::get(), - ); - - let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - bp_millau::Millau::max_extrinsic_size(), - bp_millau::Millau::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::Millau::max_extrinsic_weight(), - ), - ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, - ) - .unwrap_or(u32::MAX); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_millau::Millau::max_extrinsic_size(), - bp_millau::Millau::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - DbWeight::get(), - ); - } #[test] fn call_size() { diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 4403c423c2c1f..0e86505d846ab 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -289,3 +289,107 @@ impl MessagesParameter for MillauToRialtoMessagesParameter { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{DbWeight, RialtoGrandpaInstance, Runtime, WithRialtoMessagesInstance}; + + use bp_runtime::Chain; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, + AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, + }, + messages, + }; + + #[test] + fn ensure_millau_message_lane_weights_are_correct() { + type Weights = pallet_bridge_messages::weights::MillauWeight; + + pallet_bridge_messages::ensure_weights_are_correct::( + bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, + DbWeight::get(), + ); + + let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( + messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), + ); + pallet_bridge_messages::ensure_able_to_receive_message::( + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), + max_incoming_message_proof_size, + messages::target::maximal_incoming_message_dispatch_weight( + bp_millau::Millau::max_extrinsic_weight(), + ), + ); + + let max_incoming_inbound_lane_data_proof_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, + ) + .unwrap_or(u32::MAX); + pallet_bridge_messages::ensure_able_to_receive_confirmation::( + bp_millau::Millau::max_extrinsic_size(), + bp_millau::Millau::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + DbWeight::get(), + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: RialtoGrandpaInstance, + with_bridged_chain_messages_instance: WithRialtoMessagesInstance, + bridge: WithRialtoMessageBridge, + this_chain: bp_millau::Millau, + bridged_chain: bp_rialto::Rialto, + this_chain_account_id_converter: bp_millau::AccountIdConverter + ); + + assert_complete_bridge_constants::< + Runtime, + RialtoGrandpaInstance, + WithRialtoMessagesInstance, + WithRialtoMessageBridge, + bp_millau::Millau, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_millau::BlockLength::get(), + block_weights: bp_millau::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::RIALTO_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, + }, + }); + + assert_eq!( + RialtoToMillauConversionRate::key().to_vec(), + bp_runtime::storage_parameter_key( + bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME + ) + .0, + ); + } +} diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 3c4ec1ebce1c4..dffa197bf72a8 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -73,7 +73,9 @@ polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", bran polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] +bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } libsecp256k1 = { version = "0.7", features = ["hmac"] } +static_assertions = "1.1" [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 42d2d880e06eb..2a68912e52010 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -936,49 +936,6 @@ where #[cfg(test)] mod tests { use super::*; - use bp_runtime::Chain; - use bridge_runtime_common::messages; - - #[test] - fn ensure_rialto_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::MillauWeight; - - pallet_bridge_messages::ensure_weights_are_correct::( - bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, - DbWeight::get(), - ); - - let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - bp_rialto::Rialto::max_extrinsic_size(), - bp_rialto::Rialto::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::Rialto::max_extrinsic_weight(), - ), - ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, - ) - .unwrap_or(u32::MAX); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_rialto::Rialto::max_extrinsic_size(), - bp_rialto::Rialto::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - DbWeight::get(), - ); - } #[test] fn call_size() { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 22d11c68be20b..7e398a5a5b969 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -291,15 +291,23 @@ impl MessagesParameter for RialtoToMillauMessagesParameter { #[cfg(test)] mod tests { use super::*; - use crate::{AccountId, Call, ExistentialDeposit, Runtime, SystemCall, SystemConfig, VERSION}; + use crate::{ + AccountId, Call, DbWeight, ExistentialDeposit, MillauGrandpaInstance, Runtime, SystemCall, + SystemConfig, WithMillauMessagesInstance, VERSION, + }; use bp_message_dispatch::CallOrigin; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, }; - use bp_runtime::{derive_account_id, messages::DispatchFeePayment, SourceAccount}; - use bridge_runtime_common::messages::target::{ - FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload, + use bp_runtime::{derive_account_id, messages::DispatchFeePayment, Chain, SourceAccount}; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, + AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, + }, + messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload}, }; use frame_support::{ traits::Currency, @@ -377,4 +385,92 @@ mod tests { ); }); } + + #[test] + fn ensure_rialto_message_lane_weights_are_correct() { + type Weights = pallet_bridge_messages::weights::MillauWeight; + + pallet_bridge_messages::ensure_weights_are_correct::( + bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, + DbWeight::get(), + ); + + let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( + messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), + ); + pallet_bridge_messages::ensure_able_to_receive_message::( + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), + max_incoming_message_proof_size, + messages::target::maximal_incoming_message_dispatch_weight( + bp_rialto::Rialto::max_extrinsic_weight(), + ), + ); + + let max_incoming_inbound_lane_data_proof_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, + ) + .unwrap_or(u32::MAX); + pallet_bridge_messages::ensure_able_to_receive_confirmation::( + bp_rialto::Rialto::max_extrinsic_size(), + bp_rialto::Rialto::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + DbWeight::get(), + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: MillauGrandpaInstance, + with_bridged_chain_messages_instance: WithMillauMessagesInstance, + bridge: WithMillauMessageBridge, + this_chain: bp_rialto::Rialto, + bridged_chain: bp_millau::Millau, + this_chain_account_id_converter: bp_rialto::AccountIdConverter + ); + + assert_complete_bridge_constants::< + Runtime, + MillauGrandpaInstance, + WithMillauMessagesInstance, + WithMillauMessageBridge, + bp_rialto::Rialto, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_rialto::BlockLength::get(), + block_weights: bp_rialto::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::MILLAU_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, + }, + }); + + assert_eq!( + MillauToRialtoConversionRate::key().to_vec(), + bp_runtime::storage_parameter_key( + bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME + ) + .0, + ); + } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index ed3bb32d17060..632f45e58175f 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -12,6 +12,7 @@ codec = { package = "parity-scale-codec", version = "2.2.0", default-features = ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } scale-info = { version = "1.0", default-features = false, features = ["derive"] } +static_assertions = { version = "1.1", optional = true } # Bridge dependencies @@ -64,3 +65,7 @@ runtime-benchmarks = [ "sp-state-machine", "sp-version", ] +integrity-test = [ + "frame-system", + "static_assertions", +] diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs new file mode 100644 index 0000000000000..ab517566a0fe6 --- /dev/null +++ b/bin/runtime-common/src/integrity.rs @@ -0,0 +1,331 @@ +// 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 . + +//! Integrity tests for chain constants and pallets configuration. +//! +//! Most of the tests in this module assume that the bridge is using standard (see `crate::messages` +//! module for details) configuration. + +use crate::messages::MessageBridge; + +use bp_messages::MessageNonce; +use bp_runtime::{Chain, ChainId}; +use codec::Encode; +use frame_support::{storage::generator::StorageValue, traits::Get}; +use frame_system::limits; + +/// Macro that ensures that the runtime configuration and chain primitives crate are sharing +/// the same types (index, block number, hash, hasher, account id and header). +#[macro_export] +macro_rules! assert_chain_types( + ( runtime: $r:path, this_chain: $this:path ) => { + { + // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard + // configuration is used), or something has broke existing configuration (meaning that all bridged chains + // and relays will stop functioning) + use frame_system::Config as SystemConfig; + use static_assertions::assert_type_eq_all; + + assert_type_eq_all!(<$r as SystemConfig>::Index, bp_runtime::IndexOf<$this>); + assert_type_eq_all!(<$r as SystemConfig>::BlockNumber, bp_runtime::BlockNumberOf<$this>); + assert_type_eq_all!(<$r as SystemConfig>::Hash, bp_runtime::HashOf<$this>); + assert_type_eq_all!(<$r as SystemConfig>::Hashing, bp_runtime::HasherOf<$this>); + assert_type_eq_all!(<$r as SystemConfig>::AccountId, bp_runtime::AccountIdOf<$this>); + assert_type_eq_all!(<$r as SystemConfig>::Header, bp_runtime::HeaderOf<$this>); + } + } +); + +/// Macro that ensures that the bridge configuration and chain primitives crates are sharing +/// the same types (hash, account id, ...). +#[macro_export] +macro_rules! assert_bridge_types( + ( bridge: $bridge:path, this_chain: $this:path, bridged_chain: $bridged:path ) => { + { + // if one of this asserts fail, then all chains, bridged with this chain and bridge relays are now broken + // + // `frame_support::weights::Weight` is used here directly, because all chains we know are using this + // primitive (may be changed in the future) + use $crate::messages::{ + AccountIdOf, BalanceOf, BridgedChain, HashOf, SignatureOf, SignerOf, ThisChain, WeightOf, + }; + use static_assertions::assert_type_eq_all; + + assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$this>); + assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$this>); + assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$this>); + assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$this>); + assert_type_eq_all!(WeightOf>, frame_support::weights::Weight); + assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$this>); + + assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$bridged>); + assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$bridged>); + assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$bridged>); + assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$bridged>); + assert_type_eq_all!(WeightOf>, frame_support::weights::Weight); + assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$bridged>); + } + } +); + +/// Macro that ensures that the bridge GRANDPA pallet is configured properly to bridge with given +/// chain. +#[macro_export] +macro_rules! assert_bridge_grandpa_pallet_types( + ( runtime: $r:path, with_bridged_chain_grandpa_instance: $i:path, bridged_chain: $bridged:path ) => { + { + // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard + // configuration is used), or something has broke existing configuration (meaning that all bridged chains + // and relays will stop functioning) + use pallet_bridge_grandpa::Config as GrandpaConfig; + use static_assertions::assert_type_eq_all; + + assert_type_eq_all!(<$r as GrandpaConfig<$i>>::BridgedChain, $bridged); + } + } +); + +/// Macro that ensures that the bridge messages pallet is configured properly to bridge using given +/// configuration. +#[macro_export] +macro_rules! assert_bridge_messages_pallet_types( + ( + runtime: $r:path, + with_bridged_chain_messages_instance: $i:path, + bridge: $bridge:path, + this_chain_account_id_converter: $this_converter:path + ) => { + { + // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard + // configuration is used), or something has broke existing configuration (meaning that all bridged chains + // and relays will stop functioning) + use $crate::messages::{ + source::FromThisChainMessagePayload, + target::FromBridgedChainMessagePayload, + AccountIdOf, BalanceOf, BridgedChain, ThisChain, WeightOf, + }; + use pallet_bridge_messages::Config as MessagesConfig; + use static_assertions::assert_type_eq_all; + + assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundMessageFee, BalanceOf>); + + assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundMessageFee, BalanceOf>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); + + assert_type_eq_all!(<$r as MessagesConfig<$i>>::AccountIdConverter, $this_converter); + + assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, BridgedChain<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::SourceHeaderChain, BridgedChain<$bridge>); + } + } +); + +/// Macro that combines four other macro calls - `assert_chain_types`, `assert_bridge_types`, +/// `assert_bridge_grandpa_pallet_types` and `assert_bridge_messages_pallet_types`. It may be used +/// at the chain that is implemeting complete standard messages bridge (i.e. with bridge GRANDPA and +/// messages pallets deployed). +#[macro_export] +macro_rules! assert_complete_bridge_types( + ( + runtime: $r:path, + with_bridged_chain_grandpa_instance: $gi:path, + with_bridged_chain_messages_instance: $mi:path, + bridge: $bridge:path, + this_chain: $this:path, + bridged_chain: $bridged:path, + this_chain_account_id_converter: $this_converter:path + ) => { + $crate::assert_chain_types!(runtime: $r, this_chain: $this); + $crate::assert_bridge_types!(bridge: $bridge, this_chain: $this, bridged_chain: $bridged); + $crate::assert_bridge_grandpa_pallet_types!( + runtime: $r, + with_bridged_chain_grandpa_instance: $gi, + bridged_chain: $bridged + ); + $crate::assert_bridge_messages_pallet_types!( + runtime: $r, + with_bridged_chain_messages_instance: $mi, + bridge: $bridge, + this_chain_account_id_converter: $this_converter + ); + } +); + +/// Parameters for asserting chain-related constants. +#[derive(Debug)] +pub struct AssertChainConstants { + /// Block length limits of the chain. + pub block_length: limits::BlockLength, + /// Block weight limits of the chain. + pub block_weights: limits::BlockWeights, +} + +/// Test that our hardcoded, chain-related constants, are matching chain runtime configuration. +/// +/// In particular, this test ensures that: +/// +/// 1) block weight limits are matching; +/// 2) block size limits are matching. +pub fn assert_chain_constants(params: AssertChainConstants) +where + R: frame_system::Config, + C: Chain, +{ + // we don't check runtime version here, because in our case we'll be building relay from one + // repo and runtime will live in another repo, along with outdated relay version. To avoid + // unneeded commits, let's not raise an error in case of version mismatch. + + // if one of following assert fails, it means that we may need to upgrade bridged chain and + // relay to use updated constants. If constants are now smaller than before, it may lead to + // undeliverable messages. + + // `BlockLength` struct is not implementing `PartialEq`, so we compare encoded values here. + assert_eq!( + R::BlockLength::get().encode(), + params.block_length.encode(), + "BlockLength from runtime ({:?}) differ from hardcoded: {:?}", + R::BlockLength::get(), + params.block_length, + ); + // `BlockWeights` struct is not implementing `PartialEq`, so we compare encoded values here + assert_eq!( + R::BlockWeights::get().encode(), + params.block_weights.encode(), + "BlockWeights from runtime ({:?}) differ from hardcoded: {:?}", + R::BlockWeights::get(), + params.block_weights, + ); +} + +/// Test that the constants, used in GRANDPA pallet configuration are valid. +pub fn assert_bridge_grandpa_pallet_constants() +where + R: pallet_bridge_grandpa::Config, + GI: 'static, +{ + assert!( + R::MaxRequests::get() > 0, + "MaxRequests ({}) must be larger than zero", + R::MaxRequests::get(), + ); +} + +/// Parameters for asserting messages pallet constants. +#[derive(Debug)] +pub struct AssertBridgeMessagesPalletConstants { + /// Maximal number of unrewarded relayer entries in a confirmation transaction at the bridged + /// chain. + pub max_unrewarded_relayers_in_bridged_confirmation_tx: MessageNonce, + /// Maximal number of unconfirmed messages in a confirmation transaction at the bridged chain. + pub max_unconfirmed_messages_in_bridged_confirmation_tx: MessageNonce, + /// Identifier of the bridged chain. + pub bridged_chain_id: ChainId, +} + +/// Test that the constants, used in messages pallet configuration are valid. +pub fn assert_bridge_messages_pallet_constants(params: AssertBridgeMessagesPalletConstants) +where + R: pallet_bridge_messages::Config, + MI: 'static, +{ + assert!( + R::MaxMessagesToPruneAtOnce::get() > 0, + "MaxMessagesToPruneAtOnce ({}) must be larger than zero", + R::MaxMessagesToPruneAtOnce::get(), + ); + assert!( + R::MaxUnrewardedRelayerEntriesAtInboundLane::get() <= params.max_unrewarded_relayers_in_bridged_confirmation_tx, + "MaxUnrewardedRelayerEntriesAtInboundLane ({}) must be <= than the hardcoded value for bridged chain: {}", + R::MaxUnrewardedRelayerEntriesAtInboundLane::get(), + params.max_unrewarded_relayers_in_bridged_confirmation_tx, + ); + assert!( + R::MaxUnconfirmedMessagesAtInboundLane::get() <= params.max_unconfirmed_messages_in_bridged_confirmation_tx, + "MaxUnrewardedRelayerEntriesAtInboundLane ({}) must be <= than the hardcoded value for bridged chain: {}", + R::MaxUnconfirmedMessagesAtInboundLane::get(), + params.max_unconfirmed_messages_in_bridged_confirmation_tx, + ); + assert_eq!(R::BridgedChainId::get(), params.bridged_chain_id); +} + +/// Parameters for asserting bridge pallet names. +#[derive(Debug)] +pub struct AssertBridgePalletNames<'a> { + /// Name of the messages pallet, deployed at the bridged chain and used to bridge with this + /// chain. + pub with_this_chain_messages_pallet_name: &'a str, + /// Name of the GRANDPA pallet, deployed at this chain and used to bridge with the bridged + /// chain. + pub with_bridged_chain_grandpa_pallet_name: &'a str, + /// Name of the messages pallet, deployed at this chain and used to bridge with the bridged + /// chain. + pub with_bridged_chain_messages_pallet_name: &'a str, +} + +/// Tests that bridge pallet names used in `construct_runtime!()` macro call are matching constants +/// from chain primitives crates. +pub fn assert_bridge_pallet_names(params: AssertBridgePalletNames) +where + B: MessageBridge, + R: pallet_bridge_grandpa::Config + pallet_bridge_messages::Config, + GI: 'static, + MI: 'static, +{ + assert_eq!(B::BRIDGED_MESSAGES_PALLET_NAME, params.with_this_chain_messages_pallet_name); + assert_eq!( + pallet_bridge_grandpa::PalletOwner::::storage_value_final_key().to_vec(), + bp_runtime::storage_value_key(params.with_bridged_chain_grandpa_pallet_name, "PalletOwner",).0, + ); + assert_eq!( + pallet_bridge_messages::PalletOwner::::storage_value_final_key().to_vec(), + bp_runtime::storage_value_key( + params.with_bridged_chain_messages_pallet_name, + "PalletOwner", + ) + .0, + ); +} + +/// Parameters for asserting complete standard messages bridge. +#[derive(Debug)] +pub struct AssertCompleteBridgeConstants<'a> { + /// Parameters to assert this chain constants. + pub this_chain_constants: AssertChainConstants, + /// Parameters to assert messages pallet constants. + pub messages_pallet_constants: AssertBridgeMessagesPalletConstants, + /// Parameters to assert pallet names constants. + pub pallet_names: AssertBridgePalletNames<'a>, +} + +/// All bridge-related constants tests for the complete standard messages bridge (i.e. with bridge +/// GRANDPA and messages pallets deployed). +pub fn assert_complete_bridge_constants(params: AssertCompleteBridgeConstants) +where + R: frame_system::Config + + pallet_bridge_grandpa::Config + + pallet_bridge_messages::Config, + GI: 'static, + MI: 'static, + B: MessageBridge, + This: Chain, +{ + assert_chain_constants::(params.this_chain_constants); + assert_bridge_grandpa_pallet_constants::(); + assert_bridge_messages_pallet_constants::(params.messages_pallet_constants); + assert_bridge_pallet_names::(params.pallet_names); +} diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 66f2c6c3a01f1..c7fb98aba767d 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -21,3 +21,6 @@ pub mod messages; pub mod messages_api; pub mod messages_benchmarking; + +#[cfg(feature = "integrity-test")] +pub mod integrity; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index a8267e65eb3b7..947bfdc7f634c 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -300,7 +300,7 @@ pub mod pallet { /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt /// flag directly or call the `halt_operations`). #[pallet::storage] - pub(super) type PalletOwner, I: 'static = ()> = + pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; /// If true, all pallet transactions are failed immediately. From f3965bbd7f071a411a98181555b6d1a8b3cf07f3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Feb 2022 11:53:23 +0300 Subject: [PATCH 0650/1210] Encode and estimate Rococo/Wococo/Kusama/Polkadot messages (#1322) * encode and estimate Rococo/Wococo/Kusama/Polkadot messages * allow send-message for non-bundled chains * weight -> dispatch-weight * fmt * fix spelling --- primitives/polkadot-core/src/lib.rs | 20 +++--- primitives/runtime/src/chain.rs | 65 ++++++++++++++++++- primitives/runtime/src/lib.rs | 4 +- relays/bin-substrate/src/chains/kusama.rs | 64 ++++++++++++++---- .../src/chains/kusama_messages_to_polkadot.rs | 8 +-- relays/bin-substrate/src/chains/millau.rs | 24 ++++--- .../src/chains/millau_messages_to_rialto.rs | 11 ++-- relays/bin-substrate/src/chains/mod.rs | 10 +-- relays/bin-substrate/src/chains/polkadot.rs | 64 ++++++++++++++---- .../src/chains/polkadot_messages_to_kusama.rs | 8 +-- relays/bin-substrate/src/chains/rialto.rs | 24 ++++--- .../src/chains/rialto_messages_to_millau.rs | 11 ++-- .../src/chains/rialto_parachain.rs | 15 +++-- relays/bin-substrate/src/chains/rococo.rs | 63 ++++++++++++++---- relays/bin-substrate/src/chains/wococo.rs | 65 +++++++++++++++---- relays/bin-substrate/src/cli/encode_call.rs | 10 ++- .../bin-substrate/src/cli/encode_message.rs | 11 +++- relays/bin-substrate/src/cli/estimate_fee.rs | 5 +- relays/bin-substrate/src/cli/init_bridge.rs | 8 +-- .../src/cli/register_parachain.rs | 27 ++++---- .../src/cli/relay_headers_and_messages.rs | 8 +-- .../src/cli/resubmit_transactions.rs | 4 +- relays/bin-substrate/src/cli/send_message.rs | 28 +++++--- relays/bin-substrate/src/cli/swap_tokens.rs | 24 +++---- relays/client-kusama/src/lib.rs | 10 +-- relays/client-millau/src/lib.rs | 14 ++-- relays/client-polkadot/src/lib.rs | 10 +-- relays/client-rialto/src/lib.rs | 14 ++-- relays/client-rococo/src/lib.rs | 10 +-- relays/client-substrate/src/chain.rs | 8 +-- relays/client-substrate/src/client.rs | 8 +-- relays/client-wococo/src/lib.rs | 10 +-- .../src/finality_target.rs | 8 +-- .../src/headers_initialize.rs | 14 +++- .../src/messages_source.rs | 26 ++++---- .../src/messages_target.rs | 46 +++++++------ 36 files changed, 518 insertions(+), 241 deletions(-) diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 50e8423437405..ce27d22b240b9 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::MessageNonce; -use bp_runtime::Chain; +use bp_runtime::{Chain, EncodedOrDecodedCall}; use frame_support::{ dispatch::Dispatchable, parameter_types, @@ -228,8 +228,12 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic>; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< + AccountAddress, + EncodedOrDecodedCall, + Signature, + SignedExtensions, +>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; @@ -336,12 +340,12 @@ where fn pre_dispatch( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + Ok(()) } } diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 30e754b5702fc..1c80622472291 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use codec::{Decode, Encode}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ @@ -23,7 +24,69 @@ use sp_runtime::{ }, FixedPointOperand, }; -use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr}; +use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec}; + +/// Chain call, that is either SCALE-encoded, or decoded. +#[derive(Debug, Clone)] +pub enum EncodedOrDecodedCall { + /// The call that is SCALE-encoded. + /// + /// This variant is used when we the chain runtime is not bundled with the relay, but + /// we still need the represent call in some RPC calls or transactions. + Encoded(Vec), + /// The decoded call. + Decoded(ChainCall), +} + +impl EncodedOrDecodedCall { + /// Returns decoded call. + pub fn to_decoded(&self) -> Result { + match self { + Self::Encoded(ref encoded_call) => + ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), + Self::Decoded(ref decoded_call) => Ok(decoded_call.clone()), + } + } + + /// Converts self to decoded call. + pub fn into_decoded(self) -> Result { + match self { + Self::Encoded(encoded_call) => + ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), + Self::Decoded(decoded_call) => Ok(decoded_call), + } + } +} + +impl From for EncodedOrDecodedCall { + fn from(call: ChainCall) -> EncodedOrDecodedCall { + EncodedOrDecodedCall::Decoded(call) + } +} + +impl Decode for EncodedOrDecodedCall { + fn decode(input: &mut I) -> Result { + // having encoded version is better than decoded, because decoding isn't required + // everywhere and for mocked calls it may lead to **unneeded** errors + match input.remaining_len()? { + Some(remaining_len) => { + let mut encoded_call = vec![0u8; remaining_len]; + input.read(&mut encoded_call)?; + Ok(EncodedOrDecodedCall::Encoded(encoded_call)) + }, + None => Ok(EncodedOrDecodedCall::Decoded(ChainCall::decode(input)?)), + } + } +} + +impl Encode for EncodedOrDecodedCall { + fn encode(&self) -> Vec { + match *self { + Self::Encoded(ref encoded_call) => encoded_call.clone(), + Self::Decoded(ref decoded_call) => decoded_call.encode(), + } + } +} /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index f69afca4c0851..1d8a40339ab0c 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -25,8 +25,8 @@ use sp_io::hashing::blake2_256; use sp_std::{convert::TryFrom, vec, vec::Vec}; pub use chain::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, - IndexOf, SignatureOf, TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, 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}; diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 5a65426c9dc1d..9cdc6cd125e02 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; @@ -21,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Kusama. @@ -32,13 +37,15 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Kusama { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( relay_kusama_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::KUSAMA_TO_POLKADOT_INDEX => { @@ -48,6 +55,7 @@ impl CliEncodeCall for Kusama { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -58,13 +66,11 @@ impl CliEncodeCall for Kusama { }) } - fn get_dispatch_info( - call: &relay_kusama_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_kusama_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_kusama_client::runtime::Call::System( relay_kusama_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -78,7 +84,12 @@ impl CliChain for Kusama { const RUNTIME_VERSION: RuntimeVersion = bp_kusama::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_kusama::AccountId, + bp_polkadot::AccountPublic, + bp_polkadot::Signature, + Vec, + >; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -88,8 +99,37 @@ impl CliChain for Kusama { } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - anyhow::bail!("Sending messages from Kusama is not yet supported.") + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Kusama's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Kusama; + type Target = relay_polkadot_client::Polkadot; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::KUSAMA_TO_POLKADOT_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Polkadot call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 5c0b91d8ffe35..3679b26478371 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -82,7 +82,7 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Kusama::sign_transaction(SignParam { spec_version, transaction_version, @@ -96,12 +96,12 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( sp_runtime::FixedU128::from_float(updated_rate), ) ) - ), + ).into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 3d599c2e54513..1fc1e8308ef45 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -25,24 +25,27 @@ use crate::cli::{ }; use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_millau_client::Millau; use sp_version::RuntimeVersion; impl CliEncodeCall for Millau { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }), + }) + .into(), Call::Transfer { recipient, amount } => millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer { dest: recipient.raw_id(), value: amount.cast(), - }), + }) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::MILLAU_TO_RIALTO_INDEX => { @@ -54,6 +57,7 @@ impl CliEncodeCall for Millau { delivery_and_dispatch_fee: fee.cast(), }, ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -63,8 +67,8 @@ impl CliEncodeCall for Millau { }) } - fn get_dispatch_info(call: &millau_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -90,7 +94,7 @@ impl CliChain for Millau { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| anyhow!("Failed to decode Millau's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { type Source = Millau; type Target = relay_rialto_client::Rialto; @@ -102,11 +106,13 @@ impl CliChain for Millau { bridge::MILLAU_TO_RIALTO_INDEX, ); let call = Target::encode_call(&call)?; - let weight = call.get_dispatch_info().weight; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + call.to_decoded().map(|call| call.get_dispatch_info().weight) + })?; Ok(send_message::message_payload( spec_version, - weight, + dispatch_weight, origin, &call, DispatchFeePayment::AtSourceChain, diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 906141e2f2be7..a93007c1bb5a1 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -74,7 +74,7 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Millau::sign_transaction(SignParam { spec_version, transaction_version, @@ -82,17 +82,16 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - millau_runtime::MessagesCall::update_pallet_parameter { + millau_runtime::Call::from(millau_runtime::MessagesCall::update_pallet_parameter { parameter: millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), - } - .into(), + }).into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index e2a7a9a2b1eb7..16901143e19fb 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -210,8 +210,9 @@ mod tests { genesis_hash: Default::default(), signer: sp_keyring::AccountKeyring::Alice.pair(), era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(rialto_call.clone(), 0), - }); + unsigned: UnsignedTransaction::new(rialto_call.clone().into(), 0), + }) + .unwrap(); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); assert!( bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, @@ -231,8 +232,9 @@ mod tests { genesis_hash: Default::default(), signer: sp_keyring::AccountKeyring::Alice.pair(), era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(millau_call.clone(), 0), - }); + unsigned: UnsignedTransaction::new(millau_call.clone().into(), 0), + }) + .unwrap(); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); assert!( bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 16d44f46873f9..7ae1cbc477777 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; @@ -21,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Polkadot. @@ -32,13 +37,15 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Polkadot { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( relay_polkadot_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::POLKADOT_TO_KUSAMA_INDEX => { @@ -48,6 +55,7 @@ impl CliEncodeCall for Polkadot { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -58,13 +66,11 @@ impl CliEncodeCall for Polkadot { }) } - fn get_dispatch_info( - call: &relay_polkadot_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_polkadot_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_polkadot_client::runtime::Call::System( relay_polkadot_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -78,7 +84,12 @@ impl CliChain for Polkadot { const RUNTIME_VERSION: RuntimeVersion = bp_polkadot::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_polkadot::AccountId, + bp_kusama::AccountPublic, + bp_kusama::Signature, + Vec, + >; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -88,8 +99,37 @@ impl CliChain for Polkadot { } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - anyhow::bail!("Sending messages from Polkadot is not yet supported.") + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Polkadot's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Polkadot; + type Target = relay_kusama_client::Kusama; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::POLKADOT_TO_KUSAMA_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Kusama call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 65b1ce9b06dc8..9f8ec346db266 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -82,7 +82,7 @@ pub(crate) async fn update_kusama_to_polkadot_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Polkadot::sign_transaction(SignParam { spec_version, transaction_version, @@ -96,12 +96,12 @@ pub(crate) async fn update_kusama_to_polkadot_conversion_rate( sp_runtime::FixedU128::from_float(updated_rate), ) ) - ), + ).into(), transaction_nonce, ) - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 8931c5112da80..8f26a64a4e326 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -25,24 +25,27 @@ use crate::cli::{ }; use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_client::Rialto; use sp_version::RuntimeVersion; impl CliEncodeCall for Rialto { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }), + }) + .into(), Call::Transfer { recipient, amount } => rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer { dest: recipient.raw_id().into(), value: amount.0, - }), + }) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::RIALTO_TO_MILLAU_INDEX => { @@ -54,6 +57,7 @@ impl CliEncodeCall for Rialto { delivery_and_dispatch_fee: fee.0, }, ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -63,8 +67,8 @@ impl CliEncodeCall for Rialto { }) } - fn get_dispatch_info(call: &rialto_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -89,7 +93,7 @@ impl CliChain for Rialto { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| anyhow!("Failed to decode Rialto's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { type Source = Rialto; type Target = relay_millau_client::Millau; @@ -101,11 +105,13 @@ impl CliChain for Rialto { bridge::RIALTO_TO_MILLAU_INDEX, ); let call = Target::encode_call(&call)?; - let weight = call.get_dispatch_info().weight; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + call.to_decoded().map(|call| call.get_dispatch_info().weight) + })?; Ok(send_message::message_payload( spec_version, - weight, + dispatch_weight, origin, &call, DispatchFeePayment::AtSourceChain, diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 4a570050f4eb8..6de10d2346f93 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -74,7 +74,7 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Rialto::sign_transaction(SignParam { spec_version, transaction_version, @@ -82,17 +82,16 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - rialto_runtime::MessagesCall::update_pallet_parameter { + rialto_runtime::Call::from(rialto_runtime::MessagesCall::update_pallet_parameter { parameter: rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), - } - .into(), + }).into(), transaction_nonce, ) - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index da400a4dafd87..0ed39faa543b7 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -21,34 +21,37 @@ use crate::cli::{ encode_message, CliChain, }; use bp_message_dispatch::MessagePayload; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_parachain_client::RialtoParachain; use sp_version::RuntimeVersion; impl CliEncodeCall for RialtoParachain { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => rialto_parachain_runtime::Call::System( rialto_parachain_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), }, - ), + ) + .into(), Call::Transfer { recipient, amount } => rialto_parachain_runtime::Call::Balances( rialto_parachain_runtime::BalancesCall::transfer { dest: recipient.raw_id().into(), value: amount.0, }, - ), + ) + .into(), Call::BridgeSendMessage { .. } => { anyhow::bail!("Bridge messages are not (yet) supported here",) }, }) } - fn get_dispatch_info(call: &rialto_parachain_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index ef49899ec791d..ceef4c1f532c9 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -15,6 +15,8 @@ // along with Parity Bridges Common. If not, see . use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; @@ -22,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Rococo. @@ -33,13 +37,15 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Rococo { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( relay_rococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::ROCOCO_TO_WOCOCO_INDEX => { @@ -49,6 +55,7 @@ impl CliEncodeCall for Rococo { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -59,13 +66,11 @@ impl CliEncodeCall for Rococo { }) } - fn get_dispatch_info( - call: &relay_rococo_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_rococo_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_rococo_client::runtime::Call::System( relay_rococo_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -79,15 +84,49 @@ impl CliChain for Rococo { const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountPublic, + bp_wococo::Signature, + Vec, + >; fn ss58_format() -> u16 { 42 } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - Err(anyhow!("Sending messages from Rococo is not yet supported.")) + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Rococo's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Rococo; + type Target = relay_wococo_client::Wococo; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::ROCOCO_TO_WOCOCO_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Wococo call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 2acc8af484567..46dec2a3c90e3 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -15,6 +15,8 @@ // along with Parity Bridges Common. If not, see . use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use relay_wococo_client::Wococo; @@ -22,18 +24,22 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; impl CliEncodeCall for Wococo { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( relay_wococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::WOCOCO_TO_ROCOCO_INDEX => { @@ -43,6 +49,7 @@ impl CliEncodeCall for Wococo { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -53,18 +60,16 @@ impl CliEncodeCall for Wococo { }) } - fn get_dispatch_info( - call: &relay_wococo_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_wococo_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_wococo_client::runtime::Call::System( relay_wococo_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, }), - _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + _ => anyhow::bail!("Unsupported Wococo call: {:?}", call), } } } @@ -73,15 +78,49 @@ impl CliChain for Wococo { const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_wococo::AccountId, + bp_rococo::AccountPublic, + bp_rococo::Signature, + Vec, + >; fn ss58_format() -> u16 { 42 } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - Err(anyhow!("Sending messages from Wococo is not yet supported.")) + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Wococo's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Wococo; + type Target = relay_rococo_client::Rococo; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::WOCOCO_TO_ROCOCO_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Rococo call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs index 707e78378302f..e288e2c13d6cd 100644 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ b/relays/bin-substrate/src/cli/encode_call.rs @@ -20,6 +20,7 @@ use crate::{ }, select_full_bridge, }; +use bp_runtime::EncodedOrDecodedCall; use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -85,10 +86,10 @@ pub enum Call { pub trait CliEncodeCall: Chain { /// Encode a CLI call. - fn encode_call(call: &Call) -> anyhow::Result; + fn encode_call(call: &Call) -> anyhow::Result>; /// Get dispatch info for the call. - fn get_dispatch_info(call: &Self::Call) -> anyhow::Result; + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result; } impl EncodeCall { @@ -100,7 +101,10 @@ impl EncodeCall { let encoded = HexBytes::encode(&call); log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); - log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call)?.weight); + log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call) + .map(|dispatch_info| format!("{}", dispatch_info.weight)) + .unwrap_or_else(|_| "".to_string()) + ); log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); Ok(encoded) diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index ee77fc4a46efe..677fc29ef1531 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -18,6 +18,7 @@ use crate::{ cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}, select_full_bridge, }; +use frame_support::weights::Weight; use structopt::StructOpt; use strum::VariantNames; @@ -37,6 +38,12 @@ pub enum MessagePayload { /// SS58 encoded Source account that will send the payload. #[structopt(long)] sender: AccountId, + /// Weight of the call. + /// + /// It must be specified if the chain runtime is not bundled with the relay, or if + /// you want to override bundled weight. + #[structopt(long)] + dispatch_weight: Option, }, } @@ -97,6 +104,8 @@ mod tests { "call", "--sender", &sender, + "--dispatch-weight", + "42", "remark", "--remark-size", "12", @@ -106,6 +115,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x01000000000000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x010000002a0000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); } } diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 18e7341fc9658..30bcae079b091 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -103,6 +103,8 @@ mod tests { "call", "--sender", &alice, + "--dispatch-weight", + "42", "remark", "--remark-payload", "1234", @@ -129,7 +131,8 @@ mod tests { call: encode_call::Call::Remark { remark_payload: Some(HexBytes(vec![0x12, 0x34])), remark_size: None, - } + }, + dispatch_weight: Some(42), } } ); diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 50be6c87ccc46..ad133e369f59a 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -222,7 +222,7 @@ impl InitBridge { target_client.clone(), target_sign.public().into(), move |transaction_nonce, initialization_data| { - Bytes( + Ok(Bytes( Target::sign_transaction(SignParam { spec_version, transaction_version, @@ -230,12 +230,12 @@ impl InitBridge { signer: target_sign, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - encode_init_bridge(initialization_data), + encode_init_bridge(initialization_data).into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await; diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index d42e10d708fb6..4ede369026111 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -132,7 +132,7 @@ impl RegisterParachain { .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Relaychain::sign_transaction(SignParam { spec_version, transaction_version, @@ -140,12 +140,12 @@ impl RegisterParachain { signer: reserve_parachain_signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - reserve_parachain_id_call, + reserve_parachain_id_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -181,7 +181,7 @@ impl RegisterParachain { .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Relaychain::sign_transaction(SignParam { spec_version, transaction_version, @@ -189,12 +189,12 @@ impl RegisterParachain { signer: register_parathread_signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - register_parathread_call, + register_parathread_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -243,17 +243,20 @@ impl RegisterParachain { let force_lease_signer = relay_sign.clone(); relay_client .submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Relaychain::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: relay_genesis_hash, signer: force_lease_signer, era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(force_lease_call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new( + force_lease_call.into(), + transaction_nonce, + ), + })? .encode(), - ) + )) }) .await?; log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 4a4d24964fc5e..c8d74b8faec13 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -615,17 +615,17 @@ where let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(sign.public().into(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( C::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash, signer: sign, era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 8b021df86372d..81fa54dcd2dfb 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -445,7 +445,7 @@ async fn update_transaction_tip>( signer: key_pair.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: unsigned_tx.clone(), - }), + })?, ) .await?? .priority; @@ -468,7 +468,7 @@ async fn update_transaction_tip>( signer: key_pair.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: unsigned_tx, - }), + })?, )) } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index e3597f766b740..45f5fa89d02e9 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -124,9 +124,13 @@ impl SendMessage { let payload = { let target_call_weight = prepare_call_dispatch_weight( dispatch_weight, - ExplicitOrMaximal::Explicit(Target::get_dispatch_info(&target_call)?.weight), + || { + Ok(ExplicitOrMaximal::Explicit( + Target::get_dispatch_info(&target_call)?.weight, + )) + }, compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), - ); + )?; let source_sender_public: MultiSigner = source_sign.public().into(); let source_account_id = source_sender_public.into_account(); @@ -200,7 +204,7 @@ impl SendMessage { signer: source_sign.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), - }) + })? .encode(), )) .await?; @@ -213,7 +217,7 @@ impl SendMessage { signer: source_sign.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), - }) + })? .encode(); log::info!( @@ -241,7 +245,7 @@ impl SendMessage { HexBytes::encode(&signed_source_call) ); - Bytes(signed_source_call) + Ok(Bytes(signed_source_call)) }) .await?; }); @@ -252,12 +256,16 @@ impl SendMessage { fn prepare_call_dispatch_weight( user_specified_dispatch_weight: &Option>, - weight_from_pre_dispatch_call: ExplicitOrMaximal, + weight_from_pre_dispatch_call: impl Fn() -> anyhow::Result>, maximal_allowed_weight: Weight, -) -> Weight { - match user_specified_dispatch_weight.clone().unwrap_or(weight_from_pre_dispatch_call) { - ExplicitOrMaximal::Explicit(weight) => weight, - ExplicitOrMaximal::Maximal => maximal_allowed_weight, +) -> anyhow::Result { + match user_specified_dispatch_weight + .clone() + .map(Ok) + .unwrap_or_else(weight_from_pre_dispatch_call)? + { + ExplicitOrMaximal::Explicit(weight) => Ok(weight), + ExplicitOrMaximal::Maximal => Ok(maximal_allowed_weight), } } diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 16ec0d6a6fa16..b9cdac7d3487e 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -245,7 +245,7 @@ impl SwapTokens { .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Source::sign_transaction(SignParam { spec_version, transaction_version, @@ -253,12 +253,12 @@ impl SwapTokens { signer: create_swap_signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - create_swap_call, + create_swap_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -386,7 +386,7 @@ impl SwapTokens { .submit_and_watch_signed_extrinsic( accounts.target_account_at_bridged_chain.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Target::sign_transaction(SignParam { spec_version, transaction_version, @@ -394,12 +394,12 @@ impl SwapTokens { signer: target_sign, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - send_message_call, + send_message_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -430,7 +430,7 @@ impl SwapTokens { .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Source::sign_transaction(SignParam { spec_version, transaction_version, @@ -438,12 +438,12 @@ impl SwapTokens { signer: source_sign, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - cancel_swap_call, + cancel_swap_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 982bf88d82a96..532049e7056e8 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -101,7 +101,7 @@ impl TransactionSignScheme for Kusama { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_kusama::SignedExtensions::new( @@ -119,12 +119,12 @@ impl TransactionSignScheme for Kusama { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_kusama::UncheckedExtrinsic::new_signed( + Ok(bp_kusama::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 3c159907f7d00..cb181bc04ee92 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, IndexOf, - SignParam, TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -103,7 +103,7 @@ impl TransactionSignScheme for Millau { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = millau_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( param.unsigned.call.clone(), ( @@ -129,12 +129,12 @@ impl TransactionSignScheme for Millau { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - millau_runtime::UncheckedExtrinsic::new_signed( - call, + Ok(millau_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, signer.into_account(), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -153,7 +153,7 @@ impl TransactionSignScheme for Millau { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { - call: tx.function, + call: tx.function.into(), nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 6671b8c7228fc..c4098c819a02f 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -102,7 +102,7 @@ impl TransactionSignScheme for Polkadot { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_polkadot::SignedExtensions::new( @@ -120,12 +120,12 @@ impl TransactionSignScheme for Polkadot { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_polkadot::UncheckedExtrinsic::new_signed( + Ok(bp_polkadot::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 4062a36b0d747..e8a892a2ff415 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, IndexOf, - SignParam, TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -103,7 +103,7 @@ impl TransactionSignScheme for Rialto { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( param.unsigned.call.clone(), ( @@ -129,12 +129,12 @@ impl TransactionSignScheme for Rialto { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - rialto_runtime::UncheckedExtrinsic::new_signed( - call, + Ok(rialto_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, signer.into_account().into(), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -151,7 +151,7 @@ impl TransactionSignScheme for Rialto { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { - call: tx.function, + call: tx.function.into(), nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 56ca95606a8e7..e8b5a1abd41e0 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -104,7 +104,7 @@ impl TransactionSignScheme for Rococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_rococo::SignedExtensions::new( @@ -122,12 +122,12 @@ impl TransactionSignScheme for Rococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_rococo::UncheckedExtrinsic::new_signed( + Ok(bp_rococo::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 24b0127f3a7c0..97a2288f478d3 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use bp_messages::MessageNonce; -use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; +use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; use frame_support::weights::{Weight, WeightToFeePolynomial}; use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; @@ -141,7 +141,7 @@ pub trait BlockWithJustification

{ #[derive(Clone, Debug)] pub struct UnsignedTransaction { /// Runtime call of this transaction. - pub call: C::Call, + pub call: EncodedOrDecodedCall, /// Transaction nonce. pub nonce: C::Index, /// Tip included into transaction. @@ -150,7 +150,7 @@ pub struct UnsignedTransaction { impl UnsignedTransaction { /// Create new unsigned transaction with given call, nonce and zero tip. - pub fn new(call: C::Call, nonce: C::Index) -> Self { + pub fn new(call: EncodedOrDecodedCall, nonce: C::Index) -> Self { Self { call, nonce, tip: Zero::zero() } } @@ -174,7 +174,7 @@ pub trait TransactionSignScheme { type SignedTransaction: Clone + Debug + Codec + Send + 'static; /// Create transaction for given runtime call, signed by given account. - fn sign_transaction(param: SignParam) -> Self::SignedTransaction + fn sign_transaction(param: SignParam) -> Result where Self: Sized; diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 685f938d18a43..f35281e2d35c5 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -373,7 +373,7 @@ impl Client { pub async fn submit_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, ) -> Result { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -390,7 +390,7 @@ impl Client { }; self.jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; let tx_hash = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) @@ -403,7 +403,7 @@ impl Client { pub async fn submit_and_watch_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, ) -> Result>> { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -411,7 +411,7 @@ impl Client { let best_header_id = HeaderId(*best_header.number(), best_header.hash()); let subscription = self .jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; let tx_hash = C::Hasher::hash(&extrinsic.0); let subscription = client .subscribe( diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index fd45fc0dc186f..cb4c04903cb88 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -104,7 +104,7 @@ impl TransactionSignScheme for Wococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_wococo::SignedExtensions::new( @@ -122,12 +122,12 @@ impl TransactionSignScheme for Wococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_wococo::UncheckedExtrinsic::new_signed( + Ok(bp_wococo::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index 9a92c88a234a9..e7a7487ae2c17 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -123,17 +123,17 @@ where .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - Bytes( + Ok(Bytes( P::TransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash, signer: transaction_params.signer.clone(), era: TransactionEra::new(best_block_id, transaction_params.mortality), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) }, ) .await diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs index 8713663dd8296..0e1371c53c815 100644 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/relays/lib-substrate-relay/src/headers_initialize.rs @@ -31,7 +31,9 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use relay_substrate_client::{BlockNumberOf, Chain, ChainWithGrandpa, Client, HashOf}; +use relay_substrate_client::{ + BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, +}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; use sp_runtime::traits::Header as HeaderT; @@ -41,7 +43,10 @@ pub async fn initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + prepare_initialize_transaction: impl FnOnce( + TargetChain::Index, + InitializationData, + ) -> Result + Send + 'static, ) { @@ -77,7 +82,10 @@ async fn do_initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + prepare_initialize_transaction: impl FnOnce( + TargetChain::Index, + InitializationData, + ) -> Result + Send + 'static, ) -> Result< diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index de2306be3fef4..96e19beba25ca 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -282,8 +282,8 @@ where Ok(v) => v, Err(_) => return BalanceOf::::max_value(), }; - self.client - .estimate_extrinsic_fee(make_messages_delivery_proof_transaction::

( + async { + let dummy_tx = make_messages_delivery_proof_transaction::

( runtime_version.spec_version, runtime_version.transaction_version, self.client.genesis_hash(), @@ -292,10 +292,14 @@ where Zero::zero(), prepare_dummy_messages_delivery_proof::(), false, - )) - .await - .map(|fee| fee.inclusion_fee()) - .unwrap_or_else(|_| BalanceOf::::max_value()) + )?; + self.client + .estimate_extrinsic_fee(dummy_tx) + .await + .map(|fee| fee.inclusion_fee()) + } + .await + .unwrap_or_else(|_| BalanceOf::::max_value()) } } @@ -328,7 +332,7 @@ fn make_messages_delivery_proof_transaction( transaction_nonce: IndexOf, proof: SubstrateMessagesDeliveryProof, trace_call: bool, -) -> Bytes +) -> Result where P::SourceTransactionSignScheme: TransactionSignScheme, { @@ -336,17 +340,17 @@ where P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( proof, trace_call, ); - Bytes( + Ok(Bytes( P::SourceTransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: *source_genesis_hash, signer: source_transaction_params.signer.clone(), era: TransactionEra::new(source_best_block_id, source_transaction_params.mortality), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) } /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 5336e065a92b0..72267cbc09ac6 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -298,7 +298,7 @@ where total_size, ), false, - ); + )?; let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); @@ -323,25 +323,23 @@ where let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); - let larger_delivery_tx_fee = self - .client - .estimate_extrinsic_fee(make_messages_delivery_transaction::

( - spec_version, - transaction_version, - self.client.genesis_hash(), - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - self.relayer_id_at_source.clone(), + let dummy_tx = make_messages_delivery_transaction::

( + spec_version, + transaction_version, + self.client.genesis_hash(), + &self.transaction_params, + HeaderId(Default::default(), Default::default()), + Zero::zero(), + self.relayer_id_at_source.clone(), + nonces.clone(), + prepare_dummy_messages_proof::( nonces.clone(), - prepare_dummy_messages_proof::( - nonces.clone(), - larger_dispatch_weight, - total_size, - ), - false, - )) - .await?; + larger_dispatch_weight, + total_size, + ), + false, + )?; + let larger_delivery_tx_fee = self.client.estimate_extrinsic_fee(dummy_tx).await?; compute_prepaid_messages_refund::( total_prepaid_nonces, @@ -402,7 +400,7 @@ fn make_messages_delivery_transaction( nonces: RangeInclusive, proof: SubstrateMessagesProof, trace_call: bool, -) -> Bytes +) -> Result where P::TargetTransactionSignScheme: TransactionSignScheme, { @@ -415,17 +413,17 @@ where dispatch_weight, trace_call, ); - Bytes( + Ok(Bytes( P::TargetTransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: *target_genesis_hash, signer: target_transaction_params.signer.clone(), era: TransactionEra::new(target_best_block_id, target_transaction_params.mortality), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) } /// Prepare 'dummy' messages proof that will compose the delivery transaction. From b49b3ba8748bd49c0eef0c7f1aa98af66da0e7c1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Feb 2022 14:46:36 +0300 Subject: [PATCH 0651/1210] impl Decode for SignedExtensions (otherwise transaction resubmitter panicks) (#1325) --- primitives/polkadot-core/src/lib.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index ce27d22b240b9..2f7f6289a3eeb 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -250,7 +250,11 @@ pub type AdditionalSigned = (u32, u32, Hash, Hash, (), (), ()); #[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] pub struct SignedExtensions { encode_payload: SignedExtra, - additional_signed: AdditionalSigned, + // It may be set to `None` if extensions are decoded. We are never reconstructing transactions + // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to + // read fields of `encode_payload`. And when resigning transaction, we're reconstructing + // `SignedExtensions` from the scratch. + additional_signed: Option, _data: sp_std::marker::PhantomData, } @@ -262,9 +266,13 @@ impl parity_scale_codec::Encode for SignedExtensions { impl parity_scale_codec::Decode for SignedExtensions { fn decode( - _input: &mut I, + input: &mut I, ) -> Result { - unimplemented!("SignedExtensions are never meant to be decoded, they are only used to create transaction"); + SignedExtra::decode(input).map(|encode_payload| SignedExtensions { + encode_payload, + additional_signed: None, + _data: Default::default(), + }) } } @@ -287,7 +295,7 @@ impl SignedExtensions { (), // Check weight tip.into(), // transaction payment / tip (compact encoding) ), - additional_signed: ( + additional_signed: Some(( spec_version, transaction_version, genesis_hash, @@ -295,7 +303,7 @@ impl SignedExtensions { (), (), (), - ), + )), _data: Default::default(), } } @@ -335,7 +343,14 @@ where fn additional_signed( &self, ) -> Result { - Ok(self.additional_signed) + // we shall not ever see this error in relay, because we are never signing decoded + // transactions. Instead we're constructing and signing new transactions. So the error code + // is kinda random here + self.additional_signed.ok_or_else(|| { + frame_support::unsigned::TransactionValidityError::Unknown( + frame_support::unsigned::UnknownTransaction::Custom(0xFF), + ) + }) } fn pre_dispatch( From a031eac63c900169933c9351f9826a3832b09ed1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Feb 2022 15:35:45 +0300 Subject: [PATCH 0652/1210] use mortal transactions in transaction resubmitter (#1326) --- .../src/cli/resubmit_transactions.rs | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 81fa54dcd2dfb..d6edda3aafcd1 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -19,10 +19,10 @@ use crate::cli::{Balance, TargetConnectionParams, TargetSigningParams}; use codec::{Decode, Encode}; use num_traits::{One, Zero}; use relay_substrate_client::{ - BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderOf, SignParam, - TransactionSignScheme, + BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, + SignParam, TransactionSignScheme, }; -use relay_utils::FailedClient; +use relay_utils::{FailedClient, HeaderId}; use sp_core::Bytes; use sp_runtime::{ traits::{Hash, Header as HeaderT}, @@ -30,6 +30,7 @@ use sp_runtime::{ }; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::TransactionParams; /// Start resubmit transactions process. #[derive(StructOpt)] @@ -122,13 +123,16 @@ impl ResubmitTransactions { select_bridge!(self.chain, { let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); let client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; - let key_pair = self.target_sign.to_keypair::()?; + let transaction_params = TransactionParams { + signer: self.target_sign.to_keypair::()?, + mortality: self.target_sign.target_transactions_mortality, + }; relay_utils::relay_loop((), client) .run(relay_loop_name, move |_, client, _| { run_until_connection_lost::( client, - key_pair.clone(), + transaction_params.clone(), Context { strategy: self.strategy, best_header: HeaderOf::::new( @@ -219,13 +223,14 @@ impl Context { /// Run resubmit transactions loop. async fn run_until_connection_lost>( client: Client, - key_pair: S::AccountKeyPair, + transaction_params: TransactionParams, mut context: Context, ) -> Result<(), FailedClient> { loop { async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; - let result = run_loop_iteration::(client.clone(), key_pair.clone(), context).await; + let result = + run_loop_iteration::(client.clone(), transaction_params.clone(), context).await; context = match result { Ok(context) => context, Err(error) => { @@ -244,20 +249,21 @@ async fn run_until_connection_lost /// Run single loop iteration. async fn run_loop_iteration>( client: Client, - key_pair: S::AccountKeyPair, + transaction_params: TransactionParams, mut context: Context, ) -> Result, SubstrateError> { // correct best header is required for all other actions context.best_header = client.best_header().await?; // check if there's queued transaction, signed by given author - let original_transaction = match lookup_signer_transaction::(&client, &key_pair).await? { - Some(original_transaction) => original_transaction, - None => { - log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); - return Ok(context) - }, - }; + let original_transaction = + match lookup_signer_transaction::(&client, &transaction_params.signer).await? { + Some(original_transaction) => original_transaction, + None => { + log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); + return Ok(context) + }, + }; let original_transaction_hash = C::Hasher::hash(&original_transaction.encode()); let context = context.notice_transaction(original_transaction_hash); @@ -287,8 +293,8 @@ async fn run_loop_iteration>( // update transaction tip let (is_updated, updated_transaction) = update_transaction_tip::( &client, - &key_pair, - context.best_header.hash(), + &transaction_params, + HeaderId(*context.best_header.number(), context.best_header.hash()), original_transaction, context.tip_step, context.tip_limit, @@ -404,15 +410,15 @@ fn select_transaction_from_queue( /// Try to find appropriate tip for transaction so that its priority is larger than given. async fn update_transaction_tip>( client: &Client, - key_pair: &S::AccountKeyPair, - at_block: C::Hash, + transaction_params: &TransactionParams, + at_block: HeaderIdOf, tx: S::SignedTransaction, tip_step: C::Balance, tip_limit: C::Balance, target_priority: TransactionPriority, ) -> Result<(bool, S::SignedTransaction), SubstrateError> { let stx = format!("{:?}", tx); - let mut current_priority = client.validate_transaction(at_block, tx.clone()).await??.priority; + let mut current_priority = client.validate_transaction(at_block.1, tx.clone()).await??.priority; let mut unsigned_tx = S::parse_transaction(tx).ok_or_else(|| { SubstrateError::Custom(format!("Failed to parse {} transaction {}", C::NAME, stx,)) })?; @@ -437,12 +443,12 @@ async fn update_transaction_tip>( unsigned_tx.tip = next_tip; current_priority = client .validate_transaction( - at_block, + at_block.1, S::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: *client.genesis_hash(), - signer: key_pair.clone(), + signer: transaction_params.signer.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: unsigned_tx.clone(), })?, @@ -465,8 +471,11 @@ async fn update_transaction_tip>( spec_version, transaction_version, genesis_hash: *client.genesis_hash(), - signer: key_pair.clone(), - era: relay_substrate_client::TransactionEra::immortal(), + signer: transaction_params.signer.clone(), + era: relay_substrate_client::TransactionEra::new( + at_block, + transaction_params.mortality, + ), unsigned: unsigned_tx, })?, )) From 6c6680c3f333a060af58ef36b0f16a3cdf78ac24 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 24 Feb 2022 13:19:06 +0300 Subject: [PATCH 0653/1210] Using-same-fork metric for finality and complex relay (#1327) * using_same_fork metric in finality relay * support `using_different_forks` in messages relay * added dashboards and alerts * lockfile --- relays/client-substrate/src/sync_header.rs | 6 +- relays/finality/src/finality_loop.rs | 69 ++++-- relays/finality/src/finality_loop_tests.rs | 198 ++++++++++++------ relays/finality/src/lib.rs | 11 +- relays/finality/src/sync_loop_metrics.rs | 60 ++++-- .../src/finality_target.rs | 21 +- .../lib-substrate-relay/src/messages_lane.rs | 4 +- .../src/messages_source.rs | 82 +++++--- .../src/messages_target.rs | 57 ++--- .../src/on_demand_headers.rs | 22 +- relays/messages/Cargo.toml | 1 + relays/messages/src/message_lane_loop.rs | 7 + relays/messages/src/metrics.rs | 53 +++-- relays/utils/src/metrics.rs | 4 +- 14 files changed, 397 insertions(+), 198 deletions(-) diff --git a/relays/client-substrate/src/sync_header.rs b/relays/client-substrate/src/sync_header.rs index ed3de6289ce01..e45e6b4197abb 100644 --- a/relays/client-substrate/src/sync_header.rs +++ b/relays/client-substrate/src/sync_header.rs @@ -44,7 +44,11 @@ impl

From
for SyncHeader
{ } } -impl FinalitySourceHeader for SyncHeader
{ +impl FinalitySourceHeader for SyncHeader
{ + fn hash(&self) -> Header::Hash { + self.0.hash() + } + fn number(&self) -> Header::Number { *self.0.number() } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 320b44d310f0b..c29a5d5fec21f 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -29,7 +29,7 @@ use futures::{select, Future, FutureExt, Stream, StreamExt}; use num_traits::{One, Saturating}; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, retry_backoff, FailedClient, - MaybeConnectionError, + HeaderId, MaybeConnectionError, }; use std::{ pin::Pin, @@ -87,7 +87,9 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Get best finalized source block number. - async fn best_finalized_source_block_number(&self) -> Result; + async fn best_finalized_source_block_id( + &self, + ) -> Result, Self::Error>; /// Submit header finality proof. async fn submit_finality_proof( @@ -114,7 +116,11 @@ pub async fn run( let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(metrics_params) - .loop_metric(SyncLoopMetrics::new(Some(&metrics_prefix::

()))?)? + .loop_metric(SyncLoopMetrics::new( + Some(&metrics_prefix::

()), + "source", + "source_at_target", + )?)? .expose() .await? .run(metrics_prefix::

(), move |source_client, target_client, metrics| { @@ -169,7 +175,7 @@ where /// Information about transaction that we have submitted. #[derive(Debug, Clone)] -struct Transaction { +pub(crate) struct Transaction { /// Time when we have submitted this transaction. pub time: Instant, /// The number of the header we have submitted. @@ -181,7 +187,7 @@ pub(crate) struct RestartableFinalityProofsStream { /// Flag that the stream needs to be restarted. pub(crate) needs_restart: bool, /// The stream itself. - stream: Pin>, + pub(crate) stream: Pin>, } #[cfg(test)] @@ -192,15 +198,16 @@ impl From for RestartableFinalityProofsStream { } /// Finality synchronization loop state. -struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { +pub(crate) struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { /// Synchronization loop progress. - progress: &'a mut (Instant, Option), + pub(crate) progress: &'a mut (Instant, Option), /// Finality proofs stream. - finality_proofs_stream: &'a mut RestartableFinalityProofsStream, + pub(crate) finality_proofs_stream: + &'a mut RestartableFinalityProofsStream, /// Recent finality proofs that we have read from the stream. - recent_finality_proofs: &'a mut FinalityProofs

, + pub(crate) recent_finality_proofs: &'a mut FinalityProofs

, /// Last transaction that we have submitted to the target node. - last_transaction: Option>, + pub(crate) last_transaction: Option>, } async fn run_until_connection_lost( @@ -280,7 +287,7 @@ async fn run_until_connection_lost( } } -async fn run_loop_iteration( +pub(crate) async fn run_loop_iteration( source_client: &SC, target_client: &TC, state: FinalityLoopState<'_, P, SC::FinalityProofsStream>, @@ -295,13 +302,31 @@ where // read best source headers ids from source and target nodes let best_number_at_source = source_client.best_finalized_block_number().await.map_err(Error::Source)?; - let best_number_at_target = target_client - .best_finalized_source_block_number() + let best_id_at_target = + target_client.best_finalized_source_block_id().await.map_err(Error::Target)?; + let best_number_at_target = best_id_at_target.0; + + let different_hash_at_source = ensure_same_fork::(&best_id_at_target, source_client) .await - .map_err(Error::Target)?; + .map_err(Error::Source)?; + let using_same_fork = different_hash_at_source.is_none(); + if let Some(ref different_hash_at_source) = different_hash_at_source { + log::error!( + target: "bridge", + "Source node ({}) and pallet at target node ({}) have different headers at the same height {:?}: \ + at-source {:?} vs at-target {:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + best_number_at_target, + different_hash_at_source, + best_id_at_target.1, + ); + } + if let Some(ref metrics_sync) = *metrics_sync { metrics_sync.update_best_block_at_source(best_number_at_source); metrics_sync.update_best_block_at_target(best_number_at_target); + metrics_sync.update_using_same_fork(using_same_fork); } *state.progress = print_sync_progress::

(*state.progress, best_number_at_source, best_number_at_target); @@ -427,6 +452,22 @@ where Ok(selected_finality_proof) } +/// Ensures that both clients are on the same fork. +/// +/// Returns `Some(_)` with header has at the source client if headers are different. +async fn ensure_same_fork>( + best_id_at_target: &HeaderId, + source_client: &SC, +) -> Result, SC::Error> { + let header_at_source = source_client.header_and_finality_proof(best_id_at_target.0).await?.0; + let header_hash_at_source = header_at_source.hash(); + Ok(if best_id_at_target.1 == header_hash_at_source { + None + } else { + Some(header_hash_at_source) + }) +} + /// Finality proof that has been selected by the `read_missing_headers` function. pub(crate) enum SelectedFinalityProof { /// Mandatory header and its proof has been selected. We shall submit proof for this header. diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 915b7ee6766ef..478d8e1be652b 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -20,10 +20,12 @@ use crate::{ finality_loop::{ - prune_recent_finality_proofs, read_finality_proofs_from_stream, run, - select_better_recent_finality_proof, select_header_to_submit, FinalityProofs, - FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, TargetClient, + prune_recent_finality_proofs, read_finality_proofs_from_stream, run, run_loop_iteration, + select_better_recent_finality_proof, select_header_to_submit, FinalityLoopState, + FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, + TargetClient, }, + sync_loop_metrics::SyncLoopMetrics, FinalityProof, FinalitySyncPipeline, SourceHeader, }; @@ -31,12 +33,18 @@ use async_trait::async_trait; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, MaybeConnectionError, + metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError, +}; +use std::{ + collections::HashMap, + pin::Pin, + sync::Arc, + time::{Duration, Instant}, }; -use std::{collections::HashMap, pin::Pin, sync::Arc, time::Duration}; type IsMandatory = bool; type TestNumber = u64; +type TestHash = u64; #[derive(Debug, Clone)] enum TestError { @@ -56,16 +64,20 @@ impl FinalitySyncPipeline for TestFinalitySyncPipeline { const SOURCE_NAME: &'static str = "TestSource"; const TARGET_NAME: &'static str = "TestTarget"; - type Hash = u64; + type Hash = TestHash; type Number = TestNumber; type Header = TestSourceHeader; type FinalityProof = TestFinalityProof; } #[derive(Debug, Clone, PartialEq)] -struct TestSourceHeader(IsMandatory, TestNumber); +struct TestSourceHeader(IsMandatory, TestNumber, TestHash); + +impl SourceHeader for TestSourceHeader { + fn hash(&self) -> TestHash { + self.2 + } -impl SourceHeader for TestSourceHeader { fn number(&self) -> TestNumber { self.1 } @@ -90,7 +102,7 @@ struct ClientsData { source_headers: HashMap)>, source_proofs: Vec, - target_best_block_number: TestNumber, + target_best_block_id: HeaderId, target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, } @@ -152,10 +164,12 @@ impl RelayClient for TestTargetClient { #[async_trait] impl TargetClient for TestTargetClient { - async fn best_finalized_source_block_number(&self) -> Result { + async fn best_finalized_source_block_id( + &self, + ) -> Result, TestError> { let mut data = self.data.lock(); (self.on_method_call)(&mut *data); - Ok(data.target_best_block_number) + Ok(data.target_best_block_id) } async fn submit_finality_proof( @@ -165,7 +179,7 @@ impl TargetClient for TestTargetClient { ) -> Result<(), TestError> { let mut data = self.data.lock(); (self.on_method_call)(&mut *data); - data.target_best_block_number = header.number(); + data.target_best_block_id = HeaderId(header.number(), header.hash()); data.target_headers.push((header, proof)); Ok(()) } @@ -187,7 +201,7 @@ fn prepare_test_clients( source_headers, source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], - target_best_block_number: 5, + target_best_block_id: HeaderId(5, 5), target_headers: vec![], })); ( @@ -199,6 +213,15 @@ fn prepare_test_clients( ) } +fn test_sync_params() -> FinalitySyncParams { + FinalitySyncParams { + tick: Duration::from_secs(0), + recent_finality_proofs_limit: 1024, + stall_timeout: Duration::from_secs(1), + only_mandatory_headers: false, + } +} + fn run_sync_loop( state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, ) -> ClientsData { @@ -207,21 +230,17 @@ fn run_sync_loop( exit_sender, state_function, vec![ - (6, (TestSourceHeader(false, 6), None)), - (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(true, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10), None)), + (5, (TestSourceHeader(false, 5, 5), None)), + (6, (TestSourceHeader(false, 6, 6), None)), + (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), + (8, (TestSourceHeader(true, 8, 8), Some(TestFinalityProof(8)))), + (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), + (10, (TestSourceHeader(false, 10, 10), None)), ] .into_iter() .collect(), ); - let sync_params = FinalitySyncParams { - tick: Duration::from_secs(0), - recent_finality_proofs_limit: 1024, - stall_timeout: Duration::from_secs(1), - only_mandatory_headers: false, - }; + let sync_params = test_sync_params(); let clients_data = source_client.data.clone(); let _ = async_std::task::block_on(run( @@ -246,38 +265,38 @@ fn finality_sync_loop_works() { // // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from // the stream - if data.target_best_block_number == 9 { + if data.target_best_block_id.0 == 9 { data.source_best_block_number = 14; - data.source_headers.insert(11, (TestSourceHeader(false, 11), None)); + data.source_headers.insert(11, (TestSourceHeader(false, 11, 11), None)); data.source_headers - .insert(12, (TestSourceHeader(false, 12), Some(TestFinalityProof(12)))); - data.source_headers.insert(13, (TestSourceHeader(false, 13), None)); + .insert(12, (TestSourceHeader(false, 12, 12), Some(TestFinalityProof(12)))); + data.source_headers.insert(13, (TestSourceHeader(false, 13, 13), None)); data.source_headers - .insert(14, (TestSourceHeader(false, 14), Some(TestFinalityProof(14)))); + .insert(14, (TestSourceHeader(false, 14, 14), Some(TestFinalityProof(14)))); } // once this ^^^ is done, we generate more blocks && read persistent proof for block 16 - if data.target_best_block_number == 14 { + if data.target_best_block_id.0 == 14 { data.source_best_block_number = 17; - data.source_headers.insert(15, (TestSourceHeader(false, 15), None)); + data.source_headers.insert(15, (TestSourceHeader(false, 15, 15), None)); data.source_headers - .insert(16, (TestSourceHeader(false, 16), Some(TestFinalityProof(16)))); - data.source_headers.insert(17, (TestSourceHeader(false, 17), None)); + .insert(16, (TestSourceHeader(false, 16, 16), Some(TestFinalityProof(16)))); + data.source_headers.insert(17, (TestSourceHeader(false, 17, 17), None)); } - data.target_best_block_number == 16 + data.target_best_block_id.0 == 16 }); assert_eq!( client_data.target_headers, vec![ // before adding 11..14: finality proof for mandatory header#8 - (TestSourceHeader(true, 8), TestFinalityProof(8)), + (TestSourceHeader(true, 8, 8), TestFinalityProof(8)), // before adding 11..14: persistent finality proof for non-mandatory header#9 - (TestSourceHeader(false, 9), TestFinalityProof(9)), + (TestSourceHeader(false, 9, 9), TestFinalityProof(9)), // after adding 11..14: ephemeral finality proof for non-mandatory header#14 - (TestSourceHeader(false, 14), TestFinalityProof(14)), + (TestSourceHeader(false, 14, 14), TestFinalityProof(14)), // after adding 15..17: persistent finality proof for non-mandatory header#16 - (TestSourceHeader(false, 16), TestFinalityProof(16)), + (TestSourceHeader(false, 16, 16), TestFinalityProof(16)), ], ); } @@ -291,11 +310,11 @@ fn run_only_mandatory_headers_mode_test( exit_sender, |_| false, vec![ - (6, (TestSourceHeader(false, 6), Some(TestFinalityProof(6)))), - (7, (TestSourceHeader(false, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(has_mandatory_headers, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10), Some(TestFinalityProof(10)))), + (6, (TestSourceHeader(false, 6, 6), Some(TestFinalityProof(6)))), + (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), + (8, (TestSourceHeader(has_mandatory_headers, 8, 8), Some(TestFinalityProof(8)))), + (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), + (10, (TestSourceHeader(false, 10, 10), Some(TestFinalityProof(10)))), ] .into_iter() .collect(), @@ -322,7 +341,7 @@ fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_heade assert_eq!(run_only_mandatory_headers_mode_test(true, false), None); assert_eq!( run_only_mandatory_headers_mode_test(false, false), - Some((TestSourceHeader(false, 10), TestFinalityProof(10))), + Some((TestSourceHeader(false, 10, 10), TestFinalityProof(10))), ); } @@ -330,11 +349,11 @@ fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_heade fn select_header_to_submit_selects_mandatory_headers_when_only_mandatory_headers_are_required() { assert_eq!( run_only_mandatory_headers_mode_test(true, true), - Some((TestSourceHeader(true, 8), TestFinalityProof(8))), + Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), ); assert_eq!( run_only_mandatory_headers_mode_test(false, true), - Some((TestSourceHeader(true, 8), TestFinalityProof(8))), + Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), ); } @@ -345,63 +364,74 @@ fn select_better_recent_finality_proof_works() { select_better_recent_finality_proof::( &[(5, TestFinalityProof(5))], &mut vec![], - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ); // if there are no recent finality proofs, nothing is changed assert_eq!( select_better_recent_finality_proof::( &[], - &mut vec![TestSourceHeader(false, 5)], - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + &mut vec![TestSourceHeader(false, 5, 5)], + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ); // if there's no intersection between recent finality proofs and unjustified headers, nothing is // changed - let mut unjustified_headers = vec![TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; + let mut unjustified_headers = + vec![TestSourceHeader(false, 9, 9), TestSourceHeader(false, 10, 10)]; assert_eq!( select_better_recent_finality_proof::( &[(1, TestFinalityProof(1)), (4, TestFinalityProof(4))], &mut unjustified_headers, - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ); // if there's intersection between recent finality proofs and unjustified headers, but there are // no proofs in this intersection, nothing is changed - let mut unjustified_headers = - vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; + let mut unjustified_headers = vec![ + TestSourceHeader(false, 8, 8), + TestSourceHeader(false, 9, 9), + TestSourceHeader(false, 10, 10), + ]; assert_eq!( select_better_recent_finality_proof::( &[(7, TestFinalityProof(7)), (11, TestFinalityProof(11))], &mut unjustified_headers, - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ); assert_eq!( unjustified_headers, - vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)] + vec![ + TestSourceHeader(false, 8, 8), + TestSourceHeader(false, 9, 9), + TestSourceHeader(false, 10, 10) + ] ); // if there's intersection between recent finality proofs and unjustified headers and there's // a proof in this intersection: // - this better (last from intersection) proof is selected; // - 'obsolete' unjustified headers are pruned. - let mut unjustified_headers = - vec![TestSourceHeader(false, 8), TestSourceHeader(false, 9), TestSourceHeader(false, 10)]; + let mut unjustified_headers = vec![ + TestSourceHeader(false, 8, 8), + TestSourceHeader(false, 9, 9), + TestSourceHeader(false, 10, 10), + ]; assert_eq!( select_better_recent_finality_proof::( &[(7, TestFinalityProof(7)), (9, TestFinalityProof(9))], &mut unjustified_headers, - Some((TestSourceHeader(false, 2), TestFinalityProof(2))), + Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), ), - Some((TestSourceHeader(false, 9), TestFinalityProof(9))), + Some((TestSourceHeader(false, 9, 9), TestFinalityProof(9))), ); } @@ -475,3 +505,45 @@ fn prune_recent_finality_proofs_works() { prune_recent_finality_proofs::(20, &mut recent_finality_proofs, 2); assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); } + +#[test] +fn different_forks_at_source_and_at_target_are_detected() { + let (exit_sender, _exit_receiver) = futures::channel::mpsc::unbounded(); + let (source_client, target_client) = prepare_test_clients( + exit_sender, + |_| false, + vec![ + (5, (TestSourceHeader(false, 5, 42), None)), + (6, (TestSourceHeader(false, 6, 6), None)), + (7, (TestSourceHeader(false, 7, 7), None)), + (8, (TestSourceHeader(false, 8, 8), None)), + (9, (TestSourceHeader(false, 9, 9), None)), + (10, (TestSourceHeader(false, 10, 10), None)), + ] + .into_iter() + .collect(), + ); + + let mut progress = (Instant::now(), None); + let mut finality_proofs_stream = RestartableFinalityProofsStream { + needs_restart: false, + stream: Box::pin(futures::stream::iter(vec![]).boxed()), + }; + let mut recent_finality_proofs = Vec::new(); + let metrics_sync = SyncLoopMetrics::new(None, "source", "target").unwrap(); + async_std::task::block_on(run_loop_iteration::( + &source_client, + &target_client, + FinalityLoopState { + progress: &mut progress, + finality_proofs_stream: &mut finality_proofs_stream, + recent_finality_proofs: &mut recent_finality_proofs, + last_transaction: None, + }, + &test_sync_params(), + &Some(metrics_sync.clone()), + )) + .unwrap(); + + assert!(!metrics_sync.is_using_same_fork()); +} diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index 6421d13b787c8..49be64ff74db2 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -19,8 +19,9 @@ //! are still submitted to the target node, but are treated as auxiliary data as we are not trying //! to submit all source headers to the target node. -pub use crate::finality_loop::{ - metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient, +pub use crate::{ + finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}, + sync_loop_metrics::SyncLoopMetrics, }; use bp_header_chain::FinalityProof; @@ -42,13 +43,15 @@ pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers we're syncing are identified by this number. type Number: relay_utils::BlockNumberBase; /// Type of header that we're syncing. - type Header: SourceHeader; + type Header: SourceHeader; /// Finality proof type. type FinalityProof: FinalityProof; } /// Header that we're receiving from source node. -pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { +pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { + /// Returns hash of header. + fn hash(&self) -> Hash; /// Returns number of header. fn number(&self) -> Number; /// Returns true if this header needs to be submitted to target node. diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs index 1f65dac17c05e..a003a47d89096 100644 --- a/relays/finality/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -16,49 +16,71 @@ //! Metrics for headers synchronization relay loop. -use relay_utils::metrics::{ - metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, -}; +use relay_utils::metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry}; /// Headers sync metrics. #[derive(Clone)] pub struct SyncLoopMetrics { - /// Best syncing headers at "source" and "target" nodes. - best_block_numbers: GaugeVec, + /// Best syncing header at the source. + best_source_block_number: IntGauge, + /// Best syncing header at the target. + best_target_block_number: IntGauge, + /// Flag that has `0` value when best source headers at the source node and at-target-chain + /// are matching and `1` otherwise. + using_different_forks: IntGauge, } impl SyncLoopMetrics { /// Create and register headers loop metrics. - pub fn new(prefix: Option<&str>) -> Result { + pub fn new( + prefix: Option<&str>, + at_source_chain_label: &str, + at_target_chain_label: &str, + ) -> Result { Ok(SyncLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best block numbers on source and target nodes", - ), - &["node"], + best_source_block_number: IntGauge::new( + metric_name(prefix, &format!("best_{}_block_number", at_source_chain_label)), + format!("Best block number at the {}", at_source_chain_label), + )?, + best_target_block_number: IntGauge::new( + metric_name(prefix, &format!("best_{}_block_number", at_target_chain_label)), + format!("Best block number at the {}", at_target_chain_label), + )?, + using_different_forks: IntGauge::new( + metric_name(prefix, &format!("is_{}_and_{}_using_different_forks", at_source_chain_label, at_target_chain_label)), + "Whether the best finalized source block at target node is different (value 1) from the \ + corresponding block at the source node", )?, }) } + /// Returns current value of the using-same-fork flag. + #[cfg(test)] + pub(crate) fn is_using_same_fork(&self) -> bool { + self.using_different_forks.get() == 0 + } + /// Update best block number at source. pub fn update_best_block_at_source>(&self, source_best_number: Number) { - self.best_block_numbers - .with_label_values(&["source"]) - .set(source_best_number.into()); + self.best_source_block_number.set(source_best_number.into()); } /// Update best block number at target. pub fn update_best_block_at_target>(&self, target_best_number: Number) { - self.best_block_numbers - .with_label_values(&["target"]) - .set(target_best_number.into()); + self.best_target_block_number.set(target_best_number.into()); + } + + /// Update using-same-fork flag. + pub fn update_using_same_fork(&self, using_same_fork: bool) { + self.using_different_forks.set(if using_same_fork { 0 } else { 1 }) } } impl Metric for SyncLoopMetrics { fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.best_block_numbers.clone(), registry)?; + register(self.best_source_block_number.clone(), registry)?; + register(self.best_target_block_number.clone(), registry)?; + register(self.using_different_forks.clone(), registry)?; Ok(()) } } diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index e7a7487ae2c17..b7bc90cb4de79 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -30,8 +30,8 @@ use bp_header_chain::{justification::GrandpaJustification, storage_keys::is_halt use codec::Encode; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, ChainWithGrandpa, Client, Error, HashOf, - HeaderOf, SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithGrandpa, Client, Error, HeaderIdOf, HeaderOf, + SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::{Bytes, Pair}; @@ -90,23 +90,20 @@ where AccountIdOf: From< as Pair>::Public>, P::TransactionSignScheme: TransactionSignScheme, { - async fn best_finalized_source_block_number( - &self, - ) -> Result, Error> { + async fn best_finalized_source_block_id(&self) -> Result, Error> { // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay self.client.ensure_synced().await?; // we can't relay finality if GRANDPA pallet at target chain is halted self.ensure_pallet_active().await?; - Ok(crate::messages_source::read_client_state::< - P::TargetChain, - HashOf, - BlockNumberOf, - >(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD) + Ok(crate::messages_source::read_client_state::( + &self.client, + None, + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) .await? - .best_finalized_peer_at_best_self - .0) + .best_finalized_peer_at_best_self) } async fn submit_finality_proof( diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index a88b9441cd1ee..2da434c8c7c68 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -234,13 +234,15 @@ where }, }, SubstrateMessagesSource::

::new( - source_client, + source_client.clone(), + target_client.clone(), params.lane_id, params.source_transaction_params, params.target_to_source_headers_relay, ), SubstrateMessagesTarget::

::new( target_client, + source_client, params.lane_id, relayer_id_at_source, params.target_transaction_params, diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 96e19beba25ca..39d1586626774 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -46,7 +46,7 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; @@ -62,7 +62,8 @@ pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof { - client: Client, + source_client: Client, + target_client: Client, lane_id: LaneId, transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, @@ -71,13 +72,15 @@ pub struct SubstrateMessagesSource { impl SubstrateMessagesSource

{ /// Create new Substrate headers source. pub fn new( - client: Client, + source_client: Client, + target_client: Client, lane_id: LaneId, transaction_params: TransactionParams>, target_to_source_headers_relay: Option>, ) -> Self { SubstrateMessagesSource { - client, + source_client, + target_client, lane_id, transaction_params, target_to_source_headers_relay, @@ -89,7 +92,7 @@ impl SubstrateMessagesSource

{ &self, id: SourceHeaderIdOf>, ) -> Result, SubstrateError> { - self.client + self.source_client .storage_value( outbound_lane_data_key( P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, @@ -102,14 +105,15 @@ impl SubstrateMessagesSource

{ /// Ensure that the messages pallet at source chain is active. async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> { - ensure_messages_pallet_active::(&self.client).await + ensure_messages_pallet_active::(&self.source_client).await } } impl Clone for SubstrateMessagesSource

{ fn clone(&self) -> Self { Self { - client: self.client.clone(), + source_client: self.source_client.clone(), + target_client: self.target_client.clone(), lane_id: self.lane_id, transaction_params: self.transaction_params.clone(), target_to_source_headers_relay: self.target_to_source_headers_relay.clone(), @@ -122,7 +126,8 @@ impl RelayClient for SubstrateMessagesSource

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { - self.client.reconnect().await + self.source_client.reconnect().await?; + self.target_client.reconnect().await } } @@ -136,15 +141,15 @@ where async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver - self.client.ensure_synced().await?; + self.source_client.ensure_synced().await?; // we can't relay confirmations if messages pallet at source chain is halted self.ensure_pallet_active().await?; - read_client_state::< - _, - as MessageLane>::TargetHeaderHash, - as MessageLane>::TargetHeaderNumber, - >(&self.client, P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD) + read_client_state( + &self.source_client, + Some(&self.target_client), + P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) .await } @@ -183,7 +188,7 @@ where SubstrateError, > { let encoded_response = self - .client + .source_client .state_call( P::TargetChain::TO_CHAIN_MESSAGE_DETAILS_METHOD.into(), Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), @@ -230,7 +235,12 @@ where )); } - let proof = self.client.prove_storage(storage_keys, id.1).await?.iter_nodes().collect(); + let proof = self + .source_client + .prove_storage(storage_keys, id.1) + .await? + .iter_nodes() + .collect(); let proof = FromBridgedChainMessagesProof { bridged_header_hash: id.1, storage_proof: proof, @@ -246,10 +256,11 @@ where _generated_at_block: TargetHeaderIdOf>, proof: as MessageLane>::MessagesReceivingProof, ) -> Result<(), SubstrateError> { - let genesis_hash = *self.client.genesis_hash(); + let genesis_hash = *self.source_client.genesis_hash(); let transaction_params = self.transaction_params.clone(); - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; - self.client + let (spec_version, transaction_version) = + self.source_client.simple_runtime_version().await?; + self.source_client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { @@ -278,7 +289,7 @@ where async fn estimate_confirmation_transaction( &self, ) -> as MessageLane>::SourceChainBalance { - let runtime_version = match self.client.runtime_version().await { + let runtime_version = match self.source_client.runtime_version().await { Ok(v) => v, Err(_) => return BalanceOf::::max_value(), }; @@ -286,14 +297,14 @@ where let dummy_tx = make_messages_delivery_proof_transaction::

( runtime_version.spec_version, runtime_version.transaction_version, - self.client.genesis_hash(), + self.source_client.genesis_hash(), &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), prepare_dummy_messages_delivery_proof::(), false, )?; - self.client + self.source_client .estimate_extrinsic_fee(dummy_tx) .await .map(|fee| fee.inclusion_fee()) @@ -385,19 +396,19 @@ fn prepare_dummy_messages_delivery_proof( /// This function assumes that the chain that is followed by the `self_client` has /// bridge GRANDPA pallet deployed and it provides `best_finalized_header_id_method_name` /// runtime API to read the best finalized Bridged chain header. -pub async fn read_client_state( +/// +/// If `peer_client` is `None`, the value of `actual_best_finalized_peer_at_best_self` will +/// always match the `best_finalized_peer_at_best_self`. +pub async fn read_client_state( self_client: &Client, + peer_client: Option<&Client>, best_finalized_header_id_method_name: &str, -) -> Result< - ClientState, HeaderId>, - SubstrateError, -> +) -> Result, HeaderIdOf>, SubstrateError> where SelfChain: Chain, SelfChain::Header: DeserializeOwned, SelfChain::Index: DeserializeOwned, - BridgedHeaderHash: Decode, - BridgedHeaderNumber: Decode, + PeerChain: Chain, { // let's read our state first: we need best finalized header hash on **this** chain let self_best_finalized_header_hash = self_client.best_finalized_header_hash().await?; @@ -419,16 +430,27 @@ where Some(self_best_hash), ) .await?; - let decoded_best_finalized_peer_on_self: (BridgedHeaderNumber, BridgedHeaderHash) = + let decoded_best_finalized_peer_on_self: (BlockNumberOf, HashOf) = Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]) .map_err(SubstrateError::ResponseParseFailed)?; let peer_on_self_best_finalized_id = HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); + // read actual header, matching the `peer_on_self_best_finalized_id` from the peer chain + let actual_peer_on_self_best_finalized_id = match peer_client { + Some(peer_client) => { + let actual_peer_on_self_best_finalized = + peer_client.header_by_number(peer_on_self_best_finalized_id.0).await?; + HeaderId(peer_on_self_best_finalized_id.0, actual_peer_on_self_best_finalized.hash()) + }, + None => peer_on_self_best_finalized_id.clone(), + }; + Ok(ClientState { best_self: self_best_id, best_finalized_self: self_best_finalized_id, best_finalized_peer_at_best_self: peer_on_self_best_finalized_id, + actual_best_finalized_peer_at_best_self: actual_peer_on_self_best_finalized_id, }) } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 72267cbc09ac6..0815559f215c3 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -57,7 +57,8 @@ pub type SubstrateMessagesDeliveryProof = /// Substrate client as Substrate messages target. pub struct SubstrateMessagesTarget { - client: Client, + target_client: Client, + source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, @@ -68,7 +69,8 @@ pub struct SubstrateMessagesTarget { impl SubstrateMessagesTarget

{ /// Create new Substrate headers target. pub fn new( - client: Client, + target_client: Client, + source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, @@ -76,7 +78,8 @@ impl SubstrateMessagesTarget

{ source_to_target_headers_relay: Option>, ) -> Self { SubstrateMessagesTarget { - client, + target_client, + source_client, lane_id, relayer_id_at_source, transaction_params, @@ -90,7 +93,7 @@ impl SubstrateMessagesTarget

{ &self, id: TargetHeaderIdOf>, ) -> Result>>, SubstrateError> { - self.client + self.target_client .storage_value( inbound_lane_data_key( P::SourceChain::WITH_CHAIN_MESSAGES_PALLET_NAME, @@ -103,14 +106,15 @@ impl SubstrateMessagesTarget

{ /// Ensure that the messages pallet at target chain is active. async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> { - ensure_messages_pallet_active::(&self.client).await + ensure_messages_pallet_active::(&self.target_client).await } } impl Clone for SubstrateMessagesTarget

{ fn clone(&self) -> Self { Self { - client: self.client.clone(), + target_client: self.target_client.clone(), + source_client: self.source_client.clone(), lane_id: self.lane_id, relayer_id_at_source: self.relayer_id_at_source.clone(), transaction_params: self.transaction_params.clone(), @@ -125,7 +129,8 @@ impl RelayClient for SubstrateMessagesTarget

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { - self.client.reconnect().await + self.target_client.reconnect().await?; + self.source_client.reconnect().await } } @@ -140,15 +145,15 @@ where async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver - self.client.ensure_synced().await?; + self.target_client.ensure_synced().await?; // we can't relay messages if messages pallet at target chain is halted self.ensure_pallet_active().await?; - read_client_state::< - _, - as MessageLane>::SourceHeaderHash, - as MessageLane>::SourceHeaderNumber, - >(&self.client, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD) + read_client_state( + &self.target_client, + Some(&self.source_client), + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) .await } @@ -184,7 +189,7 @@ where ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> { let encoded_response = self - .client + .target_client .state_call( P::SourceChain::FROM_CHAIN_UNREWARDED_RELAYERS_STATE.into(), Bytes(self.lane_id.encode()), @@ -213,7 +218,7 @@ where &self.lane_id, ); let proof = self - .client + .target_client .prove_storage(vec![inbound_data_key], id.1) .await? .iter_nodes() @@ -232,12 +237,13 @@ where nonces: RangeInclusive, proof: as MessageLane>::MessagesProof, ) -> Result, SubstrateError> { - let genesis_hash = *self.client.genesis_hash(); + let genesis_hash = *self.target_client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let relayer_id_at_source = self.relayer_id_at_source.clone(); let nonces_clone = nonces.clone(); - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; - self.client + let (spec_version, transaction_version) = + self.target_client.simple_runtime_version().await?; + self.target_client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { @@ -281,12 +287,13 @@ where )) })?; - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; + let (spec_version, transaction_version) = + self.target_client.simple_runtime_version().await?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. let delivery_tx = make_messages_delivery_transaction::

( spec_version, transaction_version, - self.client.genesis_hash(), + self.target_client.genesis_hash(), &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), @@ -299,7 +306,7 @@ where ), false, )?; - let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; + let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch @@ -321,12 +328,13 @@ where let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { const WEIGHT_DIFFERENCE: Weight = 100; - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; + let (spec_version, transaction_version) = + self.target_client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); let dummy_tx = make_messages_delivery_transaction::

( spec_version, transaction_version, - self.client.genesis_hash(), + self.target_client.genesis_hash(), &self.transaction_params, HeaderId(Default::default(), Default::default()), Zero::zero(), @@ -339,7 +347,8 @@ where ), false, )?; - let larger_delivery_tx_fee = self.client.estimate_extrinsic_fee(dummy_tx).await?; + let larger_delivery_tx_fee = + self.target_client.estimate_extrinsic_fee(dummy_tx).await?; compute_prepaid_messages_refund::( total_prepaid_nonces, diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index 9a6a062d7d8e0..c1401a28a6dd8 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -382,16 +382,20 @@ where From< as sp_core::Pair>::Public>, P::TransactionSignScheme: TransactionSignScheme, { - finality_target.best_finalized_source_block_number().await.map_err(|error| { - log::error!( - target: "bridge", - "Failed to read best finalized source header from target in {} relay: {:?}", - relay_task_name, - error, - ); + finality_target + .best_finalized_source_block_id() + .await + .map_err(|error| { + log::error!( + target: "bridge", + "Failed to read best finalized source header from target in {} relay: {:?}", + relay_task_name, + error, + ); - error - }) + error + }) + .map(|id| id.0) } /// Read first mandatory header in given inclusive range. diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index b11f00b957a42..3b3551114a6c0 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -18,6 +18,7 @@ parking_lot = "0.11.0" bp-messages = { path = "../../primitives/messages" } bp-runtime = { path = "../../primitives/runtime" } +finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 6cdb2b1aa5aee..c1778d5d11e87 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -233,6 +233,9 @@ pub struct ClientState { /// Best finalized header id of the peer chain read at the best block of this chain (at /// `best_finalized_self`). pub best_finalized_peer_at_best_self: PeerHeaderId, + /// Header id of the peer chain with the number, matching the + /// `best_finalized_peer_at_best_self`. + pub actual_best_finalized_peer_at_best_self: PeerHeaderId, } /// State of source client in one-way message lane. @@ -843,12 +846,14 @@ pub(crate) mod tests { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), }, source_latest_generated_nonce: 1, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), }, target_latest_received_nonce: 0, ..Default::default() @@ -888,12 +893,14 @@ pub(crate) mod tests { best_self: HeaderId(10, 10), best_finalized_self: HeaderId(10, 10), best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), }, source_latest_generated_nonce: 10, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), }, target_latest_received_nonce: 0, ..Default::default() diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index eac2f703692a1..4decb7e092e71 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -22,6 +22,7 @@ use crate::{ }; use bp_messages::MessageNonce; +use finality_relay::SyncLoopMetrics; use relay_utils::metrics::{ metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, }; @@ -31,8 +32,10 @@ use relay_utils::metrics::{ /// Cloning only clones references. #[derive(Clone)] pub struct MessageLaneLoopMetrics { + /// Best finalized block numbers - "source", "source_at_target", "target_at_source". + source_to_target_finality_metrics: SyncLoopMetrics, /// Best finalized block numbers - "source", "target", "source_at_target", "target_at_source". - best_block_numbers: GaugeVec, + target_to_source_finality_metrics: SyncLoopMetrics, /// Lane state nonces: "source_latest_generated", "source_latest_confirmed", /// "target_latest_received", "target_latest_confirmed". lane_state_nonces: GaugeVec, @@ -42,12 +45,15 @@ impl MessageLaneLoopMetrics { /// Create and register messages loop metrics. pub fn new(prefix: Option<&str>) -> Result { Ok(MessageLaneLoopMetrics { - best_block_numbers: GaugeVec::new( - Opts::new( - metric_name(prefix, "best_block_numbers"), - "Best finalized block numbers", - ), - &["type"], + source_to_target_finality_metrics: SyncLoopMetrics::new( + prefix, + "source", + "source_at_target", + )?, + target_to_source_finality_metrics: SyncLoopMetrics::new( + prefix, + "target", + "target_at_source", )?, lane_state_nonces: GaugeVec::new( Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), @@ -58,22 +64,28 @@ impl MessageLaneLoopMetrics { /// Update source client state metrics. pub fn update_source_state(&self, source_client_state: SourceClientState

) { - self.best_block_numbers - .with_label_values(&["source"]) - .set(source_client_state.best_self.0.into()); - self.best_block_numbers - .with_label_values(&["target_at_source"]) - .set(source_client_state.best_finalized_peer_at_best_self.0.into()); + self.source_to_target_finality_metrics + .update_best_block_at_source(source_client_state.best_self.0.into()); + self.target_to_source_finality_metrics.update_best_block_at_target( + source_client_state.best_finalized_peer_at_best_self.0.into(), + ); + self.target_to_source_finality_metrics.update_using_same_fork( + source_client_state.best_finalized_peer_at_best_self.1 == + source_client_state.actual_best_finalized_peer_at_best_self.1, + ); } /// Update target client state metrics. pub fn update_target_state(&self, target_client_state: TargetClientState

) { - self.best_block_numbers - .with_label_values(&["target"]) - .set(target_client_state.best_self.0.into()); - self.best_block_numbers - .with_label_values(&["source_at_target"]) - .set(target_client_state.best_finalized_peer_at_best_self.0.into()); + self.target_to_source_finality_metrics + .update_best_block_at_source(target_client_state.best_self.0.into()); + self.source_to_target_finality_metrics.update_best_block_at_target( + target_client_state.best_finalized_peer_at_best_self.0.into(), + ); + self.source_to_target_finality_metrics.update_using_same_fork( + target_client_state.best_finalized_peer_at_best_self.1 == + target_client_state.actual_best_finalized_peer_at_best_self.1, + ); } /// Update latest generated nonce at source. @@ -119,7 +131,8 @@ impl MessageLaneLoopMetrics { impl Metric for MessageLaneLoopMetrics { fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.best_block_numbers.clone(), registry)?; + self.source_to_target_finality_metrics.register(registry)?; + self.target_to_source_finality_metrics.register(registry)?; register(self.lane_state_nonces.clone(), registry)?; Ok(()) } diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 805fe70bfe858..084f72e7950c5 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -18,7 +18,7 @@ pub use float_json_value::FloatJsonValueMetric; pub use global::GlobalMetrics; pub use substrate_prometheus_endpoint::{ prometheus::core::{Atomic, Collector}, - register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, U64, + register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, I64, U64, }; use async_std::sync::{Arc, RwLock}; @@ -30,6 +30,8 @@ mod global; /// Shared reference to `f64` value that is updated by the metric. pub type F64SharedRef = Arc>>; +/// Int gauge metric type. +pub type IntGauge = Gauge; /// Unparsed address that needs to be used to expose Prometheus metrics. #[derive(Debug, Clone)] From 0e635b78a89d69d38120a1c6e6ce4833fa8e124b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 25 Feb 2022 11:34:57 +0300 Subject: [PATCH 0654/1210] removed extra *_RUNTIME_VERSION consts from relay code (#1330) --- relays/bin-substrate/src/cli/bridge.rs | 30 ----------------- relays/bin-substrate/src/cli/estimate_fee.rs | 2 +- relays/bin-substrate/src/cli/init_bridge.rs | 32 ++----------------- relays/bin-substrate/src/cli/mod.rs | 8 ++--- .../src/cli/register_parachain.rs | 13 ++------ relays/bin-substrate/src/cli/relay_headers.rs | 32 ++----------------- .../src/cli/relay_headers_and_messages.rs | 19 ++--------- .../bin-substrate/src/cli/relay_messages.rs | 4 +-- .../src/cli/resubmit_transactions.rs | 8 +---- relays/bin-substrate/src/cli/send_message.rs | 7 ++-- relays/bin-substrate/src/cli/swap_tokens.rs | 9 ++---- 11 files changed, 19 insertions(+), 145 deletions(-) diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index ea16c92c9203a..2eb836a84a753 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -77,11 +77,6 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use millau_runtime::millau_to_rialto_account_ownership_digest as account_ownership_digest; - #[allow(dead_code)] - const SOURCE_RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); - #[allow(dead_code)] - const TARGET_RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); - $generic } FullBridge::RialtoToMillau => { @@ -105,11 +100,6 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest; - #[allow(dead_code)] - const SOURCE_RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); - #[allow(dead_code)] - const TARGET_RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); - $generic } FullBridge::RococoToWococo => { @@ -132,11 +122,6 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_rococo_client::runtime::rococo_to_wococo_account_ownership_digest as account_ownership_digest; - #[allow(dead_code)] - const SOURCE_RUNTIME_VERSION: Option = Some(bp_rococo::VERSION); - #[allow(dead_code)] - const TARGET_RUNTIME_VERSION: Option = Some(bp_wococo::VERSION); - $generic } FullBridge::WococoToRococo => { @@ -159,11 +144,6 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest; - #[allow(dead_code)] - const SOURCE_RUNTIME_VERSION: Option = Some(bp_wococo::VERSION); - #[allow(dead_code)] - const TARGET_RUNTIME_VERSION: Option = Some(bp_rococo::VERSION); - $generic } FullBridge::KusamaToPolkadot => { @@ -186,11 +166,6 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_kusama_client::runtime::kusama_to_polkadot_account_ownership_digest as account_ownership_digest; - #[allow(dead_code)] - const SOURCE_RUNTIME_VERSION: Option = Some(bp_kusama::VERSION); - #[allow(dead_code)] - const TARGET_RUNTIME_VERSION: Option = Some(bp_polkadot::VERSION); - $generic } FullBridge::PolkadotToKusama => { @@ -213,11 +188,6 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use relay_polkadot_client::runtime::polkadot_to_kusama_account_ownership_digest as account_ownership_digest; - #[allow(dead_code)] - const SOURCE_RUNTIME_VERSION: Option = Some(bp_polkadot::VERSION); - #[allow(dead_code)] - const TARGET_RUNTIME_VERSION: Option = Some(bp_kusama::VERSION); - $generic } } diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 30bcae079b091..ff5bffacdf7c0 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -46,7 +46,7 @@ impl EstimateFee { let Self { source, bridge, lane, payload } = self; select_full_bridge!(bridge, { - let source_client = source.to_client::(SOURCE_RUNTIME_VERSION).await?; + let source_client = source.to_client::().await?; let lane = lane.into(); let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index ad133e369f59a..a0129ce9baa46 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -56,10 +56,6 @@ macro_rules! select_bridge { InitBridgeName::MillauToRialto => { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; - const SOURCE_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -78,10 +74,6 @@ macro_rules! select_bridge { InitBridgeName::RialtoToMillau => { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; - const SOURCE_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -100,10 +92,6 @@ macro_rules! select_bridge { InitBridgeName::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_westend::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -126,10 +114,6 @@ macro_rules! select_bridge { InitBridgeName::RococoToWococo => { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_rococo::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_wococo::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -146,10 +130,6 @@ macro_rules! select_bridge { InitBridgeName::WococoToRococo => { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_wococo::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_rococo::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -166,10 +146,6 @@ macro_rules! select_bridge { InitBridgeName::KusamaToPolkadot => { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_kusama::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_polkadot::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -186,10 +162,6 @@ macro_rules! select_bridge { InitBridgeName::PolkadotToKusama => { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_polkadot::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_kusama::VERSION); fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -211,8 +183,8 @@ impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; - let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; + let source_client = self.source.to_client::().await?; + let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; let (spec_version, transaction_version) = diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index ae169f773eff6..a91dfc5d54ad6 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -541,11 +541,10 @@ macro_rules! declare_chain_options { /// Convert connection params into Substrate client. pub async fn to_client( &self, - bundle_runtime_version: Option ) -> anyhow::Result> { let chain_runtime_version = self .[<$chain_prefix _runtime_version>] - .into_runtime_version(bundle_runtime_version)?; + .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { host: self.[<$chain_prefix _host>].clone(), port: self.[<$chain_prefix _port>], @@ -562,14 +561,13 @@ macro_rules! declare_chain_options { #[allow(dead_code)] pub async fn selected_chain_spec_version( &self, - bundle_runtime_version: Option, ) -> anyhow::Result { let chain_runtime_version = self .[<$chain_prefix _runtime_version>] - .into_runtime_version(bundle_runtime_version.clone())?; + .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; Ok(match chain_runtime_version { ChainRuntimeVersion::Auto => self - .to_client::(bundle_runtime_version) + .to_client::() .await? .simple_runtime_version() .await? diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 4ede369026111..4d75143755890 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -84,11 +84,6 @@ macro_rules! select_bridge { use bp_rialto::{PARAS_PALLET_NAME, PARAS_REGISTRAR_PALLET_NAME}; - const RELAY_CHAIN_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); - const PARA_CHAIN_RUNTIME_VERSION: Option = - Some(rialto_parachain_runtime::VERSION); - $generic }, } @@ -99,13 +94,9 @@ impl RegisterParachain { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.parachain, { - let relay_client = self - .relay_connection - .to_client::(RELAY_CHAIN_RUNTIME_VERSION) - .await?; + let relay_client = self.relay_connection.to_client::().await?; let relay_sign = self.relay_sign.to_keypair::()?; - let para_client = - self.para_connection.to_client::(PARA_CHAIN_RUNTIME_VERSION).await?; + let para_client = self.para_connection.to_client::().await?; // hopefully we're the only actor that is registering parachain right now // => read next parachain id diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index e3c7fe76d3c37..45034aba4b5e8 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -64,10 +64,6 @@ macro_rules! select_bridge { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; - const SOURCE_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); $generic }, @@ -75,10 +71,6 @@ macro_rules! select_bridge { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; - const SOURCE_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); $generic }, @@ -86,10 +78,6 @@ macro_rules! select_bridge { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_westend::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); $generic }, @@ -97,10 +85,6 @@ macro_rules! select_bridge { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_rococo::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_wococo::VERSION); $generic }, @@ -108,10 +92,6 @@ macro_rules! select_bridge { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_wococo::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_rococo::VERSION); $generic }, @@ -119,10 +99,6 @@ macro_rules! select_bridge { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_kusama::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_polkadot::VERSION); $generic }, @@ -130,10 +106,6 @@ macro_rules! select_bridge { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; - const SOURCE_RUNTIME_VERSION: Option = - Some(bp_polkadot::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(bp_kusama::VERSION); $generic }, @@ -145,8 +117,8 @@ impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; - let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; + let source_client = self.source.to_client::().await?; + let target_client = self.target.to_client::().await?; let target_transactions_mortality = self.target_sign.target_transactions_mortality; let target_sign = self.target_sign.to_keypair::()?; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index c8d74b8faec13..47336000338f8 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -133,11 +133,6 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_millau::AccountIdConverter; type RightAccountIdConverter = bp_rialto::AccountIdConverter; - const LEFT_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); - const RIGHT_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); - use crate::chains::{ millau_messages_to_rialto::{ update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, @@ -181,11 +176,6 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_rococo::AccountIdConverter; type RightAccountIdConverter = bp_wococo::AccountIdConverter; - const LEFT_RUNTIME_VERSION: Option = - Some(bp_rococo::VERSION); - const RIGHT_RUNTIME_VERSION: Option = - Some(bp_wococo::VERSION); - use crate::chains::{ rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane, wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, @@ -259,11 +249,6 @@ macro_rules! select_bridge { type LeftAccountIdConverter = bp_kusama::AccountIdConverter; type RightAccountIdConverter = bp_polkadot::AccountIdConverter; - const LEFT_RUNTIME_VERSION: Option = - Some(bp_kusama::VERSION); - const RIGHT_RUNTIME_VERSION: Option = - Some(bp_polkadot::VERSION); - use crate::chains::{ kusama_messages_to_polkadot::{ update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, @@ -335,12 +320,12 @@ impl RelayHeadersAndMessages { select_bridge!(self, { let params: Params = self.into(); - let left_client = params.left.to_client::(LEFT_RUNTIME_VERSION).await?; + let left_client = params.left.to_client::().await?; let left_transactions_mortality = params.left_sign.transactions_mortality()?; let left_sign = params.left_sign.to_keypair::()?; let left_messages_pallet_owner = params.left_messages_pallet_owner.to_keypair::()?; - let right_client = params.right.to_client::(RIGHT_RUNTIME_VERSION).await?; + let right_client = params.right.to_client::().await?; let right_transactions_mortality = params.right_sign.transactions_mortality()?; let right_sign = params.right_sign.to_keypair::()?; let right_messages_pallet_owner = diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 521d00d50a91f..45087fad5eb3f 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -75,10 +75,10 @@ impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_full_bridge!(self.bridge, { - let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; + let source_client = self.source.to_client::().await?; let source_sign = self.source_sign.to_keypair::()?; let source_transactions_mortality = self.source_sign.transactions_mortality()?; - let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; + let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; let target_transactions_mortality = self.target_sign.transactions_mortality()?; let relayer_mode = self.relayer_mode.into(); diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index d6edda3aafcd1..f92c035082cbd 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -92,24 +92,18 @@ macro_rules! select_bridge { RelayChain::Millau => { type Target = relay_millau_client::Millau; type TargetSign = relay_millau_client::Millau; - const TARGET_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); $generic }, RelayChain::Kusama => { type Target = relay_kusama_client::Kusama; type TargetSign = relay_kusama_client::Kusama; - const TARGET_RUNTIME_VERSION: Option = - Some(bp_kusama::VERSION); $generic }, RelayChain::Polkadot => { type Target = relay_polkadot_client::Polkadot; type TargetSign = relay_polkadot_client::Polkadot; - const TARGET_RUNTIME_VERSION: Option = - Some(bp_polkadot::VERSION); $generic }, @@ -122,7 +116,7 @@ impl ResubmitTransactions { pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.chain, { let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); - let client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; + let client = self.target.to_client::().await?; let transaction_params = TransactionParams { signer: self.target_sign.to_keypair::()?, mortality: self.target_sign.target_transactions_mortality, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 45f5fa89d02e9..372ce1fa2a07a 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -116,10 +116,7 @@ impl SendMessage { encode_call::preprocess_call::(message, bridge.bridge_instance_index()); let target_call = Target::encode_call(message)?; - let target_spec_version = self - .target - .selected_chain_spec_version::(Some(Target::RUNTIME_VERSION)) - .await?; + let target_spec_version = self.target.selected_chain_spec_version::().await?; let payload = { let target_call_weight = prepare_call_dispatch_weight( @@ -168,7 +165,7 @@ impl SendMessage { crate::select_full_bridge!(self.bridge, { let payload = self.encode_payload().await?; - let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; + let source_client = self.source.to_client::().await?; let source_sign = self.source_sign.to_keypair::()?; let lane = self.lane.clone().into(); diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index b9cdac7d3487e..c4b80ec66b9c6 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -101,11 +101,6 @@ macro_rules! select_bridge { const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; - const SOURCE_RUNTIME_VERSION: Option = - Some(millau_runtime::VERSION); - const TARGET_RUNTIME_VERSION: Option = - Some(rialto_runtime::VERSION); - type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; use bp_millau::{ @@ -134,9 +129,9 @@ impl SwapTokens { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.bridge, { - let source_client = self.source.to_client::(SOURCE_RUNTIME_VERSION).await?; + let source_client = self.source.to_client::().await?; let source_sign = self.source_sign.to_keypair::()?; - let target_client = self.target.to_client::(TARGET_RUNTIME_VERSION).await?; + let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; // names of variables in this function are matching names used by the From c00af5d974458074926065cbcde5ecbdb54b2f20 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 1 Mar 2022 14:56:25 +0300 Subject: [PATCH 0655/1210] Reinitialize bridge relay subcommand (#1331) * reinitialize bridge subcommand * PolkadotToKusama in reinit-bridge --- relays/bin-substrate/Cargo.toml | 6 +- relays/bin-substrate/src/cli/mod.rs | 7 + relays/bin-substrate/src/cli/reinit_bridge.rs | 553 ++++++++++++++++++ relays/client-kusama/src/runtime.rs | 12 + relays/client-polkadot/src/runtime.rs | 12 + .../src/finality_pipeline.rs | 2 +- .../src/finality_target.rs | 2 +- 7 files changed, 590 insertions(+), 4 deletions(-) create mode 100644 relays/bin-substrate/src/cli/reinit_bridge.rs diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 0bfff98d18655..84158d2cf9233 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -31,15 +31,16 @@ bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } -bp-token-swap = { path = "../../primitives/token-swap" } -bp-wococo = { path = "../../primitives/chain-wococo" } bp-runtime = { path = "../../primitives/runtime" } +bp-token-swap = { path = "../../primitives/token-swap" } bp-westend = { path = "../../primitives/chain-westend" } +bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-dispatch = { path = "../../modules/dispatch" } +pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } pallet-bridge-token-swap = { path = "../../modules/token-swap" } relay-kusama-client = { path = "../client-kusama" } @@ -73,6 +74,7 @@ polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", bran polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } [dev-dependencies] +bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index a91dfc5d54ad6..df57537f588ec 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -35,6 +35,7 @@ pub(crate) mod send_message; mod derive_account; mod init_bridge; mod register_parachain; +mod reinit_bridge; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; @@ -71,6 +72,11 @@ pub enum Command { /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. InitBridge(init_bridge::InitBridge), + /// Reinitialize on-chain bridge pallet with current header data. + /// + /// Sends all missing mandatory headers to bootstrap the bridge with current finalized block + /// data. + ReinitBridge(reinit_bridge::ReinitBridge), /// Send custom message over the bridge. /// /// Allows interacting with the bridge by sending messages over `Messages` component. @@ -126,6 +132,7 @@ impl Command { Self::RelayMessages(arg) => arg.run().await?, Self::RelayHeadersAndMessages(arg) => arg.run().await?, Self::InitBridge(arg) => arg.run().await?, + Self::ReinitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, Self::EncodeCall(arg) => arg.run().await?, Self::EncodeMessage(arg) => arg.run().await?, diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs new file mode 100644 index 0000000000000..2871d144a984a --- /dev/null +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -0,0 +1,553 @@ +// 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 . + +use crate::{ + chains::{ + kusama_headers_to_polkadot::KusamaFinalityToPolkadot, + polkadot_headers_to_kusama::PolkadotFinalityToKusama, + }, + cli::{ + swap_tokens::wait_until_transaction_is_finalized, SourceConnectionParams, + TargetConnectionParams, TargetSigningParams, + }, +}; +use bp_header_chain::justification::GrandpaJustification; +use bp_runtime::Chain; +use codec::Encode; +use finality_relay::{SourceClient, SourceHeader}; +use frame_support::weights::Weight; +use num_traits::One; +use pallet_bridge_grandpa::weights::WeightInfo; +use relay_substrate_client::{ + AccountIdOf, BlockNumberOf, Chain as _, Client, Error as SubstrateError, HeaderOf, SignParam, + SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; +use sp_core::{Bytes, Pair}; +use std::convert::{TryFrom, TryInto}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::{ + finality_pipeline::SubstrateFinalitySyncPipeline, finality_source::SubstrateFinalitySource, + finality_target::SubstrateFinalityTarget, messages_source::read_client_state, + TransactionParams, +}; + +/// Reinitialize bridge pallet. +#[derive(Debug, PartialEq, StructOpt)] +pub struct ReinitBridge { + /// A bridge instance to reinitialize. + #[structopt(possible_values = ReinitBridgeName::VARIANTS, case_insensitive = true)] + bridge: ReinitBridgeName, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, +} + +#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] +#[strum(serialize_all = "kebab_case")] +/// Bridge to initialize. +pub enum ReinitBridgeName { + KusamaToPolkadot, + PolkadotToKusama, +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + ReinitBridgeName::KusamaToPolkadot => { + use relay_polkadot_client::runtime; + + type Finality = KusamaFinalityToPolkadot; + type Call = runtime::Call; + + fn submit_finality_proof_call( + header_and_proof: HeaderAndProof, + ) -> runtime::Call { + runtime::Call::BridgeKusamaGrandpa( + runtime::BridgeKusamaGrandpaCall::submit_finality_proof( + Box::new(header_and_proof.0.into_inner()), + header_and_proof.1, + ), + ) + } + + fn set_pallet_operation_mode_call(operational: bool) -> runtime::Call { + runtime::Call::BridgeKusamaGrandpa( + runtime::BridgeKusamaGrandpaCall::set_operational(operational), + ) + } + + fn batch_all_call(calls: Vec) -> runtime::Call { + runtime::Call::Utility(runtime::UtilityCall::batch_all(calls)) + } + + $generic + }, + ReinitBridgeName::PolkadotToKusama => { + use relay_kusama_client::runtime; + + type Finality = PolkadotFinalityToKusama; + type Call = runtime::Call; + + fn submit_finality_proof_call( + header_and_proof: HeaderAndProof, + ) -> runtime::Call { + runtime::Call::BridgePolkadotGrandpa( + runtime::BridgePolkadotGrandpaCall::submit_finality_proof( + Box::new(header_and_proof.0.into_inner()), + header_and_proof.1, + ), + ) + } + + fn set_pallet_operation_mode_call(operational: bool) -> runtime::Call { + runtime::Call::BridgePolkadotGrandpa( + runtime::BridgePolkadotGrandpaCall::set_operational(operational), + ) + } + + fn batch_all_call(calls: Vec) -> runtime::Call { + runtime::Call::Utility(runtime::UtilityCall::batch_all(calls)) + } + + $generic + }, + } + }; +} + +impl ReinitBridge { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + type Source = ::SourceChain; + type Target = ::TargetChain; + + let source_client = self.source.to_client::().await?; + let target_client = self.target.to_client::().await?; + let target_sign = self.target_sign.to_keypair::()?; + let transaction_params = TransactionParams { + signer: target_sign, + mortality: self.target_sign.target_transactions_mortality, + }; + + let finality_source = + SubstrateFinalitySource::::new(source_client.clone(), None); + let finality_target = SubstrateFinalityTarget::::new( + target_client.clone(), + transaction_params.clone(), + ); + + // this subcommand assumes that the pallet at the target chain is halted + ensure_pallet_operating_mode(&finality_target, false).await?; + + // we can't call `finality_target.best_finalized_source_block_id()`, because pallet is + // halted and the call will fail => just use what it uses internally + let current_number = + best_source_block_number_at_target::(&target_client).await?; + let target_number = finality_source.best_finalized_block_number().await?; + log::info!( + target: "bridge", + "Best finalized {} header: at {}: {}, at {}: {}", + Source::NAME, + Source::NAME, + target_number, + Target::NAME, + current_number, + ); + + // prepare list of mandatory headers from the range `(current_number; target_number]` + let headers_to_submit = find_mandatory_headers_in_range( + &finality_source, + (current_number + 1, target_number), + ) + .await?; + let latest_andatory_header_number = headers_to_submit.last().map(|(h, _)| h.number()); + log::info!( + target: "bridge", + "Missing {} mandatory {} headers at {}", + headers_to_submit.len(), + Source::NAME, + Target::NAME, + ); + + // split all mandatory headers into batches + let headers_batches = + make_mandatory_headers_batches::(headers_to_submit, |(_, proof)| { + // we don't have an access to the Kusama/Polkadot chain runtimes here, so we'll + // be using Millau weights. It isn't super-critical, unless real weights are + // magnitude higher or so + pallet_bridge_grandpa::weights::MillauWeight::::submit_finality_proof( + proof.commit.precommits.len().try_into().unwrap_or(u32::MAX), + proof.votes_ancestries.len().try_into().unwrap_or(u32::MAX), + ) + }); + log::info!( + target: "bridge", + "We're going to submit {} transactions to {} node", + headers_batches.len(), + Target::NAME, + ); + + // each batch is submitted as a separate transaction + let signer_account_id: AccountIdOf = transaction_params.signer.public().into(); + let genesis_hash = *target_client.genesis_hash(); + let (spec_version, transaction_version) = + target_client.simple_runtime_version().await?; + let last_batch_index = headers_batches.len() - 1; + for (i, headers_batch) in headers_batches.into_iter().enumerate() { + let is_last_batch = i == last_batch_index; + let expected_number = + headers_batch.last().expect("all batches are non-empty").0.number(); + let transaction_params = transaction_params.clone(); + log::info!( + target: "bridge", + "Going to submit transaction that updates best {} header at {} to {}", + Source::NAME, + Target::NAME, + expected_number, + ); + + // prepare `batch_all` call + let mut batch_calls = Vec::with_capacity(headers_batch.len() + 2); + // the first call is always resumes pallet operation + batch_calls.push(set_pallet_operation_mode_call(true)); + // followed by submit-finality-proofs calls + for header_and_proof in headers_batch { + batch_calls.push(submit_finality_proof_call(header_and_proof)); + } + // if it isn't the last batch, we shall halt pallet again + if !is_last_batch { + batch_calls.push(set_pallet_operation_mode_call(false)); + } + let submit_batch_call = batch_all_call(batch_calls); + + let batch_transaction_events = target_client + .submit_and_watch_signed_extrinsic( + signer_account_id.clone(), + move |best_block_id, transaction_nonce| { + Ok(Bytes( + Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer.clone(), + era: TransactionEra::new( + best_block_id, + transaction_params.mortality, + ), + unsigned: UnsignedTransaction::new( + submit_batch_call.into(), + transaction_nonce, + ), + })? + .encode(), + )) + }, + ) + .await?; + wait_until_transaction_is_finalized::(batch_transaction_events).await?; + + // verify that the best finalized header at target has been updated + let current_number = + best_source_block_number_at_target::(&target_client).await?; + if current_number != expected_number { + return Err(anyhow::format_err!( + "Transaction has failed to update best {} header at {} to {}. It is {}", + Source::NAME, + Target::NAME, + expected_number, + current_number, + )) + } + + // verify that the pallet is still halted (or operational if it is the last batch) + ensure_pallet_operating_mode(&finality_target, is_last_batch).await?; + } + + if let Some(latest_andatory_header_number) = latest_andatory_header_number { + log::info!( + target: "bridge", + "Successfully updated best {} header at {} to {}. Pallet is now operational", + Source::NAME, + Target::NAME, + latest_andatory_header_number, + ); + } + + Ok(()) + }) + } +} + +/// Mandatory header and its finality proof. +type HeaderAndProof

= ( + SyncHeader::SourceChain>>, + GrandpaJustification::SourceChain>>, +); +/// Vector of mandatory headers and their finality proofs. +type HeadersAndProofs

= Vec>; + +/// Returns best finalized source header number known to the bridge GRANDPA pallet at the target +/// chain. +/// +/// This function works even if bridge GRANDPA pallet at the target chain is halted. +async fn best_source_block_number_at_target( + target_client: &Client, +) -> anyhow::Result> { + Ok(read_client_state::( + &target_client, + None, + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) + .await? + .best_finalized_peer_at_best_self + .0) +} + +/// Verify that the bridge GRANDPA pallet at the target chain is either halted, or operational. +async fn ensure_pallet_operating_mode( + finality_target: &SubstrateFinalityTarget

, + operational: bool, +) -> anyhow::Result<()> { + match (operational, finality_target.ensure_pallet_active().await) { + (true, Ok(())) => Ok(()), + (false, Err(SubstrateError::BridgePalletIsHalted)) => Ok(()), + _ => + return Err(anyhow::format_err!( + "Bridge GRANDPA pallet at {} is expected to be {}, but it isn't", + P::TargetChain::NAME, + if operational { "operational" } else { "halted" }, + )), + } +} + +/// Returns list of all mandatory headers in given range. +async fn find_mandatory_headers_in_range( + finality_source: &SubstrateFinalitySource

, + range: (BlockNumberOf, BlockNumberOf), +) -> anyhow::Result> { + let mut mandatory_headers = Vec::new(); + let mut current = range.0; + while current <= range.1 { + let (header, proof) = finality_source.header_and_finality_proof(current).await?.into(); + if header.is_mandatory() { + match proof { + Some(proof) => mandatory_headers.push((header, proof)), + None => + return Err(anyhow::format_err!( + "Missing GRANDPA justification for {} header {}", + P::SourceChain::NAME, + current, + )), + } + } + + current += One::one(); + } + + Ok(mandatory_headers) +} + +/// Given list of mandatory headers, prepare batches of headers, so that every batch may fit into +/// single transaction. +fn make_mandatory_headers_batches< + P: SubstrateFinalitySyncPipeline, + F: Fn(&HeaderAndProof

) -> Weight, +>( + mut headers_to_submit: HeadersAndProofs

, + submit_header_weight: F, +) -> Vec> { + // now that we have all mandatory headers, let's prepare transactions + // (let's keep all our transactions below 2/3 of max tx size/weight to have some reserve + // for utility overhead + for halting transaction) + let maximal_tx_size = P::TargetChain::max_extrinsic_size() * 2 / 3; + let maximal_tx_weight = P::TargetChain::max_extrinsic_weight() * 2 / 3; + let mut current_batch_size: u32 = 0; + let mut current_batch_weight: Weight = 0; + let mut batches = Vec::new(); + let mut i = 0; + while i < headers_to_submit.len() { + let header_and_proof_size = + headers_to_submit[i].0.encode().len() + headers_to_submit[i].1.encode().len(); + let header_and_proof_weight = submit_header_weight(&headers_to_submit[i]); + + let new_batch_size = current_batch_size + .saturating_add(u32::try_from(header_and_proof_size).unwrap_or(u32::MAX)); + let new_batch_weight = current_batch_weight.saturating_add(header_and_proof_weight); + + let is_exceeding_tx_size = new_batch_size > maximal_tx_size; + let is_exceeding_tx_weight = new_batch_weight > maximal_tx_weight; + let is_new_batch_required = is_exceeding_tx_size || is_exceeding_tx_weight; + + if is_new_batch_required { + // if `i` is 0 and we're here, it is a weird situation: even single header submission is + // larger than we've planned for a bunch of headers. Let's be optimistic and hope that + // the tx will still succeed. + let spit_off_index = std::cmp::max(i, 1); + let remaining_headers_to_submit = headers_to_submit.split_off(spit_off_index); + batches.push(headers_to_submit); + + // we'll reiterate the same header again => so set `current_*` to zero + current_batch_size = 0; + current_batch_weight = 0; + headers_to_submit = remaining_headers_to_submit; + i = 0; + } else { + current_batch_size = new_batch_size; + current_batch_weight = new_batch_weight; + i = i + 1; + } + } + if !headers_to_submit.is_empty() { + batches.push(headers_to_submit); + } + batches +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; + use bp_test_utils::{make_default_justification, test_header}; + use relay_polkadot_client::Polkadot; + use sp_runtime::{traits::Header as _, DigestItem}; + + fn make_header_and_justification( + i: u32, + size: u32, + ) -> (SyncHeader, GrandpaJustification) { + let size = size as usize; + let mut header: bp_kusama::Header = test_header(i); + let justification = make_default_justification(&header); + let actual_size = header.encode().len() + justification.encode().len(); + // additional digest means some additional bytes, so let's decrease `additional_digest_size` + // a bit + let additional_digest_size = size.saturating_sub(actual_size).saturating_sub(100); + header.digest_mut().push(DigestItem::Other(vec![0u8; additional_digest_size])); + let justification = make_default_justification(&header); + println!("{} {}", size, header.encode().len() + justification.encode().len()); + (header.into(), justification) + } + + #[test] + fn should_parse_cli_options() { + // when + let res = ReinitBridge::from_iter(vec![ + "reinit-bridge", + "kusama-to-polkadot", + "--source-host", + "127.0.0.1", + "--source-port", + "42", + "--target-host", + "127.0.0.1", + "--target-port", + "43", + "--target-signer", + "//Alice", + ]); + + // then + assert_eq!( + res, + ReinitBridge { + bridge: ReinitBridgeName::KusamaToPolkadot, + source: SourceConnectionParams { + source_host: "127.0.0.1".into(), + source_port: 42, + source_secure: false, + source_runtime_version: SourceRuntimeVersionParams { + source_version_mode: RuntimeVersionType::Bundle, + source_spec_version: None, + source_transaction_version: None, + } + }, + target: TargetConnectionParams { + target_host: "127.0.0.1".into(), + target_port: 43, + target_secure: false, + target_runtime_version: TargetRuntimeVersionParams { + target_version_mode: RuntimeVersionType::Bundle, + target_spec_version: None, + target_transaction_version: None, + } + }, + target_sign: TargetSigningParams { + target_signer: Some("//Alice".into()), + target_signer_password: None, + target_signer_file: None, + target_signer_password_file: None, + target_transactions_mortality: None, + }, + } + ); + } + + #[test] + fn make_mandatory_headers_batches_and_empty_headers() { + let batches = make_mandatory_headers_batches::(vec![], |_| 0); + assert!(batches.is_empty()); + } + + #[test] + fn make_mandatory_headers_batches_with_single_batch() { + let headers_to_submit = + vec![make_header_and_justification(10, Polkadot::max_extrinsic_size() / 3)]; + let batches = + make_mandatory_headers_batches::(headers_to_submit, |_| 0); + assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![1],); + } + + #[test] + fn make_mandatory_headers_batches_group_by_size() { + let headers_to_submit = vec![ + make_header_and_justification(10, Polkadot::max_extrinsic_size() / 3), + make_header_and_justification(20, Polkadot::max_extrinsic_size() / 3), + make_header_and_justification(30, Polkadot::max_extrinsic_size() * 2 / 3), + make_header_and_justification(40, Polkadot::max_extrinsic_size()), + ]; + let batches = + make_mandatory_headers_batches::(headers_to_submit, |_| 0); + assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![2, 1, 1],); + } + + #[test] + fn make_mandatory_headers_batches_group_by_weight() { + let headers_to_submit = vec![ + make_header_and_justification(10, 0), + make_header_and_justification(20, 0), + make_header_and_justification(30, 0), + make_header_and_justification(40, 0), + ]; + let batches = make_mandatory_headers_batches::( + headers_to_submit, + |(header, _)| { + if header.number() == 10 || header.number() == 20 { + Polkadot::max_extrinsic_weight() / 3 + } else if header.number() == 30 { + Polkadot::max_extrinsic_weight() * 2 / 3 + } else { + Polkadot::max_extrinsic_weight() + } + }, + ); + assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![2, 1, 1],); + } +} diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs index 6d0ab5462d7c8..59a919e6cb971 100644 --- a/relays/client-kusama/src/runtime.rs +++ b/relays/client-kusama/src/runtime.rs @@ -70,6 +70,9 @@ pub enum Call { /// Balances pallet. #[codec(index = 4)] Balances(BalancesCall), + /// Utility pallet. + #[codec(index = 24)] + Utility(UtilityCall), /// Polkadot bridge pallet. #[codec(index = 110)] BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), @@ -102,6 +105,8 @@ pub enum BridgePolkadotGrandpaCall { ), #[codec(index = 1)] initialize(bp_header_chain::InitializationData<::Header>), + #[codec(index = 3)] + set_operational(bool), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -136,6 +141,13 @@ pub enum BridgePolkadotMessagesCall { ), } +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum UtilityCall { + #[codec(index = 2)] + batch_all(Vec), +} + #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum BridgePolkadotMessagesParameter { #[codec(index = 0)] diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs index 8b125a37843c8..fa45115a6b5c2 100644 --- a/relays/client-polkadot/src/runtime.rs +++ b/relays/client-polkadot/src/runtime.rs @@ -70,6 +70,9 @@ pub enum Call { /// Balances pallet. #[codec(index = 5)] Balances(BalancesCall), + /// Utility pallet. + #[codec(index = 26)] + Utility(UtilityCall), /// Kusama bridge pallet. #[codec(index = 110)] BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), @@ -102,6 +105,8 @@ pub enum BridgeKusamaGrandpaCall { ), #[codec(index = 1)] initialize(bp_header_chain::InitializationData<::Header>), + #[codec(index = 3)] + set_operational(bool), } #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -136,6 +141,13 @@ pub enum BridgeKusamaMessagesCall { ), } +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum UtilityCall { + #[codec(index = 2)] + batch_all(Vec), +} + #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum BridgeKusamaMessagesParameter { #[codec(index = 0)] diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality_pipeline.rs index 84fb8661016b0..3daf8d11440eb 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality_pipeline.rs @@ -65,7 +65,7 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Adapter that allows all `SubstrateFinalitySyncPipeline` to act as `FinalitySyncPipeline`. #[derive(Clone, Debug)] -pub(crate) struct FinalitySyncPipelineAdapter { +pub struct FinalitySyncPipelineAdapter { _phantom: PhantomData

, } diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality_target.rs index b7bc90cb4de79..4c5814171049a 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality_target.rs @@ -52,7 +52,7 @@ impl SubstrateFinalityTarget

{ } /// Ensure that the GRANDPA pallet at target chain is active. - async fn ensure_pallet_active(&self) -> Result<(), Error> { + pub async fn ensure_pallet_active(&self) -> Result<(), Error> { let is_halted = self .client .storage_value(is_halted_key(P::SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME), None) From 427fc546bf9f87adba98f5749a04a8225ea010c8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 1 Mar 2022 17:26:02 +0300 Subject: [PATCH 0656/1210] fix clippy issues (#1332) --- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-wococo/src/lib.rs | 2 +- primitives/polkadot-core/src/lib.rs | 7 +++---- relays/bin-substrate/src/cli/reinit_bridge.rs | 6 +++--- relays/bin-substrate/src/cli/send_message.rs | 3 ++- relays/lib-substrate-relay/src/helpers.rs | 2 +- relays/lib-substrate-relay/src/messages_source.rs | 3 ++- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a47f0277ef545..a216148a660c0 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -37,7 +37,7 @@ pub type Rococo = PolkadotLike; /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. -pub const SESSION_LENGTH: BlockNumber = 1 * time_units::HOURS; +pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; // NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. pub const VERSION: RuntimeVersion = RuntimeVersion { diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index a05a2ad46a933..98d9cbbb6be63 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -35,7 +35,7 @@ pub type Wococo = PolkadotLike; /// /// Note that since this is a target sessions may change before/after this time depending on network /// conditions. -pub const SESSION_LENGTH: BlockNumber = 1 * time_units::MINUTES; +pub const SESSION_LENGTH: BlockNumber = time_units::MINUTES; // We use this to get the account on Wococo (target) which is derived from Rococo's (source) // account. diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 2f7f6289a3eeb..a56adfd2337eb 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -346,11 +346,10 @@ where // we shall not ever see this error in relay, because we are never signing decoded // transactions. Instead we're constructing and signing new transactions. So the error code // is kinda random here - self.additional_signed.ok_or_else(|| { - frame_support::unsigned::TransactionValidityError::Unknown( + self.additional_signed + .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( frame_support::unsigned::UnknownTransaction::Custom(0xFF), - ) - }) + )) } fn pre_dispatch( diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs index 2871d144a984a..89470872cb2ee 100644 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -312,7 +312,7 @@ async fn best_source_block_number_at_target( target_client: &Client, ) -> anyhow::Result> { Ok(read_client_state::( - &target_client, + target_client, None, P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, ) @@ -346,7 +346,7 @@ async fn find_mandatory_headers_in_range( let mut mandatory_headers = Vec::new(); let mut current = range.0; while current <= range.1 { - let (header, proof) = finality_source.header_and_finality_proof(current).await?.into(); + let (header, proof) = finality_source.header_and_finality_proof(current).await?; if header.is_mandatory() { match proof { Some(proof) => mandatory_headers.push((header, proof)), @@ -412,7 +412,7 @@ fn make_mandatory_headers_batches< } else { current_batch_size = new_batch_size; current_batch_weight = new_batch_weight; - i = i + 1; + i += 1; } } if !headers_to_submit.is_empty() { diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 372ce1fa2a07a..42b2886b7cd54 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -18,7 +18,7 @@ use crate::cli::{ bridge::FullBridge, encode_call::{self, CliEncodeCall}, estimate_fee::estimate_message_delivery_and_dispatch_fee, - Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, + Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; @@ -304,6 +304,7 @@ pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: #[cfg(test)] mod tests { use super::*; + use crate::cli::CliChain; use hex_literal::hex; #[async_std::test] diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index f95a8e0aba3ab..6f30a5d468eee 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -23,7 +23,7 @@ pub fn token_price_metric(token_id: &str) -> Result( spec_version: u32, transaction_version: u32, @@ -443,7 +444,7 @@ where peer_client.header_by_number(peer_on_self_best_finalized_id.0).await?; HeaderId(peer_on_self_best_finalized_id.0, actual_peer_on_self_best_finalized.hash()) }, - None => peer_on_self_best_finalized_id.clone(), + None => peer_on_self_best_finalized_id, }; Ok(ClientState { From 88a5d4c7de3ecca9cce9055c18de07b62c03fa45 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 2 Mar 2022 09:35:42 +0300 Subject: [PATCH 0657/1210] Revert "Revert "override conversion rate in estimate-message-fee RPC (#1189)" (#1275)" (#1333) This reverts commit 6ba7a7a74800333d8ad7ec2bf04a8024da57b56b. --- bin/millau/runtime/src/lib.rs | 4 +- bin/millau/runtime/src/rialto_messages.rs | 13 +++--- bin/rialto/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 13 +++--- bin/runtime-common/src/messages.rs | 46 +++++++++++++++++--- primitives/chain-kusama/Cargo.toml | 2 + primitives/chain-kusama/src/lib.rs | 2 + primitives/chain-millau/src/lib.rs | 3 +- primitives/chain-polkadot/Cargo.toml | 2 + primitives/chain-polkadot/src/lib.rs | 2 + primitives/chain-rialto/src/lib.rs | 3 +- primitives/chain-rococo/src/lib.rs | 2 + primitives/chain-wococo/src/lib.rs | 2 + relays/bin-substrate/src/cli/estimate_fee.rs | 8 +++- 14 files changed, 85 insertions(+), 21 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b578cb7217b8c..775d7f75a6a63 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -52,7 +52,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -757,10 +757,12 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToRialtoMessagePayload, + rialto_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithRialtoMessageBridge::RELAYER_FEE_PERCENT, + rialto_to_this_conversion_rate, ).ok() } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 0e86505d846ab..928fe329d2f83 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -91,11 +91,14 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; - fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance { - bp_millau::Balance::try_from( - RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance), - ) - .unwrap_or(bp_millau::Balance::MAX) + fn bridged_balance_to_this_balance( + bridged_balance: bp_rialto::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_millau::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| RialtoToMillauConversionRate::get()); + bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_millau::Balance::MAX) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 2a68912e52010..8922989c34eab 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -53,7 +53,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -882,10 +882,12 @@ impl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, payload: ToMillauMessagePayload, + millau_to_this_conversion_rate: Option, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithMillauMessageBridge::RELAYER_FEE_PERCENT, + millau_to_this_conversion_rate, ).ok() } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 7e398a5a5b969..9c5d9c8012ce4 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -91,11 +91,14 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; - fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance { - bp_rialto::Balance::try_from( - MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance), - ) - .unwrap_or(bp_rialto::Balance::MAX) + fn bridged_balance_to_this_balance( + bridged_balance: bp_millau::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_rialto::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| MillauToRialtoConversionRate::get()); + bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_rialto::Balance::MAX) } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 47fb1c48f4384..3e548361f955d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -70,6 +70,7 @@ pub trait MessageBridge { /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance( bridged_balance: BalanceOf>, + bridged_to_this_conversion_rate_override: Option, ) -> BalanceOf>; } @@ -316,8 +317,11 @@ pub mod source { pallet_bridge_dispatch::verify_message_origin(submitter, payload) .map_err(|_| BAD_ORIGIN)?; - let minimal_fee_in_this_tokens = - estimate_message_dispatch_and_delivery_fee::(payload, B::RELAYER_FEE_PERCENT)?; + let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( + payload, + B::RELAYER_FEE_PERCENT, + None, + )?; // compare with actual fee paid if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { @@ -371,6 +375,7 @@ pub mod source { pub fn estimate_message_dispatch_and_delivery_fee( payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, + bridged_to_this_conversion_rate: Option, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain // @@ -391,8 +396,11 @@ pub mod source { ThisChain::::transaction_payment(confirmation_transaction); // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee) - .checked_add(&confirmation_transaction_fee); + let minimal_fee = B::bridged_balance_to_this_balance( + delivery_transaction_fee, + bridged_to_this_conversion_rate, + ) + .checked_add(&confirmation_transaction_fee); // before returning, add extra fee that is paid to the relayer (relayer interest) minimal_fee @@ -798,8 +806,12 @@ mod tests { fn bridged_balance_to_this_balance( bridged_balance: BridgedChainBalance, + bridged_to_this_conversion_rate_override: Option, ) -> ThisChainBalance { - ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32) + let conversion_rate = bridged_to_this_conversion_rate_override + .map(|r| r.to_float() as u32) + .unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE); + ThisChainBalance(bridged_balance.0 * conversion_rate) } } @@ -817,7 +829,10 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; - fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance { + fn bridged_balance_to_this_balance( + _this_balance: ThisChainBalance, + _bridged_to_this_conversion_rate_override: Option, + ) -> BridgedChainBalance { unreachable!() } } @@ -1095,6 +1110,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ), Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); @@ -1106,6 +1122,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload_with_pay_on_target, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ) .expect( "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", @@ -1572,4 +1589,21 @@ mod tests { 100 + 50 * 10 + 777, ); } + + #[test] + fn conversion_rate_override_works() { + let payload = regular_outbound_message_payload(); + let regular_fee = source::estimate_message_dispatch_and_delivery_fee::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + None, + ); + let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)), + ); + + assert!(regular_fee < overrided_fee); + } } diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 6ff860357c7c4..8d2f0e98a0117 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index f5ed359a60689..498446f5c460e 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -137,6 +138,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + kusama_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index d83b4ea433a71..670d05f46bab2 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -33,7 +33,7 @@ use scale_info::TypeInfo; use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ traits::{Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; @@ -315,6 +315,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + millau_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 917c7f9747839..710ed55e68c11 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 2983e7f2ce6b9..83ed251455f4b 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -137,6 +138,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + polkadot_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 0adb703c13670..71887226aeef6 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -30,7 +30,7 @@ use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -281,6 +281,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + rialto_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a216148a660c0..a18772d645a1d 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState} use frame_support::weights::{ Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; +use sp_runtime::FixedU128; use sp_std::prelude::*; use sp_version::RuntimeVersion; @@ -133,6 +134,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + rococo_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 98d9cbbb6be63..83bcf3d98b4d7 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -21,6 +21,7 @@ #![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use sp_runtime::FixedU128; use sp_std::prelude::*; pub use bp_polkadot_core::*; @@ -90,6 +91,7 @@ sp_api::decl_runtime_apis! { fn estimate_message_delivery_and_dispatch_fee( lane_id: LaneId, payload: OutboundPayload, + wococo_to_this_conversion_rate: Option, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index ff5bffacdf7c0..ffa566902bedb 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -21,6 +21,7 @@ use crate::{ use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; +use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; @@ -72,8 +73,13 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee anyhow::Result { + let conversion_rate_override: Option = None; let encoded_response = client - .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .state_call( + estimate_fee_method.into(), + (lane, payload, conversion_rate_override).encode().into(), + None, + ) .await?; let decoded_response: Option = Decode::decode(&mut &encoded_response.0[..]) .map_err(relay_substrate_client::Error::ResponseParseFailed)?; From 94e956ce9a9ecbc2ba9ae4c6aed8637b29e2478f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 2 Mar 2022 17:36:26 +0300 Subject: [PATCH 0658/1210] Override conversion rate when computing message fee (#1261) * override conversion rate when message is sent * spelling + fmt * add --conversion-rate-override cli option * try to read conversion rate from cmd output * fix output * fmt --- relays/bin-substrate/src/cli/estimate_fee.rs | 107 +++++++++++++++++-- relays/bin-substrate/src/cli/send_message.rs | 18 +++- relays/bin-substrate/src/cli/swap_tokens.rs | 33 ++++-- relays/lib-substrate-relay/src/helpers.rs | 27 ++++- 4 files changed, 167 insertions(+), 18 deletions(-) diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index ffa566902bedb..375c0aafc81b7 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -24,9 +24,10 @@ use relay_substrate_client::Chain; use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; +use substrate_relay_helper::helpers::target_to_source_conversion_rate; /// Estimate Delivery & Dispatch Fee command. -#[derive(StructOpt, Debug, PartialEq, Eq)] +#[derive(StructOpt, Debug, PartialEq)] pub struct EstimateFee { /// A bridge instance to encode call for. #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] @@ -36,15 +37,44 @@ pub struct EstimateFee { /// Hex-encoded id of lane that will be delivering the message. #[structopt(long, default_value = "00000000")] lane: HexLaneId, + /// A way to override conversion rate between bridge tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + conversion_rate_override: Option, /// Payload to send over the bridge. #[structopt(flatten)] payload: crate::cli::encode_message::MessagePayload, } +/// A way to override conversion rate between bridge tokens. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ConversionRateOverride { + /// The actual conversion rate is computed in the same way how rate metric works. + Metric, + /// The actual conversion rate is specified explicitly. + Explicit(f64), +} + +impl std::str::FromStr for ConversionRateOverride { + type Err = String; + + fn from_str(s: &str) -> Result { + if s.to_lowercase() == "metric" { + return Ok(ConversionRateOverride::Metric) + } + + f64::from_str(s) + .map(ConversionRateOverride::Explicit) + .map_err(|e| format!("Failed to parse '{:?}'. Expected 'metric' or explicit value", e)) + } +} + impl EstimateFee { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - let Self { source, bridge, lane, payload } = self; + let Self { source, bridge, lane, conversion_rate_override, payload } = self; select_full_bridge!(bridge, { let source_client = source.to_client::().await?; @@ -52,8 +82,9 @@ impl EstimateFee { let payload = Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; - let fee: BalanceOf = estimate_message_delivery_and_dispatch_fee( + let fee = estimate_message_delivery_and_dispatch_fee::( &source_client, + conversion_rate_override, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload, @@ -67,13 +98,70 @@ impl EstimateFee { } } -pub(crate) async fn estimate_message_delivery_and_dispatch_fee( - client: &relay_substrate_client::Client, +pub(crate) async fn estimate_message_delivery_and_dispatch_fee< + Source: Chain, + Target: Chain, + P: Clone + Encode, +>( + client: &relay_substrate_client::Client, + conversion_rate_override: Option, + estimate_fee_method: &str, + lane: bp_messages::LaneId, + payload: P, +) -> anyhow::Result> { + // actual conversion rate CAN be lesser than the rate stored in the runtime. So we may try to + // pay lesser fee for the message delivery. But in this case, message may be rejected by the + // lane. So we MUST use the larger of two fees - one computed with stored fee and the one + // computed with actual fee. + + let conversion_rate_override = match ( + conversion_rate_override, + Source::TOKEN_ID, + Target::TOKEN_ID, + ) { + (Some(ConversionRateOverride::Explicit(v)), _, _) => { + let conversion_rate_override = FixedU128::from_float(v); + log::info!(target: "bridge", "Conversion rate override: {:?} (explicit)", conversion_rate_override.to_float()); + Some(conversion_rate_override) + }, + (Some(ConversionRateOverride::Metric), Some(source_token_id), Some(target_token_id)) => { + let conversion_rate_override = FixedU128::from_float( + target_to_source_conversion_rate(source_token_id, target_token_id).await?, + ); + log::info!(target: "bridge", "Conversion rate override: {:?} (from metric)", conversion_rate_override.to_float()); + Some(conversion_rate_override) + }, + _ => None, + }; + + Ok(std::cmp::max( + do_estimate_message_delivery_and_dispatch_fee( + client, + estimate_fee_method, + lane, + payload.clone(), + None, + ) + .await?, + do_estimate_message_delivery_and_dispatch_fee( + client, + estimate_fee_method, + lane, + payload.clone(), + conversion_rate_override, + ) + .await?, + )) +} + +/// Estimate message delivery and dispatch fee with given conversion rate override. +async fn do_estimate_message_delivery_and_dispatch_fee( + client: &relay_substrate_client::Client, estimate_fee_method: &str, lane: bp_messages::LaneId, payload: P, -) -> anyhow::Result { - let conversion_rate_override: Option = None; + conversion_rate_override: Option, +) -> anyhow::Result> { let encoded_response = client .state_call( estimate_fee_method.into(), @@ -81,7 +169,7 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee = Decode::decode(&mut &encoded_response.0[..]) + let decoded_response: Option> = Decode::decode(&mut &encoded_response.0[..]) .map_err(relay_substrate_client::Error::ResponseParseFailed)?; let fee = decoded_response.ok_or_else(|| { anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())) @@ -106,6 +194,8 @@ mod tests { "rialto-to-millau", "--source-port", "1234", + "--conversion-rate-override", + "42.5", "call", "--sender", &alice, @@ -122,6 +212,7 @@ mod tests { EstimateFee { bridge: FullBridge::RialtoToMillau, lane: HexLaneId([0, 0, 0, 0]), + conversion_rate_override: Some(ConversionRateOverride::Explicit(42.5)), source: SourceConnectionParams { source_host: "127.0.0.1".into(), source_port: 1234, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 42b2886b7cd54..b1f9ac7a42ac2 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -17,12 +17,12 @@ use crate::cli::{ bridge::FullBridge, encode_call::{self, CliEncodeCall}, - estimate_fee::estimate_message_delivery_and_dispatch_fee, + estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; use bp_message_dispatch::{CallOrigin, MessagePayload}; -use bp_runtime::{BalanceOf, Chain as _}; +use bp_runtime::Chain as _; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; @@ -66,6 +66,12 @@ pub struct SendMessage { /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, + /// A way to override conversion rate between bridge tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + conversion_rate_override: Option, /// Where dispatch fee is paid? #[structopt( long, @@ -169,11 +175,13 @@ impl SendMessage { let source_sign = self.source_sign.to_keypair::()?; let lane = self.lane.clone().into(); + let conversion_rate_override = self.conversion_rate_override; let fee = match self.fee { Some(fee) => fee, None => Balance( - estimate_message_delivery_and_dispatch_fee::, _, _>( + estimate_message_delivery_and_dispatch_fee::( &source_client, + conversion_rate_override, ESTIMATE_MESSAGE_FEE_METHOD, lane, payload.clone(), @@ -317,6 +325,8 @@ mod tests { "1234", "--source-signer", "//Alice", + "--conversion-rate-override", + "0.75", "remark", "--remark-payload", "1234", @@ -354,6 +364,8 @@ mod tests { "Target", "--target-signer", "//Bob", + "--conversion-rate-override", + "metric", "remark", "--remark-payload", "1234", diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index c4b80ec66b9c6..b93b96daa2387 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -36,8 +36,8 @@ use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, U256}; use sp_runtime::traits::{Convert, Header as HeaderT}; use crate::cli::{ - Balance, CliChain, SourceConnectionParams, SourceSigningParams, TargetConnectionParams, - TargetSigningParams, + estimate_fee::ConversionRateOverride, Balance, CliChain, SourceConnectionParams, + SourceSigningParams, TargetConnectionParams, TargetSigningParams, }; /// Swap tokens. @@ -65,6 +65,12 @@ pub struct SwapTokens { /// Target chain balance that target signer wants to swap. #[structopt(long)] target_balance: Balance, + /// A way to override conversion rate between bridge tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + conversion_rate_override: Option, } /// Token swap type. @@ -133,6 +139,7 @@ impl SwapTokens { let source_sign = self.source_sign.to_keypair::()?; let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; + let conversion_rate_override = self.conversion_rate_override; // names of variables in this function are matching names used by the // `pallet-bridge-token-swap` @@ -198,9 +205,14 @@ impl SwapTokens { // prepare `create_swap` call let target_public_at_bridged_chain: AccountPublicOf = target_sign.public().into(); - let swap_delivery_and_dispatch_fee: BalanceOf = - crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( + let swap_delivery_and_dispatch_fee = + crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee::< + Source, + Target, + _, + >( &source_client, + conversion_rate_override.clone(), ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, SOURCE_TO_TARGET_LANE_ID, bp_message_dispatch::MessagePayload { @@ -356,9 +368,14 @@ impl SwapTokens { dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, call: claim_swap_call.encode(), }; - let claim_swap_delivery_and_dispatch_fee: BalanceOf = - crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee( + let claim_swap_delivery_and_dispatch_fee = + crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee::< + Target, + Source, + _, + >( &target_client, + conversion_rate_override.clone(), ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, TARGET_TO_SOURCE_LANE_ID, claim_swap_message.clone(), @@ -753,6 +770,7 @@ mod tests { swap_type: TokenSwapType::NoLock, source_balance: Balance(8000000000), target_balance: Balance(9000000000), + conversion_rate_override: None, } ); } @@ -778,6 +796,8 @@ mod tests { "//Bob", "--target-balance", "9000000000", + "--conversion-rate-override", + "metric", "lock-until-block", "--blocks-before-expire", "1", @@ -827,6 +847,7 @@ mod tests { }, source_balance: Balance(8000000000), target_balance: Balance(9000000000), + conversion_rate_override: Some(ConversionRateOverride::Metric), } ); } diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index 6f30a5d468eee..1a9abce67439b 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -16,7 +16,7 @@ //! Substrate relay helpers -use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError}; +use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, StandaloneMetric}; /// Creates standalone token price metric. pub fn token_price_metric(token_id: &str) -> Result { @@ -27,3 +27,28 @@ pub fn token_price_metric(token_id: &str) -> Result anyhow::Result { + let source_token_metric = token_price_metric(source_token_id)?; + source_token_metric.update().await; + let target_token_metric = token_price_metric(target_token_id)?; + target_token_metric.update().await; + + let source_token_value = *source_token_metric.shared_value_ref().read().await; + let target_token_value = *target_token_metric.shared_value_ref().read().await; + // `FloatJsonValueMetric` guarantees that the value is positive && normal, so no additional + // checks required here + match (source_token_value, target_token_value) { + (Some(source_token_value), Some(target_token_value)) => + Ok(target_token_value / source_token_value), + _ => Err(anyhow::format_err!( + "Failed to compute conversion rate from {} to {}", + target_token_id, + source_token_id, + )), + } +} From 576e8a76d56a246e422b7b78a555be849223e9d3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 3 Mar 2022 08:53:07 +0300 Subject: [PATCH 0659/1210] fix conversion rate override in token swap (#1336) --- relays/bin-substrate/src/cli/swap_tokens.rs | 31 +++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index b93b96daa2387..625e3197f809b 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -65,12 +65,18 @@ pub struct SwapTokens { /// Target chain balance that target signer wants to swap. #[structopt(long)] target_balance: Balance, - /// A way to override conversion rate between bridge tokens. + /// A way to override conversion rate from target to source tokens. /// /// If not specified, conversion rate from runtime storage is used. It may be obsolete and /// your message won't be relayed. #[structopt(long)] - conversion_rate_override: Option, + target_to_source_conversion_rate_override: Option, + /// A way to override conversion rate from source to target tokens. + /// + /// If not specified, conversion rate from runtime storage is used. It may be obsolete and + /// your message won't be relayed. + #[structopt(long)] + source_to_target_conversion_rate_override: Option, } /// Token swap type. @@ -139,7 +145,10 @@ impl SwapTokens { let source_sign = self.source_sign.to_keypair::()?; let target_client = self.target.to_client::().await?; let target_sign = self.target_sign.to_keypair::()?; - let conversion_rate_override = self.conversion_rate_override; + let target_to_source_conversion_rate_override = + self.target_to_source_conversion_rate_override; + let source_to_target_conversion_rate_override = + self.source_to_target_conversion_rate_override; // names of variables in this function are matching names used by the // `pallet-bridge-token-swap` @@ -212,7 +221,7 @@ impl SwapTokens { _, >( &source_client, - conversion_rate_override.clone(), + target_to_source_conversion_rate_override.clone(), ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, SOURCE_TO_TARGET_LANE_ID, bp_message_dispatch::MessagePayload { @@ -375,7 +384,7 @@ impl SwapTokens { _, >( &target_client, - conversion_rate_override.clone(), + source_to_target_conversion_rate_override.clone(), ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, TARGET_TO_SOURCE_LANE_ID, claim_swap_message.clone(), @@ -770,7 +779,8 @@ mod tests { swap_type: TokenSwapType::NoLock, source_balance: Balance(8000000000), target_balance: Balance(9000000000), - conversion_rate_override: None, + target_to_source_conversion_rate_override: None, + source_to_target_conversion_rate_override: None, } ); } @@ -796,8 +806,10 @@ mod tests { "//Bob", "--target-balance", "9000000000", - "--conversion-rate-override", + "--target-to-source-conversion-rate-override", "metric", + "--source-to-target-conversion-rate-override", + "84.56", "lock-until-block", "--blocks-before-expire", "1", @@ -847,7 +859,10 @@ mod tests { }, source_balance: Balance(8000000000), target_balance: Balance(9000000000), - conversion_rate_override: Some(ConversionRateOverride::Metric), + target_to_source_conversion_rate_override: Some(ConversionRateOverride::Metric), + source_to_target_conversion_rate_override: Some(ConversionRateOverride::Explicit( + 84.56 + )), } ); } From 0f5028ae284b8db71c472bb73d9ff887c68079ea Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 3 Mar 2022 14:46:07 +0300 Subject: [PATCH 0660/1210] fixed mess with conversion rates (#1338) --- relays/bin-substrate/src/cli/estimate_fee.rs | 10 ++- .../src/cli/relay_headers_and_messages.rs | 8 +- .../src/conversion_rate_update.rs | 22 +++-- relays/lib-substrate-relay/src/helpers.rs | 80 +++++++++++++++---- .../src/messages_metrics.rs | 28 ++----- 5 files changed, 99 insertions(+), 49 deletions(-) diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 375c0aafc81b7..1f3e560fc0d03 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -24,7 +24,7 @@ use relay_substrate_client::Chain; use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; -use substrate_relay_helper::helpers::target_to_source_conversion_rate; +use substrate_relay_helper::helpers::tokens_conversion_rate_from_metrics; /// Estimate Delivery & Dispatch Fee command. #[derive(StructOpt, Debug, PartialEq)] @@ -98,6 +98,8 @@ impl EstimateFee { } } +/// The caller may provide target to source tokens conversion rate override to use in fee +/// computation. pub(crate) async fn estimate_message_delivery_and_dispatch_fee< Source: Chain, Target: Chain, @@ -121,14 +123,14 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee< ) { (Some(ConversionRateOverride::Explicit(v)), _, _) => { let conversion_rate_override = FixedU128::from_float(v); - log::info!(target: "bridge", "Conversion rate override: {:?} (explicit)", conversion_rate_override.to_float()); + log::info!(target: "bridge", "{} -> {} conversion rate override: {:?} (explicit)", Target::NAME, Source::NAME, conversion_rate_override.to_float()); Some(conversion_rate_override) }, (Some(ConversionRateOverride::Metric), Some(source_token_id), Some(target_token_id)) => { let conversion_rate_override = FixedU128::from_float( - target_to_source_conversion_rate(source_token_id, target_token_id).await?, + tokens_conversion_rate_from_metrics(target_token_id, source_token_id).await?, ); - log::info!(target: "bridge", "Conversion rate override: {:?} (from metric)", conversion_rate_override.to_float()); + log::info!(target: "bridge", "{} -> {} conversion rate override: {:?} (from metric)", Target::NAME, Source::NAME, conversion_rate_override.to_float()); Some(conversion_rate_override) }, _ => None, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 47336000338f8..86b6da39778db 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -403,13 +403,13 @@ impl RelayHeadersAndMessages { .as_ref() .ok_or_else(format_err)? .shared_value_ref(), - left_to_right_metrics - .source_to_base_conversion_rate + right_to_left_metrics + .target_to_base_conversion_rate .as_ref() .ok_or_else(format_err)? .shared_value_ref(), - left_to_right_metrics - .target_to_base_conversion_rate + right_to_left_metrics + .source_to_base_conversion_rate .as_ref() .ok_or_else(format_err)? .shared_value_ref(), diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index 93458457d34c9..482e6e4c86166 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -106,7 +106,7 @@ async fn maybe_select_new_conversion_rate( let left_to_base_conversion_rate = (*left_to_base_conversion_rate.read().await)?; let right_to_base_conversion_rate = (*right_to_base_conversion_rate.read().await)?; let actual_left_to_right_conversion_rate = - right_to_base_conversion_rate / left_to_base_conversion_rate; + left_to_base_conversion_rate / right_to_base_conversion_rate; let rate_difference = (actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs(); @@ -229,15 +229,27 @@ mod tests { #[test] fn transaction_is_submitted_when_difference_is_above_threshold() { + let left_to_right_stored_conversion_rate = 1.0; + let left_to_base_conversion_rate = 18f64; + let right_to_base_conversion_rate = 180f64; + + assert!(left_to_base_conversion_rate < right_to_base_conversion_rate); + assert_eq!( test_maybe_select_new_conversion_rate( TransactionStatus::Idle, - Some(1.0), - Some(1.0), - Some(1.03), + Some(left_to_right_stored_conversion_rate), + Some(left_to_base_conversion_rate), + Some(right_to_base_conversion_rate), 0.02 ), - (Some((1.0, 1.03)), TransactionStatus::Idle), + ( + Some(( + left_to_right_stored_conversion_rate, + left_to_base_conversion_rate / right_to_base_conversion_rate, + )), + TransactionStatus::Idle + ), ); } } diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index 1a9abce67439b..80359b1c2a980 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -29,26 +29,78 @@ pub fn token_price_metric(token_id: &str) -> Result to_tokens`. +pub async fn tokens_conversion_rate_from_metrics( + from_token_id: &str, + to_token_id: &str, ) -> anyhow::Result { - let source_token_metric = token_price_metric(source_token_id)?; - source_token_metric.update().await; - let target_token_metric = token_price_metric(target_token_id)?; - target_token_metric.update().await; + let from_token_metric = token_price_metric(from_token_id)?; + from_token_metric.update().await; + let to_token_metric = token_price_metric(to_token_id)?; + to_token_metric.update().await; - let source_token_value = *source_token_metric.shared_value_ref().read().await; - let target_token_value = *target_token_metric.shared_value_ref().read().await; + let from_token_value = *from_token_metric.shared_value_ref().read().await; + let to_token_value = *to_token_metric.shared_value_ref().read().await; // `FloatJsonValueMetric` guarantees that the value is positive && normal, so no additional // checks required here - match (source_token_value, target_token_value) { - (Some(source_token_value), Some(target_token_value)) => - Ok(target_token_value / source_token_value), + match (from_token_value, to_token_value) { + (Some(from_token_value), Some(to_token_value)) => + Ok(tokens_conversion_rate(from_token_value, to_token_value)), _ => Err(anyhow::format_err!( "Failed to compute conversion rate from {} to {}", - target_token_id, - source_token_id, + from_token_id, + to_token_id, )), } } + +/// Compute conversion rate between two tokens, given token prices. +/// +/// Returned rate may be used in expression: `from_tokens * rate -> to_tokens`. +/// +/// Both prices are assumed to be normal and non-negative. +pub fn tokens_conversion_rate(from_token_value: f64, to_token_value: f64) -> f64 { + from_token_value / to_token_value +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rialto_to_millau_conversion_rate_is_correct() { + let rialto_price = 18.18; + let millau_price = 136.35; + assert!(rialto_price < millau_price); + + let conversion_rate = tokens_conversion_rate(rialto_price, millau_price); + let rialto_amount = 100.0; + let millau_amount = rialto_amount * conversion_rate; + assert!( + rialto_amount > millau_amount, + "{} RLT * {} = {} MLU", + rialto_amount, + conversion_rate, + millau_amount, + ); + } + + #[test] + fn millau_to_rialto_conversion_rate_is_correct() { + let rialto_price = 18.18; + let millau_price = 136.35; + assert!(rialto_price < millau_price); + + let conversion_rate = tokens_conversion_rate(millau_price, rialto_price); + let millau_amount = 100.0; + let rialto_amount = millau_amount * conversion_rate; + assert!( + rialto_amount > millau_amount, + "{} MLU * {} = {} RLT", + millau_amount, + conversion_rate, + rialto_amount, + ); + } +} diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 9e303cebc1d7b..b165892fda1dc 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -16,7 +16,7 @@ //! Tools for supporting message lanes between two Substrate-based chains. -use crate::messages_lane::SubstrateMessageLane; +use crate::{helpers::tokens_conversion_rate, messages_lane::SubstrateMessageLane}; use codec::Decode; use frame_system::AccountInfo; @@ -119,19 +119,11 @@ impl StandaloneMessagesMetrics { /// Return conversion rate from target to source tokens. pub async fn target_to_source_conversion_rate(&self) -> Option { - Self::compute_target_to_source_conversion_rate( - *self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - *self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await, - ) - } - - /// Return conversion rate from target to source tokens, given conversion rates from - /// target/source tokens to some base token. - fn compute_target_to_source_conversion_rate( - target_to_base_conversion_rate: Option, - source_to_base_conversion_rate: Option, - ) -> Option { - Some(source_to_base_conversion_rate? / target_to_base_conversion_rate?) + let from_token_value = + (*self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await)?; + let to_token_value = + (*self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await)?; + Some(tokens_conversion_rate(from_token_value, to_token_value)) } } @@ -379,14 +371,6 @@ mod tests { use frame_support::storage::generator::StorageValue; use sp_core::storage::StorageKey; - #[async_std::test] - async fn target_to_source_conversion_rate_works() { - assert_eq!( - StandaloneMessagesMetrics::::compute_target_to_source_conversion_rate(Some(183.15), Some(12.32)), - Some(12.32 / 183.15), - ); - } - #[test] fn token_decimals_used_properly() { let plancks = 425_000_000_000; From 955775435661a55cb1a90baefc0266f566cd1349 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 4 Mar 2022 16:03:19 +0300 Subject: [PATCH 0661/1210] Increase rate from metric when estimating fee (#1340) * ignore errors when dumping logs and container is missing * fixed typo * print correct payload length * increase conversion rate a bit when estimating fee (to avoid message rejects when rate update tx is active) * fmt --- relays/bin-substrate/src/cli/estimate_fee.rs | 113 ++++++++++++------ .../src/cli/relay_headers_and_messages.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 3 +- relays/bin-substrate/src/cli/swap_tokens.rs | 2 +- 4 files changed, 79 insertions(+), 41 deletions(-) diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 1f3e560fc0d03..bab625314e824 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -15,7 +15,10 @@ // along with Parity Bridges Common. If not, see . use crate::{ - cli::{bridge::FullBridge, Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams}, + cli::{ + bridge::FullBridge, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams, + }, select_full_bridge, }; use bp_runtime::BalanceOf; @@ -116,44 +119,78 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee< // lane. So we MUST use the larger of two fees - one computed with stored fee and the one // computed with actual fee. - let conversion_rate_override = match ( + let conversion_rate_override = + match (conversion_rate_override, Source::TOKEN_ID, Target::TOKEN_ID) { + (Some(ConversionRateOverride::Explicit(v)), _, _) => { + let conversion_rate_override = FixedU128::from_float(v); + log::info!( + target: "bridge", + "{} -> {} conversion rate override: {:?} (explicit)", + Target::NAME, + Source::NAME, + conversion_rate_override.to_float(), + ); + Some(conversion_rate_override) + }, + ( + Some(ConversionRateOverride::Metric), + Some(source_token_id), + Some(target_token_id), + ) => { + let conversion_rate_override = + tokens_conversion_rate_from_metrics(target_token_id, source_token_id).await?; + // So we have current actual conversion rate and rate that is stored in the runtime. + // And we may simply choose the maximal of these. But what if right now there's + // rate update transaction on the way, that is updating rate to 10 seconds old + // actual rate, which is bigger than the current rate? Then our message will be + // rejected. + // + // So let's increase the actual rate by the same value that the conversion rate + // updater is using. + let increased_conversion_rate_override = FixedU128::from_float( + conversion_rate_override * (1.0 + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO), + ); + log::info!( + target: "bridge", + "{} -> {} conversion rate override: {} (value from metric - {})", + Target::NAME, + Source::NAME, + increased_conversion_rate_override.to_float(), + conversion_rate_override, + ); + Some(increased_conversion_rate_override) + }, + _ => None, + }; + + let without_override = do_estimate_message_delivery_and_dispatch_fee( + client, + estimate_fee_method, + lane, + payload.clone(), + None, + ) + .await?; + let with_override = do_estimate_message_delivery_and_dispatch_fee( + client, + estimate_fee_method, + lane, + payload.clone(), conversion_rate_override, - Source::TOKEN_ID, - Target::TOKEN_ID, - ) { - (Some(ConversionRateOverride::Explicit(v)), _, _) => { - let conversion_rate_override = FixedU128::from_float(v); - log::info!(target: "bridge", "{} -> {} conversion rate override: {:?} (explicit)", Target::NAME, Source::NAME, conversion_rate_override.to_float()); - Some(conversion_rate_override) - }, - (Some(ConversionRateOverride::Metric), Some(source_token_id), Some(target_token_id)) => { - let conversion_rate_override = FixedU128::from_float( - tokens_conversion_rate_from_metrics(target_token_id, source_token_id).await?, - ); - log::info!(target: "bridge", "{} -> {} conversion rate override: {:?} (from metric)", Target::NAME, Source::NAME, conversion_rate_override.to_float()); - Some(conversion_rate_override) - }, - _ => None, - }; - - Ok(std::cmp::max( - do_estimate_message_delivery_and_dispatch_fee( - client, - estimate_fee_method, - lane, - payload.clone(), - None, - ) - .await?, - do_estimate_message_delivery_and_dispatch_fee( - client, - estimate_fee_method, - lane, - payload.clone(), - conversion_rate_override, - ) - .await?, - )) + ) + .await?; + let maximal_fee = std::cmp::max(without_override, with_override); + + log::info!( + target: "bridge", + "Estimated message fee: {:?} = max of {:?} (without rate override) and {:?} (with override to {:?})", + maximal_fee, + without_override, + with_override, + conversion_rate_override, + ); + + Ok(maximal_fee) } /// Estimate message delivery and dispatch fee with given conversion rate override. diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 86b6da39778db..9f19d82bdd405 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -50,7 +50,7 @@ use crate::{ /// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1), /// then rational relayers may stop relaying messages because they were submitted using /// lesser conversion rate. -const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; +pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; /// Start headers+messages relayer process. #[derive(StructOpt)] diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index b1f9ac7a42ac2..ddb1ff59b5d08 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -190,6 +190,7 @@ impl SendMessage { ), }; let dispatch_weight = payload.weight; + let payload_len = payload.encode().len(); let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage { bridge_instance_index: self.bridge.bridge_instance_index(), lane: self.lane, @@ -230,7 +231,7 @@ impl SendMessage { "Sending message to {}. Lane: {:?}. Size: {}. Dispatch weight: {}. Fee: {}", Target::NAME, lane, - signed_source_call.len(), + payload_len, dispatch_weight, fee, ); diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 625e3197f809b..0758deddfd103 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -363,7 +363,7 @@ impl SwapTokens { // if is_transfer_succeeded { - log::info!(target: "bridge", "Claiming the swap swap"); + log::info!(target: "bridge", "Claiming the swap"); // prepare `claim_swap` message that will be sent over the bridge let claim_swap_call: CallOf = From 45aed4180f0949fa26850422a1314a0fafc82532 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Mar 2022 10:14:01 +0300 Subject: [PATCH 0662/1210] use DecodeLimit when decoding incoming calls (#1344) --- bin/runtime-common/Cargo.toml | 2 ++ bin/runtime-common/src/messages.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 632f45e58175f..a7d1713afa75b 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -29,6 +29,7 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { 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-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, optional = true } @@ -50,6 +51,7 @@ std = [ "pallet-bridge-messages/std", "pallet-transaction-payment/std", "scale-info/std", + "sp-api/std", "sp-core/std", "sp-runtime/std", "sp-state-machine/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3e548361f955d..f0e23adec2ded 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -30,7 +30,7 @@ use bp_runtime::{ messages::{DispatchFeePayment, MessageDispatchResult}, ChainId, Size, StorageProofChecker, }; -use codec::{Decode, Encode}; +use codec::{Decode, DecodeLimit, Encode}; use frame_support::{ traits::{Currency, ExistenceRequirement}, weights::{Weight, WeightToFeePolynomial}, @@ -521,7 +521,11 @@ pub mod target { for Result { fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { - DecodedCall::decode(&mut &encoded_call.encoded_call[..]).map_err(drop) + DecodedCall::decode_with_depth_limit( + sp_api::MAX_EXTRINSIC_DEPTH, + &mut &encoded_call.encoded_call[..], + ) + .map_err(drop) } } From 36417c282116e991d14829be04605d15e73e3fd2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Mar 2022 11:49:39 +0300 Subject: [PATCH 0663/1210] edition = "2021" (#1346) --- bin/millau/node/Cargo.toml | 2 +- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/dispatch/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- modules/token-swap/Cargo.toml | 2 +- primitives/chain-kusama/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 2 +- primitives/chain-polkadot/Cargo.toml | 2 +- primitives/chain-rialto-parachain/Cargo.toml | 2 +- primitives/chain-rialto/Cargo.toml | 2 +- primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 2 +- primitives/chain-wococo/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/message-dispatch/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 2 +- primitives/token-swap/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/client-kusama/Cargo.toml | 2 +- relays/client-millau/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-rialto/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-westend/Cargo.toml | 2 +- relays/client-wococo/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 12a10ad6c22c8..b07cc29a06adc 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -3,7 +3,7 @@ name = "millau-bridge-node" description = "Substrate node compatible with Millau runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index b7bed40a5d17c..b9f64d1f5d335 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "millau-runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 975d551b888c8..81ed68a127b23 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -2,7 +2,7 @@ name = "rialto-parachain-collator" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 20ce70aba8f6b..d3bb30c3c8532 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "rialto-parachain-runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 6c7bce4d4e0f0..34a2ec1d8b846 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -3,7 +3,7 @@ name = "rialto-bridge-node" description = "Substrate node compatible with Rialto runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" build = "build.rs" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index dffa197bf72a8..5cfa11e12a9af 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -2,7 +2,7 @@ name = "rialto-runtime" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index a7d1713afa75b..0841171757b8a 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -2,7 +2,7 @@ name = "bridge-runtime-common" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 7a8a34ab4c0ea..d073f8722e904 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -3,7 +3,7 @@ name = "pallet-bridge-dispatch" description = "A Substrate Runtime module that dispatches a bridge message, treating it simply as encoded Call" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index e36b43585b9b6..779bf18fe2e64 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -2,7 +2,7 @@ name = "pallet-bridge-grandpa" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 47fb4323bc1ab..ee575dbe67bbf 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -3,7 +3,7 @@ name = "pallet-bridge-messages" description = "Module that allows bridged chains to exchange messages using lane concept." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 9e3e15fddf897..694e0a82da9f4 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -3,7 +3,7 @@ name = "pallet-shift-session-manager" description = "A Substrate Runtime module that selects 2/3 of initial validators for every session" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index a6103f688c424..7ccb50200c1f6 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -3,7 +3,7 @@ name = "pallet-bridge-token-swap" description = "An Substrate pallet that allows parties on different chains (bridged using messages pallet) to swap their tokens" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 8d2f0e98a0117..a676b565c33dc 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-kusama" description = "Primitives of Kusama runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index f1e17fe96f5ac..c35c1f07348e4 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-millau" description = "Primitives of Millau runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 710ed55e68c11..738899b658cdf 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-polkadot" description = "Primitives of Polkadot runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index 034188631b8cd..a15c40929579b 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-rialto-parachain" description = "Primitives of Rialto parachain runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index d16ac59484fb5..663f9076657dd 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-rialto" description = "Primitives of Rialto runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 6e1189b05f363..684b294a266fb 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-rococo" description = "Primitives of Rococo runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index cc2e912cea57f..e1d3ade7fe65b 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-westend" description = "Primitives of Westend runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index d99783695ad31..dcae1844784e9 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-wococo" description = "Primitives of Wococo runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index d4a7d30f90f6a..29aa34048e629 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-header-chain" description = "A common interface for describing what a bridge pallet should be able to do." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 9897b3199781d..6a3a2fdbdf7be 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-message-dispatch" description = "Primitives of bridge messages dispatch modules." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 5afa25fb301cd..6c52035cac6b6 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-messages" description = "Primitives of messages module." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index f05edd0d91ba3..b35ac74ad5652 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-polkadot-core" description = "Primitives of Polkadot-like runtime." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 7cc165fb4e9c4..51b817fd40382 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-runtime" description = "Primitives that may be used at (bridges) runtime level." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 3876f0200a9e9..0703b4f0f9265 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -2,7 +2,7 @@ name = "bp-test-utils" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 4048ef5288b4f..66af0be2f76d4 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-token-swap" description = "Primitives of the pallet-bridge-token-swap pallet" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 84158d2cf9233..7083d265da5e7 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-relay" version = "1.0.1" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index a48d82f641b70..91a78719bbc21 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-kusama-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index da3d4e7fe1d6c..3f193ffff033c 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-millau-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index ff77486579411..5c6904d57b356 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-polkadot-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index e4518c6877652..ebc2856064318 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-rialto-parachain-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 483812ca80885..f8ceb3a925641 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-rialto-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 28e97d3bf0cec..8d256dc8814f8 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-rococo-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index b6a702829faea..0f3e35c6f438f 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-substrate-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 9bbb0b6fb13f5..8a0e6434d09ab 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-westend-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index ea46c3c898bbb..201a727fc4755 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-wococo-client" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 645ac10775baf..cc5ae54be339c 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -2,7 +2,7 @@ name = "finality-relay" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 482aa8d947edb..52e800caa77c7 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -2,7 +2,7 @@ name = "substrate-relay-helper" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 3b3551114a6c0..b3357994b1251 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -2,7 +2,7 @@ name = "messages-relay" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 7996ba72f87bb..123c23176786c 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -2,7 +2,7 @@ name = "relay-utils" version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] From 2ccfd27c1d58c72fe9098c2adf09bd6bb734ca50 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Mar 2022 11:57:59 +0300 Subject: [PATCH 0664/1210] Mortal conversion rate updater transactions (#1257) * merge all similar update_conversion_rate functions * stall timeout in conversion rate update loop * fmt * fix --- .../src/chains/kusama_messages_to_polkadot.rs | 50 +--- .../src/chains/millau_messages_to_rialto.rs | 49 +--- .../src/chains/polkadot_messages_to_kusama.rs | 51 +--- .../src/chains/rialto_messages_to_millau.rs | 49 +--- .../src/chains/rococo_messages_to_wococo.rs | 2 + .../src/chains/wococo_messages_to_rococo.rs | 2 + .../src/cli/relay_headers_and_messages.rs | 86 ++----- .../src/conversion_rate_update.rs | 227 ++++++++++++++++-- .../lib-substrate-relay/src/messages_lane.rs | 8 + 9 files changed, 280 insertions(+), 244 deletions(-) diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 3679b26478371..9a71fbe3c6213 100644 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -16,14 +16,11 @@ //! Kusama-to-Polkadot messages sync entrypoint. -use codec::Encode; use frame_support::weights::Weight; -use sp_core::{Bytes, Pair}; use messages_relay::relay_strategy::MixStrategy; use relay_kusama_client::Kusama; use relay_polkadot_client::Polkadot; -use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::SubstrateMessageLane; /// Description of Kusama -> Polkadot messages bridge. @@ -41,6 +38,13 @@ substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_buil relay_kusama_client::runtime::Call::BridgePolkadotMessages, relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof ); +substrate_relay_helper::generate_mocked_update_conversion_rate_call_builder!( + Kusama, + KusamaMessagesToPolkadotUpdateConversionRateCallBuilder, + relay_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter, + relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate +); impl SubstrateMessageLane for KusamaMessagesToPolkadot { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = @@ -68,42 +72,8 @@ impl SubstrateMessageLane for KusamaMessagesToPolkadot { type ReceiveMessagesDeliveryProofCallBuilder = KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder; - type RelayStrategy = MixStrategy; -} + type TargetToSourceChainConversionRateUpdateBuilder = + KusamaMessagesToPolkadotUpdateConversionRateCallBuilder; -/// Update Polkadot -> Kusama conversion rate, stored in Kusama runtime storage. -pub(crate) async fn update_polkadot_to_kusama_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - let (spec_version, transaction_version) = client.simple_runtime_version().await?; - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Ok(Bytes( - Kusama::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter( - relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ) - ) - ).into(), - transaction_nonce, - ), - })? - .encode(), - )) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index a93007c1bb5a1..f20669e6c7a58 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -16,13 +16,9 @@ //! Millau-to-Rialto messages sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::{ DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane, @@ -31,6 +27,13 @@ use substrate_relay_helper::messages_lane::{ /// Description of Millau -> Rialto messages bridge. #[derive(Clone, Debug)] pub struct MillauMessagesToRialto; +substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( + Millau, + MillauMessagesToRialtoUpdateConversionRateCallBuilder, + millau_runtime::Runtime, + millau_runtime::WithRialtoMessagesInstance, + millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate +); impl SubstrateMessageLane for MillauMessagesToRialto { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = @@ -60,40 +63,8 @@ impl SubstrateMessageLane for MillauMessagesToRialto { millau_runtime::WithRialtoMessagesInstance, >; - type RelayStrategy = MixStrategy; -} + type TargetToSourceChainConversionRateUpdateBuilder = + MillauMessagesToRialtoUpdateConversionRateCallBuilder; -/// Update Rialto -> Millau conversion rate, stored in Millau runtime storage. -pub(crate) async fn update_rialto_to_millau_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - let (spec_version, transaction_version) = client.simple_runtime_version().await?; - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Ok(Bytes( - Millau::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - millau_runtime::Call::from(millau_runtime::MessagesCall::update_pallet_parameter { - parameter: millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ), - }).into(), - transaction_nonce, - ), - })? - .encode(), - )) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 9f8ec346db266..9c4a4640eb99d 100644 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -16,14 +16,10 @@ //! Polkadot-to-Kusama messages sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - use frame_support::weights::Weight; use messages_relay::relay_strategy::MixStrategy; use relay_kusama_client::Kusama; use relay_polkadot_client::Polkadot; -use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::SubstrateMessageLane; /// Description of Polkadot -> Kusama messages bridge. @@ -41,6 +37,13 @@ substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_buil relay_polkadot_client::runtime::Call::BridgeKusamaMessages, relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof ); +substrate_relay_helper::generate_mocked_update_conversion_rate_call_builder!( + Polkadot, + PolkadotMessagesToKusamaUpdateConversionRateCallBuilder, + relay_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter, + relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate +); impl SubstrateMessageLane for PolkadotMessagesToKusama { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = @@ -68,42 +71,8 @@ impl SubstrateMessageLane for PolkadotMessagesToKusama { type ReceiveMessagesDeliveryProofCallBuilder = PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder; - type RelayStrategy = MixStrategy; -} + type TargetToSourceChainConversionRateUpdateBuilder = + PolkadotMessagesToKusamaUpdateConversionRateCallBuilder; -/// Update Kusama -> Polkadot conversion rate, stored in Polkadot runtime storage. -pub(crate) async fn update_kusama_to_polkadot_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - let (spec_version, transaction_version) = client.simple_runtime_version().await?; - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Ok(Bytes( - Polkadot::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter( - relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ) - ) - ).into(), - transaction_nonce, - ) - })? - .encode(), - )) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 6de10d2346f93..d34f471464492 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -16,13 +16,9 @@ //! Rialto-to-Millau messages sync entrypoint. -use codec::Encode; -use sp_core::{Bytes, Pair}; - use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use relay_substrate_client::{Client, SignParam, TransactionSignScheme, UnsignedTransaction}; use substrate_relay_helper::messages_lane::{ DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane, @@ -31,6 +27,13 @@ use substrate_relay_helper::messages_lane::{ /// Description of Rialto -> Millau messages bridge. #[derive(Clone, Debug)] pub struct RialtoMessagesToMillau; +substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( + Rialto, + RialtoMessagesToMillauUpdateConversionRateCallBuilder, + rialto_runtime::Runtime, + rialto_runtime::WithMillauMessagesInstance, + rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate +); impl SubstrateMessageLane for RialtoMessagesToMillau { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = @@ -60,40 +63,8 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { rialto_runtime::WithMillauMessagesInstance, >; - type RelayStrategy = MixStrategy; -} + type TargetToSourceChainConversionRateUpdateBuilder = + RialtoMessagesToMillauUpdateConversionRateCallBuilder; -/// Update Millau -> Rialto conversion rate, stored in Rialto runtime storage. -pub(crate) async fn update_millau_to_rialto_conversion_rate( - client: Client, - signer: ::AccountKeyPair, - updated_rate: f64, -) -> anyhow::Result<()> { - let genesis_hash = *client.genesis_hash(); - let signer_id = (*signer.public().as_array_ref()).into(); - let (spec_version, transaction_version) = client.simple_runtime_version().await?; - client - .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Ok(Bytes( - Rialto::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - rialto_runtime::Call::from(rialto_runtime::MessagesCall::update_pallet_parameter { - parameter: rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( - sp_runtime::FixedU128::from_float(updated_rate), - ), - }).into(), - transaction_nonce, - ) - })? - .encode(), - )) - }) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index 48e41d02da4e0..4e67c87fa8c45 100644 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -57,5 +57,7 @@ impl SubstrateMessageLane for RococoMessagesToWococo { type ReceiveMessagesDeliveryProofCallBuilder = RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder; + type TargetToSourceChainConversionRateUpdateBuilder = (); + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 33d7d9adfcc42..2c44803f2c06a 100644 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -58,5 +58,7 @@ impl SubstrateMessageLane for WococoMessagesToRococo { type ReceiveMessagesDeliveryProofCallBuilder = WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder; + type TargetToSourceChainConversionRateUpdateBuilder = (); + type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 9f19d82bdd405..4ff6ee0947cb2 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -134,14 +134,8 @@ macro_rules! select_bridge { type RightAccountIdConverter = bp_rialto::AccountIdConverter; use crate::chains::{ - millau_messages_to_rialto::{ - update_rialto_to_millau_conversion_rate as update_right_to_left_conversion_rate, - MillauMessagesToRialto as LeftToRightMessageLane, - }, - rialto_messages_to_millau::{ - update_millau_to_rialto_conversion_rate as update_left_to_right_conversion_rate, - RialtoMessagesToMillau as RightToLeftMessageLane, - }, + millau_messages_to_rialto::MillauMessagesToRialto as LeftToRightMessageLane, + rialto_messages_to_millau::RialtoMessagesToMillau as RightToLeftMessageLane, }; async fn left_create_account( @@ -181,22 +175,6 @@ macro_rules! select_bridge { wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, }; - async fn update_right_to_left_conversion_rate( - _client: Client, - _signer: ::AccountKeyPair, - _updated_rate: f64, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) - } - - async fn update_left_to_right_conversion_rate( - _client: Client, - _signer: ::AccountKeyPair, - _updated_rate: f64, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Conversion rate is not supported by this bridge")) - } - async fn left_create_account( left_client: Client, left_sign: ::AccountKeyPair, @@ -250,14 +228,8 @@ macro_rules! select_bridge { type RightAccountIdConverter = bp_polkadot::AccountIdConverter; use crate::chains::{ - kusama_messages_to_polkadot::{ - update_polkadot_to_kusama_conversion_rate as update_right_to_left_conversion_rate, - KusamaMessagesToPolkadot as LeftToRightMessageLane, - }, - polkadot_messages_to_kusama::{ - update_kusama_to_polkadot_conversion_rate as update_left_to_right_conversion_rate, - PolkadotMessagesToKusama as RightToLeftMessageLane, - }, + kusama_messages_to_polkadot::KusamaMessagesToPolkadot as LeftToRightMessageLane, + polkadot_messages_to_kusama::PolkadotMessagesToKusama as RightToLeftMessageLane, }; async fn left_create_account( @@ -354,7 +326,15 @@ impl RelayHeadersAndMessages { Left::NAME ) }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + LeftToRightMessageLane, + Left, + >( + left_client.clone(), + TransactionParams { + signer: left_messages_pallet_owner.clone(), + mortality: left_transactions_mortality, + }, left_to_right_metrics .target_to_source_conversion_rate .as_ref() @@ -371,21 +351,6 @@ impl RelayHeadersAndMessages { .ok_or_else(format_err)? .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - move |new_rate| { - log::info!( - target: "bridge", - "Going to update {} -> {} (on {}) conversion rate to {}.", - Right::NAME, - Left::NAME, - Left::NAME, - new_rate, - ); - update_right_to_left_conversion_rate( - left_client.clone(), - left_messages_pallet_owner.clone(), - new_rate, - ) - }, ); } if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { @@ -397,7 +362,15 @@ impl RelayHeadersAndMessages { Right::NAME ) }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop( + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + RightToLeftMessageLane, + Right, + >( + right_client.clone(), + TransactionParams { + signer: right_messages_pallet_owner.clone(), + mortality: right_transactions_mortality, + }, right_to_left_metrics .target_to_source_conversion_rate .as_ref() @@ -414,21 +387,6 @@ impl RelayHeadersAndMessages { .ok_or_else(format_err)? .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - move |new_rate| { - log::info!( - target: "bridge", - "Going to update {} -> {} (on {}) conversion rate to {}.", - Left::NAME, - Right::NAME, - Right::NAME, - new_rate, - ); - update_left_to_right_conversion_rate( - right_client.clone(), - right_messages_pallet_owner.clone(), - new_rate, - ) - }, ); } diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index 482e6e4c86166..469bc5589932b 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -16,39 +16,143 @@ //! Tools for updating conversion rate that is stored in the runtime storage. +use crate::{messages_lane::SubstrateMessageLane, TransactionParams}; + +use codec::Encode; +use relay_substrate_client::{ + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam, + TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; use relay_utils::metrics::F64SharedRef; -use std::{future::Future, time::Duration}; +use sp_core::{Bytes, Pair}; +use std::time::{Duration, Instant}; /// Duration between updater iterations. const SLEEP_DURATION: Duration = Duration::from_secs(60); +/// Duration which will almost never expire. Since changing conversion rate may require manual +/// intervention (e.g. if call is made through `multisig` pallet), we don't want relayer to +/// resubmit transaction often. +const ALMOST_NEVER_DURATION: Duration = Duration::from_secs(60 * 60 * 24 * 30); + /// Update-conversion-rate transaction status. #[derive(Debug, Clone, Copy, PartialEq)] enum TransactionStatus { /// We have not submitted any transaction recently. Idle, /// We have recently submitted transaction that should update conversion rate. - Submitted(f64), + Submitted(Instant, f64), +} + +/// Different ways of building 'update conversion rate' calls. +pub trait UpdateConversionRateCallBuilder { + /// Given conversion rate, build call that updates conversion rate in given chain runtime + /// storage. + fn build_update_conversion_rate_call(conversion_rate: f64) -> anyhow::Result>; +} + +impl UpdateConversionRateCallBuilder for () { + fn build_update_conversion_rate_call(_conversion_rate: f64) -> anyhow::Result> { + Err(anyhow::format_err!("Conversion rate update is not supported at {}", C::NAME)) + } +} + +/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when +/// you have a direct access to the source chain runtime. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_direct_update_conversion_rate_call_builder { + ( + $source_chain:ident, + $mocked_builder:ident, + $runtime:ty, + $instance:ty, + $parameter:path + ) => { + pub struct $mocked_builder; + + impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain> + for $mocked_builder + { + fn build_update_conversion_rate_call( + conversion_rate: f64, + ) -> anyhow::Result> { + Ok(pallet_bridge_messages::Call::update_pallet_parameter::<$runtime, $instance> { + parameter: $parameter(sp_runtime::FixedU128::from_float(conversion_rate)), + }.into()) + } + } + }; +} + +/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when +/// you only have an access to the mocked version of source chain runtime. In this case you +/// should provide "name" of the call variant for the bridge messages calls, the "name" of +/// the variant for the `update_pallet_parameter` call within that first option and the name +/// of the conversion rate parameter itself. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_mocked_update_conversion_rate_call_builder { + ( + $source_chain:ident, + $mocked_builder:ident, + $bridge_messages:path, + $update_pallet_parameter:path, + $parameter:path + ) => { + pub struct $mocked_builder; + + impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain> + for $mocked_builder + { + fn build_update_conversion_rate_call( + conversion_rate: f64, + ) -> anyhow::Result> { + Ok($bridge_messages($update_pallet_parameter($parameter( + sp_runtime::FixedU128::from_float(conversion_rate), + )))) + } + } + }; } /// Run infinite conversion rate updater loop. /// /// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens * /// Rate`. -pub fn run_conversion_rate_update_loop< - SubmitConversionRateFuture: Future> + Send + 'static, ->( +pub fn run_conversion_rate_update_loop( + client: Client, + transaction_params: TransactionParams>, left_to_right_stored_conversion_rate: F64SharedRef, left_to_base_conversion_rate: F64SharedRef, right_to_base_conversion_rate: F64SharedRef, max_difference_ratio: f64, - submit_conversion_rate: impl Fn(f64) -> SubmitConversionRateFuture + Send + 'static, -) { +) where + Lane: SubstrateMessageLane, + Sign: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, +{ + let stall_timeout = transaction_stall_timeout( + transaction_params.mortality, + Lane::SourceChain::AVERAGE_BLOCK_INTERVAL, + ALMOST_NEVER_DURATION, + ); + + log::info!( + target: "bridge", + "Starting {} -> {} conversion rate (on {}) update loop. Stall timeout: {}s", + Lane::TargetChain::NAME, + Lane::SourceChain::NAME, + Lane::SourceChain::NAME, + stall_timeout.as_secs(), + ); + async_std::task::spawn(async move { let mut transaction_status = TransactionStatus::Idle; loop { async_std::task::sleep(SLEEP_DURATION).await; let maybe_new_conversion_rate = maybe_select_new_conversion_rate( + stall_timeout, &mut transaction_status, &left_to_right_stored_conversion_rate, &left_to_base_conversion_rate, @@ -57,13 +161,32 @@ pub fn run_conversion_rate_update_loop< ) .await; if let Some((prev_conversion_rate, new_conversion_rate)) = maybe_new_conversion_rate { - let submit_conversion_rate_future = submit_conversion_rate(new_conversion_rate); - match submit_conversion_rate_future.await { + log::info!( + target: "bridge", + "Going to update {} -> {} (on {}) conversion rate to {}.", + Lane::TargetChain::NAME, + Lane::SourceChain::NAME, + Lane::SourceChain::NAME, + new_conversion_rate, + ); + + let result = update_target_to_source_conversion_rate::( + client.clone(), + transaction_params.clone(), + new_conversion_rate, + ) + .await; + match result { Ok(()) => { - transaction_status = TransactionStatus::Submitted(prev_conversion_rate); + transaction_status = + TransactionStatus::Submitted(Instant::now(), prev_conversion_rate); }, Err(error) => { - log::trace!(target: "bridge", "Failed to submit conversion rate update transaction: {:?}", error); + log::error!( + target: "bridge", + "Failed to submit conversion rate update transaction: {:?}", + error, + ); }, } } @@ -73,6 +196,7 @@ pub fn run_conversion_rate_update_loop< /// Select new conversion rate to submit to the node. async fn maybe_select_new_conversion_rate( + stall_timeout: Duration, transaction_status: &mut TransactionStatus, left_to_right_stored_conversion_rate: &F64SharedRef, left_to_base_conversion_rate: &F64SharedRef, @@ -83,7 +207,18 @@ async fn maybe_select_new_conversion_rate( (*left_to_right_stored_conversion_rate.read().await)?; match *transaction_status { TransactionStatus::Idle => (), - TransactionStatus::Submitted(previous_left_to_right_stored_conversion_rate) => { + TransactionStatus::Submitted(submitted_at, _) + if Instant::now() - submitted_at > stall_timeout => + { + log::error!( + target: "bridge", + "Conversion rate update transaction has been lost and loop stalled. Restarting", + ); + + // we assume that our transaction has been lost + *transaction_status = TransactionStatus::Idle; + }, + TransactionStatus::Submitted(_, previous_left_to_right_stored_conversion_rate) => { // we can't compare float values from different sources directly, so we only care // whether the stored rate has been changed or not. If it has been changed, then we // assume that our proposal has been accepted. @@ -118,11 +253,50 @@ async fn maybe_select_new_conversion_rate( Some((left_to_right_stored_conversion_rate, actual_left_to_right_conversion_rate)) } +/// Update Target -> Source tokens conversion rate, stored in the Source runtime storage. +pub async fn update_target_to_source_conversion_rate( + client: Client, + transaction_params: TransactionParams>, + updated_rate: f64, +) -> anyhow::Result<()> +where + Lane: SubstrateMessageLane, + Sign: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, +{ + let genesis_hash = *client.genesis_hash(); + let signer_id = transaction_params.signer.public().into(); + let (spec_version, transaction_version) = client.simple_runtime_version().await?; + let call = + Lane::TargetToSourceChainConversionRateUpdateBuilder::build_update_conversion_rate_call( + updated_rate, + )?; + client + .submit_signed_extrinsic(signer_id, move |best_block_id, transaction_nonce| { + Ok(Bytes( + Sign::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer, + era: TransactionEra::new(best_block_id, transaction_params.mortality), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce).into(), + })? + .encode(), + )) + }) + .await + .map(drop) + .map_err(|err| anyhow::format_err!("{:?}", err)) +} + #[cfg(test)] mod tests { use super::*; use async_std::sync::{Arc, RwLock}; + const TEST_STALL_TIMEOUT: Duration = Duration::from_secs(60); + fn test_maybe_select_new_conversion_rate( mut transaction_status: TransactionStatus, stored_conversion_rate: Option, @@ -134,6 +308,7 @@ mod tests { let left_to_base_conversion_rate = Arc::new(RwLock::new(left_to_base_conversion_rate)); let right_to_base_conversion_rate = Arc::new(RwLock::new(right_to_base_conversion_rate)); let result = async_std::task::block_on(maybe_select_new_conversion_rate( + TEST_STALL_TIMEOUT, &mut transaction_status, &stored_conversion_rate, &left_to_base_conversion_rate, @@ -145,15 +320,10 @@ mod tests { #[test] fn rate_is_not_updated_when_transaction_is_submitted() { + let status = TransactionStatus::Submitted(Instant::now(), 10.0); assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Submitted(10.0), - Some(10.0), - Some(1.0), - Some(1.0), - 0.0 - ), - (None, TransactionStatus::Submitted(10.0)), + test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), + (None, status), ); } @@ -161,7 +331,7 @@ mod tests { fn transaction_state_is_changed_to_idle_when_stored_rate_shanges() { assert_eq!( test_maybe_select_new_conversion_rate( - TransactionStatus::Submitted(1.0), + TransactionStatus::Submitted(Instant::now(), 1.0), Some(10.0), Some(1.0), Some(1.0), @@ -252,4 +422,19 @@ mod tests { ), ); } + + #[test] + fn transaction_expires() { + let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT / 2, 10.0); + assert_eq!( + test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), + (None, status), + ); + + let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT * 2, 10.0); + assert_eq!( + test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), + (Some((10.0, 1.0)), TransactionStatus::Idle), + ); + } } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 2da434c8c7c68..fadf5e62245ad 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -17,6 +17,7 @@ //! Tools for supporting message lanes between two Substrate-based chains. use crate::{ + conversion_rate_update::UpdateConversionRateCallBuilder, messages_metrics::StandaloneMessagesMetrics, messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, @@ -89,6 +90,13 @@ pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { /// How receive messages delivery proof call is built? type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; + /// `TargetChain` tokens to `SourceChain` tokens conversion rate update builder. + /// + /// If not applicable to this bridge, you may use `()` here. + type TargetToSourceChainConversionRateUpdateBuilder: UpdateConversionRateCallBuilder< + Self::SourceChain, + >; + /// Message relay strategy. type RelayStrategy: RelayStrategy; } From 51f6f6a0e3c3dab3d9607c9aecce6fd4890dddc6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Mar 2022 15:59:59 +0300 Subject: [PATCH 0665/1210] replace From<>InboundLaneApi with direct storage reads (#1348) --- bin/millau/runtime/src/lib.rs | 6 ---- bin/rialto/runtime/src/lib.rs | 6 ---- modules/messages/src/lib.rs | 33 +++++++++---------- primitives/chain-kusama/src/lib.rs | 15 +-------- primitives/chain-millau/src/lib.rs | 15 +-------- primitives/chain-polkadot/src/lib.rs | 15 +-------- primitives/chain-rialto/src/lib.rs | 15 +-------- primitives/chain-rococo/src/lib.rs | 15 +-------- primitives/chain-wococo/src/lib.rs | 15 +-------- relays/client-kusama/src/lib.rs | 2 -- relays/client-millau/src/lib.rs | 2 -- relays/client-polkadot/src/lib.rs | 2 -- relays/client-rialto/src/lib.rs | 2 -- relays/client-rococo/src/lib.rs | 2 -- relays/client-substrate/src/chain.rs | 4 --- relays/client-wococo/src/lib.rs | 2 -- .../src/messages_target.rs | 32 +++++++++--------- 17 files changed, 39 insertions(+), 144 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 775d7f75a6a63..7eb6b0247eb6e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -779,12 +779,6 @@ impl_runtime_apis! { } } - impl bp_rialto::FromRialtoInboundLaneApi for Runtime { - fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { - BridgeRialtoMessages::inbound_unrewarded_relayers_state(lane) - } - } - #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8922989c34eab..05e1a36766273 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -903,12 +903,6 @@ impl_runtime_apis! { >(lane, begin, end) } } - - impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn unrewarded_relayers_state(lane: bp_messages::LaneId) -> bp_messages::UnrewardedRelayersState { - BridgeMillauMessages::inbound_unrewarded_relayers_state(lane) - } - } } /// Millau account ownership digest from Rialto. diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index f37dc88481e8d..f92aa3876f6b6 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -764,21 +764,6 @@ pub mod pallet { ) -> Option> { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } - - /// Get state of unrewarded relayers set. - pub fn inbound_unrewarded_relayers_state( - lane: bp_messages::LaneId, - ) -> bp_messages::UnrewardedRelayersState { - let relayers = InboundLanes::::get(&lane).relayers; - bp_messages::UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), - } - } } } @@ -1127,6 +1112,20 @@ mod tests { System::::reset_events(); } + fn inbound_unrewarded_relayers_state( + lane: bp_messages::LaneId, + ) -> bp_messages::UnrewardedRelayersState { + let relayers = InboundLanes::::get(&lane).relayers; + bp_messages::UnrewardedRelayersState { + unrewarded_relayer_entries: relayers.len() as _, + messages_in_oldest_entry: relayers + .front() + .map(|entry| 1 + entry.messages.end - entry.messages.begin) + .unwrap_or(0), + total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + } + } + fn send_regular_message() -> Weight { get_ready_for_events(); @@ -1571,7 +1570,7 @@ mod tests { }, ); assert_eq!( - Pallet::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + inbound_unrewarded_relayers_state(TEST_LANE_ID), UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, @@ -1606,7 +1605,7 @@ mod tests { }, ); assert_eq!( - Pallet::::inbound_unrewarded_relayers_state(TEST_LANE_ID), + inbound_unrewarded_relayers_state(TEST_LANE_ID), UnrewardedRelayersState { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 498446f5c460e..d1d4c79df1943 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -107,10 +107,6 @@ pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; -/// Name of the `FromKusamaInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_KUSAMA_UNREWARDED_RELAYERS_STATE: &str = - "FromKusamaInboundLaneApi_unrewarded_relayers_state"; - sp_api::decl_runtime_apis! { /// API for querying information about the finalized Kusama headers. /// @@ -151,13 +147,4 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } - - /// Inbound message lane API for messages sent by Kusama chain. - /// - /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the - /// Kusama runtime itself. - pub trait FromKusamaInboundLaneApi { - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 670d05f46bab2..3a2f120f465c2 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -22,7 +22,7 @@ mod millau_hash; -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -284,10 +284,6 @@ pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; -/// Name of the `FromMillauInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_MILLAU_UNREWARDED_RELAYERS_STATE: &str = - "FromMillauInboundLaneApi_unrewarded_relayers_state"; - sp_api::decl_runtime_apis! { /// API for querying information about the finalized Millau headers. /// @@ -328,15 +324,6 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } - - /// Inbound message lane API for messages sent by Millau chain. - /// - /// This API is implemented by runtimes that are receiving messages from Millau chain, not the - /// Millau runtime itself. - pub trait FromMillauInboundLaneApi { - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } #[cfg(test)] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 83ed251455f4b..0627a9952032c 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -107,10 +107,6 @@ pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; -/// Name of the `FromPolkadotInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_POLKADOT_UNREWARDED_RELAYERS_STATE: &str = - "FromPolkadotInboundLaneApi_unrewarded_relayers_state"; - sp_api::decl_runtime_apis! { /// API for querying information about the finalized Polkadot headers. /// @@ -151,13 +147,4 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } - - /// Inbound message lane API for messages sent by Polkadot chain. - /// - /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the - /// Polkadot runtime itself. - pub trait FromPolkadotInboundLaneApi { - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 71887226aeef6..33b30a183d643 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_With_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -250,10 +250,6 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; -/// Name of the `FromRialtoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_RIALTO_UNREWARDED_RELAYERS_STATE: &str = - "FromRialtoInboundLaneApi_unrewarded_relayers_state"; - sp_api::decl_runtime_apis! { /// API for querying information about the finalized Rialto headers. /// @@ -294,15 +290,6 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } - - /// Inbound message lane API for messages sent by Rialto chain. - /// - /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the - /// Rialto runtime itself. - pub trait FromRialtoInboundLaneApi { - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } #[cfg(test)] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a18772d645a1d..f8c080d851164 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use frame_support::weights::{ Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -91,10 +91,6 @@ pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; -/// Name of the `FromRococoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_ROCOCO_UNREWARDED_RELAYERS_STATE: &str = - "FromRococoInboundLaneApi_unrewarded_relayers_state"; - /// Existential deposit on Rococo. pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; @@ -147,13 +143,4 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } - - /// Inbound message lane API for messages sent by Rococo chain. - /// - /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the - /// Rococo runtime itself. - pub trait FromRococoInboundLaneApi { - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 83bcf3d98b4d7..4b387a846cf31 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -20,7 +20,7 @@ // Runtime-generated DecodeLimit::decode_all_with_depth_limit #![allow(clippy::unnecessary_mut_passed)] -use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}; +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use sp_runtime::FixedU128; use sp_std::prelude::*; @@ -60,10 +60,6 @@ pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; -/// Name of the `FromWococoInboundLaneApi::unrewarded_relayers_state` runtime method. -pub const FROM_WOCOCO_UNREWARDED_RELAYERS_STATE: &str = - "FromWococoInboundLaneApi_unrewarded_relayers_state"; - sp_api::decl_runtime_apis! { /// API for querying information about the finalized Wococo headers. /// @@ -104,13 +100,4 @@ sp_api::decl_runtime_apis! { end: MessageNonce, ) -> Vec>; } - - /// Inbound message lane API for messages sent by Wococo chain. - /// - /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the - /// Wococo runtime itself. - pub trait FromWococoInboundLaneApi { - /// State of the unrewarded relayers set at given lane. - fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState; - } } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 532049e7056e8..e228f2dc24de4 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -79,8 +79,6 @@ impl ChainWithMessages for Kusama { bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = - bp_kusama::FROM_KUSAMA_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index cb181bc04ee92..b0c1dc0dc7cd5 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -63,8 +63,6 @@ impl ChainWithMessages for Millau { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = - bp_millau::FROM_MILLAU_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index c4098c819a02f..d4ada45e36cc8 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -80,8 +80,6 @@ impl ChainWithMessages for Polkadot { bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = - bp_polkadot::FROM_POLKADOT_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index e8a892a2ff415..5cd21d55e7547 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -78,8 +78,6 @@ impl ChainWithMessages for Rialto { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rialto::FROM_RIALTO_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index e8b5a1abd41e0..f63041df9eddb 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -82,8 +82,6 @@ impl ChainWithMessages for Rococo { bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = - bp_rococo::FROM_ROCOCO_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 97a2288f478d3..6987fbae1c6b9 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -91,10 +91,6 @@ pub trait ChainWithMessages: Chain { /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - /// Name of the `FromInboundLaneApi::unrewarded_relayers_state` runtime - /// method. The method is provided by the runtime that is bridged with this `ChainWithMessages`. - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str; - /// Additional weight of the dispatch fee payment if dispatch is paid at the target chain /// and this `ChainWithMessages` is the target chain. const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index cb4c04903cb88..485ca1bd62f4f 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -82,8 +82,6 @@ impl ChainWithMessages for Wococo { bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_UNREWARDED_RELAYERS_STATE: &'static str = - bp_wococo::FROM_WOCOCO_UNREWARDED_RELAYERS_STATE; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 0815559f215c3..869a1d280282b 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -28,13 +28,13 @@ use crate::{ use async_trait::async_trait; use bp_messages::{ - storage_keys::inbound_lane_data_key, InboundLaneData, LaneId, MessageNonce, - UnrewardedRelayersState, + storage_keys::inbound_lane_data_key, total_unrewarded_messages, InboundLaneData, LaneId, + MessageNonce, UnrewardedRelayersState, }; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; -use codec::{Decode, Encode}; +use codec::Encode; use frame_support::weights::{Weight, WeightToFeePolynomial}; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, @@ -49,7 +49,7 @@ use relay_substrate_client::{ use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use std::{convert::TryFrom, ops::RangeInclusive}; +use std::{collections::VecDeque, convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. pub type SubstrateMessagesDeliveryProof = @@ -188,17 +188,19 @@ where id: TargetHeaderIdOf>, ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> { - let encoded_response = self - .target_client - .state_call( - P::SourceChain::FROM_CHAIN_UNREWARDED_RELAYERS_STATE.into(), - Bytes(self.lane_id.encode()), - Some(id.1), - ) - .await?; - let unrewarded_relayers_state: UnrewardedRelayersState = - Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + let relayers = self + .inbound_lane_data(id) + .await? + .map(|data| data.relayers) + .unwrap_or_else(|| VecDeque::new()); + let unrewarded_relayers_state = bp_messages::UnrewardedRelayersState { + unrewarded_relayer_entries: relayers.len() as _, + messages_in_oldest_entry: relayers + .front() + .map(|entry| 1 + entry.messages.end - entry.messages.begin) + .unwrap_or(0), + total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + }; Ok((id, unrewarded_relayers_state)) } From 83b2cbf0e983e4fccd294256a344edc124fb88d3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 9 Mar 2022 16:35:46 +0300 Subject: [PATCH 0666/1210] added no_stack_overflow_when_decoding_nested_call_during_dispatch test (#1349) --- bin/rialto/runtime/src/millau_messages.rs | 65 +++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 9c5d9c8012ce4..483fa1d56e817 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -476,4 +476,69 @@ mod tests { .0, ); } + + #[test] + #[ignore] + fn no_stack_overflow_when_decoding_nested_call_during_dispatch() { + // this test is normally ignored, because it only makes sense to run it in release mode + + let mut ext: sp_io::TestExternalities = + SystemConfig::default().build_storage::().unwrap().into(); + ext.execute_with(|| { + let bridge = MILLAU_CHAIN_ID; + + let mut call: Call = SystemCall::set_heap_pages { pages: 64 }.into(); + + for _i in 0..3000 { + call = Call::Sudo(pallet_sudo::Call::sudo { call: Box::new(call) }); + } + + let dispatch_weight = 500; + let dispatch_fee = ::WeightToFee::calc( + &dispatch_weight, + ); + assert!(dispatch_fee > 0); + + // create relayer account with minimal balance + let relayer_account: AccountId = [1u8; 32].into(); + let initial_amount = ExistentialDeposit::get(); + let _ = as Currency>::deposit_creating( + &relayer_account, + initial_amount, + ); + + // create dispatch account with minimal balance + dispatch fee + let dispatch_account = derive_account_id::< + ::SourceChainAccountId, + >(bridge, SourceAccount::Root); + let dispatch_account = + ::AccountIdConverter::convert( + dispatch_account, + ); + let _ = as Currency>::deposit_creating( + &dispatch_account, + initial_amount + dispatch_fee, + ); + + // dispatch message with intention to pay dispatch fee at the target chain + // + // this is where the stack overflow has happened before the fix has been applied + FromMillauMessageDispatch::dispatch( + &relayer_account, + DispatchMessage { + key: MessageKey { lane_id: Default::default(), nonce: 0 }, + data: DispatchMessageData { + payload: Ok(FromBridgedChainMessagePayload:: { + spec_version: VERSION.spec_version, + weight: dispatch_weight, + origin: CallOrigin::SourceRoot, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: FromBridgedChainEncodedMessageCall::new(call.encode()), + }), + fee: 1, + }, + }, + ); + }); + } } From d6b5c8c18abf8b05a6b304ae7d6e16b32ea04918 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Mar 2022 16:36:58 +0300 Subject: [PATCH 0667/1210] Support dedicated lanes for pallets (#962) * pass call origin to the message verifier * is_outbound_lane_enabled -> is_message_accepted * trait SenderOrigin * only accept messages from token swap pallet to token swap lane * tests for edge cases of pay_delivery_and_dispatch_fee * fixed origin verification * fmt * fix benchmarks compilation * fix TODO with None account and non-zero message fee (already covered by tests) * revert cargo fmt changes temporarily --- bin/millau/runtime/src/lib.rs | 5 +- bin/millau/runtime/src/rialto_messages.rs | 40 +++++++-- bin/rialto/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/millau_messages.rs | 20 ++++- bin/runtime-common/Cargo.toml | 5 +- bin/runtime-common/README.md | 7 +- bin/runtime-common/src/messages.rs | 92 ++++++++++++++----- modules/messages/src/instant_payments.rs | 92 +++++++++++++++---- modules/messages/src/lib.rs | 30 +++---- modules/messages/src/mock.rs | 29 ++++-- modules/token-swap/src/benchmarking.rs | 3 +- modules/token-swap/src/lib.rs | 104 ++++++++++++++++------ modules/token-swap/src/mock.rs | 13 ++- primitives/messages/Cargo.toml | 1 + primitives/messages/src/source_chain.rs | 46 ++++++---- 15 files changed, 361 insertions(+), 129 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7eb6b0247eb6e..5f8e503233557 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -456,10 +456,9 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - (), + WithRialtoMessagesInstance, pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = @@ -525,7 +524,7 @@ construct_runtime!( BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event}, + BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event, Origin}, // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 928fe329d2f83..d925d805dd04b 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -19,7 +19,7 @@ use crate::Runtime; use bp_messages::{ - source_chain::TargetHeaderChain, + source_chain::{SenderOrigin, TargetHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -116,12 +116,23 @@ impl messages::ChainWithMessages for Millau { } impl messages::ThisChainWithMessages for Millau { + type Origin = crate::Origin; type Call = crate::Call; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || - *lane == [0, 0, 0, 1] || - *lane == crate::TokenSwapMessagesLane::get() + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + // lanes 0x00000000 && 0x00000001 are accepting any paid messages, while + // `TokenSwapMessageLane` only accepts messages from token swap pallet + let token_swap_dedicated_lane = crate::TokenSwapMessagesLane::get(); + match *lane { + [0, 0, 0, 0] | [0, 0, 0, 1] => send_origin.linked_account().is_some(), + _ if *lane == token_swap_dedicated_lane => matches!( + send_origin.caller, + crate::OriginCaller::BridgeRialtoTokenSwap( + pallet_bridge_token_swap::RawOrigin::TokenSwap { .. } + ) + ), + _ => false, + } } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -277,6 +288,25 @@ impl SourceHeaderChain for Rialto { } } +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + crate::OriginCaller::system(frame_system::RawOrigin::Root) | + crate::OriginCaller::system(frame_system::RawOrigin::None) => + crate::RootAccountForPayments::get(), + crate::OriginCaller::BridgeRialtoTokenSwap( + pallet_bridge_token_swap::RawOrigin::TokenSwap { + ref swap_account_at_this_chain, + .. + }, + ) => Some(swap_account_at_this_chain.clone()), + _ => None, + } + } +} + /// Millau -> Rialto message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum MillauToRialtoMessagesParameter { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 05e1a36766273..8dd4c2cc27876 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -457,10 +457,9 @@ impl pallet_bridge_messages::Config for Runtime { type MessageDeliveryAndDispatchPayment = pallet_bridge_messages::instant_payments::InstantCurrencyPayments< Runtime, - (), + WithMillauMessagesInstance, pallet_balances::Pallet, GetDeliveryConfirmationTransactionFee, - RootAccountForPayments, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 483fa1d56e817..44348383f1d52 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -19,7 +19,7 @@ use crate::Runtime; use bp_messages::{ - source_chain::TargetHeaderChain, + source_chain::{SenderOrigin, TargetHeaderChain}, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -116,10 +116,11 @@ impl messages::ChainWithMessages for Rialto { } impl messages::ThisChainWithMessages for Rialto { + type Origin = crate::Origin; type Call = crate::Call; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -275,6 +276,19 @@ impl SourceHeaderChain for Millau { } } +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + crate::OriginCaller::system(frame_system::RawOrigin::Root) | + crate::OriginCaller::system(frame_system::RawOrigin::None) => + crate::RootAccountForPayments::get(), + _ => None, + } + } +} + /// Rialto -> Millau message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum RialtoToMillauMessagesParameter { diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 0841171757b8a..54055e10c5fb5 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -26,7 +26,7 @@ pallet-bridge-messages = { path = "../../modules/messages", default-features = f # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -45,6 +45,7 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", + "frame-system/std", "hash-db/std", "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", @@ -60,7 +61,6 @@ std = [ ] runtime-benchmarks = [ "ed25519-dalek/u64_backend", - "frame-system", "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", @@ -68,6 +68,5 @@ runtime-benchmarks = [ "sp-version", ] integrity-test = [ - "frame-system", "static_assertions", ] diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md index 38a47bfdcc9d9..5f2298cd787d3 100644 --- a/bin/runtime-common/README.md +++ b/bin/runtime-common/README.md @@ -62,8 +62,11 @@ corresponding chain. There is single exception, though (it may be changed in the This trait represents this chain from bridge point of view. Let's review every method of this trait: -- `ThisChainWithMessages::is_outbound_lane_enabled`: is used to check whether given lane accepts - outbound messages. +- `ThisChainWithMessages::is_message_accepted`: is used to check whether given lane accepts + messages. The send-message origin is passed to the function, so you may e.g. verify that only + given pallet is able to send messages over selected lane. **IMPORTANT**: if you assume that the + message must be paid by the sender, you must ensure that the sender origin has linked the account + for paying message delivery and dispatch fee. - `ThisChainWithMessages::maximal_pending_messages_at_outbound_lane`: you should return maximal number of pending (undelivered) messages from this function. Returning small values would require diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index f0e23adec2ded..250b68ceffe2f 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -22,7 +22,7 @@ use bp_message_dispatch::MessageDispatch as _; use bp_messages::{ - source_chain::{LaneMessageVerifier, Sender}, + source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; @@ -111,11 +111,13 @@ pub struct MessageTransaction { /// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { + /// Call origin on the chain. + type Origin; /// Call type on the chain. type Call: Encode + Decode; - /// Are we accepting any messages to the given lane? - fn is_outbound_lane_enabled(lane: &LaneId) -> bool; + /// Do we accept message sent by given origin to given lane? + fn is_message_accepted(origin: &Self::Origin, lane: &LaneId) -> bool; /// Maximal number of pending (not yet delivered) messages at This chain. /// @@ -173,6 +175,8 @@ pub type SignatureOf = ::Signature; pub type WeightOf = ::Weight; /// Type of balances that is used on the chain. pub type BalanceOf = ::Balance; +/// Type of origin that is used on the chain. +pub type OriginOf = ::Origin; /// Type of call that is used on this chain. pub type CallOf = ::Call; @@ -270,7 +274,8 @@ pub mod source { pub struct FromThisChainMessageVerifier(PhantomData); /// The error message returned from LaneMessageVerifier when outbound lane is disabled. - pub const OUTBOUND_LANE_DISABLED: &str = "The outbound message lane is disabled."; + pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = + "The outbound message lane has rejected the message."; /// The error message returned from LaneMessageVerifier when too many pending messages at the /// lane. pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; @@ -281,26 +286,30 @@ pub mod source { impl LaneMessageVerifier< + OriginOf>, AccountIdOf>, FromThisChainMessagePayload, BalanceOf>, > for FromThisChainMessageVerifier where B: MessageBridge, + // matches requirements from the `frame_system::Config::Origin` + OriginOf>: Clone + + Into>>, OriginOf>>>, AccountIdOf>: PartialEq + Clone, { type Error = &'static str; fn verify_message( - submitter: &Sender>>, + submitter: &OriginOf>, delivery_and_dispatch_fee: &BalanceOf>, lane: &LaneId, lane_outbound_data: &OutboundLaneData, payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { // reject message if lane is blocked - if !ThisChain::::is_outbound_lane_enabled(lane) { - return Err(OUTBOUND_LANE_DISABLED) + if !ThisChain::::is_message_accepted(submitter, lane) { + return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE) } // reject message if there are too many pending messages at this lane @@ -314,8 +323,23 @@ pub mod source { // Do the dispatch-specific check. We assume that the target chain uses // `Dispatch`, so we verify the message accordingly. - pallet_bridge_dispatch::verify_message_origin(submitter, payload) - .map_err(|_| BAD_ORIGIN)?; + let raw_origin_or_err: Result< + frame_system::RawOrigin>>, + OriginOf>, + > = submitter.clone().into(); + match raw_origin_or_err { + Ok(raw_origin) => + pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload) + .map(drop) + .map_err(|_| BAD_ORIGIN)?, + Err(_) => { + // so what it means that we've failed to convert origin to the + // `frame_system::RawOrigin`? now it means that the custom pallet origin has + // been used to send the message. Do we need to verify it? The answer is no, + // because pallet may craft any origin (e.g. root) && we can't verify whether it + // is valid, or not. + }, + }; let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( payload, @@ -854,6 +878,18 @@ mod tests { #[codec(index = 84)] Mint, } + #[derive(Clone, Debug)] + struct ThisChainOrigin(Result, ()>); + + impl From + for Result, ThisChainOrigin> + { + fn from( + origin: ThisChainOrigin, + ) -> Result, ThisChainOrigin> { + origin.clone().0.map_err(|_| origin) + } + } #[derive(Debug, PartialEq, Decode, Encode)] struct BridgedChainAccountId(u32); @@ -863,6 +899,18 @@ mod tests { struct BridgedChainSignature(u32); #[derive(Debug, PartialEq, Decode, Encode)] enum BridgedChainCall {} + #[derive(Clone, Debug)] + struct BridgedChainOrigin; + + impl From + for Result, BridgedChainOrigin> + { + fn from( + _origin: BridgedChainOrigin, + ) -> Result, BridgedChainOrigin> { + unreachable!() + } + } macro_rules! impl_wrapped_balance { ($name:ident) => { @@ -940,9 +988,10 @@ mod tests { } impl ThisChainWithMessages for ThisChain { + type Origin = ThisChainOrigin; type Call = ThisChainCall; - fn is_outbound_lane_enabled(lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { lane == TEST_LANE_ID } @@ -1000,9 +1049,10 @@ mod tests { } impl ThisChainWithMessages for BridgedChain { + type Origin = BridgedChainOrigin; type Call = BridgedChainCall; - fn is_outbound_lane_enabled(_lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::Origin, _lane: &LaneId) -> bool { unreachable!() } @@ -1141,7 +1191,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1150,7 +1200,7 @@ mod tests { Err(source::TOO_LOW_FEE) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1173,7 +1223,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(0)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1183,7 +1233,7 @@ mod tests { ); assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::None, + &ThisChainOrigin(Ok(frame_system::RawOrigin::None)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1192,7 +1242,7 @@ mod tests { Err(source::BAD_ORIGIN) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1215,7 +1265,7 @@ mod tests { // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(0)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1224,7 +1274,7 @@ mod tests { Err(source::BAD_ORIGIN) ); assert!(source::FromThisChainMessageVerifier::::verify_message( - &Sender::Signed(ThisChainAccountId(1)), + &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(1)))), &ThisChainBalance(1_000_000), TEST_LANE_ID, &test_lane_outbound_data(), @@ -1237,13 +1287,13 @@ mod tests { fn message_is_rejected_when_sent_using_disabled_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), b"dsbl", &test_lane_outbound_data(), ®ular_outbound_message_payload(), ), - Err(source::OUTBOUND_LANE_DISABLED) + Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE) ); } @@ -1251,7 +1301,7 @@ mod tests { fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &Sender::Root, + &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), &ThisChainBalance(1_000_000), TEST_LANE_ID, &OutboundLaneData { diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs index d67b82ade8d2d..2a620a9522258 100644 --- a/modules/messages/src/instant_payments.rs +++ b/modules/messages/src/instant_payments.rs @@ -22,7 +22,7 @@ use crate::OutboundMessages; use bp_messages::{ - source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, Sender}, + source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, SenderOrigin}, LaneId, MessageKey, MessageNonce, UnrewardedRelayer, }; use codec::Encode; @@ -31,6 +31,10 @@ use num_traits::{SaturatingAdd, Zero}; use sp_runtime::traits::Saturating; use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; +/// Error that occurs when message fee is non-zero, but payer is not defined. +const NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE: &str = + "Non-zero message fee can't be paid by "; + /// Instant message payments made in given currency. /// /// The balance is initially reserved in a special `relayers-fund` account, and transferred @@ -44,42 +48,50 @@ use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; /// to the relayer account. /// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they /// can receive the payment. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee, RootAccount)>, +pub struct InstantCurrencyPayments { + _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee)>, } -impl - MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments +impl + MessageDeliveryAndDispatchPayment + for InstantCurrencyPayments where T: frame_system::Config + crate::Config, I: 'static, + T::Origin: SenderOrigin, Currency: CurrencyT, Currency::Balance: From, GetConfirmationFee: Get, - RootAccount: Get>, { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &T::Origin, fee: &Currency::Balance, relayer_fund_account: &T::AccountId, ) -> Result<(), Self::Error> { + let submitter_account = match submitter.linked_account() { + Some(submitter_account) => submitter_account, + None if !fee.is_zero() => { + // if we'll accept some message that has declared that the `fee` has been paid but + // it isn't actually paid, then it'll lead to problems with delivery confirmation + // payments (see `pay_relayer_rewards` && `confirmation_relayer` in particular) + return Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE) + }, + None => { + // message lane verifier has accepted the message before, so this message + // is unpaid **by design** + // => let's just do nothing + return Ok(()) + }, + }; + if !frame_system::Pallet::::account_exists(relayer_fund_account) { return Err("The relayer fund account must exist for the message lanes pallet to work correctly."); } - let root_account = RootAccount::get(); - let account = match submitter { - Sender::Signed(submitter) => submitter, - Sender::Root | Sender::None => root_account - .as_ref() - .ok_or("Sending messages using Root or None origin is disallowed.")?, - }; - Currency::transfer( - account, + &submitter_account, relayer_fund_account, *fee, // it's fine for the submitter to go below Existential Deposit and die. @@ -226,7 +238,9 @@ fn pay_relayer_reward( #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, AccountId as TestAccountId, Balance as TestBalance, TestRuntime}; + use crate::mock::{ + run_test, AccountId as TestAccountId, Balance as TestBalance, Origin, TestRuntime, + }; use bp_messages::source_chain::RelayerRewards; type Balances = pallet_balances::Pallet; @@ -245,6 +259,48 @@ mod tests { .collect() } + #[test] + fn pay_delivery_and_dispatch_fee_fails_on_non_zero_fee_and_unknown_payer() { + frame_support::parameter_types! { + const GetConfirmationFee: TestBalance = 0; + }; + + run_test(|| { + let result = InstantCurrencyPayments::< + TestRuntime, + (), + Balances, + GetConfirmationFee, + >::pay_delivery_and_dispatch_fee( + &Origin::root(), + &100, + &RELAYERS_FUND_ACCOUNT, + ); + assert_eq!(result, Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE)); + }); + } + + #[test] + fn pay_delivery_and_dispatch_succeeds_on_zero_fee_and_unknown_payer() { + frame_support::parameter_types! { + const GetConfirmationFee: TestBalance = 0; + }; + + run_test(|| { + let result = InstantCurrencyPayments::< + TestRuntime, + (), + Balances, + GetConfirmationFee, + >::pay_delivery_and_dispatch_fee( + &Origin::root(), + &0, + &RELAYERS_FUND_ACCOUNT, + ); + assert!(result.is_ok()); + }); + } + #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index f92aa3876f6b6..a344cedae2411 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -170,12 +170,14 @@ pub mod pallet { type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier< + Self::Origin, Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee, >; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< + Self::Origin, Self::AccountId, Self::OutboundMessageFee, >; @@ -276,16 +278,12 @@ pub mod pallet { payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> DispatchResultWithPostInfo { - crate::send_message::( - origin.into().map_err(|_| BadOrigin)?, - lane_id, - payload, - delivery_and_dispatch_fee, + crate::send_message::(origin, lane_id, payload, delivery_and_dispatch_fee).map( + |sent_message| PostDispatchInfo { + actual_weight: Some(sent_message.weight), + pays_fee: Pays::Yes, + }, ) - .map(|sent_message| PostDispatchInfo { - actual_weight: Some(sent_message.weight), - pays_fee: Pays::Yes, - }) } /// Pay additional fee for the message. @@ -313,17 +311,15 @@ pub mod pallet { ); // withdraw additional fee from submitter - let submitter = origin.into().map_err(|_| BadOrigin)?; T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( - &submitter, + &origin, &additional_fee, &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Submitter {:?} can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", - submitter, + "Submitter can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", additional_fee, lane_id, nonce, @@ -780,6 +776,7 @@ pub fn relayer_fund_account_id bp_messages::source_chain::MessagesBridge< + T::Origin, T::AccountId, T::OutboundMessageFee, T::OutboundPayload, @@ -791,7 +788,7 @@ where type Error = sp_runtime::DispatchErrorWithPostInfo; fn send_message( - sender: bp_messages::source_chain::Sender, + sender: T::Origin, lane: LaneId, message: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -802,7 +799,7 @@ where /// Function that actually sends message. fn send_message, I: 'static>( - submitter: bp_messages::source_chain::Sender, + submitter: T::Origin, lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -856,9 +853,8 @@ fn send_message, I: 'static>( .map_err(|err| { log::trace!( target: "runtime::bridge-messages", - "Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}", + "Message to lane {:?} is rejected because submitter is unable to pay fee {:?}: {:?}", lane_id, - submitter, delivery_and_dispatch_fee, err, ); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index ef5081472279b..2669ddfbef26f 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -23,7 +23,7 @@ use bitvec::prelude::*; use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, Sender, TargetHeaderChain, + OnMessageAccepted, SenderOrigin, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -194,6 +194,16 @@ impl Config for TestRuntime { type BridgedChainId = TestBridgedChainId; } +impl SenderOrigin for Origin { + fn linked_account(&self) -> Option { + match self.caller { + OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + _ => None, + } + } +} + impl Size for TestPayload { fn size_hint(&self) -> u32 { 16 + self.extra.len() as u32 @@ -294,11 +304,13 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier for TestLaneMessageVerifier { +impl LaneMessageVerifier + for TestLaneMessageVerifier +{ type Error = &'static str; fn verify_message( - _submitter: &Sender, + _submitter: &Origin, delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, @@ -324,8 +336,8 @@ impl TestMessageDeliveryAndDispatchPayment { /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - frame_support::storage::unhashed::get(b":message-fee:") == - Some((Sender::Signed(submitter), fee)) + let raw_origin: Result, _> = Origin::signed(submitter).into(); + frame_support::storage::unhashed::get(b":message-fee:") == Some((raw_origin.unwrap(), fee)) } /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is @@ -336,13 +348,13 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment +impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &Origin, fee: &TestMessageFee, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { @@ -350,7 +362,8 @@ impl MessageDeliveryAndDispatchPayment return Err(TEST_ERROR) } - frame_support::storage::unhashed::put(b":message-fee:", &(submitter, fee)); + let raw_origin: Result, _> = submitter.clone().into(); + frame_support::storage::unhashed::put(b":message-fee:", &(raw_origin.unwrap(), fee)); Ok(()) } diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs index c68fb6b64283c..878cb20993a9d 100644 --- a/modules/token-swap/src/benchmarking.rs +++ b/modules/token-swap/src/benchmarking.rs @@ -18,7 +18,7 @@ use crate::{ swap_account_id, target_account_at_this_chain, BridgedAccountIdOf, BridgedAccountPublicOf, - BridgedAccountSignatureOf, BridgedBalanceOf, Call, Pallet, ThisChainBalance, + BridgedAccountSignatureOf, BridgedBalanceOf, Call, Origin, Pallet, ThisChainBalance, TokenSwapCreationOf, TokenSwapOf, }; @@ -43,6 +43,7 @@ pub trait Config: crate::Config { benchmarks_instance_pallet! { where_clause { where + Origin: Into, BridgedAccountPublicOf: Decode + Parameter, BridgedAccountSignatureOf: Decode, } diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index 32fd2db3c7cb0..e46a4bc2dd034 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -70,16 +70,18 @@ use bp_runtime::{messages::DispatchFeePayment, ChainId}; use bp_token_swap::{ RawBridgedTransferCall, TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType, }; -use codec::Encode; +use codec::{Decode, Encode}; use frame_support::{ fail, traits::{Currency, ExistenceRequirement}, weights::PostDispatchInfo, + RuntimeDebug, }; +use scale_info::TypeInfo; use sp_core::H256; use sp_io::hashing::blake2_256; use sp_runtime::traits::{Convert, Saturating}; -use sp_std::boxed::Box; +use sp_std::{boxed::Box, marker::PhantomData}; use weights::WeightInfo; pub use weights_ext::WeightInfoExt; @@ -95,6 +97,24 @@ pub mod weights_ext; pub use pallet::*; +/// Name of the `PendingSwaps` storage map. +pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; + +/// Origin for the token swap pallet. +#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)] +pub enum RawOrigin { + /// The call is originated by the token swap account. + TokenSwap { + /// Id of the account that has started the swap. + source_account_at_this_chain: AccountId, + /// Id of the account that holds the funds during this swap. The message fee is paid from + /// this account funds. + swap_account_at_this_chain: AccountId, + }, + /// Dummy to manage the fact we have instancing. + _Phantom(PhantomData), +} + // comes from #[pallet::event] #[allow(clippy::unused_unit)] #[frame_support::pallet] @@ -123,6 +143,7 @@ pub mod pallet { type OutboundMessageLaneId: Get; /// Messages bridge with Bridged chain. type MessagesBridge: MessagesBridge< + Self::Origin, Self::AccountId, >::Balance, MessagePayloadOf, @@ -189,6 +210,7 @@ pub mod pallet { impl, I: 'static> Pallet where BridgedAccountPublicOf: Parameter, + Origin: Into, { /// Start token swap procedure. /// @@ -310,7 +332,11 @@ pub mod pallet { // `Currency::transfer` call on the bridged chain, but no checks are made - it is // the transaction submitter to ensure it is valid. let send_message_result = T::MessagesBridge::send_message( - bp_messages::source_chain::Sender::from(Some(swap_account.clone())), + RawOrigin::TokenSwap { + source_account_at_this_chain: swap.source_account_at_this_chain.clone(), + swap_account_at_this_chain: swap_account.clone(), + } + .into(), T::OutboundMessageLaneId::get(), bp_message_dispatch::MessagePayload { spec_version: bridged_chain_spec_version, @@ -513,6 +539,10 @@ pub mod pallet { InvalidClaimant, } + /// Origin for the token swap pallet. + #[pallet::origin] + pub type Origin = RawOrigin<::AccountId, I>; + /// Pending token swaps states. #[pallet::storage] pub type PendingSwaps, I: 'static = ()> = @@ -685,7 +715,7 @@ mod tests { fn start_test_swap() { assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(TokenSwapCreation { target_public_at_bridged_chain: bridged_chain_account_public(), @@ -710,7 +740,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT + 1), + mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap(), Box::new(test_swap_creation()), ), @@ -726,7 +756,7 @@ mod tests { swap.source_balance_at_this_chain = ExistentialDeposit::get() - 1; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), swap, Box::new(test_swap_creation()), ), @@ -742,7 +772,7 @@ mod tests { swap.source_balance_at_this_chain = THIS_CHAIN_ACCOUNT_BALANCE + 1; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), swap, Box::new(test_swap_creation()), ), @@ -760,7 +790,7 @@ mod tests { swap_creation.bridged_currency_transfer = transfer; assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(swap_creation), ), @@ -773,14 +803,14 @@ mod tests { fn create_swap_fails_if_swap_is_active() { run_test(|| { assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), ), @@ -795,7 +825,7 @@ mod tests { frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER + 1); assert_noop!( Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), ), @@ -809,7 +839,7 @@ mod tests { run_test(|| { frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER); assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); @@ -823,7 +853,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::create_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap(), Box::new(test_swap_creation()), )); @@ -855,7 +885,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed( + mock::Origin::signed( 1 + target_account_at_this_chain::(&test_swap()) ), test_swap(), @@ -872,7 +902,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsPending @@ -887,7 +919,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsFailed @@ -900,7 +934,9 @@ mod tests { run_test(|| { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsInactive @@ -916,7 +952,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::FailedToTransferFromSwapAccount @@ -934,7 +972,9 @@ mod tests { assert_noop!( Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::( + &test_swap() + )), test_swap(), ), Error::::SwapIsTemporaryLocked @@ -952,7 +992,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::claim_swap( - Origin::signed(target_account_at_this_chain::(&test_swap())), + mock::Origin::signed(target_account_at_this_chain::(&test_swap())), test_swap(), )); @@ -988,7 +1028,7 @@ mod tests { assert_noop!( Pallet::::cancel_swap( - Origin::signed(THIS_CHAIN_ACCOUNT + 1), + mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), test_swap() ), Error::::MismatchedSwapSourceOrigin @@ -1002,7 +1042,10 @@ mod tests { start_test_swap(); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsPending ); }); @@ -1015,7 +1058,10 @@ mod tests { receive_test_swap_confirmation(true); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsConfirmed ); }); @@ -1025,7 +1071,10 @@ mod tests { fn cancel_swap_fails_if_swap_is_inactive() { run_test(|| { assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::SwapIsInactive ); }); @@ -1042,7 +1091,10 @@ mod tests { ); assert_noop!( - Pallet::::cancel_swap(Origin::signed(THIS_CHAIN_ACCOUNT), test_swap()), + Pallet::::cancel_swap( + mock::Origin::signed(THIS_CHAIN_ACCOUNT), + test_swap() + ), Error::::FailedToTransferFromSwapAccount ); }); @@ -1058,7 +1110,7 @@ mod tests { frame_system::Pallet::::reset_events(); assert_ok!(Pallet::::cancel_swap( - Origin::signed(THIS_CHAIN_ACCOUNT), + mock::Origin::signed(THIS_CHAIN_ACCOUNT), test_swap() )); diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs index 78b8a3381d3a8..ece7b16acc910 100644 --- a/modules/token-swap/src/mock.rs +++ b/modules/token-swap/src/mock.rs @@ -56,7 +56,7 @@ frame_support::construct_runtime! { { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Event}, - TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event}, + TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event, Origin}, } } @@ -154,18 +154,23 @@ impl bp_runtime::Chain for BridgedChain { pub struct TestMessagesBridge; -impl MessagesBridge> for TestMessagesBridge { +impl MessagesBridge> + for TestMessagesBridge +{ type Error = (); fn send_message( - sender: frame_system::RawOrigin, + sender: Origin, lane: LaneId, message: MessagePayloadOf, delivery_and_dispatch_fee: Balance, ) -> Result { - assert_ne!(sender, frame_system::RawOrigin::Signed(THIS_CHAIN_ACCOUNT)); assert_eq!(lane, OutboundMessageLaneId::get()); assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE); + match sender.caller { + OriginCaller::TokenSwap(_) => (), + _ => panic!("unexpected origin"), + } match message.call[0] { OK_TRANSFER_CALL => Ok(SendMessageArtifacts { nonce: MESSAGE_NONCE, weight: 0 }), BAD_TRANSFER_CALL => Err(()), diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 6c52035cac6b6..2142ad028173a 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -31,6 +31,7 @@ hex-literal = "0.3" [features] default = ["std"] std = [ + "bitvec/std", "bp-runtime/std", "codec/std", "frame-support/std", diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 1ff05abf131ea..fa7b3bb85ed05 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -28,7 +28,21 @@ use sp_std::{ }; /// The sender of the message on the source chain. -pub type Sender = frame_system::RawOrigin; +pub trait SenderOrigin { + /// Return id of the account that is sending this message. + /// + /// In regular messages configuration, when regular message is sent you'll always get `Some(_)` + /// from this call. This is the account that is paying send costs. However, there are some + /// examples when `None` may be returned from the call: + /// + /// - if the send-message call origin is either `frame_system::RawOrigin::Root` or + /// `frame_system::RawOrigin::None` and your configuration forbids such messages; + /// - if your configuration allows 'unpaid' messages sent by pallets. Then the pallet may just + /// use its own defined origin (not linked to any account) and the message will be accepted. + /// This may be useful for pallets that are sending important system-wide information (like + /// update of runtime version). + fn linked_account(&self) -> Option; +} /// Relayers rewards, grouped by relayer account id. pub type RelayersRewards = BTreeMap>; @@ -82,14 +96,14 @@ pub trait TargetHeaderChain { /// Lane3 until some block, ...), then it may be built using this verifier. /// /// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { +pub trait LaneMessageVerifier { /// Error type. type Error: Debug + Into<&'static str>; /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the /// lane. fn verify_message( - submitter: &Sender, + submitter: &SenderOrigin, delivery_and_dispatch_fee: &Fee, lane: &LaneId, outbound_data: &OutboundLaneData, @@ -110,14 +124,14 @@ pub trait LaneMessageVerifier { /// So to be sure that any non-altruist relayer would agree to deliver message, submitter /// should set `delivery_and_dispatch_fee` to at least (equivalent of): sum of fees from (2) /// to (4) above, plus some interest for the relayer. -pub trait MessageDeliveryAndDispatchPayment { +pub trait MessageDeliveryAndDispatchPayment { /// Error type. type Error: Debug + Into<&'static str>; /// Withhold/write-off delivery_and_dispatch_fee from submitter account to /// some relayers-fund account. fn pay_delivery_and_dispatch_fee( - submitter: &Sender, + submitter: &SenderOrigin, fee: &Balance, relayer_fund_account: &AccountId, ) -> Result<(), Self::Error>; @@ -145,7 +159,7 @@ pub struct SendMessageArtifacts { } /// Messages bridge API to be used from other pallets. -pub trait MessagesBridge { +pub trait MessagesBridge { /// Error type. type Error: Debug; @@ -153,7 +167,7 @@ pub trait MessagesBridge { /// /// Returns unique message nonce or error if send has failed. fn send_message( - sender: Sender, + sender: SenderOrigin, lane: LaneId, message: Payload, delivery_and_dispatch_fee: Balance, @@ -164,13 +178,13 @@ pub trait MessagesBridge { #[derive(RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; -impl MessagesBridge - for NoopMessagesBridge +impl + MessagesBridge for NoopMessagesBridge { type Error = &'static str; fn send_message( - _sender: Sender, + _sender: SenderOrigin, _lane: LaneId, _message: Payload, _delivery_and_dispatch_fee: Balance, @@ -245,13 +259,13 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier - for ForbidOutboundMessages +impl + LaneMessageVerifier for ForbidOutboundMessages { type Error = &'static str; fn verify_message( - _submitter: &Sender, + _submitter: &SenderOrigin, _delivery_and_dispatch_fee: &Fee, _lane: &LaneId, _outbound_data: &OutboundLaneData, @@ -261,13 +275,13 @@ impl LaneMessageVerifier } } -impl MessageDeliveryAndDispatchPayment - for ForbidOutboundMessages +impl + MessageDeliveryAndDispatchPayment for ForbidOutboundMessages { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - _submitter: &Sender, + _submitter: &SenderOrigin, _fee: &Balance, _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { From 4693b3f892c91cc43985ae4eb6d316b9e13daf72 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 15 Mar 2022 16:27:20 +0300 Subject: [PATCH 0668/1210] Update Substrate/Polkadot/Cumulus references (#1353) * cumulus: 4e952282914719fafd2df450993ccc2ce9395415 polkadot: 975e780ae0d988dc033f400ba822d14b326ee5b9 substrate: 89fcb3e4f62d221d4e161a437768e77d6265889e * fix refs * sync changes from https://github.com/paritytech/polkadot/pull/3828 * sync changes from https://github.com/paritytech/polkadot/pull/4387 * sync changes from https://github.com/paritytech/polkadot/pull/3940 * sync with changes from https://github.com/paritytech/polkadot/pull/4493 * sync with changes from https://github.com/paritytech/polkadot/pull/4958 * sync with changes from https://github.com/paritytech/polkadot/pull/3889 * sync with changes from https://github.com/paritytech/polkadot/pull/5033 * sync with changes from https://github.com/paritytech/polkadot/pull/5065 * compilation fixes * fixed prometheus endpoint startup (it now requires to be spawned within tokio context) --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/service.rs | 10 +- bin/millau/runtime/Cargo.toml | 6 +- bin/millau/runtime/src/lib.rs | 4 +- bin/rialto-parachain/node/Cargo.toml | 6 +- bin/rialto-parachain/node/src/cli.rs | 12 +- bin/rialto-parachain/node/src/command.rs | 5 +- bin/rialto-parachain/node/src/service.rs | 36 ++- bin/rialto-parachain/runtime/Cargo.toml | 4 +- bin/rialto-parachain/runtime/src/lib.rs | 9 +- bin/rialto/node/Cargo.toml | 6 +- bin/rialto/node/src/chain_spec.rs | 8 +- bin/rialto/node/src/cli.rs | 6 +- bin/rialto/node/src/command.rs | 2 + bin/rialto/runtime/Cargo.toml | 6 +- bin/rialto/runtime/src/lib.rs | 89 +++---- bin/rialto/runtime/src/parachains.rs | 3 +- bin/runtime-common/Cargo.toml | 4 +- modules/dispatch/Cargo.toml | 4 +- modules/grandpa/Cargo.toml | 8 +- modules/messages/Cargo.toml | 8 +- modules/messages/src/mock.rs | 2 +- modules/messages/src/outbound_lane.rs | 2 +- modules/shift-session-manager/Cargo.toml | 4 +- modules/token-swap/Cargo.toml | 6 +- primitives/chain-kusama/src/lib.rs | 2 - primitives/chain-millau/Cargo.toml | 6 +- primitives/chain-millau/src/lib.rs | 2 - primitives/chain-polkadot/src/lib.rs | 2 - primitives/chain-rialto-parachain/src/lib.rs | 2 - primitives/chain-rialto/src/lib.rs | 2 - primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-rococo/src/lib.rs | 2 - primitives/chain-westend/Cargo.toml | 4 +- primitives/chain-westend/src/lib.rs | 2 - primitives/chain-wococo/Cargo.toml | 2 +- primitives/chain-wococo/src/lib.rs | 2 - primitives/header-chain/Cargo.toml | 6 +- primitives/message-dispatch/Cargo.toml | 4 +- primitives/messages/Cargo.toml | 6 +- primitives/messages/src/lib.rs | 14 +- primitives/polkadot-core/Cargo.toml | 4 +- primitives/polkadot-core/src/lib.rs | 11 +- primitives/runtime/Cargo.toml | 4 +- primitives/runtime/src/storage_proof.rs | 3 +- primitives/test-utils/Cargo.toml | 4 +- primitives/token-swap/Cargo.toml | 4 +- relays/bin-substrate/Cargo.toml | 4 +- .../src/cli/register_parachain.rs | 4 +- relays/client-kusama/Cargo.toml | 4 +- relays/client-millau/Cargo.toml | 2 +- relays/client-millau/src/lib.rs | 2 + relays/client-polkadot/Cargo.toml | 4 +- relays/client-rialto/Cargo.toml | 2 +- relays/client-rialto/src/lib.rs | 2 + relays/client-rococo/Cargo.toml | 4 +- relays/client-substrate/Cargo.toml | 8 +- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/client.rs | 252 ++++++++++++++---- relays/client-substrate/src/error.rs | 2 +- relays/client-substrate/src/rpc.rs | 81 +++--- relays/client-westend/Cargo.toml | 2 +- relays/client-wococo/Cargo.toml | 4 +- relays/lib-substrate-relay/Cargo.toml | 5 +- relays/utils/Cargo.toml | 1 + relays/utils/src/relay_loop.rs | 32 ++- 66 files changed, 473 insertions(+), 286 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index b07cc29a06adc..3825b92b703c2 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,7 +10,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1", features = ["derive"] } jsonrpc-core = "18.0" serde_json = "1.0.59" diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index db64af878ff32..15f88269aa9c6 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -37,7 +37,6 @@ use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; -use sp_consensus::SlotData; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; @@ -141,7 +140,7 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; - let slot_duration = sc_consensus_aura::slot_duration(&*client)?.slot_duration(); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { @@ -152,7 +151,7 @@ pub fn new_partial( let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -349,7 +348,6 @@ pub fn new_full(mut config: Configuration) -> Result sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let raw_slot_duration = slot_duration.slot_duration(); let aura = sc_consensus_aura::start_aura::( StartAuraParams { @@ -362,9 +360,9 @@ pub fn new_full(mut config: Configuration) -> Result let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, - raw_slot_duration, + slot_duration, ); Ok((timestamp, slot)) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index b9f64d1f5d335..162404b77e7de 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,9 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -124,7 +124,7 @@ std = [ ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "libsecp256k1", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 5f8e503233557..d2da5affb235b 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -21,8 +21,6 @@ #![recursion_limit = "256"] // Runtime-generated enums #![allow(clippy::large_enum_variant)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] // From construct_runtime macro #![allow(clippy::from_over_into)] @@ -543,6 +541,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -913,7 +912,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); add_benchmark!(params, batches, pallet_bridge_token_swap, BridgeRialtoTokenSwap); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 81ed68a127b23..41021a35ed2b0 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -18,10 +18,10 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1", features = ["derive"] } derive_more = '0.99.2' log = '0.4.14' -codec = { package = 'parity-scale-codec', version = '2.0.0' } +codec = { package = 'parity-scale-codec', version = '3.0.0' } serde = { version = '1.0', features = ['derive'] } hex-literal = '0.3.1' @@ -81,7 +81,7 @@ cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-relay-chain-local = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } # Polkadot dependencies polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 7abb72cb876cd..89d049f022e3e 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::chain_spec; -use clap::{AppSettings, Parser}; +use clap::Parser; use std::path::PathBuf; /// Sub-commands supported by the collator. @@ -94,11 +94,11 @@ pub struct ExportGenesisWasmCommand { } #[derive(Debug, Parser)] -#[clap(setting( - AppSettings::PropagateVersion | - AppSettings::ArgsNegateSubcommands | - AppSettings::SubcommandsNegateReqs, -))] +#[clap( + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] pub struct Cli { #[clap(subcommand)] pub subcommand: Option, diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index 9a69042a80342..c47e742675da1 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -265,6 +265,7 @@ pub fn run() -> Result<()> { }, None => { let runner = cli.create_runner(&cli.run.normalize())?; + let collator_options = cli.run.collator_options(); runner.run_node_until_exit(|config| async move { let para_id = @@ -278,7 +279,7 @@ pub fn run() -> Result<()> { let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); let parachain_account = - AccountIdConversion::::into_account(&id); + AccountIdConversion::::into_account(&id); let state_version = RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); @@ -298,7 +299,7 @@ pub fn run() -> Result<()> { info!("Parachain genesis state: {}", genesis_state); info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - crate::service::start_node(config, polkadot_config, id) + crate::service::start_node(config, polkadot_config, collator_options, id) .await .map(|r| r.0) .map_err(Into::into) diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 61f705086e997..a2299e17457d9 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -28,6 +28,7 @@ use std::{sync::Arc, time::Duration}; use rialto_parachain_runtime::RuntimeApi; // Cumulus Imports +use cumulus_client_cli::CollatorOptions; use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; use cumulus_client_consensus_common::ParachainConsensus; use cumulus_client_network::BlockAnnounceValidator; @@ -35,8 +36,8 @@ use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; -use cumulus_relay_chain_interface::RelayChainInterface; -use cumulus_relay_chain_local::build_relay_chain_interface; +use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain; +use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; // Substrate Imports use sc_client_api::ExecutorProvider; @@ -45,7 +46,6 @@ use sc_network::NetworkService; use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; use sp_api::ConstructRuntimeApi; -use sp_consensus::SlotData; use sp_keystore::SyncCryptoStorePtr; use sp_runtime::traits::BlakeTwo256; use substrate_prometheus_endpoint::Registry; @@ -195,6 +195,7 @@ where async fn start_node_impl( parachain_config: Configuration, polkadot_config: Configuration, + collator_options: CollatorOptions, id: ParaId, rpc_ext_builder: RB, build_import_queue: BIQ, @@ -270,12 +271,16 @@ where let (mut telemetry, telemetry_worker_handle) = params.other; let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = - build_relay_chain_interface(polkadot_config, telemetry_worker_handle, &mut task_manager) - .map_err(|e| match e { - polkadot_service::Error::Sub(x) => x, - s => format!("{}", s).into(), - })?; + let (relay_chain_interface, collator_key) = build_inprocess_relay_chain( + polkadot_config, + ¶chain_config, + telemetry_worker_handle, + &mut task_manager, + ) + .map_err(|e| match e { + RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, + s => s.to_string().into(), + })?; let client = params.client.clone(); let backend = params.backend.clone(); @@ -350,7 +355,7 @@ where spawner, parachain_consensus, import_queue, - collator_key, + collator_key: collator_key.expect("Command line arguments do not allow this. qed"), relay_chain_slot_duration, }; @@ -364,6 +369,7 @@ where relay_chain_interface, relay_chain_slot_duration, import_queue, + collator_options, }; start_full_node(params)?; @@ -405,9 +411,9 @@ pub fn parachain_build_import_queue( let time = sp_timestamp::InherentDataProvider::from_system_time(); let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *time, - slot_duration.slot_duration(), + slot_duration, ); Ok((time, slot)) @@ -424,6 +430,7 @@ pub fn parachain_build_import_queue( pub async fn start_node( parachain_config: Configuration, polkadot_config: Configuration, + collator_options: CollatorOptions, id: ParaId, ) -> sc_service::error::Result<( TaskManager, @@ -432,6 +439,7 @@ pub async fn start_node( start_node_impl::( parachain_config, polkadot_config, + collator_options, id, |deny_unsafe, client, pool| { use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; @@ -481,9 +489,9 @@ pub async fn start_node( ).await; let time = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *time, - slot_duration.slot_duration(), + slot_duration, ); let parachain_inherent = parachain_inherent.ok_or_else(|| { diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index d3bb30c3c8532..1d0870fcbcd80 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -11,9 +11,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } [dependencies] -codec = { package = 'parity-scale-codec', version = '2.0.0', default-features = false, features = ['derive']} +codec = { package = 'parity-scale-codec', version = '3.0.0', default-features = false, features = ['derive']} log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = '1.0', optional = true, features = ['derive'] } # Bridge depedencies diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index e499c89f13acd..646521f329399 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -42,7 +42,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ - construct_runtime, match_type, parameter_types, + construct_runtime, match_types, parameter_types, traits::{Everything, IsInVec, Randomness}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, @@ -86,6 +86,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckGenesis, frame_system::CheckEra, @@ -350,7 +351,7 @@ parameter_types! { pub const MaxAuthorities: u32 = 100_000; } -match_type! { +match_types! { pub type ParentOrParentsUnitPlurality: impl Contains = { MultiLocation { parents: 1, interior: Here } | MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) } @@ -423,6 +424,9 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ChannelInfo = ParachainSystem; type VersionWrapper = (); type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = (); } impl cumulus_pallet_dmp_queue::Config for Runtime { @@ -613,7 +617,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, pallet_balances, Balances); add_benchmark!(params, batches, pallet_timestamp, Timestamp); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 34a2ec1d8b846..e44ceb45faa97 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,11 +10,11 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "3.0", features = ["derive"] } +clap = { version = "3.1", features = ["derive"] } futures = "0.3" jsonrpc-core = "18.0" -kvdb = "0.10" -kvdb-rocksdb = "0.12" +kvdb = "0.11" +kvdb-rocksdb = "0.15" lru = "0.7" serde_json = "1.0.59" thiserror = "1.0" diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 6bfacba83a1e1..10315e33c853a 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -16,7 +16,7 @@ use beefy_primitives::crypto::AuthorityId as BeefyId; use bp_rialto::derive_account_from_millau_id; -use polkadot_primitives::v1::{AssignmentId, ValidatorId}; +use polkadot_primitives::v2::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, @@ -253,8 +253,8 @@ fn testnet_genesis( validation_upgrade_cooldown: 2u32, validation_upgrade_delay: 2, code_retention_period: 1200, - max_code_size: polkadot_primitives::v1::MAX_CODE_SIZE, - max_pov_size: polkadot_primitives::v1::MAX_POV_SIZE, + max_code_size: polkadot_primitives::v2::MAX_CODE_SIZE, + max_pov_size: polkadot_primitives::v2::MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, chain_availability_period: 4, @@ -263,7 +263,7 @@ fn testnet_genesis( max_upward_queue_size: 1024 * 1024, max_downward_message_size: 1024 * 1024, ump_service_total_weight: 100_000_000_000, - max_upward_message_size: 1024 * 1024, + max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, hrmp_recipient_deposit: 0, diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 20155a1469e46..bb7f54998dd5f 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use clap::{AppSettings, Parser}; +use clap::Parser; use sc_cli::RunCmd; #[derive(Debug, Parser)] @@ -70,11 +70,11 @@ pub enum Subcommand { Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. - #[clap(name = "prepare-worker", setting = AppSettings::Hidden)] + #[clap(name = "prepare-worker", hide = true)] PvfPrepareWorker(ValidationWorkerCommand), /// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary. - #[clap(name = "execute-worker", setting = AppSettings::Hidden)] + #[clap(name = "execute-worker", hide = true)] PvfExecuteWorker(ValidationWorkerCommand), } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 1d81de2cb0c4d..da92837f06c09 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -192,6 +192,7 @@ pub fn run() -> sc_cli::Result<()> { let jaeger_agent = None; let telemetry_worker_handle = None; let program_path = None; + let overseer_enable_anyways = false; polkadot_service::new_full::( config, @@ -201,6 +202,7 @@ pub fn run() -> sc_cli::Result<()> { jaeger_agent, telemetry_worker_handle, program_path, + overseer_enable_anyways, overseer_gen, ) .map(|full| full.task_manager) diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 5cfa11e12a9af..59b9a8e9b5755 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,11 +8,11 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -137,7 +137,7 @@ std = [ ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "libsecp256k1", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8dd4c2cc27876..87cddf5e268db 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -21,8 +21,6 @@ #![recursion_limit = "256"] // Runtime-generated enums #![allow(clippy::large_enum_variant)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] // From construct_runtime macro #![allow(clippy::from_over_into)] @@ -534,6 +532,7 @@ pub type SignedBlock = generic::SignedBlock; pub type BlockId = generic::BlockId; /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( + frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, frame_system::CheckTxVersion, frame_system::CheckGenesis, @@ -717,55 +716,55 @@ impl_runtime_apis! { } impl polkadot_primitives::v2::ParachainHost for Runtime { - fn validators() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v1::validators::() + fn validators() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v2::validators::() } - fn validator_groups() -> (Vec>, polkadot_primitives::v1::GroupRotationInfo) { - polkadot_runtime_parachains::runtime_api_impl::v1::validator_groups::() + fn validator_groups() -> (Vec>, polkadot_primitives::v2::GroupRotationInfo) { + polkadot_runtime_parachains::runtime_api_impl::v2::validator_groups::() } - fn availability_cores() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v1::availability_cores::() + fn availability_cores() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v2::availability_cores::() } - fn persisted_validation_data(para_id: polkadot_primitives::v1::Id, assumption: polkadot_primitives::v1::OccupiedCoreAssumption) - -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v1::persisted_validation_data::(para_id, assumption) + fn persisted_validation_data(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) + -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v2::persisted_validation_data::(para_id, assumption) } fn assumed_validation_data( - para_id: polkadot_primitives::v1::Id, + para_id: polkadot_primitives::v2::Id, expected_persisted_validation_data_hash: Hash, - ) -> Option<(polkadot_primitives::v1::PersistedValidationData, polkadot_primitives::v1::ValidationCodeHash)> { - polkadot_runtime_parachains::runtime_api_impl::v1::assumed_validation_data::( + ) -> Option<(polkadot_primitives::v2::PersistedValidationData, polkadot_primitives::v2::ValidationCodeHash)> { + polkadot_runtime_parachains::runtime_api_impl::v2::assumed_validation_data::( para_id, expected_persisted_validation_data_hash, ) } fn check_validation_outputs( - para_id: polkadot_primitives::v1::Id, - outputs: polkadot_primitives::v1::CandidateCommitments, + para_id: polkadot_primitives::v2::Id, + outputs: polkadot_primitives::v2::CandidateCommitments, ) -> bool { - polkadot_runtime_parachains::runtime_api_impl::v1::check_validation_outputs::(para_id, outputs) + polkadot_runtime_parachains::runtime_api_impl::v2::check_validation_outputs::(para_id, outputs) } - fn session_index_for_child() -> polkadot_primitives::v1::SessionIndex { - polkadot_runtime_parachains::runtime_api_impl::v1::session_index_for_child::() + fn session_index_for_child() -> polkadot_primitives::v2::SessionIndex { + polkadot_runtime_parachains::runtime_api_impl::v2::session_index_for_child::() } - fn validation_code(para_id: polkadot_primitives::v1::Id, assumption: polkadot_primitives::v1::OccupiedCoreAssumption) - -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::validation_code::(para_id, assumption) + fn validation_code(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) + -> Option { + polkadot_runtime_parachains::runtime_api_impl::v2::validation_code::(para_id, assumption) } - fn candidate_pending_availability(para_id: polkadot_primitives::v1::Id) -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v1::candidate_pending_availability::(para_id) + fn candidate_pending_availability(para_id: polkadot_primitives::v2::Id) -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v2::candidate_pending_availability::(para_id) } - fn candidate_events() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v1::candidate_events::(|ev| { + fn candidate_events() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v2::candidate_events::(|ev| { match ev { Event::Inclusion(ev) => { Some(ev) @@ -775,46 +774,46 @@ impl_runtime_apis! { }) } - fn session_info(index: polkadot_primitives::v1::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::session_info::(index) + fn session_info(index: polkadot_primitives::v2::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v2::session_info::(index) } - fn dmq_contents(recipient: polkadot_primitives::v1::Id) -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v1::dmq_contents::(recipient) + fn dmq_contents(recipient: polkadot_primitives::v2::Id) -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v2::dmq_contents::(recipient) } fn inbound_hrmp_channels_contents( - recipient: polkadot_primitives::v1::Id - ) -> BTreeMap>> { - polkadot_runtime_parachains::runtime_api_impl::v1::inbound_hrmp_channels_contents::(recipient) + recipient: polkadot_primitives::v2::Id + ) -> BTreeMap>> { + polkadot_runtime_parachains::runtime_api_impl::v2::inbound_hrmp_channels_contents::(recipient) } - fn validation_code_by_hash(hash: polkadot_primitives::v1::ValidationCodeHash) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_by_hash::(hash) + fn validation_code_by_hash(hash: polkadot_primitives::v2::ValidationCodeHash) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_by_hash::(hash) } - fn on_chain_votes() -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v1::on_chain_votes::() + fn on_chain_votes() -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v2::on_chain_votes::() } - fn submit_pvf_check_statement(stmt: polkadot_primitives::v2::PvfCheckStatement, signature: polkadot_primitives::v1::ValidatorSignature) { - polkadot_runtime_parachains::runtime_api_impl::v1::submit_pvf_check_statement::(stmt, signature) + fn submit_pvf_check_statement(stmt: polkadot_primitives::v2::PvfCheckStatement, signature: polkadot_primitives::v2::ValidatorSignature) { + polkadot_runtime_parachains::runtime_api_impl::v2::submit_pvf_check_statement::(stmt, signature) } - fn pvfs_require_precheck() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v1::pvfs_require_precheck::() + fn pvfs_require_precheck() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v2::pvfs_require_precheck::() } - fn validation_code_hash(para_id: polkadot_primitives::v1::Id, assumption: polkadot_primitives::v1::OccupiedCoreAssumption) - -> Option + fn validation_code_hash(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) + -> Option { - polkadot_runtime_parachains::runtime_api_impl::v1::validation_code_hash::(para_id, assumption) + polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_hash::(para_id, assumption) } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { fn authorities() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v1::relevant_authority_ids::() + polkadot_runtime_parachains::runtime_api_impl::v2::relevant_authority_ids::() } } diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 9a316ef0e2a78..20a9aeb28c0df 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -23,7 +23,7 @@ use crate::{ use frame_support::{parameter_types, weights::Weight}; use frame_system::EnsureRoot; -use polkadot_primitives::v1::ValidatorIndex; +use polkadot_primitives::v2::ValidatorIndex; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp, @@ -108,6 +108,7 @@ impl parachains_ump::Config for Runtime { type UmpSink = (); type FirstMessageFactorPercent = FirstMessageFactorPercent; type ExecuteOverweightOrigin = EnsureRoot; + type WeightInfo = parachains_ump::TestWeightInfo; } // required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 54055e10c5fb5..abd84364ce2cd 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -8,10 +8,10 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index d073f8722e904..833d5cca77a71 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 779bf18fe2e64..eac80375da128 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -8,11 +8,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -finality-grandpa = { version = "0.14.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +finality-grandpa = { version = "0.15.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -58,5 +58,5 @@ std = [ ] runtime-benchmarks = [ "bp-test-utils", - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", ] diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index ee575dbe67bbf..804f323f10b6f 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -7,11 +7,11 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "0.20", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +bitvec = { version = "1", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -51,5 +51,5 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", ] diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 2669ddfbef26f..75dcce8df0449 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -543,7 +543,7 @@ pub fn unrewarded_relayer( begin, end, dispatch_results: if end >= begin { - bitvec![Msb0, u8; 1; (end - begin + 1) as _] + bitvec![u8, Msb0; 1; (end - begin + 1) as _] } else { Default::default() }, diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index c05437596db82..cfdc81acc315b 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -260,7 +260,7 @@ mod tests { DeliveredMessages { begin: *nonces.start(), end: *nonces.end(), - dispatch_results: bitvec![Msb0, u8; 1; (nonces.end() - nonces.start() + 1) as _], + dispatch_results: bitvec![u8, Msb0; 1; (nonces.end() - nonces.start() + 1) as _], } } diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 694e0a82da9f4..30a5618b115f2 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index 7ccb50200c1f6..aad395fb7a306 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" 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 = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies @@ -55,5 +55,5 @@ std = [ "sp-std/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index d1d4c79df1943..ca5c545267da7 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce}; use frame_support::weights::{ diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index c35c1f07348e4..0aaeb5b6bf9d4 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -14,10 +14,10 @@ bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } -impl-codec = { version = "0.5.1", default-features = false } +impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.10", default-features = false, features = ["primitive-types"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +parity-util-mem = { version = "0.11", default-features = false, features = ["primitive-types"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 3a2f120f465c2..ff8d53859535b 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] mod millau_hash; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 0627a9952032c..52202c3897fea 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce}; use frame_support::weights::{ diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 786226cf93c99..f3f449c7af3e1 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_runtime::Chain; use frame_support::{ diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 33b30a183d643..4bf20489bc851 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_With_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce}; use bp_runtime::Chain; diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 684b294a266fb..814cd09bf170c 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index f8c080d851164..a05d55ad8bd83 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce}; use frame_support::weights::{ diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index e1d3ade7fe65b..ee6e2b9be99a0 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index af0ad27c9bc10..c7ebe4b00fd5d 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index dcae1844784e9..633cdd15c1f56 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 4b387a846cf31..f39543114c78b 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -17,8 +17,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Runtime-generated DecodeLimit::decode_all_with_depth_limit -#![allow(clippy::unnecessary_mut_passed)] use bp_messages::{LaneId, MessageDetails, MessageNonce}; use sp_runtime::FixedU128; diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 29aa34048e629..7cd688d0d8197 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -finality-grandpa = { version = "0.14.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +finality-grandpa = { version = "0.15.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 6a3a2fdbdf7be..39b2d00111e15 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -8,8 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 2142ad028173a..2a84f74d225bd 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "0.20", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["derive", "bit-vec"] } +bitvec = { version = "1", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "1.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 691ed57794db7..a4f204d238f7d 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -194,7 +194,7 @@ pub struct MessageDetails { } /// Bit vector of message dispatch results. -pub type DispatchResultsBitVec = BitVec; +pub type DispatchResultsBitVec = BitVec; /// Unrewarded relayer entry stored in the inbound lane data. /// @@ -225,11 +225,9 @@ impl DeliveredMessages { /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given /// dispatch result. pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { - DeliveredMessages { - begin: nonce, - end: nonce, - dispatch_results: bitvec![Msb0, u8; if dispatch_result { 1 } else { 0 }], - } + let mut dispatch_results = BitVec::with_capacity(1); + dispatch_results.push(if dispatch_result { true } else { false }); + DeliveredMessages { begin: nonce, end: nonce, dispatch_results } } /// Return total count of delivered messages. @@ -368,7 +366,7 @@ mod tests { messages: DeliveredMessages::new(i as _, true), }; entry.messages.dispatch_results = bitvec![ - Msb0, u8; + u8, Msb0; 1; (messages_count / relayer_entries) as _ ]; @@ -394,7 +392,7 @@ mod tests { #[test] fn message_dispatch_result_works() { let delivered_messages = - DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![Msb0, u8; 1; 151] }; + DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![u8, Msb0; 1; 151] }; assert!(!delivered_messages.contains_message(99)); assert!(delivered_messages.contains_message(100)); diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index b35ac74ad5652..1542a784ef561 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "2.2.0", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index a56adfd2337eb..79db07b82cbb0 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -239,11 +239,12 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< pub type Address = MultiAddress; /// A type of the data encoded as part of the transaction. -pub type SignedExtra = ((), (), (), sp_runtime::generic::Era, Compact, (), Compact); +pub type SignedExtra = + ((), (), (), (), sp_runtime::generic::Era, Compact, (), Compact); /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). -pub type AdditionalSigned = (u32, u32, Hash, Hash, (), (), ()); +pub type AdditionalSigned = ((), u32, u32, Hash, Hash, (), (), ()); /// A simplified version of signed extensions meant for producing signed transactions /// and signed payload in the client code. @@ -287,6 +288,7 @@ impl SignedExtensions { ) -> Self { Self { encode_payload: ( + (), // non-zero sender (), // spec version (), // tx version (), // genesis @@ -296,6 +298,7 @@ impl SignedExtensions { tip.into(), // transaction payment / tip (compact encoding) ), additional_signed: Some(( + (), spec_version, transaction_version, genesis_hash, @@ -312,12 +315,12 @@ impl SignedExtensions { impl SignedExtensions { /// Return signer nonce, used to craft transaction. pub fn nonce(&self) -> Nonce { - self.encode_payload.4.into() + self.encode_payload.5.into() } /// Return transaction tip. pub fn tip(&self) -> Balance { - self.encode_payload.6.into() + self.encode_payload.7.into() } } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 51b817fd40382..085cfb9dbc6d4 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -7,10 +7,10 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.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"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 177b0f8664e4c..4a99ab6210f49 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -88,8 +88,7 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { let proof = StorageProof::new( prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) .unwrap() - .iter_nodes() - .collect(), + .iter_nodes(), ); (root, proof) diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 0703b4f0f9265..6da5c7c0f4b5f 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -7,9 +7,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } -finality-grandpa = { version = "0.14.0", default-features = false } +finality-grandpa = { version = "0.15.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 66af0be2f76d4..9097856f853ac 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 7083d265da5e7..fb8ff467d047d 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" hex = "0.4" log = "0.4.14" @@ -79,4 +79,4 @@ hex-literal = "0.3" pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempfile = "3.2" -finality-grandpa = { version = "0.14.0" } +finality-grandpa = { version = "0.15.0" } diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 4d75143755890..c761a5dd1a603 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -107,8 +107,8 @@ impl RegisterParachain { let para_id: ParaId = relay_client .storage_value(StorageKey(para_id_key.to_vec()), None) .await? - .unwrap_or(polkadot_primitives::v1::LOWEST_PUBLIC_ID) - .max(polkadot_primitives::v1::LOWEST_PUBLIC_ID); + .unwrap_or(polkadot_primitives::v2::LOWEST_PUBLIC_ID) + .max(polkadot_primitives::v2::LOWEST_PUBLIC_ID); log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 91a78719bbc21..35c24c1089e60 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 3f193ffff033c..9893243345518 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index b0c1dc0dc7cd5..e131f42494b31 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -105,6 +105,7 @@ impl TransactionSignScheme for Millau { let raw_payload = SignedPayload::from_raw( param.unsigned.call.clone(), ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), @@ -114,6 +115,7 @@ impl TransactionSignScheme for Millau { pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), ), ( + (), param.spec_version, param.transaction_version, param.genesis_hash, diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 5c6904d57b356..96cfa2ce1bacf 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index f8ceb3a925641..37c55dd5f153f 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 5cd21d55e7547..78e5f4431493d 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -105,6 +105,7 @@ impl TransactionSignScheme for Rialto { let raw_payload = SignedPayload::from_raw( param.unsigned.call.clone(), ( + frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), @@ -114,6 +115,7 @@ impl TransactionSignScheme for Rialto { pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), ), ( + (), param.spec_version, param.transaction_version, param.genesis_hash, diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 8d256dc8814f8..2b78684a853cb 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", features = ["derive"] } +scale-info = { version = "2.0.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 0f3e35c6f438f..dad864965e29e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -8,13 +8,13 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" -codec = { package = "parity-scale-codec", version = "2.2.0" } -jsonrpsee-proc-macros = "0.3.1" -jsonrpsee-ws-client = "0.3.1" +codec = { package = "parity-scale-codec", version = "3.0.0" } +jsonrpsee = { version = "0.8", features = ["macros", "ws-client"] } log = "0.4.11" num-traits = "0.2" rand = "0.7" -tokio = "1.8" +serde = { version = "1.0" } +tokio = { version = "1.8", features = ["rt-multi-thread"] } thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 6987fbae1c6b9..c3b0c32d5a4c0 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -18,7 +18,7 @@ use bp_messages::MessageNonce; use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; use frame_support::weights::{Weight, WeightToFeePolynomial}; -use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; +use jsonrpsee::core::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; use sp_core::{storage::StorageKey, Pair}; diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index f35281e2d35c5..1e48bc3339668 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -18,8 +18,9 @@ use crate::{ chain::{Chain, ChainWithBalances, TransactionStatusOf}, - rpc::Substrate, - ConnectionParams, Error, HashOf, HeaderIdOf, Result, + rpc::SubstrateClient, + AccountIdOf, BlockNumberOf, ConnectionParams, Error, HashOf, HeaderIdOf, HeaderOf, IndexOf, + Result, }; use async_std::sync::{Arc, Mutex}; @@ -27,12 +28,10 @@ use async_trait::async_trait; use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; -use jsonrpsee_ws_client::{ - types::{ - self as jsonrpsee_types, traits::SubscriptionClient, v2::params::JsonRpcParams, - DeserializeOwned, - }, - WsClient as RpcClient, WsClientBuilder as RpcClientBuilder, +use jsonrpsee::{ + core::{client::SubscriptionClientT, DeserializeOwned}, + types::params::ParamsSer, + ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; use num_traits::{Bounded, CheckedSub, One, Zero}; use pallet_balances::AccountData; @@ -154,7 +153,15 @@ impl Client { let genesis_hash_client = client.clone(); let genesis_hash = tokio .spawn(async move { - Substrate::::chain_get_block_hash(&*genesis_hash_client, number).await + SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_block_hash(&*genesis_hash_client, Some(number)) + .await }) .await??; @@ -210,7 +217,15 @@ impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { self.jsonrpsee_execute(|client| async move { - let health = Substrate::::system_health(&*client).await?; + let health = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::system_health(&*client) + .await?; let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); if is_synced { Ok(()) @@ -229,7 +244,15 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { self.jsonrpsee_execute(|client| async move { - Ok(Substrate::::chain_get_finalized_head(&*client).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_finalized_head(&*client) + .await?) }) .await } @@ -245,7 +268,15 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(|client| async move { - Ok(Substrate::::chain_get_header(&*client, None).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_header(&*client, None) + .await?) }) .await } @@ -253,7 +284,15 @@ impl Client { /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::chain_get_block(&*client, block_hash).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_block(&*client, block_hash) + .await?) }) .await } @@ -264,7 +303,15 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::chain_get_header(&*client, block_hash).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_header(&*client, Some(block_hash)) + .await?) }) .await } @@ -272,7 +319,15 @@ impl Client { /// Get a Substrate block hash by its number. pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::chain_get_block_hash(&*client, number).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::chain_get_block_hash(&*client, Some(number)) + .await?) }) .await } @@ -290,7 +345,15 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::state_runtime_version(&*client).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_runtime_version(&*client) + .await?) }) .await } @@ -316,7 +379,15 @@ impl Client { block_hash: Option, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::state_get_storage(&*client, storage_key, block_hash).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_get_storage(&*client, storage_key, block_hash) + .await?) }) .await } @@ -328,10 +399,16 @@ impl Client { { self.jsonrpsee_execute(move |client| async move { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = - Substrate::::state_get_storage(&*client, storage_key, None) - .await? - .ok_or(Error::AccountDoesNotExist)?; + let encoded_account_data = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_get_storage(&*client, storage_key, None) + .await? + .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = AccountInfo::>::decode( &mut &encoded_account_data.0[..], ) @@ -346,7 +423,15 @@ impl Client { /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::system_account_next_index(&*client, account).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::system_account_next_index(&*client, account) + .await?) }) .await } @@ -356,7 +441,15 @@ impl Client { /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { self.jsonrpsee_execute(move |client| async move { - let tx_hash = Substrate::::author_submit_extrinsic(&*client, transaction).await?; + let tx_hash = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::author_submit_extrinsic(&*client, transaction) + .await?; log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); Ok(tx_hash) }) @@ -391,7 +484,15 @@ impl Client { self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; + let tx_hash = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::author_submit_extrinsic(&*client, extrinsic) + .await?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) @@ -416,8 +517,8 @@ impl Client { let subscription = client .subscribe( "author_submitAndWatchExtrinsic", - JsonRpcParams::Array(vec![jsonrpsee_types::to_json_value(extrinsic) - .map_err(|e| Error::RpcError(e.into()))?]), + Some(ParamsSer::Array(vec![jsonrpsee::core::to_json_value(extrinsic) + .map_err(|e| Error::RpcError(e.into()))?])), "author_unwatchExtrinsic", ) .await?; @@ -438,7 +539,15 @@ impl Client { /// Returns pending extrinsics from transaction pool. pub async fn pending_extrinsics(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(Substrate::::author_pending_extrinsics(&*client).await?) + Ok(SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::author_pending_extrinsics(&*client) + .await?) }) .await } @@ -453,8 +562,15 @@ impl Client { let call = SUB_API_TXPOOL_VALIDATE_TRANSACTION.to_string(); let data = Bytes((TransactionSource::External, transaction, at_block).encode()); - let encoded_response = - Substrate::::state_call(&*client, call, data, Some(at_block)).await?; + let encoded_response = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_call(&*client, call, data, Some(at_block)) + .await?; let validity = TransactionValidity::decode(&mut &encoded_response.0[..]) .map_err(Error::ResponseParseFailed)?; @@ -469,8 +585,15 @@ impl Client { transaction: Bytes, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - let fee_details = - Substrate::::payment_query_fee_details(&*client, transaction, None).await?; + let fee_details = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::payment_query_fee_details(&*client, transaction, None) + .await?; let inclusion_fee = fee_details .inclusion_fee .map(|inclusion_fee| InclusionFee { @@ -502,8 +625,15 @@ impl Client { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); - let encoded_response = - Substrate::::state_call(&*client, call, data, Some(block)).await?; + let encoded_response = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_call(&*client, call, data, Some(block)) + .await?; let authority_list = encoded_response.0; Ok(authority_list) @@ -519,9 +649,16 @@ impl Client { at_block: Option, ) -> Result { self.jsonrpsee_execute(move |client| async move { - Substrate::::state_call(&*client, method, data, at_block) - .await - .map_err(Into::into) + SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_call(&*client, method, data, at_block) + .await + .map_err(Into::into) }) .await } @@ -533,10 +670,19 @@ impl Client { at_block: C::Hash, ) -> Result { self.jsonrpsee_execute(move |client| async move { - Substrate::::state_prove_storage(&*client, keys, Some(at_block)) - .await - .map(|proof| StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect())) - .map_err(Into::into) + SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::state_prove_storage(&*client, keys, Some(at_block)) + .await + .map(|proof| { + StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect::>()) + }) + .map_err(Into::into) }) .await } @@ -544,7 +690,15 @@ impl Client { /// Return `tokenDecimals` property from the set of chain properties. pub async fn token_decimals(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - let system_properties = Substrate::::system_properties(&*client).await?; + let system_properties = SubstrateClient::< + AccountIdOf, + BlockNumberOf, + HashOf, + HeaderOf, + IndexOf, + C::SignedBlock, + >::system_properties(&*client) + .await?; Ok(system_properties.get("tokenDecimals").and_then(|v| v.as_u64())) }) .await @@ -557,7 +711,7 @@ impl Client { Ok(client .subscribe( "grandpa_subscribeJustifications", - JsonRpcParams::NoParams, + None, "grandpa_unsubscribeJustifications", ) .await?) @@ -597,32 +751,32 @@ impl Subscription { async fn background_worker( chain_name: String, item_type: String, - mut subscription: jsonrpsee_types::Subscription, + mut subscription: jsonrpsee::core::client::Subscription, mut sender: futures::channel::mpsc::Sender>, ) { loop { match subscription.next().await { - Ok(Some(item)) => + Some(Ok(item)) => if sender.send(Some(item)).await.is_err() { break }, - Ok(None) => { + Some(Err(e)) => { log::trace!( target: "bridge", - "{} {} subscription stream has returned None. Stream needs to be restarted.", + "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", chain_name, item_type, + e, ); let _ = sender.send(None).await; break }, - Err(e) => { + None => { log::trace!( target: "bridge", - "{} {} subscription stream has returned '{:?}'. Stream needs to be restarted.", + "{} {} subscription stream has returned None. Stream needs to be restarted.", chain_name, item_type, - e, ); let _ = sender.send(None).await; break diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 309531dd26099..e698f2596c5fa 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -16,7 +16,7 @@ //! Substrate node RPC errors. -use jsonrpsee_ws_client::types::Error as RpcError; +use jsonrpsee::core::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; use sp_runtime::transaction_validity::TransactionValidityError; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index b792347d7a2ba..a0172d1e55013 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -16,8 +16,7 @@ //! The most generic Substrate node RPC interface. -use crate::chain::Chain; - +use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use pallet_transaction_payment_rpc_runtime_api::FeeDetails; use sc_rpc_api::{state::ReadProof, system::Health}; use sp_core::{ @@ -27,35 +26,51 @@ use sp_core::{ use sp_rpc::number::NumberOrHex; use sp_version::RuntimeVersion; -jsonrpsee_proc_macros::rpc_client_api! { - pub(crate) Substrate { - #[rpc(method = "system_health", positional_params)] - fn system_health() -> Health; - #[rpc(method = "system_properties", positional_params)] - fn system_properties() -> sc_chain_spec::Properties; - #[rpc(method = "chain_getHeader", positional_params)] - fn chain_get_header(block_hash: Option) -> C::Header; - #[rpc(method = "chain_getFinalizedHead", positional_params)] - fn chain_get_finalized_head() -> C::Hash; - #[rpc(method = "chain_getBlock", positional_params)] - fn chain_get_block(block_hash: Option) -> C::SignedBlock; - #[rpc(method = "chain_getBlockHash", positional_params)] - fn chain_get_block_hash(block_number: Option) -> C::Hash; - #[rpc(method = "system_accountNextIndex", positional_params)] - fn system_account_next_index(account_id: C::AccountId) -> C::Index; - #[rpc(method = "author_submitExtrinsic", positional_params)] - fn author_submit_extrinsic(extrinsic: Bytes) -> C::Hash; - #[rpc(method = "author_pendingExtrinsics", positional_params)] - fn author_pending_extrinsics() -> Vec; - #[rpc(method = "state_call", positional_params)] - fn state_call(method: String, data: Bytes, at_block: Option) -> Bytes; - #[rpc(method = "state_getStorage", positional_params)] - fn state_get_storage(key: StorageKey, at_block: Option) -> Option; - #[rpc(method = "state_getReadProof", positional_params)] - fn state_prove_storage(keys: Vec, hash: Option) -> ReadProof; - #[rpc(method = "state_getRuntimeVersion", positional_params)] - fn state_runtime_version() -> RuntimeVersion; - #[rpc(method = "payment_queryFeeDetails", positional_params)] - fn payment_query_fee_details(extrinsic: Bytes, at_block: Option) -> FeeDetails; - } +#[rpc(client)] +pub(crate) trait Substrate { + #[method(name = "system_health", param_kind = array)] + async fn system_health(&self) -> RpcResult; + #[method(name = "system_properties", param_kind = array)] + async fn system_properties(&self) -> RpcResult; + #[method(name = "chain_getHeader", param_kind = array)] + async fn chain_get_header(&self, block_hash: Option) -> RpcResult

; + #[method(name = "chain_getFinalizedHead", param_kind = array)] + async fn chain_get_finalized_head(&self) -> RpcResult; + #[method(name = "chain_getBlock", param_kind = array)] + async fn chain_get_block(&self, block_hash: Option) -> RpcResult; + #[method(name = "chain_getBlockHash", param_kind = array)] + async fn chain_get_block_hash(&self, block_number: Option) -> RpcResult; + #[method(name = "system_accountNextIndex", param_kind = array)] + async fn system_account_next_index(&self, account_id: AccountId) -> RpcResult; + #[method(name = "author_submitExtrinsic", param_kind = array)] + async fn author_submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; + #[method(name = "author_pendingExtrinsics", param_kind = array)] + async fn author_pending_extrinsics(&self) -> RpcResult>; + #[method(name = "state_call", param_kind = array)] + async fn state_call( + &self, + method: String, + data: Bytes, + at_block: Option, + ) -> RpcResult; + #[method(name = "state_getStorage", param_kind = array)] + async fn state_get_storage( + &self, + key: StorageKey, + at_block: Option, + ) -> RpcResult>; + #[method(name = "state_getReadProof", param_kind = array)] + async fn state_prove_storage( + &self, + keys: Vec, + hash: Option, + ) -> RpcResult>; + #[method(name = "state_getRuntimeVersion", param_kind = array)] + async fn state_runtime_version(&self) -> RpcResult; + #[method(name = "payment_queryFeeDetails", param_kind = array)] + async fn payment_query_fee_details( + &self, + extrinsic: Bytes, + at_block: Option, + ) -> RpcResult>; } diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 8a0e6434d09ab..d38aa16299459 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 201a727fc4755..6845ac34c84a0 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "1.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } # Bridge dependencies bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 52e800caa77c7..e2cabf52f449b 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,18 +10,17 @@ anyhow = "1.0" thiserror = "1.0.26" async-std = "1.9.0" async-trait = "0.1.42" -codec = { package = "parity-scale-codec", version = "2.2.0" } +codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" num-traits = "0.2" log = "0.4.14" - # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-grandpa = { version = "0.14.0" } +finality-grandpa = { version = "0.15.0" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } messages-relay = { path = "../messages" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 123c23176786c..bb69849da26b0 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,6 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.15" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } +tokio = { version = "1.8", features = ["rt"] } thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index a992aaaf57ee5..521a6345d3e39 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -187,12 +187,32 @@ impl LoopMetrics { let registry = self.registry; async_std::task::spawn(async move { - let result = init_prometheus(socket_addr, registry).await; - log::trace!( - target: "bridge-metrics", - "Prometheus endpoint has exited with result: {:?}", - result, - ); + let runtime = + match tokio::runtime::Builder::new_current_thread().enable_all().build() { + Ok(runtime) => runtime, + Err(err) => { + log::trace!( + target: "bridge-metrics", + "Failed to create tokio runtime. Prometheus meterics are not available: {:?}", + err, + ); + return + }, + }; + + let _ = runtime.block_on(async move { + log::trace!( + target: "bridge-metrics", + "Starting prometheus endpoint at: {:?}", + socket_addr, + ); + let result = init_prometheus(socket_addr, registry).await; + log::trace!( + target: "bridge-metrics", + "Prometheus endpoint has exited with result: {:?}", + result, + ); + }); }); } From 8ddd0c5af18682b61cd115adc7a4b4322f1a8c2e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 17 Mar 2022 12:57:33 +0300 Subject: [PATCH 0669/1210] update chain versions (#1358) --- primitives/chain-kusama/src/lib.rs | 4 ++-- primitives/chain-polkadot/src/lib.rs | 4 ++-- primitives/chain-rococo/src/lib.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index ca5c545267da7..a0a5990ca08ad 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -36,10 +36,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("kusama"), impl_name: sp_version::create_runtime_str!("parity-kusama"), authoring_version: 2, - spec_version: 9140, + spec_version: 9180, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 8, + transaction_version: 11, state_version: 0, }; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 52202c3897fea..d95e29c8b0ce8 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -36,10 +36,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("polkadot"), impl_name: sp_version::create_runtime_str!("parity-polkadot"), authoring_version: 0, - spec_version: 9140, + spec_version: 9180, impl_version: 0, apis: sp_version::create_apis_vec![[]], - transaction_version: 9, + transaction_version: 12, state_version: 0, }; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a05d55ad8bd83..127e75d5f8b2f 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -43,7 +43,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 9140, + spec_version: 9180, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, From 6b60384818fe98eb107036cc0b8091c052f5fa7d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 18 Mar 2022 17:17:23 +0300 Subject: [PATCH 0670/1210] fix parse_transaction on Rialto+Millau (#1360) --- primitives/runtime/src/chain.rs | 2 +- relays/client-millau/src/lib.rs | 35 +++++++++++++++++++++++++--- relays/client-rialto/src/lib.rs | 35 +++++++++++++++++++++++++--- relays/client-substrate/src/chain.rs | 2 +- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 1c80622472291..5a7fafe9f67c0 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -27,7 +27,7 @@ use sp_runtime::{ use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec}; /// Chain call, that is either SCALE-encoded, or decoded. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum EncodedOrDecodedCall { /// The call that is SCALE-encoded. /// diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index e131f42494b31..eae9d9b4586a5 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -31,7 +31,7 @@ use std::time::Duration; pub type HeaderId = relay_utils::HeaderId; /// Millau chain definition. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Millau; impl ChainBase for Millau { @@ -154,8 +154,8 @@ impl TransactionSignScheme for Millau { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { call: tx.function.into(), - nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), - tip: Compact::>::decode(&mut &extra.6.encode()[..]) + nonce: Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + tip: Compact::>::decode(&mut &extra.7.encode()[..]) .ok()? .into(), }) @@ -167,3 +167,32 @@ pub type SigningParams = sp_core::sr25519::Pair; /// Millau header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: millau_runtime::Call::System(millau_runtime::SystemCall::remark { + remark: b"Hello world!".to_vec(), + }) + .into(), + nonce: 777, + tip: 888, + }; + let signed_transaction = Millau::sign_transaction(SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 64].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + era: TransactionEra::immortal(), + unsigned: unsigned.clone(), + }) + .unwrap(); + let parsed_transaction = Millau::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 78e5f4431493d..858227e8083f6 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -31,7 +31,7 @@ use std::time::Duration; pub type HeaderId = relay_utils::HeaderId; /// Rialto chain definition -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Rialto; impl ChainBase for Rialto { @@ -152,8 +152,8 @@ impl TransactionSignScheme for Rialto { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { call: tx.function.into(), - nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), - tip: Compact::>::decode(&mut &extra.6.encode()[..]) + nonce: Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + tip: Compact::>::decode(&mut &extra.7.encode()[..]) .ok()? .into(), }) @@ -165,3 +165,32 @@ pub type SigningParams = sp_core::sr25519::Pair; /// Rialto header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { + remark: b"Hello world!".to_vec(), + }) + .into(), + nonce: 777, + tip: 888, + }; + let signed_transaction = Rialto::sign_transaction(SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + era: TransactionEra::immortal(), + unsigned: unsigned.clone(), + }) + .unwrap(); + let parsed_transaction = Rialto::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index c3b0c32d5a4c0..60adfb0a88ac2 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -134,7 +134,7 @@ pub trait BlockWithJustification
{ } /// Transaction before it is signed. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedTransaction { /// Runtime call of this transaction. pub call: EncodedOrDecodedCall, From 44bea30d6f9e5ece01130545951bbc147681cb57 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 22 Mar 2022 14:59:58 +0200 Subject: [PATCH 0671/1210] Few typos and clippy fixes (#1362) * fix typos * clippy fixes --- bin/runtime-common/src/messages.rs | 22 +++++++++---------- modules/grandpa/src/lib.rs | 2 +- modules/messages/src/mock.rs | 2 +- modules/messages/src/outbound_lane.rs | 2 +- primitives/header-chain/src/justification.rs | 12 +++++----- primitives/messages/src/lib.rs | 6 ++--- primitives/runtime/src/chain.rs | 1 - relays/bin-substrate/src/cli/reinit_bridge.rs | 6 ++--- .../src/conversion_rate_update.rs | 2 +- .../src/messages_target.rs | 2 +- 10 files changed, 26 insertions(+), 31 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 250b68ceffe2f..6bcaae4d36577 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -327,18 +327,16 @@ pub mod source { frame_system::RawOrigin>>, OriginOf>, > = submitter.clone().into(); - match raw_origin_or_err { - Ok(raw_origin) => - pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload) - .map(drop) - .map_err(|_| BAD_ORIGIN)?, - Err(_) => { - // so what it means that we've failed to convert origin to the - // `frame_system::RawOrigin`? now it means that the custom pallet origin has - // been used to send the message. Do we need to verify it? The answer is no, - // because pallet may craft any origin (e.g. root) && we can't verify whether it - // is valid, or not. - }, + if let Ok(raw_origin) = raw_origin_or_err { + pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload) + .map(drop) + .map_err(|_| BAD_ORIGIN)?; + } else { + // so what it means that we've failed to convert origin to the + // `frame_system::RawOrigin`? now it means that the custom pallet origin has + // been used to send the message. Do we need to verify it? The answer is no, + // because pallet may craft any origin (e.g. root) && we can't verify whether it + // is valid, or not. }; let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 947bfdc7f634c..ed5841d75107a 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -166,7 +166,7 @@ pub mod pallet { try_enact_authority_change::(&finality_target, set_id)?; >::mutate(|count| *count += 1); insert_header::(*finality_target, hash); - log::info!(target: "runtime::bridge-grandpa", "Succesfully imported finalized header with hash {:?}!", hash); + log::info!(target: "runtime::bridge-grandpa", "Successfully imported finalized header with hash {:?}!", hash); // mandatory header is a header that changes authorities set. The pallet can't go // further without importing this header. So every bridge MUST import mandatory headers. diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 75dcce8df0449..5bf36f6809cc0 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -198,7 +198,7 @@ impl SenderOrigin for Origin { fn linked_account(&self) -> Option { match self.caller { OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => - Some(submitter.clone()), + Some(*submitter), _ => None, } } diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index cfdc81acc315b..e4566b8895fa4 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -74,7 +74,7 @@ pub struct OutboundLane { } impl OutboundLane { - /// Create new inbound lane backed by given storage. + /// Create new outbound lane backed by given storage. pub fn new(storage: S) -> Self { OutboundLane { storage } } diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 9f8e9662ea0f0..ff841d70f9bb3 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -113,7 +113,7 @@ where // check if authority has already voted in the same round. // // there's a lot of code in `validate_commit` and `import_precommit` functions inside - // `finality-grandpa` crate (mostly related to reporing equivocations). But the only thing + // `finality-grandpa` crate (mostly related to reporting equivocations). But the only thing // that we care about is that only first vote from the authority is accepted if !votes.insert(signed.id.clone()) { continue @@ -121,11 +121,11 @@ where // everything below this line can't just `continue`, because state is already altered - // all precommits must be for block higher than the target + // precommits aren't allowed for block lower than the target if signed.precommit.target_number < justification.commit.target_number { return Err(Error::PrecommitIsNotCommitDescendant) } - // all precommits must be for target block descendents + // all precommits must be descendants of target block chain = chain .ensure_descendant(&justification.commit.target_hash, &signed.precommit.target_hash)?; // since we know now that the precommit target is the descendant of the justification @@ -193,8 +193,8 @@ impl AncestryChain
{ AncestryChain { parents, unvisited } } - /// Returns `Err(_)` if `precommit_target` is a descendant of the `commit_target` block and - /// `Ok(_)` otherwise. + /// Returns `Ok(_)` if `precommit_target` is a descendant of the `commit_target` block and + /// `Err(_)` otherwise. pub fn ensure_descendant( mut self, commit_target: &Header::Hash, @@ -213,7 +213,7 @@ impl AncestryChain
{ // `Some(parent_hash)` means that the `current_hash` is in the `parents` // container `is_visited_before` means that it has been visited before in // some of previous calls => since we assume that previous call has finished - // with `true`, this also will be finished with `true` + // with `true`, this also will be finished with `true` return Ok(self) } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index a4f204d238f7d..cef28ecb3679c 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -19,8 +19,6 @@ #![cfg_attr(not(feature = "std"), no_std)] // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -// Generated by `DecodeLimit::decode_with_depth_limit` -#![allow(clippy::unnecessary_mut_passed)] use bitvec::prelude::*; use bp_runtime::messages::DispatchFeePayment; @@ -42,7 +40,7 @@ pub use frame_support::weights::Weight; pub enum OperatingMode { /// Normal mode, when all operations are allowed. Normal, - /// The pallet is not accepting outbound messages. Inbound messages and receival proofs + /// The pallet is not accepting outbound messages. Inbound messages and receiving proofs /// are still accepted. /// /// This mode may be used e.g. when bridged chain expects upgrade. Then to avoid dispatch @@ -226,7 +224,7 @@ impl DeliveredMessages { /// dispatch result. pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { let mut dispatch_results = BitVec::with_capacity(1); - dispatch_results.push(if dispatch_result { true } else { false }); + dispatch_results.push(dispatch_result); DeliveredMessages { begin: nonce, end: nonce, dispatch_results } } diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 5a7fafe9f67c0..4f88e701fb1ba 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -154,7 +154,6 @@ pub trait Chain: Send + Sync + 'static { type Balance: AtLeast32BitUnsigned + FixedPointOperand + Parameter - + Parameter + Member + MaybeSerializeDeserialize + Clone diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs index 89470872cb2ee..a6897aaf0ab1e 100644 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -178,7 +178,7 @@ impl ReinitBridge { (current_number + 1, target_number), ) .await?; - let latest_andatory_header_number = headers_to_submit.last().map(|(h, _)| h.number()); + let latest_mandatory_header_number = headers_to_submit.last().map(|(h, _)| h.number()); log::info!( target: "bridge", "Missing {} mandatory {} headers at {}", @@ -281,13 +281,13 @@ impl ReinitBridge { ensure_pallet_operating_mode(&finality_target, is_last_batch).await?; } - if let Some(latest_andatory_header_number) = latest_andatory_header_number { + if let Some(latest_mandatory_header_number) = latest_mandatory_header_number { log::info!( target: "bridge", "Successfully updated best {} header at {} to {}. Pallet is now operational", Source::NAME, Target::NAME, - latest_andatory_header_number, + latest_mandatory_header_number, ); } diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index 469bc5589932b..c7e241626945d 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -280,7 +280,7 @@ where genesis_hash, signer: transaction_params.signer, era: TransactionEra::new(best_block_id, transaction_params.mortality), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce).into(), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), })? .encode(), )) diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 869a1d280282b..687d5163cb20d 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -192,7 +192,7 @@ where .inbound_lane_data(id) .await? .map(|data| data.relayers) - .unwrap_or_else(|| VecDeque::new()); + .unwrap_or_else(VecDeque::new); let unrewarded_relayers_state = bp_messages::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, messages_in_oldest_entry: relayers From 1752d85a5f655061cbfc5292d70d85635f4d0d96 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 28 Mar 2022 19:27:53 +0300 Subject: [PATCH 0672/1210] Update Substrate/Polkadot/Cumulus references (#1364) cumulus: b468d0c33eac0adda27080b59ea9b5986ce6469b polkadot: 827792ca833396c82c726eda0bc2ad32ecddba73 substrate: 666f39b8a22108f57732215de006518738034ba2 bump serde_json to 1.0.79 sync changes from https://github.com/paritytech/substrate/pull/11022 fixed clippy warnings Signed-off-by: acatangiu --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/command.rs | 2 +- bin/rialto-parachain/node/src/command.rs | 8 +++++--- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/node/src/command.rs | 2 +- .../bin-substrate/src/cli/relay_headers_and_messages.rs | 8 ++++---- relays/bin-substrate/src/cli/swap_tokens.rs | 4 ++-- relays/client-substrate/src/chain.rs | 1 + relays/utils/src/metrics.rs | 1 + relays/utils/src/relay_loop.rs | 1 + 10 files changed, 18 insertions(+), 13 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3825b92b703c2..9498b7311370d 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -12,7 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "3.1", features = ["derive"] } jsonrpc-core = "18.0" -serde_json = "1.0.59" +serde_json = "1.0.79" # Bridge dependencies diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 4dbf9575dfec7..3653428d1044f 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -135,7 +135,7 @@ pub fn run() -> sc_cli::Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; - Ok((cmd.run(client, backend), task_manager)) + Ok((cmd.run(client, backend, None), task_manager)) }) }, Some(Subcommand::Inspect(cmd)) => { diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index c47e742675da1..f93a939b9ecb6 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -202,9 +202,11 @@ pub fn run() -> Result<()> { }) }, Some(Subcommand::Revert(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, components.backend) - )) + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run( + components.client, + components.backend, + None + ))) }, Some(Subcommand::ExportGenesisState(params)) => { let mut builder = sc_cli::LoggerBuilder::new(""); diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index e44ceb45faa97..31699ffad0296 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -16,7 +16,7 @@ jsonrpc-core = "18.0" kvdb = "0.11" kvdb-rocksdb = "0.15" lru = "0.7" -serde_json = "1.0.59" +serde_json = "1.0.79" thiserror = "1.0" # Bridge dependencies diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index da92837f06c09..24e73f6fffc34 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -147,7 +147,7 @@ pub fn run() -> sc_cli::Result<()> { runner.async_run(|mut config| { let (client, backend, _, task_manager) = polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; - Ok((cmd.run(client, backend), task_manager)) + Ok((cmd.run(client, backend, None), task_manager)) }) }, Some(Subcommand::Inspect(cmd)) => { diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 4ff6ee0947cb2..d071d1f8910f2 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -330,9 +330,9 @@ impl RelayHeadersAndMessages { LeftToRightMessageLane, Left, >( - left_client.clone(), + left_client, TransactionParams { - signer: left_messages_pallet_owner.clone(), + signer: left_messages_pallet_owner, mortality: left_transactions_mortality, }, left_to_right_metrics @@ -366,9 +366,9 @@ impl RelayHeadersAndMessages { RightToLeftMessageLane, Right, >( - right_client.clone(), + right_client, TransactionParams { - signer: right_messages_pallet_owner.clone(), + signer: right_messages_pallet_owner, mortality: right_transactions_mortality, }, right_to_left_metrics diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs index 0758deddfd103..1467df3711c35 100644 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/relays/bin-substrate/src/cli/swap_tokens.rs @@ -221,7 +221,7 @@ impl SwapTokens { _, >( &source_client, - target_to_source_conversion_rate_override.clone(), + target_to_source_conversion_rate_override, ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, SOURCE_TO_TARGET_LANE_ID, bp_message_dispatch::MessagePayload { @@ -384,7 +384,7 @@ impl SwapTokens { _, >( &target_client, - source_to_target_conversion_rate_override.clone(), + source_to_target_conversion_rate_override, ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, TARGET_TO_SOURCE_LANE_ID, claim_swap_message.clone(), diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 60adfb0a88ac2..a55fa64d850ce 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -151,6 +151,7 @@ impl UnsignedTransaction { } /// Set transaction tip. + #[must_use] pub fn tip(mut self, tip: C::Balance) -> Self { self.tip = tip; self diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index 084f72e7950c5..b5225fca0e0c8 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -105,6 +105,7 @@ impl MetricsParams { } /// Do not expose metrics. + #[must_use] pub fn disable(mut self) -> Self { self.address = None; self diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 521a6345d3e39..3c1d2d4ae8287 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -85,6 +85,7 @@ pub struct LoopMetrics { impl Loop { /// Customize delay between reconnect attempts. + #[must_use] pub fn reconnect_delay(mut self, reconnect_delay: Duration) -> Self { self.reconnect_delay = reconnect_delay; self From 61333fd60e7d54fc8282e35157b379d419441c20 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 7 Apr 2022 19:02:23 +0300 Subject: [PATCH 0673/1210] pub use WeightInfo in Grandpa + Messsages pallets (#1370) --- modules/grandpa/src/lib.rs | 3 +-- modules/messages/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index ed5841d75107a..8ff8b34fb88cf 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -36,8 +36,6 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] -use crate::weights::WeightInfo; - use bp_header_chain::{justification::GrandpaJustification, InitializationData}; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; use finality_grandpa::voter_set::VoterSet; @@ -58,6 +56,7 @@ pub mod benchmarking; // Re-export in crate namespace for `construct_runtime!` pub use pallet::*; +pub use weights::WeightInfo; /// Block number of the bridged chain. pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a344cedae2411..10cdaae40712c 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -37,7 +37,8 @@ // Generated by `decl_event!` #![allow(clippy::unused_unit)] -pub use crate::weights_ext::{ +pub use weights::WeightInfo; +pub use weights_ext::{ ensure_able_to_receive_confirmation, ensure_able_to_receive_message, ensure_weights_are_correct, WeightInfoExt, EXPECTED_DEFAULT_MESSAGE_LENGTH, }; @@ -45,7 +46,6 @@ pub use crate::weights_ext::{ use crate::{ inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult}, outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult}, - weights::WeightInfo, }; use bp_messages::{ From ca6e1b15b2d12bd2a633278e9d036d4c6aa57c02 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Thu, 14 Apr 2022 14:02:16 +0800 Subject: [PATCH 0674/1210] add api data() for inbound_lane (#1373) --- modules/messages/src/inbound_lane.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 00875bb878a82..6560df2acd42d 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -71,6 +71,11 @@ impl InboundLane { InboundLane { storage } } + /// Get this lane data + pub fn data(&self) -> InboundLaneData { + self.storage.data() + } + /// Receive state of the corresponding outbound lane. pub fn receive_state_update( &mut self, From 390e3e72b5345c6083f39e8ceff3e81f7248345f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 14 Apr 2022 12:05:57 +0300 Subject: [PATCH 0675/1210] FinalityEngine in substrate relay (#1374) * introduce FinalityEngine in relay code * add FinalityEngine to relay * spelling * fix test compilation * Update relays/lib-substrate-relay/src/finality/source.rs Co-authored-by: Adrian Catangiu Co-authored-by: Adrian Catangiu --- .../src/chains/kusama_headers_to_polkadot.rs | 8 +- .../src/chains/millau_headers_to_rialto.rs | 8 +- .../src/chains/polkadot_headers_to_kusama.rs | 8 +- .../src/chains/rialto_headers_to_millau.rs | 8 +- .../src/chains/rococo_headers_to_wococo.rs | 8 +- .../src/chains/westend_headers_to_millau.rs | 8 +- .../src/chains/wococo_headers_to_rococo.rs | 8 +- relays/bin-substrate/src/cli/init_bridge.rs | 10 +- relays/bin-substrate/src/cli/reinit_bridge.rs | 12 +- relays/bin-substrate/src/cli/relay_headers.rs | 4 +- .../src/cli/relay_headers_and_messages.rs | 2 +- relays/client-substrate/src/client.rs | 4 +- relays/client-substrate/src/error.rs | 6 +- .../src/metrics/storage_proof_overhead.rs | 2 +- .../src/finality/engine.rs | 226 ++++++++++++++ .../guards.rs} | 0 .../src/finality/initialize.rs | 121 ++++++++ .../{finality_pipeline.rs => finality/mod.rs} | 39 ++- .../source.rs} | 25 +- .../target.rs} | 25 +- .../src/headers_initialize.rs | 282 ------------------ relays/lib-substrate-relay/src/lib.rs | 6 +- .../src/on_demand_headers.rs | 8 +- 23 files changed, 469 insertions(+), 359 deletions(-) create mode 100644 relays/lib-substrate-relay/src/finality/engine.rs rename relays/lib-substrate-relay/src/{finality_guards.rs => finality/guards.rs} (100%) create mode 100644 relays/lib-substrate-relay/src/finality/initialize.rs rename relays/lib-substrate-relay/src/{finality_pipeline.rs => finality/mod.rs} (85%) rename relays/lib-substrate-relay/src/{finality_source.rs => finality/source.rs} (87%) rename relays/lib-substrate-relay/src/{finality_target.rs => finality/target.rs} (81%) delete mode 100644 relays/lib-substrate-relay/src/headers_initialize.rs diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs index 0c0ba2272c7e9..97d2057209878 100644 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs @@ -18,7 +18,10 @@ use async_trait::async_trait; use relay_polkadot_client::Polkadot; -use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, +}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -47,6 +50,7 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { type SourceChain = relay_kusama_client::Kusama; type TargetChain = Polkadot; + type FinalityEngine = GrandpaFinalityEngine; type SubmitFinalityProofCallBuilder = KusamaFinalityToPolkadotCallBuilder; type TransactionSignScheme = Polkadot; @@ -55,7 +59,7 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { transaction_params: &TransactionParams, enable_version_guard: bool, ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality_guards::start::( + substrate_relay_helper::finality::guards::start::( target_client, transaction_params, enable_version_guard, diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 584f0a9bb1d8b..2fefc2e74c968 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -16,8 +16,9 @@ //! Millau-to-Rialto headers sync entrypoint. -use substrate_relay_helper::finality_pipeline::{ - DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, +use substrate_relay_helper::finality::{ + engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, + SubstrateFinalitySyncPipeline, }; /// Description of Millau -> Rialto finalized headers bridge. @@ -28,7 +29,8 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { type SourceChain = relay_millau_client::Millau; type TargetChain = relay_rialto_client::Rialto; - type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< Self, rialto_runtime::Runtime, rialto_runtime::MillauGrandpaInstance, diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs index 6d118b07caa5b..a8b6ce07ab6c9 100644 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs @@ -18,7 +18,10 @@ use async_trait::async_trait; use relay_kusama_client::Kusama; -use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, +}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -47,6 +50,7 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { type SourceChain = relay_polkadot_client::Polkadot; type TargetChain = Kusama; + type FinalityEngine = GrandpaFinalityEngine; type SubmitFinalityProofCallBuilder = PolkadotFinalityToKusamaCallBuilder; type TransactionSignScheme = Kusama; @@ -55,7 +59,7 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { transaction_params: &TransactionParams, enable_version_guard: bool, ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality_guards::start::( + substrate_relay_helper::finality::guards::start::( target_client, transaction_params, enable_version_guard, diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index a433f3562a703..a890405703e6a 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -16,8 +16,9 @@ //! Rialto-to-Millau headers sync entrypoint. -use substrate_relay_helper::finality_pipeline::{ - DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, +use substrate_relay_helper::finality::{ + engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, + SubstrateFinalitySyncPipeline, }; /// Description of Millau -> Rialto finalized headers bridge. @@ -28,7 +29,8 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { type SourceChain = relay_rialto_client::Rialto; type TargetChain = relay_millau_client::Millau; - type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< Self, millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs index bb66a7422d370..5e2b523000cf4 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs @@ -20,7 +20,10 @@ use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; use async_trait::async_trait; use relay_wococo_client::Wococo; -use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, +}; /// Description of Rococo -> Wococo finalized headers bridge. #[derive(Clone, Debug)] @@ -37,6 +40,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { type SourceChain = relay_rococo_client::Rococo; type TargetChain = Wococo; + type FinalityEngine = GrandpaFinalityEngine; type SubmitFinalityProofCallBuilder = RococoFinalityToWococoCallBuilder; type TransactionSignScheme = Wococo; @@ -45,7 +49,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { transaction_params: &TransactionParams, enable_version_guard: bool, ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality_guards::start::( + substrate_relay_helper::finality::guards::start::( target_client, transaction_params, enable_version_guard, diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 2ec20a027ff5f..3ed67dd260a6b 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -16,8 +16,9 @@ //! Westend-to-Millau headers sync entrypoint. -use substrate_relay_helper::finality_pipeline::{ - DirectSubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, +use substrate_relay_helper::finality::{ + engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, + SubstrateFinalitySyncPipeline, }; /// Description of Westend -> Millau finalized headers bridge. @@ -28,7 +29,8 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type SourceChain = relay_westend_client::Westend; type TargetChain = relay_millau_client::Millau; - type SubmitFinalityProofCallBuilder = DirectSubmitFinalityProofCallBuilder< + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< Self, millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs index a7bff5951882e..58413a9d0d561 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs @@ -18,7 +18,10 @@ use async_trait::async_trait; use relay_rococo_client::Rococo; -use substrate_relay_helper::{finality_pipeline::SubstrateFinalitySyncPipeline, TransactionParams}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, +}; /// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat /// relay as gone wild. @@ -42,6 +45,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { type SourceChain = relay_wococo_client::Wococo; type TargetChain = Rococo; + type FinalityEngine = GrandpaFinalityEngine; type SubmitFinalityProofCallBuilder = WococoFinalityToRococoCallBuilder; type TransactionSignScheme = Rococo; @@ -50,7 +54,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { transaction_params: &TransactionParams, enable_version_guard: bool, ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality_guards::start::( + substrate_relay_helper::finality::guards::start::( target_client, transaction_params, enable_version_guard, diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index a0129ce9baa46..add80c58538dd 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTr use sp_core::{Bytes, Pair}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::finality::engine::Grandpa as GrandpaFinalityEngine; /// Initialize bridge pallet. #[derive(StructOpt)] @@ -56,6 +57,7 @@ macro_rules! select_bridge { InitBridgeName::MillauToRialto => { type Source = relay_millau_client::Millau; type Target = relay_rialto_client::Rialto; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -74,6 +76,7 @@ macro_rules! select_bridge { InitBridgeName::RialtoToMillau => { type Source = relay_rialto_client::Rialto; type Target = relay_millau_client::Millau; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -92,6 +95,7 @@ macro_rules! select_bridge { InitBridgeName::WestendToMillau => { type Source = relay_westend_client::Westend; type Target = relay_millau_client::Millau; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -114,6 +118,7 @@ macro_rules! select_bridge { InitBridgeName::RococoToWococo => { type Source = relay_rococo_client::Rococo; type Target = relay_wococo_client::Wococo; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -130,6 +135,7 @@ macro_rules! select_bridge { InitBridgeName::WococoToRococo => { type Source = relay_wococo_client::Wococo; type Target = relay_rococo_client::Rococo; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -146,6 +152,7 @@ macro_rules! select_bridge { InitBridgeName::KusamaToPolkadot => { type Source = relay_kusama_client::Kusama; type Target = relay_polkadot_client::Polkadot; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -162,6 +169,7 @@ macro_rules! select_bridge { InitBridgeName::PolkadotToKusama => { type Source = relay_polkadot_client::Polkadot; type Target = relay_kusama_client::Kusama; + type Engine = GrandpaFinalityEngine; fn encode_init_bridge( init_data: InitializationData<::Header>, @@ -189,7 +197,7 @@ impl InitBridge { let (spec_version, transaction_version) = target_client.simple_runtime_version().await?; - substrate_relay_helper::headers_initialize::initialize( + substrate_relay_helper::finality::initialize::initialize::( source_client, target_client.clone(), target_sign.public().into(), diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs index a6897aaf0ab1e..dc902055d20bd 100644 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -24,7 +24,6 @@ use crate::{ TargetConnectionParams, TargetSigningParams, }, }; -use bp_header_chain::justification::GrandpaJustification; use bp_runtime::Chain; use codec::Encode; use finality_relay::{SourceClient, SourceHeader}; @@ -40,8 +39,12 @@ use std::convert::{TryFrom, TryInto}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ - finality_pipeline::SubstrateFinalitySyncPipeline, finality_source::SubstrateFinalitySource, - finality_target::SubstrateFinalityTarget, messages_source::read_client_state, + finality::{ + source::{SubstrateFinalityProof, SubstrateFinalitySource}, + target::SubstrateFinalityTarget, + SubstrateFinalitySyncPipeline, + }, + messages_source::read_client_state, TransactionParams, }; @@ -299,7 +302,7 @@ impl ReinitBridge { /// Mandatory header and its finality proof. type HeaderAndProof

= ( SyncHeader::SourceChain>>, - GrandpaJustification::SourceChain>>, + SubstrateFinalityProof

, ); /// Vector of mandatory headers and their finality proofs. type HeadersAndProofs

= Vec>; @@ -425,6 +428,7 @@ fn make_mandatory_headers_batches< mod tests { use super::*; use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; + use bp_header_chain::justification::GrandpaJustification; use bp_test_utils::{make_default_justification, test_header}; use relay_polkadot_client::Polkadot; use sp_runtime::{traits::Header as _, DigestItem}; diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 45034aba4b5e8..3a353ed4ab03c 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -18,7 +18,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; -use substrate_relay_helper::finality_pipeline::SubstrateFinalitySyncPipeline; +use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; use crate::cli::{ PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, @@ -136,7 +136,7 @@ impl RelayHeaders { ) .await?; - substrate_relay_helper::finality_pipeline::run::( + substrate_relay_helper::finality::run::( source_client, target_client, self.only_mandatory_headers, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index d071d1f8910f2..537ae1e101864 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -35,7 +35,7 @@ use relay_substrate_client::{ use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ - finality_pipeline::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, + finality::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, on_demand_headers::OnDemandHeadersRelay, TransactionParams, }; diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 1e48bc3339668..a0426b99f95ae 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -704,8 +704,8 @@ impl Client { .await } - /// Return new justifications stream. - pub async fn subscribe_justifications(&self) -> Result> { + /// Return new GRANDPA justifications stream. + pub async fn subscribe_grandpa_justifications(&self) -> Result> { let subscription = self .jsonrpsee_execute(move |client| async move { Ok(client diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index e698f2596c5fa..797af5cc5d225 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -45,9 +45,9 @@ pub enum Error { /// Account does not exist on the chain. #[error("Account does not exist on the chain.")] AccountDoesNotExist, - /// Runtime storage is missing mandatory ":code:" entry. - #[error("Mandatory :code: entry is missing from runtime storage.")] - MissingMandatoryCodeEntry, + /// Runtime storage is missing some mandatory value. + #[error("Mandatory storage value is missing from the runtime storage.")] + MissingMandatoryStorageValue, /// The client we're connected to is not synced, so we can't rely on its state. #[error("Substrate client is not synced {0}.")] ClientNotSynced(Health), diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs index f1c770ed228e7..42793fe7c5468 100644 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -72,7 +72,7 @@ impl StorageProofOverheadMetric { let maybe_encoded_storage_value = storage_value_reader.read_value(CODE).map_err(Error::StorageProofError)?; let encoded_storage_value_size = - maybe_encoded_storage_value.ok_or(Error::MissingMandatoryCodeEntry)?.len(); + maybe_encoded_storage_value.ok_or(Error::MissingMandatoryStorageValue)?.len(); Ok(storage_proof_size - encoded_storage_value_size) } diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs new file mode 100644 index 0000000000000..0b20a3222d232 --- /dev/null +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -0,0 +1,226 @@ +// 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 . + +//! Support of different finality engines, available in Substrate. + +use crate::error::Error; +use async_trait::async_trait; +use bp_header_chain::{ + find_grandpa_authorities_scheduled_change, + justification::{verify_justification, GrandpaJustification}, + FinalityProof, +}; +use codec::{Decode, Encode}; +use finality_grandpa::voter_set::VoterSet; +use num_traits::{One, Zero}; +use relay_substrate_client::{ + BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, HeaderOf, + Subscription, +}; +use sp_core::{storage::StorageKey, Bytes}; +use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; +use sp_runtime::{traits::Header, ConsensusEngineId}; +use std::marker::PhantomData; + +/// Finality enfine, used by the Substrate chain. +#[async_trait] +pub trait Engine { + /// Unique consensus engine identifier. + const ID: ConsensusEngineId; + /// Type of finality proofs, used by consensus engine. + type FinalityProof: FinalityProof> + Decode + Encode; + /// Type of bridge pallet initialization data. + type InitializationData: std::fmt::Debug + Send + Sync + 'static; + + /// Returns storage key at the bridged (target) chain that corresponds to the `bool` value, + /// which is true when the bridge pallet is halted. + fn is_halted_key() -> StorageKey; + /// Returns storage at the bridged (target) chain that corresponds to some value that is + /// missing from the storage until bridge pallet is initialized. + /// + /// Note that we don't care about type of the value - just if it present or not. + fn is_initialized_key() -> StorageKey; + /// A method to subscribe to encoded finality proofs, given source client. + async fn finality_proofs(client: Client) -> Result, SubstrateError>; + /// Prepare initialization data for the finality bridge pallet. + async fn prepare_initialization_data( + client: Client, + ) -> Result, BlockNumberOf>>; +} + +/// GRANDPA finality engine. +pub struct Grandpa(PhantomData); + +impl Grandpa { + /// Read header by hash from the source client. + async fn source_header( + source_client: &Client, + header_hash: C::Hash, + ) -> Result, BlockNumberOf>> { + source_client + .header_by_hash(header_hash) + .await + .map_err(|err| Error::RetrieveHeader(C::NAME, header_hash, err)) + } + + /// Read GRANDPA authorities set at given header. + async fn source_authorities_set( + source_client: &Client, + header_hash: C::Hash, + ) -> Result, BlockNumberOf>> { + let raw_authorities_set = source_client + .grandpa_authorities_set(header_hash) + .await + .map_err(|err| Error::RetrieveAuthorities(C::NAME, header_hash, err))?; + GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..]) + .map_err(|err| Error::DecodeAuthorities(C::NAME, header_hash, err)) + } +} + +#[async_trait] +impl Engine for Grandpa { + const ID: ConsensusEngineId = sp_finality_grandpa::GRANDPA_ENGINE_ID; + type FinalityProof = GrandpaJustification>; + type InitializationData = bp_header_chain::InitializationData; + + fn is_halted_key() -> StorageKey { + bp_header_chain::storage_keys::is_halted_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + } + + fn is_initialized_key() -> StorageKey { + bp_header_chain::storage_keys::best_finalized_hash_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + } + + async fn finality_proofs(client: Client) -> Result, SubstrateError> { + client.subscribe_grandpa_justifications().await + } + + /// Prepare initialization data for the GRANDPA verifier pallet. + async fn prepare_initialization_data( + source_client: Client, + ) -> Result, BlockNumberOf>> { + // In ideal world we just need to get best finalized header and then to read GRANDPA + // authorities set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at + // this header. + // + // But now there are problems with this approach - `CurrentSetId` may return invalid value. + // So here we're waiting for the next justification, read the authorities set and then try + // to figure out the set id with bruteforce. + let justifications = source_client + .subscribe_grandpa_justifications() + .await + .map_err(|err| Error::Subscribe(C::NAME, err))?; + // Read next justification - the header that it finalizes will be used as initial header. + let justification = justifications + .next() + .await + .map_err(|e| Error::ReadJustification(C::NAME, e)) + .and_then(|justification| { + justification.ok_or(Error::ReadJustificationStreamEnded(C::NAME)) + })?; + + // Read initial header. + let justification: GrandpaJustification = + Decode::decode(&mut &justification.0[..]) + .map_err(|err| Error::DecodeJustification(C::NAME, err))?; + + let (initial_header_hash, initial_header_number) = + (justification.commit.target_hash, justification.commit.target_number); + + let initial_header = Self::source_header(&source_client, initial_header_hash).await?; + log::trace!(target: "bridge", "Selected {} initial header: {}/{}", + C::NAME, + initial_header_number, + initial_header_hash, + ); + + // Read GRANDPA authorities set at initial header. + let initial_authorities_set = + Self::source_authorities_set(&source_client, initial_header_hash).await?; + log::trace!(target: "bridge", "Selected {} initial authorities set: {:?}", + C::NAME, + initial_authorities_set, + ); + + // If initial header changes the GRANDPA authorities set, then we need previous authorities + // to verify justification. + let mut authorities_for_verification = initial_authorities_set.clone(); + let scheduled_change = find_grandpa_authorities_scheduled_change(&initial_header); + assert!( + scheduled_change.as_ref().map(|c| c.delay.is_zero()).unwrap_or(true), + "GRANDPA authorities change at {} scheduled to happen in {:?} blocks. We expect\ + regular hange to have zero delay", + initial_header_hash, + scheduled_change.as_ref().map(|c| c.delay), + ); + let schedules_change = scheduled_change.is_some(); + if schedules_change { + authorities_for_verification = + Self::source_authorities_set(&source_client, *initial_header.parent_hash()).await?; + log::trace!( + target: "bridge", + "Selected {} header is scheduling GRANDPA authorities set changes. Using previous set: {:?}", + C::NAME, + authorities_for_verification, + ); + } + + // Now let's try to guess authorities set id by verifying justification. + let mut initial_authorities_set_id = 0; + let mut min_possible_block_number = C::BlockNumber::zero(); + let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()) + .ok_or(Error::ReadInvalidAuthorities(C::NAME, authorities_for_verification))?; + loop { + log::trace!( + target: "bridge", "Trying {} GRANDPA authorities set id: {}", + C::NAME, + initial_authorities_set_id, + ); + + let is_valid_set_id = verify_justification::( + (initial_header_hash, initial_header_number), + initial_authorities_set_id, + &authorities_for_verification, + &justification, + ) + .is_ok(); + + if is_valid_set_id { + break + } + + initial_authorities_set_id += 1; + min_possible_block_number += One::one(); + if min_possible_block_number > initial_header_number { + // there can't be more authorities set changes than headers => if we have reached + // `initial_block_number` and still have not found correct value of + // `initial_authorities_set_id`, then something else is broken => fail + return Err(Error::GuessInitialAuthorities(C::NAME, initial_header_number)) + } + } + + Ok(bp_header_chain::InitializationData { + header: Box::new(initial_header), + authority_list: initial_authorities_set, + set_id: if schedules_change { + initial_authorities_set_id + 1 + } else { + initial_authorities_set_id + }, + is_halted: false, + }) + } +} diff --git a/relays/lib-substrate-relay/src/finality_guards.rs b/relays/lib-substrate-relay/src/finality/guards.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality_guards.rs rename to relays/lib-substrate-relay/src/finality/guards.rs diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs new file mode 100644 index 0000000000000..58a0fc499fb02 --- /dev/null +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -0,0 +1,121 @@ +// 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 . + +//! Initialize Substrate -> Substrate finality bridge. +//! +//! Initialization is a transaction that calls `initialize()` function of the +//! finality pallet (GRANDPA/BEEFY/...). This transaction brings initial header +//! and authorities set from source to target chain. The finality sync starts +//! with this header. + +use crate::{error::Error, finality::engine::Engine}; + +use relay_substrate_client::{BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; +use sp_core::Bytes; +use sp_runtime::traits::Header as HeaderT; + +/// Submit headers-bridge initialization transaction. +pub async fn initialize, SourceChain: Chain, TargetChain: Chain, F>( + source_client: Client, + target_client: Client, + target_transactions_signer: TargetChain::AccountId, + prepare_initialize_transaction: F, +) where + F: FnOnce(TargetChain::Index, E::InitializationData) -> Result + + Send + + 'static, +{ + let result = do_initialize::( + source_client, + target_client, + target_transactions_signer, + prepare_initialize_transaction, + ) + .await; + + match result { + Ok(Some(tx_hash)) => log::info!( + target: "bridge", + "Successfully submitted {}-headers bridge initialization transaction to {}: {:?}", + SourceChain::NAME, + TargetChain::NAME, + tx_hash, + ), + Ok(None) => (), + Err(err) => log::error!( + target: "bridge", + "Failed to submit {}-headers bridge initialization transaction to {}: {:?}", + SourceChain::NAME, + TargetChain::NAME, + err, + ), + } +} + +/// Craft and submit initialization transaction, returning any error that may occur. +async fn do_initialize, SourceChain: Chain, TargetChain: Chain, F>( + source_client: Client, + target_client: Client, + target_transactions_signer: TargetChain::AccountId, + prepare_initialize_transaction: F, +) -> Result< + Option, + Error::Number>, +> +where + F: FnOnce(TargetChain::Index, E::InitializationData) -> Result + + Send + + 'static, +{ + let is_initialized = is_initialized::(&target_client).await?; + if is_initialized { + log::info!( + target: "bridge", + "{}-headers bridge at {} is already initialized. Skipping", + SourceChain::NAME, + TargetChain::NAME, + ); + return Ok(None) + } + + let initialization_data = E::prepare_initialization_data(source_client).await?; + log::info!( + target: "bridge", + "Prepared initialization data for {}-headers bridge at {}: {:?}", + SourceChain::NAME, + TargetChain::NAME, + initialization_data, + ); + + let initialization_tx_hash = target_client + .submit_signed_extrinsic(target_transactions_signer, move |_, transaction_nonce| { + prepare_initialize_transaction(transaction_nonce, initialization_data) + }) + .await + .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; + Ok(Some(initialization_tx_hash)) +} + +/// Returns `Ok(true)` if bridge has already been initialized. +async fn is_initialized, SourceChain: Chain, TargetChain: Chain>( + target_client: &Client, +) -> Result, BlockNumberOf>> { + Ok(target_client + .raw_storage_value(E::is_initialized_key(), None) + .await + .map_err(|err| Error::RetrieveBestFinalizedHeaderHash(SourceChain::NAME, err))? + .is_some()) +} diff --git a/relays/lib-substrate-relay/src/finality_pipeline.rs b/relays/lib-substrate-relay/src/finality/mod.rs similarity index 85% rename from relays/lib-substrate-relay/src/finality_pipeline.rs rename to relays/lib-substrate-relay/src/finality/mod.rs index 3daf8d11440eb..736937ba0724d 100644 --- a/relays/lib-substrate-relay/src/finality_pipeline.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -18,7 +18,11 @@ //! finality proofs synchronization pipelines. use crate::{ - finality_source::SubstrateFinalitySource, finality_target::SubstrateFinalityTarget, + finality::{ + engine::Engine, + source::{SubstrateFinalityProof, SubstrateFinalitySource}, + target::SubstrateFinalityTarget, + }, TransactionParams, }; @@ -27,13 +31,19 @@ use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, - ChainWithGrandpa, Client, HashOf, HeaderOf, SyncHeader, TransactionSignScheme, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, + HashOf, HeaderOf, SyncHeader, TransactionSignScheme, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; use std::{fmt::Debug, marker::PhantomData}; +pub mod engine; +pub mod guards; +pub mod initialize; +pub mod source; +pub mod target; + /// Default limit of recent finality proofs. /// /// Finality delay of 4096 blocks is unlikely to happen in practice in @@ -44,10 +54,12 @@ pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; #[async_trait] pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. - type SourceChain: ChainWithGrandpa; + type SourceChain: Chain; /// Headers of the `SourceChain` are submitted to this chain. type TargetChain: Chain; + /// Finality engine. + type FinalityEngine: Engine; /// How submit finality proof call is built? type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder; /// Scheme used to sign target chain transactions. @@ -76,7 +88,7 @@ impl FinalitySyncPipeline for FinalitySyncPipe type Hash = HashOf; type Number = BlockNumberOf; type Header = relay_substrate_client::SyncHeader>; - type FinalityProof = GrandpaJustification>; + type FinalityProof = SubstrateFinalityProof

; } /// Different ways of building `submit_finality_proof` calls. @@ -85,23 +97,26 @@ pub trait SubmitFinalityProofCallBuilder { /// function of bridge GRANDPA module at the target chain. fn build_submit_finality_proof_call( header: SyncHeader>, - proof: GrandpaJustification>, + proof: SubstrateFinalityProof

, ) -> CallOf; } /// Building `submit_finality_proof` call when you have direct access to the target /// chain runtime. -pub struct DirectSubmitFinalityProofCallBuilder { +pub struct DirectSubmitGrandpaFinalityProofCallBuilder { _phantom: PhantomData<(P, R, I)>, } -impl SubmitFinalityProofCallBuilder

for DirectSubmitFinalityProofCallBuilder +impl SubmitFinalityProofCallBuilder

+ for DirectSubmitGrandpaFinalityProofCallBuilder where P: SubstrateFinalitySyncPipeline, R: BridgeGrandpaConfig, I: 'static, R::BridgedChain: bp_runtime::Chain

>, CallOf: From>, + P::FinalityEngine: + Engine>>, { fn build_submit_finality_proof_call( header: SyncHeader>, @@ -125,22 +140,22 @@ macro_rules! generate_mocked_submit_finality_proof_call_builder { ($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => { pub struct $mocked_builder; - impl $crate::finality_pipeline::SubmitFinalityProofCallBuilder<$pipeline> + impl $crate::finality::SubmitFinalityProofCallBuilder<$pipeline> for $mocked_builder { fn build_submit_finality_proof_call( header: relay_substrate_client::SyncHeader< relay_substrate_client::HeaderOf< - <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain + <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::SourceChain > >, proof: bp_header_chain::justification::GrandpaJustification< relay_substrate_client::HeaderOf< - <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::SourceChain + <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::SourceChain > >, ) -> relay_substrate_client::CallOf< - <$pipeline as $crate::finality_pipeline::SubstrateFinalitySyncPipeline>::TargetChain + <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::TargetChain > { $bridge_grandpa($submit_finality_proof(Box::new(header.into_inner()), proof)) } diff --git a/relays/lib-substrate-relay/src/finality_source.rs b/relays/lib-substrate-relay/src/finality/source.rs similarity index 87% rename from relays/lib-substrate-relay/src/finality_source.rs rename to relays/lib-substrate-relay/src/finality/source.rs index 804d3212930d4..d0acb7717682f 100644 --- a/relays/lib-substrate-relay/src/finality_source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -16,11 +16,10 @@ //! Default generic implementation of finality source for basic Substrate client. -use crate::finality_pipeline::{FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}; +use crate::finality::{engine::Engine, FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; -use bp_header_chain::justification::GrandpaJustification; use codec::Decode; use finality_relay::SourceClient; use futures::stream::{unfold, Stream, StreamExt}; @@ -38,13 +37,19 @@ pub type RequiredHeaderNumberRef = Arc::BlockN pub type SubstrateFinalityProofsStream

= Pin< Box< dyn Stream< - Item = GrandpaJustification< - HeaderOf<

::SourceChain>, - >, + Item = <

::FinalityEngine as Engine< +

::SourceChain, + >>::FinalityProof, > + Send, >, >; +/// Substrate finality proof. Specific to the used `FinalityEngine`. +pub type SubstrateFinalityProof

= + <

::FinalityEngine as Engine< +

::SourceChain, + >>::FinalityProof; + /// Substrate node as finality source. pub struct SubstrateFinalitySource { client: Client, @@ -120,7 +125,7 @@ impl SourceClient Result< ( relay_substrate_client::SyncHeader>, - Option>>, + Option>, ), Error, > { @@ -130,9 +135,7 @@ impl SourceClient>::decode( - &mut raw_justification.as_slice(), - ) + SubstrateFinalityProof::

::decode(&mut raw_justification.as_slice()) }) .transpose() .map_err(Error::ResponseParseFailed)?; @@ -142,7 +145,7 @@ impl SourceClient Result { Ok(unfold( - self.client.clone().subscribe_justifications().await?, + P::FinalityEngine::finality_proofs(self.client.clone()).await?, move |subscription| async move { loop { let log_error = |err| { @@ -161,7 +164,7 @@ impl SourceClient>::decode( + >::FinalityProof::decode( &mut &next_justification[..], ); diff --git a/relays/lib-substrate-relay/src/finality_target.rs b/relays/lib-substrate-relay/src/finality/target.rs similarity index 81% rename from relays/lib-substrate-relay/src/finality_target.rs rename to relays/lib-substrate-relay/src/finality/target.rs index 4c5814171049a..6ca6be631aab8 100644 --- a/relays/lib-substrate-relay/src/finality_target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -14,24 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Substrate client as Substrate finality proof target. The chain we connect to should have -//! bridge GRANDPA pallet deployed and provide `FinalityApi` to allow bridging -//! with chain. +//! Substrate client as Substrate finality proof target. use crate::{ - finality_pipeline::{ - FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, + finality::{ + engine::Engine, source::SubstrateFinalityProof, FinalitySyncPipelineAdapter, + SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }, TransactionParams, }; use async_trait::async_trait; -use bp_header_chain::{justification::GrandpaJustification, storage_keys::is_halted_key}; use codec::Encode; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithGrandpa, Client, Error, HeaderIdOf, HeaderOf, - SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, + SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::{Bytes, Pair}; @@ -51,12 +49,9 @@ impl SubstrateFinalityTarget

{ SubstrateFinalityTarget { client, transaction_params } } - /// Ensure that the GRANDPA pallet at target chain is active. + /// Ensure that the bridge pallet at target chain is active. pub async fn ensure_pallet_active(&self) -> Result<(), Error> { - let is_halted = self - .client - .storage_value(is_halted_key(P::SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME), None) - .await?; + let is_halted = self.client.storage_value(P::FinalityEngine::is_halted_key(), None).await?; if is_halted.unwrap_or(false) { Err(Error::BridgePalletIsHalted) } else { @@ -94,7 +89,7 @@ where // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay self.client.ensure_synced().await?; - // we can't relay finality if GRANDPA pallet at target chain is halted + // we can't relay finality if bridge pallet at target chain is halted self.ensure_pallet_active().await?; Ok(crate::messages_source::read_client_state::( @@ -109,7 +104,7 @@ where async fn submit_finality_proof( &self, header: SyncHeader>, - proof: GrandpaJustification>, + proof: SubstrateFinalityProof

, ) -> Result<(), Error> { let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); diff --git a/relays/lib-substrate-relay/src/headers_initialize.rs b/relays/lib-substrate-relay/src/headers_initialize.rs deleted file mode 100644 index 0e1371c53c815..0000000000000 --- a/relays/lib-substrate-relay/src/headers_initialize.rs +++ /dev/null @@ -1,282 +0,0 @@ -// 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 . - -//! Initialize Substrate -> Substrate headers bridge. -//! -//! Initialization is a transaction that calls `initialize()` function of the -//! `pallet-bridge-grandpa` pallet. This transaction brings initial header -//! and authorities set from source to target chain. The headers sync starts -//! with this header. - -use crate::error::Error; - -use bp_header_chain::{ - find_grandpa_authorities_scheduled_change, - justification::{verify_justification, GrandpaJustification}, - InitializationData, -}; -use codec::Decode; -use finality_grandpa::voter_set::VoterSet; -use num_traits::{One, Zero}; -use relay_substrate_client::{ - BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, -}; -use sp_core::Bytes; -use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; -use sp_runtime::traits::Header as HeaderT; - -/// Submit headers-bridge initialization transaction. -pub async fn initialize( - source_client: Client, - target_client: Client, - target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce( - TargetChain::Index, - InitializationData, - ) -> Result - + Send - + 'static, -) { - let result = do_initialize( - source_client, - target_client, - target_transactions_signer, - prepare_initialize_transaction, - ) - .await; - - match result { - Ok(Some(tx_hash)) => log::info!( - target: "bridge", - "Successfully submitted {}-headers bridge initialization transaction to {}: {:?}", - SourceChain::NAME, - TargetChain::NAME, - tx_hash, - ), - Ok(None) => (), - Err(err) => log::error!( - target: "bridge", - "Failed to submit {}-headers bridge initialization transaction to {}: {:?}", - SourceChain::NAME, - TargetChain::NAME, - err, - ), - } -} - -/// Craft and submit initialization transaction, returning any error that may occur. -async fn do_initialize( - source_client: Client, - target_client: Client, - target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce( - TargetChain::Index, - InitializationData, - ) -> Result - + Send - + 'static, -) -> Result< - Option, - Error::Number>, -> { - let is_initialized = is_initialized::(&target_client).await?; - if is_initialized { - log::info!( - target: "bridge", - "{}-headers bridge at {} is already initialized. Skipping", - SourceChain::NAME, - TargetChain::NAME, - ); - return Ok(None) - } - - let initialization_data = prepare_initialization_data(source_client).await?; - log::info!( - target: "bridge", - "Prepared initialization data for {}-headers bridge at {}: {:?}", - SourceChain::NAME, - TargetChain::NAME, - initialization_data, - ); - - let initialization_tx_hash = target_client - .submit_signed_extrinsic(target_transactions_signer, move |_, transaction_nonce| { - prepare_initialize_transaction(transaction_nonce, initialization_data) - }) - .await - .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; - Ok(Some(initialization_tx_hash)) -} - -/// Returns `Ok(true)` if bridge has already been initialized. -async fn is_initialized( - target_client: &Client, -) -> Result, BlockNumberOf>> { - Ok(target_client - .raw_storage_value( - bp_header_chain::storage_keys::best_finalized_hash_key( - SourceChain::WITH_CHAIN_GRANDPA_PALLET_NAME, - ), - None, - ) - .await - .map_err(|err| Error::RetrieveBestFinalizedHeaderHash(SourceChain::NAME, err))? - .is_some()) -} - -/// Prepare initialization data for the GRANDPA verifier pallet. -async fn prepare_initialization_data( - source_client: Client, -) -> Result< - InitializationData, - Error::Number>, -> { - // In ideal world we just need to get best finalized header and then to read GRANDPA authorities - // set (`pallet_grandpa::CurrentSetId` + `GrandpaApi::grandpa_authorities()`) at this header. - // - // But now there are problems with this approach - `CurrentSetId` may return invalid value. So - // here we're waiting for the next justification, read the authorities set and then try to - // figure out the set id with bruteforce. - let justifications = source_client - .subscribe_justifications() - .await - .map_err(|err| Error::Subscribe(SourceChain::NAME, err))?; - // Read next justification - the header that it finalizes will be used as initial header. - let justification = justifications - .next() - .await - .map_err(|e| Error::ReadJustification(SourceChain::NAME, e)) - .and_then(|justification| { - justification.ok_or(Error::ReadJustificationStreamEnded(SourceChain::NAME)) - })?; - - // Read initial header. - let justification: GrandpaJustification = - Decode::decode(&mut &justification.0[..]) - .map_err(|err| Error::DecodeJustification(SourceChain::NAME, err))?; - - let (initial_header_hash, initial_header_number) = - (justification.commit.target_hash, justification.commit.target_number); - - let initial_header = source_header(&source_client, initial_header_hash).await?; - log::trace!(target: "bridge", "Selected {} initial header: {}/{}", - SourceChain::NAME, - initial_header_number, - initial_header_hash, - ); - - // Read GRANDPA authorities set at initial header. - let initial_authorities_set = - source_authorities_set(&source_client, initial_header_hash).await?; - log::trace!(target: "bridge", "Selected {} initial authorities set: {:?}", - SourceChain::NAME, - initial_authorities_set, - ); - - // If initial header changes the GRANDPA authorities set, then we need previous authorities - // to verify justification. - let mut authorities_for_verification = initial_authorities_set.clone(); - let scheduled_change = find_grandpa_authorities_scheduled_change(&initial_header); - assert!( - scheduled_change.as_ref().map(|c| c.delay.is_zero()).unwrap_or(true), - "GRANDPA authorities change at {} scheduled to happen in {:?} blocks. We expect\ - regular hange to have zero delay", - initial_header_hash, - scheduled_change.as_ref().map(|c| c.delay), - ); - let schedules_change = scheduled_change.is_some(); - if schedules_change { - authorities_for_verification = - source_authorities_set(&source_client, *initial_header.parent_hash()).await?; - log::trace!( - target: "bridge", - "Selected {} header is scheduling GRANDPA authorities set changes. Using previous set: {:?}", - SourceChain::NAME, - authorities_for_verification, - ); - } - - // Now let's try to guess authorities set id by verifying justification. - let mut initial_authorities_set_id = 0; - let mut min_possible_block_number = SourceChain::BlockNumber::zero(); - let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()) - .ok_or(Error::ReadInvalidAuthorities(SourceChain::NAME, authorities_for_verification))?; - loop { - log::trace!( - target: "bridge", "Trying {} GRANDPA authorities set id: {}", - SourceChain::NAME, - initial_authorities_set_id, - ); - - let is_valid_set_id = verify_justification::( - (initial_header_hash, initial_header_number), - initial_authorities_set_id, - &authorities_for_verification, - &justification, - ) - .is_ok(); - - if is_valid_set_id { - break - } - - initial_authorities_set_id += 1; - min_possible_block_number += One::one(); - if min_possible_block_number > initial_header_number { - // there can't be more authorities set changes than headers => if we have reached - // `initial_block_number` and still have not found correct value of - // `initial_authorities_set_id`, then something else is broken => fail - return Err(Error::GuessInitialAuthorities(SourceChain::NAME, initial_header_number)) - } - } - - Ok(InitializationData { - header: Box::new(initial_header), - authority_list: initial_authorities_set, - set_id: if schedules_change { - initial_authorities_set_id + 1 - } else { - initial_authorities_set_id - }, - is_halted: false, - }) -} - -/// Read header by hash from the source client. -async fn source_header( - source_client: &Client, - header_hash: SourceChain::Hash, -) -> Result::Number>> -{ - source_client - .header_by_hash(header_hash) - .await - .map_err(|err| Error::RetrieveHeader(SourceChain::NAME, header_hash, err)) -} - -/// Read GRANDPA authorities set at given header. -async fn source_authorities_set( - source_client: &Client, - header_hash: SourceChain::Hash, -) -> Result::Number>> -{ - let raw_authorities_set = source_client - .grandpa_authorities_set(header_hash) - .await - .map_err(|err| Error::RetrieveAuthorities(SourceChain::NAME, header_hash, err))?; - GrandpaAuthoritiesSet::decode(&mut &raw_authorities_set[..]) - .map_err(|err| Error::DecodeAuthorities(SourceChain::NAME, header_hash, err)) -} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 27d91147c2ddc..bd51925f5273b 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -22,11 +22,7 @@ use std::time::Duration; pub mod conversion_rate_update; pub mod error; -pub mod finality_guards; -pub mod finality_pipeline; -pub mod finality_source; -pub mod finality_target; -pub mod headers_initialize; +pub mod finality; pub mod helpers; pub mod messages_lane; pub mod messages_metrics; diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand_headers.rs index c1401a28a6dd8..915e04f08778e 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand_headers.rs @@ -30,9 +30,11 @@ use relay_utils::{ }; use crate::{ - finality_pipeline::{SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT}, - finality_source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, - finality_target::SubstrateFinalityTarget, + finality::{ + source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, + target::SubstrateFinalityTarget, + SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT, + }, TransactionParams, STALL_TIMEOUT, }; From 83f1485694a2316c1082ca17d38de7882e2f7b87 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 22 Apr 2022 10:40:38 +0300 Subject: [PATCH 0676/1210] Revert "add api data() for inbound_lane (#1373)" (#1375) This reverts commit ca6e1b15b2d12bd2a633278e9d036d4c6aa57c02. --- modules/messages/src/inbound_lane.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 6560df2acd42d..00875bb878a82 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -71,11 +71,6 @@ impl InboundLane { InboundLane { storage } } - /// Get this lane data - pub fn data(&self) -> InboundLaneData { - self.storage.data() - } - /// Receive state of the corresponding outbound lane. pub fn receive_state_update( &mut self, From 01ee20a07601215ce8c9e0b3b9b7e84050cbadcc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 25 Apr 2022 15:55:31 +0300 Subject: [PATCH 0677/1210] mention encoded-calls-messaging tag --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index ac3e49b94c6a6..3d3b177bbaae6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 +**IMPORTANT**: this documentation is outdated and it is mostly related to the previous version of our +bridge. Right there's an ongoing work to make our bridge work with XCM messages. Old bridge is still +available at [encoded-calls-messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) +tag. + ## Contents - [Installation](#installation) From e16148980e8029b6e53094e454790d8fca7ecea2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 25 Apr 2022 15:58:06 +0300 Subject: [PATCH 0678/1210] Revert "mention encoded-calls-messaging tag" This reverts commit 01ee20a07601215ce8c9e0b3b9b7e84050cbadcc. --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 3d3b177bbaae6..ac3e49b94c6a6 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,6 @@ Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 -**IMPORTANT**: this documentation is outdated and it is mostly related to the previous version of our -bridge. Right there's an ongoing work to make our bridge work with XCM messages. Old bridge is still -available at [encoded-calls-messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) -tag. - ## Contents - [Installation](#installation) From 67202ede45bab58c0bc8ff3243b9505a039fc4ff Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 28 Apr 2022 17:02:00 +0300 Subject: [PATCH 0679/1210] Switch to gav-xcm-v3 branch to be able to test bridges + XCMv3 integration (#1378) * switch to gav-xcm-v3 branch (wip) * add comment * play with CI * keep playing with CI * play with CI * trigger CI * Revert "trigger CI" This reverts commit fc35ac648fe6a3ea8e710a2e07dfee7d8762c6c4. --- bin/millau/node/src/cli.rs | 1 + bin/millau/node/src/command.rs | 30 +-- bin/millau/node/src/service.rs | 5 +- bin/millau/runtime/Cargo.toml | 4 +- bin/millau/runtime/src/lib.rs | 30 ++- bin/rialto-parachain/node/Cargo.toml | 30 +-- bin/rialto-parachain/node/src/cli.rs | 2 +- bin/rialto-parachain/node/src/command.rs | 27 ++- bin/rialto-parachain/runtime/Cargo.toml | 34 +-- bin/rialto-parachain/runtime/src/lib.rs | 35 +++- bin/rialto/node/Cargo.toml | 10 +- bin/rialto/node/src/cli.rs | 1 + bin/rialto/node/src/command.rs | 29 +-- bin/rialto/runtime/Cargo.toml | 12 +- bin/rialto/runtime/src/lib.rs | 31 ++- bin/runtime-common/Cargo.toml | 2 +- modules/dispatch/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- modules/token-swap/Cargo.toml | 2 +- modules/token-swap/src/lib.rs | 252 ++++++++++++----------- primitives/chain-millau/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/message-dispatch/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/src/lib.rs | 1 - primitives/token-swap/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 10 +- relays/client-kusama/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-wococo/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 41 files changed, 331 insertions(+), 259 deletions(-) diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index c3c3d134e3411..0280254bcada8 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -67,5 +67,6 @@ pub enum Subcommand { Inspect(node_inspect::cli::InspectCmd), /// Benchmark runtime pallets. + #[clap(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index 3653428d1044f..e9f94b03a2adc 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -19,6 +19,7 @@ use crate::{ service, service::new_partial, }; +use frame_benchmarking_cli::BenchmarkCmd; use millau_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; @@ -77,18 +78,23 @@ pub fn run() -> sc_cli::Result<()> { )); match &cli.subcommand { - Some(Subcommand::Benchmark(cmd)) => - if cfg!(feature = "runtime-benchmarks") { - let runner = cli.create_runner(cmd)?; - - runner.sync_run(|config| cmd.run::(config)) - } else { - println!( - "Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - ); - Ok(()) - }, + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + match cmd { + BenchmarkCmd::Pallet(cmd) => + if cfg!(feature = "runtime-benchmarks") { + runner + .sync_run(|config| cmd.run::(config)) + } else { + println!( + "Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + ); + Ok(()) + }, + _ => Err("Unsupported benchmarking subcommand".into()), + } + }, Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 15f88269aa9c6..a86216ca637a6 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -392,8 +392,9 @@ pub fn new_full(mut config: Configuration) -> Result if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; let beefy_params = beefy_gadget::BeefyParams { - client, + client: client.clone(), backend, + runtime: client, key_store: keystore.clone(), network: network.clone(), signed_commitment_sender: beefy_commitment_link, @@ -407,7 +408,7 @@ pub fn new_full(mut config: Configuration) -> Result task_manager.spawn_essential_handle().spawn_blocking( "beefy-gadget", None, - beefy_gadget::start_beefy_gadget::<_, _, _, _>(beefy_params), + beefy_gadget::start_beefy_gadget::<_, _, _, _, _>(beefy_params), ); let grandpa_config = sc_finality_grandpa::Config { diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 162404b77e7de..7fd2db7eee671 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -44,7 +44,6 @@ pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -57,6 +56,7 @@ sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-offchain = { 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-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d2da5affb235b..99bb8ae33c11a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -39,13 +39,13 @@ use bridge_runtime_common::messages::{ use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; -use pallet_mmr_primitives::{ - DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, -}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_mmr_primitives::{ + DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, +}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, @@ -61,7 +61,10 @@ use sp_version::RuntimeVersion; pub use frame_support::{ construct_runtime, parameter_types, traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, RuntimeDbWeight, Weight}, + weights::{ + constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, IdentityFee, + RuntimeDbWeight, Weight, + }, StorageValue, }; @@ -278,10 +281,19 @@ parameter_types! { pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0); } +pub struct BeefyDummyDataProvider; + +impl beefy_primitives::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { + fn extra_data() -> () { + () + } +} + impl pallet_beefy_mmr::Config for Runtime { type LeafVersion = LeafVersion; type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; - type ParachainHeads = (); + type LeafExtra = (); + type BeefyDataProvider = BeefyDummyDataProvider; } parameter_types! { @@ -333,9 +345,9 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = bp_millau::WeightToFee; + type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< Runtime, TargetBlockFullness, @@ -669,7 +681,7 @@ impl_runtime_apis! { } } - impl pallet_mmr_primitives::MmrApi for Runtime { + impl sp_mmr_primitives::MmrApi for Runtime { fn generate_proof(leaf_index: u64) -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> { @@ -700,6 +712,10 @@ impl_runtime_apis! { let node = DataOrHash::Data(leaf.into_opaque_leaf()); pallet_mmr::verify_leaf_proof::(root, node, proof) } + + fn mmr_root() -> Result { + Ok(Mmr::mmr_root()) + } } impl fg_primitives::GrandpaApi for Runtime { diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 41021a35ed2b0..7f5e6dedb6b9a 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -72,20 +72,20 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } # Cumulus dependencies -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } # Polkadot dependencies -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } \ No newline at end of file +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 89d049f022e3e..daf6739daa3ff 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -51,7 +51,7 @@ pub enum Subcommand { Revert(sc_cli::RevertCmd), /// The custom benchmark subcommmand benchmarking runtime pallets. - #[clap(name = "benchmark", about = "Benchmark runtime pallets.")] + #[clap(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index f93a939b9ecb6..20278b5767e41 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -22,6 +22,7 @@ use crate::{ use codec::Encode; use cumulus_client_service::genesis::generate_genesis_block; use cumulus_primitives_core::ParaId; +use frame_benchmarking_cli::BenchmarkCmd; use log::info; use polkadot_parachain::primitives::AccountIdConversion; use rialto_parachain_runtime::{Block, RuntimeApi}; @@ -255,16 +256,22 @@ pub fn run() -> Result<()> { Ok(()) }, - Some(Subcommand::Benchmark(cmd)) => - if cfg!(feature = "runtime-benchmarks") { - let runner = cli.create_runner(cmd)?; - - runner.sync_run(|config| cmd.run::(config)) - } else { - Err("Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - .into()) - }, + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + match cmd { + BenchmarkCmd::Pallet(cmd) => + if cfg!(feature = "runtime-benchmarks") { + runner.sync_run(|config| cmd.run::(config)) + } else { + println!( + "Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + ); + Ok(()) + }, + _ => Err("Unsupported benchmarking subcommand".into()), + } + }, None => { let runner = cli.create_runner(&cli.run.normalize())?; let collator_options = cli.run.collator_options(); diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 1d0870fcbcd80..52a54bd7bb72a 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -13,7 +13,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.0.0', default-features = false, features = ['derive']} log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = '1.0', optional = true, features = ['derive'] } # Bridge depedencies @@ -38,7 +38,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master ## Substrate FRAME Dependencies frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -53,22 +53,22 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Cumulus Dependencies -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } # Polkadot Dependencies -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } [features] default = ['std'] @@ -106,7 +106,9 @@ std = [ "pallet-timestamp/std", "pallet-sudo/std", "pallet-transaction-payment/std", + "pallet-xcm/std", "parachain-info/std", + "polkadot-parachain/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-parachain-system/std", "cumulus-pallet-xcmp-queue/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 646521f329399..41f159c70d24b 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -43,7 +43,7 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, match_types, parameter_types, - traits::{Everything, IsInVec, Randomness}, + traits::{Everything, IsInVec, Nothing, Randomness}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, DispatchClass, IdentityFee, Weight, @@ -69,10 +69,10 @@ use polkadot_parachain::primitives::Sibling; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, - EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset, - ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, }; use xcm_executor::{Config, XcmExecutor}; @@ -252,9 +252,9 @@ impl pallet_balances::Config for Runtime { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); } @@ -289,7 +289,7 @@ parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = NetworkId::Polkadot; pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); - pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); + pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into()).into()); } /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used @@ -349,6 +349,7 @@ parameter_types! { pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; pub const MaxAuthorities: u32 = 100_000; + pub MaxAssetsIntoHolding: u32 = 64; } match_types! { @@ -369,12 +370,11 @@ pub struct XcmConfig; impl Config for XcmConfig { type Call = Call; type XcmSender = XcmRouter; - // How to withdraw and deposit an asset. type AssetTransactor = LocalAssetTransactor; type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = NativeAsset; type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of UNIT - type LocationInverter = LocationInverter; + type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; type Trader = UsingComponents, RelayLocation, AccountId, Balances, ()>; @@ -382,6 +382,13 @@ impl Config for XcmConfig { type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; + type PalletInstancesInfo = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -391,7 +398,7 @@ pub type LocalOriginToLocation = SignedToAccountId32, + cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. XcmpQueue, ); @@ -406,11 +413,16 @@ impl pallet_xcm::Config for Runtime { type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; type Weigher = FixedWeightBounds; - type LocationInverter = LocationInverter; type Origin = Origin; type Call = Call; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = frame_support::traits::ConstU32<8>; + type UniversalLocation = UniversalLocation; } impl cumulus_pallet_xcm::Config for Runtime { @@ -427,6 +439,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type WeightInfo = (); + type PriceForSiblingDelivery = (); } impl cumulus_pallet_dmp_queue::Config for Runtime { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 31699ffad0296..6ae7eba231850 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -35,7 +35,6 @@ frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -66,6 +65,7 @@ sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -76,10 +76,10 @@ substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate # Polkadot Dependencies -polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } +polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false, features = [ "full-node", "polkadot-native" ] } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index bb7f54998dd5f..0cdd25417e7f0 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -67,6 +67,7 @@ pub enum Subcommand { Inspect(node_inspect::cli::InspectCmd), /// Benchmark runtime pallets. + #[clap(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 24e73f6fffc34..385a88ca065d3 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{Cli, Subcommand}; +use frame_benchmarking_cli::BenchmarkCmd; use rialto_runtime::{Block, RuntimeApi}; use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; @@ -86,18 +87,22 @@ pub fn run() -> sc_cli::Result<()> { )); match &cli.subcommand { - Some(Subcommand::Benchmark(cmd)) => - if cfg!(feature = "runtime-benchmarks") { - let runner = cli.create_runner(cmd)?; - - runner.sync_run(|config| cmd.run::(config)) - } else { - println!( - "Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - ); - Ok(()) - }, + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + match cmd { + BenchmarkCmd::Pallet(cmd) => + if cfg!(feature = "runtime-benchmarks") { + runner.sync_run(|config| cmd.run::(config)) + } else { + println!( + "Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + ); + Ok(()) + }, + _ => Err("Unsupported benchmarking subcommand".into()), + } + }, Some(Subcommand::Key(cmd)) => cmd.run(&cli), Some(Subcommand::Sign(cmd)) => cmd.run(), Some(Subcommand::Verify(cmd)) => cmd.run(), diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 59b9a8e9b5755..99ab1f9a6915d 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -12,7 +12,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = hex-literal = "0.3" libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -44,7 +44,6 @@ pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -58,6 +57,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { 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-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-offchain = { 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-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -68,9 +68,9 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master # Polkadot (parachain) Dependencies -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } @@ -108,7 +108,7 @@ std = [ "pallet-bridge-messages/std", "pallet-grandpa/std", "pallet-mmr/std", - "pallet-mmr-primitives/std", + "sp-mmr-primitives/std", "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 87cddf5e268db..2334d45f340e7 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -40,13 +40,13 @@ use bridge_runtime_common::messages::{ use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; -use pallet_mmr_primitives::{ - DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, -}; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_mmr_primitives::{ + DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, +}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, @@ -305,10 +305,19 @@ parameter_types! { pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0); } +pub struct BeefyDummyDataProvider; + +impl beefy_primitives::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { + fn extra_data() -> () { + () + } +} + impl pallet_beefy_mmr::Config for Runtime { type LeafVersion = LeafVersion; type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; - type ParachainHeads = (); + type LeafExtra = (); + type BeefyDataProvider = BeefyDummyDataProvider; } parameter_types! { @@ -360,9 +369,9 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type TransactionByteFee = TransactionByteFee; type OperationalFeeMultiplier = OperationalFeeMultiplier; type WeightToFee = bp_rialto::WeightToFee; + type LengthToFee = bp_rialto::WeightToFee; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< Runtime, TargetBlockFullness, @@ -610,7 +619,7 @@ impl_runtime_apis! { } } - impl pallet_mmr_primitives::MmrApi for Runtime { + impl sp_mmr_primitives::MmrApi for Runtime { fn generate_proof(leaf_index: u64) -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> { @@ -641,6 +650,10 @@ impl_runtime_apis! { let node = DataOrHash::Data(leaf.into_opaque_leaf()); pallet_mmr::verify_leaf_proof::(root, node, proof) } + + fn mmr_root() -> Result { + Ok(Mmr::mmr_root()) + } } impl bp_millau::MillauFinalityApi for Runtime { @@ -715,7 +728,7 @@ impl_runtime_apis! { } } - impl polkadot_primitives::v2::ParachainHost for Runtime { + impl polkadot_primitives::runtime_api::ParachainHost for Runtime { fn validators() -> Vec { polkadot_runtime_parachains::runtime_api_impl::v2::validators::() } @@ -809,6 +822,10 @@ impl_runtime_apis! { { polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_hash::(para_id, assumption) } + + fn staging_get_disputes() -> Vec<(polkadot_primitives::v2::SessionIndex, polkadot_primitives::v2::CandidateHash, polkadot_primitives::v2::DisputeState)> { + unimplemented!() + } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index abd84364ce2cd..6ca7de5ac43dd 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml index 833d5cca77a71..c2e8c74da828d 100644 --- a/modules/dispatch/Cargo.toml +++ b/modules/dispatch/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index eac80375da128..f4a64758aa923 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -12,7 +12,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = finality-grandpa = { version = "0.15.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 804f323f10b6f..eaacf2aeb45f1 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -11,7 +11,7 @@ bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 30a5618b115f2..bf7365166399a 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml index aad395fb7a306..d3a60d3472902 100644 --- a/modules/token-swap/Cargo.toml +++ b/modules/token-swap/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs index e46a4bc2dd034..81059ee1fd5fa 100644 --- a/modules/token-swap/src/lib.rs +++ b/modules/token-swap/src/lib.rs @@ -301,110 +301,112 @@ pub mod pallet { } let swap_account = swap_account_id::(&swap); - let actual_send_message_weight = frame_support::storage::with_transaction(|| { - // funds are transferred from This account to the temporary Swap account - let transfer_result = T::ThisCurrency::transfer( - &swap.source_account_at_this_chain, - &swap_account, - // saturating_add is ok, or we have the chain where single holder owns all - // tokens - swap.source_balance_at_this_chain - .saturating_add(swap_delivery_and_dispatch_fee), - // if we'll allow account to die, then he'll be unable to `cancel_claim` - // if something won't work - ExistenceRequirement::KeepAlive, - ); - if let Err(err) = transfer_result { - log::error!( - target: "runtime::bridge-token-swap", - "Failed to transfer This chain tokens for the swap {:?} to Swap account ({:?}): {:?}", - swap, - swap_account, - err, + let actual_send_message_weight = frame_support::storage::with_transaction( + || -> sp_runtime::TransactionOutcome> { + // funds are transferred from This account to the temporary Swap account + let transfer_result = T::ThisCurrency::transfer( + &swap.source_account_at_this_chain, + &swap_account, + // saturating_add is ok, or we have the chain where single holder owns all + // tokens + swap.source_balance_at_this_chain + .saturating_add(swap_delivery_and_dispatch_fee), + // if we'll allow account to die, then he'll be unable to `cancel_claim` + // if something won't work + ExistenceRequirement::KeepAlive, ); - - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferToSwapAccount, - )) - } - - // the transfer message is sent over the bridge. The message is supposed to be a - // `Currency::transfer` call on the bridged chain, but no checks are made - it is - // the transaction submitter to ensure it is valid. - let send_message_result = T::MessagesBridge::send_message( - RawOrigin::TokenSwap { - source_account_at_this_chain: swap.source_account_at_this_chain.clone(), - swap_account_at_this_chain: swap_account.clone(), - } - .into(), - T::OutboundMessageLaneId::get(), - bp_message_dispatch::MessagePayload { - spec_version: bridged_chain_spec_version, - weight: bridged_currency_transfer_weight, - origin: bp_message_dispatch::CallOrigin::TargetAccount( - swap_account, - target_public_at_bridged_chain, - bridged_currency_transfer_signature, - ), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: bridged_currency_transfer, - }, - swap_delivery_and_dispatch_fee, - ); - let sent_message = match send_message_result { - Ok(sent_message) => sent_message, - Err(err) => { + if let Err(err) = transfer_result { log::error!( target: "runtime::bridge-token-swap", - "Failed to send token transfer message for swap {:?} to the Bridged chain: {:?}", + "Failed to transfer This chain tokens for the swap {:?} to Swap account ({:?}): {:?}", swap, + swap_account, err, ); return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToSendTransferMessage, + Error::::FailedToTransferToSwapAccount.into(), )) - }, - }; - - // remember that we have started the swap - let swap_hash = swap.using_encoded(blake2_256).into(); - let insert_swap_result = - PendingSwaps::::try_mutate(swap_hash, |maybe_state| { - if maybe_state.is_some() { - return Err(()) + } + + // the transfer message is sent over the bridge. The message is supposed to be a + // `Currency::transfer` call on the bridged chain, but no checks are made - it + // is the transaction submitter to ensure it is valid. + let send_message_result = T::MessagesBridge::send_message( + RawOrigin::TokenSwap { + source_account_at_this_chain: swap.source_account_at_this_chain.clone(), + swap_account_at_this_chain: swap_account.clone(), } + .into(), + T::OutboundMessageLaneId::get(), + bp_message_dispatch::MessagePayload { + spec_version: bridged_chain_spec_version, + weight: bridged_currency_transfer_weight, + origin: bp_message_dispatch::CallOrigin::TargetAccount( + swap_account, + target_public_at_bridged_chain, + bridged_currency_transfer_signature, + ), + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + call: bridged_currency_transfer, + }, + swap_delivery_and_dispatch_fee, + ); + let sent_message = match send_message_result { + Ok(sent_message) => sent_message, + Err(err) => { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to send token transfer message for swap {:?} to the Bridged chain: {:?}", + swap, + err, + ); + + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::FailedToSendTransferMessage.into(), + )) + }, + }; - *maybe_state = Some(TokenSwapState::Started); - Ok(()) - }); - if insert_swap_result.is_err() { - log::error!( + // remember that we have started the swap + let swap_hash = swap.using_encoded(blake2_256).into(); + let insert_swap_result = + PendingSwaps::::try_mutate(swap_hash, |maybe_state| { + if maybe_state.is_some() { + return Err(()) + } + + *maybe_state = Some(TokenSwapState::Started); + Ok(()) + }); + if insert_swap_result.is_err() { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to start token swap {:?}: the swap is already started", + swap, + ); + + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::SwapAlreadyStarted.into(), + )) + } + + log::trace!( target: "runtime::bridge-token-swap", - "Failed to start token swap {:?}: the swap is already started", + "The swap {:?} (hash {:?}) has been started", swap, + swap_hash, ); - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::SwapAlreadyStarted, - )) - } - - log::trace!( - target: "runtime::bridge-token-swap", - "The swap {:?} (hash {:?}) has been started", - swap, - swap_hash, - ); - - // remember that we're waiting for the transfer message delivery confirmation - PendingMessages::::insert(sent_message.nonce, swap_hash); + // remember that we're waiting for the transfer message delivery confirmation + PendingMessages::::insert(sent_message.nonce, swap_hash); - // finally - emit the event - Self::deposit_event(Event::SwapStarted(swap_hash, sent_message.nonce)); + // finally - emit the event + Self::deposit_event(Event::SwapStarted(swap_hash, sent_message.nonce)); - sp_runtime::TransactionOutcome::Commit(Ok(sent_message.weight)) - })?; + sp_runtime::TransactionOutcome::Commit(Ok(sent_message.weight)) + }, + )?; Ok(PostDispatchInfo { actual_weight: Some(base_weight.saturating_add(actual_send_message_weight)), @@ -617,49 +619,51 @@ pub mod pallet { event: Event, ) -> DispatchResultWithPostInfo { let swap_account = swap_account_id::(&swap); - frame_support::storage::with_transaction(|| { - // funds are transferred from the temporary Swap account to the destination account - let transfer_result = T::ThisCurrency::transfer( - &swap_account, - &destination_account, - swap.source_balance_at_this_chain, - ExistenceRequirement::AllowDeath, - ); - if let Err(err) = transfer_result { - log::error!( - target: "runtime::bridge-token-swap", - "Failed to transfer This chain tokens for the swap {:?} from the Swap account {:?} to {:?}: {:?}", - swap, - swap_account, - destination_account, - err, + frame_support::storage::with_transaction( + || -> sp_runtime::TransactionOutcome> { + // funds are transferred from the temporary Swap account to the destination account + let transfer_result = T::ThisCurrency::transfer( + &swap_account, + &destination_account, + swap.source_balance_at_this_chain, + ExistenceRequirement::AllowDeath, ); + if let Err(err) = transfer_result { + log::error!( + target: "runtime::bridge-token-swap", + "Failed to transfer This chain tokens for the swap {:?} from the Swap account {:?} to {:?}: {:?}", + swap, + swap_account, + destination_account, + err, + ); - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferFromSwapAccount.into(), - )) - } + return sp_runtime::TransactionOutcome::Rollback(Err( + Error::::FailedToTransferFromSwapAccount.into(), + )) + } - log::trace!( - target: "runtime::bridge-token-swap", - "The swap {:?} (hash {:?}) has been completed with {} status", - swap, - swap_hash, - match event { - Event::SwapClaimed(_) => "claimed", - Event::SwapCanceled(_) => "canceled", - _ => "", - }, - ); + log::trace!( + target: "runtime::bridge-token-swap", + "The swap {:?} (hash {:?}) has been completed with {} status", + swap, + swap_hash, + match event { + Event::SwapClaimed(_) => "claimed", + Event::SwapCanceled(_) => "canceled", + _ => "", + }, + ); - // forget about swap - PendingSwaps::::remove(swap_hash); + // forget about swap + PendingSwaps::::remove(swap_hash); - // finally - emit the event - Pallet::::deposit_event(event); + // finally - emit the event + Pallet::::deposit_event(event); - sp_runtime::TransactionOutcome::Commit(Ok(().into())) - }) + sp_runtime::TransactionOutcome::Commit(Ok(Ok(().into()))) + }, + )? } } diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 0aaeb5b6bf9d4..4cd8b30f7ff90 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -17,7 +17,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.3.1", optional = true } parity-util-mem = { version = "0.11", default-features = false, features = ["primitive-types"] } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Based Dependencies diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index ee6e2b9be99a0..6a894f35c2a4c 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 7cd688d0d8197..c925abf962b2b 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } finality-grandpa = { version = "0.15.0", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml index 39b2d00111e15..02b0912894daf 100644 --- a/primitives/message-dispatch/Cargo.toml +++ b/primitives/message-dispatch/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 2a84f74d225bd..af5e801f8d2fa 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.0.1", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 1542a784ef561..ce756d0897d47 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 085cfb9dbc6d4..20208fd5fa0ba 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } hash-db = { version = "0.15.2", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 9e044ed472dd7..38d9453c98f24 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -20,7 +20,6 @@ use bp_header_chain::justification::GrandpaJustification; use codec::Encode; -use sp_application_crypto::TryFrom; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId}; use sp_runtime::traits::{Header as HeaderT, One, Zero}; use sp_std::prelude::*; diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml index 9097856f853ac..7ef5845d2aba7 100644 --- a/primitives/token-swap/Cargo.toml +++ b/primitives/token-swap/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index fb8ff467d047d..018fbfd2dded1 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" async-std = "1.9.0" -async-trait = "0.1.42" +async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" hex = "0.4" @@ -68,10 +68,10 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master # Polkadot Dependencies -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 35c24c1089e60..8ab3a27fd7c99 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", features = ["derive"] } +scale-info = { version = "2.1.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 96cfa2ce1bacf..1d61f0b4cdcee 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", features = ["derive"] } +scale-info = { version = "2.1.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 2b78684a853cb..a2d84c496077b 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", features = ["derive"] } +scale-info = { version = "2.1.1", features = ["derive"] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index dad864965e29e..5298009d8718e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.40" +async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } jsonrpsee = { version = "0.8", features = ["macros", "ws-client"] } log = "0.4.11" diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 6845ac34c84a0..d9d892a9206d4 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index cc5ae54be339c..692e902ace427 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -8,7 +8,7 @@ description = "Finality proofs relay" [dependencies] async-std = "1.6.5" -async-trait = "0.1.40" +async-trait = "0.1" backoff = "0.2" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.5" diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index e2cabf52f449b..b8bfcc9601dd4 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" anyhow = "1.0" thiserror = "1.0.26" async-std = "1.9.0" -async-trait = "0.1.42" +async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" num-traits = "0.2" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index b3357994b1251..af967f34acdad 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.40" +async-trait = "0.1" futures = "0.3.5" hex = "0.4" log = "0.4.11" diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index bb69849da26b0..af5baa5ccf00d 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" ansi_term = "0.12" anyhow = "1.0" async-std = "1.6.5" -async-trait = "0.1.40" +async-trait = "0.1" backoff = "0.2" isahc = "1.2" env_logger = "0.8.2" From 880f5586d72c26d2c5fc12b31ed3c0b33881be4b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 2 May 2022 17:36:38 +0300 Subject: [PATCH 0680/1210] Update Substrate/Polkadot refs for latest BEEFY + xcm-v3 capability (#1381) * Update Substrate/Polkadot xcm-v3-capable references Branches below are based on gav-xcm-v3 + cherry-picked BEEFY commits. polkadot: 'locked-for-gav-xcm-v3-and-bridges#6e00638f0a2d07ba3bb1c7430a539c15b5a79b74' substrate: 'sv-locked-for-gav-xcm-v3-and-bridges#a42bef088f173f54aba152ca63eb301ba44dd339' Signed-off-by: acatangiu * millau: reduce beefy min block delta to 2 * bump substrate, polkadot refs to include beefy fixes * grafana: fix beefy dashboards --- bin/millau/node/src/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index a86216ca637a6..5ac5917f16583 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -399,7 +399,7 @@ pub fn new_full(mut config: Configuration) -> Result network: network.clone(), signed_commitment_sender: beefy_commitment_link, beefy_best_block_sender: beefy_best_block_link, - min_block_delta: 4, + min_block_delta: 2, prometheus_registry: prometheus_registry.clone(), protocol_name: beefy_protocol_name, }; From f5c81df1549cca3675eded24b7f4d35c4377b4ee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 4 May 2022 15:05:14 +0300 Subject: [PATCH 0681/1210] Remove support for encoded-call messaging from relay and runtime integration code (#1376) * remove support for encoded-call messaging * continue cleanup * continue cleanup * continue cleanup * more cleanpup * more cleanup * fmt * continue cleanup * spellcheck * rename * fix benchmarks * mention encoded-calls-messaging tag * fixing deployments * fix messages generation * fmt --- README.md | 5 + bin/millau/runtime/Cargo.toml | 7 - bin/millau/runtime/src/lib.rs | 97 +- bin/millau/runtime/src/rialto_messages.rs | 46 +- bin/rialto/runtime/Cargo.toml | 4 - bin/rialto/runtime/src/lib.rs | 39 +- bin/rialto/runtime/src/millau_messages.rs | 180 +-- bin/runtime-common/Cargo.toml | 8 +- bin/runtime-common/README.md | 181 --- bin/runtime-common/src/integrity.rs | 4 +- bin/runtime-common/src/messages.rs | 382 +----- bin/runtime-common/src/messages_api.rs | 9 +- .../src/messages_benchmarking.rs | 129 +- modules/dispatch/Cargo.toml | 42 - modules/dispatch/README.md | 63 - modules/dispatch/src/lib.rs | 1084 --------------- modules/messages/Cargo.toml | 2 - modules/token-swap/Cargo.toml | 59 - modules/token-swap/src/benchmarking.rs | 198 --- modules/token-swap/src/lib.rs | 1195 ----------------- modules/token-swap/src/mock.rs | 200 --- modules/token-swap/src/weights.rs | 93 -- modules/token-swap/src/weights_ext.rs | 42 - primitives/chain-millau/src/lib.rs | 3 - primitives/message-dispatch/Cargo.toml | 27 - primitives/message-dispatch/src/lib.rs | 142 -- primitives/runtime/src/lib.rs | 8 +- primitives/token-swap/Cargo.toml | 38 - primitives/token-swap/src/lib.rs | 124 -- primitives/token-swap/src/storage_keys.rs | 51 - relays/bin-substrate/Cargo.toml | 4 - relays/bin-substrate/src/chains/kusama.rs | 115 +- relays/bin-substrate/src/chains/millau.rs | 106 +- relays/bin-substrate/src/chains/mod.rs | 140 +- relays/bin-substrate/src/chains/polkadot.rs | 115 +- relays/bin-substrate/src/chains/rialto.rs | 105 +- .../src/chains/rialto_parachain.rs | 50 +- relays/bin-substrate/src/chains/rococo.rs | 116 +- relays/bin-substrate/src/chains/westend.rs | 11 +- relays/bin-substrate/src/chains/wococo.rs | 109 +- relays/bin-substrate/src/cli/bridge.rs | 31 +- .../bin-substrate/src/cli/derive_account.rs | 101 -- relays/bin-substrate/src/cli/encode_call.rs | 354 ----- .../bin-substrate/src/cli/encode_message.rs | 151 +-- relays/bin-substrate/src/cli/estimate_fee.rs | 31 +- relays/bin-substrate/src/cli/mod.rs | 112 +- .../src/cli/register_parachain.rs | 46 +- relays/bin-substrate/src/cli/reinit_bridge.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 288 +--- relays/bin-substrate/src/cli/swap_tokens.rs | 869 ------------ relays/client-kusama/Cargo.toml | 2 - relays/client-kusama/src/runtime.rs | 35 +- relays/client-polkadot/Cargo.toml | 2 - relays/client-polkadot/src/runtime.rs | 35 +- relays/client-rococo/Cargo.toml | 2 - relays/client-rococo/src/runtime.rs | 35 +- relays/client-wococo/Cargo.toml | 2 - relays/client-wococo/src/runtime.rs | 35 +- 58 files changed, 406 insertions(+), 7060 deletions(-) delete mode 100644 bin/runtime-common/README.md delete mode 100644 modules/dispatch/Cargo.toml delete mode 100644 modules/dispatch/README.md delete mode 100644 modules/dispatch/src/lib.rs delete mode 100644 modules/token-swap/Cargo.toml delete mode 100644 modules/token-swap/src/benchmarking.rs delete mode 100644 modules/token-swap/src/lib.rs delete mode 100644 modules/token-swap/src/mock.rs delete mode 100644 modules/token-swap/src/weights.rs delete mode 100644 modules/token-swap/src/weights_ext.rs delete mode 100644 primitives/message-dispatch/Cargo.toml delete mode 100644 primitives/message-dispatch/src/lib.rs delete mode 100644 primitives/token-swap/Cargo.toml delete mode 100644 primitives/token-swap/src/lib.rs delete mode 100644 primitives/token-swap/src/storage_keys.rs delete mode 100644 relays/bin-substrate/src/cli/derive_account.rs delete mode 100644 relays/bin-substrate/src/cli/encode_call.rs delete mode 100644 relays/bin-substrate/src/cli/swap_tokens.rs diff --git a/README.md b/README.md index ac3e49b94c6a6..3d3b177bbaae6 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 +**IMPORTANT**: this documentation is outdated and it is mostly related to the previous version of our +bridge. Right there's an ongoing work to make our bridge work with XCM messages. Old bridge is still +available at [encoded-calls-messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) +tag. + ## Contents - [Installation](#installation) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 7fd2db7eee671..80d961388831a 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -17,17 +17,14 @@ serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } -bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-westend = { path = "../../../primitives/chain-westend", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } -pallet-bridge-token-swap = { path = "../../../modules/token-swap", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies @@ -77,7 +74,6 @@ default = ["std"] std = [ "beefy-primitives/std", "bp-header-chain/std", - "bp-message-dispatch/std", "bp-messages/std", "bp-millau/std", "bp-rialto/std", @@ -93,10 +89,8 @@ std = [ "pallet-balances/std", "pallet-beefy/std", "pallet-beefy-mmr/std", - "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", - "pallet-bridge-token-swap/std", "pallet-grandpa/std", "pallet-mmr/std", "pallet-randomness-collective-flip/std", @@ -129,6 +123,5 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", - "pallet-bridge-token-swap/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 99bb8ae33c11a..4d44f34b624b3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -50,7 +50,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -225,18 +225,6 @@ impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; } -impl pallet_bridge_dispatch::Config for Runtime { - type Event = Event; - type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); - type Call = Call; - type CallFilter = frame_support::traits::Everything; - type EncodedCall = crate::rialto_messages::FromRialtoEncodedCall; - type SourceChainAccountId = bp_rialto::AccountId; - type TargetChainAccountPublic = MultiSigner; - type TargetChainSignature = MultiSignature; - type AccountIdConverter = bp_millau::AccountIdConverter; -} - impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; @@ -471,38 +459,13 @@ impl pallet_bridge_messages::Config for Runtime { GetDeliveryConfirmationTransactionFee, >; type OnMessageAccepted = (); - type OnDeliveryConfirmed = - pallet_bridge_token_swap::Pallet; + type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; type BridgedChainId = RialtoChainId; } -parameter_types! { - pub const TokenSwapMessagesLane: bp_messages::LaneId = *b"swap"; -} - -/// Instance of the with-Rialto token swap pallet. -pub type WithRialtoTokenSwapInstance = (); - -impl pallet_bridge_token_swap::Config for Runtime { - type Event = Event; - type WeightInfo = (); - - type BridgedChainId = RialtoChainId; - type OutboundMessageLaneId = TokenSwapMessagesLane; - #[cfg(not(feature = "runtime-benchmarks"))] - type MessagesBridge = pallet_bridge_messages::Pallet; - #[cfg(feature = "runtime-benchmarks")] - type MessagesBridge = bp_messages::source_chain::NoopMessagesBridge; - type ThisCurrency = pallet_balances::Pallet; - type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; - - type BridgedChain = bp_rialto::Rialto; - type FromBridgedToThisAccountIdConverter = bp_millau::AccountIdConverter; -} - construct_runtime!( pub enum Runtime where Block = Block, @@ -532,9 +495,7 @@ construct_runtime!( // Rialto bridge modules. BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, - BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event, Origin}, // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, @@ -806,7 +767,6 @@ impl_runtime_apis! { let mut list = Vec::::new(); - list_benchmark!(list, extra, pallet_bridge_token_swap, BridgeRialtoTokenSwap); list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); @@ -878,8 +838,6 @@ impl_runtime_apis! { ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { prepare_message_proof::( params, - &VERSION, - Balance::MAX / 100, ) } @@ -891,33 +849,11 @@ impl_runtime_apis! { ) } - fn is_message_dispatched(nonce: bp_messages::MessageNonce) -> bool { - frame_system::Pallet::::events() - .into_iter() - .map(|event_record| event_record.event) - .any(|event| matches!( - event, - Event::BridgeDispatch(pallet_bridge_dispatch::Event::::MessageDispatched( - _, ([0, 0, 0, 0], nonce_from_event), _, - )) if nonce_from_event == nonce - )) + fn is_message_dispatched(_nonce: bp_messages::MessageNonce) -> bool { + true } } - use pallet_bridge_token_swap::benchmarking::Config as TokenSwapConfig; - - impl TokenSwapConfig for Runtime { - fn initialize_environment() { - let relayers_fund_account = pallet_bridge_messages::relayer_fund_account_id::< - bp_millau::AccountId, - bp_millau::AccountIdConverter, - >(); - pallet_balances::Pallet::::make_free_balance_be( - &relayers_fund_account, - Balance::MAX / 100, - ); - } - } add_benchmark!( params, @@ -926,37 +862,12 @@ impl_runtime_apis! { MessagesBench:: ); add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); - add_benchmark!(params, batches, pallet_bridge_token_swap, BridgeRialtoTokenSwap); Ok(batches) } } } -/// Rialto account ownership digest from Millau. -/// -/// The byte vector returned by this function should be signed with a Rialto account private key. -/// This way, the owner of `millau_account_id` on Millau proves that the Rialto account private key -/// is also under his control. -pub fn millau_to_rialto_account_ownership_digest( - rialto_call: &Call, - millau_account_id: AccountId, - rialto_spec_version: SpecVersion, -) -> sp_std::vec::Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - rialto_call, - millau_account_id, - rialto_spec_version, - bp_runtime::MILLAU_CHAIN_ID, - bp_runtime::RIALTO_CHAIN_ID, - ) -} - #[cfg(test)] mod tests { use super::*; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index d925d805dd04b..9b2c623757148 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -33,7 +33,7 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use sp_std::{convert::TryFrom, ops::RangeInclusive}; +use sp_std::convert::TryFrom; /// Initial value of `RialtoToMillauConversionRate` parameter. pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = @@ -49,19 +49,14 @@ parameter_types! { } /// Message payload for Millau -> Rialto messages. -pub type ToRialtoMessagePayload = - messages::source::FromThisChainMessagePayload; +pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload; /// Message verifier for Millau -> Rialto messages. pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = - messages::target::FromBridgedChainMessagePayload; - -/// Encoded Millau Call as it comes from Rialto. -pub type FromRialtoEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; +pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Messages proof for Rialto -> Millau messages. pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -120,19 +115,7 @@ impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { - // lanes 0x00000000 && 0x00000001 are accepting any paid messages, while - // `TokenSwapMessageLane` only accepts messages from token swap pallet - let token_swap_dedicated_lane = crate::TokenSwapMessagesLane::get(); - match *lane { - [0, 0, 0, 0] | [0, 0, 0, 1] => send_origin.linked_account().is_some(), - _ if *lane == token_swap_dedicated_lane => matches!( - send_origin.caller, - crate::OriginCaller::BridgeRialtoTokenSwap( - pallet_bridge_token_swap::RawOrigin::TokenSwap { .. } - ) - ), - _ => false, - } + (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) && send_origin.linked_account().is_some() } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -189,19 +172,8 @@ impl messages::BridgedChainWithMessages for Rialto { bp_rialto::Rialto::max_extrinsic_size() } - fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { - // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::Rialto::max_extrinsic_weight(), - ); - - // we're charging for payload bytes in `WithRialtoMessageBridge::transaction_payment` - // function - // - // this bridge may be used to deliver all kind of messages, so we're not making any - // assumptions about minimal dispatch weight here - - 0..=upper_limit + fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { + true } fn estimate_delivery_transaction( @@ -296,12 +268,6 @@ impl SenderOrigin for crate::Origin { crate::OriginCaller::system(frame_system::RawOrigin::Root) | crate::OriginCaller::system(frame_system::RawOrigin::None) => crate::RootAccountForPayments::get(), - crate::OriginCaller::BridgeRialtoTokenSwap( - pallet_bridge_token_swap::RawOrigin::TokenSwap { - ref swap_account_at_this_chain, - .. - }, - ) => Some(swap_account_at_this_chain.clone()), _ => None, } } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 99ab1f9a6915d..ccfa65090e6d1 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -18,13 +18,11 @@ serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } -bp-message-dispatch = { path = "../../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } @@ -85,7 +83,6 @@ default = ["std"] std = [ "beefy-primitives/std", "bp-header-chain/std", - "bp-message-dispatch/std", "bp-messages/std", "bp-millau/std", "bp-rialto/std", @@ -103,7 +100,6 @@ std = [ "pallet-balances/std", "pallet-beefy/std", "pallet-beefy-mmr/std", - "pallet-bridge-dispatch/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-grandpa/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 2334d45f340e7..4d2602a20a608 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -51,7 +51,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -251,18 +251,6 @@ impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; } -impl pallet_bridge_dispatch::Config for Runtime { - type Event = Event; - type BridgeMessageId = (bp_messages::LaneId, bp_messages::MessageNonce); - type Call = Call; - type CallFilter = frame_support::traits::Everything; - type EncodedCall = crate::millau_messages::FromMillauEncodedCall; - type SourceChainAccountId = bp_millau::AccountId; - type TargetChainAccountPublic = MultiSigner; - type TargetChainSignature = MultiSignature; - type AccountIdConverter = bp_rialto::AccountIdConverter; -} - impl pallet_grandpa::Config for Runtime { type Event = Event; type Call = Call; @@ -505,7 +493,6 @@ construct_runtime!( // Millau bridge modules. BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, - BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, // Parachain modules. @@ -920,30 +907,6 @@ impl_runtime_apis! { } } -/// Millau account ownership digest from Rialto. -/// -/// The byte vector returned by this function should be signed with a Millau account private key. -/// This way, the owner of `rialto_account_id` on Rialto proves that the 'millau' account private -/// key is also under his control. -pub fn rialto_to_millau_account_ownership_digest( - millau_call: &Call, - rialto_account_id: AccountId, - millau_spec_version: SpecVersion, -) -> sp_std::vec::Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - millau_call, - rialto_account_id, - millau_spec_version, - bp_runtime::RIALTO_CHAIN_ID, - bp_runtime::MILLAU_CHAIN_ID, - ) -} - #[cfg(test)] mod tests { use super::*; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 44348383f1d52..8088ee56ac754 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -33,7 +33,7 @@ use frame_support::{ }; use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use sp_std::{convert::TryFrom, ops::RangeInclusive}; +use sp_std::convert::TryFrom; /// Initial value of `MillauToRialtoConversionRate` parameter. pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = @@ -49,19 +49,14 @@ parameter_types! { } /// Message payload for Rialto -> Millau messages. -pub type ToMillauMessagePayload = - messages::source::FromThisChainMessagePayload; +pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; /// Message verifier for Rialto -> Millau messages. pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = - messages::target::FromBridgedChainMessagePayload; - -/// Encoded Rialto Call as it comes from Millau. -pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessageCall; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< @@ -177,19 +172,8 @@ impl messages::BridgedChainWithMessages for Millau { bp_millau::Millau::max_extrinsic_size() } - fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { - // we don't want to relay too large messages + keep reserve for future upgrades - let upper_limit = messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::Millau::max_extrinsic_weight(), - ); - - // we're charging for payload bytes in `WithMillauMessageBridge::transaction_payment` - // function - // - // this bridge may be used to deliver all kind of messages, so we're not making any - // assumptions about minimal dispatch weight here - - 0..=upper_limit + fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { + true } fn estimate_delivery_transaction( @@ -308,100 +292,15 @@ impl MessagesParameter for RialtoToMillauMessagesParameter { #[cfg(test)] mod tests { use super::*; - use crate::{ - AccountId, Call, DbWeight, ExistentialDeposit, MillauGrandpaInstance, Runtime, SystemCall, - SystemConfig, WithMillauMessagesInstance, VERSION, - }; - use bp_message_dispatch::CallOrigin; - use bp_messages::{ - target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - MessageKey, - }; - use bp_runtime::{derive_account_id, messages::DispatchFeePayment, Chain, SourceAccount}; + use crate::{DbWeight, MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; + use bp_runtime::Chain; use bridge_runtime_common::{ assert_complete_bridge_types, integrity::{ assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, }, - messages::target::{FromBridgedChainEncodedMessageCall, FromBridgedChainMessagePayload}, }; - use frame_support::{ - traits::Currency, - weights::{GetDispatchInfo, WeightToFeePolynomial}, - }; - use sp_runtime::traits::Convert; - - #[test] - fn transfer_happens_when_dispatch_fee_is_paid_at_target_chain() { - // this test actually belongs to the `bridge-runtime-common` crate, but there we have no - // mock runtime. Making another one there just for this test, given that both crates - // live n single repo is an overkill - let mut ext: sp_io::TestExternalities = - SystemConfig::default().build_storage::().unwrap().into(); - ext.execute_with(|| { - let bridge = MILLAU_CHAIN_ID; - let call: Call = SystemCall::set_heap_pages { pages: 64 }.into(); - let dispatch_weight = call.get_dispatch_info().weight; - let dispatch_fee = ::WeightToFee::calc( - &dispatch_weight, - ); - assert!(dispatch_fee > 0); - - // create relayer account with minimal balance - let relayer_account: AccountId = [1u8; 32].into(); - let initial_amount = ExistentialDeposit::get(); - let _ = as Currency>::deposit_creating( - &relayer_account, - initial_amount, - ); - - // create dispatch account with minimal balance + dispatch fee - let dispatch_account = derive_account_id::< - ::SourceChainAccountId, - >(bridge, SourceAccount::Root); - let dispatch_account = - ::AccountIdConverter::convert( - dispatch_account, - ); - let _ = as Currency>::deposit_creating( - &dispatch_account, - initial_amount + dispatch_fee, - ); - - // dispatch message with intention to pay dispatch fee at the target chain - FromMillauMessageDispatch::dispatch( - &relayer_account, - DispatchMessage { - key: MessageKey { lane_id: Default::default(), nonce: 0 }, - data: DispatchMessageData { - payload: Ok(FromBridgedChainMessagePayload:: { - spec_version: VERSION.spec_version, - weight: dispatch_weight, - origin: CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: FromBridgedChainEncodedMessageCall::new(call.encode()), - }), - fee: 1, - }, - }, - ); - - // ensure that fee has been transferred from dispatch to relayer account - assert_eq!( - as Currency>::free_balance( - &relayer_account - ), - initial_amount + dispatch_fee, - ); - assert_eq!( - as Currency>::free_balance( - &dispatch_account - ), - initial_amount, - ); - }); - } #[test] fn ensure_rialto_message_lane_weights_are_correct() { @@ -490,69 +389,4 @@ mod tests { .0, ); } - - #[test] - #[ignore] - fn no_stack_overflow_when_decoding_nested_call_during_dispatch() { - // this test is normally ignored, because it only makes sense to run it in release mode - - let mut ext: sp_io::TestExternalities = - SystemConfig::default().build_storage::().unwrap().into(); - ext.execute_with(|| { - let bridge = MILLAU_CHAIN_ID; - - let mut call: Call = SystemCall::set_heap_pages { pages: 64 }.into(); - - for _i in 0..3000 { - call = Call::Sudo(pallet_sudo::Call::sudo { call: Box::new(call) }); - } - - let dispatch_weight = 500; - let dispatch_fee = ::WeightToFee::calc( - &dispatch_weight, - ); - assert!(dispatch_fee > 0); - - // create relayer account with minimal balance - let relayer_account: AccountId = [1u8; 32].into(); - let initial_amount = ExistentialDeposit::get(); - let _ = as Currency>::deposit_creating( - &relayer_account, - initial_amount, - ); - - // create dispatch account with minimal balance + dispatch fee - let dispatch_account = derive_account_id::< - ::SourceChainAccountId, - >(bridge, SourceAccount::Root); - let dispatch_account = - ::AccountIdConverter::convert( - dispatch_account, - ); - let _ = as Currency>::deposit_creating( - &dispatch_account, - initial_amount + dispatch_fee, - ); - - // dispatch message with intention to pay dispatch fee at the target chain - // - // this is where the stack overflow has happened before the fix has been applied - FromMillauMessageDispatch::dispatch( - &relayer_account, - DispatchMessage { - key: MessageKey { lane_id: Default::default(), nonce: 0 }, - data: DispatchMessageData { - payload: Ok(FromBridgedChainMessagePayload:: { - spec_version: VERSION.spec_version, - weight: dispatch_weight, - origin: CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: FromBridgedChainEncodedMessageCall::new(call.encode()), - }), - fee: 1, - }, - }, - ); - }); - } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 6ca7de5ac43dd..7e8609071f86c 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,17 +9,15 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -ed25519-dalek = { version = "1.0", default-features = false, optional = true } hash-db = { version = "0.15.2", default-features = false } +log = { version = "0.4.14", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies -bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } -pallet-bridge-dispatch = { path = "../../modules/dispatch", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } @@ -40,14 +38,13 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ - "bp-message-dispatch/std", "bp-messages/std", "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", "hash-db/std", - "pallet-bridge-dispatch/std", + "log/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-transaction-payment/std", @@ -60,7 +57,6 @@ std = [ "sp-trie/std", ] runtime-benchmarks = [ - "ed25519-dalek/u64_backend", "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", diff --git a/bin/runtime-common/README.md b/bin/runtime-common/README.md deleted file mode 100644 index 5f2298cd787d3..0000000000000 --- a/bin/runtime-common/README.md +++ /dev/null @@ -1,181 +0,0 @@ -# Helpers for Messages Module Integration - -The [`messages`](./src/messages.rs) module of this crate contains a bunch of helpers for integrating -messages module into your runtime. Basic prerequisites of these helpers are: -- we're going to bridge Substrate-based chain with another Substrate-based chain; -- both chains have [messages module](../../modules/messages/README.md), Substrate bridge - module and the [call dispatch module](../../modules/dispatch/README.md); -- all message lanes are identical and may be used to transfer the same messages; -- the messages sent over the bridge are dispatched using - [call dispatch module](../../modules/dispatch/README.md); -- the messages are `bp_message_dispatch::MessagePayload` structures, where `call` field is - encoded `Call` of the target chain. This means that the `Call` is opaque to the - [messages module](../../modules/messages/README.md) instance at the source chain. - It is pre-encoded by the message submitter; -- all proofs in the [messages module](../../modules/messages/README.md) transactions are - based on the storage proofs from the bridged chain: storage proof of the outbound message (value - from the `pallet_bridge_messages::Store::MessagePayload` map), storage proof of the outbound lane - state (value from the `pallet_bridge_messages::Store::OutboundLanes` map) and storage proof of the - inbound lane state (value from the `pallet_bridge_messages::Store::InboundLanes` map); -- storage proofs are built at the finalized headers of the corresponding chain. So all message lane - transactions with proofs are verifying storage proofs against finalized chain headers from - Substrate bridge module. - -**IMPORTANT NOTE**: after reading this document, you may refer to our test runtimes -([rialto_messages.rs](../millau/runtime/src/rialto_messages.rs) and/or -[millau_messages.rs](../rialto/runtime/src/millau_messages.rs)) to see how to use these helpers. - -## Contents -- [`MessageBridge` Trait](#messagebridge-trait) -- [`ChainWithMessages` Trait ](#ChainWithMessages-trait) -- [Helpers for the Source Chain](#helpers-for-the-source-chain) -- [Helpers for the Target Chain](#helpers-for-the-target-chain) - -## `MessageBridge` Trait - -The essence of your integration will be a struct that implements a `MessageBridge` trait. It has -single method (`MessageBridge::bridged_balance_to_this_balance`), used to convert from bridged chain -tokens into this chain tokens. The bridge also requires two associated types to be specified - -`ThisChain` and `BridgedChain`. - -Worth to say that if you're going to use hardcoded constant (conversion rate) in the -`MessageBridge::bridged_balance_to_this_balance` method (or in any other method of -`ThisChainWithMessages` or `BridgedChainWithMessages` traits), then you should take a -look at the -[messages parameters functionality](../../modules/messages/README.md#Non-Essential-Functionality). -They allow pallet owner to update constants more frequently than runtime upgrade happens. - -## `ChainWithMessages` Trait - -The trait is quite simple and can easily be implemented - you just need to specify types used at the -corresponding chain. There is single exception, though (it may be changed in the future): - -- `ChainWithMessages::MessagesInstance`: this is used to compute runtime storage keys. There - may be several instances of messages pallet, included in the Runtime. Every instance stores - messages and these messages stored under different keys. When we are verifying storage proofs from - the bridged chain, we should know which instance we're talking to. This is fine, but there's - significant inconvenience with that - this chain runtime must have the same messages pallet - instance. This does not necessarily mean that we should use the same instance on both chains - - this instance may be used to bridge with another chain/instance, or may not be used at all. - -## `ThisChainWithMessages` Trait - -This trait represents this chain from bridge point of view. Let's review every method of this trait: - -- `ThisChainWithMessages::is_message_accepted`: is used to check whether given lane accepts - messages. The send-message origin is passed to the function, so you may e.g. verify that only - given pallet is able to send messages over selected lane. **IMPORTANT**: if you assume that the - message must be paid by the sender, you must ensure that the sender origin has linked the account - for paying message delivery and dispatch fee. - -- `ThisChainWithMessages::maximal_pending_messages_at_outbound_lane`: you should return maximal - number of pending (undelivered) messages from this function. Returning small values would require - relayers to operate faster and could make message sending logic more complicated. On the other - hand, returning large values could lead to chain state growth. - -- `ThisChainWithMessages::estimate_delivery_confirmation_transaction`: you'll need to return - estimated size and dispatch weight of the delivery confirmation transaction (that happens on - this chain) from this function. - -- `ThisChainWithMessages::transaction_payment`: you'll need to return fee that the submitter - must pay for given transaction on this chain. Normally, you would use transaction payment pallet - for this. However, if your chain has non-zero fee multiplier set, this would mean that the - payment will be computed using current value of this multiplier. But since this transaction - will be submitted in the future, you may want to choose other value instead. Otherwise, - non-altruistic relayer may choose not to submit this transaction until number of transactions - will decrease. - -## `BridgedChainWithMessages` Trait - -This trait represents this chain from bridge point of view. Let's review every method of this trait: - -- `BridgedChainWithMessages::maximal_extrinsic_size`: you will need to return the maximal - extrinsic size of the target chain from this function. - -- `MessageBridge::message_weight_limits`: you'll need to return a range of - dispatch weights that the outbound message may take at the target chain. Please keep in mind that - our helpers assume that the message is an encoded call of the target chain. But we never decode - this call at the source chain. So you can't simply get dispatch weight from pre-dispatch - information. Instead there are two options to prepare this range: if you know which calls are to - be sent over your bridge, then you may just return weight ranges for these particular calls. - Otherwise, if you're going to accept all kinds of calls, you may just return range `[0; maximal - incoming message dispatch weight]`. If you choose the latter, then you shall remember that the - delivery transaction itself has some weight, so you can't accept messages with weight equal to - maximal weight of extrinsic at the target chain. In our test chains, we reject all messages that - have declared dispatch weight larger than 50% of the maximal bridged extrinsic weight. - -- `MessageBridge::estimate_delivery_transaction`: you will need to return estimated dispatch weight and - size of the delivery transaction that delivers a given message to the target chain. The transaction - weight must or must not include the weight of pay-dispatch-fee operation, depending on the value - of `include_pay_dispatch_fee_cost` argument. - -- `MessageBridge::transaction_payment`: you'll need to return fee that the submitter - must pay for given transaction on bridged chain. The best case is when you have the same conversion - formula on both chains - then you may just reuse the `ThisChainWithMessages::transaction_payment` - implementation. Otherwise, you'll need to hardcode this formula into your runtime. - -## Helpers for the Source Chain - -The helpers for the Source Chain reside in the `source` submodule of the -[`messages`](./src/messages.rs) module. The structs are: `FromThisChainMessagePayload`, -`FromBridgedChainMessagesDeliveryProof`, `FromThisChainMessageVerifier`. And the helper functions -are: `maximal_message_size`, `verify_chain_message`, `verify_messages_delivery_proof` and -`estimate_message_dispatch_and_delivery_fee`. - -`FromThisChainMessagePayload` is a message that the sender sends through our bridge. It is the -`bp_message_dispatch::MessagePayload`, where `call` field is encoded target chain call. So -at this chain we don't see internals of this call - we just know its size. - -`FromThisChainMessageVerifier` is an implementation of `bp_messages::LaneMessageVerifier`. It -has following checks in its `verify_message` method: - -1. it'll verify that the used outbound lane is enabled in our runtime; - -1. it'll reject messages if there are too many undelivered outbound messages at this lane. The - sender need to wait while relayers will do their work before sending the message again; - -1. it'll reject a message if it has the wrong dispatch origin declared. Like if the submitter is not - the root of this chain, but it tries to dispatch the message at the target chain using - `bp_message_dispatch::CallOrigin::SourceRoot` origin. Or he has provided wrong signature - in the `bp_message_dispatch::CallOrigin::TargetAccount` origin; - -1. it'll reject a message if the delivery and dispatch fee that the submitter wants to pay is lesser - than the fee that is computed using the `estimate_message_dispatch_and_delivery_fee` function. - -`estimate_message_dispatch_and_delivery_fee` returns a minimal fee that the submitter needs to pay -for sending a given message. The fee includes: payment for the delivery transaction at the target -chain, payment for delivery confirmation transaction on this chain, payment for `Call` dispatch at -the target chain and relayer interest. - -`FromBridgedChainMessagesDeliveryProof` holds the lane identifier and the storage proof of this -inbound lane state at the bridged chain. This also holds the hash of the target chain header, that -was used to generate this storage proof. The proof is verified by the -`verify_messages_delivery_proof`, which simply checks that the target chain header is finalized -(using Substrate bridge module) and then reads the inbound lane state from the proof. - -`verify_chain_message` function checks that the message may be delivered to the bridged chain. There -are two main checks: - -1. that the message size is less than or equal to the `2/3` of maximal extrinsic size at the target - chain. We leave `1/3` for signed extras and for the storage proof overhead; - -1. that the message dispatch weight is less than or equal to the `1/2` of maximal normal extrinsic - weight at the target chain. We leave `1/2` for the delivery transaction overhead. - -## Helpers for the Target Chain - -The helpers for the target chain reside in the `target` submodule of the -[`messages`](./src/messages.rs) module. The structs are: `FromBridgedChainMessagePayload`, -`FromBridgedChainMessagesProof`, `FromBridgedChainMessagesProof`. And the helper functions are: -`maximal_incoming_message_dispatch_weight`, `maximal_incoming_message_size` and -`verify_messages_proof`. - -`FromBridgedChainMessagePayload` corresponds to the `FromThisChainMessagePayload` at the bridged -chain. We expect that messages with this payload are stored in the `OutboundMessages` storage map of -the [messages module](../../modules/messages/README.md). This map is used to build -`FromBridgedChainMessagesProof`. The proof holds the lane id, range of message nonces included in -the proof, storage proof of `OutboundMessages` entries and the hash of bridged chain header that has -been used to build the proof. Additionally, there's storage proof may contain the proof of outbound -lane state. It may be required to prune `relayers` entries at this chain (see -[messages module documentation](../../modules/messages/README.md#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) -for details). This proof is verified by the `verify_messages_proof` function. diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index ab517566a0fe6..603f385f29ed5 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -120,10 +120,10 @@ macro_rules! assert_bridge_messages_pallet_types( use pallet_bridge_messages::Config as MessagesConfig; use static_assertions::assert_type_eq_all; - assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload); assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundMessageFee, BalanceOf>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundMessageFee, BalanceOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 6bcaae4d36577..f7eb0b2975d6b 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -20,32 +20,21 @@ //! pallet is used to dispatch incoming messages. Message identified by a tuple //! of to elements - message lane id and message nonce. -use bp_message_dispatch::MessageDispatch as _; use bp_messages::{ source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_runtime::{ - messages::{DispatchFeePayment, MessageDispatchResult}, - ChainId, Size, StorageProofChecker, -}; -use codec::{Decode, DecodeLimit, Encode}; -use frame_support::{ - traits::{Currency, ExistenceRequirement}, - weights::{Weight, WeightToFeePolynomial}, - RuntimeDebug, -}; +use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker}; +use codec::{Decode, Encode}; +use frame_support::{traits::Currency, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating, Zero}, + traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating}, FixedPointNumber, FixedPointOperand, FixedU128, }; -use sp_std::{ - cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, ops::RangeInclusive, - vec::Vec, -}; +use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; use sp_trie::StorageProof; /// Bidirectional message bridge. @@ -136,16 +125,9 @@ pub trait BridgedChainWithMessages: ChainWithMessages { /// Maximal extrinsic size at Bridged chain. fn maximal_extrinsic_size() -> u32; - /// Returns feasible weights range for given message payload at the Bridged chain. - /// - /// If message is being sent with the weight that is out of this range, then it - /// should be rejected. - /// - /// Weights returned from this function shall not include transaction overhead - /// (like weight of signature and signed extensions verification), because they're - /// already accounted by the `weight_of_delivery_transaction`. So this function should - /// return pure call dispatch weights range. - fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive; + /// Returns `true` if message dispatch weight is withing expected limits. `false` means + /// that the message is too heavy to be sent over the bridge and shall be rejected. + fn verify_dispatch_weight(message_payload: &[u8]) -> bool; /// Estimate size and weight of single message delivery transaction at the Bridged chain. fn estimate_delivery_transaction( @@ -218,12 +200,7 @@ pub mod source { pub type BridgedChainOpaqueCall = Vec; /// Message payload for This -> Bridged chain messages. - pub type FromThisChainMessagePayload = bp_message_dispatch::MessagePayload< - AccountIdOf>, - SignerOf>, - SignatureOf>, - BridgedChainOpaqueCall, - >; + pub type FromThisChainMessagePayload = Vec; /// Messages delivery proof from bridged chain: /// @@ -260,7 +237,6 @@ pub mod source { /// This verifier assumes following: /// /// - all message lanes are equivalent, so all checks are the same; - /// - messages are being dispatched using `pallet-bridge-dispatch` pallet on the target chain. /// /// Following checks are made: /// @@ -288,7 +264,7 @@ pub mod source { LaneMessageVerifier< OriginOf>, AccountIdOf>, - FromThisChainMessagePayload, + FromThisChainMessagePayload, BalanceOf>, > for FromThisChainMessageVerifier where @@ -305,7 +281,7 @@ pub mod source { delivery_and_dispatch_fee: &BalanceOf>, lane: &LaneId, lane_outbound_data: &OutboundLaneData, - payload: &FromThisChainMessagePayload, + payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { // reject message if lane is blocked if !ThisChain::::is_message_accepted(submitter, lane) { @@ -321,24 +297,6 @@ pub mod source { return Err(TOO_MANY_PENDING_MESSAGES) } - // Do the dispatch-specific check. We assume that the target chain uses - // `Dispatch`, so we verify the message accordingly. - let raw_origin_or_err: Result< - frame_system::RawOrigin>>, - OriginOf>, - > = submitter.clone().into(); - if let Ok(raw_origin) = raw_origin_or_err { - pallet_bridge_dispatch::verify_message_origin(&raw_origin, payload) - .map(drop) - .map_err(|_| BAD_ORIGIN)?; - } else { - // so what it means that we've failed to convert origin to the - // `frame_system::RawOrigin`? now it means that the custom pallet origin has - // been used to send the message. Do we need to verify it? The answer is no, - // because pallet may craft any origin (e.g. root) && we can't verify whether it - // is valid, or not. - }; - let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( payload, B::RELAYER_FEE_PERCENT, @@ -365,10 +323,9 @@ pub mod source { /// may be 'mined' by the target chain. But the lane may have its own checks (e.g. fee /// check) that would reject message (see `FromThisChainMessageVerifier`). pub fn verify_chain_message( - payload: &FromThisChainMessagePayload, + payload: &FromThisChainMessagePayload, ) -> Result<(), &'static str> { - let weight_limits = BridgedChain::::message_weight_limits(&payload.call); - if !weight_limits.contains(&payload.weight.into()) { + if !BridgedChain::::verify_dispatch_weight(payload) { return Err("Incorrect message weight declared") } @@ -382,7 +339,7 @@ pub mod source { // is enormously large, it should be several dozens/hundreds of bytes. The delivery // transaction also contains signatures and signed extensions. Because of this, we reserve // 1/3 of the the maximal extrinsic weight for this data. - if payload.call.len() > maximal_message_size::() as usize { + if payload.len() > maximal_message_size::() as usize { return Err("The message is too large to be sent over the lane") } @@ -395,7 +352,7 @@ pub mod source { /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional /// conversions. Returns `None` if overflow has happened. pub fn estimate_message_dispatch_and_delivery_fee( - payload: &FromThisChainMessagePayload, + payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, bridged_to_this_conversion_rate: Option, ) -> Result>, &'static str> { @@ -403,13 +360,8 @@ pub mod source { // // if we're going to pay dispatch fee at the target chain, then we don't include weight // of the message dispatch in the delivery transaction cost - let pay_dispatch_fee_at_target_chain = - payload.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; - let delivery_transaction = BridgedChain::::estimate_delivery_transaction( - &payload.encode(), - pay_dispatch_fee_at_target_chain, - if pay_dispatch_fee_at_target_chain { 0.into() } else { payload.weight.into() }, - ); + let delivery_transaction = + BridgedChain::::estimate_delivery_transaction(&payload.encode(), true, 0.into()); let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); // the fee (in This tokens) of all transactions that are made on This chain @@ -477,20 +429,8 @@ pub mod source { pub mod target { use super::*; - /// Call origin for Bridged -> This chain messages. - pub type FromBridgedChainMessageCallOrigin = bp_message_dispatch::CallOrigin< - AccountIdOf>, - SignerOf>, - SignatureOf>, - >; - /// Decoded Bridged -> This message payload. - pub type FromBridgedChainMessagePayload = bp_message_dispatch::MessagePayload< - AccountIdOf>, - SignerOf>, - SignatureOf>, - FromBridgedChainEncodedMessageCall>>, - >; + pub type FromBridgedChainMessagePayload = Vec; /// Messages proof from bridged chain: /// @@ -522,35 +462,6 @@ pub mod target { } } - /// Encoded Call of This chain as it is transferred over bridge. - /// - /// Our Call is opaque (`Vec`) for Bridged chain. So it is encoded, prefixed with - /// vector length. Custom decode implementation here is exactly to deal with this. - #[derive(Decode, Encode, RuntimeDebug, PartialEq)] - pub struct FromBridgedChainEncodedMessageCall { - encoded_call: Vec, - _marker: PhantomData, - } - - impl FromBridgedChainEncodedMessageCall { - /// Create encoded call. - pub fn new(encoded_call: Vec) -> Self { - FromBridgedChainEncodedMessageCall { encoded_call, _marker: PhantomData::default() } - } - } - - impl From> - for Result - { - fn from(encoded_call: FromBridgedChainEncodedMessageCall) -> Self { - DecodedCall::decode_with_depth_limit( - sp_api::MAX_EXTRINSIC_DEPTH, - &mut &encoded_call.encoded_call[..], - ) - .map_err(drop) - } - } - /// Dispatching Bridged -> This chain messages. #[derive(RuntimeDebug, Clone, Copy)] pub struct FromBridgedChainMessageDispatch { @@ -563,60 +474,33 @@ pub mod target { where BalanceOf>: Saturating + FixedPointOperand, ThisDispatchInstance: 'static, - ThisRuntime: pallet_bridge_dispatch::Config< - ThisDispatchInstance, - BridgeMessageId = (LaneId, MessageNonce), - > + pallet_transaction_payment::Config, + ThisRuntime: pallet_transaction_payment::Config, ::OnChargeTransaction: pallet_transaction_payment::OnChargeTransaction< ThisRuntime, Balance = BalanceOf>, >, ThisCurrency: Currency>, Balance = BalanceOf>>, - pallet_bridge_dispatch::Pallet: - bp_message_dispatch::MessageDispatch< - AccountIdOf>, - (LaneId, MessageNonce), - Message = FromBridgedChainMessagePayload, - >, { - type DispatchPayload = FromBridgedChainMessagePayload; + type DispatchPayload = FromBridgedChainMessagePayload; fn dispatch_weight( - message: &DispatchMessage>>, + _message: &DispatchMessage>>, ) -> frame_support::weights::Weight { - message.data.payload.as_ref().map(|payload| payload.weight).unwrap_or(0) + 0 } fn dispatch( - relayer_account: &AccountIdOf>, + _relayer_account: &AccountIdOf>, message: DispatchMessage>>, ) -> MessageDispatchResult { let message_id = (message.key.lane_id, message.key.nonce); - pallet_bridge_dispatch::Pallet::::dispatch( - B::BRIDGED_CHAIN_ID, - B::THIS_CHAIN_ID, - message_id, - message.data.payload.map_err(drop), - |dispatch_origin, dispatch_weight| { - let unadjusted_weight_fee = ThisRuntime::WeightToFee::calc(&dispatch_weight); - let fee_multiplier = - pallet_transaction_payment::Pallet::::next_fee_multiplier(); - let adjusted_weight_fee = - fee_multiplier.saturating_mul_int(unadjusted_weight_fee); - if !adjusted_weight_fee.is_zero() { - ThisCurrency::transfer( - dispatch_origin, - relayer_account, - adjusted_weight_fee, - ExistenceRequirement::AllowDeath, - ) - .map_err(drop) - } else { - Ok(()) - } - }, - ) + log::trace!(target: "runtime::bridge-dispatch", "Incoming message {:?}: {:?}", message_id, message.data.payload); + MessageDispatchResult { + dispatch_result: true, + unspent_weight: 0, + dispatch_fee_paid_during_dispatch: false, + } } } @@ -813,7 +697,8 @@ mod tests { const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; - const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: Weight = 2048; + const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; + const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from @@ -1016,7 +901,7 @@ mod tests { unreachable!() } - fn message_weight_limits(_message_payload: &[u8]) -> RangeInclusive { + fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { unreachable!() } @@ -1074,10 +959,9 @@ mod tests { BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE } - fn message_weight_limits(message_payload: &[u8]) -> RangeInclusive { - let begin = - std::cmp::min(BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, message_payload.len() as Weight); - begin..=BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + fn verify_dispatch_weight(message_payload: &[u8]) -> bool { + message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && + message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } fn estimate_delivery_transaction( @@ -1102,57 +986,16 @@ mod tests { OutboundLaneData::default() } - #[test] - fn message_from_bridged_chain_is_decoded() { - // the message is encoded on the bridged chain - let message_on_bridged_chain = - source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: ThisChainCall::Transfer.encode(), - } - .encode(); - - // and sent to this chain where it is decoded - let message_on_this_chain = - target::FromBridgedChainMessagePayload::::decode( - &mut &message_on_bridged_chain[..], - ) - .unwrap(); - assert_eq!( - message_on_this_chain, - target::FromBridgedChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: target::FromBridgedChainEncodedMessageCall::::new( - ThisChainCall::Transfer.encode(), - ), - } - ); - assert_eq!(Ok(ThisChainCall::Transfer), message_on_this_chain.call.into()); - } - const TEST_LANE_ID: &LaneId = b"test"; const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; - fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload - { - source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![42], - } + fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { + vec![42] } #[test] fn message_fee_is_checked_by_verifier() { - const EXPECTED_MINIMAL_FEE: u32 = 5500; + const EXPECTED_MINIMAL_FEE: u32 = 2860; // payload of the This -> Bridged chain message let payload = regular_outbound_message_payload(); @@ -1167,25 +1010,6 @@ mod tests { Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); - // let's check if estimation is less than hardcoded, if dispatch is paid at target chain - let mut payload_with_pay_on_target = regular_outbound_message_payload(); - payload_with_pay_on_target.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; - let fee_at_source = - source::estimate_message_dispatch_and_delivery_fee::( - &payload_with_pay_on_target, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ) - .expect( - "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", - ); - assert!( - fee_at_source < EXPECTED_MINIMAL_FEE.into(), - "Computed fee {:?} without prepaid dispatch must be less than the fee with prepaid dispatch {}", - fee_at_source, - EXPECTED_MINIMAL_FEE, - ); - // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( @@ -1207,80 +1031,6 @@ mod tests { .is_ok(),); } - #[test] - fn should_disallow_root_calls_from_regular_accounts() { - // payload of the This -> Bridged chain message - let payload = source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![42], - }; - - // and now check that the verifier checks the fee - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::BAD_ORIGIN) - ); - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::None)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::BAD_ORIGIN) - ); - assert!(source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(),); - } - - #[test] - fn should_verify_source_and_target_origin_matching() { - // payload of the This -> Bridged chain message - let payload = source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 100, - origin: bp_message_dispatch::CallOrigin::SourceAccount(ThisChainAccountId(1)), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![42], - }; - - // and now check that the verifier checks the fee - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(0)))), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::BAD_ORIGIN) - ); - assert!(source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Signed(ThisChainAccountId(1)))), - &ThisChainBalance(1_000_000), - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(),); - } - #[test] fn message_is_rejected_when_sent_using_disabled_lane() { assert_eq!( @@ -1315,58 +1065,42 @@ mod tests { #[test] fn verify_chain_message_rejects_message_with_too_small_declared_weight() { - assert!(source::verify_chain_message::( - &source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: 5, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![1, 2, 3, 4, 5, 6], - }, - ) + assert!(source::verify_chain_message::(&vec![ + 42; + BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT - + 1 + ]) .is_err()); } #[test] fn verify_chain_message_rejects_message_with_too_large_declared_weight() { - assert!(source::verify_chain_message::( - &source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + 1, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![1, 2, 3, 4, 5, 6], - }, - ) + assert!(source::verify_chain_message::(&vec![ + 42; + BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT - + 1 + ]) .is_err()); } #[test] fn verify_chain_message_rejects_message_too_large_message() { - assert!(source::verify_chain_message::( - &source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![0; source::maximal_message_size::() as usize + 1], - }, - ) + assert!(source::verify_chain_message::(&vec![ + 0; + source::maximal_message_size::() + as usize + 1 + ],) .is_err()); } #[test] fn verify_chain_message_accepts_maximal_message() { assert_eq!( - source::verify_chain_message::( - &source::FromThisChainMessagePayload:: { - spec_version: 1, - weight: BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT, - origin: bp_message_dispatch::CallOrigin::SourceRoot, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: vec![0; source::maximal_message_size::() as _], - }, - ), + source::verify_chain_message::(&vec![ + 0; + source::maximal_message_size::() + as _ + ],), Ok(()), ); } diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index b09a88e627959..274d2ec2e00f8 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -16,10 +16,9 @@ //! Helpers for implementing various message-related runtime API mthods. -use crate::messages::{source::FromThisChainMessagePayload, MessageBridge}; +use crate::messages::MessageBridge; use bp_messages::{LaneId, MessageDetails, MessageNonce}; -use codec::Decode; use sp_std::vec::Vec; /// Implementation of the `To*OutboundLaneApi::message_details`. @@ -37,14 +36,12 @@ where .filter_map(|nonce| { let message_data = pallet_bridge_messages::Pallet::::outbound_message_data(lane, nonce)?; - let decoded_payload = - FromThisChainMessagePayload::::decode(&mut &message_data.payload[..]).ok()?; Some(MessageDetails { nonce, - dispatch_weight: decoded_payload.weight, + dispatch_weight: 0, size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, - dispatch_fee_payment: decoded_payload.dispatch_fee_payment, + dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtTargetChain, }) }) .collect() diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 7c9f50e8ea0ce..f789bee9f7b14 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -27,13 +27,8 @@ use crate::messages::{ }; use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; -use bp_runtime::{messages::DispatchFeePayment, ChainId}; use codec::Encode; -use ed25519_dalek::{PublicKey, SecretKey, Signer, KEYPAIR_LENGTH, SECRET_KEY_LENGTH}; -use frame_support::{ - traits::Currency, - weights::{GetDispatchInfo, Weight}, -}; +use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_messages::benchmarking::{ MessageDeliveryProofParams, MessageParams, MessageProofParams, ProofSize, }; @@ -41,49 +36,16 @@ use sp_core::Hasher; use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; use sp_std::{fmt::Debug, prelude::*}; use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; -use sp_version::RuntimeVersion; - -/// Return this chain account, used to dispatch message. -pub fn dispatch_account() -> AccountIdOf> -where - B: MessageBridge, - SignerOf>: - From + IdentifyAccount>>, -{ - let this_raw_public = PublicKey::from(&dispatch_account_secret()); - let this_public: SignerOf> = - sp_core::ed25519::Public::from_raw(this_raw_public.to_bytes()).into(); - this_public.into_account() -} - -/// Return public key of this chain account, used to dispatch message. -pub fn dispatch_account_secret() -> SecretKey { - // key from the repo example (https://docs.rs/ed25519-dalek/1.0.1/ed25519_dalek/struct.SecretKey.html) - SecretKey::from_bytes(&[ - 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068, 073, - 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096, - ]) - .expect("harcoded key is valid") -} /// Prepare outbound message for the `send_message` call. pub fn prepare_outbound_message( params: MessageParams>>, -) -> FromThisChainMessagePayload +) -> FromThisChainMessagePayload where B: MessageBridge, BalanceOf>: From, { - let message_payload = vec![0; params.size as usize]; - let dispatch_origin = bp_message_dispatch::CallOrigin::SourceAccount(params.sender_account); - - FromThisChainMessagePayload:: { - spec_version: 0, - weight: params.size as _, - origin: dispatch_origin, - call: message_payload, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - } + vec![0; params.size as usize] } /// Prepare proof of messages for the `receive_messages_proof` call. @@ -92,8 +54,6 @@ where /// proof. pub fn prepare_message_proof( params: MessageProofParams, - version: &RuntimeVersion, - endow_amount: BalanceOf>, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: frame_system::Config>> @@ -115,51 +75,10 @@ where + From + IdentifyAccount>>, { - // we'll be dispatching the same call at This chain - let remark = match params.size { + let message_payload = match params.size { ProofSize::Minimal(ref size) => vec![0u8; *size as _], _ => vec![], }; - let call: CallOf> = frame_system::Call::remark { remark }.into(); - let call_weight = call.get_dispatch_info().weight; - - // message payload needs to be signed, because we use `TargetAccount` call origin - // (which is 'heaviest' to verify) - let bridged_account_id: AccountIdOf> = [0u8; 32].into(); - let (this_raw_public, this_raw_signature) = ed25519_sign( - &call, - &bridged_account_id, - version.spec_version, - B::BRIDGED_CHAIN_ID, - B::THIS_CHAIN_ID, - ); - let this_public: SignerOf> = - sp_core::ed25519::Public::from_raw(this_raw_public).into(); - let this_signature: SignatureOf> = - sp_core::ed25519::Signature::from_raw(this_raw_signature).into(); - - // if dispatch fee is paid at this chain, endow relayer account - if params.dispatch_fee_payment == DispatchFeePayment::AtTargetChain { - assert_eq!(this_public.clone().into_account(), dispatch_account::()); - pallet_balances::Pallet::::make_free_balance_be( - &this_public.clone().into_account(), - endow_amount, - ); - } - - // prepare message payload that is stored in the Bridged chain storage - let message_payload = bp_message_dispatch::MessagePayload { - spec_version: version.spec_version, - weight: call_weight, - origin: bp_message_dispatch::CallOrigin::< - AccountIdOf>, - SignerOf>, - SignatureOf>, - >::TargetAccount(bridged_account_id, this_public, this_signature), - dispatch_fee_payment: params.dispatch_fee_payment.clone(), - call: call.encode(), - } - .encode(); // finally - prepare storage proof and update environment let (state_root, storage_proof) = @@ -174,11 +93,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - call_weight - .checked_mul( - params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1, - ) - .expect("too many messages requested by benchmark"), + 0, ) } @@ -312,40 +227,6 @@ where bridged_header_hash } -/// Generate ed25519 signature to be used in -/// `pallet_brdige_call_dispatch::CallOrigin::TargetAccount`. -/// -/// Returns public key of the signer and the signature itself. -fn ed25519_sign( - target_call: &impl Encode, - source_account_id: &impl Encode, - target_spec_version: u32, - source_chain_id: ChainId, - target_chain_id: ChainId, -) -> ([u8; 32], [u8; 64]) { - let target_secret = dispatch_account_secret(); - let target_public: PublicKey = (&target_secret).into(); - - let mut target_pair_bytes = [0u8; KEYPAIR_LENGTH]; - target_pair_bytes[..SECRET_KEY_LENGTH].copy_from_slice(&target_secret.to_bytes()); - target_pair_bytes[SECRET_KEY_LENGTH..].copy_from_slice(&target_public.to_bytes()); - let target_pair = - ed25519_dalek::Keypair::from_bytes(&target_pair_bytes).expect("hardcoded pair is valid"); - - let signature_message = pallet_bridge_dispatch::account_ownership_digest( - target_call, - source_account_id, - target_spec_version, - source_chain_id, - target_chain_id, - ); - let target_origin_signature = target_pair - .try_sign(&signature_message) - .expect("Ed25519 try_sign should not fail in benchmarks"); - - (target_public.to_bytes(), target_origin_signature.to_bytes()) -} - /// Populate trie with dummy keys+values until trie has at least given size. fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: ProofSize) -> H::Out { let (iterations, leaf_size, minimal_trie_size) = match trie_size { diff --git a/modules/dispatch/Cargo.toml b/modules/dispatch/Cargo.toml deleted file mode 100644 index c2e8c74da828d..0000000000000 --- a/modules/dispatch/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "pallet-bridge-dispatch" -description = "A Substrate Runtime module that dispatches a bridge message, treating it simply as encoded Call" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } - -# Bridge dependencies - -bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } - -[features] -default = ["std"] -std = [ - "bp-message-dispatch/std", - "bp-runtime/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/modules/dispatch/README.md b/modules/dispatch/README.md deleted file mode 100644 index 068ff1167f7d8..0000000000000 --- a/modules/dispatch/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# Call Dispatch Module - -The call dispatch module has a single internal (only callable by other runtime modules) entry point -for dispatching encoded calls (`pallet_bridge_dispatch::Module::dispatch`). Every dispatch -(successful or not) emits a corresponding module event. The module doesn't have any call-related -requirements - they may come from the bridged chain over some message lane, or they may be crafted -locally. But in this document we'll mostly talk about this module in the context of bridges. - -Every message that is being dispatched has three main characteristics: -- `bridge` is the 4-bytes identifier of the bridge where this message comes from. This may be the - identifier of the bridged chain (like `b"rlto"` for messages coming from `Rialto`), or the - identifier of the bridge itself (`b"rimi"` for `Rialto` <-> `Millau` bridge); -- `id` is the unique id of the message within the given bridge. For messages coming from the - [messages module](../messages/README.md), it may worth to use a tuple - `(LaneId, MessageNonce)` to identify a message; -- `message` is the `bp_message_dispatch::MessagePayload` structure. The `call` field is set - to the (potentially) encoded `Call` of this chain. - -The easiest way to understand what is happening when a `Call` is being dispatched, is to look at the -module events set: - -- `MessageRejected` event is emitted if a message has been rejected even before it has reached the - module. Dispatch then is called just to reflect the fact that message has been received, but we - have failed to pre-process it (e.g. because we have failed to decode `MessagePayload` structure - from the proof); -- `MessageVersionSpecMismatch` event is emitted if current runtime specification version differs - from the version that has been used to encode the `Call`. The message payload has the - `spec_version`, that is filled by the message submitter. If this value differs from the current - runtime version, dispatch mechanism rejects to dispatch the message. Without this check, we may - decode the wrong `Call` for example if method arguments were changed; -- `MessageCallDecodeFailed` event is emitted if we have failed to decode `Call` from the payload. - This may happen if the submitter has provided incorrect value in the `call` field, or if source - chain storage has been corrupted. The `Call` is decoded after `spec_version` check, so we'll never - try to decode `Call` from other runtime version; -- `MessageSignatureMismatch` event is emitted if submitter has chose to dispatch message using - specified this chain account (`bp_message_dispatch::CallOrigin::TargetAccount` origin), - but he has failed to prove that he owns the private key for this account; -- `MessageCallRejected` event is emitted if the module has been deployed with some call filter and - this filter has rejected the `Call`. In your bridge you may choose to reject all messages except - e.g. balance transfer calls; -- `MessageWeightMismatch` event is emitted if the message submitter has specified invalid `Call` - dispatch weight in the `weight` field of the message payload. The value of this field is compared - to the pre-dispatch weight of the decoded `Call`. If it is less than the actual pre-dispatch - weight, the dispatch is rejected. Keep in mind, that even if post-dispatch weight will be less - than specified, the submitter still have to declare (and pay for) the maximal possible weight - (that is the pre-dispatch weight); -- `MessageDispatchPaymentFailed` event is emitted if the message submitter has selected to pay - dispatch fee at the target chain, but has failed to do that; -- `MessageDispatched` event is emitted if the message has passed all checks and we have actually - dispatched it. The dispatch may still fail, though - that's why we are including the dispatch - result in the event payload. - -When we talk about module in context of bridges, these events are helping in following cases: - -1. when the message submitter has access to the state of both chains and wants to monitor what has - happened with his message. Then he could use the message id (that he gets from the - [messages module events](../messages/README.md#General-Information)) to filter events of - call dispatch module at the target chain and actually see what has happened with his message; - -1. when the message submitter only has access to the source chain state (for example, when sender is - the runtime module at the source chain). In this case, your bridge may have additional mechanism - to deliver dispatch proofs (which are storage proof of module events) back to the source chain, - thus allowing the submitter to see what has happened with his messages. diff --git a/modules/dispatch/src/lib.rs b/modules/dispatch/src/lib.rs deleted file mode 100644 index 1e030b7332059..0000000000000 --- a/modules/dispatch/src/lib.rs +++ /dev/null @@ -1,1084 +0,0 @@ -// 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 . - -//! Runtime module which takes care of dispatching messages received over the bridge. -//! -//! The messages are interpreted directly as runtime `Call`. We attempt to decode -//! them and then dispatch as usual. To prevent compatibility issues, the Calls have -//! to include a `spec_version`. This will be checked before dispatch. In the case of -//! a successful dispatch an event is emitted. - -#![cfg_attr(not(feature = "std"), no_std)] -// Generated by `decl_event!` -#![allow(clippy::unused_unit)] - -use bp_message_dispatch::{CallOrigin, MessageDispatch, MessagePayload, SpecVersion}; -use bp_runtime::{ - derive_account_id, - messages::{DispatchFeePayment, MessageDispatchResult}, - ChainId, SourceAccount, -}; -use codec::Encode; -use frame_support::{ - dispatch::Dispatchable, - ensure, - traits::{Contains, Get}, - weights::{extract_actual_weight, GetDispatchInfo}, -}; -use frame_system::RawOrigin; -use sp_runtime::traits::{BadOrigin, Convert, IdentifyAccount, MaybeDisplay, Verify}; -use sp_std::{fmt::Debug, prelude::*}; - -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type. - type Event: From> + IsType<::Event>; - /// Id of the message. Whenever message is passed to the dispatch module, it emits - /// event with this id + dispatch result. Could be e.g. (LaneId, MessageNonce) if - /// it comes from the messages module. - type BridgeMessageId: Parameter; - /// Type of account ID on source chain. - type SourceChainAccountId: Parameter - + Member - + MaybeSerializeDeserialize - + Debug - + MaybeDisplay - + Ord; - /// Type of account public key on target chain. - type TargetChainAccountPublic: Parameter + IdentifyAccount; - /// Type of signature that may prove that the message has been signed by - /// owner of `TargetChainAccountPublic`. - type TargetChainSignature: Parameter + Verify; - /// The overarching dispatch call type. - type Call: Parameter - + GetDispatchInfo - + Dispatchable< - Origin = ::Origin, - PostInfo = frame_support::dispatch::PostDispatchInfo, - >; - /// Pre-dispatch filter for incoming calls. - /// - /// The pallet will filter all incoming calls right before they're dispatched. If this - /// filter rejects the call, special event (`Event::MessageCallRejected`) is emitted. - type CallFilter: Contains<>::Call>; - /// The type that is used to wrap the `Self::Call` when it is moved over bridge. - /// - /// The idea behind this is to avoid `Call` conversion/decoding until we'll be sure - /// that all other stuff (like `spec_version`) is ok. If we would try to decode - /// `Call` which has been encoded using previous `spec_version`, then we might end - /// up with decoding error, instead of `MessageVersionSpecMismatch`. - type EncodedCall: Decode + Encode + Into>::Call, ()>>; - /// A type which can be turned into an AccountId from a 256-bit hash. - /// - /// Used when deriving target chain AccountIds from source chain AccountIds. - type AccountIdConverter: sp_runtime::traits::Convert; - } - - type BridgeMessageIdOf = >::BridgeMessageId; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(PhantomData<(T, I)>); - - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet {} - - #[pallet::call] - impl, I: 'static> Pallet {} - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event, I: 'static = ()> { - /// Message has been rejected before reaching dispatch. - MessageRejected(ChainId, BridgeMessageIdOf), - /// Message has been rejected by dispatcher because of spec version mismatch. - /// Last two arguments are: expected and passed spec version. - MessageVersionSpecMismatch(ChainId, BridgeMessageIdOf, SpecVersion, SpecVersion), - /// Message has been rejected by dispatcher because of weight mismatch. - /// Last two arguments are: expected and passed call weight. - MessageWeightMismatch(ChainId, BridgeMessageIdOf, Weight, Weight), - /// Message signature mismatch. - MessageSignatureMismatch(ChainId, BridgeMessageIdOf), - /// We have failed to decode Call from the message. - MessageCallDecodeFailed(ChainId, BridgeMessageIdOf), - /// The call from the message has been rejected by the call filter. - MessageCallRejected(ChainId, BridgeMessageIdOf), - /// The origin account has failed to pay fee for dispatching the message. - MessageDispatchPaymentFailed( - ChainId, - BridgeMessageIdOf, - ::AccountId, - Weight, - ), - /// Message has been dispatched with given result. - MessageDispatched(ChainId, BridgeMessageIdOf, DispatchResult), - /// Phantom member, never used. Needed to handle multiple pallet instances. - _Dummy(PhantomData), - } -} - -impl, I: 'static> MessageDispatch for Pallet { - type Message = MessagePayload< - T::SourceChainAccountId, - T::TargetChainAccountPublic, - T::TargetChainSignature, - T::EncodedCall, - >; - - fn dispatch_weight(message: &Self::Message) -> bp_message_dispatch::Weight { - message.weight - } - - fn dispatch Result<(), ()>>( - source_chain: ChainId, - target_chain: ChainId, - id: T::BridgeMessageId, - message: Result, - pay_dispatch_fee: P, - ) -> MessageDispatchResult { - // emit special even if message has been rejected by external component - let message = match message { - Ok(message) => message, - Err(_) => { - log::trace!( - target: "runtime::bridge-dispatch", - "Message {:?}/{:?}: rejected before actual dispatch", - source_chain, - id, - ); - Self::deposit_event(Event::MessageRejected(source_chain, id)); - return MessageDispatchResult { - dispatch_result: false, - unspent_weight: 0, - dispatch_fee_paid_during_dispatch: false, - } - }, - }; - - // verify spec version - // (we want it to be the same, because otherwise we may decode Call improperly) - let mut dispatch_result = MessageDispatchResult { - dispatch_result: false, - unspent_weight: message.weight, - dispatch_fee_paid_during_dispatch: false, - }; - let expected_version = ::Version::get().spec_version; - if message.spec_version != expected_version { - log::trace!( - "Message {:?}/{:?}: spec_version mismatch. Expected {:?}, got {:?}", - source_chain, - id, - expected_version, - message.spec_version, - ); - Self::deposit_event(Event::MessageVersionSpecMismatch( - source_chain, - id, - expected_version, - message.spec_version, - )); - return dispatch_result - } - - // now that we have spec version checked, let's decode the call - let call = match message.call.into() { - Ok(call) => call, - Err(_) => { - log::trace!( - target: "runtime::bridge-dispatch", - "Failed to decode Call from message {:?}/{:?}", - source_chain, - id, - ); - Self::deposit_event(Event::MessageCallDecodeFailed(source_chain, id)); - return dispatch_result - }, - }; - - // prepare dispatch origin - let origin_account = match message.origin { - CallOrigin::SourceRoot => { - let hex_id = - derive_account_id::(source_chain, SourceAccount::Root); - let target_id = T::AccountIdConverter::convert(hex_id); - log::trace!(target: "runtime::bridge-dispatch", "Root Account: {:?}", &target_id); - target_id - }, - CallOrigin::TargetAccount(source_account_id, target_public, target_signature) => { - let digest = account_ownership_digest( - &call, - source_account_id, - message.spec_version, - source_chain, - target_chain, - ); - - let target_account = target_public.into_account(); - if !target_signature.verify(&digest[..], &target_account) { - log::trace!( - target: "runtime::bridge-dispatch", - "Message {:?}/{:?}: origin proof is invalid. Expected account: {:?} from signature: {:?}", - source_chain, - id, - target_account, - target_signature, - ); - Self::deposit_event(Event::MessageSignatureMismatch(source_chain, id)); - return dispatch_result - } - - log::trace!(target: "runtime::bridge-dispatch", "Target Account: {:?}", &target_account); - target_account - }, - CallOrigin::SourceAccount(source_account_id) => { - let hex_id = - derive_account_id(source_chain, SourceAccount::Account(source_account_id)); - let target_id = T::AccountIdConverter::convert(hex_id); - log::trace!(target: "runtime::bridge-dispatch", "Source Account: {:?}", &target_id); - target_id - }, - }; - - // filter the call - if !T::CallFilter::contains(&call) { - log::trace!( - target: "runtime::bridge-dispatch", - "Message {:?}/{:?}: the call ({:?}) is rejected by filter", - source_chain, - id, - call, - ); - Self::deposit_event(Event::MessageCallRejected(source_chain, id)); - return dispatch_result - } - - // verify weight - // (we want passed weight to be at least equal to pre-dispatch weight of the call - // because otherwise Calls may be dispatched at lower price) - let dispatch_info = call.get_dispatch_info(); - let expected_weight = dispatch_info.weight; - if message.weight < expected_weight { - log::trace!( - target: "runtime::bridge-dispatch", - "Message {:?}/{:?}: passed weight is too low. Expected at least {:?}, got {:?}", - source_chain, - id, - expected_weight, - message.weight, - ); - Self::deposit_event(Event::MessageWeightMismatch( - source_chain, - id, - expected_weight, - message.weight, - )); - return dispatch_result - } - - // pay dispatch fee right before dispatch - let pay_dispatch_fee_at_target_chain = - message.dispatch_fee_payment == DispatchFeePayment::AtTargetChain; - if pay_dispatch_fee_at_target_chain && - pay_dispatch_fee(&origin_account, message.weight).is_err() - { - log::trace!( - target: "runtime::bridge-dispatch", - "Failed to pay dispatch fee for dispatching message {:?}/{:?} with weight {}", - source_chain, - id, - message.weight, - ); - Self::deposit_event(Event::MessageDispatchPaymentFailed( - source_chain, - id, - origin_account, - message.weight, - )); - return dispatch_result - } - dispatch_result.dispatch_fee_paid_during_dispatch = pay_dispatch_fee_at_target_chain; - - // finally dispatch message - let origin = RawOrigin::Signed(origin_account).into(); - - log::trace!(target: "runtime::bridge-dispatch", "Message being dispatched is: {:.4096?}", &call); - let result = call.dispatch(origin); - let actual_call_weight = extract_actual_weight(&result, &dispatch_info); - dispatch_result.dispatch_result = result.is_ok(); - dispatch_result.unspent_weight = message.weight.saturating_sub(actual_call_weight); - - log::trace!( - target: "runtime::bridge-dispatch", - "Message {:?}/{:?} has been dispatched. Weight: {} of {}. Result: {:?}. Call dispatch result: {:?}", - source_chain, - id, - actual_call_weight, - message.weight, - dispatch_result, - result, - ); - - Self::deposit_event(Event::MessageDispatched( - source_chain, - id, - result.map(drop).map_err(|e| e.error), - )); - - dispatch_result - } -} - -/// Check if the message is allowed to be dispatched on the target chain given the sender's origin -/// on the source chain. -/// -/// For example, if a message is sent from a "regular" account on the source chain it will not be -/// allowed to be dispatched as Root on the target chain. This is a useful check to do on the source -/// chain _before_ sending a message whose dispatch will be rejected on the target chain. -pub fn verify_message_origin< - SourceChainAccountId, - TargetChainAccountPublic, - TargetChainSignature, - Call, ->( - sender_origin: &RawOrigin, - message: &MessagePayload< - SourceChainAccountId, - TargetChainAccountPublic, - TargetChainSignature, - Call, - >, -) -> Result, BadOrigin> -where - SourceChainAccountId: PartialEq + Clone, -{ - match message.origin { - CallOrigin::SourceRoot => { - ensure!(sender_origin == &RawOrigin::Root, BadOrigin); - Ok(None) - }, - CallOrigin::TargetAccount(ref source_account_id, _, _) => { - ensure!(sender_origin == &RawOrigin::Signed(source_account_id.clone()), BadOrigin); - Ok(Some(source_account_id.clone())) - }, - CallOrigin::SourceAccount(ref source_account_id) => { - ensure!( - sender_origin == &RawOrigin::Signed(source_account_id.clone()) || - sender_origin == &RawOrigin::Root, - BadOrigin - ); - Ok(Some(source_account_id.clone())) - }, - } -} - -/// Target account ownership digest from the source chain. -/// -/// The byte vector returned by this function will be signed with a target chain account -/// private key. This way, the owner of `source_account_id` on the source chain proves that -/// the target chain account private key is also under his control. -pub fn account_ownership_digest( - call: &Call, - source_account_id: AccountId, - target_spec_version: SpecVersion, - source_chain_id: ChainId, - target_chain_id: ChainId, -) -> Vec -where - Call: Encode, - AccountId: Encode, - SpecVersion: Encode, -{ - let mut proof = Vec::new(); - call.encode_to(&mut proof); - source_account_id.encode_to(&mut proof); - target_spec_version.encode_to(&mut proof); - source_chain_id.encode_to(&mut proof); - target_chain_id.encode_to(&mut proof); - - proof -} - -#[cfg(test)] -mod tests { - // From construct_runtime macro - #![allow(clippy::from_over_into)] - - use super::*; - use codec::Decode; - use frame_support::{parameter_types, weights::Weight}; - use frame_system::{EventRecord, Phase}; - use scale_info::TypeInfo; - use sp_core::H256; - use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, - }; - - type AccountId = u64; - type BridgeMessageId = [u8; 4]; - - const SOURCE_CHAIN_ID: ChainId = *b"srce"; - const TARGET_CHAIN_ID: ChainId = *b"trgt"; - - #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] - pub struct TestAccountPublic(AccountId); - - impl IdentifyAccount for TestAccountPublic { - type AccountId = AccountId; - - fn into_account(self) -> AccountId { - self.0 - } - } - - #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] - pub struct TestSignature(AccountId); - - impl Verify for TestSignature { - type Signer = TestAccountPublic; - - fn verify>(&self, _msg: L, signer: &AccountId) -> bool { - self.0 == *signer - } - } - - pub struct AccountIdConverter; - - impl sp_runtime::traits::Convert for AccountIdConverter { - fn convert(hash: H256) -> AccountId { - hash.to_low_u64_ne() - } - } - - type Block = frame_system::mocking::MockBlock; - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - - use crate as call_dispatch; - - frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Dispatch: call_dispatch::{Pallet, Call, Event}, - } - } - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl frame_system::Config for TestRuntime { - type Origin = Origin; - type Index = u64; - type Call = Call; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - - impl Config for TestRuntime { - type Event = Event; - type BridgeMessageId = BridgeMessageId; - type SourceChainAccountId = AccountId; - type TargetChainAccountPublic = TestAccountPublic; - type TargetChainSignature = TestSignature; - type Call = Call; - type CallFilter = TestCallFilter; - type EncodedCall = EncodedCall; - type AccountIdConverter = AccountIdConverter; - } - - #[derive(Decode, Encode)] - pub struct EncodedCall(Vec); - - impl From for Result { - fn from(call: EncodedCall) -> Result { - Call::decode(&mut &call.0[..]).map_err(drop) - } - } - - pub struct TestCallFilter; - - impl Contains for TestCallFilter { - fn contains(call: &Call) -> bool { - !matches!(*call, Call::System(frame_system::Call::fill_block { .. })) - } - } - - const TEST_SPEC_VERSION: SpecVersion = 0; - const TEST_WEIGHT: Weight = 1_000_000_000; - - fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - sp_io::TestExternalities::new(t) - } - - fn prepare_message( - origin: CallOrigin, - call: Call, - ) -> as MessageDispatch< - AccountId, - ::BridgeMessageId, - >>::Message { - MessagePayload { - spec_version: TEST_SPEC_VERSION, - weight: TEST_WEIGHT, - origin, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - call: EncodedCall(call.encode()), - } - } - - fn prepare_root_message( - call: Call, - ) -> as MessageDispatch< - AccountId, - ::BridgeMessageId, - >>::Message { - prepare_message(CallOrigin::SourceRoot, call) - } - - fn prepare_target_message( - call: Call, - ) -> as MessageDispatch< - AccountId, - ::BridgeMessageId, - >>::Message { - let origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(1)); - prepare_message(origin, call) - } - - fn prepare_source_message( - call: Call, - ) -> as MessageDispatch< - AccountId, - ::BridgeMessageId, - >>::Message { - let origin = CallOrigin::SourceAccount(1); - prepare_message(origin, call) - } - - #[test] - fn should_fail_on_spec_version_mismatch() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - const BAD_SPEC_VERSION: SpecVersion = 99; - let mut message = prepare_root_message(Call::System(frame_system::Call::remark { - remark: vec![1, 2, 3], - })); - let weight = message.weight; - message.spec_version = BAD_SPEC_VERSION; - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert_eq!(result.unspent_weight, weight); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch( - call_dispatch::Event::::MessageVersionSpecMismatch( - SOURCE_CHAIN_ID, - id, - TEST_SPEC_VERSION, - BAD_SPEC_VERSION - ) - ), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_fail_on_weight_mismatch() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - let call = Call::System(frame_system::Call::set_heap_pages { pages: 42 }); - let call_weight = call.get_dispatch_info().weight; - let mut message = prepare_root_message(call); - message.weight = 7; - assert!(call_weight > 7, "needed for test to actually trigger a weight mismatch"); - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert_eq!(result.unspent_weight, 7); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch( - call_dispatch::Event::::MessageWeightMismatch( - SOURCE_CHAIN_ID, - id, - call_weight, - 7, - ) - ), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_fail_on_signature_mismatch() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let call_origin = CallOrigin::TargetAccount(1, TestAccountPublic(1), TestSignature(99)); - let message = prepare_message( - call_origin, - Call::System(frame_system::Call::remark { remark: vec![1, 2, 3] }), - ); - let weight = message.weight; - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert_eq!(result.unspent_weight, weight); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch( - call_dispatch::Event::::MessageSignatureMismatch( - SOURCE_CHAIN_ID, - id - ) - ), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_emit_event_for_rejected_messages() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - System::set_block_number(1); - Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Err(()), - |_, _| unreachable!(), - ); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageRejected( - SOURCE_CHAIN_ID, - id - )), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_fail_on_call_decode() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let mut message = prepare_root_message(Call::System(frame_system::Call::remark { - remark: vec![1, 2, 3], - })); - let weight = message.weight; - message.call.0 = vec![]; - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert_eq!(result.unspent_weight, weight); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch( - call_dispatch::Event::::MessageCallDecodeFailed( - SOURCE_CHAIN_ID, - id - ) - ), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_emit_event_for_rejected_calls() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let call = - Call::System(frame_system::Call::fill_block { ratio: Perbill::from_percent(75) }); - let weight = call.get_dispatch_info().weight; - let mut message = prepare_root_message(call); - message.weight = weight; - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert_eq!(result.unspent_weight, weight); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch( - call_dispatch::Event::::MessageCallRejected( - SOURCE_CHAIN_ID, - id - ) - ), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_emit_event_for_unpaid_calls() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let mut message = prepare_root_message(Call::System(frame_system::Call::remark { - remark: vec![1, 2, 3], - })); - let weight = message.weight; - message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; - - System::set_block_number(1); - let result = - Dispatch::dispatch(SOURCE_CHAIN_ID, TARGET_CHAIN_ID, id, Ok(message), |_, _| { - Err(()) - }); - assert_eq!(result.unspent_weight, weight); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch( - call_dispatch::Event::::MessageDispatchPaymentFailed( - SOURCE_CHAIN_ID, - id, - AccountIdConverter::convert(derive_account_id::( - SOURCE_CHAIN_ID, - SourceAccount::Root - )), - TEST_WEIGHT, - ) - ), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_dispatch_calls_paid_at_target_chain() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let mut message = prepare_root_message(Call::System(frame_system::Call::remark { - remark: vec![1, 2, 3], - })); - message.dispatch_fee_payment = DispatchFeePayment::AtTargetChain; - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| Ok(()), - ); - assert!(result.dispatch_fee_paid_during_dispatch); - assert!(result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( - SOURCE_CHAIN_ID, - id, - Ok(()) - )), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_return_dispatch_failed_flag_if_dispatch_happened_but_failed() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let call = Call::System(frame_system::Call::set_heap_pages { pages: 1 }); - let message = prepare_target_message(call); - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert!(!result.dispatch_fee_paid_during_dispatch); - assert!(!result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( - SOURCE_CHAIN_ID, - id, - Err(sp_runtime::DispatchError::BadOrigin) - )), - topics: vec![], - }], - ); - }) - } - - #[test] - fn should_dispatch_bridge_message_from_root_origin() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - let message = prepare_root_message(Call::System(frame_system::Call::remark { - remark: vec![1, 2, 3], - })); - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert!(!result.dispatch_fee_paid_during_dispatch); - assert!(result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( - SOURCE_CHAIN_ID, - id, - Ok(()) - )), - topics: vec![], - }], - ); - }); - } - - #[test] - fn should_dispatch_bridge_message_from_target_origin() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let call = Call::System(frame_system::Call::remark { remark: vec![] }); - let message = prepare_target_message(call); - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert!(!result.dispatch_fee_paid_during_dispatch); - assert!(result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( - SOURCE_CHAIN_ID, - id, - Ok(()) - )), - topics: vec![], - }], - ); - }) - } - - #[test] - fn should_dispatch_bridge_message_from_source_origin() { - new_test_ext().execute_with(|| { - let id = [0; 4]; - - let call = Call::System(frame_system::Call::remark { remark: vec![] }); - let message = prepare_source_message(call); - - System::set_block_number(1); - let result = Dispatch::dispatch( - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - id, - Ok(message), - |_, _| unreachable!(), - ); - assert!(!result.dispatch_fee_paid_during_dispatch); - assert!(result.dispatch_result); - - assert_eq!( - System::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: Event::Dispatch(call_dispatch::Event::::MessageDispatched( - SOURCE_CHAIN_ID, - id, - Ok(()) - )), - topics: vec![], - }], - ); - }) - } - - #[test] - fn origin_is_checked_when_verifying_sending_message_using_source_root_account() { - let call = Call::System(frame_system::Call::remark { remark: vec![] }); - let message = prepare_root_message(call); - - // When message is sent by Root, CallOrigin::SourceRoot is allowed - assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(None))); - - // when message is sent by some real account, CallOrigin::SourceRoot is not allowed - assert!(matches!(verify_message_origin(&RawOrigin::Signed(1), &message), Err(BadOrigin))); - } - - #[test] - fn origin_is_checked_when_verifying_sending_message_using_target_account() { - let call = Call::System(frame_system::Call::remark { remark: vec![] }); - let message = prepare_target_message(call); - - // When message is sent by Root, CallOrigin::TargetAccount is not allowed - assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Err(BadOrigin))); - - // When message is sent by some other account, it is rejected - assert!(matches!(verify_message_origin(&RawOrigin::Signed(2), &message), Err(BadOrigin))); - - // When message is sent by a real account, it is allowed to have origin - // CallOrigin::TargetAccount - assert!(matches!(verify_message_origin(&RawOrigin::Signed(1), &message), Ok(Some(1)))); - } - - #[test] - fn origin_is_checked_when_verifying_sending_message_using_source_account() { - let call = Call::System(frame_system::Call::remark { remark: vec![] }); - let message = prepare_source_message(call); - - // Sending a message from the expected origin account works - assert!(matches!(verify_message_origin(&RawOrigin::Signed(1), &message), Ok(Some(1)))); - - // If we send a message from a different account, it is rejected - assert!(matches!(verify_message_origin(&RawOrigin::Signed(2), &message), Err(BadOrigin))); - - // The Root account is allowed to assume any expected origin account - assert!(matches!(verify_message_origin(&RawOrigin::Root, &message), Ok(Some(1)))); - } -} diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index eaacf2aeb45f1..47d41dba17604 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -16,7 +16,6 @@ serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies -bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } @@ -36,7 +35,6 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m [features] default = ["std"] std = [ - "bp-message-dispatch/std", "bp-messages/std", "bp-runtime/std", "codec/std", diff --git a/modules/token-swap/Cargo.toml b/modules/token-swap/Cargo.toml deleted file mode 100644 index d3a60d3472902..0000000000000 --- a/modules/token-swap/Cargo.toml +++ /dev/null @@ -1,59 +0,0 @@ -[package] -name = "pallet-bridge-token-swap" -description = "An Substrate pallet that allows parties on different chains (bridged using messages pallet) to swap their tokens" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } - -# Bridge dependencies - -bp-message-dispatch = { path = "../../primitives/message-dispatch", default-features = false } -bp-messages = { path = "../../primitives/messages", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } -bp-token-swap = { path = "../../primitives/token-swap", default-features = false } -pallet-bridge-dispatch = { path = "../dispatch", default-features = false } -pallet-bridge-messages = { path = "../messages", default-features = false } - -# Substrate Dependencies - -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[dev-dependencies] -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } - -[features] -default = ["std"] -std = [ - "codec/std", - "bp-message-dispatch/std", - "bp-messages/std", - "bp-runtime/std", - "bp-token-swap/std", - "frame-support/std", - "frame-system/std", - "log/std", - "pallet-bridge-dispatch/std", - "pallet-bridge-messages/std", - "scale-info/std", - "serde", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", -] diff --git a/modules/token-swap/src/benchmarking.rs b/modules/token-swap/src/benchmarking.rs deleted file mode 100644 index 878cb20993a9d..0000000000000 --- a/modules/token-swap/src/benchmarking.rs +++ /dev/null @@ -1,198 +0,0 @@ -// 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 . - -//! Token-swap pallet benchmarking. - -use crate::{ - swap_account_id, target_account_at_this_chain, BridgedAccountIdOf, BridgedAccountPublicOf, - BridgedAccountSignatureOf, BridgedBalanceOf, Call, Origin, Pallet, ThisChainBalance, - TokenSwapCreationOf, TokenSwapOf, -}; - -use bp_token_swap::{TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType}; -use codec::{Decode, Encode}; -use frame_benchmarking::{account, benchmarks_instance_pallet}; -use frame_support::{traits::Currency, Parameter}; -use frame_system::RawOrigin; -use sp_core::H256; -use sp_io::hashing::blake2_256; -use sp_runtime::traits::{Bounded, TrailingZeroInput}; -use sp_std::{boxed::Box, vec::Vec}; - -const SEED: u32 = 0; - -/// Trait that must be implemented by runtime. -pub trait Config: crate::Config { - /// Initialize environment for token swap. - fn initialize_environment(); -} - -benchmarks_instance_pallet! { - where_clause { - where - Origin: Into, - BridgedAccountPublicOf: Decode + Parameter, - BridgedAccountSignatureOf: Decode, - } - - // - // Benchmarks that are used directly by the runtime. - // - - // Benchmark `create_swap` extrinsic. - // - // This benchmark assumes that message is **NOT** actually sent. Instead we're using `send_message_weight` - // from the `WeightInfoExt` trait. - // - // There aren't any factors that affect `create_swap` performance, so everything - // is straightforward here. - create_swap { - T::initialize_environment(); - - let sender = funded_account::("source_account_at_this_chain", 0); - let swap: TokenSwapOf = test_swap::(sender.clone(), true); - let swap_creation: TokenSwapCreationOf = test_swap_creation::(); - }: create_swap( - RawOrigin::Signed(sender.clone()), - swap, - Box::new(swap_creation) - ) - verify { - assert!(crate::PendingSwaps::::contains_key(test_swap_hash::(sender, true))); - } - - // Benchmark `claim_swap` extrinsic with the worst possible conditions: - // - // * swap is locked until some block, so current block number is read. - claim_swap { - T::initialize_environment(); - - let sender: T::AccountId = account("source_account_at_this_chain", 0, SEED); - crate::PendingSwaps::::insert( - test_swap_hash::(sender.clone(), false), - TokenSwapState::Confirmed, - ); - - let swap: TokenSwapOf = test_swap::(sender.clone(), false); - let claimer = target_account_at_this_chain::(&swap); - let token_swap_account = swap_account_id::(&swap); - T::ThisCurrency::make_free_balance_be(&token_swap_account, ThisChainBalance::::max_value()); - }: claim_swap(RawOrigin::Signed(claimer), swap) - verify { - assert!(!crate::PendingSwaps::::contains_key(test_swap_hash::(sender, false))); - } - - // Benchmark `cancel_swap` extrinsic with the worst possible conditions: - // - // * swap is locked until some block, so current block number is read. - cancel_swap { - T::initialize_environment(); - - let sender: T::AccountId = account("source_account_at_this_chain", 0, SEED); - crate::PendingSwaps::::insert( - test_swap_hash::(sender.clone(), false), - TokenSwapState::Failed, - ); - - let swap: TokenSwapOf = test_swap::(sender.clone(), false); - let token_swap_account = swap_account_id::(&swap); - T::ThisCurrency::make_free_balance_be(&token_swap_account, ThisChainBalance::::max_value()); - - }: cancel_swap(RawOrigin::Signed(sender.clone()), swap) - verify { - assert!(!crate::PendingSwaps::::contains_key(test_swap_hash::(sender, false))); - } -} - -/// Returns test token swap. -fn test_swap, I: 'static>(sender: T::AccountId, is_create: bool) -> TokenSwapOf { - TokenSwap { - swap_type: TokenSwapType::LockClaimUntilBlock( - if is_create { 10u32.into() } else { 0u32.into() }, - 0.into(), - ), - source_balance_at_this_chain: source_balance_to_swap::(), - source_account_at_this_chain: sender, - target_balance_at_bridged_chain: target_balance_to_swap::(), - target_account_at_bridged_chain: target_account_at_bridged_chain::(), - } -} - -/// Returns test token swap hash. -fn test_swap_hash, I: 'static>(sender: T::AccountId, is_create: bool) -> H256 { - test_swap::(sender, is_create).using_encoded(blake2_256).into() -} - -/// Returns test token swap creation params. -fn test_swap_creation, I: 'static>() -> TokenSwapCreationOf -where - BridgedAccountPublicOf: Decode, - BridgedAccountSignatureOf: Decode, -{ - TokenSwapCreation { - target_public_at_bridged_chain: target_public_at_bridged_chain::(), - swap_delivery_and_dispatch_fee: swap_delivery_and_dispatch_fee::(), - bridged_chain_spec_version: 0, - bridged_currency_transfer: Vec::new(), - bridged_currency_transfer_weight: 0, - bridged_currency_transfer_signature: bridged_currency_transfer_signature::(), - } -} - -/// Account that has some balance. -fn funded_account, I: 'static>(name: &'static str, index: u32) -> T::AccountId { - let account: T::AccountId = account(name, index, SEED); - T::ThisCurrency::make_free_balance_be(&account, ThisChainBalance::::max_value()); - account -} - -/// Currency transfer message fee. -fn swap_delivery_and_dispatch_fee, I: 'static>() -> ThisChainBalance { - ThisChainBalance::::max_value() / 4u32.into() -} - -/// Balance at the source chain that we're going to swap. -fn source_balance_to_swap, I: 'static>() -> ThisChainBalance { - ThisChainBalance::::max_value() / 2u32.into() -} - -/// Balance at the target chain that we're going to swap. -fn target_balance_to_swap, I: 'static>() -> BridgedBalanceOf { - BridgedBalanceOf::::max_value() / 2u32.into() -} - -/// Public key of `target_account_at_bridged_chain`. -fn target_public_at_bridged_chain, I: 'static>() -> BridgedAccountPublicOf -where - BridgedAccountPublicOf: Decode, -{ - BridgedAccountPublicOf::::decode(&mut TrailingZeroInput::zeroes()) - .expect("failed to decode `BridgedAccountPublicOf` from zeroes") -} - -/// Signature of `target_account_at_bridged_chain` over message. -fn bridged_currency_transfer_signature, I: 'static>() -> BridgedAccountSignatureOf -where - BridgedAccountSignatureOf: Decode, -{ - BridgedAccountSignatureOf::::decode(&mut TrailingZeroInput::zeroes()) - .expect("failed to decode `BridgedAccountSignatureOf` from zeroes") -} - -/// Account at the bridged chain that is participating in the swap. -fn target_account_at_bridged_chain, I: 'static>() -> BridgedAccountIdOf { - account("target_account_at_bridged_chain", 0, SEED) -} diff --git a/modules/token-swap/src/lib.rs b/modules/token-swap/src/lib.rs deleted file mode 100644 index 81059ee1fd5fa..0000000000000 --- a/modules/token-swap/src/lib.rs +++ /dev/null @@ -1,1195 +0,0 @@ -// 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 . - -//! Runtime module that allows token swap between two parties acting on different chains. -//! -//! The swap is made using message lanes between This (where `pallet-bridge-token-swap` pallet -//! is deployed) and some other Bridged chain. No other assumptions about the Bridged chain are -//! made, so we don't need it to have an instance of the `pallet-bridge-token-swap` pallet deployed. -//! -//! There are four accounts participating in the swap: -//! -//! 1) account of This chain that has signed the `create_swap` transaction and has balance on This -//! chain. We'll be referring to this account as `source_account_at_this_chain`; -//! -//! 2) account of the Bridged chain that is sending the `claim_swap` message from the Bridged to -//! This chain. This account has balance on Bridged chain and is willing to swap these tokens to -//! This chain tokens of the `source_account_at_this_chain`. We'll be referring to this account -//! as `target_account_at_bridged_chain`; -//! -//! 3) account of the Bridged chain that is indirectly controlled by the -//! `source_account_at_this_chain`. We'll be referring this account as -//! `source_account_at_bridged_chain`; -//! -//! 4) account of This chain that is indirectly controlled by the `target_account_at_bridged_chain`. -//! We'll be referring this account as `target_account_at_this_chain`. -//! -//! So the tokens swap is an intention of `source_account_at_this_chain` to swap his -//! `source_balance_at_this_chain` tokens to the `target_balance_at_bridged_chain` tokens owned by -//! `target_account_at_bridged_chain`. The swap process goes as follows: -//! -//! 1) the `source_account_at_this_chain` account submits the `create_swap` transaction on This -//! chain; -//! -//! 2) the tokens transfer message that would transfer `target_balance_at_bridged_chain` -//! tokens from the `target_account_at_bridged_chain` to the `source_account_at_bridged_chain`, -//! is sent over the bridge; -//! -//! 3) when transfer message is delivered and dispatched, the pallet receives notification; -//! -//! 4) if message has been successfully dispatched, the `target_account_at_bridged_chain` sends the -//! message that would transfer `source_balance_at_this_chain` tokens to his -//! `target_account_at_this_chain` account; -//! -//! 5) if message dispatch has failed, the `source_account_at_this_chain` may submit the -//! `cancel_swap` transaction and return his `source_balance_at_this_chain` back to his account. -//! -//! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special -//! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion. - -#![cfg_attr(not(feature = "std"), no_std)] - -use bp_messages::{ - source_chain::{MessagesBridge, OnDeliveryConfirmed}, - DeliveredMessages, LaneId, MessageNonce, -}; -use bp_runtime::{messages::DispatchFeePayment, ChainId}; -use bp_token_swap::{ - RawBridgedTransferCall, TokenSwap, TokenSwapCreation, TokenSwapState, TokenSwapType, -}; -use codec::{Decode, Encode}; -use frame_support::{ - fail, - traits::{Currency, ExistenceRequirement}, - weights::PostDispatchInfo, - RuntimeDebug, -}; -use scale_info::TypeInfo; -use sp_core::H256; -use sp_io::hashing::blake2_256; -use sp_runtime::traits::{Convert, Saturating}; -use sp_std::{boxed::Box, marker::PhantomData}; -use weights::WeightInfo; - -pub use weights_ext::WeightInfoExt; - -#[cfg(test)] -mod mock; - -#[cfg(feature = "runtime-benchmarks")] -pub mod benchmarking; - -pub mod weights; -pub mod weights_ext; - -pub use pallet::*; - -/// Name of the `PendingSwaps` storage map. -pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; - -/// Origin for the token swap pallet. -#[derive(PartialEq, Eq, Clone, RuntimeDebug, Encode, Decode, TypeInfo)] -pub enum RawOrigin { - /// The call is originated by the token swap account. - TokenSwap { - /// Id of the account that has started the swap. - source_account_at_this_chain: AccountId, - /// Id of the account that holds the funds during this swap. The message fee is paid from - /// this account funds. - swap_account_at_this_chain: AccountId, - }, - /// Dummy to manage the fact we have instancing. - _Phantom(PhantomData), -} - -// comes from #[pallet::event] -#[allow(clippy::unused_unit)] -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type. - type Event: From> + IsType<::Event>; - /// Benchmarks results from runtime we're plugged into. - type WeightInfo: WeightInfoExt; - - /// Id of the bridge with the Bridged chain. - type BridgedChainId: Get; - /// The identifier of outbound message lane on This chain used to send token transfer - /// messages to the Bridged chain. - /// - /// It is highly recommended to use dedicated lane for every instance of token swap - /// pallet. Messages delivery confirmation callback is implemented in the way that - /// for every confirmed message, there is (at least) a storage read. Which mean, - /// that if pallet will see unrelated confirmations, it'll just burn storage-read - /// weight, achieving nothing. - type OutboundMessageLaneId: Get; - /// Messages bridge with Bridged chain. - type MessagesBridge: MessagesBridge< - Self::Origin, - Self::AccountId, - >::Balance, - MessagePayloadOf, - >; - - /// This chain Currency used in the tokens swap. - type ThisCurrency: Currency; - /// Converter from raw hash (derived from swap) to This chain account. - type FromSwapToThisAccountIdConverter: Convert; - - /// The chain we're bridged to. - type BridgedChain: bp_runtime::Chain; - /// Converter from raw hash (derived from Bridged chain account) to This chain account. - type FromBridgedToThisAccountIdConverter: Convert; - } - - /// Tokens balance at This chain. - pub type ThisChainBalance = <>::ThisCurrency as Currency< - ::AccountId, - >>::Balance; - - /// Type of the Bridged chain. - pub type BridgedChainOf = >::BridgedChain; - /// Tokens balance type at the Bridged chain. - pub type BridgedBalanceOf = bp_runtime::BalanceOf>; - /// Account identifier type at the Bridged chain. - pub type BridgedAccountIdOf = bp_runtime::AccountIdOf>; - /// Account public key type at the Bridged chain. - pub type BridgedAccountPublicOf = bp_runtime::AccountPublicOf>; - /// Account signature type at the Bridged chain. - pub type BridgedAccountSignatureOf = bp_runtime::SignatureOf>; - - /// Bridge message payload used by the pallet. - pub type MessagePayloadOf = bp_message_dispatch::MessagePayload< - ::AccountId, - BridgedAccountPublicOf, - BridgedAccountSignatureOf, - RawBridgedTransferCall, - >; - /// Type of `TokenSwap` used by the pallet. - pub type TokenSwapOf = TokenSwap< - BlockNumberFor, - ThisChainBalance, - ::AccountId, - BridgedBalanceOf, - BridgedAccountIdOf, - >; - /// Type of `TokenSwapCreation` used by the pallet. - pub type TokenSwapCreationOf = TokenSwapCreation< - BridgedAccountPublicOf, - ThisChainBalance, - BridgedAccountSignatureOf, - >; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData<(T, I)>); - - #[pallet::hooks] - impl, I: 'static> Hooks> for Pallet {} - - #[pallet::call] - impl, I: 'static> Pallet - where - BridgedAccountPublicOf: Parameter, - Origin: Into, - { - /// Start token swap procedure. - /// - /// The dispatch origin for this call must be exactly the - /// `swap.source_account_at_this_chain` account. - /// - /// Method arguments are: - /// - /// - `swap` - token swap intention; - /// - `swap_creation_params` - additional parameters required to start tokens swap. - /// - /// The `source_account_at_this_chain` MUST have enough balance to cover both token swap and - /// message transfer. Message fee may be estimated using corresponding `OutboundLaneApi` of - /// This runtime. - /// - /// **WARNING**: the submitter of this transaction is responsible for verifying: - /// - /// 1) that the `swap_creation_params.bridged_currency_transfer` represents a valid token - /// transfer call that transfers `swap.target_balance_at_bridged_chain` to his - /// `swap.source_account_at_bridged_chain` account; - /// - /// 2) that either the `swap.source_account_at_bridged_chain` already exists, or the - /// `swap.target_balance_at_bridged_chain` is above existential deposit of the Bridged - /// chain; - /// - /// 3) the `swap_creation_params.target_public_at_bridged_chain` matches the - /// `swap.target_account_at_bridged_chain`; - /// - /// 4) the `bridged_currency_transfer_signature` is valid and generated by the owner of - /// the `swap_creation_params.target_public_at_bridged_chain` account (read more - /// about [`CallOrigin::TargetAccount`]). - /// - /// Violating rule#1 will lead to losing your `source_balance_at_this_chain` tokens. - /// Violating other rules will lead to losing message fees for this and other transactions + - /// losing fees for message transfer. - #[allow(clippy::boxed_local)] - #[pallet::weight( - T::WeightInfo::create_swap() - .saturating_add(T::WeightInfo::send_message_weight( - &&swap_creation_params.bridged_currency_transfer[..], - T::DbWeight::get(), - )) - )] - pub fn create_swap( - origin: OriginFor, - swap: TokenSwapOf, - swap_creation_params: Box>, - ) -> DispatchResultWithPostInfo { - let TokenSwapCreation { - target_public_at_bridged_chain, - swap_delivery_and_dispatch_fee, - bridged_chain_spec_version, - bridged_currency_transfer, - bridged_currency_transfer_weight, - bridged_currency_transfer_signature, - } = *swap_creation_params; - - // ensure that the `origin` is the same account that is mentioned in the `swap` - // intention - let origin_account = ensure_signed(origin)?; - ensure!( - origin_account == swap.source_account_at_this_chain, - Error::::MismatchedSwapSourceOrigin, - ); - - // remember weight components - let base_weight = T::WeightInfo::create_swap(); - - // we can't exchange less than existential deposit (the temporary `swap_account` account - // won't be created then) - // - // the same can also happen with the `swap.bridged_balance`, but we can't check it - // here (without additional knowledge of the Bridged chain). So it is the `origin` - // responsibility to check that the swap is valid. - ensure!( - swap.source_balance_at_this_chain >= T::ThisCurrency::minimum_balance(), - Error::::TooLowBalanceOnThisChain, - ); - - // if the swap is replay-protected, then we need to ensure that we have not yet passed - // the specified block yet - match swap.swap_type { - TokenSwapType::TemporaryTargetAccountAtBridgedChain => (), - TokenSwapType::LockClaimUntilBlock(block_number, _) => ensure!( - block_number >= frame_system::Pallet::::block_number(), - Error::::SwapPeriodIsFinished, - ), - } - - let swap_account = swap_account_id::(&swap); - let actual_send_message_weight = frame_support::storage::with_transaction( - || -> sp_runtime::TransactionOutcome> { - // funds are transferred from This account to the temporary Swap account - let transfer_result = T::ThisCurrency::transfer( - &swap.source_account_at_this_chain, - &swap_account, - // saturating_add is ok, or we have the chain where single holder owns all - // tokens - swap.source_balance_at_this_chain - .saturating_add(swap_delivery_and_dispatch_fee), - // if we'll allow account to die, then he'll be unable to `cancel_claim` - // if something won't work - ExistenceRequirement::KeepAlive, - ); - if let Err(err) = transfer_result { - log::error!( - target: "runtime::bridge-token-swap", - "Failed to transfer This chain tokens for the swap {:?} to Swap account ({:?}): {:?}", - swap, - swap_account, - err, - ); - - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferToSwapAccount.into(), - )) - } - - // the transfer message is sent over the bridge. The message is supposed to be a - // `Currency::transfer` call on the bridged chain, but no checks are made - it - // is the transaction submitter to ensure it is valid. - let send_message_result = T::MessagesBridge::send_message( - RawOrigin::TokenSwap { - source_account_at_this_chain: swap.source_account_at_this_chain.clone(), - swap_account_at_this_chain: swap_account.clone(), - } - .into(), - T::OutboundMessageLaneId::get(), - bp_message_dispatch::MessagePayload { - spec_version: bridged_chain_spec_version, - weight: bridged_currency_transfer_weight, - origin: bp_message_dispatch::CallOrigin::TargetAccount( - swap_account, - target_public_at_bridged_chain, - bridged_currency_transfer_signature, - ), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - call: bridged_currency_transfer, - }, - swap_delivery_and_dispatch_fee, - ); - let sent_message = match send_message_result { - Ok(sent_message) => sent_message, - Err(err) => { - log::error!( - target: "runtime::bridge-token-swap", - "Failed to send token transfer message for swap {:?} to the Bridged chain: {:?}", - swap, - err, - ); - - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToSendTransferMessage.into(), - )) - }, - }; - - // remember that we have started the swap - let swap_hash = swap.using_encoded(blake2_256).into(); - let insert_swap_result = - PendingSwaps::::try_mutate(swap_hash, |maybe_state| { - if maybe_state.is_some() { - return Err(()) - } - - *maybe_state = Some(TokenSwapState::Started); - Ok(()) - }); - if insert_swap_result.is_err() { - log::error!( - target: "runtime::bridge-token-swap", - "Failed to start token swap {:?}: the swap is already started", - swap, - ); - - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::SwapAlreadyStarted.into(), - )) - } - - log::trace!( - target: "runtime::bridge-token-swap", - "The swap {:?} (hash {:?}) has been started", - swap, - swap_hash, - ); - - // remember that we're waiting for the transfer message delivery confirmation - PendingMessages::::insert(sent_message.nonce, swap_hash); - - // finally - emit the event - Self::deposit_event(Event::SwapStarted(swap_hash, sent_message.nonce)); - - sp_runtime::TransactionOutcome::Commit(Ok(sent_message.weight)) - }, - )?; - - Ok(PostDispatchInfo { - actual_weight: Some(base_weight.saturating_add(actual_send_message_weight)), - pays_fee: Pays::Yes, - }) - } - - /// Claim previously reserved `source_balance_at_this_chain` by - /// `target_account_at_this_chain`. - /// - /// **WARNING**: the correct way to call this function is to call it over the messages - /// bridge with dispatch origin set to - /// `pallet_bridge_dispatch::CallOrigin::SourceAccount(target_account_at_bridged_chain)`. - /// - /// This should be called only when successful transfer confirmation has been received. - #[pallet::weight(T::WeightInfo::claim_swap())] - pub fn claim_swap( - origin: OriginFor, - swap: TokenSwapOf, - ) -> DispatchResultWithPostInfo { - // ensure that the `origin` is controlled by the `swap.target_account_at_bridged_chain` - let origin_account = ensure_signed(origin)?; - let target_account_at_this_chain = target_account_at_this_chain::(&swap); - ensure!(origin_account == target_account_at_this_chain, Error::::InvalidClaimant,); - - // ensure that the swap is confirmed - let swap_hash = swap.using_encoded(blake2_256).into(); - let swap_state = PendingSwaps::::get(swap_hash); - match swap_state { - Some(TokenSwapState::Started) => fail!(Error::::SwapIsPending), - Some(TokenSwapState::Confirmed) => { - let is_claim_allowed = match swap.swap_type { - TokenSwapType::TemporaryTargetAccountAtBridgedChain => true, - TokenSwapType::LockClaimUntilBlock(block_number, _) => - block_number < frame_system::Pallet::::block_number(), - }; - - ensure!(is_claim_allowed, Error::::SwapIsTemporaryLocked); - }, - Some(TokenSwapState::Failed) => fail!(Error::::SwapIsFailed), - None => fail!(Error::::SwapIsInactive), - } - - complete_claim::(swap, swap_hash, origin_account, Event::SwapClaimed(swap_hash)) - } - - /// Return previously reserved `source_balance_at_this_chain` back to the - /// `source_account_at_this_chain`. - /// - /// This should be called only when transfer has failed at Bridged chain and we have - /// received notification about that. - #[pallet::weight(T::WeightInfo::cancel_swap())] - pub fn cancel_swap( - origin: OriginFor, - swap: TokenSwapOf, - ) -> DispatchResultWithPostInfo { - // ensure that the `origin` is the same account that is mentioned in the `swap` - // intention - let origin_account = ensure_signed(origin)?; - ensure!( - origin_account == swap.source_account_at_this_chain, - Error::::MismatchedSwapSourceOrigin, - ); - - // ensure that the swap has failed - let swap_hash = swap.using_encoded(blake2_256).into(); - let swap_state = PendingSwaps::::get(swap_hash); - match swap_state { - Some(TokenSwapState::Started) => fail!(Error::::SwapIsPending), - Some(TokenSwapState::Confirmed) => fail!(Error::::SwapIsConfirmed), - Some(TokenSwapState::Failed) => { - // we allow canceling swap even before lock period is over - the - // `source_account_at_this_chain` has already paid for nothing and it is up to - // him to decide whether he want to try again - }, - None => fail!(Error::::SwapIsInactive), - } - - complete_claim::(swap, swap_hash, origin_account, Event::SwapCanceled(swap_hash)) - } - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event, I: 'static = ()> { - /// Tokens swap has been started and message has been sent to the bridged message. - /// - /// The payload is the swap hash and the transfer message nonce. - SwapStarted(H256, MessageNonce), - /// Token swap has been claimed. - SwapClaimed(H256), - /// Token swap has been canceled. - SwapCanceled(H256), - } - - #[pallet::error] - pub enum Error { - /// The account that has submitted the `start_claim` doesn't match the - /// `TokenSwap::source_account_at_this_chain`. - MismatchedSwapSourceOrigin, - /// The swap balance in This chain tokens is below existential deposit and can't be made. - TooLowBalanceOnThisChain, - /// Transfer from This chain account to temporary Swap account has failed. - FailedToTransferToSwapAccount, - /// Transfer from the temporary Swap account to the derived account of Bridged account has - /// failed. - FailedToTransferFromSwapAccount, - /// The message to transfer tokens on Target chain can't be sent. - FailedToSendTransferMessage, - /// The same swap is already started. - SwapAlreadyStarted, - /// Swap outcome is not yet received. - SwapIsPending, - /// Someone is trying to claim swap that has failed. - SwapIsFailed, - /// Claiming swap is not allowed. - /// - /// Now the only possible case when you may get this error, is when you're trying to claim - /// swap with `TokenSwapType::LockClaimUntilBlock` before lock period is over. - SwapIsTemporaryLocked, - /// Swap period is finished and you can not restart it. - /// - /// Now the only possible case when you may get this error, is when you're trying to start - /// swap with `TokenSwapType::LockClaimUntilBlock` after lock period is over. - SwapPeriodIsFinished, - /// Someone is trying to cancel swap that has been confirmed. - SwapIsConfirmed, - /// Someone is trying to claim/cancel swap that is either not started or already - /// claimed/canceled. - SwapIsInactive, - /// The swap claimant is invalid. - InvalidClaimant, - } - - /// Origin for the token swap pallet. - #[pallet::origin] - pub type Origin = RawOrigin<::AccountId, I>; - - /// Pending token swaps states. - #[pallet::storage] - pub type PendingSwaps, I: 'static = ()> = - StorageMap<_, Identity, H256, TokenSwapState>; - - /// Pending transfer messages. - #[pallet::storage] - pub type PendingMessages, I: 'static = ()> = - StorageMap<_, Identity, MessageNonce, H256>; - - impl, I: 'static> OnDeliveryConfirmed for Pallet { - fn on_messages_delivered(lane: &LaneId, delivered_messages: &DeliveredMessages) -> Weight { - // we're only interested in our lane messages - if *lane != T::OutboundMessageLaneId::get() { - return 0 - } - - // so now we're dealing with our lane messages. Ideally we'll have dedicated lane - // and every message from `delivered_messages` is actually our transfer message. - // But it may be some shared lane (which is not recommended). - let mut reads = 0; - let mut writes = 0; - for message_nonce in delivered_messages.begin..=delivered_messages.end { - reads += 1; - if let Some(swap_hash) = PendingMessages::::take(message_nonce) { - writes += 1; - - let token_swap_state = - if delivered_messages.message_dispatch_result(message_nonce) { - TokenSwapState::Confirmed - } else { - TokenSwapState::Failed - }; - - log::trace!( - target: "runtime::bridge-token-swap", - "The dispatch of swap {:?} has been completed with {:?} status", - swap_hash, - token_swap_state, - ); - - PendingSwaps::::insert(swap_hash, token_swap_state); - } - } - - ::DbWeight::get().reads_writes(reads, writes) - } - } - - /// Returns temporary account id used to lock funds during swap on This chain. - pub(crate) fn swap_account_id, I: 'static>( - swap: &TokenSwapOf, - ) -> T::AccountId { - T::FromSwapToThisAccountIdConverter::convert(swap.using_encoded(blake2_256).into()) - } - - /// Expected target account representation on This chain (aka `target_account_at_this_chain`). - pub(crate) fn target_account_at_this_chain, I: 'static>( - swap: &TokenSwapOf, - ) -> T::AccountId { - T::FromBridgedToThisAccountIdConverter::convert(bp_runtime::derive_account_id( - T::BridgedChainId::get(), - bp_runtime::SourceAccount::Account(swap.target_account_at_bridged_chain.clone()), - )) - } - - /// Complete claim with given outcome. - pub(crate) fn complete_claim, I: 'static>( - swap: TokenSwapOf, - swap_hash: H256, - destination_account: T::AccountId, - event: Event, - ) -> DispatchResultWithPostInfo { - let swap_account = swap_account_id::(&swap); - frame_support::storage::with_transaction( - || -> sp_runtime::TransactionOutcome> { - // funds are transferred from the temporary Swap account to the destination account - let transfer_result = T::ThisCurrency::transfer( - &swap_account, - &destination_account, - swap.source_balance_at_this_chain, - ExistenceRequirement::AllowDeath, - ); - if let Err(err) = transfer_result { - log::error!( - target: "runtime::bridge-token-swap", - "Failed to transfer This chain tokens for the swap {:?} from the Swap account {:?} to {:?}: {:?}", - swap, - swap_account, - destination_account, - err, - ); - - return sp_runtime::TransactionOutcome::Rollback(Err( - Error::::FailedToTransferFromSwapAccount.into(), - )) - } - - log::trace!( - target: "runtime::bridge-token-swap", - "The swap {:?} (hash {:?}) has been completed with {} status", - swap, - swap_hash, - match event { - Event::SwapClaimed(_) => "claimed", - Event::SwapCanceled(_) => "canceled", - _ => "", - }, - ); - - // forget about swap - PendingSwaps::::remove(swap_hash); - - // finally - emit the event - Pallet::::deposit_event(event); - - sp_runtime::TransactionOutcome::Commit(Ok(Ok(().into()))) - }, - )? - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::*; - use frame_support::{assert_noop, assert_ok, storage::generator::StorageMap}; - - const CAN_START_BLOCK_NUMBER: u64 = 10; - const CAN_CLAIM_BLOCK_NUMBER: u64 = CAN_START_BLOCK_NUMBER + 1; - - const BRIDGED_CHAIN_ACCOUNT: BridgedAccountId = 3; - const BRIDGED_CHAIN_SPEC_VERSION: u32 = 4; - const BRIDGED_CHAIN_CALL_WEIGHT: Balance = 5; - - fn bridged_chain_account_public() -> BridgedAccountPublic { - 1.into() - } - - fn bridged_chain_account_signature() -> BridgedAccountSignature { - sp_runtime::testing::TestSignature(2, Vec::new()) - } - - fn test_swap() -> TokenSwapOf { - bp_token_swap::TokenSwap { - swap_type: TokenSwapType::LockClaimUntilBlock(CAN_START_BLOCK_NUMBER, 0.into()), - source_balance_at_this_chain: 100, - source_account_at_this_chain: THIS_CHAIN_ACCOUNT, - target_balance_at_bridged_chain: 200, - target_account_at_bridged_chain: BRIDGED_CHAIN_ACCOUNT, - } - } - - fn test_swap_creation() -> TokenSwapCreationOf { - TokenSwapCreation { - target_public_at_bridged_chain: bridged_chain_account_public(), - swap_delivery_and_dispatch_fee: SWAP_DELIVERY_AND_DISPATCH_FEE, - bridged_chain_spec_version: BRIDGED_CHAIN_SPEC_VERSION, - bridged_currency_transfer: test_transfer(), - bridged_currency_transfer_weight: BRIDGED_CHAIN_CALL_WEIGHT, - bridged_currency_transfer_signature: bridged_chain_account_signature(), - } - } - - fn test_swap_hash() -> H256 { - test_swap().using_encoded(blake2_256).into() - } - - fn test_transfer() -> RawBridgedTransferCall { - vec![OK_TRANSFER_CALL] - } - - fn start_test_swap() { - assert_ok!(Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(TokenSwapCreation { - target_public_at_bridged_chain: bridged_chain_account_public(), - swap_delivery_and_dispatch_fee: SWAP_DELIVERY_AND_DISPATCH_FEE, - bridged_chain_spec_version: BRIDGED_CHAIN_SPEC_VERSION, - bridged_currency_transfer: test_transfer(), - bridged_currency_transfer_weight: BRIDGED_CHAIN_CALL_WEIGHT, - bridged_currency_transfer_signature: bridged_chain_account_signature(), - }), - )); - } - - fn receive_test_swap_confirmation(success: bool) { - Pallet::::on_messages_delivered( - &OutboundMessageLaneId::get(), - &DeliveredMessages::new(MESSAGE_NONCE, success), - ); - } - - #[test] - fn create_swap_fails_if_origin_is_incorrect() { - run_test(|| { - assert_noop!( - Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), - test_swap(), - Box::new(test_swap_creation()), - ), - Error::::MismatchedSwapSourceOrigin - ); - }); - } - - #[test] - fn create_swap_fails_if_this_chain_balance_is_below_existential_deposit() { - run_test(|| { - let mut swap = test_swap(); - swap.source_balance_at_this_chain = ExistentialDeposit::get() - 1; - assert_noop!( - Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - swap, - Box::new(test_swap_creation()), - ), - Error::::TooLowBalanceOnThisChain - ); - }); - } - - #[test] - fn create_swap_fails_if_currency_transfer_to_swap_account_fails() { - run_test(|| { - let mut swap = test_swap(); - swap.source_balance_at_this_chain = THIS_CHAIN_ACCOUNT_BALANCE + 1; - assert_noop!( - Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - swap, - Box::new(test_swap_creation()), - ), - Error::::FailedToTransferToSwapAccount - ); - }); - } - - #[test] - fn create_swap_fails_if_send_message_fails() { - run_test(|| { - let mut transfer = test_transfer(); - transfer[0] = BAD_TRANSFER_CALL; - let mut swap_creation = test_swap_creation(); - swap_creation.bridged_currency_transfer = transfer; - assert_noop!( - Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(swap_creation), - ), - Error::::FailedToSendTransferMessage - ); - }); - } - - #[test] - fn create_swap_fails_if_swap_is_active() { - run_test(|| { - assert_ok!(Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(test_swap_creation()), - )); - - assert_noop!( - Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(test_swap_creation()), - ), - Error::::SwapAlreadyStarted - ); - }); - } - - #[test] - fn create_swap_fails_if_trying_to_start_swap_after_lock_period_is_finished() { - run_test(|| { - frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER + 1); - assert_noop!( - Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(test_swap_creation()), - ), - Error::::SwapPeriodIsFinished - ); - }); - } - - #[test] - fn create_swap_succeeds_if_trying_to_start_swap_at_lock_period_end() { - run_test(|| { - frame_system::Pallet::::set_block_number(CAN_START_BLOCK_NUMBER); - assert_ok!(Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(test_swap_creation()), - )); - }); - } - - #[test] - fn create_swap_succeeds() { - run_test(|| { - frame_system::Pallet::::set_block_number(1); - frame_system::Pallet::::reset_events(); - - assert_ok!(Pallet::::create_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap(), - Box::new(test_swap_creation()), - )); - - let swap_hash = test_swap_hash(); - assert_eq!(PendingSwaps::::get(swap_hash), Some(TokenSwapState::Started)); - assert_eq!(PendingMessages::::get(MESSAGE_NONCE), Some(swap_hash)); - assert_eq!( - pallet_balances::Pallet::::free_balance(&swap_account_id::< - TestRuntime, - (), - >(&test_swap())), - test_swap().source_balance_at_this_chain + SWAP_DELIVERY_AND_DISPATCH_FEE, - ); - assert!( - frame_system::Pallet::::events().iter().any(|e| e.event == - crate::mock::Event::TokenSwap(crate::Event::SwapStarted( - swap_hash, - MESSAGE_NONCE, - ))), - "Missing SwapStarted event: {:?}", - frame_system::Pallet::::events(), - ); - }); - } - - #[test] - fn claim_swap_fails_if_origin_is_incorrect() { - run_test(|| { - assert_noop!( - Pallet::::claim_swap( - mock::Origin::signed( - 1 + target_account_at_this_chain::(&test_swap()) - ), - test_swap(), - ), - Error::::InvalidClaimant - ); - }); - } - - #[test] - fn claim_swap_fails_if_swap_is_pending() { - run_test(|| { - PendingSwaps::::insert(test_swap_hash(), TokenSwapState::Started); - - assert_noop!( - Pallet::::claim_swap( - mock::Origin::signed(target_account_at_this_chain::( - &test_swap() - )), - test_swap(), - ), - Error::::SwapIsPending - ); - }); - } - - #[test] - fn claim_swap_fails_if_swap_is_failed() { - run_test(|| { - PendingSwaps::::insert(test_swap_hash(), TokenSwapState::Failed); - - assert_noop!( - Pallet::::claim_swap( - mock::Origin::signed(target_account_at_this_chain::( - &test_swap() - )), - test_swap(), - ), - Error::::SwapIsFailed - ); - }); - } - - #[test] - fn claim_swap_fails_if_swap_is_inactive() { - run_test(|| { - assert_noop!( - Pallet::::claim_swap( - mock::Origin::signed(target_account_at_this_chain::( - &test_swap() - )), - test_swap(), - ), - Error::::SwapIsInactive - ); - }); - } - - #[test] - fn claim_swap_fails_if_currency_transfer_from_swap_account_fails() { - run_test(|| { - frame_system::Pallet::::set_block_number(CAN_CLAIM_BLOCK_NUMBER); - PendingSwaps::::insert(test_swap_hash(), TokenSwapState::Confirmed); - - assert_noop!( - Pallet::::claim_swap( - mock::Origin::signed(target_account_at_this_chain::( - &test_swap() - )), - test_swap(), - ), - Error::::FailedToTransferFromSwapAccount - ); - }); - } - - #[test] - fn claim_swap_fails_before_lock_period_is_completed() { - run_test(|| { - start_test_swap(); - receive_test_swap_confirmation(true); - - frame_system::Pallet::::set_block_number(CAN_CLAIM_BLOCK_NUMBER - 1); - - assert_noop!( - Pallet::::claim_swap( - mock::Origin::signed(target_account_at_this_chain::( - &test_swap() - )), - test_swap(), - ), - Error::::SwapIsTemporaryLocked - ); - }); - } - - #[test] - fn claim_swap_succeeds() { - run_test(|| { - start_test_swap(); - receive_test_swap_confirmation(true); - - frame_system::Pallet::::set_block_number(CAN_CLAIM_BLOCK_NUMBER); - frame_system::Pallet::::reset_events(); - - assert_ok!(Pallet::::claim_swap( - mock::Origin::signed(target_account_at_this_chain::(&test_swap())), - test_swap(), - )); - - let swap_hash = test_swap_hash(); - assert_eq!(PendingSwaps::::get(swap_hash), None); - assert_eq!( - pallet_balances::Pallet::::free_balance(&swap_account_id::< - TestRuntime, - (), - >(&test_swap())), - 0, - ); - assert_eq!( - pallet_balances::Pallet::::free_balance( - &target_account_at_this_chain::(&test_swap()), - ), - test_swap().source_balance_at_this_chain, - ); - assert!( - frame_system::Pallet::::events().iter().any(|e| e.event == - crate::mock::Event::TokenSwap(crate::Event::SwapClaimed(swap_hash,))), - "Missing SwapClaimed event: {:?}", - frame_system::Pallet::::events(), - ); - }); - } - - #[test] - fn cancel_swap_fails_if_origin_is_incorrect() { - run_test(|| { - start_test_swap(); - receive_test_swap_confirmation(false); - - assert_noop!( - Pallet::::cancel_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT + 1), - test_swap() - ), - Error::::MismatchedSwapSourceOrigin - ); - }); - } - - #[test] - fn cancel_swap_fails_if_swap_is_pending() { - run_test(|| { - start_test_swap(); - - assert_noop!( - Pallet::::cancel_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap() - ), - Error::::SwapIsPending - ); - }); - } - - #[test] - fn cancel_swap_fails_if_swap_is_confirmed() { - run_test(|| { - start_test_swap(); - receive_test_swap_confirmation(true); - - assert_noop!( - Pallet::::cancel_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap() - ), - Error::::SwapIsConfirmed - ); - }); - } - - #[test] - fn cancel_swap_fails_if_swap_is_inactive() { - run_test(|| { - assert_noop!( - Pallet::::cancel_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap() - ), - Error::::SwapIsInactive - ); - }); - } - - #[test] - fn cancel_swap_fails_if_currency_transfer_from_swap_account_fails() { - run_test(|| { - start_test_swap(); - receive_test_swap_confirmation(false); - let _ = pallet_balances::Pallet::::slash( - &swap_account_id::(&test_swap()), - test_swap().source_balance_at_this_chain, - ); - - assert_noop!( - Pallet::::cancel_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap() - ), - Error::::FailedToTransferFromSwapAccount - ); - }); - } - - #[test] - fn cancel_swap_succeeds() { - run_test(|| { - start_test_swap(); - receive_test_swap_confirmation(false); - - frame_system::Pallet::::set_block_number(1); - frame_system::Pallet::::reset_events(); - - assert_ok!(Pallet::::cancel_swap( - mock::Origin::signed(THIS_CHAIN_ACCOUNT), - test_swap() - )); - - let swap_hash = test_swap_hash(); - assert_eq!(PendingSwaps::::get(swap_hash), None); - assert_eq!( - pallet_balances::Pallet::::free_balance(&swap_account_id::< - TestRuntime, - (), - >(&test_swap())), - 0, - ); - assert_eq!( - pallet_balances::Pallet::::free_balance(&THIS_CHAIN_ACCOUNT), - THIS_CHAIN_ACCOUNT_BALANCE - SWAP_DELIVERY_AND_DISPATCH_FEE, - ); - assert!( - frame_system::Pallet::::events().iter().any(|e| e.event == - crate::mock::Event::TokenSwap(crate::Event::SwapCanceled(swap_hash,))), - "Missing SwapCanceled event: {:?}", - frame_system::Pallet::::events(), - ); - }); - } - - #[test] - fn messages_delivery_confirmations_are_accepted() { - run_test(|| { - start_test_swap(); - assert_eq!( - PendingMessages::::get(MESSAGE_NONCE), - Some(test_swap_hash()) - ); - assert_eq!( - PendingSwaps::::get(test_swap_hash()), - Some(TokenSwapState::Started) - ); - - // when unrelated messages are delivered - let mut messages = DeliveredMessages::new(MESSAGE_NONCE - 2, true); - messages.note_dispatched_message(false); - Pallet::::on_messages_delivered( - &OutboundMessageLaneId::get(), - &messages, - ); - assert_eq!( - PendingMessages::::get(MESSAGE_NONCE), - Some(test_swap_hash()) - ); - assert_eq!( - PendingSwaps::::get(test_swap_hash()), - Some(TokenSwapState::Started) - ); - - // when message we're interested in is accompanied by a bunch of other messages - let mut messages = DeliveredMessages::new(MESSAGE_NONCE - 1, false); - messages.note_dispatched_message(true); - messages.note_dispatched_message(false); - Pallet::::on_messages_delivered( - &OutboundMessageLaneId::get(), - &messages, - ); - assert_eq!(PendingMessages::::get(MESSAGE_NONCE), None); - assert_eq!( - PendingSwaps::::get(test_swap_hash()), - Some(TokenSwapState::Confirmed) - ); - }); - } - - #[test] - fn storage_keys_computed_properly() { - assert_eq!( - PendingSwaps::::storage_map_final_key(test_swap_hash()), - bp_token_swap::storage_keys::pending_swaps_key("TokenSwap", test_swap_hash()).0, - ); - } -} diff --git a/modules/token-swap/src/mock.rs b/modules/token-swap/src/mock.rs deleted file mode 100644 index ece7b16acc910..0000000000000 --- a/modules/token-swap/src/mock.rs +++ /dev/null @@ -1,200 +0,0 @@ -// 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 . - -use crate as pallet_bridge_token_swap; -use crate::MessagePayloadOf; - -use bp_messages::{ - source_chain::{MessagesBridge, SendMessageArtifacts}, - LaneId, MessageNonce, -}; -use bp_runtime::ChainId; -use frame_support::weights::Weight; -use sp_core::H256; -use sp_runtime::{ - testing::Header as SubstrateHeader, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, -}; - -pub type AccountId = u64; -pub type Balance = u64; -pub type Block = frame_system::mocking::MockBlock; -pub type BridgedAccountId = u64; -pub type BridgedAccountPublic = sp_runtime::testing::UintAuthorityId; -pub type BridgedAccountSignature = sp_runtime::testing::TestSignature; -pub type BridgedBalance = u64; -pub type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - -pub const OK_TRANSFER_CALL: u8 = 1; -pub const BAD_TRANSFER_CALL: u8 = 2; -pub const MESSAGE_NONCE: MessageNonce = 3; - -pub const THIS_CHAIN_ACCOUNT: AccountId = 1; -pub const THIS_CHAIN_ACCOUNT_BALANCE: Balance = 100_000; - -pub const SWAP_DELIVERY_AND_DISPATCH_FEE: Balance = 1; - -frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Event}, - TokenSwap: pallet_bridge_token_swap::{Pallet, Call, Event, Origin}, - } -} - -frame_support::parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - -impl frame_system::Config for TestRuntime { - type Origin = Origin; - type Index = u64; - type Call = Call; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = SubstrateHeader; - type Event = Event; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -frame_support::parameter_types! { - pub const ExistentialDeposit: u64 = 10; - pub const MaxReserves: u32 = 50; -} - -impl pallet_balances::Config for TestRuntime { - type MaxLocks = (); - type Balance = Balance; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type MaxReserves = MaxReserves; - type ReserveIdentifier = [u8; 8]; -} - -frame_support::parameter_types! { - pub const BridgedChainId: ChainId = *b"inst"; - pub const OutboundMessageLaneId: LaneId = *b"lane"; -} - -impl pallet_bridge_token_swap::Config for TestRuntime { - type Event = Event; - type WeightInfo = (); - - type BridgedChainId = BridgedChainId; - type OutboundMessageLaneId = OutboundMessageLaneId; - type MessagesBridge = TestMessagesBridge; - - type ThisCurrency = pallet_balances::Pallet; - type FromSwapToThisAccountIdConverter = TestAccountConverter; - - type BridgedChain = BridgedChain; - type FromBridgedToThisAccountIdConverter = TestAccountConverter; -} - -pub struct BridgedChain; - -impl bp_runtime::Chain for BridgedChain { - type BlockNumber = u64; - type Hash = H256; - type Hasher = BlakeTwo256; - type Header = sp_runtime::generic::Header; - - type AccountId = BridgedAccountId; - type Balance = BridgedBalance; - type Index = u64; - type Signature = BridgedAccountSignature; - - fn max_extrinsic_size() -> u32 { - unreachable!() - } - fn max_extrinsic_weight() -> Weight { - unreachable!() - } -} - -pub struct TestMessagesBridge; - -impl MessagesBridge> - for TestMessagesBridge -{ - type Error = (); - - fn send_message( - sender: Origin, - lane: LaneId, - message: MessagePayloadOf, - delivery_and_dispatch_fee: Balance, - ) -> Result { - assert_eq!(lane, OutboundMessageLaneId::get()); - assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE); - match sender.caller { - OriginCaller::TokenSwap(_) => (), - _ => panic!("unexpected origin"), - } - match message.call[0] { - OK_TRANSFER_CALL => Ok(SendMessageArtifacts { nonce: MESSAGE_NONCE, weight: 0 }), - BAD_TRANSFER_CALL => Err(()), - _ => unreachable!(), - } - } -} - -pub struct TestAccountConverter; - -impl sp_runtime::traits::Convert for TestAccountConverter { - fn convert(hash: H256) -> AccountId { - hash.to_low_u64_ne() - } -} - -/// Run pallet test. -pub fn run_test(test: impl FnOnce() -> T) -> T { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { - balances: vec![(THIS_CHAIN_ACCOUNT, THIS_CHAIN_ACCOUNT_BALANCE)], - } - .assimilate_storage(&mut t) - .unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(test) -} diff --git a/modules/token-swap/src/weights.rs b/modules/token-swap/src/weights.rs deleted file mode 100644 index 51c5d99de9c5c..0000000000000 --- a/modules/token-swap/src/weights.rs +++ /dev/null @@ -1,93 +0,0 @@ -// 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 . - -//! Autogenerated weights for `pallet_bridge_token_swap` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 -//! LOW RANGE: [], HIGH RANGE: [] -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 128 - -// Executed Command: -// target/release/millau-bridge-node -// benchmark -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_token_swap -// --extrinsic=* -// --execution=wasm -// --wasm-execution=Compiled -// --heap-pages=4096 -// --output=./modules/token-swap/src/weights.rs -// --template=./.maintain/millau-weight-template.hbs - -#![allow(clippy::all)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{ - traits::Get, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for `pallet_bridge_token_swap`. -pub trait WeightInfo { - fn create_swap() -> Weight; - fn claim_swap() -> Weight; - fn cancel_swap() -> Weight; -} - -/// Weights for `pallet_bridge_token_swap` using the Millau node and recommended hardware. -pub struct MillauWeight(PhantomData); -impl WeightInfo for MillauWeight { - fn create_swap() -> Weight { - (90_368_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) - } - fn claim_swap() -> Weight { - (88_397_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn cancel_swap() -> Weight { - (91_253_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - fn create_swap() -> Weight { - (90_368_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) - } - fn claim_swap() -> Weight { - (88_397_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn cancel_swap() -> Weight { - (91_253_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } -} diff --git a/modules/token-swap/src/weights_ext.rs b/modules/token-swap/src/weights_ext.rs deleted file mode 100644 index 2d27c76cbe685..0000000000000 --- a/modules/token-swap/src/weights_ext.rs +++ /dev/null @@ -1,42 +0,0 @@ -// 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 . - -//! Weight-related utilities. - -use crate::weights::WeightInfo; - -use bp_runtime::Size; -use frame_support::weights::{RuntimeDbWeight, Weight}; - -/// Extended weight info. -pub trait WeightInfoExt: WeightInfo { - // Functions that are directly mapped to extrinsics weights. - - /// Weight of message send extrinsic. - fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight; -} - -impl WeightInfoExt for () { - fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { - <() as pallet_bridge_messages::WeightInfoExt>::send_message_weight(message, db_weight) - } -} - -impl WeightInfoExt for crate::weights::MillauWeight { - fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { - <() as pallet_bridge_messages::WeightInfoExt>::send_message_weight(message, db_weight) - } -} diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index ff8d53859535b..281ea471a2cfc 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -269,9 +269,6 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; -/// Name of the With-Rialto token swap pallet instance in the Millau runtime. -pub const WITH_RIALTO_TOKEN_SWAP_PALLET_NAME: &str = "BridgeRialtoTokenSwap"; - /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; diff --git a/primitives/message-dispatch/Cargo.toml b/primitives/message-dispatch/Cargo.toml deleted file mode 100644 index 02b0912894daf..0000000000000 --- a/primitives/message-dispatch/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "bp-message-dispatch" -description = "Primitives of bridge messages dispatch modules." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[features] -default = ["std"] -std = [ - "bp-runtime/std", - "codec/std", - "frame-support/std", - "scale-info/std", - "sp-std/std", -] diff --git a/primitives/message-dispatch/src/lib.rs b/primitives/message-dispatch/src/lib.rs deleted file mode 100644 index 07e448ee7ae62..0000000000000 --- a/primitives/message-dispatch/src/lib.rs +++ /dev/null @@ -1,142 +0,0 @@ -// 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 . - -//! A common interface for all Bridge Message Dispatch modules. - -#![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] - -use bp_runtime::{ - messages::{DispatchFeePayment, MessageDispatchResult}, - ChainId, Size, -}; -use codec::{Decode, Encode}; -use frame_support::RuntimeDebug; -use scale_info::TypeInfo; -use sp_std::prelude::*; - -/// Message dispatch weight. -pub type Weight = u64; - -/// Spec version type. -pub type SpecVersion = u32; - -/// A generic trait to dispatch arbitrary messages delivered over the bridge. -pub trait MessageDispatch { - /// A type of the message to be dispatched. - type Message: codec::Decode; - - /// Estimate dispatch weight. - /// - /// This function must: (1) be instant and (2) return correct upper bound - /// of dispatch weight. - fn dispatch_weight(message: &Self::Message) -> Weight; - - /// Dispatches the message internally. - /// - /// `source_chain` indicates the chain where the message came from. - /// `target_chain` indicates the chain where message dispatch happens. - /// - /// `id` is a short unique identifier of the message. - /// - /// If message is `Ok`, then it should be dispatched. If it is `Err`, then it's just - /// a sign that some other component has rejected the message even before it has - /// reached `dispatch` method (right now this may only be caused if we fail to decode - /// the whole message). - /// - /// Returns unspent dispatch weight. - fn dispatch Result<(), ()>>( - source_chain: ChainId, - target_chain: ChainId, - id: BridgeMessageId, - message: Result, - pay_dispatch_fee: P, - ) -> MessageDispatchResult; -} - -/// Origin of a Call when it is dispatched on the target chain. -/// -/// The source chain can (and should) verify that the message can be dispatched on the target chain -/// with a particular origin given the source chain's origin. This can be done with the -/// `verify_message_origin()` function. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] -pub enum CallOrigin { - /// Call is sent by the Root origin on the source chain. On the target chain it is dispatched - /// from a derived account. - /// - /// The derived account represents the source Root account on the target chain. This is useful - /// if the target chain needs some way of knowing that a call came from a privileged origin on - /// the source chain (maybe to allow a configuration change for example). - SourceRoot, - - /// Call is sent by `SourceChainAccountId` on the source chain. On the target chain it is - /// dispatched from an account controlled by a private key on the target chain. - /// - /// The account can be identified by `TargetChainAccountPublic`. The proof that the - /// `SourceChainAccountId` controls `TargetChainAccountPublic` is the `TargetChainSignature` - /// over `(Call, SourceChainAccountId, TargetChainSpecVersion, SourceChainBridgeId).encode()`. - /// - /// NOTE sending messages using this origin (or any other) does not have replay protection! - /// The assumption is that both the source account and the target account is controlled by - /// the same entity, so source-chain replay protection is sufficient. - /// As a consequence, it's extremely important for the target chain user to never produce - /// a signature with their target-private key on something that could be sent over the bridge, - /// i.e. if the target user signs `(, Call::Transfer(X, 5))` - /// The owner of `some-source-account-id` can send that message multiple times, which would - /// result with multiple transfer calls being dispatched on the target chain. - /// So please, NEVER USE YOUR PRIVATE KEY TO SIGN SOMETHING YOU DON'T FULLY UNDERSTAND! - TargetAccount(SourceChainAccountId, TargetChainAccountPublic, TargetChainSignature), - - /// Call is sent by the `SourceChainAccountId` on the source chain. On the target chain it is - /// dispatched from a derived account ID. - /// - /// The account ID on the target chain is derived from the source account ID. This is useful if - /// you need a way to represent foreign accounts on this chain for call dispatch purposes. - /// - /// Note that the derived account does not need to have a private key on the target chain. This - /// origin can therefore represent proxies, pallets, etc. as well as "regular" accounts. - SourceAccount(SourceChainAccountId), -} - -/// Message payload type used by dispatch module. -#[derive(RuntimeDebug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] -pub struct MessagePayload< - SourceChainAccountId, - TargetChainAccountPublic, - TargetChainSignature, - Call, -> { - /// Runtime specification version. We only dispatch messages that have the same - /// runtime version. Otherwise we risk to misinterpret encoded calls. - pub spec_version: SpecVersion, - /// Weight of the call, declared by the message sender. If it is less than actual - /// static weight, the call is not dispatched. - pub weight: Weight, - /// Call origin to be used during dispatch. - pub origin: CallOrigin, - /// Where the fee for dispatching message is paid? - pub dispatch_fee_payment: DispatchFeePayment, - /// The call itself. - pub call: Call, -} - -impl Size - for MessagePayload> -{ - fn size_hint(&self) -> u32 { - self.call.len() as _ - } -} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 1d8a40339ab0c..da6f376ae4f49 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -136,15 +136,15 @@ pub trait Size { fn size_hint(&self) -> u32; } -impl Size for &[u8] { +impl Size for () { fn size_hint(&self) -> u32 { - self.len() as _ + 0 } } -impl Size for () { +impl Size for Vec { fn size_hint(&self) -> u32 { - 0 + self.len() as _ } } diff --git a/primitives/token-swap/Cargo.toml b/primitives/token-swap/Cargo.toml deleted file mode 100644 index 7ef5845d2aba7..0000000000000 --- a/primitives/token-swap/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "bp-token-swap" -description = "Primitives of the pallet-bridge-token-swap pallet" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } - -# Bridge Dependencies - -bp-runtime = { path = "../runtime", 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[dev-dependencies] -hex = "0.4" -hex-literal = "0.3" - -[features] -default = ["std"] -std = [ - "bp-runtime/std", - "codec/std", - "frame-support/std", - "scale-info/std", - "sp-core/std", - "sp-io/std", - "sp-std/std", -] diff --git a/primitives/token-swap/src/lib.rs b/primitives/token-swap/src/lib.rs deleted file mode 100644 index 79363e5477a44..0000000000000 --- a/primitives/token-swap/src/lib.rs +++ /dev/null @@ -1,124 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod storage_keys; - -use codec::{Decode, Encode}; -use frame_support::{weights::Weight, RuntimeDebug}; -use scale_info::TypeInfo; -use sp_core::{H256, U256}; -use sp_io::hashing::blake2_256; -use sp_std::vec::Vec; - -/// Pending token swap state. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub enum TokenSwapState { - /// The swap has been started using the `start_claim` call, but we have no proof that it has - /// happened at the Bridged chain. - Started, - /// The swap has happened at the Bridged chain and may be claimed by the Bridged chain party - /// using the `claim_swap` call. - Confirmed, - /// The swap has failed at the Bridged chain and This chain party may cancel it using the - /// `cancel_swap` call. - Failed, -} - -/// Token swap type. -/// -/// Different swap types give a different guarantees regarding possible swap -/// replay protection. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub enum TokenSwapType { - /// The `target_account_at_bridged_chain` is temporary and only have funds for single swap. - /// - /// ***WARNING**: if `target_account_at_bridged_chain` still exists after the swap has been - /// completed (either by claiming or canceling), the `source_account_at_this_chain` will be - /// able to restart the swap again and repeat the swap until `target_account_at_bridged_chain` - /// depletes. - TemporaryTargetAccountAtBridgedChain, - /// This swap type prevents `source_account_at_this_chain` from restarting the swap after it - /// has been completed. There are two consequences: - /// - /// 1) the `source_account_at_this_chain` won't be able to call `start_swap` after given - /// ; 2) the `target_account_at_bridged_chain` won't be able to call - /// `claim_swap` (over the bridge) before block ``. - /// - /// The second element is the nonce of the swap. You must care about its uniqueness if you're - /// planning to perform another swap with exactly the same parameters (i.e. same amount, same - /// accounts, same `ThisBlockNumber`) to avoid collisions. - LockClaimUntilBlock(ThisBlockNumber, U256), -} - -/// An intention to swap `source_balance_at_this_chain` owned by `source_account_at_this_chain` -/// to `target_balance_at_bridged_chain` owned by `target_account_at_bridged_chain`. -/// -/// **IMPORTANT NOTE**: this structure is always the same during single token swap. So even -/// when chain changes, the meaning of This and Bridged are still used to point to the same chains. -/// This chain is always the chain where swap has been started. And the Bridged chain is the other -/// chain. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct TokenSwap -{ - /// The type of the swap. - pub swap_type: TokenSwapType, - /// This chain balance to be swapped with `target_balance_at_bridged_chain`. - pub source_balance_at_this_chain: ThisBalance, - /// Account id of the party acting at This chain and owning the `source_account_at_this_chain`. - pub source_account_at_this_chain: ThisAccountId, - /// Bridged chain balance to be swapped with `source_balance_at_this_chain`. - pub target_balance_at_bridged_chain: BridgedBalance, - /// Account id of the party acting at the Bridged chain and owning the - /// `target_balance_at_bridged_chain`. - pub target_account_at_bridged_chain: BridgedAccountId, -} - -impl - TokenSwap -where - TokenSwap: - Encode, -{ - /// Returns hash, used to identify this token swap. - pub fn hash(&self) -> H256 { - self.using_encoded(blake2_256).into() - } -} - -/// SCALE-encoded `Currency::transfer` call on the bridged chain. -pub type RawBridgedTransferCall = Vec; - -/// Token swap creation parameters. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct TokenSwapCreation { - /// Public key of the `target_account_at_bridged_chain` account used to verify - /// `bridged_currency_transfer_signature`. - pub target_public_at_bridged_chain: BridgedAccountPublic, - /// Fee that the `source_account_at_this_chain` is ready to pay for the tokens - /// transfer message delivery and dispatch. - pub swap_delivery_and_dispatch_fee: ThisChainBalance, - /// Specification version of the Bridged chain. - pub bridged_chain_spec_version: u32, - /// SCALE-encoded tokens transfer call at the Bridged chain. - pub bridged_currency_transfer: RawBridgedTransferCall, - /// Dispatch weight of the tokens transfer call at the Bridged chain. - pub bridged_currency_transfer_weight: Weight, - /// The signature of the `target_account_at_bridged_chain` for the message - /// returned by the `pallet_bridge_dispatch::account_ownership_digest()` function call. - pub bridged_currency_transfer_signature: BridgedAccountSignature, -} diff --git a/primitives/token-swap/src/storage_keys.rs b/primitives/token-swap/src/storage_keys.rs deleted file mode 100644 index d0aafc0d5c273..0000000000000 --- a/primitives/token-swap/src/storage_keys.rs +++ /dev/null @@ -1,51 +0,0 @@ -// 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 . - -//! Storage keys of bridge token swap pallet. - -use frame_support::Identity; -use sp_core::{storage::StorageKey, H256}; - -/// Name of the `PendingSwaps` storage map. -pub const PENDING_SWAPS_MAP_NAME: &str = "PendingSwaps"; - -/// Storage key of `PendingSwaps` value with given token swap hash. -pub fn pending_swaps_key(pallet_prefix: &str, token_swap_hash: H256) -> StorageKey { - bp_runtime::storage_map_final_key::( - pallet_prefix, - PENDING_SWAPS_MAP_NAME, - token_swap_hash.as_ref(), - ) -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - - #[test] - fn pending_swaps_key_computed_properly() { - // If this test fails, then something has been changed in module storage that may break - // all previous swaps. - let storage_key = pending_swaps_key("BridgeTokenSwap", [42u8; 32].into()).0; - assert_eq!( - storage_key, - hex!("76276da64e7a4f454760eedeb4bad11adca2227fef56ad07cc424f1f5d128b9a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a").to_vec(), - "Unexpected storage key: {}", - hex::encode(&storage_key), - ); - } -} diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 018fbfd2dded1..1d1166d1a9d1d 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -25,24 +25,20 @@ strum = { version = "0.21.0", features = ["derive"] } bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } bp-messages = { path = "../../primitives/messages" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } -bp-token-swap = { path = "../../primitives/token-swap" } bp-westend = { path = "../../primitives/chain-westend" } bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } -pallet-bridge-token-swap = { path = "../../modules/token-swap" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 9cdc6cd125e02..2b18475d680ae 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -14,82 +14,46 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use anyhow::anyhow; -use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; +use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, - send_message::{self, DispatchFeePayment}, + encode_message::{CliEncodeMessage, RawMessage}, CliChain, }; -/// Weight of the `system::remark` call at Kusama. -/// -/// This weight is larger (x2) than actual weight at current Kusama runtime to avoid unsuccessful -/// calls in the future. But since it is used only in tests (and on test chains), this is ok. -pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; - -impl CliEncodeCall for Kusama { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), - Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( - relay_kusama_client::runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - ), - ) - .into(), - Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => - match *bridge_instance_index { - bridge::KUSAMA_TO_POLKADOT_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::send_message( - lane.0, payload, fee.0, - ), - ) - .into() - }, - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index +impl CliEncodeMessage for Kusama { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::KUSAMA_TO_POLKADOT_INDEX => + relay_kusama_client::runtime::Call::BridgePolkadotMessages( + relay_kusama_client::runtime::BridgePolkadotMessagesCall::send_message( + lane, payload, fee, ), - }, - _ => anyhow::bail!("Unsupported Kusama call: {:?}", call), + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), }) } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - match *call { - EncodedOrDecodedCall::Decoded(relay_kusama_client::runtime::Call::System( - relay_kusama_client::runtime::SystemCall::remark(_), - )) => Ok(DispatchInfo { - weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }), - _ => anyhow::bail!("Unsupported Kusama call: {:?}", call), - } - } } impl CliChain for Kusama { const RUNTIME_VERSION: RuntimeVersion = bp_kusama::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_kusama::AccountId, - bp_polkadot::AccountPublic, - bp_polkadot::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -97,39 +61,4 @@ impl CliChain for Kusama { ) .into() } - - fn encode_message( - message: encode_message::MessagePayload, - ) -> anyhow::Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| anyhow!("Failed to decode Kusama's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { - type Source = Kusama; - type Target = relay_polkadot_client::Polkadot; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::( - &mut call, - bridge::KUSAMA_TO_POLKADOT_INDEX, - ); - let call = Target::encode_call(&call)?; - let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { - Err(anyhow::format_err!( - "Please specify dispatch weight of the encoded Polkadot call" - )) - })?; - - Ok(send_message::message_payload( - spec_version, - dispatch_weight, - origin, - &call, - DispatchFeePayment::AtSourceChain, - )) - }, - } - } } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 1fc1e8308ef45..a9e99771f5922 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -18,106 +18,46 @@ use crate::cli::{ bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, - send_message::{self, DispatchFeePayment}, + encode_message::{CliEncodeMessage, RawMessage}, CliChain, }; -use anyhow::anyhow; -use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_millau_client::Millau; +use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; -impl CliEncodeCall for Millau { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), - Call::Remark { remark_payload, .. } => - millau_runtime::Call::System(millau_runtime::SystemCall::remark { - remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }) - .into(), - Call::Transfer { recipient, amount } => - millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer { - dest: recipient.raw_id(), - value: amount.cast(), - }) - .into(), - Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => - match *bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - millau_runtime::Call::BridgeRialtoMessages( - millau_runtime::MessagesCall::send_message { - lane_id: lane.0, - payload, - delivery_and_dispatch_fee: fee.cast(), - }, - ) - .into() - }, - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), +impl CliEncodeMessage for Millau { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::MILLAU_TO_RIALTO_INDEX => millau_runtime::Call::BridgeRialtoMessages( + millau_runtime::MessagesCall::send_message { + lane_id: lane, + payload, + delivery_and_dispatch_fee: fee, }, + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), }) } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - Ok(call.to_decoded()?.get_dispatch_info()) - } } impl CliChain for Millau { const RUNTIME_VERSION: RuntimeVersion = millau_runtime::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_millau::AccountId, - bp_rialto::AccountSigner, - bp_rialto::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { millau_runtime::SS58Prefix::get() as u16 } - - // TODO [#854|#843] support multiple bridges? - fn encode_message( - message: encode_message::MessagePayload, - ) -> anyhow::Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| anyhow!("Failed to decode Millau's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { - type Source = Millau; - type Target = relay_rialto_client::Rialto; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::( - &mut call, - bridge::MILLAU_TO_RIALTO_INDEX, - ); - let call = Target::encode_call(&call)?; - let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { - call.to_decoded().map(|call| call.get_dispatch_info().weight) - })?; - - Ok(send_message::message_payload( - spec_version, - dispatch_weight, - origin, - &call, - DispatchFeePayment::AtSourceChain, - )) - }, - } - } } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 16901143e19fb..9b3416f901cfa 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -41,95 +41,28 @@ mod wococo; #[cfg(test)] mod tests { - use crate::cli::{encode_call, send_message}; + use crate::cli::encode_message; use bp_messages::source_chain::TargetHeaderChain; use bp_runtime::Chain as _; use codec::Encode; - use frame_support::dispatch::GetDispatchInfo; use relay_millau_client::Millau; use relay_rialto_client::Rialto; use relay_substrate_client::{SignParam, TransactionSignScheme, UnsignedTransaction}; - use sp_core::Pair; - use sp_runtime::traits::{IdentifyAccount, Verify}; #[test] - fn millau_signature_is_valid_on_rialto() { - let millau_sign = relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); - - let call = - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); - - let millau_public: bp_millau::AccountSigner = millau_sign.public().into(); - let millau_account_id: bp_millau::AccountId = millau_public.into_account(); - - let digest = millau_runtime::millau_to_rialto_account_ownership_digest( - &call, - millau_account_id, - rialto_runtime::VERSION.spec_version, - ); - - let rialto_signer = - relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); - let signature = rialto_signer.sign(&digest); - - assert!(signature.verify(&digest[..], &rialto_signer.public())); - } - - #[test] - fn rialto_signature_is_valid_on_millau() { - let rialto_sign = relay_rialto_client::SigningParams::from_string("//Dave", None).unwrap(); - - let call = - millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); - - let rialto_public: bp_rialto::AccountSigner = rialto_sign.public().into(); - let rialto_account_id: bp_rialto::AccountId = rialto_public.into_account(); - - let digest = rialto_runtime::rialto_to_millau_account_ownership_digest( - &call, - rialto_account_id, - millau_runtime::VERSION.spec_version, - ); - - let millau_signer = - relay_millau_client::SigningParams::from_string("//Dave", None).unwrap(); - let signature = millau_signer.sign(&digest); - - assert!(signature.verify(&digest[..], &millau_signer.public())); - } - - #[test] - fn maximal_rialto_to_millau_message_arguments_size_is_computed_correctly() { + fn maximal_rialto_to_millau_message_size_is_computed_correctly() { use rialto_runtime::millau_messages::Millau; - let maximal_remark_size = encode_call::compute_maximal_message_arguments_size( + let maximal_message_size = encode_message::compute_maximal_message_size( bp_rialto::Rialto::max_extrinsic_size(), bp_millau::Millau::max_extrinsic_size(), ); - let call: millau_runtime::Call = - millau_runtime::SystemCall::remark { remark: vec![42; maximal_remark_size as _] } - .into(); - let payload = send_message::message_payload( - Default::default(), - call.get_dispatch_info().weight, - bp_message_dispatch::CallOrigin::SourceRoot, - &call, - send_message::DispatchFeePayment::AtSourceChain, - ); - assert_eq!(Millau::verify_message(&payload), Ok(())); + let message = vec![42; maximal_message_size as _]; + assert_eq!(Millau::verify_message(&message), Ok(())); - let call: millau_runtime::Call = - millau_runtime::SystemCall::remark { remark: vec![42; (maximal_remark_size + 1) as _] } - .into(); - let payload = send_message::message_payload( - Default::default(), - call.get_dispatch_info().weight, - bp_message_dispatch::CallOrigin::SourceRoot, - &call, - send_message::DispatchFeePayment::AtSourceChain, - ); - assert!(Millau::verify_message(&payload).is_err()); + let message = vec![42; (maximal_message_size + 1) as _]; + assert!(Millau::verify_message(&message).is_err()); } #[test] @@ -141,65 +74,6 @@ mod tests { "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", ) } - - #[test] - fn maximal_rialto_to_millau_message_dispatch_weight_is_computed_correctly() { - use rialto_runtime::millau_messages::Millau; - - let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_millau::Millau::max_extrinsic_weight(), - ); - let call: millau_runtime::Call = - rialto_runtime::SystemCall::remark { remark: vec![] }.into(); - - let payload = send_message::message_payload( - Default::default(), - maximal_dispatch_weight, - bp_message_dispatch::CallOrigin::SourceRoot, - &call, - send_message::DispatchFeePayment::AtSourceChain, - ); - assert_eq!(Millau::verify_message(&payload), Ok(())); - - let payload = send_message::message_payload( - Default::default(), - maximal_dispatch_weight + 1, - bp_message_dispatch::CallOrigin::SourceRoot, - &call, - send_message::DispatchFeePayment::AtSourceChain, - ); - assert!(Millau::verify_message(&payload).is_err()); - } - - #[test] - fn maximal_weight_fill_block_to_rialto_is_generated_correctly() { - use millau_runtime::rialto_messages::Rialto; - - let maximal_dispatch_weight = send_message::compute_maximal_message_dispatch_weight( - bp_rialto::Rialto::max_extrinsic_weight(), - ); - let call: rialto_runtime::Call = - millau_runtime::SystemCall::remark { remark: vec![] }.into(); - - let payload = send_message::message_payload( - Default::default(), - maximal_dispatch_weight, - bp_message_dispatch::CallOrigin::SourceRoot, - &call, - send_message::DispatchFeePayment::AtSourceChain, - ); - assert_eq!(Rialto::verify_message(&payload), Ok(())); - - let payload = send_message::message_payload( - Default::default(), - maximal_dispatch_weight + 1, - bp_message_dispatch::CallOrigin::SourceRoot, - &call, - send_message::DispatchFeePayment::AtSourceChain, - ); - assert!(Rialto::verify_message(&payload).is_err()); - } - #[test] fn rialto_tx_extra_bytes_constant_is_correct() { let rialto_call = diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 7ae1cbc477777..3ef7523f2a533 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -14,82 +14,46 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use anyhow::anyhow; -use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; +use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, - send_message::{self, DispatchFeePayment}, + encode_message::{CliEncodeMessage, RawMessage}, CliChain, }; -/// Weight of the `system::remark` call at Polkadot. -/// -/// This weight is larger (x2) than actual weight at current Polkadot runtime to avoid unsuccessful -/// calls in the future. But since it is used only in tests (and on test chains), this is ok. -pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; - -impl CliEncodeCall for Polkadot { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), - Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( - relay_polkadot_client::runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - ), - ) - .into(), - Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => - match *bridge_instance_index { - bridge::POLKADOT_TO_KUSAMA_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::send_message( - lane.0, payload, fee.0, - ), - ) - .into() - }, - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index +impl CliEncodeMessage for Polkadot { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::POLKADOT_TO_KUSAMA_INDEX => + relay_polkadot_client::runtime::Call::BridgeKusamaMessages( + relay_polkadot_client::runtime::BridgeKusamaMessagesCall::send_message( + lane, payload, fee, ), - }, - _ => anyhow::bail!("Unsupported Polkadot call: {:?}", call), + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), }) } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - match *call { - EncodedOrDecodedCall::Decoded(relay_polkadot_client::runtime::Call::System( - relay_polkadot_client::runtime::SystemCall::remark(_), - )) => Ok(DispatchInfo { - weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }), - _ => anyhow::bail!("Unsupported Polkadot call: {:?}", call), - } - } } impl CliChain for Polkadot { const RUNTIME_VERSION: RuntimeVersion = bp_polkadot::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_polkadot::AccountId, - bp_kusama::AccountPublic, - bp_kusama::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -97,39 +61,4 @@ impl CliChain for Polkadot { ) .into() } - - fn encode_message( - message: encode_message::MessagePayload, - ) -> anyhow::Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| anyhow!("Failed to decode Polkadot's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { - type Source = Polkadot; - type Target = relay_kusama_client::Kusama; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::( - &mut call, - bridge::POLKADOT_TO_KUSAMA_INDEX, - ); - let call = Target::encode_call(&call)?; - let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { - Err(anyhow::format_err!( - "Please specify dispatch weight of the encoded Kusama call" - )) - })?; - - Ok(send_message::message_payload( - spec_version, - dispatch_weight, - origin, - &call, - DispatchFeePayment::AtSourceChain, - )) - }, - } - } } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 8f26a64a4e326..0255a055a5742 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -18,105 +18,46 @@ use crate::cli::{ bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, - send_message::{self, DispatchFeePayment}, + encode_message::{CliEncodeMessage, RawMessage}, CliChain, }; -use anyhow::anyhow; -use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_client::Rialto; +use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; -impl CliEncodeCall for Rialto { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), - Call::Remark { remark_payload, .. } => - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { - remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }) - .into(), - Call::Transfer { recipient, amount } => - rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer { - dest: recipient.raw_id().into(), - value: amount.0, - }) - .into(), - Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => - match *bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - rialto_runtime::Call::BridgeMillauMessages( - rialto_runtime::MessagesCall::send_message { - lane_id: lane.0, - payload, - delivery_and_dispatch_fee: fee.0, - }, - ) - .into() - }, - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), +impl CliEncodeMessage for Rialto { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::RIALTO_TO_MILLAU_INDEX => rialto_runtime::Call::BridgeMillauMessages( + rialto_runtime::MessagesCall::send_message { + lane_id: lane, + payload, + delivery_and_dispatch_fee: fee, }, + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), }) } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - Ok(call.to_decoded()?.get_dispatch_info()) - } } impl CliChain for Rialto { const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_rialto::AccountId, - bp_millau::AccountSigner, - bp_millau::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { rialto_runtime::SS58Prefix::get() as u16 } - - fn encode_message( - message: encode_message::MessagePayload, - ) -> anyhow::Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| anyhow!("Failed to decode Rialto's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { - type Source = Rialto; - type Target = relay_millau_client::Millau; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::( - &mut call, - bridge::RIALTO_TO_MILLAU_INDEX, - ); - let call = Target::encode_call(&call)?; - let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { - call.to_decoded().map(|call| call.get_dispatch_info().weight) - })?; - - Ok(send_message::message_payload( - spec_version, - dispatch_weight, - origin, - &call, - DispatchFeePayment::AtSourceChain, - )) - }, - } - } } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 0ed39faa543b7..8e87c3ede706f 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -16,63 +16,17 @@ //! Rialto parachain specification for CLI. -use crate::cli::{ - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, -}; -use bp_message_dispatch::MessagePayload; -use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchInfo, GetDispatchInfo}; +use crate::cli::CliChain; use relay_rialto_parachain_client::RialtoParachain; use sp_version::RuntimeVersion; -impl CliEncodeCall for RialtoParachain { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), - Call::Remark { remark_payload, .. } => rialto_parachain_runtime::Call::System( - rialto_parachain_runtime::SystemCall::remark { - remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }, - ) - .into(), - Call::Transfer { recipient, amount } => rialto_parachain_runtime::Call::Balances( - rialto_parachain_runtime::BalancesCall::transfer { - dest: recipient.raw_id().into(), - value: amount.0, - }, - ) - .into(), - Call::BridgeSendMessage { .. } => { - anyhow::bail!("Bridge messages are not (yet) supported here",) - }, - }) - } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - Ok(call.to_decoded()?.get_dispatch_info()) - } -} - impl CliChain for RialtoParachain { const RUNTIME_VERSION: RuntimeVersion = rialto_parachain_runtime::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_rialto_parachain::AccountId, - bp_millau::AccountSigner, - bp_millau::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { rialto_parachain_runtime::SS58Prefix::get() as u16 } - - fn encode_message( - _message: encode_message::MessagePayload, - ) -> anyhow::Result { - anyhow::bail!("Not supported") - } } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index ceef4c1f532c9..0d2b800e79bf8 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -14,119 +14,47 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use anyhow::anyhow; -use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; +use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, - send_message::{self, DispatchFeePayment}, + encode_message::{CliEncodeMessage, RawMessage}, CliChain, }; -/// Weight of the `system::remark` call at Rococo. -/// -/// This weight is larger (x2) than actual weight at current Rococo runtime to avoid unsuccessful -/// calls in the future. But since it is used only in tests (and on test chains), this is ok. -pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; - -impl CliEncodeCall for Rococo { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), - Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( - relay_rococo_client::runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - ), - ) - .into(), - Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => - match *bridge_instance_index { - bridge::ROCOCO_TO_WOCOCO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_rococo_client::runtime::Call::BridgeWococoMessages( - relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message( - lane.0, payload, fee.0, - ), - ) - .into() - }, - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index +impl CliEncodeMessage for Rococo { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::ROCOCO_TO_WOCOCO_INDEX => + relay_rococo_client::runtime::Call::BridgeWococoMessages( + relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message( + lane, payload, fee, ), - }, - _ => anyhow::bail!("The call is not supported"), + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), }) } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - match *call { - EncodedOrDecodedCall::Decoded(relay_rococo_client::runtime::Call::System( - relay_rococo_client::runtime::SystemCall::remark(_), - )) => Ok(DispatchInfo { - weight: SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }), - _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), - } - } } - impl CliChain for Rococo { const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_rococo::AccountId, - bp_wococo::AccountPublic, - bp_wococo::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { 42 } - - fn encode_message( - message: encode_message::MessagePayload, - ) -> anyhow::Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| anyhow!("Failed to decode Rococo's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { - type Source = Rococo; - type Target = relay_wococo_client::Wococo; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::( - &mut call, - bridge::ROCOCO_TO_WOCOCO_INDEX, - ); - let call = Target::encode_call(&call)?; - let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { - Err(anyhow::format_err!( - "Please specify dispatch weight of the encoded Wococo call" - )) - })?; - - Ok(send_message::message_payload( - spec_version, - dispatch_weight, - origin, - &call, - DispatchFeePayment::AtSourceChain, - )) - }, - } - } } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 8d3b5db9ab37f..eb578ddb78348 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -16,8 +16,7 @@ //! Westend chain specification for CLI. -use crate::cli::{encode_message, CliChain}; -use anyhow::anyhow; +use crate::cli::CliChain; use relay_westend_client::Westend; use sp_version::RuntimeVersion; @@ -25,7 +24,7 @@ impl CliChain for Westend { const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = Vec; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -33,10 +32,4 @@ impl CliChain for Westend { ) .into() } - - fn encode_message( - _message: encode_message::MessagePayload, - ) -> anyhow::Result { - Err(anyhow!("Sending messages from Westend is not yet supported.")) - } } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 46dec2a3c90e3..8edb132a83abc 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -14,113 +14,48 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use anyhow::anyhow; -use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; -use codec::Decode; -use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; +use relay_substrate_client::BalanceOf; use relay_wococo_client::Wococo; use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{self, Call, CliEncodeCall}, - encode_message, - send_message::{self, DispatchFeePayment}, + encode_message::{CliEncodeMessage, RawMessage}, CliChain, }; -impl CliEncodeCall for Wococo { - fn encode_call(call: &Call) -> anyhow::Result> { - Ok(match call { - Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), - Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( - relay_wococo_client::runtime::SystemCall::remark( - remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - ), - ) - .into(), - Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => - match *bridge_instance_index { - bridge::WOCOCO_TO_ROCOCO_INDEX => { - let payload = Decode::decode(&mut &*payload.0)?; - relay_wococo_client::runtime::Call::BridgeRococoMessages( - relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message( - lane.0, payload, fee.0, - ), - ) - .into() - }, - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index +impl CliEncodeMessage for Wococo { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::WOCOCO_TO_ROCOCO_INDEX => + relay_wococo_client::runtime::Call::BridgeRococoMessages( + relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message( + lane, payload, fee, ), - }, - _ => anyhow::bail!("The call is not supported"), + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), }) } - - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { - match *call { - EncodedOrDecodedCall::Decoded(relay_wococo_client::runtime::Call::System( - relay_wococo_client::runtime::SystemCall::remark(_), - )) => Ok(DispatchInfo { - weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, - class: DispatchClass::Normal, - pays_fee: Pays::Yes, - }), - _ => anyhow::bail!("Unsupported Wococo call: {:?}", call), - } - } } impl CliChain for Wococo { const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = MessagePayload< - bp_wococo::AccountId, - bp_rococo::AccountPublic, - bp_rococo::Signature, - Vec, - >; + type MessagePayload = Vec; fn ss58_format() -> u16 { 42 } - - fn encode_message( - message: encode_message::MessagePayload, - ) -> anyhow::Result { - match message { - encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) - .map_err(|e| anyhow!("Failed to decode Wococo's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { - type Source = Wococo; - type Target = relay_rococo_client::Rococo; - - sender.enforce_chain::(); - let spec_version = Target::RUNTIME_VERSION.spec_version; - let origin = CallOrigin::SourceAccount(sender.raw_id()); - encode_call::preprocess_call::( - &mut call, - bridge::WOCOCO_TO_ROCOCO_INDEX, - ); - let call = Target::encode_call(&call)?; - let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { - Err(anyhow::format_err!( - "Please specify dispatch weight of the encoded Rococo call" - )) - })?; - - Ok(send_message::message_payload( - spec_version, - dispatch_weight, - origin, - &call, - DispatchFeePayment::AtSourceChain, - )) - }, - } - } } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 2eb836a84a753..c8476725fff2f 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -73,12 +73,9 @@ macro_rules! select_full_bridge { // Send-message / Estimate-fee #[allow(unused_imports)] use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - // Send-message - #[allow(unused_imports)] - use millau_runtime::millau_to_rialto_account_ownership_digest as account_ownership_digest; $generic - } + }, FullBridge::RialtoToMillau => { type Source = relay_rialto_client::Rialto; #[allow(dead_code)] @@ -96,12 +93,8 @@ macro_rules! select_full_bridge { #[allow(unused_imports)] use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - // Send-message - #[allow(unused_imports)] - use rialto_runtime::rialto_to_millau_account_ownership_digest as account_ownership_digest; - $generic - } + }, FullBridge::RococoToWococo => { type Source = relay_rococo_client::Rococo; #[allow(dead_code)] @@ -118,12 +111,9 @@ macro_rules! select_full_bridge { // Send-message / Estimate-fee #[allow(unused_imports)] use bp_wococo::TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - // Send-message - #[allow(unused_imports)] - use relay_rococo_client::runtime::rococo_to_wococo_account_ownership_digest as account_ownership_digest; $generic - } + }, FullBridge::WococoToRococo => { type Source = relay_wococo_client::Wococo; #[allow(dead_code)] @@ -140,12 +130,9 @@ macro_rules! select_full_bridge { // Send-message / Estimate-fee #[allow(unused_imports)] use bp_rococo::TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - // Send-message - #[allow(unused_imports)] - use relay_wococo_client::runtime::wococo_to_rococo_account_ownership_digest as account_ownership_digest; $generic - } + }, FullBridge::KusamaToPolkadot => { type Source = relay_kusama_client::Kusama; #[allow(dead_code)] @@ -162,12 +149,9 @@ macro_rules! select_full_bridge { // Send-message / Estimate-fee #[allow(unused_imports)] use bp_polkadot::TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - // Send-message - #[allow(unused_imports)] - use relay_kusama_client::runtime::kusama_to_polkadot_account_ownership_digest as account_ownership_digest; $generic - } + }, FullBridge::PolkadotToKusama => { type Source = relay_polkadot_client::Polkadot; #[allow(dead_code)] @@ -184,12 +168,9 @@ macro_rules! select_full_bridge { // Send-message / Estimate-fee #[allow(unused_imports)] use bp_kusama::TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - // Send-message - #[allow(unused_imports)] - use relay_polkadot_client::runtime::polkadot_to_kusama_account_ownership_digest as account_ownership_digest; $generic - } + }, } }; } diff --git a/relays/bin-substrate/src/cli/derive_account.rs b/relays/bin-substrate/src/cli/derive_account.rs deleted file mode 100644 index 5b809eb69f222..0000000000000 --- a/relays/bin-substrate/src/cli/derive_account.rs +++ /dev/null @@ -1,101 +0,0 @@ -// 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 . - -use crate::{ - cli::{bridge::FullBridge, AccountId}, - select_full_bridge, -}; -use relay_substrate_client::Chain; -use structopt::StructOpt; -use strum::VariantNames; - -/// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target chain. -/// -/// The (derived) target chain `AccountId` is going to be used as dispatch origin of the call -/// that has been sent over the bridge. -/// This account can also be used to receive target-chain funds (or other form of ownership), -/// since messages sent over the bridge will be able to spend these. -#[derive(StructOpt)] -pub struct DeriveAccount { - /// A bridge instance to initialize. - #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] - bridge: FullBridge, - /// Source-chain address to derive Target-chain address from. - account: AccountId, -} - -impl DeriveAccount { - /// Parse CLI arguments and derive account. - /// - /// Returns both the Source account in correct SS58 format and the derived account. - fn derive_account(&self) -> (AccountId, AccountId) { - select_full_bridge!(self.bridge, { - let mut account = self.account.clone(); - account.enforce_chain::(); - let acc = bp_runtime::SourceAccount::Account(account.raw_id()); - let id = derive_account(acc); - let derived_account = AccountId::from_raw::(id); - (account, derived_account) - }) - } - - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - select_full_bridge!(self.bridge, { - let (account, derived_account) = self.derive_account(); - println!("Source address:\n{} ({})", account, Source::NAME); - println!("->Corresponding (derived) address:\n{} ({})", derived_account, Target::NAME,); - - Ok(()) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn derive_account_cli(bridge: &str, account: &str) -> (AccountId, AccountId) { - DeriveAccount::from_iter(vec!["derive-account", bridge, account]).derive_account() - } - - #[test] - fn should_derive_accounts_correctly() { - // given - let rialto = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU"; - let millau = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"; - - // when - let (rialto_parsed, rialto_derived) = derive_account_cli("rialto-to-millau", rialto); - let (millau_parsed, millau_derived) = derive_account_cli("millau-to-rialto", millau); - let (millau2_parsed, millau2_derived) = derive_account_cli("millau-to-rialto", rialto); - - // then - assert_eq!(format!("{}", rialto_parsed), rialto); - assert_eq!(format!("{}", millau_parsed), millau); - assert_eq!(format!("{}", millau2_parsed), millau); - - assert_eq!( - format!("{}", rialto_derived), - "74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5" - ); - assert_eq!( - format!("{}", millau_derived), - "5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2" - ); - assert_eq!(millau_derived, millau2_derived); - } -} diff --git a/relays/bin-substrate/src/cli/encode_call.rs b/relays/bin-substrate/src/cli/encode_call.rs deleted file mode 100644 index e288e2c13d6cd..0000000000000 --- a/relays/bin-substrate/src/cli/encode_call.rs +++ /dev/null @@ -1,354 +0,0 @@ -// 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 . - -use crate::{ - cli::{ - bridge::FullBridge, AccountId, Balance, CliChain, ExplicitOrMaximal, HexBytes, HexLaneId, - }, - select_full_bridge, -}; -use bp_runtime::EncodedOrDecodedCall; -use frame_support::weights::DispatchInfo; -use relay_substrate_client::Chain; -use structopt::StructOpt; -use strum::VariantNames; - -/// Encode source chain runtime call. -#[derive(StructOpt, Debug)] -pub struct EncodeCall { - /// A bridge instance to encode call for. - #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] - bridge: FullBridge, - #[structopt(flatten)] - call: Call, -} - -/// All possible messages that may be delivered to generic Substrate chain. -/// -/// Note this enum may be used in the context of both Source (as part of `encode-call`) -/// and Target chain (as part of `encode-message/send-message`). -#[derive(StructOpt, Debug, PartialEq, Eq)] -pub enum Call { - /// Raw bytes for the message - Raw { - /// Raw, SCALE-encoded message - data: HexBytes, - }, - /// Make an on-chain remark (comment). - Remark { - /// Explicit remark payload. - #[structopt(long, conflicts_with("remark-size"))] - remark_payload: Option, - /// Remark size. If not passed, small UTF8-encoded string is generated by relay as remark. - #[structopt(long, conflicts_with("remark-payload"))] - remark_size: Option>, - }, - /// Transfer the specified `amount` of native tokens to a particular `recipient`. - Transfer { - /// Address of an account to receive the transfer. - #[structopt(long)] - recipient: AccountId, - /// Amount of target tokens to send in target chain base currency units. - #[structopt(long)] - amount: Balance, - }, - /// A call to the specific Bridge Messages pallet to queue message to be sent over a bridge. - BridgeSendMessage { - /// An index of the bridge instance which represents the expected target chain. - #[structopt(skip = 255)] - bridge_instance_index: u8, - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// Raw SCALE-encoded Message Payload to submit to the messages pallet. - /// - /// This can be obtained by encoding call for the target chain. - #[structopt(long)] - payload: HexBytes, - /// Declared delivery and dispatch fee in base source-chain currency units. - #[structopt(long)] - fee: Balance, - }, -} - -pub trait CliEncodeCall: Chain { - /// Encode a CLI call. - fn encode_call(call: &Call) -> anyhow::Result>; - - /// Get dispatch info for the call. - fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result; -} - -impl EncodeCall { - fn encode(&mut self) -> anyhow::Result { - select_full_bridge!(self.bridge, { - preprocess_call::(&mut self.call, self.bridge.bridge_instance_index()); - let call = Source::encode_call(&self.call)?; - - let encoded = HexBytes::encode(&call); - - log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); - log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call) - .map(|dispatch_info| format!("{}", dispatch_info.weight)) - .unwrap_or_else(|_| "".to_string()) - ); - log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); - - Ok(encoded) - }) - } - - /// Run the command. - pub async fn run(mut self) -> anyhow::Result<()> { - println!("{:?}", self.encode()?); - Ok(()) - } -} - -/// Prepare the call to be passed to [`CliEncodeCall::encode_call`]. -/// -/// This function will fill in all optional and missing pieces and will make sure that -/// values are converted to bridge-specific ones. -/// -/// Most importantly, the method will fill-in [`bridge_instance_index`] parameter for -/// target-chain specific calls. -pub(crate) fn preprocess_call( - call: &mut Call, - bridge_instance: u8, -) { - match *call { - Call::Raw { .. } => {}, - Call::Remark { ref remark_size, ref mut remark_payload } => - if remark_payload.is_none() { - *remark_payload = Some(HexBytes(generate_remark_payload( - remark_size, - compute_maximal_message_arguments_size( - Source::max_extrinsic_size(), - Target::max_extrinsic_size(), - ), - ))); - }, - Call::Transfer { ref mut recipient, .. } => { - recipient.enforce_chain::(); - }, - Call::BridgeSendMessage { ref mut bridge_instance_index, .. } => { - *bridge_instance_index = bridge_instance; - }, - }; -} - -fn generate_remark_payload( - remark_size: &Option>, - maximal_allowed_size: u32, -) -> Vec { - match remark_size { - Some(ExplicitOrMaximal::Explicit(remark_size)) => vec![0; *remark_size], - Some(ExplicitOrMaximal::Maximal) => vec![0; maximal_allowed_size as _], - None => format!( - "Unix time: {}", - std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .unwrap_or_default() - .as_secs(), - ) - .as_bytes() - .to_vec(), - } -} - -pub(crate) fn compute_maximal_message_arguments_size( - maximal_source_extrinsic_size: u32, - maximal_target_extrinsic_size: u32, -) -> u32 { - // assume that both signed extensions and other arguments fit 1KB - let service_tx_bytes_on_source_chain = 1024; - let maximal_source_extrinsic_size = - maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; - let maximal_call_size = bridge_runtime_common::messages::target::maximal_incoming_message_size( - maximal_target_extrinsic_size, - ); - let maximal_call_size = if maximal_call_size > maximal_source_extrinsic_size { - maximal_source_extrinsic_size - } else { - maximal_call_size - }; - - // bytes in Call encoding that are used to encode everything except arguments - let service_bytes = 1 + 1 + 4; - maximal_call_size - service_bytes -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cli::send_message::SendMessage; - - #[test] - fn should_encode_transfer_call() { - // given - let mut encode_call = EncodeCall::from_iter(vec![ - "encode-call", - "rialto-to-millau", - "transfer", - "--amount", - "12345", - "--recipient", - "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU", - ]); - - // when - let hex = encode_call.encode().unwrap(); - - // then - assert_eq!( - format!("{:?}", hex), - "0x040000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" - ); - } - - #[test] - fn should_encode_remark_with_default_payload() { - // given - let mut encode_call = - EncodeCall::from_iter(vec!["encode-call", "rialto-to-millau", "remark"]); - - // when - let hex = encode_call.encode().unwrap(); - - // then - assert!(format!("{:?}", hex).starts_with("0x000154556e69782074696d653a")); - } - - #[test] - fn should_encode_remark_with_explicit_payload() { - // given - let mut encode_call = EncodeCall::from_iter(vec![ - "encode-call", - "rialto-to-millau", - "remark", - "--remark-payload", - "1234", - ]); - - // when - let hex = encode_call.encode().unwrap(); - - // then - assert_eq!(format!("{:?}", hex), "0x0001081234"); - } - - #[test] - fn should_encode_remark_with_size() { - // given - let mut encode_call = EncodeCall::from_iter(vec![ - "encode-call", - "rialto-to-millau", - "remark", - "--remark-size", - "12", - ]); - - // when - let hex = encode_call.encode().unwrap(); - - // then - assert_eq!(format!("{:?}", hex), "0x000130000000000000000000000000"); - } - - #[test] - fn should_disallow_both_payload_and_size() { - // when - let err = EncodeCall::from_iter_safe(vec![ - "encode-call", - "rialto-to-millau", - "remark", - "--remark-payload", - "1234", - "--remark-size", - "12", - ]) - .unwrap_err(); - - // then - assert_eq!(err.kind, structopt::clap::ErrorKind::ArgumentConflict); - - let info = err.info.unwrap(); - assert!( - info.contains(&"remark-payload".to_string()) | - info.contains(&"remark-size".to_string()) - ) - } - - #[test] - fn should_encode_raw_call() { - // given - let mut encode_call = EncodeCall::from_iter(vec![ - "encode-call", - "rialto-to-millau", - "raw", - "040000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0", - ]); - - // when - let hex = encode_call.encode().unwrap(); - - // then - assert_eq!( - format!("{:?}", hex), - "0x040000d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27de5c0" - ); - } - - #[async_std::test] - async fn should_encode_bridge_send_message_call() { - // given - let encode_message = SendMessage::from_iter(vec![ - "send-message", - "millau-to-rialto", - "--source-port", - "10946", - "--source-signer", - "//Alice", - "--target-signer", - "//Alice", - "--origin", - "Target", - "remark", - ]) - .encode_payload() - .await - .unwrap(); - - let mut encode_call = EncodeCall::from_iter(vec![ - "encode-call", - "rialto-to-millau", - "bridge-send-message", - "--fee", - "12345", - "--payload", - format!("{:}", &HexBytes::encode(&encode_message)).as_str(), - ]); - - // when - let call_hex = encode_call.encode().unwrap(); - - // then - assert!(format!("{:?}", call_hex).starts_with( - "0x0f030000000001000000000000000000000001d43593c715fdd31c61141abd04a99fd6822c8558854cc\ - de39a5684e7a56da27d01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01" - )) - } -} diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 677fc29ef1531..e74d6da766d52 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -14,107 +14,80 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}, - select_full_bridge, -}; -use frame_support::weights::Weight; +use crate::cli::{ExplicitOrMaximal, HexBytes}; +use bp_messages::LaneId; +use bp_runtime::EncodedOrDecodedCall; +use relay_substrate_client::Chain; use structopt::StructOpt; -use strum::VariantNames; -/// Generic message payload. +/// All possible messages that may be delivered to generic Substrate chain. +/// +/// Note this enum may be used in the context of both Source (as part of `encode-call`) +/// and Target chain (as part of `encode-message/send-message`). #[derive(StructOpt, Debug, PartialEq, Eq)] -pub enum MessagePayload { - /// Raw, SCALE-encoded `MessagePayload`. +pub enum Message { + /// Raw bytes for the message. Raw { - /// Hex-encoded SCALE data. + /// Raw message bytes. data: HexBytes, }, - /// Construct message to send over the bridge. - Call { - /// Message details. - #[structopt(flatten)] - call: crate::cli::encode_call::Call, - /// SS58 encoded Source account that will send the payload. - #[structopt(long)] - sender: AccountId, - /// Weight of the call. - /// - /// It must be specified if the chain runtime is not bundled with the relay, or if - /// you want to override bundled weight. - #[structopt(long)] - dispatch_weight: Option, + /// Message with given size. + Sized { + /// Sized of the message. + size: ExplicitOrMaximal, }, } -/// A `MessagePayload` to encode. -#[derive(StructOpt)] -pub struct EncodeMessage { - /// A bridge instance to initialize. - #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] - bridge: FullBridge, - #[structopt(flatten)] - payload: MessagePayload, -} - -impl EncodeMessage { - /// Run the command. - pub fn encode(self) -> anyhow::Result { - select_full_bridge!(self.bridge, { - let payload = - Source::encode_message(self.payload).map_err(|e| anyhow::format_err!("{}", e))?; - Ok(HexBytes::encode(&payload)) - }) - } +/// Raw, SCALE-encoded message payload used in expected deployment. +pub type RawMessage = Vec; - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - let payload = self.encode()?; - println!("{:?}", payload); - Ok(()) - } +pub trait CliEncodeMessage: Chain { + /// Encode a send message call. + fn encode_send_message_call( + lane: LaneId, + message: RawMessage, + fee: Self::Balance, + bridge_instance_index: u8, + ) -> anyhow::Result>; } -#[cfg(test)] -mod tests { - use super::*; - use sp_core::crypto::Ss58Codec; - - #[test] - fn should_encode_raw_message() { - // given - let msg = "01000000e88514000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"; - let encode_message = - EncodeMessage::from_iter(vec!["encode-message", "rialto-to-millau", "raw", msg]); - - // when - let hex = encode_message.encode().unwrap(); - - // then - assert_eq!(format!("{:?}", hex), format!("0x{}", msg)); - } - - #[test] - fn should_encode_remark_with_size() { - // given - let sender = sp_keyring::AccountKeyring::Alice.to_account_id().to_ss58check(); - let encode_message = EncodeMessage::from_iter(vec![ - "encode-message", - "rialto-to-millau", - "call", - "--sender", - &sender, - "--dispatch-weight", - "42", - "remark", - "--remark-size", - "12", - ]); +/// Encode message payload passed through CLI flags. +pub(crate) fn encode_message( + message: &Message, +) -> anyhow::Result { + Ok(match message { + Message::Raw { ref data } => data.0.clone(), + Message::Sized { ref size } => match *size { + ExplicitOrMaximal::Explicit(size) => vec![42; size as usize], + ExplicitOrMaximal::Maximal => { + let maximal_size = compute_maximal_message_size( + Source::max_extrinsic_size(), + Target::max_extrinsic_size(), + ); + vec![42; maximal_size as usize] + }, + }, + }) +} - // when - let hex = encode_message.encode().unwrap(); +/// Compute maximal message size, given max extrinsic size at source and target chains. +pub(crate) fn compute_maximal_message_size( + maximal_source_extrinsic_size: u32, + maximal_target_extrinsic_size: u32, +) -> u32 { + // assume that both signed extensions and other arguments fit 1KB + let service_tx_bytes_on_source_chain = 1024; + let maximal_source_extrinsic_size = + maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; + let maximal_message_size = + bridge_runtime_common::messages::target::maximal_incoming_message_size( + maximal_target_extrinsic_size, + ); + let maximal_message_size = if maximal_message_size > maximal_source_extrinsic_size { + maximal_source_extrinsic_size + } else { + maximal_message_size + }; - // then - assert_eq!(format!("{:?}", hex), "0x010000002a0000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); - } + maximal_message_size } diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index bab625314e824..bf13996ec52be 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -17,7 +17,7 @@ use crate::{ cli::{ bridge::FullBridge, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams, + Balance, HexBytes, HexLaneId, SourceConnectionParams, }, select_full_bridge, }; @@ -48,7 +48,7 @@ pub struct EstimateFee { conversion_rate_override: Option, /// Payload to send over the bridge. #[structopt(flatten)] - payload: crate::cli::encode_message::MessagePayload, + payload: crate::cli::encode_message::Message, } /// A way to override conversion rate between bridge tokens. @@ -82,8 +82,8 @@ impl EstimateFee { select_full_bridge!(bridge, { let source_client = source.to_client::().await?; let lane = lane.into(); - let payload = - Source::encode_message(payload).map_err(|e| anyhow::format_err!("{:?}", e))?; + let payload = crate::cli::encode_message::encode_message::(&payload) + .map_err(|e| anyhow::format_err!("{:?}", e))?; let fee = estimate_message_delivery_and_dispatch_fee::( &source_client, @@ -219,14 +219,10 @@ async fn do_estimate_message_delivery_and_dispatch_fee #[cfg(test)] mod tests { use super::*; - use crate::cli::{encode_call, RuntimeVersionType, SourceRuntimeVersionParams}; - use sp_core::crypto::Ss58Codec; + use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams}; #[test] fn should_parse_cli_options() { - // given - let alice = sp_keyring::AccountKeyring::Alice.to_account_id().to_ss58check(); - // when let res = EstimateFee::from_iter(vec![ "estimate_fee", @@ -235,13 +231,7 @@ mod tests { "1234", "--conversion-rate-override", "42.5", - "call", - "--sender", - &alice, - "--dispatch-weight", - "42", - "remark", - "--remark-payload", + "raw", "1234", ]); @@ -262,13 +252,8 @@ mod tests { source_transaction_version: None, } }, - payload: crate::cli::encode_message::MessagePayload::Call { - sender: alice.parse().unwrap(), - call: encode_call::Call::Remark { - remark_payload: Some(HexBytes(vec![0x12, 0x34])), - remark_size: None, - }, - dispatch_weight: Some(42), + payload: crate::cli::encode_message::Message::Raw { + data: HexBytes(vec![0x12, 0x34]) } } ); diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index df57537f588ec..fddae4ee7abb5 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -20,19 +20,16 @@ use std::convert::TryInto; use codec::{Decode, Encode}; use relay_substrate_client::ChainRuntimeVersion; -use sp_runtime::app_crypto::Ss58Codec; use structopt::{clap::arg_enum, StructOpt}; use strum::{EnumString, EnumVariantNames}; use bp_messages::LaneId; pub(crate) mod bridge; -pub(crate) mod encode_call; pub(crate) mod encode_message; pub(crate) mod estimate_fee; pub(crate) mod send_message; -mod derive_account; mod init_bridge; mod register_parachain; mod reinit_bridge; @@ -40,7 +37,6 @@ mod relay_headers; mod relay_headers_and_messages; mod relay_messages; mod resubmit_transactions; -mod swap_tokens; /// Parse relay CLI args. pub fn parse_args() -> Command { @@ -83,25 +79,10 @@ pub enum Command { /// The message is being sent to the source chain, delivered to the target chain and dispatched /// there. SendMessage(send_message::SendMessage), - /// Generate SCALE-encoded `Call` for choosen network. - /// - /// The call can be used either as message payload or can be wrapped into a transaction - /// and executed on the chain directly. - EncodeCall(encode_call::EncodeCall), - /// Generate SCALE-encoded `MessagePayload` object that can be sent over selected bridge. - /// - /// The `MessagePayload` can be then fed to `Messages::send_message` function and sent over - /// the bridge. - EncodeMessage(encode_message::EncodeMessage), /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. EstimateFee(estimate_fee::EstimateFee), - /// Given a source chain `AccountId`, derive the corresponding `AccountId` for the target - /// chain. - DeriveAccount(derive_account::DeriveAccount), /// Resubmit transactions with increased tip if they are stalled. ResubmitTransactions(resubmit_transactions::ResubmitTransactions), - /// Swap tokens using token-swap bridge. - SwapTokens(swap_tokens::SwapTokens), /// Register parachain. RegisterParachain(register_parachain::RegisterParachain), } @@ -134,12 +115,8 @@ impl Command { Self::InitBridge(arg) => arg.run().await?, Self::ReinitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, - Self::EncodeCall(arg) => arg.run().await?, - Self::EncodeMessage(arg) => arg.run().await?, Self::EstimateFee(arg) => arg.run().await?, - Self::DeriveAccount(arg) => arg.run().await?, Self::ResubmitTransactions(arg) => arg.run().await?, - Self::SwapTokens(arg) => arg.run().await?, Self::RegisterParachain(arg) => arg.run().await?, } Ok(()) @@ -184,66 +161,7 @@ impl Balance { } } -/// Generic account id with custom parser. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct AccountId { - account: sp_runtime::AccountId32, - ss58_format: sp_core::crypto::Ss58AddressFormat, -} - -impl std::fmt::Display for AccountId { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "{}", self.account.to_ss58check_with_version(self.ss58_format)) - } -} - -impl std::str::FromStr for AccountId { - type Err = String; - - fn from_str(s: &str) -> Result { - let (account, ss58_format) = sp_runtime::AccountId32::from_ss58check_with_version(s) - .map_err(|err| format!("Unable to decode SS58 address: {:?}", err))?; - Ok(Self { account, ss58_format }) - } -} - -const SS58_FORMAT_PROOF: &str = "u16 -> Ss58Format is infallible; qed"; - -impl AccountId { - /// Create new SS58-formatted address from raw account id. - pub fn from_raw(account: sp_runtime::AccountId32) -> Self { - Self { account, ss58_format: T::ss58_format().try_into().expect(SS58_FORMAT_PROOF) } - } - - /// Enforces formatting account to be for given [`CliChain`] type. - /// - /// This will change the `ss58format` of the account to match the requested one. - /// Note that a warning will be produced in case the current format does not match - /// the requested one, but the conversion always succeeds. - pub fn enforce_chain(&mut self) { - let original = self.clone(); - self.ss58_format = T::ss58_format().try_into().expect(SS58_FORMAT_PROOF); - log::debug!("{} SS58 format: {} (RAW: {})", self, self.ss58_format, self.account); - if original.ss58_format != self.ss58_format { - log::warn!( - target: "bridge", - "Address {} does not seem to match {}'s SS58 format (got: {}, expected: {}).\nConverted to: {}", - original, - T::NAME, - original.ss58_format, - self.ss58_format, - self, - ) - } - } - - /// Returns the raw (no SS58-prefixed) account id. - pub fn raw_id(&self) -> sp_runtime::AccountId32 { - self.account.clone() - } -} - -/// Bridge-supported network definition. +// Bridge-supported network definition. /// /// Used to abstract away CLI commands. pub trait CliChain: relay_substrate_client::Chain { @@ -262,11 +180,6 @@ pub trait CliChain: relay_substrate_client::Chain { /// Numeric value of SS58 format. fn ss58_format() -> u16; - - /// Construct message payload to be sent over the bridge. - fn encode_message( - message: crate::cli::encode_message::MessagePayload, - ) -> anyhow::Result; } /// Lane id. @@ -623,29 +536,8 @@ declare_chain_options!(Parachain, parachain); #[cfg(test)] mod tests { - use std::str::FromStr; - - use sp_core::Pair; - use super::*; - - #[test] - fn should_format_addresses_with_ss58_format() { - // given - let rialto1 = "5sauUXUfPjmwxSgmb3tZ5d6yx24eZX4wWJ2JtVUBaQqFbvEU"; - let rialto2 = "5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2"; - let millau1 = "752paRyW1EGfq9YLTSSqcSJ5hqnBDidBmaftGhBo8fy6ypW9"; - let millau2 = "74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5"; - - let expected = vec![rialto1, rialto2, millau1, millau2]; - - // when - let parsed = expected.iter().map(|s| AccountId::from_str(s).unwrap()).collect::>(); - - let actual = parsed.iter().map(|a| format!("{}", a)).collect::>(); - - assert_eq!(actual, expected) - } + use sp_core::Pair; #[test] fn hex_bytes_display_matches_from_str_for_clap() { diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index c761a5dd1a603..79515b31dcfa9 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -15,8 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ - swap_tokens::wait_until_transaction_is_finalized, Balance, ParachainConnectionParams, - RelaychainConnectionParams, RelaychainSigningParams, + Balance, ParachainConnectionParams, RelaychainConnectionParams, RelaychainSigningParams, }; use codec::Encode; @@ -30,7 +29,8 @@ use polkadot_runtime_common::{ }; use polkadot_runtime_parachains::paras::ParaLifecycle; use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, Client, SignParam, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, CallOf, Chain, Client, HashOf, SignParam, Subscription, TransactionSignScheme, + TransactionStatusOf, UnsignedTransaction, }; use rialto_runtime::SudoCall; use sp_core::{ @@ -270,6 +270,46 @@ impl RegisterParachain { } } +/// Wait until transaction is included into finalized block. +/// +/// Returns the hash of the finalized block with transaction. +pub(crate) async fn wait_until_transaction_is_finalized( + subscription: Subscription>, +) -> anyhow::Result> { + loop { + let transaction_status = subscription.next().await?; + match transaction_status { + Some(TransactionStatusOf::::FinalityTimeout(_)) | + Some(TransactionStatusOf::::Usurped(_)) | + Some(TransactionStatusOf::::Dropped) | + Some(TransactionStatusOf::::Invalid) | + None => + return Err(anyhow::format_err!( + "We've been waiting for finalization of {} transaction, but it now has the {:?} status", + C::NAME, + transaction_status, + )), + Some(TransactionStatusOf::::Finalized(block_hash)) => { + log::trace!( + target: "bridge", + "{} transaction has been finalized at block {}", + C::NAME, + block_hash, + ); + return Ok(block_hash) + }, + _ => { + log::trace!( + target: "bridge", + "Received intermediate status of {} transaction: {:?}", + C::NAME, + transaction_status, + ); + }, + } + } +} + /// Wait until parachain state is changed. async fn wait_para_state( relay_client: &Client, diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs index dc902055d20bd..79869ad03151b 100644 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -20,7 +20,7 @@ use crate::{ polkadot_headers_to_kusama::PolkadotFinalityToKusama, }, cli::{ - swap_tokens::wait_until_transaction_is_finalized, SourceConnectionParams, + register_parachain::wait_until_transaction_is_finalized, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, }, }; diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index ddb1ff59b5d08..53187009d3e21 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -16,18 +16,14 @@ use crate::cli::{ bridge::FullBridge, - encode_call::{self, CliEncodeCall}, + encode_message::{self, CliEncodeMessage}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, ExplicitOrMaximal, HexBytes, HexLaneId, Origins, SourceConnectionParams, - SourceSigningParams, TargetConnectionParams, TargetSigningParams, + Balance, HexBytes, HexLaneId, SourceConnectionParams, SourceSigningParams, }; -use bp_message_dispatch::{CallOrigin, MessagePayload}; -use bp_runtime::Chain as _; use codec::Encode; -use frame_support::weights::Weight; use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; use sp_core::{Bytes, Pair}; -use sp_runtime::{traits::IdentifyAccount, AccountId32, MultiSignature, MultiSigner}; +use sp_runtime::AccountId32; use std::fmt::Debug; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -61,8 +57,6 @@ pub struct SendMessage { source: SourceConnectionParams, #[structopt(flatten)] source_sign: SourceSigningParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -72,104 +66,20 @@ pub struct SendMessage { /// your message won't be relayed. #[structopt(long)] conversion_rate_override: Option, - /// Where dispatch fee is paid? - #[structopt( - long, - possible_values = DispatchFeePayment::VARIANTS, - case_insensitive = true, - default_value = "at-source-chain", - )] - dispatch_fee_payment: DispatchFeePayment, - /// Dispatch weight of the message. If not passed, determined automatically. - #[structopt(long)] - dispatch_weight: Option>, /// Delivery and dispatch fee in source chain base currency units. If not passed, determined /// automatically. #[structopt(long)] fee: Option, /// Message type. #[structopt(subcommand)] - message: crate::cli::encode_call::Call, - /// The origin to use when dispatching the message on the target chain. Defaults to - /// `SourceAccount`. - #[structopt(long, possible_values = &Origins::variants(), default_value = "Source")] - origin: Origins, - - // Normally we don't need to connect to the target chain to send message. But for testing - // we may want to use **actual** `spec_version` of the target chain when composing a message. - // Then we'll need to read version from the target chain node. - #[structopt(flatten)] - target: TargetConnectionParams, + message: crate::cli::encode_message::Message, } impl SendMessage { - pub async fn encode_payload( - &mut self, - ) -> anyhow::Result>> { - crate::select_full_bridge!(self.bridge, { - let SendMessage { - source_sign, - target_sign, - ref mut message, - dispatch_fee_payment, - dispatch_weight, - origin, - bridge, - .. - } = self; - - let source_sign = source_sign.to_keypair::()?; - - encode_call::preprocess_call::(message, bridge.bridge_instance_index()); - let target_call = Target::encode_call(message)?; - let target_spec_version = self.target.selected_chain_spec_version::().await?; - - let payload = { - let target_call_weight = prepare_call_dispatch_weight( - dispatch_weight, - || { - Ok(ExplicitOrMaximal::Explicit( - Target::get_dispatch_info(&target_call)?.weight, - )) - }, - compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), - )?; - let source_sender_public: MultiSigner = source_sign.public().into(); - let source_account_id = source_sender_public.into_account(); - - message_payload( - target_spec_version, - target_call_weight, - match origin { - Origins::Source => CallOrigin::SourceAccount(source_account_id), - Origins::Target => { - let target_sign = target_sign.to_keypair::()?; - let digest = account_ownership_digest( - &target_call, - source_account_id.clone(), - target_spec_version, - ); - let target_origin_public = target_sign.public(); - let digest_signature = target_sign.sign(&digest); - CallOrigin::TargetAccount( - source_account_id, - target_origin_public.into(), - digest_signature.into(), - ) - }, - }, - &target_call, - *dispatch_fee_payment, - ) - }; - Ok(payload) - }) - } - /// Run the command. - pub async fn run(mut self) -> anyhow::Result<()> { + pub async fn run(self) -> anyhow::Result<()> { crate::select_full_bridge!(self.bridge, { - let payload = self.encode_payload().await?; + let payload = encode_message::encode_message::(&self.message)?; let source_client = self.source.to_client::().await?; let source_sign = self.source_sign.to_keypair::()?; @@ -189,14 +99,13 @@ impl SendMessage { .await? as _, ), }; - let dispatch_weight = payload.weight; let payload_len = payload.encode().len(); - let send_message_call = Source::encode_call(&encode_call::Call::BridgeSendMessage { - bridge_instance_index: self.bridge.bridge_instance_index(), - lane: self.lane, - payload: HexBytes::encode(&payload), - fee, - })?; + let send_message_call = Source::encode_send_message_call( + self.lane.0, + payload, + fee.cast().into(), + self.bridge.bridge_instance_index(), + )?; let source_genesis_hash = *source_client.genesis_hash(); let (spec_version, transaction_version) = @@ -228,11 +137,10 @@ impl SendMessage { log::info!( target: "bridge", - "Sending message to {}. Lane: {:?}. Size: {}. Dispatch weight: {}. Fee: {}", + "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", Target::NAME, lane, payload_len, - dispatch_weight, fee, ); log::info!( @@ -260,66 +168,15 @@ impl SendMessage { } } -fn prepare_call_dispatch_weight( - user_specified_dispatch_weight: &Option>, - weight_from_pre_dispatch_call: impl Fn() -> anyhow::Result>, - maximal_allowed_weight: Weight, -) -> anyhow::Result { - match user_specified_dispatch_weight - .clone() - .map(Ok) - .unwrap_or_else(weight_from_pre_dispatch_call)? - { - ExplicitOrMaximal::Explicit(weight) => Ok(weight), - ExplicitOrMaximal::Maximal => Ok(maximal_allowed_weight), - } -} - -pub(crate) fn message_payload( - spec_version: u32, - weight: Weight, - origin: CallOrigin, - call: &impl Encode, - dispatch_fee_payment: DispatchFeePayment, -) -> MessagePayload> -where - SAccountId: Encode + Debug, - TPublic: Encode + Debug, - TSignature: Encode + Debug, -{ - // Display nicely formatted call. - let payload = MessagePayload { - spec_version, - weight, - origin, - dispatch_fee_payment: dispatch_fee_payment.into(), - call: HexBytes::encode(call), - }; - - log::info!(target: "bridge", "Created Message Payload: {:#?}", payload); - log::info!(target: "bridge", "Encoded Message Payload: {:?}", HexBytes::encode(&payload)); - - // re-pack to return `Vec` - let MessagePayload { spec_version, weight, origin, dispatch_fee_payment, call } = payload; - MessagePayload { spec_version, weight, origin, dispatch_fee_payment, call: call.0 } -} - -pub(crate) fn compute_maximal_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { - bridge_runtime_common::messages::target::maximal_incoming_message_dispatch_weight( - maximal_extrinsic_weight, - ) -} - #[cfg(test)] mod tests { use super::*; - use crate::cli::CliChain; - use hex_literal::hex; + use crate::cli::ExplicitOrMaximal; - #[async_std::test] - async fn send_remark_rialto_to_millau() { + #[test] + fn send_raw_rialto_to_millau() { // given - let mut send_message = SendMessage::from_iter(vec![ + let send_message = SendMessage::from_iter(vec![ "send-message", "rialto-to-millau", "--source-port", @@ -328,117 +185,48 @@ mod tests { "//Alice", "--conversion-rate-override", "0.75", - "remark", - "--remark-payload", - "1234", + "raw", + "dead", ]); - // when - let payload = send_message.encode_payload().await.unwrap(); - // then + assert_eq!(send_message.bridge, FullBridge::RialtoToMillau); + assert_eq!(send_message.source.source_port, 1234); + assert_eq!(send_message.source_sign.source_signer, Some("//Alice".into())); assert_eq!( - payload, - MessagePayload { - spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 0, - origin: CallOrigin::SourceAccount( - sp_keyring::AccountKeyring::Alice.to_account_id() - ), - dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, - call: hex!("0001081234").to_vec(), - } + send_message.conversion_rate_override, + Some(ConversionRateOverride::Explicit(0.75)) ); - } - - #[async_std::test] - async fn send_remark_millau_to_rialto() { - // given - let mut send_message = SendMessage::from_iter(vec![ - "send-message", - "millau-to-rialto", - "--source-port", - "1234", - "--source-signer", - "//Alice", - "--origin", - "Target", - "--target-signer", - "//Bob", - "--conversion-rate-override", - "metric", - "remark", - "--remark-payload", - "1234", - ]); - - // when - let payload = send_message.encode_payload().await.unwrap(); - - // then - // Since signatures are randomized we extract it from here and only check the rest. - let signature = match payload.origin { - CallOrigin::TargetAccount(_, _, ref sig) => sig.clone(), - _ => panic!("Unexpected `CallOrigin`: {:?}", payload), - }; assert_eq!( - payload, - MessagePayload { - spec_version: relay_millau_client::Millau::RUNTIME_VERSION.spec_version, - weight: 0, - origin: CallOrigin::TargetAccount( - sp_keyring::AccountKeyring::Alice.to_account_id(), - sp_keyring::AccountKeyring::Bob.into(), - signature, - ), - dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, - call: hex!("0001081234").to_vec(), - } + send_message.message, + crate::cli::encode_message::Message::Raw { data: HexBytes(vec![0xDE, 0xAD]) } ); } #[test] - fn accepts_send_message_command_without_target_sign_options() { - // given - let send_message = SendMessage::from_iter_safe(vec![ - "send-message", - "rialto-to-millau", - "--source-port", - "1234", - "--source-signer", - "//Alice", - "--origin", - "Target", - "remark", - "--remark-payload", - "1234", - ]); - - assert!(send_message.is_ok()); - } - - #[async_std::test] - async fn accepts_non_default_dispatch_fee_payment() { + fn send_sized_rialto_to_millau() { // given - let mut send_message = SendMessage::from_iter(vec![ + let send_message = SendMessage::from_iter(vec![ "send-message", "rialto-to-millau", "--source-port", "1234", "--source-signer", "//Alice", - "--dispatch-fee-payment", - "at-target-chain", - "remark", + "--conversion-rate-override", + "metric", + "sized", + "max", ]); - // when - let payload = send_message.encode_payload().await.unwrap(); - // then + assert_eq!(send_message.bridge, FullBridge::RialtoToMillau); + assert_eq!(send_message.source.source_port, 1234); + assert_eq!(send_message.source_sign.source_signer, Some("//Alice".into())); + assert_eq!(send_message.conversion_rate_override, Some(ConversionRateOverride::Metric)); assert_eq!( - payload.dispatch_fee_payment, - bp_runtime::messages::DispatchFeePayment::AtTargetChain + send_message.message, + crate::cli::encode_message::Message::Sized { size: ExplicitOrMaximal::Maximal } ); } } diff --git a/relays/bin-substrate/src/cli/swap_tokens.rs b/relays/bin-substrate/src/cli/swap_tokens.rs deleted file mode 100644 index 1467df3711c35..0000000000000 --- a/relays/bin-substrate/src/cli/swap_tokens.rs +++ /dev/null @@ -1,869 +0,0 @@ -// 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 . - -//! Tokens swap using token-swap bridge pallet. - -// TokenSwapBalances fields are never directly accessed, but the whole struct is printed -// to show token swap progress -#![allow(dead_code)] - -use codec::Encode; -use num_traits::One; -use rand::random; -use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; - -use frame_support::dispatch::GetDispatchInfo; -use relay_substrate_client::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithBalances, - Client, Error as SubstrateError, HashOf, SignParam, SignatureOf, Subscription, - TransactionSignScheme, TransactionStatusOf, UnsignedTransaction, -}; -use sp_core::{blake2_256, storage::StorageKey, Bytes, Pair, U256}; -use sp_runtime::traits::{Convert, Header as HeaderT}; - -use crate::cli::{ - estimate_fee::ConversionRateOverride, Balance, CliChain, SourceConnectionParams, - SourceSigningParams, TargetConnectionParams, TargetSigningParams, -}; - -/// Swap tokens. -#[derive(StructOpt, Debug, PartialEq)] -pub struct SwapTokens { - /// A bridge instance to use in token swap. - #[structopt(possible_values = SwapTokensBridge::VARIANTS, case_insensitive = true)] - bridge: SwapTokensBridge, - - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - - #[structopt(subcommand)] - swap_type: TokenSwapType, - /// Source chain balance that source signer wants to swap. - #[structopt(long)] - source_balance: Balance, - /// Target chain balance that target signer wants to swap. - #[structopt(long)] - target_balance: Balance, - /// A way to override conversion rate from target to source tokens. - /// - /// If not specified, conversion rate from runtime storage is used. It may be obsolete and - /// your message won't be relayed. - #[structopt(long)] - target_to_source_conversion_rate_override: Option, - /// A way to override conversion rate from source to target tokens. - /// - /// If not specified, conversion rate from runtime storage is used. It may be obsolete and - /// your message won't be relayed. - #[structopt(long)] - source_to_target_conversion_rate_override: Option, -} - -/// Token swap type. -#[derive(StructOpt, Debug, PartialEq, Eq, Clone)] -pub enum TokenSwapType { - /// The `target_sign` is temporary and only have funds for single swap. - NoLock, - /// This swap type prevents `source_signer` from restarting the swap after it has been - /// completed. - LockUntilBlock { - /// Number of blocks before the swap expires. - #[structopt(long)] - blocks_before_expire: u32, - /// Unique swap nonce. - #[structopt(long)] - swap_nonce: Option, - }, -} - -/// Swap tokens bridge. -#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] -#[strum(serialize_all = "kebab_case")] -pub enum SwapTokensBridge { - /// Use token-swap pallet deployed at Millau to swap tokens with Rialto. - MillauToRialto, -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - SwapTokensBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; - const SOURCE_SPEC_VERSION: u32 = millau_runtime::VERSION.spec_version; - const TARGET_SPEC_VERSION: u32 = rialto_runtime::VERSION.spec_version; - - type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter; - - use bp_millau::{ - derive_account_from_rialto_id as derive_source_account_from_target_account, - TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, - WITH_RIALTO_TOKEN_SWAP_PALLET_NAME as TOKEN_SWAP_PALLET_NAME, - }; - use bp_rialto::{ - derive_account_from_millau_id as derive_target_account_from_source_account, - TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, - }; - - const SOURCE_CHAIN_ID: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; - const TARGET_CHAIN_ID: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; - - const SOURCE_TO_TARGET_LANE_ID: bp_messages::LaneId = *b"swap"; - const TARGET_TO_SOURCE_LANE_ID: bp_messages::LaneId = [0, 0, 0, 0]; - - $generic - }, - } - }; -} - -impl SwapTokens { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let source_sign = self.source_sign.to_keypair::()?; - let target_client = self.target.to_client::().await?; - let target_sign = self.target_sign.to_keypair::()?; - let target_to_source_conversion_rate_override = - self.target_to_source_conversion_rate_override; - let source_to_target_conversion_rate_override = - self.source_to_target_conversion_rate_override; - - // names of variables in this function are matching names used by the - // `pallet-bridge-token-swap` - - // prepare token swap intention - let token_swap = self - .prepare_token_swap::(&source_client, &source_sign, &target_sign) - .await?; - - // group all accounts that will be used later - let accounts = TokenSwapAccounts { - source_account_at_bridged_chain: derive_target_account_from_source_account( - bp_runtime::SourceAccount::Account( - token_swap.source_account_at_this_chain.clone(), - ), - ), - target_account_at_this_chain: derive_source_account_from_target_account( - bp_runtime::SourceAccount::Account( - token_swap.target_account_at_bridged_chain.clone(), - ), - ), - source_account_at_this_chain: token_swap.source_account_at_this_chain.clone(), - target_account_at_bridged_chain: token_swap.target_account_at_bridged_chain.clone(), - swap_account: FromSwapToThisAccountIdConverter::convert( - token_swap.using_encoded(blake2_256).into(), - ), - }; - - // account balances are used to demonstrate what's happening :) - let initial_balances = - read_account_balances(&accounts, &source_client, &target_client).await?; - - // before calling something that may fail, log what we're trying to do - log::info!(target: "bridge", "Starting swap: {:?}", token_swap); - log::info!(target: "bridge", "Swap accounts: {:?}", accounts); - log::info!(target: "bridge", "Initial account balances: {:?}", initial_balances); - - // - // Step 1: swap is created - // - - // prepare `Currency::transfer` call that will happen at the target chain - let bridged_currency_transfer: CallOf = pallet_balances::Call::transfer { - dest: accounts.source_account_at_bridged_chain.clone().into(), - value: token_swap.target_balance_at_bridged_chain, - } - .into(); - let bridged_currency_transfer_weight = - bridged_currency_transfer.get_dispatch_info().weight; - - // sign message - let bridged_chain_spec_version = TARGET_SPEC_VERSION; - let signature_payload = pallet_bridge_dispatch::account_ownership_digest( - &bridged_currency_transfer, - &accounts.swap_account, - &bridged_chain_spec_version, - SOURCE_CHAIN_ID, - TARGET_CHAIN_ID, - ); - let bridged_currency_transfer_signature: SignatureOf = - target_sign.sign(&signature_payload).into(); - - // prepare `create_swap` call - let target_public_at_bridged_chain: AccountPublicOf = - target_sign.public().into(); - let swap_delivery_and_dispatch_fee = - crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee::< - Source, - Target, - _, - >( - &source_client, - target_to_source_conversion_rate_override, - ESTIMATE_SOURCE_TO_TARGET_MESSAGE_FEE_METHOD, - SOURCE_TO_TARGET_LANE_ID, - bp_message_dispatch::MessagePayload { - spec_version: TARGET_SPEC_VERSION, - weight: bridged_currency_transfer_weight, - origin: bp_message_dispatch::CallOrigin::TargetAccount( - accounts.swap_account.clone(), - target_public_at_bridged_chain.clone(), - bridged_currency_transfer_signature.clone(), - ), - dispatch_fee_payment: - bp_runtime::messages::DispatchFeePayment::AtTargetChain, - call: bridged_currency_transfer.encode(), - }, - ) - .await?; - let create_swap_call: CallOf = pallet_bridge_token_swap::Call::create_swap { - swap: token_swap.clone(), - swap_creation_params: Box::new(bp_token_swap::TokenSwapCreation { - target_public_at_bridged_chain, - swap_delivery_and_dispatch_fee, - bridged_chain_spec_version, - bridged_currency_transfer: bridged_currency_transfer.encode(), - bridged_currency_transfer_weight, - bridged_currency_transfer_signature, - }), - } - .into(); - - // start tokens swap - let source_genesis_hash = *source_client.genesis_hash(); - let create_swap_signer = source_sign.clone(); - let (spec_version, transaction_version) = - source_client.simple_runtime_version().await?; - let swap_created_at = wait_until_transaction_is_finalized::( - source_client - .submit_and_watch_signed_extrinsic( - accounts.source_account_at_this_chain.clone(), - move |_, transaction_nonce| { - Ok(Bytes( - Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: create_swap_signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - create_swap_call.into(), - transaction_nonce, - ), - })? - .encode(), - )) - }, - ) - .await?, - ) - .await?; - - // read state of swap after it has been created - let token_swap_hash = token_swap.hash(); - let token_swap_storage_key = bp_token_swap::storage_keys::pending_swaps_key( - TOKEN_SWAP_PALLET_NAME, - token_swap_hash, - ); - match read_token_swap_state(&source_client, swap_created_at, &token_swap_storage_key) - .await? - { - Some(bp_token_swap::TokenSwapState::Started) => { - log::info!(target: "bridge", "Swap has been successfully started"); - let intermediate_balances = - read_account_balances(&accounts, &source_client, &target_client).await?; - log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); - }, - Some(token_swap_state) => - return Err(anyhow::format_err!( - "Fresh token swap has unexpected state: {:?}", - token_swap_state, - )), - None => return Err(anyhow::format_err!("Failed to start token swap")), - }; - - // - // Step 2: message is being relayed to the target chain and dispathed there - // - - // wait until message is dispatched at the target chain and dispatch result delivered - // back to source chain - let token_swap_state = wait_until_token_swap_state_is_changed( - &source_client, - &token_swap_storage_key, - bp_token_swap::TokenSwapState::Started, - ) - .await?; - let is_transfer_succeeded = match token_swap_state { - Some(bp_token_swap::TokenSwapState::Started) => { - unreachable!("wait_until_token_swap_state_is_changed only returns if state is not Started; qed",) - }, - None => - return Err(anyhow::format_err!("Fresh token swap has disappeared unexpectedly")), - Some(bp_token_swap::TokenSwapState::Confirmed) => { - log::info!( - target: "bridge", - "Transfer has been successfully dispatched at the target chain. Swap can be claimed", - ); - true - }, - Some(bp_token_swap::TokenSwapState::Failed) => { - log::info!( - target: "bridge", - "Transfer has been dispatched with an error at the target chain. Swap can be canceled", - ); - false - }, - }; - - // by this time: (1) token swap account has been created and (2) if transfer has been - // successfully dispatched, both target chain balances have changed - let intermediate_balances = - read_account_balances(&accounts, &source_client, &target_client).await?; - log::info!(target: "bridge", "Intermediate balances: {:?}", intermediate_balances); - - // transfer has been dispatched, but we may need to wait until block where swap can be - // claimed/canceled - if let bp_token_swap::TokenSwapType::LockClaimUntilBlock( - ref last_available_block_number, - _, - ) = token_swap.swap_type - { - wait_until_swap_unlocked( - &source_client, - last_available_block_number + BlockNumberOf::::one(), - ) - .await?; - } - - // - // Step 3: we may now claim or cancel the swap - // - - if is_transfer_succeeded { - log::info!(target: "bridge", "Claiming the swap"); - - // prepare `claim_swap` message that will be sent over the bridge - let claim_swap_call: CallOf = - pallet_bridge_token_swap::Call::claim_swap { swap: token_swap }.into(); - let claim_swap_message = bp_message_dispatch::MessagePayload { - spec_version: SOURCE_SPEC_VERSION, - weight: claim_swap_call.get_dispatch_info().weight, - origin: bp_message_dispatch::CallOrigin::SourceAccount( - accounts.target_account_at_bridged_chain.clone(), - ), - dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, - call: claim_swap_call.encode(), - }; - let claim_swap_delivery_and_dispatch_fee = - crate::cli::estimate_fee::estimate_message_delivery_and_dispatch_fee::< - Target, - Source, - _, - >( - &target_client, - source_to_target_conversion_rate_override, - ESTIMATE_TARGET_TO_SOURCE_MESSAGE_FEE_METHOD, - TARGET_TO_SOURCE_LANE_ID, - claim_swap_message.clone(), - ) - .await?; - let send_message_call: CallOf = - pallet_bridge_messages::Call::send_message { - lane_id: TARGET_TO_SOURCE_LANE_ID, - payload: claim_swap_message, - delivery_and_dispatch_fee: claim_swap_delivery_and_dispatch_fee, - } - .into(); - - // send `claim_swap` message - let target_genesis_hash = *target_client.genesis_hash(); - let (spec_version, transaction_version) = - target_client.simple_runtime_version().await?; - let _ = wait_until_transaction_is_finalized::( - target_client - .submit_and_watch_signed_extrinsic( - accounts.target_account_at_bridged_chain.clone(), - move |_, transaction_nonce| { - Ok(Bytes( - Target::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: target_genesis_hash, - signer: target_sign, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - send_message_call.into(), - transaction_nonce, - ), - })? - .encode(), - )) - }, - ) - .await?, - ) - .await?; - - // wait until swap state is updated - let token_swap_state = wait_until_token_swap_state_is_changed( - &source_client, - &token_swap_storage_key, - bp_token_swap::TokenSwapState::Confirmed, - ) - .await?; - if token_swap_state != None { - return Err(anyhow::format_err!( - "Confirmed token swap state has been changed to {:?} unexpectedly", - token_swap_state - )) - } - } else { - log::info!(target: "bridge", "Cancelling the swap"); - let cancel_swap_call: CallOf = - pallet_bridge_token_swap::Call::cancel_swap { swap: token_swap.clone() }.into(); - let (spec_version, transaction_version) = - source_client.simple_runtime_version().await?; - let _ = wait_until_transaction_is_finalized::( - source_client - .submit_and_watch_signed_extrinsic( - accounts.source_account_at_this_chain.clone(), - move |_, transaction_nonce| { - Ok(Bytes( - Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - cancel_swap_call.into(), - transaction_nonce, - ), - })? - .encode(), - )) - }, - ) - .await?, - ) - .await?; - } - - // print final balances - let final_balances = - read_account_balances(&accounts, &source_client, &target_client).await?; - log::info!(target: "bridge", "Final account balances: {:?}", final_balances); - - Ok(()) - }) - } - - /// Prepare token swap intention. - async fn prepare_token_swap( - &self, - source_client: &Client, - source_sign: &Source::KeyPair, - target_sign: &Target::KeyPair, - ) -> anyhow::Result< - bp_token_swap::TokenSwap< - BlockNumberOf, - BalanceOf, - AccountIdOf, - BalanceOf, - AccountIdOf, - >, - > - where - AccountIdOf: From<::Public>, - AccountIdOf: From<::Public>, - BalanceOf: From, - BalanceOf: From, - { - // accounts that are directly controlled by participants - let source_account_at_this_chain: AccountIdOf = source_sign.public().into(); - let target_account_at_bridged_chain: AccountIdOf = target_sign.public().into(); - - // balances that we're going to swap - let source_balance_at_this_chain: BalanceOf = self.source_balance.cast().into(); - let target_balance_at_bridged_chain: BalanceOf = self.target_balance.cast().into(); - - // prepare token swap intention - Ok(bp_token_swap::TokenSwap { - swap_type: self.prepare_token_swap_type(source_client).await?, - source_balance_at_this_chain, - source_account_at_this_chain: source_account_at_this_chain.clone(), - target_balance_at_bridged_chain, - target_account_at_bridged_chain: target_account_at_bridged_chain.clone(), - }) - } - - /// Prepare token swap type. - async fn prepare_token_swap_type( - &self, - source_client: &Client, - ) -> anyhow::Result>> { - match self.swap_type { - TokenSwapType::NoLock => - Ok(bp_token_swap::TokenSwapType::TemporaryTargetAccountAtBridgedChain), - TokenSwapType::LockUntilBlock { blocks_before_expire, ref swap_nonce } => { - let blocks_before_expire: BlockNumberOf = blocks_before_expire.into(); - let current_source_block_number = *source_client.best_header().await?.number(); - Ok(bp_token_swap::TokenSwapType::LockClaimUntilBlock( - current_source_block_number + blocks_before_expire, - swap_nonce.unwrap_or_else(|| { - U256::from(random::()).overflowing_mul(U256::from(random::())).0 - }), - )) - }, - } - } -} - -/// Accounts that are participating in the swap. -#[derive(Debug)] -struct TokenSwapAccounts { - source_account_at_this_chain: ThisAccountId, - source_account_at_bridged_chain: BridgedAccountId, - target_account_at_bridged_chain: BridgedAccountId, - target_account_at_this_chain: ThisAccountId, - swap_account: ThisAccountId, -} - -/// Swap accounts balances. -#[derive(Debug)] -struct TokenSwapBalances { - source_account_at_this_chain_balance: Option, - source_account_at_bridged_chain_balance: Option, - target_account_at_bridged_chain_balance: Option, - target_account_at_this_chain_balance: Option, - swap_account_balance: Option, -} - -/// Read swap accounts balances. -async fn read_account_balances( - accounts: &TokenSwapAccounts, AccountIdOf>, - source_client: &Client, - target_client: &Client, -) -> anyhow::Result, BalanceOf>> { - Ok(TokenSwapBalances { - source_account_at_this_chain_balance: read_account_balance( - source_client, - &accounts.source_account_at_this_chain, - ) - .await?, - source_account_at_bridged_chain_balance: read_account_balance( - target_client, - &accounts.source_account_at_bridged_chain, - ) - .await?, - target_account_at_bridged_chain_balance: read_account_balance( - target_client, - &accounts.target_account_at_bridged_chain, - ) - .await?, - target_account_at_this_chain_balance: read_account_balance( - source_client, - &accounts.target_account_at_this_chain, - ) - .await?, - swap_account_balance: read_account_balance(source_client, &accounts.swap_account).await?, - }) -} - -/// Read account balance. -async fn read_account_balance( - client: &Client, - account: &AccountIdOf, -) -> anyhow::Result>> { - match client.free_native_balance(account.clone()).await { - Ok(balance) => Ok(Some(balance)), - Err(SubstrateError::AccountDoesNotExist) => Ok(None), - Err(error) => Err(anyhow::format_err!( - "Failed to read balance of {} account {:?}: {:?}", - C::NAME, - account, - error, - )), - } -} - -/// Wait until transaction is included into finalized block. -/// -/// Returns the hash of the finalized block with transaction. -pub(crate) async fn wait_until_transaction_is_finalized( - subscription: Subscription>, -) -> anyhow::Result> { - loop { - let transaction_status = subscription.next().await?; - match transaction_status { - Some(TransactionStatusOf::::FinalityTimeout(_)) | - Some(TransactionStatusOf::::Usurped(_)) | - Some(TransactionStatusOf::::Dropped) | - Some(TransactionStatusOf::::Invalid) | - None => - return Err(anyhow::format_err!( - "We've been waiting for finalization of {} transaction, but it now has the {:?} status", - C::NAME, - transaction_status, - )), - Some(TransactionStatusOf::::Finalized(block_hash)) => { - log::trace!( - target: "bridge", - "{} transaction has been finalized at block {}", - C::NAME, - block_hash, - ); - return Ok(block_hash) - }, - _ => { - log::trace!( - target: "bridge", - "Received intermediate status of {} transaction: {:?}", - C::NAME, - transaction_status, - ); - }, - } - } -} - -/// Waits until token swap state is changed from `Started` to something else. -async fn wait_until_token_swap_state_is_changed( - client: &Client, - swap_state_storage_key: &StorageKey, - previous_token_swap_state: bp_token_swap::TokenSwapState, -) -> anyhow::Result> { - log::trace!(target: "bridge", "Waiting for token swap state change"); - loop { - async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; - - let best_block = client.best_finalized_header_number().await?; - let best_block_hash = client.block_hash_by_number(best_block).await?; - log::trace!(target: "bridge", "Inspecting {} block {}/{}", C::NAME, best_block, best_block_hash); - - let token_swap_state = - read_token_swap_state(client, best_block_hash, swap_state_storage_key).await?; - match token_swap_state { - Some(new_token_swap_state) if new_token_swap_state == previous_token_swap_state => {}, - _ => { - log::trace!( - target: "bridge", - "Token swap state has been changed from {:?} to {:?}", - previous_token_swap_state, - token_swap_state, - ); - return Ok(token_swap_state) - }, - } - } -} - -/// Waits until swap can be claimed or canceled. -async fn wait_until_swap_unlocked( - client: &Client, - required_block_number: BlockNumberOf, -) -> anyhow::Result<()> { - log::trace!(target: "bridge", "Waiting for token swap unlock"); - loop { - async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; - - let best_block = client.best_finalized_header_number().await?; - let best_block_hash = client.block_hash_by_number(best_block).await?; - if best_block >= required_block_number { - return Ok(()) - } - - log::trace!(target: "bridge", "Skipping {} block {}/{}", C::NAME, best_block, best_block_hash); - } -} - -/// Read state of the active token swap. -async fn read_token_swap_state( - client: &Client, - at_block: C::Hash, - swap_state_storage_key: &StorageKey, -) -> anyhow::Result> { - Ok(client.storage_value(swap_state_storage_key.clone(), Some(at_block)).await?) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; - - #[test] - fn swap_tokens_millau_to_rialto_no_lock() { - let swap_tokens = SwapTokens::from_iter(vec![ - "swap-tokens", - "millau-to-rialto", - "--source-host", - "127.0.0.1", - "--source-port", - "9000", - "--source-signer", - "//Alice", - "--source-balance", - "8000000000", - "--target-host", - "127.0.0.1", - "--target-port", - "9001", - "--target-signer", - "//Bob", - "--target-balance", - "9000000000", - "no-lock", - ]); - - assert_eq!( - swap_tokens, - SwapTokens { - bridge: SwapTokensBridge::MillauToRialto, - source: SourceConnectionParams { - source_host: "127.0.0.1".into(), - source_port: 9000, - source_secure: false, - source_runtime_version: SourceRuntimeVersionParams { - source_version_mode: RuntimeVersionType::Bundle, - source_spec_version: None, - source_transaction_version: None, - } - }, - source_sign: SourceSigningParams { - source_signer: Some("//Alice".into()), - source_signer_password: None, - source_signer_file: None, - source_signer_password_file: None, - source_transactions_mortality: None, - }, - target: TargetConnectionParams { - target_host: "127.0.0.1".into(), - target_port: 9001, - target_secure: false, - target_runtime_version: TargetRuntimeVersionParams { - target_version_mode: RuntimeVersionType::Bundle, - target_spec_version: None, - target_transaction_version: None, - } - }, - target_sign: TargetSigningParams { - target_signer: Some("//Bob".into()), - target_signer_password: None, - target_signer_file: None, - target_signer_password_file: None, - target_transactions_mortality: None, - }, - swap_type: TokenSwapType::NoLock, - source_balance: Balance(8000000000), - target_balance: Balance(9000000000), - target_to_source_conversion_rate_override: None, - source_to_target_conversion_rate_override: None, - } - ); - } - - #[test] - fn swap_tokens_millau_to_rialto_lock_until() { - let swap_tokens = SwapTokens::from_iter(vec![ - "swap-tokens", - "millau-to-rialto", - "--source-host", - "127.0.0.1", - "--source-port", - "9000", - "--source-signer", - "//Alice", - "--source-balance", - "8000000000", - "--target-host", - "127.0.0.1", - "--target-port", - "9001", - "--target-signer", - "//Bob", - "--target-balance", - "9000000000", - "--target-to-source-conversion-rate-override", - "metric", - "--source-to-target-conversion-rate-override", - "84.56", - "lock-until-block", - "--blocks-before-expire", - "1", - ]); - - assert_eq!( - swap_tokens, - SwapTokens { - bridge: SwapTokensBridge::MillauToRialto, - source: SourceConnectionParams { - source_host: "127.0.0.1".into(), - source_port: 9000, - source_secure: false, - source_runtime_version: SourceRuntimeVersionParams { - source_version_mode: RuntimeVersionType::Bundle, - source_spec_version: None, - source_transaction_version: None, - } - }, - source_sign: SourceSigningParams { - source_signer: Some("//Alice".into()), - source_signer_password: None, - source_signer_file: None, - source_signer_password_file: None, - source_transactions_mortality: None, - }, - target: TargetConnectionParams { - target_host: "127.0.0.1".into(), - target_port: 9001, - target_secure: false, - target_runtime_version: TargetRuntimeVersionParams { - target_version_mode: RuntimeVersionType::Bundle, - target_spec_version: None, - target_transaction_version: None, - } - }, - target_sign: TargetSigningParams { - target_signer: Some("//Bob".into()), - target_signer_password: None, - target_signer_file: None, - target_signer_password_file: None, - target_transactions_mortality: None, - }, - swap_type: TokenSwapType::LockUntilBlock { - blocks_before_expire: 1, - swap_nonce: None, - }, - source_balance: Balance(8000000000), - target_balance: Balance(9000000000), - target_to_source_conversion_rate_override: Some(ConversionRateOverride::Metric), - source_to_target_conversion_rate_override: Some(ConversionRateOverride::Explicit( - 84.56 - )), - } - ); - } -} diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 8ab3a27fd7c99..f6aee9dae2200 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -15,13 +15,11 @@ scale-info = { version = "2.1.1", features = ["derive"] } bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-messages = { path = "../../primitives/messages" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } # Substrate Dependencies diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs index 59a919e6cb971..370486d1b8347 100644 --- a/relays/client-kusama/src/runtime.rs +++ b/relays/client-kusama/src/runtime.rs @@ -27,30 +27,6 @@ use sp_runtime::FixedU128; /// Unchecked Kusama extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; -/// Polkadot account ownership digest from Kusama. -/// -/// The byte vector returned by this function should be signed with a Polkadot account private key. -/// This way, the owner of `kusama_account_id` on Kusama proves that the Polkadot account private -/// key is also under his control. -pub fn kusama_to_polkadot_account_ownership_digest( - polkadot_call: &Call, - kusama_account_id: AccountId, - polkadot_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - polkadot_call, - kusama_account_id, - polkadot_spec_version, - bp_runtime::KUSAMA_CHAIN_ID, - bp_runtime::POLKADOT_CHAIN_ID, - ) -} - /// Kusama Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Kusama chain. @@ -115,16 +91,7 @@ pub enum BridgePolkadotMessagesCall { #[codec(index = 2)] update_pallet_parameter(BridgePolkadotMessagesParameter), #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_kusama::AccountId, - bp_polkadot::AccountId, - bp_polkadot::AccountPublic, - Vec, - >, - bp_kusama::Balance, - ), + send_message(LaneId, Vec, bp_kusama::Balance), #[codec(index = 5)] receive_messages_proof( bp_polkadot::AccountId, diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 1d61f0b4cdcee..d52ddd9adf4c8 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -15,13 +15,11 @@ scale-info = { version = "2.1.1", features = ["derive"] } bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-messages = { path = "../../primitives/messages" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } # Substrate Dependencies diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs index fa45115a6b5c2..15421d94c699b 100644 --- a/relays/client-polkadot/src/runtime.rs +++ b/relays/client-polkadot/src/runtime.rs @@ -27,30 +27,6 @@ use sp_runtime::FixedU128; /// Unchecked Polkadot extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; -/// Kusama account ownership digest from Polkadot. -/// -/// The byte vector returned by this function should be signed with a Kusama account private key. -/// This way, the owner of `kusam_account_id` on Polkadot proves that the Kusama account private key -/// is also under his control. -pub fn polkadot_to_kusama_account_ownership_digest( - kusama_call: &Call, - kusam_account_id: AccountId, - kusama_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - kusama_call, - kusam_account_id, - kusama_spec_version, - bp_runtime::POLKADOT_CHAIN_ID, - bp_runtime::KUSAMA_CHAIN_ID, - ) -} - /// Polkadot Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Polkadot chain. @@ -115,16 +91,7 @@ pub enum BridgeKusamaMessagesCall { #[codec(index = 2)] update_pallet_parameter(BridgeKusamaMessagesParameter), #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_polkadot::AccountId, - bp_kusama::AccountId, - bp_kusama::AccountPublic, - Vec, - >, - bp_polkadot::Balance, - ), + send_message(LaneId, Vec, bp_polkadot::Balance), #[codec(index = 5)] receive_messages_proof( bp_kusama::AccountId, diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index a2d84c496077b..e806ad594c21a 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -15,13 +15,11 @@ scale-info = { version = "2.1.1", features = ["derive"] } bridge-runtime-common = { path = "../../bin/runtime-common" } bp-header-chain = { path = "../../primitives/header-chain" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-messages = { path = "../../primitives/messages" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs index b13808059964a..249e75a709ff5 100644 --- a/relays/client-rococo/src/runtime.rs +++ b/relays/client-rococo/src/runtime.rs @@ -26,30 +26,6 @@ use scale_info::TypeInfo; /// Unchecked Rococo extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; -/// Wococo account ownership digest from Rococo. -/// -/// The byte vector returned by this function should be signed with a Wococo account private key. -/// This way, the owner of `rococo_account_id` on Rococo proves that the Wococo account private key -/// is also under his control. -pub fn rococo_to_wococo_account_ownership_digest( - wococo_call: &Call, - rococo_account_id: AccountId, - wococo_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - wococo_call, - rococo_account_id, - wococo_spec_version, - bp_runtime::ROCOCO_CHAIN_ID, - bp_runtime::WOCOCO_CHAIN_ID, - ) -} - /// Rococo Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Rococo chain. @@ -107,16 +83,7 @@ pub enum BridgeGrandpaWococoCall { #[allow(non_camel_case_types)] pub enum BridgeWococoMessagesCall { #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_rococo::AccountId, - bp_wococo::AccountId, - bp_wococo::AccountPublic, - Vec, - >, - bp_rococo::Balance, - ), + send_message(LaneId, Vec, bp_rococo::Balance), #[codec(index = 5)] receive_messages_proof( bp_wococo::AccountId, diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index d9d892a9206d4..b322849d94adc 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -14,13 +14,11 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" # Bridge dependencies bridge-runtime-common = { path = "../../bin/runtime-common" } bp-header-chain = { path = "../../primitives/header-chain" } -bp-message-dispatch = { path = "../../primitives/message-dispatch" } bp-messages = { path = "../../primitives/messages" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } -pallet-bridge-dispatch = { path = "../../modules/dispatch" } pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs index b28e053086b16..f7b9c03bf9cd8 100644 --- a/relays/client-wococo/src/runtime.rs +++ b/relays/client-wococo/src/runtime.rs @@ -26,30 +26,6 @@ use scale_info::TypeInfo; /// Unchecked Wococo extrinsic. pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; -/// Rococo account ownership digest from Wococo. -/// -/// The byte vector returned by this function should be signed with a Rococo account private key. -/// This way, the owner of `wococo_account_id` on Rococo proves that the Rococo account private key -/// is also under his control. -pub fn wococo_to_rococo_account_ownership_digest( - rococo_call: &Call, - wococo_account_id: AccountId, - rococo_spec_version: SpecVersion, -) -> Vec -where - Call: codec::Encode, - AccountId: codec::Encode, - SpecVersion: codec::Encode, -{ - pallet_bridge_dispatch::account_ownership_digest( - rococo_call, - wococo_account_id, - rococo_spec_version, - bp_runtime::WOCOCO_CHAIN_ID, - bp_runtime::ROCOCO_CHAIN_ID, - ) -} - /// Wococo Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to Rococo chain. @@ -107,16 +83,7 @@ pub enum BridgeGrandpaRococoCall { #[allow(non_camel_case_types)] pub enum BridgeRococoMessagesCall { #[codec(index = 3)] - send_message( - LaneId, - bp_message_dispatch::MessagePayload< - bp_rococo::AccountId, - bp_wococo::AccountId, - bp_wococo::AccountPublic, - Vec, - >, - bp_rococo::Balance, - ), + send_message(LaneId, Vec, bp_rococo::Balance), #[codec(index = 5)] receive_messages_proof( bp_rococo::AccountId, From 6ebccfb9fd2e0c63ba773d6ed297c6e39fda8377 Mon Sep 17 00:00:00 2001 From: Sergei Shulepov Date: Wed, 4 May 2022 15:43:46 +0100 Subject: [PATCH 0682/1210] Update spec_version for Rococo (#1387) --- primitives/chain-rococo/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 127e75d5f8b2f..007301a7cec6c 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -43,7 +43,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: sp_version::create_runtime_str!("rococo"), impl_name: sp_version::create_runtime_str!("parity-rococo-v2.0"), authoring_version: 0, - spec_version: 9180, + spec_version: 9200, impl_version: 0, apis: sp_version::create_apis_vec![[]], transaction_version: 0, From 00af25d9468510167588ef0b02239b19f218a73a Mon Sep 17 00:00:00 2001 From: Sergei Shulepov Date: Thu, 5 May 2022 13:52:29 +0100 Subject: [PATCH 0683/1210] Generalize error text (#1388) * Generalize error text Right now, each time there is an error while executing `substrate-relay` it will be reported as: ERROR bridge Failed to start relay: This is the case even if the invoked command did not have anything to do with starting a relayer. Thus this removes this text. Now something like this would be written: ERROR bridge * Use substrate-relay prefix --- relays/bin-substrate/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 13db6beefa6a0..bc84786ee27f2 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -26,6 +26,6 @@ fn main() { let run = command.run(); let result = async_std::task::block_on(run); if let Err(error) = result { - log::error!(target: "bridge", "Failed to start relay: {}", error); + log::error!(target: "bridge", "substrate-relay: {}", error); } } From 6514cf131539495546127868096b79d37d4ad181 Mon Sep 17 00:00:00 2001 From: echo Date: Fri, 6 May 2022 16:54:21 +0800 Subject: [PATCH 0684/1210] Small opt when prune messages (#1389) * Small opt when prune messages * Fix typing error --- modules/messages/src/outbound_lane.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index e4566b8895fa4..041dec214b11c 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -148,19 +148,17 @@ impl OutboundLane { /// Returns number of pruned messages. pub fn prune_messages(&mut self, max_messages_to_prune: MessageNonce) -> MessageNonce { let mut pruned_messages = 0; - let mut anything_changed = false; let mut data = self.storage.data(); while pruned_messages < max_messages_to_prune && data.oldest_unpruned_nonce <= data.latest_received_nonce { self.storage.remove_message(&data.oldest_unpruned_nonce); - anything_changed = true; pruned_messages += 1; data.oldest_unpruned_nonce += 1; } - if anything_changed { + if pruned_messages > 0 { self.storage.set_data(data); } From bb7a60e3c30f85c9178657915cdf47c8a08f940e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 May 2022 13:20:38 +0300 Subject: [PATCH 0685/1210] Parachains finality pallet (#1068) * parachains finality * parachains pallet test * demo of how to configure GRANDPA pallet instance * allow instances in parachains pallet * spellcheck * TODO + fix * fmt * removed invalid storage_keys file * change all hashers to Blake2_128Concat * use Twox64Concat for insertion position * fix build * fix compilation * change ParaId and ParaHead types * TODOs -> TODOs with issues refs --- modules/grandpa/src/lib.rs | 2 +- modules/parachains/Cargo.toml | 50 ++ modules/parachains/src/lib.rs | 601 +++++++++++++++++++++ modules/parachains/src/mock.rs | 174 ++++++ primitives/polkadot-core/Cargo.toml | 4 + primitives/polkadot-core/src/lib.rs | 2 + primitives/polkadot-core/src/parachains.rs | 82 +++ 7 files changed, 914 insertions(+), 1 deletion(-) create mode 100644 modules/parachains/Cargo.toml create mode 100644 modules/parachains/src/lib.rs create mode 100644 modules/parachains/src/mock.rs create mode 100644 primitives/polkadot-core/src/parachains.rs diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 8ff8b34fb88cf..105dfb15ac703 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -284,7 +284,7 @@ pub mod pallet { /// Headers which have been imported into the pallet. #[pallet::storage] - pub(super) type ImportedHeaders, I: 'static = ()> = + pub type ImportedHeaders, I: 'static = ()> = StorageMap<_, Identity, BridgedBlockHash, BridgedHeader>; /// The current GRANDPA Authority set. diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml new file mode 100644 index 0000000000000..6ed9552e56b66 --- /dev/null +++ b/modules/parachains/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "pallet-bridge-parachains" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true } + +# Bridge Dependencies + +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +pallet-bridge-grandpa = { path = "../grandpa", default-features = false } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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-runtime = { 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] +bp-header-chain = { path = "../../primitives/header-chain" } +bp-test-utils = { path = "../../primitives/test-utils" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[features] +default = ["std"] +std = [ + "bp-polkadot-core/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "pallet-bridge-grandpa/std", + "scale-info/std", + "serde", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "sp-trie/std", +] diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs new file mode 100644 index 0000000000000..3f5d214f61d51 --- /dev/null +++ b/modules/parachains/src/lib.rs @@ -0,0 +1,601 @@ +// Copyright 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 . + +//! Parachains finality module. +//! +//! This module needs to be deployed with GRANDPA module, which is syncing relay +//! chain blocks. The main entry point of this module is `submit_parachain_heads`, which +//! accepts storage proof of some parachain `Heads` entries from bridged relay chain. +//! It requires corresponding relay headers to be already synced. + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaId, ParachainHeadsProof}; +use codec::{Decode, Encode}; +use frame_support::RuntimeDebug; +use scale_info::TypeInfo; +use sp_runtime::traits::Header as HeaderT; +use sp_std::vec::Vec; + +// Re-export in crate namespace for `construct_runtime!`. +pub use pallet::*; + +#[cfg(test)] +mod mock; + +/// Block hash of the bridged relay chain. +pub type RelayBlockHash = bp_polkadot_core::Hash; +/// Block number of the bridged relay chain. +pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; +/// Hasher of the bridged relay chain. +pub type RelayBlockHasher = bp_polkadot_core::Hasher; + +/// Best known parachain head as it is stored in the runtime storage. +#[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +pub struct BestParaHead { + /// Number of relay block where this head has been updated. + pub at_relay_block_number: RelayBlockNumber, + /// Hash of parachain head. + pub head_hash: ParaHash, + /// Current ring buffer position for this parachain. + pub next_imported_hash_position: u32, +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::error] + pub enum Error { + /// Relay chain block is unknown to us. + UnknownRelayChainBlock, + /// Invalid storage proof has been passed. + InvalidStorageProof, + } + + #[pallet::config] + #[pallet::disable_frame_system_supertrait_check] + pub trait Config: + pallet_bridge_grandpa::Config + { + /// Instance of bridges GRANDPA pallet that this pallet is linked to. + /// + /// The GRANDPA pallet instance must be configured to import headers of relay chain that + /// we're interested in. + type BridgesGrandpaPalletInstance: 'static; + + /// Maximal number of single parachain heads to keep in the storage. + /// + /// The setting is there to prevent growing the on-chain state indefinitely. Note + /// the setting does not relate to parachain block numbers - we will simply keep as much + /// items in the storage, so it doesn't guarantee any fixed timeframe for heads. + #[pallet::constant] + type HeadsToKeep: Get; + } + + /// Best parachain heads. + #[pallet::storage] + pub type BestParaHeads, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, ParaId, BestParaHead>; + + /// Parachain heads which have been imported into the pallet. + #[pallet::storage] + pub type ImportedParaHeads, I: 'static = ()> = + StorageDoubleMap<_, Blake2_128Concat, ParaId, Blake2_128Concat, ParaHash, ParaHead>; + + /// A ring buffer of imported parachain head hashes. Ordered by the insertion time. + #[pallet::storage] + pub(super) type ImportedParaHashes, I: 'static = ()> = + StorageDoubleMap<_, Blake2_128Concat, ParaId, Twox64Concat, u32, ParaHash>; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::call] + impl, I: 'static> Pallet + where + >::BridgedChain: + bp_runtime::Chain< + BlockNumber = RelayBlockNumber, + Hash = RelayBlockHash, + Hasher = RelayBlockHasher, + >, + { + /// Submit proof of one or several parachain heads. + /// + /// The proof is supposed to be proof of some `Heads` entries from the + /// `polkadot-runtime-parachains::paras` pallet instance, deployed at the bridged chain. + /// The proof is supposed to be crafted at the `relay_header_hash` that must already be + /// imported by corresponding GRANDPA pallet at this chain. + #[pallet::weight(0)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1391 + pub fn submit_parachain_heads( + _origin: OriginFor, + relay_block_hash: RelayBlockHash, + parachains: Vec, + parachain_heads_proof: ParachainHeadsProof, + ) -> DispatchResult { + // we'll need relay chain header to verify that parachains heads are always increasing. + let relay_block = pallet_bridge_grandpa::ImportedHeaders::< + T, + T::BridgesGrandpaPalletInstance, + >::get(relay_block_hash) + .ok_or(Error::::UnknownRelayChainBlock)?; + let relay_block_number = *relay_block.number(); + + // now parse storage proof and read parachain heads + pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( + relay_block_hash, + sp_trie::StorageProof::new(parachain_heads_proof), + move |storage| { + for parachain in parachains { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1393 + let parachain_head = match Pallet::::read_parachain_head(&storage, parachain) { + Some(parachain_head) => parachain_head, + None => { + log::trace!( + target: "runtime::bridge-parachains", + "The head of parachain {:?} has been declared, but is missing from the proof", + parachain, + ); + continue; + } + }; + + let _: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { + *stored_best_head = Some(Pallet::::update_parachain_head( + parachain, + stored_best_head.take(), + relay_block_number, + parachain_head, + )?); + Ok(()) + }); + } + }, + ) + .map_err(|_| Error::::InvalidStorageProof)?; + + // TODO: there may be parachains we are not interested in - so we only need to accept + // intersection of `parachains-interesting-to-us` and `parachains` + // https://github.com/paritytech/parity-bridges-common/issues/1392 + + // TODO: if some parachain is no more interesting to us, we should start pruning its + // heads + // https://github.com/paritytech/parity-bridges-common/issues/1392 + + Ok(()) + } + } + + impl, I: 'static> Pallet { + /// Read parachain head from storage proof. + fn read_parachain_head( + storage: &bp_runtime::StorageProofChecker, + parachain: ParaId, + ) -> Option { + let parachain_head_key = storage_keys::parachain_head_key(parachain); + let parachain_head = storage.read_value(parachain_head_key.0.as_ref()).ok()??; + let parachain_head = ParaHead::decode(&mut ¶chain_head[..]).ok()?; + Some(parachain_head) + } + + /// Try to update parachain head. + fn update_parachain_head( + parachain: ParaId, + stored_best_head: Option, + updated_at_relay_block_number: RelayBlockNumber, + updated_head: ParaHead, + ) -> Result { + // check if head has been already updated at better relay chain block. Without this + // check, we may import heads in random order + let updated_head_hash = updated_head.hash(); + let next_imported_hash_position = match stored_best_head { + Some(stored_best_head) + if stored_best_head.at_relay_block_number <= updated_at_relay_block_number => + { + // check if this head has already been imported before + if updated_head_hash == stored_best_head.head_hash { + log::trace!( + target: "runtime::bridge-parachains", + "The head of parachain {:?} can't be updated to {}, because it has been already updated\ + to the same value at previous relay chain block: {} < {}", + parachain, + updated_head_hash, + stored_best_head.at_relay_block_number, + updated_at_relay_block_number, + ); + return Err(()) + } + + stored_best_head.next_imported_hash_position + }, + None => 0, + Some(stored_best_head) => { + log::trace!( + target: "runtime::bridge-parachains", + "The head of parachain {:?} can't be updated to {}, because it has been already updated\ + to {} at better relay chain block: {} > {}", + parachain, + updated_head_hash, + stored_best_head.head_hash, + stored_best_head.at_relay_block_number, + updated_at_relay_block_number, + ); + return Err(()) + }, + }; + + // insert updated best parachain head + let head_hash_to_prune = + ImportedParaHashes::::try_get(parachain, next_imported_hash_position); + let updated_best_para_head = BestParaHead { + at_relay_block_number: updated_at_relay_block_number, + head_hash: updated_head_hash, + next_imported_hash_position: (next_imported_hash_position + 1) % + T::HeadsToKeep::get(), + }; + ImportedParaHashes::::insert( + parachain, + next_imported_hash_position, + updated_head_hash, + ); + ImportedParaHeads::::insert(parachain, updated_head_hash, updated_head); + + // remove old head + if let Ok(head_hash_to_prune) = head_hash_to_prune { + log::trace!( + target: "runtime::bridge-parachains", + "Pruning old head of parachain {:?}: {}", + parachain, + head_hash_to_prune, + ); + ImportedParaHeads::::remove(parachain, head_hash_to_prune); + } + + Ok(updated_best_para_head) + } + } +} + +pub mod storage_keys { + use super::*; + use bp_runtime::storage_map_final_key; + use frame_support::Twox64Concat; + use sp_core::storage::StorageKey; + + /// Storage key of the parachain head in the runtime storage of relay chain. + pub fn parachain_head_key(parachain: ParaId) -> StorageKey { + storage_map_final_key::("Paras", "Heads", ¶chain.encode()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{run_test, test_relay_header, Origin, TestRuntime}; + + use bp_test_utils::{authority_list, make_default_justification}; + use frame_support::{assert_noop, assert_ok, traits::OnInitialize}; + use sp_trie::{ + record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut, + }; + + type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; + + fn initialize(state_root: RelayBlockHash) { + pallet_bridge_grandpa::Pallet::::initialize( + Origin::root(), + bp_header_chain::InitializationData { + header: Box::new(test_relay_header(0, state_root)), + authority_list: authority_list(), + set_id: 1, + is_halted: false, + }, + ) + .unwrap(); + } + + fn proceed(num: RelayBlockNumber, state_root: RelayBlockHash) { + pallet_bridge_grandpa::Pallet::::on_initialize( + 0, + ); + + let header = test_relay_header(num, state_root); + let justification = make_default_justification(&header); + assert_ok!( + pallet_bridge_grandpa::Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification, + ) + ); + } + + fn prepare_parachain_heads_proof( + heads: Vec<(ParaId, ParaHead)>, + ) -> (RelayBlockHash, ParachainHeadsProof) { + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); + for (parachain, head) in heads { + let storage_key = storage_keys::parachain_head_key(parachain); + trie.insert(&storage_key.0, &head.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in tests"); + } + } + + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); + let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + (root, storage_proof) + } + + fn initial_best_head(parachain: u32) -> BestParaHead { + BestParaHead { + at_relay_block_number: 0, + head_hash: head_data(parachain, 0).hash(), + next_imported_hash_position: 1, + } + } + + fn head_data(parachain: u32, head_number: u32) -> ParaHead { + ParaHead((parachain, head_number).encode()) + } + + fn head_hash(parachain: u32, head_number: u32) -> ParaHash { + head_data(parachain, head_number).hash() + } + + fn import_parachain_1_head( + relay_chain_block: RelayBlockNumber, + relay_state_root: RelayBlockHash, + proof: ParachainHeadsProof, + ) -> sp_runtime::DispatchResult { + Pallet::::submit_parachain_heads( + Origin::signed(1), + test_relay_header(relay_chain_block, relay_state_root).hash(), + vec![ParaId(1)], + proof, + ) + } + + #[test] + fn imports_initial_parachain_heads() { + let (state_root, proof) = prepare_parachain_heads_proof(vec![ + (ParaId(1), head_data(1, 0)), + (ParaId(3), head_data(3, 10)), + ]); + run_test(|| { + initialize(state_root); + + // we're trying to update heads of parachains 1, 2 and 3 + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + test_relay_header(0, state_root).hash(), + vec![ParaId(1), ParaId(2), ParaId(3)], + proof, + ),); + + // but only 1 and 2 are updated, because proof is missing head of parachain#2 + assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); + assert_eq!(BestParaHeads::::get(ParaId(2)), None); + assert_eq!( + BestParaHeads::::get(ParaId(3)), + Some(BestParaHead { + at_relay_block_number: 0, + head_hash: head_data(3, 10).hash(), + next_imported_hash_position: 1, + }) + ); + + assert_eq!( + ImportedParaHeads::::get(ParaId(1), initial_best_head(1).head_hash), + Some(head_data(1, 0)) + ); + assert_eq!( + ImportedParaHeads::::get(ParaId(2), initial_best_head(2).head_hash), + None + ); + assert_eq!( + ImportedParaHeads::::get(ParaId(3), head_hash(3, 10)), + Some(head_data(3, 10)) + ); + }); + } + + #[test] + fn imports_parachain_heads_is_able_to_progress() { + let (state_root_5, proof_5) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + let (state_root_10, proof_10) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]); + run_test(|| { + // start with relay block #0 and import head#5 of parachain#1 + initialize(state_root_5); + assert_ok!(import_parachain_1_head(0, state_root_5, proof_5)); + assert_eq!( + BestParaHeads::::get(ParaId(1)), + Some(BestParaHead { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash(), + next_imported_hash_position: 1, + }) + ); + assert_eq!( + ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()), + Some(head_data(1, 5)) + ); + assert_eq!( + ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()), + None + ); + + // import head#10 of parachain#1 at relay block #1 + proceed(1, state_root_10); + assert_ok!(import_parachain_1_head(1, state_root_10, proof_10)); + assert_eq!( + BestParaHeads::::get(ParaId(1)), + Some(BestParaHead { + at_relay_block_number: 1, + head_hash: head_data(1, 10).hash(), + next_imported_hash_position: 2, + }) + ); + assert_eq!( + ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()), + Some(head_data(1, 5)) + ); + assert_eq!( + ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()), + Some(head_data(1, 10)) + ); + }); + } + + #[test] + fn does_nothing_when_already_imported_this_head_at_previous_relay_header() { + let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 0))]); + run_test(|| { + // import head#0 of parachain#1 at relay block#0 + initialize(state_root); + assert_ok!(import_parachain_1_head(0, state_root, proof.clone())); + assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); + + // try to import head#0 of parachain#1 at relay block#1 + // => call succeeds, but nothing is changed + proceed(1, state_root); + assert_ok!(import_parachain_1_head(1, state_root, proof)); + assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); + }); + } + + #[test] + fn does_nothing_when_already_imported_head_at_better_relay_header() { + let (state_root_5, proof_5) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + let (state_root_10, proof_10) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]); + run_test(|| { + // start with relay block #0 + initialize(state_root_5); + + // head#10 of parachain#1 at relay block#1 + proceed(1, state_root_10); + assert_ok!(import_parachain_1_head(1, state_root_10, proof_10)); + assert_eq!( + BestParaHeads::::get(ParaId(1)), + Some(BestParaHead { + at_relay_block_number: 1, + head_hash: head_data(1, 10).hash(), + next_imported_hash_position: 1, + }) + ); + + // now try to import head#1 at relay block#0 + // => nothing is changed, because better head has already been imported + assert_ok!(import_parachain_1_head(0, state_root_5, proof_5)); + assert_eq!( + BestParaHeads::::get(ParaId(1)), + Some(BestParaHead { + at_relay_block_number: 1, + head_hash: head_data(1, 10).hash(), + next_imported_hash_position: 1, + }) + ); + }); + } + + #[test] + fn prunes_old_heads() { + run_test(|| { + let heads_to_keep = crate::mock::HeadsToKeep::get(); + + // import exactly `HeadsToKeep` headers + for i in 0..heads_to_keep { + let (state_root, proof) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, i))]); + if i == 0 { + initialize(state_root); + } else { + proceed(i, state_root); + } + assert_ok!(import_parachain_1_head(i, state_root, proof)); + } + + // nothing is pruned yet + for i in 0..heads_to_keep { + assert!(ImportedParaHeads::::get(ParaId(1), head_data(1, i).hash()) + .is_some()); + } + + // import next relay chain header and next parachain head + let (state_root, proof) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, heads_to_keep))]); + proceed(heads_to_keep, state_root); + assert_ok!(import_parachain_1_head(heads_to_keep, state_root, proof)); + + // and the head#0 is pruned + assert!( + ImportedParaHeads::::get(ParaId(1), head_data(1, 0).hash()).is_none() + ); + for i in 1..=heads_to_keep { + assert!(ImportedParaHeads::::get(ParaId(1), head_data(1, i).hash()) + .is_some()); + } + }); + } + + #[test] + fn fails_on_unknown_relay_chain_block() { + let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + run_test(|| { + // start with relay block #0 + initialize(state_root); + + // try to import head#5 of parachain#1 at unknown relay chain block #1 + assert_noop!( + import_parachain_1_head(1, state_root, proof), + Error::::UnknownRelayChainBlock + ); + }); + } + + #[test] + fn fails_on_invalid_storage_proof() { + let (_state_root, proof) = + prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + run_test(|| { + // start with relay block #0 + initialize(Default::default()); + + // try to import head#5 of parachain#1 at relay chain block #0 + assert_noop!( + import_parachain_1_head(0, Default::default(), proof), + Error::::InvalidStorageProof + ); + }); + } +} diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs new file mode 100644 index 0000000000000..fcd157020bc1b --- /dev/null +++ b/modules/parachains/src/mock.rs @@ -0,0 +1,174 @@ +// 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 . + +use bp_runtime::Chain; +use frame_support::{construct_runtime, parameter_types, weights::Weight}; +use sp_runtime::{ + testing::{Header, H256}, + traits::{BlakeTwo256, Header as HeaderT, IdentityLookup}, + Perbill, +}; + +use crate as pallet_bridge_parachains; + +pub type AccountId = u64; +pub type TestNumber = u64; + +pub type RelayBlockHeader = + sp_runtime::generic::Header; + +type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + +construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Grandpa1: pallet_bridge_grandpa::::{Pallet}, + Grandpa2: pallet_bridge_grandpa::::{Pallet}, + Parachains: pallet_bridge_parachains::{Pallet}, + } +} + +parameter_types! { + pub const BlockHashCount: TestNumber = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Config for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = Call; + type BlockNumber = TestNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = frame_support::traits::Everything; + type SystemWeightInfo = (); + type DbWeight = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub const MaxRequests: u32 = 2; + pub const HeadersToKeep: u32 = 5; + pub const SessionLength: u64 = 5; + pub const NumValidators: u32 = 5; +} + +impl pallet_bridge_grandpa::Config for TestRuntime { + type BridgedChain = TestBridgedChain; + type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; + type WeightInfo = (); +} + +impl pallet_bridge_grandpa::Config for TestRuntime { + type BridgedChain = TestBridgedChain; + type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; + type WeightInfo = (); +} + +parameter_types! { + pub const HeadsToKeep: u32 = 4; +} + +impl pallet_bridge_parachains::Config for TestRuntime { + type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; + type HeadsToKeep = HeadsToKeep; +} + +#[derive(Debug)] +pub struct TestBridgedChain; + +impl Chain for TestBridgedChain { + type BlockNumber = crate::RelayBlockNumber; + type Hash = crate::RelayBlockHash; + type Hasher = crate::RelayBlockHasher; + type Header = RelayBlockHeader; + + type AccountId = AccountId; + type Balance = u32; + type Index = u32; + type Signature = sp_runtime::testing::TestSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + + fn max_extrinsic_weight() -> Weight { + unreachable!() + } +} + +#[derive(Debug)] +pub struct OtherBridgedChain; + +impl Chain for OtherBridgedChain { + type BlockNumber = u64; + type Hash = crate::RelayBlockHash; + type Hasher = crate::RelayBlockHasher; + type Header = sp_runtime::generic::Header; + + type AccountId = AccountId; + type Balance = u32; + type Index = u32; + type Signature = sp_runtime::testing::TestSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + + fn max_extrinsic_weight() -> Weight { + unreachable!() + } +} + +pub fn run_test(test: impl FnOnce() -> T) -> T { + sp_io::TestExternalities::new(Default::default()).execute_with(test) +} + +pub fn test_relay_header( + num: crate::RelayBlockNumber, + state_root: crate::RelayBlockHash, +) -> RelayBlockHeader { + RelayBlockHeader::new( + num, + Default::default(), + state_root, + Default::default(), + Default::default(), + ) +} diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index ce756d0897d47..6fa78cd349596 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -8,7 +8,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +parity-util-mem = { version = "0.11.0", optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies @@ -36,7 +38,9 @@ std = [ "frame-support/std", "frame-system/std", "parity-scale-codec/std", + "parity-util-mem", "scale-info/std", + "serde", "sp-api/std", "sp-core/std", "sp-runtime/std", diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 79db07b82cbb0..8db1af2fd3367 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -43,6 +43,8 @@ use sp_std::prelude::Vec; pub use frame_support::{weights::constants::ExtrinsicBaseWeight, Parameter}; pub use sp_runtime::{traits::Convert, Perbill}; +pub mod parachains; + /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Polkadot-like chain. This mostly depends on number of entries in the storage trie. /// Some reserve is reserved to account future chain growth. diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs new file mode 100644 index 0000000000000..c0448a846b346 --- /dev/null +++ b/primitives/polkadot-core/src/parachains.rs @@ -0,0 +1,82 @@ +// 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 . + +//! Primitives of polkadot-like chains, that are related to parachains functionality. +//! +//! Even though this (bridges) repository references polkadot repository, we can't +//! reference polkadot crates from pallets. That's because bridges repository is +//! included in the polkadot repository and included pallets are used by polkadot +//! chains. Having pallets that are referencing polkadot, would mean that there may +//! be two versions of polkadot crates included in the runtime. Which is bad. + +use frame_support::RuntimeDebug; +use parity_scale_codec::{CompactAs, Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_core::Hasher; +use sp_std::vec::Vec; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "std")] +use parity_util_mem::MallocSizeOf; + +/// Parachain id. +/// +/// This is an equivalent of the `polkadot_parachain::Id`, which is a compact-encoded `u32`. +#[derive( + Clone, + CompactAs, + Copy, + Decode, + Default, + Encode, + Eq, + Hash, + MaxEncodedLen, + Ord, + PartialEq, + PartialOrd, + RuntimeDebug, + TypeInfo, +)] +pub struct ParaId(pub u32); + +/// Parachain head. +/// +/// This is an equivalent of the `polkadot_parachain::HeadData`. +/// +/// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header. Keep in mind +/// that in Polkadot it is twice-encoded (so `header.encode().encode()`). We'll also do it to keep +/// it binary-compatible (implies hash-compatibility) with other parachain pallets. +#[derive( + PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo, Default, +)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf))] +pub struct ParaHead(pub Vec); + +impl ParaHead { + /// Returns the hash of this head data. + pub fn hash(&self) -> crate::Hash { + sp_runtime::traits::BlakeTwo256::hash(&self.0) + } +} + +/// Parachain head hash. +pub type ParaHash = crate::Hash; + +/// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. +pub type ParachainHeadsProof = Vec>; From 98e3274062944765c30e4a3d1df04172ea7dea46 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 16 May 2022 11:46:55 +0300 Subject: [PATCH 0686/1210] Xcm in Rialto<>Millau bridge (#1379) * add XCM pallet to Millau runtime * some progress * messages are delivered (no fee) * temp * flush * flush * some progress * progress * Trap(42) is dispatched successfully * fix spelling * no more manual sending * parametrize weight credit for tests * actually charge fees * enable send-using-messages-pallet to keep our test deployments alive + send valid XCM sometimes * fix benchmarks build * fix tests --- bin/millau/node/src/chain_spec.rs | 1 + bin/millau/runtime/Cargo.toml | 18 ++ bin/millau/runtime/src/lib.rs | 13 +- bin/millau/runtime/src/rialto_messages.rs | 44 ++- bin/millau/runtime/src/xcm_config.rs | 317 ++++++++++++++++++++ bin/rialto/node/src/chain_spec.rs | 1 + bin/rialto/runtime/Cargo.toml | 11 + bin/rialto/runtime/src/lib.rs | 13 +- bin/rialto/runtime/src/millau_messages.rs | 43 ++- bin/rialto/runtime/src/xcm_config.rs | 318 ++++++++++++++++++++ bin/runtime-common/Cargo.toml | 14 + bin/runtime-common/src/integrity.rs | 4 +- bin/runtime-common/src/messages.rs | 222 ++++++++++++-- bin/runtime-common/src/messages_api.rs | 43 ++- modules/messages/src/instant_payments.rs | 350 ---------------------- modules/messages/src/lib.rs | 45 ++- modules/messages/src/mock.rs | 6 +- primitives/messages/src/source_chain.rs | 23 ++ primitives/messages/src/target_chain.rs | 4 +- 19 files changed, 1059 insertions(+), 431 deletions(-) create mode 100644 bin/millau/runtime/src/xcm_config.rs create mode 100644 bin/rialto/runtime/src/xcm_config.rs delete mode 100644 modules/messages/src/instant_payments.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index a7e3c7c877183..ed7ee2440a898 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -217,6 +217,7 @@ fn testnet_genesis( owner: Some(get_account_id_from_seed::("RialtoMessagesOwner")), ..Default::default() }, + xcm_pallet: Default::default(), } } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 80d961388831a..598b100e1ab82 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } +log = { version = "0.4.14", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } @@ -53,6 +54,7 @@ sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { 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-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -62,8 +64,16 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +# Polkadot Dependencies + +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } + [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } +env_logger = "0.8" static_assertions = "1.1" [build-dependencies] @@ -85,6 +95,7 @@ std = [ "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", + "log/std", "pallet-aura/std", "pallet-balances/std", "pallet-beefy/std", @@ -100,6 +111,7 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "pallet-xcm/std", "scale-info/std", "serde", "sp-api/std", @@ -108,6 +120,7 @@ std = [ "sp-core/std", "sp-finality-grandpa/std", "sp-inherents/std", + "sp-io/std", "sp-offchain/std", "sp-runtime/std", "sp-session/std", @@ -115,6 +128,9 @@ std = [ "sp-transaction-pool/std", "sp-trie/std", "sp-version/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", @@ -123,5 +139,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4d44f34b624b3..178ec2e18e567 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -29,6 +29,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto_messages; +pub mod xcm_config; use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; @@ -451,13 +452,7 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_bridge_messages::instant_payments::InstantCurrencyPayments< - Runtime, - WithRialtoMessagesInstance, - pallet_balances::Pallet, - GetDeliveryConfirmationTransactionFee, - >; + type MessageDeliveryAndDispatchPayment = (); type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -499,6 +494,9 @@ construct_runtime!( // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, + + // Pallet for sending XCM. + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, } ); @@ -750,6 +748,7 @@ impl_runtime_apis! { Runtime, WithRialtoMessagesInstance, WithRialtoMessageBridge, + xcm_config::OutboundXcmWeigher, >(lane, begin, end) } } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 9b2c623757148..aac568e077f64 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::Runtime; +use crate::{Call, OriginCaller, Runtime}; use bp_messages::{ source_chain::{SenderOrigin, TargetHeaderChain}, @@ -40,6 +40,10 @@ pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); /// Initial value of `RialtoFeeMultiplier` parameter. pub const INITIAL_RIALTO_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge +/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual +/// tests, confirming that we don't break encoding somewhere between. +pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT; parameter_types! { /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. @@ -56,7 +60,7 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Messages proof for Rialto -> Millau messages. pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -68,9 +72,11 @@ pub type ToRialtoMessagesDeliveryProof = /// Call-dispatch based message dispatch for Rialto -> Millau messages. pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithRialtoMessageBridge, - crate::Runtime, - pallet_balances::Pallet, - (), + xcm_executor::XcmExecutor, + crate::xcm_config::XcmWeigher, + // 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + // (it is prepended with `UniversalOrigin` instruction) + frame_support::traits::ConstU64, >; /// Millau <-> Rialto message bridge. @@ -115,7 +121,23 @@ impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { - (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) && send_origin.linked_account().is_some() + let here_location = + xcm::v3::MultiLocation::from(crate::xcm_config::UniversalLocation::get()); + match send_origin.caller { + OriginCaller::XcmPallet(pallet_xcm::Origin::Xcm(ref location)) + if *location == here_location => + { + log::trace!(target: "runtime::bridge", "Verifying message sent using XCM pallet to Rialto"); + }, + _ => { + // keep in mind that in this case all messages are free (in term of fees) + // => it's just to keep testing bridge on our test deployments until we'll have a + // better option + log::trace!(target: "runtime::bridge", "Verifying message sent using messages pallet to Rialto"); + }, + } + + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -262,14 +284,8 @@ impl SourceHeaderChain for Rialto { impl SenderOrigin for crate::Origin { fn linked_account(&self) -> Option { - match self.caller { - crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => - Some(submitter.clone()), - crate::OriginCaller::system(frame_system::RawOrigin::Root) | - crate::OriginCaller::system(frame_system::RawOrigin::None) => - crate::RootAccountForPayments::get(), - _ => None, - } + // XCM deals wit fees in our deployments + None } } diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs new file mode 100644 index 0000000000000..a274b25924a5d --- /dev/null +++ b/bin/millau/runtime/src/xcm_config.rs @@ -0,0 +1,317 @@ +// 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 . + +//! XCM configurations for the Millau runtime. + +use super::{ + rialto_messages::WithRialtoMessageBridge, AccountId, AllPalletsWithSystem, Balances, + BridgeRialtoMessages, Call, Event, Origin, Runtime, XcmPallet, +}; +use bp_messages::source_chain::MessagesBridge; +use bp_millau::{Balance, WeightToFee}; +use bridge_runtime_common::messages::{ + source::{estimate_message_dispatch_and_delivery_fee, FromThisChainMessagePayload}, + MessageBridge, +}; +use codec::Encode; +use frame_support::{ + parameter_types, + traits::{Everything, Nothing}, + weights::Weight, +}; +use sp_std::marker::PhantomData; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, + CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, +}; + +parameter_types! { + /// The location of the `MLAU` token, from the context of this chain. Since this token is native to this + /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to + /// the context". + pub const TokenLocation: MultiLocation = Here.into_location(); + /// The Millau network ID, associated with Kusama. + pub const ThisNetwork: NetworkId = Kusama; + /// The Rialto network ID, associated with Polkadot. + pub const RialtoNetwork: NetworkId = Polkadot; + + /// Our XCM location ancestry - i.e. our location within the Consensus Universe. + /// + /// Since Kusama is a top-level relay-chain with its own consensus, it's just our network ID. + pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); + /// The check account, which holds any native assets that have been teleported out and not back in (yet). + pub CheckAccount: AccountId = XcmPallet::check_account(); +} + +/// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to +/// determine the sovereign account controlled by a location. +pub type SovereignAccountOf = ( + // We can directly alias an `AccountId32` into a local account. + AccountId32Aliases, +); + +/// Our asset transactor. This is what allows us to interest with the runtime facilities from the +/// point of view of XCM-only concepts like `MultiLocation` and `MultiAsset`. +/// +/// Ours is only aware of the Balances pallet, which is mapped to `TokenLocation`. +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // We can convert the MultiLocations with our converter above: + SovereignAccountOf, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We track our teleports in/out to keep total issuance correct. + CheckAccount, +>; + +/// The means that we convert the XCM message origin location into a local dispatch origin. +type LocalOriginConverter = ( + // A `Signed` origin of the sovereign account that the original location controls. + SovereignSignedViaLocation, + // The AccountId32 location type can be expressed natively as a `Signed` origin. + SignedAccountId32AsNative, +); + +/// The amount of weight an XCM operation takes. This is a safe overestimate. +pub const BASE_XCM_WEIGHT: Weight = 1_000_000_000; + +parameter_types! { + /// The amount of weight an XCM operation takes. This is a safe overestimate. + pub const BaseXcmWeight: Weight = BASE_XCM_WEIGHT; + /// Maximum number of instructions in a single XCM fragment. A sanity check against weight + /// calculations getting too crazy. + pub const MaxInstructions: u32 = 100; +} + +/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our +/// individual routers. +pub type XcmRouter = ( + // Router to send messages to Rialto. + ToRialtoBridge, +); + +parameter_types! { + pub const MaxAssetsIntoHolding: u32 = 64; +} + +/// The barriers one of which must be passed for an XCM message to be executed. +pub type Barrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, +); + +/// Outbound XCM weigher type. +pub type OutboundXcmWeigher = xcm_builder::FixedWeightBounds; +/// XCM weigher type. +pub type XcmWeigher = xcm_builder::FixedWeightBounds; + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type Call = Call; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = XcmWeigher; + // The weight trader piggybacks on the existing transaction-fee conversion logic. + type Trader = UsingComponents; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; +} + +/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior +/// location of this chain. +pub type LocalOriginToLocation = ( + // Usual Signed origin to be used in XCM as a corresponding AccountId32 + SignedToAccountId32, +); + +impl pallet_xcm::Config for Runtime { + type Event = Event; + // We don't allow any messages to be sent via the transaction yet. This is basically safe to + // enable, (safe the possibility of someone spamming the parachain if they're willing to pay + // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will + // make `DescendOrigin` a bit more useful. + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // Anyone can execute XCM messages locally. + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = xcm_executor::XcmExecutor; + // Anyone is able to use teleportation regardless of who they are and what they want to + // teleport. + type XcmTeleportFilter = Everything; + // Anyone is able to use reserve transfers regardless of who they are and what they want to + // transfer. + type XcmReserveTransferFilter = Everything; + type Weigher = XcmWeigher; + type UniversalLocation = UniversalLocation; + type Origin = Origin; + type Call = Call; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = SovereignAccountOf; + type MaxLockers = frame_support::traits::ConstU32<8>; +} + +/// With-rialto bridge. +pub struct ToRialtoBridge(PhantomData); + +impl> SendXcm + for ToRialtoBridge +{ + type Ticket = (Balance, FromThisChainMessagePayload); + + fn validate( + dest: &mut Option, + msg: &mut Option>, + ) -> SendResult { + let d = dest.take().ok_or(SendError::MissingArgument)?; + if !matches!(d, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == RialtoNetwork::get()) + { + *dest = Some(d); + return Err(SendError::NotApplicable) + }; + + let dest: InteriorMultiLocation = RialtoNetwork::get().into(); + let here = UniversalLocation::get(); + let route = dest.relative_to(&here); + let msg = (route, msg.take().unwrap()).encode(); + + let fee = estimate_message_dispatch_and_delivery_fee::( + &msg, + WithRialtoMessageBridge::RELAYER_FEE_PERCENT, + None, + ) + .map_err(SendError::Transport)?; + let fee_assets = MultiAssets::from((Here, fee)); + + Ok(((fee, msg), fee_assets)) + } + + fn deliver(ticket: Self::Ticket) -> Result { + let lane = [0, 0, 0, 0]; + let (fee, msg) = ticket; + let result = MB::send_message( + pallet_xcm::Origin::from(MultiLocation::from(UniversalLocation::get())).into(), + lane, + msg, + fee, + ); + result + .map(|artifacts| { + let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); + log::debug!(target: "runtime::bridge", "Sent XCM message {:?}/{} to Millau: {:?}", lane, artifacts.nonce, hash); + hash + }) + .map_err(|e| { + log::debug!(target: "runtime::bridge", "Failed to send XCM message over lane {:?} to Millau: {:?}", lane, e); + SendError::Transport("Bridge has rejected the message") + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_messages::{ + target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, + MessageKey, + }; + use bp_runtime::messages::MessageDispatchResult; + use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + + fn new_test_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::new( + frame_system::GenesisConfig::default().build_storage::().unwrap(), + ) + } + + #[test] + fn xcm_messages_to_rialto_are_sent() { + new_test_ext().execute_with(|| { + // the encoded message (origin ++ xcm) is 0x010109020419A8 + let dest = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))); + let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); + + let send_result = send_xcm::(dest.into(), xcm); + let expected_fee = MultiAssets::from((Here, 4_345_002_552_u64)); + let expected_hash = + ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); + assert_eq!(send_result, Ok((expected_hash, expected_fee)),); + }) + } + + #[test] + fn xcm_messages_from_rialto_are_dispatched() { + type XcmExecutor = xcm_executor::XcmExecutor; + type MessageDispatcher = FromBridgedChainMessageDispatch< + WithRialtoMessageBridge, + XcmExecutor, + XcmWeigher, + frame_support::traits::ConstU64, + >; + + new_test_ext().execute_with(|| { + let location: MultiLocation = + (Parent, X1(GlobalConsensus(RialtoNetwork::get()))).into(); + let xcm: Xcm = vec![Instruction::Trap(42)].into(); + + let mut incoming_message = DispatchMessage { + key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, + data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, + }; + + let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, 1_000_000_000); + + let dispatch_result = + MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert_eq!( + dispatch_result, + MessageDispatchResult { + dispatch_result: true, + unspent_weight: 0, + dispatch_fee_paid_during_dispatch: false, + } + ); + }) + } +} diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 10315e33c853a..9b3dc288c4939 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -290,6 +290,7 @@ fn testnet_genesis( owner: Some(get_account_id_from_seed::("MillauMessagesOwner")), ..Default::default() }, + xcm_pallet: Default::default(), } } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index ccfa65090e6d1..4c6bb990e19c6 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -66,12 +66,17 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master # Polkadot (parachain) Dependencies +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } +env_logger = "0.8" libsecp256k1 = { version = "0.7", features = ["hmac"] } static_assertions = "1.1" @@ -104,6 +109,7 @@ std = [ "pallet-bridge-messages/std", "pallet-grandpa/std", "pallet-mmr/std", + "pallet-xcm/std", "sp-mmr-primitives/std", "pallet-shift-session-manager/std", "pallet-sudo/std", @@ -130,6 +136,9 @@ std = [ "sp-transaction-pool/std", "sp-trie/std", "sp-version/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", @@ -138,5 +147,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", ] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 4d2602a20a608..52600c1a173a9 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -30,6 +30,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod millau_messages; pub mod parachains; +pub mod xcm_config; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; @@ -449,13 +450,7 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_bridge_messages::instant_payments::InstantCurrencyPayments< - Runtime, - WithMillauMessagesInstance, - pallet_balances::Pallet, - GetDeliveryConfirmationTransactionFee, - >; + type MessageDeliveryAndDispatchPayment = (); type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -513,6 +508,9 @@ construct_runtime!( Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event}, Slots: polkadot_runtime_common::slots::{Pallet, Call, Storage, Event}, ParasSudoWrapper: polkadot_runtime_common::paras_sudo_wrapper::{Pallet, Call}, + + // Pallet for sending XCM. + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, } ); @@ -902,6 +900,7 @@ impl_runtime_apis! { Runtime, WithMillauMessagesInstance, WithMillauMessageBridge, + xcm_config::OutboundXcmWeigher, >(lane, begin, end) } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 8088ee56ac754..ce1bd6b6fb0bc 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::Runtime; +use crate::{Call, OriginCaller, Runtime}; use bp_messages::{ source_chain::{SenderOrigin, TargetHeaderChain}, @@ -40,6 +40,10 @@ pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); /// Initial value of `MillauFeeMultiplier` parameter. pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge +/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual +/// tests, confirming that we don't break encoding somewhere between. +pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT; parameter_types! { /// Millau to Rialto conversion rate. Initially we treat both tokens as equal. @@ -56,14 +60,15 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithMillauMessageBridge, - crate::Runtime, - pallet_balances::Pallet, - (), + xcm_executor::XcmExecutor, + crate::xcm_config::XcmWeigher, + // + frame_support::traits::ConstU64, >; /// Messages proof for Millau -> Rialto messages. @@ -115,7 +120,23 @@ impl messages::ThisChainWithMessages for Rialto { type Call = crate::Call; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { - send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) + let here_location = + xcm::v3::MultiLocation::from(crate::xcm_config::UniversalLocation::get()); + match send_origin.caller { + OriginCaller::XcmPallet(pallet_xcm::Origin::Xcm(ref location)) + if *location == here_location => + { + log::trace!(target: "runtime::bridge", "Verifying message sent using XCM pallet to Millau"); + }, + _ => { + // keep in mind that in this case all messages are free (in term of fees) + // => it's just to keep testing bridge on our test deployments until we'll have a + // better option + log::trace!(target: "runtime::bridge", "Verifying message sent using messages pallet to Millau"); + }, + } + + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -262,14 +283,8 @@ impl SourceHeaderChain for Millau { impl SenderOrigin for crate::Origin { fn linked_account(&self) -> Option { - match self.caller { - crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => - Some(submitter.clone()), - crate::OriginCaller::system(frame_system::RawOrigin::Root) | - crate::OriginCaller::system(frame_system::RawOrigin::None) => - crate::RootAccountForPayments::get(), - _ => None, - } + // XCM deals wit fees in our deployments + None } } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs new file mode 100644 index 0000000000000..8cad3896b1b4b --- /dev/null +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -0,0 +1,318 @@ +// 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 . + +//! XCM configurations for the Rialto runtime. + +use super::{ + millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, + BridgeMillauMessages, Call, Event, Origin, Runtime, XcmPallet, +}; +use bp_messages::source_chain::MessagesBridge; +use bp_rialto::{Balance, WeightToFee}; +use bridge_runtime_common::messages::{ + source::{estimate_message_dispatch_and_delivery_fee, FromThisChainMessagePayload}, + MessageBridge, +}; +use codec::Encode; +use frame_support::{ + parameter_types, + traits::{Everything, Nothing}, + weights::Weight, +}; +use sp_std::marker::PhantomData; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, + CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, +}; + +parameter_types! { + /// The location of the `MLAU` token, from the context of this chain. Since this token is native to this + /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to + /// the context". + pub const TokenLocation: MultiLocation = Here.into_location(); + /// The Rialto network ID, associated with Polkadot. + pub const ThisNetwork: NetworkId = Polkadot; + /// The Millau network ID, associated with Kusama. + pub const MillauNetwork: NetworkId = Kusama; + + /// Our XCM location ancestry - i.e. our location within the Consensus Universe. + /// + /// Since Polkadot is a top-level relay-chain with its own consensus, it's just our network ID. + pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); + /// The check account, which holds any native assets that have been teleported out and not back in (yet). + pub CheckAccount: AccountId = XcmPallet::check_account(); +} + +/// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to +/// determine the sovereign account controlled by a location. +pub type SovereignAccountOf = ( + // We can directly alias an `AccountId32` into a local account. + AccountId32Aliases, +); + +/// Our asset transactor. This is what allows us to interest with the runtime facilities from the +/// point of view of XCM-only concepts like `MultiLocation` and `MultiAsset`. +/// +/// Ours is only aware of the Balances pallet, which is mapped to `TokenLocation`. +pub type LocalAssetTransactor = XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // We can convert the MultiLocations with our converter above: + SovereignAccountOf, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We track our teleports in/out to keep total issuance correct. + CheckAccount, +>; + +/// The means that we convert the XCM message origin location into a local dispatch origin. +type LocalOriginConverter = ( + // A `Signed` origin of the sovereign account that the original location controls. + SovereignSignedViaLocation, + // The AccountId32 location type can be expressed natively as a `Signed` origin. + SignedAccountId32AsNative, +); + +/// The amount of weight an XCM operation takes. This is a safe overestimate. +pub const BASE_XCM_WEIGHT: Weight = 1_000_000_000; + +parameter_types! { + /// The amount of weight an XCM operation takes. This is a safe overestimate. + pub const BaseXcmWeight: Weight = BASE_XCM_WEIGHT; + /// Maximum number of instructions in a single XCM fragment. A sanity check against weight + /// calculations getting too crazy. + pub const MaxInstructions: u32 = 100; +} + +/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our +/// individual routers. +pub type XcmRouter = ( + // Router to send messages to Millau. + ToMillauBridge, +); + +parameter_types! { + pub const MaxAssetsIntoHolding: u32 = 64; +} + +/// The barriers one of which must be passed for an XCM message to be executed. +pub type Barrier = ( + // Weight that is paid for may be consumed. + TakeWeightCredit, + // If the message is one that immediately attemps to pay for execution, then allow it. + AllowTopLevelPaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, +); + +/// Outbound XCM weigher type. +pub type OutboundXcmWeigher = xcm_builder::FixedWeightBounds; +/// Incoming XCM weigher type. +pub type XcmWeigher = xcm_builder::FixedWeightBounds; + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type Call = Call; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = (); + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = XcmWeigher; + // The weight trader piggybacks on the existing transaction-fee conversion logic. + type Trader = UsingComponents; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetLocker = (); + type AssetExchanger = (); + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; +} + +/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior +/// location of this chain. +pub type LocalOriginToLocation = ( + // Usual Signed origin to be used in XCM as a corresponding AccountId32 + SignedToAccountId32, +); + +impl pallet_xcm::Config for Runtime { + type Event = Event; + // We don't allow any messages to be sent via the transaction yet. This is basically safe to + // enable, (safe the possibility of someone spamming the parachain if they're willing to pay + // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will + // make `DescendOrigin` a bit more useful. + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // Anyone can execute XCM messages locally. + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = xcm_executor::XcmExecutor; + // Anyone is able to use teleportation regardless of who they are and what they want to + // teleport. + type XcmTeleportFilter = Everything; + // Anyone is able to use reserve transfers regardless of who they are and what they want to + // transfer. + type XcmReserveTransferFilter = Everything; + type Weigher = XcmWeigher; + type UniversalLocation = UniversalLocation; + type Origin = Origin; + type Call = Call; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = SovereignAccountOf; + type MaxLockers = frame_support::traits::ConstU32<8>; +} + +/// With-rialto bridge. +pub struct ToMillauBridge(PhantomData); + +impl> SendXcm + for ToMillauBridge +{ + type Ticket = (Balance, FromThisChainMessagePayload); + + fn validate( + dest: &mut Option, + msg: &mut Option>, + ) -> SendResult { + let d = dest.take().ok_or(SendError::MissingArgument)?; + if !matches!(d, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) + { + *dest = Some(d); + return Err(SendError::NotApplicable) + }; + + let dest: InteriorMultiLocation = MillauNetwork::get().into(); + let here = UniversalLocation::get(); + let route = dest.relative_to(&here); + let msg = (route, msg.take().unwrap()).encode(); + + let fee = estimate_message_dispatch_and_delivery_fee::( + &msg, + WithMillauMessageBridge::RELAYER_FEE_PERCENT, + None, + ) + .map_err(SendError::Transport)?; + let fee_assets = MultiAssets::from((Here, fee)); + + Ok(((fee, msg), fee_assets)) + } + + fn deliver(ticket: Self::Ticket) -> Result { + let lane = [0, 0, 0, 0]; + let (fee, msg) = ticket; + let result = MB::send_message( + pallet_xcm::Origin::from(MultiLocation::from(UniversalLocation::get())).into(), + lane, + msg, + fee, + ); + result + .map(|artifacts| { + let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); + log::debug!(target: "runtime::bridge", "Sent XCM message {:?}/{} to Rialto: {:?}", lane, artifacts.nonce, hash); + hash + }) + .map_err(|e| { + log::debug!(target: "runtime::bridge", "Failed to send XCM message over lane {:?} to Rialto: {:?}", lane, e); + SendError::Transport("Bridge has rejected the message") + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_messages::{ + target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, + MessageKey, + }; + use bp_runtime::messages::MessageDispatchResult; + use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + + fn new_test_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::new( + frame_system::GenesisConfig::default().build_storage::().unwrap(), + ) + } + + #[test] + fn xcm_messages_to_millau_are_sent() { + new_test_ext().execute_with(|| { + // the encoded message (origin ++ xcm) is 0x010109030419A8 + let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); + let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); + + let send_result = send_xcm::(dest.into(), xcm); + let expected_fee = MultiAssets::from((Here, 4_345_002_552_u128)); + let expected_hash = + ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); + assert_eq!(send_result, Ok((expected_hash, expected_fee)),); + }) + } + + #[test] + fn xcm_messages_from_millau_are_dispatched() { + type XcmExecutor = xcm_executor::XcmExecutor; + type MessageDispatcher = FromBridgedChainMessageDispatch< + WithMillauMessageBridge, + XcmExecutor, + XcmWeigher, + frame_support::traits::ConstU64, + >; + + new_test_ext().execute_with(|| { + let location: MultiLocation = + (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); + let xcm: Xcm = vec![Instruction::Trap(42)].into(); + + let mut incoming_message = DispatchMessage { + key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, + data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, + } + .into(); + + let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, 1_000_000_000); + + let dispatch_result = + MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert_eq!( + dispatch_result, + MessageDispatchResult { + dispatch_result: true, + unspent_weight: 0, + dispatch_fee_paid_during_dispatch: false, + } + ); + }) + } +} diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 7e8609071f86c..8177f11512574 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hash-db = { version = "0.15.2", default-features = false } log = { version = "0.4.14", default-features = false } +num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } @@ -29,12 +30,19 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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, optional = true } 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 } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +# Polkadot dependencies + +xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } + [features] default = ["std"] std = [ @@ -45,16 +53,21 @@ std = [ "frame-system/std", "hash-db/std", "log/std", + "num-traits/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-transaction-payment/std", "scale-info/std", "sp-api/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", "sp-state-machine/std", "sp-std/std", "sp-trie/std", + "xcm/std", + "xcm-builder/std", + "xcm-executor/std", ] runtime-benchmarks = [ "pallet-balances", @@ -62,6 +75,7 @@ runtime-benchmarks = [ "pallet-bridge-messages/runtime-benchmarks", "sp-state-machine", "sp-version", + "xcm-builder/runtime-benchmarks", ] integrity-test = [ "static_assertions", diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 603f385f29ed5..a145d81e9b230 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -115,7 +115,7 @@ macro_rules! assert_bridge_messages_pallet_types( use $crate::messages::{ source::FromThisChainMessagePayload, target::FromBridgedChainMessagePayload, - AccountIdOf, BalanceOf, BridgedChain, ThisChain, WeightOf, + AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, WeightOf, }; use pallet_bridge_messages::Config as MessagesConfig; use static_assertions::assert_type_eq_all; @@ -123,7 +123,7 @@ macro_rules! assert_bridge_messages_pallet_types( assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload); assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundMessageFee, BalanceOf>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload>>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundMessageFee, BalanceOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index f7eb0b2975d6b..d3e3ca28ab736 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -26,12 +26,12 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker}; -use codec::{Decode, Encode}; -use frame_support::{traits::Currency, weights::Weight, RuntimeDebug}; +use codec::{Decode, DecodeLimit, Encode}; +use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Saturating}, + traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, FixedPointNumber, FixedPointOperand, FixedU128, }; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; @@ -430,7 +430,35 @@ pub mod target { use super::*; /// Decoded Bridged -> This message payload. - pub type FromBridgedChainMessagePayload = Vec; + #[derive(RuntimeDebug, PartialEq)] + pub struct FromBridgedChainMessagePayload { + /// Data that is actually sent over the wire. + pub xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm), + /// Weight of the message, computed by the weigher. Unknown initially. + pub weight: Option, + } + + impl Decode for FromBridgedChainMessagePayload { + fn decode(input: &mut I) -> Result { + let _: codec::Compact = Decode::decode(input)?; + type XcmPairType = (xcm::v3::MultiLocation, xcm::v3::Xcm); + Ok(FromBridgedChainMessagePayload { + xcm: XcmPairType::::decode_with_depth_limit( + sp_api::MAX_EXTRINSIC_DEPTH, + input, + )?, + weight: None, + }) + } + } + + impl From<(xcm::v3::MultiLocation, xcm::v3::Xcm)> + for FromBridgedChainMessagePayload + { + fn from(xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm)) -> Self { + FromBridgedChainMessagePayload { xcm, weight: None } + } + } /// Messages proof from bridged chain: /// @@ -464,38 +492,84 @@ pub mod target { /// Dispatching Bridged -> This chain messages. #[derive(RuntimeDebug, Clone, Copy)] - pub struct FromBridgedChainMessageDispatch { - _marker: PhantomData<(B, ThisRuntime, ThisCurrency, ThisDispatchInstance)>, + pub struct FromBridgedChainMessageDispatch { + _marker: PhantomData<(B, XcmExecutor, XcmWeigher, WeightCredit)>, } - impl + impl MessageDispatch>, BalanceOf>> - for FromBridgedChainMessageDispatch + for FromBridgedChainMessageDispatch where - BalanceOf>: Saturating + FixedPointOperand, - ThisDispatchInstance: 'static, - ThisRuntime: pallet_transaction_payment::Config, - ::OnChargeTransaction: - pallet_transaction_payment::OnChargeTransaction< - ThisRuntime, - Balance = BalanceOf>, - >, - ThisCurrency: Currency>, Balance = BalanceOf>>, + XcmExecutor: xcm::v3::ExecuteXcm>>, + XcmWeigher: xcm_executor::traits::WeightBounds>>, + WeightCredit: Get, { - type DispatchPayload = FromBridgedChainMessagePayload; + type DispatchPayload = FromBridgedChainMessagePayload>>; fn dispatch_weight( - _message: &DispatchMessage>>, + message: &mut DispatchMessage>>, ) -> frame_support::weights::Weight { - 0 + match message.data.payload { + Ok(ref mut payload) => { + // I have no idea why this method takes `&mut` reference and there's nothing + // about that in documentation. Hope it'll only mutate iff error is returned. + let weight = XcmWeigher::weight(&mut payload.xcm.1); + let weight = weight.unwrap_or_else(|e| { + log::debug!( + target: "runtime::bridge-dispatch", + "Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}", + message.key.lane_id, + message.key.nonce, + e, + ); + + // we shall return 0 and then the XCM executor will fail to execute XCM + // if we'll return something else (e.g. maximal value), the lane may stuck + 0 + }); + + payload.weight = Some(weight); + weight + }, + _ => 0, + } } fn dispatch( _relayer_account: &AccountIdOf>, message: DispatchMessage>>, ) -> MessageDispatchResult { + use xcm::latest::*; + let message_id = (message.key.lane_id, message.key.nonce); - log::trace!(target: "runtime::bridge-dispatch", "Incoming message {:?}: {:?}", message_id, message.data.payload); + let do_dispatch = move || -> sp_std::result::Result { + let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } = + message.data.payload?; + log::trace!( + target: "runtime::bridge-dispatch", + "Going to execute message {:?} (weight limit: {:?}): {:?} {:?}", + message_id, + weight_limit, + location, + xcm, + ); + let hash = message_id.using_encoded(sp_io::hashing::blake2_256); + + // if this cod will end up in production, this most likely needs to be set to zero + let weight_credit = WeightCredit::get(); + + let xcm_outcome = XcmExecutor::execute_xcm_in_credit( + location, + xcm, + hash, + weight_limit.unwrap_or(0), + weight_credit, + ); + Ok(xcm_outcome) + }; + + let xcm_outcome = do_dispatch(); + log::trace!(target: "runtime::bridge-dispatch", "Incoming message {:?} dispatched with result: {:?}", message_id, xcm_outcome); MessageDispatchResult { dispatch_result: true, unspent_weight: 0, @@ -685,6 +759,112 @@ pub mod target { } } +pub use xcm_copy::*; + +// copy of private types from xcm-builder/src/universal_exports.rs +pub mod xcm_copy { + use codec::{Decode, Encode}; + use frame_support::{ensure, traits::Get}; + use sp_std::{convert::TryInto, marker::PhantomData, prelude::*}; + use xcm::prelude::*; + use xcm_executor::traits::ExportXcm; + + pub trait DispatchBlob { + /// Dispatches an incoming blob and returns the unexpectable weight consumed by the + /// dispatch. + fn dispatch_blob(blob: Vec) -> Result<(), DispatchBlobError>; + } + + pub trait HaulBlob { + /// Sends a blob over some point-to-point link. This will generally be implemented by a + /// bridge. + fn haul_blob(blob: Vec); + } + + #[derive(Clone, Encode, Decode)] + pub struct BridgeMessage { + /// The message destination as a *Universal Location*. This means it begins with a + /// `GlobalConsensus` junction describing the network under which global consensus happens. + /// If this does not match our global consensus then it's a fatal error. + universal_dest: VersionedInteriorMultiLocation, + message: VersionedXcm<()>, + } + + pub enum DispatchBlobError { + Unbridgable, + InvalidEncoding, + UnsupportedLocationVersion, + UnsupportedXcmVersion, + RoutingError, + NonUniversalDestination, + WrongGlobal, + } + + pub struct BridgeBlobDispatcher(PhantomData<(Router, OurPlace)>); + impl> DispatchBlob + for BridgeBlobDispatcher + { + fn dispatch_blob(blob: Vec) -> Result<(), DispatchBlobError> { + let our_universal = OurPlace::get(); + let our_global = + our_universal.global_consensus().map_err(|()| DispatchBlobError::Unbridgable)?; + let BridgeMessage { universal_dest, message } = + Decode::decode(&mut &blob[..]).map_err(|_| DispatchBlobError::InvalidEncoding)?; + let universal_dest: InteriorMultiLocation = universal_dest + .try_into() + .map_err(|_| DispatchBlobError::UnsupportedLocationVersion)?; + // `universal_dest` is the desired destination within the universe: first we need to + // check we're in the right global consensus. + let intended_global = universal_dest + .global_consensus() + .map_err(|()| DispatchBlobError::NonUniversalDestination)?; + ensure!(intended_global == our_global, DispatchBlobError::WrongGlobal); + let dest = universal_dest.relative_to(&our_universal); + let message: Xcm<()> = + message.try_into().map_err(|_| DispatchBlobError::UnsupportedXcmVersion)?; + send_xcm::(dest, message).map_err(|_| DispatchBlobError::RoutingError)?; + Ok(()) + } + } + + pub struct HaulBlobExporter( + PhantomData<(Bridge, BridgedNetwork, Price)>, + ); + impl, Price: Get> ExportXcm + for HaulBlobExporter + { + type Ticket = (Vec, XcmHash); + + fn validate( + network: NetworkId, + _channel: u32, + destination: &mut Option, + message: &mut Option>, + ) -> Result<((Vec, XcmHash), MultiAssets), SendError> { + let bridged_network = BridgedNetwork::get(); + ensure!(&network == &bridged_network, SendError::NotApplicable); + // We don't/can't use the `channel` for this adapter. + let dest = destination.take().ok_or(SendError::MissingArgument)?; + let universal_dest = match dest.pushed_front_with(GlobalConsensus(bridged_network)) { + Ok(d) => d.into(), + Err((dest, _)) => { + *destination = Some(dest); + return Err(SendError::NotApplicable) + }, + }; + let message = VersionedXcm::from(message.take().ok_or(SendError::MissingArgument)?); + let hash = message.using_encoded(sp_io::hashing::blake2_256); + let blob = BridgeMessage { universal_dest, message }.encode(); + Ok(((blob, hash), Price::get())) + } + + fn deliver((blob, hash): (Vec, XcmHash)) -> Result { + Bridge::haul_blob(blob); + Ok(hash) + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index 274d2ec2e00f8..4f5a175e24046 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -16,13 +16,15 @@ //! Helpers for implementing various message-related runtime API mthods. -use crate::messages::MessageBridge; +use crate::messages::{target::FromBridgedChainMessagePayload, MessageBridge}; -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{LaneId, MessageDetails, MessageKey, MessageNonce}; +use codec::Decode; +use frame_support::weights::Weight; use sp_std::vec::Vec; /// Implementation of the `To*OutboundLaneApi::message_details`. -pub fn outbound_message_details( +pub fn outbound_message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, @@ -31,6 +33,7 @@ where Runtime: pallet_bridge_messages::Config, MessagesPalletInstance: 'static, BridgeConfig: MessageBridge, + XcmWeigher: xcm_executor::traits::WeightBounds<()>, { (begin..=end) .filter_map(|nonce| { @@ -38,7 +41,12 @@ where pallet_bridge_messages::Pallet::::outbound_message_data(lane, nonce)?; Some(MessageDetails { nonce, - dispatch_weight: 0, + // this shall match the similar code in the `FromBridgedChainMessageDispatch` - if we have failed + // to decode or estimate dispatch weight, we'll just return 0 to disable actual execution + dispatch_weight: compute_message_weight::( + MessageKey { lane_id: lane, nonce }, + &message_data.payload, + ).unwrap_or(0), size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtTargetChain, @@ -46,3 +54,30 @@ where }) .collect() } + +// at the source chain we don't know the type of target chain `Call` => `()` is used (it is +// similarly currently used in Polkadot codebase) +fn compute_message_weight>( + message_key: MessageKey, + encoded_payload: &[u8], +) -> Result { + let mut payload = FromBridgedChainMessagePayload::<()>::decode(&mut &encoded_payload[..]) + .map_err(|e| { + log::debug!( + target: "runtime::bridge-dispatch", + "Failed to decode outbound XCM message {:?}: {:?}", + message_key, + e, + ); + })?; + let weight = XcmWeigher::weight(&mut payload.xcm.1); + let weight = weight.map_err(|e| { + log::debug!( + target: "runtime::bridge-dispatch", + "Failed to compute dispatch weight of outbound XCM message {:?}: {:?}", + message_key, + e, + ); + })?; + Ok(weight) +} diff --git a/modules/messages/src/instant_payments.rs b/modules/messages/src/instant_payments.rs deleted file mode 100644 index 2a620a9522258..0000000000000 --- a/modules/messages/src/instant_payments.rs +++ /dev/null @@ -1,350 +0,0 @@ -// 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 . - -//! Implementation of `MessageDeliveryAndDispatchPayment` trait on top of `Currency` trait. -//! -//! The payment is first transferred to a special `relayers-fund` account and only transferred -//! to the actual relayer in case confirmation is received. - -use crate::OutboundMessages; - -use bp_messages::{ - source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards, SenderOrigin}, - LaneId, MessageKey, MessageNonce, UnrewardedRelayer, -}; -use codec::Encode; -use frame_support::traits::{Currency as CurrencyT, ExistenceRequirement, Get}; -use num_traits::{SaturatingAdd, Zero}; -use sp_runtime::traits::Saturating; -use sp_std::{collections::vec_deque::VecDeque, fmt::Debug, ops::RangeInclusive}; - -/// Error that occurs when message fee is non-zero, but payer is not defined. -const NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE: &str = - "Non-zero message fee can't be paid by "; - -/// Instant message payments made in given currency. -/// -/// The balance is initially reserved in a special `relayers-fund` account, and transferred -/// to the relayer when message delivery is confirmed. -/// -/// Additionally, confirmation transaction submitter (`confirmation_relayer`) is reimbursed -/// with the confirmation rewards (part of message fee, reserved to pay for delivery confirmation). -/// -/// NOTE The `relayers-fund` account must always exist i.e. be over Existential Deposit (ED; the -/// pallet enforces that) to make sure that even if the message cost is below ED it is still paid -/// to the relayer account. -/// NOTE It's within relayer's interest to keep their balance above ED as well, to make sure they -/// can receive the payment. -pub struct InstantCurrencyPayments { - _phantom: sp_std::marker::PhantomData<(T, I, Currency, GetConfirmationFee)>, -} - -impl - MessageDeliveryAndDispatchPayment - for InstantCurrencyPayments -where - T: frame_system::Config + crate::Config, - I: 'static, - T::Origin: SenderOrigin, - Currency: CurrencyT, - Currency::Balance: From, - GetConfirmationFee: Get, -{ - type Error = &'static str; - - fn pay_delivery_and_dispatch_fee( - submitter: &T::Origin, - fee: &Currency::Balance, - relayer_fund_account: &T::AccountId, - ) -> Result<(), Self::Error> { - let submitter_account = match submitter.linked_account() { - Some(submitter_account) => submitter_account, - None if !fee.is_zero() => { - // if we'll accept some message that has declared that the `fee` has been paid but - // it isn't actually paid, then it'll lead to problems with delivery confirmation - // payments (see `pay_relayer_rewards` && `confirmation_relayer` in particular) - return Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE) - }, - None => { - // message lane verifier has accepted the message before, so this message - // is unpaid **by design** - // => let's just do nothing - return Ok(()) - }, - }; - - if !frame_system::Pallet::::account_exists(relayer_fund_account) { - return Err("The relayer fund account must exist for the message lanes pallet to work correctly."); - } - - Currency::transfer( - &submitter_account, - relayer_fund_account, - *fee, - // it's fine for the submitter to go below Existential Deposit and die. - ExistenceRequirement::AllowDeath, - ) - .map_err(Into::into) - } - - fn pay_relayers_rewards( - lane_id: LaneId, - messages_relayers: VecDeque>, - confirmation_relayer: &T::AccountId, - received_range: &RangeInclusive, - relayer_fund_account: &T::AccountId, - ) { - let relayers_rewards = - cal_relayers_rewards::(lane_id, messages_relayers, received_range); - if !relayers_rewards.is_empty() { - pay_relayers_rewards::( - confirmation_relayer, - relayers_rewards, - relayer_fund_account, - GetConfirmationFee::get(), - ); - } - } -} - -/// Calculate the relayers rewards -pub(crate) fn cal_relayers_rewards( - lane_id: LaneId, - messages_relayers: VecDeque>, - received_range: &RangeInclusive, -) -> RelayersRewards -where - T: frame_system::Config + crate::Config, - I: 'static, -{ - // remember to reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); - for entry in messages_relayers { - let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); - let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); - - // loop won't proceed if current entry is ahead of received range (begin > end). - // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain - let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); - for nonce in nonce_begin..nonce_end + 1 { - let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) - .expect("message was just confirmed; we never prune unconfirmed messages; qed"); - relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); - relayer_reward.messages += 1; - } - } - relayers_rewards -} - -/// Pay rewards to given relayers, optionally rewarding confirmation relayer. -fn pay_relayers_rewards( - confirmation_relayer: &AccountId, - relayers_rewards: RelayersRewards, - relayer_fund_account: &AccountId, - confirmation_fee: Currency::Balance, -) where - AccountId: Debug + Encode + PartialEq, - Currency: CurrencyT, - Currency::Balance: From, -{ - // reward every relayer except `confirmation_relayer` - let mut confirmation_relayer_reward = Currency::Balance::zero(); - for (relayer, reward) in relayers_rewards { - let mut relayer_reward = reward.reward; - - if relayer != *confirmation_relayer { - // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee - // from relayer reward. - // - // If confirmation fee has been increased (or if it was the only component of message - // fee), then messages relayer may receive zero reward. - let mut confirmation_reward = confirmation_fee.saturating_mul(reward.messages.into()); - if confirmation_reward > relayer_reward { - confirmation_reward = relayer_reward; - } - relayer_reward = relayer_reward.saturating_sub(confirmation_reward); - confirmation_relayer_reward = - confirmation_relayer_reward.saturating_add(confirmation_reward); - } else { - // If delivery confirmation is submitted by this relayer, let's add confirmation fee - // from other relayers to this relayer reward. - confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward); - continue - } - - pay_relayer_reward::(relayer_fund_account, &relayer, relayer_reward); - } - - // finally - pay reward to confirmation relayer - pay_relayer_reward::( - relayer_fund_account, - confirmation_relayer, - confirmation_relayer_reward, - ); -} - -/// Transfer funds from relayers fund account to given relayer. -fn pay_relayer_reward( - relayer_fund_account: &AccountId, - relayer_account: &AccountId, - reward: Currency::Balance, -) where - AccountId: Debug, - Currency: CurrencyT, -{ - if reward.is_zero() { - return - } - - let pay_result = Currency::transfer( - relayer_fund_account, - relayer_account, - reward, - // the relayer fund account must stay above ED (needs to be pre-funded) - ExistenceRequirement::KeepAlive, - ); - - match pay_result { - Ok(_) => log::trace!( - target: "runtime::bridge-messages", - "Rewarded relayer {:?} with {:?}", - relayer_account, - reward, - ), - Err(error) => log::trace!( - target: "runtime::bridge-messages", - "Failed to pay relayer {:?} reward {:?}: {:?}", - relayer_account, - reward, - error, - ), - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::{ - run_test, AccountId as TestAccountId, Balance as TestBalance, Origin, TestRuntime, - }; - use bp_messages::source_chain::RelayerRewards; - - type Balances = pallet_balances::Pallet; - - const RELAYER_1: TestAccountId = 1; - const RELAYER_2: TestAccountId = 2; - const RELAYER_3: TestAccountId = 3; - const RELAYERS_FUND_ACCOUNT: TestAccountId = crate::mock::ENDOWED_ACCOUNT; - - fn relayers_rewards() -> RelayersRewards { - vec![ - (RELAYER_1, RelayerRewards { reward: 100, messages: 2 }), - (RELAYER_2, RelayerRewards { reward: 100, messages: 3 }), - ] - .into_iter() - .collect() - } - - #[test] - fn pay_delivery_and_dispatch_fee_fails_on_non_zero_fee_and_unknown_payer() { - frame_support::parameter_types! { - const GetConfirmationFee: TestBalance = 0; - }; - - run_test(|| { - let result = InstantCurrencyPayments::< - TestRuntime, - (), - Balances, - GetConfirmationFee, - >::pay_delivery_and_dispatch_fee( - &Origin::root(), - &100, - &RELAYERS_FUND_ACCOUNT, - ); - assert_eq!(result, Err(NON_ZERO_MESSAGE_FEE_CANT_BE_PAID_BY_NONE)); - }); - } - - #[test] - fn pay_delivery_and_dispatch_succeeds_on_zero_fee_and_unknown_payer() { - frame_support::parameter_types! { - const GetConfirmationFee: TestBalance = 0; - }; - - run_test(|| { - let result = InstantCurrencyPayments::< - TestRuntime, - (), - Balances, - GetConfirmationFee, - >::pay_delivery_and_dispatch_fee( - &Origin::root(), - &0, - &RELAYERS_FUND_ACCOUNT, - ); - assert!(result.is_ok()); - }); - } - - #[test] - fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { - run_test(|| { - pay_relayers_rewards::( - &RELAYER_2, - relayers_rewards(), - &RELAYERS_FUND_ACCOUNT, - 10, - ); - - assert_eq!(Balances::free_balance(&RELAYER_1), 80); - assert_eq!(Balances::free_balance(&RELAYER_2), 120); - }); - } - - #[test] - fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { - run_test(|| { - pay_relayers_rewards::( - &RELAYER_3, - relayers_rewards(), - &RELAYERS_FUND_ACCOUNT, - 10, - ); - - assert_eq!(Balances::free_balance(&RELAYER_1), 80); - assert_eq!(Balances::free_balance(&RELAYER_2), 70); - assert_eq!(Balances::free_balance(&RELAYER_3), 50); - }); - } - - #[test] - fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { - run_test(|| { - pay_relayers_rewards::( - &RELAYER_3, - relayers_rewards(), - &RELAYERS_FUND_ACCOUNT, - 1000, - ); - - assert_eq!(Balances::free_balance(&RELAYER_1), 0); - assert_eq!(Balances::free_balance(&RELAYER_2), 0); - assert_eq!(Balances::free_balance(&RELAYER_3), 200); - }); - } -} diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 10cdaae40712c..5c3398ff705f4 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -51,14 +51,14 @@ use crate::{ use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, SendMessageArtifacts, TargetHeaderChain, + OnMessageAccepted, RelayersRewards, SendMessageArtifacts, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OperatingMode, OutboundLaneData, Parameter as MessagesParameter, - UnrewardedRelayersState, + UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; @@ -71,13 +71,15 @@ use frame_system::RawOrigin; use num_traits::{SaturatingAdd, Zero}; use sp_core::H256; use sp_runtime::traits::{BadOrigin, Convert}; -use sp_std::{cell::RefCell, cmp::PartialOrd, marker::PhantomData, prelude::*}; +use sp_std::{ + cell::RefCell, cmp::PartialOrd, collections::vec_deque::VecDeque, marker::PhantomData, + ops::RangeInclusive, prelude::*, +}; mod inbound_lane; mod outbound_lane; mod weights_ext; -pub mod instant_payments; pub mod weights; #[cfg(feature = "runtime-benchmarks")] @@ -426,13 +428,13 @@ pub mod pallet { } } - for message in lane_data.messages { + for mut message in lane_data.messages { debug_assert_eq!(message.key.lane_id, lane_id); // ensure that relayer has declared enough weight for dispatching next message // on this lane. We can't dispatch lane messages out-of-order, so if declared // weight is not enough, let's move to next lane - let dispatch_weight = T::MessageDispatch::dispatch_weight(&message); + let dispatch_weight = T::MessageDispatch::dispatch_weight(&mut message); if dispatch_weight > dispatch_weight_left { log::trace!( target: "runtime::bridge-messages", @@ -767,7 +769,6 @@ pub mod pallet { /// /// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending /// on the implementation it can be used to store relayers rewards. -/// See [`InstantCurrencyPayments`] for a concrete implementation. pub fn relayer_fund_account_id>( ) -> AccountId { let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); @@ -921,6 +922,36 @@ fn send_message, I: 'static>( Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } +/// Calculate the relayers rewards +pub fn calc_relayers_rewards( + lane_id: LaneId, + messages_relayers: VecDeque>, + received_range: &RangeInclusive, +) -> RelayersRewards +where + T: frame_system::Config + crate::Config, + I: 'static, +{ + // remember to reward relayers that have delivered messages + // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain + let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); + for entry in messages_relayers { + let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); + let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); + + // loop won't proceed if current entry is ahead of received range (begin > end). + // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); + for nonce in nonce_begin..nonce_end + 1 { + let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) + .expect("message was just confirmed; we never prune unconfirmed messages; qed"); + relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); + relayer_reward.messages += 1; + } + } + relayers_rewards +} + /// Ensure that the origin is either root, or `PalletOwner`. fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { match origin.into() { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 5bf36f6809cc0..a4ecb0467b79a 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -17,7 +17,7 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::{instant_payments::cal_relayers_rewards, Config}; +use crate::{calc_relayers_rewards, Config}; use bitvec::prelude::*; use bp_messages::{ @@ -375,7 +375,7 @@ impl MessageDeliveryAndDispatchPayment _relayer_fund_account: &AccountId, ) { let relayers_rewards = - cal_relayers_rewards::(lane_id, message_relayers, received_range); + calc_relayers_rewards::(lane_id, message_relayers, received_range); for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward.reward).encode(); frame_support::storage::unhashed::put(&key, &true); @@ -489,7 +489,7 @@ pub struct TestMessageDispatch; impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; - fn dispatch_weight(message: &DispatchMessage) -> Weight { + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { Ok(payload) => payload.declared_weight, Err(_) => 0, diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index fa7b3bb85ed05..28ce49acc0d7b 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -149,6 +149,29 @@ pub trait MessageDeliveryAndDispatchPayment { ); } +impl + MessageDeliveryAndDispatchPayment for () +{ + type Error = &'static str; + + fn pay_delivery_and_dispatch_fee( + _submitter: &SenderOrigin, + _fee: &Balance, + _relayer_fund_account: &AccountId, + ) -> Result<(), Self::Error> { + Ok(()) + } + + fn pay_relayers_rewards( + _lane_id: LaneId, + _messages_relayers: VecDeque>, + _confirmation_relayer: &AccountId, + _received_range: &RangeInclusive, + _relayer_fund_account: &AccountId, + ) { + } +} + /// Send message artifacts. #[derive(RuntimeDebug, PartialEq)] pub struct SendMessageArtifacts { diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index a84ea7af907de..1ee0d7d631089 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -95,7 +95,7 @@ pub trait MessageDispatch { /// /// This function must: (1) be instant and (2) return correct upper bound /// of dispatch weight. - fn dispatch_weight(message: &DispatchMessage) -> Weight; + fn dispatch_weight(message: &mut DispatchMessage) -> Weight; /// Called when inbound message is received. /// @@ -156,7 +156,7 @@ impl SourceHeaderChain for ForbidInboundMessages { impl MessageDispatch for ForbidInboundMessages { type DispatchPayload = (); - fn dispatch_weight(_message: &DispatchMessage) -> Weight { + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX } From 31de5f7db8c3303cd40e7128873b50506d217b69 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 16 May 2022 14:07:17 +0300 Subject: [PATCH 0687/1210] CheckBridgedBlockNumber signed extension to reject duplicate header-submit transactions (#1352) * CheckBridgedBlockNumber signed extension to reject duplicate header submit transactions * fix depends_on --- bin/millau/runtime/src/lib.rs | 7 ++ modules/grandpa/src/extension.rs | 171 +++++++++++++++++++++++++++++++ modules/grandpa/src/lib.rs | 5 +- modules/grandpa/src/mock.rs | 2 +- relays/client-millau/Cargo.toml | 1 + relays/client-millau/src/lib.rs | 2 + 6 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 modules/grandpa/src/extension.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 178ec2e18e567..9d59d85d88e2a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -500,6 +500,12 @@ construct_runtime!( } ); +pallet_bridge_grandpa::declare_check_bridged_block_number_ext! { + Runtime, + Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, + Call::BridgeWestendGrandpa => WestendGrandpaInstance +} + /// The address format for describing accounts. pub type Address = AccountId; /// Block header type as expected by this runtime. @@ -520,6 +526,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + CheckBridgedBlockNumber, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs new file mode 100644 index 0000000000000..bddb722c92b83 --- /dev/null +++ b/modules/grandpa/src/extension.rs @@ -0,0 +1,171 @@ +// Copyright 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 . + +/// Declares a runtime-specific `CheckBridgedBlockNumber` signed extension. +/// +/// ## Example +/// +/// ```nocompile +/// pallet_bridge_grandpa::declare_check_bridged_block_number_ext!{ +/// Runtime, +/// Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, +/// Call::BridgeWestendGrandpa => WestendGrandpaInstance, +/// } +/// ``` +#[macro_export] +macro_rules! declare_check_bridged_block_number_ext { + ($runtime:ident, $($call:path => $instance:ty),*) => { + /// Transaction-with-obsolete-bridged-header check that will reject transaction if + /// it submits obsolete bridged header. + #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] + pub struct CheckBridgedBlockNumber; + + impl sp_runtime::traits::SignedExtension for CheckBridgedBlockNumber { + const IDENTIFIER: &'static str = "CheckBridgedBlockNumber"; + type AccountId = <$runtime as frame_system::Config>::AccountId; + type Call = <$runtime as frame_system::Config>::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result< + (), + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> sp_runtime::transaction_validity::TransactionValidity { + match *call { + $( + $call($crate::Call::<$runtime, $instance>::submit_finality_proof { ref finality_target, ..}) => { + use sp_runtime::traits::Header as HeaderT; + + let bundled_block_number = *finality_target.number(); + + let best_finalized_hash = $crate::BestFinalized::<$runtime, $instance>::get(); + let best_finalized_number = match $crate::ImportedHeaders::< + $runtime, + $instance, + >::get(best_finalized_hash) { + Some(best_finalized_header) => *best_finalized_header.number(), + None => return sp_runtime::transaction_validity::InvalidTransaction::Call.into(), + }; + + if best_finalized_number < bundled_block_number { + Ok(sp_runtime::transaction_validity::ValidTransaction::default()) + } else { + sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + } + }, + )* + _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), + } + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(drop) + } + + fn post_dispatch( + _maybe_pre: Option, + _info: &sp_runtime::traits::DispatchInfoOf, + _post_info: &sp_runtime::traits::PostDispatchInfoOf, + _len: usize, + _result: &sp_runtime::DispatchResult, + ) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> { + Ok(()) + } + } + }; +} + +#[cfg(test)] +mod tests { + use crate::{ + mock::{run_test, test_header, Call, TestNumber, TestRuntime}, + BestFinalized, ImportedHeaders, + }; + use bp_test_utils::make_default_justification; + use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; + use sp_runtime::traits::SignedExtension; + + declare_check_bridged_block_number_ext! { + TestRuntime, + Call::Grandpa => () + } + + fn validate_block_submit(num: TestNumber) -> bool { + CheckBridgedBlockNumber + .validate( + &42, + &Call::Grandpa(crate::Call::::submit_finality_proof { + finality_target: Box::new(test_header(num)), + justification: make_default_justification(&test_header(num)), + }), + &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, + 0, + ) + .is_ok() + } + + fn sync_to_header_10() { + let header10_hash = sp_core::H256::default(); + BestFinalized::::put(header10_hash); + ImportedHeaders::::insert(header10_hash, test_header(10)); + } + + #[test] + fn check_bridged_block_number_rejects_obsolete_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#5 => tx is + // rejected + sync_to_header_10(); + assert!(!validate_block_submit(5)); + }); + } + + #[test] + fn check_bridged_block_number_rejects_same_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#10 => tx is + // rejected + sync_to_header_10(); + assert!(!validate_block_submit(10)); + }); + } + + #[test] + fn check_bridged_block_number_accepts_new_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#15 => tx is + // accepted + sync_to_header_10(); + assert!(validate_block_submit(15)); + }); + } +} diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 105dfb15ac703..4184464231286 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -45,10 +45,11 @@ use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; use sp_std::{boxed::Box, convert::TryInto}; +mod extension; #[cfg(test)] mod mock; -/// Pallet containing weights for this pallet. +/// Module, containing weights for this pallet. pub mod weights; #[cfg(feature = "runtime-benchmarks")] @@ -269,7 +270,7 @@ pub mod pallet { /// Hash of the best finalized header. #[pallet::storage] - pub(super) type BestFinalized, I: 'static = ()> = + pub type BestFinalized, I: 'static = ()> = StorageValue<_, BridgedBlockHash, ValueQuery>; /// A ring buffer of imported hashes. Ordered by the insertion time. diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index bfc749d5230c6..a0327761fc850 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -42,7 +42,7 @@ construct_runtime! { UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Grandpa: grandpa::{Pallet}, + Grandpa: grandpa::{Pallet, Call}, } } diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 9893243345518..ab342f63ad9a4 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -15,6 +15,7 @@ relay-utils = { path = "../utils" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } millau-runtime = { path = "../../bin/millau/runtime" } +pallet-bridge-grandpa = { path = "../../modules/grandpa" } # Substrate Dependencies diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index eae9d9b4586a5..cefc722168e46 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -113,6 +113,7 @@ impl TransactionSignScheme for Millau { frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), + millau_runtime::CheckBridgedBlockNumber, // TODO ), ( (), @@ -123,6 +124,7 @@ impl TransactionSignScheme for Millau { (), (), (), + (), ), ); let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); From f2d18f00b49eb990d33fdffbb6584ff9c5e687ed Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 20 May 2022 11:34:52 +0300 Subject: [PATCH 0688/1210] Parachains finality relay (#1199) --- bin/millau/runtime/Cargo.toml | 2 + bin/millau/runtime/src/lib.rs | 17 + modules/parachains/Cargo.toml | 2 + modules/parachains/src/lib.rs | 41 +- modules/parachains/src/mock.rs | 4 + primitives/chain-millau/src/lib.rs | 3 + primitives/parachains/Cargo.toml | 34 + primitives/parachains/src/lib.rs | 68 ++ primitives/polkadot-core/src/parachains.rs | 2 +- relays/bin-substrate/Cargo.toml | 2 + relays/bin-substrate/src/chains/mod.rs | 1 + .../src/chains/rialto_parachains_to_millau.rs | 39 + relays/bin-substrate/src/cli/mod.rs | 4 + .../bin-substrate/src/cli/relay_parachains.rs | 119 ++ relays/client-substrate/Cargo.toml | 6 +- relays/client-substrate/src/guard.rs | 45 +- relays/client-substrate/src/lib.rs | 1 + relays/client-substrate/src/test_chain.rs | 71 ++ relays/lib-substrate-relay/Cargo.toml | 4 + relays/lib-substrate-relay/src/lib.rs | 2 + .../src/parachains_source.rs | 91 ++ .../src/parachains_target.rs | 211 ++++ relays/parachains/Cargo.toml | 28 + relays/parachains/src/lib.rs | 30 + relays/parachains/src/parachains_loop.rs | 1020 +++++++++++++++++ .../parachains/src/parachains_loop_metrics.rs | 34 + 26 files changed, 1814 insertions(+), 67 deletions(-) create mode 100644 primitives/parachains/Cargo.toml create mode 100644 primitives/parachains/src/lib.rs create mode 100644 relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs create mode 100644 relays/bin-substrate/src/cli/relay_parachains.rs create mode 100644 relays/client-substrate/src/test_chain.rs create mode 100644 relays/lib-substrate-relay/src/parachains_source.rs create mode 100644 relays/lib-substrate-relay/src/parachains_target.rs create mode 100644 relays/parachains/Cargo.toml create mode 100644 relays/parachains/src/lib.rs create mode 100644 relays/parachains/src/parachains_loop.rs create mode 100644 relays/parachains/src/parachains_loop_metrics.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 598b100e1ab82..97c6878eb8437 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -26,6 +26,7 @@ bp-westend = { path = "../../../primitives/chain-westend", default-features = fa bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies @@ -102,6 +103,7 @@ std = [ "pallet-beefy-mmr/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", "pallet-grandpa/std", "pallet-mmr/std", "pallet-randomness-collective-flip/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 9d59d85d88e2a..6f38f7a54ed54 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -73,6 +73,7 @@ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; pub use pallet_bridge_messages::Call as MessagesCall; +pub use pallet_bridge_parachains::Call as BridgeParachainsCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; @@ -461,6 +462,19 @@ impl pallet_bridge_messages::Config for Runtime { type BridgedChainId = RialtoChainId; } +parameter_types! { + pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; +} + +/// Instance of the with-Rialto parachains token swap pallet. +pub type WitRialtoParachainsInstance = (); + +impl pallet_bridge_parachains::Config for Runtime { + type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; + type ParasPalletName = RialtoParasPalletName; + type HeadsToKeep = HeadersToKeep; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -495,6 +509,9 @@ construct_runtime!( // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, + // Rialto parachains bridge modules. + BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage}, + // Pallet for sending XCM. XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 6ed9552e56b66..e6942bf7ce349 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -13,6 +13,7 @@ serde = { version = "1.0.101", optional = true } # Bridge Dependencies +bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../grandpa", default-features = false } @@ -34,6 +35,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] std = [ + "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", "codec/std", diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 3f5d214f61d51..9bed2b7a18a97 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -23,7 +23,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaId, ParachainHeadsProof}; +use bp_parachains::parachain_head_storage_key_at_source; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; @@ -73,12 +74,16 @@ pub mod pallet { pub trait Config: pallet_bridge_grandpa::Config { - /// Instance of bridges GRANDPA pallet that this pallet is linked to. + /// Instance of bridges GRANDPA pallet (within this runtime) that this pallet is linked to. /// /// The GRANDPA pallet instance must be configured to import headers of relay chain that /// we're interested in. type BridgesGrandpaPalletInstance: 'static; + /// Name of the `paras` pallet in the `construct_runtime!()` call at the bridged chain. + #[pallet::constant] + type ParasPalletName: Get<&'static str>; + /// Maximal number of single parachain heads to keep in the storage. /// /// The setting is there to prevent growing the on-chain state indefinitely. Note @@ -129,7 +134,7 @@ pub mod pallet { _origin: OriginFor, relay_block_hash: RelayBlockHash, parachains: Vec, - parachain_heads_proof: ParachainHeadsProof, + parachain_heads_proof: ParaHeadsProof, ) -> DispatchResult { // we'll need relay chain header to verify that parachains heads are always increasing. let relay_block = pallet_bridge_grandpa::ImportedHeaders::< @@ -190,7 +195,8 @@ pub mod pallet { storage: &bp_runtime::StorageProofChecker, parachain: ParaId, ) -> Option { - let parachain_head_key = storage_keys::parachain_head_key(parachain); + let parachain_head_key = + parachain_head_storage_key_at_source(T::ParasPalletName::get(), parachain); let parachain_head = storage.read_value(parachain_head_key.0.as_ref()).ok()??; let parachain_head = ParaHead::decode(&mut ¶chain_head[..]).ok()?; Some(parachain_head) @@ -257,6 +263,12 @@ pub mod pallet { updated_head_hash, ); ImportedParaHeads::::insert(parachain, updated_head_hash, updated_head); + log::trace!( + target: "runtime::bridge-parachains", + "Updated head of parachain {:?} to {}", + parachain, + updated_head_hash, + ); // remove old head if let Ok(head_hash_to_prune) = head_hash_to_prune { @@ -274,22 +286,10 @@ pub mod pallet { } } -pub mod storage_keys { - use super::*; - use bp_runtime::storage_map_final_key; - use frame_support::Twox64Concat; - use sp_core::storage::StorageKey; - - /// Storage key of the parachain head in the runtime storage of relay chain. - pub fn parachain_head_key(parachain: ParaId) -> StorageKey { - storage_map_final_key::("Paras", "Heads", ¶chain.encode()) - } -} - #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_relay_header, Origin, TestRuntime}; + use crate::mock::{run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME}; use bp_test_utils::{authority_list, make_default_justification}; use frame_support::{assert_noop, assert_ok, traits::OnInitialize}; @@ -330,13 +330,14 @@ mod tests { fn prepare_parachain_heads_proof( heads: Vec<(ParaId, ParaHead)>, - ) -> (RelayBlockHash, ParachainHeadsProof) { + ) -> (RelayBlockHash, ParaHeadsProof) { let mut root = Default::default(); let mut mdb = MemoryDB::default(); { let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); for (parachain, head) in heads { - let storage_key = storage_keys::parachain_head_key(parachain); + let storage_key = + parachain_head_storage_key_at_source(PARAS_PALLET_NAME, parachain); trie.insert(&storage_key.0, &head.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in tests"); @@ -372,7 +373,7 @@ mod tests { fn import_parachain_1_head( relay_chain_block: RelayBlockNumber, relay_state_root: RelayBlockHash, - proof: ParachainHeadsProof, + proof: ParaHeadsProof, ) -> sp_runtime::DispatchResult { Pallet::::submit_parachain_heads( Origin::signed(1), diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index fcd157020bc1b..506783cdb4966 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -33,6 +33,8 @@ pub type RelayBlockHeader = type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +pub const PARAS_PALLET_NAME: &str = "Paras"; + construct_runtime! { pub enum TestRuntime where Block = Block, @@ -103,10 +105,12 @@ impl pallet_bridge_grandpa::Config for TestRun parameter_types! { pub const HeadsToKeep: u32 = 4; + pub const ParasPalletName: &'static str = PARAS_PALLET_NAME; } impl pallet_bridge_parachains::Config for TestRuntime { type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; + type ParasPalletName = ParasPalletName; type HeadsToKeep = HeadsToKeep; } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 281ea471a2cfc..79c0e63628116 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -269,6 +269,9 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; +/// Name of the With-Rialto parachains bridge pallet name in the Millau runtime. +pub const BRIDGE_PARAS_PALLET_NAME: &str = "BridgeRialtoParachains"; + /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml new file mode 100644 index 0000000000000..a27dd03363d47 --- /dev/null +++ b/primitives/parachains/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "bp-parachains" +description = "Primitives of parachains module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } + +# Bridge dependencies + +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", 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 } + +[features] +default = ["std"] +std = [ + "bp-polkadot-core/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "scale-info/std", + "serde", + "sp-core/std", +] diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs new file mode 100644 index 0000000000000..0ed4e11480dad --- /dev/null +++ b/primitives/parachains/src/lib.rs @@ -0,0 +1,68 @@ +// 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 . + +//! Primitives of parachains module. + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_polkadot_core::{ + parachains::{ParaHash, ParaId}, + BlockNumber as RelayBlockNumber, +}; +use codec::{Decode, Encode}; +use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; +use scale_info::TypeInfo; +use sp_core::storage::StorageKey; + +/// Best known parachain head hash. +#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +pub struct BestParaHeadHash { + /// Number of relay block where this head has been read. + /// + /// Parachain head is opaque to relay chain. So we can't simply decode it as a header of + /// parachains and call `block_number()` on it. Instead, we're using the fact that parachain + /// head is always built on top of previous head (because it is blockchain) and relay chain + /// always imports parachain heads in order. What it means for us is that at any given + /// **finalized** relay block `B`, head of parachain will be ancestor (or the same) of all + /// parachain heads available at descendants of `B`. + pub at_relay_block_number: RelayBlockNumber, + /// Hash of parachain head. + pub head_hash: ParaHash, +} + +/// Returns runtime storage key of given parachain head at the source chain. +/// +/// The head is stored by the `paras` pallet in the `Heads` map. +pub fn parachain_head_storage_key_at_source( + paras_pallet_name: &str, + para_id: ParaId, +) -> StorageKey { + bp_runtime::storage_map_final_key::(paras_pallet_name, "Heads", ¶_id.encode()) +} + +/// Returns runtime storage key of best known parachain head at the target chain. +/// +/// The head is stored by the `pallet-bridge-parachains` pallet in the `BestParaHeads` map. +pub fn parachain_head_storage_key_at_target( + bridge_parachains_pallet_name: &str, + para_id: ParaId, +) -> StorageKey { + bp_runtime::storage_map_final_key::( + bridge_parachains_pallet_name, + "BestParaHeads", + ¶_id.encode(), + ) +} diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index c0448a846b346..7f8b20067758c 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -79,4 +79,4 @@ impl ParaHead { pub type ParaHash = crate::Hash; /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. -pub type ParachainHeadsProof = Vec>; +pub type ParaHeadsProof = Vec>; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 1d1166d1a9d1d..6ea4bacb191c9 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -27,6 +27,7 @@ bp-kusama = { path = "../../primitives/chain-kusama" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } @@ -39,6 +40,7 @@ messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } +parachains-relay = { path = "../parachains" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } relay-polkadot-client = { path = "../client-polkadot" } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 9b3416f901cfa..7659fc4897633 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -24,6 +24,7 @@ pub mod polkadot_headers_to_kusama; pub mod polkadot_messages_to_kusama; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; +pub mod rialto_parachains_to_millau; pub mod rococo_headers_to_wococo; pub mod rococo_messages_to_wococo; pub mod westend_headers_to_millau; diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs new file mode 100644 index 0000000000000..492f1fdf16d01 --- /dev/null +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -0,0 +1,39 @@ +// 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 . + +//! Rialto-to-Millau parachains sync entrypoint. + +use parachains_relay::ParachainsPipeline; +use relay_millau_client::Millau; +use relay_rialto_client::Rialto; +use substrate_relay_helper::parachains_target::DirectSubmitParachainHeadsCallBuilder; + +/// Rialto-to-Millau parachains sync description. +#[derive(Clone, Debug)] +pub struct RialtoToMillauParachains; + +impl ParachainsPipeline for RialtoToMillauParachains { + type SourceChain = Rialto; + type TargetChain = Millau; +} + +/// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. +pub type RialtoToMillauParachainsSubmitParachainHeadsCallBuilder = + DirectSubmitParachainHeadsCallBuilder< + RialtoToMillauParachains, + millau_runtime::Runtime, + millau_runtime::WitRialtoParachainsInstance, + >; diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index fddae4ee7abb5..bf2bede5d2532 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -36,6 +36,7 @@ mod reinit_bridge; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; +mod relay_parachains; mod resubmit_transactions; /// Parse relay CLI args. @@ -85,6 +86,8 @@ pub enum Command { ResubmitTransactions(resubmit_transactions::ResubmitTransactions), /// Register parachain. RegisterParachain(register_parachain::RegisterParachain), + /// + RelayParachains(relay_parachains::RelayParachains), } impl Command { @@ -118,6 +121,7 @@ impl Command { Self::EstimateFee(arg) => arg.run().await?, Self::ResubmitTransactions(arg) => arg.run().await?, Self::RegisterParachain(arg) => arg.run().await?, + Self::RelayParachains(arg) => arg.run().await?, } Ok(()) } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs new file mode 100644 index 0000000000000..f1af5b5c95873 --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -0,0 +1,119 @@ +// 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 . + +use bp_polkadot_core::parachains::ParaId; +use parachains_relay::{parachains_loop::ParachainSyncParams, ParachainsPipeline}; +use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::{ + parachains_source::ParachainsSource, parachains_target::ParachainsTarget, TransactionParams, +}; + +use crate::cli::{ + PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, +}; + +/// Start parachain heads relayer process. +#[derive(StructOpt)] +pub struct RelayParachains { + /// A bridge instance to relay parachains heads for. + #[structopt(possible_values = RelayParachainsBridge::VARIANTS, case_insensitive = true)] + bridge: RelayParachainsBridge, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Parachain heads relay bridge. +#[derive(Debug, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +pub enum RelayParachainsBridge { + RialtoToMillau, +} + +macro_rules! select_bridge { + ($bridge: expr, $generic: tt) => { + match $bridge { + RelayParachainsBridge::RialtoToMillau => { + use crate::chains::rialto_parachains_to_millau::{ + RialtoToMillauParachains as Pipeline, + RialtoToMillauParachainsSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder, + }; + + use bp_millau::BRIDGE_PARAS_PALLET_NAME as BRIDGE_PARAS_PALLET_NAME_AT_TARGET; + use bp_rialto::PARAS_PALLET_NAME as PARAS_PALLET_NAME_AT_SOURCE; + + use relay_millau_client::Millau as TargetTransactionSignScheme; + + $generic + }, + } + }; +} + +impl RelayParachains { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + select_bridge!(self.bridge, { + type SourceChain = ::SourceChain; + type TargetChain = ::TargetChain; + + let source_client = self.source.to_client::().await?; + let source_client = ParachainsSource::::new( + source_client, + PARAS_PALLET_NAME_AT_SOURCE.into(), + ); + + let taret_transaction_params = TransactionParams { + signer: self.target_sign.to_keypair::()?, + mortality: self.target_sign.target_transactions_mortality, + }; + let target_client = self.target.to_client::().await?; + let target_client = ParachainsTarget::< + Pipeline, + TargetTransactionSignScheme, + SubmitParachainHeadsCallBuilder, + >::new( + target_client.clone(), + taret_transaction_params, + BRIDGE_PARAS_PALLET_NAME_AT_TARGET.into(), + ); + + let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + + parachains_relay::parachains_loop::run( + source_client, + target_client, + ParachainSyncParams { + parachains: vec![ParaId(2000)], + stall_timeout: std::time::Duration::from_secs(60), + strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, + }, + metrics_params, + futures::future::pending(), + ) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + }) + } +} diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 5298009d8718e..658755958be8e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } +futures = "0.3.7" jsonrpsee = { version = "0.8", features = ["macros", "ws-client"] } log = "0.4.11" num-traits = "0.2" @@ -44,5 +45,6 @@ sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } -#[dev-dependencies] -futures = "0.3.7" +[features] +default = [] +test-helpers = [] diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 359a3f69d8a36..bc8fd8e7d3029 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -196,7 +196,7 @@ impl Environment for Client { #[cfg(test)] mod tests { use super::*; - use frame_support::weights::{IdentityFee, Weight}; + use crate::test_chain::TestChain; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, future::FutureExt, @@ -204,49 +204,6 @@ mod tests { SinkExt, }; - #[derive(Debug, Clone)] - struct TestChain; - - impl bp_runtime::Chain for TestChain { - type BlockNumber = u32; - type Hash = sp_core::H256; - type Hasher = sp_runtime::traits::BlakeTwo256; - type Header = sp_runtime::generic::Header; - - type AccountId = u32; - type Balance = u32; - type Index = u32; - type Signature = sp_runtime::testing::TestSignature; - - fn max_extrinsic_size() -> u32 { - unreachable!() - } - fn max_extrinsic_weight() -> Weight { - unreachable!() - } - } - - impl Chain for TestChain { - const NAME: &'static str = "Test"; - const TOKEN_ID: Option<&'static str> = None; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "BestTestHeader"; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1); - const STORAGE_PROOF_OVERHEAD: u32 = 0; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; - - type SignedBlock = sp_runtime::generic::SignedBlock< - sp_runtime::generic::Block, - >; - type Call = (); - type WeightToFee = IdentityFee; - } - - impl ChainWithBalances for TestChain { - fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey { - unreachable!() - } - } - struct TestEnvironment { runtime_version_rx: UnboundedReceiver, free_native_balance_rx: UnboundedReceiver, diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index b3a7ec414190f..d6cab3dd91bbc 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -26,6 +26,7 @@ mod sync_header; pub mod guard; pub mod metrics; +pub mod test_chain; use std::time::Duration; diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs new file mode 100644 index 0000000000000..c7c9983efe9b9 --- /dev/null +++ b/relays/client-substrate/src/test_chain.rs @@ -0,0 +1,71 @@ +// 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 . + +//! Pallet provides a set of guard functions that are running in background threads +//! and are aborting process if some condition fails. + +//! Test chain implementation to use in tests. + +#![cfg(any(feature = "test-helpers", test))] + +use crate::{Chain, ChainWithBalances}; +use frame_support::weights::{IdentityFee, Weight}; +use std::time::Duration; + +/// Chain that may be used in tests. +#[derive(Clone, Debug, PartialEq)] +pub struct TestChain; + +impl bp_runtime::Chain for TestChain { + type BlockNumber = u32; + type Hash = sp_core::H256; + type Hasher = sp_runtime::traits::BlakeTwo256; + type Header = sp_runtime::generic::Header; + + type AccountId = u32; + type Balance = u32; + type Index = u32; + type Signature = sp_runtime::testing::TestSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + + fn max_extrinsic_weight() -> Weight { + unreachable!() + } +} + +impl Chain for TestChain { + const NAME: &'static str = "Test"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); + const STORAGE_PROOF_OVERHEAD: u32 = 0; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; + + type SignedBlock = sp_runtime::generic::SignedBlock< + sp_runtime::generic::Block, + >; + type Call = (); + type WeightToFee = IdentityFee; +} + +impl ChainWithBalances for TestChain { + fn account_info_storage_key(_account_id: &u32) -> sp_core::storage::StorageKey { + unreachable!() + } +} diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index b8bfcc9601dd4..a1370744b144c 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -18,16 +18,20 @@ log = "0.4.14" # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } +bp-parachains = { path = "../../primitives/parachains" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-grandpa = { version = "0.15.0" } finality-relay = { path = "../finality" } +parachains-relay = { path = "../parachains" } relay-utils = { path = "../utils" } messages-relay = { path = "../messages" } relay-substrate-client = { path = "../client-substrate" } pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } +pallet-bridge-parachains = { path = "../../modules/parachains" } bp-runtime = { path = "../../primitives/runtime" } bp-messages = { path = "../../primitives/messages" } diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index bd51925f5273b..374ab915166ab 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -29,6 +29,8 @@ pub mod messages_metrics; pub mod messages_source; pub mod messages_target; pub mod on_demand_headers; +pub mod parachains_source; +pub mod parachains_target; /// Default relay loop stall timeout. If transactions generated by relay are immortal, then /// this timeout is used. diff --git a/relays/lib-substrate-relay/src/parachains_source.rs b/relays/lib-substrate-relay/src/parachains_source.rs new file mode 100644 index 0000000000000..9e8d378d8bb8a --- /dev/null +++ b/relays/lib-substrate-relay/src/parachains_source.rs @@ -0,0 +1,91 @@ +// 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 . + +//! Parachain heads source. + +use async_trait::async_trait; +use bp_parachains::parachain_head_storage_key_at_source; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use codec::Decode; +use parachains_relay::{parachains_loop::SourceClient, ParachainsPipeline}; +use relay_substrate_client::{Client, Error as SubstrateError, HeaderIdOf}; +use relay_utils::relay_loop::Client as RelayClient; + +/// Substrate client as parachain heads source. +#[derive(Clone)] +pub struct ParachainsSource { + client: Client, + paras_pallet_name: String, +} + +impl ParachainsSource

{ + /// Creates new parachains source client. + pub fn new(client: Client, paras_pallet_name: String) -> Self { + ParachainsSource { client, paras_pallet_name } + } +} + +#[async_trait] +impl RelayClient for ParachainsSource

{ + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + +#[async_trait] +impl SourceClient

for ParachainsSource

{ + async fn ensure_synced(&self) -> Result { + match self.client.ensure_synced().await { + Ok(_) => Ok(true), + Err(SubstrateError::ClientNotSynced(_)) => Ok(false), + Err(e) => Err(e), + } + } + + async fn parachain_head( + &self, + at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, Self::Error> { + let storage_key = parachain_head_storage_key_at_source(&self.paras_pallet_name, para_id); + let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?; + let para_head = para_head.map(|h| ParaHead::decode(&mut &h.0[..])).transpose()?; + let para_hash = para_head.map(|h| h.hash()); + + Ok(para_hash) + } + + async fn prove_parachain_heads( + &self, + at_block: HeaderIdOf, + parachains: &[ParaId], + ) -> Result { + let storage_keys = parachains + .iter() + .map(|para_id| parachain_head_storage_key_at_source(&self.paras_pallet_name, *para_id)) + .collect(); + let parachain_heads_proof = self + .client + .prove_storage(storage_keys, at_block.1) + .await? + .iter_nodes() + .collect(); + + Ok(parachain_heads_proof) + } +} diff --git a/relays/lib-substrate-relay/src/parachains_target.rs b/relays/lib-substrate-relay/src/parachains_target.rs new file mode 100644 index 0000000000000..ed0456c06f216 --- /dev/null +++ b/relays/lib-substrate-relay/src/parachains_target.rs @@ -0,0 +1,211 @@ +// 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 . + +//! Parachain heads target. + +use crate::TransactionParams; + +use async_trait::async_trait; +use bp_parachains::{parachain_head_storage_key_at_target, BestParaHeadHash}; +use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; +use codec::{Decode, Encode}; +use pallet_bridge_parachains::{ + Call as BridgeParachainsCall, Config as BridgeParachainsConfig, RelayBlockHash, + RelayBlockHasher, RelayBlockNumber, +}; +use parachains_relay::{parachains_loop::TargetClient, ParachainsPipeline}; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError, + HashOf, HeaderIdOf, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, +}; +use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use sp_core::{Bytes, Pair}; +use sp_runtime::traits::Header as HeaderT; +use std::marker::PhantomData; + +/// Different ways of building `submit_parachain_heads` calls. +pub trait SubmitParachainHeadsCallBuilder: 'static + Send + Sync { + /// Given parachains and their heads proof, build call of `submit_parachain_heads` + /// function of bridge parachains module at the target chain. + fn build_submit_parachain_heads_call( + relay_block_hash: HashOf, + parachains: Vec, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf; +} + +/// Building `submit_parachain_heads` call when you have direct access to the target +/// chain runtime. +pub struct DirectSubmitParachainHeadsCallBuilder { + _phantom: PhantomData<(P, R, I)>, +} + +impl SubmitParachainHeadsCallBuilder

for DirectSubmitParachainHeadsCallBuilder +where + P: ParachainsPipeline, + P::SourceChain: Chain, + R: BridgeParachainsConfig + Send + Sync, + I: 'static + Send + Sync, + R::BridgedChain: bp_runtime::Chain< + BlockNumber = RelayBlockNumber, + Hash = RelayBlockHash, + Hasher = RelayBlockHasher, + >, + CallOf: From>, +{ + fn build_submit_parachain_heads_call( + relay_block_hash: HashOf, + parachains: Vec, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + BridgeParachainsCall::::submit_parachain_heads { + relay_block_hash, + parachains, + parachain_heads_proof, + } + .into() + } +} + +/// Substrate client as parachain heads source. +pub struct ParachainsTarget { + client: Client, + transaction_params: TransactionParams>, + bridge_paras_pallet_name: String, + _phantom: PhantomData, +} + +impl ParachainsTarget { + /// Creates new parachains target client. + pub fn new( + client: Client, + transaction_params: TransactionParams>, + bridge_paras_pallet_name: String, + ) -> Self { + ParachainsTarget { + client, + transaction_params, + bridge_paras_pallet_name, + _phantom: Default::default(), + } + } +} + +impl Clone for ParachainsTarget { + fn clone(&self) -> Self { + ParachainsTarget { + client: self.client.clone(), + transaction_params: self.transaction_params.clone(), + bridge_paras_pallet_name: self.bridge_paras_pallet_name.clone(), + _phantom: Default::default(), + } + } +} + +#[async_trait] +impl< + P: ParachainsPipeline, + S: 'static + TransactionSignScheme, + CB: SubmitParachainHeadsCallBuilder

, + > RelayClient for ParachainsTarget +{ + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + +#[async_trait] +impl TargetClient

for ParachainsTarget +where + P: ParachainsPipeline, + S: 'static + TransactionSignScheme, + CB: SubmitParachainHeadsCallBuilder

, + AccountIdOf: From< as Pair>::Public>, +{ + async fn best_block(&self) -> Result, Self::Error> { + let best_header = self.client.best_header().await?; + let best_hash = best_header.hash(); + let best_id = HeaderId(*best_header.number(), best_hash); + + Ok(best_id) + } + + async fn best_finalized_source_block( + &self, + at_block: &HeaderIdOf, + ) -> Result, Self::Error> { + let encoded_best_finalized_source_block = self + .client + .state_call( + P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), + Bytes(Vec::new()), + Some(at_block.1), + ) + .await?; + let decoded_best_finalized_source_block: ( + BlockNumberOf, + HashOf, + ) = Decode::decode(&mut &encoded_best_finalized_source_block.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; + Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1)) + } + + async fn parachain_head( + &self, + at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, Self::Error> { + let storage_key = + parachain_head_storage_key_at_target(&self.bridge_paras_pallet_name, para_id); + let para_head = self.client.storage_value(storage_key, Some(at_block.1)).await?; + + Ok(para_head) + } + + async fn submit_parachain_heads_proof( + &self, + at_relay_block: HeaderIdOf, + updated_parachains: Vec, + proof: ParaHeadsProof, + ) -> Result<(), Self::Error> { + let genesis_hash = *self.client.genesis_hash(); + let transaction_params = self.transaction_params.clone(); + let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; + let call = + CB::build_submit_parachain_heads_call(at_relay_block.1, updated_parachains, proof); + self.client + .submit_signed_extrinsic( + self.transaction_params.signer.public().into(), + move |best_block_id, transaction_nonce| { + Ok(Bytes( + S::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer, + era: TransactionEra::new(best_block_id, transaction_params.mortality), + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? + .encode(), + )) + }, + ) + .await + .map(drop) + } +} diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml new file mode 100644 index 0000000000000..e5c0cea137bfa --- /dev/null +++ b/relays/parachains/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "parachains-relay" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +async-std = "1.6.5" +async-trait = "0.1.40" +backoff = "0.2" +futures = "0.3.5" +linked-hash-map = "0.5.3" +log = "0.4.11" +num-traits = "0.2" +parking_lot = "0.11.0" +relay-utils = { path = "../utils" } + +# Bridge dependencies + +bp-parachains = { path = "../../primitives/parachains" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +relay-substrate-client = { path = "../client-substrate" } + +[dev-dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0" } +relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/parachains/src/lib.rs b/relays/parachains/src/lib.rs new file mode 100644 index 0000000000000..94b3ce3ec7669 --- /dev/null +++ b/relays/parachains/src/lib.rs @@ -0,0 +1,30 @@ +// 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 . + +use std::fmt::Debug; + +use relay_substrate_client::Chain; + +pub mod parachains_loop; +pub mod parachains_loop_metrics; + +/// Finality proofs synchronization pipeline. +pub trait ParachainsPipeline: 'static + Clone + Debug + Send + Sync { + /// Relay chain which is storing parachain heads in its `paras` module. + type SourceChain: Chain; + /// Target chain (either relay or para) which wants to know about new parachain heads. + type TargetChain: Chain; +} diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs new file mode 100644 index 0000000000000..56ceb67c58d20 --- /dev/null +++ b/relays/parachains/src/parachains_loop.rs @@ -0,0 +1,1020 @@ +// 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 . + +use crate::{parachains_loop_metrics::ParachainsLoopMetrics, ParachainsPipeline}; + +use async_trait::async_trait; +use bp_parachains::BestParaHeadHash; +use bp_polkadot_core::{ + parachains::{ParaHash, ParaHeadsProof, ParaId}, + BlockNumber as RelayBlockNumber, +}; +use futures::{future::FutureExt, select}; +use relay_substrate_client::{BlockNumberOf, Chain, HeaderIdOf}; +use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient}; +use std::{ + collections::{BTreeMap, BTreeSet}, + future::Future, + time::{Duration, Instant}, +}; + +/// Parachain heads synchronization params. +#[derive(Clone, Debug)] +pub struct ParachainSyncParams { + /// Parachains that we're relaying here. + pub parachains: Vec, + /// Parachain heads update strategy. + pub strategy: ParachainSyncStrategy, + /// Stall timeout. If we have submitted transaction and we see no state updates for this + /// period, we consider our transaction lost. + pub stall_timeout: Duration, +} + +/// Parachain heads update strategy. +#[derive(Clone, Copy, Debug)] +pub enum ParachainSyncStrategy { + /// Update whenever any parachain head is updated. + Any, + /// Wait till all parachain heads are updated. + All, +} + +/// Source client used in parachain heads synchronization loop. +#[async_trait] +pub trait SourceClient: RelayClient { + /// Returns `Ok(true)` if client is in synced state. + async fn ensure_synced(&self) -> Result; + + /// Get parachain head hash at given block. + async fn parachain_head( + &self, + at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, Self::Error>; + + /// Get parachain heads proof. + async fn prove_parachain_heads( + &self, + at_block: HeaderIdOf, + parachains: &[ParaId], + ) -> Result; +} + +/// Target client used in parachain heads synchronization loop. +#[async_trait] +pub trait TargetClient: RelayClient { + /// Get best block id. + async fn best_block(&self) -> Result, Self::Error>; + + /// Get best finalized source block id. + async fn best_finalized_source_block( + &self, + at_block: &HeaderIdOf, + ) -> Result, Self::Error>; + + /// Get parachain head hash at given block. + async fn parachain_head( + &self, + at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, Self::Error>; + + /// Submit parachain heads proof. + async fn submit_parachain_heads_proof( + &self, + at_source_block: HeaderIdOf, + updated_parachains: Vec, + proof: ParaHeadsProof, + ) -> Result<(), Self::Error>; +} + +/// Return prefix that will be used by default to expose Prometheus metrics of the parachains +/// sync loop. +pub fn metrics_prefix() -> String { + format!("{}_to_{}_Sync", P::SourceChain::NAME, P::TargetChain::NAME) +} + +/// Run parachain heads synchronization. +pub async fn run( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + sync_params: ParachainSyncParams, + metrics_params: MetricsParams, + exit_signal: impl Future + 'static + Send, +) -> Result<(), relay_utils::Error> +where + P::SourceChain: Chain, +{ + let exit_signal = exit_signal.shared(); + relay_utils::relay_loop(source_client, target_client) + .with_metrics(metrics_params) + .loop_metric(ParachainsLoopMetrics::new(Some(&metrics_prefix::

()))?)? + .expose() + .await? + .run(metrics_prefix::

(), move |source_client, target_client, metrics| { + run_until_connection_lost( + source_client, + target_client, + sync_params.clone(), + metrics, + exit_signal.clone(), + ) + }) + .await +} + +/// Run parachain heads synchronization. +async fn run_until_connection_lost( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + sync_params: ParachainSyncParams, + _metrics: Option, + exit_signal: impl Future + Send, +) -> Result<(), FailedClient> +where + P::SourceChain: Chain, +{ + let exit_signal = exit_signal.fuse(); + let min_block_interval = std::cmp::min( + P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + ); + + let mut tx_tracker: Option> = None; + + futures::pin_mut!(exit_signal); + + // Note that the internal loop breaks with `FailedClient` error even if error is non-connection. + // It is Ok for now, but it may need to be fixed in the future to use exponential backoff for + // regular errors. + + loop { + // either wait for new block, or exit signal + select! { + _ = async_std::task::sleep(min_block_interval).fuse() => {}, + _ = exit_signal => return Ok(()), + } + + // if source client is not yet synced, we'll need to sleep. Otherwise we risk submitting too + // much redundant transactions + match source_client.ensure_synced().await { + Ok(true) => (), + Ok(false) => { + log::warn!( + target: "bridge", + "{} client is syncing. Won't do anything until it is synced", + P::SourceChain::NAME, + ); + continue + }, + Err(e) => { + log::warn!( + target: "bridge", + "{} client has failed to return its sync status: {:?}", + P::SourceChain::NAME, + e, + ); + return Err(FailedClient::Target) + }, + } + + // if we have active transaction, we'll need to wait until it is mined or dropped + let best_target_block = target_client.best_block().await.map_err(|e| { + log::warn!(target: "bridge", "Failed to read best {} block: {:?}", P::SourceChain::NAME, e); + FailedClient::Target + })?; + let heads_at_target = + read_heads_at_target(&target_client, &best_target_block, &sync_params.parachains) + .await?; + tx_tracker = tx_tracker.take().and_then(|tx_tracker| tx_tracker.update(&heads_at_target)); + if tx_tracker.is_some() { + continue + } + + // we have no active transaction and may need to update heads, but do we have something for + // update? + let best_finalized_relay_block = target_client + .best_finalized_source_block(&best_target_block) + .await + .map_err(|e| { + log::warn!( + target: "bridge", + "Failed to read best finalized {} block from {}: {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + e, + ); + FailedClient::Target + })?; + let heads_at_source = read_heads_at_source( + &source_client, + &best_finalized_relay_block, + &sync_params.parachains, + ) + .await?; + let updated_ids = select_parachains_to_update::

( + heads_at_source, + heads_at_target, + best_finalized_relay_block, + ); + let is_update_required = is_update_required(&sync_params, &updated_ids); + + log::info!( + target: "bridge", + "Total {} parachains: {}. Up-to-date at {}: {}. Needs update at {}: {}.", + P::SourceChain::NAME, + sync_params.parachains.len(), + P::TargetChain::NAME, + sync_params.parachains.len() - updated_ids.len(), + P::TargetChain::NAME, + updated_ids.len(), + ); + + if is_update_required { + let heads_proofs = source_client + .prove_parachain_heads(best_finalized_relay_block, &updated_ids) + .await + .map_err(|e| { + log::warn!( + target: "bridge", + "Failed to prove {} parachain heads: {:?}", + P::SourceChain::NAME, + e, + ); + FailedClient::Source + })?; + log::info!( + target: "bridge", + "Submitting {} parachain heads update transaction to {}", + P::SourceChain::NAME, + P::TargetChain::NAME, + ); + target_client + .submit_parachain_heads_proof( + best_finalized_relay_block, + updated_ids.clone(), + heads_proofs, + ) + .await + .map_err(|e| { + log::warn!( + target: "bridge", + "Failed to submit {} parachain heads proof to {}: {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + e, + ); + FailedClient::Target + })?; + + tx_tracker = Some(TransactionTracker::

::new( + updated_ids, + best_finalized_relay_block.0, + sync_params.stall_timeout, + )); + } + } +} + +/// Given heads at source and target clients, returns set of heads that are out of sync. +fn select_parachains_to_update( + heads_at_source: BTreeMap>, + heads_at_target: BTreeMap>, + best_finalized_relay_block: HeaderIdOf, +) -> Vec +where + P::SourceChain: Chain, +{ + heads_at_source + .into_iter() + .zip(heads_at_target.into_iter()) + .filter(|((para, head_at_source), (_, head_at_target))| { + let needs_update = match (head_at_source, head_at_target) { + (Some(head_at_source), Some(head_at_target)) + if head_at_target.at_relay_block_number < best_finalized_relay_block.0 && + head_at_target.head_hash != *head_at_source => + { + // source client knows head that is better than the head known to the target + // client + true + }, + (Some(_), Some(_)) => { + // this is normal case when relay has recently updated heads, when parachain is + // not progressing or when our source client is + false + }, + (Some(_), None) => { + // parachain is not yet known to the target client. This is true when parachain + // or bridge has been just onboarded/started + true + }, + (None, Some(_)) => { + // parachain/parathread has been offboarded removed from the system. It needs to + // be propageted to the target client + true + }, + (None, None) => { + // all's good - parachain is unknown to both clients + false + }, + }; + if needs_update { + log::trace!( + target: "bridge", + "{} parachain {:?} needs update at {}: {:?} vs {:?}", + P::SourceChain::NAME, + para, + P::TargetChain::NAME, + head_at_source, + head_at_target, + ); + } + + needs_update + }) + .map(|((para_id, _), _)| para_id) + .collect() +} + +/// Returns true if we need to submit update transactions to the target node. +fn is_update_required(sync_params: &ParachainSyncParams, updated_ids: &[ParaId]) -> bool { + match sync_params.strategy { + ParachainSyncStrategy::All => updated_ids.len() == sync_params.parachains.len(), + ParachainSyncStrategy::Any => !updated_ids.is_empty(), + } +} + +/// Reads given parachains heads from the source client. +/// +/// Guarantees that the returning map will have an entry for every parachain from `parachains`. +async fn read_heads_at_source( + source_client: &impl SourceClient

, + at_relay_block: &HeaderIdOf, + parachains: &[ParaId], +) -> Result>, FailedClient> { + let mut para_head_hashes = BTreeMap::new(); + for para in parachains { + let para_head = source_client.parachain_head(*at_relay_block, *para).await; + match para_head { + Ok(para_head) => { + para_head_hashes.insert(*para, para_head); + }, + Err(e) => { + log::warn!( + target: "bridge", + "Failed to read head of {} parachain {:?}: {:?}", + P::SourceChain::NAME, + para, + e, + ); + return Err(FailedClient::Source) + }, + } + } + Ok(para_head_hashes) +} + +/// Reads given parachains heads from the source client. +/// +/// Guarantees that the returning map will have an entry for every parachain from `parachains`. +async fn read_heads_at_target( + target_client: &impl TargetClient

, + at_block: &HeaderIdOf, + parachains: &[ParaId], +) -> Result>, FailedClient> { + let mut para_best_head_hashes = BTreeMap::new(); + for para in parachains { + let para_best_head = target_client.parachain_head(*at_block, *para).await; + match para_best_head { + Ok(para_best_head) => { + para_best_head_hashes.insert(*para, para_best_head); + }, + Err(e) => { + log::warn!( + target: "bridge", + "Failed to read head of {} parachain {:?} at {}: {:?}", + P::SourceChain::NAME, + para, + P::TargetChain::NAME, + e, + ); + return Err(FailedClient::Target) + }, + } + } + Ok(para_best_head_hashes) +} + +/// Parachain heads transaction tracker. +struct TransactionTracker { + /// Ids of parachains which heads were updated in the tracked transaction. + awaiting_update: BTreeSet, + /// Number of relay chain block that has been used to craft parachain heads proof. + relay_block_number: BlockNumberOf, + /// Transaction submit time. + submitted_at: Instant, + /// Transaction death time. + death_time: Instant, +} + +impl TransactionTracker

+where + P::SourceChain: Chain, +{ + /// Creates new parachain heads transaction tracker. + pub fn new( + awaiting_update: impl IntoIterator, + relay_block_number: BlockNumberOf, + stall_timeout: Duration, + ) -> Self { + let now = Instant::now(); + TransactionTracker { + awaiting_update: awaiting_update.into_iter().collect(), + relay_block_number, + submitted_at: now, + death_time: now + stall_timeout, + } + } + + /// Returns `None` if all parachain heads have been updated or we consider our transaction dead. + pub fn update( + mut self, + heads_at_target: &BTreeMap>, + ) -> Option { + // remove all pending heads that were synced + for (para, best_para_head) in heads_at_target { + if best_para_head + .as_ref() + .map(|best_para_head| { + best_para_head.at_relay_block_number >= self.relay_block_number + }) + .unwrap_or(false) + { + self.awaiting_update.remove(para); + + log::trace!( + target: "bridge", + "Head of parachain {:?} has been updated at {}: {:?}. Outdated parachains remaining: {}", + para, + P::TargetChain::NAME, + best_para_head, + self.awaiting_update.len(), + ); + } + } + + // if we have synced all required heads, we are done + if self.awaiting_update.is_empty() { + return None + } + + // if our transaction is dead now, we may start over again + let now = Instant::now(); + if now >= self.death_time { + log::warn!( + target: "bridge", + "Parachain heads update transaction {} has been lost: no updates for {}s", + P::TargetChain::NAME, + (now - self.submitted_at).as_secs(), + ); + + return None + } + + Some(self) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use async_std::sync::{Arc, Mutex}; + use codec::Encode; + use futures::{SinkExt, StreamExt}; + use relay_substrate_client::test_chain::TestChain; + use relay_utils::{HeaderId, MaybeConnectionError}; + use sp_core::H256; + + const PARA_ID: u32 = 0; + const PARA_0_HASH: ParaHash = H256([1u8; 32]); + const PARA_1_HASH: ParaHash = H256([2u8; 32]); + + #[derive(Clone, Debug)] + enum TestError { + Error, + MissingParachainHeadProof, + } + + impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + false + } + } + + #[derive(Clone, Debug, PartialEq)] + struct TestParachainsPipeline; + + impl ParachainsPipeline for TestParachainsPipeline { + type SourceChain = TestChain; + type TargetChain = TestChain; + } + + #[derive(Clone, Debug)] + struct TestClient { + data: Arc>, + } + + #[derive(Clone, Debug)] + struct TestClientData { + source_sync_status: Result, + source_heads: BTreeMap>, + source_proofs: BTreeMap, TestError>>, + + target_best_block: Result, TestError>, + target_best_finalized_source_block: Result, TestError>, + target_heads: BTreeMap>, + target_submit_result: Result<(), TestError>, + + exit_signal_sender: Option>>, + } + + impl TestClientData { + pub fn minimal() -> Self { + TestClientData { + source_sync_status: Ok(true), + source_heads: vec![(PARA_ID, Ok(PARA_0_HASH))].into_iter().collect(), + source_proofs: vec![(PARA_ID, Ok(PARA_0_HASH.encode()))].into_iter().collect(), + + target_best_block: Ok(HeaderId(0, Default::default())), + target_best_finalized_source_block: Ok(HeaderId(0, Default::default())), + target_heads: BTreeMap::new(), + target_submit_result: Ok(()), + + exit_signal_sender: None, + } + } + + pub fn with_exit_signal_sender( + sender: futures::channel::mpsc::UnboundedSender<()>, + ) -> Self { + let mut client = Self::minimal(); + client.exit_signal_sender = Some(Box::new(sender)); + client + } + } + + impl From for TestClient { + fn from(data: TestClientData) -> TestClient { + TestClient { data: Arc::new(Mutex::new(data)) } + } + } + + #[async_trait] + impl RelayClient for TestClient { + type Error = TestError; + + async fn reconnect(&mut self) -> Result<(), TestError> { + unimplemented!() + } + } + + #[async_trait] + impl SourceClient for TestClient { + async fn ensure_synced(&self) -> Result { + self.data.lock().await.source_sync_status.clone() + } + + async fn parachain_head( + &self, + _at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, TestError> { + self.data.lock().await.source_heads.get(¶_id.0).cloned().transpose() + } + + async fn prove_parachain_heads( + &self, + _at_block: HeaderIdOf, + parachains: &[ParaId], + ) -> Result { + let mut proofs = Vec::new(); + for para_id in parachains { + proofs.push( + self.data + .lock() + .await + .source_proofs + .get(¶_id.0) + .cloned() + .transpose()? + .ok_or(TestError::MissingParachainHeadProof)?, + ); + } + Ok(proofs) + } + } + + #[async_trait] + impl TargetClient for TestClient { + async fn best_block(&self) -> Result, TestError> { + self.data.lock().await.target_best_block.clone() + } + + async fn best_finalized_source_block( + &self, + _at_block: &HeaderIdOf, + ) -> Result, TestError> { + self.data.lock().await.target_best_finalized_source_block.clone() + } + + async fn parachain_head( + &self, + _at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, TestError> { + self.data.lock().await.target_heads.get(¶_id.0).cloned().transpose() + } + + async fn submit_parachain_heads_proof( + &self, + _at_source_block: HeaderIdOf, + _updated_parachains: Vec, + _proof: ParaHeadsProof, + ) -> Result<(), Self::Error> { + self.data.lock().await.target_submit_result.clone()?; + + if let Some(mut exit_signal_sender) = self.data.lock().await.exit_signal_sender.take() { + exit_signal_sender.send(()).await.unwrap(); + } + Ok(()) + } + } + + fn default_sync_params() -> ParachainSyncParams { + ParachainSyncParams { + parachains: vec![ParaId(PARA_ID)], + strategy: ParachainSyncStrategy::Any, + stall_timeout: Duration::from_secs(60), + } + } + + #[test] + fn when_source_client_fails_to_return_sync_state() { + let mut test_source_client = TestClientData::minimal(); + test_source_client.source_sync_status = Err(TestError::Error); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(test_source_client), + TestClient::from(TestClientData::minimal()), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Target), + ); + } + + #[test] + fn when_target_client_fails_to_return_best_block() { + let mut test_target_client = TestClientData::minimal(); + test_target_client.target_best_block = Err(TestError::Error); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(TestClientData::minimal()), + TestClient::from(test_target_client), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Target), + ); + } + + #[test] + fn when_target_client_fails_to_read_heads() { + let mut test_target_client = TestClientData::minimal(); + test_target_client.target_heads.insert(PARA_ID, Err(TestError::Error)); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(TestClientData::minimal()), + TestClient::from(test_target_client), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Target), + ); + } + + #[test] + fn when_target_client_fails_to_read_best_finalized_source_block() { + let mut test_target_client = TestClientData::minimal(); + test_target_client.target_best_finalized_source_block = Err(TestError::Error); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(TestClientData::minimal()), + TestClient::from(test_target_client), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Target), + ); + } + + #[test] + fn when_source_client_fails_to_read_heads() { + let mut test_source_client = TestClientData::minimal(); + test_source_client.source_heads.insert(PARA_ID, Err(TestError::Error)); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(test_source_client), + TestClient::from(TestClientData::minimal()), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Source), + ); + } + + #[test] + fn when_source_client_fails_to_prove_heads() { + let mut test_source_client = TestClientData::minimal(); + test_source_client.source_proofs.insert(PARA_ID, Err(TestError::Error)); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(test_source_client), + TestClient::from(TestClientData::minimal()), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Source), + ); + } + + #[test] + fn when_target_client_rejects_update_transaction() { + let mut test_target_client = TestClientData::minimal(); + test_target_client.target_submit_result = Err(TestError::Error); + + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(TestClientData::minimal()), + TestClient::from(test_target_client), + default_sync_params(), + None, + futures::future::pending(), + )), + Err(FailedClient::Target), + ); + } + + #[test] + fn minimal_working_case() { + let (exit_signal_sender, exit_signal) = futures::channel::mpsc::unbounded(); + assert_eq!( + async_std::task::block_on(run_until_connection_lost( + TestClient::from(TestClientData::minimal()), + TestClient::from(TestClientData::with_exit_signal_sender(exit_signal_sender)), + default_sync_params(), + None, + exit_signal.into_future().map(|(_, _)| ()), + )), + Ok(()), + ); + } + + const PARA_1_ID: u32 = PARA_ID + 1; + const SOURCE_BLOCK_NUMBER: u32 = 100; + + fn test_tx_tracker() -> TransactionTracker { + TransactionTracker::new( + vec![ParaId(PARA_ID), ParaId(PARA_1_ID)], + SOURCE_BLOCK_NUMBER, + Duration::from_secs(1), + ) + } + + #[test] + fn tx_tracker_update_when_nothing_is_updated() { + assert_eq!( + test_tx_tracker() + .update(&vec![].into_iter().collect()) + .map(|t| t.awaiting_update), + Some(test_tx_tracker().awaiting_update), + ); + } + + #[test] + fn tx_tracker_update_when_one_of_heads_is_updated_to_previous_value() { + assert_eq!( + test_tx_tracker() + .update( + &vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { + at_relay_block_number: SOURCE_BLOCK_NUMBER - 1, + head_hash: PARA_0_HASH, + }) + )] + .into_iter() + .collect() + ) + .map(|t| t.awaiting_update), + Some(test_tx_tracker().awaiting_update), + ); + } + + #[test] + fn tx_tracker_update_when_one_of_heads_is_updated() { + assert_eq!( + test_tx_tracker() + .update( + &vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { + at_relay_block_number: SOURCE_BLOCK_NUMBER, + head_hash: PARA_0_HASH, + }) + )] + .into_iter() + .collect() + ) + .map(|t| t.awaiting_update), + Some(vec![ParaId(PARA_1_ID)].into_iter().collect()), + ); + } + + #[test] + fn tx_tracker_update_when_all_heads_are_updated() { + assert_eq!( + test_tx_tracker() + .update( + &vec![ + ( + ParaId(PARA_ID), + Some(BestParaHeadHash { + at_relay_block_number: SOURCE_BLOCK_NUMBER, + head_hash: PARA_0_HASH, + }) + ), + ( + ParaId(PARA_1_ID), + Some(BestParaHeadHash { + at_relay_block_number: SOURCE_BLOCK_NUMBER, + head_hash: PARA_0_HASH, + }) + ), + ] + .into_iter() + .collect() + ) + .map(|t| t.awaiting_update), + None, + ); + } + + #[test] + fn tx_tracker_update_when_tx_is_stalled() { + let mut tx_tracker = test_tx_tracker(); + tx_tracker.death_time = Instant::now(); + assert_eq!( + tx_tracker.update(&vec![].into_iter().collect()).map(|t| t.awaiting_update), + None, + ); + } + + #[test] + fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), None)].into_iter().collect(), + vec![(ParaId(PARA_ID), None)].into_iter().collect(), + HeaderId(10, Default::default()), + ), + Vec::::new(), + ); + } + + #[test] + fn parachain_is_not_updated_if_it_has_been_updated_at_better_relay_block() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), Some(PARA_0_HASH))].into_iter().collect(), + vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { at_relay_block_number: 20, head_hash: PARA_1_HASH }) + )] + .into_iter() + .collect(), + HeaderId(10, Default::default()), + ), + Vec::::new(), + ); + } + + #[test] + fn parachain_is_not_updated_if_hash_is_the_same_at_next_relay_block() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), Some(PARA_0_HASH))].into_iter().collect(), + vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) + )] + .into_iter() + .collect(), + HeaderId(10, Default::default()), + ), + Vec::::new(), + ); + } + + #[test] + fn parachain_is_updated_after_offboarding() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), None)].into_iter().collect(), + vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { + at_relay_block_number: 0, + head_hash: Default::default(), + }) + )] + .into_iter() + .collect(), + HeaderId(10, Default::default()), + ), + vec![ParaId(PARA_ID)], + ); + } + + #[test] + fn parachain_is_updated_after_onboarding() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), Some(PARA_0_HASH))].into_iter().collect(), + vec![(ParaId(PARA_ID), None)].into_iter().collect(), + HeaderId(10, Default::default()), + ), + vec![ParaId(PARA_ID)], + ); + } + + #[test] + fn parachain_is_updated_if_newer_head_is_known() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), Some(PARA_1_HASH))].into_iter().collect(), + vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) + )] + .into_iter() + .collect(), + HeaderId(10, Default::default()), + ), + vec![ParaId(PARA_ID)], + ); + } + + #[test] + fn is_update_required_works() { + let mut sync_params = ParachainSyncParams { + parachains: vec![ParaId(PARA_ID), ParaId(PARA_1_ID)], + strategy: ParachainSyncStrategy::Any, + stall_timeout: Duration::from_secs(60), + }; + + assert_eq!(is_update_required(&sync_params, &[]), false); + assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID)]), true); + assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)]), true); + + sync_params.strategy = ParachainSyncStrategy::All; + assert_eq!(is_update_required(&sync_params, &[]), false); + assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID)]), false); + assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)]), true); + } +} diff --git a/relays/parachains/src/parachains_loop_metrics.rs b/relays/parachains/src/parachains_loop_metrics.rs new file mode 100644 index 0000000000000..a0a99f5c332ab --- /dev/null +++ b/relays/parachains/src/parachains_loop_metrics.rs @@ -0,0 +1,34 @@ +// 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 . + +use relay_utils::metrics::{Metric, PrometheusError, Registry}; + +/// Parachains sync metrics. +#[derive(Clone)] +pub struct ParachainsLoopMetrics; + +impl ParachainsLoopMetrics { + /// Create and register parachains loop metrics. + pub fn new(_prefix: Option<&str>) -> Result { + Ok(ParachainsLoopMetrics) + } +} + +impl Metric for ParachainsLoopMetrics { + fn register(&self, _registry: &Registry) -> Result<(), PrometheusError> { + Ok(()) + } +} From a57bf53e521dda22cf6396f6c12676e086d3c3de Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 20 May 2022 12:03:45 +0300 Subject: [PATCH 0689/1210] messages bridge between RialtoParachain and Millau (#1218) --- bin/millau/node/src/chain_spec.rs | 12 +- bin/millau/runtime/Cargo.toml | 4 + bin/millau/runtime/src/lib.rs | 101 +++++- .../runtime/src/rialto_parachain_messages.rs | 304 ++++++++++++++++++ bin/rialto-parachain/node/Cargo.toml | 5 + bin/rialto-parachain/node/src/chain_spec.rs | 9 + bin/rialto-parachain/runtime/Cargo.toml | 12 + bin/rialto-parachain/runtime/src/lib.rs | 135 +++++++- .../runtime/src/millau_messages.rs | 304 ++++++++++++++++++ bin/rialto/runtime/src/lib.rs | 2 +- bin/runtime-common/Cargo.toml | 4 + bin/runtime-common/src/messages.rs | 132 +++++++- modules/parachains/src/lib.rs | 74 +++-- primitives/chain-millau/src/lib.rs | 15 + primitives/chain-rialto-parachain/src/lib.rs | 158 ++++++++- primitives/chain-rialto/src/lib.rs | 2 +- primitives/polkadot-core/src/parachains.rs | 9 + primitives/runtime/src/lib.rs | 3 + relays/bin-substrate/Cargo.toml | 1 + .../millau_headers_to_rialto_parachain.rs | 57 ++++ .../millau_messages_to_rialto_parachain.rs | 62 ++++ relays/bin-substrate/src/chains/mod.rs | 3 + .../src/chains/rialto_parachain.rs | 34 +- .../rialto_parachain_messages_to_millau.rs | 62 ++++ .../src/chains/rialto_parachains_to_millau.rs | 8 +- relays/bin-substrate/src/cli/bridge.rs | 44 +++ relays/bin-substrate/src/cli/init_bridge.rs | 23 ++ relays/bin-substrate/src/cli/relay_headers.rs | 9 + .../src/cli/relay_headers_and_messages.rs | 1 - .../bin-substrate/src/cli/relay_parachains.rs | 4 +- relays/client-rialto-parachain/Cargo.toml | 6 +- relays/client-rialto-parachain/src/lib.rs | 120 ++++++- relays/parachains/src/parachains_loop.rs | 14 + 33 files changed, 1658 insertions(+), 75 deletions(-) create mode 100644 bin/millau/runtime/src/rialto_parachain_messages.rs create mode 100644 bin/rialto-parachain/runtime/src/millau_messages.rs create mode 100644 relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs create mode 100644 relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs create mode 100644 relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index ed7ee2440a898..ae5f01bbb5904 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -18,8 +18,8 @@ use beefy_primitives::crypto::AuthorityId as BeefyId; use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, - BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, - Signature, SudoConfig, SystemConfig, WASM_BINARY, + BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, + SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; @@ -151,7 +151,7 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("RialtoMessagesOwner"), - get_account_id_from_seed::("WithRialtoTokenSwap"), + get_account_id_from_seed::("RialtoParachainMessagesOwner"), pallet_bridge_messages::relayer_fund_account_id::< bp_millau::AccountId, bp_millau::AccountIdConverter, @@ -217,6 +217,12 @@ fn testnet_genesis( owner: Some(get_account_id_from_seed::("RialtoMessagesOwner")), ..Default::default() }, + bridge_rialto_parachain_messages: BridgeRialtoParachainMessagesConfig { + owner: Some(get_account_id_from_seed::( + "RialtoParachainMessagesOwner", + )), + ..Default::default() + }, xcm_pallet: Default::default(), } } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 97c6878eb8437..9e8f50a38ef7e 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -20,7 +20,9 @@ serde = { version = "1.0", optional = true, features = ["derive"] } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } +bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-westend = { path = "../../../primitives/chain-westend", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } @@ -87,7 +89,9 @@ std = [ "bp-header-chain/std", "bp-messages/std", "bp-millau/std", + "bp-polkadot-core/std", "bp-rialto/std", + "bp-rialto-parachain/std", "bp-runtime/std", "bp-westend/std", "bridge-runtime-common/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 6f38f7a54ed54..23cf4d0b05b4e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -29,14 +29,21 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto_messages; +pub mod rialto_parachain_messages; pub mod xcm_config; -use crate::rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}; +use crate::{ + rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}, + rialto_parachain_messages::{ + ToRialtoParachainMessagePayload, WithRialtoParachainMessageBridge, + }, +}; use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bridge_runtime_common::messages::{ source::estimate_message_dispatch_and_delivery_fee, MessageBridge, }; +use codec::Decode; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; @@ -49,7 +56,9 @@ use sp_mmr_primitives::{ }; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, + traits::{ + Block as BlockT, Header as HeaderT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys, + }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, }; @@ -416,6 +425,15 @@ impl pallet_bridge_grandpa::Config for Runtime { type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } +pub type RialtoParachainGrandpaInstance = pallet_bridge_grandpa::Instance2; +impl pallet_bridge_grandpa::Config for Runtime { + type BridgedChain = bp_rialto_parachain::RialtoParachain; + type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; + + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; +} + impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { @@ -429,6 +447,7 @@ parameter_types! { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; + pub const RialtoParachainChainId: bp_runtime::ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; } /// Instance of the messages pallet used to relay messages to/from Rialto chain. @@ -462,6 +481,37 @@ impl pallet_bridge_messages::Config for Runtime { type BridgedChainId = RialtoChainId; } +/// Instance of the messages pallet used to relay messages to/from RialtoParachain chain. +pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1; + +impl pallet_bridge_messages::Config for Runtime { + type Event = Event; + type WeightInfo = pallet_bridge_messages::weights::MillauWeight; + type Parameter = rialto_parachain_messages::MillauToRialtoParachainMessagesParameter; + type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + + type OutboundPayload = crate::rialto_parachain_messages::ToRialtoParachainMessagePayload; + type OutboundMessageFee = Balance; + + type InboundPayload = crate::rialto_parachain_messages::FromRialtoParachainMessagePayload; + type InboundMessageFee = bp_rialto_parachain::Balance; + type InboundRelayer = bp_rialto_parachain::AccountId; + + type AccountIdConverter = bp_millau::AccountIdConverter; + + type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; + type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; + type MessageDeliveryAndDispatchPayment = (); + type OnMessageAccepted = (); + type OnDeliveryConfirmed = (); + + type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; + type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; + type BridgedChainId = RialtoParachainChainId; +} + parameter_types! { pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; } @@ -509,8 +559,9 @@ construct_runtime!( // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, - // Rialto parachains bridge modules. + // RialtoParachain bridge modules. BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage}, + BridgeRialtoParachainMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config}, // Pallet for sending XCM. XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, @@ -750,6 +801,23 @@ impl_runtime_apis! { } } + impl bp_rialto_parachain::RialtoParachainFinalityApi for Runtime { + fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { + // the parachains finality pallet is never decoding parachain heads, so it is + // only done in the integration code + use crate::rialto_parachain_messages::RIALTO_PARACHAIN_ID; + let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::< + Runtime, + WitRialtoParachainsInstance, + >::best_parachain_head(RIALTO_PARACHAIN_ID.into()) + .and_then(|encoded_header| bp_rialto_parachain::Header::decode(&mut &encoded_header.0[..]).ok()); + match best_rialto_parachain_head { + Some(head) => (*head.number(), head.hash()), + None => (Default::default(), Default::default()), + } + } + } + impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, @@ -777,6 +845,33 @@ impl_runtime_apis! { } } + impl bp_rialto_parachain::ToRialtoParachainOutboundLaneApi for Runtime { + fn estimate_message_delivery_and_dispatch_fee( + _lane_id: bp_messages::LaneId, + payload: ToRialtoParachainMessagePayload, + rialto_parachain_to_this_conversion_rate: Option, + ) -> Option { + estimate_message_dispatch_and_delivery_fee::( + &payload, + WithRialtoParachainMessageBridge::RELAYER_FEE_PERCENT, + rialto_parachain_to_this_conversion_rate, + ).ok() + } + + fn message_details( + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec> { + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithRialtoParachainMessagesInstance, + WithRialtoParachainMessageBridge, + xcm_config::OutboundXcmWeigher, + >(lane, begin, end) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs new file mode 100644 index 0000000000000..c4d8f2c10ce56 --- /dev/null +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -0,0 +1,304 @@ +// 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 . + +//! Everything required to serve Millau <-> RialtoParachain messages. + +use crate::Runtime; + +use bp_messages::{ + source_chain::{SenderOrigin, TargetHeaderChain}, + target_chain::{ProvedMessages, SourceHeaderChain}, + InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, +}; +use bp_polkadot_core::parachains::ParaId; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; +use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; +use codec::{Decode, Encode}; +use frame_support::{ + parameter_types, + weights::{DispatchClass, Weight}, + RuntimeDebug, +}; +use scale_info::TypeInfo; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; +use sp_std::convert::TryFrom; + +/// Identifier of RialtoParachain in the Rialto relay chain. +/// +/// This identifier is not something that is declared either by Rialto or RialtoParachain. This +/// is an identifier of registration. So in theory it may be changed. But since bridge is going +/// to be deployed after parachain registration AND since parachain de-registration is highly +/// likely impossible, it is fine to declare this constant here. +pub const RIALTO_PARACHAIN_ID: u32 = 2000; +/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge +/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual +/// tests, confirming that we don't break encoding somewhere between. +pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT; + +/// Initial value of `RialtoParachainToMillauConversionRate` parameter. +pub const INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE: FixedU128 = + FixedU128::from_inner(FixedU128::DIV); +/// Initial value of `RialtoParachainFeeMultiplier` parameter. +pub const INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER: FixedU128 = + FixedU128::from_inner(FixedU128::DIV); + +parameter_types! { + /// RialtoParachain to Millau conversion rate. Initially we treat both tokens as equal. + pub storage RialtoParachainToMillauConversionRate: FixedU128 = INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE; + /// Fee multiplier value at RialtoParachain chain. + pub storage RialtoParachainFeeMultiplier: FixedU128 = INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER; +} + +/// Message payload for Millau -> RialtoParachain messages. +pub type ToRialtoParachainMessagePayload = messages::source::FromThisChainMessagePayload; + +/// Message verifier for Millau -> RialtoParachain messages. +pub type ToRialtoParachainMessageVerifier = + messages::source::FromThisChainMessageVerifier; + +/// Message payload for RialtoParachain -> Millau messages. +pub type FromRialtoParachainMessagePayload = + messages::target::FromBridgedChainMessagePayload; + +/// Messages proof for RialtoParachain -> Millau messages. +type FromRialtoParachainMessagesProof = + messages::target::FromBridgedChainMessagesProof; + +/// Messages delivery proof for Millau -> RialtoParachain messages. +type ToRialtoParachainMessagesDeliveryProof = + messages::source::FromBridgedChainMessagesDeliveryProof; + +/// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. +pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChainMessageDispatch< + WithRialtoParachainMessageBridge, + xcm_executor::XcmExecutor, + crate::xcm_config::XcmWeigher, + // 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + // (it is prepended with `UniversalOrigin` instruction) + frame_support::traits::ConstU64, +>; + +/// Millau <-> RialtoParachain message bridge. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct WithRialtoParachainMessageBridge; + +impl MessageBridge for WithRialtoParachainMessageBridge { + const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; + const BRIDGED_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; + + type ThisChain = Millau; + type BridgedChain = RialtoParachain; + + fn bridged_balance_to_this_balance( + bridged_balance: bp_rialto_parachain::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_millau::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| RialtoParachainToMillauConversionRate::get()); + bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_millau::Balance::MAX) + } +} + +/// Millau chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Millau; + +impl messages::ChainWithMessages for Millau { + type Hash = bp_millau::Hash; + type AccountId = bp_millau::AccountId; + type Signer = bp_millau::AccountSigner; + type Signature = bp_millau::Signature; + type Weight = Weight; + type Balance = bp_millau::Balance; +} + +impl messages::ThisChainWithMessages for Millau { + type Call = crate::Call; + type Origin = crate::Origin; + + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) && send_origin.linked_account().is_some() + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + MessageNonce::MAX + } + + fn estimate_delivery_confirmation_transaction() -> MessageTransaction { + let inbound_data_size = InboundLaneData::::encoded_size_hint( + bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + 1, + 1, + ) + .unwrap_or(u32::MAX); + + MessageTransaction { + dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + size: inbound_data_size + .saturating_add(bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_millau::TX_EXTRA_BYTES), + } + } + + fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { + // `transaction` may represent transaction from the future, when multiplier value will + // be larger, so let's use slightly increased value + let multiplier = FixedU128::saturating_from_rational(110, 100) + .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + 1, + multiplier, + |weight| weight as _, + transaction, + ) + } +} + +/// RialtoParachain chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct RialtoParachain; + +impl messages::ChainWithMessages for RialtoParachain { + type Hash = bp_rialto_parachain::Hash; + type AccountId = bp_rialto_parachain::AccountId; + type Signer = bp_rialto_parachain::AccountSigner; + type Signature = bp_rialto_parachain::Signature; + type Weight = Weight; + type Balance = bp_rialto_parachain::Balance; +} + +impl messages::BridgedChainWithMessages for RialtoParachain { + fn maximal_extrinsic_size() -> u32 { + bp_rialto_parachain::RialtoParachain::max_extrinsic_size() + } + + fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { + true + } + + fn estimate_delivery_transaction( + message_payload: &[u8], + include_pay_dispatch_fee_cost: bool, + message_dispatch_weight: Weight, + ) -> MessageTransaction { + let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); + let extra_bytes_in_payload = Weight::from(message_payload_len) + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + + MessageTransaction { + dispatch_weight: extra_bytes_in_payload + .saturating_mul(bp_rialto_parachain::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + .saturating_add(bp_rialto_parachain::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) + .saturating_sub(if include_pay_dispatch_fee_cost { + 0 + } else { + bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT + }) + .saturating_add(message_dispatch_weight), + size: message_payload_len + .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_rialto_parachain::TX_EXTRA_BYTES), + } + } + + fn transaction_payment( + transaction: MessageTransaction, + ) -> bp_rialto_parachain::Balance { + // we don't have a direct access to the value of multiplier at RialtoParachain chain + // => it is a messages module parameter + let multiplier = RialtoParachainFeeMultiplier::get(); + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment( + bp_rialto_parachain::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic, + 1, + multiplier, + |weight| weight as _, + transaction, + ) + } +} + +impl TargetHeaderChain + for RialtoParachain +{ + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof or one or several keys; + // - id of the lane we prove state of. + type MessagesDeliveryProof = ToRialtoParachainMessagesDeliveryProof; + + fn verify_message(payload: &ToRialtoParachainMessagePayload) -> Result<(), Self::Error> { + messages::source::verify_chain_message::(payload) + } + + fn verify_messages_delivery_proof( + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + messages::source::verify_messages_delivery_proof_from_parachain::< + WithRialtoParachainMessageBridge, + bp_rialto_parachain::Header, + Runtime, + crate::WitRialtoParachainsInstance, + >(ParaId(RIALTO_PARACHAIN_ID), proof) + } +} + +impl SourceHeaderChain for RialtoParachain { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof or one or several keys; + // - id of the lane we prove messages for; + // - inclusive range of messages nonces that are proved. + type MessagesProof = FromRialtoParachainMessagesProof; + + fn verify_messages_proof( + proof: Self::MessagesProof, + messages_count: u32, + ) -> Result>, Self::Error> { + messages::target::verify_messages_proof_from_parachain::< + WithRialtoParachainMessageBridge, + bp_rialto_parachain::Header, + Runtime, + crate::WitRialtoParachainsInstance, + >(ParaId(RIALTO_PARACHAIN_ID), proof, messages_count) + } +} + +/// Millau -> RialtoParachain message lane pallet parameters. +#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] +pub enum MillauToRialtoParachainMessagesParameter { + /// The conversion formula we use is: `MillauTokens = RialtoParachainTokens * conversion_rate`. + RialtoParachainToMillauConversionRate(FixedU128), +} + +impl MessagesParameter for MillauToRialtoParachainMessagesParameter { + fn save(&self) { + match *self { + MillauToRialtoParachainMessagesParameter::RialtoParachainToMillauConversionRate( + ref conversion_rate, + ) => RialtoParachainToMillauConversionRate::set(conversion_rate), + } + } +} diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 7f5e6dedb6b9a..d73cdc6d27638 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -25,6 +25,11 @@ codec = { package = 'parity-scale-codec', version = '3.0.0' } serde = { version = '1.0', features = ['derive'] } hex-literal = '0.3.1' +# Bridge dependencies + +bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain" } +pallet-bridge-messages = { path = "../../../modules/messages" } + # RPC related Dependencies jsonrpc-core = '18.0' diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 6a8e751677df7..6f52155817417 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -81,6 +81,10 @@ pub fn development_config(id: ParaId) -> ChainSpec { get_account_id_from_seed::("Bob"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_rialto_parachain::AccountId, + bp_rialto_parachain::AccountIdConverter, + >(), ], id, ) @@ -126,6 +130,10 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec { get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_rialto_parachain::AccountId, + bp_rialto_parachain::AccountIdConverter, + >(), ], id, ) @@ -161,6 +169,7 @@ fn testnet_genesis( parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), + bridge_millau_messages: Default::default(), // parachain_system: Default::default(), } } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 52a54bd7bb72a..543e2675284bf 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -18,7 +18,13 @@ serde = { version = '1.0', optional = true, features = ['derive'] } # Bridge depedencies +bp-messages = { path = "../../../primitives/messages", default-features = false } +bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } +bridge-runtime-common = { path = "../../runtime-common", default-features = false } +pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } +pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } # Substrate Dependencies ## Substrate Primitive Dependencies @@ -82,7 +88,11 @@ runtime-benchmarks = [ 'pallet-timestamp/runtime-benchmarks', ] std = [ + "bp-messages/std", + "bp-millau/std", + "bp-runtime/std", "bp-rialto-parachain/std", + "bridge-runtime-common/std", "codec/std", "log/std", "scale-info/std", @@ -102,6 +112,8 @@ std = [ "frame-executive/std", "frame-system/std", "pallet-balances/std", + "pallet-bridge-grandpa/std", + "pallet-bridge-messages/std", "pallet-randomness-collective-flip/std", "pallet-timestamp/std", "pallet-sudo/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 41f159c70d24b..e35e78e9110b1 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -26,13 +26,18 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; + +use bridge_runtime_common::messages::{ + source::estimate_message_dispatch_and_delivery_fee, MessageBridge, +}; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, FixedU128, }; use sp_std::prelude::*; @@ -52,6 +57,7 @@ pub use frame_support::{ }; pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; +pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; #[cfg(any(feature = "std", test))] @@ -63,6 +69,9 @@ pub use bp_rialto_parachain::{ Index, Signature, MAXIMUM_BLOCK_WEIGHT, }; +pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; +pub use pallet_bridge_messages::Call as MessagesCall; + // Polkadot & XCM imports use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; @@ -76,6 +85,8 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; +mod millau_messages; + /// The address format for describing accounts. pub type Address = MultiAddress; /// Block type as expected by this runtime. @@ -88,6 +99,7 @@ pub type BlockId = generic::BlockId; pub type SignedExtra = ( frame_system::CheckNonZeroSender, frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, frame_system::CheckGenesis, frame_system::CheckEra, frame_system::CheckNonce, @@ -342,9 +354,11 @@ pub type XcmOriginToTransactDispatchOrigin = ( XcmPassthrough, ); +pub const BASE_XCM_WEIGHT: Weight = 1_000_000; + parameter_types! { // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. - pub UnitWeightCost: Weight = 1_000_000; + pub UnitWeightCost: Weight = BASE_XCM_WEIGHT; // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; @@ -366,6 +380,11 @@ pub type Barrier = ( // ^^^ Parent & its unit plurality gets free execution ); +/// Outbound XCM weigher type. +pub type OutboundXcmWeigher = FixedWeightBounds; +/// XCM weigher type. +pub type XcmWeigher = FixedWeightBounds; + pub struct XcmConfig; impl Config for XcmConfig { type Call = Call; @@ -376,7 +395,7 @@ impl Config for XcmConfig { type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of UNIT type UniversalLocation = UniversalLocation; type Barrier = Barrier; - type Weigher = FixedWeightBounds; + type Weigher = XcmWeigher; type Trader = UsingComponents, RelayLocation, AccountId, Balances, ()>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -412,7 +431,7 @@ impl pallet_xcm::Config for Runtime { type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; + type Weigher = XcmWeigher; type Origin = Origin; type Call = Call; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; @@ -454,10 +473,71 @@ impl pallet_aura::Config for Runtime { type MaxAuthorities = MaxAuthorities; } -// /// Configure the pallet template in pallets/template. -// impl template::Config for Runtime { -// type Event = Event; -// } +parameter_types! { + /// This is a pretty unscientific cap. + /// + /// Note that once this is hit the pallet will essentially throttle incoming requests down to one + /// call per block. + pub const MaxRequests: u32 = 50; + + /// Number of headers to keep. + /// + /// Assuming the worst case of every header being finalized, we will keep headers at least for a + /// week. + pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32; +} + +pub type MillauGrandpaInstance = (); +impl pallet_bridge_grandpa::Config for Runtime { + type BridgedChain = bp_millau::Millau; + type MaxRequests = MaxRequests; + type HeadersToKeep = HeadersToKeep; + type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; +} + +parameter_types! { + pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + // `IdentityFee` is used by Rialto => we may use weight directly + pub const GetDeliveryConfirmationTransactionFee: Balance = + bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; + pub const RootAccountForPayments: Option = None; + pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; +} + +/// Instance of the messages pallet used to relay messages to/from Millau chain. +pub type WithMillauMessagesInstance = (); + +impl pallet_bridge_messages::Config for Runtime { + type Event = Event; + type WeightInfo = pallet_bridge_messages::weights::MillauWeight; + type Parameter = millau_messages::RialtoParachainToMillauMessagesParameter; + type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + + type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; + type OutboundMessageFee = Balance; + + type InboundPayload = crate::millau_messages::FromMillauMessagePayload; + type InboundMessageFee = bp_millau::Balance; + type InboundRelayer = bp_millau::AccountId; + + type AccountIdConverter = bp_rialto_parachain::AccountIdConverter; + + type TargetHeaderChain = crate::millau_messages::Millau; + type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; + type MessageDeliveryAndDispatchPayment = (); + type OnMessageAccepted = (); + type OnDeliveryConfirmed = (); + + type SourceHeaderChain = crate::millau_messages::Millau; + type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; + type BridgedChainId = BridgedChainId; +} // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( @@ -486,8 +566,9 @@ construct_runtime!( CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 52, DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 53, - // //Template - // TemplatePallet: template::{Pallet, Call, Storage, Event}, + // Millau bridge modules. + BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, } ); @@ -600,6 +681,40 @@ impl_runtime_apis! { } } + impl bp_millau::MillauFinalityApi for Runtime { + fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { + let header = BridgeMillauGrandpa::best_finalized(); + (header.number, header.hash()) + } + } + + impl bp_millau::ToMillauOutboundLaneApi for Runtime { + fn estimate_message_delivery_and_dispatch_fee( + _lane_id: bp_messages::LaneId, + payload: ToMillauMessagePayload, + millau_to_this_conversion_rate: Option, + ) -> Option { + estimate_message_dispatch_and_delivery_fee::( + &payload, + WithMillauMessageBridge::RELAYER_FEE_PERCENT, + millau_to_this_conversion_rate, + ).ok() + } + + fn message_details( + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec> { + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithMillauMessagesInstance, + WithMillauMessageBridge, + OutboundXcmWeigher, + >(lane, begin, end) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn dispatch_benchmark( diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs new file mode 100644 index 0000000000000..4e765000b90d0 --- /dev/null +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -0,0 +1,304 @@ +// 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 . + +//! Everything required to serve Millau <-> RialtoParachain messages. + +// TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. +// Should be extracted to a separate crate and reused here. + +use crate::Runtime; + +use bp_messages::{ + source_chain::{SenderOrigin, TargetHeaderChain}, + target_chain::{ProvedMessages, SourceHeaderChain}, + InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, +}; +use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; +use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; +use codec::{Decode, Encode}; +use frame_support::{ + parameter_types, + weights::{DispatchClass, Weight}, + RuntimeDebug, +}; +use scale_info::TypeInfo; +use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; +use sp_std::convert::TryFrom; + +/// Initial value of `MillauToRialtoParachainConversionRate` parameter. +pub const INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE: FixedU128 = + FixedU128::from_inner(FixedU128::DIV); +/// Initial value of `MillauFeeMultiplier` parameter. +pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge +/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual +/// tests, confirming that we don't break encoding somewhere between. +pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::BASE_XCM_WEIGHT; + +parameter_types! { + /// Millau to RialtoParachain conversion rate. Initially we treat both tokens as equal. + pub storage MillauToRialtoParachainConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE; + /// Fee multiplier value at Millau chain. + pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER; +} + +/// Message payload for RialtoParachain -> Millau messages. +pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; + +/// Message verifier for RialtoParachain -> Millau messages. +pub type ToMillauMessageVerifier = + messages::source::FromThisChainMessageVerifier; + +/// Message payload for Millau -> RialtoParachain messages. +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; + +/// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. +pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< + WithMillauMessageBridge, + xcm_executor::XcmExecutor, + crate::XcmWeigher, + // 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + // (it is prepended with `UniversalOrigin` instruction) + frame_support::traits::ConstU64, +>; + +/// Messages proof for Millau -> RialtoParachain messages. +pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; + +/// Messages delivery proof for RialtoParachain -> Millau messages. +pub type ToMillauMessagesDeliveryProof = + messages::source::FromBridgedChainMessagesDeliveryProof; + +/// Millau <-> RialtoParachain message bridge. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct WithMillauMessageBridge; + +impl MessageBridge for WithMillauMessageBridge { + const RELAYER_FEE_PERCENT: u32 = 10; + const THIS_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; + const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = + bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; + + type ThisChain = RialtoParachain; + type BridgedChain = Millau; + + fn bridged_balance_to_this_balance( + bridged_balance: bp_millau::Balance, + bridged_to_this_conversion_rate_override: Option, + ) -> bp_rialto_parachain::Balance { + let conversion_rate = bridged_to_this_conversion_rate_override + .unwrap_or_else(|| MillauToRialtoParachainConversionRate::get()); + bp_rialto_parachain::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) + .unwrap_or(bp_rialto_parachain::Balance::MAX) + } +} + +/// RialtoParachain chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct RialtoParachain; + +impl messages::ChainWithMessages for RialtoParachain { + type Hash = bp_rialto_parachain::Hash; + type AccountId = bp_rialto_parachain::AccountId; + type Signer = bp_rialto_parachain::AccountSigner; + type Signature = bp_rialto_parachain::Signature; + type Weight = Weight; + type Balance = bp_rialto_parachain::Balance; +} + +impl messages::ThisChainWithMessages for RialtoParachain { + type Call = crate::Call; + type Origin = crate::Origin; + + fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + MessageNonce::MAX + } + + fn estimate_delivery_confirmation_transaction() -> MessageTransaction { + let inbound_data_size = + InboundLaneData::::encoded_size_hint( + bp_rialto_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + 1, + 1, + ) + .unwrap_or(u32::MAX); + + MessageTransaction { + dispatch_weight: + bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + size: inbound_data_size + .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_rialto_parachain::TX_EXTRA_BYTES), + } + } + + fn transaction_payment( + transaction: MessageTransaction, + ) -> bp_rialto_parachain::Balance { + // `transaction` may represent transaction from the future, when multiplier value will + // be larger, so let's use slightly increased value + let multiplier = FixedU128::saturating_from_rational(110, 100) + .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment( + bp_rialto_parachain::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic, + 1, + multiplier, + |weight| weight as _, + transaction, + ) + } +} + +/// Millau chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct Millau; + +impl messages::ChainWithMessages for Millau { + type Hash = bp_millau::Hash; + type AccountId = bp_millau::AccountId; + type Signer = bp_millau::AccountSigner; + type Signature = bp_millau::Signature; + type Weight = Weight; + type Balance = bp_millau::Balance; +} + +impl messages::BridgedChainWithMessages for Millau { + fn maximal_extrinsic_size() -> u32 { + bp_millau::Millau::max_extrinsic_size() + } + + fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { + true + } + + fn estimate_delivery_transaction( + message_payload: &[u8], + include_pay_dispatch_fee_cost: bool, + message_dispatch_weight: Weight, + ) -> MessageTransaction { + let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); + let extra_bytes_in_payload = Weight::from(message_payload_len) + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + + MessageTransaction { + dispatch_weight: extra_bytes_in_payload + .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) + .saturating_sub(if include_pay_dispatch_fee_cost { + 0 + } else { + bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT + }) + .saturating_add(message_dispatch_weight), + size: message_payload_len + .saturating_add(bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(bp_millau::TX_EXTRA_BYTES), + } + } + + fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { + // we don't have a direct access to the value of multiplier at Millau chain + // => it is a messages module parameter + let multiplier = MillauFeeMultiplier::get(); + // in our testnets, both per-byte fee and weight-to-fee are 1:1 + messages::transaction_payment( + bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, + 1, + multiplier, + |weight| weight as _, + transaction, + ) + } +} + +impl TargetHeaderChain for Millau { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof of one or several keys; + // - id of the lane we prove state of. + type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; + + fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { + messages::source::verify_chain_message::(payload) + } + + fn verify_messages_delivery_proof( + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData), Self::Error> { + messages::source::verify_messages_delivery_proof::< + WithMillauMessageBridge, + Runtime, + crate::MillauGrandpaInstance, + >(proof) + } +} + +impl SourceHeaderChain for Millau { + type Error = &'static str; + // The proof is: + // - hash of the header this proof has been created with; + // - the storage proof of one or several keys; + // - id of the lane we prove messages for; + // - inclusive range of messages nonces that are proved. + type MessagesProof = FromMillauMessagesProof; + + fn verify_messages_proof( + proof: Self::MessagesProof, + messages_count: u32, + ) -> Result>, Self::Error> { + messages::target::verify_messages_proof::< + WithMillauMessageBridge, + Runtime, + crate::MillauGrandpaInstance, + >(proof, messages_count) + } +} + +impl SenderOrigin for crate::Origin { + fn linked_account(&self) -> Option { + match self.caller { + crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => + Some(submitter.clone()), + _ => None, + } + } +} + +/// RialtoParachain -> Millau message lane pallet parameters. +#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] +pub enum RialtoParachainToMillauMessagesParameter { + /// The conversion formula we use is: `RialtoParachainTokens = MillauTokens * conversion_rate`. + MillauToRialtoParachainConversionRate(FixedU128), +} + +impl MessagesParameter for RialtoParachainToMillauMessagesParameter { + fn save(&self) { + match *self { + RialtoParachainToMillauMessagesParameter::MillauToRialtoParachainConversionRate( + ref conversion_rate, + ) => MillauToRialtoParachainConversionRate::set(conversion_rate), + } + } +} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 52600c1a173a9..e87639f6cb2a8 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -425,7 +425,7 @@ parameter_types! { pub const GetDeliveryConfirmationTransactionFee: Balance = bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; pub const RootAccountForPayments: Option = None; - pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; + pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; } /// Instance of the messages pallet used to relay messages to/from Millau chain. diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 8177f11512574..61251847bb07e 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -18,9 +18,11 @@ static_assertions = { version = "1.1", optional = true } # Bridge dependencies bp-messages = { path = "../../primitives/messages", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false } # Substrate dependencies @@ -47,6 +49,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-x default = ["std"] std = [ "bp-messages/std", + "bp-polkadot-core/std", "bp-runtime/std", "codec/std", "frame-support/std", @@ -56,6 +59,7 @@ std = [ "num-traits/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", "pallet-transaction-payment/std", "scale-info/std", "sp-api/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index d3e3ca28ab736..87dd009cff066 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -25,13 +25,14 @@ use bp_messages::{ target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; +use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaId}; use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker}; use codec::{Decode, DecodeLimit, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, + traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Header as HeaderT}, FixedPointNumber, FixedPointOperand, FixedU128, }; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; @@ -390,6 +391,9 @@ pub mod source { } /// Verify proof of This -> Bridged chain messages delivery. + /// + /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged + /// parachains, please use the `verify_messages_delivery_proof_from_parachain`. pub fn verify_messages_delivery_proof( proof: FromBridgedChainMessagesDeliveryProof>>, ) -> Result, &'static str> @@ -406,23 +410,70 @@ pub mod source { pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( bridged_header_hash.into(), StorageProof::new(storage_proof), - |storage| { - // Messages delivery proof is just proof of single storage key read => any error - // is fatal. - let storage_inbound_lane_data_key = - bp_messages::storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane); - let raw_inbound_lane_data = storage - .read_value(storage_inbound_lane_data_key.0.as_ref()) - .map_err(|_| "Failed to read inbound lane state from storage proof")? - .ok_or("Inbound lane state is missing from the messages proof")?; - let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) - .map_err(|_| "Failed to decode inbound lane state from the proof")?; - - Ok((lane, inbound_lane_data)) - }, + |storage| do_verify_messages_delivery_proof::< + B, + bp_runtime::HasherOf< + >::BridgedChain, + >, + >(lane, storage), ) .map_err(<&'static str>::from)? } + + /// Verify proof of This -> Bridged chain messages delivery. + /// + /// This function is used when Bridged chain is using parachain finality. For Bridged + /// chains with direct GRANDPA finality, please use the `verify_messages_delivery_proof`. + /// + /// This function currently only supports parachains, which are using header type that + /// implements `sp_runtime::traits::Header` trait. + pub fn verify_messages_delivery_proof_from_parachain< + B, + BridgedHeader, + ThisRuntime, + ParachainsInstance: 'static, + >( + bridged_parachain: ParaId, + proof: FromBridgedChainMessagesDeliveryProof>>, + ) -> Result, &'static str> + where + B: MessageBridge, + B::BridgedChain: ChainWithMessages, + BridgedHeader: HeaderT>>, + ThisRuntime: pallet_bridge_parachains::Config, + { + let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = + proof; + pallet_bridge_parachains::Pallet::::parse_finalized_storage_proof( + bridged_parachain, + bridged_header_hash, + StorageProof::new(storage_proof), + |para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()), + |storage| do_verify_messages_delivery_proof::(lane, storage), + ) + .map_err(<&'static str>::from)? + } + + /// The essense of This -> Bridged chain messages delivery proof verification. + fn do_verify_messages_delivery_proof( + lane: LaneId, + storage: bp_runtime::StorageProofChecker, + ) -> Result, &'static str> { + // Messages delivery proof is just proof of single storage key read => any error + // is fatal. + let storage_inbound_lane_data_key = bp_messages::storage_keys::inbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &lane, + ); + let raw_inbound_lane_data = storage + .read_value(storage_inbound_lane_data_key.0.as_ref()) + .map_err(|_| "Failed to read inbound lane state from storage proof")? + .ok_or("Inbound lane state is missing from the messages proof")?; + let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) + .map_err(|_| "Failed to decode inbound lane state from the proof")?; + + Ok((lane, inbound_lane_data)) + } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages. @@ -590,6 +641,9 @@ pub mod target { /// Verify proof of Bridged -> This chain messages. /// + /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged + /// parachains, please use the `verify_messages_proof_from_parachain`. + /// /// The `messages_count` argument verification (sane limits) is supposed to be made /// outside of this function. This function only verifies that the proof declares exactly /// `messages_count` messages. @@ -624,6 +678,54 @@ pub mod target { .map_err(Into::into) } + /// Verify proof of Bridged -> This chain messages. + /// + /// This function is used when Bridged chain is using parachain finality. For Bridged + /// chains with direct GRANDPA finality, please use the `verify_messages_proof`. + /// + /// The `messages_count` argument verification (sane limits) is supposed to be made + /// outside of this function. This function only verifies that the proof declares exactly + /// `messages_count` messages. + /// + /// This function currently only supports parachains, which are using header type that + /// implements `sp_runtime::traits::Header` trait. + pub fn verify_messages_proof_from_parachain< + B, + BridgedHeader, + ThisRuntime, + ParachainsInstance: 'static, + >( + bridged_parachain: ParaId, + proof: FromBridgedChainMessagesProof>>, + messages_count: u32, + ) -> Result>>>, &'static str> + where + B: MessageBridge, + B::BridgedChain: ChainWithMessages, + BridgedHeader: HeaderT>>, + ThisRuntime: pallet_bridge_parachains::Config, + { + verify_messages_proof_with_parser::( + proof, + messages_count, + |bridged_header_hash, bridged_storage_proof| { + pallet_bridge_parachains::Pallet::::parse_finalized_storage_proof( + bridged_parachain, + bridged_header_hash, + StorageProof::new(bridged_storage_proof), + |para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()), + |storage_adapter| storage_adapter, + ) + .map(|storage| StorageProofCheckerAdapter::<_, B> { + storage, + _dummy: Default::default(), + }) + .map_err(|err| MessageProofError::Custom(err.into())) + }, + ) + .map_err(Into::into) + } + #[derive(Debug, PartialEq)] pub(crate) enum MessageProofError { Empty, diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 9bed2b7a18a97..d7a74656c0cfd 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -24,7 +24,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_parachains::parachain_head_storage_key_at_source; -use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; @@ -67,6 +67,12 @@ pub mod pallet { UnknownRelayChainBlock, /// Invalid storage proof has been passed. InvalidStorageProof, + /// Given parachain head is unknown. + UnknownParaHead, + /// The storage proof doesn't contains storage root. So it is invalid for given header. + StorageRootMismatch, + /// Failed to extract state root from given parachain head. + FailedToExtractStateRoot, } #[pallet::config] @@ -190,6 +196,38 @@ pub mod pallet { } impl, I: 'static> Pallet { + /// Get best finalized header of the given parachain. + pub fn best_parachain_head(parachain: ParaId) -> Option { + let best_para_head_hash = BestParaHeads::::get(parachain)?.head_hash; + ImportedParaHeads::::get(parachain, best_para_head_hash) + } + + /// Get parachain head with given hash. + pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option { + ImportedParaHeads::::get(parachain, hash) + } + + /// Verify that the passed storage proof is valid, given it is crafted using + /// known finalized header. If the proof is valid, then the `parse` callback + /// is called and the function returns its result. + pub fn parse_finalized_storage_proof( + parachain: ParaId, + hash: ParaHash, + storage_proof: sp_trie::StorageProof, + decode_state_root: impl FnOnce(ParaHead) -> Option, + parse: impl FnOnce(bp_runtime::StorageProofChecker) -> R, + ) -> Result { + let para_head = + Self::parachain_head(parachain, hash).ok_or(Error::::UnknownParaHead)?; + let state_root = + decode_state_root(para_head).ok_or(Error::::FailedToExtractStateRoot)?; + let storage_proof_checker = + bp_runtime::StorageProofChecker::new(state_root, storage_proof) + .map_err(|_| Error::::StorageRootMismatch)?; + + Ok(parse(storage_proof_checker)) + } + /// Read parachain head from storage proof. fn read_parachain_head( storage: &bp_runtime::StorageProofChecker, @@ -329,7 +367,7 @@ mod tests { } fn prepare_parachain_heads_proof( - heads: Vec<(ParaId, ParaHead)>, + heads: Vec<(u32, ParaHead)>, ) -> (RelayBlockHash, ParaHeadsProof) { let mut root = Default::default(); let mut mdb = MemoryDB::default(); @@ -337,7 +375,7 @@ mod tests { let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); for (parachain, head) in heads { let storage_key = - parachain_head_storage_key_at_source(PARAS_PALLET_NAME, parachain); + parachain_head_storage_key_at_source(PARAS_PALLET_NAME, ParaId(parachain)); trie.insert(&storage_key.0, &head.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in tests"); @@ -385,10 +423,8 @@ mod tests { #[test] fn imports_initial_parachain_heads() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![ - (ParaId(1), head_data(1, 0)), - (ParaId(3), head_data(3, 10)), - ]); + let (state_root, proof) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 0)), (3, head_data(3, 10))]); run_test(|| { initialize(state_root); @@ -429,10 +465,8 @@ mod tests { #[test] fn imports_parachain_heads_is_able_to_progress() { - let (state_root_5, proof_5) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); - let (state_root_10, proof_10) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]); + let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 and import head#5 of parachain#1 initialize(state_root_5); @@ -478,7 +512,7 @@ mod tests { #[test] fn does_nothing_when_already_imported_this_head_at_previous_relay_header() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 0))]); + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); run_test(|| { // import head#0 of parachain#1 at relay block#0 initialize(state_root); @@ -495,10 +529,8 @@ mod tests { #[test] fn does_nothing_when_already_imported_head_at_better_relay_header() { - let (state_root_5, proof_5) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); - let (state_root_10, proof_10) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 10))]); + let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 initialize(state_root_5); @@ -536,8 +568,7 @@ mod tests { // import exactly `HeadsToKeep` headers for i in 0..heads_to_keep { - let (state_root, proof) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, i))]); + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, i))]); if i == 0 { initialize(state_root); } else { @@ -554,7 +585,7 @@ mod tests { // import next relay chain header and next parachain head let (state_root, proof) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, heads_to_keep))]); + prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]); proceed(heads_to_keep, state_root); assert_ok!(import_parachain_1_head(heads_to_keep, state_root, proof)); @@ -571,7 +602,7 @@ mod tests { #[test] fn fails_on_unknown_relay_chain_block() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(state_root); @@ -586,8 +617,7 @@ mod tests { #[test] fn fails_on_invalid_storage_proof() { - let (_state_root, proof) = - prepare_parachain_heads_proof(vec![(ParaId(1), head_data(1, 5))]); + let (_state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(Default::default()); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 79c0e63628116..d285283448c85 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -241,6 +241,21 @@ pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// We use this to get the account on Millau (target) which is derived from RialtoParachain's +/// (source) account. We do this so we can fund the derived account on Millau at Genesis to it can +/// pay transaction fees. +/// +/// The reason we can use the same `AccountId` type for both chains is because they share the same +/// development seed phrase. +/// +/// Note that this should only be used for testing. +pub fn derive_account_from_rialto_parachain_id( + id: bp_runtime::SourceAccount, +) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_PARACHAIN_CHAIN_ID, id); + AccountIdConverter::convert(encoded_id) +} + frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO); diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index f3f449c7af3e1..0ea849f6fed44 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -18,19 +18,32 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] +use bp_messages::{LaneId, MessageDetails, MessageNonce}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, - RuntimeDebug, + Parameter, RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, + FixedU128, MultiSignature, MultiSigner, Perbill, }; +use sp_std::vec::Vec; -/// Maximal weight of single Rialto parachain block. +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// RialtoParachain chain. This mostly depends on number of entries (and their density) in the +/// storage trie. Some reserve is reserved to account future chain growth. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Can be computed by subtracting encoded call size from raw transaction size. +pub const TX_EXTRA_BYTES: u32 = 104; + +/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. +pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; + +/// Maximal weight of single RialtoParachain block. /// /// This represents two seconds of compute assuming a target block time of six seconds. pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; @@ -42,6 +55,44 @@ pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; + +/// Maximal number of unconfirmed messages in Rialto confirmation transaction. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; + +/// Weight of single regular message delivery transaction on RialtoParachain chain. +/// +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call +/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` +/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be +/// rounded up to account possible future runtime upgrades. +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; + +/// Increase of delivery transaction weight on RialtoParachain chain with every additional message +/// byte. +/// +/// This value is a result of +/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then +/// must be rounded up to account possible future runtime upgrades. +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; + +/// Maximal weight of single message delivery confirmation transaction on RialtoParachain chain. +/// +/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` +/// weight formula computation for the case when single message is confirmed. The result then must +/// be rounded up to account possible future runtime upgrades. +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; + +/// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. +/// +/// This value corresponds to the result of +/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your +/// chain. Don't put too much reserve there, because it is used to **decrease** +/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery +/// transactions cheaper. +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; + /// Block number type used in Rialto. pub type BlockNumber = u32; @@ -103,6 +154,15 @@ impl Chain for RialtoParachain { } } +/// Convert a 256-bit hash into an AccountId. +pub struct AccountIdConverter; + +impl Convert for AccountIdConverter { + fn convert(hash: sp_core::H256) -> AccountId { + hash.to_fixed_bytes().into() + } +} + frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); @@ -122,3 +182,93 @@ frame_support::parameter_types! { .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); } + +/// Name of the With-Rialto-Parachain messages pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME: &str = "BridgeRialtoParachainMessages"; + +/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto parachain +/// runtime. +pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; + +/// Name of the `RialtoParachainFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD: &str = + "RialtoParachainFinalityApi_best_finalized"; + +/// Name of the `ToRialtoParachainOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` +/// runtime method. +pub const TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD: &str = + "ToRialtoParachainOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; +/// Name of the `ToRialtoParachainOutboundLaneApi::message_details` runtime method. +pub const TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = + "ToRialtoParachainOutboundLaneApi_message_details"; + +// We use this to get the account on RialtoParachain (target) which is derived from Millau's +// (source) account. We do this so we can fund the derived account on RialtoParachain at Genesis to +// it can pay transaction fees. +// +// The reason we can use the same `AccountId` type for both chains is because they share the same +// development seed phrase. +// +// Note that this should only be used for testing. +pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { + let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_CHAIN_ID, id); + AccountIdConverter::convert(encoded_id) +} + +sp_api::decl_runtime_apis! { + /// API for querying information about the finalized RialtoParachain headers. + /// + /// This API is implemented by runtimes that are bridging with the RialtoParachain chain, not the + /// RialtoParachain runtime itself. + pub trait RialtoParachainFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> (BlockNumber, Hash); + } + + /// Outbound message lane API for messages that are sent to RialtoParachain chain. + /// + /// This API is implemented by runtimes that are sending messages to RialtoParachain chain, not the + /// RialtoParachain runtime itself. + pub trait ToRialtoParachainOutboundLaneApi { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to RialtoParachain from this chain. + /// + /// Please keep in mind that this method returns the lowest message fee required for message + /// to be accepted to the lane. It may be good idea to pay a bit over this price to account + /// future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + rialto_parachain_to_this_conversion_rate: Option, + ) -> Option; + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn message_details( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec>; + } +} + +#[cfg(test)] +mod tests { + use super::*; + use sp_runtime::codec::Encode; + + #[test] + fn maximal_account_size_does_not_overflow_constant() { + assert!( + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), + "Actual maximal size of encoded AccountId ({}) overflows expected ({})", + AccountId::from([0u8; 32]).encode().len(), + MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, + ); + } +} diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 4bf20489bc851..56ef63f13333f 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -252,7 +252,7 @@ sp_api::decl_runtime_apis! { /// API for querying information about the finalized Rialto headers. /// /// This API is implemented by runtimes that are bridging with the Rialto chain, not the - /// Millau runtime itself. + /// Rialto runtime itself. pub trait RialtoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> (BlockNumber, Hash); diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 7f8b20067758c..8980c46c6ed21 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -55,6 +55,12 @@ use parity_util_mem::MallocSizeOf; )] pub struct ParaId(pub u32); +impl From for ParaId { + fn from(id: u32) -> Self { + ParaId(id) + } +} + /// Parachain head. /// /// This is an equivalent of the `polkadot_parachain::HeadData`. @@ -78,5 +84,8 @@ impl ParaHead { /// Parachain head hash. pub type ParaHash = crate::Hash; +/// Parachain head hasher. +pub type ParaHasher = crate::Hasher; + /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. pub type ParaHeadsProof = Vec>; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index da6f376ae4f49..cd3ea448e1d55 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -45,6 +45,9 @@ pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0]; /// Bridge-with-Rialto instance id. pub const RIALTO_CHAIN_ID: ChainId = *b"rlto"; +/// Bridge-with-RialtoParachain instance id. +pub const RIALTO_PARACHAIN_CHAIN_ID: ChainId = *b"rlpa"; + /// Bridge-with-Millau instance id. pub const MILLAU_CHAIN_ID: ChainId = *b"mlau"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 6ea4bacb191c9..18cf0cae4a6cc 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -26,6 +26,7 @@ bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } +bp-parachains = { path = "../../primitives/parachains" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs new file mode 100644 index 0000000000000..d44369de01a32 --- /dev/null +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -0,0 +1,57 @@ +// 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 . + +//! Millau-to-RialtoParachain headers sync entrypoint. + +// 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 . + +//! Millau-to-RialtoParachain headers sync entrypoint. + +use substrate_relay_helper::finality::{ + engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, + SubstrateFinalitySyncPipeline, +}; + +/// Description of Millau -> Rialto finalized headers bridge. +#[derive(Clone, Debug)] +pub struct MillauFinalityToRialtoParachain; + +impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { + type SourceChain = relay_millau_client::Millau; + type TargetChain = relay_rialto_parachain_client::RialtoParachain; + + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< + Self, + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::MillauGrandpaInstance, + >; + type TransactionSignScheme = relay_rialto_parachain_client::RialtoParachain; +} diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs new file mode 100644 index 0000000000000..f12fd1de89ec4 --- /dev/null +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -0,0 +1,62 @@ +// 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 . + +//! Millau-to-RialtoParachain messages sync entrypoint. + +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_parachain_client::RialtoParachain; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, +}; + +/// Description of Millau -> RialtoParachain messages bridge. +#[derive(Clone, Debug)] +pub struct MillauMessagesToRialtoParachain; + +impl SubstrateMessageLane for MillauMessagesToRialtoParachain { + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto_parachain::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + + type SourceChain = Millau; + type TargetChain = RialtoParachain; + + type SourceTransactionSignScheme = Millau; + type TargetTransactionSignScheme = RialtoParachain; + + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::WithMillauMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoParachainMessagesInstance, + >; + + type TargetToSourceChainConversionRateUpdateBuilder = (); + + type RelayStrategy = MixStrategy; +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 7659fc4897633..ccc1be434f579 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -19,11 +19,14 @@ pub mod kusama_headers_to_polkadot; pub mod kusama_messages_to_polkadot; pub mod millau_headers_to_rialto; +pub mod millau_headers_to_rialto_parachain; pub mod millau_messages_to_rialto; +pub mod millau_messages_to_rialto_parachain; pub mod polkadot_headers_to_kusama; pub mod polkadot_messages_to_kusama; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; +pub mod rialto_parachain_messages_to_millau; pub mod rialto_parachains_to_millau; pub mod rococo_headers_to_wococo; pub mod rococo_messages_to_wococo; diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 8e87c3ede706f..63322351d6d0e 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -16,10 +16,42 @@ //! Rialto parachain specification for CLI. -use crate::cli::CliChain; +use crate::cli::{ + bridge, + encode_message::{CliEncodeMessage, RawMessage}, + CliChain, +}; +use bp_messages::LaneId; +use bp_runtime::EncodedOrDecodedCall; use relay_rialto_parachain_client::RialtoParachain; +use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; +impl CliEncodeMessage for RialtoParachain { + fn encode_send_message_call( + lane: LaneId, + payload: RawMessage, + fee: BalanceOf, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => + rialto_parachain_runtime::Call::BridgeMillauMessages( + rialto_parachain_runtime::MessagesCall::send_message { + lane_id: lane, + payload, + delivery_and_dispatch_fee: fee, + }, + ) + .into(), + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }) + } +} + impl CliChain for RialtoParachain { const RUNTIME_VERSION: RuntimeVersion = rialto_parachain_runtime::VERSION; diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs new file mode 100644 index 0000000000000..e1fef8caf0a36 --- /dev/null +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -0,0 +1,62 @@ +// 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 . + +//! RialtoParachain-to-Millau messages sync entrypoint. + +use messages_relay::relay_strategy::MixStrategy; +use relay_millau_client::Millau; +use relay_rialto_parachain_client::RialtoParachain; +use substrate_relay_helper::messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, +}; + +/// Description of RialtoParachain -> Millau messages bridge. +#[derive(Clone, Debug)] +pub struct RialtoParachainMessagesToMillau; + +impl SubstrateMessageLane for RialtoParachainMessagesToMillau { + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto_parachain::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + + type SourceChain = RialtoParachain; + type TargetChain = Millau; + + type SourceTransactionSignScheme = RialtoParachain; + type TargetTransactionSignScheme = Millau; + + type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< + Self, + millau_runtime::Runtime, + millau_runtime::WithRialtoParachainMessagesInstance, + >; + type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< + Self, + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::WithMillauMessagesInstance, + >; + + type TargetToSourceChainConversionRateUpdateBuilder = (); + + type RelayStrategy = MixStrategy; +} diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index 492f1fdf16d01..dddf73902975a 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -23,17 +23,17 @@ use substrate_relay_helper::parachains_target::DirectSubmitParachainHeadsCallBui /// Rialto-to-Millau parachains sync description. #[derive(Clone, Debug)] -pub struct RialtoToMillauParachains; +pub struct RialtoParachainsToMillau; -impl ParachainsPipeline for RialtoToMillauParachains { +impl ParachainsPipeline for RialtoParachainsToMillau { type SourceChain = Rialto; type TargetChain = Millau; } /// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. -pub type RialtoToMillauParachainsSubmitParachainHeadsCallBuilder = +pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder = DirectSubmitParachainHeadsCallBuilder< - RialtoToMillauParachains, + RialtoParachainsToMillau, millau_runtime::Runtime, millau_runtime::WitRialtoParachainsInstance, >; diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index c8476725fff2f..db6c61381f484 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -26,6 +26,8 @@ pub enum FullBridge { WococoToRococo, KusamaToPolkadot, PolkadotToKusama, + MillauToRialtoParachain, + RialtoParachainToMillau, } impl FullBridge { @@ -38,6 +40,8 @@ impl FullBridge { Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX, Self::KusamaToPolkadot => KUSAMA_TO_POLKADOT_INDEX, Self::PolkadotToKusama => POLKADOT_TO_KUSAMA_INDEX, + Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, + Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, } } } @@ -48,6 +52,8 @@ pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0; pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0; pub const KUSAMA_TO_POLKADOT_INDEX: u8 = 0; pub const POLKADOT_TO_KUSAMA_INDEX: u8 = 0; +pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1; +pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; /// The macro allows executing bridge-specific code without going fully generic. /// @@ -171,6 +177,44 @@ macro_rules! select_full_bridge { $generic }, + FullBridge::MillauToRialtoParachain => { + type Source = relay_millau_client::Millau; + #[allow(dead_code)] + type Target = relay_rialto_parachain_client::RialtoParachain; + + // Derive-account + #[allow(unused_imports)] + use bp_rialto_parachain::derive_account_from_millau_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as MessagesLane; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + + $generic + } + FullBridge::RialtoParachainToMillau => { + type Source = relay_rialto_parachain_client::RialtoParachain; + #[allow(dead_code)] + type Target = relay_millau_client::Millau; + + // Derive-account + #[allow(unused_imports)] + use bp_millau::derive_account_from_rialto_parachain_id as derive_account; + + // Relay-messages + #[allow(unused_imports)] + use crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as MessagesLane; + + // Send-message / Estimate-fee + #[allow(unused_imports)] + use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; + + $generic + } } }; } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index add80c58538dd..63252382ec369 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -49,6 +49,7 @@ pub enum InitBridgeName { WococoToRococo, KusamaToPolkadot, PolkadotToKusama, + MillauToRialtoParachain, } macro_rules! select_bridge { @@ -181,6 +182,28 @@ macro_rules! select_bridge { ) } + $generic + }, + InitBridgeName::MillauToRialtoParachain => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_parachain_client::RialtoParachain; + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: InitializationData<::Header>, + ) -> ::Call { + let initialize_call = rialto_parachain_runtime::BridgeGrandpaCall::< + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::MillauGrandpaInstance, + >::initialize { + init_data, + }; + rialto_parachain_runtime::SudoCall::sudo { + call: Box::new(initialize_call.into()), + } + .into() + } + $generic }, } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 3a353ed4ab03c..59ab3a1a33e28 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -55,6 +55,7 @@ pub enum RelayHeadersBridge { WococoToRococo, KusamaToPolkadot, PolkadotToKusama, + MillauToRialtoParachain, } macro_rules! select_bridge { @@ -109,6 +110,14 @@ macro_rules! select_bridge { $generic }, + RelayHeadersBridge::MillauToRialtoParachain => { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_parachain_client::RialtoParachain; + type Finality = crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; + + $generic + + }, } }; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 537ae1e101864..1b6bc41301d00 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -480,7 +480,6 @@ impl RelayHeadersAndMessages { right_to_left_transaction_params, params.shared.only_mandatory_headers, ); - // Need 2x capacity since we consider both directions for each lane let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index f1af5b5c95873..23ff1da642086 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -55,8 +55,8 @@ macro_rules! select_bridge { match $bridge { RelayParachainsBridge::RialtoToMillau => { use crate::chains::rialto_parachains_to_millau::{ - RialtoToMillauParachains as Pipeline, - RialtoToMillauParachainsSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder, + RialtoParachainsToMillau as Pipeline, + RialtoParachainsToMillauSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder, }; use bp_millau::BRIDGE_PARAS_PALLET_NAME as BRIDGE_PARAS_PALLET_NAME_AT_TARGET; diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index ebc2856064318..190f3b0f7e317 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -6,12 +6,14 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Bridge dependencies -bp-rialto = { path = "../../primitives/chain-rialto" } +bp-messages = { path = "../../primitives/messages" } +bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } # Substrate Dependencies @@ -19,3 +21,5 @@ rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 65bf46f660cc7..f70815c03ef8b 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -16,8 +16,15 @@ //! Types used to connect to the Rialto-Substrate chain. +use bp_messages::MessageNonce; +use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase}; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithBalances, ChainWithMessages, Error as SubstrateError, SignParam, + TransactionSignScheme, UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; /// Rialto header id. @@ -40,11 +47,11 @@ impl ChainBase for RialtoParachain { type Signature = rialto_parachain_runtime::Signature; fn max_extrinsic_size() -> u32 { - bp_rialto::Rialto::max_extrinsic_size() + bp_rialto_parachain::RialtoParachain::max_extrinsic_size() } fn max_extrinsic_weight() -> Weight { - bp_rialto::Rialto::max_extrinsic_weight() + bp_rialto_parachain::RialtoParachain::max_extrinsic_weight() } } @@ -52,12 +59,111 @@ impl Chain for RialtoParachain { const NAME: &'static str = "RialtoParachain"; const TOKEN_ID: Option<&'static str> = None; // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; + // should be removed in https://github.com/paritytech/parity-bridges-common/issues/1246 + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; + const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = + bp_rialto_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = rialto_parachain_runtime::SignedBlock; type Call = rialto_parachain_runtime::Call; - type WeightToFee = bp_rialto::WeightToFee; + type WeightToFee = bp_rialto_parachain::WeightToFee; } + +impl ChainWithBalances for RialtoParachain { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + use frame_support::storage::generator::StorageMap; + StorageKey( + frame_system::Account::::storage_map_final_key( + account_id, + ), + ) + } +} + +impl ChainWithMessages for RialtoParachain { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto_parachain::TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightInfo = (); +} + +impl TransactionSignScheme for RialtoParachain { + type Chain = RialtoParachain; + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic; + + fn sign_transaction(param: SignParam) -> Result { + let raw_payload = SignedPayload::from_raw( + param.unsigned.call, + ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from( + param.era.frame_era(), + ), + frame_system::CheckNonce::::from( + param.unsigned.nonce, + ), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::< + rialto_parachain_runtime::Runtime, + >::from(param.unsigned.tip), + ), + ( + (), + param.spec_version, + param.transaction_version, + param.genesis_hash, + param.era.signed_payload(param.genesis_hash), + (), + (), + (), + ), + ); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(rialto_parachain_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + *address == rialto_parachain_runtime::Address::Id(signer.public().into()) + }) + .unwrap_or(false) + } + + fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { + unimplemented!("TODO") + } +} + +/// RialtoParachain signing params. +pub type SigningParams = sp_core::sr25519::Pair; + +/// RialtoParachain header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 56ceb67c58d20..b3baa217e89ff 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -298,6 +298,20 @@ fn select_parachains_to_update( where P::SourceChain: Chain, { + log::trace!( + target: "bridge", + "Selecting {} parachains to update at {} (relay block: {:?}):\n\t\ + At {}: {:?}\n\t\ + At {}: {:?}", + P::SourceChain::NAME, + P::TargetChain::NAME, + best_finalized_relay_block, + P::SourceChain::NAME, + heads_at_source, + P::TargetChain::NAME, + heads_at_target, + ); + heads_at_source .into_iter() .zip(heads_at_target.into_iter()) From 45c63e2d1420fa41ff4e3515cef290f042856c33 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 May 2022 10:54:20 +0300 Subject: [PATCH 0690/1210] Complex RialtoParachain <> Millau relay (#1405) * complex parachain relay * fix spelling --- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 2 +- .../runtime/src/rialto_parachain_messages.rs | 19 +- primitives/chain-millau/src/lib.rs | 3 - primitives/chain-rialto-parachain/src/lib.rs | 8 + primitives/chain-rialto/src/lib.rs | 2 + relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/chains/millau.rs | 9 + .../src/chains/rialto_parachains_to_millau.rs | 16 +- relays/bin-substrate/src/cli/mod.rs | 2 +- .../src/cli/relay_headers_and_messages.rs | 397 +++++++-- .../bin-substrate/src/cli/relay_parachains.rs | 29 +- relays/client-rialto/src/lib.rs | 9 +- relays/client-substrate/src/chain.rs | 14 + relays/client-substrate/src/client.rs | 5 + relays/client-substrate/src/lib.rs | 4 +- relays/lib-substrate-relay/src/lib.rs | 5 +- .../lib-substrate-relay/src/messages_lane.rs | 9 +- .../src/messages_source.rs | 55 +- .../src/messages_target.rs | 13 +- .../headers.rs} | 22 +- .../lib-substrate-relay/src/on_demand/mod.rs | 35 + .../src/on_demand/parachains.rs | 797 ++++++++++++++++++ .../lib-substrate-relay/src/parachains/mod.rs | 110 +++ .../src/parachains/source.rs | 163 ++++ .../target.rs} | 130 +-- .../src/parachains_source.rs | 91 -- 27 files changed, 1639 insertions(+), 313 deletions(-) rename relays/lib-substrate-relay/src/{on_demand_headers.rs => on_demand/headers.rs} (96%) create mode 100644 relays/lib-substrate-relay/src/on_demand/mod.rs create mode 100644 relays/lib-substrate-relay/src/on_demand/parachains.rs create mode 100644 relays/lib-substrate-relay/src/parachains/mod.rs create mode 100644 relays/lib-substrate-relay/src/parachains/source.rs rename relays/lib-substrate-relay/src/{parachains_target.rs => parachains/target.rs} (50%) delete mode 100644 relays/lib-substrate-relay/src/parachains_source.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 23cf4d0b05b4e..f032eec844db4 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -805,7 +805,7 @@ impl_runtime_apis! { fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { // the parachains finality pallet is never decoding parachain heads, so it is // only done in the integration code - use crate::rialto_parachain_messages::RIALTO_PARACHAIN_ID; + use bp_rialto_parachain::RIALTO_PARACHAIN_ID; let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::< Runtime, WitRialtoParachainsInstance, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index aac568e077f64..dad7591147d81 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -97,7 +97,7 @@ impl MessageBridge for WithRialtoMessageBridge { bridged_to_this_conversion_rate_override: Option, ) -> bp_millau::Balance { let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(|| RialtoToMillauConversionRate::get()); + .unwrap_or_else(RialtoToMillauConversionRate::get); bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) .unwrap_or(bp_millau::Balance::MAX) } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index c4d8f2c10ce56..3ac2690888259 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -19,7 +19,7 @@ use crate::Runtime; use bp_messages::{ - source_chain::{SenderOrigin, TargetHeaderChain}, + source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -36,13 +36,6 @@ use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; -/// Identifier of RialtoParachain in the Rialto relay chain. -/// -/// This identifier is not something that is declared either by Rialto or RialtoParachain. This -/// is an identifier of registration. So in theory it may be changed. But since bridge is going -/// to be deployed after parachain registration AND since parachain de-registration is highly -/// likely impossible, it is fine to declare this constant here. -pub const RIALTO_PARACHAIN_ID: u32 = 2000; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. @@ -109,7 +102,7 @@ impl MessageBridge for WithRialtoParachainMessageBridge { bridged_to_this_conversion_rate_override: Option, ) -> bp_millau::Balance { let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(|| RialtoParachainToMillauConversionRate::get()); + .unwrap_or_else(RialtoParachainToMillauConversionRate::get); bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) .unwrap_or(bp_millau::Balance::MAX) } @@ -132,8 +125,8 @@ impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; type Origin = crate::Origin; - fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { - (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) && send_origin.linked_account().is_some() + fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { @@ -260,7 +253,7 @@ impl TargetHeaderChain(ParaId(RIALTO_PARACHAIN_ID), proof) + >(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof) } } @@ -282,7 +275,7 @@ impl SourceHeaderChain for RialtoParachain { bp_rialto_parachain::Header, Runtime, crate::WitRialtoParachainsInstance, - >(ParaId(RIALTO_PARACHAIN_ID), proof, messages_count) + >(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof, messages_count) } } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index d285283448c85..6cc417756a606 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -284,9 +284,6 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; -/// Name of the With-Rialto parachains bridge pallet name in the Millau runtime. -pub const BRIDGE_PARAS_PALLET_NAME: &str = "BridgeRialtoParachains"; - /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 0ea849f6fed44..598286b2f3ab3 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -32,6 +32,14 @@ use sp_runtime::{ }; use sp_std::vec::Vec; +/// Identifier of RialtoParachain in the Rialto relay chain. +/// +/// This identifier is not something that is declared either by Rialto or RialtoParachain. This +/// is an identifier of registration. So in theory it may be changed. But since bridge is going +/// to be deployed after parachain registration AND since parachain de-registration is highly +/// likely impossible, it is fine to declare this constant here. +pub const RIALTO_PARACHAIN_ID: u32 = 2000; + /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// RialtoParachain chain. This mostly depends on number of entries (and their density) in the /// storage trie. Some reserve is reserved to account future chain growth. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 56ef63f13333f..ca3381a25fd38 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -228,6 +228,8 @@ frame_support::parameter_types! { pub const WITH_RIALTO_GRANDPA_PALLET_NAME: &str = "BridgeRialtoGrandpa"; /// Name of the With-Rialto messages pallet instance that is deployed at bridged chains. pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; +/// Name of the With-Rialto parachains bridge pallet instance that is deployed at bridged chains. +pub const WITH_RIALTO_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeRialtoParachains"; /// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto runtime. pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 18cf0cae4a6cc..c7204be3202da 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -41,6 +41,7 @@ messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } +pallet-bridge-parachains = { path = "../../modules/parachains" } parachains-relay = { path = "../parachains" } relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index a9e99771f5922..4b31e423ac02b 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -43,6 +43,15 @@ impl CliEncodeMessage for Millau { }, ) .into(), + bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => + millau_runtime::Call::BridgeRialtoParachainMessages( + millau_runtime::MessagesCall::send_message { + lane_id: lane, + payload, + delivery_and_dispatch_fee: fee, + }, + ) + .into(), _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", bridge_instance_index diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index dddf73902975a..078c24a3e34c4 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -19,7 +19,10 @@ use parachains_relay::ParachainsPipeline; use relay_millau_client::Millau; use relay_rialto_client::Rialto; -use substrate_relay_helper::parachains_target::DirectSubmitParachainHeadsCallBuilder; +use relay_rialto_parachain_client::RialtoParachain; +use substrate_relay_helper::parachains::{ + DirectSubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; /// Rialto-to-Millau parachains sync description. #[derive(Clone, Debug)] @@ -30,6 +33,17 @@ impl ParachainsPipeline for RialtoParachainsToMillau { type TargetChain = Millau; } +impl SubstrateParachainsPipeline for RialtoParachainsToMillau { + type SourceParachain = RialtoParachain; + type SourceRelayChain = Rialto; + type TargetChain = Millau; + + type SubmitParachainHeadsCallBuilder = RialtoParachainsToMillauSubmitParachainHeadsCallBuilder; + type TransactionSignScheme = Millau; + + const SOURCE_PARACHAIN_PARA_ID: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID; +} + /// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder = DirectSubmitParachainHeadsCallBuilder< diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index bf2bede5d2532..4748e42e3f3cc 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -238,7 +238,7 @@ impl HexBytes { } /// Prometheus metrics params. -#[derive(StructOpt)] +#[derive(Clone, Debug, StructOpt)] pub struct PrometheusParams { /// Do not expose a Prometheus metric endpoint. #[structopt(long)] diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 1b6bc41301d00..c3c05910475e7 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -26,17 +26,25 @@ use futures::{FutureExt, TryFutureExt}; use structopt::StructOpt; use strum::VariantNames; +use async_std::sync::Arc; +use bp_polkadot_core::parachains::ParaHash; use codec::Encode; use messages_relay::relay_strategy::MixStrategy; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, ChainRuntimeVersion, Client, SignParam, TransactionSignScheme, - UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, ChainRuntimeVersion, Client, + SignParam, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, - on_demand_headers::OnDemandHeadersRelay, TransactionParams, + finality::SubstrateFinalitySyncPipeline, + messages_lane::MessagesRelayParams, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, + }, + parachains::SubstrateParachainsPipeline, + TransactionParams, }; use crate::{ @@ -56,6 +64,7 @@ pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; #[derive(StructOpt)] pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), + MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), RococoWococo(RococoWococoHeadersAndMessages), KusamaPolkadot(KusamaPolkadotHeadersAndMessages), } @@ -83,6 +92,33 @@ pub struct HeadersAndMessagesSharedParams { // terminology, which is unusable for both-way relays (if you're relaying headers from Rialto to // Millau and from Millau to Rialto, then which chain is source?). macro_rules! declare_bridge_options { + // chain, parachain, relay-chain-of-parachain + ($chain1:ident, $chain2:ident, $chain3:ident) => { + paste::item! { + #[doc = $chain1 ", " $chain2 " and " $chain3 " headers+messages relay params."] + #[derive(StructOpt)] + pub struct [<$chain1 $chain2 HeadersAndMessages>] { + #[structopt(flatten)] + shared: HeadersAndMessagesSharedParams, + #[structopt(flatten)] + left: [<$chain1 ConnectionParams>], + #[structopt(flatten)] + left_sign: [<$chain1 SigningParams>], + #[structopt(flatten)] + left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>], + #[structopt(flatten)] + right: [<$chain2 ConnectionParams>], + #[structopt(flatten)] + right_sign: [<$chain2 SigningParams>], + #[structopt(flatten)] + right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], + #[structopt(flatten)] + right_relay: [<$chain3 ConnectionParams>], + } + } + + declare_bridge_options!({ implement }, $chain1, $chain2); + }; ($chain1:ident, $chain2:ident) => { paste::item! { #[doc = $chain1 " and " $chain2 " headers+messages relay params."] @@ -103,7 +139,12 @@ macro_rules! declare_bridge_options { #[structopt(flatten)] right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], } + } + declare_bridge_options!({ implement }, $chain1, $chain2); + }; + ({ implement }, $chain1:ident, $chain2:ident) => { + paste::item! { impl From for [<$chain1 $chain2 HeadersAndMessages>] { fn from(relay_params: RelayHeadersAndMessages) -> [<$chain1 $chain2 HeadersAndMessages>] { match relay_params { @@ -125,11 +166,6 @@ macro_rules! select_bridge { type Left = relay_millau_client::Millau; type Right = relay_rialto_client::Rialto; - type LeftToRightFinality = - crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; - type RightToLeftFinality = - crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; - type LeftAccountIdConverter = bp_millau::AccountIdConverter; type RightAccountIdConverter = bp_rialto::AccountIdConverter; @@ -138,6 +174,106 @@ macro_rules! select_bridge { rialto_messages_to_millau::RialtoMessagesToMillau as RightToLeftMessageLane, }; + async fn start_on_demand_relays( + params: &Params, + left_client: Client, + right_client: Client, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + start_on_demand_relay_to_relay::< + Left, + Right, + crate::chains::millau_headers_to_rialto::MillauFinalityToRialto, + crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau, + >( + left_client, + right_client, + TransactionParams { + mortality: params.right_sign.transactions_mortality()?, + signer: params.right_sign.to_keypair::()?, + }, + TransactionParams { + mortality: params.left_sign.transactions_mortality()?, + signer: params.left_sign.to_keypair::()?, + }, + params.shared.only_mandatory_headers, + params.shared.only_mandatory_headers, + params.left.can_start_version_guard(), + params.right.can_start_version_guard(), + ).await + } + + async fn left_create_account( + _left_client: Client, + _left_sign: ::AccountKeyPair, + _account_id: AccountIdOf, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Account creation is not supported by this bridge")) + } + + async fn right_create_account( + _right_client: Client, + _right_sign: ::AccountKeyPair, + _account_id: AccountIdOf, + ) -> anyhow::Result<()> { + Err(anyhow::format_err!("Account creation is not supported by this bridge")) + } + + $generic + }, + RelayHeadersAndMessages::MillauRialtoParachain(_) => { + type Params = MillauRialtoParachainHeadersAndMessages; + + type Left = relay_millau_client::Millau; + type Right = relay_rialto_parachain_client::RialtoParachain; + + type LeftAccountIdConverter = bp_millau::AccountIdConverter; + type RightAccountIdConverter = bp_rialto_parachain::AccountIdConverter; + + use crate::chains::{ + millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as LeftToRightMessageLane, + rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as RightToLeftMessageLane, + }; + + async fn start_on_demand_relays( + params: &Params, + left_client: Client, + right_client: Client, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + type RightRelayChain = relay_rialto_client::Rialto; + let rialto_relay_chain_client = params.right_relay.to_client::().await?; // TODO: should be the relaychain connection params + + start_on_demand_relay_to_parachain::< + Left, + Right, + RightRelayChain, + crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain, + crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau, + crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau, + >( + left_client, + right_client, + rialto_relay_chain_client, + TransactionParams { + mortality: params.right_sign.transactions_mortality()?, + signer: params.right_sign.to_keypair::()?, + }, + TransactionParams { + mortality: params.left_sign.transactions_mortality()?, + signer: params.left_sign.to_keypair::()?, + }, + params.shared.only_mandatory_headers, + params.shared.only_mandatory_headers, + params.left.can_start_version_guard(), + params.right.can_start_version_guard(), + ).await + } + async fn left_create_account( _left_client: Client, _left_sign: ::AccountKeyPair, @@ -162,11 +298,6 @@ macro_rules! select_bridge { type Left = relay_rococo_client::Rococo; type Right = relay_wococo_client::Wococo; - type LeftToRightFinality = - crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; - type RightToLeftFinality = - crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; - type LeftAccountIdConverter = bp_rococo::AccountIdConverter; type RightAccountIdConverter = bp_wococo::AccountIdConverter; @@ -175,6 +306,37 @@ macro_rules! select_bridge { wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, }; + async fn start_on_demand_relays( + params: &Params, + left_client: Client, + right_client: Client, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + start_on_demand_relay_to_relay::< + Left, + Right, + crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo, + crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo, + >( + left_client, + right_client, + TransactionParams { + mortality: params.right_sign.transactions_mortality()?, + signer: params.right_sign.to_keypair::()?, + }, + TransactionParams { + mortality: params.left_sign.transactions_mortality()?, + signer: params.left_sign.to_keypair::()?, + }, + params.shared.only_mandatory_headers, + params.shared.only_mandatory_headers, + params.left.can_start_version_guard(), + params.right.can_start_version_guard(), + ).await + } + async fn left_create_account( left_client: Client, left_sign: ::AccountKeyPair, @@ -219,11 +381,6 @@ macro_rules! select_bridge { type Left = relay_kusama_client::Kusama; type Right = relay_polkadot_client::Polkadot; - type LeftToRightFinality = - crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; - type RightToLeftFinality = - crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; - type LeftAccountIdConverter = bp_kusama::AccountIdConverter; type RightAccountIdConverter = bp_polkadot::AccountIdConverter; @@ -232,6 +389,37 @@ macro_rules! select_bridge { polkadot_messages_to_kusama::PolkadotMessagesToKusama as RightToLeftMessageLane, }; + async fn start_on_demand_relays( + params: &Params, + left_client: Client, + right_client: Client, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + start_on_demand_relay_to_relay::< + Left, + Right, + crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot, + crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama, + >( + left_client, + right_client, + TransactionParams { + mortality: params.right_sign.transactions_mortality()?, + signer: params.right_sign.to_keypair::()?, + }, + TransactionParams { + mortality: params.left_sign.transactions_mortality()?, + signer: params.left_sign.to_keypair::()?, + }, + params.shared.only_mandatory_headers, + params.shared.only_mandatory_headers, + params.left.can_start_version_guard(), + params.right.can_start_version_guard(), + ).await + } + async fn left_create_account( left_client: Client, left_sign: ::AccountKeyPair, @@ -277,12 +465,14 @@ macro_rules! select_bridge { // All supported chains. declare_chain_options!(Millau, millau); declare_chain_options!(Rialto, rialto); +declare_chain_options!(RialtoParachain, rialto_parachain); declare_chain_options!(Rococo, rococo); declare_chain_options!(Wococo, wococo); declare_chain_options!(Kusama, kusama); declare_chain_options!(Polkadot, polkadot); // All supported bridges. declare_bridge_options!(Millau, Rialto); +declare_bridge_options!(Millau, RialtoParachain, Rialto); declare_bridge_options!(Rococo, Wococo); declare_bridge_options!(Kusama, Polkadot); @@ -303,12 +493,12 @@ impl RelayHeadersAndMessages { let right_messages_pallet_owner = params.right_messages_pallet_owner.to_keypair::()?; - let lanes = params.shared.lane; + let lanes = params.shared.lane.clone(); let relayer_mode = params.shared.relayer_mode.into(); let relay_strategy = MixStrategy::new(relayer_mode); // create metrics registry and register standalone metrics - let metrics_params: MetricsParams = params.shared.prometheus_params.into(); + let metrics_params: MetricsParams = params.shared.prometheus_params.clone().into(); let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); let left_to_right_metrics = substrate_relay_helper::messages_metrics::standalone_metrics::< @@ -448,38 +638,8 @@ impl RelayHeadersAndMessages { .await?; // start on-demand header relays - let left_to_right_transaction_params = TransactionParams { - mortality: right_transactions_mortality, - signer: right_sign.clone(), - }; - let right_to_left_transaction_params = TransactionParams { - mortality: left_transactions_mortality, - signer: left_sign.clone(), - }; - LeftToRightFinality::start_relay_guards( - &right_client, - &left_to_right_transaction_params, - params.right.can_start_version_guard(), - ) - .await?; - RightToLeftFinality::start_relay_guards( - &left_client, - &right_to_left_transaction_params, - params.left.can_start_version_guard(), - ) - .await?; - let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( - left_client.clone(), - right_client.clone(), - left_to_right_transaction_params, - params.shared.only_mandatory_headers, - ); - let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::( - right_client.clone(), - left_client.clone(), - right_to_left_transaction_params, - params.shared.only_mandatory_headers, - ); + let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = + start_on_demand_relays(¶ms, left_client.clone(), right_client.clone()).await?; // Need 2x capacity since we consider both directions for each lane let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { @@ -543,6 +703,137 @@ impl RelayHeadersAndMessages { } } +/// Start bidirectional on-demand headers <> headers relay. +async fn start_on_demand_relay_to_relay( + left_client: Client, + right_client: Client, + left_to_right_transaction_params: TransactionParams>, + right_to_left_transaction_params: TransactionParams>, + left_to_right_only_mandatory_headers: bool, + right_to_left_only_mandatory_headers: bool, + left_can_start_version_guard: bool, + right_can_start_version_guard: bool, +) -> anyhow::Result<( + Arc>>, + Arc>>, +)> +where + LC: Chain + TransactionSignScheme, + RC: Chain + TransactionSignScheme, + LR: SubstrateFinalitySyncPipeline< + SourceChain = LC, + TargetChain = RC, + TransactionSignScheme = RC, + >, + RL: SubstrateFinalitySyncPipeline< + SourceChain = RC, + TargetChain = LC, + TransactionSignScheme = LC, + >, + AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, + AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, +{ + LR::start_relay_guards( + &right_client, + &left_to_right_transaction_params, + right_can_start_version_guard, + ) + .await?; + RL::start_relay_guards( + &left_client, + &right_to_left_transaction_params, + left_can_start_version_guard, + ) + .await?; + let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( + left_client.clone(), + right_client.clone(), + left_to_right_transaction_params, + left_to_right_only_mandatory_headers, + ); + let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::( + right_client.clone(), + left_client.clone(), + right_to_left_transaction_params, + right_to_left_only_mandatory_headers, + ); + + Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_headers))) +} + +/// Start bidirectional on-demand headers <> parachains relay. +async fn start_on_demand_relay_to_parachain( + left_client: Client, + right_client: Client, + right_relay_client: Client, + left_to_right_transaction_params: TransactionParams>, + right_to_left_transaction_params: TransactionParams>, + left_to_right_only_mandatory_headers: bool, + right_to_left_only_mandatory_headers: bool, + left_can_start_version_guard: bool, + right_can_start_version_guard: bool, +) -> anyhow::Result<( + Arc>>, + Arc>>, +)> +where + LC: Chain + TransactionSignScheme, + RC: Chain + TransactionSignScheme, + RRC: Chain + + TransactionSignScheme, + LR: SubstrateFinalitySyncPipeline< + SourceChain = LC, + TargetChain = RC, + TransactionSignScheme = RC, + >, + RRF: SubstrateFinalitySyncPipeline< + SourceChain = RRC, + TargetChain = LC, + TransactionSignScheme = LC, + >, + RL: SubstrateParachainsPipeline< + SourceRelayChain = RRC, + SourceParachain = RC, + TargetChain = LC, + TransactionSignScheme = LC, + >, + AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, + AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, +{ + LR::start_relay_guards( + &right_client, + &left_to_right_transaction_params, + right_can_start_version_guard, + ) + .await?; + RRF::start_relay_guards( + &left_client, + &right_to_left_transaction_params, + left_can_start_version_guard, + ) + .await?; + let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( + left_client.clone(), + right_client, + left_to_right_transaction_params, + left_to_right_only_mandatory_headers, + ); + let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::new::( + right_relay_client.clone(), + left_client.clone(), + right_to_left_transaction_params.clone(), + right_to_left_only_mandatory_headers, + ); + let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::( + right_relay_client, + left_client, + right_to_left_transaction_params, + Arc::new(right_relay_to_left_on_demand_headers), + ); + + Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_parachains))) +} + /// Sign and submit transaction with given call to the chain. async fn submit_signed_extrinsic>( client: Client, diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 23ff1da642086..8667ff741660d 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -20,7 +20,8 @@ use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ - parachains_source::ParachainsSource, parachains_target::ParachainsTarget, TransactionParams, + parachains::{source::ParachainsSource, target::ParachainsTarget}, + TransactionParams, }; use crate::cli::{ @@ -54,15 +55,7 @@ macro_rules! select_bridge { ($bridge: expr, $generic: tt) => { match $bridge { RelayParachainsBridge::RialtoToMillau => { - use crate::chains::rialto_parachains_to_millau::{ - RialtoParachainsToMillau as Pipeline, - RialtoParachainsToMillauSubmitParachainHeadsCallBuilder as SubmitParachainHeadsCallBuilder, - }; - - use bp_millau::BRIDGE_PARAS_PALLET_NAME as BRIDGE_PARAS_PALLET_NAME_AT_TARGET; - use bp_rialto::PARAS_PALLET_NAME as PARAS_PALLET_NAME_AT_SOURCE; - - use relay_millau_client::Millau as TargetTransactionSignScheme; + use crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau as Pipeline; $generic }, @@ -78,25 +71,15 @@ impl RelayParachains { type TargetChain = ::TargetChain; let source_client = self.source.to_client::().await?; - let source_client = ParachainsSource::::new( - source_client, - PARAS_PALLET_NAME_AT_SOURCE.into(), - ); + let source_client = ParachainsSource::::new(source_client, None); let taret_transaction_params = TransactionParams { signer: self.target_sign.to_keypair::()?, mortality: self.target_sign.target_transactions_mortality, }; let target_client = self.target.to_client::().await?; - let target_client = ParachainsTarget::< - Pipeline, - TargetTransactionSignScheme, - SubmitParachainHeadsCallBuilder, - >::new( - target_client.clone(), - taret_transaction_params, - BRIDGE_PARAS_PALLET_NAME_AT_TARGET.into(), - ); + let target_client = + ParachainsTarget::::new(target_client.clone(), taret_transaction_params); let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 858227e8083f6..e79556b966894 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -21,7 +21,8 @@ use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, + Error as SubstrateError, IndexOf, RelayChain, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -69,6 +70,12 @@ impl Chain for Rialto { type WeightToFee = bp_rialto::WeightToFee; } +impl RelayChain for Rialto { + const PARAS_PALLET_NAME: &'static str = bp_rialto::PARAS_PALLET_NAME; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = + bp_rialto::WITH_RIALTO_BRIDGE_PARAS_PALLET_NAME; +} + impl ChainWithGrandpa for Rialto { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME; } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index a55fa64d850ce..f4a2fcf262fd1 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -64,6 +64,20 @@ pub trait Chain: ChainBase + Clone { type WeightToFee: WeightToFeePolynomial; } +/// Substrate-based relay chain that supports parachains. +/// +/// We assume that the parachains are supported using `runtime_parachains::paras` pallet. +pub trait RelayChain: Chain { + /// Name of the `runtime_parachains::paras` pallet in the runtime of this chain. + const PARAS_PALLET_NAME: &'static str; + /// Name of the bridge parachains pallet (used in `construct_runtime` macro call) that is + /// deployed at the **bridged** chain. + /// + /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using + /// the same name. + const PARACHAINS_FINALITY_PALLET_NAME: &'static str; +} + /// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of /// view. /// diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index a0426b99f95ae..0f9445a8d35ae 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -262,6 +262,11 @@ impl Client { Ok(*self.header_by_hash(self.best_finalized_header_hash().await?).await?.number()) } + /// Return header of the best finalized block. + pub async fn best_finalized_header(&self) -> Result { + self.header_by_hash(self.best_finalized_header_hash().await?).await + } + /// Returns the best Substrate header. pub async fn best_header(&self) -> Result where diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index d6cab3dd91bbc..0234459f9d7d5 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -33,8 +33,8 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, SignParam, TransactionSignScheme, TransactionStatusOf, - UnsignedTransaction, WeightToFeeOf, + ChainWithGrandpa, ChainWithMessages, RelayChain, SignParam, TransactionSignScheme, + TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, }, client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 374ab915166ab..73dedb3a33497 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -28,9 +28,8 @@ pub mod messages_lane; pub mod messages_metrics; pub mod messages_source; pub mod messages_target; -pub mod on_demand_headers; -pub mod parachains_source; -pub mod parachains_target; +pub mod on_demand; +pub mod parachains; /// Default relay loop stall timeout. If transactions generated by relay are immortal, then /// this timeout is used. diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index fadf5e62245ad..9d6a6f4862f18 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -21,10 +21,11 @@ use crate::{ messages_metrics::StandaloneMessagesMetrics, messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, - on_demand_headers::OnDemandHeadersRelay, + on_demand::OnDemandRelay, TransactionParams, STALL_TIMEOUT, }; +use async_std::sync::Arc; use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{AccountIdOf, Chain as _}; use bridge_runtime_common::messages::{ @@ -135,9 +136,11 @@ pub struct MessagesRelayParams { pub target_transaction_params: TransactionParams>, /// Optional on-demand source to target headers relay. - pub source_to_target_headers_relay: Option>, + pub source_to_target_headers_relay: + Option>>>, /// Optional on-demand target to source headers relay. - pub target_to_source_headers_relay: Option>, + pub target_to_source_headers_relay: + Option>>>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, /// Metrics parameters. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 77dd2aed05bcd..9c447c6b8354c 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -23,10 +23,11 @@ use crate::{ MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, }, messages_target::SubstrateMessagesDeliveryProof, - on_demand_headers::OnDemandHeadersRelay, + on_demand::OnDemandRelay, TransactionParams, }; +use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::{operating_mode_key, outbound_lane_data_key}, @@ -66,7 +67,7 @@ pub struct SubstrateMessagesSource { target_client: Client, lane_id: LaneId, transaction_params: TransactionParams>, - target_to_source_headers_relay: Option>, + target_to_source_headers_relay: Option>>>, } impl SubstrateMessagesSource

{ @@ -76,7 +77,9 @@ impl SubstrateMessagesSource

{ target_client: Client, lane_id: LaneId, transaction_params: TransactionParams>, - target_to_source_headers_relay: Option>, + target_to_source_headers_relay: Option< + Arc>>, + >, ) -> Self { SubstrateMessagesSource { source_client, @@ -282,7 +285,7 @@ where async fn require_target_header_on_source(&self, id: TargetHeaderIdOf>) { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { - target_to_source_headers_relay.require_finalized_header(id).await; + target_to_source_headers_relay.require_more_headers(id.0).await; } } @@ -424,18 +427,13 @@ where let self_best_id = HeaderId(*self_best_header.number(), self_best_hash); // now let's read id of best finalized peer header at our best finalized block - let encoded_best_finalized_peer_on_self = self_client - .state_call( - best_finalized_header_id_method_name.into(), - Bytes(Vec::new()), - Some(self_best_hash), + let peer_on_self_best_finalized_id = + best_finalized_peer_header_at_self::( + self_client, + self_best_hash, + best_finalized_header_id_method_name, ) .await?; - let decoded_best_finalized_peer_on_self: (BlockNumberOf, HashOf) = - Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; - let peer_on_self_best_finalized_id = - HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); // read actual header, matching the `peer_on_self_best_finalized_id` from the peer chain let actual_peer_on_self_best_finalized_id = match peer_client { @@ -455,6 +453,35 @@ where }) } +/// Reads best `PeerChain` header known to the `SelfChain` using provided runtime API method. +/// +/// Method is supposed to be the `FinalityApi::best_finalized()` method. +pub async fn best_finalized_peer_header_at_self( + self_client: &Client, + at_self_hash: HashOf, + best_finalized_header_id_method_name: &str, +) -> Result, SubstrateError> +where + SelfChain: Chain, + PeerChain: Chain, +{ + // now let's read id of best finalized peer header at our best finalized block + let encoded_best_finalized_peer_on_self = self_client + .state_call( + best_finalized_header_id_method_name.into(), + Bytes(Vec::new()), + Some(at_self_hash), + ) + .await?; + let decoded_best_finalized_peer_on_self: (BlockNumberOf, HashOf) = + Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; + let peer_on_self_best_finalized_id = + HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); + + Ok(peer_on_self_best_finalized_id) +} + fn make_message_details_map( weights: Vec>, nonces: RangeInclusive, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 687d5163cb20d..08604e66b72a9 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -22,10 +22,11 @@ use crate::{ messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, messages_metrics::StandaloneMessagesMetrics, messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, - on_demand_headers::OnDemandHeadersRelay, + on_demand::OnDemandRelay, TransactionParams, }; +use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::inbound_lane_data_key, total_unrewarded_messages, InboundLaneData, LaneId, @@ -42,7 +43,7 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, WeightToFeeOf, }; @@ -63,7 +64,7 @@ pub struct SubstrateMessagesTarget { relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, - source_to_target_headers_relay: Option>, + source_to_target_headers_relay: Option>>>, } impl SubstrateMessagesTarget

{ @@ -75,7 +76,9 @@ impl SubstrateMessagesTarget

{ relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, - source_to_target_headers_relay: Option>, + source_to_target_headers_relay: Option< + Arc>>, + >, ) -> Self { SubstrateMessagesTarget { target_client, @@ -269,7 +272,7 @@ where async fn require_source_header_on_target(&self, id: SourceHeaderIdOf>) { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { - source_to_target_headers_relay.require_finalized_header(id).await; + source_to_target_headers_relay.require_more_headers(id.0).await; } } diff --git a/relays/lib-substrate-relay/src/on_demand_headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs similarity index 96% rename from relays/lib-substrate-relay/src/on_demand_headers.rs rename to relays/lib-substrate-relay/src/on_demand/headers.rs index 915e04f08778e..3d007de4dbf64 100644 --- a/relays/lib-substrate-relay/src/on_demand_headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -14,15 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! On-demand Substrate -> Substrate headers relay. +//! On-demand Substrate -> Substrate header finality relay. use async_std::sync::{Arc, Mutex}; +use async_trait::async_trait; use futures::{select, FutureExt}; use num_traits::{One, Zero}; use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderIdOf, HeaderOf, SyncHeader, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderOf, SyncHeader, TransactionSignScheme, }; use relay_utils::{ @@ -35,10 +36,11 @@ use crate::{ target::SubstrateFinalityTarget, SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT, }, + on_demand::OnDemandRelay, TransactionParams, STALL_TIMEOUT, }; -/// On-demand Substrate <-> Substrate headers relay. +/// On-demand Substrate <-> Substrate header finality relay. /// /// This relay may be requested to sync more headers, whenever some other relay (e.g. messages /// relay) needs it to continue its regular work. When enough headers are relayed, on-demand stops @@ -82,20 +84,24 @@ impl OnDemandHeadersRelay { this } +} - /// Someone is asking us to relay given finalized header. - pub async fn require_finalized_header(&self, header_id: HeaderIdOf) { +#[async_trait] +impl OnDemandRelay> + for OnDemandHeadersRelay +{ + async fn require_more_headers(&self, required_header: BlockNumberOf) { let mut required_header_number = self.required_header_number.lock().await; - if header_id.0 > *required_header_number { + if required_header > *required_header_number { log::trace!( target: "bridge", "More {} headers required in {} relay. Going to sync up to the {}", SourceChain::NAME, self.relay_task_name, - header_id.0, + required_header, ); - *required_header_number = header_id.0; + *required_header_number = required_header; } } } diff --git a/relays/lib-substrate-relay/src/on_demand/mod.rs b/relays/lib-substrate-relay/src/on_demand/mod.rs new file mode 100644 index 0000000000000..7a2dfc9c1532f --- /dev/null +++ b/relays/lib-substrate-relay/src/on_demand/mod.rs @@ -0,0 +1,35 @@ +// 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 . + +//! Types and functions intended to ease adding of new Substrate -> Substrate +//! on-demand pipelines. + +use async_trait::async_trait; + +pub mod headers; +pub mod parachains; + +/// On-demand headers relay that is relaying finalizing headers only when requested. +#[async_trait] +pub trait OnDemandRelay: Send + Sync { + /// Ask relay to relay source header with given number to the target chain. + /// + /// Depending on implementation, on-demand relay may also relay `required_header` ancestors + /// (e.g. if they're mandatory), or its descendants. The request is considered complete if + /// the best avbailable header at the target chain has number that is larger than or equal + /// to the `required_header`. + async fn require_more_headers(&self, required_header: SourceHeaderNumber); +} diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs new file mode 100644 index 0000000000000..8f1bee352007c --- /dev/null +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -0,0 +1,797 @@ +// 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 . + +//! On-demand Substrate -> Substrate parachain finality relay. + +use crate::{ + messages_source::best_finalized_peer_header_at_self, + on_demand::OnDemandRelay, + parachains::{ + source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter, + SubstrateParachainsPipeline, + }, + TransactionParams, +}; + +use async_std::{ + channel::{unbounded, Receiver, Sender}, + sync::{Arc, Mutex}, +}; +use async_trait::async_trait; +use bp_polkadot_core::parachains::ParaHash; +use futures::{select, FutureExt}; +use num_traits::Zero; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use parachains_relay::parachains_loop::{ParachainSyncParams, TargetClient}; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, + TransactionSignScheme, +}; +use relay_utils::{ + metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, HeaderId, +}; +use sp_runtime::traits::Header as HeaderT; +use std::{cmp::Ordering, collections::BTreeMap}; + +/// On-demand Substrate <-> Substrate parachain finality relay. +/// +/// This relay may be requested to sync more parachain headers, whenever some other relay +/// (e.g. messages relay) needs it to continue its regular work. When enough parachain headers +/// are relayed, on-demand stops syncing headers. +#[derive(Clone)] +pub struct OnDemandParachainsRelay { + /// Relay task name. + relay_task_name: String, + /// Channel used to communicate with background task and ask for relay of parachain heads. + required_header_number_sender: Sender>, +} + +impl OnDemandParachainsRelay { + /// Create new on-demand parachains relay. + /// + /// Note that the argument is the source relay chain client, not the parachain client. + /// That's because parachain finality is determined by the relay chain and we don't + /// need to connect to the parachain itself here. + pub fn new>( + source_relay_client: Client, + target_client: Client, + target_transaction_params: TransactionParams>, + on_demand_source_relay_to_target_headers: Arc< + dyn OnDemandRelay>, + >, + ) -> Self + where + P::SourceParachain: Chain, + P::SourceRelayChain: + Chain, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, + { + let (required_header_number_sender, required_header_number_receiver) = unbounded(); + let this = OnDemandParachainsRelay { + relay_task_name: on_demand_parachains_relay_name::(), + required_header_number_sender, + }; + async_std::task::spawn(async move { + background_task::

( + source_relay_client, + target_client, + target_transaction_params, + on_demand_source_relay_to_target_headers, + required_header_number_receiver, + ) + .await; + }); + + this + } +} + +#[async_trait] +impl OnDemandRelay> + for OnDemandParachainsRelay +where + SourceParachain: Chain, +{ + async fn require_more_headers(&self, required_header: BlockNumberOf) { + if let Err(e) = self.required_header_number_sender.send(required_header).await { + log::trace!( + target: "bridge", + "Failed to request {} header {:?} in {:?}: {:?}", + SourceParachain::NAME, + required_header, + self.relay_task_name, + e, + ); + } + } +} + +/// Background task that is responsible for starting parachain headers relay. +async fn background_task( + source_relay_client: Client, + target_client: Client, + target_transaction_params: TransactionParams>, + on_demand_source_relay_to_target_headers: Arc< + dyn OnDemandRelay>, + >, + required_parachain_header_number_receiver: Receiver>, +) where + P::SourceParachain: Chain, + P::SourceRelayChain: + Chain, + AccountIdOf: + From< as sp_core::Pair>::Public>, + P::TransactionSignScheme: TransactionSignScheme, +{ + let relay_task_name = on_demand_parachains_relay_name::(); + let target_transactions_mortality = target_transaction_params.mortality; + + let mut relay_state = RelayState::Idle; + let mut headers_map_cache = BTreeMap::new(); + let mut required_parachain_header_number = Zero::zero(); + let required_para_header_number_ref = Arc::new(Mutex::new(required_parachain_header_number)); + + let mut restart_relay = true; + let parachains_relay_task = futures::future::Fuse::terminated(); + futures::pin_mut!(parachains_relay_task); + + let mut parachains_source = ParachainsSource::

::new( + source_relay_client.clone(), + Some(required_para_header_number_ref.clone()), + ); + let mut parachains_target = + ParachainsTarget::

::new(target_client.clone(), target_transaction_params.clone()); + + loop { + select! { + new_required_parachain_header_number = required_parachain_header_number_receiver.recv().fuse() => { + let new_required_parachain_header_number = match new_required_parachain_header_number { + Ok(new_required_parachain_header_number) => new_required_parachain_header_number, + Err(e) => { + log::error!( + target: "bridge", + "Background task of {} has exited with error: {:?}", + relay_task_name, + e, + ); + + return; + }, + }; + + // keep in mind that we are not updating `required_para_header_number_ref` here, because + // then we'll be submitting all previous headers as well (while required relay headers are + // delivered) and we want to avoid that (to reduce cost) + required_parachain_header_number = std::cmp::max( + required_parachain_header_number, + new_required_parachain_header_number, + ); + }, + _ = parachains_relay_task => { + // this should never happen in practice given the current code + restart_relay = true; + }, + } + + // the workflow of the on-demand parachains relay is: + // + // 1) message relay (or any other dependent relay) sees new message at parachain header + // `PH`; 2) it sees that the target chain does not know `PH`; + // 3) it asks on-demand parachains relay to relay `PH` to the target chain; + // + // Phase#1: relaying relay chain header + // + // 4) on-demand parachains relay waits for GRANDPA-finalized block of the source relay chain + // `RH` that is storing `PH` or its descendant. Let it be `PH'`; + // 5) it asks on-demand headers relay to relay `RH` to the target chain; + // 6) it waits until `RH` (or its descendant) is relayed to the target chain; + // + // Phase#2: relaying parachain header + // + // 7) on-demand parachains relay sets `ParachainsSource::maximal_header_number` to the + // `PH'.number()`. 8) parachains finality relay sees that the parachain head has been + // updated and relays `PH'` to the target chain. + + // select headers to relay + let relay_data = read_relay_data( + ¶chains_source, + ¶chains_target, + required_parachain_header_number, + &mut headers_map_cache, + ) + .await; + match relay_data { + Ok(mut relay_data) => { + let prev_relay_state = relay_state; + relay_state = select_headers_to_relay(&mut relay_data, relay_state); + log::trace!( + target: "bridge", + "Selected new relay state in {}: {:?} using old state {:?} and data {:?}", + relay_task_name, + relay_state, + prev_relay_state, + relay_data, + ); + }, + Err(failed_client) => { + relay_utils::relay_loop::reconnect_failed_client( + failed_client, + relay_utils::relay_loop::RECONNECT_DELAY, + &mut parachains_source, + &mut parachains_target, + ) + .await; + continue + }, + } + + // we have selected our new 'state' => let's notify our source clients about our new + // requirements + match relay_state { + RelayState::Idle => (), + RelayState::RelayingRelayHeader(required_relay_header, _) => { + on_demand_source_relay_to_target_headers + .require_more_headers(required_relay_header) + .await; + }, + RelayState::RelayingParaHeader(required_para_header) => { + *required_para_header_number_ref.lock().await = required_para_header; + }, + } + + // start/restart relay + if restart_relay { + let stall_timeout = relay_substrate_client::transaction_stall_timeout( + target_transactions_mortality, + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + crate::STALL_TIMEOUT, + ); + + log::info!( + target: "bridge", + "Starting {} relay\n\t\ + Tx mortality: {:?} (~{}m)\n\t\ + Stall timeout: {:?}", + relay_task_name, + target_transactions_mortality, + stall_timeout.as_secs_f64() / 60.0f64, + stall_timeout, + ); + + parachains_relay_task.set( + parachains_relay::parachains_loop::run( + parachains_source.clone(), + parachains_target.clone(), + ParachainSyncParams { + parachains: vec![P::SOURCE_PARACHAIN_PARA_ID.into()], + stall_timeout: std::time::Duration::from_secs(60), + strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, + }, + MetricsParams::disabled(), + futures::future::pending(), + ) + .fuse(), + ); + + restart_relay = false; + } + } +} + +/// On-demand parachains relay task name. +fn on_demand_parachains_relay_name() -> String { + format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) +} + +/// On-demand relay state. +#[derive(Clone, Copy, Debug, PartialEq)] +enum RelayState { + /// On-demand relay is not doing anything. + Idle, + /// Relaying given relay header to relay given parachain header later. + RelayingRelayHeader(SourceRelayBlock, SourceParaBlock), + /// Relaying given parachain header. + RelayingParaHeader(SourceParaBlock), +} + +/// Data gathered from source and target clients, used by on-demand relay. +#[derive(Debug)] +struct RelayData<'a, SourceParaBlock, SourceRelayBlock> { + /// Parachain header number that is required at the target chain. + pub required_para_header: SourceParaBlock, + /// Parachain header number, known to the target chain. + pub para_header_at_target: SourceParaBlock, + /// Parachain header number, known to the source (relay) chain. + pub para_header_at_source: Option, + /// Relay header number at the source chain. + pub relay_header_at_source: SourceRelayBlock, + /// Relay header number at the target chain. + pub relay_header_at_target: SourceRelayBlock, + /// Map of relay to para header block numbers for recent relay headers. + /// + /// Even if we have been trying to relay relay header #100 to relay parachain header #50 + /// afterwards, it may happen that the relay header #200 may be relayed instead - either + /// by us (e.g. if GRANDPA justification is generated for #200, or if we are only syncing + /// mandatory headers), or by other relayer. Then, instead of parachain header #50 we may + /// relay parachain header #70. + /// + /// This cache is especially important, given that we assume that the nodes we're connected + /// to are not necessarily archive nodes. Then, if current relay chain block is #210 and #200 + /// has been delivered to the target chain, we have more chances to generate storage proof + /// at relay block #200 than on relay block #100, which is most likely has pruned state + /// already. + pub headers_map_cache: &'a mut BTreeMap, +} + +/// Read required data from source and target clients. +async fn read_relay_data<'a, P: SubstrateParachainsPipeline>( + source: &ParachainsSource

, + target: &ParachainsTarget

, + required_header_number: BlockNumberOf, + headers_map_cache: &'a mut BTreeMap< + BlockNumberOf, + BlockNumberOf, + >, +) -> Result< + RelayData<'a, BlockNumberOf, BlockNumberOf>, + FailedClient, +> +where + ParachainsTarget

: + TargetClient> + RelayClient, +{ + let map_target_err = |e| { + log::error!( + target: "bridge", + "Failed to read {} relay data from {} client: {:?}", + on_demand_parachains_relay_name::(), + P::TargetChain::NAME, + e, + ); + FailedClient::Target + }; + let map_source_err = |e| { + log::error!( + target: "bridge", + "Failed to read {} relay data from {} client: {:?}", + on_demand_parachains_relay_name::(), + P::SourceRelayChain::NAME, + e, + ); + FailedClient::Source + }; + + let best_target_block_hash = target.best_block().await.map_err(map_target_err)?.1; + let para_header_at_target = + best_finalized_peer_header_at_self::( + target.client(), + best_target_block_hash, + P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD, + ) + .await + .map_err(map_target_err)? + .0; + + let best_finalized_relay_header = + source.client().best_finalized_header().await.map_err(map_source_err)?; + let best_finalized_relay_block_id = + HeaderId(*best_finalized_relay_header.number(), best_finalized_relay_header.hash()); + let para_header_at_source = source + .on_chain_parachain_header( + best_finalized_relay_block_id, + P::SOURCE_PARACHAIN_PARA_ID.into(), + ) + .await + .map_err(map_source_err)? + .map(|h| *h.number()); + + let relay_header_at_source = best_finalized_relay_block_id.0; + let relay_header_at_target = + best_finalized_peer_header_at_self::( + target.client(), + best_target_block_hash, + P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) + .await + .map_err(map_target_err)? + .0; + + Ok(RelayData { + required_para_header: required_header_number, + para_header_at_target, + para_header_at_source, + relay_header_at_source, + relay_header_at_target, + headers_map_cache, + }) +} + +// This number is bigger than the session length of any well-known Substrate-based relay +// chain. We expect that the underlying on-demand relay will submit at least 1 header per +// session. +const MAX_HEADERS_MAP_CACHE_ENTRIES: usize = 4096; + +/// Select relay and parachain headers that need to be relayed. +fn select_headers_to_relay<'a, SourceParaBlock, SourceRelayBlock>( + data: &mut RelayData<'a, SourceParaBlock, SourceRelayBlock>, + mut state: RelayState, +) -> RelayState +where + RelayData<'a, SourceParaBlock, SourceRelayBlock>: std::fmt::Debug, // TODO: remove + SourceParaBlock: Copy + PartialOrd, + SourceRelayBlock: Copy + Ord, +{ + // despite of our current state, we want to update the headers map cache + if let Some(para_header_at_source) = data.para_header_at_source { + data.headers_map_cache + .insert(data.relay_header_at_source, para_header_at_source); + if data.headers_map_cache.len() > MAX_HEADERS_MAP_CACHE_ENTRIES { + let first_key = *data.headers_map_cache.keys().next().expect("map is not empty; qed"); + data.headers_map_cache.remove(&first_key); + } + } + + // this switch is responsible for processing `RelayingRelayHeader` state + match state { + RelayState::Idle | RelayState::RelayingParaHeader(_) => (), + RelayState::RelayingRelayHeader(relay_header_number, para_header_number) => { + match data.relay_header_at_target.cmp(&relay_header_number) { + Ordering::Less => { + // relay header hasn't yet been relayed + return RelayState::RelayingRelayHeader(relay_header_number, para_header_number) + }, + Ordering::Equal => { + // relay header has been realyed and we may continue with parachain header + state = RelayState::RelayingParaHeader(para_header_number); + }, + Ordering::Greater => { + // relay header descendant has been relayed and we may need to change parachain + // header that we want to relay + let next_para_header_number = data + .headers_map_cache + .range(..=data.relay_header_at_target) + .next_back() + .map(|(_, next_para_header_number)| *next_para_header_number) + .unwrap_or_else(|| para_header_number); + state = RelayState::RelayingParaHeader(next_para_header_number); + }, + } + }, + } + + // this switch is responsible for processing `RelayingParaHeader` state + match state { + RelayState::Idle => (), + RelayState::RelayingRelayHeader(_, _) => unreachable!("processed by previous match; qed"), + RelayState::RelayingParaHeader(para_header_number) => { + if data.para_header_at_target < para_header_number { + // parachain header hasn't yet been relayed + return RelayState::RelayingParaHeader(para_header_number) + } + }, + } + + // if we have already satisfied our "customer", do nothing + if data.required_para_header <= data.para_header_at_target { + return RelayState::Idle + } + + // if required header is not available even at the source chain, let's wait + if Some(data.required_para_header) > data.para_header_at_source { + return RelayState::Idle + } + + // we will always try to sync latest parachain/relay header, even if we've been asked for some + // its ancestor + + // we need relay chain header first + if data.relay_header_at_target < data.relay_header_at_source { + return RelayState::RelayingRelayHeader( + data.relay_header_at_source, + data.required_para_header, + ) + } + + // if all relay headers synced, we may start directly with parachain header + RelayState::RelayingParaHeader(data.required_para_header) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn relay_waits_for_relay_header_to_be_delivered() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::RelayingRelayHeader(750, 100), + ), + RelayState::RelayingRelayHeader(750, 100), + ); + } + + #[test] + fn relay_starts_relaying_requested_para_header_after_relay_header_is_delivered() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 750, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::RelayingRelayHeader(750, 100), + ), + RelayState::RelayingParaHeader(100), + ); + } + + #[test] + fn relay_selects_same_para_header_after_better_relay_header_is_delivered_1() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 780, + headers_map_cache: &mut vec![(700, 90), (750, 100)].into_iter().collect(), + }, + RelayState::RelayingRelayHeader(750, 100), + ), + RelayState::RelayingParaHeader(100), + ); + } + + #[test] + fn relay_selects_same_para_header_after_better_relay_header_is_delivered_2() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 780, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::RelayingRelayHeader(750, 100), + ), + RelayState::RelayingParaHeader(100), + ); + } + + #[test] + fn relay_selects_better_para_header_after_better_relay_header_is_delivered() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 50, + para_header_at_source: Some(120), + relay_header_at_source: 800, + relay_header_at_target: 780, + headers_map_cache: &mut vec![(700, 90), (750, 100), (780, 110), (790, 120)] + .into_iter() + .collect(), + }, + RelayState::RelayingRelayHeader(750, 100), + ), + RelayState::RelayingParaHeader(110), + ); + } + + #[test] + fn relay_waits_for_para_header_to_be_delivered() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::RelayingParaHeader(100), + ), + RelayState::RelayingParaHeader(100), + ); + } + + #[test] + fn relay_stays_idle_if_required_para_header_is_already_delivered() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 100, + para_header_at_target: 100, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::Idle, + ), + RelayState::Idle, + ); + } + + #[test] + fn relay_waits_for_required_para_header_to_appear_at_source_1() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 110, + para_header_at_target: 100, + para_header_at_source: None, + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::Idle, + ), + RelayState::Idle, + ); + } + + #[test] + fn relay_waits_for_required_para_header_to_appear_at_source_2() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 110, + para_header_at_target: 100, + para_header_at_source: Some(100), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::Idle, + ), + RelayState::Idle, + ); + } + + #[test] + fn relay_starts_relaying_relay_header_when_new_para_header_is_requested() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 110, + para_header_at_target: 100, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::Idle, + ), + RelayState::RelayingRelayHeader(800, 110), + ); + } + + #[test] + fn relay_starts_relaying_para_header_when_new_para_header_is_requested() { + assert_eq!( + select_headers_to_relay( + &mut RelayData { + required_para_header: 110, + para_header_at_target: 100, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 800, + headers_map_cache: &mut BTreeMap::new(), + }, + RelayState::Idle, + ), + RelayState::RelayingParaHeader(110), + ); + } + + #[test] + fn headers_map_cache_is_updated() { + let mut headers_map_cache = BTreeMap::new(); + + // when parachain header is known, map is updated + select_headers_to_relay( + &mut RelayData { + required_para_header: 0, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut headers_map_cache, + }, + RelayState::RelayingRelayHeader(750, 100), + ); + assert_eq!(headers_map_cache.clone().into_iter().collect::>(), vec![(800, 110)],); + + // when parachain header is not known, map is NOT updated + select_headers_to_relay( + &mut RelayData { + required_para_header: 0, + para_header_at_target: 50, + para_header_at_source: None, + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut headers_map_cache, + }, + RelayState::RelayingRelayHeader(750, 100), + ); + assert_eq!(headers_map_cache.clone().into_iter().collect::>(), vec![(800, 110)],); + + // map auto-deduplicates equal entries + select_headers_to_relay( + &mut RelayData { + required_para_header: 0, + para_header_at_target: 50, + para_header_at_source: Some(110), + relay_header_at_source: 800, + relay_header_at_target: 700, + headers_map_cache: &mut headers_map_cache, + }, + RelayState::RelayingRelayHeader(750, 100), + ); + assert_eq!(headers_map_cache.clone().into_iter().collect::>(), vec![(800, 110)],); + + // nothing is pruned if number of map entries is < MAX_HEADERS_MAP_CACHE_ENTRIES + for i in 1..MAX_HEADERS_MAP_CACHE_ENTRIES { + select_headers_to_relay( + &mut RelayData { + required_para_header: 0, + para_header_at_target: 50, + para_header_at_source: Some(110 + i), + relay_header_at_source: 800 + i, + relay_header_at_target: 700, + headers_map_cache: &mut headers_map_cache, + }, + RelayState::RelayingRelayHeader(750, 100), + ); + assert_eq!(headers_map_cache.len(), i + 1); + } + + // when we add next entry, the oldest one is pruned + assert!(headers_map_cache.contains_key(&800)); + assert_eq!(headers_map_cache.len(), MAX_HEADERS_MAP_CACHE_ENTRIES); + select_headers_to_relay( + &mut RelayData { + required_para_header: 0, + para_header_at_target: 50, + para_header_at_source: Some(110 + MAX_HEADERS_MAP_CACHE_ENTRIES), + relay_header_at_source: 800 + MAX_HEADERS_MAP_CACHE_ENTRIES, + relay_header_at_target: 700, + headers_map_cache: &mut headers_map_cache, + }, + RelayState::RelayingRelayHeader(750, 100), + ); + assert!(!headers_map_cache.contains_key(&800)); + assert_eq!(headers_map_cache.len(), MAX_HEADERS_MAP_CACHE_ENTRIES); + } +} diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/relays/lib-substrate-relay/src/parachains/mod.rs new file mode 100644 index 0000000000000..ef14b7bb10322 --- /dev/null +++ b/relays/lib-substrate-relay/src/parachains/mod.rs @@ -0,0 +1,110 @@ +// 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 . + +//! Types and functions intended to ease adding of new Substrate -> Substrate +//! parachain finality proofs synchronization pipelines. + +use async_trait::async_trait; +use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; +use pallet_bridge_parachains::{ + Call as BridgeParachainsCall, Config as BridgeParachainsConfig, RelayBlockHash, + RelayBlockHasher, RelayBlockNumber, +}; +use parachains_relay::ParachainsPipeline; +use relay_substrate_client::{CallOf, Chain, HashOf, RelayChain, TransactionSignScheme}; +use std::{fmt::Debug, marker::PhantomData}; + +pub mod source; +pub mod target; + +/// Substrate -> Substrate parachain finality proofs synchronization pipeline. +/// +/// This is currently restricted to the single parachain, because it is how it +/// will be used (at least) initially. +#[async_trait] +pub trait SubstrateParachainsPipeline: 'static + Clone + Debug + Send + Sync { + /// Headers of this parachain are submitted to the `Self::TargetChain`. + type SourceParachain: Chain; + /// Relay chain that is storing headers of `Self::SourceParachain`. + type SourceRelayChain: RelayChain; + /// Target chain where `Self::SourceParachain` headers are submitted. + type TargetChain: Chain; + + /// How submit parachains heads call is built? + type SubmitParachainHeadsCallBuilder: SubmitParachainHeadsCallBuilder; + /// Scheme used to sign target chain transactions. + type TransactionSignScheme: TransactionSignScheme; + + /// Id of the `Self::SourceParachain`, used for registration in `Self::SourceRelayChain`. + const SOURCE_PARACHAIN_PARA_ID: u32; +} + +/// Adapter that allows all `SubstrateParachainsPipeline` to act as `ParachainsPipeline`. +#[derive(Clone, Debug)] +pub struct ParachainsPipelineAdapter { + _phantom: PhantomData

, +} + +impl ParachainsPipeline for ParachainsPipelineAdapter

{ + type SourceChain = P::SourceRelayChain; + type TargetChain = P::TargetChain; +} + +/// Different ways of building `submit_parachain_heads` calls. +pub trait SubmitParachainHeadsCallBuilder: + 'static + Send + Sync +{ + /// Given parachains and their heads proof, build call of `submit_parachain_heads` + /// function of bridge parachains module at the target chain. + fn build_submit_parachain_heads_call( + relay_block_hash: HashOf, + parachains: Vec, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf; +} + +/// Building `submit_parachain_heads` call when you have direct access to the target +/// chain runtime. +pub struct DirectSubmitParachainHeadsCallBuilder { + _phantom: PhantomData<(P, R, I)>, +} + +impl SubmitParachainHeadsCallBuilder

for DirectSubmitParachainHeadsCallBuilder +where + P: SubstrateParachainsPipeline, + P::SourceRelayChain: Chain, + R: BridgeParachainsConfig + Send + Sync, + I: 'static + Send + Sync, + R::BridgedChain: bp_runtime::Chain< + BlockNumber = RelayBlockNumber, + Hash = RelayBlockHash, + Hasher = RelayBlockHasher, + >, + CallOf: From>, +{ + fn build_submit_parachain_heads_call( + relay_block_hash: HashOf, + parachains: Vec, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + BridgeParachainsCall::::submit_parachain_heads { + relay_block_hash, + parachains, + parachain_heads_proof, + } + .into() + } +} diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs new file mode 100644 index 0000000000000..3ae735ab8930f --- /dev/null +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -0,0 +1,163 @@ +// 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 . + +//! Parachain heads source. + +use crate::{ + finality::source::RequiredHeaderNumberRef, + parachains::{ParachainsPipelineAdapter, SubstrateParachainsPipeline}, +}; + +use async_std::sync::{Arc, Mutex}; +use async_trait::async_trait; +use bp_parachains::parachain_head_storage_key_at_source; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use codec::Decode; +use parachains_relay::parachains_loop::SourceClient; +use relay_substrate_client::{ + Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, RelayChain, +}; +use relay_utils::relay_loop::Client as RelayClient; +use sp_runtime::traits::Header as HeaderT; + +/// Substrate client as parachain heads source. +#[derive(Clone)] +pub struct ParachainsSource { + client: Client, + maximal_header_number: Option>, + previous_parachain_head: Arc>>, +} + +impl ParachainsSource

{ + /// Creates new parachains source client. + pub fn new( + client: Client, + maximal_header_number: Option>, + ) -> Self { + let previous_parachain_head = Arc::new(Mutex::new(None)); + ParachainsSource { client, maximal_header_number, previous_parachain_head } + } + + /// Returns reference to the underlying RPC client. + pub fn client(&self) -> &Client { + &self.client + } + + /// Return decoded head of given parachain. + pub async fn on_chain_parachain_header( + &self, + at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result>, SubstrateError> { + let storage_key = + parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, para_id); + let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?; + let para_head = para_head.map(|h| ParaHead::decode(&mut &h.0[..])).transpose()?; + let para_head = match para_head { + Some(para_head) => para_head, + None => return Ok(None), + }; + + Ok(Some(Decode::decode(&mut ¶_head.0[..])?)) + } +} + +#[async_trait] +impl RelayClient for ParachainsSource

{ + type Error = SubstrateError; + + async fn reconnect(&mut self) -> Result<(), SubstrateError> { + self.client.reconnect().await + } +} + +#[async_trait] +impl SourceClient> + for ParachainsSource

+where + P::SourceParachain: Chain, +{ + async fn ensure_synced(&self) -> Result { + match self.client.ensure_synced().await { + Ok(_) => Ok(true), + Err(SubstrateError::ClientNotSynced(_)) => Ok(false), + Err(e) => Err(e), + } + } + + async fn parachain_head( + &self, + at_block: HeaderIdOf, + para_id: ParaId, + ) -> Result, Self::Error> { + // we don't need to support many parachains now + if para_id.0 != P::SOURCE_PARACHAIN_PARA_ID { + return Err(SubstrateError::Custom(format!( + "Parachain id {} is not matching expected {}", + para_id.0, + P::SOURCE_PARACHAIN_PARA_ID, + ))) + } + + let parachain_head = match self.on_chain_parachain_header(at_block, para_id).await? { + Some(parachain_header) => { + let mut parachain_head = Some(parachain_header.hash()); + // never return head that is larger than requested. This way we'll never sync + // headers past `maximal_header_number` + if let Some(ref maximal_header_number) = self.maximal_header_number { + let maximal_header_number = *maximal_header_number.lock().await; + if *parachain_header.number() > maximal_header_number { + let previous_parachain_head = *self.previous_parachain_head.lock().await; + if let Some(previous_parachain_head) = previous_parachain_head { + parachain_head = Some(previous_parachain_head); + } + } + } + + parachain_head + }, + None => None, + }; + + *self.previous_parachain_head.lock().await = parachain_head; + + Ok(parachain_head) + } + + async fn prove_parachain_heads( + &self, + at_block: HeaderIdOf, + parachains: &[ParaId], + ) -> Result { + let storage_keys = parachains + .iter() + .map(|para_id| { + parachain_head_storage_key_at_source( + P::SourceRelayChain::PARAS_PALLET_NAME, + *para_id, + ) + }) + .collect(); + let parachain_heads_proof = self + .client + .prove_storage(storage_keys, at_block.1) + .await? + .iter_nodes() + .collect(); + + Ok(parachain_heads_proof) + } +} diff --git a/relays/lib-substrate-relay/src/parachains_target.rs b/relays/lib-substrate-relay/src/parachains/target.rs similarity index 50% rename from relays/lib-substrate-relay/src/parachains_target.rs rename to relays/lib-substrate-relay/src/parachains/target.rs index ed0456c06f216..3a4e0b2c27fe8 100644 --- a/relays/lib-substrate-relay/src/parachains_target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -16,112 +16,58 @@ //! Parachain heads target. -use crate::TransactionParams; +use crate::{ + parachains::{ + ParachainsPipelineAdapter, SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, + }, + TransactionParams, +}; use async_trait::async_trait; use bp_parachains::{parachain_head_storage_key_at_target, BestParaHeadHash}; use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; use codec::{Decode, Encode}; -use pallet_bridge_parachains::{ - Call as BridgeParachainsCall, Config as BridgeParachainsConfig, RelayBlockHash, - RelayBlockHasher, RelayBlockNumber, -}; -use parachains_relay::{parachains_loop::TargetClient, ParachainsPipeline}; +use parachains_relay::parachains_loop::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError, - HashOf, HeaderIdOf, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, + HeaderIdOf, RelayChain, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; use sp_runtime::traits::Header as HeaderT; -use std::marker::PhantomData; - -/// Different ways of building `submit_parachain_heads` calls. -pub trait SubmitParachainHeadsCallBuilder: 'static + Send + Sync { - /// Given parachains and their heads proof, build call of `submit_parachain_heads` - /// function of bridge parachains module at the target chain. - fn build_submit_parachain_heads_call( - relay_block_hash: HashOf, - parachains: Vec, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf; -} - -/// Building `submit_parachain_heads` call when you have direct access to the target -/// chain runtime. -pub struct DirectSubmitParachainHeadsCallBuilder { - _phantom: PhantomData<(P, R, I)>, -} - -impl SubmitParachainHeadsCallBuilder

for DirectSubmitParachainHeadsCallBuilder -where - P: ParachainsPipeline, - P::SourceChain: Chain, - R: BridgeParachainsConfig + Send + Sync, - I: 'static + Send + Sync, - R::BridgedChain: bp_runtime::Chain< - BlockNumber = RelayBlockNumber, - Hash = RelayBlockHash, - Hasher = RelayBlockHasher, - >, - CallOf: From>, -{ - fn build_submit_parachain_heads_call( - relay_block_hash: HashOf, - parachains: Vec, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - BridgeParachainsCall::::submit_parachain_heads { - relay_block_hash, - parachains, - parachain_heads_proof, - } - .into() - } -} /// Substrate client as parachain heads source. -pub struct ParachainsTarget { +pub struct ParachainsTarget { client: Client, - transaction_params: TransactionParams>, - bridge_paras_pallet_name: String, - _phantom: PhantomData, + transaction_params: TransactionParams>, } -impl ParachainsTarget { +impl ParachainsTarget

{ /// Creates new parachains target client. pub fn new( client: Client, - transaction_params: TransactionParams>, - bridge_paras_pallet_name: String, + transaction_params: TransactionParams>, ) -> Self { - ParachainsTarget { - client, - transaction_params, - bridge_paras_pallet_name, - _phantom: Default::default(), - } + ParachainsTarget { client, transaction_params } + } + + /// Returns reference to the underlying RPC client. + pub fn client(&self) -> &Client { + &self.client } } -impl Clone for ParachainsTarget { +impl Clone for ParachainsTarget

{ fn clone(&self) -> Self { ParachainsTarget { client: self.client.clone(), transaction_params: self.transaction_params.clone(), - bridge_paras_pallet_name: self.bridge_paras_pallet_name.clone(), - _phantom: Default::default(), } } } #[async_trait] -impl< - P: ParachainsPipeline, - S: 'static + TransactionSignScheme, - CB: SubmitParachainHeadsCallBuilder

, - > RelayClient for ParachainsTarget -{ +impl RelayClient for ParachainsTarget

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { @@ -130,12 +76,11 @@ impl< } #[async_trait] -impl TargetClient

for ParachainsTarget +impl

TargetClient> for ParachainsTarget

where - P: ParachainsPipeline, - S: 'static + TransactionSignScheme, - CB: SubmitParachainHeadsCallBuilder

, - AccountIdOf: From< as Pair>::Public>, + P: SubstrateParachainsPipeline, + P::TransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, { async fn best_block(&self) -> Result, Self::Error> { let best_header = self.client.best_header().await?; @@ -148,18 +93,18 @@ where async fn best_finalized_source_block( &self, at_block: &HeaderIdOf, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { let encoded_best_finalized_source_block = self .client .state_call( - P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), + P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), Bytes(Vec::new()), Some(at_block.1), ) .await?; let decoded_best_finalized_source_block: ( - BlockNumberOf, - HashOf, + BlockNumberOf, + HashOf, ) = Decode::decode(&mut &encoded_best_finalized_source_block.0[..]) .map_err(SubstrateError::ResponseParseFailed)?; Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1)) @@ -170,8 +115,10 @@ where at_block: HeaderIdOf, para_id: ParaId, ) -> Result, Self::Error> { - let storage_key = - parachain_head_storage_key_at_target(&self.bridge_paras_pallet_name, para_id); + let storage_key = parachain_head_storage_key_at_target( + P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, + para_id, + ); let para_head = self.client.storage_value(storage_key, Some(at_block.1)).await?; Ok(para_head) @@ -179,21 +126,24 @@ where async fn submit_parachain_heads_proof( &self, - at_relay_block: HeaderIdOf, + at_relay_block: HeaderIdOf, updated_parachains: Vec, proof: ParaHeadsProof, ) -> Result<(), Self::Error> { let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; - let call = - CB::build_submit_parachain_heads_call(at_relay_block.1, updated_parachains, proof); + let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( + at_relay_block.1, + updated_parachains, + proof, + ); self.client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { Ok(Bytes( - S::sign_transaction(SignParam { + P::TransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash, diff --git a/relays/lib-substrate-relay/src/parachains_source.rs b/relays/lib-substrate-relay/src/parachains_source.rs deleted file mode 100644 index 9e8d378d8bb8a..0000000000000 --- a/relays/lib-substrate-relay/src/parachains_source.rs +++ /dev/null @@ -1,91 +0,0 @@ -// 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 . - -//! Parachain heads source. - -use async_trait::async_trait; -use bp_parachains::parachain_head_storage_key_at_source; -use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; -use codec::Decode; -use parachains_relay::{parachains_loop::SourceClient, ParachainsPipeline}; -use relay_substrate_client::{Client, Error as SubstrateError, HeaderIdOf}; -use relay_utils::relay_loop::Client as RelayClient; - -/// Substrate client as parachain heads source. -#[derive(Clone)] -pub struct ParachainsSource { - client: Client, - paras_pallet_name: String, -} - -impl ParachainsSource

{ - /// Creates new parachains source client. - pub fn new(client: Client, paras_pallet_name: String) -> Self { - ParachainsSource { client, paras_pallet_name } - } -} - -#[async_trait] -impl RelayClient for ParachainsSource

{ - type Error = SubstrateError; - - async fn reconnect(&mut self) -> Result<(), SubstrateError> { - self.client.reconnect().await - } -} - -#[async_trait] -impl SourceClient

for ParachainsSource

{ - async fn ensure_synced(&self) -> Result { - match self.client.ensure_synced().await { - Ok(_) => Ok(true), - Err(SubstrateError::ClientNotSynced(_)) => Ok(false), - Err(e) => Err(e), - } - } - - async fn parachain_head( - &self, - at_block: HeaderIdOf, - para_id: ParaId, - ) -> Result, Self::Error> { - let storage_key = parachain_head_storage_key_at_source(&self.paras_pallet_name, para_id); - let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?; - let para_head = para_head.map(|h| ParaHead::decode(&mut &h.0[..])).transpose()?; - let para_hash = para_head.map(|h| h.hash()); - - Ok(para_hash) - } - - async fn prove_parachain_heads( - &self, - at_block: HeaderIdOf, - parachains: &[ParaId], - ) -> Result { - let storage_keys = parachains - .iter() - .map(|para_id| parachain_head_storage_key_at_source(&self.paras_pallet_name, *para_id)) - .collect(); - let parachain_heads_proof = self - .client - .prove_storage(storage_keys, at_block.1) - .await? - .iter_nodes() - .collect(); - - Ok(parachain_heads_proof) - } -} From 056f619b563b38742029b23923b01f784c03edb5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 May 2022 12:57:17 +0300 Subject: [PATCH 0691/1210] Fix clippy warnings + try to enable proper (no-warning) clippy on CI (#1410) * fix clippy warnings * try to reenable proper clippy on CI * fix clippy error * more Eqs * ignore clippy::derive-partial-eq-without-eq - clippy seems to be broken now :/ --- bin/millau/runtime/src/lib.rs | 4 +--- bin/rialto-parachain/node/src/chain_spec.rs | 4 +++- bin/rialto-parachain/runtime/src/lib.rs | 2 +- .../runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/lib.rs | 4 +--- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/xcm_config.rs | 3 +-- bin/runtime-common/src/messages.rs | 24 +++++++++---------- modules/grandpa/src/extension.rs | 6 ++--- primitives/header-chain/src/justification.rs | 2 +- primitives/header-chain/src/lib.rs | 2 +- primitives/messages/src/source_chain.rs | 4 ++-- primitives/runtime/src/storage_proof.rs | 2 +- relays/bin-substrate/src/cli/bridge.rs | 16 ++++++------- .../bin-substrate/src/cli/encode_message.rs | 6 ++--- .../src/cli/register_parachain.rs | 4 ++-- relays/bin-substrate/src/cli/reinit_bridge.rs | 4 ++-- .../bin-substrate/src/cli/relay_messages.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 1 + relays/client-millau/src/lib.rs | 2 +- relays/client-rialto/src/lib.rs | 2 +- relays/client-substrate/src/test_chain.rs | 2 +- relays/finality/src/finality_loop_tests.rs | 4 ++-- relays/messages/src/message_lane_loop.rs | 4 ++-- relays/parachains/src/parachains_loop.rs | 14 +++++------ relays/utils/src/lib.rs | 2 +- relays/utils/src/relay_loop.rs | 2 +- 27 files changed, 61 insertions(+), 65 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f032eec844db4..612a9e4364b75 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -283,9 +283,7 @@ parameter_types! { pub struct BeefyDummyDataProvider; impl beefy_primitives::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { - fn extra_data() -> () { - () - } + fn extra_data() {} } impl pallet_beefy_mmr::Config for Runtime { diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 6f52155817417..4a9bdaf9afd70 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -34,7 +34,9 @@ pub fn get_from_seed(seed: &str) -> ::Pu } /// The extensions for the [`ChainSpec`]. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +#[derive( + Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, +)] #[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index e35e78e9110b1..7110e5ba4fc46 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -301,7 +301,7 @@ parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = NetworkId::Polkadot; pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into()).into()); + pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); } /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 4e765000b90d0..8d88a4d44bcc9 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -101,7 +101,7 @@ impl MessageBridge for WithMillauMessageBridge { bridged_to_this_conversion_rate_override: Option, ) -> bp_rialto_parachain::Balance { let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(|| MillauToRialtoParachainConversionRate::get()); + .unwrap_or_else(MillauToRialtoParachainConversionRate::get); bp_rialto_parachain::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) .unwrap_or(bp_rialto_parachain::Balance::MAX) } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e87639f6cb2a8..82eb57f40ffa1 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -297,9 +297,7 @@ parameter_types! { pub struct BeefyDummyDataProvider; impl beefy_primitives::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { - fn extra_data() -> () { - () - } + fn extra_data() {} } impl pallet_beefy_mmr::Config for Runtime { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index ce1bd6b6fb0bc..fdc376be70e6e 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -96,7 +96,7 @@ impl MessageBridge for WithMillauMessageBridge { bridged_to_this_conversion_rate_override: Option, ) -> bp_rialto::Balance { let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(|| MillauToRialtoConversionRate::get()); + .unwrap_or_else(MillauToRialtoConversionRate::get); bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) .unwrap_or(bp_rialto::Balance::MAX) } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 8cad3896b1b4b..65ffc54a9f680 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -297,8 +297,7 @@ mod tests { let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, - } - .into(); + }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); assert_eq!(dispatch_weight, 1_000_000_000); diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 87dd009cff066..d302d35c85650 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -481,7 +481,7 @@ pub mod target { use super::*; /// Decoded Bridged -> This message payload. - #[derive(RuntimeDebug, PartialEq)] + #[derive(RuntimeDebug, PartialEq, Eq)] pub struct FromBridgedChainMessagePayload { /// Data that is actually sent over the wire. pub xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm), @@ -726,7 +726,7 @@ pub mod target { .map_err(Into::into) } - #[derive(Debug, PartialEq)] + #[derive(Debug, PartialEq, Eq)] pub(crate) enum MessageProofError { Empty, MessagesCountMismatch, @@ -944,7 +944,7 @@ pub mod xcm_copy { message: &mut Option>, ) -> Result<((Vec, XcmHash), MultiAssets), SendError> { let bridged_network = BridgedNetwork::get(); - ensure!(&network == &bridged_network, SendError::NotApplicable); + ensure!(network == bridged_network, SendError::NotApplicable); // We don't/can't use the `channel` for this adapter. let dest = destination.take().ok_or(SendError::MissingArgument)?; let universal_dest = match dest.pushed_front_with(GlobalConsensus(bridged_network)) { @@ -1030,13 +1030,13 @@ mod tests { } } - #[derive(Debug, PartialEq, Decode, Encode, Clone)] + #[derive(Debug, PartialEq, Eq, Decode, Encode, Clone)] struct ThisChainAccountId(u32); - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct ThisChainSigner(u32); - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct ThisChainSignature(u32); - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] enum ThisChainCall { #[codec(index = 42)] Transfer, @@ -1056,13 +1056,13 @@ mod tests { } } - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct BridgedChainAccountId(u32); - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct BridgedChainSigner(u32); - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct BridgedChainSignature(u32); - #[derive(Debug, PartialEq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode)] enum BridgedChainCall {} #[derive(Clone, Debug)] struct BridgedChainOrigin; @@ -1079,7 +1079,7 @@ mod tests { macro_rules! impl_wrapped_balance { ($name:ident) => { - #[derive(Debug, PartialEq, Decode, Encode, Clone, Copy)] + #[derive(Debug, PartialEq, Eq, Decode, Encode, Clone, Copy)] struct $name(u32); impl From for $name { diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index bddb722c92b83..4a7d19acf2112 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -20,9 +20,9 @@ /// /// ```nocompile /// pallet_bridge_grandpa::declare_check_bridged_block_number_ext!{ -/// Runtime, -/// Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, -/// Call::BridgeWestendGrandpa => WestendGrandpaInstance, +/// Runtime, +/// Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, +/// Call::BridgeWestendGrandpa => WestendGrandpaInstance, /// } /// ``` #[macro_export] diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index ff841d70f9bb3..dadd48a485029 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -53,7 +53,7 @@ impl crate::FinalityProof for GrandpaJustification { } /// Justification verification error. -#[derive(RuntimeDebug, PartialEq)] +#[derive(Eq, RuntimeDebug, PartialEq)] pub enum Error { /// Failed to decode justification. JustificationDecode, diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 28949f28de5d8..29d9cc525445d 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -38,7 +38,7 @@ pub trait Parameter: Codec + EncodeLike + Clone + Eq + Debug + TypeInfo {} impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + Debug + TypeInfo {} /// A GRANDPA Authority List and ID. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)] +#[derive(Default, Encode, Eq, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct AuthoritySet { /// List of GRANDPA authorities for the current round. diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 28ce49acc0d7b..8451941a40ebf 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -173,7 +173,7 @@ impl } /// Send message artifacts. -#[derive(RuntimeDebug, PartialEq)] +#[derive(Eq, RuntimeDebug, PartialEq)] pub struct SendMessageArtifacts { /// Nonce of the message. pub nonce: MessageNonce, @@ -198,7 +198,7 @@ pub trait MessagesBridge { } /// Bridge that does nothing when message is being sent. -#[derive(RuntimeDebug, PartialEq)] +#[derive(Eq, RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; impl diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 4a99ab6210f49..30976ff7fb8e8 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -58,7 +58,7 @@ where } } -#[derive(RuntimeDebug, PartialEq)] +#[derive(Eq, RuntimeDebug, PartialEq)] pub enum Error { StorageRootMismatch, StorageValueUnavailable, diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index db6c61381f484..45d6f960aeb3b 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -74,7 +74,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; + use $crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -93,7 +93,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; + use $crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -112,7 +112,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane; + use $crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -131,7 +131,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane; + use $crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -150,7 +150,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane; + use $crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -169,7 +169,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane; + use $crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -188,7 +188,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as MessagesLane; + use $crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] @@ -207,7 +207,7 @@ macro_rules! select_full_bridge { // Relay-messages #[allow(unused_imports)] - use crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as MessagesLane; + use $crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as MessagesLane; // Send-message / Estimate-fee #[allow(unused_imports)] diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index e74d6da766d52..ad6070fdb0f9f 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -83,11 +83,9 @@ pub(crate) fn compute_maximal_message_size( bridge_runtime_common::messages::target::maximal_incoming_message_size( maximal_target_extrinsic_size, ); - let maximal_message_size = if maximal_message_size > maximal_source_extrinsic_size { + if maximal_message_size > maximal_source_extrinsic_size { maximal_source_extrinsic_size } else { maximal_message_size - }; - - maximal_message_size + } } diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 79515b31dcfa9..d164781205378 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -46,7 +46,7 @@ const NEXT_FREE_PARA_ID_STORAGE_NAME: &str = "NextFreeParaId"; const PARAS_LIFECYCLES_STORAGE_NAME: &str = "ParaLifecycles"; /// Register parachain. -#[derive(StructOpt, Debug, PartialEq)] +#[derive(StructOpt, Debug, PartialEq, Eq)] pub struct RegisterParachain { /// A parachain to register. #[structopt(possible_values = Parachain::VARIANTS, case_insensitive = true)] @@ -69,7 +69,7 @@ pub struct RegisterParachain { } /// Parachain to register. -#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] +#[derive(Debug, EnumString, EnumVariantNames, PartialEq, Eq)] #[strum(serialize_all = "kebab_case")] pub enum Parachain { RialtoParachain, diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs index 79869ad03151b..f598bdbca05a5 100644 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -49,7 +49,7 @@ use substrate_relay_helper::{ }; /// Reinitialize bridge pallet. -#[derive(Debug, PartialEq, StructOpt)] +#[derive(Debug, PartialEq, Eq, StructOpt)] pub struct ReinitBridge { /// A bridge instance to reinitialize. #[structopt(possible_values = ReinitBridgeName::VARIANTS, case_insensitive = true)] @@ -62,7 +62,7 @@ pub struct ReinitBridge { target_sign: TargetSigningParams, } -#[derive(Debug, EnumString, EnumVariantNames, PartialEq)] +#[derive(Debug, EnumString, EnumVariantNames, PartialEq, Eq)] #[strum(serialize_all = "kebab_case")] /// Bridge to initialize. pub enum ReinitBridgeName { diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 45087fad5eb3f..820a71748d2be 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -29,7 +29,7 @@ use crate::{ }; /// Relayer operating mode. -#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq)] +#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)] #[strum(serialize_all = "kebab_case")] pub enum RelayerMode { /// The relayer doesn't care about rewards. diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 53187009d3e21..959fbbd7fcac0 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -100,6 +100,7 @@ impl SendMessage { ), }; let payload_len = payload.encode().len(); + #[allow(clippy::useless_conversion)] let send_message_call = Source::encode_send_message_call( self.lane.0, payload, diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index cefc722168e46..a2d18d538520c 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -31,7 +31,7 @@ use std::time::Duration; pub type HeaderId = relay_utils::HeaderId; /// Millau chain definition. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Millau; impl ChainBase for Millau { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index e79556b966894..70fcf4450922d 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -32,7 +32,7 @@ use std::time::Duration; pub type HeaderId = relay_utils::HeaderId; /// Rialto chain definition -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Rialto; impl ChainBase for Rialto { diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index c7c9983efe9b9..f97df643a208d 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -26,7 +26,7 @@ use frame_support::weights::{IdentityFee, Weight}; use std::time::Duration; /// Chain that may be used in tests. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct TestChain; impl bp_runtime::Chain for TestChain { diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 478d8e1be652b..330d166098ca3 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -70,7 +70,7 @@ impl FinalitySyncPipeline for TestFinalitySyncPipeline { type FinalityProof = TestFinalityProof; } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] struct TestSourceHeader(IsMandatory, TestNumber, TestHash); impl SourceHeader for TestSourceHeader { @@ -87,7 +87,7 @@ impl SourceHeader for TestSourceHeader { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] struct TestFinalityProof(TestNumber); impl FinalityProof for TestFinalityProof { diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index c1778d5d11e87..487623096f06e 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -62,7 +62,7 @@ pub struct Params { } /// Relayer operating mode. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RelayerMode { /// The relayer doesn't care about rewards. Altruistic, @@ -111,7 +111,7 @@ pub type MessageDetailsMap = BTreeMap>; /// Message delivery race proof parameters. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct MessageProofParameters { /// Include outbound lane state proof? pub outbound_state_proof_required: bool, diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index b3baa217e89ff..827a5d4430bd2 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -538,7 +538,7 @@ mod tests { } } - #[derive(Clone, Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq, Eq)] struct TestParachainsPipeline; impl ParachainsPipeline for TestParachainsPipeline { @@ -1022,13 +1022,13 @@ mod tests { stall_timeout: Duration::from_secs(60), }; - assert_eq!(is_update_required(&sync_params, &[]), false); - assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID)]), true); - assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)]), true); + assert!(!is_update_required(&sync_params, &[])); + assert!(is_update_required(&sync_params, &[ParaId(PARA_ID)])); + assert!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)])); sync_params.strategy = ParachainSyncStrategy::All; - assert_eq!(is_update_required(&sync_params, &[]), false); - assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID)]), false); - assert_eq!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)]), true); + assert!(!is_update_required(&sync_params, &[])); + assert!(!is_update_required(&sync_params, &[ParaId(PARA_ID)])); + assert!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)])); } } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index a335be791242c..603011819bc6f 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -179,7 +179,7 @@ pub fn interval(timeout: Duration) -> impl futures::Stream { } /// Which client has caused error. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Eq, Clone, Copy, PartialEq)] pub enum FailedClient { /// It is the source client who has caused error. Source, diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 3c1d2d4ae8287..11e14744a075c 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -201,7 +201,7 @@ impl LoopMetrics { }, }; - let _ = runtime.block_on(async move { + runtime.block_on(async move { log::trace!( target: "bridge-metrics", "Starting prometheus endpoint at: {:?}", From 7fd0ab1546b6ee56513c43ae7182b0fdf21bd7c8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 May 2022 16:37:04 +0300 Subject: [PATCH 0692/1210] allow(clippy::too_many_arguments) for on-demand relays startup (#1414) * allow(clippy::too_many_arguments) for on-demand relays startup * add TODO --- relays/bin-substrate/src/cli/relay_headers_and_messages.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index c3c05910475e7..923d82c11f4ef 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -704,6 +704,7 @@ impl RelayHeadersAndMessages { } /// Start bidirectional on-demand headers <> headers relay. +#[allow(clippy::too_many_arguments)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1415 async fn start_on_demand_relay_to_relay( left_client: Client, right_client: Client, @@ -762,6 +763,7 @@ where } /// Start bidirectional on-demand headers <> parachains relay. +#[allow(clippy::too_many_arguments)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1415 async fn start_on_demand_relay_to_parachain( left_client: Client, right_client: Client, From 74f2c04ba8e82a021f50e9ee4e8db7fa05fae6d3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 27 May 2022 15:54:47 +0300 Subject: [PATCH 0693/1210] Fix XCM instruction weight in RialtoParachain to match Millau weight (#1418) * fix XCM instruction weight in RialtoParachain to match Millau weight * fix spelling --- bin/rialto-parachain/runtime/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 7110e5ba4fc46..0ebd0dc306ecf 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -354,10 +354,13 @@ pub type XcmOriginToTransactDispatchOrigin = ( XcmPassthrough, ); -pub const BASE_XCM_WEIGHT: Weight = 1_000_000; +// TODO: until https://github.com/paritytech/parity-bridges-common/issues/1417 is fixed (in either way), +// the following constant must match the similar constant in the Millau runtime. + +/// One XCM operation is `1_000_000_000` weight - almost certainly a conservative estimate. +pub const BASE_XCM_WEIGHT: Weight = 1_000_000_000; parameter_types! { - // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate. pub UnitWeightCost: Weight = BASE_XCM_WEIGHT; // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); From 66d9e7264c43706cf4f6289e58a26f7c0f7efc7a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 27 May 2022 16:49:50 +0300 Subject: [PATCH 0694/1210] fixed on-demand parachains relay case: if better relay header is delivered, then we must select para header that may be proved using this relay header (#1419) --- .../src/on_demand/parachains.rs | 413 ++++++------------ .../src/parachains/source.rs | 57 +-- relays/parachains/src/parachains_loop.rs | 88 +++- 3 files changed, 245 insertions(+), 313 deletions(-) diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 8f1bee352007c..d8cc60ab29777 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -37,14 +37,14 @@ use num_traits::Zero; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use parachains_relay::parachains_loop::{ParachainSyncParams, TargetClient}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, TransactionSignScheme, }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, HeaderId, }; use sp_runtime::traits::Header as HeaderT; -use std::{cmp::Ordering, collections::BTreeMap}; +use std::fmt::Debug; /// On-demand Substrate <-> Substrate parachain finality relay. /// @@ -142,9 +142,8 @@ async fn background_task( let target_transactions_mortality = target_transaction_params.mortality; let mut relay_state = RelayState::Idle; - let mut headers_map_cache = BTreeMap::new(); let mut required_parachain_header_number = Zero::zero(); - let required_para_header_number_ref = Arc::new(Mutex::new(required_parachain_header_number)); + let required_para_header_number_ref = Arc::new(Mutex::new(None)); let mut restart_relay = true; let parachains_relay_task = futures::future::Fuse::terminated(); @@ -191,7 +190,10 @@ async fn background_task( // the workflow of the on-demand parachains relay is: // // 1) message relay (or any other dependent relay) sees new message at parachain header - // `PH`; 2) it sees that the target chain does not know `PH`; + // `PH`; + // + // 2) it sees that the target chain does not know `PH`; + // // 3) it asks on-demand parachains relay to relay `PH` to the target chain; // // Phase#1: relaying relay chain header @@ -204,21 +206,21 @@ async fn background_task( // Phase#2: relaying parachain header // // 7) on-demand parachains relay sets `ParachainsSource::maximal_header_number` to the - // `PH'.number()`. 8) parachains finality relay sees that the parachain head has been - // updated and relays `PH'` to the target chain. + // `PH'.number()`. + // 8) parachains finality relay sees that the parachain head has been + // updated and relays `PH'` to the target chain. // select headers to relay let relay_data = read_relay_data( ¶chains_source, ¶chains_target, required_parachain_header_number, - &mut headers_map_cache, ) .await; match relay_data { - Ok(mut relay_data) => { + Ok(relay_data) => { let prev_relay_state = relay_state; - relay_state = select_headers_to_relay(&mut relay_data, relay_state); + relay_state = select_headers_to_relay(&relay_data, relay_state); log::trace!( target: "bridge", "Selected new relay state in {}: {:?} using old state {:?} and data {:?}", @@ -244,13 +246,13 @@ async fn background_task( // requirements match relay_state { RelayState::Idle => (), - RelayState::RelayingRelayHeader(required_relay_header, _) => { + RelayState::RelayingRelayHeader(required_relay_header) => { on_demand_source_relay_to_target_headers .require_more_headers(required_relay_header) .await; }, RelayState::RelayingParaHeader(required_para_header) => { - *required_para_header_number_ref.lock().await = required_para_header; + *required_para_header_number_ref.lock().await = Some(required_para_header); }, } @@ -300,55 +302,44 @@ fn on_demand_parachains_relay_name() -> /// On-demand relay state. #[derive(Clone, Copy, Debug, PartialEq)] -enum RelayState { +enum RelayState { /// On-demand relay is not doing anything. Idle, /// Relaying given relay header to relay given parachain header later. - RelayingRelayHeader(SourceRelayBlock, SourceParaBlock), + RelayingRelayHeader(RelayNumber), /// Relaying given parachain header. - RelayingParaHeader(SourceParaBlock), + RelayingParaHeader(HeaderId), } /// Data gathered from source and target clients, used by on-demand relay. #[derive(Debug)] -struct RelayData<'a, SourceParaBlock, SourceRelayBlock> { +struct RelayData { /// Parachain header number that is required at the target chain. - pub required_para_header: SourceParaBlock, + pub required_para_header: ParaNumber, /// Parachain header number, known to the target chain. - pub para_header_at_target: SourceParaBlock, - /// Parachain header number, known to the source (relay) chain. - pub para_header_at_source: Option, + pub para_header_at_target: ParaNumber, + /// Parachain header id, known to the source (relay) chain. + pub para_header_at_source: Option>, + /// Parachain header, that is available at the source relay chain at `relay_header_at_target` + /// block. + pub para_header_at_relay_header_at_target: Option>, /// Relay header number at the source chain. - pub relay_header_at_source: SourceRelayBlock, + pub relay_header_at_source: RelayNumber, /// Relay header number at the target chain. - pub relay_header_at_target: SourceRelayBlock, - /// Map of relay to para header block numbers for recent relay headers. - /// - /// Even if we have been trying to relay relay header #100 to relay parachain header #50 - /// afterwards, it may happen that the relay header #200 may be relayed instead - either - /// by us (e.g. if GRANDPA justification is generated for #200, or if we are only syncing - /// mandatory headers), or by other relayer. Then, instead of parachain header #50 we may - /// relay parachain header #70. - /// - /// This cache is especially important, given that we assume that the nodes we're connected - /// to are not necessarily archive nodes. Then, if current relay chain block is #210 and #200 - /// has been delivered to the target chain, we have more chances to generate storage proof - /// at relay block #200 than on relay block #100, which is most likely has pruned state - /// already. - pub headers_map_cache: &'a mut BTreeMap, + pub relay_header_at_target: RelayNumber, } /// Read required data from source and target clients. -async fn read_relay_data<'a, P: SubstrateParachainsPipeline>( +async fn read_relay_data( source: &ParachainsSource

, target: &ParachainsTarget

, required_header_number: BlockNumberOf, - headers_map_cache: &'a mut BTreeMap< - BlockNumberOf, +) -> Result< + RelayData< + HashOf, BlockNumberOf, + BlockNumberOf, >, -) -> Result< - RelayData<'a, BlockNumberOf, BlockNumberOf>, FailedClient, > where @@ -398,7 +389,7 @@ where ) .await .map_err(map_source_err)? - .map(|h| *h.number()); + .map(|h| HeaderId(*h.number(), h.hash())); let relay_header_at_source = best_finalized_relay_block_id.0; let relay_header_at_target = @@ -408,68 +399,52 @@ where P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD, ) .await - .map_err(map_target_err)? - .0; + .map_err(map_target_err)?; + + let para_header_at_relay_header_at_target = source + .on_chain_parachain_header(relay_header_at_target, P::SOURCE_PARACHAIN_PARA_ID.into()) + .await + .map_err(map_source_err)? + .map(|h| HeaderId(*h.number(), h.hash())); Ok(RelayData { required_para_header: required_header_number, para_header_at_target, para_header_at_source, relay_header_at_source, - relay_header_at_target, - headers_map_cache, + relay_header_at_target: relay_header_at_target.0, + para_header_at_relay_header_at_target, }) } -// This number is bigger than the session length of any well-known Substrate-based relay -// chain. We expect that the underlying on-demand relay will submit at least 1 header per -// session. -const MAX_HEADERS_MAP_CACHE_ENTRIES: usize = 4096; - /// Select relay and parachain headers that need to be relayed. -fn select_headers_to_relay<'a, SourceParaBlock, SourceRelayBlock>( - data: &mut RelayData<'a, SourceParaBlock, SourceRelayBlock>, - mut state: RelayState, -) -> RelayState +fn select_headers_to_relay( + data: &RelayData, + mut state: RelayState, +) -> RelayState where - RelayData<'a, SourceParaBlock, SourceRelayBlock>: std::fmt::Debug, // TODO: remove - SourceParaBlock: Copy + PartialOrd, - SourceRelayBlock: Copy + Ord, + ParaHash: Clone, + ParaNumber: Copy + PartialOrd, + RelayNumber: Copy + Debug + Ord, { - // despite of our current state, we want to update the headers map cache - if let Some(para_header_at_source) = data.para_header_at_source { - data.headers_map_cache - .insert(data.relay_header_at_source, para_header_at_source); - if data.headers_map_cache.len() > MAX_HEADERS_MAP_CACHE_ENTRIES { - let first_key = *data.headers_map_cache.keys().next().expect("map is not empty; qed"); - data.headers_map_cache.remove(&first_key); - } - } - // this switch is responsible for processing `RelayingRelayHeader` state match state { RelayState::Idle | RelayState::RelayingParaHeader(_) => (), - RelayState::RelayingRelayHeader(relay_header_number, para_header_number) => { - match data.relay_header_at_target.cmp(&relay_header_number) { - Ordering::Less => { - // relay header hasn't yet been relayed - return RelayState::RelayingRelayHeader(relay_header_number, para_header_number) - }, - Ordering::Equal => { - // relay header has been realyed and we may continue with parachain header - state = RelayState::RelayingParaHeader(para_header_number); - }, - Ordering::Greater => { - // relay header descendant has been relayed and we may need to change parachain - // header that we want to relay - let next_para_header_number = data - .headers_map_cache - .range(..=data.relay_header_at_target) - .next_back() - .map(|(_, next_para_header_number)| *next_para_header_number) - .unwrap_or_else(|| para_header_number); - state = RelayState::RelayingParaHeader(next_para_header_number); - }, + RelayState::RelayingRelayHeader(relay_header_number) => { + if data.relay_header_at_target < relay_header_number { + // required relay header hasn't yet been relayed + return RelayState::RelayingRelayHeader(relay_header_number) + } + + // we may switch to `RelayingParaHeader` if parachain head is available + if let Some(para_header_at_relay_header_at_target) = + data.para_header_at_relay_header_at_target.clone() + { + state = RelayState::RelayingParaHeader(para_header_at_relay_header_at_target); + } else { + // otherwise, we'd need to restart (this may happen only if parachain has been + // deregistered) + state = RelayState::Idle; } }, } @@ -477,11 +452,11 @@ where // this switch is responsible for processing `RelayingParaHeader` state match state { RelayState::Idle => (), - RelayState::RelayingRelayHeader(_, _) => unreachable!("processed by previous match; qed"), - RelayState::RelayingParaHeader(para_header_number) => { - if data.para_header_at_target < para_header_number { + RelayState::RelayingRelayHeader(_) => unreachable!("processed by previous match; qed"), + RelayState::RelayingParaHeader(para_header_id) => { + if data.para_header_at_target < para_header_id.0 { // parachain header hasn't yet been relayed - return RelayState::RelayingParaHeader(para_header_number) + return RelayState::RelayingParaHeader(para_header_id) } }, } @@ -491,8 +466,14 @@ where return RelayState::Idle } + // if we haven't read para head from the source, we can't yet do anyhting + let para_header_at_source = match data.para_header_at_source { + Some(ref para_header_at_source) => para_header_at_source.clone(), + None => return RelayState::Idle, + }; + // if required header is not available even at the source chain, let's wait - if Some(data.required_para_header) > data.para_header_at_source { + if data.required_para_header > para_header_at_source.0 { return RelayState::Idle } @@ -501,14 +482,11 @@ where // we need relay chain header first if data.relay_header_at_target < data.relay_header_at_source { - return RelayState::RelayingRelayHeader( - data.relay_header_at_source, - data.required_para_header, - ) + return RelayState::RelayingRelayHeader(data.relay_header_at_source) } // if all relay headers synced, we may start directly with parachain header - RelayState::RelayingParaHeader(data.required_para_header) + RelayState::RelayingParaHeader(para_header_at_source) } #[cfg(test)] @@ -519,17 +497,17 @@ mod tests { fn relay_waits_for_relay_header_to_be_delivered() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 100, + &RelayData { + required_para_header: 90, para_header_at_target: 50, - para_header_at_source: Some(110), + para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 700, - headers_map_cache: &mut BTreeMap::new(), + para_header_at_relay_header_at_target: Some(HeaderId(100, 100)), }, - RelayState::RelayingRelayHeader(750, 100), + RelayState::RelayingRelayHeader(750), ), - RelayState::RelayingRelayHeader(750, 100), + RelayState::RelayingRelayHeader(750), ); } @@ -537,53 +515,17 @@ mod tests { fn relay_starts_relaying_requested_para_header_after_relay_header_is_delivered() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 100, + &RelayData { + required_para_header: 90, para_header_at_target: 50, - para_header_at_source: Some(110), + para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 750, - headers_map_cache: &mut BTreeMap::new(), - }, - RelayState::RelayingRelayHeader(750, 100), - ), - RelayState::RelayingParaHeader(100), - ); - } - - #[test] - fn relay_selects_same_para_header_after_better_relay_header_is_delivered_1() { - assert_eq!( - select_headers_to_relay( - &mut RelayData { - required_para_header: 100, - para_header_at_target: 50, - para_header_at_source: Some(110), - relay_header_at_source: 800, - relay_header_at_target: 780, - headers_map_cache: &mut vec![(700, 90), (750, 100)].into_iter().collect(), - }, - RelayState::RelayingRelayHeader(750, 100), - ), - RelayState::RelayingParaHeader(100), - ); - } - - #[test] - fn relay_selects_same_para_header_after_better_relay_header_is_delivered_2() { - assert_eq!( - select_headers_to_relay( - &mut RelayData { - required_para_header: 100, - para_header_at_target: 50, - para_header_at_source: Some(110), - relay_header_at_source: 800, - relay_header_at_target: 780, - headers_map_cache: &mut BTreeMap::new(), + para_header_at_relay_header_at_target: Some(HeaderId(100, 100)), }, - RelayState::RelayingRelayHeader(750, 100), + RelayState::RelayingRelayHeader(750), ), - RelayState::RelayingParaHeader(100), + RelayState::RelayingParaHeader(HeaderId(100, 100)), ); } @@ -591,37 +533,34 @@ mod tests { fn relay_selects_better_para_header_after_better_relay_header_is_delivered() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 100, + &RelayData { + required_para_header: 90, para_header_at_target: 50, - para_header_at_source: Some(120), + para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 780, - headers_map_cache: &mut vec![(700, 90), (750, 100), (780, 110), (790, 120)] - .into_iter() - .collect(), + para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, - RelayState::RelayingRelayHeader(750, 100), + RelayState::RelayingRelayHeader(750), ), - RelayState::RelayingParaHeader(110), + RelayState::RelayingParaHeader(HeaderId(105, 105)), ); } - #[test] fn relay_waits_for_para_header_to_be_delivered() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 100, + &RelayData { + required_para_header: 90, para_header_at_target: 50, - para_header_at_source: Some(110), + para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut BTreeMap::new(), + relay_header_at_target: 780, + para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, - RelayState::RelayingParaHeader(100), + RelayState::RelayingParaHeader(HeaderId(105, 105)), ), - RelayState::RelayingParaHeader(100), + RelayState::RelayingParaHeader(HeaderId(105, 105)), ); } @@ -629,13 +568,13 @@ mod tests { fn relay_stays_idle_if_required_para_header_is_already_delivered() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 100, - para_header_at_target: 100, - para_header_at_source: Some(110), + &RelayData { + required_para_header: 90, + para_header_at_target: 105, + para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut BTreeMap::new(), + relay_header_at_target: 780, + para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, ), @@ -647,13 +586,13 @@ mod tests { fn relay_waits_for_required_para_header_to_appear_at_source_1() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 110, - para_header_at_target: 100, + &RelayData { + required_para_header: 120, + para_header_at_target: 105, para_header_at_source: None, relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut BTreeMap::new(), + relay_header_at_target: 780, + para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, ), @@ -665,13 +604,13 @@ mod tests { fn relay_waits_for_required_para_header_to_appear_at_source_2() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 110, - para_header_at_target: 100, - para_header_at_source: Some(100), + &RelayData { + required_para_header: 120, + para_header_at_target: 105, + para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut BTreeMap::new(), + relay_header_at_target: 780, + para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, ), @@ -683,17 +622,17 @@ mod tests { fn relay_starts_relaying_relay_header_when_new_para_header_is_requested() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 110, - para_header_at_target: 100, - para_header_at_source: Some(110), + &RelayData { + required_para_header: 120, + para_header_at_target: 105, + para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut BTreeMap::new(), + relay_header_at_target: 780, + para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, ), - RelayState::RelayingRelayHeader(800, 110), + RelayState::RelayingRelayHeader(800), ); } @@ -701,97 +640,35 @@ mod tests { fn relay_starts_relaying_para_header_when_new_para_header_is_requested() { assert_eq!( select_headers_to_relay( - &mut RelayData { - required_para_header: 110, - para_header_at_target: 100, - para_header_at_source: Some(110), + &RelayData { + required_para_header: 120, + para_header_at_target: 105, + para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, relay_header_at_target: 800, - headers_map_cache: &mut BTreeMap::new(), + para_header_at_relay_header_at_target: Some(HeaderId(125, 125)), }, RelayState::Idle, ), - RelayState::RelayingParaHeader(110), + RelayState::RelayingParaHeader(HeaderId(125, 125)), ); } #[test] - fn headers_map_cache_is_updated() { - let mut headers_map_cache = BTreeMap::new(); - - // when parachain header is known, map is updated - select_headers_to_relay( - &mut RelayData { - required_para_header: 0, - para_header_at_target: 50, - para_header_at_source: Some(110), - relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut headers_map_cache, - }, - RelayState::RelayingRelayHeader(750, 100), - ); - assert_eq!(headers_map_cache.clone().into_iter().collect::>(), vec![(800, 110)],); - - // when parachain header is not known, map is NOT updated - select_headers_to_relay( - &mut RelayData { - required_para_header: 0, - para_header_at_target: 50, - para_header_at_source: None, - relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut headers_map_cache, - }, - RelayState::RelayingRelayHeader(750, 100), - ); - assert_eq!(headers_map_cache.clone().into_iter().collect::>(), vec![(800, 110)],); - - // map auto-deduplicates equal entries - select_headers_to_relay( - &mut RelayData { - required_para_header: 0, - para_header_at_target: 50, - para_header_at_source: Some(110), - relay_header_at_source: 800, - relay_header_at_target: 700, - headers_map_cache: &mut headers_map_cache, - }, - RelayState::RelayingRelayHeader(750, 100), - ); - assert_eq!(headers_map_cache.clone().into_iter().collect::>(), vec![(800, 110)],); - - // nothing is pruned if number of map entries is < MAX_HEADERS_MAP_CACHE_ENTRIES - for i in 1..MAX_HEADERS_MAP_CACHE_ENTRIES { - select_headers_to_relay( - &mut RelayData { - required_para_header: 0, - para_header_at_target: 50, - para_header_at_source: Some(110 + i), - relay_header_at_source: 800 + i, - relay_header_at_target: 700, - headers_map_cache: &mut headers_map_cache, + fn relay_goes_idle_when_parachain_is_deregistered() { + assert_eq!( + select_headers_to_relay::( + &RelayData { + required_para_header: 120, + para_header_at_target: 105, + para_header_at_source: None, + relay_header_at_source: 800, + relay_header_at_target: 800, + para_header_at_relay_header_at_target: None, }, - RelayState::RelayingRelayHeader(750, 100), - ); - assert_eq!(headers_map_cache.len(), i + 1); - } - - // when we add next entry, the oldest one is pruned - assert!(headers_map_cache.contains_key(&800)); - assert_eq!(headers_map_cache.len(), MAX_HEADERS_MAP_CACHE_ENTRIES); - select_headers_to_relay( - &mut RelayData { - required_para_header: 0, - para_header_at_target: 50, - para_header_at_source: Some(110 + MAX_HEADERS_MAP_CACHE_ENTRIES), - relay_header_at_source: 800 + MAX_HEADERS_MAP_CACHE_ENTRIES, - relay_header_at_target: 700, - headers_map_cache: &mut headers_map_cache, - }, - RelayState::RelayingRelayHeader(750, 100), + RelayState::RelayingRelayHeader(800), + ), + RelayState::Idle, ); - assert!(!headers_map_cache.contains_key(&800)); - assert_eq!(headers_map_cache.len(), MAX_HEADERS_MAP_CACHE_ENTRIES); } } diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index 3ae735ab8930f..ea30143e4b64f 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -16,39 +16,38 @@ //! Parachain heads source. -use crate::{ - finality::source::RequiredHeaderNumberRef, - parachains::{ParachainsPipelineAdapter, SubstrateParachainsPipeline}, -}; +use crate::parachains::{ParachainsPipelineAdapter, SubstrateParachainsPipeline}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use codec::Decode; -use parachains_relay::parachains_loop::SourceClient; +use parachains_relay::parachains_loop::{ParaHashAtSource, SourceClient}; use relay_substrate_client::{ Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, RelayChain, }; use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::traits::Header as HeaderT; +/// Shared updatable reference to the maximal parachain header id that we want to sync from the +/// source. +pub type RequiredHeaderIdRef = Arc>>>; + /// Substrate client as parachain heads source. #[derive(Clone)] pub struct ParachainsSource { client: Client, - maximal_header_number: Option>, - previous_parachain_head: Arc>>, + maximal_header_id: Option>, } impl ParachainsSource

{ /// Creates new parachains source client. pub fn new( client: Client, - maximal_header_number: Option>, + maximal_header_id: Option>, ) -> Self { - let previous_parachain_head = Arc::new(Mutex::new(None)); - ParachainsSource { client, maximal_header_number, previous_parachain_head } + ParachainsSource { client, maximal_header_id } } /// Returns reference to the underlying RPC client. @@ -102,7 +101,7 @@ where &self, at_block: HeaderIdOf, para_id: ParaId, - ) -> Result, Self::Error> { + ) -> Result { // we don't need to support many parachains now if para_id.0 != P::SOURCE_PARACHAIN_PARA_ID { return Err(SubstrateError::Custom(format!( @@ -112,29 +111,33 @@ where ))) } - let parachain_head = match self.on_chain_parachain_header(at_block, para_id).await? { + Ok(match self.on_chain_parachain_header(at_block, para_id).await? { Some(parachain_header) => { - let mut parachain_head = Some(parachain_header.hash()); + let mut parachain_head = ParaHashAtSource::Some(parachain_header.hash()); // never return head that is larger than requested. This way we'll never sync - // headers past `maximal_header_number` - if let Some(ref maximal_header_number) = self.maximal_header_number { - let maximal_header_number = *maximal_header_number.lock().await; - if *parachain_header.number() > maximal_header_number { - let previous_parachain_head = *self.previous_parachain_head.lock().await; - if let Some(previous_parachain_head) = previous_parachain_head { - parachain_head = Some(previous_parachain_head); - } + // headers past `maximal_header_id` + if let Some(ref maximal_header_id) = self.maximal_header_id { + let maximal_header_id = *maximal_header_id.lock().await; + match maximal_header_id { + Some(maximal_header_id) + if *parachain_header.number() > maximal_header_id.0 => + { + // we don't want this header yet => let's report previously requested + // header + parachain_head = ParaHashAtSource::Some(maximal_header_id.1); + }, + Some(_) => (), + None => { + // on-demand relay has not yet asked us to sync anything let's do that + parachain_head = ParaHashAtSource::Unavailable; + }, } } parachain_head }, - None => None, - }; - - *self.previous_parachain_head.lock().await = parachain_head; - - Ok(parachain_head) + None => ParaHashAtSource::None, + }) } async fn prove_parachain_heads( diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 827a5d4430bd2..fd173f2d25bc1 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -52,6 +52,23 @@ pub enum ParachainSyncStrategy { All, } +/// Parachain head hash, available at the source (relay) chain. +#[derive(Clone, Copy, Debug)] +pub enum ParaHashAtSource { + /// There's no parachain head at the source chain. + /// + /// Normally it means that the parachain is not registered there. + None, + /// Parachain head with given hash is available at the source chain. + Some(ParaHash), + /// The source client refuses to report parachain head hash at this moment. + /// + /// It is a "mild" error, which may appear when e.g. on-demand parachains relay is used. + /// This variant must be treated as "we don't want to update parachain head value at the + /// target chain at this moment". + Unavailable, +} + /// Source client used in parachain heads synchronization loop. #[async_trait] pub trait SourceClient: RelayClient { @@ -63,7 +80,7 @@ pub trait SourceClient: RelayClient { &self, at_block: HeaderIdOf, para_id: ParaId, - ) -> Result, Self::Error>; + ) -> Result; /// Get parachain heads proof. async fn prove_parachain_heads( @@ -291,7 +308,7 @@ where /// Given heads at source and target clients, returns set of heads that are out of sync. fn select_parachains_to_update( - heads_at_source: BTreeMap>, + heads_at_source: BTreeMap, heads_at_target: BTreeMap>, best_finalized_relay_block: HeaderIdOf, ) -> Vec @@ -317,7 +334,12 @@ where .zip(heads_at_target.into_iter()) .filter(|((para, head_at_source), (_, head_at_target))| { let needs_update = match (head_at_source, head_at_target) { - (Some(head_at_source), Some(head_at_target)) + (ParaHashAtSource::Unavailable, _) => { + // source client has politely asked us not to update current parachain head + // at the target chain + false + }, + (ParaHashAtSource::Some(head_at_source), Some(head_at_target)) if head_at_target.at_relay_block_number < best_finalized_relay_block.0 && head_at_target.head_hash != *head_at_source => { @@ -325,22 +347,22 @@ where // client true }, - (Some(_), Some(_)) => { + (ParaHashAtSource::Some(_), Some(_)) => { // this is normal case when relay has recently updated heads, when parachain is // not progressing or when our source client is false }, - (Some(_), None) => { + (ParaHashAtSource::Some(_), None) => { // parachain is not yet known to the target client. This is true when parachain // or bridge has been just onboarded/started true }, - (None, Some(_)) => { + (ParaHashAtSource::None, Some(_)) => { // parachain/parathread has been offboarded removed from the system. It needs to // be propageted to the target client true }, - (None, None) => { + (ParaHashAtSource::None, None) => { // all's good - parachain is unknown to both clients false }, @@ -378,7 +400,7 @@ async fn read_heads_at_source( source_client: &impl SourceClient

, at_relay_block: &HeaderIdOf, parachains: &[ParaId], -) -> Result>, FailedClient> { +) -> Result, FailedClient> { let mut para_head_hashes = BTreeMap::new(); for para in parachains { let para_head = source_client.parachain_head(*at_relay_block, *para).await; @@ -554,7 +576,7 @@ mod tests { #[derive(Clone, Debug)] struct TestClientData { source_sync_status: Result, - source_heads: BTreeMap>, + source_heads: BTreeMap>, source_proofs: BTreeMap, TestError>>, target_best_block: Result, TestError>, @@ -569,7 +591,9 @@ mod tests { pub fn minimal() -> Self { TestClientData { source_sync_status: Ok(true), - source_heads: vec![(PARA_ID, Ok(PARA_0_HASH))].into_iter().collect(), + source_heads: vec![(PARA_ID, Ok(ParaHashAtSource::Some(PARA_0_HASH)))] + .into_iter() + .collect(), source_proofs: vec![(PARA_ID, Ok(PARA_0_HASH.encode()))].into_iter().collect(), target_best_block: Ok(HeaderId(0, Default::default())), @@ -615,8 +639,11 @@ mod tests { &self, _at_block: HeaderIdOf, para_id: ParaId, - ) -> Result, TestError> { - self.data.lock().await.source_heads.get(¶_id.0).cloned().transpose() + ) -> Result { + match self.data.lock().await.source_heads.get(¶_id.0).cloned() { + Some(result) => result, + None => Ok(ParaHashAtSource::None), + } } async fn prove_parachain_heads( @@ -923,7 +950,7 @@ mod tests { fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), None)].into_iter().collect(), + vec![(ParaId(PARA_ID), ParaHashAtSource::None)].into_iter().collect(), vec![(ParaId(PARA_ID), None)].into_iter().collect(), HeaderId(10, Default::default()), ), @@ -935,7 +962,9 @@ mod tests { fn parachain_is_not_updated_if_it_has_been_updated_at_better_relay_block() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), Some(PARA_0_HASH))].into_iter().collect(), + vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_0_HASH))] + .into_iter() + .collect(), vec![( ParaId(PARA_ID), Some(BestParaHeadHash { at_relay_block_number: 20, head_hash: PARA_1_HASH }) @@ -952,7 +981,9 @@ mod tests { fn parachain_is_not_updated_if_hash_is_the_same_at_next_relay_block() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), Some(PARA_0_HASH))].into_iter().collect(), + vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_0_HASH))] + .into_iter() + .collect(), vec![( ParaId(PARA_ID), Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) @@ -969,7 +1000,7 @@ mod tests { fn parachain_is_updated_after_offboarding() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), None)].into_iter().collect(), + vec![(ParaId(PARA_ID), ParaHashAtSource::None)].into_iter().collect(), vec![( ParaId(PARA_ID), Some(BestParaHeadHash { @@ -989,7 +1020,9 @@ mod tests { fn parachain_is_updated_after_onboarding() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), Some(PARA_0_HASH))].into_iter().collect(), + vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_0_HASH))] + .into_iter() + .collect(), vec![(ParaId(PARA_ID), None)].into_iter().collect(), HeaderId(10, Default::default()), ), @@ -1001,7 +1034,9 @@ mod tests { fn parachain_is_updated_if_newer_head_is_known() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), Some(PARA_1_HASH))].into_iter().collect(), + vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_1_HASH))] + .into_iter() + .collect(), vec![( ParaId(PARA_ID), Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) @@ -1014,6 +1049,23 @@ mod tests { ); } + #[test] + fn parachain_is_not_updated_if_source_head_is_unavailable() { + assert_eq!( + select_parachains_to_update::( + vec![(ParaId(PARA_ID), ParaHashAtSource::Unavailable)].into_iter().collect(), + vec![( + ParaId(PARA_ID), + Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) + )] + .into_iter() + .collect(), + HeaderId(10, Default::default()), + ), + vec![], + ); + } + #[test] fn is_update_required_works() { let mut sync_params = ParachainSyncParams { From dfe97e0018b145bbbae785e8d450eb504c9aed3f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 27 May 2022 17:32:00 +0300 Subject: [PATCH 0695/1210] Add RialtoParachain <> Millau bridge to test deployments (#1412) * add RialtoParachain <> Millau bridge to test deployments * flush (still not working, but possible fix in comments) * proper fix * fixed on-demand parachains relay case: if better relay header is delivered, then we must select para header that may be proved using this relay header * dashboards * fmt * removing debugging code * more cleanup --- relays/client-substrate/src/client.rs | 2 ++ .../src/on_demand/headers.rs | 26 +++++++++---------- .../src/on_demand/parachains.rs | 16 ++++++------ relays/parachains/src/parachains_loop.rs | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 0f9445a8d35ae..bb9f823005668 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -187,6 +187,8 @@ impl Client { params.host, params.port, ); + log::info!(target: "bridge", "Connecting to {} node at {}", C::NAME, uri); + let client = tokio .spawn(async move { RpcClientBuilder::default() diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 3d007de4dbf64..f22ad96b636ea 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -95,9 +95,9 @@ impl OnDemandRelay> if required_header > *required_header_number { log::trace!( target: "bridge", - "More {} headers required in {} relay. Going to sync up to the {}", - SourceChain::NAME, + "[{}] More {} headers required. Going to sync up to the {}", self.relay_task_name, + SourceChain::NAME, required_header, ); @@ -184,7 +184,7 @@ async fn background_task( log::trace!( target: "bridge", - "Mandatory headers scan range in {}: ({:?}, {:?}, {:?}) -> {:?}", + "[{}] Mandatory headers scan range: ({:?}, {:?}, {:?}) -> {:?}", relay_task_name, required_header_number_value, best_finalized_source_header_at_source_fmt, @@ -213,18 +213,18 @@ async fn background_task( log::trace!( target: "bridge", - "No mandatory {} headers in the range {:?} of {} relay", + "[{}] No mandatory {} headers in the range {:?}", + relay_task_name, P::SourceChain::NAME, mandatory_scan_range, - relay_task_name, ); }, Err(e) => { log::warn!( target: "bridge", - "Failed to scan mandatory {} headers range in {} relay (range: {:?}): {:?}", - P::SourceChain::NAME, + "[{}] Failed to scan mandatory {} headers range ({:?}): {:?}", relay_task_name, + P::SourceChain::NAME, mandatory_scan_range, e, ); @@ -253,7 +253,7 @@ async fn background_task( log::info!( target: "bridge", - "Starting {} relay\n\t\ + "[{}] Starting on-demand relay task\n\t\ Only mandatory headers: {}\n\t\ Tx mortality: {:?} (~{}m)\n\t\ Stall timeout: {:?}", @@ -347,9 +347,9 @@ async fn relay_mandatory_header_from_range( log::trace!( target: "bridge", - "Too many {} headers missing at target in {} relay ({} vs {}). Going to sync up to the mandatory {}", - P::SourceChain::NAME, + "[{}] Too many {} headers missing at target ({} vs {}). Going to sync up to the mandatory {}", relay_task_name, + P::SourceChain::NAME, best_finalized_source_header_at_target, range.1, mandatory_source_header_number, @@ -369,7 +369,7 @@ async fn best_finalized_source_header_at_source( /// On-demand headers relay task name. fn on_demand_headers_relay_name() -> String { - format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) + format!("{}-to-{}-on-demand-headers", SourceChain::NAME, TargetChain::NAME) } #[cfg(test)] diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index d8cc60ab29777..579f3103e8222 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -111,10 +111,10 @@ where if let Err(e) = self.required_header_number_sender.send(required_header).await { log::trace!( target: "bridge", - "Failed to request {} header {:?} in {:?}: {:?}", + "[{}] Failed to request {} header {:?}: {:?}", + self.relay_task_name, SourceParachain::NAME, required_header, - self.relay_task_name, e, ); } @@ -164,7 +164,7 @@ async fn background_task( Err(e) => { log::error!( target: "bridge", - "Background task of {} has exited with error: {:?}", + "[{}] Background task has exited with error: {:?}", relay_task_name, e, ); @@ -223,7 +223,7 @@ async fn background_task( relay_state = select_headers_to_relay(&relay_data, relay_state); log::trace!( target: "bridge", - "Selected new relay state in {}: {:?} using old state {:?} and data {:?}", + "[{}] Selected new relay state: {:?} using old state {:?} and data {:?}", relay_task_name, relay_state, prev_relay_state, @@ -266,7 +266,7 @@ async fn background_task( log::info!( target: "bridge", - "Starting {} relay\n\t\ + "[{}] Starting on-demand-relay task\n\t\ Tx mortality: {:?} (~{}m)\n\t\ Stall timeout: {:?}", relay_task_name, @@ -297,7 +297,7 @@ async fn background_task( /// On-demand parachains relay task name. fn on_demand_parachains_relay_name() -> String { - format!("on-demand-{}-to-{}", SourceChain::NAME, TargetChain::NAME) + format!("{}-to-{}-on-demand-parachain", SourceChain::NAME, TargetChain::NAME) } /// On-demand relay state. @@ -349,7 +349,7 @@ where let map_target_err = |e| { log::error!( target: "bridge", - "Failed to read {} relay data from {} client: {:?}", + "[{}] Failed to read relay data from {} client: {:?}", on_demand_parachains_relay_name::(), P::TargetChain::NAME, e, @@ -359,7 +359,7 @@ where let map_source_err = |e| { log::error!( target: "bridge", - "Failed to read {} relay data from {} client: {:?}", + "[{}] Failed to read relay data from {} client: {:?}", on_demand_parachains_relay_name::(), P::SourceRelayChain::NAME, e, diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index fd173f2d25bc1..6e9cc5f1da59b 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -121,7 +121,7 @@ pub trait TargetClient: RelayClient { /// Return prefix that will be used by default to expose Prometheus metrics of the parachains /// sync loop. pub fn metrics_prefix() -> String { - format!("{}_to_{}_Sync", P::SourceChain::NAME, P::TargetChain::NAME) + format!("{}_to_{}_Parachains", P::SourceChain::NAME, P::TargetChain::NAME) } /// Run parachain heads synchronization. From a3731c415c4c441f619ec115a90537668c23df74 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 May 2022 16:31:57 +0300 Subject: [PATCH 0696/1210] ensure that the bridge GRANDPA pallet is initialized in the finality relay (#1423) --- relays/client-substrate/src/error.rs | 3 +++ .../src/finality/initialize.rs | 6 +++++- .../lib-substrate-relay/src/finality/target.rs | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 797af5cc5d225..016ec774beb49 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -54,6 +54,9 @@ pub enum Error { /// The bridge pallet is halted and all transactions will be rejected. #[error("Bridge pallet is halted.")] BridgePalletIsHalted, + /// The bridge pallet is not yet initialized and all transactions will be rejected. + #[error("Bridge pallet is not initialized.")] + BridgePalletIsNotInitialized, /// An error has happened when we have tried to parse storage proof. #[error("Error when parsing storage proof: {0:?}.")] StorageProofError(bp_runtime::StorageProofError), diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index 58a0fc499fb02..2fc9302d90f58 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -110,7 +110,11 @@ where } /// Returns `Ok(true)` if bridge has already been initialized. -async fn is_initialized, SourceChain: Chain, TargetChain: Chain>( +pub(crate) async fn is_initialized< + E: Engine, + SourceChain: Chain, + TargetChain: Chain, +>( target_client: &Client, ) -> Result, BlockNumberOf>> { Ok(target_client diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 6ca6be631aab8..12098a7479977 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -53,10 +53,20 @@ impl SubstrateFinalityTarget

{ pub async fn ensure_pallet_active(&self) -> Result<(), Error> { let is_halted = self.client.storage_value(P::FinalityEngine::is_halted_key(), None).await?; if is_halted.unwrap_or(false) { - Err(Error::BridgePalletIsHalted) - } else { - Ok(()) + return Err(Error::BridgePalletIsHalted) } + + let is_initialized = + super::initialize::is_initialized::( + &self.client, + ) + .await + .map_err(|e| Error::Custom(e.to_string()))?; + if !is_initialized { + return Err(Error::BridgePalletIsNotInitialized) + } + + Ok(()) } } From 0e51be4fc32068859008c4be1595c9b3de3bbfa9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Jun 2022 13:00:59 +0300 Subject: [PATCH 0697/1210] Get dispatch weight from the target chain (when DispatchFeePayment::AtTargetChain is used) (#1430) * reintroduce FromInboundLaneApi * impl FromInboundLaneApi for testnet runtimes * use inboundlaneapi in relay * remove unused OutboundXcmWeigher * spelling * added the only test to messages pallet * fmt --- bin/millau/runtime/src/lib.rs | 32 ++++-- bin/millau/runtime/src/xcm_config.rs | 2 - bin/rialto-parachain/runtime/src/lib.rs | 18 +++- bin/rialto/runtime/src/lib.rs | 16 ++- bin/rialto/runtime/src/xcm_config.rs | 2 - bin/runtime-common/src/messages_api.rs | 68 +++++------- modules/messages/src/lib.rs | 46 +++++++- primitives/chain-kusama/src/lib.rs | 24 ++++- primitives/chain-millau/src/lib.rs | 24 ++++- primitives/chain-polkadot/src/lib.rs | 25 ++++- primitives/chain-rialto-parachain/src/lib.rs | 25 ++++- primitives/chain-rialto/src/lib.rs | 24 ++++- primitives/chain-rococo/src/lib.rs | 24 ++++- primitives/chain-wococo/src/lib.rs | 24 ++++- primitives/messages/src/lib.rs | 21 +++- primitives/messages/src/target_chain.rs | 5 +- relays/client-kusama/src/lib.rs | 2 + relays/client-millau/src/lib.rs | 2 + relays/client-polkadot/src/lib.rs | 2 + relays/client-rialto-parachain/src/lib.rs | 2 + relays/client-rialto/src/lib.rs | 2 + relays/client-rococo/src/lib.rs | 2 + relays/client-substrate/src/chain.rs | 4 + relays/client-wococo/src/lib.rs | 2 + .../src/messages_source.rs | 102 ++++++++++++++++-- 25 files changed, 411 insertions(+), 89 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 612a9e4364b75..743bab6d13764 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -833,16 +833,26 @@ impl_runtime_apis! { lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec> { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithRialtoMessagesInstance, - WithRialtoMessageBridge, - xcm_config::OutboundXcmWeigher, >(lane, begin, end) } } + impl bp_rialto::FromRialtoInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithRialtoMessagesInstance, + >(lane, messages) + } + } + impl bp_rialto_parachain::ToRialtoParachainOutboundLaneApi for Runtime { fn estimate_message_delivery_and_dispatch_fee( _lane_id: bp_messages::LaneId, @@ -860,16 +870,26 @@ impl_runtime_apis! { lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec> { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithRialtoParachainMessagesInstance, - WithRialtoParachainMessageBridge, - xcm_config::OutboundXcmWeigher, >(lane, begin, end) } } + impl bp_rialto_parachain::FromRialtoParachainInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithRialtoParachainMessagesInstance, + >(lane, messages) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index a274b25924a5d..5ba8d97e65e6d 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -122,8 +122,6 @@ pub type Barrier = ( AllowKnownQueryResponses, ); -/// Outbound XCM weigher type. -pub type OutboundXcmWeigher = xcm_builder::FixedWeightBounds; /// XCM weigher type. pub type XcmWeigher = xcm_builder::FixedWeightBounds; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 0ebd0dc306ecf..1f8a0a2581e6a 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -383,8 +383,6 @@ pub type Barrier = ( // ^^^ Parent & its unit plurality gets free execution ); -/// Outbound XCM weigher type. -pub type OutboundXcmWeigher = FixedWeightBounds; /// XCM weigher type. pub type XcmWeigher = FixedWeightBounds; @@ -708,16 +706,26 @@ impl_runtime_apis! { lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec> { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithMillauMessagesInstance, - WithMillauMessageBridge, - OutboundXcmWeigher, >(lane, begin, end) } } + impl bp_millau::FromMillauInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithMillauMessagesInstance, + >(lane, messages) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn dispatch_benchmark( diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 82eb57f40ffa1..9b7dc70394ac5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -893,15 +893,25 @@ impl_runtime_apis! { lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec> { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithMillauMessagesInstance, - WithMillauMessageBridge, - xcm_config::OutboundXcmWeigher, >(lane, begin, end) } } + + impl bp_millau::FromMillauInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithMillauMessagesInstance, + >(lane, messages) + } + } } #[cfg(test)] diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 65ffc54a9f680..8a230101f3065 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -122,8 +122,6 @@ pub type Barrier = ( AllowKnownQueryResponses, ); -/// Outbound XCM weigher type. -pub type OutboundXcmWeigher = xcm_builder::FixedWeightBounds; /// Incoming XCM weigher type. pub type XcmWeigher = xcm_builder::FixedWeightBounds; diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index 4f5a175e24046..68465fa16e417 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -16,68 +16,54 @@ //! Helpers for implementing various message-related runtime API mthods. -use crate::messages::{target::FromBridgedChainMessagePayload, MessageBridge}; - -use bp_messages::{LaneId, MessageDetails, MessageKey, MessageNonce}; -use codec::Decode; -use frame_support::weights::Weight; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use sp_std::vec::Vec; /// Implementation of the `To*OutboundLaneApi::message_details`. -pub fn outbound_message_details( +pub fn outbound_message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, -) -> Vec> +) -> Vec> where Runtime: pallet_bridge_messages::Config, MessagesPalletInstance: 'static, - BridgeConfig: MessageBridge, - XcmWeigher: xcm_executor::traits::WeightBounds<()>, { (begin..=end) .filter_map(|nonce| { let message_data = pallet_bridge_messages::Pallet::::outbound_message_data(lane, nonce)?; - Some(MessageDetails { + Some(OutboundMessageDetails { nonce, - // this shall match the similar code in the `FromBridgedChainMessageDispatch` - if we have failed - // to decode or estimate dispatch weight, we'll just return 0 to disable actual execution - dispatch_weight: compute_message_weight::( - MessageKey { lane_id: lane, nonce }, - &message_data.payload, - ).unwrap_or(0), + // dispatch message weight is always zero at the source chain, since we're paying for + // dispatch at the target chain + dispatch_weight: 0, size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, + // we're delivering XCM messages here, so fee is always paid at the target chain dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtTargetChain, }) }) .collect() } -// at the source chain we don't know the type of target chain `Call` => `()` is used (it is -// similarly currently used in Polkadot codebase) -fn compute_message_weight>( - message_key: MessageKey, - encoded_payload: &[u8], -) -> Result { - let mut payload = FromBridgedChainMessagePayload::<()>::decode(&mut &encoded_payload[..]) - .map_err(|e| { - log::debug!( - target: "runtime::bridge-dispatch", - "Failed to decode outbound XCM message {:?}: {:?}", - message_key, - e, - ); - })?; - let weight = XcmWeigher::weight(&mut payload.xcm.1); - let weight = weight.map_err(|e| { - log::debug!( - target: "runtime::bridge-dispatch", - "Failed to compute dispatch weight of outbound XCM message {:?}: {:?}", - message_key, - e, - ); - })?; - Ok(weight) +/// Implementation of the `To*InboundLaneApi::message_details`. +pub fn inbound_message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, +) -> Vec +where + Runtime: pallet_bridge_messages::Config, + MessagesPalletInstance: 'static, +{ + messages + .into_iter() + .map(|(payload, details)| { + pallet_bridge_messages::Pallet::::inbound_message_data( + lane, payload, details, + ) + }) + .collect() } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 5c3398ff705f4..a41ea3d1d95a8 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -56,9 +56,10 @@ use bp_messages::{ target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, - total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, - MessageNonce, OperatingMode, OutboundLaneData, Parameter as MessagesParameter, - UnrewardedRelayer, UnrewardedRelayersState, + total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, + MessageData, MessageKey, MessageNonce, MessagePayload, OperatingMode, OutboundLaneData, + OutboundMessageDetails, Parameter as MessagesParameter, UnrewardedRelayer, + UnrewardedRelayersState, }; use bp_runtime::{ChainId, Size}; use codec::{Decode, Encode}; @@ -156,7 +157,7 @@ pub mod pallet { /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; /// Message fee type of inbound messages. This fee is paid on the bridged chain. - type InboundMessageFee: Decode; + type InboundMessageFee: Decode + Zero; /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the /// bridged chain. type InboundRelayer: Parameter; @@ -762,6 +763,22 @@ pub mod pallet { ) -> Option> { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) } + + /// Prepare data, related to given inbound message. + pub fn inbound_message_data( + lane: LaneId, + payload: MessagePayload, + outbound_details: OutboundMessageDetails, + ) -> InboundMessageDetails { + let mut dispatch_message = DispatchMessage { + key: MessageKey { lane_id: lane, nonce: outbound_details.nonce }, + data: MessageData { payload, fee: outbound_details.delivery_and_dispatch_fee } + .into(), + }; + InboundMessageDetails { + dispatch_weight: T::MessageDispatch::dispatch_weight(&mut dispatch_message), + } + } } } @@ -2332,4 +2349,25 @@ mod tests { bp_messages::storage_keys::inbound_lane_data_key("Messages", &TEST_LANE_ID).0, ); } + + #[test] + fn inbound_message_details_works() { + run_test(|| { + assert_eq!( + Pallet::::inbound_message_data( + TEST_LANE_ID, + REGULAR_PAYLOAD.encode(), + OutboundMessageDetails { + nonce: 0, + dispatch_weight: 0, + size: 0, + delivery_and_dispatch_fee: 0, + dispatch_fee_payment: + bp_runtime::messages::DispatchFeePayment::AtTargetChain, + }, + ), + InboundMessageDetails { dispatch_weight: REGULAR_PAYLOAD.declared_weight }, + ); + }); + } } diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index a0a5990ca08ad..880fe5ac1bd00 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -18,7 +18,9 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -105,6 +107,9 @@ pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; +/// Name of the `FromKusamaInboundLaneApi::message_details` runtime method. +pub const FROM_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "FromKusamaInboundLaneApi_message_details"; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Kusama headers. /// @@ -143,6 +148,21 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by Kusama chain. + /// + /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the + /// Kusama runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromKusamaInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 6cc417756a606..b91ec86e3febb 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -20,7 +20,9 @@ mod millau_hash; -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -294,6 +296,9 @@ pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; +/// Name of the `FromMillauInboundLaneApi::message_details` runtime method. +pub const FROM_MILLAU_MESSAGE_DETAILS_METHOD: &str = "FromMillauInboundLaneApi_message_details"; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Millau headers. /// @@ -332,7 +337,22 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by Millau chain. + /// + /// This API is implemented by runtimes that are receiving messages from Millau chain, not the + /// Millau runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromMillauInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index d95e29c8b0ce8..e16a23e1d148f 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -18,7 +18,9 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use frame_support::weights::{ WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -105,6 +107,10 @@ pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; +/// Name of the `FromPolkadotInboundLaneApi::message_details` runtime method. +pub const FROM_POLKADOT_MESSAGE_DETAILS_METHOD: &str = + "FromPolkadotOutboundLaneApi_message_details"; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Polkadot headers. /// @@ -143,6 +149,21 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by Polkadot chain. + /// + /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the + /// Polkadot runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromPolkadotInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 598286b2f3ab3..d42bfaf4110b4 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -18,7 +18,9 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -210,6 +212,10 @@ pub const TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD: &str = pub const TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = "ToRialtoParachainOutboundLaneApi_message_details"; +/// Name of the `FromRialtoParachainInboundLaneApi::message_details` runtime method. +pub const FROM_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = + "FromRialtoParachainInboundLaneApi_message_details"; + // We use this to get the account on RialtoParachain (target) which is derived from Millau's // (source) account. We do this so we can fund the derived account on RialtoParachain at Genesis to // it can pay transaction fees. @@ -261,7 +267,22 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by RialtoParachain chain. + /// + /// This API is implemented by runtimes that are receiving messages from RialtoParachain chain, not the + /// RialtoParachain runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromRialtoParachainInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index ca3381a25fd38..9d598b8d22fed 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -18,7 +18,9 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use bp_runtime::Chain; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, @@ -250,6 +252,9 @@ pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; +/// Name of the `FromRialtoInboundLaneApi::message_details` runtime method. +pub const FROM_RIALTO_MESSAGE_DETAILS_METHOD: &str = "FromRialtoInboundLaneApi_message_details"; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Rialto headers. /// @@ -288,7 +293,22 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by Rialto chain. + /// + /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the + /// Rialto runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromRialtoInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 007301a7cec6c..a0f545a95c21e 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -18,7 +18,9 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use frame_support::weights::{ Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; @@ -89,6 +91,9 @@ pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; +/// Name of the `FromRococoInboundLaneApi::message_details` runtime method. +pub const FROM_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "FromRococoInboundLaneApi_message_details"; + /// Existential deposit on Rococo. pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; @@ -139,6 +144,21 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by Rococo chain. + /// + /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the + /// Rococo runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromRococoInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index f39543114c78b..69039355923c4 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -18,7 +18,9 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{LaneId, MessageDetails, MessageNonce}; +use bp_messages::{ + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, +}; use sp_runtime::FixedU128; use sp_std::prelude::*; @@ -58,6 +60,9 @@ pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = /// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; +/// Name of the `FromWococoInboundLaneApi::message_details` runtime method. +pub const FROM_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "FromWococoInboundLaneApi_message_details"; + sp_api::decl_runtime_apis! { /// API for querying information about the finalized Wococo headers. /// @@ -96,6 +101,21 @@ sp_api::decl_runtime_apis! { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by Wococo chain. + /// + /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the + /// Wococo runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait FromWococoInboundLaneApi { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; } } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index cef28ecb3679c..35df6d01f1cbe 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -176,12 +176,15 @@ impl InboundLaneData { } } -/// Message details, returned by runtime APIs. +/// Outbound message details, returned by runtime APIs. #[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] -pub struct MessageDetails { +pub struct OutboundMessageDetails { /// Nonce assigned to the message. pub nonce: MessageNonce, - /// Message dispatch weight, declared by the submitter. + /// Message dispatch weight. + /// + /// Depending on messages pallet configuration, it may be declared by the message submitter, + /// computed automatically or just be zero if dispatch fee is paid at the target chain. pub dispatch_weight: Weight, /// Size of the encoded message. pub size: u32, @@ -191,6 +194,18 @@ pub struct MessageDetails { pub dispatch_fee_payment: DispatchFeePayment, } +/// Inbound message details, returned by runtime APIs. +#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +pub struct InboundMessageDetails { + /// Computed message dispatch weight. + /// + /// Runtime API guarantees that it will match the value, returned by + /// `target_chain::MessageDispatch::dispatch_weight`. This means that if the runtime + /// has failed to decode the message, it will be zero - that's because `undecodable` + /// message cannot be dispatched. + pub dispatch_weight: Weight, +} + /// Bit vector of message dispatch results. pub type DispatchResultsBitVec = BitVec; diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 1ee0d7d631089..a5686e4abea73 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -93,8 +93,9 @@ pub trait MessageDispatch { /// Estimate dispatch weight. /// - /// This function must: (1) be instant and (2) return correct upper bound - /// of dispatch weight. + /// This function must return correct upper bound of dispatch weight. The return value + /// of this function is expected to match return value of the corresponding + /// `FromInboundLaneApi::message_details().dispatch_weight` call. fn dispatch_weight(message: &mut DispatchMessage) -> Weight; /// Called when inbound message is received. diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index e228f2dc24de4..8011cbc564666 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -79,6 +79,8 @@ impl ChainWithMessages for Kusama { bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_kusama::FROM_KUSAMA_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index a2d18d538520c..1fa4708368a36 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -63,6 +63,8 @@ impl ChainWithMessages for Millau { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_millau::FROM_MILLAU_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index d4ada45e36cc8..745bbc44fb6fb 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -80,6 +80,8 @@ impl ChainWithMessages for Polkadot { bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot::FROM_POLKADOT_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index f70815c03ef8b..9f54363d9c4fc 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -88,6 +88,8 @@ impl ChainWithMessages for RialtoParachain { bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto_parachain::TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto_parachain::FROM_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 70fcf4450922d..7ddaaabe3611c 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -85,6 +85,8 @@ impl ChainWithMessages for Rialto { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rialto::FROM_RIALTO_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index f63041df9eddb..161b719516ae9 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -82,6 +82,8 @@ impl ChainWithMessages for Rococo { bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_rococo::FROM_ROCOCO_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index f4a2fcf262fd1..d7f441b73ac2c 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -105,6 +105,10 @@ pub trait ChainWithMessages: Chain { /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; + /// Name of the `FromInboundLaneApi::message_details` runtime API method. + /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; + /// Additional weight of the dispatch fee payment if dispatch is paid at the target chain /// and this `ChainWithMessages` is the target chain. const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 485ca1bd62f4f..eb20e40f483e6 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -82,6 +82,8 @@ impl ChainWithMessages for Wococo { bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_wococo::FROM_WOCOCO_MESSAGE_DETAILS_METHOD; const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 9c447c6b8354c..7dc582dd5762d 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -31,8 +31,10 @@ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::{operating_mode_key, outbound_lane_data_key}, - LaneId, MessageNonce, OperatingMode, OutboundLaneData, UnrewardedRelayersState, + InboundMessageDetails, LaneId, MessageData, MessageNonce, OperatingMode, OutboundLaneData, + OutboundMessageDetails, UnrewardedRelayersState, }; +use bp_runtime::messages::DispatchFeePayment; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -54,7 +56,7 @@ use relay_substrate_client::{ use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use std::ops::RangeInclusive; +use std::{collections::HashMap, ops::RangeInclusive}; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and @@ -199,11 +201,97 @@ where ) .await?; - make_message_details_map::( + let mut messages = make_message_details_map::( Decode::decode(&mut &encoded_response.0[..]) .map_err(SubstrateError::ResponseParseFailed)?, nonces, - ) + )?; + + // prepare arguments of the inbound message details call (if we need it) + let mut messages_to_refine = HashMap::new(); + for (message_nonce, message) in &messages { + if message.dispatch_fee_payment != DispatchFeePayment::AtTargetChain { + continue + } + + // for pay-at-target messages we may want to ask target chain for + // refined dispatch weight + let message_key = bp_messages::storage_keys::message_key( + P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, + &self.lane_id, + *message_nonce, + ); + let message_data: MessageData> = + self.source_client.storage_value(message_key, Some(id.1)).await?.ok_or_else( + || { + SubstrateError::Custom(format!( + "Message to {} {:?}/{} is missing from runtime the storage of {} at {:?}", + P::TargetChain::NAME, + self.lane_id, + message_nonce, + P::SourceChain::NAME, + id, + )) + }, + )?; + let message_payload = message_data.payload; + messages_to_refine.insert( + *message_nonce, + ( + message_payload, + OutboundMessageDetails { + nonce: *message_nonce, + dispatch_weight: message.dispatch_weight, + size: message.size, + delivery_and_dispatch_fee: message.reward, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + }, + ), + ); + } + + // request inbound message details from the target client + if !messages_to_refine.is_empty() { + let refined_messages_encoded = self + .target_client + .state_call( + P::SourceChain::FROM_CHAIN_MESSAGE_DETAILS_METHOD.into(), + Bytes((self.lane_id, messages_to_refine.values().collect::>()).encode()), + None, + ) + .await?; + let refined_messages = + Vec::::decode(&mut &refined_messages_encoded.0[..]) + .map_err(SubstrateError::ResponseParseFailed)?; + if refined_messages.len() != messages_to_refine.len() { + return Err(SubstrateError::Custom(format!( + "Call of {} at {} has returned {} entries instead of expected {}", + P::SourceChain::FROM_CHAIN_MESSAGE_DETAILS_METHOD, + P::TargetChain::NAME, + refined_messages.len(), + messages_to_refine.len(), + ))) + } + + for (nonce, refined_message) in messages_to_refine.keys().zip(refined_messages) { + let message = messages + .get_mut(nonce) + .expect("`messages_to_refine` is a subset of `messages`; qed"); + log::trace!( + target: "bridge", + "Refined weight of {}->{} message {:?}/{}: at-source: {}, at-target: {}", + P::SourceChain::NAME, + P::TargetChain::NAME, + self.lane_id, + nonce, + message.dispatch_weight, + refined_message.dispatch_weight, + ); + message.dispatch_weight = refined_message.dispatch_weight; + } + } + + Ok(messages) } async fn prove_messages( @@ -483,7 +571,7 @@ where } fn make_message_details_map( - weights: Vec>, + weights: Vec>, nonces: RangeInclusive, ) -> Result, SubstrateError> { let make_missing_nonce_error = |expected_nonce| { @@ -558,10 +646,10 @@ mod tests { fn message_details_from_rpc( nonces: RangeInclusive, - ) -> Vec> { + ) -> Vec> { nonces .into_iter() - .map(|nonce| bp_messages::MessageDetails { + .map(|nonce| bp_messages::OutboundMessageDetails { nonce, dispatch_weight: 0, size: 0, From b070e8bded5afc2e377cb2d7dbf4a4689ef30858 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Jun 2022 18:12:46 +0300 Subject: [PATCH 0698/1210] Added tracked parachains filter (#1432) * added trackerd parachains filter + changed some docs * fix compilation --- bin/millau/runtime/src/lib.rs | 1 + modules/grandpa/src/lib.rs | 2 + modules/messages/src/mock.rs | 2 +- modules/parachains/src/lib.rs | 100 +++++++++++++++++++----- modules/parachains/src/mock.rs | 6 +- primitives/runtime/src/storage_proof.rs | 25 +++++- 6 files changed, 113 insertions(+), 23 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 743bab6d13764..3b4b06fbc147d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -520,6 +520,7 @@ pub type WitRialtoParachainsInstance = (); impl pallet_bridge_parachains::Config for Runtime { type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; type ParasPalletName = RialtoParasPalletName; + type TrackedParachains = frame_support::traits::Everything; type HeadsToKeep = HeadersToKeep; } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 4184464231286..8fa0ed89cca2a 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -93,6 +93,8 @@ pub mod pallet { /// The setting is there to prevent growing the on-chain state indefinitely. Note /// the setting does not relate to block numbers - we will simply keep as much items /// in the storage, so it doesn't guarantee any fixed timeframe for finality headers. + /// + /// Incautious change of this constant may lead to orphan entries in the runtime storage. #[pallet::constant] type HeadersToKeep: Get; diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index a4ecb0467b79a..33c6eae6eb23b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -149,7 +149,7 @@ parameter_types! { pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; pub storage TokenConversionRate: FixedU128 = 1.into(); - pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; + pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; } #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index d7a74656c0cfd..50bfc4567645e 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -25,8 +25,9 @@ use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; +use bp_runtime::StorageProofError; use codec::{Decode, Encode}; -use frame_support::RuntimeDebug; +use frame_support::{traits::Contains, RuntimeDebug}; use scale_info::TypeInfo; use sp_runtime::traits::Header as HeaderT; use sp_std::vec::Vec; @@ -90,11 +91,20 @@ pub mod pallet { #[pallet::constant] type ParasPalletName: Get<&'static str>; + /// Set of parachains that are tracked by this pallet. + /// + /// The set may be extended easily, without requiring any runtime upgrades. Removing tracked + /// parachain requires special handling - pruning existing heads and cleaning related data + /// structures. + type TrackedParachains: Contains; + /// Maximal number of single parachain heads to keep in the storage. /// /// The setting is there to prevent growing the on-chain state indefinitely. Note /// the setting does not relate to parachain block numbers - we will simply keep as much /// items in the storage, so it doesn't guarantee any fixed timeframe for heads. + /// + /// Incautious change of this constant may lead to orphan entries in the runtime storage. #[pallet::constant] type HeadsToKeep: Get; } @@ -156,17 +166,40 @@ pub mod pallet { sp_trie::StorageProof::new(parachain_heads_proof), move |storage| { for parachain in parachains { - // TODO: https://github.com/paritytech/parity-bridges-common/issues/1393 + // if we're not tracking this parachain, we'll just ignore its head proof here + if !T::TrackedParachains::contains(¶chain) { + log::trace!( + target: "runtime::bridge-parachains", + "The head of parachain {:?} has been provided, but it is not tracked by the pallet", + parachain, + ); + continue; + } + let parachain_head = match Pallet::::read_parachain_head(&storage, parachain) { - Some(parachain_head) => parachain_head, - None => { + Ok(Some(parachain_head)) => parachain_head, + Ok(None) => { + log::trace!( + target: "runtime::bridge-parachains", + "The head of parachain {:?} is None. {}", + parachain, + if BestParaHeads::::contains_key(¶chain) { + "Looks like it is not yet registered at the source relay chain" + } else { + "Looks like it has been deregistered from the source relay chain" + }, + ); + continue; + }, + Err(e) => { log::trace!( target: "runtime::bridge-parachains", - "The head of parachain {:?} has been declared, but is missing from the proof", + "The read of head of parachain {:?} has failed: {:?}", parachain, + e, ); continue; - } + }, }; let _: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { @@ -183,14 +216,6 @@ pub mod pallet { ) .map_err(|_| Error::::InvalidStorageProof)?; - // TODO: there may be parachains we are not interested in - so we only need to accept - // intersection of `parachains-interesting-to-us` and `parachains` - // https://github.com/paritytech/parity-bridges-common/issues/1392 - - // TODO: if some parachain is no more interesting to us, we should start pruning its - // heads - // https://github.com/paritytech/parity-bridges-common/issues/1392 - Ok(()) } } @@ -232,12 +257,10 @@ pub mod pallet { fn read_parachain_head( storage: &bp_runtime::StorageProofChecker, parachain: ParaId, - ) -> Option { + ) -> Result, StorageProofError> { let parachain_head_key = parachain_head_storage_key_at_source(T::ParasPalletName::get(), parachain); - let parachain_head = storage.read_value(parachain_head_key.0.as_ref()).ok()??; - let parachain_head = ParaHead::decode(&mut ¶chain_head[..]).ok()?; - Some(parachain_head) + storage.read_and_decode_value(parachain_head_key.0.as_ref()) } /// Try to update parachain head. @@ -327,7 +350,9 @@ pub mod pallet { #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME}; + use crate::mock::{ + run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, + }; use bp_test_utils::{authority_list, make_default_justification}; use frame_support::{assert_noop, assert_ok, traits::OnInitialize}; @@ -510,6 +535,43 @@ mod tests { }); } + #[test] + fn ignores_untracked_parachain() { + let (state_root, proof) = prepare_parachain_heads_proof(vec![ + (1, head_data(1, 5)), + (UNTRACKED_PARACHAIN_ID, head_data(1, 5)), + (2, head_data(1, 5)), + ]); + run_test(|| { + // start with relay block #0 and try to import head#5 of parachain#1 and untracked + // parachain + initialize(state_root); + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + test_relay_header(0, state_root).hash(), + vec![ParaId(1), ParaId(UNTRACKED_PARACHAIN_ID), ParaId(2)], + proof, + )); + assert_eq!( + BestParaHeads::::get(ParaId(1)), + Some(BestParaHead { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash(), + next_imported_hash_position: 1, + }) + ); + assert_eq!(BestParaHeads::::get(ParaId(UNTRACKED_PARACHAIN_ID)), None,); + assert_eq!( + BestParaHeads::::get(ParaId(2)), + Some(BestParaHead { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash(), + next_imported_hash_position: 1, + }) + ); + }); + } + #[test] fn does_nothing_when_already_imported_this_head_at_previous_relay_header() { let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 506783cdb4966..c314fe7ab17c7 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_polkadot_core::parachains::ParaId; use bp_runtime::Chain; -use frame_support::{construct_runtime, parameter_types, weights::Weight}; +use frame_support::{construct_runtime, parameter_types, traits::IsInVec, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, Header as HeaderT, IdentityLookup}, @@ -34,6 +35,7 @@ type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; pub const PARAS_PALLET_NAME: &str = "Paras"; +pub const UNTRACKED_PARACHAIN_ID: u32 = 10; construct_runtime! { pub enum TestRuntime where @@ -106,11 +108,13 @@ impl pallet_bridge_grandpa::Config for TestRun parameter_types! { pub const HeadsToKeep: u32 = 4; pub const ParasPalletName: &'static str = PARAS_PALLET_NAME; + pub GetTenFirstParachains: Vec = (0..10).map(ParaId).collect(); } impl pallet_bridge_parachains::Config for TestRuntime { type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type ParasPalletName = ParasPalletName; + type TrackedParachains = IsInVec; type HeadsToKeep = HeadsToKeep; } diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 30976ff7fb8e8..24b7dac97e070 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -16,6 +16,7 @@ //! Logic for checking Substrate storage proofs. +use codec::Decode; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; @@ -50,18 +51,29 @@ 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. + /// incomplete or otherwise invalid proof, this function returns an error. pub fn read_value(&self, key: &[u8]) -> Result>, Error> { // LayoutV1 or LayoutV0 is identical for proof that only read values. read_trie_value::, _>(&self.db, &self.root, key) .map_err(|_| Error::StorageValueUnavailable) } + + /// Reads and decodes a value from the available subset of storage. If the value cannot be read + /// due to an incomplete or otherwise invalid proof, this function returns an error. If value is + /// read, but decoding fails, this function returns an error. + pub fn read_and_decode_value(&self, key: &[u8]) -> Result, Error> { + self.read_value(key).and_then(|v| { + v.map(|v| T::decode(&mut &v[..]).map_err(Error::StorageValueDecodeFailed)) + .transpose() + }) + } } #[derive(Eq, RuntimeDebug, PartialEq)] pub enum Error { StorageRootMismatch, StorageValueUnavailable, + StorageValueDecodeFailed(codec::Error), } /// Return valid storage proof and state root. @@ -69,6 +81,7 @@ pub enum Error { /// NOTE: This should only be used for **testing**. #[cfg(feature = "std")] pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { + use codec::Encode; use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; let state_version = sp_runtime::StateVersion::default(); @@ -79,6 +92,7 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { (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()))]), + (None, vec![(b"key4".to_vec(), Some((42u64, 42u32, 42u16, 42u8).encode()))]), // Value is too big to fit in a branch node (None, vec![(b"key11".to_vec(), Some(vec![0u8; 32]))]), ], @@ -86,7 +100,7 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { )); let root = backend.storage_root(std::iter::empty(), state_version).0; let proof = StorageProof::new( - prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) + prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key4"[..], &b"key22"[..]]) .unwrap() .iter_nodes(), ); @@ -97,6 +111,7 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { #[cfg(test)] pub mod tests { use super::*; + use codec::Encode; #[test] fn storage_proof_check() { @@ -107,8 +122,14 @@ pub mod tests { >::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"key4"), Ok(Some((42u64, 42u32, 42u16, 42u8).encode()))); assert_eq!(checker.read_value(b"key11111"), Err(Error::StorageValueUnavailable)); assert_eq!(checker.read_value(b"key22"), Ok(None)); + assert_eq!(checker.read_and_decode_value(b"key4"), Ok(Some((42u64, 42u32, 42u16, 42u8))),); + assert!(matches!( + checker.read_and_decode_value::<[u8; 64]>(b"key4"), + Err(Error::StorageValueDecodeFailed(_)), + )); // checking proof against invalid commitment fails assert_eq!( From 079c6357ab4b761628a52ea2a4f2cba1b668083e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Jun 2022 12:43:36 +0300 Subject: [PATCH 0699/1210] added one more test to parachains finality pallet (#1435) --- modules/parachains/src/lib.rs | 52 ++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 50bfc4567645e..cafd715f8c878 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -264,7 +264,7 @@ pub mod pallet { } /// Try to update parachain head. - fn update_parachain_head( + pub(super) fn update_parachain_head( parachain: ParaId, stored_best_head: Option, updated_at_relay_block_number: RelayBlockNumber, @@ -691,4 +691,54 @@ mod tests { ); }); } + + #[test] + fn is_not_rewriting_existing_head_if_failed_to_read_updated_head() { + let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10_at_20, proof_10_at_20) = + prepare_parachain_heads_proof(vec![(2, head_data(2, 10))]); + let (state_root_10_at_30, proof_10_at_30) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); + run_test(|| { + // we've already imported head#5 of parachain#1 at relay block#10 + initialize(state_root_5); + import_parachain_1_head(0, state_root_5, proof_5).expect("ok"); + assert_eq!( + Pallet::::best_parachain_head(ParaId(1)), + Some(head_data(1, 5)) + ); + + // then if someone is pretending to provide updated head#10 of parachain#1 at relay + // block#20, but fails to do that + // + // => we'll leave previous value + proceed(20, state_root_10_at_20); + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + test_relay_header(20, state_root_10_at_20).hash(), + vec![ParaId(1)], + proof_10_at_20, + ),); + assert_eq!( + Pallet::::best_parachain_head(ParaId(1)), + Some(head_data(1, 5)) + ); + + // then if someone is pretending to provide updated head#10 of parachain#1 at relay + // block#30, and actualy provides it + // + // => we'll update value + proceed(30, state_root_10_at_30); + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + test_relay_header(30, state_root_10_at_30).hash(), + vec![ParaId(1)], + proof_10_at_30, + ),); + assert_eq!( + Pallet::::best_parachain_head(ParaId(1)), + Some(head_data(1, 10)) + ); + }); + } } From f8afd0bf79b421f9592d52ce0898edc1ae56853d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Jun 2022 10:50:55 +0300 Subject: [PATCH 0700/1210] Parachains pallet benchmarks (#1436) * added parachains pallet benchmarks * deduplicate insertion of bridged header * pruning weight * fixes * fix compilation --- bin/millau/runtime/Cargo.toml | 1 + bin/millau/runtime/src/lib.rs | 32 +++++- .../runtime/src/rialto_parachain_messages.rs | 4 +- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/lib.rs | 1 + .../src/messages_benchmarking.rs | 46 ++++---- .../src/parachains_benchmarking.rs | 80 +++++++++++++ modules/messages/src/benchmarking.rs | 38 ++----- modules/parachains/Cargo.toml | 4 + modules/parachains/src/benchmarking.rs | 105 ++++++++++++++++++ modules/parachains/src/lib.rs | 93 +++++++++++++--- modules/parachains/src/mock.rs | 1 + modules/parachains/src/weights.rs | 98 ++++++++++++++++ modules/parachains/src/weights_ext.rs | 97 ++++++++++++++++ primitives/polkadot-core/src/parachains.rs | 11 +- primitives/runtime/src/lib.rs | 4 +- primitives/runtime/src/storage_proof.rs | 16 +++ .../src/chains/rialto_parachains_to_millau.rs | 2 +- .../src/parachains/source.rs | 2 +- relays/parachains/src/parachains_loop.rs | 2 +- 20 files changed, 565 insertions(+), 74 deletions(-) create mode 100644 bin/runtime-common/src/parachains_benchmarking.rs create mode 100644 modules/parachains/src/benchmarking.rs create mode 100644 modules/parachains/src/weights.rs create mode 100644 modules/parachains/src/weights_ext.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 9e8f50a38ef7e..a98fc2f6c30eb 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -145,6 +145,7 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3b4b06fbc147d..fbc3f8e374aed 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -515,9 +515,10 @@ parameter_types! { } /// Instance of the with-Rialto parachains token swap pallet. -pub type WitRialtoParachainsInstance = (); +pub type WithRialtoParachainsInstance = (); -impl pallet_bridge_parachains::Config for Runtime { +impl pallet_bridge_parachains::Config for Runtime { + type WeightInfo = pallet_bridge_parachains::weights::MillauWeight; type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; type ParasPalletName = RialtoParasPalletName; type TrackedParachains = frame_support::traits::Everything; @@ -807,7 +808,7 @@ impl_runtime_apis! { use bp_rialto_parachain::RIALTO_PARACHAIN_ID; let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::< Runtime, - WitRialtoParachainsInstance, + WithRialtoParachainsInstance, >::best_parachain_head(RIALTO_PARACHAIN_ID.into()) .and_then(|encoded_header| bp_rialto_parachain::Header::decode(&mut &encoded_header.0[..]).ok()); match best_rialto_parachain_head { @@ -901,11 +902,13 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; + use pallet_bridge_parachains::benchmarking::Pallet as ParachainsBench; let mut list = Vec::::new(); list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); + list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::); let storage_info = AllPalletsWithSystem::storage_info(); @@ -942,6 +945,10 @@ impl_runtime_apis! { MessageParams, MessageProofParams, }; + use pallet_bridge_parachains::benchmarking::{ + Pallet as ParachainsBench, + Config as ParachainsConfig, + }; use rialto_messages::WithRialtoMessageBridge; impl MessagesConfig for Runtime { @@ -991,6 +998,19 @@ impl_runtime_apis! { } } + impl ParachainsConfig for Runtime { + fn prepare_parachain_heads_proof( + parachains: &[bp_polkadot_core::parachains::ParaId], + parachain_head_size: u32, + proof_size: bp_runtime::StorageProofSize, + ) -> (pallet_bridge_parachains::RelayBlockHash, bp_polkadot_core::parachains::ParaHeadsProof) { + bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::( + parachains, + parachain_head_size, + proof_size, + ) + } + } add_benchmark!( params, @@ -999,6 +1019,12 @@ impl_runtime_apis! { MessagesBench:: ); add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); + add_benchmark!( + params, + batches, + pallet_bridge_parachains, + ParachainsBench:: + ); Ok(batches) } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 3ac2690888259..26b2b5d4c48b7 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -252,7 +252,7 @@ impl TargetHeaderChain(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof) } } @@ -274,7 +274,7 @@ impl SourceHeaderChain for RialtoParachain { WithRialtoParachainMessageBridge, bp_rialto_parachain::Header, Runtime, - crate::WitRialtoParachainsInstance, + crate::WithRialtoParachainsInstance, >(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof, messages_count) } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 61251847bb07e..198df7f163214 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -18,6 +18,7 @@ static_assertions = { version = "1.1", optional = true } # Bridge dependencies bp-messages = { path = "../../primitives/messages", default-features = false } +bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } @@ -49,6 +50,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-x default = ["std"] std = [ "bp-messages/std", + "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", "codec/std", diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index c7fb98aba767d..616a55d436625 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -21,6 +21,7 @@ pub mod messages; pub mod messages_api; pub mod messages_benchmarking; +pub mod parachains_benchmarking; #[cfg(feature = "integrity-test")] pub mod integrity; diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index f789bee9f7b14..880cb8fd55c18 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -27,10 +27,11 @@ use crate::messages::{ }; use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; +use bp_runtime::StorageProofSize; use codec::Encode; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_messages::benchmarking::{ - MessageDeliveryProofParams, MessageParams, MessageProofParams, ProofSize, + MessageDeliveryProofParams, MessageParams, MessageProofParams, }; use sp_core::Hasher; use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; @@ -59,7 +60,7 @@ where R: frame_system::Config>> + pallet_balances::Config>> + pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain

, + R::BridgedChain: bp_runtime::Chain>, Header = BH>, B: MessageBridge, BI: 'static, FI: 'static, @@ -76,14 +77,14 @@ where + IdentifyAccount>>, { let message_payload = match params.size { - ProofSize::Minimal(ref size) => vec![0u8; *size as _], + StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], _ => vec![], }; // finally - prepare storage proof and update environment let (state_root, storage_proof) = prepare_messages_storage_proof::(¶ms, message_payload); - let bridged_header_hash = insert_bridged_chain_header::(state_root); + let bridged_header_hash = insert_header_to_grandpa_pallet::(state_root); ( FromBridgedChainMessagesProof { @@ -103,7 +104,7 @@ pub fn prepare_message_delivery_proof( ) -> FromBridgedChainMessagesDeliveryProof>> where R: pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain
, + R::BridgedChain: bp_runtime::Chain>, Header = BH>, FI: 'static, B: MessageBridge, BH: Header>>, @@ -131,7 +132,7 @@ where let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); // finally insert header with given state root to our storage - let bridged_header_hash = insert_bridged_chain_header::(root); + let bridged_header_hash = insert_header_to_grandpa_pallet::(root); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), @@ -203,19 +204,16 @@ where (root, storage_proof) } -/// Insert Bridged chain header with given state root into storage of GRANDPA pallet at This chain. -fn insert_bridged_chain_header( - state_root: HashOf>, -) -> HashOf> +/// Insert header to the bridge GRANDPA pallet. +pub(crate) fn insert_header_to_grandpa_pallet( + state_root: bp_runtime::HashOf, +) -> bp_runtime::HashOf where - R: pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain
, - FI: 'static, - B: MessageBridge, - BH: Header>>, - HashOf>: Default, + R: pallet_bridge_grandpa::Config, + GI: 'static, + R::BridgedChain: bp_runtime::Chain, { - let bridged_header = BH::new( + let bridged_header = bp_runtime::HeaderOf::::new( Zero::zero(), Default::default(), state_root, @@ -223,16 +221,20 @@ where Default::default(), ); let bridged_header_hash = bridged_header.hash(); - pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); + pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); bridged_header_hash } /// Populate trie with dummy keys+values until trie has at least given size. -fn grow_trie(mut root: H::Out, mdb: &mut MemoryDB, trie_size: ProofSize) -> H::Out { +pub fn grow_trie( + mut root: H::Out, + mdb: &mut MemoryDB, + trie_size: StorageProofSize, +) -> H::Out { let (iterations, leaf_size, minimal_trie_size) = match trie_size { - ProofSize::Minimal(_) => return root, - ProofSize::HasLargeLeaf(size) => (1, size, size), - ProofSize::HasExtraNodes(size) => (8, 1, size), + StorageProofSize::Minimal(_) => return root, + StorageProofSize::HasLargeLeaf(size) => (1, size, size), + StorageProofSize::HasExtraNodes(size) => (8, 1, size), }; let mut key_index = 0; diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs new file mode 100644 index 0000000000000..e2635eb2543c1 --- /dev/null +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -0,0 +1,80 @@ +// 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 . + +//! Everything required to run benchmarks of parachains finality module. + +#![cfg(feature = "runtime-benchmarks")] + +use crate::messages_benchmarking::{grow_trie, insert_header_to_grandpa_pallet}; + +use bp_parachains::parachain_head_storage_key_at_source; +use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId}; +use bp_runtime::StorageProofSize; +use codec::Encode; +use frame_support::traits::Get; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher}; +use sp_std::prelude::*; +use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; + +/// Prepare proof of messages for the `receive_messages_proof` call. +/// +/// In addition to returning valid messages proof, environment is prepared to verify this message +/// proof. +pub fn prepare_parachain_heads_proof( + parachains: &[ParaId], + parachain_head_size: u32, + size: StorageProofSize, +) -> (RelayBlockHash, ParaHeadsProof) +where + R: pallet_bridge_parachains::Config + + pallet_bridge_grandpa::Config, + PI: 'static, + >::BridgedChain: + bp_runtime::Chain, +{ + let parachain_head = ParaHead(vec![0u8; parachain_head_size as usize]); + + // insert all heads to the trie + let mut storage_keys = Vec::with_capacity(parachains.len()); + let mut state_root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMutV1::::new(&mut mdb, &mut state_root); + + // insert parachain heads + for parachain in parachains { + let storage_key = + parachain_head_storage_key_at_source(R::ParasPalletName::get(), *parachain); + trie.insert(&storage_key.0, ¶chain_head.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + } + state_root = grow_trie(state_root, &mut mdb, size); + + // generate heads storage proof + let mut proof_recorder = Recorder::::new(); + record_all_keys::, _>(&mdb, &state_root, &mut proof_recorder) + .map_err(|_| "record_all_keys has failed") + .expect("record_all_keys should not fail in benchmarks"); + let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + let relay_block_hash = + insert_header_to_grandpa_pallet::(state_root); + + (relay_block_hash, ParaHeadsProof(proof)) +} diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 46a8150d034bd..66aa70312cc9a 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -26,7 +26,7 @@ use bp_messages::{ InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, }; -use bp_runtime::messages::DispatchFeePayment; +use bp_runtime::{messages::DispatchFeePayment, StorageProofSize}; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::{traits::Get, weights::Weight}; use frame_system::RawOrigin; @@ -37,20 +37,6 @@ const SEED: u32 = 0; /// Pallet we're benchmarking here. pub struct Pallet, I: 'static>(crate::Pallet); -/// Proof size requirements. -#[derive(Clone, Copy, Debug)] -pub enum ProofSize { - /// The proof is expected to be minimal. If value size may be changed, then it is expected to - /// have given size. - Minimal(u32), - /// The proof is expected to have at least given size and grow by increasing number of trie - /// nodes included in the proof. - HasExtraNodes(u32), - /// The proof is expected to have at least given size and grow by increasing value that is - /// stored in the trie. - HasLargeLeaf(u32), -} - /// Benchmark-specific message parameters. #[derive(Debug)] pub struct MessageParams { @@ -70,7 +56,7 @@ pub struct MessageProofParams { /// If `Some`, the proof needs to include this outbound lane data. pub outbound_lane_data: Option, /// Proof size requirements. - pub size: ProofSize, + pub size: StorageProofSize, /// Where the fee for dispatching message is paid? pub dispatch_fee_payment: DispatchFeePayment, } @@ -83,7 +69,7 @@ pub struct MessageDeliveryProofParams { /// The proof needs to include this inbound lane data. pub inbound_lane_data: InboundLaneData, /// Proof size requirements. - pub size: ProofSize, + pub size: StorageProofSize, } /// Trait that must be implemented by runtime. @@ -302,7 +288,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -337,7 +323,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=22, outbound_lane_data: None, - size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) @@ -376,7 +362,7 @@ benchmarks_instance_pallet! { latest_received_nonce: 20, latest_generated_nonce: 21, }), - size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -408,7 +394,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: ProofSize::HasExtraNodes(1024), + size: StorageProofSize::HasExtraNodes(1024), dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -443,7 +429,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: ProofSize::HasExtraNodes(16 * 1024), + size: StorageProofSize::HasExtraNodes(16 * 1024), dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -477,7 +463,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: ProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), + size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -517,7 +503,7 @@ benchmarks_instance_pallet! { }].into_iter().collect(), last_confirmed_nonce: 0, }, - size: ProofSize::Minimal(0), + size: StorageProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { @@ -560,7 +546,7 @@ benchmarks_instance_pallet! { }].into_iter().collect(), last_confirmed_nonce: 0, }, - size: ProofSize::Minimal(0), + size: StorageProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { @@ -606,7 +592,7 @@ benchmarks_instance_pallet! { ].into_iter().collect(), last_confirmed_nonce: 0, }, - size: ProofSize::Minimal(0), + size: StorageProofSize::Minimal(0), }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) verify { diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index e6942bf7ce349..8636c7a40b6d2 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -20,6 +20,7 @@ pallet-bridge-grandpa = { path = "../grandpa", default-features = false } # Substrate Dependencies +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -50,3 +51,6 @@ std = [ "sp-std/std", "sp-trie/std", ] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", +] diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs new file mode 100644 index 0000000000000..2734dfafd6fa2 --- /dev/null +++ b/modules/parachains/src/benchmarking.rs @@ -0,0 +1,105 @@ +// 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 . + +//! Parachains finality pallet benchmarking. + +use crate::{ + weights_ext::DEFAULT_PARACHAIN_HEAD_SIZE, Call, RelayBlockHash, RelayBlockHasher, + RelayBlockNumber, +}; + +use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; +use bp_runtime::StorageProofSize; +use frame_benchmarking::{account, benchmarks_instance_pallet}; +use frame_system::RawOrigin; +use sp_std::prelude::*; + +/// Pallet we're benchmarking here. +pub struct Pallet, I: 'static>(crate::Pallet); + +/// Trait that must be implemented by runtime to benchmark the parachains finality pallet. +pub trait Config: crate::Config { + /// Generate parachain heads proof and prepare environment for verifying this proof. + fn prepare_parachain_heads_proof( + parachains: &[ParaId], + parachain_head_size: u32, + proof_size: StorageProofSize, + ) -> (RelayBlockHash, ParaHeadsProof); +} + +benchmarks_instance_pallet! { + where_clause { + where + >::BridgedChain: + bp_runtime::Chain< + BlockNumber = RelayBlockNumber, + Hash = RelayBlockHash, + Hasher = RelayBlockHasher, + >, + } + + // Benchmark `submit_parachain_heads` extrinsic with different number of parachains. + submit_parachain_heads_with_n_parachains { + let p in 1..1024; + + let sender = account("sender", 0, 0); + let parachains = (1..=p).map(ParaId).collect::>(); + let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + ¶chains, + DEFAULT_PARACHAIN_HEAD_SIZE, + StorageProofSize::Minimal(0), + ); + }: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof) + verify { + for parachain in parachains { + assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); + } + } + + // Benchmark `submit_parachain_heads` extrinsic with 1kb proof size. + submit_parachain_heads_with_1kb_proof { + let sender = account("sender", 0, 0); + let parachains = vec![ParaId(1)]; + let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + ¶chains, + DEFAULT_PARACHAIN_HEAD_SIZE, + StorageProofSize::HasExtraNodes(1024), + ); + + }: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof) + verify { + for parachain in parachains { + assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); + } + } + + // Benchmark `submit_parachain_heads` extrinsic with 16kb proof size. + submit_parachain_heads_with_16kb_proof { + let sender = account("sender", 0, 0); + let parachains = vec![ParaId(1)]; + let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + ¶chains, + DEFAULT_PARACHAIN_HEAD_SIZE, + StorageProofSize::HasExtraNodes(16 * 1024), + ); + + }: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof) + verify { + for parachain in parachains { + assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); + } + } +} diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index cafd715f8c878..4cedffc300b82 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -23,11 +23,14 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub use weights::WeightInfo; +pub use weights_ext::WeightInfoExt; + use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::StorageProofError; use codec::{Decode, Encode}; -use frame_support::{traits::Contains, RuntimeDebug}; +use frame_support::{traits::Contains, weights::PostDispatchInfo, RuntimeDebug}; use scale_info::TypeInfo; use sp_runtime::traits::Header as HeaderT; use sp_std::vec::Vec; @@ -35,6 +38,12 @@ use sp_std::vec::Vec; // Re-export in crate namespace for `construct_runtime!`. pub use pallet::*; +pub mod weights; +pub mod weights_ext; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + #[cfg(test)] mod mock; @@ -56,12 +65,23 @@ pub struct BestParaHead { pub next_imported_hash_position: u32, } +/// Artifacts of the parachains head update. +struct UpdateParachainHeadArtifacts { + /// New best head of the parachain. + pub best_head: BestParaHead, + /// If `true`, some old parachain head has been pruned during update. + pub prune_happened: bool, +} + #[frame_support::pallet] pub mod pallet { use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; + /// Weight info of the given parachains pallet. + pub type WeightInfoOf = >::WeightInfo; + #[pallet::error] pub enum Error { /// Relay chain block is unknown to us. @@ -81,6 +101,9 @@ pub mod pallet { pub trait Config: pallet_bridge_grandpa::Config { + /// Benchmarks results from runtime we're plugged into. + type WeightInfo: WeightInfoExt; + /// Instance of bridges GRANDPA pallet (within this runtime) that this pallet is linked to. /// /// The GRANDPA pallet instance must be configured to import headers of relay chain that @@ -145,13 +168,17 @@ pub mod pallet { /// `polkadot-runtime-parachains::paras` pallet instance, deployed at the bridged chain. /// The proof is supposed to be crafted at the `relay_header_hash` that must already be /// imported by corresponding GRANDPA pallet at this chain. - #[pallet::weight(0)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1391 + #[pallet::weight(WeightInfoOf::::submit_parachain_heads_weight( + T::DbWeight::get(), + parachain_heads_proof, + parachains.len() as _, + ))] pub fn submit_parachain_heads( _origin: OriginFor, relay_block_hash: RelayBlockHash, parachains: Vec, parachain_heads_proof: ParaHeadsProof, - ) -> DispatchResult { + ) -> DispatchResultWithPostInfo { // we'll need relay chain header to verify that parachains heads are always increasing. let relay_block = pallet_bridge_grandpa::ImportedHeaders::< T, @@ -161,9 +188,14 @@ pub mod pallet { let relay_block_number = *relay_block.number(); // now parse storage proof and read parachain heads + let mut actual_weight = WeightInfoOf::::submit_parachain_heads_weight( + T::DbWeight::get(), + ¶chain_heads_proof, + parachains.len() as _, + ); pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( relay_block_hash, - sp_trie::StorageProof::new(parachain_heads_proof), + sp_trie::StorageProof::new(parachain_heads_proof.0), move |storage| { for parachain in parachains { // if we're not tracking this parachain, we'll just ignore its head proof here @@ -202,21 +234,27 @@ pub mod pallet { }, }; - let _: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { - *stored_best_head = Some(Pallet::::update_parachain_head( + let prune_happened: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { + let artifacts = Pallet::::update_parachain_head( parachain, stored_best_head.take(), relay_block_number, parachain_head, - )?); - Ok(()) + )?; + *stored_best_head = Some(artifacts.best_head); + Ok(artifacts.prune_happened) }); + + if matches!(prune_happened, Err(_) | Ok(false)) { + actual_weight = actual_weight + .saturating_sub(WeightInfoOf::::parachain_head_pruning_weight(T::DbWeight::get())); + } } }, ) .map_err(|_| Error::::InvalidStorageProof)?; - Ok(()) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } } @@ -269,7 +307,7 @@ pub mod pallet { stored_best_head: Option, updated_at_relay_block_number: RelayBlockNumber, updated_head: ParaHead, - ) -> Result { + ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order let updated_head_hash = updated_head.hash(); @@ -332,6 +370,7 @@ pub mod pallet { ); // remove old head + let prune_happened = head_hash_to_prune.is_ok(); if let Ok(head_hash_to_prune) = head_hash_to_prune { log::trace!( target: "runtime::bridge-parachains", @@ -342,7 +381,7 @@ pub mod pallet { ImportedParaHeads::::remove(parachain, head_hash_to_prune); } - Ok(updated_best_para_head) + Ok(UpdateParachainHeadArtifacts { best_head: updated_best_para_head, prune_happened }) } } } @@ -355,7 +394,12 @@ mod tests { }; use bp_test_utils::{authority_list, make_default_justification}; - use frame_support::{assert_noop, assert_ok, traits::OnInitialize}; + use frame_support::{ + assert_noop, assert_ok, + dispatch::DispatchResultWithPostInfo, + traits::{Get, OnInitialize}, + weights::Weight, + }; use sp_trie::{ record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut, }; @@ -414,7 +458,7 @@ mod tests { .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - (root, storage_proof) + (root, ParaHeadsProof(storage_proof)) } fn initial_best_head(parachain: u32) -> BestParaHead { @@ -437,7 +481,7 @@ mod tests { relay_chain_block: RelayBlockNumber, relay_state_root: RelayBlockHash, proof: ParaHeadsProof, - ) -> sp_runtime::DispatchResult { + ) -> DispatchResultWithPostInfo { Pallet::::submit_parachain_heads( Origin::signed(1), test_relay_header(relay_chain_block, relay_state_root).hash(), @@ -446,6 +490,16 @@ mod tests { ) } + fn weight_of_import_parachain_1_head(proof: &ParaHeadsProof, prune_expected: bool) -> Weight { + let db_weight = ::DbWeight::get(); + WeightInfoOf::::submit_parachain_heads_weight(db_weight, proof, 1) + .saturating_sub(if prune_expected { + 0 + } else { + WeightInfoOf::::parachain_head_pruning_weight(db_weight) + }) + } + #[test] fn imports_initial_parachain_heads() { let (state_root, proof) = @@ -636,7 +690,11 @@ mod tests { } else { proceed(i, state_root); } - assert_ok!(import_parachain_1_head(i, state_root, proof)); + + let expected_weight = weight_of_import_parachain_1_head(&proof, false); + let result = import_parachain_1_head(i, state_root, proof); + assert_ok!(result); + assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); } // nothing is pruned yet @@ -649,7 +707,10 @@ mod tests { let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]); proceed(heads_to_keep, state_root); - assert_ok!(import_parachain_1_head(heads_to_keep, state_root, proof)); + let expected_weight = weight_of_import_parachain_1_head(&proof, true); + let result = import_parachain_1_head(heads_to_keep, state_root, proof); + assert_ok!(result); + assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); // and the head#0 is pruned assert!( diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index c314fe7ab17c7..e07b0a91010d1 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -112,6 +112,7 @@ parameter_types! { } impl pallet_bridge_parachains::Config for TestRuntime { + type WeightInfo = (); type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type ParasPalletName = ParasPalletName; type TrackedParachains = IsInVec; diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs new file mode 100644 index 0000000000000..e203e3ef521e1 --- /dev/null +++ b/modules/parachains/src/weights.rs @@ -0,0 +1,98 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_parachains` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-06-06, STEPS: 50, REPEAT: 20 +//! LOW RANGE: [], HIGH RANGE: [] +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled +//! CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/millau-bridge-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_bridge_parachains +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./modules/parachains/src/weights.rs +// --template=./.maintain/millau-weight-template.hbs + +#![allow(clippy::all)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for `pallet_bridge_parachains`. +pub trait WeightInfo { + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight; + fn submit_parachain_heads_with_1kb_proof() -> Weight; + fn submit_parachain_heads_with_16kb_proof() -> Weight; +} + +/// Weights for `pallet_bridge_parachains` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { + (0 as Weight) + .saturating_add((18_729_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) + .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) + } + fn submit_parachain_heads_with_1kb_proof() -> Weight { + (25_355_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } + fn submit_parachain_heads_with_16kb_proof() -> Weight { + (74_570_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { + (0 as Weight) + .saturating_add((18_729_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) + .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) + } + fn submit_parachain_heads_with_1kb_proof() -> Weight { + (25_355_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } + fn submit_parachain_heads_with_16kb_proof() -> Weight { + (74_570_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + } +} diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs new file mode 100644 index 0000000000000..3f3815eed96c6 --- /dev/null +++ b/modules/parachains/src/weights_ext.rs @@ -0,0 +1,97 @@ +// 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 . + +//! Weight-related utilities. + +use crate::weights::{MillauWeight, WeightInfo}; + +use bp_runtime::Size; +use frame_support::weights::{RuntimeDbWeight, Weight}; + +/// Size of the regular parachain head. +/// +/// It's not that we are expecting all parachain heads to share the same size or that we would +/// reject all heads that have larger/lesser size. It is about head size that we use in benchmarks. +/// Relayer would need to pay additional fee for extra bytes. +/// +/// 384 is a bit larger (1.3 times) than the size of the randomly chosen Polkadot block. +pub const DEFAULT_PARACHAIN_HEAD_SIZE: u32 = 384; + +/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at +/// the Rialto chain. +pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; + +/// Extended weight info. +pub trait WeightInfoExt: WeightInfo { + /// Storage proof overhead, that is included in every storage proof. + /// + /// The relayer would pay some extra fee for additional proof bytes, since they mean + /// more hashing operations. + fn expected_extra_storage_proof_size() -> u32; + + /// Weight of the parachain heads delivery extrinsic. + fn submit_parachain_heads_weight( + db_weight: RuntimeDbWeight, + proof: &impl Size, + parachains_count: u32, + ) -> Weight { + // weight of the `submit_parachain_heads` with exactly `parachains_count` parachain + // heads of the default size (`DEFAULT_PARACHAIN_HEAD_SIZE`) + let base_weight = Self::submit_parachain_heads_with_n_parachains(parachains_count); + + // overhead because of extra storage proof bytes + let expected_proof_size = parachains_count + .saturating_mul(DEFAULT_PARACHAIN_HEAD_SIZE) + .saturating_add(Self::expected_extra_storage_proof_size()); + let actual_proof_size = proof.size_hint(); + let proof_size_overhead = Self::storage_proof_size_overhead( + actual_proof_size.saturating_sub(expected_proof_size), + ); + + // potential pruning weight (refunded if hasn't happened) + let pruning_weight = (parachains_count as Weight) + .saturating_mul(Self::parachain_head_pruning_weight(db_weight)); + + base_weight.saturating_add(proof_size_overhead).saturating_add(pruning_weight) + } + + /// Returns weight of single parachain head pruning. + fn parachain_head_pruning_weight(db_weight: RuntimeDbWeight) -> Weight { + // it's just one write operation, we don't want any benchmarks for that + db_weight.writes(1) + } + + /// Returns weight that needs to be accounted when storage proof of given size is received. + fn storage_proof_size_overhead(extra_proof_bytes: u32) -> Weight { + let extra_proof_bytes_in_bytes = extra_proof_bytes as Weight; + let extra_byte_weight = (Self::submit_parachain_heads_with_16kb_proof() - + Self::submit_parachain_heads_with_1kb_proof()) / + (15 * 1024); + extra_proof_bytes_in_bytes.saturating_mul(extra_byte_weight) + } +} + +impl WeightInfoExt for () { + fn expected_extra_storage_proof_size() -> u32 { + EXTRA_STORAGE_PROOF_SIZE + } +} + +impl WeightInfoExt for MillauWeight { + fn expected_extra_storage_proof_size() -> u32 { + EXTRA_STORAGE_PROOF_SIZE + } +} diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 8980c46c6ed21..af05e7e98582b 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -22,6 +22,7 @@ //! chains. Having pallets that are referencing polkadot, would mean that there may //! be two versions of polkadot crates included in the runtime. Which is bad. +use bp_runtime::Size; use frame_support::RuntimeDebug; use parity_scale_codec::{CompactAs, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -88,4 +89,12 @@ pub type ParaHash = crate::Hash; pub type ParaHasher = crate::Hasher; /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. -pub type ParaHeadsProof = Vec>; +#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] +pub struct ParaHeadsProof(pub Vec>); + +impl Size for ParaHeadsProof { + fn size_hint(&self) -> u32 { + u32::try_from(self.0.iter().fold(0usize, |sum, node| sum.saturating_add(node.len()))) + .unwrap_or(u32::MAX) + } +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index cd3ea448e1d55..bd09a651c7204 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -29,7 +29,9 @@ pub use chain::{ 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}; +pub use storage_proof::{ + Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker, +}; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 24b7dac97e070..8236c0f2232c7 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -22,6 +22,22 @@ use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; use sp_trie::{read_trie_value, LayoutV1, MemoryDB, StorageProof}; +/// Storage proof size requirements. +/// +/// This is currently used by benchmarks when generating storage proofs. +#[derive(Clone, Copy, Debug)] +pub enum ProofSize { + /// The proof is expected to be minimal. If value size may be changed, then it is expected to + /// have given size. + Minimal(u32), + /// The proof is expected to have at least given size and grow by increasing number of trie + /// nodes included in the proof. + HasExtraNodes(u32), + /// The proof is expected to have at least given size and grow by increasing value that is + /// stored in the trie. + HasLargeLeaf(u32), +} + /// 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. diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index 078c24a3e34c4..986c335e1e469 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -49,5 +49,5 @@ pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder = DirectSubmitParachainHeadsCallBuilder< RialtoParachainsToMillau, millau_runtime::Runtime, - millau_runtime::WitRialtoParachainsInstance, + millau_runtime::WithRialtoParachainsInstance, >; diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index ea30143e4b64f..dd239366719fc 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -161,6 +161,6 @@ where .iter_nodes() .collect(); - Ok(parachain_heads_proof) + Ok(ParaHeadsProof(parachain_heads_proof)) } } diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 6e9cc5f1da59b..b1dd74146281c 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -664,7 +664,7 @@ mod tests { .ok_or(TestError::MissingParachainHeadProof)?, ); } - Ok(proofs) + Ok(ParaHeadsProof(proofs)) } } From 401c3f72cb3533d7030abb12411281a452a9230b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Jun 2022 12:04:01 +0300 Subject: [PATCH 0701/1210] remove unused RialtoParachainGrandpaInstance (#1441) --- bin/millau/runtime/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index fbc3f8e374aed..8114d6c92cd3e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -423,15 +423,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; } -pub type RialtoParachainGrandpaInstance = pallet_bridge_grandpa::Instance2; -impl pallet_bridge_grandpa::Config for Runtime { - type BridgedChain = bp_rialto_parachain::RialtoParachain; - type MaxRequests = MaxRequests; - type HeadersToKeep = HeadersToKeep; - - type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; -} - impl pallet_shift_session_manager::Config for Runtime {} parameter_types! { From b6fa3448c4246392f48634cff8e882bc13663ae7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Jun 2022 12:29:03 +0300 Subject: [PATCH 0702/1210] CheckBridgedBlockNumber -> BridgeRejectObsoleteGrandpaHeader (#1442) --- bin/millau/runtime/src/lib.rs | 4 ++-- modules/grandpa/src/extension.rs | 22 +++++++++++----------- relays/client-millau/src/lib.rs | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8114d6c92cd3e..58830a476a84e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -559,7 +559,7 @@ construct_runtime!( } ); -pallet_bridge_grandpa::declare_check_bridged_block_number_ext! { +pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header! { Runtime, Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, Call::BridgeWestendGrandpa => WestendGrandpaInstance @@ -585,7 +585,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, - CheckBridgedBlockNumber, + BridgeRejectObsoleteGrandpaHeader, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index 4a7d19acf2112..43ad622105225 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -14,27 +14,27 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -/// Declares a runtime-specific `CheckBridgedBlockNumber` signed extension. +/// Declares a runtime-specific `BridgeRejectObsoleteGrandpaHeader` signed extension. /// /// ## Example /// /// ```nocompile -/// pallet_bridge_grandpa::declare_check_bridged_block_number_ext!{ +/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header!{ /// Runtime, /// Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, /// Call::BridgeWestendGrandpa => WestendGrandpaInstance, /// } /// ``` #[macro_export] -macro_rules! declare_check_bridged_block_number_ext { +macro_rules! declare_bridge_reject_obsolete_grandpa_header { ($runtime:ident, $($call:path => $instance:ty),*) => { /// Transaction-with-obsolete-bridged-header check that will reject transaction if /// it submits obsolete bridged header. #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] - pub struct CheckBridgedBlockNumber; + pub struct BridgeRejectObsoleteGrandpaHeader; - impl sp_runtime::traits::SignedExtension for CheckBridgedBlockNumber { - const IDENTIFIER: &'static str = "CheckBridgedBlockNumber"; + impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteGrandpaHeader { + const IDENTIFIER: &'static str = "BridgeRejectObsoleteGrandpaHeader"; type AccountId = <$runtime as frame_system::Config>::AccountId; type Call = <$runtime as frame_system::Config>::Call; type AdditionalSigned = (); @@ -114,13 +114,13 @@ mod tests { use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use sp_runtime::traits::SignedExtension; - declare_check_bridged_block_number_ext! { + declare_bridge_reject_obsolete_grandpa_header! { TestRuntime, Call::Grandpa => () } fn validate_block_submit(num: TestNumber) -> bool { - CheckBridgedBlockNumber + BridgeRejectObsoleteGrandpaHeader .validate( &42, &Call::Grandpa(crate::Call::::submit_finality_proof { @@ -140,7 +140,7 @@ mod tests { } #[test] - fn check_bridged_block_number_rejects_obsolete_header() { + fn extension_rejects_obsolete_header() { run_test(|| { // when current best finalized is #10 and we're trying to import header#5 => tx is // rejected @@ -150,7 +150,7 @@ mod tests { } #[test] - fn check_bridged_block_number_rejects_same_header() { + fn extension_rejects_same_header() { run_test(|| { // when current best finalized is #10 and we're trying to import header#10 => tx is // rejected @@ -160,7 +160,7 @@ mod tests { } #[test] - fn check_bridged_block_number_accepts_new_header() { + fn extension_accepts_new_header() { run_test(|| { // when current best finalized is #10 and we're trying to import header#15 => tx is // accepted diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 1fa4708368a36..2779fb0fd3b35 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -115,7 +115,7 @@ impl TransactionSignScheme for Millau { frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), - millau_runtime::CheckBridgedBlockNumber, // TODO + millau_runtime::BridgeRejectObsoleteGrandpaHeader, ), ( (), From 773c5deb3dc8ee6bb6ecd10a27d6bd4fc85cf719 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Jun 2022 15:59:48 +0300 Subject: [PATCH 0703/1210] remove duplicate parachain heads exension (#1444) * remove duplicate parachain heads exension * fix benchmarks compilation * actually fix it --- bin/millau/runtime/src/lib.rs | 12 +- .../src/messages_benchmarking.rs | 11 +- .../src/parachains_benchmarking.rs | 10 +- modules/grandpa/src/extension.rs | 5 + modules/parachains/src/benchmarking.rs | 19 +- modules/parachains/src/extension.rs | 195 ++++++++++++++++++ modules/parachains/src/lib.rs | 23 ++- modules/parachains/src/mock.rs | 2 +- relays/client-millau/src/lib.rs | 2 + .../lib-substrate-relay/src/parachains/mod.rs | 10 +- .../src/parachains/target.rs | 2 +- 11 files changed, 256 insertions(+), 35 deletions(-) create mode 100644 modules/parachains/src/extension.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 58830a476a84e..f9d8f891fd44a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -565,6 +565,11 @@ pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header! { Call::BridgeWestendGrandpa => WestendGrandpaInstance } +pallet_bridge_parachains::declare_bridge_reject_obsolete_parachain_header! { + Runtime, + Call::BridgeRialtoParachains => WithRialtoParachainsInstance +} + /// The address format for describing accounts. pub type Address = AccountId; /// Block header type as expected by this runtime. @@ -586,6 +591,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, BridgeRejectObsoleteGrandpaHeader, + BridgeRejectObsoleteParachainHeader, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; @@ -994,7 +1000,11 @@ impl_runtime_apis! { parachains: &[bp_polkadot_core::parachains::ParaId], parachain_head_size: u32, proof_size: bp_runtime::StorageProofSize, - ) -> (pallet_bridge_parachains::RelayBlockHash, bp_polkadot_core::parachains::ParaHeadsProof) { + ) -> ( + pallet_bridge_parachains::RelayBlockNumber, + pallet_bridge_parachains::RelayBlockHash, + bp_polkadot_core::parachains::ParaHeadsProof, + ) { bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::( parachains, parachain_head_size, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 880cb8fd55c18..865b55f57ccdf 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -84,7 +84,7 @@ where // finally - prepare storage proof and update environment let (state_root, storage_proof) = prepare_messages_storage_proof::(¶ms, message_payload); - let bridged_header_hash = insert_header_to_grandpa_pallet::(state_root); + let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); ( FromBridgedChainMessagesProof { @@ -132,7 +132,7 @@ where let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); // finally insert header with given state root to our storage - let bridged_header_hash = insert_header_to_grandpa_pallet::(root); + let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(root); FromBridgedChainMessagesDeliveryProof { bridged_header_hash: bridged_header_hash.into(), @@ -207,14 +207,15 @@ where /// Insert header to the bridge GRANDPA pallet. pub(crate) fn insert_header_to_grandpa_pallet( state_root: bp_runtime::HashOf, -) -> bp_runtime::HashOf +) -> (bp_runtime::BlockNumberOf, bp_runtime::HashOf) where R: pallet_bridge_grandpa::Config, GI: 'static, R::BridgedChain: bp_runtime::Chain, { + let bridged_block_number = Zero::zero(); let bridged_header = bp_runtime::HeaderOf::::new( - Zero::zero(), + bridged_block_number, Default::default(), state_root, Default::default(), @@ -222,7 +223,7 @@ where ); let bridged_header_hash = bridged_header.hash(); pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); - bridged_header_hash + (bridged_block_number, bridged_header_hash) } /// Populate trie with dummy keys+values until trie has at least given size. diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index e2635eb2543c1..f707f652d8c38 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -25,7 +25,7 @@ use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::StorageProofSize; use codec::Encode; use frame_support::traits::Get; -use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher}; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use sp_std::prelude::*; use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; @@ -37,13 +37,13 @@ pub fn prepare_parachain_heads_proof( parachains: &[ParaId], parachain_head_size: u32, size: StorageProofSize, -) -> (RelayBlockHash, ParaHeadsProof) +) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof) where R: pallet_bridge_parachains::Config + pallet_bridge_grandpa::Config, PI: 'static, >::BridgedChain: - bp_runtime::Chain, + bp_runtime::Chain, { let parachain_head = ParaHead(vec![0u8; parachain_head_size as usize]); @@ -73,8 +73,8 @@ where .expect("record_all_keys should not fail in benchmarks"); let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - let relay_block_hash = + let (relay_block_number, relay_block_hash) = insert_header_to_grandpa_pallet::(state_root); - (relay_block_hash, ParaHeadsProof(proof)) + (relay_block_number, relay_block_hash, ParaHeadsProof(proof)) } diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index 43ad622105225..654b74bf446ea 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -25,6 +25,11 @@ /// Call::BridgeWestendGrandpa => WestendGrandpaInstance, /// } /// ``` +/// +/// The goal of this extension is to avoid "mining" transactions that provide +/// outdated bridged chain headers. Without that extension, even honest relayers +/// may lose their funds if there are multiple relays running and submitting the +/// same information. #[macro_export] macro_rules! declare_bridge_reject_obsolete_grandpa_header { ($runtime:ident, $($call:path => $instance:ty),*) => { diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index 2734dfafd6fa2..749182a82ea69 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -37,7 +37,7 @@ pub trait Config: crate::Config { parachains: &[ParaId], parachain_head_size: u32, proof_size: StorageProofSize, - ) -> (RelayBlockHash, ParaHeadsProof); + ) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof); } benchmarks_instance_pallet! { @@ -57,12 +57,13 @@ benchmarks_instance_pallet! { let sender = account("sender", 0, 0); let parachains = (1..=p).map(ParaId).collect::>(); - let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, StorageProofSize::Minimal(0), ); - }: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof) + let at_relay_block = (relay_block_number, relay_block_hash); + }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof) verify { for parachain in parachains { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); @@ -73,13 +74,13 @@ benchmarks_instance_pallet! { submit_parachain_heads_with_1kb_proof { let sender = account("sender", 0, 0); let parachains = vec![ParaId(1)]; - let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, StorageProofSize::HasExtraNodes(1024), ); - - }: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof) + let at_relay_block = (relay_block_number, relay_block_hash); + }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof) verify { for parachain in parachains { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); @@ -90,13 +91,13 @@ benchmarks_instance_pallet! { submit_parachain_heads_with_16kb_proof { let sender = account("sender", 0, 0); let parachains = vec![ParaId(1)]; - let (relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, StorageProofSize::HasExtraNodes(16 * 1024), ); - - }: submit_parachain_heads(RawOrigin::Signed(sender), relay_block_hash, parachains.clone(), parachain_heads_proof) + let at_relay_block = (relay_block_number, relay_block_hash); + }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof) verify { for parachain in parachains { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs new file mode 100644 index 0000000000000..1d0eb7a7ff908 --- /dev/null +++ b/modules/parachains/src/extension.rs @@ -0,0 +1,195 @@ +// Copyright 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 . + +/// Declares a runtime-specific `BridgeRejectObsoleteParachainHeader` signed extension. +/// +/// ## Example +/// +/// ```nocompile +/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_parachain_header!{ +/// Runtime, +/// Call::BridgeRialtoParachains => RialtoGrandpaInstance, +/// Call::BridgeWestendParachains => WestendGrandpaInstance, +/// } +/// ``` +/// +/// The goal of this extension is to avoid "mining" transactions that provide +/// outdated bridged parachain heads. Without that extension, even honest relayers +/// may lose their funds if there are multiple relays running and submitting the +/// same information. +/// +/// This extension only works with transactions that are updating single parachain +/// head. We can't use unbounded validation - it may take too long and either break +/// block production, or "eat" significant portion of block production time literally +/// for nothing. In addition, the single-parachain-head-per-transaction is how the +/// pallet will be used in our environment. +#[macro_export] +macro_rules! declare_bridge_reject_obsolete_parachain_header { + ($runtime:ident, $($call:path => $instance:ty),*) => { + /// Transaction-with-obsolete-bridged-parachain-header check that will reject transaction if + /// it submits obsolete bridged parachain header. + #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] + pub struct BridgeRejectObsoleteParachainHeader; + + impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteParachainHeader { + const IDENTIFIER: &'static str = "BridgeRejectObsoleteParachainHeader"; + type AccountId = <$runtime as frame_system::Config>::AccountId; + type Call = <$runtime as frame_system::Config>::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result< + (), + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> sp_runtime::transaction_validity::TransactionValidity { + match *call { + $( + $call($crate::Call::<$runtime, $instance>::submit_parachain_heads { + ref at_relay_block, + ref parachains, + .. + }) if parachains.len() == 1 => { + let parachain = parachains.get(0).expect("verified by match condition; qed"); + + let bundled_relay_block_number = at_relay_block.0; + + let best_parachain_head = $crate::BestParaHeads::<$runtime, $instance>::get(parachain); + match best_parachain_head { + Some(best_parachain_head) if best_parachain_head.at_relay_block_number + >= bundled_relay_block_number => + sp_runtime::transaction_validity::InvalidTransaction::Stale.into(), + _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), + } + }, + )* + _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), + } + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(drop) + } + + fn post_dispatch( + _maybe_pre: Option, + _info: &sp_runtime::traits::DispatchInfoOf, + _post_info: &sp_runtime::traits::PostDispatchInfoOf, + _len: usize, + _result: &sp_runtime::DispatchResult, + ) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> { + Ok(()) + } + } + }; +} + +#[cfg(test)] +mod tests { + use crate::{ + mock::{run_test, Call, TestRuntime}, + BestParaHead, BestParaHeads, RelayBlockNumber, + }; + use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; + use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; + use sp_runtime::traits::SignedExtension; + + declare_bridge_reject_obsolete_parachain_header! { + TestRuntime, + Call::Parachains => () + } + + fn validate_submit_parachain_heads(num: RelayBlockNumber, parachains: Vec) -> bool { + BridgeRejectObsoleteParachainHeader + .validate( + &42, + &Call::Parachains(crate::Call::::submit_parachain_heads { + at_relay_block: (num, Default::default()), + parachains, + parachain_heads_proof: ParaHeadsProof(Vec::new()), + }), + &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, + 0, + ) + .is_ok() + } + + fn sync_to_relay_header_10() { + BestParaHeads::::insert( + ParaId(1), + BestParaHead { + at_relay_block_number: 10, + head_hash: Default::default(), + next_imported_hash_position: 0, + }, + ); + } + + #[test] + fn extension_rejects_obsolete_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#5 => tx is + // rejected + sync_to_relay_header_10(); + assert!(!validate_submit_parachain_heads(5, vec![ParaId(1)])); + }); + } + + #[test] + fn extension_rejects_same_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#10 => tx is + // rejected + sync_to_relay_header_10(); + assert!(!validate_submit_parachain_heads(10, vec![ParaId(1)])); + }); + } + + #[test] + fn extension_accepts_new_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#15 => tx is + // accepted + sync_to_relay_header_10(); + assert!(validate_submit_parachain_heads(15, vec![ParaId(1)])); + }); + } + + #[test] + fn extension_accepts_if_more_than_one_parachain_is_submitted() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#5, but another + // parachain head is also supplied => tx is accepted + sync_to_relay_header_10(); + assert!(validate_submit_parachain_heads(5, vec![ParaId(1), ParaId(2)])); + }); + } +} diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 4cedffc300b82..cf634e5b5ca5c 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -44,6 +44,7 @@ pub mod weights_ext; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; +mod extension; #[cfg(test)] mod mock; @@ -84,8 +85,10 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// Relay chain block is unknown to us. + /// Relay chain block hash is unknown to us. UnknownRelayChainBlock, + /// The number of stored relay block is different from what the relayer has provided. + InvalidRelayChainBlockNumber, /// Invalid storage proof has been passed. InvalidStorageProof, /// Given parachain head is unknown. @@ -175,17 +178,21 @@ pub mod pallet { ))] pub fn submit_parachain_heads( _origin: OriginFor, - relay_block_hash: RelayBlockHash, + at_relay_block: (RelayBlockNumber, RelayBlockHash), parachains: Vec, parachain_heads_proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { // we'll need relay chain header to verify that parachains heads are always increasing. + let (relay_block_number, relay_block_hash) = at_relay_block; let relay_block = pallet_bridge_grandpa::ImportedHeaders::< T, T::BridgesGrandpaPalletInstance, >::get(relay_block_hash) .ok_or(Error::::UnknownRelayChainBlock)?; - let relay_block_number = *relay_block.number(); + ensure!( + *relay_block.number() == relay_block_number, + Error::::InvalidRelayChainBlockNumber, + ); // now parse storage proof and read parachain heads let mut actual_weight = WeightInfoOf::::submit_parachain_heads_weight( @@ -484,7 +491,7 @@ mod tests { ) -> DispatchResultWithPostInfo { Pallet::::submit_parachain_heads( Origin::signed(1), - test_relay_header(relay_chain_block, relay_state_root).hash(), + (relay_chain_block, test_relay_header(relay_chain_block, relay_state_root).hash()), vec![ParaId(1)], proof, ) @@ -510,7 +517,7 @@ mod tests { // we're trying to update heads of parachains 1, 2 and 3 assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), - test_relay_header(0, state_root).hash(), + (0, test_relay_header(0, state_root).hash()), vec![ParaId(1), ParaId(2), ParaId(3)], proof, ),); @@ -602,7 +609,7 @@ mod tests { initialize(state_root); assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), - test_relay_header(0, state_root).hash(), + (0, test_relay_header(0, state_root).hash()), vec![ParaId(1), ParaId(UNTRACKED_PARACHAIN_ID), ParaId(2)], proof, )); @@ -776,7 +783,7 @@ mod tests { proceed(20, state_root_10_at_20); assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), - test_relay_header(20, state_root_10_at_20).hash(), + (20, test_relay_header(20, state_root_10_at_20).hash()), vec![ParaId(1)], proof_10_at_20, ),); @@ -792,7 +799,7 @@ mod tests { proceed(30, state_root_10_at_30); assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), - test_relay_header(30, state_root_10_at_30).hash(), + (30, test_relay_header(30, state_root_10_at_30).hash()), vec![ParaId(1)], proof_10_at_30, ),); diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index e07b0a91010d1..eaf5d3b4fdd91 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -46,7 +46,7 @@ construct_runtime! { System: frame_system::{Pallet, Call, Config, Storage, Event}, Grandpa1: pallet_bridge_grandpa::::{Pallet}, Grandpa2: pallet_bridge_grandpa::::{Pallet}, - Parachains: pallet_bridge_parachains::{Pallet}, + Parachains: pallet_bridge_parachains::{Call, Pallet}, } } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 2779fb0fd3b35..e0837e50bb72a 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -116,6 +116,7 @@ impl TransactionSignScheme for Millau { frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), millau_runtime::BridgeRejectObsoleteGrandpaHeader, + millau_runtime::BridgeRejectObsoleteParachainHeader, ), ( (), @@ -127,6 +128,7 @@ impl TransactionSignScheme for Millau { (), (), (), + (), ), ); let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/relays/lib-substrate-relay/src/parachains/mod.rs index ef14b7bb10322..51549ef02bd52 100644 --- a/relays/lib-substrate-relay/src/parachains/mod.rs +++ b/relays/lib-substrate-relay/src/parachains/mod.rs @@ -24,7 +24,7 @@ use pallet_bridge_parachains::{ RelayBlockHasher, RelayBlockNumber, }; use parachains_relay::ParachainsPipeline; -use relay_substrate_client::{CallOf, Chain, HashOf, RelayChain, TransactionSignScheme}; +use relay_substrate_client::{CallOf, Chain, HeaderIdOf, RelayChain, TransactionSignScheme}; use std::{fmt::Debug, marker::PhantomData}; pub mod source; @@ -70,7 +70,7 @@ pub trait SubmitParachainHeadsCallBuilder: /// Given parachains and their heads proof, build call of `submit_parachain_heads` /// function of bridge parachains module at the target chain. fn build_submit_parachain_heads_call( - relay_block_hash: HashOf, + at_relay_block: HeaderIdOf, parachains: Vec, parachain_heads_proof: ParaHeadsProof, ) -> CallOf; @@ -85,7 +85,7 @@ pub struct DirectSubmitParachainHeadsCallBuilder { impl SubmitParachainHeadsCallBuilder

for DirectSubmitParachainHeadsCallBuilder where P: SubstrateParachainsPipeline, - P::SourceRelayChain: Chain, + P::SourceRelayChain: Chain, R: BridgeParachainsConfig + Send + Sync, I: 'static + Send + Sync, R::BridgedChain: bp_runtime::Chain< @@ -96,12 +96,12 @@ where CallOf: From>, { fn build_submit_parachain_heads_call( - relay_block_hash: HashOf, + at_relay_block: HeaderIdOf, parachains: Vec, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { BridgeParachainsCall::::submit_parachain_heads { - relay_block_hash, + at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, } diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 3a4e0b2c27fe8..9ff35f5a0c106 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -134,7 +134,7 @@ where let transaction_params = self.transaction_params.clone(); let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( - at_relay_block.1, + at_relay_block, updated_parachains, proof, ); From 1d5c84982286f81ebf6a1d8b3df5d6679bea0c29 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 8 Jun 2022 12:37:07 +0300 Subject: [PATCH 0704/1210] fix clippy errors (#1447) --- primitives/messages/src/storage_keys.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/primitives/messages/src/storage_keys.rs b/primitives/messages/src/storage_keys.rs index 19494b8b8527e..4db11edec3420 100644 --- a/primitives/messages/src/storage_keys.rs +++ b/primitives/messages/src/storage_keys.rs @@ -91,7 +91,7 @@ mod tests { fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // all previously crafted messages proofs. - let storage_key = message_key("BridgeMessages", &*b"test", 42).0; + let storage_key = message_key("BridgeMessages", b"test", 42).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), @@ -104,7 +104,7 @@ mod tests { fn outbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // all previously crafted outbound lane state proofs. - let storage_key = outbound_lane_data_key("BridgeMessages", &*b"test").0; + let storage_key = outbound_lane_data_key("BridgeMessages", b"test").0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), @@ -117,7 +117,7 @@ mod tests { fn inbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // all previously crafted inbound lane state proofs. - let storage_key = inbound_lane_data_key("BridgeMessages", &*b"test").0; + let storage_key = inbound_lane_data_key("BridgeMessages", b"test").0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), From e22946d0b57b4b50da39092c4ce7474d3c17235f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Jun 2022 10:01:13 +0300 Subject: [PATCH 0705/1210] fix another clippy warning (#1448) --- relays/bin-substrate/src/cli/reinit_bridge.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs index f598bdbca05a5..484fc6ee6340e 100644 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ b/relays/bin-substrate/src/cli/reinit_bridge.rs @@ -332,12 +332,11 @@ async fn ensure_pallet_operating_mode( match (operational, finality_target.ensure_pallet_active().await) { (true, Ok(())) => Ok(()), (false, Err(SubstrateError::BridgePalletIsHalted)) => Ok(()), - _ => - return Err(anyhow::format_err!( - "Bridge GRANDPA pallet at {} is expected to be {}, but it isn't", - P::TargetChain::NAME, - if operational { "operational" } else { "halted" }, - )), + _ => Err(anyhow::format_err!( + "Bridge GRANDPA pallet at {} is expected to be {}, but it isn't", + P::TargetChain::NAME, + if operational { "operational" } else { "halted" }, + )), } } From 714878a7190e22c618429cc49aec93a9e292cad6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Jun 2022 14:37:36 +0300 Subject: [PATCH 0706/1210] Signed extension for rejecting obsolete messages pallet transactions (#1446) * BridgeRejectObsoleteMessages * add obsolete confirmations verification to the BridgeRejectObsoleteMessages * move tests where they belong --- bin/millau/runtime/src/lib.rs | 10 + bin/runtime-common/Cargo.toml | 3 + bin/runtime-common/src/lib.rs | 1 + bin/runtime-common/src/messages.rs | 4 +- bin/runtime-common/src/messages_extension.rs | 261 ++++++++++++++++++ modules/messages/src/benchmarking.rs | 3 + modules/messages/src/lib.rs | 52 +++- primitives/messages/src/lib.rs | 5 + relays/client-millau/src/lib.rs | 2 + .../src/messages_source.rs | 1 + .../src/messages_target.rs | 10 +- relays/messages/src/message_lane_loop.rs | 1 + relays/messages/src/message_race_delivery.rs | 2 + 13 files changed, 345 insertions(+), 10 deletions(-) create mode 100644 bin/runtime-common/src/messages_extension.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f9d8f891fd44a..5195f9b48a2ae 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -67,6 +67,9 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; +// to be able to use Millau runtime in `bridge-runtime-common` tests +pub use bridge_runtime_common; + // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, @@ -570,6 +573,12 @@ pallet_bridge_parachains::declare_bridge_reject_obsolete_parachain_header! { Call::BridgeRialtoParachains => WithRialtoParachainsInstance } +bridge_runtime_common::declare_bridge_reject_obsolete_messages! { + Runtime, + Call::BridgeRialtoMessages => WithRialtoMessagesInstance, + Call::BridgeRialtoParachainMessages => WithRialtoParachainMessagesInstance +} + /// The address format for describing accounts. pub type Address = AccountId; /// Block header type as expected by this runtime. @@ -592,6 +601,7 @@ pub type SignedExtra = ( pallet_transaction_payment::ChargeTransactionPayment, BridgeRejectObsoleteGrandpaHeader, BridgeRejectObsoleteParachainHeader, + BridgeRejectObsoleteMessages, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 198df7f163214..3bf778ee50a03 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -46,6 +46,9 @@ xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", d xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +[dev-dependencies] +millau-runtime = { path = "../millau/runtime" } + [features] default = ["std"] std = [ diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 616a55d436625..9776fd5827d82 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -21,6 +21,7 @@ pub mod messages; pub mod messages_api; pub mod messages_benchmarking; +pub mod messages_extension; pub mod parachains_benchmarking; #[cfg(feature = "integrity-test")] diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index d302d35c85650..a9a252118b254 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -197,9 +197,6 @@ pub fn transaction_payment( pub mod source { use super::*; - /// Encoded Call of the Bridged chain. We never try to decode it on This chain. - pub type BridgedChainOpaqueCall = Vec; - /// Message payload for This -> Bridged chain messages. pub type FromThisChainMessagePayload = Vec; @@ -523,6 +520,7 @@ pub mod target { pub bridged_header_hash: BridgedHeaderHash, /// A storage trie proof of messages being delivered. pub storage_proof: RawStorageProof, + /// Messages in this proof are sent over this lane. pub lane: LaneId, /// Nonce of the first message being delivered. pub nonces_start: MessageNonce, diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs new file mode 100644 index 0000000000000..fd1d9d7a934b5 --- /dev/null +++ b/bin/runtime-common/src/messages_extension.rs @@ -0,0 +1,261 @@ +// Copyright 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 . + +/// Declares a runtime-specific `BridgeRejectObsoleteMessages` and +/// `BridgeRejectObsoleteMessageConfirmations` signed extensions. +/// +/// ## Example +/// +/// ```nocompile +/// bridge_runtime_common::declare_bridge_reject_obsolete_messages!{ +/// Runtime, +/// Call::BridgeRialtoMessages => WithRialtoMessagesInstance, +/// Call::BridgeRialtoParachainMessages => WithRialtoParachainMessagesInstance, +/// } +/// ``` +/// +/// The goal of this extension is to avoid "mining" messages delivery and delivery confirmation +/// transactions, that are delivering outdated messages/confirmations. Without that extension, +/// even honest relayers may lose their funds if there are multiple relays running and submitting +/// the same messages/confirmations. +#[macro_export] +macro_rules! declare_bridge_reject_obsolete_messages { + ($runtime:ident, $($call:path => $instance:ty),*) => { + /// Transaction-with-obsolete-messages check that will reject transaction if + /// it submits obsolete messages/confirmations. + #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] + pub struct BridgeRejectObsoleteMessages; + + impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteMessages { + const IDENTIFIER: &'static str = "BridgeRejectObsoleteMessages"; + type AccountId = <$runtime as frame_system::Config>::AccountId; + type Call = <$runtime as frame_system::Config>::Call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result< + (), + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> sp_runtime::transaction_validity::TransactionValidity { + match *call { + $( + $call(pallet_bridge_messages::Call::<$runtime, $instance>::receive_messages_proof { + ref proof, + .. + }) => { + let nonces_end = proof.nonces_end; + + let inbound_lane_data = pallet_bridge_messages::InboundLanes::<$runtime, $instance>::get(&proof.lane); + if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() { + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into(); + } + + Ok(sp_runtime::transaction_validity::ValidTransaction::default()) + }, + $call(pallet_bridge_messages::Call::<$runtime, $instance>::receive_messages_delivery_proof { + ref proof, + ref relayers_state, + .. + }) => { + let latest_delivered_nonce = relayers_state.last_delivered_nonce; + + let outbound_lane_data = pallet_bridge_messages::OutboundLanes::<$runtime, $instance>::get(&proof.lane); + if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce { + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into(); + } + + Ok(sp_runtime::transaction_validity::ValidTransaction::default()) + } + )* + _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), + } + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(drop) + } + + fn post_dispatch( + _maybe_pre: Option, + _info: &sp_runtime::traits::DispatchInfoOf, + _post_info: &sp_runtime::traits::PostDispatchInfoOf, + _len: usize, + _result: &sp_runtime::DispatchResult, + ) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> { + Ok(()) + } + } + }; +} + +#[cfg(test)] +mod tests { + use bp_messages::UnrewardedRelayersState; + use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; + use millau_runtime::{ + bridge_runtime_common::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + }, + BridgeRejectObsoleteMessages, Call, Runtime, WithRialtoMessagesInstance, + }; + use sp_runtime::traits::SignedExtension; + + fn deliver_message_10() { + pallet_bridge_messages::InboundLanes::::insert( + [0, 0, 0, 0], + bp_messages::InboundLaneData { relayers: Default::default(), last_confirmed_nonce: 10 }, + ); + } + + fn validate_message_delivery( + nonces_start: bp_messages::MessageNonce, + nonces_end: bp_messages::MessageNonce, + ) -> bool { + BridgeRejectObsoleteMessages + .validate( + &[0u8; 32].into(), + &Call::BridgeRialtoMessages(pallet_bridge_messages::Call::< + Runtime, + WithRialtoMessagesInstance, + >::receive_messages_proof { + relayer_id_at_bridged_chain: [0u8; 32].into(), + messages_count: (nonces_end - nonces_start + 1) as u32, + dispatch_weight: 0, + proof: FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof: vec![], + lane: [0, 0, 0, 0], + nonces_start, + nonces_end, + }, + }), + &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, + 0, + ) + .is_ok() + } + + #[test] + fn extension_rejects_obsolete_messages() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best delivered is message#10 and we're trying to deliver message#5 => tx + // is rejected + deliver_message_10(); + assert!(!validate_message_delivery(8, 9)); + }); + } + + #[test] + fn extension_rejects_same_message() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best delivered is message#10 and we're trying to import message#10 => tx + // is rejected + deliver_message_10(); + assert!(!validate_message_delivery(8, 10)); + }); + } + + #[test] + fn extension_accepts_new_message() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best delivered is message#10 and we're trying to deliver message#15 => + // tx is accepted + deliver_message_10(); + assert!(validate_message_delivery(10, 15)); + }); + } + + fn confirm_message_10() { + pallet_bridge_messages::OutboundLanes::::insert( + [0, 0, 0, 0], + bp_messages::OutboundLaneData { + oldest_unpruned_nonce: 0, + latest_received_nonce: 10, + latest_generated_nonce: 10, + }, + ); + } + + fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool { + BridgeRejectObsoleteMessages + .validate( + &[0u8; 32].into(), + &Call::BridgeRialtoMessages(pallet_bridge_messages::Call::< + Runtime, + WithRialtoMessagesInstance, + >::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: Vec::new(), + lane: [0, 0, 0, 0], + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce, + ..Default::default() + }, + }), + &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, + 0, + ) + .is_ok() + } + + #[test] + fn extension_rejects_obsolete_confirmations() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best confirmed is message#10 and we're trying to confirm message#5 => tx + // is rejected + confirm_message_10(); + assert!(!validate_message_confirmation(5)); + }); + } + + #[test] + fn extension_rejects_same_confirmation() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best confirmed is message#10 and we're trying to confirm message#10 => + // tx is rejected + confirm_message_10(); + assert!(!validate_message_confirmation(10)); + }); + } + + #[test] + fn extension_accepts_new_confirmation() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best confirmed is message#10 and we're trying to confirm message#15 => + // tx is accepted + confirm_message_10(); + assert!(validate_message_confirmation(15)); + }); + } +} diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 66aa70312cc9a..c312528d4bd29 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -493,6 +493,7 @@ benchmarks_instance_pallet! { unrewarded_relayer_entries: 1, messages_in_oldest_entry: 1, total_messages: 1, + last_delivered_nonce: 1, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), @@ -534,6 +535,7 @@ benchmarks_instance_pallet! { unrewarded_relayer_entries: 1, messages_in_oldest_entry: 2, total_messages: 2, + last_delivered_nonce: 2, }; let mut delivered_messages = DeliveredMessages::new(1, true); delivered_messages.note_dispatched_message(true); @@ -576,6 +578,7 @@ benchmarks_instance_pallet! { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, total_messages: 2, + last_delivered_nonce: 2, }; let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a41ea3d1d95a8..0f287a9df47e1 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -554,6 +554,12 @@ pub mod pallet { relayers_state.unrewarded_relayer_entries, Error::::InvalidUnrewardedRelayersState ); + // the `last_delivered_nonce` field may also be used by the signed extension. Even + // though providing wrong value isn't critical, let's also check it here. + ensure!( + lane_data.last_delivered_nonce() == relayers_state.last_delivered_nonce, + Error::::InvalidUnrewardedRelayersState + ); // mark messages as delivered let mut lane = outbound_lane::(lane_id); @@ -1159,7 +1165,9 @@ mod tests { fn inbound_unrewarded_relayers_state( lane: bp_messages::LaneId, ) -> bp_messages::UnrewardedRelayersState { - let relayers = InboundLanes::::get(&lane).relayers; + let inbound_lane_data = InboundLanes::::get(&lane); + let last_delivered_nonce = inbound_lane_data.last_delivered_nonce(); + let relayers = inbound_lane_data.relayers; bp_messages::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, messages_in_oldest_entry: relayers @@ -1167,6 +1175,7 @@ mod tests { .map(|entry| 1 + entry.messages.end - entry.messages.begin) .unwrap_or(0), total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + last_delivered_nonce, } } @@ -1225,6 +1234,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 1, + last_delivered_nonce: 1, ..Default::default() }, )); @@ -1467,6 +1477,7 @@ mod tests { unrewarded_relayer_entries: 1, messages_in_oldest_entry: 1, total_messages: 1, + last_delivered_nonce: 1, }, ), Error::::Halted, @@ -1522,6 +1533,7 @@ mod tests { unrewarded_relayer_entries: 1, messages_in_oldest_entry: 1, total_messages: 1, + last_delivered_nonce: 1, }, )); }); @@ -1619,6 +1631,7 @@ mod tests { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, total_messages: 2, + last_delivered_nonce: 10, }, ); @@ -1654,6 +1667,7 @@ mod tests { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 1, total_messages: 2, + last_delivered_nonce: 11, }, ); }); @@ -1749,6 +1763,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 1, + last_delivered_nonce: 1, ..Default::default() }, )); @@ -1774,6 +1789,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 2, total_messages: 2, + last_delivered_nonce: 2, ..Default::default() }, )); @@ -1818,6 +1834,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 2, + last_delivered_nonce: 2, ..Default::default() }, ), @@ -1843,6 +1860,33 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 2, total_messages: 1, + last_delivered_nonce: 2, + ..Default::default() + }, + ), + Error::::InvalidUnrewardedRelayersState, + ); + + // when last delivered nonce is invalid + assert_noop!( + Pallet::::receive_messages_delivery_proof( + Origin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![ + unrewarded_relayer(1, 1, TEST_RELAYER_A), + unrewarded_relayer(2, 2, TEST_RELAYER_B) + ] + .into_iter() + .collect(), + ..Default::default() + } + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 2, + total_messages: 2, + last_delivered_nonce: 8, ..Default::default() }, ), @@ -2079,6 +2123,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 2, + last_delivered_nonce: 2, ..Default::default() }, )); @@ -2089,6 +2134,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 1, + last_delivered_nonce: 3, ..Default::default() }, )); @@ -2116,6 +2162,7 @@ mod tests { let relayers_state = UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 3, + last_delivered_nonce: 3, ..Default::default() }; let pre_dispatch_weight = @@ -2190,7 +2237,7 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, relayers: Default::default() }, ))), - UnrewardedRelayersState::default(), + UnrewardedRelayersState { last_delivered_nonce: 1, ..Default::default() }, ), Error::::TryingToConfirmMoreMessagesThanExpected, ); @@ -2269,6 +2316,7 @@ mod tests { UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: max_messages_to_prune, + last_delivered_nonce: max_messages_to_prune, ..Default::default() }, )); diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 35df6d01f1cbe..8d51a6fa86462 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -289,6 +289,11 @@ pub struct UnrewardedRelayersState { pub messages_in_oldest_entry: MessageNonce, /// Total number of messages in the relayers vector. pub total_messages: MessageNonce, + /// Nonce of the latest message that has been delivered to the target chain. + /// + /// This corresponds to the result of the `InboundLaneData::last_delivered_nonce` call + /// at the bridged chain. + pub last_delivered_nonce: MessageNonce, } /// Outbound lane data. diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index e0837e50bb72a..36ad9df69d69b 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -117,6 +117,7 @@ impl TransactionSignScheme for Millau { pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), millau_runtime::BridgeRejectObsoleteGrandpaHeader, millau_runtime::BridgeRejectObsoleteParachainHeader, + millau_runtime::BridgeRejectObsoleteMessages, ), ( (), @@ -129,6 +130,7 @@ impl TransactionSignScheme for Millau { (), (), (), + (), ), ); let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 7dc582dd5762d..85bd9ea7d0f77 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -474,6 +474,7 @@ fn prepare_dummy_messages_delivery_proof( unrewarded_relayer_entries: 1, messages_in_oldest_entry: 1, total_messages: 1, + last_delivered_nonce: 1, }, FromBridgedChainMessagesDeliveryProof { bridged_header_hash: Default::default(), diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 08604e66b72a9..00c0c1570541e 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -191,11 +191,10 @@ where id: TargetHeaderIdOf>, ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> { - let relayers = self - .inbound_lane_data(id) - .await? - .map(|data| data.relayers) - .unwrap_or_else(VecDeque::new); + let inbound_lane_data = self.inbound_lane_data(id).await?; + let last_delivered_nonce = + inbound_lane_data.as_ref().map(|data| data.last_delivered_nonce()).unwrap_or(0); + let relayers = inbound_lane_data.map(|data| data.relayers).unwrap_or_else(VecDeque::new); let unrewarded_relayers_state = bp_messages::UnrewardedRelayersState { unrewarded_relayer_entries: relayers.len() as _, messages_in_oldest_entry: relayers @@ -203,6 +202,7 @@ where .map(|entry| 1 + entry.messages.end - entry.messages.begin) .unwrap_or(0), total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + last_delivered_nonce, }; Ok((id, unrewarded_relayers_state)) } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 487623096f06e..84473f0f27b23 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -729,6 +729,7 @@ pub(crate) mod tests { unrewarded_relayer_entries: 0, messages_in_oldest_entry: 0, total_messages: 0, + last_delivered_nonce: 0, }, )) } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index dc994364f1787..4484d4b7994c4 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -639,6 +639,7 @@ mod tests { unrewarded_relayer_entries: 0, messages_in_oldest_entry: 0, total_messages: 0, + last_delivered_nonce: 0, }, }, }), @@ -954,6 +955,7 @@ mod tests { unrewarded_relayer_entries: 2, messages_in_oldest_entry: 2, total_messages: 2, + last_delivered_nonce: 19, }, }, }, From 582a26e52440c0e77509495fa48688d8783810f8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Jun 2022 12:11:28 +0300 Subject: [PATCH 0707/1210] Fix deployments again (#1452) * Revert "try to fix nonces collisions (#1450)" This reverts commit 5a91ddf4cca0b81f9b04fe7a362298c3863851fa. * Revert "Revert "try to fix nonces collisions (#1450)"" This reverts commit e6350e839b97946541c1468235575c4bad4c75c1. * added some accounts to RialtoParachain --- bin/rialto-parachain/node/src/chain_spec.rs | 57 +++++++++++---------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 4a9bdaf9afd70..f1d063c5a7bdf 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -62,6 +62,33 @@ where AccountPublic::from(get_from_seed::(seed)).into_account() } +/// We're using the same set of endowed accounts on all RialtoParachain chains (dev/local) to make +/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, +/// accounts used by relayers in our test deployments, accounts used for demonstration +/// purposes), are all available on these chains. +fn endowed_accounts() -> Vec { + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("George"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + get_account_id_from_seed::("George//stash"), + pallet_bridge_messages::relayer_fund_account_id::< + bp_rialto_parachain::AccountId, + bp_rialto_parachain::AccountIdConverter, + >(), + ] +} + pub fn development_config(id: ParaId) -> ChainSpec { // Give your base currency a unit name and decimal places let mut properties = sc_chain_spec::Properties::new(); @@ -78,16 +105,7 @@ pub fn development_config(id: ParaId) -> ChainSpec { testnet_genesis( get_account_id_from_seed::("Alice"), vec![get_from_seed::("Alice"), get_from_seed::("Bob")], - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_rialto_parachain::AccountId, - bp_rialto_parachain::AccountIdConverter, - >(), - ], + endowed_accounts(), id, ) }, @@ -119,24 +137,7 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec { testnet_genesis( get_account_id_from_seed::("Alice"), vec![get_from_seed::("Alice"), get_from_seed::("Bob")], - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_rialto_parachain::AccountId, - bp_rialto_parachain::AccountIdConverter, - >(), - ], + endowed_accounts(), id, ) }, From d91e4bfbb8686f608aa95227f9fca2d51117d155 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Jun 2022 15:43:58 +0300 Subject: [PATCH 0708/1210] Add missing parts to rialto parachain bridge (part 1) (#1454) * add proper parameter names to bridge declaration * associate RialtoParachain token with DOT * RialtoParachain<>Millau message pallet owners * fix compilation --- bin/rialto-parachain/node/src/chain_spec.rs | 9 ++++--- bin/rialto-parachain/runtime/src/lib.rs | 2 +- primitives/chain-millau/src/lib.rs | 8 ++++++ primitives/chain-rialto-parachain/src/lib.rs | 13 ++++++--- .../millau_messages_to_rialto_parachain.rs | 27 ++++++++++++++----- .../rialto_parachain_messages_to_millau.rs | 24 ++++++++++++----- relays/client-rialto-parachain/src/lib.rs | 5 ++-- 7 files changed, 64 insertions(+), 24 deletions(-) diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index f1d063c5a7bdf..e22035905c978 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use cumulus_primitives_core::ParaId; -use rialto_parachain_runtime::{AccountId, AuraId, Signature}; +use rialto_parachain_runtime::{AccountId, AuraId, BridgeMillauMessagesConfig, Signature}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; @@ -82,6 +82,7 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), + get_account_id_from_seed::("MillauMessagesOwner"), pallet_bridge_messages::relayer_fund_account_id::< bp_rialto_parachain::AccountId, bp_rialto_parachain::AccountIdConverter, @@ -172,7 +173,9 @@ fn testnet_genesis( parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), - bridge_millau_messages: Default::default(), - // parachain_system: Default::default(), + bridge_millau_messages: BridgeMillauMessagesConfig { + owner: Some(get_account_id_from_seed::("MillauMessagesOwner")), + ..Default::default() + }, } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 1f8a0a2581e6a..ec1c754f7dfdb 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -85,7 +85,7 @@ use xcm_builder::{ }; use xcm_executor::{Config, XcmExecutor}; -mod millau_messages; +pub mod millau_messages; /// The address format for describing accounts. pub type Address = MultiAddress; diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index b91ec86e3febb..c9b4153b2fc89 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -282,9 +282,17 @@ frame_support::parameter_types! { pub const WITH_MILLAU_GRANDPA_PALLET_NAME: &str = "BridgeMillauGrandpa"; /// Name of the With-Millau messages pallet instance that is deployed at bridged chains. pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; +/// Name of the transaction payment pallet at the Millau runtime. +pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; /// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; +/// Name of the RialtoParachain->Millau (actually DOT->KSM) conversion rate stored in the Millau +/// runtime. +pub const RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = + "RialtoParachainToMillauConversionRate"; +/// Name of the RialtoParachain fee multiplier parameter, stored in the Millau runtime. +pub const RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME: &str = "RialtoParachainFeeMultiplier"; /// Name of the `MillauFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index d42bfaf4110b4..df66996c4b133 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -195,10 +195,15 @@ frame_support::parameter_types! { /// Name of the With-Rialto-Parachain messages pallet instance that is deployed at bridged chains. pub const WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME: &str = "BridgeRialtoParachainMessages"; - -/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto parachain -/// runtime. -pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; +/// Name of the transaction payment pallet at the Rialto parachain runtime. +pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; + +/// Name of the Millau->RialtoParachain (actually KSM->DOT) conversion rate stored in the Rialto +/// parachain runtime. +pub const MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME: &str = + "MillauToRialtoParachainConversionRate"; +/// Name of the Millau fee multiplier parameter, stored in the Rialto parachain runtime. +pub const MILLAU_FEE_MULTIPLIER_PARAMETER_NAME: &str = "MillauFeeMultiplier"; /// Name of the `RialtoParachainFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD: &str = diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index f12fd1de89ec4..d5b42798dd4fa 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -27,17 +27,29 @@ use substrate_relay_helper::messages_lane::{ /// Description of Millau -> RialtoParachain messages bridge. #[derive(Clone, Debug)] pub struct MillauMessagesToRialtoParachain; +substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( + Millau, + MillauMessagesToRialtoParachainUpdateConversionRateCallBuilder, + millau_runtime::Runtime, + millau_runtime::WithRialtoParachainMessagesInstance, + millau_runtime::rialto_parachain_messages::MillauToRialtoParachainMessagesParameter::RialtoParachainToMillauConversionRate +); impl SubstrateMessageLane for MillauMessagesToRialtoParachain { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto_parachain::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + Some(bp_rialto_parachain::MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME); const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + Some(bp_millau::RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto_parachain::MILLAU_FEE_MULTIPLIER_PARAMETER_NAME); + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME); + + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_millau::TRANSACTION_PAYMENT_PALLET_NAME); + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_rialto_parachain::TRANSACTION_PAYMENT_PALLET_NAME); type SourceChain = Millau; type TargetChain = RialtoParachain; @@ -56,7 +68,8 @@ impl SubstrateMessageLane for MillauMessagesToRialtoParachain { millau_runtime::WithRialtoParachainMessagesInstance, >; - type TargetToSourceChainConversionRateUpdateBuilder = (); + type TargetToSourceChainConversionRateUpdateBuilder = + MillauMessagesToRialtoParachainUpdateConversionRateCallBuilder; type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index e1fef8caf0a36..bc9b8a3170b14 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -27,17 +27,29 @@ use substrate_relay_helper::messages_lane::{ /// Description of RialtoParachain -> Millau messages bridge. #[derive(Clone, Debug)] pub struct RialtoParachainMessagesToMillau; +substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( + RialtoParachain, + RialtoParachainMessagesToMillauUpdateConversionRateCallBuilder, + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::WithMillauMessagesInstance, + rialto_parachain_runtime::millau_messages::RialtoParachainToMillauMessagesParameter::MillauToRialtoParachainConversionRate +); impl SubstrateMessageLane for RialtoParachainMessagesToMillau { const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); + Some(bp_millau::RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto_parachain::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); + Some(bp_rialto_parachain::MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME); - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_millau::RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME); + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = + Some(bp_rialto_parachain::MILLAU_FEE_MULTIPLIER_PARAMETER_NAME); + + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_rialto_parachain::TRANSACTION_PAYMENT_PALLET_NAME); + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = + Some(bp_millau::TRANSACTION_PAYMENT_PALLET_NAME); type SourceChain = RialtoParachain; type TargetChain = Millau; diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 9f54363d9c4fc..74393211d9377 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -57,9 +57,8 @@ impl ChainBase for RialtoParachain { impl Chain for RialtoParachain { const NAME: &'static str = "RialtoParachain"; - const TOKEN_ID: Option<&'static str> = None; - // should be fixed/changed in https://github.com/paritytech/parity-bridges-common/pull/1199 - // should be removed in https://github.com/paritytech/parity-bridges-common/issues/1246 + // RialtoParachain token has no value, but we associate it with DOT token + const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); From 90ac1c37922233f28aaa90a84fbcb03bea7ce2ed Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Jun 2022 11:01:31 +0300 Subject: [PATCH 0709/1210] actually use RialtoParachainMessagesToMillauUpdateConversionRateCallBuilder (#1456) --- .../src/chains/rialto_parachain_messages_to_millau.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index bc9b8a3170b14..b8ff0af10f840 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -68,7 +68,8 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { rialto_parachain_runtime::WithMillauMessagesInstance, >; - type TargetToSourceChainConversionRateUpdateBuilder = (); + type TargetToSourceChainConversionRateUpdateBuilder = + RialtoParachainMessagesToMillauUpdateConversionRateCallBuilder; type RelayStrategy = MixStrategy; } From a26ba0e110ea2003849d8042dad969b7a79be9a4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Jun 2022 14:44:41 +0300 Subject: [PATCH 0710/1210] use Millau //Iden for RialtoParachain -> Millau transactions (#1460) --- bin/millau/node/src/chain_spec.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index ae5f01bbb5904..2b80b4aac819f 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -142,6 +142,7 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Ferdie"), get_account_id_from_seed::("George"), get_account_id_from_seed::("Harry"), + get_account_id_from_seed::("Iden"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), @@ -150,6 +151,7 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), + get_account_id_from_seed::("Iden//stash"), get_account_id_from_seed::("RialtoMessagesOwner"), get_account_id_from_seed::("RialtoParachainMessagesOwner"), pallet_bridge_messages::relayer_fund_account_id::< From a214112bdc6c53e06b3c0145315306b94173f5dd Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 16 Jun 2022 15:18:34 +0300 Subject: [PATCH 0711/1210] Separate signers for different complex relay layers (#1465) * separate accounts for different complex relay layers * fix clippy issue * cleanup + expose relay accounts balance metrics * expose messages pallet owner balance metric * use new metrics in maintenance dashboard * tests + use separate accounts to sign RialtoHeaders -> Millau transactions in RialtoParachain<>Millau bridge * clippy + fmt + spellcheck --- bin/millau/node/src/chain_spec.rs | 2 + relays/bin-substrate/src/cli/mod.rs | 42 +- .../src/cli/relay_headers_and_messages.rs | 450 +++++++++++++++--- relays/lib-substrate-relay/src/lib.rs | 58 +++ .../src/messages_metrics.rs | 27 +- 5 files changed, 498 insertions(+), 81 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 2b80b4aac819f..3204173598a07 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -143,6 +143,7 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("George"), get_account_id_from_seed::("Harry"), get_account_id_from_seed::("Iden"), + get_account_id_from_seed::("Ken"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), @@ -152,6 +153,7 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("Iden//stash"), + get_account_id_from_seed::("Ken//stash"), get_account_id_from_seed::("RialtoMessagesOwner"), get_account_id_from_seed::("RialtoParachainMessagesOwner"), pallet_bridge_messages::relayer_fund_account_id::< diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 4748e42e3f3cc..5061c70eb7840 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -22,6 +22,7 @@ use codec::{Decode, Encode}; use relay_substrate_client::ChainRuntimeVersion; use structopt::{clap::arg_enum, StructOpt}; use strum::{EnumString, EnumVariantNames}; +use substrate_relay_helper::TransactionParams; use bp_messages::LaneId; @@ -64,7 +65,7 @@ pub enum Command { /// and two `RelayMessages` relays. Headers are only relayed when they are required by /// the message relays - i.e. when there are messages or confirmations that needs to be /// relayed between chains. - RelayHeadersAndMessages(relay_headers_and_messages::RelayHeadersAndMessages), + RelayHeadersAndMessages(Box), /// Initialize on-chain bridge pallet with current header data. /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. @@ -238,7 +239,7 @@ impl HexBytes { } /// Prometheus metrics params. -#[derive(Clone, Debug, StructOpt)] +#[derive(Clone, Debug, PartialEq, StructOpt)] pub struct PrometheusParams { /// Do not expose a Prometheus metric endpoint. #[structopt(long)] @@ -302,6 +303,29 @@ pub enum RuntimeVersionType { Bundle, } +/// Helper trait to override transaction parameters differently. +pub trait TransactionParamsProvider { + /// Returns `true` if transaction parameters are defined by this provider. + fn is_defined(&self) -> bool; + /// Returns transaction parameters. + fn transaction_params( + &self, + ) -> anyhow::Result>; + + /// Returns transaction parameters, defined by `self` provider or, if they're not defined, + /// defined by `other` provider. + fn transaction_params_or( + &self, + other: &T, + ) -> anyhow::Result> { + if self.is_defined() { + self.transaction_params::() + } else { + other.transaction_params::() + } + } +} + /// Create chain-specific set of configuration objects: connection parameters, /// signing parameters and bridge initialization parameters. #[macro_export] @@ -434,6 +458,20 @@ macro_rules! declare_chain_options { } } + #[allow(dead_code)] + impl TransactionParamsProvider for [<$chain SigningParams>] { + fn is_defined(&self) -> bool { + self.[<$chain_prefix _signer>].is_some() || self.[<$chain_prefix _signer_file>].is_some() + } + + fn transaction_params(&self) -> anyhow::Result> { + Ok(TransactionParams { + mortality: self.transactions_mortality()?, + signer: self.to_keypair::()?, + }) + } + } + #[allow(dead_code)] impl [<$chain MessagesPalletOwnerSigningParams>] { /// Parse signing params into chain-specific KeyPair. diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 923d82c11f4ef..51c863080fd50 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -44,11 +44,14 @@ use substrate_relay_helper::{ headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, }, parachains::SubstrateParachainsPipeline, - TransactionParams, + TaggedAccount, TransactionParams, }; use crate::{ - cli::{relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams, RuntimeVersionType}, + cli::{ + relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams, RuntimeVersionType, + TransactionParamsProvider, + }, declare_chain_options, }; @@ -61,7 +64,7 @@ use crate::{ pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; /// Start headers+messages relayer process. -#[derive(StructOpt)] +#[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), @@ -70,7 +73,7 @@ pub enum RelayHeadersAndMessages { } /// Parameters that have the same names across all bridges. -#[derive(StructOpt)] +#[derive(Debug, PartialEq, StructOpt)] pub struct HeadersAndMessagesSharedParams { /// Hex-encoded lane identifiers that should be served by the complex relay. #[structopt(long, default_value = "00000000")] @@ -95,21 +98,32 @@ macro_rules! declare_bridge_options { // chain, parachain, relay-chain-of-parachain ($chain1:ident, $chain2:ident, $chain3:ident) => { paste::item! { - #[doc = $chain1 ", " $chain2 " and " $chain3 " headers+messages relay params."] - #[derive(StructOpt)] + #[doc = $chain1 ", " $chain2 " and " $chain3 " headers+parachains+messages relay params."] + #[derive(Debug, PartialEq, StructOpt)] pub struct [<$chain1 $chain2 HeadersAndMessages>] { #[structopt(flatten)] shared: HeadersAndMessagesSharedParams, #[structopt(flatten)] left: [<$chain1 ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$chain1 SigningParams>], + // override for right_relay->left headers signer + #[structopt(flatten)] + right_relay_headers_to_left_sign_override: [<$chain3 HeadersTo $chain1 SigningParams>], + // override for right->left parachains signer + #[structopt(flatten)] + right_parachains_to_left_sign_override: [<$chain3 ParachainsTo $chain1 SigningParams>], #[structopt(flatten)] left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>], #[structopt(flatten)] right: [<$chain2 ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$chain2 SigningParams>], + // override for left->right headers signer + #[structopt(flatten)] + left_headers_to_right_sign_override: [<$chain1 HeadersTo $chain2 SigningParams>], #[structopt(flatten)] right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], #[structopt(flatten)] @@ -122,18 +136,26 @@ macro_rules! declare_bridge_options { ($chain1:ident, $chain2:ident) => { paste::item! { #[doc = $chain1 " and " $chain2 " headers+messages relay params."] - #[derive(StructOpt)] + #[derive(Debug, PartialEq, StructOpt)] pub struct [<$chain1 $chain2 HeadersAndMessages>] { #[structopt(flatten)] shared: HeadersAndMessagesSharedParams, + // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left: [<$chain1 ConnectionParams>], + // override for right->left headers signer + #[structopt(flatten)] + right_headers_to_left_sign_override: [<$chain2 HeadersTo $chain1 SigningParams>], #[structopt(flatten)] left_sign: [<$chain1 SigningParams>], #[structopt(flatten)] left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>], + // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right: [<$chain2 ConnectionParams>], + // override for left->right headers signer + #[structopt(flatten)] + left_headers_to_right_sign_override: [<$chain1 HeadersTo $chain2 SigningParams>], #[structopt(flatten)] right_sign: [<$chain2 SigningParams>], #[structopt(flatten)] @@ -178,6 +200,8 @@ macro_rules! select_bridge { params: &Params, left_client: Client, right_client: Client, + at_left_relay_accounts: &mut Vec>>, + at_right_relay_accounts: &mut Vec>>, ) -> anyhow::Result<( Arc>>, Arc>>, @@ -190,18 +214,14 @@ macro_rules! select_bridge { >( left_client, right_client, - TransactionParams { - mortality: params.right_sign.transactions_mortality()?, - signer: params.right_sign.to_keypair::()?, - }, - TransactionParams { - mortality: params.left_sign.transactions_mortality()?, - signer: params.left_sign.to_keypair::()?, - }, + params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, + params.right_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, params.shared.only_mandatory_headers, params.shared.only_mandatory_headers, params.left.can_start_version_guard(), params.right.can_start_version_guard(), + at_left_relay_accounts, + at_right_relay_accounts, ).await } @@ -241,12 +261,14 @@ macro_rules! select_bridge { params: &Params, left_client: Client, right_client: Client, + at_left_relay_accounts: &mut Vec>>, + at_right_relay_accounts: &mut Vec>>, ) -> anyhow::Result<( Arc>>, Arc>>, )> { type RightRelayChain = relay_rialto_client::Rialto; - let rialto_relay_chain_client = params.right_relay.to_client::().await?; // TODO: should be the relaychain connection params + let rialto_relay_chain_client = params.right_relay.to_client::().await?; start_on_demand_relay_to_parachain::< Left, @@ -259,18 +281,15 @@ macro_rules! select_bridge { left_client, right_client, rialto_relay_chain_client, - TransactionParams { - mortality: params.right_sign.transactions_mortality()?, - signer: params.right_sign.to_keypair::()?, - }, - TransactionParams { - mortality: params.left_sign.transactions_mortality()?, - signer: params.left_sign.to_keypair::()?, - }, + params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, + params.right_relay_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, + params.right_parachains_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, params.shared.only_mandatory_headers, params.shared.only_mandatory_headers, params.left.can_start_version_guard(), params.right.can_start_version_guard(), + at_left_relay_accounts, + at_right_relay_accounts, ).await } @@ -310,6 +329,8 @@ macro_rules! select_bridge { params: &Params, left_client: Client, right_client: Client, + at_left_relay_accounts: &mut Vec>>, + at_right_relay_accounts: &mut Vec>>, ) -> anyhow::Result<( Arc>>, Arc>>, @@ -322,18 +343,14 @@ macro_rules! select_bridge { >( left_client, right_client, - TransactionParams { - mortality: params.right_sign.transactions_mortality()?, - signer: params.right_sign.to_keypair::()?, - }, - TransactionParams { - mortality: params.left_sign.transactions_mortality()?, - signer: params.left_sign.to_keypair::()?, - }, + params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, + params.right_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, params.shared.only_mandatory_headers, params.shared.only_mandatory_headers, params.left.can_start_version_guard(), params.right.can_start_version_guard(), + at_left_relay_accounts, + at_right_relay_accounts, ).await } @@ -393,6 +410,8 @@ macro_rules! select_bridge { params: &Params, left_client: Client, right_client: Client, + at_left_relay_accounts: &mut Vec>>, + at_right_relay_accounts: &mut Vec>>, ) -> anyhow::Result<( Arc>>, Arc>>, @@ -405,18 +424,14 @@ macro_rules! select_bridge { >( left_client, right_client, - TransactionParams { - mortality: params.right_sign.transactions_mortality()?, - signer: params.right_sign.to_keypair::()?, - }, - TransactionParams { - mortality: params.left_sign.transactions_mortality()?, - signer: params.left_sign.to_keypair::()?, - }, + params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, + params.right_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, params.shared.only_mandatory_headers, params.shared.only_mandatory_headers, params.left.can_start_version_guard(), params.right.can_start_version_guard(), + at_left_relay_accounts, + at_right_relay_accounts, ).await } @@ -470,6 +485,15 @@ declare_chain_options!(Rococo, rococo); declare_chain_options!(Wococo, wococo); declare_chain_options!(Kusama, kusama); declare_chain_options!(Polkadot, polkadot); +// Means to override signers of different layer transactions. +declare_chain_options!(MillauHeadersToRialto, millau_headers_to_rialto); +declare_chain_options!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); +declare_chain_options!(RialtoHeadersToMillau, rialto_headers_to_millau); +declare_chain_options!(RialtoParachainsToMillau, rialto_parachains_to_millau); +declare_chain_options!(WococoHeadersToRococo, wococo_headers_to_rococo); +declare_chain_options!(RococoHeadersToWococo, rococo_headers_to_wococo); +declare_chain_options!(KusamaHeadersToPolkadot, kusama_headers_to_polkadot); +declare_chain_options!(PolkadotHeadersToKusama, polkadot_headers_to_kusama); // All supported bridges. declare_bridge_options!(Millau, Rialto); declare_bridge_options!(Millau, RialtoParachain, Rialto); @@ -505,6 +529,14 @@ impl RelayHeadersAndMessages { LeftToRightMessageLane, >(left_client.clone(), right_client.clone())?; let right_to_left_metrics = left_to_right_metrics.clone().reverse(); + let mut at_left_relay_accounts = vec![TaggedAccount::Messages { + id: left_sign.public().into(), + bridged_chain: Right::NAME.to_string(), + }]; + let mut at_right_relay_accounts = vec![TaggedAccount::Messages { + id: right_sign.public().into(), + bridged_chain: Left::NAME.to_string(), + }]; // start conversion rate update loops for left/right chains if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { @@ -522,7 +554,7 @@ impl RelayHeadersAndMessages { >( left_client, TransactionParams { - signer: left_messages_pallet_owner, + signer: left_messages_pallet_owner.clone(), mortality: left_transactions_mortality, }, left_to_right_metrics @@ -542,6 +574,10 @@ impl RelayHeadersAndMessages { .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, ); + at_left_relay_accounts.push(TaggedAccount::MessagesPalletOwner { + id: left_messages_pallet_owner.public().into(), + bridged_chain: Right::NAME.to_string(), + }); } if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { let right_client = right_client.clone(); @@ -558,7 +594,7 @@ impl RelayHeadersAndMessages { >( right_client, TransactionParams { - signer: right_messages_pallet_owner, + signer: right_messages_pallet_owner.clone(), mortality: right_transactions_mortality, }, right_to_left_metrics @@ -578,6 +614,10 @@ impl RelayHeadersAndMessages { .shared_value_ref(), CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, ); + at_right_relay_accounts.push(TaggedAccount::MessagesPalletOwner { + id: right_messages_pallet_owner.public().into(), + bridged_chain: Left::NAME.to_string(), + }); } // optionally, create relayers fund account @@ -619,27 +659,33 @@ impl RelayHeadersAndMessages { } } + // start on-demand header relays + let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = + start_on_demand_relays( + ¶ms, + left_client.clone(), + right_client.clone(), + &mut at_left_relay_accounts, + &mut at_right_relay_accounts, + ) + .await?; + // add balance-related metrics let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( left_client.clone(), metrics_params, - Some(left_sign.public().into()), - left_messages_pallet_owner.map(|kp| kp.public().into()), + at_left_relay_accounts, ) .await?; let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( right_client.clone(), metrics_params, - Some(right_sign.public().into()), - right_messages_pallet_owner.map(|kp| kp.public().into()), + at_right_relay_accounts, ) .await?; - // start on-demand header relays - let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = - start_on_demand_relays(¶ms, left_client.clone(), right_client.clone()).await?; // Need 2x capacity since we consider both directions for each lane let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { @@ -714,13 +760,15 @@ async fn start_on_demand_relay_to_relay( right_to_left_only_mandatory_headers: bool, left_can_start_version_guard: bool, right_can_start_version_guard: bool, + at_left_relay_accounts: &mut Vec>>, + at_right_relay_accounts: &mut Vec>>, ) -> anyhow::Result<( Arc>>, Arc>>, )> where - LC: Chain + TransactionSignScheme, - RC: Chain + TransactionSignScheme, + LC: Chain + TransactionSignScheme + CliChain>, + RC: Chain + TransactionSignScheme + CliChain>, LR: SubstrateFinalitySyncPipeline< SourceChain = LC, TargetChain = RC, @@ -734,6 +782,15 @@ where AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, { + at_left_relay_accounts.push(TaggedAccount::Headers { + id: right_to_left_transaction_params.signer.public().into(), + bridged_chain: RC::NAME.to_string(), + }); + at_right_relay_accounts.push(TaggedAccount::Headers { + id: left_to_right_transaction_params.signer.public().into(), + bridged_chain: LC::NAME.to_string(), + }); + LR::start_relay_guards( &right_client, &left_to_right_transaction_params, @@ -768,21 +825,27 @@ async fn start_on_demand_relay_to_parachain( left_client: Client, right_client: Client, right_relay_client: Client, - left_to_right_transaction_params: TransactionParams>, - right_to_left_transaction_params: TransactionParams>, + left_headers_to_right_transaction_params: TransactionParams>, + right_headers_to_left_transaction_params: TransactionParams>, + right_parachains_to_left_transaction_params: TransactionParams>, left_to_right_only_mandatory_headers: bool, right_to_left_only_mandatory_headers: bool, left_can_start_version_guard: bool, right_can_start_version_guard: bool, + at_left_relay_accounts: &mut Vec>>, + at_right_relay_accounts: &mut Vec>>, ) -> anyhow::Result<( Arc>>, Arc>>, )> where - LC: Chain + TransactionSignScheme, - RC: Chain + TransactionSignScheme, + LC: Chain + TransactionSignScheme + CliChain>, + RC: Chain + + TransactionSignScheme + + CliChain>, RRC: Chain - + TransactionSignScheme, + + TransactionSignScheme + + CliChain>, LR: SubstrateFinalitySyncPipeline< SourceChain = LC, TargetChain = RC, @@ -802,34 +865,47 @@ where AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, { + at_left_relay_accounts.push(TaggedAccount::Headers { + id: right_headers_to_left_transaction_params.signer.public().into(), + bridged_chain: RRC::NAME.to_string(), + }); + at_left_relay_accounts.push(TaggedAccount::Parachains { + id: right_parachains_to_left_transaction_params.signer.public().into(), + bridged_chain: RRC::NAME.to_string(), + }); + at_right_relay_accounts.push(TaggedAccount::Headers { + id: left_headers_to_right_transaction_params.signer.public().into(), + bridged_chain: LC::NAME.to_string(), + }); + LR::start_relay_guards( &right_client, - &left_to_right_transaction_params, + &left_headers_to_right_transaction_params, right_can_start_version_guard, ) .await?; RRF::start_relay_guards( &left_client, - &right_to_left_transaction_params, + &right_headers_to_left_transaction_params, left_can_start_version_guard, ) .await?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( left_client.clone(), right_client, - left_to_right_transaction_params, + left_headers_to_right_transaction_params, left_to_right_only_mandatory_headers, ); let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::new::( right_relay_client.clone(), left_client.clone(), - right_to_left_transaction_params.clone(), + right_headers_to_left_transaction_params, right_to_left_only_mandatory_headers, ); let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::( right_relay_client, left_client, - right_to_left_transaction_params, + right_parachains_to_left_transaction_params, Arc::new(right_relay_to_left_on_demand_headers), ); @@ -866,3 +942,255 @@ where .map(drop) .map_err(|e| anyhow::format_err!("{}", e)) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_parse_relay_to_relay_options() { + // when + let res = RelayHeadersAndMessages::from_iter(vec![ + "relay-headers-and-messages", + "millau-rialto", + "--millau-host", + "millau-node-alice", + "--millau-port", + "9944", + "--millau-signer", + "//Charlie", + "--millau-messages-pallet-owner", + "//RialtoMessagesOwner", + "--millau-transactions-mortality", + "64", + "--rialto-host", + "rialto-node-alice", + "--rialto-port", + "9944", + "--rialto-signer", + "//Charlie", + "--rialto-messages-pallet-owner", + "//MillauMessagesOwner", + "--rialto-transactions-mortality", + "64", + "--lane", + "00000000", + "--lane", + "73776170", + "--prometheus-host", + "0.0.0.0", + ]); + + // then + assert_eq!( + res, + RelayHeadersAndMessages::MillauRialto(MillauRialtoHeadersAndMessages { + shared: HeadersAndMessagesSharedParams { + lane: vec![ + HexLaneId([0x00, 0x00, 0x00, 0x00]), + HexLaneId([0x73, 0x77, 0x61, 0x70]) + ], + relayer_mode: RelayerMode::Rational, + create_relayers_fund_accounts: false, + only_mandatory_headers: false, + prometheus_params: PrometheusParams { + no_prometheus: false, + prometheus_host: "0.0.0.0".into(), + prometheus_port: 9616, + }, + }, + left: MillauConnectionParams { + millau_host: "millau-node-alice".into(), + millau_port: 9944, + millau_secure: false, + millau_runtime_version: MillauRuntimeVersionParams { + millau_version_mode: RuntimeVersionType::Bundle, + millau_spec_version: None, + millau_transaction_version: None, + }, + }, + left_sign: MillauSigningParams { + millau_signer: Some("//Charlie".into()), + millau_signer_password: None, + millau_signer_file: None, + millau_signer_password_file: None, + millau_transactions_mortality: Some(64), + }, + left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { + millau_messages_pallet_owner: Some("//RialtoMessagesOwner".into()), + millau_messages_pallet_owner_password: None, + }, + left_headers_to_right_sign_override: MillauHeadersToRialtoSigningParams { + millau_headers_to_rialto_signer: None, + millau_headers_to_rialto_signer_password: None, + millau_headers_to_rialto_signer_file: None, + millau_headers_to_rialto_signer_password_file: None, + millau_headers_to_rialto_transactions_mortality: None, + }, + right: RialtoConnectionParams { + rialto_host: "rialto-node-alice".into(), + rialto_port: 9944, + rialto_secure: false, + rialto_runtime_version: RialtoRuntimeVersionParams { + rialto_version_mode: RuntimeVersionType::Bundle, + rialto_spec_version: None, + rialto_transaction_version: None, + }, + }, + right_sign: RialtoSigningParams { + rialto_signer: Some("//Charlie".into()), + rialto_signer_password: None, + rialto_signer_file: None, + rialto_signer_password_file: None, + rialto_transactions_mortality: Some(64), + }, + right_messages_pallet_owner: RialtoMessagesPalletOwnerSigningParams { + rialto_messages_pallet_owner: Some("//MillauMessagesOwner".into()), + rialto_messages_pallet_owner_password: None, + }, + right_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { + rialto_headers_to_millau_signer: None, + rialto_headers_to_millau_signer_password: None, + rialto_headers_to_millau_signer_file: None, + rialto_headers_to_millau_signer_password_file: None, + rialto_headers_to_millau_transactions_mortality: None, + }, + }), + ); + } + + #[test] + fn should_parse_relay_to_parachain_options() { + // when + let res = RelayHeadersAndMessages::from_iter(vec![ + "relay-headers-and-messages", + "millau-rialto-parachain", + "--millau-host", + "millau-node-alice", + "--millau-port", + "9944", + "--millau-signer", + "//Iden", + "--rialto-headers-to-millau-signer", + "//Ken", + "--millau-messages-pallet-owner", + "//RialtoParachainMessagesOwner", + "--millau-transactions-mortality", + "64", + "--rialto-parachain-host", + "rialto-parachain-collator-charlie", + "--rialto-parachain-port", + "9944", + "--rialto-parachain-signer", + "//George", + "--rialto-parachain-messages-pallet-owner", + "//MillauMessagesOwner", + "--rialto-parachain-transactions-mortality", + "64", + "--rialto-host", + "rialto-node-alice", + "--rialto-port", + "9944", + "--lane", + "00000000", + "--prometheus-host", + "0.0.0.0", + ]); + + // then + assert_eq!( + res, + RelayHeadersAndMessages::MillauRialtoParachain( + MillauRialtoParachainHeadersAndMessages { + shared: HeadersAndMessagesSharedParams { + lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], + relayer_mode: RelayerMode::Rational, + create_relayers_fund_accounts: false, + only_mandatory_headers: false, + prometheus_params: PrometheusParams { + no_prometheus: false, + prometheus_host: "0.0.0.0".into(), + prometheus_port: 9616, + }, + }, + left: MillauConnectionParams { + millau_host: "millau-node-alice".into(), + millau_port: 9944, + millau_secure: false, + millau_runtime_version: MillauRuntimeVersionParams { + millau_version_mode: RuntimeVersionType::Bundle, + millau_spec_version: None, + millau_transaction_version: None, + }, + }, + left_sign: MillauSigningParams { + millau_signer: Some("//Iden".into()), + millau_signer_password: None, + millau_signer_file: None, + millau_signer_password_file: None, + millau_transactions_mortality: Some(64), + }, + left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { + millau_messages_pallet_owner: Some("//RialtoParachainMessagesOwner".into()), + millau_messages_pallet_owner_password: None, + }, + left_headers_to_right_sign_override: + MillauHeadersToRialtoParachainSigningParams { + millau_headers_to_rialto_parachain_signer: None, + millau_headers_to_rialto_parachain_signer_password: None, + millau_headers_to_rialto_parachain_signer_file: None, + millau_headers_to_rialto_parachain_signer_password_file: None, + millau_headers_to_rialto_parachain_transactions_mortality: None, + }, + right: RialtoParachainConnectionParams { + rialto_parachain_host: "rialto-parachain-collator-charlie".into(), + rialto_parachain_port: 9944, + rialto_parachain_secure: false, + rialto_parachain_runtime_version: RialtoParachainRuntimeVersionParams { + rialto_parachain_version_mode: RuntimeVersionType::Bundle, + rialto_parachain_spec_version: None, + rialto_parachain_transaction_version: None, + }, + }, + right_sign: RialtoParachainSigningParams { + rialto_parachain_signer: Some("//George".into()), + rialto_parachain_signer_password: None, + rialto_parachain_signer_file: None, + rialto_parachain_signer_password_file: None, + rialto_parachain_transactions_mortality: Some(64), + }, + right_messages_pallet_owner: RialtoParachainMessagesPalletOwnerSigningParams { + rialto_parachain_messages_pallet_owner: Some( + "//MillauMessagesOwner".into() + ), + rialto_parachain_messages_pallet_owner_password: None, + }, + right_relay_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { + rialto_headers_to_millau_signer: Some("//Ken".into()), + rialto_headers_to_millau_signer_password: None, + rialto_headers_to_millau_signer_file: None, + rialto_headers_to_millau_signer_password_file: None, + rialto_headers_to_millau_transactions_mortality: None, + }, + right_parachains_to_left_sign_override: RialtoParachainsToMillauSigningParams { + rialto_parachains_to_millau_signer: None, + rialto_parachains_to_millau_signer_password: None, + rialto_parachains_to_millau_signer_file: None, + rialto_parachains_to_millau_signer_password_file: None, + rialto_parachains_to_millau_transactions_mortality: None, + }, + right_relay: RialtoConnectionParams { + rialto_host: "rialto-node-alice".into(), + rialto_port: 9944, + rialto_secure: false, + rialto_runtime_version: RialtoRuntimeVersionParams { + rialto_version_mode: RuntimeVersionType::Bundle, + rialto_spec_version: None, + rialto_transaction_version: None, + }, + }, + } + ), + ); + } +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 73dedb3a33497..51edf857838e9 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -48,3 +48,61 @@ pub struct TransactionParams { /// Transactions mortality. pub mortality: Option, } + +/// Tagged relay account, which balance may be exposed as metrics by the relay. +#[derive(Clone, Debug)] +pub enum TaggedAccount { + /// Account, used to sign headers relay transactions from given bridged chain. + Headers { + /// Account id. + id: AccountId, + /// Name of the bridged chain, which headers are relayed. + bridged_chain: String, + }, + /// Account, used to sign parachains relay transactions from given bridged relay chain. + Parachains { + /// Account id. + id: AccountId, + /// Name of the bridged relay chain with parachain heads. + bridged_chain: String, + }, + /// Account, used to sign message relay transactions from given bridged chain. + Messages { + /// Account id. + id: AccountId, + /// Name of the bridged chain, which sends us messages or delivery confirmations. + bridged_chain: String, + }, + /// Account, used to sign messages with-bridged-chain pallet parameters update transactions. + MessagesPalletOwner { + /// Account id. + id: AccountId, + /// Name of the chain, bridged using messages pallet at our chain. + bridged_chain: String, + }, +} + +impl TaggedAccount { + /// Returns reference to the account id. + pub fn id(&self) -> &AccountId { + match *self { + TaggedAccount::Headers { ref id, .. } => id, + TaggedAccount::Parachains { ref id, .. } => id, + TaggedAccount::Messages { ref id, .. } => id, + TaggedAccount::MessagesPalletOwner { ref id, .. } => id, + } + } + + /// Returns stringified account tag. + pub fn tag(&self) -> String { + match *self { + TaggedAccount::Headers { ref bridged_chain, .. } => format!("{}Headers", bridged_chain), + TaggedAccount::Parachains { ref bridged_chain, .. } => + format!("{}Parachains", bridged_chain), + TaggedAccount::Messages { ref bridged_chain, .. } => + format!("{}Messages", bridged_chain), + TaggedAccount::MessagesPalletOwner { ref bridged_chain, .. } => + format!("{}MessagesPalletOwner", bridged_chain), + } + } +} diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index b165892fda1dc..7c621b4c39a51 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -16,7 +16,7 @@ //! Tools for supporting message lanes between two Substrate-based chains. -use crate::{helpers::tokens_conversion_rate, messages_lane::SubstrateMessageLane}; +use crate::{helpers::tokens_conversion_rate, messages_lane::SubstrateMessageLane, TaggedAccount}; use codec::Decode; use frame_system::AccountInfo; @@ -274,13 +274,12 @@ pub fn standalone_metrics( pub async fn add_relay_balances_metrics( client: Client, metrics: MetricsParams, - relay_account_id: Option>, - messages_pallet_owner_account_id: Option>, + relay_accounts: Vec>>, ) -> anyhow::Result where BalanceOf: Into + std::fmt::Debug, { - if relay_account_id.is_none() && messages_pallet_owner_account_id.is_none() { + if relay_accounts.is_empty() { return Ok(metrics) } @@ -306,26 +305,18 @@ where e, ) })?; - if let Some(relay_account_id) = relay_account_id { + + for account in relay_accounts { let relay_account_balance_metric = FloatStorageValueMetric::new( FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, client.clone(), - C::account_info_storage_key(&relay_account_id), - format!("at_{}_relay_balance", C::NAME), - format!("Balance of the relay account at the {}", C::NAME), + C::account_info_storage_key(account.id()), + format!("at_{}_relay_{}_balance", C::NAME, account.tag()), + format!("Balance of the {} relay account at the {}", account.tag(), C::NAME), )?; relay_account_balance_metric.register_and_spawn(&metrics.registry)?; } - if let Some(messages_pallet_owner_account_id) = messages_pallet_owner_account_id { - let pallet_owner_account_balance_metric = FloatStorageValueMetric::new( - FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, - client.clone(), - C::account_info_storage_key(&messages_pallet_owner_account_id), - format!("at_{}_messages_pallet_owner_balance", C::NAME), - format!("Balance of the messages pallet owner at the {}", C::NAME), - )?; - pallet_owner_account_balance_metric.register_and_spawn(&metrics.registry)?; - } + Ok(metrics) } From 1f722b3d88a232c874583f9326cc586b8ef11390 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 21 Jun 2022 14:52:07 +0300 Subject: [PATCH 0712/1210] Fix on-different-forks metrics during initialization (#1468) * fix on-different-forks metrics during initialization * "initialize" parachain finality pallet in on-demand parachains relay * decrease converstion rate requests count * more error logging * fix compilation * clippy --- README.md | 2 +- bin/millau/runtime/src/lib.rs | 23 ++--- bin/rialto-parachain/runtime/src/lib.rs | 5 +- bin/rialto/runtime/src/lib.rs | 5 +- modules/grandpa/src/lib.rs | 16 +-- primitives/chain-kusama/src/lib.rs | 2 +- primitives/chain-millau/src/lib.rs | 2 +- primitives/chain-polkadot/src/lib.rs | 2 +- primitives/chain-rialto-parachain/src/lib.rs | 2 +- primitives/chain-rialto/src/lib.rs | 2 +- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-westend/src/lib.rs | 2 +- primitives/chain-wococo/src/lib.rs | 2 +- primitives/header-chain/src/lib.rs | 6 +- relays/client-substrate/src/client.rs | 20 +++- relays/lib-substrate-relay/src/error.rs | 5 + .../src/finality/engine.rs | 19 +++- .../src/finality/initialize.rs | 21 +--- .../src/finality/target.rs | 9 +- .../src/messages_source.rs | 14 ++- .../src/messages_target.rs | 4 + .../src/on_demand/headers.rs | 2 +- .../src/on_demand/parachains.rs | 97 ++++++++++++++----- .../src/parachains/target.rs | 12 ++- relays/utils/src/metrics/float_json_value.rs | 2 +- 25 files changed, 173 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index 3d3b177bbaae6..e2192e3d6780f 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ To run a Rialto node for example, you can use the following command: ```bash docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ - -it paritytech/rialto-bridge-node --dev --tmp \ + -it local/rialto-bridge-node --dev --tmp \ --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external ``` diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 5195f9b48a2ae..c5c002c472179 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -795,33 +795,28 @@ impl_runtime_apis! { } impl bp_rialto::RialtoFinalityApi for Runtime { - fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { - let header = BridgeRialtoGrandpa::best_finalized(); - (header.number, header.hash()) + fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> { + BridgeRialtoGrandpa::best_finalized().map(|header| (header.number, header.hash())) } } impl bp_westend::WestendFinalityApi for Runtime { - fn best_finalized() -> (bp_westend::BlockNumber, bp_westend::Hash) { - let header = BridgeWestendGrandpa::best_finalized(); - (header.number, header.hash()) + fn best_finalized() -> Option<(bp_westend::BlockNumber, bp_westend::Hash)> { + BridgeWestendGrandpa::best_finalized().map(|header| (header.number, header.hash())) } } impl bp_rialto_parachain::RialtoParachainFinalityApi for Runtime { - fn best_finalized() -> (bp_rialto::BlockNumber, bp_rialto::Hash) { + fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> { // the parachains finality pallet is never decoding parachain heads, so it is // only done in the integration code use bp_rialto_parachain::RIALTO_PARACHAIN_ID; - let best_rialto_parachain_head = pallet_bridge_parachains::Pallet::< + let encoded_head = pallet_bridge_parachains::Pallet::< Runtime, WithRialtoParachainsInstance, - >::best_parachain_head(RIALTO_PARACHAIN_ID.into()) - .and_then(|encoded_header| bp_rialto_parachain::Header::decode(&mut &encoded_header.0[..]).ok()); - match best_rialto_parachain_head { - Some(head) => (*head.number(), head.hash()), - None => (Default::default(), Default::default()), - } + >::best_parachain_head(RIALTO_PARACHAIN_ID.into())?; + let head = bp_rialto_parachain::Header::decode(&mut &encoded_head.0[..]).ok()?; + Some((*head.number(), head.hash())) } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index ec1c754f7dfdb..0927f138f3baf 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -683,9 +683,8 @@ impl_runtime_apis! { } impl bp_millau::MillauFinalityApi for Runtime { - fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { - let header = BridgeMillauGrandpa::best_finalized(); - (header.number, header.hash()) + fn best_finalized() -> Option<(bp_millau::BlockNumber, bp_millau::Hash)> { + BridgeMillauGrandpa::best_finalized().map(|header| (header.number, header.hash())) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9b7dc70394ac5..e10ddda0fb3a9 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -640,9 +640,8 @@ impl_runtime_apis! { } impl bp_millau::MillauFinalityApi for Runtime { - fn best_finalized() -> (bp_millau::BlockNumber, bp_millau::Hash) { - let header = BridgeMillauGrandpa::best_finalized(); - (header.number, header.hash()) + fn best_finalized() -> Option<(bp_millau::BlockNumber, bp_millau::Hash)> { + BridgeMillauGrandpa::best_finalized().map(|header| (header.number, header.hash())) } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 8fa0ed89cca2a..684905f288606 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -537,17 +537,9 @@ impl, I: 'static> Pallet { /// /// Returns a dummy header if there is no best header. This can only happen /// if the pallet has not been initialized yet. - pub fn best_finalized() -> BridgedHeader { + pub fn best_finalized() -> Option> { let hash = >::get(); - >::get(hash).unwrap_or_else(|| { - >::new( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ) - }) + >::get(hash) } /// Check if a particular header is known to the bridge pallet. @@ -718,7 +710,7 @@ mod tests { BestFinalized::::get(), BridgedBlockHash::::default() ); - assert_eq!(Pallet::::best_finalized(), test_header(0)); + assert_eq!(Pallet::::best_finalized(), None); let init_data = init_with_origin(Origin::root()).unwrap(); @@ -1131,7 +1123,7 @@ mod tests { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1)); - let first_header = Pallet::::best_finalized(); + let first_header = Pallet::::best_finalized().unwrap(); next_block(); assert_ok!(submit_finality_proof(2)); diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 880fe5ac1bd00..637f6b9da03f7 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -117,7 +117,7 @@ sp_api::decl_runtime_apis! { /// Kusama runtime itself. pub trait KusamaFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to Kusama chain. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index c9b4153b2fc89..240c2daaa98c1 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -314,7 +314,7 @@ sp_api::decl_runtime_apis! { /// Millau runtime itself. pub trait MillauFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to Millau chain. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index e16a23e1d148f..f06bb917edc71 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -118,7 +118,7 @@ sp_api::decl_runtime_apis! { /// Polkadot runtime itself. pub trait PolkadotFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to Polkadot chain. diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index df66996c4b133..38b4192bf348c 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -241,7 +241,7 @@ sp_api::decl_runtime_apis! { /// RialtoParachain runtime itself. pub trait RialtoParachainFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to RialtoParachain chain. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 9d598b8d22fed..e5c5ebab76ff5 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -262,7 +262,7 @@ sp_api::decl_runtime_apis! { /// Rialto runtime itself. pub trait RialtoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to Rialto chain. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a0f545a95c21e..1c2bfb42d0f0d 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -113,7 +113,7 @@ sp_api::decl_runtime_apis! { /// Rococo runtime itself. pub trait RococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to Rococo chain. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index c7ebe4b00fd5d..539cf69eb73a5 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -106,6 +106,6 @@ sp_api::decl_runtime_apis! { /// Westend runtime itself. pub trait WestendFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 69039355923c4..6e0bad1227404 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -70,7 +70,7 @@ sp_api::decl_runtime_apis! { /// Wococo runtime itself. pub trait WococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> (BlockNumber, Hash); + fn best_finalized() -> Option<(BlockNumber, Hash)>; } /// Outbound message lane API for messages that are sent to Wococo chain. diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 29d9cc525445d..ff8ee82f41e42 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -88,7 +88,7 @@ pub trait InclusionProofVerifier { /// A trait for pallets which want to keep track of finalized headers from a bridged chain. pub trait HeaderChain { /// Get the best finalized header known to the header chain. - fn best_finalized() -> H; + fn best_finalized() -> Option; /// Get the best authority set known to the header chain. fn authority_set() -> AuthoritySet; @@ -98,8 +98,8 @@ pub trait HeaderChain { } impl HeaderChain for () { - fn best_finalized() -> H { - H::default() + fn best_finalized() -> Option { + None } fn authority_set() -> AuthoritySet { diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index bb9f823005668..448c33c5ba397 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -456,8 +456,12 @@ impl Client { IndexOf, C::SignedBlock, >::author_submit_extrinsic(&*client, transaction) - .await?; - log::trace!(target: "bridge", "Sent transaction to Substrate node: {:?}", tx_hash); + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; + log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) .await @@ -499,7 +503,11 @@ impl Client { IndexOf, C::SignedBlock, >::author_submit_extrinsic(&*client, extrinsic) - .await?; + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) @@ -528,7 +536,11 @@ impl Client { .map_err(|e| Error::RpcError(e.into()))?])), "author_unwatchExtrinsic", ) - .await?; + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(subscription) }) diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs index 9402d55e37981..5accba4fc7ce5 100644 --- a/relays/lib-substrate-relay/src/error.rs +++ b/relays/lib-substrate-relay/src/error.rs @@ -58,4 +58,9 @@ pub enum Error { /// Failed to retrieve best finalized source header hash from the target chain. #[error("Failed to retrieve best finalized {0} header from the target chain: {1}")] RetrieveBestFinalizedHeaderHash(&'static str, client::Error), + /// Failed to submit signed extrinsic from to the target chain. + #[error( + "Failed to retrieve `is_initialized` flag of the with-{0} finality pallet at {1}: {2:?}" + )] + IsInitializedRetrieve(&'static str, &'static str, client::Error), } diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 0b20a3222d232..76038fcb97676 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -37,7 +37,7 @@ use std::marker::PhantomData; /// Finality enfine, used by the Substrate chain. #[async_trait] -pub trait Engine { +pub trait Engine: Send { /// Unique consensus engine identifier. const ID: ConsensusEngineId; /// Type of finality proofs, used by consensus engine. @@ -59,6 +59,23 @@ pub trait Engine { async fn prepare_initialization_data( client: Client, ) -> Result, BlockNumberOf>>; + + /// Returns `Ok(true)` if finality pallet at the bridged chain has already been initialized. + async fn is_initialized( + target_client: &Client, + ) -> Result { + Ok(target_client + .raw_storage_value(Self::is_initialized_key(), None) + .await? + .is_some()) + } + + /// Returns `Ok(true)` if finality pallet at the bridged chain is halted. + async fn is_halted( + target_client: &Client, + ) -> Result { + Ok(target_client.storage_value(Self::is_halted_key(), None).await?.unwrap_or(false)) + } } /// GRANDPA finality engine. diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index 2fc9302d90f58..be1719b4ae033 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -23,7 +23,7 @@ use crate::{error::Error, finality::engine::Engine}; -use relay_substrate_client::{BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf}; +use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use sp_core::Bytes; use sp_runtime::traits::Header as HeaderT; @@ -80,7 +80,9 @@ where + Send + 'static, { - let is_initialized = is_initialized::(&target_client).await?; + let is_initialized = E::is_initialized(&target_client) + .await + .map_err(|e| Error::IsInitializedRetrieve(SourceChain::NAME, TargetChain::NAME, e))?; if is_initialized { log::info!( target: "bridge", @@ -108,18 +110,3 @@ where .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; Ok(Some(initialization_tx_hash)) } - -/// Returns `Ok(true)` if bridge has already been initialized. -pub(crate) async fn is_initialized< - E: Engine, - SourceChain: Chain, - TargetChain: Chain, ->( - target_client: &Client, -) -> Result, BlockNumberOf>> { - Ok(target_client - .raw_storage_value(E::is_initialized_key(), None) - .await - .map_err(|err| Error::RetrieveBestFinalizedHeaderHash(SourceChain::NAME, err))? - .is_some()) -} diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 12098a7479977..d04fe280e5a2f 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -51,15 +51,12 @@ impl SubstrateFinalityTarget

{ /// Ensure that the bridge pallet at target chain is active. pub async fn ensure_pallet_active(&self) -> Result<(), Error> { - let is_halted = self.client.storage_value(P::FinalityEngine::is_halted_key(), None).await?; - if is_halted.unwrap_or(false) { + let is_halted = P::FinalityEngine::is_halted(&self.client).await?; + if is_halted { return Err(Error::BridgePalletIsHalted) } - let is_initialized = - super::initialize::is_initialized::( - &self.client, - ) + let is_initialized = P::FinalityEngine::is_initialized(&self.client) .await .map_err(|e| Error::Custom(e.to_string()))?; if !is_initialized { diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 85bd9ea7d0f77..0e21ef66eda3b 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -146,7 +146,11 @@ where async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver + // + // we can't continue to deliver messages if target node is out of sync, because + // it may have already received (some of) messages that we're going to deliver self.source_client.ensure_synced().await?; + self.target_client.ensure_synced().await?; // we can't relay confirmations if messages pallet at source chain is halted self.ensure_pallet_active().await?; @@ -562,9 +566,13 @@ where Some(at_self_hash), ) .await?; - let decoded_best_finalized_peer_on_self: (BlockNumberOf, HashOf) = - Decode::decode(&mut &encoded_best_finalized_peer_on_self.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + let decoded_best_finalized_peer_on_self = + Option::<(BlockNumberOf, HashOf)>::decode( + &mut &encoded_best_finalized_peer_on_self.0[..], + ) + .map_err(SubstrateError::ResponseParseFailed)? + .map(Ok) + .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))?; let peer_on_self_best_finalized_id = HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 00c0c1570541e..d860fa68a934b 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -146,8 +146,12 @@ where BalanceOf: TryFrom>, { async fn state(&self) -> Result>, SubstrateError> { + // we can't continue to deliver confirmations if source node is out of sync, because + // it may have already received confirmations that we're going to deliver + // // we can't continue to deliver messages if target node is out of sync, because // it may have already received (some of) messages that we're going to deliver + self.source_client.ensure_synced().await?; self.target_client.ensure_synced().await?; // we can't relay messages if messages pallet at target chain is halted self.ensure_pallet_active().await?; diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index f22ad96b636ea..749205ef9b3cd 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -253,7 +253,7 @@ async fn background_task( log::info!( target: "bridge", - "[{}] Starting on-demand relay task\n\t\ + "[{}] Starting on-demand headers relay task\n\t\ Only mandatory headers: {}\n\t\ Tx mortality: {:?} (~{}m)\n\t\ Stall timeout: {:?}", diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 579f3103e8222..f25d3b76948c9 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -181,6 +181,7 @@ async fn background_task( new_required_parachain_header_number, ); }, + _ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, _ = parachains_relay_task => { // this should never happen in practice given the current code restart_relay = true; @@ -266,7 +267,7 @@ async fn background_task( log::info!( target: "bridge", - "[{}] Starting on-demand-relay task\n\t\ + "[{}] Starting on-demand-parachains relay task\n\t\ Tx mortality: {:?} (~{}m)\n\t\ Stall timeout: {:?}", relay_task_name, @@ -317,7 +318,7 @@ struct RelayData { /// Parachain header number that is required at the target chain. pub required_para_header: ParaNumber, /// Parachain header number, known to the target chain. - pub para_header_at_target: ParaNumber, + pub para_header_at_target: Option, /// Parachain header id, known to the source (relay) chain. pub para_header_at_source: Option>, /// Parachain header, that is available at the source relay chain at `relay_header_at_target` @@ -374,9 +375,15 @@ where best_target_block_hash, P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD, ) - .await - .map_err(map_target_err)? - .0; + .await; + // if there are no parachain heads at the target (`BridgePalletIsNotInitialized`), we'll need + // to submit at least one. Otherwise the pallet will be treated as uninitialized and messages + // sync will stall. + let para_header_at_target = match para_header_at_target { + Ok(para_header_at_target) => Some(para_header_at_target.0), + Err(SubstrateError::BridgePalletIsNotInitialized) => None, + Err(e) => return Err(map_target_err(e)), + }; let best_finalized_relay_header = source.client().best_finalized_header().await.map_err(map_source_err)?; @@ -424,7 +431,7 @@ fn select_headers_to_relay( ) -> RelayState where ParaHash: Clone, - ParaNumber: Copy + PartialOrd, + ParaNumber: Copy + PartialOrd + Zero, RelayNumber: Copy + Debug + Ord, { // this switch is responsible for processing `RelayingRelayHeader` state @@ -450,30 +457,38 @@ where } // this switch is responsible for processing `RelayingParaHeader` state + let para_header_at_target_or_zero = data.para_header_at_target.unwrap_or_else(Zero::zero); match state { RelayState::Idle => (), RelayState::RelayingRelayHeader(_) => unreachable!("processed by previous match; qed"), RelayState::RelayingParaHeader(para_header_id) => { - if data.para_header_at_target < para_header_id.0 { + if para_header_at_target_or_zero < para_header_id.0 { // parachain header hasn't yet been relayed return RelayState::RelayingParaHeader(para_header_id) } }, } - // if we have already satisfied our "customer", do nothing - if data.required_para_header <= data.para_header_at_target { - return RelayState::Idle - } - // if we haven't read para head from the source, we can't yet do anyhting let para_header_at_source = match data.para_header_at_source { Some(ref para_header_at_source) => para_header_at_source.clone(), None => return RelayState::Idle, }; + // if we have parachain head at the source, but no parachain heads at the target, we'll need + // to deliver at least one parachain head + let (required_para_header, para_header_at_target) = match data.para_header_at_target { + Some(para_header_at_target) => (data.required_para_header, para_header_at_target), + None => (para_header_at_source.0, Zero::zero()), + }; + + // if we have already satisfied our "customer", do nothing + if required_para_header <= para_header_at_target { + return RelayState::Idle + } + // if required header is not available even at the source chain, let's wait - if data.required_para_header > para_header_at_source.0 { + if required_para_header > para_header_at_source.0 { return RelayState::Idle } @@ -499,7 +514,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 90, - para_header_at_target: 50, + para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 700, @@ -517,7 +532,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 90, - para_header_at_target: 50, + para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 750, @@ -535,7 +550,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 90, - para_header_at_target: 50, + para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 780, @@ -552,7 +567,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 90, - para_header_at_target: 50, + para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 780, @@ -570,7 +585,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 90, - para_header_at_target: 105, + para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 780, @@ -588,7 +603,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 120, - para_header_at_target: 105, + para_header_at_target: Some(105), para_header_at_source: None, relay_header_at_source: 800, relay_header_at_target: 780, @@ -606,7 +621,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 120, - para_header_at_target: 105, + para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, relay_header_at_target: 780, @@ -624,7 +639,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 120, - para_header_at_target: 105, + para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, relay_header_at_target: 780, @@ -642,7 +657,7 @@ mod tests { select_headers_to_relay( &RelayData { required_para_header: 120, - para_header_at_target: 105, + para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, relay_header_at_target: 800, @@ -660,7 +675,7 @@ mod tests { select_headers_to_relay::( &RelayData { required_para_header: 120, - para_header_at_target: 105, + para_header_at_target: Some(105), para_header_at_source: None, relay_header_at_source: 800, relay_header_at_target: 800, @@ -671,4 +686,40 @@ mod tests { RelayState::Idle, ); } + + #[test] + fn relay_starts_relaying_first_parachain_header() { + assert_eq!( + select_headers_to_relay::( + &RelayData { + required_para_header: 0, + para_header_at_target: None, + para_header_at_source: Some(HeaderId(125, 125)), + relay_header_at_source: 800, + relay_header_at_target: 800, + para_header_at_relay_header_at_target: Some(HeaderId(125, 125)), + }, + RelayState::Idle, + ), + RelayState::RelayingParaHeader(HeaderId(125, 125)), + ); + } + + #[test] + fn relay_starts_relaying_relay_header_to_relay_first_parachain_header() { + assert_eq!( + select_headers_to_relay::( + &RelayData { + required_para_header: 0, + para_header_at_target: None, + para_header_at_source: Some(HeaderId(125, 125)), + relay_header_at_source: 800, + relay_header_at_target: 700, + para_header_at_relay_header_at_target: Some(HeaderId(125, 125)), + }, + RelayState::Idle, + ), + RelayState::RelayingRelayHeader(800), + ); + } } diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 9ff35f5a0c106..67d82e1f7075f 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -102,11 +102,13 @@ where Some(at_block.1), ) .await?; - let decoded_best_finalized_source_block: ( - BlockNumberOf, - HashOf, - ) = Decode::decode(&mut &encoded_best_finalized_source_block.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; + let decoded_best_finalized_source_block = + Option::<(BlockNumberOf, HashOf)>::decode( + &mut &encoded_best_finalized_source_block.0[..], + ) + .map_err(SubstrateError::ResponseParseFailed)? + .map(Ok) + .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))?; Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1)) } diff --git a/relays/utils/src/metrics/float_json_value.rs b/relays/utils/src/metrics/float_json_value.rs index 7535cbef9863f..17b09e050973a 100644 --- a/relays/utils/src/metrics/float_json_value.rs +++ b/relays/utils/src/metrics/float_json_value.rs @@ -27,7 +27,7 @@ use async_trait::async_trait; use std::time::Duration; /// Value update interval. -const UPDATE_INTERVAL: Duration = Duration::from_secs(60); +const UPDATE_INTERVAL: Duration = Duration::from_secs(300); /// Metric that represents float value received from HTTP service as float gauge. /// From 8de0b4b79e0edb2a04fde99cc27409b64d074491 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 21 Jun 2022 15:41:43 +0300 Subject: [PATCH 0713/1210] remove local images refs (#1470) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2192e3d6780f..3d3b177bbaae6 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ To run a Rialto node for example, you can use the following command: ```bash docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ - -it local/rialto-bridge-node --dev --tmp \ + -it paritytech/rialto-bridge-node --dev --tmp \ --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external ``` From 0f0b0e42288dad67fb83afb1ef4b634d01790bf4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 24 Jun 2022 15:37:46 +0300 Subject: [PATCH 0714/1210] Store both block number and hash in best finalized storage value (#1475) * store both block number and hash in BestFinalized * also fix relay code * spelling --- modules/grandpa/src/benchmarking.rs | 2 +- modules/grandpa/src/extension.rs | 14 ++++------ modules/grandpa/src/lib.rs | 26 +++++++++---------- primitives/header-chain/src/storage_keys.rs | 8 +++--- .../src/finality/engine.rs | 2 +- 5 files changed, 24 insertions(+), 28 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 46e1e41a87028..f12894bb5cbd2 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -115,7 +115,7 @@ benchmarks_instance_pallet! { let header: BridgedHeader = bp_test_utils::test_header(header_number::()); let expected_hash = header.hash(); - assert_eq!(>::get(), expected_hash); + assert_eq!(>::get().unwrap().1, expected_hash); assert!(>::contains_key(expected_hash)); } } diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index 654b74bf446ea..bda7d49d7c436 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -66,12 +66,9 @@ macro_rules! declare_bridge_reject_obsolete_grandpa_header { let bundled_block_number = *finality_target.number(); - let best_finalized_hash = $crate::BestFinalized::<$runtime, $instance>::get(); - let best_finalized_number = match $crate::ImportedHeaders::< - $runtime, - $instance, - >::get(best_finalized_hash) { - Some(best_finalized_header) => *best_finalized_header.number(), + let best_finalized = $crate::BestFinalized::<$runtime, $instance>::get(); + let best_finalized_number = match best_finalized { + Some((best_finalized_number, _)) => best_finalized_number, None => return sp_runtime::transaction_validity::InvalidTransaction::Call.into(), }; @@ -113,7 +110,7 @@ macro_rules! declare_bridge_reject_obsolete_grandpa_header { mod tests { use crate::{ mock::{run_test, test_header, Call, TestNumber, TestRuntime}, - BestFinalized, ImportedHeaders, + BestFinalized, }; use bp_test_utils::make_default_justification; use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; @@ -140,8 +137,7 @@ mod tests { fn sync_to_header_10() { let header10_hash = sp_core::H256::default(); - BestFinalized::::put(header10_hash); - ImportedHeaders::::insert(header10_hash, test_header(10)); + BestFinalized::::put((10, header10_hash)); } #[test] diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 684905f288606..1527de80fc22b 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -143,7 +143,10 @@ pub mod pallet { let (hash, number) = (finality_target.hash(), finality_target.number()); log::trace!(target: "runtime::bridge-grandpa", "Going to try and finalize header {:?}", finality_target); - let best_finalized = match >::get(>::get()) { + let best_finalized = BestFinalized::::get(); + let best_finalized = + best_finalized.and_then(|(_, hash)| ImportedHeaders::::get(hash)); + let best_finalized = match best_finalized { Some(best_finalized) => best_finalized, None => { log::error!( @@ -273,7 +276,7 @@ pub mod pallet { /// Hash of the best finalized header. #[pallet::storage] pub type BestFinalized, I: 'static = ()> = - StorageValue<_, BridgedBlockHash, ValueQuery>; + StorageValue<_, (BridgedBlockNumber, BridgedBlockHash), OptionQuery>; /// A ring buffer of imported hashes. Ordered by the insertion time. #[pallet::storage] @@ -458,7 +461,7 @@ pub mod pallet { ) { let index = >::get(); let pruning = >::try_get(index); - >::put(hash); + >::put((*header.number(), hash)); >::insert(hash, header); >::insert(index, hash); @@ -538,7 +541,7 @@ impl, I: 'static> Pallet { /// Returns a dummy header if there is no best header. This can only happen /// if the pallet has not been initialized yet. pub fn best_finalized() -> Option> { - let hash = >::get(); + let (_, hash) = >::get()?; >::get(hash) } @@ -706,16 +709,13 @@ mod tests { #[test] fn init_storage_entries_are_correctly_initialized() { run_test(|| { - assert_eq!( - BestFinalized::::get(), - BridgedBlockHash::::default() - ); + assert_eq!(BestFinalized::::get(), None,); assert_eq!(Pallet::::best_finalized(), None); let init_data = init_with_origin(Origin::root()).unwrap(); assert!(>::contains_key(init_data.header.hash())); - assert_eq!(BestFinalized::::get(), init_data.header.hash()); + assert_eq!(BestFinalized::::get().unwrap().1, init_data.header.hash()); assert_eq!( CurrentAuthoritySet::::get().authorities, init_data.authority_list @@ -826,7 +826,7 @@ mod tests { ); let header = test_header(1); - assert_eq!(>::get(), header.hash()); + assert_eq!(>::get().unwrap().1, header.hash()); assert!(>::contains_key(header.hash())); }) } @@ -943,7 +943,7 @@ mod tests { ); // Make sure that our header is the best finalized - assert_eq!(>::get(), header.hash()); + assert_eq!(>::get().unwrap().1, header.hash()); assert!(>::contains_key(header.hash())); // Make sure that the authority set actually changed upon importing our header @@ -1027,7 +1027,7 @@ mod tests { header.set_state_root(state_root); let hash = header.hash(); - >::put(hash); + >::put((2, hash)); >::insert(hash, header); assert_ok!( @@ -1153,7 +1153,7 @@ mod tests { assert_eq!( BestFinalized::::storage_value_final_key().to_vec(), - bp_header_chain::storage_keys::best_finalized_hash_key("Grandpa").0, + bp_header_chain::storage_keys::best_finalized_key("Grandpa").0, ); } } diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs index e123703eed50e..14c40d69853b9 100644 --- a/primitives/header-chain/src/storage_keys.rs +++ b/primitives/header-chain/src/storage_keys.rs @@ -34,8 +34,8 @@ pub fn is_halted_key(pallet_prefix: &str) -> StorageKey { ) } -/// Storage key of the best finalized header hash value in the runtime storage. -pub fn best_finalized_hash_key(pallet_prefix: &str) -> StorageKey { +/// Storage key of the best finalized header number and hash value in the runtime storage. +pub fn best_finalized_key(pallet_prefix: &str) -> StorageKey { StorageKey( bp_runtime::storage_value_final_key( pallet_prefix.as_bytes(), @@ -64,10 +64,10 @@ mod tests { } #[test] - fn best_finalized_hash_key_computed_properly() { + fn best_finalized_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // compatibility with previous pallet. - let storage_key = best_finalized_hash_key("BridgeGrandpa").0; + let storage_key = best_finalized_key("BridgeGrandpa").0; assert_eq!( storage_key, hex!("0b06f475eddb98cf933a12262e0388dea4ebafdd473c549fdb24c5c991c5591c").to_vec(), diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 76038fcb97676..0f2cc87660bfc 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -118,7 +118,7 @@ impl Engine for Grandpa { } fn is_initialized_key() -> StorageKey { - bp_header_chain::storage_keys::best_finalized_hash_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } async fn finality_proofs(client: Client) -> Result, SubstrateError> { From ec16a2dce8847980e56dd860f759e7219613c67b Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 24 Jun 2022 21:23:01 +0300 Subject: [PATCH 0715/1210] Avoid duplicate function definitions Avoid duplicate function definitions for: - ensure_owner_or_root() - ensure_not_halted() - set_owner() - set_operating_mode() / set_operational() Signed-off-by: Serban Iorga --- modules/grandpa/src/lib.rs | 88 +++++++++------------------ modules/messages/src/lib.rs | 85 +++++++++----------------- primitives/runtime/Cargo.toml | 2 + primitives/runtime/src/lib.rs | 84 ++++++++++++++++++++++++- relays/lib-substrate-relay/src/lib.rs | 15 +++-- 5 files changed, 150 insertions(+), 124 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 1527de80fc22b..726de9c507ed4 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -37,12 +37,12 @@ #![allow(clippy::large_enum_variant)] use bp_header_chain::{justification::GrandpaJustification, InitializationData}; -use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf}; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{ensure, fail}; -use frame_system::{ensure_signed, RawOrigin}; +use frame_system::ensure_signed; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; -use sp_runtime::traits::{BadOrigin, Header as HeaderT, Zero}; +use sp_runtime::traits::{Header as HeaderT, Zero}; use sp_std::{boxed::Box, convert::TryInto}; mod extension; @@ -117,6 +117,18 @@ pub mod pallet { } } + impl, I: 'static> OwnedBridgeModule for Pallet { + const LOG_TARGET: &'static str = "runtime::bridge-grandpa"; + const OPERATING_MODE_KEY: &'static str = "IsHalted"; + type OwnerStorage = PalletOwner; + type OperatingMode = bool; + type OperatingModeStorage = IsHalted; + + fn is_halted() -> bool { + Self::OperatingModeStorage::get() + } + } + #[pallet::call] impl, I: 'static> Pallet { /// Verify a target header is finalized according to the given finality proof. @@ -135,7 +147,7 @@ pub mod pallet { finality_target: Box>, justification: GrandpaJustification>, ) -> DispatchResultWithPostInfo { - ensure_operational::()?; + Self::ensure_not_halted().map_err(Error::::BridgeModule)?; let _ = ensure_signed(origin)?; ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); @@ -198,7 +210,7 @@ pub mod pallet { origin: OriginFor, init_data: super::InitializationData>, ) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; + Self::ensure_owner_or_root(origin)?; let init_allowed = !>::exists(); ensure!(init_allowed, >::AlreadyInitialized); @@ -217,43 +229,16 @@ pub mod pallet { /// /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_owner( - origin: OriginFor, - new_owner: Option, - ) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; - match new_owner { - Some(new_owner) => { - PalletOwner::::put(&new_owner); - log::info!(target: "runtime::bridge-grandpa", "Setting pallet Owner to: {:?}", new_owner); - }, - None => { - PalletOwner::::kill(); - log::info!(target: "runtime::bridge-grandpa", "Removed Owner of pallet."); - }, - } - - Ok(().into()) + pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { + >::set_owner(origin, new_owner) } /// Halt or resume all pallet operations. /// /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operational( - origin: OriginFor, - operational: bool, - ) -> DispatchResultWithPostInfo { - ensure_owner_or_root::(origin)?; - >::put(!operational); - - if operational { - log::info!(target: "runtime::bridge-grandpa", "Resuming pallet operations."); - } else { - log::warn!(target: "runtime::bridge-grandpa", "Stopping pallet operations."); - } - - Ok(().into()) + pub fn set_operational(origin: OriginFor, operational: bool) -> DispatchResult { + Self::set_operating_mode(origin, !operational) } } @@ -310,7 +295,7 @@ pub mod pallet { /// If true, all pallet transactions are failed immediately. #[pallet::storage] - pub(super) type IsHalted, I: 'static = ()> = StorageValue<_, bool, ValueQuery>; + pub type IsHalted, I: 'static = ()> = StorageValue<_, bool, ValueQuery>; #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { @@ -364,10 +349,10 @@ pub mod pallet { NotInitialized, /// The pallet has already been initialized. AlreadyInitialized, - /// All pallet operations are halted. - Halted, /// The storage proof doesn't contains storage root. So it is invalid for given header. StorageRootMismatch, + /// Error generated by the `OwnedBridgeModule` trait. + BridgeModule(bp_runtime::OwnedBridgeModuleError), } /// Check the given header for a GRANDPA scheduled authority set change. If a change @@ -513,26 +498,6 @@ pub mod pallet { insert_header::(header, hash); } } - - /// Ensure that the origin is either root, or `PalletOwner`. - fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { - match origin.into() { - Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) - if Some(signer) == >::get().as_ref() => - Ok(()), - _ => Err(BadOrigin), - } - } - - /// Ensure that the pallet is in operational mode (not halted). - fn ensure_operational, I: 'static>() -> Result<(), Error> { - if >::get() { - Err(>::Halted) - } else { - Ok(()) - } - } } impl, I: 'static> Pallet { @@ -799,7 +764,10 @@ mod tests { initialize_substrate_bridge(); assert_ok!(Pallet::::set_operational(Origin::root(), false)); - assert_noop!(submit_finality_proof(1), Error::::Halted); + assert_noop!( + submit_finality_proof(1), + Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted) + ); assert_ok!(Pallet::::set_operational(Origin::root(), true)); assert_ok!(submit_finality_proof(1)); diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 0f287a9df47e1..78f44e75027b5 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -61,17 +61,16 @@ use bp_messages::{ OutboundMessageDetails, Parameter as MessagesParameter, UnrewardedRelayer, UnrewardedRelayersState, }; -use bp_runtime::{ChainId, Size}; +use bp_runtime::{ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode}; use frame_support::{ fail, traits::Get, weights::{Pays, PostDispatchInfo}, }; -use frame_system::RawOrigin; use num_traits::{SaturatingAdd, Zero}; use sp_core::H256; -use sp_runtime::traits::{BadOrigin, Convert}; +use sp_runtime::traits::Convert; use sp_std::{ cell::RefCell, cmp::PartialOrd, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, prelude::*, @@ -217,6 +216,18 @@ pub mod pallet { #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); + impl, I: 'static> OwnedBridgeModule for Pallet { + const LOG_TARGET: &'static str = "runtime::bridge-messages"; + const OPERATING_MODE_KEY: &'static str = "PalletOperatingMode"; + type OwnerStorage = PalletOwner; + type OperatingMode = OperatingMode; + type OperatingModeStorage = PalletOperatingMode; + + fn is_halted() -> bool { + Self::OperatingModeStorage::get() == OperatingMode::Halted + } + } + #[pallet::call] impl, I: 'static> Pallet { /// Change `PalletOwner`. @@ -224,18 +235,7 @@ pub mod pallet { /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { - ensure_owner_or_root::(origin)?; - match new_owner { - Some(new_owner) => { - PalletOwner::::put(&new_owner); - log::info!(target: "runtime::bridge-messages", "Setting pallet Owner to: {:?}", new_owner); - }, - None => { - PalletOwner::::kill(); - log::info!(target: "runtime::bridge-messages", "Removed Owner of pallet."); - }, - } - Ok(()) + >::set_owner(origin, new_owner) } /// Halt or resume all/some pallet operations. @@ -246,14 +246,7 @@ pub mod pallet { origin: OriginFor, operating_mode: OperatingMode, ) -> DispatchResult { - ensure_owner_or_root::(origin)?; - PalletOperatingMode::::put(operating_mode); - log::info!( - target: "runtime::bridge-messages", - "Setting messages pallet operating mode to {:?}.", - operating_mode, - ); - Ok(()) + >::set_operating_mode(origin, operating_mode) } /// Update pallet parameter. @@ -267,7 +260,7 @@ pub mod pallet { origin: OriginFor, parameter: T::Parameter, ) -> DispatchResult { - ensure_owner_or_root::(origin)?; + Self::ensure_owner_or_root(origin)?; parameter.save(); Self::deposit_event(Event::ParameterUpdated(parameter)); Ok(()) @@ -297,7 +290,7 @@ pub mod pallet { nonce: MessageNonce, additional_fee: T::OutboundMessageFee, ) -> DispatchResultWithPostInfo { - ensure_not_halted::()?; + Self::ensure_not_halted().map_err(Error::::BridgeModule)?; // if someone tries to pay for already-delivered message, we're rejecting this intention // (otherwise this additional fee will be locked forever in relayers fund) // @@ -368,7 +361,7 @@ pub mod pallet { messages_count: u32, dispatch_weight: Weight, ) -> DispatchResultWithPostInfo { - ensure_not_halted::()?; + Self::ensure_not_halted().map_err(Error::::BridgeModule)?; let relayer_id_at_this_chain = ensure_signed(origin)?; // reject transactions that are declaring too many messages @@ -512,7 +505,7 @@ pub mod pallet { proof: MessagesDeliveryProofOf, relayers_state: UnrewardedRelayersState, ) -> DispatchResultWithPostInfo { - ensure_not_halted::()?; + Self::ensure_not_halted().map_err(Error::::BridgeModule)?; // why do we need to know the weight of this (`receive_messages_delivery_proof`) call? // Because we may want to return some funds for messages that are not processed by the @@ -669,8 +662,8 @@ pub mod pallet { #[pallet::error] pub enum Error { - /// All pallet operations are halted. - Halted, + /// Pallet is not in Normal operating mode. + NotOperatingNormally, /// Message has been treated as invalid by chain verifier. MessageRejectedByChainVerifier, /// Message has been treated as invalid by lane verifier. @@ -695,6 +688,8 @@ pub mod pallet { /// The number of actually confirmed messages is going to be larger than the number of /// messages in the proof. This may mean that this or bridged chain storage is corrupted. TryingToConfirmMoreMessagesThanExpected, + /// Error generated by the `OwnedBridgeModule` trait. + BridgeModule(bp_runtime::OwnedBridgeModuleError), } /// Optional pallet owner. @@ -975,30 +970,10 @@ where relayers_rewards } -/// Ensure that the origin is either root, or `PalletOwner`. -fn ensure_owner_or_root, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { - match origin.into() { - Ok(RawOrigin::Root) => Ok(()), - Ok(RawOrigin::Signed(ref signer)) - if Some(signer) == Pallet::::module_owner().as_ref() => - Ok(()), - _ => Err(BadOrigin), - } -} - /// Ensure that the pallet is in normal operational mode. fn ensure_normal_operating_mode, I: 'static>() -> Result<(), Error> { if PalletOperatingMode::::get() != OperatingMode::Normal { - Err(Error::::Halted) - } else { - Ok(()) - } -} - -/// Ensure that the pallet is not halted. -fn ensure_not_halted, I: 'static>() -> Result<(), Error> { - if PalletOperatingMode::::get() == OperatingMode::Halted { - Err(Error::::Halted) + Err(Error::::NotOperatingNormally) } else { Ok(()) } @@ -1442,12 +1417,12 @@ mod tests { REGULAR_PAYLOAD, REGULAR_PAYLOAD.declared_weight, ), - Error::::Halted, + Error::::NotOperatingNormally, ); assert_noop!( Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1,), - Error::::Halted, + Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted), ); assert_noop!( @@ -1458,7 +1433,7 @@ mod tests { 1, REGULAR_PAYLOAD.declared_weight, ), - Error::::Halted, + Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted), ); assert_noop!( @@ -1480,7 +1455,7 @@ mod tests { last_delivered_nonce: 1, }, ), - Error::::Halted, + Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted), ); }); } @@ -1500,7 +1475,7 @@ mod tests { REGULAR_PAYLOAD, REGULAR_PAYLOAD.declared_weight, ), - Error::::Halted, + Error::::NotOperatingNormally, ); assert_ok!(Pallet::::increase_message_fee( diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 20208fd5fa0ba..691426aaf04a7 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -15,6 +15,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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 } @@ -30,6 +31,7 @@ default = ["std"] std = [ "codec/std", "frame-support/std", + "frame-system/std", "hash-db/std", "num-traits/std", "scale-info/std", diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index bd09a651c7204..ee5e6b5d24e99 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -18,11 +18,16 @@ #![cfg_attr(not(feature = "std"), no_std)] -use codec::Encode; -use frame_support::{RuntimeDebug, StorageHasher}; +use codec::{Decode, Encode, FullCodec}; +use frame_support::{ + log, pallet_prelude::DispatchResult, PalletError, RuntimeDebug, StorageHasher, StorageValue, +}; +use frame_system::RawOrigin; +use scale_info::TypeInfo; use sp_core::{hash::H256, storage::StorageKey}; use sp_io::hashing::blake2_256; -use sp_std::{convert::TryFrom, vec, vec::Vec}; +use sp_runtime::traits::BadOrigin; +use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, @@ -257,6 +262,79 @@ pub fn storage_value_key(pallet_prefix: &str, value_name: &str) -> StorageKey { StorageKey(final_key) } +/// Error generated by the `OwnedBridgeModule` trait. +#[derive(Encode, Decode, TypeInfo, PalletError)] +pub enum OwnedBridgeModuleError { + /// All pallet operations are halted. + Halted, +} + +/// Bridge module that has owner and operating mode +pub trait OwnedBridgeModule { + /// The target that will be used when publishing logs related to this module. + const LOG_TARGET: &'static str; + const OPERATING_MODE_KEY: &'static str; + + type OwnerStorage: StorageValue>; + type OperatingMode: Copy + Debug + FullCodec; + type OperatingModeStorage: StorageValue; + + /// Check if the module is halted. + fn is_halted() -> bool; + + /// Ensure that the origin is either root, or `PalletOwner`. + fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { + match origin.into() { + Ok(RawOrigin::Root) => Ok(()), + Ok(RawOrigin::Signed(ref signer)) + if Self::OwnerStorage::get().as_ref() == Some(signer) => + Ok(()), + _ => Err(BadOrigin), + } + } + + /// Ensure that the module is not halted. + fn ensure_not_halted() -> Result<(), OwnedBridgeModuleError> { + match Self::is_halted() { + true => Err(OwnedBridgeModuleError::Halted), + false => Ok(()), + } + } + + /// Change the owner of the module. + fn set_owner(origin: T::Origin, maybe_owner: Option) -> DispatchResult { + Self::ensure_owner_or_root(origin)?; + match maybe_owner { + Some(owner) => { + Self::OwnerStorage::put(&owner); + log::info!(target: Self::LOG_TARGET, "Setting pallet Owner to: {:?}", owner); + }, + None => { + Self::OwnerStorage::kill(); + log::info!(target: Self::LOG_TARGET, "Removed Owner of pallet."); + }, + } + + Ok(()) + } + + /// Halt or resume all/some module operations. + fn set_operating_mode( + origin: T::Origin, + operating_mode: Self::OperatingMode, + ) -> DispatchResult { + Self::ensure_owner_or_root(origin)?; + Self::OperatingModeStorage::put(operating_mode); + log::info!( + target: Self::LOG_TARGET, + "Setting operating mode ( {} = {:?}).", + Self::OPERATING_MODE_KEY, + operating_mode + ); + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 51edf857838e9..1af4f67a7caf5 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -97,12 +97,15 @@ impl TaggedAccount { pub fn tag(&self) -> String { match *self { TaggedAccount::Headers { ref bridged_chain, .. } => format!("{}Headers", bridged_chain), - TaggedAccount::Parachains { ref bridged_chain, .. } => - format!("{}Parachains", bridged_chain), - TaggedAccount::Messages { ref bridged_chain, .. } => - format!("{}Messages", bridged_chain), - TaggedAccount::MessagesPalletOwner { ref bridged_chain, .. } => - format!("{}MessagesPalletOwner", bridged_chain), + TaggedAccount::Parachains { ref bridged_chain, .. } => { + format!("{}Parachains", bridged_chain) + }, + TaggedAccount::Messages { ref bridged_chain, .. } => { + format!("{}Messages", bridged_chain) + }, + TaggedAccount::MessagesPalletOwner { ref bridged_chain, .. } => { + format!("{}MessagesPalletOwner", bridged_chain) + }, } } } From aa05093e7b1f2865294abefec2f7da4be3160d85 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 28 Jun 2022 17:39:07 +0300 Subject: [PATCH 0716/1210] Unify the operating mode for bridge pallets (#1483) Unify the operating mode for bridge pallets - define the OperationMode trait and BasicOperatingMode enum - use the OperationMode trait in all the bridge pallets - use BasicOperatingMode instead of IsHalted for the Grandpa pallet - use BasicOperatingMode as part of MessagesOperatingMode Signed-off-by: Serban Iorga --- modules/grandpa/src/benchmarking.rs | 3 +- modules/grandpa/src/lib.rs | 119 ++++++++++++------ modules/messages/src/lib.rs | 79 +++++++----- modules/parachains/src/lib.rs | 3 +- primitives/header-chain/src/lib.rs | 5 +- primitives/header-chain/src/storage_keys.rs | 14 +-- primitives/messages/src/lib.rs | 22 ++-- primitives/runtime/Cargo.toml | 2 + primitives/runtime/src/lib.rs | 44 +++++-- .../src/finality/engine.rs | 22 ++-- .../src/messages_source.rs | 9 +- 11 files changed, 218 insertions(+), 104 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index f12894bb5cbd2..655cd6eae74e5 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -41,6 +41,7 @@ use crate::*; +use bp_runtime::BasicOperatingMode; use bp_test_utils::{ accounts, make_justification_for_header, JustificationGeneratorParams, TEST_GRANDPA_ROUND, TEST_GRANDPA_SET_ID, @@ -84,7 +85,7 @@ fn prepare_benchmark_data, I: 'static>( header: Box::new(bp_test_utils::test_header(Zero::zero())), authority_list, set_id: TEST_GRANDPA_SET_ID, - is_halted: false, + operating_mode: BasicOperatingMode::Normal, }; bootstrap_bridge::(init_data); diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 726de9c507ed4..056aee406d8c0 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -71,6 +71,7 @@ pub type BridgedHeader = HeaderOf<>::BridgedChain>; #[frame_support::pallet] pub mod pallet { use super::*; + use bp_runtime::BasicOperatingMode; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -119,14 +120,9 @@ pub mod pallet { impl, I: 'static> OwnedBridgeModule for Pallet { const LOG_TARGET: &'static str = "runtime::bridge-grandpa"; - const OPERATING_MODE_KEY: &'static str = "IsHalted"; type OwnerStorage = PalletOwner; - type OperatingMode = bool; - type OperatingModeStorage = IsHalted; - - fn is_halted() -> bool { - Self::OperatingModeStorage::get() - } + type OperatingMode = BasicOperatingMode; + type OperatingModeStorage = PalletOperatingMode; } #[pallet::call] @@ -237,8 +233,11 @@ pub mod pallet { /// /// May only be called either by root, or by `PalletOwner`. #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operational(origin: OriginFor, operational: bool) -> DispatchResult { - Self::set_operating_mode(origin, !operational) + pub fn set_operating_mode( + origin: OriginFor, + operating_mode: BasicOperatingMode, + ) -> DispatchResult { + >::set_operating_mode(origin, operating_mode) } } @@ -293,9 +292,12 @@ pub mod pallet { pub type PalletOwner, I: 'static = ()> = StorageValue<_, T::AccountId, OptionQuery>; - /// If true, all pallet transactions are failed immediately. + /// The current operating mode of the pallet. + /// + /// Depending on the mode either all, or no transactions will be allowed. #[pallet::storage] - pub type IsHalted, I: 'static = ()> = StorageValue<_, bool, ValueQuery>; + pub type PalletOperatingMode, I: 'static = ()> = + StorageValue<_, BasicOperatingMode, ValueQuery>; #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { @@ -324,7 +326,7 @@ pub mod pallet { } else { // Since the bridge hasn't been initialized we shouldn't allow anyone to perform // transactions. - >::put(true); + >::put(BasicOperatingMode::Halted); } } } @@ -463,7 +465,8 @@ pub mod pallet { pub(crate) fn initialize_bridge, I: 'static>( init_params: super::InitializationData>, ) { - let super::InitializationData { header, authority_list, set_id, is_halted } = init_params; + let super::InitializationData { header, authority_list, set_id, operating_mode } = + init_params; let initial_hash = header.hash(); >::put(initial_hash); @@ -473,7 +476,7 @@ pub mod pallet { let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); >::put(authority_set); - >::put(is_halted); + >::put(operating_mode); } #[cfg(feature = "runtime-benchmarks")] @@ -576,7 +579,7 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader authority_list: sp_std::vec::Vec::new(), /* we don't verify any proofs in external * benchmarks */ set_id: 0, - is_halted: false, + operating_mode: bp_runtime::BasicOperatingMode::Normal, }); } @@ -584,6 +587,7 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader mod tests { use super::*; use crate::mock::{run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime}; + use bp_runtime::BasicOperatingMode; use bp_test_utils::{ authority_list, make_default_justification, make_justification_for_header, JustificationGeneratorParams, ALICE, BOB, @@ -611,7 +615,7 @@ mod tests { header: Box::new(genesis), authority_list: authority_list(), set_id: 1, - is_halted: false, + operating_mode: BasicOperatingMode::Normal, }; Pallet::::initialize(origin, init_data.clone()).map(|_| init_data) @@ -685,7 +689,7 @@ mod tests { CurrentAuthoritySet::::get().authorities, init_data.authority_list ); - assert!(!IsHalted::::get()); + assert_eq!(PalletOperatingMode::::get(), BasicOperatingMode::Normal); }) } @@ -707,29 +711,50 @@ mod tests { assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); assert_noop!( - Pallet::::set_operational(Origin::signed(2), false), + Pallet::::set_operating_mode( + Origin::signed(2), + BasicOperatingMode::Halted + ), DispatchError::BadOrigin, ); - assert_ok!(Pallet::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + BasicOperatingMode::Halted + )); assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); assert_noop!( - Pallet::::set_operational(Origin::signed(1), true), + Pallet::::set_operating_mode( + Origin::signed(1), + BasicOperatingMode::Normal + ), DispatchError::BadOrigin, ); assert_noop!( - Pallet::::set_operational(Origin::signed(2), true), + Pallet::::set_operating_mode( + Origin::signed(2), + BasicOperatingMode::Normal + ), DispatchError::BadOrigin, ); - assert_ok!(Pallet::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + BasicOperatingMode::Normal + )); }); } #[test] fn pallet_may_be_halted_by_root() { run_test(|| { - assert_ok!(Pallet::::set_operational(Origin::root(), false)); - assert_ok!(Pallet::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + BasicOperatingMode::Halted + )); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + BasicOperatingMode::Normal + )); }); } @@ -738,21 +763,39 @@ mod tests { run_test(|| { PalletOwner::::put(2); - assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); - assert_ok!(Pallet::::set_operational(Origin::signed(2), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(2), + BasicOperatingMode::Halted + )); + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(2), + BasicOperatingMode::Normal + )); assert_noop!( - Pallet::::set_operational(Origin::signed(1), false), + Pallet::::set_operating_mode( + Origin::signed(1), + BasicOperatingMode::Halted + ), DispatchError::BadOrigin, ); assert_noop!( - Pallet::::set_operational(Origin::signed(1), true), + Pallet::::set_operating_mode( + Origin::signed(1), + BasicOperatingMode::Normal + ), DispatchError::BadOrigin, ); - assert_ok!(Pallet::::set_operational(Origin::signed(2), false)); + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(2), + BasicOperatingMode::Halted + )); assert_noop!( - Pallet::::set_operational(Origin::signed(1), true), + Pallet::::set_operating_mode( + Origin::signed(1), + BasicOperatingMode::Normal + ), DispatchError::BadOrigin, ); }); @@ -763,13 +806,19 @@ mod tests { run_test(|| { initialize_substrate_bridge(); - assert_ok!(Pallet::::set_operational(Origin::root(), false)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + BasicOperatingMode::Halted + )); assert_noop!( submit_finality_proof(1), Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted) ); - assert_ok!(Pallet::::set_operational(Origin::root(), true)); + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + BasicOperatingMode::Normal + )); assert_ok!(submit_finality_proof(1)); }) } @@ -851,7 +900,7 @@ mod tests { header: Box::new(genesis), authority_list: invalid_authority_list, set_id: 1, - is_halted: false, + operating_mode: BasicOperatingMode::Normal, }; assert_ok!(Pallet::::initialize(Origin::root(), init_data)); @@ -1115,8 +1164,8 @@ mod tests { #[test] fn storage_keys_computed_properly() { assert_eq!( - IsHalted::::storage_value_final_key().to_vec(), - bp_header_chain::storage_keys::is_halted_key("Grandpa").0, + PalletOperatingMode::::storage_value_final_key().to_vec(), + bp_header_chain::storage_keys::pallet_operating_mode_key("Grandpa").0, ); assert_eq!( diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 78f44e75027b5..eed718477beb3 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -57,11 +57,11 @@ use bp_messages::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, - MessageData, MessageKey, MessageNonce, MessagePayload, OperatingMode, OutboundLaneData, + MessageData, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, Parameter as MessagesParameter, UnrewardedRelayer, UnrewardedRelayersState, }; -use bp_runtime::{ChainId, OwnedBridgeModule, Size}; +use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode}; use frame_support::{ fail, @@ -218,14 +218,9 @@ pub mod pallet { impl, I: 'static> OwnedBridgeModule for Pallet { const LOG_TARGET: &'static str = "runtime::bridge-messages"; - const OPERATING_MODE_KEY: &'static str = "PalletOperatingMode"; type OwnerStorage = PalletOwner; - type OperatingMode = OperatingMode; + type OperatingMode = MessagesOperatingMode; type OperatingModeStorage = PalletOperatingMode; - - fn is_halted() -> bool { - Self::OperatingModeStorage::get() == OperatingMode::Halted - } } #[pallet::call] @@ -244,7 +239,7 @@ pub mod pallet { #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operating_mode( origin: OriginFor, - operating_mode: OperatingMode, + operating_mode: MessagesOperatingMode, ) -> DispatchResult { >::set_operating_mode(origin, operating_mode) } @@ -708,7 +703,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn operating_mode)] pub type PalletOperatingMode, I: 'static = ()> = - StorageValue<_, OperatingMode, ValueQuery>; + StorageValue<_, MessagesOperatingMode, ValueQuery>; /// Map of lane id => inbound lane data. #[pallet::storage] @@ -728,7 +723,7 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { /// Initial pallet operating mode. - pub operating_mode: OperatingMode, + pub operating_mode: MessagesOperatingMode, /// Initial pallet owner. pub owner: Option, /// Dummy marker. @@ -972,11 +967,13 @@ where /// Ensure that the pallet is in normal operational mode. fn ensure_normal_operating_mode, I: 'static>() -> Result<(), Error> { - if PalletOperatingMode::::get() != OperatingMode::Normal { - Err(Error::::NotOperatingNormally) - } else { - Ok(()) + if PalletOperatingMode::::get() == + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) + { + return Ok(()) } + + Err(Error::::NotOperatingNormally) } /// Creates new inbound lane object, backed by runtime storage. @@ -1234,26 +1231,35 @@ mod tests { assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); assert_noop!( - Pallet::::set_operating_mode(Origin::signed(2), OperatingMode::Halted), + Pallet::::set_operating_mode( + Origin::signed(2), + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) + ), DispatchError::BadOrigin, ); assert_ok!(Pallet::::set_operating_mode( Origin::root(), - OperatingMode::Halted + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) )); assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); assert_noop!( - Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Normal), + Pallet::::set_operating_mode( + Origin::signed(1), + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) + ), DispatchError::BadOrigin, ); assert_noop!( - Pallet::::set_operating_mode(Origin::signed(2), OperatingMode::Normal), + Pallet::::set_operating_mode( + Origin::signed(2), + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) + ), DispatchError::BadOrigin, ); assert_ok!(Pallet::::set_operating_mode( Origin::root(), - OperatingMode::Normal + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) )); }); } @@ -1263,11 +1269,11 @@ mod tests { run_test(|| { assert_ok!(Pallet::::set_operating_mode( Origin::root(), - OperatingMode::Halted + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) )); assert_ok!(Pallet::::set_operating_mode( Origin::root(), - OperatingMode::Normal + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) )); }); } @@ -1279,28 +1285,37 @@ mod tests { assert_ok!(Pallet::::set_operating_mode( Origin::signed(2), - OperatingMode::Halted + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) )); assert_ok!(Pallet::::set_operating_mode( Origin::signed(2), - OperatingMode::Normal + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) )); assert_noop!( - Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Halted), + Pallet::::set_operating_mode( + Origin::signed(1), + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) + ), DispatchError::BadOrigin, ); assert_noop!( - Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Normal), + Pallet::::set_operating_mode( + Origin::signed(1), + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) + ), DispatchError::BadOrigin, ); assert_ok!(Pallet::::set_operating_mode( Origin::signed(2), - OperatingMode::Halted + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) )); assert_noop!( - Pallet::::set_operating_mode(Origin::signed(1), OperatingMode::Normal), + Pallet::::set_operating_mode( + Origin::signed(1), + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) + ), DispatchError::BadOrigin, ); }); @@ -1408,7 +1423,9 @@ mod tests { // send message first to be able to check that delivery_proof fails later send_regular_message(); - PalletOperatingMode::::put(OperatingMode::Halted); + PalletOperatingMode::::put(MessagesOperatingMode::Basic( + BasicOperatingMode::Halted, + )); assert_noop!( Pallet::::send_message( @@ -1466,7 +1483,9 @@ mod tests { // send message first to be able to check that delivery_proof fails later send_regular_message(); - PalletOperatingMode::::put(OperatingMode::RejectingOutboundMessages); + PalletOperatingMode::::put( + MessagesOperatingMode::RejectingOutboundMessages, + ); assert_noop!( Pallet::::send_message( diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index cf634e5b5ca5c..46be3866db12e 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -400,6 +400,7 @@ mod tests { run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; + use bp_runtime::BasicOperatingMode; use bp_test_utils::{authority_list, make_default_justification}; use frame_support::{ assert_noop, assert_ok, @@ -420,7 +421,7 @@ mod tests { header: Box::new(test_relay_header(0, state_root)), authority_list: authority_list(), set_id: 1, - is_halted: false, + operating_mode: BasicOperatingMode::Normal, }, ) .unwrap(); diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index ff8ee82f41e42..8ac7972621ce6 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,6 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +use bp_runtime::BasicOperatingMode; use codec::{Codec, Decode, Encode, EncodeLike}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; use scale_info::TypeInfo; @@ -66,8 +67,8 @@ pub struct InitializationData { pub authority_list: AuthorityList, /// The ID of the initial authority set. pub set_id: SetId, - /// Should the pallet block transaction immediately after initialization. - pub is_halted: bool, + /// Pallet operating mode. + pub operating_mode: BasicOperatingMode, } /// base trait for verifying transaction inclusion proofs. diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs index 14c40d69853b9..bb642b1817f75 100644 --- a/primitives/header-chain/src/storage_keys.rs +++ b/primitives/header-chain/src/storage_keys.rs @@ -17,18 +17,18 @@ //! Storage keys of bridge GRANDPA pallet. /// Name of the `IsHalted` storage value. -pub const IS_HALTED_VALUE_NAME: &str = "IsHalted"; +pub const PALLET_OPERATING_MODE_VALUE_NAME: &str = "PalletOperatingMode"; /// Name of the `BestFinalized` storage value. pub const BEST_FINALIZED_VALUE_NAME: &str = "BestFinalized"; use sp_core::storage::StorageKey; -/// Storage key of the `IsHalted` flag in the runtime storage. -pub fn is_halted_key(pallet_prefix: &str) -> StorageKey { +/// Storage key of the `PalletOperatingMode` variable in the runtime storage. +pub fn pallet_operating_mode_key(pallet_prefix: &str) -> StorageKey { StorageKey( bp_runtime::storage_value_final_key( pallet_prefix.as_bytes(), - IS_HALTED_VALUE_NAME.as_bytes(), + PALLET_OPERATING_MODE_VALUE_NAME.as_bytes(), ) .to_vec(), ) @@ -51,13 +51,13 @@ mod tests { use hex_literal::hex; #[test] - fn is_halted_key_computed_properly() { + fn pallet_operating_mode_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // compatibility with previous pallet. - let storage_key = is_halted_key("BridgeGrandpa").0; + let storage_key = pallet_operating_mode_key("BridgeGrandpa").0; assert_eq!( storage_key, - hex!("0b06f475eddb98cf933a12262e0388de9611a984bbd04e2fd39f97bbc006115f").to_vec(), + hex!("0b06f475eddb98cf933a12262e0388de0f4cf0917788d791142ff6c1f216e7b3").to_vec(), "Unexpected storage key: {}", hex::encode(&storage_key), ); diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 8d51a6fa86462..455caad729b70 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -32,14 +32,15 @@ pub mod storage_keys; pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in related crates. +use bp_runtime::{BasicOperatingMode, OperatingMode}; pub use frame_support::weights::Weight; /// Messages pallet operating mode. #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] -pub enum OperatingMode { - /// Normal mode, when all operations are allowed. - Normal, +pub enum MessagesOperatingMode { + /// Basic operating mode (Normal/Halted) + Basic(BasicOperatingMode), /// The pallet is not accepting outbound messages. Inbound messages and receiving proofs /// are still accepted. /// @@ -48,13 +49,20 @@ pub enum OperatingMode { /// queued messages to the bridged chain. Once upgrade is completed, the mode may be switched /// back to `Normal`. RejectingOutboundMessages, - /// The pallet is halted. All operations (except operating mode change) are prohibited. - Halted, } -impl Default for OperatingMode { +impl Default for MessagesOperatingMode { fn default() -> Self { - OperatingMode::Normal + MessagesOperatingMode::Basic(BasicOperatingMode::Normal) + } +} + +impl OperatingMode for MessagesOperatingMode { + fn is_halted(&self) -> bool { + match self { + Self::Basic(operating_mode) => operating_mode.is_halted(), + _ => false, + } } } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 691426aaf04a7..94dd12175d9d6 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -11,6 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features = hash-db = { version = "0.15.2", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Dependencies @@ -35,6 +36,7 @@ std = [ "hash-db/std", "num-traits/std", "scale-info/std", + "serde", "sp-core/std", "sp-io/std", "sp-runtime/std", diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index ee5e6b5d24e99..cba89df726679 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -269,18 +269,47 @@ pub enum OwnedBridgeModuleError { Halted, } +/// Operating mode for a bridge module. +pub trait OperatingMode: Send + Copy + Debug + FullCodec { + // Returns true if the bridge module is halted. + fn is_halted(&self) -> bool; +} + +/// Basic operating modes for a bridges module (Normal/Halted). +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub enum BasicOperatingMode { + /// Normal mode, when all operations are allowed. + Normal, + /// The pallet is halted. All operations (except operating mode change) are prohibited. + Halted, +} + +impl Default for BasicOperatingMode { + fn default() -> Self { + Self::Normal + } +} + +impl OperatingMode for BasicOperatingMode { + fn is_halted(&self) -> bool { + *self == BasicOperatingMode::Halted + } +} + /// Bridge module that has owner and operating mode pub trait OwnedBridgeModule { /// The target that will be used when publishing logs related to this module. const LOG_TARGET: &'static str; - const OPERATING_MODE_KEY: &'static str; type OwnerStorage: StorageValue>; - type OperatingMode: Copy + Debug + FullCodec; - type OperatingModeStorage: StorageValue; + type OperatingMode: OperatingMode; + type OperatingModeStorage: StorageValue; /// Check if the module is halted. - fn is_halted() -> bool; + fn is_halted() -> bool { + Self::OperatingModeStorage::get().is_halted() + } /// Ensure that the origin is either root, or `PalletOwner`. fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { @@ -325,12 +354,7 @@ pub trait OwnedBridgeModule { ) -> DispatchResult { Self::ensure_owner_or_root(origin)?; Self::OperatingModeStorage::put(operating_mode); - log::info!( - target: Self::LOG_TARGET, - "Setting operating mode ( {} = {:?}).", - Self::OPERATING_MODE_KEY, - operating_mode - ); + log::info!(target: Self::LOG_TARGET, "Setting operating mode to {:?}.", operating_mode); Ok(()) } } diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 0f2cc87660bfc..b2b72e4f2c39f 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -23,6 +23,7 @@ use bp_header_chain::{ justification::{verify_justification, GrandpaJustification}, FinalityProof, }; +use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; @@ -44,10 +45,12 @@ pub trait Engine: Send { type FinalityProof: FinalityProof> + Decode + Encode; /// Type of bridge pallet initialization data. type InitializationData: std::fmt::Debug + Send + Sync + 'static; + /// Type of bridge pallet operating mode. + type OperatingMode: OperatingMode + 'static; - /// Returns storage key at the bridged (target) chain that corresponds to the `bool` value, - /// which is true when the bridge pallet is halted. - fn is_halted_key() -> StorageKey; + /// Returns storage key at the bridged (target) chain that corresponds to the variable + /// that holds the operating mode of the pallet. + fn pallet_operating_mode_key() -> StorageKey; /// Returns storage at the bridged (target) chain that corresponds to some value that is /// missing from the storage until bridge pallet is initialized. /// @@ -74,7 +77,11 @@ pub trait Engine: Send { async fn is_halted( target_client: &Client, ) -> Result { - Ok(target_client.storage_value(Self::is_halted_key(), None).await?.unwrap_or(false)) + Ok(target_client + .storage_value::(Self::pallet_operating_mode_key(), None) + .await? + .map(|operating_mode| operating_mode.is_halted()) + .unwrap_or(false)) } } @@ -112,9 +119,10 @@ impl Engine for Grandpa { const ID: ConsensusEngineId = sp_finality_grandpa::GRANDPA_ENGINE_ID; type FinalityProof = GrandpaJustification>; type InitializationData = bp_header_chain::InitializationData; + type OperatingMode = BasicOperatingMode; - fn is_halted_key() -> StorageKey { - bp_header_chain::storage_keys::is_halted_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + fn pallet_operating_mode_key() -> StorageKey { + bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } fn is_initialized_key() -> StorageKey { @@ -237,7 +245,7 @@ impl Engine for Grandpa { } else { initial_authorities_set_id }, - is_halted: false, + operating_mode: BasicOperatingMode::Normal, }) } } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 0e21ef66eda3b..5a6b6554e4bae 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -31,10 +31,10 @@ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::{operating_mode_key, outbound_lane_data_key}, - InboundMessageDetails, LaneId, MessageData, MessageNonce, OperatingMode, OutboundLaneData, - OutboundMessageDetails, UnrewardedRelayersState, + InboundMessageDetails, LaneId, MessageData, MessageNonce, MessagesOperatingMode, + OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, }; -use bp_runtime::messages::DispatchFeePayment; +use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -420,7 +420,8 @@ where let operating_mode = client .storage_value(operating_mode_key(WithChain::WITH_CHAIN_MESSAGES_PALLET_NAME), None) .await?; - let is_halted = operating_mode == Some(OperatingMode::Halted); + let is_halted = + operating_mode == Some(MessagesOperatingMode::Basic(BasicOperatingMode::Halted)); if is_halted { Err(SubstrateError::BridgePalletIsHalted) } else { From 58be93a0d4792fe308d04c511c6ab89366472300 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 29 Jun 2022 15:58:19 +0300 Subject: [PATCH 0717/1210] Parachain loop metrics (#1484) * parachain loop metrics * some fixes * mini refactoring * add tests --- modules/parachains/src/lib.rs | 24 ++++++ primitives/parachains/src/lib.rs | 18 ++++- primitives/runtime/src/lib.rs | 32 ++++++++ .../src/parachains/source.rs | 22 +++++- .../src/parachains/target.rs | 51 +++++++++++-- relays/parachains/src/parachains_loop.rs | 29 ++++++-- .../parachains/src/parachains_loop_metrics.rs | 74 +++++++++++++++++-- 7 files changed, 228 insertions(+), 22 deletions(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 46be3866db12e..dc5ad5074b196 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -405,6 +405,7 @@ mod tests { use frame_support::{ assert_noop, assert_ok, dispatch::DispatchResultWithPostInfo, + storage::generator::{StorageDoubleMap, StorageMap}, traits::{Get, OnInitialize}, weights::Weight, }; @@ -810,4 +811,27 @@ mod tests { ); }); } + + #[test] + fn storage_keys_computed_properly() { + assert_eq!( + BestParaHeads::::storage_map_final_key(ParaId(42)).to_vec(), + bp_parachains::best_parachain_head_hash_storage_key_at_target("Parachains", ParaId(42)) + .0, + ); + + assert_eq!( + ImportedParaHeads::::storage_double_map_final_key( + ParaId(42), + ParaHash::from([21u8; 32]) + ) + .to_vec(), + bp_parachains::imported_parachain_head_storage_key_at_target( + "Parachains", + ParaId(42), + ParaHash::from([21u8; 32]) + ) + .0, + ); + } } diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index 0ed4e11480dad..791d2bd47f11f 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -56,7 +56,7 @@ pub fn parachain_head_storage_key_at_source( /// Returns runtime storage key of best known parachain head at the target chain. /// /// The head is stored by the `pallet-bridge-parachains` pallet in the `BestParaHeads` map. -pub fn parachain_head_storage_key_at_target( +pub fn best_parachain_head_hash_storage_key_at_target( bridge_parachains_pallet_name: &str, para_id: ParaId, ) -> StorageKey { @@ -66,3 +66,19 @@ pub fn parachain_head_storage_key_at_target( ¶_id.encode(), ) } + +/// Returns runtime storage key of the parachain head with given hash at the target chain. +/// +/// The head is stored by the `pallet-bridge-parachains` pallet in the `ImportedParaHeads` map. +pub fn imported_parachain_head_storage_key_at_target( + bridge_parachains_pallet_name: &str, + para_id: ParaId, + head_hash: ParaHash, +) -> StorageKey { + bp_runtime::storage_double_map_final_key::( + bridge_parachains_pallet_name, + "ImportedParaHeads", + ¶_id.encode(), + &head_hash.encode(), + ) +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index cba89df726679..4b69bbdb68828 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -236,6 +236,38 @@ pub fn storage_map_final_key( StorageKey(final_key) } +/// This is a copy of the +/// `frame_support::storage::generator::StorageDoubleMap::storage_double_map_final_key` for maps +/// based on selected hashers. +/// +/// We're using it because to call `storage_double_map_final_key` directly, we need access to the +/// runtime and pallet instance, which (sometimes) is impossible. +pub fn storage_double_map_final_key( + pallet_prefix: &str, + map_name: &str, + key1: &[u8], + key2: &[u8], +) -> StorageKey { + let key1_hashed = H1::hash(key1); + let key2_hashed = H2::hash(key2); + 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() + + key1_hashed.as_ref().len() + + key2_hashed.as_ref().len(), + ); + + final_key.extend_from_slice(&pallet_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key1_hashed.as_ref()); + final_key.extend_from_slice(key2_hashed.as_ref()); + + StorageKey(final_key) +} + /// This is how a storage key of storage parameter (`parameter_types! { storage Param: bool = false; /// }`) is computed. /// diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index dd239366719fc..c613387e7a258 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -23,7 +23,10 @@ use async_trait::async_trait; use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use codec::Decode; -use parachains_relay::parachains_loop::{ParaHashAtSource, SourceClient}; +use parachains_relay::{ + parachains_loop::{ParaHashAtSource, SourceClient}, + parachains_loop_metrics::ParachainsLoopMetrics, +}; use relay_substrate_client::{ Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, RelayChain, }; @@ -100,6 +103,7 @@ where async fn parachain_head( &self, at_block: HeaderIdOf, + metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result { // we don't need to support many parachains now @@ -111,9 +115,11 @@ where ))) } - Ok(match self.on_chain_parachain_header(at_block, para_id).await? { + let mut para_header_number_at_source = None; + let para_hash_at_source = match self.on_chain_parachain_header(at_block, para_id).await? { Some(parachain_header) => { let mut parachain_head = ParaHashAtSource::Some(parachain_header.hash()); + para_header_number_at_source = Some(*parachain_header.number()); // never return head that is larger than requested. This way we'll never sync // headers past `maximal_header_id` if let Some(ref maximal_header_id) = self.maximal_header_id { @@ -125,11 +131,13 @@ where // we don't want this header yet => let's report previously requested // header parachain_head = ParaHashAtSource::Some(maximal_header_id.1); + para_header_number_at_source = Some(maximal_header_id.0); }, Some(_) => (), None => { // on-demand relay has not yet asked us to sync anything let's do that parachain_head = ParaHashAtSource::Unavailable; + para_header_number_at_source = None; }, } } @@ -137,7 +145,15 @@ where parachain_head }, None => ParaHashAtSource::None, - }) + }; + + if let (Some(metrics), Some(para_header_number_at_source)) = + (metrics, para_header_number_at_source) + { + metrics.update_best_parachain_block_at_source(para_id, para_header_number_at_source); + } + + Ok(para_hash_at_source) } async fn prove_parachain_heads( diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 67d82e1f7075f..ca30629198b5b 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -24,13 +24,19 @@ use crate::{ }; use async_trait::async_trait; -use bp_parachains::{parachain_head_storage_key_at_target, BestParaHeadHash}; -use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; +use bp_parachains::{ + best_parachain_head_hash_storage_key_at_target, imported_parachain_head_storage_key_at_target, + BestParaHeadHash, +}; +use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId}; use codec::{Decode, Encode}; -use parachains_relay::parachains_loop::TargetClient; +use parachains_relay::{ + parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics, +}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, RelayChain, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, + HeaderIdOf, HeaderOf, RelayChain, SignParam, TransactionEra, TransactionSignScheme, + UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -115,15 +121,46 @@ where async fn parachain_head( &self, at_block: HeaderIdOf, + metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result, Self::Error> { - let storage_key = parachain_head_storage_key_at_target( + let best_para_head_hash_key = best_parachain_head_hash_storage_key_at_target( P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, para_id, ); - let para_head = self.client.storage_value(storage_key, Some(at_block.1)).await?; + let best_para_head_hash: Option = + self.client.storage_value(best_para_head_hash_key, Some(at_block.1)).await?; + if let (Some(metrics), &Some(ref best_para_head_hash)) = (metrics, &best_para_head_hash) { + let imported_para_head_key = imported_parachain_head_storage_key_at_target( + P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, + para_id, + best_para_head_hash.head_hash, + ); + let imported_para_header = self + .client + .storage_value::(imported_para_head_key, Some(at_block.1)) + .await? + .and_then(|h| match HeaderOf::::decode(&mut &h.0[..]) { + Ok(header) => Some(header), + Err(e) => { + log::error!( + target: "bridge-metrics", + "Failed to decode {} parachain header at {}: {:?}. Metric will have obsolete value", + P::SourceParachain::NAME, + P::TargetChain::NAME, + e, + ); + + None + }, + }); + if let Some(imported_para_header) = imported_para_header { + metrics + .update_best_parachain_block_at_target(para_id, *imported_para_header.number()); + } + } - Ok(para_head) + Ok(best_para_head_hash) } async fn submit_parachain_heads_proof( diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index b1dd74146281c..60627d23e0b15 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -76,9 +76,13 @@ pub trait SourceClient: RelayClient { async fn ensure_synced(&self) -> Result; /// Get parachain head hash at given block. + /// + /// The implementation may call `ParachainsLoopMetrics::update_best_parachain_block_at_source` + /// on provided `metrics` object to update corresponding metric value. async fn parachain_head( &self, at_block: HeaderIdOf, + metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result; @@ -103,9 +107,13 @@ pub trait TargetClient: RelayClient { ) -> Result, Self::Error>; /// Get parachain head hash at given block. + /// + /// The implementation may call `ParachainsLoopMetrics::update_best_parachain_block_at_target` + /// on provided `metrics` object to update corresponding metric value. async fn parachain_head( &self, at_block: HeaderIdOf, + metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result, Self::Error>; @@ -158,7 +166,7 @@ async fn run_until_connection_lost( source_client: impl SourceClient

, target_client: impl TargetClient

, sync_params: ParachainSyncParams, - _metrics: Option, + metrics: Option, exit_signal: impl Future + Send, ) -> Result<(), FailedClient> where @@ -213,9 +221,13 @@ where log::warn!(target: "bridge", "Failed to read best {} block: {:?}", P::SourceChain::NAME, e); FailedClient::Target })?; - let heads_at_target = - read_heads_at_target(&target_client, &best_target_block, &sync_params.parachains) - .await?; + let heads_at_target = read_heads_at_target( + &target_client, + metrics.as_ref(), + &best_target_block, + &sync_params.parachains, + ) + .await?; tx_tracker = tx_tracker.take().and_then(|tx_tracker| tx_tracker.update(&heads_at_target)); if tx_tracker.is_some() { continue @@ -238,6 +250,7 @@ where })?; let heads_at_source = read_heads_at_source( &source_client, + metrics.as_ref(), &best_finalized_relay_block, &sync_params.parachains, ) @@ -398,12 +411,13 @@ fn is_update_required(sync_params: &ParachainSyncParams, updated_ids: &[ParaId]) /// Guarantees that the returning map will have an entry for every parachain from `parachains`. async fn read_heads_at_source( source_client: &impl SourceClient

, + metrics: Option<&ParachainsLoopMetrics>, at_relay_block: &HeaderIdOf, parachains: &[ParaId], ) -> Result, FailedClient> { let mut para_head_hashes = BTreeMap::new(); for para in parachains { - let para_head = source_client.parachain_head(*at_relay_block, *para).await; + let para_head = source_client.parachain_head(*at_relay_block, metrics, *para).await; match para_head { Ok(para_head) => { para_head_hashes.insert(*para, para_head); @@ -428,12 +442,13 @@ async fn read_heads_at_source( /// Guarantees that the returning map will have an entry for every parachain from `parachains`. async fn read_heads_at_target( target_client: &impl TargetClient

, + metrics: Option<&ParachainsLoopMetrics>, at_block: &HeaderIdOf, parachains: &[ParaId], ) -> Result>, FailedClient> { let mut para_best_head_hashes = BTreeMap::new(); for para in parachains { - let para_best_head = target_client.parachain_head(*at_block, *para).await; + let para_best_head = target_client.parachain_head(*at_block, metrics, *para).await; match para_best_head { Ok(para_best_head) => { para_best_head_hashes.insert(*para, para_best_head); @@ -638,6 +653,7 @@ mod tests { async fn parachain_head( &self, _at_block: HeaderIdOf, + _metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result { match self.data.lock().await.source_heads.get(¶_id.0).cloned() { @@ -684,6 +700,7 @@ mod tests { async fn parachain_head( &self, _at_block: HeaderIdOf, + _metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result, TestError> { self.data.lock().await.target_heads.get(¶_id.0).cloned().transpose() diff --git a/relays/parachains/src/parachains_loop_metrics.rs b/relays/parachains/src/parachains_loop_metrics.rs index a0a99f5c332ab..ff8bace274439 100644 --- a/relays/parachains/src/parachains_loop_metrics.rs +++ b/relays/parachains/src/parachains_loop_metrics.rs @@ -14,21 +14,85 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use relay_utils::metrics::{Metric, PrometheusError, Registry}; +use bp_polkadot_core::parachains::ParaId; +use relay_utils::metrics::{ + metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, +}; /// Parachains sync metrics. #[derive(Clone)] -pub struct ParachainsLoopMetrics; +pub struct ParachainsLoopMetrics { + /// Best parachains header numbers at the source. + best_source_block_numbers: GaugeVec, + /// Best parachains header numbers at the target. + best_target_block_numbers: GaugeVec, +} impl ParachainsLoopMetrics { /// Create and register parachains loop metrics. - pub fn new(_prefix: Option<&str>) -> Result { - Ok(ParachainsLoopMetrics) + pub fn new(prefix: Option<&str>) -> Result { + Ok(ParachainsLoopMetrics { + best_source_block_numbers: GaugeVec::new( + Opts::new( + metric_name(prefix, "best_parachain_block_number_at_source"), + "Best parachain block numbers at the source relay chain".to_string(), + ), + &["parachain"], + )?, + best_target_block_numbers: GaugeVec::new( + Opts::new( + metric_name(prefix, "best_parachain_block_number_at_target"), + "Best parachain block numbers at the target chain".to_string(), + ), + &["parachain"], + )?, + }) + } + + /// Update best block number at source. + pub fn update_best_parachain_block_at_source>( + &self, + parachain: ParaId, + block_number: Number, + ) { + let block_number = block_number.into(); + let label = parachain_label(¶chain); + log::trace!( + target: "bridge-metrics", + "Updated value of metric 'best_parachain_block_number_at_source[{}]': {:?}", + label, + block_number, + ); + self.best_source_block_numbers.with_label_values(&[&label]).set(block_number); + } + + /// Update best block number at target. + pub fn update_best_parachain_block_at_target>( + &self, + parachain: ParaId, + block_number: Number, + ) { + let block_number = block_number.into(); + let label = parachain_label(¶chain); + log::trace!( + target: "bridge-metrics", + "Updated value of metric 'best_parachain_block_number_at_target[{}]': {:?}", + label, + block_number, + ); + self.best_target_block_numbers.with_label_values(&[&label]).set(block_number); } } impl Metric for ParachainsLoopMetrics { - fn register(&self, _registry: &Registry) -> Result<(), PrometheusError> { + fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { + register(self.best_source_block_numbers.clone(), registry)?; + register(self.best_target_block_numbers.clone(), registry)?; Ok(()) } } + +/// Return metric label for the parachain. +fn parachain_label(parachain: &ParaId) -> String { + format!("para_{}", parachain.0) +} From 8ed984b9b4fe9554cd0bf583b737919542a7fc58 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 29 Jun 2022 15:59:50 +0300 Subject: [PATCH 0718/1210] Sync Westmint to Millau (#1482) * sync Westmint to Millau * "Westend parachains at Millau" dashboard --- bin/millau/node/src/chain_spec.rs | 4 ++ bin/millau/runtime/src/lib.rs | 29 ++++++++++- primitives/chain-westend/src/lib.rs | 20 +++++++ relays/bin-substrate/src/chains/mod.rs | 1 + .../chains/westend_parachains_to_millau.rs | 52 +++++++++++++++++++ .../bin-substrate/src/cli/relay_parachains.rs | 6 +++ relays/client-westend/src/lib.rs | 50 +++++++++++++++++- 7 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 relays/bin-substrate/src/chains/westend_parachains_to_millau.rs diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 3204173598a07..648e51e533ad2 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -144,6 +144,8 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Harry"), get_account_id_from_seed::("Iden"), get_account_id_from_seed::("Ken"), + get_account_id_from_seed::("Leon"), + get_account_id_from_seed::("Mary"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), @@ -154,6 +156,8 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Harry//stash"), get_account_id_from_seed::("Iden//stash"), get_account_id_from_seed::("Ken//stash"), + get_account_id_from_seed::("Leon//stash"), + get_account_id_from_seed::("Mary//stash"), get_account_id_from_seed::("RialtoMessagesOwner"), get_account_id_from_seed::("RialtoParachainMessagesOwner"), pallet_bridge_messages::relayer_fund_account_id::< diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index c5c002c472179..fecbf4f99073f 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -506,9 +506,10 @@ impl pallet_bridge_messages::Config for Run parameter_types! { pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; + pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME; } -/// Instance of the with-Rialto parachains token swap pallet. +/// Instance of the with-Rialto parachains pallet. pub type WithRialtoParachainsInstance = (); impl pallet_bridge_parachains::Config for Runtime { @@ -519,6 +520,17 @@ impl pallet_bridge_parachains::Config for Runtime type HeadsToKeep = HeadersToKeep; } +/// Instance of the with-Westend parachains pallet. +pub type WithWestendParachainsInstance = pallet_bridge_parachains::Instance1; + +impl pallet_bridge_parachains::Config for Runtime { + type WeightInfo = pallet_bridge_parachains::weights::MillauWeight; + type BridgesGrandpaPalletInstance = WestendGrandpaInstance; + type ParasPalletName = WestendParasPalletName; + type TrackedParachains = frame_support::traits::Everything; + type HeadsToKeep = HeadersToKeep; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -552,6 +564,7 @@ construct_runtime!( // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, + BridgeWestendParachains: pallet_bridge_parachains::::{Pallet, Call, Storage}, // RialtoParachain bridge modules. BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage}, @@ -806,6 +819,20 @@ impl_runtime_apis! { } } + impl bp_westend::WestmintFinalityApi for Runtime { + fn best_finalized() -> Option<(bp_westend::BlockNumber, bp_westend::Hash)> { + // the parachains finality pallet is never decoding parachain heads, so it is + // only done in the integration code + use bp_westend::WESTMINT_PARACHAIN_ID; + let encoded_head = pallet_bridge_parachains::Pallet::< + Runtime, + WithWestendParachainsInstance, + >::best_parachain_head(WESTMINT_PARACHAIN_ID.into())?; + let head = bp_westend::Header::decode(&mut &encoded_head.0[..]).ok()?; + Some((*head.number(), head.hash())) + } + } + impl bp_rialto_parachain::RialtoParachainFinalityApi for Runtime { fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> { // the parachains finality pallet is never decoding parachain heads, so it is diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 539cf69eb73a5..0dc4ccc65aea1 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -86,8 +86,13 @@ pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) - AccountIdConverter::convert(encoded_id) } +/// Name of the parachains pallet at the Westend runtime. +pub const PARAS_PALLET_NAME: &str = "Paras"; + /// Name of the With-Westend GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; +/// Name of the With-Westend parachains bridge pallet instance that is deployed at bridged chains. +pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains"; /// Name of the `WestendFinalityApi::best_finalized` runtime method. pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; @@ -108,4 +113,19 @@ sp_api::decl_runtime_apis! { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> Option<(BlockNumber, Hash)>; } + + /// API for querying information about the finalized Westmint headers. + /// + /// This API is implemented by runtimes that are bridging with the Westmint chain, not the + /// Westmint runtime itself. + pub trait WestmintFinalityApi { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> Option<(BlockNumber, Hash)>; + } } + +/// Identifier of Westmint parachain at the Westend relay chain. +pub const WESTMINT_PARACHAIN_ID: u32 = 2000; + +/// Name of the `WestmintFinalityApi::best_finalized` runtime method. +pub const BEST_FINALIZED_WESTMINT_HEADER_METHOD: &str = "WestmintFinalityApi_best_finalized"; diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index ccc1be434f579..02e17c361d493 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -31,6 +31,7 @@ pub mod rialto_parachains_to_millau; pub mod rococo_headers_to_wococo; pub mod rococo_messages_to_wococo; pub mod westend_headers_to_millau; +pub mod westend_parachains_to_millau; pub mod wococo_headers_to_rococo; pub mod wococo_messages_to_rococo; diff --git a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs new file mode 100644 index 0000000000000..3a508ae49b6ed --- /dev/null +++ b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs @@ -0,0 +1,52 @@ +// 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 . + +//! Westend-to-Millau parachains sync entrypoint. + +use parachains_relay::ParachainsPipeline; +use relay_millau_client::Millau; +use relay_westend_client::{Westend, Westmint}; +use substrate_relay_helper::parachains::{ + DirectSubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// Westend-to-Millau parachains sync description. +#[derive(Clone, Debug)] +pub struct WestendParachainsToMillau; + +impl ParachainsPipeline for WestendParachainsToMillau { + type SourceChain = Westend; + type TargetChain = Millau; +} + +impl SubstrateParachainsPipeline for WestendParachainsToMillau { + type SourceParachain = Westmint; + type SourceRelayChain = Westend; + type TargetChain = Millau; + + type SubmitParachainHeadsCallBuilder = WestendParachainsToMillauSubmitParachainHeadsCallBuilder; + type TransactionSignScheme = Millau; + + const SOURCE_PARACHAIN_PARA_ID: u32 = bp_westend::WESTMINT_PARACHAIN_ID; +} + +/// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. +pub type WestendParachainsToMillauSubmitParachainHeadsCallBuilder = + DirectSubmitParachainHeadsCallBuilder< + WestendParachainsToMillau, + millau_runtime::Runtime, + millau_runtime::WithWestendParachainsInstance, + >; diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 8667ff741660d..4714f1cc5a998 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -49,6 +49,7 @@ pub struct RelayParachains { #[strum(serialize_all = "kebab_case")] pub enum RelayParachainsBridge { RialtoToMillau, + WestendToMillau, } macro_rules! select_bridge { @@ -57,6 +58,11 @@ macro_rules! select_bridge { RelayParachainsBridge::RialtoToMillau => { use crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau as Pipeline; + $generic + }, + RelayParachainsBridge::WestendToMillau => { + use crate::chains::westend_parachains_to_millau::WestendParachainsToMillau as Pipeline; + $generic }, } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index caf0c010c56ae..cd2e3caab6182 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Westend chain. use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, RelayChain}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -65,6 +65,12 @@ impl Chain for Westend { type WeightToFee = bp_westend::WeightToFee; } +impl RelayChain for Westend { + const PARAS_PALLET_NAME: &'static str = bp_westend::PARAS_PALLET_NAME; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = + bp_westend::WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME; +} + impl ChainWithGrandpa for Westend { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_westend::WITH_WESTEND_GRANDPA_PALLET_NAME; @@ -75,3 +81,45 @@ impl ChainWithBalances for Westend { StorageKey(bp_westend::account_info_storage_key(account_id)) } } + +/// Westmint parachain definition +#[derive(Debug, Clone, Copy)] +pub struct Westmint; + +// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend +// primitives here. +impl ChainBase for Westmint { + type BlockNumber = bp_westend::BlockNumber; + type Hash = bp_westend::Hash; + type Hasher = bp_westend::Hasher; + type Header = bp_westend::Header; + + type AccountId = bp_westend::AccountId; + type Balance = bp_westend::Balance; + type Index = bp_westend::Nonce; + type Signature = bp_westend::Signature; + + fn max_extrinsic_size() -> u32 { + bp_westend::Westend::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_westend::Westend::max_extrinsic_weight() + } +} + +// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend +// primitives here. +impl Chain for Westmint { + const NAME: &'static str = "Westmint"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_westend::BEST_FINALIZED_WESTMINT_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; + const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; + + type SignedBlock = bp_westend::SignedBlock; + type Call = bp_westend::Call; + type WeightToFee = bp_westend::WeightToFee; +} From dd71e7fa06865fd0d0c65ad59cde9c3a632b1e7f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 29 Jun 2022 11:49:03 +0300 Subject: [PATCH 0719/1210] Define const LOG_TARGET for bridge pallets Signed-off-by: Serban Iorga --- modules/grandpa/src/lib.rs | 27 +++++++++++++++------- modules/messages/src/lib.rs | 43 +++++++++++++++++------------------ modules/parachains/src/lib.rs | 17 ++++++++------ 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 056aee406d8c0..c0b4d9d3eefbe 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -59,6 +59,9 @@ pub mod benchmarking; pub use pallet::*; pub use weights::WeightInfo; +/// The target that will be used when publishing logs related to this pallet. +const LOG_TARGET: &str = "runtime::bridge-grandpa"; + /// Block number of the bridged chain. pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; /// Block hash of the bridged chain. @@ -119,7 +122,7 @@ pub mod pallet { } impl, I: 'static> OwnedBridgeModule for Pallet { - const LOG_TARGET: &'static str = "runtime::bridge-grandpa"; + const LOG_TARGET: &'static str = LOG_TARGET; type OwnerStorage = PalletOwner; type OperatingMode = BasicOperatingMode; type OperatingModeStorage = PalletOperatingMode; @@ -149,7 +152,11 @@ pub mod pallet { ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); let (hash, number) = (finality_target.hash(), finality_target.number()); - log::trace!(target: "runtime::bridge-grandpa", "Going to try and finalize header {:?}", finality_target); + log::trace!( + target: LOG_TARGET, + "Going to try and finalize header {:?}", + finality_target + ); let best_finalized = BestFinalized::::get(); let best_finalized = @@ -158,7 +165,7 @@ pub mod pallet { Some(best_finalized) => best_finalized, None => { log::error!( - target: "runtime::bridge-grandpa", + target: LOG_TARGET, "Cannot finalize header {:?} because pallet is not yet initialized", finality_target, ); @@ -179,7 +186,11 @@ pub mod pallet { try_enact_authority_change::(&finality_target, set_id)?; >::mutate(|count| *count += 1); insert_header::(*finality_target, hash); - log::info!(target: "runtime::bridge-grandpa", "Successfully imported finalized header with hash {:?}!", hash); + log::info!( + target: LOG_TARGET, + "Successfully imported finalized header with hash {:?}!", + hash + ); // mandatory header is a header that changes authorities set. The pallet can't go // further without importing this header. So every bridge MUST import mandatory headers. @@ -213,7 +224,7 @@ pub mod pallet { initialize_bridge::(init_data.clone()); log::info!( - target: "runtime::bridge-grandpa", + target: LOG_TARGET, "Pallet has been initialized with the following parameters: {:?}", init_data ); @@ -392,7 +403,7 @@ pub mod pallet { change_enacted = true; log::info!( - target: "runtime::bridge-grandpa", + target: LOG_TARGET, "Transitioned from authority set {} to {}! New authorities are: {:?}", current_set_id, current_set_id + 1, @@ -429,7 +440,7 @@ pub mod pallet { ) .map_err(|e| { log::error!( - target: "runtime::bridge-grandpa", + target: LOG_TARGET, "Received invalid justification for {:?}: {:?}", hash, e, @@ -455,7 +466,7 @@ pub mod pallet { // Update ring buffer pointer and remove old header. >::put((index + 1) % T::HeadersToKeep::get()); if let Ok(hash) = pruning { - log::debug!(target: "runtime::bridge-grandpa", "Pruning old header: {:?}.", hash); + log::debug!(target: LOG_TARGET, "Pruning old header: {:?}.", hash); >::remove(hash); } } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index eed718477beb3..03d73c88eaaf4 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -90,6 +90,9 @@ mod mock; pub use pallet::*; +/// The target that will be used when publishing logs related to this pallet. +const LOG_TARGET: &str = "runtime::bridge-messages"; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -217,7 +220,7 @@ pub mod pallet { pub struct Pallet(PhantomData<(T, I)>); impl, I: 'static> OwnedBridgeModule for Pallet { - const LOG_TARGET: &'static str = "runtime::bridge-messages"; + const LOG_TARGET: &'static str = LOG_TARGET; type OwnerStorage = PalletOwner; type OperatingMode = MessagesOperatingMode; type OperatingModeStorage = PalletOperatingMode; @@ -309,7 +312,7 @@ pub mod pallet { ) .map_err(|err| { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Submitter can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", additional_fee, lane_id, @@ -389,11 +392,7 @@ pub mod pallet { T::InboundPayload, >(proof, messages_count) .map_err(|err| { - log::trace!( - target: "runtime::bridge-messages", - "Rejecting invalid messages proof: {:?}", - err, - ); + log::trace!(target: LOG_TARGET, "Rejecting invalid messages proof: {:?}", err,); Error::::InvalidMessagesProof })?; @@ -409,7 +408,7 @@ pub mod pallet { let updated_latest_confirmed_nonce = lane.receive_state_update(lane_state); if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Received lane {:?} state update: latest_confirmed_nonce={}", lane_id, updated_latest_confirmed_nonce, @@ -426,7 +425,7 @@ pub mod pallet { let dispatch_weight = T::MessageDispatch::dispatch_weight(&mut message); if dispatch_weight > dispatch_weight_left { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Cannot dispatch any more messages on lane {:?}. Weight: declared={}, left={}", lane_id, dispatch_weight, @@ -478,7 +477,7 @@ pub mod pallet { } log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Received messages: total={}, valid={}. Weight used: {}/{}", total_messages, valid_messages, @@ -524,7 +523,7 @@ pub mod pallet { let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof) .map_err(|err| { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Rejecting invalid messages delivery proof: {:?}", err, ); @@ -564,7 +563,7 @@ pub mod pallet { to_confirm_messages_count, ) => { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Messages delivery proof contains too many messages to confirm: {} vs declared {}", to_confirm_messages_count, relayers_state.total_messages, @@ -574,7 +573,7 @@ pub mod pallet { }, error => { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", error, ); @@ -593,7 +592,7 @@ pub mod pallet { Some(difference) if difference == 0 => (), Some(difference) => { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "T::OnDeliveryConfirmed callback has spent less weight than expected. Refunding: \ {} - {} = {}", preliminary_callback_overhead, @@ -608,7 +607,7 @@ pub mod pallet { "T::OnDeliveryConfirmed callback consumed too much weight." ); log::error!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "T::OnDeliveryConfirmed callback has spent more weight that it is allowed to: \ {} vs {}", preliminary_callback_overhead, @@ -634,7 +633,7 @@ pub mod pallet { } log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Received messages delivery proof up to (and including) {} at lane {:?}", last_delivered_nonce, lane_id, @@ -829,7 +828,7 @@ fn send_message, I: 'static>( // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload).map_err(|err| { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Message to lane {:?} is rejected by target chain: {:?}", lane_id, err, @@ -849,7 +848,7 @@ fn send_message, I: 'static>( ) .map_err(|err| { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Message to lane {:?} is rejected by lane verifier: {:?}", lane_id, err, @@ -866,7 +865,7 @@ fn send_message, I: 'static>( ) .map_err(|err| { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Message to lane {:?} is rejected because submitter is unable to pay fee {:?}: {:?}", lane_id, delivery_and_dispatch_fee, @@ -892,7 +891,7 @@ fn send_message, I: 'static>( Some(difference) if difference == 0 => (), Some(difference) => { log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "T::OnMessageAccepted callback has spent less weight than expected. Refunding: \ {} - {} = {}", single_message_callback_overhead, @@ -904,7 +903,7 @@ fn send_message, I: 'static>( None => { debug_assert!(false, "T::OnMessageAccepted callback consumed too much weight."); log::error!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "T::OnMessageAccepted callback has spent more weight that it is allowed to: \ {} vs {}", single_message_callback_overhead, @@ -923,7 +922,7 @@ fn send_message, I: 'static>( } log::trace!( - target: "runtime::bridge-messages", + target: LOG_TARGET, "Accepted message {} to lane {:?}. Message size: {:?}", nonce, lane_id, diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index dc5ad5074b196..a70672b612bb6 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -48,6 +48,9 @@ mod extension; #[cfg(test)] mod mock; +/// The target that will be used when publishing logs related to this pallet. +const LOG_TARGET: &str = "runtime::bridge-parachains"; + /// Block hash of the bridged relay chain. pub type RelayBlockHash = bp_polkadot_core::Hash; /// Block number of the bridged relay chain. @@ -208,7 +211,7 @@ pub mod pallet { // if we're not tracking this parachain, we'll just ignore its head proof here if !T::TrackedParachains::contains(¶chain) { log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "The head of parachain {:?} has been provided, but it is not tracked by the pallet", parachain, ); @@ -219,7 +222,7 @@ pub mod pallet { Ok(Some(parachain_head)) => parachain_head, Ok(None) => { log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "The head of parachain {:?} is None. {}", parachain, if BestParaHeads::::contains_key(¶chain) { @@ -232,7 +235,7 @@ pub mod pallet { }, Err(e) => { log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "The read of head of parachain {:?} has failed: {:?}", parachain, e, @@ -325,7 +328,7 @@ pub mod pallet { // check if this head has already been imported before if updated_head_hash == stored_best_head.head_hash { log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "The head of parachain {:?} can't be updated to {}, because it has been already updated\ to the same value at previous relay chain block: {} < {}", parachain, @@ -341,7 +344,7 @@ pub mod pallet { None => 0, Some(stored_best_head) => { log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "The head of parachain {:?} can't be updated to {}, because it has been already updated\ to {} at better relay chain block: {} > {}", parachain, @@ -370,7 +373,7 @@ pub mod pallet { ); ImportedParaHeads::::insert(parachain, updated_head_hash, updated_head); log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "Updated head of parachain {:?} to {}", parachain, updated_head_hash, @@ -380,7 +383,7 @@ pub mod pallet { let prune_happened = head_hash_to_prune.is_ok(); if let Ok(head_hash_to_prune) = head_hash_to_prune { log::trace!( - target: "runtime::bridge-parachains", + target: LOG_TARGET, "Pruning old head of parachain {:?}: {}", parachain, head_hash_to_prune, From 3e97edac2a51ae7f80065426b72ce9d190dc8889 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 29 Jun 2022 16:34:58 +0300 Subject: [PATCH 0720/1210] Test pallet owner calls using macro Define macro that generates tests for set_owner() and set_operating_mode() in order to avoid duplicate code. Signed-off-by: Serban Iorga --- modules/grandpa/src/lib.rs | 103 ++----------------------------- modules/messages/Cargo.toml | 1 + modules/messages/src/lib.rs | 103 ++----------------------------- primitives/test-utils/src/lib.rs | 89 ++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 196 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index c0b4d9d3eefbe..c75ccc2e80a81 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -600,8 +600,8 @@ mod tests { use crate::mock::{run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime}; use bp_runtime::BasicOperatingMode; use bp_test_utils::{ - authority_list, make_default_justification, make_justification_for_header, - JustificationGeneratorParams, ALICE, BOB, + authority_list, generate_owned_bridge_module_tests, make_default_justification, + make_justification_for_header, JustificationGeneratorParams, ALICE, BOB, }; use codec::Encode; use frame_support::{ @@ -715,103 +715,6 @@ mod tests { }) } - #[test] - fn pallet_owner_may_change_owner() { - run_test(|| { - PalletOwner::::put(2); - - assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(2), - BasicOperatingMode::Halted - ), - DispatchError::BadOrigin, - ); - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - BasicOperatingMode::Halted - )); - - assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - BasicOperatingMode::Normal - ), - DispatchError::BadOrigin, - ); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(2), - BasicOperatingMode::Normal - ), - DispatchError::BadOrigin, - ); - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - BasicOperatingMode::Normal - )); - }); - } - - #[test] - fn pallet_may_be_halted_by_root() { - run_test(|| { - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - BasicOperatingMode::Halted - )); - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - BasicOperatingMode::Normal - )); - }); - } - - #[test] - fn pallet_may_be_halted_by_owner() { - run_test(|| { - PalletOwner::::put(2); - - assert_ok!(Pallet::::set_operating_mode( - Origin::signed(2), - BasicOperatingMode::Halted - )); - assert_ok!(Pallet::::set_operating_mode( - Origin::signed(2), - BasicOperatingMode::Normal - )); - - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - BasicOperatingMode::Halted - ), - DispatchError::BadOrigin, - ); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - BasicOperatingMode::Normal - ), - DispatchError::BadOrigin, - ); - - assert_ok!(Pallet::::set_operating_mode( - Origin::signed(2), - BasicOperatingMode::Halted - )); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - BasicOperatingMode::Normal - ), - DispatchError::BadOrigin, - ); - }); - } - #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { @@ -1184,4 +1087,6 @@ mod tests { bp_header_chain::storage_keys::best_finalized_key("Grandpa").0, ); } + + generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 47d41dba17604..5f98523266f75 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -31,6 +31,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [dev-dependencies] sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +bp-test-utils = { path = "../../primitives/test-utils" } [features] default = ["std"] diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 03d73c88eaaf4..a990101818718 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1120,6 +1120,7 @@ mod tests { REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; + use bp_test_utils::generate_owned_bridge_module_tests; use frame_support::{ assert_noop, assert_ok, storage::generator::{StorageMap, StorageValue}, @@ -1223,103 +1224,6 @@ mod tests { ); } - #[test] - fn pallet_owner_may_change_owner() { - run_test(|| { - PalletOwner::::put(2); - - assert_ok!(Pallet::::set_owner(Origin::root(), Some(1))); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(2), - MessagesOperatingMode::Basic(BasicOperatingMode::Halted) - ), - DispatchError::BadOrigin, - ); - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - MessagesOperatingMode::Basic(BasicOperatingMode::Halted) - )); - - assert_ok!(Pallet::::set_owner(Origin::signed(1), None)); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - ), - DispatchError::BadOrigin, - ); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(2), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - ), - DispatchError::BadOrigin, - ); - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - )); - }); - } - - #[test] - fn pallet_may_be_halted_by_root() { - run_test(|| { - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - MessagesOperatingMode::Basic(BasicOperatingMode::Halted) - )); - assert_ok!(Pallet::::set_operating_mode( - Origin::root(), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - )); - }); - } - - #[test] - fn pallet_may_be_halted_by_owner() { - run_test(|| { - PalletOwner::::put(2); - - assert_ok!(Pallet::::set_operating_mode( - Origin::signed(2), - MessagesOperatingMode::Basic(BasicOperatingMode::Halted) - )); - assert_ok!(Pallet::::set_operating_mode( - Origin::signed(2), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - )); - - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - MessagesOperatingMode::Basic(BasicOperatingMode::Halted) - ), - DispatchError::BadOrigin, - ); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - ), - DispatchError::BadOrigin, - ); - - assert_ok!(Pallet::::set_operating_mode( - Origin::signed(2), - MessagesOperatingMode::Basic(BasicOperatingMode::Halted) - )); - assert_noop!( - Pallet::::set_operating_mode( - Origin::signed(1), - MessagesOperatingMode::Basic(BasicOperatingMode::Normal) - ), - DispatchError::BadOrigin, - ); - }); - } - #[test] fn pallet_parameter_may_be_updated_by_root() { run_test(|| { @@ -2411,4 +2315,9 @@ mod tests { ); }); } + + generate_owned_bridge_module_tests!( + MessagesOperatingMode::Basic(BasicOperatingMode::Normal), + MessagesOperatingMode::Basic(BasicOperatingMode::Halted) + ); } diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 38d9453c98f24..66dbe9e7389e1 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -210,3 +210,92 @@ pub fn test_header(number: H::Number) -> H { pub fn header_id(index: u8) -> (H::Hash, H::Number) { (test_header::(index.into()).hash(), index.into()) } + +#[macro_export] +/// Adds methods for testing the `set_owner()` and `set_operating_mode()` for a pallet. +/// Some values are hardcoded like: +/// - `run_test()` +/// - `Pallet::` +/// - `PalletOwner::` +/// - `PalletOperatingMode::` +/// While this is not ideal, all the pallets use the same names, so it works for the moment. +/// We can revisit this in the future if anything changes. +macro_rules! generate_owned_bridge_module_tests { + ($normal_operating_mode: expr, $halted_operating_mode: expr) => { + #[test] + fn test_set_owner() { + run_test(|| { + PalletOwner::::put(1); + + // The root should be able to change the owner. + assert_ok!(Pallet::::set_owner(Origin::root(), Some(2))); + assert_eq!(PalletOwner::::get(), Some(2)); + + // The owner should be able to change the owner. + assert_ok!(Pallet::::set_owner(Origin::signed(2), Some(3))); + assert_eq!(PalletOwner::::get(), Some(3)); + + // Other users shouldn't be able to change the owner. + assert_noop!( + Pallet::::set_owner(Origin::signed(1), Some(4)), + DispatchError::BadOrigin + ); + assert_eq!(PalletOwner::::get(), Some(3)); + }); + } + + #[test] + fn test_set_operating_mode() { + run_test(|| { + PalletOwner::::put(1); + PalletOperatingMode::::put($normal_operating_mode); + + // The root should be able to halt the pallet. + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + $halted_operating_mode + )); + assert_eq!(PalletOperatingMode::::get(), $halted_operating_mode); + // The root should be able to resume the pallet. + assert_ok!(Pallet::::set_operating_mode( + Origin::root(), + $normal_operating_mode + )); + assert_eq!(PalletOperatingMode::::get(), $normal_operating_mode); + + // The owner should be able to halt the pallet. + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(1), + $halted_operating_mode + )); + assert_eq!(PalletOperatingMode::::get(), $halted_operating_mode); + // The owner should be able to resume the pallet. + assert_ok!(Pallet::::set_operating_mode( + Origin::signed(1), + $normal_operating_mode + )); + assert_eq!(PalletOperatingMode::::get(), $normal_operating_mode); + + // Other users shouldn't be able to halt the pallet. + assert_noop!( + Pallet::::set_operating_mode( + Origin::signed(2), + $halted_operating_mode + ), + DispatchError::BadOrigin + ); + assert_eq!(PalletOperatingMode::::get(), $normal_operating_mode); + // Other users shouldn't be able to resume the pallet. + PalletOperatingMode::::put($halted_operating_mode); + assert_noop!( + Pallet::::set_operating_mode( + Origin::signed(2), + $normal_operating_mode + ), + DispatchError::BadOrigin + ); + assert_eq!(PalletOperatingMode::::get(), $halted_operating_mode); + }); + } + }; +} From 05d46ca7ce1a76e69fe4aec4aeeb457adb12b68c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 29 Jun 2022 11:30:25 +0300 Subject: [PATCH 0721/1210] Add owner calls to the parachains pallet Signed-off-by: Serban Iorga --- modules/parachains/src/lib.rs | 54 ++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index a70672b612bb6..5601f588d5033 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -80,6 +80,7 @@ struct UpdateParachainHeadArtifacts { #[frame_support::pallet] pub mod pallet { use super::*; + use bp_runtime::{BasicOperatingMode, OwnedBridgeModule}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -100,6 +101,8 @@ pub mod pallet { StorageRootMismatch, /// Failed to extract state root from given parachain head. FailedToExtractStateRoot, + /// Error generated by the `OwnedBridgeModule` trait. + BridgeModule(bp_runtime::OwnedBridgeModuleError), } #[pallet::config] @@ -138,6 +141,23 @@ pub mod pallet { type HeadsToKeep: Get; } + /// Optional pallet owner. + /// + /// Pallet owner has a right to halt all pallet operations and then resume them. If it is + /// `None`, then there are no direct ways to halt/resume pallet operations, but other + /// runtime methods may still be used to do that (i.e. democracy::referendum to update halt + /// flag directly or call the `halt_operations`). + #[pallet::storage] + pub type PalletOwner, I: 'static = ()> = + StorageValue<_, T::AccountId, OptionQuery>; + + /// The current operating mode of the pallet. + /// + /// Depending on the mode either all, or no transactions will be allowed. + #[pallet::storage] + pub type PalletOperatingMode, I: 'static = ()> = + StorageValue<_, BasicOperatingMode, ValueQuery>; + /// Best parachain heads. #[pallet::storage] pub type BestParaHeads, I: 'static = ()> = @@ -158,6 +178,13 @@ pub mod pallet { #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); + impl, I: 'static> OwnedBridgeModule for Pallet { + const LOG_TARGET: &'static str = LOG_TARGET; + type OwnerStorage = PalletOwner; + type OperatingMode = BasicOperatingMode; + type OperatingModeStorage = PalletOperatingMode; + } + #[pallet::call] impl, I: 'static> Pallet where @@ -185,6 +212,7 @@ pub mod pallet { parachains: Vec, parachain_heads_proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { + Self::ensure_not_halted().map_err(Error::::BridgeModule)?; // we'll need relay chain header to verify that parachains heads are always increasing. let (relay_block_number, relay_block_hash) = at_relay_block; let relay_block = pallet_bridge_grandpa::ImportedHeaders::< @@ -266,6 +294,25 @@ pub mod pallet { Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } + + /// Change `PalletOwner`. + /// + /// May only be called either by root, or by `PalletOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { + >::set_owner(origin, new_owner) + } + + /// Halt or resume all pallet operations. + /// + /// May only be called either by root, or by `PalletOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_operating_mode( + origin: OriginFor, + operating_mode: BasicOperatingMode, + ) -> DispatchResult { + >::set_operating_mode(origin, operating_mode) + } } impl, I: 'static> Pallet { @@ -404,7 +451,9 @@ mod tests { }; use bp_runtime::BasicOperatingMode; - use bp_test_utils::{authority_list, make_default_justification}; + use bp_test_utils::{ + authority_list, generate_owned_bridge_module_tests, make_default_justification, + }; use frame_support::{ assert_noop, assert_ok, dispatch::DispatchResultWithPostInfo, @@ -412,6 +461,7 @@ mod tests { traits::{Get, OnInitialize}, weights::Weight, }; + use sp_runtime::DispatchError; use sp_trie::{ record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut, }; @@ -837,4 +887,6 @@ mod tests { .0, ); } + + generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); } From 59d4e6bbbf0e1d23f9d552952049258ce21f7776 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 30 Jun 2022 12:43:01 +0300 Subject: [PATCH 0722/1210] [parachains pallet] add unit test Add unit test in order to check that the submit_parachain_heads() call returns an error when the pallet is halted. Signed-off-by: Serban Iorga --- modules/parachains/src/lib.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 5601f588d5033..df169ab0bbc63 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -450,7 +450,7 @@ mod tests { run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; - use bp_runtime::BasicOperatingMode; + use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError}; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, }; @@ -562,6 +562,36 @@ mod tests { }) } + #[test] + fn submit_parachain_heads_checks_operating_mode() { + let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + + run_test(|| { + initialize(state_root); + + // `submit_parachain_heads()` should fail when the pallet is halted. + PalletOperatingMode::::put(BasicOperatingMode::Halted); + assert_noop!( + Pallet::::submit_parachain_heads( + Origin::signed(1), + (0, test_relay_header(0, state_root).hash()), + vec![ParaId(1), ParaId(2), ParaId(3)], + proof.clone(), + ), + Error::::BridgeModule(OwnedBridgeModuleError::Halted) + ); + + // `submit_parachain_heads()` should succeed now that the pallet is resumed. + PalletOperatingMode::::put(BasicOperatingMode::Normal); + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + (0, test_relay_header(0, state_root).hash()), + vec![ParaId(1)], + proof, + ),); + }); + } + #[test] fn imports_initial_parachain_heads() { let (state_root, proof) = From 2004a193b27b2824cae597f8182fd31040088a14 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 30 Jun 2022 13:50:46 +0300 Subject: [PATCH 0723/1210] [parachains pallet] implement genesis_build Signed-off-by: Serban Iorga --- modules/parachains/src/lib.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index df169ab0bbc63..ec2d16427e71a 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -441,6 +441,37 @@ pub mod pallet { Ok(UpdateParachainHeadArtifacts { best_head: updated_best_para_head, prune_happened }) } } + + #[pallet::genesis_config] + pub struct GenesisConfig, I: 'static = ()> { + /// Initial pallet operating mode. + pub operating_mode: BasicOperatingMode, + /// Initial pallet owner. + pub owner: Option, + /// Dummy marker. + pub phantom: sp_std::marker::PhantomData, + } + + #[cfg(feature = "std")] + impl, I: 'static> Default for GenesisConfig { + fn default() -> Self { + Self { + operating_mode: Default::default(), + owner: Default::default(), + phantom: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl, I: 'static> GenesisBuild for GenesisConfig { + fn build(&self) { + PalletOperatingMode::::put(&self.operating_mode); + if let Some(ref owner) = self.owner { + PalletOwner::::put(owner); + } + } + } } #[cfg(test)] From 2f5bb0f164ac83667103236b5363c127933995c5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 4 Jul 2022 15:05:44 +0300 Subject: [PATCH 0724/1210] Remove without_storage_info for messages pallet (#1487) * draft: remove without_storage_info for messages pallet * some cleanup --- bin/millau/runtime/src/lib.rs | 3 + bin/millau/runtime/src/rialto_messages.rs | 15 ++-- .../runtime/src/rialto_parachain_messages.rs | 13 +-- bin/rialto-parachain/runtime/src/lib.rs | 1 + .../runtime/src/millau_messages.rs | 13 +-- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/millau_messages.rs | 15 ++-- bin/runtime-common/src/messages.rs | 13 ++- modules/messages/src/inbound_lane.rs | 81 ++++++++++++++++++- modules/messages/src/lib.rs | 74 ++++++++++++----- modules/messages/src/mock.rs | 10 ++- modules/messages/src/outbound_lane.rs | 66 ++++++++++++++- modules/messages/src/weights_ext.rs | 6 +- modules/parachains/src/weights_ext.rs | 2 +- primitives/chain-millau/src/lib.rs | 19 ----- primitives/chain-rialto-parachain/src/lib.rs | 19 ----- primitives/chain-rialto/src/lib.rs | 19 ----- primitives/messages/src/lib.rs | 32 ++++---- primitives/polkadot-core/src/lib.rs | 17 ---- primitives/polkadot-core/src/parachains.rs | 2 +- primitives/runtime/src/lib.rs | 17 ++-- relays/client-kusama/src/lib.rs | 1 - relays/client-millau/src/lib.rs | 1 - relays/client-polkadot/src/lib.rs | 1 - relays/client-rialto-parachain/src/lib.rs | 2 - relays/client-rialto/src/lib.rs | 1 - relays/client-rococo/src/lib.rs | 1 - relays/client-substrate/src/chain.rs | 2 - relays/client-substrate/src/test_chain.rs | 1 - relays/client-westend/src/lib.rs | 2 - relays/client-wococo/src/lib.rs | 1 - .../src/messages_source.rs | 13 ++- 32 files changed, 283 insertions(+), 181 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index fecbf4f99073f..8b2988d421fdc 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -453,6 +453,7 @@ impl pallet_bridge_messages::Config for Runtime { type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = crate::rialto_messages::ToRialtoMaximalOutboundPayloadSize; type OutboundPayload = crate::rialto_messages::ToRialtoMessagePayload; type OutboundMessageFee = Balance; @@ -484,6 +485,8 @@ impl pallet_bridge_messages::Config for Run type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = + crate::rialto_parachain_messages::ToRialtoParachainMaximalOutboundPayloadSize; type OutboundPayload = crate::rialto_parachain_messages::ToRialtoParachainMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index dad7591147d81..bbcc6144f8521 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -79,6 +79,10 @@ pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDi frame_support::traits::ConstU64, >; +/// Maximal outbound payload size of Millau -> Rialto messages. +pub type ToRialtoMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithRialtoMessageBridge; @@ -145,12 +149,9 @@ impl messages::ThisChainWithMessages for Millau { } fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint( - bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - 1, - 1, - ) - .unwrap_or(u32::MAX); + let inbound_data_size = InboundLaneData::::encoded_size_hint(1, 1) + .and_then(|x| u32::try_from(x).ok()) + .unwrap_or(u32::MAX); MessageTransaction { dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, @@ -346,10 +347,10 @@ mod tests { let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ) + .and_then(|x| u32::try_from(x).ok()) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_millau::Millau::max_extrinsic_size(), diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 26b2b5d4c48b7..ceabe2b00018d 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -84,6 +84,10 @@ pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChain frame_support::traits::ConstU64, >; +/// Maximal outbound payload size of Millau -> RialtoParachain messages. +pub type ToRialtoParachainMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + /// Millau <-> RialtoParachain message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithRialtoParachainMessageBridge; @@ -134,12 +138,9 @@ impl messages::ThisChainWithMessages for Millau { } fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint( - bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - 1, - 1, - ) - .unwrap_or(u32::MAX); + let inbound_data_size = InboundLaneData::::encoded_size_hint(1, 1) + .and_then(|x| u32::try_from(x).ok()) + .unwrap_or(u32::MAX); MessageTransaction { dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 0927f138f3baf..37930c3555412 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -520,6 +520,7 @@ impl pallet_bridge_messages::Config for Runtime { type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = crate::millau_messages::ToMillauMaximalOutboundPayloadSize; type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 8d88a4d44bcc9..ef8e3c657ac69 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -82,6 +82,10 @@ pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesPro pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; +/// Maximal outbound payload size of Rialto -> Millau messages. +pub type ToMillauMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + /// Millau <-> RialtoParachain message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithMillauMessageBridge; @@ -134,12 +138,9 @@ impl messages::ThisChainWithMessages for RialtoParachain { fn estimate_delivery_confirmation_transaction() -> MessageTransaction { let inbound_data_size = - InboundLaneData::::encoded_size_hint( - bp_rialto_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - 1, - 1, - ) - .unwrap_or(u32::MAX); + InboundLaneData::::encoded_size_hint(1, 1) + .and_then(|x| u32::try_from(x).ok()) + .unwrap_or(u32::MAX); MessageTransaction { dispatch_weight: diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e10ddda0fb3a9..3d468a5b4ec1c 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -437,6 +437,7 @@ impl pallet_bridge_messages::Config for Runtime { type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = crate::millau_messages::ToMillauMaximalOutboundPayloadSize; type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; type OutboundMessageFee = Balance; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index fdc376be70e6e..d547dde538fec 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -78,6 +78,10 @@ pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesPro pub type ToMillauMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; +/// Maximal outbound payload size of Rialto -> Millau messages. +pub type ToMillauMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + /// Millau <-> Rialto message bridge. #[derive(RuntimeDebug, Clone, Copy)] pub struct WithMillauMessageBridge; @@ -144,12 +148,9 @@ impl messages::ThisChainWithMessages for Rialto { } fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint( - bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - 1, - 1, - ) - .unwrap_or(u32::MAX); + let inbound_data_size = InboundLaneData::::encoded_size_hint(1, 1) + .and_then(|x| u32::try_from(x).ok()) + .unwrap_or(u32::MAX); MessageTransaction { dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, @@ -343,10 +344,10 @@ mod tests { let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( - bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ) + .and_then(|x| u32::try_from(x).ok()) .unwrap_or(u32::MAX); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_rialto::Rialto::max_extrinsic_size(), diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index a9a252118b254..e8f8fc1f7f038 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -200,6 +200,15 @@ pub mod source { /// Message payload for This -> Bridged chain messages. pub type FromThisChainMessagePayload = Vec; + /// Maximal size of outbound message payload. + pub struct FromThisChainMaximalOutboundPayloadSize(PhantomData); + + impl Get for FromThisChainMaximalOutboundPayloadSize { + fn get() -> u32 { + maximal_message_size::() + } + } + /// Messages delivery proof from bridged chain: /// /// - hash of finalized header; @@ -216,7 +225,7 @@ pub mod source { } impl Size for FromBridgedChainMessagesDeliveryProof { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { u32::try_from( self.storage_proof .iter() @@ -529,7 +538,7 @@ pub mod target { } impl Size for FromBridgedChainMessagesProof { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { u32::try_from( self.storage_proof .iter() diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 00875bb878a82..6624655ddc18e 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -16,13 +16,17 @@ //! Everything about incoming messages receival. +use crate::Config; + use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, UnrewardedRelayer, }; use bp_runtime::messages::MessageDispatchResult; -use frame_support::RuntimeDebug; +use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; +use frame_support::{traits::Get, RuntimeDebug}; +use scale_info::{Type, TypeInfo}; use sp_std::prelude::PartialEq; /// Inbound lane storage. @@ -44,6 +48,76 @@ pub trait InboundLaneStorage { fn set_data(&mut self, data: InboundLaneData); } +/// Inbound lane data wrapper that implements `MaxEncodedLen`. +/// +/// We have already had `MaxEncodedLen`-like functionality before, but its usage has +/// been localized and we haven't been passing bounds (maximal count of unrewarded relayer entries, +/// maximal count of unconfirmed messages) everywhere. This wrapper allows us to avoid passing +/// these generic bounds all over the code. +/// +/// The encoding of this type matches encoding of the corresponding `MessageData`. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct StoredInboundLaneData, I: 'static>(pub InboundLaneData); + +impl, I: 'static> sp_std::ops::Deref for StoredInboundLaneData { + type Target = InboundLaneData; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl, I: 'static> sp_std::ops::DerefMut for StoredInboundLaneData { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl, I: 'static> Default for StoredInboundLaneData { + fn default() -> Self { + StoredInboundLaneData(Default::default()) + } +} + +impl, I: 'static> From> + for StoredInboundLaneData +{ + fn from(data: InboundLaneData) -> Self { + StoredInboundLaneData(data) + } +} + +impl, I: 'static> From> + for InboundLaneData +{ + fn from(data: StoredInboundLaneData) -> Self { + data.0 + } +} + +impl, I: 'static> EncodeLike> + for InboundLaneData +{ +} + +impl, I: 'static> TypeInfo for StoredInboundLaneData { + type Identity = Self; + + fn type_info() -> Type { + InboundLaneData::::type_info() + } +} + +impl, I: 'static> MaxEncodedLen for StoredInboundLaneData { + fn max_encoded_len() -> usize { + InboundLaneData::::encoded_size_hint( + T::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize, + T::MaxUnconfirmedMessagesAtInboundLane::get() as usize, + ) + .unwrap_or(usize::MAX) + } +} + /// Result of single message receival. #[derive(RuntimeDebug, PartialEq, Eq)] pub enum ReceivalResult { @@ -333,7 +407,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); let max_nonce = - ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); + ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); for current_nonce in 1..max_nonce + 1 { assert_eq!( lane.receive_message::( @@ -372,8 +446,7 @@ mod tests { fn fails_to_receive_messages_above_unconfirmed_messages_limit_per_lane() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let max_nonce = - ::MaxUnconfirmedMessagesAtInboundLane::get(); + let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); for current_nonce in 1..=max_nonce { assert_eq!( lane.receive_message::( diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a990101818718..e02c94d022768 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -37,6 +37,8 @@ // Generated by `decl_event!` #![allow(clippy::unused_unit)] +pub use inbound_lane::StoredInboundLaneData; +pub use outbound_lane::StoredMessageData; pub use weights::WeightInfo; pub use weights_ext::{ ensure_able_to_receive_confirmation, ensure_able_to_receive_message, @@ -62,9 +64,9 @@ use bp_messages::{ UnrewardedRelayersState, }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{ - fail, + ensure, fail, traits::Get, weights::{Pays, PostDispatchInfo}, }; @@ -145,6 +147,9 @@ pub mod pallet { /// these messages are from different lanes. type MaxUnconfirmedMessagesAtInboundLane: Get; + /// Maximal size of the outbound payload. + #[pallet::constant] + type MaximalOutboundPayloadSize: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter + Size; /// Message fee type of outbound messages. This fee is paid on this chain. @@ -154,7 +159,8 @@ pub mod pallet { + Parameter + SaturatingAdd + Zero - + Copy; + + Copy + + MaxEncodedLen; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; @@ -162,7 +168,7 @@ pub mod pallet { type InboundMessageFee: Decode + Zero; /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the /// bridged chain. - type InboundRelayer: Parameter; + type InboundRelayer: Parameter + MaxEncodedLen; /// A type which can be turned into an AccountId from a 256-bit hash. /// @@ -216,7 +222,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); impl, I: 'static> OwnedBridgeModule for Pallet { @@ -658,6 +663,8 @@ pub mod pallet { pub enum Error { /// Pallet is not in Normal operating mode. NotOperatingNormally, + /// The message is too large to be sent over the bridge. + MessageIsTooLarge, /// Message has been treated as invalid by chain verifier. MessageRejectedByChainVerifier, /// Message has been treated as invalid by lane verifier. @@ -707,7 +714,7 @@ pub mod pallet { /// Map of lane id => inbound lane data. #[pallet::storage] pub type InboundLanes, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, LaneId, InboundLaneData, ValueQuery>; + StorageMap<_, Blake2_128Concat, LaneId, StoredInboundLaneData, ValueQuery>; /// Map of lane id => outbound lane data. #[pallet::storage] @@ -717,7 +724,7 @@ pub mod pallet { /// All queued outbound messages. #[pallet::storage] pub type OutboundMessages, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, MessageKey, MessageData>; + StorageMap<_, Blake2_128Concat, MessageKey, StoredMessageData>; #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { @@ -756,7 +763,7 @@ pub mod pallet { lane: LaneId, nonce: MessageNonce, ) -> Option> { - OutboundMessages::::get(MessageKey { lane_id: lane, nonce }) + OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(Into::into) } /// Prepare data, related to given inbound message. @@ -822,6 +829,12 @@ fn send_message, I: 'static>( > { ensure_normal_operating_mode::()?; + // the most lightweigh check is the message size check + ensure!( + payload.size() < T::MaximalOutboundPayloadSize::get(), + Error::::MessageIsTooLarge, + ); + // initially, actual (post-dispatch) weight is equal to pre-dispatch weight let mut actual_weight = T::WeightInfo::send_message_weight(&payload, T::DbWeight::get()); @@ -955,7 +968,8 @@ where // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); for nonce in nonce_begin..nonce_end + 1 { - let message_data = OutboundMessages::::get(MessageKey { lane_id, nonce }) + let key = MessageKey { lane_id, nonce }; + let message_data = OutboundMessages::::get(key) .expect("message was just confirmed; we never prune unconfirmed messages; qed"); relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); relayer_reward.messages += 1; @@ -1027,7 +1041,8 @@ impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage< match self.cached_data.clone().into_inner() { Some(data) => data, None => { - let data = InboundLanes::::get(&self.lane_id); + let data: InboundLaneData = + InboundLanes::::get(&self.lane_id).into(); *self.cached_data.try_borrow_mut().expect( "we're in the single-threaded environment;\ we have no recursive borrows; qed", @@ -1042,7 +1057,7 @@ impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage< "we're in the single-threaded environment;\ we have no recursive borrows; qed", ) = Some(data.clone()); - InboundLanes::::insert(&self.lane_id, data) + InboundLanes::::insert(&self.lane_id, StoredInboundLaneData::(data)) } } @@ -1070,6 +1085,7 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag #[cfg(test)] fn message(&self, nonce: &MessageNonce) -> Option> { OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce }) + .map(Into::into) } fn save_message( @@ -1116,8 +1132,9 @@ mod tests { message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, - TestOnMessageAccepted, TestRuntime, TokenConversionRate, PAYLOAD_REJECTED_BY_TARGET_CHAIN, - REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, + TestOnMessageAccepted, TestRuntime, TokenConversionRate, MAX_OUTBOUND_PAYLOAD_SIZE, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, + TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -1137,7 +1154,7 @@ mod tests { fn inbound_unrewarded_relayers_state( lane: bp_messages::LaneId, ) -> bp_messages::UnrewardedRelayersState { - let inbound_lane_data = InboundLanes::::get(&lane); + let inbound_lane_data = InboundLanes::::get(&lane).0; let last_delivered_nonce = inbound_lane_data.last_delivered_nonce(); let relayers = inbound_lane_data.relayers; bp_messages::UnrewardedRelayersState { @@ -1443,6 +1460,27 @@ mod tests { }); } + #[test] + fn send_message_rejects_too_large_message() { + run_test(|| { + let mut message_payload = message_payload(1, 0); + // the payload isn't simply extra, so it'll definitely overflow + // `MAX_OUTBOUND_PAYLOAD_SIZE` if we add `MAX_OUTBOUND_PAYLOAD_SIZE` bytes to extra + message_payload + .extra + .extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]); + assert_noop!( + Pallet::::send_message( + Origin::signed(1), + TEST_LANE_ID, + message_payload, + 0, + ), + Error::::MessageIsTooLarge, + ); + }) + } + #[test] fn chain_verifier_rejects_invalid_message_in_send_message() { run_test(|| { @@ -1502,7 +1540,7 @@ mod tests { REGULAR_PAYLOAD.declared_weight, )); - assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).0.last_delivered_nonce(), 1); }); } @@ -1547,7 +1585,7 @@ mod tests { )); assert_eq!( - InboundLanes::::get(TEST_LANE_ID), + InboundLanes::::get(TEST_LANE_ID).0, InboundLaneData { last_confirmed_nonce: 9, relayers: vec![ @@ -2146,8 +2184,8 @@ mod tests { run_test(|| { let mut small_payload = message_payload(0, 100); let mut large_payload = message_payload(1, 100); - small_payload.extra = vec![1; 100]; - large_payload.extra = vec![2; 16_384]; + small_payload.extra = vec![1; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 10]; + large_payload.extra = vec![2; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 5]; assert_ok!(Pallet::::send_message( Origin::signed(1), diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 33c6eae6eb23b..b836517e419a2 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -174,6 +174,7 @@ impl Config for TestRuntime { type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = frame_support::traits::ConstU32; type OutboundPayload = TestPayload; type OutboundMessageFee = TestMessageFee; @@ -205,11 +206,14 @@ impl SenderOrigin for Origin { } impl Size for TestPayload { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { 16 + self.extra.len() as u32 } } +/// Maximal outbound payload size. +pub const MAX_OUTBOUND_PAYLOAD_SIZE: u32 = 4096; + /// Account that has balance to use in tests. pub const ENDOWED_ACCOUNT: AccountId = 0xDEAD; @@ -244,7 +248,7 @@ pub struct TestMessagesProof { } impl Size for TestMessagesProof { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { 0 } } @@ -271,7 +275,7 @@ impl From>, ()>> for TestMessagesProof { pub struct TestMessagesDeliveryProof(pub Result<(LaneId, InboundLaneData), ()>); impl Size for TestMessagesDeliveryProof { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { 0 } } diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 041dec214b11c..5f977b2f2e297 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -16,12 +16,16 @@ //! Everything about outgoing messages sending. +use crate::Config; + use bitvec::prelude::*; use bp_messages::{ DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, }; -use frame_support::RuntimeDebug; +use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; +use frame_support::{traits::Get, RuntimeDebug}; +use scale_info::{Type, TypeInfo}; use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. @@ -44,6 +48,66 @@ pub trait OutboundLaneStorage { fn remove_message(&mut self, nonce: &MessageNonce); } +/// Outbound message data wrapper that implements `MaxEncodedLen`. +/// +/// We have already had `MaxEncodedLen`-like functionality before, but its usage has +/// been localized and we haven't been passing it everywhere. This wrapper allows us +/// to avoid passing these generic bounds all over the code. +/// +/// The encoding of this type matches encoding of the corresponding `MessageData`. +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] +pub struct StoredMessageData, I: 'static>(pub MessageData); + +impl, I: 'static> sp_std::ops::Deref for StoredMessageData { + type Target = MessageData; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl, I: 'static> sp_std::ops::DerefMut for StoredMessageData { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl, I: 'static> From> + for StoredMessageData +{ + fn from(data: MessageData) -> Self { + StoredMessageData(data) + } +} + +impl, I: 'static> From> + for MessageData +{ + fn from(data: StoredMessageData) -> Self { + data.0 + } +} + +impl, I: 'static> TypeInfo for StoredMessageData { + type Identity = Self; + + fn type_info() -> Type { + MessageData::::type_info() + } +} + +impl, I: 'static> EncodeLike> + for MessageData +{ +} + +impl, I: 'static> MaxEncodedLen for StoredMessageData { + fn max_encoded_len() -> usize { + T::OutboundMessageFee::max_encoded_len() + .saturating_add(T::MaximalOutboundPayloadSize::get() as usize) + } +} + /// Result of messages receival confirmation. #[derive(RuntimeDebug, PartialEq, Eq)] pub enum ReceivalConfirmationResult { diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 483a22eda1d6b..80ac810e8c921 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -199,7 +199,7 @@ pub trait WeightInfoExt: WeightInfo { /// Weight of message send extrinsic. fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { let transaction_overhead = Self::send_message_overhead(); - let message_size_overhead = Self::send_message_size_overhead(message.size_hint()); + let message_size_overhead = Self::send_message_size_overhead(message.size()); let call_back_overhead = Self::single_message_callback_overhead(db_weight); transaction_overhead @@ -225,7 +225,7 @@ pub trait WeightInfoExt: WeightInfo { let expected_proof_size = EXPECTED_DEFAULT_MESSAGE_LENGTH .saturating_mul(messages_count.saturating_sub(1)) .saturating_add(Self::expected_extra_storage_proof_size()); - let actual_proof_size = proof.size_hint(); + let actual_proof_size = proof.size(); let proof_size_overhead = Self::storage_proof_size_overhead( actual_proof_size.saturating_sub(expected_proof_size), ); @@ -253,7 +253,7 @@ pub trait WeightInfoExt: WeightInfo { // proof size overhead weight let expected_proof_size = Self::expected_extra_storage_proof_size(); - let actual_proof_size = proof.size_hint(); + let actual_proof_size = proof.size(); let proof_size_overhead = Self::storage_proof_size_overhead( actual_proof_size.saturating_sub(expected_proof_size), ); diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs index 3f3815eed96c6..f345762dad9c8 100644 --- a/modules/parachains/src/weights_ext.rs +++ b/modules/parachains/src/weights_ext.rs @@ -56,7 +56,7 @@ pub trait WeightInfoExt: WeightInfo { let expected_proof_size = parachains_count .saturating_mul(DEFAULT_PARACHAIN_HEAD_SIZE) .saturating_add(Self::expected_extra_storage_proof_size()); - let actual_proof_size = proof.size_hint(); + let actual_proof_size = proof.size(); let proof_size_overhead = Self::storage_proof_size_overhead( actual_proof_size.saturating_sub(expected_proof_size), ); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 240c2daaa98c1..48c80e7017a08 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -53,9 +53,6 @@ pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Can be computed by subtracting encoded call size from raw transaction size. pub const TX_EXTRA_BYTES: u32 = 103; -/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. -pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; - /// Maximum weight of single Millau block. /// /// This represents 0.5 seconds of compute assuming a target block time of six seconds. @@ -363,19 +360,3 @@ sp_api::decl_runtime_apis! { ) -> Vec; } } - -#[cfg(test)] -mod tests { - use super::*; - use sp_runtime::codec::Encode; - - #[test] - fn maximal_account_size_does_not_overflow_constant() { - assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), - "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::from([0u8; 32]).encode().len(), - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - ); - } -} diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 38b4192bf348c..9e54744f2d29b 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -50,9 +50,6 @@ pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Can be computed by subtracting encoded call size from raw transaction size. pub const TX_EXTRA_BYTES: u32 = 104; -/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. -pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; - /// Maximal weight of single RialtoParachain block. /// /// This represents two seconds of compute assuming a target block time of six seconds. @@ -290,19 +287,3 @@ sp_api::decl_runtime_apis! { ) -> Vec; } } - -#[cfg(test)] -mod tests { - use super::*; - use sp_runtime::codec::Encode; - - #[test] - fn maximal_account_size_does_not_overflow_constant() { - assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), - "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::from([0u8; 32]).encode().len(), - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - ); - } -} diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index e5c5ebab76ff5..9acc9f9f9a6db 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -44,9 +44,6 @@ pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Can be computed by subtracting encoded call size from raw transaction size. pub const TX_EXTRA_BYTES: u32 = 104; -/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. -pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; - /// Maximal weight of single Rialto block. /// /// This represents two seconds of compute assuming a target block time of six seconds. @@ -311,19 +308,3 @@ sp_api::decl_runtime_apis! { ) -> Vec; } } - -#[cfg(test)] -mod tests { - use super::*; - use sp_runtime::codec::Encode; - - #[test] - fn maximal_account_size_does_not_overflow_constant() { - assert!( - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize >= AccountId::from([0u8; 32]).encode().len(), - "Actual maximal size of encoded AccountId ({}) overflows expected ({})", - AccountId::from([0u8; 32]).encode().len(), - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - ); - } -} diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 455caad729b70..ad1dbd38be901 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -21,8 +21,8 @@ #![allow(clippy::too_many_arguments)] use bitvec::prelude::*; -use bp_runtime::messages::DispatchFeePayment; -use codec::{Decode, Encode}; +use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode, OperatingMode}; +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; @@ -32,11 +32,10 @@ pub mod storage_keys; pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in related crates. -use bp_runtime::{BasicOperatingMode, OperatingMode}; pub use frame_support::weights::Weight; /// Messages pallet operating mode. -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum MessagesOperatingMode { /// Basic operating mode (Normal/Halted) @@ -89,7 +88,7 @@ pub type BridgeMessageId = (LaneId, MessageNonce); pub type MessagePayload = Vec; /// Message key (unique message identifier) as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] pub struct MessageKey { /// ID of the message lane. pub lane_id: LaneId, @@ -158,13 +157,13 @@ impl InboundLaneData { /// Returns approximate size of the struct, given a number of entries in the `relayers` set and /// size of each entry. /// - /// Returns `None` if size overflows `u32` limits. - pub fn encoded_size_hint( - relayer_id_encoded_size: u32, - relayers_entries: u32, - messages_count: u32, - ) -> Option { - let message_nonce_size = 8; + /// Returns `None` if size overflows `usize` limits. + pub fn encoded_size_hint(relayers_entries: usize, messages_count: usize) -> Option + where + RelayerId: MaxEncodedLen, + { + let message_nonce_size = MessageNonce::max_encoded_len(); + let relayer_id_encoded_size = RelayerId::max_encoded_len(); let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; let dispatch_results_per_byte = 8; @@ -305,7 +304,7 @@ pub struct UnrewardedRelayersState { } /// Outbound lane data. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct OutboundLaneData { /// Nonce of the oldest message that we haven't yet pruned. May point to not-yet-generated /// message if all sent messages are already pruned. @@ -379,11 +378,8 @@ mod tests { (13u8, 128u8), ]; for (relayer_entries, messages_count) in test_cases { - let expected_size = InboundLaneData::::encoded_size_hint( - 1, - relayer_entries as _, - messages_count as _, - ); + let expected_size = + InboundLaneData::::encoded_size_hint(relayer_entries as _, messages_count as _); let actual_size = InboundLaneData { relayers: (1u8..=relayer_entries) .map(|i| { diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 8db1af2fd3367..4b0ef430ad533 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -65,11 +65,6 @@ pub mod parachains; /// at next runtime upgrade. pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; -/// Maximal size (in bytes) of encoded (using `Encode::encode()`) account id. -/// -/// All polkadot-like chains are using same crypto. -pub const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 32; - /// All Polkadot-like chains allow normal extrinsics to fill block up to 75 percent. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. @@ -429,18 +424,6 @@ pub fn account_info_storage_key(id: &AccountId) -> Vec { #[cfg(test)] mod tests { use super::*; - use sp_runtime::codec::Encode; - - #[test] - fn maximal_encoded_account_id_size_is_correct() { - let actual_size = AccountId::from([0u8; 32]).encode().len(); - assert!( - actual_size <= MAXIMAL_ENCODED_ACCOUNT_ID_SIZE as usize, - "Actual size of encoded account id for Polkadot-like chains ({}) is larger than expected {}", - actual_size, - MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - ); - } #[test] fn should_generate_storage_key() { diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index af05e7e98582b..59b895065e179 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -93,7 +93,7 @@ pub type ParaHasher = crate::Hasher; pub struct ParaHeadsProof(pub Vec>); impl Size for ParaHeadsProof { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { u32::try_from(self.0.iter().fold(0usize, |sum, node| sum.saturating_add(node.len()))) .unwrap_or(u32::MAX) } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 4b69bbdb68828..2849e346da426 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -18,7 +18,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use codec::{Decode, Encode, FullCodec}; +use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; use frame_support::{ log, pallet_prelude::DispatchResult, PalletError, RuntimeDebug, StorageHasher, StorageValue, }; @@ -139,21 +139,18 @@ pub fn derive_relayer_fund_account_id(bridge_id: ChainId) -> H256 { /// 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; + /// Return size of this object (in bytes). + fn size(&self) -> u32; } impl Size for () { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { 0 } } impl Size for Vec { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { self.len() as _ } } @@ -162,7 +159,7 @@ impl Size for Vec { pub struct PreComputedSize(pub usize); impl Size for PreComputedSize { - fn size_hint(&self) -> u32 { + fn size(&self) -> u32 { u32::try_from(self.0).unwrap_or(u32::MAX) } } @@ -308,7 +305,7 @@ pub trait OperatingMode: Send + Copy + Debug + FullCodec { } /// Basic operating modes for a bridges module (Normal/Halted). -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum BasicOperatingMode { /// Normal mode, when all operations are allowed. diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 8011cbc564666..31eb3f40e3394 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -63,7 +63,6 @@ impl Chain for Kusama { bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_kusama::SignedBlock; type Call = crate::runtime::Call; diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 36ad9df69d69b..4250bd34de75f 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -82,7 +82,6 @@ impl Chain for Millau { bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::Call; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 745bbc44fb6fb..35d876f546380 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -63,7 +63,6 @@ impl Chain for Polkadot { bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_polkadot::SignedBlock; type Call = crate::runtime::Call; diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 74393211d9377..a6f34201ca5f5 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -63,8 +63,6 @@ impl Chain for RialtoParachain { bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = - bp_rialto_parachain::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = rialto_parachain_runtime::SignedBlock; type Call = rialto_parachain_runtime::Call; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 7ddaaabe3611c..67b96563817e3 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -63,7 +63,6 @@ impl Chain for Rialto { bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::Call; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 161b719516ae9..42a22a8f268bd 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -66,7 +66,6 @@ impl Chain for Rococo { bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_rococo::SignedBlock; type Call = crate::runtime::Call; diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index d7f441b73ac2c..adfecff4eed18 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -52,8 +52,6 @@ pub trait Chain: ChainBase + Clone { const AVERAGE_BLOCK_INTERVAL: Duration; /// Maximal expected storage proof overhead (in bytes). const STORAGE_PROOF_OVERHEAD: u32; - /// Maximal size (in bytes) of SCALE-encoded account id on this chain. - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32; /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index f97df643a208d..f9a9e2455ed99 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -55,7 +55,6 @@ impl Chain for TestChain { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); const STORAGE_PROOF_OVERHEAD: u32 = 0; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0; type SignedBlock = sp_runtime::generic::SignedBlock< sp_runtime::generic::Block, diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index cd2e3caab6182..4b27bfeb82d8a 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -58,7 +58,6 @@ impl Chain for Westend { bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; @@ -117,7 +116,6 @@ impl Chain for Westmint { bp_westend::BEST_FINALIZED_WESTMINT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index eb20e40f483e6..3c96a80b60db5 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -66,7 +66,6 @@ impl Chain for Wococo { bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; - const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE; type SignedBlock = bp_wococo::SignedBlock; type Call = crate::runtime::Call; diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 5a6b6554e4bae..8ed8367d35d7c 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -467,12 +467,10 @@ where /// affect the call weight - we only care about its size. fn prepare_dummy_messages_delivery_proof( ) -> SubstrateMessagesDeliveryProof { - let single_message_confirmation_size = bp_messages::InboundLaneData::<()>::encoded_size_hint( - SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, - 1, - 1, - ) - .unwrap_or(u32::MAX); + let single_message_confirmation_size = + bp_messages::InboundLaneData::<()>::encoded_size_hint(1, 1) + .and_then(|x| u32::try_from(x).ok()) + .unwrap_or(u32::MAX); let proof_size = TC::STORAGE_PROOF_OVERHEAD.saturating_add(single_message_confirmation_size); ( UnrewardedRelayersState { @@ -651,6 +649,7 @@ fn make_message_details_map( mod tests { use super::*; use bp_runtime::messages::DispatchFeePayment; + use codec::MaxEncodedLen; use relay_rococo_client::Rococo; use relay_wococo_client::Wococo; @@ -765,7 +764,7 @@ mod tests { #[test] fn prepare_dummy_messages_delivery_proof_works() { let expected_minimal_size = - Wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Rococo::STORAGE_PROOF_OVERHEAD; + bp_wococo::AccountId::max_encoded_len() as u32 + Rococo::STORAGE_PROOF_OVERHEAD; let dummy_proof = prepare_dummy_messages_delivery_proof::(); assert!( dummy_proof.1.encode().len() as u32 > expected_minimal_size, From 1bd26309249a1b79d5d0fd0d5b1f519f7f83bbbb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 5 Jul 2022 12:41:58 +0300 Subject: [PATCH 0725/1210] backport named events PR (#1489) --- modules/messages/src/lib.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index e02c94d022768..26e62a07d7b6d 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -265,7 +265,7 @@ pub mod pallet { ) -> DispatchResult { Self::ensure_owner_or_root(origin)?; parameter.save(); - Self::deposit_event(Event::ParameterUpdated(parameter)); + Self::deposit_event(Event::ParameterUpdated { parameter }); Ok(()) } @@ -623,7 +623,10 @@ pub mod pallet { // emit 'delivered' event let received_range = confirmed_messages.begin..=confirmed_messages.end; - Self::deposit_event(Event::MessagesDelivered(lane_id, confirmed_messages)); + Self::deposit_event(Event::MessagesDelivered { + lane_id, + messages: confirmed_messages, + }); // if some new messages have been confirmed, reward relayers let relayer_fund_account = @@ -652,11 +655,11 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { /// Pallet parameter has been updated. - ParameterUpdated(T::Parameter), + ParameterUpdated { parameter: T::Parameter }, /// Message has been accepted and is waiting to be delivered. - MessageAccepted(LaneId, MessageNonce), + MessageAccepted { lane_id: LaneId, nonce: MessageNonce }, /// Messages in the inclusive range have been delivered to the bridged chain. - MessagesDelivered(LaneId, DeliveredMessages), + MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages }, } #[pallet::error] @@ -942,7 +945,7 @@ fn send_message, I: 'static>( encoded_payload_len, ); - Pallet::::deposit_event(Event::MessageAccepted(lane_id, nonce)); + Pallet::::deposit_event(Event::MessageAccepted { lane_id, nonce }); Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } @@ -1188,7 +1191,10 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(Event::MessageAccepted(TEST_LANE_ID, message_nonce)), + event: TestEvent::Messages(Event::MessageAccepted { + lane_id: TEST_LANE_ID, + nonce: message_nonce + }), topics: vec![], }], ); @@ -1232,10 +1238,10 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(Event::MessagesDelivered( - TEST_LANE_ID, - DeliveredMessages::new(1, true), - )), + event: TestEvent::Messages(Event::MessagesDelivered { + lane_id: TEST_LANE_ID, + messages: DeliveredMessages::new(1, true), + }), topics: vec![], }], ); @@ -1257,7 +1263,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(Event::ParameterUpdated(parameter)), + event: TestEvent::Messages(Event::ParameterUpdated { parameter }), topics: vec![], }], ); @@ -1281,7 +1287,7 @@ mod tests { System::::events(), vec![EventRecord { phase: Phase::Initialization, - event: TestEvent::Messages(Event::ParameterUpdated(parameter)), + event: TestEvent::Messages(Event::ParameterUpdated { parameter }), topics: vec![], }], ); From c3dc52fd8fcce7bfdb06949e87302c290c0f67ca Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 5 Jul 2022 16:28:19 +0300 Subject: [PATCH 0726/1210] [CLI] Remove some macros Refactor the implementations for the following CLI methods in order to avoid using macros: - init_bridge - relay_headers - relay_parachains Signed-off-by: Serban Iorga --- relays/bin-substrate/src/chains/westend.rs | 16 +- relays/bin-substrate/src/cli/bridge.rs | 137 +++++++ relays/bin-substrate/src/cli/init_bridge.rs | 363 +++++++++--------- relays/bin-substrate/src/cli/relay_headers.rs | 155 +++----- .../bin-substrate/src/cli/relay_parachains.rs | 120 +++--- 5 files changed, 467 insertions(+), 324 deletions(-) diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index eb578ddb78348..ae52944707487 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -17,7 +17,7 @@ //! Westend chain specification for CLI. use crate::cli::CliChain; -use relay_westend_client::Westend; +use relay_westend_client::{Westend, Westmint}; use sp_version::RuntimeVersion; impl CliChain for Westend { @@ -33,3 +33,17 @@ impl CliChain for Westend { .into() } } + +impl CliChain for Westmint { + const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; + + type KeyPair = sp_core::sr25519::Pair; + type MessagePayload = Vec; + + fn ss58_format() -> u16 { + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::SubstrateAccount, + ) + .into() + } +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 45d6f960aeb3b..c6b6375b051e0 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::cli::CliChain; +use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme}; use strum::{EnumString, EnumVariantNames}; +use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] #[strum(serialize_all = "kebab_case")] @@ -218,3 +221,137 @@ macro_rules! select_full_bridge { } }; } + +/// Minimal bridge representation that can be used from the CLI. +/// It connects a source chain to a target chain. +pub trait CliBridgeBase: Sized { + /// The source chain. + type Source: Chain + CliChain; + /// The target chain. + type Target: Chain + + TransactionSignScheme + + CliChain>; +} + +/// Bridge representation that can be used from the CLI. +pub trait CliBridge: CliBridgeBase { + /// Finality proofs synchronization pipeline. + type Finality: SubstrateFinalitySyncPipeline< + SourceChain = Self::Source, + TargetChain = Self::Target, + TransactionSignScheme = Self::Target, + >; +} + +//// `Millau` to `Rialto` bridge definition. +pub struct MillauToRialtoCliBridge {} + +impl CliBridgeBase for MillauToRialtoCliBridge { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; +} + +impl CliBridge for MillauToRialtoCliBridge { + type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; +} + +//// `Rialto` to `Millau` bridge definition. +pub struct RialtoToMillauCliBridge {} + +impl CliBridgeBase for RialtoToMillauCliBridge { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; +} + +impl CliBridge for RialtoToMillauCliBridge { + type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; +} + +//// `Westend` to `Millau` bridge definition. +pub struct WestendToMillauCliBridge {} + +impl CliBridgeBase for WestendToMillauCliBridge { + type Source = relay_westend_client::Westend; + type Target = relay_millau_client::Millau; +} + +impl CliBridge for WestendToMillauCliBridge { + type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; +} + +//// `Rococo` to `Wococo` bridge definition. +pub struct RococoToWococoCliBridge {} + +impl CliBridgeBase for RococoToWococoCliBridge { + type Source = relay_rococo_client::Rococo; + type Target = relay_wococo_client::Wococo; +} + +impl CliBridge for RococoToWococoCliBridge { + type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; +} + +//// `Wococo` to `Rococo` bridge definition. +pub struct WococoToRococoCliBridge {} + +impl CliBridgeBase for WococoToRococoCliBridge { + type Source = relay_wococo_client::Wococo; + type Target = relay_rococo_client::Rococo; +} + +impl CliBridge for WococoToRococoCliBridge { + type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; +} + +//// `Kusama` to `Polkadot` bridge definition. +pub struct KusamaToPolkadotCliBridge {} + +impl CliBridgeBase for KusamaToPolkadotCliBridge { + type Source = relay_kusama_client::Kusama; + type Target = relay_polkadot_client::Polkadot; +} + +impl CliBridge for KusamaToPolkadotCliBridge { + type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; +} + +//// `Polkadot` to `Kusama` bridge definition. +pub struct PolkadotToKusamaCliBridge {} + +impl CliBridgeBase for PolkadotToKusamaCliBridge { + type Source = relay_polkadot_client::Polkadot; + type Target = relay_kusama_client::Kusama; +} + +impl CliBridge for PolkadotToKusamaCliBridge { + type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; +} + +//// `Millau` to `RialtoParachain` bridge definition. +pub struct MillauToRialtoParachainCliBridge {} + +impl CliBridgeBase for MillauToRialtoParachainCliBridge { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_parachain_client::RialtoParachain; +} + +impl CliBridge for MillauToRialtoParachainCliBridge { + type Finality = + crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; +} + +//// `RialtoParachain` to `Millau` bridge definition. +pub struct RialtoParachainToMillauCliBridge {} + +impl CliBridgeBase for RialtoParachainToMillauCliBridge { + type Source = relay_rialto_parachain_client::RialtoParachain; + type Target = relay_millau_client::Millau; +} + +//// `WestendParachain` to `Millau` bridge definition. +pub struct WestmintToMillauCliBridge {} + +impl CliBridgeBase for WestmintToMillauCliBridge { + type Source = relay_westend_client::Westmint; + type Target = relay_millau_client::Millau; +} diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 63252382ec369..e8efcd503f5b4 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -14,15 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{SourceConnectionParams, TargetConnectionParams, TargetSigningParams}; -use bp_header_chain::InitializationData; +use async_trait::async_trait; + +use crate::cli::{ + bridge::{ + CliBridgeBase, KusamaToPolkadotCliBridge, MillauToRialtoCliBridge, + MillauToRialtoParachainCliBridge, PolkadotToKusamaCliBridge, RialtoToMillauCliBridge, + RococoToWococoCliBridge, WestendToMillauCliBridge, WococoToRococoCliBridge, + }, + SourceConnectionParams, TargetConnectionParams, TargetSigningParams, +}; use bp_runtime::Chain as ChainBase; use codec::Encode; -use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{ + AccountKeyPairOf, Chain, SignParam, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{Bytes, Pair}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; -use substrate_relay_helper::finality::engine::Grandpa as GrandpaFinalityEngine; +use substrate_relay_helper::finality::engine::{Engine, Grandpa as GrandpaFinalityEngine}; /// Initialize bridge pallet. #[derive(StructOpt)] @@ -52,198 +62,181 @@ pub enum InitBridgeName { MillauToRialtoParachain, } -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - InitBridgeName::MillauToRialto => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - rialto_runtime::SudoCall::sudo { - call: Box::new( - rialto_runtime::BridgeGrandpaMillauCall::initialize { init_data } - .into(), +#[async_trait] +trait BridgeInitializer: CliBridgeBase +where + ::AccountId: From< as Pair>::Public>, +{ + type Engine: Engine; + + /// Get the encoded call to init the bridge. + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call; + + /// Initialize the bridge. + async fn init_bridge(data: InitBridge) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let target_client = data.target.to_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + + let (spec_version, transaction_version) = target_client.simple_runtime_version().await?; + substrate_relay_helper::finality::initialize::initialize::( + source_client, + target_client.clone(), + target_sign.public().into(), + move |transaction_nonce, initialization_data| { + Ok(Bytes( + Self::Target::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: *target_client.genesis_hash(), + signer: target_sign, + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new( + Self::encode_init_bridge(initialization_data).into(), + transaction_nonce, ), - } - .into() - } - - $generic - }, - InitBridgeName::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - let initialize_call = millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >::initialize { - init_data, - }; - millau_runtime::SudoCall::sudo { call: Box::new(initialize_call.into()) }.into() - } - - $generic - }, - InitBridgeName::WestendToMillau => { - type Source = relay_westend_client::Westend; - type Target = relay_millau_client::Millau; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - // at Westend -> Millau initialization we're not using sudo, because otherwise - // our deployments may fail, because we need to initialize both Rialto -> Millau - // and Westend -> Millau bridge. => since there's single possible sudo account, - // one of transaction may fail with duplicate nonce error - millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >::initialize { - init_data, - } - .into() - } - - $generic + })? + .encode(), + )) }, - InitBridgeName::RococoToWococo => { - type Source = relay_rococo_client::Rococo; - type Target = relay_wococo_client::Wococo; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - relay_wococo_client::runtime::Call::BridgeGrandpaRococo( - relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize( - init_data, - ), - ) - } + ) + .await; - $generic - }, - InitBridgeName::WococoToRococo => { - type Source = relay_wococo_client::Wococo; - type Target = relay_rococo_client::Rococo; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - relay_rococo_client::runtime::Call::BridgeGrandpaWococo( - relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize( - init_data, - ), - ) - } + Ok(()) + } +} - $generic - }, - InitBridgeName::KusamaToPolkadot => { - type Source = relay_kusama_client::Kusama; - type Target = relay_polkadot_client::Polkadot; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize( - init_data, - ), - ) - } +impl BridgeInitializer for MillauToRialtoCliBridge { + type Engine = GrandpaFinalityEngine; - $generic - }, - InitBridgeName::PolkadotToKusama => { - type Source = relay_polkadot_client::Polkadot; - type Target = relay_kusama_client::Kusama; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize( - init_data, - ), - ) - } + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + rialto_runtime::SudoCall::sudo { + call: Box::new( + rialto_runtime::BridgeGrandpaMillauCall::initialize { init_data }.into(), + ), + } + .into() + } +} - $generic - }, - InitBridgeName::MillauToRialtoParachain => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_parachain_client::RialtoParachain; - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: InitializationData<::Header>, - ) -> ::Call { - let initialize_call = rialto_parachain_runtime::BridgeGrandpaCall::< - rialto_parachain_runtime::Runtime, - rialto_parachain_runtime::MillauGrandpaInstance, - >::initialize { - init_data, - }; - rialto_parachain_runtime::SudoCall::sudo { - call: Box::new(initialize_call.into()), - } - .into() - } - - $generic - }, +impl BridgeInitializer for MillauToRialtoParachainCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + let initialize_call = rialto_parachain_runtime::BridgeGrandpaCall::< + rialto_parachain_runtime::Runtime, + rialto_parachain_runtime::MillauGrandpaInstance, + >::initialize { + init_data, + }; + rialto_parachain_runtime::SudoCall::sudo { call: Box::new(initialize_call.into()) }.into() + } +} + +impl BridgeInitializer for RialtoToMillauCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + let initialize_call = millau_runtime::BridgeGrandpaCall::< + millau_runtime::Runtime, + millau_runtime::RialtoGrandpaInstance, + >::initialize { + init_data, + }; + millau_runtime::SudoCall::sudo { call: Box::new(initialize_call.into()) }.into() + } +} + +impl BridgeInitializer for WestendToMillauCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + // at Westend -> Millau initialization we're not using sudo, because otherwise + // our deployments may fail, because we need to initialize both Rialto -> Millau + // and Westend -> Millau bridge. => since there's single possible sudo account, + // one of transaction may fail with duplicate nonce error + millau_runtime::BridgeGrandpaCall::< + millau_runtime::Runtime, + millau_runtime::WestendGrandpaInstance, + >::initialize { + init_data, } - }; + .into() + } +} + +impl BridgeInitializer for RococoToWococoCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_wococo_client::runtime::Call::BridgeGrandpaRococo( + relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), + ) + } +} + +impl BridgeInitializer for WococoToRococoCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_rococo_client::runtime::Call::BridgeGrandpaWococo( + relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize(init_data), + ) + } +} + +impl BridgeInitializer for KusamaToPolkadotCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( + relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize(init_data), + ) + } +} + +impl BridgeInitializer for PolkadotToKusamaCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( + relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize(init_data), + ) + } } impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let target_client = self.target.to_client::().await?; - let target_sign = self.target_sign.to_keypair::()?; - - let (spec_version, transaction_version) = - target_client.simple_runtime_version().await?; - substrate_relay_helper::finality::initialize::initialize::( - source_client, - target_client.clone(), - target_sign.public().into(), - move |transaction_nonce, initialization_data| { - Ok(Bytes( - Target::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: *target_client.genesis_hash(), - signer: target_sign, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - encode_init_bridge(initialization_data).into(), - transaction_nonce, - ), - })? - .encode(), - )) - }, - ) - .await; - - Ok(()) - }) + match self.bridge { + InitBridgeName::MillauToRialto => MillauToRialtoCliBridge::init_bridge(self), + InitBridgeName::RialtoToMillau => RialtoToMillauCliBridge::init_bridge(self), + InitBridgeName::WestendToMillau => WestendToMillauCliBridge::init_bridge(self), + InitBridgeName::RococoToWococo => RococoToWococoCliBridge::init_bridge(self), + InitBridgeName::WococoToRococo => WococoToRococoCliBridge::init_bridge(self), + InitBridgeName::KusamaToPolkadot => KusamaToPolkadotCliBridge::init_bridge(self), + InitBridgeName::PolkadotToKusama => PolkadotToKusamaCliBridge::init_bridge(self), + InitBridgeName::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::init_bridge(self), + } + .await } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 59ab3a1a33e28..4ad43c3c24519 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, ChainBase}; +use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -21,6 +24,11 @@ use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; use crate::cli::{ + bridge::{ + CliBridge, KusamaToPolkadotCliBridge, MillauToRialtoCliBridge, + MillauToRialtoParachainCliBridge, PolkadotToKusamaCliBridge, RialtoToMillauCliBridge, + RococoToWococoCliBridge, WestendToMillauCliBridge, WococoToRococoCliBridge, + }, PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, }; @@ -58,101 +66,66 @@ pub enum RelayHeadersBridge { MillauToRialtoParachain, } -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - RelayHeadersBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; - type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; - - $generic - }, - RelayHeadersBridge::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; - type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; - - $generic - }, - RelayHeadersBridge::WestendToMillau => { - type Source = relay_westend_client::Westend; - type Target = relay_millau_client::Millau; - type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; - - $generic - }, - RelayHeadersBridge::RococoToWococo => { - type Source = relay_rococo_client::Rococo; - type Target = relay_wococo_client::Wococo; - type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; - - $generic - }, - RelayHeadersBridge::WococoToRococo => { - type Source = relay_wococo_client::Wococo; - type Target = relay_rococo_client::Rococo; - type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; - - $generic - }, - RelayHeadersBridge::KusamaToPolkadot => { - type Source = relay_kusama_client::Kusama; - type Target = relay_polkadot_client::Polkadot; - type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; - - $generic - }, - RelayHeadersBridge::PolkadotToKusama => { - type Source = relay_polkadot_client::Polkadot; - type Target = relay_kusama_client::Kusama; - type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; - - $generic - }, - RelayHeadersBridge::MillauToRialtoParachain => { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_parachain_client::RialtoParachain; - type Finality = crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; - - $generic - - }, - } - }; +#[async_trait] +trait HeadersRelayer: CliBridge +where + ::AccountId: From< as Pair>::Public>, +{ + /// Relay headers. + async fn relay_headers(data: RelayHeaders) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let target_client = data.target.to_client::().await?; + let target_transactions_mortality = data.target_sign.target_transactions_mortality; + let target_sign = data.target_sign.to_keypair::()?; + + let metrics_params: relay_utils::metrics::MetricsParams = data.prometheus_params.into(); + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + + let target_transactions_params = substrate_relay_helper::TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }; + Self::Finality::start_relay_guards( + &target_client, + &target_transactions_params, + data.target.can_start_version_guard(), + ) + .await?; + + substrate_relay_helper::finality::run::( + source_client, + target_client, + data.only_mandatory_headers, + target_transactions_params, + metrics_params, + ) + .await + } } +impl HeadersRelayer for MillauToRialtoCliBridge {} +impl HeadersRelayer for RialtoToMillauCliBridge {} +impl HeadersRelayer for WestendToMillauCliBridge {} +impl HeadersRelayer for RococoToWococoCliBridge {} +impl HeadersRelayer for WococoToRococoCliBridge {} +impl HeadersRelayer for KusamaToPolkadotCliBridge {} +impl HeadersRelayer for PolkadotToKusamaCliBridge {} +impl HeadersRelayer for MillauToRialtoParachainCliBridge {} + impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let target_client = self.target.to_client::().await?; - let target_transactions_mortality = self.target_sign.target_transactions_mortality; - let target_sign = self.target_sign.to_keypair::()?; - - let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); - GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - - let target_transactions_params = substrate_relay_helper::TransactionParams { - signer: target_sign, - mortality: target_transactions_mortality, - }; - Finality::start_relay_guards( - &target_client, - &target_transactions_params, - self.target.can_start_version_guard(), - ) - .await?; - - substrate_relay_helper::finality::run::( - source_client, - target_client, - self.only_mandatory_headers, - target_transactions_params, - metrics_params, - ) - .await - }) + match self.bridge { + RelayHeadersBridge::MillauToRialto => MillauToRialtoCliBridge::relay_headers(self), + RelayHeadersBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_headers(self), + RelayHeadersBridge::WestendToMillau => WestendToMillauCliBridge::relay_headers(self), + RelayHeadersBridge::RococoToWococo => RococoToWococoCliBridge::relay_headers(self), + RelayHeadersBridge::WococoToRococo => WococoToRococoCliBridge::relay_headers(self), + RelayHeadersBridge::KusamaToPolkadot => KusamaToPolkadotCliBridge::relay_headers(self), + RelayHeadersBridge::PolkadotToKusama => PolkadotToKusamaCliBridge::relay_headers(self), + RelayHeadersBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::relay_headers(self), + } + .await } } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 4714f1cc5a998..eb46909b3a1be 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -14,18 +14,29 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use async_trait::async_trait; use bp_polkadot_core::parachains::ParaId; -use parachains_relay::{parachains_loop::ParachainSyncParams, ParachainsPipeline}; +use pallet_bridge_parachains::RelayBlockNumber; +use parachains_relay::{ + parachains_loop::{ParachainSyncParams, SourceClient, TargetClient}, + ParachainsPipeline, +}; +use relay_substrate_client::{Chain, RelayChain}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ - parachains::{source::ParachainsSource, target::ParachainsTarget}, + parachains::{ + source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter, + SubstrateParachainsPipeline, + }, TransactionParams, }; use crate::cli::{ - PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, + bridge::{CliBridgeBase, RialtoParachainToMillauCliBridge, WestmintToMillauCliBridge}, + CliChain, PrometheusParams, SourceConnectionParams, TargetConnectionParams, + TargetSigningParams, }; /// Start parachain heads relayer process. @@ -52,57 +63,72 @@ pub enum RelayParachainsBridge { WestendToMillau, } -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - RelayParachainsBridge::RialtoToMillau => { - use crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau as Pipeline; +#[async_trait] +trait ParachainsRelayer: CliBridgeBase +where + ParachainsSource: SourceClient>, + ParachainsTarget: TargetClient>, +{ + type SourceRelay: Chain + CliChain + RelayChain; + type Pipeline: SubstrateParachainsPipeline< + SourceParachain = Self::Source, + TargetChain = Self::Target, + SourceRelayChain = Self::SourceRelay, + TransactionSignScheme = Self::Target, + > + ParachainsPipeline; - $generic - }, - RelayParachainsBridge::WestendToMillau => { - use crate::chains::westend_parachains_to_millau::WestendParachainsToMillau as Pipeline; + async fn relay_headers(data: RelayParachains) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let source_client = ParachainsSource::::new(source_client, None); + + let target_transaction_params = TransactionParams { + signer: data.target_sign.to_keypair::()?, + mortality: data.target_sign.target_transactions_mortality, + }; + let target_client = data.target.to_client::().await?; + let target_client = ParachainsTarget::::new( + target_client.clone(), + target_transaction_params, + ); + + let metrics_params: relay_utils::metrics::MetricsParams = data.prometheus_params.into(); + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - $generic + parachains_relay::parachains_loop::run( + source_client, + target_client, + ParachainSyncParams { + parachains: vec![ParaId(2000)], + stall_timeout: std::time::Duration::from_secs(60), + strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, }, - } - }; + metrics_params, + futures::future::pending(), + ) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} + +impl ParachainsRelayer for RialtoParachainToMillauCliBridge { + type SourceRelay = relay_rialto_client::Rialto; + type Pipeline = crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau; +} + +impl ParachainsRelayer for WestmintToMillauCliBridge { + type SourceRelay = relay_westend_client::Westend; + type Pipeline = crate::chains::westend_parachains_to_millau::WestendParachainsToMillau; } impl RelayParachains { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { - type SourceChain = ::SourceChain; - type TargetChain = ::TargetChain; - - let source_client = self.source.to_client::().await?; - let source_client = ParachainsSource::::new(source_client, None); - - let taret_transaction_params = TransactionParams { - signer: self.target_sign.to_keypair::()?, - mortality: self.target_sign.target_transactions_mortality, - }; - let target_client = self.target.to_client::().await?; - let target_client = - ParachainsTarget::::new(target_client.clone(), taret_transaction_params); - - let metrics_params: relay_utils::metrics::MetricsParams = self.prometheus_params.into(); - GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - - parachains_relay::parachains_loop::run( - source_client, - target_client, - ParachainSyncParams { - parachains: vec![ParaId(2000)], - stall_timeout: std::time::Duration::from_secs(60), - strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, - }, - metrics_params, - futures::future::pending(), - ) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - }) + match self.bridge { + RelayParachainsBridge::RialtoToMillau => + RialtoParachainToMillauCliBridge::relay_headers(self), + RelayParachainsBridge::WestendToMillau => + WestmintToMillauCliBridge::relay_headers(self), + } + .await } } From 132891bebb2465c89c8668d3156eb67c4fc4cbd9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 6 Jul 2022 11:23:43 +0300 Subject: [PATCH 0727/1210] Remove obsolete bridges (#1491) * remove Rococo<>Wococo bridge mentions * remove Kusama <> Polkadot bridge mentions * fmt * remove unneeded mocked runtimes && trait impls for obsolete bridges * remove unused deps --- relays/bin-substrate/Cargo.toml | 8 - relays/bin-substrate/src/chains/kusama.rs | 64 -- .../src/chains/kusama_headers_to_polkadot.rs | 129 ---- .../src/chains/kusama_messages_to_polkadot.rs | 79 --- relays/bin-substrate/src/chains/mod.rs | 110 ---- relays/bin-substrate/src/chains/polkadot.rs | 64 -- .../src/chains/polkadot_headers_to_kusama.rs | 92 --- .../src/chains/polkadot_messages_to_kusama.rs | 78 --- relays/bin-substrate/src/chains/rococo.rs | 60 -- .../src/chains/rococo_headers_to_wococo.rs | 60 -- .../src/chains/rococo_messages_to_wococo.rs | 63 -- relays/bin-substrate/src/chains/wococo.rs | 61 -- .../src/chains/wococo_headers_to_rococo.rs | 86 --- .../src/chains/wococo_messages_to_rococo.rs | 64 -- relays/bin-substrate/src/cli/bridge.rs | 136 ----- relays/bin-substrate/src/cli/init_bridge.rs | 61 +- relays/bin-substrate/src/cli/mod.rs | 7 - relays/bin-substrate/src/cli/reinit_bridge.rs | 556 ------------------ relays/bin-substrate/src/cli/relay_headers.rs | 17 +- .../src/cli/relay_headers_and_messages.rs | 212 +------ .../src/cli/resubmit_transactions.rs | 14 - relays/client-kusama/Cargo.toml | 9 - relays/client-kusama/src/lib.rs | 83 +-- relays/client-kusama/src/runtime.rs | 133 ----- relays/client-polkadot/Cargo.toml | 9 - relays/client-polkadot/src/lib.rs | 83 +-- relays/client-polkadot/src/runtime.rs | 133 ----- relays/client-rococo/Cargo.toml | 10 - relays/client-rococo/src/lib.rs | 83 +-- relays/client-rococo/src/runtime.rs | 112 ---- relays/client-wococo/Cargo.toml | 11 +- relays/client-wococo/src/lib.rs | 83 +-- relays/client-wococo/src/runtime.rs | 112 ---- relays/lib-substrate-relay/Cargo.toml | 1 + .../src/messages_target.rs | 5 +- 35 files changed, 24 insertions(+), 2864 deletions(-) delete mode 100644 relays/bin-substrate/src/chains/kusama.rs delete mode 100644 relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs delete mode 100644 relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs delete mode 100644 relays/bin-substrate/src/chains/polkadot.rs delete mode 100644 relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs delete mode 100644 relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs delete mode 100644 relays/bin-substrate/src/chains/rococo.rs delete mode 100644 relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs delete mode 100644 relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs delete mode 100644 relays/bin-substrate/src/chains/wococo.rs delete mode 100644 relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs delete mode 100644 relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs delete mode 100644 relays/bin-substrate/src/cli/reinit_bridge.rs delete mode 100644 relays/client-kusama/src/runtime.rs delete mode 100644 relays/client-polkadot/src/runtime.rs delete mode 100644 relays/client-rococo/src/runtime.rs delete mode 100644 relays/client-wococo/src/runtime.rs diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index c7204be3202da..ead0f664c073e 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -23,18 +23,14 @@ strum = { version = "0.21.0", features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } -bp-kusama = { path = "../../primitives/chain-kusama" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } -bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } -bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } @@ -43,13 +39,9 @@ pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } pallet-bridge-parachains = { path = "../../modules/parachains" } parachains-relay = { path = "../parachains" } -relay-kusama-client = { path = "../client-kusama" } relay-millau-client = { path = "../client-millau" } -relay-polkadot-client = { path = "../client-polkadot" } relay-rialto-client = { path = "../client-rialto" } relay-rialto-parachain-client = { path = "../client-rialto-parachain" } -relay-rococo-client = { path = "../client-rococo" } -relay-wococo-client = { path = "../client-wococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs deleted file mode 100644 index 2b18475d680ae..0000000000000 --- a/relays/bin-substrate/src/chains/kusama.rs +++ /dev/null @@ -1,64 +0,0 @@ -// 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 . - -use bp_messages::LaneId; -use bp_runtime::EncodedOrDecodedCall; -use relay_kusama_client::Kusama; -use relay_substrate_client::BalanceOf; -use sp_version::RuntimeVersion; - -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; - -impl CliEncodeMessage for Kusama { - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::KUSAMA_TO_POLKADOT_INDEX => - relay_kusama_client::runtime::Call::BridgePolkadotMessages( - relay_kusama_client::runtime::BridgePolkadotMessagesCall::send_message( - lane, payload, fee, - ), - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } -} - -impl CliChain for Kusama { - const RUNTIME_VERSION: RuntimeVersion = bp_kusama::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; - - fn ss58_format() -> u16 { - sp_core::crypto::Ss58AddressFormat::from( - sp_core::crypto::Ss58AddressFormatRegistry::KusamaAccount, - ) - .into() - } -} diff --git a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs deleted file mode 100644 index 97d2057209878..0000000000000 --- a/relays/bin-substrate/src/chains/kusama_headers_to_polkadot.rs +++ /dev/null @@ -1,129 +0,0 @@ -// 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 . - -//! Kusama-to-Polkadot headers sync entrypoint. - -use async_trait::async_trait; -use relay_polkadot_client::Polkadot; -use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, - TransactionParams, -}; - -/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat -/// relay as gone wild. -/// -/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 21 -/// DOT, and initial value of this constant was rounded up to 30 DOT. But for actual Kusama <> -/// Polkadot deployment we'll be using the same account for delivering finality (free for mandatory -/// headers) and messages. It means that we can't predict maximal loss. But to protect funds against -/// relay/deployment issues, let's limit it so something that is much larger than this estimation - -/// e.g. to 100 DOT. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1307 -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_polkadot::Balance = 100 * 10_000_000_000; - -/// Description of Kusama -> Polkadot finalized headers bridge. -#[derive(Clone, Debug)] -pub struct KusamaFinalityToPolkadot; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( - KusamaFinalityToPolkadot, - KusamaFinalityToPolkadotCallBuilder, - relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa, - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof -); - -#[async_trait] -impl SubstrateFinalitySyncPipeline for KusamaFinalityToPolkadot { - type SourceChain = relay_kusama_client::Kusama; - type TargetChain = Polkadot; - - type FinalityEngine = GrandpaFinalityEngine; - type SubmitFinalityProofCallBuilder = KusamaFinalityToPolkadotCallBuilder; - type TransactionSignScheme = Polkadot; - - async fn start_relay_guards( - target_client: &relay_substrate_client::Client, - transaction_params: &TransactionParams, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality::guards::start::( - target_client, - transaction_params, - enable_version_guard, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ) - .await - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use frame_support::weights::WeightToFeePolynomial; - use pallet_bridge_grandpa::weights::WeightInfo; - - pub fn compute_maximal_balance_decrease_per_day(expected_source_headers_per_day: u32) -> B - where - B: From + std::ops::Mul, - W: WeightToFeePolynomial, - { - // we assume that the GRANDPA is not lagging here => ancestry length will be near to 0 - // (let's round up to 2) - const AVG_VOTES_ANCESTRIES_LEN: u32 = 2; - // let's assume number of validators is 1024 (more than on any existing well-known chain - // atm) => number of precommits is *2/3 + 1 - const AVG_PRECOMMITS_LEN: u32 = 1024 * 2 / 3 + 1; - - // GRANDPA pallet weights. We're now using Rialto weights everywhere. - // - // Using Rialto runtime is slightly incorrect, because `DbWeight` of other runtimes may - // differ from the `DbWeight` of Rialto runtime. But now (and most probably forever) it is - // the same. - type GrandpaPalletWeights = - pallet_bridge_grandpa::weights::MillauWeight; - - // The following formula shall not be treated as super-accurate - guard is to protect from - // mad relays, not to protect from over-average loses. - - // increase number of headers a bit - let expected_source_headers_per_day = expected_source_headers_per_day * 110 / 100; - let single_source_header_submit_call_weight = GrandpaPalletWeights::submit_finality_proof( - AVG_VOTES_ANCESTRIES_LEN, - AVG_PRECOMMITS_LEN, - ); - // for simplicity - add extra weight for base tx fee + fee that is paid for the tx size + - // adjusted fee - let single_source_header_submit_tx_weight = single_source_header_submit_call_weight * 3 / 2; - let single_source_header_tx_cost = W::calc(&single_source_header_submit_tx_weight); - single_source_header_tx_cost * B::from(expected_source_headers_per_day) - } - - #[test] - fn maximal_balance_decrease_per_day_is_sane() { - // we expect Kusama -> Polkadot relay to be running in mandatory-headers-only mode - // => we expect single header for every Kusama session - let maximal_balance_decrease = compute_maximal_balance_decrease_per_day::< - bp_polkadot::Balance, - bp_polkadot::WeightToFee, - >(bp_kusama::DAYS / bp_kusama::SESSION_LENGTH + 1); - assert!( - MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, - "Maximal expected loss per day {} is larger than hardcoded {}", - maximal_balance_decrease, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } -} diff --git a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs deleted file mode 100644 index 9a71fbe3c6213..0000000000000 --- a/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ /dev/null @@ -1,79 +0,0 @@ -// 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 . - -//! Kusama-to-Polkadot messages sync entrypoint. - -use frame_support::weights::Weight; - -use messages_relay::relay_strategy::MixStrategy; -use relay_kusama_client::Kusama; -use relay_polkadot_client::Polkadot; -use substrate_relay_helper::messages_lane::SubstrateMessageLane; - -/// Description of Kusama -> Polkadot messages bridge. -#[derive(Clone, Debug)] -pub struct KusamaMessagesToPolkadot; -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( - KusamaMessagesToPolkadot, - KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder, - relay_polkadot_client::runtime::Call::BridgeKusamaMessages, - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof -); -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( - KusamaMessagesToPolkadot, - KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder, - relay_kusama_client::runtime::Call::BridgePolkadotMessages, - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof -); -substrate_relay_helper::generate_mocked_update_conversion_rate_call_builder!( - Kusama, - KusamaMessagesToPolkadotUpdateConversionRateCallBuilder, - relay_kusama_client::runtime::Call::BridgePolkadotMessages, - relay_kusama_client::runtime::BridgePolkadotMessagesCall::update_pallet_parameter, - relay_kusama_client::runtime::BridgePolkadotMessagesParameter::PolkadotToKusamaConversionRate -); - -impl SubstrateMessageLane for KusamaMessagesToPolkadot { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_polkadot::KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME); - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_kusama::POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME); - - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_kusama::TRANSACTION_PAYMENT_PALLET_NAME); - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_polkadot::TRANSACTION_PAYMENT_PALLET_NAME); - - type SourceChain = Kusama; - type TargetChain = Polkadot; - - type SourceTransactionSignScheme = Kusama; - type TargetTransactionSignScheme = Polkadot; - - type ReceiveMessagesProofCallBuilder = KusamaMessagesToPolkadotReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - KusamaMessagesToPolkadotReceiveMessagesDeliveryProofCallBuilder; - - type TargetToSourceChainConversionRateUpdateBuilder = - KusamaMessagesToPolkadotUpdateConversionRateCallBuilder; - - type RelayStrategy = MixStrategy; -} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 02e17c361d493..d3c1290d98dc4 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -16,33 +16,21 @@ //! Chain-specific relayer configuration. -pub mod kusama_headers_to_polkadot; -pub mod kusama_messages_to_polkadot; pub mod millau_headers_to_rialto; pub mod millau_headers_to_rialto_parachain; pub mod millau_messages_to_rialto; pub mod millau_messages_to_rialto_parachain; -pub mod polkadot_headers_to_kusama; -pub mod polkadot_messages_to_kusama; pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; pub mod rialto_parachain_messages_to_millau; pub mod rialto_parachains_to_millau; -pub mod rococo_headers_to_wococo; -pub mod rococo_messages_to_wococo; pub mod westend_headers_to_millau; pub mod westend_parachains_to_millau; -pub mod wococo_headers_to_rococo; -pub mod wococo_messages_to_rococo; -mod kusama; mod millau; -mod polkadot; mod rialto; mod rialto_parachain; -mod rococo; mod westend; -mod wococo; #[cfg(test)] mod tests { @@ -123,101 +111,3 @@ mod tests { ); } } - -#[cfg(test)] -mod rococo_tests { - use bp_header_chain::justification::GrandpaJustification; - use codec::Encode; - - #[test] - fn scale_compatibility_of_bridges_call() { - // given - let header = sp_runtime::generic::Header { - parent_hash: Default::default(), - number: Default::default(), - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: sp_runtime::generic::Digest { logs: vec![] }, - }; - - let justification = GrandpaJustification { - round: 0, - commit: finality_grandpa::Commit { - target_hash: Default::default(), - target_number: Default::default(), - precommits: vec![], - }, - votes_ancestries: vec![], - }; - - let actual = relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof( - Box::new(header.clone()), - justification.clone(), - ); - let expected = - millau_runtime::BridgeGrandpaCall::::submit_finality_proof { - finality_target: Box::new(header), - justification, - }; - - // when - let actual_encoded = actual.encode(); - let expected_encoded = expected.encode(); - - // then - assert_eq!( - actual_encoded, expected_encoded, - "\n\nEncoding difference.\nGot {:#?} \nExpected: {:#?}", - actual, expected - ); - } -} - -#[cfg(test)] -mod westend_tests { - use bp_header_chain::justification::GrandpaJustification; - use codec::Encode; - - #[test] - fn scale_compatibility_of_bridges_call() { - // given - let header = sp_runtime::generic::Header { - parent_hash: Default::default(), - number: Default::default(), - state_root: Default::default(), - extrinsics_root: Default::default(), - digest: sp_runtime::generic::Digest { logs: vec![] }, - }; - - let justification = GrandpaJustification { - round: 0, - commit: finality_grandpa::Commit { - target_hash: Default::default(), - target_number: Default::default(), - precommits: vec![], - }, - votes_ancestries: vec![], - }; - - let actual = relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof( - Box::new(header.clone()), - justification.clone(), - ); - let expected = - millau_runtime::BridgeGrandpaCall::::submit_finality_proof { - finality_target: Box::new(header), - justification, - }; - - // when - let actual_encoded = actual.encode(); - let expected_encoded = expected.encode(); - - // then - assert_eq!( - actual_encoded, expected_encoded, - "\n\nEncoding difference.\nGot {:#?} \nExpected: {:#?}", - actual, expected - ); - } -} diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs deleted file mode 100644 index 3ef7523f2a533..0000000000000 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ /dev/null @@ -1,64 +0,0 @@ -// 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 . - -use bp_messages::LaneId; -use bp_runtime::EncodedOrDecodedCall; -use relay_polkadot_client::Polkadot; -use relay_substrate_client::BalanceOf; -use sp_version::RuntimeVersion; - -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; - -impl CliEncodeMessage for Polkadot { - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::POLKADOT_TO_KUSAMA_INDEX => - relay_polkadot_client::runtime::Call::BridgeKusamaMessages( - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::send_message( - lane, payload, fee, - ), - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } -} - -impl CliChain for Polkadot { - const RUNTIME_VERSION: RuntimeVersion = bp_polkadot::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; - - fn ss58_format() -> u16 { - sp_core::crypto::Ss58AddressFormat::from( - sp_core::crypto::Ss58AddressFormatRegistry::PolkadotAccount, - ) - .into() - } -} diff --git a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs deleted file mode 100644 index a8b6ce07ab6c9..0000000000000 --- a/relays/bin-substrate/src/chains/polkadot_headers_to_kusama.rs +++ /dev/null @@ -1,92 +0,0 @@ -// 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 . - -//! Polkadot-to-Kusama headers sync entrypoint. - -use async_trait::async_trait; -use relay_kusama_client::Kusama; -use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, - TransactionParams, -}; - -/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat -/// relay as gone wild. -/// -/// Actual value, returned by `maximal_balance_decrease_per_day_is_sane` test is approximately 0.001 -/// KSM, and initial value of this constant was rounded up to 0.1 KSM. But for actual Kusama <> -/// Polkadot deployment we'll be using the same account for delivering finality (free for mandatory -/// headers) and messages. It means that we can't predict maximal loss. But to protect funds against -/// relay/deployment issues, let's limit it so something that is much larger than this estimation - -/// e.g. to 2 KSM. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1307 -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_kusama::Balance = 2 * 1_000_000_000_000; - -/// Description of Polkadot -> Kusama finalized headers bridge. -#[derive(Clone, Debug)] -pub struct PolkadotFinalityToKusama; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( - PolkadotFinalityToKusama, - PolkadotFinalityToKusamaCallBuilder, - relay_kusama_client::runtime::Call::BridgePolkadotGrandpa, - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof -); - -#[async_trait] -impl SubstrateFinalitySyncPipeline for PolkadotFinalityToKusama { - type SourceChain = relay_polkadot_client::Polkadot; - type TargetChain = Kusama; - - type FinalityEngine = GrandpaFinalityEngine; - type SubmitFinalityProofCallBuilder = PolkadotFinalityToKusamaCallBuilder; - type TransactionSignScheme = Kusama; - - async fn start_relay_guards( - target_client: &relay_substrate_client::Client, - transaction_params: &TransactionParams, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality::guards::start::( - target_client, - transaction_params, - enable_version_guard, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ) - .await - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::chains::kusama_headers_to_polkadot::tests::compute_maximal_balance_decrease_per_day; - - #[test] - fn maximal_balance_decrease_per_day_is_sane() { - // we expect Polkadot -> Kusama relay to be running in mandatory-headers-only mode - // => we expect single header for every Polkadot session - let maximal_balance_decrease = compute_maximal_balance_decrease_per_day::< - bp_kusama::Balance, - bp_kusama::WeightToFee, - >(bp_polkadot::DAYS / bp_polkadot::SESSION_LENGTH + 1); - assert!( - MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, - "Maximal expected loss per day {} is larger than hardcoded {}", - maximal_balance_decrease, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } -} diff --git a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs deleted file mode 100644 index 9c4a4640eb99d..0000000000000 --- a/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ /dev/null @@ -1,78 +0,0 @@ -// 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 . - -//! Polkadot-to-Kusama messages sync entrypoint. - -use frame_support::weights::Weight; -use messages_relay::relay_strategy::MixStrategy; -use relay_kusama_client::Kusama; -use relay_polkadot_client::Polkadot; -use substrate_relay_helper::messages_lane::SubstrateMessageLane; - -/// Description of Polkadot -> Kusama messages bridge. -#[derive(Clone, Debug)] -pub struct PolkadotMessagesToKusama; -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( - PolkadotMessagesToKusama, - PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder, - relay_kusama_client::runtime::Call::BridgePolkadotMessages, - relay_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof -); -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( - PolkadotMessagesToKusama, - PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder, - relay_polkadot_client::runtime::Call::BridgeKusamaMessages, - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof -); -substrate_relay_helper::generate_mocked_update_conversion_rate_call_builder!( - Polkadot, - PolkadotMessagesToKusamaUpdateConversionRateCallBuilder, - relay_polkadot_client::runtime::Call::BridgeKusamaMessages, - relay_polkadot_client::runtime::BridgeKusamaMessagesCall::update_pallet_parameter, - relay_polkadot_client::runtime::BridgeKusamaMessagesParameter::KusamaToPolkadotConversionRate -); - -impl SubstrateMessageLane for PolkadotMessagesToKusama { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_kusama::POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME); - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_polkadot::KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME); - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_kusama::POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME); - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_polkadot::KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME); - - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_polkadot::TRANSACTION_PAYMENT_PALLET_NAME); - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_kusama::TRANSACTION_PAYMENT_PALLET_NAME); - - type SourceChain = Polkadot; - type TargetChain = Kusama; - - type SourceTransactionSignScheme = Polkadot; - type TargetTransactionSignScheme = Kusama; - - type ReceiveMessagesProofCallBuilder = PolkadotMessagesToKusamaReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - PolkadotMessagesToKusamaReceiveMessagesDeliveryProofCallBuilder; - - type TargetToSourceChainConversionRateUpdateBuilder = - PolkadotMessagesToKusamaUpdateConversionRateCallBuilder; - - type RelayStrategy = MixStrategy; -} diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs deleted file mode 100644 index 0d2b800e79bf8..0000000000000 --- a/relays/bin-substrate/src/chains/rococo.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 . - -use bp_messages::LaneId; -use bp_runtime::EncodedOrDecodedCall; -use relay_rococo_client::Rococo; -use relay_substrate_client::BalanceOf; -use sp_version::RuntimeVersion; - -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; - -impl CliEncodeMessage for Rococo { - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::ROCOCO_TO_WOCOCO_INDEX => - relay_rococo_client::runtime::Call::BridgeWococoMessages( - relay_rococo_client::runtime::BridgeWococoMessagesCall::send_message( - lane, payload, fee, - ), - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } -} -impl CliChain for Rococo { - const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; - - fn ss58_format() -> u16 { - 42 - } -} diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs deleted file mode 100644 index 5e2b523000cf4..0000000000000 --- a/relays/bin-substrate/src/chains/rococo_headers_to_wococo.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 . - -//! Rococo-to-Wococo headers sync entrypoint. - -use crate::chains::wococo_headers_to_rococo::MAXIMAL_BALANCE_DECREASE_PER_DAY; - -use async_trait::async_trait; -use relay_wococo_client::Wococo; -use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, - TransactionParams, -}; - -/// Description of Rococo -> Wococo finalized headers bridge. -#[derive(Clone, Debug)] -pub struct RococoFinalityToWococo; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( - RococoFinalityToWococo, - RococoFinalityToWococoCallBuilder, - relay_wococo_client::runtime::Call::BridgeGrandpaRococo, - relay_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof -); - -#[async_trait] -impl SubstrateFinalitySyncPipeline for RococoFinalityToWococo { - type SourceChain = relay_rococo_client::Rococo; - type TargetChain = Wococo; - - type FinalityEngine = GrandpaFinalityEngine; - type SubmitFinalityProofCallBuilder = RococoFinalityToWococoCallBuilder; - type TransactionSignScheme = Wococo; - - async fn start_relay_guards( - target_client: &relay_substrate_client::Client, - transaction_params: &TransactionParams, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality::guards::start::( - target_client, - transaction_params, - enable_version_guard, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ) - .await - } -} diff --git a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs deleted file mode 100644 index 4e67c87fa8c45..0000000000000 --- a/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ /dev/null @@ -1,63 +0,0 @@ -// 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 . - -//! Rococo-to-Wococo messages sync entrypoint. - -use frame_support::weights::Weight; -use messages_relay::relay_strategy::MixStrategy; -use relay_rococo_client::Rococo; -use relay_wococo_client::Wococo; -use substrate_relay_helper::messages_lane::SubstrateMessageLane; - -/// Description of Rococo -> Wococo messages bridge. -#[derive(Clone, Debug)] -pub struct RococoMessagesToWococo; -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( - RococoMessagesToWococo, - RococoMessagesToWococoReceiveMessagesProofCallBuilder, - relay_wococo_client::runtime::Call::BridgeRococoMessages, - relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof -); -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( - RococoMessagesToWococo, - RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder, - relay_rococo_client::runtime::Call::BridgeWococoMessages, - relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof -); - -impl SubstrateMessageLane for RococoMessagesToWococo { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - - type SourceChain = Rococo; - type TargetChain = Wococo; - - type SourceTransactionSignScheme = Rococo; - type TargetTransactionSignScheme = Wococo; - - type ReceiveMessagesProofCallBuilder = RococoMessagesToWococoReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - RococoMessagesToWococoReceiveMessagesDeliveryProofCallBuilder; - - type TargetToSourceChainConversionRateUpdateBuilder = (); - - type RelayStrategy = MixStrategy; -} diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs deleted file mode 100644 index 8edb132a83abc..0000000000000 --- a/relays/bin-substrate/src/chains/wococo.rs +++ /dev/null @@ -1,61 +0,0 @@ -// 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 . - -use bp_messages::LaneId; -use bp_runtime::EncodedOrDecodedCall; -use relay_substrate_client::BalanceOf; -use relay_wococo_client::Wococo; -use sp_version::RuntimeVersion; - -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; - -impl CliEncodeMessage for Wococo { - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::WOCOCO_TO_ROCOCO_INDEX => - relay_wococo_client::runtime::Call::BridgeRococoMessages( - relay_wococo_client::runtime::BridgeRococoMessagesCall::send_message( - lane, payload, fee, - ), - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } -} - -impl CliChain for Wococo { - const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; - - type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; - - fn ss58_format() -> u16 { - 42 - } -} diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs deleted file mode 100644 index 58413a9d0d561..0000000000000 --- a/relays/bin-substrate/src/chains/wococo_headers_to_rococo.rs +++ /dev/null @@ -1,86 +0,0 @@ -// 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 . - -//! Wococo-to-Rococo headers sync entrypoint. - -use async_trait::async_trait; -use relay_rococo_client::Rococo; -use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, - TransactionParams, -}; - -/// Maximal saturating difference between `balance(now)` and `balance(now-24h)` to treat -/// relay as gone wild. -/// -/// See `maximal_balance_decrease_per_day_is_sane` test for details. -/// Note that this is in plancks, so this corresponds to `1500 UNITS`. -pub(crate) const MAXIMAL_BALANCE_DECREASE_PER_DAY: bp_rococo::Balance = 1_500_000_000_000_000; - -/// Description of Wococo -> Rococo finalized headers bridge. -#[derive(Clone, Debug)] -pub struct WococoFinalityToRococo; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( - WococoFinalityToRococo, - WococoFinalityToRococoCallBuilder, - relay_rococo_client::runtime::Call::BridgeGrandpaWococo, - relay_rococo_client::runtime::BridgeGrandpaWococoCall::submit_finality_proof -); - -#[async_trait] -impl SubstrateFinalitySyncPipeline for WococoFinalityToRococo { - type SourceChain = relay_wococo_client::Wococo; - type TargetChain = Rococo; - - type FinalityEngine = GrandpaFinalityEngine; - type SubmitFinalityProofCallBuilder = WococoFinalityToRococoCallBuilder; - type TransactionSignScheme = Rococo; - - async fn start_relay_guards( - target_client: &relay_substrate_client::Client, - transaction_params: &TransactionParams, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - substrate_relay_helper::finality::guards::start::( - target_client, - transaction_params, - enable_version_guard, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ) - .await - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::chains::kusama_headers_to_polkadot::tests::compute_maximal_balance_decrease_per_day; - - #[test] - fn maximal_balance_decrease_per_day_is_sane() { - // we expect Wococo -> Rococo relay to be running in all-headers mode - let maximal_balance_decrease = compute_maximal_balance_decrease_per_day::< - bp_kusama::Balance, - bp_kusama::WeightToFee, - >(bp_wococo::DAYS); - assert!( - MAXIMAL_BALANCE_DECREASE_PER_DAY >= maximal_balance_decrease, - "Maximal expected loss per day {} is larger than hardcoded {}", - maximal_balance_decrease, - MAXIMAL_BALANCE_DECREASE_PER_DAY, - ); - } -} diff --git a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs deleted file mode 100644 index 2c44803f2c06a..0000000000000 --- a/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ /dev/null @@ -1,64 +0,0 @@ -// 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 . - -//! Wococo-to-Rococo messages sync entrypoint. - -use frame_support::weights::Weight; - -use messages_relay::relay_strategy::MixStrategy; -use relay_rococo_client::Rococo; -use relay_wococo_client::Wococo; -use substrate_relay_helper::messages_lane::SubstrateMessageLane; - -/// Description of Wococo -> Rococo messages bridge. -#[derive(Clone, Debug)] -pub struct WococoMessagesToRococo; -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( - WococoMessagesToRococo, - WococoMessagesToRococoReceiveMessagesProofCallBuilder, - relay_rococo_client::runtime::Call::BridgeWococoMessages, - relay_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof -); -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( - WococoMessagesToRococo, - WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder, - relay_wococo_client::runtime::Call::BridgeRococoMessages, - relay_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof -); - -impl SubstrateMessageLane for WococoMessagesToRococo { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - - type SourceChain = Wococo; - type TargetChain = Rococo; - - type SourceTransactionSignScheme = Wococo; - type TargetTransactionSignScheme = Rococo; - - type ReceiveMessagesProofCallBuilder = WococoMessagesToRococoReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - WococoMessagesToRococoReceiveMessagesDeliveryProofCallBuilder; - - type TargetToSourceChainConversionRateUpdateBuilder = (); - - type RelayStrategy = MixStrategy; -} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index c6b6375b051e0..242c22647c194 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -25,10 +25,6 @@ use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; pub enum FullBridge { MillauToRialto, RialtoToMillau, - RococoToWococo, - WococoToRococo, - KusamaToPolkadot, - PolkadotToKusama, MillauToRialtoParachain, RialtoParachainToMillau, } @@ -39,10 +35,6 @@ impl FullBridge { match self { Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, - Self::RococoToWococo => ROCOCO_TO_WOCOCO_INDEX, - Self::WococoToRococo => WOCOCO_TO_ROCOCO_INDEX, - Self::KusamaToPolkadot => KUSAMA_TO_POLKADOT_INDEX, - Self::PolkadotToKusama => POLKADOT_TO_KUSAMA_INDEX, Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, } @@ -51,10 +43,6 @@ impl FullBridge { pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; -pub const ROCOCO_TO_WOCOCO_INDEX: u8 = 0; -pub const WOCOCO_TO_ROCOCO_INDEX: u8 = 0; -pub const KUSAMA_TO_POLKADOT_INDEX: u8 = 0; -pub const POLKADOT_TO_KUSAMA_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1; pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; @@ -104,82 +92,6 @@ macro_rules! select_full_bridge { $generic }, - FullBridge::RococoToWococo => { - type Source = relay_rococo_client::Rococo; - #[allow(dead_code)] - type Target = relay_wococo_client::Wococo; - - // Derive-account - #[allow(unused_imports)] - use bp_wococo::derive_account_from_rococo_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::rococo_messages_to_wococo::RococoMessagesToWococo as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_wococo::TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::WococoToRococo => { - type Source = relay_wococo_client::Wococo; - #[allow(dead_code)] - type Target = relay_rococo_client::Rococo; - - // Derive-account - #[allow(unused_imports)] - use bp_rococo::derive_account_from_wococo_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::wococo_messages_to_rococo::WococoMessagesToRococo as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_rococo::TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::KusamaToPolkadot => { - type Source = relay_kusama_client::Kusama; - #[allow(dead_code)] - type Target = relay_polkadot_client::Polkadot; - - // Derive-account - #[allow(unused_imports)] - use bp_polkadot::derive_account_from_kusama_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::kusama_messages_to_polkadot::KusamaMessagesToPolkadot as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_polkadot::TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::PolkadotToKusama => { - type Source = relay_polkadot_client::Polkadot; - #[allow(dead_code)] - type Target = relay_kusama_client::Kusama; - - // Derive-account - #[allow(unused_imports)] - use bp_kusama::derive_account_from_polkadot_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::polkadot_messages_to_kusama::PolkadotMessagesToKusama as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_kusama::TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, FullBridge::MillauToRialtoParachain => { type Source = relay_millau_client::Millau; #[allow(dead_code)] @@ -279,54 +191,6 @@ impl CliBridge for WestendToMillauCliBridge { type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; } -//// `Rococo` to `Wococo` bridge definition. -pub struct RococoToWococoCliBridge {} - -impl CliBridgeBase for RococoToWococoCliBridge { - type Source = relay_rococo_client::Rococo; - type Target = relay_wococo_client::Wococo; -} - -impl CliBridge for RococoToWococoCliBridge { - type Finality = crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo; -} - -//// `Wococo` to `Rococo` bridge definition. -pub struct WococoToRococoCliBridge {} - -impl CliBridgeBase for WococoToRococoCliBridge { - type Source = relay_wococo_client::Wococo; - type Target = relay_rococo_client::Rococo; -} - -impl CliBridge for WococoToRococoCliBridge { - type Finality = crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo; -} - -//// `Kusama` to `Polkadot` bridge definition. -pub struct KusamaToPolkadotCliBridge {} - -impl CliBridgeBase for KusamaToPolkadotCliBridge { - type Source = relay_kusama_client::Kusama; - type Target = relay_polkadot_client::Polkadot; -} - -impl CliBridge for KusamaToPolkadotCliBridge { - type Finality = crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot; -} - -//// `Polkadot` to `Kusama` bridge definition. -pub struct PolkadotToKusamaCliBridge {} - -impl CliBridgeBase for PolkadotToKusamaCliBridge { - type Source = relay_polkadot_client::Polkadot; - type Target = relay_kusama_client::Kusama; -} - -impl CliBridge for PolkadotToKusamaCliBridge { - type Finality = crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama; -} - //// `Millau` to `RialtoParachain` bridge definition. pub struct MillauToRialtoParachainCliBridge {} diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index e8efcd503f5b4..b3110e69ff349 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -18,9 +18,8 @@ use async_trait::async_trait; use crate::cli::{ bridge::{ - CliBridgeBase, KusamaToPolkadotCliBridge, MillauToRialtoCliBridge, - MillauToRialtoParachainCliBridge, PolkadotToKusamaCliBridge, RialtoToMillauCliBridge, - RococoToWococoCliBridge, WestendToMillauCliBridge, WococoToRococoCliBridge, + CliBridgeBase, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, + RialtoToMillauCliBridge, WestendToMillauCliBridge, }, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, }; @@ -55,10 +54,6 @@ pub enum InitBridgeName { MillauToRialto, RialtoToMillau, WestendToMillau, - RococoToWococo, - WococoToRococo, - KusamaToPolkadot, - PolkadotToKusama, MillauToRialtoParachain, } @@ -175,54 +170,6 @@ impl BridgeInitializer for WestendToMillauCliBridge { } } -impl BridgeInitializer for RococoToWococoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_wococo_client::runtime::Call::BridgeGrandpaRococo( - relay_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), - ) - } -} - -impl BridgeInitializer for WococoToRococoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_rococo_client::runtime::Call::BridgeGrandpaWococo( - relay_rococo_client::runtime::BridgeGrandpaWococoCall::initialize(init_data), - ) - } -} - -impl BridgeInitializer for KusamaToPolkadotCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize(init_data), - ) - } -} - -impl BridgeInitializer for PolkadotToKusamaCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize(init_data), - ) - } -} - impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { @@ -230,10 +177,6 @@ impl InitBridge { InitBridgeName::MillauToRialto => MillauToRialtoCliBridge::init_bridge(self), InitBridgeName::RialtoToMillau => RialtoToMillauCliBridge::init_bridge(self), InitBridgeName::WestendToMillau => WestendToMillauCliBridge::init_bridge(self), - InitBridgeName::RococoToWococo => RococoToWococoCliBridge::init_bridge(self), - InitBridgeName::WococoToRococo => WococoToRococoCliBridge::init_bridge(self), - InitBridgeName::KusamaToPolkadot => KusamaToPolkadotCliBridge::init_bridge(self), - InitBridgeName::PolkadotToKusama => PolkadotToKusamaCliBridge::init_bridge(self), InitBridgeName::MillauToRialtoParachain => MillauToRialtoParachainCliBridge::init_bridge(self), } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 5061c70eb7840..6f394092e14ad 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -33,7 +33,6 @@ pub(crate) mod send_message; mod init_bridge; mod register_parachain; -mod reinit_bridge; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; @@ -70,11 +69,6 @@ pub enum Command { /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. InitBridge(init_bridge::InitBridge), - /// Reinitialize on-chain bridge pallet with current header data. - /// - /// Sends all missing mandatory headers to bootstrap the bridge with current finalized block - /// data. - ReinitBridge(reinit_bridge::ReinitBridge), /// Send custom message over the bridge. /// /// Allows interacting with the bridge by sending messages over `Messages` component. @@ -117,7 +111,6 @@ impl Command { Self::RelayMessages(arg) => arg.run().await?, Self::RelayHeadersAndMessages(arg) => arg.run().await?, Self::InitBridge(arg) => arg.run().await?, - Self::ReinitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, Self::EstimateFee(arg) => arg.run().await?, Self::ResubmitTransactions(arg) => arg.run().await?, diff --git a/relays/bin-substrate/src/cli/reinit_bridge.rs b/relays/bin-substrate/src/cli/reinit_bridge.rs deleted file mode 100644 index 484fc6ee6340e..0000000000000 --- a/relays/bin-substrate/src/cli/reinit_bridge.rs +++ /dev/null @@ -1,556 +0,0 @@ -// 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 . - -use crate::{ - chains::{ - kusama_headers_to_polkadot::KusamaFinalityToPolkadot, - polkadot_headers_to_kusama::PolkadotFinalityToKusama, - }, - cli::{ - register_parachain::wait_until_transaction_is_finalized, SourceConnectionParams, - TargetConnectionParams, TargetSigningParams, - }, -}; -use bp_runtime::Chain; -use codec::Encode; -use finality_relay::{SourceClient, SourceHeader}; -use frame_support::weights::Weight; -use num_traits::One; -use pallet_bridge_grandpa::weights::WeightInfo; -use relay_substrate_client::{ - AccountIdOf, BlockNumberOf, Chain as _, Client, Error as SubstrateError, HeaderOf, SignParam, - SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{Bytes, Pair}; -use std::convert::{TryFrom, TryInto}; -use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; -use substrate_relay_helper::{ - finality::{ - source::{SubstrateFinalityProof, SubstrateFinalitySource}, - target::SubstrateFinalityTarget, - SubstrateFinalitySyncPipeline, - }, - messages_source::read_client_state, - TransactionParams, -}; - -/// Reinitialize bridge pallet. -#[derive(Debug, PartialEq, Eq, StructOpt)] -pub struct ReinitBridge { - /// A bridge instance to reinitialize. - #[structopt(possible_values = ReinitBridgeName::VARIANTS, case_insensitive = true)] - bridge: ReinitBridgeName, - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, -} - -#[derive(Debug, EnumString, EnumVariantNames, PartialEq, Eq)] -#[strum(serialize_all = "kebab_case")] -/// Bridge to initialize. -pub enum ReinitBridgeName { - KusamaToPolkadot, - PolkadotToKusama, -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - ReinitBridgeName::KusamaToPolkadot => { - use relay_polkadot_client::runtime; - - type Finality = KusamaFinalityToPolkadot; - type Call = runtime::Call; - - fn submit_finality_proof_call( - header_and_proof: HeaderAndProof, - ) -> runtime::Call { - runtime::Call::BridgeKusamaGrandpa( - runtime::BridgeKusamaGrandpaCall::submit_finality_proof( - Box::new(header_and_proof.0.into_inner()), - header_and_proof.1, - ), - ) - } - - fn set_pallet_operation_mode_call(operational: bool) -> runtime::Call { - runtime::Call::BridgeKusamaGrandpa( - runtime::BridgeKusamaGrandpaCall::set_operational(operational), - ) - } - - fn batch_all_call(calls: Vec) -> runtime::Call { - runtime::Call::Utility(runtime::UtilityCall::batch_all(calls)) - } - - $generic - }, - ReinitBridgeName::PolkadotToKusama => { - use relay_kusama_client::runtime; - - type Finality = PolkadotFinalityToKusama; - type Call = runtime::Call; - - fn submit_finality_proof_call( - header_and_proof: HeaderAndProof, - ) -> runtime::Call { - runtime::Call::BridgePolkadotGrandpa( - runtime::BridgePolkadotGrandpaCall::submit_finality_proof( - Box::new(header_and_proof.0.into_inner()), - header_and_proof.1, - ), - ) - } - - fn set_pallet_operation_mode_call(operational: bool) -> runtime::Call { - runtime::Call::BridgePolkadotGrandpa( - runtime::BridgePolkadotGrandpaCall::set_operational(operational), - ) - } - - fn batch_all_call(calls: Vec) -> runtime::Call { - runtime::Call::Utility(runtime::UtilityCall::batch_all(calls)) - } - - $generic - }, - } - }; -} - -impl ReinitBridge { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.bridge, { - type Source = ::SourceChain; - type Target = ::TargetChain; - - let source_client = self.source.to_client::().await?; - let target_client = self.target.to_client::().await?; - let target_sign = self.target_sign.to_keypair::()?; - let transaction_params = TransactionParams { - signer: target_sign, - mortality: self.target_sign.target_transactions_mortality, - }; - - let finality_source = - SubstrateFinalitySource::::new(source_client.clone(), None); - let finality_target = SubstrateFinalityTarget::::new( - target_client.clone(), - transaction_params.clone(), - ); - - // this subcommand assumes that the pallet at the target chain is halted - ensure_pallet_operating_mode(&finality_target, false).await?; - - // we can't call `finality_target.best_finalized_source_block_id()`, because pallet is - // halted and the call will fail => just use what it uses internally - let current_number = - best_source_block_number_at_target::(&target_client).await?; - let target_number = finality_source.best_finalized_block_number().await?; - log::info!( - target: "bridge", - "Best finalized {} header: at {}: {}, at {}: {}", - Source::NAME, - Source::NAME, - target_number, - Target::NAME, - current_number, - ); - - // prepare list of mandatory headers from the range `(current_number; target_number]` - let headers_to_submit = find_mandatory_headers_in_range( - &finality_source, - (current_number + 1, target_number), - ) - .await?; - let latest_mandatory_header_number = headers_to_submit.last().map(|(h, _)| h.number()); - log::info!( - target: "bridge", - "Missing {} mandatory {} headers at {}", - headers_to_submit.len(), - Source::NAME, - Target::NAME, - ); - - // split all mandatory headers into batches - let headers_batches = - make_mandatory_headers_batches::(headers_to_submit, |(_, proof)| { - // we don't have an access to the Kusama/Polkadot chain runtimes here, so we'll - // be using Millau weights. It isn't super-critical, unless real weights are - // magnitude higher or so - pallet_bridge_grandpa::weights::MillauWeight::::submit_finality_proof( - proof.commit.precommits.len().try_into().unwrap_or(u32::MAX), - proof.votes_ancestries.len().try_into().unwrap_or(u32::MAX), - ) - }); - log::info!( - target: "bridge", - "We're going to submit {} transactions to {} node", - headers_batches.len(), - Target::NAME, - ); - - // each batch is submitted as a separate transaction - let signer_account_id: AccountIdOf = transaction_params.signer.public().into(); - let genesis_hash = *target_client.genesis_hash(); - let (spec_version, transaction_version) = - target_client.simple_runtime_version().await?; - let last_batch_index = headers_batches.len() - 1; - for (i, headers_batch) in headers_batches.into_iter().enumerate() { - let is_last_batch = i == last_batch_index; - let expected_number = - headers_batch.last().expect("all batches are non-empty").0.number(); - let transaction_params = transaction_params.clone(); - log::info!( - target: "bridge", - "Going to submit transaction that updates best {} header at {} to {}", - Source::NAME, - Target::NAME, - expected_number, - ); - - // prepare `batch_all` call - let mut batch_calls = Vec::with_capacity(headers_batch.len() + 2); - // the first call is always resumes pallet operation - batch_calls.push(set_pallet_operation_mode_call(true)); - // followed by submit-finality-proofs calls - for header_and_proof in headers_batch { - batch_calls.push(submit_finality_proof_call(header_and_proof)); - } - // if it isn't the last batch, we shall halt pallet again - if !is_last_batch { - batch_calls.push(set_pallet_operation_mode_call(false)); - } - let submit_batch_call = batch_all_call(batch_calls); - - let batch_transaction_events = target_client - .submit_and_watch_signed_extrinsic( - signer_account_id.clone(), - move |best_block_id, transaction_nonce| { - Ok(Bytes( - Target::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer.clone(), - era: TransactionEra::new( - best_block_id, - transaction_params.mortality, - ), - unsigned: UnsignedTransaction::new( - submit_batch_call.into(), - transaction_nonce, - ), - })? - .encode(), - )) - }, - ) - .await?; - wait_until_transaction_is_finalized::(batch_transaction_events).await?; - - // verify that the best finalized header at target has been updated - let current_number = - best_source_block_number_at_target::(&target_client).await?; - if current_number != expected_number { - return Err(anyhow::format_err!( - "Transaction has failed to update best {} header at {} to {}. It is {}", - Source::NAME, - Target::NAME, - expected_number, - current_number, - )) - } - - // verify that the pallet is still halted (or operational if it is the last batch) - ensure_pallet_operating_mode(&finality_target, is_last_batch).await?; - } - - if let Some(latest_mandatory_header_number) = latest_mandatory_header_number { - log::info!( - target: "bridge", - "Successfully updated best {} header at {} to {}. Pallet is now operational", - Source::NAME, - Target::NAME, - latest_mandatory_header_number, - ); - } - - Ok(()) - }) - } -} - -/// Mandatory header and its finality proof. -type HeaderAndProof

= ( - SyncHeader::SourceChain>>, - SubstrateFinalityProof

, -); -/// Vector of mandatory headers and their finality proofs. -type HeadersAndProofs

= Vec>; - -/// Returns best finalized source header number known to the bridge GRANDPA pallet at the target -/// chain. -/// -/// This function works even if bridge GRANDPA pallet at the target chain is halted. -async fn best_source_block_number_at_target( - target_client: &Client, -) -> anyhow::Result> { - Ok(read_client_state::( - target_client, - None, - P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, - ) - .await? - .best_finalized_peer_at_best_self - .0) -} - -/// Verify that the bridge GRANDPA pallet at the target chain is either halted, or operational. -async fn ensure_pallet_operating_mode( - finality_target: &SubstrateFinalityTarget

, - operational: bool, -) -> anyhow::Result<()> { - match (operational, finality_target.ensure_pallet_active().await) { - (true, Ok(())) => Ok(()), - (false, Err(SubstrateError::BridgePalletIsHalted)) => Ok(()), - _ => Err(anyhow::format_err!( - "Bridge GRANDPA pallet at {} is expected to be {}, but it isn't", - P::TargetChain::NAME, - if operational { "operational" } else { "halted" }, - )), - } -} - -/// Returns list of all mandatory headers in given range. -async fn find_mandatory_headers_in_range( - finality_source: &SubstrateFinalitySource

, - range: (BlockNumberOf, BlockNumberOf), -) -> anyhow::Result> { - let mut mandatory_headers = Vec::new(); - let mut current = range.0; - while current <= range.1 { - let (header, proof) = finality_source.header_and_finality_proof(current).await?; - if header.is_mandatory() { - match proof { - Some(proof) => mandatory_headers.push((header, proof)), - None => - return Err(anyhow::format_err!( - "Missing GRANDPA justification for {} header {}", - P::SourceChain::NAME, - current, - )), - } - } - - current += One::one(); - } - - Ok(mandatory_headers) -} - -/// Given list of mandatory headers, prepare batches of headers, so that every batch may fit into -/// single transaction. -fn make_mandatory_headers_batches< - P: SubstrateFinalitySyncPipeline, - F: Fn(&HeaderAndProof

) -> Weight, ->( - mut headers_to_submit: HeadersAndProofs

, - submit_header_weight: F, -) -> Vec> { - // now that we have all mandatory headers, let's prepare transactions - // (let's keep all our transactions below 2/3 of max tx size/weight to have some reserve - // for utility overhead + for halting transaction) - let maximal_tx_size = P::TargetChain::max_extrinsic_size() * 2 / 3; - let maximal_tx_weight = P::TargetChain::max_extrinsic_weight() * 2 / 3; - let mut current_batch_size: u32 = 0; - let mut current_batch_weight: Weight = 0; - let mut batches = Vec::new(); - let mut i = 0; - while i < headers_to_submit.len() { - let header_and_proof_size = - headers_to_submit[i].0.encode().len() + headers_to_submit[i].1.encode().len(); - let header_and_proof_weight = submit_header_weight(&headers_to_submit[i]); - - let new_batch_size = current_batch_size - .saturating_add(u32::try_from(header_and_proof_size).unwrap_or(u32::MAX)); - let new_batch_weight = current_batch_weight.saturating_add(header_and_proof_weight); - - let is_exceeding_tx_size = new_batch_size > maximal_tx_size; - let is_exceeding_tx_weight = new_batch_weight > maximal_tx_weight; - let is_new_batch_required = is_exceeding_tx_size || is_exceeding_tx_weight; - - if is_new_batch_required { - // if `i` is 0 and we're here, it is a weird situation: even single header submission is - // larger than we've planned for a bunch of headers. Let's be optimistic and hope that - // the tx will still succeed. - let spit_off_index = std::cmp::max(i, 1); - let remaining_headers_to_submit = headers_to_submit.split_off(spit_off_index); - batches.push(headers_to_submit); - - // we'll reiterate the same header again => so set `current_*` to zero - current_batch_size = 0; - current_batch_weight = 0; - headers_to_submit = remaining_headers_to_submit; - i = 0; - } else { - current_batch_size = new_batch_size; - current_batch_weight = new_batch_weight; - i += 1; - } - } - if !headers_to_submit.is_empty() { - batches.push(headers_to_submit); - } - batches -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams, TargetRuntimeVersionParams}; - use bp_header_chain::justification::GrandpaJustification; - use bp_test_utils::{make_default_justification, test_header}; - use relay_polkadot_client::Polkadot; - use sp_runtime::{traits::Header as _, DigestItem}; - - fn make_header_and_justification( - i: u32, - size: u32, - ) -> (SyncHeader, GrandpaJustification) { - let size = size as usize; - let mut header: bp_kusama::Header = test_header(i); - let justification = make_default_justification(&header); - let actual_size = header.encode().len() + justification.encode().len(); - // additional digest means some additional bytes, so let's decrease `additional_digest_size` - // a bit - let additional_digest_size = size.saturating_sub(actual_size).saturating_sub(100); - header.digest_mut().push(DigestItem::Other(vec![0u8; additional_digest_size])); - let justification = make_default_justification(&header); - println!("{} {}", size, header.encode().len() + justification.encode().len()); - (header.into(), justification) - } - - #[test] - fn should_parse_cli_options() { - // when - let res = ReinitBridge::from_iter(vec![ - "reinit-bridge", - "kusama-to-polkadot", - "--source-host", - "127.0.0.1", - "--source-port", - "42", - "--target-host", - "127.0.0.1", - "--target-port", - "43", - "--target-signer", - "//Alice", - ]); - - // then - assert_eq!( - res, - ReinitBridge { - bridge: ReinitBridgeName::KusamaToPolkadot, - source: SourceConnectionParams { - source_host: "127.0.0.1".into(), - source_port: 42, - source_secure: false, - source_runtime_version: SourceRuntimeVersionParams { - source_version_mode: RuntimeVersionType::Bundle, - source_spec_version: None, - source_transaction_version: None, - } - }, - target: TargetConnectionParams { - target_host: "127.0.0.1".into(), - target_port: 43, - target_secure: false, - target_runtime_version: TargetRuntimeVersionParams { - target_version_mode: RuntimeVersionType::Bundle, - target_spec_version: None, - target_transaction_version: None, - } - }, - target_sign: TargetSigningParams { - target_signer: Some("//Alice".into()), - target_signer_password: None, - target_signer_file: None, - target_signer_password_file: None, - target_transactions_mortality: None, - }, - } - ); - } - - #[test] - fn make_mandatory_headers_batches_and_empty_headers() { - let batches = make_mandatory_headers_batches::(vec![], |_| 0); - assert!(batches.is_empty()); - } - - #[test] - fn make_mandatory_headers_batches_with_single_batch() { - let headers_to_submit = - vec![make_header_and_justification(10, Polkadot::max_extrinsic_size() / 3)]; - let batches = - make_mandatory_headers_batches::(headers_to_submit, |_| 0); - assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![1],); - } - - #[test] - fn make_mandatory_headers_batches_group_by_size() { - let headers_to_submit = vec![ - make_header_and_justification(10, Polkadot::max_extrinsic_size() / 3), - make_header_and_justification(20, Polkadot::max_extrinsic_size() / 3), - make_header_and_justification(30, Polkadot::max_extrinsic_size() * 2 / 3), - make_header_and_justification(40, Polkadot::max_extrinsic_size()), - ]; - let batches = - make_mandatory_headers_batches::(headers_to_submit, |_| 0); - assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![2, 1, 1],); - } - - #[test] - fn make_mandatory_headers_batches_group_by_weight() { - let headers_to_submit = vec![ - make_header_and_justification(10, 0), - make_header_and_justification(20, 0), - make_header_and_justification(30, 0), - make_header_and_justification(40, 0), - ]; - let batches = make_mandatory_headers_batches::( - headers_to_submit, - |(header, _)| { - if header.number() == 10 || header.number() == 20 { - Polkadot::max_extrinsic_weight() / 3 - } else if header.number() == 30 { - Polkadot::max_extrinsic_weight() * 2 / 3 - } else { - Polkadot::max_extrinsic_weight() - } - }, - ); - assert_eq!(batches.into_iter().map(|x| x.len()).collect::>(), vec![2, 1, 1],); - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 4ad43c3c24519..25bb3440c6c8f 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -25,9 +25,8 @@ use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; use crate::cli::{ bridge::{ - CliBridge, KusamaToPolkadotCliBridge, MillauToRialtoCliBridge, - MillauToRialtoParachainCliBridge, PolkadotToKusamaCliBridge, RialtoToMillauCliBridge, - RococoToWococoCliBridge, WestendToMillauCliBridge, WococoToRococoCliBridge, + CliBridge, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, + RialtoToMillauCliBridge, WestendToMillauCliBridge, }, PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, }; @@ -59,10 +58,6 @@ pub enum RelayHeadersBridge { MillauToRialto, RialtoToMillau, WestendToMillau, - RococoToWococo, - WococoToRococo, - KusamaToPolkadot, - PolkadotToKusama, MillauToRialtoParachain, } @@ -106,10 +101,6 @@ where impl HeadersRelayer for MillauToRialtoCliBridge {} impl HeadersRelayer for RialtoToMillauCliBridge {} impl HeadersRelayer for WestendToMillauCliBridge {} -impl HeadersRelayer for RococoToWococoCliBridge {} -impl HeadersRelayer for WococoToRococoCliBridge {} -impl HeadersRelayer for KusamaToPolkadotCliBridge {} -impl HeadersRelayer for PolkadotToKusamaCliBridge {} impl HeadersRelayer for MillauToRialtoParachainCliBridge {} impl RelayHeaders { @@ -119,10 +110,6 @@ impl RelayHeaders { RelayHeadersBridge::MillauToRialto => MillauToRialtoCliBridge::relay_headers(self), RelayHeadersBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_headers(self), RelayHeadersBridge::WestendToMillau => WestendToMillauCliBridge::relay_headers(self), - RelayHeadersBridge::RococoToWococo => RococoToWococoCliBridge::relay_headers(self), - RelayHeadersBridge::WococoToRococo => WococoToRococoCliBridge::relay_headers(self), - RelayHeadersBridge::KusamaToPolkadot => KusamaToPolkadotCliBridge::relay_headers(self), - RelayHeadersBridge::PolkadotToKusama => PolkadotToKusamaCliBridge::relay_headers(self), RelayHeadersBridge::MillauToRialtoParachain => MillauToRialtoParachainCliBridge::relay_headers(self), } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 51c863080fd50..3fb84caed2c1e 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -28,15 +28,14 @@ use strum::VariantNames; use async_std::sync::Arc; use bp_polkadot_core::parachains::ParaHash; -use codec::Encode; use messages_relay::relay_strategy::MixStrategy; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, ChainRuntimeVersion, Client, - SignParam, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, ChainRuntimeVersion, Client, + TransactionSignScheme, }; use relay_utils::metrics::MetricsParams; -use sp_core::{Bytes, Pair}; +use sp_core::Pair; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, messages_lane::MessagesRelayParams, @@ -68,8 +67,6 @@ pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), - RococoWococo(RococoWococoHeadersAndMessages), - KusamaPolkadot(KusamaPolkadotHeadersAndMessages), } /// Parameters that have the same names across all bridges. @@ -309,168 +306,6 @@ macro_rules! select_bridge { Err(anyhow::format_err!("Account creation is not supported by this bridge")) } - $generic - }, - RelayHeadersAndMessages::RococoWococo(_) => { - type Params = RococoWococoHeadersAndMessages; - - type Left = relay_rococo_client::Rococo; - type Right = relay_wococo_client::Wococo; - - type LeftAccountIdConverter = bp_rococo::AccountIdConverter; - type RightAccountIdConverter = bp_wococo::AccountIdConverter; - - use crate::chains::{ - rococo_messages_to_wococo::RococoMessagesToWococo as LeftToRightMessageLane, - wococo_messages_to_rococo::WococoMessagesToRococo as RightToLeftMessageLane, - }; - - async fn start_on_demand_relays( - params: &Params, - left_client: Client, - right_client: Client, - at_left_relay_accounts: &mut Vec>>, - at_right_relay_accounts: &mut Vec>>, - ) -> anyhow::Result<( - Arc>>, - Arc>>, - )> { - start_on_demand_relay_to_relay::< - Left, - Right, - crate::chains::rococo_headers_to_wococo::RococoFinalityToWococo, - crate::chains::wococo_headers_to_rococo::WococoFinalityToRococo, - >( - left_client, - right_client, - params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, - params.right_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, - params.shared.only_mandatory_headers, - params.shared.only_mandatory_headers, - params.left.can_start_version_guard(), - params.right.can_start_version_guard(), - at_left_relay_accounts, - at_right_relay_accounts, - ).await - } - - async fn left_create_account( - left_client: Client, - left_sign: ::AccountKeyPair, - account_id: AccountIdOf, - ) -> anyhow::Result<()> { - submit_signed_extrinsic( - left_client, - left_sign, - relay_rococo_client::runtime::Call::Balances( - relay_rococo_client::runtime::BalancesCall::transfer( - bp_rococo::AccountAddress::Id(account_id), - bp_rococo::EXISTENTIAL_DEPOSIT.into(), - ), - ), - ) - .await - } - - async fn right_create_account( - right_client: Client, - right_sign: ::AccountKeyPair, - account_id: AccountIdOf, - ) -> anyhow::Result<()> { - submit_signed_extrinsic( - right_client, - right_sign, - relay_wococo_client::runtime::Call::Balances( - relay_wococo_client::runtime::BalancesCall::transfer( - bp_wococo::AccountAddress::Id(account_id), - bp_wococo::EXISTENTIAL_DEPOSIT.into(), - ), - ), - ) - .await - } - - $generic - }, - RelayHeadersAndMessages::KusamaPolkadot(_) => { - type Params = KusamaPolkadotHeadersAndMessages; - - type Left = relay_kusama_client::Kusama; - type Right = relay_polkadot_client::Polkadot; - - type LeftAccountIdConverter = bp_kusama::AccountIdConverter; - type RightAccountIdConverter = bp_polkadot::AccountIdConverter; - - use crate::chains::{ - kusama_messages_to_polkadot::KusamaMessagesToPolkadot as LeftToRightMessageLane, - polkadot_messages_to_kusama::PolkadotMessagesToKusama as RightToLeftMessageLane, - }; - - async fn start_on_demand_relays( - params: &Params, - left_client: Client, - right_client: Client, - at_left_relay_accounts: &mut Vec>>, - at_right_relay_accounts: &mut Vec>>, - ) -> anyhow::Result<( - Arc>>, - Arc>>, - )> { - start_on_demand_relay_to_relay::< - Left, - Right, - crate::chains::kusama_headers_to_polkadot::KusamaFinalityToPolkadot, - crate::chains::polkadot_headers_to_kusama::PolkadotFinalityToKusama, - >( - left_client, - right_client, - params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, - params.right_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, - params.shared.only_mandatory_headers, - params.shared.only_mandatory_headers, - params.left.can_start_version_guard(), - params.right.can_start_version_guard(), - at_left_relay_accounts, - at_right_relay_accounts, - ).await - } - - async fn left_create_account( - left_client: Client, - left_sign: ::AccountKeyPair, - account_id: AccountIdOf, - ) -> anyhow::Result<()> { - submit_signed_extrinsic( - left_client, - left_sign, - relay_kusama_client::runtime::Call::Balances( - relay_kusama_client::runtime::BalancesCall::transfer( - bp_kusama::AccountAddress::Id(account_id), - bp_kusama::EXISTENTIAL_DEPOSIT.into(), - ), - ), - ) - .await - } - - async fn right_create_account( - right_client: Client, - right_sign: ::AccountKeyPair, - account_id: AccountIdOf, - ) -> anyhow::Result<()> { - submit_signed_extrinsic( - right_client, - right_sign, - relay_polkadot_client::runtime::Call::Balances( - relay_polkadot_client::runtime::BalancesCall::transfer( - bp_polkadot::AccountAddress::Id(account_id), - bp_polkadot::EXISTENTIAL_DEPOSIT.into(), - ), - ), - ) - .await - } - $generic }, } @@ -481,24 +316,14 @@ macro_rules! select_bridge { declare_chain_options!(Millau, millau); declare_chain_options!(Rialto, rialto); declare_chain_options!(RialtoParachain, rialto_parachain); -declare_chain_options!(Rococo, rococo); -declare_chain_options!(Wococo, wococo); -declare_chain_options!(Kusama, kusama); -declare_chain_options!(Polkadot, polkadot); // Means to override signers of different layer transactions. declare_chain_options!(MillauHeadersToRialto, millau_headers_to_rialto); declare_chain_options!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); declare_chain_options!(RialtoHeadersToMillau, rialto_headers_to_millau); declare_chain_options!(RialtoParachainsToMillau, rialto_parachains_to_millau); -declare_chain_options!(WococoHeadersToRococo, wococo_headers_to_rococo); -declare_chain_options!(RococoHeadersToWococo, rococo_headers_to_wococo); -declare_chain_options!(KusamaHeadersToPolkadot, kusama_headers_to_polkadot); -declare_chain_options!(PolkadotHeadersToKusama, polkadot_headers_to_kusama); // All supported bridges. declare_bridge_options!(Millau, Rialto); declare_bridge_options!(Millau, RialtoParachain, Rialto); -declare_bridge_options!(Rococo, Wococo); -declare_bridge_options!(Kusama, Polkadot); impl RelayHeadersAndMessages { /// Run the command. @@ -912,37 +737,6 @@ where Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_parachains))) } -/// Sign and submit transaction with given call to the chain. -async fn submit_signed_extrinsic>( - client: Client, - sign: C::AccountKeyPair, - call: CallOf, -) -> anyhow::Result<()> -where - AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, - CallOf: Send, -{ - let genesis_hash = *client.genesis_hash(); - let (spec_version, transaction_version) = client.simple_runtime_version().await?; - client - .submit_signed_extrinsic(sign.public().into(), move |_, transaction_nonce| { - Ok(Bytes( - C::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer: sign, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), - })? - .encode(), - )) - }) - .await - .map(drop) - .map_err(|e| anyhow::format_err!("{}", e)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index f92c035082cbd..62af6afe93720 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -62,8 +62,6 @@ pub struct ResubmitTransactions { #[strum(serialize_all = "kebab_case")] pub enum RelayChain { Millau, - Kusama, - Polkadot, } /// Strategy to use for priority selection. @@ -93,18 +91,6 @@ macro_rules! select_bridge { type Target = relay_millau_client::Millau; type TargetSign = relay_millau_client::Millau; - $generic - }, - RelayChain::Kusama => { - type Target = relay_kusama_client::Kusama; - type TargetSign = relay_kusama_client::Kusama; - - $generic - }, - RelayChain::Polkadot => { - type Target = relay_polkadot_client::Polkadot; - type TargetSign = relay_polkadot_client::Polkadot; - $generic }, } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index f6aee9dae2200..2efe62d8ec87c 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -6,23 +6,14 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.1.1", features = ["derive"] } # Bridge dependencies -bp-header-chain = { path = "../../primitives/header-chain" } bp-kusama = { path = "../../primitives/chain-kusama" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 31eb3f40e3394..b076da7ab750b 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,19 +16,11 @@ //! Types used to connect to the Kusama chain. -use bp_messages::MessageNonce; -use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use sp_core::storage::StorageKey; use std::time::Duration; -pub mod runtime; - /// Kusama header id. pub type HeaderId = relay_utils::HeaderId; @@ -65,7 +57,7 @@ impl Chain for Kusama { const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_kusama::SignedBlock; - type Call = crate::runtime::Call; + type Call = (); type WeightToFee = bp_kusama::WeightToFee; } @@ -73,80 +65,11 @@ impl ChainWithGrandpa for Kusama { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME; } -impl ChainWithMessages for Kusama { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_kusama::WITH_KUSAMA_MESSAGES_PALLET_NAME; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_kusama::TO_KUSAMA_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_kusama::FROM_KUSAMA_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_kusama::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); -} - impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_kusama::account_info_storage_key(account_id)) } } -impl TransactionSignScheme for Kusama { - type Chain = Kusama; - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_kusama::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_kusama::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_kusama::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - /// Kusama header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// Kusama signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-kusama/src/runtime.rs b/relays/client-kusama/src/runtime.rs deleted file mode 100644 index 370486d1b8347..0000000000000 --- a/relays/client-kusama/src/runtime.rs +++ /dev/null @@ -1,133 +0,0 @@ -// 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 . - -//! Types that are specific to the Kusama runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; -use sp_runtime::FixedU128; - -/// Unchecked Kusama extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Kusama Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Kusama chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Kusama -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/kusama/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 4)] - Balances(BalancesCall), - /// Utility pallet. - #[codec(index = 24)] - Utility(UtilityCall), - /// Polkadot bridge pallet. - #[codec(index = 110)] - BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), - /// Polkadot messages pallet. - #[codec(index = 111)] - BridgePolkadotMessages(BridgePolkadotMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgePolkadotGrandpaCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), - #[codec(index = 3)] - set_operational(bool), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgePolkadotMessagesCall { - #[codec(index = 2)] - update_pallet_parameter(BridgePolkadotMessagesParameter), - #[codec(index = 3)] - send_message(LaneId, Vec, bp_kusama::Balance), - #[codec(index = 5)] - receive_messages_proof( - bp_polkadot::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_polkadot::Hash, - >, - UnrewardedRelayersState, - ), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum UtilityCall { - #[codec(index = 2)] - batch_all(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum BridgePolkadotMessagesParameter { - #[codec(index = 0)] - PolkadotToKusamaConversionRate(FixedU128), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index d52ddd9adf4c8..aefbadfdd18af 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -6,23 +6,14 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.1.1", features = ["derive"] } # Bridge dependencies -bp-header-chain = { path = "../../primitives/header-chain" } -bp-kusama = { path = "../../primitives/chain-kusama" } -bp-messages = { path = "../../primitives/messages" } bp-polkadot = { path = "../../primitives/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 35d876f546380..9327c76c4ef39 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,19 +16,11 @@ //! Types used to connect to the Polkadot chain. -use bp_messages::MessageNonce; -use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use sp_core::storage::StorageKey; use std::time::Duration; -pub mod runtime; - /// Polkadot header id. pub type HeaderId = relay_utils::HeaderId; @@ -65,7 +57,7 @@ impl Chain for Polkadot { const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_polkadot::SignedBlock; - type Call = crate::runtime::Call; + type Call = (); type WeightToFee = bp_polkadot::WeightToFee; } @@ -74,80 +66,11 @@ impl ChainWithGrandpa for Polkadot { bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME; } -impl ChainWithMessages for Polkadot { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_polkadot::WITH_POLKADOT_MESSAGES_PALLET_NAME; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot::TO_POLKADOT_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot::FROM_POLKADOT_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_polkadot::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); -} - impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_polkadot::account_info_storage_key(account_id)) } } -impl TransactionSignScheme for Polkadot { - type Chain = Polkadot; - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_polkadot::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_polkadot::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_polkadot::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - /// Polkadot header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// Polkadot signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-polkadot/src/runtime.rs b/relays/client-polkadot/src/runtime.rs deleted file mode 100644 index 15421d94c699b..0000000000000 --- a/relays/client-polkadot/src/runtime.rs +++ /dev/null @@ -1,133 +0,0 @@ -// 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 . - -//! Types that are specific to the Polkadot runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; -use sp_runtime::FixedU128; - -/// Unchecked Polkadot extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Polkadot Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Polkadot chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Polkadot -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/kusama/blob/master/runtime/kusam/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 5)] - Balances(BalancesCall), - /// Utility pallet. - #[codec(index = 26)] - Utility(UtilityCall), - /// Kusama bridge pallet. - #[codec(index = 110)] - BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), - /// Kusama messages pallet. - #[codec(index = 111)] - BridgeKusamaMessages(BridgeKusamaMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeKusamaGrandpaCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), - #[codec(index = 3)] - set_operational(bool), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeKusamaMessagesCall { - #[codec(index = 2)] - update_pallet_parameter(BridgeKusamaMessagesParameter), - #[codec(index = 3)] - send_message(LaneId, Vec, bp_polkadot::Balance), - #[codec(index = 5)] - receive_messages_proof( - bp_kusama::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_kusama::Hash, - >, - UnrewardedRelayersState, - ), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum UtilityCall { - #[codec(index = 2)] - batch_all(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum BridgeKusamaMessagesParameter { - #[codec(index = 0)] - KusamaToPolkadotConversionRate(FixedU128), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index e806ad594c21a..14d3c8ca23259 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -6,24 +6,14 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.1.1", features = ["derive"] } # Bridge dependencies -bridge-runtime-common = { path = "../../bin/runtime-common" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } -bp-wococo = { path = "../../primitives/chain-wococo" } -pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 42a22a8f268bd..c33af96aedf65 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,19 +16,11 @@ //! Types used to connect to the Rococo-Substrate chain. -use bp_messages::MessageNonce; -use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use sp_core::storage::StorageKey; use std::time::Duration; -pub mod runtime; - /// Rococo header id. pub type HeaderId = relay_utils::HeaderId; @@ -68,7 +60,7 @@ impl Chain for Rococo { const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_rococo::SignedBlock; - type Call = crate::runtime::Call; + type Call = (); type WeightToFee = bp_rococo::WeightToFee; } @@ -76,77 +68,8 @@ impl ChainWithGrandpa for Rococo { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rococo::WITH_ROCOCO_GRANDPA_PALLET_NAME; } -impl ChainWithMessages for Rococo { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_rococo::WITH_ROCOCO_MESSAGES_PALLET_NAME; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rococo::TO_ROCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rococo::FROM_ROCOCO_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); -} - impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_rococo::account_info_storage_key(account_id)) } } - -impl TransactionSignScheme for Rococo { - type Chain = Rococo; - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_rococo::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_rococo::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_rococo::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - -/// Rococo signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-rococo/src/runtime.rs b/relays/client-rococo/src/runtime.rs deleted file mode 100644 index 249e75a709ff5..0000000000000 --- a/relays/client-rococo/src/runtime.rs +++ /dev/null @@ -1,112 +0,0 @@ -// 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 . - -//! Types that are specific to the Rococo runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; - -/// Unchecked Rococo extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Rococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 4)] - Balances(BalancesCall), - /// Wococo bridge pallet. - #[codec(index = 41)] - BridgeGrandpaWococo(BridgeGrandpaWococoCall), - /// Wococo messages pallet. - #[codec(index = 44)] - BridgeWococoMessages(BridgeWococoMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaWococoCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeWococoMessagesCall { - #[codec(index = 3)] - send_message(LaneId, Vec, bp_rococo::Balance), - #[codec(index = 5)] - receive_messages_proof( - bp_wococo::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_wococo::Hash, - >, - UnrewardedRelayersState, - ), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index b322849d94adc..5b97694af1c9e 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -6,22 +6,13 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies -bridge-runtime-common = { path = "../../bin/runtime-common" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../primitives/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } + bp-wococo = { path = "../../primitives/chain-wococo" } -pallet-bridge-messages = { path = "../../modules/messages" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 3c96a80b60db5..06a63e7d2b46c 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,19 +16,11 @@ //! Types used to connect to the Wococo-Substrate chain. -use bp_messages::MessageNonce; -use codec::Encode; use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use sp_core::storage::StorageKey; use std::time::Duration; -pub mod runtime; - /// Wococo header id. pub type HeaderId = relay_utils::HeaderId; @@ -68,7 +60,7 @@ impl Chain for Wococo { const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_wococo::SignedBlock; - type Call = crate::runtime::Call; + type Call = (); type WeightToFee = bp_wococo::WeightToFee; } @@ -76,77 +68,8 @@ impl ChainWithGrandpa for Wococo { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_wococo::WITH_WOCOCO_GRANDPA_PALLET_NAME; } -impl ChainWithMessages for Wococo { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_wococo::WITH_WOCOCO_MESSAGES_PALLET_NAME; - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_wococo::TO_WOCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_wococo::FROM_WOCOCO_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); -} - impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { StorageKey(bp_wococo::account_info_storage_key(account_id)) } } - -impl TransactionSignScheme for Wococo { - type Chain = Wococo; - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = crate::runtime::UncheckedExtrinsic; - - fn sign_transaction(param: SignParam) -> Result { - let raw_payload = SignedPayload::new( - param.unsigned.call.clone(), - bp_wococo::SignedExtensions::new( - param.spec_version, - param.transaction_version, - param.era, - param.genesis_hash, - param.unsigned.nonce, - param.unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(bp_wococo::UncheckedExtrinsic::new_signed( - call, - sp_runtime::MultiAddress::Id(signer.into_account()), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_wococo::AccountId::from(*signer.public().as_array_ref()).into() - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { call: tx.function, nonce: extra.nonce(), tip: extra.tip() }) - } -} - -/// Wococo signing params. -pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-wococo/src/runtime.rs b/relays/client-wococo/src/runtime.rs deleted file mode 100644 index f7b9c03bf9cd8..0000000000000 --- a/relays/client-wococo/src/runtime.rs +++ /dev/null @@ -1,112 +0,0 @@ -// 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 . - -//! Types that are specific to the Wococo runtime. - -use bp_messages::{LaneId, UnrewardedRelayersState}; -use bp_polkadot_core::{AccountAddress, Balance, PolkadotLike}; -use bp_runtime::Chain; -use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; -use scale_info::TypeInfo; - -/// Unchecked Wococo extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Wococo Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/polkadot/blob/master/runtime/rococo/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// System pallet. - #[codec(index = 0)] - System(SystemCall), - /// Balances pallet. - #[codec(index = 4)] - Balances(BalancesCall), - /// Rococo bridge pallet. - #[codec(index = 40)] - BridgeGrandpaRococo(BridgeGrandpaRococoCall), - /// Rococo messages pallet. - #[codec(index = 43)] - BridgeRococoMessages(BridgeRococoMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BalancesCall { - #[codec(index = 0)] - transfer(AccountAddress, Compact), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeGrandpaRococoCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeRococoMessagesCall { - #[codec(index = 3)] - send_message(LaneId, Vec, bp_rococo::Balance), - #[codec(index = 5)] - receive_messages_proof( - bp_rococo::AccountId, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof, - u32, - Weight, - ), - #[codec(index = 6)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - bp_rococo::Hash, - >, - UnrewardedRelayersState, - ), -} - -impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index a1370744b144c..a74ebf3e183bd 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -51,6 +51,7 @@ bp-rialto = { path = "../../primitives/chain-rialto" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +relay-rialto-client = { path = "../client-rialto" } relay-rococo-client = { path = "../client-rococo" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index d860fa68a934b..b315dfed4bb50 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -522,6 +522,7 @@ fn compute_prepaid_messages_refund( #[cfg(test)] mod tests { use super::*; + use relay_rialto_client::Rialto; use relay_rococo_client::Rococo; use relay_wococo_client::Wococo; @@ -581,10 +582,10 @@ mod tests { #[test] fn compute_prepaid_messages_refund_returns_sane_results() { assert!( - compute_prepaid_messages_refund::( + compute_prepaid_messages_refund::( 10, FixedU128::saturating_from_rational(110, 100), - ) > (10 * Wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into() + ) > (10 * Rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into() ); } } From 26022707d1c57b4118bf84b8dc51ccf0ca38e544 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 6 Jul 2022 15:45:30 +0300 Subject: [PATCH 0728/1210] [CLI] remove select_full_bridge!() macro Signed-off-by: Serban Iorga --- relays/bin-substrate/src/cli/bridge.rs | 176 +++++++------- relays/bin-substrate/src/cli/estimate_fee.rs | 76 +++--- relays/bin-substrate/src/cli/relay_headers.rs | 9 +- .../bin-substrate/src/cli/relay_messages.rs | 107 +++++---- relays/bin-substrate/src/cli/send_message.rs | 216 ++++++++++-------- 5 files changed, 324 insertions(+), 260 deletions(-) diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 242c22647c194..103c9cb391a46 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -15,9 +15,12 @@ // along with Parity Bridges Common. If not, see . use crate::cli::CliChain; +use bp_runtime::{AccountIdOf, SourceAccount}; use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme}; use strum::{EnumString, EnumVariantNames}; -use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; +use substrate_relay_helper::{ + finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, +}; #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] #[strum(serialize_all = "kebab_case")] @@ -46,94 +49,6 @@ pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1; pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; -/// The macro allows executing bridge-specific code without going fully generic. -/// -/// It matches on the [`FullBridge`] enum, sets bridge-specific types or imports and injects -/// the `$generic` code at every variant. -#[macro_export] -macro_rules! select_full_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - FullBridge::MillauToRialto => { - type Source = relay_millau_client::Millau; - #[allow(dead_code)] - type Target = relay_rialto_client::Rialto; - - // Derive-account - #[allow(unused_imports)] - use bp_rialto::derive_account_from_millau_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::millau_messages_to_rialto::MillauMessagesToRialto as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::RialtoToMillau => { - type Source = relay_rialto_client::Rialto; - #[allow(dead_code)] - type Target = relay_millau_client::Millau; - - // Derive-account - #[allow(unused_imports)] - use bp_millau::derive_account_from_rialto_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - }, - FullBridge::MillauToRialtoParachain => { - type Source = relay_millau_client::Millau; - #[allow(dead_code)] - type Target = relay_rialto_parachain_client::RialtoParachain; - - // Derive-account - #[allow(unused_imports)] - use bp_rialto_parachain::derive_account_from_millau_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - } - FullBridge::RialtoParachainToMillau => { - type Source = relay_rialto_parachain_client::RialtoParachain; - #[allow(dead_code)] - type Target = relay_millau_client::Millau; - - // Derive-account - #[allow(unused_imports)] - use bp_millau::derive_account_from_rialto_parachain_id as derive_account; - - // Relay-messages - #[allow(unused_imports)] - use $crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as MessagesLane; - - // Send-message / Estimate-fee - #[allow(unused_imports)] - use bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD as ESTIMATE_MESSAGE_FEE_METHOD; - - $generic - } - } - }; -} - /// Minimal bridge representation that can be used from the CLI. /// It connects a source chain to a target chain. pub trait CliBridgeBase: Sized { @@ -145,8 +60,8 @@ pub trait CliBridgeBase: Sized { + CliChain>; } -/// Bridge representation that can be used from the CLI. -pub trait CliBridge: CliBridgeBase { +/// Bridge representation that can be used from the CLI for relaying headers. +pub trait HeadersCliBridge: CliBridgeBase { /// Finality proofs synchronization pipeline. type Finality: SubstrateFinalitySyncPipeline< SourceChain = Self::Source, @@ -155,6 +70,25 @@ pub trait CliBridge: CliBridgeBase { >; } +/// Bridge representation that can be used from the CLI for relaying messages. +pub trait MessagesCliBridge: CliBridgeBase { + /// Name of the runtime method used to estimate the message dispatch and delivery fee for the + /// defined bridge. + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str; + /// The Source -> Destination messages synchronization pipeline. + type MessagesLane: SubstrateMessageLane< + SourceChain = Self::Source, + TargetChain = Self::Target, + SourceTransactionSignScheme = Self::Source, + TargetTransactionSignScheme = Self::Target, + >; + + /// We use this to get the account on the target which is derived from the source account. + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf; +} + //// `Millau` to `Rialto` bridge definition. pub struct MillauToRialtoCliBridge {} @@ -163,10 +97,22 @@ impl CliBridgeBase for MillauToRialtoCliBridge { type Target = relay_rialto_client::Rialto; } -impl CliBridge for MillauToRialtoCliBridge { +impl HeadersCliBridge for MillauToRialtoCliBridge { type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; } +impl MessagesCliBridge for MillauToRialtoCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; + + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_rialto::derive_account_from_millau_id(id) + } +} + //// `Rialto` to `Millau` bridge definition. pub struct RialtoToMillauCliBridge {} @@ -175,10 +121,24 @@ impl CliBridgeBase for RialtoToMillauCliBridge { type Target = relay_millau_client::Millau; } -impl CliBridge for RialtoToMillauCliBridge { +impl HeadersCliBridge for RialtoToMillauCliBridge { type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; } +impl MessagesCliBridge for RialtoToMillauCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; + + /// We use this to get the account on the target chain which is derived from + /// the source chain account. + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_millau::derive_account_from_rialto_id(id) + } +} + //// `Westend` to `Millau` bridge definition. pub struct WestendToMillauCliBridge {} @@ -187,7 +147,7 @@ impl CliBridgeBase for WestendToMillauCliBridge { type Target = relay_millau_client::Millau; } -impl CliBridge for WestendToMillauCliBridge { +impl HeadersCliBridge for WestendToMillauCliBridge { type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; } @@ -199,11 +159,24 @@ impl CliBridgeBase for MillauToRialtoParachainCliBridge { type Target = relay_rialto_parachain_client::RialtoParachain; } -impl CliBridge for MillauToRialtoParachainCliBridge { +impl HeadersCliBridge for MillauToRialtoParachainCliBridge { type Finality = crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; } +impl MessagesCliBridge for MillauToRialtoParachainCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; + + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_rialto_parachain::derive_account_from_millau_id(id) + } +} + //// `RialtoParachain` to `Millau` bridge definition. pub struct RialtoParachainToMillauCliBridge {} @@ -212,6 +185,19 @@ impl CliBridgeBase for RialtoParachainToMillauCliBridge { type Target = relay_millau_client::Millau; } +impl MessagesCliBridge for RialtoParachainToMillauCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; + + fn derive_account_from_id( + id: SourceAccount>, + ) -> AccountIdOf { + bp_millau::derive_account_from_rialto_parachain_id(id) + } +} + //// `WestendParachain` to `Millau` bridge definition. pub struct WestmintToMillauCliBridge {} diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index bf13996ec52be..30f20b681d4a2 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -14,17 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - cli::{ - bridge::FullBridge, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - Balance, HexBytes, HexLaneId, SourceConnectionParams, - }, - select_full_bridge, +use crate::cli::{ + bridge::{FullBridge, MessagesCliBridge, *}, + relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + Balance, HexBytes, HexLaneId, SourceConnectionParams, }; +use async_trait::async_trait; use bp_runtime::BalanceOf; use codec::{Decode, Encode}; -use relay_substrate_client::Chain; +use relay_substrate_client::{Chain, ChainBase}; use sp_runtime::FixedU128; +use std::fmt::Display; use structopt::StructOpt; use strum::VariantNames; use substrate_relay_helper::helpers::tokens_conversion_rate_from_metrics; @@ -74,30 +74,50 @@ impl std::str::FromStr for ConversionRateOverride { } } -impl EstimateFee { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - let Self { source, bridge, lane, conversion_rate_override, payload } = self; - - select_full_bridge!(bridge, { - let source_client = source.to_client::().await?; - let lane = lane.into(); - let payload = crate::cli::encode_message::encode_message::(&payload) +#[async_trait] +trait FeeEstimator: MessagesCliBridge +where + ::Balance: Display + Into, +{ + async fn estimate_fee(data: EstimateFee) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let lane = data.lane.into(); + let payload = + crate::cli::encode_message::encode_message::(&data.payload) .map_err(|e| anyhow::format_err!("{:?}", e))?; - let fee = estimate_message_delivery_and_dispatch_fee::( - &source_client, - conversion_rate_override, - ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload, - ) - .await?; + let fee = estimate_message_delivery_and_dispatch_fee::( + &source_client, + data.conversion_rate_override, + Self::ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload, + ) + .await?; + + log::info!(target: "bridge", "Fee: {:?}", Balance(fee.into())); + println!("{}", fee); + Ok(()) + } +} - log::info!(target: "bridge", "Fee: {:?}", Balance(fee as _)); - println!("{}", fee); - Ok(()) - }) +impl FeeEstimator for MillauToRialtoCliBridge {} +impl FeeEstimator for RialtoToMillauCliBridge {} +impl FeeEstimator for MillauToRialtoParachainCliBridge {} +impl FeeEstimator for RialtoParachainToMillauCliBridge {} + +impl EstimateFee { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self.bridge { + FullBridge::MillauToRialto => MillauToRialtoCliBridge::estimate_fee(self), + FullBridge::RialtoToMillau => RialtoToMillauCliBridge::estimate_fee(self), + FullBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::estimate_fee(self), + FullBridge::RialtoParachainToMillau => + RialtoParachainToMillauCliBridge::estimate_fee(self), + } + .await } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 25bb3440c6c8f..f8d7eeb541830 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -24,11 +24,8 @@ use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; use crate::cli::{ - bridge::{ - CliBridge, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, - RialtoToMillauCliBridge, WestendToMillauCliBridge, - }, - PrometheusParams, SourceConnectionParams, TargetConnectionParams, TargetSigningParams, + bridge::*, PrometheusParams, SourceConnectionParams, TargetConnectionParams, + TargetSigningParams, }; /// Start headers relayer process. @@ -62,7 +59,7 @@ pub enum RelayHeadersBridge { } #[async_trait] -trait HeadersRelayer: CliBridge +trait HeadersRelayer: HeadersCliBridge where ::AccountId: From< as Pair>::Public>, { diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 820a71748d2be..7242d13185203 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -14,18 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use async_trait::async_trait; +use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use messages_relay::relay_strategy::MixStrategy; -use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; - -use crate::{ - cli::{ - bridge::FullBridge, HexLaneId, PrometheusParams, SourceConnectionParams, - SourceSigningParams, TargetConnectionParams, TargetSigningParams, - }, - select_full_bridge, +use relay_substrate_client::{AccountKeyPairOf, ChainBase, TransactionSignScheme}; +use substrate_relay_helper::{ + messages_lane::{MessagesRelayParams, SubstrateMessageLane}, + TransactionParams, +}; + +use crate::cli::{ + bridge::*, CliChain, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, + TargetConnectionParams, TargetSigningParams, }; /// Relayer operating mode. @@ -71,40 +74,66 @@ pub struct RelayMessages { prometheus_params: PrometheusParams, } +#[async_trait] +trait MessagesRelayer: MessagesCliBridge +where + Self::Source: TransactionSignScheme + + CliChain>, + ::AccountId: From< as Pair>::Public>, + ::AccountId: From< as Pair>::Public>, + ::Balance: TryFrom<::Balance>, + Self::MessagesLane: SubstrateMessageLane, +{ + async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> { + let source_client = data.source.to_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + let target_client = data.target.to_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + let target_transactions_mortality = data.target_sign.transactions_mortality()?; + let relayer_mode = data.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); + + substrate_relay_helper::messages_lane::run::(MessagesRelayParams { + source_client, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, + target_client, + target_transaction_params: TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }, + source_to_target_headers_relay: None, + target_to_source_headers_relay: None, + lane_id: data.lane.into(), + metrics_params: data.prometheus_params.into(), + standalone_metrics: None, + relay_strategy, + }) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} + +impl MessagesRelayer for MillauToRialtoCliBridge {} +impl MessagesRelayer for RialtoToMillauCliBridge {} +impl MessagesRelayer for MillauToRialtoParachainCliBridge {} +impl MessagesRelayer for RialtoParachainToMillauCliBridge {} + impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - select_full_bridge!(self.bridge, { - let source_client = self.source.to_client::().await?; - let source_sign = self.source_sign.to_keypair::()?; - let source_transactions_mortality = self.source_sign.transactions_mortality()?; - let target_client = self.target.to_client::().await?; - let target_sign = self.target_sign.to_keypair::()?; - let target_transactions_mortality = self.target_sign.transactions_mortality()?; - let relayer_mode = self.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); - - substrate_relay_helper::messages_lane::run::(MessagesRelayParams { - source_client, - source_transaction_params: TransactionParams { - signer: source_sign, - mortality: source_transactions_mortality, - }, - target_client, - target_transaction_params: TransactionParams { - signer: target_sign, - mortality: target_transactions_mortality, - }, - source_to_target_headers_relay: None, - target_to_source_headers_relay: None, - lane_id: self.lane.into(), - metrics_params: self.prometheus_params.into(), - standalone_metrics: None, - relay_strategy, - }) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - }) + match self.bridge { + FullBridge::MillauToRialto => MillauToRialtoCliBridge::relay_messages(self), + FullBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_messages(self), + FullBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::relay_messages(self), + FullBridge::RialtoParachainToMillau => + RialtoParachainToMillauCliBridge::relay_messages(self), + } + .await } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 959fbbd7fcac0..ee17fb3f31fea 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -15,16 +15,20 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ - bridge::FullBridge, + bridge::{FullBridge, MessagesCliBridge, *}, encode_message::{self, CliEncodeMessage}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, HexBytes, HexLaneId, SourceConnectionParams, SourceSigningParams, + Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams, SourceSigningParams, }; +use async_trait::async_trait; +use bp_runtime::AccountIdOf; use codec::Encode; -use relay_substrate_client::{Chain, SignParam, TransactionSignScheme, UnsignedTransaction}; +use relay_substrate_client::{ + AccountKeyPairOf, Chain, ChainBase, SignParam, TransactionSignScheme, UnsignedTransaction, +}; use sp_core::{Bytes, Pair}; use sp_runtime::AccountId32; -use std::fmt::Debug; +use std::fmt::{Debug, Display}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -75,97 +79,125 @@ pub struct SendMessage { message: crate::cli::encode_message::Message, } +#[async_trait] +trait MessageSender: MessagesCliBridge +where + Self::Source: ChainBase + + TransactionSignScheme + + CliChain> + + CliEncodeMessage, + ::Balance: Display + From + Into, + ::Call: Sync, + ::SignedTransaction: Sync, + AccountIdOf: From< as Pair>::Public>, + AccountId32: From< as Pair>::Public>, +{ + async fn send_message(data: SendMessage) -> anyhow::Result<()> { + let payload = encode_message::encode_message::(&data.message)?; + + let source_client = data.source.to_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + + let lane = data.lane.clone().into(); + let conversion_rate_override = data.conversion_rate_override; + let fee = match data.fee { + Some(fee) => fee, + None => Balance( + estimate_message_delivery_and_dispatch_fee::( + &source_client, + conversion_rate_override, + Self::ESTIMATE_MESSAGE_FEE_METHOD, + lane, + payload.clone(), + ) + .await? + .into(), + ), + }; + let payload_len = payload.encode().len(); + let send_message_call = Self::Source::encode_send_message_call( + data.lane.0, + payload, + fee.cast().into(), + data.bridge.bridge_instance_index(), + )?; + + let source_genesis_hash = *source_client.genesis_hash(); + let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; + let estimated_transaction_fee = source_client + .estimate_extrinsic_fee(Bytes( + Self::Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), + })? + .encode(), + )) + .await?; + source_client + .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { + let signed_source_call = Self::Source::sign_transaction(SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + era: relay_substrate_client::TransactionEra::immortal(), + unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), + })? + .encode(); + + log::info!( + target: "bridge", + "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", + Self::Target::NAME, + lane, + payload_len, + fee, + ); + log::info!( + target: "bridge", + "The source account ({:?}) balance will be reduced by (at most) {} (message fee) + + {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()), + fee.0, + estimated_transaction_fee.inclusion_fee(), + fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()), + Self::Source::NAME, + ); + log::info!( + target: "bridge", + "Signed {} Call: {:?}", + Self::Source::NAME, + HexBytes::encode(&signed_source_call) + ); + + Ok(Bytes(signed_source_call)) + }) + .await?; + + Ok(()) + } +} + +impl MessageSender for MillauToRialtoCliBridge {} +impl MessageSender for RialtoToMillauCliBridge {} +impl MessageSender for MillauToRialtoParachainCliBridge {} +impl MessageSender for RialtoParachainToMillauCliBridge {} + impl SendMessage { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { - crate::select_full_bridge!(self.bridge, { - let payload = encode_message::encode_message::(&self.message)?; - - let source_client = self.source.to_client::().await?; - let source_sign = self.source_sign.to_keypair::()?; - - let lane = self.lane.clone().into(); - let conversion_rate_override = self.conversion_rate_override; - let fee = match self.fee { - Some(fee) => fee, - None => Balance( - estimate_message_delivery_and_dispatch_fee::( - &source_client, - conversion_rate_override, - ESTIMATE_MESSAGE_FEE_METHOD, - lane, - payload.clone(), - ) - .await? as _, - ), - }; - let payload_len = payload.encode().len(); - #[allow(clippy::useless_conversion)] - let send_message_call = Source::encode_send_message_call( - self.lane.0, - payload, - fee.cast().into(), - self.bridge.bridge_instance_index(), - )?; - - let source_genesis_hash = *source_client.genesis_hash(); - let (spec_version, transaction_version) = - source_client.simple_runtime_version().await?; - let estimated_transaction_fee = source_client - .estimate_extrinsic_fee(Bytes( - Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), - })? - .encode(), - )) - .await?; - source_client - .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { - let signed_source_call = Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), - })? - .encode(); - - log::info!( - target: "bridge", - "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", - Target::NAME, - lane, - payload_len, - fee, - ); - log::info!( - target: "bridge", - "The source account ({:?}) balance will be reduced by (at most) {} (message fee) + {} (tx fee ) = {} {} tokens", - AccountId32::from(source_sign.public()), - fee.0, - estimated_transaction_fee.inclusion_fee(), - fee.0.saturating_add(estimated_transaction_fee.inclusion_fee() as _), - Source::NAME, - ); - log::info!( - target: "bridge", - "Signed {} Call: {:?}", - Source::NAME, - HexBytes::encode(&signed_source_call) - ); - - Ok(Bytes(signed_source_call)) - }) - .await?; - }); - - Ok(()) + match self.bridge { + FullBridge::MillauToRialto => MillauToRialtoCliBridge::send_message(self), + FullBridge::RialtoToMillau => RialtoToMillauCliBridge::send_message(self), + FullBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::send_message(self), + FullBridge::RialtoParachainToMillau => + RialtoParachainToMillauCliBridge::send_message(self), + } + .await } } From 1b1907fa4b86eb509b58f5556400e593153408db Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 7 Jul 2022 11:29:30 +0300 Subject: [PATCH 0729/1210] Fix and update benchmarks (#1494) * decrease parameters range in grandpa benchmarks * fix messages benchmarks * update all weights * dealing with failed test (WiP) * Revert "dealing with failed test (WiP)" This reverts commit 0379d24bcf0692da5813968d83e0cbc918ac4691. * proper tests fix --- modules/grandpa/src/benchmarking.rs | 14 +- modules/grandpa/src/weights.rs | 17 +- modules/messages/src/benchmarking.rs | 38 ++-- modules/messages/src/weights.rs | 173 +++++++++--------- modules/messages/src/weights_ext.rs | 6 +- modules/parachains/src/weights.rs | 26 +-- .../lib-substrate-relay/src/messages_lane.rs | 2 +- 7 files changed, 140 insertions(+), 136 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 655cd6eae74e5..f93798536a3d1 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -63,6 +63,16 @@ const MAX_VOTE_ANCESTRIES: u32 = 1000; // number of validators. const MAX_VALIDATOR_SET_SIZE: u32 = 1024; +// `1..MAX_VALIDATOR_SET_SIZE` and `1..MAX_VOTE_ANCESTRIES` are too large && benchmarks are +// running for almost 40m (steps=50, repeat=20) on a decent laptop, which is too much. Since +// we're building linear function here, let's just select some limited subrange for benchmarking. +const VALIDATOR_SET_SIZE_RANGE_BEGIN: u32 = MAX_VALIDATOR_SET_SIZE / 20; +const VALIDATOR_SET_SIZE_RANGE_END: u32 = + VALIDATOR_SET_SIZE_RANGE_BEGIN + VALIDATOR_SET_SIZE_RANGE_BEGIN; +const MAX_VOTE_ANCESTRIES_RANGE_BEGIN: u32 = MAX_VOTE_ANCESTRIES / 20; +const MAX_VOTE_ANCESTRIES_RANGE_END: u32 = + MAX_VOTE_ANCESTRIES_RANGE_BEGIN + MAX_VOTE_ANCESTRIES_RANGE_BEGIN; + /// Returns number of first header to be imported. /// /// Since we bootstrap the pallet with `HeadersToKeep` already imported headers, @@ -107,8 +117,8 @@ benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to // annotate the weight in the pallet. submit_finality_proof { - let p in 1..MAX_VALIDATOR_SET_SIZE; - let v in 1..MAX_VOTE_ANCESTRIES; + let p in VALIDATOR_SET_SIZE_RANGE_BEGIN..VALIDATOR_SET_SIZE_RANGE_END; + let v in MAX_VOTE_ANCESTRIES_RANGE_BEGIN..MAX_VOTE_ANCESTRIES_RANGE_END; let caller: T::AccountId = whitelisted_caller(); let (header, justification) = prepare_benchmark_data::(p, v); }: submit_finality_proof(RawOrigin::Signed(caller), Box::new(header), justification) diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 2c4660160a004..d17fee6ceda86 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,14 +17,15 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 +//! DATE: 2022-07-06, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 128 +//! CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // target/release/millau-bridge-node // benchmark +// pallet // --chain=dev // --steps=50 // --repeat=20 @@ -55,9 +56,9 @@ pub trait WeightInfo { pub struct MillauWeight(PhantomData); impl WeightInfo for MillauWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (115_651_000 as Weight) - .saturating_add((61_465_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((3_438_000 as Weight).saturating_mul(v as Weight)) + (55_070_000 as Weight) + .saturating_add((39_678_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_540_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -66,9 +67,9 @@ impl WeightInfo for MillauWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (115_651_000 as Weight) - .saturating_add((61_465_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((3_438_000 as Weight).saturating_mul(v as Weight)) + (55_070_000 as Weight) + .saturating_add((39_678_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_540_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index c312528d4bd29..78a04d22868f1 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -19,12 +19,13 @@ use crate::{ inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, outbound_lane::ReceivalConfirmationResult, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, + OutboundLanes, OutboundMessages, }; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, - InboundLaneData, LaneId, MessageData, MessageNonce, OutboundLaneData, UnrewardedRelayer, - UnrewardedRelayersState, + InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, + UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::{messages::DispatchFeePayment, StorageProofSize}; use frame_benchmarking::{account, benchmarks_instance_pallet}; @@ -244,7 +245,10 @@ benchmarks_instance_pallet! { send_regular_message_with_payload::(vec![42u8; T::maximal_message_size() as _]); }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) verify { - assert_eq!(T::account_balance(&sender), 0.into()); + assert_eq!( + OutboundMessages::::get(MessageKey { lane_id: T::bench_lane_id(), nonce }).unwrap().fee, + T::message_fee() + additional_fee, + ); } // Benchmark `increase_message_fee` with following conditions: @@ -265,7 +269,10 @@ benchmarks_instance_pallet! { send_regular_message_with_payload::(vec![42u8; i as _]); }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) verify { - assert_eq!(T::account_balance(&sender), 0.into()); + assert_eq!( + OutboundMessages::::get(MessageKey { lane_id: T::bench_lane_id(), nonce }).unwrap().fee, + T::message_fee() + additional_fee, + ); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: @@ -508,10 +515,7 @@ benchmarks_instance_pallet! { }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { - assert_eq!( - T::account_balance(&relayer_id), - relayer_balance + T::message_fee(), - ); + assert_eq!(OutboundLanes::::get(T::bench_lane_id()).latest_received_nonce, 1); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -552,7 +556,7 @@ benchmarks_instance_pallet! { }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { - ensure_relayer_rewarded::(&relayer_id, &relayer_balance); + assert_eq!(OutboundLanes::::get(T::bench_lane_id()).latest_received_nonce, 2); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -599,8 +603,7 @@ benchmarks_instance_pallet! { }); }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) verify { - ensure_relayer_rewarded::(&relayer1_id, &relayer1_balance); - ensure_relayer_rewarded::(&relayer2_id, &relayer2_balance); + assert_eq!(OutboundLanes::::get(T::bench_lane_id()).latest_received_nonce, 2); } } @@ -642,16 +645,3 @@ fn receive_messages, I: 'static>(nonce: MessageNonce) { last_confirmed_nonce: 0, }); } - -fn ensure_relayer_rewarded, I: 'static>( - relayer_id: &T::AccountId, - old_balance: &T::OutboundMessageFee, -) { - let new_balance = T::account_balance(relayer_id); - assert!( - new_balance > *old_balance, - "Relayer haven't received reward for relaying message: old balance = {:?}, new balance = {:?}", - old_balance, - new_balance, - ); -} diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 462f768a08b38..6db9ad5c44279 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,14 +17,15 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-28, STEPS: 50, REPEAT: 20 +//! DATE: 2022-07-07, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 128 +//! CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // target/release/millau-bridge-node // benchmark +// pallet // --chain=dev // --steps=50 // --repeat=20 @@ -68,149 +69,149 @@ pub trait WeightInfo { pub struct MillauWeight(PhantomData); impl WeightInfo for MillauWeight { fn send_minimal_message_worst_case() -> Weight { - (117_480_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) + (37_948_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (128_391_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) + (39_158_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (149_149_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(12 as Weight)) + (48_698_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (6_015_058_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (2_919_864_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn increase_message_fee(i: u32) -> Weight { (0 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof() -> Weight { - (179_892_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (25_992_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_two_messages_proof() -> Weight { - (291_793_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (37_016_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (192_191_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (31_589_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (202_104_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (25_962_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (357_144_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) - } - fn receive_single_prepaid_message_proof() -> Weight { - (122_648_000 as Weight) + (74_385_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + fn receive_single_prepaid_message_proof() -> Weight { + (26_159_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } fn receive_delivery_proof_for_single_message() -> Weight { - (107_631_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (27_590_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (113_885_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + (27_354_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (155_151_000 as Weight) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) - .saturating_add(T::DbWeight::get().writes(4 as Weight)) + (27_652_000 as Weight) + .saturating_add(T::DbWeight::get().reads(3 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) } } // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (117_480_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + (37_948_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (128_391_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + (39_158_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (149_149_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(12 as Weight)) + (48_698_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (6_015_058_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (2_919_864_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn increase_message_fee(i: u32) -> Weight { (0 as Weight) - .saturating_add((2_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add((1_000 as Weight).saturating_mul(i as Weight)) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof() -> Weight { - (179_892_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (25_992_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_two_messages_proof() -> Weight { - (291_793_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (37_016_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (192_191_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (31_589_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (202_104_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (25_962_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (357_144_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) - } - fn receive_single_prepaid_message_proof() -> Weight { - (122_648_000 as Weight) + (74_385_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + fn receive_single_prepaid_message_proof() -> Weight { + (26_159_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } fn receive_delivery_proof_for_single_message() -> Weight { - (107_631_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (27_590_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (113_885_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + (27_354_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (155_151_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(8 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + (27_652_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 80ac810e8c921..3c5a24788ec6a 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -79,10 +79,12 @@ pub fn ensure_weights_are_correct( // verify `receive_messages_delivery_proof` weight components assert_ne!(W::receive_messages_delivery_proof_overhead(), 0); - assert_ne!(W::receive_messages_delivery_proof_messages_overhead(1), 0); - assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1), 0); assert_ne!(W::storage_proof_size_overhead(1), 0); + // `receive_messages_delivery_proof_messages_overhead` and + // `receive_messages_delivery_proof_relayers_overhead` may return zero if rewards are not paid + // during confirmations delivery, so we're not checking it here + // verify that the hardcoded value covers `receive_messages_delivery_proof` weight let actual_messages_delivery_confirmation_tx_weight = W::receive_messages_delivery_proof_weight( &PreComputedSize(W::expected_extra_storage_proof_size() as usize), diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index e203e3ef521e1..bf7384b814689 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_parachains` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-06-06, STEPS: 50, REPEAT: 20 +//! DATE: 2022-07-06, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -59,19 +59,19 @@ pub struct MillauWeight(PhantomData); impl WeightInfo for MillauWeight { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { (0 as Weight) - .saturating_add((18_729_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add((18_706_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - (25_355_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (27_549_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - (74_570_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) + (80_792_000 as Weight) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } } @@ -80,19 +80,19 @@ impl WeightInfo for MillauWeight { impl WeightInfo for () { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { (0 as Weight) - .saturating_add((18_729_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add((18_706_000 as Weight).saturating_mul(p as Weight)) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - (25_355_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + (27_549_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - (74_570_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) + (80_792_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 9d6a6f4862f18..050fa3ee1ae38 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -510,7 +510,7 @@ mod tests { // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (958, 216_583_333_334), + (1024, 216_583_333_334), ); } } From 0e2f19fa6cc109a7bb1eea0011b99d58ee580fee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 8 Jul 2022 21:04:39 +0300 Subject: [PATCH 0730/1210] Change account names to something meaningful (#1497) * change testnets account "names" to something meaningful * fixes * fix doc * fmt * account names as consts * fmt * spelling --- bin/millau/node/src/chain_spec.rs | 127 ++++++++---------- bin/rialto-parachain/node/src/chain_spec.rs | 54 +++++--- bin/rialto/node/src/chain_spec.rs | 98 ++++++-------- .../src/cli/relay_headers_and_messages.rs | 18 +-- 4 files changed, 146 insertions(+), 151 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 648e51e533ad2..3e812ca9aab28 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -15,7 +15,6 @@ // along with Parity Bridges Common. If not, see . use beefy_primitives::crypto::AuthorityId as BeefyId; -use bp_millau::derive_account_from_rialto_id; use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, @@ -26,6 +25,21 @@ use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; +/// "Names" of the authorities accounts at local testnet. +const LOCAL_AUTHORITIES_ACCOUNTS: [&str; 5] = ["Alice", "Bob", "Charlie", "Dave", "Eve"]; +/// "Names" of the authorities accounts at development testnet. +const DEV_AUTHORITIES_ACCOUNTS: [&str; 1] = [LOCAL_AUTHORITIES_ACCOUNTS[0]]; +/// "Names" of all possible authorities accounts. +const ALL_AUTHORITIES_ACCOUNTS: [&str; 5] = LOCAL_AUTHORITIES_ACCOUNTS; +/// "Name" of the `sudo` account. +const SUDO_ACCOUNT: &str = "Sudo"; +/// "Name" of the account, which owns the with-Westend GRANDPA pallet. +const WESTEND_GRANDPA_PALLET_OWNER: &str = "Westend.GrandpaOwner"; +/// "Name" of the account, which owns the with-Rialto messages pallet. +const RIALTO_MESSAGES_PALLET_OWNER: &str = "Rialto.MessagesOwner"; +/// "Name" of the account, which owns the with-RialtoParachain messages pallet. +const RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER: &str = "RialtoParachain.MessagesOwner"; + /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; @@ -86,8 +100,11 @@ impl Alternative { sc_service::ChainType::Development, || { testnet_genesis( - vec![get_authority_keys_from_seed("Alice")], - get_account_id_from_seed::("Alice"), + DEV_AUTHORITIES_ACCOUNTS + .into_iter() + .map(get_authority_keys_from_seed) + .collect(), + get_account_id_from_seed::(SUDO_ACCOUNT), endowed_accounts(), true, ) @@ -105,14 +122,11 @@ impl Alternative { sc_service::ChainType::Local, || { testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), - get_authority_keys_from_seed("Charlie"), - get_authority_keys_from_seed("Dave"), - get_authority_keys_from_seed("Eve"), - ], - get_account_id_from_seed::("Alice"), + LOCAL_AUTHORITIES_ACCOUNTS + .into_iter() + .map(get_authority_keys_from_seed) + .collect(), + get_account_id_from_seed::(SUDO_ACCOUNT), endowed_accounts(), true, ) @@ -133,56 +147,39 @@ impl Alternative { /// accounts used by relayers in our test deployments, accounts used for demonstration /// purposes), are all available on these chains. fn endowed_accounts() -> Vec { + let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { + [ + get_account_id_from_seed::(x), + get_account_id_from_seed::(&format!("{}//stash", x)), + ] + }); vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), + // Sudo account + get_account_id_from_seed::(SUDO_ACCOUNT), + // Regular (unused) accounts get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Harry"), - get_account_id_from_seed::("Iden"), - get_account_id_from_seed::("Ken"), - get_account_id_from_seed::("Leon"), - get_account_id_from_seed::("Mary"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("Harry//stash"), - get_account_id_from_seed::("Iden//stash"), - get_account_id_from_seed::("Ken//stash"), - get_account_id_from_seed::("Leon//stash"), - get_account_id_from_seed::("Mary//stash"), - get_account_id_from_seed::("RialtoMessagesOwner"), - get_account_id_from_seed::("RialtoParachainMessagesOwner"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_millau::AccountId, - bp_millau::AccountIdConverter, - >(), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Charlie"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Eve"), - )), - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Ferdie"), - )), + // Accounts, used by Westend<>Millau bridge + get_account_id_from_seed::(WESTEND_GRANDPA_PALLET_OWNER), + get_account_id_from_seed::("Westend.HeadersRelay1"), + get_account_id_from_seed::("Westend.HeadersRelay2"), + get_account_id_from_seed::("Westend.WestmintHeaders1"), + get_account_id_from_seed::("Westend.WestmintHeaders2"), + // Accounts, used by Rialto<>Millau bridge + get_account_id_from_seed::(RIALTO_MESSAGES_PALLET_OWNER), + get_account_id_from_seed::("Rialto.HeadersAndMessagesRelay"), + get_account_id_from_seed::("Rialto.OutboundMessagesRelay.Lane00000001"), + get_account_id_from_seed::("Rialto.InboundMessagesRelay.Lane00000001"), + get_account_id_from_seed::("Rialto.MessagesSender"), + // Accounts, used by RialtoParachain<>Millau bridge + get_account_id_from_seed::(RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER), + get_account_id_from_seed::("RialtoParachain.HeadersAndMessagesRelay"), + get_account_id_from_seed::("RialtoParachain.RialtoHeadersRelay"), + get_account_id_from_seed::("RialtoParachain.MessagesSender"), ] + .into_iter() + .chain(all_authorities) + .collect() } fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys { @@ -217,28 +214,20 @@ fn testnet_genesis( bridge_westend_grandpa: BridgeWestendGrandpaConfig { // for our deployments to avoid multiple same-nonces transactions: // //Alice is already used to initialize Rialto<->Millau bridge - // => let's use //George to initialize Westend->Millau bridge - owner: Some(get_account_id_from_seed::("George")), + // => let's use //Westend.GrandpaOwner to initialize Westend->Millau bridge + owner: Some(get_account_id_from_seed::(WESTEND_GRANDPA_PALLET_OWNER)), ..Default::default() }, bridge_rialto_messages: BridgeRialtoMessagesConfig { - owner: Some(get_account_id_from_seed::("RialtoMessagesOwner")), + owner: Some(get_account_id_from_seed::(RIALTO_MESSAGES_PALLET_OWNER)), ..Default::default() }, bridge_rialto_parachain_messages: BridgeRialtoParachainMessagesConfig { owner: Some(get_account_id_from_seed::( - "RialtoParachainMessagesOwner", + RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER, )), ..Default::default() }, xcm_pallet: Default::default(), } } - -#[test] -fn derived_dave_account_is_as_expected() { - let dave = get_account_id_from_seed::("Dave"); - let derived: AccountId = - derive_account_from_rialto_id(bp_runtime::SourceAccount::Account(dave)); - assert_eq!(derived.to_string(), "5DNW6UVnb7TN6wX5KwXtDYR3Eccecbdzuw89HqjyNfkzce6J".to_string()); -} diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index e22035905c978..6873730c1969a 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -22,6 +22,17 @@ use serde::{Deserialize, Serialize}; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; +/// "Names" of the authorities accounts at local testnet. +const LOCAL_AUTHORITIES_ACCOUNTS: [&str; 2] = ["Alice", "Bob"]; +/// "Names" of the authorities accounts at development testnet. +const DEV_AUTHORITIES_ACCOUNTS: [&str; 2] = LOCAL_AUTHORITIES_ACCOUNTS; +/// "Names" of all possible authorities accounts. +const ALL_AUTHORITIES_ACCOUNTS: [&str; 2] = LOCAL_AUTHORITIES_ACCOUNTS; +/// "Name" of the `sudo` account. +const SUDO_ACCOUNT: &str = "Sudo"; +/// "Name" of the account, which owns the with-Millau messages pallet. +const MILLAU_MESSAGES_PALLET_OWNER: &str = "Millau.MessagesOwner"; + /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; @@ -67,27 +78,32 @@ where /// accounts used by relayers in our test deployments, accounts used for demonstration /// purposes), are all available on these chains. fn endowed_accounts() -> Vec { + let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { + [ + get_account_id_from_seed::(x), + get_account_id_from_seed::(&format!("{}//stash", x)), + ] + }); vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), + // Sudo account + get_account_id_from_seed::(SUDO_ACCOUNT), + // Regular (unused) accounts get_account_id_from_seed::("Charlie"), get_account_id_from_seed::("Dave"), get_account_id_from_seed::("Eve"), get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("MillauMessagesOwner"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_rialto_parachain::AccountId, - bp_rialto_parachain::AccountIdConverter, - >(), + // Accounts, used by RialtoParachain<>Millau bridge + get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER), + get_account_id_from_seed::("Millau.HeadersAndMessagesRelay"), + get_account_id_from_seed::("Millau.MessagesSender"), ] + .into_iter() + .chain(all_authorities) + .collect() } pub fn development_config(id: ParaId) -> ChainSpec { @@ -104,8 +120,11 @@ pub fn development_config(id: ParaId) -> ChainSpec { ChainType::Local, move || { testnet_genesis( - get_account_id_from_seed::("Alice"), - vec![get_from_seed::("Alice"), get_from_seed::("Bob")], + get_account_id_from_seed::(SUDO_ACCOUNT), + DEV_AUTHORITIES_ACCOUNTS + .into_iter() + .map(|x| get_from_seed::(x)) + .collect(), endowed_accounts(), id, ) @@ -136,8 +155,11 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec { ChainType::Local, move || { testnet_genesis( - get_account_id_from_seed::("Alice"), - vec![get_from_seed::("Alice"), get_from_seed::("Bob")], + get_account_id_from_seed::(SUDO_ACCOUNT), + LOCAL_AUTHORITIES_ACCOUNTS + .into_iter() + .map(|x| get_from_seed::(x)) + .collect(), endowed_accounts(), id, ) @@ -174,7 +196,7 @@ fn testnet_genesis( aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), bridge_millau_messages: BridgeMillauMessagesConfig { - owner: Some(get_account_id_from_seed::("MillauMessagesOwner")), + owner: Some(get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER)), ..Default::default() }, } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 9b3dc288c4939..41958aaf3907d 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -15,7 +15,6 @@ // along with Parity Bridges Common. If not, see . use beefy_primitives::crypto::AuthorityId as BeefyId; -use bp_rialto::derive_account_from_millau_id; use polkadot_primitives::v2::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, @@ -29,6 +28,17 @@ use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; +/// "Names" of the authorities accounts at local testnet. +const LOCAL_AUTHORITIES_ACCOUNTS: [&str; 5] = ["Alice", "Bob", "Charlie", "Dave", "Eve"]; +/// "Names" of the authorities accounts at development testnet. +const DEV_AUTHORITIES_ACCOUNTS: [&str; 1] = [LOCAL_AUTHORITIES_ACCOUNTS[0]]; +/// "Names" of all possible authorities accounts. +const ALL_AUTHORITIES_ACCOUNTS: [&str; 5] = LOCAL_AUTHORITIES_ACCOUNTS; +/// "Name" of the `sudo` account. +const SUDO_ACCOUNT: &str = "Sudo"; +/// "Name" of the account, which owns the with-Millau messages pallet. +const MILLAU_MESSAGES_PALLET_OWNER: &str = "Millau.MessagesOwner"; + /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; @@ -95,8 +105,11 @@ impl Alternative { sc_service::ChainType::Development, || { testnet_genesis( - vec![get_authority_keys_from_seed("Alice")], - get_account_id_from_seed::("Alice"), + DEV_AUTHORITIES_ACCOUNTS + .into_iter() + .map(get_authority_keys_from_seed) + .collect(), + get_account_id_from_seed::(SUDO_ACCOUNT), endowed_accounts(), true, ) @@ -114,14 +127,11 @@ impl Alternative { sc_service::ChainType::Local, || { testnet_genesis( - vec![ - get_authority_keys_from_seed("Alice"), - get_authority_keys_from_seed("Bob"), - get_authority_keys_from_seed("Charlie"), - get_authority_keys_from_seed("Dave"), - get_authority_keys_from_seed("Eve"), - ], - get_account_id_from_seed::("Alice"), + LOCAL_AUTHORITIES_ACCOUNTS + .into_iter() + .map(get_authority_keys_from_seed) + .collect(), + get_account_id_from_seed::(SUDO_ACCOUNT), endowed_accounts(), true, ) @@ -142,48 +152,28 @@ impl Alternative { /// accounts used by relayers in our test deployments, accounts used for demonstration /// purposes), are all available on these chains. fn endowed_accounts() -> Vec { + let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { + [ + get_account_id_from_seed::(x), + get_account_id_from_seed::(&format!("{}//stash", x)), + ] + }); vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), + // Sudo account + get_account_id_from_seed::(SUDO_ACCOUNT), + // Regular (unused) accounts get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("George"), - get_account_id_from_seed::("Harry"), - get_account_id_from_seed::("Alice//stash"), - get_account_id_from_seed::("Bob//stash"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), - get_account_id_from_seed::("George//stash"), - get_account_id_from_seed::("Harry//stash"), - get_account_id_from_seed::("MillauMessagesOwner"), - get_account_id_from_seed::("WithMillauTokenSwap"), - pallet_bridge_messages::relayer_fund_account_id::< - bp_rialto::AccountId, - bp_rialto::AccountIdConverter, - >(), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Alice"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Bob"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Charlie"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Dave"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Eve"), - )), - derive_account_from_millau_id(bp_runtime::SourceAccount::Account( - get_account_id_from_seed::("Ferdie"), - )), + // Accounts, used by Rialto<>Millau bridge + get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER), + get_account_id_from_seed::("Millau.HeadersAndMessagesRelay"), + get_account_id_from_seed::("Millau.OutboundMessagesRelay.Lane00000001"), + get_account_id_from_seed::("Millau.InboundMessagesRelay.Lane00000001"), + get_account_id_from_seed::("Millau.MessagesSender"), ] + .into_iter() + .chain(all_authorities) + .collect() } fn session_keys( @@ -287,17 +277,9 @@ fn testnet_genesis( }, paras: Default::default(), bridge_millau_messages: BridgeMillauMessagesConfig { - owner: Some(get_account_id_from_seed::("MillauMessagesOwner")), + owner: Some(get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER)), ..Default::default() }, xcm_pallet: Default::default(), } } - -#[test] -fn derived_dave_account_is_as_expected() { - let dave = get_account_id_from_seed::("Dave"); - let derived: AccountId = - derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); - assert_eq!(derived.to_string(), "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string()); -} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 3fb84caed2c1e..c1e0acaea3c75 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -754,7 +754,7 @@ mod tests { "--millau-signer", "//Charlie", "--millau-messages-pallet-owner", - "//RialtoMessagesOwner", + "//Rialto.MessagesOwner", "--millau-transactions-mortality", "64", "--rialto-host", @@ -764,7 +764,7 @@ mod tests { "--rialto-signer", "//Charlie", "--rialto-messages-pallet-owner", - "//MillauMessagesOwner", + "//Millau.MessagesOwner", "--rialto-transactions-mortality", "64", "--lane", @@ -811,7 +811,7 @@ mod tests { millau_transactions_mortality: Some(64), }, left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { - millau_messages_pallet_owner: Some("//RialtoMessagesOwner".into()), + millau_messages_pallet_owner: Some("//Rialto.MessagesOwner".into()), millau_messages_pallet_owner_password: None, }, left_headers_to_right_sign_override: MillauHeadersToRialtoSigningParams { @@ -839,7 +839,7 @@ mod tests { rialto_transactions_mortality: Some(64), }, right_messages_pallet_owner: RialtoMessagesPalletOwnerSigningParams { - rialto_messages_pallet_owner: Some("//MillauMessagesOwner".into()), + rialto_messages_pallet_owner: Some("//Millau.MessagesOwner".into()), rialto_messages_pallet_owner_password: None, }, right_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { @@ -868,7 +868,7 @@ mod tests { "--rialto-headers-to-millau-signer", "//Ken", "--millau-messages-pallet-owner", - "//RialtoParachainMessagesOwner", + "//RialtoParachain.MessagesOwner", "--millau-transactions-mortality", "64", "--rialto-parachain-host", @@ -878,7 +878,7 @@ mod tests { "--rialto-parachain-signer", "//George", "--rialto-parachain-messages-pallet-owner", - "//MillauMessagesOwner", + "//Millau.MessagesOwner", "--rialto-parachain-transactions-mortality", "64", "--rialto-host", @@ -925,7 +925,9 @@ mod tests { millau_transactions_mortality: Some(64), }, left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { - millau_messages_pallet_owner: Some("//RialtoParachainMessagesOwner".into()), + millau_messages_pallet_owner: Some( + "//RialtoParachain.MessagesOwner".into() + ), millau_messages_pallet_owner_password: None, }, left_headers_to_right_sign_override: @@ -955,7 +957,7 @@ mod tests { }, right_messages_pallet_owner: RialtoParachainMessagesPalletOwnerSigningParams { rialto_parachain_messages_pallet_owner: Some( - "//MillauMessagesOwner".into() + "//Millau.MessagesOwner".into() ), rialto_parachain_messages_pallet_owner_password: None, }, From 622f762cf0e050264f81606d748c32f5dd9db48e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 12 Jul 2022 11:07:38 +0300 Subject: [PATCH 0731/1210] remove account derivation functions (#1498) --- bin/millau/runtime/src/lib.rs | 4 - bin/millau/runtime/src/rialto_messages.rs | 1 - bin/rialto-parachain/runtime/src/lib.rs | 2 - bin/rialto/runtime/src/lib.rs | 2 - bin/rialto/runtime/src/millau_messages.rs | 1 - bin/runtime-common/src/integrity.rs | 9 +- modules/messages/src/benchmarking.rs | 16 ---- modules/messages/src/lib.rs | 25 +----- modules/messages/src/mock.rs | 12 --- primitives/chain-kusama/src/lib.rs | 7 -- primitives/chain-millau/src/lib.rs | 39 +-------- primitives/chain-polkadot/src/lib.rs | 7 -- primitives/chain-rialto-parachain/src/lib.rs | 24 +----- primitives/chain-rialto/src/lib.rs | 24 +----- primitives/chain-rococo/src/lib.rs | 7 -- primitives/chain-westend/src/lib.rs | 7 -- primitives/chain-wococo/src/lib.rs | 7 -- primitives/messages/src/source_chain.rs | 6 -- primitives/polkadot-core/src/lib.rs | 9 -- primitives/runtime/src/lib.rs | 10 --- relays/bin-substrate/src/cli/bridge.rs | 32 -------- .../src/cli/relay_headers_and_messages.rs | 82 ------------------- 22 files changed, 6 insertions(+), 327 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8b2988d421fdc..4041cfe171b30 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -461,8 +461,6 @@ impl pallet_bridge_messages::Config for Runtime { type InboundMessageFee = bp_rialto::Balance; type InboundRelayer = bp_rialto::AccountId; - type AccountIdConverter = bp_millau::AccountIdConverter; - type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type MessageDeliveryAndDispatchPayment = (); @@ -494,8 +492,6 @@ impl pallet_bridge_messages::Config for Run type InboundMessageFee = bp_rialto_parachain::Balance; type InboundRelayer = bp_rialto_parachain::AccountId; - type AccountIdConverter = bp_millau::AccountIdConverter; - type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; type MessageDeliveryAndDispatchPayment = (); diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index bbcc6144f8521..5d192bd56ad26 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -371,7 +371,6 @@ mod tests { bridge: WithRialtoMessageBridge, this_chain: bp_millau::Millau, bridged_chain: bp_rialto::Rialto, - this_chain_account_id_converter: bp_millau::AccountIdConverter ); assert_complete_bridge_constants::< diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 37930c3555412..f2463b5e06f51 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -528,8 +528,6 @@ impl pallet_bridge_messages::Config for Runtime { type InboundMessageFee = bp_millau::Balance; type InboundRelayer = bp_millau::AccountId; - type AccountIdConverter = bp_rialto_parachain::AccountIdConverter; - type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = (); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 3d468a5b4ec1c..e06fdffe88909 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -445,8 +445,6 @@ impl pallet_bridge_messages::Config for Runtime { type InboundMessageFee = bp_millau::Balance; type InboundRelayer = bp_millau::AccountId; - type AccountIdConverter = bp_rialto::AccountIdConverter; - type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = (); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index d547dde538fec..e5e95e3d4a351 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -368,7 +368,6 @@ mod tests { bridge: WithMillauMessageBridge, this_chain: bp_rialto::Rialto, bridged_chain: bp_millau::Millau, - this_chain_account_id_converter: bp_rialto::AccountIdConverter ); assert_complete_bridge_constants::< diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index a145d81e9b230..850c71181ef34 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -105,8 +105,7 @@ macro_rules! assert_bridge_messages_pallet_types( ( runtime: $r:path, with_bridged_chain_messages_instance: $i:path, - bridge: $bridge:path, - this_chain_account_id_converter: $this_converter:path + bridge: $bridge:path ) => { { // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard @@ -127,8 +126,6 @@ macro_rules! assert_bridge_messages_pallet_types( assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundMessageFee, BalanceOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::AccountIdConverter, $this_converter); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, BridgedChain<$bridge>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::SourceHeaderChain, BridgedChain<$bridge>); } @@ -148,7 +145,6 @@ macro_rules! assert_complete_bridge_types( bridge: $bridge:path, this_chain: $this:path, bridged_chain: $bridged:path, - this_chain_account_id_converter: $this_converter:path ) => { $crate::assert_chain_types!(runtime: $r, this_chain: $this); $crate::assert_bridge_types!(bridge: $bridge, this_chain: $this, bridged_chain: $bridged); @@ -160,8 +156,7 @@ macro_rules! assert_complete_bridge_types( $crate::assert_bridge_messages_pallet_types!( runtime: $r, with_bridged_chain_messages_instance: $mi, - bridge: $bridge, - this_chain_account_id_converter: $this_converter + bridge: $bridge ); } ); diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 78a04d22868f1..9c74265e2da67 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -126,10 +126,8 @@ benchmarks_instance_pallet! { // added. send_minimal_message_worst_case { let lane_id = T::bench_lane_id(); - let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); - T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -159,10 +157,8 @@ benchmarks_instance_pallet! { // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_1_kb_message_worst_case { let lane_id = T::bench_lane_id(); - let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); - T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -198,10 +194,8 @@ benchmarks_instance_pallet! { // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. send_16_kb_message_worst_case { let lane_id = T::bench_lane_id(); - let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 0, SEED); T::endow_account(&sender); - T::endow_account(&relayers_fund_id); // 'send' messages that are to be pruned when our message is sent for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { @@ -233,10 +227,8 @@ benchmarks_instance_pallet! { // // Result of this benchmark is directly used by weight formula of the call. maximal_increase_message_fee { - let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 42, SEED); T::endow_account(&sender); - T::endow_account(&relayers_fund_id); let additional_fee = T::account_balance(&sender); let lane_id = T::bench_lane_id(); @@ -257,10 +249,8 @@ benchmarks_instance_pallet! { increase_message_fee { let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); - let relayers_fund_id = crate::relayer_fund_account_id::(); let sender = account("sender", 42, SEED); T::endow_account(&sender); - T::endow_account(&relayers_fund_id); let additional_fee = T::account_balance(&sender); let lane_id = T::bench_lane_id(); @@ -488,10 +478,8 @@ benchmarks_instance_pallet! { // // This is base benchmark for all other confirmations delivery benchmarks. receive_delivery_proof_for_single_message { - let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); - T::endow_account(&relayers_fund_id); // send message that we're going to confirm send_regular_message::(); @@ -526,10 +514,8 @@ benchmarks_instance_pallet! { // as `weight(receive_delivery_proof_for_two_messages_by_single_relayer) // - weight(receive_delivery_proof_for_single_message)`. receive_delivery_proof_for_two_messages_by_single_relayer { - let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer_id: T::AccountId = account("relayer", 0, SEED); let relayer_balance = T::account_balance(&relayer_id); - T::endow_account(&relayers_fund_id); // send message that we're going to confirm send_regular_message::(); @@ -567,12 +553,10 @@ benchmarks_instance_pallet! { // as `weight(receive_delivery_proof_for_two_messages_by_two_relayers) // - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`. receive_delivery_proof_for_two_messages_by_two_relayers { - let relayers_fund_id = crate::relayer_fund_account_id::(); let relayer1_id: T::AccountId = account("relayer1", 1, SEED); let relayer1_balance = T::account_balance(&relayer1_id); let relayer2_id: T::AccountId = account("relayer2", 2, SEED); let relayer2_balance = T::account_balance(&relayer2_id); - T::endow_account(&relayers_fund_id); // send message that we're going to confirm send_regular_message::(); diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 26e62a07d7b6d..ca4b7044b2cfb 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -71,8 +71,6 @@ use frame_support::{ weights::{Pays, PostDispatchInfo}, }; use num_traits::{SaturatingAdd, Zero}; -use sp_core::H256; -use sp_runtime::traits::Convert; use sp_std::{ cell::RefCell, cmp::PartialOrd, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, prelude::*, @@ -170,11 +168,6 @@ pub mod pallet { /// bridged chain. type InboundRelayer: Parameter + MaxEncodedLen; - /// A type which can be turned into an AccountId from a 256-bit hash. - /// - /// Used when deriving the shared relayer fund account. - type AccountIdConverter: sp_runtime::traits::Convert; - // Types that are used by outbound_lane (on source chain). /// Target header chain. @@ -313,16 +306,14 @@ pub mod pallet { T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( &origin, &additional_fee, - &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( target: LOG_TARGET, - "Submitter can't pay additional fee {:?} for the message {:?}/{:?} to {:?}: {:?}", + "Submitter can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", additional_fee, lane_id, nonce, - relayer_fund_account_id::(), err, ); @@ -629,14 +620,11 @@ pub mod pallet { }); // if some new messages have been confirmed, reward relayers - let relayer_fund_account = - relayer_fund_account_id::(); >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( lane_id, lane_data.relayers, &confirmation_relayer, &received_range, - &relayer_fund_account, ); } @@ -787,16 +775,6 @@ pub mod pallet { } } -/// AccountId of the shared relayer fund account. -/// -/// This account is passed to `MessageDeliveryAndDispatchPayment` trait, and depending -/// on the implementation it can be used to store relayers rewards. -pub fn relayer_fund_account_id>( -) -> AccountId { - let encoded_id = bp_runtime::derive_relayer_fund_account_id(bp_runtime::NO_INSTANCE_ID); - AccountIdConverter::convert(encoded_id) -} - impl bp_messages::source_chain::MessagesBridge< T::Origin, @@ -877,7 +855,6 @@ fn send_message, I: 'static>( T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( &submitter, &delivery_and_dispatch_fee, - &relayer_fund_account_id::(), ) .map_err(|err| { log::trace!( diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index b836517e419a2..9584d17b836b0 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -68,14 +68,6 @@ pub struct TestPayload { pub type TestMessageFee = u64; pub type TestRelayer = u64; -pub struct AccountIdConverter; - -impl sp_runtime::traits::Convert for AccountIdConverter { - fn convert(hash: H256) -> AccountId { - hash.to_low_u64_ne() - } -} - type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -182,8 +174,6 @@ impl Config for TestRuntime { type InboundMessageFee = TestMessageFee; type InboundRelayer = TestRelayer; - type AccountIdConverter = AccountIdConverter; - type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; @@ -360,7 +350,6 @@ impl MessageDeliveryAndDispatchPayment fn pay_delivery_and_dispatch_fee( submitter: &Origin, fee: &TestMessageFee, - _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) { return Err(TEST_ERROR) @@ -376,7 +365,6 @@ impl MessageDeliveryAndDispatchPayment message_relayers: VecDeque>, _confirmation_relayer: &AccountId, received_range: &RangeInclusive, - _relayer_fund_account: &AccountId, ) { let relayers_rewards = calc_relayers_rewards::(lane_id, message_relayers, received_range); diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 637f6b9da03f7..f3450a77dcbff 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -63,13 +63,6 @@ impl WeightToFeePolynomial for WeightToFee { } } -// We use this to get the account on Kusama (target) which is derived from Polkadot's (source) -// account. -pub fn derive_account_from_polkadot_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::POLKADOT_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - /// Per-byte fee for Kusama transactions. pub const TRANSACTION_BYTE_FEE: Balance = 10 * 1_000_000_000_000 / 30_000 / 1_000; diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 48c80e7017a08..6bdd9c53ee133 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -32,7 +32,7 @@ use frame_system::limits; use scale_info::TypeInfo; use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ - traits::{Convert, IdentifyAccount, Verify}, + traits::{IdentifyAccount, Verify}, FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -218,43 +218,6 @@ impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { } } -/// Convert a 256-bit hash into an AccountId. -pub struct AccountIdConverter; - -impl sp_runtime::traits::Convert for AccountIdConverter { - fn convert(hash: sp_core::H256) -> AccountId { - hash.to_fixed_bytes().into() - } -} - -/// We use this to get the account on Millau (target) which is derived from Rialto's (source) -/// account. We do this so we can fund the derived account on Millau at Genesis to it can pay -/// transaction fees. -/// -/// The reason we can use the same `AccountId` type for both chains is because they share the same -/// development seed phrase. -/// -/// Note that this should only be used for testing. -pub fn derive_account_from_rialto_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - -/// We use this to get the account on Millau (target) which is derived from RialtoParachain's -/// (source) account. We do this so we can fund the derived account on Millau at Genesis to it can -/// pay transaction fees. -/// -/// The reason we can use the same `AccountId` type for both chains is because they share the same -/// development seed phrase. -/// -/// Note that this should only be used for testing. -pub fn derive_account_from_rialto_parachain_id( - id: bp_runtime::SourceAccount, -) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::RIALTO_PARACHAIN_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index f06bb917edc71..af195e511c4c8 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -63,13 +63,6 @@ impl WeightToFeePolynomial for WeightToFee { } } -// We use this to get the account on Polkadot (target) which is derived from Kusama's (source) -// account. -pub fn derive_account_from_kusama_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::KUSAMA_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - /// Per-byte fee for Polkadot transactions. pub const TRANSACTION_BYTE_FEE: Balance = 10 * 10_000_000_000 / 100 / 1_000; diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 9e54744f2d29b..00402ae49d2f6 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{ use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ - traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, + traits::{BlakeTwo256, IdentifyAccount, Verify}, FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::vec::Vec; @@ -161,15 +161,6 @@ impl Chain for RialtoParachain { } } -/// Convert a 256-bit hash into an AccountId. -pub struct AccountIdConverter; - -impl Convert for AccountIdConverter { - fn convert(hash: sp_core::H256) -> AccountId { - hash.to_fixed_bytes().into() - } -} - frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); @@ -218,19 +209,6 @@ pub const TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = pub const FROM_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = "FromRialtoParachainInboundLaneApi_message_details"; -// We use this to get the account on RialtoParachain (target) which is derived from Millau's -// (source) account. We do this so we can fund the derived account on RialtoParachain at Genesis to -// it can pay transaction fees. -// -// The reason we can use the same `AccountId` type for both chains is because they share the same -// development seed phrase. -// -// Note that this should only be used for testing. -pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - sp_api::decl_runtime_apis! { /// API for querying information about the finalized RialtoParachain headers. /// diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 9acc9f9f9a6db..e5d1abbc7e630 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{ use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ - traits::{BlakeTwo256, Convert, IdentifyAccount, Verify}, + traits::{BlakeTwo256, IdentifyAccount, Verify}, FixedU128, MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -181,28 +181,6 @@ impl Chain for Rialto { } } -/// Convert a 256-bit hash into an AccountId. -pub struct AccountIdConverter; - -impl Convert for AccountIdConverter { - fn convert(hash: sp_core::H256) -> AccountId { - hash.to_fixed_bytes().into() - } -} - -// We use this to get the account on Rialto (target) which is derived from Millau's (source) -// account. We do this so we can fund the derived account on Rialto at Genesis to it can pay -// transaction fees. -// -// The reason we can use the same `AccountId` type for both chains is because they share the same -// development seed phrase. -// -// Note that this should only be used for testing. -pub fn derive_account_from_millau_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::MILLAU_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 1c2bfb42d0f0d..ad3190a12235f 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -69,13 +69,6 @@ impl WeightToFeePolynomial for WeightToFee { } } -// We use this to get the account on Rococo (target) which is derived from Wococo's (source) -// account. -pub fn derive_account_from_wococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::WOCOCO_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - /// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; /// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 0dc4ccc65aea1..16c0252ea77ac 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -79,13 +79,6 @@ impl sp_runtime::traits::Dispatchable for Call { } } -// We use this to get the account on Westend (target) which is derived from Rococo's (source) -// account. -pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - /// Name of the parachains pallet at the Westend runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 6e0bad1227404..83d913db7fc13 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -38,13 +38,6 @@ pub type Wococo = PolkadotLike; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::MINUTES; -// We use this to get the account on Wococo (target) which is derived from Rococo's (source) -// account. -pub fn derive_account_from_rococo_id(id: bp_runtime::SourceAccount) -> AccountId { - let encoded_id = bp_runtime::derive_account_id(bp_runtime::ROCOCO_CHAIN_ID, id); - AccountIdConverter::convert(encoded_id) -} - /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; /// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 8451941a40ebf..be56ffe87fb3d 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -133,7 +133,6 @@ pub trait MessageDeliveryAndDispatchPayment { fn pay_delivery_and_dispatch_fee( submitter: &SenderOrigin, fee: &Balance, - relayer_fund_account: &AccountId, ) -> Result<(), Self::Error>; /// Pay rewards for delivering messages to the given relayers. @@ -145,7 +144,6 @@ pub trait MessageDeliveryAndDispatchPayment { messages_relayers: VecDeque>, confirmation_relayer: &AccountId, received_range: &RangeInclusive, - relayer_fund_account: &AccountId, ); } @@ -157,7 +155,6 @@ impl fn pay_delivery_and_dispatch_fee( _submitter: &SenderOrigin, _fee: &Balance, - _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { Ok(()) } @@ -167,7 +164,6 @@ impl _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, _received_range: &RangeInclusive, - _relayer_fund_account: &AccountId, ) { } } @@ -306,7 +302,6 @@ impl fn pay_delivery_and_dispatch_fee( _submitter: &SenderOrigin, _fee: &Balance, - _relayer_fund_account: &AccountId, ) -> Result<(), Self::Error> { Err(ALL_OUTBOUND_MESSAGES_REJECTED) } @@ -316,7 +311,6 @@ impl _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, _received_range: &RangeInclusive, - _relayer_fund_account: &AccountId, ) { } } diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 4b0ef430ad533..6245c2b1694d9 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -390,15 +390,6 @@ impl Chain for PolkadotLike { } } -/// Convert a 256-bit hash into an AccountId. -pub struct AccountIdConverter; - -impl Convert for AccountIdConverter { - fn convert(hash: sp_core::H256) -> AccountId { - hash.to_fixed_bytes().into() - } -} - /// Return a storage key for account data. /// /// This is based on FRAME storage-generation code from Substrate: diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 2849e346da426..ca8a22ee16a60 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -127,16 +127,6 @@ where .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: ChainId) -> H256 { - ("relayer-fund-account", bridge_id).using_encoded(blake2_256).into() -} - /// Anything that has size. pub trait Size { /// Return size of this object (in bytes). diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 103c9cb391a46..3ef324265c3c2 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -15,7 +15,6 @@ // along with Parity Bridges Common. If not, see . use crate::cli::CliChain; -use bp_runtime::{AccountIdOf, SourceAccount}; use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ @@ -82,11 +81,6 @@ pub trait MessagesCliBridge: CliBridgeBase { SourceTransactionSignScheme = Self::Source, TargetTransactionSignScheme = Self::Target, >; - - /// We use this to get the account on the target which is derived from the source account. - fn derive_account_from_id( - id: SourceAccount>, - ) -> AccountIdOf; } //// `Millau` to `Rialto` bridge definition. @@ -105,12 +99,6 @@ impl MessagesCliBridge for MillauToRialtoCliBridge { const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; - - fn derive_account_from_id( - id: SourceAccount>, - ) -> AccountIdOf { - bp_rialto::derive_account_from_millau_id(id) - } } //// `Rialto` to `Millau` bridge definition. @@ -129,14 +117,6 @@ impl MessagesCliBridge for RialtoToMillauCliBridge { const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; - - /// We use this to get the account on the target chain which is derived from - /// the source chain account. - fn derive_account_from_id( - id: SourceAccount>, - ) -> AccountIdOf { - bp_millau::derive_account_from_rialto_id(id) - } } //// `Westend` to `Millau` bridge definition. @@ -169,12 +149,6 @@ impl MessagesCliBridge for MillauToRialtoParachainCliBridge { bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; - - fn derive_account_from_id( - id: SourceAccount>, - ) -> AccountIdOf { - bp_rialto_parachain::derive_account_from_millau_id(id) - } } //// `RialtoParachain` to `Millau` bridge definition. @@ -190,12 +164,6 @@ impl MessagesCliBridge for RialtoParachainToMillauCliBridge { bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; - - fn derive_account_from_id( - id: SourceAccount>, - ) -> AccountIdOf { - bp_millau::derive_account_from_rialto_parachain_id(id) - } } //// `WestendParachain` to `Millau` bridge definition. diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index c1e0acaea3c75..4d6456cc6198e 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -77,9 +77,6 @@ pub struct HeadersAndMessagesSharedParams { lane: Vec, #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] relayer_mode: RelayerMode, - /// Create relayers fund accounts on both chains, if it does not exists yet. - #[structopt(long)] - create_relayers_fund_accounts: bool, /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) /// are relayed. #[structopt(long)] @@ -185,9 +182,6 @@ macro_rules! select_bridge { type Left = relay_millau_client::Millau; type Right = relay_rialto_client::Rialto; - type LeftAccountIdConverter = bp_millau::AccountIdConverter; - type RightAccountIdConverter = bp_rialto::AccountIdConverter; - use crate::chains::{ millau_messages_to_rialto::MillauMessagesToRialto as LeftToRightMessageLane, rialto_messages_to_millau::RialtoMessagesToMillau as RightToLeftMessageLane, @@ -222,22 +216,6 @@ macro_rules! select_bridge { ).await } - async fn left_create_account( - _left_client: Client, - _left_sign: ::AccountKeyPair, - _account_id: AccountIdOf, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) - } - - async fn right_create_account( - _right_client: Client, - _right_sign: ::AccountKeyPair, - _account_id: AccountIdOf, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) - } - $generic }, RelayHeadersAndMessages::MillauRialtoParachain(_) => { @@ -246,9 +224,6 @@ macro_rules! select_bridge { type Left = relay_millau_client::Millau; type Right = relay_rialto_parachain_client::RialtoParachain; - type LeftAccountIdConverter = bp_millau::AccountIdConverter; - type RightAccountIdConverter = bp_rialto_parachain::AccountIdConverter; - use crate::chains::{ millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as LeftToRightMessageLane, rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as RightToLeftMessageLane, @@ -290,22 +265,6 @@ macro_rules! select_bridge { ).await } - async fn left_create_account( - _left_client: Client, - _left_sign: ::AccountKeyPair, - _account_id: AccountIdOf, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) - } - - async fn right_create_account( - _right_client: Client, - _right_sign: ::AccountKeyPair, - _account_id: AccountIdOf, - ) -> anyhow::Result<()> { - Err(anyhow::format_err!("Account creation is not supported by this bridge")) - } - $generic }, } @@ -445,45 +404,6 @@ impl RelayHeadersAndMessages { }); } - // optionally, create relayers fund account - if params.shared.create_relayers_fund_accounts { - let relayer_fund_acount_id = pallet_bridge_messages::relayer_fund_account_id::< - AccountIdOf, - LeftAccountIdConverter, - >(); - let relayers_fund_account_balance = - left_client.free_native_balance(relayer_fund_acount_id.clone()).await; - if let Err(relay_substrate_client::Error::AccountDoesNotExist) = - relayers_fund_account_balance - { - log::info!(target: "bridge", "Going to create relayers fund account at {}.", Left::NAME); - left_create_account( - left_client.clone(), - left_sign.clone(), - relayer_fund_acount_id, - ) - .await?; - } - - let relayer_fund_acount_id = pallet_bridge_messages::relayer_fund_account_id::< - AccountIdOf, - RightAccountIdConverter, - >(); - let relayers_fund_account_balance = - right_client.free_native_balance(relayer_fund_acount_id.clone()).await; - if let Err(relay_substrate_client::Error::AccountDoesNotExist) = - relayers_fund_account_balance - { - log::info!(target: "bridge", "Going to create relayers fund account at {}.", Right::NAME); - right_create_account( - right_client.clone(), - right_sign.clone(), - relayer_fund_acount_id, - ) - .await?; - } - } - // start on-demand header relays let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = start_on_demand_relays( @@ -785,7 +705,6 @@ mod tests { HexLaneId([0x73, 0x77, 0x61, 0x70]) ], relayer_mode: RelayerMode::Rational, - create_relayers_fund_accounts: false, only_mandatory_headers: false, prometheus_params: PrometheusParams { no_prometheus: false, @@ -899,7 +818,6 @@ mod tests { shared: HeadersAndMessagesSharedParams { lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], relayer_mode: RelayerMode::Rational, - create_relayers_fund_accounts: false, only_mandatory_headers: false, prometheus_params: PrometheusParams { no_prometheus: false, From 6e5277a44114998cfaf322cdb32ec03af478764e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 13 Jul 2022 14:07:36 +0300 Subject: [PATCH 0732/1210] CLI refactoring * [CLI] Make bridge definitions more complete * [CLI] Refactor relay_headers_and_messages Signed-off-by: Serban Iorga --- bin/runtime-common/src/messages.rs | 2 +- relays/bin-substrate/src/cli/bridge.rs | 55 +- relays/bin-substrate/src/cli/chain_schema.rs | 409 ++++++++ relays/bin-substrate/src/cli/estimate_fee.rs | 6 +- relays/bin-substrate/src/cli/init_bridge.rs | 6 +- relays/bin-substrate/src/cli/mod.rs | 366 +------ .../src/cli/register_parachain.rs | 11 +- relays/bin-substrate/src/cli/relay_headers.rs | 17 +- .../src/cli/relay_headers_and_messages.rs | 910 ------------------ .../src/cli/relay_headers_and_messages/mod.rs | 694 +++++++++++++ .../relay_to_parachain.rs | 235 +++++ .../relay_to_relay.rs | 187 ++++ .../bin-substrate/src/cli/relay_messages.rs | 23 +- .../bin-substrate/src/cli/relay_parachains.rs | 55 +- .../src/cli/resubmit_transactions.rs | 4 +- relays/bin-substrate/src/cli/send_message.rs | 9 +- relays/client-substrate/src/client.rs | 9 + .../src/messages_metrics.rs | 2 +- 18 files changed, 1635 insertions(+), 1365 deletions(-) create mode 100644 relays/bin-substrate/src/cli/chain_schema.rs delete mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages.rs create mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs create mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs create mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index e8f8fc1f7f038..173a501032f6e 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -860,7 +860,7 @@ pub mod target { return Err(MessageProofError::Empty) } - // We only support single lane messages in this schema + // We only support single lane messages in this generated_schema let mut proved_messages = ProvedMessages::new(); proved_messages.insert(lane, proved_lane_messages); diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 3ef324265c3c2..e0d65e3caf9b1 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -15,10 +15,14 @@ // along with Parity Bridges Common. If not, see . use crate::cli::CliChain; -use relay_substrate_client::{AccountKeyPairOf, Chain, TransactionSignScheme}; +use messages_relay::relay_strategy::MixStrategy; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use parachains_relay::ParachainsPipeline; +use relay_substrate_client::{AccountKeyPairOf, Chain, RelayChain, TransactionSignScheme}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, + parachains::SubstrateParachainsPipeline, }; #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] @@ -59,8 +63,9 @@ pub trait CliBridgeBase: Sized { + CliChain>; } -/// Bridge representation that can be used from the CLI for relaying headers. -pub trait HeadersCliBridge: CliBridgeBase { +/// Bridge representation that can be used from the CLI for relaying headers +/// from a relay chain to a relay chain. +pub trait RelayToRelayHeadersCliBridge: CliBridgeBase { /// Finality proofs synchronization pipeline. type Finality: SubstrateFinalitySyncPipeline< SourceChain = Self::Source, @@ -69,6 +74,29 @@ pub trait HeadersCliBridge: CliBridgeBase { >; } +/// Bridge representation that can be used from the CLI for relaying headers +/// from a parachain to a relay chain. +pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase { + // The `CliBridgeBase` type represents the parachain in this situation. + // We need to add an extra type for the relay chain. + type SourceRelay: Chain + + CliChain + + RelayChain; + /// Finality proofs synchronization pipeline (source parachain -> target). + type ParachainFinality: SubstrateParachainsPipeline< + SourceRelayChain = Self::SourceRelay, + SourceParachain = Self::Source, + TargetChain = Self::Target, + TransactionSignScheme = Self::Target, + > + ParachainsPipeline; + /// Finality proofs synchronization pipeline (source relay chain -> target). + type RelayFinality: SubstrateFinalitySyncPipeline< + SourceChain = Self::SourceRelay, + TargetChain = Self::Target, + TransactionSignScheme = Self::Target, + >; +} + /// Bridge representation that can be used from the CLI for relaying messages. pub trait MessagesCliBridge: CliBridgeBase { /// Name of the runtime method used to estimate the message dispatch and delivery fee for the @@ -80,6 +108,7 @@ pub trait MessagesCliBridge: CliBridgeBase { TargetChain = Self::Target, SourceTransactionSignScheme = Self::Source, TargetTransactionSignScheme = Self::Target, + RelayStrategy = MixStrategy, >; } @@ -91,7 +120,7 @@ impl CliBridgeBase for MillauToRialtoCliBridge { type Target = relay_rialto_client::Rialto; } -impl HeadersCliBridge for MillauToRialtoCliBridge { +impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; } @@ -109,7 +138,7 @@ impl CliBridgeBase for RialtoToMillauCliBridge { type Target = relay_millau_client::Millau; } -impl HeadersCliBridge for RialtoToMillauCliBridge { +impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; } @@ -127,7 +156,7 @@ impl CliBridgeBase for WestendToMillauCliBridge { type Target = relay_millau_client::Millau; } -impl HeadersCliBridge for WestendToMillauCliBridge { +impl RelayToRelayHeadersCliBridge for WestendToMillauCliBridge { type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; } @@ -139,7 +168,7 @@ impl CliBridgeBase for MillauToRialtoParachainCliBridge { type Target = relay_rialto_parachain_client::RialtoParachain; } -impl HeadersCliBridge for MillauToRialtoParachainCliBridge { +impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { type Finality = crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; } @@ -159,6 +188,12 @@ impl CliBridgeBase for RialtoParachainToMillauCliBridge { type Target = relay_millau_client::Millau; } +impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge { + type SourceRelay = relay_rialto_client::Rialto; + type ParachainFinality = crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau; + type RelayFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; +} + impl MessagesCliBridge for RialtoParachainToMillauCliBridge { const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; @@ -169,6 +204,12 @@ impl MessagesCliBridge for RialtoParachainToMillauCliBridge { //// `WestendParachain` to `Millau` bridge definition. pub struct WestmintToMillauCliBridge {} +impl ParachainToRelayHeadersCliBridge for WestmintToMillauCliBridge { + type SourceRelay = relay_westend_client::Westend; + type ParachainFinality = crate::chains::westend_parachains_to_millau::WestendParachainsToMillau; + type RelayFinality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; +} + impl CliBridgeBase for WestmintToMillauCliBridge { type Source = relay_westend_client::Westmint; type Target = relay_millau_client::Millau; diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs new file mode 100644 index 0000000000000..f6edd26db7a67 --- /dev/null +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -0,0 +1,409 @@ +// Copyright 2019-2022 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 . + +use sp_core::Pair; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames}; + +use crate::cli::CliChain; +pub use relay_substrate_client::ChainRuntimeVersion; +use substrate_relay_helper::TransactionParams; + +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + +/// Create chain-specific set of runtime version parameters. +#[macro_export] +macro_rules! declare_chain_runtime_version_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + paste::item! { + #[doc = $chain " runtime version params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] + pub struct [<$chain RuntimeVersionParams>] { + #[doc = "The type of runtime version for chain " $chain] + #[structopt(long, default_value = "Bundle")] + pub [<$chain_prefix _version_mode>]: RuntimeVersionType, + #[doc = "The custom sepc_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _spec_version>]: Option, + #[doc = "The custom transaction_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _transaction_version>]: Option, + } + + impl [<$chain RuntimeVersionParams>] { + /// Converts self into `ChainRuntimeVersion`. + pub fn into_runtime_version( + self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + Ok(match self.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let except_spec_version = self.[<$chain_prefix _spec_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let except_transaction_version = self.[<$chain_prefix _transaction_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + except_spec_version, + except_transaction_version + ) + }, + RuntimeVersionType::Bundle => match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom( + runtime_version.spec_version, + runtime_version.transaction_version + ), + None => ChainRuntimeVersion::Auto + }, + }) + } + } + } + }; +} + +/// Create chain-specific set of runtime version parameters. +#[macro_export] +macro_rules! declare_chain_connection_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + paste::item! { + #[doc = $chain " connection params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain ConnectionParams>] { + #[doc = "Connect to " $chain " node at given host."] + #[structopt(long, default_value = "127.0.0.1")] + pub [<$chain_prefix _host>]: String, + #[doc = "Connect to " $chain " node websocket server at given port."] + #[structopt(long, default_value = "9944")] + pub [<$chain_prefix _port>]: u16, + #[doc = "Use secure websocket connection."] + #[structopt(long)] + pub [<$chain_prefix _secure>]: bool, + #[doc = "Custom runtime version"] + #[structopt(flatten)] + pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], + } + + impl [<$chain ConnectionParams>] { + /// Convert connection params into Substrate client. + #[allow(dead_code)] + pub async fn into_client( + self, + ) -> anyhow::Result> { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; + Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { + host: self.[<$chain_prefix _host>], + port: self.[<$chain_prefix _port>], + secure: self.[<$chain_prefix _secure>], + chain_runtime_version, + }) + .await + ) + } + } + } + }; +} + +/// Helper trait to override transaction parameters differently. +pub trait TransactionParamsProvider { + /// Returns `true` if transaction parameters are defined by this provider. + fn is_defined(&self) -> bool; + /// Returns transaction parameters. + fn transaction_params( + &self, + ) -> anyhow::Result>; + + /// Returns transaction parameters, defined by `self` provider or, if they're not defined, + /// defined by `other` provider. + fn transaction_params_or( + &self, + other: &T, + ) -> anyhow::Result> { + if self.is_defined() { + self.transaction_params::() + } else { + other.transaction_params::() + } + } +} + +/// Create chain-specific set of signing parameters. +#[macro_export] +macro_rules! declare_chain_signing_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + paste::item! { + #[doc = $chain " signing params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain SigningParams>] { + #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _signer>]: Option, + #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _signer_password>]: Option, + + #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] + #[structopt(long)] + pub [<$chain_prefix _signer_file>]: Option, + #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] + #[structopt(long)] + pub [<$chain_prefix _signer_password_file>]: Option, + + #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] + #[structopt(long)] + pub [<$chain_prefix _transactions_mortality>]: Option, + } + + impl [<$chain SigningParams>] { + /// Return transactions mortality. + #[allow(dead_code)] + pub fn transactions_mortality(&self) -> anyhow::Result> { + self.[<$chain_prefix _transactions_mortality>] + .map(|transactions_mortality| { + if !(4..=65536).contains(&transactions_mortality) + || !transactions_mortality.is_power_of_two() + { + Err(anyhow::format_err!( + "Transactions mortality {} is not a power of two in a [4; 65536] range", + transactions_mortality, + )) + } else { + Ok(transactions_mortality) + } + }) + .transpose() + } + + /// Parse signing params into chain-specific KeyPair. + #[allow(dead_code)] + pub fn to_keypair(&self) -> anyhow::Result { + let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { + (Some(suri), _) => suri.to_owned(), + (None, Some(suri_file)) => std::fs::read_to_string(suri_file) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI from file {:?}: {}", + suri_file, + err, + ))?, + (None, None) => return Err(anyhow::format_err!( + "One of options must be specified: '{}' or '{}'", + stringify!([<$chain_prefix _signer>]), + stringify!([<$chain_prefix _signer_file>]), + )), + }; + + let suri_password = match ( + self.[<$chain_prefix _signer_password>].as_ref(), + self.[<$chain_prefix _signer_password_file>].as_ref(), + ) { + (Some(suri_password), _) => Some(suri_password.to_owned()), + (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) + .map(Some) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI password from file {:?}: {}", + suri_password_file, + err, + ))?, + _ => None, + }; + + use sp_core::crypto::Pair; + + Chain::KeyPair::from_string( + &suri, + suri_password.as_deref() + ).map_err(|e| anyhow::format_err!("{:?}", e)) + } + } + + #[allow(dead_code)] + impl TransactionParamsProvider for [<$chain SigningParams>] { + fn is_defined(&self) -> bool { + self.[<$chain_prefix _signer>].is_some() || self.[<$chain_prefix _signer_file>].is_some() + } + + fn transaction_params(&self) -> anyhow::Result> { + Ok(TransactionParams { + mortality: self.transactions_mortality()?, + signer: self.to_keypair::()?, + }) + } + } + } + }; +} + +/// Create chain-specific set of messages pallet owner signing parameters. +#[macro_export] +macro_rules! declare_chain_messages_pallet_owner_signing_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + paste::item! { + #[doc = "Parameters required to sign transaction on behalf of owner of the messages pallet at " $chain "."] + #[derive(StructOpt, Debug, PartialEq, Eq)] + pub struct [<$chain MessagesPalletOwnerSigningParams>] { + #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _messages_pallet_owner>]: Option, + #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _messages_pallet_owner_password>]: Option, + } + + #[allow(dead_code)] + impl [<$chain MessagesPalletOwnerSigningParams>] { + /// Parse signing params into chain-specific KeyPair. + pub fn to_keypair(&self) -> anyhow::Result> { + let [<$chain_prefix _messages_pallet_owner>] = match self.[<$chain_prefix _messages_pallet_owner>] { + Some(ref messages_pallet_owner) => messages_pallet_owner, + None => return Ok(None), + }; + Chain::KeyPair::from_string( + [<$chain_prefix _messages_pallet_owner>], + self.[<$chain_prefix _messages_pallet_owner_password>].as_deref() + ).map_err(|e| anyhow::format_err!("{:?}", e)).map(Some) + } + } + } + }; +} + +/// Create chain-specific set of configuration objects: connection parameters, +/// signing parameters and bridge initialization parameters. +#[macro_export] +macro_rules! declare_chain_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + $crate::declare_chain_runtime_version_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_connection_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_signing_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_messages_pallet_owner_signing_params_cli_schema!( + $chain, + $chain_prefix + ); + }; +} + +declare_chain_cli_schema!(Source, source); +declare_chain_cli_schema!(Target, target); +declare_chain_cli_schema!(Relaychain, relaychain); +declare_chain_cli_schema!(Parachain, parachain); + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::Pair; + + #[test] + fn reads_suri_from_file() { + const ALICE: &str = "//Alice"; + const BOB: &str = "//Bob"; + const ALICE_PASSWORD: &str = "alice_password"; + const BOB_PASSWORD: &str = "bob_password"; + + let alice: sp_core::sr25519::Pair = Pair::from_string(ALICE, Some(ALICE_PASSWORD)).unwrap(); + let bob: sp_core::sr25519::Pair = Pair::from_string(BOB, Some(BOB_PASSWORD)).unwrap(); + let bob_with_alice_password = + sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); + + let temp_dir = tempfile::tempdir().unwrap(); + let mut suri_file_path = temp_dir.path().to_path_buf(); + let mut password_file_path = temp_dir.path().to_path_buf(); + suri_file_path.push("suri"); + password_file_path.push("password"); + std::fs::write(&suri_file_path, BOB.as_bytes()).unwrap(); + std::fs::write(&password_file_path, BOB_PASSWORD.as_bytes()).unwrap(); + + // when both seed and password are read from file + assert_eq!( + TargetSigningParams { + target_signer: Some(ALICE.into()), + target_signer_password: Some(ALICE_PASSWORD.into()), + + target_signer_file: None, + target_signer_password_file: None, + + target_transactions_mortality: None, + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(alice.public()), + ); + + // when both seed and password are read from file + assert_eq!( + TargetSigningParams { + target_signer: None, + target_signer_password: None, + + target_signer_file: Some(suri_file_path.clone()), + target_signer_password_file: Some(password_file_path.clone()), + + target_transactions_mortality: None, + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(bob.public()), + ); + + // when password are is overriden by cli option + assert_eq!( + TargetSigningParams { + target_signer: None, + target_signer_password: Some(ALICE_PASSWORD.into()), + + target_signer_file: Some(suri_file_path.clone()), + target_signer_password_file: Some(password_file_path.clone()), + + target_transactions_mortality: None, + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(bob_with_alice_password.public()), + ); + + // when both seed and password are overriden by cli options + assert_eq!( + TargetSigningParams { + target_signer: Some(ALICE.into()), + target_signer_password: Some(ALICE_PASSWORD.into()), + + target_signer_file: Some(suri_file_path), + target_signer_password_file: Some(password_file_path), + + target_transactions_mortality: None, + } + .to_keypair::() + .map(|p| p.public()) + .map_err(drop), + Ok(alice.public()), + ); + } +} diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 30f20b681d4a2..0f4fd765f4074 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -16,8 +16,9 @@ use crate::cli::{ bridge::{FullBridge, MessagesCliBridge, *}, + chain_schema::*, relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - Balance, HexBytes, HexLaneId, SourceConnectionParams, + Balance, HexBytes, HexLaneId, }; use async_trait::async_trait; use bp_runtime::BalanceOf; @@ -80,7 +81,7 @@ where ::Balance: Display + Into, { async fn estimate_fee(data: EstimateFee) -> anyhow::Result<()> { - let source_client = data.source.to_client::().await?; + let source_client = data.source.into_client::().await?; let lane = data.lane.into(); let payload = crate::cli::encode_message::encode_message::(&data.payload) @@ -239,7 +240,6 @@ async fn do_estimate_message_delivery_and_dispatch_fee #[cfg(test)] mod tests { use super::*; - use crate::cli::{RuntimeVersionType, SourceRuntimeVersionParams}; #[test] fn should_parse_cli_options() { diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index b3110e69ff349..98f30b9f7bdfc 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -21,7 +21,7 @@ use crate::cli::{ CliBridgeBase, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, RialtoToMillauCliBridge, WestendToMillauCliBridge, }, - SourceConnectionParams, TargetConnectionParams, TargetSigningParams, + chain_schema::*, }; use bp_runtime::Chain as ChainBase; use codec::Encode; @@ -71,8 +71,8 @@ where /// Initialize the bridge. async fn init_bridge(data: InitBridge) -> anyhow::Result<()> { - let source_client = data.source.to_client::().await?; - let target_client = data.target.to_client::().await?; + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; let target_sign = data.target_sign.to_keypair::()?; let (spec_version, transaction_version) = target_client.simple_runtime_version().await?; diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 6f394092e14ad..e35548c347c42 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -19,10 +19,8 @@ use std::convert::TryInto; use codec::{Decode, Encode}; -use relay_substrate_client::ChainRuntimeVersion; use structopt::{clap::arg_enum, StructOpt}; use strum::{EnumString, EnumVariantNames}; -use substrate_relay_helper::TransactionParams; use bp_messages::LaneId; @@ -31,6 +29,7 @@ pub(crate) mod encode_message; pub(crate) mod estimate_fee; pub(crate) mod send_message; +mod chain_schema; mod init_bridge; mod register_parachain; mod relay_headers; @@ -296,283 +295,9 @@ pub enum RuntimeVersionType { Bundle, } -/// Helper trait to override transaction parameters differently. -pub trait TransactionParamsProvider { - /// Returns `true` if transaction parameters are defined by this provider. - fn is_defined(&self) -> bool; - /// Returns transaction parameters. - fn transaction_params( - &self, - ) -> anyhow::Result>; - - /// Returns transaction parameters, defined by `self` provider or, if they're not defined, - /// defined by `other` provider. - fn transaction_params_or( - &self, - other: &T, - ) -> anyhow::Result> { - if self.is_defined() { - self.transaction_params::() - } else { - other.transaction_params::() - } - } -} - -/// Create chain-specific set of configuration objects: connection parameters, -/// signing parameters and bridge initialization parameters. -#[macro_export] -macro_rules! declare_chain_options { - ($chain:ident, $chain_prefix:ident) => { - paste::item! { - #[doc = $chain " connection params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] - pub struct [<$chain ConnectionParams>] { - #[doc = "Connect to " $chain " node at given host."] - #[structopt(long, default_value = "127.0.0.1")] - pub [<$chain_prefix _host>]: String, - #[doc = "Connect to " $chain " node websocket server at given port."] - #[structopt(long, default_value = "9944")] - pub [<$chain_prefix _port>]: u16, - #[doc = "Use secure websocket connection."] - #[structopt(long)] - pub [<$chain_prefix _secure>]: bool, - #[doc = "Custom runtime version"] - #[structopt(flatten)] - pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], - } - - #[doc = $chain " runtime version params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] - pub struct [<$chain RuntimeVersionParams>] { - #[doc = "The type of runtime version for chain " $chain] - #[structopt(long, default_value = "Bundle")] - pub [<$chain_prefix _version_mode>]: RuntimeVersionType, - #[doc = "The custom sepc_version for chain " $chain] - #[structopt(long)] - pub [<$chain_prefix _spec_version>]: Option, - #[doc = "The custom transaction_version for chain " $chain] - #[structopt(long)] - pub [<$chain_prefix _transaction_version>]: Option, - } - - #[doc = $chain " signing params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] - pub struct [<$chain SigningParams>] { - #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _signer>]: Option, - #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _signer_password>]: Option, - - #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] - #[structopt(long)] - pub [<$chain_prefix _signer_file>]: Option, - #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] - #[structopt(long)] - pub [<$chain_prefix _signer_password_file>]: Option, - - #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] - #[structopt(long)] - pub [<$chain_prefix _transactions_mortality>]: Option, - } - - #[doc = "Parameters required to sign transaction on behalf of owner of the messages pallet at " $chain "."] - #[derive(StructOpt, Debug, PartialEq, Eq)] - pub struct [<$chain MessagesPalletOwnerSigningParams>] { - #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _messages_pallet_owner>]: Option, - #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _messages_pallet_owner_password>]: Option, - } - - impl [<$chain SigningParams>] { - /// Return transactions mortality. - #[allow(dead_code)] - pub fn transactions_mortality(&self) -> anyhow::Result> { - self.[<$chain_prefix _transactions_mortality>] - .map(|transactions_mortality| { - if !(4..=65536).contains(&transactions_mortality) - || !transactions_mortality.is_power_of_two() - { - Err(anyhow::format_err!( - "Transactions mortality {} is not a power of two in a [4; 65536] range", - transactions_mortality, - )) - } else { - Ok(transactions_mortality) - } - }) - .transpose() - } - - /// Parse signing params into chain-specific KeyPair. - #[allow(dead_code)] - pub fn to_keypair(&self) -> anyhow::Result { - let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { - (Some(suri), _) => suri.to_owned(), - (None, Some(suri_file)) => std::fs::read_to_string(suri_file) - .map_err(|err| anyhow::format_err!( - "Failed to read SURI from file {:?}: {}", - suri_file, - err, - ))?, - (None, None) => return Err(anyhow::format_err!( - "One of options must be specified: '{}' or '{}'", - stringify!([<$chain_prefix _signer>]), - stringify!([<$chain_prefix _signer_file>]), - )), - }; - - let suri_password = match ( - self.[<$chain_prefix _signer_password>].as_ref(), - self.[<$chain_prefix _signer_password_file>].as_ref(), - ) { - (Some(suri_password), _) => Some(suri_password.to_owned()), - (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) - .map(Some) - .map_err(|err| anyhow::format_err!( - "Failed to read SURI password from file {:?}: {}", - suri_password_file, - err, - ))?, - _ => None, - }; - - use sp_core::crypto::Pair; - - Chain::KeyPair::from_string( - &suri, - suri_password.as_deref() - ).map_err(|e| anyhow::format_err!("{:?}", e)) - } - } - - #[allow(dead_code)] - impl TransactionParamsProvider for [<$chain SigningParams>] { - fn is_defined(&self) -> bool { - self.[<$chain_prefix _signer>].is_some() || self.[<$chain_prefix _signer_file>].is_some() - } - - fn transaction_params(&self) -> anyhow::Result> { - Ok(TransactionParams { - mortality: self.transactions_mortality()?, - signer: self.to_keypair::()?, - }) - } - } - - #[allow(dead_code)] - impl [<$chain MessagesPalletOwnerSigningParams>] { - /// Parse signing params into chain-specific KeyPair. - pub fn to_keypair(&self) -> anyhow::Result> { - use sp_core::crypto::Pair; - - let [<$chain_prefix _messages_pallet_owner>] = match self.[<$chain_prefix _messages_pallet_owner>] { - Some(ref messages_pallet_owner) => messages_pallet_owner, - None => return Ok(None), - }; - Chain::KeyPair::from_string( - [<$chain_prefix _messages_pallet_owner>], - self.[<$chain_prefix _messages_pallet_owner_password>].as_deref() - ).map_err(|e| anyhow::format_err!("{:?}", e)).map(Some) - } - } - - impl [<$chain ConnectionParams>] { - /// Returns `true` if version guard can be started. - /// - /// There's no reason to run version guard when version mode is set to `Auto`. It can - /// lead to relay shutdown when chain is upgraded, even though we have explicitly - /// said that we don't want to shutdown. - #[allow(dead_code)] - pub fn can_start_version_guard(&self) -> bool { - self.[<$chain_prefix _runtime_version>].[<$chain_prefix _version_mode>] != RuntimeVersionType::Auto - } - - /// Convert connection params into Substrate client. - pub async fn to_client( - &self, - ) -> anyhow::Result> { - let chain_runtime_version = self - .[<$chain_prefix _runtime_version>] - .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; - Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { - host: self.[<$chain_prefix _host>].clone(), - port: self.[<$chain_prefix _port>], - secure: self.[<$chain_prefix _secure>], - chain_runtime_version, - }) - .await - ) - } - - /// Return selected `chain_spec` version. - /// - /// This function only connects to the node if version mode is set to `Auto`. - #[allow(dead_code)] - pub async fn selected_chain_spec_version( - &self, - ) -> anyhow::Result { - let chain_runtime_version = self - .[<$chain_prefix _runtime_version>] - .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; - Ok(match chain_runtime_version { - ChainRuntimeVersion::Auto => self - .to_client::() - .await? - .simple_runtime_version() - .await? - .0, - ChainRuntimeVersion::Custom(spec_version, _) => spec_version, - }) - } - } - - impl [<$chain RuntimeVersionParams>] { - /// Converts self into `ChainRuntimeVersion`. - pub fn into_runtime_version( - self, - bundle_runtime_version: Option, - ) -> anyhow::Result { - Ok(match self.[<$chain_prefix _version_mode>] { - RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, - RuntimeVersionType::Custom => { - let except_spec_version = self.[<$chain_prefix _spec_version>] - .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; - let except_transaction_version = self.[<$chain_prefix _transaction_version>] - .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; - ChainRuntimeVersion::Custom( - except_spec_version, - except_transaction_version - ) - }, - RuntimeVersionType::Bundle => match bundle_runtime_version { - Some(runtime_version) => ChainRuntimeVersion::Custom( - runtime_version.spec_version, - runtime_version.transaction_version - ), - None => ChainRuntimeVersion::Auto - }, - }) - } - } - } - }; -} - -declare_chain_options!(Source, source); -declare_chain_options!(Target, target); -declare_chain_options!(Relaychain, relaychain); -declare_chain_options!(Parachain, parachain); - #[cfg(test)] mod tests { use super::*; - use sp_core::Pair; #[test] fn hex_bytes_display_matches_from_str_for_clap() { @@ -586,93 +311,4 @@ mod tests { // then assert_eq!(hex.0, hex2.0); } - - #[test] - fn reads_suri_from_file() { - const ALICE: &str = "//Alice"; - const BOB: &str = "//Bob"; - const ALICE_PASSWORD: &str = "alice_password"; - const BOB_PASSWORD: &str = "bob_password"; - - let alice = sp_core::sr25519::Pair::from_string(ALICE, Some(ALICE_PASSWORD)).unwrap(); - let bob = sp_core::sr25519::Pair::from_string(BOB, Some(BOB_PASSWORD)).unwrap(); - let bob_with_alice_password = - sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); - - let temp_dir = tempfile::tempdir().unwrap(); - let mut suri_file_path = temp_dir.path().to_path_buf(); - let mut password_file_path = temp_dir.path().to_path_buf(); - suri_file_path.push("suri"); - password_file_path.push("password"); - std::fs::write(&suri_file_path, BOB.as_bytes()).unwrap(); - std::fs::write(&password_file_path, BOB_PASSWORD.as_bytes()).unwrap(); - - // when both seed and password are read from file - assert_eq!( - TargetSigningParams { - target_signer: Some(ALICE.into()), - target_signer_password: Some(ALICE_PASSWORD.into()), - - target_signer_file: None, - target_signer_password_file: None, - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(alice.public()), - ); - - // when both seed and password are read from file - assert_eq!( - TargetSigningParams { - target_signer: None, - target_signer_password: None, - - target_signer_file: Some(suri_file_path.clone()), - target_signer_password_file: Some(password_file_path.clone()), - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(bob.public()), - ); - - // when password are is overriden by cli option - assert_eq!( - TargetSigningParams { - target_signer: None, - target_signer_password: Some(ALICE_PASSWORD.into()), - - target_signer_file: Some(suri_file_path.clone()), - target_signer_password_file: Some(password_file_path.clone()), - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(bob_with_alice_password.public()), - ); - - // when both seed and password are overriden by cli options - assert_eq!( - TargetSigningParams { - target_signer: Some(ALICE.into()), - target_signer_password: Some(ALICE_PASSWORD.into()), - - target_signer_file: Some(suri_file_path), - target_signer_password_file: Some(password_file_path), - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(alice.public()), - ); - } } diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index d164781205378..9573cde30319f 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -14,9 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{ - Balance, ParachainConnectionParams, RelaychainConnectionParams, RelaychainSigningParams, -}; +use crate::cli::{chain_schema::*, Balance}; use codec::Encode; use frame_support::Twox64Concat; @@ -94,9 +92,9 @@ impl RegisterParachain { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.parachain, { - let relay_client = self.relay_connection.to_client::().await?; + let relay_client = self.relay_connection.into_client::().await?; let relay_sign = self.relay_sign.to_keypair::()?; - let para_client = self.para_connection.to_client::().await?; + let para_client = self.para_connection.into_client::().await?; // hopefully we're the only actor that is registering parachain right now // => read next parachain id @@ -343,9 +341,6 @@ async fn wait_para_state( #[cfg(test)] mod tests { use super::*; - use crate::cli::{ - ParachainRuntimeVersionParams, RelaychainRuntimeVersionParams, RuntimeVersionType, - }; #[test] fn register_rialto_parachain() { diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index f8d7eeb541830..59325e452e370 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, ChainBase}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf}; use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -23,10 +23,7 @@ use strum::{EnumString, EnumVariantNames, VariantNames}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; -use crate::cli::{ - bridge::*, PrometheusParams, SourceConnectionParams, TargetConnectionParams, - TargetSigningParams, -}; +use crate::cli::{bridge::*, chain_schema::*, PrometheusParams}; /// Start headers relayer process. #[derive(StructOpt)] @@ -59,14 +56,14 @@ pub enum RelayHeadersBridge { } #[async_trait] -trait HeadersRelayer: HeadersCliBridge +trait HeadersRelayer: RelayToRelayHeadersCliBridge where - ::AccountId: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, { /// Relay headers. async fn relay_headers(data: RelayHeaders) -> anyhow::Result<()> { - let source_client = data.source.to_client::().await?; - let target_client = data.target.to_client::().await?; + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; let target_transactions_mortality = data.target_sign.target_transactions_mortality; let target_sign = data.target_sign.to_keypair::()?; @@ -80,7 +77,7 @@ where Self::Finality::start_relay_guards( &target_client, &target_transactions_params, - data.target.can_start_version_guard(), + target_client.can_start_version_guard(), ) .await?; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs deleted file mode 100644 index 4d6456cc6198e..0000000000000 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ /dev/null @@ -1,910 +0,0 @@ -// 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 . - -//! Complex headers+messages relays support. -//! -//! To add new complex relay between `ChainA` and `ChainB`, you must: -//! -//! 1) ensure that there's a `declare_chain_options!(...)` for both chains; -//! 2) add `declare_bridge_options!(...)` for the bridge; -//! 3) add bridge support to the `select_bridge! { ... }` macro. - -use futures::{FutureExt, TryFutureExt}; -use structopt::StructOpt; -use strum::VariantNames; - -use async_std::sync::Arc; -use bp_polkadot_core::parachains::ParaHash; -use messages_relay::relay_strategy::MixStrategy; -use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, ChainRuntimeVersion, Client, - TransactionSignScheme, -}; -use relay_utils::metrics::MetricsParams; -use sp_core::Pair; -use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, - messages_lane::MessagesRelayParams, - on_demand::{ - headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, - }, - parachains::SubstrateParachainsPipeline, - TaggedAccount, TransactionParams, -}; - -use crate::{ - cli::{ - relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams, RuntimeVersionType, - TransactionParamsProvider, - }, - declare_chain_options, -}; - -/// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. -/// -/// If it is zero, then transaction will be submitted every time we see difference between -/// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1), -/// then rational relayers may stop relaying messages because they were submitted using -/// lesser conversion rate. -pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; - -/// Start headers+messages relayer process. -#[derive(Debug, PartialEq, StructOpt)] -pub enum RelayHeadersAndMessages { - MillauRialto(MillauRialtoHeadersAndMessages), - MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), -} - -/// Parameters that have the same names across all bridges. -#[derive(Debug, PartialEq, StructOpt)] -pub struct HeadersAndMessagesSharedParams { - /// Hex-encoded lane identifiers that should be served by the complex relay. - #[structopt(long, default_value = "00000000")] - lane: Vec, - #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] - relayer_mode: RelayerMode, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) - /// are relayed. - #[structopt(long)] - only_mandatory_headers: bool, - #[structopt(flatten)] - prometheus_params: PrometheusParams, -} - -// The reason behind this macro is that 'normal' relays are using source and target chains -// terminology, which is unusable for both-way relays (if you're relaying headers from Rialto to -// Millau and from Millau to Rialto, then which chain is source?). -macro_rules! declare_bridge_options { - // chain, parachain, relay-chain-of-parachain - ($chain1:ident, $chain2:ident, $chain3:ident) => { - paste::item! { - #[doc = $chain1 ", " $chain2 " and " $chain3 " headers+parachains+messages relay params."] - #[derive(Debug, PartialEq, StructOpt)] - pub struct [<$chain1 $chain2 HeadersAndMessages>] { - #[structopt(flatten)] - shared: HeadersAndMessagesSharedParams, - #[structopt(flatten)] - left: [<$chain1 ConnectionParams>], - // default signer, which is always used to sign messages relay transactions on the left chain - #[structopt(flatten)] - left_sign: [<$chain1 SigningParams>], - // override for right_relay->left headers signer - #[structopt(flatten)] - right_relay_headers_to_left_sign_override: [<$chain3 HeadersTo $chain1 SigningParams>], - // override for right->left parachains signer - #[structopt(flatten)] - right_parachains_to_left_sign_override: [<$chain3 ParachainsTo $chain1 SigningParams>], - #[structopt(flatten)] - left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>], - #[structopt(flatten)] - right: [<$chain2 ConnectionParams>], - // default signer, which is always used to sign messages relay transactions on the right chain - #[structopt(flatten)] - right_sign: [<$chain2 SigningParams>], - // override for left->right headers signer - #[structopt(flatten)] - left_headers_to_right_sign_override: [<$chain1 HeadersTo $chain2 SigningParams>], - #[structopt(flatten)] - right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], - #[structopt(flatten)] - right_relay: [<$chain3 ConnectionParams>], - } - } - - declare_bridge_options!({ implement }, $chain1, $chain2); - }; - ($chain1:ident, $chain2:ident) => { - paste::item! { - #[doc = $chain1 " and " $chain2 " headers+messages relay params."] - #[derive(Debug, PartialEq, StructOpt)] - pub struct [<$chain1 $chain2 HeadersAndMessages>] { - #[structopt(flatten)] - shared: HeadersAndMessagesSharedParams, - // default signer, which is always used to sign messages relay transactions on the left chain - #[structopt(flatten)] - left: [<$chain1 ConnectionParams>], - // override for right->left headers signer - #[structopt(flatten)] - right_headers_to_left_sign_override: [<$chain2 HeadersTo $chain1 SigningParams>], - #[structopt(flatten)] - left_sign: [<$chain1 SigningParams>], - #[structopt(flatten)] - left_messages_pallet_owner: [<$chain1 MessagesPalletOwnerSigningParams>], - // default signer, which is always used to sign messages relay transactions on the right chain - #[structopt(flatten)] - right: [<$chain2 ConnectionParams>], - // override for left->right headers signer - #[structopt(flatten)] - left_headers_to_right_sign_override: [<$chain1 HeadersTo $chain2 SigningParams>], - #[structopt(flatten)] - right_sign: [<$chain2 SigningParams>], - #[structopt(flatten)] - right_messages_pallet_owner: [<$chain2 MessagesPalletOwnerSigningParams>], - } - } - - declare_bridge_options!({ implement }, $chain1, $chain2); - }; - ({ implement }, $chain1:ident, $chain2:ident) => { - paste::item! { - impl From for [<$chain1 $chain2 HeadersAndMessages>] { - fn from(relay_params: RelayHeadersAndMessages) -> [<$chain1 $chain2 HeadersAndMessages>] { - match relay_params { - RelayHeadersAndMessages::[<$chain1 $chain2>](params) => params, - _ => unreachable!(), - } - } - } - } - }; -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - RelayHeadersAndMessages::MillauRialto(_) => { - type Params = MillauRialtoHeadersAndMessages; - - type Left = relay_millau_client::Millau; - type Right = relay_rialto_client::Rialto; - - use crate::chains::{ - millau_messages_to_rialto::MillauMessagesToRialto as LeftToRightMessageLane, - rialto_messages_to_millau::RialtoMessagesToMillau as RightToLeftMessageLane, - }; - - async fn start_on_demand_relays( - params: &Params, - left_client: Client, - right_client: Client, - at_left_relay_accounts: &mut Vec>>, - at_right_relay_accounts: &mut Vec>>, - ) -> anyhow::Result<( - Arc>>, - Arc>>, - )> { - start_on_demand_relay_to_relay::< - Left, - Right, - crate::chains::millau_headers_to_rialto::MillauFinalityToRialto, - crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau, - >( - left_client, - right_client, - params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, - params.right_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, - params.shared.only_mandatory_headers, - params.shared.only_mandatory_headers, - params.left.can_start_version_guard(), - params.right.can_start_version_guard(), - at_left_relay_accounts, - at_right_relay_accounts, - ).await - } - - $generic - }, - RelayHeadersAndMessages::MillauRialtoParachain(_) => { - type Params = MillauRialtoParachainHeadersAndMessages; - - type Left = relay_millau_client::Millau; - type Right = relay_rialto_parachain_client::RialtoParachain; - - use crate::chains::{ - millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain as LeftToRightMessageLane, - rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau as RightToLeftMessageLane, - }; - - async fn start_on_demand_relays( - params: &Params, - left_client: Client, - right_client: Client, - at_left_relay_accounts: &mut Vec>>, - at_right_relay_accounts: &mut Vec>>, - ) -> anyhow::Result<( - Arc>>, - Arc>>, - )> { - type RightRelayChain = relay_rialto_client::Rialto; - let rialto_relay_chain_client = params.right_relay.to_client::().await?; - - start_on_demand_relay_to_parachain::< - Left, - Right, - RightRelayChain, - crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain, - crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau, - crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau, - >( - left_client, - right_client, - rialto_relay_chain_client, - params.left_headers_to_right_sign_override.transaction_params_or::(¶ms.right_sign)?, - params.right_relay_headers_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, - params.right_parachains_to_left_sign_override.transaction_params_or::(¶ms.left_sign)?, - params.shared.only_mandatory_headers, - params.shared.only_mandatory_headers, - params.left.can_start_version_guard(), - params.right.can_start_version_guard(), - at_left_relay_accounts, - at_right_relay_accounts, - ).await - } - - $generic - }, - } - }; -} - -// All supported chains. -declare_chain_options!(Millau, millau); -declare_chain_options!(Rialto, rialto); -declare_chain_options!(RialtoParachain, rialto_parachain); -// Means to override signers of different layer transactions. -declare_chain_options!(MillauHeadersToRialto, millau_headers_to_rialto); -declare_chain_options!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); -declare_chain_options!(RialtoHeadersToMillau, rialto_headers_to_millau); -declare_chain_options!(RialtoParachainsToMillau, rialto_parachains_to_millau); -// All supported bridges. -declare_bridge_options!(Millau, Rialto); -declare_bridge_options!(Millau, RialtoParachain, Rialto); - -impl RelayHeadersAndMessages { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self, { - let params: Params = self.into(); - - let left_client = params.left.to_client::().await?; - let left_transactions_mortality = params.left_sign.transactions_mortality()?; - let left_sign = params.left_sign.to_keypair::()?; - let left_messages_pallet_owner = - params.left_messages_pallet_owner.to_keypair::()?; - let right_client = params.right.to_client::().await?; - let right_transactions_mortality = params.right_sign.transactions_mortality()?; - let right_sign = params.right_sign.to_keypair::()?; - let right_messages_pallet_owner = - params.right_messages_pallet_owner.to_keypair::()?; - - let lanes = params.shared.lane.clone(); - let relayer_mode = params.shared.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); - - // create metrics registry and register standalone metrics - let metrics_params: MetricsParams = params.shared.prometheus_params.clone().into(); - let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); - let left_to_right_metrics = - substrate_relay_helper::messages_metrics::standalone_metrics::< - LeftToRightMessageLane, - >(left_client.clone(), right_client.clone())?; - let right_to_left_metrics = left_to_right_metrics.clone().reverse(); - let mut at_left_relay_accounts = vec![TaggedAccount::Messages { - id: left_sign.public().into(), - bridged_chain: Right::NAME.to_string(), - }]; - let mut at_right_relay_accounts = vec![TaggedAccount::Messages { - id: right_sign.public().into(), - bridged_chain: Left::NAME.to_string(), - }]; - - // start conversion rate update loops for left/right chains - if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { - let left_client = left_client.clone(); - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Right::NAME, - Left::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - LeftToRightMessageLane, - Left, - >( - left_client, - TransactionParams { - signer: left_messages_pallet_owner.clone(), - mortality: left_transactions_mortality, - }, - left_to_right_metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - left_to_right_metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - left_to_right_metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - at_left_relay_accounts.push(TaggedAccount::MessagesPalletOwner { - id: left_messages_pallet_owner.public().into(), - bridged_chain: Right::NAME.to_string(), - }); - } - if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { - let right_client = right_client.clone(); - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Left::NAME, - Right::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - RightToLeftMessageLane, - Right, - >( - right_client, - TransactionParams { - signer: right_messages_pallet_owner.clone(), - mortality: right_transactions_mortality, - }, - right_to_left_metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - right_to_left_metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - right_to_left_metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - at_right_relay_accounts.push(TaggedAccount::MessagesPalletOwner { - id: right_messages_pallet_owner.public().into(), - bridged_chain: Left::NAME.to_string(), - }); - } - - // start on-demand header relays - let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = - start_on_demand_relays( - ¶ms, - left_client.clone(), - right_client.clone(), - &mut at_left_relay_accounts, - &mut at_right_relay_accounts, - ) - .await?; - - // add balance-related metrics - let metrics_params = - substrate_relay_helper::messages_metrics::add_relay_balances_metrics( - left_client.clone(), - metrics_params, - at_left_relay_accounts, - ) - .await?; - let metrics_params = - substrate_relay_helper::messages_metrics::add_relay_balances_metrics( - right_client.clone(), - metrics_params, - at_right_relay_accounts, - ) - .await?; - - // Need 2x capacity since we consider both directions for each lane - let mut message_relays = Vec::with_capacity(lanes.len() * 2); - for lane in lanes { - let lane = lane.into(); - let left_to_right_messages = substrate_relay_helper::messages_lane::run::< - LeftToRightMessageLane, - >(MessagesRelayParams { - source_client: left_client.clone(), - source_transaction_params: TransactionParams { - signer: left_sign.clone(), - mortality: left_transactions_mortality, - }, - target_client: right_client.clone(), - target_transaction_params: TransactionParams { - signer: right_sign.clone(), - mortality: right_transactions_mortality, - }, - source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), - target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params.clone().disable(), - standalone_metrics: Some(left_to_right_metrics.clone()), - relay_strategy: relay_strategy.clone(), - }) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - let right_to_left_messages = substrate_relay_helper::messages_lane::run::< - RightToLeftMessageLane, - >(MessagesRelayParams { - source_client: right_client.clone(), - source_transaction_params: TransactionParams { - signer: right_sign.clone(), - mortality: right_transactions_mortality, - }, - target_client: left_client.clone(), - target_transaction_params: TransactionParams { - signer: left_sign.clone(), - mortality: left_transactions_mortality, - }, - source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), - target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params.clone().disable(), - standalone_metrics: Some(right_to_left_metrics.clone()), - relay_strategy: relay_strategy.clone(), - }) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - - message_relays.push(left_to_right_messages); - message_relays.push(right_to_left_messages); - } - - relay_utils::relay_metrics(metrics_params) - .expose() - .await - .map_err(|e| anyhow::format_err!("{}", e))?; - - futures::future::select_all(message_relays).await.0 - }) - } -} - -/// Start bidirectional on-demand headers <> headers relay. -#[allow(clippy::too_many_arguments)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1415 -async fn start_on_demand_relay_to_relay( - left_client: Client, - right_client: Client, - left_to_right_transaction_params: TransactionParams>, - right_to_left_transaction_params: TransactionParams>, - left_to_right_only_mandatory_headers: bool, - right_to_left_only_mandatory_headers: bool, - left_can_start_version_guard: bool, - right_can_start_version_guard: bool, - at_left_relay_accounts: &mut Vec>>, - at_right_relay_accounts: &mut Vec>>, -) -> anyhow::Result<( - Arc>>, - Arc>>, -)> -where - LC: Chain + TransactionSignScheme + CliChain>, - RC: Chain + TransactionSignScheme + CliChain>, - LR: SubstrateFinalitySyncPipeline< - SourceChain = LC, - TargetChain = RC, - TransactionSignScheme = RC, - >, - RL: SubstrateFinalitySyncPipeline< - SourceChain = RC, - TargetChain = LC, - TransactionSignScheme = LC, - >, - AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, - AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, -{ - at_left_relay_accounts.push(TaggedAccount::Headers { - id: right_to_left_transaction_params.signer.public().into(), - bridged_chain: RC::NAME.to_string(), - }); - at_right_relay_accounts.push(TaggedAccount::Headers { - id: left_to_right_transaction_params.signer.public().into(), - bridged_chain: LC::NAME.to_string(), - }); - - LR::start_relay_guards( - &right_client, - &left_to_right_transaction_params, - right_can_start_version_guard, - ) - .await?; - RL::start_relay_guards( - &left_client, - &right_to_left_transaction_params, - left_can_start_version_guard, - ) - .await?; - let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( - left_client.clone(), - right_client.clone(), - left_to_right_transaction_params, - left_to_right_only_mandatory_headers, - ); - let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::( - right_client.clone(), - left_client.clone(), - right_to_left_transaction_params, - right_to_left_only_mandatory_headers, - ); - - Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_headers))) -} - -/// Start bidirectional on-demand headers <> parachains relay. -#[allow(clippy::too_many_arguments)] // TODO: https://github.com/paritytech/parity-bridges-common/issues/1415 -async fn start_on_demand_relay_to_parachain( - left_client: Client, - right_client: Client, - right_relay_client: Client, - left_headers_to_right_transaction_params: TransactionParams>, - right_headers_to_left_transaction_params: TransactionParams>, - right_parachains_to_left_transaction_params: TransactionParams>, - left_to_right_only_mandatory_headers: bool, - right_to_left_only_mandatory_headers: bool, - left_can_start_version_guard: bool, - right_can_start_version_guard: bool, - at_left_relay_accounts: &mut Vec>>, - at_right_relay_accounts: &mut Vec>>, -) -> anyhow::Result<( - Arc>>, - Arc>>, -)> -where - LC: Chain + TransactionSignScheme + CliChain>, - RC: Chain - + TransactionSignScheme - + CliChain>, - RRC: Chain - + TransactionSignScheme - + CliChain>, - LR: SubstrateFinalitySyncPipeline< - SourceChain = LC, - TargetChain = RC, - TransactionSignScheme = RC, - >, - RRF: SubstrateFinalitySyncPipeline< - SourceChain = RRC, - TargetChain = LC, - TransactionSignScheme = LC, - >, - RL: SubstrateParachainsPipeline< - SourceRelayChain = RRC, - SourceParachain = RC, - TargetChain = LC, - TransactionSignScheme = LC, - >, - AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, - AccountIdOf: From<<::AccountKeyPair as Pair>::Public>, -{ - at_left_relay_accounts.push(TaggedAccount::Headers { - id: right_headers_to_left_transaction_params.signer.public().into(), - bridged_chain: RRC::NAME.to_string(), - }); - at_left_relay_accounts.push(TaggedAccount::Parachains { - id: right_parachains_to_left_transaction_params.signer.public().into(), - bridged_chain: RRC::NAME.to_string(), - }); - at_right_relay_accounts.push(TaggedAccount::Headers { - id: left_headers_to_right_transaction_params.signer.public().into(), - bridged_chain: LC::NAME.to_string(), - }); - - LR::start_relay_guards( - &right_client, - &left_headers_to_right_transaction_params, - right_can_start_version_guard, - ) - .await?; - RRF::start_relay_guards( - &left_client, - &right_headers_to_left_transaction_params, - left_can_start_version_guard, - ) - .await?; - let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::( - left_client.clone(), - right_client, - left_headers_to_right_transaction_params, - left_to_right_only_mandatory_headers, - ); - let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::new::( - right_relay_client.clone(), - left_client.clone(), - right_headers_to_left_transaction_params, - right_to_left_only_mandatory_headers, - ); - let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::( - right_relay_client, - left_client, - right_parachains_to_left_transaction_params, - Arc::new(right_relay_to_left_on_demand_headers), - ); - - Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_parachains))) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_parse_relay_to_relay_options() { - // when - let res = RelayHeadersAndMessages::from_iter(vec![ - "relay-headers-and-messages", - "millau-rialto", - "--millau-host", - "millau-node-alice", - "--millau-port", - "9944", - "--millau-signer", - "//Charlie", - "--millau-messages-pallet-owner", - "//Rialto.MessagesOwner", - "--millau-transactions-mortality", - "64", - "--rialto-host", - "rialto-node-alice", - "--rialto-port", - "9944", - "--rialto-signer", - "//Charlie", - "--rialto-messages-pallet-owner", - "//Millau.MessagesOwner", - "--rialto-transactions-mortality", - "64", - "--lane", - "00000000", - "--lane", - "73776170", - "--prometheus-host", - "0.0.0.0", - ]); - - // then - assert_eq!( - res, - RelayHeadersAndMessages::MillauRialto(MillauRialtoHeadersAndMessages { - shared: HeadersAndMessagesSharedParams { - lane: vec![ - HexLaneId([0x00, 0x00, 0x00, 0x00]), - HexLaneId([0x73, 0x77, 0x61, 0x70]) - ], - relayer_mode: RelayerMode::Rational, - only_mandatory_headers: false, - prometheus_params: PrometheusParams { - no_prometheus: false, - prometheus_host: "0.0.0.0".into(), - prometheus_port: 9616, - }, - }, - left: MillauConnectionParams { - millau_host: "millau-node-alice".into(), - millau_port: 9944, - millau_secure: false, - millau_runtime_version: MillauRuntimeVersionParams { - millau_version_mode: RuntimeVersionType::Bundle, - millau_spec_version: None, - millau_transaction_version: None, - }, - }, - left_sign: MillauSigningParams { - millau_signer: Some("//Charlie".into()), - millau_signer_password: None, - millau_signer_file: None, - millau_signer_password_file: None, - millau_transactions_mortality: Some(64), - }, - left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { - millau_messages_pallet_owner: Some("//Rialto.MessagesOwner".into()), - millau_messages_pallet_owner_password: None, - }, - left_headers_to_right_sign_override: MillauHeadersToRialtoSigningParams { - millau_headers_to_rialto_signer: None, - millau_headers_to_rialto_signer_password: None, - millau_headers_to_rialto_signer_file: None, - millau_headers_to_rialto_signer_password_file: None, - millau_headers_to_rialto_transactions_mortality: None, - }, - right: RialtoConnectionParams { - rialto_host: "rialto-node-alice".into(), - rialto_port: 9944, - rialto_secure: false, - rialto_runtime_version: RialtoRuntimeVersionParams { - rialto_version_mode: RuntimeVersionType::Bundle, - rialto_spec_version: None, - rialto_transaction_version: None, - }, - }, - right_sign: RialtoSigningParams { - rialto_signer: Some("//Charlie".into()), - rialto_signer_password: None, - rialto_signer_file: None, - rialto_signer_password_file: None, - rialto_transactions_mortality: Some(64), - }, - right_messages_pallet_owner: RialtoMessagesPalletOwnerSigningParams { - rialto_messages_pallet_owner: Some("//Millau.MessagesOwner".into()), - rialto_messages_pallet_owner_password: None, - }, - right_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { - rialto_headers_to_millau_signer: None, - rialto_headers_to_millau_signer_password: None, - rialto_headers_to_millau_signer_file: None, - rialto_headers_to_millau_signer_password_file: None, - rialto_headers_to_millau_transactions_mortality: None, - }, - }), - ); - } - - #[test] - fn should_parse_relay_to_parachain_options() { - // when - let res = RelayHeadersAndMessages::from_iter(vec![ - "relay-headers-and-messages", - "millau-rialto-parachain", - "--millau-host", - "millau-node-alice", - "--millau-port", - "9944", - "--millau-signer", - "//Iden", - "--rialto-headers-to-millau-signer", - "//Ken", - "--millau-messages-pallet-owner", - "//RialtoParachain.MessagesOwner", - "--millau-transactions-mortality", - "64", - "--rialto-parachain-host", - "rialto-parachain-collator-charlie", - "--rialto-parachain-port", - "9944", - "--rialto-parachain-signer", - "//George", - "--rialto-parachain-messages-pallet-owner", - "//Millau.MessagesOwner", - "--rialto-parachain-transactions-mortality", - "64", - "--rialto-host", - "rialto-node-alice", - "--rialto-port", - "9944", - "--lane", - "00000000", - "--prometheus-host", - "0.0.0.0", - ]); - - // then - assert_eq!( - res, - RelayHeadersAndMessages::MillauRialtoParachain( - MillauRialtoParachainHeadersAndMessages { - shared: HeadersAndMessagesSharedParams { - lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], - relayer_mode: RelayerMode::Rational, - only_mandatory_headers: false, - prometheus_params: PrometheusParams { - no_prometheus: false, - prometheus_host: "0.0.0.0".into(), - prometheus_port: 9616, - }, - }, - left: MillauConnectionParams { - millau_host: "millau-node-alice".into(), - millau_port: 9944, - millau_secure: false, - millau_runtime_version: MillauRuntimeVersionParams { - millau_version_mode: RuntimeVersionType::Bundle, - millau_spec_version: None, - millau_transaction_version: None, - }, - }, - left_sign: MillauSigningParams { - millau_signer: Some("//Iden".into()), - millau_signer_password: None, - millau_signer_file: None, - millau_signer_password_file: None, - millau_transactions_mortality: Some(64), - }, - left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { - millau_messages_pallet_owner: Some( - "//RialtoParachain.MessagesOwner".into() - ), - millau_messages_pallet_owner_password: None, - }, - left_headers_to_right_sign_override: - MillauHeadersToRialtoParachainSigningParams { - millau_headers_to_rialto_parachain_signer: None, - millau_headers_to_rialto_parachain_signer_password: None, - millau_headers_to_rialto_parachain_signer_file: None, - millau_headers_to_rialto_parachain_signer_password_file: None, - millau_headers_to_rialto_parachain_transactions_mortality: None, - }, - right: RialtoParachainConnectionParams { - rialto_parachain_host: "rialto-parachain-collator-charlie".into(), - rialto_parachain_port: 9944, - rialto_parachain_secure: false, - rialto_parachain_runtime_version: RialtoParachainRuntimeVersionParams { - rialto_parachain_version_mode: RuntimeVersionType::Bundle, - rialto_parachain_spec_version: None, - rialto_parachain_transaction_version: None, - }, - }, - right_sign: RialtoParachainSigningParams { - rialto_parachain_signer: Some("//George".into()), - rialto_parachain_signer_password: None, - rialto_parachain_signer_file: None, - rialto_parachain_signer_password_file: None, - rialto_parachain_transactions_mortality: Some(64), - }, - right_messages_pallet_owner: RialtoParachainMessagesPalletOwnerSigningParams { - rialto_parachain_messages_pallet_owner: Some( - "//Millau.MessagesOwner".into() - ), - rialto_parachain_messages_pallet_owner_password: None, - }, - right_relay_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { - rialto_headers_to_millau_signer: Some("//Ken".into()), - rialto_headers_to_millau_signer_password: None, - rialto_headers_to_millau_signer_file: None, - rialto_headers_to_millau_signer_password_file: None, - rialto_headers_to_millau_transactions_mortality: None, - }, - right_parachains_to_left_sign_override: RialtoParachainsToMillauSigningParams { - rialto_parachains_to_millau_signer: None, - rialto_parachains_to_millau_signer_password: None, - rialto_parachains_to_millau_signer_file: None, - rialto_parachains_to_millau_signer_password_file: None, - rialto_parachains_to_millau_transactions_mortality: None, - }, - right_relay: RialtoConnectionParams { - rialto_host: "rialto-node-alice".into(), - rialto_port: 9944, - rialto_secure: false, - rialto_runtime_version: RialtoRuntimeVersionParams { - rialto_version_mode: RuntimeVersionType::Bundle, - rialto_spec_version: None, - rialto_transaction_version: None, - }, - }, - } - ), - ); - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs new file mode 100644 index 0000000000000..82f55a6d6c7aa --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -0,0 +1,694 @@ +// Copyright 2019-2022 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 . + +//! Complex 2-ways headers+messages relays support. +//! +//! To add new complex relay between `ChainA` and `ChainB`, you must: +//! +//! 1) ensure that there's a `declare_chain_cli_schema!(...)` for both chains. +//! 2) add `declare_chain_to_chain_bridge_schema!(...)` or +//! `declare_chain_to_parachain_bridge_schema` for the bridge. +//! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it. + +#[macro_use] +mod relay_to_relay; +#[macro_use] +mod relay_to_parachain; + +use async_trait::async_trait; +use std::sync::Arc; +use structopt::StructOpt; +use strum::VariantNames; + +use futures::{FutureExt, TryFutureExt}; +use relay_to_parachain::*; +use relay_to_relay::*; + +use crate::{ + cli::{ + bridge::{ + CliBridgeBase, MessagesCliBridge, MillauToRialtoCliBridge, + MillauToRialtoParachainCliBridge, ParachainToRelayHeadersCliBridge, + RelayToRelayHeadersCliBridge, RialtoParachainToMillauCliBridge, + RialtoToMillauCliBridge, + }, + chain_schema::*, + relay_messages::RelayerMode, + CliChain, HexLaneId, PrometheusParams, + }, + declare_chain_cli_schema, +}; +use bp_runtime::{BalanceOf, BlockNumberOf}; +use messages_relay::relay_strategy::MixStrategy; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, Client, TransactionSignScheme, +}; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; +use substrate_relay_helper::{ + messages_lane::MessagesRelayParams, on_demand::OnDemandRelay, TaggedAccount, TransactionParams, +}; + +/// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. +/// +/// If it is zero, then transaction will be submitted every time we see difference between +/// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1), +/// then rational relayers may stop relaying messages because they were submitted using +/// lesser conversion rate. +pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; + +/// Parameters that have the same names across all bridges. +#[derive(Debug, PartialEq, StructOpt)] +pub struct HeadersAndMessagesSharedParams { + /// Hex-encoded lane identifiers that should be served by the complex relay. + #[structopt(long, default_value = "00000000")] + pub lane: Vec, + #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] + pub relayer_mode: RelayerMode, + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. + #[structopt(long)] + pub only_mandatory_headers: bool, + #[structopt(flatten)] + pub prometheus_params: PrometheusParams, +} + +pub struct Full2WayBridgeCommonParams< + Left: TransactionSignScheme + CliChain, + Right: TransactionSignScheme + CliChain, +> { + pub shared: HeadersAndMessagesSharedParams, + + pub left: Client, + // default signer, which is always used to sign messages relay transactions on the left chain + pub left_sign: AccountKeyPairOf, + pub left_transactions_mortality: Option, + pub left_messages_pallet_owner: Option>, + pub at_left_accounts: Vec>>, + + pub right: Client, + // default signer, which is always used to sign messages relay transactions on the right chain + pub right_sign: AccountKeyPairOf, + pub right_transactions_mortality: Option, + pub right_messages_pallet_owner: Option>, + pub at_right_accounts: Vec>>, +} + +// All supported chains. +declare_chain_cli_schema!(Millau, millau); +declare_chain_cli_schema!(Rialto, rialto); +declare_chain_cli_schema!(RialtoParachain, rialto_parachain); +// Means to override signers of different layer transactions. +declare_chain_cli_schema!(MillauHeadersToRialto, millau_headers_to_rialto); +declare_chain_cli_schema!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); +declare_chain_cli_schema!(RialtoHeadersToMillau, rialto_headers_to_millau); +declare_chain_cli_schema!(RialtoParachainsToMillau, rialto_parachains_to_millau); +// All supported bridges. +declare_relay_to_relay_bridge_schema!(Millau, Rialto); +declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); + +#[async_trait] +trait Full2WayBridgeBase: Sized + Send + Sync { + /// The CLI params for the bridge. + type Params; + /// The left relay chain. + type Left: TransactionSignScheme + + CliChain>; + /// The right destination chain (it can be a relay or a parachain). + type Right: TransactionSignScheme + + CliChain>; + + fn common(&self) -> &Full2WayBridgeCommonParams; + + fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams; + + async fn start_on_demand_headers_relayers( + &mut self, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )>; +} + +#[async_trait] +trait Full2WayBridge: Sized + Sync +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, + BalanceOf: TryFrom> + Into, +{ + type Base: Full2WayBridgeBase; + + /// The left relay chain. + type Left: Chain + + ChainWithBalances + + TransactionSignScheme + + CliChain>; + /// The right relay chain. + type Right: Chain + + ChainWithBalances + + TransactionSignScheme + + CliChain>; + + // Left to Right bridge + type L2R: MessagesCliBridge; + // Right to Left bridge + type R2L: MessagesCliBridge; + + fn new(params: ::Params) -> anyhow::Result; + + fn base(&self) -> &Self::Base; + + fn mut_base(&mut self) -> &mut Self::Base; + + async fn run(&mut self) -> anyhow::Result<()> { + let left_client = self.base().common().left.clone(); + let left_transactions_mortality = self.base().common().left_transactions_mortality; + let left_sign = self.base().common().left_sign.clone(); + let left_messages_pallet_owner = self.base().common().left_messages_pallet_owner.clone(); + let right_client = self.base().common().right.clone(); + let right_transactions_mortality = self.base().common().right_transactions_mortality; + let right_sign = self.base().common().right_sign.clone(); + let right_messages_pallet_owner = self.base().common().right_messages_pallet_owner.clone(); + + let lanes = self.base().common().shared.lane.clone(); + let relayer_mode = self.base().common().shared.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); + + // create metrics registry and register standalone metrics + let metrics_params: MetricsParams = + self.base().common().shared.prometheus_params.clone().into(); + let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); + let left_to_right_metrics = substrate_relay_helper::messages_metrics::standalone_metrics::< + ::MessagesLane, + >(left_client.clone(), right_client.clone())?; + let right_to_left_metrics = left_to_right_metrics.clone().reverse(); + self.mut_base().mut_common().at_left_accounts.push(TaggedAccount::Messages { + id: left_sign.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }); + self.mut_base().mut_common().at_right_accounts.push(TaggedAccount::Messages { + id: right_sign.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }); + + // start conversion rate update loops for left/right chains + if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { + let left_client = left_client.clone(); + let format_err = || { + anyhow::format_err!( + "Cannon run conversion rate updater: {} -> {}", + Self::Right::NAME, + Self::Left::NAME + ) + }; + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + ::MessagesLane, + Self::Left, + >( + left_client, + TransactionParams { + signer: left_messages_pallet_owner.clone(), + mortality: left_transactions_mortality, + }, + left_to_right_metrics + .target_to_source_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + left_to_right_metrics + .target_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + left_to_right_metrics + .source_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + ); + self.mut_base().mut_common().at_left_accounts.push( + TaggedAccount::MessagesPalletOwner { + id: left_messages_pallet_owner.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }, + ); + } + if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { + let right_client = right_client.clone(); + let format_err = || { + anyhow::format_err!( + "Cannon run conversion rate updater: {} -> {}", + Self::Left::NAME, + Self::Right::NAME + ) + }; + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + ::MessagesLane, + Self::Right, + >( + right_client, + TransactionParams { + signer: right_messages_pallet_owner.clone(), + mortality: right_transactions_mortality, + }, + right_to_left_metrics + .target_to_source_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + right_to_left_metrics + .target_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + right_to_left_metrics + .source_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + ); + self.mut_base().mut_common().at_right_accounts.push( + TaggedAccount::MessagesPalletOwner { + id: right_messages_pallet_owner.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }, + ); + } + + // start on-demand header relays + let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = + self.mut_base().start_on_demand_headers_relayers().await?; + + // add balance-related metrics + let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + left_client.clone(), + metrics_params, + &self.base().common().at_left_accounts, + ) + .await?; + let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + right_client.clone(), + metrics_params, + &self.base().common().at_right_accounts, + ) + .await?; + + // Need 2x capacity since we consider both directions for each lane + let mut message_relays = Vec::with_capacity(lanes.len() * 2); + for lane in lanes { + let lane = lane.into(); + let left_to_right_messages = substrate_relay_helper::messages_lane::run::< + ::MessagesLane, + >(MessagesRelayParams { + source_client: left_client.clone(), + source_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, + target_client: right_client.clone(), + target_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, + source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), + target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), + lane_id: lane, + metrics_params: metrics_params.clone().disable(), + standalone_metrics: Some(left_to_right_metrics.clone()), + relay_strategy: relay_strategy.clone(), + }) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + let right_to_left_messages = substrate_relay_helper::messages_lane::run::< + ::MessagesLane, + >(MessagesRelayParams { + source_client: right_client.clone(), + source_transaction_params: TransactionParams { + signer: right_sign.clone(), + mortality: right_transactions_mortality, + }, + target_client: left_client.clone(), + target_transaction_params: TransactionParams { + signer: left_sign.clone(), + mortality: left_transactions_mortality, + }, + source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), + target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), + lane_id: lane, + metrics_params: metrics_params.clone().disable(), + standalone_metrics: Some(right_to_left_metrics.clone()), + relay_strategy: relay_strategy.clone(), + }) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + + message_relays.push(left_to_right_messages); + message_relays.push(right_to_left_messages); + } + + relay_utils::relay_metrics(metrics_params) + .expose() + .await + .map_err(|e| anyhow::format_err!("{}", e))?; + + futures::future::select_all(message_relays).await.0 + } +} + +pub struct MillauRialtoFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for MillauRialtoFull2WayBridge { + type Base = RelayToRelayBridge; + type Left = relay_millau_client::Millau; + type Right = relay_rialto_client::Rialto; + type L2R = MillauToRialtoCliBridge; + type R2L = RialtoToMillauCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + +pub struct MillauRialtoParachainFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for MillauRialtoParachainFull2WayBridge { + type Base = RelayToParachainBridge; + type Left = relay_millau_client::Millau; + type Right = relay_rialto_parachain_client::RialtoParachain; + type L2R = MillauToRialtoParachainCliBridge; + type R2L = RialtoParachainToMillauCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + +/// Start headers+messages relayer process. +#[derive(Debug, PartialEq, StructOpt)] +pub enum RelayHeadersAndMessages { + MillauRialto(MillauRialtoHeadersAndMessages), + MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), +} + +impl RelayHeadersAndMessages { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self { + RelayHeadersAndMessages::MillauRialto(params) => + MillauRialtoFull2WayBridge::new(params.into_bridge().await?)?.run().await, + RelayHeadersAndMessages::MillauRialtoParachain(params) => + MillauRialtoParachainFull2WayBridge::new(params.into_bridge().await?)? + .run() + .await, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_parse_relay_to_relay_options() { + // when + let res = RelayHeadersAndMessages::from_iter(vec![ + "relay-headers-and-messages", + "millau-rialto", + "--millau-host", + "millau-node-alice", + "--millau-port", + "9944", + "--millau-signer", + "//Charlie", + "--millau-messages-pallet-owner", + "//RialtoMessagesOwner", + "--millau-transactions-mortality", + "64", + "--rialto-host", + "rialto-node-alice", + "--rialto-port", + "9944", + "--rialto-signer", + "//Charlie", + "--rialto-messages-pallet-owner", + "//MillauMessagesOwner", + "--rialto-transactions-mortality", + "64", + "--lane", + "00000000", + "--lane", + "73776170", + "--prometheus-host", + "0.0.0.0", + ]); + + // then + assert_eq!( + res, + RelayHeadersAndMessages::MillauRialto(MillauRialtoHeadersAndMessages { + shared: HeadersAndMessagesSharedParams { + lane: vec![ + HexLaneId([0x00, 0x00, 0x00, 0x00]), + HexLaneId([0x73, 0x77, 0x61, 0x70]) + ], + relayer_mode: RelayerMode::Rational, + only_mandatory_headers: false, + prometheus_params: PrometheusParams { + no_prometheus: false, + prometheus_host: "0.0.0.0".into(), + prometheus_port: 9616, + }, + }, + left: MillauConnectionParams { + millau_host: "millau-node-alice".into(), + millau_port: 9944, + millau_secure: false, + millau_runtime_version: MillauRuntimeVersionParams { + millau_version_mode: RuntimeVersionType::Bundle, + millau_spec_version: None, + millau_transaction_version: None, + }, + }, + left_sign: MillauSigningParams { + millau_signer: Some("//Charlie".into()), + millau_signer_password: None, + millau_signer_file: None, + millau_signer_password_file: None, + millau_transactions_mortality: Some(64), + }, + left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { + millau_messages_pallet_owner: Some("//RialtoMessagesOwner".into()), + millau_messages_pallet_owner_password: None, + }, + left_headers_to_right_sign_override: MillauHeadersToRialtoSigningParams { + millau_headers_to_rialto_signer: None, + millau_headers_to_rialto_signer_password: None, + millau_headers_to_rialto_signer_file: None, + millau_headers_to_rialto_signer_password_file: None, + millau_headers_to_rialto_transactions_mortality: None, + }, + right: RialtoConnectionParams { + rialto_host: "rialto-node-alice".into(), + rialto_port: 9944, + rialto_secure: false, + rialto_runtime_version: RialtoRuntimeVersionParams { + rialto_version_mode: RuntimeVersionType::Bundle, + rialto_spec_version: None, + rialto_transaction_version: None, + }, + }, + right_sign: RialtoSigningParams { + rialto_signer: Some("//Charlie".into()), + rialto_signer_password: None, + rialto_signer_file: None, + rialto_signer_password_file: None, + rialto_transactions_mortality: Some(64), + }, + right_messages_pallet_owner: RialtoMessagesPalletOwnerSigningParams { + rialto_messages_pallet_owner: Some("//MillauMessagesOwner".into()), + rialto_messages_pallet_owner_password: None, + }, + right_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { + rialto_headers_to_millau_signer: None, + rialto_headers_to_millau_signer_password: None, + rialto_headers_to_millau_signer_file: None, + rialto_headers_to_millau_signer_password_file: None, + rialto_headers_to_millau_transactions_mortality: None, + }, + }), + ); + } + + #[test] + fn should_parse_relay_to_parachain_options() { + // when + let res = RelayHeadersAndMessages::from_iter(vec![ + "relay-headers-and-messages", + "millau-rialto-parachain", + "--millau-host", + "millau-node-alice", + "--millau-port", + "9944", + "--millau-signer", + "//Iden", + "--rialto-headers-to-millau-signer", + "//Ken", + "--millau-messages-pallet-owner", + "//RialtoParachainMessagesOwner", + "--millau-transactions-mortality", + "64", + "--rialto-parachain-host", + "rialto-parachain-collator-charlie", + "--rialto-parachain-port", + "9944", + "--rialto-parachain-signer", + "//George", + "--rialto-parachain-messages-pallet-owner", + "//MillauMessagesOwner", + "--rialto-parachain-transactions-mortality", + "64", + "--rialto-host", + "rialto-node-alice", + "--rialto-port", + "9944", + "--lane", + "00000000", + "--prometheus-host", + "0.0.0.0", + ]); + + // then + assert_eq!( + res, + RelayHeadersAndMessages::MillauRialtoParachain( + MillauRialtoParachainHeadersAndMessages { + shared: HeadersAndMessagesSharedParams { + lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], + relayer_mode: RelayerMode::Rational, + only_mandatory_headers: false, + prometheus_params: PrometheusParams { + no_prometheus: false, + prometheus_host: "0.0.0.0".into(), + prometheus_port: 9616, + }, + }, + left: MillauConnectionParams { + millau_host: "millau-node-alice".into(), + millau_port: 9944, + millau_secure: false, + millau_runtime_version: MillauRuntimeVersionParams { + millau_version_mode: RuntimeVersionType::Bundle, + millau_spec_version: None, + millau_transaction_version: None, + }, + }, + left_sign: MillauSigningParams { + millau_signer: Some("//Iden".into()), + millau_signer_password: None, + millau_signer_file: None, + millau_signer_password_file: None, + millau_transactions_mortality: Some(64), + }, + left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { + millau_messages_pallet_owner: Some("//RialtoParachainMessagesOwner".into()), + millau_messages_pallet_owner_password: None, + }, + left_headers_to_right_sign_override: + MillauHeadersToRialtoParachainSigningParams { + millau_headers_to_rialto_parachain_signer: None, + millau_headers_to_rialto_parachain_signer_password: None, + millau_headers_to_rialto_parachain_signer_file: None, + millau_headers_to_rialto_parachain_signer_password_file: None, + millau_headers_to_rialto_parachain_transactions_mortality: None, + }, + right: RialtoParachainConnectionParams { + rialto_parachain_host: "rialto-parachain-collator-charlie".into(), + rialto_parachain_port: 9944, + rialto_parachain_secure: false, + rialto_parachain_runtime_version: RialtoParachainRuntimeVersionParams { + rialto_parachain_version_mode: RuntimeVersionType::Bundle, + rialto_parachain_spec_version: None, + rialto_parachain_transaction_version: None, + }, + }, + right_sign: RialtoParachainSigningParams { + rialto_parachain_signer: Some("//George".into()), + rialto_parachain_signer_password: None, + rialto_parachain_signer_file: None, + rialto_parachain_signer_password_file: None, + rialto_parachain_transactions_mortality: Some(64), + }, + right_messages_pallet_owner: RialtoParachainMessagesPalletOwnerSigningParams { + rialto_parachain_messages_pallet_owner: Some( + "//MillauMessagesOwner".into() + ), + rialto_parachain_messages_pallet_owner_password: None, + }, + right_relay_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { + rialto_headers_to_millau_signer: Some("//Ken".into()), + rialto_headers_to_millau_signer_password: None, + rialto_headers_to_millau_signer_file: None, + rialto_headers_to_millau_signer_password_file: None, + rialto_headers_to_millau_transactions_mortality: None, + }, + right_parachains_to_left_sign_override: RialtoParachainsToMillauSigningParams { + rialto_parachains_to_millau_signer: None, + rialto_parachains_to_millau_signer_password: None, + rialto_parachains_to_millau_signer_file: None, + rialto_parachains_to_millau_signer_password_file: None, + rialto_parachains_to_millau_transactions_mortality: None, + }, + right_relay: RialtoConnectionParams { + rialto_host: "rialto-node-alice".into(), + rialto_port: 9944, + rialto_secure: false, + rialto_runtime_version: RialtoRuntimeVersionParams { + rialto_version_mode: RuntimeVersionType::Bundle, + rialto_spec_version: None, + rialto_transaction_version: None, + }, + }, + } + ), + ); + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs new file mode 100644 index 0000000000000..0d847141d4a68 --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -0,0 +1,235 @@ +// Copyright 2019-2022 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 . + +use async_trait::async_trait; +use std::sync::Arc; + +use crate::cli::{ + bridge::{ + CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, + RelayToRelayHeadersCliBridge, + }, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + CliChain, +}; +use bp_polkadot_core::parachains::ParaHash; +use bp_runtime::BlockNumberOf; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, Client, TransactionSignScheme}; +use sp_core::Pair; +use substrate_relay_helper::{ + finality::SubstrateFinalitySyncPipeline, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, + }, + TaggedAccount, TransactionParams, +}; + +pub struct RelayToParachainBridge< + L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge, + R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge, +> { + pub common: + Full2WayBridgeCommonParams<::Target, ::Target>, + pub right_relay: Client<::SourceRelay>, + + // override for right_relay->left headers signer + pub right_headers_to_left_transaction_params: + TransactionParams::Target>>, + // override for right->left parachains signer + pub right_parachains_to_left_transaction_params: + TransactionParams::Target>>, + // override for left->right headers signer + pub left_headers_to_right_transaction_params: + TransactionParams::Target>>, +} + +macro_rules! declare_relay_to_parachain_bridge_schema { + // chain, parachain, relay-chain-of-parachain + ($left_chain:ident, $right_parachain:ident, $right_chain:ident) => { + paste::item! { + #[doc = $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."] + #[derive(Debug, PartialEq, StructOpt)] + pub struct [<$left_chain $right_parachain HeadersAndMessages>] { + #[structopt(flatten)] + shared: HeadersAndMessagesSharedParams, + #[structopt(flatten)] + left: [<$left_chain ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the left chain + #[structopt(flatten)] + left_sign: [<$left_chain SigningParams>], + // override for right_relay->left headers signer + #[structopt(flatten)] + right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], + // override for right->left parachains signer + #[structopt(flatten)] + right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>], + #[structopt(flatten)] + left_messages_pallet_owner: [<$left_chain MessagesPalletOwnerSigningParams>], + #[structopt(flatten)] + right: [<$right_parachain ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the right chain + #[structopt(flatten)] + right_sign: [<$right_parachain SigningParams>], + // override for left->right headers signer + #[structopt(flatten)] + left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], + #[structopt(flatten)] + right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>], + #[structopt(flatten)] + right_relay: [<$right_chain ConnectionParams>], + } + + impl [<$left_chain $right_parachain HeadersAndMessages>] { + async fn into_bridge< + Left: TransactionSignScheme + CliChain>, + Right: TransactionSignScheme + CliChain>, + RightRelay: TransactionSignScheme + CliChain, + L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, + R2L: CliBridgeBase + + MessagesCliBridge + + ParachainToRelayHeadersCliBridge, + >( + self, + ) -> anyhow::Result> { + Ok(RelayToParachainBridge { + common: Full2WayBridgeCommonParams { + shared: self.shared, + left: self.left.into_client::().await?, + left_sign: self.left_sign.to_keypair::()?, + left_transactions_mortality: self.left_sign.transactions_mortality()?, + left_messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + at_left_accounts: vec![], + right: self.right.into_client::().await?, + right_sign: self.right_sign.to_keypair::()?, + right_transactions_mortality: self.right_sign.transactions_mortality()?, + right_messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + at_right_accounts: vec![], + }, + right_relay: self.right_relay.into_client::().await?, + right_headers_to_left_transaction_params: self + .right_relay_headers_to_left_sign_override + .transaction_params_or::( + &self.left_sign, + )?, + right_parachains_to_left_transaction_params: self + .right_parachains_to_left_sign_override + .transaction_params_or::( + &self.left_sign, + )?, + left_headers_to_right_transaction_params: self + .left_headers_to_right_sign_override + .transaction_params_or::(&self.right_sign)?, + }) + } + } + } + }; +} + +#[async_trait] +impl< + Left: Chain + TransactionSignScheme + CliChain>, + Right: Chain + + TransactionSignScheme + + CliChain>, + RightRelay: Chain + + TransactionSignScheme + + CliChain, + L2R: CliBridgeBase + + MessagesCliBridge + + RelayToRelayHeadersCliBridge, + R2L: CliBridgeBase + + MessagesCliBridge + + ParachainToRelayHeadersCliBridge, + > Full2WayBridgeBase for RelayToParachainBridge +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, +{ + type Params = RelayToParachainBridge; + type Left = Left; + type Right = Right; + + fn common(&self) -> &Full2WayBridgeCommonParams { + &self.common + } + + fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams { + &mut self.common + } + + async fn start_on_demand_headers_relayers( + &mut self, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + self.common.at_left_accounts.push(TaggedAccount::Headers { + id: self.right_headers_to_left_transaction_params.signer.public().into(), + bridged_chain: RightRelay::NAME.to_string(), + }); + self.common.at_left_accounts.push(TaggedAccount::Parachains { + id: self.right_parachains_to_left_transaction_params.signer.public().into(), + bridged_chain: RightRelay::NAME.to_string(), + }); + self.common.at_right_accounts.push(TaggedAccount::Headers { + id: self.left_headers_to_right_transaction_params.signer.public().into(), + bridged_chain: Left::NAME.to_string(), + }); + + ::Finality::start_relay_guards( + &self.common.right, + &self.left_headers_to_right_transaction_params, + self.common.right.can_start_version_guard(), + ) + .await?; + ::RelayFinality::start_relay_guards( + &self.common.left, + &self.right_headers_to_left_transaction_params, + self.common.left.can_start_version_guard(), + ) + .await?; + + let left_to_right_on_demand_headers = + OnDemandHeadersRelay::new::<::Finality>( + self.common.left.clone(), + self.common.right.clone(), + self.left_headers_to_right_transaction_params.clone(), + self.common.shared.only_mandatory_headers, + ); + let right_relay_to_left_on_demand_headers = + OnDemandHeadersRelay::new::<::RelayFinality>( + self.right_relay.clone(), + self.common.left.clone(), + self.right_headers_to_left_transaction_params.clone(), + self.common.shared.only_mandatory_headers, + ); + let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::< + ::ParachainFinality, + >( + self.right_relay.clone(), + self.common.left.clone(), + self.right_parachains_to_left_transaction_params.clone(), + Arc::new(right_relay_to_left_on_demand_headers), + ); + + Ok(( + Arc::new(left_to_right_on_demand_headers), + Arc::new(right_to_left_on_demand_parachains), + )) + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs new file mode 100644 index 0000000000000..4e9ecd2b58122 --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -0,0 +1,187 @@ +// Copyright 2019-2022 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 . + +use async_trait::async_trait; +use std::sync::Arc; + +use crate::cli::{ + bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + CliChain, +}; +use bp_runtime::BlockNumberOf; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, TransactionSignScheme}; +use sp_core::Pair; +use substrate_relay_helper::{ + finality::SubstrateFinalitySyncPipeline, + on_demand::{headers::OnDemandHeadersRelay, OnDemandRelay}, + TaggedAccount, TransactionParams, +}; + +pub struct RelayToRelayBridge< + L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge, + R2L: MessagesCliBridge + RelayToRelayHeadersCliBridge, +> { + pub common: + Full2WayBridgeCommonParams<::Target, ::Target>, + // override for right->left headers signer + pub right_to_left_transaction_params: + TransactionParams::Target>>, + // override for left->right headers signer + pub left_to_right_transaction_params: + TransactionParams::Target>>, +} + +macro_rules! declare_relay_to_relay_bridge_schema { + ($left_chain:ident, $right_chain:ident) => { + paste::item! { + #[doc = $left_chain " and " $right_chain " headers+messages relay params."] + #[derive(Debug, PartialEq, StructOpt)] + pub struct [<$left_chain $right_chain HeadersAndMessages>] { + #[structopt(flatten)] + shared: HeadersAndMessagesSharedParams, + // default signer, which is always used to sign messages relay transactions on the left chain + #[structopt(flatten)] + left: [<$left_chain ConnectionParams>], + // override for right->left headers signer + #[structopt(flatten)] + right_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], + #[structopt(flatten)] + left_sign: [<$left_chain SigningParams>], + #[structopt(flatten)] + left_messages_pallet_owner: [<$left_chain MessagesPalletOwnerSigningParams>], + // default signer, which is always used to sign messages relay transactions on the right chain + #[structopt(flatten)] + right: [<$right_chain ConnectionParams>], + // override for left->right headers signer + #[structopt(flatten)] + left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_chain SigningParams>], + #[structopt(flatten)] + right_sign: [<$right_chain SigningParams>], + #[structopt(flatten)] + right_messages_pallet_owner: [<$right_chain MessagesPalletOwnerSigningParams>], + } + + impl [<$left_chain $right_chain HeadersAndMessages>] { + async fn into_bridge< + Left: TransactionSignScheme + CliChain>, + Right: TransactionSignScheme + CliChain>, + L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, + R2L: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, + >( + self, + ) -> anyhow::Result> { + Ok(RelayToRelayBridge { + common: Full2WayBridgeCommonParams { + shared: self.shared, + left: self.left.into_client::().await?, + left_sign: self.left_sign.to_keypair::()?, + left_transactions_mortality: self.left_sign.transactions_mortality()?, + left_messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + at_left_accounts: vec![], + right: self.right.into_client::().await?, + right_sign: self.right_sign.to_keypair::()?, + right_transactions_mortality: self.right_sign.transactions_mortality()?, + right_messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + at_right_accounts: vec![], + }, + + right_to_left_transaction_params: self + .right_headers_to_left_sign_override + .transaction_params_or::(&self.left_sign)?, + left_to_right_transaction_params: self + .left_headers_to_right_sign_override + .transaction_params_or::(&self.right_sign)?, + }) + } + } + } + }; +} + +#[async_trait] +impl< + Left: Chain + TransactionSignScheme + CliChain>, + Right: Chain + TransactionSignScheme + CliChain>, + L2R: CliBridgeBase + + MessagesCliBridge + + RelayToRelayHeadersCliBridge, + R2L: CliBridgeBase + + MessagesCliBridge + + RelayToRelayHeadersCliBridge, + > Full2WayBridgeBase for RelayToRelayBridge +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, +{ + type Params = RelayToRelayBridge; + type Left = Left; + type Right = Right; + + fn common(&self) -> &Full2WayBridgeCommonParams { + &self.common + } + + fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams { + &mut self.common + } + + async fn start_on_demand_headers_relayers( + &mut self, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + self.common.at_right_accounts.push(TaggedAccount::Headers { + id: self.left_to_right_transaction_params.signer.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }); + self.common.at_left_accounts.push(TaggedAccount::Headers { + id: self.right_to_left_transaction_params.signer.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }); + + ::Finality::start_relay_guards( + &self.common.right, + &self.left_to_right_transaction_params, + self.common.right.can_start_version_guard(), + ) + .await?; + ::Finality::start_relay_guards( + &self.common.left, + &self.right_to_left_transaction_params, + self.common.left.can_start_version_guard(), + ) + .await?; + + let left_to_right_on_demand_headers = + OnDemandHeadersRelay::new::<::Finality>( + self.common.left.clone(), + self.common.right.clone(), + self.left_to_right_transaction_params.clone(), + self.common.shared.only_mandatory_headers, + ); + let right_to_left_on_demand_headers = + OnDemandHeadersRelay::new::<::Finality>( + self.common.right.clone(), + self.common.left.clone(), + self.right_to_left_transaction_params.clone(), + self.common.shared.only_mandatory_headers, + ); + + Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_headers))) + } +} diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 7242d13185203..df21abac991ff 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -20,16 +20,10 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use messages_relay::relay_strategy::MixStrategy; -use relay_substrate_client::{AccountKeyPairOf, ChainBase, TransactionSignScheme}; -use substrate_relay_helper::{ - messages_lane::{MessagesRelayParams, SubstrateMessageLane}, - TransactionParams, -}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, TransactionSignScheme}; +use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; -use crate::cli::{ - bridge::*, CliChain, HexLaneId, PrometheusParams, SourceConnectionParams, SourceSigningParams, - TargetConnectionParams, TargetSigningParams, -}; +use crate::cli::{bridge::*, chain_schema::*, CliChain, HexLaneId, PrometheusParams}; /// Relayer operating mode. #[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)] @@ -79,16 +73,15 @@ trait MessagesRelayer: MessagesCliBridge where Self::Source: TransactionSignScheme + CliChain>, - ::AccountId: From< as Pair>::Public>, - ::AccountId: From< as Pair>::Public>, - ::Balance: TryFrom<::Balance>, - Self::MessagesLane: SubstrateMessageLane, + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom>, { async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> { - let source_client = data.source.to_client::().await?; + let source_client = data.source.into_client::().await?; let source_sign = data.source_sign.to_keypair::()?; let source_transactions_mortality = data.source_sign.transactions_mortality()?; - let target_client = data.target.to_client::().await?; + let target_client = data.target.into_client::().await?; let target_sign = data.target_sign.to_keypair::()?; let target_transactions_mortality = data.target_sign.transactions_mortality()?; let relayer_mode = data.relayer_mode.into(); diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index eb46909b3a1be..f2d56b7d6e249 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -16,27 +16,22 @@ use async_trait::async_trait; use bp_polkadot_core::parachains::ParaId; -use pallet_bridge_parachains::RelayBlockNumber; -use parachains_relay::{ - parachains_loop::{ParachainSyncParams, SourceClient, TargetClient}, - ParachainsPipeline, -}; -use relay_substrate_client::{Chain, RelayChain}; +use parachains_relay::parachains_loop::{ParachainSyncParams, SourceClient, TargetClient}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ - parachains::{ - source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter, - SubstrateParachainsPipeline, - }, + parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, TransactionParams, }; use crate::cli::{ - bridge::{CliBridgeBase, RialtoParachainToMillauCliBridge, WestmintToMillauCliBridge}, - CliChain, PrometheusParams, SourceConnectionParams, TargetConnectionParams, - TargetSigningParams, + bridge::{ + ParachainToRelayHeadersCliBridge, RialtoParachainToMillauCliBridge, + WestmintToMillauCliBridge, + }, + chain_schema::*, + PrometheusParams, }; /// Start parachain heads relayer process. @@ -64,29 +59,23 @@ pub enum RelayParachainsBridge { } #[async_trait] -trait ParachainsRelayer: CliBridgeBase +trait ParachainsRelayer: ParachainToRelayHeadersCliBridge where - ParachainsSource: SourceClient>, - ParachainsTarget: TargetClient>, + ParachainsSource: + SourceClient>, + ParachainsTarget: + TargetClient>, { - type SourceRelay: Chain + CliChain + RelayChain; - type Pipeline: SubstrateParachainsPipeline< - SourceParachain = Self::Source, - TargetChain = Self::Target, - SourceRelayChain = Self::SourceRelay, - TransactionSignScheme = Self::Target, - > + ParachainsPipeline; - async fn relay_headers(data: RelayParachains) -> anyhow::Result<()> { - let source_client = data.source.to_client::().await?; - let source_client = ParachainsSource::::new(source_client, None); + let source_client = data.source.into_client::().await?; + let source_client = ParachainsSource::::new(source_client, None); let target_transaction_params = TransactionParams { signer: data.target_sign.to_keypair::()?, mortality: data.target_sign.target_transactions_mortality, }; - let target_client = data.target.to_client::().await?; - let target_client = ParachainsTarget::::new( + let target_client = data.target.into_client::().await?; + let target_client = ParachainsTarget::::new( target_client.clone(), target_transaction_params, ); @@ -110,15 +99,9 @@ where } } -impl ParachainsRelayer for RialtoParachainToMillauCliBridge { - type SourceRelay = relay_rialto_client::Rialto; - type Pipeline = crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau; -} +impl ParachainsRelayer for RialtoParachainToMillauCliBridge {} -impl ParachainsRelayer for WestmintToMillauCliBridge { - type SourceRelay = relay_westend_client::Westend; - type Pipeline = crate::chains::westend_parachains_to_millau::WestendParachainsToMillau; -} +impl ParachainsRelayer for WestmintToMillauCliBridge {} impl RelayParachains { /// Run the command. diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 62af6afe93720..a4cec796552e1 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{Balance, TargetConnectionParams, TargetSigningParams}; +use crate::cli::{chain_schema::*, Balance}; use codec::{Decode, Encode}; use num_traits::{One, Zero}; @@ -102,7 +102,7 @@ impl ResubmitTransactions { pub async fn run(self) -> anyhow::Result<()> { select_bridge!(self.chain, { let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); - let client = self.target.to_client::().await?; + let client = self.target.into_client::().await?; let transaction_params = TransactionParams { signer: self.target_sign.to_keypair::()?, mortality: self.target_sign.target_transactions_mortality, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index ee17fb3f31fea..da844172c984e 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -16,15 +16,16 @@ use crate::cli::{ bridge::{FullBridge, MessagesCliBridge, *}, + chain_schema::*, encode_message::{self, CliEncodeMessage}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, CliChain, HexBytes, HexLaneId, SourceConnectionParams, SourceSigningParams, + Balance, CliChain, HexBytes, HexLaneId, }; use async_trait::async_trait; -use bp_runtime::AccountIdOf; use codec::Encode; use relay_substrate_client::{ - AccountKeyPairOf, Chain, ChainBase, SignParam, TransactionSignScheme, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, ChainBase, SignParam, TransactionSignScheme, + UnsignedTransaction, }; use sp_core::{Bytes, Pair}; use sp_runtime::AccountId32; @@ -95,7 +96,7 @@ where async fn send_message(data: SendMessage) -> anyhow::Result<()> { let payload = encode_message::encode_message::(&data.message)?; - let source_client = data.source.to_client::().await?; + let source_client = data.source.into_client::().await?; let source_sign = data.source_sign.to_keypair::()?; let lane = data.lane.clone().into(); diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 448c33c5ba397..5619645d0a485 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -756,6 +756,15 @@ impl Client { let client = self.client.clone(); self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? } + + /// Returns `true` if version guard can be started. + /// + /// There's no reason to run version guard when version mode is set to `Auto`. It can + /// lead to relay shutdown when chain is upgraded, even though we have explicitly + /// said that we don't want to shutdown. + pub fn can_start_version_guard(&self) -> bool { + !matches!(self.chain_runtime_version, ChainRuntimeVersion::Auto) + } } impl Subscription { diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 7c621b4c39a51..4210c7d981bd5 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -274,7 +274,7 @@ pub fn standalone_metrics( pub async fn add_relay_balances_metrics( client: Client, metrics: MetricsParams, - relay_accounts: Vec>>, + relay_accounts: &Vec>>, ) -> anyhow::Result where BalanceOf: Into + std::fmt::Debug, From dd23dc1f1009778f8e68722ec7aefa9f2cd28a1b Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 13 Jul 2022 14:51:10 +0300 Subject: [PATCH 0733/1210] Move bridge definitions Move bridge definitions to their specific folder. Signed-off-by: Serban Iorga --- .../src/chains/millau_headers_to_rialto.rs | 19 ++++ .../millau_headers_to_rialto_parachain.rs | 20 ++++ .../src/chains/rialto_headers_to_millau.rs | 19 ++++ .../src/chains/rialto_parachains_to_millau.rs | 22 ++++ .../src/chains/westend_headers_to_millau.rs | 13 +++ .../chains/westend_parachains_to_millau.rs | 15 +++ relays/bin-substrate/src/cli/bridge.rs | 103 ------------------ relays/bin-substrate/src/cli/estimate_fee.rs | 18 ++- relays/bin-substrate/src/cli/init_bridge.rs | 12 +- relays/bin-substrate/src/cli/relay_headers.rs | 6 + .../src/cli/relay_headers_and_messages/mod.rs | 12 +- .../bin-substrate/src/cli/relay_messages.rs | 6 + .../bin-substrate/src/cli/relay_parachains.rs | 13 +-- relays/bin-substrate/src/cli/send_message.rs | 20 +++- 14 files changed, 167 insertions(+), 131 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 2fefc2e74c968..0aa49bdada92c 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -16,6 +16,7 @@ //! Millau-to-Rialto headers sync entrypoint. +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; use substrate_relay_helper::finality::{ engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, @@ -37,3 +38,21 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { >; type TransactionSignScheme = relay_rialto_client::Rialto; } + +//// `Millau` to `Rialto` bridge definition. +pub struct MillauToRialtoCliBridge {} + +impl CliBridgeBase for MillauToRialtoCliBridge { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_client::Rialto; +} + +impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { + type Finality = MillauFinalityToRialto; +} + +impl MessagesCliBridge for MillauToRialtoCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; +} diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs index d44369de01a32..4eaf3f6f750a1 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -34,6 +34,7 @@ //! Millau-to-RialtoParachain headers sync entrypoint. +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; use substrate_relay_helper::finality::{ engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, @@ -55,3 +56,22 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { >; type TransactionSignScheme = relay_rialto_parachain_client::RialtoParachain; } + +//// `Millau` to `RialtoParachain` bridge definition. +pub struct MillauToRialtoParachainCliBridge {} + +impl CliBridgeBase for MillauToRialtoParachainCliBridge { + type Source = relay_millau_client::Millau; + type Target = relay_rialto_parachain_client::RialtoParachain; +} + +impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { + type Finality = MillauFinalityToRialtoParachain; +} + +impl MessagesCliBridge for MillauToRialtoParachainCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; +} diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index a890405703e6a..65c5cba1ae378 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -16,6 +16,7 @@ //! Rialto-to-Millau headers sync entrypoint. +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; use substrate_relay_helper::finality::{ engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, @@ -37,3 +38,21 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { >; type TransactionSignScheme = relay_millau_client::Millau; } + +//// `Rialto` to `Millau` bridge definition. +pub struct RialtoToMillauCliBridge {} + +impl CliBridgeBase for RialtoToMillauCliBridge { + type Source = relay_rialto_client::Rialto; + type Target = relay_millau_client::Millau; +} + +impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { + type Finality = RialtoFinalityToMillau; +} + +impl MessagesCliBridge for RialtoToMillauCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; +} diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index 986c335e1e469..800d5a3e79bd2 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -16,6 +16,7 @@ //! Rialto-to-Millau parachains sync entrypoint. +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use parachains_relay::ParachainsPipeline; use relay_millau_client::Millau; use relay_rialto_client::Rialto; @@ -51,3 +52,24 @@ pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder = millau_runtime::Runtime, millau_runtime::WithRialtoParachainsInstance, >; + +//// `RialtoParachain` to `Millau` bridge definition. +pub struct RialtoParachainToMillauCliBridge {} + +impl CliBridgeBase for RialtoParachainToMillauCliBridge { + type Source = RialtoParachain; + type Target = Millau; +} + +impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge { + type SourceRelay = Rialto; + type ParachainFinality = RialtoParachainsToMillau; + type RelayFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; +} + +impl MessagesCliBridge for RialtoParachainToMillauCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; +} diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 3ed67dd260a6b..833946458974a 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -16,6 +16,7 @@ //! Westend-to-Millau headers sync entrypoint. +use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; use substrate_relay_helper::finality::{ engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, @@ -37,3 +38,15 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { >; type TransactionSignScheme = relay_millau_client::Millau; } + +//// `Westend` to `Millau` bridge definition. +pub struct WestendToMillauCliBridge {} + +impl CliBridgeBase for WestendToMillauCliBridge { + type Source = relay_westend_client::Westend; + type Target = relay_millau_client::Millau; +} + +impl RelayToRelayHeadersCliBridge for WestendToMillauCliBridge { + type Finality = WestendFinalityToMillau; +} diff --git a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs index 3a508ae49b6ed..586d391d247c1 100644 --- a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs @@ -16,6 +16,7 @@ //! Westend-to-Millau parachains sync entrypoint. +use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; use parachains_relay::ParachainsPipeline; use relay_millau_client::Millau; use relay_westend_client::{Westend, Westmint}; @@ -50,3 +51,17 @@ pub type WestendParachainsToMillauSubmitParachainHeadsCallBuilder = millau_runtime::Runtime, millau_runtime::WithWestendParachainsInstance, >; + +//// `WestendParachain` to `Millau` bridge definition. +pub struct WestmintToMillauCliBridge {} + +impl ParachainToRelayHeadersCliBridge for WestmintToMillauCliBridge { + type SourceRelay = Westend; + type ParachainFinality = WestendParachainsToMillau; + type RelayFinality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; +} + +impl CliBridgeBase for WestmintToMillauCliBridge { + type Source = Westmint; + type Target = Millau; +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index e0d65e3caf9b1..503e523c0289a 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -111,106 +111,3 @@ pub trait MessagesCliBridge: CliBridgeBase { RelayStrategy = MixStrategy, >; } - -//// `Millau` to `Rialto` bridge definition. -pub struct MillauToRialtoCliBridge {} - -impl CliBridgeBase for MillauToRialtoCliBridge { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; -} - -impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { - type Finality = crate::chains::millau_headers_to_rialto::MillauFinalityToRialto; -} - -impl MessagesCliBridge for MillauToRialtoCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; - type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; -} - -//// `Rialto` to `Millau` bridge definition. -pub struct RialtoToMillauCliBridge {} - -impl CliBridgeBase for RialtoToMillauCliBridge { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; -} - -impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { - type Finality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; -} - -impl MessagesCliBridge for RialtoToMillauCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; - type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; -} - -//// `Westend` to `Millau` bridge definition. -pub struct WestendToMillauCliBridge {} - -impl CliBridgeBase for WestendToMillauCliBridge { - type Source = relay_westend_client::Westend; - type Target = relay_millau_client::Millau; -} - -impl RelayToRelayHeadersCliBridge for WestendToMillauCliBridge { - type Finality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; -} - -//// `Millau` to `RialtoParachain` bridge definition. -pub struct MillauToRialtoParachainCliBridge {} - -impl CliBridgeBase for MillauToRialtoParachainCliBridge { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_parachain_client::RialtoParachain; -} - -impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { - type Finality = - crate::chains::millau_headers_to_rialto_parachain::MillauFinalityToRialtoParachain; -} - -impl MessagesCliBridge for MillauToRialtoParachainCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD; - type MessagesLane = - crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; -} - -//// `RialtoParachain` to `Millau` bridge definition. -pub struct RialtoParachainToMillauCliBridge {} - -impl CliBridgeBase for RialtoParachainToMillauCliBridge { - type Source = relay_rialto_parachain_client::RialtoParachain; - type Target = relay_millau_client::Millau; -} - -impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge { - type SourceRelay = relay_rialto_client::Rialto; - type ParachainFinality = crate::chains::rialto_parachains_to_millau::RialtoParachainsToMillau; - type RelayFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; -} - -impl MessagesCliBridge for RialtoParachainToMillauCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; - type MessagesLane = - crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; -} - -//// `WestendParachain` to `Millau` bridge definition. -pub struct WestmintToMillauCliBridge {} - -impl ParachainToRelayHeadersCliBridge for WestmintToMillauCliBridge { - type SourceRelay = relay_westend_client::Westend; - type ParachainFinality = crate::chains::westend_parachains_to_millau::WestendParachainsToMillau; - type RelayFinality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; -} - -impl CliBridgeBase for WestmintToMillauCliBridge { - type Source = relay_westend_client::Westmint; - type Target = relay_millau_client::Millau; -} diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 0f4fd765f4074..ed1e27bcf5f00 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -14,11 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{ - bridge::{FullBridge, MessagesCliBridge, *}, - chain_schema::*, - relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - Balance, HexBytes, HexLaneId, +use crate::{ + chains::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + }, + cli::{ + bridge::{FullBridge, MessagesCliBridge}, + chain_schema::*, + relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + Balance, HexBytes, HexLaneId, + }, }; use async_trait::async_trait; use bp_runtime::BalanceOf; diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 98f30b9f7bdfc..971512f2111b1 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -16,12 +16,14 @@ use async_trait::async_trait; -use crate::cli::{ - bridge::{ - CliBridgeBase, MillauToRialtoCliBridge, MillauToRialtoParachainCliBridge, - RialtoToMillauCliBridge, WestendToMillauCliBridge, +use crate::{ + chains::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + westend_headers_to_millau::WestendToMillauCliBridge, }, - chain_schema::*, + cli::{bridge::CliBridgeBase, chain_schema::*}, }; use bp_runtime::Chain as ChainBase; use codec::Encode; diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 59325e452e370..df6d96f7223e7 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -20,6 +20,12 @@ use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use crate::chains::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + westend_headers_to_millau::WestendToMillauCliBridge, +}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 82f55a6d6c7aa..d4840f4c7d113 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -38,12 +38,16 @@ use relay_to_parachain::*; use relay_to_relay::*; use crate::{ + chains::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + }, cli::{ bridge::{ - CliBridgeBase, MessagesCliBridge, MillauToRialtoCliBridge, - MillauToRialtoParachainCliBridge, ParachainToRelayHeadersCliBridge, - RelayToRelayHeadersCliBridge, RialtoParachainToMillauCliBridge, - RialtoToMillauCliBridge, + CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, + RelayToRelayHeadersCliBridge, }, chain_schema::*, relay_messages::RelayerMode, diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index df21abac991ff..a68ce03054308 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -19,6 +19,12 @@ use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; +use crate::chains::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, +}; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, TransactionSignScheme}; use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index f2d56b7d6e249..2fa6dcaf9eb4b 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::chains::{ + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + westend_parachains_to_millau::WestmintToMillauCliBridge, +}; use async_trait::async_trait; use bp_polkadot_core::parachains::ParaId; use parachains_relay::parachains_loop::{ParachainSyncParams, SourceClient, TargetClient}; @@ -25,14 +29,7 @@ use substrate_relay_helper::{ TransactionParams, }; -use crate::cli::{ - bridge::{ - ParachainToRelayHeadersCliBridge, RialtoParachainToMillauCliBridge, - WestmintToMillauCliBridge, - }, - chain_schema::*, - PrometheusParams, -}; +use crate::cli::{bridge::ParachainToRelayHeadersCliBridge, chain_schema::*, PrometheusParams}; /// Start parachain heads relayer process. #[derive(StructOpt)] diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index da844172c984e..2e4e3628b0b42 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -14,12 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::{ - bridge::{FullBridge, MessagesCliBridge, *}, - chain_schema::*, - encode_message::{self, CliEncodeMessage}, - estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, CliChain, HexBytes, HexLaneId, +use crate::{ + chains::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + }, + cli::{ + bridge::{FullBridge, MessagesCliBridge}, + chain_schema::*, + encode_message::{self, CliEncodeMessage}, + estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, + Balance, CliChain, HexBytes, HexLaneId, + }, }; use async_trait::async_trait; use codec::Encode; From 54a73aec7e9073321909cf72af33480e917238fd Mon Sep 17 00:00:00 2001 From: Dan Shields <35669742+NukeManDan@users.noreply.github.com> Date: Thu, 14 Jul 2022 06:57:35 +0100 Subject: [PATCH 0734/1210] rm substrate.dev homepage (#1506) new docs page --- README.md | 4 ++-- bin/millau/node/Cargo.toml | 1 - bin/millau/runtime/Cargo.toml | 1 - bin/rialto-parachain/node/Cargo.toml | 1 - bin/rialto-parachain/runtime/Cargo.toml | 1 - bin/rialto/node/Cargo.toml | 1 - bin/rialto/runtime/Cargo.toml | 1 - bin/runtime-common/Cargo.toml | 1 - 8 files changed, 2 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3d3b177bbaae6..d45b328b2bdfe 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ docker run --rm -it -w /shellhere/parity-bridges-common \ If you want to reproduce other steps of CI process you can use the following [guide](https://github.com/paritytech/scripts#reproduce-ci-locally). -If you need more information about setting up your development environment Substrate's -[Getting Started](https://substrate.dev/docs/en/knowledgebase/getting-started/) page is a good +If you need more information about setting up your development environment [Substrate's +Installation page](https://docs.substrate.io/main-docs/install/) is a good resource. ## High-Level Architecture diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 9498b7311370d..28bd9ed0564fc 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -5,7 +5,6 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" build = "build.rs" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index a98fc2f6c30eb..80858b2e31eb5 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -3,7 +3,6 @@ name = "millau-runtime" version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index d73cdc6d27638..26b91019c1e0e 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -3,7 +3,6 @@ name = "rialto-parachain-collator" version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 543e2675284bf..ac1c1cf3d568d 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -3,7 +3,6 @@ name = "rialto-parachain-runtime" version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 6ae7eba231850..fe2186ea3f30f 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -5,7 +5,6 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" build = "build.rs" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 4c6bb990e19c6..ff3eb703ff358 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -3,7 +3,6 @@ name = "rialto-runtime" version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 3bf778ee50a03..cb9f37fe66c42 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -3,7 +3,6 @@ name = "bridge-runtime-common" version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" -homepage = "https://substrate.dev" repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" From 9a37168a73f3e2a4ceef0375f5d54fb3a64fbf70 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 14 Jul 2022 15:18:15 +0300 Subject: [PATCH 0735/1210] Add another condition to the reject-obsolete-parachain-heads extension (#1505) * add another condition to the reject-obsolete-parachain-heads extension * add tracing to obsolete-tx-extensions * fix tests * extension_rejects_header_from_new_relay_block_with_same_hash * fmt * fix benchmarks --- bin/millau/runtime/src/lib.rs | 1 + bin/runtime-common/src/messages_extension.rs | 16 +++ .../src/parachains_benchmarking.rs | 8 +- modules/grandpa/src/extension.rs | 7 ++ modules/grandpa/src/lib.rs | 2 +- modules/messages/src/lib.rs | 2 +- modules/parachains/src/benchmarking.rs | 16 +-- modules/parachains/src/extension.rs | 59 +++++++-- modules/parachains/src/lib.rs | 112 +++++++++++------- .../lib-substrate-relay/src/parachains/mod.rs | 6 +- .../src/parachains/source.rs | 47 ++++++-- .../src/parachains/target.rs | 4 +- relays/parachains/src/parachains_loop.rs | 37 ++++-- 13 files changed, 225 insertions(+), 92 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4041cfe171b30..4ee80e9e124d3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1035,6 +1035,7 @@ impl_runtime_apis! { pallet_bridge_parachains::RelayBlockNumber, pallet_bridge_parachains::RelayBlockHash, bp_polkadot_core::parachains::ParaHeadsProof, + Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, ) { bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::( parachains, diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index fd1d9d7a934b5..48b30fa646e2a 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -70,6 +70,14 @@ macro_rules! declare_bridge_reject_obsolete_messages { let inbound_lane_data = pallet_bridge_messages::InboundLanes::<$runtime, $instance>::get(&proof.lane); if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages delivery transaction: lane {:?}, bundled {:?}, best {:?}", + proof.lane, + proof.nonces_end, + inbound_lane_data.last_delivered_nonce(), + ); + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into(); } @@ -84,6 +92,14 @@ macro_rules! declare_bridge_reject_obsolete_messages { let outbound_lane_data = pallet_bridge_messages::OutboundLanes::<$runtime, $instance>::get(&proof.lane); if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages confirmation transaction: lane {:?}, bundled {:?}, best {:?}", + proof.lane, + latest_delivered_nonce, + outbound_lane_data.latest_received_nonce, + ); + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into(); } diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index f707f652d8c38..97a1cd3ee7d9f 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -21,7 +21,7 @@ use crate::messages_benchmarking::{grow_trie, insert_header_to_grandpa_pallet}; use bp_parachains::parachain_head_storage_key_at_source; -use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::StorageProofSize; use codec::Encode; use frame_support::traits::Get; @@ -37,7 +37,7 @@ pub fn prepare_parachain_heads_proof( parachains: &[ParaId], parachain_head_size: u32, size: StorageProofSize, -) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof) +) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof, Vec<(ParaId, ParaHash)>) where R: pallet_bridge_parachains::Config + pallet_bridge_grandpa::Config, @@ -48,6 +48,7 @@ where let parachain_head = ParaHead(vec![0u8; parachain_head_size as usize]); // insert all heads to the trie + let mut parachain_heads = Vec::with_capacity(parachains.len()); let mut storage_keys = Vec::with_capacity(parachains.len()); let mut state_root = Default::default(); let mut mdb = MemoryDB::default(); @@ -62,6 +63,7 @@ where .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); storage_keys.push(storage_key); + parachain_heads.push((*parachain, parachain_head.hash())) } } state_root = grow_trie(state_root, &mut mdb, size); @@ -76,5 +78,5 @@ where let (relay_block_number, relay_block_hash) = insert_header_to_grandpa_pallet::(state_root); - (relay_block_number, relay_block_hash, ParaHeadsProof(proof)) + (relay_block_number, relay_block_hash, ParaHeadsProof(proof), parachain_heads) } diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index bda7d49d7c436..007c5f3df7475 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -75,6 +75,13 @@ macro_rules! declare_bridge_reject_obsolete_grandpa_header { if best_finalized_number < bundled_block_number { Ok(sp_runtime::transaction_validity::ValidTransaction::default()) } else { + log::trace!( + target: $crate::LOG_TARGET, + "Rejecting obsolete bridged header: bundled {:?}, best {:?}", + bundled_block_number, + best_finalized_number, + ); + sp_runtime::transaction_validity::InvalidTransaction::Stale.into() } }, diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index c75ccc2e80a81..4074421fc52d5 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -60,7 +60,7 @@ pub use pallet::*; pub use weights::WeightInfo; /// The target that will be used when publishing logs related to this pallet. -const LOG_TARGET: &str = "runtime::bridge-grandpa"; +pub const LOG_TARGET: &str = "runtime::bridge-grandpa"; /// Block number of the bridged chain. pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index ca4b7044b2cfb..48ca546def8c1 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -91,7 +91,7 @@ mod mock; pub use pallet::*; /// The target that will be used when publishing logs related to this pallet. -const LOG_TARGET: &str = "runtime::bridge-messages"; +pub const LOG_TARGET: &str = "runtime::bridge-messages"; #[frame_support::pallet] pub mod pallet { diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index 749182a82ea69..aba296dfc1d5b 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -21,7 +21,7 @@ use crate::{ RelayBlockNumber, }; -use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::StorageProofSize; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_system::RawOrigin; @@ -37,7 +37,7 @@ pub trait Config: crate::Config { parachains: &[ParaId], parachain_head_size: u32, proof_size: StorageProofSize, - ) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof); + ) -> (RelayBlockNumber, RelayBlockHash, ParaHeadsProof, Vec<(ParaId, ParaHash)>); } benchmarks_instance_pallet! { @@ -57,13 +57,13 @@ benchmarks_instance_pallet! { let sender = account("sender", 0, 0); let parachains = (1..=p).map(ParaId).collect::>(); - let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, StorageProofSize::Minimal(0), ); let at_relay_block = (relay_block_number, relay_block_hash); - }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof) + }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof) verify { for parachain in parachains { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); @@ -74,13 +74,13 @@ benchmarks_instance_pallet! { submit_parachain_heads_with_1kb_proof { let sender = account("sender", 0, 0); let parachains = vec![ParaId(1)]; - let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, StorageProofSize::HasExtraNodes(1024), ); let at_relay_block = (relay_block_number, relay_block_hash); - }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof) + }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof) verify { for parachain in parachains { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); @@ -91,13 +91,13 @@ benchmarks_instance_pallet! { submit_parachain_heads_with_16kb_proof { let sender = account("sender", 0, 0); let parachains = vec![ParaId(1)]; - let (relay_block_number, relay_block_hash, parachain_heads_proof) = T::prepare_parachain_heads_proof( + let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, StorageProofSize::HasExtraNodes(16 * 1024), ); let at_relay_block = (relay_block_number, relay_block_hash); - }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains.clone(), parachain_heads_proof) + }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof) verify { for parachain in parachains { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs index 1d0eb7a7ff908..efcd9ec567ff8 100644 --- a/modules/parachains/src/extension.rs +++ b/modules/parachains/src/extension.rs @@ -72,15 +72,34 @@ macro_rules! declare_bridge_reject_obsolete_parachain_header { ref parachains, .. }) if parachains.len() == 1 => { - let parachain = parachains.get(0).expect("verified by match condition; qed"); + let (parachain, parachain_head_hash) = parachains.get(0).expect("verified by match condition; qed"); let bundled_relay_block_number = at_relay_block.0; let best_parachain_head = $crate::BestParaHeads::<$runtime, $instance>::get(parachain); + match best_parachain_head { Some(best_parachain_head) if best_parachain_head.at_relay_block_number - >= bundled_relay_block_number => - sp_runtime::transaction_validity::InvalidTransaction::Stale.into(), + >= bundled_relay_block_number => { + log::trace!( + target: $crate::LOG_TARGET, + "Rejecting obsolete parachain-head {:?} transaction: bundled relay block number: \ + {:?} best relay block number: {:?}", + parachain, + bundled_relay_block_number, + best_parachain_head.at_relay_block_number, + ); + sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + } + Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => { + log::trace!( + target: $crate::LOG_TARGET, + "Rejecting obsolete parachain-head {:?} transaction: head hash {:?}", + parachain, + best_parachain_head.head_hash, + ); + sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + } _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), } }, @@ -118,7 +137,7 @@ mod tests { mock::{run_test, Call, TestRuntime}, BestParaHead, BestParaHeads, RelayBlockNumber, }; - use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; + use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use sp_runtime::traits::SignedExtension; @@ -127,7 +146,10 @@ mod tests { Call::Parachains => () } - fn validate_submit_parachain_heads(num: RelayBlockNumber, parachains: Vec) -> bool { + fn validate_submit_parachain_heads( + num: RelayBlockNumber, + parachains: Vec<(ParaId, ParaHash)>, + ) -> bool { BridgeRejectObsoleteParachainHeader .validate( &42, @@ -147,29 +169,39 @@ mod tests { ParaId(1), BestParaHead { at_relay_block_number: 10, - head_hash: Default::default(), + head_hash: [1u8; 32].into(), next_imported_hash_position: 0, }, ); } #[test] - fn extension_rejects_obsolete_header() { + fn extension_rejects_header_from_the_obsolete_relay_block() { run_test(|| { // when current best finalized is #10 and we're trying to import header#5 => tx is // rejected sync_to_relay_header_10(); - assert!(!validate_submit_parachain_heads(5, vec![ParaId(1)])); + assert!(!validate_submit_parachain_heads(5, vec![(ParaId(1), [1u8; 32].into())])); + }); + } + + #[test] + fn extension_rejects_header_from_the_same_relay_block() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#10 => tx is + // rejected + sync_to_relay_header_10(); + assert!(!validate_submit_parachain_heads(10, vec![(ParaId(1), [1u8; 32].into())])); }); } #[test] - fn extension_rejects_same_header() { + fn extension_rejects_header_from_new_relay_block_with_same_hash() { run_test(|| { // when current best finalized is #10 and we're trying to import header#10 => tx is // rejected sync_to_relay_header_10(); - assert!(!validate_submit_parachain_heads(10, vec![ParaId(1)])); + assert!(!validate_submit_parachain_heads(20, vec![(ParaId(1), [1u8; 32].into())])); }); } @@ -179,7 +211,7 @@ mod tests { // when current best finalized is #10 and we're trying to import header#15 => tx is // accepted sync_to_relay_header_10(); - assert!(validate_submit_parachain_heads(15, vec![ParaId(1)])); + assert!(validate_submit_parachain_heads(15, vec![(ParaId(1), [2u8; 32].into())])); }); } @@ -189,7 +221,10 @@ mod tests { // when current best finalized is #10 and we're trying to import header#5, but another // parachain head is also supplied => tx is accepted sync_to_relay_header_10(); - assert!(validate_submit_parachain_heads(5, vec![ParaId(1), ParaId(2)])); + assert!(validate_submit_parachain_heads( + 5, + vec![(ParaId(1), [1u8; 32].into()), (ParaId(2), [1u8; 32].into())] + )); }); } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index ec2d16427e71a..05e14575eacf3 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -49,7 +49,7 @@ mod extension; mod mock; /// The target that will be used when publishing logs related to this pallet. -const LOG_TARGET: &str = "runtime::bridge-parachains"; +pub const LOG_TARGET: &str = "runtime::bridge-parachains"; /// Block hash of the bridged relay chain. pub type RelayBlockHash = bp_polkadot_core::Hash; @@ -209,7 +209,7 @@ pub mod pallet { pub fn submit_parachain_heads( _origin: OriginFor, at_relay_block: (RelayBlockNumber, RelayBlockHash), - parachains: Vec, + parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; @@ -235,7 +235,7 @@ pub mod pallet { relay_block_hash, sp_trie::StorageProof::new(parachain_heads_proof.0), move |storage| { - for parachain in parachains { + for (parachain, parachain_head_hash) in parachains { // if we're not tracking this parachain, we'll just ignore its head proof here if !T::TrackedParachains::contains(¶chain) { log::trace!( @@ -272,12 +272,27 @@ pub mod pallet { }, }; + // if relayer has specified invalid parachain head hash, ignore the head + // (this isn't strictly necessary, but better safe than sorry) + let actual_parachain_head_hash = parachain_head.hash(); + if parachain_head_hash != actual_parachain_head_hash { + log::trace!( + target: LOG_TARGET, + "The submitter has specified invalid parachain {:?} head hash: {:?} vs {:?}", + parachain, + parachain_head_hash, + actual_parachain_head_hash, + ); + continue; + } + let prune_happened: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { let artifacts = Pallet::::update_parachain_head( parachain, stored_best_head.take(), relay_block_number, parachain_head, + parachain_head_hash, )?; *stored_best_head = Some(artifacts.best_head); Ok(artifacts.prune_happened) @@ -364,10 +379,10 @@ pub mod pallet { stored_best_head: Option, updated_at_relay_block_number: RelayBlockNumber, updated_head: ParaHead, + updated_head_hash: ParaHash, ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order - let updated_head_hash = updated_head.hash(); let next_imported_hash_position = match stored_best_head { Some(stored_best_head) if stored_best_head.at_relay_block_number <= updated_at_relay_block_number => @@ -376,7 +391,7 @@ pub mod pallet { if updated_head_hash == stored_best_head.head_hash { log::trace!( target: LOG_TARGET, - "The head of parachain {:?} can't be updated to {}, because it has been already updated\ + "The head of parachain {:?} can't be updated to {}, because it has been already updated \ to the same value at previous relay chain block: {} < {}", parachain, updated_head_hash, @@ -392,7 +407,7 @@ pub mod pallet { Some(stored_best_head) => { log::trace!( target: LOG_TARGET, - "The head of parachain {:?} can't be updated to {}, because it has been already updated\ + "The head of parachain {:?} can't be updated to {}, because it has been already updated \ to {} at better relay chain block: {} > {}", parachain, updated_head_hash, @@ -530,7 +545,8 @@ mod tests { fn prepare_parachain_heads_proof( heads: Vec<(u32, ParaHead)>, - ) -> (RelayBlockHash, ParaHeadsProof) { + ) -> (RelayBlockHash, ParaHeadsProof, Vec<(ParaId, ParaHash)>) { + let mut parachains = Vec::with_capacity(heads.len()); let mut root = Default::default(); let mut mdb = MemoryDB::default(); { @@ -541,6 +557,7 @@ mod tests { trie.insert(&storage_key.0, &head.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in tests"); + parachains.push((ParaId(parachain), head.hash())); } } @@ -551,7 +568,7 @@ mod tests { .expect("record_all_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - (root, ParaHeadsProof(storage_proof)) + (root, ParaHeadsProof(storage_proof), parachains) } fn initial_best_head(parachain: u32) -> BestParaHead { @@ -573,12 +590,13 @@ mod tests { fn import_parachain_1_head( relay_chain_block: RelayBlockNumber, relay_state_root: RelayBlockHash, + parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { Pallet::::submit_parachain_heads( Origin::signed(1), (relay_chain_block, test_relay_header(relay_chain_block, relay_state_root).hash()), - vec![ParaId(1)], + parachains, proof, ) } @@ -595,7 +613,8 @@ mod tests { #[test] fn submit_parachain_heads_checks_operating_mode() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let (state_root, proof, parachains) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); run_test(|| { initialize(state_root); @@ -606,7 +625,7 @@ mod tests { Pallet::::submit_parachain_heads( Origin::signed(1), (0, test_relay_header(0, state_root).hash()), - vec![ParaId(1), ParaId(2), ParaId(3)], + parachains.clone(), proof.clone(), ), Error::::BridgeModule(OwnedBridgeModuleError::Halted) @@ -617,7 +636,7 @@ mod tests { assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), (0, test_relay_header(0, state_root).hash()), - vec![ParaId(1)], + parachains, proof, ),); }); @@ -625,7 +644,7 @@ mod tests { #[test] fn imports_initial_parachain_heads() { - let (state_root, proof) = + let (state_root, proof, parachains) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0)), (3, head_data(3, 10))]); run_test(|| { initialize(state_root); @@ -634,7 +653,7 @@ mod tests { assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), (0, test_relay_header(0, state_root).hash()), - vec![ParaId(1), ParaId(2), ParaId(3)], + parachains, proof, ),); @@ -667,12 +686,14 @@ mod tests { #[test] fn imports_parachain_heads_is_able_to_progress() { - let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); - let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); + let (state_root_5, proof_5, parachains_5) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10, proof_10, parachains_10) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 and import head#5 of parachain#1 initialize(state_root_5); - assert_ok!(import_parachain_1_head(0, state_root_5, proof_5)); + assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5)); assert_eq!( BestParaHeads::::get(ParaId(1)), Some(BestParaHead { @@ -692,7 +713,7 @@ mod tests { // import head#10 of parachain#1 at relay block #1 proceed(1, state_root_10); - assert_ok!(import_parachain_1_head(1, state_root_10, proof_10)); + assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( BestParaHeads::::get(ParaId(1)), Some(BestParaHead { @@ -714,7 +735,7 @@ mod tests { #[test] fn ignores_untracked_parachain() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![ + let (state_root, proof, parachains) = prepare_parachain_heads_proof(vec![ (1, head_data(1, 5)), (UNTRACKED_PARACHAIN_ID, head_data(1, 5)), (2, head_data(1, 5)), @@ -726,7 +747,7 @@ mod tests { assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), (0, test_relay_header(0, state_root).hash()), - vec![ParaId(1), ParaId(UNTRACKED_PARACHAIN_ID), ParaId(2)], + parachains, proof, )); assert_eq!( @@ -751,32 +772,35 @@ mod tests { #[test] fn does_nothing_when_already_imported_this_head_at_previous_relay_header() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let (state_root, proof, parachains) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); run_test(|| { // import head#0 of parachain#1 at relay block#0 initialize(state_root); - assert_ok!(import_parachain_1_head(0, state_root, proof.clone())); + assert_ok!(import_parachain_1_head(0, state_root, parachains.clone(), proof.clone())); assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); // try to import head#0 of parachain#1 at relay block#1 // => call succeeds, but nothing is changed proceed(1, state_root); - assert_ok!(import_parachain_1_head(1, state_root, proof)); + assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); }); } #[test] fn does_nothing_when_already_imported_head_at_better_relay_header() { - let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); - let (state_root_10, proof_10) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); + let (state_root_5, proof_5, parachains_5) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10, proof_10, parachains_10) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 initialize(state_root_5); // head#10 of parachain#1 at relay block#1 proceed(1, state_root_10); - assert_ok!(import_parachain_1_head(1, state_root_10, proof_10)); + assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( BestParaHeads::::get(ParaId(1)), Some(BestParaHead { @@ -786,9 +810,9 @@ mod tests { }) ); - // now try to import head#1 at relay block#0 + // now try to import head#5 at relay block#0 // => nothing is changed, because better head has already been imported - assert_ok!(import_parachain_1_head(0, state_root_5, proof_5)); + assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5)); assert_eq!( BestParaHeads::::get(ParaId(1)), Some(BestParaHead { @@ -807,7 +831,8 @@ mod tests { // import exactly `HeadsToKeep` headers for i in 0..heads_to_keep { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, i))]); + let (state_root, proof, parachains) = + prepare_parachain_heads_proof(vec![(1, head_data(1, i))]); if i == 0 { initialize(state_root); } else { @@ -815,7 +840,7 @@ mod tests { } let expected_weight = weight_of_import_parachain_1_head(&proof, false); - let result = import_parachain_1_head(i, state_root, proof); + let result = import_parachain_1_head(i, state_root, parachains, proof); assert_ok!(result); assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); } @@ -827,11 +852,11 @@ mod tests { } // import next relay chain header and next parachain head - let (state_root, proof) = + let (state_root, proof, parachains) = prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]); proceed(heads_to_keep, state_root); let expected_weight = weight_of_import_parachain_1_head(&proof, true); - let result = import_parachain_1_head(heads_to_keep, state_root, proof); + let result = import_parachain_1_head(heads_to_keep, state_root, parachains, proof); assert_ok!(result); assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); @@ -848,14 +873,15 @@ mod tests { #[test] fn fails_on_unknown_relay_chain_block() { - let (state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root, proof, parachains) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(state_root); // try to import head#5 of parachain#1 at unknown relay chain block #1 assert_noop!( - import_parachain_1_head(1, state_root, proof), + import_parachain_1_head(1, state_root, parachains, proof), Error::::UnknownRelayChainBlock ); }); @@ -863,14 +889,15 @@ mod tests { #[test] fn fails_on_invalid_storage_proof() { - let (_state_root, proof) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (_state_root, proof, parachains) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(Default::default()); // try to import head#5 of parachain#1 at relay chain block #0 assert_noop!( - import_parachain_1_head(0, Default::default(), proof), + import_parachain_1_head(0, Default::default(), parachains, proof), Error::::InvalidStorageProof ); }); @@ -878,15 +905,16 @@ mod tests { #[test] fn is_not_rewriting_existing_head_if_failed_to_read_updated_head() { - let (state_root_5, proof_5) = prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); - let (state_root_10_at_20, proof_10_at_20) = + let (state_root_5, proof_5, parachains_5) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + let (state_root_10_at_20, proof_10_at_20, parachains_10_at_20) = prepare_parachain_heads_proof(vec![(2, head_data(2, 10))]); - let (state_root_10_at_30, proof_10_at_30) = + let (state_root_10_at_30, proof_10_at_30, parachains_10_at_30) = prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); run_test(|| { // we've already imported head#5 of parachain#1 at relay block#10 initialize(state_root_5); - import_parachain_1_head(0, state_root_5, proof_5).expect("ok"); + import_parachain_1_head(0, state_root_5, parachains_5, proof_5).expect("ok"); assert_eq!( Pallet::::best_parachain_head(ParaId(1)), Some(head_data(1, 5)) @@ -900,7 +928,7 @@ mod tests { assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), (20, test_relay_header(20, state_root_10_at_20).hash()), - vec![ParaId(1)], + parachains_10_at_20, proof_10_at_20, ),); assert_eq!( @@ -916,7 +944,7 @@ mod tests { assert_ok!(Pallet::::submit_parachain_heads( Origin::signed(1), (30, test_relay_header(30, state_root_10_at_30).hash()), - vec![ParaId(1)], + parachains_10_at_30, proof_10_at_30, ),); assert_eq!( diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/relays/lib-substrate-relay/src/parachains/mod.rs index 51549ef02bd52..f201476aa1635 100644 --- a/relays/lib-substrate-relay/src/parachains/mod.rs +++ b/relays/lib-substrate-relay/src/parachains/mod.rs @@ -18,7 +18,7 @@ //! parachain finality proofs synchronization pipelines. use async_trait::async_trait; -use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use pallet_bridge_parachains::{ Call as BridgeParachainsCall, Config as BridgeParachainsConfig, RelayBlockHash, RelayBlockHasher, RelayBlockNumber, @@ -71,7 +71,7 @@ pub trait SubmitParachainHeadsCallBuilder: /// function of bridge parachains module at the target chain. fn build_submit_parachain_heads_call( at_relay_block: HeaderIdOf, - parachains: Vec, + parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf; } @@ -97,7 +97,7 @@ where { fn build_submit_parachain_heads_call( at_relay_block: HeaderIdOf, - parachains: Vec, + parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { BridgeParachainsCall::::submit_parachain_heads { diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index c613387e7a258..ecc940467035e 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -160,23 +160,46 @@ where &self, at_block: HeaderIdOf, parachains: &[ParaId], - ) -> Result { - let storage_keys = parachains - .iter() - .map(|para_id| { - parachain_head_storage_key_at_source( - P::SourceRelayChain::PARAS_PALLET_NAME, - *para_id, - ) - }) - .collect(); + ) -> Result<(ParaHeadsProof, Vec), Self::Error> { + if parachains.len() != 1 || parachains[0].0 != P::SOURCE_PARACHAIN_PARA_ID { + return Err(SubstrateError::Custom(format!( + "Trying to prove unexpected parachains {:?}. Expected {:?}", + parachains, + P::SOURCE_PARACHAIN_PARA_ID, + ))) + } + + let parachain = parachains[0]; + let storage_key = + parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, parachain); let parachain_heads_proof = self .client - .prove_storage(storage_keys, at_block.1) + .prove_storage(vec![storage_key.clone()], at_block.1) .await? .iter_nodes() .collect(); - Ok(ParaHeadsProof(parachain_heads_proof)) + // why we're reading parachain head here once again (it has already been read at the + // `parachain_head`)? that's because `parachain_head` sometimes returns obsolete parachain + // head and loop sometimes asks to prove this obsolete head and gets other (actual) head + // instead + // + // => since we want to provide proper hashes in our `submit_parachain_heads` call, we're + // rereading actual value here + let parachain_head = self + .client + .raw_storage_value(storage_key, Some(at_block.1)) + .await? + .map(|h| ParaHead::decode(&mut &h.0[..])) + .transpose()? + .ok_or_else(|| { + SubstrateError::Custom(format!( + "Failed to read expected parachain {:?} head at {:?}", + parachain, at_block + )) + })?; + let parachain_head_hash = parachain_head.hash(); + + Ok((ParaHeadsProof(parachain_heads_proof), vec![parachain_head_hash])) } } diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index ca30629198b5b..d26894b9bd302 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -28,7 +28,7 @@ use bp_parachains::{ best_parachain_head_hash_storage_key_at_target, imported_parachain_head_storage_key_at_target, BestParaHeadHash, }; -use bp_polkadot_core::parachains::{ParaHead, ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use codec::{Decode, Encode}; use parachains_relay::{ parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics, @@ -166,7 +166,7 @@ where async fn submit_parachain_heads_proof( &self, at_relay_block: HeaderIdOf, - updated_parachains: Vec, + updated_parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, ) -> Result<(), Self::Error> { let genesis_hash = *self.client.genesis_hash(); diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 60627d23e0b15..795d07b8440ec 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -69,6 +69,16 @@ pub enum ParaHashAtSource { Unavailable, } +impl ParaHashAtSource { + /// Return parachain head hash, if available. + pub fn hash(&self) -> Option<&ParaHash> { + match *self { + ParaHashAtSource::Some(ref para_hash) => Some(para_hash), + _ => None, + } + } +} + /// Source client used in parachain heads synchronization loop. #[async_trait] pub trait SourceClient: RelayClient { @@ -87,11 +97,15 @@ pub trait SourceClient: RelayClient { ) -> Result; /// Get parachain heads proof. + /// + /// The number and order of entries in the resulting parachain head hashes vector must match the + /// number and order of parachains in the `parachains` vector. The incorrect implementation will + /// result in panic. async fn prove_parachain_heads( &self, at_block: HeaderIdOf, parachains: &[ParaId], - ) -> Result; + ) -> Result<(ParaHeadsProof, Vec), Self::Error>; } /// Target client used in parachain heads synchronization loop. @@ -121,7 +135,7 @@ pub trait TargetClient: RelayClient { async fn submit_parachain_heads_proof( &self, at_source_block: HeaderIdOf, - updated_parachains: Vec, + updated_parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, ) -> Result<(), Self::Error>; } @@ -274,7 +288,7 @@ where ); if is_update_required { - let heads_proofs = source_client + let (heads_proofs, head_hashes) = source_client .prove_parachain_heads(best_finalized_relay_block, &updated_ids) .await .map_err(|e| { @@ -292,10 +306,17 @@ where P::SourceChain::NAME, P::TargetChain::NAME, ); + + assert_eq!( + head_hashes.len(), + updated_ids.len(), + "Incorrect parachains SourceClient implementation" + ); + target_client .submit_parachain_heads_proof( best_finalized_relay_block, - updated_ids.clone(), + updated_ids.iter().cloned().zip(head_hashes).collect(), heads_proofs, ) .await @@ -394,7 +415,7 @@ where needs_update }) - .map(|((para_id, _), _)| para_id) + .map(|((para, _), _)| para) .collect() } @@ -666,7 +687,7 @@ mod tests { &self, _at_block: HeaderIdOf, parachains: &[ParaId], - ) -> Result { + ) -> Result<(ParaHeadsProof, Vec), TestError> { let mut proofs = Vec::new(); for para_id in parachains { proofs.push( @@ -680,7 +701,7 @@ mod tests { .ok_or(TestError::MissingParachainHeadProof)?, ); } - Ok(ParaHeadsProof(proofs)) + Ok((ParaHeadsProof(proofs), vec![Default::default(); parachains.len()])) } } @@ -709,7 +730,7 @@ mod tests { async fn submit_parachain_heads_proof( &self, _at_source_block: HeaderIdOf, - _updated_parachains: Vec, + _updated_parachains: Vec<(ParaId, ParaHash)>, _proof: ParaHeadsProof, ) -> Result<(), Self::Error> { self.data.lock().await.target_submit_result.clone()?; From 3d94069bf00ba613b897e18c1299e99118f7df34 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 14 Jul 2022 15:19:11 +0300 Subject: [PATCH 0736/1210] More relay processes in rialtoParachain<>Millau bridge (#1500) * more relay processes in rialtoParachain<>Millau bridge * fix dashboards * fix dump-logs --- bin/millau/node/src/chain_spec.rs | 6 ++++-- bin/rialto-parachain/node/src/chain_spec.rs | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 3e812ca9aab28..66ab997aa7431 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -173,8 +173,10 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Rialto.MessagesSender"), // Accounts, used by RialtoParachain<>Millau bridge get_account_id_from_seed::(RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER), - get_account_id_from_seed::("RialtoParachain.HeadersAndMessagesRelay"), - get_account_id_from_seed::("RialtoParachain.RialtoHeadersRelay"), + get_account_id_from_seed::("RialtoParachain.HeadersAndMessagesRelay1"), + get_account_id_from_seed::("RialtoParachain.HeadersAndMessagesRelay2"), + get_account_id_from_seed::("RialtoParachain.RialtoHeadersRelay1"), + get_account_id_from_seed::("RialtoParachain.RialtoHeadersRelay2"), get_account_id_from_seed::("RialtoParachain.MessagesSender"), ] .into_iter() diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 6873730c1969a..4a7865b18542e 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -98,7 +98,8 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::("Ferdie//stash"), // Accounts, used by RialtoParachain<>Millau bridge get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER), - get_account_id_from_seed::("Millau.HeadersAndMessagesRelay"), + get_account_id_from_seed::("Millau.HeadersAndMessagesRelay1"), + get_account_id_from_seed::("Millau.HeadersAndMessagesRelay2"), get_account_id_from_seed::("Millau.MessagesSender"), ] .into_iter() From 912442a1c7bfe3f3718726809372b31e2318d159 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 14 Jul 2022 17:49:18 +0300 Subject: [PATCH 0737/1210] Define HeaderIdProvider trait Define HeaderIdProvider trait Signed-off-by: Serban Iorga --- primitives/runtime/src/chain.rs | 2 ++ primitives/runtime/src/lib.rs | 24 ++++++++++++++++++- .../src/cli/resubmit_transactions.rs | 5 ++-- relays/client-substrate/src/client.rs | 20 +++++++--------- .../src/messages_source.rs | 9 ++++--- .../src/on_demand/parachains.rs | 9 ++++--- .../src/parachains/target.rs | 4 ++-- 7 files changed, 47 insertions(+), 26 deletions(-) diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 4f88e701fb1ba..14035566e6742 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::HeaderIdProvider; use codec::{Decode, Encode}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; @@ -143,6 +144,7 @@ pub trait Chain: Send + Sync + 'static { // https://crates.parity.io/sp_runtime/traits/trait.Header.html type Header: Parameter + HeaderT + + HeaderIdProvider + MaybeSerializeDeserialize; /// The user account identifier type for the runtime. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index ca8a22ee16a60..982b8f9a0eb84 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -26,7 +26,7 @@ use frame_system::RawOrigin; use scale_info::TypeInfo; use sp_core::{hash::H256, storage::StorageKey}; use sp_io::hashing::blake2_256; -use sp_runtime::traits::BadOrigin; +use sp_runtime::traits::{BadOrigin, Header as HeaderT}; use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; pub use chain::{ @@ -34,6 +34,7 @@ pub use chain::{ HasherOf, HeaderOf, IndexOf, SignatureOf, TransactionEraOf, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; +use num_traits::{CheckedSub, One}; pub use storage_proof::{ Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker, }; @@ -83,6 +84,27 @@ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-deriva #[derive(RuntimeDebug, Default, Clone, Copy, Eq, Hash, PartialEq)] pub struct HeaderId(pub Number, pub Hash); +/// Generic header id provider. +pub trait HeaderIdProvider { + // Get the header id. + fn id(&self) -> HeaderId; + + // Get the header id for the parent block. + fn parent_id(&self) -> Option>; +} + +impl HeaderIdProvider

for Header { + fn id(&self) -> HeaderId { + HeaderId(*self.number(), self.hash()) + } + + fn parent_id(&self) -> Option> { + self.number() + .checked_sub(&One::one()) + .map(|parent_number| HeaderId(parent_number, *self.parent_hash())) + } +} + /// Unique identifier of the chain. /// /// In addition to its main function (identifying the chain), this type may also be used to diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index a4cec796552e1..dad1afbf146d1 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -16,13 +16,14 @@ use crate::cli::{chain_schema::*, Balance}; +use bp_runtime::HeaderIdProvider; use codec::{Decode, Encode}; use num_traits::{One, Zero}; use relay_substrate_client::{ BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, SignParam, TransactionSignScheme, }; -use relay_utils::{FailedClient, HeaderId}; +use relay_utils::FailedClient; use sp_core::Bytes; use sp_runtime::{ traits::{Hash, Header as HeaderT}, @@ -274,7 +275,7 @@ async fn run_loop_iteration>( let (is_updated, updated_transaction) = update_transaction_tip::( &client, &transaction_params, - HeaderId(*context.best_header.number(), context.best_header.hash()), + context.best_header.id(), original_transaction, context.tip_step, context.tip_limit, diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 5619645d0a485..e5309bb54eab8 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -25,6 +25,7 @@ use crate::{ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; +use bp_runtime::HeaderIdProvider; use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; @@ -33,10 +34,10 @@ use jsonrpsee::{ types::params::ParamsSer, ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; -use num_traits::{Bounded, CheckedSub, One, Zero}; +use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; -use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId}; +use relay_utils::relay_loop::RECONNECT_DELAY; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, Hasher, @@ -484,14 +485,11 @@ impl Client { let best_header = self.best_header().await?; // By using parent of best block here, we are protecing again best-block reorganizations. - // E.g. transaction my have been submitted when the best block was `A[num=100]`. Then it has - // been changed to `B[num=100]`. Hash of `A` has been included into transaction signature - // payload. So when signature will be checked, the check will fail and transaction will be - // dropped from the pool. - let best_header_id = match best_header.number().checked_sub(&One::one()) { - Some(parent_block_number) => HeaderId(parent_block_number, *best_header.parent_hash()), - None => HeaderId(*best_header.number(), best_header.hash()), - }; + // E.g. transaction may have been submitted when the best block was `A[num=100]`. Then it + // has been changed to `B[num=100]`. Hash of `A` has been included into transaction + // signature payload. So when signature will be checked, the check will fail and transaction + // will be dropped from the pool. + let best_header_id = best_header.parent_id().unwrap_or_else(|| best_header.id()); self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; @@ -524,7 +522,7 @@ impl Client { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; let best_header = self.best_header().await?; - let best_header_id = HeaderId(*best_header.number(), best_header.hash()); + let best_header_id = best_header.id(); let subscription = self .jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 8ed8367d35d7c..2daa41fc28405 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -34,7 +34,7 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageData, MessageNonce, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, }; -use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode}; +use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode, HeaderIdProvider}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -510,13 +510,12 @@ where let self_best_finalized_header_hash = self_client.best_finalized_header_hash().await?; let self_best_finalized_header = self_client.header_by_hash(self_best_finalized_header_hash).await?; - let self_best_finalized_id = - HeaderId(*self_best_finalized_header.number(), self_best_finalized_header_hash); + let self_best_finalized_id = self_best_finalized_header.id(); // now let's read our best header on **this** chain let self_best_header = self_client.best_header().await?; let self_best_hash = self_best_header.hash(); - let self_best_id = HeaderId(*self_best_header.number(), self_best_hash); + let self_best_id = self_best_header.id(); // now let's read id of best finalized peer header at our best finalized block let peer_on_self_best_finalized_id = @@ -532,7 +531,7 @@ where Some(peer_client) => { let actual_peer_on_self_best_finalized = peer_client.header_by_number(peer_on_self_best_finalized_id.0).await?; - HeaderId(peer_on_self_best_finalized_id.0, actual_peer_on_self_best_finalized.hash()) + actual_peer_on_self_best_finalized.id() }, None => peer_on_self_best_finalized_id, }; diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index f25d3b76948c9..77d80bc79b3be 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -32,6 +32,7 @@ use async_std::{ }; use async_trait::async_trait; use bp_polkadot_core::parachains::ParaHash; +use bp_runtime::HeaderIdProvider; use futures::{select, FutureExt}; use num_traits::Zero; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; @@ -43,7 +44,6 @@ use relay_substrate_client::{ use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, HeaderId, }; -use sp_runtime::traits::Header as HeaderT; use std::fmt::Debug; /// On-demand Substrate <-> Substrate parachain finality relay. @@ -387,8 +387,7 @@ where let best_finalized_relay_header = source.client().best_finalized_header().await.map_err(map_source_err)?; - let best_finalized_relay_block_id = - HeaderId(*best_finalized_relay_header.number(), best_finalized_relay_header.hash()); + let best_finalized_relay_block_id = best_finalized_relay_header.id(); let para_header_at_source = source .on_chain_parachain_header( best_finalized_relay_block_id, @@ -396,7 +395,7 @@ where ) .await .map_err(map_source_err)? - .map(|h| HeaderId(*h.number(), h.hash())); + .map(|h| h.id()); let relay_header_at_source = best_finalized_relay_block_id.0; let relay_header_at_target = @@ -412,7 +411,7 @@ where .on_chain_parachain_header(relay_header_at_target, P::SOURCE_PARACHAIN_PARA_ID.into()) .await .map_err(map_source_err)? - .map(|h| HeaderId(*h.number(), h.hash())); + .map(|h| h.id()); Ok(RelayData { required_para_header: required_header_number, diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index d26894b9bd302..43168f2c85248 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -29,6 +29,7 @@ use bp_parachains::{ BestParaHeadHash, }; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use bp_runtime::HeaderIdProvider; use codec::{Decode, Encode}; use parachains_relay::{ parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics, @@ -90,8 +91,7 @@ where { async fn best_block(&self) -> Result, Self::Error> { let best_header = self.client.best_header().await?; - let best_hash = best_header.hash(); - let best_id = HeaderId(*best_header.number(), best_hash); + let best_id = best_header.id(); Ok(best_id) } From bb4233edb611dbedee9eaac4f7c79b6fa8672bbc Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 18 Jul 2022 13:19:06 +0300 Subject: [PATCH 0738/1210] Follow-up on #1487 (#1511) * Remove unused trait implementations Signed-off-by: Serban Iorga * Define encoded_size_hint_u32() Signed-off-by: Serban Iorga * Define TransactionEstimationParams trait Signed-off-by: Serban Iorga * Rework TransactionEstimation Signed-off-by: Serban Iorga * Docs + Renamings Signed-off-by: Serban Iorga --- bin/millau/runtime/src/rialto_messages.rs | 29 +++---- .../runtime/src/rialto_parachain_messages.rs | 23 +++--- .../runtime/src/millau_messages.rs | 25 +++--- bin/rialto/runtime/src/millau_messages.rs | 29 +++---- bin/runtime-common/src/messages.rs | 77 +++++++++++++++---- modules/messages/src/inbound_lane.rs | 8 -- modules/messages/src/outbound_lane.rs | 8 -- primitives/messages/src/lib.rs | 13 ++++ .../src/messages_source.rs | 4 +- 9 files changed, 115 insertions(+), 101 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 5d192bd56ad26..da44bcf8f8feb 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -24,7 +24,9 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; +use bridge_runtime_common::messages::{ + self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, +}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -123,6 +125,12 @@ impl messages::ChainWithMessages for Millau { impl messages::ThisChainWithMessages for Millau { type Origin = crate::Origin; type Call = crate::Call; + type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< + Self::AccountId, + { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_rialto::EXTRA_STORAGE_PROOF_SIZE }, + { bp_millau::TX_EXTRA_BYTES }, + >; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { let here_location = @@ -148,19 +156,6 @@ impl messages::ThisChainWithMessages for Millau { MessageNonce::MAX } - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint(1, 1) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); - - MessageTransaction { - dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - size: inbound_data_size - .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_millau::TX_EXTRA_BYTES), - } - } - fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { // `transaction` may represent transaction from the future, when multiplier value will // be larger, so let's use slightly increased value @@ -346,12 +341,10 @@ mod tests { ); let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_messages::InboundLaneData::<()>::encoded_size_hint_u32( bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, - ) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); + ); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_millau::Millau::max_extrinsic_size(), bp_millau::Millau::max_extrinsic_weight(), diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index ceabe2b00018d..ef1dac57d8385 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -25,7 +25,9 @@ use bp_messages::{ }; use bp_polkadot_core::parachains::ParaId; use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; +use bridge_runtime_common::messages::{ + self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, +}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -128,6 +130,12 @@ impl messages::ChainWithMessages for Millau { impl messages::ThisChainWithMessages for Millau { type Call = crate::Call; type Origin = crate::Origin; + type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< + Self::AccountId, + { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE }, + { bp_millau::TX_EXTRA_BYTES }, + >; fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] @@ -137,19 +145,6 @@ impl messages::ThisChainWithMessages for Millau { MessageNonce::MAX } - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint(1, 1) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); - - MessageTransaction { - dispatch_weight: bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - size: inbound_data_size - .saturating_add(bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_millau::TX_EXTRA_BYTES), - } - } - fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { // `transaction` may represent transaction from the future, when multiplier value will // be larger, so let's use slightly increased value diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index ef8e3c657ac69..248ec7b834d41 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -27,7 +27,9 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; +use bridge_runtime_common::messages::{ + self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, +}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -127,6 +129,12 @@ impl messages::ChainWithMessages for RialtoParachain { impl messages::ThisChainWithMessages for RialtoParachain { type Call = crate::Call; type Origin = crate::Origin; + type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< + Self::AccountId, + { bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, + { bp_rialto_parachain::TX_EXTRA_BYTES }, + >; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) @@ -136,21 +144,6 @@ impl messages::ThisChainWithMessages for RialtoParachain { MessageNonce::MAX } - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = - InboundLaneData::::encoded_size_hint(1, 1) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); - - MessageTransaction { - dispatch_weight: - bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - size: inbound_data_size - .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_rialto_parachain::TX_EXTRA_BYTES), - } - } - fn transaction_payment( transaction: MessageTransaction, ) -> bp_rialto_parachain::Balance { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index e5e95e3d4a351..1267cbd06e29f 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -24,7 +24,9 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge, MessageTransaction}; +use bridge_runtime_common::messages::{ + self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, +}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -122,6 +124,12 @@ impl messages::ChainWithMessages for Rialto { impl messages::ThisChainWithMessages for Rialto { type Origin = crate::Origin; type Call = crate::Call; + type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< + Self::AccountId, + { bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, + { bp_rialto::TX_EXTRA_BYTES }, + >; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { let here_location = @@ -147,19 +155,6 @@ impl messages::ThisChainWithMessages for Rialto { MessageNonce::MAX } - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint(1, 1) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); - - MessageTransaction { - dispatch_weight: bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - size: inbound_data_size - .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_rialto::TX_EXTRA_BYTES), - } - } - fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { // `transaction` may represent transaction from the future, when multiplier value will // be larger, so let's use slightly increased value @@ -343,12 +338,10 @@ mod tests { ); let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint( + bp_messages::InboundLaneData::<()>::encoded_size_hint_u32( bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, - ) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); + ); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_rialto::Rialto::max_extrinsic_size(), bp_rialto::Rialto::max_extrinsic_weight(), diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 173a501032f6e..8153e0840cf5c 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -27,7 +27,7 @@ use bp_messages::{ }; use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaId}; use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker}; -use codec::{Decode, DecodeLimit, Encode}; +use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; @@ -69,7 +69,7 @@ pub trait ChainWithMessages { /// Hash used in the chain. type Hash: Decode; /// Accound id on the chain. - type AccountId: Encode + Decode; + type AccountId: Encode + Decode + MaxEncodedLen; /// Public key of the chain account that may be used to verify signatures. type Signer: Encode + Decode; /// Signature type used on the chain. @@ -99,12 +99,54 @@ pub struct MessageTransaction { pub size: u32, } +/// Helper trait for estimating the size and weight of a single message delivery confirmation +/// transaction. +pub trait ConfirmationTransactionEstimation { + // Estimate size and weight of single message delivery confirmation transaction. + fn estimate_delivery_confirmation_transaction() -> MessageTransaction; +} + +/// Default implementation for `ConfirmationTransactionEstimation`. +pub struct BasicConfirmationTransactionEstimation< + AccountId: MaxEncodedLen, + const MAX_CONFIRMATION_TX_WEIGHT: Weight, + const EXTRA_STORAGE_PROOF_SIZE: u32, + const TX_EXTRA_BYTES: u32, +>(PhantomData); + +impl< + AccountId: MaxEncodedLen, + const MAX_CONFIRMATION_TX_WEIGHT: Weight, + const EXTRA_STORAGE_PROOF_SIZE: u32, + const TX_EXTRA_BYTES: u32, + > ConfirmationTransactionEstimation + for BasicConfirmationTransactionEstimation< + AccountId, + MAX_CONFIRMATION_TX_WEIGHT, + EXTRA_STORAGE_PROOF_SIZE, + TX_EXTRA_BYTES, + > +{ + fn estimate_delivery_confirmation_transaction() -> MessageTransaction { + let inbound_data_size = InboundLaneData::::encoded_size_hint_u32(1, 1); + MessageTransaction { + dispatch_weight: MAX_CONFIRMATION_TX_WEIGHT, + size: inbound_data_size + .saturating_add(EXTRA_STORAGE_PROOF_SIZE) + .saturating_add(TX_EXTRA_BYTES), + } + } +} + /// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { /// Call origin on the chain. type Origin; /// Call type on the chain. type Call: Encode + Decode; + /// Helper for estimating the size and weight of a single message delivery confirmation + /// transaction at this chain. + type ConfirmationTransactionEstimation: ConfirmationTransactionEstimation>; /// Do we accept message sent by given origin to given lane? fn is_message_accepted(origin: &Self::Origin, lane: &LaneId) -> bool; @@ -115,7 +157,9 @@ pub trait ThisChainWithMessages: ChainWithMessages { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; /// Estimate size and weight of single message delivery confirmation transaction at This chain. - fn estimate_delivery_confirmation_transaction() -> MessageTransaction>; + fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { + Self::ConfirmationTransactionEstimation::estimate_delivery_confirmation_transaction() + } /// Returns minimal transaction fee that must be paid for given transaction at This chain. fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; @@ -1037,7 +1081,7 @@ mod tests { } } - #[derive(Debug, PartialEq, Eq, Decode, Encode, Clone)] + #[derive(Debug, PartialEq, Eq, Decode, Encode, Clone, MaxEncodedLen)] struct ThisChainAccountId(u32); #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct ThisChainSigner(u32); @@ -1063,7 +1107,7 @@ mod tests { } } - #[derive(Debug, PartialEq, Eq, Decode, Encode)] + #[derive(Debug, PartialEq, Eq, Decode, Encode, MaxEncodedLen)] struct BridgedChainAccountId(u32); #[derive(Debug, PartialEq, Eq, Decode, Encode)] struct BridgedChainSigner(u32); @@ -1162,6 +1206,12 @@ mod tests { impl ThisChainWithMessages for ThisChain { type Origin = ThisChainOrigin; type Call = ThisChainCall; + type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< + ::AccountId, + { DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT }, + 0, + 0, + >; fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { lane == TEST_LANE_ID @@ -1171,13 +1221,6 @@ mod tests { MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE } - fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { - MessageTransaction { - dispatch_weight: DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT, - size: 0, - } - } - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { ThisChainBalance( transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, @@ -1223,6 +1266,12 @@ mod tests { impl ThisChainWithMessages for BridgedChain { type Origin = BridgedChainOrigin; type Call = BridgedChainCall; + type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< + ::AccountId, + 0, + 0, + 0, + >; fn is_message_accepted(_send_origin: &Self::Origin, _lane: &LaneId) -> bool { unreachable!() @@ -1232,10 +1281,6 @@ mod tests { unreachable!() } - fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { - unreachable!() - } - fn transaction_payment( _transaction: MessageTransaction>, ) -> BalanceOf { diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 6624655ddc18e..cae76927045bc 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -79,14 +79,6 @@ impl, I: 'static> Default for StoredInboundLaneData { } } -impl, I: 'static> From> - for StoredInboundLaneData -{ - fn from(data: InboundLaneData) -> Self { - StoredInboundLaneData(data) - } -} - impl, I: 'static> From> for InboundLaneData { diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 5f977b2f2e297..bdd503c811e73 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -72,14 +72,6 @@ impl, I: 'static> sp_std::ops::DerefMut for StoredMessageData } } -impl, I: 'static> From> - for StoredMessageData -{ - fn from(data: MessageData) -> Self { - StoredMessageData(data) - } -} - impl, I: 'static> From> for MessageData { diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index ad1dbd38be901..d5b2b9c9db4f2 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -174,6 +174,19 @@ impl InboundLaneData { .and_then(|result| result.checked_add(dispatch_result_size)) } + /// Returns the approximate size of the struct as u32, given a number of entries in the + /// `relayers` set and the size of each entry. + /// + /// Returns `u32::MAX` if size overflows `u32` limits. + pub fn encoded_size_hint_u32(relayers_entries: usize, messages_count: usize) -> u32 + where + RelayerId: MaxEncodedLen, + { + Self::encoded_size_hint(relayers_entries, messages_count) + .and_then(|x| u32::try_from(x).ok()) + .unwrap_or(u32::MAX) + } + /// Nonce of the last message that has been delivered to this (target) chain. pub fn last_delivered_nonce(&self) -> MessageNonce { self.relayers diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 2daa41fc28405..6647376d93516 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -468,9 +468,7 @@ where fn prepare_dummy_messages_delivery_proof( ) -> SubstrateMessagesDeliveryProof { let single_message_confirmation_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint(1, 1) - .and_then(|x| u32::try_from(x).ok()) - .unwrap_or(u32::MAX); + bp_messages::InboundLaneData::<()>::encoded_size_hint_u32(1, 1); let proof_size = TC::STORAGE_PROOF_OVERHEAD.saturating_add(single_message_confirmation_size); ( UnrewardedRelayersState { From 9502df1a626388161a96b2bbc2359c9b206d1d27 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 20 Jul 2022 13:10:59 +0300 Subject: [PATCH 0739/1210] Introduce bridge relayers pallet (#1513) * introduce relayers pallet * add MessageDeliveryAndDispatchPaymentAdapter * plug in pallet into test runtimes * tests prototype * tests for the relayers pallet * tests for payment adapter * mint_reward_payment_procedure_actually_mints_tokens * benchmarks * remove irrelevant todo * remove redundant clone --- bin/millau/runtime/Cargo.toml | 5 + bin/millau/runtime/src/lib.rs | 24 +++- bin/rialto-parachain/runtime/Cargo.toml | 4 + bin/rialto-parachain/runtime/src/lib.rs | 15 +- bin/rialto/runtime/Cargo.toml | 4 + bin/rialto/runtime/src/lib.rs | 15 +- modules/grandpa/src/weights.rs | 1 + modules/messages/src/weights.rs | 79 ++++++----- modules/parachains/src/weights.rs | 1 + modules/relayers/Cargo.toml | 55 ++++++++ modules/relayers/src/benchmarking.rs | 40 ++++++ modules/relayers/src/lib.rs | 170 ++++++++++++++++++++++ modules/relayers/src/mock.rs | 156 ++++++++++++++++++++ modules/relayers/src/payment_adapter.rs | 180 ++++++++++++++++++++++++ modules/relayers/src/weights.rs | 73 ++++++++++ primitives/relayers/Cargo.toml | 38 +++++ primitives/relayers/src/lib.rs | 45 ++++++ 17 files changed, 862 insertions(+), 43 deletions(-) create mode 100644 modules/relayers/Cargo.toml create mode 100644 modules/relayers/src/benchmarking.rs create mode 100644 modules/relayers/src/lib.rs create mode 100644 modules/relayers/src/mock.rs create mode 100644 modules/relayers/src/payment_adapter.rs create mode 100644 modules/relayers/src/weights.rs create mode 100644 primitives/relayers/Cargo.toml create mode 100644 primitives/relayers/src/lib.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 80858b2e31eb5..33bdcca35cf76 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -20,6 +20,7 @@ bp-header-chain = { path = "../../../primitives/header-chain", default-features bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } @@ -28,6 +29,7 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false } +pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies @@ -89,6 +91,7 @@ std = [ "bp-messages/std", "bp-millau/std", "bp-polkadot-core/std", + "bp-relayers/std", "bp-rialto/std", "bp-rialto-parachain/std", "bp-runtime/std", @@ -107,6 +110,7 @@ std = [ "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", "pallet-grandpa/std", "pallet-mmr/std", "pallet-randomness-collective-flip/std", @@ -145,6 +149,7 @@ runtime-benchmarks = [ "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4ee80e9e124d3..36ce83049d1c5 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -388,6 +388,13 @@ parameter_types! { pub const MaxRequests: u32 = 50; } +impl pallet_bridge_relayers::Config for Runtime { + type Event = Event; + type Reward = Balance; + type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type WeightInfo = (); +} + #[cfg(feature = "runtime-benchmarks")] parameter_types! { /// Number of headers to keep in benchmarks. @@ -463,7 +470,12 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type MessageDeliveryAndDispatchPayment = (); + type MessageDeliveryAndDispatchPayment = + pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + Runtime, + WithRialtoMessagesInstance, + GetDeliveryConfirmationTransactionFee, + >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -494,7 +506,12 @@ impl pallet_bridge_messages::Config for Run type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; - type MessageDeliveryAndDispatchPayment = (); + type MessageDeliveryAndDispatchPayment = + pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + Runtime, + WithRialtoParachainMessagesInstance, + GetDeliveryConfirmationTransactionFee, + >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -558,6 +575,7 @@ construct_runtime!( MmrLeaf: pallet_beefy_mmr::{Pallet, Storage}, // Rialto bridge modules. + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, @@ -937,6 +955,7 @@ impl_runtime_apis! { list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::); + list_benchmark!(list, extra, pallet_bridge_relayers, BridgeRelayers); let storage_info = AllPalletsWithSystem::storage_info(); @@ -1058,6 +1077,7 @@ impl_runtime_apis! { pallet_bridge_parachains, ParachainsBench:: ); + add_benchmark!(params, batches, pallet_bridge_relayers, BridgeRelayers); Ok(batches) } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index ac1c1cf3d568d..6c3d838196a42 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -19,11 +19,13 @@ serde = { version = '1.0', optional = true, features = ['derive'] } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } +pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } # Substrate Dependencies ## Substrate Primitive Dependencies @@ -89,6 +91,7 @@ runtime-benchmarks = [ std = [ "bp-messages/std", "bp-millau/std", + "bp-relayers/std", "bp-runtime/std", "bp-rialto-parachain/std", "bridge-runtime-common/std", @@ -113,6 +116,7 @@ std = [ "pallet-balances/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-bridge-relayers/std", "pallet-randomness-collective-flip/std", "pallet-timestamp/std", "pallet-sudo/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index f2463b5e06f51..c52504c1950e5 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -474,6 +474,13 @@ impl pallet_aura::Config for Runtime { type MaxAuthorities = MaxAuthorities; } +impl pallet_bridge_relayers::Config for Runtime { + type Event = Event; + type Reward = Balance; + type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type WeightInfo = (); +} + parameter_types! { /// This is a pretty unscientific cap. /// @@ -530,7 +537,12 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = (); + type MessageDeliveryAndDispatchPayment = + pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + Runtime, + WithMillauMessagesInstance, + GetDeliveryConfirmationTransactionFee, + >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -567,6 +579,7 @@ construct_runtime!( DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 53, // Millau bridge modules. + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index ff3eb703ff358..a29560a65d9a0 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -19,11 +19,13 @@ serde = { version = "1.0", optional = true, features = ["derive"] } bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } +pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } # Substrate Dependencies @@ -89,6 +91,7 @@ std = [ "bp-header-chain/std", "bp-messages/std", "bp-millau/std", + "bp-relayers/std", "bp-rialto/std", "bp-runtime/std", "bridge-runtime-common/std", @@ -106,6 +109,7 @@ std = [ "pallet-beefy-mmr/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", + "pallet-bridge-relayers/std", "pallet-grandpa/std", "pallet-mmr/std", "pallet-xcm/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index e06fdffe88909..f0bc0982e69cb 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -389,6 +389,13 @@ impl pallet_authority_discovery::Config for Runtime { type MaxAuthorities = MaxAuthorities; } +impl pallet_bridge_relayers::Config for Runtime { + type Event = Event; + type Reward = Balance; + type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type WeightInfo = (); +} + parameter_types! { /// This is a pretty unscientific cap. /// @@ -447,7 +454,12 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = (); + type MessageDeliveryAndDispatchPayment = + pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + Runtime, + WithMillauMessagesInstance, + GetDeliveryConfirmationTransactionFee, + >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -484,6 +496,7 @@ construct_runtime!( MmrLeaf: pallet_beefy_mmr::{Pallet, Storage}, // Millau bridge modules. + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index d17fee6ceda86..f23a2ac190397 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -40,6 +40,7 @@ #![allow(clippy::all)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{ traits::Get, diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 6db9ad5c44279..3f9ea8bbb16d5 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-07, STEPS: 50, REPEAT: 20 +//! DATE: 2022-07-20, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -40,6 +40,7 @@ #![allow(clippy::all)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{ traits::Get, @@ -69,22 +70,22 @@ pub trait WeightInfo { pub struct MillauWeight(PhantomData); impl WeightInfo for MillauWeight { fn send_minimal_message_worst_case() -> Weight { - (37_948_000 as Weight) + (38_822_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (39_158_000 as Weight) + (39_799_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (48_698_000 as Weight) + (47_772_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (2_919_864_000 as Weight) + (3_081_804_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -95,71 +96,71 @@ impl WeightInfo for MillauWeight { .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof() -> Weight { - (25_992_000 as Weight) + (26_523_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_two_messages_proof() -> Weight { - (37_016_000 as Weight) + (39_278_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (31_589_000 as Weight) + (32_416_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (25_962_000 as Weight) + (27_078_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (74_385_000 as Weight) + (78_235_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (26_159_000 as Weight) + (27_635_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (27_590_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (34_576_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (27_354_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (37_318_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (27_652_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + (41_245_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(3 as Weight)) } } // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (37_948_000 as Weight) + (38_822_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (39_158_000 as Weight) + (39_799_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (48_698_000 as Weight) + (47_772_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (2_919_864_000 as Weight) + (3_081_804_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -170,48 +171,48 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof() -> Weight { - (25_992_000 as Weight) + (26_523_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_two_messages_proof() -> Weight { - (37_016_000 as Weight) + (39_278_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (31_589_000 as Weight) + (32_416_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (25_962_000 as Weight) + (27_078_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (74_385_000 as Weight) + (78_235_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (26_159_000 as Weight) + (27_635_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (27_590_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (34_576_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (27_354_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (37_318_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (27_652_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + (41_245_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } } diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index bf7384b814689..b96e24752d512 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -40,6 +40,7 @@ #![allow(clippy::all)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{ traits::Get, diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml new file mode 100644 index 0000000000000..ef689f55918b2 --- /dev/null +++ b/modules/relayers/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "pallet-bridge-relayers" +description = "Module used to store relayer rewards and coordinate relayers set." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } +num-traits = { version = "0.2", default-features = false } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } + +# Bridge dependencies + +bp-messages = { path = "../../primitives/messages", default-features = false } +bp-relayers = { path = "../../primitives/relayers", default-features = false } +pallet-bridge-messages = { path = "../messages", default-features = false } + +# Substrate Dependencies + +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[dev-dependencies] +bp-runtime = { path = "../../primitives/runtime" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[features] +default = ["std"] +std = [ + "bp-messages/std", + "bp-relayers/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "num-traits/std", + "pallet-bridge-messages/std", + "scale-info/std", + "serde", + "sp-arithmetic/std", + "sp-std/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", +] diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs new file mode 100644 index 0000000000000..706454e0497dd --- /dev/null +++ b/modules/relayers/src/benchmarking.rs @@ -0,0 +1,40 @@ +// 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 . + +//! Benchmarks for the relayers Pallet. + +#![cfg(feature = "runtime-benchmarks")] + +use crate::*; + +use frame_benchmarking::{benchmarks, whitelisted_caller}; +use frame_system::RawOrigin; + +/// Reward amount that is (hopefully) is larger than existential deposit across all chains. +const REWARD_AMOUNT: u32 = u32::MAX; + +benchmarks! { + // Benchmark `claim_rewards` call. + claim_rewards { + let relayer: T::AccountId = whitelisted_caller(); + RelayerRewards::::insert(&relayer, T::Reward::from(REWARD_AMOUNT)); + }: _(RawOrigin::Signed(relayer)) + verify { + // we can't check anything here, because `PaymentProcedure` is responsible for + // payment logic, so we assume that if call has succeeded, the procedure has + // also completed successfully + } +} diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs new file mode 100644 index 0000000000000..596dd89f31339 --- /dev/null +++ b/modules/relayers/src/lib.rs @@ -0,0 +1,170 @@ +// 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 . + +//! Runtime module that is used to store relayer rewards and (in the future) to +//! coordinate relations between relayers. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +use bp_relayers::PaymentProcedure; +use sp_arithmetic::traits::AtLeast32BitUnsigned; +use sp_std::marker::PhantomData; +use weights::WeightInfo; + +pub use pallet::*; +pub use payment_adapter::MessageDeliveryAndDispatchPaymentAdapter; + +mod benchmarking; +mod mock; +mod payment_adapter; + +pub mod weights; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type Event: From> + IsType<::Event>; + /// Type of relayer reward. + type Reward: AtLeast32BitUnsigned + Copy + Parameter + MaxEncodedLen; + /// Pay rewards adapter. + type PaymentProcedure: PaymentProcedure; + /// Pallet call weights. + type WeightInfo: WeightInfo; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(PhantomData); + + #[pallet::call] + impl Pallet { + /// Claim accumulated rewards. + #[pallet::weight(T::WeightInfo::claim_rewards())] + pub fn claim_rewards(origin: OriginFor) -> DispatchResult { + let relayer = ensure_signed(origin)?; + + RelayerRewards::::try_mutate_exists(&relayer, |maybe_reward| -> DispatchResult { + let reward = maybe_reward.take().ok_or(Error::::NoRewardForRelayer)?; + T::PaymentProcedure::pay_reward(&relayer, reward).map_err(|e| { + log::trace!( + target: "runtime::bridge-relayers", + "Failed to pay rewards to {:?}: {:?}", + relayer, + e, + ); + Error::::FailedToPayReward + })?; + + Self::deposit_event(Event::::RewardPaid { relayer: relayer.clone(), reward }); + Ok(()) + }) + } + } + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Reward has been paid to the relayer. + RewardPaid { + /// Relayer account that has been rewarded. + relayer: T::AccountId, + /// Reward amount. + reward: T::Reward, + }, + } + + #[pallet::error] + pub enum Error { + /// No reward can be claimed by given relayer. + NoRewardForRelayer, + /// Reward payment procedure has failed. + FailedToPayReward, + } + + /// Map of the relayer => accumulated reward. + #[pallet::storage] + pub type RelayerRewards = + StorageMap<_, Blake2_128Concat, T::AccountId, T::Reward, OptionQuery>; +} + +#[cfg(test)] +mod tests { + use super::*; + use mock::*; + + use frame_support::{assert_noop, assert_ok, traits::fungible::Inspect}; + use sp_runtime::DispatchError; + + #[test] + fn root_cant_claim_anything() { + run_test(|| { + assert_noop!( + Pallet::::claim_rewards(Origin::root()), + DispatchError::BadOrigin, + ); + }); + } + + #[test] + fn relayer_cant_claim_if_no_reward_exists() { + run_test(|| { + assert_noop!( + Pallet::::claim_rewards(Origin::signed(REGULAR_RELAYER)), + Error::::NoRewardForRelayer, + ); + }); + } + + #[test] + fn relayer_cant_claim_if_payment_procedure_fails() { + run_test(|| { + RelayerRewards::::insert(FAILING_RELAYER, 100); + assert_noop!( + Pallet::::claim_rewards(Origin::signed(FAILING_RELAYER)), + Error::::FailedToPayReward, + ); + }); + } + + #[test] + fn relayer_can_claim_reward() { + run_test(|| { + RelayerRewards::::insert(REGULAR_RELAYER, 100); + assert_ok!(Pallet::::claim_rewards(Origin::signed(REGULAR_RELAYER))); + assert_eq!(RelayerRewards::::get(REGULAR_RELAYER), None); + }); + } + + #[test] + fn mint_reward_payment_procedure_actually_mints_tokens() { + type Balances = pallet_balances::Pallet; + + run_test(|| { + assert_eq!(Balances::balance(&1), 0); + assert_eq!(Balances::total_issuance(), 0); + bp_relayers::MintReward::::pay_reward(&1, 100).unwrap(); + assert_eq!(Balances::balance(&1), 100); + assert_eq!(Balances::total_issuance(), 100); + }); + } +} diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs new file mode 100644 index 0000000000000..2ceabc6621fb3 --- /dev/null +++ b/modules/relayers/src/mock.rs @@ -0,0 +1,156 @@ +// 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 . + +#![cfg(test)] + +use crate as pallet_bridge_relayers; + +use bp_messages::{source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages}; +use bp_relayers::PaymentProcedure; +use frame_support::{parameter_types, weights::RuntimeDbWeight}; +use sp_core::H256; +use sp_runtime::{ + testing::Header as SubstrateHeader, + traits::{BlakeTwo256, IdentityLookup}, +}; + +pub type AccountId = u64; +pub type Balance = u64; + +type Block = frame_system::mocking::MockBlock; +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + +frame_support::construct_runtime! { + pub enum TestRuntime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Event}, + Messages: pallet_bridge_messages::{Pallet, Event}, + Relayers: pallet_bridge_relayers::{Pallet, Call, Event}, + } +} + +parameter_types! { + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; +} + +impl frame_system::Config for TestRuntime { + type Origin = Origin; + type Index = u64; + type Call = Call; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = SubstrateHeader; + type Event = Event; + type BlockHashCount = frame_support::traits::ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = frame_support::traits::Everything; + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = DbWeight; + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_balances::Config for TestRuntime { + type MaxLocks = (); + type Balance = Balance; + type DustRemoval = (); + type Event = Event; + type ExistentialDeposit = frame_support::traits::ConstU64<1>; + type AccountStore = frame_system::Pallet; + type WeightInfo = (); + type MaxReserves = (); + type ReserveIdentifier = (); +} + +parameter_types! { + pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; +} + +// we're not testing messages pallet here, so values in this config might be crazy +impl pallet_bridge_messages::Config for TestRuntime { + type Event = Event; + type WeightInfo = (); + type Parameter = (); + type MaxMessagesToPruneAtOnce = frame_support::traits::ConstU64<0>; + type MaxUnrewardedRelayerEntriesAtInboundLane = frame_support::traits::ConstU64<8>; + type MaxUnconfirmedMessagesAtInboundLane = frame_support::traits::ConstU64<8>; + + type MaximalOutboundPayloadSize = frame_support::traits::ConstU32<1024>; + type OutboundPayload = (); + type OutboundMessageFee = Balance; + + type InboundPayload = (); + type InboundMessageFee = Balance; + type InboundRelayer = AccountId; + + type TargetHeaderChain = ForbidOutboundMessages; + type LaneMessageVerifier = ForbidOutboundMessages; + type MessageDeliveryAndDispatchPayment = (); + type OnMessageAccepted = (); + type OnDeliveryConfirmed = (); + + type SourceHeaderChain = ForbidInboundMessages; + type MessageDispatch = ForbidInboundMessages; + type BridgedChainId = TestBridgedChainId; +} + +impl pallet_bridge_relayers::Config for TestRuntime { + type Event = Event; + type Reward = Balance; + type PaymentProcedure = TestPaymentProcedure; + type WeightInfo = (); +} + +/// Regular relayer that may receive rewards. +pub const REGULAR_RELAYER: AccountId = 1; + +/// Relayer that can't receive rewards. +pub const FAILING_RELAYER: AccountId = 2; + +/// Payment procedure that rejects payments to the `FAILING_RELAYER`. +pub struct TestPaymentProcedure; + +impl PaymentProcedure for TestPaymentProcedure { + type Error = (); + + fn pay_reward(relayer: &AccountId, _reward: Balance) -> Result<(), Self::Error> { + match *relayer { + FAILING_RELAYER => Err(()), + _ => Ok(()), + } + } +} + +/// Run pallet test. +pub fn run_test(test: impl FnOnce() -> T) -> T { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(test) +} diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs new file mode 100644 index 0000000000000..6aa1248959dca --- /dev/null +++ b/modules/relayers/src/payment_adapter.rs @@ -0,0 +1,180 @@ +// 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 . + +//! Code that allows relayers pallet to be used as a delivery+dispatch payment mechanism +//! for the messages pallet. + +use crate::{Config, RelayerRewards}; + +use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; +use frame_support::traits::Get; +use sp_arithmetic::traits::{Bounded, Saturating, Zero}; +use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; + +/// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism +/// for the messages pallet. +pub struct MessageDeliveryAndDispatchPaymentAdapter( + PhantomData<(T, MessagesInstance, GetConfirmationFee)>, +); + +impl + MessageDeliveryAndDispatchPayment + for MessageDeliveryAndDispatchPaymentAdapter +where + T: Config + pallet_bridge_messages::Config, + MessagesInstance: 'static, + GetConfirmationFee: Get, +{ + type Error = &'static str; + + fn pay_delivery_and_dispatch_fee( + _submitter: &T::Origin, + _fee: &T::Reward, + ) -> Result<(), Self::Error> { + // nothing shall happen here, because XCM deals with fee payment (planned to be burnt? + // or transferred to the treasury?) + Ok(()) + } + + fn pay_relayers_rewards( + lane_id: bp_messages::LaneId, + messages_relayers: VecDeque>, + confirmation_relayer: &T::AccountId, + received_range: &RangeInclusive, + ) { + let relayers_rewards = pallet_bridge_messages::calc_relayers_rewards::( + lane_id, + messages_relayers, + received_range, + ); + if !relayers_rewards.is_empty() { + schedule_relayers_rewards::( + confirmation_relayer, + relayers_rewards, + GetConfirmationFee::get(), + ); + } + } +} + +// Update rewards to given relayers, optionally rewarding confirmation relayer. +fn schedule_relayers_rewards( + confirmation_relayer: &T::AccountId, + relayers_rewards: RelayersRewards, + confirmation_fee: T::Reward, +) { + // reward every relayer except `confirmation_relayer` + let mut confirmation_relayer_reward = T::Reward::zero(); + for (relayer, reward) in relayers_rewards { + let mut relayer_reward = reward.reward; + + if relayer != *confirmation_relayer { + // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee + // from relayer reward. + // + // If confirmation fee has been increased (or if it was the only component of message + // fee), then messages relayer may receive zero reward. + let mut confirmation_reward = T::Reward::try_from(reward.messages) + .unwrap_or_else(|_| Bounded::max_value()) + .saturating_mul(confirmation_fee); + if confirmation_reward > relayer_reward { + confirmation_reward = relayer_reward; + } + relayer_reward = relayer_reward.saturating_sub(confirmation_reward); + confirmation_relayer_reward = + confirmation_relayer_reward.saturating_add(confirmation_reward); + } else { + // If delivery confirmation is submitted by this relayer, let's add confirmation fee + // from other relayers to this relayer reward. + confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward); + continue + } + + schedule_relayer_reward::(&relayer, relayer_reward); + } + + // finally - pay reward to confirmation relayer + schedule_relayer_reward::(confirmation_relayer, confirmation_relayer_reward); +} + +/// Remember that the reward shall be paid to the relayer. +fn schedule_relayer_reward(relayer: &T::AccountId, reward: T::Reward) { + if reward.is_zero() { + return + } + + RelayerRewards::::mutate(relayer, |old_reward: &mut Option| { + let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); + log::trace!( + target: "T::bridge-relayers", + "Relayer {:?} can now claim reward: {:?}", + relayer, + new_reward, + ); + *old_reward = Some(new_reward); + }); +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + + const RELAYER_1: AccountId = 1; + const RELAYER_2: AccountId = 2; + const RELAYER_3: AccountId = 3; + + fn relayers_rewards() -> RelayersRewards { + vec![ + (RELAYER_1, bp_messages::source_chain::RelayerRewards { reward: 100, messages: 2 }), + (RELAYER_2, bp_messages::source_chain::RelayerRewards { reward: 100, messages: 3 }), + ] + .into_iter() + .collect() + } + + #[test] + fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { + run_test(|| { + schedule_relayers_rewards::(&RELAYER_2, relayers_rewards(), 10); + + assert_eq!(RelayerRewards::::get(&RELAYER_1), Some(80)); + assert_eq!(RelayerRewards::::get(&RELAYER_2), Some(120)); + }); + } + + #[test] + fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { + run_test(|| { + schedule_relayers_rewards::(&RELAYER_3, relayers_rewards(), 10); + + assert_eq!(RelayerRewards::::get(&RELAYER_1), Some(80)); + assert_eq!(RelayerRewards::::get(&RELAYER_2), Some(70)); + assert_eq!(RelayerRewards::::get(&RELAYER_3), Some(50)); + }); + } + + #[test] + fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { + run_test(|| { + schedule_relayers_rewards::(&RELAYER_3, relayers_rewards(), 1000); + + assert_eq!(RelayerRewards::::get(&RELAYER_1), None); + assert_eq!(RelayerRewards::::get(&RELAYER_2), None); + assert_eq!(RelayerRewards::::get(&RELAYER_3), Some(200)); + }); + } +} diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs new file mode 100644 index 0000000000000..fd7efe940d455 --- /dev/null +++ b/modules/relayers/src/weights.rs @@ -0,0 +1,73 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_relayers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-07-20, STEPS: 50, REPEAT: 20 +//! LOW RANGE: [], HIGH RANGE: [] +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled +//! CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/millau-bridge-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_bridge_relayers +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./modules/relayers/src/weights.rs +// --template=./.maintain/millau-weight-template.hbs + +#![allow(clippy::all)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for `pallet_bridge_relayers`. +pub trait WeightInfo { + fn claim_rewards() -> Weight; +} + +/// Weights for `pallet_bridge_relayers` using the Millau node and recommended hardware. +pub struct MillauWeight(PhantomData); +impl WeightInfo for MillauWeight { + fn claim_rewards() -> Weight { + (38_435_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + fn claim_rewards() -> Weight { + (38_435_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } +} diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml new file mode 100644 index 0000000000000..0d6d020a0997b --- /dev/null +++ b/primitives/relayers/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "bp-relayers" +description = "Primitives of relayers module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge dependencies + +#bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +#frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[dev-dependencies] +hex = "0.4" +hex-literal = "0.3" + +[features] +default = ["std"] +std = [ +# "bp-runtime/std", + "frame-support/std", +# "frame-system/std", +# "scale-info/std", +# "serde", +# "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs new file mode 100644 index 0000000000000..d1c82d612e2e9 --- /dev/null +++ b/primitives/relayers/src/lib.rs @@ -0,0 +1,45 @@ +// 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 . + +//! Primitives of messages module. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{fmt::Debug, marker::PhantomData}; + +/// Reward payment procedure. +pub trait PaymentProcedure { + /// Error that may be returned by the procedure. + type Error: Debug; + + /// Pay reward to the relayer. + fn pay_reward(relayer: &Relayer, reward: Reward) -> Result<(), Self::Error>; +} + +/// Reward payment procedure that is simply minting given amount of tokens. +pub struct MintReward(PhantomData<(T, Relayer)>); + +impl PaymentProcedure for MintReward +where + T: frame_support::traits::fungible::Mutate, +{ + type Error = sp_runtime::DispatchError; + + fn pay_reward(relayer: &Relayer, reward: T::Balance) -> Result<(), Self::Error> { + T::mint_into(relayer, reward) + } +} From d997b20963575cc09982577dc401c845340497fb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 20 Jul 2022 13:42:52 +0300 Subject: [PATCH 0740/1210] reuse lane_id variable (#1517) --- modules/messages/src/benchmarking.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 9c74265e2da67..e7650f17214db 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -238,7 +238,7 @@ benchmarks_instance_pallet! { }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) verify { assert_eq!( - OutboundMessages::::get(MessageKey { lane_id: T::bench_lane_id(), nonce }).unwrap().fee, + OutboundMessages::::get(MessageKey { lane_id, nonce }).unwrap().fee, T::message_fee() + additional_fee, ); } @@ -260,7 +260,7 @@ benchmarks_instance_pallet! { }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) verify { assert_eq!( - OutboundMessages::::get(MessageKey { lane_id: T::bench_lane_id(), nonce }).unwrap().fee, + OutboundMessages::::get(MessageKey { lane_id, nonce }).unwrap().fee, T::message_fee() + additional_fee, ); } From 068704c9c8204396ccd86088b7853a41375a0380 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 25 Jul 2022 11:27:35 +0300 Subject: [PATCH 0741/1210] Reduce the number of macros used for SignedExtensions Reduce the number of macros used for SignedExtensions Signed-off-by: Serban Iorga --- bin/millau/runtime/src/lib.rs | 30 +-- bin/runtime-common/src/lib.rs | 167 ++++++++++++ bin/runtime-common/src/messages_extension.rs | 257 ++++++++----------- modules/grandpa/src/extension.rs | 164 ++++-------- modules/parachains/src/extension.rs | 196 +++++--------- primitives/runtime/src/lib.rs | 7 + relays/client-millau/src/lib.rs | 6 +- 7 files changed, 412 insertions(+), 415 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 36ce83049d1c5..fc2f19b945889 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -78,7 +78,7 @@ pub use frame_support::{ constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, IdentityFee, RuntimeDbWeight, Weight, }, - StorageValue, + RuntimeDebug, StorageValue, }; pub use frame_system::Call as SystemCall; @@ -89,6 +89,7 @@ pub use pallet_bridge_parachains::Call as BridgeParachainsCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; +use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; @@ -592,21 +593,14 @@ construct_runtime!( } ); -pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header! { - Runtime, - Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, - Call::BridgeWestendGrandpa => WestendGrandpaInstance -} - -pallet_bridge_parachains::declare_bridge_reject_obsolete_parachain_header! { - Runtime, - Call::BridgeRialtoParachains => WithRialtoParachainsInstance -} - -bridge_runtime_common::declare_bridge_reject_obsolete_messages! { - Runtime, - Call::BridgeRialtoMessages => WithRialtoMessagesInstance, - Call::BridgeRialtoParachainMessages => WithRialtoParachainMessagesInstance +generate_bridge_reject_obsolete_headers_and_messages! { + Call, AccountId, + // Grandpa + BridgeRialtoGrandpa, BridgeWestendGrandpa, + // Parachains + BridgeRialtoParachains, + //Messages + BridgeRialtoMessages, BridgeRialtoParachainMessages } /// The address format for describing accounts. @@ -629,9 +623,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, - BridgeRejectObsoleteGrandpaHeader, - BridgeRejectObsoleteParachainHeader, - BridgeRejectObsoleteMessages, + BridgeRejectObsoleteHeadersAndMessages, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 9776fd5827d82..5b2cea8ddd7ff 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -18,6 +18,9 @@ #![cfg_attr(not(feature = "std"), no_std)] +use bp_runtime::FilterCall; +use sp_runtime::transaction_validity::TransactionValidity; + pub mod messages; pub mod messages_api; pub mod messages_benchmarking; @@ -26,3 +29,167 @@ pub mod parachains_benchmarking; #[cfg(feature = "integrity-test")] pub mod integrity; + +/// A duplication of the `FilterCall` trait. +/// +/// We need this trait in order to be able to implement it for the messages pallet, +/// since the implementation is done outside of the pallet crate. +pub trait BridgeRuntimeFilterCall { + /// Checks if a runtime call is valid. + fn validate(call: &Call) -> TransactionValidity; +} + +impl BridgeRuntimeFilterCall for pallet_bridge_grandpa::Pallet +where + pallet_bridge_grandpa::Pallet: FilterCall, +{ + fn validate(call: &Call) -> TransactionValidity { + as FilterCall>::validate(call) + } +} + +impl BridgeRuntimeFilterCall for pallet_bridge_parachains::Pallet +where + pallet_bridge_parachains::Pallet: FilterCall, +{ + fn validate(call: &Call) -> TransactionValidity { + as FilterCall>::validate(call) + } +} + +/// Declares a runtime-specific `BridgeRejectObsoleteHeadersAndMessages` signed extension. +/// +/// ## Example +/// +/// ```nocompile +/// generate_bridge_reject_obsolete_headers_and_messages!{ +/// Call, AccountId +/// BridgeRialtoGrandpa, BridgeWestendGrandpa, +/// BridgeRialtoParachains +/// } +/// ``` +/// +/// The goal of this extension is to avoid "mining" transactions that provide outdated bridged +/// headers and messages. Without that extension, even honest relayers may lose their funds if +/// there are multiple relays running and submitting the same information. +#[macro_export] +macro_rules! generate_bridge_reject_obsolete_headers_and_messages { + ($call:ty, $account_id:ty, $($filter_call:ty),*) => { + #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] + pub struct BridgeRejectObsoleteHeadersAndMessages; + impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { + const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; + type AccountId = $account_id; + type Call = $call; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> sp_std::result::Result< + (), + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, + _len: usize, + ) -> sp_runtime::transaction_validity::TransactionValidity { + let valid = sp_runtime::transaction_validity::ValidTransaction::default(); + $( + let valid = valid + .combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?); + )* + Ok(valid) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, + ) -> Result { + self.validate(who, call, info, len).map(drop) + } + } + }; +} + +#[cfg(test)] +mod tests { + use crate::BridgeRuntimeFilterCall; + use frame_support::{assert_err, assert_ok}; + use sp_runtime::{ + traits::SignedExtension, + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + }; + + pub struct MockCall { + data: u32, + } + + impl sp_runtime::traits::Dispatchable for MockCall { + type Origin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch( + self, + _origin: Self::Origin, + ) -> sp_runtime::DispatchResultWithInfo { + unimplemented!() + } + } + + struct FirstFilterCall; + impl BridgeRuntimeFilterCall for FirstFilterCall { + fn validate(call: &MockCall) -> TransactionValidity { + if call.data <= 1 { + return InvalidTransaction::Custom(1).into() + } + + Ok(ValidTransaction { priority: 1, ..Default::default() }) + } + } + + struct SecondFilterCall; + impl BridgeRuntimeFilterCall for SecondFilterCall { + fn validate(call: &MockCall) -> TransactionValidity { + if call.data <= 2 { + return InvalidTransaction::Custom(2).into() + } + + Ok(ValidTransaction { priority: 2, ..Default::default() }) + } + } + + #[test] + fn test() { + generate_bridge_reject_obsolete_headers_and_messages!( + MockCall, + (), + FirstFilterCall, + SecondFilterCall + ); + + assert_err!( + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0), + InvalidTransaction::Custom(1) + ); + + assert_err!( + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0), + InvalidTransaction::Custom(2) + ); + + assert_ok!( + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0), + ValidTransaction { priority: 3, ..Default::default() } + ) + } +} diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index 48b30fa646e2a..95a8b947e74be 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -14,136 +14,100 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -/// Declares a runtime-specific `BridgeRejectObsoleteMessages` and -/// `BridgeRejectObsoleteMessageConfirmations` signed extensions. -/// -/// ## Example -/// -/// ```nocompile -/// bridge_runtime_common::declare_bridge_reject_obsolete_messages!{ -/// Runtime, -/// Call::BridgeRialtoMessages => WithRialtoMessagesInstance, -/// Call::BridgeRialtoParachainMessages => WithRialtoParachainMessagesInstance, -/// } -/// ``` -/// -/// The goal of this extension is to avoid "mining" messages delivery and delivery confirmation -/// transactions, that are delivering outdated messages/confirmations. Without that extension, +use crate::{ + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + }, + BridgeRuntimeFilterCall, +}; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use pallet_bridge_messages::{Config, Pallet}; +use sp_runtime::transaction_validity::TransactionValidity; + +/// Validate messages in order to avoid "mining" messages delivery and delivery confirmation +/// transactions, that are delivering outdated messages/confirmations. Without this validation, /// even honest relayers may lose their funds if there are multiple relays running and submitting /// the same messages/confirmations. -#[macro_export] -macro_rules! declare_bridge_reject_obsolete_messages { - ($runtime:ident, $($call:path => $instance:ty),*) => { - /// Transaction-with-obsolete-messages check that will reject transaction if - /// it submits obsolete messages/confirmations. - #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] - pub struct BridgeRejectObsoleteMessages; - - impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteMessages { - const IDENTIFIER: &'static str = "BridgeRejectObsoleteMessages"; - type AccountId = <$runtime as frame_system::Config>::AccountId; - type Call = <$runtime as frame_system::Config>::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result< - (), - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(()) - } - - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, - _len: usize, - ) -> sp_runtime::transaction_validity::TransactionValidity { - match *call { - $( - $call(pallet_bridge_messages::Call::<$runtime, $instance>::receive_messages_proof { - ref proof, - .. - }) => { - let nonces_end = proof.nonces_end; - - let inbound_lane_data = pallet_bridge_messages::InboundLanes::<$runtime, $instance>::get(&proof.lane); - if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() { - log::trace!( - target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages delivery transaction: lane {:?}, bundled {:?}, best {:?}", - proof.lane, - proof.nonces_end, - inbound_lane_data.last_delivered_nonce(), - ); - - return sp_runtime::transaction_validity::InvalidTransaction::Stale.into(); - } - - Ok(sp_runtime::transaction_validity::ValidTransaction::default()) - }, - $call(pallet_bridge_messages::Call::<$runtime, $instance>::receive_messages_delivery_proof { - ref proof, - ref relayers_state, - .. - }) => { - let latest_delivered_nonce = relayers_state.last_delivered_nonce; - - let outbound_lane_data = pallet_bridge_messages::OutboundLanes::<$runtime, $instance>::get(&proof.lane); - if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce { - log::trace!( - target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages confirmation transaction: lane {:?}, bundled {:?}, best {:?}", - proof.lane, - latest_delivered_nonce, - outbound_lane_data.latest_received_nonce, - ); - - return sp_runtime::transaction_validity::InvalidTransaction::Stale.into(); - } - - Ok(sp_runtime::transaction_validity::ValidTransaction::default()) - } - )* - _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), +impl< + BridgedHeaderHash, + SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< + >::InboundMessageFee, + MessagesProof = FromBridgedChainMessagesProof, + >, + TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain< + >::OutboundPayload, + ::AccountId, + MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof, + >, + Call: IsSubType, T>>, + T: frame_system::Config + + Config, + I: 'static, + > BridgeRuntimeFilterCall for Pallet +{ + fn validate(call: &Call) -> TransactionValidity { + match call.is_sub_type() { + Some(pallet_bridge_messages::Call::::receive_messages_proof { + ref proof, + .. + }) => { + let inbound_lane_data = + pallet_bridge_messages::InboundLanes::::get(&proof.lane); + if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages delivery transaction: \ + lane {:?}, bundled {:?}, best {:?}", + proof.lane, + proof.nonces_end, + inbound_lane_data.last_delivered_nonce(), + ); + + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() } - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &sp_runtime::traits::DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(drop) - } - - fn post_dispatch( - _maybe_pre: Option, - _info: &sp_runtime::traits::DispatchInfoOf, - _post_info: &sp_runtime::traits::PostDispatchInfoOf, - _len: usize, - _result: &sp_runtime::DispatchResult, - ) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> { - Ok(()) - } + }, + Some(pallet_bridge_messages::Call::::receive_messages_delivery_proof { + ref proof, + ref relayers_state, + .. + }) => { + let latest_delivered_nonce = relayers_state.last_delivered_nonce; + + let outbound_lane_data = + pallet_bridge_messages::OutboundLanes::::get(&proof.lane); + if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages confirmation transaction: \ + lane {:?}, bundled {:?}, best {:?}", + proof.lane, + latest_delivered_nonce, + outbound_lane_data.latest_received_nonce, + ); + + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + } + }, + _ => {}, } - }; + + Ok(sp_runtime::transaction_validity::ValidTransaction::default()) + } } #[cfg(test)] mod tests { use bp_messages::UnrewardedRelayersState; - use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use millau_runtime::{ - bridge_runtime_common::messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + bridge_runtime_common::{ + messages::{ + source::FromBridgedChainMessagesDeliveryProof, + target::FromBridgedChainMessagesProof, + }, + BridgeRuntimeFilterCall, }, - BridgeRejectObsoleteMessages, Call, Runtime, WithRialtoMessagesInstance, + Call, Runtime, WithRialtoMessagesInstance, }; - use sp_runtime::traits::SignedExtension; fn deliver_message_10() { pallet_bridge_messages::InboundLanes::::insert( @@ -156,13 +120,9 @@ mod tests { nonces_start: bp_messages::MessageNonce, nonces_end: bp_messages::MessageNonce, ) -> bool { - BridgeRejectObsoleteMessages - .validate( - &[0u8; 32].into(), - &Call::BridgeRialtoMessages(pallet_bridge_messages::Call::< - Runtime, - WithRialtoMessagesInstance, - >::receive_messages_proof { + pallet_bridge_messages::Pallet::::validate( + &Call::BridgeRialtoMessages( + pallet_bridge_messages::Call::::receive_messages_proof { relayer_id_at_bridged_chain: [0u8; 32].into(), messages_count: (nonces_end - nonces_start + 1) as u32, dispatch_weight: 0, @@ -173,11 +133,10 @@ mod tests { nonces_start, nonces_end, }, - }), - &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, - 0, - ) - .is_ok() + }, + ), + ) + .is_ok() } #[test] @@ -222,27 +181,23 @@ mod tests { } fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool { - BridgeRejectObsoleteMessages - .validate( - &[0u8; 32].into(), - &Call::BridgeRialtoMessages(pallet_bridge_messages::Call::< - Runtime, - WithRialtoMessagesInstance, - >::receive_messages_delivery_proof { - proof: FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: Default::default(), - storage_proof: Vec::new(), - lane: [0, 0, 0, 0], - }, - relayers_state: UnrewardedRelayersState { - last_delivered_nonce, - ..Default::default() - }, - }), - &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, - 0, - ) - .is_ok() + pallet_bridge_messages::Pallet::::validate( + &Call::BridgeRialtoMessages(pallet_bridge_messages::Call::< + Runtime, + WithRialtoMessagesInstance, + >::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: Vec::new(), + lane: [0, 0, 0, 0], + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce, + ..Default::default() + }, + }), + ) + .is_ok() } #[test] diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index 007c5f3df7475..a724b6518d84b 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -14,132 +14,68 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -/// Declares a runtime-specific `BridgeRejectObsoleteGrandpaHeader` signed extension. -/// -/// ## Example -/// -/// ```nocompile -/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_grandpa_header!{ -/// Runtime, -/// Call::BridgeRialtoGrandpa => RialtoGrandpaInstance, -/// Call::BridgeWestendGrandpa => WestendGrandpaInstance, -/// } -/// ``` -/// -/// The goal of this extension is to avoid "mining" transactions that provide -/// outdated bridged chain headers. Without that extension, even honest relayers -/// may lose their funds if there are multiple relays running and submitting the -/// same information. -#[macro_export] -macro_rules! declare_bridge_reject_obsolete_grandpa_header { - ($runtime:ident, $($call:path => $instance:ty),*) => { - /// Transaction-with-obsolete-bridged-header check that will reject transaction if - /// it submits obsolete bridged header. - #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] - pub struct BridgeRejectObsoleteGrandpaHeader; - - impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteGrandpaHeader { - const IDENTIFIER: &'static str = "BridgeRejectObsoleteGrandpaHeader"; - type AccountId = <$runtime as frame_system::Config>::AccountId; - type Call = <$runtime as frame_system::Config>::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result< - (), - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(()) - } - - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, - _len: usize, - ) -> sp_runtime::transaction_validity::TransactionValidity { - match *call { - $( - $call($crate::Call::<$runtime, $instance>::submit_finality_proof { ref finality_target, ..}) => { - use sp_runtime::traits::Header as HeaderT; - - let bundled_block_number = *finality_target.number(); - - let best_finalized = $crate::BestFinalized::<$runtime, $instance>::get(); - let best_finalized_number = match best_finalized { - Some((best_finalized_number, _)) => best_finalized_number, - None => return sp_runtime::transaction_validity::InvalidTransaction::Call.into(), - }; - - if best_finalized_number < bundled_block_number { - Ok(sp_runtime::transaction_validity::ValidTransaction::default()) - } else { - log::trace!( - target: $crate::LOG_TARGET, - "Rejecting obsolete bridged header: bundled {:?}, best {:?}", - bundled_block_number, - best_finalized_number, - ); - - sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - }, - )* - _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), - } - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &sp_runtime::traits::DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(drop) - } - - fn post_dispatch( - _maybe_pre: Option, - _info: &sp_runtime::traits::DispatchInfoOf, - _post_info: &sp_runtime::traits::PostDispatchInfoOf, - _len: usize, - _result: &sp_runtime::DispatchResult, - ) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> { - Ok(()) - } +use crate::{Config, Pallet}; +use bp_runtime::FilterCall; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use sp_runtime::{ + traits::Header, + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, +}; + +/// Validate Grandpa headers in order to avoid "mining" transactions that provide outdated +/// bridged chain headers. Without this validation, even honest relayers may lose their funds +/// if there are multiple relays running and submitting the same information. +impl< + Call: IsSubType, T>>, + T: frame_system::Config + Config, + I: 'static, + > FilterCall for Pallet +{ + fn validate(call: &::Call) -> TransactionValidity { + let bundled_block_number = match call.is_sub_type() { + Some(crate::Call::::submit_finality_proof { ref finality_target, .. }) => + *finality_target.number(), + _ => return Ok(ValidTransaction::default()), + }; + + let best_finalized = crate::BestFinalized::::get(); + let best_finalized_number = match best_finalized { + Some((best_finalized_number, _)) => best_finalized_number, + None => return InvalidTransaction::Call.into(), + }; + + if best_finalized_number >= bundled_block_number { + log::trace!( + target: crate::LOG_TARGET, + "Rejecting obsolete bridged header: bundled {:?}, best {:?}", + bundled_block_number, + best_finalized_number, + ); + + return InvalidTransaction::Stale.into() } - }; + + Ok(ValidTransaction::default()) + } } #[cfg(test)] mod tests { + use super::FilterCall; use crate::{ mock::{run_test, test_header, Call, TestNumber, TestRuntime}, BestFinalized, }; use bp_test_utils::make_default_justification; - use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; - use sp_runtime::traits::SignedExtension; - - declare_bridge_reject_obsolete_grandpa_header! { - TestRuntime, - Call::Grandpa => () - } fn validate_block_submit(num: TestNumber) -> bool { - BridgeRejectObsoleteGrandpaHeader - .validate( - &42, - &Call::Grandpa(crate::Call::::submit_finality_proof { - finality_target: Box::new(test_header(num)), - justification: make_default_justification(&test_header(num)), - }), - &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, - 0, - ) - .is_ok() + crate::Pallet::::validate(&Call::Grandpa( + crate::Call::::submit_finality_proof { + finality_target: Box::new(test_header(num)), + justification: make_default_justification(&test_header(num)), + }, + )) + .is_ok() } fn sync_to_header_10() { diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs index efcd9ec567ff8..3ed6dd9cbeda5 100644 --- a/modules/parachains/src/extension.rs +++ b/modules/parachains/src/extension.rs @@ -14,154 +14,98 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -/// Declares a runtime-specific `BridgeRejectObsoleteParachainHeader` signed extension. -/// -/// ## Example -/// -/// ```nocompile -/// pallet_bridge_grandpa::declare_bridge_reject_obsolete_parachain_header!{ -/// Runtime, -/// Call::BridgeRialtoParachains => RialtoGrandpaInstance, -/// Call::BridgeWestendParachains => WestendGrandpaInstance, -/// } -/// ``` -/// -/// The goal of this extension is to avoid "mining" transactions that provide -/// outdated bridged parachain heads. Without that extension, even honest relayers +use crate::{Config, Pallet, RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use bp_runtime::FilterCall; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}; + +/// Validate parachain heads in order to avoid "mining" transactions that provide +/// outdated bridged parachain heads. Without this validation, even honest relayers /// may lose their funds if there are multiple relays running and submitting the /// same information. /// -/// This extension only works with transactions that are updating single parachain +/// This validation only works with transactions that are updating single parachain /// head. We can't use unbounded validation - it may take too long and either break /// block production, or "eat" significant portion of block production time literally /// for nothing. In addition, the single-parachain-head-per-transaction is how the /// pallet will be used in our environment. -#[macro_export] -macro_rules! declare_bridge_reject_obsolete_parachain_header { - ($runtime:ident, $($call:path => $instance:ty),*) => { - /// Transaction-with-obsolete-bridged-parachain-header check that will reject transaction if - /// it submits obsolete bridged parachain header. - #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] - pub struct BridgeRejectObsoleteParachainHeader; - - impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteParachainHeader { - const IDENTIFIER: &'static str = "BridgeRejectObsoleteParachainHeader"; - type AccountId = <$runtime as frame_system::Config>::AccountId; - type Call = <$runtime as frame_system::Config>::Call; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result< - (), - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(()) - } - - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, - _len: usize, - ) -> sp_runtime::transaction_validity::TransactionValidity { - match *call { - $( - $call($crate::Call::<$runtime, $instance>::submit_parachain_heads { - ref at_relay_block, - ref parachains, - .. - }) if parachains.len() == 1 => { - let (parachain, parachain_head_hash) = parachains.get(0).expect("verified by match condition; qed"); - - let bundled_relay_block_number = at_relay_block.0; - - let best_parachain_head = $crate::BestParaHeads::<$runtime, $instance>::get(parachain); - - match best_parachain_head { - Some(best_parachain_head) if best_parachain_head.at_relay_block_number - >= bundled_relay_block_number => { - log::trace!( - target: $crate::LOG_TARGET, - "Rejecting obsolete parachain-head {:?} transaction: bundled relay block number: \ - {:?} best relay block number: {:?}", - parachain, - bundled_relay_block_number, - best_parachain_head.at_relay_block_number, - ); - sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => { - log::trace!( - target: $crate::LOG_TARGET, - "Rejecting obsolete parachain-head {:?} transaction: head hash {:?}", - parachain, - best_parachain_head.head_hash, - ); - sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), - } - }, - )* - _ => Ok(sp_runtime::transaction_validity::ValidTransaction::default()), - } - } - - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - info: &sp_runtime::traits::DispatchInfoOf, - len: usize, - ) -> Result { - self.validate(who, call, info, len).map(drop) - } - - fn post_dispatch( - _maybe_pre: Option, - _info: &sp_runtime::traits::DispatchInfoOf, - _post_info: &sp_runtime::traits::PostDispatchInfoOf, - _len: usize, - _result: &sp_runtime::DispatchResult, - ) -> Result<(), sp_runtime::transaction_validity::TransactionValidityError> { - Ok(()) - } +impl< + Call: IsSubType, T>>, + T: frame_system::Config + Config, + I: 'static, + > FilterCall for Pallet +where + >::BridgedChain: + bp_runtime::Chain< + BlockNumber = RelayBlockNumber, + Hash = RelayBlockHash, + Hasher = RelayBlockHasher, + >, +{ + fn validate(call: &Call) -> TransactionValidity { + let (bundled_relay_block_number, parachains) = match call.is_sub_type() { + Some(crate::Call::::submit_parachain_heads { + ref at_relay_block, + ref parachains, + .. + }) if parachains.len() == 1 => (at_relay_block.0, parachains), + _ => return Ok(ValidTransaction::default()), + }; + + let (parachain, parachain_head_hash) = + parachains.get(0).expect("verified by match condition; qed"); + let best_parachain_head = crate::BestParaHeads::::get(parachain); + + match best_parachain_head { + Some(best_parachain_head) + if best_parachain_head.at_relay_block_number >= bundled_relay_block_number => + { + log::trace!( + target: crate::LOG_TARGET, + "Rejecting obsolete parachain-head {:?} transaction: \ + bundled relay block number: {:?} \ + best relay block number: {:?}", + parachain, + bundled_relay_block_number, + best_parachain_head.at_relay_block_number, + ); + InvalidTransaction::Stale.into() + }, + Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => { + log::trace!( + target: crate::LOG_TARGET, + "Rejecting obsolete parachain-head {:?} transaction: head hash {:?}", + parachain, + best_parachain_head.head_hash, + ); + InvalidTransaction::Stale.into() + }, + _ => Ok(ValidTransaction::default()), } - }; + } } #[cfg(test)] mod tests { use crate::{ + extension::FilterCall, mock::{run_test, Call, TestRuntime}, BestParaHead, BestParaHeads, RelayBlockNumber, }; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; - use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; - use sp_runtime::traits::SignedExtension; - - declare_bridge_reject_obsolete_parachain_header! { - TestRuntime, - Call::Parachains => () - } fn validate_submit_parachain_heads( num: RelayBlockNumber, parachains: Vec<(ParaId, ParaHash)>, ) -> bool { - BridgeRejectObsoleteParachainHeader - .validate( - &42, - &Call::Parachains(crate::Call::::submit_parachain_heads { - at_relay_block: (num, Default::default()), - parachains, - parachain_heads_proof: ParaHeadsProof(Vec::new()), - }), - &DispatchInfo { weight: 0, class: DispatchClass::Operational, pays_fee: Pays::Yes }, - 0, - ) - .is_ok() + crate::Pallet::::validate(&Call::Parachains( + crate::Call::::submit_parachain_heads { + at_relay_block: (num, Default::default()), + parachains, + parachain_heads_proof: ParaHeadsProof(Vec::new()), + }, + )) + .is_ok() } fn sync_to_relay_header_10() { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 982b8f9a0eb84..9807fa50864db 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -35,6 +35,7 @@ pub use chain::{ }; pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedSub, One}; +use sp_runtime::transaction_validity::TransactionValidity; pub use storage_proof::{ Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker, }; @@ -400,6 +401,12 @@ pub trait OwnedBridgeModule { } } +/// A trait for querying whether a runtime call is valid. +pub trait FilterCall { + /// Checks if a runtime call is valid. + fn validate(call: &Call) -> TransactionValidity; +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 4250bd34de75f..08bd1d76324d8 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -114,9 +114,7 @@ impl TransactionSignScheme for Millau { frame_system::CheckNonce::::from(param.unsigned.nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), - millau_runtime::BridgeRejectObsoleteGrandpaHeader, - millau_runtime::BridgeRejectObsoleteParachainHeader, - millau_runtime::BridgeRejectObsoleteMessages, + millau_runtime::BridgeRejectObsoleteHeadersAndMessages, ), ( (), @@ -128,8 +126,6 @@ impl TransactionSignScheme for Millau { (), (), (), - (), - (), ), ); let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); From 091fa76d88df8003ea18844735522a9ba9dd02ba Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 25 Jul 2022 17:59:34 +0300 Subject: [PATCH 0742/1210] Deduplicate parachains validation Deduplicate the logic that validates the updated parachain heads. Signed-off-by: Serban Iorga --- modules/parachains/src/extension.rs | 48 ++++------ modules/parachains/src/lib.rs | 87 +++++++++++-------- .../src/parachains/source.rs | 6 +- 3 files changed, 70 insertions(+), 71 deletions(-) diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs index 3ed6dd9cbeda5..18e718da0e46f 100644 --- a/modules/parachains/src/extension.rs +++ b/modules/parachains/src/extension.rs @@ -17,7 +17,7 @@ use crate::{Config, Pallet, RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use bp_runtime::FilterCall; use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; -use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}; +use sp_runtime::transaction_validity::{TransactionValidity, ValidTransaction}; /// Validate parachain heads in order to avoid "mining" transactions that provide /// outdated bridged parachain heads. Without this validation, even honest relayers @@ -43,45 +43,27 @@ where >, { fn validate(call: &Call) -> TransactionValidity { - let (bundled_relay_block_number, parachains) = match call.is_sub_type() { + let (updated_at_relay_block_number, parachains) = match call.is_sub_type() { Some(crate::Call::::submit_parachain_heads { ref at_relay_block, ref parachains, .. - }) if parachains.len() == 1 => (at_relay_block.0, parachains), + }) => (at_relay_block.0, parachains), + _ => return Ok(ValidTransaction::default()), + }; + let (parachain, parachain_head_hash) = match parachains.as_slice() { + &[(parachain, parachain_head_hash)] => (parachain, parachain_head_hash), _ => return Ok(ValidTransaction::default()), }; - let (parachain, parachain_head_hash) = - parachains.get(0).expect("verified by match condition; qed"); - let best_parachain_head = crate::BestParaHeads::::get(parachain); - - match best_parachain_head { - Some(best_parachain_head) - if best_parachain_head.at_relay_block_number >= bundled_relay_block_number => - { - log::trace!( - target: crate::LOG_TARGET, - "Rejecting obsolete parachain-head {:?} transaction: \ - bundled relay block number: {:?} \ - best relay block number: {:?}", - parachain, - bundled_relay_block_number, - best_parachain_head.at_relay_block_number, - ); - InvalidTransaction::Stale.into() - }, - Some(best_parachain_head) if best_parachain_head.head_hash == *parachain_head_hash => { - log::trace!( - target: crate::LOG_TARGET, - "Rejecting obsolete parachain-head {:?} transaction: head hash {:?}", - parachain, - best_parachain_head.head_hash, - ); - InvalidTransaction::Stale.into() - }, - _ => Ok(ValidTransaction::default()), - } + let maybe_stored_best_head = crate::BestParaHeads::::get(parachain); + Self::validate_updated_parachain_head( + parachain, + &maybe_stored_best_head, + updated_at_relay_block_number, + parachain_head_hash, + "Rejecting obsolete parachain-head transaction", + ) } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 05e14575eacf3..7d12ee34e08cf 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -373,6 +373,48 @@ pub mod pallet { storage.read_and_decode_value(parachain_head_key.0.as_ref()) } + /// Check if para head has been already updated at better relay chain block. + /// Without this check, we may import heads in random order. + pub fn validate_updated_parachain_head( + parachain: ParaId, + maybe_stored_best_head: &Option, + updated_at_relay_block_number: RelayBlockNumber, + updated_head_hash: ParaHash, + err_log_prefix: &str, + ) -> TransactionValidity { + let stored_best_head = match maybe_stored_best_head { + Some(stored_best_head) => stored_best_head, + None => return Ok(ValidTransaction::default()), + }; + + if stored_best_head.at_relay_block_number >= updated_at_relay_block_number { + log::trace!( + target: LOG_TARGET, + "{}. The parachain head for {:?} was already updated at better relay chain block {} >= {}.", + err_log_prefix, + parachain, + stored_best_head.at_relay_block_number, + updated_at_relay_block_number + ); + return InvalidTransaction::Stale.into() + } + + if stored_best_head.head_hash == updated_head_hash { + log::trace!( + target: LOG_TARGET, + "{}. The parachain head hash for {:?} was already updated to {} at block {} < {}.", + err_log_prefix, + parachain, + updated_head_hash, + stored_best_head.at_relay_block_number, + updated_at_relay_block_number + ); + return InvalidTransaction::Stale.into() + } + + Ok(ValidTransaction::default()) + } + /// Try to update parachain head. pub(super) fn update_parachain_head( parachain: ParaId, @@ -383,41 +425,16 @@ pub mod pallet { ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order - let next_imported_hash_position = match stored_best_head { - Some(stored_best_head) - if stored_best_head.at_relay_block_number <= updated_at_relay_block_number => - { - // check if this head has already been imported before - if updated_head_hash == stored_best_head.head_hash { - log::trace!( - target: LOG_TARGET, - "The head of parachain {:?} can't be updated to {}, because it has been already updated \ - to the same value at previous relay chain block: {} < {}", - parachain, - updated_head_hash, - stored_best_head.at_relay_block_number, - updated_at_relay_block_number, - ); - return Err(()) - } - - stored_best_head.next_imported_hash_position - }, - None => 0, - Some(stored_best_head) => { - log::trace!( - target: LOG_TARGET, - "The head of parachain {:?} can't be updated to {}, because it has been already updated \ - to {} at better relay chain block: {} > {}", - parachain, - updated_head_hash, - stored_best_head.head_hash, - stored_best_head.at_relay_block_number, - updated_at_relay_block_number, - ); - return Err(()) - }, - }; + Self::validate_updated_parachain_head( + parachain, + &stored_best_head, + updated_at_relay_block_number, + updated_head_hash, + "The parachain head can't be updated", + ) + .map_err(|_| ())?; + let next_imported_hash_position = stored_best_head + .map_or(0, |stored_best_head| stored_best_head.next_imported_hash_position); // insert updated best parachain head let head_hash_to_prune = diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index ecc940467035e..ea647c740d10f 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -161,11 +161,11 @@ where at_block: HeaderIdOf, parachains: &[ParaId], ) -> Result<(ParaHeadsProof, Vec), Self::Error> { - if parachains.len() != 1 || parachains[0].0 != P::SOURCE_PARACHAIN_PARA_ID { + let parachain = ParaId(P::SOURCE_PARACHAIN_PARA_ID); + if parachains != [parachain] { return Err(SubstrateError::Custom(format!( "Trying to prove unexpected parachains {:?}. Expected {:?}", - parachains, - P::SOURCE_PARACHAIN_PARA_ID, + parachains, parachain, ))) } From baf0eda8efffb7c63bdb1a30eeaaf1e49dc4b9ed Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 26 Jul 2022 14:56:41 +0300 Subject: [PATCH 0743/1210] Remove unneeded variable Signed-off-by: Serban Iorga --- relays/lib-substrate-relay/src/parachains/source.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index ea647c740d10f..f763b744f192e 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -115,10 +115,11 @@ where ))) } + let mut para_hash_at_source = ParaHashAtSource::None; let mut para_header_number_at_source = None; - let para_hash_at_source = match self.on_chain_parachain_header(at_block, para_id).await? { + match self.on_chain_parachain_header(at_block, para_id).await? { Some(parachain_header) => { - let mut parachain_head = ParaHashAtSource::Some(parachain_header.hash()); + para_hash_at_source = ParaHashAtSource::Some(parachain_header.hash()); para_header_number_at_source = Some(*parachain_header.number()); // never return head that is larger than requested. This way we'll never sync // headers past `maximal_header_id` @@ -130,21 +131,19 @@ where { // we don't want this header yet => let's report previously requested // header - parachain_head = ParaHashAtSource::Some(maximal_header_id.1); + para_hash_at_source = ParaHashAtSource::Some(maximal_header_id.1); para_header_number_at_source = Some(maximal_header_id.0); }, Some(_) => (), None => { // on-demand relay has not yet asked us to sync anything let's do that - parachain_head = ParaHashAtSource::Unavailable; + para_hash_at_source = ParaHashAtSource::Unavailable; para_header_number_at_source = None; }, } } - - parachain_head }, - None => ParaHashAtSource::None, + None => {}, }; if let (Some(metrics), Some(para_header_number_at_source)) = From 60c8014e1de9d7e0b155ea250532f2a22c05954c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 26 Jul 2022 22:50:04 +0300 Subject: [PATCH 0744/1210] Define StorageDoubleMapKeyProvider Signed-off-by: Serban Iorga --- modules/parachains/src/lib.rs | 22 ++++-- primitives/parachains/src/lib.rs | 25 +++---- primitives/runtime/src/lib.rs | 75 +++++++++++-------- relays/client-substrate/src/client.rs | 20 ++++- .../src/parachains/target.rs | 23 +++--- 5 files changed, 100 insertions(+), 65 deletions(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 7d12ee34e08cf..3cf0e60e3cdf8 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -80,7 +80,8 @@ struct UpdateParachainHeadArtifacts { #[frame_support::pallet] pub mod pallet { use super::*; - use bp_runtime::{BasicOperatingMode, OwnedBridgeModule}; + use bp_parachains::ImportedParaHeadsKeyProvider; + use bp_runtime::{BasicOperatingMode, OwnedBridgeModule, StorageDoubleMapKeyProvider}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -165,8 +166,14 @@ pub mod pallet { /// Parachain heads which have been imported into the pallet. #[pallet::storage] - pub type ImportedParaHeads, I: 'static = ()> = - StorageDoubleMap<_, Blake2_128Concat, ParaId, Blake2_128Concat, ParaHash, ParaHead>; + pub type ImportedParaHeads, I: 'static = ()> = StorageDoubleMap< + _, + ::Hasher1, + ::Key1, + ::Hasher2, + ::Key2, + ::Value, + >; /// A ring buffer of imported parachain head hashes. Ordered by the insertion time. #[pallet::storage] @@ -513,7 +520,8 @@ mod tests { run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; - use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError}; + use bp_parachains::ImportedParaHeadsKeyProvider; + use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider}; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, }; @@ -985,10 +993,10 @@ mod tests { ParaHash::from([21u8; 32]) ) .to_vec(), - bp_parachains::imported_parachain_head_storage_key_at_target( + ImportedParaHeadsKeyProvider::final_key( "Parachains", - ParaId(42), - ParaHash::from([21u8; 32]) + &ParaId(42), + &ParaHash::from([21u8; 32]) ) .0, ); diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index 791d2bd47f11f..e6c9360d59427 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -19,9 +19,10 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_polkadot_core::{ - parachains::{ParaHash, ParaId}, + parachains::{ParaHash, ParaHead, ParaId}, BlockNumber as RelayBlockNumber, }; +use bp_runtime::StorageDoubleMapKeyProvider; use codec::{Decode, Encode}; use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; use scale_info::TypeInfo; @@ -67,18 +68,16 @@ pub fn best_parachain_head_hash_storage_key_at_target( ) } -/// Returns runtime storage key of the parachain head with given hash at the target chain. +/// Can be use to access the runtime storage key of the parachain head at the target chain. /// /// The head is stored by the `pallet-bridge-parachains` pallet in the `ImportedParaHeads` map. -pub fn imported_parachain_head_storage_key_at_target( - bridge_parachains_pallet_name: &str, - para_id: ParaId, - head_hash: ParaHash, -) -> StorageKey { - bp_runtime::storage_double_map_final_key::( - bridge_parachains_pallet_name, - "ImportedParaHeads", - ¶_id.encode(), - &head_hash.encode(), - ) +pub struct ImportedParaHeadsKeyProvider; +impl StorageDoubleMapKeyProvider for ImportedParaHeadsKeyProvider { + const MAP_NAME: &'static str = "ImportedParaHeads"; + + type Hasher1 = Blake2_128Concat; + type Key1 = ParaId; + type Hasher2 = Blake2_128Concat; + type Key2 = ParaHash; + type Value = ParaHead; } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 9807fa50864db..ae7250c49bdf6 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -246,38 +246,6 @@ pub fn storage_map_final_key( StorageKey(final_key) } -/// This is a copy of the -/// `frame_support::storage::generator::StorageDoubleMap::storage_double_map_final_key` for maps -/// based on selected hashers. -/// -/// We're using it because to call `storage_double_map_final_key` directly, we need access to the -/// runtime and pallet instance, which (sometimes) is impossible. -pub fn storage_double_map_final_key( - pallet_prefix: &str, - map_name: &str, - key1: &[u8], - key2: &[u8], -) -> StorageKey { - let key1_hashed = H1::hash(key1); - let key2_hashed = H2::hash(key2); - 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() + - key1_hashed.as_ref().len() + - key2_hashed.as_ref().len(), - ); - - final_key.extend_from_slice(&pallet_prefix_hashed[..]); - final_key.extend_from_slice(&storage_prefix_hashed[..]); - final_key.extend_from_slice(key1_hashed.as_ref()); - final_key.extend_from_slice(key2_hashed.as_ref()); - - StorageKey(final_key) -} - /// This is how a storage key of storage parameter (`parameter_types! { storage Param: bool = false; /// }`) is computed. /// @@ -304,6 +272,49 @@ pub fn storage_value_key(pallet_prefix: &str, value_name: &str) -> StorageKey { StorageKey(final_key) } +/// Can be use to access the runtime storage key of a `StorageDoubleMap`. +pub trait StorageDoubleMapKeyProvider { + // The name of the variable that holds the `StorageDoubleMap` + const MAP_NAME: &'static str; + + // The same as `StorageDoubleMap::Hasher1` + type Hasher1: StorageHasher; + // The same as `StorageDoubleMap::Key1` + type Key1: FullCodec; + // The same as `StorageDoubleMap::Hasher2` + type Hasher2: StorageHasher; + // The same as `StorageDoubleMap::Key2` + type Key2: FullCodec; + // The same as `StorageDoubleMap::Value` + type Value: FullCodec; + + /// This is a copy of the + /// `frame_support::storage::generator::StorageDoubleMap::storage_double_map_final_key`. + /// + /// We're using it because to call `storage_double_map_final_key` directly, we need access + /// to the runtime and pallet instance, which (sometimes) is impossible. + fn final_key(pallet_prefix: &str, key1: &Self::Key1, key2: &Self::Key2) -> StorageKey { + let key1_hashed = Self::Hasher1::hash(&key1.encode()); + let key2_hashed = Self::Hasher2::hash(&key2.encode()); + let pallet_prefix_hashed = frame_support::Twox128::hash(pallet_prefix.as_bytes()); + let storage_prefix_hashed = frame_support::Twox128::hash(Self::MAP_NAME.as_bytes()); + + let mut final_key = Vec::with_capacity( + pallet_prefix_hashed.len() + + storage_prefix_hashed.len() + + key1_hashed.as_ref().len() + + key2_hashed.as_ref().len(), + ); + + final_key.extend_from_slice(&pallet_prefix_hashed[..]); + final_key.extend_from_slice(&storage_prefix_hashed[..]); + final_key.extend_from_slice(key1_hashed.as_ref()); + final_key.extend_from_slice(key2_hashed.as_ref()); + + StorageKey(final_key) + } +} + /// Error generated by the `OwnedBridgeModule` trait. #[derive(Encode, Decode, TypeInfo, PalletError)] pub enum OwnedBridgeModuleError { diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index e5309bb54eab8..9ba16b76f2493 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -25,7 +25,7 @@ use crate::{ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; -use bp_runtime::HeaderIdProvider; +use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider}; use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; @@ -380,6 +380,24 @@ impl Client { .transpose() } + /// Read `DoubleMapStorage` value from runtime storage. + pub async fn storage_double_map_value( + &self, + pallet_prefix: &str, + key1: &T::Key1, + key2: &T::Key2, + block_hash: Option, + ) -> Result> { + let storage_key = T::final_key(pallet_prefix, key1, key2); + + self.raw_storage_value(storage_key, block_hash) + .await? + .map(|encoded_value| { + T::Value::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed) + }) + .transpose() + } + /// Read raw value from runtime storage. pub async fn raw_storage_value( &self, diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 43168f2c85248..b34cbc2eb1e61 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -25,10 +25,9 @@ use crate::{ use async_trait::async_trait; use bp_parachains::{ - best_parachain_head_hash_storage_key_at_target, imported_parachain_head_storage_key_at_target, - BestParaHeadHash, + best_parachain_head_hash_storage_key_at_target, BestParaHeadHash, ImportedParaHeadsKeyProvider, }; -use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderIdProvider; use codec::{Decode, Encode}; use parachains_relay::{ @@ -131,14 +130,14 @@ where let best_para_head_hash: Option = self.client.storage_value(best_para_head_hash_key, Some(at_block.1)).await?; if let (Some(metrics), &Some(ref best_para_head_hash)) = (metrics, &best_para_head_hash) { - let imported_para_head_key = imported_parachain_head_storage_key_at_target( - P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, - para_id, - best_para_head_hash.head_hash, - ); - let imported_para_header = self + let imported_para_head = self .client - .storage_value::(imported_para_head_key, Some(at_block.1)) + .storage_double_map_value::( + P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, + ¶_id, + &best_para_head_hash.head_hash, + Some(at_block.1), + ) .await? .and_then(|h| match HeaderOf::::decode(&mut &h.0[..]) { Ok(header) => Some(header), @@ -154,9 +153,9 @@ where None }, }); - if let Some(imported_para_header) = imported_para_header { + if let Some(imported_para_head) = imported_para_head { metrics - .update_best_parachain_block_at_target(para_id, *imported_para_header.number()); + .update_best_parachain_block_at_target(para_id, *imported_para_head.number()); } } From f6e9e4e74c22aad1f719167b485841649fabad66 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 26 Jul 2022 23:32:10 +0300 Subject: [PATCH 0745/1210] Log error instead of returning it Log error when `best_parachain_block_at_target` can't be updated instead of propagating it. Signed-off-by: Serban Iorga --- .../src/parachains/target.rs | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index b34cbc2eb1e61..c2c1498eea0d0 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -138,21 +138,25 @@ where &best_para_head_hash.head_hash, Some(at_block.1), ) - .await? - .and_then(|h| match HeaderOf::::decode(&mut &h.0[..]) { - Ok(header) => Some(header), - Err(e) => { - log::error!( - target: "bridge-metrics", - "Failed to decode {} parachain header at {}: {:?}. Metric will have obsolete value", - P::SourceParachain::NAME, - P::TargetChain::NAME, - e, - ); - - None - }, - }); + .await + .and_then(|maybe_encoded_head| match maybe_encoded_head { + Some(encoded_head) => + HeaderOf::::decode(&mut &encoded_head.0[..]) + .map(|head| Some(head)) + .map_err(Self::Error::ResponseParseFailed), + None => Ok(None), + }) + .map_err(|e| { + log::error!( + target: "bridge-metrics", + "Failed to read or decode {} parachain header at {}: {:?}. Metric will have obsolete value", + P::SourceParachain::NAME, + P::TargetChain::NAME, + e, + ); + e + }) + .unwrap_or(None); if let Some(imported_para_head) = imported_para_head { metrics .update_best_parachain_block_at_target(para_id, *imported_para_head.number()); From 77fbc2c7dc42f3bc5d949f99c919cddf1cf706a6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 27 Jul 2022 15:15:07 +0300 Subject: [PATCH 0746/1210] Send messages using xcm pallet (#1518) * send messages using xcm pallet * XcmBridge && XcmBridgeAdapter + (untested) config in RialtoParachain * impl encode_send_xcm for the rest * remove duplicate code * some fixes * cleanup * some more tests * cleanup * cleanup * send Rialto -> Millau messages using bridge-messages pallet * fmt * some clippy fixes * more clippy --- bin/millau/runtime/src/lib.rs | 1 + bin/millau/runtime/src/rialto_messages.rs | 4 +- .../runtime/src/rialto_parachain_messages.rs | 4 +- bin/millau/runtime/src/xcm_config.rs | 135 +++++++++--------- bin/rialto-parachain/runtime/src/lib.rs | 113 ++++++++++++++- .../runtime/src/millau_messages.rs | 21 ++- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/xcm_config.rs | 84 ++++------- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages.rs | 108 +++++++++++++- modules/messages/src/lib.rs | 30 ++-- relays/bin-substrate/Cargo.toml | 3 + relays/bin-substrate/src/chains/millau.rs | 37 +++++ relays/bin-substrate/src/chains/rialto.rs | 22 +++ .../src/chains/rialto_parachain.rs | 24 ++++ .../bin-substrate/src/cli/encode_message.rs | 8 +- relays/bin-substrate/src/cli/send_message.rs | 33 +++-- 17 files changed, 476 insertions(+), 154 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index fc2f19b945889..97f49c2f6ffc8 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -88,6 +88,7 @@ pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_bridge_parachains::Call as BridgeParachainsCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; +pub use pallet_xcm::Call as XcmCall; use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages; #[cfg(any(feature = "std", test))] diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index da44bcf8f8feb..ccca4222f61d7 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -37,6 +37,8 @@ use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; +/// Default lane that is used to send messages to Rialto. +pub const DEFAULT_XCM_LANE_TO_RIALTO: LaneId = [0, 0, 0, 0]; /// Initial value of `RialtoToMillauConversionRate` parameter. pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); @@ -149,7 +151,7 @@ impl messages::ThisChainWithMessages for Millau { }, } - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + *lane == DEFAULT_XCM_LANE_TO_RIALTO || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index ef1dac57d8385..6840b703f4f4d 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -38,6 +38,8 @@ use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; +/// Default lane that is used to send messages to Rialto parachain. +pub const DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN: LaneId = [0, 0, 0, 0]; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. @@ -138,7 +140,7 @@ impl messages::ThisChainWithMessages for Millau { >; fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + *lane == DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 5ba8d97e65e6d..19fb68b66265b 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -17,22 +17,22 @@ //! XCM configurations for the Millau runtime. use super::{ - rialto_messages::WithRialtoMessageBridge, AccountId, AllPalletsWithSystem, Balances, - BridgeRialtoMessages, Call, Event, Origin, Runtime, XcmPallet, + rialto_messages::{WithRialtoMessageBridge, DEFAULT_XCM_LANE_TO_RIALTO}, + rialto_parachain_messages::{ + WithRialtoParachainMessageBridge, DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN, + }, + AccountId, AllPalletsWithSystem, Balances, Call, Event, Origin, Runtime, + WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmPallet, }; -use bp_messages::source_chain::MessagesBridge; -use bp_millau::{Balance, WeightToFee}; -use bridge_runtime_common::messages::{ - source::{estimate_message_dispatch_and_delivery_fee, FromThisChainMessagePayload}, - MessageBridge, -}; -use codec::Encode; +use bp_messages::LaneId; +use bp_millau::WeightToFee; +use bp_rialto_parachain::RIALTO_PARACHAIN_ID; +use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; use frame_support::{ parameter_types, traits::{Everything, Nothing}, weights::Weight, }; -use sp_std::marker::PhantomData; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, @@ -49,6 +49,8 @@ parameter_types! { pub const ThisNetwork: NetworkId = Kusama; /// The Rialto network ID, associated with Polkadot. pub const RialtoNetwork: NetworkId = Polkadot; + /// The RialtoParachain network ID, associated with Westend. + pub const RialtoParachainNetwork: NetworkId = Westend; /// Our XCM location ancestry - i.e. our location within the Consensus Universe. /// @@ -105,7 +107,9 @@ parameter_types! { /// individual routers. pub type XcmRouter = ( // Router to send messages to Rialto. - ToRialtoBridge, + XcmBridgeAdapter, + // Router to send messages to RialtoParachains. + XcmBridgeAdapter, ); parameter_types! { @@ -189,60 +193,56 @@ impl pallet_xcm::Config for Runtime { type MaxLockers = frame_support::traits::ConstU32<8>; } -/// With-rialto bridge. -pub struct ToRialtoBridge(PhantomData); - -impl> SendXcm - for ToRialtoBridge -{ - type Ticket = (Balance, FromThisChainMessagePayload); - - fn validate( - dest: &mut Option, - msg: &mut Option>, - ) -> SendResult { - let d = dest.take().ok_or(SendError::MissingArgument)?; - if !matches!(d, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == RialtoNetwork::get()) - { - *dest = Some(d); - return Err(SendError::NotApplicable) - }; +/// With-Rialto bridge. +pub struct ToRialtoBridge; + +impl XcmBridge for ToRialtoBridge { + type MessageBridge = WithRialtoMessageBridge; + type MessageSender = pallet_bridge_messages::Pallet; + + fn universal_location() -> InteriorMultiLocation { + UniversalLocation::get() + } + + fn verify_destination(dest: &MultiLocation) -> bool { + matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == RialtoNetwork::get()) + } + fn build_destination() -> MultiLocation { let dest: InteriorMultiLocation = RialtoNetwork::get().into(); let here = UniversalLocation::get(); - let route = dest.relative_to(&here); - let msg = (route, msg.take().unwrap()).encode(); + dest.relative_to(&here) + } - let fee = estimate_message_dispatch_and_delivery_fee::( - &msg, - WithRialtoMessageBridge::RELAYER_FEE_PERCENT, - None, - ) - .map_err(SendError::Transport)?; - let fee_assets = MultiAssets::from((Here, fee)); + fn xcm_lane() -> LaneId { + DEFAULT_XCM_LANE_TO_RIALTO + } +} + +/// With-RialtoParachain bridge. +pub struct ToRialtoParachainBridge; + +impl XcmBridge for ToRialtoParachainBridge { + type MessageBridge = WithRialtoParachainMessageBridge; + type MessageSender = + pallet_bridge_messages::Pallet; - Ok(((fee, msg), fee_assets)) + fn universal_location() -> InteriorMultiLocation { + UniversalLocation::get() } - fn deliver(ticket: Self::Ticket) -> Result { - let lane = [0, 0, 0, 0]; - let (fee, msg) = ticket; - let result = MB::send_message( - pallet_xcm::Origin::from(MultiLocation::from(UniversalLocation::get())).into(), - lane, - msg, - fee, - ); - result - .map(|artifacts| { - let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); - log::debug!(target: "runtime::bridge", "Sent XCM message {:?}/{} to Millau: {:?}", lane, artifacts.nonce, hash); - hash - }) - .map_err(|e| { - log::debug!(target: "runtime::bridge", "Failed to send XCM message over lane {:?} to Millau: {:?}", lane, e); - SendError::Transport("Bridge has rejected the message") - }) + fn verify_destination(dest: &MultiLocation) -> bool { + matches!(*dest, MultiLocation { parents: 1, interior: X2(GlobalConsensus(r), Parachain(RIALTO_PARACHAIN_ID)) } if r == RialtoNetwork::get()) + } + + fn build_destination() -> MultiLocation { + let dest: InteriorMultiLocation = RialtoParachainNetwork::get().into(); + let here = UniversalLocation::get(); + dest.relative_to(&here) + } + + fn xcm_lane() -> LaneId { + DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN } } @@ -255,6 +255,7 @@ mod tests { }; use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + use codec::Encode; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -263,17 +264,23 @@ mod tests { } #[test] - fn xcm_messages_to_rialto_are_sent() { + fn xcm_messages_are_sent_using_bridge_router() { new_test_ext().execute_with(|| { - // the encoded message (origin ++ xcm) is 0x010109020419A8 - let dest = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))); let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - - let send_result = send_xcm::(dest.into(), xcm); let expected_fee = MultiAssets::from((Here, 4_345_002_552_u64)); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - assert_eq!(send_result, Ok((expected_hash, expected_fee)),); + + // message 1 to Rialto + let dest = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))); + let send_result = send_xcm::(dest.into(), xcm.clone()); + assert_eq!(send_result, Ok((expected_hash, expected_fee.clone()))); + + // message 2 to RialtoParachain (expected hash is the same, since other lane is used) + let dest = + (Parent, X2(GlobalConsensus(RialtoNetwork::get()), Parachain(RIALTO_PARACHAIN_ID))); + let send_result = send_xcm::(dest.into(), xcm); + assert_eq!(send_result, Ok((expected_hash, expected_fee))); }) } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index c52504c1950e5..9f9a37b45775f 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -26,10 +26,13 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; +use crate::millau_messages::{ + ToMillauMessagePayload, WithMillauMessageBridge, DEFAULT_XCM_LANE_TO_MILLAU, +}; use bridge_runtime_common::messages::{ - source::estimate_message_dispatch_and_delivery_fee, MessageBridge, + source::{estimate_message_dispatch_and_delivery_fee, XcmBridge, XcmBridgeAdapter}, + MessageBridge, }; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -71,6 +74,7 @@ pub use bp_rialto_parachain::{ pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; pub use pallet_bridge_messages::Call as MessagesCall; +pub use pallet_xcm::Call as XcmCall; // Polkadot & XCM imports use pallet_xcm::XcmPassthrough; @@ -302,6 +306,10 @@ parameter_types! { pub const RelayNetwork: NetworkId = NetworkId::Polkadot; pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); + /// The Millau network ID, associated with Kusama. + pub const MillauNetwork: NetworkId = Kusama; + /// The RialtoParachain network ID, associated with Westend. + pub const ThisNetwork: NetworkId = Westend; } /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used @@ -417,12 +425,36 @@ pub type LocalOriginToLocation = SignedToAccountId32, - // ..and XCMP to communicate with the sibling chains. - XcmpQueue, + // Bridge is used to communicate with other relay chain (Millau). + XcmBridgeAdapter, ); +/// With-Millau bridge. +pub struct ToMillauBridge; + +impl XcmBridge for ToMillauBridge { + type MessageBridge = WithMillauMessageBridge; + type MessageSender = pallet_bridge_messages::Pallet; + + fn universal_location() -> InteriorMultiLocation { + UniversalLocation::get() + } + + fn verify_destination(dest: &MultiLocation) -> bool { + matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) + } + + fn build_destination() -> MultiLocation { + let dest: InteriorMultiLocation = MillauNetwork::get().into(); + let here = UniversalLocation::get(); + dest.relative_to(&here) + } + + fn xcm_lane() -> bp_messages::LaneId { + DEFAULT_XCM_LANE_TO_MILLAU + } +} + impl pallet_xcm::Config for Runtime { type Event = Event; type SendXcmOrigin = EnsureXcmOrigin; @@ -800,3 +832,72 @@ cumulus_pallet_parachain_system::register_validate_block!( BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, CheckInherents = CheckInherents, ); + +#[cfg(test)] +mod tests { + use super::*; + use bp_messages::{ + target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, + MessageKey, + }; + use bp_runtime::messages::MessageDispatchResult; + use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + use codec::Encode; + + fn new_test_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::new( + frame_system::GenesisConfig::default().build_storage::().unwrap(), + ) + } + + #[test] + fn xcm_messages_to_millau_are_sent() { + new_test_ext().execute_with(|| { + // the encoded message (origin ++ xcm) is 0x010109020419A8 + let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); + let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); + + let send_result = send_xcm::(dest.into(), xcm); + let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(4_345_002_552_u128))); + let expected_hash = + ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); + assert_eq!(send_result, Ok((expected_hash, expected_fee)),); + }) + } + + #[test] + fn xcm_messages_from_millau_are_dispatched() { + type XcmExecutor = xcm_executor::XcmExecutor; + type MessageDispatcher = FromBridgedChainMessageDispatch< + WithMillauMessageBridge, + XcmExecutor, + XcmWeigher, + frame_support::traits::ConstU64, + >; + + new_test_ext().execute_with(|| { + let location: MultiLocation = + (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); + let xcm: Xcm = vec![Instruction::Trap(42)].into(); + + let mut incoming_message = DispatchMessage { + key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, + data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, + }; + + let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, 1_000_000_000); + + let dispatch_result = + MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert_eq!( + dispatch_result, + MessageDispatchResult { + dispatch_result: true, + unspent_weight: 0, + dispatch_fee_paid_during_dispatch: false, + } + ); + }) + } +} diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 248ec7b834d41..136b4343c190f 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -19,7 +19,7 @@ // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // Should be extracted to a separate crate and reused here. -use crate::Runtime; +use crate::{OriginCaller, Runtime}; use bp_messages::{ source_chain::{SenderOrigin, TargetHeaderChain}, @@ -40,6 +40,8 @@ use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; +/// Default lane that is used to send messages to Millau. +pub const DEFAULT_XCM_LANE_TO_MILLAU: LaneId = [0, 0, 0, 0]; /// Initial value of `MillauToRialtoParachainConversionRate` parameter. pub const INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE: FixedU128 = FixedU128::from_inner(FixedU128::DIV); @@ -137,7 +139,22 @@ impl messages::ThisChainWithMessages for RialtoParachain { >; fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { - send_origin.linked_account().is_some() && (*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1]) + let here_location = xcm::v3::MultiLocation::from(crate::UniversalLocation::get()); + match send_origin.caller { + OriginCaller::PolkadotXcm(pallet_xcm::Origin::Xcm(ref location)) + if *location == here_location => + { + log::trace!(target: "runtime::bridge", "Verifying message sent using XCM pallet to Millau"); + }, + _ => { + // keep in mind that in this case all messages are free (in term of fees) + // => it's just to keep testing bridge on our test deployments until we'll have a + // better option + log::trace!(target: "runtime::bridge", "Verifying message sent using messages pallet to Millau"); + }, + } + + *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index f0bc0982e69cb..9f0708ce9fd81 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -73,6 +73,7 @@ pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall; pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; +pub use pallet_xcm::Call as XcmCall; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 8a230101f3065..63b2d0bead0f0 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -17,22 +17,16 @@ //! XCM configurations for the Rialto runtime. use super::{ - millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, - BridgeMillauMessages, Call, Event, Origin, Runtime, XcmPallet, + millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, Call, + Event, Origin, Runtime, WithMillauMessagesInstance, XcmPallet, }; -use bp_messages::source_chain::MessagesBridge; -use bp_rialto::{Balance, WeightToFee}; -use bridge_runtime_common::messages::{ - source::{estimate_message_dispatch_and_delivery_fee, FromThisChainMessagePayload}, - MessageBridge, -}; -use codec::Encode; +use bp_rialto::WeightToFee; +use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; use frame_support::{ parameter_types, traits::{Everything, Nothing}, weights::Weight, }; -use sp_std::marker::PhantomData; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, @@ -105,7 +99,7 @@ parameter_types! { /// individual routers. pub type XcmRouter = ( // Router to send messages to Millau. - ToMillauBridge, + XcmBridgeAdapter, ); parameter_types! { @@ -189,60 +183,29 @@ impl pallet_xcm::Config for Runtime { type MaxLockers = frame_support::traits::ConstU32<8>; } -/// With-rialto bridge. -pub struct ToMillauBridge(PhantomData); - -impl> SendXcm - for ToMillauBridge -{ - type Ticket = (Balance, FromThisChainMessagePayload); - - fn validate( - dest: &mut Option, - msg: &mut Option>, - ) -> SendResult { - let d = dest.take().ok_or(SendError::MissingArgument)?; - if !matches!(d, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) - { - *dest = Some(d); - return Err(SendError::NotApplicable) - }; +/// With-Millau bridge. +pub struct ToMillauBridge; - let dest: InteriorMultiLocation = MillauNetwork::get().into(); - let here = UniversalLocation::get(); - let route = dest.relative_to(&here); - let msg = (route, msg.take().unwrap()).encode(); +impl XcmBridge for ToMillauBridge { + type MessageBridge = WithMillauMessageBridge; + type MessageSender = pallet_bridge_messages::Pallet; - let fee = estimate_message_dispatch_and_delivery_fee::( - &msg, - WithMillauMessageBridge::RELAYER_FEE_PERCENT, - None, - ) - .map_err(SendError::Transport)?; - let fee_assets = MultiAssets::from((Here, fee)); + fn universal_location() -> InteriorMultiLocation { + UniversalLocation::get() + } - Ok(((fee, msg), fee_assets)) + fn verify_destination(dest: &MultiLocation) -> bool { + matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) + } + + fn build_destination() -> MultiLocation { + let dest: InteriorMultiLocation = MillauNetwork::get().into(); + let here = UniversalLocation::get(); + dest.relative_to(&here) } - fn deliver(ticket: Self::Ticket) -> Result { - let lane = [0, 0, 0, 0]; - let (fee, msg) = ticket; - let result = MB::send_message( - pallet_xcm::Origin::from(MultiLocation::from(UniversalLocation::get())).into(), - lane, - msg, - fee, - ); - result - .map(|artifacts| { - let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); - log::debug!(target: "runtime::bridge", "Sent XCM message {:?}/{} to Rialto: {:?}", lane, artifacts.nonce, hash); - hash - }) - .map_err(|e| { - log::debug!(target: "runtime::bridge", "Failed to send XCM message over lane {:?} to Rialto: {:?}", lane, e); - SendError::Transport("Bridge has rejected the message") - }) + fn xcm_lane() -> bp_messages::LaneId { + [0, 0, 0, 0] } } @@ -255,6 +218,7 @@ mod tests { }; use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + use codec::Encode; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index cb9f37fe66c42..121ef318fbb08 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -41,6 +41,7 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master # Polkadot dependencies +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } @@ -65,6 +66,7 @@ std = [ "pallet-bridge-messages/std", "pallet-bridge-parachains/std", "pallet-transaction-payment/std", + "pallet-xcm/std", "scale-info/std", "sp-api/std", "sp-core/std", diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 8153e0840cf5c..ef0722a80bce5 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -37,6 +37,7 @@ use sp_runtime::{ }; use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; use sp_trie::StorageProof; +use xcm::latest::prelude::*; /// Bidirectional message bridge. pub trait MessageBridge { @@ -524,6 +525,111 @@ pub mod source { Ok((lane, inbound_lane_data)) } + + /// XCM bridge. + pub trait XcmBridge { + /// Runtime message bridge configuration. + type MessageBridge: MessageBridge; + /// Runtime message sender adapter. + type MessageSender: bp_messages::source_chain::MessagesBridge< + OriginOf>, + AccountIdOf>, + BalanceOf>, + FromThisChainMessagePayload, + >; + + /// Our location within the Consensus Universe. + fn universal_location() -> InteriorMultiLocation; + /// Verify that the adapter is responsible for handling given XCM destination. + fn verify_destination(dest: &MultiLocation) -> bool; + /// Build route from this chain to the XCM destination. + fn build_destination() -> MultiLocation; + /// Return message lane used to deliver XCM messages. + fn xcm_lane() -> LaneId; + } + + /// XCM bridge adapter for `bridge-messages` pallet. + pub struct XcmBridgeAdapter(PhantomData); + + impl SendXcm for XcmBridgeAdapter + where + BalanceOf>: Into, + OriginOf>: From, + { + type Ticket = (BalanceOf>, FromThisChainMessagePayload); + + fn validate( + dest: &mut Option, + msg: &mut Option>, + ) -> SendResult { + let d = dest.take().ok_or(SendError::MissingArgument)?; + if !T::verify_destination(&d) { + *dest = Some(d); + return Err(SendError::NotApplicable) + } + + let route = T::build_destination(); + let msg = (route, msg.take().unwrap()).encode(); + + let fee = estimate_message_dispatch_and_delivery_fee::( + &msg, + T::MessageBridge::RELAYER_FEE_PERCENT, + None, + ); + let fee = match fee { + Ok(fee) => fee, + Err(e) => { + log::trace!( + target: "runtime::bridge", + "Failed to comupte fee for XCM message to {:?}: {:?}", + T::MessageBridge::BRIDGED_CHAIN_ID, + e, + ); + *dest = Some(d); + return Err(SendError::Transport(e)) + }, + }; + let fee_assets = MultiAssets::from((Here, fee)); + + Ok(((fee, msg), fee_assets)) + } + + fn deliver(ticket: Self::Ticket) -> Result { + use bp_messages::source_chain::MessagesBridge; + + let lane = T::xcm_lane(); + let (fee, msg) = ticket; + let result = T::MessageSender::send_message( + pallet_xcm::Origin::from(MultiLocation::from(T::universal_location())).into(), + lane, + msg, + fee, + ); + result + .map(|artifacts| { + let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); + log::debug!( + target: "runtime::bridge", + "Sent XCM message {:?}/{} to {:?}: {:?}", + lane, + artifacts.nonce, + T::MessageBridge::BRIDGED_CHAIN_ID, + hash, + ); + hash + }) + .map_err(|e| { + log::debug!( + target: "runtime::bridge", + "Failed to send XCM message over lane {:?} to {:?}: {:?}", + lane, + T::MessageBridge::BRIDGED_CHAIN_ID, + e, + ); + SendError::Transport("Bridge has rejected the message") + }) + } + } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages. @@ -641,8 +747,6 @@ pub mod target { _relayer_account: &AccountIdOf>, message: DispatchMessage>>, ) -> MessageDispatchResult { - use xcm::latest::*; - let message_id = (message.key.lane_id, message.key.nonce); let do_dispatch = move || -> sp_std::result::Result { let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } = diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 48ca546def8c1..9806a264c9946 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -812,7 +812,7 @@ fn send_message, I: 'static>( // the most lightweigh check is the message size check ensure!( - payload.size() < T::MaximalOutboundPayloadSize::get(), + payload.size() <= T::MaximalOutboundPayloadSize::get(), Error::::MessageIsTooLarge, ); @@ -1109,12 +1109,12 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, message_payload, run_test, unrewarded_relayer, Event as TestEvent, Origin, - TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, - TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, - TestOnMessageAccepted, TestRuntime, TokenConversionRate, MAX_OUTBOUND_PAYLOAD_SIZE, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, - TEST_RELAYER_B, + message, message_payload, run_test, unrewarded_relayer, Balance, Event as TestEvent, + Origin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, + TestMessagesParameter, TestMessagesProof, TestOnDeliveryConfirmed1, + TestOnDeliveryConfirmed2, TestOnMessageAccepted, TestRuntime, TokenConversionRate, + MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, + TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -1456,11 +1456,23 @@ mod tests { Pallet::::send_message( Origin::signed(1), TEST_LANE_ID, - message_payload, - 0, + message_payload.clone(), + Balance::MAX, ), Error::::MessageIsTooLarge, ); + + // let's check that we're able to send `MAX_OUTBOUND_PAYLOAD_SIZE` messages + while message_payload.size() > MAX_OUTBOUND_PAYLOAD_SIZE { + message_payload.extra.pop(); + } + assert_eq!(message_payload.size(), MAX_OUTBOUND_PAYLOAD_SIZE); + assert_ok!(Pallet::::send_message( + Origin::signed(1), + TEST_LANE_ID, + message_payload, + Balance::MAX, + ),); }) } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index ead0f664c073e..63ccb4f918e29 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -60,10 +60,13 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master # Polkadot Dependencies +#pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } + [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 4b31e423ac02b..2cf0258d4325c 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -22,12 +22,49 @@ use crate::cli::{ CliChain, }; use bp_messages::LaneId; +use bp_rialto_parachain::RIALTO_PARACHAIN_ID; use bp_runtime::EncodedOrDecodedCall; use relay_millau_client::Millau; use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; +use xcm::latest::prelude::*; impl CliEncodeMessage for Millau { + fn encode_send_xcm( + message: xcm::VersionedXcm<()>, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::MILLAU_TO_RIALTO_INDEX => { + let dest = + (Parent, X1(GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()))); + millau_runtime::Call::XcmPallet(millau_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), + }) + .into() + }, + bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => { + let dest = ( + Parent, + X2( + GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()), + Parachain(RIALTO_PARACHAIN_ID), + ), + ); + millau_runtime::Call::XcmPallet(millau_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), + }) + .into() + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }) + } + fn encode_send_message_call( lane: LaneId, payload: RawMessage, diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 0255a055a5742..2753a917ad24a 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -26,8 +26,30 @@ use bp_runtime::EncodedOrDecodedCall; use relay_rialto_client::Rialto; use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; +use xcm::latest::prelude::*; impl CliEncodeMessage for Rialto { + fn encode_send_xcm( + message: xcm::VersionedXcm<()>, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::RIALTO_TO_MILLAU_INDEX => { + let dest = + (Parent, X1(GlobalConsensus(rialto_runtime::xcm_config::MillauNetwork::get()))); + rialto_runtime::Call::XcmPallet(rialto_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), + }) + .into() + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }) + } + fn encode_send_message_call( lane: LaneId, payload: RawMessage, diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 63322351d6d0e..09edeaecea02b 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -26,8 +26,32 @@ use bp_runtime::EncodedOrDecodedCall; use relay_rialto_parachain_client::RialtoParachain; use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; +use xcm::latest::prelude::*; impl CliEncodeMessage for RialtoParachain { + fn encode_send_xcm( + message: xcm::VersionedXcm<()>, + bridge_instance_index: u8, + ) -> anyhow::Result> { + Ok(match bridge_instance_index { + bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => { + let dest = + (Parent, X1(GlobalConsensus(rialto_parachain_runtime::MillauNetwork::get()))); + rialto_parachain_runtime::Call::PolkadotXcm( + rialto_parachain_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), + }, + ) + .into() + }, + _ => anyhow::bail!( + "Unsupported target bridge pallet with instance index: {}", + bridge_instance_index + ), + }) + } + fn encode_send_message_call( lane: LaneId, payload: RawMessage, diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index ad6070fdb0f9f..9f9ef37ff0eaa 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -42,7 +42,13 @@ pub enum Message { pub type RawMessage = Vec; pub trait CliEncodeMessage: Chain { - /// Encode a send message call. + /// Encode a send XCM call of the XCM pallet. + fn encode_send_xcm( + message: xcm::VersionedXcm<()>, + bridge_instance_index: u8, + ) -> anyhow::Result>; + + /// Encode a send message call of the bridge-messages pallet. fn encode_send_message_call( lane: LaneId, message: RawMessage, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 2e4e3628b0b42..11625c3b8ea2a 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -24,13 +24,13 @@ use crate::{ cli::{ bridge::{FullBridge, MessagesCliBridge}, chain_schema::*, - encode_message::{self, CliEncodeMessage}, + encode_message::{self, CliEncodeMessage, RawMessage}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, Balance, CliChain, HexBytes, HexLaneId, }, }; use async_trait::async_trait; -use codec::Encode; +use codec::{Decode, Encode}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainBase, SignParam, TransactionSignScheme, UnsignedTransaction, @@ -70,6 +70,10 @@ pub struct SendMessage { source: SourceConnectionParams, #[structopt(flatten)] source_sign: SourceSigningParams, + /// Send message using XCM pallet instead. By default message is sent using + /// bridge messages pallet. + #[structopt(long)] + use_xcm_pallet: bool, /// Hex-encoded lane id. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, @@ -124,12 +128,19 @@ where ), }; let payload_len = payload.encode().len(); - let send_message_call = Self::Source::encode_send_message_call( - data.lane.0, - payload, - fee.cast().into(), - data.bridge.bridge_instance_index(), - )?; + let send_message_call = if data.use_xcm_pallet { + Self::Source::encode_send_xcm( + decode_xcm(payload)?, + data.bridge.bridge_instance_index(), + )? + } else { + Self::Source::encode_send_message_call( + data.lane.0, + payload, + fee.cast().into(), + data.bridge.bridge_instance_index(), + )? + }; let source_genesis_hash = *source_client.genesis_hash(); let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; @@ -210,6 +221,12 @@ impl SendMessage { } } +/// Decode SCALE encoded raw XCM message. +fn decode_xcm(message: RawMessage) -> anyhow::Result> { + Decode::decode(&mut &message[..]) + .map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e)) +} + #[cfg(test)] mod tests { use super::*; From 51090b98fcb9298cc488c5b6dd05a40a01da74d2 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 28 Jul 2022 12:17:04 +0300 Subject: [PATCH 0747/1210] Small cosmetic changes Signed-off-by: Serban Iorga --- bin/millau/runtime/src/lib.rs | 3 +- .../src/on_demand/parachains.rs | 52 +++++++------------ 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 97f49c2f6ffc8..468c596b02e18 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -847,11 +847,10 @@ impl_runtime_apis! { fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> { // the parachains finality pallet is never decoding parachain heads, so it is // only done in the integration code - use bp_rialto_parachain::RIALTO_PARACHAIN_ID; let encoded_head = pallet_bridge_parachains::Pallet::< Runtime, WithRialtoParachainsInstance, - >::best_parachain_head(RIALTO_PARACHAIN_ID.into())?; + >::best_parachain_head(bp_rialto_parachain::RIALTO_PARACHAIN_ID.into())?; let head = bp_rialto_parachain::Header::decode(&mut &encoded_head.0[..]).ok()?; Some((*head.number(), head.hash())) } diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 77d80bc79b3be..8300bf74cd6c2 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -433,42 +433,30 @@ where ParaNumber: Copy + PartialOrd + Zero, RelayNumber: Copy + Debug + Ord, { - // this switch is responsible for processing `RelayingRelayHeader` state - match state { - RelayState::Idle | RelayState::RelayingParaHeader(_) => (), - RelayState::RelayingRelayHeader(relay_header_number) => { - if data.relay_header_at_target < relay_header_number { - // required relay header hasn't yet been relayed - return RelayState::RelayingRelayHeader(relay_header_number) - } - - // we may switch to `RelayingParaHeader` if parachain head is available - if let Some(para_header_at_relay_header_at_target) = - data.para_header_at_relay_header_at_target.clone() - { - state = RelayState::RelayingParaHeader(para_header_at_relay_header_at_target); - } else { - // otherwise, we'd need to restart (this may happen only if parachain has been - // deregistered) - state = RelayState::Idle; - } - }, + // Process the `RelayingRelayHeader` state. + if let &RelayState::RelayingRelayHeader(relay_header_number) = &state { + if data.relay_header_at_target < relay_header_number { + // The required relay header hasn't yet been relayed. Ask / wait for it. + return state + } + + // We may switch to `RelayingParaHeader` if parachain head is available. + state = data + .para_header_at_relay_header_at_target + .clone() + .map_or(RelayState::Idle, RelayState::RelayingParaHeader); } - // this switch is responsible for processing `RelayingParaHeader` state - let para_header_at_target_or_zero = data.para_header_at_target.unwrap_or_else(Zero::zero); - match state { - RelayState::Idle => (), - RelayState::RelayingRelayHeader(_) => unreachable!("processed by previous match; qed"), - RelayState::RelayingParaHeader(para_header_id) => { - if para_header_at_target_or_zero < para_header_id.0 { - // parachain header hasn't yet been relayed - return RelayState::RelayingParaHeader(para_header_id) - } - }, + // Process the `RelayingParaHeader` state. + if let RelayState::RelayingParaHeader(para_header_id) = &state { + let para_header_at_target_or_zero = data.para_header_at_target.unwrap_or_else(Zero::zero); + if para_header_at_target_or_zero < para_header_id.0 { + // The required parachain header hasn't yet been relayed. Ask / wait for it. + return state + } } - // if we haven't read para head from the source, we can't yet do anyhting + // if we haven't read para head from the source, we can't yet do anything let para_header_at_source = match data.para_header_at_source { Some(ref para_header_at_source) => para_header_at_source.clone(), None => return RelayState::Idle, From 03830ef25626b2c3078a99984dc404eda5685a68 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 28 Jul 2022 15:18:40 +0300 Subject: [PATCH 0748/1210] Change Runtime APIs best_finalized() signature Change Runtime APIs best_finalized() signature to return Option Signed-off-by: Serban Iorga --- bin/millau/runtime/src/lib.rs | 21 +++++++++---------- bin/rialto-parachain/runtime/src/lib.rs | 5 +++-- bin/rialto/runtime/src/lib.rs | 5 +++-- primitives/chain-kusama/src/lib.rs | 2 +- primitives/chain-millau/src/lib.rs | 2 +- primitives/chain-polkadot/src/lib.rs | 2 +- primitives/chain-rialto-parachain/src/lib.rs | 2 +- primitives/chain-rialto/src/lib.rs | 2 +- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-westend/src/lib.rs | 4 ++-- primitives/chain-wococo/src/lib.rs | 2 +- primitives/runtime/src/lib.rs | 2 +- .../src/messages_source.rs | 16 ++++++-------- .../src/parachains/target.rs | 15 +++++++------ 14 files changed, 39 insertions(+), 43 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 468c596b02e18..59f2a08177c62 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -40,6 +40,7 @@ use crate::{ }; use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; +use bp_runtime::{HeaderId, HeaderIdProvider}; use bridge_runtime_common::messages::{ source::estimate_message_dispatch_and_delivery_fee, MessageBridge, }; @@ -56,9 +57,7 @@ use sp_mmr_primitives::{ }; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{ - Block as BlockT, Header as HeaderT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys, - }, + traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, }; @@ -818,19 +817,19 @@ impl_runtime_apis! { } impl bp_rialto::RialtoFinalityApi for Runtime { - fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> { - BridgeRialtoGrandpa::best_finalized().map(|header| (header.number, header.hash())) + fn best_finalized() -> Option> { + BridgeRialtoGrandpa::best_finalized().map(|header| header.id()) } } impl bp_westend::WestendFinalityApi for Runtime { - fn best_finalized() -> Option<(bp_westend::BlockNumber, bp_westend::Hash)> { - BridgeWestendGrandpa::best_finalized().map(|header| (header.number, header.hash())) + fn best_finalized() -> Option> { + BridgeWestendGrandpa::best_finalized().map(|header| header.id()) } } impl bp_westend::WestmintFinalityApi for Runtime { - fn best_finalized() -> Option<(bp_westend::BlockNumber, bp_westend::Hash)> { + fn best_finalized() -> Option> { // the parachains finality pallet is never decoding parachain heads, so it is // only done in the integration code use bp_westend::WESTMINT_PARACHAIN_ID; @@ -839,12 +838,12 @@ impl_runtime_apis! { WithWestendParachainsInstance, >::best_parachain_head(WESTMINT_PARACHAIN_ID.into())?; let head = bp_westend::Header::decode(&mut &encoded_head.0[..]).ok()?; - Some((*head.number(), head.hash())) + Some(head.id()) } } impl bp_rialto_parachain::RialtoParachainFinalityApi for Runtime { - fn best_finalized() -> Option<(bp_rialto::BlockNumber, bp_rialto::Hash)> { + fn best_finalized() -> Option> { // the parachains finality pallet is never decoding parachain heads, so it is // only done in the integration code let encoded_head = pallet_bridge_parachains::Pallet::< @@ -852,7 +851,7 @@ impl_runtime_apis! { WithRialtoParachainsInstance, >::best_parachain_head(bp_rialto_parachain::RIALTO_PARACHAIN_ID.into())?; let head = bp_rialto_parachain::Header::decode(&mut &encoded_head.0[..]).ok()?; - Some((*head.number(), head.hash())) + Some(head.id()) } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 9f9a37b45775f..e96268d8aa8ca 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -49,6 +49,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. +use bp_runtime::{HeaderId, HeaderIdProvider}; pub use frame_support::{ construct_runtime, match_types, parameter_types, traits::{Everything, IsInVec, Nothing, Randomness}, @@ -727,8 +728,8 @@ impl_runtime_apis! { } impl bp_millau::MillauFinalityApi for Runtime { - fn best_finalized() -> Option<(bp_millau::BlockNumber, bp_millau::Hash)> { - BridgeMillauGrandpa::best_finalized().map(|header| (header.number, header.hash())) + fn best_finalized() -> Option> { + BridgeMillauGrandpa::best_finalized().map(|header| header.id()) } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9f0708ce9fd81..56cbca221d456 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -35,6 +35,7 @@ pub mod xcm_config; use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; +use bp_runtime::{HeaderId, HeaderIdProvider}; use bridge_runtime_common::messages::{ source::estimate_message_dispatch_and_delivery_fee, MessageBridge, }; @@ -653,8 +654,8 @@ impl_runtime_apis! { } impl bp_millau::MillauFinalityApi for Runtime { - fn best_finalized() -> Option<(bp_millau::BlockNumber, bp_millau::Hash)> { - BridgeMillauGrandpa::best_finalized().map(|header| (header.number, header.hash())) + fn best_finalized() -> Option> { + BridgeMillauGrandpa::best_finalized().map(|header| header.id()) } } diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index f3450a77dcbff..a72e607ddb29e 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -110,7 +110,7 @@ sp_api::decl_runtime_apis! { /// Kusama runtime itself. pub trait KusamaFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to Kusama chain. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 6bdd9c53ee133..71a545e6ba7bf 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -274,7 +274,7 @@ sp_api::decl_runtime_apis! { /// Millau runtime itself. pub trait MillauFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to Millau chain. diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index af195e511c4c8..2fcfa1f03e883 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -111,7 +111,7 @@ sp_api::decl_runtime_apis! { /// Polkadot runtime itself. pub trait PolkadotFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to Polkadot chain. diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 00402ae49d2f6..baef2e403b498 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -216,7 +216,7 @@ sp_api::decl_runtime_apis! { /// RialtoParachain runtime itself. pub trait RialtoParachainFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to RialtoParachain chain. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index e5d1abbc7e630..d242f6dc4ac57 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -237,7 +237,7 @@ sp_api::decl_runtime_apis! { /// Rialto runtime itself. pub trait RialtoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to Rialto chain. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index ad3190a12235f..45f1937eee58a 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -106,7 +106,7 @@ sp_api::decl_runtime_apis! { /// Rococo runtime itself. pub trait RococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to Rococo chain. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 16c0252ea77ac..e0ac5ad961f7b 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -104,7 +104,7 @@ sp_api::decl_runtime_apis! { /// Westend runtime itself. pub trait WestendFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// API for querying information about the finalized Westmint headers. @@ -113,7 +113,7 @@ sp_api::decl_runtime_apis! { /// Westmint runtime itself. pub trait WestmintFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 83d913db7fc13..02276aa7dd865 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -63,7 +63,7 @@ sp_api::decl_runtime_apis! { /// Wococo runtime itself. pub trait WococoFinalityApi { /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option<(BlockNumber, Hash)>; + fn best_finalized() -> Option>; } /// Outbound message lane API for messages that are sent to Wococo chain. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index ae7250c49bdf6..a51327e89b802 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -82,7 +82,7 @@ pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/root"; /// Generic header Id. -#[derive(RuntimeDebug, Default, Clone, Copy, Eq, Hash, PartialEq)] +#[derive(RuntimeDebug, Default, Clone, Encode, Decode, Copy, Eq, Hash, PartialEq)] pub struct HeaderId(pub Number, pub Hash); /// Generic header id provider. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 6647376d93516..95a3feab0c11a 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -562,17 +562,13 @@ where Some(at_self_hash), ) .await?; - let decoded_best_finalized_peer_on_self = - Option::<(BlockNumberOf, HashOf)>::decode( - &mut &encoded_best_finalized_peer_on_self.0[..], - ) - .map_err(SubstrateError::ResponseParseFailed)? - .map(Ok) - .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))?; - let peer_on_self_best_finalized_id = - HeaderId(decoded_best_finalized_peer_on_self.0, decoded_best_finalized_peer_on_self.1); - Ok(peer_on_self_best_finalized_id) + Option::, BlockNumberOf>>::decode( + &mut &encoded_best_finalized_peer_on_self.0[..], + ) + .map_err(SubstrateError::ResponseParseFailed)? + .map(Ok) + .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized)) } fn make_message_details_map( diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index c2c1498eea0d0..a96c0ba0ab692 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -107,14 +107,13 @@ where Some(at_block.1), ) .await?; - let decoded_best_finalized_source_block = - Option::<(BlockNumberOf, HashOf)>::decode( - &mut &encoded_best_finalized_source_block.0[..], - ) - .map_err(SubstrateError::ResponseParseFailed)? - .map(Ok) - .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized))?; - Ok(HeaderId(decoded_best_finalized_source_block.0, decoded_best_finalized_source_block.1)) + + Option::, BlockNumberOf>>::decode( + &mut &encoded_best_finalized_source_block.0[..], + ) + .map_err(SubstrateError::ResponseParseFailed)? + .map(Ok) + .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized)) } async fn parachain_head( From e3ccbab1e7c115731425cf5792d36d6fd6c3cbc4 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 29 Jul 2022 16:08:48 +0300 Subject: [PATCH 0749/1210] Remove unneeded error conversion (#1527) --- relays/lib-substrate-relay/src/finality/target.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index d04fe280e5a2f..f9859937ff342 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -56,9 +56,7 @@ impl SubstrateFinalityTarget

{ return Err(Error::BridgePalletIsHalted) } - let is_initialized = P::FinalityEngine::is_initialized(&self.client) - .await - .map_err(|e| Error::Custom(e.to_string()))?; + let is_initialized = P::FinalityEngine::is_initialized(&self.client).await?; if !is_initialized { return Err(Error::BridgePalletIsNotInitialized) } From 74834ad7f936d490e29b3638edfdc8575ad8a5da Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 Aug 2022 09:07:13 +0300 Subject: [PATCH 0750/1210] refund relayer if parachain head has not been updated (#1528) --- modules/parachains/src/lib.rs | 33 ++++++++++++++++++++++----- modules/parachains/src/weights_ext.rs | 11 +++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 3cf0e60e3cdf8..33338433e3bfe 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -238,6 +238,7 @@ pub mod pallet { ¶chain_heads_proof, parachains.len() as _, ); + pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( relay_block_hash, sp_trie::StorageProof::new(parachain_heads_proof.0), @@ -293,7 +294,7 @@ pub mod pallet { continue; } - let prune_happened: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { + let update_result: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { let artifacts = Pallet::::update_parachain_head( parachain, stored_best_head.take(), @@ -305,7 +306,14 @@ pub mod pallet { Ok(artifacts.prune_happened) }); - if matches!(prune_happened, Err(_) | Ok(false)) { + // we're refunding weight if update has not happened and if pruning has not happened + let is_update_happened = matches!(update_result, Ok(_)); + if !is_update_happened { + actual_weight = actual_weight + .saturating_sub(WeightInfoOf::::parachain_head_storage_write_weight(T::DbWeight::get())); + } + let is_prune_happened = matches!(update_result, Ok(true)); + if !is_prune_happened { actual_weight = actual_weight .saturating_sub(WeightInfoOf::::parachain_head_pruning_weight(T::DbWeight::get())); } @@ -538,6 +546,8 @@ mod tests { }; type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; + type WeightInfo = ::WeightInfo; + type DbWeight = ::DbWeight; fn initialize(state_root: RelayBlockHash) { pallet_bridge_grandpa::Pallet::::initialize( @@ -675,12 +685,16 @@ mod tests { initialize(state_root); // we're trying to update heads of parachains 1, 2 and 3 - assert_ok!(Pallet::::submit_parachain_heads( + let expected_weight = + WeightInfo::submit_parachain_heads_weight(DbWeight::get(), &proof, 2); + let result = Pallet::::submit_parachain_heads( Origin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, - ),); + ); + assert_ok!(result); + assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); // but only 1 and 2 are updated, because proof is missing head of parachain#2 assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); @@ -768,13 +782,20 @@ mod tests { run_test(|| { // start with relay block #0 and try to import head#5 of parachain#1 and untracked // parachain + let expected_weight = + WeightInfo::submit_parachain_heads_weight(DbWeight::get(), &proof, 3) + .saturating_sub(WeightInfo::parachain_head_storage_write_weight( + DbWeight::get(), + )); initialize(state_root); - assert_ok!(Pallet::::submit_parachain_heads( + let result = Pallet::::submit_parachain_heads( Origin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, - )); + ); + assert_ok!(result); + assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); assert_eq!( BestParaHeads::::get(ParaId(1)), Some(BestParaHead { diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs index f345762dad9c8..98655a6ea4702 100644 --- a/modules/parachains/src/weights_ext.rs +++ b/modules/parachains/src/weights_ext.rs @@ -68,6 +68,17 @@ pub trait WeightInfoExt: WeightInfo { base_weight.saturating_add(proof_size_overhead).saturating_add(pruning_weight) } + /// Returns weight of single parachain head storage update. + /// + /// This weight only includes db write operations that happens if parachain head is actually + /// updated. All extra weights (weight of storage proof validation, additional checks, ...) is + /// not included. + fn parachain_head_storage_write_weight(db_weight: RuntimeDbWeight) -> Weight { + // it's just a couple of operations - we need to write the hash (`ImportedParaHashes`) and + // the head itself (`ImportedParaHeads`. Pruning is not included here + db_weight.writes(2) + } + /// Returns weight of single parachain head pruning. fn parachain_head_pruning_weight(db_weight: RuntimeDbWeight) -> Weight { // it's just one write operation, we don't want any benchmarks for that From e02bdec26ab6f60aa735730941015d7c88cd289f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 Aug 2022 09:17:46 +0300 Subject: [PATCH 0751/1210] fix truncated doc (#1529) --- relays/parachains/src/parachains_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 795d07b8440ec..3c7ac85913947 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -383,7 +383,7 @@ where }, (ParaHashAtSource::Some(_), Some(_)) => { // this is normal case when relay has recently updated heads, when parachain is - // not progressing or when our source client is + // not progressing, or when our source client is still syncing false }, (ParaHashAtSource::Some(_), None) => { From d8ec611aba9f55ec55dfa781d6512969142ce832 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 Aug 2022 14:30:09 +0300 Subject: [PATCH 0752/1210] Bump jsonrpsee (#1530) * switch to jsonrpsee 0.15 * use client_bounds marker --- relays/client-substrate/Cargo.toml | 2 +- relays/client-substrate/src/client.rs | 242 +++++--------------------- relays/client-substrate/src/rpc.rs | 31 ++-- 3 files changed, 65 insertions(+), 210 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 658755958be8e..91fd8eb10a0e7 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -10,7 +10,7 @@ async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.7" -jsonrpsee = { version = "0.8", features = ["macros", "ws-client"] } +jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } log = "0.4.11" num-traits = "0.2" rand = "0.7" diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 9ba16b76f2493..ee2b0048fed96 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -19,8 +19,7 @@ use crate::{ chain::{Chain, ChainWithBalances, TransactionStatusOf}, rpc::SubstrateClient, - AccountIdOf, BlockNumberOf, ConnectionParams, Error, HashOf, HeaderIdOf, HeaderOf, IndexOf, - Result, + ConnectionParams, Error, HashOf, HeaderIdOf, Result, }; use async_std::sync::{Arc, Mutex}; @@ -154,15 +153,8 @@ impl Client { let genesis_hash_client = client.clone(); let genesis_hash = tokio .spawn(async move { - SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_block_hash(&*genesis_hash_client, Some(number)) - .await + SubstrateClient::::chain_get_block_hash(&*genesis_hash_client, Some(number)) + .await }) .await??; @@ -220,15 +212,7 @@ impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { self.jsonrpsee_execute(|client| async move { - let health = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::system_health(&*client) - .await?; + let health = SubstrateClient::::system_health(&*client).await?; let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); if is_synced { Ok(()) @@ -247,15 +231,7 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { self.jsonrpsee_execute(|client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_finalized_head(&*client) - .await?) + Ok(SubstrateClient::::chain_get_finalized_head(&*client).await?) }) .await } @@ -276,15 +252,7 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(|client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_header(&*client, None) - .await?) + Ok(SubstrateClient::::chain_get_header(&*client, None).await?) }) .await } @@ -292,15 +260,7 @@ impl Client { /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_block(&*client, block_hash) - .await?) + Ok(SubstrateClient::::chain_get_block(&*client, block_hash).await?) }) .await } @@ -311,15 +271,7 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_header(&*client, Some(block_hash)) - .await?) + Ok(SubstrateClient::::chain_get_header(&*client, Some(block_hash)).await?) }) .await } @@ -327,15 +279,7 @@ impl Client { /// Get a Substrate block hash by its number. pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::chain_get_block_hash(&*client, Some(number)) - .await?) + Ok(SubstrateClient::::chain_get_block_hash(&*client, Some(number)).await?) }) .await } @@ -353,15 +297,7 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_runtime_version(&*client) - .await?) + Ok(SubstrateClient::::state_runtime_version(&*client).await?) }) .await } @@ -405,15 +341,7 @@ impl Client { block_hash: Option, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_get_storage(&*client, storage_key, block_hash) - .await?) + Ok(SubstrateClient::::state_get_storage(&*client, storage_key, block_hash).await?) }) .await } @@ -425,16 +353,10 @@ impl Client { { self.jsonrpsee_execute(move |client| async move { let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_get_storage(&*client, storage_key, None) - .await? - .ok_or(Error::AccountDoesNotExist)?; + let encoded_account_data = + SubstrateClient::::state_get_storage(&*client, storage_key, None) + .await? + .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = AccountInfo::>::decode( &mut &encoded_account_data.0[..], ) @@ -449,15 +371,7 @@ impl Client { /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::system_account_next_index(&*client, account) - .await?) + Ok(SubstrateClient::::system_account_next_index(&*client, account).await?) }) .await } @@ -467,19 +381,12 @@ impl Client { /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { self.jsonrpsee_execute(move |client| async move { - let tx_hash = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::author_submit_extrinsic(&*client, transaction) - .await - .map_err(|e| { - log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); - e - })?; + let tx_hash = SubstrateClient::::author_submit_extrinsic(&*client, transaction) + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) @@ -511,19 +418,12 @@ impl Client { self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::author_submit_extrinsic(&*client, extrinsic) - .await - .map_err(|e| { - log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); - e - })?; + let tx_hash = SubstrateClient::::author_submit_extrinsic(&*client, extrinsic) + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) @@ -574,15 +474,7 @@ impl Client { /// Returns pending extrinsics from transaction pool. pub async fn pending_extrinsics(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::author_pending_extrinsics(&*client) - .await?) + Ok(SubstrateClient::::author_pending_extrinsics(&*client).await?) }) .await } @@ -597,15 +489,8 @@ impl Client { let call = SUB_API_TXPOOL_VALIDATE_TRANSACTION.to_string(); let data = Bytes((TransactionSource::External, transaction, at_block).encode()); - let encoded_response = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_call(&*client, call, data, Some(at_block)) - .await?; + let encoded_response = + SubstrateClient::::state_call(&*client, call, data, Some(at_block)).await?; let validity = TransactionValidity::decode(&mut &encoded_response.0[..]) .map_err(Error::ResponseParseFailed)?; @@ -620,15 +505,9 @@ impl Client { transaction: Bytes, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - let fee_details = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::payment_query_fee_details(&*client, transaction, None) - .await?; + let fee_details = + SubstrateClient::::payment_query_fee_details(&*client, transaction, None) + .await?; let inclusion_fee = fee_details .inclusion_fee .map(|inclusion_fee| InclusionFee { @@ -660,15 +539,8 @@ impl Client { let call = SUB_API_GRANDPA_AUTHORITIES.to_string(); let data = Bytes(Vec::new()); - let encoded_response = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_call(&*client, call, data, Some(block)) - .await?; + let encoded_response = + SubstrateClient::::state_call(&*client, call, data, Some(block)).await?; let authority_list = encoded_response.0; Ok(authority_list) @@ -684,16 +556,9 @@ impl Client { at_block: Option, ) -> Result { self.jsonrpsee_execute(move |client| async move { - SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_call(&*client, method, data, at_block) - .await - .map_err(Into::into) + SubstrateClient::::state_call(&*client, method, data, at_block) + .await + .map_err(Into::into) }) .await } @@ -705,19 +570,12 @@ impl Client { at_block: C::Hash, ) -> Result { self.jsonrpsee_execute(move |client| async move { - SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::state_prove_storage(&*client, keys, Some(at_block)) - .await - .map(|proof| { - StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect::>()) - }) - .map_err(Into::into) + SubstrateClient::::state_prove_storage(&*client, keys, Some(at_block)) + .await + .map(|proof| { + StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect::>()) + }) + .map_err(Into::into) }) .await } @@ -725,15 +583,7 @@ impl Client { /// Return `tokenDecimals` property from the set of chain properties. pub async fn token_decimals(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - let system_properties = SubstrateClient::< - AccountIdOf, - BlockNumberOf, - HashOf, - HeaderOf, - IndexOf, - C::SignedBlock, - >::system_properties(&*client) - .await?; + let system_properties = SubstrateClient::::system_properties(&*client).await?; Ok(system_properties.get("tokenDecimals").and_then(|v| v.as_u64())) }) .await diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index a0172d1e55013..37c84b7d28f1f 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -16,6 +16,8 @@ //! The most generic Substrate node RPC interface. +use crate::Chain; + use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use pallet_transaction_payment_rpc_runtime_api::FeeDetails; use sc_rpc_api::{state::ReadProof, system::Health}; @@ -26,24 +28,27 @@ use sp_core::{ use sp_rpc::number::NumberOrHex; use sp_version::RuntimeVersion; -#[rpc(client)] -pub(crate) trait Substrate { +#[rpc(client, client_bounds(C: Chain))] +pub(crate) trait Substrate { #[method(name = "system_health", param_kind = array)] async fn system_health(&self) -> RpcResult; #[method(name = "system_properties", param_kind = array)] async fn system_properties(&self) -> RpcResult; #[method(name = "chain_getHeader", param_kind = array)] - async fn chain_get_header(&self, block_hash: Option) -> RpcResult

; + async fn chain_get_header(&self, block_hash: Option) -> RpcResult; #[method(name = "chain_getFinalizedHead", param_kind = array)] - async fn chain_get_finalized_head(&self) -> RpcResult; + async fn chain_get_finalized_head(&self) -> RpcResult; #[method(name = "chain_getBlock", param_kind = array)] - async fn chain_get_block(&self, block_hash: Option) -> RpcResult; + async fn chain_get_block(&self, block_hash: Option) -> RpcResult; #[method(name = "chain_getBlockHash", param_kind = array)] - async fn chain_get_block_hash(&self, block_number: Option) -> RpcResult; + async fn chain_get_block_hash( + &self, + block_number: Option, + ) -> RpcResult; #[method(name = "system_accountNextIndex", param_kind = array)] - async fn system_account_next_index(&self, account_id: AccountId) -> RpcResult; + async fn system_account_next_index(&self, account_id: C::AccountId) -> RpcResult; #[method(name = "author_submitExtrinsic", param_kind = array)] - async fn author_submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; + async fn author_submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; #[method(name = "author_pendingExtrinsics", param_kind = array)] async fn author_pending_extrinsics(&self) -> RpcResult>; #[method(name = "state_call", param_kind = array)] @@ -51,26 +56,26 @@ pub(crate) trait Substrate, + at_block: Option, ) -> RpcResult; #[method(name = "state_getStorage", param_kind = array)] async fn state_get_storage( &self, key: StorageKey, - at_block: Option, + at_block: Option, ) -> RpcResult>; #[method(name = "state_getReadProof", param_kind = array)] async fn state_prove_storage( &self, keys: Vec, - hash: Option, - ) -> RpcResult>; + hash: Option, + ) -> RpcResult>; #[method(name = "state_getRuntimeVersion", param_kind = array)] async fn state_runtime_version(&self) -> RpcResult; #[method(name = "payment_queryFeeDetails", param_kind = array)] async fn payment_query_fee_details( &self, extrinsic: Bytes, - at_block: Option, + at_block: Option, ) -> RpcResult>; } From 7c14ec340768aa2f8a93c5e9cf7c9b7b3f526537 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 2 Aug 2022 12:49:08 +0300 Subject: [PATCH 0753/1210] Follow-up on #1419 (#1531) * Parachains source cosmetic changes - Make `ParaHashAtSource` more generic - Modify `on_chain_parachain_header` to return `HeaderId` - Shortening variable names Signed-off-by: Serban Iorga * Change ParachainsSource::max_head_id type Change ParachainsSource::max_head_id to Arc> Signed-off-by: Serban Iorga * code review changes --- primitives/runtime/src/lib.rs | 4 +- .../bin-substrate/src/cli/relay_parachains.rs | 11 ++- .../src/finality/source.rs | 5 +- .../src/on_demand/parachains.rs | 22 +++--- .../src/parachains/source.rs | 76 ++++++++----------- relays/parachains/src/parachains_loop.rs | 74 +++++++++--------- 6 files changed, 91 insertions(+), 101 deletions(-) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a51327e89b802..a7e3e44626ad0 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -82,7 +82,9 @@ pub const ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-derivation/root"; /// Generic header Id. -#[derive(RuntimeDebug, Default, Clone, Encode, Decode, Copy, Eq, Hash, PartialEq)] +#[derive( + RuntimeDebug, Default, Clone, Encode, Decode, Copy, Eq, Hash, PartialEq, PartialOrd, Ord, +)] pub struct HeaderId(pub Number, pub Hash); /// Generic header id provider. diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 2fa6dcaf9eb4b..09251972587da 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -18,10 +18,14 @@ use crate::chains::{ rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, westend_parachains_to_millau::WestmintToMillauCliBridge, }; +use async_std::sync::Mutex; use async_trait::async_trait; use bp_polkadot_core::parachains::ParaId; -use parachains_relay::parachains_loop::{ParachainSyncParams, SourceClient, TargetClient}; +use parachains_relay::parachains_loop::{ + AvailableHeader, ParachainSyncParams, SourceClient, TargetClient, +}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; +use std::sync::Arc; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ @@ -65,7 +69,10 @@ where { async fn relay_headers(data: RelayParachains) -> anyhow::Result<()> { let source_client = data.source.into_client::().await?; - let source_client = ParachainsSource::::new(source_client, None); + let source_client = ParachainsSource::::new( + source_client, + Arc::new(Mutex::new(AvailableHeader::Missing)), + ); let target_transaction_params = TransactionParams { signer: data.target_sign.to_keypair::()?, diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index d0acb7717682f..c8360bbddbc57 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -27,7 +27,6 @@ use relay_substrate_client::{ BlockNumberOf, BlockWithJustification, Chain, Client, Error, HeaderOf, }; use relay_utils::relay_loop::Client as RelayClient; -use sp_runtime::traits::Header as HeaderT; use std::pin::Pin; /// Shared updatable reference to the maximal header number that we want to sync from the source. @@ -76,9 +75,7 @@ impl SubstrateFinalitySource

{ ) -> Result, Error> { // we **CAN** continue to relay finality proofs if source node is out of sync, because // target node may be missing proofs that are already available at the source - let finalized_header_hash = self.client.best_finalized_header_hash().await?; - let finalized_header = self.client.header_by_hash(finalized_header_hash).await?; - Ok(*finalized_header.number()) + self.client.best_finalized_header_number().await } } diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 8300bf74cd6c2..dc400115502eb 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -36,7 +36,7 @@ use bp_runtime::HeaderIdProvider; use futures::{select, FutureExt}; use num_traits::Zero; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use parachains_relay::parachains_loop::{ParachainSyncParams, TargetClient}; +use parachains_relay::parachains_loop::{AvailableHeader, ParachainSyncParams, TargetClient}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, TransactionSignScheme, @@ -143,7 +143,7 @@ async fn background_task( let mut relay_state = RelayState::Idle; let mut required_parachain_header_number = Zero::zero(); - let required_para_header_number_ref = Arc::new(Mutex::new(None)); + let required_para_header_number_ref = Arc::new(Mutex::new(AvailableHeader::Unavailable)); let mut restart_relay = true; let parachains_relay_task = futures::future::Fuse::terminated(); @@ -151,7 +151,7 @@ async fn background_task( let mut parachains_source = ParachainsSource::

::new( source_relay_client.clone(), - Some(required_para_header_number_ref.clone()), + required_para_header_number_ref.clone(), ); let mut parachains_target = ParachainsTarget::

::new(target_client.clone(), target_transaction_params.clone()); @@ -253,7 +253,8 @@ async fn background_task( .await; }, RelayState::RelayingParaHeader(required_para_header) => { - *required_para_header_number_ref.lock().await = Some(required_para_header); + *required_para_header_number_ref.lock().await = + AvailableHeader::Available(required_para_header); }, } @@ -389,13 +390,9 @@ where source.client().best_finalized_header().await.map_err(map_source_err)?; let best_finalized_relay_block_id = best_finalized_relay_header.id(); let para_header_at_source = source - .on_chain_parachain_header( - best_finalized_relay_block_id, - P::SOURCE_PARACHAIN_PARA_ID.into(), - ) + .on_chain_para_head_id(best_finalized_relay_block_id, P::SOURCE_PARACHAIN_PARA_ID.into()) .await - .map_err(map_source_err)? - .map(|h| h.id()); + .map_err(map_source_err)?; let relay_header_at_source = best_finalized_relay_block_id.0; let relay_header_at_target = @@ -408,10 +405,9 @@ where .map_err(map_target_err)?; let para_header_at_relay_header_at_target = source - .on_chain_parachain_header(relay_header_at_target, P::SOURCE_PARACHAIN_PARA_ID.into()) + .on_chain_para_head_id(relay_header_at_target, P::SOURCE_PARACHAIN_PARA_ID.into()) .await - .map_err(map_source_err)? - .map(|h| h.id()); + .map_err(map_source_err)?; Ok(RelayData { required_para_header: required_header_number, diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index f763b744f192e..c23ac87947632 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -22,35 +22,35 @@ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use bp_runtime::HeaderIdProvider; use codec::Decode; use parachains_relay::{ - parachains_loop::{ParaHashAtSource, SourceClient}, + parachains_loop::{AvailableHeader, SourceClient}, parachains_loop_metrics::ParachainsLoopMetrics, }; use relay_substrate_client::{ Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, RelayChain, }; use relay_utils::relay_loop::Client as RelayClient; -use sp_runtime::traits::Header as HeaderT; /// Shared updatable reference to the maximal parachain header id that we want to sync from the /// source. -pub type RequiredHeaderIdRef = Arc>>>; +pub type RequiredHeaderIdRef = Arc>>>; /// Substrate client as parachain heads source. #[derive(Clone)] pub struct ParachainsSource { client: Client, - maximal_header_id: Option>, + max_head_id: RequiredHeaderIdRef, } impl ParachainsSource

{ /// Creates new parachains source client. pub fn new( client: Client, - maximal_header_id: Option>, + max_head_id: RequiredHeaderIdRef, ) -> Self { - ParachainsSource { client, maximal_header_id } + ParachainsSource { client, max_head_id } } /// Returns reference to the underlying RPC client. @@ -59,11 +59,11 @@ impl ParachainsSource

{ } /// Return decoded head of given parachain. - pub async fn on_chain_parachain_header( + pub async fn on_chain_para_head_id( &self, at_block: HeaderIdOf, para_id: ParaId, - ) -> Result>, SubstrateError> { + ) -> Result>, SubstrateError> { let storage_key = parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, para_id); let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?; @@ -72,8 +72,8 @@ impl ParachainsSource

{ Some(para_head) => para_head, None => return Ok(None), }; - - Ok(Some(Decode::decode(&mut ¶_head.0[..])?)) + let para_head: HeaderOf = Decode::decode(&mut ¶_head.0[..])?; + Ok(Some(para_head.id())) } } @@ -105,7 +105,7 @@ where at_block: HeaderIdOf, metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, - ) -> Result { + ) -> Result, Self::Error> { // we don't need to support many parachains now if para_id.0 != P::SOURCE_PARACHAIN_PARA_ID { return Err(SubstrateError::Custom(format!( @@ -115,44 +115,28 @@ where ))) } - let mut para_hash_at_source = ParaHashAtSource::None; - let mut para_header_number_at_source = None; - match self.on_chain_parachain_header(at_block, para_id).await? { - Some(parachain_header) => { - para_hash_at_source = ParaHashAtSource::Some(parachain_header.hash()); - para_header_number_at_source = Some(*parachain_header.number()); - // never return head that is larger than requested. This way we'll never sync - // headers past `maximal_header_id` - if let Some(ref maximal_header_id) = self.maximal_header_id { - let maximal_header_id = *maximal_header_id.lock().await; - match maximal_header_id { - Some(maximal_header_id) - if *parachain_header.number() > maximal_header_id.0 => - { - // we don't want this header yet => let's report previously requested - // header - para_hash_at_source = ParaHashAtSource::Some(maximal_header_id.1); - para_header_number_at_source = Some(maximal_header_id.0); - }, - Some(_) => (), - None => { - // on-demand relay has not yet asked us to sync anything let's do that - para_hash_at_source = ParaHashAtSource::Unavailable; - para_header_number_at_source = None; - }, - } - } - }, - None => {}, - }; + let mut para_head_id = AvailableHeader::Missing; + if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block, para_id).await? { + // Never return head that is larger than requested. This way we'll never sync + // headers past `max_header_id`. + para_head_id = match *self.max_head_id.lock().await { + AvailableHeader::Unavailable => AvailableHeader::Unavailable, + AvailableHeader::Missing => { + // `max_header_id` is not set. There is no limit. + AvailableHeader::Available(on_chain_para_head_id) + }, + AvailableHeader::Available(max_head_id) => { + // We report at most `max_header_id`. + AvailableHeader::Available(std::cmp::min(on_chain_para_head_id, max_head_id)) + }, + } + } - if let (Some(metrics), Some(para_header_number_at_source)) = - (metrics, para_header_number_at_source) - { - metrics.update_best_parachain_block_at_source(para_id, para_header_number_at_source); + if let (Some(metrics), AvailableHeader::Available(para_head_id)) = (metrics, para_head_id) { + metrics.update_best_parachain_block_at_source(para_id, para_head_id.0); } - Ok(para_hash_at_source) + Ok(para_head_id.map(|para_head_id| para_head_id.1)) } async fn prove_parachain_heads( diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 3c7ac85913947..f44f986d63231 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -52,29 +52,33 @@ pub enum ParachainSyncStrategy { All, } -/// Parachain head hash, available at the source (relay) chain. +/// Parachain header availability at a certain chain. #[derive(Clone, Copy, Debug)] -pub enum ParaHashAtSource { - /// There's no parachain head at the source chain. - /// - /// Normally it means that the parachain is not registered there. - None, - /// Parachain head with given hash is available at the source chain. - Some(ParaHash), - /// The source client refuses to report parachain head hash at this moment. +pub enum AvailableHeader { + /// The client refuses to report parachain head at this moment. /// /// It is a "mild" error, which may appear when e.g. on-demand parachains relay is used. /// This variant must be treated as "we don't want to update parachain head value at the /// target chain at this moment". Unavailable, + /// There's no parachain header at the relay chain. + /// + /// Normally it means that the parachain is not registered there. + Missing, + /// Parachain head with given hash is available at the source chain. + Available(T), } -impl ParaHashAtSource { - /// Return parachain head hash, if available. - pub fn hash(&self) -> Option<&ParaHash> { - match *self { - ParaHashAtSource::Some(ref para_hash) => Some(para_hash), - _ => None, +impl AvailableHeader { + /// Transform contained value. + pub fn map(self, f: F) -> AvailableHeader + where + F: FnOnce(T) -> U, + { + match self { + AvailableHeader::Unavailable => AvailableHeader::Unavailable, + AvailableHeader::Missing => AvailableHeader::Missing, + AvailableHeader::Available(val) => AvailableHeader::Available(f(val)), } } } @@ -94,7 +98,7 @@ pub trait SourceClient: RelayClient { at_block: HeaderIdOf, metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, - ) -> Result; + ) -> Result, Self::Error>; /// Get parachain heads proof. /// @@ -342,7 +346,7 @@ where /// Given heads at source and target clients, returns set of heads that are out of sync. fn select_parachains_to_update( - heads_at_source: BTreeMap, + heads_at_source: BTreeMap>, heads_at_target: BTreeMap>, best_finalized_relay_block: HeaderIdOf, ) -> Vec @@ -368,12 +372,12 @@ where .zip(heads_at_target.into_iter()) .filter(|((para, head_at_source), (_, head_at_target))| { let needs_update = match (head_at_source, head_at_target) { - (ParaHashAtSource::Unavailable, _) => { + (AvailableHeader::Unavailable, _) => { // source client has politely asked us not to update current parachain head // at the target chain false }, - (ParaHashAtSource::Some(head_at_source), Some(head_at_target)) + (AvailableHeader::Available(head_at_source), Some(head_at_target)) if head_at_target.at_relay_block_number < best_finalized_relay_block.0 && head_at_target.head_hash != *head_at_source => { @@ -381,22 +385,22 @@ where // client true }, - (ParaHashAtSource::Some(_), Some(_)) => { + (AvailableHeader::Available(_), Some(_)) => { // this is normal case when relay has recently updated heads, when parachain is // not progressing, or when our source client is still syncing false }, - (ParaHashAtSource::Some(_), None) => { + (AvailableHeader::Available(_), None) => { // parachain is not yet known to the target client. This is true when parachain // or bridge has been just onboarded/started true }, - (ParaHashAtSource::None, Some(_)) => { + (AvailableHeader::Missing, Some(_)) => { // parachain/parathread has been offboarded removed from the system. It needs to // be propageted to the target client true }, - (ParaHashAtSource::None, None) => { + (AvailableHeader::Missing, None) => { // all's good - parachain is unknown to both clients false }, @@ -435,7 +439,7 @@ async fn read_heads_at_source( metrics: Option<&ParachainsLoopMetrics>, at_relay_block: &HeaderIdOf, parachains: &[ParaId], -) -> Result, FailedClient> { +) -> Result>, FailedClient> { let mut para_head_hashes = BTreeMap::new(); for para in parachains { let para_head = source_client.parachain_head(*at_relay_block, metrics, *para).await; @@ -612,7 +616,7 @@ mod tests { #[derive(Clone, Debug)] struct TestClientData { source_sync_status: Result, - source_heads: BTreeMap>, + source_heads: BTreeMap, TestError>>, source_proofs: BTreeMap, TestError>>, target_best_block: Result, TestError>, @@ -627,7 +631,7 @@ mod tests { pub fn minimal() -> Self { TestClientData { source_sync_status: Ok(true), - source_heads: vec![(PARA_ID, Ok(ParaHashAtSource::Some(PARA_0_HASH)))] + source_heads: vec![(PARA_ID, Ok(AvailableHeader::Available(PARA_0_HASH)))] .into_iter() .collect(), source_proofs: vec![(PARA_ID, Ok(PARA_0_HASH.encode()))].into_iter().collect(), @@ -676,10 +680,10 @@ mod tests { _at_block: HeaderIdOf, _metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, - ) -> Result { + ) -> Result, TestError> { match self.data.lock().await.source_heads.get(¶_id.0).cloned() { Some(result) => result, - None => Ok(ParaHashAtSource::None), + None => Ok(AvailableHeader::Missing), } } @@ -988,7 +992,7 @@ mod tests { fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::None)].into_iter().collect(), + vec![(ParaId(PARA_ID), AvailableHeader::Missing)].into_iter().collect(), vec![(ParaId(PARA_ID), None)].into_iter().collect(), HeaderId(10, Default::default()), ), @@ -1000,7 +1004,7 @@ mod tests { fn parachain_is_not_updated_if_it_has_been_updated_at_better_relay_block() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_0_HASH))] + vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_0_HASH))] .into_iter() .collect(), vec![( @@ -1019,7 +1023,7 @@ mod tests { fn parachain_is_not_updated_if_hash_is_the_same_at_next_relay_block() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_0_HASH))] + vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_0_HASH))] .into_iter() .collect(), vec![( @@ -1038,7 +1042,7 @@ mod tests { fn parachain_is_updated_after_offboarding() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::None)].into_iter().collect(), + vec![(ParaId(PARA_ID), AvailableHeader::Missing)].into_iter().collect(), vec![( ParaId(PARA_ID), Some(BestParaHeadHash { @@ -1058,7 +1062,7 @@ mod tests { fn parachain_is_updated_after_onboarding() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_0_HASH))] + vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_0_HASH))] .into_iter() .collect(), vec![(ParaId(PARA_ID), None)].into_iter().collect(), @@ -1072,7 +1076,7 @@ mod tests { fn parachain_is_updated_if_newer_head_is_known() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::Some(PARA_1_HASH))] + vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_1_HASH))] .into_iter() .collect(), vec![( @@ -1091,7 +1095,7 @@ mod tests { fn parachain_is_not_updated_if_source_head_is_unavailable() { assert_eq!( select_parachains_to_update::( - vec![(ParaId(PARA_ID), ParaHashAtSource::Unavailable)].into_iter().collect(), + vec![(ParaId(PARA_ID), AvailableHeader::Unavailable)].into_iter().collect(), vec![( ParaId(PARA_ID), Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) From d7d20519122f4f918512f997f709165198ee1958 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 2 Aug 2022 13:40:41 +0300 Subject: [PATCH 0754/1210] Use jsonrpsee subscriptions (#1533) * splitted Substrate RPC trait * introduce subscription methods * removed commented code * removed commented code --- relays/client-substrate/src/client.rs | 83 ++++++++---------- relays/client-substrate/src/rpc.rs | 116 ++++++++++++++++++-------- 2 files changed, 119 insertions(+), 80 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index ee2b0048fed96..f1ddeeeb0f039 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -18,7 +18,11 @@ use crate::{ chain::{Chain, ChainWithBalances, TransactionStatusOf}, - rpc::SubstrateClient, + rpc::{ + SubstrateAuthorClient, SubstrateChainClient, SubstrateFrameSystemClient, + SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient, + SubstrateTransactionPaymentClient, + }, ConnectionParams, Error, HashOf, HeaderIdOf, Result, }; @@ -29,8 +33,7 @@ use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; use jsonrpsee::{ - core::{client::SubscriptionClientT, DeserializeOwned}, - types::params::ParamsSer, + core::DeserializeOwned, ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; use num_traits::{Bounded, Zero}; @@ -153,8 +156,7 @@ impl Client { let genesis_hash_client = client.clone(); let genesis_hash = tokio .spawn(async move { - SubstrateClient::::chain_get_block_hash(&*genesis_hash_client, Some(number)) - .await + SubstrateChainClient::::block_hash(&*genesis_hash_client, Some(number)).await }) .await??; @@ -212,7 +214,7 @@ impl Client { /// Returns true if client is connected to at least one peer and is in synced state. pub async fn ensure_synced(&self) -> Result<()> { self.jsonrpsee_execute(|client| async move { - let health = SubstrateClient::::system_health(&*client).await?; + let health = SubstrateSystemClient::::health(&*client).await?; let is_synced = !health.is_syncing && (!health.should_have_peers || health.peers > 0); if is_synced { Ok(()) @@ -231,7 +233,7 @@ impl Client { /// Return hash of the best finalized block. pub async fn best_finalized_header_hash(&self) -> Result { self.jsonrpsee_execute(|client| async move { - Ok(SubstrateClient::::chain_get_finalized_head(&*client).await?) + Ok(SubstrateChainClient::::finalized_head(&*client).await?) }) .await } @@ -252,7 +254,7 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(|client| async move { - Ok(SubstrateClient::::chain_get_header(&*client, None).await?) + Ok(SubstrateChainClient::::header(&*client, None).await?) }) .await } @@ -260,7 +262,7 @@ impl Client { /// Get a Substrate block from its hash. pub async fn get_block(&self, block_hash: Option) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::chain_get_block(&*client, block_hash).await?) + Ok(SubstrateChainClient::::block(&*client, block_hash).await?) }) .await } @@ -271,7 +273,7 @@ impl Client { C::Header: DeserializeOwned, { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::chain_get_header(&*client, Some(block_hash)).await?) + Ok(SubstrateChainClient::::header(&*client, Some(block_hash)).await?) }) .await } @@ -279,7 +281,7 @@ impl Client { /// Get a Substrate block hash by its number. pub async fn block_hash_by_number(&self, number: C::BlockNumber) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::chain_get_block_hash(&*client, Some(number)).await?) + Ok(SubstrateChainClient::::block_hash(&*client, Some(number)).await?) }) .await } @@ -297,7 +299,7 @@ impl Client { /// Return runtime version. pub async fn runtime_version(&self) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::state_runtime_version(&*client).await?) + Ok(SubstrateStateClient::::runtime_version(&*client).await?) }) .await } @@ -341,7 +343,7 @@ impl Client { block_hash: Option, ) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::state_get_storage(&*client, storage_key, block_hash).await?) + Ok(SubstrateStateClient::::storage(&*client, storage_key, block_hash).await?) }) .await } @@ -354,7 +356,7 @@ impl Client { self.jsonrpsee_execute(move |client| async move { let storage_key = C::account_info_storage_key(&account); let encoded_account_data = - SubstrateClient::::state_get_storage(&*client, storage_key, None) + SubstrateStateClient::::storage(&*client, storage_key, None) .await? .ok_or(Error::AccountDoesNotExist)?; let decoded_account_data = AccountInfo::>::decode( @@ -371,7 +373,7 @@ impl Client { /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. pub async fn next_account_index(&self, account: C::AccountId) -> Result { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::system_account_next_index(&*client, account).await?) + Ok(SubstrateFrameSystemClient::::account_next_index(&*client, account).await?) }) .await } @@ -381,7 +383,7 @@ impl Client { /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { self.jsonrpsee_execute(move |client| async move { - let tx_hash = SubstrateClient::::author_submit_extrinsic(&*client, transaction) + let tx_hash = SubstrateAuthorClient::::submit_extrinsic(&*client, transaction) .await .map_err(|e| { log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); @@ -418,12 +420,12 @@ impl Client { self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = SubstrateClient::::author_submit_extrinsic(&*client, extrinsic) + let tx_hash = SubstrateAuthorClient::::submit_extrinsic(&*client, extrinsic) .await .map_err(|e| { - log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); - e - })?; + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) @@ -445,18 +447,13 @@ impl Client { .jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; let tx_hash = C::Hasher::hash(&extrinsic.0); - let subscription = client - .subscribe( - "author_submitAndWatchExtrinsic", - Some(ParamsSer::Array(vec![jsonrpsee::core::to_json_value(extrinsic) - .map_err(|e| Error::RpcError(e.into()))?])), - "author_unwatchExtrinsic", - ) - .await - .map_err(|e| { - log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); - e - })?; + let subscription = + SubstrateAuthorClient::::submit_and_watch_extrinsic(&*client, extrinsic) + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(subscription) }) @@ -474,7 +471,7 @@ impl Client { /// Returns pending extrinsics from transaction pool. pub async fn pending_extrinsics(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateClient::::author_pending_extrinsics(&*client).await?) + Ok(SubstrateAuthorClient::::pending_extrinsics(&*client).await?) }) .await } @@ -490,7 +487,7 @@ impl Client { let data = Bytes((TransactionSource::External, transaction, at_block).encode()); let encoded_response = - SubstrateClient::::state_call(&*client, call, data, Some(at_block)).await?; + SubstrateStateClient::::call(&*client, call, data, Some(at_block)).await?; let validity = TransactionValidity::decode(&mut &encoded_response.0[..]) .map_err(Error::ResponseParseFailed)?; @@ -506,7 +503,7 @@ impl Client { ) -> Result> { self.jsonrpsee_execute(move |client| async move { let fee_details = - SubstrateClient::::payment_query_fee_details(&*client, transaction, None) + SubstrateTransactionPaymentClient::::fee_details(&*client, transaction, None) .await?; let inclusion_fee = fee_details .inclusion_fee @@ -540,7 +537,7 @@ impl Client { let data = Bytes(Vec::new()); let encoded_response = - SubstrateClient::::state_call(&*client, call, data, Some(block)).await?; + SubstrateStateClient::::call(&*client, call, data, Some(block)).await?; let authority_list = encoded_response.0; Ok(authority_list) @@ -556,7 +553,7 @@ impl Client { at_block: Option, ) -> Result { self.jsonrpsee_execute(move |client| async move { - SubstrateClient::::state_call(&*client, method, data, at_block) + SubstrateStateClient::::call(&*client, method, data, at_block) .await .map_err(Into::into) }) @@ -570,7 +567,7 @@ impl Client { at_block: C::Hash, ) -> Result { self.jsonrpsee_execute(move |client| async move { - SubstrateClient::::state_prove_storage(&*client, keys, Some(at_block)) + SubstrateStateClient::::prove_storage(&*client, keys, Some(at_block)) .await .map(|proof| { StorageProof::new(proof.proof.into_iter().map(|b| b.0).collect::>()) @@ -583,7 +580,7 @@ impl Client { /// Return `tokenDecimals` property from the set of chain properties. pub async fn token_decimals(&self) -> Result> { self.jsonrpsee_execute(move |client| async move { - let system_properties = SubstrateClient::::system_properties(&*client).await?; + let system_properties = SubstrateSystemClient::::properties(&*client).await?; Ok(system_properties.get("tokenDecimals").and_then(|v| v.as_u64())) }) .await @@ -593,13 +590,7 @@ impl Client { pub async fn subscribe_grandpa_justifications(&self) -> Result> { let subscription = self .jsonrpsee_execute(move |client| async move { - Ok(client - .subscribe( - "grandpa_subscribeJustifications", - None, - "grandpa_unsubscribeJustifications", - ) - .await?) + Ok(SubstrateGrandpaClient::::subscribe_justifications(&*client).await?) }) .await?; let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 37c84b7d28f1f..fdba424dd90fd 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -16,7 +16,7 @@ //! The most generic Substrate node RPC interface. -use crate::Chain; +use crate::{Chain, TransactionStatusOf}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use pallet_transaction_payment_rpc_runtime_api::FeeDetails; @@ -28,52 +28,100 @@ use sp_core::{ use sp_rpc::number::NumberOrHex; use sp_version::RuntimeVersion; -#[rpc(client, client_bounds(C: Chain))] -pub(crate) trait Substrate { - #[method(name = "system_health", param_kind = array)] - async fn system_health(&self) -> RpcResult; - #[method(name = "system_properties", param_kind = array)] - async fn system_properties(&self) -> RpcResult; - #[method(name = "chain_getHeader", param_kind = array)] - async fn chain_get_header(&self, block_hash: Option) -> RpcResult; - #[method(name = "chain_getFinalizedHead", param_kind = array)] - async fn chain_get_finalized_head(&self) -> RpcResult; - #[method(name = "chain_getBlock", param_kind = array)] - async fn chain_get_block(&self, block_hash: Option) -> RpcResult; - #[method(name = "chain_getBlockHash", param_kind = array)] - async fn chain_get_block_hash( - &self, - block_number: Option, - ) -> RpcResult; - #[method(name = "system_accountNextIndex", param_kind = array)] - async fn system_account_next_index(&self, account_id: C::AccountId) -> RpcResult; - #[method(name = "author_submitExtrinsic", param_kind = array)] - async fn author_submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; - #[method(name = "author_pendingExtrinsics", param_kind = array)] - async fn author_pending_extrinsics(&self) -> RpcResult>; - #[method(name = "state_call", param_kind = array)] - async fn state_call( +/// RPC methods of Substrate `system` namespace, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "system")] +pub(crate) trait SubstrateSystem { + /// Return node health. + #[method(name = "health")] + async fn health(&self) -> RpcResult; + /// Return system properties. + #[method(name = "properties")] + async fn properties(&self) -> RpcResult; +} + +/// RPC methods of Substrate `chain` namespace, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "chain")] +pub(crate) trait SubstrateChain { + /// Get block hash by its number. + #[method(name = "getBlockHash")] + async fn block_hash(&self, block_number: Option) -> RpcResult; + /// Return block header by its hash. + #[method(name = "getHeader")] + async fn header(&self, block_hash: Option) -> RpcResult; + /// Return best finalized block hash. + #[method(name = "getFinalizedHead")] + async fn finalized_head(&self) -> RpcResult; + /// Return signed block (with justifications) by its hash. + #[method(name = "getBlock")] + async fn block(&self, block_hash: Option) -> RpcResult; +} + +/// RPC methods of Substrate `author` namespace, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "author")] +pub(crate) trait SubstrateAuthor { + /// Submit extrinsic to the transaction pool. + #[method(name = "submitExtrinsic")] + async fn submit_extrinsic(&self, extrinsic: Bytes) -> RpcResult; + /// Return vector of pending extrinsics from the transaction pool. + #[method(name = "pendingExtrinsics")] + async fn pending_extrinsics(&self) -> RpcResult>; + /// Submit and watch for extrinsic state. + #[subscription(name = "submitAndWatchExtrinsic", unsubscribe = "unwatchExtrinsic", item = TransactionStatusOf)] + fn submit_and_watch_extrinsic(&self, extrinsic: Bytes); +} + +/// RPC methods of Substrate `state` namespace, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "state")] +pub(crate) trait SubstrateState { + /// Get current runtime version. + #[method(name = "getRuntimeVersion")] + async fn runtime_version(&self) -> RpcResult; + /// Call given runtime method. + #[method(name = "call")] + async fn call( &self, method: String, data: Bytes, at_block: Option, ) -> RpcResult; - #[method(name = "state_getStorage", param_kind = array)] - async fn state_get_storage( + /// Get value of the runtime storage. + #[method(name = "getStorage")] + async fn storage( &self, key: StorageKey, at_block: Option, ) -> RpcResult>; - #[method(name = "state_getReadProof", param_kind = array)] - async fn state_prove_storage( + /// Get proof of the runtime storage value. + #[method(name = "getReadProof")] + async fn prove_storage( &self, keys: Vec, hash: Option, ) -> RpcResult>; - #[method(name = "state_getRuntimeVersion", param_kind = array)] - async fn state_runtime_version(&self) -> RpcResult; - #[method(name = "payment_queryFeeDetails", param_kind = array)] - async fn payment_query_fee_details( +} + +/// RPC methods of Substrate `grandpa` namespace, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "grandpa")] +pub(crate) trait SubstrateGrandpa { + /// Subscribe to GRANDPA justifications. + #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] + fn subscribe_justifications(&self); +} + +/// RPC methods of Substrate `system` frame pallet, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "system")] +pub(crate) trait SubstrateFrameSystem { + /// Return index of next account transaction. + #[method(name = "accountNextIndex")] + async fn account_next_index(&self, account_id: C::AccountId) -> RpcResult; +} + +/// RPC methods of Substrate `pallet_transaction_payment` frame pallet, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "payment")] +pub(crate) trait SubstrateTransactionPayment { + /// Query transaction fee details. + #[method(name = "queryFeeDetails")] + async fn fee_details( &self, extrinsic: Bytes, at_block: Option, From 8e8ec0afe6e95cb318bfdbd93ecb5c582d843cfa Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 3 Aug 2022 14:10:23 +0300 Subject: [PATCH 0755/1210] [Complex Relayers] Deduplicate l2r and r2l logic (#1535) * [Complex Relayers] Deduplicate l2r and r2l logic Signed-off-by: Serban Iorga * Renamings --- .../src/cli/relay_headers_and_messages/mod.rs | 395 ++++++++++-------- .../relay_to_parachain.rs | 52 +-- .../relay_to_relay.rs | 51 +-- .../src/messages_metrics.rs | 8 +- 4 files changed, 276 insertions(+), 230 deletions(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index d4840f4c7d113..98a0469ae4d77 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -29,7 +29,7 @@ mod relay_to_relay; mod relay_to_parachain; use async_trait::async_trait; -use std::sync::Arc; +use std::{marker::PhantomData, sync::Arc}; use structopt::StructOpt; use strum::VariantNames; @@ -55,6 +55,7 @@ use crate::{ }, declare_chain_cli_schema, }; +use bp_messages::LaneId; use bp_runtime::{BalanceOf, BlockNumberOf}; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ @@ -63,7 +64,8 @@ use relay_substrate_client::{ use relay_utils::metrics::MetricsParams; use sp_core::Pair; use substrate_relay_helper::{ - messages_lane::MessagesRelayParams, on_demand::OnDemandRelay, TaggedAccount, TransactionParams, + messages_lane::MessagesRelayParams, messages_metrics::StandaloneMessagesMetrics, + on_demand::OnDemandRelay, TaggedAccount, TransactionParams, }; /// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. @@ -95,20 +97,155 @@ pub struct Full2WayBridgeCommonParams< Right: TransactionSignScheme + CliChain, > { pub shared: HeadersAndMessagesSharedParams, + pub left: BridgeEndCommonParams, + pub right: BridgeEndCommonParams, - pub left: Client, - // default signer, which is always used to sign messages relay transactions on the left chain - pub left_sign: AccountKeyPairOf, - pub left_transactions_mortality: Option, - pub left_messages_pallet_owner: Option>, - pub at_left_accounts: Vec>>, - - pub right: Client, - // default signer, which is always used to sign messages relay transactions on the right chain - pub right_sign: AccountKeyPairOf, - pub right_transactions_mortality: Option, - pub right_messages_pallet_owner: Option>, - pub at_right_accounts: Vec>>, + pub metrics_params: MetricsParams, + pub left_to_right_metrics: StandaloneMessagesMetrics, + pub right_to_left_metrics: StandaloneMessagesMetrics, +} + +impl + Full2WayBridgeCommonParams +{ + pub fn new>( + shared: HeadersAndMessagesSharedParams, + left: BridgeEndCommonParams, + right: BridgeEndCommonParams, + ) -> anyhow::Result { + // Create metrics registry. + let metrics_params = shared.prometheus_params.clone().into(); + let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); + let left_to_right_metrics = substrate_relay_helper::messages_metrics::standalone_metrics::< + L2R::MessagesLane, + >(left.client.clone(), right.client.clone())?; + let right_to_left_metrics = left_to_right_metrics.clone().reverse(); + + Ok(Self { + shared, + left, + right, + metrics_params, + left_to_right_metrics, + right_to_left_metrics, + }) + } +} + +pub struct BridgeEndCommonParams { + pub client: Client, + pub sign: AccountKeyPairOf, + pub transactions_mortality: Option, + pub messages_pallet_owner: Option>, + pub accounts: Vec>>, +} + +struct FullBridge< + 'a, + Source: TransactionSignScheme + CliChain, + Target: TransactionSignScheme + CliChain, + Bridge: MessagesCliBridge, +> { + shared: &'a HeadersAndMessagesSharedParams, + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + metrics: &'a StandaloneMessagesMetrics, + _phantom_data: PhantomData, +} + +impl< + 'a, + Source: TransactionSignScheme + CliChain, + Target: TransactionSignScheme + CliChain, + Bridge: MessagesCliBridge, + > FullBridge<'a, Source, Target, Bridge> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, +{ + fn new( + shared: &'a HeadersAndMessagesSharedParams, + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + metrics: &'a StandaloneMessagesMetrics, + ) -> Self { + Self { shared, source, target, metrics_params, metrics, _phantom_data: Default::default() } + } + + fn start_conversion_rate_update_loop(&mut self) -> anyhow::Result<()> { + if let Some(ref messages_pallet_owner) = self.source.messages_pallet_owner { + let format_err = || { + anyhow::format_err!( + "Cannon run conversion rate updater: {} -> {}", + Target::NAME, + Source::NAME + ) + }; + substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< + Bridge::MessagesLane, + Source, + >( + self.source.client.clone(), + TransactionParams { + signer: messages_pallet_owner.clone(), + mortality: self.source.transactions_mortality, + }, + self.metrics + .target_to_source_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + self.metrics + .target_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + self.metrics + .source_to_base_conversion_rate + .as_ref() + .ok_or_else(format_err)? + .shared_value_ref(), + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, + ); + self.source.accounts.push(TaggedAccount::MessagesPalletOwner { + id: messages_pallet_owner.public().into(), + bridged_chain: Target::NAME.to_string(), + }); + } + Ok(()) + } + + fn messages_relay_params( + &self, + source_to_target_headers_relay: Arc>>, + target_to_source_headers_relay: Arc>>, + lane_id: LaneId, + ) -> MessagesRelayParams { + let relayer_mode = self.shared.relayer_mode.into(); + let relay_strategy = MixStrategy::new(relayer_mode); + + MessagesRelayParams { + source_client: self.source.client.clone(), + source_transaction_params: TransactionParams { + signer: self.source.sign.clone(), + mortality: self.source.transactions_mortality, + }, + target_client: self.target.client.clone(), + target_transaction_params: TransactionParams { + signer: self.target.sign.clone(), + mortality: self.target.transactions_mortality, + }, + source_to_target_headers_relay: Some(source_to_target_headers_relay), + target_to_source_headers_relay: Some(target_to_source_headers_relay), + lane_id, + metrics_params: self.metrics_params.clone().disable(), + standalone_metrics: Some(self.metrics.clone()), + relay_strategy, + } + } } // All supported chains. @@ -179,195 +316,97 @@ where fn mut_base(&mut self) -> &mut Self::Base; - async fn run(&mut self) -> anyhow::Result<()> { - let left_client = self.base().common().left.clone(); - let left_transactions_mortality = self.base().common().left_transactions_mortality; - let left_sign = self.base().common().left_sign.clone(); - let left_messages_pallet_owner = self.base().common().left_messages_pallet_owner.clone(); - let right_client = self.base().common().right.clone(); - let right_transactions_mortality = self.base().common().right_transactions_mortality; - let right_sign = self.base().common().right_sign.clone(); - let right_messages_pallet_owner = self.base().common().right_messages_pallet_owner.clone(); + fn left_to_right(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::L2R>::new( + &common.shared, + &mut common.left, + &mut common.right, + &common.metrics_params, + &common.left_to_right_metrics, + ) + } - let lanes = self.base().common().shared.lane.clone(); - let relayer_mode = self.base().common().shared.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); + fn right_to_left(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::R2L>::new( + &common.shared, + &mut common.right, + &mut common.left, + &common.metrics_params, + &common.right_to_left_metrics, + ) + } - // create metrics registry and register standalone metrics - let metrics_params: MetricsParams = - self.base().common().shared.prometheus_params.clone().into(); - let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); - let left_to_right_metrics = substrate_relay_helper::messages_metrics::standalone_metrics::< - ::MessagesLane, - >(left_client.clone(), right_client.clone())?; - let right_to_left_metrics = left_to_right_metrics.clone().reverse(); - self.mut_base().mut_common().at_left_accounts.push(TaggedAccount::Messages { - id: left_sign.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }); - self.mut_base().mut_common().at_right_accounts.push(TaggedAccount::Messages { - id: right_sign.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }); + async fn run(&mut self) -> anyhow::Result<()> { + // Register standalone metrics. + { + let common = self.mut_base().mut_common(); + common.left.accounts.push(TaggedAccount::Messages { + id: common.left.sign.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }); + common.right.accounts.push(TaggedAccount::Messages { + id: common.right.sign.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }); + } // start conversion rate update loops for left/right chains - if let Some(left_messages_pallet_owner) = left_messages_pallet_owner.clone() { - let left_client = left_client.clone(); - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Self::Right::NAME, - Self::Left::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - ::MessagesLane, - Self::Left, - >( - left_client, - TransactionParams { - signer: left_messages_pallet_owner.clone(), - mortality: left_transactions_mortality, - }, - left_to_right_metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - left_to_right_metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - left_to_right_metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - self.mut_base().mut_common().at_left_accounts.push( - TaggedAccount::MessagesPalletOwner { - id: left_messages_pallet_owner.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }, - ); - } - if let Some(right_messages_pallet_owner) = right_messages_pallet_owner.clone() { - let right_client = right_client.clone(); - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Self::Left::NAME, - Self::Right::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - ::MessagesLane, - Self::Right, - >( - right_client, - TransactionParams { - signer: right_messages_pallet_owner.clone(), - mortality: right_transactions_mortality, - }, - right_to_left_metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - right_to_left_metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - right_to_left_metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - self.mut_base().mut_common().at_right_accounts.push( - TaggedAccount::MessagesPalletOwner { - id: right_messages_pallet_owner.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }, - ); - } + self.left_to_right().start_conversion_rate_update_loop()?; + self.right_to_left().start_conversion_rate_update_loop()?; // start on-demand header relays let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = self.mut_base().start_on_demand_headers_relayers().await?; // add balance-related metrics - let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( - left_client.clone(), - metrics_params, - &self.base().common().at_left_accounts, - ) - .await?; - let metrics_params = substrate_relay_helper::messages_metrics::add_relay_balances_metrics( - right_client.clone(), - metrics_params, - &self.base().common().at_right_accounts, - ) - .await?; + { + let common = self.mut_base().mut_common(); + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + common.left.client.clone(), + &mut common.metrics_params, + &common.left.accounts, + ) + .await?; + substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + common.right.client.clone(), + &mut common.metrics_params, + &common.right.accounts, + ) + .await?; + } + let lanes = self.base().common().shared.lane.clone(); // Need 2x capacity since we consider both directions for each lane let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { let lane = lane.into(); + let left_to_right_messages = substrate_relay_helper::messages_lane::run::< ::MessagesLane, - >(MessagesRelayParams { - source_client: left_client.clone(), - source_transaction_params: TransactionParams { - signer: left_sign.clone(), - mortality: left_transactions_mortality, - }, - target_client: right_client.clone(), - target_transaction_params: TransactionParams { - signer: right_sign.clone(), - mortality: right_transactions_mortality, - }, - source_to_target_headers_relay: Some(left_to_right_on_demand_headers.clone()), - target_to_source_headers_relay: Some(right_to_left_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params.clone().disable(), - standalone_metrics: Some(left_to_right_metrics.clone()), - relay_strategy: relay_strategy.clone(), - }) + >(self.left_to_right().messages_relay_params( + left_to_right_on_demand_headers.clone(), + right_to_left_on_demand_headers.clone(), + lane, + )) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); + message_relays.push(left_to_right_messages); + let right_to_left_messages = substrate_relay_helper::messages_lane::run::< ::MessagesLane, - >(MessagesRelayParams { - source_client: right_client.clone(), - source_transaction_params: TransactionParams { - signer: right_sign.clone(), - mortality: right_transactions_mortality, - }, - target_client: left_client.clone(), - target_transaction_params: TransactionParams { - signer: left_sign.clone(), - mortality: left_transactions_mortality, - }, - source_to_target_headers_relay: Some(right_to_left_on_demand_headers.clone()), - target_to_source_headers_relay: Some(left_to_right_on_demand_headers.clone()), - lane_id: lane, - metrics_params: metrics_params.clone().disable(), - standalone_metrics: Some(right_to_left_metrics.clone()), - relay_strategy: relay_strategy.clone(), - }) + >(self.right_to_left().messages_relay_params( + right_to_left_on_demand_headers.clone(), + left_to_right_on_demand_headers.clone(), + lane, + )) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); - - message_relays.push(left_to_right_messages); message_relays.push(right_to_left_messages); } - relay_utils::relay_metrics(metrics_params) + relay_utils::relay_metrics(self.base().common().metrics_params.clone()) .expose() .await .map_err(|e| anyhow::format_err!("{}", e))?; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 0d847141d4a68..b8f1992a2ff86 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -106,19 +106,23 @@ macro_rules! declare_relay_to_parachain_bridge_schema { self, ) -> anyhow::Result> { Ok(RelayToParachainBridge { - common: Full2WayBridgeCommonParams { - shared: self.shared, - left: self.left.into_client::().await?, - left_sign: self.left_sign.to_keypair::()?, - left_transactions_mortality: self.left_sign.transactions_mortality()?, - left_messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, - at_left_accounts: vec![], - right: self.right.into_client::().await?, - right_sign: self.right_sign.to_keypair::()?, - right_transactions_mortality: self.right_sign.transactions_mortality()?, - right_messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, - at_right_accounts: vec![], - }, + common: Full2WayBridgeCommonParams::new::( + self.shared, + BridgeEndCommonParams { + client: self.left.into_client::().await?, + sign: self.left_sign.to_keypair::()?, + transactions_mortality: self.left_sign.transactions_mortality()?, + messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + BridgeEndCommonParams { + client: self.right.into_client::().await?, + sign: self.right_sign.to_keypair::()?, + transactions_mortality: self.right_sign.transactions_mortality()?, + messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + )?, right_relay: self.right_relay.into_client::().await?, right_headers_to_left_transaction_params: self .right_relay_headers_to_left_sign_override @@ -178,43 +182,43 @@ where Arc>>, Arc>>, )> { - self.common.at_left_accounts.push(TaggedAccount::Headers { + self.common.left.accounts.push(TaggedAccount::Headers { id: self.right_headers_to_left_transaction_params.signer.public().into(), bridged_chain: RightRelay::NAME.to_string(), }); - self.common.at_left_accounts.push(TaggedAccount::Parachains { + self.common.left.accounts.push(TaggedAccount::Parachains { id: self.right_parachains_to_left_transaction_params.signer.public().into(), bridged_chain: RightRelay::NAME.to_string(), }); - self.common.at_right_accounts.push(TaggedAccount::Headers { + self.common.right.accounts.push(TaggedAccount::Headers { id: self.left_headers_to_right_transaction_params.signer.public().into(), bridged_chain: Left::NAME.to_string(), }); ::Finality::start_relay_guards( - &self.common.right, + &self.common.right.client, &self.left_headers_to_right_transaction_params, - self.common.right.can_start_version_guard(), + self.common.right.client.can_start_version_guard(), ) .await?; ::RelayFinality::start_relay_guards( - &self.common.left, + &self.common.left.client, &self.right_headers_to_left_transaction_params, - self.common.left.can_start_version_guard(), + self.common.left.client.can_start_version_guard(), ) .await?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::<::Finality>( - self.common.left.clone(), - self.common.right.clone(), + self.common.left.client.clone(), + self.common.right.client.clone(), self.left_headers_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::new::<::RelayFinality>( self.right_relay.clone(), - self.common.left.clone(), + self.common.left.client.clone(), self.right_headers_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); @@ -222,7 +226,7 @@ where ::ParachainFinality, >( self.right_relay.clone(), - self.common.left.clone(), + self.common.left.client.clone(), self.right_parachains_to_left_transaction_params.clone(), Arc::new(right_relay_to_left_on_demand_headers), ); diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index 4e9ecd2b58122..7350f903f62c3 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -85,20 +85,23 @@ macro_rules! declare_relay_to_relay_bridge_schema { self, ) -> anyhow::Result> { Ok(RelayToRelayBridge { - common: Full2WayBridgeCommonParams { - shared: self.shared, - left: self.left.into_client::().await?, - left_sign: self.left_sign.to_keypair::()?, - left_transactions_mortality: self.left_sign.transactions_mortality()?, - left_messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, - at_left_accounts: vec![], - right: self.right.into_client::().await?, - right_sign: self.right_sign.to_keypair::()?, - right_transactions_mortality: self.right_sign.transactions_mortality()?, - right_messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, - at_right_accounts: vec![], - }, - + common: Full2WayBridgeCommonParams::new::( + self.shared, + BridgeEndCommonParams { + client: self.left.into_client::().await?, + sign: self.left_sign.to_keypair::()?, + transactions_mortality: self.left_sign.transactions_mortality()?, + messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + BridgeEndCommonParams { + client: self.right.into_client::().await?, + sign: self.right_sign.to_keypair::()?, + transactions_mortality: self.right_sign.transactions_mortality()?, + messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + )?, right_to_left_transaction_params: self .right_headers_to_left_sign_override .transaction_params_or::(&self.left_sign)?, @@ -145,39 +148,39 @@ where Arc>>, Arc>>, )> { - self.common.at_right_accounts.push(TaggedAccount::Headers { + self.common.right.accounts.push(TaggedAccount::Headers { id: self.left_to_right_transaction_params.signer.public().into(), bridged_chain: Self::Left::NAME.to_string(), }); - self.common.at_left_accounts.push(TaggedAccount::Headers { + self.common.left.accounts.push(TaggedAccount::Headers { id: self.right_to_left_transaction_params.signer.public().into(), bridged_chain: Self::Right::NAME.to_string(), }); ::Finality::start_relay_guards( - &self.common.right, + &self.common.right.client, &self.left_to_right_transaction_params, - self.common.right.can_start_version_guard(), + self.common.right.client.can_start_version_guard(), ) .await?; ::Finality::start_relay_guards( - &self.common.left, + &self.common.left.client, &self.right_to_left_transaction_params, - self.common.left.can_start_version_guard(), + self.common.left.client.can_start_version_guard(), ) .await?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new::<::Finality>( - self.common.left.clone(), - self.common.right.clone(), + self.common.left.client.clone(), + self.common.right.client.clone(), self.left_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::new::<::Finality>( - self.common.right.clone(), - self.common.left.clone(), + self.common.right.client.clone(), + self.common.left.client.clone(), self.right_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 4210c7d981bd5..805d002b65f87 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -273,14 +273,14 @@ pub fn standalone_metrics( /// Add relay accounts balance metrics. pub async fn add_relay_balances_metrics( client: Client, - metrics: MetricsParams, + metrics: &mut MetricsParams, relay_accounts: &Vec>>, -) -> anyhow::Result +) -> anyhow::Result<()> where BalanceOf: Into + std::fmt::Debug, { if relay_accounts.is_empty() { - return Ok(metrics) + return Ok(()) } // if `tokenDecimals` is missing from system properties, we'll be using @@ -317,7 +317,7 @@ where relay_account_balance_metric.register_and_spawn(&metrics.registry)?; } - Ok(metrics) + Ok(()) } /// Adapter for `FloatStorageValueMetric` to decode account free balance. From 8b00454e771e4932113a9e18faa7710614ddad05 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 5 Aug 2022 10:00:53 +0300 Subject: [PATCH 0756/1210] Unprofitable message delivery tx metric (#1536) * unprofitable message delivery tx metric * proper impl * send Rialto -> Millau messages using XCM pallet * use altruistic relays in Rialto <> Millau bridge * add unprofitable transactions dashboard * fix + logging * fix test --- relays/messages/src/message_lane_loop.rs | 6 +- relays/messages/src/message_race_delivery.rs | 7 +- relays/messages/src/metrics.rs | 23 +++++- .../src/relay_strategy/altruistic_strategy.rs | 32 +++++++- .../relay_strategy/enforcement_strategy.rs | 6 +- .../src/relay_strategy/mix_strategy.rs | 14 ++++ relays/messages/src/relay_strategy/mod.rs | 19 ++++- .../src/relay_strategy/rational_strategy.rs | 73 ++++++++++++++----- 8 files changed, 151 insertions(+), 29 deletions(-) diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 84473f0f27b23..2e700deb9a6bf 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -271,7 +271,11 @@ pub async fn run( relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) .with_metrics(metrics_params) - .loop_metric(MessageLaneLoopMetrics::new(Some(&metrics_prefix::

(¶ms.lane)))?)? + .loop_metric(MessageLaneLoopMetrics::new( + Some(&metrics_prefix::

(¶ms.lane)), + P::SOURCE_NAME, + P::TARGET_NAME, + )?)? .expose() .await? .run(metrics_prefix::

(¶ms.lane), move |source_client, target_client, metrics| { diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 4484d4b7994c4..85f6d955e7df0 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -56,7 +56,7 @@ pub async fn run( source_state_updates, MessageDeliveryRaceTarget { client: target_client.clone(), - metrics_msg, + metrics_msg: metrics_msg.clone(), _phantom: Default::default(), }, target_state_updates, @@ -74,6 +74,7 @@ pub async fn run( latest_confirmed_nonces_at_source: VecDeque::new(), target_nonces: None, strategy: BasicStrategy::new(), + metrics_msg, }, ) .await @@ -255,6 +256,8 @@ struct MessageDeliveryStrategy target_nonces: Option>, /// Basic delivery strategy. strategy: MessageDeliveryStrategyBase

, + /// Message lane metrics. + metrics_msg: Option, } type MessageDeliveryStrategyBase

= BasicStrategy< @@ -519,6 +522,7 @@ where lane_target_client: lane_target_client.clone(), nonces_queue: source_queue.clone(), nonces_queue_range: 0..maximal_source_queue_index + 1, + metrics: self.metrics_msg.clone(), }; let mut strategy = EnforcementStrategy::new(self.relay_strategy.clone()); @@ -631,6 +635,7 @@ mod tests { latest_confirmed_nonces_at_source: vec![(header_id(1), 19)].into_iter().collect(), lane_source_client: TestSourceClient::default(), lane_target_client: TestTargetClient::default(), + metrics_msg: None, target_nonces: Some(TargetClientNonces { latest_nonce: 19, nonces_data: DeliveryRaceTargetNoncesData { diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 4decb7e092e71..f5cc8831c0286 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -24,7 +24,7 @@ use crate::{ use bp_messages::MessageNonce; use finality_relay::SyncLoopMetrics; use relay_utils::metrics::{ - metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, + metric_name, register, Counter, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, }; /// Message lane relay metrics. @@ -39,11 +39,17 @@ pub struct MessageLaneLoopMetrics { /// Lane state nonces: "source_latest_generated", "source_latest_confirmed", /// "target_latest_received", "target_latest_confirmed". lane_state_nonces: GaugeVec, + /// Count of unprofitable message delivery transactions that we have submitted so far. + unprofitable_delivery_transactions: Counter, } impl MessageLaneLoopMetrics { /// Create and register messages loop metrics. - pub fn new(prefix: Option<&str>) -> Result { + pub fn new( + prefix: Option<&str>, + source_name: &str, + target_name: &str, + ) -> Result { Ok(MessageLaneLoopMetrics { source_to_target_finality_metrics: SyncLoopMetrics::new( prefix, @@ -59,6 +65,13 @@ impl MessageLaneLoopMetrics { Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), &["type"], )?, + unprofitable_delivery_transactions: Counter::new( + metric_name(prefix, "unprofitable_delivery_transactions"), + format!( + "Count of unprofitable message delivery transactions from {} to {}", + source_name, target_name + ), + )?, }) } @@ -127,6 +140,11 @@ impl MessageLaneLoopMetrics { .with_label_values(&["target_latest_confirmed"]) .set(target_latest_confirmed_nonce); } + + /// Note unprofitable delivery transaction. + pub fn note_unprofitable_delivery_transactions(&self) { + self.unprofitable_delivery_transactions.inc() + } } impl Metric for MessageLaneLoopMetrics { @@ -134,6 +152,7 @@ impl Metric for MessageLaneLoopMetrics { self.source_to_target_finality_metrics.register(registry)?; self.target_to_source_finality_metrics.register(registry)?; register(self.lane_state_nonces.clone(), registry)?; + register(self.unprofitable_delivery_transactions.clone(), registry)?; Ok(()) } } diff --git a/relays/messages/src/relay_strategy/altruistic_strategy.rs b/relays/messages/src/relay_strategy/altruistic_strategy.rs index d6fec7f1297b3..b66129117873e 100644 --- a/relays/messages/src/relay_strategy/altruistic_strategy.rs +++ b/relays/messages/src/relay_strategy/altruistic_strategy.rs @@ -23,7 +23,7 @@ use crate::{ message_lane_loop::{ SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, }, - relay_strategy::{RelayReference, RelayStrategy}, + relay_strategy::{RationalStrategy, RelayReference, RelayStrategy}, }; /// The relayer doesn't care about rewards. @@ -38,8 +38,36 @@ impl RelayStrategy for AltruisticStrategy { TargetClient: MessageLaneTargetClient

, >( &mut self, - _reference: &mut RelayReference, + reference: &mut RelayReference, ) -> bool { + // we don't care about costs and rewards, but we want to report unprofitable transactions + // => let rational strategy fill required fields + let _ = RationalStrategy.decide(reference).await; true } + + async fn final_decision< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: &RelayReference, + ) { + if let Some(ref metrics) = reference.metrics { + if reference.total_cost > reference.total_reward { + log::debug!( + target: "bridge", + "The relayer has submitted unprofitable {} -> {} message delivery trabsaction with {} messages: total cost = {:?}, total reward = {:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + reference.index + 1, + reference.total_cost, + reference.total_reward, + ); + + metrics.note_unprofitable_delivery_transactions(); + } + } + } } diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/relay_strategy/enforcement_strategy.rs index 1e9ef5bdbf818..5d231462e86d9 100644 --- a/relays/messages/src/relay_strategy/enforcement_strategy.rs +++ b/relays/messages/src/relay_strategy/enforcement_strategy.rs @@ -65,6 +65,7 @@ impl EnforcementStrategy { let mut relay_reference = RelayReference { lane_source_client: reference.lane_source_client.clone(), lane_target_client: reference.lane_target_client.clone(), + metrics: reference.metrics.clone(), selected_reward: P::SourceChainBalance::zero(), selected_cost: P::SourceChainBalance::zero(), @@ -211,7 +212,10 @@ impl EnforcementStrategy { ); } - Some(hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1) + let selected_max_nonce = + hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; + self.strategy.final_decision(&relay_reference).await; + Some(selected_max_nonce) } else { None } diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs index 4ac7fe1d0ed06..d00c27196787c 100644 --- a/relays/messages/src/relay_strategy/mix_strategy.rs +++ b/relays/messages/src/relay_strategy/mix_strategy.rs @@ -55,4 +55,18 @@ impl RelayStrategy for MixStrategy { RelayerMode::Rational => RationalStrategy.decide(reference).await, } } + + async fn final_decision< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: &RelayReference, + ) { + match self.relayer_mode { + RelayerMode::Altruistic => AltruisticStrategy.final_decision(reference).await, + RelayerMode::Rational => RationalStrategy.final_decision(reference).await, + } + } } diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs index d902bd93e5cf9..da615f34e8659 100644 --- a/relays/messages/src/relay_strategy/mod.rs +++ b/relays/messages/src/relay_strategy/mod.rs @@ -16,11 +16,9 @@ //! Relayer strategy -use std::ops::Range; - use async_trait::async_trait; - use bp_messages::{MessageNonce, Weight}; +use std::ops::Range; use crate::{ message_lane::MessageLane, @@ -29,6 +27,7 @@ use crate::{ TargetClient as MessageLaneTargetClient, }, message_race_strategy::SourceRangesQueue, + metrics::MessageLaneLoopMetrics, }; pub(crate) use self::enforcement_strategy::*; @@ -55,6 +54,16 @@ pub trait RelayStrategy: 'static + Clone + Send + Sync { &mut self, reference: &mut RelayReference, ) -> bool; + + /// Notification that the following maximal nonce has been selected for the delivery. + async fn final_decision< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + reference: &RelayReference, + ); } /// Reference data for participating in relay @@ -67,6 +76,8 @@ pub struct RelayReference< pub lane_source_client: SourceClient, /// The client that is connected to the message lane target node. pub lane_target_client: TargetClient, + /// Metrics reference. + pub metrics: Option, /// Current block reward summary pub selected_reward: P::SourceChainBalance, /// Current block cost summary @@ -112,6 +123,8 @@ pub struct RelayMessagesBatchReference< pub lane_source_client: SourceClient, /// The client that is connected to the message lane target node. pub lane_target_client: TargetClient, + /// Metrics reference. + pub metrics: Option, /// Source queue. pub nonces_queue: SourceRangesQueue< P::SourceHeaderHash, diff --git a/relays/messages/src/relay_strategy/rational_strategy.rs b/relays/messages/src/relay_strategy/rational_strategy.rs index fd0a1ffafc8b9..f45f01725c631 100644 --- a/relays/messages/src/relay_strategy/rational_strategy.rs +++ b/relays/messages/src/relay_strategy/rational_strategy.rs @@ -44,37 +44,23 @@ impl RelayStrategy for RationalStrategy { &mut self, reference: &mut RelayReference, ) -> bool { - // technically, multiple confirmations will be delivered in a single transaction, - // meaning less loses for relayer. But here we don't know the final relayer yet, so - // we're adding a separate transaction for every message. Normally, this cost is covered - // by the message sender. Probably reconsider this? - let confirmation_transaction_cost = - reference.lane_source_client.estimate_confirmation_transaction().await; - - let delivery_transaction_cost = match reference - .lane_target_client - .estimate_delivery_transaction_in_source_tokens( - reference.hard_selected_begin_nonce..= - (reference.hard_selected_begin_nonce + reference.index as MessageNonce), - reference.selected_prepaid_nonces, - reference.selected_unpaid_weight, - reference.selected_size as u32, - ) - .await - { - Ok(v) => v, + let total_cost = match estimate_messages_delivery_cost(reference).await { + Ok(total_cost) => total_cost, Err(err) => { log::debug!( target: "bridge", "Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery", err, ); + return false }, }; // if it is the first message that makes reward less than cost, let's log it // if this message makes batch profitable again, let's log it + let MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost } = + total_cost; let is_total_reward_less_than_cost = reference.total_reward < reference.total_cost; let prev_total_cost = reference.total_cost; let prev_total_reward = reference.total_reward; @@ -119,4 +105,53 @@ impl RelayStrategy for RationalStrategy { false } + + async fn final_decision< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + >( + &self, + _reference: &RelayReference, + ) { + // rational relayer would never submit unprofitable transactions, so we don't need to do + // anything here + } +} + +/// Total cost of mesage delivery and confirmation. +struct MessagesDeliveryCost { + /// Cost of message delivery transaction. + pub delivery_transaction_cost: SourceChainBalance, + /// Cost of confirmation delivery transaction. + pub confirmation_transaction_cost: SourceChainBalance, +} + +/// Returns cost of message delivery and confirmation delivery transactions +async fn estimate_messages_delivery_cost< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, +>( + reference: &RelayReference, +) -> Result, TargetClient::Error> { + // technically, multiple confirmations will be delivered in a single transaction, + // meaning less loses for relayer. But here we don't know the final relayer yet, so + // we're adding a separate transaction for every message. Normally, this cost is covered + // by the message sender. Probably reconsider this? + let confirmation_transaction_cost = + reference.lane_source_client.estimate_confirmation_transaction().await; + + let delivery_transaction_cost = reference + .lane_target_client + .estimate_delivery_transaction_in_source_tokens( + reference.hard_selected_begin_nonce..= + (reference.hard_selected_begin_nonce + reference.index as MessageNonce), + reference.selected_prepaid_nonces, + reference.selected_unpaid_weight, + reference.selected_size as u32, + ) + .await?; + + Ok(MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost }) } From 364e9f75cbd3548d6fb75119558d2b653b9c6d3b Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 10 Aug 2022 19:46:31 +0300 Subject: [PATCH 0757/1210] Call To*InboundLaneApi::message_details() with batched messages (#1545) * generated_message_details() -> Simplifications - avoid using a HashMap for `messages_to_refine`. It seems that a vec is enough - minimize the number of conversions between `OutboundMessageDetails` and `MessageDetails` - use references where possible in order to minimize the number of intermediary Vecs - simplify `make_message_details_map()` logic, reduce its scope and rename it to `validate_out_msgs_details()` Signed-off-by: Serban Iorga * Define typed_state_call() Signed-off-by: Serban Iorga * Call To*InboundLaneApi::message_details() with single messages Signed-off-by: Serban Iorga * Call To*InboundLaneApi::message_details() with batched messages Signed-off-by: Serban Iorga * validate_out_msgs_details() -> change check * Define split_msgs_to_refine() Signed-off-by: Serban Iorga Signed-off-by: Serban Iorga --- relays/client-substrate/src/client.rs | 12 + .../src/messages_source.rs | 423 ++++++++++-------- 2 files changed, 251 insertions(+), 184 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index f1ddeeeb0f039..53ebe81e8604d 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -545,6 +545,18 @@ impl Client { .await } + /// Execute runtime call at given block, provided the input and output types. + /// It also performs the input encode and output decode. + pub async fn typed_state_call( + &self, + method_name: String, + input: Input, + at_block: Option, + ) -> Result { + let encoded_output = self.state_call(method_name, Bytes(input.encode()), at_block).await?; + Output::decode(&mut &encoded_output.0[..]).map_err(Error::ResponseParseFailed) + } + /// Execute runtime call at given block. pub async fn state_call( &self, diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 95a3feab0c11a..f032ec3c0c082 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -31,8 +31,8 @@ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::{operating_mode_key, outbound_lane_data_key}, - InboundMessageDetails, LaneId, MessageData, MessageNonce, MessagesOperatingMode, - OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, + InboundMessageDetails, LaneId, MessageData, MessageNonce, MessagePayload, + MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, }; use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode, HeaderIdProvider}; use bridge_runtime_common::messages::{ @@ -56,12 +56,13 @@ use relay_substrate_client::{ use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; -use std::{collections::HashMap, ops::RangeInclusive}; +use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything /// required to submit to the target node: cumulative dispatch weight of bundled messages and /// the proof itself. pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); +type MessagesToRefine<'a, Balance> = Vec<(MessagePayload, &'a mut OutboundMessageDetails)>; /// Substrate client as Substrate messages source. pub struct SubstrateMessagesSource { @@ -192,110 +193,97 @@ where &self, id: SourceHeaderIdOf>, nonces: RangeInclusive, - ) -> Result< - MessageDetailsMap< as MessageLane>::SourceChainBalance>, - SubstrateError, - > { - let encoded_response = self + ) -> Result>, SubstrateError> { + let mut out_msgs_details = self .source_client - .state_call( + .typed_state_call::<_, Vec<_>>( P::TargetChain::TO_CHAIN_MESSAGE_DETAILS_METHOD.into(), - Bytes((self.lane_id, nonces.start(), nonces.end()).encode()), + (self.lane_id, *nonces.start(), *nonces.end()), Some(id.1), ) .await?; - - let mut messages = make_message_details_map::( - Decode::decode(&mut &encoded_response.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?, - nonces, - )?; + validate_out_msgs_details::(&out_msgs_details, nonces)?; // prepare arguments of the inbound message details call (if we need it) - let mut messages_to_refine = HashMap::new(); - for (message_nonce, message) in &messages { - if message.dispatch_fee_payment != DispatchFeePayment::AtTargetChain { + let mut msgs_to_refine = vec![]; + for out_msg_details in out_msgs_details.iter_mut() { + if out_msg_details.dispatch_fee_payment != DispatchFeePayment::AtTargetChain { continue } // for pay-at-target messages we may want to ask target chain for // refined dispatch weight - let message_key = bp_messages::storage_keys::message_key( + let msg_key = bp_messages::storage_keys::message_key( P::TargetChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &self.lane_id, - *message_nonce, - ); - let message_data: MessageData> = - self.source_client.storage_value(message_key, Some(id.1)).await?.ok_or_else( - || { - SubstrateError::Custom(format!( - "Message to {} {:?}/{} is missing from runtime the storage of {} at {:?}", - P::TargetChain::NAME, - self.lane_id, - message_nonce, - P::SourceChain::NAME, - id, - )) - }, - )?; - let message_payload = message_data.payload; - messages_to_refine.insert( - *message_nonce, - ( - message_payload, - OutboundMessageDetails { - nonce: *message_nonce, - dispatch_weight: message.dispatch_weight, - size: message.size, - delivery_and_dispatch_fee: message.reward, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, - }, - ), + out_msg_details.nonce, ); + let msg_data: MessageData> = + self.source_client.storage_value(msg_key, Some(id.1)).await?.ok_or_else(|| { + SubstrateError::Custom(format!( + "Message to {} {:?}/{} is missing from runtime the storage of {} at {:?}", + P::TargetChain::NAME, + self.lane_id, + out_msg_details.nonce, + P::SourceChain::NAME, + id, + )) + })?; + + msgs_to_refine.push((msg_data.payload, out_msg_details)); } - // request inbound message details from the target client - if !messages_to_refine.is_empty() { - let refined_messages_encoded = self + for mut msgs_to_refine_batch in + split_msgs_to_refine::(self.lane_id, msgs_to_refine)? + { + let in_msgs_details = self .target_client - .state_call( + .typed_state_call::<_, Vec>( P::SourceChain::FROM_CHAIN_MESSAGE_DETAILS_METHOD.into(), - Bytes((self.lane_id, messages_to_refine.values().collect::>()).encode()), + (self.lane_id, &msgs_to_refine_batch), None, ) .await?; - let refined_messages = - Vec::::decode(&mut &refined_messages_encoded.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; - if refined_messages.len() != messages_to_refine.len() { + if in_msgs_details.len() != msgs_to_refine_batch.len() { return Err(SubstrateError::Custom(format!( "Call of {} at {} has returned {} entries instead of expected {}", P::SourceChain::FROM_CHAIN_MESSAGE_DETAILS_METHOD, P::TargetChain::NAME, - refined_messages.len(), - messages_to_refine.len(), + in_msgs_details.len(), + msgs_to_refine_batch.len(), ))) } - - for (nonce, refined_message) in messages_to_refine.keys().zip(refined_messages) { - let message = messages - .get_mut(nonce) - .expect("`messages_to_refine` is a subset of `messages`; qed"); + for ((_, out_msg_details), in_msg_details) in + msgs_to_refine_batch.iter_mut().zip(in_msgs_details) + { log::trace!( target: "bridge", "Refined weight of {}->{} message {:?}/{}: at-source: {}, at-target: {}", P::SourceChain::NAME, P::TargetChain::NAME, self.lane_id, - nonce, - message.dispatch_weight, - refined_message.dispatch_weight, + out_msg_details.nonce, + out_msg_details.dispatch_weight, + in_msg_details.dispatch_weight, ); - message.dispatch_weight = refined_message.dispatch_weight; + out_msg_details.dispatch_weight = in_msg_details.dispatch_weight; } } - Ok(messages) + let mut msgs_details_map = MessageDetailsMap::new(); + for out_msg_details in out_msgs_details { + msgs_details_map.insert( + out_msg_details.nonce, + MessageDetails { + dispatch_weight: out_msg_details.dispatch_weight, + size: out_msg_details.size as _, + reward: out_msg_details.delivery_and_dispatch_fee, + dispatch_fee_payment: out_msg_details.dispatch_fee_payment, + }, + ); + } + + Ok(msgs_details_map) } async fn prove_messages( @@ -571,10 +559,10 @@ where .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized)) } -fn make_message_details_map( - weights: Vec>, +fn validate_out_msgs_details( + out_msgs_details: &[OutboundMessageDetails], nonces: RangeInclusive, -) -> Result, SubstrateError> { +) -> Result<(), SubstrateError> { let make_missing_nonce_error = |expected_nonce| { Err(SubstrateError::Custom(format!( "Missing nonce {} in message_details call result. Expected all nonces from {:?}", @@ -582,73 +570,88 @@ fn make_message_details_map( ))) }; - let mut weights_map = MessageDetailsMap::new(); - - // this is actually prevented by external logic - if nonces.is_empty() { - return Ok(weights_map) + if out_msgs_details.len() > nonces.clone().count() { + return Err(SubstrateError::Custom( + "More messages than requested returned by the message_details call.".into(), + )) } - // check if last nonce is missing - loop below is not checking this - let last_nonce_is_missing = - weights.last().map(|details| details.nonce != *nonces.end()).unwrap_or(true); - if last_nonce_is_missing { + // Check if last nonce is missing. The loop below is not checking this. + if out_msgs_details.is_empty() && !nonces.is_empty() { return make_missing_nonce_error(*nonces.end()) } - let mut expected_nonce = *nonces.start(); - let mut is_at_head = true; - - for details in weights { - match (details.nonce == expected_nonce, is_at_head) { - (true, _) => (), - (false, true) => { - // this may happen if some messages were already pruned from the source node - // - // this is not critical error and will be auto-resolved by messages lane (and target - // node) - log::info!( - target: "bridge", - "Some messages are missing from the {} node: {:?}. Target node may be out of sync?", - C::NAME, - expected_nonce..details.nonce, - ); - }, - (false, false) => { - // some nonces are missing from the middle/tail of the range - // - // this is critical error, because we can't miss any nonces - return make_missing_nonce_error(expected_nonce) - }, + let mut nonces_iter = nonces.clone().rev().peekable(); + let mut out_msgs_details_iter = out_msgs_details.iter().rev(); + while let Some((out_msg_details, &nonce)) = out_msgs_details_iter.next().zip(nonces_iter.peek()) + { + nonces_iter.next(); + if out_msg_details.nonce != nonce { + // Some nonces are missing from the middle/tail of the range. This is critical error. + return make_missing_nonce_error(nonce) } + } - weights_map.insert( - details.nonce, - MessageDetails { - dispatch_weight: details.dispatch_weight, - size: details.size as _, - reward: details.delivery_and_dispatch_fee, - dispatch_fee_payment: details.dispatch_fee_payment, - }, + // Check if some nonces from the beginning of the range are missing. This may happen if + // some messages were already pruned from the source node. This is not a critical error + // and will be auto-resolved by messages lane (and target node). + if nonces_iter.peek().is_some() { + log::info!( + target: "bridge", + "Some messages are missing from the {} node: {:?}. Target node may be out of sync?", + C::NAME, + nonces_iter.rev().collect::>(), ); - expected_nonce = details.nonce + 1; - is_at_head = false; } - Ok(weights_map) + Ok(()) +} + +fn split_msgs_to_refine( + lane_id: LaneId, + msgs_to_refine: MessagesToRefine, +) -> Result>, SubstrateError> { + let max_batch_size = Target::max_extrinsic_size() as usize; + let mut batches = vec![]; + + let mut current_msgs_batch = msgs_to_refine; + while !current_msgs_batch.is_empty() { + let mut next_msgs_batch = vec![]; + while (lane_id, ¤t_msgs_batch).encoded_size() > max_batch_size { + if current_msgs_batch.len() <= 1 { + return Err(SubstrateError::Custom(format!( + "Call of {} at {} can't be executed even if only one message is supplied. \ + max_extrinsic_size(): {}", + Source::FROM_CHAIN_MESSAGE_DETAILS_METHOD, + Target::NAME, + Target::max_extrinsic_size(), + ))) + } + + if let Some(msg) = current_msgs_batch.pop() { + next_msgs_batch.insert(0, msg); + } + } + + batches.push(current_msgs_batch); + current_msgs_batch = next_msgs_batch; + } + + Ok(batches) } #[cfg(test)] mod tests { use super::*; - use bp_runtime::messages::DispatchFeePayment; + use bp_runtime::{messages::DispatchFeePayment, Chain as ChainBase}; use codec::MaxEncodedLen; + use relay_rialto_client::Rialto; use relay_rococo_client::Rococo; use relay_wococo_client::Wococo; fn message_details_from_rpc( nonces: RangeInclusive, - ) -> Vec> { + ) -> Vec> { nonces .into_iter() .map(|nonce| bp_messages::OutboundMessageDetails { @@ -662,94 +665,49 @@ mod tests { } #[test] - fn make_message_details_map_succeeds_if_no_messages_are_missing() { - assert_eq!( - make_message_details_map::(message_details_from_rpc(1..=3), 1..=3,).unwrap(), - vec![ - ( - 1, - MessageDetails { - dispatch_weight: 0, - size: 0, - reward: 0, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - } - ), - ( - 2, - MessageDetails { - dispatch_weight: 0, - size: 0, - reward: 0, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - } - ), - ( - 3, - MessageDetails { - dispatch_weight: 0, - size: 0, - reward: 0, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - } - ), - ] - .into_iter() - .collect(), + fn validate_out_msgs_details_succeeds_if_no_messages_are_missing() { + assert!( + validate_out_msgs_details::(&message_details_from_rpc(1..=3), 1..=3,).is_ok() ); } #[test] - fn make_message_details_map_succeeds_if_head_messages_are_missing() { - assert_eq!( - make_message_details_map::(message_details_from_rpc(2..=3), 1..=3,).unwrap(), - vec![ - ( - 2, - MessageDetails { - dispatch_weight: 0, - size: 0, - reward: 0, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - } - ), - ( - 3, - MessageDetails { - dispatch_weight: 0, - size: 0, - reward: 0, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, - } - ), - ] - .into_iter() - .collect(), - ); + fn validate_out_msgs_details_succeeds_if_head_messages_are_missing() { + assert!( + validate_out_msgs_details::(&message_details_from_rpc(2..=3), 1..=3,).is_ok() + ) } #[test] - fn make_message_details_map_fails_if_mid_messages_are_missing() { + fn validate_out_msgs_details_fails_if_mid_messages_are_missing() { let mut message_details_from_rpc = message_details_from_rpc(1..=3); message_details_from_rpc.remove(1); assert!(matches!( - make_message_details_map::(message_details_from_rpc, 1..=3,), + validate_out_msgs_details::(&message_details_from_rpc, 1..=3,), + Err(SubstrateError::Custom(_)) + )); + } + + #[test] + fn validate_out_msgs_details_map_fails_if_tail_messages_are_missing() { + assert!(matches!( + validate_out_msgs_details::(&message_details_from_rpc(1..=2), 1..=3,), Err(SubstrateError::Custom(_)) )); } #[test] - fn make_message_details_map_fails_if_tail_messages_are_missing() { + fn validate_out_msgs_details_fails_if_all_messages_are_missing() { assert!(matches!( - make_message_details_map::(message_details_from_rpc(1..=2), 1..=3,), + validate_out_msgs_details::(&[], 1..=3), Err(SubstrateError::Custom(_)) )); } #[test] - fn make_message_details_map_fails_if_all_messages_are_missing() { + fn validate_out_msgs_details_fails_if_more_messages_than_nonces() { assert!(matches!( - make_message_details_map::(vec![], 1..=3), + validate_out_msgs_details::(&message_details_from_rpc(1..=5), 2..=5,), Err(SubstrateError::Custom(_)) )); } @@ -766,4 +724,101 @@ mod tests { dummy_proof.1.encode().len(), ); } + + fn check_split_msgs_to_refine( + payload_sizes: Vec, + expected_batches: Result, ()>, + ) { + let mut out_msgs_details = vec![]; + for (idx, _) in payload_sizes.iter().enumerate() { + out_msgs_details.push(OutboundMessageDetails::> { + nonce: idx as MessageNonce, + dispatch_weight: 0, + size: 0, + delivery_and_dispatch_fee: 0, + dispatch_fee_payment: DispatchFeePayment::AtTargetChain, + }); + } + + let mut msgs_to_refine = vec![]; + for (&payload_size, out_msg_details) in + payload_sizes.iter().zip(out_msgs_details.iter_mut()) + { + let payload = vec![1u8; payload_size]; + msgs_to_refine.push((payload, out_msg_details)); + } + + let maybe_batches = split_msgs_to_refine::([0, 0, 0, 0], msgs_to_refine); + match expected_batches { + Ok(expected_batches) => { + let batches = maybe_batches.unwrap(); + let mut idx = 0; + assert_eq!(batches.len(), expected_batches.len()); + for (batch, &expected_batch_size) in batches.iter().zip(expected_batches.iter()) { + assert_eq!(batch.len(), expected_batch_size); + for msg_to_refine in batch { + assert_eq!(msg_to_refine.0.len(), payload_sizes[idx]); + idx += 1; + } + } + }, + Err(_) => { + matches!(maybe_batches, Err(SubstrateError::Custom(_))); + }, + } + } + + #[test] + fn test_split_msgs_to_refine() { + let max_extrinsic_size = Rococo::max_extrinsic_size() as usize; + + // Check that an error is returned when one of the messages is too big. + check_split_msgs_to_refine(vec![max_extrinsic_size], Err(())); + check_split_msgs_to_refine(vec![50, 100, max_extrinsic_size, 200], Err(())); + + // Otherwise check that the split is valid. + check_split_msgs_to_refine(vec![100, 200, 300, 400], Ok(vec![4])); + check_split_msgs_to_refine( + vec![ + 50, + 100, + max_extrinsic_size - 500, + 500, + 1000, + 1500, + max_extrinsic_size - 3500, + 5000, + 10000, + ], + Ok(vec![3, 4, 2]), + ); + check_split_msgs_to_refine( + vec![ + 50, + 100, + max_extrinsic_size - 150, + 500, + 1000, + 1500, + max_extrinsic_size - 3000, + 5000, + 10000, + ], + Ok(vec![2, 1, 3, 1, 2]), + ); + check_split_msgs_to_refine( + vec![ + 5000, + 10000, + max_extrinsic_size - 3500, + 500, + 1000, + 1500, + max_extrinsic_size - 500, + 50, + 100, + ], + Ok(vec![2, 4, 3]), + ); + } } From 62bd234ebbc535b7d82500e088381698534db407 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 12 Aug 2022 12:05:46 +0300 Subject: [PATCH 0758/1210] Follow-up on #1518 (#1546) * Adjustments for the xcm messages sending logic Signed-off-by: Serban Iorga * Deduplicate XCM destination Signed-off-by: Serban Iorga * [send_message] small changes Signed-off-by: Serban Iorga * Define CustomNetworkId Right now we use some associations between Rialto, RialtoParachain and Millau chains and chains defined in the NetworkId enum. But if we are not carreful we might do mistakes like: In Millau: pub const ThisNetwork: NetworkId = Kusama; pub const RialtoNetwork: NetworkId = Polkadot; In Rialto: pub const ThisNetwork: NetworkId = Kusama; pub const MillauNetwork: NetworkId = Polkadot; We're introducing CustomNetworkId to have a centralized mapping between NetworkId chains and our custom chains. Signed-off-by: Serban Iorga * Revert "Deduplicate XCM destination" This reverts commit 3a0a950e1d7484e3ecac45f5c00b152f0485cd11. Signed-off-by: Serban Iorga --- bin/millau/runtime/src/xcm_config.rs | 17 ++++---- bin/rialto-parachain/runtime/src/lib.rs | 11 ++--- bin/rialto/runtime/src/xcm_config.rs | 13 +++--- bin/runtime-common/src/lib.rs | 23 +++++++++++ bin/runtime-common/src/messages.rs | 2 +- relays/bin-substrate/Cargo.toml | 1 - relays/bin-substrate/src/chains/millau.rs | 40 ++++++++----------- relays/bin-substrate/src/chains/rialto.rs | 19 +++++---- .../src/chains/rialto_parachain.rs | 21 +++++----- relays/bin-substrate/src/cli/estimate_fee.rs | 10 ++--- relays/bin-substrate/src/cli/send_message.rs | 4 +- 11 files changed, 89 insertions(+), 72 deletions(-) diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 19fb68b66265b..57f28e1404444 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -27,7 +27,10 @@ use super::{ use bp_messages::LaneId; use bp_millau::WeightToFee; use bp_rialto_parachain::RIALTO_PARACHAIN_ID; -use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; +use bridge_runtime_common::{ + messages::source::{XcmBridge, XcmBridgeAdapter}, + CustomNetworkId, +}; use frame_support::{ parameter_types, traits::{Everything, Nothing}, @@ -45,12 +48,12 @@ parameter_types! { /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to /// the context". pub const TokenLocation: MultiLocation = Here.into_location(); - /// The Millau network ID, associated with Kusama. - pub const ThisNetwork: NetworkId = Kusama; - /// The Rialto network ID, associated with Polkadot. - pub const RialtoNetwork: NetworkId = Polkadot; - /// The RialtoParachain network ID, associated with Westend. - pub const RialtoParachainNetwork: NetworkId = Westend; + /// The Millau network ID. + pub const ThisNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); + /// The Rialto network ID. + pub const RialtoNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); + /// The RialtoParachain network ID. + pub const RialtoParachainNetwork: NetworkId = CustomNetworkId::RialtoParachain.as_network_id(); /// Our XCM location ancestry - i.e. our location within the Consensus Universe. /// diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index e96268d8aa8ca..5cc577281fdaa 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -78,6 +78,7 @@ pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_xcm::Call as XcmCall; // Polkadot & XCM imports +use bridge_runtime_common::CustomNetworkId; use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; use xcm::latest::prelude::*; @@ -304,13 +305,13 @@ impl pallet_randomness_collective_flip::Config for Runtime {} parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); - /// The Millau network ID, associated with Kusama. - pub const MillauNetwork: NetworkId = Kusama; - /// The RialtoParachain network ID, associated with Westend. - pub const ThisNetwork: NetworkId = Westend; + /// The Millau network ID. + pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); + /// The RialtoParachain network ID. + pub const ThisNetwork: NetworkId = CustomNetworkId::RialtoParachain.as_network_id(); } /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 63b2d0bead0f0..dbe8ad81c4fe1 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -21,7 +21,10 @@ use super::{ Event, Origin, Runtime, WithMillauMessagesInstance, XcmPallet, }; use bp_rialto::WeightToFee; -use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; +use bridge_runtime_common::{ + messages::source::{XcmBridge, XcmBridgeAdapter}, + CustomNetworkId, +}; use frame_support::{ parameter_types, traits::{Everything, Nothing}, @@ -39,10 +42,10 @@ parameter_types! { /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to /// the context". pub const TokenLocation: MultiLocation = Here.into_location(); - /// The Rialto network ID, associated with Polkadot. - pub const ThisNetwork: NetworkId = Polkadot; - /// The Millau network ID, associated with Kusama. - pub const MillauNetwork: NetworkId = Kusama; + /// The Rialto network ID. + pub const ThisNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); + /// The Millau network ID. + pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); /// Our XCM location ancestry - i.e. our location within the Consensus Universe. /// diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 5b2cea8ddd7ff..a8f2434fc7d0b 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -20,6 +20,7 @@ use bp_runtime::FilterCall; use sp_runtime::transaction_validity::TransactionValidity; +use xcm::v3::NetworkId; pub mod messages; pub mod messages_api; @@ -119,6 +120,28 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { }; } +/// A mapping over `NetworkId`. +/// Since `NetworkId` doesn't include `Millau`, `Rialto` and `RialtoParachain`, we create some +/// synthetic associations between these chains and `NetworkId` chains. +pub enum CustomNetworkId { + /// The Millau network ID, associated with Kusama. + Millau, + /// The Rialto network ID, associated with Polkadot. + Rialto, + /// The RialtoParachain network ID, associated with Westend. + RialtoParachain, +} + +impl CustomNetworkId { + pub const fn as_network_id(&self) -> NetworkId { + match *self { + CustomNetworkId::Millau => NetworkId::Kusama, + CustomNetworkId::Rialto => NetworkId::Polkadot, + CustomNetworkId::RialtoParachain => NetworkId::Westend, + } + } +} + #[cfg(test)] mod tests { use crate::BridgeRuntimeFilterCall; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index ef0722a80bce5..a7ad19dc1f168 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -569,7 +569,7 @@ pub mod source { } let route = T::build_destination(); - let msg = (route, msg.take().unwrap()).encode(); + let msg = (route, msg.take().ok_or(SendError::MissingArgument)?).encode(); let fee = estimate_message_dispatch_and_delivery_fee::( &msg, diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 63ccb4f918e29..56d669e49735e 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -60,7 +60,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master # Polkadot Dependencies -#pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 2cf0258d4325c..b71ecb288e9d0 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -34,35 +34,27 @@ impl CliEncodeMessage for Millau { message: xcm::VersionedXcm<()>, bridge_instance_index: u8, ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => { - let dest = - (Parent, X1(GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()))); - millau_runtime::Call::XcmPallet(millau_runtime::XcmCall::send { - dest: Box::new(dest.into()), - message: Box::new(message), - }) - .into() - }, - bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => { - let dest = ( - Parent, - X2( - GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()), - Parachain(RIALTO_PARACHAIN_ID), - ), - ); - millau_runtime::Call::XcmPallet(millau_runtime::XcmCall::send { - dest: Box::new(dest.into()), - message: Box::new(message), - }) - .into() - }, + let dest = match bridge_instance_index { + bridge::MILLAU_TO_RIALTO_INDEX => + (Parent, X1(GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()))), + bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => ( + Parent, + X2( + GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()), + Parachain(RIALTO_PARACHAIN_ID), + ), + ), _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", bridge_instance_index ), + }; + + Ok(millau_runtime::Call::XcmPallet(millau_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), }) + .into()) } fn encode_send_message_call( diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 2753a917ad24a..9dd86c9d95339 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -33,21 +33,20 @@ impl CliEncodeMessage for Rialto { message: xcm::VersionedXcm<()>, bridge_instance_index: u8, ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => { - let dest = - (Parent, X1(GlobalConsensus(rialto_runtime::xcm_config::MillauNetwork::get()))); - rialto_runtime::Call::XcmPallet(rialto_runtime::XcmCall::send { - dest: Box::new(dest.into()), - message: Box::new(message), - }) - .into() - }, + let dest = match bridge_instance_index { + bridge::RIALTO_TO_MILLAU_INDEX => + (Parent, X1(GlobalConsensus(rialto_runtime::xcm_config::MillauNetwork::get()))), _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", bridge_instance_index ), + }; + + Ok(rialto_runtime::Call::XcmPallet(rialto_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), }) + .into()) } fn encode_send_message_call( diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 09edeaecea02b..8cd7135c27a3c 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -33,23 +33,20 @@ impl CliEncodeMessage for RialtoParachain { message: xcm::VersionedXcm<()>, bridge_instance_index: u8, ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => { - let dest = - (Parent, X1(GlobalConsensus(rialto_parachain_runtime::MillauNetwork::get()))); - rialto_parachain_runtime::Call::PolkadotXcm( - rialto_parachain_runtime::XcmCall::send { - dest: Box::new(dest.into()), - message: Box::new(message), - }, - ) - .into() - }, + let dest = match bridge_instance_index { + bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => + (Parent, X1(GlobalConsensus(rialto_parachain_runtime::MillauNetwork::get()))), _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", bridge_instance_index ), + }; + + Ok(rialto_parachain_runtime::Call::PolkadotXcm(rialto_parachain_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), }) + .into()) } fn encode_send_message_call( diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index ed1e27bcf5f00..806df7f01f777 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -100,7 +100,7 @@ where data.conversion_rate_override, Self::ESTIMATE_MESSAGE_FEE_METHOD, lane, - payload, + &payload, ) .await?; @@ -141,7 +141,7 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee< conversion_rate_override: Option, estimate_fee_method: &str, lane: bp_messages::LaneId, - payload: P, + payload: &P, ) -> anyhow::Result> { // actual conversion rate CAN be lesser than the rate stored in the runtime. So we may try to // pay lesser fee for the message delivery. But in this case, message may be rejected by the @@ -196,7 +196,7 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee< client, estimate_fee_method, lane, - payload.clone(), + payload, None, ) .await?; @@ -204,7 +204,7 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee< client, estimate_fee_method, lane, - payload.clone(), + payload, conversion_rate_override, ) .await?; @@ -227,7 +227,7 @@ async fn do_estimate_message_delivery_and_dispatch_fee client: &relay_substrate_client::Client, estimate_fee_method: &str, lane: bp_messages::LaneId, - payload: P, + payload: &P, conversion_rate_override: Option, ) -> anyhow::Result> { let encoded_response = client diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 11625c3b8ea2a..a45235f0bec28 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -121,13 +121,13 @@ where conversion_rate_override, Self::ESTIMATE_MESSAGE_FEE_METHOD, lane, - payload.clone(), + &payload, ) .await? .into(), ), }; - let payload_len = payload.encode().len(); + let payload_len = payload.encoded_size(); let send_message_call = if data.use_xcm_pallet { Self::Source::encode_send_xcm( decode_xcm(payload)?, From 7d5488f1c9dc50c80a6b66a1e6691feba7cc1b44 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 12 Aug 2022 19:09:51 +0300 Subject: [PATCH 0759/1210] relayers pallet - small changes (#1547) Signed-off-by: Serban Iorga Signed-off-by: Serban Iorga --- modules/messages/src/lib.rs | 2 +- modules/relayers/src/lib.rs | 29 +++++++++++++- modules/relayers/src/payment_adapter.rs | 51 ++++++++++++------------- primitives/relayers/Cargo.toml | 11 ------ 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 9806a264c9946..6e87c51ca986f 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -947,7 +947,7 @@ where // loop won't proceed if current entry is ahead of received range (begin > end). // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); - for nonce in nonce_begin..nonce_end + 1 { + for nonce in nonce_begin..=nonce_end { let key = MessageKey { lane_id, nonce }; let message_data = OutboundMessages::::get(key) .expect("message was just confirmed; we never prune unconfirmed messages; qed"); diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 596dd89f31339..779cc285c99fa 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -34,6 +34,9 @@ mod payment_adapter; pub mod weights; +/// The target that will be used when publishing logs related to this pallet. +pub const LOG_TARGET: &str = "runtime::bridge-relayers"; + #[frame_support::pallet] pub mod pallet { use super::*; @@ -67,7 +70,7 @@ pub mod pallet { let reward = maybe_reward.take().ok_or(Error::::NoRewardForRelayer)?; T::PaymentProcedure::pay_reward(&relayer, reward).map_err(|e| { log::trace!( - target: "runtime::bridge-relayers", + target: LOG_TARGET, "Failed to pay rewards to {:?}: {:?}", relayer, e, @@ -110,11 +113,18 @@ pub mod pallet { #[cfg(test)] mod tests { use super::*; - use mock::*; + use mock::{Event as TestEvent, *}; + use crate::Event::RewardPaid; use frame_support::{assert_noop, assert_ok, traits::fungible::Inspect}; + use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; + fn get_ready_for_events() { + System::::set_block_number(1); + System::::reset_events(); + } + #[test] fn root_cant_claim_anything() { run_test(|| { @@ -149,9 +159,24 @@ mod tests { #[test] fn relayer_can_claim_reward() { run_test(|| { + get_ready_for_events(); + RelayerRewards::::insert(REGULAR_RELAYER, 100); assert_ok!(Pallet::::claim_rewards(Origin::signed(REGULAR_RELAYER))); assert_eq!(RelayerRewards::::get(REGULAR_RELAYER), None); + + //Check if the `RewardPaid` event was emitted. + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Relayers(RewardPaid { + relayer: REGULAR_RELAYER, + reward: 100 + }), + topics: vec![], + }], + ); }); } diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 6aa1248959dca..46a7ad94d4af2 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -20,8 +20,8 @@ use crate::{Config, RelayerRewards}; use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; -use frame_support::traits::Get; -use sp_arithmetic::traits::{Bounded, Saturating, Zero}; +use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; +use sp_arithmetic::traits::{Saturating, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism @@ -60,18 +60,17 @@ where messages_relayers, received_range, ); - if !relayers_rewards.is_empty() { - schedule_relayers_rewards::( - confirmation_relayer, - relayers_rewards, - GetConfirmationFee::get(), - ); - } + + register_relayers_rewards::( + confirmation_relayer, + relayers_rewards, + GetConfirmationFee::get(), + ); } } // Update rewards to given relayers, optionally rewarding confirmation relayer. -fn schedule_relayers_rewards( +fn register_relayers_rewards( confirmation_relayer: &T::AccountId, relayers_rewards: RelayersRewards, confirmation_fee: T::Reward, @@ -87,44 +86,42 @@ fn schedule_relayers_rewards( // // If confirmation fee has been increased (or if it was the only component of message // fee), then messages relayer may receive zero reward. - let mut confirmation_reward = T::Reward::try_from(reward.messages) - .unwrap_or_else(|_| Bounded::max_value()) - .saturating_mul(confirmation_fee); - if confirmation_reward > relayer_reward { - confirmation_reward = relayer_reward; - } + let mut confirmation_reward = + T::Reward::saturated_from(reward.messages).saturating_mul(confirmation_fee); + confirmation_reward = sp_std::cmp::min(confirmation_reward, relayer_reward); relayer_reward = relayer_reward.saturating_sub(confirmation_reward); confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(confirmation_reward); + + register_relayer_reward::(&relayer, relayer_reward); } else { // If delivery confirmation is submitted by this relayer, let's add confirmation fee // from other relayers to this relayer reward. - confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(reward.reward); - continue + confirmation_relayer_reward = + confirmation_relayer_reward.saturating_add(relayer_reward); } - - schedule_relayer_reward::(&relayer, relayer_reward); } // finally - pay reward to confirmation relayer - schedule_relayer_reward::(confirmation_relayer, confirmation_relayer_reward); + register_relayer_reward::(confirmation_relayer, confirmation_relayer_reward); } /// Remember that the reward shall be paid to the relayer. -fn schedule_relayer_reward(relayer: &T::AccountId, reward: T::Reward) { +fn register_relayer_reward(relayer: &T::AccountId, reward: T::Reward) { if reward.is_zero() { return } RelayerRewards::::mutate(relayer, |old_reward: &mut Option| { let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); + *old_reward = Some(new_reward); + log::trace!( - target: "T::bridge-relayers", + target: crate::LOG_TARGET, "Relayer {:?} can now claim reward: {:?}", relayer, new_reward, ); - *old_reward = Some(new_reward); }); } @@ -149,7 +146,7 @@ mod tests { #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { - schedule_relayers_rewards::(&RELAYER_2, relayers_rewards(), 10); + register_relayers_rewards::(&RELAYER_2, relayers_rewards(), 10); assert_eq!(RelayerRewards::::get(&RELAYER_1), Some(80)); assert_eq!(RelayerRewards::::get(&RELAYER_2), Some(120)); @@ -159,7 +156,7 @@ mod tests { #[test] fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { run_test(|| { - schedule_relayers_rewards::(&RELAYER_3, relayers_rewards(), 10); + register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 10); assert_eq!(RelayerRewards::::get(&RELAYER_1), Some(80)); assert_eq!(RelayerRewards::::get(&RELAYER_2), Some(70)); @@ -170,7 +167,7 @@ mod tests { #[test] fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { run_test(|| { - schedule_relayers_rewards::(&RELAYER_3, relayers_rewards(), 1000); + register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 1000); assert_eq!(RelayerRewards::::get(&RELAYER_1), None); assert_eq!(RelayerRewards::::get(&RELAYER_2), None); diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 0d6d020a0997b..908412477c221 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -8,15 +8,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -# Bridge dependencies - -#bp-runtime = { path = "../runtime", default-features = false } - # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -#frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -27,12 +21,7 @@ hex-literal = "0.3" [features] default = ["std"] std = [ -# "bp-runtime/std", "frame-support/std", -# "frame-system/std", -# "scale-info/std", -# "serde", -# "sp-core/std", "sp-runtime/std", "sp-std/std", ] From 71eafe4428261d65fcc9167181eafad1d34093e0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 16 Aug 2022 17:19:33 +0300 Subject: [PATCH 0760/1210] Declare declare_bridge_chain_runtime_apis! macro Signed-off-by: Serban Iorga --- primitives/chain-kusama/Cargo.toml | 1 + primitives/chain-kusama/src/lib.rs | 71 +-------------- primitives/chain-millau/Cargo.toml | 1 + primitives/chain-millau/src/lib.rs | 72 +-------------- primitives/chain-polkadot/Cargo.toml | 1 + primitives/chain-polkadot/src/lib.rs | 72 +-------------- primitives/chain-rialto-parachain/Cargo.toml | 1 + primitives/chain-rialto-parachain/src/lib.rs | 75 +--------------- primitives/chain-rialto/Cargo.toml | 1 + primitives/chain-rialto/src/lib.rs | 72 +-------------- primitives/chain-rococo/Cargo.toml | 1 + primitives/chain-rococo/src/lib.rs | 71 +-------------- primitives/chain-wococo/Cargo.toml | 1 + primitives/chain-wococo/src/lib.rs | 71 +-------------- primitives/runtime/src/chain.rs | 92 ++++++++++++++++++++ 15 files changed, 113 insertions(+), 490 deletions(-) diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index a676b565c33dc..5e1b91d1cf182 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +paste = "1.0" smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index a72e607ddb29e..ab011d814c0dd 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -29,6 +29,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +use bp_runtime::declare_bridge_chain_runtime_apis; /// Kusama Chain pub type Kusama = PolkadotLike; @@ -90,72 +91,4 @@ pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the Polkadot fee multiplier parameter, stored in the Polkadot runtime. pub const POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME: &str = "PolkadotFeeMultiplier"; -/// Name of the `KusamaFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_KUSAMA_HEADER_METHOD: &str = "KusamaFinalityApi_best_finalized"; - -/// Name of the `ToKusamaOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_KUSAMA_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToKusamaOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToKusamaOutboundLaneApi::message_details` runtime method. -pub const TO_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "ToKusamaOutboundLaneApi_message_details"; - -/// Name of the `FromKusamaInboundLaneApi::message_details` runtime method. -pub const FROM_KUSAMA_MESSAGE_DETAILS_METHOD: &str = "FromKusamaInboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Kusama headers. - /// - /// This API is implemented by runtimes that are bridging with the Kusama chain, not the - /// Kusama runtime itself. - pub trait KusamaFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to Kusama chain. - /// - /// This API is implemented by runtimes that are sending messages to Kusama chain, not the - /// Kusama runtime itself. - pub trait ToKusamaOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Kusama from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - kusama_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by Kusama chain. - /// - /// This API is implemented by runtimes that are receiving messages from Kusama chain, not the - /// Kusama runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromKusamaInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(kusama); diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 4cd8b30f7ff90..7c1e0dab7a571 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 71a545e6ba7bf..4efaeac0f8ce6 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -23,7 +23,7 @@ mod millau_hash; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::Chain; +use bp_runtime::{declare_bridge_chain_runtime_apis, Chain}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, @@ -254,72 +254,4 @@ pub const RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the RialtoParachain fee multiplier parameter, stored in the Millau runtime. pub const RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME: &str = "RialtoParachainFeeMultiplier"; -/// Name of the `MillauFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_MILLAU_HEADER_METHOD: &str = "MillauFinalityApi_best_finalized"; - -/// Name of the `ToMillauOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToMillauOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToMillauOutboundLaneApi::message_details` runtime method. -pub const TO_MILLAU_MESSAGE_DETAILS_METHOD: &str = "ToMillauOutboundLaneApi_message_details"; - -/// Name of the `FromMillauInboundLaneApi::message_details` runtime method. -pub const FROM_MILLAU_MESSAGE_DETAILS_METHOD: &str = "FromMillauInboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Millau headers. - /// - /// This API is implemented by runtimes that are bridging with the Millau chain, not the - /// Millau runtime itself. - pub trait MillauFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to Millau chain. - /// - /// This API is implemented by runtimes that are sending messages to Millau chain, not the - /// Millau runtime itself. - pub trait ToMillauOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Millau from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - millau_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by Millau chain. - /// - /// This API is implemented by runtimes that are receiving messages from Millau chain, not the - /// Millau runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromMillauInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(millau); diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 738899b658cdf..6525ea3b752ba 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] smallvec = "1.7" +paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 2fcfa1f03e883..90184d1feb4a3 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -29,6 +29,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +use bp_runtime::declare_bridge_chain_runtime_apis; /// Polkadot Chain pub type Polkadot = PolkadotLike; @@ -90,73 +91,4 @@ pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the Kusama fee multiplier parameter, stored in the Polkadot runtime. pub const KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME: &str = "KusamaFeeMultiplier"; -/// Name of the `PolkadotFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_POLKADOT_HEADER_METHOD: &str = "PolkadotFinalityApi_best_finalized"; - -/// Name of the `ToPolkadotOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_POLKADOT_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToPolkadotOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToPolkadotOutboundLaneApi::message_details` runtime method. -pub const TO_POLKADOT_MESSAGE_DETAILS_METHOD: &str = "ToPolkadotOutboundLaneApi_message_details"; - -/// Name of the `FromPolkadotInboundLaneApi::message_details` runtime method. -pub const FROM_POLKADOT_MESSAGE_DETAILS_METHOD: &str = - "FromPolkadotOutboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Polkadot headers. - /// - /// This API is implemented by runtimes that are bridging with the Polkadot chain, not the - /// Polkadot runtime itself. - pub trait PolkadotFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to Polkadot chain. - /// - /// This API is implemented by runtimes that are sending messages to Polkadot chain, not the - /// Polkadot runtime itself. - pub trait ToPolkadotOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Polkadot from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - polkadot_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by Polkadot chain. - /// - /// This API is implemented by runtimes that are receiving messages from Polkadot chain, not the - /// Polkadot runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromPolkadotInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(polkadot); diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index a15c40929579b..5bfda1631e5ac 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index baef2e403b498..847ce68ef8e81 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -21,7 +21,7 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::Chain; +use bp_runtime::{declare_bridge_chain_runtime_apis, Chain}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, @@ -193,75 +193,4 @@ pub const MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the Millau fee multiplier parameter, stored in the Rialto parachain runtime. pub const MILLAU_FEE_MULTIPLIER_PARAMETER_NAME: &str = "MillauFeeMultiplier"; -/// Name of the `RialtoParachainFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD: &str = - "RialtoParachainFinalityApi_best_finalized"; - -/// Name of the `ToRialtoParachainOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` -/// runtime method. -pub const TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToRialtoParachainOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToRialtoParachainOutboundLaneApi::message_details` runtime method. -pub const TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = - "ToRialtoParachainOutboundLaneApi_message_details"; - -/// Name of the `FromRialtoParachainInboundLaneApi::message_details` runtime method. -pub const FROM_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD: &str = - "FromRialtoParachainInboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized RialtoParachain headers. - /// - /// This API is implemented by runtimes that are bridging with the RialtoParachain chain, not the - /// RialtoParachain runtime itself. - pub trait RialtoParachainFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to RialtoParachain chain. - /// - /// This API is implemented by runtimes that are sending messages to RialtoParachain chain, not the - /// RialtoParachain runtime itself. - pub trait ToRialtoParachainOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to RialtoParachain from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - rialto_parachain_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by RialtoParachain chain. - /// - /// This API is implemented by runtimes that are receiving messages from RialtoParachain chain, not the - /// RialtoParachain runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromRialtoParachainInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(rialto_parachain); diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index 663f9076657dd..5e02bb454b7d7 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index d242f6dc4ac57..f2293bace0fa5 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -21,7 +21,7 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::Chain; +use bp_runtime::{declare_bridge_chain_runtime_apis, Chain}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, @@ -217,72 +217,4 @@ pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; /// Name of the parachains pallet in the Rialto runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; -/// Name of the `RialtoFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_RIALTO_HEADER_METHOD: &str = "RialtoFinalityApi_best_finalized"; - -/// Name of the `ToRialtoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToRialtoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToRialtoOutboundLaneApi::message_details` runtime method. -pub const TO_RIALTO_MESSAGE_DETAILS_METHOD: &str = "ToRialtoOutboundLaneApi_message_details"; - -/// Name of the `FromRialtoInboundLaneApi::message_details` runtime method. -pub const FROM_RIALTO_MESSAGE_DETAILS_METHOD: &str = "FromRialtoInboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Rialto headers. - /// - /// This API is implemented by runtimes that are bridging with the Rialto chain, not the - /// Rialto runtime itself. - pub trait RialtoFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to Rialto chain. - /// - /// This API is implemented by runtimes that are sending messages to Rialto chain, not the - /// Rialto runtime itself. - pub trait ToRialtoOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Rialto from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - rialto_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by Rialto chain. - /// - /// This API is implemented by runtimes that are receiving messages from Rialto chain, not the - /// Rialto runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromRialtoInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(rialto); diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 814cd09bf170c..ec281790bb055 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +paste = "1.0" smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 45f1937eee58a..feee87c2e5d2e 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -29,6 +29,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +use bp_runtime::declare_bridge_chain_runtime_apis; /// Rococo Chain pub type Rococo = PolkadotLike; @@ -74,19 +75,6 @@ pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; /// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; -/// Name of the `RococoFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_ROCOCO_HEADER_METHOD: &str = "RococoFinalityApi_best_finalized"; - -/// Name of the `ToRococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToRococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToRococoOutboundLaneApi::message_details` runtime method. -pub const TO_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "ToRococoOutboundLaneApi_message_details"; - -/// Name of the `FromRococoInboundLaneApi::message_details` runtime method. -pub const FROM_ROCOCO_MESSAGE_DETAILS_METHOD: &str = "FromRococoInboundLaneApi_message_details"; - /// Existential deposit on Rococo. pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; @@ -99,59 +87,4 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; /// transactions cheaper. pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Rococo headers. - /// - /// This API is implemented by runtimes that are bridging with the Rococo chain, not the - /// Rococo runtime itself. - pub trait RococoFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to Rococo chain. - /// - /// This API is implemented by runtimes that are sending messages to Rococo chain, not the - /// Rococo runtime itself. - pub trait ToRococoOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Rococo from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - rococo_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by Rococo chain. - /// - /// This API is implemented by runtimes that are receiving messages from Rococo chain, not the - /// Rococo runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromRococoInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(rococo); diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 633cdd15c1f56..3cea9f2a148f9 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +paste = "1.0" # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 02276aa7dd865..a2fd5d7c6dacf 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -27,6 +27,7 @@ use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime pub use bp_rococo::{WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, VERSION}; +use bp_runtime::declare_bridge_chain_runtime_apis; /// Wococo Chain pub type Wococo = PolkadotLike; @@ -43,72 +44,4 @@ pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; /// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; -/// Name of the `WococoFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_WOCOCO_HEADER_METHOD: &str = "WococoFinalityApi_best_finalized"; - -/// Name of the `ToWococoOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime -/// method. -pub const TO_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD: &str = - "ToWococoOutboundLaneApi_estimate_message_delivery_and_dispatch_fee"; -/// Name of the `ToWococoOutboundLaneApi::message_details` runtime method. -pub const TO_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "ToWococoOutboundLaneApi_message_details"; - -/// Name of the `FromWococoInboundLaneApi::message_details` runtime method. -pub const FROM_WOCOCO_MESSAGE_DETAILS_METHOD: &str = "FromWococoInboundLaneApi_message_details"; - -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Wococo headers. - /// - /// This API is implemented by runtimes that are bridging with the Wococo chain, not the - /// Wococo runtime itself. - pub trait WococoFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to Wococo chain. - /// - /// This API is implemented by runtimes that are sending messages to Wococo chain, not the - /// Wococo runtime itself. - pub trait ToWococoOutboundLaneApi { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to Wococo from this chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be good idea to pay a bit over this price to account - /// future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - wococo_to_this_conversion_rate: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. - /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by Wococo chain. - /// - /// This API is implemented by runtimes that are receiving messages from Wococo chain, not the - /// Wococo runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait FromWococoInboundLaneApi { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; - } -} +declare_bridge_chain_runtime_apis!(wococo); diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 14035566e6742..c8d5d9b94aacc 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -214,3 +214,95 @@ pub type AccountPublicOf = as Verify>::Signer; /// Transaction era used by the chain. pub type TransactionEraOf = crate::TransactionEra, HashOf>; + +/// Convenience macro that declares runtime apis and related constants for a bridge chain. +/// This includes: +/// - chain-specific bridge runtime APIs: +/// - `FinalityApi` +/// - `ToOutboundLaneApi` +/// - `FromInboundLaneApi` +/// - constants that are stringified names of runtime API methods: +/// - `BEST_FINALIZED__HEADER_METHOD` +/// - `TO__ESTIMATE_MESSAGE_FEE_METHOD` +/// - `TO__MESSAGE_DETAILS_METHOD` +/// - `FROM__MESSAGE_DETAILS_METHOD`, +/// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). +#[macro_export] +macro_rules! declare_bridge_chain_runtime_apis { + ($chain: ident) => { + paste::item! { + /// Name of the `FinalityApi::best_finalized` runtime method. + pub const []: &str = + stringify!([<$chain:camel FinalityApi_best_finalized>]); + + /// Name of the `ToOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime + /// method. + pub const []: &str = + stringify!([]); + /// Name of the `ToOutboundLaneApi::message_details` runtime method. + pub const []: &str = + stringify!([]); + + /// Name of the `FromInboundLaneApi::message_details` runtime method. + pub const []: &str = + stringify!([]); + + sp_api::decl_runtime_apis! { + /// API for querying information about the finalized chain headers. + /// + /// This API is implemented by runtimes that are receiving messages from this chain, not by this + /// chain's runtime itself. + pub trait [<$chain:camel FinalityApi>] { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> Option>; + } + + /// Outbound message lane API for messages that are sent to this chain. + /// + /// This API is implemented by runtimes that are receiving messages from this chain, not by this + /// chain's runtime itself. + pub trait [] { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to this chain from the bridged chain. + /// + /// Please keep in mind that this method returns the lowest message fee required for message + /// to be accepted to the lane. It may be a good idea to pay a bit over this price to account + /// for future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + [<$chain:lower _to_this_conversion_rate>]: Option, + ) -> Option; + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn message_details( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by this chain. + /// + /// This API is implemented by runtimes that are receiving messages from this chain, not by this + /// chain's runtime itself. + /// + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait [] { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; + } + } + } + } +} From 849a95776828e361799e75b6c63da4983952afc7 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 18 Aug 2022 14:16:58 +0200 Subject: [PATCH 0761/1210] Bko cosmetics (#1550) * Bump log version to 0.4.17 * Removed unnecesseray dependency + rename BridgeGrandpaMillauCall to BridgeGrandpaCall --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 4 +--- relays/bin-substrate/src/cli/init_bridge.rs | 4 +--- relays/client-millau/Cargo.toml | 1 - relays/client-substrate/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 19 files changed, 18 insertions(+), 23 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 33bdcca35cf76..e3c04e4d7a076 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 26b91019c1e0e..5a5d307aeb522 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -19,7 +19,7 @@ runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] clap = { version = "3.1", features = ["derive"] } derive_more = '0.99.2' -log = '0.4.14' +log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.0.0' } serde = { version = '1.0', features = ['derive'] } hex-literal = '0.3.1' diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 6c3d838196a42..a72b284daf6f7 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -11,7 +11,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.0.0', default-features = false, features = ['derive']} -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = '1.0', optional = true, features = ['derive'] } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index a29560a65d9a0..b2ba7da2febe7 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 56cbca221d456..acca140d325d4 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -70,7 +70,7 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; -pub use pallet_bridge_grandpa::Call as BridgeGrandpaMillauCall; +pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 121ef318fbb08..1d09192ced55d 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hash-db = { version = "0.15.2", default-features = false } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index f4a64758aa923..89cfb5e164040 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } finality-grandpa = { version = "0.15.0", default-features = false } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 5f98523266f75..b6fc8c604bc35 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 8636c7a40b6d2..2a8ab1d09d139 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index ef689f55918b2..b3f5475d429b2 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.14", default-features = false } +log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true, features = ["derive"] } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 56d669e49735e..b780c33ead095 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -12,7 +12,7 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" hex = "0.4" -log = "0.4.14" +log = "0.4.17" num-format = "0.4" num-traits = "0.2" paste = "1.0" @@ -35,7 +35,6 @@ bridge-runtime-common = { path = "../../bin/runtime-common" } finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } -pallet-bridge-grandpa = { path = "../../modules/grandpa" } pallet-bridge-messages = { path = "../../modules/messages" } pallet-bridge-parachains = { path = "../../modules/parachains" } parachains-relay = { path = "../parachains" } @@ -70,7 +69,6 @@ xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", d [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" -pallet-bridge-grandpa = { path = "../../modules/grandpa" } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempfile = "3.2" finality-grandpa = { version = "0.15.0" } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 971512f2111b1..150c55d9c6c67 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -112,9 +112,7 @@ impl BridgeInitializer for MillauToRialtoCliBridge { init_data: >::InitializationData, ) -> ::Call { rialto_runtime::SudoCall::sudo { - call: Box::new( - rialto_runtime::BridgeGrandpaMillauCall::initialize { init_data }.into(), - ), + call: Box::new(rialto_runtime::BridgeGrandpaCall::initialize { init_data }.into()), } .into() } diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index ab342f63ad9a4..9893243345518 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -15,7 +15,6 @@ relay-utils = { path = "../utils" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } millau-runtime = { path = "../../bin/millau/runtime" } -pallet-bridge-grandpa = { path = "../../modules/grandpa" } # Substrate Dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 91fd8eb10a0e7..ab6c9f9536fed 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -11,7 +11,7 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.7" jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } -log = "0.4.11" +log = "0.4.17" num-traits = "0.2" rand = "0.7" serde = { version = "1.0" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 692e902ace427..ae4be5b5524d5 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -12,7 +12,7 @@ async-trait = "0.1" backoff = "0.2" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.5" -log = "0.4.11" +log = "0.4.17" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index a74ebf3e183bd..70b319854883b 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.0.0" } futures = "0.3.12" num-traits = "0.2" -log = "0.4.14" +log = "0.4.17" # Bridge dependencies diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index af967f34acdad..02e453b1c32a4 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -10,7 +10,7 @@ async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" futures = "0.3.5" hex = "0.4" -log = "0.4.11" +log = "0.4.17" num-traits = "0.2" parking_lot = "0.11.0" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index e5c0cea137bfa..6115a2d6ce28d 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -11,7 +11,7 @@ async-trait = "0.1.40" backoff = "0.2" futures = "0.3.5" linked-hash-map = "0.5.3" -log = "0.4.11" +log = "0.4.17" num-traits = "0.2" parking_lot = "0.11.0" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index af5baa5ccf00d..ebbfa74c6ff81 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -15,7 +15,7 @@ isahc = "1.2" env_logger = "0.8.2" futures = "0.3.5" jsonpath_lib = "0.2" -log = "0.4.11" +log = "0.4.17" num-traits = "0.2" serde_json = "1.0" sysinfo = "0.15" From cbdc27e14c8fd8ccf33ea9830426dfdab15e1113 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 18 Aug 2022 15:33:17 +0300 Subject: [PATCH 0762/1210] Follow-up on #1536 (#1549) * Make RelayStrategy::final_decision() sync Signed-off-by: Serban Iorga * Move logic from RelayStrategy to RelayReference Signed-off-by: Serban Iorga * Rename RelayStrategy::final_decision() Signed-off-by: Serban Iorga --- .../src/relay_strategy/altruistic_strategy.rs | 22 +++-- .../relay_strategy/enforcement_strategy.rs | 2 +- .../src/relay_strategy/mix_strategy.rs | 6 +- relays/messages/src/relay_strategy/mod.rs | 90 ++++++++++++++++- .../src/relay_strategy/rational_strategy.rs | 98 ++----------------- 5 files changed, 116 insertions(+), 102 deletions(-) diff --git a/relays/messages/src/relay_strategy/altruistic_strategy.rs b/relays/messages/src/relay_strategy/altruistic_strategy.rs index b66129117873e..7e00678e1317f 100644 --- a/relays/messages/src/relay_strategy/altruistic_strategy.rs +++ b/relays/messages/src/relay_strategy/altruistic_strategy.rs @@ -23,7 +23,7 @@ use crate::{ message_lane_loop::{ SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, }, - relay_strategy::{RationalStrategy, RelayReference, RelayStrategy}, + relay_strategy::{RelayReference, RelayStrategy}, }; /// The relayer doesn't care about rewards. @@ -40,13 +40,20 @@ impl RelayStrategy for AltruisticStrategy { &mut self, reference: &mut RelayReference, ) -> bool { - // we don't care about costs and rewards, but we want to report unprofitable transactions - // => let rational strategy fill required fields - let _ = RationalStrategy.decide(reference).await; + // We don't care about costs and rewards, but we want to report unprofitable transactions. + if let Err(e) = reference.update_cost_and_reward().await { + log::debug!( + target: "bridge", + "Failed to update transaction cost and reward: {:?}. \ + The `unprofitable_delivery_transactions` metric will be inaccurate", + e, + ); + } + true } - async fn final_decision< + fn on_final_decision< P: MessageLane, SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, @@ -55,10 +62,11 @@ impl RelayStrategy for AltruisticStrategy { reference: &RelayReference, ) { if let Some(ref metrics) = reference.metrics { - if reference.total_cost > reference.total_reward { + if !reference.is_profitable() { log::debug!( target: "bridge", - "The relayer has submitted unprofitable {} -> {} message delivery trabsaction with {} messages: total cost = {:?}, total reward = {:?}", + "The relayer has submitted unprofitable {} -> {} message delivery transaction \ + with {} messages: total cost = {:?}, total reward = {:?}", P::SOURCE_NAME, P::TARGET_NAME, reference.index + 1, diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/relay_strategy/enforcement_strategy.rs index 5d231462e86d9..bb4192d45ab05 100644 --- a/relays/messages/src/relay_strategy/enforcement_strategy.rs +++ b/relays/messages/src/relay_strategy/enforcement_strategy.rs @@ -214,7 +214,7 @@ impl EnforcementStrategy { let selected_max_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; - self.strategy.final_decision(&relay_reference).await; + self.strategy.on_final_decision(&relay_reference); Some(selected_max_nonce) } else { None diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs index d00c27196787c..331f77b012d22 100644 --- a/relays/messages/src/relay_strategy/mix_strategy.rs +++ b/relays/messages/src/relay_strategy/mix_strategy.rs @@ -56,7 +56,7 @@ impl RelayStrategy for MixStrategy { } } - async fn final_decision< + fn on_final_decision< P: MessageLane, SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, @@ -65,8 +65,8 @@ impl RelayStrategy for MixStrategy { reference: &RelayReference, ) { match self.relayer_mode { - RelayerMode::Altruistic => AltruisticStrategy.final_decision(reference).await, - RelayerMode::Rational => RationalStrategy.final_decision(reference).await, + RelayerMode::Altruistic => AltruisticStrategy.on_final_decision(reference), + RelayerMode::Rational => RationalStrategy.on_final_decision(reference), } } } diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs index da615f34e8659..7bfd74c4790f8 100644 --- a/relays/messages/src/relay_strategy/mod.rs +++ b/relays/messages/src/relay_strategy/mod.rs @@ -18,6 +18,7 @@ use async_trait::async_trait; use bp_messages::{MessageNonce, Weight}; +use sp_arithmetic::traits::Saturating; use std::ops::Range; use crate::{ @@ -56,7 +57,7 @@ pub trait RelayStrategy: 'static + Clone + Send + Sync { ) -> bool; /// Notification that the following maximal nonce has been selected for the delivery. - async fn final_decision< + fn on_final_decision< P: MessageLane, SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, @@ -66,6 +67,14 @@ pub trait RelayStrategy: 'static + Clone + Send + Sync { ); } +/// Total cost of mesage delivery and confirmation. +struct MessagesDeliveryCost { + /// Cost of message delivery transaction. + pub delivery_transaction_cost: SourceChainBalance, + /// Cost of confirmation delivery transaction. + pub confirmation_transaction_cost: SourceChainBalance, +} + /// Reference data for participating in relay pub struct RelayReference< P: MessageLane, @@ -107,6 +116,85 @@ pub struct RelayReference< pub details: MessageDetails, } +impl< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, + > RelayReference +{ + /// Returns whether the current `RelayReference` is profitable. + pub fn is_profitable(&self) -> bool { + self.total_reward >= self.total_cost + } + + async fn estimate_messages_delivery_cost( + &self, + ) -> Result, TargetClient::Error> { + // technically, multiple confirmations will be delivered in a single transaction, + // meaning less loses for relayer. But here we don't know the final relayer yet, so + // we're adding a separate transaction for every message. Normally, this cost is covered + // by the message sender. Probably reconsider this? + let confirmation_transaction_cost = + self.lane_source_client.estimate_confirmation_transaction().await; + + let delivery_transaction_cost = self + .lane_target_client + .estimate_delivery_transaction_in_source_tokens( + self.hard_selected_begin_nonce..= + (self.hard_selected_begin_nonce + self.index as MessageNonce), + self.selected_prepaid_nonces, + self.selected_unpaid_weight, + self.selected_size as u32, + ) + .await?; + + Ok(MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost }) + } + + async fn update_cost_and_reward(&mut self) -> Result<(), TargetClient::Error> { + let prev_is_profitable = self.is_profitable(); + let prev_total_cost = self.total_cost; + let prev_total_reward = self.total_reward; + + let MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost } = + self.estimate_messages_delivery_cost().await?; + self.total_confirmations_cost = + self.total_confirmations_cost.saturating_add(confirmation_transaction_cost); + self.total_reward = self.total_reward.saturating_add(self.details.reward); + self.total_cost = self.total_confirmations_cost.saturating_add(delivery_transaction_cost); + + if prev_is_profitable && !self.is_profitable() { + // if it is the first message that makes reward less than cost, let's log it + log::debug!( + target: "bridge", + "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ + total reward {:?}->{:?}", + self.nonce, + self.details.reward, + prev_total_cost, + self.total_cost, + prev_total_reward, + self.total_reward, + ); + } else if !prev_is_profitable && self.is_profitable() { + // if this message makes batch profitable again, let's log it + log::debug!( + target: "bridge", + "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ + equal to the total reward {:?}->{:?} (again)", + self.nonce, + self.details.reward, + prev_total_cost, + self.total_cost, + prev_total_reward, + self.total_reward, + ); + } + + Ok(()) + } +} + /// Relay reference data pub struct RelayMessagesBatchReference< P: MessageLane, diff --git a/relays/messages/src/relay_strategy/rational_strategy.rs b/relays/messages/src/relay_strategy/rational_strategy.rs index f45f01725c631..1791670fa45a8 100644 --- a/relays/messages/src/relay_strategy/rational_strategy.rs +++ b/relays/messages/src/relay_strategy/rational_strategy.rs @@ -17,9 +17,6 @@ //! Rational relay strategy use async_trait::async_trait; -use num_traits::SaturatingAdd; - -use bp_messages::MessageNonce; use crate::{ message_lane::MessageLane, @@ -44,60 +41,18 @@ impl RelayStrategy for RationalStrategy { &mut self, reference: &mut RelayReference, ) -> bool { - let total_cost = match estimate_messages_delivery_cost(reference).await { - Ok(total_cost) => total_cost, - Err(err) => { - log::debug!( - target: "bridge", - "Failed to estimate delivery transaction cost: {:?}. No nonces selected for delivery", - err, - ); - - return false - }, - }; - - // if it is the first message that makes reward less than cost, let's log it - // if this message makes batch profitable again, let's log it - let MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost } = - total_cost; - let is_total_reward_less_than_cost = reference.total_reward < reference.total_cost; - let prev_total_cost = reference.total_cost; - let prev_total_reward = reference.total_reward; - reference.total_confirmations_cost = reference - .total_confirmations_cost - .saturating_add(&confirmation_transaction_cost); - reference.total_reward = reference.total_reward.saturating_add(&reference.details.reward); - reference.total_cost = - reference.total_confirmations_cost.saturating_add(&delivery_transaction_cost); - if !is_total_reward_less_than_cost && reference.total_reward < reference.total_cost { + if let Err(e) = reference.update_cost_and_reward().await { log::debug!( target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ - total reward {:?}->{:?}", - reference.nonce, - reference.details.reward, - prev_total_cost, - reference.total_cost, - prev_total_reward, - reference.total_reward, - ); - } else if is_total_reward_less_than_cost && reference.total_reward >= reference.total_cost { - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ - equal to the total reward {:?}->{:?} (again)", - reference.nonce, - reference.details.reward, - prev_total_cost, - reference.total_cost, - prev_total_reward, - reference.total_reward, + "Failed to update transaction cost and reward: {:?}. No nonces selected for delivery", + e, ); + + return false } - // Rational relayer never want to lose his funds - if reference.total_reward >= reference.total_cost { + // Rational relayer never wants to lose his funds. + if reference.is_profitable() { reference.selected_reward = reference.total_reward; reference.selected_cost = reference.total_cost; return true @@ -106,7 +61,7 @@ impl RelayStrategy for RationalStrategy { false } - async fn final_decision< + fn on_final_decision< P: MessageLane, SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, @@ -118,40 +73,3 @@ impl RelayStrategy for RationalStrategy { // anything here } } - -/// Total cost of mesage delivery and confirmation. -struct MessagesDeliveryCost { - /// Cost of message delivery transaction. - pub delivery_transaction_cost: SourceChainBalance, - /// Cost of confirmation delivery transaction. - pub confirmation_transaction_cost: SourceChainBalance, -} - -/// Returns cost of message delivery and confirmation delivery transactions -async fn estimate_messages_delivery_cost< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, ->( - reference: &RelayReference, -) -> Result, TargetClient::Error> { - // technically, multiple confirmations will be delivered in a single transaction, - // meaning less loses for relayer. But here we don't know the final relayer yet, so - // we're adding a separate transaction for every message. Normally, this cost is covered - // by the message sender. Probably reconsider this? - let confirmation_transaction_cost = - reference.lane_source_client.estimate_confirmation_transaction().await; - - let delivery_transaction_cost = reference - .lane_target_client - .estimate_delivery_transaction_in_source_tokens( - reference.hard_selected_begin_nonce..= - (reference.hard_selected_begin_nonce + reference.index as MessageNonce), - reference.selected_prepaid_nonces, - reference.selected_unpaid_weight, - reference.selected_size as u32, - ) - .await?; - - Ok(MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost }) -} From d5c2272f10a70def441593583a81efe32adcbd3b Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 19 Aug 2022 11:31:30 +0200 Subject: [PATCH 0763/1210] Bump codec version 3.0.0 -> 3.1.5 + unify parity-scale-codec vs codec (#1552) --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- primitives/chain-rococo/Cargo.toml | 4 ++-- primitives/chain-westend/Cargo.toml | 4 ++-- primitives/chain-westend/src/lib.rs | 4 +--- primitives/chain-wococo/Cargo.toml | 4 ++-- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 4 ++-- primitives/polkadot-core/src/lib.rs | 21 ++++++--------------- primitives/polkadot-core/src/parachains.rs | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/client-millau/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-rialto/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-westend/Cargo.toml | 1 - relays/lib-substrate-relay/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- 30 files changed, 38 insertions(+), 50 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index e3c04e4d7a076..05e79074b6891 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 5a5d307aeb522..75a7297f3f099 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -20,7 +20,7 @@ runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] clap = { version = "3.1", features = ["derive"] } derive_more = '0.99.2' log = '0.4.17' -codec = { package = 'parity-scale-codec', version = '3.0.0' } +codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } hex-literal = '0.3.1' diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index a72b284daf6f7..d125931220f10 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } [dependencies] -codec = { package = 'parity-scale-codec', version = '3.0.0', default-features = false, features = ['derive']} +codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = '1.0', optional = true, features = ['derive'] } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index b2ba7da2febe7..8d90f1f3296cf 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hex-literal = "0.3" libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.17", default-features = false } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 1d09192ced55d..bb75d828d28fd 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.15.2", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 89cfb5e164040..645f2b72a8180 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.15.0", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index b6fc8c604bc35..78a70b9bd580d 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bitvec = { version = "1", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 2a8ab1d09d139..99e91180b38d2 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.101", optional = true } diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index b3f5475d429b2..70720a211cecb 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index bf7365166399a..5dae3e00fd3b8 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index ec281790bb055..8c02dcccf8489 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } paste = "1.0" smallvec = "1.7" @@ -30,7 +30,7 @@ std = [ "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", - "parity-scale-codec/std", + "codec/std", "sp-api/std", "sp-runtime/std", "sp-std/std", diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 6a894f35c2a4c..f37aa3b0e397e 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } smallvec = "1.7" @@ -32,7 +32,7 @@ std = [ "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", - "parity-scale-codec/std", + "codec/std", "scale-info/std", "sp-api/std", "sp-runtime/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index e0ac5ad961f7b..c914cf0f0c347 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -63,9 +63,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// Westend Runtime `Call` enum. /// /// We are not currently submitting any Westend transactions => it is empty. -#[derive( - parity_scale_codec::Encode, parity_scale_codec::Decode, Debug, PartialEq, Eq, Clone, TypeInfo, -)] +#[derive(codec::Encode, codec::Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call {} impl sp_runtime::traits::Dispatchable for Call { diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 3cea9f2a148f9..44af20b726f5e 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } paste = "1.0" # Bridge Dependencies @@ -28,7 +28,7 @@ std = [ "bp-polkadot-core/std", "bp-runtime/std", "bp-rococo/std", - "parity-scale-codec/std", + "codec/std", "sp-api/std", "sp-runtime/std", "sp-std/std", diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index c925abf962b2b..3a423292277ce 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.15.0", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index af5e801f8d2fa..6690a1bfbb070 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bitvec = { version = "1", default-features = false, features = ["alloc"] } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index a27dd03363d47..f6327c772c0da 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 6fa78cd349596..4448e75f11a45 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.11.0", optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } @@ -37,7 +37,7 @@ std = [ "bp-runtime/std", "frame-support/std", "frame-system/std", - "parity-scale-codec/std", + "codec/std", "parity-util-mem", "scale-info/std", "serde", diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 6245c2b1694d9..476b1f2f23061 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -18,6 +18,7 @@ use bp_messages::MessageNonce; use bp_runtime::{Chain, EncodedOrDecodedCall}; +use codec::Compact; use frame_support::{ dispatch::Dispatchable, parameter_types, @@ -28,7 +29,6 @@ use frame_support::{ Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128, }; use frame_system::limits; -use parity_scale_codec::Compact; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_core::Hasher as HasherT; use sp_runtime::{ @@ -256,16 +256,14 @@ pub struct SignedExtensions { _data: sp_std::marker::PhantomData, } -impl parity_scale_codec::Encode for SignedExtensions { +impl codec::Encode for SignedExtensions { fn using_encoded R>(&self, f: F) -> R { self.encode_payload.using_encoded(f) } } -impl parity_scale_codec::Decode for SignedExtensions { - fn decode( - input: &mut I, - ) -> Result { +impl codec::Decode for SignedExtensions { + fn decode(input: &mut I) -> Result { SignedExtra::decode(input).map(|encode_payload| SignedExtensions { encode_payload, additional_signed: None, @@ -323,14 +321,7 @@ impl SignedExtensions { impl sp_runtime::traits::SignedExtension for SignedExtensions where - Call: parity_scale_codec::Codec - + sp_std::fmt::Debug - + Sync - + Send - + Clone - + Eq - + PartialEq - + StaticTypeInfo, + Call: codec::Codec + sp_std::fmt::Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo, Call: Dispatchable, { const IDENTIFIER: &'static str = "Not needed."; @@ -399,7 +390,7 @@ impl Chain for PolkadotLike { pub fn account_info_storage_key(id: &AccountId) -> Vec { let module_prefix_hashed = Twox128::hash(b"System"); let storage_prefix_hashed = Twox128::hash(b"Account"); - let key_hashed = parity_scale_codec::Encode::using_encoded(id, Blake2_128Concat::hash); + let key_hashed = codec::Encode::using_encoded(id, Blake2_128Concat::hash); let mut final_key = Vec::with_capacity( module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len(), diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 59b895065e179..51fcd59cae13f 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -23,8 +23,8 @@ //! be two versions of polkadot crates included in the runtime. Which is bad. use bp_runtime::Size; +use codec::{CompactAs, Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; -use parity_scale_codec::{CompactAs, Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_core::Hasher; use sp_std::vec::Vec; diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 94dd12175d9d6..db0b730f81b58 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } hash-db = { version = "0.15.2", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 6da5c7c0f4b5f..70a8fa6bd94f6 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.15.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index b780c33ead095..ff7496f16ec72 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.12" hex = "0.4" log = "0.4.17" diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 9893243345518..66395d5de897c 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 190f3b0f7e317..915d0e786cc75 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 37c55dd5f153f..ef339feb8a556 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index ab6c9f9536fed..721415fb2d9e6 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.7" jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } log = "0.4.17" diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index d38aa16299459..2ad9963406775 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 70b319854883b..cd8cb51739399 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0" thiserror = "1.0.26" async-std = "1.9.0" async-trait = "0.1" -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.12" num-traits = "0.2" log = "0.4.17" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 6115a2d6ce28d..60ac120d7bcef 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -23,6 +23,6 @@ bp-polkadot-core = { path = "../../primitives/polkadot-core" } relay-substrate-client = { path = "../client-substrate" } [dev-dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } +codec = { package = "parity-scale-codec", version = "3.1.5" } relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } From 34de4aabc61f3edd1b11f53b72a969e95e09a2ef Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 22 Aug 2022 15:46:19 +0300 Subject: [PATCH 0764/1210] Split decl_bridge_runtime_apis!() (#1553) Signed-off-by: Serban Iorga Signed-off-by: Serban Iorga --- primitives/chain-kusama/src/lib.rs | 6 +- primitives/chain-millau/src/lib.rs | 7 +- primitives/chain-polkadot/src/lib.rs | 6 +- primitives/chain-rialto-parachain/src/lib.rs | 7 +- primitives/chain-rialto/src/lib.rs | 7 +- primitives/chain-rococo/src/lib.rs | 6 +- primitives/chain-westend/Cargo.toml | 1 + primitives/chain-westend/src/lib.rs | 29 +-- primitives/chain-wococo/src/lib.rs | 6 +- primitives/runtime/src/chain.rs | 177 +++++++++++-------- 10 files changed, 143 insertions(+), 109 deletions(-) diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index ab011d814c0dd..598e5730253d6 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -29,7 +29,9 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; -use bp_runtime::declare_bridge_chain_runtime_apis; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, +}; /// Kusama Chain pub type Kusama = PolkadotLike; @@ -91,4 +93,4 @@ pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the Polkadot fee multiplier parameter, stored in the Polkadot runtime. pub const POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME: &str = "PolkadotFeeMultiplier"; -declare_bridge_chain_runtime_apis!(kusama); +decl_bridge_runtime_apis!(kusama); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 4efaeac0f8ce6..536a9216c80e4 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -23,7 +23,10 @@ mod millau_hash; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{declare_bridge_chain_runtime_apis, Chain}; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, + Chain, +}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, @@ -254,4 +257,4 @@ pub const RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the RialtoParachain fee multiplier parameter, stored in the Millau runtime. pub const RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME: &str = "RialtoParachainFeeMultiplier"; -declare_bridge_chain_runtime_apis!(millau); +decl_bridge_runtime_apis!(millau); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 90184d1feb4a3..7519c38878dfe 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -29,7 +29,9 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; -use bp_runtime::declare_bridge_chain_runtime_apis; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, +}; /// Polkadot Chain pub type Polkadot = PolkadotLike; @@ -91,4 +93,4 @@ pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the Kusama fee multiplier parameter, stored in the Polkadot runtime. pub const KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME: &str = "KusamaFeeMultiplier"; -declare_bridge_chain_runtime_apis!(polkadot); +decl_bridge_runtime_apis!(polkadot); diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 847ce68ef8e81..285f7f0f184bd 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -21,7 +21,10 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{declare_bridge_chain_runtime_apis, Chain}; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, + Chain, +}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, @@ -193,4 +196,4 @@ pub const MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME: &str = /// Name of the Millau fee multiplier parameter, stored in the Rialto parachain runtime. pub const MILLAU_FEE_MULTIPLIER_PARAMETER_NAME: &str = "MillauFeeMultiplier"; -declare_bridge_chain_runtime_apis!(rialto_parachain); +decl_bridge_runtime_apis!(rialto_parachain); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index f2293bace0fa5..cd4a81264d192 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -21,7 +21,10 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{declare_bridge_chain_runtime_apis, Chain}; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, + Chain, +}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, @@ -217,4 +220,4 @@ pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; /// Name of the parachains pallet in the Rialto runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; -declare_bridge_chain_runtime_apis!(rialto); +decl_bridge_runtime_apis!(rialto); diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index feee87c2e5d2e..dfc31c827376d 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -29,7 +29,9 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; -use bp_runtime::declare_bridge_chain_runtime_apis; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, +}; /// Rococo Chain pub type Rococo = PolkadotLike; @@ -87,4 +89,4 @@ pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; /// transactions cheaper. pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; -declare_bridge_chain_runtime_apis!(rococo); +decl_bridge_runtime_apis!(rococo); diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index f37aa3b0e397e..fb2f846f7efd3 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +paste = "1.0" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } smallvec = "1.7" diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index c914cf0f0c347..1e023295a8a0f 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -26,6 +26,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; +use bp_runtime::decl_bridge_finality_runtime_apis; /// Westend Chain pub type Westend = PolkadotLike; @@ -85,9 +86,6 @@ pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; /// Name of the With-Westend parachains bridge pallet instance that is deployed at bridged chains. pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains"; -/// Name of the `WestendFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_finalized"; - /// The target length of a session (how often authorities change) on Westend measured in of number /// of blocks. /// @@ -95,28 +93,9 @@ pub const BEST_FINALIZED_WESTEND_HEADER_METHOD: &str = "WestendFinalityApi_best_ /// conditions. pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; -sp_api::decl_runtime_apis! { - /// API for querying information about the finalized Westend headers. - /// - /// This API is implemented by runtimes that are bridging with the Westend chain, not the - /// Westend runtime itself. - pub trait WestendFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// API for querying information about the finalized Westmint headers. - /// - /// This API is implemented by runtimes that are bridging with the Westmint chain, not the - /// Westmint runtime itself. - pub trait WestmintFinalityApi { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } -} - /// Identifier of Westmint parachain at the Westend relay chain. pub const WESTMINT_PARACHAIN_ID: u32 = 2000; -/// Name of the `WestmintFinalityApi::best_finalized` runtime method. -pub const BEST_FINALIZED_WESTMINT_HEADER_METHOD: &str = "WestmintFinalityApi_best_finalized"; +decl_bridge_finality_runtime_apis!(westend); + +decl_bridge_finality_runtime_apis!(westmint); diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index a2fd5d7c6dacf..6db6e2fe6fd95 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -27,7 +27,9 @@ use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime pub use bp_rococo::{WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, VERSION}; -use bp_runtime::declare_bridge_chain_runtime_apis; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, +}; /// Wococo Chain pub type Wococo = PolkadotLike; @@ -44,4 +46,4 @@ pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; /// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; -declare_bridge_chain_runtime_apis!(wococo); +decl_bridge_runtime_apis!(wococo); diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index c8d5d9b94aacc..154603ccd3a10 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -215,94 +215,131 @@ pub type AccountPublicOf = as Verify>::Signer; /// Transaction era used by the chain. pub type TransactionEraOf = crate::TransactionEra, HashOf>; -/// Convenience macro that declares runtime apis and related constants for a bridge chain. +/// Convenience macro that declares bridge finality runtime apis and related constants for a chain. /// This includes: /// - chain-specific bridge runtime APIs: /// - `FinalityApi` +/// - constants that are stringified names of runtime API methods: +/// - `BEST_FINALIZED__HEADER_METHOD` +/// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). +#[macro_export] +macro_rules! decl_bridge_finality_runtime_apis { + ($chain: ident) => { + paste::item! { + mod [<$chain _finality_api>] { + use super::*; + + /// Name of the `FinalityApi::best_finalized` runtime method. + pub const []: &str = + stringify!([<$chain:camel FinalityApi_best_finalized>]); + + sp_api::decl_runtime_apis! { + /// API for querying information about the finalized chain headers. + /// + /// This API is implemented by runtimes that are receiving messages from this chain, not by this + /// chain's runtime itself. + pub trait [<$chain:camel FinalityApi>] { + /// Returns number and hash of the best finalized header known to the bridge module. + fn best_finalized() -> Option>; + } + } + } + + pub use [<$chain _finality_api>]::*; + } + }; +} + +/// Convenience macro that declares bridge messages runtime apis and related constants for a chain. +/// This includes: +/// - chain-specific bridge runtime APIs: /// - `ToOutboundLaneApi` /// - `FromInboundLaneApi` /// - constants that are stringified names of runtime API methods: -/// - `BEST_FINALIZED__HEADER_METHOD` /// - `TO__ESTIMATE_MESSAGE_FEE_METHOD` /// - `TO__MESSAGE_DETAILS_METHOD` /// - `FROM__MESSAGE_DETAILS_METHOD`, /// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). #[macro_export] -macro_rules! declare_bridge_chain_runtime_apis { +macro_rules! decl_bridge_messages_runtime_apis { ($chain: ident) => { paste::item! { - /// Name of the `FinalityApi::best_finalized` runtime method. - pub const []: &str = - stringify!([<$chain:camel FinalityApi_best_finalized>]); - - /// Name of the `ToOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime - /// method. - pub const []: &str = - stringify!([]); - /// Name of the `ToOutboundLaneApi::message_details` runtime method. - pub const []: &str = - stringify!([]); - - /// Name of the `FromInboundLaneApi::message_details` runtime method. - pub const []: &str = - stringify!([]); - - sp_api::decl_runtime_apis! { - /// API for querying information about the finalized chain headers. - /// - /// This API is implemented by runtimes that are receiving messages from this chain, not by this - /// chain's runtime itself. - pub trait [<$chain:camel FinalityApi>] { - /// Returns number and hash of the best finalized header known to the bridge module. - fn best_finalized() -> Option>; - } - - /// Outbound message lane API for messages that are sent to this chain. - /// - /// This API is implemented by runtimes that are receiving messages from this chain, not by this - /// chain's runtime itself. - pub trait [] { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. + mod [<$chain _messages_api>] { + use super::*; + + /// Name of the `ToOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime + /// method. + pub const []: &str = + stringify!([]); + /// Name of the `ToOutboundLaneApi::message_details` runtime method. + pub const []: &str = + stringify!([]); + + /// Name of the `FromInboundLaneApi::message_details` runtime method. + pub const []: &str = + stringify!([]); + + sp_api::decl_runtime_apis! { + /// Outbound message lane API for messages that are sent to this chain. /// - /// Returns `None` if message is too expensive to be sent to this chain from the bridged chain. + /// This API is implemented by runtimes that are receiving messages from this chain, not by this + /// chain's runtime itself. + pub trait [] { + /// Estimate message delivery and dispatch fee that needs to be paid by the sender on + /// this chain. + /// + /// Returns `None` if message is too expensive to be sent to this chain from the bridged chain. + /// + /// Please keep in mind that this method returns the lowest message fee required for message + /// to be accepted to the lane. It may be a good idea to pay a bit over this price to account + /// for future exchange rate changes and guarantee that relayer would deliver your message + /// to the target chain. + fn estimate_message_delivery_and_dispatch_fee( + lane_id: LaneId, + payload: OutboundPayload, + [<$chain:lower _to_this_conversion_rate>]: Option, + ) -> Option; + /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all + /// messages in given inclusive range. + /// + /// If some (or all) messages are missing from the storage, they'll also will + /// be missing from the resulting vector. The vector is ordered by the nonce. + fn message_details( + lane: LaneId, + begin: MessageNonce, + end: MessageNonce, + ) -> Vec>; + } + + /// Inbound message lane API for messages sent by this chain. /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be a good idea to pay a bit over this price to account - /// for future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - [<$chain:lower _to_this_conversion_rate>]: Option, - ) -> Option; - /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all - /// messages in given inclusive range. + /// This API is implemented by runtimes that are receiving messages from this chain, not by this + /// chain's runtime itself. /// - /// If some (or all) messages are missing from the storage, they'll also will - /// be missing from the resulting vector. The vector is ordered by the nonce. - fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec>; - } - - /// Inbound message lane API for messages sent by this chain. - /// - /// This API is implemented by runtimes that are receiving messages from this chain, not by this - /// chain's runtime itself. - /// - /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the - /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait [] { - /// Return details of given inbound messages. - fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; + /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the + /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. + pub trait [] { + /// Return details of given inbound messages. + fn message_details( + lane: LaneId, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, + ) -> Vec; + } } } + + pub use [<$chain _messages_api>]::*; } } } + +/// Convenience macro that declares bridge finality runtime apis, bridge messages runtime apis +/// and related constants for a chain. +/// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). +#[macro_export] +macro_rules! decl_bridge_runtime_apis { + ($chain: ident) => { + decl_bridge_finality_runtime_apis!($chain); + decl_bridge_messages_runtime_apis!($chain); + }; +} From 4a908fd37c343c6ed37d6fa7ba27b16a19b233bd Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 26 Aug 2022 16:24:36 +0200 Subject: [PATCH 0765/1210] Reexport paste from `sp-runtime` in `bp-runtime` to aviod including `paste` dependency everywhere (#1556) * Reexport paste from `sp-runtime` in `bp-runtime` to aviod including `paste` dependency everywhere * Add import `bp_runtime` to macro calls: decl_bridge_finality_runtime_apis/decl_bridge_messages_runtime_apis --- primitives/chain-kusama/Cargo.toml | 1 - primitives/chain-kusama/src/lib.rs | 4 +--- primitives/chain-millau/Cargo.toml | 1 - primitives/chain-millau/src/lib.rs | 5 +---- primitives/chain-polkadot/Cargo.toml | 1 - primitives/chain-polkadot/src/lib.rs | 4 +--- primitives/chain-rialto-parachain/Cargo.toml | 1 - primitives/chain-rialto-parachain/src/lib.rs | 5 +---- primitives/chain-rialto/Cargo.toml | 1 - primitives/chain-rialto/src/lib.rs | 5 +---- primitives/chain-rococo/Cargo.toml | 1 - primitives/chain-rococo/src/lib.rs | 4 +--- primitives/chain-westend/Cargo.toml | 1 - primitives/chain-wococo/Cargo.toml | 1 - primitives/chain-wococo/src/lib.rs | 4 +--- primitives/runtime/src/chain.rs | 8 ++++---- primitives/runtime/src/lib.rs | 3 +++ relays/bin-substrate/Cargo.toml | 1 - relays/bin-substrate/src/cli/chain_schema.rs | 8 ++++---- .../cli/relay_headers_and_messages/relay_to_parachain.rs | 2 +- .../src/cli/relay_headers_and_messages/relay_to_relay.rs | 2 +- 21 files changed, 20 insertions(+), 43 deletions(-) diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 5e1b91d1cf182..a676b565c33dc 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -paste = "1.0" smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 598e5730253d6..0b218b22250fd 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -29,9 +29,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, -}; +use bp_runtime::decl_bridge_runtime_apis; /// Kusama Chain pub type Kusama = PolkadotLike; diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 7c1e0dab7a571..4cd8b30f7ff90 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 536a9216c80e4..2f5b12eed0df0 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -23,10 +23,7 @@ mod millau_hash; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, - Chain, -}; +use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 6525ea3b752ba..738899b658cdf 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] smallvec = "1.7" -paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 7519c38878dfe..6f584f5526a22 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -29,9 +29,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, -}; +use bp_runtime::decl_bridge_runtime_apis; /// Polkadot Chain pub type Polkadot = PolkadotLike; diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index 5bfda1631e5ac..a15c40929579b 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 285f7f0f184bd..8afbf87725c2b 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -21,10 +21,7 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, - Chain, -}; +use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index 5e02bb454b7d7..663f9076657dd 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -paste = "1.0" # Bridge Dependencies diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index cd4a81264d192..1b8d19249ea61 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -21,10 +21,7 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, - Chain, -}; +use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, Parameter, RuntimeDebug, diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 8c02dcccf8489..fe6b07eeb766d 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -paste = "1.0" smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index dfc31c827376d..aa1d40ce92e25 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -29,9 +29,7 @@ use sp_std::prelude::*; use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, -}; +use bp_runtime::decl_bridge_runtime_apis; /// Rococo Chain pub type Rococo = PolkadotLike; diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index fb2f846f7efd3..f37aa3b0e397e 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -paste = "1.0" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } smallvec = "1.7" diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 44af20b726f5e..92e7c9e80e279 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -paste = "1.0" # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 6db6e2fe6fd95..c1626b0dc67d0 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -27,9 +27,7 @@ use sp_std::prelude::*; pub use bp_polkadot_core::*; // Rococo runtime = Wococo runtime pub use bp_rococo::{WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, VERSION}; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, decl_bridge_runtime_apis, -}; +use bp_runtime::decl_bridge_runtime_apis; /// Wococo Chain pub type Wococo = PolkadotLike; diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 154603ccd3a10..7cb0ad976f06a 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -225,7 +225,7 @@ pub type TransactionEraOf = crate::TransactionEra, HashOf #[macro_export] macro_rules! decl_bridge_finality_runtime_apis { ($chain: ident) => { - paste::item! { + bp_runtime::paste::item! { mod [<$chain _finality_api>] { use super::*; @@ -263,7 +263,7 @@ macro_rules! decl_bridge_finality_runtime_apis { #[macro_export] macro_rules! decl_bridge_messages_runtime_apis { ($chain: ident) => { - paste::item! { + bp_runtime::paste::item! { mod [<$chain _messages_api>] { use super::*; @@ -339,7 +339,7 @@ macro_rules! decl_bridge_messages_runtime_apis { #[macro_export] macro_rules! decl_bridge_runtime_apis { ($chain: ident) => { - decl_bridge_finality_runtime_apis!($chain); - decl_bridge_messages_runtime_apis!($chain); + bp_runtime::decl_bridge_finality_runtime_apis!($chain); + bp_runtime::decl_bridge_messages_runtime_apis!($chain); }; } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a7e3e44626ad0..7589e70d703ae 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -48,6 +48,9 @@ pub mod messages; mod chain; mod storage_proof; +// Re-export macro to aviod include paste dependency everywhere +pub use sp_runtime::paste; + /// Use this when something must be shared among all instances. pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0]; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index ff7496f16ec72..8f984925cea76 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -15,7 +15,6 @@ hex = "0.4" log = "0.4.17" num-format = "0.4" num-traits = "0.2" -paste = "1.0" rand = "0.8" structopt = "0.3" strum = { version = "0.21.0", features = ["derive"] } diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index f6edd26db7a67..0f108aed6de52 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -38,7 +38,7 @@ pub enum RuntimeVersionType { #[macro_export] macro_rules! declare_chain_runtime_version_params_cli_schema { ($chain:ident, $chain_prefix:ident) => { - paste::item! { + bp_runtime::paste::item! { #[doc = $chain " runtime version params."] #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] pub struct [<$chain RuntimeVersionParams>] { @@ -89,7 +89,7 @@ macro_rules! declare_chain_runtime_version_params_cli_schema { #[macro_export] macro_rules! declare_chain_connection_params_cli_schema { ($chain:ident, $chain_prefix:ident) => { - paste::item! { + bp_runtime::paste::item! { #[doc = $chain " connection params."] #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] pub struct [<$chain ConnectionParams>] { @@ -157,7 +157,7 @@ pub trait TransactionParamsProvider { #[macro_export] macro_rules! declare_chain_signing_params_cli_schema { ($chain:ident, $chain_prefix:ident) => { - paste::item! { + bp_runtime::paste::item! { #[doc = $chain " signing params."] #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] pub struct [<$chain SigningParams>] { @@ -263,7 +263,7 @@ macro_rules! declare_chain_signing_params_cli_schema { #[macro_export] macro_rules! declare_chain_messages_pallet_owner_signing_params_cli_schema { ($chain:ident, $chain_prefix:ident) => { - paste::item! { + bp_runtime::paste::item! { #[doc = "Parameters required to sign transaction on behalf of owner of the messages pallet at " $chain "."] #[derive(StructOpt, Debug, PartialEq, Eq)] pub struct [<$chain MessagesPalletOwnerSigningParams>] { diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index b8f1992a2ff86..4123dae5a70f0 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -60,7 +60,7 @@ pub struct RelayToParachainBridge< macro_rules! declare_relay_to_parachain_bridge_schema { // chain, parachain, relay-chain-of-parachain ($left_chain:ident, $right_parachain:ident, $right_chain:ident) => { - paste::item! { + bp_runtime::paste::item! { #[doc = $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."] #[derive(Debug, PartialEq, StructOpt)] pub struct [<$left_chain $right_parachain HeadersAndMessages>] { diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index 7350f903f62c3..2e092ad406be7 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -47,7 +47,7 @@ pub struct RelayToRelayBridge< macro_rules! declare_relay_to_relay_bridge_schema { ($left_chain:ident, $right_chain:ident) => { - paste::item! { + bp_runtime::paste::item! { #[doc = $left_chain " and " $right_chain " headers+messages relay params."] #[derive(Debug, PartialEq, StructOpt)] pub struct [<$left_chain $right_chain HeadersAndMessages>] { From 2062ddebe6827ddb070ec84ef34df152363ac4cb Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 26 Aug 2022 22:25:23 +0200 Subject: [PATCH 0766/1210] Unnecessery clones + removed unused Enum value (#1557) * Unnecessary clone * Removed unused Enum value * Client - ConnectionParams wrapped with Arc + removed unnecessery clone * Client - ConnectionParams wrapped with Arc + removed unnecessery clone --- relays/client-millau/src/lib.rs | 2 +- relays/client-rialto/src/lib.rs | 2 +- relays/client-substrate/src/client.rs | 11 ++++++----- relays/lib-substrate-relay/src/error.rs | 3 --- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 08bd1d76324d8..36b7cb792b436 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -104,7 +104,7 @@ impl TransactionSignScheme for Millau { fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( - param.unsigned.call.clone(), + param.unsigned.call, ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 67b96563817e3..733ca9d146570 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -111,7 +111,7 @@ impl TransactionSignScheme for Rialto { fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( - param.unsigned.call.clone(), + param.unsigned.call, ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 53ebe81e8604d..c6fd07c5ae599 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -80,7 +80,7 @@ pub struct Client { /// Tokio runtime handle. tokio: Arc, /// Client connection params. - params: ConnectionParams, + params: Arc, /// Substrate RPC client. client: Arc, /// Genesis block hash. @@ -99,7 +99,7 @@ impl relay_utils::relay_loop::Client for Client { type Error = Error; async fn reconnect(&mut self) -> Result<()> { - let (tokio, client) = Self::build_client(self.params.clone()).await?; + let (tokio, client) = Self::build_client(&self.params).await?; self.tokio = tokio; self.client = client; Ok(()) @@ -131,6 +131,7 @@ impl Client { /// This function will keep connecting to given Substrate node until connection is established /// and is functional. If attempt fail, it will wait for `RECONNECT_DELAY` and retry again. pub async fn new(params: ConnectionParams) -> Self { + let params = Arc::new(params); loop { match Self::try_connect(params.clone()).await { Ok(client) => return client, @@ -149,8 +150,8 @@ impl Client { /// Try to connect to Substrate node over websocket. Returns Substrate RPC client if connection /// has been established or error otherwise. - pub async fn try_connect(params: ConnectionParams) -> Result { - let (tokio, client) = Self::build_client(params.clone()).await?; + pub async fn try_connect(params: Arc) -> Result { + let (tokio, client) = Self::build_client(¶ms).await?; let number: C::BlockNumber = Zero::zero(); let genesis_hash_client = client.clone(); @@ -173,7 +174,7 @@ impl Client { /// Build client to use in connection. async fn build_client( - params: ConnectionParams, + params: &ConnectionParams, ) -> Result<(Arc, Arc)> { let tokio = tokio::runtime::Runtime::new()?; let uri = format!( diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs index 5accba4fc7ce5..64ed3a4fd49c6 100644 --- a/relays/lib-substrate-relay/src/error.rs +++ b/relays/lib-substrate-relay/src/error.rs @@ -55,9 +55,6 @@ pub enum Error { /// Failed to retrieve header by the hash from the source chain. #[error("Failed to retrieve {0} header with hash {1}: {:?}")] RetrieveHeader(&'static str, Hash, client::Error), - /// Failed to retrieve best finalized source header hash from the target chain. - #[error("Failed to retrieve best finalized {0} header from the target chain: {1}")] - RetrieveBestFinalizedHeaderHash(&'static str, client::Error), /// Failed to submit signed extrinsic from to the target chain. #[error( "Failed to retrieve `is_initialized` flag of the with-{0} finality pallet at {1}: {2:?}" From f02db9ae3311be907187f454eba58e009b5e71e2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 30 Aug 2022 13:58:37 +0300 Subject: [PATCH 0767/1210] Extract unsigned tx from the SignParam structure (#1561) * change sign_transaction method * clippy * rustup update && clippy * remove redudnant clone --- bin/rialto-parachain/node/src/chain_spec.rs | 10 +- primitives/runtime/src/lib.rs | 10 +- primitives/test-utils/src/keyring.rs | 2 +- relays/bin-substrate/src/chains/mod.rs | 34 +++--- relays/bin-substrate/src/cli/init_bridge.rs | 29 ++--- relays/bin-substrate/src/cli/mod.rs | 7 -- .../src/cli/register_parachain.rs | 78 ++++++------- .../src/cli/resubmit_transactions.rs | 36 +++--- relays/bin-substrate/src/cli/send_message.rs | 79 +++++++------ relays/client-millau/src/lib.rs | 51 +++++---- relays/client-rialto-parachain/src/lib.rs | 17 +-- relays/client-rialto/src/lib.rs | 51 +++++---- relays/client-substrate/src/chain.rs | 28 +++-- relays/client-substrate/src/client.rs | 54 +++++---- relays/finality/src/finality_loop_tests.rs | 10 +- .../src/conversion_rate_update.rs | 29 +++-- relays/lib-substrate-relay/src/error.rs | 2 +- .../src/finality/initialize.rs | 43 ++++++-- .../lib-substrate-relay/src/finality/mod.rs | 2 +- .../src/finality/target.rs | 22 ++-- relays/lib-substrate-relay/src/lib.rs | 11 -- .../lib-substrate-relay/src/messages_lane.rs | 4 +- .../src/messages_source.rs | 56 +++++----- .../src/messages_target.rs | 104 +++++++++--------- .../src/on_demand/headers.rs | 3 +- .../src/on_demand/parachains.rs | 2 +- .../src/parachains/target.rs | 23 ++-- relays/messages/src/message_lane_loop.rs | 30 ++--- relays/utils/src/lib.rs | 9 ++ 29 files changed, 434 insertions(+), 402 deletions(-) diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index 4a7865b18542e..a0306514c0391 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -122,10 +122,7 @@ pub fn development_config(id: ParaId) -> ChainSpec { move || { testnet_genesis( get_account_id_from_seed::(SUDO_ACCOUNT), - DEV_AUTHORITIES_ACCOUNTS - .into_iter() - .map(|x| get_from_seed::(x)) - .collect(), + DEV_AUTHORITIES_ACCOUNTS.into_iter().map(get_from_seed::).collect(), endowed_accounts(), id, ) @@ -157,10 +154,7 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec { move || { testnet_genesis( get_account_id_from_seed::(SUDO_ACCOUNT), - LOCAL_AUTHORITIES_ACCOUNTS - .into_iter() - .map(|x| get_from_seed::(x)) - .collect(), + LOCAL_AUTHORITIES_ACCOUNTS.into_iter().map(get_from_seed::).collect(), endowed_accounts(), id, ) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 7589e70d703ae..7ca17fbd5a178 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -183,7 +183,7 @@ impl Size for PreComputedSize { } /// Era of specific transaction. -#[derive(RuntimeDebug, Clone, Copy)] +#[derive(RuntimeDebug, Clone, Copy, PartialEq)] pub enum TransactionEra { /// Transaction is immortal. Immortal, @@ -207,6 +207,14 @@ impl, BlockHash: Copy> TransactionEra Option { + match *self { + TransactionEra::Immortal => None, + TransactionEra::Mortal(_, period) => Some(period), + } + } + /// Returns era that is used by FRAME-based runtimes. pub fn frame_era(&self) -> sp_runtime::generic::Era { match *self { diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index 2436d79339236..f827c729434ec 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -43,7 +43,7 @@ impl Account { pub fn secret(&self) -> SecretKey { let data = self.0.encode(); let mut bytes = [0_u8; 32]; - bytes[0..data.len()].copy_from_slice(&*data); + bytes[0..data.len()].copy_from_slice(&data); SecretKey::from_bytes(&bytes) .expect("A static array of the correct length is a known good.") } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index d3c1290d98dc4..c1e963a63ec7c 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -71,14 +71,15 @@ mod tests { fn rialto_tx_extra_bytes_constant_is_correct() { let rialto_call = rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); - let rialto_tx = Rialto::sign_transaction(SignParam { - spec_version: 1, - transaction_version: 1, - genesis_hash: Default::default(), - signer: sp_keyring::AccountKeyring::Alice.pair(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(rialto_call.clone().into(), 0), - }) + let rialto_tx = Rialto::sign_transaction( + SignParam { + spec_version: 1, + transaction_version: 1, + genesis_hash: Default::default(), + signer: sp_keyring::AccountKeyring::Alice.pair(), + }, + UnsignedTransaction::new(rialto_call.clone().into(), 0), + ) .unwrap(); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); assert!( @@ -93,14 +94,15 @@ mod tests { fn millau_tx_extra_bytes_constant_is_correct() { let millau_call = millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); - let millau_tx = Millau::sign_transaction(SignParam { - spec_version: 0, - transaction_version: 0, - genesis_hash: Default::default(), - signer: sp_keyring::AccountKeyring::Alice.pair(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(millau_call.clone().into(), 0), - }) + let millau_tx = Millau::sign_transaction( + SignParam { + spec_version: 0, + transaction_version: 0, + genesis_hash: Default::default(), + signer: sp_keyring::AccountKeyring::Alice.pair(), + }, + UnsignedTransaction::new(millau_call.clone().into(), 0), + ) .unwrap(); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); assert!( diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 150c55d9c6c67..218130dbe562e 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -26,11 +26,8 @@ use crate::{ cli::{bridge::CliBridgeBase, chain_schema::*}, }; use bp_runtime::Chain as ChainBase; -use codec::Encode; -use relay_substrate_client::{ - AccountKeyPairOf, Chain, SignParam, TransactionSignScheme, UnsignedTransaction, -}; -use sp_core::{Bytes, Pair}; +use relay_substrate_client::{AccountKeyPairOf, Chain, SignParam, UnsignedTransaction}; +use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::finality::engine::{Engine, Grandpa as GrandpaFinalityEngine}; @@ -82,20 +79,16 @@ where source_client, target_client.clone(), target_sign.public().into(), + SignParam { + spec_version, + transaction_version, + genesis_hash: *target_client.genesis_hash(), + signer: target_sign, + }, move |transaction_nonce, initialization_data| { - Ok(Bytes( - Self::Target::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: *target_client.genesis_hash(), - signer: target_sign, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - Self::encode_init_bridge(initialization_data).into(), - transaction_nonce, - ), - })? - .encode(), + Ok(UnsignedTransaction::new( + Self::encode_init_bridge(initialization_data).into(), + transaction_nonce, )) }, ) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index e35548c347c42..44bfce9f384ec 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -223,13 +223,6 @@ impl std::fmt::Display for HexBytes { } } -impl HexBytes { - /// Encode given object and wrap into nicely formatted bytes. - pub fn encode(t: &T) -> Self { - Self(t.encode()) - } -} - /// Prometheus metrics params. #[derive(Clone, Debug, PartialEq, StructOpt)] pub struct PrometheusParams { diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 9573cde30319f..890436537795c 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -27,13 +27,13 @@ use polkadot_runtime_common::{ }; use polkadot_runtime_parachains::paras::ParaLifecycle; use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, Client, HashOf, SignParam, Subscription, TransactionSignScheme, - TransactionStatusOf, UnsignedTransaction, + AccountIdOf, CallOf, Chain, Client, HashOf, SignParam, Subscription, TransactionStatusOf, + UnsignedTransaction, }; use rialto_runtime::SudoCall; use sp_core::{ storage::{well_known_keys::CODE, StorageKey}, - Bytes, Pair, + Pair, }; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -120,20 +120,16 @@ impl RegisterParachain { relay_client .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: reserve_parachain_signer, + }, move |_, transaction_nonce| { - Ok(Bytes( - Relaychain::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: reserve_parachain_signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - reserve_parachain_id_call.into(), - transaction_nonce, - ), - })? - .encode(), + Ok(UnsignedTransaction::new( + reserve_parachain_id_call.into(), + transaction_nonce, )) }, ) @@ -169,20 +165,16 @@ impl RegisterParachain { relay_client .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: register_parathread_signer, + }, move |_, transaction_nonce| { - Ok(Bytes( - Relaychain::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: register_parathread_signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - register_parathread_call.into(), - transaction_nonce, - ), - })? - .encode(), + Ok(UnsignedTransaction::new( + register_parathread_call.into(), + transaction_nonce, )) }, ) @@ -231,22 +223,18 @@ impl RegisterParachain { .into(); let force_lease_signer = relay_sign.clone(); relay_client - .submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { - Ok(Bytes( - Relaychain::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: force_lease_signer, - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new( - force_lease_call.into(), - transaction_nonce, - ), - })? - .encode(), - )) - }) + .submit_signed_extrinsic( + relay_sudo_account, + SignParam:: { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: force_lease_signer, + }, + move |_, transaction_nonce| { + Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce)) + }, + ) .await?; log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index dad1afbf146d1..ac479986ed8fb 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -425,14 +425,15 @@ async fn update_transaction_tip>( current_priority = client .validate_transaction( at_block.1, - S::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: *client.genesis_hash(), - signer: transaction_params.signer.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: unsigned_tx.clone(), - })?, + S::sign_transaction( + SignParam { + spec_version, + transaction_version, + genesis_hash: *client.genesis_hash(), + signer: transaction_params.signer.clone(), + }, + unsigned_tx.clone(), + )?, ) .await?? .priority; @@ -448,17 +449,18 @@ async fn update_transaction_tip>( Ok(( old_tip != unsigned_tx.tip, - S::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: *client.genesis_hash(), - signer: transaction_params.signer.clone(), - era: relay_substrate_client::TransactionEra::new( + S::sign_transaction( + SignParam { + spec_version, + transaction_version, + genesis_hash: *client.genesis_hash(), + signer: transaction_params.signer.clone(), + }, + unsigned_tx.era(relay_substrate_client::TransactionEra::new( at_block, transaction_params.mortality, - ), - unsigned: unsigned_tx, - })?, + )), + )?, )) } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index a45235f0bec28..79d1efee63879 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -26,7 +26,7 @@ use crate::{ chain_schema::*, encode_message::{self, CliEncodeMessage, RawMessage}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, CliChain, HexBytes, HexLaneId, + Balance, CliChain, HexLaneId, }, }; use async_trait::async_trait; @@ -146,55 +146,50 @@ where let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; let estimated_transaction_fee = source_client .estimate_extrinsic_fee(Bytes( - Self::Source::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), - })? + Self::Source::sign_transaction( + SignParam { + spec_version, + transaction_version, + genesis_hash: source_genesis_hash, + signer: source_sign.clone(), + }, + UnsignedTransaction::new(send_message_call.clone(), 0), + )? .encode(), )) .await?; source_client - .submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { - let signed_source_call = Self::Source::sign_transaction(SignParam { + .submit_signed_extrinsic( + source_sign.public().into(), + SignParam:: { spec_version, transaction_version, genesis_hash: source_genesis_hash, signer: source_sign.clone(), - era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), - })? - .encode(); - - log::info!( - target: "bridge", - "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", - Self::Target::NAME, - lane, - payload_len, - fee, - ); - log::info!( - target: "bridge", - "The source account ({:?}) balance will be reduced by (at most) {} (message fee) - + {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()), - fee.0, - estimated_transaction_fee.inclusion_fee(), - fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()), - Self::Source::NAME, - ); - log::info!( - target: "bridge", - "Signed {} Call: {:?}", - Self::Source::NAME, - HexBytes::encode(&signed_source_call) - ); + }, + move |_, transaction_nonce| { + let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); + log::info!( + target: "bridge", + "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", + Self::Target::NAME, + lane, + payload_len, + fee, + ); + log::info!( + target: "bridge", + "The source account ({:?}) balance will be reduced by (at most) {} (message fee) + + {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()), + fee.0, + estimated_transaction_fee.inclusion_fee(), + fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()), + Self::Source::NAME, + ); - Ok(Bytes(signed_source_call)) - }) + Ok(unsigned) + }, + ) .await?; Ok(()) @@ -230,7 +225,7 @@ fn decode_xcm(message: RawMessage) -> anyhow::Result> { #[cfg(test)] mod tests { use super::*; - use crate::cli::ExplicitOrMaximal; + use crate::cli::{ExplicitOrMaximal, HexBytes}; #[test] fn send_raw_rialto_to_millau() { diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 36b7cb792b436..7bab3669c4d02 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -102,18 +102,21 @@ impl TransactionSignScheme for Millau { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = millau_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Result { + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { let raw_payload = SignedPayload::from_raw( - param.unsigned.call, + unsigned.call.clone(), ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(param.era.frame_era()), - frame_system::CheckNonce::::from(param.unsigned.nonce), + frame_system::CheckEra::::from(unsigned.era.frame_era()), + frame_system::CheckNonce::::from(unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), + pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), millau_runtime::BridgeRejectObsoleteHeadersAndMessages, ), ( @@ -121,7 +124,7 @@ impl TransactionSignScheme for Millau { param.spec_version, param.transaction_version, param.genesis_hash, - param.era.signed_payload(param.genesis_hash), + unsigned.era.signed_payload(param.genesis_hash), (), (), (), @@ -155,13 +158,17 @@ impl TransactionSignScheme for Millau { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { - call: tx.function.into(), - nonce: Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), - tip: Compact::>::decode(&mut &extra.7.encode()[..]) - .ok()? - .into(), - }) + Some( + UnsignedTransaction::new( + tx.function.into(), + Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + ) + .tip( + Compact::>::decode(&mut &extra.7.encode()[..]) + .ok()? + .into(), + ), + ) } } @@ -185,15 +192,17 @@ mod tests { .into(), nonce: 777, tip: 888, - }; - let signed_transaction = Millau::sign_transaction(SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 64].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), era: TransactionEra::immortal(), - unsigned: unsigned.clone(), - }) + }; + let signed_transaction = Millau::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 64].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) .unwrap(); let parsed_transaction = Millau::parse_transaction(signed_transaction).unwrap(); assert_eq!(parsed_transaction, unsigned); diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index a6f34201ca5f5..c678a21420fd4 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -101,31 +101,32 @@ impl TransactionSignScheme for RialtoParachain { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Result { + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { let raw_payload = SignedPayload::from_raw( - param.unsigned.call, + unsigned.call, ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), frame_system::CheckEra::::from( - param.era.frame_era(), - ), - frame_system::CheckNonce::::from( - param.unsigned.nonce, + unsigned.era.frame_era(), ), + frame_system::CheckNonce::::from(unsigned.nonce), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::< rialto_parachain_runtime::Runtime, - >::from(param.unsigned.tip), + >::from(unsigned.tip), ), ( (), param.spec_version, param.transaction_version, param.genesis_hash, - param.era.signed_payload(param.genesis_hash), + unsigned.era.signed_payload(param.genesis_hash), (), (), (), diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 733ca9d146570..b2984336cd265 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -109,25 +109,28 @@ impl TransactionSignScheme for Rialto { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Result { + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { let raw_payload = SignedPayload::from_raw( - param.unsigned.call, + unsigned.call.clone(), ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), frame_system::CheckTxVersion::::new(), frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(param.era.frame_era()), - frame_system::CheckNonce::::from(param.unsigned.nonce), + frame_system::CheckEra::::from(unsigned.era.frame_era()), + frame_system::CheckNonce::::from(unsigned.nonce), frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(param.unsigned.tip), + pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), ), ( (), param.spec_version, param.transaction_version, param.genesis_hash, - param.era.signed_payload(param.genesis_hash), + unsigned.era.signed_payload(param.genesis_hash), (), (), (), @@ -158,13 +161,17 @@ impl TransactionSignScheme for Rialto { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction { - call: tx.function.into(), - nonce: Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), - tip: Compact::>::decode(&mut &extra.7.encode()[..]) - .ok()? - .into(), - }) + Some( + UnsignedTransaction::new( + tx.function.into(), + Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + ) + .tip( + Compact::>::decode(&mut &extra.7.encode()[..]) + .ok()? + .into(), + ), + ) } } @@ -188,15 +195,17 @@ mod tests { .into(), nonce: 777, tip: 888, - }; - let signed_transaction = Rialto::sign_transaction(SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), era: TransactionEra::immortal(), - unsigned: unsigned.clone(), - }) + }; + let signed_transaction = Rialto::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) .unwrap(); let parsed_transaction = Rialto::parse_transaction(signed_transaction).unwrap(); assert_eq!(parsed_transaction, unsigned); diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index adfecff4eed18..132b86ad0b7bd 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -15,7 +15,9 @@ // along with Parity Bridges Common. If not, see . use bp_messages::MessageNonce; -use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; +use bp_runtime::{ + Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEra, TransactionEraOf, +}; use codec::{Codec, Encode}; use frame_support::weights::{Weight, WeightToFeePolynomial}; use jsonrpsee::core::{DeserializeOwned, Serialize}; @@ -158,12 +160,14 @@ pub struct UnsignedTransaction { pub nonce: C::Index, /// Tip included into transaction. pub tip: C::Balance, + /// Transaction era used by the chain. + pub era: TransactionEraOf, } impl UnsignedTransaction { - /// Create new unsigned transaction with given call, nonce and zero tip. + /// Create new unsigned transaction with given call, nonce, era and zero tip. pub fn new(call: EncodedOrDecodedCall, nonce: C::Index) -> Self { - Self { call, nonce, tip: Zero::zero() } + Self { call, nonce, era: TransactionEra::Immortal, tip: Zero::zero() } } /// Set transaction tip. @@ -172,13 +176,20 @@ impl UnsignedTransaction { self.tip = tip; self } + + /// Set transaction era. + #[must_use] + pub fn era(mut self, era: TransactionEraOf) -> Self { + self.era = era; + self + } } /// Account key pair used by transactions signing scheme. pub type AccountKeyPairOf = ::AccountKeyPair; /// Substrate-based chain transactions signing scheme. -pub trait TransactionSignScheme { +pub trait TransactionSignScheme: 'static { /// Chain that this scheme is to be used. type Chain: Chain; /// Type of key pairs used to sign transactions. @@ -187,7 +198,10 @@ pub trait TransactionSignScheme { type SignedTransaction: Clone + Debug + Codec + Send + 'static; /// Create transaction for given runtime call, signed by given account. - fn sign_transaction(param: SignParam) -> Result + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result where Self: Sized; @@ -213,10 +227,6 @@ pub struct SignParam { pub genesis_hash: ::Hash, /// Signer account pub signer: T::AccountKeyPair, - /// Transaction era used by the chain. - pub era: TransactionEraOf, - /// Transaction before it is signed. - pub unsigned: UnsignedTransaction, } impl BlockWithJustification for SignedBlock { diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index c6fd07c5ae599..38e2a8b106c66 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -17,13 +17,14 @@ //! Substrate node client. use crate::{ - chain::{Chain, ChainWithBalances, TransactionStatusOf}, + chain::{Chain, ChainWithBalances}, rpc::{ SubstrateAuthorClient, SubstrateChainClient, SubstrateFrameSystemClient, SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient, SubstrateTransactionPaymentClient, }, - ConnectionParams, Error, HashOf, HeaderIdOf, Result, + ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, TransactionSignScheme, + TransactionStatusOf, UnsignedTransaction, }; use async_std::sync::{Arc, Mutex}; @@ -403,10 +404,13 @@ impl Client { /// if all client instances are clones of the same initial `Client`. /// /// Note: The given transaction needs to be SCALE encoded beforehand. - pub async fn submit_signed_extrinsic( + pub async fn submit_signed_extrinsic + 'static>( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, + signing_data: SignParam, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + + Send + + 'static, ) -> Result { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -421,12 +425,14 @@ impl Client { self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = SubstrateAuthorClient::::submit_extrinsic(&*client, extrinsic) - .await - .map_err(|e| { - log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); - e - })?; + let signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode(); + let tx_hash = + SubstrateAuthorClient::::submit_extrinsic(&*client, Bytes(signed_extrinsic)) + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) }) @@ -435,10 +441,15 @@ impl Client { /// Does exactly the same as `submit_signed_extrinsic`, but keeps watching for extrinsic status /// after submission. - pub async fn submit_and_watch_signed_extrinsic( + pub async fn submit_and_watch_signed_extrinsic< + S: TransactionSignScheme + 'static, + >( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, + signing_data: SignParam, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + + Send + + 'static, ) -> Result>> { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -447,14 +458,17 @@ impl Client { let subscription = self .jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let tx_hash = C::Hasher::hash(&extrinsic.0); - let subscription = - SubstrateAuthorClient::::submit_and_watch_extrinsic(&*client, extrinsic) - .await - .map_err(|e| { - log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); - e - })?; + let signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode(); + let tx_hash = C::Hasher::hash(&signed_extrinsic); + let subscription = SubstrateAuthorClient::::submit_and_watch_extrinsic( + &*client, + Bytes(signed_extrinsic), + ) + .await + .map_err(|e| { + log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); + e + })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(subscription) }) diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 330d166098ca3..b7f7bc80029fa 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -127,7 +127,7 @@ impl SourceClient for TestSourceClient { async fn best_finalized_block_number(&self) -> Result { let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); + (self.on_method_call)(&mut data); Ok(data.source_best_block_number) } @@ -136,13 +136,13 @@ impl SourceClient for TestSourceClient { number: TestNumber, ) -> Result<(TestSourceHeader, Option), TestError> { let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); + (self.on_method_call)(&mut data); data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) } async fn finality_proofs(&self) -> Result { let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); + (self.on_method_call)(&mut data); Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) } } @@ -168,7 +168,7 @@ impl TargetClient for TestTargetClient { &self, ) -> Result, TestError> { let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); + (self.on_method_call)(&mut data); Ok(data.target_best_block_id) } @@ -178,7 +178,7 @@ impl TargetClient for TestTargetClient { proof: TestFinalityProof, ) -> Result<(), TestError> { let mut data = self.data.lock(); - (self.on_method_call)(&mut *data); + (self.on_method_call)(&mut data); data.target_best_block_id = HeaderId(header.number(), header.hash()); data.target_headers.push((header, proof)); Ok(()) diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index c7e241626945d..ed13f4e5b35ff 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -18,13 +18,12 @@ use crate::{messages_lane::SubstrateMessageLane, TransactionParams}; -use codec::Encode; use relay_substrate_client::{ transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::metrics::F64SharedRef; -use sp_core::{Bytes, Pair}; +use sp_core::Pair; use std::time::{Duration, Instant}; /// Duration between updater iterations. @@ -272,19 +271,19 @@ where updated_rate, )?; client - .submit_signed_extrinsic(signer_id, move |best_block_id, transaction_nonce| { - Ok(Bytes( - Sign::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer, - era: TransactionEra::new(best_block_id, transaction_params.mortality), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), - })? - .encode(), - )) - }) + .submit_signed_extrinsic( + signer_id, + SignParam:: { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer, + }, + move |best_block_id, transaction_nonce| { + Ok(UnsignedTransaction::new(call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) + }, + ) .await .map(drop) .map_err(|err| anyhow::format_err!("{:?}", err)) diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs index 64ed3a4fd49c6..b41870a181d93 100644 --- a/relays/lib-substrate-relay/src/error.rs +++ b/relays/lib-substrate-relay/src/error.rs @@ -53,7 +53,7 @@ pub enum Error { #[error("Failed to decode {0} GRANDPA authorities set at header {1}: {2:?}")] DecodeAuthorities(&'static str, Hash, codec::Error), /// Failed to retrieve header by the hash from the source chain. - #[error("Failed to retrieve {0} header with hash {1}: {:?}")] + #[error("Failed to retrieve {0} header with hash {1}: {2:?}")] RetrieveHeader(&'static str, Hash, client::Error), /// Failed to submit signed extrinsic from to the target chain. #[error( diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index be1719b4ae033..e25743180ee9e 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -23,18 +23,28 @@ use crate::{error::Error, finality::engine::Engine}; -use relay_substrate_client::{Chain, Client, Error as SubstrateError}; -use sp_core::Bytes; +use relay_substrate_client::{ + Chain, Client, Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, +}; use sp_runtime::traits::Header as HeaderT; /// Submit headers-bridge initialization transaction. -pub async fn initialize, SourceChain: Chain, TargetChain: Chain, F>( +pub async fn initialize< + E: Engine, + SourceChain: Chain, + TargetChain: Chain + TransactionSignScheme, + F, +>( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, + target_signing_data: SignParam, prepare_initialize_transaction: F, ) where - F: FnOnce(TargetChain::Index, E::InitializationData) -> Result + F: FnOnce( + TargetChain::Index, + E::InitializationData, + ) -> Result, SubstrateError> + Send + 'static, { @@ -42,6 +52,7 @@ pub async fn initialize, SourceChain: Chain, TargetChain: source_client, target_client, target_transactions_signer, + target_signing_data, prepare_initialize_transaction, ) .await; @@ -66,17 +77,26 @@ pub async fn initialize, SourceChain: Chain, TargetChain: } /// Craft and submit initialization transaction, returning any error that may occur. -async fn do_initialize, SourceChain: Chain, TargetChain: Chain, F>( +async fn do_initialize< + E: Engine, + SourceChain: Chain, + TargetChain: Chain + TransactionSignScheme, + F, +>( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, + target_signing_data: SignParam, prepare_initialize_transaction: F, ) -> Result< Option, Error::Number>, > where - F: FnOnce(TargetChain::Index, E::InitializationData) -> Result + F: FnOnce( + TargetChain::Index, + E::InitializationData, + ) -> Result, SubstrateError> + Send + 'static, { @@ -103,10 +123,15 @@ where ); let initialization_tx_hash = target_client - .submit_signed_extrinsic(target_transactions_signer, move |_, transaction_nonce| { - prepare_initialize_transaction(transaction_nonce, initialization_data) - }) + .submit_signed_extrinsic( + target_transactions_signer, + target_signing_data, + move |_, transaction_nonce| { + prepare_initialize_transaction(transaction_nonce, initialization_data) + }, + ) .await .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; + Ok(Some(initialization_tx_hash)) } diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index 736937ba0724d..3144a1016ea5c 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -194,7 +194,7 @@ where stall_timeout: transaction_stall_timeout( transaction_params.mortality, P::TargetChain::AVERAGE_BLOCK_INTERVAL, - crate::STALL_TIMEOUT, + relay_utils::STALL_TIMEOUT, ), only_mandatory_headers, }, diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index f9859937ff342..351f21cec80a9 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -25,14 +25,13 @@ use crate::{ }; use async_trait::async_trait; -use codec::Encode; use finality_relay::TargetClient; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; -use sp_core::{Bytes, Pair}; +use sp_core::Pair; /// Substrate client as Substrate finality target. pub struct SubstrateFinalityTarget { @@ -119,18 +118,15 @@ where self.client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer.clone(), + }, move |best_block_id, transaction_nonce| { - Ok(Bytes( - P::TransactionSignScheme::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer.clone(), - era: TransactionEra::new(best_block_id, transaction_params.mortality), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), - })? - .encode(), - )) + Ok(UnsignedTransaction::new(call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) }, ) .await diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 1af4f67a7caf5..f4f1aae9d29d1 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -18,8 +18,6 @@ #![warn(missing_docs)] -use std::time::Duration; - pub mod conversion_rate_update; pub mod error; pub mod finality; @@ -31,15 +29,6 @@ pub mod messages_target; pub mod on_demand; pub mod parachains; -/// Default relay loop stall timeout. If transactions generated by relay are immortal, then -/// this timeout is used. -/// -/// There are no any strict requirements on block time in Substrate. But we assume here that all -/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest -/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine -/// transaction, or remove it from the pool. -pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); - /// Transaction creation parameters. #[derive(Clone, Debug)] pub struct TransactionParams { diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 050fa3ee1ae38..18e150e3617dd 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -22,7 +22,7 @@ use crate::{ messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand::OnDemandRelay, - TransactionParams, STALL_TIMEOUT, + TransactionParams, }; use async_std::sync::Arc; @@ -39,7 +39,7 @@ use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, Client, HashOf, TransactionSignScheme, }; -use relay_utils::metrics::MetricsParams; +use relay_utils::{metrics::MetricsParams, STALL_TIMEOUT}; use sp_core::Pair; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index f032ec3c0c082..5de9e30dd0ea2 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -346,11 +346,14 @@ where self.source_client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash, + signer: self.transaction_params.signer.clone(), + }, move |best_block_id, transaction_nonce| { make_messages_delivery_proof_transaction::

( - spec_version, - transaction_version, - &genesis_hash, &transaction_params, best_block_id, transaction_nonce, @@ -377,18 +380,24 @@ where Err(_) => return BalanceOf::::max_value(), }; async { - let dummy_tx = make_messages_delivery_proof_transaction::

( - runtime_version.spec_version, - runtime_version.transaction_version, - self.source_client.genesis_hash(), - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - prepare_dummy_messages_delivery_proof::(), - false, - )?; + let dummy_tx = P::SourceTransactionSignScheme::sign_transaction( + SignParam:: { + spec_version: runtime_version.spec_version, + transaction_version: runtime_version.transaction_version, + genesis_hash: *self.source_client.genesis_hash(), + signer: self.transaction_params.signer.clone(), + }, + make_messages_delivery_proof_transaction::

( + &self.transaction_params, + HeaderId(Default::default(), Default::default()), + Zero::zero(), + prepare_dummy_messages_delivery_proof::(), + false, + )?, + )? + .encode(); self.source_client - .estimate_extrinsic_fee(dummy_tx) + .estimate_extrinsic_fee(Bytes(dummy_tx)) .await .map(|fee| fee.inclusion_fee()) } @@ -418,17 +427,13 @@ where } /// Make messages delivery proof transaction from given proof. -#[allow(clippy::too_many_arguments)] fn make_messages_delivery_proof_transaction( - spec_version: u32, - transaction_version: u32, - source_genesis_hash: &HashOf, source_transaction_params: &TransactionParams>, source_best_block_id: HeaderIdOf, transaction_nonce: IndexOf, proof: SubstrateMessagesDeliveryProof, trace_call: bool, -) -> Result +) -> Result, SubstrateError> where P::SourceTransactionSignScheme: TransactionSignScheme, { @@ -436,17 +441,8 @@ where P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( proof, trace_call, ); - Ok(Bytes( - P::SourceTransactionSignScheme::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: *source_genesis_hash, - signer: source_transaction_params.signer.clone(), - era: TransactionEra::new(source_best_block_id, source_transaction_params.mortality), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), - })? - .encode(), - )) + Ok(UnsignedTransaction::new(call.into(), transaction_nonce) + .era(TransactionEra::new(source_best_block_id, source_transaction_params.mortality))) } /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index b315dfed4bb50..d88b0539153dd 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -255,11 +255,14 @@ where self.target_client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash, + signer: self.transaction_params.signer.clone(), + }, move |best_block_id, transaction_nonce| { make_messages_delivery_transaction::

( - spec_version, - transaction_version, - &genesis_hash, &transaction_params, best_block_id, transaction_nonce, @@ -299,23 +302,29 @@ where let (spec_version, transaction_version) = self.target_client.simple_runtime_version().await?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. - let delivery_tx = make_messages_delivery_transaction::

( - spec_version, - transaction_version, - self.target_client.genesis_hash(), - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - self.relayer_id_at_source.clone(), - nonces.clone(), - prepare_dummy_messages_proof::( + let delivery_tx = P::TargetTransactionSignScheme::sign_transaction( + SignParam { + spec_version, + transaction_version, + genesis_hash: Default::default(), + signer: self.transaction_params.signer.clone(), + }, + make_messages_delivery_transaction::

( + &self.transaction_params, + HeaderId(Default::default(), Default::default()), + Zero::zero(), + self.relayer_id_at_source.clone(), nonces.clone(), - total_dispatch_weight, - total_size, - ), - false, - )?; - let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(delivery_tx).await?; + prepare_dummy_messages_proof::( + nonces.clone(), + total_dispatch_weight, + total_size, + ), + false, + )?, + )? + .encode(); + let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(Bytes(delivery_tx)).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch @@ -340,24 +349,30 @@ where let (spec_version, transaction_version) = self.target_client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); - let dummy_tx = make_messages_delivery_transaction::

( - spec_version, - transaction_version, - self.target_client.genesis_hash(), - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - self.relayer_id_at_source.clone(), - nonces.clone(), - prepare_dummy_messages_proof::( + let dummy_tx = P::TargetTransactionSignScheme::sign_transaction( + SignParam { + spec_version, + transaction_version, + genesis_hash: Default::default(), + signer: self.transaction_params.signer.clone(), + }, + make_messages_delivery_transaction::

( + &self.transaction_params, + HeaderId(Default::default(), Default::default()), + Zero::zero(), + self.relayer_id_at_source.clone(), nonces.clone(), - larger_dispatch_weight, - total_size, - ), - false, - )?; + prepare_dummy_messages_proof::( + nonces.clone(), + larger_dispatch_weight, + total_size, + ), + false, + )?, + )? + .encode(); let larger_delivery_tx_fee = - self.target_client.estimate_extrinsic_fee(dummy_tx).await?; + self.target_client.estimate_extrinsic_fee(Bytes(dummy_tx)).await?; compute_prepaid_messages_refund::( total_prepaid_nonces, @@ -406,11 +421,7 @@ where } /// Make messages delivery transaction from given proof. -#[allow(clippy::too_many_arguments)] fn make_messages_delivery_transaction( - spec_version: u32, - transaction_version: u32, - target_genesis_hash: &HashOf, target_transaction_params: &TransactionParams>, target_best_block_id: HeaderIdOf, transaction_nonce: IndexOf, @@ -418,7 +429,7 @@ fn make_messages_delivery_transaction( nonces: RangeInclusive, proof: SubstrateMessagesProof, trace_call: bool, -) -> Result +) -> Result, SubstrateError> where P::TargetTransactionSignScheme: TransactionSignScheme, { @@ -431,17 +442,8 @@ where dispatch_weight, trace_call, ); - Ok(Bytes( - P::TargetTransactionSignScheme::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash: *target_genesis_hash, - signer: target_transaction_params.signer.clone(), - era: TransactionEra::new(target_best_block_id, target_transaction_params.mortality), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), - })? - .encode(), - )) + Ok(UnsignedTransaction::new(call.into(), transaction_nonce) + .era(TransactionEra::new(target_best_block_id, target_transaction_params.mortality))) } /// Prepare 'dummy' messages proof that will compose the delivery transaction. diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 749205ef9b3cd..09e7a41a0c725 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -28,6 +28,7 @@ use relay_substrate_client::{ }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, + STALL_TIMEOUT, }; use crate::{ @@ -37,7 +38,7 @@ use crate::{ SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT, }, on_demand::OnDemandRelay, - TransactionParams, STALL_TIMEOUT, + TransactionParams, }; /// On-demand Substrate <-> Substrate header finality relay. diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index dc400115502eb..577312e16c109 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -263,7 +263,7 @@ async fn background_task( let stall_timeout = relay_substrate_client::transaction_stall_timeout( target_transactions_mortality, P::TargetChain::AVERAGE_BLOCK_INTERVAL, - crate::STALL_TIMEOUT, + relay_utils::STALL_TIMEOUT, ); log::info!( diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index a96c0ba0ab692..355dd394c2188 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -29,7 +29,7 @@ use bp_parachains::{ }; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderIdProvider; -use codec::{Decode, Encode}; +use codec::Decode; use parachains_relay::{ parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics, }; @@ -141,7 +141,7 @@ where .and_then(|maybe_encoded_head| match maybe_encoded_head { Some(encoded_head) => HeaderOf::::decode(&mut &encoded_head.0[..]) - .map(|head| Some(head)) + .map(Some) .map_err(Self::Error::ResponseParseFailed), None => Ok(None), }) @@ -182,18 +182,15 @@ where self.client .submit_signed_extrinsic( self.transaction_params.signer.public().into(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash, + signer: transaction_params.signer, + }, move |best_block_id, transaction_nonce| { - Ok(Bytes( - P::TransactionSignScheme::sign_transaction(SignParam { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer, - era: TransactionEra::new(best_block_id, transaction_params.mortality), - unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), - })? - .encode(), - )) + Ok(UnsignedTransaction::new(call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) }, ) .await diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 2e700deb9a6bf..bd7a7de8290b9 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -94,7 +94,7 @@ pub struct MessageDeliveryParams { } /// Message details. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct MessageDetails { /// Message dispatch weight. pub dispatch_weight: Weight, @@ -224,7 +224,7 @@ pub trait TargetClient: RelayClient { } /// State of the client. -#[derive(Clone, Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct ClientState { /// The best header id of this chain. pub best_self: SelfHeaderId, @@ -560,7 +560,7 @@ pub(crate) mod tests { async fn reconnect(&mut self) -> Result<(), TestError> { { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); data.is_source_reconnected = true; } Ok(()) @@ -571,7 +571,7 @@ pub(crate) mod tests { impl SourceClient for TestSourceClient { async fn state(&self) -> Result, TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); if data.is_source_fails { return Err(TestError) } @@ -583,7 +583,7 @@ pub(crate) mod tests { id: SourceHeaderIdOf, ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); if data.is_source_fails { return Err(TestError) } @@ -595,7 +595,7 @@ pub(crate) mod tests { id: SourceHeaderIdOf, ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); Ok((id, data.source_latest_confirmed_received_nonce)) } @@ -629,7 +629,7 @@ pub(crate) mod tests { TestError, > { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); Ok(( id, nonces.clone(), @@ -650,7 +650,7 @@ pub(crate) mod tests { proof: TestMessagesReceivingProof, ) -> Result<(), TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); data.source_state.best_self = HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); data.source_state.best_finalized_self = data.source_state.best_self; @@ -663,7 +663,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); data.target_to_source_header_required = Some(id); data.target_to_source_header_requirements.push(id); - (self.tick)(&mut *data); + (self.tick)(&mut data); } async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance { @@ -693,7 +693,7 @@ pub(crate) mod tests { async fn reconnect(&mut self) -> Result<(), TestError> { { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); data.is_target_reconnected = true; } Ok(()) @@ -704,7 +704,7 @@ pub(crate) mod tests { impl TargetClient for TestTargetClient { async fn state(&self) -> Result, TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); if data.is_target_fails { return Err(TestError) } @@ -716,7 +716,7 @@ pub(crate) mod tests { id: TargetHeaderIdOf, ) -> Result<(TargetHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); if data.is_target_fails { return Err(TestError) } @@ -743,7 +743,7 @@ pub(crate) mod tests { id: TargetHeaderIdOf, ) -> Result<(TargetHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); if data.is_target_fails { return Err(TestError) } @@ -764,7 +764,7 @@ pub(crate) mod tests { proof: TestMessagesProof, ) -> Result, TestError> { let mut data = self.data.lock(); - (self.tick)(&mut *data); + (self.tick)(&mut data); if data.is_target_fails { return Err(TestError) } @@ -784,7 +784,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); data.source_to_target_header_required = Some(id); data.source_to_target_header_requirements.push(id); - (self.tick)(&mut *data); + (self.tick)(&mut data); } async fn estimate_delivery_transaction_in_source_tokens( diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 603011819bc6f..8e8870ac188f6 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -25,6 +25,15 @@ use futures::future::FutureExt; use std::time::Duration; use thiserror::Error; +/// Default relay loop stall timeout. If transactions generated by relay are immortal, then +/// this timeout is used. +/// +/// There are no any strict requirements on block time in Substrate. But we assume here that all +/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest +/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine +/// transaction, or remove it from the pool. +pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60); + /// Max delay after connection-unrelated error happened before we'll try the /// same request again. pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); From db8d63590742608a6723ffc23e1bb7770fe17c26 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 5 Sep 2022 08:30:12 +0200 Subject: [PATCH 0768/1210] Get paraId from configured SOURCE_PARACHAIN_PARA_ID (#1564) --- relays/bin-substrate/src/cli/relay_parachains.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 09251972587da..94b856019f95d 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -91,7 +91,9 @@ where source_client, target_client, ParachainSyncParams { - parachains: vec![ParaId(2000)], + parachains: vec![ + ParaId(::SOURCE_PARACHAIN_PARA_ID) + ], stall_timeout: std::time::Duration::from_secs(60), strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, }, From 24b4005b0ac3dd2eb97841e60be891f2b01cfcc8 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 5 Sep 2022 13:13:31 +0300 Subject: [PATCH 0769/1210] Follow-up on #1068 (#1567) * BestParaHead small changes Signed-off-by: Serban Iorga * Renamings Signed-off-by: Serban Iorga * Use ParaInfo in parachains loop Signed-off-by: Serban Iorga * Define StorageMapKeyProvider Signed-off-by: Serban Iorga * CR fixes Signed-off-by: Serban Iorga --- modules/parachains/src/extension.rs | 15 +- modules/parachains/src/lib.rs | 180 ++++++++++-------- primitives/parachains/src/lib.rs | 31 +-- primitives/runtime/src/lib.rs | 34 +++- relays/client-substrate/src/client.rs | 19 +- .../src/parachains/target.rs | 20 +- 6 files changed, 188 insertions(+), 111 deletions(-) diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs index 18e718da0e46f..fb93e671e228c 100644 --- a/modules/parachains/src/extension.rs +++ b/modules/parachains/src/extension.rs @@ -56,7 +56,7 @@ where _ => return Ok(ValidTransaction::default()), }; - let maybe_stored_best_head = crate::BestParaHeads::::get(parachain); + let maybe_stored_best_head = crate::ParasInfo::::get(parachain); Self::validate_updated_parachain_head( parachain, &maybe_stored_best_head, @@ -72,8 +72,9 @@ mod tests { use crate::{ extension::FilterCall, mock::{run_test, Call, TestRuntime}, - BestParaHead, BestParaHeads, RelayBlockNumber, + ParaInfo, ParasInfo, RelayBlockNumber, }; + use bp_parachains::BestParaHeadHash; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; fn validate_submit_parachain_heads( @@ -91,11 +92,13 @@ mod tests { } fn sync_to_relay_header_10() { - BestParaHeads::::insert( + ParasInfo::::insert( ParaId(1), - BestParaHead { - at_relay_block_number: 10, - head_hash: [1u8; 32].into(), + ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 10, + head_hash: [1u8; 32].into(), + }, next_imported_hash_position: 0, }, ); diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 33338433e3bfe..604ac5df0562c 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -26,12 +26,10 @@ pub use weights::WeightInfo; pub use weights_ext::WeightInfoExt; -use bp_parachains::parachain_head_storage_key_at_source; +use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo}; use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::StorageProofError; -use codec::{Decode, Encode}; -use frame_support::{traits::Contains, weights::PostDispatchInfo, RuntimeDebug}; -use scale_info::TypeInfo; +use frame_support::{traits::Contains, weights::PostDispatchInfo}; use sp_runtime::traits::Header as HeaderT; use sp_std::vec::Vec; @@ -58,21 +56,10 @@ pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; /// Hasher of the bridged relay chain. pub type RelayBlockHasher = bp_polkadot_core::Hasher; -/// Best known parachain head as it is stored in the runtime storage. -#[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct BestParaHead { - /// Number of relay block where this head has been updated. - pub at_relay_block_number: RelayBlockNumber, - /// Hash of parachain head. - pub head_hash: ParaHash, - /// Current ring buffer position for this parachain. - pub next_imported_hash_position: u32, -} - /// Artifacts of the parachains head update. struct UpdateParachainHeadArtifacts { /// New best head of the parachain. - pub best_head: BestParaHead, + pub best_head: ParaInfo, /// If `true`, some old parachain head has been pruned during update. pub prune_happened: bool, } @@ -80,8 +67,10 @@ struct UpdateParachainHeadArtifacts { #[frame_support::pallet] pub mod pallet { use super::*; - use bp_parachains::ImportedParaHeadsKeyProvider; - use bp_runtime::{BasicOperatingMode, OwnedBridgeModule, StorageDoubleMapKeyProvider}; + use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; + use bp_runtime::{ + BasicOperatingMode, OwnedBridgeModule, StorageDoubleMapKeyProvider, StorageMapKeyProvider, + }; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -159,10 +148,18 @@ pub mod pallet { pub type PalletOperatingMode, I: 'static = ()> = StorageValue<_, BasicOperatingMode, ValueQuery>; - /// Best parachain heads. + /// Parachains info. + /// + /// Contains the following info: + /// - best parachain head hash + /// - the head of the `ImportedParaHashes` ring buffer #[pallet::storage] - pub type BestParaHeads, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, ParaId, BestParaHead>; + pub type ParasInfo, I: 'static = ()> = StorageMap< + _, + ::Hasher, + ::Key, + ::Value, + >; /// Parachain heads which have been imported into the pallet. #[pallet::storage] @@ -261,7 +258,7 @@ pub mod pallet { target: LOG_TARGET, "The head of parachain {:?} is None. {}", parachain, - if BestParaHeads::::contains_key(¶chain) { + if ParasInfo::::contains_key(¶chain) { "Looks like it is not yet registered at the source relay chain" } else { "Looks like it has been deregistered from the source relay chain" @@ -294,7 +291,7 @@ pub mod pallet { continue; } - let update_result: Result<_, ()> = BestParaHeads::::try_mutate(parachain, |stored_best_head| { + let update_result: Result<_, ()> = ParasInfo::::try_mutate(parachain, |stored_best_head| { let artifacts = Pallet::::update_parachain_head( parachain, stored_best_head.take(), @@ -348,7 +345,7 @@ pub mod pallet { impl, I: 'static> Pallet { /// Get best finalized header of the given parachain. pub fn best_parachain_head(parachain: ParaId) -> Option { - let best_para_head_hash = BestParaHeads::::get(parachain)?.head_hash; + let best_para_head_hash = ParasInfo::::get(parachain)?.best_head_hash.head_hash; ImportedParaHeads::::get(parachain, best_para_head_hash) } @@ -392,7 +389,7 @@ pub mod pallet { /// Without this check, we may import heads in random order. pub fn validate_updated_parachain_head( parachain: ParaId, - maybe_stored_best_head: &Option, + maybe_stored_best_head: &Option, updated_at_relay_block_number: RelayBlockNumber, updated_head_hash: ParaHash, err_log_prefix: &str, @@ -402,26 +399,28 @@ pub mod pallet { None => return Ok(ValidTransaction::default()), }; - if stored_best_head.at_relay_block_number >= updated_at_relay_block_number { + if stored_best_head.best_head_hash.at_relay_block_number >= + updated_at_relay_block_number + { log::trace!( target: LOG_TARGET, "{}. The parachain head for {:?} was already updated at better relay chain block {} >= {}.", err_log_prefix, parachain, - stored_best_head.at_relay_block_number, + stored_best_head.best_head_hash.at_relay_block_number, updated_at_relay_block_number ); return InvalidTransaction::Stale.into() } - if stored_best_head.head_hash == updated_head_hash { + if stored_best_head.best_head_hash.head_hash == updated_head_hash { log::trace!( target: LOG_TARGET, "{}. The parachain head hash for {:?} was already updated to {} at block {} < {}.", err_log_prefix, parachain, updated_head_hash, - stored_best_head.at_relay_block_number, + stored_best_head.best_head_hash.at_relay_block_number, updated_at_relay_block_number ); return InvalidTransaction::Stale.into() @@ -433,7 +432,7 @@ pub mod pallet { /// Try to update parachain head. pub(super) fn update_parachain_head( parachain: ParaId, - stored_best_head: Option, + stored_best_head: Option, updated_at_relay_block_number: RelayBlockNumber, updated_head: ParaHead, updated_head_hash: ParaHash, @@ -454,9 +453,11 @@ pub mod pallet { // insert updated best parachain head let head_hash_to_prune = ImportedParaHashes::::try_get(parachain, next_imported_hash_position); - let updated_best_para_head = BestParaHead { - at_relay_block_number: updated_at_relay_block_number, - head_hash: updated_head_hash, + let updated_best_para_head = ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: updated_at_relay_block_number, + head_hash: updated_head_hash, + }, next_imported_hash_position: (next_imported_hash_position + 1) % T::HeadsToKeep::get(), }; @@ -527,9 +528,13 @@ mod tests { use crate::mock::{ run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; + use codec::Encode; - use bp_parachains::ImportedParaHeadsKeyProvider; - use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider}; + use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; + use bp_runtime::{ + BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider, + StorageMapKeyProvider, + }; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, }; @@ -606,10 +611,12 @@ mod tests { (root, ParaHeadsProof(storage_proof), parachains) } - fn initial_best_head(parachain: u32) -> BestParaHead { - BestParaHead { - at_relay_block_number: 0, - head_hash: head_data(parachain, 0).hash(), + fn initial_best_head(parachain: u32) -> ParaInfo { + ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 0, + head_hash: head_data(parachain, 0).hash(), + }, next_imported_hash_position: 1, } } @@ -697,23 +704,31 @@ mod tests { assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); // but only 1 and 2 are updated, because proof is missing head of parachain#2 - assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); - assert_eq!(BestParaHeads::::get(ParaId(2)), None); + assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); + assert_eq!(ParasInfo::::get(ParaId(2)), None); assert_eq!( - BestParaHeads::::get(ParaId(3)), - Some(BestParaHead { - at_relay_block_number: 0, - head_hash: head_data(3, 10).hash(), + ParasInfo::::get(ParaId(3)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 0, + head_hash: head_data(3, 10).hash() + }, next_imported_hash_position: 1, }) ); assert_eq!( - ImportedParaHeads::::get(ParaId(1), initial_best_head(1).head_hash), + ImportedParaHeads::::get( + ParaId(1), + initial_best_head(1).best_head_hash.head_hash + ), Some(head_data(1, 0)) ); assert_eq!( - ImportedParaHeads::::get(ParaId(2), initial_best_head(2).head_hash), + ImportedParaHeads::::get( + ParaId(2), + initial_best_head(2).best_head_hash.head_hash + ), None ); assert_eq!( @@ -734,10 +749,12 @@ mod tests { initialize(state_root_5); assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5)); assert_eq!( - BestParaHeads::::get(ParaId(1)), - Some(BestParaHead { - at_relay_block_number: 0, - head_hash: head_data(1, 5).hash(), + ParasInfo::::get(ParaId(1)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash() + }, next_imported_hash_position: 1, }) ); @@ -754,10 +771,12 @@ mod tests { proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( - BestParaHeads::::get(ParaId(1)), - Some(BestParaHead { - at_relay_block_number: 1, - head_hash: head_data(1, 10).hash(), + ParasInfo::::get(ParaId(1)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 1, + head_hash: head_data(1, 10).hash() + }, next_imported_hash_position: 2, }) ); @@ -797,19 +816,23 @@ mod tests { assert_ok!(result); assert_eq!(result.expect("checked above").actual_weight, Some(expected_weight)); assert_eq!( - BestParaHeads::::get(ParaId(1)), - Some(BestParaHead { - at_relay_block_number: 0, - head_hash: head_data(1, 5).hash(), + ParasInfo::::get(ParaId(1)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash() + }, next_imported_hash_position: 1, }) ); - assert_eq!(BestParaHeads::::get(ParaId(UNTRACKED_PARACHAIN_ID)), None,); + assert_eq!(ParasInfo::::get(ParaId(UNTRACKED_PARACHAIN_ID)), None,); assert_eq!( - BestParaHeads::::get(ParaId(2)), - Some(BestParaHead { - at_relay_block_number: 0, - head_hash: head_data(1, 5).hash(), + ParasInfo::::get(ParaId(2)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash() + }, next_imported_hash_position: 1, }) ); @@ -824,13 +847,13 @@ mod tests { // import head#0 of parachain#1 at relay block#0 initialize(state_root); assert_ok!(import_parachain_1_head(0, state_root, parachains.clone(), proof.clone())); - assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); + assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); // try to import head#0 of parachain#1 at relay block#1 // => call succeeds, but nothing is changed proceed(1, state_root); assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); - assert_eq!(BestParaHeads::::get(ParaId(1)), Some(initial_best_head(1))); + assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); }); } @@ -848,10 +871,12 @@ mod tests { proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( - BestParaHeads::::get(ParaId(1)), - Some(BestParaHead { - at_relay_block_number: 1, - head_hash: head_data(1, 10).hash(), + ParasInfo::::get(ParaId(1)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 1, + head_hash: head_data(1, 10).hash() + }, next_imported_hash_position: 1, }) ); @@ -860,10 +885,12 @@ mod tests { // => nothing is changed, because better head has already been imported assert_ok!(import_parachain_1_head(0, state_root_5, parachains_5, proof_5)); assert_eq!( - BestParaHeads::::get(ParaId(1)), - Some(BestParaHead { - at_relay_block_number: 1, - head_hash: head_data(1, 10).hash(), + ParasInfo::::get(ParaId(1)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 1, + head_hash: head_data(1, 10).hash() + }, next_imported_hash_position: 1, }) ); @@ -1003,9 +1030,8 @@ mod tests { #[test] fn storage_keys_computed_properly() { assert_eq!( - BestParaHeads::::storage_map_final_key(ParaId(42)).to_vec(), - bp_parachains::best_parachain_head_hash_storage_key_at_target("Parachains", ParaId(42)) - .0, + ParasInfo::::storage_map_final_key(ParaId(42)).to_vec(), + ParasInfoKeyProvider::final_key("Parachains", &ParaId(42)).0 ); assert_eq!( diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index e6c9360d59427..52b4954897308 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -22,7 +22,7 @@ use bp_polkadot_core::{ parachains::{ParaHash, ParaHead, ParaId}, BlockNumber as RelayBlockNumber, }; -use bp_runtime::StorageDoubleMapKeyProvider; +use bp_runtime::{StorageDoubleMapKeyProvider, StorageMapKeyProvider}; use codec::{Decode, Encode}; use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; use scale_info::TypeInfo; @@ -44,6 +44,15 @@ pub struct BestParaHeadHash { pub head_hash: ParaHash, } +/// Best known parachain head as it is stored in the runtime storage. +#[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +pub struct ParaInfo { + /// Best known parachain head hash. + pub best_head_hash: BestParaHeadHash, + /// Current ring buffer position for this parachain. + pub next_imported_hash_position: u32, +} + /// Returns runtime storage key of given parachain head at the source chain. /// /// The head is stored by the `paras` pallet in the `Heads` map. @@ -54,18 +63,16 @@ pub fn parachain_head_storage_key_at_source( bp_runtime::storage_map_final_key::(paras_pallet_name, "Heads", ¶_id.encode()) } -/// Returns runtime storage key of best known parachain head at the target chain. +/// Can be use to access the runtime storage key of the parachains info at the target chain. /// -/// The head is stored by the `pallet-bridge-parachains` pallet in the `BestParaHeads` map. -pub fn best_parachain_head_hash_storage_key_at_target( - bridge_parachains_pallet_name: &str, - para_id: ParaId, -) -> StorageKey { - bp_runtime::storage_map_final_key::( - bridge_parachains_pallet_name, - "BestParaHeads", - ¶_id.encode(), - ) +/// The info is stored by the `pallet-bridge-parachains` pallet in the `ParasInfo` map. +pub struct ParasInfoKeyProvider; +impl StorageMapKeyProvider for ParasInfoKeyProvider { + const MAP_NAME: &'static str = "ParasInfo"; + + type Hasher = Blake2_128Concat; + type Key = ParaId; + type Value = ParaInfo; } /// Can be use to access the runtime storage key of the parachain head at the target chain. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 7ca17fbd5a178..87779195552b3 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -285,20 +285,42 @@ pub fn storage_value_key(pallet_prefix: &str, value_name: &str) -> StorageKey { StorageKey(final_key) } +/// Can be use to access the runtime storage key of a `StorageMap`. +pub trait StorageMapKeyProvider { + /// The name of the variable that holds the `StorageMap`. + const MAP_NAME: &'static str; + + /// The same as `StorageMap::Hasher1`. + type Hasher: StorageHasher; + /// The same as `StorageMap::Key1`. + type Key: FullCodec; + /// The same as `StorageMap::Value`. + type Value: FullCodec; + + /// This is a copy of the + /// `frame_support::storage::generator::StorageMap::storage_map_final_key`. + /// + /// 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. + fn final_key(pallet_prefix: &str, key: &Self::Key) -> StorageKey { + storage_map_final_key::(pallet_prefix, Self::MAP_NAME, &key.encode()) + } +} + /// Can be use to access the runtime storage key of a `StorageDoubleMap`. pub trait StorageDoubleMapKeyProvider { - // The name of the variable that holds the `StorageDoubleMap` + /// The name of the variable that holds the `StorageDoubleMap`. const MAP_NAME: &'static str; - // The same as `StorageDoubleMap::Hasher1` + /// The same as `StorageDoubleMap::Hasher1`. type Hasher1: StorageHasher; - // The same as `StorageDoubleMap::Key1` + /// The same as `StorageDoubleMap::Key1`. type Key1: FullCodec; - // The same as `StorageDoubleMap::Hasher2` + /// The same as `StorageDoubleMap::Hasher2`. type Hasher2: StorageHasher; - // The same as `StorageDoubleMap::Key2` + /// The same as `StorageDoubleMap::Key2`. type Key2: FullCodec; - // The same as `StorageDoubleMap::Value` + /// The same as `StorageDoubleMap::Value`. type Value: FullCodec; /// This is a copy of the diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 38e2a8b106c66..b1f0eb85873da 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -29,7 +29,7 @@ use crate::{ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; -use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider}; +use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider, StorageMapKeyProvider}; use codec::{Decode, Encode}; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; @@ -320,6 +320,23 @@ impl Client { .transpose() } + /// Read `MapStorage` value from runtime storage. + pub async fn storage_map_value( + &self, + pallet_prefix: &str, + key: &T::Key, + block_hash: Option, + ) -> Result> { + let storage_key = T::final_key(pallet_prefix, key); + + self.raw_storage_value(storage_key, block_hash) + .await? + .map(|encoded_value| { + T::Value::decode(&mut &encoded_value.0[..]).map_err(Error::ResponseParseFailed) + }) + .transpose() + } + /// Read `DoubleMapStorage` value from runtime storage. pub async fn storage_double_map_value( &self, diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 355dd394c2188..fa159cdeb7e5a 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -24,9 +24,7 @@ use crate::{ }; use async_trait::async_trait; -use bp_parachains::{ - best_parachain_head_hash_storage_key_at_target, BestParaHeadHash, ImportedParaHeadsKeyProvider, -}; +use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderIdProvider; use codec::Decode; @@ -122,12 +120,16 @@ where metrics: Option<&ParachainsLoopMetrics>, para_id: ParaId, ) -> Result, Self::Error> { - let best_para_head_hash_key = best_parachain_head_hash_storage_key_at_target( - P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, - para_id, - ); - let best_para_head_hash: Option = - self.client.storage_value(best_para_head_hash_key, Some(at_block.1)).await?; + let best_para_head_hash: Option = self + .client + .storage_map_value::( + P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, + ¶_id, + Some(at_block.1), + ) + .await? + .map(|para_info| para_info.best_head_hash); + if let (Some(metrics), &Some(ref best_para_head_hash)) = (metrics, &best_para_head_hash) { let imported_para_head = self .client From 63bc67aee7b2a70787c5d7996579cfbe578f2954 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Sep 2022 10:56:39 +0300 Subject: [PATCH 0770/1210] update Substrate/Polkadot/Cumulus refs (#1562) * update Substrate/Polkadot/Cumulus refs * finality-grandpa 0.16 * fix miillau-runtime compilation * fix rialto runtime compilation * fixed rialto-parachain runtime compilation * backport GRANDPA test fixes * helper instead of removed record_all_keys * substrate-relay is compiling * millau-bridge-node at least compiles * rialto-bridge-node at least compiles * rialto-parachain-collator compiles * fixings tests (wip) * fmt * fixed BEEFY alert * clippy * removed unused dep * -extra var * move Leaf to mod mmr * fix benchmarks --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/service.rs | 96 ++++++------ bin/millau/runtime/src/lib.rs | 82 +++++++--- bin/millau/runtime/src/xcm_config.rs | 3 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto-parachain/node/src/cli.rs | 4 +- bin/rialto-parachain/node/src/command.rs | 19 +-- bin/rialto-parachain/node/src/service.rs | 39 +++-- bin/rialto-parachain/runtime/src/lib.rs | 8 +- bin/rialto/node/src/command.rs | 54 +++---- bin/rialto/runtime/src/lib.rs | 54 ++++++- bin/rialto/runtime/src/parachains.rs | 6 +- bin/rialto/runtime/src/xcm_config.rs | 3 +- .../src/messages_benchmarking.rs | 36 ++--- bin/runtime-common/src/messages_extension.rs | 4 +- .../src/parachains_benchmarking.rs | 15 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/src/lib.rs | 18 +-- modules/parachains/src/lib.rs | 22 ++- modules/relayers/src/payment_adapter.rs | 16 +- modules/shift-session-manager/src/lib.rs | 19 +++ primitives/header-chain/Cargo.toml | 3 +- .../tests/implementation_match.rs | 146 ++++++++++-------- primitives/runtime/Cargo.toml | 2 + primitives/runtime/src/lib.rs | 3 +- primitives/runtime/src/storage_proof.rs | 27 +++- primitives/test-utils/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/src/chain.rs | 4 +- relays/lib-substrate-relay/Cargo.toml | 2 +- .../lib-substrate-relay/src/messages_lane.rs | 2 +- .../src/messages_target.rs | 15 +- 32 files changed, 418 insertions(+), 294 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 28bd9ed0564fc..e83f3c4f564c7 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "3.1", features = ["derive"] } -jsonrpc-core = "18.0" +jsonrpsee = { version = "0.15.1", features = ["server"] } serde_json = "1.0.79" # Bridge dependencies diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 5ac5917f16583..5b4461f3ca642 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -16,19 +16,7 @@ //! Service and ServiceFactory implementation. Specialized wrapper over substrate service. -// ===================================================================================== -// ===================================================================================== -// ===================================================================================== -// UPDATE GUIDE: -// 1) replace everything with node-template/src/service.rs contents (found in main Substrate repo); -// 2) from old code keep `rpc_extensions_builder` - we use our own custom RPCs; -// 3) from old code keep the Beefy gadget; -// 4) fix compilation errors; -// 5) test :) -// ===================================================================================== -// ===================================================================================== -// ===================================================================================== - +use jsonrpsee::RpcModule; use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::{BlockBackend, ExecutorProvider}; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; @@ -83,6 +71,8 @@ pub fn new_partial( FullSelectChain, >, sc_finality_grandpa::LinkHalf, + beefy_gadget::BeefyVoterLinks, + beefy_gadget::BeefyRPCLinks, Option, ), >, @@ -140,11 +130,18 @@ pub fn new_partial( telemetry.as_ref().map(|x| x.handle()), )?; + let (beefy_block_import, beefy_voter_links, beefy_rpc_links) = + beefy_gadget::beefy_block_import_and_links( + grandpa_block_import.clone(), + backend.clone(), + client.clone(), + ); + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), + block_import: beefy_block_import, justification_import: Some(Box::new(grandpa_block_import.clone())), client: client.clone(), create_inherent_data_providers: move |_, ()| async move { @@ -175,7 +172,7 @@ pub fn new_partial( keystore_container, select_chain, transaction_pool, - other: (grandpa_block_import, grandpa_link, telemetry), + other: (grandpa_block_import, grandpa_link, beefy_voter_links, beefy_rpc_links, telemetry), }) } @@ -196,7 +193,7 @@ pub fn new_full(mut config: Configuration) -> Result mut keystore_container, select_chain, transaction_pool, - other: (block_import, grandpa_link, mut telemetry), + other: (block_import, grandpa_link, beefy_voter_links, beefy_rpc_links, mut telemetry), } = new_partial(&config)?; if let Some(url) = &config.keystore_remote { @@ -264,18 +261,16 @@ pub fn new_full(mut config: Configuration) -> Result let enable_grandpa = !config.disable_grandpa; let prometheus_registry = config.prometheus_registry().cloned(); let shared_voter_state = SharedVoterState::empty(); - let (beefy_commitment_link, beefy_commitment_stream) = - beefy_gadget::notification::BeefySignedCommitmentStream::::channel(); - let (beefy_best_block_link, beefy_best_block_stream) = - beefy_gadget::notification::BeefyBestBlockStream::::channel(); let rpc_extensions_builder = { use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; - use sc_finality_grandpa_rpc::{GrandpaApi, GrandpaRpcHandler}; + use beefy_gadget_rpc::{Beefy, BeefyApiServer}; + use pallet_mmr_rpc::{Mmr, MmrApiServer}; + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; + use sc_finality_grandpa_rpc::{Grandpa, GrandpaApiServer}; use sc_rpc::DenyUnsafe; - use substrate_frame_rpc_system::{FullSystem, SystemApi}; + use substrate_frame_rpc_system::{System, SystemApiServer}; let backend = backend.clone(); let client = client.clone(); @@ -291,33 +286,33 @@ pub fn new_full(mut config: Configuration) -> Result ); Box::new(move |_, subscription_executor: sc_rpc::SubscriptionTaskExecutor| { - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(SystemApi::to_delegate(FullSystem::new( - client.clone(), - pool.clone(), - DenyUnsafe::No, - ))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new( - client.clone(), - ))); - io.extend_with(GrandpaApi::to_delegate(GrandpaRpcHandler::new( - shared_authority_set.clone(), - shared_voter_state.clone(), - justification_stream.clone(), - subscription_executor.clone(), - finality_proof_provider.clone(), - ))); - io.extend_with(beefy_gadget_rpc::BeefyApi::to_delegate( - beefy_gadget_rpc::BeefyRpcHandler::::new( - beefy_commitment_stream.clone(), - beefy_best_block_stream.clone(), + let mut io = RpcModule::new(()); + let map_err = |e| sc_service::Error::Other(format!("{}", e)); + io.merge(System::new(client.clone(), pool.clone(), DenyUnsafe::No).into_rpc()) + .map_err(map_err)?; + io.merge(TransactionPayment::new(client.clone()).into_rpc()).map_err(map_err)?; + io.merge( + Grandpa::new( + subscription_executor.clone(), + shared_authority_set.clone(), + shared_voter_state.clone(), + justification_stream.clone(), + finality_proof_provider.clone(), + ) + .into_rpc(), + ) + .map_err(map_err)?; + io.merge( + Beefy::::new( + beefy_rpc_links.from_voter_justif_stream.clone(), + beefy_rpc_links.from_voter_best_beefy_stream.clone(), subscription_executor, ) - .map_err(|e| sc_service::Error::Other(format!("{}", e)))?, - )); - io.extend_with(pallet_mmr_rpc::MmrApi::to_delegate(pallet_mmr_rpc::Mmr::new( - client.clone(), - ))); + .map_err(|e| sc_service::Error::Other(format!("{}", e)))? + .into_rpc(), + ) + .map_err(map_err)?; + io.merge(Mmr::new(client.clone()).into_rpc()).map_err(map_err)?; Ok(io) }) }; @@ -328,7 +323,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), - rpc_extensions_builder, + rpc_builder: rpc_extensions_builder.clone(), backend: backend.clone(), system_rpc_tx, config, @@ -397,11 +392,10 @@ pub fn new_full(mut config: Configuration) -> Result runtime: client, key_store: keystore.clone(), network: network.clone(), - signed_commitment_sender: beefy_commitment_link, - beefy_best_block_sender: beefy_best_block_link, min_block_delta: 2, prometheus_registry: prometheus_registry.clone(), protocol_name: beefy_protocol_name, + links: beefy_voter_links, }; // Start the BEEFY bridge gadget. diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 59f2a08177c62..66f454a0ecc9e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -52,9 +52,7 @@ use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_mmr_primitives::{ - DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, -}; +use sp_mmr_primitives::{DataOrHash, EncodableOpaqueLeaf, Error as MmrError, Proof as MmrProof}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, @@ -238,6 +236,8 @@ impl pallet_aura::Config for Runtime { impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; + type MaxAuthorities = MaxAuthorities; + type OnNewValidatorSet = MmrLeaf; } impl pallet_grandpa::Config for Runtime { @@ -256,12 +256,21 @@ impl pallet_grandpa::Config for Runtime { type MaxAuthorities = MaxAuthorities; } -type MmrHash = ::Output; +/// MMR helper types. +mod mmr { + use super::Runtime; + pub use pallet_mmr::primitives::*; + use sp_runtime::traits::Keccak256; + + pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; + pub type Hash = ::Output; + pub type Hashing = ::Hashing; +} impl pallet_mmr::Config for Runtime { const INDEXING_PREFIX: &'static [u8] = b"mmr"; type Hashing = Keccak256; - type Hash = MmrHash; + type Hash = mmr::Hash; type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; type WeightInfo = (); type LeafData = pallet_beefy_mmr::Pallet; @@ -355,6 +364,7 @@ impl pallet_transaction_payment::Config for Runtime { AdjustmentVariable, MinimumMultiplier, >; + type Event = Event; } impl pallet_sudo::Config for Runtime { @@ -562,7 +572,7 @@ construct_runtime!( Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, // Consensus support. Session: pallet_session::{Pallet, Call, Storage, Event, Config}, @@ -744,41 +754,69 @@ impl_runtime_apis! { } } - impl sp_mmr_primitives::MmrApi for Runtime { + impl sp_mmr_primitives::MmrApi for Runtime { fn generate_proof(leaf_index: u64) - -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> + -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> { - Mmr::generate_proof(leaf_index) - .map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof)) + Mmr::generate_batch_proof(vec![leaf_index]) + .and_then(|(leaves, proof)| Ok(( + mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), + mmr::BatchProof::into_single_leaf_proof(proof)? + ))) } - fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) + fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) -> Result<(), MmrError> { - pub type Leaf = < - ::LeafData as LeafDataProvider - >::LeafData; - - let leaf: Leaf = leaf + let leaf: mmr::Leaf = leaf .into_opaque_leaf() .try_decode() .ok_or(MmrError::Verify)?; - Mmr::verify_leaf(leaf, proof) + Mmr::verify_leaves(vec![leaf], mmr::Proof::into_batch_proof(proof)) } fn verify_proof_stateless( - root: MmrHash, + root: mmr::Hash, leaf: EncodableOpaqueLeaf, - proof: MmrProof + proof: MmrProof ) -> Result<(), MmrError> { - type MmrHashing = ::Hashing; let node = DataOrHash::Data(leaf.into_opaque_leaf()); - pallet_mmr::verify_leaf_proof::(root, node, proof) + pallet_mmr::verify_leaves_proof::( + root, + vec![node], + pallet_mmr::primitives::Proof::into_batch_proof(proof), + ) } - fn mmr_root() -> Result { + fn mmr_root() -> Result { Ok(Mmr::mmr_root()) } + + fn generate_batch_proof(leaf_indices: Vec) + -> Result<(Vec, mmr::BatchProof), mmr::Error> + { + Mmr::generate_batch_proof(leaf_indices) + .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) + } + + fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) + -> Result<(), mmr::Error> + { + let leaves = leaves.into_iter().map(|leaf| + leaf.into_opaque_leaf() + .try_decode() + .ok_or(mmr::Error::Verify)).collect::, mmr::Error>>()?; + Mmr::verify_leaves(leaves, proof) + } + + fn verify_batch_proof_stateless( + root: mmr::Hash, + leaves: Vec, + proof: mmr::BatchProof + ) -> Result<(), mmr::Error> { + let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); + pallet_mmr::verify_leaves_proof::(root, nodes, proof) + } } impl fg_primitives::GrandpaApi for Runtime { diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 57f28e1404444..88398345d4ad0 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -156,6 +156,7 @@ impl xcm_executor::Config for XcmConfig { type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; + type CallDispatcher = Call; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -270,7 +271,7 @@ mod tests { fn xcm_messages_are_sent_using_bridge_router() { new_test_ext().execute_with(|| { let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - let expected_fee = MultiAssets::from((Here, 4_345_002_552_u64)); + let expected_fee = MultiAssets::from((Here, 4_259_858_152_u64)); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 75a7297f3f099..109be667c4cd3 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -30,7 +30,7 @@ bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain" } pallet-bridge-messages = { path = "../../../modules/messages" } # RPC related Dependencies -jsonrpc-core = '18.0' +jsonrpsee = { version = "0.15.1", features = ["server"] } # Local Dependencies rialto-parachain-runtime = { path = '../runtime' } diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index daf6739daa3ff..bd45db9758cba 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -59,7 +59,7 @@ pub enum Subcommand { #[derive(Debug, Parser)] pub struct ExportGenesisStateCommand { /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] + #[clap(action)] pub output: Option, /// Id of the parachain this state is for. @@ -81,7 +81,7 @@ pub struct ExportGenesisStateCommand { #[derive(Debug, Parser)] pub struct ExportGenesisWasmCommand { /// Output file name or stdout if unspecified. - #[clap(parse(from_os_str))] + #[clap(action)] pub output: Option, /// Write output in binary. Default is to write in hex. diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index 20278b5767e41..6afae824a74ce 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -20,11 +20,10 @@ use crate::{ service::{new_partial, ParachainRuntimeExecutor}, }; use codec::Encode; -use cumulus_client_service::genesis::generate_genesis_block; +use cumulus_client_cli::generate_genesis_block; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::BenchmarkCmd; use log::info; -use polkadot_parachain::primitives::AccountIdConversion; use rialto_parachain_runtime::{Block, RuntimeApi}; use sc_cli::{ ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, @@ -32,7 +31,7 @@ use sc_cli::{ }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_core::hexdisplay::HexDisplay; -use sp_runtime::traits::Block as BlockT; +use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; use std::{io::Write, net::SocketAddr}; fn load_spec( @@ -219,7 +218,7 @@ pub fn run() -> Result<()> { params.parachain_id.expect("Missing ParaId").into(), )?; let state_version = Cli::native_runtime_version(&spec).state_version(); - let block: Block = generate_genesis_block(&spec, state_version)?; + let block: Block = generate_genesis_block(&*spec, state_version)?; let raw_header = block.header().encode(); let output_buf = if params.raw { raw_header @@ -288,11 +287,11 @@ pub fn run() -> Result<()> { let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); let parachain_account = - AccountIdConversion::::into_account(&id); + AccountIdConversion::::into_account_truncating(&id); let state_version = RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); - let block: Block = generate_genesis_block(&config.chain_spec, state_version) + let block: Block = generate_genesis_block(&*config.chain_spec, state_version) .map_err(|e| format!("{:?}", e))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); @@ -402,12 +401,8 @@ impl CliConfiguration for RelayChainCli { self.base.base.role(is_dev) } - fn transaction_pool(&self) -> Result { - self.base.base.transaction_pool() - } - - fn state_cache_child_ratio(&self) -> Result> { - self.base.base.state_cache_child_ratio() + fn transaction_pool(&self, is_dev: bool) -> Result { + self.base.base.transaction_pool(is_dev) } fn rpc_methods(&self) -> Result { diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index a2299e17457d9..e55f89bacf70a 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -42,8 +42,8 @@ use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; // Substrate Imports use sc_client_api::ExecutorProvider; use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; -use sc_network::NetworkService; -use sc_service::{Configuration, PartialComponents, Role, TFullBackend, TFullClient, TaskManager}; +use sc_network::{NetworkBlock, NetworkService}; +use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; use sp_api::ConstructRuntimeApi; use sp_keystore::SyncCryptoStorePtr; @@ -229,8 +229,9 @@ where TFullClient>, >, >, - ) -> jsonrpc_core::IoHandler + ) -> Result, sc_service::Error> + Send + + Clone + 'static, BIQ: FnOnce( Arc>>, @@ -261,10 +262,6 @@ where bool, ) -> Result>, sc_service::Error>, { - if matches!(parachain_config.role, Role::Light) { - return Err("Light client not supported!".into()) - } - let parachain_config = prepare_node_config(parachain_config); let params = new_partial::(¶chain_config, build_import_queue)?; @@ -276,6 +273,7 @@ where ¶chain_config, telemetry_worker_handle, &mut task_manager, + None, ) .map_err(|e| match e { RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, @@ -307,11 +305,11 @@ where let rpc_client = client.clone(); let rpc_transaction_pool = transaction_pool.clone(); let rpc_extensions_builder = Box::new(move |deny_unsafe, _| { - Ok(rpc_ext_builder(deny_unsafe, rpc_client.clone(), rpc_transaction_pool.clone())) + rpc_ext_builder(deny_unsafe, rpc_client.clone(), rpc_transaction_pool.clone()) }); sc_service::spawn_tasks(sc_service::SpawnTasksParams { - rpc_extensions_builder, + rpc_builder: rpc_extensions_builder.clone(), client: client.clone(), transaction_pool: transaction_pool.clone(), task_manager: &mut task_manager, @@ -441,18 +439,17 @@ pub async fn start_node( polkadot_config, collator_options, id, - |deny_unsafe, client, pool| { - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi}; - use substrate_frame_rpc_system::{FullSystem, SystemApi}; - - let mut io = jsonrpc_core::IoHandler::default(); - io.extend_with(SystemApi::to_delegate(FullSystem::new( - client.clone(), - pool, - deny_unsafe, - ))); - io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(client))); - io + |_deny_unsafe, client, pool| { + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; + use sc_rpc::DenyUnsafe; + use substrate_frame_rpc_system::{System, SystemApiServer}; + + let mut io = jsonrpsee::RpcModule::new(()); + let map_err = |e| sc_service::Error::Other(format!("{}", e)); + io.merge(System::new(client.clone(), pool, DenyUnsafe::No).into_rpc()) + .map_err(map_err)?; + io.merge(TransactionPayment::new(client).into_rpc()).map_err(map_err)?; + Ok(io) }, parachain_build_import_queue, |client, diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 5cc577281fdaa..885688d683d37 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -34,6 +34,7 @@ use bridge_runtime_common::messages::{ source::{estimate_message_dispatch_and_delivery_fee, XcmBridge, XcmBridgeAdapter}, MessageBridge, }; +use cumulus_pallet_parachain_system::AnyRelayNumber; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ @@ -274,6 +275,7 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); + type Event = Event; } impl pallet_sudo::Config for Runtime { @@ -295,6 +297,7 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type ReservedDmpWeight = ReservedDmpWeight; type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = AnyRelayNumber; } impl parachain_info::Config for Runtime {} @@ -419,6 +422,7 @@ impl Config for XcmConfig { type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; + type CallDispatcher = Call; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -596,7 +600,7 @@ construct_runtime!( Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 20, ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21, @@ -860,7 +864,7 @@ mod tests { let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); let send_result = send_xcm::(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(4_345_002_552_u128))); + let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(4_259_858_152_u128))); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); assert_eq!(send_result, Ok((expected_hash, expected_fee)),); diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 385a88ca065d3..852acb5955311 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -17,7 +17,7 @@ use crate::cli::{Cli, Subcommand}; use frame_benchmarking_cli::BenchmarkCmd; use rialto_runtime::{Block, RuntimeApi}; -use sc_cli::{ChainSpec, Role, RuntimeVersion, SubstrateCli}; +use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -186,34 +186,30 @@ pub fn run() -> sc_cli::Result<()> { // let is_collator = crate::service::IsCollator::No; let overseer_gen = polkadot_service::overseer::RealOverseerGen; runner.run_node_until_exit(|config| async move { - match config.role { - Role::Light => Err(sc_cli::Error::Service(sc_service::Error::Other( - "Light client is not supported by this node".into(), - ))), - _ => { - let is_collator = polkadot_service::IsCollator::No; - let grandpa_pause = None; - let enable_beefy = true; - let jaeger_agent = None; - let telemetry_worker_handle = None; - let program_path = None; - let overseer_enable_anyways = false; - - polkadot_service::new_full::( - config, - is_collator, - grandpa_pause, - enable_beefy, - jaeger_agent, - telemetry_worker_handle, - program_path, - overseer_enable_anyways, - overseer_gen, - ) - .map(|full| full.task_manager) - .map_err(service_error) - }, - } + let is_collator = polkadot_service::IsCollator::No; + let grandpa_pause = None; + let enable_beefy = true; + let jaeger_agent = None; + let telemetry_worker_handle = None; + let program_path = None; + let overseer_enable_anyways = false; + + polkadot_service::new_full::( + config, + is_collator, + grandpa_pause, + enable_beefy, + jaeger_agent, + telemetry_worker_handle, + program_path, + overseer_enable_anyways, + overseer_gen, + None, + None, + None, + ) + .map(|full| full.task_manager) + .map_err(service_error) }) }, } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index acca140d325d4..3729ab78630e7 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -42,6 +42,7 @@ use bridge_runtime_common::messages::{ use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; +use pallet_mmr::primitives as mmr; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -252,6 +253,8 @@ impl pallet_babe::Config for Runtime { impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; + type MaxAuthorities = MaxAuthorities; + type OnNewValidatorSet = MmrLeaf; } impl pallet_grandpa::Config for Runtime { @@ -270,6 +273,9 @@ impl pallet_grandpa::Config for Runtime { type WeightInfo = (); } +type MmrHash = ::Output; +type MmrHashing = ::Hashing; + impl pallet_mmr::Config for Runtime { const INDEXING_PREFIX: &'static [u8] = b"mmr"; type Hashing = Keccak256; @@ -367,6 +373,7 @@ impl pallet_transaction_payment::Config for Runtime { AdjustmentVariable, MinimumMultiplier, >; + type Event = Event; } impl pallet_sudo::Config for Runtime { @@ -484,7 +491,7 @@ construct_runtime!( Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, // Consensus support. AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, @@ -620,8 +627,11 @@ impl_runtime_apis! { fn generate_proof(leaf_index: u64) -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> { - Mmr::generate_proof(leaf_index) - .map(|(leaf, proof)| (EncodableOpaqueLeaf::from_leaf(&leaf), proof)) + Mmr::generate_batch_proof(vec![leaf_index]) + .and_then(|(leaves, proof)| Ok(( + mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), + mmr::BatchProof::into_single_leaf_proof(proof)? + ))) } fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) @@ -635,7 +645,7 @@ impl_runtime_apis! { .into_opaque_leaf() .try_decode() .ok_or(MmrError::Verify)?; - Mmr::verify_leaf(leaf, proof) + Mmr::verify_leaves(vec![leaf], mmr::Proof::into_batch_proof(proof)) } fn verify_proof_stateless( @@ -643,14 +653,46 @@ impl_runtime_apis! { leaf: EncodableOpaqueLeaf, proof: MmrProof ) -> Result<(), MmrError> { - type MmrHashing = ::Hashing; let node = DataOrHash::Data(leaf.into_opaque_leaf()); - pallet_mmr::verify_leaf_proof::(root, node, proof) + pallet_mmr::verify_leaves_proof::( + root, + vec![node], + pallet_mmr::primitives::Proof::into_batch_proof(proof), + ) } fn mmr_root() -> Result { Ok(Mmr::mmr_root()) } + + fn generate_batch_proof(leaf_indices: Vec) + -> Result<(Vec, mmr::BatchProof), mmr::Error> + { + Mmr::generate_batch_proof(leaf_indices) + .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) + } + + fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) + -> Result<(), mmr::Error> + { + type Leaf = < + ::LeafData as LeafDataProvider + >::LeafData; + let leaves = leaves.into_iter().map(|leaf| + leaf.into_opaque_leaf() + .try_decode() + .ok_or(mmr::Error::Verify)).collect::, mmr::Error>>()?; + Mmr::verify_leaves(leaves, proof) + } + + fn verify_batch_proof_stateless( + root: MmrHash, + leaves: Vec, + proof: mmr::BatchProof + ) -> Result<(), mmr::Error> { + let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); + pallet_mmr::verify_leaves_proof::(root, nodes, proof) + } } impl bp_millau::MillauFinalityApi for Runtime { diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 20a9aeb28c0df..d6267bca23735 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -18,7 +18,7 @@ use crate::{ AccountId, Babe, Balance, Balances, BlockNumber, Call, Event, Origin, Registrar, Runtime, - Slots, UncheckedExtrinsic, + ShiftSessionManager, Slots, UncheckedExtrinsic, }; use frame_support::{parameter_types, weights::Weight}; @@ -95,7 +95,9 @@ impl parachains_paras_inherent::Config for Runtime { impl parachains_scheduler::Config for Runtime {} -impl parachains_session_info::Config for Runtime {} +impl parachains_session_info::Config for Runtime { + type ValidatorSet = ShiftSessionManager; +} impl parachains_shared::Config for Runtime {} diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index dbe8ad81c4fe1..ab0029302abd4 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -146,6 +146,7 @@ impl xcm_executor::Config for XcmConfig { type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; + type CallDispatcher = Call; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -237,7 +238,7 @@ mod tests { let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); let send_result = send_xcm::(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, 4_345_002_552_u128)); + let expected_fee = MultiAssets::from((Here, 4_259_858_152_u128)); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); assert_eq!(send_result, Ok((expected_hash, expected_fee)),); diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 865b55f57ccdf..68f58d76b8780 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -27,7 +27,7 @@ use crate::messages::{ }; use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; -use bp_runtime::StorageProofSize; +use bp_runtime::{record_all_trie_keys, StorageProofSize}; use codec::Encode; use frame_support::weights::{GetDispatchInfo, Weight}; use pallet_bridge_messages::benchmarking::{ @@ -36,7 +36,7 @@ use pallet_bridge_messages::benchmarking::{ use sp_core::Hasher; use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; use sp_std::{fmt::Debug, prelude::*}; -use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; /// Prepare outbound message for the `send_message` call. pub fn prepare_outbound_message( @@ -117,7 +117,7 @@ where let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); + let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); @@ -125,10 +125,10 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>::new(); + record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); // finally insert header with given state root to our storage @@ -160,7 +160,7 @@ where let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); + let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); // insert messages for nonce in params.message_nonces.clone() { @@ -195,10 +195,10 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>::new(); + record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); (root, storage_proof) @@ -241,18 +241,16 @@ pub fn grow_trie( let mut key_index = 0; loop { // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>::new(); + record_all_trie_keys::, _>(mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); if size > minimal_trie_size as _ { return root } - let mut trie = TrieDBMutV1::::from_existing(mdb, &mut root) - .map_err(|_| "TrieDBMutV1::from_existing has failed") - .expect("TrieDBMutV1::from_existing should not fail in benchmarks"); + let mut trie = TrieDBMutBuilderV1::::from_existing(mdb, &mut root).build(); for _ in 0..iterations { trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) .map_err(|_| "TrieMut::insert has failed") diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index 95a8b947e74be..bcaadd60ca035 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -52,7 +52,7 @@ impl< .. }) => { let inbound_lane_data = - pallet_bridge_messages::InboundLanes::::get(&proof.lane); + pallet_bridge_messages::InboundLanes::::get(proof.lane); if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() { log::trace!( target: pallet_bridge_messages::LOG_TARGET, @@ -74,7 +74,7 @@ impl< let latest_delivered_nonce = relayers_state.last_delivered_nonce; let outbound_lane_data = - pallet_bridge_messages::OutboundLanes::::get(&proof.lane); + pallet_bridge_messages::OutboundLanes::::get(proof.lane); if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce { log::trace!( target: pallet_bridge_messages::LOG_TARGET, diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index 97a1cd3ee7d9f..59e2ef6962c83 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -22,12 +22,12 @@ use crate::messages_benchmarking::{grow_trie, insert_header_to_grandpa_pallet}; use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; -use bp_runtime::StorageProofSize; +use bp_runtime::{record_all_trie_keys, StorageProofSize}; use codec::Encode; use frame_support::traits::Get; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use sp_std::prelude::*; -use sp_trie::{record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut}; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; /// Prepare proof of messages for the `receive_messages_proof` call. /// @@ -53,7 +53,8 @@ where let mut state_root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMutV1::::new(&mut mdb, &mut state_root); + let mut trie = + TrieDBMutBuilderV1::::new(&mut mdb, &mut state_root).build(); // insert parachain heads for parachain in parachains { @@ -69,10 +70,10 @@ where state_root = grow_trie(state_root, &mut mdb, size); // generate heads storage proof - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &state_root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>::new(); + record_all_trie_keys::, _>(&mdb, &state_root, &mut proof_recorder) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); let (relay_block_number, relay_block_hash) = diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 645f2b72a8180..55022d7e5c439 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -finality-grandpa = { version = "0.15.0", default-features = false } +finality-grandpa = { version = "0.16.0", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 6e87c51ca986f..c2e4dce9b2d0d 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -741,7 +741,7 @@ pub mod pallet { #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { - PalletOperatingMode::::put(&self.operating_mode); + PalletOperatingMode::::put(self.operating_mode); if let Some(ref owner) = self.owner { PalletOwner::::put(owner); } @@ -1022,7 +1022,7 @@ impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage< Some(data) => data, None => { let data: InboundLaneData = - InboundLanes::::get(&self.lane_id).into(); + InboundLanes::::get(self.lane_id).into(); *self.cached_data.try_borrow_mut().expect( "we're in the single-threaded environment;\ we have no recursive borrows; qed", @@ -1037,7 +1037,7 @@ impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage< "we're in the single-threaded environment;\ we have no recursive borrows; qed", ) = Some(data.clone()); - InboundLanes::::insert(&self.lane_id, StoredInboundLaneData::(data)) + InboundLanes::::insert(self.lane_id, StoredInboundLaneData::(data)) } } @@ -1055,11 +1055,11 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag } fn data(&self) -> OutboundLaneData { - OutboundLanes::::get(&self.lane_id) + OutboundLanes::::get(self.lane_id) } fn set_data(&mut self, data: OutboundLaneData) { - OutboundLanes::::insert(&self.lane_id, data) + OutboundLanes::::insert(self.lane_id, data) } #[cfg(test)] @@ -1134,7 +1134,7 @@ mod tests { fn inbound_unrewarded_relayers_state( lane: bp_messages::LaneId, ) -> bp_messages::UnrewardedRelayersState { - let inbound_lane_data = InboundLanes::::get(&lane).0; + let inbound_lane_data = InboundLanes::::get(lane).0; let last_delivered_nonce = inbound_lane_data.last_delivered_nonce(); let relayers = inbound_lane_data.relayers; bp_messages::UnrewardedRelayersState { @@ -1656,7 +1656,7 @@ mod tests { receive_messages_delivery_proof(); assert_eq!( - OutboundLanes::::get(&TEST_LANE_ID).latest_received_nonce, + OutboundLanes::::get(TEST_LANE_ID).latest_received_nonce, 1, ); }); @@ -1839,7 +1839,7 @@ mod tests { 0, // weight may be zero in this case (all messages are improperly encoded) ),); - assert_eq!(InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), 1,); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1,); }); } @@ -1860,7 +1860,7 @@ mod tests { REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight, ),); - assert_eq!(InboundLanes::::get(&TEST_LANE_ID).last_delivered_nonce(), 3,); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 3,); }); } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 604ac5df0562c..bf07cdc9e6730 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -258,7 +258,7 @@ pub mod pallet { target: LOG_TARGET, "The head of parachain {:?} is None. {}", parachain, - if ParasInfo::::contains_key(¶chain) { + if ParasInfo::::contains_key(parachain) { "Looks like it is not yet registered at the source relay chain" } else { "Looks like it has been deregistered from the source relay chain" @@ -514,7 +514,7 @@ pub mod pallet { #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { - PalletOperatingMode::::put(&self.operating_mode); + PalletOperatingMode::::put(self.operating_mode); if let Some(ref owner) = self.owner { PalletOwner::::put(owner); } @@ -532,8 +532,8 @@ mod tests { use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; use bp_runtime::{ - BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider, - StorageMapKeyProvider, + record_all_trie_keys, BasicOperatingMode, OwnedBridgeModuleError, + StorageDoubleMapKeyProvider, StorageMapKeyProvider, }; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, @@ -546,9 +546,7 @@ mod tests { weights::Weight, }; use sp_runtime::DispatchError; - use sp_trie::{ - record_all_keys, trie_types::TrieDBMutV1, LayoutV1, MemoryDB, Recorder, TrieMut, - }; + use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type WeightInfo = ::WeightInfo; @@ -590,7 +588,7 @@ mod tests { let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMutV1::::new(&mut mdb, &mut root); + let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); for (parachain, head) in heads { let storage_key = parachain_head_storage_key_at_source(PARAS_PALLET_NAME, ParaId(parachain)); @@ -602,10 +600,10 @@ mod tests { } // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::::new(); - record_all_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_keys has failed") - .expect("record_all_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>::new(); + record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); (root, ParaHeadsProof(storage_proof), parachains) diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 46a7ad94d4af2..f027ab6429024 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -148,8 +148,8 @@ mod tests { run_test(|| { register_relayers_rewards::(&RELAYER_2, relayers_rewards(), 10); - assert_eq!(RelayerRewards::::get(&RELAYER_1), Some(80)); - assert_eq!(RelayerRewards::::get(&RELAYER_2), Some(120)); + assert_eq!(RelayerRewards::::get(RELAYER_1), Some(80)); + assert_eq!(RelayerRewards::::get(RELAYER_2), Some(120)); }); } @@ -158,9 +158,9 @@ mod tests { run_test(|| { register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 10); - assert_eq!(RelayerRewards::::get(&RELAYER_1), Some(80)); - assert_eq!(RelayerRewards::::get(&RELAYER_2), Some(70)); - assert_eq!(RelayerRewards::::get(&RELAYER_3), Some(50)); + assert_eq!(RelayerRewards::::get(RELAYER_1), Some(80)); + assert_eq!(RelayerRewards::::get(RELAYER_2), Some(70)); + assert_eq!(RelayerRewards::::get(RELAYER_3), Some(50)); }); } @@ -169,9 +169,9 @@ mod tests { run_test(|| { register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 1000); - assert_eq!(RelayerRewards::::get(&RELAYER_1), None); - assert_eq!(RelayerRewards::::get(&RELAYER_2), None); - assert_eq!(RelayerRewards::::get(&RELAYER_3), Some(200)); + assert_eq!(RelayerRewards::::get(RELAYER_1), None); + assert_eq!(RelayerRewards::::get(RELAYER_2), None); + assert_eq!(RelayerRewards::::get(RELAYER_3), Some(200)); }); } } diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 9cf84412575a8..f8475851bb9a7 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -19,6 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] +use frame_support::traits::{ValidatorSet, ValidatorSetWithIdentification}; use sp_std::prelude::*; pub use pallet::*; @@ -49,6 +50,24 @@ pub mod pallet { pub(super) type InitialValidators = StorageValue<_, Vec>; } +impl ValidatorSet for Pallet { + type ValidatorId = T::ValidatorId; + type ValidatorIdOf = T::ValidatorIdOf; + + fn session_index() -> sp_staking::SessionIndex { + pallet_session::Pallet::::current_index() + } + + fn validators() -> Vec { + pallet_session::Pallet::::validators() + } +} + +impl ValidatorSetWithIdentification for Pallet { + type Identification = (); + type IdentificationOf = (); +} + impl pallet_session::SessionManager for Pallet { fn end_session(_: sp_staking::SessionIndex) {} fn start_session(_: sp_staking::SessionIndex) {} diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 3a423292277ce..be87cce460e38 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -finality-grandpa = { version = "0.15.0", default-features = false } +finality-grandpa = { version = "0.16.0", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } @@ -25,7 +25,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -assert_matches = "1.5" bp-test-utils = { path = "../test-utils" } hex = "0.4" hex-literal = "0.3" diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index 51275bbd645e5..aaa19d4b918bb 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -20,7 +20,6 @@ //! Some of tests in this module may partially duplicate tests from `justification.rs`, //! but their purpose is different. -use assert_matches::assert_matches; use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; use bp_test_utils::{ header_id, make_justification_for_header, signed_precommit, test_header, Account, @@ -106,7 +105,7 @@ pub fn make_default_justification(header: &TestHeader) -> GrandpaJustification( @@ -222,21 +233,26 @@ fn same_result_when_authority_equivocates_once_in_a_round() { ), Ok(()), ); - // original implementation returns non-empty GHOST - assert_matches!( - finality_grandpa::validate_commit( - &justification.commit, - &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), - ) - .map(|result| result.ghost().cloned()), - Ok(Some(_)) - ); + // original implementation returns `Ok(validation_result)` + // with `validation_result.is_valid() == true`. + let result = finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .unwrap(); + + assert!(result.is_valid()); } #[test] fn same_result_when_authority_equivocates_twice_in_a_round() { - let mut justification = make_default_justification(&test_header(1)); + let mut justification = make_justification_for_header(JustificationGeneratorParams { + header: test_header(1), + authorities: minimal_accounts_set(), + ancestors: 0, + ..Default::default() + }); // there's some code in the original implementation that should return an error when // same authority submits more than two different votes in a single round: // https://github.com/paritytech/finality-grandpa/blob/6aeea2d1159d0f418f0b86e70739f2130629ca09/src/lib.rs#L473 @@ -266,16 +282,16 @@ fn same_result_when_authority_equivocates_twice_in_a_round() { ), Ok(()), ); - // original implementation returns non-empty GHOST - assert_matches!( - finality_grandpa::validate_commit( - &justification.commit, - &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), - ) - .map(|result| result.ghost().cloned()), - Ok(Some(_)) - ); + // original implementation returns `Ok(validation_result)` + // with `validation_result.is_valid() == true`. + let result = finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .unwrap(); + + assert!(result.is_valid()); } #[test] @@ -299,14 +315,14 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta ), Err(Error::TooLowCumulativeWeight), ); - // original implementation returns empty GHOST - assert_matches!( - finality_grandpa::validate_commit( - &justification.commit, - &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), - ) - .map(|result| result.ghost().cloned()), - Ok(None) - ); + // original implementation returns `Ok(validation_result)` + // with `validation_result.is_valid() == false`. + let result = finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .unwrap(); + + assert!(!result.is_valid()); } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index db0b730f81b58..79f2b9fe03c5c 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -23,6 +23,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master 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 } +trie-db = { version = "0.24.0", default-features = false } [dev-dependencies] hex-literal = "0.3" @@ -43,4 +44,5 @@ std = [ "sp-std/std", "sp-state-machine/std", "sp-trie/std", + "trie-db/std", ] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 87779195552b3..d775e09c47a00 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -37,7 +37,8 @@ pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedSub, One}; use sp_runtime::transaction_validity::TransactionValidity; pub use storage_proof::{ - Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker, + record_all_keys as record_all_trie_keys, Error as StorageProofError, + ProofSize as StorageProofSize, StorageProofChecker, }; #[cfg(feature = "std")] diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 8236c0f2232c7..277456709f97c 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -19,8 +19,11 @@ use codec::Decode; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; -use sp_std::vec::Vec; -use sp_trie::{read_trie_value, LayoutV1, MemoryDB, StorageProof}; +use sp_std::{boxed::Box, vec::Vec}; +use sp_trie::{ + read_trie_value, LayoutV1, MemoryDB, Recorder, StorageProof, Trie, TrieConfiguration, + TrieDBBuilder, TrieError, TrieHash, +}; /// Storage proof size requirements. /// @@ -70,7 +73,7 @@ where /// incomplete or otherwise invalid proof, this function returns an error. pub fn read_value(&self, key: &[u8]) -> Result>, Error> { // LayoutV1 or LayoutV0 is identical for proof that only read values. - read_trie_value::, _>(&self.db, &self.root, key) + read_trie_value::, _>(&self.db, &self.root, key, None, None) .map_err(|_| Error::StorageValueUnavailable) } @@ -124,6 +127,24 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { (root, proof) } +/// Record all keys for a given root. +pub fn record_all_keys( + db: &DB, + root: &TrieHash, + recorder: &mut Recorder, +) -> Result<(), Box>> +where + DB: hash_db::HashDBRef, +{ + let trie = TrieDBBuilder::::new(db, root).with_recorder(recorder).build(); + for x in trie.iter()? { + let (key, _) = x?; + trie.get(&key)?; + } + + Ok(()) +} + #[cfg(test)] pub mod tests { use super::*; diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 70a8fa6bd94f6..0a591334577af 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-header-chain = { path = "../header-chain", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } -finality-grandpa = { version = "0.15.0", default-features = false } +finality-grandpa = { version = "0.16.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 8f984925cea76..2a463fff60e6a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -70,4 +70,4 @@ bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempfile = "3.2" -finality-grandpa = { version = "0.15.0" } +finality-grandpa = { version = "0.16.0" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 132b86ad0b7bd..9562d68d4611b 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -19,7 +19,7 @@ use bp_runtime::{ Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEra, TransactionEraOf, }; use codec::{Codec, Encode}; -use frame_support::weights::{Weight, WeightToFeePolynomial}; +use frame_support::weights::{Weight, WeightToFee}; use jsonrpsee::core::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; @@ -61,7 +61,7 @@ pub trait Chain: ChainBase + Clone { type Call: Clone + Codec + Dispatchable + Debug + Send; /// Type that is used by the chain, to convert from weight to fee. - type WeightToFee: WeightToFeePolynomial; + type WeightToFee: WeightToFee; } /// Substrate-based relay chain that supports parachains. diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index cd8cb51739399..bdf49d42eab44 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -22,7 +22,7 @@ bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-grandpa = { version = "0.15.0" } +finality-grandpa = { version = "0.16.0" } finality-relay = { path = "../finality" } parachains-relay = { path = "../parachains" } relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 18e150e3617dd..f69ebc347d72c 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -510,7 +510,7 @@ mod tests { // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (1024, 216_583_333_334), + (1024, 216_609_134_667), ); } } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index d88b0539153dd..29d80bc2c5ee1 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -36,7 +36,7 @@ use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::Encode; -use frame_support::weights::{Weight, WeightToFeePolynomial}; +use frame_support::weights::{Weight, WeightToFee}; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{TargetClient, TargetClientState}, @@ -502,8 +502,8 @@ fn compute_fee_multiplier( ) -> FixedU128 { let adjusted_weight_fee_difference = larger_adjusted_weight_fee.saturating_sub(smaller_adjusted_weight_fee); - let smaller_tx_unadjusted_weight_fee = WeightToFeeOf::::calc(&smaller_tx_weight); - let larger_tx_unadjusted_weight_fee = WeightToFeeOf::::calc(&larger_tx_weight); + let smaller_tx_unadjusted_weight_fee = WeightToFeeOf::::weight_to_fee(&smaller_tx_weight); + let larger_tx_unadjusted_weight_fee = WeightToFeeOf::::weight_to_fee(&larger_tx_weight); FixedU128::saturating_from_rational( adjusted_weight_fee_difference, larger_tx_unadjusted_weight_fee.saturating_sub(smaller_tx_unadjusted_weight_fee), @@ -516,7 +516,7 @@ fn compute_prepaid_messages_refund( total_prepaid_nonces: MessageNonce, fee_multiplier: FixedU128, ) -> BalanceOf { - fee_multiplier.saturating_mul_int(WeightToFeeOf::::calc( + fee_multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee( &C::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN.saturating_mul(total_prepaid_nonces), )) } @@ -560,16 +560,15 @@ mod tests { #[test] fn compute_fee_multiplier_returns_sane_results() { - let multiplier = FixedU128::saturating_from_rational(1, 1000); + let multiplier: FixedU128 = bp_rococo::WeightToFee::weight_to_fee(&1).into(); let smaller_weight = 1_000_000; let smaller_adjusted_weight_fee = - multiplier.saturating_mul_int(WeightToFeeOf::::calc(&smaller_weight)); + multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&smaller_weight)); let larger_weight = smaller_weight + 200_000; let larger_adjusted_weight_fee = - multiplier.saturating_mul_int(WeightToFeeOf::::calc(&larger_weight)); - + multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&larger_weight)); assert_eq!( compute_fee_multiplier::( smaller_adjusted_weight_fee, From 56bfa87acb793fb485f63f3f1e7eecb29bdf8f8a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Sep 2022 13:09:05 +0300 Subject: [PATCH 0771/1210] Add events to the bridge parachains pallet (#1568) * add events to the bridge parachains pallet * clippy + spellcheck * fix compilation * untracked is not a word? --- bin/millau/runtime/src/lib.rs | 6 +- modules/parachains/src/extension.rs | 12 +- modules/parachains/src/lib.rs | 263 +++++++++++++++++++++++++++- modules/parachains/src/mock.rs | 11 +- 4 files changed, 275 insertions(+), 17 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 66f454a0ecc9e..2fea97cea8d49 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -540,6 +540,7 @@ parameter_types! { pub type WithRialtoParachainsInstance = (); impl pallet_bridge_parachains::Config for Runtime { + type Event = Event; type WeightInfo = pallet_bridge_parachains::weights::MillauWeight; type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; type ParasPalletName = RialtoParasPalletName; @@ -551,6 +552,7 @@ impl pallet_bridge_parachains::Config for Runtime pub type WithWestendParachainsInstance = pallet_bridge_parachains::Instance1; impl pallet_bridge_parachains::Config for Runtime { + type Event = Event; type WeightInfo = pallet_bridge_parachains::weights::MillauWeight; type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; @@ -592,10 +594,10 @@ construct_runtime!( // Westend bridge modules. BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, - BridgeWestendParachains: pallet_bridge_parachains::::{Pallet, Call, Storage}, + BridgeWestendParachains: pallet_bridge_parachains::::{Pallet, Call, Storage, Event}, // RialtoParachain bridge modules. - BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage}, + BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage, Event}, BridgeRialtoParachainMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config}, // Pallet for sending XCM. diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs index fb93e671e228c..05500cf41ddb3 100644 --- a/modules/parachains/src/extension.rs +++ b/modules/parachains/src/extension.rs @@ -17,7 +17,7 @@ use crate::{Config, Pallet, RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use bp_runtime::FilterCall; use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; -use sp_runtime::transaction_validity::{TransactionValidity, ValidTransaction}; +use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}; /// Validate parachain heads in order to avoid "mining" transactions that provide /// outdated bridged parachain heads. Without this validation, even honest relayers @@ -57,13 +57,19 @@ where }; let maybe_stored_best_head = crate::ParasInfo::::get(parachain); - Self::validate_updated_parachain_head( + let is_valid = Self::validate_updated_parachain_head( parachain, &maybe_stored_best_head, updated_at_relay_block_number, parachain_head_hash, "Rejecting obsolete parachain-head transaction", - ) + ); + + if is_valid { + Ok(ValidTransaction::default()) + } else { + InvalidTransaction::Stale.into() + } } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index bf07cdc9e6730..944059d6d9e0e 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -77,6 +77,27 @@ pub mod pallet { /// Weight info of the given parachains pallet. pub type WeightInfoOf = >::WeightInfo; + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event, I: 'static = ()> { + /// The caller has provided head of parachain that the pallet is not configured to track. + UntrackedParachainRejected { parachain: ParaId }, + /// The caller has declared that he has provided given parachain head, but it is missing + /// from the storage proof. + MissingParachainHead { parachain: ParaId }, + /// The caller has provided parachain head hash that is not matching the hash read from the + /// storage proof. + IncorrectParachainHeadHash { + parachain: ParaId, + parachain_head_hash: ParaHash, + actual_parachain_head_hash: ParaHash, + }, + /// The caller has provided obsolete parachain head, which is already known to the pallet. + RejectedObsoleteParachainHead { parachain: ParaId, parachain_head_hash: ParaHash }, + /// Parachain head has been updated. + UpdatedParachainHead { parachain: ParaId, parachain_head_hash: ParaHash }, + } + #[pallet::error] pub enum Error { /// Relay chain block hash is unknown to us. @@ -100,6 +121,8 @@ pub mod pallet { pub trait Config: pallet_bridge_grandpa::Config { + /// The overarching event type. + type Event: From> + IsType<::Event>; /// Benchmarks results from runtime we're plugged into. type WeightInfo: WeightInfoExt; @@ -248,6 +271,7 @@ pub mod pallet { "The head of parachain {:?} has been provided, but it is not tracked by the pallet", parachain, ); + Self::deposit_event(Event::UntrackedParachainRejected { parachain }); continue; } @@ -264,6 +288,7 @@ pub mod pallet { "Looks like it has been deregistered from the source relay chain" }, ); + Self::deposit_event(Event::MissingParachainHead { parachain }); continue; }, Err(e) => { @@ -273,6 +298,7 @@ pub mod pallet { parachain, e, ); + Self::deposit_event(Event::MissingParachainHead { parachain }); continue; }, }; @@ -288,6 +314,11 @@ pub mod pallet { parachain_head_hash, actual_parachain_head_hash, ); + Self::deposit_event(Event::IncorrectParachainHeadHash { + parachain, + parachain_head_hash, + actual_parachain_head_hash, + }); continue; } @@ -387,16 +418,20 @@ pub mod pallet { /// Check if para head has been already updated at better relay chain block. /// Without this check, we may import heads in random order. + /// + /// Returns `true` if the pallet is ready to import given parachain head. + /// Returns `false` if the pallet already knows the same or better parachain head. + #[must_use] pub fn validate_updated_parachain_head( parachain: ParaId, maybe_stored_best_head: &Option, updated_at_relay_block_number: RelayBlockNumber, updated_head_hash: ParaHash, err_log_prefix: &str, - ) -> TransactionValidity { + ) -> bool { let stored_best_head = match maybe_stored_best_head { Some(stored_best_head) => stored_best_head, - None => return Ok(ValidTransaction::default()), + None => return true, }; if stored_best_head.best_head_hash.at_relay_block_number >= @@ -410,7 +445,7 @@ pub mod pallet { stored_best_head.best_head_hash.at_relay_block_number, updated_at_relay_block_number ); - return InvalidTransaction::Stale.into() + return false } if stored_best_head.best_head_hash.head_hash == updated_head_hash { @@ -423,10 +458,10 @@ pub mod pallet { stored_best_head.best_head_hash.at_relay_block_number, updated_at_relay_block_number ); - return InvalidTransaction::Stale.into() + return false } - Ok(ValidTransaction::default()) + true } /// Try to update parachain head. @@ -439,14 +474,20 @@ pub mod pallet { ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order - Self::validate_updated_parachain_head( + let is_valid = Self::validate_updated_parachain_head( parachain, &stored_best_head, updated_at_relay_block_number, updated_head_hash, "The parachain head can't be updated", - ) - .map_err(|_| ())?; + ); + if !is_valid { + Self::deposit_event(Event::RejectedObsoleteParachainHead { + parachain, + parachain_head_hash: updated_head_hash, + }); + return Err(()) + } let next_imported_hash_position = stored_best_head .map_or(0, |stored_best_head| stored_best_head.next_imported_hash_position); @@ -485,6 +526,10 @@ pub mod pallet { ); ImportedParaHeads::::remove(parachain, head_hash_to_prune); } + Self::deposit_event(Event::UpdatedParachainHead { + parachain, + parachain_head_hash: updated_head_hash, + }); Ok(UpdateParachainHeadArtifacts { best_head: updated_best_para_head, prune_happened }) } @@ -526,7 +571,8 @@ pub mod pallet { mod tests { use super::*; use crate::mock::{ - run_test, test_relay_header, Origin, TestRuntime, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, + run_test, test_relay_header, Event as TestEvent, Origin, TestRuntime, PARAS_PALLET_NAME, + UNTRACKED_PARACHAIN_ID, }; use codec::Encode; @@ -545,6 +591,7 @@ mod tests { traits::{Get, OnInitialize}, weights::Weight, }; + use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; @@ -733,6 +780,28 @@ mod tests { ImportedParaHeads::::get(ParaId(3), head_hash(3, 10)), Some(head_data(3, 10)) ); + + assert_eq!( + System::::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: initial_best_head(1).best_head_hash.head_hash, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(3), + parachain_head_hash: head_data(3, 10).hash(), + }), + topics: vec![], + } + ], + ); }); } @@ -764,6 +833,17 @@ mod tests { ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()), None ); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 5).hash(), + }), + topics: vec![], + }], + ); // import head#10 of parachain#1 at relay block #1 proceed(1, state_root_10); @@ -786,6 +866,27 @@ mod tests { ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()), Some(head_data(1, 10)) ); + assert_eq!( + System::::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 5).hash(), + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 10).hash(), + }), + topics: vec![], + } + ], + ); }); } @@ -834,6 +935,34 @@ mod tests { next_imported_hash_position: 1, }) ); + assert_eq!( + System::::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 5).hash(), + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UntrackedParachainRejected { + parachain: ParaId(UNTRACKED_PARACHAIN_ID), + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(2), + parachain_head_hash: head_data(1, 5).hash(), + }), + topics: vec![], + } + ], + ); }); } @@ -846,12 +975,44 @@ mod tests { initialize(state_root); assert_ok!(import_parachain_1_head(0, state_root, parachains.clone(), proof.clone())); assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: initial_best_head(1).best_head_hash.head_hash, + }), + topics: vec![], + }], + ); // try to import head#0 of parachain#1 at relay block#1 // => call succeeds, but nothing is changed proceed(1, state_root); assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); + assert_eq!( + System::::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: initial_best_head(1).best_head_hash.head_hash, + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::RejectedObsoleteParachainHead { + parachain: ParaId(1), + parachain_head_hash: initial_best_head(1).best_head_hash.head_hash, + }), + topics: vec![], + } + ], + ); }); } @@ -878,6 +1039,17 @@ mod tests { next_imported_hash_position: 1, }) ); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 10).hash(), + }), + topics: vec![], + }], + ); // now try to import head#5 at relay block#0 // => nothing is changed, because better head has already been imported @@ -892,6 +1064,27 @@ mod tests { next_imported_hash_position: 1, }) ); + assert_eq!( + System::::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 10).hash(), + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::RejectedObsoleteParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 5).hash(), + }), + topics: vec![], + } + ], + ); }); } @@ -1047,5 +1240,57 @@ mod tests { ); } + #[test] + fn ignores_parachain_head_if_it_is_missing_from_storage_proof() { + let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let parachains = vec![(ParaId(2), Default::default())]; + run_test(|| { + initialize(state_root); + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + (0, test_relay_header(0, state_root).hash()), + parachains, + proof, + )); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::MissingParachainHead { + parachain: ParaId(2), + }), + topics: vec![], + }], + ); + }); + } + + #[test] + fn ignores_parachain_head_if_parachain_head_hash_is_wrong() { + let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let parachains = vec![(ParaId(1), head_data(1, 10).hash())]; + run_test(|| { + initialize(state_root); + assert_ok!(Pallet::::submit_parachain_heads( + Origin::signed(1), + (0, test_relay_header(0, state_root).hash()), + parachains, + proof, + )); + assert_eq!( + System::::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::IncorrectParachainHeadHash { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 10).hash(), + actual_parachain_head_hash: head_data(1, 0).hash(), + }), + topics: vec![], + }], + ); + }); + } + generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index eaf5d3b4fdd91..292856f35a766 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -46,7 +46,7 @@ construct_runtime! { System: frame_system::{Pallet, Call, Config, Storage, Event}, Grandpa1: pallet_bridge_grandpa::::{Pallet}, Grandpa2: pallet_bridge_grandpa::::{Pallet}, - Parachains: pallet_bridge_parachains::{Call, Pallet}, + Parachains: pallet_bridge_parachains::{Call, Pallet, Event}, } } @@ -67,7 +67,7 @@ impl frame_system::Config for TestRuntime { type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type Event = Event; type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; @@ -112,6 +112,7 @@ parameter_types! { } impl pallet_bridge_parachains::Config for TestRuntime { + type Event = Event; type WeightInfo = (); type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type ParasPalletName = ParasPalletName; @@ -166,7 +167,11 @@ impl Chain for OtherBridgedChain { } pub fn run_test(test: impl FnOnce() -> T) -> T { - sp_io::TestExternalities::new(Default::default()).execute_with(test) + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + System::set_block_number(1); + System::reset_events(); + test() + }) } pub fn test_relay_header( From 95e31922333abb37352425144a34fe3afedd96e8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Sep 2022 14:33:38 +0300 Subject: [PATCH 0772/1210] Expand docs on ParasPalletName (#1571) * expand docs on ParasPalletName * fmt --- modules/parachains/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 944059d6d9e0e..290bdadf04a73 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -132,7 +132,11 @@ pub mod pallet { /// we're interested in. type BridgesGrandpaPalletInstance: 'static; - /// Name of the `paras` pallet in the `construct_runtime!()` call at the bridged chain. + /// Name of the original `paras` pallet in the `construct_runtime!()` call at the bridged + /// chain. + /// + /// Please keep in mind that this should be the name of the `runtime_parachains::paras` + /// pallet from polkadot repository, not the `pallet-bridge-parachains`. #[pallet::constant] type ParasPalletName: Get<&'static str>; From db189aec7b08d88cfe2f0bebf46f47e23cbe5452 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 14 Sep 2022 17:30:57 +0300 Subject: [PATCH 0773/1210] TransactionInvalidationTracker (#1544) * TransactionInvalidationTracker * TransacitonInvalidationTracker -> TransactionTracker * change sign_transaction method * clippy and spelling * removed comment * more transactiontracker tests * stalls_when_transaction_tracker_returns_error * remove test code * remove "impl TransactionTracker for ()" * enum TrackedTransactionStatus * test TransactionTracker in on_transaction_status * do_wait --- .../src/cli/register_parachain.rs | 134 +++----- relays/client-substrate/src/client.rs | 36 +- relays/client-substrate/src/lib.rs | 2 + .../src/transaction_tracker.rs | 322 ++++++++++++++++++ relays/finality/src/finality_loop.rs | 79 +++-- relays/finality/src/finality_loop_tests.rs | 60 +++- .../src/finality/target.rs | 9 +- relays/utils/src/lib.rs | 17 + 8 files changed, 514 insertions(+), 145 deletions(-) create mode 100644 relays/client-substrate/src/transaction_tracker.rs diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 890436537795c..4febc4b04a8e1 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -26,10 +26,8 @@ use polkadot_runtime_common::{ paras_registrar::Call as ParaRegistrarCall, slots::Call as ParaSlotsCall, }; use polkadot_runtime_parachains::paras::ParaLifecycle; -use relay_substrate_client::{ - AccountIdOf, CallOf, Chain, Client, HashOf, SignParam, Subscription, TransactionStatusOf, - UnsignedTransaction, -}; +use relay_substrate_client::{AccountIdOf, CallOf, Chain, Client, SignParam, UnsignedTransaction}; +use relay_utils::{TrackedTransactionStatus, TransactionTracker}; use rialto_runtime::SudoCall; use sp_core::{ storage::{well_known_keys::CODE, StorageKey}, @@ -116,26 +114,30 @@ impl RegisterParachain { ParaRegistrarCall::reserve {}.into(); let reserve_parachain_signer = relay_sign.clone(); let (spec_version, transaction_version) = relay_client.simple_runtime_version().await?; - wait_until_transaction_is_finalized::( - relay_client - .submit_and_watch_signed_extrinsic( - relay_sudo_account.clone(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: reserve_parachain_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - reserve_parachain_id_call.into(), - transaction_nonce, - )) - }, - ) - .await?, - ) - .await?; + let reserve_result = relay_client + .submit_and_watch_signed_extrinsic( + relay_sudo_account.clone(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: reserve_parachain_signer, + }, + move |_, transaction_nonce| { + Ok(UnsignedTransaction::new( + reserve_parachain_id_call.into(), + transaction_nonce, + )) + }, + ) + .await? + .wait() + .await; + if reserve_result == TrackedTransactionStatus::Lost { + return Err(anyhow::format_err!( + "Failed to finalize `reserve-parachain-id` transaction" + )) + } log::info!(target: "bridge", "Reserved parachain id: {:?}", para_id); // step 2: register parathread @@ -161,26 +163,30 @@ impl RegisterParachain { } .into(); let register_parathread_signer = relay_sign.clone(); - wait_until_transaction_is_finalized::( - relay_client - .submit_and_watch_signed_extrinsic( - relay_sudo_account.clone(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: register_parathread_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - register_parathread_call.into(), - transaction_nonce, - )) - }, - ) - .await?, - ) - .await?; + let register_result = relay_client + .submit_and_watch_signed_extrinsic( + relay_sudo_account.clone(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash: relay_genesis_hash, + signer: register_parathread_signer, + }, + move |_, transaction_nonce| { + Ok(UnsignedTransaction::new( + register_parathread_call.into(), + transaction_nonce, + )) + }, + ) + .await? + .wait() + .await; + if register_result == TrackedTransactionStatus::Lost { + return Err(anyhow::format_err!( + "Failed to finalize `register-parathread` transaction" + )) + } log::info!(target: "bridge", "Registered parachain: {:?}. Waiting for onboarding", para_id); // wait until parathread is onboarded @@ -256,46 +262,6 @@ impl RegisterParachain { } } -/// Wait until transaction is included into finalized block. -/// -/// Returns the hash of the finalized block with transaction. -pub(crate) async fn wait_until_transaction_is_finalized( - subscription: Subscription>, -) -> anyhow::Result> { - loop { - let transaction_status = subscription.next().await?; - match transaction_status { - Some(TransactionStatusOf::::FinalityTimeout(_)) | - Some(TransactionStatusOf::::Usurped(_)) | - Some(TransactionStatusOf::::Dropped) | - Some(TransactionStatusOf::::Invalid) | - None => - return Err(anyhow::format_err!( - "We've been waiting for finalization of {} transaction, but it now has the {:?} status", - C::NAME, - transaction_status, - )), - Some(TransactionStatusOf::::Finalized(block_hash)) => { - log::trace!( - target: "bridge", - "{} transaction has been finalized at block {}", - C::NAME, - block_hash, - ); - return Ok(block_hash) - }, - _ => { - log::trace!( - target: "bridge", - "Received intermediate status of {} transaction: {:?}", - C::NAME, - transaction_status, - ); - }, - } - } -} - /// Wait until parachain state is changed. async fn wait_para_state( relay_client: &Client, diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index b1f0eb85873da..ed327e167b064 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -23,8 +23,8 @@ use crate::{ SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient, SubstrateTransactionPaymentClient, }, - ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, TransactionSignScheme, - TransactionStatusOf, UnsignedTransaction, + transaction_stall_timeout, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, + TransactionSignScheme, TransactionTracker, UnsignedTransaction, }; use async_std::sync::{Arc, Mutex}; @@ -40,7 +40,7 @@ use jsonrpsee::{ use num_traits::{Bounded, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; -use relay_utils::relay_loop::RECONNECT_DELAY; +use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT}; use sp_core::{ storage::{StorageData, StorageKey}, Bytes, Hasher, @@ -58,7 +58,7 @@ const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_valida const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// Opaque justifications subscription type. -pub struct Subscription(Mutex>>); +pub struct Subscription(pub(crate) Mutex>>); /// Opaque GRANDPA authorities set. pub type OpaqueGrandpaAuthoritiesSet = Vec; @@ -467,14 +467,20 @@ impl Client { prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, - ) -> Result>> { + ) -> Result> { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; let best_header = self.best_header().await?; let best_header_id = best_header.id(); - let subscription = self + let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); + let (tracker, subscription) = self .jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; + let stall_timeout = transaction_stall_timeout( + extrinsic.era.mortality_period(), + C::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); let signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode(); let tx_hash = C::Hasher::hash(&signed_extrinsic); let subscription = SubstrateAuthorClient::::submit_and_watch_extrinsic( @@ -487,17 +493,21 @@ impl Client { e })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); - Ok(subscription) + let tracker = TransactionTracker::new( + stall_timeout, + tx_hash, + Subscription(Mutex::new(receiver)), + ); + Ok((tracker, subscription)) }) .await?; - let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); self.tokio.spawn(Subscription::background_worker( C::NAME.into(), "extrinsic".into(), subscription, sender, )); - Ok(Subscription(Mutex::new(receiver))) + Ok(tracker) } /// Returns pending extrinsics from transaction pool. @@ -669,6 +679,14 @@ impl Client { } impl Subscription { + /// Consumes subscription and returns future statuses stream. + pub fn into_stream(self) -> impl futures::Stream { + futures::stream::unfold(self, |this| async { + let item = this.0.lock().await.next().await.unwrap_or(None); + item.map(|i| (i, this)) + }) + } + /// Return next item from the subscription. pub async fn next(&self) -> Result> { let mut receiver = self.0.lock().await; diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 0234459f9d7d5..b9e489688d35d 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -23,6 +23,7 @@ mod client; mod error; mod rpc; mod sync_header; +mod transaction_tracker; pub mod guard; pub mod metrics; @@ -39,6 +40,7 @@ pub use crate::{ client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, sync_header::SyncHeader, + transaction_tracker::TransactionTracker, }; pub use bp_runtime::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, diff --git a/relays/client-substrate/src/transaction_tracker.rs b/relays/client-substrate/src/transaction_tracker.rs new file mode 100644 index 0000000000000..b85e859017f7e --- /dev/null +++ b/relays/client-substrate/src/transaction_tracker.rs @@ -0,0 +1,322 @@ +// 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 . + +//! Helper for tracking transaction invalidation events. + +use crate::{Chain, HashOf, Subscription, TransactionStatusOf}; + +use async_trait::async_trait; +use futures::{Stream, StreamExt}; +use relay_utils::TrackedTransactionStatus; +use std::time::Duration; + +/// Substrate transaction tracker implementation. +/// +/// Substrate node provides RPC API to submit and watch for transaction events. This way +/// we may know when transaction is included into block, finalized or rejected. There are +/// some edge cases, when we can't fully trust this mechanism - e.g. transaction may broadcasted +/// and then dropped out of node transaction pool (some other cases are also possible - node +/// restarts, connection lost, ...). Then we can't know for sure - what is currently happening +/// with our transaction. Is the transaction really lost? Is it still alive on the chain network? +/// +/// We have several options to handle such cases: +/// +/// 1) hope that the transaction is still alive and wait for its mining until it is spoiled; +/// +/// 2) assume that the transaction is lost and resubmit another transaction instantly; +/// +/// 3) wait for some time (if transaction is mortal - then until block where it dies; if it is +/// immortal - then for some time that we assume is long enough to mine it) and assume that +/// it is lost. +/// +/// This struct implements third option as it seems to be the most optimal. +pub struct TransactionTracker { + transaction_hash: HashOf, + stall_timeout: Duration, + subscription: Subscription>, +} + +impl TransactionTracker { + /// Create transaction tracker. + pub fn new( + stall_timeout: Duration, + transaction_hash: HashOf, + subscription: Subscription>, + ) -> Self { + Self { stall_timeout, transaction_hash, subscription } + } + + /// Wait for final transaction status and return it along with last known internal invalidation + /// status. + async fn do_wait(self) -> (TrackedTransactionStatus, InvalidationStatus) { + let invalidation_status = watch_transaction_status::( + self.transaction_hash, + self.subscription.into_stream(), + ) + .await; + match invalidation_status { + InvalidationStatus::Finalized => + (TrackedTransactionStatus::Finalized, invalidation_status), + InvalidationStatus::Invalid => (TrackedTransactionStatus::Lost, invalidation_status), + InvalidationStatus::Lost => { + async_std::task::sleep(self.stall_timeout).await; + // if someone is still watching for our transaction, then we're reporting + // an error here (which is treated as "transaction lost") + log::trace!( + target: "bridge", + "{} transaction {:?} is considered lost after timeout", + C::NAME, + self.transaction_hash, + ); + + (TrackedTransactionStatus::Lost, invalidation_status) + }, + } + } +} + +#[async_trait] +impl relay_utils::TransactionTracker for TransactionTracker { + async fn wait(self) -> TrackedTransactionStatus { + self.do_wait().await.0 + } +} + +/// Transaction invalidation status. +/// +/// Note that in places where the `TransactionTracker` is used, the finalization event will be +/// ignored - relay loops are detecting the mining/finalization using their own +/// techniques. That's why we're using `InvalidationStatus` here. +#[derive(Debug, PartialEq)] +enum InvalidationStatus { + /// Transaction has been included into block and finalized. + Finalized, + /// Transaction has been invalidated. + Invalid, + /// We have lost track of transaction status. + Lost, +} + +/// Watch for transaction status until transaction is finalized or we lose track of its status. +async fn watch_transaction_status>>( + transaction_hash: HashOf, + subscription: S, +) -> InvalidationStatus { + futures::pin_mut!(subscription); + + loop { + match subscription.next().await { + Some(TransactionStatusOf::::Finalized(block_hash)) => { + // the only "successful" outcome of this method is when the block with transaction + // has been finalized + log::trace!( + target: "bridge", + "{} transaction {:?} has been finalized at block: {:?}", + C::NAME, + transaction_hash, + block_hash, + ); + return InvalidationStatus::Finalized + }, + Some(TransactionStatusOf::::Invalid) => { + // if node says that the transaction is invalid, there are still chances that + // it is not actually invalid - e.g. if the block where transaction has been + // revalidated is retracted and transaction (at some other node pool) becomes + // valid again on other fork. But let's assume that the chances of this event + // are almost zero - there's a lot of things that must happen for this to be the + // case. + log::trace!( + target: "bridge", + "{} transaction {:?} has been invalidated", + C::NAME, + transaction_hash, + ); + return InvalidationStatus::Invalid + }, + Some(TransactionStatusOf::::Future) | + Some(TransactionStatusOf::::Ready) | + Some(TransactionStatusOf::::Broadcast(_)) => { + // nothing important (for us) has happened + }, + Some(TransactionStatusOf::::InBlock(block_hash)) => { + // TODO: read matching system event (ExtrinsicSuccess or ExtrinsicFailed), log it + // here and use it later (on finality) for reporting invalid transaction + // https://github.com/paritytech/parity-bridges-common/issues/1464 + log::trace!( + target: "bridge", + "{} transaction {:?} has been included in block: {:?}", + C::NAME, + transaction_hash, + block_hash, + ); + }, + Some(TransactionStatusOf::::Retracted(block_hash)) => { + log::trace!( + target: "bridge", + "{} transaction {:?} at block {:?} has been retracted", + C::NAME, + transaction_hash, + block_hash, + ); + }, + Some(TransactionStatusOf::::FinalityTimeout(block_hash)) => { + // finality is lagging? let's wait a bit more and report a stall + log::trace!( + target: "bridge", + "{} transaction {:?} block {:?} has not been finalized for too long", + C::NAME, + transaction_hash, + block_hash, + ); + return InvalidationStatus::Lost + }, + Some(TransactionStatusOf::::Usurped(new_transaction_hash)) => { + // this may be result of our transaction resubmitter work or some manual + // intervention. In both cases - let's start stall timeout, because the meaning + // of transaction may have changed + log::trace!( + target: "bridge", + "{} transaction {:?} has been usurped by new transaction: {:?}", + C::NAME, + transaction_hash, + new_transaction_hash, + ); + return InvalidationStatus::Lost + }, + Some(TransactionStatusOf::::Dropped) => { + // the transaction has been removed from the pool because of its limits. Let's wait + // a bit and report a stall + log::trace!( + target: "bridge", + "{} transaction {:?} has been dropped from the pool", + C::NAME, + transaction_hash, + ); + return InvalidationStatus::Lost + }, + None => { + // the status of transaction is unknown to us (the subscription has been closed?). + // Let's wait a bit and report a stall + return InvalidationStatus::Lost + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test_chain::TestChain; + use futures::{FutureExt, SinkExt}; + use sc_transaction_pool_api::TransactionStatus; + + async fn on_transaction_status( + status: TransactionStatus, HashOf>, + ) -> Option<(TrackedTransactionStatus, InvalidationStatus)> { + let (mut sender, receiver) = futures::channel::mpsc::channel(1); + let tx_tracker = TransactionTracker::::new( + Duration::from_secs(0), + Default::default(), + Subscription(async_std::sync::Mutex::new(receiver)), + ); + + sender.send(Some(status)).await.unwrap(); + tx_tracker.do_wait().now_or_never() + } + + #[async_std::test] + async fn returns_finalized_on_finalized() { + assert_eq!( + on_transaction_status(TransactionStatus::Finalized(Default::default())).await, + Some((TrackedTransactionStatus::Finalized, InvalidationStatus::Finalized)), + ); + } + + #[async_std::test] + async fn returns_invalid_on_invalid() { + assert_eq!( + on_transaction_status(TransactionStatus::Invalid).await, + Some((TrackedTransactionStatus::Lost, InvalidationStatus::Invalid)), + ); + } + + #[async_std::test] + async fn waits_on_future() { + assert_eq!(on_transaction_status(TransactionStatus::Future).await, None,); + } + + #[async_std::test] + async fn waits_on_ready() { + assert_eq!(on_transaction_status(TransactionStatus::Ready).await, None,); + } + + #[async_std::test] + async fn waits_on_broadcast() { + assert_eq!( + on_transaction_status(TransactionStatus::Broadcast(Default::default())).await, + None, + ); + } + + #[async_std::test] + async fn waits_on_in_block() { + assert_eq!( + on_transaction_status(TransactionStatus::InBlock(Default::default())).await, + None, + ); + } + + #[async_std::test] + async fn waits_on_retracted() { + assert_eq!( + on_transaction_status(TransactionStatus::Retracted(Default::default())).await, + None, + ); + } + + #[async_std::test] + async fn lost_on_finality_timeout() { + assert_eq!( + on_transaction_status(TransactionStatus::FinalityTimeout(Default::default())).await, + Some((TrackedTransactionStatus::Lost, InvalidationStatus::Lost)), + ); + } + + #[async_std::test] + async fn lost_on_usurped() { + assert_eq!( + on_transaction_status(TransactionStatus::Usurped(Default::default())).await, + Some((TrackedTransactionStatus::Lost, InvalidationStatus::Lost)), + ); + } + + #[async_std::test] + async fn lost_on_dropped() { + assert_eq!( + on_transaction_status(TransactionStatus::Dropped).await, + Some((TrackedTransactionStatus::Lost, InvalidationStatus::Lost)), + ); + } + + #[async_std::test] + async fn lost_on_subscription_error() { + assert_eq!( + watch_transaction_status::(Default::default(), futures::stream::iter([])) + .now_or_never(), + Some(InvalidationStatus::Lost), + ); + } +} diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index c29a5d5fec21f..951edfdde9485 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -29,7 +29,7 @@ use futures::{select, Future, FutureExt, Stream, StreamExt}; use num_traits::{One, Saturating}; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, retry_backoff, FailedClient, - HeaderId, MaybeConnectionError, + HeaderId, MaybeConnectionError, TrackedTransactionStatus, TransactionTracker, }; use std::{ pin::Pin, @@ -86,6 +86,9 @@ pub trait SourceClient: RelayClient { /// Target client used in finality synchronization loop. #[async_trait] pub trait TargetClient: RelayClient { + /// Transaction tracker to track submitted transactions. + type TransactionTracker: TransactionTracker; + /// Get best finalized source block number. async fn best_finalized_source_block_id( &self, @@ -96,7 +99,7 @@ pub trait TargetClient: RelayClient { &self, header: P::Header, proof: P::FinalityProof, - ) -> Result<(), Self::Error>; + ) -> Result; } /// Return prefix that will be used by default to expose Prometheus metrics of the finality proofs @@ -153,8 +156,6 @@ pub(crate) enum Error { Target(TargetError), /// Finality proof for mandatory header is missing from the source node. MissingMandatoryFinalityProof(P::Number), - /// The synchronization has stalled. - Stalled, } impl Error @@ -167,7 +168,6 @@ where match *self { Error::Source(ref error) if error.is_connection_error() => Err(FailedClient::Source), Error::Target(ref error) if error.is_connection_error() => Err(FailedClient::Target), - Error::Stalled => Err(FailedClient::Both), _ => Ok(()), } } @@ -175,9 +175,9 @@ where /// Information about transaction that we have submitted. #[derive(Debug, Clone)] -pub(crate) struct Transaction { - /// Time when we have submitted this transaction. - pub time: Instant, +pub(crate) struct Transaction { + /// Submitted transaction tracker. + pub tracker: Tracker, /// The number of the header we have submitted. pub submitted_header_number: Number, } @@ -206,11 +206,12 @@ pub(crate) struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsS &'a mut RestartableFinalityProofsStream, /// Recent finality proofs that we have read from the stream. pub(crate) recent_finality_proofs: &'a mut FinalityProofs

, - /// Last transaction that we have submitted to the target node. - pub(crate) last_transaction: Option>, + /// Number of the last header, submitted to the target node. + pub(crate) submitted_header_number: Option, } -async fn run_until_connection_lost( +/// Run finality relay loop until connection to one of nodes is lost. +pub(crate) async fn run_until_connection_lost( source_client: impl SourceClient

, target_client: impl TargetClient

, sync_params: FinalitySyncParams, @@ -230,8 +231,9 @@ async fn run_until_connection_lost( }) }; + let last_transaction_tracker = futures::future::Fuse::terminated(); let exit_signal = exit_signal.fuse(); - futures::pin_mut!(exit_signal); + futures::pin_mut!(last_transaction_tracker, exit_signal); let mut finality_proofs_stream = RestartableFinalityProofsStream { needs_restart: false, @@ -241,7 +243,7 @@ async fn run_until_connection_lost( let mut progress = (Instant::now(), None); let mut retry_backoff = retry_backoff(); - let mut last_transaction = None; + let mut last_submitted_header_number = None; loop { // run loop iteration @@ -252,7 +254,7 @@ async fn run_until_connection_lost( progress: &mut progress, finality_proofs_stream: &mut finality_proofs_stream, recent_finality_proofs: &mut recent_finality_proofs, - last_transaction: last_transaction.clone(), + submitted_header_number: last_submitted_header_number, }, &sync_params, &metrics_sync, @@ -261,8 +263,14 @@ async fn run_until_connection_lost( // deal with errors let next_tick = match iteration_result { - Ok(updated_last_transaction) => { - last_transaction = updated_last_transaction; + Ok(Some(updated_last_transaction)) => { + last_transaction_tracker.set(updated_last_transaction.tracker.wait().fuse()); + last_submitted_header_number = + Some(updated_last_transaction.submitted_header_number); + retry_backoff.reset(); + sync_params.tick + }, + Ok(None) => { retry_backoff.reset(); sync_params.tick }, @@ -281,6 +289,18 @@ async fn run_until_connection_lost( // wait till exit signal, or new source block select! { + transaction_status = last_transaction_tracker => { + if transaction_status == TrackedTransactionStatus::Lost { + log::error!( + target: "bridge", + "Finality synchronization from {} to {} has stalled. Going to restart", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + + return Err(FailedClient::Both); + } + }, _ = async_std::task::sleep(next_tick).fuse() => {}, _ = exit_signal => return Ok(()), } @@ -293,7 +313,7 @@ pub(crate) async fn run_loop_iteration( state: FinalityLoopState<'_, P, SC::FinalityProofsStream>, sync_params: &FinalitySyncParams, metrics_sync: &Option, -) -> Result>, Error> +) -> Result>, Error> where P: FinalitySyncPipeline, SC: SourceClient

, @@ -333,20 +353,11 @@ where // if we have already submitted header, then we just need to wait for it // if we're waiting too much, then we believe our transaction has been lost and restart sync - if let Some(last_transaction) = state.last_transaction { - if best_number_at_target >= last_transaction.submitted_header_number { + if let Some(submitted_header_number) = state.submitted_header_number { + if best_number_at_target >= submitted_header_number { // transaction has been mined && we can continue - } else if last_transaction.time.elapsed() > sync_params.stall_timeout { - log::error!( - target: "bridge", - "Finality synchronization from {} to {} has stalled. Going to restart", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - - return Err(Error::Stalled) } else { - return Ok(Some(last_transaction)) + return Ok(None) } } @@ -363,22 +374,20 @@ where .await? { Some((header, justification)) => { - let new_transaction = - Transaction { time: Instant::now(), submitted_header_number: header.number() }; - + let submitted_header_number = header.number(); log::debug!( target: "bridge", "Going to submit finality proof of {} header #{:?} to {}", P::SOURCE_NAME, - new_transaction.submitted_header_number, + submitted_header_number, P::TARGET_NAME, ); - target_client + let tracker = target_client .submit_finality_proof(header, justification) .await .map_err(Error::Target)?; - Ok(Some(new_transaction)) + Ok(Some(Transaction { tracker, submitted_header_number })) }, None => Ok(None), } diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index b7f7bc80029fa..7144ccb0c4810 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -20,10 +20,10 @@ use crate::{ finality_loop::{ - prune_recent_finality_proofs, read_finality_proofs_from_stream, run, run_loop_iteration, - select_better_recent_finality_proof, select_header_to_submit, FinalityLoopState, - FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, SourceClient, - TargetClient, + prune_recent_finality_proofs, read_finality_proofs_from_stream, run_loop_iteration, + run_until_connection_lost, select_better_recent_finality_proof, select_header_to_submit, + FinalityLoopState, FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, + SourceClient, TargetClient, }, sync_loop_metrics::SyncLoopMetrics, FinalityProof, FinalitySyncPipeline, SourceHeader, @@ -33,7 +33,8 @@ use async_trait::async_trait; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError, + relay_loop::Client as RelayClient, FailedClient, HeaderId, MaybeConnectionError, + TrackedTransactionStatus, TransactionTracker, }; use std::{ collections::HashMap, @@ -46,6 +47,22 @@ type IsMandatory = bool; type TestNumber = u64; type TestHash = u64; +#[derive(Clone, Debug)] +struct TestTransactionTracker(TrackedTransactionStatus); + +impl Default for TestTransactionTracker { + fn default() -> TestTransactionTracker { + TestTransactionTracker(TrackedTransactionStatus::Finalized) + } +} + +#[async_trait] +impl TransactionTracker for TestTransactionTracker { + async fn wait(self) -> TrackedTransactionStatus { + self.0 + } +} + #[derive(Debug, Clone)] enum TestError { NonConnection, @@ -104,6 +121,7 @@ struct ClientsData { target_best_block_id: HeaderId, target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, + target_transaction_tracker: TestTransactionTracker, } #[derive(Clone)] @@ -164,6 +182,8 @@ impl RelayClient for TestTargetClient { #[async_trait] impl TargetClient for TestTargetClient { + type TransactionTracker = TestTransactionTracker; + async fn best_finalized_source_block_id( &self, ) -> Result, TestError> { @@ -176,12 +196,13 @@ impl TargetClient for TestTargetClient { &self, header: TestSourceHeader, proof: TestFinalityProof, - ) -> Result<(), TestError> { + ) -> Result { let mut data = self.data.lock(); (self.on_method_call)(&mut data); data.target_best_block_id = HeaderId(header.number(), header.hash()); data.target_headers.push((header, proof)); - Ok(()) + (self.on_method_call)(&mut data); + Ok(data.target_transaction_tracker.clone()) } } @@ -203,6 +224,7 @@ fn prepare_test_clients( target_best_block_id: HeaderId(5, 5), target_headers: vec![], + target_transaction_tracker: TestTransactionTracker(TrackedTransactionStatus::Finalized), })); ( TestSourceClient { @@ -224,7 +246,7 @@ fn test_sync_params() -> FinalitySyncParams { fn run_sync_loop( state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, -) -> ClientsData { +) -> (ClientsData, Result<(), FailedClient>) { let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); let (source_client, target_client) = prepare_test_clients( exit_sender, @@ -243,21 +265,21 @@ fn run_sync_loop( let sync_params = test_sync_params(); let clients_data = source_client.data.clone(); - let _ = async_std::task::block_on(run( + let result = async_std::task::block_on(run_until_connection_lost( source_client, target_client, sync_params, - MetricsParams::disabled(), + None, exit_receiver.into_future().map(|(_, _)| ()), )); let clients_data = clients_data.lock().clone(); - clients_data + (clients_data, result) } #[test] fn finality_sync_loop_works() { - let client_data = run_sync_loop(|data| { + let (client_data, result) = run_sync_loop(|data| { // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, // because header#8 has persistent finality proof && it is mandatory => it is submitted // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, @@ -286,6 +308,7 @@ fn finality_sync_loop_works() { data.target_best_block_id.0 == 16 }); + assert_eq!(result, Ok(())); assert_eq!( client_data.target_headers, vec![ @@ -538,7 +561,7 @@ fn different_forks_at_source_and_at_target_are_detected() { progress: &mut progress, finality_proofs_stream: &mut finality_proofs_stream, recent_finality_proofs: &mut recent_finality_proofs, - last_transaction: None, + submitted_header_number: None, }, &test_sync_params(), &Some(metrics_sync.clone()), @@ -547,3 +570,14 @@ fn different_forks_at_source_and_at_target_are_detected() { assert!(!metrics_sync.is_using_same_fork()); } + +#[test] +fn stalls_when_transaction_tracker_returns_error() { + let (_, result) = run_sync_loop(|data| { + data.target_transaction_tracker = TestTransactionTracker(TrackedTransactionStatus::Lost); + data.target_best_block_id = HeaderId(5, 5); + data.target_best_block_id.0 == 16 + }); + + assert_eq!(result, Err(FailedClient::Both)); +} diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 351f21cec80a9..7bdb77d4ee05e 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -28,7 +28,7 @@ use async_trait::async_trait; use finality_relay::TargetClient; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, - SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, + SyncHeader, TransactionEra, TransactionSignScheme, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -89,6 +89,8 @@ where AccountIdOf: From< as Pair>::Public>, P::TransactionSignScheme: TransactionSignScheme, { + type TransactionTracker = TransactionTracker; + async fn best_finalized_source_block_id(&self) -> Result, Error> { // we can't continue to relay finality if target node is out of sync, because // it may have already received (some of) headers that we're going to relay @@ -109,14 +111,14 @@ where &self, header: SyncHeader>, proof: SubstrateFinalityProof

, - ) -> Result<(), Error> { + ) -> Result { let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client - .submit_signed_extrinsic( + .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), SignParam:: { spec_version, @@ -130,6 +132,5 @@ where }, ) .await - .map(drop) } } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 8e8870ac188f6..dbc8e5df8218b 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -20,6 +20,7 @@ pub use bp_runtime::HeaderId; pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; +use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; use futures::future::FutureExt; use std::time::Duration; @@ -119,6 +120,22 @@ pub trait MaybeConnectionError { fn is_connection_error(&self) -> bool; } +/// Final status of the tracked transaction. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum TrackedTransactionStatus { + /// Transaction has been lost. + Lost, + /// Transaction has been mined and finalized. + Finalized, +} + +/// Transaction tracker. +#[async_trait] +pub trait TransactionTracker: Send { + /// Wait until transaction is either finalized or invalidated/lost. + async fn wait(self) -> TrackedTransactionStatus; +} + /// Stringified error that may be either connection-related or not. #[derive(Error, Debug)] pub enum StringifiedMaybeConnectionError { From 54228395e4caf92c37c13e41fbd629840f6e44eb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 20 Sep 2022 17:26:24 +0300 Subject: [PATCH 0774/1210] Do not wait for tx status forever (#1578) * do not wait for tx status forever * more logging --- .../src/transaction_tracker.rs | 81 +++++++++++++++---- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/relays/client-substrate/src/transaction_tracker.rs b/relays/client-substrate/src/transaction_tracker.rs index b85e859017f7e..a84a46240a4ab 100644 --- a/relays/client-substrate/src/transaction_tracker.rs +++ b/relays/client-substrate/src/transaction_tracker.rs @@ -19,7 +19,7 @@ use crate::{Chain, HashOf, Subscription, TransactionStatusOf}; use async_trait::async_trait; -use futures::{Stream, StreamExt}; +use futures::{future::Either, Future, FutureExt, Stream, StreamExt}; use relay_utils::TrackedTransactionStatus; use std::time::Duration; @@ -61,28 +61,50 @@ impl TransactionTracker { /// Wait for final transaction status and return it along with last known internal invalidation /// status. - async fn do_wait(self) -> (TrackedTransactionStatus, InvalidationStatus) { - let invalidation_status = watch_transaction_status::( + async fn do_wait( + self, + wait_for_stall_timeout: impl Future, + wait_for_stall_timeout_rest: impl Future, + ) -> (TrackedTransactionStatus, Option) { + // sometimes we want to wait for the rest of the stall timeout even if + // `wait_for_invalidation` has been "select"ed first => it is shared + let wait_for_invalidation = watch_transaction_status::( self.transaction_hash, self.subscription.into_stream(), - ) - .await; - match invalidation_status { - InvalidationStatus::Finalized => - (TrackedTransactionStatus::Finalized, invalidation_status), - InvalidationStatus::Invalid => (TrackedTransactionStatus::Lost, invalidation_status), - InvalidationStatus::Lost => { - async_std::task::sleep(self.stall_timeout).await; - // if someone is still watching for our transaction, then we're reporting - // an error here (which is treated as "transaction lost") + ); + futures::pin_mut!(wait_for_stall_timeout, wait_for_invalidation); + + match futures::future::select(wait_for_stall_timeout, wait_for_invalidation).await { + Either::Left((_, _)) => { log::trace!( target: "bridge", - "{} transaction {:?} is considered lost after timeout", + "{} transaction {:?} is considered lost after timeout (no status response from the node)", C::NAME, self.transaction_hash, ); - (TrackedTransactionStatus::Lost, invalidation_status) + (TrackedTransactionStatus::Lost, None) + }, + Either::Right((invalidation_status, _)) => match invalidation_status { + InvalidationStatus::Finalized => + (TrackedTransactionStatus::Finalized, Some(invalidation_status)), + InvalidationStatus::Invalid => + (TrackedTransactionStatus::Lost, Some(invalidation_status)), + InvalidationStatus::Lost => { + // wait for the rest of stall timeout - this way we'll be sure that the + // transaction is actually dead if it has been crafted properly + wait_for_stall_timeout_rest.await; + // if someone is still watching for our transaction, then we're reporting + // an error here (which is treated as "transaction lost") + log::trace!( + target: "bridge", + "{} transaction {:?} is considered lost after timeout", + C::NAME, + self.transaction_hash, + ); + + (TrackedTransactionStatus::Lost, Some(invalidation_status)) + }, }, } } @@ -91,7 +113,9 @@ impl TransactionTracker { #[async_trait] impl relay_utils::TransactionTracker for TransactionTracker { async fn wait(self) -> TrackedTransactionStatus { - self.do_wait().await.0 + let wait_for_stall_timeout = async_std::task::sleep(self.stall_timeout).shared(); + let wait_for_stall_timeout_rest = wait_for_stall_timeout.clone(); + self.do_wait(wait_for_stall_timeout, wait_for_stall_timeout_rest).await.0 } } @@ -233,8 +257,13 @@ mod tests { Subscription(async_std::sync::Mutex::new(receiver)), ); + let wait_for_stall_timeout = futures::future::pending(); + let wait_for_stall_timeout_rest = futures::future::ready(()); sender.send(Some(status)).await.unwrap(); - tx_tracker.do_wait().now_or_never() + tx_tracker + .do_wait(wait_for_stall_timeout, wait_for_stall_timeout_rest) + .now_or_never() + .map(|(ts, is)| (ts, is.unwrap())) } #[async_std::test] @@ -319,4 +348,22 @@ mod tests { Some(InvalidationStatus::Lost), ); } + + #[async_std::test] + async fn lost_on_timeout_when_waiting_for_invalidation_status() { + let (_sender, receiver) = futures::channel::mpsc::channel(1); + let tx_tracker = TransactionTracker::::new( + Duration::from_secs(0), + Default::default(), + Subscription(async_std::sync::Mutex::new(receiver)), + ); + + let wait_for_stall_timeout = futures::future::ready(()).shared(); + let wait_for_stall_timeout_rest = wait_for_stall_timeout.clone(); + let wait_result = tx_tracker + .do_wait(wait_for_stall_timeout, wait_for_stall_timeout_rest) + .now_or_never(); + + assert_eq!(wait_result, Some((TrackedTransactionStatus::Lost, None))); + } } From 67907f766d7a39011f043056a7b02dc5d4fe5727 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Sep 2022 10:25:25 +0300 Subject: [PATCH 0775/1210] fix spelling (#1580) --- bin/rialto-parachain/node/src/cli.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index bd45db9758cba..51fa1e9776c38 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -50,7 +50,7 @@ pub enum Subcommand { /// Revert the chain to a previous state. Revert(sc_cli::RevertCmd), - /// The custom benchmark subcommmand benchmarking runtime pallets. + /// The custom benchmark subcommand benchmarking runtime pallets. #[clap(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), } @@ -116,7 +116,7 @@ pub struct Cli { #[derive(Debug)] pub struct RelayChainCli { - /// The actual relay chain cli object. + /// The actual relay chain CLI object. pub base: polkadot_cli::RunCmd, /// Optional chain id that should be passed to the relay chain. From 48cb59a431806c33ffc6527f5bf81165d183cd67 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Sep 2022 15:21:51 +0300 Subject: [PATCH 0776/1210] use transaction tracker in parachains relay (#1575) * use transaction tracker in parachains relay * actually return tx tracker from target client implementation --- .../src/parachains/target.rs | 9 +- relays/parachains/src/parachains_loop.rs | 203 ++++++++++++------ 2 files changed, 139 insertions(+), 73 deletions(-) diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index fa159cdeb7e5a..34a6a31311dd2 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -34,7 +34,7 @@ use parachains_relay::{ use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, HeaderOf, RelayChain, SignParam, TransactionEra, TransactionSignScheme, - UnsignedTransaction, + TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -86,6 +86,8 @@ where P::TransactionSignScheme: TransactionSignScheme, AccountIdOf: From< as Pair>::Public>, { + type TransactionTracker = TransactionTracker; + async fn best_block(&self) -> Result, Self::Error> { let best_header = self.client.best_header().await?; let best_id = best_header.id(); @@ -172,7 +174,7 @@ where at_relay_block: HeaderIdOf, updated_parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, - ) -> Result<(), Self::Error> { + ) -> Result { let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; @@ -182,7 +184,7 @@ where proof, ); self.client - .submit_signed_extrinsic( + .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), SignParam:: { spec_version, @@ -196,6 +198,5 @@ where }, ) .await - .map(drop) } } diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index f44f986d63231..09e55740cef3c 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -22,13 +22,21 @@ use bp_polkadot_core::{ parachains::{ParaHash, ParaHeadsProof, ParaId}, BlockNumber as RelayBlockNumber, }; -use futures::{future::FutureExt, select}; +use futures::{ + future::{FutureExt, Shared}, + poll, select, +}; use relay_substrate_client::{BlockNumberOf, Chain, HeaderIdOf}; -use relay_utils::{metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient}; +use relay_utils::{ + metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, + TrackedTransactionStatus, TransactionTracker, +}; use std::{ collections::{BTreeMap, BTreeSet}, future::Future, - time::{Duration, Instant}, + pin::Pin, + task::Poll, + time::Duration, }; /// Parachain heads synchronization params. @@ -115,6 +123,9 @@ pub trait SourceClient: RelayClient { /// Target client used in parachain heads synchronization loop. #[async_trait] pub trait TargetClient: RelayClient { + /// Transaction tracker to track submitted transactions. + type TransactionTracker: TransactionTracker; + /// Get best block id. async fn best_block(&self) -> Result, Self::Error>; @@ -141,7 +152,7 @@ pub trait TargetClient: RelayClient { at_source_block: HeaderIdOf, updated_parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, - ) -> Result<(), Self::Error>; + ) -> Result; } /// Return prefix that will be used by default to expose Prometheus metrics of the parachains @@ -196,7 +207,7 @@ where P::TargetChain::AVERAGE_BLOCK_INTERVAL, ); - let mut tx_tracker: Option> = None; + let mut submitted_heads_tracker: Option> = None; futures::pin_mut!(exit_signal); @@ -246,9 +257,29 @@ where &sync_params.parachains, ) .await?; - tx_tracker = tx_tracker.take().and_then(|tx_tracker| tx_tracker.update(&heads_at_target)); - if tx_tracker.is_some() { - continue + + // check if our transaction has been mined + if let Some(tracker) = submitted_heads_tracker.take() { + match tracker.update(&heads_at_target).await { + SubmittedHeadsStatus::Waiting(tracker) => { + // no news about our transaction and we shall keep waiting + submitted_heads_tracker = Some(tracker); + continue + }, + SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized) => { + // all heads have been updated, we don't need this tracker anymore + }, + SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) => { + log::warn!( + target: "bridge", + "Parachains synchronization from {} to {} has stalled. Going to restart", + P::SourceChain::NAME, + P::TargetChain::NAME, + ); + + return Err(FailedClient::Both) + }, + } } // we have no active transaction and may need to update heads, but do we have something for @@ -317,7 +348,7 @@ where "Incorrect parachains SourceClient implementation" ); - target_client + let transaction_tracker = target_client .submit_parachain_heads_proof( best_finalized_relay_block, updated_ids.iter().cloned().zip(head_hashes).collect(), @@ -334,11 +365,10 @@ where ); FailedClient::Target })?; - - tx_tracker = Some(TransactionTracker::

::new( + submitted_heads_tracker = Some(SubmittedHeadsTracker::

::new( updated_ids, best_finalized_relay_block.0, - sync_params.stall_timeout, + transaction_tracker, )); } } @@ -494,19 +524,27 @@ async fn read_heads_at_target( Ok(para_best_head_hashes) } -/// Parachain heads transaction tracker. -struct TransactionTracker { +/// Submitted heads status. +enum SubmittedHeadsStatus { + /// Heads are not yet updated. + Waiting(SubmittedHeadsTracker

), + /// Heads transaction has either been finalized or lost (i.e. received its "final" status). + Final(TrackedTransactionStatus), +} + +/// Submitted parachain heads transaction. +struct SubmittedHeadsTracker { /// Ids of parachains which heads were updated in the tracked transaction. awaiting_update: BTreeSet, /// Number of relay chain block that has been used to craft parachain heads proof. relay_block_number: BlockNumberOf, - /// Transaction submit time. - submitted_at: Instant, - /// Transaction death time. - death_time: Instant, + /// Future that waits for submitted transaction finality or loss. + /// + /// It needs to be shared because of `poll` macro and our consuming `update` method. + transaction_tracker: Shared + Send>>>, } -impl TransactionTracker

+impl SubmittedHeadsTracker

where P::SourceChain: Chain, { @@ -514,22 +552,20 @@ where pub fn new( awaiting_update: impl IntoIterator, relay_block_number: BlockNumberOf, - stall_timeout: Duration, + transaction_tracker: impl TransactionTracker + 'static, ) -> Self { - let now = Instant::now(); - TransactionTracker { + SubmittedHeadsTracker { awaiting_update: awaiting_update.into_iter().collect(), relay_block_number, - submitted_at: now, - death_time: now + stall_timeout, + transaction_tracker: transaction_tracker.wait().fuse().boxed().shared(), } } - /// Returns `None` if all parachain heads have been updated or we consider our transaction dead. - pub fn update( + /// Returns `None` if all submitted parachain heads have been updated. + pub async fn update( mut self, heads_at_target: &BTreeMap>, - ) -> Option { + ) -> SubmittedHeadsStatus

{ // remove all pending heads that were synced for (para, best_para_head) in heads_at_target { if best_para_head @@ -554,23 +590,17 @@ where // if we have synced all required heads, we are done if self.awaiting_update.is_empty() { - return None + return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized) } - // if our transaction is dead now, we may start over again - let now = Instant::now(); - if now >= self.death_time { - log::warn!( - target: "bridge", - "Parachain heads update transaction {} has been lost: no updates for {}s", - P::TargetChain::NAME, - (now - self.submitted_at).as_secs(), - ); - - return None + // if underlying transaction tracker has reported that the transaction is lost, we may + // then restart our sync + let transaction_tracker = self.transaction_tracker.clone(); + if let Poll::Ready(TrackedTransactionStatus::Lost) = poll!(transaction_tracker) { + return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) } - Some(self) + SubmittedHeadsStatus::Waiting(self) } } @@ -613,6 +643,16 @@ mod tests { data: Arc>, } + #[derive(Clone, Debug)] + struct TestTransactionTracker(TrackedTransactionStatus); + + #[async_trait] + impl TransactionTracker for TestTransactionTracker { + async fn wait(self) -> TrackedTransactionStatus { + self.0 + } + } + #[derive(Clone, Debug)] struct TestClientData { source_sync_status: Result, @@ -711,6 +751,8 @@ mod tests { #[async_trait] impl TargetClient for TestClient { + type TransactionTracker = TestTransactionTracker; + async fn best_block(&self) -> Result, TestError> { self.data.lock().await.target_best_block.clone() } @@ -736,13 +778,14 @@ mod tests { _at_source_block: HeaderIdOf, _updated_parachains: Vec<(ParaId, ParaHash)>, _proof: ParaHeadsProof, - ) -> Result<(), Self::Error> { - self.data.lock().await.target_submit_result.clone()?; + ) -> Result { + let mut data = self.data.lock().await; + data.target_submit_result.clone()?; - if let Some(mut exit_signal_sender) = self.data.lock().await.exit_signal_sender.take() { + if let Some(mut exit_signal_sender) = data.exit_signal_sender.take() { exit_signal_sender.send(()).await.unwrap(); } - Ok(()) + Ok(TestTransactionTracker(TrackedTransactionStatus::Finalized)) } } @@ -891,27 +934,35 @@ mod tests { const PARA_1_ID: u32 = PARA_ID + 1; const SOURCE_BLOCK_NUMBER: u32 = 100; - fn test_tx_tracker() -> TransactionTracker { - TransactionTracker::new( + fn test_tx_tracker() -> SubmittedHeadsTracker { + SubmittedHeadsTracker::new( vec![ParaId(PARA_ID), ParaId(PARA_1_ID)], SOURCE_BLOCK_NUMBER, - Duration::from_secs(1), + TestTransactionTracker(TrackedTransactionStatus::Finalized), ) } - #[test] - fn tx_tracker_update_when_nothing_is_updated() { + impl From> for Option> { + fn from(status: SubmittedHeadsStatus) -> Option> { + match status { + SubmittedHeadsStatus::Waiting(tracker) => Some(tracker.awaiting_update), + _ => None, + } + } + } + + #[async_std::test] + async fn tx_tracker_update_when_nothing_is_updated() { assert_eq!( - test_tx_tracker() - .update(&vec![].into_iter().collect()) - .map(|t| t.awaiting_update), Some(test_tx_tracker().awaiting_update), + test_tx_tracker().update(&vec![].into_iter().collect()).await.into(), ); } - #[test] - fn tx_tracker_update_when_one_of_heads_is_updated_to_previous_value() { + #[async_std::test] + async fn tx_tracker_update_when_one_of_heads_is_updated_to_previous_value() { assert_eq!( + Some(test_tx_tracker().awaiting_update), test_tx_tracker() .update( &vec![( @@ -924,14 +975,15 @@ mod tests { .into_iter() .collect() ) - .map(|t| t.awaiting_update), - Some(test_tx_tracker().awaiting_update), + .await + .into(), ); } - #[test] - fn tx_tracker_update_when_one_of_heads_is_updated() { + #[async_std::test] + async fn tx_tracker_update_when_one_of_heads_is_updated() { assert_eq!( + Some(vec![ParaId(PARA_1_ID)].into_iter().collect::>()), test_tx_tracker() .update( &vec![( @@ -944,14 +996,15 @@ mod tests { .into_iter() .collect() ) - .map(|t| t.awaiting_update), - Some(vec![ParaId(PARA_1_ID)].into_iter().collect()), + .await + .into(), ); } - #[test] - fn tx_tracker_update_when_all_heads_are_updated() { + #[async_std::test] + async fn tx_tracker_update_when_all_heads_are_updated() { assert_eq!( + Option::>::None, test_tx_tracker() .update( &vec![ @@ -973,21 +1026,33 @@ mod tests { .into_iter() .collect() ) - .map(|t| t.awaiting_update), - None, + .await + .into(), ); } - #[test] - fn tx_tracker_update_when_tx_is_stalled() { + #[async_std::test] + async fn tx_tracker_update_when_tx_is_stalled() { let mut tx_tracker = test_tx_tracker(); - tx_tracker.death_time = Instant::now(); + tx_tracker.transaction_tracker = + futures::future::ready(TrackedTransactionStatus::Lost).boxed().shared(); assert_eq!( - tx_tracker.update(&vec![].into_iter().collect()).map(|t| t.awaiting_update), - None, + Option::>::None, + tx_tracker.update(&vec![].into_iter().collect()).await.into(), ); } + #[async_std::test] + async fn tx_tracker_update_when_tx_is_finalized() { + let mut tx_tracker = test_tx_tracker(); + tx_tracker.transaction_tracker = + futures::future::ready(TrackedTransactionStatus::Finalized).boxed().shared(); + assert!(matches!( + tx_tracker.update(&vec![].into_iter().collect()).await, + SubmittedHeadsStatus::Waiting(_), + )); + } + #[test] fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() { assert_eq!( From 73400e123a964949c277a97d381da290b78dd073 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 23 Sep 2022 12:02:59 +0300 Subject: [PATCH 0777/1210] use transaction tracker in messages relay (#1581) --- relays/client-substrate/src/lib.rs | 27 ---- .../lib-substrate-relay/src/messages_lane.rs | 12 +- .../src/messages_source.rs | 11 +- .../src/messages_target.rs | 15 +- relays/messages/src/message_lane_loop.rs | 135 ++++++++++++++++-- relays/messages/src/message_race_delivery.rs | 9 +- relays/messages/src/message_race_loop.rs | 59 ++++---- relays/messages/src/message_race_receiving.rs | 14 +- 8 files changed, 176 insertions(+), 106 deletions(-) diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index b9e489688d35d..bd38f3a928f83 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -88,30 +88,3 @@ pub fn transaction_stall_timeout( .map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1)) .unwrap_or(default_stall_timeout) } - -/// Returns stall timeout for relay loop that submit transactions to two chains. -/// -/// Bidirectional relay may have two active transactions. Even if one of them has been spoiled, we -/// can't just restart the loop - the other transaction may still be alive and we'll be submitting -/// duplicate transaction, which may result in funds loss. So we'll be selecting maximal mortality -/// for choosing loop stall timeout. -pub fn bidirectional_transaction_stall_timeout( - left_mortality_period: Option, - right_mortality_period: Option, - left_average_block_interval: Duration, - right_average_block_interval: Duration, - default_stall_timeout: Duration, -) -> Duration { - std::cmp::max( - transaction_stall_timeout( - left_mortality_period, - left_average_block_interval, - default_stall_timeout, - ), - transaction_stall_timeout( - right_mortality_period, - right_average_block_interval, - default_stall_timeout, - ), - ) -} diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index f69ebc347d72c..55fcb540ebef5 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -164,13 +164,6 @@ where { let source_client = params.source_client; let target_client = params.target_client; - let stall_timeout = relay_substrate_client::bidirectional_transaction_stall_timeout( - params.source_transaction_params.mortality, - params.target_transaction_params.mortality, - P::SourceChain::AVERAGE_BLOCK_INTERVAL, - P::TargetChain::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); let relayer_id_at_source: AccountIdOf = params.source_transaction_params.signer.public().into(); @@ -202,8 +195,7 @@ where Max messages in single transaction: {}\n\t\ Max messages size in single transaction: {}\n\t\ Max messages weight in single transaction: {}\n\t\ - Tx mortality: {:?} (~{}m)/{:?} (~{}m)\n\t\ - Stall timeout: {:?}", + Tx mortality: {:?} (~{}m)/{:?} (~{}m)", P::SourceChain::NAME, P::TargetChain::NAME, P::SourceChain::NAME, @@ -223,7 +215,6 @@ where P::TargetChain::AVERAGE_BLOCK_INTERVAL, STALL_TIMEOUT, ).as_secs_f64() / 60.0f64, - stall_timeout, ); messages_relay::message_lane_loop::run( @@ -232,7 +223,6 @@ where source_tick: P::SourceChain::AVERAGE_BLOCK_INTERVAL, target_tick: P::TargetChain::AVERAGE_BLOCK_INTERVAL, reconnect_delay: relay_utils::relay_loop::RECONNECT_DELAY, - stall_timeout, delivery_params: messages_relay::message_lane_loop::MessageDeliveryParams { max_unrewarded_relayer_entries_at_target: P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 5de9e30dd0ea2..ca0c3f54bb562 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -51,7 +51,7 @@ use num_traits::{Bounded, Zero}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionSignScheme, UnsignedTransaction, + TransactionSignScheme, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -144,6 +144,8 @@ where From< as Pair>::Public>, P::SourceTransactionSignScheme: TransactionSignScheme, { + type TransactionTracker = TransactionTracker; + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver @@ -338,13 +340,13 @@ where &self, _generated_at_block: TargetHeaderIdOf>, proof: as MessageLane>::MessagesReceivingProof, - ) -> Result<(), SubstrateError> { + ) -> Result { let genesis_hash = *self.source_client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let (spec_version, transaction_version) = self.source_client.simple_runtime_version().await?; self.source_client - .submit_signed_extrinsic( + .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), SignParam:: { spec_version, @@ -362,8 +364,7 @@ where ) }, ) - .await?; - Ok(()) + .await } async fn require_target_header_on_source(&self, id: TargetHeaderIdOf>) { diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 29d80bc2c5ee1..4e5ba6ae087bc 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -39,13 +39,13 @@ use codec::Encode; use frame_support::weights::{Weight, WeightToFee}; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{TargetClient, TargetClientState}, + message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionSignScheme, UnsignedTransaction, WeightToFeeOf, + TransactionSignScheme, TransactionTracker, UnsignedTransaction, WeightToFeeOf, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -145,6 +145,8 @@ where P::TargetTransactionSignScheme: TransactionSignScheme, BalanceOf: TryFrom>, { + type TransactionTracker = TransactionTracker; + async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because // it may have already received confirmations that we're going to deliver @@ -245,15 +247,16 @@ where _generated_at_header: SourceHeaderIdOf>, nonces: RangeInclusive, proof: as MessageLane>::MessagesProof, - ) -> Result, SubstrateError> { + ) -> Result, SubstrateError> { let genesis_hash = *self.target_client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let relayer_id_at_source = self.relayer_id_at_source.clone(); let nonces_clone = nonces.clone(); let (spec_version, transaction_version) = self.target_client.simple_runtime_version().await?; - self.target_client - .submit_signed_extrinsic( + let tx_tracker = self + .target_client + .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), SignParam:: { spec_version, @@ -274,7 +277,7 @@ where }, ) .await?; - Ok(nonces) + Ok(NoncesSubmitArtifacts { nonces, tx_tracker }) } async fn require_source_header_on_target(&self, id: SourceHeaderIdOf>) { diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index bd7a7de8290b9..6e3b02f1cffc8 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -33,7 +33,7 @@ use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; use bp_runtime::messages::DispatchFeePayment; use relay_utils::{ interval, metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, - retry_backoff, FailedClient, + retry_backoff, FailedClient, TransactionTracker, }; use crate::{ @@ -55,8 +55,6 @@ pub struct Params { pub target_tick: Duration, /// Delay between moments when connection error happens and our reconnect attempt. pub reconnect_delay: Duration, - /// The loop will auto-restart if there has been no updates during this period. - pub stall_timeout: Duration, /// Message delivery race parameters. pub delivery_params: MessageDeliveryParams, } @@ -119,9 +117,20 @@ pub struct MessageProofParameters { pub dispatch_weight: Weight, } +/// Artifacts of submitting nonces proof. +pub struct NoncesSubmitArtifacts { + /// Submitted nonces range. + pub nonces: RangeInclusive, + /// Submitted transaction tracker. + pub tx_tracker: T, +} + /// Source client trait. #[async_trait] pub trait SourceClient: RelayClient { + /// Transaction tracker to track submitted transactions. + type TransactionTracker: TransactionTracker; + /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -160,7 +169,7 @@ pub trait SourceClient: RelayClient { &self, generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, - ) -> Result<(), Self::Error>; + ) -> Result; /// We need given finalized target header on source to continue synchronization. async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

); @@ -172,6 +181,9 @@ pub trait SourceClient: RelayClient { /// Target client trait. #[async_trait] pub trait TargetClient: RelayClient { + /// Transaction tracker to track submitted transactions. + type TransactionTracker: TransactionTracker; + /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -205,7 +217,7 @@ pub trait TargetClient: RelayClient { generated_at_header: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; /// We need given finalized source header on target to continue synchronization. async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

); @@ -327,7 +339,6 @@ async fn run_until_connection_lost< delivery_source_state_receiver, target_client.clone(), delivery_target_state_receiver, - params.stall_timeout, metrics_msg.clone(), params.delivery_params, ) @@ -342,7 +353,6 @@ async fn run_until_connection_lost< receiving_source_state_receiver, target_client.clone(), receiving_target_state_receiver, - params.stall_timeout, metrics_msg.clone(), ) .fuse(); @@ -465,7 +475,7 @@ pub(crate) mod tests { use futures::stream::StreamExt; use parking_lot::Mutex; - use relay_utils::{HeaderId, MaybeConnectionError}; + use relay_utils::{HeaderId, MaybeConnectionError, TrackedTransactionStatus}; use crate::relay_strategy::AltruisticStrategy; @@ -518,19 +528,37 @@ pub(crate) mod tests { type TargetHeaderHash = TestTargetHeaderHash; } - #[derive(Debug, Default, Clone)] + #[derive(Clone, Debug)] + pub struct TestTransactionTracker(TrackedTransactionStatus); + + impl Default for TestTransactionTracker { + fn default() -> TestTransactionTracker { + TestTransactionTracker(TrackedTransactionStatus::Finalized) + } + } + + #[async_trait] + impl TransactionTracker for TestTransactionTracker { + async fn wait(self) -> TrackedTransactionStatus { + self.0 + } + } + + #[derive(Debug, Clone)] pub struct TestClientData { is_source_fails: bool, is_source_reconnected: bool, source_state: SourceClientState, source_latest_generated_nonce: MessageNonce, source_latest_confirmed_received_nonce: MessageNonce, + source_tracked_transaction_status: TrackedTransactionStatus, submitted_messages_receiving_proofs: Vec, is_target_fails: bool, is_target_reconnected: bool, target_state: SourceClientState, target_latest_received_nonce: MessageNonce, target_latest_confirmed_received_nonce: MessageNonce, + target_tracked_transaction_status: TrackedTransactionStatus, submitted_messages_proofs: Vec, target_to_source_header_required: Option, target_to_source_header_requirements: Vec, @@ -538,6 +566,31 @@ pub(crate) mod tests { source_to_target_header_requirements: Vec, } + impl Default for TestClientData { + fn default() -> TestClientData { + TestClientData { + is_source_fails: false, + is_source_reconnected: false, + source_state: Default::default(), + source_latest_generated_nonce: 0, + source_latest_confirmed_received_nonce: 0, + source_tracked_transaction_status: TrackedTransactionStatus::Finalized, + submitted_messages_receiving_proofs: Vec::new(), + is_target_fails: false, + is_target_reconnected: false, + target_state: Default::default(), + target_latest_received_nonce: 0, + target_latest_confirmed_received_nonce: 0, + target_tracked_transaction_status: TrackedTransactionStatus::Finalized, + submitted_messages_proofs: Vec::new(), + target_to_source_header_required: None, + target_to_source_header_requirements: Vec::new(), + source_to_target_header_required: None, + source_to_target_header_requirements: Vec::new(), + } + } + } + #[derive(Clone)] pub struct TestSourceClient { data: Arc>, @@ -569,6 +622,8 @@ pub(crate) mod tests { #[async_trait] impl SourceClient for TestSourceClient { + type TransactionTracker = TestTransactionTracker; + async fn state(&self) -> Result, TestError> { let mut data = self.data.lock(); (self.tick)(&mut data); @@ -648,7 +703,7 @@ pub(crate) mod tests { &self, _generated_at_block: TargetHeaderIdOf, proof: TestMessagesReceivingProof, - ) -> Result<(), TestError> { + ) -> Result { let mut data = self.data.lock(); (self.tick)(&mut data); data.source_state.best_self = @@ -656,7 +711,7 @@ pub(crate) mod tests { data.source_state.best_finalized_self = data.source_state.best_self; data.submitted_messages_receiving_proofs.push(proof); data.source_latest_confirmed_received_nonce = proof; - Ok(()) + Ok(TestTransactionTracker(data.source_tracked_transaction_status)) } async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { @@ -702,6 +757,8 @@ pub(crate) mod tests { #[async_trait] impl TargetClient for TestTargetClient { + type TransactionTracker = TestTransactionTracker; + async fn state(&self) -> Result, TestError> { let mut data = self.data.lock(); (self.tick)(&mut data); @@ -762,7 +819,7 @@ pub(crate) mod tests { _generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: TestMessagesProof, - ) -> Result, TestError> { + ) -> Result, TestError> { let mut data = self.data.lock(); (self.tick)(&mut data); if data.is_target_fails { @@ -777,7 +834,10 @@ pub(crate) mod tests { target_latest_confirmed_received_nonce; } data.submitted_messages_proofs.push(proof); - Ok(nonces) + Ok(NoncesSubmitArtifacts { + nonces, + tx_tracker: TestTransactionTracker(data.target_tracked_transaction_status), + }) } async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { @@ -817,7 +877,6 @@ pub(crate) mod tests { source_tick: Duration::from_millis(100), target_tick: Duration::from_millis(100), reconnect_delay: Duration::from_millis(0), - stall_timeout: Duration::from_millis(60 * 1000), delivery_params: MessageDeliveryParams { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, @@ -889,6 +948,54 @@ pub(crate) mod tests { assert_eq!(result.submitted_messages_proofs, vec![(1..=1, None)],); } + #[test] + fn message_lane_loop_is_able_to_recover_from_race_stall() { + // with this configuration, both source and target clients will lose their transactions => + // reconnect will happen + let (source_exit_sender, exit_receiver) = unbounded(); + let target_exit_sender = source_exit_sender.clone(); + let result = run_loop_test( + TestClientData { + source_state: ClientState { + best_self: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + }, + source_latest_generated_nonce: 1, + source_tracked_transaction_status: TrackedTransactionStatus::Lost, + target_state: ClientState { + best_self: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + }, + target_latest_received_nonce: 0, + target_tracked_transaction_status: TrackedTransactionStatus::Lost, + ..Default::default() + }, + Arc::new(move |data: &mut TestClientData| { + if data.is_source_reconnected { + data.source_tracked_transaction_status = TrackedTransactionStatus::Finalized; + } + if data.is_source_reconnected && data.is_target_reconnected { + source_exit_sender.unbounded_send(()).unwrap(); + } + }), + Arc::new(move |data: &mut TestClientData| { + if data.is_target_reconnected { + data.target_tracked_transaction_status = TrackedTransactionStatus::Finalized; + } + if data.is_source_reconnected && data.is_target_reconnected { + target_exit_sender.unbounded_send(()).unwrap(); + } + }), + exit_receiver.into_future().map(|(_, _)| ()), + ); + + assert!(result.is_source_reconnected); + } + #[test] fn message_lane_loop_works() { let (exit_sender, exit_receiver) = unbounded(); diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 85f6d955e7df0..e15e08b04233d 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -13,7 +13,7 @@ //! Message delivery race delivers proof-of-messages from "lane.source" to "lane.target". -use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive, time::Duration}; +use std::{collections::VecDeque, marker::PhantomData, ops::RangeInclusive}; use async_trait::async_trait; use futures::stream::FusedStream; @@ -24,7 +24,7 @@ use relay_utils::FailedClient; use crate::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, + MessageDeliveryParams, MessageDetailsMap, MessageProofParameters, NoncesSubmitArtifacts, SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }, @@ -43,7 +43,6 @@ pub async fn run( source_state_updates: impl FusedStream>, target_client: impl MessageLaneTargetClient

, target_state_updates: impl FusedStream>, - stall_timeout: Duration, metrics_msg: Option, params: MessageDeliveryParams, ) -> Result<(), FailedClient> { @@ -60,7 +59,6 @@ pub async fn run( _phantom: Default::default(), }, target_state_updates, - stall_timeout, MessageDeliveryStrategy:: { lane_source_client: source_client, lane_target_client: target_client, @@ -174,6 +172,7 @@ where { type Error = C::Error; type TargetNoncesData = DeliveryRaceTargetNoncesData; + type TransactionTracker = C::TransactionTracker; async fn require_source_header(&self, id: SourceHeaderIdOf

) { self.client.require_source_header_on_target(id).await @@ -215,7 +214,7 @@ where generated_at_block: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> { self.client.submit_messages_proof(generated_at_block, nonces, proof).await } } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index a7254f70ee4a4..a68efbfd19383 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -20,7 +20,7 @@ //! associated data - like messages, lane state, etc) to the target node by //! generating and submitting proof. -use crate::message_lane_loop::ClientState; +use crate::message_lane_loop::{ClientState, NoncesSubmitArtifacts}; use async_trait::async_trait; use bp_messages::MessageNonce; @@ -28,7 +28,10 @@ use futures::{ future::FutureExt, stream::{FusedStream, StreamExt}, }; -use relay_utils::{process_future_result, retry_backoff, FailedClient, MaybeConnectionError}; +use relay_utils::{ + process_future_result, retry_backoff, FailedClient, MaybeConnectionError, + TrackedTransactionStatus, TransactionTracker, +}; use std::{ fmt::Debug, ops::RangeInclusive, @@ -124,6 +127,8 @@ pub trait TargetClient { type Error: std::fmt::Debug + MaybeConnectionError; /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; + /// Transaction tracker to track submitted transactions. + type TransactionTracker: TransactionTracker; /// Ask headers relay to relay finalized headers up to (and including) given header /// from race source to race target. @@ -141,7 +146,7 @@ pub trait TargetClient { generated_at_block: P::SourceHeaderId, nonces: RangeInclusive, proof: P::Proof, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; } /// Race strategy. @@ -222,7 +227,6 @@ pub async fn run, TC: TargetClient

>( race_source_updated: impl FusedStream>, race_target: TC, race_target_updated: impl FusedStream>, - stall_timeout: Duration, mut strategy: impl RaceStrategy< P::SourceHeaderId, P::TargetHeaderId, @@ -234,7 +238,6 @@ pub async fn run, TC: TargetClient

>( ) -> Result<(), FailedClient> { let mut progress_context = Instant::now(); let mut race_state = RaceState::default(); - let mut stall_countdown = Instant::now(); let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = true; @@ -250,6 +253,7 @@ pub async fn run, TC: TargetClient

>( let target_best_nonces = futures::future::Fuse::terminated(); let target_finalized_nonces = futures::future::Fuse::terminated(); let target_submit_proof = futures::future::Fuse::terminated(); + let target_tx_tracker = futures::future::Fuse::terminated(); let target_go_offline_future = futures::future::Fuse::terminated(); futures::pin_mut!( @@ -261,6 +265,7 @@ pub async fn run, TC: TargetClient

>( target_best_nonces, target_finalized_nonces, target_submit_proof, + target_tx_tracker, target_go_offline_future, ); @@ -343,11 +348,7 @@ pub async fn run, TC: TargetClient

>( nonces, ); - let prev_best_at_target = strategy.best_at_target(); strategy.best_target_nonces_updated(nonces, &mut race_state); - if strategy.best_at_target() != prev_best_at_target { - stall_countdown = Instant::now(); - } }, &mut target_go_offline_future, async_std::task::sleep, @@ -400,23 +401,37 @@ pub async fn run, TC: TargetClient

>( target_client_is_online = process_future_result( proof_submit_result, &mut target_retry_backoff, - |nonces_range| { + |artifacts: NoncesSubmitArtifacts| { log::debug!( target: "bridge", "Successfully submitted proof of nonces {:?} to {}", - nonces_range, + artifacts.nonces, P::target_name(), ); race_state.nonces_to_submit = None; - race_state.nonces_submitted = Some(nonces_range); - stall_countdown = Instant::now(); + race_state.nonces_submitted = Some(artifacts.nonces); + target_tx_tracker.set(artifacts.tx_tracker.wait().fuse()); }, &mut target_go_offline_future, async_std::task::sleep, || format!("Error submitting proof {}", P::target_name()), ).fail_if_connection_error(FailedClient::Target)?; }, + target_transaction_status = target_tx_tracker => { + if target_transaction_status == TrackedTransactionStatus::Lost { + log::warn!( + target: "bridge", + "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", + P::source_name(), + P::target_name(), + race_state, + strategy, + ); + + return Err(FailedClient::Both); + } + }, // when we're ready to retry request _ = source_go_offline_future => { @@ -429,24 +444,6 @@ pub async fn run, TC: TargetClient

>( progress_context = print_race_progress::(progress_context, &strategy); - if stall_countdown.elapsed() > stall_timeout { - log::warn!( - target: "bridge", - "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", - P::source_name(), - P::target_name(), - race_state, - strategy, - ); - - return Err(FailedClient::Both) - } else if race_state.nonces_to_submit.is_none() && - race_state.nonces_submitted.is_none() && - strategy.is_empty() - { - stall_countdown = Instant::now(); - } - if source_client_is_online { source_client_is_online = false; diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index 5aa36cbd9c6dc..c3d65d0e86a4d 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -16,7 +16,7 @@ use crate::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - SourceClient as MessageLaneSourceClient, SourceClientState, + NoncesSubmitArtifacts, SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }, message_race_loop::{ @@ -31,7 +31,7 @@ use async_trait::async_trait; use bp_messages::MessageNonce; use futures::stream::FusedStream; use relay_utils::FailedClient; -use std::{marker::PhantomData, ops::RangeInclusive, time::Duration}; +use std::{marker::PhantomData, ops::RangeInclusive}; /// Message receiving confirmations delivery strategy. type ReceivingConfirmationsBasicStrategy

= BasicStrategy< @@ -49,7 +49,6 @@ pub async fn run( source_state_updates: impl FusedStream>, target_client: impl MessageLaneTargetClient

, target_state_updates: impl FusedStream>, - stall_timeout: Duration, metrics_msg: Option, ) -> Result<(), FailedClient> { crate::message_race_loop::run( @@ -65,7 +64,6 @@ pub async fn run( _phantom: Default::default(), }, source_state_updates, - stall_timeout, ReceivingConfirmationsBasicStrategy::

::new(), ) .await @@ -157,6 +155,7 @@ where { type Error = C::Error; type TargetNoncesData = (); + type TransactionTracker = C::TransactionTracker; async fn require_source_header(&self, id: TargetHeaderIdOf

) { self.client.require_target_header_on_source(id).await @@ -182,9 +181,10 @@ where generated_at_block: TargetHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesReceivingProof, - ) -> Result, Self::Error> { - self.client.submit_messages_receiving_proof(generated_at_block, proof).await?; - Ok(nonces) + ) -> Result, Self::Error> { + let tx_tracker = + self.client.submit_messages_receiving_proof(generated_at_block, proof).await?; + Ok(NoncesSubmitArtifacts { nonces, tx_tracker }) } } From bf9cfecd55f4c981c2f464c92e8edb920abccc4c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 26 Sep 2022 15:30:38 +0300 Subject: [PATCH 0778/1210] fail if transaction submit has failed (#1584) --- relays/messages/src/message_race_loop.rs | 2 +- relays/utils/src/lib.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index a68efbfd19383..546e283ceab21 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -416,7 +416,7 @@ pub async fn run, TC: TargetClient

>( &mut target_go_offline_future, async_std::task::sleep, || format!("Error submitting proof {}", P::target_name()), - ).fail_if_connection_error(FailedClient::Target)?; + ).fail_if_error(FailedClient::Target).map(|_| true)?; }, target_transaction_status = target_tx_tracker => { if target_transaction_status == TrackedTransactionStatus::Lost { diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index dbc8e5df8218b..b19b9cd449883 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -236,6 +236,16 @@ impl ProcessFutureResult { } } + /// Returns `Ok(())` if future has succeeded. + /// Returns `Err(failed_client)` otherwise. + pub fn fail_if_error(self, failed_client: FailedClient) -> Result<(), FailedClient> { + if self.is_ok() { + Ok(()) + } else { + Err(failed_client) + } + } + /// Returns Ok(true) if future has succeeded. /// Returns Ok(false) if future has failed with non-connection error. /// Returns Err if future is `ConnectionFailed`. From 8fe6103be3b481b9ce81776e88b7f6a06b0656e1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 30 Sep 2022 15:42:55 +0300 Subject: [PATCH 0779/1210] remove unnecessary consts (#1586) --- primitives/chain-kusama/Cargo.toml | 10 --- primitives/chain-kusama/src/lib.rs | 61 +------------------ primitives/chain-polkadot/Cargo.toml | 10 --- primitives/chain-polkadot/src/lib.rs | 61 +------------------ primitives/chain-rococo/Cargo.toml | 12 ---- primitives/chain-rococo/src/lib.rs | 57 +---------------- primitives/chain-westend/Cargo.toml | 6 -- primitives/chain-westend/src/lib.rs | 35 ----------- primitives/chain-wococo/Cargo.toml | 8 --- primitives/chain-wococo/src/lib.rs | 14 +---- relays/bin-substrate/src/chains/millau.rs | 2 +- relays/bin-substrate/src/chains/rialto.rs | 2 +- .../src/chains/rialto_parachain.rs | 2 +- relays/bin-substrate/src/chains/westend.rs | 4 +- relays/bin-substrate/src/cli/chain_schema.rs | 2 +- relays/bin-substrate/src/cli/mod.rs | 4 +- relays/client-kusama/src/lib.rs | 1 - relays/client-millau/src/lib.rs | 2 +- relays/client-polkadot/src/lib.rs | 1 - relays/client-rialto-parachain/src/lib.rs | 2 +- relays/client-rialto/src/lib.rs | 2 +- relays/client-rococo/src/lib.rs | 1 - relays/client-substrate/src/chain.rs | 7 +-- relays/client-substrate/src/test_chain.rs | 3 +- relays/client-westend/src/lib.rs | 2 - relays/client-wococo/src/lib.rs | 1 - .../src/messages_target.rs | 10 +-- 27 files changed, 29 insertions(+), 293 deletions(-) diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index a676b565c33dc..ef902fef824cf 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -11,27 +11,17 @@ smallvec = "1.7" # Bridge Dependencies -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", - "frame-support/std", "sp-api/std", - "sp-runtime/std", - "sp-std/std", - "sp-version/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 0b218b22250fd..7837afe690e4a 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -18,58 +18,12 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; -use frame_support::weights::{ - WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; - pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_runtime_apis; +use bp_runtime::decl_bridge_finality_runtime_apis; /// Kusama Chain pub type Kusama = PolkadotLike; -// NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("kusama"), - impl_name: sp_version::create_runtime_str!("parity-kusama"), - authoring_version: 2, - spec_version: 9180, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 11, - state_version: 0, -}; - -// NOTE: This needs to be kept up to date with the Kusama runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 1_000_000_000_000 / 30_000; - // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -/// Per-byte fee for Kusama transactions. -pub const TRANSACTION_BYTE_FEE: Balance = 10 * 1_000_000_000_000 / 30_000 / 1_000; - -/// Existential deposit on Kusama. -pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 30_000; - /// The target length of a session (how often authorities change) on Kusama measured in of number of /// blocks. /// @@ -79,16 +33,5 @@ pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; /// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; -/// Name of the With-Kusama messages pallet instance that is deployed at bridged chains. -pub const WITH_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; - -/// Name of the transaction payment pallet at the Kusama runtime. -pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; - -/// Name of the DOT->KSM conversion rate stored in the Kusama runtime. -pub const POLKADOT_TO_KUSAMA_CONVERSION_RATE_PARAMETER_NAME: &str = - "PolkadotToKusamaConversionRate"; -/// Name of the Polkadot fee multiplier parameter, stored in the Polkadot runtime. -pub const POLKADOT_FEE_MULTIPLIER_PARAMETER_NAME: &str = "PolkadotFeeMultiplier"; -decl_bridge_runtime_apis!(kusama); +decl_bridge_finality_runtime_apis!(kusama); diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 738899b658cdf..8be9b25c77f5a 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -11,27 +11,17 @@ smallvec = "1.7" # Bridge Dependencies -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", - "frame-support/std", "sp-api/std", - "sp-runtime/std", - "sp-std/std", - "sp-version/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 6f584f5526a22..cfcbacb0d1a76 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -18,58 +18,12 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; -use frame_support::weights::{ - WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; - pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_runtime_apis; +use bp_runtime::decl_bridge_finality_runtime_apis; /// Polkadot Chain pub type Polkadot = PolkadotLike; -// NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("polkadot"), - impl_name: sp_version::create_runtime_str!("parity-polkadot"), - authoring_version: 0, - spec_version: 9180, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 12, - state_version: 0, -}; - -// NOTE: This needs to be kept up to date with the Polkadot runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 10_000_000_000 / 100; - // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -/// Per-byte fee for Polkadot transactions. -pub const TRANSACTION_BYTE_FEE: Balance = 10 * 10_000_000_000 / 100 / 1_000; - -/// Existential deposit on Polkadot. -pub const EXISTENTIAL_DEPOSIT: Balance = 10_000_000_000; - /// The target length of a session (how often authorities change) on Polkadot measured in of number /// of blocks. /// @@ -79,16 +33,5 @@ pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; /// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; -/// Name of the With-Polkadot messages pallet instance that is deployed at bridged chains. -pub const WITH_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; - -/// Name of the transaction payment pallet at the Polkadot runtime. -pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; - -/// Name of the KSM->DOT conversion rate parameter, stored in the Polkadot runtime. -pub const KUSAMA_TO_POLKADOT_CONVERSION_RATE_PARAMETER_NAME: &str = - "KusamaToPolkadotConversionRate"; -/// Name of the Kusama fee multiplier parameter, stored in the Polkadot runtime. -pub const KUSAMA_FEE_MULTIPLIER_PARAMETER_NAME: &str = "KusamaFeeMultiplier"; -decl_bridge_runtime_apis!(polkadot); +decl_bridge_finality_runtime_apis!(polkadot); diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index fe6b07eeb766d..730fad599bb10 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -7,31 +7,19 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } smallvec = "1.7" # Bridge Dependencies -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", - "frame-support/std", - "codec/std", "sp-api/std", - "sp-runtime/std", - "sp-std/std", - "sp-version/std", ] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index aa1d40ce92e25..39188066dca4b 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -18,18 +18,8 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; -use frame_support::weights::{ - Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; - pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_runtime_apis; +use bp_runtime::decl_bridge_finality_runtime_apis; /// Rococo Chain pub type Rococo = PolkadotLike; @@ -41,50 +31,7 @@ pub type Rococo = PolkadotLike; /// conditions. pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; -// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("rococo"), - impl_name: sp_version::create_runtime_str!("parity-rococo-v2.0"), - authoring_version: 0, - spec_version: 9200, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 0, - state_version: 0, -}; - -// NOTE: This needs to be kept up to date with the Rococo runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 1_000_000_000_000 / 100; - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - /// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; -/// Name of the With-Rococo messages pallet instance that is deployed at bridged chains. -pub const WITH_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; - -/// Existential deposit on Rococo. -pub const EXISTENTIAL_DEPOSIT: Balance = 1_000_000_000_000 / 100; - -/// Weight of pay-dispatch-fee operation for inbound messages at Rococo chain. -/// -/// This value corresponds to the result of -/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your -/// chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery -/// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; -decl_bridge_runtime_apis!(rococo); +decl_bridge_finality_runtime_apis!(rococo); diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index f37aa3b0e397e..ca5840b9dea5f 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -19,11 +19,8 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -31,11 +28,8 @@ std = [ "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", - "frame-support/std", "codec/std", "scale-info/std", "sp-api/std", "sp-runtime/std", - "sp-std/std", - "sp-version/std", ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 1e023295a8a0f..08803b7a3dd39 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -18,12 +18,7 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use frame_support::weights::{ - WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, -}; use scale_info::TypeInfo; -use sp_std::prelude::*; -use sp_version::RuntimeVersion; pub use bp_polkadot_core::*; use bp_runtime::decl_bridge_finality_runtime_apis; @@ -31,36 +26,6 @@ use bp_runtime::decl_bridge_finality_runtime_apis; /// Westend Chain pub type Westend = PolkadotLike; -// NOTE: This needs to be kept up to date with the Westend runtime found in the Polkadot repo. -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - const CENTS: Balance = 1_000_000_000_000 / 1_000; - // in Westend, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = CENTS; - let q = 10 * Balance::from(ExtrinsicBaseWeight::get()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -// NOTE: This needs to be kept up to date with the Westend runtime found in the Polkadot repo. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("westend"), - impl_name: sp_version::create_runtime_str!("parity-westend"), - authoring_version: 2, - spec_version: 9140, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 8, - state_version: 0, -}; - /// Westend Runtime `Call` enum. /// /// We are not currently submitting any Westend transactions => it is empty. diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 92e7c9e80e279..27297fe98543a 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -7,28 +7,20 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } # Bridge Dependencies -bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-rococo = { path = "../chain-rococo", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ - "bp-messages/std", "bp-polkadot-core/std", "bp-runtime/std", "bp-rococo/std", - "codec/std", "sp-api/std", - "sp-runtime/std", - "sp-std/std", ] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index c1626b0dc67d0..2a417479d3b2f 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -18,16 +18,8 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; -use sp_runtime::FixedU128; -use sp_std::prelude::*; - pub use bp_polkadot_core::*; -// Rococo runtime = Wococo runtime -pub use bp_rococo::{WeightToFee, EXISTENTIAL_DEPOSIT, PAY_INBOUND_DISPATCH_FEE_WEIGHT, VERSION}; -use bp_runtime::decl_bridge_runtime_apis; +use bp_runtime::decl_bridge_finality_runtime_apis; /// Wococo Chain pub type Wococo = PolkadotLike; @@ -41,7 +33,5 @@ pub const SESSION_LENGTH: BlockNumber = time_units::MINUTES; /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; -/// Name of the With-Wococo messages pallet instance that is deployed at bridged chains. -pub const WITH_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; -decl_bridge_runtime_apis!(wococo); +decl_bridge_finality_runtime_apis!(wococo); diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index b71ecb288e9d0..59d53edf997e0 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -90,7 +90,7 @@ impl CliEncodeMessage for Millau { } impl CliChain for Millau { - const RUNTIME_VERSION: RuntimeVersion = millau_runtime::VERSION; + const RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; type MessagePayload = Vec; diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 9dd86c9d95339..285476a331298 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -73,7 +73,7 @@ impl CliEncodeMessage for Rialto { } impl CliChain for Rialto { - const RUNTIME_VERSION: RuntimeVersion = rialto_runtime::VERSION; + const RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; type MessagePayload = Vec; diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 8cd7135c27a3c..c359c42087d46 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -74,7 +74,7 @@ impl CliEncodeMessage for RialtoParachain { } impl CliChain for RialtoParachain { - const RUNTIME_VERSION: RuntimeVersion = rialto_parachain_runtime::VERSION; + const RUNTIME_VERSION: Option = Some(rialto_parachain_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; type MessagePayload = Vec; diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index ae52944707487..8d43d6a5ab709 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -21,7 +21,7 @@ use relay_westend_client::{Westend, Westmint}; use sp_version::RuntimeVersion; impl CliChain for Westend { - const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; + const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; type MessagePayload = Vec; @@ -35,7 +35,7 @@ impl CliChain for Westend { } impl CliChain for Westmint { - const RUNTIME_VERSION: RuntimeVersion = bp_westend::VERSION; + const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; type MessagePayload = Vec; diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 0f108aed6de52..8023fd9b0f7f6 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -115,7 +115,7 @@ macro_rules! declare_chain_connection_params_cli_schema { ) -> anyhow::Result> { let chain_runtime_version = self .[<$chain_prefix _runtime_version>] - .into_runtime_version(Some(Chain::RUNTIME_VERSION))?; + .into_runtime_version(Chain::RUNTIME_VERSION)?; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { host: self.[<$chain_prefix _host>], port: self.[<$chain_prefix _port>], diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 44bfce9f384ec..42a073bd4f65a 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -163,7 +163,9 @@ impl Balance { /// Used to abstract away CLI commands. pub trait CliChain: relay_substrate_client::Chain { /// Current version of the chain runtime, known to relay. - const RUNTIME_VERSION: sp_version::RuntimeVersion; + /// + /// can be `None` if relay is not going to submit transactions to that chain. + const RUNTIME_VERSION: Option; /// Crypto KeyPair type used to send messages. /// diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index b076da7ab750b..cdf7213df9bbb 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -58,7 +58,6 @@ impl Chain for Kusama { type SignedBlock = bp_kusama::SignedBlock; type Call = (); - type WeightToFee = bp_kusama::WeightToFee; } impl ChainWithGrandpa for Kusama { diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 7bab3669c4d02..3c861214df4cf 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -71,6 +71,7 @@ impl ChainWithMessages for Millau { bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightToFee = bp_millau::WeightToFee; type WeightInfo = (); } @@ -85,7 +86,6 @@ impl Chain for Millau { type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::Call; - type WeightToFee = bp_millau::WeightToFee; } impl ChainWithBalances for Millau { diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 9327c76c4ef39..bb3867fda5318 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -58,7 +58,6 @@ impl Chain for Polkadot { type SignedBlock = bp_polkadot::SignedBlock; type Call = (); - type WeightToFee = bp_polkadot::WeightToFee; } impl ChainWithGrandpa for Polkadot { diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index c678a21420fd4..489baa4be5aad 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -66,7 +66,6 @@ impl Chain for RialtoParachain { type SignedBlock = rialto_parachain_runtime::SignedBlock; type Call = rialto_parachain_runtime::Call; - type WeightToFee = bp_rialto_parachain::WeightToFee; } impl ChainWithBalances for RialtoParachain { @@ -93,6 +92,7 @@ impl ChainWithMessages for RialtoParachain { bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightToFee = bp_rialto_parachain::WeightToFee; type WeightInfo = (); } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index b2984336cd265..816a21baf0c5e 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -66,7 +66,6 @@ impl Chain for Rialto { type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::Call; - type WeightToFee = bp_rialto::WeightToFee; } impl RelayChain for Rialto { @@ -92,6 +91,7 @@ impl ChainWithMessages for Rialto { bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + type WeightToFee = bp_rialto::WeightToFee; type WeightInfo = (); } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index c33af96aedf65..f4905d52dc7ee 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -61,7 +61,6 @@ impl Chain for Rococo { type SignedBlock = bp_rococo::SignedBlock; type Call = (); - type WeightToFee = bp_rococo::WeightToFee; } impl ChainWithGrandpa for Rococo { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 9562d68d4611b..3f483078cac79 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -59,9 +59,6 @@ pub trait Chain: ChainBase + Clone { type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. type Call: Clone + Codec + Dispatchable + Debug + Send; - - /// Type that is used by the chain, to convert from weight to fee. - type WeightToFee: WeightToFee; } /// Substrate-based relay chain that supports parachains. @@ -120,6 +117,8 @@ pub trait ChainWithMessages: Chain { /// `ChainWithMessages`. const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; + /// Type that is used by the chain, to convert from weight to fee. + type WeightToFee: WeightToFee; /// Weights of message pallet calls. type WeightInfo: pallet_bridge_messages::WeightInfoExt; } @@ -127,7 +126,7 @@ pub trait ChainWithMessages: Chain { /// Call type used by the chain. pub type CallOf = ::Call; /// Weight-to-Fee type used by the chain. -pub type WeightToFeeOf = ::WeightToFee; +pub type WeightToFeeOf = ::WeightToFee; /// Transaction status of the chain. pub type TransactionStatusOf = TransactionStatus, HashOf>; diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index f9a9e2455ed99..8e1832db08453 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -22,7 +22,7 @@ #![cfg(any(feature = "test-helpers", test))] use crate::{Chain, ChainWithBalances}; -use frame_support::weights::{IdentityFee, Weight}; +use frame_support::weights::Weight; use std::time::Duration; /// Chain that may be used in tests. @@ -60,7 +60,6 @@ impl Chain for TestChain { sp_runtime::generic::Block, >; type Call = (); - type WeightToFee = IdentityFee; } impl ChainWithBalances for TestChain { diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 4b27bfeb82d8a..f6a4220c618a4 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -61,7 +61,6 @@ impl Chain for Westend { type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; - type WeightToFee = bp_westend::WeightToFee; } impl RelayChain for Westend { @@ -119,5 +118,4 @@ impl Chain for Westmint { type SignedBlock = bp_westend::SignedBlock; type Call = bp_westend::Call; - type WeightToFee = bp_westend::WeightToFee; } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 06a63e7d2b46c..87da6fb83679e 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -61,7 +61,6 @@ impl Chain for Wococo { type SignedBlock = bp_wococo::SignedBlock; type Call = (); - type WeightToFee = bp_wococo::WeightToFee; } impl ChainWithGrandpa for Wococo { diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 4e5ba6ae087bc..21a43112f81ca 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -497,7 +497,7 @@ where /// **WARNING**: this functions will only be accurate if weight-to-fee conversion function /// is linear. For non-linear polynomials the error will grow with `weight_difference` growth. /// So better to use smaller differences. -fn compute_fee_multiplier( +fn compute_fee_multiplier( smaller_adjusted_weight_fee: BalanceOf, smaller_tx_weight: Weight, larger_adjusted_weight_fee: BalanceOf, @@ -563,17 +563,17 @@ mod tests { #[test] fn compute_fee_multiplier_returns_sane_results() { - let multiplier: FixedU128 = bp_rococo::WeightToFee::weight_to_fee(&1).into(); + let multiplier: FixedU128 = bp_rialto::WeightToFee::weight_to_fee(&1).into(); let smaller_weight = 1_000_000; let smaller_adjusted_weight_fee = - multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&smaller_weight)); + multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&smaller_weight)); let larger_weight = smaller_weight + 200_000; let larger_adjusted_weight_fee = - multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&larger_weight)); + multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&larger_weight)); assert_eq!( - compute_fee_multiplier::( + compute_fee_multiplier::( smaller_adjusted_weight_fee, smaller_weight, larger_adjusted_weight_fee, From 1d74d63d71c08d6b64fe6dc70d516990306301c5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 30 Sep 2022 15:43:06 +0300 Subject: [PATCH 0780/1210] restart relay loop when proof genration fails (#1585) --- relays/messages/src/message_race_loop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 546e283ceab21..86306b1c424da 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -395,7 +395,7 @@ pub async fn run, TC: TargetClient

>( &mut source_go_offline_future, async_std::task::sleep, || format!("Error generating proof at {}", P::source_name()), - ).fail_if_connection_error(FailedClient::Source)?; + ).fail_if_error(FailedClient::Source).map(|_| true)?; }, proof_submit_result = target_submit_proof => { target_client_is_online = process_future_result( From 9d3b81f90b2e15e4f104644e3bb3d3bdb4c176a8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 3 Oct 2022 09:25:48 +0300 Subject: [PATCH 0781/1210] Read extrinsic dispatch result for mined transaction (#1582) * read extrinsic dispatch result for mined transaction * commit for the history * Revert "commit for the history" This reverts commit 99341b04750639db296172cc1432bd70e458ef4b. * Revert "read extrinsic dispatch result for mined transaction" This reverts commit 662b776cbf992be9f1637e52f023b782e8c441d1. * check for successfult transaction in finality relay * check for successful transaction in parachains relay * TrackedTransactionStatus ->TrackedTransactionStatus * check for successful transaction in messages relay * fix compilation * message_lane_loop_is_able_to_recover_from_unsuccessful_transaction * fixed too-complex-type clippy error * aaand compilation --- relays/client-substrate/src/client.rs | 4 +- .../src/transaction_tracker.rs | 124 ++++++++++++--- relays/finality/src/finality_loop.rs | 58 +++++-- relays/finality/src/finality_loop_tests.rs | 22 ++- .../src/finality/target.rs | 2 +- .../src/messages_source.rs | 2 +- .../src/messages_target.rs | 2 +- .../src/parachains/target.rs | 2 +- relays/messages/src/message_lane_loop.rs | 145 +++++++++++++++-- relays/messages/src/message_race_loop.rs | 56 +++++-- relays/parachains/src/parachains_loop.rs | 148 ++++++++++++------ relays/utils/src/lib.rs | 11 +- 12 files changed, 462 insertions(+), 114 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index ed327e167b064..067d3d89d2450 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -467,7 +467,8 @@ impl Client { prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, - ) -> Result> { + ) -> Result> { + let self_clone = self.clone(); let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; let best_header = self.best_header().await?; @@ -494,6 +495,7 @@ impl Client { })?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); let tracker = TransactionTracker::new( + self_clone, stall_timeout, tx_hash, Subscription(Mutex::new(receiver)), diff --git a/relays/client-substrate/src/transaction_tracker.rs b/relays/client-substrate/src/transaction_tracker.rs index a84a46240a4ab..44d8b72cb8d4f 100644 --- a/relays/client-substrate/src/transaction_tracker.rs +++ b/relays/client-substrate/src/transaction_tracker.rs @@ -16,13 +16,28 @@ //! Helper for tracking transaction invalidation events. -use crate::{Chain, HashOf, Subscription, TransactionStatusOf}; +use crate::{Chain, Client, Error, HashOf, HeaderIdOf, Subscription, TransactionStatusOf}; use async_trait::async_trait; use futures::{future::Either, Future, FutureExt, Stream, StreamExt}; -use relay_utils::TrackedTransactionStatus; +use relay_utils::{HeaderId, TrackedTransactionStatus}; +use sp_runtime::traits::Header as _; use std::time::Duration; +/// Transaction tracker environment. +#[async_trait] +pub trait Environment: Send + Sync { + /// Returns header id by its hash. + async fn header_id_by_hash(&self, hash: HashOf) -> Result, Error>; +} + +#[async_trait] +impl Environment for Client { + async fn header_id_by_hash(&self, hash: HashOf) -> Result, Error> { + self.header_by_hash(hash).await.map(|h| HeaderId(*h.number(), hash)) + } +} + /// Substrate transaction tracker implementation. /// /// Substrate node provides RPC API to submit and watch for transaction events. This way @@ -43,20 +58,22 @@ use std::time::Duration; /// it is lost. /// /// This struct implements third option as it seems to be the most optimal. -pub struct TransactionTracker { +pub struct TransactionTracker { + environment: E, transaction_hash: HashOf, stall_timeout: Duration, subscription: Subscription>, } -impl TransactionTracker { +impl> TransactionTracker { /// Create transaction tracker. pub fn new( + environment: E, stall_timeout: Duration, transaction_hash: HashOf, subscription: Subscription>, ) -> Self { - Self { stall_timeout, transaction_hash, subscription } + Self { environment, stall_timeout, transaction_hash, subscription } } /// Wait for final transaction status and return it along with last known internal invalidation @@ -65,10 +82,11 @@ impl TransactionTracker { self, wait_for_stall_timeout: impl Future, wait_for_stall_timeout_rest: impl Future, - ) -> (TrackedTransactionStatus, Option) { + ) -> (TrackedTransactionStatus>, Option>>) { // sometimes we want to wait for the rest of the stall timeout even if // `wait_for_invalidation` has been "select"ed first => it is shared - let wait_for_invalidation = watch_transaction_status::( + let wait_for_invalidation = watch_transaction_status::<_, C, _>( + self.environment, self.transaction_hash, self.subscription.into_stream(), ); @@ -86,8 +104,8 @@ impl TransactionTracker { (TrackedTransactionStatus::Lost, None) }, Either::Right((invalidation_status, _)) => match invalidation_status { - InvalidationStatus::Finalized => - (TrackedTransactionStatus::Finalized, Some(invalidation_status)), + InvalidationStatus::Finalized(at_block) => + (TrackedTransactionStatus::Finalized(at_block), Some(invalidation_status)), InvalidationStatus::Invalid => (TrackedTransactionStatus::Lost, Some(invalidation_status)), InvalidationStatus::Lost => { @@ -111,8 +129,10 @@ impl TransactionTracker { } #[async_trait] -impl relay_utils::TransactionTracker for TransactionTracker { - async fn wait(self) -> TrackedTransactionStatus { +impl> relay_utils::TransactionTracker for TransactionTracker { + type HeaderId = HeaderIdOf; + + async fn wait(self) -> TrackedTransactionStatus> { let wait_for_stall_timeout = async_std::task::sleep(self.stall_timeout).shared(); let wait_for_stall_timeout_rest = wait_for_stall_timeout.clone(); self.do_wait(wait_for_stall_timeout, wait_for_stall_timeout_rest).await.0 @@ -125,9 +145,9 @@ impl relay_utils::TransactionTracker for TransactionTracker { /// ignored - relay loops are detecting the mining/finalization using their own /// techniques. That's why we're using `InvalidationStatus` here. #[derive(Debug, PartialEq)] -enum InvalidationStatus { - /// Transaction has been included into block and finalized. - Finalized, +enum InvalidationStatus { + /// Transaction has been included into block and finalized at given block. + Finalized(BlockId), /// Transaction has been invalidated. Invalid, /// We have lost track of transaction status. @@ -135,10 +155,15 @@ enum InvalidationStatus { } /// Watch for transaction status until transaction is finalized or we lose track of its status. -async fn watch_transaction_status>>( +async fn watch_transaction_status< + E: Environment, + C: Chain, + S: Stream>, +>( + environment: E, transaction_hash: HashOf, subscription: S, -) -> InvalidationStatus { +) -> InvalidationStatus> { futures::pin_mut!(subscription); loop { @@ -153,7 +178,23 @@ async fn watch_transaction_status header_id, + Err(e) => { + log::error!( + target: "bridge", + "Failed to read header {:?} when watching for {} transaction {:?}: {:?}", + block_hash, + C::NAME, + transaction_hash, + e, + ); + // that's the best option we have here + return InvalidationStatus::Lost + }, + }; + return InvalidationStatus::Finalized(header_id) }, Some(TransactionStatusOf::::Invalid) => { // if node says that the transaction is invalid, there are still chances that @@ -247,11 +288,27 @@ mod tests { use futures::{FutureExt, SinkExt}; use sc_transaction_pool_api::TransactionStatus; + struct TestEnvironment(Result, Error>); + + #[async_trait] + impl Environment for TestEnvironment { + async fn header_id_by_hash( + &self, + _hash: HashOf, + ) -> Result, Error> { + self.0.as_ref().map_err(|_| Error::UninitializedBridgePallet).cloned() + } + } + async fn on_transaction_status( status: TransactionStatus, HashOf>, - ) -> Option<(TrackedTransactionStatus, InvalidationStatus)> { + ) -> Option<( + TrackedTransactionStatus>, + InvalidationStatus>, + )> { let (mut sender, receiver) = futures::channel::mpsc::channel(1); - let tx_tracker = TransactionTracker::::new( + let tx_tracker = TransactionTracker::::new( + TestEnvironment(Ok(HeaderId(0, Default::default()))), Duration::from_secs(0), Default::default(), Subscription(async_std::sync::Mutex::new(receiver)), @@ -270,7 +327,23 @@ mod tests { async fn returns_finalized_on_finalized() { assert_eq!( on_transaction_status(TransactionStatus::Finalized(Default::default())).await, - Some((TrackedTransactionStatus::Finalized, InvalidationStatus::Finalized)), + Some(( + TrackedTransactionStatus::Finalized(Default::default()), + InvalidationStatus::Finalized(Default::default()) + )), + ); + } + + #[async_std::test] + async fn returns_lost_on_finalized_and_environment_error() { + assert_eq!( + watch_transaction_status::<_, TestChain, _>( + TestEnvironment(Err(Error::UninitializedBridgePallet)), + Default::default(), + futures::stream::iter([TransactionStatus::Finalized(Default::default())]) + ) + .now_or_never(), + Some(InvalidationStatus::Lost), ); } @@ -343,8 +416,12 @@ mod tests { #[async_std::test] async fn lost_on_subscription_error() { assert_eq!( - watch_transaction_status::(Default::default(), futures::stream::iter([])) - .now_or_never(), + watch_transaction_status::<_, TestChain, _>( + TestEnvironment(Ok(HeaderId(0, Default::default()))), + Default::default(), + futures::stream::iter([]) + ) + .now_or_never(), Some(InvalidationStatus::Lost), ); } @@ -352,7 +429,8 @@ mod tests { #[async_std::test] async fn lost_on_timeout_when_waiting_for_invalidation_status() { let (_sender, receiver) = futures::channel::mpsc::channel(1); - let tx_tracker = TransactionTracker::::new( + let tx_tracker = TransactionTracker::::new( + TestEnvironment(Ok(HeaderId(0, Default::default()))), Duration::from_secs(0), Default::default(), Subscription(async_std::sync::Mutex::new(receiver)), diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 951edfdde9485..a890686047098 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -290,15 +290,55 @@ pub(crate) async fn run_until_connection_lost( // wait till exit signal, or new source block select! { transaction_status = last_transaction_tracker => { - if transaction_status == TrackedTransactionStatus::Lost { - log::error!( - target: "bridge", - "Finality synchronization from {} to {} has stalled. Going to restart", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - - return Err(FailedClient::Both); + match transaction_status { + TrackedTransactionStatus::Finalized(_) => { + // transaction has been finalized, but it may have been finalized in the "failed" state. So + // let's check if the block number has been actually updated. If it is not, then we are stalled. + // + // please also note that we're restarting the loop if we have failed to read required data + // from the target client - that's the best we can do here to avoid actual stall. + target_client + .best_finalized_source_block_id() + .await + .map_err(|e| format!("failed to read best block from target node: {:?}", e)) + .and_then(|best_id_at_target| { + let last_submitted_header_number = last_submitted_header_number + .expect("always Some when last_transaction_tracker is set;\ + last_transaction_tracker is set;\ + qed"); + if last_submitted_header_number > best_id_at_target.0 { + Err(format!( + "best block at target after tx is {:?} and we've submitted {:?}", + best_id_at_target, + last_submitted_header_number, + )) + } else { + Ok(()) + } + }) + .map_err(|e| { + log::error!( + target: "bridge", + "Failed Finality synchronization from {} to {} has stalled. Transaction failed: {}. \ + Going to restart", + P::SOURCE_NAME, + P::TARGET_NAME, + e, + ); + + FailedClient::Both + })?; + }, + TrackedTransactionStatus::Lost => { + log::error!( + target: "bridge", + "Finality synchronization from {} to {} has stalled. Going to restart", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + + return Err(FailedClient::Both); + }, } }, _ = async_std::task::sleep(next_tick).fuse() => {}, diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 7144ccb0c4810..c8d5cefc22772 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -48,17 +48,19 @@ type TestNumber = u64; type TestHash = u64; #[derive(Clone, Debug)] -struct TestTransactionTracker(TrackedTransactionStatus); +struct TestTransactionTracker(TrackedTransactionStatus>); impl Default for TestTransactionTracker { fn default() -> TestTransactionTracker { - TestTransactionTracker(TrackedTransactionStatus::Finalized) + TestTransactionTracker(TrackedTransactionStatus::Finalized(Default::default())) } } #[async_trait] impl TransactionTracker for TestTransactionTracker { - async fn wait(self) -> TrackedTransactionStatus { + type HeaderId = HeaderId; + + async fn wait(self) -> TrackedTransactionStatus> { self.0 } } @@ -224,7 +226,9 @@ fn prepare_test_clients( target_best_block_id: HeaderId(5, 5), target_headers: vec![], - target_transaction_tracker: TestTransactionTracker(TrackedTransactionStatus::Finalized), + target_transaction_tracker: TestTransactionTracker(TrackedTransactionStatus::Finalized( + Default::default(), + )), })); ( TestSourceClient { @@ -581,3 +585,13 @@ fn stalls_when_transaction_tracker_returns_error() { assert_eq!(result, Err(FailedClient::Both)); } + +#[test] +fn stalls_when_transaction_tracker_returns_finalized_but_transaction_fails() { + let (_, result) = run_sync_loop(|data| { + data.target_best_block_id = HeaderId(5, 5); + data.target_best_block_id.0 == 16 + }); + + assert_eq!(result, Err(FailedClient::Both)); +} diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 7bdb77d4ee05e..132c332534382 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -89,7 +89,7 @@ where AccountIdOf: From< as Pair>::Public>, P::TransactionSignScheme: TransactionSignScheme, { - type TransactionTracker = TransactionTracker; + type TransactionTracker = TransactionTracker>; async fn best_finalized_source_block_id(&self) -> Result, Error> { // we can't continue to relay finality if target node is out of sync, because diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index ca0c3f54bb562..e34f477e5f0c2 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -144,7 +144,7 @@ where From< as Pair>::Public>, P::SourceTransactionSignScheme: TransactionSignScheme, { - type TransactionTracker = TransactionTracker; + type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 21a43112f81ca..da41dba63a538 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -145,7 +145,7 @@ where P::TargetTransactionSignScheme: TransactionSignScheme, BalanceOf: TryFrom>, { - type TransactionTracker = TransactionTracker; + type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { // we can't continue to deliver confirmations if source node is out of sync, because diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 34a6a31311dd2..8d0d361984f3e 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -86,7 +86,7 @@ where P::TransactionSignScheme: TransactionSignScheme, AccountIdOf: From< as Pair>::Public>, { - type TransactionTracker = TransactionTracker; + type TransactionTracker = TransactionTracker>; async fn best_block(&self) -> Result, Self::Error> { let best_header = self.client.best_header().await?; diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 6e3b02f1cffc8..05c157ee7210a 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -129,7 +129,7 @@ pub struct NoncesSubmitArtifacts { #[async_trait] pub trait SourceClient: RelayClient { /// Transaction tracker to track submitted transactions. - type TransactionTracker: TransactionTracker; + type TransactionTracker: TransactionTracker>; /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -182,7 +182,7 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Transaction tracker to track submitted transactions. - type TransactionTracker: TransactionTracker; + type TransactionTracker: TransactionTracker>; /// Returns state of the client. async fn state(&self) -> Result, Self::Error>; @@ -529,17 +529,19 @@ pub(crate) mod tests { } #[derive(Clone, Debug)] - pub struct TestTransactionTracker(TrackedTransactionStatus); + pub struct TestTransactionTracker(TrackedTransactionStatus); impl Default for TestTransactionTracker { fn default() -> TestTransactionTracker { - TestTransactionTracker(TrackedTransactionStatus::Finalized) + TestTransactionTracker(TrackedTransactionStatus::Finalized(Default::default())) } } #[async_trait] impl TransactionTracker for TestTransactionTracker { - async fn wait(self) -> TrackedTransactionStatus { + type HeaderId = TestTargetHeaderId; + + async fn wait(self) -> TrackedTransactionStatus { self.0 } } @@ -551,14 +553,14 @@ pub(crate) mod tests { source_state: SourceClientState, source_latest_generated_nonce: MessageNonce, source_latest_confirmed_received_nonce: MessageNonce, - source_tracked_transaction_status: TrackedTransactionStatus, + source_tracked_transaction_status: TrackedTransactionStatus, submitted_messages_receiving_proofs: Vec, is_target_fails: bool, is_target_reconnected: bool, target_state: SourceClientState, target_latest_received_nonce: MessageNonce, target_latest_confirmed_received_nonce: MessageNonce, - target_tracked_transaction_status: TrackedTransactionStatus, + target_tracked_transaction_status: TrackedTransactionStatus, submitted_messages_proofs: Vec, target_to_source_header_required: Option, target_to_source_header_requirements: Vec, @@ -574,14 +576,20 @@ pub(crate) mod tests { source_state: Default::default(), source_latest_generated_nonce: 0, source_latest_confirmed_received_nonce: 0, - source_tracked_transaction_status: TrackedTransactionStatus::Finalized, + source_tracked_transaction_status: TrackedTransactionStatus::Finalized(HeaderId( + 0, + Default::default(), + )), submitted_messages_receiving_proofs: Vec::new(), is_target_fails: false, is_target_reconnected: false, target_state: Default::default(), target_latest_received_nonce: 0, target_latest_confirmed_received_nonce: 0, - target_tracked_transaction_status: TrackedTransactionStatus::Finalized, + target_tracked_transaction_status: TrackedTransactionStatus::Finalized(HeaderId( + 0, + Default::default(), + )), submitted_messages_proofs: Vec::new(), target_to_source_header_required: None, target_to_source_header_requirements: Vec::new(), @@ -595,6 +603,7 @@ pub(crate) mod tests { pub struct TestSourceClient { data: Arc>, tick: Arc, + post_tick: Arc, } impl Default for TestSourceClient { @@ -602,6 +611,7 @@ pub(crate) mod tests { TestSourceClient { data: Arc::new(Mutex::new(TestClientData::default())), tick: Arc::new(|_| {}), + post_tick: Arc::new(|_| {}), } } } @@ -615,6 +625,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut data); data.is_source_reconnected = true; + (self.post_tick)(&mut data); } Ok(()) } @@ -630,6 +641,7 @@ pub(crate) mod tests { if data.is_source_fails { return Err(TestError) } + (self.post_tick)(&mut data); Ok(data.source_state.clone()) } @@ -642,6 +654,7 @@ pub(crate) mod tests { if data.is_source_fails { return Err(TestError) } + (self.post_tick)(&mut data); Ok((id, data.source_latest_generated_nonce)) } @@ -651,6 +664,7 @@ pub(crate) mod tests { ) -> Result<(SourceHeaderIdOf, MessageNonce), TestError> { let mut data = self.data.lock(); (self.tick)(&mut data); + (self.post_tick)(&mut data); Ok((id, data.source_latest_confirmed_received_nonce)) } @@ -685,6 +699,7 @@ pub(crate) mod tests { > { let mut data = self.data.lock(); (self.tick)(&mut data); + (self.post_tick)(&mut data); Ok(( id, nonces.clone(), @@ -711,6 +726,7 @@ pub(crate) mod tests { data.source_state.best_finalized_self = data.source_state.best_self; data.submitted_messages_receiving_proofs.push(proof); data.source_latest_confirmed_received_nonce = proof; + (self.post_tick)(&mut data); Ok(TestTransactionTracker(data.source_tracked_transaction_status)) } @@ -719,6 +735,7 @@ pub(crate) mod tests { data.target_to_source_header_required = Some(id); data.target_to_source_header_requirements.push(id); (self.tick)(&mut data); + (self.post_tick)(&mut data); } async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance { @@ -730,6 +747,7 @@ pub(crate) mod tests { pub struct TestTargetClient { data: Arc>, tick: Arc, + post_tick: Arc, } impl Default for TestTargetClient { @@ -737,6 +755,7 @@ pub(crate) mod tests { TestTargetClient { data: Arc::new(Mutex::new(TestClientData::default())), tick: Arc::new(|_| {}), + post_tick: Arc::new(|_| {}), } } } @@ -750,6 +769,7 @@ pub(crate) mod tests { let mut data = self.data.lock(); (self.tick)(&mut data); data.is_target_reconnected = true; + (self.post_tick)(&mut data); } Ok(()) } @@ -765,6 +785,7 @@ pub(crate) mod tests { if data.is_target_fails { return Err(TestError) } + (self.post_tick)(&mut data); Ok(data.target_state.clone()) } @@ -777,6 +798,7 @@ pub(crate) mod tests { if data.is_target_fails { return Err(TestError) } + (self.post_tick)(&mut data); Ok((id, data.target_latest_received_nonce)) } @@ -804,6 +826,7 @@ pub(crate) mod tests { if data.is_target_fails { return Err(TestError) } + (self.post_tick)(&mut data); Ok((id, data.target_latest_confirmed_received_nonce)) } @@ -834,6 +857,7 @@ pub(crate) mod tests { target_latest_confirmed_received_nonce; } data.submitted_messages_proofs.push(proof); + (self.post_tick)(&mut data); Ok(NoncesSubmitArtifacts { nonces, tx_tracker: TestTransactionTracker(data.target_tracked_transaction_status), @@ -845,6 +869,7 @@ pub(crate) mod tests { data.source_to_target_header_required = Some(id); data.source_to_target_header_requirements.push(id); (self.tick)(&mut data); + (self.post_tick)(&mut data); } async fn estimate_delivery_transaction_in_source_tokens( @@ -863,14 +888,24 @@ pub(crate) mod tests { fn run_loop_test( data: TestClientData, source_tick: Arc, + source_post_tick: Arc, target_tick: Arc, + target_post_tick: Arc, exit_signal: impl Future + 'static + Send, ) -> TestClientData { async_std::task::block_on(async { let data = Arc::new(Mutex::new(data)); - let source_client = TestSourceClient { data: data.clone(), tick: source_tick }; - let target_client = TestTargetClient { data: data.clone(), tick: target_tick }; + let source_client = TestSourceClient { + data: data.clone(), + tick: source_tick, + post_tick: source_post_tick, + }; + let target_client = TestTargetClient { + data: data.clone(), + tick: target_tick, + post_tick: target_post_tick, + }; let _ = run( Params { lane: [0, 0, 0, 0], @@ -928,6 +963,7 @@ pub(crate) mod tests { data.is_target_fails = true; } }), + Arc::new(|_| {}), Arc::new(move |data: &mut TestClientData| { if data.is_target_reconnected { data.is_target_fails = false; @@ -942,6 +978,7 @@ pub(crate) mod tests { exit_sender.unbounded_send(()).unwrap(); } }), + Arc::new(|_| {}), exit_receiver.into_future().map(|(_, _)| ()), ); @@ -976,24 +1013,104 @@ pub(crate) mod tests { }, Arc::new(move |data: &mut TestClientData| { if data.is_source_reconnected { - data.source_tracked_transaction_status = TrackedTransactionStatus::Finalized; + data.source_tracked_transaction_status = + TrackedTransactionStatus::Finalized(Default::default()); } if data.is_source_reconnected && data.is_target_reconnected { source_exit_sender.unbounded_send(()).unwrap(); } }), + Arc::new(|_| {}), Arc::new(move |data: &mut TestClientData| { if data.is_target_reconnected { - data.target_tracked_transaction_status = TrackedTransactionStatus::Finalized; + data.target_tracked_transaction_status = + TrackedTransactionStatus::Finalized(Default::default()); } if data.is_source_reconnected && data.is_target_reconnected { target_exit_sender.unbounded_send(()).unwrap(); } }), + Arc::new(|_| {}), + exit_receiver.into_future().map(|(_, _)| ()), + ); + + assert!(result.is_source_reconnected); + } + + #[test] + fn message_lane_loop_is_able_to_recover_from_unsuccessful_transaction() { + // with this configuration, both source and target clients will mine their transactions, but + // their corresponding nonce won't be udpated => reconnect will happen + let (exit_sender, exit_receiver) = unbounded(); + let result = run_loop_test( + TestClientData { + source_state: ClientState { + best_self: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + }, + source_latest_generated_nonce: 1, + target_state: ClientState { + best_self: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + }, + target_latest_received_nonce: 0, + ..Default::default() + }, + Arc::new(move |data: &mut TestClientData| { + // blocks are produced on every tick + data.source_state.best_self = + HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); + data.source_state.best_finalized_self = data.source_state.best_self; + // syncing target headers -> source chain + if let Some(last_requirement) = data.target_to_source_header_requirements.last() { + if *last_requirement != data.source_state.best_finalized_peer_at_best_self { + data.source_state.best_finalized_peer_at_best_self = *last_requirement; + } + } + }), + Arc::new(move |data: &mut TestClientData| { + // if it is the first time we're submitting delivery proof, let's revert changes + // to source status => then the delivery confirmation transaction is "finalized", + // but the state is not altered + if data.submitted_messages_receiving_proofs.len() == 1 { + data.source_latest_confirmed_received_nonce = 0; + } + }), + Arc::new(move |data: &mut TestClientData| { + // blocks are produced on every tick + data.target_state.best_self = + HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); + data.target_state.best_finalized_self = data.target_state.best_self; + // syncing source headers -> target chain + if let Some(last_requirement) = data.source_to_target_header_requirements.last() { + if *last_requirement != data.target_state.best_finalized_peer_at_best_self { + data.target_state.best_finalized_peer_at_best_self = *last_requirement; + } + } + // if source has received all messages receiving confirmations => stop + if data.source_latest_confirmed_received_nonce == 1 { + exit_sender.unbounded_send(()).unwrap(); + } + }), + Arc::new(move |data: &mut TestClientData| { + // if it is the first time we're submitting messages proof, let's revert changes + // to target status => then the messages delivery transaction is "finalized", but + // the state is not altered + if data.submitted_messages_proofs.len() == 1 { + data.target_latest_received_nonce = 0; + data.target_latest_confirmed_received_nonce = 0; + } + }), exit_receiver.into_future().map(|(_, _)| ()), ); assert!(result.is_source_reconnected); + assert_eq!(result.submitted_messages_proofs.len(), 2); + assert_eq!(result.submitted_messages_receiving_proofs.len(), 2); } #[test] @@ -1037,6 +1154,7 @@ pub(crate) mod tests { } } }), + Arc::new(|_| {}), Arc::new(move |data: &mut TestClientData| { // blocks are produced on every tick data.target_state.best_self = @@ -1061,6 +1179,7 @@ pub(crate) mod tests { exit_sender.unbounded_send(()).unwrap(); } }), + Arc::new(|_| {}), exit_receiver.into_future().map(|(_, _)| ()), ); diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 86306b1c424da..15308f93032b4 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -128,7 +128,7 @@ pub trait TargetClient { /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; /// Transaction tracker to track submitted transactions. - type TransactionTracker: TransactionTracker; + type TransactionTracker: TransactionTracker; /// Ask headers relay to relay finalized headers up to (and including) given header /// from race source to race target. @@ -419,17 +419,49 @@ pub async fn run, TC: TargetClient

>( ).fail_if_error(FailedClient::Target).map(|_| true)?; }, target_transaction_status = target_tx_tracker => { - if target_transaction_status == TrackedTransactionStatus::Lost { - log::warn!( - target: "bridge", - "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", - P::source_name(), - P::target_name(), - race_state, - strategy, - ); - - return Err(FailedClient::Both); + match (target_transaction_status, race_state.nonces_submitted.as_ref()) { + (TrackedTransactionStatus::Finalized(at_block), Some(nonces_submitted)) => { + // our transaction has been mined, but was it successful or not? let's check the best + // nonce at the target node. + race_target.nonces(at_block, false) + .await + .map_err(|e| format!("failed to read nonces from target node: {:?}", e)) + .and_then(|(_, nonces_at_target)| { + if nonces_at_target.latest_nonce < *nonces_submitted.end() { + Err(format!( + "best nonce at target after tx is {:?} and we've submitted {:?}", + nonces_at_target.latest_nonce, + nonces_submitted.end(), + )) + } else { + Ok(()) + } + }) + .map_err(|e| { + log::error!( + target: "bridge", + "{} -> {} race has stalled. Transaction failed: {}. Going to restart", + P::source_name(), + P::target_name(), + e, + ); + + FailedClient::Both + })?; + }, + (TrackedTransactionStatus::Lost, _) => { + log::warn!( + target: "bridge", + "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", + P::source_name(), + P::target_name(), + race_state, + strategy, + ); + + return Err(FailedClient::Both); + }, + _ => (), } }, diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 09e55740cef3c..6648f2efc7279 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -124,7 +124,7 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Transaction tracker to track submitted transactions. - type TransactionTracker: TransactionTracker; + type TransactionTracker: TransactionTracker>; /// Get best block id. async fn best_block(&self) -> Result, Self::Error>; @@ -260,13 +260,13 @@ where // check if our transaction has been mined if let Some(tracker) = submitted_heads_tracker.take() { - match tracker.update(&heads_at_target).await { + match tracker.update(&best_target_block, &heads_at_target).await { SubmittedHeadsStatus::Waiting(tracker) => { // no news about our transaction and we shall keep waiting submitted_heads_tracker = Some(tracker); continue }, - SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized) => { + SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized(_)) => { // all heads have been updated, we don't need this tracker anymore }, SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) => { @@ -529,9 +529,24 @@ enum SubmittedHeadsStatus { /// Heads are not yet updated. Waiting(SubmittedHeadsTracker

), /// Heads transaction has either been finalized or lost (i.e. received its "final" status). - Final(TrackedTransactionStatus), + Final(TrackedTransactionStatus>), } +/// Type of the transaction tracker that the `SubmittedHeadsTracker` is using. +/// +/// It needs to be shared because of `poll` macro and our consuming `update` method. +type SharedTransactionTracker

= Shared< + Pin< + Box< + dyn Future< + Output = TrackedTransactionStatus< + HeaderIdOf<

::TargetChain>, + >, + > + Send, + >, + >, +>; + /// Submitted parachain heads transaction. struct SubmittedHeadsTracker { /// Ids of parachains which heads were updated in the tracked transaction. @@ -541,7 +556,7 @@ struct SubmittedHeadsTracker { /// Future that waits for submitted transaction finality or loss. /// /// It needs to be shared because of `poll` macro and our consuming `update` method. - transaction_tracker: Shared + Send>>>, + transaction_tracker: SharedTransactionTracker

, } impl SubmittedHeadsTracker

@@ -552,7 +567,7 @@ where pub fn new( awaiting_update: impl IntoIterator, relay_block_number: BlockNumberOf, - transaction_tracker: impl TransactionTracker + 'static, + transaction_tracker: impl TransactionTracker> + 'static, ) -> Self { SubmittedHeadsTracker { awaiting_update: awaiting_update.into_iter().collect(), @@ -564,6 +579,7 @@ where /// Returns `None` if all submitted parachain heads have been updated. pub async fn update( mut self, + at_target_block: &HeaderIdOf, heads_at_target: &BTreeMap>, ) -> SubmittedHeadsStatus

{ // remove all pending heads that were synced @@ -590,14 +606,23 @@ where // if we have synced all required heads, we are done if self.awaiting_update.is_empty() { - return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized) + return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized( + *at_target_block, + )) } // if underlying transaction tracker has reported that the transaction is lost, we may // then restart our sync let transaction_tracker = self.transaction_tracker.clone(); - if let Poll::Ready(TrackedTransactionStatus::Lost) = poll!(transaction_tracker) { - return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) + match poll!(transaction_tracker) { + Poll::Ready(TrackedTransactionStatus::Lost) => + return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost), + Poll::Ready(TrackedTransactionStatus::Finalized(_)) => { + // so we are here and our transaction is mined+finalized, but some of heads were not + // updated => we're considering our loop as stalled + return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) + }, + _ => (), } SubmittedHeadsStatus::Waiting(self) @@ -644,12 +669,17 @@ mod tests { } #[derive(Clone, Debug)] - struct TestTransactionTracker(TrackedTransactionStatus); + struct TestTransactionTracker(Option>>); #[async_trait] impl TransactionTracker for TestTransactionTracker { - async fn wait(self) -> TrackedTransactionStatus { - self.0 + type HeaderId = HeaderIdOf; + + async fn wait(self) -> TrackedTransactionStatus> { + match self.0 { + Some(status) => status, + None => futures::future::pending().await, + } } } @@ -785,7 +815,9 @@ mod tests { if let Some(mut exit_signal_sender) = data.exit_signal_sender.take() { exit_signal_sender.send(()).await.unwrap(); } - Ok(TestTransactionTracker(TrackedTransactionStatus::Finalized)) + Ok(TestTransactionTracker(Some( + TrackedTransactionStatus::Finalized(Default::default()), + ))) } } @@ -938,10 +970,31 @@ mod tests { SubmittedHeadsTracker::new( vec![ParaId(PARA_ID), ParaId(PARA_1_ID)], SOURCE_BLOCK_NUMBER, - TestTransactionTracker(TrackedTransactionStatus::Finalized), + TestTransactionTracker(None), ) } + fn all_expected_tracker_heads() -> BTreeMap> { + vec![ + ( + ParaId(PARA_ID), + Some(BestParaHeadHash { + at_relay_block_number: SOURCE_BLOCK_NUMBER, + head_hash: PARA_0_HASH, + }), + ), + ( + ParaId(PARA_1_ID), + Some(BestParaHeadHash { + at_relay_block_number: SOURCE_BLOCK_NUMBER, + head_hash: PARA_0_HASH, + }), + ), + ] + .into_iter() + .collect() + } + impl From> for Option> { fn from(status: SubmittedHeadsStatus) -> Option> { match status { @@ -955,7 +1008,10 @@ mod tests { async fn tx_tracker_update_when_nothing_is_updated() { assert_eq!( Some(test_tx_tracker().awaiting_update), - test_tx_tracker().update(&vec![].into_iter().collect()).await.into(), + test_tx_tracker() + .update(&HeaderId(0, Default::default()), &vec![].into_iter().collect()) + .await + .into(), ); } @@ -965,6 +1021,7 @@ mod tests { Some(test_tx_tracker().awaiting_update), test_tx_tracker() .update( + &HeaderId(0, Default::default()), &vec![( ParaId(PARA_ID), Some(BestParaHeadHash { @@ -986,6 +1043,7 @@ mod tests { Some(vec![ParaId(PARA_1_ID)].into_iter().collect::>()), test_tx_tracker() .update( + &HeaderId(0, Default::default()), &vec![( ParaId(PARA_ID), Some(BestParaHeadHash { @@ -1006,50 +1064,52 @@ mod tests { assert_eq!( Option::>::None, test_tx_tracker() - .update( - &vec![ - ( - ParaId(PARA_ID), - Some(BestParaHeadHash { - at_relay_block_number: SOURCE_BLOCK_NUMBER, - head_hash: PARA_0_HASH, - }) - ), - ( - ParaId(PARA_1_ID), - Some(BestParaHeadHash { - at_relay_block_number: SOURCE_BLOCK_NUMBER, - head_hash: PARA_0_HASH, - }) - ), - ] - .into_iter() - .collect() - ) + .update(&HeaderId(0, Default::default()), &all_expected_tracker_heads()) .await .into(), ); } #[async_std::test] - async fn tx_tracker_update_when_tx_is_stalled() { + async fn tx_tracker_update_when_tx_is_lost() { let mut tx_tracker = test_tx_tracker(); tx_tracker.transaction_tracker = futures::future::ready(TrackedTransactionStatus::Lost).boxed().shared(); - assert_eq!( - Option::>::None, - tx_tracker.update(&vec![].into_iter().collect()).await.into(), - ); + assert!(matches!( + tx_tracker + .update(&HeaderId(0, Default::default()), &vec![].into_iter().collect()) + .await, + SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost), + )); + } + + #[async_std::test] + async fn tx_tracker_update_when_tx_is_finalized_but_heads_are_not_updated() { + let mut tx_tracker = test_tx_tracker(); + tx_tracker.transaction_tracker = + futures::future::ready(TrackedTransactionStatus::Finalized(Default::default())) + .boxed() + .shared(); + assert!(matches!( + tx_tracker + .update(&HeaderId(0, Default::default()), &vec![].into_iter().collect()) + .await, + SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost), + )); } #[async_std::test] - async fn tx_tracker_update_when_tx_is_finalized() { + async fn tx_tracker_update_when_tx_is_finalized_and_heads_are_updated() { let mut tx_tracker = test_tx_tracker(); tx_tracker.transaction_tracker = - futures::future::ready(TrackedTransactionStatus::Finalized).boxed().shared(); + futures::future::ready(TrackedTransactionStatus::Finalized(Default::default())) + .boxed() + .shared(); assert!(matches!( - tx_tracker.update(&vec![].into_iter().collect()).await, - SubmittedHeadsStatus::Waiting(_), + tx_tracker + .update(&HeaderId(0, Default::default()), &all_expected_tracker_heads()) + .await, + SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized(_)), )); } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index b19b9cd449883..eb3d8ec752508 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -122,18 +122,21 @@ pub trait MaybeConnectionError { /// Final status of the tracked transaction. #[derive(Debug, Clone, Copy, PartialEq)] -pub enum TrackedTransactionStatus { +pub enum TrackedTransactionStatus { /// Transaction has been lost. Lost, - /// Transaction has been mined and finalized. - Finalized, + /// Transaction has been mined and finalized at given block. + Finalized(BlockId), } /// Transaction tracker. #[async_trait] pub trait TransactionTracker: Send { + /// Header id, used by the chain. + type HeaderId: Clone + Send; + /// Wait until transaction is either finalized or invalidated/lost. - async fn wait(self) -> TrackedTransactionStatus; + async fn wait(self) -> TrackedTransactionStatus; } /// Stringified error that may be either connection-related or not. From 9ec3e63da4c05b2519fdc2af2ade01e4e14e10ed Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 3 Oct 2022 11:02:12 +0200 Subject: [PATCH 0782/1210] =?UTF-8?q?Cleaning=20deps=20+=20satisfy=20`carg?= =?UTF-8?q?o=20build=20--release=20--all-targets=20--all-fe=E2=80=A6=20(#1?= =?UTF-8?q?587)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Cleaning deps + satisfy `cargo build --release --all-targets --all-features` * PR fixes --- bin/millau/node/Cargo.toml | 3 -- bin/millau/runtime/Cargo.toml | 10 ------ bin/rialto-parachain/node/Cargo.toml | 13 -------- bin/rialto-parachain/runtime/Cargo.toml | 5 +-- bin/rialto-parachain/runtime/src/lib.rs | 7 +++++ bin/rialto/node/Cargo.toml | 42 ------------------------- bin/rialto/runtime/Cargo.toml | 12 ------- bin/runtime-common/Cargo.toml | 9 ------ modules/grandpa/Cargo.toml | 5 +-- modules/messages/Cargo.toml | 3 +- modules/parachains/Cargo.toml | 5 +-- modules/relayers/Cargo.toml | 4 --- primitives/chain-kusama/Cargo.toml | 1 - primitives/chain-rococo/Cargo.toml | 1 - primitives/chain-westend/Cargo.toml | 3 -- primitives/chain-wococo/Cargo.toml | 2 -- primitives/messages/Cargo.toml | 2 -- primitives/parachains/Cargo.toml | 2 -- primitives/polkadot-core/Cargo.toml | 4 --- relays/bin-substrate/Cargo.toml | 6 ---- relays/client-substrate/Cargo.toml | 1 - relays/client-westend/Cargo.toml | 1 - relays/parachains/Cargo.toml | 4 --- 23 files changed, 11 insertions(+), 134 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index e83f3c4f564c7..a7a2f86ea33cc 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -15,10 +15,7 @@ serde_json = "1.0.79" # Bridge dependencies -bp-millau = { path = "../../../primitives/chain-millau" } -bp-runtime = { path = "../../../primitives/runtime" } millau-runtime = { path = "../runtime" } -pallet-bridge-messages = { path = "../../../modules/messages" } # Substrate Dependencies diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 05e79074b6891..dfab9588d5d08 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,14 +9,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies -bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } @@ -56,7 +53,6 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-consensus-aura = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { 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-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -65,7 +61,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot Dependencies @@ -87,7 +82,6 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran default = ["std"] std = [ "beefy-primitives/std", - "bp-header-chain/std", "bp-messages/std", "bp-millau/std", "bp-polkadot-core/std", @@ -122,12 +116,10 @@ std = [ "pallet-transaction-payment/std", "pallet-xcm/std", "scale-info/std", - "serde", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", "sp-core/std", - "sp-finality-grandpa/std", "sp-inherents/std", "sp-io/std", "sp-offchain/std", @@ -135,7 +127,6 @@ std = [ "sp-session/std", "sp-std/std", "sp-transaction-pool/std", - "sp-trie/std", "sp-version/std", "xcm/std", "xcm-builder/std", @@ -146,7 +137,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 109be667c4cd3..1b37cb3a3fee7 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -18,16 +18,9 @@ runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] clap = { version = "3.1", features = ["derive"] } -derive_more = '0.99.2' log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } -hex-literal = '0.3.1' - -# Bridge dependencies - -bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain" } -pallet-bridge-messages = { path = "../../../modules/messages" } # RPC related Dependencies jsonrpsee = { version = "0.15.1", features = ["server"] } @@ -52,7 +45,6 @@ sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "mas sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ['wasmtime'] } @@ -63,11 +55,9 @@ sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master ## Substrate Primitive Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -78,7 +68,6 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch # Cumulus dependencies cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } @@ -89,7 +78,5 @@ cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech # Polkadot dependencies polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index d125931220f10..de3067162652d 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -11,9 +11,9 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} +hex-literal = "0.3" log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = '1.0', optional = true, features = ['derive'] } # Bridge depedencies @@ -67,7 +67,6 @@ cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = " cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } # Polkadot Dependencies @@ -98,7 +97,6 @@ std = [ "codec/std", "log/std", "scale-info/std", - "serde", "sp-api/std", "sp-std/std", "sp-io/std", @@ -130,7 +128,6 @@ std = [ "cumulus-pallet-xcm/std", "cumulus-primitives-core/std", "cumulus-primitives-timestamp/std", - "cumulus-primitives-utility/std", "xcm/std", "xcm-builder/std", "xcm-executor/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 885688d683d37..dab7e4d96f865 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -777,6 +777,13 @@ impl_runtime_apis! { #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(_extra: bool) -> ( + Vec, + Vec, + ) { + todo!("TODO: fix or remove") + } + fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index fe2186ea3f30f..6a0a1e946c811 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,68 +10,26 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "3.1", features = ["derive"] } -futures = "0.3" -jsonrpc-core = "18.0" -kvdb = "0.11" -kvdb-rocksdb = "0.15" -lru = "0.7" serde_json = "1.0.79" -thiserror = "1.0" # Bridge dependencies -bp-runtime = { path = "../../../primitives/runtime" } -bp-rialto = { path = "../../../primitives/chain-rialto" } -pallet-bridge-messages = { path = "../../../modules/messages" } rialto-runtime = { path = "../runtime" } # Substrate Dependencies -beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" } -beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-slots = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-uncles = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 8d90f1f3296cf..fe2ab903b0ac7 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,15 +8,11 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -hex-literal = "0.3" -libsecp256k1 = { version = "0.7", optional = true, default-features = false, features = ["hmac"] } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies -bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } @@ -53,7 +49,6 @@ sp-authority-discovery = { git = "https://github.com/paritytech/substrate", bran sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-consensus-babe = { 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { 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-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -62,7 +57,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot (parachain) Dependencies @@ -78,7 +72,6 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-x [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } env_logger = "0.8" -libsecp256k1 = { version = "0.7", features = ["hmac"] } static_assertions = "1.1" [build-dependencies] @@ -88,7 +81,6 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran default = ["std"] std = [ "beefy-primitives/std", - "bp-header-chain/std", "bp-messages/std", "bp-millau/std", "bp-relayers/std", @@ -123,13 +115,11 @@ std = [ "polkadot-runtime-common/std", "polkadot-runtime-parachains/std", "scale-info/std", - "serde", "sp-api/std", "sp-authority-discovery/std", "sp-block-builder/std", "sp-consensus-babe/std", "sp-core/std", - "sp-finality-grandpa/std", "sp-inherents/std", "sp-io/std", "sp-offchain/std", @@ -137,7 +127,6 @@ std = [ "sp-session/std", "sp-std/std", "sp-transaction-pool/std", - "sp-trie/std", "sp-version/std", "xcm/std", "xcm-builder/std", @@ -148,7 +137,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "libsecp256k1", "pallet-bridge-messages/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index bb75d828d28fd..3f717b05c6e6d 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -10,7 +10,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.15.2", default-features = false } log = { version = "0.4.17", default-features = false } -num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } @@ -29,15 +28,12 @@ pallet-bridge-parachains = { path = "../../modules/parachains", default-features frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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, optional = true } 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 } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } # Polkadot dependencies @@ -61,18 +57,15 @@ std = [ "frame-system/std", "hash-db/std", "log/std", - "num-traits/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-parachains/std", - "pallet-transaction-payment/std", "pallet-xcm/std", "scale-info/std", "sp-api/std", "sp-core/std", "sp-io/std", "sp-runtime/std", - "sp-state-machine/std", "sp-std/std", "sp-trie/std", "xcm/std", @@ -83,8 +76,6 @@ runtime-benchmarks = [ "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", - "sp-state-machine", - "sp-version", "xcm-builder/runtime-benchmarks", ] integrity-test = [ diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 55022d7e5c439..45f314a0bbd3b 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -11,9 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.0", default-features = false } log = { version = "0.4.17", default-features = false } -num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } # Bridge Dependencies @@ -47,10 +45,9 @@ std = [ "finality-grandpa/std", "frame-support/std", "frame-system/std", + "frame-benchmarking/std", "log/std", - "num-traits/std", "scale-info/std", - "serde", "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 78a70b9bd580d..f8ff74cdd55ae 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -12,7 +12,6 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -41,10 +40,10 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "frame-benchmarking/std", "log/std", "num-traits/std", "scale-info/std", - "serde", "sp-core/std", "sp-runtime/std", "sp-std/std", diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 99e91180b38d2..bccd16f3d593d 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -9,7 +9,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true } # Bridge Dependencies @@ -23,7 +22,6 @@ pallet-bridge-grandpa = { path = "../grandpa", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { 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-runtime = { 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 } @@ -42,11 +40,10 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "frame-benchmarking/std", "log/std", "pallet-bridge-grandpa/std", "scale-info/std", - "serde", - "sp-core/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 70720a211cecb..00d1bb591206d 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -9,9 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } -num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true, features = ["derive"] } # Bridge dependencies @@ -43,10 +41,8 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "num-traits/std", "pallet-bridge-messages/std", "scale-info/std", - "serde", "sp-arithmetic/std", "sp-std/std", ] diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index ef902fef824cf..3bca5f4c3f077 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.7" # Bridge Dependencies diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 730fad599bb10..65d3f502db446 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.7" # Bridge Dependencies bp-polkadot-core = { path = "../polkadot-core", default-features = false } diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index ca5840b9dea5f..e5f7bf89565b6 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -9,11 +9,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -smallvec = "1.7" # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -25,7 +23,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master [features] default = ["std"] std = [ - "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", "codec/std", diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 27297fe98543a..5a4c439e042a9 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -10,7 +10,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-rococo = { path = "../chain-rococo", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies @@ -21,6 +20,5 @@ default = ["std"] std = [ "bp-polkadot-core/std", "bp-runtime/std", - "bp-rococo/std", "sp-api/std", ] diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 6690a1bfbb070..736764ef20ffc 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -20,7 +20,6 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -35,7 +34,6 @@ std = [ "bp-runtime/std", "codec/std", "frame-support/std", - "frame-system/std", "scale-info/std", "serde", "sp-core/std", diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index f6327c772c0da..0aa2adfead184 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -9,7 +9,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies @@ -29,6 +28,5 @@ std = [ "codec/std", "frame-support/std", "scale-info/std", - "serde", "sp-core/std", ] diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 4448e75f11a45..9a68e8ccc2db6 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -21,11 +21,9 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-runtime = { 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-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] hex = "0.4" @@ -41,9 +39,7 @@ std = [ "parity-util-mem", "scale-info/std", "serde", - "sp-api/std", "sp-core/std", "sp-runtime/std", "sp-std/std", - "sp-version/std", ] diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 2a463fff60e6a..ab10efc63ca11 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -15,23 +15,19 @@ hex = "0.4" log = "0.4.17" num-format = "0.4" num-traits = "0.2" -rand = "0.8" structopt = "0.3" strum = { version = "0.21.0", features = ["derive"] } # Bridge dependencies -bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } -bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-relay = { path = "../finality" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-messages = { path = "../../modules/messages" } @@ -50,9 +46,7 @@ substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 721415fb2d9e6..60ef1c67a26a8 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,7 +14,6 @@ jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.7" -serde = { version = "1.0" } tokio = { version = "1.8", features = ["rt-multi-thread"] } thiserror = "1.0.26" diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 2ad9963406775..57d2ca3b1e756 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -17,4 +17,3 @@ bp-westend = { path = "../../primitives/chain-westend" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 60ac120d7bcef..2af091c7ebb63 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -8,12 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" async-trait = "0.1.40" -backoff = "0.2" futures = "0.3.5" -linked-hash-map = "0.5.3" log = "0.4.17" -num-traits = "0.2" -parking_lot = "0.11.0" relay-utils = { path = "../utils" } # Bridge dependencies From 929513e5b4d68f32722262015b728083e1bec374 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 4 Oct 2022 08:02:19 +0200 Subject: [PATCH 0783/1210] LaneMessageVerifier - removed unused Submitter (#1589) * LaneMessageVerifier - removed unused Submitter * fmt --- bin/runtime-common/src/messages.rs | 1 - modules/messages/src/lib.rs | 1 - modules/messages/src/mock.rs | 4 +--- primitives/messages/src/source_chain.rs | 6 +++--- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index a7ad19dc1f168..50944826ddeae 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -315,7 +315,6 @@ pub mod source { impl LaneMessageVerifier< OriginOf>, - AccountIdOf>, FromThisChainMessagePayload, BalanceOf>, > for FromThisChainMessageVerifier diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index c2e4dce9b2d0d..0580a0ffdfac5 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -175,7 +175,6 @@ pub mod pallet { /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier< Self::Origin, - Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee, >; diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 9584d17b836b0..41ae0352cfb04 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -298,9 +298,7 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier - for TestLaneMessageVerifier -{ +impl LaneMessageVerifier for TestLaneMessageVerifier { type Error = &'static str; fn verify_message( diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index be56ffe87fb3d..c03d303ee8417 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -96,7 +96,7 @@ pub trait TargetHeaderChain { /// Lane3 until some block, ...), then it may be built using this verifier. /// /// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { +pub trait LaneMessageVerifier { /// Error type. type Error: Debug + Into<&'static str>; @@ -278,8 +278,8 @@ impl TargetHeaderChain for ForbidOutboun } } -impl - LaneMessageVerifier for ForbidOutboundMessages +impl LaneMessageVerifier + for ForbidOutboundMessages { type Error = &'static str; From 13596d29e4527615617130ddcc9f8bbf19b02be3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 4 Oct 2022 11:44:38 +0300 Subject: [PATCH 0784/1210] Use proper account types (#1591) * use proper account types * Update primitives/messages/src/source_chain.rs Co-authored-by: Branislav Kontur Co-authored-by: Branislav Kontur --- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/millau/runtime/src/rialto_parachain_messages.rs | 4 +--- bin/rialto-parachain/runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- primitives/messages/src/source_chain.rs | 4 ++++ 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index ccca4222f61d7..7054382b3852f 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -236,7 +236,7 @@ impl messages::BridgedChainWithMessages for Rialto { } } -impl TargetHeaderChain for Rialto { +impl TargetHeaderChain for Rialto { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 6840b703f4f4d..f26e0d1006ae4 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -229,9 +229,7 @@ impl messages::BridgedChainWithMessages for RialtoParachain { } } -impl TargetHeaderChain - for RialtoParachain -{ +impl TargetHeaderChain for RialtoParachain { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 136b4343c190f..96ff18810bcf4 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -243,7 +243,7 @@ impl messages::BridgedChainWithMessages for Millau { } } -impl TargetHeaderChain for Millau { +impl TargetHeaderChain for Millau { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 1267cbd06e29f..2de74f4c6b966 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -233,7 +233,7 @@ impl messages::BridgedChainWithMessages for Millau { } } -impl TargetHeaderChain for Millau { +impl TargetHeaderChain for Millau { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index c03d303ee8417..5c6283a803602 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -61,6 +61,10 @@ pub struct RelayerRewards { /// All implementations of this trait should only work with finalized data that /// can't change. Wrong implementation may lead to invalid lane states (i.e. lane /// that's stuck) and/or processing messages without paying fees. +/// +/// The `Payload` type here means the payload of the message that is sent from the +/// source chain to the target chain. The `AccountId` type here means the account +/// type used by the source chain. pub trait TargetHeaderChain { /// Error type. type Error: Debug + Into<&'static str>; From df7e1b1d5db15b3fe7baae1fd2f6dc270465b315 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 4 Oct 2022 14:18:22 +0300 Subject: [PATCH 0785/1210] MillauWeight -> BridgeWeight (#1593) --- bin/millau/runtime/src/lib.rs | 12 ++-- bin/millau/runtime/src/rialto_messages.rs | 2 +- bin/rialto-parachain/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- modules/grandpa/src/weights.rs | 22 ++++--- modules/messages/src/weights.rs | 62 ++++++++++--------- modules/messages/src/weights_ext.rs | 2 +- modules/parachains/src/weights.rs | 22 ++++--- modules/parachains/src/weights_ext.rs | 4 +- modules/relayers/src/weights.rs | 14 +++-- .../lib-substrate-relay/src/messages_lane.rs | 2 +- 12 files changed, 80 insertions(+), 72 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2fea97cea8d49..8470efa7e86b3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -432,7 +432,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; + type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; @@ -441,7 +441,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; + type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -465,7 +465,7 @@ pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_messages::weights::MillauWeight; + type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = rialto_messages::MillauToRialtoMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -500,7 +500,7 @@ pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1 impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_messages::weights::MillauWeight; + type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = rialto_parachain_messages::MillauToRialtoParachainMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; @@ -541,7 +541,7 @@ pub type WithRialtoParachainsInstance = (); impl pallet_bridge_parachains::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_parachains::weights::MillauWeight; + type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; type ParasPalletName = RialtoParasPalletName; type TrackedParachains = frame_support::traits::Everything; @@ -553,7 +553,7 @@ pub type WithWestendParachainsInstance = pallet_bridge_parachains::Instance1; impl pallet_bridge_parachains::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_parachains::weights::MillauWeight; + type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; type TrackedParachains = frame_support::traits::Everything; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 7054382b3852f..f043f8b9d4316 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -320,7 +320,7 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::MillauWeight; + type Weights = pallet_bridge_messages::weights::BridgeWeight; pallet_bridge_messages::ensure_weights_are_correct::( bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index dab7e4d96f865..b714e6d631859 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -538,7 +538,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; + type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } parameter_types! { @@ -559,7 +559,7 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_messages::weights::MillauWeight; + type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = millau_messages::RialtoParachainToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 3729ab78630e7..09afe728fd28d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -424,7 +424,7 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type WeightInfo = pallet_bridge_grandpa::weights::MillauWeight; + type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } impl pallet_shift_session_manager::Config for Runtime {} @@ -447,7 +447,7 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type Event = Event; - type WeightInfo = pallet_bridge_messages::weights::MillauWeight; + type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = millau_messages::RialtoToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 2de74f4c6b966..e5869998fa8ba 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -315,7 +315,7 @@ mod tests { #[test] fn ensure_rialto_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::MillauWeight; + type Weights = pallet_bridge_messages::weights::BridgeWeight; pallet_bridge_messages::ensure_weights_are_correct::( bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index f23a2ac190397..ece88ab55c5f0 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-06, STEPS: 50, REPEAT: 20 +//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -53,13 +53,15 @@ pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; } -/// Weights for `pallet_bridge_grandpa` using the Millau node and recommended hardware. -pub struct MillauWeight(PhantomData); -impl WeightInfo for MillauWeight { +/// Weights for `pallet_bridge_grandpa` that are generated using one of the Bridge testnets. +/// +/// Those weights are test only and must never be used in production. +pub struct BridgeWeight(PhantomData); +impl WeightInfo for BridgeWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (55_070_000 as Weight) - .saturating_add((39_678_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((1_540_000 as Weight).saturating_mul(v as Weight)) + (105_417_000 as Weight) + .saturating_add((40_923_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_691_000 as Weight).saturating_mul(v as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(6 as Weight)) } @@ -68,9 +70,9 @@ impl WeightInfo for MillauWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (55_070_000 as Weight) - .saturating_add((39_678_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((1_540_000 as Weight).saturating_mul(v as Weight)) + (105_417_000 as Weight) + .saturating_add((40_923_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((1_691_000 as Weight).saturating_mul(v as Weight)) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(6 as Weight)) } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 3f9ea8bbb16d5..02b014120f14d 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-20, STEPS: 50, REPEAT: 20 +//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -66,26 +66,28 @@ pub trait WeightInfo { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; } -/// Weights for `pallet_bridge_messages` using the Millau node and recommended hardware. -pub struct MillauWeight(PhantomData); -impl WeightInfo for MillauWeight { +/// Weights for `pallet_bridge_messages` that are generated using one of the Bridge testnets. +/// +/// Those weights are test only and must never be used in production. +pub struct BridgeWeight(PhantomData); +impl WeightInfo for BridgeWeight { fn send_minimal_message_worst_case() -> Weight { - (38_822_000 as Weight) + (62_300_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (39_799_000 as Weight) + (63_176_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (47_772_000 as Weight) + (73_472_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(10 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (3_081_804_000 as Weight) + (2_539_209_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } @@ -96,47 +98,47 @@ impl WeightInfo for MillauWeight { .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof() -> Weight { - (26_523_000 as Weight) + (49_205_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_two_messages_proof() -> Weight { - (39_278_000 as Weight) + (62_182_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (32_416_000 as Weight) + (55_928_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (27_078_000 as Weight) + (47_298_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (78_235_000 as Weight) + (105_016_000 as Weight) .saturating_add(T::DbWeight::get().reads(3 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (27_635_000 as Weight) + (49_067_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (34_576_000 as Weight) + (58_520_000 as Weight) .saturating_add(T::DbWeight::get().reads(5 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (37_318_000 as Weight) + (61_563_000 as Weight) .saturating_add(T::DbWeight::get().reads(6 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (41_245_000 as Weight) + (63_197_000 as Weight) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -145,22 +147,22 @@ impl WeightInfo for MillauWeight { // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (38_822_000 as Weight) + (62_300_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn send_1_kb_message_worst_case() -> Weight { - (39_799_000 as Weight) + (63_176_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn send_16_kb_message_worst_case() -> Weight { - (47_772_000 as Weight) + (73_472_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(10 as Weight)) } fn maximal_increase_message_fee() -> Weight { - (3_081_804_000 as Weight) + (2_539_209_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } @@ -171,47 +173,47 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof() -> Weight { - (26_523_000 as Weight) + (49_205_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_two_messages_proof() -> Weight { - (39_278_000 as Weight) + (62_182_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (32_416_000 as Weight) + (55_928_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_single_message_proof_1_kb() -> Weight { - (27_078_000 as Weight) + (47_298_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_message_proof_16_kb() -> Weight { - (78_235_000 as Weight) + (105_016_000 as Weight) .saturating_add(RocksDbWeight::get().reads(3 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } fn receive_single_prepaid_message_proof() -> Weight { - (27_635_000 as Weight) + (49_067_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_single_message() -> Weight { - (34_576_000 as Weight) + (58_520_000 as Weight) .saturating_add(RocksDbWeight::get().reads(5 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (37_318_000 as Weight) + (61_563_000 as Weight) .saturating_add(RocksDbWeight::get().reads(6 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (41_245_000 as Weight) + (63_197_000 as Weight) .saturating_add(RocksDbWeight::get().reads(7 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 3c5a24788ec6a..52eb426190530 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -392,7 +392,7 @@ impl WeightInfoExt for () { } } -impl WeightInfoExt for crate::weights::MillauWeight { +impl WeightInfoExt for crate::weights::BridgeWeight { fn expected_extra_storage_proof_size() -> u32 { EXTRA_STORAGE_PROOF_SIZE } diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index b96e24752d512..1ab2e6c554806 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_parachains` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-06, STEPS: 50, REPEAT: 20 +//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -55,23 +55,25 @@ pub trait WeightInfo { fn submit_parachain_heads_with_16kb_proof() -> Weight; } -/// Weights for `pallet_bridge_parachains` using the Millau node and recommended hardware. -pub struct MillauWeight(PhantomData); -impl WeightInfo for MillauWeight { +/// Weights for `pallet_bridge_parachains` that are generated using one of the Bridge testnets. +/// +/// Those weights are test only and must never be used in production. +pub struct BridgeWeight(PhantomData); +impl WeightInfo for BridgeWeight { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { (0 as Weight) - .saturating_add((18_706_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((24_869_000 as Weight).saturating_mul(p as Weight)) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - (27_549_000 as Weight) + (56_262_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - (80_792_000 as Weight) + (105_189_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(3 as Weight)) } @@ -81,18 +83,18 @@ impl WeightInfo for MillauWeight { impl WeightInfo for () { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { (0 as Weight) - .saturating_add((18_706_000 as Weight).saturating_mul(p as Weight)) + .saturating_add((24_869_000 as Weight).saturating_mul(p as Weight)) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - (27_549_000 as Weight) + (56_262_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - (80_792_000 as Weight) + (105_189_000 as Weight) .saturating_add(RocksDbWeight::get().reads(4 as Weight)) .saturating_add(RocksDbWeight::get().writes(3 as Weight)) } diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs index 98655a6ea4702..63684ecc2158b 100644 --- a/modules/parachains/src/weights_ext.rs +++ b/modules/parachains/src/weights_ext.rs @@ -16,7 +16,7 @@ //! Weight-related utilities. -use crate::weights::{MillauWeight, WeightInfo}; +use crate::weights::{BridgeWeight, WeightInfo}; use bp_runtime::Size; use frame_support::weights::{RuntimeDbWeight, Weight}; @@ -101,7 +101,7 @@ impl WeightInfoExt for () { } } -impl WeightInfoExt for MillauWeight { +impl WeightInfoExt for BridgeWeight { fn expected_extra_storage_proof_size() -> u32 { EXTRA_STORAGE_PROOF_SIZE } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index fd7efe940d455..afecbe9d6d750 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_relayers` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-07-20, STEPS: 50, REPEAT: 20 +//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -53,11 +53,13 @@ pub trait WeightInfo { fn claim_rewards() -> Weight; } -/// Weights for `pallet_bridge_relayers` using the Millau node and recommended hardware. -pub struct MillauWeight(PhantomData); -impl WeightInfo for MillauWeight { +/// Weights for `pallet_bridge_relayers` that are generated using one of the Bridge testnets. +/// +/// Those weights are test only and must never be used in production. +pub struct BridgeWeight(PhantomData); +impl WeightInfo for BridgeWeight { fn claim_rewards() -> Weight { - (38_435_000 as Weight) + (55_856_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } @@ -66,7 +68,7 @@ impl WeightInfo for MillauWeight { // For backwards compatibility and tests impl WeightInfo for () { fn claim_rewards() -> Weight { - (38_435_000 as Weight) + (55_856_000 as Weight) .saturating_add(RocksDbWeight::get().reads(2 as Weight)) .saturating_add(RocksDbWeight::get().writes(2 as Weight)) } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 55fcb540ebef5..14227f379d7b6 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -484,7 +484,7 @@ mod tests { use bp_runtime::Chain; type RialtoToMillauMessagesWeights = - pallet_bridge_messages::weights::MillauWeight; + pallet_bridge_messages::weights::BridgeWeight; #[test] fn select_delivery_transaction_limits_works() { From 41faeb9dbca4d587d6abfac79ec0f1e5e2ab90e4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 10 Oct 2022 11:32:53 +0300 Subject: [PATCH 0786/1210] Remove pallet::without_storage_info from bridge GRANDPA pallet (#1478) * remove pallet::without_storage_info from bridge GRANDPA pallet * StoredBridgedHeader * spelling * fix benchmarks * MAX_BRIDGED_AUTHORITIES: 256 -> 2048 * Update modules/grandpa/src/storage_types.rs Co-authored-by: Adrian Catangiu * Update modules/grandpa/src/storage_types.rs Co-authored-by: Adrian Catangiu * moved max authorities + header size to chain primitives * removed unused code * new -> try_new * fix benchmarks compilation Co-authored-by: Adrian Catangiu --- bin/millau/runtime/src/lib.rs | 16 ++ bin/rialto-parachain/runtime/src/lib.rs | 7 + bin/rialto/runtime/src/lib.rs | 7 + modules/grandpa/src/lib.rs | 185 +++++++++++++++++++++--- modules/grandpa/src/mock.rs | 5 + modules/grandpa/src/storage_types.rs | 106 ++++++++++++++ modules/parachains/src/mock.rs | 4 + primitives/chain-millau/src/lib.rs | 6 + primitives/chain-rialto/src/lib.rs | 6 + primitives/chain-westend/src/lib.rs | 12 ++ primitives/header-chain/src/lib.rs | 41 ------ primitives/runtime/src/chain.rs | 20 ++- 12 files changed, 349 insertions(+), 66 deletions(-) create mode 100644 modules/grandpa/src/storage_types.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8470efa7e86b3..538417127e362 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -426,11 +426,25 @@ parameter_types! { pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; } +parameter_types! { + /// Maximal number of authorities at Rialto. + pub const MaxAuthoritiesAtRialto: u32 = bp_rialto::MAX_AUTHORITIES_COUNT; + /// Maximal size of SCALE-encoded Rialto header. + pub const MaxRialtoHeaderSize: u32 = bp_rialto::MAX_HEADER_SIZE; + + /// Maximal number of authorities at Westend. + pub const MaxAuthoritiesAtWestend: u32 = bp_westend::MAX_AUTHORITIES_COUNT; + /// Maximal size of SCALE-encoded Westend header. + pub const MaxWestendHeaderSize: u32 = bp_westend::MAX_HEADER_SIZE; +} + pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = MaxAuthoritiesAtRialto; + type MaxBridgedHeaderSize = MaxRialtoHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -440,6 +454,8 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = MaxAuthoritiesAtWestend; + type MaxBridgedHeaderSize = MaxWestendHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index b714e6d631859..752270f04c382 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -531,6 +531,11 @@ parameter_types! { /// Assuming the worst case of every header being finalized, we will keep headers at least for a /// week. pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32; + + /// Maximal number of authorities at Millau. + pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; + /// Maximal size of SCALE-encoded Millau header. + pub const MaxMillauHeaderSize: u32 = bp_millau::MAX_HEADER_SIZE; } pub type MillauGrandpaInstance = (); @@ -538,6 +543,8 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; + type MaxBridgedHeaderSize = MaxMillauHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 09afe728fd28d..161b0319508c6 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -417,6 +417,11 @@ parameter_types! { /// Assuming the worst case of every header being finalized, we will keep headers at least for a /// week. pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; + + /// Maximal number of authorities at Millau. + pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; + /// Maximal size of SCALE-encoded Millau header. + pub const MaxMillauHeaderSize: u32 = bp_millau::MAX_HEADER_SIZE; } pub type MillauGrandpaInstance = (); @@ -424,6 +429,8 @@ impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; + type MaxBridgedHeaderSize = MaxMillauHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 4074421fc52d5..c4cbadcb388f6 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -36,6 +36,8 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] +use storage_types::{StoredAuthoritySet, StoredBridgedHeader}; + use bp_header_chain::{justification::GrandpaJustification, InitializationData}; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; @@ -48,6 +50,7 @@ use sp_std::{boxed::Box, convert::TryInto}; mod extension; #[cfg(test)] mod mock; +mod storage_types; /// Module, containing weights for this pallet. pub mod weights; @@ -102,12 +105,24 @@ pub mod pallet { #[pallet::constant] type HeadersToKeep: Get; + /// Max number of authorities at the bridged chain. + #[pallet::constant] + type MaxBridgedAuthorities: Get; + /// Maximal size (in bytes) of the SCALE-encoded bridged chain header. + /// + /// This constant must be selected with care. The pallet requires mandatory headers to be + /// submitted to be able to proceed. Mandatory headers contain public keys of all GRANDPA + /// authorities. E.g. for 1024 authorities, the size of encoded keys will be at least 32 KB. + /// The same header may also contain other digest items as well, so some reserve here + /// is required. + #[pallet::constant] + type MaxBridgedHeaderSize: Get; + /// Weights gathered through benchmarking. type WeightInfo: WeightInfo; } #[pallet::pallet] - #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); #[pallet::hooks] @@ -180,12 +195,14 @@ pub mod pallet { let authority_set = >::get(); let set_id = authority_set.set_id; - verify_justification::(&justification, hash, *number, authority_set)?; + verify_justification::(&justification, hash, *number, authority_set.into())?; let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; + let finality_target = + StoredBridgedHeader::::try_from_bridged_header(*finality_target)?; >::mutate(|count| *count += 1); - insert_header::(*finality_target, hash); + insert_header::(finality_target, hash); log::info!( target: LOG_TARGET, "Successfully imported finalized header with hash {:?}!", @@ -221,7 +238,7 @@ pub mod pallet { let init_allowed = !>::exists(); ensure!(init_allowed, >::AlreadyInitialized); - initialize_bridge::(init_data.clone()); + initialize_bridge::(init_data.clone())?; log::info!( target: LOG_TARGET, @@ -286,12 +303,12 @@ pub mod pallet { /// Headers which have been imported into the pallet. #[pallet::storage] pub type ImportedHeaders, I: 'static = ()> = - StorageMap<_, Identity, BridgedBlockHash, BridgedHeader>; + StorageMap<_, Identity, BridgedBlockHash, StoredBridgedHeader>; /// The current GRANDPA Authority set. #[pallet::storage] pub(super) type CurrentAuthoritySet, I: 'static = ()> = - StorageValue<_, bp_header_chain::AuthoritySet, ValueQuery>; + StorageValue<_, StoredAuthoritySet, ValueQuery>; /// Optional pallet owner. /// @@ -333,7 +350,7 @@ pub mod pallet { } if let Some(init_data) = self.init_data.clone() { - initialize_bridge::(init_data); + initialize_bridge::(init_data).expect("genesis config is correct; qed"); } else { // Since the bridge hasn't been initialized we shouldn't allow anyone to perform // transactions. @@ -364,6 +381,10 @@ pub mod pallet { AlreadyInitialized, /// The storage proof doesn't contains storage root. So it is invalid for given header. StorageRootMismatch, + /// Too many authorities in the set. + TooManyAuthoritiesInSet, + /// Too large header. + TooLargeHeader, /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } @@ -392,8 +413,11 @@ pub mod pallet { ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); // TODO [#788]: Stop manually increasing the `set_id` here. - let next_authorities = bp_header_chain::AuthoritySet { - authorities: change.next_authorities, + let next_authorities = StoredAuthoritySet:: { + authorities: change + .next_authorities + .try_into() + .map_err(|_| Error::::TooManyAuthoritiesInSet)?, set_id: current_set_id + 1, }; @@ -454,7 +478,7 @@ pub mod pallet { /// Note this function solely takes care of updating the storage and pruning old entries, /// but does not verify the validity of such import. pub(crate) fn insert_header, I: 'static>( - header: BridgedHeader, + header: StoredBridgedHeader, hash: BridgedBlockHash, ) { let index = >::get(); @@ -475,19 +499,23 @@ pub mod pallet { /// were called by a trusted origin. pub(crate) fn initialize_bridge, I: 'static>( init_params: super::InitializationData>, - ) { + ) -> Result<(), Error> { let super::InitializationData { header, authority_list, set_id, operating_mode } = init_params; + let authority_set = StoredAuthoritySet::::try_new(authority_list, set_id) + .map_err(|_| Error::TooManyAuthoritiesInSet)?; + let header = StoredBridgedHeader::::try_from_bridged_header(*header)?; let initial_hash = header.hash(); >::put(initial_hash); >::put(0); - insert_header::(*header, initial_hash); + insert_header::(header, initial_hash); - let authority_set = bp_header_chain::AuthoritySet::new(authority_list, set_id); >::put(authority_set); >::put(operating_mode); + + Ok(()) } #[cfg(feature = "runtime-benchmarks")] @@ -496,7 +524,7 @@ pub mod pallet { ) { let start_number = *init_params.header.number(); let end_number = start_number + T::HeadersToKeep::get().into(); - initialize_bridge::(init_params); + initialize_bridge::(init_params).expect("benchmarks are correct"); let mut number = start_number; while number < end_number { @@ -509,7 +537,11 @@ pub mod pallet { Default::default(), ); let hash = header.hash(); - insert_header::(header, hash); + insert_header::( + StoredBridgedHeader::try_from_bridged_header(header) + .expect("only used from benchmarks; benchmarks are correct; qed"), + hash, + ); } } } @@ -521,7 +553,7 @@ impl, I: 'static> Pallet { /// if the pallet has not been initialized yet. pub fn best_finalized() -> Option> { let (_, hash) = >::get()?; - >::get(hash) + >::get(hash).map(|h| h.0) } /// Check if a particular header is known to the bridge pallet. @@ -591,13 +623,17 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader * benchmarks */ set_id: 0, operating_mode: bp_runtime::BasicOperatingMode::Normal, - }); + }) + .expect("only used from benchmarks; benchmarks are correct; qed"); } #[cfg(test)] mod tests { use super::*; - use crate::mock::{run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime}; + use crate::mock::{ + run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime, + MAX_BRIDGED_AUTHORITIES, MAX_HEADER_SIZE, + }; use bp_runtime::BasicOperatingMode; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, @@ -673,6 +709,22 @@ mod tests { Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] } } + fn many_authorities_log() -> Digest { + let consensus_log = + ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + next_authorities: std::iter::repeat((ALICE.into(), 1)) + .take(MAX_BRIDGED_AUTHORITIES as usize + 1) + .collect(), + delay: 0, + }); + + Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] } + } + + fn large_digest() -> Digest { + Digest { logs: vec![DigestItem::Other(vec![42; MAX_HEADER_SIZE as _])] } + } + #[test] fn init_root_or_owner_origin_can_initialize_pallet() { run_test(|| { @@ -715,6 +767,45 @@ mod tests { }) } + #[test] + fn init_fails_if_there_are_too_many_authorities_in_the_set() { + run_test(|| { + let genesis = test_header(0); + let init_data = InitializationData { + header: Box::new(genesis), + authority_list: std::iter::repeat(authority_list().remove(0)) + .take(MAX_BRIDGED_AUTHORITIES as usize + 1) + .collect(), + set_id: 1, + operating_mode: BasicOperatingMode::Normal, + }; + + assert_noop!( + Pallet::::initialize(Origin::root(), init_data), + Error::::TooManyAuthoritiesInSet, + ); + }); + } + + #[test] + fn init_fails_if_header_is_too_large() { + run_test(|| { + let mut genesis = test_header(0); + genesis.digest = large_digest(); + let init_data = InitializationData { + header: Box::new(genesis), + authority_list: authority_list(), + set_id: 1, + operating_mode: BasicOperatingMode::Normal, + }; + + assert_noop!( + Pallet::::initialize(Origin::root(), init_data), + Error::::TooLargeHeader, + ); + }); + } + #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { @@ -880,7 +971,8 @@ mod tests { // Make sure that the authority set actually changed upon importing our header assert_eq!( >::get(), - bp_header_chain::AuthoritySet::new(next_authorities, next_set_id), + StoredAuthoritySet::::try_new(next_authorities, next_set_id) + .unwrap(), ); }) } @@ -935,6 +1027,56 @@ mod tests { }) } + #[test] + fn importing_header_rejects_header_with_too_many_authorities() { + run_test(|| { + initialize_substrate_bridge(); + + // Need to update the header digest to indicate that our header signals an authority set + // change. However, the change doesn't happen until the next block. + let mut header = test_header(2); + header.digest = many_authorities_log(); + + // Create a valid justification for the header + let justification = make_default_justification(&header); + + // Should not be allowed to import this header + assert_err!( + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification + ), + >::TooManyAuthoritiesInSet + ); + }); + } + + #[test] + fn importing_header_rejects_header_if_it_is_too_large() { + run_test(|| { + initialize_substrate_bridge(); + + // Need to update the header digest to indicate that our header signals an authority set + // change. However, the change doesn't happen until the next block. + let mut header = test_header(2); + header.digest = large_digest(); + + // Create a valid justification for the header + let justification = make_default_justification(&header); + + // Should not be allowed to import this header + assert_err!( + Pallet::::submit_finality_proof( + Origin::signed(1), + Box::new(header), + justification + ), + >::TooLargeHeader + ); + }); + } + #[test] fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { run_test(|| { @@ -959,7 +1101,10 @@ mod tests { let hash = header.hash(); >::put((2, hash)); - >::insert(hash, header); + >::insert( + hash, + StoredBridgedHeader::try_from_bridged_header(header).unwrap(), + ); assert_ok!( Pallet::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index a0327761fc850..babdd4b7920c9 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -33,6 +33,9 @@ pub type TestNumber = crate::BridgedBlockNumber; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +pub const MAX_BRIDGED_AUTHORITIES: u32 = 2048; +pub const MAX_HEADER_SIZE: u32 = 65536; + use crate as grandpa; construct_runtime! { @@ -91,6 +94,8 @@ impl grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = frame_support::traits::ConstU32; + type MaxBridgedHeaderSize = frame_support::traits::ConstU32; type WeightInfo = (); } diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs new file mode 100644 index 0000000000000..5d2cb661d813a --- /dev/null +++ b/modules/grandpa/src/storage_types.rs @@ -0,0 +1,106 @@ +// Copyright 2022 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 . + +//! Wrappers for public types that are implementing `MaxEncodedLen` + +use crate::{BridgedHeader, Config, Error}; + +use bp_header_chain::AuthoritySet; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound}; +use scale_info::{Type, TypeInfo}; +use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; + +/// A bounded list of Grandpa authorities with associated weights. +pub type StoredAuthorityList = + BoundedVec<(AuthorityId, AuthorityWeight), MaxBridgedAuthorities>; + +/// A bounded GRANDPA Authority List and ID. +#[derive(Clone, Decode, Encode, Eq, TypeInfo, MaxEncodedLen, RuntimeDebugNoBound)] +#[scale_info(skip_type_params(T, I))] +pub struct StoredAuthoritySet, I: 'static> { + /// List of GRANDPA authorities for the current round. + pub authorities: StoredAuthorityList<>::MaxBridgedAuthorities>, + /// Monotonic identifier of the current GRANDPA authority set. + pub set_id: SetId, +} + +impl, I: 'static> StoredAuthoritySet { + /// Try to create a new bounded GRANDPA Authority Set from unbounded list. + /// + /// Returns error if number of authorities in the provided list is too large. + pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result { + Ok(Self { authorities: TryFrom::try_from(authorities)?, set_id }) + } +} + +impl, I: 'static> PartialEq for StoredAuthoritySet { + fn eq(&self, other: &Self) -> bool { + self.set_id == other.set_id && self.authorities == other.authorities + } +} + +impl, I: 'static> Default for StoredAuthoritySet { + fn default() -> Self { + StoredAuthoritySet { authorities: BoundedVec::default(), set_id: 0 } + } +} + +impl, I: 'static> From> for AuthoritySet { + fn from(t: StoredAuthoritySet) -> Self { + AuthoritySet { authorities: t.authorities.into(), set_id: t.set_id } + } +} + +/// A bounded chain header. +#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebugNoBound)] +pub struct StoredBridgedHeader, I: 'static>(pub BridgedHeader); + +impl, I: 'static> StoredBridgedHeader { + /// Construct `StoredBridgedHeader` from the `BridgedHeader` with all required checks. + pub fn try_from_bridged_header(header: BridgedHeader) -> Result> { + // this conversion is heavy (since we do encoding here), so we may want to optimize it later + // (e.g. by introducing custom Encode implementation, and turning `StoredBridgedHeader` into + // `enum StoredBridgedHeader { Decoded(BridgedHeader), Encoded(Vec) }`) + if header.encoded_size() > T::MaxBridgedHeaderSize::get() as usize { + Err(Error::TooLargeHeader) + } else { + Ok(StoredBridgedHeader(header)) + } + } +} + +impl, I: 'static> sp_std::ops::Deref for StoredBridgedHeader { + type Target = BridgedHeader; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl, I: 'static> TypeInfo for StoredBridgedHeader { + type Identity = Self; + + fn type_info() -> Type { + BridgedHeader::::type_info() + } +} + +impl, I: 'static> MaxEncodedLen for StoredBridgedHeader { + fn max_encoded_len() -> usize { + T::MaxBridgedHeaderSize::get() as usize + } +} diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 292856f35a766..a31fb4c47f90e 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -95,6 +95,8 @@ impl pallet_bridge_grandpa::Config for TestRun type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; + type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; type WeightInfo = (); } @@ -102,6 +104,8 @@ impl pallet_bridge_grandpa::Config for TestRun type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; + type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; + type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; type WeightInfo = (); } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 2f5b12eed0df0..60fe21884487e 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -109,6 +109,12 @@ pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; +/// Maximal number of GRANDPA authorities at Millau. +pub const MAX_AUTHORITIES_COUNT: u32 = 5; + +/// Maximal SCALE-encoded header size (in bytes) at Millau. +pub const MAX_HEADER_SIZE: u32 = 512; + /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 1b8d19249ea61..9698da8877946 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -100,6 +100,12 @@ pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; /// conditions. pub const SESSION_LENGTH: BlockNumber = 4; +/// Maximal number of GRANDPA authorities at Rialto. +pub const MAX_AUTHORITIES_COUNT: u32 = 5; + +/// Maximal SCALE-encoded header size (in bytes) at Rialto. +pub const MAX_HEADER_SIZE: u32 = 512; + /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 08803b7a3dd39..eeb30709accd7 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -58,6 +58,18 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains /// conditions. pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; +/// Maximal number of GRANDPA authorities at Westend. +/// +/// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration. +pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; + +/// Maximal SCALE-encoded header size (in bytes) at Westend. +/// +/// Let's assume that the largest header is header that enacts new authorities set with +/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have +/// some fixed reserve for other things (digest, block hash and number, ...) as well. +pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; + /// Identifier of Westmint parachain at the Westend relay chain. pub const WESTMINT_PARACHAIN_ID: u32 = 2000; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 8ac7972621ce6..f5590ce0a5a2b 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -71,47 +71,6 @@ pub struct InitializationData { pub operating_mode: BasicOperatingMode, } -/// base trait for verifying transaction inclusion proofs. -pub trait InclusionProofVerifier { - /// Transaction type. - type Transaction: Parameter; - /// Transaction inclusion proof type. - type TransactionInclusionProof: Parameter; - - /// Verify that transaction is a part of given block. - /// - /// Returns Some(transaction) if proof is valid and None otherwise. - fn verify_transaction_inclusion_proof( - proof: &Self::TransactionInclusionProof, - ) -> Option; -} - -/// A trait for pallets which want to keep track of finalized headers from a bridged chain. -pub trait HeaderChain { - /// Get the best finalized header known to the header chain. - fn best_finalized() -> Option; - - /// Get the best authority set known to the header chain. - fn authority_set() -> AuthoritySet; - - /// Write a header finalized by GRANDPA to the underlying pallet storage. - fn append_header(header: H) -> Result<(), E>; -} - -impl HeaderChain for () { - fn best_finalized() -> Option { - None - } - - fn authority_set() -> AuthoritySet { - AuthoritySet::default() - } - - fn append_header(_header: H) -> Result<(), E> { - Ok(()) - } -} - /// Abstract finality proof that is justifying block finality. pub trait FinalityProof: Clone + Send + Sync + Debug { /// Return number of header that this proof is generated for. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 7cb0ad976f06a..be95f17480d01 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::HeaderIdProvider; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ @@ -111,6 +111,7 @@ pub trait Chain: Send + Sync + 'static { + AsPrimitive + Default + Saturating + + MaxEncodedLen // original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but // `sp_runtime::generic::Era` requires block number -> `u64` conversion. + Into; @@ -130,7 +131,8 @@ pub trait Chain: Send + Sync + 'static { + SimpleBitOps + AsRef<[u8]> + AsMut<[u8]> - + MaybeMallocSizeOf; + + MaybeMallocSizeOf + + MaxEncodedLen; /// A type that fulfills the abstract idea of what a Substrate hasher (a type /// that produces hashes) is. @@ -148,7 +150,13 @@ pub trait Chain: Send + Sync + 'static { + MaybeSerializeDeserialize; /// The user account identifier type for the runtime. - type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord; + type AccountId: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + MaybeDisplay + + Ord + + MaxEncodedLen; /// Balance of an account in native tokens. /// /// The chain may support multiple tokens, but this particular type is for token that is used @@ -165,7 +173,8 @@ pub trait Chain: Send + Sync + 'static { + PartialOrd + SaturatingAdd + Zero - + TryFrom; + + TryFrom + + MaxEncodedLen; /// Index of a transaction used by the chain. type Index: Parameter + Member @@ -175,7 +184,8 @@ pub trait Chain: Send + Sync + 'static { + MaybeDisplay + MaybeSerializeDeserialize + AtLeast32Bit - + Copy; + + Copy + + MaxEncodedLen; /// Signature type, used on this chain. type Signature: Parameter + Verify; From ff4be92029e876f8934629abb53ed20442964a3e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 10 Oct 2022 15:57:02 +0300 Subject: [PATCH 0787/1210] Remove without_storage_info from parachains pallet (#1596) * remove without_storage_info from pallet-bridge-parachains * fix benchmarks --- bin/millau/runtime/src/lib.rs | 4 + modules/grandpa/src/lib.rs | 32 ++++-- modules/grandpa/src/storage_types.rs | 46 +------- modules/parachains/src/lib.rs | 139 +++++++++++++++++++++--- modules/parachains/src/mock.rs | 2 + primitives/chain-rialto/src/lib.rs | 3 + primitives/chain-westend/src/lib.rs | 3 + primitives/parachains/src/lib.rs | 6 +- primitives/runtime/src/lib.rs | 2 + primitives/runtime/src/storage_types.rs | 90 +++++++++++++++ 10 files changed, 258 insertions(+), 69 deletions(-) create mode 100644 primitives/runtime/src/storage_types.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 538417127e362..cb0862bc047f3 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -550,6 +550,8 @@ impl pallet_bridge_messages::Config for Run parameter_types! { pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME; + pub const MaxRialtoParaHeadSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_SIZE; + pub const MaxWestendParaHeadSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_SIZE; } /// Instance of the with-Rialto parachains pallet. @@ -562,6 +564,7 @@ impl pallet_bridge_parachains::Config for Runtime type ParasPalletName = RialtoParasPalletName; type TrackedParachains = frame_support::traits::Everything; type HeadsToKeep = HeadersToKeep; + type MaxParaHeadSize = MaxRialtoParaHeadSize; } /// Instance of the with-Westend parachains pallet. @@ -574,6 +577,7 @@ impl pallet_bridge_parachains::Config for Runtime type ParasPalletName = WestendParasPalletName; type TrackedParachains = frame_support::traits::Everything; type HeadsToKeep = HeadersToKeep; + type MaxParaHeadSize = MaxWestendParaHeadSize; } construct_runtime!( diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index c4cbadcb388f6..37afbf2739ec7 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -36,10 +36,12 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] -use storage_types::{StoredAuthoritySet, StoredBridgedHeader}; +use storage_types::StoredAuthoritySet; use bp_header_chain::{justification::GrandpaJustification, InitializationData}; -use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule}; +use bp_runtime::{ + BlockNumberOf, BoundedStorageValue, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule, +}; use finality_grandpa::voter_set::VoterSet; use frame_support::{ensure, fail}; use frame_system::ensure_signed; @@ -73,6 +75,9 @@ pub type BridgedBlockHash = HashOf<>::BridgedChain>; pub type BridgedBlockHasher = HasherOf<>::BridgedChain>; /// Header of the bridged chain. pub type BridgedHeader = HeaderOf<>::BridgedChain>; +/// Stored header of the bridged chain. +pub type StoredBridgedHeader = + BoundedStorageValue<>::MaxBridgedHeaderSize, BridgedHeader>; #[frame_support::pallet] pub mod pallet { @@ -199,8 +204,18 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; - let finality_target = - StoredBridgedHeader::::try_from_bridged_header(*finality_target)?; + let finality_target = StoredBridgedHeader::::try_from_inner(*finality_target) + .map_err(|e| { + log::error!( + target: LOG_TARGET, + "Size of header {:?} ({}) is larger that the configured value {}", + hash, + e.value_size, + e.maximal_size, + ); + + Error::::TooLargeHeader + })?; >::mutate(|count| *count += 1); insert_header::(finality_target, hash); log::info!( @@ -504,7 +519,8 @@ pub mod pallet { init_params; let authority_set = StoredAuthoritySet::::try_new(authority_list, set_id) .map_err(|_| Error::TooManyAuthoritiesInSet)?; - let header = StoredBridgedHeader::::try_from_bridged_header(*header)?; + let header = StoredBridgedHeader::::try_from_inner(*header) + .map_err(|_| Error::::TooLargeHeader)?; let initial_hash = header.hash(); >::put(initial_hash); @@ -538,7 +554,7 @@ pub mod pallet { ); let hash = header.hash(); insert_header::( - StoredBridgedHeader::try_from_bridged_header(header) + StoredBridgedHeader::::try_from_inner(header) .expect("only used from benchmarks; benchmarks are correct; qed"), hash, ); @@ -553,7 +569,7 @@ impl, I: 'static> Pallet { /// if the pallet has not been initialized yet. pub fn best_finalized() -> Option> { let (_, hash) = >::get()?; - >::get(hash).map(|h| h.0) + >::get(hash).map(|h| h.into_inner()) } /// Check if a particular header is known to the bridge pallet. @@ -1103,7 +1119,7 @@ mod tests { >::put((2, hash)); >::insert( hash, - StoredBridgedHeader::try_from_bridged_header(header).unwrap(), + StoredBridgedHeader::::try_from_inner(header).unwrap(), ); assert_ok!( diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index 5d2cb661d813a..ac4835e4f0d41 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -16,12 +16,12 @@ //! Wrappers for public types that are implementing `MaxEncodedLen` -use crate::{BridgedHeader, Config, Error}; +use crate::Config; use bp_header_chain::AuthoritySet; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound}; -use scale_info::{Type, TypeInfo}; +use frame_support::{BoundedVec, RuntimeDebugNoBound}; +use scale_info::TypeInfo; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; /// A bounded list of Grandpa authorities with associated weights. @@ -64,43 +64,3 @@ impl, I: 'static> From> for AuthoritySet { AuthoritySet { authorities: t.authorities.into(), set_id: t.set_id } } } - -/// A bounded chain header. -#[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebugNoBound)] -pub struct StoredBridgedHeader, I: 'static>(pub BridgedHeader); - -impl, I: 'static> StoredBridgedHeader { - /// Construct `StoredBridgedHeader` from the `BridgedHeader` with all required checks. - pub fn try_from_bridged_header(header: BridgedHeader) -> Result> { - // this conversion is heavy (since we do encoding here), so we may want to optimize it later - // (e.g. by introducing custom Encode implementation, and turning `StoredBridgedHeader` into - // `enum StoredBridgedHeader { Decoded(BridgedHeader), Encoded(Vec) }`) - if header.encoded_size() > T::MaxBridgedHeaderSize::get() as usize { - Err(Error::TooLargeHeader) - } else { - Ok(StoredBridgedHeader(header)) - } - } -} - -impl, I: 'static> sp_std::ops::Deref for StoredBridgedHeader { - type Target = BridgedHeader; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl, I: 'static> TypeInfo for StoredBridgedHeader { - type Identity = Self; - - fn type_info() -> Type { - BridgedHeader::::type_info() - } -} - -impl, I: 'static> MaxEncodedLen for StoredBridgedHeader { - fn max_encoded_len() -> usize { - T::MaxBridgedHeaderSize::get() as usize - } -} diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 290bdadf04a73..ac21e997f3146 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -69,11 +69,15 @@ pub mod pallet { use super::*; use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; use bp_runtime::{ - BasicOperatingMode, OwnedBridgeModule, StorageDoubleMapKeyProvider, StorageMapKeyProvider, + BasicOperatingMode, BoundedStorageValue, OwnedBridgeModule, StorageDoubleMapKeyProvider, + StorageMapKeyProvider, }; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; + /// Stored parachain head of given parachains pallet. + pub type StoredParaHeadOf = + BoundedStorageValue<>::MaxParaHeadSize, ParaHead>; /// Weight info of the given parachains pallet. pub type WeightInfoOf = >::WeightInfo; @@ -94,6 +98,12 @@ pub mod pallet { }, /// The caller has provided obsolete parachain head, which is already known to the pallet. RejectedObsoleteParachainHead { parachain: ParaId, parachain_head_hash: ParaHash }, + /// The caller has provided parachain head that exceeds the maximal configured head size. + RejectedLargeParachainHead { + parachain: ParaId, + parachain_head_hash: ParaHash, + parachain_head_size: u32, + }, /// Parachain head has been updated. UpdatedParachainHead { parachain: ParaId, parachain_head_hash: ParaHash }, } @@ -156,6 +166,17 @@ pub mod pallet { /// Incautious change of this constant may lead to orphan entries in the runtime storage. #[pallet::constant] type HeadsToKeep: Get; + + /// Maximal size (in bytes) of the SCALE-encoded parachain head. + /// + /// Keep in mind that the size of any tracked parachain header must not exceed this value. + /// So if you're going to track multiple parachains, one of which is storing large digests + /// in its headers, you shall choose this maximal value. + /// + /// There's no mandatory headers in this pallet, so it can't stall if there's some header + /// that exceeds this bound. + #[pallet::constant] + type MaxParaHeadSize: Get; } /// Optional pallet owner. @@ -196,7 +217,7 @@ pub mod pallet { ::Key1, ::Hasher2, ::Key2, - ::Value, + StoredParaHeadOf, >; /// A ring buffer of imported parachain head hashes. Ordered by the insertion time. @@ -206,7 +227,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - #[pallet::without_storage_info] pub struct Pallet(PhantomData<(T, I)>); impl, I: 'static> OwnedBridgeModule for Pallet { @@ -381,12 +401,12 @@ pub mod pallet { /// Get best finalized header of the given parachain. pub fn best_parachain_head(parachain: ParaId) -> Option { let best_para_head_hash = ParasInfo::::get(parachain)?.best_head_hash.head_hash; - ImportedParaHeads::::get(parachain, best_para_head_hash) + ImportedParaHeads::::get(parachain, best_para_head_hash).map(|h| h.into_inner()) } /// Get parachain head with given hash. pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option { - ImportedParaHeads::::get(parachain, hash) + ImportedParaHeads::::get(parachain, hash).map(|h| h.into_inner()) } /// Verify that the passed storage proof is valid, given it is crafted using @@ -478,12 +498,13 @@ pub mod pallet { ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order + let err_log_prefix = "The parachain head can't be updated"; let is_valid = Self::validate_updated_parachain_head( parachain, &stored_best_head, updated_at_relay_block_number, updated_head_hash, - "The parachain head can't be updated", + err_log_prefix, ); if !is_valid { Self::deposit_event(Event::RejectedObsoleteParachainHead { @@ -492,6 +513,30 @@ pub mod pallet { }); return Err(()) } + + // verify that the parachain head size is <= `MaxParaHeadSize` + let updated_head = match StoredParaHeadOf::::try_from_inner(updated_head) { + Ok(updated_head) => updated_head, + Err(e) => { + log::trace!( + target: LOG_TARGET, + "{}. The parachain head size for {:?} is {}. It exceeds maximal configured size {}.", + err_log_prefix, + parachain, + e.value_size, + e.maximal_size, + ); + + Self::deposit_event(Event::RejectedLargeParachainHead { + parachain, + parachain_head_hash: updated_head_hash, + parachain_head_size: e.value_size as _, + }); + + return Err(()) + }, + }; + let next_imported_hash_position = stored_best_head .map_or(0, |stored_best_head| stored_best_head.next_imported_hash_position); @@ -575,8 +620,8 @@ pub mod pallet { mod tests { use super::*; use crate::mock::{ - run_test, test_relay_header, Event as TestEvent, Origin, TestRuntime, PARAS_PALLET_NAME, - UNTRACKED_PARACHAIN_ID, + run_test, test_relay_header, Event as TestEvent, Origin, TestRuntime, + MAXIMAL_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; use codec::Encode; @@ -674,6 +719,12 @@ mod tests { ParaHead((parachain, head_number).encode()) } + fn large_head_data(parachain: u32, head_number: u32) -> ParaHead { + ParaHead( + (parachain, head_number, vec![42u8; MAXIMAL_PARACHAIN_HEAD_SIZE as usize]).encode(), + ) + } + fn head_hash(parachain: u32, head_number: u32) -> ParaHash { head_data(parachain, head_number).hash() } @@ -770,18 +821,21 @@ mod tests { ImportedParaHeads::::get( ParaId(1), initial_best_head(1).best_head_hash.head_hash - ), + ) + .map(|h| h.into_inner()), Some(head_data(1, 0)) ); assert_eq!( ImportedParaHeads::::get( ParaId(2), initial_best_head(2).best_head_hash.head_hash - ), + ) + .map(|h| h.into_inner()), None ); assert_eq!( - ImportedParaHeads::::get(ParaId(3), head_hash(3, 10)), + ImportedParaHeads::::get(ParaId(3), head_hash(3, 10)) + .map(|h| h.into_inner()), Some(head_data(3, 10)) ); @@ -830,11 +884,13 @@ mod tests { }) ); assert_eq!( - ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()), + ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()) + .map(|h| h.into_inner()), Some(head_data(1, 5)) ); assert_eq!( - ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()), + ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()) + .map(|h| h.into_inner()), None ); assert_eq!( @@ -863,11 +919,13 @@ mod tests { }) ); assert_eq!( - ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()), + ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()) + .map(|h| h.into_inner()), Some(head_data(1, 5)) ); assert_eq!( - ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()), + ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()) + .map(|h| h.into_inner()), Some(head_data(1, 10)) ); assert_eq!( @@ -1092,6 +1150,57 @@ mod tests { }); } + #[test] + fn does_nothing_when_parachain_head_is_too_large() { + let (state_root, proof, parachains) = + prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (2, large_head_data(1, 5))]); + run_test(|| { + // start with relay block #0 and try to import head#5 of parachain#1 and untracked + // parachain + initialize(state_root); + let result = Pallet::::submit_parachain_heads( + Origin::signed(1), + (0, test_relay_header(0, state_root).hash()), + parachains, + proof, + ); + assert_ok!(result); + assert_eq!( + ParasInfo::::get(ParaId(1)), + Some(ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 0, + head_hash: head_data(1, 5).hash() + }, + next_imported_hash_position: 1, + }) + ); + assert_eq!(ParasInfo::::get(ParaId(2)), None); + assert_eq!( + System::::events(), + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 5).hash(), + }), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::RejectedLargeParachainHead { + parachain: ParaId(2), + parachain_head_hash: large_head_data(1, 5).hash(), + parachain_head_size: large_head_data(1, 5).encoded_size() as u32, + }), + topics: vec![], + }, + ], + ); + }); + } + #[test] fn prunes_old_heads() { run_test(|| { diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index a31fb4c47f90e..f1d39592b20a4 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -36,6 +36,7 @@ type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type HeadsToKeep = HeadsToKeep; + type MaxParaHeadSize = frame_support::traits::ConstU32; } #[derive(Debug)] diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 9698da8877946..257e94d0273c2 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -106,6 +106,9 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 5; /// Maximal SCALE-encoded header size (in bytes) at Rialto. pub const MAX_HEADER_SIZE: u32 = 512; +/// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet. +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; + /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index eeb30709accd7..2fd27094cb50f 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -70,6 +70,9 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; /// some fixed reserve for other things (digest, block hash and number, ...) as well. pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; +/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet. +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; + /// Identifier of Westmint parachain at the Westend relay chain. pub const WESTMINT_PARACHAIN_ID: u32 = 2000; diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index 52b4954897308..f2edebf8a22a7 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -23,13 +23,13 @@ use bp_polkadot_core::{ BlockNumber as RelayBlockNumber, }; use bp_runtime::{StorageDoubleMapKeyProvider, StorageMapKeyProvider}; -use codec::{Decode, Encode}; +use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; use scale_info::TypeInfo; use sp_core::storage::StorageKey; /// Best known parachain head hash. -#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] pub struct BestParaHeadHash { /// Number of relay block where this head has been read. /// @@ -45,7 +45,7 @@ pub struct BestParaHeadHash { } /// Best known parachain head as it is stored in the runtime storage. -#[derive(Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] pub struct ParaInfo { /// Best known parachain head hash. pub best_head_hash: BestParaHeadHash, diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index d775e09c47a00..94a231333ded7 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -40,6 +40,7 @@ pub use storage_proof::{ record_all_keys as record_all_trie_keys, Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker, }; +pub use storage_types::BoundedStorageValue; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; @@ -48,6 +49,7 @@ pub mod messages; mod chain; mod storage_proof; +mod storage_types; // Re-export macro to aviod include paste dependency everywhere pub use sp_runtime::paste; diff --git a/primitives/runtime/src/storage_types.rs b/primitives/runtime/src/storage_types.rs new file mode 100644 index 0000000000000..b37f779d00b32 --- /dev/null +++ b/primitives/runtime/src/storage_types.rs @@ -0,0 +1,90 @@ +// Copyright 2022 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 . + +//! Wrapper for a runtime storage value that checks if value exceeds given maximum +//! during conversion. + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{traits::Get, RuntimeDebug}; +use scale_info::{Type, TypeInfo}; +use sp_std::{marker::PhantomData, ops::Deref}; + +/// Error that is returned when the value size exceeds maximal configured size. +#[derive(RuntimeDebug)] +pub struct MaximalSizeExceededError { + /// Size of the value. + pub value_size: usize, + /// Maximal configured size. + pub maximal_size: usize, +} + +/// A bounded runtime storage value. +#[derive(Clone, Decode, Encode, Eq, PartialEq)] +pub struct BoundedStorageValue { + value: V, + _phantom: PhantomData, +} + +impl sp_std::fmt::Debug for BoundedStorageValue { + fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + self.value.fmt(fmt) + } +} + +impl, V: Encode> BoundedStorageValue { + /// Construct `BoundedStorageValue` from the underlying `value` with all required checks. + /// + /// Returns error if value size exceeds given bounds. + pub fn try_from_inner(value: V) -> Result { + // this conversion is heavy (since we do encoding here), so we may want to optimize it later + // (e.g. by introducing custom Encode implementation, and turning `BoundedStorageValue` into + // `enum BoundedStorageValue { Decoded(V), Encoded(Vec) }`) + let value_size = value.encoded_size(); + let maximal_size = B::get() as usize; + if value_size > maximal_size { + Err(MaximalSizeExceededError { value_size, maximal_size }) + } else { + Ok(BoundedStorageValue { value, _phantom: Default::default() }) + } + } + + /// Convert into the inner type + pub fn into_inner(self) -> V { + self.value + } +} + +impl Deref for BoundedStorageValue { + type Target = V; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +impl TypeInfo for BoundedStorageValue { + type Identity = Self; + + fn type_info() -> Type { + V::type_info() + } +} + +impl, V: Encode> MaxEncodedLen for BoundedStorageValue { + fn max_encoded_len() -> usize { + B::get() as usize + } +} From 5f0a4c68445ac45dc9b26fc34e653cd381f46b2e Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 17 Oct 2022 11:51:08 +0200 Subject: [PATCH 0788/1210] Removed unused AccountId from `trait MessagesBridge` (#1600) --- bin/runtime-common/src/messages.rs | 1 - modules/messages/src/lib.rs | 8 ++------ primitives/messages/src/source_chain.rs | 6 +++--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 50944826ddeae..57f3f38cb2efb 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -532,7 +532,6 @@ pub mod source { /// Runtime message sender adapter. type MessageSender: bp_messages::source_chain::MessagesBridge< OriginOf>, - AccountIdOf>, BalanceOf>, FromThisChainMessagePayload, >; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 0580a0ffdfac5..962fd8f791578 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -775,12 +775,8 @@ pub mod pallet { } impl - bp_messages::source_chain::MessagesBridge< - T::Origin, - T::AccountId, - T::OutboundMessageFee, - T::OutboundPayload, - > for Pallet + bp_messages::source_chain::MessagesBridge + for Pallet where T: Config, I: 'static, diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 5c6283a803602..70b52dc63aab8 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -182,7 +182,7 @@ pub struct SendMessageArtifacts { } /// Messages bridge API to be used from other pallets. -pub trait MessagesBridge { +pub trait MessagesBridge { /// Error type. type Error: Debug; @@ -201,8 +201,8 @@ pub trait MessagesBridge { #[derive(Eq, RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; -impl - MessagesBridge for NoopMessagesBridge +impl MessagesBridge + for NoopMessagesBridge { type Error = &'static str; From 921dbb1e5bb154fe752e1e11947941d1d2ca25a9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 18 Oct 2022 12:10:21 +0300 Subject: [PATCH 0789/1210] increase max header size of Rialto and Millau (512 -> 1024) (#1603) --- modules/grandpa/src/lib.rs | 27 +++++++++++++++++++++++---- primitives/chain-millau/src/lib.rs | 2 +- primitives/chain-rialto/src/lib.rs | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 37afbf2739ec7..b3801beb6f1f2 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -517,12 +517,31 @@ pub mod pallet { ) -> Result<(), Error> { let super::InitializationData { header, authority_list, set_id, operating_mode } = init_params; + let authority_set_length = authority_list.len(); let authority_set = StoredAuthoritySet::::try_new(authority_list, set_id) - .map_err(|_| Error::TooManyAuthoritiesInSet)?; - let header = StoredBridgedHeader::::try_from_inner(*header) - .map_err(|_| Error::::TooLargeHeader)?; - + .map_err(|_| { + log::error!( + target: LOG_TARGET, + "Failed to initialize bridge. Number of authorities in the set {} is larger than the configured value {}", + authority_set_length, + T::MaxBridgedAuthorities::get(), + ); + + Error::TooManyAuthoritiesInSet + })?; let initial_hash = header.hash(); + let header = StoredBridgedHeader::::try_from_inner(*header).map_err(|e| { + log::error!( + target: LOG_TARGET, + "Failed to initialize bridge. Size of header {:?} ({}) is larger that the configured value {}", + initial_hash, + e.value_size, + e.maximal_size, + ); + + Error::::TooLargeHeader + })?; + >::put(initial_hash); >::put(0); insert_header::(header, initial_hash); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 60fe21884487e..e63903aff7d57 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -113,7 +113,7 @@ pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; pub const MAX_AUTHORITIES_COUNT: u32 = 5; /// Maximal SCALE-encoded header size (in bytes) at Millau. -pub const MAX_HEADER_SIZE: u32 = 512; +pub const MAX_HEADER_SIZE: u32 = 1024; /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 257e94d0273c2..d87e82e78a2ff 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -104,7 +104,7 @@ pub const SESSION_LENGTH: BlockNumber = 4; pub const MAX_AUTHORITIES_COUNT: u32 = 5; /// Maximal SCALE-encoded header size (in bytes) at Rialto. -pub const MAX_HEADER_SIZE: u32 = 512; +pub const MAX_HEADER_SIZE: u32 = 1024; /// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet. pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; From 0937c3f19e661f71feb14aa8f3c5d2b240768668 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 18 Oct 2022 13:59:52 +0300 Subject: [PATCH 0790/1210] Fix new nightly clippy issues (#1604) * clipy * revert some fixes that newest clippy reports as issues, but older does not --- bin/millau/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- primitives/messages/src/lib.rs | 2 +- primitives/test-utils/src/lib.rs | 2 +- relays/finality/src/sync_loop_metrics.rs | 2 +- relays/messages/src/relay_strategy/mod.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index cb0862bc047f3..b048bf5e6059c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -423,7 +423,7 @@ parameter_types! { /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a /// week. - pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; + pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS; } parameter_types! { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 161b0319508c6..506806d0aebaa 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -416,7 +416,7 @@ parameter_types! { /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a /// week. - pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS as u32; + pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS; /// Maximal number of authorities at Millau. pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index d5b2b9c9db4f2..8742ff8448d72 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -414,7 +414,7 @@ mod tests { .len(); let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs(); assert!( - difference / (std::cmp::min(actual_size, expected_size.unwrap() as usize) as f64) < 0.1, + difference / (std::cmp::min(actual_size, expected_size.unwrap()) as f64) < 0.1, "Too large difference between actual ({}) and expected ({:?}) inbound lane data size. Test case: {}+{}", actual_size, expected_size, diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 66dbe9e7389e1..e16c43c9816aa 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -112,7 +112,7 @@ pub fn make_justification_for_header( }; // Note: Adding 1 to account for the target header - let chain = generate_chain(i as u32, depth + 1, &header); + let chain = generate_chain(i, depth + 1, &header); // We don't include our finality target header in the vote ancestries for child in &chain[1..] { diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs index a003a47d89096..fcfdbbd99f1b4 100644 --- a/relays/finality/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -72,7 +72,7 @@ impl SyncLoopMetrics { /// Update using-same-fork flag. pub fn update_using_same_fork(&self, using_same_fork: bool) { - self.using_different_forks.set(if using_same_fork { 0 } else { 1 }) + self.using_different_forks.set((!using_same_fork).into()) } } diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs index 7bfd74c4790f8..aa28e63582fd7 100644 --- a/relays/messages/src/relay_strategy/mod.rs +++ b/relays/messages/src/relay_strategy/mod.rs @@ -144,7 +144,7 @@ impl< (self.hard_selected_begin_nonce + self.index as MessageNonce), self.selected_prepaid_nonces, self.selected_unpaid_weight, - self.selected_size as u32, + self.selected_size, ) .await?; From 40666343d1d19eafdc45cac6246688e334352259 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 20 Oct 2022 10:27:23 +0300 Subject: [PATCH 0791/1210] Bump Substrate/Polkadot/Cumulus refs (aka Weights v1.5) (#1597) * update Substrate + Polkadot + Cumulus refs * Origin -> RuntimeOrigin * weights v1.5 * update refs once again + `cargo test -p pallet-bridge-grandpa` works * started work on `cargo test -p pallet-bridge-messages` * cargo test -p pallet-bridge-relayers * cargo test -p pallet-bridge-parachains * cargo test -p millau-runtime * cargo test -p bridge-runtime-common * cargo test -p rialto-runtime * cargo test -p rialto-parachain-runtime * cargo test -p millau-bridge-node * cargo test -p rialto-bridge-node * cargo test -p rialto-parachain-collator * cargo test -p messages-relay * cargo test -p parachains-relay * cargo test -p substrate-relay * cargo test --all * cargo check -p millau-runtime --locked --features runtime-benchmarks * fix remaining test * fmt * try to allow clippy failure temporarily * Revert "try to allow clippy failure temporarily" This reverts commit d1b6593580f07e0dbeecb7ab0aa92cee98888ed3. * use min_by * Revert "use min_by" This reverts commit 33042f49ed37e8dd0505370289e17f03bf1a56ee. * Revert "Revert "use min_by"" This reverts commit 1d2204f0b14dc81e5650bb574dedb5fa78c7097d. * trigger CI * Revert "trigger CI" This reverts commit 259d91b5606743bba9d043c69f07eac6c8700ef5. * new day, new clippy warning * more clippy issues --- bin/millau/node/src/service.rs | 53 ++-- bin/millau/runtime/src/lib.rs | 68 +++-- bin/millau/runtime/src/rialto_messages.rs | 47 ++-- .../runtime/src/rialto_parachain_messages.rs | 45 ++-- bin/millau/runtime/src/xcm_config.rs | 45 ++-- bin/rialto-parachain/node/src/command.rs | 2 +- bin/rialto-parachain/node/src/service.rs | 12 +- bin/rialto-parachain/runtime/src/lib.rs | 91 ++++--- .../runtime/src/millau_messages.rs | 47 ++-- bin/rialto/node/Cargo.toml | 1 + bin/rialto/node/src/chain_spec.rs | 3 +- bin/rialto/runtime/src/lib.rs | 74 ++++-- bin/rialto/runtime/src/millau_messages.rs | 46 ++-- bin/rialto/runtime/src/parachains.rs | 70 +++-- bin/rialto/runtime/src/xcm_config.rs | 47 ++-- bin/runtime-common/src/integrity.rs | 6 +- bin/runtime-common/src/lib.rs | 4 +- bin/runtime-common/src/messages.rs | 121 +++++---- bin/runtime-common/src/messages_api.rs | 2 +- .../src/messages_benchmarking.rs | 4 +- bin/runtime-common/src/messages_extension.rs | 10 +- modules/grandpa/src/extension.rs | 19 +- modules/grandpa/src/lib.rs | 56 ++-- modules/grandpa/src/mock.rs | 8 +- modules/grandpa/src/storage_types.rs | 2 +- modules/grandpa/src/weights.rs | 20 +- modules/messages/src/inbound_lane.rs | 2 +- modules/messages/src/lib.rs | 242 ++++++++++-------- modules/messages/src/mock.rs | 42 +-- modules/messages/src/weights.rs | 174 ++++++------- modules/messages/src/weights_ext.rs | 47 ++-- modules/parachains/src/extension.rs | 19 +- modules/parachains/src/lib.rs | 33 +-- modules/parachains/src/mock.rs | 10 +- modules/parachains/src/weights.rs | 44 ++-- modules/parachains/src/weights_ext.rs | 7 +- modules/relayers/src/lib.rs | 14 +- modules/relayers/src/mock.rs | 12 +- modules/relayers/src/payment_adapter.rs | 4 +- modules/relayers/src/weights.rs | 12 +- modules/shift-session-manager/src/lib.rs | 10 +- primitives/chain-millau/Cargo.toml | 2 +- primitives/chain-millau/src/lib.rs | 36 +-- primitives/chain-rialto-parachain/src/lib.rs | 36 +-- primitives/chain-rialto/src/lib.rs | 36 +-- primitives/chain-westend/src/lib.rs | 7 +- primitives/messages/src/source_chain.rs | 7 +- primitives/messages/src/target_chain.rs | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/polkadot-core/src/lib.rs | 16 +- primitives/runtime/src/lib.rs | 6 +- primitives/test-utils/src/lib.rs | 18 +- relays/bin-substrate/src/chains/millau.rs | 6 +- relays/bin-substrate/src/chains/mod.rs | 10 +- relays/bin-substrate/src/chains/rialto.rs | 4 +- .../src/chains/rialto_parachain.rs | 12 +- relays/client-millau/src/lib.rs | 4 +- relays/client-rialto-parachain/src/lib.rs | 2 +- relays/client-rialto/src/lib.rs | 4 +- .../src/transaction_tracker.rs | 2 +- .../lib-substrate-relay/src/messages_lane.rs | 22 +- .../src/messages_source.rs | 4 +- .../src/messages_target.rs | 25 +- relays/messages/src/message_lane_loop.rs | 10 +- relays/messages/src/message_race_delivery.rs | 25 +- .../relay_strategy/enforcement_strategy.rs | 11 +- 66 files changed, 991 insertions(+), 893 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 5b4461f3ca642..72ad071726b50 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -18,7 +18,7 @@ use jsonrpsee::RpcModule; use millau_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::{BlockBackend, ExecutorProvider}; +use sc_client_api::BlockBackend; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; use sc_finality_grandpa::SharedVoterState; @@ -140,7 +140,7 @@ pub fn new_partial( let slot_duration = sc_consensus_aura::slot_duration(&*client)?; let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { + sc_consensus_aura::import_queue::(ImportQueueParams { block_import: beefy_block_import, justification_import: Some(Box::new(grandpa_block_import.clone())), client: client.clone(), @@ -153,12 +153,9 @@ pub fn new_partial( slot_duration, ); - Ok((timestamp, slot)) + Ok((slot, timestamp)) }, spawner: &task_manager.spawn_essential_handle(), - can_author_with: sp_consensus::CanAuthorWithNativeVersion::new( - client.executor().clone(), - ), registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -207,6 +204,8 @@ pub fn new_full(mut config: Configuration) -> Result }; } + let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); + // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change // anything in terms of behaviour, but makes the logs more consistent with the other // Substrate nodes. @@ -219,14 +218,21 @@ pub fn new_full(mut config: Configuration) -> Result .extra_sets .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); - let beefy_protocol_name = beefy_gadget::protocol_standard_name( - &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), - &config.chain_spec, - ); + let beefy_gossip_proto_name = + beefy_gadget::gossip_protocol_name(genesis_hash, config.chain_spec.fork_id()); + // `beefy_on_demand_justifications_handler` is given to `beefy-gadget` task to be run, + // while `beefy_req_resp_cfg` is added to `config.network.request_response_protocols`. + let (beefy_on_demand_justifications_handler, beefy_req_resp_cfg) = + beefy_gadget::communication::request_response::BeefyJustifsRequestHandler::new( + genesis_hash, + config.chain_spec.fork_id(), + client.clone(), + ); config .network .extra_sets - .push(beefy_gadget::beefy_peers_set_config(beefy_protocol_name.clone())); + .push(beefy_gadget::communication::beefy_peers_set_config(beefy_gossip_proto_name.clone())); + config.network.request_response_protocols.push(beefy_req_resp_cfg); let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), @@ -234,7 +240,7 @@ pub fn new_full(mut config: Configuration) -> Result Vec::default(), )); - let (network, system_rpc_tx, network_starter) = + let (network, system_rpc_tx, tx_handler_controller, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -327,6 +333,7 @@ pub fn new_full(mut config: Configuration) -> Result backend: backend.clone(), system_rpc_tx, config, + tx_handler_controller, telemetry: telemetry.as_mut(), })?; @@ -339,12 +346,9 @@ pub fn new_full(mut config: Configuration) -> Result telemetry.as_ref().map(|x| x.handle()), ); - let can_author_with = - sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()); - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let aura = sc_consensus_aura::start_aura::( + let aura = sc_consensus_aura::start_aura::( StartAuraParams { slot_duration, client: client.clone(), @@ -360,12 +364,11 @@ pub fn new_full(mut config: Configuration) -> Result slot_duration, ); - Ok((timestamp, slot)) + Ok((slot, timestamp)) }, force_authoring, backoff_authoring_blocks, keystore: keystore_container.sync_keystore(), - can_author_with, sync_oracle: network.clone(), justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), @@ -386,23 +389,31 @@ pub fn new_full(mut config: Configuration) -> Result let keystore = if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; + let justifications_protocol_name = beefy_on_demand_justifications_handler.protocol_name(); + let payload_provider = beefy_primitives::mmr::MmrRootProvider::new(client.clone()); let beefy_params = beefy_gadget::BeefyParams { client: client.clone(), backend, + payload_provider, runtime: client, key_store: keystore.clone(), - network: network.clone(), + network_params: beefy_gadget::BeefyNetworkParams { + network: network.clone(), + gossip_protocol_name: beefy_gossip_proto_name, + justifications_protocol_name, + _phantom: core::marker::PhantomData::, + }, min_block_delta: 2, prometheus_registry: prometheus_registry.clone(), - protocol_name: beefy_protocol_name, links: beefy_voter_links, + on_demand_justifications_handler: beefy_on_demand_justifications_handler, }; // Start the BEEFY bridge gadget. task_manager.spawn_essential_handle().spawn_blocking( "beefy-gadget", None, - beefy_gadget::start_beefy_gadget::<_, _, _, _, _>(beefy_params), + beefy_gadget::start_beefy_gadget::<_, _, _, _, _, _>(beefy_params), ); let grandpa_config = sc_finality_grandpa::Config { diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b048bf5e6059c..6439c04565571 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -69,11 +69,12 @@ pub use bridge_runtime_common; // A few exports that help ease life for downstream crates. pub use frame_support::{ - construct_runtime, parameter_types, + construct_runtime, + dispatch::DispatchClass, + parameter_types, traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, weights::{ - constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, IdentityFee, - RuntimeDbWeight, Weight, + constants::WEIGHT_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, }, RuntimeDebug, StorageValue, }; @@ -177,7 +178,7 @@ impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. - type Call = Call; + type RuntimeCall = RuntimeCall; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = IdentityLookup; /// The index type for storing how many extrinsics an account has signed. @@ -191,9 +192,9 @@ impl frame_system::Config for Runtime { /// The header type. type Header = generic::Header; /// The ubiquitous event type. - type Event = Event; + type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; /// Version of the runtime. @@ -241,8 +242,7 @@ impl pallet_beefy::Config for Runtime { } impl pallet_grandpa::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; type KeyOwnerProofSystem = (); type KeyOwnerProof = >::Proof; @@ -331,7 +331,7 @@ impl pallet_balances::Config for Runtime { /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type. - type Event = Event; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; @@ -351,6 +351,7 @@ parameter_types! { pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); + pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); } impl pallet_transaction_payment::Config for Runtime { @@ -363,13 +364,14 @@ impl pallet_transaction_payment::Config for Runtime { TargetBlockFullness, AdjustmentVariable, MinimumMultiplier, + MaximumMultiplier, >; - type Event = Event; + type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; } parameter_types! { @@ -379,7 +381,7 @@ parameter_types! { } impl pallet_session::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; type ValidatorIdOf = (); type ShouldEndSession = pallet_session::PeriodicSessions; @@ -400,7 +402,7 @@ parameter_types! { } impl pallet_bridge_relayers::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = bp_relayers::MintReward, AccountId>; type WeightInfo = (); @@ -470,7 +472,7 @@ parameter_types! { bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Millau => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; + bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() as _; pub const RootAccountForPayments: Option = None; pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; pub const RialtoParachainChainId: bp_runtime::ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; @@ -480,7 +482,7 @@ parameter_types! { pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = rialto_messages::MillauToRialtoMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; @@ -515,7 +517,7 @@ impl pallet_bridge_messages::Config for Runtime { pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1; impl pallet_bridge_messages::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = rialto_parachain_messages::MillauToRialtoParachainMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; @@ -558,7 +560,7 @@ parameter_types! { pub type WithRialtoParachainsInstance = (); impl pallet_bridge_parachains::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; type ParasPalletName = RialtoParasPalletName; @@ -571,7 +573,7 @@ impl pallet_bridge_parachains::Config for Runtime pub type WithWestendParachainsInstance = pallet_bridge_parachains::Instance1; impl pallet_bridge_parachains::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; @@ -626,7 +628,7 @@ construct_runtime!( ); generate_bridge_reject_obsolete_headers_and_messages! { - Call, AccountId, + RuntimeCall, AccountId, // Grandpa BridgeRialtoGrandpa, BridgeWestendGrandpa, // Parachains @@ -658,11 +660,12 @@ pub type SignedExtra = ( BridgeRejectObsoleteHeadersAndMessages, ); /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; +pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -821,6 +824,23 @@ impl_runtime_apis! { .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) } + fn generate_historical_batch_proof( + leaf_indices: Vec, + leaves_count: mmr::LeafIndex, + ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { + Mmr::generate_historical_batch_proof(leaf_indices, leaves_count).map( + |(leaves, proof)| { + ( + leaves + .into_iter() + .map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)) + .collect(), + proof, + ) + }, + ) + } + fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) -> Result<(), mmr::Error> { @@ -1151,6 +1171,6 @@ mod tests { BRIDGES_PALLETS_MAX_CALL_SIZE ); const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests - assert!(core::mem::size_of::() <= MAX_CALL_SIZE); + assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index f043f8b9d4316..bb9f5dfe757e7 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{Call, OriginCaller, Runtime}; +use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::{SenderOrigin, TargetHeaderChain}, @@ -28,11 +28,7 @@ use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; use codec::{Decode, Encode}; -use frame_support::{ - parameter_types, - weights::{DispatchClass, Weight}, - RuntimeDebug, -}; +use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; @@ -47,13 +43,18 @@ pub const INITIAL_RIALTO_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(Fixed /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; parameter_types! { /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE; /// Fee multiplier value at Rialto chain. pub storage RialtoFeeMultiplier: FixedU128 = INITIAL_RIALTO_FEE_MULTIPLIER; + /// Weight credit for our test messages. + /// + /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + /// (it is prepended with `UniversalOrigin` instruction). + pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); } /// Message payload for Millau -> Rialto messages. @@ -64,7 +65,7 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Messages proof for Rialto -> Millau messages. pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -78,9 +79,7 @@ pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDi WithRialtoMessageBridge, xcm_executor::XcmExecutor, crate::xcm_config::XcmWeigher, - // 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - // (it is prepended with `UniversalOrigin` instruction) - frame_support::traits::ConstU64, + WeightCredit, >; /// Maximal outbound payload size of Millau -> Rialto messages. @@ -120,21 +119,20 @@ impl messages::ChainWithMessages for Millau { type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; - type Weight = Weight; type Balance = bp_millau::Balance; } impl messages::ThisChainWithMessages for Millau { - type Origin = crate::Origin; - type Call = crate::Call; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< Self::AccountId, - { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_rialto::EXTRA_STORAGE_PROOF_SIZE }, { bp_millau::TX_EXTRA_BYTES }, >; - fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { let here_location = xcm::v3::MultiLocation::from(crate::xcm_config::UniversalLocation::get()); match send_origin.caller { @@ -168,7 +166,7 @@ impl messages::ThisChainWithMessages for Millau { bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -183,7 +181,6 @@ impl messages::ChainWithMessages for Rialto { type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; - type Weight = Weight; type Balance = bp_rialto::Balance; } @@ -202,15 +199,15 @@ impl messages::BridgedChainWithMessages for Rialto { message_dispatch_weight: Weight, ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + let extra_bytes_in_payload = message_payload_len + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); MessageTransaction { - dispatch_weight: extra_bytes_in_payload - .saturating_mul(bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + dispatch_weight: bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT + .saturating_mul(extra_bytes_in_payload as u64) .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) .saturating_sub(if include_pay_dispatch_fee_cost { - 0 + Weight::from_ref_time(0) } else { bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT }) @@ -230,7 +227,7 @@ impl messages::BridgedChainWithMessages for Rialto { bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -280,7 +277,7 @@ impl SourceHeaderChain for Rialto { } } -impl SenderOrigin for crate::Origin { +impl SenderOrigin for RuntimeOrigin { fn linked_account(&self) -> Option { // XCM deals wit fees in our deployments None diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index f26e0d1006ae4..cce7aa79bad25 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> RialtoParachain messages. -use crate::Runtime; +use crate::{Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, @@ -29,11 +29,7 @@ use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; use codec::{Decode, Encode}; -use frame_support::{ - parameter_types, - weights::{DispatchClass, Weight}, - RuntimeDebug, -}; +use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; @@ -43,7 +39,7 @@ pub const DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN: LaneId = [0, 0, 0, 0]; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; /// Initial value of `RialtoParachainToMillauConversionRate` parameter. pub const INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE: FixedU128 = @@ -57,6 +53,11 @@ parameter_types! { pub storage RialtoParachainToMillauConversionRate: FixedU128 = INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE; /// Fee multiplier value at RialtoParachain chain. pub storage RialtoParachainFeeMultiplier: FixedU128 = INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER; + /// Weight credit for our test messages. + /// + /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + /// (it is prepended with `UniversalOrigin` instruction). + pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); } /// Message payload for Millau -> RialtoParachain messages. @@ -68,7 +69,7 @@ pub type ToRialtoParachainMessageVerifier = /// Message payload for RialtoParachain -> Millau messages. pub type FromRialtoParachainMessagePayload = - messages::target::FromBridgedChainMessagePayload; + messages::target::FromBridgedChainMessagePayload; /// Messages proof for RialtoParachain -> Millau messages. type FromRialtoParachainMessagesProof = @@ -83,9 +84,7 @@ pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChain WithRialtoParachainMessageBridge, xcm_executor::XcmExecutor, crate::xcm_config::XcmWeigher, - // 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - // (it is prepended with `UniversalOrigin` instruction) - frame_support::traits::ConstU64, + WeightCredit, >; /// Maximal outbound payload size of Millau -> RialtoParachain messages. @@ -125,21 +124,20 @@ impl messages::ChainWithMessages for Millau { type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; - type Weight = Weight; type Balance = bp_millau::Balance; } impl messages::ThisChainWithMessages for Millau { - type Call = crate::Call; - type Origin = crate::Origin; + type RuntimeCall = RuntimeCall; + type RuntimeOrigin = RuntimeOrigin; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< Self::AccountId, - { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE }, { bp_millau::TX_EXTRA_BYTES }, >; - fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { *lane == DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN || *lane == [0, 0, 0, 1] } @@ -157,7 +155,7 @@ impl messages::ThisChainWithMessages for Millau { bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -172,7 +170,6 @@ impl messages::ChainWithMessages for RialtoParachain { type AccountId = bp_rialto_parachain::AccountId; type Signer = bp_rialto_parachain::AccountSigner; type Signature = bp_rialto_parachain::Signature; - type Weight = Weight; type Balance = bp_rialto_parachain::Balance; } @@ -191,15 +188,15 @@ impl messages::BridgedChainWithMessages for RialtoParachain { message_dispatch_weight: Weight, ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + let extra_bytes_in_payload = message_payload_len + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); MessageTransaction { - dispatch_weight: extra_bytes_in_payload - .saturating_mul(bp_rialto_parachain::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + dispatch_weight: bp_rialto_parachain::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT + .saturating_mul(extra_bytes_in_payload as _) .saturating_add(bp_rialto_parachain::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) .saturating_sub(if include_pay_dispatch_fee_cost { - 0 + Weight::from_ref_time(0) } else { bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT }) @@ -223,7 +220,7 @@ impl messages::BridgedChainWithMessages for RialtoParachain { .base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 88398345d4ad0..9a5851c8d0552 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -21,7 +21,7 @@ use super::{ rialto_parachain_messages::{ WithRialtoParachainMessageBridge, DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN, }, - AccountId, AllPalletsWithSystem, Balances, Call, Event, Origin, Runtime, + AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmPallet, }; use bp_messages::LaneId; @@ -34,12 +34,11 @@ use bridge_runtime_common::{ use frame_support::{ parameter_types, traits::{Everything, Nothing}, - weights::Weight, }; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, SignedAccountId32AsNative, + CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; @@ -60,7 +59,7 @@ parameter_types! { /// Since Kusama is a top-level relay-chain with its own consensus, it's just our network ID. pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); /// The check account, which holds any native assets that have been teleported out and not back in (yet). - pub CheckAccount: AccountId = XcmPallet::check_account(); + pub CheckAccount: (AccountId, MintLocation) = (XcmPallet::check_account(), MintLocation::Local); } /// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to @@ -90,17 +89,17 @@ pub type LocalAssetTransactor = XcmCurrencyAdapter< /// The means that we convert the XCM message origin location into a local dispatch origin. type LocalOriginConverter = ( // A `Signed` origin of the sovereign account that the original location controls. - SovereignSignedViaLocation, + SovereignSignedViaLocation, // The AccountId32 location type can be expressed natively as a `Signed` origin. - SignedAccountId32AsNative, + SignedAccountId32AsNative, ); /// The amount of weight an XCM operation takes. This is a safe overestimate. -pub const BASE_XCM_WEIGHT: Weight = 1_000_000_000; +pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const BaseXcmWeight: Weight = BASE_XCM_WEIGHT; + pub const BaseXcmWeight: u64 = BASE_XCM_WEIGHT; /// Maximum number of instructions in a single XCM fragment. A sanity check against weight /// calculations getting too crazy. pub const MaxInstructions: u32 = 100; @@ -130,11 +129,11 @@ pub type Barrier = ( ); /// XCM weigher type. -pub type XcmWeigher = xcm_builder::FixedWeightBounds; +pub type XcmWeigher = xcm_builder::FixedWeightBounds; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type Call = Call; + type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; @@ -156,26 +155,26 @@ impl xcm_executor::Config for XcmConfig { type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; - type CallDispatcher = Call; + type CallDispatcher = RuntimeCall; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior /// location of this chain. pub type LocalOriginToLocation = ( // Usual Signed origin to be used in XCM as a corresponding AccountId32 - SignedToAccountId32, + SignedToAccountId32, ); impl pallet_xcm::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; // We don't allow any messages to be sent via the transaction yet. This is basically safe to // enable, (safe the possibility of someone spamming the parachain if they're willing to pay // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will // make `DescendOrigin` a bit more useful. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmExecuteFilter = Everything; type XcmExecutor = xcm_executor::XcmExecutor; // Anyone is able to use teleportation regardless of who they are and what they want to @@ -186,8 +185,8 @@ impl pallet_xcm::Config for Runtime { type XcmReserveTransferFilter = Everything; type Weigher = XcmWeigher; type UniversalLocation = UniversalLocation; - type Origin = Origin; - type Call = Call; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type Currency = Balances; @@ -253,6 +252,7 @@ impl XcmBridge for ToRialtoParachainBridge { #[cfg(test)] mod tests { use super::*; + use crate::rialto_messages::WeightCredit; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, @@ -295,13 +295,13 @@ mod tests { WithRialtoMessageBridge, XcmExecutor, XcmWeigher, - frame_support::traits::ConstU64, + WeightCredit, >; new_test_ext().execute_with(|| { let location: MultiLocation = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))).into(); - let xcm: Xcm = vec![Instruction::Trap(42)].into(); + let xcm: Xcm = vec![Instruction::Trap(42)].into(); let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, @@ -309,7 +309,10 @@ mod tests { }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, 1_000_000_000); + assert_eq!( + dispatch_weight, + frame_support::weights::Weight::from_ref_time(1_000_000_000) + ); let dispatch_result = MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); @@ -317,7 +320,7 @@ mod tests { dispatch_result, MessageDispatchResult { dispatch_result: true, - unspent_weight: 0, + unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } ); diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index 6afae824a74ce..533e731b3ac9d 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -354,7 +354,7 @@ impl CliConfiguration for RelayChainCli { fn base_path(&self) -> Result> { Ok(self .shared_params() - .base_path() + .base_path()? .or_else(|| self.base_path.clone().map(Into::into))) } diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index e55f89bacf70a..f97c2fcd7c45e 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -40,7 +40,6 @@ use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain; use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; // Substrate Imports -use sc_client_api::ExecutorProvider; use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; use sc_network::{NetworkBlock, NetworkService}; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; @@ -289,7 +288,7 @@ where let prometheus_registry = parachain_config.prometheus_registry().cloned(); let transaction_pool = params.transaction_pool.clone(); let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); - let (network, system_rpc_tx, start_network) = + let (network, system_rpc_tx, tx_handler_controller, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { config: ¶chain_config, client: client.clone(), @@ -318,6 +317,7 @@ where backend: backend.clone(), network: network.clone(), system_rpc_tx, + tx_handler_controller, telemetry: telemetry.as_mut(), })?; @@ -401,10 +401,9 @@ pub fn parachain_build_import_queue( _, _, _, - _, >(cumulus_client_consensus_aura::ImportQueueParams { block_import: client.clone(), - client: client.clone(), + client, create_inherent_data_providers: move |_, _| async move { let time = sp_timestamp::InherentDataProvider::from_system_time(); @@ -414,10 +413,9 @@ pub fn parachain_build_import_queue( slot_duration, ); - Ok((time, slot)) + Ok((slot, time)) }, registry: config.prometheus_registry(), - can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), spawner: &task_manager.spawn_essential_handle(), telemetry, }) @@ -496,7 +494,7 @@ pub async fn start_node( "Failed to create parachain inherent", ) })?; - Ok((time, slot, parachain_inherent)) + Ok((slot, time, parachain_inherent)) } }, block_import: client.clone(), diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 752270f04c382..c427bfac59a84 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -52,11 +52,13 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. use bp_runtime::{HeaderId, HeaderIdProvider}; pub use frame_support::{ - construct_runtime, match_types, parameter_types, + construct_runtime, + dispatch::DispatchClass, + match_types, parameter_types, traits::{Everything, IsInVec, Nothing, Randomness}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, - DispatchClass, IdentityFee, Weight, + IdentityFee, Weight, }, StorageValue, }; @@ -114,9 +116,10 @@ pub type SignedExtra = ( pallet_transaction_payment::ChargeTransactionPayment, ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; +pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -188,7 +191,7 @@ impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. - type Call = Call; + type RuntimeCall = RuntimeCall; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The index type for storing how many extrinsics an account has signed. @@ -202,9 +205,9 @@ impl frame_system::Config for Runtime { /// The header type. type Header = generic::Header; /// The ubiquitous event type. - type Event = Event; + type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; /// Runtime version. @@ -259,7 +262,7 @@ impl pallet_balances::Config for Runtime { /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type. - type Event = Event; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; @@ -275,21 +278,21 @@ impl pallet_transaction_payment::Config for Runtime { type WeightToFee = IdentityFee; type LengthToFee = IdentityFee; type FeeMultiplierUpdate = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { - type Call = Call; - type Event = Event; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; } parameter_types! { - pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); } impl cumulus_pallet_parachain_system::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; @@ -309,7 +312,7 @@ impl pallet_randomness_collective_flip::Config for Runtime {} parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); - pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub RelayOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); /// The Millau network ID. pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); @@ -350,31 +353,31 @@ pub type XcmOriginToTransactDispatchOrigin = ( // Sovereign account converter; this attempts to derive an `AccountId` from the origin location // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, + SovereignSignedViaLocation, // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when // recognised. - RelayChainAsNative, + RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when // recognised. - SiblingParachainAsNative, + SiblingParachainAsNative, // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a // transaction from the Root origin. - ParentAsSuperuser, + ParentAsSuperuser, // Native signed account converter; this just converts an `AccountId32` origin into a normal // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, + SignedAccountId32AsNative, // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, + XcmPassthrough, ); // TODO: until https://github.com/paritytech/parity-bridges-common/issues/1417 is fixed (in either way), // the following constant must match the similar constant in the Millau runtime. /// One XCM operation is `1_000_000_000` weight - almost certainly a conservative estimate. -pub const BASE_XCM_WEIGHT: Weight = 1_000_000_000; +pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; parameter_types! { - pub UnitWeightCost: Weight = BASE_XCM_WEIGHT; + pub UnitWeightCost: u64 = BASE_XCM_WEIGHT; // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; @@ -397,11 +400,11 @@ pub type Barrier = ( ); /// XCM weigher type. -pub type XcmWeigher = FixedWeightBounds; +pub type XcmWeigher = FixedWeightBounds; pub struct XcmConfig; impl Config for XcmConfig { - type Call = Call; + type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = LocalAssetTransactor; type OriginConverter = XcmOriginToTransactDispatchOrigin; @@ -422,11 +425,11 @@ impl Config for XcmConfig { type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; - type CallDispatcher = Call; + type CallDispatcher = RuntimeCall; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. -pub type LocalOriginToLocation = SignedToAccountId32; +pub type LocalOriginToLocation = SignedToAccountId32; /// The means for routing XCM messages which are not for local execution into the right message /// queues. @@ -462,17 +465,17 @@ impl XcmBridge for ToMillauBridge { } impl pallet_xcm::Config for Runtime { - type Event = Event; - type SendXcmOrigin = EnsureXcmOrigin; + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; + type ExecuteXcmOrigin = EnsureXcmOrigin; type XcmExecuteFilter = Everything; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; type Weigher = XcmWeigher; - type Origin = Origin; - type Call = Call; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type Currency = Balances; @@ -484,12 +487,12 @@ impl pallet_xcm::Config for Runtime { } impl cumulus_pallet_xcm::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; } impl cumulus_pallet_xcmp_queue::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; type VersionWrapper = (); @@ -501,7 +504,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { } impl cumulus_pallet_dmp_queue::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; type ExecuteOverweightOrigin = frame_system::EnsureRoot; } @@ -513,7 +516,7 @@ impl pallet_aura::Config for Runtime { } impl pallet_bridge_relayers::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = bp_relayers::MintReward, AccountId>; type WeightInfo = (); @@ -556,7 +559,7 @@ parameter_types! { bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Rialto => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = - bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; + bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() as _; pub const RootAccountForPayments: Option = None; pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; } @@ -565,7 +568,7 @@ parameter_types! { pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = millau_messages::RialtoParachainToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; @@ -856,6 +859,7 @@ cumulus_pallet_parachain_system::register_validate_block!( #[cfg(test)] mod tests { use super::*; + use crate::millau_messages::WeightCredit; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, @@ -892,13 +896,13 @@ mod tests { WithMillauMessageBridge, XcmExecutor, XcmWeigher, - frame_support::traits::ConstU64, + WeightCredit, >; new_test_ext().execute_with(|| { let location: MultiLocation = (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); - let xcm: Xcm = vec![Instruction::Trap(42)].into(); + let xcm: Xcm = vec![Instruction::Trap(42)].into(); let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, @@ -906,7 +910,10 @@ mod tests { }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, 1_000_000_000); + assert_eq!( + dispatch_weight, + frame_support::weights::Weight::from_ref_time(1_000_000_000) + ); let dispatch_result = MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); @@ -914,7 +921,7 @@ mod tests { dispatch_result, MessageDispatchResult { dispatch_result: true, - unspent_weight: 0, + unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } ); diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 96ff18810bcf4..14dc922e19c6e 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -19,7 +19,7 @@ // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // Should be extracted to a separate crate and reused here. -use crate::{OriginCaller, Runtime}; +use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::{SenderOrigin, TargetHeaderChain}, @@ -31,11 +31,7 @@ use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; use codec::{Decode, Encode}; -use frame_support::{ - parameter_types, - weights::{DispatchClass, Weight}, - RuntimeDebug, -}; +use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; @@ -50,13 +46,18 @@ pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(Fixed /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::BASE_XCM_WEIGHT; parameter_types! { /// Millau to RialtoParachain conversion rate. Initially we treat both tokens as equal. pub storage MillauToRialtoParachainConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE; /// Fee multiplier value at Millau chain. pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER; + /// Weight credit for our test messages. + /// + /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + /// (it is prepended with `UniversalOrigin` instruction). + pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); } /// Message payload for RialtoParachain -> Millau messages. @@ -67,16 +68,14 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> RialtoParachain messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithMillauMessageBridge, xcm_executor::XcmExecutor, crate::XcmWeigher, - // 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - // (it is prepended with `UniversalOrigin` instruction) - frame_support::traits::ConstU64, + WeightCredit, >; /// Messages proof for Millau -> RialtoParachain messages. @@ -124,21 +123,20 @@ impl messages::ChainWithMessages for RialtoParachain { type AccountId = bp_rialto_parachain::AccountId; type Signer = bp_rialto_parachain::AccountSigner; type Signature = bp_rialto_parachain::Signature; - type Weight = Weight; type Balance = bp_rialto_parachain::Balance; } impl messages::ThisChainWithMessages for RialtoParachain { - type Call = crate::Call; - type Origin = crate::Origin; + type RuntimeCall = RuntimeCall; + type RuntimeOrigin = RuntimeOrigin; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< Self::AccountId, - { bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, { bp_rialto_parachain::TX_EXTRA_BYTES }, >; - fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { let here_location = xcm::v3::MultiLocation::from(crate::UniversalLocation::get()); match send_origin.caller { OriginCaller::PolkadotXcm(pallet_xcm::Origin::Xcm(ref location)) @@ -175,7 +173,7 @@ impl messages::ThisChainWithMessages for RialtoParachain { .base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -190,7 +188,6 @@ impl messages::ChainWithMessages for Millau { type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; - type Weight = Weight; type Balance = bp_millau::Balance; } @@ -209,15 +206,15 @@ impl messages::BridgedChainWithMessages for Millau { message_dispatch_weight: Weight, ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + let extra_bytes_in_payload = message_payload_len + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); MessageTransaction { - dispatch_weight: extra_bytes_in_payload - .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + dispatch_weight: bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT + .saturating_mul(extra_bytes_in_payload as u64) .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) .saturating_sub(if include_pay_dispatch_fee_cost { - 0 + Weight::from_ref_time(0) } else { bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT }) @@ -237,7 +234,7 @@ impl messages::BridgedChainWithMessages for Millau { bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -287,7 +284,7 @@ impl SourceHeaderChain for Millau { } } -impl SenderOrigin for crate::Origin { +impl SenderOrigin for RuntimeOrigin { fn linked_account(&self) -> Option { match self.caller { crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 6a0a1e946c811..688279afc7327 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -21,6 +21,7 @@ rialto-runtime = { path = "../runtime" } beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 41958aaf3907d..ffd7bafaa8377 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use beefy_primitives::crypto::AuthorityId as BeefyId; +use frame_support::weights::Weight; use polkadot_primitives::v2::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, @@ -252,7 +253,7 @@ fn testnet_genesis( max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, max_downward_message_size: 1024 * 1024, - ump_service_total_weight: 100_000_000_000, + ump_service_total_weight: Weight::from_ref_time(100_000_000_000), max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 506806d0aebaa..ff7ad88725c23 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -63,9 +63,11 @@ use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. pub use frame_support::{ - construct_runtime, parameter_types, + construct_runtime, + dispatch::DispatchClass, + parameter_types, traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, RuntimeDbWeight, Weight}, + weights::{constants::WEIGHT_PER_SECOND, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -169,7 +171,7 @@ impl frame_system::Config for Runtime { /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. - type Call = Call; + type RuntimeCall = RuntimeCall; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The index type for storing how many extrinsics an account has signed. @@ -183,9 +185,9 @@ impl frame_system::Config for Runtime { /// The header type. type Header = generic::Header; /// The ubiquitous event type. - type Event = Event; + type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). type BlockHashCount = BlockHashCount; /// Version of the runtime. @@ -258,8 +260,7 @@ impl pallet_beefy::Config for Runtime { } impl pallet_grandpa::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; type MaxAuthorities = MaxAuthorities; type KeyOwnerProofSystem = (); type KeyOwnerProof = @@ -340,7 +341,7 @@ impl pallet_balances::Config for Runtime { /// The type for recording an account's balance. type Balance = Balance; /// The ubiquitous event type. - type Event = Event; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; @@ -360,6 +361,7 @@ parameter_types! { pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); + pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); } impl pallet_transaction_payment::Config for Runtime { @@ -372,17 +374,18 @@ impl pallet_transaction_payment::Config for Runtime { TargetBlockFullness, AdjustmentVariable, MinimumMultiplier, + MaximumMultiplier, >; - type Event = Event; + type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { - type Event = Event; - type Call = Call; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; } impl pallet_session::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; type ValidatorIdOf = (); type ShouldEndSession = Babe; @@ -399,7 +402,7 @@ impl pallet_authority_discovery::Config for Runtime { } impl pallet_bridge_relayers::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = bp_relayers::MintReward, AccountId>; type WeightInfo = (); @@ -444,7 +447,7 @@ parameter_types! { bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; // `IdentityFee` is used by Rialto => we may use weight directly pub const GetDeliveryConfirmationTransactionFee: Balance = - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; + bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() as _; pub const RootAccountForPayments: Option = None; pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; } @@ -453,7 +456,7 @@ parameter_types! { pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type Parameter = millau_messages::RialtoToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; @@ -529,6 +532,9 @@ construct_runtime!( Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event}, Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, + ParaSessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, + ParasDisputes: polkadot_runtime_parachains::disputes::{Pallet, Call, Storage, Event}, + ParasSlashing: polkadot_runtime_parachains::disputes::slashing::{Pallet, Call, Storage, ValidateUnsigned}, // Parachain Onboarding Pallets Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event}, @@ -562,11 +568,12 @@ pub type SignedExtra = ( pallet_transaction_payment::ChargeTransactionPayment, ); /// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; +pub type SignedPayload = generic::SignedPayload; /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; +pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< Runtime, @@ -679,6 +686,23 @@ impl_runtime_apis! { .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) } + fn generate_historical_batch_proof( + leaf_indices: Vec, + leaves_count: mmr::LeafIndex, + ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { + Mmr::generate_historical_batch_proof(leaf_indices, leaves_count).map( + |(leaves, proof)| { + ( + leaves + .into_iter() + .map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)) + .collect(), + proof, + ) + }, + ) + } + fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) -> Result<(), mmr::Error> { @@ -725,17 +749,17 @@ impl_runtime_apis! { } impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration { + fn configuration() -> sp_consensus_babe::BabeConfiguration { // The choice of `c` parameter (where `1 - c` represents the // probability of a slot being empty), is done in accordance to the // slot duration and expected target block time, for safely // resisting network delays of maximum two seconds. // - sp_consensus_babe::BabeGenesisConfiguration { + sp_consensus_babe::BabeConfiguration { slot_duration: Babe::slot_duration(), epoch_length: EpochDuration::get(), c: BABE_GENESIS_EPOCH_CONFIG.c, - genesis_authorities: Babe::authorities().to_vec(), + authorities: Babe::authorities().to_vec(), randomness: Babe::randomness(), allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots, } @@ -824,7 +848,7 @@ impl_runtime_apis! { fn candidate_events() -> Vec> { polkadot_runtime_parachains::runtime_api_impl::v2::candidate_events::(|ev| { match ev { - Event::Inclusion(ev) => { + RuntimeEvent::Inclusion(ev) => { Some(ev) } _ => None, @@ -867,10 +891,6 @@ impl_runtime_apis! { { polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_hash::(para_id, assumption) } - - fn staging_get_disputes() -> Vec<(polkadot_primitives::v2::SessionIndex, polkadot_primitives::v2::CandidateHash, polkadot_primitives::v2::DisputeState)> { - unimplemented!() - } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { @@ -995,6 +1015,6 @@ mod tests { // result of large `SessionKeys` struct. // Total size of Rialto runtime Call is 232. const MAX_CALL_SIZE: usize = 232; - assert!(core::mem::size_of::() <= MAX_CALL_SIZE); + assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index e5869998fa8ba..ec8a7b822dca7 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{Call, OriginCaller, Runtime}; +use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::{SenderOrigin, TargetHeaderChain}, @@ -28,11 +28,7 @@ use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; use codec::{Decode, Encode}; -use frame_support::{ - parameter_types, - weights::{DispatchClass, Weight}, - RuntimeDebug, -}; +use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; use sp_std::convert::TryFrom; @@ -45,13 +41,18 @@ pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(Fixed /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = 2 * crate::xcm_config::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; parameter_types! { /// Millau to Rialto conversion rate. Initially we treat both tokens as equal. pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE; /// Fee multiplier value at Millau chain. pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER; + /// Weight credit for our test messages. + /// + /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge + /// (it is prepended with `UniversalOrigin` instruction). + pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); } /// Message payload for Rialto -> Millau messages. @@ -62,15 +63,14 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithMillauMessageBridge, xcm_executor::XcmExecutor, crate::xcm_config::XcmWeigher, - // - frame_support::traits::ConstU64, + WeightCredit, >; /// Messages proof for Millau -> Rialto messages. @@ -117,21 +117,20 @@ impl messages::ChainWithMessages for Rialto { type AccountId = bp_rialto::AccountId; type Signer = bp_rialto::AccountSigner; type Signature = bp_rialto::Signature; - type Weight = Weight; type Balance = bp_rialto::Balance; } impl messages::ThisChainWithMessages for Rialto { - type Origin = crate::Origin; - type Call = crate::Call; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< Self::AccountId, - { bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT }, + { bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, { bp_rialto::TX_EXTRA_BYTES }, >; - fn is_message_accepted(send_origin: &Self::Origin, lane: &LaneId) -> bool { + fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { let here_location = xcm::v3::MultiLocation::from(crate::xcm_config::UniversalLocation::get()); match send_origin.caller { @@ -165,7 +164,7 @@ impl messages::ThisChainWithMessages for Rialto { bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -180,7 +179,6 @@ impl messages::ChainWithMessages for Millau { type AccountId = bp_millau::AccountId; type Signer = bp_millau::AccountSigner; type Signature = bp_millau::Signature; - type Weight = Weight; type Balance = bp_millau::Balance; } @@ -199,15 +197,15 @@ impl messages::BridgedChainWithMessages for Millau { message_dispatch_weight: Weight, ) -> MessageTransaction { let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = Weight::from(message_payload_len) - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH.into()); + let extra_bytes_in_payload = message_payload_len + .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); MessageTransaction { - dispatch_weight: extra_bytes_in_payload - .saturating_mul(bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT) + dispatch_weight: bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT + .saturating_mul(extra_bytes_in_payload as u64) .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) .saturating_sub(if include_pay_dispatch_fee_cost { - 0 + Weight::from_ref_time(0) } else { bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT }) @@ -227,7 +225,7 @@ impl messages::BridgedChainWithMessages for Millau { bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, 1, multiplier, - |weight| weight as _, + |weight| weight.ref_time() as _, transaction, ) } @@ -277,7 +275,7 @@ impl SourceHeaderChain for Millau { } } -impl SenderOrigin for crate::Origin { +impl SenderOrigin for RuntimeOrigin { fn linked_account(&self) -> Option { // XCM deals wit fees in our deployments None diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index d6267bca23735..583358e50368d 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -17,29 +17,31 @@ //! Parachains support in Rialto runtime. use crate::{ - AccountId, Babe, Balance, Balances, BlockNumber, Call, Event, Origin, Registrar, Runtime, - ShiftSessionManager, Slots, UncheckedExtrinsic, + AccountId, Babe, Balance, Balances, BlockNumber, Registrar, Runtime, RuntimeCall, RuntimeEvent, + RuntimeOrigin, ShiftSessionManager, Slots, UncheckedExtrinsic, }; -use frame_support::{parameter_types, weights::Weight}; +use frame_support::{parameter_types, traits::KeyOwnerProofSystem, weights::Weight}; use frame_system::EnsureRoot; -use polkadot_primitives::v2::ValidatorIndex; +use polkadot_primitives::v2::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ - configuration as parachains_configuration, dmp as parachains_dmp, hrmp as parachains_hrmp, + configuration as parachains_configuration, disputes as parachains_disputes, + disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras, paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler, session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump, }; +use sp_core::crypto::KeyTypeId; use sp_runtime::transaction_validity::TransactionPriority; impl frame_system::offchain::SendTransactionTypes for Runtime where - Call: From, + RuntimeCall: From, { type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = Call; + type OverarchingCall = RuntimeCall; } /// Special `RewardValidators` that does nothing ;) @@ -58,14 +60,14 @@ impl parachains_configuration::Config for Runtime { impl parachains_dmp::Config for Runtime {} impl parachains_hrmp::Config for Runtime { - type Event = Event; - type Origin = Origin; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type Currency = Balances; type WeightInfo = parachains_hrmp::TestWeightInfo; } impl parachains_inclusion::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type RewardValidators = RewardValidators; type DisputesHandler = (); } @@ -76,6 +78,26 @@ impl parachains_initializer::Config for Runtime { type WeightInfo = (); } +impl parachains_disputes::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RewardValidators = (); + type SlashingHandler = (); + type WeightInfo = parachains_disputes::TestWeightInfo; +} + +impl parachains_slashing::Config for Runtime { + type KeyOwnerProofSystem = (); + type KeyOwnerProof = + >::Proof; + type KeyOwnerIdentification = >::IdentificationTuple; + type HandleReports = (); + type WeightInfo = parachains_slashing::TestWeightInfo; + type BenchmarkingConfig = parachains_slashing::BenchConfig<200>; +} + impl parachains_origin::Config for Runtime {} parameter_types! { @@ -83,7 +105,7 @@ parameter_types! { } impl parachains_paras::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = parachains_paras::TestWeightInfo; type UnsignedPriority = ParasUnsignedPriority; type NextSessionRotation = Babe; @@ -106,7 +128,7 @@ parameter_types! { } impl parachains_ump::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type UmpSink = (); type FirstMessageFactorPercent = FirstMessageFactorPercent; type ExecuteOverweightOrigin = EnsureRoot; @@ -121,8 +143,8 @@ parameter_types! { } impl paras_registrar::Config for Runtime { - type Event = Event; - type Origin = Origin; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type Currency = Balances; type OnSwap = Slots; type ParaDeposit = ParaDeposit; @@ -135,7 +157,7 @@ parameter_types! { } impl slots::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type Registrar = Registrar; type LeasePeriod = LeasePeriod; @@ -150,33 +172,33 @@ pub struct ZeroWeights; impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights { fn reserve() -> Weight { - 0 + Weight::from_ref_time(0) } fn register() -> Weight { - 0 + Weight::from_ref_time(0) } fn force_register() -> Weight { - 0 + Weight::from_ref_time(0) } fn deregister() -> Weight { - 0 + Weight::from_ref_time(0) } fn swap() -> Weight { - 0 + Weight::from_ref_time(0) } } impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights { fn force_lease() -> Weight { - 0 + Weight::from_ref_time(0) } fn manage_lease_period_start(_c: u32, _t: u32) -> Weight { - 0 + Weight::from_ref_time(0) } fn clear_all_leases() -> Weight { - 0 + Weight::from_ref_time(0) } fn trigger_onboard() -> Weight { - 0 + Weight::from_ref_time(0) } } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index ab0029302abd4..780ce710ba9f6 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -17,8 +17,8 @@ //! XCM configurations for the Rialto runtime. use super::{ - millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, Call, - Event, Origin, Runtime, WithMillauMessagesInstance, XcmPallet, + millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, WithMillauMessagesInstance, XcmPallet, }; use bp_rialto::WeightToFee; use bridge_runtime_common::{ @@ -28,12 +28,11 @@ use bridge_runtime_common::{ use frame_support::{ parameter_types, traits::{Everything, Nothing}, - weights::Weight, }; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, SignedAccountId32AsNative, + CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; @@ -52,7 +51,7 @@ parameter_types! { /// Since Polkadot is a top-level relay-chain with its own consensus, it's just our network ID. pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); /// The check account, which holds any native assets that have been teleported out and not back in (yet). - pub CheckAccount: AccountId = XcmPallet::check_account(); + pub CheckAccount: (AccountId, MintLocation) = (XcmPallet::check_account(), MintLocation::Local); } /// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to @@ -82,17 +81,17 @@ pub type LocalAssetTransactor = XcmCurrencyAdapter< /// The means that we convert the XCM message origin location into a local dispatch origin. type LocalOriginConverter = ( // A `Signed` origin of the sovereign account that the original location controls. - SovereignSignedViaLocation, + SovereignSignedViaLocation, // The AccountId32 location type can be expressed natively as a `Signed` origin. - SignedAccountId32AsNative, + SignedAccountId32AsNative, ); /// The amount of weight an XCM operation takes. This is a safe overestimate. -pub const BASE_XCM_WEIGHT: Weight = 1_000_000_000; +pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const BaseXcmWeight: Weight = BASE_XCM_WEIGHT; + pub const BaseXcmWeight: u64 = BASE_XCM_WEIGHT; /// Maximum number of instructions in a single XCM fragment. A sanity check against weight /// calculations getting too crazy. pub const MaxInstructions: u32 = 100; @@ -120,11 +119,11 @@ pub type Barrier = ( ); /// Incoming XCM weigher type. -pub type XcmWeigher = xcm_builder::FixedWeightBounds; +pub type XcmWeigher = xcm_builder::FixedWeightBounds; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type Call = Call; + type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; @@ -146,26 +145,26 @@ impl xcm_executor::Config for XcmConfig { type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; - type CallDispatcher = Call; + type CallDispatcher = RuntimeCall; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior /// location of this chain. pub type LocalOriginToLocation = ( // Usual Signed origin to be used in XCM as a corresponding AccountId32 - SignedToAccountId32, + SignedToAccountId32, ); impl pallet_xcm::Config for Runtime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; // We don't allow any messages to be sent via the transaction yet. This is basically safe to // enable, (safe the possibility of someone spamming the parachain if they're willing to pay // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will // make `DescendOrigin` a bit more useful. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmRouter = XcmRouter; // Anyone can execute XCM messages locally. - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmExecuteFilter = Everything; type XcmExecutor = xcm_executor::XcmExecutor; // Anyone is able to use teleportation regardless of who they are and what they want to @@ -176,8 +175,8 @@ impl pallet_xcm::Config for Runtime { type XcmReserveTransferFilter = Everything; type Weigher = XcmWeigher; type UniversalLocation = UniversalLocation; - type Origin = Origin; - type Call = Call; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type Currency = Balances; @@ -216,6 +215,7 @@ impl XcmBridge for ToMillauBridge { #[cfg(test)] mod tests { use super::*; + use crate::millau_messages::WeightCredit; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, MessageKey, @@ -252,13 +252,13 @@ mod tests { WithMillauMessageBridge, XcmExecutor, XcmWeigher, - frame_support::traits::ConstU64, + WeightCredit, >; new_test_ext().execute_with(|| { let location: MultiLocation = (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); - let xcm: Xcm = vec![Instruction::Trap(42)].into(); + let xcm: Xcm = vec![Instruction::Trap(42)].into(); let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, @@ -266,7 +266,10 @@ mod tests { }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, 1_000_000_000); + assert_eq!( + dispatch_weight, + frame_support::weights::Weight::from_ref_time(1_000_000_000) + ); let dispatch_result = MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); @@ -274,7 +277,7 @@ mod tests { dispatch_result, MessageDispatchResult { dispatch_result: true, - unspent_weight: 0, + unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } ); diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 850c71181ef34..90f048cb9cc30 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -60,7 +60,7 @@ macro_rules! assert_bridge_types( // `frame_support::weights::Weight` is used here directly, because all chains we know are using this // primitive (may be changed in the future) use $crate::messages::{ - AccountIdOf, BalanceOf, BridgedChain, HashOf, SignatureOf, SignerOf, ThisChain, WeightOf, + AccountIdOf, BalanceOf, BridgedChain, HashOf, SignatureOf, SignerOf, ThisChain, }; use static_assertions::assert_type_eq_all; @@ -68,14 +68,12 @@ macro_rules! assert_bridge_types( assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$this>); assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$this>); assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$this>); - assert_type_eq_all!(WeightOf>, frame_support::weights::Weight); assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$this>); assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$bridged>); assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$bridged>); assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$bridged>); assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$bridged>); - assert_type_eq_all!(WeightOf>, frame_support::weights::Weight); assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$bridged>); } } @@ -114,7 +112,7 @@ macro_rules! assert_bridge_messages_pallet_types( use $crate::messages::{ source::FromThisChainMessagePayload, target::FromBridgedChainMessagePayload, - AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, WeightOf, + AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, }; use pallet_bridge_messages::Config as MessagesConfig; use static_assertions::assert_type_eq_all; diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index a8f2434fc7d0b..e56b887885aa7 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -156,14 +156,14 @@ mod tests { } impl sp_runtime::traits::Dispatchable for MockCall { - type Origin = (); + type RuntimeOrigin = (); type Config = (); type Info = (); type PostInfo = (); fn dispatch( self, - _origin: Self::Origin, + _origin: Self::RuntimeOrigin, ) -> sp_runtime::DispatchResultWithInfo { unimplemented!() } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 57f3f38cb2efb..880bc6bc394d6 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -75,11 +75,6 @@ pub trait ChainWithMessages { type Signer: Encode + Decode; /// Signature type used on the chain. type Signature: Encode + Decode; - /// Type of weight that is used on the chain. This would almost always be a regular - /// `frame_support::weight::Weight`. But since the meaning of weight on different chains - /// may be different, the `WeightOf<>` construct is used to avoid confusion between - /// different weights. - type Weight: From + PartialOrd; /// Type of balances that is used on the chain. type Balance: Encode + Decode @@ -110,14 +105,14 @@ pub trait ConfirmationTransactionEstimation { /// Default implementation for `ConfirmationTransactionEstimation`. pub struct BasicConfirmationTransactionEstimation< AccountId: MaxEncodedLen, - const MAX_CONFIRMATION_TX_WEIGHT: Weight, + const MAX_CONFIRMATION_TX_WEIGHT: u64, const EXTRA_STORAGE_PROOF_SIZE: u32, const TX_EXTRA_BYTES: u32, >(PhantomData); impl< AccountId: MaxEncodedLen, - const MAX_CONFIRMATION_TX_WEIGHT: Weight, + const MAX_CONFIRMATION_TX_WEIGHT: u64, const EXTRA_STORAGE_PROOF_SIZE: u32, const TX_EXTRA_BYTES: u32, > ConfirmationTransactionEstimation @@ -131,7 +126,7 @@ impl< fn estimate_delivery_confirmation_transaction() -> MessageTransaction { let inbound_data_size = InboundLaneData::::encoded_size_hint_u32(1, 1); MessageTransaction { - dispatch_weight: MAX_CONFIRMATION_TX_WEIGHT, + dispatch_weight: Weight::from_ref_time(MAX_CONFIRMATION_TX_WEIGHT), size: inbound_data_size .saturating_add(EXTRA_STORAGE_PROOF_SIZE) .saturating_add(TX_EXTRA_BYTES), @@ -142,15 +137,15 @@ impl< /// This chain that has `pallet-bridge-messages` and `dispatch` modules. pub trait ThisChainWithMessages: ChainWithMessages { /// Call origin on the chain. - type Origin; + type RuntimeOrigin; /// Call type on the chain. - type Call: Encode + Decode; + type RuntimeCall: Encode + Decode; /// Helper for estimating the size and weight of a single message delivery confirmation /// transaction at this chain. - type ConfirmationTransactionEstimation: ConfirmationTransactionEstimation>; + type ConfirmationTransactionEstimation: ConfirmationTransactionEstimation; /// Do we accept message sent by given origin to given lane? - fn is_message_accepted(origin: &Self::Origin, lane: &LaneId) -> bool; + fn is_message_accepted(origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool; /// Maximal number of pending (not yet delivered) messages at This chain. /// @@ -158,12 +153,12 @@ pub trait ThisChainWithMessages: ChainWithMessages { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; /// Estimate size and weight of single message delivery confirmation transaction at This chain. - fn estimate_delivery_confirmation_transaction() -> MessageTransaction> { + fn estimate_delivery_confirmation_transaction() -> MessageTransaction { Self::ConfirmationTransactionEstimation::estimate_delivery_confirmation_transaction() } /// Returns minimal transaction fee that must be paid for given transaction at This chain. - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; + fn transaction_payment(transaction: MessageTransaction) -> BalanceOf; } /// Bridged chain that has `pallet-bridge-messages` and `dispatch` modules. @@ -179,12 +174,12 @@ pub trait BridgedChainWithMessages: ChainWithMessages { fn estimate_delivery_transaction( message_payload: &[u8], include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: WeightOf, - ) -> MessageTransaction>; + message_dispatch_weight: Weight, + ) -> MessageTransaction; /// Returns minimal transaction fee that must be paid for given transaction at the Bridged /// chain. - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf; + fn transaction_payment(transaction: MessageTransaction) -> BalanceOf; } /// This chain in context of message bridge. @@ -199,14 +194,12 @@ pub type AccountIdOf = ::AccountId; pub type SignerOf = ::Signer; /// Signature type used on the chain. pub type SignatureOf = ::Signature; -/// Type of weight that used on the chain. -pub type WeightOf = ::Weight; /// Type of balances that is used on the chain. pub type BalanceOf = ::Balance; /// Type of origin that is used on the chain. -pub type OriginOf = ::Origin; +pub type OriginOf = ::RuntimeOrigin; /// Type of call that is used on this chain. -pub type CallOf = ::Call; +pub type CallOf = ::RuntimeCall; /// Raw storage proof type (just raw trie nodes). pub type RawStorageProof = Vec>; @@ -411,8 +404,11 @@ pub mod source { // // if we're going to pay dispatch fee at the target chain, then we don't include weight // of the message dispatch in the delivery transaction cost - let delivery_transaction = - BridgedChain::::estimate_delivery_transaction(&payload.encode(), true, 0.into()); + let delivery_transaction = BridgedChain::::estimate_delivery_transaction( + &payload.encode(), + true, + Weight::from_ref_time(0), + ); let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); // the fee (in This tokens) of all transactions that are made on This chain @@ -720,7 +716,7 @@ pub mod target { // I have no idea why this method takes `&mut` reference and there's nothing // about that in documentation. Hope it'll only mutate iff error is returned. let weight = XcmWeigher::weight(&mut payload.xcm.1); - let weight = weight.unwrap_or_else(|e| { + let weight = Weight::from_ref_time(weight.unwrap_or_else(|e| { log::debug!( target: "runtime::bridge-dispatch", "Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}", @@ -732,12 +728,12 @@ pub mod target { // we shall return 0 and then the XCM executor will fail to execute XCM // if we'll return something else (e.g. maximal value), the lane may stuck 0 - }); + })); payload.weight = Some(weight); weight }, - _ => 0, + _ => Weight::from_ref_time(0), } } @@ -766,8 +762,8 @@ pub mod target { location, xcm, hash, - weight_limit.unwrap_or(0), - weight_credit, + weight_limit.unwrap_or(Weight::from_ref_time(0)).ref_time(), + weight_credit.ref_time(), ); Ok(xcm_outcome) }; @@ -776,7 +772,7 @@ pub mod target { log::trace!(target: "runtime::bridge-dispatch", "Incoming message {:?} dispatched with result: {:?}", message_id, xcm_outcome); MessageDispatchResult { dispatch_result: true, - unspent_weight: 0, + unspent_weight: Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } } @@ -1093,6 +1089,7 @@ pub mod xcm_copy { fn validate( network: NetworkId, _channel: u32, + _universal_source: &mut Option, destination: &mut Option, message: &mut Option>, ) -> Result<((Vec, XcmHash), MultiAssets), SendError> { @@ -1127,10 +1124,10 @@ mod tests { use frame_support::weights::Weight; use std::ops::RangeInclusive; - const DELIVERY_TRANSACTION_WEIGHT: Weight = 100; - const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: Weight = 100; - const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 2; - const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: Weight = 4; + const DELIVERY_TRANSACTION_WEIGHT: Weight = Weight::from_ref_time(100); + const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: u64 = 100; + const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: u32 = 2; + const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: u32 = 4; const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; @@ -1301,13 +1298,12 @@ mod tests { type AccountId = ThisChainAccountId; type Signer = ThisChainSigner; type Signature = ThisChainSignature; - type Weight = frame_support::weights::Weight; type Balance = ThisChainBalance; } impl ThisChainWithMessages for ThisChain { - type Origin = ThisChainOrigin; - type Call = ThisChainCall; + type RuntimeOrigin = ThisChainOrigin; + type RuntimeCall = ThisChainCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< ::AccountId, { DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT }, @@ -1315,7 +1311,7 @@ mod tests { 0, >; - fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { lane == TEST_LANE_ID } @@ -1323,9 +1319,12 @@ mod tests { MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE } - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { + fn transaction_payment(transaction: MessageTransaction) -> BalanceOf { ThisChainBalance( - transaction.dispatch_weight as u32 * THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, + transaction + .dispatch_weight + .saturating_mul(THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) + .ref_time() as _, ) } } @@ -1342,14 +1341,12 @@ mod tests { fn estimate_delivery_transaction( _message_payload: &[u8], _include_pay_dispatch_fee_cost: bool, - _message_dispatch_weight: WeightOf, - ) -> MessageTransaction> { + _message_dispatch_weight: Weight, + ) -> MessageTransaction { unreachable!() } - fn transaction_payment( - _transaction: MessageTransaction>, - ) -> BalanceOf { + fn transaction_payment(_transaction: MessageTransaction) -> BalanceOf { unreachable!() } } @@ -1361,13 +1358,12 @@ mod tests { type AccountId = BridgedChainAccountId; type Signer = BridgedChainSigner; type Signature = BridgedChainSignature; - type Weight = frame_support::weights::Weight; type Balance = BridgedChainBalance; } impl ThisChainWithMessages for BridgedChain { - type Origin = BridgedChainOrigin; - type Call = BridgedChainCall; + type RuntimeOrigin = BridgedChainOrigin; + type RuntimeCall = BridgedChainCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< ::AccountId, 0, @@ -1375,7 +1371,7 @@ mod tests { 0, >; - fn is_message_accepted(_send_origin: &Self::Origin, _lane: &LaneId) -> bool { + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { unreachable!() } @@ -1383,9 +1379,7 @@ mod tests { unreachable!() } - fn transaction_payment( - _transaction: MessageTransaction>, - ) -> BalanceOf { + fn transaction_payment(_transaction: MessageTransaction) -> BalanceOf { unreachable!() } } @@ -1403,17 +1397,20 @@ mod tests { fn estimate_delivery_transaction( _message_payload: &[u8], _include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: WeightOf, - ) -> MessageTransaction> { + message_dispatch_weight: Weight, + ) -> MessageTransaction { MessageTransaction { dispatch_weight: DELIVERY_TRANSACTION_WEIGHT + message_dispatch_weight, size: 0, } } - fn transaction_payment(transaction: MessageTransaction>) -> BalanceOf { + fn transaction_payment(transaction: MessageTransaction) -> BalanceOf { BridgedChainBalance( - transaction.dispatch_weight as u32 * BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u32, + transaction + .dispatch_weight + .saturating_mul(BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) + .ref_time() as _, ) } } @@ -1786,11 +1783,11 @@ mod tests { assert_eq!( transaction_payment( - 100, + Weight::from_ref_time(100), 10, FixedU128::zero(), - |weight| weight, - MessageTransaction { size: 50, dispatch_weight: 777 }, + |weight| weight.ref_time(), + MessageTransaction { size: 50, dispatch_weight: Weight::from_ref_time(777) }, ), 100 + 50 * 10, ); @@ -1801,12 +1798,12 @@ mod tests { use sp_runtime::traits::One; assert_eq!( - transaction_payment( - 100, + transaction_payment::( + Weight::from_ref_time(100), 10, FixedU128::one(), - |weight| weight, - MessageTransaction { size: 50, dispatch_weight: 777 }, + |weight| weight.ref_time(), + MessageTransaction { size: 50, dispatch_weight: Weight::from_ref_time(777) }, ), 100 + 50 * 10 + 777, ); diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index 68465fa16e417..acc4c6d9a6e94 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -39,7 +39,7 @@ where nonce, // dispatch message weight is always zero at the source chain, since we're paying for // dispatch at the target chain - dispatch_weight: 0, + dispatch_weight: frame_support::weights::Weight::from_ref_time(0), size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, // we're delivering XCM messages here, so fee is always paid at the target chain diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 68f58d76b8780..2a384236aff95 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -29,7 +29,7 @@ use crate::messages::{ use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; use bp_runtime::{record_all_trie_keys, StorageProofSize}; use codec::Encode; -use frame_support::weights::{GetDispatchInfo, Weight}; +use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; use pallet_bridge_messages::benchmarking::{ MessageDeliveryProofParams, MessageParams, MessageProofParams, }; @@ -94,7 +94,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - 0, + Weight::from_ref_time(0), ) } diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index bcaadd60ca035..39d44ad11fb34 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -40,7 +40,7 @@ impl< MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof, >, Call: IsSubType, T>>, - T: frame_system::Config + T: frame_system::Config + Config, I: 'static, > BridgeRuntimeFilterCall for Pallet @@ -106,7 +106,7 @@ mod tests { }, BridgeRuntimeFilterCall, }, - Call, Runtime, WithRialtoMessagesInstance, + Runtime, RuntimeCall, WithRialtoMessagesInstance, }; fn deliver_message_10() { @@ -121,11 +121,11 @@ mod tests { nonces_end: bp_messages::MessageNonce, ) -> bool { pallet_bridge_messages::Pallet::::validate( - &Call::BridgeRialtoMessages( + &RuntimeCall::BridgeRialtoMessages( pallet_bridge_messages::Call::::receive_messages_proof { relayer_id_at_bridged_chain: [0u8; 32].into(), messages_count: (nonces_end - nonces_start + 1) as u32, - dispatch_weight: 0, + dispatch_weight: frame_support::weights::Weight::from_ref_time(0), proof: FromBridgedChainMessagesProof { bridged_header_hash: Default::default(), storage_proof: vec![], @@ -182,7 +182,7 @@ mod tests { fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool { pallet_bridge_messages::Pallet::::validate( - &Call::BridgeRialtoMessages(pallet_bridge_messages::Call::< + &RuntimeCall::BridgeRialtoMessages(pallet_bridge_messages::Call::< Runtime, WithRialtoMessagesInstance, >::receive_messages_delivery_proof { diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index a724b6518d84b..c0f02da751e61 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -27,11 +27,11 @@ use sp_runtime::{ /// if there are multiple relays running and submitting the same information. impl< Call: IsSubType, T>>, - T: frame_system::Config + Config, + T: frame_system::Config + Config, I: 'static, > FilterCall for Pallet { - fn validate(call: &::Call) -> TransactionValidity { + fn validate(call: &::RuntimeCall) -> TransactionValidity { let bundled_block_number = match call.is_sub_type() { Some(crate::Call::::submit_finality_proof { ref finality_target, .. }) => *finality_target.number(), @@ -63,18 +63,19 @@ impl< mod tests { use super::FilterCall; use crate::{ - mock::{run_test, test_header, Call, TestNumber, TestRuntime}, + mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime}, BestFinalized, }; use bp_test_utils::make_default_justification; fn validate_block_submit(num: TestNumber) -> bool { - crate::Pallet::::validate(&Call::Grandpa( - crate::Call::::submit_finality_proof { - finality_target: Box::new(test_header(num)), - justification: make_default_justification(&test_header(num)), - }, - )) + crate::Pallet::::validate(&RuntimeCall::Grandpa(crate::Call::< + TestRuntime, + (), + >::submit_finality_proof { + finality_target: Box::new(test_header(num)), + justification: make_default_justification(&test_header(num)), + })) .is_ok() } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index b3801beb6f1f2..97875e8faded7 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -135,7 +135,7 @@ pub mod pallet { fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { >::mutate(|count| *count = count.saturating_sub(1)); - (0_u64) + Weight::from_ref_time(0) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -666,7 +666,7 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader mod tests { use super::*; use crate::mock::{ - run_test, test_header, Origin, TestHeader, TestNumber, TestRuntime, + run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime, MAX_BRIDGED_AUTHORITIES, MAX_HEADER_SIZE, }; use bp_runtime::BasicOperatingMode; @@ -676,17 +676,17 @@ mod tests { }; use codec::Encode; use frame_support::{ - assert_err, assert_noop, assert_ok, storage::generator::StorageValue, - weights::PostDispatchInfo, + assert_err, assert_noop, assert_ok, dispatch::PostDispatchInfo, + storage::generator::StorageValue, }; use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { - assert_ok!(init_with_origin(Origin::root())); + assert_ok!(init_with_origin(RuntimeOrigin::root())); } fn init_with_origin( - origin: Origin, + origin: RuntimeOrigin, ) -> Result< InitializationData, sp_runtime::DispatchErrorWithPostInfo, @@ -708,7 +708,7 @@ mod tests { let justification = make_default_justification(&header); Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification, ) @@ -763,13 +763,13 @@ mod tests { #[test] fn init_root_or_owner_origin_can_initialize_pallet() { run_test(|| { - assert_noop!(init_with_origin(Origin::signed(1)), DispatchError::BadOrigin); - assert_ok!(init_with_origin(Origin::root())); + assert_noop!(init_with_origin(RuntimeOrigin::signed(1)), DispatchError::BadOrigin); + assert_ok!(init_with_origin(RuntimeOrigin::root())); // Reset storage so we can initialize the pallet again BestFinalized::::kill(); PalletOwner::::put(2); - assert_ok!(init_with_origin(Origin::signed(2))); + assert_ok!(init_with_origin(RuntimeOrigin::signed(2))); }) } @@ -779,7 +779,7 @@ mod tests { assert_eq!(BestFinalized::::get(), None,); assert_eq!(Pallet::::best_finalized(), None); - let init_data = init_with_origin(Origin::root()).unwrap(); + let init_data = init_with_origin(RuntimeOrigin::root()).unwrap(); assert!(>::contains_key(init_data.header.hash())); assert_eq!(BestFinalized::::get().unwrap().1, init_data.header.hash()); @@ -796,7 +796,7 @@ mod tests { run_test(|| { initialize_substrate_bridge(); assert_noop!( - init_with_origin(Origin::root()), + init_with_origin(RuntimeOrigin::root()), >::AlreadyInitialized ); }) @@ -816,7 +816,7 @@ mod tests { }; assert_noop!( - Pallet::::initialize(Origin::root(), init_data), + Pallet::::initialize(RuntimeOrigin::root(), init_data), Error::::TooManyAuthoritiesInSet, ); }); @@ -835,7 +835,7 @@ mod tests { }; assert_noop!( - Pallet::::initialize(Origin::root(), init_data), + Pallet::::initialize(RuntimeOrigin::root(), init_data), Error::::TooLargeHeader, ); }); @@ -847,7 +847,7 @@ mod tests { initialize_substrate_bridge(); assert_ok!(Pallet::::set_operating_mode( - Origin::root(), + RuntimeOrigin::root(), BasicOperatingMode::Halted )); assert_noop!( @@ -856,7 +856,7 @@ mod tests { ); assert_ok!(Pallet::::set_operating_mode( - Origin::root(), + RuntimeOrigin::root(), BasicOperatingMode::Normal )); assert_ok!(submit_finality_proof(1)); @@ -878,7 +878,7 @@ mod tests { submit_finality_proof(1), PostDispatchInfo { actual_weight: None, - pays_fee: frame_support::weights::Pays::Yes, + pays_fee: frame_support::dispatch::Pays::Yes, }, ); @@ -901,7 +901,7 @@ mod tests { assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification, ), @@ -921,7 +921,7 @@ mod tests { assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification, ), @@ -943,14 +943,14 @@ mod tests { operating_mode: BasicOperatingMode::Normal, }; - assert_ok!(Pallet::::initialize(Origin::root(), init_data)); + assert_ok!(Pallet::::initialize(RuntimeOrigin::root(), init_data)); let header = test_header(1); let justification = make_default_justification(&header); assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification, ), @@ -989,13 +989,13 @@ mod tests { // Let's import our test header assert_ok!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header.clone()), justification ), PostDispatchInfo { actual_weight: None, - pays_fee: frame_support::weights::Pays::No, + pays_fee: frame_support::dispatch::Pays::No, }, ); @@ -1028,7 +1028,7 @@ mod tests { // Should not be allowed to import this header assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification ), @@ -1053,7 +1053,7 @@ mod tests { // Should not be allowed to import this header assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification ), @@ -1078,7 +1078,7 @@ mod tests { // Should not be allowed to import this header assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification ), @@ -1103,7 +1103,7 @@ mod tests { // Should not be allowed to import this header assert_err!( Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification ), @@ -1168,7 +1168,7 @@ mod tests { invalid_justification.round = 42; Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), invalid_justification, ) diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index babdd4b7920c9..0f83bd528d68e 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -51,22 +51,22 @@ construct_runtime! { parameter_types! { pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Config for TestRuntime { - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type Index = u64; - type Call = Call; + type RuntimeCall = RuntimeCall; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type RuntimeEvent = (); type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index ac4835e4f0d41..d930dbadbc639 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -43,7 +43,7 @@ impl, I: 'static> StoredAuthoritySet { /// /// Returns error if number of authorities in the provided list is too large. pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result { - Ok(Self { authorities: TryFrom::try_from(authorities)?, set_id }) + Ok(Self { authorities: TryFrom::try_from(authorities).map_err(drop)?, set_id }) } } diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index ece88ab55c5f0..bb9d5270b54fa 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -59,21 +59,21 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (105_417_000 as Weight) - .saturating_add((40_923_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((1_691_000 as Weight).saturating_mul(v as Weight)) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(6 as Weight)) + Weight::from_ref_time(105_417_000 as u64) + .saturating_add(Weight::from_ref_time(40_923_000 as u64).saturating_mul(p as u64)) + .saturating_add(Weight::from_ref_time(1_691_000 as u64).saturating_mul(v as u64)) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(6 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - (105_417_000 as Weight) - .saturating_add((40_923_000 as Weight).saturating_mul(p as Weight)) - .saturating_add((1_691_000 as Weight).saturating_mul(v as Weight)) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + Weight::from_ref_time(105_417_000 as u64) + .saturating_add(Weight::from_ref_time(40_923_000 as u64).saturating_mul(p as u64)) + .saturating_add(Weight::from_ref_time(1_691_000 as u64).saturating_mul(v as u64)) + .saturating_add(RocksDbWeight::get().reads(7 as u64)) + .saturating_add(RocksDbWeight::get().writes(6 as u64)) } } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index cae76927045bc..bee1df06c5a71 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -554,7 +554,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); let mut payload = REGULAR_PAYLOAD; - payload.dispatch_result.unspent_weight = 1; + *payload.dispatch_result.unspent_weight.ref_time_mut() = 1; assert_eq!( lane.receive_message::( &TEST_RELAYER_A, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 962fd8f791578..61e6df211c747 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -65,11 +65,7 @@ use bp_messages::{ }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{ - ensure, fail, - traits::Get, - weights::{Pays, PostDispatchInfo}, -}; +use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; use num_traits::{SaturatingAdd, Zero}; use sp_std::{ cell::RefCell, cmp::PartialOrd, collections::vec_deque::VecDeque, marker::PhantomData, @@ -104,7 +100,8 @@ pub mod pallet { // General types /// The overarching event type. - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + + IsType<::RuntimeEvent>; /// Benchmarks results from runtime we're plugged into. type WeightInfo: WeightInfoExt; @@ -174,13 +171,13 @@ pub mod pallet { type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier< - Self::Origin, + Self::RuntimeOrigin, Self::OutboundPayload, Self::OutboundMessageFee, >; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< - Self::Origin, + Self::RuntimeOrigin, Self::AccountId, Self::OutboundMessageFee, >; @@ -333,9 +330,10 @@ pub mod pallet { }); // compute actual dispatch weight that depends on the stored message size - let actual_weight = sp_std::cmp::min( + let actual_weight = sp_std::cmp::min_by( T::WeightInfo::maximal_increase_message_fee(), T::WeightInfo::increase_message_fee(message_size as _), + |w1, w2| w1.ref_time().cmp(&w2.ref_time()), ); Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) @@ -418,7 +416,7 @@ pub mod pallet { // on this lane. We can't dispatch lane messages out-of-order, so if declared // weight is not enough, let's move to next lane let dispatch_weight = T::MessageDispatch::dispatch_weight(&mut message); - if dispatch_weight > dispatch_weight_left { + if dispatch_weight.ref_time() > dispatch_weight_left.ref_time() { log::trace!( target: LOG_TARGET, "Cannot dispatch any more messages on lane {:?}. Weight: declared={}, left={}", @@ -456,7 +454,10 @@ pub mod pallet { ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), }; - let unspent_weight = sp_std::cmp::min(unspent_weight, dispatch_weight); + let unspent_weight = + sp_std::cmp::min_by(unspent_weight, dispatch_weight, |w1, w2| { + w1.ref_time().cmp(&w2.ref_time()) + }); dispatch_weight_left -= dispatch_weight - unspent_weight; actual_weight = actual_weight.saturating_sub(unspent_weight).saturating_sub( // delivery call weight formula assumes that the fee is paid at @@ -465,7 +466,7 @@ pub mod pallet { if refund_pay_dispatch_fee { T::WeightInfo::pay_inbound_dispatch_fee_overhead() } else { - 0 + Weight::from_ref_time(0) }, ); } @@ -580,11 +581,11 @@ pub mod pallet { if let Some(confirmed_messages) = confirmed_messages { // handle messages delivery confirmation let preliminary_callback_overhead = - relayers_state.total_messages.saturating_mul(single_message_callback_overhead); + single_message_callback_overhead.saturating_mul(relayers_state.total_messages); let actual_callback_weight = T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); - match preliminary_callback_overhead.checked_sub(actual_callback_weight) { - Some(difference) if difference == 0 => (), + match preliminary_callback_overhead.checked_sub(&actual_callback_weight) { + Some(difference) if difference.ref_time() == 0 => (), Some(difference) => { log::trace!( target: LOG_TARGET, @@ -775,8 +776,11 @@ pub mod pallet { } impl - bp_messages::source_chain::MessagesBridge - for Pallet + bp_messages::source_chain::MessagesBridge< + T::RuntimeOrigin, + T::OutboundMessageFee, + T::OutboundPayload, + > for Pallet where T: Config, I: 'static, @@ -784,7 +788,7 @@ where type Error = sp_runtime::DispatchErrorWithPostInfo; fn send_message( - sender: T::Origin, + sender: T::RuntimeOrigin, lane: LaneId, message: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -795,7 +799,7 @@ where /// Function that actually sends message. fn send_message, I: 'static>( - submitter: T::Origin, + submitter: T::RuntimeOrigin, lane_id: LaneId, payload: T::OutboundPayload, delivery_and_dispatch_fee: T::OutboundMessageFee, @@ -875,8 +879,8 @@ fn send_message, I: 'static>( let single_message_callback_overhead = T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); let actual_callback_weight = T::OnMessageAccepted::on_messages_accepted(&lane_id, &nonce); - match single_message_callback_overhead.checked_sub(actual_callback_weight) { - Some(difference) if difference == 0 => (), + match single_message_callback_overhead.checked_sub(&actual_callback_weight) { + Some(difference) if difference.ref_time() == 0 => (), Some(difference) => { log::trace!( target: LOG_TARGET, @@ -1104,8 +1108,8 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, message_payload, run_test, unrewarded_relayer, Balance, Event as TestEvent, - Origin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, + message, message_payload, run_test, unrewarded_relayer, Balance, RuntimeEvent as TestEvent, + RuntimeOrigin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, TestMessagesParameter, TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, TestOnMessageAccepted, TestRuntime, TokenConversionRate, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, @@ -1149,10 +1153,10 @@ mod tests { let message_nonce = outbound_lane::(TEST_LANE_ID).data().latest_generated_nonce + 1; let weight = Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight, + REGULAR_PAYLOAD.declared_weight.ref_time(), ) .expect("send_message has failed") .actual_weight @@ -1174,7 +1178,7 @@ mod tests { // check that fee has been withdrawn from submitter assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid( 1, - REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight.ref_time() )); weight @@ -1185,7 +1189,7 @@ mod tests { System::::reset_events(); assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1226,7 +1230,7 @@ mod tests { let parameter = TestMessagesParameter::TokenConversionRate(10.into()); assert_ok!(Pallet::::update_pallet_parameter( - Origin::root(), + RuntimeOrigin::root(), parameter.clone(), )); @@ -1250,7 +1254,7 @@ mod tests { let parameter = TestMessagesParameter::TokenConversionRate(10.into()); assert_ok!(Pallet::::update_pallet_parameter( - Origin::signed(2), + RuntimeOrigin::signed(2), parameter.clone(), )); @@ -1271,7 +1275,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::update_pallet_parameter( - Origin::signed(2), + RuntimeOrigin::signed(2), TestMessagesParameter::TokenConversionRate(10.into()), ), DispatchError::BadOrigin, @@ -1281,7 +1285,7 @@ mod tests { assert_noop!( Pallet::::update_pallet_parameter( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesParameter::TokenConversionRate(10.into()), ), DispatchError::BadOrigin, @@ -1327,22 +1331,27 @@ mod tests { assert_noop!( Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight, + REGULAR_PAYLOAD.declared_weight.ref_time(), ), Error::::NotOperatingNormally, ); assert_noop!( - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1,), + Pallet::::increase_message_fee( + RuntimeOrigin::signed(1), + TEST_LANE_ID, + 1, + 1, + ), Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted), ); assert_noop!( Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok(vec![message(2, REGULAR_PAYLOAD)]).into(), 1, @@ -1353,7 +1362,7 @@ mod tests { assert_noop!( Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1387,23 +1396,23 @@ mod tests { assert_noop!( Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight, + REGULAR_PAYLOAD.declared_weight.ref_time(), ), Error::::NotOperatingNormally, ); assert_ok!(Pallet::::increase_message_fee( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, 1, 1, )); assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), 1, @@ -1411,7 +1420,7 @@ mod tests { ),); assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1449,7 +1458,7 @@ mod tests { .extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]); assert_noop!( Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, message_payload.clone(), Balance::MAX, @@ -1463,7 +1472,7 @@ mod tests { } assert_eq!(message_payload.size(), MAX_OUTBOUND_PAYLOAD_SIZE); assert_ok!(Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, message_payload, Balance::MAX, @@ -1477,10 +1486,10 @@ mod tests { // messages with this payload are rejected by target chain verifier assert_noop!( Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN, - PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight + PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight.ref_time(), ), Error::::MessageRejectedByChainVerifier, ); @@ -1493,7 +1502,7 @@ mod tests { // messages with zero fee are rejected by lane verifier assert_noop!( Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 0 @@ -1509,10 +1518,10 @@ mod tests { TestMessageDeliveryAndDispatchPayment::reject_payments(); assert_noop!( Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight + REGULAR_PAYLOAD.declared_weight.ref_time(), ), Error::::FailedToWithdrawMessageFee, ); @@ -1523,7 +1532,7 @@ mod tests { fn receive_messages_proof_works() { run_test(|| { assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), 1, @@ -1567,7 +1576,7 @@ mod tests { Some(OutboundLaneData { latest_received_nonce: 9, ..Default::default() }); assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, message_proof, 1, @@ -1601,12 +1610,14 @@ mod tests { #[test] fn receive_messages_proof_does_not_accept_message_if_dispatch_weight_is_not_enough() { run_test(|| { + let mut declared_weight = REGULAR_PAYLOAD.declared_weight; + *declared_weight.ref_time_mut() -= 1; assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), 1, - REGULAR_PAYLOAD.declared_weight - 1, + declared_weight, )); assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 0); }); @@ -1617,11 +1628,11 @@ mod tests { run_test(|| { assert_noop!( Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Err(()).into(), 1, - 0, + Weight::from_ref_time(0), ), Error::::InvalidMessagesProof, ); @@ -1633,11 +1644,11 @@ mod tests { run_test(|| { assert_noop!( Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), u32::MAX, - 0, + Weight::from_ref_time(0), ), Error::::TooManyMessagesInTheProof, ); @@ -1661,13 +1672,13 @@ mod tests { fn receive_messages_delivery_proof_rewards_relayers() { run_test(|| { assert_ok!(Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 1000, )); assert_ok!(Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, 2000, @@ -1675,7 +1686,7 @@ mod tests { // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1698,7 +1709,7 @@ mod tests { // this reports delivery of both message 1 and message 2 => reward is paid only to // TEST_RELAYER_B assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1728,7 +1739,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Err(())), Default::default(), ), @@ -1743,7 +1754,7 @@ mod tests { // when number of relayers entries is invalid assert_noop!( Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1769,7 +1780,7 @@ mod tests { // when number of messages is invalid assert_noop!( Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1795,7 +1806,7 @@ mod tests { // when last delivered nonce is invalid assert_noop!( Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -1827,11 +1838,12 @@ mod tests { invalid_message.data.payload = Vec::new(); assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok(vec![invalid_message]).into(), 1, - 0, // weight may be zero in this case (all messages are improperly encoded) + Weight::from_ref_time(0), /* weight may be zero in this case (all messages are + * improperly encoded) */ ),); assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1,); @@ -1845,7 +1857,7 @@ mod tests { invalid_message.data.payload = Vec::new(); assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, Ok( vec![message(1, REGULAR_PAYLOAD), invalid_message, message(3, REGULAR_PAYLOAD),] @@ -1862,12 +1874,12 @@ mod tests { #[test] fn actual_dispatch_weight_does_not_overlow() { run_test(|| { - let message1 = message(1, message_payload(0, Weight::MAX / 2)); - let message2 = message(2, message_payload(0, Weight::MAX / 2)); - let message3 = message(3, message_payload(0, Weight::MAX / 2)); + let message1 = message(1, message_payload(0, u64::MAX / 2)); + let message2 = message(2, message_payload(0, u64::MAX / 2)); + let message3 = message(3, message_payload(0, u64::MAX / 2)); assert_ok!(Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, // this may cause overflow if source chain storage is invalid Ok(vec![message1, message2, message3]).into(), @@ -1886,7 +1898,7 @@ mod tests { assert_noop!( Pallet::::increase_message_fee( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, 1, 100, @@ -1901,7 +1913,7 @@ mod tests { run_test(|| { assert_noop!( Pallet::::increase_message_fee( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, 1, 100, @@ -1920,7 +1932,7 @@ mod tests { assert_noop!( Pallet::::increase_message_fee( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, 1, 100, @@ -1936,7 +1948,7 @@ mod tests { send_regular_message(); assert_ok!(Pallet::::increase_message_fee( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, 1, 100, @@ -1950,11 +1962,11 @@ mod tests { run_test(|| { fn submit_with_unspent_weight( nonce: MessageNonce, - unspent_weight: Weight, + unspent_weight: u64, is_prepaid: bool, ) -> (Weight, Weight) { let mut payload = REGULAR_PAYLOAD; - payload.dispatch_result.unspent_weight = unspent_weight; + *payload.dispatch_result.unspent_weight.ref_time_mut() = unspent_weight; payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid; let proof = Ok(vec![message(nonce, payload)]).into(); let messages_count = 1; @@ -1965,7 +1977,7 @@ mod tests { REGULAR_PAYLOAD.declared_weight, ); let post_dispatch_weight = Pallet::::receive_messages_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_RELAYER_A, proof, messages_count, @@ -1980,16 +1992,26 @@ mod tests { // when dispatch is returning `unspent_weight < declared_weight` let (pre, post) = submit_with_unspent_weight(1, 1, false); - assert_eq!(post, pre - 1); + assert_eq!(post.ref_time(), pre.ref_time() - 1); // when dispatch is returning `unspent_weight = declared_weight` - let (pre, post) = submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight, false); - assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight); + let (pre, post) = + submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight.ref_time(), false); + assert_eq!( + post.ref_time(), + pre.ref_time() - REGULAR_PAYLOAD.declared_weight.ref_time() + ); // when dispatch is returning `unspent_weight > declared_weight` - let (pre, post) = - submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight + 1, false); - assert_eq!(post, pre - REGULAR_PAYLOAD.declared_weight); + let (pre, post) = submit_with_unspent_weight( + 3, + REGULAR_PAYLOAD.declared_weight.ref_time() + 1, + false, + ); + assert_eq!( + post.ref_time(), + pre.ref_time() - REGULAR_PAYLOAD.declared_weight.ref_time() + ); // when there's no unspent weight let (pre, post) = submit_with_unspent_weight(4, 0, false); @@ -1998,8 +2020,10 @@ mod tests { // when dispatch is returning `unspent_weight < declared_weight` AND message is prepaid let (pre, post) = submit_with_unspent_weight(5, 1, true); assert_eq!( - post, - pre - 1 - ::WeightInfo::pay_inbound_dispatch_fee_overhead() + post.ref_time(), + pre.ref_time() - + 1 - ::WeightInfo::pay_inbound_dispatch_fee_overhead() + .ref_time() ); }); } @@ -2043,7 +2067,7 @@ mod tests { // first tx with messages 1+2 assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(messages_1_and_2_proof), UnrewardedRelayersState { unrewarded_relayer_entries: 1, @@ -2054,7 +2078,7 @@ mod tests { )); // second tx with message 3 assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(messages_3_proof), UnrewardedRelayersState { unrewarded_relayer_entries: 1, @@ -2097,7 +2121,7 @@ mod tests { crate::mock::DbWeight::get(), ); let post_dispatch_weight = Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), proof, relayers_state, ) @@ -2157,7 +2181,7 @@ mod tests { // numer of actually confirmed messages is `1`. assert_noop!( Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 1, relayers: Default::default() }, @@ -2178,32 +2202,40 @@ mod tests { large_payload.extra = vec![2; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 5]; assert_ok!(Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, small_payload, 100, )); assert_ok!(Pallet::::send_message( - Origin::signed(1), + RuntimeOrigin::signed(1), TEST_LANE_ID, large_payload, 100, )); - let small_weight = - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1) - .expect("increase_message_fee has failed") - .actual_weight - .expect("increase_message_fee always returns Some"); + let small_weight = Pallet::::increase_message_fee( + RuntimeOrigin::signed(1), + TEST_LANE_ID, + 1, + 1, + ) + .expect("increase_message_fee has failed") + .actual_weight + .expect("increase_message_fee always returns Some"); - let large_weight = - Pallet::::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 2, 1) - .expect("increase_message_fee has failed") - .actual_weight - .expect("increase_message_fee always returns Some"); + let large_weight = Pallet::::increase_message_fee( + RuntimeOrigin::signed(1), + TEST_LANE_ID, + 2, + 1, + ) + .expect("increase_message_fee has failed") + .actual_weight + .expect("increase_message_fee always returns Some"); assert!( - large_weight > small_weight, + large_weight.ref_time() > small_weight.ref_time(), "Actual post-dispatch weigth for larger message {} must be larger than {} for small message", large_weight, small_weight, @@ -2225,7 +2257,7 @@ mod tests { // confirm delivery of all sent messages assert_ok!(Pallet::::receive_messages_delivery_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( TEST_LANE_ID, InboundLaneData { @@ -2332,7 +2364,7 @@ mod tests { REGULAR_PAYLOAD.encode(), OutboundMessageDetails { nonce: 0, - dispatch_weight: 0, + dispatch_weight: Weight::from_ref_time(0), size: 0, delivery_and_dispatch_fee: 0, dispatch_fee_payment: diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 41ae0352cfb04..4e6a6e53fbc16 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -87,23 +87,23 @@ frame_support::construct_runtime! { parameter_types! { pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; } impl frame_system::Config for TestRuntime { - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type Index = u64; - type Call = Call; + type RuntimeCall = RuntimeCall; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = SubstrateHeader; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; @@ -128,7 +128,7 @@ impl pallet_balances::Config for TestRuntime { type MaxLocks = (); type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type WeightInfo = (); @@ -159,7 +159,7 @@ impl MessagesParameter for TestMessagesParameter { } impl Config for TestRuntime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Parameter = TestMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; @@ -185,7 +185,7 @@ impl Config for TestRuntime { type BridgedChainId = TestBridgedChainId; } -impl SenderOrigin for Origin { +impl SenderOrigin for RuntimeOrigin { fn linked_account(&self) -> Option { match self.caller { OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => @@ -298,11 +298,11 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier for TestLaneMessageVerifier { +impl LaneMessageVerifier for TestLaneMessageVerifier { type Error = &'static str; fn verify_message( - _submitter: &Origin, + _submitter: &RuntimeOrigin, delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, @@ -328,7 +328,8 @@ impl TestMessageDeliveryAndDispatchPayment { /// Returns true if given fee has been paid by given submitter. pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - let raw_origin: Result, _> = Origin::signed(submitter).into(); + let raw_origin: Result, _> = + RuntimeOrigin::signed(submitter).into(); frame_support::storage::unhashed::get(b":message-fee:") == Some((raw_origin.unwrap(), fee)) } @@ -340,13 +341,13 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment +impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { type Error = &'static str; fn pay_delivery_and_dispatch_fee( - submitter: &Origin, + submitter: &RuntimeOrigin, fee: &TestMessageFee, ) -> Result<(), Self::Error> { if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) { @@ -451,7 +452,7 @@ impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 { fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode(); frame_support::storage::unhashed::put(&key, &true); - 0 + Weight::from_ref_time(0) } } @@ -482,7 +483,7 @@ impl MessageDispatch for TestMessageDispatch { fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { Ok(payload) => payload.declared_weight, - Err(_) => 0, + Err(_) => Weight::from_ref_time(0), } } @@ -503,8 +504,13 @@ pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message TestPayload { - TestPayload { id, declared_weight, dispatch_result: dispatch_result(0), extra: Vec::new() } +pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { + TestPayload { + id, + declared_weight: Weight::from_ref_time(declared_weight), + dispatch_result: dispatch_result(0), + extra: Vec::new(), + } } /// Return message data with valid fee for given payload. @@ -513,10 +519,10 @@ pub fn message_data(payload: TestPayload) -> MessageData { } /// Returns message dispatch result with given unspent weight. -pub const fn dispatch_result(unspent_weight: Weight) -> MessageDispatchResult { +pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult { MessageDispatchResult { dispatch_result: true, - unspent_weight, + unspent_weight: Weight::from_ref_time(unspent_weight), dispatch_fee_paid_during_dispatch: true, } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 02b014120f14d..3801b57b61a4c 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 +//! DATE: 2022-10-17, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -72,149 +72,149 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn send_minimal_message_worst_case() -> Weight { - (62_300_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(10 as Weight)) + Weight::from_ref_time(61_807_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(10 as u64)) } fn send_1_kb_message_worst_case() -> Weight { - (63_176_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(10 as Weight)) + Weight::from_ref_time(65_074_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(10 as u64)) } fn send_16_kb_message_worst_case() -> Weight { - (73_472_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(10 as Weight)) + Weight::from_ref_time(73_584_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(10 as u64)) } fn maximal_increase_message_fee() -> Weight { - (2_539_209_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(2_522_629_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn increase_message_fee(i: u32) -> Weight { - (0 as Weight) - .saturating_add((1_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(27_072_000 as u64) + .saturating_add(Weight::from_ref_time(892 as u64).saturating_mul(i as u64)) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_message_proof() -> Weight { - (49_205_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(49_628_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - (62_182_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(61_514_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (55_928_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(65_960_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - (47_298_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(48_009_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - (105_016_000 as Weight) - .saturating_add(T::DbWeight::get().reads(3 as Weight)) - .saturating_add(T::DbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(100_439_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_prepaid_message_proof() -> Weight { - (49_067_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(50_463_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - (58_520_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(57_383_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (61_563_000 as Weight) - .saturating_add(T::DbWeight::get().reads(6 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(62_003_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (63_197_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + Weight::from_ref_time(64_401_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { fn send_minimal_message_worst_case() -> Weight { - (62_300_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(10 as Weight)) + Weight::from_ref_time(61_807_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(10 as u64)) } fn send_1_kb_message_worst_case() -> Weight { - (63_176_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(10 as Weight)) + Weight::from_ref_time(65_074_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(10 as u64)) } fn send_16_kb_message_worst_case() -> Weight { - (73_472_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(10 as Weight)) + Weight::from_ref_time(73_584_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(10 as u64)) } fn maximal_increase_message_fee() -> Weight { - (2_539_209_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(2_522_629_000 as u64) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn increase_message_fee(i: u32) -> Weight { - (0 as Weight) - .saturating_add((1_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(27_072_000 as u64) + .saturating_add(Weight::from_ref_time(892 as u64).saturating_mul(i as u64)) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_message_proof() -> Weight { - (49_205_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(49_628_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - (62_182_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(61_514_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - (55_928_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(65_960_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - (47_298_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(48_009_000 as u64) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - (105_016_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(3 as Weight)) - .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + Weight::from_ref_time(100_439_000 as u64) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_prepaid_message_proof() -> Weight { - (49_067_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(50_463_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - (58_520_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(57_383_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - (61_563_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(6 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(62_003_000 as u64) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - (63_197_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + Weight::from_ref_time(64_401_000 as u64) + .saturating_add(RocksDbWeight::get().reads(7 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 52eb426190530..eaf6bc1029eff 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -43,14 +43,14 @@ pub fn ensure_weights_are_correct( db_weight: RuntimeDbWeight, ) { // verify `send_message` weight components - assert_ne!(W::send_message_overhead(), 0); - assert_ne!(W::send_message_size_overhead(0), 0); + assert_ne!(W::send_message_overhead(), Weight::from_ref_time(0)); + assert_ne!(W::send_message_size_overhead(0), Weight::from_ref_time(0)); // verify `receive_messages_proof` weight components - assert_ne!(W::receive_messages_proof_overhead(), 0); - assert_ne!(W::receive_messages_proof_messages_overhead(1), 0); - assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), 0); - assert_ne!(W::storage_proof_size_overhead(1), 0); + assert_ne!(W::receive_messages_proof_overhead(), Weight::from_ref_time(0)); + assert_ne!(W::receive_messages_proof_messages_overhead(1), Weight::from_ref_time(0)); + assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), Weight::from_ref_time(0)); + assert_ne!(W::storage_proof_size_overhead(1), Weight::from_ref_time(0)); // verify that the hardcoded value covers `receive_messages_proof` weight let actual_single_regular_message_delivery_tx_weight = W::receive_messages_proof_weight( @@ -58,11 +58,11 @@ pub fn ensure_weights_are_correct( (EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize, ), 1, - 0, + Weight::from_ref_time(0), ); assert!( - actual_single_regular_message_delivery_tx_weight <= - expected_default_message_delivery_tx_weight, + actual_single_regular_message_delivery_tx_weight.ref_time() <= + expected_default_message_delivery_tx_weight.ref_time(), "Default message delivery transaction weight {} is larger than expected weight {}", actual_single_regular_message_delivery_tx_weight, expected_default_message_delivery_tx_weight, @@ -71,15 +71,16 @@ pub fn ensure_weights_are_correct( // verify that hardcoded value covers additional byte length of `receive_messages_proof` weight let actual_additional_byte_delivery_weight = W::storage_proof_size_overhead(1); assert!( - actual_additional_byte_delivery_weight <= expected_additional_byte_delivery_weight, + actual_additional_byte_delivery_weight.ref_time() <= + expected_additional_byte_delivery_weight.ref_time(), "Single additional byte delivery weight {} is larger than expected weight {}", actual_additional_byte_delivery_weight, expected_additional_byte_delivery_weight, ); // verify `receive_messages_delivery_proof` weight components - assert_ne!(W::receive_messages_delivery_proof_overhead(), 0); - assert_ne!(W::storage_proof_size_overhead(1), 0); + assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::from_ref_time(0)); + assert_ne!(W::storage_proof_size_overhead(1), Weight::from_ref_time(0)); // `receive_messages_delivery_proof_messages_overhead` and // `receive_messages_delivery_proof_relayers_overhead` may return zero if rewards are not paid @@ -96,8 +97,8 @@ pub fn ensure_weights_are_correct( db_weight, ); assert!( - actual_messages_delivery_confirmation_tx_weight <= - expected_messages_delivery_confirmation_tx_weight, + actual_messages_delivery_confirmation_tx_weight.ref_time() <= + expected_messages_delivery_confirmation_tx_weight.ref_time(), "Messages delivery confirmation transaction weight {} is larger than expected weight {}", actual_messages_delivery_confirmation_tx_weight, expected_messages_delivery_confirmation_tx_weight, @@ -106,7 +107,7 @@ pub fn ensure_weights_are_correct( // verify pay-dispatch-fee overhead for inbound messages let actual_pay_inbound_dispatch_fee_weight = W::pay_inbound_dispatch_fee_overhead(); assert!( - actual_pay_inbound_dispatch_fee_weight <= expected_pay_inbound_dispatch_fee_weight, + actual_pay_inbound_dispatch_fee_weight.ref_time() <= expected_pay_inbound_dispatch_fee_weight.ref_time(), "Weight {} of pay-dispatch-fee overhead for inbound messages is larger than expected weight {}", actual_pay_inbound_dispatch_fee_weight, expected_pay_inbound_dispatch_fee_weight, @@ -140,7 +141,7 @@ pub fn ensure_able_to_receive_message( max_incoming_message_dispatch_weight, ); assert!( - max_delivery_transaction_dispatch_weight <= max_extrinsic_weight, + max_delivery_transaction_dispatch_weight.ref_time() <= max_extrinsic_weight.ref_time(), "Weight of maximal message delivery transaction + {} is larger than maximal possible transaction weight {}", max_delivery_transaction_dispatch_weight, max_extrinsic_weight, @@ -179,7 +180,7 @@ pub fn ensure_able_to_receive_confirmation( db_weight, ); assert!( - max_confirmation_transaction_dispatch_weight <= max_extrinsic_weight, + max_confirmation_transaction_dispatch_weight.ref_time() <= max_extrinsic_weight.ref_time(), "Weight of maximal confirmation transaction {} is larger than maximal possible transaction weight {}", max_confirmation_transaction_dispatch_weight, max_extrinsic_weight, @@ -264,13 +265,13 @@ pub trait WeightInfoExt: WeightInfo { // message let callback_overhead = relayers_state .total_messages - .saturating_mul(Self::single_message_callback_overhead(db_weight)); + .saturating_mul(Self::single_message_callback_overhead(db_weight).ref_time()); transaction_overhead .saturating_add(messages_overhead) .saturating_add(relayers_overhead) .saturating_add(proof_size_overhead) - .saturating_add(callback_overhead) + .saturating_add(Weight::from_ref_time(callback_overhead)) } // Functions that are used by extrinsics weights formulas. @@ -305,7 +306,7 @@ pub trait WeightInfoExt: WeightInfo { let weight_of_single_message_and_single_tx_overhead = Self::receive_single_message_proof(); weight_of_two_messages_and_single_tx_overhead .saturating_sub(weight_of_single_message_and_single_tx_overhead) - .saturating_mul(messages as Weight) + .saturating_mul(messages as _) } /// Returns weight that needs to be accounted when message delivery transaction @@ -336,7 +337,7 @@ pub trait WeightInfoExt: WeightInfo { let weight_of_single_message = Self::receive_delivery_proof_for_single_message(); weight_of_two_messages .saturating_sub(weight_of_single_message) - .saturating_mul(messages as Weight) + .saturating_mul(messages as _) } /// Returns weight that needs to be accounted when receiving confirmations for given a number of @@ -348,7 +349,7 @@ pub trait WeightInfoExt: WeightInfo { Self::receive_delivery_proof_for_two_messages_by_single_relayer(); weight_of_two_messages_by_two_relayers .saturating_sub(weight_of_two_messages_by_single_relayer) - .saturating_mul(relayers as Weight) + .saturating_mul(relayers as _) } /// Returns weight that needs to be accounted when storage proof of given size is received @@ -360,7 +361,7 @@ pub trait WeightInfoExt: WeightInfo { /// relayer must pay when it relays proof of given size (even if cost based on other parameters /// is less than that cost). fn storage_proof_size_overhead(proof_size: u32) -> Weight { - let proof_size_in_bytes = proof_size as Weight; + let proof_size_in_bytes = proof_size; let byte_weight = (Self::receive_single_message_proof_16_kb() - Self::receive_single_message_proof_1_kb()) / (15 * 1024); diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs index 05500cf41ddb3..5c2f54257ff8c 100644 --- a/modules/parachains/src/extension.rs +++ b/modules/parachains/src/extension.rs @@ -31,7 +31,7 @@ use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, /// pallet will be used in our environment. impl< Call: IsSubType, T>>, - T: frame_system::Config + Config, + T: frame_system::Config + Config, I: 'static, > FilterCall for Pallet where @@ -77,7 +77,7 @@ where mod tests { use crate::{ extension::FilterCall, - mock::{run_test, Call, TestRuntime}, + mock::{run_test, RuntimeCall, TestRuntime}, ParaInfo, ParasInfo, RelayBlockNumber, }; use bp_parachains::BestParaHeadHash; @@ -87,13 +87,14 @@ mod tests { num: RelayBlockNumber, parachains: Vec<(ParaId, ParaHash)>, ) -> bool { - crate::Pallet::::validate(&Call::Parachains( - crate::Call::::submit_parachain_heads { - at_relay_block: (num, Default::default()), - parachains, - parachain_heads_proof: ParaHeadsProof(Vec::new()), - }, - )) + crate::Pallet::::validate(&RuntimeCall::Parachains(crate::Call::< + TestRuntime, + (), + >::submit_parachain_heads { + at_relay_block: (num, Default::default()), + parachains, + parachain_heads_proof: ParaHeadsProof(Vec::new()), + })) .is_ok() } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index ac21e997f3146..e0c3ff8340f6b 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -29,7 +29,7 @@ pub use weights_ext::WeightInfoExt; use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo}; use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::StorageProofError; -use frame_support::{traits::Contains, weights::PostDispatchInfo}; +use frame_support::{dispatch::PostDispatchInfo, traits::Contains}; use sp_runtime::traits::Header as HeaderT; use sp_std::vec::Vec; @@ -132,7 +132,8 @@ pub mod pallet { pallet_bridge_grandpa::Config { /// The overarching event type. - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + + IsType<::RuntimeEvent>; /// Benchmarks results from runtime we're plugged into. type WeightInfo: WeightInfoExt; @@ -620,7 +621,7 @@ pub mod pallet { mod tests { use super::*; use crate::mock::{ - run_test, test_relay_header, Event as TestEvent, Origin, TestRuntime, + run_test, test_relay_header, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, MAXIMAL_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; use codec::Encode; @@ -650,7 +651,7 @@ mod tests { fn initialize(state_root: RelayBlockHash) { pallet_bridge_grandpa::Pallet::::initialize( - Origin::root(), + RuntimeOrigin::root(), bp_header_chain::InitializationData { header: Box::new(test_relay_header(0, state_root)), authority_list: authority_list(), @@ -670,7 +671,7 @@ mod tests { let justification = make_default_justification(&header); assert_ok!( pallet_bridge_grandpa::Pallet::::submit_finality_proof( - Origin::signed(1), + RuntimeOrigin::signed(1), Box::new(header), justification, ) @@ -736,7 +737,7 @@ mod tests { proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (relay_chain_block, test_relay_header(relay_chain_block, relay_state_root).hash()), parachains, proof, @@ -747,7 +748,7 @@ mod tests { let db_weight = ::DbWeight::get(); WeightInfoOf::::submit_parachain_heads_weight(db_weight, proof, 1) .saturating_sub(if prune_expected { - 0 + Weight::from_ref_time(0) } else { WeightInfoOf::::parachain_head_pruning_weight(db_weight) }) @@ -765,7 +766,7 @@ mod tests { PalletOperatingMode::::put(BasicOperatingMode::Halted); assert_noop!( Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains.clone(), proof.clone(), @@ -776,7 +777,7 @@ mod tests { // `submit_parachain_heads()` should succeed now that the pallet is resumed. PalletOperatingMode::::put(BasicOperatingMode::Normal); assert_ok!(Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, @@ -795,7 +796,7 @@ mod tests { let expected_weight = WeightInfo::submit_parachain_heads_weight(DbWeight::get(), &proof, 2); let result = Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, @@ -969,7 +970,7 @@ mod tests { )); initialize(state_root); let result = Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, @@ -1159,7 +1160,7 @@ mod tests { // parachain initialize(state_root); let result = Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, @@ -1303,7 +1304,7 @@ mod tests { // => we'll leave previous value proceed(20, state_root_10_at_20); assert_ok!(Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (20, test_relay_header(20, state_root_10_at_20).hash()), parachains_10_at_20, proof_10_at_20, @@ -1319,7 +1320,7 @@ mod tests { // => we'll update value proceed(30, state_root_10_at_30); assert_ok!(Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (30, test_relay_header(30, state_root_10_at_30).hash()), parachains_10_at_30, proof_10_at_30, @@ -1360,7 +1361,7 @@ mod tests { run_test(|| { initialize(state_root); assert_ok!(Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, @@ -1385,7 +1386,7 @@ mod tests { run_test(|| { initialize(state_root); assert_ok!(Pallet::::submit_parachain_heads( - Origin::signed(1), + RuntimeOrigin::signed(1), (0, test_relay_header(0, state_root).hash()), parachains, proof, diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index f1d39592b20a4..9638472aa985f 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -53,22 +53,22 @@ construct_runtime! { parameter_types! { pub const BlockHashCount: TestNumber = 250; - pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Config for TestRuntime { - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type Index = u64; - type Call = Call; + type RuntimeCall = RuntimeCall; type BlockNumber = TestNumber; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; @@ -117,7 +117,7 @@ parameter_types! { } impl pallet_bridge_parachains::Config for TestRuntime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type ParasPalletName = ParasPalletName; diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 1ab2e6c554806..43cd68b01d1dc 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -61,41 +61,41 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { - (0 as Weight) - .saturating_add((24_869_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(T::DbWeight::get().reads(2 as Weight)) - .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) - .saturating_add(T::DbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) + Weight::from_ref_time(0 as u64) + .saturating_add(Weight::from_ref_time(24_869_000 as u64).saturating_mul(p as u64)) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(p as u64))) + .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(p as u64))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - (56_262_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + Weight::from_ref_time(56_262_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - (105_189_000 as Weight) - .saturating_add(T::DbWeight::get().reads(4 as Weight)) - .saturating_add(T::DbWeight::get().writes(3 as Weight)) + Weight::from_ref_time(105_189_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { - (0 as Weight) - .saturating_add((24_869_000 as Weight).saturating_mul(p as Weight)) - .saturating_add(RocksDbWeight::get().reads(2 as Weight)) - .saturating_add(RocksDbWeight::get().reads((2 as Weight).saturating_mul(p as Weight))) - .saturating_add(RocksDbWeight::get().writes((3 as Weight).saturating_mul(p as Weight))) + Weight::from_ref_time(0 as u64) + .saturating_add(Weight::from_ref_time(24_869_000 as u64).saturating_mul(p as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(p as u64))) + .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(p as u64))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - (56_262_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + Weight::from_ref_time(56_262_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - (105_189_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + Weight::from_ref_time(105_189_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) } } diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs index 63684ecc2158b..eecdfe903593e 100644 --- a/modules/parachains/src/weights_ext.rs +++ b/modules/parachains/src/weights_ext.rs @@ -62,8 +62,8 @@ pub trait WeightInfoExt: WeightInfo { ); // potential pruning weight (refunded if hasn't happened) - let pruning_weight = (parachains_count as Weight) - .saturating_mul(Self::parachain_head_pruning_weight(db_weight)); + let pruning_weight = + Self::parachain_head_pruning_weight(db_weight).saturating_mul(parachains_count as u64); base_weight.saturating_add(proof_size_overhead).saturating_add(pruning_weight) } @@ -87,11 +87,10 @@ pub trait WeightInfoExt: WeightInfo { /// Returns weight that needs to be accounted when storage proof of given size is received. fn storage_proof_size_overhead(extra_proof_bytes: u32) -> Weight { - let extra_proof_bytes_in_bytes = extra_proof_bytes as Weight; let extra_byte_weight = (Self::submit_parachain_heads_with_16kb_proof() - Self::submit_parachain_heads_with_1kb_proof()) / (15 * 1024); - extra_proof_bytes_in_bytes.saturating_mul(extra_byte_weight) + extra_byte_weight.saturating_mul(extra_proof_bytes as u64) } } diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 779cc285c99fa..f3195f1288ebe 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -46,7 +46,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// The overarching event type. - type Event: From> + IsType<::Event>; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// Type of relayer reward. type Reward: AtLeast32BitUnsigned + Copy + Parameter + MaxEncodedLen; /// Pay rewards adapter. @@ -113,7 +113,7 @@ pub mod pallet { #[cfg(test)] mod tests { use super::*; - use mock::{Event as TestEvent, *}; + use mock::{RuntimeEvent as TestEvent, *}; use crate::Event::RewardPaid; use frame_support::{assert_noop, assert_ok, traits::fungible::Inspect}; @@ -129,7 +129,7 @@ mod tests { fn root_cant_claim_anything() { run_test(|| { assert_noop!( - Pallet::::claim_rewards(Origin::root()), + Pallet::::claim_rewards(RuntimeOrigin::root()), DispatchError::BadOrigin, ); }); @@ -139,7 +139,7 @@ mod tests { fn relayer_cant_claim_if_no_reward_exists() { run_test(|| { assert_noop!( - Pallet::::claim_rewards(Origin::signed(REGULAR_RELAYER)), + Pallet::::claim_rewards(RuntimeOrigin::signed(REGULAR_RELAYER)), Error::::NoRewardForRelayer, ); }); @@ -150,7 +150,7 @@ mod tests { run_test(|| { RelayerRewards::::insert(FAILING_RELAYER, 100); assert_noop!( - Pallet::::claim_rewards(Origin::signed(FAILING_RELAYER)), + Pallet::::claim_rewards(RuntimeOrigin::signed(FAILING_RELAYER)), Error::::FailedToPayReward, ); }); @@ -162,7 +162,9 @@ mod tests { get_ready_for_events(); RelayerRewards::::insert(REGULAR_RELAYER, 100); - assert_ok!(Pallet::::claim_rewards(Origin::signed(REGULAR_RELAYER))); + assert_ok!(Pallet::::claim_rewards(RuntimeOrigin::signed( + REGULAR_RELAYER + ))); assert_eq!(RelayerRewards::::get(REGULAR_RELAYER), None); //Check if the `RewardPaid` event was emitted. diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 2ceabc6621fb3..d090da3e6da56 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -51,16 +51,16 @@ parameter_types! { } impl frame_system::Config for TestRuntime { - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type Index = u64; - type Call = Call; + type RuntimeCall = RuntimeCall; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = SubstrateHeader; - type Event = Event; + type RuntimeEvent = RuntimeEvent; type BlockHashCount = frame_support::traits::ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; @@ -81,7 +81,7 @@ impl pallet_balances::Config for TestRuntime { type MaxLocks = (); type Balance = Balance; type DustRemoval = (); - type Event = Event; + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = frame_support::traits::ConstU64<1>; type AccountStore = frame_system::Pallet; type WeightInfo = (); @@ -95,7 +95,7 @@ parameter_types! { // we're not testing messages pallet here, so values in this config might be crazy impl pallet_bridge_messages::Config for TestRuntime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); type Parameter = (); type MaxMessagesToPruneAtOnce = frame_support::traits::ConstU64<0>; @@ -122,7 +122,7 @@ impl pallet_bridge_messages::Config for TestRuntime { } impl pallet_bridge_relayers::Config for TestRuntime { - type Event = Event; + type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = TestPaymentProcedure; type WeightInfo = (); diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index f027ab6429024..d472810c5ccff 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -31,7 +31,7 @@ pub struct MessageDeliveryAndDispatchPaymentAdapter - MessageDeliveryAndDispatchPayment + MessageDeliveryAndDispatchPayment for MessageDeliveryAndDispatchPaymentAdapter where T: Config + pallet_bridge_messages::Config, @@ -41,7 +41,7 @@ where type Error = &'static str; fn pay_delivery_and_dispatch_fee( - _submitter: &T::Origin, + _submitter: &T::RuntimeOrigin, _fee: &T::Reward, ) -> Result<(), Self::Error> { // nothing shall happen here, because XCM deals with fee payment (planned to be burnt? diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index afecbe9d6d750..b8df8c94499cc 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -59,17 +59,17 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn claim_rewards() -> Weight { - (55_856_000 as Weight) - .saturating_add(T::DbWeight::get().reads(2 as Weight)) - .saturating_add(T::DbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(55_856_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { fn claim_rewards() -> Weight { - (55_856_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(2 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + Weight::from_ref_time(55_856_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } } diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index f8475851bb9a7..073013d92d030 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -153,22 +153,22 @@ mod tests { parameter_types! { pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Config for TestRuntime { - type Origin = Origin; + type RuntimeOrigin = RuntimeOrigin; type Index = u64; - type Call = Call; + type RuntimeCall = RuntimeCall; type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type Event = (); + type RuntimeEvent = (); type BlockHashCount = BlockHashCount; type Version = (); type PalletInfo = PalletInfo; @@ -191,7 +191,7 @@ mod tests { } impl pallet_session::Config for TestRuntime { - type Event = (); + type RuntimeEvent = (); type ValidatorId = ::AccountId; type ValidatorIdOf = ConvertInto; type ShouldEndSession = pallet_session::PeriodicSessions; diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 4cd8b30f7ff90..c4d77b80febf8 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -16,7 +16,7 @@ fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.3.1", optional = true } -parity-util-mem = { version = "0.11", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.12", default-features = false, features = ["primitive-types"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index e63903aff7d57..9c0b4782e37eb 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -25,7 +25,8 @@ use bp_messages::{ }; use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, + dispatch::DispatchClass, + weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, Parameter, RuntimeDebug, }; use frame_system::limits; @@ -56,11 +57,8 @@ pub const TX_EXTRA_BYTES: u32 = 103; /// Maximum weight of single Millau block. /// /// This represents 0.5 seconds of compute assuming a target block time of six seconds. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2; - -/// Represents the average portion of a block's weight that will be used by an -/// `on_initialize()` runtime call. -pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` +pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_div(2); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -77,21 +75,22 @@ pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` /// bytes is delivered. The message must have dispatch weight set to zero. The result then must be /// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); /// Increase of delivery transaction weight on Millau chain with every additional message byte. /// /// This value is a result of /// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then /// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); /// Maximal weight of single message delivery confirmation transaction on Millau chain. /// /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` /// weight formula computation for the case when single message is confirmed. The result then must /// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = + Weight::from_ref_time(2_000_000_000); /// Weight of pay-dispatch-fee operation for inbound messages at Millau chain. /// @@ -100,7 +99,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// chain. Don't put too much reserve there, because it is used to **decrease** /// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery /// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(700_000_000); /// The target length of a session (how often authorities change) on Millau measured in of number of /// blocks. @@ -227,21 +226,8 @@ impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() - // Allowance for Normal class - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - // Allowance for Operational class - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Extra reserved space for Operational class - weights.reserved = Some(MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - // By default Mandatory class is not limited at all. - // This parameter is used to derive maximal size of a single extrinsic. - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); + pub BlockWeights: limits::BlockWeights = + limits::BlockWeights::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); } /// Name of the With-Millau GRANDPA pallet instance that is deployed at bridged chains. diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 8afbf87725c2b..3a54a2fb54805 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -23,7 +23,8 @@ use bp_messages::{ }; use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, + dispatch::DispatchClass, + weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, Parameter, RuntimeDebug, }; use frame_system::limits; @@ -53,11 +54,8 @@ pub const TX_EXTRA_BYTES: u32 = 104; /// Maximal weight of single RialtoParachain block. /// /// This represents two seconds of compute assuming a target block time of six seconds. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; - -/// Represents the average portion of a block's weight that will be used by an -/// `on_initialize()` runtime call. -pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` +pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_mul(2); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -74,7 +72,7 @@ pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` /// bytes is delivered. The message must have dispatch weight set to zero. The result then must be /// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); /// Increase of delivery transaction weight on RialtoParachain chain with every additional message /// byte. @@ -82,14 +80,15 @@ pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// This value is a result of /// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then /// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); /// Maximal weight of single message delivery confirmation transaction on RialtoParachain chain. /// /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` /// weight formula computation for the case when single message is confirmed. The result then must /// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = + Weight::from_ref_time(2_000_000_000); /// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. /// @@ -98,7 +97,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// chain. Don't put too much reserve there, because it is used to **decrease** /// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery /// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(600_000_000); /// Block number type used in Rialto. pub type BlockNumber = u32; @@ -164,21 +163,8 @@ impl Chain for RialtoParachain { frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() - // Allowance for Normal class - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - // Allowance for Operational class - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Extra reserved space for Operational class - weights.reserved = Some(MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - // By default Mandatory class is not limited at all. - // This parameter is used to derive maximal size of a single extrinsic. - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); + pub BlockWeights: limits::BlockWeights = + limits::BlockWeights::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); } /// Name of the With-Rialto-Parachain messages pallet instance that is deployed at bridged chains. diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index d87e82e78a2ff..4d272fe68399f 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -23,7 +23,8 @@ use bp_messages::{ }; use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ - weights::{constants::WEIGHT_PER_SECOND, DispatchClass, IdentityFee, Weight}, + dispatch::DispatchClass, + weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, Parameter, RuntimeDebug, }; use frame_system::limits; @@ -47,11 +48,8 @@ pub const TX_EXTRA_BYTES: u32 = 104; /// Maximal weight of single Rialto block. /// /// This represents two seconds of compute assuming a target block time of six seconds. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; - -/// Represents the average portion of a block's weight that will be used by an -/// `on_initialize()` runtime call. -pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` +pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_mul(2); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -68,21 +66,22 @@ pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` /// bytes is delivered. The message must have dispatch weight set to zero. The result then must be /// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); /// Increase of delivery transaction weight on Rialto chain with every additional message byte. /// /// This value is a result of /// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then /// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); /// Maximal weight of single message delivery confirmation transaction on Rialto chain. /// /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` /// weight formula computation for the case when single message is confirmed. The result then must /// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = + Weight::from_ref_time(2_000_000_000); /// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. /// @@ -91,7 +90,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// chain. Don't put too much reserve there, because it is used to **decrease** /// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery /// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 700_000_000; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(700_000_000); /// The target length of a session (how often authorities change) on Rialto measured in of number of /// blocks. @@ -193,21 +192,8 @@ impl Chain for Rialto { frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() - // Allowance for Normal class - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - // Allowance for Operational class - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Extra reserved space for Operational class - weights.reserved = Some(MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - // By default Mandatory class is not limited at all. - // This parameter is used to derive maximal size of a single extrinsic. - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); + pub BlockWeights: limits::BlockWeights = + limits::BlockWeights::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); } /// Name of the With-Rialto GRANDPA pallet instance that is deployed at bridged chains. diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 2fd27094cb50f..8d5d8d9a924d1 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -33,12 +33,15 @@ pub type Westend = PolkadotLike; pub enum Call {} impl sp_runtime::traits::Dispatchable for Call { - type Origin = (); + type RuntimeOrigin = (); type Config = (); type Info = (); type PostInfo = (); - fn dispatch(self, _origin: Self::Origin) -> sp_runtime::DispatchResultWithInfo { + fn dispatch( + self, + _origin: Self::RuntimeOrigin, + ) -> sp_runtime::DispatchResultWithInfo { unimplemented!("The Call is not expected to be dispatched.") } } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 70b52dc63aab8..e1f2c0c3c8dfb 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -212,7 +212,7 @@ impl MessagesBridge Result { - Ok(SendMessageArtifacts { nonce: 0, weight: 0 }) + Ok(SendMessageArtifacts { nonce: 0, weight: Weight::from_ref_time(0) }) } } @@ -233,10 +233,11 @@ pub trait OnDeliveryConfirmed { fn on_messages_delivered(_lane: &LaneId, _messages: &DeliveredMessages) -> Weight; } +#[allow(clippy::let_and_return)] #[impl_trait_for_tuples::impl_for_tuples(30)] impl OnDeliveryConfirmed for Tuple { fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { - let mut total_weight: Weight = 0; + let mut total_weight = Weight::from_ref_time(0); for_tuples!( #( total_weight = total_weight.saturating_add(Tuple::on_messages_delivered(lane, messages)); @@ -254,7 +255,7 @@ pub trait OnMessageAccepted { impl OnMessageAccepted for () { fn on_messages_accepted(_lane: &LaneId, _message: &MessageNonce) -> Weight { - 0 + Weight::from_ref_time(0) } } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index a5686e4abea73..05623d0efba35 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -167,7 +167,7 @@ impl MessageDispatch for ForbidInboundMessages { ) -> MessageDispatchResult { MessageDispatchResult { dispatch_result: false, - unspent_weight: 0, + unspent_weight: Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 9a68e8ccc2db6..a9db53a8bf01e 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -parity-util-mem = { version = "0.11.0", optional = true } +parity-util-mem = { version = "0.12.0", optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 476b1f2f23061..34eb4ae13b19a 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -20,11 +20,11 @@ use bp_messages::MessageNonce; use bp_runtime::{Chain, EncodedOrDecodedCall}; use codec::Compact; use frame_support::{ - dispatch::Dispatchable, + dispatch::{DispatchClass, Dispatchable}, parameter_types, weights::{ constants::{BlockExecutionWeight, WEIGHT_PER_SECOND}, - DispatchClass, Weight, + Weight, }, Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128, }; @@ -73,7 +73,8 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// All Polkadot-like chains allow 2 seconds of compute with a 6-second average block time. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = 2 * WEIGHT_PER_SECOND; +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` +pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_mul(2); /// All Polkadot-like chains assume that an on-initialize consumes 1 percent of the weight on /// average, hence a single extrinsic will not be allowed to consume more than @@ -134,7 +135,8 @@ pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192; /// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` /// weight formula computation for the case when single message is confirmed. The result then must /// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000_000; +pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = + Weight::from_ref_time(2_000_000_000); /// Increase of delivery transaction weight on Polkadot-like chain with every additional message /// byte. @@ -142,7 +144,7 @@ pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = 2_000_000 /// This value is a result of /// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then /// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = 25_000; +pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); /// Maximal number of bytes, included in the signed Polkadot-like transaction apart from the encoded /// call itself. @@ -156,7 +158,7 @@ pub const TX_EXTRA_BYTES: u32 = 256; /// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` /// bytes is delivered. The message must have dispatch weight set to zero. The result then must be /// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; +pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); /// Weight of pay-dispatch-fee operation for inbound messages at Polkadot-like chain. /// @@ -165,7 +167,7 @@ pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = 1_500_000_000; /// chain. Don't put too much reserve there, because it is used to **decrease** /// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery /// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = 600_000_000; +pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(600_000_000); /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 94a231333ded7..cd3951920491c 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -403,7 +403,7 @@ pub trait OwnedBridgeModule { } /// Ensure that the origin is either root, or `PalletOwner`. - fn ensure_owner_or_root(origin: T::Origin) -> Result<(), BadOrigin> { + fn ensure_owner_or_root(origin: T::RuntimeOrigin) -> Result<(), BadOrigin> { match origin.into() { Ok(RawOrigin::Root) => Ok(()), Ok(RawOrigin::Signed(ref signer)) @@ -422,7 +422,7 @@ pub trait OwnedBridgeModule { } /// Change the owner of the module. - fn set_owner(origin: T::Origin, maybe_owner: Option) -> DispatchResult { + fn set_owner(origin: T::RuntimeOrigin, maybe_owner: Option) -> DispatchResult { Self::ensure_owner_or_root(origin)?; match maybe_owner { Some(owner) => { @@ -440,7 +440,7 @@ pub trait OwnedBridgeModule { /// Halt or resume all/some module operations. fn set_operating_mode( - origin: T::Origin, + origin: T::RuntimeOrigin, operating_mode: Self::OperatingMode, ) -> DispatchResult { Self::ensure_owner_or_root(origin)?; diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index e16c43c9816aa..c1e95ec6fefdc 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -228,16 +228,16 @@ macro_rules! generate_owned_bridge_module_tests { PalletOwner::::put(1); // The root should be able to change the owner. - assert_ok!(Pallet::::set_owner(Origin::root(), Some(2))); + assert_ok!(Pallet::::set_owner(RuntimeOrigin::root(), Some(2))); assert_eq!(PalletOwner::::get(), Some(2)); // The owner should be able to change the owner. - assert_ok!(Pallet::::set_owner(Origin::signed(2), Some(3))); + assert_ok!(Pallet::::set_owner(RuntimeOrigin::signed(2), Some(3))); assert_eq!(PalletOwner::::get(), Some(3)); // Other users shouldn't be able to change the owner. assert_noop!( - Pallet::::set_owner(Origin::signed(1), Some(4)), + Pallet::::set_owner(RuntimeOrigin::signed(1), Some(4)), DispatchError::BadOrigin ); assert_eq!(PalletOwner::::get(), Some(3)); @@ -252,26 +252,26 @@ macro_rules! generate_owned_bridge_module_tests { // The root should be able to halt the pallet. assert_ok!(Pallet::::set_operating_mode( - Origin::root(), + RuntimeOrigin::root(), $halted_operating_mode )); assert_eq!(PalletOperatingMode::::get(), $halted_operating_mode); // The root should be able to resume the pallet. assert_ok!(Pallet::::set_operating_mode( - Origin::root(), + RuntimeOrigin::root(), $normal_operating_mode )); assert_eq!(PalletOperatingMode::::get(), $normal_operating_mode); // The owner should be able to halt the pallet. assert_ok!(Pallet::::set_operating_mode( - Origin::signed(1), + RuntimeOrigin::signed(1), $halted_operating_mode )); assert_eq!(PalletOperatingMode::::get(), $halted_operating_mode); // The owner should be able to resume the pallet. assert_ok!(Pallet::::set_operating_mode( - Origin::signed(1), + RuntimeOrigin::signed(1), $normal_operating_mode )); assert_eq!(PalletOperatingMode::::get(), $normal_operating_mode); @@ -279,7 +279,7 @@ macro_rules! generate_owned_bridge_module_tests { // Other users shouldn't be able to halt the pallet. assert_noop!( Pallet::::set_operating_mode( - Origin::signed(2), + RuntimeOrigin::signed(2), $halted_operating_mode ), DispatchError::BadOrigin @@ -289,7 +289,7 @@ macro_rules! generate_owned_bridge_module_tests { PalletOperatingMode::::put($halted_operating_mode); assert_noop!( Pallet::::set_operating_mode( - Origin::signed(2), + RuntimeOrigin::signed(2), $normal_operating_mode ), DispatchError::BadOrigin diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 59d53edf997e0..55c48bee3efa1 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -50,7 +50,7 @@ impl CliEncodeMessage for Millau { ), }; - Ok(millau_runtime::Call::XcmPallet(millau_runtime::XcmCall::send { + Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::send { dest: Box::new(dest.into()), message: Box::new(message), }) @@ -64,7 +64,7 @@ impl CliEncodeMessage for Millau { bridge_instance_index: u8, ) -> anyhow::Result> { Ok(match bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => millau_runtime::Call::BridgeRialtoMessages( + bridge::MILLAU_TO_RIALTO_INDEX => millau_runtime::RuntimeCall::BridgeRialtoMessages( millau_runtime::MessagesCall::send_message { lane_id: lane, payload, @@ -73,7 +73,7 @@ impl CliEncodeMessage for Millau { ) .into(), bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => - millau_runtime::Call::BridgeRialtoParachainMessages( + millau_runtime::RuntimeCall::BridgeRialtoParachainMessages( millau_runtime::MessagesCall::send_message { lane_id: lane, payload, diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index c1e963a63ec7c..772f2552f5bfc 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -69,8 +69,9 @@ mod tests { } #[test] fn rialto_tx_extra_bytes_constant_is_correct() { - let rialto_call = - rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); + let rialto_call = rialto_runtime::RuntimeCall::System(rialto_runtime::SystemCall::remark { + remark: vec![], + }); let rialto_tx = Rialto::sign_transaction( SignParam { spec_version: 1, @@ -92,8 +93,9 @@ mod tests { #[test] fn millau_tx_extra_bytes_constant_is_correct() { - let millau_call = - millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); + let millau_call = millau_runtime::RuntimeCall::System(millau_runtime::SystemCall::remark { + remark: vec![], + }); let millau_tx = Millau::sign_transaction( SignParam { spec_version: 0, diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 285476a331298..6a322d889cb9b 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -42,7 +42,7 @@ impl CliEncodeMessage for Rialto { ), }; - Ok(rialto_runtime::Call::XcmPallet(rialto_runtime::XcmCall::send { + Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::send { dest: Box::new(dest.into()), message: Box::new(message), }) @@ -56,7 +56,7 @@ impl CliEncodeMessage for Rialto { bridge_instance_index: u8, ) -> anyhow::Result> { Ok(match bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => rialto_runtime::Call::BridgeMillauMessages( + bridge::RIALTO_TO_MILLAU_INDEX => rialto_runtime::RuntimeCall::BridgeMillauMessages( rialto_runtime::MessagesCall::send_message { lane_id: lane, payload, diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index c359c42087d46..08cc38d90d780 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -42,10 +42,12 @@ impl CliEncodeMessage for RialtoParachain { ), }; - Ok(rialto_parachain_runtime::Call::PolkadotXcm(rialto_parachain_runtime::XcmCall::send { - dest: Box::new(dest.into()), - message: Box::new(message), - }) + Ok(rialto_parachain_runtime::RuntimeCall::PolkadotXcm( + rialto_parachain_runtime::XcmCall::send { + dest: Box::new(dest.into()), + message: Box::new(message), + }, + ) .into()) } @@ -57,7 +59,7 @@ impl CliEncodeMessage for RialtoParachain { ) -> anyhow::Result> { Ok(match bridge_instance_index { bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => - rialto_parachain_runtime::Call::BridgeMillauMessages( + rialto_parachain_runtime::RuntimeCall::BridgeMillauMessages( rialto_parachain_runtime::MessagesCall::send_message { lane_id: lane, payload, diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 3c861214df4cf..8adb108c85bef 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -85,7 +85,7 @@ impl Chain for Millau { const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = millau_runtime::SignedBlock; - type Call = millau_runtime::Call; + type Call = millau_runtime::RuntimeCall; } impl ChainWithBalances for Millau { @@ -186,7 +186,7 @@ mod tests { #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: millau_runtime::Call::System(millau_runtime::SystemCall::remark { + call: millau_runtime::RuntimeCall::System(millau_runtime::SystemCall::remark { remark: b"Hello world!".to_vec(), }) .into(), diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 489baa4be5aad..7e1415720ba66 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -65,7 +65,7 @@ impl Chain for RialtoParachain { const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = rialto_parachain_runtime::SignedBlock; - type Call = rialto_parachain_runtime::Call; + type Call = rialto_parachain_runtime::RuntimeCall; } impl ChainWithBalances for RialtoParachain { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 816a21baf0c5e..fbb1f85ec1b33 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -65,7 +65,7 @@ impl Chain for Rialto { const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = rialto_runtime::SignedBlock; - type Call = rialto_runtime::Call; + type Call = rialto_runtime::RuntimeCall; } impl RelayChain for Rialto { @@ -189,7 +189,7 @@ mod tests { #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { + call: rialto_runtime::RuntimeCall::System(rialto_runtime::SystemCall::remark { remark: b"Hello world!".to_vec(), }) .into(), diff --git a/relays/client-substrate/src/transaction_tracker.rs b/relays/client-substrate/src/transaction_tracker.rs index 44d8b72cb8d4f..1730647f00d53 100644 --- a/relays/client-substrate/src/transaction_tracker.rs +++ b/relays/client-substrate/src/transaction_tracker.rs @@ -168,7 +168,7 @@ async fn watch_transaction_status< loop { match subscription.next().await { - Some(TransactionStatusOf::::Finalized(block_hash)) => { + Some(TransactionStatusOf::::Finalized((block_hash, _))) => { // the only "successful" outcome of this method is when the block with transaction // has been finalized log::trace!( diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 14227f379d7b6..d821aa6f4cb40 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -32,7 +32,7 @@ use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::Encode; -use frame_support::weights::{GetDispatchInfo, Weight}; +use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ @@ -461,17 +461,23 @@ pub fn select_delivery_transaction_limits 0, "Relay should fit at least one message in every delivery transaction", ); assert!( - weight_for_messages_dispatch >= max_extrinsic_weight / 2, + weight_for_messages_dispatch.ref_time() >= max_extrinsic_weight.ref_time() / 2, "Relay shall be able to deliver messages with dispatch weight = max_extrinsic_weight / 2", ); @@ -500,7 +506,9 @@ mod tests { // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - (1024, 216_609_134_667), + // + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` + (1024, Weight::from_ref_time(216_609_134_667).set_proof_size(217)), ); } } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index e34f477e5f0c2..25869da678ac3 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -653,7 +653,7 @@ mod tests { .into_iter() .map(|nonce| bp_messages::OutboundMessageDetails { nonce, - dispatch_weight: 0, + dispatch_weight: Weight::from_ref_time(0), size: 0, delivery_and_dispatch_fee: 0, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, @@ -730,7 +730,7 @@ mod tests { for (idx, _) in payload_sizes.iter().enumerate() { out_msgs_details.push(OutboundMessageDetails::> { nonce: idx as MessageNonce, - dispatch_weight: 0, + dispatch_weight: Weight::from_ref_time(0), size: 0, delivery_and_dispatch_fee: 0, dispatch_fee_payment: DispatchFeePayment::AtTargetChain, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index da41dba63a538..46c3b6141cc62 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -347,7 +347,7 @@ where // chain. This requires more knowledge of the Target chain, but seems there's no better way // to solve this now. let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { - const WEIGHT_DIFFERENCE: Weight = 100; + const WEIGHT_DIFFERENCE: Weight = Weight::from_ref_time(100); let (spec_version, transaction_version) = self.target_client.simple_runtime_version().await?; @@ -533,7 +533,7 @@ mod tests { #[test] fn prepare_dummy_messages_proof_works() { - const DISPATCH_WEIGHT: Weight = 1_000_000; + const DISPATCH_WEIGHT: Weight = Weight::from_ref_time(1_000_000); const SIZE: u32 = 1_000; let dummy_proof = prepare_dummy_messages_proof::(1..=10, DISPATCH_WEIGHT, SIZE); assert_eq!(dummy_proof.0, DISPATCH_WEIGHT); @@ -563,21 +563,24 @@ mod tests { #[test] fn compute_fee_multiplier_returns_sane_results() { - let multiplier: FixedU128 = bp_rialto::WeightToFee::weight_to_fee(&1).into(); + let multiplier: FixedU128 = + bp_rialto::WeightToFee::weight_to_fee(&Weight::from_ref_time(1)).into(); let smaller_weight = 1_000_000; - let smaller_adjusted_weight_fee = - multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&smaller_weight)); + let smaller_adjusted_weight_fee = multiplier.saturating_mul_int( + WeightToFeeOf::::weight_to_fee(&Weight::from_ref_time(smaller_weight)), + ); let larger_weight = smaller_weight + 200_000; - let larger_adjusted_weight_fee = - multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee(&larger_weight)); + let larger_adjusted_weight_fee = multiplier.saturating_mul_int( + WeightToFeeOf::::weight_to_fee(&Weight::from_ref_time(larger_weight)), + ); assert_eq!( compute_fee_multiplier::( smaller_adjusted_weight_fee, - smaller_weight, + Weight::from_ref_time(smaller_weight), larger_adjusted_weight_fee, - larger_weight, + Weight::from_ref_time(larger_weight), ), multiplier, ); @@ -589,7 +592,9 @@ mod tests { compute_prepaid_messages_refund::( 10, FixedU128::saturating_from_rational(110, 100), - ) > (10 * Rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN).into() + ) > Rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN + .saturating_mul(10u64) + .ref_time() as _ ); } } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 05c157ee7210a..8d9f3ded08741 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -678,7 +678,7 @@ pub(crate) mod tests { ( nonce, MessageDetails { - dispatch_weight: 1, + dispatch_weight: Weight::from_ref_time(1), size: 1, reward: 1, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, @@ -879,9 +879,11 @@ pub(crate) mod tests { total_dispatch_weight: Weight, total_size: u32, ) -> Result { - Ok(BASE_MESSAGE_DELIVERY_TRANSACTION_COST * (nonces.end() - nonces.start() + 1) + + Ok((Weight::from_ref_time(BASE_MESSAGE_DELIVERY_TRANSACTION_COST) * + (nonces.end() - nonces.start() + 1) + total_dispatch_weight + - total_size as TestSourceChainBalance) + Weight::from_ref_time(total_size as u64)) + .ref_time()) } } @@ -916,7 +918,7 @@ pub(crate) mod tests { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: 4, + max_messages_weight_in_single_batch: Weight::from_ref_time(4), max_messages_size_in_single_batch: 4, relay_strategy: AltruisticStrategy, }, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index e15e08b04233d..a2c81d8cc3035 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -295,7 +295,7 @@ impl MessageDeliveryStrategy; @@ -629,7 +629,7 @@ mod tests { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: 4, + max_messages_weight_in_single_batch: Weight::from_ref_time(4), max_messages_size_in_single_batch: 4, latest_confirmed_nonces_at_source: vec![(header_id(1), 19)].into_iter().collect(), lane_source_client: TestSourceClient::default(), @@ -667,10 +667,10 @@ mod tests { (race_state, race_strategy) } - fn proof_parameters(state_required: bool, weight: Weight) -> MessageProofParameters { + fn proof_parameters(state_required: bool, weight: u32) -> MessageProofParameters { MessageProofParameters { outbound_state_proof_required: state_required, - dispatch_weight: weight, + dispatch_weight: Weight::from_ref_time(weight as u64), } } @@ -684,7 +684,7 @@ mod tests { ( idx, MessageDetails { - dispatch_weight: idx, + dispatch_weight: Weight::from_ref_time(idx), size: idx as _, reward: idx as _, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, @@ -813,7 +813,7 @@ mod tests { let (state, mut strategy) = prepare_strategy(); // not all queued messages may fit in the batch, because batch has max weight - strategy.max_messages_weight_in_single_batch = 3; + strategy.max_messages_weight_in_single_batch = Weight::from_ref_time(3); assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) @@ -827,7 +827,8 @@ mod tests { // first message doesn't fit in the batch, because it has weight (10) that overflows max // weight (4) - strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().dispatch_weight = 10; + strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().dispatch_weight = + Weight::from_ref_time(10); assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=20), proof_parameters(false, 10))) @@ -1023,7 +1024,7 @@ mod tests { let nonces = source_nonces( 24..=24, 19, - DEFAULT_REWARD - DEFAULT_DISPATCH_WEIGHT, + DEFAULT_REWARD - DEFAULT_DISPATCH_WEIGHT.ref_time(), dispatch_fee_payment, ); strategy.strategy.source_nonces_updated(header_id(2), nonces); @@ -1031,7 +1032,7 @@ mod tests { strategy.max_unrewarded_relayer_entries_at_target = 100; strategy.max_unconfirmed_nonces_at_target = 100; strategy.max_messages_in_single_batch = 100; - strategy.max_messages_weight_in_single_batch = 100; + strategy.max_messages_weight_in_single_batch = Weight::from_ref_time(100); strategy.max_messages_size_in_single_batch = 100; strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); @@ -1070,7 +1071,7 @@ mod tests { strategy.max_unrewarded_relayer_entries_at_target = 100; strategy.max_unconfirmed_nonces_at_target = 100; strategy.max_messages_in_single_batch = 5; - strategy.max_messages_weight_in_single_batch = 100; + strategy.max_messages_weight_in_single_batch = Weight::from_ref_time(100); strategy.max_messages_size_in_single_batch = 100; state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/relay_strategy/enforcement_strategy.rs index bb4192d45ab05..9ebb7c0e6879d 100644 --- a/relays/messages/src/relay_strategy/enforcement_strategy.rs +++ b/relays/messages/src/relay_strategy/enforcement_strategy.rs @@ -55,7 +55,7 @@ impl EnforcementStrategy { let mut hard_selected_count = 0; let mut soft_selected_count = 0; - let mut selected_weight: Weight = 0; + let mut selected_weight = Weight::from_ref_time(0); let mut selected_count: MessageNonce = 0; let hard_selected_begin_nonce = @@ -77,12 +77,12 @@ impl EnforcementStrategy { hard_selected_begin_nonce, selected_prepaid_nonces: 0, - selected_unpaid_weight: 0, + selected_unpaid_weight: Weight::from_ref_time(0), index: 0, nonce: 0, details: MessageDetails { - dispatch_weight: 0, + dispatch_weight: Weight::from_ref_time(0), size: 0, reward: P::SourceChainBalance::zero(), dispatch_fee_payment: DispatchFeePayment::AtSourceChain, @@ -105,9 +105,10 @@ impl EnforcementStrategy { // transaction will be rejected by the target runtime, but at least we have tried. // limit messages in the batch by weight - let new_selected_weight = match selected_weight.checked_add(details.dispatch_weight) { + let new_selected_weight = match selected_weight.checked_add(&details.dispatch_weight) { Some(new_selected_weight) - if new_selected_weight <= reference.max_messages_weight_in_single_batch => + if new_selected_weight.ref_time() <= + reference.max_messages_weight_in_single_batch.ref_time() => new_selected_weight, new_selected_weight if selected_count == 0 => { log::warn!( From ccc3b30d1ad5e5ec2c54364612f88b8d0a59e3b5 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 20 Oct 2022 17:03:37 +0300 Subject: [PATCH 0792/1210] Finality loop - cosmetic changes (#1609) * Move some logic to RestartableFinalityProofsStream * Move some logic to `Transaction` * Avoid unnecessary split_off --- relays/finality/src/finality_loop.rs | 246 +++++++++++---------- relays/finality/src/finality_loop_tests.rs | 5 +- 2 files changed, 134 insertions(+), 117 deletions(-) diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index a890686047098..302a038b81eb1 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -32,6 +32,7 @@ use relay_utils::{ HeaderId, MaybeConnectionError, TrackedTransactionStatus, TransactionTracker, }; use std::{ + fmt::Debug, pin::Pin, time::{Duration, Instant}, }; @@ -182,15 +183,114 @@ pub(crate) struct Transaction { pub submitted_header_number: Number, } +impl Transaction { + pub async fn submit< + C: TargetClient, + P: FinalitySyncPipeline, + >( + target_client: &C, + header: P::Header, + justification: P::FinalityProof, + ) -> Result { + let submitted_header_number = header.number(); + log::debug!( + target: "bridge", + "Going to submit finality proof of {} header #{:?} to {}", + P::SOURCE_NAME, + submitted_header_number, + P::TARGET_NAME, + ); + + let tracker = target_client.submit_finality_proof(header, justification).await?; + Ok(Transaction { tracker, submitted_header_number }) + } + + pub async fn track, P: FinalitySyncPipeline>( + self, + target_client: &C, + ) -> Result<(), String> { + match self.tracker.wait().await { + TrackedTransactionStatus::Finalized(_) => { + // The transaction has been finalized, but it may have been finalized in the + // "failed" state. So let's check if the block number was actually updated. + // If it wasn't then we are stalled. + // + // Please also note that we're returning an error if we fail to read required data + // from the target client - that's the best we can do here to avoid actual stall. + target_client + .best_finalized_source_block_id() + .await + .map_err(|e| format!("failed to read best block from target node: {:?}", e)) + .and_then(|best_id_at_target| { + if self.submitted_header_number > best_id_at_target.0 { + return Err(format!( + "best block at target after tx is {:?} and we've submitted {:?}", + best_id_at_target.0, self.submitted_header_number, + )) + } + Ok(()) + }) + }, + TrackedTransactionStatus::Lost => Err("transaction failed".to_string()), + } + } +} + /// Finality proofs stream that may be restarted. pub(crate) struct RestartableFinalityProofsStream { /// Flag that the stream needs to be restarted. pub(crate) needs_restart: bool, /// The stream itself. - pub(crate) stream: Pin>, + stream: Pin>, +} + +impl RestartableFinalityProofsStream { + pub async fn create_raw_stream< + C: SourceClient, + P: FinalitySyncPipeline, + >( + source_client: &C, + ) -> Result { + source_client.finality_proofs().await.map_err(|error| { + log::error!( + target: "bridge", + "Failed to subscribe to {} justifications: {:?}. Going to reconnect", + P::SOURCE_NAME, + error, + ); + + FailedClient::Source + }) + } + + pub async fn restart_if_scheduled< + C: SourceClient, + P: FinalitySyncPipeline, + >( + &mut self, + source_client: &C, + ) -> Result<(), FailedClient> { + if self.needs_restart { + log::warn!(target: "bridge", "{} finality proofs stream is being restarted", P::SOURCE_NAME); + + self.needs_restart = false; + self.stream = Box::pin(Self::create_raw_stream(source_client).await?); + } + Ok(()) + } + + pub fn next(&mut self) -> Option { + match self.stream.next().now_or_never() { + Some(Some(finality_proof)) => Some(finality_proof), + Some(None) => { + self.needs_restart = true; + None + }, + None => None, + } + } } -#[cfg(test)] impl From for RestartableFinalityProofsStream { fn from(stream: S) -> Self { RestartableFinalityProofsStream { needs_restart: false, stream: Box::pin(stream) } @@ -218,27 +318,12 @@ pub(crate) async fn run_until_connection_lost( metrics_sync: Option, exit_signal: impl Future, ) -> Result<(), FailedClient> { - let restart_finality_proofs_stream = || async { - source_client.finality_proofs().await.map_err(|error| { - log::error!( - target: "bridge", - "Failed to subscribe to {} justifications: {:?}. Going to reconnect", - P::SOURCE_NAME, - error, - ); - - FailedClient::Source - }) - }; - let last_transaction_tracker = futures::future::Fuse::terminated(); let exit_signal = exit_signal.fuse(); futures::pin_mut!(last_transaction_tracker, exit_signal); - let mut finality_proofs_stream = RestartableFinalityProofsStream { - needs_restart: false, - stream: Box::pin(restart_finality_proofs_stream().await?), - }; + let mut finality_proofs_stream = + RestartableFinalityProofsStream::create_raw_stream(&source_client).await?.into(); let mut recent_finality_proofs = Vec::new(); let mut progress = (Instant::now(), None); @@ -263,10 +348,9 @@ pub(crate) async fn run_until_connection_lost( // deal with errors let next_tick = match iteration_result { - Ok(Some(updated_last_transaction)) => { - last_transaction_tracker.set(updated_last_transaction.tracker.wait().fuse()); - last_submitted_header_number = - Some(updated_last_transaction.submitted_header_number); + Ok(Some(updated_transaction)) => { + last_submitted_header_number = Some(updated_transaction.submitted_header_number); + last_transaction_tracker.set(updated_transaction.track(&target_client).fuse()); retry_backoff.reset(); sync_params.tick }, @@ -280,66 +364,23 @@ pub(crate) async fn run_until_connection_lost( retry_backoff.next_backoff().unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) }, }; - if finality_proofs_stream.needs_restart { - log::warn!(target: "bridge", "{} finality proofs stream is being restarted", P::SOURCE_NAME); - - finality_proofs_stream.needs_restart = false; - finality_proofs_stream.stream = Box::pin(restart_finality_proofs_stream().await?); - } + finality_proofs_stream.restart_if_scheduled(&source_client).await?; // wait till exit signal, or new source block select! { - transaction_status = last_transaction_tracker => { - match transaction_status { - TrackedTransactionStatus::Finalized(_) => { - // transaction has been finalized, but it may have been finalized in the "failed" state. So - // let's check if the block number has been actually updated. If it is not, then we are stalled. - // - // please also note that we're restarting the loop if we have failed to read required data - // from the target client - that's the best we can do here to avoid actual stall. - target_client - .best_finalized_source_block_id() - .await - .map_err(|e| format!("failed to read best block from target node: {:?}", e)) - .and_then(|best_id_at_target| { - let last_submitted_header_number = last_submitted_header_number - .expect("always Some when last_transaction_tracker is set;\ - last_transaction_tracker is set;\ - qed"); - if last_submitted_header_number > best_id_at_target.0 { - Err(format!( - "best block at target after tx is {:?} and we've submitted {:?}", - best_id_at_target, - last_submitted_header_number, - )) - } else { - Ok(()) - } - }) - .map_err(|e| { - log::error!( - target: "bridge", - "Failed Finality synchronization from {} to {} has stalled. Transaction failed: {}. \ - Going to restart", - P::SOURCE_NAME, - P::TARGET_NAME, - e, - ); - - FailedClient::Both - })?; - }, - TrackedTransactionStatus::Lost => { - log::error!( - target: "bridge", - "Finality synchronization from {} to {} has stalled. Going to restart", - P::SOURCE_NAME, - P::TARGET_NAME, - ); - - return Err(FailedClient::Both); - }, - } + transaction_result = last_transaction_tracker => { + transaction_result.map_err(|e| { + log::error!( + target: "bridge", + "Finality synchronization from {} to {} has stalled with error: {}. Going to restart", + P::SOURCE_NAME, + P::TARGET_NAME, + e, + ); + + // Restart the loop if we're stalled. + FailedClient::Both + })? }, _ = async_std::task::sleep(next_tick).fuse() => {}, _ = exit_signal => return Ok(()), @@ -414,20 +455,10 @@ where .await? { Some((header, justification)) => { - let submitted_header_number = header.number(); - log::debug!( - target: "bridge", - "Going to submit finality proof of {} header #{:?} to {}", - P::SOURCE_NAME, - submitted_header_number, - P::TARGET_NAME, - ); - - let tracker = target_client - .submit_finality_proof(header, justification) + let transaction = Transaction::submit(target_client, header, justification) .await .map_err(Error::Target)?; - Ok(Some(Transaction { tracker, submitted_header_number })) + Ok(Some(transaction)) }, None => Ok(None), } @@ -598,17 +629,7 @@ pub(crate) fn read_finality_proofs_from_stream< let mut proofs_count = 0; let mut first_header_number = None; let mut last_header_number = None; - loop { - let next_proof = finality_proofs_stream.stream.next(); - let finality_proof = match next_proof.now_or_never() { - Some(Some(finality_proof)) => finality_proof, - Some(None) => { - finality_proofs_stream.needs_restart = true; - break - }, - None => break, - }; - + while let Some(finality_proof) = finality_proofs_stream.next() { let target_header_number = finality_proof.target_header_number(); if first_header_number.is_none() { first_header_number = Some(target_header_number); @@ -700,16 +721,15 @@ pub(crate) fn prune_recent_finality_proofs( recent_finality_proofs: &mut FinalityProofs

, recent_finality_proofs_limit: usize, ) { - let position = recent_finality_proofs - .binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number); - - // remove all obsolete elements - *recent_finality_proofs = recent_finality_proofs - .split_off(position.map(|position| position + 1).unwrap_or_else(|position| position)); - - // now - limit vec by size - let split_index = recent_finality_proofs.len().saturating_sub(recent_finality_proofs_limit); - *recent_finality_proofs = recent_finality_proofs.split_off(split_index); + let justified_header_idx = recent_finality_proofs + .binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number) + .map(|idx| idx + 1) + .unwrap_or_else(|idx| idx); + let proofs_limit_idx = + recent_finality_proofs.len().saturating_sub(recent_finality_proofs_limit); + + *recent_finality_proofs = + recent_finality_proofs.split_off(std::cmp::max(justified_header_idx, proofs_limit_idx)); } fn print_sync_progress( diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index c8d5cefc22772..a6e97c0770f99 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -552,10 +552,7 @@ fn different_forks_at_source_and_at_target_are_detected() { ); let mut progress = (Instant::now(), None); - let mut finality_proofs_stream = RestartableFinalityProofsStream { - needs_restart: false, - stream: Box::pin(futures::stream::iter(vec![]).boxed()), - }; + let mut finality_proofs_stream = futures::stream::iter(vec![]).boxed().into(); let mut recent_finality_proofs = Vec::new(); let metrics_sync = SyncLoopMetrics::new(None, "source", "target").unwrap(); async_std::task::block_on(run_loop_iteration::( From 96eb9a0673648275a5948d6d13b0782674bae8b2 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 21 Oct 2022 08:18:13 +0200 Subject: [PATCH 0793/1210] Removed unused trait SenderOrigin (#1611) --- bin/millau/runtime/src/rialto_messages.rs | 9 +-------- .../runtime/src/millau_messages.rs | 12 +----------- bin/rialto/runtime/src/millau_messages.rs | 9 +-------- modules/messages/src/mock.rs | 12 +----------- primitives/messages/src/source_chain.rs | 17 ----------------- 5 files changed, 4 insertions(+), 55 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index bb9f5dfe757e7..cf2bd4badaf1e 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -19,7 +19,7 @@ use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ - source_chain::{SenderOrigin, TargetHeaderChain}, + source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -277,13 +277,6 @@ impl SourceHeaderChain for Rialto { } } -impl SenderOrigin for RuntimeOrigin { - fn linked_account(&self) -> Option { - // XCM deals wit fees in our deployments - None - } -} - /// Millau -> Rialto message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum MillauToRialtoMessagesParameter { diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 14dc922e19c6e..4688f89a7087a 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -22,7 +22,7 @@ use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ - source_chain::{SenderOrigin, TargetHeaderChain}, + source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -284,16 +284,6 @@ impl SourceHeaderChain for Millau { } } -impl SenderOrigin for RuntimeOrigin { - fn linked_account(&self) -> Option { - match self.caller { - crate::OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => - Some(submitter.clone()), - _ => None, - } - } -} - /// RialtoParachain -> Millau message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum RialtoParachainToMillauMessagesParameter { diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index ec8a7b822dca7..43c95744165f3 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -19,7 +19,7 @@ use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ - source_chain::{SenderOrigin, TargetHeaderChain}, + source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; @@ -275,13 +275,6 @@ impl SourceHeaderChain for Millau { } } -impl SenderOrigin for RuntimeOrigin { - fn linked_account(&self) -> Option { - // XCM deals wit fees in our deployments - None - } -} - /// Rialto -> Millau message lane pallet parameters. #[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] pub enum RialtoToMillauMessagesParameter { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 4e6a6e53fbc16..fd4c45a0eaa9c 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -23,7 +23,7 @@ use bitvec::prelude::*; use bp_messages::{ source_chain::{ LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, SenderOrigin, TargetHeaderChain, + OnMessageAccepted, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -185,16 +185,6 @@ impl Config for TestRuntime { type BridgedChainId = TestBridgedChainId; } -impl SenderOrigin for RuntimeOrigin { - fn linked_account(&self) -> Option { - match self.caller { - OriginCaller::system(frame_system::RawOrigin::Signed(ref submitter)) => - Some(*submitter), - _ => None, - } - } -} - impl Size for TestPayload { fn size(&self) -> u32 { 16 + self.extra.len() as u32 diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index e1f2c0c3c8dfb..4eb79edd8482c 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -27,23 +27,6 @@ use sp_std::{ ops::RangeInclusive, }; -/// The sender of the message on the source chain. -pub trait SenderOrigin { - /// Return id of the account that is sending this message. - /// - /// In regular messages configuration, when regular message is sent you'll always get `Some(_)` - /// from this call. This is the account that is paying send costs. However, there are some - /// examples when `None` may be returned from the call: - /// - /// - if the send-message call origin is either `frame_system::RawOrigin::Root` or - /// `frame_system::RawOrigin::None` and your configuration forbids such messages; - /// - if your configuration allows 'unpaid' messages sent by pallets. Then the pallet may just - /// use its own defined origin (not linked to any account) and the message will be accepted. - /// This may be useful for pallets that are sending important system-wide information (like - /// update of runtime version). - fn linked_account(&self) -> Option; -} - /// Relayers rewards, grouped by relayer account id. pub type RelayersRewards = BTreeMap>; From dc7de1f43d70baa40be35106ae60818ab8df4e09 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 21 Oct 2022 13:43:07 +0300 Subject: [PATCH 0794/1210] weights v1.5: iteration 2 (#1613) --- bin/runtime-common/src/messages.rs | 15 ++++--- bin/runtime-common/src/messages_api.rs | 2 +- .../src/messages_benchmarking.rs | 2 +- bin/runtime-common/src/messages_extension.rs | 2 +- modules/grandpa/src/lib.rs | 4 +- modules/messages/src/lib.rs | 20 ++++----- modules/messages/src/weights_ext.rs | 42 +++++++++---------- modules/parachains/src/lib.rs | 2 +- primitives/messages/src/source_chain.rs | 6 +-- primitives/messages/src/target_chain.rs | 2 +- primitives/runtime/src/lib.rs | 21 +++++++++- .../lib-substrate-relay/src/messages_lane.rs | 17 ++++---- .../src/messages_source.rs | 4 +- relays/messages/src/message_race_delivery.rs | 2 +- .../relay_strategy/enforcement_strategy.rs | 10 ++--- 15 files changed, 81 insertions(+), 70 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 880bc6bc394d6..14d505f51b960 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -407,7 +407,7 @@ pub mod source { let delivery_transaction = BridgedChain::::estimate_delivery_transaction( &payload.encode(), true, - Weight::from_ref_time(0), + Weight::zero(), ); let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); @@ -733,7 +733,7 @@ pub mod target { payload.weight = Some(weight); weight }, - _ => Weight::from_ref_time(0), + _ => Weight::zero(), } } @@ -762,17 +762,22 @@ pub mod target { location, xcm, hash, - weight_limit.unwrap_or(Weight::from_ref_time(0)).ref_time(), + weight_limit.unwrap_or_else(Weight::zero).ref_time(), weight_credit.ref_time(), ); Ok(xcm_outcome) }; let xcm_outcome = do_dispatch(); - log::trace!(target: "runtime::bridge-dispatch", "Incoming message {:?} dispatched with result: {:?}", message_id, xcm_outcome); + log::trace!( + target: "runtime::bridge-dispatch", + "Incoming message {:?} dispatched with result: {:?}", + message_id, + xcm_outcome, + ); MessageDispatchResult { dispatch_result: true, - unspent_weight: Weight::from_ref_time(0), + unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, } } diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index acc4c6d9a6e94..28090daee5ae0 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -39,7 +39,7 @@ where nonce, // dispatch message weight is always zero at the source chain, since we're paying for // dispatch at the target chain - dispatch_weight: frame_support::weights::Weight::from_ref_time(0), + dispatch_weight: frame_support::weights::Weight::zero(), size: message_data.payload.len() as _, delivery_and_dispatch_fee: message_data.fee, // we're delivering XCM messages here, so fee is always paid at the target chain diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 2a384236aff95..71eed881a063d 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -94,7 +94,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - Weight::from_ref_time(0), + Weight::zero(), ) } diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index 39d44ad11fb34..c5fb897b92681 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -125,7 +125,7 @@ mod tests { pallet_bridge_messages::Call::::receive_messages_proof { relayer_id_at_bridged_chain: [0u8; 32].into(), messages_count: (nonces_end - nonces_start + 1) as u32, - dispatch_weight: frame_support::weights::Weight::from_ref_time(0), + dispatch_weight: frame_support::weights::Weight::zero(), proof: FromBridgedChainMessagesProof { bridged_header_hash: Default::default(), storage_proof: vec![], diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 97875e8faded7..e061b702a11e0 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -135,9 +135,7 @@ pub mod pallet { fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { >::mutate(|count| *count = count.saturating_sub(1)); - Weight::from_ref_time(0) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + T::DbWeight::get().reads_writes(1, 1) } } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 61e6df211c747..66f568e698c9e 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -330,11 +330,8 @@ pub mod pallet { }); // compute actual dispatch weight that depends on the stored message size - let actual_weight = sp_std::cmp::min_by( - T::WeightInfo::maximal_increase_message_fee(), - T::WeightInfo::increase_message_fee(message_size as _), - |w1, w2| w1.ref_time().cmp(&w2.ref_time()), - ); + let actual_weight = T::WeightInfo::maximal_increase_message_fee() + .min(T::WeightInfo::increase_message_fee(message_size as _)); Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } @@ -416,7 +413,7 @@ pub mod pallet { // on this lane. We can't dispatch lane messages out-of-order, so if declared // weight is not enough, let's move to next lane let dispatch_weight = T::MessageDispatch::dispatch_weight(&mut message); - if dispatch_weight.ref_time() > dispatch_weight_left.ref_time() { + if dispatch_weight.any_gt(dispatch_weight_left) { log::trace!( target: LOG_TARGET, "Cannot dispatch any more messages on lane {:?}. Weight: declared={}, left={}", @@ -454,10 +451,7 @@ pub mod pallet { ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), }; - let unspent_weight = - sp_std::cmp::min_by(unspent_weight, dispatch_weight, |w1, w2| { - w1.ref_time().cmp(&w2.ref_time()) - }); + let unspent_weight = unspent_weight.min(dispatch_weight); dispatch_weight_left -= dispatch_weight - unspent_weight; actual_weight = actual_weight.saturating_sub(unspent_weight).saturating_sub( // delivery call weight formula assumes that the fee is paid at @@ -466,7 +460,7 @@ pub mod pallet { if refund_pay_dispatch_fee { T::WeightInfo::pay_inbound_dispatch_fee_overhead() } else { - Weight::from_ref_time(0) + Weight::zero() }, ); } @@ -585,7 +579,7 @@ pub mod pallet { let actual_callback_weight = T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); match preliminary_callback_overhead.checked_sub(&actual_callback_weight) { - Some(difference) if difference.ref_time() == 0 => (), + Some(difference) if difference.is_zero() => (), Some(difference) => { log::trace!( target: LOG_TARGET, @@ -880,7 +874,7 @@ fn send_message, I: 'static>( T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); let actual_callback_weight = T::OnMessageAccepted::on_messages_accepted(&lane_id, &nonce); match single_message_callback_overhead.checked_sub(&actual_callback_weight) { - Some(difference) if difference.ref_time() == 0 => (), + Some(difference) if difference.is_zero() => (), Some(difference) => { log::trace!( target: LOG_TARGET, diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index eaf6bc1029eff..80a1b9cdf8ad5 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -43,14 +43,14 @@ pub fn ensure_weights_are_correct( db_weight: RuntimeDbWeight, ) { // verify `send_message` weight components - assert_ne!(W::send_message_overhead(), Weight::from_ref_time(0)); - assert_ne!(W::send_message_size_overhead(0), Weight::from_ref_time(0)); + assert_ne!(W::send_message_overhead(), Weight::zero()); + assert_ne!(W::send_message_size_overhead(0), Weight::zero()); // verify `receive_messages_proof` weight components - assert_ne!(W::receive_messages_proof_overhead(), Weight::from_ref_time(0)); - assert_ne!(W::receive_messages_proof_messages_overhead(1), Weight::from_ref_time(0)); - assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), Weight::from_ref_time(0)); - assert_ne!(W::storage_proof_size_overhead(1), Weight::from_ref_time(0)); + assert_ne!(W::receive_messages_proof_overhead(), Weight::zero()); + assert_ne!(W::receive_messages_proof_messages_overhead(1), Weight::zero()); + assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), Weight::zero()); + assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); // verify that the hardcoded value covers `receive_messages_proof` weight let actual_single_regular_message_delivery_tx_weight = W::receive_messages_proof_weight( @@ -58,11 +58,11 @@ pub fn ensure_weights_are_correct( (EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize, ), 1, - Weight::from_ref_time(0), + Weight::zero(), ); assert!( - actual_single_regular_message_delivery_tx_weight.ref_time() <= - expected_default_message_delivery_tx_weight.ref_time(), + actual_single_regular_message_delivery_tx_weight + .all_lte(expected_default_message_delivery_tx_weight), "Default message delivery transaction weight {} is larger than expected weight {}", actual_single_regular_message_delivery_tx_weight, expected_default_message_delivery_tx_weight, @@ -71,16 +71,15 @@ pub fn ensure_weights_are_correct( // verify that hardcoded value covers additional byte length of `receive_messages_proof` weight let actual_additional_byte_delivery_weight = W::storage_proof_size_overhead(1); assert!( - actual_additional_byte_delivery_weight.ref_time() <= - expected_additional_byte_delivery_weight.ref_time(), + actual_additional_byte_delivery_weight.all_lte(expected_additional_byte_delivery_weight), "Single additional byte delivery weight {} is larger than expected weight {}", actual_additional_byte_delivery_weight, expected_additional_byte_delivery_weight, ); // verify `receive_messages_delivery_proof` weight components - assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::from_ref_time(0)); - assert_ne!(W::storage_proof_size_overhead(1), Weight::from_ref_time(0)); + assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::zero()); + assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); // `receive_messages_delivery_proof_messages_overhead` and // `receive_messages_delivery_proof_relayers_overhead` may return zero if rewards are not paid @@ -97,8 +96,8 @@ pub fn ensure_weights_are_correct( db_weight, ); assert!( - actual_messages_delivery_confirmation_tx_weight.ref_time() <= - expected_messages_delivery_confirmation_tx_weight.ref_time(), + actual_messages_delivery_confirmation_tx_weight + .all_lte(expected_messages_delivery_confirmation_tx_weight), "Messages delivery confirmation transaction weight {} is larger than expected weight {}", actual_messages_delivery_confirmation_tx_weight, expected_messages_delivery_confirmation_tx_weight, @@ -107,7 +106,7 @@ pub fn ensure_weights_are_correct( // verify pay-dispatch-fee overhead for inbound messages let actual_pay_inbound_dispatch_fee_weight = W::pay_inbound_dispatch_fee_overhead(); assert!( - actual_pay_inbound_dispatch_fee_weight.ref_time() <= expected_pay_inbound_dispatch_fee_weight.ref_time(), + actual_pay_inbound_dispatch_fee_weight.all_lte(expected_pay_inbound_dispatch_fee_weight), "Weight {} of pay-dispatch-fee overhead for inbound messages is larger than expected weight {}", actual_pay_inbound_dispatch_fee_weight, expected_pay_inbound_dispatch_fee_weight, @@ -141,7 +140,7 @@ pub fn ensure_able_to_receive_message( max_incoming_message_dispatch_weight, ); assert!( - max_delivery_transaction_dispatch_weight.ref_time() <= max_extrinsic_weight.ref_time(), + max_delivery_transaction_dispatch_weight.all_lte(max_extrinsic_weight), "Weight of maximal message delivery transaction + {} is larger than maximal possible transaction weight {}", max_delivery_transaction_dispatch_weight, max_extrinsic_weight, @@ -180,7 +179,7 @@ pub fn ensure_able_to_receive_confirmation( db_weight, ); assert!( - max_confirmation_transaction_dispatch_weight.ref_time() <= max_extrinsic_weight.ref_time(), + max_confirmation_transaction_dispatch_weight.all_lte(max_extrinsic_weight), "Weight of maximal confirmation transaction {} is larger than maximal possible transaction weight {}", max_confirmation_transaction_dispatch_weight, max_extrinsic_weight, @@ -263,15 +262,14 @@ pub trait WeightInfoExt: WeightInfo { // and cost of calling `OnDeliveryConfirmed::on_messages_delivered()` for every confirmed // message - let callback_overhead = relayers_state - .total_messages - .saturating_mul(Self::single_message_callback_overhead(db_weight).ref_time()); + let callback_overhead = Self::single_message_callback_overhead(db_weight) + .saturating_mul(relayers_state.total_messages); transaction_overhead .saturating_add(messages_overhead) .saturating_add(relayers_overhead) .saturating_add(proof_size_overhead) - .saturating_add(Weight::from_ref_time(callback_overhead)) + .saturating_add(callback_overhead) } // Functions that are used by extrinsics weights formulas. diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index e0c3ff8340f6b..4b2be1b71707f 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -748,7 +748,7 @@ mod tests { let db_weight = ::DbWeight::get(); WeightInfoOf::::submit_parachain_heads_weight(db_weight, proof, 1) .saturating_sub(if prune_expected { - Weight::from_ref_time(0) + Weight::zero() } else { WeightInfoOf::::parachain_head_pruning_weight(db_weight) }) diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 4eb79edd8482c..8050f994dd3f1 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -195,7 +195,7 @@ impl MessagesBridge Result { - Ok(SendMessageArtifacts { nonce: 0, weight: Weight::from_ref_time(0) }) + Ok(SendMessageArtifacts { nonce: 0, weight: Weight::zero() }) } } @@ -220,7 +220,7 @@ pub trait OnDeliveryConfirmed { #[impl_trait_for_tuples::impl_for_tuples(30)] impl OnDeliveryConfirmed for Tuple { fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { - let mut total_weight = Weight::from_ref_time(0); + let mut total_weight = Weight::zero(); for_tuples!( #( total_weight = total_weight.saturating_add(Tuple::on_messages_delivered(lane, messages)); @@ -238,7 +238,7 @@ pub trait OnMessageAccepted { impl OnMessageAccepted for () { fn on_messages_accepted(_lane: &LaneId, _message: &MessageNonce) -> Weight { - Weight::from_ref_time(0) + Weight::zero() } } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 05623d0efba35..58419c398bb33 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -167,7 +167,7 @@ impl MessageDispatch for ForbidInboundMessages { ) -> MessageDispatchResult { MessageDispatchResult { dispatch_result: false, - unspent_weight: Weight::from_ref_time(0), + unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index cd3951920491c..9f525f5ea8563 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -20,7 +20,8 @@ use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; use frame_support::{ - log, pallet_prelude::DispatchResult, PalletError, RuntimeDebug, StorageHasher, StorageValue, + log, pallet_prelude::DispatchResult, weights::Weight, PalletError, RuntimeDebug, StorageHasher, + StorageValue, }; use frame_system::RawOrigin; use scale_info::TypeInfo; @@ -456,6 +457,24 @@ pub trait FilterCall { fn validate(call: &Call) -> TransactionValidity; } +/// All extra operations with weights that we need in bridges. +pub trait WeightExtraOps { + /// Checked division of individual components of two weights. + /// + /// Divides components and returns minimal division result. Returns `None` if one + /// of `other` weight components is zero. + fn min_components_checked_div(&self, other: Weight) -> Option; +} + +impl WeightExtraOps for Weight { + fn min_components_checked_div(&self, other: Weight) -> Option { + Some(sp_std::cmp::min( + self.ref_time().checked_div(other.ref_time())?, + self.proof_size().checked_div(other.proof_size())?, + )) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index d821aa6f4cb40..72da8f20220e8 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -27,7 +27,7 @@ use crate::{ use async_std::sync::Arc; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, Chain as _}; +use bp_runtime::{AccountIdOf, Chain as _, WeightExtraOps}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -462,15 +462,12 @@ pub fn select_delivery_transaction_limits 0, diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 25869da678ac3..c4e0f15f859ab 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -653,7 +653,7 @@ mod tests { .into_iter() .map(|nonce| bp_messages::OutboundMessageDetails { nonce, - dispatch_weight: Weight::from_ref_time(0), + dispatch_weight: Weight::zero(), size: 0, delivery_and_dispatch_fee: 0, dispatch_fee_payment: DispatchFeePayment::AtSourceChain, @@ -730,7 +730,7 @@ mod tests { for (idx, _) in payload_sizes.iter().enumerate() { out_msgs_details.push(OutboundMessageDetails::> { nonce: idx as MessageNonce, - dispatch_weight: Weight::from_ref_time(0), + dispatch_weight: Weight::zero(), size: 0, delivery_and_dispatch_fee: 0, dispatch_fee_payment: DispatchFeePayment::AtTargetChain, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index a2c81d8cc3035..9481e47faf88f 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -295,7 +295,7 @@ impl MessageDeliveryStrategy EnforcementStrategy { let mut hard_selected_count = 0; let mut soft_selected_count = 0; - let mut selected_weight = Weight::from_ref_time(0); + let mut selected_weight = Weight::zero(); let mut selected_count: MessageNonce = 0; let hard_selected_begin_nonce = @@ -77,12 +77,12 @@ impl EnforcementStrategy { hard_selected_begin_nonce, selected_prepaid_nonces: 0, - selected_unpaid_weight: Weight::from_ref_time(0), + selected_unpaid_weight: Weight::zero(), index: 0, nonce: 0, details: MessageDetails { - dispatch_weight: Weight::from_ref_time(0), + dispatch_weight: Weight::zero(), size: 0, reward: P::SourceChainBalance::zero(), dispatch_fee_payment: DispatchFeePayment::AtSourceChain, @@ -107,8 +107,8 @@ impl EnforcementStrategy { // limit messages in the batch by weight let new_selected_weight = match selected_weight.checked_add(&details.dispatch_weight) { Some(new_selected_weight) - if new_selected_weight.ref_time() <= - reference.max_messages_weight_in_single_batch.ref_time() => + if new_selected_weight + .all_lte(reference.max_messages_weight_in_single_batch) => new_selected_weight, new_selected_weight if selected_count == 0 => { log::warn!( From 1b39bf0b0c12903cc9558d627a359325ada57068 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 21 Oct 2022 13:43:59 +0300 Subject: [PATCH 0795/1210] Fix parachains_loop::tests::minimal_working_case --- relays/parachains/src/parachains_loop.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 6648f2efc7279..3ef9a7f7a731c 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -24,7 +24,7 @@ use bp_polkadot_core::{ }; use futures::{ future::{FutureExt, Shared}, - poll, select, + poll, select_biased, }; use relay_substrate_client::{BlockNumberOf, Chain, HeaderIdOf}; use relay_utils::{ @@ -216,10 +216,12 @@ where // regular errors. loop { - // either wait for new block, or exit signal - select! { - _ = async_std::task::sleep(min_block_interval).fuse() => {}, + // Either wait for new block, or exit signal. + // Please note that we are prioritizing the exit signal since if both events happen at once + // it doesn't make sense to perform one more loop iteration. + select_biased! { _ = exit_signal => return Ok(()), + _ = async_std::task::sleep(min_block_interval).fuse() => {}, } // if source client is not yet synced, we'll need to sleep. Otherwise we risk submitting too From 06de8d3596dcbe8f8da86e516e18f7ac08e05f53 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 21 Oct 2022 14:59:36 +0300 Subject: [PATCH 0796/1210] remove xcm-copy module (#1614) --- bin/runtime-common/src/messages.rs | 107 ----------------------------- 1 file changed, 107 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 14d505f51b960..3744d7153eef8 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -1015,113 +1015,6 @@ pub mod target { } } -pub use xcm_copy::*; - -// copy of private types from xcm-builder/src/universal_exports.rs -pub mod xcm_copy { - use codec::{Decode, Encode}; - use frame_support::{ensure, traits::Get}; - use sp_std::{convert::TryInto, marker::PhantomData, prelude::*}; - use xcm::prelude::*; - use xcm_executor::traits::ExportXcm; - - pub trait DispatchBlob { - /// Dispatches an incoming blob and returns the unexpectable weight consumed by the - /// dispatch. - fn dispatch_blob(blob: Vec) -> Result<(), DispatchBlobError>; - } - - pub trait HaulBlob { - /// Sends a blob over some point-to-point link. This will generally be implemented by a - /// bridge. - fn haul_blob(blob: Vec); - } - - #[derive(Clone, Encode, Decode)] - pub struct BridgeMessage { - /// The message destination as a *Universal Location*. This means it begins with a - /// `GlobalConsensus` junction describing the network under which global consensus happens. - /// If this does not match our global consensus then it's a fatal error. - universal_dest: VersionedInteriorMultiLocation, - message: VersionedXcm<()>, - } - - pub enum DispatchBlobError { - Unbridgable, - InvalidEncoding, - UnsupportedLocationVersion, - UnsupportedXcmVersion, - RoutingError, - NonUniversalDestination, - WrongGlobal, - } - - pub struct BridgeBlobDispatcher(PhantomData<(Router, OurPlace)>); - impl> DispatchBlob - for BridgeBlobDispatcher - { - fn dispatch_blob(blob: Vec) -> Result<(), DispatchBlobError> { - let our_universal = OurPlace::get(); - let our_global = - our_universal.global_consensus().map_err(|()| DispatchBlobError::Unbridgable)?; - let BridgeMessage { universal_dest, message } = - Decode::decode(&mut &blob[..]).map_err(|_| DispatchBlobError::InvalidEncoding)?; - let universal_dest: InteriorMultiLocation = universal_dest - .try_into() - .map_err(|_| DispatchBlobError::UnsupportedLocationVersion)?; - // `universal_dest` is the desired destination within the universe: first we need to - // check we're in the right global consensus. - let intended_global = universal_dest - .global_consensus() - .map_err(|()| DispatchBlobError::NonUniversalDestination)?; - ensure!(intended_global == our_global, DispatchBlobError::WrongGlobal); - let dest = universal_dest.relative_to(&our_universal); - let message: Xcm<()> = - message.try_into().map_err(|_| DispatchBlobError::UnsupportedXcmVersion)?; - send_xcm::(dest, message).map_err(|_| DispatchBlobError::RoutingError)?; - Ok(()) - } - } - - pub struct HaulBlobExporter( - PhantomData<(Bridge, BridgedNetwork, Price)>, - ); - impl, Price: Get> ExportXcm - for HaulBlobExporter - { - type Ticket = (Vec, XcmHash); - - fn validate( - network: NetworkId, - _channel: u32, - _universal_source: &mut Option, - destination: &mut Option, - message: &mut Option>, - ) -> Result<((Vec, XcmHash), MultiAssets), SendError> { - let bridged_network = BridgedNetwork::get(); - ensure!(network == bridged_network, SendError::NotApplicable); - // We don't/can't use the `channel` for this adapter. - let dest = destination.take().ok_or(SendError::MissingArgument)?; - let universal_dest = match dest.pushed_front_with(GlobalConsensus(bridged_network)) { - Ok(d) => d.into(), - Err((dest, _)) => { - *destination = Some(dest); - return Err(SendError::NotApplicable) - }, - }; - let message = VersionedXcm::from(message.take().ok_or(SendError::MissingArgument)?); - let hash = message.using_encoded(sp_io::hashing::blake2_256); - let blob = BridgeMessage { universal_dest, message }.encode(); - Ok(((blob, hash), Price::get())) - } - - fn deliver((blob, hash): (Vec, XcmHash)) -> Result { - Bridge::haul_blob(blob); - Ok(hash) - } - } -} - #[cfg(test)] mod tests { use super::*; From 33f2413e360bae8bf62bbabff4eaf5f2806ad672 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 24 Oct 2022 10:55:31 +0300 Subject: [PATCH 0797/1210] Define SubstrateBeefy RPC client (#1615) --- relays/client-substrate/src/client.rs | 12 +++-- relays/client-substrate/src/lib.rs | 1 + relays/client-substrate/src/rpc.rs | 47 +++++++++++++++++-- .../src/finality/engine.rs | 18 +++---- .../src/finality/source.rs | 2 +- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 067d3d89d2450..a713b3ba12128 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -19,8 +19,8 @@ use crate::{ chain::{Chain, ChainWithBalances}, rpc::{ - SubstrateAuthorClient, SubstrateChainClient, SubstrateFrameSystemClient, - SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient, + SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient, + SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, SubstrateTransactionPaymentClient, }, transaction_stall_timeout, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, @@ -642,11 +642,13 @@ impl Client { .await } - /// Return new GRANDPA justifications stream. - pub async fn subscribe_grandpa_justifications(&self) -> Result> { + /// Return new finality justifications stream. + pub async fn subscribe_finality_justifications>( + &self, + ) -> Result> { let subscription = self .jsonrpsee_execute(move |client| async move { - Ok(SubstrateGrandpaClient::::subscribe_justifications(&*client).await?) + Ok(FC::subscribe_justifications(&client).await?) }) .await?; let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index bd38f3a928f83..9e6c73d83caf9 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -39,6 +39,7 @@ pub use crate::{ }, client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, + rpc::{SubstrateBeefyFinalityClient, SubstrateFinalityClient, SubstrateGrandpaFinalityClient}, sync_header::SyncHeader, transaction_tracker::TransactionTracker, }; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index fdba424dd90fd..083b1dea761a1 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -16,9 +16,15 @@ //! The most generic Substrate node RPC interface. -use crate::{Chain, TransactionStatusOf}; +use async_trait::async_trait; -use jsonrpsee::{core::RpcResult, proc_macros::rpc}; +use crate::{Chain, ChainWithGrandpa, TransactionStatusOf}; + +use jsonrpsee::{ + core::{client::Subscription, RpcResult}, + proc_macros::rpc, + ws_client::WsClient, +}; use pallet_transaction_payment_rpc_runtime_api::FeeDetails; use sc_rpc_api::{state::ReadProof, system::Health}; use sp_core::{ @@ -100,14 +106,49 @@ pub(crate) trait SubstrateState { ) -> RpcResult>; } +/// RPC methods that we are using for a certain finality gadget. +#[async_trait] +pub trait SubstrateFinalityClient { + /// Subscribe to finality justifications. + async fn subscribe_justifications(client: &WsClient) -> RpcResult>; +} + /// RPC methods of Substrate `grandpa` namespace, that we are using. -#[rpc(client, client_bounds(C: Chain), namespace = "grandpa")] +#[rpc(client, client_bounds(C: ChainWithGrandpa), namespace = "grandpa")] pub(crate) trait SubstrateGrandpa { /// Subscribe to GRANDPA justifications. #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] fn subscribe_justifications(&self); } +/// RPC finality methods of Substrate `grandpa` namespace, that we are using. +pub struct SubstrateGrandpaFinalityClient; +#[async_trait] +impl SubstrateFinalityClient for SubstrateGrandpaFinalityClient { + async fn subscribe_justifications(client: &WsClient) -> RpcResult> { + SubstrateGrandpaClient::::subscribe_justifications(client).await + } +} + +// TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged +/// RPC methods of Substrate `beefy` namespace, that we are using. +#[rpc(client, client_bounds(C: Chain), namespace = "beefy")] +pub(crate) trait SubstrateBeefy { + /// Subscribe to BEEFY justifications. + #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] + fn subscribe_justifications(&self); +} + +/// RPC finality methods of Substrate `beefy` namespace, that we are using. +pub struct SubstrateBeefyFinalityClient; +// TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged +#[async_trait] +impl SubstrateFinalityClient for SubstrateBeefyFinalityClient { + async fn subscribe_justifications(client: &WsClient) -> RpcResult> { + SubstrateBeefyClient::::subscribe_justifications(client).await + } +} + /// RPC methods of Substrate `system` frame pallet, that we are using. #[rpc(client, client_bounds(C: Chain), namespace = "system")] pub(crate) trait SubstrateFrameSystem { diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index b2b72e4f2c39f..83ea074e93d0b 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -29,18 +29,20 @@ use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; use relay_substrate_client::{ BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, HeaderOf, - Subscription, + Subscription, SubstrateFinalityClient, SubstrateGrandpaFinalityClient, }; use sp_core::{storage::StorageKey, Bytes}; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; use sp_runtime::{traits::Header, ConsensusEngineId}; use std::marker::PhantomData; -/// Finality enfine, used by the Substrate chain. +/// Finality engine, used by the Substrate chain. #[async_trait] pub trait Engine: Send { /// Unique consensus engine identifier. const ID: ConsensusEngineId; + /// Type of Finality RPC client used by this engine. + type FinalityClient: SubstrateFinalityClient; /// Type of finality proofs, used by consensus engine. type FinalityProof: FinalityProof> + Decode + Encode; /// Type of bridge pallet initialization data. @@ -57,7 +59,9 @@ pub trait Engine: Send { /// Note that we don't care about type of the value - just if it present or not. fn is_initialized_key() -> StorageKey; /// A method to subscribe to encoded finality proofs, given source client. - async fn finality_proofs(client: Client) -> Result, SubstrateError>; + async fn finality_proofs(client: &Client) -> Result, SubstrateError> { + client.subscribe_finality_justifications::().await + } /// Prepare initialization data for the finality bridge pallet. async fn prepare_initialization_data( client: Client, @@ -117,6 +121,7 @@ impl Grandpa { #[async_trait] impl Engine for Grandpa { const ID: ConsensusEngineId = sp_finality_grandpa::GRANDPA_ENGINE_ID; + type FinalityClient = SubstrateGrandpaFinalityClient; type FinalityProof = GrandpaJustification>; type InitializationData = bp_header_chain::InitializationData; type OperatingMode = BasicOperatingMode; @@ -129,10 +134,6 @@ impl Engine for Grandpa { bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } - async fn finality_proofs(client: Client) -> Result, SubstrateError> { - client.subscribe_grandpa_justifications().await - } - /// Prepare initialization data for the GRANDPA verifier pallet. async fn prepare_initialization_data( source_client: Client, @@ -144,8 +145,7 @@ impl Engine for Grandpa { // But now there are problems with this approach - `CurrentSetId` may return invalid value. // So here we're waiting for the next justification, read the authorities set and then try // to figure out the set id with bruteforce. - let justifications = source_client - .subscribe_grandpa_justifications() + let justifications = Self::finality_proofs(&source_client) .await .map_err(|err| Error::Subscribe(C::NAME, err))?; // Read next justification - the header that it finalizes will be used as initial header. diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index c8360bbddbc57..199de36813791 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -142,7 +142,7 @@ impl SourceClient Result { Ok(unfold( - P::FinalityEngine::finality_proofs(self.client.clone()).await?, + P::FinalityEngine::finality_proofs(&self.client).await?, move |subscription| async move { loop { let log_error = |err| { From 879bad9da44b10bb2ae4a5ea0d93273b0f3b1788 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 24 Oct 2022 11:41:37 +0300 Subject: [PATCH 0798/1210] fix parameter to match used value GRANDPA benchmarks (#1616) --- bin/millau/runtime/src/lib.rs | 10 ++++++++-- modules/grandpa/src/benchmarking.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 6439c04565571..1f60e91f59f5c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -417,6 +417,12 @@ parameter_types! { /// /// Note: This is lower than regular value, to speed up benchmarking setup. pub const HeadersToKeep: u32 = 1024; + /// Maximal number of authorities at Rialto. + /// + /// In benchmarks we're using sets of up to `1024` authorities to prepare for possible + /// upgrades in the future and see if performance degrades when number of authorities + /// grow. + pub const MaxAuthoritiesAtRialto: u32 = pallet_bridge_grandpa::benchmarking::MAX_VALIDATOR_SET_SIZE; } #[cfg(not(feature = "runtime-benchmarks"))] @@ -426,11 +432,11 @@ parameter_types! { /// Assuming the worst case of every header being finalized, we will keep headers at least for a /// week. pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS; + /// Maximal number of authorities at Rialto. + pub const MaxAuthoritiesAtRialto: u32 = bp_rialto::MAX_AUTHORITIES_COUNT; } parameter_types! { - /// Maximal number of authorities at Rialto. - pub const MaxAuthoritiesAtRialto: u32 = bp_rialto::MAX_AUTHORITIES_COUNT; /// Maximal size of SCALE-encoded Rialto header. pub const MaxRialtoHeaderSize: u32 = bp_rialto::MAX_HEADER_SIZE; diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index f93798536a3d1..e937f7a0bf414 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -61,7 +61,7 @@ const MAX_VOTE_ANCESTRIES: u32 = 1000; // The maximum number of pre-commits to include in a justification. In practice this scales with the // number of validators. -const MAX_VALIDATOR_SET_SIZE: u32 = 1024; +pub const MAX_VALIDATOR_SET_SIZE: u32 = 1024; // `1..MAX_VALIDATOR_SET_SIZE` and `1..MAX_VOTE_ANCESTRIES` are too large && benchmarks are // running for almost 40m (steps=50, repeat=20) on a decent laptop, which is too much. Since From b1c23a6a8ac458727eba9fdf84e809bc21aa336c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 28 Oct 2022 11:46:40 +0300 Subject: [PATCH 0799/1210] fixes for nightly clippy (#1618) --- bin/millau/node/src/chain_spec.rs | 4 ++-- bin/millau/node/src/command.rs | 2 +- bin/millau/node/src/service.rs | 4 ++-- bin/rialto-parachain/node/src/chain_spec.rs | 4 ++-- bin/rialto-parachain/node/src/command.rs | 6 +++--- bin/rialto-parachain/node/src/service.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 4 ++-- bin/rialto/node/src/command.rs | 2 +- relays/bin-substrate/src/cli/estimate_fee.rs | 4 ++-- relays/bin-substrate/src/cli/mod.rs | 6 +++--- relays/bin-substrate/src/cli/resubmit_transactions.rs | 4 ++-- relays/client-substrate/src/error.rs | 2 +- relays/finality/src/finality_loop.rs | 2 +- relays/finality/src/sync_loop_metrics.rs | 10 +++++----- relays/lib-substrate-relay/src/finality/source.rs | 2 +- relays/lib-substrate-relay/src/helpers.rs | 4 ++-- relays/lib-substrate-relay/src/lib.rs | 8 ++++---- relays/lib-substrate-relay/src/on_demand/headers.rs | 4 ++-- relays/messages/src/message_race_loop.rs | 2 +- relays/utils/src/initialize.rs | 8 ++++---- relays/utils/src/lib.rs | 4 ++-- relays/utils/src/metrics.rs | 2 +- 22 files changed, 45 insertions(+), 45 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 66ab997aa7431..2ded668fdeebc 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -56,7 +56,7 @@ pub enum Alternative { /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) + TPublic::Pair::from_string(&format!("//{seed}"), None) .expect("static values are valid; qed") .public() } @@ -150,7 +150,7 @@ fn endowed_accounts() -> Vec { let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { [ get_account_id_from_seed::(x), - get_account_id_from_seed::(&format!("{}//stash", x)), + get_account_id_from_seed::(&format!("{x}//stash")), ] }); vec![ diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index e9f94b03a2adc..b8dff87f8f244 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -62,7 +62,7 @@ impl SubstrateCli for Cli { match id { "" | "dev" => crate::chain_spec::Alternative::Development, "local" => crate::chain_spec::Alternative::LocalTestnet, - _ => return Err(format!("Unsupported chain specification: {}", id)), + _ => return Err(format!("Unsupported chain specification: {id}")), } .load(), )) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 72ad071726b50..72a1036c641ba 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -293,7 +293,7 @@ pub fn new_full(mut config: Configuration) -> Result Box::new(move |_, subscription_executor: sc_rpc::SubscriptionTaskExecutor| { let mut io = RpcModule::new(()); - let map_err = |e| sc_service::Error::Other(format!("{}", e)); + let map_err = |e| sc_service::Error::Other(format!("{e}")); io.merge(System::new(client.clone(), pool.clone(), DenyUnsafe::No).into_rpc()) .map_err(map_err)?; io.merge(TransactionPayment::new(client.clone()).into_rpc()).map_err(map_err)?; @@ -314,7 +314,7 @@ pub fn new_full(mut config: Configuration) -> Result beefy_rpc_links.from_voter_best_beefy_stream.clone(), subscription_executor, ) - .map_err(|e| sc_service::Error::Other(format!("{}", e)))? + .map_err(|e| sc_service::Error::Other(format!("{e}")))? .into_rpc(), ) .map_err(map_err)?; diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index a0306514c0391..bfce4f717c679 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -39,7 +39,7 @@ pub type ChainSpec = /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) + TPublic::Pair::from_string(&format!("//{seed}"), None) .expect("static values are valid; qed") .public() } @@ -81,7 +81,7 @@ fn endowed_accounts() -> Vec { let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { [ get_account_id_from_seed::(x), - get_account_id_from_seed::(&format!("{}//stash", x)), + get_account_id_from_seed::(&format!("{x}//stash")), ] }); vec![ diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index 533e731b3ac9d..dd9e95abbe543 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -196,7 +196,7 @@ pub fn run() -> Result<()> { &polkadot_cli, config.tokio_handle.clone(), ) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + .map_err(|err| format!("Relay chain argument error: {err}"))?; cmd.run(config, polkadot_config) }) @@ -292,7 +292,7 @@ pub fn run() -> Result<()> { let state_version = RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); let block: Block = generate_genesis_block(&*config.chain_spec, state_version) - .map_err(|e| format!("{:?}", e))?; + .map_err(|e| format!("{e:?}"))?; let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); let polkadot_config = SubstrateCli::create_configuration( @@ -300,7 +300,7 @@ pub fn run() -> Result<()> { &polkadot_cli, config.tokio_handle.clone(), ) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + .map_err(|err| format!("Relay chain argument error: {err}"))?; info!("Parachain id: {:?}", id); info!("Parachain Account: {}", parachain_account); diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index f97c2fcd7c45e..8d722b3caa62a 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -443,7 +443,7 @@ pub async fn start_node( use substrate_frame_rpc_system::{System, SystemApiServer}; let mut io = jsonrpsee::RpcModule::new(()); - let map_err = |e| sc_service::Error::Other(format!("{}", e)); + let map_err = |e| sc_service::Error::Other(format!("{e}")); io.merge(System::new(client.clone(), pool, DenyUnsafe::No).into_rpc()) .map_err(map_err)?; io.merge(TransactionPayment::new(client).into_rpc()).map_err(map_err)?; diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index ffd7bafaa8377..0e9edb38ac03e 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -57,7 +57,7 @@ pub enum Alternative { /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) + TPublic::Pair::from_string(&format!("//{seed}"), None) .expect("static values are valid; qed") .public() } @@ -156,7 +156,7 @@ fn endowed_accounts() -> Vec { let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { [ get_account_id_from_seed::(x), - get_account_id_from_seed::(&format!("{}//stash", x)), + get_account_id_from_seed::(&format!("{x}//stash")), ] }); vec![ diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 852acb5955311..8286444d3ea85 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -57,7 +57,7 @@ impl SubstrateCli for Cli { match id { "" | "dev" => crate::chain_spec::Alternative::Development, "local" => crate::chain_spec::Alternative::LocalTestnet, - _ => return Err(format!("Unsupported chain specification: {}", id)), + _ => return Err(format!("Unsupported chain specification: {id}")), } .load(), )) diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 806df7f01f777..88823eec2f292 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -79,7 +79,7 @@ impl std::str::FromStr for ConversionRateOverride { f64::from_str(s) .map(ConversionRateOverride::Explicit) - .map_err(|e| format!("Failed to parse '{:?}'. Expected 'metric' or explicit value", e)) + .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'metric' or explicit value")) } } @@ -105,7 +105,7 @@ where .await?; log::info!(target: "bridge", "Fee: {:?}", Balance(fee.into())); - println!("{}", fee); + println!("{fee}"); Ok(()) } } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 42a073bd4f65a..2369bb60dda75 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -215,7 +215,7 @@ impl std::str::FromStr for HexBytes { impl std::fmt::Debug for HexBytes { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "0x{}", self) + write!(fmt, "0x{self}") } } @@ -275,7 +275,7 @@ where V::from_str(s) .map(ExplicitOrMaximal::Explicit) - .map_err(|e| format!("Failed to parse '{:?}'. Expected 'max' or explicit value", e)) + .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'max' or explicit value")) } } @@ -298,7 +298,7 @@ mod tests { fn hex_bytes_display_matches_from_str_for_clap() { // given let hex = HexBytes(vec![1, 2, 3, 4]); - let display = format!("{}", hex); + let display = format!("{hex}"); // when let hex2: HexBytes = display.parse().unwrap(); diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index ac479986ed8fb..4481d3fb7121f 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -398,10 +398,10 @@ async fn update_transaction_tip>( tip_limit: C::Balance, target_priority: TransactionPriority, ) -> Result<(bool, S::SignedTransaction), SubstrateError> { - let stx = format!("{:?}", tx); + let stx = format!("{tx:?}"); let mut current_priority = client.validate_transaction(at_block.1, tx.clone()).await??.priority; let mut unsigned_tx = S::parse_transaction(tx).ok_or_else(|| { - SubstrateError::Custom(format!("Failed to parse {} transaction {}", C::NAME, stx,)) + SubstrateError::Custom(format!("Failed to parse {} transaction {stx}", C::NAME,)) })?; let old_tip = unsigned_tx.tip; diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 016ec774beb49..4252a5027d446 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -70,7 +70,7 @@ pub enum Error { impl From for Error { fn from(error: tokio::task::JoinError) -> Self { - Error::Custom(format!("Failed to wait tokio task: {}", error)) + Error::Custom(format!("Failed to wait tokio task: {error}")) } } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 302a038b81eb1..1ee1a8d9db6bb 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -220,7 +220,7 @@ impl Transaction best_id_at_target.0 { return Err(format!( diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs index fcfdbbd99f1b4..ae73bbedc4f75 100644 --- a/relays/finality/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -39,15 +39,15 @@ impl SyncLoopMetrics { ) -> Result { Ok(SyncLoopMetrics { best_source_block_number: IntGauge::new( - metric_name(prefix, &format!("best_{}_block_number", at_source_chain_label)), - format!("Best block number at the {}", at_source_chain_label), + metric_name(prefix, &format!("best_{at_source_chain_label}_block_number")), + format!("Best block number at the {at_source_chain_label}"), )?, best_target_block_number: IntGauge::new( - metric_name(prefix, &format!("best_{}_block_number", at_target_chain_label)), - format!("Best block number at the {}", at_target_chain_label), + metric_name(prefix, &format!("best_{at_target_chain_label}_block_number")), + format!("Best block number at the {at_target_chain_label}"), )?, using_different_forks: IntGauge::new( - metric_name(prefix, &format!("is_{}_and_{}_using_different_forks", at_source_chain_label, at_target_chain_label)), + metric_name(prefix, &format!("is_{at_source_chain_label}_and_{at_target_chain_label}_using_different_forks")), "Whether the best finalized source block at target node is different (value 1) from the \ corresponding block at the source node", )?, diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index 199de36813791..430a83eb43ca7 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -168,7 +168,7 @@ impl SourceClient j, Err(err) => { - log_error(format!("decode failed with error {:?}", err)); + log_error(format!("decode failed with error {err:?}")); continue }, }; diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs index 80359b1c2a980..0b824708a8996 100644 --- a/relays/lib-substrate-relay/src/helpers.rs +++ b/relays/lib-substrate-relay/src/helpers.rs @@ -21,8 +21,8 @@ use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, StandaloneMetr /// Creates standalone token price metric. pub fn token_price_metric(token_id: &str) -> Result { FloatJsonValueMetric::new( - format!("https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", token_id), - format!("$.{}.btc", token_id), + format!("https://api.coingecko.com/api/v3/simple/price?ids={token_id}&vs_currencies=btc"), + format!("$.{token_id}.btc"), format!("{}_to_base_conversion_rate", token_id.replace('-', "_")), format!("Rate used to convert from {} to some BASE tokens", token_id.to_uppercase()), ) diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index f4f1aae9d29d1..86e652716f643 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -85,15 +85,15 @@ impl TaggedAccount { /// Returns stringified account tag. pub fn tag(&self) -> String { match *self { - TaggedAccount::Headers { ref bridged_chain, .. } => format!("{}Headers", bridged_chain), + TaggedAccount::Headers { ref bridged_chain, .. } => format!("{bridged_chain}Headers"), TaggedAccount::Parachains { ref bridged_chain, .. } => { - format!("{}Parachains", bridged_chain) + format!("{bridged_chain}Parachains") }, TaggedAccount::Messages { ref bridged_chain, .. } => { - format!("{}Messages", bridged_chain) + format!("{bridged_chain}Messages") }, TaggedAccount::MessagesPalletOwner { ref bridged_chain, .. } => { - format!("{}MessagesPalletOwner", bridged_chain) + format!("{bridged_chain}MessagesPalletOwner") }, } } diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 09e7a41a0c725..87f1e012cc57d 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -172,9 +172,9 @@ async fn background_task( // submit mandatory header if some headers are missing let best_finalized_source_header_at_source_fmt = - format!("{:?}", best_finalized_source_header_at_source); + format!("{best_finalized_source_header_at_source:?}"); let best_finalized_source_header_at_target_fmt = - format!("{:?}", best_finalized_source_header_at_target); + format!("{best_finalized_source_header_at_target:?}"); let required_header_number_value = *required_header_number.lock().await; let mandatory_scan_range = mandatory_headers_scan_range::( best_finalized_source_header_at_source.ok(), diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 15308f93032b4..4f59b635ae6f2 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -425,7 +425,7 @@ pub async fn run, TC: TargetClient

>( // nonce at the target node. race_target.nonces(at_block, false) .await - .map_err(|e| format!("failed to read nonces from target node: {:?}", e)) + .map_err(|e| format!("failed to read nonces from target node: {e:?}")) .and_then(|(_, nonces_at_target)| { if nonces_at_target.latest_nonce < *nonces_submitted.end() { Err(format!( diff --git a/relays/utils/src/initialize.rs b/relays/utils/src/initialize.rs index ad69a766e6236..8224c1803ad2f 100644 --- a/relays/utils/src/initialize.rs +++ b/relays/utils/src/initialize.rs @@ -68,7 +68,7 @@ pub fn initialize_logger(with_timestamp: bool) { let log_level = color_level(record.level()); let log_target = color_target(record.target()); - writeln!(buf, "{}{} {} {}", loop_name_prefix(), log_level, log_target, record.args(),) + writeln!(buf, "{}{log_level} {log_target} {}", loop_name_prefix(), record.args(),) }); } @@ -92,7 +92,7 @@ fn loop_name_prefix() -> String { if loop_name.is_empty() { String::new() } else { - format!("[{}] ", loop_name) + format!("[{loop_name}] ") } }) .unwrap_or_else(|_| String::new()) @@ -105,8 +105,8 @@ enum Either { impl Display for Either { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Self::Left(a) => write!(fmt, "{}", a), - Self::Right(b) => write!(fmt, "{}", b), + Self::Left(a) => write!(fmt, "{a}"), + Self::Right(b) => write!(fmt, "{b}"), } } } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index eb3d8ec752508..42bf86ebf5b37 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -189,12 +189,12 @@ pub fn format_ids(mut ids: impl ExactSizeIterator { let id0 = ids.next().expect(NTH_PROOF); let id1 = ids.next().expect(NTH_PROOF); - format!("[{:?}, {:?}]", id0, id1) + format!("[{id0:?}, {id1:?}]") }, len => { let id0 = ids.next().expect(NTH_PROOF); let id_last = ids.last().expect(NTH_PROOF); - format!("{}:[{:?} ... {:?}]", len, id0, id_last) + format!("{len}:[{id0:?} ... {id_last:?}]") }, } } diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index b5225fca0e0c8..fa7a79a71c144 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -121,7 +121,7 @@ impl From> for MetricsParams { /// Returns metric name optionally prefixed with given prefix. pub fn metric_name(prefix: Option<&str>, name: &str) -> String { if let Some(prefix) = prefix { - format!("{}_{}", prefix, name) + format!("{prefix}_{name}") } else { name.into() } From 96eee99c02989e3c3c42285b684a38a79351ccf3 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 28 Oct 2022 13:12:37 +0300 Subject: [PATCH 0800/1210] Finality loop: get block justification and authorities change by consensus engine ID (#1619) * SignedBlock: get justification by consensus engine id * Define ConsensusLogReader Making the check for authority changes more generic * cod review changes --- primitives/header-chain/src/lib.rs | 39 ++++++++++----- relays/client-substrate/src/chain.rs | 10 ++-- relays/client-substrate/src/sync_header.rs | 8 +-- relays/finality/src/finality_loop_tests.rs | 6 ++- relays/finality/src/lib.rs | 8 +-- .../src/finality/engine.rs | 50 +++++++++++-------- .../lib-substrate-relay/src/finality/mod.rs | 3 +- .../src/finality/source.rs | 13 ++--- .../src/on_demand/headers.rs | 15 +++--- 9 files changed, 88 insertions(+), 64 deletions(-) diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index f5590ce0a5a2b..21a42874b719d 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -26,7 +26,7 @@ use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; -use sp_runtime::{generic::OpaqueDigestItemId, traits::Header as HeaderT, RuntimeDebug}; +use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; use sp_std::boxed::Box; pub mod justification; @@ -77,18 +77,31 @@ pub trait FinalityProof: Clone + Send + Sync + Debug { fn target_header_number(&self) -> Number; } -/// Find header digest that schedules next GRANDPA authorities set. -pub fn find_grandpa_authorities_scheduled_change( - header: &H, -) -> Option> { - let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); +/// A trait that provides helper methods for querying the consensus log. +pub trait ConsensusLogReader { + fn schedules_authorities_change(digest: &Digest) -> bool; +} - let filter_log = |log: ConsensusLog| match log { - ConsensusLog::ScheduledChange(change) => Some(change), - _ => None, - }; +/// A struct that provides helper methods for querying the GRANDPA consensus log. +pub struct GrandpaConsensusLogReader(sp_std::marker::PhantomData); - // find the first consensus digest with the right ID which converts to - // the right kind of consensus log. - header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) +impl GrandpaConsensusLogReader { + pub fn find_authorities_change( + digest: &Digest, + ) -> Option> { + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + digest + .convert_first(|log| log.consensus_try_to(&GRANDPA_ENGINE_ID)) + .and_then(|log| match log { + ConsensusLog::ScheduledChange(change) => Some(change), + _ => None, + }) + } +} + +impl ConsensusLogReader for GrandpaConsensusLogReader { + fn schedules_authorities_change(digest: &Digest) -> bool { + GrandpaConsensusLogReader::::find_authorities_change(digest).is_some() + } } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 3f483078cac79..97e3b0f0fc21e 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -27,7 +27,7 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, traits::{Block as BlockT, Dispatchable, Member}, - EncodedJustification, + ConsensusEngineId, EncodedJustification, }; use std::{fmt::Debug, time::Duration}; @@ -147,7 +147,7 @@ pub trait BlockWithJustification

{ /// Return encoded block extrinsics. fn extrinsics(&self) -> Vec; /// Return block justification, if known. - fn justification(&self) -> Option<&EncodedJustification>; + fn justification(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification>; } /// Transaction before it is signed. @@ -237,9 +237,7 @@ impl BlockWithJustification for SignedBlock self.block.extrinsics().iter().map(Encode::encode).collect() } - fn justification(&self) -> Option<&EncodedJustification> { - self.justifications - .as_ref() - .and_then(|j| j.get(sp_finality_grandpa::GRANDPA_ENGINE_ID)) + fn justification(&self, engine_id: ConsensusEngineId) -> Option<&EncodedJustification> { + self.justifications.as_ref().and_then(|j| j.get(engine_id)) } } diff --git a/relays/client-substrate/src/sync_header.rs b/relays/client-substrate/src/sync_header.rs index e45e6b4197abb..fdfd1f22ce9ed 100644 --- a/relays/client-substrate/src/sync_header.rs +++ b/relays/client-substrate/src/sync_header.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use bp_header_chain::find_grandpa_authorities_scheduled_change; +use bp_header_chain::ConsensusLogReader; use finality_relay::SourceHeader as FinalitySourceHeader; use sp_runtime::traits::Header as HeaderT; @@ -44,7 +44,9 @@ impl
From
for SyncHeader
{ } } -impl FinalitySourceHeader for SyncHeader
{ +impl FinalitySourceHeader + for SyncHeader
+{ fn hash(&self) -> Header::Hash { self.0.hash() } @@ -54,6 +56,6 @@ impl FinalitySourceHeader for Syn } fn is_mandatory(&self) -> bool { - find_grandpa_authorities_scheduled_change(&self.0).is_some() + R::schedules_authorities_change(self.digest()) } } diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index a6e97c0770f99..1853c095f703f 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -30,6 +30,7 @@ use crate::{ }; use async_trait::async_trait; +use bp_header_chain::GrandpaConsensusLogReader; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; use relay_utils::{ @@ -85,6 +86,7 @@ impl FinalitySyncPipeline for TestFinalitySyncPipeline { type Hash = TestHash; type Number = TestNumber; + type ConsensusLogReader = GrandpaConsensusLogReader; type Header = TestSourceHeader; type FinalityProof = TestFinalityProof; } @@ -92,7 +94,9 @@ impl FinalitySyncPipeline for TestFinalitySyncPipeline { #[derive(Debug, Clone, PartialEq, Eq)] struct TestSourceHeader(IsMandatory, TestNumber, TestHash); -impl SourceHeader for TestSourceHeader { +impl SourceHeader> + for TestSourceHeader +{ fn hash(&self) -> TestHash { self.2 } diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index 49be64ff74db2..dca47c6a572cf 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -24,7 +24,7 @@ pub use crate::{ sync_loop_metrics::SyncLoopMetrics, }; -use bp_header_chain::FinalityProof; +use bp_header_chain::{ConsensusLogReader, FinalityProof}; use std::fmt::Debug; mod finality_loop; @@ -42,14 +42,16 @@ pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { type Hash: Eq + Clone + Copy + Send + Sync + Debug; /// Headers we're syncing are identified by this number. type Number: relay_utils::BlockNumberBase; + /// A reader that can extract the consensus log from the header digest and interpret it. + type ConsensusLogReader: ConsensusLogReader; /// Type of header that we're syncing. - type Header: SourceHeader; + type Header: SourceHeader; /// Finality proof type. type FinalityProof: FinalityProof; } /// Header that we're receiving from source node. -pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { +pub trait SourceHeader: Clone + Debug + PartialEq + Send + Sync { /// Returns hash of header. fn hash(&self) -> Hash; /// Returns number of header. diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 83ea074e93d0b..4c2da5a53195d 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -19,9 +19,8 @@ use crate::error::Error; use async_trait::async_trait; use bp_header_chain::{ - find_grandpa_authorities_scheduled_change, justification::{verify_justification, GrandpaJustification}, - FinalityProof, + ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader, }; use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode}; @@ -32,7 +31,7 @@ use relay_substrate_client::{ Subscription, SubstrateFinalityClient, SubstrateGrandpaFinalityClient, }; use sp_core::{storage::StorageKey, Bytes}; -use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; +use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header, ConsensusEngineId}; use std::marker::PhantomData; @@ -41,6 +40,8 @@ use std::marker::PhantomData; pub trait Engine: Send { /// Unique consensus engine identifier. const ID: ConsensusEngineId; + /// A reader that can extract the consensus log from the header digest and interpret it. + type ConsensusLogReader: ConsensusLogReader; /// Type of Finality RPC client used by this engine. type FinalityClient: SubstrateFinalityClient; /// Type of finality proofs, used by consensus engine. @@ -50,22 +51,11 @@ pub trait Engine: Send { /// Type of bridge pallet operating mode. type OperatingMode: OperatingMode + 'static; - /// Returns storage key at the bridged (target) chain that corresponds to the variable - /// that holds the operating mode of the pallet. - fn pallet_operating_mode_key() -> StorageKey; /// Returns storage at the bridged (target) chain that corresponds to some value that is /// missing from the storage until bridge pallet is initialized. /// /// Note that we don't care about type of the value - just if it present or not. fn is_initialized_key() -> StorageKey; - /// A method to subscribe to encoded finality proofs, given source client. - async fn finality_proofs(client: &Client) -> Result, SubstrateError> { - client.subscribe_finality_justifications::().await - } - /// Prepare initialization data for the finality bridge pallet. - async fn prepare_initialization_data( - client: Client, - ) -> Result, BlockNumberOf>>; /// Returns `Ok(true)` if finality pallet at the bridged chain has already been initialized. async fn is_initialized( @@ -77,6 +67,10 @@ pub trait Engine: Send { .is_some()) } + /// Returns storage key at the bridged (target) chain that corresponds to the variable + /// that holds the operating mode of the pallet. + fn pallet_operating_mode_key() -> StorageKey; + /// Returns `Ok(true)` if finality pallet at the bridged chain is halted. async fn is_halted( target_client: &Client, @@ -87,6 +81,16 @@ pub trait Engine: Send { .map(|operating_mode| operating_mode.is_halted()) .unwrap_or(false)) } + + /// A method to subscribe to encoded finality proofs, given source client. + async fn finality_proofs(client: &Client) -> Result, SubstrateError> { + client.subscribe_finality_justifications::().await + } + + /// Prepare initialization data for the finality bridge pallet. + async fn prepare_initialization_data( + client: Client, + ) -> Result, BlockNumberOf>>; } /// GRANDPA finality engine. @@ -120,20 +124,21 @@ impl Grandpa { #[async_trait] impl Engine for Grandpa { - const ID: ConsensusEngineId = sp_finality_grandpa::GRANDPA_ENGINE_ID; + const ID: ConsensusEngineId = GRANDPA_ENGINE_ID; + type ConsensusLogReader = GrandpaConsensusLogReader<::Number>; type FinalityClient = SubstrateGrandpaFinalityClient; type FinalityProof = GrandpaJustification>; type InitializationData = bp_header_chain::InitializationData; type OperatingMode = BasicOperatingMode; - fn pallet_operating_mode_key() -> StorageKey { - bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) - } - fn is_initialized_key() -> StorageKey { bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } + fn pallet_operating_mode_key() -> StorageKey { + bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + } + /// Prepare initialization data for the GRANDPA verifier pallet. async fn prepare_initialization_data( source_client: Client, @@ -183,11 +188,14 @@ impl Engine for Grandpa { // If initial header changes the GRANDPA authorities set, then we need previous authorities // to verify justification. let mut authorities_for_verification = initial_authorities_set.clone(); - let scheduled_change = find_grandpa_authorities_scheduled_change(&initial_header); + let scheduled_change = + GrandpaConsensusLogReader::>::find_authorities_change( + initial_header.digest(), + ); assert!( scheduled_change.as_ref().map(|c| c.delay.is_zero()).unwrap_or(true), "GRANDPA authorities change at {} scheduled to happen in {:?} blocks. We expect\ - regular hange to have zero delay", + regular change to have zero delay", initial_header_hash, scheduled_change.as_ref().map(|c| c.delay), ); diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index 3144a1016ea5c..aefcd21722525 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -87,7 +87,8 @@ impl FinalitySyncPipeline for FinalitySyncPipe type Hash = HashOf; type Number = BlockNumberOf; - type Header = relay_substrate_client::SyncHeader>; + type ConsensusLogReader = >::ConsensusLogReader; + type Header = SyncHeader>; type FinalityProof = SubstrateFinalityProof

; } diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index 430a83eb43ca7..e75862a8227bc 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -33,15 +33,8 @@ use std::pin::Pin; pub type RequiredHeaderNumberRef = Arc::BlockNumber>>; /// Substrate finality proofs stream. -pub type SubstrateFinalityProofsStream

= Pin< - Box< - dyn Stream< - Item = <

::FinalityEngine as Engine< -

::SourceChain, - >>::FinalityProof, - > + Send, - >, ->; +pub type SubstrateFinalityProofsStream

= + Pin> + Send>>; /// Substrate finality proof. Specific to the used `FinalityEngine`. pub type SubstrateFinalityProof

= @@ -130,7 +123,7 @@ impl SourceClient::decode(&mut raw_justification.as_slice()) }) diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 87f1e012cc57d..3a54e6bb00cba 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -18,13 +18,14 @@ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; +use bp_header_chain::ConsensusLogReader; use futures::{select, FutureExt}; use num_traits::{One, Zero}; +use sp_runtime::traits::Header; -use finality_relay::{FinalitySyncParams, SourceHeader, TargetClient as FinalityTargetClient}; +use finality_relay::{FinalitySyncParams, TargetClient as FinalityTargetClient}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, HeaderOf, SyncHeader, - TransactionSignScheme, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, TransactionSignScheme, }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, @@ -33,6 +34,7 @@ use relay_utils::{ use crate::{ finality::{ + engine::Engine, source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, target::SubstrateFinalityTarget, SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT, @@ -416,9 +418,10 @@ async fn find_mandatory_header_in_range( ) -> Result>, relay_substrate_client::Error> { let mut current = range.0; while current <= range.1 { - let header: SyncHeader> = - finality_source.client().header_by_number(current).await?.into(); - if header.is_mandatory() { + let header = finality_source.client().header_by_number(current).await?; + if >::ConsensusLogReader::schedules_authorities_change( + header.digest(), + ) { return Ok(Some(current)) } From 380ba3a0b9400181311c7cfee15ccbdc15cb22df Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 2 Nov 2022 14:36:48 +0300 Subject: [PATCH 0801/1210] refactor transaction sign scheme (#1621) --- .../src/chains/millau_headers_to_rialto.rs | 1 - .../millau_headers_to_rialto_parachain.rs | 1 - .../src/chains/millau_messages_to_rialto.rs | 3 - .../millau_messages_to_rialto_parachain.rs | 3 - relays/bin-substrate/src/chains/mod.rs | 2 +- .../src/chains/rialto_headers_to_millau.rs | 1 - .../src/chains/rialto_messages_to_millau.rs | 3 - .../rialto_parachain_messages_to_millau.rs | 3 - .../src/chains/rialto_parachains_to_millau.rs | 1 - .../src/chains/westend_headers_to_millau.rs | 1 - .../chains/westend_parachains_to_millau.rs | 1 - relays/bin-substrate/src/cli/bridge.rs | 11 +-- .../src/cli/relay_headers_and_messages/mod.rs | 31 ++++---- .../relay_to_parachain.rs | 14 ++-- .../relay_to_relay.rs | 10 +-- .../bin-substrate/src/cli/relay_messages.rs | 5 +- .../src/cli/resubmit_transactions.rs | 76 +++++++++---------- relays/bin-substrate/src/cli/send_message.rs | 6 +- relays/client-millau/src/lib.rs | 17 ++--- relays/client-rialto-parachain/src/lib.rs | 11 ++- relays/client-rialto/src/lib.rs | 17 ++--- relays/client-substrate/src/chain.rs | 16 ++-- relays/client-substrate/src/client.rs | 28 ++++--- relays/client-substrate/src/lib.rs | 2 +- .../src/conversion_rate_update.rs | 24 +++--- .../src/finality/guards.rs | 8 +- .../src/finality/initialize.rs | 6 +- .../lib-substrate-relay/src/finality/mod.rs | 15 ++-- .../src/finality/target.rs | 11 ++- .../lib-substrate-relay/src/messages_lane.rs | 25 ++---- .../src/messages_source.rs | 27 +++---- .../src/messages_target.rs | 27 +++---- .../src/on_demand/headers.rs | 19 ++--- .../src/on_demand/parachains.rs | 12 +-- .../lib-substrate-relay/src/parachains/mod.rs | 6 +- .../src/parachains/target.rs | 13 ++-- 36 files changed, 188 insertions(+), 269 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index 0aa49bdada92c..e0dbabd86b4c5 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -36,7 +36,6 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { rialto_runtime::Runtime, rialto_runtime::MillauGrandpaInstance, >; - type TransactionSignScheme = relay_rialto_client::Rialto; } //// `Millau` to `Rialto` bridge definition. diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs index 4eaf3f6f750a1..cdb3999db6ed1 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -54,7 +54,6 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { rialto_parachain_runtime::Runtime, rialto_parachain_runtime::MillauGrandpaInstance, >; - type TransactionSignScheme = relay_rialto_parachain_client::RialtoParachain; } //// `Millau` to `RialtoParachain` bridge definition. diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index f20669e6c7a58..332721e217f0d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -49,9 +49,6 @@ impl SubstrateMessageLane for MillauMessagesToRialto { type SourceChain = Millau; type TargetChain = Rialto; - type SourceTransactionSignScheme = Millau; - type TargetTransactionSignScheme = Rialto; - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< Self, rialto_runtime::Runtime, diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index d5b42798dd4fa..04b2b1e46e66a 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -54,9 +54,6 @@ impl SubstrateMessageLane for MillauMessagesToRialtoParachain { type SourceChain = Millau; type TargetChain = RialtoParachain; - type SourceTransactionSignScheme = Millau; - type TargetTransactionSignScheme = RialtoParachain; - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< Self, rialto_parachain_runtime::Runtime, diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 772f2552f5bfc..13aca0651ae52 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -40,7 +40,7 @@ mod tests { use codec::Encode; use relay_millau_client::Millau; use relay_rialto_client::Rialto; - use relay_substrate_client::{SignParam, TransactionSignScheme, UnsignedTransaction}; + use relay_substrate_client::{ChainWithTransactions, SignParam, UnsignedTransaction}; #[test] fn maximal_rialto_to_millau_message_size_is_computed_correctly() { diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index 65c5cba1ae378..b1ab4a8537b6e 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -36,7 +36,6 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { millau_runtime::Runtime, millau_runtime::RialtoGrandpaInstance, >; - type TransactionSignScheme = relay_millau_client::Millau; } //// `Rialto` to `Millau` bridge definition. diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index d34f471464492..e922659ab9a8b 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -49,9 +49,6 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { type SourceChain = Rialto; type TargetChain = Millau; - type SourceTransactionSignScheme = Rialto; - type TargetTransactionSignScheme = Millau; - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< Self, millau_runtime::Runtime, diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index b8ff0af10f840..ef13920cf8554 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -54,9 +54,6 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { type SourceChain = RialtoParachain; type TargetChain = Millau; - type SourceTransactionSignScheme = RialtoParachain; - type TargetTransactionSignScheme = Millau; - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< Self, millau_runtime::Runtime, diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index 800d5a3e79bd2..911d439938948 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -40,7 +40,6 @@ impl SubstrateParachainsPipeline for RialtoParachainsToMillau { type TargetChain = Millau; type SubmitParachainHeadsCallBuilder = RialtoParachainsToMillauSubmitParachainHeadsCallBuilder; - type TransactionSignScheme = Millau; const SOURCE_PARACHAIN_PARA_ID: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID; } diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs index 833946458974a..2a253756c2b98 100644 --- a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_headers_to_millau.rs @@ -36,7 +36,6 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { millau_runtime::Runtime, millau_runtime::WestendGrandpaInstance, >; - type TransactionSignScheme = relay_millau_client::Millau; } //// `Westend` to `Millau` bridge definition. diff --git a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs index 586d391d247c1..73409e65569db 100644 --- a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs @@ -39,7 +39,6 @@ impl SubstrateParachainsPipeline for WestendParachainsToMillau { type TargetChain = Millau; type SubmitParachainHeadsCallBuilder = WestendParachainsToMillauSubmitParachainHeadsCallBuilder; - type TransactionSignScheme = Millau; const SOURCE_PARACHAIN_PARA_ID: u32 = bp_westend::WESTMINT_PARACHAIN_ID; } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 503e523c0289a..ffe4cc51e55c9 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -18,7 +18,7 @@ use crate::cli::CliChain; use messages_relay::relay_strategy::MixStrategy; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use parachains_relay::ParachainsPipeline; -use relay_substrate_client::{AccountKeyPairOf, Chain, RelayChain, TransactionSignScheme}; +use relay_substrate_client::{AccountKeyPairOf, Chain, ChainWithTransactions, RelayChain}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, @@ -58,9 +58,7 @@ pub trait CliBridgeBase: Sized { /// The source chain. type Source: Chain + CliChain; /// The target chain. - type Target: Chain - + TransactionSignScheme - + CliChain>; + type Target: ChainWithTransactions + CliChain>; } /// Bridge representation that can be used from the CLI for relaying headers @@ -70,7 +68,6 @@ pub trait RelayToRelayHeadersCliBridge: CliBridgeBase { type Finality: SubstrateFinalitySyncPipeline< SourceChain = Self::Source, TargetChain = Self::Target, - TransactionSignScheme = Self::Target, >; } @@ -87,13 +84,11 @@ pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase { SourceRelayChain = Self::SourceRelay, SourceParachain = Self::Source, TargetChain = Self::Target, - TransactionSignScheme = Self::Target, > + ParachainsPipeline; /// Finality proofs synchronization pipeline (source relay chain -> target). type RelayFinality: SubstrateFinalitySyncPipeline< SourceChain = Self::SourceRelay, TargetChain = Self::Target, - TransactionSignScheme = Self::Target, >; } @@ -106,8 +101,6 @@ pub trait MessagesCliBridge: CliBridgeBase { type MessagesLane: SubstrateMessageLane< SourceChain = Self::Source, TargetChain = Self::Target, - SourceTransactionSignScheme = Self::Source, - TargetTransactionSignScheme = Self::Target, RelayStrategy = MixStrategy, >; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 98a0469ae4d77..1feba9d6284e5 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -59,7 +59,7 @@ use bp_messages::LaneId; use bp_runtime::{BalanceOf, BlockNumberOf}; use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, Client, TransactionSignScheme, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithTransactions, Client, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; @@ -93,8 +93,8 @@ pub struct HeadersAndMessagesSharedParams { } pub struct Full2WayBridgeCommonParams< - Left: TransactionSignScheme + CliChain, - Right: TransactionSignScheme + CliChain, + Left: ChainWithTransactions + CliChain, + Right: ChainWithTransactions + CliChain, > { pub shared: HeadersAndMessagesSharedParams, pub left: BridgeEndCommonParams, @@ -105,7 +105,7 @@ pub struct Full2WayBridgeCommonParams< pub right_to_left_metrics: StandaloneMessagesMetrics, } -impl +impl Full2WayBridgeCommonParams { pub fn new>( @@ -132,7 +132,7 @@ impl { +pub struct BridgeEndCommonParams { pub client: Client, pub sign: AccountKeyPairOf, pub transactions_mortality: Option, @@ -142,8 +142,8 @@ pub struct BridgeEndCommonParams { struct FullBridge< 'a, - Source: TransactionSignScheme + CliChain, - Target: TransactionSignScheme + CliChain, + Source: ChainWithTransactions + CliChain, + Target: ChainWithTransactions + CliChain, Bridge: MessagesCliBridge, > { shared: &'a HeadersAndMessagesSharedParams, @@ -156,8 +156,8 @@ struct FullBridge< impl< 'a, - Source: TransactionSignScheme + CliChain, - Target: TransactionSignScheme + CliChain, + Source: ChainWithTransactions + CliChain, + Target: ChainWithTransactions + CliChain, Bridge: MessagesCliBridge, > FullBridge<'a, Source, Target, Bridge> where @@ -186,7 +186,6 @@ where }; substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< Bridge::MessagesLane, - Source, >( self.source.client.clone(), TransactionParams { @@ -266,11 +265,9 @@ trait Full2WayBridgeBase: Sized + Send + Sync { /// The CLI params for the bridge. type Params; /// The left relay chain. - type Left: TransactionSignScheme - + CliChain>; + type Left: ChainWithTransactions + CliChain>; /// The right destination chain (it can be a relay or a parachain). - type Right: TransactionSignScheme - + CliChain>; + type Right: ChainWithTransactions + CliChain>; fn common(&self) -> &Full2WayBridgeCommonParams; @@ -295,14 +292,12 @@ where type Base: Full2WayBridgeBase; /// The left relay chain. - type Left: Chain + type Left: ChainWithTransactions + ChainWithBalances - + TransactionSignScheme + CliChain>; /// The right relay chain. - type Right: Chain + type Right: ChainWithTransactions + ChainWithBalances - + TransactionSignScheme + CliChain>; // Left to Right bridge diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 4123dae5a70f0..0990a2d217587 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -28,7 +28,7 @@ use crate::cli::{ use bp_polkadot_core::parachains::ParaHash; use bp_runtime::BlockNumberOf; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, Client, TransactionSignScheme}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client}; use sp_core::Pair; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, @@ -95,9 +95,9 @@ macro_rules! declare_relay_to_parachain_bridge_schema { impl [<$left_chain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: TransactionSignScheme + CliChain>, - Right: TransactionSignScheme + CliChain>, - RightRelay: TransactionSignScheme + CliChain, + Left: ChainWithTransactions + CliChain>, + Right: ChainWithTransactions + CliChain>, + RightRelay: ChainWithTransactions + CliChain, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase + MessagesCliBridge @@ -146,12 +146,12 @@ macro_rules! declare_relay_to_parachain_bridge_schema { #[async_trait] impl< - Left: Chain + TransactionSignScheme + CliChain>, + Left: ChainWithTransactions + CliChain>, Right: Chain - + TransactionSignScheme + + ChainWithTransactions + CliChain>, RightRelay: Chain - + TransactionSignScheme + + ChainWithTransactions + CliChain, L2R: CliBridgeBase + MessagesCliBridge diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index 2e092ad406be7..fb33fab8b7856 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -23,7 +23,7 @@ use crate::cli::{ CliChain, }; use bp_runtime::BlockNumberOf; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, TransactionSignScheme}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, ChainWithTransactions}; use sp_core::Pair; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, @@ -77,8 +77,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { impl [<$left_chain $right_chain HeadersAndMessages>] { async fn into_bridge< - Left: TransactionSignScheme + CliChain>, - Right: TransactionSignScheme + CliChain>, + Left: ChainWithTransactions + CliChain>, + Right: ChainWithTransactions + CliChain>, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, >( @@ -117,8 +117,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { #[async_trait] impl< - Left: Chain + TransactionSignScheme + CliChain>, - Right: Chain + TransactionSignScheme + CliChain>, + Left: ChainWithTransactions + CliChain>, + Right: ChainWithTransactions + CliChain>, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index a68ce03054308..d03a1f97c3dd7 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -26,7 +26,7 @@ use crate::chains::{ rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, }; use messages_relay::relay_strategy::MixStrategy; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, TransactionSignScheme}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions}; use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; use crate::cli::{bridge::*, chain_schema::*, CliChain, HexLaneId, PrometheusParams}; @@ -77,8 +77,7 @@ pub struct RelayMessages { #[async_trait] trait MessagesRelayer: MessagesCliBridge where - Self::Source: TransactionSignScheme - + CliChain>, + Self::Source: ChainWithTransactions + CliChain>, AccountIdOf: From< as Pair>::Public>, AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 4481d3fb7121f..c69f9c8ae4e7b 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -20,8 +20,8 @@ use bp_runtime::HeaderIdProvider; use codec::{Decode, Encode}; use num_traits::{One, Zero}; use relay_substrate_client::{ - BlockWithJustification, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, - SignParam, TransactionSignScheme, + AccountKeyPairOf, BlockWithJustification, Chain, ChainWithTransactions, Client, + Error as SubstrateError, HeaderIdOf, HeaderOf, SignParam, }; use relay_utils::FailedClient; use sp_core::Bytes; @@ -111,7 +111,7 @@ impl ResubmitTransactions { relay_utils::relay_loop((), client) .run(relay_loop_name, move |_, client, _| { - run_until_connection_lost::( + run_until_connection_lost( client, transaction_params.clone(), Context { @@ -140,16 +140,16 @@ impl ResubmitTransactions { impl PrioritySelectionStrategy { /// Select target priority. - async fn select_target_priority>( + async fn select_target_priority( &self, client: &Client, context: &Context, ) -> Result, SubstrateError> { match *self { PrioritySelectionStrategy::MakeItBestTransaction => - read_previous_block_best_priority::(client, context).await, + read_previous_block_best_priority(client, context).await, PrioritySelectionStrategy::MakeItBetterThanQueuedTransaction => - select_priority_from_queue::(client, context).await, + select_priority_from_queue(client, context).await, } } } @@ -202,16 +202,15 @@ impl Context { } /// Run resubmit transactions loop. -async fn run_until_connection_lost>( +async fn run_until_connection_lost( client: Client, - transaction_params: TransactionParams, + transaction_params: TransactionParams>, mut context: Context, ) -> Result<(), FailedClient> { loop { async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; - let result = - run_loop_iteration::(client.clone(), transaction_params.clone(), context).await; + let result = run_loop_iteration(client.clone(), transaction_params.clone(), context).await; context = match result { Ok(context) => context, Err(error) => { @@ -228,9 +227,9 @@ async fn run_until_connection_lost } /// Run single loop iteration. -async fn run_loop_iteration>( +async fn run_loop_iteration( client: Client, - transaction_params: TransactionParams, + transaction_params: TransactionParams>, mut context: Context, ) -> Result, SubstrateError> { // correct best header is required for all other actions @@ -238,7 +237,7 @@ async fn run_loop_iteration>( // check if there's queued transaction, signed by given author let original_transaction = - match lookup_signer_transaction::(&client, &transaction_params.signer).await? { + match lookup_signer_transaction(&client, &transaction_params.signer).await? { Some(original_transaction) => original_transaction, None => { log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); @@ -262,17 +261,16 @@ async fn run_loop_iteration>( } // select priority for updated transaction - let target_priority = - match context.strategy.select_target_priority::(&client, &context).await? { - Some(target_priority) => target_priority, - None => { - log::trace!(target: "bridge", "Failed to select target priority"); - return Ok(context) - }, - }; + let target_priority = match context.strategy.select_target_priority(&client, &context).await? { + Some(target_priority) => target_priority, + None => { + log::trace!(target: "bridge", "Failed to select target priority"); + return Ok(context) + }, + }; // update transaction tip - let (is_updated, updated_transaction) = update_transaction_tip::( + let (is_updated, updated_transaction) = update_transaction_tip( &client, &transaction_params, context.best_header.id(), @@ -304,15 +302,15 @@ async fn run_loop_iteration>( } /// Search transaction pool for transaction, signed by given key pair. -async fn lookup_signer_transaction>( +async fn lookup_signer_transaction( client: &Client, - key_pair: &S::AccountKeyPair, -) -> Result, SubstrateError> { + key_pair: &AccountKeyPairOf, +) -> Result, SubstrateError> { let pending_transactions = client.pending_extrinsics().await?; for pending_transaction in pending_transactions { - let pending_transaction = S::SignedTransaction::decode(&mut &pending_transaction.0[..]) + let pending_transaction = C::SignedTransaction::decode(&mut &pending_transaction.0[..]) .map_err(SubstrateError::ResponseParseFailed)?; - if !S::is_signed_by(key_pair, &pending_transaction) { + if !C::is_signed_by(key_pair, &pending_transaction) { continue } @@ -323,7 +321,7 @@ async fn lookup_signer_transaction } /// Read priority of best signed transaction of previous block. -async fn read_previous_block_best_priority>( +async fn read_previous_block_best_priority( client: &Client, context: &Context, ) -> Result, SubstrateError> { @@ -331,8 +329,8 @@ async fn read_previous_block_best_priority Ok(Some( client @@ -345,7 +343,7 @@ async fn read_previous_block_best_priority>( +async fn select_priority_from_queue( client: &Client, context: &Context, ) -> Result, SubstrateError> { @@ -356,7 +354,7 @@ async fn select_priority_from_queue return Ok(None), }; - let selected_transaction = S::SignedTransaction::decode(&mut &selected_transaction[..]) + let selected_transaction = C::SignedTransaction::decode(&mut &selected_transaction[..]) .map_err(SubstrateError::ResponseParseFailed)?; let target_priority = client .validate_transaction(context.best_header.hash(), selected_transaction) @@ -389,18 +387,18 @@ fn select_transaction_from_queue( } /// Try to find appropriate tip for transaction so that its priority is larger than given. -async fn update_transaction_tip>( +async fn update_transaction_tip( client: &Client, - transaction_params: &TransactionParams, + transaction_params: &TransactionParams>, at_block: HeaderIdOf, - tx: S::SignedTransaction, + tx: C::SignedTransaction, tip_step: C::Balance, tip_limit: C::Balance, target_priority: TransactionPriority, -) -> Result<(bool, S::SignedTransaction), SubstrateError> { +) -> Result<(bool, C::SignedTransaction), SubstrateError> { let stx = format!("{tx:?}"); let mut current_priority = client.validate_transaction(at_block.1, tx.clone()).await??.priority; - let mut unsigned_tx = S::parse_transaction(tx).ok_or_else(|| { + let mut unsigned_tx = C::parse_transaction(tx).ok_or_else(|| { SubstrateError::Custom(format!("Failed to parse {} transaction {stx}", C::NAME,)) })?; let old_tip = unsigned_tx.tip; @@ -425,7 +423,7 @@ async fn update_transaction_tip>( current_priority = client .validate_transaction( at_block.1, - S::sign_transaction( + C::sign_transaction( SignParam { spec_version, transaction_version, @@ -449,7 +447,7 @@ async fn update_transaction_tip>( Ok(( old_tip != unsigned_tx.tip, - S::sign_transaction( + C::sign_transaction( SignParam { spec_version, transaction_version, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 79d1efee63879..2b314b921fa90 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -32,7 +32,7 @@ use crate::{ use async_trait::async_trait; use codec::{Decode, Encode}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainBase, SignParam, TransactionSignScheme, + AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, SignParam, UnsignedTransaction, }; use sp_core::{Bytes, Pair}; @@ -96,12 +96,12 @@ pub struct SendMessage { trait MessageSender: MessagesCliBridge where Self::Source: ChainBase - + TransactionSignScheme + + ChainWithTransactions + CliChain> + CliEncodeMessage, ::Balance: Display + From + Into, ::Call: Sync, - ::SignedTransaction: Sync, + ::SignedTransaction: Sync, AccountIdOf: From< as Pair>::Public>, AccountId32: From< as Pair>::Public>, { diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 8adb108c85bef..77f09a89f153a 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -21,7 +21,7 @@ use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, + ChainWithTransactions, Error as SubstrateError, IndexOf, SignParam, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -97,14 +97,13 @@ impl ChainWithBalances for Millau { } } -impl TransactionSignScheme for Millau { - type Chain = Millau; +impl ChainWithTransactions for Millau { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = millau_runtime::UncheckedExtrinsic; fn sign_transaction( param: SignParam, - unsigned: UnsignedTransaction, + unsigned: UnsignedTransaction, ) -> Result { let raw_payload = SignedPayload::from_raw( unsigned.call.clone(), @@ -156,18 +155,14 @@ impl TransactionSignScheme for Millau { .unwrap_or(false) } - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some( UnsignedTransaction::new( tx.function.into(), - Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), ) - .tip( - Compact::>::decode(&mut &extra.7.encode()[..]) - .ok()? - .into(), - ), + .tip(Compact::>::decode(&mut &extra.7.encode()[..]).ok()?.into()), ) } } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 7e1415720ba66..fe7c2c816162f 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, Error as SubstrateError, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, ChainWithTransactions, + Error as SubstrateError, SignParam, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -96,14 +96,13 @@ impl ChainWithMessages for RialtoParachain { type WeightInfo = (); } -impl TransactionSignScheme for RialtoParachain { - type Chain = RialtoParachain; +impl ChainWithTransactions for RialtoParachain { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic; fn sign_transaction( param: SignParam, - unsigned: UnsignedTransaction, + unsigned: UnsignedTransaction, ) -> Result { let raw_payload = SignedPayload::from_raw( unsigned.call, @@ -157,7 +156,7 @@ impl TransactionSignScheme for RialtoParachain { .unwrap_or(false) } - fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { + fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { unimplemented!("TODO") } } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index fbb1f85ec1b33..45166559b365a 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -21,7 +21,7 @@ use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - Error as SubstrateError, IndexOf, RelayChain, SignParam, TransactionSignScheme, + ChainWithTransactions, Error as SubstrateError, IndexOf, RelayChain, SignParam, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -104,14 +104,13 @@ impl ChainWithBalances for Rialto { } } -impl TransactionSignScheme for Rialto { - type Chain = Rialto; +impl ChainWithTransactions for Rialto { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_runtime::UncheckedExtrinsic; fn sign_transaction( param: SignParam, - unsigned: UnsignedTransaction, + unsigned: UnsignedTransaction, ) -> Result { let raw_payload = SignedPayload::from_raw( unsigned.call.clone(), @@ -159,18 +158,14 @@ impl TransactionSignScheme for Rialto { .unwrap_or(false) } - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some( UnsignedTransaction::new( tx.function.into(), - Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), ) - .tip( - Compact::>::decode(&mut &extra.7.encode()[..]) - .ok()? - .into(), - ), + .tip(Compact::>::decode(&mut &extra.7.encode()[..]).ok()?.into()), ) } } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 97e3b0f0fc21e..5763d4a61357b 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -185,12 +185,10 @@ impl UnsignedTransaction { } /// Account key pair used by transactions signing scheme. -pub type AccountKeyPairOf = ::AccountKeyPair; +pub type AccountKeyPairOf = ::AccountKeyPair; /// Substrate-based chain transactions signing scheme. -pub trait TransactionSignScheme: 'static { - /// Chain that this scheme is to be used. - type Chain: Chain; +pub trait ChainWithTransactions: Chain { /// Type of key pairs used to sign transactions. type AccountKeyPair: Pair; /// Signed transaction. @@ -199,7 +197,7 @@ pub trait TransactionSignScheme: 'static { /// Create transaction for given runtime call, signed by given account. fn sign_transaction( param: SignParam, - unsigned: UnsignedTransaction, + unsigned: UnsignedTransaction, ) -> Result where Self: Sized; @@ -213,19 +211,19 @@ pub trait TransactionSignScheme: 'static { /// Parse signed transaction into its unsigned part. /// /// Returns `None` if signed transaction has unsupported format. - fn parse_transaction(tx: Self::SignedTransaction) -> Option>; + fn parse_transaction(tx: Self::SignedTransaction) -> Option>; } /// Sign transaction parameters -pub struct SignParam { +pub struct SignParam { /// Version of the runtime specification. pub spec_version: u32, /// Transaction version pub transaction_version: u32, /// Hash of the genesis block. - pub genesis_hash: ::Hash, + pub genesis_hash: HashOf, /// Signer account - pub signer: T::AccountKeyPair, + pub signer: AccountKeyPairOf, } impl BlockWithJustification for SignedBlock { diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index a713b3ba12128..4f783291ee323 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -17,14 +17,14 @@ //! Substrate node client. use crate::{ - chain::{Chain, ChainWithBalances}, + chain::{Chain, ChainWithBalances, ChainWithTransactions}, rpc::{ SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient, SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, SubstrateTransactionPaymentClient, }, transaction_stall_timeout, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, - TransactionSignScheme, TransactionTracker, UnsignedTransaction, + TransactionTracker, UnsignedTransaction, }; use async_std::sync::{Arc, Mutex}; @@ -421,14 +421,17 @@ impl Client { /// if all client instances are clones of the same initial `Client`. /// /// Note: The given transaction needs to be SCALE encoded beforehand. - pub async fn submit_signed_extrinsic + 'static>( + pub async fn submit_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - signing_data: SignParam, + signing_data: SignParam, prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, - ) -> Result { + ) -> Result + where + C: ChainWithTransactions, + { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; let best_header = self.best_header().await?; @@ -442,7 +445,7 @@ impl Client { self.jsonrpsee_execute(move |client| async move { let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode(); + let signed_extrinsic = C::sign_transaction(signing_data, extrinsic)?.encode(); let tx_hash = SubstrateAuthorClient::::submit_extrinsic(&*client, Bytes(signed_extrinsic)) .await @@ -458,16 +461,17 @@ impl Client { /// Does exactly the same as `submit_signed_extrinsic`, but keeps watching for extrinsic status /// after submission. - pub async fn submit_and_watch_signed_extrinsic< - S: TransactionSignScheme + 'static, - >( + pub async fn submit_and_watch_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - signing_data: SignParam, + signing_data: SignParam, prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, - ) -> Result> { + ) -> Result> + where + C: ChainWithTransactions, + { let self_clone = self.clone(); let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -482,7 +486,7 @@ impl Client { C::AVERAGE_BLOCK_INTERVAL, STALL_TIMEOUT, ); - let signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode(); + let signed_extrinsic = C::sign_transaction(signing_data, extrinsic)?.encode(); let tx_hash = C::Hasher::hash(&signed_extrinsic); let subscription = SubstrateAuthorClient::::submit_and_watch_extrinsic( &*client, diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 9e6c73d83caf9..99ff0fbe39447 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -34,7 +34,7 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, RelayChain, SignParam, TransactionSignScheme, + ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, RelayChain, SignParam, TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, }, client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs index ed13f4e5b35ff..3bd9a5a6a1985 100644 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ b/relays/lib-substrate-relay/src/conversion_rate_update.rs @@ -19,8 +19,8 @@ use crate::{messages_lane::SubstrateMessageLane, TransactionParams}; use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam, - TransactionEra, TransactionSignScheme, UnsignedTransaction, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, ChainWithTransactions, + Client, SignParam, TransactionEra, UnsignedTransaction, }; use relay_utils::metrics::F64SharedRef; use sp_core::Pair; @@ -119,17 +119,17 @@ macro_rules! generate_mocked_update_conversion_rate_call_builder { /// /// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens * /// Rate`. -pub fn run_conversion_rate_update_loop( +pub fn run_conversion_rate_update_loop( client: Client, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, left_to_right_stored_conversion_rate: F64SharedRef, left_to_base_conversion_rate: F64SharedRef, right_to_base_conversion_rate: F64SharedRef, max_difference_ratio: f64, ) where Lane: SubstrateMessageLane, - Sign: TransactionSignScheme, - AccountIdOf: From< as Pair>::Public>, + Lane::SourceChain: ChainWithTransactions, + AccountIdOf: From< as Pair>::Public>, { let stall_timeout = transaction_stall_timeout( transaction_params.mortality, @@ -169,7 +169,7 @@ pub fn run_conversion_rate_update_loop( new_conversion_rate, ); - let result = update_target_to_source_conversion_rate::( + let result = update_target_to_source_conversion_rate::( client.clone(), transaction_params.clone(), new_conversion_rate, @@ -253,15 +253,15 @@ async fn maybe_select_new_conversion_rate( } /// Update Target -> Source tokens conversion rate, stored in the Source runtime storage. -pub async fn update_target_to_source_conversion_rate( +pub async fn update_target_to_source_conversion_rate( client: Client, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, updated_rate: f64, ) -> anyhow::Result<()> where Lane: SubstrateMessageLane, - Sign: TransactionSignScheme, - AccountIdOf: From< as Pair>::Public>, + Lane::SourceChain: ChainWithTransactions, + AccountIdOf: From< as Pair>::Public>, { let genesis_hash = *client.genesis_hash(); let signer_id = transaction_params.signer.public().into(); @@ -273,7 +273,7 @@ where client .submit_signed_extrinsic( signer_id, - SignParam:: { + SignParam:: { spec_version, transaction_version, genesis_hash, diff --git a/relays/lib-substrate-relay/src/finality/guards.rs b/relays/lib-substrate-relay/src/finality/guards.rs index a3e69afe1b1d9..1451b549cc0da 100644 --- a/relays/lib-substrate-relay/src/finality/guards.rs +++ b/relays/lib-substrate-relay/src/finality/guards.rs @@ -19,19 +19,19 @@ use crate::TransactionParams; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, ChainWithBalances, TransactionSignScheme, + AccountIdOf, AccountKeyPairOf, ChainWithBalances, ChainWithTransactions, }; use sp_core::Pair; /// Start finality relay guards. -pub async fn start>( +pub async fn start( target_client: &relay_substrate_client::Client, - transaction_params: &TransactionParams, + transaction_params: &TransactionParams>, enable_version_guard: bool, maximal_balance_decrease_per_day: C::Balance, ) -> relay_substrate_client::Result<()> where - AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, { if enable_version_guard { relay_substrate_client::guard::abort_on_spec_version_change( diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index e25743180ee9e..6ff185800cced 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -24,7 +24,7 @@ use crate::{error::Error, finality::engine::Engine}; use relay_substrate_client::{ - Chain, Client, Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, + Chain, ChainWithTransactions, Client, Error as SubstrateError, SignParam, UnsignedTransaction, }; use sp_runtime::traits::Header as HeaderT; @@ -32,7 +32,7 @@ use sp_runtime::traits::Header as HeaderT; pub async fn initialize< E: Engine, SourceChain: Chain, - TargetChain: Chain + TransactionSignScheme, + TargetChain: ChainWithTransactions, F, >( source_client: Client, @@ -80,7 +80,7 @@ pub async fn initialize< async fn do_initialize< E: Engine, SourceChain: Chain, - TargetChain: Chain + TransactionSignScheme, + TargetChain: ChainWithTransactions, F, >( source_client: Client, diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index aefcd21722525..5d7b52cd1dec7 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -31,8 +31,8 @@ use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, - HashOf, HeaderOf, SyncHeader, TransactionSignScheme, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, + ChainWithTransactions, Client, HashOf, HeaderOf, SyncHeader, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; @@ -56,19 +56,17 @@ pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. type SourceChain: Chain; /// Headers of the `SourceChain` are submitted to this chain. - type TargetChain: Chain; + type TargetChain: ChainWithTransactions; /// Finality engine. type FinalityEngine: Engine; /// How submit finality proof call is built? type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder; - /// Scheme used to sign target chain transactions. - type TransactionSignScheme: TransactionSignScheme; /// Add relay guards if required. async fn start_relay_guards( _target_client: &Client, - _transaction_params: &TransactionParams>, + _transaction_params: &TransactionParams>, _enable_version_guard: bool, ) -> relay_substrate_client::Result<()> { Ok(()) @@ -169,12 +167,11 @@ pub async fn run( source_client: Client, target_client: Client, only_mandatory_headers: bool, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, metrics_params: MetricsParams, ) -> anyhow::Result<()> where - AccountIdOf: From< as Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, { log::info!( target: "bridge", diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 132c332534382..09d9ad15f5436 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -28,7 +28,7 @@ use async_trait::async_trait; use finality_relay::TargetClient; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, - SyncHeader, TransactionEra, TransactionSignScheme, TransactionTracker, UnsignedTransaction, + SyncHeader, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -36,14 +36,14 @@ use sp_core::Pair; /// Substrate client as Substrate finality target. pub struct SubstrateFinalityTarget { client: Client, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, } impl SubstrateFinalityTarget

{ /// Create new Substrate headers target. pub fn new( client: Client, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, ) -> Self { SubstrateFinalityTarget { client, transaction_params } } @@ -86,8 +86,7 @@ impl RelayClient for SubstrateFinalityTarget

TargetClient> for SubstrateFinalityTarget

where - AccountIdOf: From< as Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, { type TransactionTracker = TransactionTracker>; @@ -120,7 +119,7 @@ where self.client .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), - SignParam:: { + SignParam:: { spec_version, transaction_version, genesis_hash, diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 72da8f20220e8..09d02f7448e4d 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -37,7 +37,7 @@ use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, - ChainWithMessages, Client, HashOf, TransactionSignScheme, + ChainWithMessages, ChainWithTransactions, Client, HashOf, }; use relay_utils::{metrics::MetricsParams, STALL_TIMEOUT}; use sp_core::Pair; @@ -77,14 +77,9 @@ pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; /// Messages of this chain are relayed to the `TargetChain`. - type SourceChain: ChainWithMessages; + type SourceChain: ChainWithMessages + ChainWithTransactions; /// Messages from the `SourceChain` are dispatched on this chain. - type TargetChain: ChainWithMessages; - - /// Scheme used to sign source chain transactions. - type SourceTransactionSignScheme: TransactionSignScheme; - /// Scheme used to sign target chain transactions. - type TargetTransactionSignScheme: TransactionSignScheme; + type TargetChain: ChainWithMessages + ChainWithTransactions; /// How receive messages proof call is built? type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder; @@ -128,13 +123,11 @@ pub struct MessagesRelayParams { /// Messages source client. pub source_client: Client, /// Source transaction params. - pub source_transaction_params: - TransactionParams>, + pub source_transaction_params: TransactionParams>, /// Messages target client. pub target_client: Client, /// Target transaction params. - pub target_transaction_params: - TransactionParams>, + pub target_transaction_params: TransactionParams>, /// Optional on-demand source to target headers relay. pub source_to_target_headers_relay: Option>>>, @@ -154,13 +147,9 @@ pub struct MessagesRelayParams { /// Run Substrate-to-Substrate messages sync loop. pub async fn run(params: MessagesRelayParams

) -> anyhow::Result<()> where - AccountIdOf: - From< as Pair>::Public>, - AccountIdOf: - From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, - P::SourceTransactionSignScheme: TransactionSignScheme, - P::TargetTransactionSignScheme: TransactionSignScheme, { let source_client = params.source_client; let target_client = params.target_client; diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index c4e0f15f859ab..632c36a51bbca 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -49,9 +49,9 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionSignScheme, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, + ChainWithTransactions, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, + TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -69,7 +69,7 @@ pub struct SubstrateMessagesSource { source_client: Client, target_client: Client, lane_id: LaneId, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option>>>, } @@ -79,7 +79,7 @@ impl SubstrateMessagesSource

{ source_client: Client, target_client: Client, lane_id: LaneId, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, target_to_source_headers_relay: Option< Arc>>, >, @@ -140,9 +140,7 @@ impl RelayClient for SubstrateMessagesSource

{ #[async_trait] impl SourceClient> for SubstrateMessagesSource

where - AccountIdOf: - From< as Pair>::Public>, - P::SourceTransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, { type TransactionTracker = TransactionTracker>; @@ -348,7 +346,7 @@ where self.source_client .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), - SignParam:: { + SignParam:: { spec_version, transaction_version, genesis_hash, @@ -381,8 +379,8 @@ where Err(_) => return BalanceOf::::max_value(), }; async { - let dummy_tx = P::SourceTransactionSignScheme::sign_transaction( - SignParam:: { + let dummy_tx = P::SourceChain::sign_transaction( + SignParam:: { spec_version: runtime_version.spec_version, transaction_version: runtime_version.transaction_version, genesis_hash: *self.source_client.genesis_hash(), @@ -429,15 +427,12 @@ where /// Make messages delivery proof transaction from given proof. fn make_messages_delivery_proof_transaction( - source_transaction_params: &TransactionParams>, + source_transaction_params: &TransactionParams>, source_best_block_id: HeaderIdOf, transaction_nonce: IndexOf, proof: SubstrateMessagesDeliveryProof, trace_call: bool, -) -> Result, SubstrateError> -where - P::SourceTransactionSignScheme: TransactionSignScheme, -{ +) -> Result, SubstrateError> { let call = P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( proof, trace_call, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 46c3b6141cc62..955f35942cf2f 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -43,9 +43,9 @@ use messages_relay::{ }; use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionSignScheme, TransactionTracker, UnsignedTransaction, WeightToFeeOf, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, + ChainWithTransactions, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, + TransactionEra, TransactionTracker, UnsignedTransaction, WeightToFeeOf, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -62,7 +62,7 @@ pub struct SubstrateMessagesTarget { source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>>>, } @@ -74,7 +74,7 @@ impl SubstrateMessagesTarget

{ source_client: Client, lane_id: LaneId, relayer_id_at_source: AccountIdOf, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option< Arc>>, @@ -140,9 +140,7 @@ impl RelayClient for SubstrateMessagesTarget

{ #[async_trait] impl TargetClient> for SubstrateMessagesTarget

where - AccountIdOf: - From< as Pair>::Public>, - P::TargetTransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, { type TransactionTracker = TransactionTracker>; @@ -258,7 +256,7 @@ where .target_client .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), - SignParam:: { + SignParam:: { spec_version, transaction_version, genesis_hash, @@ -305,7 +303,7 @@ where let (spec_version, transaction_version) = self.target_client.simple_runtime_version().await?; // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. - let delivery_tx = P::TargetTransactionSignScheme::sign_transaction( + let delivery_tx = P::TargetChain::sign_transaction( SignParam { spec_version, transaction_version, @@ -352,7 +350,7 @@ where let (spec_version, transaction_version) = self.target_client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); - let dummy_tx = P::TargetTransactionSignScheme::sign_transaction( + let dummy_tx = P::TargetChain::sign_transaction( SignParam { spec_version, transaction_version, @@ -425,17 +423,14 @@ where /// Make messages delivery transaction from given proof. fn make_messages_delivery_transaction( - target_transaction_params: &TransactionParams>, + target_transaction_params: &TransactionParams>, target_best_block_id: HeaderIdOf, transaction_nonce: IndexOf, relayer_id_at_source: AccountIdOf, nonces: RangeInclusive, proof: SubstrateMessagesProof, trace_call: bool, -) -> Result, SubstrateError> -where - P::TargetTransactionSignScheme: TransactionSignScheme, -{ +) -> Result, SubstrateError> { let messages_count = nonces.end() - nonces.start() + 1; let dispatch_weight = proof.0; let call = P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 3a54e6bb00cba..c0603cda8cdc1 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -24,9 +24,7 @@ use num_traits::{One, Zero}; use sp_runtime::traits::Header; use finality_relay::{FinalitySyncParams, TargetClient as FinalityTargetClient}; -use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, TransactionSignScheme, -}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client}; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, STALL_TIMEOUT, @@ -61,13 +59,12 @@ impl OnDemandHeadersRelay { pub fn new>( source_client: Client, target_client: Client, - target_transaction_params: TransactionParams>, + target_transaction_params: TransactionParams>, only_mandatory_headers: bool, ) -> Self where AccountIdOf: - From< as sp_core::Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + From< as sp_core::Pair>::Public>, { let required_header_number = Arc::new(Mutex::new(Zero::zero())); let this = OnDemandHeadersRelay { @@ -113,13 +110,11 @@ impl OnDemandRelay> async fn background_task( source_client: Client, target_client: Client, - target_transaction_params: TransactionParams>, + target_transaction_params: TransactionParams>, only_mandatory_headers: bool, required_header_number: RequiredHeaderNumberRef, ) where - AccountIdOf: - From< as sp_core::Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as sp_core::Pair>::Public>, { let relay_task_name = on_demand_headers_relay_name::(); let target_transactions_mortality = target_transaction_params.mortality; @@ -389,9 +384,7 @@ async fn best_finalized_source_header_at_target Result, as RelayClient>::Error> where - AccountIdOf: - From< as sp_core::Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as sp_core::Pair>::Public>, { finality_target .best_finalized_source_block_id() diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 577312e16c109..35ef8244ae630 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -39,7 +39,6 @@ use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumbe use parachains_relay::parachains_loop::{AvailableHeader, ParachainSyncParams, TargetClient}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - TransactionSignScheme, }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, HeaderId, @@ -68,7 +67,7 @@ impl OnDemandParachainsRelay { pub fn new>( source_relay_client: Client, target_client: Client, - target_transaction_params: TransactionParams>, + target_transaction_params: TransactionParams>, on_demand_source_relay_to_target_headers: Arc< dyn OnDemandRelay>, >, @@ -78,8 +77,7 @@ impl OnDemandParachainsRelay { P::SourceRelayChain: Chain, AccountIdOf: - From< as sp_core::Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + From< as sp_core::Pair>::Public>, { let (required_header_number_sender, required_header_number_receiver) = unbounded(); let this = OnDemandParachainsRelay { @@ -125,7 +123,7 @@ where async fn background_task( source_relay_client: Client, target_client: Client, - target_transaction_params: TransactionParams>, + target_transaction_params: TransactionParams>, on_demand_source_relay_to_target_headers: Arc< dyn OnDemandRelay>, >, @@ -134,9 +132,7 @@ async fn background_task( P::SourceParachain: Chain, P::SourceRelayChain: Chain, - AccountIdOf: - From< as sp_core::Pair>::Public>, - P::TransactionSignScheme: TransactionSignScheme, + AccountIdOf: From< as sp_core::Pair>::Public>, { let relay_task_name = on_demand_parachains_relay_name::(); let target_transactions_mortality = target_transaction_params.mortality; diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/relays/lib-substrate-relay/src/parachains/mod.rs index f201476aa1635..1d744a30e4ea5 100644 --- a/relays/lib-substrate-relay/src/parachains/mod.rs +++ b/relays/lib-substrate-relay/src/parachains/mod.rs @@ -24,7 +24,7 @@ use pallet_bridge_parachains::{ RelayBlockHasher, RelayBlockNumber, }; use parachains_relay::ParachainsPipeline; -use relay_substrate_client::{CallOf, Chain, HeaderIdOf, RelayChain, TransactionSignScheme}; +use relay_substrate_client::{CallOf, Chain, ChainWithTransactions, HeaderIdOf, RelayChain}; use std::{fmt::Debug, marker::PhantomData}; pub mod source; @@ -41,12 +41,10 @@ pub trait SubstrateParachainsPipeline: 'static + Clone + Debug + Send + Sync { /// Relay chain that is storing headers of `Self::SourceParachain`. type SourceRelayChain: RelayChain; /// Target chain where `Self::SourceParachain` headers are submitted. - type TargetChain: Chain; + type TargetChain: ChainWithTransactions; /// How submit parachains heads call is built? type SubmitParachainHeadsCallBuilder: SubmitParachainHeadsCallBuilder; - /// Scheme used to sign target chain transactions. - type TransactionSignScheme: TransactionSignScheme; /// Id of the `Self::SourceParachain`, used for registration in `Self::SourceRelayChain`. const SOURCE_PARACHAIN_PARA_ID: u32; diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 8d0d361984f3e..c4022f12f5edf 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -33,8 +33,8 @@ use parachains_relay::{ }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, HeaderOf, RelayChain, SignParam, TransactionEra, TransactionSignScheme, - TransactionTracker, UnsignedTransaction, + HeaderIdOf, HeaderOf, RelayChain, SignParam, TransactionEra, TransactionTracker, + UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -43,14 +43,14 @@ use sp_runtime::traits::Header as HeaderT; /// Substrate client as parachain heads source. pub struct ParachainsTarget { client: Client, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, } impl ParachainsTarget

{ /// Creates new parachains target client. pub fn new( client: Client, - transaction_params: TransactionParams>, + transaction_params: TransactionParams>, ) -> Self { ParachainsTarget { client, transaction_params } } @@ -83,8 +83,7 @@ impl RelayClient for ParachainsTarget

{ impl

TargetClient> for ParachainsTarget

where P: SubstrateParachainsPipeline, - P::TransactionSignScheme: TransactionSignScheme, - AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, { type TransactionTracker = TransactionTracker>; @@ -186,7 +185,7 @@ where self.client .submit_and_watch_signed_extrinsic( self.transaction_params.signer.public().into(), - SignParam:: { + SignParam:: { spec_version, transaction_version, genesis_hash, From 895624c86b8e64a8f05d55ffa8476228e00e1433 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 8 Nov 2022 09:40:04 +0100 Subject: [PATCH 0802/1210] Bump xcm v3 + substrate * Bumping substrate/polkadot/cumulus * Update Cargo.lock * Fixes * Fixes for mmr * Bump clap * Fix for millau - added CompatibilityMode * Fixes for rialto-parachain * Align everywhere branch='master' and just use overrides from main Cargo.toml --- bin/millau/node/Cargo.toml | 2 +- bin/millau/node/src/service.rs | 4 ++- bin/millau/runtime/Cargo.toml | 9 +++-- bin/millau/runtime/src/lib.rs | 16 ++++----- bin/rialto-parachain/node/Cargo.toml | 28 ++++++++------- bin/rialto-parachain/node/src/service.rs | 36 +++++++++++++++---- bin/rialto-parachain/runtime/Cargo.toml | 26 +++++++------- bin/rialto/node/Cargo.toml | 11 +++--- bin/rialto/runtime/Cargo.toml | 15 ++++---- bin/rialto/runtime/src/lib.rs | 16 ++++----- bin/rialto/runtime/src/parachains.rs | 6 ++++ bin/runtime-common/Cargo.toml | 9 +++-- primitives/runtime/src/storage_proof.rs | 7 ++-- relays/bin-substrate/Cargo.toml | 11 +++--- .../src/metrics/storage_proof_overhead.rs | 2 +- .../src/messages_source.rs | 2 +- .../src/messages_target.rs | 2 +- .../src/parachains/source.rs | 2 +- 18 files changed, 115 insertions(+), 89 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index a7a2f86ea33cc..a8d03c6f1a4e9 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "3.1", features = ["derive"] } +clap = { version = "4.0.9", features = ["derive"] } jsonrpsee = { version = "0.15.1", features = ["server"] } serde_json = "1.0.79" diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 72a1036c641ba..e23e1fa56ca4f 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -19,7 +19,7 @@ use jsonrpsee::RpcModule; use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::BlockBackend; -use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; +use sc_consensus_aura::{CompatibilityMode, ImportQueueParams, SlotProportion, StartAuraParams}; pub use sc_executor::NativeElseWasmExecutor; use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; @@ -159,6 +159,7 @@ pub fn new_partial( registry: config.prometheus_registry(), check_for_equivocation: Default::default(), telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: CompatibilityMode::None, })?; Ok(sc_service::PartialComponents { @@ -374,6 +375,7 @@ pub fn new_full(mut config: Configuration) -> Result block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: CompatibilityMode::None, }, )?; diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index dfab9588d5d08..b297dedfa5375 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -64,11 +64,10 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot Dependencies - -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 1f60e91f59f5c..09f17cf6cf534 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -785,11 +785,11 @@ impl_runtime_apis! { } } - impl sp_mmr_primitives::MmrApi for Runtime { - fn generate_proof(leaf_index: u64) + impl sp_mmr_primitives::MmrApi for Runtime { + fn generate_proof(block_number: BlockNumber) -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> { - Mmr::generate_batch_proof(vec![leaf_index]) + Mmr::generate_batch_proof(vec![block_number]) .and_then(|(leaves, proof)| Ok(( mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), mmr::BatchProof::into_single_leaf_proof(proof)? @@ -823,18 +823,18 @@ impl_runtime_apis! { Ok(Mmr::mmr_root()) } - fn generate_batch_proof(leaf_indices: Vec) + fn generate_batch_proof(block_numbers: Vec) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_batch_proof(leaf_indices) + Mmr::generate_batch_proof(block_numbers) .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) } fn generate_historical_batch_proof( - leaf_indices: Vec, - leaves_count: mmr::LeafIndex, + block_numbers: Vec, + best_known_block_number: BlockNumber ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_historical_batch_proof(leaf_indices, leaves_count).map( + Mmr::generate_historical_batch_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( leaves diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 1b37cb3a3fee7..03d1a28c6a495 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "3.1", features = ["derive"] } +clap = { version = "4.0.9", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } @@ -48,6 +48,7 @@ sc-network = { git = "https://github.com/paritytech/substrate", branch = "master sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ['wasmtime'] } +sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -66,17 +67,18 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } # Cumulus dependencies -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "master" } # Polkadot dependencies -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 8d722b3caa62a..7dc25f6550d00 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -30,14 +30,16 @@ use rialto_parachain_runtime::RuntimeApi; // Cumulus Imports use cumulus_client_cli::CollatorOptions; use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::ParachainConsensus; +use cumulus_client_consensus_common::{ParachainBlockImport, ParachainConsensus}; use cumulus_client_network::BlockAnnounceValidator; use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain; -use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; +use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult}; +use cumulus_relay_chain_minimal_node::build_minimal_relay_chain_node; +use polkadot_service::CollatorPair; // Substrate Imports use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; @@ -187,6 +189,27 @@ where Ok(params) } +async fn build_relay_chain_interface( + polkadot_config: Configuration, + parachain_config: &Configuration, + telemetry_worker_handle: Option, + task_manager: &mut TaskManager, + collator_options: CollatorOptions, + hwbench: Option, +) -> RelayChainResult<(Arc<(dyn RelayChainInterface + 'static)>, Option)> { + match collator_options.relay_chain_rpc_url { + Some(relay_chain_url) => + build_minimal_relay_chain_node(polkadot_config, task_manager, relay_chain_url).await, + None => build_inprocess_relay_chain( + polkadot_config, + parachain_config, + telemetry_worker_handle, + task_manager, + hwbench, + ), + } +} + /// Start a node with the given parachain `Configuration` and relay chain `Configuration`. /// /// This is the actual implementation that is abstract over the executor and the runtime api. @@ -267,13 +290,15 @@ where let (mut telemetry, telemetry_worker_handle) = params.other; let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = build_inprocess_relay_chain( + let (relay_chain_interface, collator_key) = build_relay_chain_interface( polkadot_config, ¶chain_config, telemetry_worker_handle, &mut task_manager, + collator_options, None, ) + .await .map_err(|e| match e { RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, s => s.to_string().into(), @@ -367,7 +392,6 @@ where relay_chain_interface, relay_chain_slot_duration, import_queue, - collator_options, }; start_full_node(params)?; @@ -402,7 +426,7 @@ pub fn parachain_build_import_queue( _, _, >(cumulus_client_consensus_aura::ImportQueueParams { - block_import: client.clone(), + block_import: ParachainBlockImport::new(client.clone()), client, create_inherent_data_providers: move |_, _| async move { let time = sp_timestamp::InherentDataProvider::from_system_time(); @@ -497,7 +521,7 @@ pub async fn start_node( Ok((slot, time, parachain_inherent)) } }, - block_import: client.clone(), + block_import: ParachainBlockImport::new(client.clone()), para_client: client, backoff_authoring_blocks: Option::<()>::None, sync_oracle, diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index de3067162652d..467fbd3699a3d 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -60,21 +60,21 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Cumulus Dependencies -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "gav-xcm-v3", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } # Polkadot Dependencies -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [features] default = ['std'] diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 688279afc7327..82b073896d987 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "3.1", features = ["derive"] } +clap = { version = "4.0.9", features = ["derive"] } serde_json = "1.0.79" # Bridge dependencies @@ -33,11 +33,10 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies - -polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false, features = [ "full-node", "polkadot-native" ] } +polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index fe2ab903b0ac7..8b043d37886ac 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -60,14 +60,13 @@ sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot (parachain) Dependencies - -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index ff7ad88725c23..53b0f821f3e48 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -637,11 +637,11 @@ impl_runtime_apis! { } } - impl sp_mmr_primitives::MmrApi for Runtime { - fn generate_proof(leaf_index: u64) + impl sp_mmr_primitives::MmrApi for Runtime { + fn generate_proof(block_number: BlockNumber) -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> { - Mmr::generate_batch_proof(vec![leaf_index]) + Mmr::generate_batch_proof(vec![block_number]) .and_then(|(leaves, proof)| Ok(( mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), mmr::BatchProof::into_single_leaf_proof(proof)? @@ -679,18 +679,18 @@ impl_runtime_apis! { Ok(Mmr::mmr_root()) } - fn generate_batch_proof(leaf_indices: Vec) + fn generate_batch_proof(block_numbers: Vec) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_batch_proof(leaf_indices) + Mmr::generate_batch_proof(block_numbers) .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) } fn generate_historical_batch_proof( - leaf_indices: Vec, - leaves_count: mmr::LeafIndex, + block_numbers: Vec, + best_known_block_number: BlockNumber ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_historical_batch_proof(leaf_indices, leaves_count).map( + Mmr::generate_historical_batch_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( leaves diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 583358e50368d..960931a0b3cee 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -186,6 +186,12 @@ impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights { fn swap() -> Weight { Weight::from_ref_time(0) } + fn schedule_code_upgrade(_: u32) -> Weight { + Weight::from_ref_time(0) + } + fn set_current_head(_: u32) -> Weight { + Weight::from_ref_time(0) + } } impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights { diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 3f717b05c6e6d..2fb64a5b73325 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -36,11 +36,10 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot dependencies - -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] millau-runtime = { path = "../millau/runtime" } diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 277456709f97c..e1465d2fa1657 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -118,11 +118,8 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { state_version, )); let root = backend.storage_root(std::iter::empty(), state_version).0; - let proof = StorageProof::new( - prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key4"[..], &b"key22"[..]]) - .unwrap() - .iter_nodes(), - ); + let proof = + prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key4"[..], &b"key22"[..]]).unwrap(); (root, proof) } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index ab10efc63ca11..a3b5ef9213ca7 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -51,12 +51,11 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies - -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3" } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "gav-xcm-v3", default-features = false } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs index 42793fe7c5468..6e0b74020b70b 100644 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ b/relays/client-substrate/src/metrics/storage_proof_overhead.rs @@ -62,7 +62,7 @@ impl StorageProofOverheadMetric { .client .prove_storage(vec![StorageKey(CODE.to_vec())], best_header_hash) .await?; - let storage_proof_size: usize = storage_proof.clone().iter_nodes().map(|n| n.len()).sum(); + let storage_proof_size: usize = storage_proof.iter_nodes().map(|n| n.len()).sum(); let storage_value_reader = bp_runtime::StorageProofChecker::::new( *best_header.state_root(), diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 632c36a51bbca..c02db3fb48a63 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -322,7 +322,7 @@ where .source_client .prove_storage(storage_keys, id.1) .await? - .iter_nodes() + .into_iter_nodes() .collect(); let proof = FromBridgedChainMessagesProof { bridged_header_hash: id.1, diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 955f35942cf2f..ed4d040b5d869 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -230,7 +230,7 @@ where .target_client .prove_storage(vec![inbound_data_key], id.1) .await? - .iter_nodes() + .into_iter_nodes() .collect(); let proof = FromBridgedChainMessagesDeliveryProof { bridged_header_hash: id.1, diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index c23ac87947632..2cae7f1a2242a 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -159,7 +159,7 @@ where .client .prove_storage(vec![storage_key.clone()], at_block.1) .await? - .iter_nodes() + .into_iter_nodes() .collect(); // why we're reading parachain head here once again (it has already been read at the From 8525de49817bbfdf62915a61172f5daf102fa05b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 8 Nov 2022 17:43:29 +0300 Subject: [PATCH 0803/1210] Statemine primitives (#1625) * Statemine primitives * ref issue in TODO * fix TODO --- primitives/chain-kusama/src/lib.rs | 7 -- primitives/chain-polkadot/Cargo.toml | 2 - primitives/chain-polkadot/src/lib.rs | 7 -- primitives/chain-rococo/src/lib.rs | 7 -- primitives/chain-statemine/Cargo.toml | 24 ++++ primitives/chain-statemine/src/lib.rs | 38 ++++++ primitives/chain-westend/Cargo.toml | 6 - primitives/chain-westend/src/lib.rs | 29 ----- primitives/chain-wococo/src/lib.rs | 7 -- relays/bin-substrate/Cargo.toml | 2 + relays/bin-substrate/src/chains/millau.rs | 1 - relays/bin-substrate/src/chains/mod.rs | 1 + relays/bin-substrate/src/chains/rialto.rs | 1 - .../src/chains/rialto_parachain.rs | 1 - relays/bin-substrate/src/chains/statemine.rs | 34 ++++++ relays/bin-substrate/src/chains/westend.rs | 2 - relays/bin-substrate/src/cli/mod.rs | 5 - relays/client-statemine/Cargo.toml | 24 ++++ relays/client-statemine/src/lib.rs | 112 ++++++++++++++++++ relays/client-statemine/src/runtime.rs | 68 +++++++++++ relays/client-westend/src/lib.rs | 4 +- 21 files changed, 305 insertions(+), 77 deletions(-) create mode 100644 primitives/chain-statemine/Cargo.toml create mode 100644 primitives/chain-statemine/src/lib.rs create mode 100644 relays/bin-substrate/src/chains/statemine.rs create mode 100644 relays/client-statemine/Cargo.toml create mode 100644 relays/client-statemine/src/lib.rs create mode 100644 relays/client-statemine/src/runtime.rs diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 7837afe690e4a..27d5f125ee266 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -24,13 +24,6 @@ use bp_runtime::decl_bridge_finality_runtime_apis; /// Kusama Chain pub type Kusama = PolkadotLike; -/// The target length of a session (how often authorities change) on Kusama measured in of number of -/// blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; - /// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 8be9b25c77f5a..b26093a05706e 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -7,8 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.7" - # Bridge Dependencies bp-polkadot-core = { path = "../polkadot-core", default-features = false } diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index cfcbacb0d1a76..0cada4e49a9be 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -24,13 +24,6 @@ use bp_runtime::decl_bridge_finality_runtime_apis; /// Polkadot Chain pub type Polkadot = PolkadotLike; -/// The target length of a session (how often authorities change) on Polkadot measured in of number -/// of blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = 4 * time_units::HOURS; - /// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 39188066dca4b..dd5be65dd866b 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -24,13 +24,6 @@ use bp_runtime::decl_bridge_finality_runtime_apis; /// Rococo Chain pub type Rococo = PolkadotLike; -/// The target length of a session (how often authorities change) on Rococo measured in of number -/// of blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = time_units::HOURS; - /// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; diff --git a/primitives/chain-statemine/Cargo.toml b/primitives/chain-statemine/Cargo.toml new file mode 100644 index 0000000000000..18d186ba41ef5 --- /dev/null +++ b/primitives/chain-statemine/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "bp-statemine" +description = "Primitives of Statemine runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-polkadot-core = { path = "../polkadot-core", default-features = false } + +# Substrate Based Dependencies + +sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-polkadot-core/std", + "sp-version/std", +] diff --git a/primitives/chain-statemine/src/lib.rs b/primitives/chain-statemine/src/lib.rs new file mode 100644 index 0000000000000..613e4a4f4501a --- /dev/null +++ b/primitives/chain-statemine/src/lib.rs @@ -0,0 +1,38 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] +// RuntimeApi generated functions +#![allow(clippy::too_many_arguments)] + +pub use bp_polkadot_core::*; + +use sp_version::RuntimeVersion; + +/// Statemine Chain. +pub type Statemine = PolkadotLike; + +/// Known Statemine runtime version. +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: sp_version::create_runtime_str!("statemine"), + impl_name: sp_version::create_runtime_str!("statemine"), + authoring_version: 1, + spec_version: 9300, + impl_version: 0, + apis: sp_version::create_apis_vec![[]], + transaction_version: 8, + state_version: 1, +}; diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index e5f7bf89565b6..7d74362b09a1a 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -7,8 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge Dependencies @@ -18,15 +16,11 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ "bp-polkadot-core/std", "bp-runtime/std", - "codec/std", - "scale-info/std", "sp-api/std", - "sp-runtime/std", ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 8d5d8d9a924d1..9f4a98baedc37 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -18,34 +18,12 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use scale_info::TypeInfo; - pub use bp_polkadot_core::*; use bp_runtime::decl_bridge_finality_runtime_apis; /// Westend Chain pub type Westend = PolkadotLike; -/// Westend Runtime `Call` enum. -/// -/// We are not currently submitting any Westend transactions => it is empty. -#[derive(codec::Encode, codec::Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call {} - -impl sp_runtime::traits::Dispatchable for Call { - type RuntimeOrigin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch( - self, - _origin: Self::RuntimeOrigin, - ) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} - /// Name of the parachains pallet at the Westend runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; @@ -54,13 +32,6 @@ pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; /// Name of the With-Westend parachains bridge pallet instance that is deployed at bridged chains. pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains"; -/// The target length of a session (how often authorities change) on Westend measured in of number -/// of blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = 10 * time_units::MINUTES; - /// Maximal number of GRANDPA authorities at Westend. /// /// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration. diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 2a417479d3b2f..f3fe0196dc591 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -24,13 +24,6 @@ use bp_runtime::decl_bridge_finality_runtime_apis; /// Wococo Chain pub type Wococo = PolkadotLike; -/// The target length of a session (how often authorities change) on Wococo measured in of number -/// of blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = time_units::MINUTES; - /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a3b5ef9213ca7..90adaf7e6529c 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -26,6 +26,7 @@ bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-runtime = { path = "../../primitives/runtime" } +bp-statemine = { path = "../../primitives/chain-statemine" } bp-westend = { path = "../../primitives/chain-westend" } bridge-runtime-common = { path = "../../bin/runtime-common" } messages-relay = { path = "../messages" } @@ -36,6 +37,7 @@ parachains-relay = { path = "../parachains" } relay-millau-client = { path = "../client-millau" } relay-rialto-client = { path = "../client-rialto" } relay-rialto-parachain-client = { path = "../client-rialto-parachain" } +relay-statemine-client = { path = "../client-statemine" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 55c48bee3efa1..92fc43fbe36fe 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -93,7 +93,6 @@ impl CliChain for Millau { const RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; fn ss58_format() -> u16 { millau_runtime::SS58Prefix::get() as u16 diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 13aca0651ae52..5d7171691bffb 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -30,6 +30,7 @@ pub mod westend_parachains_to_millau; mod millau; mod rialto; mod rialto_parachain; +mod statemine; mod westend; #[cfg(test)] diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 6a322d889cb9b..43ec9dbd224e4 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -76,7 +76,6 @@ impl CliChain for Rialto { const RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; fn ss58_format() -> u16 { rialto_runtime::SS58Prefix::get() as u16 diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 08cc38d90d780..546cd04bdde15 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -79,7 +79,6 @@ impl CliChain for RialtoParachain { const RUNTIME_VERSION: Option = Some(rialto_parachain_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; fn ss58_format() -> u16 { rialto_parachain_runtime::SS58Prefix::get() as u16 diff --git a/relays/bin-substrate/src/chains/statemine.rs b/relays/bin-substrate/src/chains/statemine.rs new file mode 100644 index 0000000000000..0c0edd2f3e484 --- /dev/null +++ b/relays/bin-substrate/src/chains/statemine.rs @@ -0,0 +1,34 @@ +// 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 . + +//! Statemine chain specification for CLI. + +use crate::cli::CliChain; +use relay_statemine_client::Statemine; +use sp_version::RuntimeVersion; + +impl CliChain for Statemine { + const RUNTIME_VERSION: Option = Some(bp_statemine::VERSION); + + type KeyPair = sp_core::sr25519::Pair; + + fn ss58_format() -> u16 { + sp_core::crypto::Ss58AddressFormat::from( + sp_core::crypto::Ss58AddressFormatRegistry::KusamaAccount, + ) + .into() + } +} diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 8d43d6a5ab709..1627bc015d323 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -24,7 +24,6 @@ impl CliChain for Westend { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -38,7 +37,6 @@ impl CliChain for Westmint { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = Vec; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 2369bb60dda75..2f2f1f227b70b 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -172,11 +172,6 @@ pub trait CliChain: relay_substrate_client::Chain { /// In case of chains supporting multiple cryptos, pick one used by the CLI. type KeyPair: sp_core::crypto::Pair; - /// Bridge Message Payload type. - /// - /// TODO [#854] This should be removed in favor of target-specifc types. - type MessagePayload; - /// Numeric value of SS58 format. fn ss58_format() -> u16; } diff --git a/relays/client-statemine/Cargo.toml b/relays/client-statemine/Cargo.toml new file mode 100644 index 0000000000000..249f9fd6f4305 --- /dev/null +++ b/relays/client-statemine/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "relay-statemine-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } +scale-info = { version = "2.1.1", features = ["derive"] } + +# Bridge dependencies + +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-statemine = { path = "../../primitives/chain-statemine" } + +# Substrate Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-statemine/src/lib.rs b/relays/client-statemine/src/lib.rs new file mode 100644 index 0000000000000..a5f6fed79f434 --- /dev/null +++ b/relays/client-statemine/src/lib.rs @@ -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 . + +//! Types used to connect to the Statemine chain. + +use codec::Encode; +use frame_support::weights::Weight; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithTransactions, Error as SubstrateError, SignParam, + UnsignedTransaction, +}; +use sp_core::Pair; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +pub mod runtime; + +/// Statemine chain definition +#[derive(Debug, Clone, Copy)] +pub struct Statemine; + +impl ChainBase for Statemine { + type BlockNumber = bp_statemine::BlockNumber; + type Hash = bp_statemine::Hash; + type Hasher = bp_statemine::Hasher; + type Header = bp_statemine::Header; + + type AccountId = bp_statemine::AccountId; + type Balance = bp_statemine::Balance; + type Index = bp_statemine::Nonce; + type Signature = bp_statemine::Signature; + + fn max_extrinsic_size() -> u32 { + bp_statemine::Statemine::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_statemine::Statemine::max_extrinsic_weight() + } +} + +impl Chain for Statemine { + const NAME: &'static str = "Statemine"; + const TOKEN_ID: Option<&'static str> = Some("kusama"); + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_statemine::EXTRA_STORAGE_PROOF_SIZE; + + type SignedBlock = bp_statemine::SignedBlock; + type Call = runtime::Call; +} + +impl ChainWithTransactions for Statemine { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = runtime::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call.clone(), + bp_statemine::SignedExtensions::new( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ), + ) + .expect("SignedExtension never fails."); + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(runtime::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == bp_statemine::Address::Id(signer.public().into())) + .unwrap_or(false) + } + + fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { + unimplemented!("not used on Statemine") + } +} diff --git a/relays/client-statemine/src/runtime.rs b/relays/client-statemine/src/runtime.rs new file mode 100644 index 0000000000000..92924555769e4 --- /dev/null +++ b/relays/client-statemine/src/runtime.rs @@ -0,0 +1,68 @@ +// 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 . + +//! Types that are specific to the Statemine runtime. + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_runtime::FixedU128; + +/// Unchecked Statemine extrinsic. +pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; + +/// Statemine Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Statemine chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Statemine +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// See: [link](https://github.com/paritytech/cumulus/blob/master/parachains/runtimes/assets/statemine/src/lib.rs) +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// With-Statemint bridge pallet. + // TODO (https://github.com/paritytech/parity-bridges-common/issues/1626): + // must be updated when we'll make appropriate changes in the Statemine runtime + #[codec(index = 42)] + WithStatemintBridgePallet(WithStatemintBridgePalletCall), +} + +/// Calls of the with-Statemint bridge pallet. +// TODO (https://github.com/paritytech/parity-bridges-common/issues/1626): +// must be updated when we'll make appropriate changes in the Statemine runtime +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum WithStatemintBridgePalletCall { + #[codec(index = 42)] + update_dot_to_ksm_conversion_rate(FixedU128), +} + +impl sp_runtime::traits::Dispatchable for Call { + type RuntimeOrigin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch( + self, + _origin: Self::RuntimeOrigin, + ) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index f6a4220c618a4..0f650e9e2847f 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -60,7 +60,7 @@ impl Chain for Westend { const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_westend::SignedBlock; - type Call = bp_westend::Call; + type Call = (); } impl RelayChain for Westend { @@ -117,5 +117,5 @@ impl Chain for Westmint { const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_westend::SignedBlock; - type Call = bp_westend::Call; + type Call = (); } From 0dc8bda4338863a4217d8da2fc13b6da12a0d32e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 11 Nov 2022 15:31:01 +0300 Subject: [PATCH 0804/1210] Reintroduce header chain trait (#1622) * reintroduce header chain trait * renive BridgedChainWithMessages::maximal_extrinsic_size --- bin/millau/runtime/src/rialto_messages.rs | 39 +- .../runtime/src/rialto_parachain_messages.rs | 46 +- .../runtime/src/millau_messages.rs | 37 +- bin/rialto/runtime/src/millau_messages.rs | 37 +- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/integrity.rs | 31 - bin/runtime-common/src/lib.rs | 2 + bin/runtime-common/src/messages.rs | 861 +++++++----------- .../src/messages_benchmarking.rs | 131 +-- bin/runtime-common/src/messages_generation.rs | 154 ++++ .../src/parachains_benchmarking.rs | 4 +- modules/grandpa/src/lib.rs | 34 +- modules/parachains/Cargo.toml | 2 + modules/parachains/src/lib.rs | 41 +- primitives/chain-rialto-parachain/src/lib.rs | 6 +- primitives/header-chain/Cargo.toml | 2 + primitives/header-chain/src/lib.rs | 42 +- primitives/runtime/src/chain.rs | 6 + primitives/runtime/src/lib.rs | 2 +- 19 files changed, 648 insertions(+), 831 deletions(-) create mode 100644 bin/runtime-common/src/messages_generation.rs diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index cf2bd4badaf1e..c989de67b1763 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,14 +16,14 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{OriginCaller, RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; @@ -98,6 +98,8 @@ impl MessageBridge for WithRialtoMessageBridge { type ThisChain = Millau; type BridgedChain = Rialto; + type BridgedHeaderChain = + pallet_bridge_grandpa::GrandpaChainHeaders; fn bridged_balance_to_this_balance( bridged_balance: bp_rialto::Balance, @@ -115,18 +117,14 @@ impl MessageBridge for WithRialtoMessageBridge { pub struct Millau; impl messages::ChainWithMessages for Millau { - type Hash = bp_millau::Hash; - type AccountId = bp_millau::AccountId; - type Signer = bp_millau::AccountSigner; - type Signature = bp_millau::Signature; - type Balance = bp_millau::Balance; + type Chain = bp_millau::Millau; } impl messages::ThisChainWithMessages for Millau { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - Self::AccountId, + bp_millau::AccountId, { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_rialto::EXTRA_STORAGE_PROOF_SIZE }, { bp_millau::TX_EXTRA_BYTES }, @@ -177,18 +175,10 @@ impl messages::ThisChainWithMessages for Millau { pub struct Rialto; impl messages::ChainWithMessages for Rialto { - type Hash = bp_rialto::Hash; - type AccountId = bp_rialto::AccountId; - type Signer = bp_rialto::AccountSigner; - type Signature = bp_rialto::Signature; - type Balance = bp_rialto::Balance; + type Chain = bp_rialto::Rialto; } impl messages::BridgedChainWithMessages for Rialto { - fn maximal_extrinsic_size() -> u32 { - bp_rialto::Rialto::max_extrinsic_size() - } - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } @@ -248,11 +238,7 @@ impl TargetHeaderChain for Rialto fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::< - WithRialtoMessageBridge, - Runtime, - crate::RialtoGrandpaInstance, - >(proof) + messages::source::verify_messages_delivery_proof::(proof) } } @@ -269,11 +255,8 @@ impl SourceHeaderChain for Rialto { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::< - WithRialtoMessageBridge, - Runtime, - crate::RialtoGrandpaInstance, - >(proof, messages_count) + messages::target::verify_messages_proof::(proof, messages_count) + .map_err(Into::into) } } @@ -296,7 +279,7 @@ impl MessagesParameter for MillauToRialtoMessagesParameter { #[cfg(test)] mod tests { use super::*; - use crate::{DbWeight, RialtoGrandpaInstance, Runtime, WithRialtoMessagesInstance}; + use crate::{DbWeight, Runtime, WithRialtoMessagesInstance}; use bp_runtime::Chain; use bridge_runtime_common::{ diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index cce7aa79bad25..70e8db89d3a27 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -16,15 +16,14 @@ //! Everything required to serve Millau <-> RialtoParachain messages. -use crate::{Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{Runtime, RuntimeCall, RuntimeOrigin, WithRialtoParachainsInstance}; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_polkadot_core::parachains::ParaId; -use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; +use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; @@ -103,6 +102,11 @@ impl MessageBridge for WithRialtoParachainMessageBridge { type ThisChain = Millau; type BridgedChain = RialtoParachain; + type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< + Runtime, + WithRialtoParachainsInstance, + bp_rialto_parachain::RialtoParachain, + >; fn bridged_balance_to_this_balance( bridged_balance: bp_rialto_parachain::Balance, @@ -120,18 +124,14 @@ impl MessageBridge for WithRialtoParachainMessageBridge { pub struct Millau; impl messages::ChainWithMessages for Millau { - type Hash = bp_millau::Hash; - type AccountId = bp_millau::AccountId; - type Signer = bp_millau::AccountSigner; - type Signature = bp_millau::Signature; - type Balance = bp_millau::Balance; + type Chain = bp_millau::Millau; } impl messages::ThisChainWithMessages for Millau { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - Self::AccountId, + bp_rialto_parachain::AccountId, { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE }, { bp_millau::TX_EXTRA_BYTES }, @@ -166,18 +166,10 @@ impl messages::ThisChainWithMessages for Millau { pub struct RialtoParachain; impl messages::ChainWithMessages for RialtoParachain { - type Hash = bp_rialto_parachain::Hash; - type AccountId = bp_rialto_parachain::AccountId; - type Signer = bp_rialto_parachain::AccountSigner; - type Signature = bp_rialto_parachain::Signature; - type Balance = bp_rialto_parachain::Balance; + type Chain = bp_rialto_parachain::RialtoParachain; } impl messages::BridgedChainWithMessages for RialtoParachain { - fn maximal_extrinsic_size() -> u32 { - bp_rialto_parachain::RialtoParachain::max_extrinsic_size() - } - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } @@ -241,12 +233,7 @@ impl TargetHeaderChain fo fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof_from_parachain::< - WithRialtoParachainMessageBridge, - bp_rialto_parachain::Header, - Runtime, - crate::WithRialtoParachainsInstance, - >(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof) + messages::source::verify_messages_delivery_proof::(proof) } } @@ -263,12 +250,11 @@ impl SourceHeaderChain for RialtoParachain { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof_from_parachain::< - WithRialtoParachainMessageBridge, - bp_rialto_parachain::Header, - Runtime, - crate::WithRialtoParachainsInstance, - >(ParaId(bp_rialto_parachain::RIALTO_PARACHAIN_ID), proof, messages_count) + messages::target::verify_messages_proof::( + proof, + messages_count, + ) + .map_err(Into::into) } } diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 4688f89a7087a..a13a17a1ea281 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -19,14 +19,14 @@ // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // Should be extracted to a separate crate and reused here. -use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{MillauGrandpaInstance, OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; +use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; @@ -102,6 +102,8 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = RialtoParachain; type BridgedChain = Millau; + type BridgedHeaderChain = + pallet_bridge_grandpa::GrandpaChainHeaders; fn bridged_balance_to_this_balance( bridged_balance: bp_millau::Balance, @@ -119,18 +121,14 @@ impl MessageBridge for WithMillauMessageBridge { pub struct RialtoParachain; impl messages::ChainWithMessages for RialtoParachain { - type Hash = bp_rialto_parachain::Hash; - type AccountId = bp_rialto_parachain::AccountId; - type Signer = bp_rialto_parachain::AccountSigner; - type Signature = bp_rialto_parachain::Signature; - type Balance = bp_rialto_parachain::Balance; + type Chain = bp_rialto_parachain::RialtoParachain; } impl messages::ThisChainWithMessages for RialtoParachain { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - Self::AccountId, + bp_rialto_parachain::AccountId, { bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, { bp_rialto_parachain::TX_EXTRA_BYTES }, @@ -184,18 +182,10 @@ impl messages::ThisChainWithMessages for RialtoParachain { pub struct Millau; impl messages::ChainWithMessages for Millau { - type Hash = bp_millau::Hash; - type AccountId = bp_millau::AccountId; - type Signer = bp_millau::AccountSigner; - type Signature = bp_millau::Signature; - type Balance = bp_millau::Balance; + type Chain = bp_millau::Millau; } impl messages::BridgedChainWithMessages for Millau { - fn maximal_extrinsic_size() -> u32 { - bp_millau::Millau::max_extrinsic_size() - } - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } @@ -255,11 +245,7 @@ impl TargetHeaderChain f fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::< - WithMillauMessageBridge, - Runtime, - crate::MillauGrandpaInstance, - >(proof) + messages::source::verify_messages_delivery_proof::(proof) } } @@ -276,11 +262,8 @@ impl SourceHeaderChain for Millau { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::< - WithMillauMessageBridge, - Runtime, - crate::MillauGrandpaInstance, - >(proof, messages_count) + messages::target::verify_messages_proof::(proof, messages_count) + .map_err(Into::into) } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 43c95744165f3..b27cce40074aa 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,14 +16,14 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{MillauGrandpaInstance, OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, }; -use bp_runtime::{Chain, ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; +use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{ self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, }; @@ -96,6 +96,8 @@ impl MessageBridge for WithMillauMessageBridge { type ThisChain = Rialto; type BridgedChain = Millau; + type BridgedHeaderChain = + pallet_bridge_grandpa::GrandpaChainHeaders; fn bridged_balance_to_this_balance( bridged_balance: bp_millau::Balance, @@ -113,18 +115,14 @@ impl MessageBridge for WithMillauMessageBridge { pub struct Rialto; impl messages::ChainWithMessages for Rialto { - type Hash = bp_rialto::Hash; - type AccountId = bp_rialto::AccountId; - type Signer = bp_rialto::AccountSigner; - type Signature = bp_rialto::Signature; - type Balance = bp_rialto::Balance; + type Chain = bp_rialto::Rialto; } impl messages::ThisChainWithMessages for Rialto { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - Self::AccountId, + bp_rialto::AccountId, { bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, { bp_rialto::TX_EXTRA_BYTES }, @@ -175,18 +173,10 @@ impl messages::ThisChainWithMessages for Rialto { pub struct Millau; impl messages::ChainWithMessages for Millau { - type Hash = bp_millau::Hash; - type AccountId = bp_millau::AccountId; - type Signer = bp_millau::AccountSigner; - type Signature = bp_millau::Signature; - type Balance = bp_millau::Balance; + type Chain = bp_millau::Millau; } impl messages::BridgedChainWithMessages for Millau { - fn maximal_extrinsic_size() -> u32 { - bp_millau::Millau::max_extrinsic_size() - } - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } @@ -246,11 +236,7 @@ impl TargetHeaderChain for Millau fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::< - WithMillauMessageBridge, - Runtime, - crate::MillauGrandpaInstance, - >(proof) + messages::source::verify_messages_delivery_proof::(proof) } } @@ -267,11 +253,8 @@ impl SourceHeaderChain for Millau { proof: Self::MessagesProof, messages_count: u32, ) -> Result>, Self::Error> { - messages::target::verify_messages_proof::< - WithMillauMessageBridge, - Runtime, - crate::MillauGrandpaInstance, - >(proof, messages_count) + messages::target::verify_messages_proof::(proof, messages_count) + .map_err(Into::into) } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 2fb64a5b73325..4f8f7e34c4042 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -15,6 +15,7 @@ static_assertions = { version = "1.1", optional = true } # Bridge dependencies +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } @@ -47,6 +48,7 @@ millau-runtime = { path = "../millau/runtime" } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-messages/std", "bp-parachains/std", "bp-polkadot-core/std", diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 90f048cb9cc30..3b64d1e8afea5 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -49,36 +49,6 @@ macro_rules! assert_chain_types( } ); -/// Macro that ensures that the bridge configuration and chain primitives crates are sharing -/// the same types (hash, account id, ...). -#[macro_export] -macro_rules! assert_bridge_types( - ( bridge: $bridge:path, this_chain: $this:path, bridged_chain: $bridged:path ) => { - { - // if one of this asserts fail, then all chains, bridged with this chain and bridge relays are now broken - // - // `frame_support::weights::Weight` is used here directly, because all chains we know are using this - // primitive (may be changed in the future) - use $crate::messages::{ - AccountIdOf, BalanceOf, BridgedChain, HashOf, SignatureOf, SignerOf, ThisChain, - }; - use static_assertions::assert_type_eq_all; - - assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$this>); - assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$this>); - assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$this>); - assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$this>); - assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$this>); - - assert_type_eq_all!(HashOf>, bp_runtime::HashOf<$bridged>); - assert_type_eq_all!(AccountIdOf>, bp_runtime::AccountIdOf<$bridged>); - assert_type_eq_all!(SignerOf>, bp_runtime::AccountPublicOf<$bridged>); - assert_type_eq_all!(SignatureOf>, bp_runtime::SignatureOf<$bridged>); - assert_type_eq_all!(BalanceOf>, bp_runtime::BalanceOf<$bridged>); - } - } -); - /// Macro that ensures that the bridge GRANDPA pallet is configured properly to bridge with given /// chain. #[macro_export] @@ -145,7 +115,6 @@ macro_rules! assert_complete_bridge_types( bridged_chain: $bridged:path, ) => { $crate::assert_chain_types!(runtime: $r, this_chain: $this); - $crate::assert_bridge_types!(bridge: $bridge, this_chain: $this, bridged_chain: $bridged); $crate::assert_bridge_grandpa_pallet_types!( runtime: $r, with_bridged_chain_grandpa_instance: $gi, diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index e56b887885aa7..ca8f2268404e5 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -28,6 +28,8 @@ pub mod messages_benchmarking; pub mod messages_extension; pub mod parachains_benchmarking; +mod messages_generation; + #[cfg(feature = "integrity-test")] pub mod integrity; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3744d7153eef8..75c3ec6e57f30 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -20,22 +20,22 @@ //! pallet is used to dispatch incoming messages. Message identified by a tuple //! of to elements - message lane id and message nonce. +use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, }; -use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaId}; -use bp_runtime::{messages::MessageDispatchResult, ChainId, Size, StorageProofChecker}; +use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Size, StorageProofChecker}; use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul, Header as HeaderT}, + traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, FixedPointNumber, FixedPointOperand, FixedU128, }; -use sp_std::{cmp::PartialOrd, convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; +use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; use sp_trie::StorageProof; use xcm::latest::prelude::*; @@ -57,6 +57,8 @@ pub trait MessageBridge { type ThisChain: ThisChainWithMessages; /// Bridged chain in context of message bridge. type BridgedChain: BridgedChainWithMessages; + /// Bridged header chain. + type BridgedHeaderChain: HeaderChain<::Chain>; /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance( @@ -65,27 +67,6 @@ pub trait MessageBridge { ) -> BalanceOf>; } -/// Chain that has `pallet-bridge-messages` and `dispatch` modules. -pub trait ChainWithMessages { - /// Hash used in the chain. - type Hash: Decode; - /// Accound id on the chain. - type AccountId: Encode + Decode + MaxEncodedLen; - /// Public key of the chain account that may be used to verify signatures. - type Signer: Encode + Decode; - /// Signature type used on the chain. - type Signature: Encode + Decode; - /// Type of balances that is used on the chain. - type Balance: Encode - + Decode - + CheckedAdd - + CheckedDiv - + CheckedMul - + PartialOrd - + From - + Copy; -} - /// Message related transaction parameters estimation. #[derive(RuntimeDebug)] pub struct MessageTransaction { @@ -134,7 +115,13 @@ impl< } } -/// This chain that has `pallet-bridge-messages` and `dispatch` modules. +/// Chain that has `pallet-bridge-messages` module. +pub trait ChainWithMessages { + /// Underlying chain type. + type Chain: Chain; +} + +/// This chain that has `pallet-bridge-messages` module. pub trait ThisChainWithMessages: ChainWithMessages { /// Call origin on the chain. type RuntimeOrigin; @@ -161,11 +148,8 @@ pub trait ThisChainWithMessages: ChainWithMessages { fn transaction_payment(transaction: MessageTransaction) -> BalanceOf; } -/// Bridged chain that has `pallet-bridge-messages` and `dispatch` modules. +/// Bridged chain that has `pallet-bridge-messages` module. pub trait BridgedChainWithMessages: ChainWithMessages { - /// Maximal extrinsic size at Bridged chain. - fn maximal_extrinsic_size() -> u32; - /// Returns `true` if message dispatch weight is withing expected limits. `false` means /// that the message is too heavy to be sent over the bridge and shall be rejected. fn verify_dispatch_weight(message_payload: &[u8]) -> bool; @@ -186,16 +170,16 @@ pub trait BridgedChainWithMessages: ChainWithMessages { pub type ThisChain = ::ThisChain; /// Bridged chain in context of message bridge. pub type BridgedChain = ::BridgedChain; +/// Underlying chain type. +pub type UnderlyingChainOf = ::Chain; /// Hash used on the chain. -pub type HashOf = ::Hash; +pub type HashOf = bp_runtime::HashOf<::Chain>; +/// Hasher used on the chain. +pub type HasherOf = bp_runtime::HasherOf<::Chain>; /// Account id used on the chain. -pub type AccountIdOf = ::AccountId; -/// Public key of the chain account that may be used to verify signature. -pub type SignerOf = ::Signer; -/// Signature type used on the chain. -pub type SignatureOf = ::Signature; +pub type AccountIdOf = bp_runtime::AccountIdOf<::Chain>; /// Type of balances that is used on the chain. -pub type BalanceOf = ::Balance; +pub type BalanceOf = bp_runtime::BalanceOf<::Chain>; /// Type of origin that is used on the chain. pub type OriginOf = ::RuntimeOrigin; /// Type of call that is used on this chain. @@ -358,7 +342,9 @@ pub mod source { /// Return maximal message size of This -> Bridged chain message. pub fn maximal_message_size() -> u32 { - super::target::maximal_incoming_message_size(BridgedChain::::maximal_extrinsic_size()) + super::target::maximal_incoming_message_size( + UnderlyingChainOf::>::max_extrinsic_size(), + ) } /// Do basic Bridged-chain specific verification of This -> Bridged chain message. @@ -440,87 +426,35 @@ pub mod source { /// /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged /// parachains, please use the `verify_messages_delivery_proof_from_parachain`. - pub fn verify_messages_delivery_proof( - proof: FromBridgedChainMessagesDeliveryProof>>, - ) -> Result, &'static str> - where - ThisRuntime: pallet_bridge_grandpa::Config, - HashOf>: Into< - bp_runtime::HashOf< - >::BridgedChain, - >, - >, - { - let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = - proof; - pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( - bridged_header_hash.into(), - StorageProof::new(storage_proof), - |storage| do_verify_messages_delivery_proof::< - B, - bp_runtime::HasherOf< - >::BridgedChain, - >, - >(lane, storage), - ) - .map_err(<&'static str>::from)? - } - - /// Verify proof of This -> Bridged chain messages delivery. - /// - /// This function is used when Bridged chain is using parachain finality. For Bridged - /// chains with direct GRANDPA finality, please use the `verify_messages_delivery_proof`. - /// - /// This function currently only supports parachains, which are using header type that - /// implements `sp_runtime::traits::Header` trait. - pub fn verify_messages_delivery_proof_from_parachain< - B, - BridgedHeader, - ThisRuntime, - ParachainsInstance: 'static, - >( - bridged_parachain: ParaId, + pub fn verify_messages_delivery_proof( proof: FromBridgedChainMessagesDeliveryProof>>, - ) -> Result, &'static str> - where - B: MessageBridge, - B::BridgedChain: ChainWithMessages, - BridgedHeader: HeaderT>>, - ThisRuntime: pallet_bridge_parachains::Config, - { + ) -> Result, &'static str> { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = proof; - pallet_bridge_parachains::Pallet::::parse_finalized_storage_proof( - bridged_parachain, + B::BridgedHeaderChain::parse_finalized_storage_proof( bridged_header_hash, StorageProof::new(storage_proof), - |para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()), - |storage| do_verify_messages_delivery_proof::(lane, storage), + |storage| { + // Messages delivery proof is just proof of single storage key read => any error + // is fatal. + let storage_inbound_lane_data_key = + bp_messages::storage_keys::inbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &lane, + ); + let raw_inbound_lane_data = storage + .read_value(storage_inbound_lane_data_key.0.as_ref()) + .map_err(|_| "Failed to read inbound lane state from storage proof")? + .ok_or("Inbound lane state is missing from the messages proof")?; + let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) + .map_err(|_| "Failed to decode inbound lane state from the proof")?; + + Ok((lane, inbound_lane_data)) + }, ) .map_err(<&'static str>::from)? } - /// The essense of This -> Bridged chain messages delivery proof verification. - fn do_verify_messages_delivery_proof( - lane: LaneId, - storage: bp_runtime::StorageProofChecker, - ) -> Result, &'static str> { - // Messages delivery proof is just proof of single storage key read => any error - // is fatal. - let storage_inbound_lane_data_key = bp_messages::storage_keys::inbound_lane_data_key( - B::BRIDGED_MESSAGES_PALLET_NAME, - &lane, - ); - let raw_inbound_lane_data = storage - .read_value(storage_inbound_lane_data_key.0.as_ref()) - .map_err(|_| "Failed to read inbound lane state from storage proof")? - .ok_or("Inbound lane state is missing from the messages proof")?; - let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) - .map_err(|_| "Failed to decode inbound lane state from the proof")?; - - Ok((lane, inbound_lane_data)) - } - /// XCM bridge. pub trait XcmBridge { /// Runtime message bridge configuration. @@ -801,98 +735,106 @@ pub mod target { /// The `messages_count` argument verification (sane limits) is supposed to be made /// outside of this function. This function only verifies that the proof declares exactly /// `messages_count` messages. - pub fn verify_messages_proof( + pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof>>, messages_count: u32, - ) -> Result>>>, &'static str> - where - ThisRuntime: pallet_bridge_grandpa::Config, - HashOf>: Into< - bp_runtime::HashOf< - >::BridgedChain, - >, - >, - { - verify_messages_proof_with_parser::( - proof, - messages_count, - |bridged_header_hash, bridged_storage_proof| { - pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( - bridged_header_hash.into(), - StorageProof::new(bridged_storage_proof), - |storage_adapter| storage_adapter, - ) - .map(|storage| StorageProofCheckerAdapter::<_, B> { - storage, - _dummy: Default::default(), - }) - .map_err(|err| MessageProofError::Custom(err.into())) - }, - ) - .map_err(Into::into) - } + ) -> Result>>>, MessageProofError> { + let FromBridgedChainMessagesProof { + bridged_header_hash, + storage_proof, + lane, + nonces_start, + nonces_end, + } = proof; - /// Verify proof of Bridged -> This chain messages. - /// - /// This function is used when Bridged chain is using parachain finality. For Bridged - /// chains with direct GRANDPA finality, please use the `verify_messages_proof`. - /// - /// The `messages_count` argument verification (sane limits) is supposed to be made - /// outside of this function. This function only verifies that the proof declares exactly - /// `messages_count` messages. - /// - /// This function currently only supports parachains, which are using header type that - /// implements `sp_runtime::traits::Header` trait. - pub fn verify_messages_proof_from_parachain< - B, - BridgedHeader, - ThisRuntime, - ParachainsInstance: 'static, - >( - bridged_parachain: ParaId, - proof: FromBridgedChainMessagesProof>>, - messages_count: u32, - ) -> Result>>>, &'static str> - where - B: MessageBridge, - B::BridgedChain: ChainWithMessages, - BridgedHeader: HeaderT>>, - ThisRuntime: pallet_bridge_parachains::Config, - { - verify_messages_proof_with_parser::( - proof, - messages_count, - |bridged_header_hash, bridged_storage_proof| { - pallet_bridge_parachains::Pallet::::parse_finalized_storage_proof( - bridged_parachain, - bridged_header_hash, - StorageProof::new(bridged_storage_proof), - |para_head| BridgedHeader::decode(&mut ¶_head.0[..]).ok().map(|h| *h.state_root()), - |storage_adapter| storage_adapter, - ) - .map(|storage| StorageProofCheckerAdapter::<_, B> { - storage, - _dummy: Default::default(), - }) - .map_err(|err| MessageProofError::Custom(err.into())) + B::BridgedHeaderChain::parse_finalized_storage_proof( + bridged_header_hash, + StorageProof::new(storage_proof), + |storage| { + let parser = + StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default() }; + + // receiving proofs where end < begin is ok (if proof includes outbound lane state) + let messages_in_the_proof = + if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { + // let's check that the user (relayer) has passed correct `messages_count` + // (this bounds maximal capacity of messages vec below) + let messages_in_the_proof = nonces_difference.saturating_add(1); + if messages_in_the_proof != MessageNonce::from(messages_count) { + return Err(MessageProofError::MessagesCountMismatch) + } + + messages_in_the_proof + } else { + 0 + }; + + // Read messages first. All messages that are claimed to be in the proof must + // be in the proof. So any error in `read_value`, or even missing value is fatal. + // + // Mind that we allow proofs with no messages if outbound lane state is proved. + let mut messages = Vec::with_capacity(messages_in_the_proof as _); + for nonce in nonces_start..=nonces_end { + let message_key = MessageKey { lane_id: lane, nonce }; + let raw_message_data = parser + .read_raw_message(&message_key) + .ok_or(MessageProofError::MissingRequiredMessage)?; + let message_data = MessageData::>>::decode( + &mut &raw_message_data[..], + ) + .map_err(|_| MessageProofError::FailedToDecodeMessage)?; + messages.push(Message { key: message_key, data: message_data }); + } + + // Now let's check if proof contains outbound lane state proof. It is optional, so + // we simply ignore `read_value` errors and missing value. + let mut proved_lane_messages = ProvedLaneMessages { lane_state: None, messages }; + let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane); + if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { + proved_lane_messages.lane_state = Some( + OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) + .map_err(|_| MessageProofError::FailedToDecodeOutboundLaneState)?, + ); + } + + // Now we may actually check if the proof is empty or not. + if proved_lane_messages.lane_state.is_none() && + proved_lane_messages.messages.is_empty() + { + return Err(MessageProofError::Empty) + } + + // We only support single lane messages in this generated_schema + let mut proved_messages = ProvedMessages::new(); + proved_messages.insert(lane, proved_lane_messages); + + Ok(proved_messages) }, ) - .map_err(Into::into) + .map_err(MessageProofError::HeaderChain)? } + /// Error that happens during message proof verification. #[derive(Debug, PartialEq, Eq)] - pub(crate) enum MessageProofError { + pub enum MessageProofError { + /// Error returned by the bridged header chain. + HeaderChain(HeaderChainError), + /// The message proof is empty. Empty, + /// Declared messages count doesn't match actual value. MessagesCountMismatch, + /// Message is missing from the proof. MissingRequiredMessage, + /// Failed to decode message from the proof. FailedToDecodeMessage, + /// Failed to decode outbound lane data from the proof. FailedToDecodeOutboundLaneState, - Custom(&'static str), } impl From for &'static str { fn from(err: MessageProofError) -> &'static str { match err { + MessageProofError::HeaderChain(err) => err.into(), MessageProofError::Empty => "Messages proof is empty", MessageProofError::MessagesCountMismatch => "Declared messages count doesn't match actual value", @@ -901,26 +843,16 @@ pub mod target { "Failed to decode message from the proof", MessageProofError::FailedToDecodeOutboundLaneState => "Failed to decode outbound lane data from the proof", - MessageProofError::Custom(err) => err, } } } - pub(crate) trait MessageProofParser { - fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option>; - fn read_raw_message(&self, message_key: &MessageKey) -> Option>; - } - struct StorageProofCheckerAdapter { storage: StorageProofChecker, _dummy: sp_std::marker::PhantomData, } - impl MessageProofParser for StorageProofCheckerAdapter - where - H: Hasher, - B: MessageBridge, - { + impl StorageProofCheckerAdapter { fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { let storage_outbound_lane_data_key = bp_messages::storage_keys::outbound_lane_data_key( B::BRIDGED_MESSAGES_PALLET_NAME, @@ -938,89 +870,20 @@ pub mod target { self.storage.read_value(storage_message_key.0.as_ref()).ok()? } } - - /// Verify proof of Bridged -> This chain messages using given message proof parser. - pub(crate) fn verify_messages_proof_with_parser( - proof: FromBridgedChainMessagesProof>>, - messages_count: u32, - build_parser: BuildParser, - ) -> Result>>>, MessageProofError> - where - BuildParser: - FnOnce(HashOf>, RawStorageProof) -> Result, - Parser: MessageProofParser, - { - let FromBridgedChainMessagesProof { - bridged_header_hash, - storage_proof, - lane, - nonces_start, - nonces_end, - } = proof; - - // receiving proofs where end < begin is ok (if proof includes outbound lane state) - let messages_in_the_proof = - if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { - // let's check that the user (relayer) has passed correct `messages_count` - // (this bounds maximal capacity of messages vec below) - let messages_in_the_proof = nonces_difference.saturating_add(1); - if messages_in_the_proof != MessageNonce::from(messages_count) { - return Err(MessageProofError::MessagesCountMismatch) - } - - messages_in_the_proof - } else { - 0 - }; - - let parser = build_parser(bridged_header_hash, storage_proof)?; - - // Read messages first. All messages that are claimed to be in the proof must - // be in the proof. So any error in `read_value`, or even missing value is fatal. - // - // Mind that we allow proofs with no messages if outbound lane state is proved. - let mut messages = Vec::with_capacity(messages_in_the_proof as _); - for nonce in nonces_start..=nonces_end { - let message_key = MessageKey { lane_id: lane, nonce }; - let raw_message_data = parser - .read_raw_message(&message_key) - .ok_or(MessageProofError::MissingRequiredMessage)?; - let message_data = - MessageData::>>::decode(&mut &raw_message_data[..]) - .map_err(|_| MessageProofError::FailedToDecodeMessage)?; - messages.push(Message { key: message_key, data: message_data }); - } - - // Now let's check if proof contains outbound lane state proof. It is optional, so we - // simply ignore `read_value` errors and missing value. - let mut proved_lane_messages = ProvedLaneMessages { lane_state: None, messages }; - let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane); - if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { - proved_lane_messages.lane_state = Some( - OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) - .map_err(|_| MessageProofError::FailedToDecodeOutboundLaneState)?, - ); - } - - // Now we may actually check if the proof is empty or not. - if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { - return Err(MessageProofError::Empty) - } - - // We only support single lane messages in this generated_schema - let mut proved_messages = ProvedMessages::new(); - proved_messages.insert(lane, proved_lane_messages); - - Ok(proved_messages) - } } #[cfg(test)] mod tests { use super::*; + use crate::messages_generation::{ + encode_all_messages, encode_lane_data, prepare_messages_storage_proof, + }; + use bp_runtime::HeaderOf; use codec::{Decode, Encode}; use frame_support::weights::Weight; - use std::ops::RangeInclusive; + use sp_core::H256; + use sp_runtime::traits::{BlakeTwo256, Header as _}; + use std::cell::RefCell; const DELIVERY_TRANSACTION_WEIGHT: Weight = Weight::from_ref_time(100); const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: u64 = 100; @@ -1032,7 +895,7 @@ mod tests { const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from - /// BridgedChain; + /// BridgedChain. #[derive(Debug, PartialEq, Eq)] struct OnThisChainBridge; @@ -1044,6 +907,7 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; + type BridgedHeaderChain = BridgedHeaderChain; fn bridged_balance_to_this_balance( bridged_balance: BridgedChainBalance, @@ -1052,7 +916,7 @@ mod tests { let conversion_rate = bridged_to_this_conversion_rate_override .map(|r| r.to_float() as u32) .unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE); - ThisChainBalance(bridged_balance.0 * conversion_rate) + bridged_balance as ThisChainBalance * conversion_rate as ThisChainBalance } } @@ -1069,6 +933,7 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; + type BridgedHeaderChain = ThisHeaderChain; fn bridged_balance_to_this_balance( _this_balance: ThisChainBalance, @@ -1078,19 +943,6 @@ mod tests { } } - #[derive(Debug, PartialEq, Eq, Decode, Encode, Clone, MaxEncodedLen)] - struct ThisChainAccountId(u32); - #[derive(Debug, PartialEq, Eq, Decode, Encode)] - struct ThisChainSigner(u32); - #[derive(Debug, PartialEq, Eq, Decode, Encode)] - struct ThisChainSignature(u32); - #[derive(Debug, PartialEq, Eq, Decode, Encode)] - enum ThisChainCall { - #[codec(index = 42)] - Transfer, - #[codec(index = 84)] - Mint, - } #[derive(Clone, Debug)] struct ThisChainOrigin(Result, ()>); @@ -1104,14 +956,6 @@ mod tests { } } - #[derive(Debug, PartialEq, Eq, Decode, Encode, MaxEncodedLen)] - struct BridgedChainAccountId(u32); - #[derive(Debug, PartialEq, Eq, Decode, Encode)] - struct BridgedChainSigner(u32); - #[derive(Debug, PartialEq, Eq, Decode, Encode)] - struct BridgedChainSignature(u32); - #[derive(Debug, PartialEq, Eq, Decode, Encode)] - enum BridgedChainCall {} #[derive(Clone, Debug)] struct BridgedChainOrigin; @@ -1125,85 +969,42 @@ mod tests { } } - macro_rules! impl_wrapped_balance { - ($name:ident) => { - #[derive(Debug, PartialEq, Eq, Decode, Encode, Clone, Copy)] - struct $name(u32); - - impl From for $name { - fn from(balance: u32) -> Self { - Self(balance) - } - } - - impl sp_std::ops::Add for $name { - type Output = $name; - - fn add(self, other: Self) -> Self { - Self(self.0 + other.0) - } - } - - impl sp_std::ops::Div for $name { - type Output = $name; - - fn div(self, other: Self) -> Self { - Self(self.0 / other.0) - } - } - - impl sp_std::ops::Mul for $name { - type Output = $name; + struct ThisUnderlyingChain; + type ThisChainHeader = sp_runtime::generic::Header; + type ThisChainAccountId = u32; + type ThisChainBalance = u32; + #[derive(Decode, Encode)] + struct ThisChainCall; - fn mul(self, other: Self) -> Self { - Self(self.0 * other.0) - } - } - - impl sp_std::cmp::PartialOrd for $name { - fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) - } - } - - impl CheckedAdd for $name { - fn checked_add(&self, other: &Self) -> Option { - self.0.checked_add(other.0).map(Self) - } - } - - impl CheckedDiv for $name { - fn checked_div(&self, other: &Self) -> Option { - self.0.checked_div(other.0).map(Self) - } - } + impl Chain for ThisUnderlyingChain { + type BlockNumber = u64; + type Hash = H256; + type Hasher = BlakeTwo256; + type Header = ThisChainHeader; + type AccountId = ThisChainAccountId; + type Balance = ThisChainBalance; + type Index = u32; + type Signature = sp_runtime::MultiSignature; - impl CheckedMul for $name { - fn checked_mul(&self, other: &Self) -> Option { - self.0.checked_mul(other.0).map(Self) - } - } - }; + fn max_extrinsic_size() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } } - impl_wrapped_balance!(ThisChainBalance); - impl_wrapped_balance!(BridgedChainBalance); - struct ThisChain; impl ChainWithMessages for ThisChain { - type Hash = (); - type AccountId = ThisChainAccountId; - type Signer = ThisChainSigner; - type Signature = ThisChainSignature; - type Balance = ThisChainBalance; + type Chain = ThisUnderlyingChain; } impl ThisChainWithMessages for ThisChain { type RuntimeOrigin = ThisChainOrigin; type RuntimeCall = ThisChainCall; type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - ::AccountId, + ThisChainAccountId, { DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT }, 0, 0, @@ -1218,20 +1019,14 @@ mod tests { } fn transaction_payment(transaction: MessageTransaction) -> BalanceOf { - ThisChainBalance( - transaction - .dispatch_weight - .saturating_mul(THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) - .ref_time() as _, - ) + transaction + .dispatch_weight + .saturating_mul(THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) + .ref_time() as _ } } impl BridgedChainWithMessages for ThisChain { - fn maximal_extrinsic_size() -> u32 { - unreachable!() - } - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { unreachable!() } @@ -1249,25 +1044,42 @@ mod tests { } } - struct BridgedChain; + struct BridgedUnderlyingChain; + type BridgedChainHeader = sp_runtime::generic::Header; + type BridgedChainAccountId = u128; + type BridgedChainBalance = u128; + #[derive(Decode, Encode)] + struct BridgedChainCall; - impl ChainWithMessages for BridgedChain { - type Hash = (); + impl Chain for BridgedUnderlyingChain { + type BlockNumber = u64; + type Hash = H256; + type Hasher = BlakeTwo256; + type Header = BridgedChainHeader; type AccountId = BridgedChainAccountId; - type Signer = BridgedChainSigner; - type Signature = BridgedChainSignature; type Balance = BridgedChainBalance; + type Index = u32; + type Signature = sp_runtime::MultiSignature; + + fn max_extrinsic_size() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } + } + + struct BridgedChain; + + impl ChainWithMessages for BridgedChain { + type Chain = BridgedUnderlyingChain; } impl ThisChainWithMessages for BridgedChain { type RuntimeOrigin = BridgedChainOrigin; type RuntimeCall = BridgedChainCall; - type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - ::AccountId, - 0, - 0, - 0, - >; + type ConfirmationTransactionEstimation = + BasicConfirmationTransactionEstimation; fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { unreachable!() @@ -1283,10 +1095,6 @@ mod tests { } impl BridgedChainWithMessages for BridgedChain { - fn maximal_extrinsic_size() -> u32 { - BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE - } - fn verify_dispatch_weight(message_payload: &[u8]) -> bool { message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT @@ -1304,12 +1112,32 @@ mod tests { } fn transaction_payment(transaction: MessageTransaction) -> BalanceOf { - BridgedChainBalance( - transaction - .dispatch_weight - .saturating_mul(BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) - .ref_time() as _, - ) + transaction + .dispatch_weight + .saturating_mul(BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) + .ref_time() as _ + } + } + + thread_local! { + static TEST_BRIDGED_HEADER: RefCell> = RefCell::new(None); + } + + struct BridgedHeaderChain; + + impl HeaderChain for BridgedHeaderChain { + fn finalized_header( + _hash: HashOf, + ) -> Option> { + TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()) + } + } + + struct ThisHeaderChain; + + impl HeaderChain for ThisHeaderChain { + fn finalized_header(_hash: HashOf) -> Option> { + unreachable!() } } @@ -1338,14 +1166,14 @@ mod tests { OnThisChainBridge::RELAYER_FEE_PERCENT, None, ), - Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), + Ok(EXPECTED_MINIMAL_FEE), ); // and now check that the verifier checks the fee assert_eq!( source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1), + &1, TEST_LANE_ID, &test_lane_outbound_data(), &payload, @@ -1354,7 +1182,7 @@ mod tests { ); assert!(source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), + &1_000_000, TEST_LANE_ID, &test_lane_outbound_data(), &payload, @@ -1367,7 +1195,7 @@ mod tests { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), + &1_000_000, b"dsbl", &test_lane_outbound_data(), ®ular_outbound_message_payload(), @@ -1381,7 +1209,7 @@ mod tests { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &ThisChainBalance(1_000_000), + &1_000_000, TEST_LANE_ID, &OutboundLaneData { latest_received_nonce: 100, @@ -1436,62 +1264,48 @@ mod tests { ); } - #[derive(Debug)] - struct TestMessageProofParser { - failing: bool, - messages: RangeInclusive, + fn using_messages_proof( + nonces_end: MessageNonce, outbound_lane_data: Option, - } - - impl target::MessageProofParser for TestMessageProofParser { - fn read_raw_outbound_lane_data(&self, _lane_id: &LaneId) -> Option> { - if self.failing { - Some(vec![]) - } else { - self.outbound_lane_data.clone().map(|data| data.encode()) - } - } - - fn read_raw_message(&self, message_key: &MessageKey) -> Option> { - if self.failing { - Some(vec![]) - } else if self.messages.contains(&message_key.nonce) { - Some( - MessageData:: { - payload: message_key.nonce.encode(), - fee: BridgedChainBalance(0), - } - .encode(), - ) - } else { - None - } - } - } + encode_message: impl Fn(MessageNonce, &MessageData) -> Option>, + encode_outbound_lane_data: impl Fn(&OutboundLaneData) -> Vec, + test: impl Fn(target::FromBridgedChainMessagesProof) -> R, + ) -> R { + let (state_root, storage_proof) = prepare_messages_storage_proof::( + *TEST_LANE_ID, + 1..=nonces_end, + outbound_lane_data, + bp_runtime::StorageProofSize::Minimal(0), + vec![42], + encode_message, + encode_outbound_lane_data, + ); - #[allow(clippy::reversed_empty_ranges)] - fn no_messages_range() -> RangeInclusive { - 1..=0 - } + TEST_BRIDGED_HEADER.with(|h| { + *h.borrow_mut() = Some(BridgedChainHeader::new( + 0, + Default::default(), + state_root, + Default::default(), + Default::default(), + )) + }); - fn messages_proof(nonces_end: MessageNonce) -> target::FromBridgedChainMessagesProof<()> { - target::FromBridgedChainMessagesProof { - bridged_header_hash: (), - storage_proof: vec![], - lane: Default::default(), + test(target::FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof, + lane: *TEST_LANE_ID, nonces_start: 1, nonces_end, - } + }) } #[test] fn messages_proof_is_rejected_if_declared_less_than_actual_number_of_messages() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(10), - 5, - |_, _| unreachable!(), - ), + using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { + target::verify_messages_proof::(proof, 5) + }), Err(target::MessageProofError::MessagesCountMismatch), ); } @@ -1499,38 +1313,45 @@ mod tests { #[test] fn messages_proof_is_rejected_if_declared_more_than_actual_number_of_messages() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(10), - 15, - |_, _| unreachable!(), - ), + using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { + target::verify_messages_proof::(proof, 15) + }), Err(target::MessageProofError::MessagesCountMismatch), ); } #[test] - fn message_proof_is_rejected_if_build_parser_fails() { + fn message_proof_is_rejected_if_header_is_missing_from_the_chain() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(10), - 10, - |_, _| Err(target::MessageProofError::Custom("test")), - ), - Err(target::MessageProofError::Custom("test")), + using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { + TEST_BRIDGED_HEADER.with(|h| *h.borrow_mut() = None); + target::verify_messages_proof::(proof, 10) + }), + Err(target::MessageProofError::HeaderChain(HeaderChainError::UnknownHeader)), + ); + } + + #[test] + fn message_proof_is_rejected_if_header_state_root_mismatches() { + assert_eq!( + using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { + TEST_BRIDGED_HEADER + .with(|h| h.borrow_mut().as_mut().unwrap().state_root = Default::default()); + target::verify_messages_proof::(proof, 10) + }), + Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageRootMismatch)), ); } #[test] fn message_proof_is_rejected_if_required_message_is_missing() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(10), + using_messages_proof( 10, - |_, _| Ok(TestMessageProofParser { - failing: false, - messages: 1..=5, - outbound_lane_data: None, - }), + None, + |n, m| if n != 5 { Some(m.encode()) } else { None }, + encode_lane_data, + |proof| target::verify_messages_proof::(proof, 10) ), Err(target::MessageProofError::MissingRequiredMessage), ); @@ -1539,14 +1360,19 @@ mod tests { #[test] fn message_proof_is_rejected_if_message_decode_fails() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(10), + using_messages_proof( 10, - |_, _| Ok(TestMessageProofParser { - failing: true, - messages: 1..=10, - outbound_lane_data: None, - }), + None, + |n, m| { + let mut m = m.encode(); + if n == 5 { + m = MessageData { fee: 0, payload: vec![0u8; 42] }.encode(); + m.truncate(2); + } + Some(m.encode()) + }, + encode_lane_data, + |proof| target::verify_messages_proof::(proof, 10), ), Err(target::MessageProofError::FailedToDecodeMessage), ); @@ -1555,18 +1381,20 @@ mod tests { #[test] fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(0), - 0, - |_, _| Ok(TestMessageProofParser { - failing: true, - messages: no_messages_range(), - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 1, - latest_received_nonce: 1, - latest_generated_nonce: 1, - }), + using_messages_proof( + 10, + Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, }), + encode_all_messages, + |d| { + let mut d = d.encode(); + d.truncate(1); + d + }, + |proof| target::verify_messages_proof::(proof, 10), ), Err(target::MessageProofError::FailedToDecodeOutboundLaneState), ); @@ -1575,15 +1403,9 @@ mod tests { #[test] fn message_proof_is_rejected_if_it_is_empty() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(0), - 0, - |_, _| Ok(TestMessageProofParser { - failing: false, - messages: no_messages_range(), - outbound_lane_data: None, - }), - ), + using_messages_proof(0, None, encode_all_messages, encode_lane_data, |proof| { + target::verify_messages_proof::(proof, 0) + },), Err(target::MessageProofError::Empty), ); } @@ -1591,21 +1413,19 @@ mod tests { #[test] fn non_empty_message_proof_without_messages_is_accepted() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(0), + using_messages_proof( 0, - |_, _| Ok(TestMessageProofParser { - failing: false, - messages: no_messages_range(), - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 1, - latest_received_nonce: 1, - latest_generated_nonce: 1, - }), + Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, }), + encode_all_messages, + encode_lane_data, + |proof| target::verify_messages_proof::(proof, 0), ), Ok(vec![( - Default::default(), + *TEST_LANE_ID, ProvedLaneMessages { lane_state: Some(OutboundLaneData { oldest_unpruned_nonce: 1, @@ -1623,21 +1443,19 @@ mod tests { #[test] fn non_empty_message_proof_is_accepted() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(1), + using_messages_proof( 1, - |_, _| Ok(TestMessageProofParser { - failing: false, - messages: 1..=1, - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 1, - latest_received_nonce: 1, - latest_generated_nonce: 1, - }), + Some(OutboundLaneData { + oldest_unpruned_nonce: 1, + latest_received_nonce: 1, + latest_generated_nonce: 1, }), + encode_all_messages, + encode_lane_data, + |proof| target::verify_messages_proof::(proof, 1), ), Ok(vec![( - Default::default(), + *TEST_LANE_ID, ProvedLaneMessages { lane_state: Some(OutboundLaneData { oldest_unpruned_nonce: 1, @@ -1645,8 +1463,8 @@ mod tests { latest_generated_nonce: 1, }), messages: vec![Message { - key: MessageKey { lane_id: Default::default(), nonce: 1 }, - data: MessageData { payload: 1u64.encode(), fee: BridgedChainBalance(0) }, + key: MessageKey { lane_id: *TEST_LANE_ID, nonce: 1 }, + data: MessageData { payload: vec![42], fee: 0 }, }], }, )] @@ -1656,21 +1474,12 @@ mod tests { } #[test] - fn verify_messages_proof_with_parser_does_not_panic_if_messages_count_mismatches() { + fn verify_messages_proof_does_not_panic_if_messages_count_mismatches() { assert_eq!( - target::verify_messages_proof_with_parser::( - messages_proof(u64::MAX), - 0, - |_, _| Ok(TestMessageProofParser { - failing: false, - messages: 0..=u64::MAX, - outbound_lane_data: Some(OutboundLaneData { - oldest_unpruned_nonce: 1, - latest_received_nonce: 1, - latest_generated_nonce: 1, - }), - }), - ), + using_messages_proof(1, None, encode_all_messages, encode_lane_data, |mut proof| { + proof.nonces_end = u64::MAX; + target::verify_messages_proof::(proof, u32::MAX) + },), Err(target::MessageProofError::MessagesCountMismatch), ); } diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 71eed881a063d..24df69dc90a5e 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -19,14 +19,18 @@ #![cfg(feature = "runtime-benchmarks")] -use crate::messages::{ - source::{FromBridgedChainMessagesDeliveryProof, FromThisChainMessagePayload}, - target::FromBridgedChainMessagesProof, - AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, RawStorageProof, - SignatureOf, SignerOf, ThisChain, +use crate::{ + messages::{ + source::{FromBridgedChainMessagesDeliveryProof, FromThisChainMessagePayload}, + target::FromBridgedChainMessagesProof, + AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, ThisChain, + }, + messages_generation::{ + encode_all_messages, encode_lane_data, grow_trie, prepare_messages_storage_proof, + }, }; -use bp_messages::{storage_keys, MessageData, MessageKey, MessagePayload}; +use bp_messages::storage_keys; use bp_runtime::{record_all_trie_keys, StorageProofSize}; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; @@ -34,7 +38,7 @@ use pallet_bridge_messages::benchmarking::{ MessageDeliveryProofParams, MessageParams, MessageProofParams, }; use sp_core::Hasher; -use sp_runtime::traits::{Header, IdentifyAccount, MaybeSerializeDeserialize, Zero}; +use sp_runtime::traits::{Header, MaybeSerializeDeserialize, Zero}; use sp_std::{fmt::Debug, prelude::*}; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; @@ -71,10 +75,6 @@ where BalanceOf>: Debug + MaybeSerializeDeserialize, CallOf>: From> + GetDispatchInfo, HashOf>: Copy + Default, - SignatureOf>: From, - SignerOf>: Clone - + From - + IdentifyAccount>>, { let message_payload = match params.size { StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], @@ -82,8 +82,15 @@ where }; // finally - prepare storage proof and update environment - let (state_root, storage_proof) = - prepare_messages_storage_proof::(¶ms, message_payload); + let (state_root, storage_proof) = prepare_messages_storage_proof::( + params.lane, + params.message_nonces.clone(), + params.outbound_lane_data, + params.size, + message_payload, + encode_all_messages, + encode_lane_data, + ); let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); ( @@ -141,69 +148,6 @@ where } } -/// Prepare storage proof of given messages. -/// -/// Returns state trie root and nodes with prepared messages. -fn prepare_messages_storage_proof( - params: &MessageProofParams, - message_payload: MessagePayload, -) -> (HashOf>, RawStorageProof) -where - B: MessageBridge, - BHH: Hasher>>, - HashOf>: Copy + Default, -{ - // prepare Bridged chain storage with messages and (optionally) outbound lane state - let message_count = - params.message_nonces.end().saturating_sub(*params.message_nonces.start()) + 1; - let mut storage_keys = Vec::with_capacity(message_count as usize + 1); - let mut root = Default::default(); - let mut mdb = MemoryDB::default(); - { - let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); - - // insert messages - for nonce in params.message_nonces.clone() { - let message_key = MessageKey { lane_id: params.lane, nonce }; - let message_data = MessageData { - fee: BalanceOf::>::from(0), - payload: message_payload.clone(), - }; - let storage_key = storage_keys::message_key( - B::BRIDGED_MESSAGES_PALLET_NAME, - &message_key.lane_id, - message_key.nonce, - ) - .0; - trie.insert(&storage_key, &message_data.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - storage_keys.push(storage_key); - } - - // insert outbound lane state - if let Some(ref outbound_lane_data) = params.outbound_lane_data { - let storage_key = - storage_keys::outbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, ¶ms.lane) - .0; - trie.insert(&storage_key, &outbound_lane_data.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - storage_keys.push(storage_key); - } - } - root = grow_trie(root, &mut mdb, params.size); - - // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - - (root, storage_proof) -} - /// Insert header to the bridge GRANDPA pallet. pub(crate) fn insert_header_to_grandpa_pallet( state_root: bp_runtime::HashOf, @@ -225,38 +169,3 @@ where pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); (bridged_block_number, bridged_header_hash) } - -/// Populate trie with dummy keys+values until trie has at least given size. -pub fn grow_trie( - mut root: H::Out, - mdb: &mut MemoryDB, - trie_size: StorageProofSize, -) -> H::Out { - let (iterations, leaf_size, minimal_trie_size) = match trie_size { - StorageProofSize::Minimal(_) => return root, - StorageProofSize::HasLargeLeaf(size) => (1, size, size), - StorageProofSize::HasExtraNodes(size) => (8, 1, size), - }; - - let mut key_index = 0; - loop { - // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); - if size > minimal_trie_size as _ { - return root - } - - let mut trie = TrieDBMutBuilderV1::::from_existing(mdb, &mut root).build(); - for _ in 0..iterations { - trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - key_index += 1; - } - trie.commit(); - } -} diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs new file mode 100644 index 0000000000000..822b635cc9b63 --- /dev/null +++ b/bin/runtime-common/src/messages_generation.rs @@ -0,0 +1,154 @@ +// Copyright 2019-2022 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 . + +//! Helpers for generating message storage proofs, that are used by tests and by benchmarks. + +#![cfg(any(feature = "runtime-benchmarks", test))] + +use crate::messages::{BalanceOf, BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof}; + +use bp_messages::{ + storage_keys, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, +}; +use bp_runtime::{record_all_trie_keys, StorageProofSize}; +use codec::Encode; +use sp_core::Hasher; +use sp_runtime::traits::Zero; +use sp_std::{ops::RangeInclusive, prelude::*}; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; + +/// Simple and correct message data encode function. +pub(crate) fn encode_all_messages( + _: MessageNonce, + m: &MessageData, +) -> Option> { + Some(m.encode()) +} + +/// Simple and correct outbound lane data encode function. +pub(crate) fn encode_lane_data(d: &OutboundLaneData) -> Vec { + d.encode() +} + +/// Prepare storage proof of given messages. +/// +/// Returns state trie root and nodes with prepared messages. +pub(crate) fn prepare_messages_storage_proof( + lane: LaneId, + message_nonces: RangeInclusive, + outbound_lane_data: Option, + size: StorageProofSize, + message_payload: MessagePayload, + encode_message: impl Fn(MessageNonce, &MessageData>>) -> Option>, + encode_outbound_lane_data: impl Fn(&OutboundLaneData) -> Vec, +) -> (HashOf>, RawStorageProof) +where + B: MessageBridge, + HashOf>: Copy + Default, +{ + // prepare Bridged chain storage with messages and (optionally) outbound lane state + let message_count = message_nonces.end().saturating_sub(*message_nonces.start()) + 1; + let mut storage_keys = Vec::with_capacity(message_count as usize + 1); + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = + TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); + + // insert messages + for nonce in message_nonces { + let message_key = MessageKey { lane_id: lane, nonce }; + let message_data = MessageData { + fee: BalanceOf::>::zero(), + payload: message_payload.clone(), + }; + let message_data = match encode_message(nonce, &message_data) { + Some(message_data) => message_data, + None => continue, + }; + let storage_key = storage_keys::message_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &message_key.lane_id, + message_key.nonce, + ) + .0; + trie.insert(&storage_key, &message_data) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + + // insert outbound lane state + if let Some(outbound_lane_data) = outbound_lane_data.as_ref().map(encode_outbound_lane_data) + { + let storage_key = + storage_keys::outbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane).0; + trie.insert(&storage_key, &outbound_lane_data) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + storage_keys.push(storage_key); + } + } + root = grow_trie(root, &mut mdb, size); + + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::>>>::new(); + record_all_trie_keys::>>, _>( + &mdb, + &root, + &mut proof_recorder, + ) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); + let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + + (root, storage_proof) +} + +/// Populate trie with dummy keys+values until trie has at least given size. +pub fn grow_trie( + mut root: H::Out, + mdb: &mut MemoryDB, + trie_size: StorageProofSize, +) -> H::Out { + let (iterations, leaf_size, minimal_trie_size) = match trie_size { + StorageProofSize::Minimal(_) => return root, + StorageProofSize::HasLargeLeaf(size) => (1, size, size), + StorageProofSize::HasExtraNodes(size) => (8, 1, size), + }; + + let mut key_index = 0; + loop { + // generate storage proof to be delivered to This chain + let mut proof_recorder = Recorder::>::new(); + record_all_trie_keys::, _>(mdb, &root, &mut proof_recorder) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); + let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); + if size > minimal_trie_size as _ { + return root + } + + let mut trie = TrieDBMutBuilderV1::::from_existing(mdb, &mut root).build(); + for _ in 0..iterations { + trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + key_index += 1; + } + trie.commit(); + } +} diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index 59e2ef6962c83..fcd32ea28b86e 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -18,7 +18,9 @@ #![cfg(feature = "runtime-benchmarks")] -use crate::messages_benchmarking::{grow_trie, insert_header_to_grandpa_pallet}; +use crate::{ + messages_benchmarking::insert_header_to_grandpa_pallet, messages_generation::grow_trie, +}; use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index e061b702a11e0..2402b2512e27c 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -38,7 +38,7 @@ use storage_types::StoredAuthoritySet; -use bp_header_chain::{justification::GrandpaJustification, InitializationData}; +use bp_header_chain::{justification::GrandpaJustification, HeaderChain, InitializationData}; use bp_runtime::{ BlockNumberOf, BoundedStorageValue, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule, }; @@ -67,6 +67,8 @@ pub use weights::WeightInfo; /// The target that will be used when publishing logs related to this pallet. pub const LOG_TARGET: &str = "runtime::bridge-grandpa"; +/// Bridged chain from the pallet configuration. +pub type BridgedChain = >::BridgedChain; /// Block number of the bridged chain. pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; /// Block hash of the bridged chain. @@ -382,8 +384,6 @@ pub mod pallet { TooManyRequests, /// The header being imported is older than the best finalized header known to the pallet. OldHeader, - /// The header is unknown to the pallet. - UnknownHeader, /// The scheduled authority set change found in the header is unsupported by the pallet. /// /// This is the case for non-standard (e.g forced) authority set changes. @@ -392,8 +392,6 @@ pub mod pallet { NotInitialized, /// The pallet has already been initialized. AlreadyInitialized, - /// The storage proof doesn't contains storage root. So it is invalid for given header. - StorageRootMismatch, /// Too many authorities in the set. TooManyAuthoritiesInSet, /// Too large header. @@ -581,9 +579,6 @@ pub mod pallet { impl, I: 'static> Pallet { /// Get the best finalized header the pallet knows of. - /// - /// Returns a dummy header if there is no best header. This can only happen - /// if the pallet has not been initialized yet. pub fn best_finalized() -> Option> { let (_, hash) = >::get()?; >::get(hash).map(|h| h.into_inner()) @@ -593,21 +588,14 @@ impl, I: 'static> Pallet { pub fn is_known_header(hash: BridgedBlockHash) -> bool { >::contains_key(hash) } +} - /// Verify that the passed storage proof is valid, given it is crafted using - /// known finalized header. If the proof is valid, then the `parse` callback - /// is called and the function returns its result. - pub fn parse_finalized_storage_proof( - hash: BridgedBlockHash, - storage_proof: sp_trie::StorageProof, - parse: impl FnOnce(bp_runtime::StorageProofChecker>) -> R, - ) -> Result { - let header = >::get(hash).ok_or(Error::::UnknownHeader)?; - let storage_proof_checker = - bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) - .map_err(|_| Error::::StorageRootMismatch)?; - - Ok(parse(storage_proof_checker)) +/// Bridge GRANDPA pallet as header chain. +pub type GrandpaChainHeaders = Pallet; + +impl, I: 'static> HeaderChain> for GrandpaChainHeaders { + fn finalized_header(hash: HashOf>) -> Option>> { + ImportedHeaders::::get(hash).map(|h| h.into_inner()) } } @@ -1119,7 +1107,7 @@ mod tests { sp_trie::StorageProof::new(vec![]), |_| (), ), - Error::::UnknownHeader, + bp_header_chain::HeaderChainError::UnknownHeader, ); }); } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index bccd16f3d593d..ce674459eacfc 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -12,6 +12,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" # Bridge Dependencies +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } @@ -34,6 +35,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 4b2be1b71707f..e6625476a3de0 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -26,12 +26,14 @@ pub use weights::WeightInfo; pub use weights_ext::WeightInfoExt; +use bp_header_chain::HeaderChain; use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo}; -use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId}; -use bp_runtime::StorageProofError; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use bp_runtime::{HashOf, HeaderOf, Parachain, StorageProofError}; +use codec::Decode; use frame_support::{dispatch::PostDispatchInfo, traits::Contains}; use sp_runtime::traits::Header as HeaderT; -use sp_std::vec::Vec; +use sp_std::{marker::PhantomData, vec::Vec}; // Re-export in crate namespace for `construct_runtime!`. pub use pallet::*; @@ -410,27 +412,6 @@ pub mod pallet { ImportedParaHeads::::get(parachain, hash).map(|h| h.into_inner()) } - /// Verify that the passed storage proof is valid, given it is crafted using - /// known finalized header. If the proof is valid, then the `parse` callback - /// is called and the function returns its result. - pub fn parse_finalized_storage_proof( - parachain: ParaId, - hash: ParaHash, - storage_proof: sp_trie::StorageProof, - decode_state_root: impl FnOnce(ParaHead) -> Option, - parse: impl FnOnce(bp_runtime::StorageProofChecker) -> R, - ) -> Result { - let para_head = - Self::parachain_head(parachain, hash).ok_or(Error::::UnknownParaHead)?; - let state_root = - decode_state_root(para_head).ok_or(Error::::FailedToExtractStateRoot)?; - let storage_proof_checker = - bp_runtime::StorageProofChecker::new(state_root, storage_proof) - .map_err(|_| Error::::StorageRootMismatch)?; - - Ok(parse(storage_proof_checker)) - } - /// Read parachain head from storage proof. fn read_parachain_head( storage: &bp_runtime::StorageProofChecker, @@ -617,6 +598,18 @@ pub mod pallet { } } +/// Single parachain header chain adapter. +pub struct ParachainHeaders(PhantomData<(T, I, C)>); + +impl, I: 'static, C: Parachain> HeaderChain + for ParachainHeaders +{ + fn finalized_header(hash: HashOf) -> Option> { + Pallet::::parachain_head(ParaId(C::PARACHAIN_ID), hash) + .and_then(|head| Decode::decode(&mut &head.0[..]).ok()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 3a54a2fb54805..584882425b4db 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -21,7 +21,7 @@ use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{decl_bridge_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_runtime_apis, Chain, Parachain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, @@ -160,6 +160,10 @@ impl Chain for RialtoParachain { } } +impl Parachain for RialtoParachain { + const PARACHAIN_ID: u32 = RIALTO_PARACHAIN_ID; +} + frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index be87cce460e38..3b7ea58cb96a7 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -23,6 +23,7 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", sp-finality-grandpa = { 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-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] bp-test-utils = { path = "../test-utils" } @@ -42,4 +43,5 @@ std = [ "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", + "sp-trie/std", ] diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 21a42874b719d..2b4e0802a5a70 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,19 +19,58 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_runtime::BasicOperatingMode; +use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker}; use codec::{Codec, Decode, Encode, EncodeLike}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; +use frame_support::PalletError; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; use sp_std::boxed::Box; +use sp_trie::StorageProof; pub mod justification; pub mod storage_keys; +/// Header chain error. +#[derive(Clone, Copy, Decode, Encode, Eq, PalletError, PartialEq, RuntimeDebug, TypeInfo)] +pub enum HeaderChainError { + /// Header with given hash is missing from the chain. + UnknownHeader, + /// The storage proof doesn't contains storage root. + StorageRootMismatch, +} + +impl From for &'static str { + fn from(err: HeaderChainError) -> &'static str { + match err { + HeaderChainError::UnknownHeader => "UnknownHeader", + HeaderChainError::StorageRootMismatch => "StorageRootMismatch", + } + } +} + +/// Substrate header chain, abstracted from the way it is stored. +pub trait HeaderChain { + /// Returns finalized header by its hash. + fn finalized_header(hash: HashOf) -> Option>; + /// Parse storage proof using finalized header. + fn parse_finalized_storage_proof( + hash: HashOf, + storage_proof: StorageProof, + parse: impl FnOnce(StorageProofChecker>) -> R, + ) -> Result { + let header = Self::finalized_header(hash).ok_or(HeaderChainError::UnknownHeader)?; + let storage_proof_checker = + bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) + .map_err(|_| HeaderChainError::StorageRootMismatch)?; + + Ok(parse(storage_proof_checker)) + } +} + /// A type that can be used as a parameter in a dispatchable function. /// /// When using `decl_module` all arguments for call functions must implement this trait. @@ -79,6 +118,7 @@ pub trait FinalityProof: Clone + Send + Sync + Debug { /// A trait that provides helper methods for querying the consensus log. pub trait ConsensusLogReader { + /// Returns true if digest contains item that schedules authorities set change. fn schedules_authorities_change(digest: &Digest) -> bool; } diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index be95f17480d01..6f43c0f354900 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -195,6 +195,12 @@ pub trait Chain: Send + Sync + 'static { fn max_extrinsic_weight() -> Weight; } +/// Minimal parachain representation that may be used from no_std environment. +pub trait Parachain: Chain { + /// Parachain identifier. + const PARACHAIN_ID: u32; +} + /// Block number used by the chain. pub type BlockNumberOf = ::BlockNumber; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 9f525f5ea8563..83043f80621f6 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -32,7 +32,7 @@ use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, - HasherOf, HeaderOf, IndexOf, SignatureOf, TransactionEraOf, + HasherOf, HeaderOf, IndexOf, Parachain, SignatureOf, TransactionEraOf, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedSub, One}; From 515870563e454ebedae59324e5a18367863649d5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 14 Nov 2022 14:33:54 +0300 Subject: [PATCH 0805/1210] rename ChainWithMessages -> UnderlyingChainProvider (#1639) --- bin/millau/runtime/src/rialto_messages.rs | 4 ++-- .../runtime/src/rialto_parachain_messages.rs | 4 ++-- .../runtime/src/millau_messages.rs | 4 ++-- bin/rialto/runtime/src/millau_messages.rs | 4 ++-- bin/runtime-common/src/messages.rs | 24 +++++++++---------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index c989de67b1763..c6bc308a8e819 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -116,7 +116,7 @@ impl MessageBridge for WithRialtoMessageBridge { #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; -impl messages::ChainWithMessages for Millau { +impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } @@ -174,7 +174,7 @@ impl messages::ThisChainWithMessages for Millau { #[derive(RuntimeDebug, Clone, Copy)] pub struct Rialto; -impl messages::ChainWithMessages for Rialto { +impl messages::UnderlyingChainProvider for Rialto { type Chain = bp_rialto::Rialto; } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 70e8db89d3a27..da4ca9d83cb2e 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -123,7 +123,7 @@ impl MessageBridge for WithRialtoParachainMessageBridge { #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; -impl messages::ChainWithMessages for Millau { +impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } @@ -165,7 +165,7 @@ impl messages::ThisChainWithMessages for Millau { #[derive(RuntimeDebug, Clone, Copy)] pub struct RialtoParachain; -impl messages::ChainWithMessages for RialtoParachain { +impl messages::UnderlyingChainProvider for RialtoParachain { type Chain = bp_rialto_parachain::RialtoParachain; } diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index a13a17a1ea281..60bc038339620 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -120,7 +120,7 @@ impl MessageBridge for WithMillauMessageBridge { #[derive(RuntimeDebug, Clone, Copy)] pub struct RialtoParachain; -impl messages::ChainWithMessages for RialtoParachain { +impl messages::UnderlyingChainProvider for RialtoParachain { type Chain = bp_rialto_parachain::RialtoParachain; } @@ -181,7 +181,7 @@ impl messages::ThisChainWithMessages for RialtoParachain { #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; -impl messages::ChainWithMessages for Millau { +impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index b27cce40074aa..cf8812eaf9a69 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -114,7 +114,7 @@ impl MessageBridge for WithMillauMessageBridge { #[derive(RuntimeDebug, Clone, Copy)] pub struct Rialto; -impl messages::ChainWithMessages for Rialto { +impl messages::UnderlyingChainProvider for Rialto { type Chain = bp_rialto::Rialto; } @@ -172,7 +172,7 @@ impl messages::ThisChainWithMessages for Rialto { #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; -impl messages::ChainWithMessages for Millau { +impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 75c3ec6e57f30..320b91539b945 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -58,7 +58,7 @@ pub trait MessageBridge { /// Bridged chain in context of message bridge. type BridgedChain: BridgedChainWithMessages; /// Bridged header chain. - type BridgedHeaderChain: HeaderChain<::Chain>; + type BridgedHeaderChain: HeaderChain>; /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance( @@ -115,14 +115,14 @@ impl< } } -/// Chain that has `pallet-bridge-messages` module. -pub trait ChainWithMessages { +/// A trait that provides the type of the underlying chain. +pub trait UnderlyingChainProvider { /// Underlying chain type. type Chain: Chain; } /// This chain that has `pallet-bridge-messages` module. -pub trait ThisChainWithMessages: ChainWithMessages { +pub trait ThisChainWithMessages: UnderlyingChainProvider { /// Call origin on the chain. type RuntimeOrigin; /// Call type on the chain. @@ -149,7 +149,7 @@ pub trait ThisChainWithMessages: ChainWithMessages { } /// Bridged chain that has `pallet-bridge-messages` module. -pub trait BridgedChainWithMessages: ChainWithMessages { +pub trait BridgedChainWithMessages: UnderlyingChainProvider { /// Returns `true` if message dispatch weight is withing expected limits. `false` means /// that the message is too heavy to be sent over the bridge and shall be rejected. fn verify_dispatch_weight(message_payload: &[u8]) -> bool; @@ -171,15 +171,15 @@ pub type ThisChain = ::ThisChain; /// Bridged chain in context of message bridge. pub type BridgedChain = ::BridgedChain; /// Underlying chain type. -pub type UnderlyingChainOf = ::Chain; +pub type UnderlyingChainOf = ::Chain; /// Hash used on the chain. -pub type HashOf = bp_runtime::HashOf<::Chain>; +pub type HashOf = bp_runtime::HashOf<::Chain>; /// Hasher used on the chain. -pub type HasherOf = bp_runtime::HasherOf<::Chain>; +pub type HasherOf = bp_runtime::HasherOf>; /// Account id used on the chain. -pub type AccountIdOf = bp_runtime::AccountIdOf<::Chain>; +pub type AccountIdOf = bp_runtime::AccountIdOf>; /// Type of balances that is used on the chain. -pub type BalanceOf = bp_runtime::BalanceOf<::Chain>; +pub type BalanceOf = bp_runtime::BalanceOf>; /// Type of origin that is used on the chain. pub type OriginOf = ::RuntimeOrigin; /// Type of call that is used on this chain. @@ -996,7 +996,7 @@ mod tests { struct ThisChain; - impl ChainWithMessages for ThisChain { + impl UnderlyingChainProvider for ThisChain { type Chain = ThisUnderlyingChain; } @@ -1071,7 +1071,7 @@ mod tests { struct BridgedChain; - impl ChainWithMessages for BridgedChain { + impl UnderlyingChainProvider for BridgedChain { type Chain = BridgedUnderlyingChain; } From d841826a0c5a93c2911e8834a21b3a6f59fce987 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 14 Nov 2022 16:39:47 +0100 Subject: [PATCH 0806/1210] Rococo/Wococo bridge hub relay integration (#1565) * [BridgeHub] Added bridge-hub-rococo/wococo clients with bridge-hub-rococo-runtime * [BridgeHub] Add init-bridge stuff for bridge-hub-rococo/wococo * [BridgeHub] Add init-bridge stuff for bridge-hub-rococo/wococo * [BridgeHub] Fixed Call-encoding for init-bridge rococo runtime wrapper * Final index update to runtime calls * [BridgeHub] Add init-bridge stuff for bridge-hub-rococo/wococo (otherside) * Added runtime best_finalized functions + relay-headers init * Renaming and change BridgeHubRococo/Wococo to Rococo/Wococo config * [BridgeHub] Add relay-parachains (Rococo/Wococo) * Missing stuff for adding xcm messaging to BridgeHub * extracted parachain IDs to the primitives * fix compilation * Fixes * Init setup for Rococo->Wococo messaging support * Removed unused AccountId from `trait MessagesBridge` * Removed unused trait SenderOrigin * Small fixes * Cleaning after master-merge * Fixes * Fixes * Fixes * Fixes * Fixes: - align WeightToFee with BridgeHubRococo runtime - MAX_HEADER_SIZE - updated TODOs * Added relay_messages cfg for BridgeHubWococo -> BridgeHubRococo Co-authored-by: Svyatoslav Nikolsky --- primitives/chain-bridge-hub-rococo/Cargo.toml | 37 +++ primitives/chain-bridge-hub-rococo/src/lib.rs | 75 ++++++ primitives/chain-bridge-hub-wococo/Cargo.toml | 32 +++ primitives/chain-bridge-hub-wococo/src/lib.rs | 49 ++++ primitives/chain-rococo/Cargo.toml | 2 + primitives/chain-rococo/src/lib.rs | 23 ++ primitives/chain-wococo/Cargo.toml | 2 + primitives/chain-wococo/src/lib.rs | 4 + primitives/runtime/src/lib.rs | 6 + relays/bin-substrate/Cargo.toml | 9 + ...ub_rococo_messages_to_bridge_hub_wococo.rs | 78 +++++++ ...ub_wococo_messages_to_bridge_hub_rococo.rs | 78 +++++++ relays/bin-substrate/src/chains/mod.rs | 8 + relays/bin-substrate/src/chains/rococo.rs | 42 ++++ .../rococo_headers_to_bridge_hub_wococo.rs | 53 +++++ .../rococo_parachains_to_bridge_hub_wococo.rs | 78 +++++++ relays/bin-substrate/src/chains/wococo.rs | 42 ++++ .../wococo_headers_to_bridge_hub_rococo.rs | 53 +++++ .../wococo_parachains_to_bridge_hub_rococo.rs | 78 +++++++ relays/bin-substrate/src/cli/bridge.rs | 4 + relays/bin-substrate/src/cli/estimate_fee.rs | 3 + relays/bin-substrate/src/cli/init_bridge.rs | 32 +++ relays/bin-substrate/src/cli/relay_headers.rs | 10 + .../bin-substrate/src/cli/relay_messages.rs | 8 + .../bin-substrate/src/cli/relay_parachains.rs | 20 +- relays/bin-substrate/src/cli/send_message.rs | 6 + relays/client-bridge-hub-rococo/Cargo.toml | 29 +++ relays/client-bridge-hub-rococo/src/lib.rs | 168 ++++++++++++++ .../src/runtime_wrapper.rs | 219 ++++++++++++++++++ relays/client-bridge-hub-wococo/Cargo.toml | 22 ++ relays/client-bridge-hub-wococo/src/lib.rs | 168 ++++++++++++++ .../src/runtime_wrapper.rs | 28 +++ relays/client-rococo/src/lib.rs | 7 +- relays/client-wococo/src/lib.rs | 7 +- 34 files changed, 1476 insertions(+), 4 deletions(-) create mode 100644 primitives/chain-bridge-hub-rococo/Cargo.toml create mode 100644 primitives/chain-bridge-hub-rococo/src/lib.rs create mode 100644 primitives/chain-bridge-hub-wococo/Cargo.toml create mode 100644 primitives/chain-bridge-hub-wococo/src/lib.rs create mode 100644 relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs create mode 100644 relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs create mode 100644 relays/bin-substrate/src/chains/rococo.rs create mode 100644 relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs create mode 100644 relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs create mode 100644 relays/bin-substrate/src/chains/wococo.rs create mode 100644 relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs create mode 100644 relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs create mode 100644 relays/client-bridge-hub-rococo/Cargo.toml create mode 100644 relays/client-bridge-hub-rococo/src/lib.rs create mode 100644 relays/client-bridge-hub-rococo/src/runtime_wrapper.rs create mode 100644 relays/client-bridge-hub-wococo/Cargo.toml create mode 100644 relays/client-bridge-hub-wococo/src/lib.rs create mode 100644 relays/client-bridge-hub-wococo/src/runtime_wrapper.rs diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml new file mode 100644 index 0000000000000..51bc88baf0e62 --- /dev/null +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "bp-bridge-hub-rococo" +description = "Primitives of BridgeHubRococo parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +smallvec = "1.10.0" + +# Bridge Dependencies + +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +# Polkadot Dependencies +polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } + +[features] +default = ["std"] +std = [ + "bp-polkadot-core/std", + "bp-messages/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-std/std", + "polkadot-runtime-constants/std", +] diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs new file mode 100644 index 0000000000000..32e8eb646a342 --- /dev/null +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -0,0 +1,75 @@ +// 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 . + +//! Module with configuration which reflects BridgeHubRococo runtime setup (AccountId, Headers, +//! Hashes...) + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_messages::*; +pub use bp_polkadot_core::*; +use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis}; +use frame_support::{ + parameter_types, + sp_runtime::{FixedU128, MultiAddress, MultiSigner}, + weights::{ + constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }, + Parameter, +}; +use sp_std::prelude::*; + +pub type BridgeHubRococo = PolkadotLike; + +/// [`WeightToFee`] should reflect cumulus/bridge-hub-rococo-runtime [`WeightToFee`] +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + pub const CENTS: Balance = polkadot_runtime_constants::currency::CENTS; + + // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // in BridgeHub, we map to 1/10 of that, or 1/100 CENT + let p = CENTS; + let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec::smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// The address format for describing accounts. +pub type Address = MultiAddress; + +/// Identifier of BridgeHubRococo in the Rococo relay chain. +pub const BRIDGE_HUB_ROCOCO_PARACHAIN_ID: u32 = 1013; + +/// Name of the With-BridgeHubRococo messages pallet instance that is deployed at bridged chains. +pub const WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; + +parameter_types! { + pub const SS58Prefix: u16 = 42; +} + +decl_bridge_finality_runtime_apis!(bridge_hub_rococo); +decl_bridge_messages_runtime_apis!(bridge_hub_rococo); diff --git a/primitives/chain-bridge-hub-wococo/Cargo.toml b/primitives/chain-bridge-hub-wococo/Cargo.toml new file mode 100644 index 0000000000000..94ac501fbd531 --- /dev/null +++ b/primitives/chain-bridge-hub-wococo/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "bp-bridge-hub-wococo" +description = "Primitives of BridgeHubWococo parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-bridge-hub-rococo = { path = "../chain-bridge-hub-rococo", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-runtime/std", + "bp-messages/std", + "frame-support/std", + "sp-api/std", + "sp-std/std", + "bp-bridge-hub-rococo/std", +] diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs new file mode 100644 index 0000000000000..93f0d78dfd857 --- /dev/null +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -0,0 +1,49 @@ +// 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 . + +//! Module with configuration which reflects BridgeHubWococo runtime setup +//! (AccountId, Headers, Hashes...) +//! +//! but actually this is just reexported BridgeHubRococo stuff, because they are supposed to be +//! identical, at least uses the same parachain runtime + +#![cfg_attr(not(feature = "std"), no_std)] + +// Re-export only what is really needed +pub use bp_bridge_hub_rococo::{ + account_info_storage_key, AccountId, AccountPublic, AccountSigner, Address, Balance, + BlockNumber, Hash, Hashing, Header, Nonce, SS58Prefix, Signature, SignedBlock, + SignedExtensions, UncheckedExtrinsic, WeightToFee, ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, + DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, EXTRA_STORAGE_PROOF_SIZE, + MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + PAY_INBOUND_DISPATCH_FEE_WEIGHT, TX_EXTRA_BYTES, +}; +use bp_messages::*; +use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis}; +use frame_support::{sp_runtime::FixedU128, Parameter}; +use sp_std::prelude::*; + +pub type BridgeHubWococo = bp_bridge_hub_rococo::BridgeHubRococo; + +/// Identifier of BridgeHubWococo in the Wococo relay chain. +pub const BRIDGE_HUB_WOCOCO_PARACHAIN_ID: u32 = 1013; + +/// Name of the With-BridgeHubWococo messages pallet instance that is deployed at bridged chains. +pub const WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; + +decl_bridge_finality_runtime_apis!(bridge_hub_wococo); +decl_bridge_messages_runtime_apis!(bridge_hub_wococo); diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 65d3f502db446..73a2450cd17d7 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -14,6 +14,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -21,4 +22,5 @@ std = [ "bp-polkadot-core/std", "bp-runtime/std", "sp-api/std", + "frame-support/std", ] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index dd5be65dd866b..6fd7228fd75e5 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -20,11 +20,34 @@ pub use bp_polkadot_core::*; use bp_runtime::decl_bridge_finality_runtime_apis; +use frame_support::parameter_types; /// Rococo Chain pub type Rococo = PolkadotLike; +parameter_types! { + pub const SS58Prefix: u8 = 42; +} + +/// Name of the parachains pallet in the Rococo runtime. +pub const PARAS_PALLET_NAME: &str = "Paras"; + /// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; +/// Maximal SCALE-encoded header size (in bytes) at Rococo. +/// +/// Let's assume that the largest header is header that enacts new authorities set with +/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have +/// some fixed reserve for other things (digest, block hash and number, ...) as well. +pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; + +/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet. +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; + +/// Maximal number of GRANDPA authorities at Rococo. +/// +/// Corresponds to the `MaxAuthorities` constant value from the Rococo runtime configuration. +pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; + decl_bridge_finality_runtime_apis!(rococo); diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 5a4c439e042a9..6b741cd4b73c6 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } +bp-rococo = { path = "../chain-rococo", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -20,5 +21,6 @@ default = ["std"] std = [ "bp-polkadot-core/std", "bp-runtime/std", + "bp-rococo/std", "sp-api/std", ] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index f3fe0196dc591..0436b03c0364e 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -19,6 +19,10 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; +pub use bp_rococo::{ + SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_HEADER_SIZE, MAX_NESTED_PARACHAIN_HEAD_SIZE, + PARAS_PALLET_NAME, +}; use bp_runtime::decl_bridge_finality_runtime_apis; /// Wococo Chain diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 83043f80621f6..75d75c2beff59 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -79,6 +79,12 @@ pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; /// Bridge-with-Wococo instance id. pub const WOCOCO_CHAIN_ID: ChainId = *b"woco"; +/// Bridge-with-BridgeHubRococo instance id. +pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro"; + +/// Bridge-with-BridgeHubWococo instance id. +pub const BRIDGE_HUB_WOCOCO_CHAIN_ID: ChainId = *b"bhwo"; + /// Call-dispatch module prefix. pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 90adaf7e6529c..c214471eb6bdf 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -20,14 +20,19 @@ strum = { version = "0.21.0", features = ["derive"] } # Bridge dependencies +bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } +bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } +bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } +bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bp-statemine = { path = "../../primitives/chain-statemine" } bp-westend = { path = "../../primitives/chain-westend" } +bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } @@ -37,10 +42,14 @@ parachains-relay = { path = "../parachains" } relay-millau-client = { path = "../client-millau" } relay-rialto-client = { path = "../client-rialto" } relay-rialto-parachain-client = { path = "../client-rialto-parachain" } +relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } +relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } +relay-rococo-client = { path = "../client-rococo" } relay-statemine-client = { path = "../client-statemine" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } +relay-wococo-client = { path = "../client-wococo" } rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } rialto-runtime = { path = "../../bin/rialto/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs new file mode 100644 index 0000000000000..915dd82969852 --- /dev/null +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -0,0 +1,78 @@ +// Copyright 2022 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 . + +//! BridgeHubRococo-to-BridgeHubWococo messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use bp_messages::Weight; +use messages_relay::relay_strategy::MixStrategy; +use relay_bridge_hub_rococo_client::BridgeHubRococo; +use relay_bridge_hub_wococo_client::BridgeHubWococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +pub struct BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { + type Source = BridgeHubRococo; + type Target = BridgeHubWococo; +} + +impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + "TODO: not needed now, used for send_message and estimate_fee CLI"; + type MessagesLane = BridgeHubRococoMessagesToBridgeHubWococoMessageLane; +} + +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + BridgeHubRococoMessagesToBridgeHubWococoMessageLane, + BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoMessages, + relay_bridge_hub_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + BridgeHubRococoMessagesToBridgeHubWococoMessageLane, + BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoMessages, + relay_bridge_hub_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof +); + +/// Description of BridgeHubRococo -> BridgeHubWococo messages bridge. +#[derive(Clone, Debug)] +pub struct BridgeHubRococoMessagesToBridgeHubWococoMessageLane; + +impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWococoMessageLane { + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + + type SourceChain = BridgeHubRococo; + type TargetChain = BridgeHubWococo; + + type ReceiveMessagesProofCallBuilder = + BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type TargetToSourceChainConversionRateUpdateBuilder = (); + + type RelayStrategy = MixStrategy; +} diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..179b9076ba72d --- /dev/null +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -0,0 +1,78 @@ +// Copyright 2022 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 . + +//! BridgeHubWococo-to-BridgeHubRococo messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use bp_messages::Weight; +use messages_relay::relay_strategy::MixStrategy; +use relay_bridge_hub_rococo_client::BridgeHubRococo; +use relay_bridge_hub_wococo_client::BridgeHubWococo; +use substrate_relay_helper::messages_lane::SubstrateMessageLane; + +pub struct BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { + type Source = BridgeHubWococo; + type Target = BridgeHubRococo; +} + +impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + "TODO: not needed now, used for send_message and estimate_fee CLI"; + type MessagesLane = BridgeHubWococoMessagesToBridgeHubRococoMessageLane; +} + +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + BridgeHubWococoMessagesToBridgeHubRococoMessageLane, + BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoMessages, + relay_bridge_hub_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + BridgeHubWococoMessagesToBridgeHubRococoMessageLane, + BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoMessages, + relay_bridge_hub_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof +); + +/// Description of BridgeHubWococo -> BridgeHubRococo messages bridge. +#[derive(Clone, Debug)] +pub struct BridgeHubWococoMessagesToBridgeHubRococoMessageLane; + +impl SubstrateMessageLane for BridgeHubWococoMessagesToBridgeHubRococoMessageLane { + const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; + + const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; + + const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; + + type SourceChain = BridgeHubWococo; + type TargetChain = BridgeHubRococo; + + type ReceiveMessagesProofCallBuilder = + BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type TargetToSourceChainConversionRateUpdateBuilder = (); + + type RelayStrategy = MixStrategy; +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 5d7171691bffb..6bd444cc3959f 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -16,6 +16,8 @@ //! Chain-specific relayer configuration. +pub mod bridge_hub_rococo_messages_to_bridge_hub_wococo; +pub mod bridge_hub_wococo_messages_to_bridge_hub_rococo; pub mod millau_headers_to_rialto; pub mod millau_headers_to_rialto_parachain; pub mod millau_messages_to_rialto; @@ -24,14 +26,20 @@ pub mod rialto_headers_to_millau; pub mod rialto_messages_to_millau; pub mod rialto_parachain_messages_to_millau; pub mod rialto_parachains_to_millau; +pub mod rococo_headers_to_bridge_hub_wococo; +pub mod rococo_parachains_to_bridge_hub_wococo; pub mod westend_headers_to_millau; pub mod westend_parachains_to_millau; +pub mod wococo_headers_to_bridge_hub_rococo; +pub mod wococo_parachains_to_bridge_hub_rococo; mod millau; mod rialto; mod rialto_parachain; +mod rococo; mod statemine; mod westend; +mod wococo; #[cfg(test)] mod tests { diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs new file mode 100644 index 0000000000000..6a99eab6cb385 --- /dev/null +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -0,0 +1,42 @@ +// Copyright 2022 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 . + +//! Rococo + Rococo parachains specification for CLI. + +use crate::cli::CliChain; +use relay_bridge_hub_rococo_client::BridgeHubRococo; +use relay_rococo_client::Rococo; +use sp_version::RuntimeVersion; + +impl CliChain for Rococo { + const RUNTIME_VERSION: Option = None; + + type KeyPair = sp_core::sr25519::Pair; + + fn ss58_format() -> u16 { + bp_rococo::SS58Prefix::get() as u16 + } +} + +impl CliChain for BridgeHubRococo { + const RUNTIME_VERSION: Option = None; + + type KeyPair = sp_core::sr25519::Pair; + + fn ss58_format() -> u16 { + relay_bridge_hub_rococo_client::runtime::SS58Prefix::get() + } +} diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs new file mode 100644 index 0000000000000..2ec13614a34a1 --- /dev/null +++ b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs @@ -0,0 +1,53 @@ +// Copyright 2022 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 . + +//! Rococo-to-Wococo bridge hubs headers sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; +use substrate_relay_helper::finality::{ + engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, +}; + +/// Description of Rococo -> Wococo finalized headers bridge. +#[derive(Clone, Debug)] +pub struct RococoFinalityToBridgeHubWococo; + +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + RococoFinalityToBridgeHubWococo, + RococoFinalityToBridgeHubWococoCallBuilder, + relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa, + relay_bridge_hub_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof +); + +impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { + type SourceChain = relay_rococo_client::Rococo; + type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; + + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = RococoFinalityToBridgeHubWococoCallBuilder; +} + +/// `Rococo` to BridgeHub `Wococo` bridge definition. +pub struct RococoToBridgeHubWococoCliBridge {} + +impl CliBridgeBase for RococoToBridgeHubWococoCliBridge { + type Source = relay_rococo_client::Rococo; + type Target = relay_bridge_hub_wococo_client::BridgeHubWococo; +} + +impl RelayToRelayHeadersCliBridge for RococoToBridgeHubWococoCliBridge { + type Finality = RococoFinalityToBridgeHubWococo; +} diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs new file mode 100644 index 0000000000000..509cbf70db160 --- /dev/null +++ b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs @@ -0,0 +1,78 @@ +// 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 . + +//! Wococo-to-Rococo parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use parachains_relay::ParachainsPipeline; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::parachains::{ + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// BridgeHub-to-BridgeHub parachain sync description. +#[derive(Clone, Debug)] +pub struct BridgeHubRococoToBridgeHubWococo; + +impl ParachainsPipeline for BridgeHubRococoToBridgeHubWococo { + type SourceChain = relay_rococo_client::Rococo; + type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; +} + +impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWococo { + type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo; + type SourceRelayChain = relay_rococo_client::Rococo; + type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; + + type SubmitParachainHeadsCallBuilder = BridgeHubRococoToBridgeHubWococoCallBuilder; + + const SOURCE_PARACHAIN_PARA_ID: u32 = bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID; +} + +pub struct BridgeHubRococoToBridgeHubWococoCallBuilder; +impl SubmitParachainHeadsCallBuilder + for BridgeHubRococoToBridgeHubWococoCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoParachain( + relay_bridge_hub_wococo_client::runtime::BridgeParachainCall::submit_parachain_heads( + (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + ), + ) + } +} + +/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. +pub struct BridgeHubRococoToBridgeHubWococoCliBridge {} + +impl ParachainToRelayHeadersCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge { + type SourceRelay = relay_rococo_client::Rococo; + type ParachainFinality = BridgeHubRococoToBridgeHubWococo; + type RelayFinality = + crate::chains::rococo_headers_to_bridge_hub_wococo::RococoFinalityToBridgeHubWococo; +} + +impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge { + type Source = relay_bridge_hub_rococo_client::BridgeHubRococo; + type Target = relay_bridge_hub_wococo_client::BridgeHubWococo; +} diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs new file mode 100644 index 0000000000000..c44f3ac811f3f --- /dev/null +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -0,0 +1,42 @@ +// Copyright 2022 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 . + +//! Wococo + Wococo parachains specification for CLI. + +use crate::cli::CliChain; +use relay_bridge_hub_wococo_client::BridgeHubWococo; +use relay_wococo_client::Wococo; +use sp_version::RuntimeVersion; + +impl CliChain for Wococo { + const RUNTIME_VERSION: Option = None; + + type KeyPair = sp_core::sr25519::Pair; + + fn ss58_format() -> u16 { + bp_wococo::SS58Prefix::get() as u16 + } +} + +impl CliChain for BridgeHubWococo { + const RUNTIME_VERSION: Option = None; + + type KeyPair = sp_core::sr25519::Pair; + + fn ss58_format() -> u16 { + relay_bridge_hub_wococo_client::runtime::SS58Prefix::get() + } +} diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..30d6af00cd3b3 --- /dev/null +++ b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs @@ -0,0 +1,53 @@ +// Copyright 2022 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 . + +//! Wococo-to-Rococo bridge hubs headers sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; +use substrate_relay_helper::finality::{ + engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, +}; + +/// Description of Wococo -> Rococo finalized headers bridge. +#[derive(Clone, Debug)] +pub struct WococoFinalityToBridgeHubRococo; + +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + WococoFinalityToBridgeHubRococo, + WococoFinalityToBridgeHubRococoCallBuilder, + relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoGrandpa, + relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::submit_finality_proof +); + +impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { + type SourceChain = relay_wococo_client::Wococo; + type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; + + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = WococoFinalityToBridgeHubRococoCallBuilder; +} + +/// `Wococo` to BridgeHub `Rococo` bridge definition. +pub struct WococoToBridgeHubRococoCliBridge {} + +impl CliBridgeBase for WococoToBridgeHubRococoCliBridge { + type Source = relay_wococo_client::Wococo; + type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; +} + +impl RelayToRelayHeadersCliBridge for WococoToBridgeHubRococoCliBridge { + type Finality = WococoFinalityToBridgeHubRococo; +} diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..d4fbf095df480 --- /dev/null +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -0,0 +1,78 @@ +// 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 . + +//! Rococo-to-Wococo parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use parachains_relay::ParachainsPipeline; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::parachains::{ + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// BridgeHub-to-BridgeHub parachain sync description. +#[derive(Clone, Debug)] +pub struct BridgeHubWococoToBridgeHubRococo; + +impl ParachainsPipeline for BridgeHubWococoToBridgeHubRococo { + type SourceChain = relay_wococo_client::Wococo; + type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; +} + +impl SubstrateParachainsPipeline for BridgeHubWococoToBridgeHubRococo { + type SourceParachain = relay_bridge_hub_wococo_client::BridgeHubWococo; + type SourceRelayChain = relay_wococo_client::Wococo; + type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; + + type SubmitParachainHeadsCallBuilder = BridgeHubWococoToBridgeHubRococoCallBuilder; + + const SOURCE_PARACHAIN_PARA_ID: u32 = bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID; +} + +pub struct BridgeHubWococoToBridgeHubRococoCallBuilder; +impl SubmitParachainHeadsCallBuilder + for BridgeHubWococoToBridgeHubRococoCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoParachain( + relay_bridge_hub_rococo_client::runtime::BridgeParachainCall::submit_parachain_heads( + (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + ), + ) + } +} + +/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. +pub struct BridgeHubWococoToBridgeHubRococoCliBridge {} + +impl ParachainToRelayHeadersCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge { + type SourceRelay = relay_wococo_client::Wococo; + type ParachainFinality = BridgeHubWococoToBridgeHubRococo; + type RelayFinality = + crate::chains::wococo_headers_to_bridge_hub_rococo::WococoFinalityToBridgeHubRococo; +} + +impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge { + type Source = relay_bridge_hub_wococo_client::BridgeHubWococo; + type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index ffe4cc51e55c9..0bed036d91a9b 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -33,6 +33,8 @@ pub enum FullBridge { RialtoToMillau, MillauToRialtoParachain, RialtoParachainToMillau, + BridgeHubRococoToBridgeHubWococo, + BridgeHubWococoToBridgeHubRococo, } impl FullBridge { @@ -43,6 +45,8 @@ impl FullBridge { Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, + Self::BridgeHubRococoToBridgeHubWococo | Self::BridgeHubWococoToBridgeHubRococo => + unimplemented!("TODO: (bridge_instance_index) do we need it or refactor or remove?"), } } } diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs index 88823eec2f292..00a175187778c 100644 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/relays/bin-substrate/src/cli/estimate_fee.rs @@ -125,6 +125,9 @@ impl EstimateFee { MillauToRialtoParachainCliBridge::estimate_fee(self), FullBridge::RialtoParachainToMillau => RialtoParachainToMillauCliBridge::estimate_fee(self), + FullBridge::BridgeHubRococoToBridgeHubWococo | + FullBridge::BridgeHubWococoToBridgeHubRococo => + unimplemented!("TODO: (EstimateFee) do we need it or refactor or remove?"), } .await } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 218130dbe562e..54a3c74a4b6e2 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -21,7 +21,9 @@ use crate::{ millau_headers_to_rialto::MillauToRialtoCliBridge, millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, + rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, westend_headers_to_millau::WestendToMillauCliBridge, + wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, }, cli::{bridge::CliBridgeBase, chain_schema::*}, }; @@ -54,6 +56,8 @@ pub enum InitBridgeName { RialtoToMillau, WestendToMillau, MillauToRialtoParachain, + RococoToBridgeHubWococo, + WococoToBridgeHubRococo, } #[async_trait] @@ -163,6 +167,30 @@ impl BridgeInitializer for WestendToMillauCliBridge { } } +impl BridgeInitializer for RococoToBridgeHubWococoCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa( + relay_bridge_hub_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), + ) + } +} + +impl BridgeInitializer for WococoToBridgeHubRococoCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoGrandpa( + relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::initialize(init_data), + ) + } +} + impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { @@ -172,6 +200,10 @@ impl InitBridge { InitBridgeName::WestendToMillau => WestendToMillauCliBridge::init_bridge(self), InitBridgeName::MillauToRialtoParachain => MillauToRialtoParachainCliBridge::init_bridge(self), + InitBridgeName::RococoToBridgeHubWococo => + RococoToBridgeHubWococoCliBridge::init_bridge(self), + InitBridgeName::WococoToBridgeHubRococo => + WococoToBridgeHubRococoCliBridge::init_bridge(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index df6d96f7223e7..37b805d720b5d 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -24,7 +24,9 @@ use crate::chains::{ millau_headers_to_rialto::MillauToRialtoCliBridge, millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, + rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, westend_headers_to_millau::WestendToMillauCliBridge, + wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, }; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; @@ -59,6 +61,8 @@ pub enum RelayHeadersBridge { RialtoToMillau, WestendToMillau, MillauToRialtoParachain, + RococoToBridgeHubWococo, + WococoToBridgeHubRococo, } #[async_trait] @@ -102,6 +106,8 @@ impl HeadersRelayer for MillauToRialtoCliBridge {} impl HeadersRelayer for RialtoToMillauCliBridge {} impl HeadersRelayer for WestendToMillauCliBridge {} impl HeadersRelayer for MillauToRialtoParachainCliBridge {} +impl HeadersRelayer for RococoToBridgeHubWococoCliBridge {} +impl HeadersRelayer for WococoToBridgeHubRococoCliBridge {} impl RelayHeaders { /// Run the command. @@ -112,6 +118,10 @@ impl RelayHeaders { RelayHeadersBridge::WestendToMillau => WestendToMillauCliBridge::relay_headers(self), RelayHeadersBridge::MillauToRialtoParachain => MillauToRialtoParachainCliBridge::relay_headers(self), + RelayHeadersBridge::RococoToBridgeHubWococo => + RococoToBridgeHubWococoCliBridge::relay_headers(self), + RelayHeadersBridge::WococoToBridgeHubRococo => + WococoToBridgeHubRococoCliBridge::relay_headers(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index d03a1f97c3dd7..23f9bf0c113f7 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -20,6 +20,8 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use crate::chains::{ + bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge, + bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge, millau_headers_to_rialto::MillauToRialtoCliBridge, millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -119,6 +121,8 @@ impl MessagesRelayer for MillauToRialtoCliBridge {} impl MessagesRelayer for RialtoToMillauCliBridge {} impl MessagesRelayer for MillauToRialtoParachainCliBridge {} impl MessagesRelayer for RialtoParachainToMillauCliBridge {} +impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} +impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} impl RelayMessages { /// Run the command. @@ -130,6 +134,10 @@ impl RelayMessages { MillauToRialtoParachainCliBridge::relay_messages(self), FullBridge::RialtoParachainToMillau => RialtoParachainToMillauCliBridge::relay_messages(self), + FullBridge::BridgeHubRococoToBridgeHubWococo => + BridgeHubRococoToBridgeHubWococoMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubWococoToBridgeHubRococo => + BridgeHubWococoToBridgeHubRococoMessagesCliBridge::relay_messages(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 94b856019f95d..286cecc914bc3 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -16,7 +16,9 @@ use crate::chains::{ rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, westend_parachains_to_millau::WestmintToMillauCliBridge, + wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, }; use async_std::sync::Mutex; use async_trait::async_trait; @@ -29,7 +31,10 @@ use std::sync::Arc; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ - parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, + parachains::{ + source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter, + SubstrateParachainsPipeline, + }, TransactionParams, }; @@ -56,7 +61,10 @@ pub struct RelayParachains { #[strum(serialize_all = "kebab_case")] pub enum RelayParachainsBridge { RialtoToMillau, + // TODO:check-parameter - rename to WestmintToMillau? WestendToMillau, + BridgeHubRococoToBridgeHubWococo, + BridgeHubWococoToBridgeHubRococo, } #[async_trait] @@ -92,7 +100,7 @@ where target_client, ParachainSyncParams { parachains: vec![ - ParaId(::SOURCE_PARACHAIN_PARA_ID) + ParaId(::SOURCE_PARACHAIN_PARA_ID) ], stall_timeout: std::time::Duration::from_secs(60), strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, @@ -109,6 +117,10 @@ impl ParachainsRelayer for RialtoParachainToMillauCliBridge {} impl ParachainsRelayer for WestmintToMillauCliBridge {} +impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} + +impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} + impl RelayParachains { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { @@ -117,6 +129,10 @@ impl RelayParachains { RialtoParachainToMillauCliBridge::relay_headers(self), RelayParachainsBridge::WestendToMillau => WestmintToMillauCliBridge::relay_headers(self), + RelayParachainsBridge::BridgeHubRococoToBridgeHubWococo => + BridgeHubRococoToBridgeHubWococoCliBridge::relay_headers(self), + RelayParachainsBridge::BridgeHubWococoToBridgeHubRococo => + BridgeHubWococoToBridgeHubRococoCliBridge::relay_headers(self), } .await } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 2b314b921fa90..bb46762cee880 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -211,6 +211,12 @@ impl SendMessage { MillauToRialtoParachainCliBridge::send_message(self), FullBridge::RialtoParachainToMillau => RialtoParachainToMillauCliBridge::send_message(self), + FullBridge::BridgeHubRococoToBridgeHubWococo => unimplemented!( + "Sending message from BridgeHubRococo to BridgeHubWococo is not supported" + ), + FullBridge::BridgeHubWococoToBridgeHubRococo => unimplemented!( + "Sending message from BridgeHubWococo to BridgeHubRococo is not supported" + ), } .await } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml new file mode 100644 index 0000000000000..4a01d81e7771f --- /dev/null +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "relay-bridge-hub-rococo-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +relay-substrate-client = { path = "../client-substrate" } + +# Bridge dependencies + +bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } +bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-runtime = { path = "../../primitives/runtime" } + +bridge-runtime-common = { path = "../../bin/runtime-common" } +# Substrate Dependencies + +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[dev-dependencies] +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs new file mode 100644 index 0000000000000..375f11423a524 --- /dev/null +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -0,0 +1,168 @@ +// Copyright 2022 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 . + +//! Types used to connect to the BridgeHub-Rococo-Substrate parachain. + +use bp_messages::{MessageNonce, Weight}; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, SignParam, + UnsignedTransaction, +}; +use sp_core::Pair; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Re-export runtime wrapper +pub mod runtime_wrapper; +pub use runtime_wrapper as runtime; + +/// Rococo chain definition +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BridgeHubRococo; + +impl ChainBase for BridgeHubRococo { + type BlockNumber = bp_bridge_hub_rococo::BlockNumber; + type Hash = bp_bridge_hub_rococo::Hash; + type Hasher = bp_bridge_hub_rococo::Hashing; + type Header = bp_bridge_hub_rococo::Header; + + type AccountId = bp_bridge_hub_rococo::AccountId; + type Balance = bp_bridge_hub_rococo::Balance; + type Index = bp_bridge_hub_rococo::Nonce; + type Signature = bp_bridge_hub_rococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_weight() + } +} + +impl Chain for BridgeHubRococo { + const NAME: &'static str = "BridgeHubRococo"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_bridge_hub_rococo::EXTRA_STORAGE_PROOF_SIZE; + + type SignedBlock = bp_bridge_hub_rococo::SignedBlock; + type Call = runtime::Call; +} + +impl ChainWithTransactions for BridgeHubRococo { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = runtime::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_bridge_hub_rococo::SignedExtensions::new( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(bp_bridge_hub_rococo::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + *address == bp_bridge_hub_rococo::Address::Id(signer.public().into()) + }) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} + +impl ChainWithMessages for BridgeHubRococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME; + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; + + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_bridge_hub_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + + type WeightToFee = bp_bridge_hub_rococo::WeightToFee; + // TODO: fix (https://github.com/paritytech/parity-bridges-common/issues/1640) + type WeightInfo = (); +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + .into(), + nonce: 777, + tip: 888, + era: TransactionEra::immortal(), + }; + let signed_transaction = BridgeHubRococo::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) + .unwrap(); + let parsed_transaction = BridgeHubRococo::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs new file mode 100644 index 0000000000000..c88a40073cb86 --- /dev/null +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -0,0 +1,219 @@ +// 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 . + +// TODO: join with primitives do we need this here or move to the primitives? + +//! Types that are specific to the BridgeHubRococo runtime. + +use bp_polkadot_core::PolkadotLike; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_bridge_hub_rococo::SS58Prefix; +use bp_messages::UnrewardedRelayersState; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use bp_runtime::Chain; + +// TODO:check-parameter - check SignedExtension +/// Unchecked BridgeHubRococo extrinsic. +pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; + +/// Rococo Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo +/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// // TODO:check-parameter -> change bko-bridge-rococo-wococo when merged to master in cumulus +/// See: [link](https://github.com/paritytech/cumulus/blob/bko-bridge-rococo-wococo/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs) +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// System pallet. + #[codec(index = 0)] + System(SystemCall), + /// Wococo bridge pallet. + #[codec(index = 41)] + BridgeWococoGrandpa(BridgeWococoGrandpaCall), + /// Rococo bridge pallet. + #[codec(index = 43)] + BridgeRococoGrandpa(BridgeRococoGrandpaCall), + + /// Wococo parachain bridge pallet. + #[codec(index = 42)] + BridgeWococoParachain(BridgeParachainCall), + /// Rococo parachain bridge pallet. + #[codec(index = 44)] + BridgeRococoParachain(BridgeParachainCall), + + /// Wococo messages bridge pallet. + #[codec(index = 46)] + BridgeWococoMessages(BridgeWococoMessagesCall), + /// Rococo messages bridge pallet. + #[codec(index = 45)] + BridgeRococoMessages(BridgeRococoMessagesCall), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + #[codec(index = 1)] + remark(Vec), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeWococoGrandpaCall { + #[codec(index = 0)] + submit_finality_proof( + Box<::Header>, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeRococoGrandpaCall { + #[codec(index = 0)] + submit_finality_proof( + Box<::Header>, + bp_header_chain::justification::GrandpaJustification<::Header>, + ), + #[codec(index = 1)] + initialize(bp_header_chain::InitializationData<::Header>), +} + +pub type RelayBlockHash = bp_polkadot_core::Hash; +pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeParachainCall { + #[codec(index = 0)] + submit_parachain_heads( + (RelayBlockNumber, RelayBlockHash), + Vec<(ParaId, ParaHash)>, + ParaHeadsProof, + ), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeWococoMessagesCall { + #[codec(index = 5)] + receive_messages_proof( + relay_substrate_client::AccountIdOf, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< + relay_substrate_client::HashOf, + >, + u32, + bp_messages::Weight, + ), + + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + relay_substrate_client::HashOf, + >, + UnrewardedRelayersState, + ), +} + +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeRococoMessagesCall { + #[codec(index = 5)] + receive_messages_proof( + relay_substrate_client::AccountIdOf, + bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< + relay_substrate_client::HashOf, + >, + u32, + bp_messages::Weight, + ), + + #[codec(index = 6)] + receive_messages_delivery_proof( + bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + relay_substrate_client::HashOf, + >, + UnrewardedRelayersState, + ), +} + +impl sp_runtime::traits::Dispatchable for Call { + type RuntimeOrigin = (); + type Config = (); + type Info = (); + type PostInfo = (); + + fn dispatch( + self, + _origin: Self::RuntimeOrigin, + ) -> sp_runtime::DispatchResultWithInfo { + unimplemented!("The Call is not expected to be dispatched.") + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_runtime::BasicOperatingMode; + use sp_core::hexdisplay::HexDisplay; + use sp_finality_grandpa::AuthorityList; + use sp_runtime::traits::Header; + use std::str::FromStr; + + pub type RelayBlockHasher = bp_polkadot_core::Hasher; + pub type RelayBlockHeader = sp_runtime::generic::Header; + + #[test] + fn encode_decode_calls() { + let header = RelayBlockHeader::new( + 75, + bp_polkadot_core::Hash::from_str( + "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", + ) + .expect("invalid value"), + Default::default(), + ); + let init_data = bp_header_chain::InitializationData { + header: Box::new(header), + authority_list: AuthorityList::default(), + set_id: 6, + operating_mode: BasicOperatingMode::Normal, + }; + let call = BridgeRococoGrandpaCall::initialize(init_data); + let tx = Call::BridgeRococoGrandpa(call); + + // encode call as hex string + let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); + assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); + } +} diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml new file mode 100644 index 0000000000000..fa28dfde202aa --- /dev/null +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "relay-bridge-hub-wococo-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +relay-substrate-client = { path = "../client-substrate" } + +# Bridge dependencies + +bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } +bp-messages = { path = "../../primitives/messages" } +relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } + +# Substrate Dependencies + +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs new file mode 100644 index 0000000000000..f00aa6a9fa910 --- /dev/null +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -0,0 +1,168 @@ +// Copyright 2022 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 . + +//! Types used to connect to the BridgeHub-Wococo-Substrate parachain. + +use bp_messages::{MessageNonce, Weight}; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainBase, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, SignParam, + UnsignedTransaction, +}; +use sp_core::Pair; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Re-export runtime wrapper +pub mod runtime_wrapper; +pub use runtime_wrapper as runtime; + +/// Wococo chain definition +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BridgeHubWococo; + +impl ChainBase for BridgeHubWococo { + type BlockNumber = bp_bridge_hub_wococo::BlockNumber; + type Hash = bp_bridge_hub_wococo::Hash; + type Hasher = bp_bridge_hub_wococo::Hashing; + type Header = bp_bridge_hub_wococo::Header; + + type AccountId = bp_bridge_hub_wococo::AccountId; + type Balance = bp_bridge_hub_wococo::Balance; + type Index = bp_bridge_hub_wococo::Nonce; + type Signature = bp_bridge_hub_wococo::Signature; + + fn max_extrinsic_size() -> u32 { + bp_bridge_hub_wococo::BridgeHubWococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_bridge_hub_wococo::BridgeHubWococo::max_extrinsic_weight() + } +} + +impl Chain for BridgeHubWococo { + const NAME: &'static str = "BridgeHubWococo"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_bridge_hub_wococo::BEST_FINALIZED_BRIDGE_HUB_WOCOCO_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const STORAGE_PROOF_OVERHEAD: u32 = bp_bridge_hub_wococo::EXTRA_STORAGE_PROOF_SIZE; + + type SignedBlock = bp_bridge_hub_wococo::SignedBlock; + type Call = runtime::Call; +} + +impl ChainWithTransactions for BridgeHubWococo { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = runtime::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_bridge_hub_wococo::SignedExtensions::new( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(bp_bridge_hub_wococo::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + *address == bp_bridge_hub_wococo::Address::Id(signer.public().into()) + }) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} + +impl ChainWithMessages for BridgeHubWococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_wococo::WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME; + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_wococo::TO_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_wococo::FROM_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; + + const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = + bp_bridge_hub_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + + type WeightToFee = bp_bridge_hub_wococo::WeightToFee; + // TODO: fix (https://github.com/paritytech/parity-bridges-common/issues/1640) + type WeightInfo = (); +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + .into(), + nonce: 777, + tip: 888, + era: TransactionEra::immortal(), + }; + let signed_transaction = BridgeHubWococo::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) + .unwrap(); + let parsed_transaction = BridgeHubWococo::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs new file mode 100644 index 0000000000000..8d94e7f9026a9 --- /dev/null +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -0,0 +1,28 @@ +// 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 . + +//! Types that are specific to the BridgeHubWococo runtime. + +pub use bp_bridge_hub_wococo::SS58Prefix; + +// We reuse everything from rococo runtime wrapper +pub type Call = relay_bridge_hub_rococo_client::runtime::Call; +pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; +pub type BridgeGrandpaRococoCall = relay_bridge_hub_rococo_client::runtime::BridgeRococoGrandpaCall; +pub type BridgeParachainCall = relay_bridge_hub_rococo_client::runtime::BridgeParachainCall; +pub type BridgeRococoMessagesCall = + relay_bridge_hub_rococo_client::runtime::BridgeRococoMessagesCall; +pub type SystemCall = relay_bridge_hub_rococo_client::runtime::SystemCall; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index f4905d52dc7ee..5f1ff033559cd 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Rococo-Substrate chain. use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, RelayChain}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -72,3 +72,8 @@ impl ChainWithBalances for Rococo { StorageKey(bp_rococo::account_info_storage_key(account_id)) } } + +impl RelayChain for Rococo { + const PARAS_PALLET_NAME: &'static str = bp_rococo::PARAS_PALLET_NAME; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "bridgeRococoParachain"; +} diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 87da6fb83679e..b4e9dd74d1985 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Wococo-Substrate chain. use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, RelayChain}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -72,3 +72,8 @@ impl ChainWithBalances for Wococo { StorageKey(bp_wococo::account_info_storage_key(account_id)) } } + +impl RelayChain for Wococo { + const PARAS_PALLET_NAME: &'static str = bp_wococo::PARAS_PALLET_NAME; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "bridgeWococoParachain"; +} From 4580d18923e75930f2251d3d0def6ca6fd43fa04 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 17 Nov 2022 07:30:27 +0100 Subject: [PATCH 0807/1210] Small fix after rebase (#1644) --- primitives/chain-bridge-hub-rococo/src/lib.rs | 40 +++++++++++++++-- primitives/chain-bridge-hub-wococo/src/lib.rs | 45 ++++++++++++++++--- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 32e8eb646a342..0d1a81be10292 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright 2022 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 @@ -21,19 +21,51 @@ use bp_messages::*; pub use bp_polkadot_core::*; -use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis}; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, +}; use frame_support::{ + dispatch::DispatchClass, parameter_types, sp_runtime::{FixedU128, MultiAddress, MultiSigner}, weights::{ constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, - Parameter, + Parameter, RuntimeDebug, }; use sp_std::prelude::*; -pub type BridgeHubRococo = PolkadotLike; +/// BridgeHubRococo parachain. +#[derive(RuntimeDebug)] +pub struct BridgeHubRococo; + +impl Chain for BridgeHubRococo { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +impl Parachain for BridgeHubRococo { + const PARACHAIN_ID: u32 = BRIDGE_HUB_ROCOCO_PARACHAIN_ID; +} /// [`WeightToFee`] should reflect cumulus/bridge-hub-rococo-runtime [`WeightToFee`] pub struct WeightToFee; diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 93f0d78dfd857..33c4dcca127e3 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -25,19 +25,50 @@ // Re-export only what is really needed pub use bp_bridge_hub_rococo::{ account_info_storage_key, AccountId, AccountPublic, AccountSigner, Address, Balance, - BlockNumber, Hash, Hashing, Header, Nonce, SS58Prefix, Signature, SignedBlock, - SignedExtensions, UncheckedExtrinsic, WeightToFee, ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, EXTRA_STORAGE_PROOF_SIZE, - MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, + BlockLength, BlockNumber, BlockWeights, Hash, Hasher, Hashing, Header, Index, Nonce, + SS58Prefix, Signature, SignedBlock, SignedExtensions, UncheckedExtrinsic, WeightToFee, + ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, + EXTRA_STORAGE_PROOF_SIZE, MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, PAY_INBOUND_DISPATCH_FEE_WEIGHT, TX_EXTRA_BYTES, }; use bp_messages::*; -use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis}; -use frame_support::{sp_runtime::FixedU128, Parameter}; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, +}; +use frame_support::{dispatch::DispatchClass, sp_runtime::FixedU128, Parameter, RuntimeDebug}; use sp_std::prelude::*; -pub type BridgeHubWococo = bp_bridge_hub_rococo::BridgeHubRococo; +/// BridgeHubWococo parachain. +#[derive(RuntimeDebug)] +pub struct BridgeHubWococo; + +impl Chain for BridgeHubWococo { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +impl Parachain for BridgeHubWococo { + const PARACHAIN_ID: u32 = BRIDGE_HUB_WOCOCO_PARACHAIN_ID; +} /// Identifier of BridgeHubWococo in the Wococo relay chain. pub const BRIDGE_HUB_WOCOCO_PARACHAIN_ID: u32 = 1013; From 73c06c52a0f6c63dbda4194d0dd23e0fe39d33b2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 18 Nov 2022 12:24:45 +0300 Subject: [PATCH 0808/1210] Remove message fee + message send calls (#1642) * remove message fee * it is compiling! * fixes + fmt * more cleanup * more cleanup * restore MessageDeliveryAndDispatchPayment since we'll need relayer rewards * started rational relayer removal * more removal * removed estimate fee subcommand * remove DispatchFeePayment * more removals * removed conversion rates && some metrics * - unneeded associated type * - OutboundMessageFee * fix benchmarks compilation * fmt * test + fix benchmarks * fix send message * clippy --- bin/millau/runtime/src/lib.rs | 81 +-- bin/millau/runtime/src/rialto_messages.rs | 128 +--- .../runtime/src/rialto_parachain_messages.rs | 119 +--- bin/millau/runtime/src/xcm_config.rs | 4 +- bin/rialto-parachain/runtime/src/lib.rs | 42 +- .../runtime/src/millau_messages.rs | 117 +--- bin/rialto/runtime/src/lib.rs | 34 +- bin/rialto/runtime/src/millau_messages.rs | 130 +--- bin/rialto/runtime/src/xcm_config.rs | 4 +- bin/runtime-common/src/integrity.rs | 2 - bin/runtime-common/src/messages.rs | 402 +---------- bin/runtime-common/src/messages_api.rs | 9 +- .../src/messages_benchmarking.rs | 18 +- bin/runtime-common/src/messages_extension.rs | 1 - bin/runtime-common/src/messages_generation.rs | 22 +- modules/grandpa/src/weights.rs | 14 +- modules/messages/src/benchmarking.rs | 224 +----- modules/messages/src/inbound_lane.rs | 40 +- modules/messages/src/lib.rs | 651 +++--------------- modules/messages/src/mock.rs | 111 +-- modules/messages/src/outbound_lane.rs | 106 +-- modules/messages/src/weights.rs | 107 +-- modules/messages/src/weights_ext.rs | 93 +-- modules/parachains/src/weights.rs | 18 +- modules/relayers/src/mock.rs | 3 - modules/relayers/src/payment_adapter.rs | 67 +- modules/relayers/src/weights.rs | 6 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 4 +- primitives/chain-bridge-hub-wococo/src/lib.rs | 6 +- primitives/chain-millau/src/lib.rs | 45 +- primitives/chain-rialto-parachain/src/lib.rs | 44 +- primitives/chain-rialto/src/lib.rs | 39 +- primitives/chain-statemine/Cargo.toml | 24 - primitives/chain-statemine/src/lib.rs | 38 - primitives/messages/src/lib.rs | 33 +- primitives/messages/src/source_chain.rs | 64 +- primitives/messages/src/target_chain.rs | 50 +- primitives/polkadot-core/src/lib.rs | 37 - primitives/runtime/src/chain.rs | 24 +- primitives/runtime/src/messages.rs | 14 - relays/bin-substrate/Cargo.toml | 2 - ...ub_rococo_messages_to_bridge_hub_wococo.rs | 14 - ...ub_wococo_messages_to_bridge_hub_rococo.rs | 14 - relays/bin-substrate/src/chains/millau.rs | 39 +- .../src/chains/millau_messages_to_rialto.rs | 23 - .../millau_messages_to_rialto_parachain.rs | 28 - relays/bin-substrate/src/chains/mod.rs | 1 - relays/bin-substrate/src/chains/rialto.rs | 30 +- .../src/chains/rialto_messages_to_millau.rs | 23 - .../src/chains/rialto_parachain.rs | 31 +- .../rialto_parachain_messages_to_millau.rs | 28 - relays/bin-substrate/src/chains/statemine.rs | 34 - relays/bin-substrate/src/cli/bridge.rs | 9 +- .../bin-substrate/src/cli/encode_message.rs | 78 ++- relays/bin-substrate/src/cli/estimate_fee.rs | 292 -------- relays/bin-substrate/src/cli/mod.rs | 4 - .../src/cli/relay_headers_and_messages/mod.rs | 96 +-- .../bin-substrate/src/cli/relay_messages.rs | 69 +- relays/bin-substrate/src/cli/send_message.rs | 117 +--- relays/client-bridge-hub-rococo/src/lib.rs | 3 - relays/client-bridge-hub-wococo/src/lib.rs | 3 - relays/client-kusama/src/lib.rs | 1 - relays/client-millau/src/lib.rs | 3 - relays/client-polkadot/src/lib.rs | 1 - relays/client-rialto-parachain/src/lib.rs | 5 +- relays/client-rialto/src/lib.rs | 3 - relays/client-rococo/src/lib.rs | 1 - relays/client-statemine/Cargo.toml | 24 - relays/client-statemine/src/lib.rs | 112 --- relays/client-statemine/src/runtime.rs | 68 -- relays/client-substrate/src/chain.rs | 8 +- relays/client-substrate/src/metrics/mod.rs | 2 - .../src/metrics/storage_proof_overhead.rs | 101 --- relays/client-substrate/src/test_chain.rs | 1 - relays/client-westend/src/lib.rs | 2 - relays/client-wococo/src/lib.rs | 1 - .../src/conversion_rate_update.rs | 439 ------------ relays/lib-substrate-relay/src/helpers.rs | 106 --- relays/lib-substrate-relay/src/lib.rs | 2 - .../lib-substrate-relay/src/messages_lane.rs | 69 +- .../src/messages_metrics.rs | 257 +------ .../src/messages_source.rs | 118 +--- .../src/messages_target.rs | 309 +-------- relays/messages/src/lib.rs | 2 +- relays/messages/src/message_lane_loop.rs | 81 +-- relays/messages/src/message_race_delivery.rs | 139 +--- ...ent_strategy.rs => message_race_limits.rs} | 142 ++-- relays/messages/src/metrics.rs | 23 +- .../src/relay_strategy/altruistic_strategy.rs | 81 --- .../src/relay_strategy/mix_strategy.rs | 72 -- relays/messages/src/relay_strategy/mod.rs | 224 ------ .../src/relay_strategy/rational_strategy.rs | 75 -- 92 files changed, 589 insertions(+), 5796 deletions(-) delete mode 100644 primitives/chain-statemine/Cargo.toml delete mode 100644 primitives/chain-statemine/src/lib.rs delete mode 100644 relays/bin-substrate/src/chains/statemine.rs delete mode 100644 relays/bin-substrate/src/cli/estimate_fee.rs delete mode 100644 relays/client-statemine/Cargo.toml delete mode 100644 relays/client-statemine/src/lib.rs delete mode 100644 relays/client-statemine/src/runtime.rs delete mode 100644 relays/client-substrate/src/metrics/storage_proof_overhead.rs delete mode 100644 relays/lib-substrate-relay/src/conversion_rate_update.rs delete mode 100644 relays/lib-substrate-relay/src/helpers.rs rename relays/messages/src/{relay_strategy/enforcement_strategy.rs => message_race_limits.rs} (56%) delete mode 100644 relays/messages/src/relay_strategy/altruistic_strategy.rs delete mode 100644 relays/messages/src/relay_strategy/mix_strategy.rs delete mode 100644 relays/messages/src/relay_strategy/mod.rs delete mode 100644 relays/messages/src/relay_strategy/rational_strategy.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 09f17cf6cf534..095250a55861a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -32,18 +32,8 @@ pub mod rialto_messages; pub mod rialto_parachain_messages; pub mod xcm_config; -use crate::{ - rialto_messages::{ToRialtoMessagePayload, WithRialtoMessageBridge}, - rialto_parachain_messages::{ - ToRialtoParachainMessagePayload, WithRialtoParachainMessageBridge, - }, -}; - use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bp_runtime::{HeaderId, HeaderIdProvider}; -use bridge_runtime_common::messages::{ - source::estimate_message_dispatch_and_delivery_fee, MessageBridge, -}; use codec::Decode; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, @@ -57,7 +47,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -476,9 +466,6 @@ parameter_types! { bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - // `IdentityFee` is used by Millau => we may use weight directly - pub const GetDeliveryConfirmationTransactionFee: Balance = - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() as _; pub const RootAccountForPayments: Option = None; pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; pub const RialtoParachainChainId: bp_runtime::ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; @@ -490,17 +477,14 @@ pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type Parameter = rialto_messages::MillauToRialtoMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaximalOutboundPayloadSize = crate::rialto_messages::ToRialtoMaximalOutboundPayloadSize; type OutboundPayload = crate::rialto_messages::ToRialtoMessagePayload; - type OutboundMessageFee = Balance; type InboundPayload = crate::rialto_messages::FromRialtoMessagePayload; - type InboundMessageFee = bp_rialto::Balance; type InboundRelayer = bp_rialto::AccountId; type TargetHeaderChain = crate::rialto_messages::Rialto; @@ -509,7 +493,6 @@ impl pallet_bridge_messages::Config for Runtime { pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< Runtime, WithRialtoMessagesInstance, - GetDeliveryConfirmationTransactionFee, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -525,7 +508,6 @@ pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1 impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type Parameter = rialto_parachain_messages::MillauToRialtoParachainMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -533,10 +515,8 @@ impl pallet_bridge_messages::Config for Run type MaximalOutboundPayloadSize = crate::rialto_parachain_messages::ToRialtoParachainMaximalOutboundPayloadSize; type OutboundPayload = crate::rialto_parachain_messages::ToRialtoParachainMessagePayload; - type OutboundMessageFee = Balance; type InboundPayload = crate::rialto_parachain_messages::FromRialtoParachainMessagePayload; - type InboundMessageFee = bp_rialto_parachain::Balance; type InboundRelayer = bp_rialto_parachain::AccountId; type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; @@ -545,7 +525,6 @@ impl pallet_bridge_messages::Config for Run pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< Runtime, WithRialtoParachainMessagesInstance, - GetDeliveryConfirmationTransactionFee, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -941,24 +920,12 @@ impl_runtime_apis! { } } - impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { - fn estimate_message_delivery_and_dispatch_fee( - _lane_id: bp_messages::LaneId, - payload: ToRialtoMessagePayload, - rialto_to_this_conversion_rate: Option, - ) -> Option { - estimate_message_dispatch_and_delivery_fee::( - &payload, - WithRialtoMessageBridge::RELAYER_FEE_PERCENT, - rialto_to_this_conversion_rate, - ).ok() - } - + impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithRialtoMessagesInstance, @@ -966,10 +933,10 @@ impl_runtime_apis! { } } - impl bp_rialto::FromRialtoInboundLaneApi for Runtime { + impl bp_rialto::FromRialtoInboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, ) -> Vec { bridge_runtime_common::messages_api::inbound_message_details::< Runtime, @@ -978,24 +945,12 @@ impl_runtime_apis! { } } - impl bp_rialto_parachain::ToRialtoParachainOutboundLaneApi for Runtime { - fn estimate_message_delivery_and_dispatch_fee( - _lane_id: bp_messages::LaneId, - payload: ToRialtoParachainMessagePayload, - rialto_parachain_to_this_conversion_rate: Option, - ) -> Option { - estimate_message_dispatch_and_delivery_fee::( - &payload, - WithRialtoParachainMessageBridge::RELAYER_FEE_PERCENT, - rialto_parachain_to_this_conversion_rate, - ).ok() - } - + impl bp_rialto_parachain::ToRialtoParachainOutboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithRialtoParachainMessagesInstance, @@ -1003,10 +958,10 @@ impl_runtime_apis! { } } - impl bp_rialto_parachain::FromRialtoParachainInboundLaneApi for Runtime { + impl bp_rialto_parachain::FromRialtoParachainInboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, ) -> Vec { bridge_runtime_common::messages_api::inbound_message_details::< Runtime, @@ -1060,13 +1015,11 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof, prepare_message_proof, prepare_outbound_message}; - use bridge_runtime_common::messages; + use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof, prepare_message_proof}; use pallet_bridge_messages::benchmarking::{ Pallet as MessagesBench, Config as MessagesConfig, MessageDeliveryProofParams, - MessageParams, MessageProofParams, }; use pallet_bridge_parachains::benchmarking::{ @@ -1076,18 +1029,10 @@ impl_runtime_apis! { use rialto_messages::WithRialtoMessageBridge; impl MessagesConfig for Runtime { - fn maximal_message_size() -> u32 { - messages::source::maximal_message_size::() - } - fn bridged_relayer_id() -> Self::InboundRelayer { [0u8; 32].into() } - fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee { - pallet_balances::Pallet::::free_balance(account) - } - fn endow_account(account: &Self::AccountId) { pallet_balances::Pallet::::make_free_balance_be( account, @@ -1095,12 +1040,6 @@ impl_runtime_apis! { ); } - fn prepare_outbound_message( - params: MessageParams, - ) -> (rialto_messages::ToRialtoMessagePayload, Balance) { - (prepare_outbound_message::(params), Self::message_fee()) - } - fn prepare_message_proof( params: MessageProofParams, ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index c6bc308a8e819..c0868298a3276 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -21,35 +21,20 @@ use crate::{OriginCaller, RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOr use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, + InboundLaneData, LaneId, Message, MessageNonce, }; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, -}; -use codec::{Decode, Encode}; -use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use sp_std::convert::TryFrom; +use bridge_runtime_common::messages::{self, MessageBridge}; +use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto. pub const DEFAULT_XCM_LANE_TO_RIALTO: LaneId = [0, 0, 0, 0]; -/// Initial value of `RialtoToMillauConversionRate` parameter. -pub const INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE: FixedU128 = - FixedU128::from_inner(FixedU128::DIV); -/// Initial value of `RialtoFeeMultiplier` parameter. -pub const INITIAL_RIALTO_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; parameter_types! { - /// Rialto to Millau conversion rate. Initially we treat both tokens as equal. - pub storage RialtoToMillauConversionRate: FixedU128 = INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE; - /// Fee multiplier value at Rialto chain. - pub storage RialtoFeeMultiplier: FixedU128 = INITIAL_RIALTO_FEE_MULTIPLIER; /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge @@ -91,7 +76,6 @@ pub type ToRialtoMaximalOutboundPayloadSize = pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { - const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; @@ -100,16 +84,6 @@ impl MessageBridge for WithRialtoMessageBridge { type BridgedChain = Rialto; type BridgedHeaderChain = pallet_bridge_grandpa::GrandpaChainHeaders; - - fn bridged_balance_to_this_balance( - bridged_balance: bp_rialto::Balance, - bridged_to_this_conversion_rate_override: Option, - ) -> bp_millau::Balance { - let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(RialtoToMillauConversionRate::get); - bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) - .unwrap_or(bp_millau::Balance::MAX) - } } /// Millau chain from message lane point of view. @@ -123,12 +97,6 @@ impl messages::UnderlyingChainProvider for Millau { impl messages::ThisChainWithMessages for Millau { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; - type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - bp_millau::AccountId, - { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, - { bp_rialto::EXTRA_STORAGE_PROOF_SIZE }, - { bp_millau::TX_EXTRA_BYTES }, - >; fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { let here_location = @@ -153,21 +121,6 @@ impl messages::ThisChainWithMessages for Millau { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } - - fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { - // `transaction` may represent transaction from the future, when multiplier value will - // be larger, so let's use slightly increased value - let multiplier = FixedU128::saturating_from_rational(110, 100) - .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } /// Rialto chain from message lane point of view. @@ -182,45 +135,6 @@ impl messages::BridgedChainWithMessages for Rialto { fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } - - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction { - let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = message_payload_len - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); - - MessageTransaction { - dispatch_weight: bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT - .saturating_mul(extra_bytes_in_payload as u64) - .saturating_add(bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) - .saturating_sub(if include_pay_dispatch_fee_cost { - Weight::from_ref_time(0) - } else { - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT - }) - .saturating_add(message_dispatch_weight), - size: message_payload_len - .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_rialto::TX_EXTRA_BYTES), - } - } - - fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { - // we don't have a direct access to the value of multiplier at Rialto chain - // => it is a messages module parameter - let multiplier = RialtoFeeMultiplier::get(); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } impl TargetHeaderChain for Rialto { @@ -242,7 +156,7 @@ impl TargetHeaderChain for Rialto } } -impl SourceHeaderChain for Rialto { +impl SourceHeaderChain for Rialto { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; @@ -254,28 +168,12 @@ impl SourceHeaderChain for Rialto { fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { messages::target::verify_messages_proof::(proof, messages_count) .map_err(Into::into) } } -/// Millau -> Rialto message lane pallet parameters. -#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub enum MillauToRialtoMessagesParameter { - /// The conversion formula we use is: `MillauTokens = RialtoTokens * conversion_rate`. - RialtoToMillauConversionRate(FixedU128), -} - -impl MessagesParameter for MillauToRialtoMessagesParameter { - fn save(&self) { - match *self { - MillauToRialtoMessagesParameter::RialtoToMillauConversionRate(ref conversion_rate) => - RialtoToMillauConversionRate::set(conversion_rate), - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -295,13 +193,7 @@ mod tests { fn ensure_millau_message_lane_weights_are_correct() { type Weights = pallet_bridge_messages::weights::BridgeWeight; - pallet_bridge_messages::ensure_weights_are_correct::( - bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT, - DbWeight::get(), - ); + pallet_bridge_messages::ensure_weights_are_correct::(); let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), @@ -366,13 +258,5 @@ mod tests { bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, }, }); - - assert_eq!( - RialtoToMillauConversionRate::key().to_vec(), - bp_runtime::storage_parameter_key( - bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME - ) - .0, - ); } } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index da4ca9d83cb2e..8655edd59f491 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -21,17 +21,11 @@ use crate::{Runtime, RuntimeCall, RuntimeOrigin, WithRialtoParachainsInstance}; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, + InboundLaneData, LaneId, Message, MessageNonce, }; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, -}; -use codec::{Decode, Encode}; -use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use sp_std::convert::TryFrom; +use bridge_runtime_common::messages::{self, MessageBridge}; +use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto parachain. pub const DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN: LaneId = [0, 0, 0, 0]; @@ -40,18 +34,7 @@ pub const DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN: LaneId = [0, 0, 0, 0]; /// tests, confirming that we don't break encoding somewhere between. pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; -/// Initial value of `RialtoParachainToMillauConversionRate` parameter. -pub const INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE: FixedU128 = - FixedU128::from_inner(FixedU128::DIV); -/// Initial value of `RialtoParachainFeeMultiplier` parameter. -pub const INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER: FixedU128 = - FixedU128::from_inner(FixedU128::DIV); - parameter_types! { - /// RialtoParachain to Millau conversion rate. Initially we treat both tokens as equal. - pub storage RialtoParachainToMillauConversionRate: FixedU128 = INITIAL_RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE; - /// Fee multiplier value at RialtoParachain chain. - pub storage RialtoParachainFeeMultiplier: FixedU128 = INITIAL_RIALTO_PARACHAIN_FEE_MULTIPLIER; /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge @@ -95,7 +78,6 @@ pub type ToRialtoParachainMaximalOutboundPayloadSize = pub struct WithRialtoParachainMessageBridge; impl MessageBridge for WithRialtoParachainMessageBridge { - const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; @@ -107,16 +89,6 @@ impl MessageBridge for WithRialtoParachainMessageBridge { WithRialtoParachainsInstance, bp_rialto_parachain::RialtoParachain, >; - - fn bridged_balance_to_this_balance( - bridged_balance: bp_rialto_parachain::Balance, - bridged_to_this_conversion_rate_override: Option, - ) -> bp_millau::Balance { - let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(RialtoParachainToMillauConversionRate::get); - bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) - .unwrap_or(bp_millau::Balance::MAX) - } } /// Millau chain from message lane point of view. @@ -130,12 +102,6 @@ impl messages::UnderlyingChainProvider for Millau { impl messages::ThisChainWithMessages for Millau { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - bp_rialto_parachain::AccountId, - { bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, - { bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE }, - { bp_millau::TX_EXTRA_BYTES }, - >; fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { *lane == DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN || *lane == [0, 0, 0, 1] @@ -144,21 +110,6 @@ impl messages::ThisChainWithMessages for Millau { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } - - fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { - // `transaction` may represent transaction from the future, when multiplier value will - // be larger, so let's use slightly increased value - let multiplier = FixedU128::saturating_from_rational(110, 100) - .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } /// RialtoParachain chain from message lane point of view. @@ -173,49 +124,6 @@ impl messages::BridgedChainWithMessages for RialtoParachain { fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } - - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction { - let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = message_payload_len - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); - - MessageTransaction { - dispatch_weight: bp_rialto_parachain::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT - .saturating_mul(extra_bytes_in_payload as _) - .saturating_add(bp_rialto_parachain::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) - .saturating_sub(if include_pay_dispatch_fee_cost { - Weight::from_ref_time(0) - } else { - bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT - }) - .saturating_add(message_dispatch_weight), - size: message_payload_len - .saturating_add(bp_millau::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_rialto_parachain::TX_EXTRA_BYTES), - } - } - - fn transaction_payment( - transaction: MessageTransaction, - ) -> bp_rialto_parachain::Balance { - // we don't have a direct access to the value of multiplier at RialtoParachain chain - // => it is a messages module parameter - let multiplier = RialtoParachainFeeMultiplier::get(); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_rialto_parachain::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } impl TargetHeaderChain for RialtoParachain { @@ -237,7 +145,7 @@ impl TargetHeaderChain fo } } -impl SourceHeaderChain for RialtoParachain { +impl SourceHeaderChain for RialtoParachain { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; @@ -249,7 +157,7 @@ impl SourceHeaderChain for RialtoParachain { fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { messages::target::verify_messages_proof::( proof, messages_count, @@ -257,20 +165,3 @@ impl SourceHeaderChain for RialtoParachain { .map_err(Into::into) } } - -/// Millau -> RialtoParachain message lane pallet parameters. -#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub enum MillauToRialtoParachainMessagesParameter { - /// The conversion formula we use is: `MillauTokens = RialtoParachainTokens * conversion_rate`. - RialtoParachainToMillauConversionRate(FixedU128), -} - -impl MessagesParameter for MillauToRialtoParachainMessagesParameter { - fn save(&self) { - match *self { - MillauToRialtoParachainMessagesParameter::RialtoParachainToMillauConversionRate( - ref conversion_rate, - ) => RialtoParachainToMillauConversionRate::set(conversion_rate), - } - } -} diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 9a5851c8d0552..32b14f27a3b80 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -271,7 +271,7 @@ mod tests { fn xcm_messages_are_sent_using_bridge_router() { new_test_ext().execute_with(|| { let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - let expected_fee = MultiAssets::from((Here, 4_259_858_152_u64)); + let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); @@ -305,7 +305,7 @@ mod tests { let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, + data: DispatchMessageData { payload: Ok((location, xcm).into()) }, }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index c427bfac59a84..c5b9e50d067c0 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -26,14 +26,9 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use crate::millau_messages::{ - ToMillauMessagePayload, WithMillauMessageBridge, DEFAULT_XCM_LANE_TO_MILLAU, -}; +use crate::millau_messages::{WithMillauMessageBridge, DEFAULT_XCM_LANE_TO_MILLAU}; -use bridge_runtime_common::messages::{ - source::{estimate_message_dispatch_and_delivery_fee, XcmBridge, XcmBridgeAdapter}, - MessageBridge, -}; +use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; use cumulus_pallet_parachain_system::AnyRelayNumber; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; @@ -41,7 +36,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedU128, + ApplyExtrinsicResult, }; use sp_std::prelude::*; @@ -557,9 +552,6 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - // `IdentityFee` is used by Rialto => we may use weight directly - pub const GetDeliveryConfirmationTransactionFee: Balance = - bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() as _; pub const RootAccountForPayments: Option = None; pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; } @@ -570,17 +562,14 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type Parameter = millau_messages::RialtoParachainToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaximalOutboundPayloadSize = crate::millau_messages::ToMillauMaximalOutboundPayloadSize; type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; - type OutboundMessageFee = Balance; type InboundPayload = crate::millau_messages::FromMillauMessagePayload; - type InboundMessageFee = bp_millau::Balance; type InboundRelayer = bp_millau::AccountId; type TargetHeaderChain = crate::millau_messages::Millau; @@ -589,7 +578,6 @@ impl pallet_bridge_messages::Config for Runtime { pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< Runtime, WithMillauMessagesInstance, - GetDeliveryConfirmationTransactionFee, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -748,24 +736,12 @@ impl_runtime_apis! { } } - impl bp_millau::ToMillauOutboundLaneApi for Runtime { - fn estimate_message_delivery_and_dispatch_fee( - _lane_id: bp_messages::LaneId, - payload: ToMillauMessagePayload, - millau_to_this_conversion_rate: Option, - ) -> Option { - estimate_message_dispatch_and_delivery_fee::( - &payload, - WithMillauMessageBridge::RELAYER_FEE_PERCENT, - millau_to_this_conversion_rate, - ).ok() - } - + impl bp_millau::ToMillauOutboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithMillauMessagesInstance, @@ -773,10 +749,10 @@ impl_runtime_apis! { } } - impl bp_millau::FromMillauInboundLaneApi for Runtime { + impl bp_millau::FromMillauInboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, ) -> Vec { bridge_runtime_common::messages_api::inbound_message_details::< Runtime, @@ -882,7 +858,7 @@ mod tests { let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); let send_result = send_xcm::(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(4_259_858_152_u128))); + let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(1_000_000_u128))); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); assert_eq!(send_result, Ok((expected_hash, expected_fee)),); @@ -906,7 +882,7 @@ mod tests { let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, + data: DispatchMessageData { payload: Ok((location, xcm).into()) }, }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 60bc038339620..ceabcd57b6663 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -24,35 +24,20 @@ use crate::{MillauGrandpaInstance, OriginCaller, Runtime, RuntimeCall, RuntimeOr use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, + InboundLaneData, LaneId, Message, MessageNonce, }; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, -}; -use codec::{Decode, Encode}; -use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use sp_std::convert::TryFrom; +use bridge_runtime_common::messages::{self, MessageBridge}; +use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Millau. pub const DEFAULT_XCM_LANE_TO_MILLAU: LaneId = [0, 0, 0, 0]; -/// Initial value of `MillauToRialtoParachainConversionRate` parameter. -pub const INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE: FixedU128 = - FixedU128::from_inner(FixedU128::DIV); -/// Initial value of `MillauFeeMultiplier` parameter. -pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::BASE_XCM_WEIGHT; parameter_types! { - /// Millau to RialtoParachain conversion rate. Initially we treat both tokens as equal. - pub storage MillauToRialtoParachainConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE; - /// Fee multiplier value at Millau chain. - pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER; /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge @@ -94,7 +79,6 @@ pub type ToMillauMaximalOutboundPayloadSize = pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = @@ -104,16 +88,6 @@ impl MessageBridge for WithMillauMessageBridge { type BridgedChain = Millau; type BridgedHeaderChain = pallet_bridge_grandpa::GrandpaChainHeaders; - - fn bridged_balance_to_this_balance( - bridged_balance: bp_millau::Balance, - bridged_to_this_conversion_rate_override: Option, - ) -> bp_rialto_parachain::Balance { - let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(MillauToRialtoParachainConversionRate::get); - bp_rialto_parachain::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) - .unwrap_or(bp_rialto_parachain::Balance::MAX) - } } /// RialtoParachain chain from message lane point of view. @@ -127,12 +101,6 @@ impl messages::UnderlyingChainProvider for RialtoParachain { impl messages::ThisChainWithMessages for RialtoParachain { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - bp_rialto_parachain::AccountId, - { bp_rialto_parachain::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, - { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, - { bp_rialto_parachain::TX_EXTRA_BYTES }, - >; fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { let here_location = xcm::v3::MultiLocation::from(crate::UniversalLocation::get()); @@ -156,25 +124,6 @@ impl messages::ThisChainWithMessages for RialtoParachain { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } - - fn transaction_payment( - transaction: MessageTransaction, - ) -> bp_rialto_parachain::Balance { - // `transaction` may represent transaction from the future, when multiplier value will - // be larger, so let's use slightly increased value - let multiplier = FixedU128::saturating_from_rational(110, 100) - .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_rialto_parachain::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } /// Millau chain from message lane point of view. @@ -189,45 +138,6 @@ impl messages::BridgedChainWithMessages for Millau { fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } - - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction { - let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = message_payload_len - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); - - MessageTransaction { - dispatch_weight: bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT - .saturating_mul(extra_bytes_in_payload as u64) - .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) - .saturating_sub(if include_pay_dispatch_fee_cost { - Weight::from_ref_time(0) - } else { - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT - }) - .saturating_add(message_dispatch_weight), - size: message_payload_len - .saturating_add(bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_millau::TX_EXTRA_BYTES), - } - } - - fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { - // we don't have a direct access to the value of multiplier at Millau chain - // => it is a messages module parameter - let multiplier = MillauFeeMultiplier::get(); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } impl TargetHeaderChain for Millau { @@ -249,7 +159,7 @@ impl TargetHeaderChain f } } -impl SourceHeaderChain for Millau { +impl SourceHeaderChain for Millau { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; @@ -261,25 +171,8 @@ impl SourceHeaderChain for Millau { fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { messages::target::verify_messages_proof::(proof, messages_count) .map_err(Into::into) } } - -/// RialtoParachain -> Millau message lane pallet parameters. -#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub enum RialtoParachainToMillauMessagesParameter { - /// The conversion formula we use is: `RialtoParachainTokens = MillauTokens * conversion_rate`. - MillauToRialtoParachainConversionRate(FixedU128), -} - -impl MessagesParameter for RialtoParachainToMillauMessagesParameter { - fn save(&self) { - match *self { - RialtoParachainToMillauMessagesParameter::MillauToRialtoParachainConversionRate( - ref conversion_rate, - ) => MillauToRialtoParachainConversionRate::set(conversion_rate), - } - } -} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 53b0f821f3e48..3ce0b650dc5f1 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -32,13 +32,8 @@ pub mod millau_messages; pub mod parachains; pub mod xcm_config; -use crate::millau_messages::{ToMillauMessagePayload, WithMillauMessageBridge}; - use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bp_runtime::{HeaderId, HeaderIdProvider}; -use bridge_runtime_common::messages::{ - source::estimate_message_dispatch_and_delivery_fee, MessageBridge, -}; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; @@ -54,7 +49,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, FixedU128, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -445,9 +440,6 @@ parameter_types! { bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - // `IdentityFee` is used by Rialto => we may use weight directly - pub const GetDeliveryConfirmationTransactionFee: Balance = - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() as _; pub const RootAccountForPayments: Option = None; pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; } @@ -458,17 +450,14 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type Parameter = millau_messages::RialtoToMillauMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaximalOutboundPayloadSize = crate::millau_messages::ToMillauMaximalOutboundPayloadSize; type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; - type OutboundMessageFee = Balance; type InboundPayload = crate::millau_messages::FromMillauMessagePayload; - type InboundMessageFee = bp_millau::Balance; type InboundRelayer = bp_millau::AccountId; type TargetHeaderChain = crate::millau_messages::Millau; @@ -477,7 +466,6 @@ impl pallet_bridge_messages::Config for Runtime { pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< Runtime, WithMillauMessagesInstance, - GetDeliveryConfirmationTransactionFee, >; type OnMessageAccepted = (); type OnDeliveryConfirmed = (); @@ -958,24 +946,12 @@ impl_runtime_apis! { } } - impl bp_millau::ToMillauOutboundLaneApi for Runtime { - fn estimate_message_delivery_and_dispatch_fee( - _lane_id: bp_messages::LaneId, - payload: ToMillauMessagePayload, - millau_to_this_conversion_rate: Option, - ) -> Option { - estimate_message_dispatch_and_delivery_fee::( - &payload, - WithMillauMessageBridge::RELAYER_FEE_PERCENT, - millau_to_this_conversion_rate, - ).ok() - } - + impl bp_millau::ToMillauOutboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, begin: bp_messages::MessageNonce, end: bp_messages::MessageNonce, - ) -> Vec> { + ) -> Vec { bridge_runtime_common::messages_api::outbound_message_details::< Runtime, WithMillauMessagesInstance, @@ -983,10 +959,10 @@ impl_runtime_apis! { } } - impl bp_millau::FromMillauInboundLaneApi for Runtime { + impl bp_millau::FromMillauInboundLaneApi for Runtime { fn message_details( lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, ) -> Vec { bridge_runtime_common::messages_api::inbound_message_details::< Runtime, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index cf8812eaf9a69..9eb6c82f3678d 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -21,33 +21,18 @@ use crate::{MillauGrandpaInstance, OriginCaller, Runtime, RuntimeCall, RuntimeOr use bp_messages::{ source_chain::TargetHeaderChain, target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, Parameter as MessagesParameter, + InboundLaneData, LaneId, Message, MessageNonce, }; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, BasicConfirmationTransactionEstimation, MessageBridge, MessageTransaction, -}; -use codec::{Decode, Encode}; -use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight, RuntimeDebug}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; -use sp_std::convert::TryFrom; - -/// Initial value of `MillauToRialtoConversionRate` parameter. -pub const INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE: FixedU128 = - FixedU128::from_inner(FixedU128::DIV); -/// Initial value of `MillauFeeMultiplier` parameter. -pub const INITIAL_MILLAU_FEE_MULTIPLIER: FixedU128 = FixedU128::from_inner(FixedU128::DIV); +use bridge_runtime_common::messages::{self, MessageBridge}; +use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; + /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; parameter_types! { - /// Millau to Rialto conversion rate. Initially we treat both tokens as equal. - pub storage MillauToRialtoConversionRate: FixedU128 = INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE; - /// Fee multiplier value at Millau chain. - pub storage MillauFeeMultiplier: FixedU128 = INITIAL_MILLAU_FEE_MULTIPLIER; /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge @@ -89,7 +74,6 @@ pub type ToMillauMaximalOutboundPayloadSize = pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; @@ -98,16 +82,6 @@ impl MessageBridge for WithMillauMessageBridge { type BridgedChain = Millau; type BridgedHeaderChain = pallet_bridge_grandpa::GrandpaChainHeaders; - - fn bridged_balance_to_this_balance( - bridged_balance: bp_millau::Balance, - bridged_to_this_conversion_rate_override: Option, - ) -> bp_rialto::Balance { - let conversion_rate = bridged_to_this_conversion_rate_override - .unwrap_or_else(MillauToRialtoConversionRate::get); - bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance)) - .unwrap_or(bp_rialto::Balance::MAX) - } } /// Rialto chain from message lane point of view. @@ -121,12 +95,6 @@ impl messages::UnderlyingChainProvider for Rialto { impl messages::ThisChainWithMessages for Rialto { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; - type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - bp_rialto::AccountId, - { bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT.ref_time() }, - { bp_millau::EXTRA_STORAGE_PROOF_SIZE }, - { bp_rialto::TX_EXTRA_BYTES }, - >; fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { let here_location = @@ -151,21 +119,6 @@ impl messages::ThisChainWithMessages for Rialto { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } - - fn transaction_payment(transaction: MessageTransaction) -> bp_rialto::Balance { - // `transaction` may represent transaction from the future, when multiplier value will - // be larger, so let's use slightly increased value - let multiplier = FixedU128::saturating_from_rational(110, 100) - .saturating_mul(pallet_transaction_payment::Pallet::::next_fee_multiplier()); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_rialto::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } /// Millau chain from message lane point of view. @@ -180,45 +133,6 @@ impl messages::BridgedChainWithMessages for Millau { fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { true } - - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction { - let message_payload_len = u32::try_from(message_payload.len()).unwrap_or(u32::MAX); - let extra_bytes_in_payload = message_payload_len - .saturating_sub(pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH); - - MessageTransaction { - dispatch_weight: bp_millau::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT - .saturating_mul(extra_bytes_in_payload as u64) - .saturating_add(bp_millau::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT) - .saturating_sub(if include_pay_dispatch_fee_cost { - Weight::from_ref_time(0) - } else { - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT - }) - .saturating_add(message_dispatch_weight), - size: message_payload_len - .saturating_add(bp_rialto::EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(bp_millau::TX_EXTRA_BYTES), - } - } - - fn transaction_payment(transaction: MessageTransaction) -> bp_millau::Balance { - // we don't have a direct access to the value of multiplier at Millau chain - // => it is a messages module parameter - let multiplier = MillauFeeMultiplier::get(); - // in our testnets, both per-byte fee and weight-to-fee are 1:1 - messages::transaction_payment( - bp_millau::BlockWeights::get().get(DispatchClass::Normal).base_extrinsic, - 1, - multiplier, - |weight| weight.ref_time() as _, - transaction, - ) - } } impl TargetHeaderChain for Millau { @@ -240,7 +154,7 @@ impl TargetHeaderChain for Millau } } -impl SourceHeaderChain for Millau { +impl SourceHeaderChain for Millau { type Error = &'static str; // The proof is: // - hash of the header this proof has been created with; @@ -252,28 +166,12 @@ impl SourceHeaderChain for Millau { fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { messages::target::verify_messages_proof::(proof, messages_count) .map_err(Into::into) } } -/// Rialto -> Millau message lane pallet parameters. -#[derive(RuntimeDebug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub enum RialtoToMillauMessagesParameter { - /// The conversion formula we use is: `RialtoTokens = MillauTokens * conversion_rate`. - MillauToRialtoConversionRate(FixedU128), -} - -impl MessagesParameter for RialtoToMillauMessagesParameter { - fn save(&self) { - match *self { - RialtoToMillauMessagesParameter::MillauToRialtoConversionRate(ref conversion_rate) => - MillauToRialtoConversionRate::set(conversion_rate), - } - } -} - #[cfg(test)] mod tests { use super::*; @@ -291,13 +189,7 @@ mod tests { fn ensure_rialto_message_lane_weights_are_correct() { type Weights = pallet_bridge_messages::weights::BridgeWeight; - pallet_bridge_messages::ensure_weights_are_correct::( - bp_rialto::DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - bp_rialto::ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, - bp_rialto::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT, - DbWeight::get(), - ); + pallet_bridge_messages::ensure_weights_are_correct::(); let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), @@ -362,13 +254,5 @@ mod tests { bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, }, }); - - assert_eq!( - MillauToRialtoConversionRate::key().to_vec(), - bp_runtime::storage_parameter_key( - bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME - ) - .0, - ); } } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 780ce710ba9f6..b874ec8ce8534 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -238,7 +238,7 @@ mod tests { let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); let send_result = send_xcm::(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, 4_259_858_152_u128)); + let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); let expected_hash = ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); assert_eq!(send_result, Ok((expected_hash, expected_fee)),); @@ -262,7 +262,7 @@ mod tests { let mut incoming_message = DispatchMessage { key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()), fee: 0 }, + data: DispatchMessageData { payload: Ok((location, xcm).into()) }, }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 3b64d1e8afea5..a9a2c06470c97 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -88,10 +88,8 @@ macro_rules! assert_bridge_messages_pallet_types( use static_assertions::assert_type_eq_all; assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundMessageFee, BalanceOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload>>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundMessageFee, BalanceOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, BridgedChain<$bridge>); diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 320b91539b945..3bbf6df4f559a 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -24,26 +24,19 @@ use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, - InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData, + InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Size, StorageProofChecker}; -use codec::{Decode, DecodeLimit, Encode, MaxEncodedLen}; +use codec::{Decode, DecodeLimit, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedAdd, CheckedDiv, CheckedMul}, - FixedPointNumber, FixedPointOperand, FixedU128, -}; use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; use sp_trie::StorageProof; use xcm::latest::prelude::*; /// Bidirectional message bridge. pub trait MessageBridge { - /// Relayer interest (in percents). - const RELAYER_FEE_PERCENT: u32; - /// Identifier of this chain. const THIS_CHAIN_ID: ChainId; /// Identifier of the Bridged chain. @@ -59,60 +52,6 @@ pub trait MessageBridge { type BridgedChain: BridgedChainWithMessages; /// Bridged header chain. type BridgedHeaderChain: HeaderChain>; - - /// Convert Bridged chain balance into This chain balance. - fn bridged_balance_to_this_balance( - bridged_balance: BalanceOf>, - bridged_to_this_conversion_rate_override: Option, - ) -> BalanceOf>; -} - -/// Message related transaction parameters estimation. -#[derive(RuntimeDebug)] -pub struct MessageTransaction { - /// The estimated dispatch weight of the transaction. - pub dispatch_weight: Weight, - /// The estimated size of the encoded transaction. - pub size: u32, -} - -/// Helper trait for estimating the size and weight of a single message delivery confirmation -/// transaction. -pub trait ConfirmationTransactionEstimation { - // Estimate size and weight of single message delivery confirmation transaction. - fn estimate_delivery_confirmation_transaction() -> MessageTransaction; -} - -/// Default implementation for `ConfirmationTransactionEstimation`. -pub struct BasicConfirmationTransactionEstimation< - AccountId: MaxEncodedLen, - const MAX_CONFIRMATION_TX_WEIGHT: u64, - const EXTRA_STORAGE_PROOF_SIZE: u32, - const TX_EXTRA_BYTES: u32, ->(PhantomData); - -impl< - AccountId: MaxEncodedLen, - const MAX_CONFIRMATION_TX_WEIGHT: u64, - const EXTRA_STORAGE_PROOF_SIZE: u32, - const TX_EXTRA_BYTES: u32, - > ConfirmationTransactionEstimation - for BasicConfirmationTransactionEstimation< - AccountId, - MAX_CONFIRMATION_TX_WEIGHT, - EXTRA_STORAGE_PROOF_SIZE, - TX_EXTRA_BYTES, - > -{ - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - let inbound_data_size = InboundLaneData::::encoded_size_hint_u32(1, 1); - MessageTransaction { - dispatch_weight: Weight::from_ref_time(MAX_CONFIRMATION_TX_WEIGHT), - size: inbound_data_size - .saturating_add(EXTRA_STORAGE_PROOF_SIZE) - .saturating_add(TX_EXTRA_BYTES), - } - } } /// A trait that provides the type of the underlying chain. @@ -127,9 +66,6 @@ pub trait ThisChainWithMessages: UnderlyingChainProvider { type RuntimeOrigin; /// Call type on the chain. type RuntimeCall: Encode + Decode; - /// Helper for estimating the size and weight of a single message delivery confirmation - /// transaction at this chain. - type ConfirmationTransactionEstimation: ConfirmationTransactionEstimation; /// Do we accept message sent by given origin to given lane? fn is_message_accepted(origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool; @@ -138,14 +74,6 @@ pub trait ThisChainWithMessages: UnderlyingChainProvider { /// /// Any messages over this limit, will be rejected. fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; - - /// Estimate size and weight of single message delivery confirmation transaction at This chain. - fn estimate_delivery_confirmation_transaction() -> MessageTransaction { - Self::ConfirmationTransactionEstimation::estimate_delivery_confirmation_transaction() - } - - /// Returns minimal transaction fee that must be paid for given transaction at This chain. - fn transaction_payment(transaction: MessageTransaction) -> BalanceOf; } /// Bridged chain that has `pallet-bridge-messages` module. @@ -153,17 +81,6 @@ pub trait BridgedChainWithMessages: UnderlyingChainProvider { /// Returns `true` if message dispatch weight is withing expected limits. `false` means /// that the message is too heavy to be sent over the bridge and shall be rejected. fn verify_dispatch_weight(message_payload: &[u8]) -> bool; - - /// Estimate size and weight of single message delivery transaction at the Bridged chain. - fn estimate_delivery_transaction( - message_payload: &[u8], - include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction; - - /// Returns minimal transaction fee that must be paid for given transaction at the Bridged - /// chain. - fn transaction_payment(transaction: MessageTransaction) -> BalanceOf; } /// This chain in context of message bridge. @@ -188,33 +105,6 @@ pub type CallOf = ::RuntimeCall; /// Raw storage proof type (just raw trie nodes). pub type RawStorageProof = Vec>; -/// Compute fee of transaction at runtime where regular transaction payment pallet is being used. -/// -/// The value of `multiplier` parameter is the expected value of -/// `pallet_transaction_payment::NextFeeMultiplier` at the moment when transaction is submitted. If -/// you're charging this payment in advance (and that's what happens with delivery and confirmation -/// transaction in this crate), then there's a chance that the actual fee will be larger than what -/// is paid in advance. So the value must be chosen carefully. -pub fn transaction_payment( - base_extrinsic_weight: Weight, - per_byte_fee: Balance, - multiplier: FixedU128, - weight_to_fee: impl Fn(Weight) -> Balance, - transaction: MessageTransaction, -) -> Balance { - // base fee is charged for every tx - let base_fee = weight_to_fee(base_extrinsic_weight); - - // non-adjustable per-byte fee - let len_fee = per_byte_fee.saturating_mul(Balance::from(transaction.size)); - - // the adjustable part of the fee - let unadjusted_weight_fee = weight_to_fee(transaction.dispatch_weight); - let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee); - - base_fee.saturating_add(len_fee).saturating_add(adjusted_weight_fee) -} - /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -286,15 +176,9 @@ pub mod source { pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; /// The error message returned from LaneMessageVerifier when call origin is mismatch. pub const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; - /// The error message returned from LaneMessageVerifier when the message fee is too low. - pub const TOO_LOW_FEE: &str = "Provided fee is below minimal threshold required by the lane."; - impl - LaneMessageVerifier< - OriginOf>, - FromThisChainMessagePayload, - BalanceOf>, - > for FromThisChainMessageVerifier + impl LaneMessageVerifier>, FromThisChainMessagePayload> + for FromThisChainMessageVerifier where B: MessageBridge, // matches requirements from the `frame_system::Config::Origin` @@ -306,10 +190,9 @@ pub mod source { fn verify_message( submitter: &OriginOf>, - delivery_and_dispatch_fee: &BalanceOf>, lane: &LaneId, lane_outbound_data: &OutboundLaneData, - payload: &FromThisChainMessagePayload, + _payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { // reject message if lane is blocked if !ThisChain::::is_message_accepted(submitter, lane) { @@ -325,17 +208,6 @@ pub mod source { return Err(TOO_MANY_PENDING_MESSAGES) } - let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( - payload, - B::RELAYER_FEE_PERCENT, - None, - )?; - - // compare with actual fee paid - if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { - return Err(TOO_LOW_FEE) - } - Ok(()) } } @@ -376,52 +248,6 @@ pub mod source { Ok(()) } - /// Estimate delivery and dispatch fee that must be paid for delivering a message to the Bridged - /// chain. - /// - /// The fee is paid in This chain Balance, but we use Bridged chain balance to avoid additional - /// conversions. Returns `None` if overflow has happened. - pub fn estimate_message_dispatch_and_delivery_fee( - payload: &FromThisChainMessagePayload, - relayer_fee_percent: u32, - bridged_to_this_conversion_rate: Option, - ) -> Result>, &'static str> { - // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain - // - // if we're going to pay dispatch fee at the target chain, then we don't include weight - // of the message dispatch in the delivery transaction cost - let delivery_transaction = BridgedChain::::estimate_delivery_transaction( - &payload.encode(), - true, - Weight::zero(), - ); - let delivery_transaction_fee = BridgedChain::::transaction_payment(delivery_transaction); - - // the fee (in This tokens) of all transactions that are made on This chain - let confirmation_transaction = ThisChain::::estimate_delivery_confirmation_transaction(); - let confirmation_transaction_fee = - ThisChain::::transaction_payment(confirmation_transaction); - - // minimal fee (in This tokens) is a sum of all required fees - let minimal_fee = B::bridged_balance_to_this_balance( - delivery_transaction_fee, - bridged_to_this_conversion_rate, - ) - .checked_add(&confirmation_transaction_fee); - - // before returning, add extra fee that is paid to the relayer (relayer interest) - minimal_fee - .and_then(|fee| - // having message with fee that is near the `Balance::MAX_VALUE` of the chain is - // unlikely and should be treated as an error - // => let's do multiplication first - fee - .checked_mul(&relayer_fee_percent.into()) - .and_then(|interest| interest.checked_div(&100u32.into())) - .and_then(|interest| fee.checked_add(&interest))) - .ok_or("Overflow when computing minimal required message delivery and dispatch fee") - } - /// Verify proof of This -> Bridged chain messages delivery. /// /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged @@ -462,7 +288,6 @@ pub mod source { /// Runtime message sender adapter. type MessageSender: bp_messages::source_chain::MessagesBridge< OriginOf>, - BalanceOf>, FromThisChainMessagePayload, >; @@ -484,7 +309,7 @@ pub mod source { BalanceOf>: Into, OriginOf>: From, { - type Ticket = (BalanceOf>, FromThisChainMessagePayload); + type Ticket = FromThisChainMessagePayload; fn validate( dest: &mut Option, @@ -499,39 +324,22 @@ pub mod source { let route = T::build_destination(); let msg = (route, msg.take().ok_or(SendError::MissingArgument)?).encode(); - let fee = estimate_message_dispatch_and_delivery_fee::( - &msg, - T::MessageBridge::RELAYER_FEE_PERCENT, - None, - ); - let fee = match fee { - Ok(fee) => fee, - Err(e) => { - log::trace!( - target: "runtime::bridge", - "Failed to comupte fee for XCM message to {:?}: {:?}", - T::MessageBridge::BRIDGED_CHAIN_ID, - e, - ); - *dest = Some(d); - return Err(SendError::Transport(e)) - }, - }; - let fee_assets = MultiAssets::from((Here, fee)); + // let's just take fixed (out of thin air) fee per message in our test bridges + // (this code won't be used in production anyway) + let fee_assets = MultiAssets::from((Here, 1_000_000_u128)); - Ok(((fee, msg), fee_assets)) + Ok((msg, fee_assets)) } fn deliver(ticket: Self::Ticket) -> Result { use bp_messages::source_chain::MessagesBridge; let lane = T::xcm_lane(); - let (fee, msg) = ticket; + let msg = ticket; let result = T::MessageSender::send_message( pallet_xcm::Origin::from(MultiLocation::from(T::universal_location())).into(), lane, msg, - fee, ); result .map(|artifacts| { @@ -633,7 +441,7 @@ pub mod target { } impl - MessageDispatch>, BalanceOf>> + MessageDispatch>> for FromBridgedChainMessageDispatch where XcmExecutor: xcm::v3::ExecuteXcm>>, @@ -643,7 +451,7 @@ pub mod target { type DispatchPayload = FromBridgedChainMessagePayload>>; fn dispatch_weight( - message: &mut DispatchMessage>>, + message: &mut DispatchMessage, ) -> frame_support::weights::Weight { match message.data.payload { Ok(ref mut payload) => { @@ -673,7 +481,7 @@ pub mod target { fn dispatch( _relayer_account: &AccountIdOf>, - message: DispatchMessage>>, + message: DispatchMessage, ) -> MessageDispatchResult { let message_id = (message.key.lane_id, message.key.nonce); let do_dispatch = move || -> sp_std::result::Result { @@ -738,7 +546,7 @@ pub mod target { pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof>>, messages_count: u32, - ) -> Result>>>, MessageProofError> { + ) -> Result, MessageProofError> { let FromBridgedChainMessagesProof { bridged_header_hash, storage_proof, @@ -779,11 +587,9 @@ pub mod target { let raw_message_data = parser .read_raw_message(&message_key) .ok_or(MessageProofError::MissingRequiredMessage)?; - let message_data = MessageData::>>::decode( - &mut &raw_message_data[..], - ) - .map_err(|_| MessageProofError::FailedToDecodeMessage)?; - messages.push(Message { key: message_key, data: message_data }); + let payload = MessagePayload::decode(&mut &raw_message_data[..]) + .map_err(|_| MessageProofError::FailedToDecodeMessage)?; + messages.push(Message { key: message_key, payload }); } // Now let's check if proof contains outbound lane state proof. It is optional, so @@ -885,11 +691,6 @@ mod tests { use sp_runtime::traits::{BlakeTwo256, Header as _}; use std::cell::RefCell; - const DELIVERY_TRANSACTION_WEIGHT: Weight = Weight::from_ref_time(100); - const DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT: u64 = 100; - const THIS_CHAIN_WEIGHT_TO_BALANCE_RATE: u32 = 2; - const BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE: u32 = 4; - const BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE: u32 = 6; const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; @@ -900,7 +701,6 @@ mod tests { struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { - const RELAYER_FEE_PERCENT: u32 = 10; const THIS_CHAIN_ID: ChainId = *b"this"; const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; @@ -908,16 +708,6 @@ mod tests { type ThisChain = ThisChain; type BridgedChain = BridgedChain; type BridgedHeaderChain = BridgedHeaderChain; - - fn bridged_balance_to_this_balance( - bridged_balance: BridgedChainBalance, - bridged_to_this_conversion_rate_override: Option, - ) -> ThisChainBalance { - let conversion_rate = bridged_to_this_conversion_rate_override - .map(|r| r.to_float() as u32) - .unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE); - bridged_balance as ThisChainBalance * conversion_rate as ThisChainBalance - } } /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from @@ -926,7 +716,6 @@ mod tests { struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { - const RELAYER_FEE_PERCENT: u32 = 20; const THIS_CHAIN_ID: ChainId = *b"brdg"; const BRIDGED_CHAIN_ID: ChainId = *b"this"; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; @@ -934,13 +723,6 @@ mod tests { type ThisChain = BridgedChain; type BridgedChain = ThisChain; type BridgedHeaderChain = ThisHeaderChain; - - fn bridged_balance_to_this_balance( - _this_balance: ThisChainBalance, - _bridged_to_this_conversion_rate_override: Option, - ) -> BridgedChainBalance { - unreachable!() - } } #[derive(Clone, Debug)] @@ -989,6 +771,7 @@ mod tests { fn max_extrinsic_size() -> u32 { BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE } + fn max_extrinsic_weight() -> Weight { Weight::zero() } @@ -1003,12 +786,6 @@ mod tests { impl ThisChainWithMessages for ThisChain { type RuntimeOrigin = ThisChainOrigin; type RuntimeCall = ThisChainCall; - type ConfirmationTransactionEstimation = BasicConfirmationTransactionEstimation< - ThisChainAccountId, - { DELIVERY_CONFIRMATION_TRANSACTION_WEIGHT }, - 0, - 0, - >; fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { lane == TEST_LANE_ID @@ -1017,31 +794,12 @@ mod tests { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE } - - fn transaction_payment(transaction: MessageTransaction) -> BalanceOf { - transaction - .dispatch_weight - .saturating_mul(THIS_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) - .ref_time() as _ - } } impl BridgedChainWithMessages for ThisChain { fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { unreachable!() } - - fn estimate_delivery_transaction( - _message_payload: &[u8], - _include_pay_dispatch_fee_cost: bool, - _message_dispatch_weight: Weight, - ) -> MessageTransaction { - unreachable!() - } - - fn transaction_payment(_transaction: MessageTransaction) -> BalanceOf { - unreachable!() - } } struct BridgedUnderlyingChain; @@ -1078,8 +836,6 @@ mod tests { impl ThisChainWithMessages for BridgedChain { type RuntimeOrigin = BridgedChainOrigin; type RuntimeCall = BridgedChainCall; - type ConfirmationTransactionEstimation = - BasicConfirmationTransactionEstimation; fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { unreachable!() @@ -1088,10 +844,6 @@ mod tests { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { unreachable!() } - - fn transaction_payment(_transaction: MessageTransaction) -> BalanceOf { - unreachable!() - } } impl BridgedChainWithMessages for BridgedChain { @@ -1099,24 +851,6 @@ mod tests { message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT } - - fn estimate_delivery_transaction( - _message_payload: &[u8], - _include_pay_dispatch_fee_cost: bool, - message_dispatch_weight: Weight, - ) -> MessageTransaction { - MessageTransaction { - dispatch_weight: DELIVERY_TRANSACTION_WEIGHT + message_dispatch_weight, - size: 0, - } - } - - fn transaction_payment(transaction: MessageTransaction) -> BalanceOf { - transaction - .dispatch_weight - .saturating_mul(BRIDGED_CHAIN_WEIGHT_TO_BALANCE_RATE as u64) - .ref_time() as _ - } } thread_local! { @@ -1152,50 +886,11 @@ mod tests { vec![42] } - #[test] - fn message_fee_is_checked_by_verifier() { - const EXPECTED_MINIMAL_FEE: u32 = 2860; - - // payload of the This -> Bridged chain message - let payload = regular_outbound_message_payload(); - - // let's check if estimation matching hardcoded value - assert_eq!( - source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ), - Ok(EXPECTED_MINIMAL_FEE), - ); - - // and now check that the verifier checks the fee - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &1, - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ), - Err(source::TOO_LOW_FEE) - ); - assert!(source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &1_000_000, - TEST_LANE_ID, - &test_lane_outbound_data(), - &payload, - ) - .is_ok(),); - } - #[test] fn message_is_rejected_when_sent_using_disabled_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &1_000_000, b"dsbl", &test_lane_outbound_data(), ®ular_outbound_message_payload(), @@ -1209,7 +904,6 @@ mod tests { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - &1_000_000, TEST_LANE_ID, &OutboundLaneData { latest_received_nonce: 100, @@ -1267,7 +961,7 @@ mod tests { fn using_messages_proof( nonces_end: MessageNonce, outbound_lane_data: Option, - encode_message: impl Fn(MessageNonce, &MessageData) -> Option>, + encode_message: impl Fn(MessageNonce, &MessagePayload) -> Option>, encode_outbound_lane_data: impl Fn(&OutboundLaneData) -> Vec, test: impl Fn(target::FromBridgedChainMessagesProof) -> R, ) -> R { @@ -1366,10 +1060,9 @@ mod tests { |n, m| { let mut m = m.encode(); if n == 5 { - m = MessageData { fee: 0, payload: vec![0u8; 42] }.encode(); - m.truncate(2); + m = vec![42] } - Some(m.encode()) + Some(m) }, encode_lane_data, |proof| target::verify_messages_proof::(proof, 10), @@ -1464,7 +1157,7 @@ mod tests { }), messages: vec![Message { key: MessageKey { lane_id: *TEST_LANE_ID, nonce: 1 }, - data: MessageData { payload: vec![42], fee: 0 }, + payload: vec![42], }], }, )] @@ -1483,53 +1176,4 @@ mod tests { Err(target::MessageProofError::MessagesCountMismatch), ); } - - #[test] - fn transaction_payment_works_with_zero_multiplier() { - use sp_runtime::traits::Zero; - - assert_eq!( - transaction_payment( - Weight::from_ref_time(100), - 10, - FixedU128::zero(), - |weight| weight.ref_time(), - MessageTransaction { size: 50, dispatch_weight: Weight::from_ref_time(777) }, - ), - 100 + 50 * 10, - ); - } - - #[test] - fn transaction_payment_works_with_non_zero_multiplier() { - use sp_runtime::traits::One; - - assert_eq!( - transaction_payment::( - Weight::from_ref_time(100), - 10, - FixedU128::one(), - |weight| weight.ref_time(), - MessageTransaction { size: 50, dispatch_weight: Weight::from_ref_time(777) }, - ), - 100 + 50 * 10 + 777, - ); - } - - #[test] - fn conversion_rate_override_works() { - let payload = regular_outbound_message_payload(); - let regular_fee = source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - None, - ); - let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::( - &payload, - OnThisChainBridge::RELAYER_FEE_PERCENT, - Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)), - ); - - assert!(regular_fee < overrided_fee); - } } diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index 28090daee5ae0..199e062fe9826 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -26,7 +26,7 @@ pub fn outbound_message_details( lane: LaneId, begin: MessageNonce, end: MessageNonce, -) -> Vec> +) -> Vec where Runtime: pallet_bridge_messages::Config, MessagesPalletInstance: 'static, @@ -40,10 +40,7 @@ where // dispatch message weight is always zero at the source chain, since we're paying for // dispatch at the target chain dispatch_weight: frame_support::weights::Weight::zero(), - size: message_data.payload.len() as _, - delivery_and_dispatch_fee: message_data.fee, - // we're delivering XCM messages here, so fee is always paid at the target chain - dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtTargetChain, + size: message_data.len() as _, }) }) .collect() @@ -52,7 +49,7 @@ where /// Implementation of the `To*InboundLaneApi::message_details`. pub fn inbound_message_details( lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, ) -> Vec where Runtime: pallet_bridge_messages::Config, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 24df69dc90a5e..919c03583b882 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -21,8 +21,7 @@ use crate::{ messages::{ - source::{FromBridgedChainMessagesDeliveryProof, FromThisChainMessagePayload}, - target::FromBridgedChainMessagesProof, + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, ThisChain, }, messages_generation::{ @@ -34,25 +33,12 @@ use bp_messages::storage_keys; use bp_runtime::{record_all_trie_keys, StorageProofSize}; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; -use pallet_bridge_messages::benchmarking::{ - MessageDeliveryProofParams, MessageParams, MessageProofParams, -}; +use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; use sp_core::Hasher; use sp_runtime::traits::{Header, MaybeSerializeDeserialize, Zero}; use sp_std::{fmt::Debug, prelude::*}; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; -/// Prepare outbound message for the `send_message` call. -pub fn prepare_outbound_message( - params: MessageParams>>, -) -> FromThisChainMessagePayload -where - B: MessageBridge, - BalanceOf>: From, -{ - vec![0; params.size as usize] -} - /// Prepare proof of messages for the `receive_messages_proof` call. /// /// In addition to returning valid messages proof, environment is prepared to verify this message diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index c5fb897b92681..28606d58dadfa 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -31,7 +31,6 @@ use sp_runtime::transaction_validity::TransactionValidity; impl< BridgedHeaderHash, SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< - >::InboundMessageFee, MessagesProof = FromBridgedChainMessagesProof, >, TargetHeaderChain: bp_messages::source_chain::TargetHeaderChain< diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs index 822b635cc9b63..560033d122a84 100644 --- a/bin/runtime-common/src/messages_generation.rs +++ b/bin/runtime-common/src/messages_generation.rs @@ -18,23 +18,19 @@ #![cfg(any(feature = "runtime-benchmarks", test))] -use crate::messages::{BalanceOf, BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof}; +use crate::messages::{BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof}; use bp_messages::{ - storage_keys, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, + storage_keys, LaneId, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; use bp_runtime::{record_all_trie_keys, StorageProofSize}; use codec::Encode; use sp_core::Hasher; -use sp_runtime::traits::Zero; use sp_std::{ops::RangeInclusive, prelude::*}; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; /// Simple and correct message data encode function. -pub(crate) fn encode_all_messages( - _: MessageNonce, - m: &MessageData, -) -> Option> { +pub(crate) fn encode_all_messages(_: MessageNonce, m: &MessagePayload) -> Option> { Some(m.encode()) } @@ -52,7 +48,7 @@ pub(crate) fn prepare_messages_storage_proof( outbound_lane_data: Option, size: StorageProofSize, message_payload: MessagePayload, - encode_message: impl Fn(MessageNonce, &MessageData>>) -> Option>, + encode_message: impl Fn(MessageNonce, &MessagePayload) -> Option>, encode_outbound_lane_data: impl Fn(&OutboundLaneData) -> Vec, ) -> (HashOf>, RawStorageProof) where @@ -71,12 +67,8 @@ where // insert messages for nonce in message_nonces { let message_key = MessageKey { lane_id: lane, nonce }; - let message_data = MessageData { - fee: BalanceOf::>::zero(), - payload: message_payload.clone(), - }; - let message_data = match encode_message(nonce, &message_data) { - Some(message_data) => message_data, + let message_payload = match encode_message(nonce, &message_payload) { + Some(message_payload) => message_payload, None => continue, }; let storage_key = storage_keys::message_key( @@ -85,7 +77,7 @@ where message_key.nonce, ) .0; - trie.insert(&storage_key, &message_data) + trie.insert(&storage_key, &message_payload) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); storage_keys.push(storage_key); diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index bb9d5270b54fa..6997713face51 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 +//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -59,9 +59,9 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - Weight::from_ref_time(105_417_000 as u64) - .saturating_add(Weight::from_ref_time(40_923_000 as u64).saturating_mul(p as u64)) - .saturating_add(Weight::from_ref_time(1_691_000 as u64).saturating_mul(v as u64)) + Weight::from_ref_time(198_274_668 as u64) + .saturating_add(Weight::from_ref_time(39_830_948 as u64).saturating_mul(p as u64)) + .saturating_add(Weight::from_ref_time(1_535_681 as u64).saturating_mul(v as u64)) .saturating_add(T::DbWeight::get().reads(7 as u64)) .saturating_add(T::DbWeight::get().writes(6 as u64)) } @@ -70,9 +70,9 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - Weight::from_ref_time(105_417_000 as u64) - .saturating_add(Weight::from_ref_time(40_923_000 as u64).saturating_mul(p as u64)) - .saturating_add(Weight::from_ref_time(1_691_000 as u64).saturating_mul(v as u64)) + Weight::from_ref_time(198_274_668 as u64) + .saturating_add(Weight::from_ref_time(39_830_948 as u64).saturating_mul(p as u64)) + .saturating_add(Weight::from_ref_time(1_535_681 as u64).saturating_mul(v as u64)) .saturating_add(RocksDbWeight::get().reads(7 as u64)) .saturating_add(RocksDbWeight::get().writes(6 as u64)) } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index e7650f17214db..254ba6cbace30 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -18,35 +18,25 @@ use crate::{ inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, - outbound_lane::ReceivalConfirmationResult, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, - OutboundLanes, OutboundMessages, + weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, OutboundLanes, }; use bp_messages::{ source_chain::TargetHeaderChain, target_chain::SourceHeaderChain, DeliveredMessages, - InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, OutboundLaneData, - UnrewardedRelayer, UnrewardedRelayersState, + InboundLaneData, LaneId, MessageNonce, OutboundLaneData, UnrewardedRelayer, + UnrewardedRelayersState, }; -use bp_runtime::{messages::DispatchFeePayment, StorageProofSize}; +use bp_runtime::StorageProofSize; use frame_benchmarking::{account, benchmarks_instance_pallet}; -use frame_support::{traits::Get, weights::Weight}; +use frame_support::weights::Weight; use frame_system::RawOrigin; -use sp_std::{collections::vec_deque::VecDeque, convert::TryInto, ops::RangeInclusive, prelude::*}; +use sp_std::{ops::RangeInclusive, prelude::*}; const SEED: u32 = 0; /// Pallet we're benchmarking here. pub struct Pallet, I: 'static>(crate::Pallet); -/// Benchmark-specific message parameters. -#[derive(Debug)] -pub struct MessageParams { - /// Size of the message payload. - pub size: u32, - /// Message sender account. - pub sender_account: ThisAccountId, -} - /// Benchmark-specific message proof parameters. #[derive(Debug)] pub struct MessageProofParams { @@ -58,8 +48,6 @@ pub struct MessageProofParams { pub outbound_lane_data: Option, /// Proof size requirements. pub size: StorageProofSize, - /// Where the fee for dispatching message is paid? - pub dispatch_fee_payment: DispatchFeePayment, } /// Benchmark-specific message delivery proof parameters. @@ -79,29 +67,14 @@ pub trait Config: crate::Config { fn bench_lane_id() -> LaneId { Default::default() } - /// Get maximal size of the message payload. - fn maximal_message_size() -> u32; /// Return id of relayer account at the bridged chain. fn bridged_relayer_id() -> Self::InboundRelayer; - /// Return balance of given account. - fn account_balance(account: &Self::AccountId) -> Self::OutboundMessageFee; /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); - /// Fee paid by submitter for single message delivery. - fn message_fee() -> Self::OutboundMessageFee { - 100_000_000_000_000.into() - } - /// Prepare message to send over lane. - fn prepare_outbound_message( - params: MessageParams, - ) -> (Self::OutboundPayload, Self::OutboundMessageFee); /// Prepare messages proof to receive by the module. fn prepare_message_proof( params: MessageProofParams, - ) -> ( - >::MessagesProof, - Weight, - ); + ) -> (::MessagesProof, Weight); /// Prepare messages delivery proof to receive by the module. fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, @@ -115,156 +88,6 @@ benchmarks_instance_pallet! { // Benchmarks that are used directly by the runtime. // - // Benchmark `send_message` extrinsic with the worst possible conditions: - // * outbound lane already has state, so it needs to be read and decoded; - // * relayers fund account does not exists (in practice it needs to exist in production environment); - // * maximal number of messages is being pruned during the call; - // * message size is minimal for the target chain. - // - // Result of this benchmark is used as a base weight for `send_message` call. Then the 'message weight' - // (estimated using `send_half_maximal_message_worst_case` and `send_maximal_message_worst_case`) is - // added. - send_minimal_message_worst_case { - let lane_id = T::bench_lane_id(); - let sender = account("sender", 0, SEED); - T::endow_account(&sender); - - // 'send' messages that are to be pruned when our message is sent - for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { - send_regular_message::(); - } - confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - - let (payload, fee) = T::prepare_outbound_message(MessageParams { - size: 0, - sender_account: sender.clone(), - }); - }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) - verify { - assert_eq!( - crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, - T::MaxMessagesToPruneAtOnce::get() + 1, - ); - } - - // Benchmark `send_message` extrinsic with the worst possible conditions: - // * outbound lane already has state, so it needs to be read and decoded; - // * relayers fund account does not exists (in practice it needs to exist in production environment); - // * maximal number of messages is being pruned during the call; - // * message size is 1KB. - // - // With single KB of message size, the weight of the call is increased (roughly) by - // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. - send_1_kb_message_worst_case { - let lane_id = T::bench_lane_id(); - let sender = account("sender", 0, SEED); - T::endow_account(&sender); - - // 'send' messages that are to be pruned when our message is sent - for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { - send_regular_message::(); - } - confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - - let size = 1024; - assert!( - T::maximal_message_size() > size, - "This benchmark can only be used with runtime that accepts 1KB messages", - ); - - let (payload, fee) = T::prepare_outbound_message(MessageParams { - size, - sender_account: sender.clone(), - }); - }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) - verify { - assert_eq!( - crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, - T::MaxMessagesToPruneAtOnce::get() + 1, - ); - } - - // Benchmark `send_message` extrinsic with the worst possible conditions: - // * outbound lane already has state, so it needs to be read and decoded; - // * relayers fund account does not exists (in practice it needs to exist in production environment); - // * maximal number of messages is being pruned during the call; - // * message size is 16KB. - // - // With single KB of message size, the weight of the call is increased (roughly) by - // `(send_16_kb_message_worst_case - send_1_kb_message_worst_case) / 15`. - send_16_kb_message_worst_case { - let lane_id = T::bench_lane_id(); - let sender = account("sender", 0, SEED); - T::endow_account(&sender); - - // 'send' messages that are to be pruned when our message is sent - for _nonce in 1..=T::MaxMessagesToPruneAtOnce::get() { - send_regular_message::(); - } - confirm_message_delivery::(T::MaxMessagesToPruneAtOnce::get()); - - let size = 16 * 1024; - assert!( - T::maximal_message_size() > size, - "This benchmark can only be used with runtime that accepts 16KB messages", - ); - - let (payload, fee) = T::prepare_outbound_message(MessageParams { - size, - sender_account: sender.clone(), - }); - }: send_message(RawOrigin::Signed(sender), lane_id, payload, fee) - verify { - assert_eq!( - crate::OutboundLanes::::get(&T::bench_lane_id()).latest_generated_nonce, - T::MaxMessagesToPruneAtOnce::get() + 1, - ); - } - - // Benchmark `increase_message_fee` with following conditions: - // * message has maximal message; - // * submitter account is killed because its balance is less than ED after payment. - // - // Result of this benchmark is directly used by weight formula of the call. - maximal_increase_message_fee { - let sender = account("sender", 42, SEED); - T::endow_account(&sender); - - let additional_fee = T::account_balance(&sender); - let lane_id = T::bench_lane_id(); - let nonce = 1; - - send_regular_message_with_payload::(vec![42u8; T::maximal_message_size() as _]); - }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) - verify { - assert_eq!( - OutboundMessages::::get(MessageKey { lane_id, nonce }).unwrap().fee, - T::message_fee() + additional_fee, - ); - } - - // Benchmark `increase_message_fee` with following conditions: - // * message size varies from minimal to maximal; - // * submitter account is killed because its balance is less than ED after payment. - increase_message_fee { - let i in 0..T::maximal_message_size().try_into().unwrap_or_default(); - - let sender = account("sender", 42, SEED); - T::endow_account(&sender); - - let additional_fee = T::account_balance(&sender); - let lane_id = T::bench_lane_id(); - let nonce = 1; - - send_regular_message_with_payload::(vec![42u8; i as _]); - }: increase_message_fee(RawOrigin::Signed(sender.clone()), lane_id, nonce, additional_fee) - verify { - assert_eq!( - OutboundMessages::::get(MessageKey { lane_id, nonce }).unwrap().fee, - T::message_fee() + additional_fee, - ); - } - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; @@ -286,7 +109,6 @@ benchmarks_instance_pallet! { message_nonces: 21..=21, outbound_lane_data: None, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -321,7 +143,6 @@ benchmarks_instance_pallet! { message_nonces: 21..=22, outbound_lane_data: None, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) verify { @@ -360,7 +181,6 @@ benchmarks_instance_pallet! { latest_generated_nonce: 21, }), size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -392,7 +212,6 @@ benchmarks_instance_pallet! { message_nonces: 21..=21, outbound_lane_data: None, size: StorageProofSize::HasExtraNodes(1024), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -427,7 +246,6 @@ benchmarks_instance_pallet! { message_nonces: 21..=21, outbound_lane_data: None, size: StorageProofSize::HasExtraNodes(16 * 1024), - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -461,7 +279,6 @@ benchmarks_instance_pallet! { message_nonces: 21..=21, outbound_lane_data: None, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -479,7 +296,6 @@ benchmarks_instance_pallet! { // This is base benchmark for all other confirmations delivery benchmarks. receive_delivery_proof_for_single_message { let relayer_id: T::AccountId = account("relayer", 0, SEED); - let relayer_balance = T::account_balance(&relayer_id); // send message that we're going to confirm send_regular_message::(); @@ -515,7 +331,6 @@ benchmarks_instance_pallet! { // - weight(receive_delivery_proof_for_single_message)`. receive_delivery_proof_for_two_messages_by_single_relayer { let relayer_id: T::AccountId = account("relayer", 0, SEED); - let relayer_balance = T::account_balance(&relayer_id); // send message that we're going to confirm send_regular_message::(); @@ -554,9 +369,7 @@ benchmarks_instance_pallet! { // - weight(receive_delivery_proof_for_two_messages_by_single_relayer)`. receive_delivery_proof_for_two_messages_by_two_relayers { let relayer1_id: T::AccountId = account("relayer1", 1, SEED); - let relayer1_balance = T::account_balance(&relayer1_id); let relayer2_id: T::AccountId = account("relayer2", 2, SEED); - let relayer2_balance = T::account_balance(&relayer2_id); // send message that we're going to confirm send_regular_message::(); @@ -593,28 +406,7 @@ benchmarks_instance_pallet! { fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { payload: vec![], fee: T::message_fee() }); -} - -fn send_regular_message_with_payload, I: 'static>(payload: Vec) { - let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(MessageData { payload, fee: T::message_fee() }); -} - -fn confirm_message_delivery, I: 'static>(nonce: MessageNonce) { - let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - let latest_received_nonce = outbound_lane.data().latest_received_nonce; - let mut relayers = VecDeque::with_capacity((nonce - latest_received_nonce) as usize); - for nonce in latest_received_nonce + 1..=nonce { - relayers.push_back(UnrewardedRelayer { - relayer: (), - messages: DeliveredMessages::new(nonce, true), - }); - } - assert!(matches!( - outbound_lane.confirm_delivery(nonce - latest_received_nonce, nonce, &relayers), - ReceivalConfirmationResult::ConfirmedMessages(_), - )); + outbound_lane.send_message(vec![]); } fn receive_messages, I: 'static>(nonce: MessageNonce) { diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index bee1df06c5a71..ba4483e608c3c 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -31,8 +31,6 @@ use sp_std::prelude::PartialEq; /// Inbound lane storage. pub trait InboundLaneStorage { - /// Delivery and dispatch fee type on source chain. - type MessageFee; /// Id of relayer on source chain. type Relayer: Clone + PartialEq; @@ -183,12 +181,12 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message, AccountId>( + pub fn receive_message, AccountId>( &mut self, relayer_at_bridged_chain: &S::Relayer, relayer_at_this_chain: &AccountId, nonce: MessageNonce, - message_data: DispatchMessageData, + message_data: DispatchMessageData, ) -> ReceivalResult { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; @@ -242,9 +240,9 @@ mod tests { use crate::{ inbound_lane, mock::{ - dispatch_result, message_data, run_test, unrewarded_relayer, TestMessageDispatch, - TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, - TEST_RELAYER_C, + dispatch_result, inbound_message_data, run_test, unrewarded_relayer, + TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, + TEST_RELAYER_B, TEST_RELAYER_C, }, RuntimeInboundLaneStorage, }; @@ -258,7 +256,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, nonce, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -386,7 +384,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, 10, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::InvalidNonce ); @@ -406,7 +404,7 @@ mod tests { &(TEST_RELAYER_A + current_nonce), &(TEST_RELAYER_A + current_nonce), current_nonce, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -417,7 +415,7 @@ mod tests { &(TEST_RELAYER_A + max_nonce + 1), &(TEST_RELAYER_A + max_nonce + 1), max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::TooManyUnrewardedRelayers, ); @@ -427,7 +425,7 @@ mod tests { &(TEST_RELAYER_A + max_nonce), &(TEST_RELAYER_A + max_nonce), max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::TooManyUnrewardedRelayers, ); @@ -445,7 +443,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, current_nonce, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -456,7 +454,7 @@ mod tests { &TEST_RELAYER_B, &TEST_RELAYER_B, max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::TooManyUnconfirmedMessages, ); @@ -466,7 +464,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, max_nonce + 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::TooManyUnconfirmedMessages, ); @@ -482,7 +480,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -491,7 +489,7 @@ mod tests { &TEST_RELAYER_B, &TEST_RELAYER_B, 2, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -500,7 +498,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, 3, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -524,7 +522,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::Dispatched(dispatch_result(0)) ); @@ -533,7 +531,7 @@ mod tests { &TEST_RELAYER_B, &TEST_RELAYER_B, 1, - message_data(REGULAR_PAYLOAD).into() + inbound_message_data(REGULAR_PAYLOAD) ), ReceivalResult::InvalidNonce, ); @@ -560,7 +558,7 @@ mod tests { &TEST_RELAYER_A, &TEST_RELAYER_A, 1, - message_data(payload).into() + inbound_message_data(payload) ), ReceivalResult::Dispatched(dispatch_result(1)) ); diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 66f568e698c9e..d6a5ffe453c0b 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -38,7 +38,7 @@ #![allow(clippy::unused_unit)] pub use inbound_lane::StoredInboundLaneData; -pub use outbound_lane::StoredMessageData; +pub use outbound_lane::StoredMessagePayload; pub use weights::WeightInfo; pub use weights_ext::{ ensure_able_to_receive_confirmation, ensure_able_to_receive_message, @@ -59,17 +59,16 @@ use bp_messages::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, - MessageData, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, - OutboundMessageDetails, Parameter as MessagesParameter, UnrewardedRelayer, - UnrewardedRelayersState, + MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, + OutboundMessageDetails, UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; -use num_traits::{SaturatingAdd, Zero}; +use num_traits::Zero; use sp_std::{ - cell::RefCell, cmp::PartialOrd, collections::vec_deque::VecDeque, marker::PhantomData, - ops::RangeInclusive, prelude::*, + cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, + prelude::*, }; mod inbound_lane; @@ -108,11 +107,6 @@ pub mod pallet { /// Gets the chain id value from the instance. #[pallet::constant] type BridgedChainId: Get; - /// Pallet parameter that is opaque to the pallet itself, but may be used by the runtime - /// for integrating the pallet. - /// - /// All pallet parameters may only be updated either by the root, or by the pallet owner. - type Parameter: MessagesParameter; /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs /// whenever new message is sent. The reason is that if you want to use lane, you should @@ -142,25 +136,14 @@ pub mod pallet { /// these messages are from different lanes. type MaxUnconfirmedMessagesAtInboundLane: Get; - /// Maximal size of the outbound payload. + /// Maximal encoded size of the outbound payload. #[pallet::constant] type MaximalOutboundPayloadSize: Get; /// Payload type of outbound messages. This payload is dispatched on the bridged chain. type OutboundPayload: Parameter + Size; - /// Message fee type of outbound messages. This fee is paid on this chain. - type OutboundMessageFee: Default - + From - + PartialOrd - + Parameter - + SaturatingAdd - + Zero - + Copy - + MaxEncodedLen; /// Payload type of inbound messages. This payload is dispatched on this chain. type InboundPayload: Decode; - /// Message fee type of inbound messages. This fee is paid on the bridged chain. - type InboundMessageFee: Decode + Zero; /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the /// bridged chain. type InboundRelayer: Parameter + MaxEncodedLen; @@ -170,16 +153,11 @@ pub mod pallet { /// Target header chain. type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. - type LaneMessageVerifier: LaneMessageVerifier< - Self::RuntimeOrigin, - Self::OutboundPayload, - Self::OutboundMessageFee, - >; + type LaneMessageVerifier: LaneMessageVerifier; /// Message delivery payment. type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< Self::RuntimeOrigin, Self::AccountId, - Self::OutboundMessageFee, >; /// Handler for accepted messages. type OnMessageAccepted: OnMessageAccepted; @@ -189,19 +167,17 @@ pub mod pallet { // Types that are used by inbound_lane (on target chain). /// Source header chain, as it is represented on target chain. - type SourceHeaderChain: SourceHeaderChain; + type SourceHeaderChain: SourceHeaderChain; /// Message dispatch. type MessageDispatch: MessageDispatch< Self::AccountId, - Self::InboundMessageFee, DispatchPayload = Self::InboundPayload, >; } /// Shortcut to messages proof type for Config. - type MessagesProofOf = <>::SourceHeaderChain as SourceHeaderChain< - >::InboundMessageFee, - >>::MessagesProof; + type MessagesProofOf = + <>::SourceHeaderChain as SourceHeaderChain>::MessagesProof; /// Shortcut to messages delivery proof type for Config. type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< @@ -241,101 +217,6 @@ pub mod pallet { >::set_operating_mode(origin, operating_mode) } - /// Update pallet parameter. - /// - /// May only be called either by root, or by `PalletOwner`. - /// - /// The weight is: single read for permissions check + 2 writes for parameter value and - /// event. - #[pallet::weight((T::DbWeight::get().reads_writes(1, 2), DispatchClass::Operational))] - pub fn update_pallet_parameter( - origin: OriginFor, - parameter: T::Parameter, - ) -> DispatchResult { - Self::ensure_owner_or_root(origin)?; - parameter.save(); - Self::deposit_event(Event::ParameterUpdated { parameter }); - Ok(()) - } - - /// Send message over lane. - #[pallet::weight(T::WeightInfo::send_message_weight(payload, T::DbWeight::get()))] - pub fn send_message( - origin: OriginFor, - lane_id: LaneId, - payload: T::OutboundPayload, - delivery_and_dispatch_fee: T::OutboundMessageFee, - ) -> DispatchResultWithPostInfo { - crate::send_message::(origin, lane_id, payload, delivery_and_dispatch_fee).map( - |sent_message| PostDispatchInfo { - actual_weight: Some(sent_message.weight), - pays_fee: Pays::Yes, - }, - ) - } - - /// Pay additional fee for the message. - #[pallet::weight(T::WeightInfo::maximal_increase_message_fee())] - pub fn increase_message_fee( - origin: OriginFor, - lane_id: LaneId, - nonce: MessageNonce, - additional_fee: T::OutboundMessageFee, - ) -> DispatchResultWithPostInfo { - Self::ensure_not_halted().map_err(Error::::BridgeModule)?; - // if someone tries to pay for already-delivered message, we're rejecting this intention - // (otherwise this additional fee will be locked forever in relayers fund) - // - // if someone tries to pay for not-yet-sent message, we're rejecting this intention, or - // we're risking to have mess in the storage - let lane = outbound_lane::(lane_id); - ensure!( - nonce > lane.data().latest_received_nonce, - Error::::MessageIsAlreadyDelivered - ); - ensure!( - nonce <= lane.data().latest_generated_nonce, - Error::::MessageIsNotYetSent - ); - - // withdraw additional fee from submitter - T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( - &origin, - &additional_fee, - ) - .map_err(|err| { - log::trace!( - target: LOG_TARGET, - "Submitter can't pay additional fee {:?} for the message {:?}/{:?}: {:?}", - additional_fee, - lane_id, - nonce, - err, - ); - - Error::::FailedToWithdrawMessageFee - })?; - - // and finally update fee in the storage - let message_key = MessageKey { lane_id, nonce }; - let message_size = OutboundMessages::::mutate(message_key, |message_data| { - // saturating_add is fine here - overflow here means that someone controls all - // chain funds, which shouldn't ever happen + `pay_delivery_and_dispatch_fee` - // above will fail before we reach here - let message_data = message_data.as_mut().expect( - "the message is sent and not yet delivered; so it is in the storage; qed", - ); - message_data.fee = message_data.fee.saturating_add(&additional_fee); - message_data.payload.len() - }); - - // compute actual dispatch weight that depends on the stored message size - let actual_weight = T::WeightInfo::maximal_increase_message_fee() - .min(T::WeightInfo::increase_message_fee(message_size as _)); - - Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) - } - /// Receive messages proof from bridged chain. /// /// The weight of the call assumes that the transaction always brings outbound lane @@ -378,7 +259,6 @@ pub mod pallet { // verify messages proof && convert proof into messages let messages = verify_and_decode_messages_proof::< T::SourceHeaderChain, - T::InboundMessageFee, T::InboundPayload, >(proof, messages_count) .map_err(|err| { @@ -636,8 +516,6 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { - /// Pallet parameter has been updated. - ParameterUpdated { parameter: T::Parameter }, /// Message has been accepted and is waiting to be delivered. MessageAccepted { lane_id: LaneId, nonce: MessageNonce }, /// Messages in the inclusive range have been delivered to the bridged chain. @@ -709,7 +587,7 @@ pub mod pallet { /// All queued outbound messages. #[pallet::storage] pub type OutboundMessages, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, MessageKey, StoredMessageData>; + StorageMap<_, Blake2_128Concat, MessageKey, StoredMessagePayload>; #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { @@ -744,10 +622,7 @@ pub mod pallet { impl, I: 'static> Pallet { /// Get stored data of the outbound message with given nonce. - pub fn outbound_message_data( - lane: LaneId, - nonce: MessageNonce, - ) -> Option> { + pub fn outbound_message_data(lane: LaneId, nonce: MessageNonce) -> Option { OutboundMessages::::get(MessageKey { lane_id: lane, nonce }).map(Into::into) } @@ -755,12 +630,11 @@ pub mod pallet { pub fn inbound_message_data( lane: LaneId, payload: MessagePayload, - outbound_details: OutboundMessageDetails, + outbound_details: OutboundMessageDetails, ) -> InboundMessageDetails { let mut dispatch_message = DispatchMessage { key: MessageKey { lane_id: lane, nonce: outbound_details.nonce }, - data: MessageData { payload, fee: outbound_details.delivery_and_dispatch_fee } - .into(), + data: payload.into(), }; InboundMessageDetails { dispatch_weight: T::MessageDispatch::dispatch_weight(&mut dispatch_message), @@ -769,12 +643,8 @@ pub mod pallet { } } -impl - bp_messages::source_chain::MessagesBridge< - T::RuntimeOrigin, - T::OutboundMessageFee, - T::OutboundPayload, - > for Pallet +impl bp_messages::source_chain::MessagesBridge + for Pallet where T: Config, I: 'static, @@ -785,9 +655,8 @@ where sender: T::RuntimeOrigin, lane: LaneId, message: T::OutboundPayload, - delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> Result { - crate::send_message::(sender, lane, message, delivery_and_dispatch_fee) + crate::send_message::(sender, lane, message) } } @@ -796,21 +665,14 @@ fn send_message, I: 'static>( submitter: T::RuntimeOrigin, lane_id: LaneId, payload: T::OutboundPayload, - delivery_and_dispatch_fee: T::OutboundMessageFee, ) -> sp_std::result::Result< SendMessageArtifacts, sp_runtime::DispatchErrorWithPostInfo, > { ensure_normal_operating_mode::()?; - // the most lightweigh check is the message size check - ensure!( - payload.size() <= T::MaximalOutboundPayloadSize::get(), - Error::::MessageIsTooLarge, - ); - // initially, actual (post-dispatch) weight is equal to pre-dispatch weight - let mut actual_weight = T::WeightInfo::send_message_weight(&payload, T::DbWeight::get()); + let mut actual_weight = frame_support::weights::Weight::zero(); // TODO (https://github.com/paritytech/parity-bridges-common/issues/1647): remove this // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload).map_err(|err| { @@ -826,46 +688,28 @@ fn send_message, I: 'static>( // now let's enforce any additional lane rules let mut lane = outbound_lane::(lane_id); - T::LaneMessageVerifier::verify_message( - &submitter, - &delivery_and_dispatch_fee, - &lane_id, - &lane.data(), - &payload, - ) - .map_err(|err| { - log::trace!( - target: LOG_TARGET, - "Message to lane {:?} is rejected by lane verifier: {:?}", - lane_id, - err, - ); - - Error::::MessageRejectedByLaneVerifier - })?; - - // let's withdraw delivery and dispatch fee from submitter - T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee( - &submitter, - &delivery_and_dispatch_fee, - ) - .map_err(|err| { - log::trace!( - target: LOG_TARGET, - "Message to lane {:?} is rejected because submitter is unable to pay fee {:?}: {:?}", - lane_id, - delivery_and_dispatch_fee, - err, - ); + T::LaneMessageVerifier::verify_message(&submitter, &lane_id, &lane.data(), &payload).map_err( + |err| { + log::trace!( + target: LOG_TARGET, + "Message to lane {:?} is rejected by lane verifier: {:?}", + lane_id, + err, + ); - Error::::FailedToWithdrawMessageFee - })?; + Error::::MessageRejectedByLaneVerifier + }, + )?; // finally, save message in outbound storage and emit event let encoded_payload = payload.encode(); let encoded_payload_len = encoded_payload.len(); - let nonce = - lane.send_message(MessageData { payload: encoded_payload, fee: delivery_and_dispatch_fee }); + ensure!( + encoded_payload_len <= T::MaximalOutboundPayloadSize::get() as usize, + Error::::MessageIsTooLarge + ); + let nonce = lane.send_message(encoded_payload); + // Guaranteed to be called outside only when the message is accepted. // We assume that the maximum weight call back used is `single_message_callback_overhead`, so do // not perform complex db operation in callback. If you want to, put these magic logic in @@ -920,32 +764,26 @@ fn send_message, I: 'static>( Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } -/// Calculate the relayers rewards +/// Calculate the number of messages that the relayers have delivered. pub fn calc_relayers_rewards( - lane_id: LaneId, messages_relayers: VecDeque>, received_range: &RangeInclusive, -) -> RelayersRewards +) -> RelayersRewards where T: frame_system::Config + crate::Config, I: 'static, { // remember to reward relayers that have delivered messages // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let mut relayers_rewards: RelayersRewards<_, T::OutboundMessageFee> = RelayersRewards::new(); + let mut relayers_rewards = RelayersRewards::new(); for entry in messages_relayers { let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); // loop won't proceed if current entry is ahead of received range (begin > end). // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain - let mut relayer_reward = relayers_rewards.entry(entry.relayer).or_default(); - for nonce in nonce_begin..=nonce_end { - let key = MessageKey { lane_id, nonce }; - let message_data = OutboundMessages::::get(key) - .expect("message was just confirmed; we never prune unconfirmed messages; qed"); - relayer_reward.reward = relayer_reward.reward.saturating_add(&message_data.fee); - relayer_reward.messages += 1; + if nonce_end >= nonce_begin { + *relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1; } } relayers_rewards @@ -995,7 +833,6 @@ struct RuntimeInboundLaneStorage, I: 'static = ()> { } impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage { - type MessageFee = T::InboundMessageFee; type Relayer = T::InboundRelayer; fn id(&self) -> LaneId { @@ -1041,8 +878,6 @@ struct RuntimeOutboundLaneStorage { } impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage { - type MessageFee = T::OutboundMessageFee; - fn id(&self) -> LaneId { self.lane_id } @@ -1056,17 +891,20 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag } #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option> { + fn message(&self, nonce: &MessageNonce) -> Option { OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce }) .map(Into::into) } - fn save_message( - &mut self, - nonce: MessageNonce, - mesage_data: MessageData, - ) { - OutboundMessages::::insert(MessageKey { lane_id: self.lane_id, nonce }, mesage_data); + fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload) { + OutboundMessages::::insert( + MessageKey { lane_id: self.lane_id, nonce }, + StoredMessagePayload::::try_from(message_payload).expect( + "save_message is called after all checks in send_message; \ + send_message checks message size; \ + qed", + ), + ); } fn remove_message(&mut self, nonce: &MessageNonce) { @@ -1075,10 +913,10 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag } /// Verify messages proof and return proved messages with decoded payload. -fn verify_and_decode_messages_proof, Fee, DispatchPayload: Decode>( +fn verify_and_decode_messages_proof( proof: Chain::MessagesProof, messages_count: u32, -) -> Result>, Chain::Error> { +) -> Result>, Chain::Error> { // `receive_messages_proof` weight formula and `MaxUnconfirmedMessagesAtInboundLane` check // guarantees that the `message_count` is sane and Vec may be allocated. // (tx with too many messages will either be rejected from the pool, or will fail earlier) @@ -1102,12 +940,12 @@ fn verify_and_decode_messages_proof, Fee, Dispatch mod tests { use super::*; use crate::mock::{ - message, message_payload, run_test, unrewarded_relayer, Balance, RuntimeEvent as TestEvent, + message, message_payload, run_test, unrewarded_relayer, RuntimeEvent as TestEvent, RuntimeOrigin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, - TestMessagesParameter, TestMessagesProof, TestOnDeliveryConfirmed1, - TestOnDeliveryConfirmed2, TestOnMessageAccepted, TestRuntime, TokenConversionRate, - MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, - TEST_RELAYER_A, TEST_RELAYER_B, + TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, + TestOnMessageAccepted, TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, + PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, + TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -1146,15 +984,13 @@ mod tests { let message_nonce = outbound_lane::(TEST_LANE_ID).data().latest_generated_nonce + 1; - let weight = Pallet::::send_message( + let weight = send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight.ref_time(), ) .expect("send_message has failed") - .actual_weight - .expect("send_message always returns Some"); + .weight; // check event with assigned nonce assert_eq!( @@ -1169,12 +1005,6 @@ mod tests { }], ); - // check that fee has been withdrawn from submitter - assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid( - 1, - REGULAR_PAYLOAD.declared_weight.ref_time() - )); - weight } @@ -1217,102 +1047,6 @@ mod tests { ); } - #[test] - fn pallet_parameter_may_be_updated_by_root() { - run_test(|| { - get_ready_for_events(); - - let parameter = TestMessagesParameter::TokenConversionRate(10.into()); - assert_ok!(Pallet::::update_pallet_parameter( - RuntimeOrigin::root(), - parameter.clone(), - )); - - assert_eq!(TokenConversionRate::get(), 10.into()); - assert_eq!( - System::::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: TestEvent::Messages(Event::ParameterUpdated { parameter }), - topics: vec![], - }], - ); - }); - } - - #[test] - fn pallet_parameter_may_be_updated_by_owner() { - run_test(|| { - PalletOwner::::put(2); - get_ready_for_events(); - - let parameter = TestMessagesParameter::TokenConversionRate(10.into()); - assert_ok!(Pallet::::update_pallet_parameter( - RuntimeOrigin::signed(2), - parameter.clone(), - )); - - assert_eq!(TokenConversionRate::get(), 10.into()); - assert_eq!( - System::::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: TestEvent::Messages(Event::ParameterUpdated { parameter }), - topics: vec![], - }], - ); - }); - } - - #[test] - fn pallet_parameter_cant_be_updated_by_arbitrary_submitter() { - run_test(|| { - assert_noop!( - Pallet::::update_pallet_parameter( - RuntimeOrigin::signed(2), - TestMessagesParameter::TokenConversionRate(10.into()), - ), - DispatchError::BadOrigin, - ); - - PalletOwner::::put(2); - - assert_noop!( - Pallet::::update_pallet_parameter( - RuntimeOrigin::signed(1), - TestMessagesParameter::TokenConversionRate(10.into()), - ), - DispatchError::BadOrigin, - ); - }); - } - - #[test] - fn fixed_u128_works_as_i_think() { - // this test is here just to be sure that conversion rate may be represented with FixedU128 - run_test(|| { - use sp_runtime::{FixedPointNumber, FixedU128}; - - // 1:1 conversion that we use by default for testnets - let rialto_token = 1u64; - let rialto_token_in_millau_tokens = - TokenConversionRate::get().saturating_mul_int(rialto_token); - assert_eq!(rialto_token_in_millau_tokens, 1); - - // let's say conversion rate is 1:1.7 - let conversion_rate = FixedU128::saturating_from_rational(170, 100); - let rialto_tokens = 100u64; - let rialto_tokens_in_millau_tokens = conversion_rate.saturating_mul_int(rialto_tokens); - assert_eq!(rialto_tokens_in_millau_tokens, 170); - - // let's say conversion rate is 1:0.25 - let conversion_rate = FixedU128::saturating_from_rational(25, 100); - let rialto_tokens = 100u64; - let rialto_tokens_in_millau_tokens = conversion_rate.saturating_mul_int(rialto_tokens); - assert_eq!(rialto_tokens_in_millau_tokens, 25); - }); - } - #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { @@ -1324,25 +1058,14 @@ mod tests { )); assert_noop!( - Pallet::::send_message( + send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight.ref_time(), ), Error::::NotOperatingNormally, ); - assert_noop!( - Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 1, - ), - Error::::BridgeModule(bp_runtime::OwnedBridgeModuleError::Halted), - ); - assert_noop!( Pallet::::receive_messages_proof( RuntimeOrigin::signed(1), @@ -1389,22 +1112,14 @@ mod tests { ); assert_noop!( - Pallet::::send_message( + send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight.ref_time(), ), Error::::NotOperatingNormally, ); - assert_ok!(Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 1, - )); - assert_ok!(Pallet::::receive_messages_proof( RuntimeOrigin::signed(1), TEST_RELAYER_A, @@ -1451,25 +1166,23 @@ mod tests { .extra .extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]); assert_noop!( - Pallet::::send_message( + send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, message_payload.clone(), - Balance::MAX, ), Error::::MessageIsTooLarge, ); // let's check that we're able to send `MAX_OUTBOUND_PAYLOAD_SIZE` messages - while message_payload.size() > MAX_OUTBOUND_PAYLOAD_SIZE { + while message_payload.encoded_size() as u32 > MAX_OUTBOUND_PAYLOAD_SIZE { message_payload.extra.pop(); } - assert_eq!(message_payload.size(), MAX_OUTBOUND_PAYLOAD_SIZE); - assert_ok!(Pallet::::send_message( + assert_eq!(message_payload.encoded_size() as u32, MAX_OUTBOUND_PAYLOAD_SIZE); + assert_ok!(send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, message_payload, - Balance::MAX, ),); }) } @@ -1479,11 +1192,10 @@ mod tests { run_test(|| { // messages with this payload are rejected by target chain verifier assert_noop!( - Pallet::::send_message( + send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN, - PAYLOAD_REJECTED_BY_TARGET_CHAIN.declared_weight.ref_time(), ), Error::::MessageRejectedByChainVerifier, ); @@ -1494,34 +1206,15 @@ mod tests { fn lane_verifier_rejects_invalid_message_in_send_message() { run_test(|| { // messages with zero fee are rejected by lane verifier + let mut message = REGULAR_PAYLOAD; + message.reject_by_lane_verifier = true; assert_noop!( - Pallet::::send_message( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - 0 - ), + send_message::(RuntimeOrigin::signed(1), TEST_LANE_ID, message,), Error::::MessageRejectedByLaneVerifier, ); }); } - #[test] - fn message_send_fails_if_submitter_cant_pay_message_fee() { - run_test(|| { - TestMessageDeliveryAndDispatchPayment::reject_payments(); - assert_noop!( - Pallet::::send_message( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - REGULAR_PAYLOAD.declared_weight.ref_time(), - ), - Error::::FailedToWithdrawMessageFee, - ); - }); - } - #[test] fn receive_messages_proof_works() { run_test(|| { @@ -1665,17 +1358,15 @@ mod tests { #[test] fn receive_messages_delivery_proof_rewards_relayers() { run_test(|| { - assert_ok!(Pallet::::send_message( + assert_ok!(send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - 1000, )); - assert_ok!(Pallet::::send_message( + assert_ok!(send_message::( RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD, - 2000, )); // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A @@ -1697,8 +1388,8 @@ mod tests { ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1000)); - assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 2000)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1)); + assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1)); // this reports delivery of both message 1 and message 2 => reward is paid only to // TEST_RELAYER_B @@ -1723,8 +1414,8 @@ mod tests { ..Default::default() }, )); - assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1000)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 2000)); + assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1)); + assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1)); }); } @@ -1829,7 +1520,7 @@ mod tests { fn receive_messages_accepts_single_message_with_invalid_payload() { run_test(|| { let mut invalid_message = message(1, REGULAR_PAYLOAD); - invalid_message.data.payload = Vec::new(); + invalid_message.payload = Vec::new(); assert_ok!(Pallet::::receive_messages_proof( RuntimeOrigin::signed(1), @@ -1848,7 +1539,7 @@ mod tests { fn receive_messages_accepts_batch_with_message_with_invalid_payload() { run_test(|| { let mut invalid_message = message(2, REGULAR_PAYLOAD); - invalid_message.data.payload = Vec::new(); + invalid_message.payload = Vec::new(); assert_ok!(Pallet::::receive_messages_proof( RuntimeOrigin::signed(1), @@ -1884,73 +1575,6 @@ mod tests { }); } - #[test] - fn increase_message_fee_fails_if_message_is_already_delivered() { - run_test(|| { - send_regular_message(); - receive_messages_delivery_proof(); - - assert_noop!( - Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 100, - ), - Error::::MessageIsAlreadyDelivered, - ); - }); - } - - #[test] - fn increase_message_fee_fails_if_message_is_not_yet_sent() { - run_test(|| { - assert_noop!( - Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 100, - ), - Error::::MessageIsNotYetSent, - ); - }); - } - - #[test] - fn increase_message_fee_fails_if_submitter_cant_pay_additional_fee() { - run_test(|| { - send_regular_message(); - - TestMessageDeliveryAndDispatchPayment::reject_payments(); - - assert_noop!( - Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 100, - ), - Error::::FailedToWithdrawMessageFee, - ); - }); - } - - #[test] - fn increase_message_fee_succeeds() { - run_test(|| { - send_regular_message(); - - assert_ok!(Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 100, - ),); - assert!(TestMessageDeliveryAndDispatchPayment::is_fee_paid(1, 100)); - }); - } - #[test] fn weight_refund_from_receive_messages_proof_works() { run_test(|| { @@ -2187,101 +1811,6 @@ mod tests { }); } - #[test] - fn increase_message_fee_weight_depends_on_message_size() { - run_test(|| { - let mut small_payload = message_payload(0, 100); - let mut large_payload = message_payload(1, 100); - small_payload.extra = vec![1; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 10]; - large_payload.extra = vec![2; MAX_OUTBOUND_PAYLOAD_SIZE as usize / 5]; - - assert_ok!(Pallet::::send_message( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - small_payload, - 100, - )); - assert_ok!(Pallet::::send_message( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - large_payload, - 100, - )); - - let small_weight = Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 1, - 1, - ) - .expect("increase_message_fee has failed") - .actual_weight - .expect("increase_message_fee always returns Some"); - - let large_weight = Pallet::::increase_message_fee( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - 2, - 1, - ) - .expect("increase_message_fee has failed") - .actual_weight - .expect("increase_message_fee always returns Some"); - - assert!( - large_weight.ref_time() > small_weight.ref_time(), - "Actual post-dispatch weigth for larger message {} must be larger than {} for small message", - large_weight, - small_weight, - ); - }); - } - - #[test] - fn weight_is_refunded_for_messages_that_are_not_pruned() { - run_test(|| { - // send first MAX messages - no messages are pruned - let max_messages_to_prune = crate::mock::MaxMessagesToPruneAtOnce::get(); - let when_zero_messages_are_pruned = send_regular_message(); - let mut delivered_messages = DeliveredMessages::new(1, true); - for _ in 1..max_messages_to_prune { - assert_eq!(send_regular_message(), when_zero_messages_are_pruned); - delivered_messages.note_dispatched_message(true); - } - - // confirm delivery of all sent messages - assert_ok!(Pallet::::receive_messages_delivery_proof( - RuntimeOrigin::signed(1), - TestMessagesDeliveryProof(Ok(( - TEST_LANE_ID, - InboundLaneData { - last_confirmed_nonce: 1, - relayers: vec![UnrewardedRelayer { - relayer: 0, - messages: delivered_messages, - }] - .into_iter() - .collect(), - }, - ))), - UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - total_messages: max_messages_to_prune, - last_delivered_nonce: max_messages_to_prune, - ..Default::default() - }, - )); - - // when next message is sent, MAX messages are pruned - let weight_when_max_messages_are_pruned = send_regular_message(); - assert_eq!( - weight_when_max_messages_are_pruned, - when_zero_messages_are_pruned + - crate::mock::DbWeight::get().writes(max_messages_to_prune), - ); - }); - } - #[test] fn message_accepted_callbacks_are_called() { run_test(|| { @@ -2302,27 +1831,6 @@ mod tests { }); } - #[test] - fn message_accepted_refunds_non_zero_weight() { - run_test(|| { - TestOnMessageAccepted::set_consumed_weight_per_message( - crate::mock::DbWeight::get().writes(1), - ); - let actual_callback_weight = send_regular_message(); - let pre_dispatch_weight = ::WeightInfo::send_message_weight( - ®ULAR_PAYLOAD, - crate::mock::DbWeight::get(), - ); - let prune_weight = crate::mock::DbWeight::get() - .writes(::MaxMessagesToPruneAtOnce::get()); - - assert_eq!( - pre_dispatch_weight.saturating_sub(actual_callback_weight), - crate::mock::DbWeight::get().reads(1).saturating_add(prune_weight) - ); - }); - } - #[test] fn storage_keys_computed_properly() { assert_eq!( @@ -2360,9 +1868,6 @@ mod tests { nonce: 0, dispatch_weight: Weight::from_ref_time(0), size: 0, - delivery_and_dispatch_fee: 0, - dispatch_fee_payment: - bp_runtime::messages::DispatchFeePayment::AtTargetChain, }, ), InboundMessageDetails { dispatch_weight: REGULAR_PAYLOAD.declared_weight }, diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index fd4c45a0eaa9c..afda37ba8be7b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -26,10 +26,11 @@ use bp_messages::{ OnMessageAccepted, TargetHeaderChain, }, target_chain::{ - DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, + DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, + SourceHeaderChain, }, - DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, - OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayer, + DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, + OutboundLaneData, UnrewardedRelayer, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -42,7 +43,7 @@ use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, traits::{BlakeTwo256, IdentityLookup}, - FixedU128, Perbill, + Perbill, }; use std::{ collections::{BTreeMap, VecDeque}, @@ -55,6 +56,8 @@ pub type Balance = u64; pub struct TestPayload { /// Field that may be used to identify messages. pub id: u64, + /// Reject this message by lane verifier? + pub reject_by_lane_verifier: bool, /// Dispatch weight that is declared by the message sender. pub declared_weight: Weight, /// Message dispatch result. @@ -140,38 +143,20 @@ parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; - pub storage TokenConversionRate: FixedU128 = 1.into(); pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; } -#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, TypeInfo)] -pub enum TestMessagesParameter { - TokenConversionRate(FixedU128), -} - -impl MessagesParameter for TestMessagesParameter { - fn save(&self) { - match *self { - TestMessagesParameter::TokenConversionRate(conversion_rate) => - TokenConversionRate::set(&conversion_rate), - } - } -} - impl Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); - type Parameter = TestMessagesParameter; type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaximalOutboundPayloadSize = frame_support::traits::ConstU32; type OutboundPayload = TestPayload; - type OutboundMessageFee = TestMessageFee; type InboundPayload = TestPayload; - type InboundMessageFee = TestMessageFee; type InboundRelayer = TestRelayer; type TargetHeaderChain = TestTargetHeaderChain; @@ -219,7 +204,7 @@ pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 50); pub const PAYLOAD_REJECTED_BY_TARGET_CHAIN: TestPayload = message_payload(1, 50); /// Vec of proved messages, grouped by lane. -pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages>)>; +pub type MessagesByLaneVec = Vec<(LaneId, ProvedLaneMessages)>; /// Test messages proof. #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] @@ -233,14 +218,12 @@ impl Size for TestMessagesProof { } } -impl From>, ()>> for TestMessagesProof { - fn from(result: Result>, ()>) -> Self { +impl From, ()>> for TestMessagesProof { + fn from(result: Result, ()>) -> Self { Self { result: result.map(|messages| { - let mut messages_by_lane: BTreeMap< - LaneId, - ProvedLaneMessages>, - > = BTreeMap::new(); + let mut messages_by_lane: BTreeMap> = + BTreeMap::new(); for message in messages { messages_by_lane.entry(message.key.lane_id).or_default().messages.push(message); } @@ -288,17 +271,16 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier for TestLaneMessageVerifier { +impl LaneMessageVerifier for TestLaneMessageVerifier { type Error = &'static str; fn verify_message( _submitter: &RuntimeOrigin, - delivery_and_dispatch_fee: &TestMessageFee, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, - _payload: &TestPayload, + payload: &TestPayload, ) -> Result<(), Self::Error> { - if *delivery_and_dispatch_fee != 0 { + if !payload.reject_by_lane_verifier { Ok(()) } else { Err(TEST_ERROR) @@ -311,18 +293,6 @@ impl LaneMessageVerifier for TestLan pub struct TestMessageDeliveryAndDispatchPayment; impl TestMessageDeliveryAndDispatchPayment { - /// Reject all payments. - pub fn reject_payments() { - frame_support::storage::unhashed::put(b":reject-message-fee:", &true); - } - - /// Returns true if given fee has been paid by given submitter. - pub fn is_fee_paid(submitter: AccountId, fee: TestMessageFee) -> bool { - let raw_origin: Result, _> = - RuntimeOrigin::signed(submitter).into(); - frame_support::storage::unhashed::get(b":message-fee:") == Some((raw_origin.unwrap(), fee)) - } - /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is /// cleared after the call. pub fn is_reward_paid(relayer: AccountId, fee: TestMessageFee) -> bool { @@ -331,34 +301,21 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment +impl MessageDeliveryAndDispatchPayment for TestMessageDeliveryAndDispatchPayment { type Error = &'static str; - fn pay_delivery_and_dispatch_fee( - submitter: &RuntimeOrigin, - fee: &TestMessageFee, - ) -> Result<(), Self::Error> { - if frame_support::storage::unhashed::get(b":reject-message-fee:") == Some(true) { - return Err(TEST_ERROR) - } - - let raw_origin: Result, _> = submitter.clone().into(); - frame_support::storage::unhashed::put(b":message-fee:", &(raw_origin.unwrap(), fee)); - Ok(()) - } - fn pay_relayers_rewards( - lane_id: LaneId, + _lane_id: LaneId, message_relayers: VecDeque>, _confirmation_relayer: &AccountId, received_range: &RangeInclusive, ) { let relayers_rewards = - calc_relayers_rewards::(lane_id, message_relayers, received_range); + calc_relayers_rewards::(message_relayers, received_range); for (relayer, reward) in &relayers_rewards { - let key = (b":relayer-reward:", relayer, reward.reward).encode(); + let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } } @@ -450,7 +407,7 @@ impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 { #[derive(Debug)] pub struct TestSourceHeaderChain; -impl SourceHeaderChain for TestSourceHeaderChain { +impl SourceHeaderChain for TestSourceHeaderChain { type Error = &'static str; type MessagesProof = TestMessagesProof; @@ -458,7 +415,7 @@ impl SourceHeaderChain for TestSourceHeaderChain { fn verify_messages_proof( proof: Self::MessagesProof, _messages_count: u32, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { proof.result.map(|proof| proof.into_iter().collect()).map_err(|_| TEST_ERROR) } } @@ -467,10 +424,10 @@ impl SourceHeaderChain for TestSourceHeaderChain { #[derive(Debug)] pub struct TestMessageDispatch; -impl MessageDispatch for TestMessageDispatch { +impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; - fn dispatch_weight(message: &mut DispatchMessage) -> Weight { + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { Ok(payload) => payload.declared_weight, Err(_) => Weight::from_ref_time(0), @@ -479,7 +436,7 @@ impl MessageDispatch for TestMessageDispatch { fn dispatch( _relayer_account: &AccountId, - message: DispatchMessage, + message: DispatchMessage, ) -> MessageDispatchResult { match message.data.payload.as_ref() { Ok(payload) => payload.dispatch_result.clone(), @@ -489,25 +446,31 @@ impl MessageDispatch for TestMessageDispatch { } /// Return test lane message with given nonce and payload. -pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message { - Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, data: message_data(payload) } +pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message { + Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, payload: payload.encode() } +} + +/// Return valid outbound message data, constructed from given payload. +pub fn outbound_message_data(payload: TestPayload) -> MessagePayload { + payload.encode() +} + +/// Return valid inbound (dispatch) message data, constructed from given payload. +pub fn inbound_message_data(payload: TestPayload) -> DispatchMessageData { + DispatchMessageData { payload: Ok(payload) } } /// Constructs message payload using given arguments and zero unspent weight. pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { TestPayload { id, + reject_by_lane_verifier: false, declared_weight: Weight::from_ref_time(declared_weight), dispatch_result: dispatch_result(0), extra: Vec::new(), } } -/// Return message data with valid fee for given payload. -pub fn message_data(payload: TestPayload) -> MessageData { - MessageData { payload: payload.encode(), fee: 1 } -} - /// Returns message dispatch result with given unspent weight. pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult { MessageDispatchResult { diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index bdd503c811e73..890b85072ab9d 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -20,19 +20,14 @@ use crate::Config; use bitvec::prelude::*; use bp_messages::{ - DeliveredMessages, DispatchResultsBitVec, LaneId, MessageData, MessageNonce, OutboundLaneData, - UnrewardedRelayer, + DeliveredMessages, DispatchResultsBitVec, LaneId, MessageNonce, MessagePayload, + OutboundLaneData, UnrewardedRelayer, }; -use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; -use frame_support::{traits::Get, RuntimeDebug}; -use scale_info::{Type, TypeInfo}; +use frame_support::{BoundedVec, RuntimeDebug}; use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. pub trait OutboundLaneStorage { - /// Delivery and dispatch fee type on source chain. - type MessageFee; - /// Lane id. fn id(&self) -> LaneId; /// Get lane data from the storage. @@ -41,64 +36,15 @@ pub trait OutboundLaneStorage { fn set_data(&mut self, data: OutboundLaneData); /// Returns saved outbound message payload. #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option>; + fn message(&self, nonce: &MessageNonce) -> Option; /// Save outbound message in the storage. - fn save_message(&mut self, nonce: MessageNonce, message_data: MessageData); + fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload); /// Remove outbound message from the storage. fn remove_message(&mut self, nonce: &MessageNonce); } /// Outbound message data wrapper that implements `MaxEncodedLen`. -/// -/// We have already had `MaxEncodedLen`-like functionality before, but its usage has -/// been localized and we haven't been passing it everywhere. This wrapper allows us -/// to avoid passing these generic bounds all over the code. -/// -/// The encoding of this type matches encoding of the corresponding `MessageData`. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq)] -pub struct StoredMessageData, I: 'static>(pub MessageData); - -impl, I: 'static> sp_std::ops::Deref for StoredMessageData { - type Target = MessageData; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl, I: 'static> sp_std::ops::DerefMut for StoredMessageData { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl, I: 'static> From> - for MessageData -{ - fn from(data: StoredMessageData) -> Self { - data.0 - } -} - -impl, I: 'static> TypeInfo for StoredMessageData { - type Identity = Self; - - fn type_info() -> Type { - MessageData::::type_info() - } -} - -impl, I: 'static> EncodeLike> - for MessageData -{ -} - -impl, I: 'static> MaxEncodedLen for StoredMessageData { - fn max_encoded_len() -> usize { - T::OutboundMessageFee::max_encoded_len() - .saturating_add(T::MaximalOutboundPayloadSize::get() as usize) - } -} +pub type StoredMessagePayload = BoundedVec>::MaximalOutboundPayloadSize>; /// Result of messages receival confirmation. #[derive(RuntimeDebug, PartialEq, Eq)] @@ -143,12 +89,12 @@ impl OutboundLane { /// Send message over lane. /// /// Returns new message nonce. - pub fn send_message(&mut self, message_data: MessageData) -> MessageNonce { + pub fn send_message(&mut self, message_payload: MessagePayload) -> MessageNonce { let mut data = self.storage.data(); let nonce = data.latest_generated_nonce + 1; data.latest_generated_nonce = nonce; - self.storage.save_message(nonce, message_data); + self.storage.save_message(nonce, message_payload); self.storage.set_data(data); nonce @@ -295,8 +241,8 @@ mod tests { use super::*; use crate::{ mock::{ - message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, REGULAR_PAYLOAD, - TEST_LANE_ID, + outbound_message_data, run_test, unrewarded_relayer, TestRelayer, TestRuntime, + REGULAR_PAYLOAD, TEST_LANE_ID, }, outbound_lane, }; @@ -324,9 +270,9 @@ mod tests { ) -> ReceivalConfirmationResult { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); let result = lane.confirm_delivery(3, latest_received_nonce, relayers); @@ -341,7 +287,7 @@ mod tests { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); assert_eq!(lane.storage.data().latest_generated_nonce, 0); - assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 1); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1); assert!(lane.storage.message(&1).is_some()); assert_eq!(lane.storage.data().latest_generated_nonce, 1); }); @@ -351,9 +297,9 @@ mod tests { fn confirm_delivery_works() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 1); - assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 2); - assert_eq!(lane.send_message(message_data(REGULAR_PAYLOAD)), 3); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 2); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 3); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( @@ -369,9 +315,9 @@ mod tests { fn confirm_delivery_rejects_nonce_lesser_than_latest_received() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( @@ -470,9 +416,9 @@ mod tests { assert_eq!(lane.prune_messages(100), 0); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // when nothing is confirmed, nothing is pruned - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!(lane.prune_messages(100), 0); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // after confirmation, some messages are received @@ -496,9 +442,9 @@ mod tests { fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); - lane.send_message(message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!( lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3), diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 3801b57b61a4c..2ae60c17fafb9 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-17, STEPS: 50, REPEAT: 20 +//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -50,11 +50,6 @@ use sp_std::marker::PhantomData; /// Weight functions needed for `pallet_bridge_messages`. pub trait WeightInfo { - fn send_minimal_message_worst_case() -> Weight; - fn send_1_kb_message_worst_case() -> Weight; - fn send_16_kb_message_worst_case() -> Weight; - fn maximal_increase_message_fee() -> Weight; - fn increase_message_fee(i: u32) -> Weight; fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; fn receive_single_message_proof_with_outbound_lane_state() -> Weight; @@ -71,150 +66,98 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { - fn send_minimal_message_worst_case() -> Weight { - Weight::from_ref_time(61_807_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(10 as u64)) - } - fn send_1_kb_message_worst_case() -> Weight { - Weight::from_ref_time(65_074_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(10 as u64)) - } - fn send_16_kb_message_worst_case() -> Weight { - Weight::from_ref_time(73_584_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(10 as u64)) - } - fn maximal_increase_message_fee() -> Weight { - Weight::from_ref_time(2_522_629_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - fn increase_message_fee(i: u32) -> Weight { - Weight::from_ref_time(27_072_000 as u64) - .saturating_add(Weight::from_ref_time(892 as u64).saturating_mul(i as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(49_628_000 as u64) + Weight::from_ref_time(50_596_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(61_514_000 as u64) + Weight::from_ref_time(77_041_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(65_960_000 as u64) + Weight::from_ref_time(58_331_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(48_009_000 as u64) + Weight::from_ref_time(48_061_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(100_439_000 as u64) + Weight::from_ref_time(101_601_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_prepaid_message_proof() -> Weight { - Weight::from_ref_time(50_463_000 as u64) + Weight::from_ref_time(49_646_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(57_383_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) + Weight::from_ref_time(55_108_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(62_003_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) + Weight::from_ref_time(53_917_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(64_401_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) + Weight::from_ref_time(57_335_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) .saturating_add(T::DbWeight::get().writes(3 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { - fn send_minimal_message_worst_case() -> Weight { - Weight::from_ref_time(61_807_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(10 as u64)) - } - fn send_1_kb_message_worst_case() -> Weight { - Weight::from_ref_time(65_074_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(10 as u64)) - } - fn send_16_kb_message_worst_case() -> Weight { - Weight::from_ref_time(73_584_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(10 as u64)) - } - fn maximal_increase_message_fee() -> Weight { - Weight::from_ref_time(2_522_629_000 as u64) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - fn increase_message_fee(i: u32) -> Weight { - Weight::from_ref_time(27_072_000 as u64) - .saturating_add(Weight::from_ref_time(892 as u64).saturating_mul(i as u64)) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(49_628_000 as u64) + Weight::from_ref_time(50_596_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(61_514_000 as u64) + Weight::from_ref_time(77_041_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(65_960_000 as u64) + Weight::from_ref_time(58_331_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(48_009_000 as u64) + Weight::from_ref_time(48_061_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(100_439_000 as u64) + Weight::from_ref_time(101_601_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_prepaid_message_proof() -> Weight { - Weight::from_ref_time(50_463_000 as u64) + Weight::from_ref_time(49_646_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(57_383_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) + Weight::from_ref_time(55_108_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(62_003_000 as u64) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) + Weight::from_ref_time(53_917_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(64_401_000 as u64) - .saturating_add(RocksDbWeight::get().reads(7 as u64)) + Weight::from_ref_time(57_335_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) .saturating_add(RocksDbWeight::get().writes(3 as u64)) } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 80a1b9cdf8ad5..5ad86c817dcee 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -35,82 +35,16 @@ const SIGNED_EXTENSIONS_SIZE: u32 = 1024; pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Ensure that weights from `WeightInfoExt` implementation are looking correct. -pub fn ensure_weights_are_correct( - expected_default_message_delivery_tx_weight: Weight, - expected_additional_byte_delivery_weight: Weight, - expected_messages_delivery_confirmation_tx_weight: Weight, - expected_pay_inbound_dispatch_fee_weight: Weight, - db_weight: RuntimeDbWeight, -) { - // verify `send_message` weight components - assert_ne!(W::send_message_overhead(), Weight::zero()); - assert_ne!(W::send_message_size_overhead(0), Weight::zero()); - +pub fn ensure_weights_are_correct() { // verify `receive_messages_proof` weight components assert_ne!(W::receive_messages_proof_overhead(), Weight::zero()); assert_ne!(W::receive_messages_proof_messages_overhead(1), Weight::zero()); assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), Weight::zero()); assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); - // verify that the hardcoded value covers `receive_messages_proof` weight - let actual_single_regular_message_delivery_tx_weight = W::receive_messages_proof_weight( - &PreComputedSize( - (EXPECTED_DEFAULT_MESSAGE_LENGTH + W::expected_extra_storage_proof_size()) as usize, - ), - 1, - Weight::zero(), - ); - assert!( - actual_single_regular_message_delivery_tx_weight - .all_lte(expected_default_message_delivery_tx_weight), - "Default message delivery transaction weight {} is larger than expected weight {}", - actual_single_regular_message_delivery_tx_weight, - expected_default_message_delivery_tx_weight, - ); - - // verify that hardcoded value covers additional byte length of `receive_messages_proof` weight - let actual_additional_byte_delivery_weight = W::storage_proof_size_overhead(1); - assert!( - actual_additional_byte_delivery_weight.all_lte(expected_additional_byte_delivery_weight), - "Single additional byte delivery weight {} is larger than expected weight {}", - actual_additional_byte_delivery_weight, - expected_additional_byte_delivery_weight, - ); - // verify `receive_messages_delivery_proof` weight components assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::zero()); assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); - - // `receive_messages_delivery_proof_messages_overhead` and - // `receive_messages_delivery_proof_relayers_overhead` may return zero if rewards are not paid - // during confirmations delivery, so we're not checking it here - - // verify that the hardcoded value covers `receive_messages_delivery_proof` weight - let actual_messages_delivery_confirmation_tx_weight = W::receive_messages_delivery_proof_weight( - &PreComputedSize(W::expected_extra_storage_proof_size() as usize), - &UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - total_messages: 1, - ..Default::default() - }, - db_weight, - ); - assert!( - actual_messages_delivery_confirmation_tx_weight - .all_lte(expected_messages_delivery_confirmation_tx_weight), - "Messages delivery confirmation transaction weight {} is larger than expected weight {}", - actual_messages_delivery_confirmation_tx_weight, - expected_messages_delivery_confirmation_tx_weight, - ); - - // verify pay-dispatch-fee overhead for inbound messages - let actual_pay_inbound_dispatch_fee_weight = W::pay_inbound_dispatch_fee_overhead(); - assert!( - actual_pay_inbound_dispatch_fee_weight.all_lte(expected_pay_inbound_dispatch_fee_weight), - "Weight {} of pay-dispatch-fee overhead for inbound messages is larger than expected weight {}", - actual_pay_inbound_dispatch_fee_weight, - expected_pay_inbound_dispatch_fee_weight, - ); } /// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain. @@ -198,17 +132,6 @@ pub trait WeightInfoExt: WeightInfo { // Functions that are directly mapped to extrinsics weights. - /// Weight of message send extrinsic. - fn send_message_weight(message: &impl Size, db_weight: RuntimeDbWeight) -> Weight { - let transaction_overhead = Self::send_message_overhead(); - let message_size_overhead = Self::send_message_size_overhead(message.size()); - let call_back_overhead = Self::single_message_callback_overhead(db_weight); - - transaction_overhead - .saturating_add(message_size_overhead) - .saturating_add(call_back_overhead) - } - /// Weight of message delivery extrinsic. fn receive_messages_proof_weight( proof: &impl Size, @@ -274,20 +197,6 @@ pub trait WeightInfoExt: WeightInfo { // Functions that are used by extrinsics weights formulas. - /// Returns weight of message send transaction (`send_message`). - fn send_message_overhead() -> Weight { - Self::send_minimal_message_worst_case() - } - - /// Returns weight that needs to be accounted when message of given size is sent - /// (`send_message`). - fn send_message_size_overhead(message_size: u32) -> Weight { - let message_size_in_kb = (1024u64 + message_size as u64) / 1024; - let single_kb_weight = - (Self::send_16_kb_message_worst_case() - Self::send_1_kb_message_worst_case()) / 15; - message_size_in_kb * single_kb_weight - } - /// Returns weight overhead of message delivery transaction (`receive_messages_proof`). fn receive_messages_proof_overhead() -> Weight { let weight_of_two_messages_and_two_tx_overheads = diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 43cd68b01d1dc..5c9206d0ca0a8 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_parachains` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 +//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -61,19 +61,19 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { - Weight::from_ref_time(0 as u64) - .saturating_add(Weight::from_ref_time(24_869_000 as u64).saturating_mul(p as u64)) + Weight::from_ref_time(51_173_000 as u64) + .saturating_add(Weight::from_ref_time(24_495_968 as u64).saturating_mul(p as u64)) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(p as u64))) .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(p as u64))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - Weight::from_ref_time(56_262_000 as u64) + Weight::from_ref_time(58_175_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - Weight::from_ref_time(105_189_000 as u64) + Weight::from_ref_time(101_796_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(3 as u64)) } @@ -82,19 +82,19 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { - Weight::from_ref_time(0 as u64) - .saturating_add(Weight::from_ref_time(24_869_000 as u64).saturating_mul(p as u64)) + Weight::from_ref_time(51_173_000 as u64) + .saturating_add(Weight::from_ref_time(24_495_968 as u64).saturating_mul(p as u64)) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(p as u64))) .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(p as u64))) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - Weight::from_ref_time(56_262_000 as u64) + Weight::from_ref_time(58_175_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - Weight::from_ref_time(105_189_000 as u64) + Weight::from_ref_time(101_796_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(3 as u64)) } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index d090da3e6da56..f2ae936ae8c9b 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -97,17 +97,14 @@ parameter_types! { impl pallet_bridge_messages::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); - type Parameter = (); type MaxMessagesToPruneAtOnce = frame_support::traits::ConstU64<0>; type MaxUnrewardedRelayerEntriesAtInboundLane = frame_support::traits::ConstU64<8>; type MaxUnconfirmedMessagesAtInboundLane = frame_support::traits::ConstU64<8>; type MaximalOutboundPayloadSize = frame_support::traits::ConstU32<1024>; type OutboundPayload = (); - type OutboundMessageFee = Balance; type InboundPayload = (); - type InboundMessageFee = Balance; type InboundRelayer = AccountId; type TargetHeaderChain = ForbidOutboundMessages; diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index d472810c5ccff..772d07d2ad971 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -20,43 +20,31 @@ use crate::{Config, RelayerRewards}; use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; -use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; -use sp_arithmetic::traits::{Saturating, Zero}; +use frame_support::sp_runtime::SaturatedConversion; +use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism /// for the messages pallet. -pub struct MessageDeliveryAndDispatchPaymentAdapter( - PhantomData<(T, MessagesInstance, GetConfirmationFee)>, +pub struct MessageDeliveryAndDispatchPaymentAdapter( + PhantomData<(T, MessagesInstance)>, ); -impl - MessageDeliveryAndDispatchPayment - for MessageDeliveryAndDispatchPaymentAdapter +impl MessageDeliveryAndDispatchPayment + for MessageDeliveryAndDispatchPaymentAdapter where - T: Config + pallet_bridge_messages::Config, + T: Config + pallet_bridge_messages::Config, MessagesInstance: 'static, - GetConfirmationFee: Get, { type Error = &'static str; - fn pay_delivery_and_dispatch_fee( - _submitter: &T::RuntimeOrigin, - _fee: &T::Reward, - ) -> Result<(), Self::Error> { - // nothing shall happen here, because XCM deals with fee payment (planned to be burnt? - // or transferred to the treasury?) - Ok(()) - } - fn pay_relayers_rewards( - lane_id: bp_messages::LaneId, + _lane_id: bp_messages::LaneId, messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, received_range: &RangeInclusive, ) { let relayers_rewards = pallet_bridge_messages::calc_relayers_rewards::( - lane_id, messages_relayers, received_range, ); @@ -64,7 +52,10 @@ where register_relayers_rewards::( confirmation_relayer, relayers_rewards, - GetConfirmationFee::get(), + // TODO (https://github.com/paritytech/parity-bridges-common/issues/1318): this shall be fixed + // in some way. ATM the future of the `register_relayers_rewards` is not yet known + 100_000_u32.into(), + 10_000_u32.into(), ); } } @@ -72,13 +63,17 @@ where // Update rewards to given relayers, optionally rewarding confirmation relayer. fn register_relayers_rewards( confirmation_relayer: &T::AccountId, - relayers_rewards: RelayersRewards, + relayers_rewards: RelayersRewards, + delivery_fee: T::Reward, confirmation_fee: T::Reward, ) { // reward every relayer except `confirmation_relayer` let mut confirmation_relayer_reward = T::Reward::zero(); - for (relayer, reward) in relayers_rewards { - let mut relayer_reward = reward.reward; + for (relayer, messages) in relayers_rewards { + // sane runtime configurations guarantee that the number of messages will be below + // `u32::MAX` + let mut relayer_reward = + T::Reward::unique_saturated_from(messages).saturating_mul(delivery_fee); if relayer != *confirmation_relayer { // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee @@ -87,12 +82,11 @@ fn register_relayers_rewards( // If confirmation fee has been increased (or if it was the only component of message // fee), then messages relayer may receive zero reward. let mut confirmation_reward = - T::Reward::saturated_from(reward.messages).saturating_mul(confirmation_fee); + T::Reward::saturated_from(messages).saturating_mul(confirmation_fee); confirmation_reward = sp_std::cmp::min(confirmation_reward, relayer_reward); relayer_reward = relayer_reward.saturating_sub(confirmation_reward); confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(confirmation_reward); - register_relayer_reward::(&relayer, relayer_reward); } else { // If delivery confirmation is submitted by this relayer, let's add confirmation fee @@ -134,32 +128,27 @@ mod tests { const RELAYER_2: AccountId = 2; const RELAYER_3: AccountId = 3; - fn relayers_rewards() -> RelayersRewards { - vec![ - (RELAYER_1, bp_messages::source_chain::RelayerRewards { reward: 100, messages: 2 }), - (RELAYER_2, bp_messages::source_chain::RelayerRewards { reward: 100, messages: 3 }), - ] - .into_iter() - .collect() + fn relayers_rewards() -> RelayersRewards { + vec![(RELAYER_1, 2), (RELAYER_2, 3)].into_iter().collect() } #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { - register_relayers_rewards::(&RELAYER_2, relayers_rewards(), 10); + register_relayers_rewards::(&RELAYER_2, relayers_rewards(), 50, 10); assert_eq!(RelayerRewards::::get(RELAYER_1), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2), Some(120)); + assert_eq!(RelayerRewards::::get(RELAYER_2), Some(170)); }); } #[test] fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { run_test(|| { - register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 10); + register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 50, 10); assert_eq!(RelayerRewards::::get(RELAYER_1), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2), Some(70)); + assert_eq!(RelayerRewards::::get(RELAYER_2), Some(120)); assert_eq!(RelayerRewards::::get(RELAYER_3), Some(50)); }); } @@ -167,11 +156,11 @@ mod tests { #[test] fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { run_test(|| { - register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 1000); + register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 50, 1000); assert_eq!(RelayerRewards::::get(RELAYER_1), None); assert_eq!(RelayerRewards::::get(RELAYER_2), None); - assert_eq!(RelayerRewards::::get(RELAYER_3), Some(200)); + assert_eq!(RelayerRewards::::get(RELAYER_3), Some(250)); }); } } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index b8df8c94499cc..7bcd8711a9eac 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_relayers` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-04, STEPS: 50, REPEAT: 20 +//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -59,7 +59,7 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn claim_rewards() -> Weight { - Weight::from_ref_time(55_856_000 as u64) + Weight::from_ref_time(59_334_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } @@ -68,7 +68,7 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { fn claim_rewards() -> Weight { - Weight::from_ref_time(55_856_000 as u64) + Weight::from_ref_time(59_334_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 0d1a81be10292..aa65f378542a6 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -27,12 +27,12 @@ use bp_runtime::{ use frame_support::{ dispatch::DispatchClass, parameter_types, - sp_runtime::{FixedU128, MultiAddress, MultiSigner}, + sp_runtime::{MultiAddress, MultiSigner}, weights::{ constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, - Parameter, RuntimeDebug, + RuntimeDebug, }; use sp_std::prelude::*; diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 33c4dcca127e3..5cee3f14dd6dd 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -27,16 +27,14 @@ pub use bp_bridge_hub_rococo::{ account_info_storage_key, AccountId, AccountPublic, AccountSigner, Address, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher, Hashing, Header, Index, Nonce, SS58Prefix, Signature, SignedBlock, SignedExtensions, UncheckedExtrinsic, WeightToFee, - ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT, DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT, - EXTRA_STORAGE_PROOF_SIZE, MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT, MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - PAY_INBOUND_DISPATCH_FEE_WEIGHT, TX_EXTRA_BYTES, + TX_EXTRA_BYTES, }; use bp_messages::*; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; -use frame_support::{dispatch::DispatchClass, sp_runtime::FixedU128, Parameter, RuntimeDebug}; +use frame_support::{dispatch::DispatchClass, RuntimeDebug}; use sp_std::prelude::*; /// BridgeHubWococo parachain. diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 9c0b4782e37eb..07cdb0c27f6ed 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -27,14 +27,14 @@ use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, - Parameter, RuntimeDebug, + RuntimeDebug, }; use frame_system::limits; use scale_info::TypeInfo; use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ traits::{IdentifyAccount, Verify}, - FixedU128, MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; @@ -69,38 +69,6 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; /// Maximal number of unconfirmed messages in Millau confirmation transaction. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; -/// Weight of single regular message delivery transaction on Millau chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` -/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be -/// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); - -/// Increase of delivery transaction weight on Millau chain with every additional message byte. -/// -/// This value is a result of -/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then -/// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); - -/// Maximal weight of single message delivery confirmation transaction on Millau chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` -/// weight formula computation for the case when single message is confirmed. The result then must -/// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = - Weight::from_ref_time(2_000_000_000); - -/// Weight of pay-dispatch-fee operation for inbound messages at Millau chain. -/// -/// This value corresponds to the result of -/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your -/// chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery -/// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(700_000_000); - /// The target length of a session (how often authorities change) on Millau measured in of number of /// blocks. /// @@ -237,13 +205,4 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the transaction payment pallet at the Millau runtime. pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; -/// Name of the Rialto->Millau (actually DOT->KSM) conversion rate stored in the Millau runtime. -pub const RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = "RialtoToMillauConversionRate"; -/// Name of the RialtoParachain->Millau (actually DOT->KSM) conversion rate stored in the Millau -/// runtime. -pub const RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME: &str = - "RialtoParachainToMillauConversionRate"; -/// Name of the RialtoParachain fee multiplier parameter, stored in the Millau runtime. -pub const RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME: &str = "RialtoParachainFeeMultiplier"; - decl_bridge_runtime_apis!(millau); diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 584882425b4db..82b6a12c182a3 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -25,13 +25,13 @@ use bp_runtime::{decl_bridge_runtime_apis, Chain, Parachain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, - Parameter, RuntimeDebug, + RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, - FixedU128, MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, }; use sp_std::vec::Vec; @@ -66,39 +66,6 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Maximal number of unconfirmed messages in Rialto confirmation transaction. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; -/// Weight of single regular message delivery transaction on RialtoParachain chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` -/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be -/// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); - -/// Increase of delivery transaction weight on RialtoParachain chain with every additional message -/// byte. -/// -/// This value is a result of -/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then -/// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); - -/// Maximal weight of single message delivery confirmation transaction on RialtoParachain chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` -/// weight formula computation for the case when single message is confirmed. The result then must -/// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = - Weight::from_ref_time(2_000_000_000); - -/// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. -/// -/// This value corresponds to the result of -/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your -/// chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery -/// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(600_000_000); - /// Block number type used in Rialto. pub type BlockNumber = u32; @@ -176,11 +143,4 @@ pub const WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME: &str = "BridgeRialtoParach /// Name of the transaction payment pallet at the Rialto parachain runtime. pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; -/// Name of the Millau->RialtoParachain (actually KSM->DOT) conversion rate stored in the Rialto -/// parachain runtime. -pub const MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME: &str = - "MillauToRialtoParachainConversionRate"; -/// Name of the Millau fee multiplier parameter, stored in the Rialto parachain runtime. -pub const MILLAU_FEE_MULTIPLIER_PARAMETER_NAME: &str = "MillauFeeMultiplier"; - decl_bridge_runtime_apis!(rialto_parachain); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 4d272fe68399f..dfb727829d9aa 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -25,13 +25,13 @@ use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, - Parameter, RuntimeDebug, + RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, - FixedU128, MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, }; use sp_std::prelude::*; @@ -60,38 +60,6 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Maximal number of unconfirmed messages in Rialto confirmation transaction. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; -/// Weight of single regular message delivery transaction on Rialto chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` -/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be -/// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); - -/// Increase of delivery transaction weight on Rialto chain with every additional message byte. -/// -/// This value is a result of -/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then -/// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); - -/// Maximal weight of single message delivery confirmation transaction on Rialto chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` -/// weight formula computation for the case when single message is confirmed. The result then must -/// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = - Weight::from_ref_time(2_000_000_000); - -/// Weight of pay-dispatch-fee operation for inbound messages at Rialto chain. -/// -/// This value corresponds to the result of -/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your -/// chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery -/// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(700_000_000); - /// The target length of a session (how often authorities change) on Rialto measured in of number of /// blocks. /// @@ -203,9 +171,6 @@ pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; /// Name of the With-Rialto parachains bridge pallet instance that is deployed at bridged chains. pub const WITH_RIALTO_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeRialtoParachains"; -/// Name of the Millau->Rialto (actually KSM->DOT) conversion rate stored in the Rialto runtime. -pub const MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME: &str = "MillauToRialtoConversionRate"; - /// Name of the parachain registrar pallet in the Rialto runtime. pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; diff --git a/primitives/chain-statemine/Cargo.toml b/primitives/chain-statemine/Cargo.toml deleted file mode 100644 index 18d186ba41ef5..0000000000000 --- a/primitives/chain-statemine/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "bp-statemine" -description = "Primitives of Statemine runtime." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# Bridge Dependencies - -bp-polkadot-core = { path = "../polkadot-core", default-features = false } - -# Substrate Based Dependencies - -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } - -[features] -default = ["std"] -std = [ - "bp-polkadot-core/std", - "sp-version/std", -] diff --git a/primitives/chain-statemine/src/lib.rs b/primitives/chain-statemine/src/lib.rs deleted file mode 100644 index 613e4a4f4501a..0000000000000 --- a/primitives/chain-statemine/src/lib.rs +++ /dev/null @@ -1,38 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] - -pub use bp_polkadot_core::*; - -use sp_version::RuntimeVersion; - -/// Statemine Chain. -pub type Statemine = PolkadotLike; - -/// Known Statemine runtime version. -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: sp_version::create_runtime_str!("statemine"), - impl_name: sp_version::create_runtime_str!("statemine"), - authoring_version: 1, - spec_version: 9300, - impl_version: 0, - apis: sp_version::create_apis_vec![[]], - transaction_version: 8, - state_version: 1, -}; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 8742ff8448d72..f535a40a9db9b 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -21,7 +21,7 @@ #![allow(clippy::too_many_arguments)] use bitvec::prelude::*; -use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode, OperatingMode}; +use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; @@ -65,16 +65,6 @@ impl OperatingMode for MessagesOperatingMode { } } -/// Messages pallet parameter. -pub trait Parameter: frame_support::Parameter { - /// Save parameter value in the runtime storage. - fn save(&self); -} - -impl Parameter for () { - fn save(&self) {} -} - /// Lane identifier. pub type LaneId = [u8; 4]; @@ -96,22 +86,13 @@ pub struct MessageKey { pub nonce: MessageNonce, } -/// Message data as it is stored in the storage. -#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] -pub struct MessageData { - /// Message payload. - pub payload: MessagePayload, - /// Message delivery and dispatch fee, paid by the submitter. - pub fee: Fee, -} - /// Message as it is stored in the storage. #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] -pub struct Message { +pub struct Message { /// Message key. pub key: MessageKey, - /// Message data. - pub data: MessageData, + /// Message payload. + pub payload: MessagePayload, } /// Inbound lane data. @@ -198,7 +179,7 @@ impl InboundLaneData { /// Outbound message details, returned by runtime APIs. #[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] -pub struct OutboundMessageDetails { +pub struct OutboundMessageDetails { /// Nonce assigned to the message. pub nonce: MessageNonce, /// Message dispatch weight. @@ -208,10 +189,6 @@ pub struct OutboundMessageDetails { pub dispatch_weight: Weight, /// Size of the encoded message. pub size: u32, - /// Delivery+dispatch fee paid by the message submitter at the source chain. - pub delivery_and_dispatch_fee: OutboundMessageFee, - /// Where the fee for dispatching message is paid? - pub dispatch_fee_payment: DispatchFeePayment, } /// Inbound message details, returned by runtime APIs. diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 8050f994dd3f1..6a22ececf8efc 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -27,17 +27,8 @@ use sp_std::{ ops::RangeInclusive, }; -/// Relayers rewards, grouped by relayer account id. -pub type RelayersRewards = BTreeMap>; - -/// Single relayer rewards. -#[derive(RuntimeDebug, Default)] -pub struct RelayerRewards { - /// Total rewards that are to be paid to the relayer. - pub reward: Balance, - /// Total number of messages relayed by this relayer. - pub messages: MessageNonce, -} +/// Number of messages, delivered by relayers. +pub type RelayersRewards = BTreeMap; /// Target chain API. Used by source chain to verify target chain proofs. /// @@ -83,7 +74,7 @@ pub trait TargetHeaderChain { /// Lane3 until some block, ...), then it may be built using this verifier. /// /// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { +pub trait LaneMessageVerifier { /// Error type. type Error: Debug + Into<&'static str>; @@ -91,7 +82,6 @@ pub trait LaneMessageVerifier { /// lane. fn verify_message( submitter: &SenderOrigin, - delivery_and_dispatch_fee: &Fee, lane: &LaneId, outbound_data: &OutboundLaneData, payload: &Payload, @@ -107,21 +97,10 @@ pub trait LaneMessageVerifier { /// 3) message-dispatch fee. It is paid by relayer for processing message by target chain; /// 4) message-receiving-delivery-transaction-fee. It is submitted to the source node /// by relayer. -/// -/// So to be sure that any non-altruist relayer would agree to deliver message, submitter -/// should set `delivery_and_dispatch_fee` to at least (equivalent of): sum of fees from (2) -/// to (4) above, plus some interest for the relayer. -pub trait MessageDeliveryAndDispatchPayment { +pub trait MessageDeliveryAndDispatchPayment { /// Error type. type Error: Debug + Into<&'static str>; - /// Withhold/write-off delivery_and_dispatch_fee from submitter account to - /// some relayers-fund account. - fn pay_delivery_and_dispatch_fee( - submitter: &SenderOrigin, - fee: &Balance, - ) -> Result<(), Self::Error>; - /// Pay rewards for delivering messages to the given relayers. /// /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is @@ -134,18 +113,9 @@ pub trait MessageDeliveryAndDispatchPayment { ); } -impl - MessageDeliveryAndDispatchPayment for () -{ +impl MessageDeliveryAndDispatchPayment for () { type Error = &'static str; - fn pay_delivery_and_dispatch_fee( - _submitter: &SenderOrigin, - _fee: &Balance, - ) -> Result<(), Self::Error> { - Ok(()) - } - fn pay_relayers_rewards( _lane_id: LaneId, _messages_relayers: VecDeque>, @@ -165,7 +135,7 @@ pub struct SendMessageArtifacts { } /// Messages bridge API to be used from other pallets. -pub trait MessagesBridge { +pub trait MessagesBridge { /// Error type. type Error: Debug; @@ -176,7 +146,6 @@ pub trait MessagesBridge { sender: SenderOrigin, lane: LaneId, message: Payload, - delivery_and_dispatch_fee: Balance, ) -> Result; } @@ -184,16 +153,13 @@ pub trait MessagesBridge { #[derive(Eq, RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; -impl MessagesBridge - for NoopMessagesBridge -{ +impl MessagesBridge for NoopMessagesBridge { type Error = &'static str; fn send_message( _sender: SenderOrigin, _lane: LaneId, _message: Payload, - _delivery_and_dispatch_fee: Balance, ) -> Result { Ok(SendMessageArtifacts { nonce: 0, weight: Weight::zero() }) } @@ -266,14 +232,11 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier - for ForbidOutboundMessages -{ +impl LaneMessageVerifier for ForbidOutboundMessages { type Error = &'static str; fn verify_message( _submitter: &SenderOrigin, - _delivery_and_dispatch_fee: &Fee, _lane: &LaneId, _outbound_data: &OutboundLaneData, _payload: &Payload, @@ -282,18 +245,11 @@ impl LaneMessageVerifier } } -impl - MessageDeliveryAndDispatchPayment for ForbidOutboundMessages +impl MessageDeliveryAndDispatchPayment + for ForbidOutboundMessages { type Error = &'static str; - fn pay_delivery_and_dispatch_fee( - _submitter: &SenderOrigin, - _fee: &Balance, - ) -> Result<(), Self::Error> { - Err(ALL_OUTBOUND_MESSAGES_REJECTED) - } - fn pay_relayers_rewards( _lane_id: LaneId, _messages_relayers: VecDeque>, diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 58419c398bb33..5f682dee16666 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -16,7 +16,7 @@ //! Primitives of messages module, that are used on the target chain. -use crate::{LaneId, Message, MessageData, MessageKey, OutboundLaneData}; +use crate::{LaneId, Message, MessageKey, MessagePayload, OutboundLaneData}; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; @@ -38,20 +38,18 @@ pub struct ProvedLaneMessages { /// Message data with decoded dispatch payload. #[derive(RuntimeDebug)] -pub struct DispatchMessageData { +pub struct DispatchMessageData { /// Result of dispatch payload decoding. pub payload: Result, - /// Message delivery and dispatch fee, paid by the submitter. - pub fee: Fee, } /// Message with decoded dispatch payload. #[derive(RuntimeDebug)] -pub struct DispatchMessage { +pub struct DispatchMessage { /// Message key. pub key: MessageKey, /// Message data with decoded dispatch payload. - pub data: DispatchMessageData, + pub data: DispatchMessageData, } /// Source chain API. Used by target chain, to verify source chain proofs. @@ -59,7 +57,7 @@ pub struct DispatchMessage { /// All implementations of this trait should only work with finalized data that /// can't change. Wrong implementation may lead to invalid lane states (i.e. lane /// that's stuck) and/or processing messages without paying fees. -pub trait SourceHeaderChain { +pub trait SourceHeaderChain { /// Error type. type Error: Debug + Into<&'static str>; @@ -81,11 +79,11 @@ pub trait SourceHeaderChain { fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result>, Self::Error>; + ) -> Result, Self::Error>; } /// Called when inbound message is received. -pub trait MessageDispatch { +pub trait MessageDispatch { /// Decoded message payload type. Valid message may contain invalid payload. In this case /// message is delivered, but dispatch fails. Therefore, two separate types of payload /// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch). @@ -96,7 +94,7 @@ pub trait MessageDispatch { /// This function must return correct upper bound of dispatch weight. The return value /// of this function is expected to match return value of the corresponding /// `FromInboundLaneApi::message_details().dispatch_weight` call. - fn dispatch_weight(message: &mut DispatchMessage) -> Weight; + fn dispatch_weight(message: &mut DispatchMessage) -> Weight; /// Called when inbound message is received. /// @@ -107,7 +105,7 @@ pub trait MessageDispatch { /// it must be paid inside this method to the `relayer_account`. fn dispatch( relayer_account: &AccountId, - message: DispatchMessage, + message: DispatchMessage, ) -> MessageDispatchResult; } @@ -117,20 +115,15 @@ impl Default for ProvedLaneMessages { } } -impl From> for DispatchMessage { - fn from(message: Message) -> Self { - DispatchMessage { key: message.key, data: message.data.into() } +impl From for DispatchMessage { + fn from(message: Message) -> Self { + DispatchMessage { key: message.key, data: message.payload.into() } } } -impl From> - for DispatchMessageData -{ - fn from(data: MessageData) -> Self { - DispatchMessageData { - payload: DispatchPayload::decode(&mut &data.payload[..]), - fee: data.fee, - } +impl From for DispatchMessageData { + fn from(payload: MessagePayload) -> Self { + DispatchMessageData { payload: DispatchPayload::decode(&mut &payload[..]) } } } @@ -142,29 +135,26 @@ pub struct ForbidInboundMessages; const ALL_INBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all inbound messages"; -impl SourceHeaderChain for ForbidInboundMessages { +impl SourceHeaderChain for ForbidInboundMessages { type Error = &'static str; type MessagesProof = (); fn verify_messages_proof( _proof: Self::MessagesProof, _messages_count: u32, - ) -> Result>, Self::Error> { + ) -> Result, Self::Error> { Err(ALL_INBOUND_MESSAGES_REJECTED) } } -impl MessageDispatch for ForbidInboundMessages { +impl MessageDispatch for ForbidInboundMessages { type DispatchPayload = (); - fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX } - fn dispatch( - _: &AccountId, - _: DispatchMessage, - ) -> MessageDispatchResult { + fn dispatch(_: &AccountId, _: DispatchMessage) -> MessageDispatchResult { MessageDispatchResult { dispatch_result: false, unspent_weight: Weight::zero(), diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 34eb4ae13b19a..878c3dc38ebcf 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -126,49 +126,12 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; /// Maximal number of unconfirmed messages at inbound lane. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192; -// One important thing about weight-related constants here is that actually we may have -// different weights on different Polkadot-like chains. But now all deployments are -// almost the same, so we're exporting constants from this crate. - -/// Maximal weight of single message delivery confirmation transaction on Polkadot-like chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_delivery_proof` -/// weight formula computation for the case when single message is confirmed. The result then must -/// be rounded up to account possible future runtime upgrades. -pub const MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT: Weight = - Weight::from_ref_time(2_000_000_000); - -/// Increase of delivery transaction weight on Polkadot-like chain with every additional message -/// byte. -/// -/// This value is a result of -/// `pallet_bridge_messages::WeightInfoExt::storage_proof_size_overhead(1)` call. The result then -/// must be rounded up to account possible future runtime upgrades. -pub const ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT: Weight = Weight::from_ref_time(25_000); - /// Maximal number of bytes, included in the signed Polkadot-like transaction apart from the encoded /// call itself. /// /// Can be computed by subtracting encoded call size from raw transaction size. pub const TX_EXTRA_BYTES: u32 = 256; -/// Weight of single regular message delivery transaction on Polkadot-like chain. -/// -/// This value is a result of `pallet_bridge_messages::Pallet::receive_messages_proof_weight()` call -/// for the case when single message of `pallet_bridge_messages::EXPECTED_DEFAULT_MESSAGE_LENGTH` -/// bytes is delivered. The message must have dispatch weight set to zero. The result then must be -/// rounded up to account possible future runtime upgrades. -pub const DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT: Weight = Weight::from_ref_time(1_500_000_000); - -/// Weight of pay-dispatch-fee operation for inbound messages at Polkadot-like chain. -/// -/// This value corresponds to the result of -/// `pallet_bridge_messages::WeightInfoExt::pay_inbound_dispatch_fee_overhead()` call for your -/// chain. Don't put too much reserve there, because it is used to **decrease** -/// `DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT` cost. So putting large reserve would make delivery -/// transactions cheaper. -pub const PAY_INBOUND_DISPATCH_FEE_WEIGHT: Weight = Weight::from_ref_time(600_000_000); - /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 6f43c0f354900..d4a8d5aa020b5 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -300,21 +300,7 @@ macro_rules! decl_bridge_messages_runtime_apis { /// /// This API is implemented by runtimes that are receiving messages from this chain, not by this /// chain's runtime itself. - pub trait [] { - /// Estimate message delivery and dispatch fee that needs to be paid by the sender on - /// this chain. - /// - /// Returns `None` if message is too expensive to be sent to this chain from the bridged chain. - /// - /// Please keep in mind that this method returns the lowest message fee required for message - /// to be accepted to the lane. It may be a good idea to pay a bit over this price to account - /// for future exchange rate changes and guarantee that relayer would deliver your message - /// to the target chain. - fn estimate_message_delivery_and_dispatch_fee( - lane_id: LaneId, - payload: OutboundPayload, - [<$chain:lower _to_this_conversion_rate>]: Option, - ) -> Option; + pub trait [] { /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. /// @@ -324,7 +310,7 @@ macro_rules! decl_bridge_messages_runtime_apis { lane: LaneId, begin: MessageNonce, end: MessageNonce, - ) -> Vec>; + ) -> Vec; } /// Inbound message lane API for messages sent by this chain. @@ -334,11 +320,11 @@ macro_rules! decl_bridge_messages_runtime_apis { /// /// Entries of the resulting vector are matching entries of the `messages` vector. Entries of the /// `messages` vector may (and need to) be read using `ToOutboundLaneApi::message_details`. - pub trait [] { + pub trait [] { /// Return details of given inbound messages. fn message_details( lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, + messages: Vec<(MessagePayload, OutboundMessageDetails)>, ) -> Vec; } } @@ -346,7 +332,7 @@ macro_rules! decl_bridge_messages_runtime_apis { pub use [<$chain _messages_api>]::*; } - } + }; } /// Convenience macro that declares bridge finality runtime apis, bridge messages runtime apis diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index 7a6687c18b776..d77b1df7515c6 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -20,20 +20,6 @@ use codec::{Decode, Encode}; use frame_support::{weights::Weight, RuntimeDebug}; use scale_info::TypeInfo; -/// Where message dispatch fee is paid? -#[derive(Encode, Decode, RuntimeDebug, Clone, Copy, PartialEq, Eq, TypeInfo)] -pub enum DispatchFeePayment { - /// The dispatch fee is paid at the source chain. - AtSourceChain, - /// The dispatch fee is paid at the target chain. - /// - /// The fee will be paid right before the message is dispatched. So in case of any other - /// issues (like invalid call encoding, invalid signature, ...) the dispatch module won't - /// do any direct transfers. Instead, it'll return fee related to this message dispatch to the - /// relayer. - AtTargetChain, -} - /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] pub struct MessageDispatchResult { diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index c214471eb6bdf..9ae6a98868e39 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -30,7 +30,6 @@ bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } -bp-statemine = { path = "../../primitives/chain-statemine" } bp-westend = { path = "../../primitives/chain-westend" } bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } @@ -45,7 +44,6 @@ relay-rialto-parachain-client = { path = "../client-rialto-parachain" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } relay-rococo-client = { path = "../client-rococo" } -relay-statemine-client = { path = "../client-statemine" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index 915dd82969852..78ef00f6d6248 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -18,7 +18,6 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use bp_messages::Weight; -use messages_relay::relay_strategy::MixStrategy; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_wococo_client::BridgeHubWococo; use substrate_relay_helper::messages_lane::SubstrateMessageLane; @@ -55,15 +54,6 @@ substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_buil pub struct BridgeHubRococoMessagesToBridgeHubWococoMessageLane; impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWococoMessageLane { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - type SourceChain = BridgeHubRococo; type TargetChain = BridgeHubWococo; @@ -71,8 +61,4 @@ impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWococoMessageLan BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder; type ReceiveMessagesDeliveryProofCallBuilder = BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type TargetToSourceChainConversionRateUpdateBuilder = (); - - type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index 179b9076ba72d..51e1020e74953 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -18,7 +18,6 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use bp_messages::Weight; -use messages_relay::relay_strategy::MixStrategy; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_wococo_client::BridgeHubWococo; use substrate_relay_helper::messages_lane::SubstrateMessageLane; @@ -55,15 +54,6 @@ substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_buil pub struct BridgeHubWococoMessagesToBridgeHubRococoMessageLane; impl SubstrateMessageLane for BridgeHubWococoMessagesToBridgeHubRococoMessageLane { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = None; - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - type SourceChain = BridgeHubWococo; type TargetChain = BridgeHubRococo; @@ -71,8 +61,4 @@ impl SubstrateMessageLane for BridgeHubWococoMessagesToBridgeHubRococoMessageLan BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; type ReceiveMessagesDeliveryProofCallBuilder = BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type TargetToSourceChainConversionRateUpdateBuilder = (); - - type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 92fc43fbe36fe..705755506f78c 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -16,16 +16,10 @@ //! Millau chain specification for CLI. -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; -use bp_messages::LaneId; +use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_rialto_parachain::RIALTO_PARACHAIN_ID; use bp_runtime::EncodedOrDecodedCall; use relay_millau_client::Millau; -use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; use xcm::latest::prelude::*; @@ -56,37 +50,6 @@ impl CliEncodeMessage for Millau { }) .into()) } - - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => millau_runtime::RuntimeCall::BridgeRialtoMessages( - millau_runtime::MessagesCall::send_message { - lane_id: lane, - payload, - delivery_and_dispatch_fee: fee, - }, - ) - .into(), - bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => - millau_runtime::RuntimeCall::BridgeRialtoParachainMessages( - millau_runtime::MessagesCall::send_message { - lane_id: lane, - payload, - delivery_and_dispatch_fee: fee, - }, - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } } impl CliChain for Millau { diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 332721e217f0d..b9920db53d85d 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -16,7 +16,6 @@ //! Millau-to-Rialto messages sync entrypoint. -use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_client::Rialto; use substrate_relay_helper::messages_lane::{ @@ -27,25 +26,8 @@ use substrate_relay_helper::messages_lane::{ /// Description of Millau -> Rialto messages bridge. #[derive(Clone, Debug)] pub struct MillauMessagesToRialto; -substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( - Millau, - MillauMessagesToRialtoUpdateConversionRateCallBuilder, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, - millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate -); impl SubstrateMessageLane for MillauMessagesToRialto { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - type SourceChain = Millau; type TargetChain = Rialto; @@ -59,9 +41,4 @@ impl SubstrateMessageLane for MillauMessagesToRialto { millau_runtime::Runtime, millau_runtime::WithRialtoMessagesInstance, >; - - type TargetToSourceChainConversionRateUpdateBuilder = - MillauMessagesToRialtoUpdateConversionRateCallBuilder; - - type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index 04b2b1e46e66a..70cb887fa35d4 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -16,7 +16,6 @@ //! Millau-to-RialtoParachain messages sync entrypoint. -use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_parachain_client::RialtoParachain; use substrate_relay_helper::messages_lane::{ @@ -27,30 +26,8 @@ use substrate_relay_helper::messages_lane::{ /// Description of Millau -> RialtoParachain messages bridge. #[derive(Clone, Debug)] pub struct MillauMessagesToRialtoParachain; -substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( - Millau, - MillauMessagesToRialtoParachainUpdateConversionRateCallBuilder, - millau_runtime::Runtime, - millau_runtime::WithRialtoParachainMessagesInstance, - millau_runtime::rialto_parachain_messages::MillauToRialtoParachainMessagesParameter::RialtoParachainToMillauConversionRate -); impl SubstrateMessageLane for MillauMessagesToRialtoParachain { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto_parachain::MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME); - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto_parachain::MILLAU_FEE_MULTIPLIER_PARAMETER_NAME); - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME); - - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_millau::TRANSACTION_PAYMENT_PALLET_NAME); - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_rialto_parachain::TRANSACTION_PAYMENT_PALLET_NAME); - type SourceChain = Millau; type TargetChain = RialtoParachain; @@ -64,9 +41,4 @@ impl SubstrateMessageLane for MillauMessagesToRialtoParachain { millau_runtime::Runtime, millau_runtime::WithRialtoParachainMessagesInstance, >; - - type TargetToSourceChainConversionRateUpdateBuilder = - MillauMessagesToRialtoParachainUpdateConversionRateCallBuilder; - - type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 6bd444cc3959f..7caba7561ddc1 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -37,7 +37,6 @@ mod millau; mod rialto; mod rialto_parachain; mod rococo; -mod statemine; mod westend; mod wococo; diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 43ec9dbd224e4..83bccf626b9ed 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -16,15 +16,9 @@ //! Rialto chain specification for CLI. -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; -use bp_messages::LaneId; +use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_rialto_client::Rialto; -use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; use xcm::latest::prelude::*; @@ -48,28 +42,6 @@ impl CliEncodeMessage for Rialto { }) .into()) } - - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => rialto_runtime::RuntimeCall::BridgeMillauMessages( - rialto_runtime::MessagesCall::send_message { - lane_id: lane, - payload, - delivery_and_dispatch_fee: fee, - }, - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } } impl CliChain for Rialto { diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index e922659ab9a8b..80b6b9fdbc6b0 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -16,7 +16,6 @@ //! Rialto-to-Millau messages sync entrypoint. -use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_client::Rialto; use substrate_relay_helper::messages_lane::{ @@ -27,25 +26,8 @@ use substrate_relay_helper::messages_lane::{ /// Description of Rialto -> Millau messages bridge. #[derive(Clone, Debug)] pub struct RialtoMessagesToMillau; -substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( - Rialto, - RialtoMessagesToMillauUpdateConversionRateCallBuilder, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, - rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate -); impl SubstrateMessageLane for RialtoMessagesToMillau { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto::MILLAU_TO_RIALTO_CONVERSION_RATE_PARAMETER_NAME); - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = None; - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = None; - type SourceChain = Rialto; type TargetChain = Millau; @@ -59,9 +41,4 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { rialto_runtime::Runtime, rialto_runtime::WithMillauMessagesInstance, >; - - type TargetToSourceChainConversionRateUpdateBuilder = - RialtoMessagesToMillauUpdateConversionRateCallBuilder; - - type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 546cd04bdde15..a480dc3eebbc6 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -16,15 +16,9 @@ //! Rialto parachain specification for CLI. -use crate::cli::{ - bridge, - encode_message::{CliEncodeMessage, RawMessage}, - CliChain, -}; -use bp_messages::LaneId; +use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_rialto_parachain_client::RialtoParachain; -use relay_substrate_client::BalanceOf; use sp_version::RuntimeVersion; use xcm::latest::prelude::*; @@ -50,29 +44,6 @@ impl CliEncodeMessage for RialtoParachain { ) .into()) } - - fn encode_send_message_call( - lane: LaneId, - payload: RawMessage, - fee: BalanceOf, - bridge_instance_index: u8, - ) -> anyhow::Result> { - Ok(match bridge_instance_index { - bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => - rialto_parachain_runtime::RuntimeCall::BridgeMillauMessages( - rialto_parachain_runtime::MessagesCall::send_message { - lane_id: lane, - payload, - delivery_and_dispatch_fee: fee, - }, - ) - .into(), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }) - } } impl CliChain for RialtoParachain { diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index ef13920cf8554..5cca26105b87d 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -16,7 +16,6 @@ //! RialtoParachain-to-Millau messages sync entrypoint. -use messages_relay::relay_strategy::MixStrategy; use relay_millau_client::Millau; use relay_rialto_parachain_client::RialtoParachain; use substrate_relay_helper::messages_lane::{ @@ -27,30 +26,8 @@ use substrate_relay_helper::messages_lane::{ /// Description of RialtoParachain -> Millau messages bridge. #[derive(Clone, Debug)] pub struct RialtoParachainMessagesToMillau; -substrate_relay_helper::generate_direct_update_conversion_rate_call_builder!( - RialtoParachain, - RialtoParachainMessagesToMillauUpdateConversionRateCallBuilder, - rialto_parachain_runtime::Runtime, - rialto_parachain_runtime::WithMillauMessagesInstance, - rialto_parachain_runtime::millau_messages::RialtoParachainToMillauMessagesParameter::MillauToRialtoParachainConversionRate -); impl SubstrateMessageLane for RialtoParachainMessagesToMillau { - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_PARACHAIN_TO_MILLAU_CONVERSION_RATE_PARAMETER_NAME); - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto_parachain::MILLAU_TO_RIALTO_PARACHAIN_CONVERSION_RATE_PARAMETER_NAME); - - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_millau::RIALTO_PARACHAIN_FEE_MULTIPLIER_PARAMETER_NAME); - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str> = - Some(bp_rialto_parachain::MILLAU_FEE_MULTIPLIER_PARAMETER_NAME); - - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_rialto_parachain::TRANSACTION_PAYMENT_PALLET_NAME); - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str> = - Some(bp_millau::TRANSACTION_PAYMENT_PALLET_NAME); - type SourceChain = RialtoParachain; type TargetChain = Millau; @@ -64,9 +41,4 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { rialto_parachain_runtime::Runtime, rialto_parachain_runtime::WithMillauMessagesInstance, >; - - type TargetToSourceChainConversionRateUpdateBuilder = - RialtoParachainMessagesToMillauUpdateConversionRateCallBuilder; - - type RelayStrategy = MixStrategy; } diff --git a/relays/bin-substrate/src/chains/statemine.rs b/relays/bin-substrate/src/chains/statemine.rs deleted file mode 100644 index 0c0edd2f3e484..0000000000000 --- a/relays/bin-substrate/src/chains/statemine.rs +++ /dev/null @@ -1,34 +0,0 @@ -// 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 . - -//! Statemine chain specification for CLI. - -use crate::cli::CliChain; -use relay_statemine_client::Statemine; -use sp_version::RuntimeVersion; - -impl CliChain for Statemine { - const RUNTIME_VERSION: Option = Some(bp_statemine::VERSION); - - type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - sp_core::crypto::Ss58AddressFormat::from( - sp_core::crypto::Ss58AddressFormatRegistry::KusamaAccount, - ) - .into() - } -} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 0bed036d91a9b..ae2a36cd1d553 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -15,7 +15,6 @@ // along with Parity Bridges Common. If not, see . use crate::cli::CliChain; -use messages_relay::relay_strategy::MixStrategy; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use parachains_relay::ParachainsPipeline; use relay_substrate_client::{AccountKeyPairOf, Chain, ChainWithTransactions, RelayChain}; @@ -46,7 +45,7 @@ impl FullBridge { Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, Self::BridgeHubRococoToBridgeHubWococo | Self::BridgeHubWococoToBridgeHubRococo => - unimplemented!("TODO: (bridge_instance_index) do we need it or refactor or remove?"), + unimplemented!("Relay doesn't support send-message subcommand on bridge hubs"), } } } @@ -102,9 +101,5 @@ pub trait MessagesCliBridge: CliBridgeBase { /// defined bridge. const ESTIMATE_MESSAGE_FEE_METHOD: &'static str; /// The Source -> Destination messages synchronization pipeline. - type MessagesLane: SubstrateMessageLane< - SourceChain = Self::Source, - TargetChain = Self::Target, - RelayStrategy = MixStrategy, - >; + type MessagesLane: SubstrateMessageLane; } diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 9f9ef37ff0eaa..c7ca5d51f7993 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -15,8 +15,8 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ExplicitOrMaximal, HexBytes}; -use bp_messages::LaneId; use bp_runtime::EncodedOrDecodedCall; +use codec::Encode; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -47,14 +47,6 @@ pub trait CliEncodeMessage: Chain { message: xcm::VersionedXcm<()>, bridge_instance_index: u8, ) -> anyhow::Result>; - - /// Encode a send message call of the bridge-messages pallet. - fn encode_send_message_call( - lane: LaneId, - message: RawMessage, - fee: Self::Balance, - bridge_instance_index: u8, - ) -> anyhow::Result>; } /// Encode message payload passed through CLI flags. @@ -63,15 +55,36 @@ pub(crate) fn encode_message( ) -> anyhow::Result { Ok(match message { Message::Raw { ref data } => data.0.clone(), - Message::Sized { ref size } => match *size { - ExplicitOrMaximal::Explicit(size) => vec![42; size as usize], - ExplicitOrMaximal::Maximal => { - let maximal_size = compute_maximal_message_size( + Message::Sized { ref size } => { + let expected_xcm_size = match *size { + ExplicitOrMaximal::Explicit(size) => size, + ExplicitOrMaximal::Maximal => compute_maximal_message_size( Source::max_extrinsic_size(), Target::max_extrinsic_size(), + ), + }; + + // there's no way to craft XCM of the given size - we'll be using `ExpectPallet` + // instruction, which has byte vector inside + let mut current_vec_size = expected_xcm_size; + let xcm = loop { + let xcm = xcm::VersionedXcm::<()>::V3( + vec![xcm::v3::Instruction::ExpectPallet { + index: 0, + name: vec![42; current_vec_size as usize], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + }] + .into(), ); - vec![42; maximal_size as usize] - }, + if xcm.encode().len() <= expected_xcm_size as usize { + break xcm + } + + current_vec_size -= 1; + }; + xcm.encode() }, }) } @@ -95,3 +108,38 @@ pub(crate) fn compute_maximal_message_size( maximal_message_size } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::cli::send_message::decode_xcm; + use bp_runtime::Chain; + use relay_millau_client::Millau; + use relay_rialto_client::Rialto; + + #[test] + fn encode_explicit_size_message_works() { + let msg = encode_message::(&Message::Sized { + size: ExplicitOrMaximal::Explicit(100), + }) + .unwrap(); + assert_eq!(msg.len(), 100); + // check that it decodes to valid xcm + let _ = decode_xcm(msg).unwrap(); + } + + #[test] + fn encode_maximal_size_message_works() { + let maximal_size = compute_maximal_message_size( + Rialto::max_extrinsic_size(), + Millau::max_extrinsic_size(), + ); + + let msg = + encode_message::(&Message::Sized { size: ExplicitOrMaximal::Maximal }) + .unwrap(); + assert_eq!(msg.len(), maximal_size as usize); + // check that it decodes to valid xcm + let _ = decode_xcm(msg).unwrap(); + } +} diff --git a/relays/bin-substrate/src/cli/estimate_fee.rs b/relays/bin-substrate/src/cli/estimate_fee.rs deleted file mode 100644 index 00a175187778c..0000000000000 --- a/relays/bin-substrate/src/cli/estimate_fee.rs +++ /dev/null @@ -1,292 +0,0 @@ -// 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 . - -use crate::{ - chains::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, - }, - cli::{ - bridge::{FullBridge, MessagesCliBridge}, - chain_schema::*, - relay_headers_and_messages::CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - Balance, HexBytes, HexLaneId, - }, -}; -use async_trait::async_trait; -use bp_runtime::BalanceOf; -use codec::{Decode, Encode}; -use relay_substrate_client::{Chain, ChainBase}; -use sp_runtime::FixedU128; -use std::fmt::Display; -use structopt::StructOpt; -use strum::VariantNames; -use substrate_relay_helper::helpers::tokens_conversion_rate_from_metrics; - -/// Estimate Delivery & Dispatch Fee command. -#[derive(StructOpt, Debug, PartialEq)] -pub struct EstimateFee { - /// A bridge instance to encode call for. - #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] - bridge: FullBridge, - #[structopt(flatten)] - source: SourceConnectionParams, - /// Hex-encoded id of lane that will be delivering the message. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// A way to override conversion rate between bridge tokens. - /// - /// If not specified, conversion rate from runtime storage is used. It may be obsolete and - /// your message won't be relayed. - #[structopt(long)] - conversion_rate_override: Option, - /// Payload to send over the bridge. - #[structopt(flatten)] - payload: crate::cli::encode_message::Message, -} - -/// A way to override conversion rate between bridge tokens. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ConversionRateOverride { - /// The actual conversion rate is computed in the same way how rate metric works. - Metric, - /// The actual conversion rate is specified explicitly. - Explicit(f64), -} - -impl std::str::FromStr for ConversionRateOverride { - type Err = String; - - fn from_str(s: &str) -> Result { - if s.to_lowercase() == "metric" { - return Ok(ConversionRateOverride::Metric) - } - - f64::from_str(s) - .map(ConversionRateOverride::Explicit) - .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'metric' or explicit value")) - } -} - -#[async_trait] -trait FeeEstimator: MessagesCliBridge -where - ::Balance: Display + Into, -{ - async fn estimate_fee(data: EstimateFee) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let lane = data.lane.into(); - let payload = - crate::cli::encode_message::encode_message::(&data.payload) - .map_err(|e| anyhow::format_err!("{:?}", e))?; - - let fee = estimate_message_delivery_and_dispatch_fee::( - &source_client, - data.conversion_rate_override, - Self::ESTIMATE_MESSAGE_FEE_METHOD, - lane, - &payload, - ) - .await?; - - log::info!(target: "bridge", "Fee: {:?}", Balance(fee.into())); - println!("{fee}"); - Ok(()) - } -} - -impl FeeEstimator for MillauToRialtoCliBridge {} -impl FeeEstimator for RialtoToMillauCliBridge {} -impl FeeEstimator for MillauToRialtoParachainCliBridge {} -impl FeeEstimator for RialtoParachainToMillauCliBridge {} - -impl EstimateFee { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - FullBridge::MillauToRialto => MillauToRialtoCliBridge::estimate_fee(self), - FullBridge::RialtoToMillau => RialtoToMillauCliBridge::estimate_fee(self), - FullBridge::MillauToRialtoParachain => - MillauToRialtoParachainCliBridge::estimate_fee(self), - FullBridge::RialtoParachainToMillau => - RialtoParachainToMillauCliBridge::estimate_fee(self), - FullBridge::BridgeHubRococoToBridgeHubWococo | - FullBridge::BridgeHubWococoToBridgeHubRococo => - unimplemented!("TODO: (EstimateFee) do we need it or refactor or remove?"), - } - .await - } -} - -/// The caller may provide target to source tokens conversion rate override to use in fee -/// computation. -pub(crate) async fn estimate_message_delivery_and_dispatch_fee< - Source: Chain, - Target: Chain, - P: Clone + Encode, ->( - client: &relay_substrate_client::Client, - conversion_rate_override: Option, - estimate_fee_method: &str, - lane: bp_messages::LaneId, - payload: &P, -) -> anyhow::Result> { - // actual conversion rate CAN be lesser than the rate stored in the runtime. So we may try to - // pay lesser fee for the message delivery. But in this case, message may be rejected by the - // lane. So we MUST use the larger of two fees - one computed with stored fee and the one - // computed with actual fee. - - let conversion_rate_override = - match (conversion_rate_override, Source::TOKEN_ID, Target::TOKEN_ID) { - (Some(ConversionRateOverride::Explicit(v)), _, _) => { - let conversion_rate_override = FixedU128::from_float(v); - log::info!( - target: "bridge", - "{} -> {} conversion rate override: {:?} (explicit)", - Target::NAME, - Source::NAME, - conversion_rate_override.to_float(), - ); - Some(conversion_rate_override) - }, - ( - Some(ConversionRateOverride::Metric), - Some(source_token_id), - Some(target_token_id), - ) => { - let conversion_rate_override = - tokens_conversion_rate_from_metrics(target_token_id, source_token_id).await?; - // So we have current actual conversion rate and rate that is stored in the runtime. - // And we may simply choose the maximal of these. But what if right now there's - // rate update transaction on the way, that is updating rate to 10 seconds old - // actual rate, which is bigger than the current rate? Then our message will be - // rejected. - // - // So let's increase the actual rate by the same value that the conversion rate - // updater is using. - let increased_conversion_rate_override = FixedU128::from_float( - conversion_rate_override * (1.0 + CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO), - ); - log::info!( - target: "bridge", - "{} -> {} conversion rate override: {} (value from metric - {})", - Target::NAME, - Source::NAME, - increased_conversion_rate_override.to_float(), - conversion_rate_override, - ); - Some(increased_conversion_rate_override) - }, - _ => None, - }; - - let without_override = do_estimate_message_delivery_and_dispatch_fee( - client, - estimate_fee_method, - lane, - payload, - None, - ) - .await?; - let with_override = do_estimate_message_delivery_and_dispatch_fee( - client, - estimate_fee_method, - lane, - payload, - conversion_rate_override, - ) - .await?; - let maximal_fee = std::cmp::max(without_override, with_override); - - log::info!( - target: "bridge", - "Estimated message fee: {:?} = max of {:?} (without rate override) and {:?} (with override to {:?})", - maximal_fee, - without_override, - with_override, - conversion_rate_override, - ); - - Ok(maximal_fee) -} - -/// Estimate message delivery and dispatch fee with given conversion rate override. -async fn do_estimate_message_delivery_and_dispatch_fee( - client: &relay_substrate_client::Client, - estimate_fee_method: &str, - lane: bp_messages::LaneId, - payload: &P, - conversion_rate_override: Option, -) -> anyhow::Result> { - let encoded_response = client - .state_call( - estimate_fee_method.into(), - (lane, payload, conversion_rate_override).encode().into(), - None, - ) - .await?; - let decoded_response: Option> = Decode::decode(&mut &encoded_response.0[..]) - .map_err(relay_substrate_client::Error::ResponseParseFailed)?; - let fee = decoded_response.ok_or_else(|| { - anyhow::format_err!("Unable to decode fee from: {:?}", HexBytes(encoded_response.to_vec())) - })?; - Ok(fee) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_parse_cli_options() { - // when - let res = EstimateFee::from_iter(vec![ - "estimate_fee", - "rialto-to-millau", - "--source-port", - "1234", - "--conversion-rate-override", - "42.5", - "raw", - "1234", - ]); - - // then - assert_eq!( - res, - EstimateFee { - bridge: FullBridge::RialtoToMillau, - lane: HexLaneId([0, 0, 0, 0]), - conversion_rate_override: Some(ConversionRateOverride::Explicit(42.5)), - source: SourceConnectionParams { - source_host: "127.0.0.1".into(), - source_port: 1234, - source_secure: false, - source_runtime_version: SourceRuntimeVersionParams { - source_version_mode: RuntimeVersionType::Bundle, - source_spec_version: None, - source_transaction_version: None, - } - }, - payload: crate::cli::encode_message::Message::Raw { - data: HexBytes(vec![0x12, 0x34]) - } - } - ); - } -} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 2f2f1f227b70b..2086008bc9566 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -26,7 +26,6 @@ use bp_messages::LaneId; pub(crate) mod bridge; pub(crate) mod encode_message; -pub(crate) mod estimate_fee; pub(crate) mod send_message; mod chain_schema; @@ -74,8 +73,6 @@ pub enum Command { /// The message is being sent to the source chain, delivered to the target chain and dispatched /// there. SendMessage(send_message::SendMessage), - /// Estimate Delivery and Dispatch Fee required for message submission to messages pallet. - EstimateFee(estimate_fee::EstimateFee), /// Resubmit transactions with increased tip if they are stalled. ResubmitTransactions(resubmit_transactions::ResubmitTransactions), /// Register parachain. @@ -111,7 +108,6 @@ impl Command { Self::RelayHeadersAndMessages(arg) => arg.run().await?, Self::InitBridge(arg) => arg.run().await?, Self::SendMessage(arg) => arg.run().await?, - Self::EstimateFee(arg) => arg.run().await?, Self::ResubmitTransactions(arg) => arg.run().await?, Self::RegisterParachain(arg) => arg.run().await?, Self::RelayParachains(arg) => arg.run().await?, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 1feba9d6284e5..49e9c5aa1560f 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -31,7 +31,6 @@ mod relay_to_parachain; use async_trait::async_trait; use std::{marker::PhantomData, sync::Arc}; use structopt::StructOpt; -use strum::VariantNames; use futures::{FutureExt, TryFutureExt}; use relay_to_parachain::*; @@ -50,40 +49,27 @@ use crate::{ RelayToRelayHeadersCliBridge, }, chain_schema::*, - relay_messages::RelayerMode, CliChain, HexLaneId, PrometheusParams, }, declare_chain_cli_schema, }; use bp_messages::LaneId; use bp_runtime::{BalanceOf, BlockNumberOf}; -use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithTransactions, Client, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; use substrate_relay_helper::{ - messages_lane::MessagesRelayParams, messages_metrics::StandaloneMessagesMetrics, - on_demand::OnDemandRelay, TaggedAccount, TransactionParams, + messages_lane::MessagesRelayParams, on_demand::OnDemandRelay, TaggedAccount, TransactionParams, }; -/// Maximal allowed conversion rate error ratio (abs(real - stored) / stored) that we allow. -/// -/// If it is zero, then transaction will be submitted every time we see difference between -/// stored and real conversion rates. If it is large enough (e.g. > than 10 percents, which is 0.1), -/// then rational relayers may stop relaying messages because they were submitted using -/// lesser conversion rate. -pub(crate) const CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO: f64 = 0.05; - /// Parameters that have the same names across all bridges. #[derive(Debug, PartialEq, StructOpt)] pub struct HeadersAndMessagesSharedParams { /// Hex-encoded lane identifiers that should be served by the complex relay. #[structopt(long, default_value = "00000000")] pub lane: Vec, - #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] - pub relayer_mode: RelayerMode, /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) /// are relayed. #[structopt(long)] @@ -101,8 +87,6 @@ pub struct Full2WayBridgeCommonParams< pub right: BridgeEndCommonParams, pub metrics_params: MetricsParams, - pub left_to_right_metrics: StandaloneMessagesMetrics, - pub right_to_left_metrics: StandaloneMessagesMetrics, } impl @@ -116,19 +100,8 @@ impl(left.client.clone(), right.client.clone())?; - let right_to_left_metrics = left_to_right_metrics.clone().reverse(); - - Ok(Self { - shared, - left, - right, - metrics_params, - left_to_right_metrics, - right_to_left_metrics, - }) + + Ok(Self { shared, left, right, metrics_params }) } } @@ -146,11 +119,9 @@ struct FullBridge< Target: ChainWithTransactions + CliChain, Bridge: MessagesCliBridge, > { - shared: &'a HeadersAndMessagesSharedParams, source: &'a mut BridgeEndCommonParams, target: &'a mut BridgeEndCommonParams, metrics_params: &'a MetricsParams, - metrics: &'a StandaloneMessagesMetrics, _phantom_data: PhantomData, } @@ -166,55 +137,11 @@ where BalanceOf: TryFrom> + Into, { fn new( - shared: &'a HeadersAndMessagesSharedParams, source: &'a mut BridgeEndCommonParams, target: &'a mut BridgeEndCommonParams, metrics_params: &'a MetricsParams, - metrics: &'a StandaloneMessagesMetrics, ) -> Self { - Self { shared, source, target, metrics_params, metrics, _phantom_data: Default::default() } - } - - fn start_conversion_rate_update_loop(&mut self) -> anyhow::Result<()> { - if let Some(ref messages_pallet_owner) = self.source.messages_pallet_owner { - let format_err = || { - anyhow::format_err!( - "Cannon run conversion rate updater: {} -> {}", - Target::NAME, - Source::NAME - ) - }; - substrate_relay_helper::conversion_rate_update::run_conversion_rate_update_loop::< - Bridge::MessagesLane, - >( - self.source.client.clone(), - TransactionParams { - signer: messages_pallet_owner.clone(), - mortality: self.source.transactions_mortality, - }, - self.metrics - .target_to_source_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - self.metrics - .target_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - self.metrics - .source_to_base_conversion_rate - .as_ref() - .ok_or_else(format_err)? - .shared_value_ref(), - CONVERSION_RATE_ALLOWED_DIFFERENCE_RATIO, - ); - self.source.accounts.push(TaggedAccount::MessagesPalletOwner { - id: messages_pallet_owner.public().into(), - bridged_chain: Target::NAME.to_string(), - }); - } - Ok(()) + Self { source, target, metrics_params, _phantom_data: Default::default() } } fn messages_relay_params( @@ -223,9 +150,6 @@ where target_to_source_headers_relay: Arc>>, lane_id: LaneId, ) -> MessagesRelayParams { - let relayer_mode = self.shared.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); - MessagesRelayParams { source_client: self.source.client.clone(), source_transaction_params: TransactionParams { @@ -241,8 +165,6 @@ where target_to_source_headers_relay: Some(target_to_source_headers_relay), lane_id, metrics_params: self.metrics_params.clone().disable(), - standalone_metrics: Some(self.metrics.clone()), - relay_strategy, } } } @@ -314,22 +236,18 @@ where fn left_to_right(&mut self) -> FullBridge { let common = self.mut_base().mut_common(); FullBridge::<_, _, Self::L2R>::new( - &common.shared, &mut common.left, &mut common.right, &common.metrics_params, - &common.left_to_right_metrics, ) } fn right_to_left(&mut self) -> FullBridge { let common = self.mut_base().mut_common(); FullBridge::<_, _, Self::R2L>::new( - &common.shared, &mut common.right, &mut common.left, &common.metrics_params, - &common.right_to_left_metrics, ) } @@ -347,10 +265,6 @@ where }); } - // start conversion rate update loops for left/right chains - self.left_to_right().start_conversion_rate_update_loop()?; - self.right_to_left().start_conversion_rate_update_loop()?; - // start on-demand header relays let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = self.mut_base().start_on_demand_headers_relayers().await?; @@ -528,7 +442,6 @@ mod tests { HexLaneId([0x00, 0x00, 0x00, 0x00]), HexLaneId([0x73, 0x77, 0x61, 0x70]) ], - relayer_mode: RelayerMode::Rational, only_mandatory_headers: false, prometheus_params: PrometheusParams { no_prometheus: false, @@ -641,7 +554,6 @@ mod tests { MillauRialtoParachainHeadersAndMessages { shared: HeadersAndMessagesSharedParams { lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], - relayer_mode: RelayerMode::Rational, only_mandatory_headers: false, prometheus_params: PrometheusParams { no_prometheus: false, diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 23f9bf0c113f7..7f4dc34ac8bff 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -17,7 +17,7 @@ use async_trait::async_trait; use sp_core::Pair; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; +use strum::VariantNames; use crate::chains::{ bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge, @@ -27,32 +27,11 @@ use crate::chains::{ rialto_headers_to_millau::RialtoToMillauCliBridge, rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, }; -use messages_relay::relay_strategy::MixStrategy; use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions}; use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; use crate::cli::{bridge::*, chain_schema::*, CliChain, HexLaneId, PrometheusParams}; -/// Relayer operating mode. -#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)] -#[strum(serialize_all = "kebab_case")] -pub enum RelayerMode { - /// The relayer doesn't care about rewards. - Altruistic, - /// The relayer will deliver all messages and confirmations as long as he's not losing any - /// funds. - Rational, -} - -impl From for messages_relay::message_lane_loop::RelayerMode { - fn from(mode: RelayerMode) -> Self { - match mode { - RelayerMode::Altruistic => Self::Altruistic, - RelayerMode::Rational => Self::Rational, - } - } -} - /// Start messages relayer process. #[derive(StructOpt)] pub struct RelayMessages { @@ -62,8 +41,6 @@ pub struct RelayMessages { /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. #[structopt(long, default_value = "00000000")] lane: HexLaneId, - #[structopt(long, possible_values = RelayerMode::VARIANTS, case_insensitive = true, default_value = "rational")] - relayer_mode: RelayerMode, #[structopt(flatten)] source: SourceConnectionParams, #[structopt(flatten)] @@ -91,8 +68,6 @@ where let target_client = data.target.into_client::().await?; let target_sign = data.target_sign.to_keypair::()?; let target_transactions_mortality = data.target_sign.transactions_mortality()?; - let relayer_mode = data.relayer_mode.into(); - let relay_strategy = MixStrategy::new(relayer_mode); substrate_relay_helper::messages_lane::run::(MessagesRelayParams { source_client, @@ -109,8 +84,6 @@ where target_to_source_headers_relay: None, lane_id: data.lane.into(), metrics_params: data.prometheus_params.into(), - standalone_metrics: None, - relay_strategy, }) .await .map_err(|e| anyhow::format_err!("{}", e)) @@ -142,43 +115,3 @@ impl RelayMessages { .await } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn should_use_rational_relayer_mode_by_default() { - assert_eq!( - RelayMessages::from_iter(vec![ - "relay-messages", - "rialto-to-millau", - "--source-port=0", - "--source-signer=//Alice", - "--target-port=0", - "--target-signer=//Alice", - "--lane=00000000", - ]) - .relayer_mode, - RelayerMode::Rational, - ); - } - - #[test] - fn should_accept_altruistic_relayer_mode() { - assert_eq!( - RelayMessages::from_iter(vec![ - "relay-messages", - "rialto-to-millau", - "--source-port=0", - "--source-signer=//Alice", - "--target-port=0", - "--target-signer=//Alice", - "--lane=00000000", - "--relayer-mode=altruistic", - ]) - .relayer_mode, - RelayerMode::Altruistic, - ); - } -} diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index bb46762cee880..d492d3422c706 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -25,8 +25,7 @@ use crate::{ bridge::{FullBridge, MessagesCliBridge}, chain_schema::*, encode_message::{self, CliEncodeMessage, RawMessage}, - estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, - Balance, CliChain, HexLaneId, + CliChain, }, }; use async_trait::async_trait; @@ -35,30 +34,11 @@ use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, SignParam, UnsignedTransaction, }; -use sp_core::{Bytes, Pair}; +use sp_core::Pair; use sp_runtime::AccountId32; -use std::fmt::{Debug, Display}; +use std::fmt::Display; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; - -/// Relayer operating mode. -#[derive(Debug, EnumString, EnumVariantNames, Clone, Copy, PartialEq, Eq)] -#[strum(serialize_all = "kebab_case")] -pub enum DispatchFeePayment { - /// The dispatch fee is paid at the source chain. - AtSourceChain, - /// The dispatch fee is paid at the target chain. - AtTargetChain, -} - -impl From for bp_runtime::messages::DispatchFeePayment { - fn from(dispatch_fee_payment: DispatchFeePayment) -> Self { - match dispatch_fee_payment { - DispatchFeePayment::AtSourceChain => Self::AtSourceChain, - DispatchFeePayment::AtTargetChain => Self::AtTargetChain, - } - } -} +use strum::VariantNames; /// Send bridge message. #[derive(StructOpt)] @@ -70,23 +50,6 @@ pub struct SendMessage { source: SourceConnectionParams, #[structopt(flatten)] source_sign: SourceSigningParams, - /// Send message using XCM pallet instead. By default message is sent using - /// bridge messages pallet. - #[structopt(long)] - use_xcm_pallet: bool, - /// Hex-encoded lane id. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - /// A way to override conversion rate between bridge tokens. - /// - /// If not specified, conversion rate from runtime storage is used. It may be obsolete and - /// your message won't be relayed. - #[structopt(long)] - conversion_rate_override: Option, - /// Delivery and dispatch fee in source chain base currency units. If not passed, determined - /// automatically. - #[structopt(long)] - fee: Option, /// Message type. #[structopt(subcommand)] message: crate::cli::encode_message::Message, @@ -111,53 +74,14 @@ where let source_client = data.source.into_client::().await?; let source_sign = data.source_sign.to_keypair::()?; - let lane = data.lane.clone().into(); - let conversion_rate_override = data.conversion_rate_override; - let fee = match data.fee { - Some(fee) => fee, - None => Balance( - estimate_message_delivery_and_dispatch_fee::( - &source_client, - conversion_rate_override, - Self::ESTIMATE_MESSAGE_FEE_METHOD, - lane, - &payload, - ) - .await? - .into(), - ), - }; let payload_len = payload.encoded_size(); - let send_message_call = if data.use_xcm_pallet { - Self::Source::encode_send_xcm( - decode_xcm(payload)?, - data.bridge.bridge_instance_index(), - )? - } else { - Self::Source::encode_send_message_call( - data.lane.0, - payload, - fee.cast().into(), - data.bridge.bridge_instance_index(), - )? - }; + let send_message_call = Self::Source::encode_send_xcm( + decode_xcm(payload)?, + data.bridge.bridge_instance_index(), + )?; let source_genesis_hash = *source_client.genesis_hash(); let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; - let estimated_transaction_fee = source_client - .estimate_extrinsic_fee(Bytes( - Self::Source::sign_transaction( - SignParam { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - }, - UnsignedTransaction::new(send_message_call.clone(), 0), - )? - .encode(), - )) - .await?; source_client .submit_signed_extrinsic( source_sign.public().into(), @@ -171,22 +95,10 @@ where let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); log::info!( target: "bridge", - "Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", + "Sending message to {}. Size: {}", Self::Target::NAME, - lane, payload_len, - fee, - ); - log::info!( - target: "bridge", - "The source account ({:?}) balance will be reduced by (at most) {} (message fee) - + {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()), - fee.0, - estimated_transaction_fee.inclusion_fee(), - fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()), - Self::Source::NAME, ); - Ok(unsigned) }, ) @@ -223,7 +135,7 @@ impl SendMessage { } /// Decode SCALE encoded raw XCM message. -fn decode_xcm(message: RawMessage) -> anyhow::Result> { +pub(crate) fn decode_xcm(message: RawMessage) -> anyhow::Result> { Decode::decode(&mut &message[..]) .map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e)) } @@ -243,8 +155,6 @@ mod tests { "1234", "--source-signer", "//Alice", - "--conversion-rate-override", - "0.75", "raw", "dead", ]); @@ -253,10 +163,6 @@ mod tests { assert_eq!(send_message.bridge, FullBridge::RialtoToMillau); assert_eq!(send_message.source.source_port, 1234); assert_eq!(send_message.source_sign.source_signer, Some("//Alice".into())); - assert_eq!( - send_message.conversion_rate_override, - Some(ConversionRateOverride::Explicit(0.75)) - ); assert_eq!( send_message.message, crate::cli::encode_message::Message::Raw { data: HexBytes(vec![0xDE, 0xAD]) } @@ -273,8 +179,6 @@ mod tests { "1234", "--source-signer", "//Alice", - "--conversion-rate-override", - "metric", "sized", "max", ]); @@ -283,7 +187,6 @@ mod tests { assert_eq!(send_message.bridge, FullBridge::RialtoToMillau); assert_eq!(send_message.source.source_port, 1234); assert_eq!(send_message.source_sign.source_signer, Some("//Alice".into())); - assert_eq!(send_message.conversion_rate_override, Some(ConversionRateOverride::Metric)); assert_eq!( send_message.message, crate::cli::encode_message::Message::Sized { size: ExplicitOrMaximal::Maximal } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 375f11423a524..e4740490cb5d0 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -60,7 +60,6 @@ impl Chain for BridgeHubRococo { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_bridge_hub_rococo::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_bridge_hub_rococo::SignedBlock; type Call = runtime::Call; @@ -126,8 +125,6 @@ impl ChainWithMessages for BridgeHubRococo { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_bridge_hub_rococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index f00aa6a9fa910..3199b3b4fc1c8 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -60,7 +60,6 @@ impl Chain for BridgeHubWococo { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_wococo::BEST_FINALIZED_BRIDGE_HUB_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_bridge_hub_wococo::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_bridge_hub_wococo::SignedBlock; type Call = runtime::Call; @@ -126,8 +125,6 @@ impl ChainWithMessages for BridgeHubWococo { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_wococo::FROM_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_bridge_hub_wococo::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = bp_bridge_hub_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index cdf7213df9bbb..355f26b849660 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -54,7 +54,6 @@ impl Chain for Kusama { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_kusama::SignedBlock; type Call = (); diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 77f09a89f153a..f8b350d3d0c2e 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -65,8 +65,6 @@ impl ChainWithMessages for Millau { bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::FROM_MILLAU_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_millau::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = @@ -82,7 +80,6 @@ impl Chain for Millau { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = millau_runtime::SignedBlock; type Call = millau_runtime::RuntimeCall; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index bb3867fda5318..101b62b9c35ee 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -54,7 +54,6 @@ impl Chain for Polkadot { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_polkadot::SignedBlock; type Call = (); diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index fe7c2c816162f..8cf74bdf9b1f5 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -62,7 +62,6 @@ impl Chain for RialtoParachain { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = rialto_parachain_runtime::SignedBlock; type Call = rialto_parachain_runtime::RuntimeCall; @@ -86,8 +85,6 @@ impl ChainWithMessages for RialtoParachain { bp_rialto_parachain::TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto_parachain::FROM_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_rialto_parachain::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = @@ -157,7 +154,7 @@ impl ChainWithTransactions for RialtoParachain { } fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { - unimplemented!("TODO") + None } } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 45166559b365a..23ecbbd47f6d3 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -62,7 +62,6 @@ impl Chain for Rialto { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = rialto_runtime::SignedBlock; type Call = rialto_runtime::RuntimeCall; @@ -85,8 +84,6 @@ impl ChainWithMessages for Rialto { bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::FROM_RIALTO_MESSAGE_DETAILS_METHOD; - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight = - bp_rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT; const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5f1ff033559cd..fc3aa76eb4491 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -57,7 +57,6 @@ impl Chain for Rococo { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_rococo::SignedBlock; type Call = (); diff --git a/relays/client-statemine/Cargo.toml b/relays/client-statemine/Cargo.toml deleted file mode 100644 index 249f9fd6f4305..0000000000000 --- a/relays/client-statemine/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "relay-statemine-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } -scale-info = { version = "2.1.1", features = ["derive"] } - -# Bridge dependencies - -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-statemine = { path = "../../primitives/chain-statemine" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-statemine/src/lib.rs b/relays/client-statemine/src/lib.rs deleted file mode 100644 index a5f6fed79f434..0000000000000 --- a/relays/client-statemine/src/lib.rs +++ /dev/null @@ -1,112 +0,0 @@ -// 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 . - -//! Types used to connect to the Statemine chain. - -use codec::Encode; -use frame_support::weights::Weight; -use relay_substrate_client::{ - Chain, ChainBase, ChainWithTransactions, Error as SubstrateError, SignParam, - UnsignedTransaction, -}; -use sp_core::Pair; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub mod runtime; - -/// Statemine chain definition -#[derive(Debug, Clone, Copy)] -pub struct Statemine; - -impl ChainBase for Statemine { - type BlockNumber = bp_statemine::BlockNumber; - type Hash = bp_statemine::Hash; - type Hasher = bp_statemine::Hasher; - type Header = bp_statemine::Header; - - type AccountId = bp_statemine::AccountId; - type Balance = bp_statemine::Balance; - type Index = bp_statemine::Nonce; - type Signature = bp_statemine::Signature; - - fn max_extrinsic_size() -> u32 { - bp_statemine::Statemine::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_statemine::Statemine::max_extrinsic_weight() - } -} - -impl Chain for Statemine { - const NAME: &'static str = "Statemine"; - const TOKEN_ID: Option<&'static str> = Some("kusama"); - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = ""; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_statemine::EXTRA_STORAGE_PROOF_SIZE; - - type SignedBlock = bp_statemine::SignedBlock; - type Call = runtime::Call; -} - -impl ChainWithTransactions for Statemine { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = runtime::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call.clone(), - bp_statemine::SignedExtensions::new( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - ), - ) - .expect("SignedExtension never fails."); - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(runtime::UncheckedExtrinsic::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == bp_statemine::Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { - unimplemented!("not used on Statemine") - } -} diff --git a/relays/client-statemine/src/runtime.rs b/relays/client-statemine/src/runtime.rs deleted file mode 100644 index 92924555769e4..0000000000000 --- a/relays/client-statemine/src/runtime.rs +++ /dev/null @@ -1,68 +0,0 @@ -// 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 . - -//! Types that are specific to the Statemine runtime. - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_runtime::FixedU128; - -/// Unchecked Statemine extrinsic. -pub type UncheckedExtrinsic = bp_polkadot_core::UncheckedExtrinsic; - -/// Statemine Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to Statemine chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with Statemine -/// `construct_runtime`, so that we maintain SCALE-compatibility. -/// -/// See: [link](https://github.com/paritytech/cumulus/blob/master/parachains/runtimes/assets/statemine/src/lib.rs) -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// With-Statemint bridge pallet. - // TODO (https://github.com/paritytech/parity-bridges-common/issues/1626): - // must be updated when we'll make appropriate changes in the Statemine runtime - #[codec(index = 42)] - WithStatemintBridgePallet(WithStatemintBridgePalletCall), -} - -/// Calls of the with-Statemint bridge pallet. -// TODO (https://github.com/paritytech/parity-bridges-common/issues/1626): -// must be updated when we'll make appropriate changes in the Statemine runtime -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum WithStatemintBridgePalletCall { - #[codec(index = 42)] - update_dot_to_ksm_conversion_rate(FixedU128), -} - -impl sp_runtime::traits::Dispatchable for Call { - type RuntimeOrigin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch( - self, - _origin: Self::RuntimeOrigin, - ) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 5763d4a61357b..0e19cf92b778f 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -19,7 +19,7 @@ use bp_runtime::{ Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEra, TransactionEraOf, }; use codec::{Codec, Encode}; -use frame_support::weights::{Weight, WeightToFee}; +use frame_support::weights::WeightToFee; use jsonrpsee::core::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; @@ -52,8 +52,6 @@ pub trait Chain: ChainBase + Clone { /// How often blocks are produced on that chain. It's suggested to set this value /// to match the block time of the chain. const AVERAGE_BLOCK_INTERVAL: Duration; - /// Maximal expected storage proof overhead (in bytes). - const STORAGE_PROOF_OVERHEAD: u32; /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; @@ -106,10 +104,6 @@ pub trait ChainWithMessages: Chain { /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - /// Additional weight of the dispatch fee payment if dispatch is paid at the target chain - /// and this `ChainWithMessages` is the target chain. - const PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN: Weight; - /// Maximal number of unrewarded relayers in a single confirmation transaction at this /// `ChainWithMessages`. const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce; diff --git a/relays/client-substrate/src/metrics/mod.rs b/relays/client-substrate/src/metrics/mod.rs index 3b63099e00036..fe200e2d3dca7 100644 --- a/relays/client-substrate/src/metrics/mod.rs +++ b/relays/client-substrate/src/metrics/mod.rs @@ -17,7 +17,5 @@ //! Contains several Substrate-specific metrics that may be exposed by relay. pub use float_storage_value::{FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric}; -pub use storage_proof_overhead::StorageProofOverheadMetric; mod float_storage_value; -mod storage_proof_overhead; diff --git a/relays/client-substrate/src/metrics/storage_proof_overhead.rs b/relays/client-substrate/src/metrics/storage_proof_overhead.rs deleted file mode 100644 index 6e0b74020b70b..0000000000000 --- a/relays/client-substrate/src/metrics/storage_proof_overhead.rs +++ /dev/null @@ -1,101 +0,0 @@ -// 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 . - -use crate::{chain::Chain, client::Client, error::Error}; - -use async_trait::async_trait; -use relay_utils::metrics::{ - metric_name, register, Gauge, Metric, PrometheusError, Registry, StandaloneMetric, U64, -}; -use sp_core::storage::StorageKey; -use sp_runtime::traits::Header as HeaderT; -use sp_storage::well_known_keys::CODE; -use std::time::Duration; - -/// Storage proof overhead update interval (in blocks). -const UPDATE_INTERVAL_IN_BLOCKS: u32 = 100; - -/// Metric that represents extra size of storage proof as unsigned integer gauge. -/// -/// There's one thing to keep in mind when using this metric: the overhead may be slightly -/// different for other values, but this metric gives a good estimation. -#[derive(Debug)] -pub struct StorageProofOverheadMetric { - client: Client, - metric: Gauge, -} - -impl Clone for StorageProofOverheadMetric { - fn clone(&self) -> Self { - StorageProofOverheadMetric { client: self.client.clone(), metric: self.metric.clone() } - } -} - -impl StorageProofOverheadMetric { - /// Create new metric instance with given name and help. - pub fn new(client: Client, name: String, help: String) -> Result { - Ok(StorageProofOverheadMetric { - client, - metric: Gauge::new(metric_name(None, &name), help)?, - }) - } - - /// Returns approximate storage proof size overhead. - async fn compute_storage_proof_overhead(&self) -> Result { - let best_header_hash = self.client.best_finalized_header_hash().await?; - let best_header = self.client.header_by_hash(best_header_hash).await?; - - let storage_proof = self - .client - .prove_storage(vec![StorageKey(CODE.to_vec())], best_header_hash) - .await?; - let storage_proof_size: usize = storage_proof.iter_nodes().map(|n| n.len()).sum(); - - let storage_value_reader = bp_runtime::StorageProofChecker::::new( - *best_header.state_root(), - storage_proof, - ) - .map_err(Error::StorageProofError)?; - let maybe_encoded_storage_value = - storage_value_reader.read_value(CODE).map_err(Error::StorageProofError)?; - let encoded_storage_value_size = - maybe_encoded_storage_value.ok_or(Error::MissingMandatoryStorageValue)?.len(); - - Ok(storage_proof_size - encoded_storage_value_size) - } -} - -impl Metric for StorageProofOverheadMetric { - fn register(&self, registry: &Registry) -> Result<(), PrometheusError> { - register(self.metric.clone(), registry).map(drop) - } -} - -#[async_trait] -impl StandaloneMetric for StorageProofOverheadMetric { - fn update_interval(&self) -> Duration { - C::AVERAGE_BLOCK_INTERVAL * UPDATE_INTERVAL_IN_BLOCKS - } - - async fn update(&self) { - relay_utils::metrics::set_gauge_value( - &self.metric, - self.compute_storage_proof_overhead() - .await - .map(|overhead| Some(overhead as u64)), - ); - } -} diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 8e1832db08453..4589687d39de1 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -54,7 +54,6 @@ impl Chain for TestChain { const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); - const STORAGE_PROOF_OVERHEAD: u32 = 0; type SignedBlock = sp_runtime::generic::SignedBlock< sp_runtime::generic::Block, diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 0f650e9e2847f..6a2944629bed1 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -57,7 +57,6 @@ impl Chain for Westend { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_westend::SignedBlock; type Call = (); @@ -114,7 +113,6 @@ impl Chain for Westmint { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTMINT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_westend::SignedBlock; type Call = (); diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index b4e9dd74d1985..04b5193afd33a 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -57,7 +57,6 @@ impl Chain for Wococo { const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE; type SignedBlock = bp_wococo::SignedBlock; type Call = (); diff --git a/relays/lib-substrate-relay/src/conversion_rate_update.rs b/relays/lib-substrate-relay/src/conversion_rate_update.rs deleted file mode 100644 index 3bd9a5a6a1985..0000000000000 --- a/relays/lib-substrate-relay/src/conversion_rate_update.rs +++ /dev/null @@ -1,439 +0,0 @@ -// 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 . - -//! Tools for updating conversion rate that is stored in the runtime storage. - -use crate::{messages_lane::SubstrateMessageLane, TransactionParams}; - -use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, ChainWithTransactions, - Client, SignParam, TransactionEra, UnsignedTransaction, -}; -use relay_utils::metrics::F64SharedRef; -use sp_core::Pair; -use std::time::{Duration, Instant}; - -/// Duration between updater iterations. -const SLEEP_DURATION: Duration = Duration::from_secs(60); - -/// Duration which will almost never expire. Since changing conversion rate may require manual -/// intervention (e.g. if call is made through `multisig` pallet), we don't want relayer to -/// resubmit transaction often. -const ALMOST_NEVER_DURATION: Duration = Duration::from_secs(60 * 60 * 24 * 30); - -/// Update-conversion-rate transaction status. -#[derive(Debug, Clone, Copy, PartialEq)] -enum TransactionStatus { - /// We have not submitted any transaction recently. - Idle, - /// We have recently submitted transaction that should update conversion rate. - Submitted(Instant, f64), -} - -/// Different ways of building 'update conversion rate' calls. -pub trait UpdateConversionRateCallBuilder { - /// Given conversion rate, build call that updates conversion rate in given chain runtime - /// storage. - fn build_update_conversion_rate_call(conversion_rate: f64) -> anyhow::Result>; -} - -impl UpdateConversionRateCallBuilder for () { - fn build_update_conversion_rate_call(_conversion_rate: f64) -> anyhow::Result> { - Err(anyhow::format_err!("Conversion rate update is not supported at {}", C::NAME)) - } -} - -/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when -/// you have a direct access to the source chain runtime. -#[rustfmt::skip] -#[macro_export] -macro_rules! generate_direct_update_conversion_rate_call_builder { - ( - $source_chain:ident, - $mocked_builder:ident, - $runtime:ty, - $instance:ty, - $parameter:path - ) => { - pub struct $mocked_builder; - - impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain> - for $mocked_builder - { - fn build_update_conversion_rate_call( - conversion_rate: f64, - ) -> anyhow::Result> { - Ok(pallet_bridge_messages::Call::update_pallet_parameter::<$runtime, $instance> { - parameter: $parameter(sp_runtime::FixedU128::from_float(conversion_rate)), - }.into()) - } - } - }; -} - -/// Macro that generates `UpdateConversionRateCallBuilder` implementation for the case when -/// you only have an access to the mocked version of source chain runtime. In this case you -/// should provide "name" of the call variant for the bridge messages calls, the "name" of -/// the variant for the `update_pallet_parameter` call within that first option and the name -/// of the conversion rate parameter itself. -#[rustfmt::skip] -#[macro_export] -macro_rules! generate_mocked_update_conversion_rate_call_builder { - ( - $source_chain:ident, - $mocked_builder:ident, - $bridge_messages:path, - $update_pallet_parameter:path, - $parameter:path - ) => { - pub struct $mocked_builder; - - impl $crate::conversion_rate_update::UpdateConversionRateCallBuilder<$source_chain> - for $mocked_builder - { - fn build_update_conversion_rate_call( - conversion_rate: f64, - ) -> anyhow::Result> { - Ok($bridge_messages($update_pallet_parameter($parameter( - sp_runtime::FixedU128::from_float(conversion_rate), - )))) - } - } - }; -} - -/// Run infinite conversion rate updater loop. -/// -/// The loop is maintaining the Left -> Right conversion rate, used as `RightTokens = LeftTokens * -/// Rate`. -pub fn run_conversion_rate_update_loop( - client: Client, - transaction_params: TransactionParams>, - left_to_right_stored_conversion_rate: F64SharedRef, - left_to_base_conversion_rate: F64SharedRef, - right_to_base_conversion_rate: F64SharedRef, - max_difference_ratio: f64, -) where - Lane: SubstrateMessageLane, - Lane::SourceChain: ChainWithTransactions, - AccountIdOf: From< as Pair>::Public>, -{ - let stall_timeout = transaction_stall_timeout( - transaction_params.mortality, - Lane::SourceChain::AVERAGE_BLOCK_INTERVAL, - ALMOST_NEVER_DURATION, - ); - - log::info!( - target: "bridge", - "Starting {} -> {} conversion rate (on {}) update loop. Stall timeout: {}s", - Lane::TargetChain::NAME, - Lane::SourceChain::NAME, - Lane::SourceChain::NAME, - stall_timeout.as_secs(), - ); - - async_std::task::spawn(async move { - let mut transaction_status = TransactionStatus::Idle; - loop { - async_std::task::sleep(SLEEP_DURATION).await; - let maybe_new_conversion_rate = maybe_select_new_conversion_rate( - stall_timeout, - &mut transaction_status, - &left_to_right_stored_conversion_rate, - &left_to_base_conversion_rate, - &right_to_base_conversion_rate, - max_difference_ratio, - ) - .await; - if let Some((prev_conversion_rate, new_conversion_rate)) = maybe_new_conversion_rate { - log::info!( - target: "bridge", - "Going to update {} -> {} (on {}) conversion rate to {}.", - Lane::TargetChain::NAME, - Lane::SourceChain::NAME, - Lane::SourceChain::NAME, - new_conversion_rate, - ); - - let result = update_target_to_source_conversion_rate::( - client.clone(), - transaction_params.clone(), - new_conversion_rate, - ) - .await; - match result { - Ok(()) => { - transaction_status = - TransactionStatus::Submitted(Instant::now(), prev_conversion_rate); - }, - Err(error) => { - log::error!( - target: "bridge", - "Failed to submit conversion rate update transaction: {:?}", - error, - ); - }, - } - } - } - }); -} - -/// Select new conversion rate to submit to the node. -async fn maybe_select_new_conversion_rate( - stall_timeout: Duration, - transaction_status: &mut TransactionStatus, - left_to_right_stored_conversion_rate: &F64SharedRef, - left_to_base_conversion_rate: &F64SharedRef, - right_to_base_conversion_rate: &F64SharedRef, - max_difference_ratio: f64, -) -> Option<(f64, f64)> { - let left_to_right_stored_conversion_rate = - (*left_to_right_stored_conversion_rate.read().await)?; - match *transaction_status { - TransactionStatus::Idle => (), - TransactionStatus::Submitted(submitted_at, _) - if Instant::now() - submitted_at > stall_timeout => - { - log::error!( - target: "bridge", - "Conversion rate update transaction has been lost and loop stalled. Restarting", - ); - - // we assume that our transaction has been lost - *transaction_status = TransactionStatus::Idle; - }, - TransactionStatus::Submitted(_, previous_left_to_right_stored_conversion_rate) => { - // we can't compare float values from different sources directly, so we only care - // whether the stored rate has been changed or not. If it has been changed, then we - // assume that our proposal has been accepted. - // - // float comparison is ok here, because we compare same-origin (stored in runtime - // storage) values and if they are different, it means that the value has actually been - // updated - #[allow(clippy::float_cmp)] - if previous_left_to_right_stored_conversion_rate == left_to_right_stored_conversion_rate - { - // the rate has not been changed => we won't submit any transactions until it is - // accepted, or the rate is changed by someone else - return None - } - - *transaction_status = TransactionStatus::Idle; - }, - } - - let left_to_base_conversion_rate = (*left_to_base_conversion_rate.read().await)?; - let right_to_base_conversion_rate = (*right_to_base_conversion_rate.read().await)?; - let actual_left_to_right_conversion_rate = - left_to_base_conversion_rate / right_to_base_conversion_rate; - - let rate_difference = - (actual_left_to_right_conversion_rate - left_to_right_stored_conversion_rate).abs(); - let rate_difference_ratio = rate_difference / left_to_right_stored_conversion_rate; - if rate_difference_ratio < max_difference_ratio { - return None - } - - Some((left_to_right_stored_conversion_rate, actual_left_to_right_conversion_rate)) -} - -/// Update Target -> Source tokens conversion rate, stored in the Source runtime storage. -pub async fn update_target_to_source_conversion_rate( - client: Client, - transaction_params: TransactionParams>, - updated_rate: f64, -) -> anyhow::Result<()> -where - Lane: SubstrateMessageLane, - Lane::SourceChain: ChainWithTransactions, - AccountIdOf: From< as Pair>::Public>, -{ - let genesis_hash = *client.genesis_hash(); - let signer_id = transaction_params.signer.public().into(); - let (spec_version, transaction_version) = client.simple_runtime_version().await?; - let call = - Lane::TargetToSourceChainConversionRateUpdateBuilder::build_update_conversion_rate_call( - updated_rate, - )?; - client - .submit_signed_extrinsic( - signer_id, - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer, - }, - move |best_block_id, transaction_nonce| { - Ok(UnsignedTransaction::new(call.into(), transaction_nonce) - .era(TransactionEra::new(best_block_id, transaction_params.mortality))) - }, - ) - .await - .map(drop) - .map_err(|err| anyhow::format_err!("{:?}", err)) -} - -#[cfg(test)] -mod tests { - use super::*; - use async_std::sync::{Arc, RwLock}; - - const TEST_STALL_TIMEOUT: Duration = Duration::from_secs(60); - - fn test_maybe_select_new_conversion_rate( - mut transaction_status: TransactionStatus, - stored_conversion_rate: Option, - left_to_base_conversion_rate: Option, - right_to_base_conversion_rate: Option, - max_difference_ratio: f64, - ) -> (Option<(f64, f64)>, TransactionStatus) { - let stored_conversion_rate = Arc::new(RwLock::new(stored_conversion_rate)); - let left_to_base_conversion_rate = Arc::new(RwLock::new(left_to_base_conversion_rate)); - let right_to_base_conversion_rate = Arc::new(RwLock::new(right_to_base_conversion_rate)); - let result = async_std::task::block_on(maybe_select_new_conversion_rate( - TEST_STALL_TIMEOUT, - &mut transaction_status, - &stored_conversion_rate, - &left_to_base_conversion_rate, - &right_to_base_conversion_rate, - max_difference_ratio, - )); - (result, transaction_status) - } - - #[test] - fn rate_is_not_updated_when_transaction_is_submitted() { - let status = TransactionStatus::Submitted(Instant::now(), 10.0); - assert_eq!( - test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), - (None, status), - ); - } - - #[test] - fn transaction_state_is_changed_to_idle_when_stored_rate_shanges() { - assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Submitted(Instant::now(), 1.0), - Some(10.0), - Some(1.0), - Some(1.0), - 100.0 - ), - (None, TransactionStatus::Idle), - ); - } - - #[test] - fn transaction_is_not_submitted_when_left_to_base_rate_is_unknown() { - assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Idle, - Some(10.0), - None, - Some(1.0), - 0.0 - ), - (None, TransactionStatus::Idle), - ); - } - - #[test] - fn transaction_is_not_submitted_when_right_to_base_rate_is_unknown() { - assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Idle, - Some(10.0), - Some(1.0), - None, - 0.0 - ), - (None, TransactionStatus::Idle), - ); - } - - #[test] - fn transaction_is_not_submitted_when_stored_rate_is_unknown() { - assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Idle, - None, - Some(1.0), - Some(1.0), - 0.0 - ), - (None, TransactionStatus::Idle), - ); - } - - #[test] - fn transaction_is_not_submitted_when_difference_is_below_threshold() { - assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Idle, - Some(1.0), - Some(1.0), - Some(1.01), - 0.02 - ), - (None, TransactionStatus::Idle), - ); - } - - #[test] - fn transaction_is_submitted_when_difference_is_above_threshold() { - let left_to_right_stored_conversion_rate = 1.0; - let left_to_base_conversion_rate = 18f64; - let right_to_base_conversion_rate = 180f64; - - assert!(left_to_base_conversion_rate < right_to_base_conversion_rate); - - assert_eq!( - test_maybe_select_new_conversion_rate( - TransactionStatus::Idle, - Some(left_to_right_stored_conversion_rate), - Some(left_to_base_conversion_rate), - Some(right_to_base_conversion_rate), - 0.02 - ), - ( - Some(( - left_to_right_stored_conversion_rate, - left_to_base_conversion_rate / right_to_base_conversion_rate, - )), - TransactionStatus::Idle - ), - ); - } - - #[test] - fn transaction_expires() { - let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT / 2, 10.0); - assert_eq!( - test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), - (None, status), - ); - - let status = TransactionStatus::Submitted(Instant::now() - TEST_STALL_TIMEOUT * 2, 10.0); - assert_eq!( - test_maybe_select_new_conversion_rate(status, Some(10.0), Some(1.0), Some(1.0), 0.0), - (Some((10.0, 1.0)), TransactionStatus::Idle), - ); - } -} diff --git a/relays/lib-substrate-relay/src/helpers.rs b/relays/lib-substrate-relay/src/helpers.rs deleted file mode 100644 index 0b824708a8996..0000000000000 --- a/relays/lib-substrate-relay/src/helpers.rs +++ /dev/null @@ -1,106 +0,0 @@ -// 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 . - -//! Substrate relay helpers - -use relay_utils::metrics::{FloatJsonValueMetric, PrometheusError, StandaloneMetric}; - -/// Creates standalone token price metric. -pub fn token_price_metric(token_id: &str) -> Result { - FloatJsonValueMetric::new( - format!("https://api.coingecko.com/api/v3/simple/price?ids={token_id}&vs_currencies=btc"), - format!("$.{token_id}.btc"), - format!("{}_to_base_conversion_rate", token_id.replace('-', "_")), - format!("Rate used to convert from {} to some BASE tokens", token_id.to_uppercase()), - ) -} - -/// Compute conversion rate between two tokens immediately, without spawning any metrics. -/// -/// Returned rate may be used in expression: `from_tokens * rate -> to_tokens`. -pub async fn tokens_conversion_rate_from_metrics( - from_token_id: &str, - to_token_id: &str, -) -> anyhow::Result { - let from_token_metric = token_price_metric(from_token_id)?; - from_token_metric.update().await; - let to_token_metric = token_price_metric(to_token_id)?; - to_token_metric.update().await; - - let from_token_value = *from_token_metric.shared_value_ref().read().await; - let to_token_value = *to_token_metric.shared_value_ref().read().await; - // `FloatJsonValueMetric` guarantees that the value is positive && normal, so no additional - // checks required here - match (from_token_value, to_token_value) { - (Some(from_token_value), Some(to_token_value)) => - Ok(tokens_conversion_rate(from_token_value, to_token_value)), - _ => Err(anyhow::format_err!( - "Failed to compute conversion rate from {} to {}", - from_token_id, - to_token_id, - )), - } -} - -/// Compute conversion rate between two tokens, given token prices. -/// -/// Returned rate may be used in expression: `from_tokens * rate -> to_tokens`. -/// -/// Both prices are assumed to be normal and non-negative. -pub fn tokens_conversion_rate(from_token_value: f64, to_token_value: f64) -> f64 { - from_token_value / to_token_value -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn rialto_to_millau_conversion_rate_is_correct() { - let rialto_price = 18.18; - let millau_price = 136.35; - assert!(rialto_price < millau_price); - - let conversion_rate = tokens_conversion_rate(rialto_price, millau_price); - let rialto_amount = 100.0; - let millau_amount = rialto_amount * conversion_rate; - assert!( - rialto_amount > millau_amount, - "{} RLT * {} = {} MLU", - rialto_amount, - conversion_rate, - millau_amount, - ); - } - - #[test] - fn millau_to_rialto_conversion_rate_is_correct() { - let rialto_price = 18.18; - let millau_price = 136.35; - assert!(rialto_price < millau_price); - - let conversion_rate = tokens_conversion_rate(millau_price, rialto_price); - let millau_amount = 100.0; - let rialto_amount = millau_amount * conversion_rate; - assert!( - rialto_amount > millau_amount, - "{} MLU * {} = {} RLT", - millau_amount, - conversion_rate, - rialto_amount, - ); - } -} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 86e652716f643..62ae756e0031e 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -18,10 +18,8 @@ #![warn(missing_docs)] -pub mod conversion_rate_update; pub mod error; pub mod finality; -pub mod helpers; pub mod messages_lane; pub mod messages_metrics; pub mod messages_source; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 09d02f7448e4d..da138a3d1258f 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -17,8 +17,6 @@ //! Tools for supporting message lanes between two Substrate-based chains. use crate::{ - conversion_rate_update::UpdateConversionRateCallBuilder, - messages_metrics::StandaloneMessagesMetrics, messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand::OnDemandRelay, @@ -33,49 +31,21 @@ use bridge_runtime_common::messages::{ }; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; -use messages_relay::{message_lane::MessageLane, relay_strategy::RelayStrategy}; +use messages_relay::message_lane::MessageLane; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, ChainWithTransactions, Client, HashOf, }; -use relay_utils::{metrics::MetricsParams, STALL_TIMEOUT}; +use relay_utils::{ + metrics::{GlobalMetrics, MetricsParams, StandaloneMetric}, + STALL_TIMEOUT, +}; use sp_core::Pair; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; /// Substrate -> Substrate messages synchronization pipeline. pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { - /// Name of the source -> target tokens conversion rate parameter. - /// - /// The parameter is stored at the target chain and the storage key is computed using - /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed - /// to be 1. - const SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; - /// Name of the target -> source tokens conversion rate parameter. - /// - /// The parameter is stored at the source chain and the storage key is computed using - /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed - /// to be 1. - const TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME: Option<&'static str>; - - /// Name of the source chain fee multiplier parameter. - /// - /// The parameter is stored at the target chain and the storage key is computed using - /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed - /// to be 1. - const SOURCE_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str>; - /// Name of the target chain fee multiplier parameter. - /// - /// The parameter is stored at the source chain and the storage key is computed using - /// `bp_runtime::storage_parameter_key` function. If value is unknown, it is assumed - /// to be 1. - const TARGET_FEE_MULTIPLIER_PARAMETER_NAME: Option<&'static str>; - - /// Name of the transaction payment pallet, deployed at the source chain. - const AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; - /// Name of the transaction payment pallet, deployed at the target chain. - const AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME: Option<&'static str>; - /// Messages of this chain are relayed to the `TargetChain`. type SourceChain: ChainWithMessages + ChainWithTransactions; /// Messages from the `SourceChain` are dispatched on this chain. @@ -85,16 +55,6 @@ pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder; /// How receive messages delivery proof call is built? type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; - - /// `TargetChain` tokens to `SourceChain` tokens conversion rate update builder. - /// - /// If not applicable to this bridge, you may use `()` here. - type TargetToSourceChainConversionRateUpdateBuilder: UpdateConversionRateCallBuilder< - Self::SourceChain, - >; - - /// Message relay strategy. - type RelayStrategy: RelayStrategy; } /// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. @@ -138,10 +98,6 @@ pub struct MessagesRelayParams { pub lane_id: LaneId, /// Metrics parameters. pub metrics_params: MetricsParams, - /// Pre-registered standalone metrics. - pub standalone_metrics: Option>, - /// Relay strategy. - pub relay_strategy: P::RelayStrategy, } /// Run Substrate-to-Substrate messages sync loop. @@ -170,13 +126,6 @@ where let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); - let standalone_metrics = params.standalone_metrics.map(Ok).unwrap_or_else(|| { - crate::messages_metrics::standalone_metrics::

( - source_client.clone(), - target_client.clone(), - ) - })?; - log::info!( target: "bridge", "Starting {} -> {} messages relay.\n\t\ @@ -220,7 +169,6 @@ where max_messages_in_single_batch, max_messages_weight_in_single_batch, max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, }, }, SubstrateMessagesSource::

::new( @@ -236,10 +184,12 @@ where params.lane_id, relayer_id_at_source, params.target_transaction_params, - standalone_metrics.clone(), params.source_to_target_headers_relay, ), - standalone_metrics.register_and_spawn(params.metrics_params)?, + { + GlobalMetrics::new()?.register_and_spawn(¶ms.metrics_params.registry)?; + params.metrics_params + }, futures::future::pending(), ) .await @@ -271,7 +221,6 @@ where R: BridgeMessagesConfig>, I: 'static, R::SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< - R::InboundMessageFee, MessagesProof = FromBridgedChainMessagesProof>, >, CallOf: From> + GetDispatchInfo, diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 805d002b65f87..37a6d67baae43 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -16,260 +16,20 @@ //! Tools for supporting message lanes between two Substrate-based chains. -use crate::{helpers::tokens_conversion_rate, messages_lane::SubstrateMessageLane, TaggedAccount}; +use crate::TaggedAccount; use codec::Decode; use frame_system::AccountInfo; use pallet_balances::AccountData; use relay_substrate_client::{ - metrics::{ - FixedU128OrOne, FloatStorageValue, FloatStorageValueMetric, StorageProofOverheadMetric, - }, + metrics::{FloatStorageValue, FloatStorageValueMetric}, AccountIdOf, BalanceOf, Chain, ChainWithBalances, Client, Error as SubstrateError, IndexOf, }; -use relay_utils::metrics::{ - FloatJsonValueMetric, GlobalMetrics, MetricsParams, PrometheusError, StandaloneMetric, -}; +use relay_utils::metrics::{MetricsParams, StandaloneMetric}; use sp_core::storage::StorageData; use sp_runtime::{FixedPointNumber, FixedU128}; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; -/// Name of the `NextFeeMultiplier` storage value within the transaction payment pallet. -const NEXT_FEE_MULTIPLIER_VALUE_NAME: &str = "NextFeeMultiplier"; - -/// Shared references to the standalone metrics of the message lane relay loop. -#[derive(Debug, Clone)] -pub struct StandaloneMessagesMetrics { - /// Global metrics. - pub global: GlobalMetrics, - /// Storage chain proof overhead metric. - pub source_storage_proof_overhead: StorageProofOverheadMetric, - /// Target chain proof overhead metric. - pub target_storage_proof_overhead: StorageProofOverheadMetric, - /// Source tokens to base conversion rate metric. - pub source_to_base_conversion_rate: Option, - /// Target tokens to base conversion rate metric. - pub target_to_base_conversion_rate: Option, - /// Source tokens to target tokens conversion rate metric. This rate is stored by the target - /// chain. - pub source_to_target_conversion_rate: Option>, - /// Target tokens to source tokens conversion rate metric. This rate is stored by the source - /// chain. - pub target_to_source_conversion_rate: Option>, - - /// Actual source chain fee multiplier. - pub source_fee_multiplier: Option>, - /// Source chain fee multiplier, stored at the target chain. - pub source_fee_multiplier_at_target: Option>, - /// Actual target chain fee multiplier. - pub target_fee_multiplier: Option>, - /// Target chain fee multiplier, stored at the target chain. - pub target_fee_multiplier_at_source: Option>, -} - -impl StandaloneMessagesMetrics { - /// Swap source and target sides. - pub fn reverse(self) -> StandaloneMessagesMetrics { - StandaloneMessagesMetrics { - global: self.global, - source_storage_proof_overhead: self.target_storage_proof_overhead, - target_storage_proof_overhead: self.source_storage_proof_overhead, - source_to_base_conversion_rate: self.target_to_base_conversion_rate, - target_to_base_conversion_rate: self.source_to_base_conversion_rate, - source_to_target_conversion_rate: self.target_to_source_conversion_rate, - target_to_source_conversion_rate: self.source_to_target_conversion_rate, - source_fee_multiplier: self.target_fee_multiplier, - source_fee_multiplier_at_target: self.target_fee_multiplier_at_source, - target_fee_multiplier: self.source_fee_multiplier, - target_fee_multiplier_at_source: self.source_fee_multiplier_at_target, - } - } - - /// Register all metrics in the registry. - pub fn register_and_spawn( - self, - metrics: MetricsParams, - ) -> Result { - self.global.register_and_spawn(&metrics.registry)?; - self.source_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - self.target_storage_proof_overhead.register_and_spawn(&metrics.registry)?; - if let Some(m) = self.source_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_base_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_to_source_conversion_rate { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.source_fee_multiplier { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.source_fee_multiplier_at_target { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_fee_multiplier { - m.register_and_spawn(&metrics.registry)?; - } - if let Some(m) = self.target_fee_multiplier_at_source { - m.register_and_spawn(&metrics.registry)?; - } - Ok(metrics) - } - - /// Return conversion rate from target to source tokens. - pub async fn target_to_source_conversion_rate(&self) -> Option { - let from_token_value = - (*self.target_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await)?; - let to_token_value = - (*self.source_to_base_conversion_rate.as_ref()?.shared_value_ref().read().await)?; - Some(tokens_conversion_rate(from_token_value, to_token_value)) - } -} - -/// Create symmetric standalone metrics for the message lane relay loop. -/// -/// All metrics returned by this function are exposed by loops that are serving given lane (`P`) -/// and by loops that are serving reverse lane (`P` with swapped `TargetChain` and `SourceChain`). -/// We assume that either conversion rate parameters have values in the storage, or they are -/// initialized with 1:1. -pub fn standalone_metrics( - source_client: Client, - target_client: Client, -) -> anyhow::Result> { - Ok(StandaloneMessagesMetrics { - global: GlobalMetrics::new()?, - source_storage_proof_overhead: StorageProofOverheadMetric::new( - source_client.clone(), - format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), - format!("{} storage proof overhead", P::SourceChain::NAME), - )?, - target_storage_proof_overhead: StorageProofOverheadMetric::new( - target_client.clone(), - format!("{}_storage_proof_overhead", P::TargetChain::NAME.to_lowercase()), - format!("{} storage proof overhead", P::TargetChain::NAME), - )?, - source_to_base_conversion_rate: P::SourceChain::TOKEN_ID - .map(|source_chain_token_id| { - crate::helpers::token_price_metric(source_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_base_conversion_rate: P::TargetChain::TOKEN_ID - .map(|target_chain_token_id| { - crate::helpers::token_price_metric(target_chain_token_id).map(Some) - }) - .unwrap_or(Ok(None))?, - source_to_target_conversion_rate: P::SOURCE_TO_TARGET_CONVERSION_RATE_PARAMETER_NAME - .map(bp_runtime::storage_parameter_key) - .map(|key| { - FloatStorageValueMetric::new( - FixedU128OrOne::default(), - target_client.clone(), - key, - format!( - "{}_{}_to_{}_conversion_rate", - P::TargetChain::NAME, - P::SourceChain::NAME, - P::TargetChain::NAME - ), - format!( - "{} to {} tokens conversion rate (used by {})", - P::SourceChain::NAME, - P::TargetChain::NAME, - P::TargetChain::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - target_to_source_conversion_rate: P::TARGET_TO_SOURCE_CONVERSION_RATE_PARAMETER_NAME - .map(bp_runtime::storage_parameter_key) - .map(|key| { - FloatStorageValueMetric::new( - FixedU128OrOne::default(), - source_client.clone(), - key, - format!( - "{}_{}_to_{}_conversion_rate", - P::SourceChain::NAME, - P::TargetChain::NAME, - P::SourceChain::NAME - ), - format!( - "{} to {} tokens conversion rate (used by {})", - P::TargetChain::NAME, - P::SourceChain::NAME, - P::SourceChain::NAME - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - source_fee_multiplier: P::AT_SOURCE_TRANSACTION_PAYMENT_PALLET_NAME - .map(|pallet| bp_runtime::storage_value_key(pallet, NEXT_FEE_MULTIPLIER_VALUE_NAME)) - .map(|key| { - log::trace!(target: "bridge", "{}_fee_multiplier", P::SourceChain::NAME); - FloatStorageValueMetric::new( - FixedU128OrOne::default(), - source_client.clone(), - key, - format!("{}_fee_multiplier", P::SourceChain::NAME,), - format!("{} fee multiplier", P::SourceChain::NAME,), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - source_fee_multiplier_at_target: P::SOURCE_FEE_MULTIPLIER_PARAMETER_NAME - .map(bp_runtime::storage_parameter_key) - .map(|key| { - FloatStorageValueMetric::new( - FixedU128OrOne::default(), - target_client.clone(), - key, - format!("{}_{}_fee_multiplier", P::TargetChain::NAME, P::SourceChain::NAME,), - format!( - "{} fee multiplier stored at {}", - P::SourceChain::NAME, - P::TargetChain::NAME, - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - target_fee_multiplier: P::AT_TARGET_TRANSACTION_PAYMENT_PALLET_NAME - .map(|pallet| bp_runtime::storage_value_key(pallet, NEXT_FEE_MULTIPLIER_VALUE_NAME)) - .map(|key| { - log::trace!(target: "bridge", "{}_fee_multiplier", P::TargetChain::NAME); - FloatStorageValueMetric::new( - FixedU128OrOne::default(), - target_client, - key, - format!("{}_fee_multiplier", P::TargetChain::NAME,), - format!("{} fee multiplier", P::TargetChain::NAME,), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - target_fee_multiplier_at_source: P::TARGET_FEE_MULTIPLIER_PARAMETER_NAME - .map(bp_runtime::storage_parameter_key) - .map(|key| { - FloatStorageValueMetric::new( - FixedU128OrOne::default(), - source_client, - key, - format!("{}_{}_fee_multiplier", P::SourceChain::NAME, P::TargetChain::NAME,), - format!( - "{} fee multiplier stored at {}", - P::TargetChain::NAME, - P::SourceChain::NAME, - ), - ) - .map(Some) - }) - .unwrap_or(Ok(None))?, - }) -} - /// Add relay accounts balance metrics. pub async fn add_relay_balances_metrics( client: Client, @@ -359,9 +119,6 @@ fn convert_to_token_balance(balance: u128, token_decimals: u32) -> FixedU128 { #[cfg(test)] mod tests { use super::*; - use frame_support::storage::generator::StorageValue; - use sp_core::storage::StorageKey; - #[test] fn token_decimals_used_properly() { let plancks = 425_000_000_000; @@ -369,12 +126,4 @@ mod tests { let dots = convert_to_token_balance(plancks, token_decimals); assert_eq!(dots, FixedU128::saturating_from_rational(425, 10)); } - - #[test] - fn next_fee_multiplier_storage_key_is_correct() { - assert_eq!( - bp_runtime::storage_value_key("TransactionPayment", NEXT_FEE_MULTIPLIER_VALUE_NAME), - StorageKey(pallet_transaction_payment::NextFeeMultiplier::::storage_value_final_key().to_vec()), - ); - } } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index c02db3fb48a63..57f84eb6bb19d 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -31,13 +31,11 @@ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::{operating_mode_key, outbound_lane_data_key}, - InboundMessageDetails, LaneId, MessageData, MessageNonce, MessagePayload, - MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, -}; -use bp_runtime::{messages::DispatchFeePayment, BasicOperatingMode, HeaderIdProvider}; -use bridge_runtime_common::messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + InboundMessageDetails, LaneId, MessageNonce, MessagePayload, MessagesOperatingMode, + OutboundLaneData, OutboundMessageDetails, }; +use bp_runtime::{BasicOperatingMode, HeaderIdProvider}; +use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::{Decode, Encode}; use frame_support::weights::Weight; use messages_relay::{ @@ -47,11 +45,11 @@ use messages_relay::{ SourceClientState, }, }; -use num_traits::{Bounded, Zero}; +use num_traits::Zero; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, - ChainWithTransactions, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, - TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -62,7 +60,7 @@ use std::ops::RangeInclusive; /// required to submit to the target node: cumulative dispatch weight of bundled messages and /// the proof itself. pub type SubstrateMessagesProof = (Weight, FromBridgedChainMessagesProof>); -type MessagesToRefine<'a, Balance> = Vec<(MessagePayload, &'a mut OutboundMessageDetails)>; +type MessagesToRefine<'a> = Vec<(MessagePayload, &'a mut OutboundMessageDetails)>; /// Substrate client as Substrate messages source. pub struct SubstrateMessagesSource { @@ -207,9 +205,7 @@ where // prepare arguments of the inbound message details call (if we need it) let mut msgs_to_refine = vec![]; for out_msg_details in out_msgs_details.iter_mut() { - if out_msg_details.dispatch_fee_payment != DispatchFeePayment::AtTargetChain { - continue - } + // in our current strategy all messages are supposed to be paid at the target chain // for pay-at-target messages we may want to ask target chain for // refined dispatch weight @@ -218,7 +214,7 @@ where &self.lane_id, out_msg_details.nonce, ); - let msg_data: MessageData> = + let msg_payload: MessagePayload = self.source_client.storage_value(msg_key, Some(id.1)).await?.ok_or_else(|| { SubstrateError::Custom(format!( "Message to {} {:?}/{} is missing from runtime the storage of {} at {:?}", @@ -230,7 +226,7 @@ where )) })?; - msgs_to_refine.push((msg_data.payload, out_msg_details)); + msgs_to_refine.push((msg_payload, out_msg_details)); } for mut msgs_to_refine_batch in @@ -277,8 +273,7 @@ where MessageDetails { dispatch_weight: out_msg_details.dispatch_weight, size: out_msg_details.size as _, - reward: out_msg_details.delivery_and_dispatch_fee, - dispatch_fee_payment: out_msg_details.dispatch_fee_payment, + reward: Zero::zero(), }, ); } @@ -370,39 +365,6 @@ where target_to_source_headers_relay.require_more_headers(id.0).await; } } - - async fn estimate_confirmation_transaction( - &self, - ) -> as MessageLane>::SourceChainBalance { - let runtime_version = match self.source_client.runtime_version().await { - Ok(v) => v, - Err(_) => return BalanceOf::::max_value(), - }; - async { - let dummy_tx = P::SourceChain::sign_transaction( - SignParam:: { - spec_version: runtime_version.spec_version, - transaction_version: runtime_version.transaction_version, - genesis_hash: *self.source_client.genesis_hash(), - signer: self.transaction_params.signer.clone(), - }, - make_messages_delivery_proof_transaction::

( - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - prepare_dummy_messages_delivery_proof::(), - false, - )?, - )? - .encode(); - self.source_client - .estimate_extrinsic_fee(Bytes(dummy_tx)) - .await - .map(|fee| fee.inclusion_fee()) - } - .await - .unwrap_or_else(|_| BalanceOf::::max_value()) - } } /// Ensure that the messages pallet at source chain is active. @@ -441,30 +403,6 @@ fn make_messages_delivery_proof_transaction( .era(TransactionEra::new(source_best_block_id, source_transaction_params.mortality))) } -/// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. -/// -/// We don't care about proof actually being the valid proof, because its validity doesn't -/// affect the call weight - we only care about its size. -fn prepare_dummy_messages_delivery_proof( -) -> SubstrateMessagesDeliveryProof { - let single_message_confirmation_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint_u32(1, 1); - let proof_size = TC::STORAGE_PROOF_OVERHEAD.saturating_add(single_message_confirmation_size); - ( - UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - messages_in_oldest_entry: 1, - total_messages: 1, - last_delivered_nonce: 1, - }, - FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: Default::default(), - storage_proof: vec![vec![0; proof_size as usize]], - lane: Default::default(), - }, - ) -} - /// Read best blocks from given client. /// /// This function assumes that the chain that is followed by the `self_client` has @@ -552,7 +490,7 @@ where } fn validate_out_msgs_details( - out_msgs_details: &[OutboundMessageDetails], + out_msgs_details: &[OutboundMessageDetails], nonces: RangeInclusive, ) -> Result<(), SubstrateError> { let make_missing_nonce_error = |expected_nonce| { @@ -601,8 +539,8 @@ fn validate_out_msgs_details( fn split_msgs_to_refine( lane_id: LaneId, - msgs_to_refine: MessagesToRefine, -) -> Result>, SubstrateError> { + msgs_to_refine: MessagesToRefine, +) -> Result, SubstrateError> { let max_batch_size = Target::max_extrinsic_size() as usize; let mut batches = vec![]; @@ -635,23 +573,20 @@ fn split_msgs_to_refine( #[cfg(test)] mod tests { use super::*; - use bp_runtime::{messages::DispatchFeePayment, Chain as ChainBase}; - use codec::MaxEncodedLen; + use bp_runtime::Chain as ChainBase; use relay_rialto_client::Rialto; use relay_rococo_client::Rococo; use relay_wococo_client::Wococo; fn message_details_from_rpc( nonces: RangeInclusive, - ) -> Vec> { + ) -> Vec { nonces .into_iter() .map(|nonce| bp_messages::OutboundMessageDetails { nonce, dispatch_weight: Weight::zero(), size: 0, - delivery_and_dispatch_fee: 0, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }) .collect() } @@ -704,31 +639,16 @@ mod tests { )); } - #[test] - fn prepare_dummy_messages_delivery_proof_works() { - let expected_minimal_size = - bp_wococo::AccountId::max_encoded_len() as u32 + Rococo::STORAGE_PROOF_OVERHEAD; - let dummy_proof = prepare_dummy_messages_delivery_proof::(); - assert!( - dummy_proof.1.encode().len() as u32 > expected_minimal_size, - "Expected proof size at least {}. Got: {}", - expected_minimal_size, - dummy_proof.1.encode().len(), - ); - } - fn check_split_msgs_to_refine( payload_sizes: Vec, expected_batches: Result, ()>, ) { let mut out_msgs_details = vec![]; for (idx, _) in payload_sizes.iter().enumerate() { - out_msgs_details.push(OutboundMessageDetails::> { + out_msgs_details.push(OutboundMessageDetails { nonce: idx as MessageNonce, dispatch_weight: Weight::zero(), size: 0, - delivery_and_dispatch_fee: 0, - dispatch_fee_payment: DispatchFeePayment::AtTargetChain, }); } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index ed4d040b5d869..22a50acf37eb6 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -20,7 +20,6 @@ use crate::{ messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, - messages_metrics::StandaloneMessagesMetrics, messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, on_demand::OnDemandRelay, TransactionParams, @@ -32,24 +31,18 @@ use bp_messages::{ storage_keys::inbound_lane_data_key, total_unrewarded_messages, InboundLaneData, LaneId, MessageNonce, UnrewardedRelayersState, }; -use bridge_runtime_common::messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, -}; -use codec::Encode; -use frame_support::weights::{Weight, WeightToFee}; +use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; -use num_traits::{Bounded, Zero}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, - ChainWithTransactions, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, - TransactionEra, TransactionTracker, UnsignedTransaction, WeightToFeeOf, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + TransactionTracker, UnsignedTransaction, }; -use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; -use sp_core::{Bytes, Pair}; -use sp_runtime::{traits::Saturating, FixedPointNumber, FixedU128}; +use relay_utils::relay_loop::Client as RelayClient; +use sp_core::Pair; use std::{collections::VecDeque, convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. @@ -63,7 +56,6 @@ pub struct SubstrateMessagesTarget { lane_id: LaneId, relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, - metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option>>>, } @@ -75,7 +67,6 @@ impl SubstrateMessagesTarget

{ lane_id: LaneId, relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, - metric_values: StandaloneMessagesMetrics, source_to_target_headers_relay: Option< Arc>>, >, @@ -86,7 +77,6 @@ impl SubstrateMessagesTarget

{ lane_id, relayer_id_at_source, transaction_params, - metric_values, source_to_target_headers_relay, } } @@ -121,7 +111,6 @@ impl Clone for SubstrateMessagesTarget

{ lane_id: self.lane_id, relayer_id_at_source: self.relayer_id_at_source.clone(), transaction_params: self.transaction_params.clone(), - metric_values: self.metric_values.clone(), source_to_target_headers_relay: self.source_to_target_headers_relay.clone(), } } @@ -283,142 +272,6 @@ where source_to_target_headers_relay.require_more_headers(id.0).await; } } - - async fn estimate_delivery_transaction_in_source_tokens( - &self, - nonces: RangeInclusive, - total_prepaid_nonces: MessageNonce, - total_dispatch_weight: Weight, - total_size: u32, - ) -> Result< as MessageLane>::SourceChainBalance, SubstrateError> { - let conversion_rate = - self.metric_values.target_to_source_conversion_rate().await.ok_or_else(|| { - SubstrateError::Custom(format!( - "Failed to compute conversion rate from {} to {}", - P::TargetChain::NAME, - P::SourceChain::NAME, - )) - })?; - - let (spec_version, transaction_version) = - self.target_client.simple_runtime_version().await?; - // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. - let delivery_tx = P::TargetChain::sign_transaction( - SignParam { - spec_version, - transaction_version, - genesis_hash: Default::default(), - signer: self.transaction_params.signer.clone(), - }, - make_messages_delivery_transaction::

( - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - self.relayer_id_at_source.clone(), - nonces.clone(), - prepare_dummy_messages_proof::( - nonces.clone(), - total_dispatch_weight, - total_size, - ), - false, - )?, - )? - .encode(); - let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(Bytes(delivery_tx)).await?; - let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); - - // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch - // fee payment (Currency::transfer in regular deployment). But if message dispatch has - // already been paid at the Source chain, the delivery transaction will refund relayer with - // this additional cost. But `estimate_extrinsic_fee` obviously just returns pre-dispatch - // cost of the transaction. So if transaction delivers prepaid message, then it may happen - // that pre-dispatch cost is larger than reward and `Rational` relayer will refuse to - // deliver this message. - // - // The most obvious solution would be to deduct total weight of dispatch fee payments from - // the `total_dispatch_weight` and use regular `estimate_extrinsic_fee` call. But what if - // `total_dispatch_weight` is less than total dispatch fee payments weight? Weight is - // strictly positive, so we can't use this option. - // - // Instead we'll be directly using `WeightToFee` and `NextFeeMultiplier` of the Target - // chain. This requires more knowledge of the Target chain, but seems there's no better way - // to solve this now. - let expected_refund_in_target_tokens = if total_prepaid_nonces != 0 { - const WEIGHT_DIFFERENCE: Weight = Weight::from_ref_time(100); - - let (spec_version, transaction_version) = - self.target_client.simple_runtime_version().await?; - let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); - let dummy_tx = P::TargetChain::sign_transaction( - SignParam { - spec_version, - transaction_version, - genesis_hash: Default::default(), - signer: self.transaction_params.signer.clone(), - }, - make_messages_delivery_transaction::

( - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - self.relayer_id_at_source.clone(), - nonces.clone(), - prepare_dummy_messages_proof::( - nonces.clone(), - larger_dispatch_weight, - total_size, - ), - false, - )?, - )? - .encode(); - let larger_delivery_tx_fee = - self.target_client.estimate_extrinsic_fee(Bytes(dummy_tx)).await?; - - compute_prepaid_messages_refund::( - total_prepaid_nonces, - compute_fee_multiplier::( - delivery_tx_fee.adjusted_weight_fee, - total_dispatch_weight, - larger_delivery_tx_fee.adjusted_weight_fee, - larger_dispatch_weight, - ), - ) - } else { - Zero::zero() - }; - - let delivery_fee_in_source_tokens = - convert_target_tokens_to_source_tokens::( - FixedU128::from_float(conversion_rate), - inclusion_fee_in_target_tokens.saturating_sub(expected_refund_in_target_tokens), - ); - - log::trace!( - target: "bridge", - "Estimated {} -> {} messages delivery transaction.\n\t\ - Total nonces: {:?}\n\t\ - Prepaid messages: {}\n\t\ - Total messages size: {}\n\t\ - Total messages dispatch weight: {}\n\t\ - Inclusion fee (in {1} tokens): {:?}\n\t\ - Expected refund (in {1} tokens): {:?}\n\t\ - {1} -> {0} conversion rate: {:?}\n\t\ - Expected delivery tx fee (in {0} tokens): {:?}", - P::SourceChain::NAME, - P::TargetChain::NAME, - nonces, - total_prepaid_nonces, - total_size, - total_dispatch_weight, - inclusion_fee_in_target_tokens, - expected_refund_in_target_tokens, - conversion_rate, - delivery_fee_in_source_tokens, - ); - - Ok(delivery_fee_in_source_tokens) - } } /// Make messages delivery transaction from given proof. @@ -443,153 +296,3 @@ fn make_messages_delivery_transaction( Ok(UnsignedTransaction::new(call.into(), transaction_nonce) .era(TransactionEra::new(target_best_block_id, target_transaction_params.mortality))) } - -/// Prepare 'dummy' messages proof that will compose the delivery transaction. -/// -/// We don't care about proof actually being the valid proof, because its validity doesn't -/// affect the call weight - we only care about its size. -fn prepare_dummy_messages_proof( - nonces: RangeInclusive, - total_dispatch_weight: Weight, - total_size: u32, -) -> SubstrateMessagesProof { - ( - total_dispatch_weight, - FromBridgedChainMessagesProof { - bridged_header_hash: Default::default(), - storage_proof: vec![vec![ - 0; - SC::STORAGE_PROOF_OVERHEAD.saturating_add(total_size) as usize - ]], - lane: Default::default(), - nonces_start: *nonces.start(), - nonces_end: *nonces.end(), - }, - ) -} - -/// Given delivery transaction fee in target chain tokens and conversion rate to the source -/// chain tokens, compute transaction cost in source chain tokens. -fn convert_target_tokens_to_source_tokens( - target_to_source_conversion_rate: FixedU128, - target_transaction_fee: TC::Balance, -) -> SC::Balance -where - SC::Balance: TryFrom, -{ - SC::Balance::try_from( - target_to_source_conversion_rate.saturating_mul_int(target_transaction_fee), - ) - .unwrap_or_else(|_| SC::Balance::max_value()) -} - -/// Compute fee multiplier that is used by the chain, given a couple of fees for transactions -/// that are only differ in dispatch weights. -/// -/// This function assumes that standard transaction payment pallet is used by the chain. -/// The only fee component that depends on dispatch weight is the `adjusted_weight_fee`. -/// -/// **WARNING**: this functions will only be accurate if weight-to-fee conversion function -/// is linear. For non-linear polynomials the error will grow with `weight_difference` growth. -/// So better to use smaller differences. -fn compute_fee_multiplier( - smaller_adjusted_weight_fee: BalanceOf, - smaller_tx_weight: Weight, - larger_adjusted_weight_fee: BalanceOf, - larger_tx_weight: Weight, -) -> FixedU128 { - let adjusted_weight_fee_difference = - larger_adjusted_weight_fee.saturating_sub(smaller_adjusted_weight_fee); - let smaller_tx_unadjusted_weight_fee = WeightToFeeOf::::weight_to_fee(&smaller_tx_weight); - let larger_tx_unadjusted_weight_fee = WeightToFeeOf::::weight_to_fee(&larger_tx_weight); - FixedU128::saturating_from_rational( - adjusted_weight_fee_difference, - larger_tx_unadjusted_weight_fee.saturating_sub(smaller_tx_unadjusted_weight_fee), - ) -} - -/// Compute fee that will be refunded to the relayer because dispatch of `total_prepaid_nonces` -/// messages has been paid at the source chain. -fn compute_prepaid_messages_refund( - total_prepaid_nonces: MessageNonce, - fee_multiplier: FixedU128, -) -> BalanceOf { - fee_multiplier.saturating_mul_int(WeightToFeeOf::::weight_to_fee( - &C::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN.saturating_mul(total_prepaid_nonces), - )) -} - -#[cfg(test)] -mod tests { - use super::*; - use relay_rialto_client::Rialto; - use relay_rococo_client::Rococo; - use relay_wococo_client::Wococo; - - #[test] - fn prepare_dummy_messages_proof_works() { - const DISPATCH_WEIGHT: Weight = Weight::from_ref_time(1_000_000); - const SIZE: u32 = 1_000; - let dummy_proof = prepare_dummy_messages_proof::(1..=10, DISPATCH_WEIGHT, SIZE); - assert_eq!(dummy_proof.0, DISPATCH_WEIGHT); - assert!( - dummy_proof.1.encode().len() as u32 > SIZE, - "Expected proof size at least {}. Got: {}", - SIZE, - dummy_proof.1.encode().len(), - ); - } - - #[test] - fn convert_target_tokens_to_source_tokens_works() { - assert_eq!( - convert_target_tokens_to_source_tokens::((150, 100).into(), 1_000), - 1_500 - ); - assert_eq!( - convert_target_tokens_to_source_tokens::((50, 100).into(), 1_000), - 500 - ); - assert_eq!( - convert_target_tokens_to_source_tokens::((100, 100).into(), 1_000), - 1_000 - ); - } - - #[test] - fn compute_fee_multiplier_returns_sane_results() { - let multiplier: FixedU128 = - bp_rialto::WeightToFee::weight_to_fee(&Weight::from_ref_time(1)).into(); - - let smaller_weight = 1_000_000; - let smaller_adjusted_weight_fee = multiplier.saturating_mul_int( - WeightToFeeOf::::weight_to_fee(&Weight::from_ref_time(smaller_weight)), - ); - - let larger_weight = smaller_weight + 200_000; - let larger_adjusted_weight_fee = multiplier.saturating_mul_int( - WeightToFeeOf::::weight_to_fee(&Weight::from_ref_time(larger_weight)), - ); - assert_eq!( - compute_fee_multiplier::( - smaller_adjusted_weight_fee, - Weight::from_ref_time(smaller_weight), - larger_adjusted_weight_fee, - Weight::from_ref_time(larger_weight), - ), - multiplier, - ); - } - - #[test] - fn compute_prepaid_messages_refund_returns_sane_results() { - assert!( - compute_prepaid_messages_refund::( - 10, - FixedU128::saturating_from_rational(110, 100), - ) > Rialto::PAY_INBOUND_DISPATCH_FEE_WEIGHT_AT_CHAIN - .saturating_mul(10u64) - .ref_time() as _ - ); - } -} diff --git a/relays/messages/src/lib.rs b/relays/messages/src/lib.rs index c9e460300342f..9c62cee5ee3db 100644 --- a/relays/messages/src/lib.rs +++ b/relays/messages/src/lib.rs @@ -29,9 +29,9 @@ mod metrics; pub mod message_lane; pub mod message_lane_loop; -pub mod relay_strategy; mod message_race_delivery; +mod message_race_limits; mod message_race_loop; mod message_race_receiving; mod message_race_strategy; diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 8d9f3ded08741..6b28dcbaa602c 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -30,7 +30,6 @@ use async_trait::async_trait; use futures::{channel::mpsc::unbounded, future::FutureExt, stream::StreamExt}; use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState, Weight}; -use bp_runtime::messages::DispatchFeePayment; use relay_utils::{ interval, metrics::MetricsParams, process_future_result, relay_loop::Client as RelayClient, retry_backoff, FailedClient, TransactionTracker, @@ -41,12 +40,11 @@ use crate::{ message_race_delivery::run as run_message_delivery_race, message_race_receiving::run as run_message_receiving_race, metrics::MessageLaneLoopMetrics, - relay_strategy::RelayStrategy, }; /// Message lane loop configuration params. #[derive(Debug, Clone)] -pub struct Params { +pub struct Params { /// Id of lane this loop is servicing. pub lane: LaneId, /// Interval at which we ask target node about its updates. @@ -56,22 +54,12 @@ pub struct Params { /// Delay between moments when connection error happens and our reconnect attempt. pub reconnect_delay: Duration, /// Message delivery race parameters. - pub delivery_params: MessageDeliveryParams, -} - -/// Relayer operating mode. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum RelayerMode { - /// The relayer doesn't care about rewards. - Altruistic, - /// The relayer will deliver all messages and confirmations as long as he's not losing any - /// funds. - Rational, + pub delivery_params: MessageDeliveryParams, } /// Message delivery race parameters. #[derive(Debug, Clone)] -pub struct MessageDeliveryParams { +pub struct MessageDeliveryParams { /// Maximal number of unconfirmed relayer entries at the inbound lane. If there's that number /// of entries in the `InboundLaneData::relayers` set, all new messages will be rejected until /// reward payment will be proved (by including outbound lane state to the message delivery @@ -87,8 +75,6 @@ pub struct MessageDeliveryParams { pub max_messages_weight_in_single_batch: Weight, /// Maximal cumulative size of relayed messages in single delivery transaction. pub max_messages_size_in_single_batch: u32, - /// Relay strategy - pub relay_strategy: Strategy, } /// Message details. @@ -100,8 +86,6 @@ pub struct MessageDetails { pub size: u32, /// The relayer reward paid in the source chain tokens. pub reward: SourceChainBalance, - /// Where the fee for dispatching message is paid? - pub dispatch_fee_payment: DispatchFeePayment, } /// Messages details map. @@ -173,9 +157,6 @@ pub trait SourceClient: RelayClient { /// We need given finalized target header on source to continue synchronization. async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

); - - /// Estimate cost of single message confirmation transaction in source chain tokens. - async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance; } /// Target client trait. @@ -221,18 +202,6 @@ pub trait TargetClient: RelayClient { /// We need given finalized source header on target to continue synchronization. async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

); - - /// Estimate cost of messages delivery transaction in source chain tokens. - /// - /// Please keep in mind that the returned cost must be converted to the source chain - /// tokens, even though the transaction fee will be paid in the target chain tokens. - async fn estimate_delivery_transaction_in_source_tokens( - &self, - nonces: RangeInclusive, - total_prepaid_nonces: MessageNonce, - total_dispatch_weight: Weight, - total_size: u32, - ) -> Result; } /// State of the client. @@ -272,8 +241,8 @@ pub fn metrics_prefix(lane: &LaneId) -> String { } /// Run message lane service loop. -pub async fn run( - params: Params, +pub async fn run( + params: Params, source_client: impl SourceClient

, target_client: impl TargetClient

, metrics_params: MetricsParams, @@ -283,11 +252,7 @@ pub async fn run( relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) .with_metrics(metrics_params) - .loop_metric(MessageLaneLoopMetrics::new( - Some(&metrics_prefix::

(¶ms.lane)), - P::SOURCE_NAME, - P::TARGET_NAME, - )?)? + .loop_metric(MessageLaneLoopMetrics::new(Some(&metrics_prefix::

(¶ms.lane)))?)? .expose() .await? .run(metrics_prefix::

(¶ms.lane), move |source_client, target_client, metrics| { @@ -304,13 +269,8 @@ pub async fn run( /// Run one-way message delivery loop until connection with target or source node is lost, or exit /// signal is received. -async fn run_until_connection_lost< - P: MessageLane, - Strategy: RelayStrategy, - SC: SourceClient

, - TC: TargetClient

, ->( - params: Params, +async fn run_until_connection_lost, TC: TargetClient

>( + params: Params, source_client: SC, target_client: TC, metrics_msg: Option, @@ -477,17 +437,12 @@ pub(crate) mod tests { use relay_utils::{HeaderId, MaybeConnectionError, TrackedTransactionStatus}; - use crate::relay_strategy::AltruisticStrategy; - use super::*; pub fn header_id(number: TestSourceHeaderNumber) -> TestSourceHeaderId { HeaderId(number, number) } - pub const CONFIRMATION_TRANSACTION_COST: TestSourceChainBalance = 1; - pub const BASE_MESSAGE_DELIVERY_TRANSACTION_COST: TestSourceChainBalance = 1; - pub type TestSourceChainBalance = u64; pub type TestSourceHeaderId = HeaderId; pub type TestTargetHeaderId = HeaderId; @@ -681,7 +636,6 @@ pub(crate) mod tests { dispatch_weight: Weight::from_ref_time(1), size: 1, reward: 1, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, ) }) @@ -737,10 +691,6 @@ pub(crate) mod tests { (self.tick)(&mut data); (self.post_tick)(&mut data); } - - async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance { - CONFIRMATION_TRANSACTION_COST - } } #[derive(Clone)] @@ -871,20 +821,6 @@ pub(crate) mod tests { (self.tick)(&mut data); (self.post_tick)(&mut data); } - - async fn estimate_delivery_transaction_in_source_tokens( - &self, - nonces: RangeInclusive, - _total_prepaid_nonces: MessageNonce, - total_dispatch_weight: Weight, - total_size: u32, - ) -> Result { - Ok((Weight::from_ref_time(BASE_MESSAGE_DELIVERY_TRANSACTION_COST) * - (nonces.end() - nonces.start() + 1) + - total_dispatch_weight + - Weight::from_ref_time(total_size as u64)) - .ref_time()) - } } fn run_loop_test( @@ -920,7 +856,6 @@ pub(crate) mod tests { max_messages_in_single_batch: 4, max_messages_weight_in_single_batch: Weight::from_ref_time(4), max_messages_size_in_single_batch: 4, - relay_strategy: AltruisticStrategy, }, }, source_client, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 9481e47faf88f..b49a05dac5cf9 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -28,23 +28,23 @@ use crate::{ SourceClient as MessageLaneSourceClient, SourceClientState, TargetClient as MessageLaneTargetClient, TargetClientState, }, + message_race_limits::{MessageRaceLimits, RelayMessagesBatchReference}, message_race_loop::{ MessageRace, NoncesRange, RaceState, RaceStrategy, SourceClient, SourceClientNonces, TargetClient, TargetClientNonces, }, message_race_strategy::BasicStrategy, metrics::MessageLaneLoopMetrics, - relay_strategy::{EnforcementStrategy, RelayMessagesBatchReference, RelayStrategy}, }; /// Run message delivery race. -pub async fn run( +pub async fn run( source_client: impl MessageLaneSourceClient

, source_state_updates: impl FusedStream>, target_client: impl MessageLaneTargetClient

, target_state_updates: impl FusedStream>, metrics_msg: Option, - params: MessageDeliveryParams, + params: MessageDeliveryParams, ) -> Result<(), FailedClient> { crate::message_race_loop::run( MessageDeliveryRaceSource { @@ -59,7 +59,7 @@ pub async fn run( _phantom: Default::default(), }, target_state_updates, - MessageDeliveryStrategy:: { + MessageDeliveryStrategy:: { lane_source_client: source_client, lane_target_client: target_client, max_unrewarded_relayer_entries_at_target: params @@ -68,7 +68,6 @@ pub async fn run( max_messages_in_single_batch: params.max_messages_in_single_batch, max_messages_weight_in_single_batch: params.max_messages_weight_in_single_batch, max_messages_size_in_single_batch: params.max_messages_size_in_single_batch, - relay_strategy: params.relay_strategy, latest_confirmed_nonces_at_source: VecDeque::new(), target_nonces: None, strategy: BasicStrategy::new(), @@ -231,7 +230,7 @@ struct DeliveryRaceTargetNoncesData { } /// Messages delivery strategy. -struct MessageDeliveryStrategy { +struct MessageDeliveryStrategy { /// The client that is connected to the message lane source node. lane_source_client: SC, /// The client that is connected to the message lane target node. @@ -246,8 +245,6 @@ struct MessageDeliveryStrategy max_messages_weight_in_single_batch: Weight, /// Maximal messages size in the single delivery transaction. max_messages_size_in_single_batch: u32, - /// Relayer operating mode. - relay_strategy: Strategy, /// Latest confirmed nonces at the source client + the header id where we have first met this /// nonce. latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, @@ -268,9 +265,7 @@ type MessageDeliveryStrategyBase

= BasicStrategy<

::MessagesProof, >; -impl std::fmt::Debug - for MessageDeliveryStrategy -{ +impl std::fmt::Debug for MessageDeliveryStrategy { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { fmt.debug_struct("MessageDeliveryStrategy") .field( @@ -288,7 +283,7 @@ impl std::fmt::Debug } } -impl MessageDeliveryStrategy { +impl MessageDeliveryStrategy { /// Returns total weight of all undelivered messages. fn total_queued_dispatch_weight(&self) -> Weight { self.strategy @@ -300,9 +295,8 @@ impl MessageDeliveryStrategy - RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> - for MessageDeliveryStrategy +impl RaceStrategy, TargetHeaderIdOf

, P::MessagesProof> + for MessageDeliveryStrategy where P: MessageLane, SC: MessageLaneSourceClient

, @@ -524,8 +518,7 @@ where metrics: self.metrics_msg.clone(), }; - let mut strategy = EnforcementStrategy::new(self.relay_strategy.clone()); - let range_end = strategy.decide(reference).await?; + let range_end = MessageRaceLimits::decide(reference).await?; let range_begin = source_queue[0].1.begin(); let selected_nonces = range_begin..=range_end; @@ -562,38 +555,27 @@ impl NoncesRange for MessageDetailsMap; type TestStrategy = - MessageDeliveryStrategy; + MessageDeliveryStrategy; fn source_nonces( new_nonces: RangeInclusive, confirmed_nonce: MessageNonce, reward: TestSourceChainBalance, - dispatch_fee_payment: DispatchFeePayment, ) -> SourceClientNonces> { SourceClientNonces { new_nonces: new_nonces @@ -605,7 +587,6 @@ mod tests { dispatch_weight: DEFAULT_DISPATCH_WEIGHT, size: DEFAULT_SIZE, reward, - dispatch_fee_payment, }, ) }) @@ -648,13 +629,11 @@ mod tests { }, }), strategy: BasicStrategy::new(), - relay_strategy: MixStrategy::new(RelayerMode::Altruistic), }; - race_strategy.strategy.source_nonces_updated( - header_id(1), - source_nonces(20..=23, 19, DEFAULT_REWARD, DispatchFeePayment::AtSourceChain), - ); + race_strategy + .strategy + .source_nonces_updated(header_id(1), source_nonces(20..=23, 19, 0)); let target_nonces = TargetClientNonces { latest_nonce: 19, nonces_data: () }; race_strategy @@ -687,7 +666,6 @@ mod tests { dispatch_weight: Weight::from_ref_time(idx), size: idx as _, reward: idx as _, - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, ) }) @@ -978,83 +956,6 @@ mod tests { assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2))); } - #[async_std::test] - async fn rational_relayer_is_delivering_messages_if_cost_is_equal_to_reward() { - let (state, mut strategy) = prepare_strategy(); - strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); - - // so now we have: - // - 20..=23 with reward = cost - // => strategy shall select all 20..=23 - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - - #[async_std::test] - async fn rational_relayer_is_not_delivering_messages_if_cost_is_larger_than_reward() { - let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces( - 24..=25, - 19, - DEFAULT_REWARD - BASE_MESSAGE_DELIVERY_TRANSACTION_COST, - DispatchFeePayment::AtSourceChain, - ); - strategy.strategy.source_nonces_updated(header_id(2), nonces); - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); - - // so now we have: - // - 20..=23 with reward = cost - // - 24..=25 with reward less than cost - // => strategy shall only select 20..=23 - assert_eq!( - strategy.select_nonces_to_deliver(state).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - - #[async_std::test] - async fn rational_relayer_is_delivering_unpaid_messages() { - async fn test_with_dispatch_fee_payment( - dispatch_fee_payment: DispatchFeePayment, - ) -> Option<(RangeInclusive, MessageProofParameters)> { - let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces( - 24..=24, - 19, - DEFAULT_REWARD - DEFAULT_DISPATCH_WEIGHT.ref_time(), - dispatch_fee_payment, - ); - strategy.strategy.source_nonces_updated(header_id(2), nonces); - state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - strategy.max_unrewarded_relayer_entries_at_target = 100; - strategy.max_unconfirmed_nonces_at_target = 100; - strategy.max_messages_in_single_batch = 100; - strategy.max_messages_weight_in_single_batch = Weight::from_ref_time(100); - strategy.max_messages_size_in_single_batch = 100; - strategy.relay_strategy = MixStrategy::new(RelayerMode::Rational); - - // so now we have: - // - 20..=23 with reward = cost - // - 24..=24 with reward less than cost, but we're deducting `DEFAULT_DISPATCH_WEIGHT` - // from the cost, so it should be fine; - // => when MSG#24 fee is paid at the target chain, strategy shall select all 20..=24 - // => when MSG#25 fee is paid at the source chain, strategy shall only select 20..=23 - strategy.select_nonces_to_deliver(state).await - } - - assert_eq!( - test_with_dispatch_fee_payment(DispatchFeePayment::AtTargetChain).await, - Some(((20..=24), proof_parameters(false, 5))) - ); - assert_eq!( - test_with_dispatch_fee_payment(DispatchFeePayment::AtSourceChain).await, - Some(((20..=23), proof_parameters(false, 4))) - ); - } - #[async_std::test] async fn relayer_uses_flattened_view_of_the_source_queue_to_select_nonces() { // Real scenario that has happened on test deployments: @@ -1066,7 +967,7 @@ mod tests { // This was happening because selector (`select_nonces_for_delivery_transaction`) has been // called for every `source_queue` entry separately without preserving any context. let (mut state, mut strategy) = prepare_strategy(); - let nonces = source_nonces(24..=25, 19, DEFAULT_REWARD, DispatchFeePayment::AtSourceChain); + let nonces = source_nonces(24..=25, 19, 0); strategy.strategy.source_nonces_updated(header_id(2), nonces); strategy.max_unrewarded_relayer_entries_at_target = 100; strategy.max_unconfirmed_nonces_at_target = 100; diff --git a/relays/messages/src/relay_strategy/enforcement_strategy.rs b/relays/messages/src/message_race_limits.rs similarity index 56% rename from relays/messages/src/relay_strategy/enforcement_strategy.rs rename to relays/messages/src/message_race_limits.rs index 59e1b445bdcd5..a28d9ba63da96 100644 --- a/relays/messages/src/relay_strategy/enforcement_strategy.rs +++ b/relays/messages/src/message_race_limits.rs @@ -17,43 +17,88 @@ //! enforcement strategy use num_traits::Zero; +use std::ops::Range; use bp_messages::{MessageNonce, Weight}; -use bp_runtime::messages::DispatchFeePayment; use crate::{ message_lane::MessageLane, message_lane_loop::{ - MessageDetails, SourceClient as MessageLaneSourceClient, + MessageDetails, MessageDetailsMap, SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, }, message_race_loop::NoncesRange, - relay_strategy::{RelayMessagesBatchReference, RelayReference, RelayStrategy}, + message_race_strategy::SourceRangesQueue, + metrics::MessageLaneLoopMetrics, }; -/// Do hard check and run soft check strategy -#[derive(Clone)] -pub struct EnforcementStrategy { - strategy: Strategy, +/// Reference data for participating in relay +pub struct RelayReference< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, +> { + /// The client that is connected to the message lane source node. + pub lane_source_client: SourceClient, + /// The client that is connected to the message lane target node. + pub lane_target_client: TargetClient, + /// Metrics reference. + pub metrics: Option, + /// Messages size summary + pub selected_size: u32, + + /// Hard check begin nonce + pub hard_selected_begin_nonce: MessageNonce, + + /// Index by all ready nonces + pub index: usize, + /// Current nonce + pub nonce: MessageNonce, + /// Current nonce details + pub details: MessageDetails, } -impl EnforcementStrategy { - pub fn new(strategy: Strategy) -> Self { - Self { strategy } - } +/// Relay reference data +pub struct RelayMessagesBatchReference< + P: MessageLane, + SourceClient: MessageLaneSourceClient

, + TargetClient: MessageLaneTargetClient

, +> { + /// Maximal number of relayed messages in single delivery transaction. + pub max_messages_in_this_batch: MessageNonce, + /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. + pub max_messages_weight_in_single_batch: Weight, + /// Maximal cumulative size of relayed messages in single delivery transaction. + pub max_messages_size_in_single_batch: u32, + /// The client that is connected to the message lane source node. + pub lane_source_client: SourceClient, + /// The client that is connected to the message lane target node. + pub lane_target_client: TargetClient, + /// Metrics reference. + pub metrics: Option, + /// Source queue. + pub nonces_queue: SourceRangesQueue< + P::SourceHeaderHash, + P::SourceHeaderNumber, + MessageDetailsMap, + >, + /// Source queue range + pub nonces_queue_range: Range, } -impl EnforcementStrategy { +/// Limits of the message race transactions. +#[derive(Clone)] +pub struct MessageRaceLimits; + +impl MessageRaceLimits { pub async fn decide< P: MessageLane, SourceClient: MessageLaneSourceClient

, TargetClient: MessageLaneTargetClient

, >( - &mut self, reference: RelayMessagesBatchReference, ) -> Option { let mut hard_selected_count = 0; - let mut soft_selected_count = 0; let mut selected_weight = Weight::zero(); let mut selected_count: MessageNonce = 0; @@ -67,17 +112,9 @@ impl EnforcementStrategy { lane_target_client: reference.lane_target_client.clone(), metrics: reference.metrics.clone(), - selected_reward: P::SourceChainBalance::zero(), - selected_cost: P::SourceChainBalance::zero(), selected_size: 0, - total_reward: P::SourceChainBalance::zero(), - total_confirmations_cost: P::SourceChainBalance::zero(), - total_cost: P::SourceChainBalance::zero(), - hard_selected_begin_nonce, - selected_prepaid_nonces: 0, - selected_unpaid_weight: Weight::zero(), index: 0, nonce: 0, @@ -85,7 +122,6 @@ impl EnforcementStrategy { dispatch_weight: Weight::zero(), size: 0, reward: P::SourceChainBalance::zero(), - dispatch_fee_payment: DispatchFeePayment::AtSourceChain, }, }; @@ -148,74 +184,14 @@ impl EnforcementStrategy { } relay_reference.selected_size = new_selected_size; - // If dispatch fee has been paid at the source chain, it means that it is **relayer** - // who's paying for dispatch at the target chain AND reward must cover this dispatch - // fee. - // - // If dispatch fee is paid at the target chain, it means that it'll be withdrawn from - // the dispatch origin account AND reward is not covering this fee. - // - // So in the latter case we're not adding the dispatch weight to the delivery - // transaction weight. - let mut new_selected_prepaid_nonces = relay_reference.selected_prepaid_nonces; - let new_selected_unpaid_weight = match details.dispatch_fee_payment { - DispatchFeePayment::AtSourceChain => { - new_selected_prepaid_nonces += 1; - relay_reference.selected_unpaid_weight.saturating_add(details.dispatch_weight) - }, - DispatchFeePayment::AtTargetChain => relay_reference.selected_unpaid_weight, - }; - relay_reference.selected_prepaid_nonces = new_selected_prepaid_nonces; - relay_reference.selected_unpaid_weight = new_selected_unpaid_weight; - - // now the message has passed all 'strong' checks, and we CAN deliver it. But do we WANT - // to deliver it? It depends on the relayer strategy. - if self.strategy.decide(&mut relay_reference).await { - soft_selected_count = index + 1; - } - hard_selected_count = index + 1; selected_weight = new_selected_weight; selected_count = new_selected_count; } - if hard_selected_count != soft_selected_count { - let hard_selected_end_nonce = - hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; - let soft_selected_begin_nonce = hard_selected_begin_nonce; - let soft_selected_end_nonce = - soft_selected_begin_nonce + soft_selected_count as MessageNonce - 1; - log::warn!( - target: "bridge", - "Relayer may deliver nonces [{:?}; {:?}], but because of its strategy it has selected \ - nonces [{:?}; {:?}].", - hard_selected_begin_nonce, - hard_selected_end_nonce, - soft_selected_begin_nonce, - soft_selected_end_nonce, - ); - - hard_selected_count = soft_selected_count; - } - if hard_selected_count != 0 { - if relay_reference.selected_reward != P::SourceChainBalance::zero() && - relay_reference.selected_cost != P::SourceChainBalance::zero() - { - log::trace!( - target: "bridge", - "Expected reward from delivering nonces [{:?}; {:?}] is: {:?} - {:?} = {:?}", - hard_selected_begin_nonce, - hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1, - &relay_reference.selected_reward, - &relay_reference.selected_cost, - relay_reference.selected_reward - relay_reference.selected_cost, - ); - } - let selected_max_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; - self.strategy.on_final_decision(&relay_reference); Some(selected_max_nonce) } else { None diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index f5cc8831c0286..4decb7e092e71 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -24,7 +24,7 @@ use crate::{ use bp_messages::MessageNonce; use finality_relay::SyncLoopMetrics; use relay_utils::metrics::{ - metric_name, register, Counter, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, + metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, }; /// Message lane relay metrics. @@ -39,17 +39,11 @@ pub struct MessageLaneLoopMetrics { /// Lane state nonces: "source_latest_generated", "source_latest_confirmed", /// "target_latest_received", "target_latest_confirmed". lane_state_nonces: GaugeVec, - /// Count of unprofitable message delivery transactions that we have submitted so far. - unprofitable_delivery_transactions: Counter, } impl MessageLaneLoopMetrics { /// Create and register messages loop metrics. - pub fn new( - prefix: Option<&str>, - source_name: &str, - target_name: &str, - ) -> Result { + pub fn new(prefix: Option<&str>) -> Result { Ok(MessageLaneLoopMetrics { source_to_target_finality_metrics: SyncLoopMetrics::new( prefix, @@ -65,13 +59,6 @@ impl MessageLaneLoopMetrics { Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"), &["type"], )?, - unprofitable_delivery_transactions: Counter::new( - metric_name(prefix, "unprofitable_delivery_transactions"), - format!( - "Count of unprofitable message delivery transactions from {} to {}", - source_name, target_name - ), - )?, }) } @@ -140,11 +127,6 @@ impl MessageLaneLoopMetrics { .with_label_values(&["target_latest_confirmed"]) .set(target_latest_confirmed_nonce); } - - /// Note unprofitable delivery transaction. - pub fn note_unprofitable_delivery_transactions(&self) { - self.unprofitable_delivery_transactions.inc() - } } impl Metric for MessageLaneLoopMetrics { @@ -152,7 +134,6 @@ impl Metric for MessageLaneLoopMetrics { self.source_to_target_finality_metrics.register(registry)?; self.target_to_source_finality_metrics.register(registry)?; register(self.lane_state_nonces.clone(), registry)?; - register(self.unprofitable_delivery_transactions.clone(), registry)?; Ok(()) } } diff --git a/relays/messages/src/relay_strategy/altruistic_strategy.rs b/relays/messages/src/relay_strategy/altruistic_strategy.rs deleted file mode 100644 index 7e00678e1317f..0000000000000 --- a/relays/messages/src/relay_strategy/altruistic_strategy.rs +++ /dev/null @@ -1,81 +0,0 @@ -// 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 . - -//! Altruistic relay strategy - -use async_trait::async_trait; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, - }, - relay_strategy::{RelayReference, RelayStrategy}, -}; - -/// The relayer doesn't care about rewards. -#[derive(Clone)] -pub struct AltruisticStrategy; - -#[async_trait] -impl RelayStrategy for AltruisticStrategy { - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool { - // We don't care about costs and rewards, but we want to report unprofitable transactions. - if let Err(e) = reference.update_cost_and_reward().await { - log::debug!( - target: "bridge", - "Failed to update transaction cost and reward: {:?}. \ - The `unprofitable_delivery_transactions` metric will be inaccurate", - e, - ); - } - - true - } - - fn on_final_decision< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &self, - reference: &RelayReference, - ) { - if let Some(ref metrics) = reference.metrics { - if !reference.is_profitable() { - log::debug!( - target: "bridge", - "The relayer has submitted unprofitable {} -> {} message delivery transaction \ - with {} messages: total cost = {:?}, total reward = {:?}", - P::SOURCE_NAME, - P::TARGET_NAME, - reference.index + 1, - reference.total_cost, - reference.total_reward, - ); - - metrics.note_unprofitable_delivery_transactions(); - } - } - } -} diff --git a/relays/messages/src/relay_strategy/mix_strategy.rs b/relays/messages/src/relay_strategy/mix_strategy.rs deleted file mode 100644 index 331f77b012d22..0000000000000 --- a/relays/messages/src/relay_strategy/mix_strategy.rs +++ /dev/null @@ -1,72 +0,0 @@ -// 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 . - -//! Adapter for using `enum RelayerMode` in a context which requires `RelayStrategy`. - -use async_trait::async_trait; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - RelayerMode, SourceClient as MessageLaneSourceClient, - TargetClient as MessageLaneTargetClient, - }, - relay_strategy::{AltruisticStrategy, RationalStrategy, RelayReference, RelayStrategy}, -}; - -/// `RelayerMode` adapter. -#[derive(Clone)] -pub struct MixStrategy { - relayer_mode: RelayerMode, -} - -impl MixStrategy { - /// Create mix strategy instance - pub fn new(relayer_mode: RelayerMode) -> Self { - Self { relayer_mode } - } -} - -#[async_trait] -impl RelayStrategy for MixStrategy { - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool { - match self.relayer_mode { - RelayerMode::Altruistic => AltruisticStrategy.decide(reference).await, - RelayerMode::Rational => RationalStrategy.decide(reference).await, - } - } - - fn on_final_decision< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &self, - reference: &RelayReference, - ) { - match self.relayer_mode { - RelayerMode::Altruistic => AltruisticStrategy.on_final_decision(reference), - RelayerMode::Rational => RationalStrategy.on_final_decision(reference), - } - } -} diff --git a/relays/messages/src/relay_strategy/mod.rs b/relays/messages/src/relay_strategy/mod.rs deleted file mode 100644 index aa28e63582fd7..0000000000000 --- a/relays/messages/src/relay_strategy/mod.rs +++ /dev/null @@ -1,224 +0,0 @@ -// 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 . - -//! Relayer strategy - -use async_trait::async_trait; -use bp_messages::{MessageNonce, Weight}; -use sp_arithmetic::traits::Saturating; -use std::ops::Range; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - MessageDetails, MessageDetailsMap, SourceClient as MessageLaneSourceClient, - TargetClient as MessageLaneTargetClient, - }, - message_race_strategy::SourceRangesQueue, - metrics::MessageLaneLoopMetrics, -}; - -pub(crate) use self::enforcement_strategy::*; -pub use self::{altruistic_strategy::*, mix_strategy::*, rational_strategy::*}; - -mod altruistic_strategy; -mod enforcement_strategy; -mod mix_strategy; -mod rational_strategy; - -/// Relayer strategy trait -#[async_trait] -pub trait RelayStrategy: 'static + Clone + Send + Sync { - /// The relayer decide how to process nonce by reference. - /// From given set of source nonces, that are ready to be delivered, select nonces - /// to fit into single delivery transaction. - /// - /// The function returns last nonce that must be delivered to the target chain. - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool; - - /// Notification that the following maximal nonce has been selected for the delivery. - fn on_final_decision< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &self, - reference: &RelayReference, - ); -} - -/// Total cost of mesage delivery and confirmation. -struct MessagesDeliveryCost { - /// Cost of message delivery transaction. - pub delivery_transaction_cost: SourceChainBalance, - /// Cost of confirmation delivery transaction. - pub confirmation_transaction_cost: SourceChainBalance, -} - -/// Reference data for participating in relay -pub struct RelayReference< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, -> { - /// The client that is connected to the message lane source node. - pub lane_source_client: SourceClient, - /// The client that is connected to the message lane target node. - pub lane_target_client: TargetClient, - /// Metrics reference. - pub metrics: Option, - /// Current block reward summary - pub selected_reward: P::SourceChainBalance, - /// Current block cost summary - pub selected_cost: P::SourceChainBalance, - /// Messages size summary - pub selected_size: u32, - - /// Current block reward summary - pub total_reward: P::SourceChainBalance, - /// All confirmations cost - pub total_confirmations_cost: P::SourceChainBalance, - /// Current block cost summary - pub total_cost: P::SourceChainBalance, - - /// Hard check begin nonce - pub hard_selected_begin_nonce: MessageNonce, - /// Count prepaid nonces - pub selected_prepaid_nonces: MessageNonce, - /// Unpaid nonces weight summary - pub selected_unpaid_weight: Weight, - - /// Index by all ready nonces - pub index: usize, - /// Current nonce - pub nonce: MessageNonce, - /// Current nonce details - pub details: MessageDetails, -} - -impl< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - > RelayReference -{ - /// Returns whether the current `RelayReference` is profitable. - pub fn is_profitable(&self) -> bool { - self.total_reward >= self.total_cost - } - - async fn estimate_messages_delivery_cost( - &self, - ) -> Result, TargetClient::Error> { - // technically, multiple confirmations will be delivered in a single transaction, - // meaning less loses for relayer. But here we don't know the final relayer yet, so - // we're adding a separate transaction for every message. Normally, this cost is covered - // by the message sender. Probably reconsider this? - let confirmation_transaction_cost = - self.lane_source_client.estimate_confirmation_transaction().await; - - let delivery_transaction_cost = self - .lane_target_client - .estimate_delivery_transaction_in_source_tokens( - self.hard_selected_begin_nonce..= - (self.hard_selected_begin_nonce + self.index as MessageNonce), - self.selected_prepaid_nonces, - self.selected_unpaid_weight, - self.selected_size, - ) - .await?; - - Ok(MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost }) - } - - async fn update_cost_and_reward(&mut self) -> Result<(), TargetClient::Error> { - let prev_is_profitable = self.is_profitable(); - let prev_total_cost = self.total_cost; - let prev_total_reward = self.total_reward; - - let MessagesDeliveryCost { confirmation_transaction_cost, delivery_transaction_cost } = - self.estimate_messages_delivery_cost().await?; - self.total_confirmations_cost = - self.total_confirmations_cost.saturating_add(confirmation_transaction_cost); - self.total_reward = self.total_reward.saturating_add(self.details.reward); - self.total_cost = self.total_confirmations_cost.saturating_add(delivery_transaction_cost); - - if prev_is_profitable && !self.is_profitable() { - // if it is the first message that makes reward less than cost, let's log it - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it larger than \ - total reward {:?}->{:?}", - self.nonce, - self.details.reward, - prev_total_cost, - self.total_cost, - prev_total_reward, - self.total_reward, - ); - } else if !prev_is_profitable && self.is_profitable() { - // if this message makes batch profitable again, let's log it - log::debug!( - target: "bridge", - "Message with nonce {} (reward = {:?}) changes total cost {:?}->{:?} and makes it less than or \ - equal to the total reward {:?}->{:?} (again)", - self.nonce, - self.details.reward, - prev_total_cost, - self.total_cost, - prev_total_reward, - self.total_reward, - ); - } - - Ok(()) - } -} - -/// Relay reference data -pub struct RelayMessagesBatchReference< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, -> { - /// Maximal number of relayed messages in single delivery transaction. - pub max_messages_in_this_batch: MessageNonce, - /// Maximal cumulative dispatch weight of relayed messages in single delivery transaction. - pub max_messages_weight_in_single_batch: Weight, - /// Maximal cumulative size of relayed messages in single delivery transaction. - pub max_messages_size_in_single_batch: u32, - /// The client that is connected to the message lane source node. - pub lane_source_client: SourceClient, - /// The client that is connected to the message lane target node. - pub lane_target_client: TargetClient, - /// Metrics reference. - pub metrics: Option, - /// Source queue. - pub nonces_queue: SourceRangesQueue< - P::SourceHeaderHash, - P::SourceHeaderNumber, - MessageDetailsMap, - >, - /// Source queue range - pub nonces_queue_range: Range, -} diff --git a/relays/messages/src/relay_strategy/rational_strategy.rs b/relays/messages/src/relay_strategy/rational_strategy.rs deleted file mode 100644 index 1791670fa45a8..0000000000000 --- a/relays/messages/src/relay_strategy/rational_strategy.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Rational relay strategy - -use async_trait::async_trait; - -use crate::{ - message_lane::MessageLane, - message_lane_loop::{ - SourceClient as MessageLaneSourceClient, TargetClient as MessageLaneTargetClient, - }, - relay_strategy::{RelayReference, RelayStrategy}, -}; - -/// The relayer will deliver all messages and confirmations as long as he's not losing any -/// funds. -#[derive(Clone)] -pub struct RationalStrategy; - -#[async_trait] -impl RelayStrategy for RationalStrategy { - async fn decide< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &mut self, - reference: &mut RelayReference, - ) -> bool { - if let Err(e) = reference.update_cost_and_reward().await { - log::debug!( - target: "bridge", - "Failed to update transaction cost and reward: {:?}. No nonces selected for delivery", - e, - ); - - return false - } - - // Rational relayer never wants to lose his funds. - if reference.is_profitable() { - reference.selected_reward = reference.total_reward; - reference.selected_cost = reference.total_cost; - return true - } - - false - } - - fn on_final_decision< - P: MessageLane, - SourceClient: MessageLaneSourceClient

, - TargetClient: MessageLaneTargetClient

, - >( - &self, - _reference: &RelayReference, - ) { - // rational relayer would never submit unprofitable transactions, so we don't need to do - // anything here - } -} From eb4d859ffcd8200af8adbb1fb419408885137f1c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 18 Nov 2022 16:15:25 +0300 Subject: [PATCH 0809/1210] Remove callbacks from the messages pallet (#1649) * remove callbacks * clippy * fmt --- bin/millau/runtime/src/lib.rs | 4 - bin/millau/runtime/src/rialto_messages.rs | 3 +- bin/rialto-parachain/runtime/src/lib.rs | 2 - bin/rialto/runtime/src/lib.rs | 2 - bin/rialto/runtime/src/millau_messages.rs | 3 +- modules/messages/src/lib.rs | 205 +--------------------- modules/messages/src/mock.rs | 89 +--------- modules/messages/src/weights_ext.rs | 20 +-- modules/relayers/src/mock.rs | 2 - primitives/messages/src/source_chain.rs | 45 +---- 10 files changed, 13 insertions(+), 362 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 095250a55861a..49cd16834bb76 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -494,8 +494,6 @@ impl pallet_bridge_messages::Config for Runtime { Runtime, WithRialtoMessagesInstance, >; - type OnMessageAccepted = (); - type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; @@ -526,8 +524,6 @@ impl pallet_bridge_messages::Config for Run Runtime, WithRialtoParachainMessagesInstance, >; - type OnMessageAccepted = (); - type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index c0868298a3276..5d7b189db2af9 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -177,7 +177,7 @@ impl SourceHeaderChain for Rialto { #[cfg(test)] mod tests { use super::*; - use crate::{DbWeight, Runtime, WithRialtoMessagesInstance}; + use crate::{Runtime, WithRialtoMessagesInstance}; use bp_runtime::Chain; use bridge_runtime_common::{ @@ -218,7 +218,6 @@ mod tests { max_incoming_inbound_lane_data_proof_size, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - DbWeight::get(), ); } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index c5b9e50d067c0..7487e68f8f953 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -579,8 +579,6 @@ impl pallet_bridge_messages::Config for Runtime { Runtime, WithMillauMessagesInstance, >; - type OnMessageAccepted = (); - type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 3ce0b650dc5f1..378a471325d66 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -467,8 +467,6 @@ impl pallet_bridge_messages::Config for Runtime { Runtime, WithMillauMessagesInstance, >; - type OnMessageAccepted = (); - type OnDeliveryConfirmed = (); type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 9eb6c82f3678d..98030ac3ee52e 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -175,7 +175,7 @@ impl SourceHeaderChain for Millau { #[cfg(test)] mod tests { use super::*; - use crate::{DbWeight, MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; + use crate::{MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; use bp_runtime::Chain; use bridge_runtime_common::{ assert_complete_bridge_types, @@ -214,7 +214,6 @@ mod tests { max_incoming_inbound_lane_data_proof_size, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - DbWeight::get(), ); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index d6a5ffe453c0b..8324aa75bc833 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -52,8 +52,8 @@ use crate::{ use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, RelayersRewards, SendMessageArtifacts, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, + SendMessageArtifacts, TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -65,7 +65,6 @@ use bp_messages::{ use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; -use num_traits::Zero; use sp_std::{ cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, prelude::*, @@ -159,10 +158,6 @@ pub mod pallet { Self::RuntimeOrigin, Self::AccountId, >; - /// Handler for accepted messages. - type OnMessageAccepted: OnMessageAccepted; - /// Handler for delivered messages. - type OnDeliveryConfirmed: OnDeliveryConfirmed; // Types that are used by inbound_lane (on target chain). @@ -362,33 +357,14 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::receive_messages_delivery_proof_weight( proof, relayers_state, - T::DbWeight::get(), ))] pub fn receive_messages_delivery_proof( origin: OriginFor, proof: MessagesDeliveryProofOf, relayers_state: UnrewardedRelayersState, - ) -> DispatchResultWithPostInfo { + ) -> DispatchResult { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; - // why do we need to know the weight of this (`receive_messages_delivery_proof`) call? - // Because we may want to return some funds for messages that are not processed by the - // delivery callback, or if their actual processing weight is less than accounted by - // weight formula. So to refund relayer, we need to: - // - // ActualWeight = DeclaredWeight - UnspentCallbackWeight - // - // The DeclaredWeight is exactly what's computed here. Unfortunately it is impossible - // to get pre-computed value (and it has been already computed by the executive). - let single_message_callback_overhead = - T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); - let declared_weight = T::WeightInfo::receive_messages_delivery_proof_weight( - &proof, - &relayers_state, - T::DbWeight::get(), - ); - let mut actual_weight = declared_weight; - let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof) .map_err(|err| { @@ -453,39 +429,6 @@ pub mod pallet { }; if let Some(confirmed_messages) = confirmed_messages { - // handle messages delivery confirmation - let preliminary_callback_overhead = - single_message_callback_overhead.saturating_mul(relayers_state.total_messages); - let actual_callback_weight = - T::OnDeliveryConfirmed::on_messages_delivered(&lane_id, &confirmed_messages); - match preliminary_callback_overhead.checked_sub(&actual_callback_weight) { - Some(difference) if difference.is_zero() => (), - Some(difference) => { - log::trace!( - target: LOG_TARGET, - "T::OnDeliveryConfirmed callback has spent less weight than expected. Refunding: \ - {} - {} = {}", - preliminary_callback_overhead, - actual_callback_weight, - difference, - ); - actual_weight = actual_weight.saturating_sub(difference); - }, - None => { - debug_assert!( - false, - "T::OnDeliveryConfirmed callback consumed too much weight." - ); - log::error!( - target: LOG_TARGET, - "T::OnDeliveryConfirmed callback has spent more weight that it is allowed to: \ - {} vs {}", - preliminary_callback_overhead, - actual_callback_weight, - ); - }, - } - // emit 'delivered' event let received_range = confirmed_messages.begin..=confirmed_messages.end; Self::deposit_event(Event::MessagesDelivered { @@ -509,7 +452,7 @@ pub mod pallet { lane_id, ); - Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) + Ok(()) } } @@ -710,38 +653,6 @@ fn send_message, I: 'static>( ); let nonce = lane.send_message(encoded_payload); - // Guaranteed to be called outside only when the message is accepted. - // We assume that the maximum weight call back used is `single_message_callback_overhead`, so do - // not perform complex db operation in callback. If you want to, put these magic logic in - // outside pallet and control the weight there. - let single_message_callback_overhead = - T::WeightInfo::single_message_callback_overhead(T::DbWeight::get()); - let actual_callback_weight = T::OnMessageAccepted::on_messages_accepted(&lane_id, &nonce); - match single_message_callback_overhead.checked_sub(&actual_callback_weight) { - Some(difference) if difference.is_zero() => (), - Some(difference) => { - log::trace!( - target: LOG_TARGET, - "T::OnMessageAccepted callback has spent less weight than expected. Refunding: \ - {} - {} = {}", - single_message_callback_overhead, - actual_callback_weight, - difference, - ); - actual_weight = actual_weight.saturating_sub(difference); - }, - None => { - debug_assert!(false, "T::OnMessageAccepted callback consumed too much weight."); - log::error!( - target: LOG_TARGET, - "T::OnMessageAccepted callback has spent more weight that it is allowed to: \ - {} vs {}", - single_message_callback_overhead, - actual_callback_weight, - ); - }, - } - // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages // the cost of pruning every message is roughly single db write // => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned @@ -942,8 +853,7 @@ mod tests { use crate::mock::{ message, message_payload, run_test, unrewarded_relayer, RuntimeEvent as TestEvent, RuntimeOrigin, TestMessageDeliveryAndDispatchPayment, TestMessagesDeliveryProof, - TestMessagesProof, TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2, - TestOnMessageAccepted, TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, + TestMessagesProof, TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B, }; @@ -1674,12 +1584,9 @@ mod tests { TEST_LANE_ID, InboundLaneData { last_confirmed_nonce: 0, - relayers: vec![UnrewardedRelayer { - relayer: 0, - messages: delivered_message_3.clone(), - }] - .into_iter() - .collect(), + relayers: vec![UnrewardedRelayer { relayer: 0, messages: delivered_message_3 }] + .into_iter() + .collect(), }, )); @@ -1705,82 +1612,6 @@ mod tests { ..Default::default() }, )); - - // ensure that both callbacks have been called twice: for 1+2, then for 3 - TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); - TestOnDeliveryConfirmed1::ensure_called(&TEST_LANE_ID, &delivered_message_3); - TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_messages_1_and_2); - TestOnDeliveryConfirmed2::ensure_called(&TEST_LANE_ID, &delivered_message_3); - }); - } - - fn confirm_3_messages_delivery() -> (Weight, Weight) { - send_regular_message(); - send_regular_message(); - send_regular_message(); - - let proof = TestMessagesDeliveryProof(Ok(( - TEST_LANE_ID, - InboundLaneData { - last_confirmed_nonce: 0, - relayers: vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)].into_iter().collect(), - }, - ))); - let relayers_state = UnrewardedRelayersState { - unrewarded_relayer_entries: 1, - total_messages: 3, - last_delivered_nonce: 3, - ..Default::default() - }; - let pre_dispatch_weight = - ::WeightInfo::receive_messages_delivery_proof_weight( - &proof, - &relayers_state, - crate::mock::DbWeight::get(), - ); - let post_dispatch_weight = Pallet::::receive_messages_delivery_proof( - RuntimeOrigin::signed(1), - proof, - relayers_state, - ) - .expect("confirmation has failed") - .actual_weight - .expect("receive_messages_delivery_proof always returns Some"); - (pre_dispatch_weight, post_dispatch_weight) - } - - #[test] - fn receive_messages_delivery_proof_refunds_zero_weight() { - run_test(|| { - let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery(); - assert_eq!(pre_dispatch_weight, post_dispatch_weight); - }); - } - - #[test] - fn receive_messages_delivery_proof_refunds_non_zero_weight() { - run_test(|| { - TestOnDeliveryConfirmed1::set_consumed_weight_per_message( - crate::mock::DbWeight::get().writes(1), - ); - - let (pre_dispatch_weight, post_dispatch_weight) = confirm_3_messages_delivery(); - assert_eq!( - pre_dispatch_weight.saturating_sub(post_dispatch_weight), - crate::mock::DbWeight::get().reads(1) * 3 - ); - }); - } - - #[test] - #[should_panic] - #[cfg(debug_assertions)] - fn receive_messages_panics_in_debug_mode_if_callback_is_wrong() { - run_test(|| { - TestOnDeliveryConfirmed1::set_consumed_weight_per_message( - crate::mock::DbWeight::get().reads_writes(2, 2), - ); - confirm_3_messages_delivery() }); } @@ -1811,26 +1642,6 @@ mod tests { }); } - #[test] - fn message_accepted_callbacks_are_called() { - run_test(|| { - send_regular_message(); - TestOnMessageAccepted::ensure_called(&TEST_LANE_ID, &1); - }); - } - - #[test] - #[should_panic] - #[cfg(debug_assertions)] - fn message_accepted_panics_in_debug_mode_if_callback_is_wrong() { - run_test(|| { - TestOnMessageAccepted::set_consumed_weight_per_message( - crate::mock::DbWeight::get().reads_writes(2, 2), - ); - send_regular_message(); - }); - } - #[test] fn storage_keys_computed_properly() { assert_eq!( diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index afda37ba8be7b..5d58883d0a6f9 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -21,10 +21,7 @@ use crate::{calc_relayers_rewards, Config}; use bitvec::prelude::*; use bp_messages::{ - source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnDeliveryConfirmed, - OnMessageAccepted, TargetHeaderChain, - }, + source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{ DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -162,8 +159,6 @@ impl Config for TestRuntime { type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; - type OnMessageAccepted = TestOnMessageAccepted; - type OnDeliveryConfirmed = (TestOnDeliveryConfirmed1, TestOnDeliveryConfirmed2); type SourceHeaderChain = TestSourceHeaderChain; type MessageDispatch = TestMessageDispatch; @@ -321,88 +316,6 @@ impl MessageDeliveryAndDispatchPayment } } -#[derive(Debug)] -pub struct TestOnMessageAccepted; - -impl TestOnMessageAccepted { - /// Verify that the callback has been called when the message is accepted. - pub fn ensure_called(lane: &LaneId, message: &MessageNonce) { - let key = (b"TestOnMessageAccepted", lane, message).encode(); - assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); - } - - /// Set consumed weight returned by the callback. - pub fn set_consumed_weight_per_message(weight: Weight) { - frame_support::storage::unhashed::put(b"TestOnMessageAccepted_Weight", &weight); - } - - /// Get consumed weight returned by the callback. - pub fn get_consumed_weight_per_message() -> Option { - frame_support::storage::unhashed::get(b"TestOnMessageAccepted_Weight") - } -} - -impl OnMessageAccepted for TestOnMessageAccepted { - fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight { - let key = (b"TestOnMessageAccepted", lane, message).encode(); - frame_support::storage::unhashed::put(&key, &true); - Self::get_consumed_weight_per_message() - .unwrap_or_else(|| DbWeight::get().reads_writes(1, 1)) - } -} - -/// First on-messages-delivered callback. -#[derive(Debug)] -pub struct TestOnDeliveryConfirmed1; - -impl TestOnDeliveryConfirmed1 { - /// Verify that the callback has been called with given delivered messages. - pub fn ensure_called(lane: &LaneId, messages: &DeliveredMessages) { - let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode(); - assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); - } - - /// Set consumed weight returned by the callback. - pub fn set_consumed_weight_per_message(weight: Weight) { - frame_support::storage::unhashed::put(b"TestOnDeliveryConfirmed1_Weight", &weight); - } - - /// Get consumed weight returned by the callback. - pub fn get_consumed_weight_per_message() -> Option { - frame_support::storage::unhashed::get(b"TestOnDeliveryConfirmed1_Weight") - } -} - -impl OnDeliveryConfirmed for TestOnDeliveryConfirmed1 { - fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { - let key = (b"TestOnDeliveryConfirmed1", lane, messages).encode(); - frame_support::storage::unhashed::put(&key, &true); - Self::get_consumed_weight_per_message() - .unwrap_or_else(|| DbWeight::get().reads_writes(1, 1)) - .saturating_mul(messages.total_messages()) - } -} - -/// Second on-messages-delivered callback. -#[derive(Debug)] -pub struct TestOnDeliveryConfirmed2; - -impl TestOnDeliveryConfirmed2 { - /// Verify that the callback has been called with given delivered messages. - pub fn ensure_called(lane: &LaneId, messages: &DeliveredMessages) { - let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode(); - assert_eq!(frame_support::storage::unhashed::get(&key), Some(true)); - } -} - -impl OnDeliveryConfirmed for TestOnDeliveryConfirmed2 { - fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { - let key = (b"TestOnDeliveryConfirmed2", lane, messages).encode(); - frame_support::storage::unhashed::put(&key, &true); - Weight::from_ref_time(0) - } -} - /// Source header chain that is used in tests. #[derive(Debug)] pub struct TestSourceHeaderChain; diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 5ad86c817dcee..1604832c0790a 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -20,7 +20,7 @@ use crate::weights::WeightInfo; use bp_messages::{MessageNonce, UnrewardedRelayersState}; use bp_runtime::{PreComputedSize, Size}; -use frame_support::weights::{RuntimeDbWeight, Weight}; +use frame_support::weights::Weight; /// Size of the message being delivered in benchmarks. pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128; @@ -88,7 +88,6 @@ pub fn ensure_able_to_receive_confirmation( max_inbound_lane_data_proof_size_from_peer_chain: u32, max_unrewarded_relayer_entries_at_peer_inbound_lane: MessageNonce, max_unconfirmed_messages_at_inbound_lane: MessageNonce, - db_weight: RuntimeDbWeight, ) { // verify that we're able to receive confirmation of maximal-size let max_confirmation_transaction_size = @@ -110,7 +109,6 @@ pub fn ensure_able_to_receive_confirmation( total_messages: max_unconfirmed_messages_at_inbound_lane, ..Default::default() }, - db_weight, ); assert!( max_confirmation_transaction_dispatch_weight.all_lte(max_extrinsic_weight), @@ -166,7 +164,6 @@ pub trait WeightInfoExt: WeightInfo { fn receive_messages_delivery_proof_weight( proof: &impl Size, relayers_state: &UnrewardedRelayersState, - db_weight: RuntimeDbWeight, ) -> Weight { // basic components of extrinsic weight let transaction_overhead = Self::receive_messages_delivery_proof_overhead(); @@ -183,16 +180,10 @@ pub trait WeightInfoExt: WeightInfo { actual_proof_size.saturating_sub(expected_proof_size), ); - // and cost of calling `OnDeliveryConfirmed::on_messages_delivered()` for every confirmed - // message - let callback_overhead = Self::single_message_callback_overhead(db_weight) - .saturating_mul(relayers_state.total_messages); - transaction_overhead .saturating_add(messages_overhead) .saturating_add(relayers_overhead) .saturating_add(proof_size_overhead) - .saturating_add(callback_overhead) } // Functions that are used by extrinsics weights formulas. @@ -283,15 +274,6 @@ pub trait WeightInfoExt: WeightInfo { Self::receive_single_message_proof() .saturating_sub(Self::receive_single_prepaid_message_proof()) } - - /// Returns pre-dispatch weight of single callback call. - /// - /// When benchmarking the weight please take into consideration both the `OnMessageAccepted` and - /// `OnDeliveryConfirmed` callbacks. The method should return the greater of the two, because - /// it's used to estimate the weight in both contexts. - fn single_message_callback_overhead(db_weight: RuntimeDbWeight) -> Weight { - db_weight.reads_writes(1, 1) - } } impl WeightInfoExt for () { diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index f2ae936ae8c9b..acb709407dca1 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -110,8 +110,6 @@ impl pallet_bridge_messages::Config for TestRuntime { type TargetHeaderChain = ForbidOutboundMessages; type LaneMessageVerifier = ForbidOutboundMessages; type MessageDeliveryAndDispatchPayment = (); - type OnMessageAccepted = (); - type OnDeliveryConfirmed = (); type SourceHeaderChain = ForbidInboundMessages; type MessageDispatch = ForbidInboundMessages; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 6a22ececf8efc..1cac449ee63ea 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -16,7 +16,7 @@ //! Primitives of messages module, that are used on the source chain. -use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; +use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; use crate::UnrewardedRelayer; use bp_runtime::Size; @@ -165,49 +165,6 @@ impl MessagesBridge for NoopMessag } } -/// Handler for messages delivery confirmation. -pub trait OnDeliveryConfirmed { - /// Called when we receive confirmation that our messages have been delivered to the - /// target chain. The confirmation also has single bit dispatch result for every - /// confirmed message (see `DeliveredMessages` for details). Guaranteed to be called - /// only when at least one message is delivered. - /// - /// Should return total weight consumed by the call. - /// - /// NOTE: messages pallet assumes that maximal weight that may be spent on processing - /// single message is single DB read + single DB write. So this function shall never - /// return weight that is larger than total number of messages * (db read + db write). - /// If your pallet needs more time for processing single message, please do it - /// from `on_initialize` call(s) of the next block(s). - fn on_messages_delivered(_lane: &LaneId, _messages: &DeliveredMessages) -> Weight; -} - -#[allow(clippy::let_and_return)] -#[impl_trait_for_tuples::impl_for_tuples(30)] -impl OnDeliveryConfirmed for Tuple { - fn on_messages_delivered(lane: &LaneId, messages: &DeliveredMessages) -> Weight { - let mut total_weight = Weight::zero(); - for_tuples!( - #( - total_weight = total_weight.saturating_add(Tuple::on_messages_delivered(lane, messages)); - )* - ); - total_weight - } -} - -/// Handler for messages have been accepted -pub trait OnMessageAccepted { - /// Called when a message has been accepted by message pallet. - fn on_messages_accepted(lane: &LaneId, message: &MessageNonce) -> Weight; -} - -impl OnMessageAccepted for () { - fn on_messages_accepted(_lane: &LaneId, _message: &MessageNonce) -> Weight { - Weight::zero() - } -} - /// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and /// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden. pub struct ForbidOutboundMessages; From fe6e4734901fdea3484c2c6aad288f52490cbdde Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Nov 2022 13:29:26 +0300 Subject: [PATCH 0810/1210] Prune messages from on-idle callback (#1650) * prune messages from on-idle callback * no more secondary lanes at deployments * clippy * Update modules/messages/src/lib.rs Co-authored-by: Adrian Catangiu * sub -> add * more tests + check that message is sent using one of ActiveOutboundLanes * ensure spent_weight is correct Co-authored-by: Adrian Catangiu --- bin/millau/runtime/src/lib.rs | 6 +- bin/millau/runtime/src/rialto_messages.rs | 24 +- .../runtime/src/rialto_parachain_messages.rs | 6 +- bin/millau/runtime/src/xcm_config.rs | 10 +- bin/rialto-parachain/runtime/src/lib.rs | 7 +- .../runtime/src/millau_messages.rs | 23 +- bin/rialto/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/millau_messages.rs | 24 +- bin/runtime-common/src/integrity.rs | 6 +- modules/messages/src/lib.rs | 253 ++++++++++++++++-- modules/messages/src/mock.rs | 9 +- modules/messages/src/outbound_lane.rs | 58 +++- modules/relayers/src/mock.rs | 3 +- 13 files changed, 322 insertions(+), 110 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 49cd16834bb76..b1f1e33d18a47 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -469,6 +469,8 @@ parameter_types! { pub const RootAccountForPayments: Option = None; pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; pub const RialtoParachainChainId: bp_runtime::ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; + pub RialtoActiveOutboundLanes: &'static [bp_messages::LaneId] = &[rialto_messages::XCM_LANE]; + pub RialtoParachainActiveOutboundLanes: &'static [bp_messages::LaneId] = &[rialto_parachain_messages::XCM_LANE]; } /// Instance of the messages pallet used to relay messages to/from Rialto chain. @@ -477,7 +479,7 @@ pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type ActiveOutboundLanes = RialtoActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -506,7 +508,7 @@ pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1 impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type ActiveOutboundLanes = RialtoParachainActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 5d7b189db2af9..e78d69229e18e 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{OriginCaller, RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, @@ -28,7 +28,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto. -pub const DEFAULT_XCM_LANE_TO_RIALTO: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = [0, 0, 0, 0]; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. @@ -98,24 +98,8 @@ impl messages::ThisChainWithMessages for Millau { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; - fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - let here_location = - xcm::v3::MultiLocation::from(crate::xcm_config::UniversalLocation::get()); - match send_origin.caller { - OriginCaller::XcmPallet(pallet_xcm::Origin::Xcm(ref location)) - if *location == here_location => - { - log::trace!(target: "runtime::bridge", "Verifying message sent using XCM pallet to Rialto"); - }, - _ => { - // keep in mind that in this case all messages are free (in term of fees) - // => it's just to keep testing bridge on our test deployments until we'll have a - // better option - log::trace!(target: "runtime::bridge", "Verifying message sent using messages pallet to Rialto"); - }, - } - - *lane == DEFAULT_XCM_LANE_TO_RIALTO || *lane == [0, 0, 0, 1] + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { + true } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 8655edd59f491..b6e8f52d342e2 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -28,7 +28,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto parachain. -pub const DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = [0, 0, 0, 0]; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. @@ -103,8 +103,8 @@ impl messages::ThisChainWithMessages for Millau { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - *lane == DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN || *lane == [0, 0, 0, 1] + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { + true } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 32b14f27a3b80..13304d2671f41 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -17,10 +17,8 @@ //! XCM configurations for the Millau runtime. use super::{ - rialto_messages::{WithRialtoMessageBridge, DEFAULT_XCM_LANE_TO_RIALTO}, - rialto_parachain_messages::{ - WithRialtoParachainMessageBridge, DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN, - }, + rialto_messages::{WithRialtoMessageBridge, XCM_LANE}, + rialto_parachain_messages::{WithRialtoParachainMessageBridge, XCM_LANE as XCM_LANE_PARACHAIN}, AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmPallet, }; @@ -218,7 +216,7 @@ impl XcmBridge for ToRialtoBridge { } fn xcm_lane() -> LaneId { - DEFAULT_XCM_LANE_TO_RIALTO + XCM_LANE } } @@ -245,7 +243,7 @@ impl XcmBridge for ToRialtoParachainBridge { } fn xcm_lane() -> LaneId { - DEFAULT_XCM_LANE_TO_RIALTO_PARACHAIN + XCM_LANE_PARACHAIN } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 7487e68f8f953..fcf83c8229454 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -26,7 +26,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use crate::millau_messages::{WithMillauMessageBridge, DEFAULT_XCM_LANE_TO_MILLAU}; +use crate::millau_messages::{WithMillauMessageBridge, XCM_LANE}; use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; use cumulus_pallet_parachain_system::AnyRelayNumber; @@ -455,7 +455,7 @@ impl XcmBridge for ToMillauBridge { } fn xcm_lane() -> bp_messages::LaneId { - DEFAULT_XCM_LANE_TO_MILLAU + XCM_LANE } } @@ -554,6 +554,7 @@ parameter_types! { bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; pub const RootAccountForPayments: Option = None; pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; + pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[millau_messages::XCM_LANE]; } /// Instance of the messages pallet used to relay messages to/from Millau chain. @@ -562,7 +563,7 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type ActiveOutboundLanes = ActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index ceabcd57b6663..25d37f1598832 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -19,7 +19,7 @@ // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // Should be extracted to a separate crate and reused here. -use crate::{MillauGrandpaInstance, OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, @@ -31,7 +31,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Millau. -pub const DEFAULT_XCM_LANE_TO_MILLAU: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = [0, 0, 0, 0]; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. @@ -102,23 +102,8 @@ impl messages::ThisChainWithMessages for RialtoParachain { type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - let here_location = xcm::v3::MultiLocation::from(crate::UniversalLocation::get()); - match send_origin.caller { - OriginCaller::PolkadotXcm(pallet_xcm::Origin::Xcm(ref location)) - if *location == here_location => - { - log::trace!(target: "runtime::bridge", "Verifying message sent using XCM pallet to Millau"); - }, - _ => { - // keep in mind that in this case all messages are free (in term of fees) - // => it's just to keep testing bridge on our test deployments until we'll have a - // better option - log::trace!(target: "runtime::bridge", "Verifying message sent using messages pallet to Millau"); - }, - } - - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { + true } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 378a471325d66..048be3ba25ef8 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -442,6 +442,7 @@ parameter_types! { bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; pub const RootAccountForPayments: Option = None; pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; + pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[millau_messages::XCM_LANE]; } /// Instance of the messages pallet used to relay messages to/from Millau chain. @@ -450,7 +451,7 @@ pub type WithMillauMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type ActiveOutboundLanes = ActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 98030ac3ee52e..221590e9f8122 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,7 +16,7 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{MillauGrandpaInstance, OriginCaller, Runtime, RuntimeCall, RuntimeOrigin}; +use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; use bp_messages::{ source_chain::TargetHeaderChain, @@ -27,6 +27,8 @@ use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +/// Lane that is used for XCM messages exchange. +pub const XCM_LANE: LaneId = [0, 0, 0, 0]; /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. @@ -96,24 +98,8 @@ impl messages::ThisChainWithMessages for Rialto { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; - fn is_message_accepted(send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - let here_location = - xcm::v3::MultiLocation::from(crate::xcm_config::UniversalLocation::get()); - match send_origin.caller { - OriginCaller::XcmPallet(pallet_xcm::Origin::Xcm(ref location)) - if *location == here_location => - { - log::trace!(target: "runtime::bridge", "Verifying message sent using XCM pallet to Millau"); - }, - _ => { - // keep in mind that in this case all messages are free (in term of fees) - // => it's just to keep testing bridge on our test deployments until we'll have a - // better option - log::trace!(target: "runtime::bridge", "Verifying message sent using messages pallet to Millau"); - }, - } - - *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { + true } fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index a9a2c06470c97..4c69a29b82170 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -204,9 +204,9 @@ where MI: 'static, { assert!( - R::MaxMessagesToPruneAtOnce::get() > 0, - "MaxMessagesToPruneAtOnce ({}) must be larger than zero", - R::MaxMessagesToPruneAtOnce::get(), + !R::ActiveOutboundLanes::get().is_empty(), + "ActiveOutboundLanes ({:?}) must not be empty", + R::ActiveOutboundLanes::get(), ); assert!( R::MaxUnrewardedRelayerEntriesAtInboundLane::get() <= params.max_unrewarded_relayers_in_bridged_confirmation_tx, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 8324aa75bc833..e2e3bef485584 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -65,6 +65,7 @@ use bp_messages::{ use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; +use sp_runtime::traits::UniqueSaturatedFrom; use sp_std::{ cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, prelude::*, @@ -107,10 +108,8 @@ pub mod pallet { #[pallet::constant] type BridgedChainId: Get; - /// Maximal number of messages that may be pruned during maintenance. Maintenance occurs - /// whenever new message is sent. The reason is that if you want to use lane, you should - /// be ready to pay for its maintenance. - type MaxMessagesToPruneAtOnce: Get; + /// Get all active outbound lanes that the message pallet is serving. + type ActiveOutboundLanes: Get<&'static [LaneId]>; /// Maximal number of unrewarded relayer entries at inbound lane. Unrewarded means that the /// relayer has delivered messages, but either confirmations haven't been delivered back to /// the source chain, or we haven't received reward confirmations yet. @@ -191,6 +190,40 @@ pub mod pallet { type OperatingModeStorage = PalletOperatingMode; } + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet + where + u32: TryFrom<::BlockNumber>, + { + fn on_idle(_block: T::BlockNumber, remaining_weight: Weight) -> Weight { + // we'll need at least to read outbound lane state, kill a message and update lane state + let db_weight = T::DbWeight::get(); + if !remaining_weight.all_gte(db_weight.reads_writes(1, 2)) { + return Weight::zero() + } + + // messages from lane with index `i` in `ActiveOutboundLanes` are pruned when + // `System::block_number() % lanes.len() == i`. Otherwise we need to read lane states on + // every block, wasting the whole `remaining_weight` for nothing and causing starvation + // of the last lane pruning + let active_lanes = T::ActiveOutboundLanes::get(); + let active_lanes_len = (active_lanes.len() as u32).into(); + let active_lane_index = u32::unique_saturated_from( + frame_system::Pallet::::block_number() % active_lanes_len, + ); + let active_lane_id = active_lanes[active_lane_index as usize]; + + // first db read - outbound lane state + let mut active_lane = outbound_lane::(active_lane_id); + let mut used_weight = db_weight.reads(1); + // and here we'll have writes + used_weight += active_lane.prune_messages(db_weight, remaining_weight - used_weight); + + // we already checked we have enough `remaining_weight` to cover this `used_weight` + used_weight + } + } + #[pallet::call] impl, I: 'static> Pallet { /// Change `PalletOwner`. @@ -469,6 +502,8 @@ pub mod pallet { pub enum Error { /// Pallet is not in Normal operating mode. NotOperatingNormally, + /// The outbound lane is inactive. + InactiveOutboundLane, /// The message is too large to be sent over the bridge. MessageIsTooLarge, /// Message has been treated as invalid by chain verifier. @@ -614,8 +649,8 @@ fn send_message, I: 'static>( > { ensure_normal_operating_mode::()?; - // initially, actual (post-dispatch) weight is equal to pre-dispatch weight - let mut actual_weight = frame_support::weights::Weight::zero(); // TODO (https://github.com/paritytech/parity-bridges-common/issues/1647): remove this + // let's check if outbound lane is active + ensure!(T::ActiveOutboundLanes::get().contains(&lane_id), Error::::InactiveOutboundLane,); // let's first check if message can be delivered to target chain T::TargetHeaderChain::verify_message(&payload).map_err(|err| { @@ -653,15 +688,6 @@ fn send_message, I: 'static>( ); let nonce = lane.send_message(encoded_payload); - // message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages - // the cost of pruning every message is roughly single db write - // => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned - let max_messages_to_prune = T::MaxMessagesToPruneAtOnce::get(); - let pruned_messages = lane.prune_messages(max_messages_to_prune); - if let Some(extra_messages) = max_messages_to_prune.checked_sub(pruned_messages) { - actual_weight = actual_weight.saturating_sub(T::DbWeight::get().writes(extra_messages)); - } - log::trace!( target: LOG_TARGET, "Accepted message {} to lane {:?}. Message size: {:?}", @@ -672,6 +698,14 @@ fn send_message, I: 'static>( Pallet::::deposit_event(Event::MessageAccepted { lane_id, nonce }); + // we may introduce benchmarks for that, but no heavy ops planned here apart from + // db reads and writes. There are currently 2 db reads and 2 db writes: + // - one db read for operation mode check (`ensure_normal_operating_mode`); + // - one db read for outbound lane state (`outbound_lane`); + // - one db write for outbound lane state (`send_message`); + // - one db write for the message (`send_message`); + let actual_weight = T::DbWeight::get().reads_writes(2, 2); + Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } @@ -851,17 +885,18 @@ fn verify_and_decode_messages_proof::receive_messages_delivery_proof( + RuntimeOrigin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + last_confirmed_nonce: 4, + relayers: vec![unrewarded_relayer(1, 4, TEST_RELAYER_A)] + .into_iter() + .collect(), + }, + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 4, + total_messages: 4, + last_delivered_nonce: 4, + }, + )); + + // all 4 messages may be pruned now + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().latest_received_nonce, + 4 + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 1 + ); + System::::set_block_number(2); + + // if passed wight is too low to do anything + let dbw = DbWeight::get(); + assert_eq!( + Pallet::::on_idle(0, dbw.reads_writes(1, 1)), + Weight::zero(), + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 1 + ); + + // if passed wight is enough to prune single message + assert_eq!( + Pallet::::on_idle(0, dbw.reads_writes(1, 2)), + dbw.reads_writes(1, 2), + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 2 + ); + + // if passed wight is enough to prune two more messages + assert_eq!( + Pallet::::on_idle(0, dbw.reads_writes(1, 3)), + dbw.reads_writes(1, 3), + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 4 + ); + + // if passed wight is enough to prune many messages + assert_eq!( + Pallet::::on_idle(0, dbw.reads_writes(100, 100)), + dbw.reads_writes(1, 2), + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 5 + ); + }); + } + + #[test] + fn on_idle_callback_is_rotating_lanes_to_prune() { + run_test(|| { + // send + receive confirmation for lane 1 + send_regular_message(); + receive_messages_delivery_proof(); + // send + receive confirmation for lane 2 + assert_ok!(send_message::( + RuntimeOrigin::signed(1), + TEST_LANE_ID_2, + REGULAR_PAYLOAD, + )); + assert_ok!(Pallet::::receive_messages_delivery_proof( + RuntimeOrigin::signed(1), + TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID_2, + InboundLaneData { + last_confirmed_nonce: 1, + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] + .into_iter() + .collect(), + }, + ))), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + last_delivered_nonce: 1, + }, + )); + + // nothing is pruned yet + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().latest_received_nonce, + 1 + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 1 + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID_2).data().latest_received_nonce, + 1 + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID_2).data().oldest_unpruned_nonce, + 1 + ); + + // in block#2.on_idle lane messages of lane 1 are pruned + let dbw = DbWeight::get(); + System::::set_block_number(2); + assert_eq!( + Pallet::::on_idle(0, dbw.reads_writes(100, 100)), + dbw.reads_writes(1, 2), + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 2 + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID_2).data().oldest_unpruned_nonce, + 1 + ); + + // in block#3.on_idle lane messages of lane 2 are pruned + System::::set_block_number(3); + + assert_eq!( + Pallet::::on_idle(0, dbw.reads_writes(100, 100)), + dbw.reads_writes(1, 2), + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID).data().oldest_unpruned_nonce, + 2 + ); + assert_eq!( + outbound_lane::(TEST_LANE_ID_2).data().oldest_unpruned_nonce, + 2 + ); + }); + } + + #[test] + fn outbound_message_from_unconfigured_lane_is_rejected() { + run_test(|| { + assert_noop!( + send_message::( + RuntimeOrigin::signed(1), + TEST_LANE_ID_3, + REGULAR_PAYLOAD, + ), + Error::::InactiveOutboundLane, + ); + }); + } + generate_owned_bridge_module_tests!( MessagesOperatingMode::Basic(BasicOperatingMode::Normal), MessagesOperatingMode::Basic(BasicOperatingMode::Halted) diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 5d58883d0a6f9..861f273d7e7cc 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -141,12 +141,13 @@ parameter_types! { pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; + pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID, TEST_LANE_ID_2]; } impl Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); - type MaxMessagesToPruneAtOnce = MaxMessagesToPruneAtOnce; + type ActiveOutboundLanes = ActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -192,6 +193,12 @@ pub const TEST_ERROR: &str = "Test error"; /// Lane that we're using in tests. pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; +/// Secondary lane that we're using in tests. +pub const TEST_LANE_ID_2: LaneId = [0, 0, 0, 2]; + +/// Inactive outbound lane. +pub const TEST_LANE_ID_3: LaneId = [0, 0, 0, 3]; + /// Regular message payload. pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 50); diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 890b85072ab9d..3774dc7ff3668 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -23,7 +23,11 @@ use bp_messages::{ DeliveredMessages, DispatchResultsBitVec, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, }; -use frame_support::{BoundedVec, RuntimeDebug}; +use frame_support::{ + weights::{RuntimeDbWeight, Weight}, + BoundedVec, RuntimeDebug, +}; +use num_traits::Zero; use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. @@ -147,24 +151,32 @@ impl OutboundLane { /// Prune at most `max_messages_to_prune` already received messages. /// - /// Returns number of pruned messages. - pub fn prune_messages(&mut self, max_messages_to_prune: MessageNonce) -> MessageNonce { - let mut pruned_messages = 0; + /// Returns weight, consumed by messages pruning and lane state update. + pub fn prune_messages( + &mut self, + db_weight: RuntimeDbWeight, + mut remaining_weight: Weight, + ) -> Weight { + let write_weight = db_weight.writes(1); + let two_writes_weight = write_weight + write_weight; + let mut spent_weight = Weight::zero(); let mut data = self.storage.data(); - while pruned_messages < max_messages_to_prune && + while remaining_weight.all_gte(two_writes_weight) && data.oldest_unpruned_nonce <= data.latest_received_nonce { self.storage.remove_message(&data.oldest_unpruned_nonce); - pruned_messages += 1; + spent_weight += write_weight; + remaining_weight -= write_weight; data.oldest_unpruned_nonce += 1; } - if pruned_messages > 0 { + if !spent_weight.is_zero() { + spent_weight += write_weight; self.storage.set_data(data); } - pruned_messages + spent_weight } } @@ -246,6 +258,7 @@ mod tests { }, outbound_lane, }; + use frame_support::weights::constants::RocksDbWeight; use sp_std::ops::RangeInclusive; fn unrewarded_relayers( @@ -413,27 +426,48 @@ mod tests { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); // when lane is empty, nothing is pruned - assert_eq!(lane.prune_messages(100), 0); + assert_eq!( + lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)), + Weight::zero() + ); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // when nothing is confirmed, nothing is pruned lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - assert_eq!(lane.prune_messages(100), 0); + assert!(lane.storage.message(&1).is_some()); + assert!(lane.storage.message(&2).is_some()); + assert!(lane.storage.message(&3).is_some()); + assert_eq!( + lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)), + Weight::zero() + ); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // after confirmation, some messages are received assert_eq!( lane.confirm_delivery(2, 2, &unrewarded_relayers(1..=2)), ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)), ); - assert_eq!(lane.prune_messages(100), 2); + assert_eq!( + lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)), + RocksDbWeight::get().writes(3), + ); + assert!(lane.storage.message(&1).is_none()); + assert!(lane.storage.message(&2).is_none()); + assert!(lane.storage.message(&3).is_some()); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 3); // after last message is confirmed, everything is pruned assert_eq!( lane.confirm_delivery(1, 3, &unrewarded_relayers(3..=3)), ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)), ); - assert_eq!(lane.prune_messages(100), 1); + assert_eq!( + lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)), + RocksDbWeight::get().writes(2), + ); + assert!(lane.storage.message(&1).is_none()); + assert!(lane.storage.message(&2).is_none()); + assert!(lane.storage.message(&3).is_none()); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 4); }); } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index acb709407dca1..7cf5575f5f384 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -91,13 +91,14 @@ impl pallet_balances::Config for TestRuntime { parameter_types! { pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; + pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[[0, 0, 0, 0]]; } // we're not testing messages pallet here, so values in this config might be crazy impl pallet_bridge_messages::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); - type MaxMessagesToPruneAtOnce = frame_support::traits::ConstU64<0>; + type ActiveOutboundLanes = ActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = frame_support::traits::ConstU64<8>; type MaxUnconfirmedMessagesAtInboundLane = frame_support::traits::ConstU64<8>; From 947604554394e1521df82d73bf9a87c53911331e Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 21 Nov 2022 16:55:11 +0100 Subject: [PATCH 0811/1210] Added event `MessagesReceived` for better visibility on receiving side (#1655) * Added event `MessagesReceived` for better visibility on receiving side * Fixes/comments from PR * Final cleanup --- modules/messages/src/inbound_lane.rs | 25 +++------------- modules/messages/src/lib.rs | 44 +++++++++++++++++++++------- primitives/messages/src/lib.rs | 42 ++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index ba4483e608c3c..aa2a9682668e3 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -21,9 +21,8 @@ use crate::Config; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, - UnrewardedRelayer, + ReceivalResult, UnrewardedRelayer, }; -use bp_runtime::messages::MessageDispatchResult; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use frame_support::{traits::Get, RuntimeDebug}; use scale_info::{Type, TypeInfo}; @@ -108,22 +107,6 @@ impl, I: 'static> MaxEncodedLen for StoredInboundLaneData { } } -/// Result of single message receival. -#[derive(RuntimeDebug, PartialEq, Eq)] -pub enum ReceivalResult { - /// Message has been received and dispatched. Note that we don't care whether dispatch has - /// been successful or not - in both case message falls into this category. - /// - /// The message dispatch result is also returned. - Dispatched(MessageDispatchResult), - /// Message has invalid nonce and lane has rejected to accept this message. - InvalidNonce, - /// There are too many unrewarded relayer entries at the lane. - TooManyUnrewardedRelayers, - /// There are too many unconfirmed messages at the lane. - TooManyUnconfirmedMessages, -} - /// Inbound messages lane. pub struct InboundLane { storage: S, @@ -181,12 +164,12 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message, AccountId>( + pub fn receive_message, AccountId>( &mut self, relayer_at_bridged_chain: &S::Relayer, relayer_at_this_chain: &AccountId, nonce: MessageNonce, - message_data: DispatchMessageData, + message_data: DispatchMessageData, ) -> ReceivalResult { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; @@ -206,7 +189,7 @@ impl InboundLane { } // then, dispatch message - let dispatch_result = P::dispatch( + let dispatch_result = Dispatch::dispatch( relayer_at_this_chain, DispatchMessage { key: MessageKey { lane_id: self.storage.id(), nonce }, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index e2e3bef485584..b7e7f72f5faaf 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -46,7 +46,7 @@ pub use weights_ext::{ }; use crate::{ - inbound_lane::{InboundLane, InboundLaneStorage, ReceivalResult}, + inbound_lane::{InboundLane, InboundLaneStorage}, outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult}, }; @@ -91,6 +91,7 @@ pub const LOG_TARGET: &str = "runtime::bridge-messages"; #[frame_support::pallet] pub mod pallet { use super::*; + use bp_messages::{ReceivalResult, ReceivedMessages}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -298,6 +299,7 @@ pub mod pallet { // dispatch messages and (optionally) update lane(s) state(s) let mut total_messages = 0; let mut valid_messages = 0; + let mut messages_received_status = Vec::with_capacity(messages.len()); let mut dispatch_weight_left = dispatch_weight; for (lane_id, lane_data) in messages { let mut lane = inbound_lane::(lane_id); @@ -314,24 +316,37 @@ pub mod pallet { } } + let mut lane_messages_received_status = + ReceivedMessages::new(lane_id, Vec::with_capacity(lane_data.messages.len())); + let mut is_lane_processing_stopped_no_weight_left = false; + for mut message in lane_data.messages { debug_assert_eq!(message.key.lane_id, lane_id); + total_messages += 1; + + if is_lane_processing_stopped_no_weight_left { + lane_messages_received_status + .push_skipped_for_not_enough_weight(message.key.nonce); + continue + } // ensure that relayer has declared enough weight for dispatching next message // on this lane. We can't dispatch lane messages out-of-order, so if declared // weight is not enough, let's move to next lane - let dispatch_weight = T::MessageDispatch::dispatch_weight(&mut message); - if dispatch_weight.any_gt(dispatch_weight_left) { + let message_dispatch_weight = T::MessageDispatch::dispatch_weight(&mut message); + if message_dispatch_weight.any_gt(dispatch_weight_left) { log::trace!( target: LOG_TARGET, "Cannot dispatch any more messages on lane {:?}. Weight: declared={}, left={}", lane_id, - dispatch_weight, + message_dispatch_weight, dispatch_weight_left, ); - break + lane_messages_received_status + .push_skipped_for_not_enough_weight(message.key.nonce); + is_lane_processing_stopped_no_weight_left = true; + continue } - total_messages += 1; let receival_result = lane.receive_message::( &relayer_id_at_bridged_chain, @@ -346,7 +361,7 @@ pub mod pallet { // losing funds for messages dispatch. But keep in mind that relayer pays base // delivery transaction cost anyway. And base cost covers everything except // dispatch, so we have a balance here. - let (unspent_weight, refund_pay_dispatch_fee) = match receival_result { + let (unspent_weight, refund_pay_dispatch_fee) = match &receival_result { ReceivalResult::Dispatched(dispatch_result) => { valid_messages += 1; ( @@ -356,11 +371,12 @@ pub mod pallet { }, ReceivalResult::InvalidNonce | ReceivalResult::TooManyUnrewardedRelayers | - ReceivalResult::TooManyUnconfirmedMessages => (dispatch_weight, true), + ReceivalResult::TooManyUnconfirmedMessages => (message_dispatch_weight, true), }; + lane_messages_received_status.push(message.key.nonce, receival_result); - let unspent_weight = unspent_weight.min(dispatch_weight); - dispatch_weight_left -= dispatch_weight - unspent_weight; + let unspent_weight = unspent_weight.min(message_dispatch_weight); + dispatch_weight_left -= message_dispatch_weight - unspent_weight; actual_weight = actual_weight.saturating_sub(unspent_weight).saturating_sub( // delivery call weight formula assumes that the fee is paid at // this (target) chain. If the message is prepaid at the source @@ -372,9 +388,11 @@ pub mod pallet { }, ); } + + messages_received_status.push(lane_messages_received_status); } - log::trace!( + log::debug!( target: LOG_TARGET, "Received messages: total={}, valid={}. Weight used: {}/{}", total_messages, @@ -383,6 +401,8 @@ pub mod pallet { declared_weight, ); + Self::deposit_event(Event::MessagesReceived(messages_received_status)); + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } @@ -494,6 +514,8 @@ pub mod pallet { pub enum Event, I: 'static = ()> { /// Message has been accepted and is waiting to be delivered. MessageAccepted { lane_id: LaneId, nonce: MessageNonce }, + /// Messages have been received from the bridged chain. + MessagesReceived(Vec>), /// Messages in the inclusive range have been delivered to the bridged chain. MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages }, } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index f535a40a9db9b..d816447959893 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -32,6 +32,7 @@ pub mod storage_keys; pub mod target_chain; // Weight is reexported to avoid additional frame-support dependencies in related crates. +use bp_runtime::messages::MessageDispatchResult; pub use frame_support::weights::Weight; /// Messages pallet operating mode. @@ -218,6 +219,47 @@ pub struct UnrewardedRelayer { pub messages: DeliveredMessages, } +/// Received messages with their dispatch result. +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] +pub struct ReceivedMessages { + /// Id of the lane which is receiving messages. + pub lane: LaneId, + /// Result of messages which we tried to dispatch + pub receive_results: Vec<(MessageNonce, Result)>, + /// Messages which were skipped and never dispatched + pub skipped_for_not_enough_weight: Vec, +} + +impl ReceivedMessages { + pub fn new(lane: LaneId, receive_results: Vec<(MessageNonce, Result)>) -> Self { + ReceivedMessages { lane, receive_results, skipped_for_not_enough_weight: Vec::new() } + } + + pub fn push(&mut self, message: MessageNonce, result: Result) { + self.receive_results.push((message, result)); + } + + pub fn push_skipped_for_not_enough_weight(&mut self, message: MessageNonce) { + self.skipped_for_not_enough_weight.push(message); + } +} + +/// Result of single message receival. +#[derive(RuntimeDebug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)] +pub enum ReceivalResult { + /// Message has been received and dispatched. Note that we don't care whether dispatch has + /// been successful or not - in both case message falls into this category. + /// + /// The message dispatch result is also returned. + Dispatched(MessageDispatchResult), + /// Message has invalid nonce and lane has rejected to accept this message. + InvalidNonce, + /// There are too many unrewarded relayer entries at the lane. + TooManyUnrewardedRelayers, + /// There are too many unconfirmed messages at the lane. + TooManyUnconfirmedMessages, +} + /// Delivered messages with their dispatch result. #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct DeliveredMessages { From 6dcca2dc6aa8618e17157acb48416486d3a5eed6 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 21 Nov 2022 18:52:24 +0200 Subject: [PATCH 0812/1210] Add BEEFY finality pallet with basic functionality (#1606) * pallet-bridge-beefy: initial commit --- bin/rialto/runtime/Cargo.toml | 2 + bin/rialto/runtime/src/lib.rs | 11 + modules/beefy/Cargo.toml | 54 +++ modules/beefy/src/lib.rs | 644 +++++++++++++++++++++++++++++ modules/beefy/src/mock.rs | 226 ++++++++++ modules/beefy/src/mock_chain.rs | 299 ++++++++++++++ modules/beefy/src/utils.rs | 363 ++++++++++++++++ primitives/beefy/Cargo.toml | 48 +++ primitives/beefy/src/lib.rs | 152 +++++++ primitives/chain-millau/Cargo.toml | 2 + primitives/chain-millau/src/lib.rs | 12 + 11 files changed, 1813 insertions(+) create mode 100644 modules/beefy/Cargo.toml create mode 100644 modules/beefy/src/lib.rs create mode 100644 modules/beefy/src/mock.rs create mode 100644 modules/beefy/src/mock_chain.rs create mode 100644 modules/beefy/src/utils.rs create mode 100644 primitives/beefy/Cargo.toml create mode 100644 primitives/beefy/src/lib.rs diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 8b043d37886ac..7220e5790a409 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -19,6 +19,7 @@ bp-relayers = { path = "../../../primitives/relayers", default-features = false bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } +pallet-bridge-beefy = { path = "../../../modules/beefy", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } @@ -98,6 +99,7 @@ std = [ "pallet-balances/std", "pallet-beefy/std", "pallet-beefy-mmr/std", + "pallet-bridge-beefy/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-relayers/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 048be3ba25ef8..25778705e5ef5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -68,6 +68,7 @@ pub use frame_support::{ pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; +pub use pallet_bridge_beefy::Call as BridgeBeefyCall; pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; pub use pallet_bridge_messages::Call as MessagesCall; pub use pallet_sudo::Call as SudoCall; @@ -474,6 +475,13 @@ impl pallet_bridge_messages::Config for Runtime { type BridgedChainId = BridgedChainId; } +pub type MillauBeefyInstance = (); +impl pallet_bridge_beefy::Config for Runtime { + type MaxRequests = frame_support::traits::ConstU32<16>; + type CommitmentsToKeep = frame_support::traits::ConstU32<8>; + type BridgedChain = bp_millau::Millau; +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -506,6 +514,9 @@ construct_runtime!( BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + // Millau bridge modules (BEEFY based). + BridgeMillauBeefy: pallet_bridge_beefy::{Pallet, Call, Storage}, + // Parachain modules. ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin}, Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config}, diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml new file mode 100644 index 0000000000000..25905126d5358 --- /dev/null +++ b/modules/beefy/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "pallet-bridge-beefy" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +log = { version = "0.4.14", default-features = false } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +serde = { version = "1.0", optional = true } + +# Bridge Dependencies + +bp-beefy = { path = "../../primitives/beefy", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } + +# Substrate Dependencies + +beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +primitive-types = { version = "0.12.0", default-features = false, features = ["impl-codec"] } +sp-core = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[dev-dependencies] +beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } +mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.3.2" } +pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } +rand = "0.8" +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +bp-test-utils = { path = "../../primitives/test-utils" } + +[features] +default = ["std"] +std = [ + "beefy-merkle-tree/std", + "bp-beefy/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "primitive-types/std", + "scale-info/std", + "serde", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs new file mode 100644 index 0000000000000..5ef58c5a3cbb4 --- /dev/null +++ b/modules/beefy/src/lib.rs @@ -0,0 +1,644 @@ +// Copyright 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 . + +//! BEEFY bridge pallet. +//! +//! This pallet is an on-chain BEEFY light client for Substrate-based chains that are using the +//! following pallets bundle: `pallet-mmr`, `pallet-beefy` and `pallet-beefy-mmr`. +//! +//! The pallet is able to verify MMR leaf proofs and BEEFY commitments, so it has access +//! to the following data of the bridged chain: +//! +//! - header hashes +//! - changes of BEEFY authorities +//! - extra data of MMR leafs +//! +//! Given the header hash, other pallets are able to verify header-based proofs +//! (e.g. storage proofs, transaction inclusion proofs, etc.). + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_beefy::{ChainWithBeefy, InitializationData}; +use sp_std::{boxed::Box, prelude::*}; + +// Re-export in crate namespace for `construct_runtime!` +pub use pallet::*; + +mod utils; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod mock_chain; + +/// The target that will be used when publishing logs related to this pallet. +pub const LOG_TARGET: &str = "runtime::bridge-beefy"; + +/// Configured bridged chain. +pub type BridgedChain = >::BridgedChain; +/// Block number, used by configured bridged chain. +pub type BridgedBlockNumber = bp_runtime::BlockNumberOf>; +/// Block hash, used by configured bridged chain. +pub type BridgedBlockHash = bp_runtime::HashOf>; + +/// Pallet initialization data. +pub type InitializationDataOf = + InitializationData, bp_beefy::MmrHashOf>>; +/// BEEFY commitment hasher, used by configured bridged chain. +pub type BridgedBeefyCommitmentHasher = bp_beefy::BeefyCommitmentHasher>; +/// BEEFY validator id, used by configured bridged chain. +pub type BridgedBeefyAuthorityId = bp_beefy::BeefyAuthorityIdOf>; +/// BEEFY validator set, used by configured bridged chain. +pub type BridgedBeefyAuthoritySet = bp_beefy::BeefyAuthoritySetOf>; +/// BEEFY authority set, used by configured bridged chain. +pub type BridgedBeefyAuthoritySetInfo = bp_beefy::BeefyAuthoritySetInfoOf>; +/// BEEFY signed commitment, used by configured bridged chain. +pub type BridgedBeefySignedCommitment = bp_beefy::BeefySignedCommitmentOf>; +/// MMR hashing algorithm, used by configured bridged chain. +pub type BridgedMmrHashing = bp_beefy::MmrHashingOf>; +/// MMR hashing output type of `BridgedMmrHashing`. +pub type BridgedMmrHash = bp_beefy::MmrHashOf>; +/// The type of the MMR leaf extra data used by the configured bridged chain. +pub type BridgedBeefyMmrLeafExtra = bp_beefy::BeefyMmrLeafExtraOf>; +/// BEEFY MMR proof type used by the pallet +pub type BridgedMmrProof = bp_beefy::MmrProofOf>; +/// MMR leaf type, used by configured bridged chain. +pub type BridgedBeefyMmrLeaf = bp_beefy::BeefyMmrLeafOf>; +/// Imported commitment data, stored by the pallet. +pub type ImportedCommitment = bp_beefy::ImportedCommitment< + BridgedBlockNumber, + BridgedBlockHash, + BridgedMmrHash, +>; + +/// Some high level info about the imported commitments. +#[derive(codec::Encode, codec::Decode, scale_info::TypeInfo)] +pub struct ImportedCommitmentsInfoData { + /// Best known block number, provided in a BEEFY commitment. However this is not + /// the best proven block. The best proven block is this block's parent. + best_block_number: BlockNumber, + /// The head of the `ImportedBlockNumbers` ring buffer. + next_block_number_index: u32, +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use bp_runtime::{BasicOperatingMode, OwnedBridgeModule}; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The upper bound on the number of requests allowed by the pallet. + /// + /// A request refers to an action which writes a header to storage. + /// + /// Once this bound is reached the pallet will reject all commitments + /// until the request count has decreased. + #[pallet::constant] + type MaxRequests: Get; + + /// Maximal number of imported commitments to keep in the storage. + /// + /// The setting is there to prevent growing the on-chain state indefinitely. Note + /// the setting does not relate to block numbers - we will simply keep as much items + /// in the storage, so it doesn't guarantee any fixed timeframe for imported commitments. + #[pallet::constant] + type CommitmentsToKeep: Get; + + /// The chain we are bridging to here. + type BridgedChain: ChainWithBeefy; + } + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet { + fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { + >::mutate(|count| *count = count.saturating_sub(1)); + + Weight::from_ref_time(0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + } + + impl, I: 'static> OwnedBridgeModule for Pallet { + const LOG_TARGET: &'static str = LOG_TARGET; + type OwnerStorage = PalletOwner; + type OperatingMode = BasicOperatingMode; + type OperatingModeStorage = PalletOperatingMode; + } + + #[pallet::call] + impl, I: 'static> Pallet + where + BridgedMmrHashing: 'static + Send + Sync, + { + /// Initialize pallet with BEEFY authority set and best known finalized block number. + #[pallet::weight((T::DbWeight::get().reads_writes(2, 3), DispatchClass::Operational))] + pub fn initialize( + origin: OriginFor, + init_data: InitializationDataOf, + ) -> DispatchResult { + Self::ensure_owner_or_root(origin)?; + + let is_initialized = >::exists(); + ensure!(!is_initialized, >::AlreadyInitialized); + + log::info!(target: LOG_TARGET, "Initializing bridge BEEFY pallet: {:?}", init_data); + Ok(initialize::(init_data)?) + } + + /// Change `PalletOwner`. + /// + /// May only be called either by root, or by `PalletOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { + >::set_owner(origin, new_owner) + } + + /// Halt or resume all pallet operations. + /// + /// May only be called either by root, or by `PalletOwner`. + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_operating_mode( + origin: OriginFor, + operating_mode: BasicOperatingMode, + ) -> DispatchResult { + >::set_operating_mode(origin, operating_mode) + } + + /// Submit a commitment generated by BEEFY authority set. + /// + /// It will use the underlying storage pallet to fetch information about the current + /// authority set and best finalized block number in order to verify that the commitment + /// is valid. + /// + /// If successful in verification, it will update the underlying storage with the data + /// provided in the newly submitted commitment. + #[pallet::weight(0)] + pub fn submit_commitment( + origin: OriginFor, + commitment: BridgedBeefySignedCommitment, + validator_set: BridgedBeefyAuthoritySet, + mmr_leaf: Box>, + mmr_proof: BridgedMmrProof, + ) -> DispatchResult + where + BridgedBeefySignedCommitment: Clone, + { + Self::ensure_not_halted().map_err(Error::::BridgeModule)?; + ensure_signed(origin)?; + + ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); + + // Ensure that the commitment is for a better block. + let commitments_info = + ImportedCommitmentsInfo::::get().ok_or(Error::::NotInitialized)?; + ensure!( + commitment.commitment.block_number > commitments_info.best_block_number, + Error::::OldCommitment + ); + + // Verify commitment and mmr leaf. + let current_authority_set_info = CurrentAuthoritySetInfo::::get(); + let mmr_root = utils::verify_commitment::( + &commitment, + ¤t_authority_set_info, + &validator_set, + )?; + utils::verify_beefy_mmr_leaf::(&mmr_leaf, mmr_proof, mmr_root)?; + + // Update request count. + RequestCount::::mutate(|count| *count += 1); + // Update authority set if needed. + if mmr_leaf.beefy_next_authority_set.id > current_authority_set_info.id { + CurrentAuthoritySetInfo::::put(mmr_leaf.beefy_next_authority_set); + } + + // Import commitment. + let block_number_index = commitments_info.next_block_number_index; + let to_prune = ImportedBlockNumbers::::try_get(block_number_index); + ImportedCommitments::::insert( + commitment.commitment.block_number, + ImportedCommitment:: { + parent_number_and_hash: mmr_leaf.parent_number_and_hash, + mmr_root, + }, + ); + ImportedBlockNumbers::::insert( + block_number_index, + commitment.commitment.block_number, + ); + ImportedCommitmentsInfo::::put(ImportedCommitmentsInfoData { + best_block_number: commitment.commitment.block_number, + next_block_number_index: (block_number_index + 1) % T::CommitmentsToKeep::get(), + }); + if let Ok(old_block_number) = to_prune { + log::debug!( + target: LOG_TARGET, + "Pruning commitment for old block: {:?}.", + old_block_number + ); + ImportedCommitments::::remove(old_block_number); + } + + log::info!( + target: LOG_TARGET, + "Successfully imported commitment for block {:?}", + commitment.commitment.block_number, + ); + + Ok(()) + } + } + + /// The current number of requests which have written to storage. + /// + /// If the `RequestCount` hits `MaxRequests`, no more calls will be allowed to the pallet until + /// the request capacity is increased. + /// + /// The `RequestCount` is decreased by one at the beginning of every block. This is to ensure + /// that the pallet can always make progress. + #[pallet::storage] + #[pallet::getter(fn request_count)] + pub type RequestCount, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; + + /// High level info about the imported commitments. + /// + /// Contains the following info: + /// - best known block number of the bridged chain, finalized by BEEFY + /// - the head of the `ImportedBlockNumbers` ring buffer + #[pallet::storage] + pub type ImportedCommitmentsInfo, I: 'static = ()> = + StorageValue<_, ImportedCommitmentsInfoData>>; + + /// A ring buffer containing the block numbers of the commitments that we have imported, + /// ordered by the insertion time. + #[pallet::storage] + pub(super) type ImportedBlockNumbers, I: 'static = ()> = + StorageMap<_, Identity, u32, BridgedBlockNumber>; + + /// All the commitments that we have imported and haven't been pruned yet. + #[pallet::storage] + pub type ImportedCommitments, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, BridgedBlockNumber, ImportedCommitment>; + + /// The current BEEFY authority set at the bridged chain. + #[pallet::storage] + pub type CurrentAuthoritySetInfo, I: 'static = ()> = + StorageValue<_, BridgedBeefyAuthoritySetInfo, ValueQuery>; + + /// Optional pallet owner. + /// + /// Pallet owner has the right to halt all pallet operations and then resume it. If it is + /// `None`, then there are no direct ways to halt/resume pallet operations, but other + /// runtime methods may still be used to do that (i.e. `democracy::referendum` to update halt + /// flag directly or calling `halt_operations`). + #[pallet::storage] + pub type PalletOwner, I: 'static = ()> = + StorageValue<_, T::AccountId, OptionQuery>; + + /// The current operating mode of the pallet. + /// + /// Depending on the mode either all, or no transactions will be allowed. + #[pallet::storage] + pub type PalletOperatingMode, I: 'static = ()> = + StorageValue<_, BasicOperatingMode, ValueQuery>; + + #[pallet::genesis_config] + pub struct GenesisConfig, I: 'static = ()> { + /// Optional module owner account. + pub owner: Option, + /// Optional module initialization data. + pub init_data: Option>, + } + + #[cfg(feature = "std")] + impl, I: 'static> Default for GenesisConfig { + fn default() -> Self { + Self { owner: None, init_data: None } + } + } + + #[pallet::genesis_build] + impl, I: 'static> GenesisBuild for GenesisConfig { + fn build(&self) { + if let Some(ref owner) = self.owner { + >::put(owner); + } + + if let Some(init_data) = self.init_data.clone() { + initialize::(init_data) + .expect("invalid initialization data of BEEFY bridge pallet"); + } else { + // Since the bridge hasn't been initialized we shouldn't allow anyone to perform + // transactions. + >::put(BasicOperatingMode::Halted); + } + } + } + + #[pallet::error] + pub enum Error { + /// The pallet has not been initialized yet. + NotInitialized, + /// The pallet has already been initialized. + AlreadyInitialized, + /// Invalid initial authority set. + InvalidInitialAuthoritySet, + /// There are too many requests for the current window to handle. + TooManyRequests, + /// The imported commitment is older than the best commitment known to the pallet. + OldCommitment, + /// The commitment is signed by unknown validator set. + InvalidCommitmentValidatorSetId, + /// The id of the provided validator set is invalid. + InvalidValidatorSetId, + /// The number of signatures in the commitment is invalid. + InvalidCommitmentSignaturesLen, + /// The number of validator ids provided is invalid. + InvalidValidatorSetLen, + /// There aren't enough correct signatures in the commitment to finalize the block. + NotEnoughCorrectSignatures, + /// MMR root is missing from the commitment. + MmrRootMissingFromCommitment, + /// MMR proof verification has failed. + MmrProofVerificationFailed, + /// The validators are not matching the merkle tree root of the authority set. + InvalidValidatorSetRoot, + /// Error generated by the `OwnedBridgeModule` trait. + BridgeModule(bp_runtime::OwnedBridgeModuleError), + } + + /// Initialize pallet with given parameters. + pub(super) fn initialize, I: 'static>( + init_data: InitializationDataOf, + ) -> Result<(), Error> { + if init_data.authority_set.len == 0 { + return Err(Error::::InvalidInitialAuthoritySet) + } + CurrentAuthoritySetInfo::::put(init_data.authority_set); + + >::put(init_data.operating_mode); + ImportedCommitmentsInfo::::put(ImportedCommitmentsInfoData { + best_block_number: init_data.best_block_number, + next_block_number_index: 0, + }); + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use beefy_primitives::mmr::BeefyAuthoritySet; + use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError}; + use bp_test_utils::generate_owned_bridge_module_tests; + use frame_support::{assert_noop, assert_ok, traits::Get}; + use mock::*; + use mock_chain::*; + use sp_runtime::DispatchError; + + fn next_block() { + use frame_support::traits::OnInitialize; + + let current_number = frame_system::Pallet::::block_number(); + frame_system::Pallet::::set_block_number(current_number + 1); + let _ = Pallet::::on_initialize(current_number); + } + + fn import_header_chain(headers: Vec) { + for header in headers { + if header.commitment.is_some() { + assert_ok!(import_commitment(header)); + } + } + } + + #[test] + fn fails_to_initialize_if_already_initialized() { + run_test_with_initialize(32, || { + assert_noop!( + Pallet::::initialize( + RuntimeOrigin::root(), + InitializationData { + operating_mode: BasicOperatingMode::Normal, + best_block_number: 0, + authority_set: BeefyAuthoritySet { id: 0, len: 1, root: [0u8; 32].into() } + } + ), + Error::::AlreadyInitialized, + ); + }); + } + + #[test] + fn fails_to_initialize_if_authority_set_is_empty() { + run_test(|| { + assert_noop!( + Pallet::::initialize( + RuntimeOrigin::root(), + InitializationData { + operating_mode: BasicOperatingMode::Normal, + best_block_number: 0, + authority_set: BeefyAuthoritySet { id: 0, len: 0, root: [0u8; 32].into() } + } + ), + Error::::InvalidInitialAuthoritySet, + ); + }); + } + + #[test] + fn fails_to_import_commitment_if_halted() { + run_test_with_initialize(1, || { + assert_ok!(Pallet::::set_operating_mode( + RuntimeOrigin::root(), + BasicOperatingMode::Halted + )); + assert_noop!( + import_commitment(ChainBuilder::new(1).append_finalized_header().to_header()), + Error::::BridgeModule(OwnedBridgeModuleError::Halted), + ); + }) + } + + #[test] + fn fails_to_import_commitment_if_too_many_requests() { + run_test_with_initialize(1, || { + let max_requests = <::MaxRequests as Get>::get() as u64; + let mut chain = ChainBuilder::new(1); + for _ in 0..max_requests + 2 { + chain = chain.append_finalized_header(); + } + + // import `max_request` headers + for i in 0..max_requests { + assert_ok!(import_commitment(chain.header(i + 1))); + } + + // try to import next header: it fails because we are no longer accepting commitments + assert_noop!( + import_commitment(chain.header(max_requests + 1)), + Error::::TooManyRequests, + ); + + // when next block is "started", we allow import of next header + next_block(); + assert_ok!(import_commitment(chain.header(max_requests + 1))); + + // but we can't import two headers until next block and so on + assert_noop!( + import_commitment(chain.header(max_requests + 2)), + Error::::TooManyRequests, + ); + }) + } + + #[test] + fn fails_to_import_commitment_if_not_initialized() { + run_test(|| { + assert_noop!( + import_commitment(ChainBuilder::new(1).append_finalized_header().to_header()), + Error::::NotInitialized, + ); + }) + } + + #[test] + fn submit_commitment_works_with_long_chain_with_handoffs() { + run_test_with_initialize(3, || { + let chain = ChainBuilder::new(3) + .append_finalized_header() + .append_default_headers(16) // 2..17 + .append_finalized_header() // 18 + .append_default_headers(16) // 19..34 + .append_handoff_header(9) // 35 + .append_default_headers(8) // 36..43 + .append_finalized_header() // 44 + .append_default_headers(8) // 45..52 + .append_handoff_header(17) // 53 + .append_default_headers(4) // 54..57 + .append_finalized_header() // 58 + .append_default_headers(4); // 59..63 + import_header_chain(chain.to_chain()); + + assert_eq!( + ImportedCommitmentsInfo::::get().unwrap().best_block_number, + 58 + ); + assert_eq!(CurrentAuthoritySetInfo::::get().id, 2); + assert_eq!(CurrentAuthoritySetInfo::::get().len, 17); + + let imported_commitment = ImportedCommitments::::get(58).unwrap(); + assert_eq!( + imported_commitment, + bp_beefy::ImportedCommitment { + parent_number_and_hash: (57, chain.header(57).header.hash()), + mmr_root: chain.header(58).mmr_root, + }, + ); + }) + } + + #[test] + fn commitment_pruning_works() { + run_test_with_initialize(3, || { + let commitments_to_keep = >::CommitmentsToKeep::get(); + let commitments_to_import: Vec = ChainBuilder::new(3) + .append_finalized_headers(commitments_to_keep as usize + 2) + .to_chain(); + + // import exactly `CommitmentsToKeep` commitments + for index in 0..commitments_to_keep { + next_block(); + import_commitment(commitments_to_import[index as usize].clone()) + .expect("must succeed"); + assert_eq!( + ImportedCommitmentsInfo::::get().unwrap().next_block_number_index, + (index + 1) % commitments_to_keep + ); + } + + // ensure that all commitments are in the storage + assert_eq!( + ImportedCommitmentsInfo::::get().unwrap().best_block_number, + commitments_to_keep as TestBridgedBlockNumber + ); + assert_eq!( + ImportedCommitmentsInfo::::get().unwrap().next_block_number_index, + 0 + ); + for index in 0..commitments_to_keep { + assert!(ImportedCommitments::::get( + index as TestBridgedBlockNumber + 1 + ) + .is_some()); + assert_eq!( + ImportedBlockNumbers::::get(index), + Some(index + 1).map(Into::into) + ); + } + + // import next commitment + next_block(); + import_commitment(commitments_to_import[commitments_to_keep as usize].clone()) + .expect("must succeed"); + assert_eq!( + ImportedCommitmentsInfo::::get().unwrap().next_block_number_index, + 1 + ); + assert!(ImportedCommitments::::get( + commitments_to_keep as TestBridgedBlockNumber + 1 + ) + .is_some()); + assert_eq!( + ImportedBlockNumbers::::get(0), + Some(commitments_to_keep + 1).map(Into::into) + ); + // the side effect of the import is that the commitment#1 is pruned + assert!(ImportedCommitments::::get(1).is_none()); + + // import next commitment + next_block(); + import_commitment(commitments_to_import[commitments_to_keep as usize + 1].clone()) + .expect("must succeed"); + assert_eq!( + ImportedCommitmentsInfo::::get().unwrap().next_block_number_index, + 2 + ); + assert!(ImportedCommitments::::get( + commitments_to_keep as TestBridgedBlockNumber + 2 + ) + .is_some()); + assert_eq!( + ImportedBlockNumbers::::get(1), + Some(commitments_to_keep + 2).map(Into::into) + ); + // the side effect of the import is that the commitment#2 is pruned + assert!(ImportedCommitments::::get(1).is_none()); + assert!(ImportedCommitments::::get(2).is_none()); + }); + } + + generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); +} diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs new file mode 100644 index 0000000000000..927c39ff9aad4 --- /dev/null +++ b/modules/beefy/src/mock.rs @@ -0,0 +1,226 @@ +// 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 . + +use crate as beefy; +use crate::{ + utils::get_authorities_mmr_root, BridgedBeefyAuthoritySet, BridgedBeefyAuthoritySetInfo, + BridgedBeefyCommitmentHasher, BridgedBeefyMmrLeafExtra, BridgedBeefySignedCommitment, + BridgedMmrHash, BridgedMmrHashing, BridgedMmrProof, +}; + +use bp_beefy::{BeefyValidatorSignatureOf, ChainWithBeefy, Commitment, MmrDataOrHash}; +use bp_runtime::{BasicOperatingMode, Chain}; +use codec::Encode; +use frame_support::{construct_runtime, parameter_types, weights::Weight}; +use sp_core::{sr25519::Signature, Pair}; +use sp_runtime::{ + testing::{Header, H256}, + traits::{BlakeTwo256, Hash, IdentityLookup}, + Perbill, +}; + +pub use beefy_primitives::crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; +use sp_core::crypto::Wraps; +use sp_runtime::traits::Keccak256; + +pub type TestAccountId = u64; +pub type TestBridgedBlockNumber = u64; +pub type TestBridgedBlockHash = H256; +pub type TestBridgedHeader = Header; +pub type TestBridgedAuthoritySetInfo = BridgedBeefyAuthoritySetInfo; +pub type TestBridgedValidatorSet = BridgedBeefyAuthoritySet; +pub type TestBridgedCommitment = BridgedBeefySignedCommitment; +pub type TestBridgedValidatorSignature = BeefyValidatorSignatureOf; +pub type TestBridgedCommitmentHasher = BridgedBeefyCommitmentHasher; +pub type TestBridgedMmrHashing = BridgedMmrHashing; +pub type TestBridgedMmrHash = BridgedMmrHash; +pub type TestBridgedBeefyMmrLeafExtra = BridgedBeefyMmrLeafExtra; +pub type TestBridgedMmrProof = BridgedMmrProof; +pub type TestBridgedRawMmrLeaf = beefy_primitives::mmr::MmrLeaf< + TestBridgedBlockNumber, + TestBridgedBlockHash, + TestBridgedMmrHash, + TestBridgedBeefyMmrLeafExtra, +>; +pub type TestBridgedMmrNode = MmrDataOrHash; + +type TestBlock = frame_system::mocking::MockBlock; +type TestUncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + +construct_runtime! { + pub enum TestRuntime where + Block = TestBlock, + NodeBlock = TestBlock, + UncheckedExtrinsic = TestUncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Beefy: beefy::{Pallet}, + } +} + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} + +impl frame_system::Config for TestRuntime { + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type RuntimeCall = RuntimeCall; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = TestAccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = (); + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = frame_support::traits::Everything; + type SystemWeightInfo = (); + type DbWeight = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl beefy::Config for TestRuntime { + type MaxRequests = frame_support::traits::ConstU32<16>; + type BridgedChain = TestBridgedChain; + type CommitmentsToKeep = frame_support::traits::ConstU32<16>; +} + +#[derive(Debug)] +pub struct TestBridgedChain; + +impl Chain for TestBridgedChain { + type BlockNumber = TestBridgedBlockNumber; + type Hash = H256; + type Hasher = BlakeTwo256; + type Header = ::Header; + + type AccountId = TestAccountId; + type Balance = u64; + type Index = u64; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + fn max_extrinsic_weight() -> Weight { + unreachable!() + } +} + +impl ChainWithBeefy for TestBridgedChain { + type CommitmentHasher = Keccak256; + type MmrHashing = Keccak256; + type MmrHash = ::Output; + type BeefyMmrLeafExtra = (); + type AuthorityId = BeefyId; + type Signature = beefy_primitives::crypto::AuthoritySignature; + type AuthorityIdToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; +} + +/// Run test within test runtime. +pub fn run_test(test: impl FnOnce() -> T) -> T { + sp_io::TestExternalities::new(Default::default()).execute_with(test) +} + +/// Initialize pallet and run test. +pub fn run_test_with_initialize(initial_validators_count: u32, test: impl FnOnce() -> T) -> T { + run_test(|| { + let validators = validator_ids(0, initial_validators_count); + let authority_set = authority_set_info(0, &validators); + + crate::Pallet::::initialize( + RuntimeOrigin::root(), + bp_beefy::InitializationData { + operating_mode: BasicOperatingMode::Normal, + best_block_number: 0, + authority_set, + }, + ) + .expect("initialization data is correct"); + + test() + }) +} + +/// Import given commitment. +pub fn import_commitment( + header: crate::mock_chain::HeaderAndCommitment, +) -> sp_runtime::DispatchResult { + crate::Pallet::::submit_commitment( + RuntimeOrigin::signed(1), + header + .commitment + .expect("thou shall not call import_commitment on header without commitment"), + header.validator_set, + Box::new(header.leaf), + header.leaf_proof, + ) +} + +pub fn validator_pairs(index: u32, count: u32) -> Vec { + (index..index + count) + .map(|index| { + let mut seed = [1u8; 32]; + seed[0..8].copy_from_slice(&(index as u64).encode()); + BeefyPair::from_seed(&seed) + }) + .collect() +} + +/// Return identifiers of validators, starting at given index. +pub fn validator_ids(index: u32, count: u32) -> Vec { + validator_pairs(index, count).into_iter().map(|pair| pair.public()).collect() +} + +pub fn authority_set_info(id: u64, validators: &Vec) -> TestBridgedAuthoritySetInfo { + let merkle_root = get_authorities_mmr_root::(validators.iter()); + + TestBridgedAuthoritySetInfo { id, len: validators.len() as u32, root: merkle_root } +} + +/// Sign BEEFY commitment. +pub fn sign_commitment( + commitment: Commitment, + validator_pairs: &[BeefyPair], + signature_count: usize, +) -> TestBridgedCommitment { + let total_validators = validator_pairs.len(); + let random_validators = + rand::seq::index::sample(&mut rand::thread_rng(), total_validators, signature_count); + + let commitment_hash = TestBridgedCommitmentHasher::hash(&commitment.encode()); + let mut signatures = vec![None; total_validators]; + for validator_idx in random_validators.iter() { + let validator = &validator_pairs[validator_idx]; + signatures[validator_idx] = + Some(validator.as_inner_ref().sign_prehashed(commitment_hash.as_fixed_bytes()).into()); + } + + TestBridgedCommitment { commitment, signatures } +} diff --git a/modules/beefy/src/mock_chain.rs b/modules/beefy/src/mock_chain.rs new file mode 100644 index 0000000000000..4896f9bf90925 --- /dev/null +++ b/modules/beefy/src/mock_chain.rs @@ -0,0 +1,299 @@ +// 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 . + +//! Utilities to build bridged chain and BEEFY+MMR structures. + +use crate::{ + mock::{ + sign_commitment, validator_pairs, BeefyPair, TestBridgedBlockNumber, TestBridgedCommitment, + TestBridgedHeader, TestBridgedMmrHash, TestBridgedMmrHashing, TestBridgedMmrNode, + TestBridgedMmrProof, TestBridgedRawMmrLeaf, TestBridgedValidatorSet, + TestBridgedValidatorSignature, TestRuntime, + }, + utils::get_authorities_mmr_root, +}; + +use beefy_primitives::mmr::{BeefyNextAuthoritySet, MmrLeafVersion}; +use bp_beefy::{BeefyPayload, Commitment, ValidatorSetId, MMR_ROOT_PAYLOAD_ID}; +use codec::Encode; +use pallet_mmr::NodeIndex; +use rand::Rng; +use sp_core::Pair; +use sp_runtime::traits::{Hash, Header as HeaderT}; +use std::collections::HashMap; + +#[derive(Debug, Clone)] +pub struct HeaderAndCommitment { + pub header: TestBridgedHeader, + pub commitment: Option, + pub validator_set: TestBridgedValidatorSet, + pub leaf: TestBridgedRawMmrLeaf, + pub leaf_proof: TestBridgedMmrProof, + pub mmr_root: TestBridgedMmrHash, +} + +impl HeaderAndCommitment { + pub fn customize_signatures( + &mut self, + f: impl FnOnce(&mut Vec>), + ) { + if let Some(commitment) = &mut self.commitment { + f(&mut commitment.signatures); + } + } + + pub fn customize_commitment( + &mut self, + f: impl FnOnce(&mut Commitment), + validator_pairs: &[BeefyPair], + signature_count: usize, + ) { + if let Some(mut commitment) = self.commitment.take() { + f(&mut commitment.commitment); + self.commitment = + Some(sign_commitment(commitment.commitment, validator_pairs, signature_count)); + } + } +} + +pub struct ChainBuilder { + headers: Vec, + validator_set_id: ValidatorSetId, + validator_keys: Vec, + mmr: mmr_lib::MMR, +} + +struct BridgedMmrStorage { + nodes: HashMap, +} + +impl mmr_lib::MMRStore for BridgedMmrStorage { + fn get_elem(&self, pos: NodeIndex) -> mmr_lib::Result> { + Ok(self.nodes.get(&pos).cloned()) + } + + fn append(&mut self, pos: NodeIndex, elems: Vec) -> mmr_lib::Result<()> { + for (i, elem) in elems.into_iter().enumerate() { + self.nodes.insert(pos + i as NodeIndex, elem); + } + Ok(()) + } +} + +impl ChainBuilder { + /// Creates new chain builder with given validator set size. + pub fn new(initial_validators_count: u32) -> Self { + ChainBuilder { + headers: Vec::new(), + validator_set_id: 0, + validator_keys: validator_pairs(0, initial_validators_count), + mmr: mmr_lib::MMR::new(0, BridgedMmrStorage { nodes: HashMap::new() }), + } + } + + /// Get header with given number. + pub fn header(&self, number: TestBridgedBlockNumber) -> HeaderAndCommitment { + self.headers[number as usize - 1].clone() + } + + /// Returns single built header. + pub fn to_header(&self) -> HeaderAndCommitment { + assert_eq!(self.headers.len(), 1); + self.headers[0].clone() + } + + /// Returns built chain. + pub fn to_chain(&self) -> Vec { + self.headers.clone() + } + + /// Appends header, that has been finalized by BEEFY (so it has a linked signed commitment). + pub fn append_finalized_header(self) -> Self { + let next_validator_set_id = self.validator_set_id; + let next_validator_keys = self.validator_keys.clone(); + HeaderBuilder::with_chain(self, next_validator_set_id, next_validator_keys).finalize() + } + + /// Append multiple finalized headers at once. + pub fn append_finalized_headers(mut self, count: usize) -> Self { + for _ in 0..count { + self = self.append_finalized_header(); + } + self + } + + /// Appends header, that enacts new validator set. + /// + /// Such headers are explicitly finalized by BEEFY. + pub fn append_handoff_header(self, next_validators_len: u32) -> Self { + let new_validator_set_id = self.validator_set_id + 1; + let new_validator_pairs = + validator_pairs(rand::thread_rng().gen::() % (u32::MAX / 2), next_validators_len); + + HeaderBuilder::with_chain(self, new_validator_set_id, new_validator_pairs).finalize() + } + + /// Append several default header without commitment. + pub fn append_default_headers(mut self, count: usize) -> Self { + for _ in 0..count { + let next_validator_set_id = self.validator_set_id; + let next_validator_keys = self.validator_keys.clone(); + self = + HeaderBuilder::with_chain(self, next_validator_set_id, next_validator_keys).build() + } + self + } +} + +/// Custom header builder. +pub struct HeaderBuilder { + chain: ChainBuilder, + header: TestBridgedHeader, + leaf: TestBridgedRawMmrLeaf, + leaf_proof: Option, + next_validator_set_id: ValidatorSetId, + next_validator_keys: Vec, +} + +impl HeaderBuilder { + fn with_chain( + chain: ChainBuilder, + next_validator_set_id: ValidatorSetId, + next_validator_keys: Vec, + ) -> Self { + // we're starting with header#1, since header#0 is always finalized + let header_number = chain.headers.len() as TestBridgedBlockNumber + 1; + let header = TestBridgedHeader::new( + header_number, + Default::default(), + Default::default(), + chain.headers.last().map(|h| h.header.hash()).unwrap_or_default(), + Default::default(), + ); + + let next_validators = + next_validator_keys.iter().map(|pair| pair.public()).collect::>(); + let next_validators_mmr_root = + get_authorities_mmr_root::(next_validators.iter()); + let leaf = beefy_primitives::mmr::MmrLeaf { + version: MmrLeafVersion::new(1, 0), + parent_number_and_hash: (header.number().saturating_sub(1), *header.parent_hash()), + beefy_next_authority_set: BeefyNextAuthoritySet { + id: next_validator_set_id, + len: next_validators.len() as u32, + root: next_validators_mmr_root, + }, + leaf_extra: (), + }; + + HeaderBuilder { + chain, + header, + leaf, + leaf_proof: None, + next_validator_keys, + next_validator_set_id, + } + } + + /// Customize generated proof of header MMR leaf. + /// + /// Can only be called once. + pub fn customize_proof( + mut self, + f: impl FnOnce(TestBridgedMmrProof) -> TestBridgedMmrProof, + ) -> Self { + assert!(self.leaf_proof.is_none()); + + let leaf_hash = TestBridgedMmrHashing::hash(&self.leaf.encode()); + let node = TestBridgedMmrNode::Hash(leaf_hash); + let leaf_position = self.chain.mmr.push(node).unwrap(); + + let proof = self.chain.mmr.gen_proof(vec![leaf_position]).unwrap(); + // genesis has no leaf => leaf index is header number minus 1 + let leaf_index = *self.header.number() - 1; + let leaf_count = *self.header.number(); + self.leaf_proof = Some(f(TestBridgedMmrProof { + leaf_index, + leaf_count, + items: proof.proof_items().iter().map(|i| i.hash()).collect(), + })); + + self + } + + /// Build header without commitment. + pub fn build(mut self) -> ChainBuilder { + if self.leaf_proof.is_none() { + self = self.customize_proof(|proof| proof); + } + + let validators = + self.chain.validator_keys.iter().map(|pair| pair.public()).collect::>(); + self.chain.headers.push(HeaderAndCommitment { + header: self.header, + commitment: None, + validator_set: TestBridgedValidatorSet::new(validators, self.chain.validator_set_id) + .unwrap(), + leaf: self.leaf, + leaf_proof: self.leaf_proof.expect("guaranteed by the customize_proof call above; qed"), + mmr_root: self.chain.mmr.get_root().unwrap().hash(), + }); + + self.chain.validator_set_id = self.next_validator_set_id; + self.chain.validator_keys = self.next_validator_keys; + + self.chain + } + + /// Build header with commitment. + pub fn finalize(self) -> ChainBuilder { + let validator_count = self.chain.validator_keys.len(); + let current_validator_set_id = self.chain.validator_set_id; + let current_validator_set_keys = self.chain.validator_keys.clone(); + let mut chain = self.build(); + + let last_header = chain.headers.last_mut().expect("added by append_header; qed"); + last_header.commitment = Some(sign_commitment( + Commitment { + payload: BeefyPayload::from_single_entry( + MMR_ROOT_PAYLOAD_ID, + chain.mmr.get_root().unwrap().hash().encode(), + ), + block_number: *last_header.header.number(), + validator_set_id: current_validator_set_id, + }, + ¤t_validator_set_keys, + validator_count * 2 / 3 + 1, + )); + + chain + } +} + +/// Default Merging & Hashing behavior for MMR. +pub struct BridgedMmrHashMerge; + +impl mmr_lib::Merge for BridgedMmrHashMerge { + type Item = TestBridgedMmrNode; + + fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item { + let mut concat = left.hash().as_ref().to_vec(); + concat.extend_from_slice(right.hash().as_ref()); + + TestBridgedMmrNode::Hash(TestBridgedMmrHashing::hash(&concat)) + } +} diff --git a/modules/beefy/src/utils.rs b/modules/beefy/src/utils.rs new file mode 100644 index 0000000000000..c8a7d2cee140a --- /dev/null +++ b/modules/beefy/src/utils.rs @@ -0,0 +1,363 @@ +use crate::{ + BridgedBeefyAuthorityId, BridgedBeefyAuthoritySet, BridgedBeefyAuthoritySetInfo, + BridgedBeefyCommitmentHasher, BridgedBeefyMmrLeaf, BridgedBeefySignedCommitment, BridgedChain, + BridgedMmrHash, BridgedMmrHashing, BridgedMmrProof, Config, Error, LOG_TARGET, +}; +use bp_beefy::{merkle_root, verify_mmr_leaves_proof, BeefyVerify, MmrDataOrHash, MmrProof}; +use codec::Encode; +use frame_support::ensure; +use sp_runtime::traits::{Convert, Hash}; +use sp_std::{vec, vec::Vec}; + +type BridgedMmrDataOrHash = MmrDataOrHash, BridgedBeefyMmrLeaf>; +/// A way to encode validator id to the BEEFY merkle tree leaf. +type BridgedBeefyAuthorityIdToMerkleLeaf = + bp_beefy::BeefyAuthorityIdToMerkleLeafOf>; + +/// Get the MMR root for a collection of validators. +pub(crate) fn get_authorities_mmr_root< + 'a, + T: Config, + I: 'static, + V: Iterator>, +>( + authorities: V, +) -> BridgedMmrHash { + let merkle_leafs = authorities + .cloned() + .map(BridgedBeefyAuthorityIdToMerkleLeaf::::convert) + .collect::>(); + merkle_root::, _>(merkle_leafs) +} + +fn verify_authority_set, I: 'static>( + authority_set_info: &BridgedBeefyAuthoritySetInfo, + authority_set: &BridgedBeefyAuthoritySet, +) -> Result<(), Error> { + ensure!(authority_set.id() == authority_set_info.id, Error::::InvalidValidatorSetId); + ensure!( + authority_set.len() == authority_set_info.len as usize, + Error::::InvalidValidatorSetLen + ); + + // Ensure that the authority set that signed the commitment is the expected one. + let root = get_authorities_mmr_root::(authority_set.validators().iter()); + ensure!(root == authority_set_info.root, Error::::InvalidValidatorSetRoot); + + Ok(()) +} + +/// Number of correct signatures, required from given validators set to accept signed +/// commitment. +/// +/// We're using 'conservative' approach here, where signatures of `2/3+1` validators are +/// required.. +pub(crate) fn signatures_required, I: 'static>(validators_len: usize) -> usize { + validators_len - validators_len.saturating_sub(1) / 3 +} + +fn verify_signatures, I: 'static>( + commitment: &BridgedBeefySignedCommitment, + authority_set: &BridgedBeefyAuthoritySet, +) -> Result<(), Error> { + ensure!( + commitment.signatures.len() == authority_set.len(), + Error::::InvalidCommitmentSignaturesLen + ); + + // Ensure that the commitment was signed by enough authorities. + let msg = commitment.commitment.encode(); + let mut missing_signatures = signatures_required::(authority_set.len()); + for (idx, (authority, maybe_sig)) in + authority_set.validators().iter().zip(commitment.signatures.iter()).enumerate() + { + if let Some(sig) = maybe_sig { + if BeefyVerify::>::verify(sig, &msg, authority) { + missing_signatures = missing_signatures.saturating_sub(1); + if missing_signatures == 0 { + break + } + } else { + log::debug!( + target: LOG_TARGET, + "Signed commitment contains incorrect signature of validator {} ({:?}): {:?}", + idx, + authority, + sig, + ); + } + } + } + ensure!(missing_signatures == 0, Error::::NotEnoughCorrectSignatures); + + Ok(()) +} + +/// Extract MMR root from commitment payload. +fn extract_mmr_root, I: 'static>( + commitment: &BridgedBeefySignedCommitment, +) -> Result, Error> { + commitment + .commitment + .payload + .get_decoded(&bp_beefy::MMR_ROOT_PAYLOAD_ID) + .ok_or(Error::MmrRootMissingFromCommitment) +} + +pub(crate) fn verify_commitment, I: 'static>( + commitment: &BridgedBeefySignedCommitment, + authority_set_info: &BridgedBeefyAuthoritySetInfo, + authority_set: &BridgedBeefyAuthoritySet, +) -> Result, Error> { + // Ensure that the commitment is signed by the best known BEEFY validator set. + ensure!( + commitment.commitment.validator_set_id == authority_set_info.id, + Error::::InvalidCommitmentValidatorSetId + ); + ensure!( + commitment.signatures.len() == authority_set_info.len as usize, + Error::::InvalidCommitmentSignaturesLen + ); + + verify_authority_set(authority_set_info, authority_set)?; + verify_signatures(commitment, authority_set)?; + + extract_mmr_root(commitment) +} + +/// Verify MMR proof of given leaf. +pub(crate) fn verify_beefy_mmr_leaf, I: 'static>( + mmr_leaf: &BridgedBeefyMmrLeaf, + mmr_proof: BridgedMmrProof, + mmr_root: BridgedMmrHash, +) -> Result<(), Error> { + let mmr_proof_leaf_index = mmr_proof.leaf_index; + let mmr_proof_leaf_count = mmr_proof.leaf_count; + let mmr_proof_length = mmr_proof.items.len(); + + // Verify the mmr proof for the provided leaf. + let mmr_leaf_hash = BridgedMmrHashing::::hash(&mmr_leaf.encode()); + verify_mmr_leaves_proof( + mmr_root, + vec![BridgedMmrDataOrHash::::Hash(mmr_leaf_hash)], + MmrProof::into_batch_proof(mmr_proof), + ) + .map_err(|e| { + log::error!( + target: LOG_TARGET, + "MMR proof of leaf {:?} (root: {:?}, leaf: {}, leaf count: {}, len: {}) \ + verification has failed with error: {:?}", + mmr_leaf_hash, + mmr_root, + mmr_proof_leaf_index, + mmr_proof_leaf_count, + mmr_proof_length, + e, + ); + + Error::::MmrProofVerificationFailed + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{mock::*, mock_chain::*, *}; + use beefy_primitives::ValidatorSet; + use bp_beefy::{BeefyPayload, MMR_ROOT_PAYLOAD_ID}; + use frame_support::{assert_noop, assert_ok}; + + #[test] + fn submit_commitment_checks_metadata() { + run_test_with_initialize(8, || { + // Fails if `commitment.commitment.validator_set_id` differs. + let mut header = ChainBuilder::new(8).append_finalized_header().to_header(); + header.customize_commitment( + |commitment| { + commitment.validator_set_id += 1; + }, + &validator_pairs(0, 8), + 6, + ); + assert_noop!( + import_commitment(header), + Error::::InvalidCommitmentValidatorSetId, + ); + + // Fails if `commitment.signatures.len()` differs. + let mut header = ChainBuilder::new(8).append_finalized_header().to_header(); + header.customize_signatures(|signatures| { + signatures.pop(); + }); + assert_noop!( + import_commitment(header), + Error::::InvalidCommitmentSignaturesLen, + ); + }); + } + + #[test] + fn submit_commitment_checks_validator_set() { + run_test_with_initialize(8, || { + // Fails if `ValidatorSet::id` differs. + let mut header = ChainBuilder::new(8).append_finalized_header().to_header(); + header.validator_set = ValidatorSet::new(validator_ids(0, 8), 1).unwrap(); + assert_noop!( + import_commitment(header), + Error::::InvalidValidatorSetId, + ); + + // Fails if `ValidatorSet::len()` differs. + let mut header = ChainBuilder::new(8).append_finalized_header().to_header(); + header.validator_set = ValidatorSet::new(validator_ids(0, 5), 0).unwrap(); + assert_noop!( + import_commitment(header), + Error::::InvalidValidatorSetLen, + ); + + // Fails if the validators differ. + let mut header = ChainBuilder::new(8).append_finalized_header().to_header(); + header.validator_set = ValidatorSet::new(validator_ids(3, 8), 0).unwrap(); + assert_noop!( + import_commitment(header), + Error::::InvalidValidatorSetRoot, + ); + }); + } + + #[test] + fn submit_commitment_checks_signatures() { + run_test_with_initialize(20, || { + // Fails when there aren't enough signatures. + let mut header = ChainBuilder::new(20).append_finalized_header().to_header(); + header.customize_signatures(|signatures| { + let first_signature_idx = signatures.iter().position(Option::is_some).unwrap(); + signatures[first_signature_idx] = None; + }); + assert_noop!( + import_commitment(header), + Error::::NotEnoughCorrectSignatures, + ); + + // Fails when there aren't enough correct signatures. + let mut header = ChainBuilder::new(20).append_finalized_header().to_header(); + header.customize_signatures(|signatures| { + let first_signature_idx = signatures.iter().position(Option::is_some).unwrap(); + let last_signature_idx = signatures.len() - + signatures.iter().rev().position(Option::is_some).unwrap() - + 1; + signatures[first_signature_idx] = signatures[last_signature_idx].clone(); + }); + assert_noop!( + import_commitment(header), + Error::::NotEnoughCorrectSignatures, + ); + + // Returns Ok(()) when there are enough signatures, even if some are incorrect. + let mut header = ChainBuilder::new(20).append_finalized_header().to_header(); + header.customize_signatures(|signatures| { + let first_signature_idx = signatures.iter().position(Option::is_some).unwrap(); + let first_missing_signature_idx = + signatures.iter().position(Option::is_none).unwrap(); + signatures[first_missing_signature_idx] = signatures[first_signature_idx].clone(); + }); + assert_ok!(import_commitment(header)); + }); + } + + #[test] + fn submit_commitment_checks_mmr_proof() { + run_test_with_initialize(1, || { + let validators = validator_pairs(0, 1); + + // Fails if leaf is not for parent. + let mut header = ChainBuilder::new(1).append_finalized_header().to_header(); + header.leaf.parent_number_and_hash.0 += 1; + assert_noop!( + import_commitment(header), + Error::::MmrProofVerificationFailed, + ); + + // Fails if mmr proof is incorrect. + let mut header = ChainBuilder::new(1).append_finalized_header().to_header(); + header.leaf_proof.leaf_index += 1; + assert_noop!( + import_commitment(header), + Error::::MmrProofVerificationFailed, + ); + + // Fails if mmr root is incorrect. + let mut header = ChainBuilder::new(1).append_finalized_header().to_header(); + // Replace MMR root with zeroes. + header.customize_commitment( + |commitment| { + commitment.payload = + BeefyPayload::from_single_entry(MMR_ROOT_PAYLOAD_ID, [0u8; 32].encode()); + }, + &validators, + 1, + ); + assert_noop!( + import_commitment(header), + Error::::MmrProofVerificationFailed, + ); + }); + } + + #[test] + fn submit_commitment_extracts_mmr_root() { + run_test_with_initialize(1, || { + let validators = validator_pairs(0, 1); + + // Fails if there is no mmr root in the payload. + let mut header = ChainBuilder::new(1).append_finalized_header().to_header(); + // Remove MMR root from the payload. + header.customize_commitment( + |commitment| { + commitment.payload = BeefyPayload::from_single_entry(*b"xy", vec![]); + }, + &validators, + 1, + ); + assert_noop!( + import_commitment(header), + Error::::MmrRootMissingFromCommitment, + ); + + // Fails if mmr root can't be decoded. + let mut header = ChainBuilder::new(1).append_finalized_header().to_header(); + // MMR root is a 32-byte array and we have replaced it with single byte + header.customize_commitment( + |commitment| { + commitment.payload = + BeefyPayload::from_single_entry(MMR_ROOT_PAYLOAD_ID, vec![42]); + }, + &validators, + 1, + ); + assert_noop!( + import_commitment(header), + Error::::MmrRootMissingFromCommitment, + ); + }); + } + + #[test] + fn submit_commitment_stores_valid_data() { + run_test_with_initialize(20, || { + let header = ChainBuilder::new(20).append_handoff_header(30).to_header(); + assert_ok!(import_commitment(header.clone())); + + assert_eq!(ImportedCommitmentsInfo::::get().unwrap().best_block_number, 1); + assert_eq!(CurrentAuthoritySetInfo::::get().id, 1); + assert_eq!(CurrentAuthoritySetInfo::::get().len, 30); + assert_eq!( + ImportedCommitments::::get(1).unwrap(), + bp_beefy::ImportedCommitment { + parent_number_and_hash: (0, [0; 32].into()), + mmr_root: header.mmr_root, + }, + ); + }); + } +} diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml new file mode 100644 index 0000000000000..6b169e6611321 --- /dev/null +++ b/primitives/beefy/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "bp-beefy" +description = "Primitives of pallet-bridge-beefy module." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } +scale-info = { version = "2.0.1", default-features = false, features = ["bit-vec", "derive"] } +serde = { version = "1.0", optional = true } +static_assertions = "1.1" + +# Bridge Dependencies + +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Dependencies + +beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-application-crypto = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "beefy-primitives/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "pallet-beefy-mmr/std", + "pallet-mmr/std", + "scale-info/std", + "serde", + "sp-application-crypto/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std" +] diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs new file mode 100644 index 0000000000000..a0a096bdce17c --- /dev/null +++ b/primitives/beefy/src/lib.rs @@ -0,0 +1,152 @@ +// 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 . + +//! Primitives that are used to interact with BEEFY bridge pallet. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +pub use beefy_merkle_tree::{merkle_root, Keccak256 as BeefyKeccak256}; +pub use beefy_primitives::{ + crypto::{AuthorityId as EcdsaValidatorId, AuthoritySignature as EcdsaValidatorSignature}, + known_payloads::MMR_ROOT_ID as MMR_ROOT_PAYLOAD_ID, + mmr::{BeefyAuthoritySet, MmrLeafVersion}, + BeefyAuthorityId, BeefyVerify, Commitment, Payload as BeefyPayload, SignedCommitment, + ValidatorSet, ValidatorSetId, BEEFY_ENGINE_ID, +}; +pub use pallet_beefy_mmr::BeefyEcdsaToEthereum; +pub use pallet_mmr::{ + primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof}, + verify_leaves_proof as verify_mmr_leaves_proof, +}; + +use bp_runtime::{BasicOperatingMode, BlockNumberOf, Chain, HashOf}; +use codec::{Decode, Encode}; +use frame_support::Parameter; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{Convert, MaybeSerializeDeserialize}, + RuntimeDebug, +}; +use sp_std::prelude::*; + +/// Substrate-based chain with BEEFY && MMR pallets deployed. +/// +/// Both BEEFY and MMR pallets and their clients may be configured to use different +/// primitives. Some of types can be configured in low-level pallets, but are constrained +/// when BEEFY+MMR bundle is used. +pub trait ChainWithBeefy: Chain { + /// The hashing algorithm used to compute the digest of the BEEFY commitment. + /// + /// Corresponds to the hashing algorithm, used by `beefy_gadget::BeefyKeystore`. + type CommitmentHasher: sp_runtime::traits::Hash; + + /// The hashing algorithm used to build the MMR. + /// + /// The same algorithm is also used to compute merkle roots in BEEFY + /// (e.g. validator addresses root in leaf data). + /// + /// Corresponds to the `Hashing` field of the `pallet-mmr` configuration. + type MmrHashing: sp_runtime::traits::Hash; + + /// The output type of the hashing algorithm used to build the MMR. + /// + /// This type is actually stored in the MMR. + + /// Corresponds to the `Hash` field of the `pallet-mmr` configuration. + type MmrHash: sp_std::hash::Hash + + Parameter + + Copy + + AsRef<[u8]> + + Default + + MaybeSerializeDeserialize; + + /// The type expected for the MMR leaf extra data. + type BeefyMmrLeafExtra: Parameter; + + /// A way to identify a BEEFY validator. + /// + /// Corresponds to the `BeefyId` field of the `pallet-beefy` configuration. + type AuthorityId: BeefyAuthorityId + Parameter; + + /// The signature type used by BEEFY. + /// + /// Corresponds to the `BeefyId` field of the `pallet-beefy` configuration. + type Signature: BeefyVerify + Parameter; + + /// A way to convert validator id to its raw representation in the BEEFY merkle tree. + /// + /// Corresponds to the `BeefyAuthorityToMerkleLeaf` field of the `pallet-beefy-mmr` + /// configuration. + type AuthorityIdToMerkleLeaf: Convert>; +} + +/// BEEFY validator id used by given Substrate chain. +pub type BeefyAuthorityIdOf = ::AuthorityId; +/// BEEFY validator set, containing both validator identifiers and the numeric set id. +pub type BeefyAuthoritySetOf = ValidatorSet>; +/// BEEFY authority set, containing both validator identifiers and the numeric set id. +pub type BeefyAuthoritySetInfoOf = beefy_primitives::mmr::BeefyAuthoritySet>; +/// BEEFY validator signature used by given Substrate chain. +pub type BeefyValidatorSignatureOf = ::Signature; +/// Signed BEEFY commitment used by given Substrate chain. +pub type BeefySignedCommitmentOf = + SignedCommitment, BeefyValidatorSignatureOf>; +/// Hash algorithm, used to compute the digest of the BEEFY commitment before signing it. +pub type BeefyCommitmentHasher = ::CommitmentHasher; +/// Hash algorithm used in Beefy MMR construction by given Substrate chain. +pub type MmrHashingOf = ::MmrHashing; +/// Hash type, used in MMR construction by given Substrate chain. +pub type MmrHashOf = ::MmrHash; +/// BEEFY MMR proof type used by the given Substrate chain. +pub type MmrProofOf = MmrProof>; +/// The type of the MMR leaf extra data used by the given Substrate chain. +pub type BeefyMmrLeafExtraOf = ::BeefyMmrLeafExtra; +/// A way to convert a validator id to its raw representation in the BEEFY merkle tree, used by +/// the given Substrate chain. +pub type BeefyAuthorityIdToMerkleLeafOf = ::AuthorityIdToMerkleLeaf; +/// Actual type of leafs in the BEEFY MMR. +pub type BeefyMmrLeafOf = beefy_primitives::mmr::MmrLeaf< + BlockNumberOf, + HashOf, + MmrHashOf, + BeefyMmrLeafExtraOf, +>; + +/// Data required for initializing the BEEFY pallet. +/// +/// Provides the initial context that the bridge needs in order to know +/// where to start the sync process from. +#[derive(Encode, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct InitializationData { + /// Pallet operating mode. + pub operating_mode: BasicOperatingMode, + /// Number of the best block, finalized by BEEFY. + pub best_block_number: BlockNumber, + /// BEEFY authority set that will be finalizing descendants of the `best_beefy_block_number` + /// block. + pub authority_set: BeefyAuthoritySet, +} + +/// Basic data, stored by the pallet for every imported commitment. +#[derive(Encode, Decode, RuntimeDebug, PartialEq, TypeInfo)] +pub struct ImportedCommitment { + /// Block number and hash of the finalized block parent. + pub parent_number_and_hash: (BlockNumber, BlockHash), + /// MMR root at the imported block. + pub mmr_root: MmrHash, +} diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index c4d77b80febf8..b422e1545d670 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies +bp-beefy = { path = "../beefy", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } @@ -34,6 +35,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", [features] default = ["std"] std = [ + "bp-beefy/std", "bp-messages/std", "bp-runtime/std", "fixed-hash/std", diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 07cdb0c27f6ed..ceb4be21b81c6 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -20,6 +20,7 @@ mod millau_hash; +use bp_beefy::ChainWithBeefy; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; @@ -41,6 +42,7 @@ use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; +use sp_runtime::traits::Keccak256; pub use millau_hash::MillauHash; @@ -155,6 +157,16 @@ impl Chain for Millau { } } +impl ChainWithBeefy for Millau { + type CommitmentHasher = Keccak256; + type MmrHashing = Keccak256; + type MmrHash = ::Output; + type BeefyMmrLeafExtra = (); + type AuthorityId = bp_beefy::EcdsaValidatorId; + type Signature = bp_beefy::EcdsaValidatorSignature; + type AuthorityIdToMerkleLeaf = bp_beefy::BeefyEcdsaToEthereum; +} + /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. #[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] From 86265db43864f68a9f0dac28be6000d5fb3a62d8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Nov 2022 11:48:20 +0300 Subject: [PATCH 0813/1210] Complex parachain <> parachain relay (#1637) * complex parachain <> parachain relay * spelling --- .../src/cli/relay_headers_and_messages/mod.rs | 44 ++- .../parachain_to_parachain.rs | 281 ++++++++++++++++++ .../relay_to_parachain.rs | 43 ++- .../relay_to_relay.rs | 8 +- 4 files changed, 357 insertions(+), 19 deletions(-) create mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 49e9c5aa1560f..bdc92f984daf8 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -23,6 +23,8 @@ //! `declare_chain_to_parachain_bridge_schema` for the bridge. //! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it. +#[macro_use] +mod parachain_to_parachain; #[macro_use] mod relay_to_relay; #[macro_use] @@ -78,20 +80,26 @@ pub struct HeadersAndMessagesSharedParams { pub prometheus_params: PrometheusParams, } +/// Bridge parameters, shared by all bridge types. pub struct Full2WayBridgeCommonParams< Left: ChainWithTransactions + CliChain, Right: ChainWithTransactions + CliChain, > { + /// Shared parameters. pub shared: HeadersAndMessagesSharedParams, + /// Parameters of the left chain. pub left: BridgeEndCommonParams, + /// Parameters of the right chain. pub right: BridgeEndCommonParams, + /// Common metric parameters. pub metrics_params: MetricsParams, } impl Full2WayBridgeCommonParams { + /// Creates new bridge parameters from its components. pub fn new>( shared: HeadersAndMessagesSharedParams, left: BridgeEndCommonParams, @@ -105,14 +113,21 @@ impl { + /// Chain client. pub client: Client, + /// Transactions signer. pub sign: AccountKeyPairOf, + /// Transactions mortality. pub transactions_mortality: Option, + /// Account that "owns" messages pallet. pub messages_pallet_owner: Option>, + /// Accounts, which balances are exposed as metrics by the relay process. pub accounts: Vec>>, } +/// All data of the bidirectional complex relay. struct FullBridge< 'a, Source: ChainWithTransactions + CliChain, @@ -136,6 +151,7 @@ where AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom> + Into, { + /// Construct complex relay given it components. fn new( source: &'a mut BridgeEndCommonParams, target: &'a mut BridgeEndCommonParams, @@ -144,6 +160,7 @@ where Self { source, target, metrics_params, _phantom_data: Default::default() } } + /// Returns message relay parameters. fn messages_relay_params( &self, source_to_target_headers_relay: Arc>>, @@ -182,6 +199,12 @@ declare_chain_cli_schema!(RialtoParachainsToMillau, rialto_parachains_to_millau) declare_relay_to_relay_bridge_schema!(Millau, Rialto); declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); +/// Base portion of the bidirectional complex relay. +/// +/// This main purpose of extracting this trait is that in different relays the implementation +/// of `start_on_demand_headers_relayers` method will be different. But the number of +/// implementations is limited to relay <> relay, parachain <> relay and parachain <> parachain. +/// This trait allows us to reuse these implementations in different bridges. #[async_trait] trait Full2WayBridgeBase: Sized + Send + Sync { /// The CLI params for the bridge. @@ -191,10 +214,13 @@ trait Full2WayBridgeBase: Sized + Send + Sync { /// The right destination chain (it can be a relay or a parachain). type Right: ChainWithTransactions + CliChain>; + /// Reference to common relay parameters. fn common(&self) -> &Full2WayBridgeCommonParams; + /// Mutable reference to common relay parameters. fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams; + /// Start on-demand headers relays. async fn start_on_demand_headers_relayers( &mut self, ) -> anyhow::Result<( @@ -203,6 +229,7 @@ trait Full2WayBridgeBase: Sized + Send + Sync { )>; } +/// Bidirectional complex relay. #[async_trait] trait Full2WayBridge: Sized + Sync where @@ -211,6 +238,7 @@ where BalanceOf: TryFrom> + Into, BalanceOf: TryFrom> + Into, { + /// Base portion of the bidirectional complex relay. type Base: Full2WayBridgeBase; /// The left relay chain. @@ -222,17 +250,21 @@ where + ChainWithBalances + CliChain>; - // Left to Right bridge + /// Left to Right bridge. type L2R: MessagesCliBridge; - // Right to Left bridge + /// Right to Left bridge type R2L: MessagesCliBridge; + /// Construct new bridge. fn new(params: ::Params) -> anyhow::Result; + /// Reference to the base relay portion. fn base(&self) -> &Self::Base; + /// Mutable reference to the base relay portion. fn mut_base(&mut self) -> &mut Self::Base; + /// Creates and returns Left to Right complex relay. fn left_to_right(&mut self) -> FullBridge { let common = self.mut_base().mut_common(); FullBridge::<_, _, Self::L2R>::new( @@ -242,6 +274,7 @@ where ) } + /// Creates and returns Right to Left complex relay. fn right_to_left(&mut self) -> FullBridge { let common = self.mut_base().mut_common(); FullBridge::<_, _, Self::R2L>::new( @@ -251,6 +284,7 @@ where ) } + /// Start complex relay. async fn run(&mut self) -> anyhow::Result<()> { // Register standalone metrics. { @@ -324,6 +358,7 @@ where } } +/// Millau <> Rialto complex relay. pub struct MillauRialtoFull2WayBridge { base: ::Base, } @@ -349,6 +384,7 @@ impl Full2WayBridge for MillauRialtoFull2WayBridge { } } +/// Millau <> RialtoParachain complex relay. pub struct MillauRialtoParachainFull2WayBridge { base: ::Base, } @@ -374,10 +410,12 @@ impl Full2WayBridge for MillauRialtoParachainFull2WayBridge { } } -/// Start headers+messages relayer process. +/// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { + /// Millau <> Rialto relay. MillauRialto(MillauRialtoHeadersAndMessages), + /// Millau <> RialtoParachain relay. MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs new file mode 100644 index 0000000000000..9adc8fd662430 --- /dev/null +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -0,0 +1,281 @@ +// Copyright 2019-2022 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 . + +#![allow(unused_macros)] // TODO (https://github.com/paritytech/parity-bridges-common/issues/1629): remove me + +use async_trait::async_trait; +use std::sync::Arc; + +use crate::cli::{ + bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + CliChain, +}; +use bp_polkadot_core::parachains::ParaHash; +use bp_runtime::BlockNumberOf; +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client}; +use sp_core::Pair; +use substrate_relay_helper::{ + finality::SubstrateFinalitySyncPipeline, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, + }, + TaggedAccount, TransactionParams, +}; + +/// A base relay between two parachain from different consensus systems. +/// +/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 2 on-demand +/// parachain heads relay. +pub struct ParachainToParachainBridge< + L2R: MessagesCliBridge + ParachainToRelayHeadersCliBridge, + R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge, +> { + /// Parameters that are shared by all bridge types. + pub common: + Full2WayBridgeCommonParams<::Target, ::Target>, + /// Client of the left relay chain. + pub left_relay: Client<::SourceRelay>, + /// Client of the right relay chain. + pub right_relay: Client<::SourceRelay>, + + /// Override for right_relay->left headers signer. + pub right_headers_to_left_transaction_params: + TransactionParams::Target>>, + /// Override for left_relay->right headers signer. + pub left_headers_to_right_transaction_params: + TransactionParams::Target>>, + + /// Override for right->left parachains signer. + pub right_parachains_to_left_transaction_params: + TransactionParams::Target>>, + /// Override for left->right parachains signer. + pub left_parachains_to_right_transaction_params: + TransactionParams::Target>>, +} + +macro_rules! declare_parachain_to_parachain_bridge_schema { + // left-parachain, relay-chain-of-left-parachain, right-parachain, relay-chain-of-right-parachain + ($left_parachain:ident, $left_chain:ident, $right_parachain:ident, $right_chain:ident) => { + bp_runtime::paste::item! { + #[doc = $left_parachain ", " $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."] + #[derive(Debug, PartialEq, StructOpt)] + pub struct [<$left_parachain $right_parachain HeadersAndMessages>] { + // shared parameters + #[structopt(flatten)] + shared: HeadersAndMessagesSharedParams, + + #[structopt(flatten)] + left: [<$left_parachain ConnectionParams>], + #[structopt(flatten)] + left_relay: [<$left_chain ConnectionParams>], + + // default signer, which is always used to sign messages relay transactions on the left chain + #[structopt(flatten)] + left_sign: [<$left_parachain SigningParams>], + // signer used to sign parameter update transactions at the left parachain + #[structopt(flatten)] + left_messages_pallet_owner: [<$left_parachain MessagesPalletOwnerSigningParams>], + + #[structopt(flatten)] + right: [<$right_parachain ConnectionParams>], + #[structopt(flatten)] + right_relay: [<$right_chain ConnectionParams>], + + // default signer, which is always used to sign messages relay transactions on the right chain + #[structopt(flatten)] + right_sign: [<$right_parachain SigningParams>], + // signer used to sign parameter update transactions at the right parachain + #[structopt(flatten)] + right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>], + + // override for right_relay->left-parachain headers signer + #[structopt(flatten)] + right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_parachain SigningParams>], + // override for left_relay->right-parachain headers signer + #[structopt(flatten)] + left_relay_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], + + // override for right->left parachains signer + #[structopt(flatten)] + right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_parachain SigningParams>], + // override for left->right parachains signer + #[structopt(flatten)] + left_parachains_to_right_sign_override: [<$left_chain ParachainsTo $right_parachain SigningParams>], + } + + impl [<$left_chain $right_parachain HeadersAndMessages>] { + async fn into_bridge< + Left: ChainWithTransactions + CliChain>, + LeftRelay: CliChain, + Right: ChainWithTransactions + CliChain>, + RightRelay: CliChain, + L2R: CliBridgeBase + + MessagesCliBridge + + ParachainToRelayHeadersCliBridge, + R2L: CliBridgeBase + + MessagesCliBridge + + ParachainToRelayHeadersCliBridge, + >( + self, + ) -> anyhow::Result> { + Ok(ParachainToParachainBridge { + common: Full2WayBridgeCommonParams::new::( + self.shared, + BridgeEndCommonParams { + client: self.left.into_client::().await?, + sign: self.left_sign.to_keypair::()?, + transactions_mortality: self.left_sign.transactions_mortality()?, + messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + BridgeEndCommonParams { + client: self.right.into_client::().await?, + sign: self.right_sign.to_keypair::()?, + transactions_mortality: self.right_sign.transactions_mortality()?, + messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, + accounts: vec![], + }, + )?, + left_relay: self.left_relay.into_client::().await?, + right_relay: self.right_relay.into_client::().await?, + right_headers_to_left_transaction_params: self + .right_relay_headers_to_left_sign_override + .transaction_params_or::(&self.left_sign)?, + left_headers_to_right_transaction_params: self + .left_relay_headers_to_right_sign_override + .transaction_params_or::(&self.right_sign)?, + right_parachains_to_left_transaction_params: self + .right_parachains_to_left_sign_override + .transaction_params_or::(&self.left_sign)?, + left_parachains_to_right_transaction_params: self + .left_parachains_to_right_sign_override + .transaction_params_or::(&self.right_sign)?, + }) + } + } + } + }; +} + +#[async_trait] +impl< + Left: Chain + ChainWithTransactions + CliChain>, + Right: Chain + + ChainWithTransactions + + CliChain>, + LeftRelay: Chain + + CliChain, + RightRelay: Chain + + CliChain, + L2R: CliBridgeBase + + MessagesCliBridge + + ParachainToRelayHeadersCliBridge, + R2L: CliBridgeBase + + MessagesCliBridge + + ParachainToRelayHeadersCliBridge, + > Full2WayBridgeBase for ParachainToParachainBridge +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, +{ + type Params = ParachainToParachainBridge; + type Left = Left; + type Right = Right; + + fn common(&self) -> &Full2WayBridgeCommonParams { + &self.common + } + + fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams { + &mut self.common + } + + async fn start_on_demand_headers_relayers( + &mut self, + ) -> anyhow::Result<( + Arc>>, + Arc>>, + )> { + self.common.left.accounts.push(TaggedAccount::Headers { + id: self.right_headers_to_left_transaction_params.signer.public().into(), + bridged_chain: RightRelay::NAME.to_string(), + }); + self.common.left.accounts.push(TaggedAccount::Parachains { + id: self.right_parachains_to_left_transaction_params.signer.public().into(), + bridged_chain: RightRelay::NAME.to_string(), + }); + self.common.right.accounts.push(TaggedAccount::Headers { + id: self.left_headers_to_right_transaction_params.signer.public().into(), + bridged_chain: Left::NAME.to_string(), + }); + self.common.right.accounts.push(TaggedAccount::Parachains { + id: self.left_parachains_to_right_transaction_params.signer.public().into(), + bridged_chain: LeftRelay::NAME.to_string(), + }); + + ::RelayFinality::start_relay_guards( + &self.common.right.client, + &self.left_headers_to_right_transaction_params, + self.common.right.client.can_start_version_guard(), + ) + .await?; + ::RelayFinality::start_relay_guards( + &self.common.left.client, + &self.right_headers_to_left_transaction_params, + self.common.left.client.can_start_version_guard(), + ) + .await?; + + let left_relay_to_right_on_demand_headers = + OnDemandHeadersRelay::new::<::RelayFinality>( + self.left_relay.clone(), + self.common.right.client.clone(), + self.left_headers_to_right_transaction_params.clone(), + self.common.shared.only_mandatory_headers, + ); + let right_relay_to_left_on_demand_headers = + OnDemandHeadersRelay::new::<::RelayFinality>( + self.right_relay.clone(), + self.common.left.client.clone(), + self.right_headers_to_left_transaction_params.clone(), + self.common.shared.only_mandatory_headers, + ); + + let left_to_right_on_demand_parachains = OnDemandParachainsRelay::new::< + ::ParachainFinality, + >( + self.left_relay.clone(), + self.common.right.client.clone(), + self.left_parachains_to_right_transaction_params.clone(), + Arc::new(left_relay_to_right_on_demand_headers), + ); + let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::< + ::ParachainFinality, + >( + self.right_relay.clone(), + self.common.left.client.clone(), + self.right_parachains_to_left_transaction_params.clone(), + Arc::new(right_relay_to_left_on_demand_headers), + ); + + Ok(( + Arc::new(left_to_right_on_demand_parachains), + Arc::new(right_to_left_on_demand_parachains), + )) + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 0990a2d217587..4070783df09bc 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -38,21 +38,27 @@ use substrate_relay_helper::{ TaggedAccount, TransactionParams, }; +/// A base relay between standalone (relay) chain and a parachain from another consensus system. +/// +/// Such relay starts 2 messages relay. It also starts 2 on-demand header relays and 1 on-demand +/// parachain heads relay. pub struct RelayToParachainBridge< L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge, > { + /// Parameters that are shared by all bridge types. pub common: Full2WayBridgeCommonParams<::Target, ::Target>, + /// Client of the right relay chain. pub right_relay: Client<::SourceRelay>, - // override for right_relay->left headers signer + /// Override for right_relay->left headers signer. pub right_headers_to_left_transaction_params: TransactionParams::Target>>, - // override for right->left parachains signer + /// Override for right->left parachains signer. pub right_parachains_to_left_transaction_params: TransactionParams::Target>>, - // override for left->right headers signer + /// Override for left->right headers signer. pub left_headers_to_right_transaction_params: TransactionParams::Target>>, } @@ -64,40 +70,50 @@ macro_rules! declare_relay_to_parachain_bridge_schema { #[doc = $left_chain ", " $right_parachain " and " $right_chain " headers+parachains+messages relay params."] #[derive(Debug, PartialEq, StructOpt)] pub struct [<$left_chain $right_parachain HeadersAndMessages>] { + // shared parameters #[structopt(flatten)] shared: HeadersAndMessagesSharedParams, + #[structopt(flatten)] left: [<$left_chain ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_chain SigningParams>], - // override for right_relay->left headers signer - #[structopt(flatten)] - right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], - // override for right->left parachains signer - #[structopt(flatten)] - right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>], + // signer used to sign parameter update transactions at the left chain #[structopt(flatten)] left_messages_pallet_owner: [<$left_chain MessagesPalletOwnerSigningParams>], + #[structopt(flatten)] right: [<$right_parachain ConnectionParams>], + #[structopt(flatten)] + right_relay: [<$right_chain ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$right_parachain SigningParams>], + // signer used to sign parameter update transactions at the left chain + #[structopt(flatten)] + right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>], + + + // override for right_relay->left headers signer + #[structopt(flatten)] + right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], // override for left->right headers signer #[structopt(flatten)] left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], + + // override for right->left parachains signer #[structopt(flatten)] - right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>], - #[structopt(flatten)] - right_relay: [<$right_chain ConnectionParams>], + right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>], } impl [<$left_chain $right_parachain HeadersAndMessages>] { async fn into_bridge< Left: ChainWithTransactions + CliChain>, Right: ChainWithTransactions + CliChain>, - RightRelay: ChainWithTransactions + CliChain, + RightRelay: CliChain, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase + MessagesCliBridge @@ -151,7 +167,6 @@ impl< + ChainWithTransactions + CliChain>, RightRelay: Chain - + ChainWithTransactions + CliChain, L2R: CliBridgeBase + MessagesCliBridge diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index fb33fab8b7856..bda532a2afd6c 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -31,16 +31,20 @@ use substrate_relay_helper::{ TaggedAccount, TransactionParams, }; +/// A base relay between two standalone (relay) chains. +/// +/// Such relay starts 2 messages relay and 2 on-demand header relays. pub struct RelayToRelayBridge< L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: MessagesCliBridge + RelayToRelayHeadersCliBridge, > { + /// Parameters that are shared by all bridge types. pub common: Full2WayBridgeCommonParams<::Target, ::Target>, - // override for right->left headers signer + /// Override for right->left headers signer. pub right_to_left_transaction_params: TransactionParams::Target>>, - // override for left->right headers signer + /// Override for left->right headers signer. pub left_to_right_transaction_params: TransactionParams::Target>>, } From 0131af9f71db72a3a5713c741ad9514e845fc056 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 22 Nov 2022 12:37:54 +0100 Subject: [PATCH 0814/1210] Utility to generate hex bytes for send-message command (#1658) --- primitives/test-utils/Cargo.toml | 3 +++ primitives/test-utils/src/lib.rs | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 0a591334577af..2bc77e632e5f1 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -15,6 +15,9 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +[dev-dependencies] +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } + [features] default = ["std"] std = [ diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index c1e95ec6fefdc..186d192014bb0 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -299,3 +299,47 @@ macro_rules! generate_owned_bridge_module_tests { } }; } + +#[cfg(test)] +mod tests { + use codec::Encode; + use sp_application_crypto::sp_core::{hexdisplay, hexdisplay::HexDisplay}; + use xcm::VersionedXcm; + + fn print_xcm(xcm: &VersionedXcm) { + println!("-----------------"); + println!("xcm (plain): {:?}", xcm); + println!("xcm (bytes): {:?}", xcm.encode()); + println!("xcm (hex): {:?}", hexdisplay::HexDisplay::from(&xcm.encode())); + } + + fn as_hex(xcm: &VersionedXcm) -> String { + HexDisplay::from(&xcm.encode()).to_string() + } + + pub type RuntimeCall = (); + + #[test] + fn generate_versioned_xcm_message_hex_bytes() { + let xcm: xcm::v2::Xcm = xcm::v2::Xcm(vec![xcm::v2::Instruction::Trap(43)]); + let xcm: VersionedXcm = From::from(xcm); + print_xcm(&xcm); + assert_eq!("020419ac", format!("{}", as_hex(&xcm))); + + let xcm: xcm::v3::Xcm = vec![xcm::v3::Instruction::Trap(43)].into(); + let xcm: VersionedXcm = From::from(xcm); + print_xcm(&xcm); + assert_eq!("030419ac", format!("{}", as_hex(&xcm))); + + let xcm: xcm::v3::Xcm = vec![ + xcm::v3::Instruction::ClearError, + xcm::v3::Instruction::ClearTopic, + xcm::v3::Instruction::ClearTransactStatus, + xcm::v3::Instruction::Trap(43), + ] + .into(); + let xcm: VersionedXcm = From::from(xcm); + print_xcm(&xcm); + assert_eq!("0310172c2319ac", format!("{}", as_hex(&xcm))); + } +} From eaef31fcdd70671f637cb882c47fc827b73ee1f3 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 22 Nov 2022 13:23:48 +0100 Subject: [PATCH 0815/1210] More accurate dispatch_result: true/false (#1659) --- bin/runtime-common/src/messages.rs | 40 ++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3bbf6df4f559a..3127e3c7665e2 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -511,14 +511,40 @@ pub mod target { }; let xcm_outcome = do_dispatch(); - log::trace!( - target: "runtime::bridge-dispatch", - "Incoming message {:?} dispatched with result: {:?}", - message_id, - xcm_outcome, - ); + let dispatch_result = match xcm_outcome { + Ok(outcome) => { + log::trace!( + target: "runtime::bridge-dispatch", + "Incoming message {:?} dispatched with result: {:?}", + message_id, + outcome, + ); + match outcome.ensure_execution() { + Ok(_weight) => true, + Err(e) => { + log::error!( + target: "runtime::bridge-dispatch", + "Incoming message {:?} was not dispatched, error: {:?}", + message_id, + e, + ); + false + }, + } + }, + Err(e) => { + log::error!( + target: "runtime::bridge-dispatch", + "Incoming message {:?} was not dispatched, codec error: {:?}", + message_id, + e, + ); + false + }, + }; + MessageDispatchResult { - dispatch_result: true, + dispatch_result, unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, } From f433793d29fd1868a4d9e5f0302053b4d806db7b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 22 Nov 2022 16:56:42 +0300 Subject: [PATCH 0816/1210] Remove dispatch_result field (#1660) * remove dispatch_result field * fix benchmarks --- bin/millau/runtime/src/rialto_messages.rs | 1 - bin/millau/runtime/src/xcm_config.rs | 1 - bin/rialto-parachain/runtime/src/lib.rs | 1 - bin/rialto/runtime/src/millau_messages.rs | 1 - bin/rialto/runtime/src/xcm_config.rs | 1 - bin/runtime-common/src/messages.rs | 9 +-- modules/messages/Cargo.toml | 1 - modules/messages/src/benchmarking.rs | 12 ++-- modules/messages/src/inbound_lane.rs | 9 +-- modules/messages/src/lib.rs | 10 +-- modules/messages/src/mock.rs | 15 +---- modules/messages/src/outbound_lane.rs | 78 +++-------------------- primitives/messages/Cargo.toml | 2 - primitives/messages/src/lib.rs | 73 +++++---------------- primitives/messages/src/target_chain.rs | 1 - primitives/runtime/src/messages.rs | 6 -- 16 files changed, 41 insertions(+), 180 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index e78d69229e18e..ff4b6ba1dda31 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -194,7 +194,6 @@ mod tests { let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint_u32( bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_millau::Millau::max_extrinsic_size(), diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 13304d2671f41..41f336e61b8c0 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -317,7 +317,6 @@ mod tests { assert_eq!( dispatch_result, MessageDispatchResult { - dispatch_result: true, unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index fcf83c8229454..e80ecdf188dcd 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -895,7 +895,6 @@ mod tests { assert_eq!( dispatch_result, MessageDispatchResult { - dispatch_result: true, unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 221590e9f8122..66480c3168dc9 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -192,7 +192,6 @@ mod tests { let max_incoming_inbound_lane_data_proof_size = bp_messages::InboundLaneData::<()>::encoded_size_hint_u32( bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX as _, ); pallet_bridge_messages::ensure_able_to_receive_confirmation::( bp_rialto::Rialto::max_extrinsic_size(), diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index b874ec8ce8534..895522655d270 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -276,7 +276,6 @@ mod tests { assert_eq!( dispatch_result, MessageDispatchResult { - dispatch_result: true, unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3127e3c7665e2..696d059cf6311 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -511,7 +511,7 @@ pub mod target { }; let xcm_outcome = do_dispatch(); - let dispatch_result = match xcm_outcome { + match xcm_outcome { Ok(outcome) => { log::trace!( target: "runtime::bridge-dispatch", @@ -520,7 +520,7 @@ pub mod target { outcome, ); match outcome.ensure_execution() { - Ok(_weight) => true, + Ok(_weight) => (), Err(e) => { log::error!( target: "runtime::bridge-dispatch", @@ -528,7 +528,6 @@ pub mod target { message_id, e, ); - false }, } }, @@ -539,12 +538,10 @@ pub mod target { message_id, e, ); - false }, - }; + } MessageDispatchResult { - dispatch_result, unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index f8ff74cdd55ae..0c2fecb0be3eb 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 254ba6cbace30..b8360facacbc7 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -311,7 +311,7 @@ benchmarks_instance_pallet! { inbound_lane_data: InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: relayer_id.clone(), - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }].into_iter().collect(), last_confirmed_nonce: 0, }, @@ -342,8 +342,8 @@ benchmarks_instance_pallet! { total_messages: 2, last_delivered_nonce: 2, }; - let mut delivered_messages = DeliveredMessages::new(1, true); - delivered_messages.note_dispatched_message(true); + let mut delivered_messages = DeliveredMessages::new(1); + delivered_messages.note_dispatched_message(); let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -387,11 +387,11 @@ benchmarks_instance_pallet! { relayers: vec![ UnrewardedRelayer { relayer: relayer1_id.clone(), - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }, UnrewardedRelayer { relayer: relayer2_id.clone(), - messages: DeliveredMessages::new(2, true), + messages: DeliveredMessages::new(2), }, ].into_iter().collect(), last_confirmed_nonce: 0, @@ -414,7 +414,7 @@ fn receive_messages, I: 'static>(nonce: MessageNonce) { inbound_lane_storage.set_data(InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: T::bridged_relayer_id(), - messages: DeliveredMessages::new(nonce, true), + messages: DeliveredMessages::new(nonce), }] .into_iter() .collect(), diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index aa2a9682668e3..0797cbfb946d6 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -101,7 +101,6 @@ impl, I: 'static> MaxEncodedLen for StoredInboundLaneData { fn max_encoded_len() -> usize { InboundLaneData::::encoded_size_hint( T::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize, - T::MaxUnconfirmedMessagesAtInboundLane::get() as usize, ) .unwrap_or(usize::MAX) } @@ -150,10 +149,6 @@ impl InboundLane { // overlap. match data.relayers.front_mut() { Some(entry) if entry.messages.begin < new_confirmed_nonce => { - entry.messages.dispatch_results = entry - .messages - .dispatch_results - .split_off((new_confirmed_nonce + 1 - entry.messages.begin) as _); entry.messages.begin = new_confirmed_nonce + 1; }, _ => {}, @@ -200,7 +195,7 @@ impl InboundLane { // now let's update inbound lane storage let push_new = match data.relayers.back_mut() { Some(entry) if entry.relayer == *relayer_at_bridged_chain => { - entry.messages.note_dispatched_message(dispatch_result.dispatch_result); + entry.messages.note_dispatched_message(); false }, _ => true, @@ -208,7 +203,7 @@ impl InboundLane { if push_new { data.relayers.push_back(UnrewardedRelayer { relayer: (*relayer_at_bridged_chain).clone(), - messages: DeliveredMessages::new(nonce, dispatch_result.dispatch_result), + messages: DeliveredMessages::new(nonce), }); } self.storage.set_data(data); diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index b7e7f72f5faaf..abe6ec6798378 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -987,7 +987,7 @@ mod tests { last_confirmed_nonce: 1, relayers: vec![UnrewardedRelayer { relayer: 0, - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }] .into_iter() .collect(), @@ -1007,7 +1007,7 @@ mod tests { phase: Phase::Initialization, event: TestEvent::Messages(Event::MessagesDelivered { lane_id: TEST_LANE_ID, - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }), topics: vec![], }], @@ -1622,8 +1622,8 @@ mod tests { // messages 1+2 are confirmed in 1 tx, message 3 in a separate tx // dispatch of message 2 has failed - let mut delivered_messages_1_and_2 = DeliveredMessages::new(1, true); - delivered_messages_1_and_2.note_dispatched_message(false); + let mut delivered_messages_1_and_2 = DeliveredMessages::new(1); + delivered_messages_1_and_2.note_dispatched_message(); let messages_1_and_2_proof = Ok(( TEST_LANE_ID, InboundLaneData { @@ -1636,7 +1636,7 @@ mod tests { .collect(), }, )); - let delivered_message_3 = DeliveredMessages::new(3, true); + let delivered_message_3 = DeliveredMessages::new(3); let messages_3_proof = Ok(( TEST_LANE_ID, InboundLaneData { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 861f273d7e7cc..7a59eb4fc3e2a 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -19,7 +19,6 @@ use crate::{calc_relayers_rewards, Config}; -use bitvec::prelude::*; use bp_messages::{ source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{ @@ -394,7 +393,6 @@ pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { /// Returns message dispatch result with given unspent weight. pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult { MessageDispatchResult { - dispatch_result: true, unspent_weight: Weight::from_ref_time(unspent_weight), dispatch_fee_paid_during_dispatch: true, } @@ -406,18 +404,7 @@ pub fn unrewarded_relayer( end: MessageNonce, relayer: TestRelayer, ) -> UnrewardedRelayer { - UnrewardedRelayer { - relayer, - messages: DeliveredMessages { - begin, - end, - dispatch_results: if end >= begin { - bitvec![u8, Msb0; 1; (end - begin + 1) as _] - } else { - Default::default() - }, - }, - } + UnrewardedRelayer { relayer, messages: DeliveredMessages { begin, end } } } /// Run pallet test. diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 3774dc7ff3668..33a58a40400bf 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -18,10 +18,8 @@ use crate::Config; -use bitvec::prelude::*; use bp_messages::{ - DeliveredMessages, DispatchResultsBitVec, LaneId, MessageNonce, MessagePayload, - OutboundLaneData, UnrewardedRelayer, + DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, }; use frame_support::{ weights::{RuntimeDbWeight, Weight}, @@ -67,9 +65,6 @@ pub enum ReceivalConfirmationResult { /// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid /// bridged chain storage. NonConsecutiveUnrewardedRelayerEntries, - /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May - /// be a result of invalid bridged chain storage. - InvalidNumberOfDispatchResults, /// The chain has more messages that need to be confirmed than there is in the proof. TryingToConfirmMoreMessagesThanExpected(MessageNonce), } @@ -129,14 +124,9 @@ impl OutboundLane { ) } - let dispatch_results = match extract_dispatch_results( - data.latest_received_nonce, - latest_delivered_nonce, - relayers, - ) { - Ok(dispatch_results) => dispatch_results, - Err(extract_error) => return extract_error, - }; + if let Err(e) = ensure_unrewarded_relayers_are_correct(latest_delivered_nonce, relayers) { + return e + } let prev_latest_received_nonce = data.latest_received_nonce; data.latest_received_nonce = latest_delivered_nonce; @@ -145,7 +135,6 @@ impl OutboundLane { ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages { begin: prev_latest_received_nonce + 1, end: latest_delivered_nonce, - dispatch_results, }) } @@ -180,21 +169,14 @@ impl OutboundLane { } } -/// Extract new dispatch results from the unrewarded relayers vec. +/// Verifies unrewarded relayers vec. /// /// Returns `Err(_)` if unrewarded relayers vec contains invalid data, meaning that the bridged /// chain has invalid runtime storage. -fn extract_dispatch_results( - prev_latest_received_nonce: MessageNonce, +fn ensure_unrewarded_relayers_are_correct( latest_received_nonce: MessageNonce, relayers: &VecDeque>, -) -> Result { - // the only caller of this functions checks that the - // prev_latest_received_nonce..=latest_received_nonce is valid, so we're ready to accept - // messages in this range => with_capacity call must succeed here or we'll be unable to receive - // confirmations at all - let mut received_dispatch_result = - BitVec::with_capacity((latest_received_nonce - prev_latest_received_nonce + 1) as _); +) -> Result<(), ReceivalConfirmationResult> { let mut last_entry_end: Option = None; for entry in relayers { // unrewarded relayer entry must have at least 1 unconfirmed message @@ -219,33 +201,9 @@ fn extract_dispatch_results( // this is detected now return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages) } - // entry must have single dispatch result for every message - // (guaranteed by the `InboundLane::receive_message()`) - if entry.messages.dispatch_results.len() as MessageNonce != - entry.messages.end - entry.messages.begin + 1 - { - return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults) - } - - // now we know that the entry is valid - // => let's check if it brings new confirmations - let new_messages_begin = - sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1); - let new_messages_end = sp_std::cmp::min(entry.messages.end, latest_received_nonce); - let new_messages_range = new_messages_begin..=new_messages_end; - if new_messages_range.is_empty() { - continue - } - - // now we know that entry brings new confirmations - // => let's extract dispatch results - received_dispatch_result.extend_from_bitslice( - &entry.messages.dispatch_results - [(new_messages_begin - entry.messages.begin) as usize..], - ); } - Ok(received_dispatch_result) + Ok(()) } #[cfg(test)] @@ -270,11 +228,7 @@ mod tests { } fn delivered_messages(nonces: RangeInclusive) -> DeliveredMessages { - DeliveredMessages { - begin: *nonces.start(), - end: *nonces.end(), - dispatch_results: bitvec![u8, Msb0; 1; (nonces.end() - nonces.start() + 1) as _], - } + DeliveredMessages { begin: *nonces.start(), end: *nonces.end() } } fn assert_3_messages_confirmation_fails( @@ -407,20 +361,6 @@ mod tests { ); } - #[test] - fn confirm_delivery_fails_if_number_of_dispatch_results_in_entry_is_invalid() { - let mut relayers: VecDeque<_> = unrewarded_relayers(1..=1) - .into_iter() - .chain(unrewarded_relayers(2..=2).into_iter()) - .chain(unrewarded_relayers(3..=3).into_iter()) - .collect(); - relayers[0].messages.dispatch_results.clear(); - assert_eq!( - assert_3_messages_confirmation_fails(3, &relayers), - ReceivalConfirmationResult::InvalidNumberOfDispatchResults, - ); - } - #[test] fn prune_messages_works() { run_test(|| { diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 736764ef20ffc..4899a1f22da39 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } impl-trait-for-tuples = "0.2" scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } @@ -30,7 +29,6 @@ hex-literal = "0.3" [features] default = ["std"] std = [ - "bitvec/std", "bp-runtime/std", "codec/std", "frame-support/std", diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index d816447959893..722a73cb24eba 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -20,7 +20,6 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bitvec::prelude::*; use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; @@ -140,7 +139,7 @@ impl InboundLaneData { /// size of each entry. /// /// Returns `None` if size overflows `usize` limits. - pub fn encoded_size_hint(relayers_entries: usize, messages_count: usize) -> Option + pub fn encoded_size_hint(relayers_entries: usize) -> Option where RelayerId: MaxEncodedLen, { @@ -148,23 +147,18 @@ impl InboundLaneData { let relayer_id_encoded_size = RelayerId::max_encoded_len(); let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; - let dispatch_results_per_byte = 8; - let dispatch_result_size = - sp_std::cmp::max(relayers_entries, messages_count / dispatch_results_per_byte); - relayers_size - .checked_add(message_nonce_size) - .and_then(|result| result.checked_add(dispatch_result_size)) + relayers_size.checked_add(message_nonce_size) } /// Returns the approximate size of the struct as u32, given a number of entries in the /// `relayers` set and the size of each entry. /// /// Returns `u32::MAX` if size overflows `u32` limits. - pub fn encoded_size_hint_u32(relayers_entries: usize, messages_count: usize) -> u32 + pub fn encoded_size_hint_u32(relayers_entries: usize) -> u32 where RelayerId: MaxEncodedLen, { - Self::encoded_size_hint(relayers_entries, messages_count) + Self::encoded_size_hint(relayers_entries) .and_then(|x| u32::try_from(x).ok()) .unwrap_or(u32::MAX) } @@ -204,9 +198,6 @@ pub struct InboundMessageDetails { pub dispatch_weight: Weight, } -/// Bit vector of message dispatch results. -pub type DispatchResultsBitVec = BitVec; - /// Unrewarded relayer entry stored in the inbound lane data. /// /// This struct represents a continuous range of messages that have been delivered by the same @@ -267,19 +258,13 @@ pub struct DeliveredMessages { pub begin: MessageNonce, /// Nonce of the last message that has been delivered (inclusive). pub end: MessageNonce, - /// Dispatch result (`false`/`true`), returned by the message dispatcher for every - /// message in the `[begin; end]` range. See `dispatch_result` field of the - /// `bp_runtime::messages::MessageDispatchResult` structure for more information. - pub dispatch_results: DispatchResultsBitVec, } impl DeliveredMessages { /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given /// dispatch result. - pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { - let mut dispatch_results = BitVec::with_capacity(1); - dispatch_results.push(dispatch_result); - DeliveredMessages { begin: nonce, end: nonce, dispatch_results } + pub fn new(nonce: MessageNonce) -> Self { + DeliveredMessages { begin: nonce, end: nonce } } /// Return total count of delivered messages. @@ -292,30 +277,14 @@ impl DeliveredMessages { } /// Note new dispatched message. - pub fn note_dispatched_message(&mut self, dispatch_result: bool) { + pub fn note_dispatched_message(&mut self) { self.end += 1; - self.dispatch_results.push(dispatch_result); } /// Returns true if delivered messages contain message with given nonce. pub fn contains_message(&self, nonce: MessageNonce) -> bool { (self.begin..=self.end).contains(&nonce) } - - /// Get dispatch result flag by message nonce. - /// - /// Dispatch result flag must be interpreted using the knowledge of dispatch mechanism - /// at the target chain. See `dispatch_result` field of the - /// `bp_runtime::messages::MessageDispatchResult` structure for more information. - /// - /// Panics if message nonce is not in the `begin..=end` range. Typically you'll first - /// check if message is within the range by calling `contains_message`. - pub fn message_dispatch_result(&self, nonce: MessageNonce) -> bool { - const INVALID_NONCE: &str = "Invalid nonce used to index dispatch_results"; - - let index = nonce.checked_sub(self.begin).expect(INVALID_NONCE) as usize; - *self.dispatch_results.get(index).expect(INVALID_NONCE) - } } /// Gist of `InboundLaneData::relayers` field used by runtime APIs. @@ -386,10 +355,10 @@ mod tests { assert_eq!( total_unrewarded_messages( &vec![ - UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0, true) }, + UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) }, UnrewardedRelayer { relayer: 2, - messages: DeliveredMessages::new(MessageNonce::MAX, true) + messages: DeliveredMessages::new(MessageNonce::MAX) }, ] .into_iter() @@ -410,21 +379,12 @@ mod tests { (13u8, 128u8), ]; for (relayer_entries, messages_count) in test_cases { - let expected_size = - InboundLaneData::::encoded_size_hint(relayer_entries as _, messages_count as _); + let expected_size = InboundLaneData::::encoded_size_hint(relayer_entries as _); let actual_size = InboundLaneData { relayers: (1u8..=relayer_entries) - .map(|i| { - let mut entry = UnrewardedRelayer { - relayer: i, - messages: DeliveredMessages::new(i as _, true), - }; - entry.messages.dispatch_results = bitvec![ - u8, Msb0; - 1; - (messages_count / relayer_entries) as _ - ]; - entry + .map(|i| UnrewardedRelayer { + relayer: i, + messages: DeliveredMessages::new(i as _), }) .collect(), last_confirmed_nonce: messages_count as _, @@ -444,15 +404,12 @@ mod tests { } #[test] - fn message_dispatch_result_works() { - let delivered_messages = - DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![u8, Msb0; 1; 151] }; + fn contains_result_works() { + let delivered_messages = DeliveredMessages { begin: 100, end: 150 }; assert!(!delivered_messages.contains_message(99)); assert!(delivered_messages.contains_message(100)); assert!(delivered_messages.contains_message(150)); assert!(!delivered_messages.contains_message(151)); - - assert!(delivered_messages.message_dispatch_result(125)); } } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 5f682dee16666..6487508588d5a 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -156,7 +156,6 @@ impl MessageDispatch for ForbidInboundMessages { fn dispatch(_: &AccountId, _: DispatchMessage) -> MessageDispatchResult { MessageDispatchResult { - dispatch_result: false, unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, } diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index d77b1df7515c6..b2e8aacedfa65 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -23,12 +23,6 @@ use scale_info::TypeInfo; /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] pub struct MessageDispatchResult { - /// Dispatch result flag. This flag is relayed back to the source chain and, generally - /// speaking, may bring any (that fits in single bit) information from the dispatcher at - /// the target chain to the message submitter at the source chain. If you're using immediate - /// call dispatcher, then it'll be result of the dispatch - `true` if dispatch has succeeded - /// and `false` otherwise. - pub dispatch_result: bool, /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: /// From 9924fada6f8f52ad5af9bd72134287b986561f18 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 23 Nov 2022 23:18:17 +0100 Subject: [PATCH 0817/1210] Fixes fo ro/wo bridge (#1661) --- primitives/chain-bridge-hub-wococo/src/lib.rs | 2 +- relays/client-bridge-hub-rococo/src/runtime_wrapper.rs | 8 ++++---- relays/client-substrate/src/error.rs | 3 --- relays/client-substrate/src/transaction_tracker.rs | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 5cee3f14dd6dd..2b0dc344f14df 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -69,7 +69,7 @@ impl Parachain for BridgeHubWococo { } /// Identifier of BridgeHubWococo in the Wococo relay chain. -pub const BRIDGE_HUB_WOCOCO_PARACHAIN_ID: u32 = 1013; +pub const BRIDGE_HUB_WOCOCO_PARACHAIN_ID: u32 = 1014; /// Name of the With-BridgeHubWococo messages pallet instance that is deployed at bridged chains. pub const WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index c88a40073cb86..6f83257cf4dc0 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -118,7 +118,7 @@ pub enum BridgeParachainCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeWococoMessagesCall { - #[codec(index = 5)] + #[codec(index = 2)] receive_messages_proof( relay_substrate_client::AccountIdOf, bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< @@ -128,7 +128,7 @@ pub enum BridgeWococoMessagesCall { bp_messages::Weight, ), - #[codec(index = 6)] + #[codec(index = 3)] receive_messages_delivery_proof( bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< relay_substrate_client::HashOf, @@ -140,7 +140,7 @@ pub enum BridgeWococoMessagesCall { #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] pub enum BridgeRococoMessagesCall { - #[codec(index = 5)] + #[codec(index = 2)] receive_messages_proof( relay_substrate_client::AccountIdOf, bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< @@ -150,7 +150,7 @@ pub enum BridgeRococoMessagesCall { bp_messages::Weight, ), - #[codec(index = 6)] + #[codec(index = 3)] receive_messages_delivery_proof( bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< relay_substrate_client::HashOf, diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 4252a5027d446..9323b7572214c 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -39,9 +39,6 @@ pub enum Error { /// The response from the server could not be SCALE decoded. #[error("Response parse failed: {0}")] ResponseParseFailed(#[from] codec::Error), - /// The Substrate bridge pallet has not yet been initialized. - #[error("The Substrate bridge pallet has not been initialized yet.")] - UninitializedBridgePallet, /// Account does not exist on the chain. #[error("Account does not exist on the chain.")] AccountDoesNotExist, diff --git a/relays/client-substrate/src/transaction_tracker.rs b/relays/client-substrate/src/transaction_tracker.rs index 1730647f00d53..211f7faab0e19 100644 --- a/relays/client-substrate/src/transaction_tracker.rs +++ b/relays/client-substrate/src/transaction_tracker.rs @@ -296,7 +296,7 @@ mod tests { &self, _hash: HashOf, ) -> Result, Error> { - self.0.as_ref().map_err(|_| Error::UninitializedBridgePallet).cloned() + self.0.as_ref().map_err(|_| Error::BridgePalletIsNotInitialized).cloned() } } @@ -338,7 +338,7 @@ mod tests { async fn returns_lost_on_finalized_and_environment_error() { assert_eq!( watch_transaction_status::<_, TestChain, _>( - TestEnvironment(Err(Error::UninitializedBridgePallet)), + TestEnvironment(Err(Error::BridgePalletIsNotInitialized)), Default::default(), futures::stream::iter([TransactionStatus::Finalized(Default::default())]) ) From 3b9885bdc961bc31e54a002b3b724311fa5d9672 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 25 Nov 2022 10:56:48 +0200 Subject: [PATCH 0818/1210] Add RococoBridgeHub <> WococoBridgeHub full 2 way bridge (#1663) * Add RococoBridgeHub <> WococoBridgeHub full 2 way bridge * Use StorageMapKeyProvider instead of account_info_storage_key() Avoid duplicating storage_map_final_key() * clippy + leftovers --- primitives/chain-bridge-hub-wococo/src/lib.rs | 2 +- primitives/polkadot-core/src/lib.rs | 40 ++++++++------- .../rococo_parachains_to_bridge_hub_wococo.rs | 9 +++- .../wococo_parachains_to_bridge_hub_rococo.rs | 9 +++- .../src/cli/relay_headers_and_messages/mod.rs | 50 +++++++++++++++++++ .../parachain_to_parachain.rs | 6 +-- relays/client-bridge-hub-rococo/src/lib.rs | 12 +++-- relays/client-bridge-hub-wococo/src/lib.rs | 12 +++-- relays/client-kusama/src/lib.rs | 3 +- relays/client-polkadot/src/lib.rs | 3 +- relays/client-rococo/src/lib.rs | 2 +- relays/client-westend/src/lib.rs | 2 +- relays/client-wococo/src/lib.rs | 2 +- 13 files changed, 116 insertions(+), 36 deletions(-) diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 2b0dc344f14df..a2c3f2ad37a32 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -24,7 +24,7 @@ // Re-export only what is really needed pub use bp_bridge_hub_rococo::{ - account_info_storage_key, AccountId, AccountPublic, AccountSigner, Address, Balance, + AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, AccountSigner, Address, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher, Hashing, Header, Index, Nonce, SS58Prefix, Signature, SignedBlock, SignedExtensions, UncheckedExtrinsic, WeightToFee, MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 878c3dc38ebcf..9e1f4b0452f9b 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::MessageNonce; -use bp_runtime::{Chain, EncodedOrDecodedCall}; +use bp_runtime::{Chain, EncodedOrDecodedCall, StorageMapKeyProvider}; use codec::Compact; use frame_support::{ dispatch::{DispatchClass, Dispatchable}, @@ -26,11 +26,11 @@ use frame_support::{ constants::{BlockExecutionWeight, WEIGHT_PER_SECOND}, Weight, }, - Blake2_128Concat, RuntimeDebug, StorageHasher, Twox128, + Blake2_128Concat, RuntimeDebug, }; use frame_system::limits; use scale_info::{StaticTypeInfo, TypeInfo}; -use sp_core::Hasher as HasherT; +use sp_core::{storage::StorageKey, Hasher as HasherT}; use sp_runtime::{ generic, traits::{BlakeTwo256, DispatchInfoOf, IdentifyAccount, Verify}, @@ -346,26 +346,28 @@ impl Chain for PolkadotLike { } } -/// Return a storage key for account data. +/// Provides a storage key for account data. /// -/// This is based on FRAME storage-generation code from Substrate: -/// [link](https://github.com/paritytech/substrate/blob/c939ceba381b6313462d47334f775e128ea4e95d/frame/support/src/storage/generator/map.rs#L74) +/// We need to use this approach when we don't have access to the runtime. /// The equivalent command to invoke in case full `Runtime` is known is this: /// `let key = frame_system::Account::::storage_map_final_key(&account_id);` -pub fn account_info_storage_key(id: &AccountId) -> Vec { - let module_prefix_hashed = Twox128::hash(b"System"); - let storage_prefix_hashed = Twox128::hash(b"Account"); - let key_hashed = codec::Encode::using_encoded(id, Blake2_128Concat::hash); - - let mut final_key = Vec::with_capacity( - module_prefix_hashed.len() + storage_prefix_hashed.len() + key_hashed.len(), - ); +pub struct AccountInfoStorageMapKeyProvider; + +impl StorageMapKeyProvider for AccountInfoStorageMapKeyProvider { + const MAP_NAME: &'static str = "Account"; + type Hasher = Blake2_128Concat; + type Key = AccountId; + // This should actually be `AccountInfo`, but we don't use this property in order to decode the + // data. So we use `Vec` as if we would work with encoded data. + type Value = Vec; +} - final_key.extend_from_slice(&module_prefix_hashed[..]); - final_key.extend_from_slice(&storage_prefix_hashed[..]); - final_key.extend_from_slice(&key_hashed); +impl AccountInfoStorageMapKeyProvider { + const PALLET_NAME: &'static str = "System"; - final_key + pub fn final_key(id: &AccountId) -> StorageKey { + ::final_key(Self::PALLET_NAME, id) + } } #[cfg(test)] @@ -379,7 +381,7 @@ mod tests { 25, 26, 27, 28, 29, 30, 31, 32, ] .into(); - let key = account_info_storage_key(&acc); + let key = AccountInfoStorageMapKeyProvider::final_key(&acc); assert_eq!(hex::encode(key), "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da92dccd599abfe1920a1cff8a7358231430102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"); } } diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs index 509cbf70db160..8b208712db5d0 100644 --- a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs @@ -16,7 +16,7 @@ //! Wococo-to-Rococo parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use parachains_relay::ParachainsPipeline; use relay_substrate_client::{CallOf, HeaderIdOf}; @@ -76,3 +76,10 @@ impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge { type Source = relay_bridge_hub_rococo_client::BridgeHubRococo; type Target = relay_bridge_hub_wococo_client::BridgeHubWococo; } + +impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_bridge_hub_wococo::TO_BRIDGE_HUB_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane; +} diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs index d4fbf095df480..453455a7b561d 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -16,7 +16,7 @@ //! Rococo-to-Wococo parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use parachains_relay::ParachainsPipeline; use relay_substrate_client::{CallOf, HeaderIdOf}; @@ -76,3 +76,10 @@ impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge { type Source = relay_bridge_hub_wococo_client::BridgeHubWococo; type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; } + +impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge { + const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = + bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD; + type MessagesLane = + crate::chains::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane; +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index bdc92f984daf8..f84174563e146 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -44,6 +44,8 @@ use crate::{ millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, + wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, }, cli::{ bridge::{ @@ -51,6 +53,7 @@ use crate::{ RelayToRelayHeadersCliBridge, }, chain_schema::*, + relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge, CliChain, HexLaneId, PrometheusParams, }, declare_chain_cli_schema, @@ -190,14 +193,29 @@ where declare_chain_cli_schema!(Millau, millau); declare_chain_cli_schema!(Rialto, rialto); declare_chain_cli_schema!(RialtoParachain, rialto_parachain); +declare_chain_cli_schema!(Rococo, rococo); +declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); +declare_chain_cli_schema!(Wococo, wococo); +declare_chain_cli_schema!(BridgeHubWococo, bridge_hub_wococo); // Means to override signers of different layer transactions. declare_chain_cli_schema!(MillauHeadersToRialto, millau_headers_to_rialto); declare_chain_cli_schema!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); declare_chain_cli_schema!(RialtoHeadersToMillau, rialto_headers_to_millau); declare_chain_cli_schema!(RialtoParachainsToMillau, rialto_parachains_to_millau); +declare_chain_cli_schema!(RococoHeadersToBridgeHubWococo, rococo_headers_to_bridge_hub_wococo); +declare_chain_cli_schema!( + RococoParachainsToBridgeHubWococo, + rococo_parachains_to_bridge_hub_wococo +); +declare_chain_cli_schema!(WococoHeadersToBridgeHubRococo, wococo_headers_to_bridge_hub_rococo); +declare_chain_cli_schema!( + WococoParachainsToBridgeHubRococo, + wococo_parachains_to_bridge_hub_rococo +); // All supported bridges. declare_relay_to_relay_bridge_schema!(Millau, Rialto); declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); +declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWococo, Wococo); /// Base portion of the bidirectional complex relay. /// @@ -410,6 +428,32 @@ impl Full2WayBridge for MillauRialtoParachainFull2WayBridge { } } +/// BridgeHubRococo <> BridgeHubWococo complex relay. +pub struct BridgeHubRococoBridgeHubWococoFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for BridgeHubRococoBridgeHubWococoFull2WayBridge { + type Base = ParachainToParachainBridge; + type Left = relay_bridge_hub_rococo_client::BridgeHubRococo; + type Right = relay_bridge_hub_wococo_client::BridgeHubWococo; + type L2R = BridgeHubRococoToBridgeHubWococoCliBridge; + type R2L = BridgeHubWococoToBridgeHubRococoCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { @@ -417,6 +461,8 @@ pub enum RelayHeadersAndMessages { MillauRialto(MillauRialtoHeadersAndMessages), /// Millau <> RialtoParachain relay. MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), + /// BridgeHubRococo <> BridgeHubWococo relay. + BridgeHubRococoBridgeHubWococo(BridgeHubRococoBridgeHubWococoHeadersAndMessages), } impl RelayHeadersAndMessages { @@ -429,6 +475,10 @@ impl RelayHeadersAndMessages { MillauRialtoParachainFull2WayBridge::new(params.into_bridge().await?)? .run() .await, + RelayHeadersAndMessages::BridgeHubRococoBridgeHubWococo(params) => + BridgeHubRococoBridgeHubWococoFull2WayBridge::new(params.into_bridge().await?)? + .run() + .await, } } } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 9adc8fd662430..e7328a837eb99 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -118,7 +118,7 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { left_parachains_to_right_sign_override: [<$left_chain ParachainsTo $right_parachain SigningParams>], } - impl [<$left_chain $right_parachain HeadersAndMessages>] { + impl [<$left_parachain $right_parachain HeadersAndMessages>] { async fn into_bridge< Left: ChainWithTransactions + CliChain>, LeftRelay: CliChain, @@ -132,7 +132,7 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { + ParachainToRelayHeadersCliBridge, >( self, - ) -> anyhow::Result> { + ) -> anyhow::Result> { Ok(ParachainToParachainBridge { common: Full2WayBridgeCommonParams::new::( self.shared, @@ -151,7 +151,7 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { accounts: vec![], }, )?, - left_relay: self.left_relay.into_client::().await?, + left_relay: self.left_relay.into_client::().await?, right_relay: self.right_relay.into_client::().await?, right_headers_to_left_transaction_params: self .right_relay_headers_to_left_sign_override diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index e4740490cb5d0..1de0e26d43661 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -19,10 +19,10 @@ use bp_messages::{MessageNonce, Weight}; use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, SignParam, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, ChainWithTransactions, + Error as SubstrateError, SignParam, UnsignedTransaction, }; -use sp_core::Pair; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -65,6 +65,12 @@ impl Chain for BridgeHubRococo { type Call = runtime::Call; } +impl ChainWithBalances for BridgeHubRococo { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + bp_bridge_hub_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) + } +} + impl ChainWithTransactions for BridgeHubRococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = runtime::UncheckedExtrinsic; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 3199b3b4fc1c8..46bac2e826e3f 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -19,10 +19,10 @@ use bp_messages::{MessageNonce, Weight}; use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, SignParam, - UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithMessages, ChainWithTransactions, + Error as SubstrateError, SignParam, UnsignedTransaction, }; -use sp_core::Pair; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; @@ -65,6 +65,12 @@ impl Chain for BridgeHubWococo { type Call = runtime::Call; } +impl ChainWithBalances for BridgeHubWococo { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + bp_bridge_hub_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) + } +} + impl ChainWithTransactions for BridgeHubWococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = runtime::UncheckedExtrinsic; diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 355f26b849660..25d7bb76e59bf 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Kusama chain. +use bp_kusama::AccountInfoStorageMapKeyProvider; use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; use sp_core::storage::StorageKey; @@ -65,7 +66,7 @@ impl ChainWithGrandpa for Kusama { impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_kusama::account_info_storage_key(account_id)) + AccountInfoStorageMapKeyProvider::final_key(account_id) } } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 101b62b9c35ee..8bba686cfe9e7 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Polkadot chain. +use bp_polkadot::AccountInfoStorageMapKeyProvider; use frame_support::weights::Weight; use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; use sp_core::storage::StorageKey; @@ -66,7 +67,7 @@ impl ChainWithGrandpa for Polkadot { impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_polkadot::account_info_storage_key(account_id)) + AccountInfoStorageMapKeyProvider::final_key(account_id) } } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index fc3aa76eb4491..38a95042ff3b0 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -68,7 +68,7 @@ impl ChainWithGrandpa for Rococo { impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_rococo::account_info_storage_key(account_id)) + bp_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) } } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 6a2944629bed1..9132a38710a11 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -75,7 +75,7 @@ impl ChainWithGrandpa for Westend { impl ChainWithBalances for Westend { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_westend::account_info_storage_key(account_id)) + bp_westend::AccountInfoStorageMapKeyProvider::final_key(account_id) } } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 04b5193afd33a..6fc3714f66704 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -68,7 +68,7 @@ impl ChainWithGrandpa for Wococo { impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - StorageKey(bp_wococo::account_info_storage_key(account_id)) + bp_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) } } From 5e738af4fad14d225191cf0a50bdc965cbc57c94 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 28 Nov 2022 13:22:17 +0300 Subject: [PATCH 0819/1210] fix clippy (#1664) --- relays/client-substrate/src/guard.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index bc8fd8e7d3029..1afbf0d3d17ed 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -124,9 +124,10 @@ pub fn abort_when_account_balance_decreased( let current_time = env.now(); // remember balances that are beyound 24h border - let time_border = current_time - DAY; - while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) { - balances.pop_front(); + if let Some(time_border) = current_time.checked_sub(DAY) { + while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) { + balances.pop_front(); + } } // read balance of the account From df3f9d2a0b1cd7bbd5a70349fd05c30e0de4f5a2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 28 Nov 2022 16:49:05 +0300 Subject: [PATCH 0820/1210] Per-lane rewards in pallet-bridge-relayers (#1665) * per-lane rewards in pallet-bridge-relayers * add lane id to RewardPaid event * clippy * fix benchmarks --- modules/relayers/src/benchmarking.rs | 5 +- modules/relayers/src/lib.rs | 108 +++++++++++++++++------- modules/relayers/src/mock.rs | 13 ++- modules/relayers/src/payment_adapter.rs | 83 +++++++++--------- primitives/relayers/Cargo.toml | 7 +- primitives/relayers/src/lib.rs | 11 ++- 6 files changed, 151 insertions(+), 76 deletions(-) diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index 706454e0497dd..b79c0fb3ff0b5 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -29,9 +29,10 @@ const REWARD_AMOUNT: u32 = u32::MAX; benchmarks! { // Benchmark `claim_rewards` call. claim_rewards { + let lane = [0, 0, 0, 0]; let relayer: T::AccountId = whitelisted_caller(); - RelayerRewards::::insert(&relayer, T::Reward::from(REWARD_AMOUNT)); - }: _(RawOrigin::Signed(relayer)) + RelayerRewards::::insert(&relayer, lane, T::Reward::from(REWARD_AMOUNT)); + }: _(RawOrigin::Signed(relayer), lane) verify { // we can't check anything here, because `PaymentProcedure` is responsible for // payment logic, so we assume that if call has succeeded, the procedure has diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index f3195f1288ebe..921ec0e4d9820 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -20,8 +20,10 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] +use bp_messages::LaneId; use bp_relayers::PaymentProcedure; -use sp_arithmetic::traits::AtLeast32BitUnsigned; +use frame_support::sp_runtime::Saturating; +use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; use sp_std::marker::PhantomData; use weights::WeightInfo; @@ -63,24 +65,54 @@ pub mod pallet { impl Pallet { /// Claim accumulated rewards. #[pallet::weight(T::WeightInfo::claim_rewards())] - pub fn claim_rewards(origin: OriginFor) -> DispatchResult { + pub fn claim_rewards(origin: OriginFor, lane_id: LaneId) -> DispatchResult { let relayer = ensure_signed(origin)?; - RelayerRewards::::try_mutate_exists(&relayer, |maybe_reward| -> DispatchResult { - let reward = maybe_reward.take().ok_or(Error::::NoRewardForRelayer)?; - T::PaymentProcedure::pay_reward(&relayer, reward).map_err(|e| { - log::trace!( - target: LOG_TARGET, - "Failed to pay rewards to {:?}: {:?}", - relayer, - e, - ); - Error::::FailedToPayReward - })?; - - Self::deposit_event(Event::::RewardPaid { relayer: relayer.clone(), reward }); - Ok(()) - }) + RelayerRewards::::try_mutate_exists( + &relayer, + lane_id, + |maybe_reward| -> DispatchResult { + let reward = maybe_reward.take().ok_or(Error::::NoRewardForRelayer)?; + T::PaymentProcedure::pay_reward(&relayer, lane_id, reward).map_err(|e| { + log::trace!( + target: LOG_TARGET, + "Failed to pay {:?} rewards to {:?}: {:?}", + lane_id, + relayer, + e, + ); + Error::::FailedToPayReward + })?; + + Self::deposit_event(Event::::RewardPaid { + relayer: relayer.clone(), + lane_id, + reward, + }); + Ok(()) + }, + ) + } + } + + impl Pallet { + /// Register reward for given relayer. + pub fn register_relayer_reward(lane_id: LaneId, relayer: &T::AccountId, reward: T::Reward) { + if reward.is_zero() { + return + } + + RelayerRewards::::mutate(relayer, lane_id, |old_reward: &mut Option| { + let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); + *old_reward = Some(new_reward); + + log::trace!( + target: crate::LOG_TARGET, + "Relayer {:?} can now claim reward: {:?}", + relayer, + new_reward, + ); + }); } } @@ -91,6 +123,8 @@ pub mod pallet { RewardPaid { /// Relayer account that has been rewarded. relayer: T::AccountId, + /// Relayer has received reward for serving this lane. + lane_id: LaneId, /// Reward amount. reward: T::Reward, }, @@ -106,8 +140,15 @@ pub mod pallet { /// Map of the relayer => accumulated reward. #[pallet::storage] - pub type RelayerRewards = - StorageMap<_, Blake2_128Concat, T::AccountId, T::Reward, OptionQuery>; + pub type RelayerRewards = StorageDoubleMap< + _, + Blake2_128Concat, + T::AccountId, + Identity, + LaneId, + T::Reward, + OptionQuery, + >; } #[cfg(test)] @@ -129,7 +170,7 @@ mod tests { fn root_cant_claim_anything() { run_test(|| { assert_noop!( - Pallet::::claim_rewards(RuntimeOrigin::root()), + Pallet::::claim_rewards(RuntimeOrigin::root(), TEST_LANE_ID), DispatchError::BadOrigin, ); }); @@ -139,7 +180,10 @@ mod tests { fn relayer_cant_claim_if_no_reward_exists() { run_test(|| { assert_noop!( - Pallet::::claim_rewards(RuntimeOrigin::signed(REGULAR_RELAYER)), + Pallet::::claim_rewards( + RuntimeOrigin::signed(REGULAR_RELAYER), + TEST_LANE_ID + ), Error::::NoRewardForRelayer, ); }); @@ -148,9 +192,12 @@ mod tests { #[test] fn relayer_cant_claim_if_payment_procedure_fails() { run_test(|| { - RelayerRewards::::insert(FAILING_RELAYER, 100); + RelayerRewards::::insert(FAILING_RELAYER, TEST_LANE_ID, 100); assert_noop!( - Pallet::::claim_rewards(RuntimeOrigin::signed(FAILING_RELAYER)), + Pallet::::claim_rewards( + RuntimeOrigin::signed(FAILING_RELAYER), + TEST_LANE_ID + ), Error::::FailedToPayReward, ); }); @@ -161,11 +208,12 @@ mod tests { run_test(|| { get_ready_for_events(); - RelayerRewards::::insert(REGULAR_RELAYER, 100); - assert_ok!(Pallet::::claim_rewards(RuntimeOrigin::signed( - REGULAR_RELAYER - ))); - assert_eq!(RelayerRewards::::get(REGULAR_RELAYER), None); + RelayerRewards::::insert(REGULAR_RELAYER, TEST_LANE_ID, 100); + assert_ok!(Pallet::::claim_rewards( + RuntimeOrigin::signed(REGULAR_RELAYER), + TEST_LANE_ID + )); + assert_eq!(RelayerRewards::::get(REGULAR_RELAYER, TEST_LANE_ID), None); //Check if the `RewardPaid` event was emitted. assert_eq!( @@ -174,6 +222,7 @@ mod tests { phase: Phase::Initialization, event: TestEvent::Relayers(RewardPaid { relayer: REGULAR_RELAYER, + lane_id: TEST_LANE_ID, reward: 100 }), topics: vec![], @@ -189,7 +238,8 @@ mod tests { run_test(|| { assert_eq!(Balances::balance(&1), 0); assert_eq!(Balances::total_issuance(), 0); - bp_relayers::MintReward::::pay_reward(&1, 100).unwrap(); + bp_relayers::MintReward::::pay_reward(&1, TEST_LANE_ID, 100) + .unwrap(); assert_eq!(Balances::balance(&1), 100); assert_eq!(Balances::total_issuance(), 100); }); diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 7cf5575f5f384..55db2d575e7ef 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -18,7 +18,9 @@ use crate as pallet_bridge_relayers; -use bp_messages::{source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages}; +use bp_messages::{ + source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages, LaneId, +}; use bp_relayers::PaymentProcedure; use frame_support::{parameter_types, weights::RuntimeDbWeight}; use sp_core::H256; @@ -124,6 +126,9 @@ impl pallet_bridge_relayers::Config for TestRuntime { type WeightInfo = (); } +/// Message lane that we're using in tests. +pub const TEST_LANE_ID: LaneId = [0, 0, 0, 0]; + /// Regular relayer that may receive rewards. pub const REGULAR_RELAYER: AccountId = 1; @@ -136,7 +141,11 @@ pub struct TestPaymentProcedure; impl PaymentProcedure for TestPaymentProcedure { type Error = (); - fn pay_reward(relayer: &AccountId, _reward: Balance) -> Result<(), Self::Error> { + fn pay_reward( + relayer: &AccountId, + _lane_id: LaneId, + _reward: Balance, + ) -> Result<(), Self::Error> { match *relayer { FAILING_RELAYER => Err(()), _ => Ok(()), diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 772d07d2ad971..4939d274c6095 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -17,7 +17,7 @@ //! Code that allows relayers pallet to be used as a delivery+dispatch payment mechanism //! for the messages pallet. -use crate::{Config, RelayerRewards}; +use crate::{Config, Pallet}; use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; use frame_support::sp_runtime::SaturatedConversion; @@ -39,7 +39,7 @@ where type Error = &'static str; fn pay_relayers_rewards( - _lane_id: bp_messages::LaneId, + lane_id: bp_messages::LaneId, messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, received_range: &RangeInclusive, @@ -52,8 +52,9 @@ where register_relayers_rewards::( confirmation_relayer, relayers_rewards, + lane_id, // TODO (https://github.com/paritytech/parity-bridges-common/issues/1318): this shall be fixed - // in some way. ATM the future of the `register_relayers_rewards` is not yet known + // in some way. ATM the future of the `register_relayer_reward` is not yet known 100_000_u32.into(), 10_000_u32.into(), ); @@ -64,6 +65,7 @@ where fn register_relayers_rewards( confirmation_relayer: &T::AccountId, relayers_rewards: RelayersRewards, + lane_id: bp_messages::LaneId, delivery_fee: T::Reward, confirmation_fee: T::Reward, ) { @@ -87,7 +89,7 @@ fn register_relayers_rewards( relayer_reward = relayer_reward.saturating_sub(confirmation_reward); confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(confirmation_reward); - register_relayer_reward::(&relayer, relayer_reward); + Pallet::::register_relayer_reward(lane_id, &relayer, relayer_reward); } else { // If delivery confirmation is submitted by this relayer, let's add confirmation fee // from other relayers to this relayer reward. @@ -97,32 +99,17 @@ fn register_relayers_rewards( } // finally - pay reward to confirmation relayer - register_relayer_reward::(confirmation_relayer, confirmation_relayer_reward); -} - -/// Remember that the reward shall be paid to the relayer. -fn register_relayer_reward(relayer: &T::AccountId, reward: T::Reward) { - if reward.is_zero() { - return - } - - RelayerRewards::::mutate(relayer, |old_reward: &mut Option| { - let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); - *old_reward = Some(new_reward); - - log::trace!( - target: crate::LOG_TARGET, - "Relayer {:?} can now claim reward: {:?}", - relayer, - new_reward, - ); - }); + Pallet::::register_relayer_reward( + lane_id, + confirmation_relayer, + confirmation_relayer_reward, + ); } #[cfg(test)] mod tests { use super::*; - use crate::mock::*; + use crate::{mock::*, RelayerRewards}; const RELAYER_1: AccountId = 1; const RELAYER_2: AccountId = 2; @@ -135,32 +122,50 @@ mod tests { #[test] fn confirmation_relayer_is_rewarded_if_it_has_also_delivered_messages() { run_test(|| { - register_relayers_rewards::(&RELAYER_2, relayers_rewards(), 50, 10); - - assert_eq!(RelayerRewards::::get(RELAYER_1), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2), Some(170)); + register_relayers_rewards::( + &RELAYER_2, + relayers_rewards(), + TEST_LANE_ID, + 50, + 10, + ); + + assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), Some(80)); + assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), Some(170)); }); } #[test] fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { run_test(|| { - register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 50, 10); - - assert_eq!(RelayerRewards::::get(RELAYER_1), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2), Some(120)); - assert_eq!(RelayerRewards::::get(RELAYER_3), Some(50)); + register_relayers_rewards::( + &RELAYER_3, + relayers_rewards(), + TEST_LANE_ID, + 50, + 10, + ); + + assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), Some(80)); + assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), Some(120)); + assert_eq!(RelayerRewards::::get(RELAYER_3, TEST_LANE_ID), Some(50)); }); } #[test] fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { run_test(|| { - register_relayers_rewards::(&RELAYER_3, relayers_rewards(), 50, 1000); - - assert_eq!(RelayerRewards::::get(RELAYER_1), None); - assert_eq!(RelayerRewards::::get(RELAYER_2), None); - assert_eq!(RelayerRewards::::get(RELAYER_3), Some(250)); + register_relayers_rewards::( + &RELAYER_3, + relayers_rewards(), + TEST_LANE_ID, + 50, + 1000, + ); + + assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), None); + assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), None); + assert_eq!(RelayerRewards::::get(RELAYER_3, TEST_LANE_ID), Some(250)); }); } } diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 908412477c221..4dc09f8d12658 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -8,6 +8,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +# Bridge Dependencies + +bp-messages = { path = "../messages", default-features = false } + # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -21,7 +25,8 @@ hex-literal = "0.3" [features] default = ["std"] std = [ + "bp-messages/std", "frame-support/std", "sp-runtime/std", - "sp-std/std", + "sp-std/std", ] diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index d1c82d612e2e9..bd456d36310ca 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -19,6 +19,7 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +use bp_messages::LaneId; use sp_std::{fmt::Debug, marker::PhantomData}; /// Reward payment procedure. @@ -26,8 +27,8 @@ pub trait PaymentProcedure { /// Error that may be returned by the procedure. type Error: Debug; - /// Pay reward to the relayer. - fn pay_reward(relayer: &Relayer, reward: Reward) -> Result<(), Self::Error>; + /// Pay reward to the relayer for serving given message lane. + fn pay_reward(relayer: &Relayer, lane_id: LaneId, reward: Reward) -> Result<(), Self::Error>; } /// Reward payment procedure that is simply minting given amount of tokens. @@ -39,7 +40,11 @@ where { type Error = sp_runtime::DispatchError; - fn pay_reward(relayer: &Relayer, reward: T::Balance) -> Result<(), Self::Error> { + fn pay_reward( + relayer: &Relayer, + _lane_id: LaneId, + reward: T::Balance, + ) -> Result<(), Self::Error> { T::mint_into(relayer, reward) } } From 0b17765e29804a3577e6509238392064de48ad69 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 29 Nov 2022 15:23:48 +0300 Subject: [PATCH 0821/1210] fix clippy (#1668) --- relays/lib-substrate-relay/src/parachains/target.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index c4022f12f5edf..68fd72765aa35 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -131,7 +131,7 @@ where .await? .map(|para_info| para_info.best_head_hash); - if let (Some(metrics), &Some(ref best_para_head_hash)) = (metrics, &best_para_head_hash) { + if let (Some(metrics), Some(best_para_head_hash)) = (metrics, &best_para_head_hash) { let imported_para_head = self .client .storage_double_map_value::( From a220f7f15790cab2e6d2e883cad1e57f4810fbf5 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 30 Nov 2022 16:44:30 +0100 Subject: [PATCH 0822/1210] Added generic DispatchLevelResult to the MessageDispatchResult (#1670) * Added generic DispatchLevelResult to the MessageDispatchResult * Removed unnecessery `Clone + Decode + sp_std::fmt::Debug + Eq` + clippy --- bin/millau/runtime/src/xcm_config.rs | 1 + bin/rialto-parachain/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/xcm_config.rs | 1 + bin/runtime-common/src/messages.rs | 4 +++- modules/messages/src/inbound_lane.rs | 2 +- modules/messages/src/lib.rs | 8 +++++++- modules/messages/src/mock.rs | 11 ++++++++--- primitives/messages/src/lib.rs | 19 +++++++++++-------- primitives/messages/src/target_chain.rs | 12 ++++++++++-- primitives/runtime/src/messages.rs | 4 +++- 10 files changed, 46 insertions(+), 17 deletions(-) diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 41f336e61b8c0..b5be117ac7732 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -319,6 +319,7 @@ mod tests { MessageDispatchResult { unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, + dispatch_level_result: (), } ); }) diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index e80ecdf188dcd..f946abf4c1da9 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -897,6 +897,7 @@ mod tests { MessageDispatchResult { unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, + dispatch_level_result: (), } ); }) diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 895522655d270..892c1ed747b19 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -278,6 +278,7 @@ mod tests { MessageDispatchResult { unspent_weight: frame_support::weights::Weight::from_ref_time(0), dispatch_fee_paid_during_dispatch: false, + dispatch_level_result: (), } ); }) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 696d059cf6311..23c79b1c58377 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -449,6 +449,7 @@ pub mod target { WeightCredit: Get, { type DispatchPayload = FromBridgedChainMessagePayload>>; + type DispatchLevelResult = (); fn dispatch_weight( message: &mut DispatchMessage, @@ -482,7 +483,7 @@ pub mod target { fn dispatch( _relayer_account: &AccountIdOf>, message: DispatchMessage, - ) -> MessageDispatchResult { + ) -> MessageDispatchResult { let message_id = (message.key.lane_id, message.key.nonce); let do_dispatch = move || -> sp_std::result::Result { let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } = @@ -544,6 +545,7 @@ pub mod target { MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, + dispatch_level_result: (), } } } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 0797cbfb946d6..00c63b5d670a4 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -165,7 +165,7 @@ impl InboundLane { relayer_at_this_chain: &AccountId, nonce: MessageNonce, message_data: DispatchMessageData, - ) -> ReceivalResult { + ) -> ReceivalResult { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index abe6ec6798378..0df6c686cc690 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -515,7 +515,13 @@ pub mod pallet { /// Message has been accepted and is waiting to be delivered. MessageAccepted { lane_id: LaneId, nonce: MessageNonce }, /// Messages have been received from the bridged chain. - MessagesReceived(Vec>), + MessagesReceived( + Vec< + ReceivedMessages< + >::DispatchLevelResult, + >, + >, + ), /// Messages in the inclusive range have been delivered to the bridged chain. MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages }, } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 7a59eb4fc3e2a..36c38677e5373 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -60,12 +60,13 @@ pub struct TestPayload { /// /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, /// but for test purposes we'll be making it larger than `declared_weight` sometimes. - pub dispatch_result: MessageDispatchResult, + pub dispatch_result: MessageDispatchResult, /// Extra bytes that affect payload size. pub extra: Vec, } pub type TestMessageFee = u64; pub type TestRelayer = u64; +pub type TestDispatchLevelResult = (); type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -345,6 +346,7 @@ pub struct TestMessageDispatch; impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; + type DispatchLevelResult = TestDispatchLevelResult; fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { @@ -356,7 +358,7 @@ impl MessageDispatch for TestMessageDispatch { fn dispatch( _relayer_account: &AccountId, message: DispatchMessage, - ) -> MessageDispatchResult { + ) -> MessageDispatchResult { match message.data.payload.as_ref() { Ok(payload) => payload.dispatch_result.clone(), Err(_) => dispatch_result(0), @@ -391,10 +393,13 @@ pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { } /// Returns message dispatch result with given unspent weight. -pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult { +pub const fn dispatch_result( + unspent_weight: u64, +) -> MessageDispatchResult { MessageDispatchResult { unspent_weight: Weight::from_ref_time(unspent_weight), dispatch_fee_paid_during_dispatch: true, + dispatch_level_result: (), } } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 722a73cb24eba..daaa2800988be 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -30,8 +30,8 @@ pub mod source_chain; pub mod storage_keys; pub mod target_chain; -// Weight is reexported to avoid additional frame-support dependencies in related crates. use bp_runtime::messages::MessageDispatchResult; +// Weight is reexported to avoid additional frame-support dependencies in related crates. pub use frame_support::weights::Weight; /// Messages pallet operating mode. @@ -212,21 +212,24 @@ pub struct UnrewardedRelayer { /// Received messages with their dispatch result. #[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct ReceivedMessages { +pub struct ReceivedMessages { /// Id of the lane which is receiving messages. pub lane: LaneId, /// Result of messages which we tried to dispatch - pub receive_results: Vec<(MessageNonce, Result)>, + pub receive_results: Vec<(MessageNonce, ReceivalResult)>, /// Messages which were skipped and never dispatched pub skipped_for_not_enough_weight: Vec, } -impl ReceivedMessages { - pub fn new(lane: LaneId, receive_results: Vec<(MessageNonce, Result)>) -> Self { +impl ReceivedMessages { + pub fn new( + lane: LaneId, + receive_results: Vec<(MessageNonce, ReceivalResult)>, + ) -> Self { ReceivedMessages { lane, receive_results, skipped_for_not_enough_weight: Vec::new() } } - pub fn push(&mut self, message: MessageNonce, result: Result) { + pub fn push(&mut self, message: MessageNonce, result: ReceivalResult) { self.receive_results.push((message, result)); } @@ -237,12 +240,12 @@ impl ReceivedMessages { /// Result of single message receival. #[derive(RuntimeDebug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)] -pub enum ReceivalResult { +pub enum ReceivalResult { /// Message has been received and dispatched. Note that we don't care whether dispatch has /// been successful or not - in both case message falls into this category. /// /// The message dispatch result is also returned. - Dispatched(MessageDispatchResult), + Dispatched(MessageDispatchResult), /// Message has invalid nonce and lane has rejected to accept this message. InvalidNonce, /// There are too many unrewarded relayer entries at the lane. diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 6487508588d5a..63c8b639e6c28 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -89,6 +89,9 @@ pub trait MessageDispatch { /// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch). type DispatchPayload: Decode; + /// Fine-grained result of single message dispatch (for better diagnostic purposes) + type DispatchLevelResult: Clone + Decode + sp_std::fmt::Debug + Eq; + /// Estimate dispatch weight. /// /// This function must return correct upper bound of dispatch weight. The return value @@ -106,7 +109,7 @@ pub trait MessageDispatch { fn dispatch( relayer_account: &AccountId, message: DispatchMessage, - ) -> MessageDispatchResult; + ) -> MessageDispatchResult; } impl Default for ProvedLaneMessages { @@ -149,15 +152,20 @@ impl SourceHeaderChain for ForbidInboundMessages { impl MessageDispatch for ForbidInboundMessages { type DispatchPayload = (); + type DispatchLevelResult = (); fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX } - fn dispatch(_: &AccountId, _: DispatchMessage) -> MessageDispatchResult { + fn dispatch( + _: &AccountId, + _: DispatchMessage, + ) -> MessageDispatchResult { MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_fee_paid_during_dispatch: false, + dispatch_level_result: (), } } } diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index b2e8aacedfa65..0bb09090df90b 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -22,7 +22,7 @@ use scale_info::TypeInfo; /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] -pub struct MessageDispatchResult { +pub struct MessageDispatchResult { /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: /// @@ -34,4 +34,6 @@ pub struct MessageDispatchResult { /// configuration supports pay-dispatch-fee-at-target-chain option and message sender has /// enabled this option. pub dispatch_fee_paid_during_dispatch: bool, + /// Fine-grained result of single message dispatch (for better diagnostic purposes) + pub dispatch_level_result: DispatchLevelResult, } From 5f618d489c6c587c5af610505da616c1ddef447f Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 1 Dec 2022 22:27:18 +0100 Subject: [PATCH 0823/1210] `dry-run` mode for init bridge command (#1690) * `dry-run` mode for init bridge command * fix clippy --- primitives/messages/src/target_chain.rs | 2 +- relays/bin-substrate/src/cli/init_bridge.rs | 17 +++++++++++++---- .../src/finality/initialize.rs | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 63c8b639e6c28..9c6b60e1e1531 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -90,7 +90,7 @@ pub trait MessageDispatch { type DispatchPayload: Decode; /// Fine-grained result of single message dispatch (for better diagnostic purposes) - type DispatchLevelResult: Clone + Decode + sp_std::fmt::Debug + Eq; + type DispatchLevelResult: Clone + sp_std::fmt::Debug + Eq; /// Estimate dispatch weight. /// diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 54a3c74a4b6e2..52a3a6fce5a5b 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . use async_trait::async_trait; +use codec::Encode; use crate::{ chains::{ @@ -46,6 +47,9 @@ pub struct InitBridge { target: TargetConnectionParams, #[structopt(flatten)] target_sign: TargetSigningParams, + /// Generates all required data, but does not submit extrinsic + #[structopt(long)] + dry_run: bool, } #[derive(Debug, EnumString, EnumVariantNames)] @@ -77,6 +81,7 @@ where let source_client = data.source.into_client::().await?; let target_client = data.target.into_client::().await?; let target_sign = data.target_sign.to_keypair::()?; + let dry_run = data.dry_run; let (spec_version, transaction_version) = target_client.simple_runtime_version().await?; substrate_relay_helper::finality::initialize::initialize::( @@ -90,11 +95,15 @@ where signer: target_sign, }, move |transaction_nonce, initialization_data| { - Ok(UnsignedTransaction::new( - Self::encode_init_bridge(initialization_data).into(), - transaction_nonce, - )) + let call = Self::encode_init_bridge(initialization_data); + log::info!( + target: "bridge", + "Initialize bridge call encoded as hex string: {:?}", + format!("0x{}", hex::encode(call.encode())) + ); + Ok(UnsignedTransaction::new(call.into(), transaction_nonce)) }, + dry_run, ) .await; diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index 6ff185800cced..938f1330b2ead 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -40,6 +40,7 @@ pub async fn initialize< target_transactions_signer: TargetChain::AccountId, target_signing_data: SignParam, prepare_initialize_transaction: F, + dry_run: bool, ) where F: FnOnce( TargetChain::Index, @@ -54,6 +55,7 @@ pub async fn initialize< target_transactions_signer, target_signing_data, prepare_initialize_transaction, + dry_run, ) .await; @@ -88,6 +90,7 @@ async fn do_initialize< target_transactions_signer: TargetChain::AccountId, target_signing_data: SignParam, prepare_initialize_transaction: F, + dry_run: bool, ) -> Result< Option, Error::Number>, @@ -110,7 +113,9 @@ where SourceChain::NAME, TargetChain::NAME, ); - return Ok(None) + if !dry_run { + return Ok(None) + } } let initialization_data = E::prepare_initialization_data(source_client).await?; @@ -127,7 +132,14 @@ where target_transactions_signer, target_signing_data, move |_, transaction_nonce| { - prepare_initialize_transaction(transaction_nonce, initialization_data) + let tx = prepare_initialize_transaction(transaction_nonce, initialization_data); + if dry_run { + Err(SubstrateError::Custom( + "Not submitting extrinsic in `dry-run` mode!".to_string(), + )) + } else { + tx + } }, ) .await From 48363704956116d13038312bd7588d3fe4df477e Mon Sep 17 00:00:00 2001 From: Binston Sukhael Cardoza Date: Fri, 2 Dec 2022 13:15:34 +0530 Subject: [PATCH 0824/1210] Replace const parameters types (#1691) * Replace const parameters * fmt * missed out Maxlocks --- bin/millau/runtime/src/lib.rs | 41 +++++++++--------------- bin/millau/runtime/src/xcm_config.rs | 8 ++--- bin/rialto-parachain/runtime/src/lib.rs | 20 +++++------- bin/rialto/runtime/src/lib.rs | 36 +++++++++------------ bin/rialto/runtime/src/parachains.rs | 6 +--- bin/rialto/runtime/src/xcm_config.rs | 8 ++--- modules/beefy/src/mock.rs | 5 ++- modules/grandpa/src/mock.rs | 5 ++- modules/messages/src/mock.rs | 9 ++---- modules/parachains/src/mock.rs | 13 +++++--- modules/shift-session-manager/src/lib.rs | 3 +- 11 files changed, 59 insertions(+), 95 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b1f1e33d18a47..d6e99afb2d8bb 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -62,7 +62,7 @@ pub use frame_support::{ construct_runtime, dispatch::DispatchClass, parameter_types, - traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, + traits::{ConstU32, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, weights::{ constants::WEIGHT_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, }, @@ -215,19 +215,15 @@ impl frame_system::Config for Runtime { impl pallet_randomness_collective_flip::Config for Runtime {} -parameter_types! { - pub const MaxAuthorities: u32 = 10; -} - impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; type DisabledValidators = (); } impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; type OnNewValidatorSet = MmrLeaf; } @@ -243,7 +239,7 @@ impl pallet_grandpa::Config for Runtime { type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; } /// MMR helper types. @@ -311,10 +307,6 @@ impl pallet_timestamp::Config for Runtime { parameter_types! { pub const ExistentialDeposit: bp_millau::Balance = 500; - // For weight estimation, we assume that the most locks on an individual account will be 50. - // This number may need to be adjusted in the future if this assumption no longer holds true. - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { @@ -327,15 +319,16 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; + // For weight estimation, we assume that the most locks on an individual account will be 50. + // This number may need to be adjusted in the future if this assumption no longer holds true. + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; } parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; - pub const OperationalFeeMultiplier: u8 = 5; // values for following parameters are copied from polkadot repo, but it is fine // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); @@ -346,7 +339,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = bp_millau::WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< @@ -383,14 +376,6 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } -parameter_types! { - // This is a pretty unscientific cap. - // - // Note that once this is hit the pallet will essentially throttle incoming requests down to one - // call per block. - pub const MaxRequests: u32 = 50; -} - impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; @@ -439,7 +424,11 @@ parameter_types! { pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; - type MaxRequests = MaxRequests; + // This is a pretty unscientific cap. + // + // Note that once this is hit the pallet will essentially throttle incoming requests down to one + // call per block. + type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtRialto; type MaxBridgedHeaderSize = MaxRialtoHeaderSize; @@ -450,7 +439,7 @@ impl pallet_bridge_grandpa::Config for Runtime { pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; - type MaxRequests = MaxRequests; + type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtWestend; type MaxBridgedHeaderSize = MaxWestendHeaderSize; diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index b5be117ac7732..a3a59e626e572 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -31,7 +31,7 @@ use bridge_runtime_common::{ }; use frame_support::{ parameter_types, - traits::{Everything, Nothing}, + traits::{ConstU32, Everything, Nothing}, }; use xcm::latest::prelude::*; use xcm_builder::{ @@ -112,10 +112,6 @@ pub type XcmRouter = ( XcmBridgeAdapter, ); -parameter_types! { - pub const MaxAssetsIntoHolding: u32 = 64; -} - /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( // Weight that is paid for may be consumed. @@ -149,7 +145,7 @@ impl xcm_executor::Config for XcmConfig { type AssetClaims = XcmPallet; type SubscriptionService = XcmPallet; type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index f946abf4c1da9..2d0be49a07f46 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -50,7 +50,7 @@ pub use frame_support::{ construct_runtime, dispatch::DispatchClass, match_types, parameter_types, - traits::{Everything, IsInVec, Nothing, Randomness}, + traits::{ConstU32, Everything, IsInVec, Nothing, Randomness}, weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, IdentityFee, Weight, @@ -249,8 +249,6 @@ parameter_types! { pub const CreationFee: u128 = MILLIUNIT; pub const TransactionByteFee: u128 = MICROUNIT; pub const OperationalFeeMultiplier: u8 = 5; - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { @@ -262,8 +260,8 @@ impl pallet_balances::Config for Runtime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = pallet_balances::weights::SubstrateWeight; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; } @@ -518,12 +516,6 @@ impl pallet_bridge_relayers::Config for Runtime { } parameter_types! { - /// This is a pretty unscientific cap. - /// - /// Note that once this is hit the pallet will essentially throttle incoming requests down to one - /// call per block. - pub const MaxRequests: u32 = 50; - /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a @@ -539,7 +531,11 @@ parameter_types! { pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; - type MaxRequests = MaxRequests; + /// This is a pretty unscientific cap. + /// + /// Note that once this is hit the pallet will essentially throttle incoming requests down to + /// one call per block. + type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; type MaxBridgedHeaderSize = MaxMillauHeaderSize; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 25778705e5ef5..59284df910a26 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -61,7 +61,7 @@ pub use frame_support::{ construct_runtime, dispatch::DispatchClass, parameter_types, - traits::{Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, + traits::{ConstU32, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, weights::{constants::WEIGHT_PER_SECOND, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -222,13 +222,12 @@ pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = parameter_types! { pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64; pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK; - pub const MaxAuthorities: u32 = 10; } impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; // session module is the trigger type EpochChangeTrigger = pallet_babe::ExternalTrigger; @@ -251,13 +250,13 @@ impl pallet_babe::Config for Runtime { impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; type OnNewValidatorSet = MmrLeaf; } impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; type KeyOwnerProofSystem = (); type KeyOwnerProof = >::Proof; @@ -327,10 +326,6 @@ impl pallet_timestamp::Config for Runtime { parameter_types! { pub const ExistentialDeposit: bp_rialto::Balance = 500; - // For weight estimation, we assume that the most locks on an individual account will be 50. - // This number may need to be adjusted in the future if this assumption no longer holds true. - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; } impl pallet_balances::Config for Runtime { @@ -343,15 +338,16 @@ impl pallet_balances::Config for Runtime { type AccountStore = System; // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; + // For weight estimation, we assume that the most locks on an individual account will be 50. + // This number may need to be adjusted in the future if this assumption no longer holds true. + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; } parameter_types! { pub const TransactionBaseFee: Balance = 0; pub const TransactionByteFee: Balance = 1; - pub const OperationalFeeMultiplier: u8 = 5; // values for following parameters are copied from polkadot repo, but it is fine // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); @@ -362,7 +358,7 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = OperationalFeeMultiplier; + type OperationalFeeMultiplier = ConstU8<5>; type WeightToFee = bp_rialto::WeightToFee; type LengthToFee = bp_rialto::WeightToFee; type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< @@ -394,7 +390,7 @@ impl pallet_session::Config for Runtime { } impl pallet_authority_discovery::Config for Runtime { - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<10>; } impl pallet_bridge_relayers::Config for Runtime { @@ -405,12 +401,6 @@ impl pallet_bridge_relayers::Config for Runtime { } parameter_types! { - /// This is a pretty unscientific cap. - /// - /// Note that once this is hit the pallet will essentially throttle incoming requests down to one - /// call per block. - pub const MaxRequests: u32 = 50; - /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a @@ -426,7 +416,11 @@ parameter_types! { pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; - type MaxRequests = MaxRequests; + /// This is a pretty unscientific cap. + /// + /// Note that once this is hit the pallet will essentially throttle incoming requests down to + /// one call per block. + type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; type MaxBridgedHeaderSize = MaxMillauHeaderSize; diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 960931a0b3cee..1c7280198a421 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -123,14 +123,10 @@ impl parachains_session_info::Config for Runtime { impl parachains_shared::Config for Runtime {} -parameter_types! { - pub const FirstMessageFactorPercent: u64 = 100; -} - impl parachains_ump::Config for Runtime { type RuntimeEvent = RuntimeEvent; type UmpSink = (); - type FirstMessageFactorPercent = FirstMessageFactorPercent; + type FirstMessageFactorPercent = frame_support::traits::ConstU64<100>; type ExecuteOverweightOrigin = EnsureRoot; type WeightInfo = parachains_ump::TestWeightInfo; } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 892c1ed747b19..419a55489307c 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -27,7 +27,7 @@ use bridge_runtime_common::{ }; use frame_support::{ parameter_types, - traits::{Everything, Nothing}, + traits::{ConstU32, Everything, Nothing}, }; use xcm::latest::prelude::*; use xcm_builder::{ @@ -104,10 +104,6 @@ pub type XcmRouter = ( XcmBridgeAdapter, ); -parameter_types! { - pub const MaxAssetsIntoHolding: u32 = 64; -} - /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( // Weight that is paid for may be consumed. @@ -141,7 +137,7 @@ impl xcm_executor::Config for XcmConfig { type AssetClaims = XcmPallet; type SubscriptionService = XcmPallet; type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); type MessageExporter = (); type UniversalAliases = Nothing; diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 927c39ff9aad4..a07f7962a44d8 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -24,7 +24,7 @@ use crate::{ use bp_beefy::{BeefyValidatorSignatureOf, ChainWithBeefy, Commitment, MmrDataOrHash}; use bp_runtime::{BasicOperatingMode, Chain}; use codec::Encode; -use frame_support::{construct_runtime, parameter_types, weights::Weight}; +use frame_support::{construct_runtime, parameter_types, traits::ConstU64, weights::Weight}; use sp_core::{sr25519::Signature, Pair}; use sp_runtime::{ testing::{Header, H256}, @@ -72,7 +72,6 @@ construct_runtime! { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); @@ -89,7 +88,7 @@ impl frame_system::Config for TestRuntime { type Lookup = IdentityLookup; type Header = Header; type RuntimeEvent = (); - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 0f83bd528d68e..12a40a688f6aa 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -18,7 +18,7 @@ #![allow(clippy::from_over_into)] use bp_runtime::Chain; -use frame_support::{construct_runtime, parameter_types, weights::Weight}; +use frame_support::{construct_runtime, parameter_types, traits::ConstU64, weights::Weight}; use sp_core::sr25519::Signature; use sp_runtime::{ testing::{Header, H256}, @@ -50,7 +50,6 @@ construct_runtime! { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); @@ -67,7 +66,7 @@ impl frame_system::Config for TestRuntime { type Lookup = IdentityLookup; type Header = Header; type RuntimeEvent = (); - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 36c38677e5373..da2d1c6a4da4e 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -32,6 +32,7 @@ use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, + traits::ConstU64, weights::{RuntimeDbWeight, Weight}, }; use scale_info::TypeInfo; @@ -104,7 +105,7 @@ impl frame_system::Config for TestRuntime { type Lookup = IdentityLookup; type Header = SubstrateHeader; type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; + type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; @@ -120,16 +121,12 @@ impl frame_system::Config for TestRuntime { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} - impl pallet_balances::Config for TestRuntime { type MaxLocks = (); type Balance = Balance; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU64<1>; type AccountStore = frame_system::Pallet; type WeightInfo = (); type MaxReserves = (); diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 9638472aa985f..4e17a71bcdc5e 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -16,7 +16,11 @@ use bp_polkadot_core::parachains::ParaId; use bp_runtime::Chain; -use frame_support::{construct_runtime, parameter_types, traits::IsInVec, weights::Weight}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{ConstU32, IsInVec}, + weights::Weight, +}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, Header as HeaderT, IdentityLookup}, @@ -86,15 +90,14 @@ impl frame_system::Config for TestRuntime { } parameter_types! { - pub const MaxRequests: u32 = 2; - pub const HeadersToKeep: u32 = 5; pub const SessionLength: u64 = 5; pub const NumValidators: u32 = 5; + pub const HeadersToKeep: u32 = 5; } impl pallet_bridge_grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; - type MaxRequests = MaxRequests; + type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; @@ -103,7 +106,7 @@ impl pallet_bridge_grandpa::Config for TestRun impl pallet_bridge_grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; - type MaxRequests = MaxRequests; + type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 073013d92d030..dce6005ab549d 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -152,7 +152,6 @@ mod tests { } parameter_types! { - pub const BlockHashCount: u64 = 250; pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); @@ -169,7 +168,7 @@ mod tests { type Lookup = IdentityLookup; type Header = Header; type RuntimeEvent = (); - type BlockHashCount = BlockHashCount; + type BlockHashCount = frame_support::traits::ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; type AccountData = (); From 7f312eedc520b4f5af77df7373dc6545169af0bf Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 2 Dec 2022 12:57:41 +0300 Subject: [PATCH 0825/1210] refund_pay_dispatch_fee removed (#1695) --- bin/millau/runtime/src/xcm_config.rs | 1 - bin/rialto-parachain/runtime/src/lib.rs | 1 - bin/rialto/runtime/src/xcm_config.rs | 1 - bin/runtime-common/src/messages.rs | 6 +--- modules/messages/src/benchmarking.rs | 33 ------------------ modules/messages/src/lib.rs | 46 +++++++------------------ modules/messages/src/mock.rs | 1 - modules/messages/src/weights.rs | 11 ------ modules/messages/src/weights_ext.rs | 9 ----- primitives/messages/src/target_chain.rs | 6 +--- primitives/runtime/src/messages.rs | 4 --- 11 files changed, 14 insertions(+), 105 deletions(-) diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index a3a59e626e572..b5e238d28b352 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -314,7 +314,6 @@ mod tests { dispatch_result, MessageDispatchResult { unspent_weight: frame_support::weights::Weight::from_ref_time(0), - dispatch_fee_paid_during_dispatch: false, dispatch_level_result: (), } ); diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 2d0be49a07f46..0fe03883e0fe8 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -892,7 +892,6 @@ mod tests { dispatch_result, MessageDispatchResult { unspent_weight: frame_support::weights::Weight::from_ref_time(0), - dispatch_fee_paid_during_dispatch: false, dispatch_level_result: (), } ); diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 419a55489307c..feab0f35c79cb 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -273,7 +273,6 @@ mod tests { dispatch_result, MessageDispatchResult { unspent_weight: frame_support::weights::Weight::from_ref_time(0), - dispatch_fee_paid_during_dispatch: false, dispatch_level_result: (), } ); diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 23c79b1c58377..3530e683140bc 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -542,11 +542,7 @@ pub mod target { }, } - MessageDispatchResult { - unspent_weight: Weight::zero(), - dispatch_fee_paid_during_dispatch: false, - dispatch_level_result: (), - } + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } } } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index b8360facacbc7..36018474a8f8f 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -256,39 +256,6 @@ benchmarks_instance_pallet! { assert!(T::is_message_dispatched(21)); } - // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * proof does not include outbound lane state proof; - // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at source (bridged) chain. - // - // This benchmark is used to compute extra weight spent at target chain when fee is paid there. Then we use - // this information in two places: (1) to reduce weight of delivery tx if sender pays fee at the source chain - // and (2) to refund relayer with this weight if fee has been paid at the source chain. - receive_single_prepaid_message_proof { - let relayer_id_on_source = T::bridged_relayer_id(); - let relayer_id_on_target = account("relayer", 0, SEED); - T::endow_account(&relayer_id_on_target); - - // mark messages 1..=20 as delivered - receive_messages::(20); - - let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { - lane: T::bench_lane_id(), - message_nonces: 21..=21, - outbound_lane_data: None, - size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), - }); - }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) - verify { - assert_eq!( - crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), - 21, - ); - assert!(T::is_message_dispatched(21)); - } - // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: // * single relayer is rewarded for relaying single message; // * relayer account does not exist (in practice it needs to exist in production environment). diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 0df6c686cc690..d19b17e0ddfa0 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -361,32 +361,20 @@ pub mod pallet { // losing funds for messages dispatch. But keep in mind that relayer pays base // delivery transaction cost anyway. And base cost covers everything except // dispatch, so we have a balance here. - let (unspent_weight, refund_pay_dispatch_fee) = match &receival_result { + let unspent_weight = match &receival_result { ReceivalResult::Dispatched(dispatch_result) => { valid_messages += 1; - ( - dispatch_result.unspent_weight, - !dispatch_result.dispatch_fee_paid_during_dispatch, - ) + dispatch_result.unspent_weight }, ReceivalResult::InvalidNonce | ReceivalResult::TooManyUnrewardedRelayers | - ReceivalResult::TooManyUnconfirmedMessages => (message_dispatch_weight, true), + ReceivalResult::TooManyUnconfirmedMessages => message_dispatch_weight, }; lane_messages_received_status.push(message.key.nonce, receival_result); let unspent_weight = unspent_weight.min(message_dispatch_weight); dispatch_weight_left -= message_dispatch_weight - unspent_weight; - actual_weight = actual_weight.saturating_sub(unspent_weight).saturating_sub( - // delivery call weight formula assumes that the fee is paid at - // this (target) chain. If the message is prepaid at the source - // chain, let's refund relayer with this extra cost. - if refund_pay_dispatch_fee { - T::WeightInfo::pay_inbound_dispatch_fee_overhead() - } else { - Weight::zero() - }, - ); + actual_weight = actual_weight.saturating_sub(unspent_weight); } messages_received_status.push(lane_messages_received_status); @@ -1554,11 +1542,9 @@ mod tests { fn submit_with_unspent_weight( nonce: MessageNonce, unspent_weight: u64, - is_prepaid: bool, ) -> (Weight, Weight) { let mut payload = REGULAR_PAYLOAD; *payload.dispatch_result.unspent_weight.ref_time_mut() = unspent_weight; - payload.dispatch_result.dispatch_fee_paid_during_dispatch = !is_prepaid; let proof = Ok(vec![message(nonce, payload)]).into(); let messages_count = 1; let pre_dispatch_weight = @@ -1582,40 +1568,32 @@ mod tests { } // when dispatch is returning `unspent_weight < declared_weight` - let (pre, post) = submit_with_unspent_weight(1, 1, false); + let (pre, post) = submit_with_unspent_weight(1, 1); assert_eq!(post.ref_time(), pre.ref_time() - 1); // when dispatch is returning `unspent_weight = declared_weight` let (pre, post) = - submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight.ref_time(), false); + submit_with_unspent_weight(2, REGULAR_PAYLOAD.declared_weight.ref_time()); assert_eq!( post.ref_time(), pre.ref_time() - REGULAR_PAYLOAD.declared_weight.ref_time() ); // when dispatch is returning `unspent_weight > declared_weight` - let (pre, post) = submit_with_unspent_weight( - 3, - REGULAR_PAYLOAD.declared_weight.ref_time() + 1, - false, - ); + let (pre, post) = + submit_with_unspent_weight(3, REGULAR_PAYLOAD.declared_weight.ref_time() + 1); assert_eq!( post.ref_time(), pre.ref_time() - REGULAR_PAYLOAD.declared_weight.ref_time() ); // when there's no unspent weight - let (pre, post) = submit_with_unspent_weight(4, 0, false); + let (pre, post) = submit_with_unspent_weight(4, 0); assert_eq!(post, pre); - // when dispatch is returning `unspent_weight < declared_weight` AND message is prepaid - let (pre, post) = submit_with_unspent_weight(5, 1, true); - assert_eq!( - post.ref_time(), - pre.ref_time() - - 1 - ::WeightInfo::pay_inbound_dispatch_fee_overhead() - .ref_time() - ); + // when dispatch is returning `unspent_weight < declared_weight` + let (pre, post) = submit_with_unspent_weight(5, 1); + assert_eq!(post.ref_time(), pre.ref_time() - 1); }); } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index da2d1c6a4da4e..59f72602c84e2 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -395,7 +395,6 @@ pub const fn dispatch_result( ) -> MessageDispatchResult { MessageDispatchResult { unspent_weight: Weight::from_ref_time(unspent_weight), - dispatch_fee_paid_during_dispatch: true, dispatch_level_result: (), } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 2ae60c17fafb9..834e0d1f3d646 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -55,7 +55,6 @@ pub trait WeightInfo { fn receive_single_message_proof_with_outbound_lane_state() -> Weight; fn receive_single_message_proof_1_kb() -> Weight; fn receive_single_message_proof_16_kb() -> Weight; - fn receive_single_prepaid_message_proof() -> Weight; fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; @@ -91,11 +90,6 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - fn receive_single_prepaid_message_proof() -> Weight { - Weight::from_ref_time(49_646_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } fn receive_delivery_proof_for_single_message() -> Weight { Weight::from_ref_time(55_108_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) @@ -140,11 +134,6 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } - fn receive_single_prepaid_message_proof() -> Weight { - Weight::from_ref_time(49_646_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } fn receive_delivery_proof_for_single_message() -> Weight { Weight::from_ref_time(55_108_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 1604832c0790a..e597ed84cdd2b 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -265,15 +265,6 @@ pub trait WeightInfoExt: WeightInfo { (15 * 1024); proof_size_in_bytes * byte_weight } - - /// Returns weight of the pay-dispatch-fee operation for inbound messages. - /// - /// This function may return zero if runtime doesn't support pay-dispatch-fee-at-target-chain - /// option. - fn pay_inbound_dispatch_fee_overhead() -> Weight { - Self::receive_single_message_proof() - .saturating_sub(Self::receive_single_prepaid_message_proof()) - } } impl WeightInfoExt for () { diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 9c6b60e1e1531..1a3daad404388 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -162,10 +162,6 @@ impl MessageDispatch for ForbidInboundMessages { _: &AccountId, _: DispatchMessage, ) -> MessageDispatchResult { - MessageDispatchResult { - unspent_weight: Weight::zero(), - dispatch_fee_paid_during_dispatch: false, - dispatch_level_result: (), - } + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } } } diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index 0bb09090df90b..9f7c8ab5ca4e3 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -30,10 +30,6 @@ pub struct MessageDispatchResult { /// the weight, declared by the message sender; /// 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. - pub dispatch_fee_paid_during_dispatch: bool, /// Fine-grained result of single message dispatch (for better diagnostic purposes) pub dispatch_level_result: DispatchLevelResult, } From 7984059b5380efa3b9b43d160de1258c2b1a29a8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 2 Dec 2022 13:03:53 +0300 Subject: [PATCH 0826/1210] removed ESTIMATE_MESSAGE_FEE_METHOD (#1696) --- primitives/runtime/src/chain.rs | 6 ------ .../bridge_hub_rococo_messages_to_bridge_hub_wococo.rs | 2 -- .../bridge_hub_wococo_messages_to_bridge_hub_rococo.rs | 2 -- relays/bin-substrate/src/chains/millau_headers_to_rialto.rs | 2 -- .../src/chains/millau_headers_to_rialto_parachain.rs | 2 -- relays/bin-substrate/src/chains/rialto_headers_to_millau.rs | 2 -- .../bin-substrate/src/chains/rialto_parachains_to_millau.rs | 2 -- .../src/chains/rococo_parachains_to_bridge_hub_wococo.rs | 2 -- .../src/chains/wococo_parachains_to_bridge_hub_rococo.rs | 2 -- relays/bin-substrate/src/cli/bridge.rs | 3 --- 10 files changed, 25 deletions(-) diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index d4a8d5aa020b5..cb5cbad434c51 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -272,8 +272,6 @@ macro_rules! decl_bridge_finality_runtime_apis { /// - `ToOutboundLaneApi` /// - `FromInboundLaneApi` /// - constants that are stringified names of runtime API methods: -/// - `TO__ESTIMATE_MESSAGE_FEE_METHOD` -/// - `TO__MESSAGE_DETAILS_METHOD` /// - `FROM__MESSAGE_DETAILS_METHOD`, /// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). #[macro_export] @@ -283,10 +281,6 @@ macro_rules! decl_bridge_messages_runtime_apis { mod [<$chain _messages_api>] { use super::*; - /// Name of the `ToOutboundLaneApi::estimate_message_delivery_and_dispatch_fee` runtime - /// method. - pub const []: &str = - stringify!([]); /// Name of the `ToOutboundLaneApi::message_details` runtime method. pub const []: &str = stringify!([]); diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index 78ef00f6d6248..6f9f05e663e7e 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -30,8 +30,6 @@ impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { } impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - "TODO: not needed now, used for send_message and estimate_fee CLI"; type MessagesLane = BridgeHubRococoMessagesToBridgeHubWococoMessageLane; } diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index 51e1020e74953..2b38eccbcb644 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -30,8 +30,6 @@ impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { } impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - "TODO: not needed now, used for send_message and estimate_fee CLI"; type MessagesLane = BridgeHubWococoMessagesToBridgeHubRococoMessageLane; } diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs index e0dbabd86b4c5..e136b800b17a8 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs @@ -51,7 +51,5 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { } impl MessagesCliBridge for MillauToRialtoCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_rialto::TO_RIALTO_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; } diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs index cdb3999db6ed1..b830ce7fcc4e4 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -69,8 +69,6 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { } impl MessagesCliBridge for MillauToRialtoParachainCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_rialto_parachain::TO_RIALTO_PARACHAIN_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; } diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs index b1ab4a8537b6e..208b2638af01e 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs @@ -51,7 +51,5 @@ impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { } impl MessagesCliBridge for RialtoToMillauCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; } diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index 911d439938948..d1cf853ac775b 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -67,8 +67,6 @@ impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge { } impl MessagesCliBridge for RialtoParachainToMillauCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_millau::TO_MILLAU_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; } diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs index 8b208712db5d0..23e87194c9165 100644 --- a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs @@ -78,8 +78,6 @@ impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge { } impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_bridge_hub_wococo::TO_BRIDGE_HUB_WOCOCO_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane; } diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs index 453455a7b561d..caaeab566558b 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -78,8 +78,6 @@ impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge { } impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge { - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str = - bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_ESTIMATE_MESSAGE_FEE_METHOD; type MessagesLane = crate::chains::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane; } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index ae2a36cd1d553..c1923f89a8485 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -97,9 +97,6 @@ pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase { /// Bridge representation that can be used from the CLI for relaying messages. pub trait MessagesCliBridge: CliBridgeBase { - /// Name of the runtime method used to estimate the message dispatch and delivery fee for the - /// defined bridge. - const ESTIMATE_MESSAGE_FEE_METHOD: &'static str; /// The Source -> Destination messages synchronization pipeline. type MessagesLane: SubstrateMessageLane; } From ea6a875d6f7144d30d56bf073909fb97bcf9f8aa Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 2 Dec 2022 13:28:58 +0300 Subject: [PATCH 0827/1210] added version guards to RBH<>WBH GRANDPA finality (and complex) relay (#1697) --- .../rococo_headers_to_bridge_hub_wococo.rs | 23 +++++++++++++++++-- .../wococo_headers_to_bridge_hub_rococo.rs | 23 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs index 2ec13614a34a1..2fac858336d92 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs @@ -17,8 +17,12 @@ //! Rococo-to-Wococo bridge hubs headers sync entrypoint. use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, }; /// Description of Rococo -> Wococo finalized headers bridge. @@ -32,12 +36,27 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( relay_bridge_hub_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof ); +#[async_trait] impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { type SourceChain = relay_rococo_client::Rococo; type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; type FinalityEngine = GrandpaFinalityEngine; type SubmitFinalityProofCallBuilder = RococoFinalityToBridgeHubWococoCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.0, + ); + } + Ok(()) + } } /// `Rococo` to BridgeHub `Wococo` bridge definition. diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs index 30d6af00cd3b3..6089ae7328cd9 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs @@ -17,8 +17,12 @@ //! Wococo-to-Rococo bridge hubs headers sync entrypoint. use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, }; /// Description of Wococo -> Rococo finalized headers bridge. @@ -32,12 +36,27 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::submit_finality_proof ); +#[async_trait] impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { type SourceChain = relay_wococo_client::Wococo; type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; type FinalityEngine = GrandpaFinalityEngine; type SubmitFinalityProofCallBuilder = WococoFinalityToBridgeHubRococoCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.0, + ); + } + Ok(()) + } } /// `Wococo` to BridgeHub `Rococo` bridge definition. From b9348a171c9378a7744c432a3a737f452dfc4f30 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 2 Dec 2022 14:05:54 +0300 Subject: [PATCH 0828/1210] removed MintReward and added PayLaneRewardFromAccount (#1693) * removed MintReward and added PayLaneRewardFromAccount * clippy * added issue ref to TODO --- bin/millau/runtime/src/lib.rs | 3 +- bin/rialto-parachain/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/lib.rs | 3 +- modules/relayers/src/lib.rs | 30 +++++++++++--- primitives/messages/src/lib.rs | 11 +++++ primitives/relayers/Cargo.toml | 1 + primitives/relayers/src/lib.rs | 54 +++++++++++++++++++++---- 7 files changed, 89 insertions(+), 16 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index d6e99afb2d8bb..237c2aaa4c1ec 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -379,7 +379,8 @@ impl pallet_session::Config for Runtime { impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; - type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type PaymentProcedure = + bp_relayers::PayLaneRewardFromAccount, AccountId>; type WeightInfo = (); } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 0fe03883e0fe8..a30864e038a24 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -511,7 +511,8 @@ impl pallet_aura::Config for Runtime { impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; - type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type PaymentProcedure = + bp_relayers::PayLaneRewardFromAccount, AccountId>; type WeightInfo = (); } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 59284df910a26..dd4d254f17b2b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -396,7 +396,8 @@ impl pallet_authority_discovery::Config for Runtime { impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; - type PaymentProcedure = bp_relayers::MintReward, AccountId>; + type PaymentProcedure = + bp_relayers::PayLaneRewardFromAccount, AccountId>; type WeightInfo = (); } diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 921ec0e4d9820..9ae211e9b91fa 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -157,7 +157,10 @@ mod tests { use mock::{RuntimeEvent as TestEvent, *}; use crate::Event::RewardPaid; - use frame_support::{assert_noop, assert_ok, traits::fungible::Inspect}; + use frame_support::{ + assert_noop, assert_ok, + traits::fungible::{Inspect, Mutate}, + }; use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; @@ -232,16 +235,31 @@ mod tests { } #[test] - fn mint_reward_payment_procedure_actually_mints_tokens() { + fn pay_lane_reward_from_account_actually_pays_reward() { type Balances = pallet_balances::Pallet; + type PayLaneRewardFromAccount = bp_relayers::PayLaneRewardFromAccount; run_test(|| { + let lane0_rewards_account = + PayLaneRewardFromAccount::lane_rewards_account([0, 0, 0, 0]); + let lane1_rewards_account = + PayLaneRewardFromAccount::lane_rewards_account([0, 0, 0, 1]); + + Balances::mint_into(&lane0_rewards_account, 100).unwrap(); + Balances::mint_into(&lane1_rewards_account, 100).unwrap(); + assert_eq!(Balances::balance(&lane0_rewards_account), 100); + assert_eq!(Balances::balance(&lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 0); - assert_eq!(Balances::total_issuance(), 0); - bp_relayers::MintReward::::pay_reward(&1, TEST_LANE_ID, 100) - .unwrap(); + + PayLaneRewardFromAccount::pay_reward(&1, [0, 0, 0, 0], 100).unwrap(); + assert_eq!(Balances::balance(&lane0_rewards_account), 0); + assert_eq!(Balances::balance(&lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 100); - assert_eq!(Balances::total_issuance(), 100); + + PayLaneRewardFromAccount::pay_reward(&1, [0, 0, 0, 1], 100).unwrap(); + assert_eq!(Balances::balance(&lane0_rewards_account), 0); + assert_eq!(Balances::balance(&lane1_rewards_account), 0); + assert_eq!(Balances::balance(&1), 200); }); } } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index daaa2800988be..3a14724f9d6e2 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -24,6 +24,7 @@ use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; +use sp_core::TypeId; use sp_std::{collections::vec_deque::VecDeque, prelude::*}; pub mod source_chain; @@ -68,6 +69,16 @@ impl OperatingMode for MessagesOperatingMode { /// Lane identifier. pub type LaneId = [u8; 4]; +/// Lane id which implements `TypeId`. +// TODO (https://github.com/paritytech/parity-bridges-common/issues/1694): +// `LaneId` shall be replaced with this across all codebase (codec-compatible) +#[derive(Decode, Encode, RuntimeDebug)] +pub struct TypedLaneId(pub [u8; 4]); + +impl TypeId for TypedLaneId { + const TYPE_ID: [u8; 4] = *b"blan"; +} + /// Message nonce. Valid messages will never have 0 nonce. pub type MessageNonce = u64; diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 4dc09f8d12658..4f893f9f83ebc 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -19,6 +19,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] +bp-rialto = { path = "../chain-rialto" } hex = "0.4" hex-literal = "0.3" diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index bd456d36310ca..04c43d5c7813b 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -19,7 +19,11 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use bp_messages::LaneId; +use bp_messages::{LaneId, TypedLaneId}; +use sp_runtime::{ + codec::{Decode, Encode}, + traits::AccountIdConversion, +}; use sp_std::{fmt::Debug, marker::PhantomData}; /// Reward payment procedure. @@ -31,20 +35,56 @@ pub trait PaymentProcedure { fn pay_reward(relayer: &Relayer, lane_id: LaneId, reward: Reward) -> Result<(), Self::Error>; } -/// Reward payment procedure that is simply minting given amount of tokens. -pub struct MintReward(PhantomData<(T, Relayer)>); +/// Reward payment procedure that does `balances::transfer` call from the account, derived from +/// given lane. +pub struct PayLaneRewardFromAccount(PhantomData<(T, Relayer)>); -impl PaymentProcedure for MintReward +impl PayLaneRewardFromAccount where - T: frame_support::traits::fungible::Mutate, + Relayer: Decode + Encode, +{ + /// Return account that pay rewards for serving given lane. + pub fn lane_rewards_account(lane_id: LaneId) -> Relayer { + TypedLaneId(lane_id).into_sub_account_truncating(b"bridge-lane") + } +} + +impl PaymentProcedure for PayLaneRewardFromAccount +where + T: frame_support::traits::fungible::Transfer, + Relayer: Decode + Encode, { type Error = sp_runtime::DispatchError; fn pay_reward( relayer: &Relayer, - _lane_id: LaneId, + lane_id: LaneId, reward: T::Balance, ) -> Result<(), Self::Error> { - T::mint_into(relayer, reward) + T::transfer(&Self::lane_rewards_account(lane_id), relayer, reward, false).map(drop) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn lanes_are_using_different_accounts() { + assert_eq!( + PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account([ + 0, 0, 0, 0 + ]), + hex_literal::hex!("626c616e000000006272696467652d6c616e6500000000000000000000000000") + .into(), + ); + + assert_eq!( + PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account([ + 0, 0, 0, 1 + ]), + hex_literal::hex!("626c616e000000016272696467652d6c616e6500000000000000000000000000") + .into(), + ); } } From dc74c7e14573c370db1582e4532845c55de74d2f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 5 Dec 2022 11:07:27 +0300 Subject: [PATCH 0829/1210] fix clippy (#1698) --- bin/millau/node/src/service.rs | 3 +-- modules/messages/src/weights_ext.rs | 18 ++++-------------- primitives/messages/src/lib.rs | 6 +----- primitives/test-utils/src/lib.rs | 2 +- .../lib-substrate-relay/src/messages_source.rs | 3 +-- .../src/parachains/source.rs | 6 ++---- 6 files changed, 10 insertions(+), 28 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index e23e1fa56ca4f..20662d17bb9ca 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -199,8 +199,7 @@ pub fn new_full(mut config: Configuration) -> Result Ok(k) => keystore_container.set_remote_keystore(k), Err(e) => return Err(ServiceError::Other(format!( - "Error hooking up remote keystore for {}: {}", - url, e + "Error hooking up remote keystore for {url}: {e}" ))), }; } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index e597ed84cdd2b..b763ca69024e8 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -59,10 +59,7 @@ pub fn ensure_able_to_receive_message( max_incoming_message_proof_size.saturating_add(SIGNED_EXTENSIONS_SIZE); assert!( max_delivery_transaction_size <= max_extrinsic_size, - "Size of maximal message delivery transaction {} + {} is larger than maximal possible transaction size {}", - max_incoming_message_proof_size, - SIGNED_EXTENSIONS_SIZE, - max_extrinsic_size, + "Size of maximal message delivery transaction {max_incoming_message_proof_size} + {SIGNED_EXTENSIONS_SIZE} is larger than maximal possible transaction size {max_extrinsic_size}", ); // verify that we're able to receive proof of maximal-size message with maximal dispatch weight @@ -75,9 +72,7 @@ pub fn ensure_able_to_receive_message( ); assert!( max_delivery_transaction_dispatch_weight.all_lte(max_extrinsic_weight), - "Weight of maximal message delivery transaction + {} is larger than maximal possible transaction weight {}", - max_delivery_transaction_dispatch_weight, - max_extrinsic_weight, + "Weight of maximal message delivery transaction + {max_delivery_transaction_dispatch_weight} is larger than maximal possible transaction weight {max_extrinsic_weight}", ); } @@ -94,10 +89,7 @@ pub fn ensure_able_to_receive_confirmation( max_inbound_lane_data_proof_size_from_peer_chain.saturating_add(SIGNED_EXTENSIONS_SIZE); assert!( max_confirmation_transaction_size <= max_extrinsic_size, - "Size of maximal message delivery confirmation transaction {} + {} is larger than maximal possible transaction size {}", - max_inbound_lane_data_proof_size_from_peer_chain, - SIGNED_EXTENSIONS_SIZE, - max_extrinsic_size, + "Size of maximal message delivery confirmation transaction {max_inbound_lane_data_proof_size_from_peer_chain} + {SIGNED_EXTENSIONS_SIZE} is larger than maximal possible transaction size {max_extrinsic_size}", ); // verify that we're able to reward maximal number of relayers that have delivered maximal @@ -112,9 +104,7 @@ pub fn ensure_able_to_receive_confirmation( ); assert!( max_confirmation_transaction_dispatch_weight.all_lte(max_extrinsic_weight), - "Weight of maximal confirmation transaction {} is larger than maximal possible transaction weight {}", - max_confirmation_transaction_dispatch_weight, - max_extrinsic_weight, + "Weight of maximal confirmation transaction {max_confirmation_transaction_dispatch_weight} is larger than maximal possible transaction weight {max_extrinsic_weight}", ); } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 3a14724f9d6e2..5e7c2593bff40 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -408,11 +408,7 @@ mod tests { let difference = (expected_size.unwrap() as f64 - actual_size as f64).abs(); assert!( difference / (std::cmp::min(actual_size, expected_size.unwrap()) as f64) < 0.1, - "Too large difference between actual ({}) and expected ({:?}) inbound lane data size. Test case: {}+{}", - actual_size, - expected_size, - relayer_entries, - messages_count, + "Too large difference between actual ({actual_size}) and expected ({expected_size:?}) inbound lane data size. Test case: {relayer_entries}+{messages_count}", ); } } diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 186d192014bb0..e0d06ce9970a4 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -308,7 +308,7 @@ mod tests { fn print_xcm(xcm: &VersionedXcm) { println!("-----------------"); - println!("xcm (plain): {:?}", xcm); + println!("xcm (plain): {xcm:?}"); println!("xcm (bytes): {:?}", xcm.encode()); println!("xcm (hex): {:?}", hexdisplay::HexDisplay::from(&xcm.encode())); } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 57f84eb6bb19d..bf3779b3b404d 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -495,8 +495,7 @@ fn validate_out_msgs_details( ) -> Result<(), SubstrateError> { let make_missing_nonce_error = |expected_nonce| { Err(SubstrateError::Custom(format!( - "Missing nonce {} in message_details call result. Expected all nonces from {:?}", - expected_nonce, nonces, + "Missing nonce {expected_nonce} in message_details call result. Expected all nonces from {nonces:?}", ))) }; diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index 2cae7f1a2242a..b61b893e5bc21 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -147,8 +147,7 @@ where let parachain = ParaId(P::SOURCE_PARACHAIN_PARA_ID); if parachains != [parachain] { return Err(SubstrateError::Custom(format!( - "Trying to prove unexpected parachains {:?}. Expected {:?}", - parachains, parachain, + "Trying to prove unexpected parachains {parachains:?}. Expected {parachain:?}", ))) } @@ -177,8 +176,7 @@ where .transpose()? .ok_or_else(|| { SubstrateError::Custom(format!( - "Failed to read expected parachain {:?} head at {:?}", - parachain, at_block + "Failed to read expected parachain {parachain:?} head at {at_block:?}" )) })?; let parachain_head_hash = parachain_head.hash(); From e53f3f335f007ff3cdb4e3c48f38359fcc3accc8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 5 Dec 2022 13:36:11 +0300 Subject: [PATCH 0830/1210] fixed benchmarks of relayers pallet (#1700) --- bin/millau/runtime/src/lib.rs | 23 +++++++++++++++++++++-- modules/relayers/src/benchmarking.rs | 14 +++++++++++++- modules/relayers/src/lib.rs | 3 ++- modules/relayers/src/weights.rs | 6 +++--- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 237c2aaa4c1ec..3c2a21d59d2ee 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -969,13 +969,14 @@ impl_runtime_apis! { use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; use pallet_bridge_parachains::benchmarking::Pallet as ParachainsBench; + use pallet_bridge_relayers::benchmarking::Pallet as RelayersBench; let mut list = Vec::::new(); list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::); - list_benchmark!(list, extra, pallet_bridge_relayers, BridgeRelayers); + list_benchmark!(list, extra, pallet_bridge_relayers, RelayersBench::); let storage_info = AllPalletsWithSystem::storage_info(); @@ -1014,6 +1015,10 @@ impl_runtime_apis! { Pallet as ParachainsBench, Config as ParachainsConfig, }; + use pallet_bridge_relayers::benchmarking::{ + Pallet as RelayersBench, + Config as RelayersConfig, + }; use rialto_messages::WithRialtoMessageBridge; impl MessagesConfig for Runtime { @@ -1068,6 +1073,20 @@ impl_runtime_apis! { } } + impl RelayersConfig for Runtime { + fn prepare_environment( + lane: bp_messages::LaneId, + reward: Balance, + ) { + use frame_support::traits::fungible::Mutate; + let lane_rewards_account = bp_relayers::PayLaneRewardFromAccount::< + Balances, + AccountId + >::lane_rewards_account(lane); + Balances::mint_into(&lane_rewards_account, reward).unwrap(); + } + } + add_benchmark!( params, batches, @@ -1081,7 +1100,7 @@ impl_runtime_apis! { pallet_bridge_parachains, ParachainsBench:: ); - add_benchmark!(params, batches, pallet_bridge_relayers, BridgeRelayers); + add_benchmark!(params, batches, pallet_bridge_relayers, RelayersBench::); Ok(batches) } diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index b79c0fb3ff0b5..e79dda14acbbb 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -26,12 +26,24 @@ use frame_system::RawOrigin; /// Reward amount that is (hopefully) is larger than existential deposit across all chains. const REWARD_AMOUNT: u32 = u32::MAX; +/// Pallet we're benchmarking here. +pub struct Pallet(crate::Pallet); + +/// Trait that must be implemented by runtime. +pub trait Config: crate::Config { + /// Prepare environment for paying given reward for serving given lane. + fn prepare_environment(lane: LaneId, reward: Self::Reward); +} + benchmarks! { // Benchmark `claim_rewards` call. claim_rewards { let lane = [0, 0, 0, 0]; let relayer: T::AccountId = whitelisted_caller(); - RelayerRewards::::insert(&relayer, lane, T::Reward::from(REWARD_AMOUNT)); + let reward = T::Reward::from(REWARD_AMOUNT); + + T::prepare_environment(lane, reward); + RelayerRewards::::insert(&relayer, lane, reward); }: _(RawOrigin::Signed(relayer), lane) verify { // we can't check anything here, because `PaymentProcedure` is responsible for diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 9ae211e9b91fa..0c6454f714a00 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -30,7 +30,8 @@ use weights::WeightInfo; pub use pallet::*; pub use payment_adapter::MessageDeliveryAndDispatchPaymentAdapter; -mod benchmarking; +pub mod benchmarking; + mod mock; mod payment_adapter; diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 7bcd8711a9eac..26a1cfab1e4d6 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_relayers` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 +//! DATE: 2022-12-05, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -59,7 +59,7 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn claim_rewards() -> Weight { - Weight::from_ref_time(59_334_000 as u64) + Weight::from_ref_time(64_065_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } @@ -68,7 +68,7 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { fn claim_rewards() -> Weight { - Weight::from_ref_time(59_334_000 as u64) + Weight::from_ref_time(64_065_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } From e42b25690ac6bf810435967717e3f01e7052499f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 5 Dec 2022 14:03:23 +0300 Subject: [PATCH 0831/1210] only store header state root (pallet-bridge-grandpa) (#1699) --- bin/millau/runtime/src/lib.rs | 11 +- bin/rialto-parachain/runtime/src/lib.rs | 7 +- bin/rialto/runtime/src/lib.rs | 7 +- bin/runtime-common/src/messages.rs | 9 +- modules/grandpa/src/extension.rs | 5 +- modules/grandpa/src/lib.rs | 163 +++++------------------- modules/grandpa/src/mock.rs | 2 - modules/parachains/src/lib.rs | 7 +- modules/parachains/src/mock.rs | 2 - primitives/chain-millau/src/lib.rs | 3 - primitives/chain-rialto/src/lib.rs | 5 +- primitives/chain-rococo/src/lib.rs | 7 +- primitives/chain-westend/src/lib.rs | 7 +- primitives/chain-wococo/src/lib.rs | 3 +- primitives/header-chain/src/lib.rs | 42 ++++-- primitives/runtime/src/lib.rs | 26 +++- 16 files changed, 113 insertions(+), 193 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3c2a21d59d2ee..2e20afb645796 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -413,13 +413,8 @@ parameter_types! { } parameter_types! { - /// Maximal size of SCALE-encoded Rialto header. - pub const MaxRialtoHeaderSize: u32 = bp_rialto::MAX_HEADER_SIZE; - /// Maximal number of authorities at Westend. pub const MaxAuthoritiesAtWestend: u32 = bp_westend::MAX_AUTHORITIES_COUNT; - /// Maximal size of SCALE-encoded Westend header. - pub const MaxWestendHeaderSize: u32 = bp_westend::MAX_HEADER_SIZE; } pub type RialtoGrandpaInstance = (); @@ -432,7 +427,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtRialto; - type MaxBridgedHeaderSize = MaxRialtoHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -443,7 +437,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtWestend; - type MaxBridgedHeaderSize = MaxWestendHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -871,13 +864,13 @@ impl_runtime_apis! { impl bp_rialto::RialtoFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeRialtoGrandpa::best_finalized().map(|header| header.id()) + BridgeRialtoGrandpa::best_finalized() } } impl bp_westend::WestendFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeWestendGrandpa::best_finalized().map(|header| header.id()) + BridgeWestendGrandpa::best_finalized() } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index a30864e038a24..3d19dd4e75de5 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -45,7 +45,7 @@ use sp_version::NativeVersion; use sp_version::RuntimeVersion; // A few exports that help ease life for downstream crates. -use bp_runtime::{HeaderId, HeaderIdProvider}; +use bp_runtime::HeaderId; pub use frame_support::{ construct_runtime, dispatch::DispatchClass, @@ -525,8 +525,6 @@ parameter_types! { /// Maximal number of authorities at Millau. pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; - /// Maximal size of SCALE-encoded Millau header. - pub const MaxMillauHeaderSize: u32 = bp_millau::MAX_HEADER_SIZE; } pub type MillauGrandpaInstance = (); @@ -539,7 +537,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; - type MaxBridgedHeaderSize = MaxMillauHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -728,7 +725,7 @@ impl_runtime_apis! { impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeMillauGrandpa::best_finalized().map(|header| header.id()) + BridgeMillauGrandpa::best_finalized() } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index dd4d254f17b2b..0b91faf2eaa13 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -33,7 +33,7 @@ pub mod parachains; pub mod xcm_config; use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; -use bp_runtime::{HeaderId, HeaderIdProvider}; +use bp_runtime::HeaderId; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; @@ -410,8 +410,6 @@ parameter_types! { /// Maximal number of authorities at Millau. pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; - /// Maximal size of SCALE-encoded Millau header. - pub const MaxMillauHeaderSize: u32 = bp_millau::MAX_HEADER_SIZE; } pub type MillauGrandpaInstance = (); @@ -424,7 +422,6 @@ impl pallet_bridge_grandpa::Config for Runtime { type MaxRequests = ConstU32<50>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; - type MaxBridgedHeaderSize = MaxMillauHeaderSize; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -721,7 +718,7 @@ impl_runtime_apis! { impl bp_millau::MillauFinalityApi for Runtime { fn best_finalized() -> Option> { - BridgeMillauGrandpa::best_finalized().map(|header| header.id()) + BridgeMillauGrandpa::best_finalized() } } diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3530e683140bc..a0a75692ba0a0 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -705,7 +705,6 @@ mod tests { use crate::messages_generation::{ encode_all_messages, encode_lane_data, prepare_messages_storage_proof, }; - use bp_runtime::HeaderOf; use codec::{Decode, Encode}; use frame_support::weights::Weight; use sp_core::H256; @@ -881,17 +880,17 @@ mod tests { struct BridgedHeaderChain; impl HeaderChain for BridgedHeaderChain { - fn finalized_header( + fn finalized_header_state_root( _hash: HashOf, - ) -> Option> { - TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()) + ) -> Option> { + TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()).map(|h| *h.state_root()) } } struct ThisHeaderChain; impl HeaderChain for ThisHeaderChain { - fn finalized_header(_hash: HashOf) -> Option> { + fn finalized_header_state_root(_hash: HashOf) -> Option> { unreachable!() } } diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs index c0f02da751e61..87075ee5d588d 100644 --- a/modules/grandpa/src/extension.rs +++ b/modules/grandpa/src/extension.rs @@ -40,7 +40,7 @@ impl< let best_finalized = crate::BestFinalized::::get(); let best_finalized_number = match best_finalized { - Some((best_finalized_number, _)) => best_finalized_number, + Some(best_finalized_id) => best_finalized_id.number(), None => return InvalidTransaction::Call.into(), }; @@ -66,6 +66,7 @@ mod tests { mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime}, BestFinalized, }; + use bp_runtime::HeaderId; use bp_test_utils::make_default_justification; fn validate_block_submit(num: TestNumber) -> bool { @@ -81,7 +82,7 @@ mod tests { fn sync_to_header_10() { let header10_hash = sp_core::H256::default(); - BestFinalized::::put((10, header10_hash)); + BestFinalized::::put(HeaderId(10, header10_hash)); } #[test] diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 2402b2512e27c..54bf5a8810c4f 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -38,10 +38,11 @@ use storage_types::StoredAuthoritySet; -use bp_header_chain::{justification::GrandpaJustification, HeaderChain, InitializationData}; -use bp_runtime::{ - BlockNumberOf, BoundedStorageValue, Chain, HashOf, HasherOf, HeaderOf, OwnedBridgeModule, +use bp_header_chain::{ + justification::GrandpaJustification, HeaderChain, InitializationData, StoredHeaderData, + StoredHeaderDataBuilder, }; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{ensure, fail}; use frame_system::ensure_signed; @@ -73,13 +74,15 @@ pub type BridgedChain = >::BridgedChain; pub type BridgedBlockNumber = BlockNumberOf<>::BridgedChain>; /// Block hash of the bridged chain. pub type BridgedBlockHash = HashOf<>::BridgedChain>; +/// Block id of the bridged chain. +pub type BridgedBlockId = HeaderId, BridgedBlockNumber>; /// Hasher of the bridged chain. pub type BridgedBlockHasher = HasherOf<>::BridgedChain>; /// Header of the bridged chain. pub type BridgedHeader = HeaderOf<>::BridgedChain>; -/// Stored header of the bridged chain. -pub type StoredBridgedHeader = - BoundedStorageValue<>::MaxBridgedHeaderSize, BridgedHeader>; +/// Header data of the bridged chain that is stored at this chain by this pallet. +pub type BridgedStoredHeaderData = + StoredHeaderData, BridgedBlockHash>; #[frame_support::pallet] pub mod pallet { @@ -115,15 +118,6 @@ pub mod pallet { /// Max number of authorities at the bridged chain. #[pallet::constant] type MaxBridgedAuthorities: Get; - /// Maximal size (in bytes) of the SCALE-encoded bridged chain header. - /// - /// This constant must be selected with care. The pallet requires mandatory headers to be - /// submitted to be able to proceed. Mandatory headers contain public keys of all GRANDPA - /// authorities. E.g. for 1024 authorities, the size of encoded keys will be at least 32 KB. - /// The same header may also contain other digest items as well, so some reserve here - /// is required. - #[pallet::constant] - type MaxBridgedHeaderSize: Get; /// Weights gathered through benchmarking. type WeightInfo: WeightInfo; @@ -178,11 +172,8 @@ pub mod pallet { finality_target ); - let best_finalized = BestFinalized::::get(); - let best_finalized = - best_finalized.and_then(|(_, hash)| ImportedHeaders::::get(hash)); - let best_finalized = match best_finalized { - Some(best_finalized) => best_finalized, + let best_finalized_number = match BestFinalized::::get() { + Some(best_finalized_id) => best_finalized_id.number(), None => { log::error!( target: LOG_TARGET, @@ -196,7 +187,7 @@ pub mod pallet { // We do a quick check here to ensure that our header chain is making progress and isn't // "travelling back in time" (which could be indicative of something bad, e.g a // hard-fork). - ensure!(best_finalized.number() < number, >::OldHeader); + ensure!(best_finalized_number < *number, >::OldHeader); let authority_set = >::get(); let set_id = authority_set.set_id; @@ -204,20 +195,8 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; - let finality_target = StoredBridgedHeader::::try_from_inner(*finality_target) - .map_err(|e| { - log::error!( - target: LOG_TARGET, - "Size of header {:?} ({}) is larger that the configured value {}", - hash, - e.value_size, - e.maximal_size, - ); - - Error::::TooLargeHeader - })?; >::mutate(|count| *count += 1); - insert_header::(finality_target, hash); + insert_header::(*finality_target, hash); log::info!( target: LOG_TARGET, "Successfully imported finalized header with hash {:?}!", @@ -302,8 +281,9 @@ pub mod pallet { /// Hash of the best finalized header. #[pallet::storage] + #[pallet::getter(fn best_finalized)] pub type BestFinalized, I: 'static = ()> = - StorageValue<_, (BridgedBlockNumber, BridgedBlockHash), OptionQuery>; + StorageValue<_, BridgedBlockId, OptionQuery>; /// A ring buffer of imported hashes. Ordered by the insertion time. #[pallet::storage] @@ -315,10 +295,10 @@ pub mod pallet { pub(super) type ImportedHashesPointer, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; - /// Headers which have been imported into the pallet. + /// Relevant fields of imported headers. #[pallet::storage] pub type ImportedHeaders, I: 'static = ()> = - StorageMap<_, Identity, BridgedBlockHash, StoredBridgedHeader>; + StorageMap<_, Identity, BridgedBlockHash, BridgedStoredHeaderData>; /// The current GRANDPA Authority set. #[pallet::storage] @@ -394,8 +374,6 @@ pub mod pallet { AlreadyInitialized, /// Too many authorities in the set. TooManyAuthoritiesInSet, - /// Too large header. - TooLargeHeader, /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } @@ -489,13 +467,13 @@ pub mod pallet { /// Note this function solely takes care of updating the storage and pruning old entries, /// but does not verify the validity of such import. pub(crate) fn insert_header, I: 'static>( - header: StoredBridgedHeader, + header: BridgedHeader, hash: BridgedBlockHash, ) { let index = >::get(); let pruning = >::try_get(index); - >::put((*header.number(), hash)); - >::insert(hash, header); + >::put(HeaderId(*header.number(), hash)); + >::insert(hash, header.build()); >::insert(index, hash); // Update ring buffer pointer and remove old header. @@ -526,21 +504,10 @@ pub mod pallet { Error::TooManyAuthoritiesInSet })?; let initial_hash = header.hash(); - let header = StoredBridgedHeader::::try_from_inner(*header).map_err(|e| { - log::error!( - target: LOG_TARGET, - "Failed to initialize bridge. Size of header {:?} ({}) is larger that the configured value {}", - initial_hash, - e.value_size, - e.maximal_size, - ); - - Error::::TooLargeHeader - })?; >::put(initial_hash); >::put(0); - insert_header::(header, initial_hash); + insert_header::(*header, initial_hash); >::put(authority_set); @@ -568,34 +535,19 @@ pub mod pallet { Default::default(), ); let hash = header.hash(); - insert_header::( - StoredBridgedHeader::::try_from_inner(header) - .expect("only used from benchmarks; benchmarks are correct; qed"), - hash, - ); + insert_header::(header, hash); } } } -impl, I: 'static> Pallet { - /// Get the best finalized header the pallet knows of. - pub fn best_finalized() -> Option> { - let (_, hash) = >::get()?; - >::get(hash).map(|h| h.into_inner()) - } - - /// Check if a particular header is known to the bridge pallet. - pub fn is_known_header(hash: BridgedBlockHash) -> bool { - >::contains_key(hash) - } -} - /// Bridge GRANDPA pallet as header chain. pub type GrandpaChainHeaders = Pallet; impl, I: 'static> HeaderChain> for GrandpaChainHeaders { - fn finalized_header(hash: HashOf>) -> Option>> { - ImportedHeaders::::get(hash).map(|h| h.into_inner()) + fn finalized_header_state_root( + header_hash: HashOf>, + ) -> Option>> { + ImportedHeaders::::get(header_hash).map(|h| h.state_root) } } @@ -653,7 +605,7 @@ mod tests { use super::*; use crate::mock::{ run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime, - MAX_BRIDGED_AUTHORITIES, MAX_HEADER_SIZE, + MAX_BRIDGED_AUTHORITIES, }; use bp_runtime::BasicOperatingMode; use bp_test_utils::{ @@ -742,10 +694,6 @@ mod tests { Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] } } - fn large_digest() -> Digest { - Digest { logs: vec![DigestItem::Other(vec![42; MAX_HEADER_SIZE as _])] } - } - #[test] fn init_root_or_owner_origin_can_initialize_pallet() { run_test(|| { @@ -808,25 +756,6 @@ mod tests { }); } - #[test] - fn init_fails_if_header_is_too_large() { - run_test(|| { - let mut genesis = test_header(0); - genesis.digest = large_digest(); - let init_data = InitializationData { - header: Box::new(genesis), - authority_list: authority_list(), - set_id: 1, - operating_mode: BasicOperatingMode::Normal, - }; - - assert_noop!( - Pallet::::initialize(RuntimeOrigin::root(), init_data), - Error::::TooLargeHeader, - ); - }); - } - #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { @@ -1073,31 +1002,6 @@ mod tests { }); } - #[test] - fn importing_header_rejects_header_if_it_is_too_large() { - run_test(|| { - initialize_substrate_bridge(); - - // Need to update the header digest to indicate that our header signals an authority set - // change. However, the change doesn't happen until the next block. - let mut header = test_header(2); - header.digest = large_digest(); - - // Create a valid justification for the header - let justification = make_default_justification(&header); - - // Should not be allowed to import this header - assert_err!( - Pallet::::submit_finality_proof( - RuntimeOrigin::signed(1), - Box::new(header), - justification - ), - >::TooLargeHeader - ); - }); - } - #[test] fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { run_test(|| { @@ -1121,11 +1025,8 @@ mod tests { header.set_state_root(state_root); let hash = header.hash(); - >::put((2, hash)); - >::insert( - hash, - StoredBridgedHeader::::try_from_inner(header).unwrap(), - ); + >::put(HeaderId(2, hash)); + >::insert(hash, header.build()); assert_ok!( Pallet::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), @@ -1220,7 +1121,7 @@ mod tests { run_test(|| { initialize_substrate_bridge(); assert_ok!(submit_finality_proof(1)); - let first_header = Pallet::::best_finalized().unwrap(); + let first_header_hash = Pallet::::best_finalized().unwrap().hash(); next_block(); assert_ok!(submit_finality_proof(2)); @@ -1235,8 +1136,8 @@ mod tests { assert_ok!(submit_finality_proof(6)); assert!( - !Pallet::::is_known_header(first_header.hash()), - "First header should be pruned." + !ImportedHeaders::::contains_key(first_header_hash), + "First header should be pruned.", ); }) } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 12a40a688f6aa..ba6f176e8234c 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -34,7 +34,6 @@ type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; pub const MAX_BRIDGED_AUTHORITIES: u32 = 2048; -pub const MAX_HEADER_SIZE: u32 = 65536; use crate as grandpa; @@ -94,7 +93,6 @@ impl grandpa::Config for TestRuntime { type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32; - type MaxBridgedHeaderSize = frame_support::traits::ConstU32; type WeightInfo = (); } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index e6625476a3de0..9ca2ac0f48277 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -275,7 +275,7 @@ pub mod pallet { >::get(relay_block_hash) .ok_or(Error::::UnknownRelayChainBlock)?; ensure!( - *relay_block.number() == relay_block_number, + relay_block.number == relay_block_number, Error::::InvalidRelayChainBlockNumber, ); @@ -604,9 +604,10 @@ pub struct ParachainHeaders(PhantomData<(T, I, C)>); impl, I: 'static, C: Parachain> HeaderChain for ParachainHeaders { - fn finalized_header(hash: HashOf) -> Option> { + fn finalized_header_state_root(hash: HashOf) -> Option> { Pallet::::parachain_head(ParaId(C::PARACHAIN_ID), hash) - .and_then(|head| Decode::decode(&mut &head.0[..]).ok()) + .and_then(|head| HeaderOf::::decode(&mut &head.0[..]).ok()) + .map(|h| *h.state_root()) } } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 4e17a71bcdc5e..6e8df019fff09 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -100,7 +100,6 @@ impl pallet_bridge_grandpa::Config for TestRun type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; - type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; type WeightInfo = (); } @@ -109,7 +108,6 @@ impl pallet_bridge_grandpa::Config for TestRun type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; - type MaxBridgedHeaderSize = frame_support::traits::ConstU32<512>; type WeightInfo = (); } diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index ceb4be21b81c6..2a4139e07cb99 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -81,9 +81,6 @@ pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; /// Maximal number of GRANDPA authorities at Millau. pub const MAX_AUTHORITIES_COUNT: u32 = 5; -/// Maximal SCALE-encoded header size (in bytes) at Millau. -pub const MAX_HEADER_SIZE: u32 = 1024; - /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index dfb727829d9aa..4aea107777a4f 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -70,11 +70,8 @@ pub const SESSION_LENGTH: BlockNumber = 4; /// Maximal number of GRANDPA authorities at Rialto. pub const MAX_AUTHORITIES_COUNT: u32 = 5; -/// Maximal SCALE-encoded header size (in bytes) at Rialto. -pub const MAX_HEADER_SIZE: u32 = 1024; - /// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet. -pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 1024; /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 6fd7228fd75e5..32e4e30ca4abd 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -35,15 +35,12 @@ pub const PARAS_PALLET_NAME: &str = "Paras"; /// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; -/// Maximal SCALE-encoded header size (in bytes) at Rococo. +/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet. /// /// Let's assume that the largest header is header that enacts new authorities set with /// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have /// some fixed reserve for other things (digest, block hash and number, ...) as well. -pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; - -/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet. -pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; /// Maximal number of GRANDPA authorities at Rococo. /// diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 9f4a98baedc37..6df4d5ff6d542 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -37,15 +37,12 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains /// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration. pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; -/// Maximal SCALE-encoded header size (in bytes) at Westend. +/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet. /// /// Let's assume that the largest header is header that enacts new authorities set with /// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have /// some fixed reserve for other things (digest, block hash and number, ...) as well. -pub const MAX_HEADER_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; - -/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet. -pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = MAX_HEADER_SIZE; +pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; /// Identifier of Westmint parachain at the Westend relay chain. pub const WESTMINT_PARACHAIN_ID: u32 = 2000; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 0436b03c0364e..c4dc6da13f0f7 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -20,8 +20,7 @@ pub use bp_polkadot_core::*; pub use bp_rococo::{ - SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_HEADER_SIZE, MAX_NESTED_PARACHAIN_HEAD_SIZE, - PARAS_PALLET_NAME, + SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, }; use bp_runtime::decl_bridge_finality_runtime_apis; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 2b4e0802a5a70..9924366326450 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,8 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker}; -use codec::{Codec, Decode, Encode, EncodeLike}; +use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, StorageProofChecker}; +use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; use frame_support::PalletError; use scale_info::TypeInfo; @@ -52,20 +52,44 @@ impl From for &'static str { } } +/// Header data that we're storing on-chain. +/// +/// Even though we may store full header, our applications (XCM) only use couple of header +/// fields. Extracting those values makes on-chain storage and PoV smaller, which is good. +#[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] +pub struct StoredHeaderData { + /// Header number. + pub number: Number, + /// Header state root. + pub state_root: Hash, +} + +/// Stored header data builder. +pub trait StoredHeaderDataBuilder { + /// Build header data from self. + fn build(&self) -> StoredHeaderData; +} + +impl StoredHeaderDataBuilder for H { + fn build(&self) -> StoredHeaderData { + StoredHeaderData { number: *self.number(), state_root: *self.state_root() } + } +} + /// Substrate header chain, abstracted from the way it is stored. pub trait HeaderChain { - /// Returns finalized header by its hash. - fn finalized_header(hash: HashOf) -> Option>; + /// Returns state (storage) root of given finalized header. + fn finalized_header_state_root(header_hash: HashOf) -> Option>; /// Parse storage proof using finalized header. fn parse_finalized_storage_proof( - hash: HashOf, + header_hash: HashOf, storage_proof: StorageProof, parse: impl FnOnce(StorageProofChecker>) -> R, ) -> Result { - let header = Self::finalized_header(hash).ok_or(HeaderChainError::UnknownHeader)?; - let storage_proof_checker = - bp_runtime::StorageProofChecker::new(*header.state_root(), storage_proof) - .map_err(|_| HeaderChainError::StorageRootMismatch)?; + let state_root = Self::finalized_header_state_root(header_hash) + .ok_or(HeaderChainError::UnknownHeader)?; + let storage_proof_checker = bp_runtime::StorageProofChecker::new(state_root, storage_proof) + .map_err(|_| HeaderChainError::StorageRootMismatch)?; Ok(parse(storage_proof_checker)) } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 75d75c2beff59..34f521a72739b 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -96,10 +96,34 @@ pub const ROOT_ACCOUNT_DERIVATION_PREFIX: &[u8] = b"pallet-bridge/account-deriva /// Generic header Id. #[derive( - RuntimeDebug, Default, Clone, Encode, Decode, Copy, Eq, Hash, PartialEq, PartialOrd, Ord, + RuntimeDebug, + Default, + Clone, + Encode, + Decode, + Copy, + Eq, + Hash, + MaxEncodedLen, + PartialEq, + PartialOrd, + Ord, + TypeInfo, )] pub struct HeaderId(pub Number, pub Hash); +impl HeaderId { + /// Return header number. + pub fn number(&self) -> Number { + self.0 + } + + /// Return header hash. + pub fn hash(&self) -> Hash { + self.1 + } +} + /// Generic header id provider. pub trait HeaderIdProvider { // Get the header id. From 3e77b457b6a3f4a79b3cf9ae16983d1ae72a11c3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Dec 2022 16:09:21 +0300 Subject: [PATCH 0832/1210] DeliveryConfirmationPayments trait for paying relayer rewards at the source chain (#1653) * DeliveryConfirmationPayments * ref proper PR in TODO --- bin/millau/runtime/src/lib.rs | 10 +++-- bin/rialto-parachain/runtime/src/lib.rs | 5 ++- bin/rialto/runtime/src/lib.rs | 5 ++- modules/messages/src/lib.rs | 36 ++-------------- modules/messages/src/mock.rs | 6 +-- modules/relayers/Cargo.toml | 2 - modules/relayers/src/lib.rs | 2 +- modules/relayers/src/mock.rs | 33 +-------------- modules/relayers/src/payment_adapter.rs | 55 ++++++++++++++++++------- primitives/messages/src/lib.rs | 26 +++++++++++- primitives/messages/src/source_chain.rs | 31 ++++++++++++++ 11 files changed, 118 insertions(+), 93 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2e20afb645796..2bc26002b84f2 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -475,9 +475,10 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithRialtoMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::rialto_messages::Rialto; @@ -505,9 +506,10 @@ impl pallet_bridge_messages::Config for Run type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithRialtoParachainMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 3d19dd4e75de5..fd667af738a3e 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -570,9 +570,10 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithMillauMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::millau_messages::Millau; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0b91faf2eaa13..93e2ad92c18d9 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -457,9 +457,10 @@ impl pallet_bridge_messages::Config for Runtime { type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::MessageDeliveryAndDispatchPaymentAdapter< + pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, - WithMillauMessagesInstance, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, >; type SourceHeaderChain = crate::millau_messages::Millau; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index d19b17e0ddfa0..33e250574ba32 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -52,24 +52,21 @@ use crate::{ use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, - SendMessageArtifacts, TargetHeaderChain, + LaneMessageVerifier, MessageDeliveryAndDispatchPayment, SendMessageArtifacts, + TargetHeaderChain, }, target_chain::{ DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, - OutboundMessageDetails, UnrewardedRelayer, UnrewardedRelayersState, + OutboundMessageDetails, UnrewardedRelayersState, }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; use sp_runtime::traits::UniqueSaturatedFrom; -use sp_std::{ - cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive, - prelude::*, -}; +use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; @@ -725,31 +722,6 @@ fn send_message, I: 'static>( Ok(SendMessageArtifacts { nonce, weight: actual_weight }) } -/// Calculate the number of messages that the relayers have delivered. -pub fn calc_relayers_rewards( - messages_relayers: VecDeque>, - received_range: &RangeInclusive, -) -> RelayersRewards -where - T: frame_system::Config + crate::Config, - I: 'static, -{ - // remember to reward relayers that have delivered messages - // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let mut relayers_rewards = RelayersRewards::new(); - for entry in messages_relayers { - let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); - let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); - - // loop won't proceed if current entry is ahead of received range (begin > end). - // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain - if nonce_end >= nonce_begin { - *relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1; - } - } - relayers_rewards -} - /// Ensure that the pallet is in normal operational mode. fn ensure_normal_operating_mode, I: 'static>() -> Result<(), Error> { if PalletOperatingMode::::get() == diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 59f72602c84e2..599d3a6b3793c 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -17,9 +17,10 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::{calc_relayers_rewards, Config}; +use crate::Config; use bp_messages::{ + calc_relayers_rewards, source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, target_chain::{ DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, @@ -311,8 +312,7 @@ impl MessageDeliveryAndDispatchPayment _confirmation_relayer: &AccountId, received_range: &RangeInclusive, ) { - let relayers_rewards = - calc_relayers_rewards::(message_relayers, received_range); + let relayers_rewards = calc_relayers_rewards(message_relayers, received_range); for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 00d1bb591206d..27e7424a97caf 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -15,7 +15,6 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" bp-messages = { path = "../../primitives/messages", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } -pallet-bridge-messages = { path = "../messages", default-features = false } # Substrate Dependencies @@ -41,7 +40,6 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "pallet-bridge-messages/std", "scale-info/std", "sp-arithmetic/std", "sp-std/std", diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 0c6454f714a00..7467653710953 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -28,7 +28,7 @@ use sp_std::marker::PhantomData; use weights::WeightInfo; pub use pallet::*; -pub use payment_adapter::MessageDeliveryAndDispatchPaymentAdapter; +pub use payment_adapter::DeliveryConfirmationPaymentsAdapter; pub mod benchmarking; diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 55db2d575e7ef..4880e90803940 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -18,9 +18,7 @@ use crate as pallet_bridge_relayers; -use bp_messages::{ - source_chain::ForbidOutboundMessages, target_chain::ForbidInboundMessages, LaneId, -}; +use bp_messages::LaneId; use bp_relayers::PaymentProcedure; use frame_support::{parameter_types, weights::RuntimeDbWeight}; use sp_core::H256; @@ -43,7 +41,6 @@ frame_support::construct_runtime! { { System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Event}, - Messages: pallet_bridge_messages::{Pallet, Event}, Relayers: pallet_bridge_relayers::{Pallet, Call, Event}, } } @@ -91,34 +88,6 @@ impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = (); } -parameter_types! { - pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; - pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[[0, 0, 0, 0]]; -} - -// we're not testing messages pallet here, so values in this config might be crazy -impl pallet_bridge_messages::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type ActiveOutboundLanes = ActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = frame_support::traits::ConstU64<8>; - type MaxUnconfirmedMessagesAtInboundLane = frame_support::traits::ConstU64<8>; - - type MaximalOutboundPayloadSize = frame_support::traits::ConstU32<1024>; - type OutboundPayload = (); - - type InboundPayload = (); - type InboundRelayer = AccountId; - - type TargetHeaderChain = ForbidOutboundMessages; - type LaneMessageVerifier = ForbidOutboundMessages; - type MessageDeliveryAndDispatchPayment = (); - - type SourceHeaderChain = ForbidInboundMessages; - type MessageDispatch = ForbidInboundMessages; - type BridgedChainId = TestBridgedChainId; -} - impl pallet_bridge_relayers::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 4939d274c6095..750f3397e74b7 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -19,22 +19,25 @@ use crate::{Config, Pallet}; -use bp_messages::source_chain::{MessageDeliveryAndDispatchPayment, RelayersRewards}; -use frame_support::sp_runtime::SaturatedConversion; +use bp_messages::source_chain::{ + DeliveryConfirmationPayments, MessageDeliveryAndDispatchPayment, RelayersRewards, +}; +use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism /// for the messages pallet. -pub struct MessageDeliveryAndDispatchPaymentAdapter( - PhantomData<(T, MessagesInstance)>, +pub struct DeliveryConfirmationPaymentsAdapter( + PhantomData<(T, DeliveryReward, ConfirmationReward)>, ); -impl MessageDeliveryAndDispatchPayment - for MessageDeliveryAndDispatchPaymentAdapter +// TODO (https://github.com/paritytech/parity-bridges-common/pull/1652): this impl must be removed +impl + MessageDeliveryAndDispatchPayment + for DeliveryConfirmationPaymentsAdapter where - T: Config + pallet_bridge_messages::Config, - MessagesInstance: 'static, + T: Config, { type Error = &'static str; @@ -44,23 +47,47 @@ where confirmation_relayer: &T::AccountId, received_range: &RangeInclusive, ) { - let relayers_rewards = pallet_bridge_messages::calc_relayers_rewards::( - messages_relayers, - received_range, - ); + let relayers_rewards = + bp_messages::calc_relayers_rewards::(messages_relayers, received_range); register_relayers_rewards::( confirmation_relayer, relayers_rewards, lane_id, - // TODO (https://github.com/paritytech/parity-bridges-common/issues/1318): this shall be fixed - // in some way. ATM the future of the `register_relayer_reward` is not yet known 100_000_u32.into(), 10_000_u32.into(), ); } } +impl DeliveryConfirmationPayments + for DeliveryConfirmationPaymentsAdapter +where + T: Config, + DeliveryReward: Get, + ConfirmationReward: Get, +{ + type Error = &'static str; + + fn pay_reward( + lane_id: bp_messages::LaneId, + messages_relayers: VecDeque>, + confirmation_relayer: &T::AccountId, + received_range: &RangeInclusive, + ) { + let relayers_rewards = + bp_messages::calc_relayers_rewards::(messages_relayers, received_range); + + register_relayers_rewards::( + confirmation_relayer, + relayers_rewards, + lane_id, + DeliveryReward::get(), + ConfirmationReward::get(), + ); + } +} + // Update rewards to given relayers, optionally rewarding confirmation relayer. fn register_relayers_rewards( confirmation_relayer: &T::AccountId, diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 5e7c2593bff40..c288323f94159 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -25,7 +25,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; use sp_core::TypeId; -use sp_std::{collections::vec_deque::VecDeque, prelude::*}; +use sp_std::{collections::vec_deque::VecDeque, ops::RangeInclusive, prelude::*}; pub mod source_chain; pub mod storage_keys; @@ -360,6 +360,30 @@ pub fn total_unrewarded_messages( } } +/// Calculate the number of messages that the relayers have delivered. +pub fn calc_relayers_rewards( + messages_relayers: VecDeque>, + received_range: &RangeInclusive, +) -> source_chain::RelayersRewards +where + AccountId: sp_std::cmp::Ord, +{ + // remember to reward relayers that have delivered messages + // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain + let mut relayers_rewards = source_chain::RelayersRewards::new(); + for entry in messages_relayers { + let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); + let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); + + // loop won't proceed if current entry is ahead of received range (begin > end). + // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain + if nonce_end >= nonce_begin { + *relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1; + } + } + relayers_rewards +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 1cac449ee63ea..337fd05251764 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -125,6 +125,37 @@ impl MessageDeliveryAndDispatchPayment { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Pay rewards for delivering messages to the given relayers. + /// + /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is + /// a relayer that has submitted delivery confirmation transaction. + fn pay_reward( + lane_id: LaneId, + messages_relayers: VecDeque>, + confirmation_relayer: &AccountId, + received_range: &RangeInclusive, + ); +} + +impl DeliveryConfirmationPayments for () { + type Error = &'static str; + + fn pay_reward( + _lane_id: LaneId, + _messages_relayers: VecDeque>, + _confirmation_relayer: &AccountId, + _received_range: &RangeInclusive, + ) { + // this implementation is not rewarding relayers at all + } +} + /// Send message artifacts. #[derive(Eq, RuntimeDebug, PartialEq)] pub struct SendMessageArtifacts { From 72e8dd420a6f67e085af619421e0269ab7264862 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Dec 2022 12:15:27 +0300 Subject: [PATCH 0833/1210] Signed extension to refund relayer at the target chain (#1657) * add utlity pallet to the Millau runtime * RefundRelayerForMessagesDeliveryFromParachain prototype * done with RefundRelayerForMessagesDeliveryFromParachain::post_dispatch * parse calls * check batch for obsolete headers/messages * fmt * shorten generic arg names + add parachain id generic arg * check lane_id * impl all state read functions * fix typos from review * renamed extension + reference issue from TODO * tests for pre-dispaytch * renamed extension source file * tests for post-dispatch * abstract fee calculation * clippy * actually fix clippy * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu Co-authored-by: Adrian Catangiu --- bin/millau/runtime/Cargo.toml | 2 + bin/millau/runtime/src/lib.rs | 8 + bin/runtime-common/Cargo.toml | 8 + bin/runtime-common/src/lib.rs | 3 +- .../src/refund_relayer_extension.rs | 845 ++++++++++++++++++ modules/grandpa/src/lib.rs | 7 + modules/messages/src/lib.rs | 9 +- modules/parachains/src/lib.rs | 5 + modules/relayers/Cargo.toml | 2 + modules/relayers/src/lib.rs | 4 +- 10 files changed, 889 insertions(+), 4 deletions(-) create mode 100644 bin/runtime-common/src/refund_relayer_extension.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index b297dedfa5375..7605a642cdcc9 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -49,6 +49,7 @@ pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "maste pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -113,6 +114,7 @@ std = [ "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "pallet-utility/std", "pallet-xcm/std", "scale-info/std", "sp-api/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2bc26002b84f2..09171dd640c60 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -550,6 +550,13 @@ impl pallet_bridge_parachains::Config for Runtime type MaxParaHeadSize = MaxWestendParaHeadSize; } +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + construct_runtime!( pub enum Runtime where Block = Block, @@ -558,6 +565,7 @@ construct_runtime!( { System: frame_system::{Pallet, Call, Config, Storage, Event}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + Utility: pallet_utility, // Must be before session. Aura: pallet_aura::{Pallet, Config}, diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 4f8f7e34c4042..9153d7a05dda8 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -23,12 +23,15 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false } +pallet-bridge-relayers = { path = "../../modules/relayers", default-features = false } # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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 } @@ -43,6 +46,8 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] +bp-rialto = { path = "../../primitives/chain-rialto" } +bp-test-utils = { path = "../../primitives/test-utils" } millau-runtime = { path = "../millau/runtime" } [features] @@ -61,6 +66,9 @@ std = [ "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", + "pallet-transaction-payment/std", + "pallet-utility/std", "pallet-xcm/std", "scale-info/std", "sp-api/std", diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index ca8f2268404e5..f8d2e7a039ebb 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -27,6 +27,7 @@ pub mod messages_api; pub mod messages_benchmarking; pub mod messages_extension; pub mod parachains_benchmarking; +pub mod refund_relayer_extension; mod messages_generation; @@ -78,7 +79,7 @@ where #[macro_export] macro_rules! generate_bridge_reject_obsolete_headers_and_messages { ($call:ty, $account_id:ty, $($filter_call:ty),*) => { - #[derive(Clone, codec::Decode, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] + #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] pub struct BridgeRejectObsoleteHeadersAndMessages; impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs new file mode 100644 index 0000000000000..cb3448d3dd4cd --- /dev/null +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -0,0 +1,845 @@ +// Copyright 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 . + +//! Signed extension that refunds relayer if he has delivered some new messages. +//! It also refunds transaction cost if the transaction is an `utility.batchAll()` +//! with calls that are: delivering new messsage and all necessary underlying headers +//! (parachain or relay chain). + +// hack because we have circular (test-level) dependency between `millau-runtime` +// and `bridge-runtime-common` crates +#[cfg(not(test))] +use crate::messages::target::FromBridgedChainMessagesProof; +#[cfg(test)] +use millau_runtime::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; + +use bp_messages::{target_chain::SourceHeaderChain, LaneId, MessageNonce}; +use bp_polkadot_core::parachains::ParaId; +use bp_runtime::{Chain, HashOf}; +use codec::{Decode, Encode}; +use frame_support::{ + dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, + traits::IsSubType, + CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, +}; +use pallet_bridge_grandpa::{ + BridgedChain, Call as GrandpaCall, Config as GrandpaConfig, Pallet as GrandpaPallet, +}; +use pallet_bridge_messages::{ + Call as MessagesCall, Config as MessagesConfig, Pallet as MessagesPallet, +}; +use pallet_bridge_parachains::{ + Call as ParachainsCall, Config as ParachainsConfig, Pallet as ParachainsPallet, RelayBlockHash, + RelayBlockHasher, RelayBlockNumber, +}; +use pallet_bridge_relayers::{Config as RelayersConfig, Pallet as RelayersPallet}; +use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTransaction}; +use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{DispatchInfoOf, Get, Header as HeaderT, PostDispatchInfoOf, SignedExtension, Zero}, + transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, + DispatchResult, FixedPointOperand, +}; +use sp_std::marker::PhantomData; + +// TODO (https://github.com/paritytech/parity-bridges-common/issues/1667): +// support multiple bridges in this extension + +/// Transaction fee calculation. +pub trait TransactionFeeCalculation { + /// Compute fee that is paid for given transaction. The fee is later refunded to relayer. + fn compute_fee( + info: &DispatchInfo, + post_info: &PostDispatchInfo, + len: usize, + tip: Balance, + ) -> Balance; +} + +impl TransactionFeeCalculation> for R +where + R: TransactionPaymentConfig, + ::RuntimeCall: + Dispatchable, + BalanceOf: FixedPointOperand, +{ + fn compute_fee( + info: &DispatchInfo, + post_info: &PostDispatchInfo, + len: usize, + tip: BalanceOf, + ) -> BalanceOf { + pallet_transaction_payment::Pallet::::compute_actual_fee(len as _, info, post_info, tip) + } +} +/// Signed extension that refunds relayer for new messages coming from the parachain. +/// +/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) +/// with message delivery transaction. Batch may deliver either both relay chain header and +/// parachain head, or just parachain head. Corresponding headers must be used in messages +/// proof verification. +/// +/// Extension does not refund transaction tip due to security reasons. +#[derive( + CloneNoBound, Decode, Encode, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, +)] +#[scale_info(skip_type_params(RT, GI, PI, MI, BE, PID, LID, FEE))] +#[allow(clippy::type_complexity)] // TODO: get rid of that in https://github.com/paritytech/parity-bridges-common/issues/1666 +pub struct RefundRelayerForMessagesFromParachain( + PhantomData<(RT, GI, PI, MI, BE, PID, LID, FEE)>, +); + +/// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`. +#[derive(PartialEq)] +#[cfg_attr(test, derive(Debug))] +pub struct PreDispatchData { + /// Transaction submitter (relayer) account. + pub relayer: AccountId, + /// Type of the call. + pub call_type: CallType, +} + +/// Type of the call that the extension recognizes. +#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] +pub enum CallType { + /// Relay chain finality + parachain finality + message delivery calls. + AllFinalityAndDelivery(ExpectedRelayChainState, ExpectedParachainState, MessagesState), + /// Parachain finality + message delivery calls. + ParachainFinalityAndDelivery(ExpectedParachainState, MessagesState), + /// Standalone message delivery call. + Delivery(MessagesState), +} + +impl CallType { + /// Returns the pre-dispatch messages pallet state. + fn pre_dispatch_messages_state(&self) -> MessagesState { + match *self { + Self::AllFinalityAndDelivery(_, _, messages_state) => messages_state, + Self::ParachainFinalityAndDelivery(_, messages_state) => messages_state, + Self::Delivery(messages_state) => messages_state, + } + } +} + +/// Expected post-dispatch state of the relay chain pallet. +#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] +pub struct ExpectedRelayChainState { + /// Best known relay chain block number. + pub best_block_number: RelayBlockNumber, +} + +/// Expected post-dispatch state of the parachain pallet. +#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] +pub struct ExpectedParachainState { + /// At which relay block the parachain head has been updated? + pub at_relay_block_number: RelayBlockNumber, +} + +/// Pre-dispatch state of messages pallet. +/// +/// This struct is for pre-dispatch state of the pallet, not the expected post-dispatch state. +/// That's because message delivery transaction may deliver some of messages that it brings. +/// If this happens, we consider it "helpful" and refund its cost. If transaction fails to +/// deliver at least one message, it is considered wrong and is not refunded. +#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] +pub struct MessagesState { + /// Best delivered message nonce. + pub best_nonce: MessageNonce, +} + +// without this typedef rustfmt fails with internal err +type BalanceOf = + <::OnChargeTransaction as OnChargeTransaction>::Balance; +type CallOf = ::RuntimeCall; + +impl SignedExtension + for RefundRelayerForMessagesFromParachain +where + R: 'static + + Send + + Sync + + frame_system::Config + + UtilityConfig> + + GrandpaConfig + + ParachainsConfig + + MessagesConfig + + RelayersConfig, + GI: 'static + Send + Sync, + PI: 'static + Send + Sync, + MI: 'static + Send + Sync, + BE: 'static + + Send + + Sync + + Default + + SignedExtension>, + PID: 'static + Send + Sync + Get, + LID: 'static + Send + Sync + Get, + FEE: 'static + Send + Sync + TransactionFeeCalculation<::Reward>, + ::RuntimeCall: + Dispatchable, + CallOf: IsSubType, R>> + + IsSubType, R>> + + IsSubType, R>> + + IsSubType, R>>, + >::BridgedChain: + Chain, + >::SourceHeaderChain: SourceHeaderChain< + MessagesProof = FromBridgedChainMessagesProof>>, + >, +{ + const IDENTIFIER: &'static str = "RefundRelayerForMessagesFromParachain"; + type AccountId = R::AccountId; + type Call = CallOf; + type AdditionalSigned = (); + type Pre = Option>; + + fn additional_signed(&self) -> Result<(), TransactionValidityError> { + Ok(()) + } + + fn validate( + &self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + Ok(ValidTransaction::default()) + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + post_info: &DispatchInfoOf, + len: usize, + ) -> Result { + // reject batch transactions with obsolete headers + if let Some(UtilityCall::::batch_all { ref calls }) = call.is_sub_type() { + for nested_call in calls { + let reject_obsolete_transactions = BE::default(); + reject_obsolete_transactions.pre_dispatch(who, nested_call, post_info, len)?; + } + } + + // now try to check if tx matches one of types we support + let parse_call_type = || { + if let Some(UtilityCall::::batch_all { ref calls }) = call.is_sub_type() { + if calls.len() == 3 { + return Some(CallType::AllFinalityAndDelivery( + extract_expected_relay_chain_state::(&calls[0])?, + extract_expected_parachain_state::(&calls[1])?, + extract_messages_state::(&calls[2])?, + )) + } + if calls.len() == 2 { + return Some(CallType::ParachainFinalityAndDelivery( + extract_expected_parachain_state::(&calls[0])?, + extract_messages_state::(&calls[1])?, + )) + } + return None + } + + Some(CallType::Delivery(extract_messages_state::(call)?)) + }; + + Ok(parse_call_type().map(|call_type| PreDispatchData { relayer: who.clone(), call_type })) + } + + fn post_dispatch( + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + // we never refund anything if it is not bridge transaction or if it is a bridge + // transaction that we do not support here + let (relayer, call_type) = match pre { + Some(Some(pre)) => (pre.relayer, pre.call_type), + _ => return Ok(()), + }; + + // we never refund anything if transaction has failed + if result.is_err() { + return Ok(()) + } + + // check if relay chain state has been updated + if let CallType::AllFinalityAndDelivery(expected_relay_chain_state, _, _) = call_type { + let actual_relay_chain_state = relay_chain_state::(); + if actual_relay_chain_state != Some(expected_relay_chain_state) { + // we only refund relayer if all calls have updated chain state + return Ok(()) + } + + // there's a conflict between how bridge GRANDPA pallet works and the + // `AllFinalityAndDelivery` transaction. If relay chain header is mandatory, the GRANDPA + // pallet returns `Pays::No`, because such transaction is mandatory for operating the + // bridge. But `utility.batchAll` transaction always requires payment. But in both cases + // we'll refund relayer - either explicitly here, or using `Pays::No` if he's choosing + // to submit dedicated transaction. + } + + // check if parachain state has been updated + match call_type { + CallType::AllFinalityAndDelivery(_, expected_parachain_state, _) | + CallType::ParachainFinalityAndDelivery(expected_parachain_state, _) => { + let actual_parachain_state = parachain_state::(); + if actual_parachain_state != Some(expected_parachain_state) { + // we only refund relayer if all calls have updated chain state + return Ok(()) + } + }, + _ => (), + } + + // check if messages have been delivered + let actual_messages_state = messages_state::(); + let pre_dispatch_messages_state = call_type.pre_dispatch_messages_state(); + if actual_messages_state == Some(pre_dispatch_messages_state) { + // we only refund relayer if all calls have updated chain state + return Ok(()) + } + + // regarding the tip - refund that happens here (at this side of the bridge) isn't the whole + // relayer compensation. He'll receive some amount at the other side of the bridge. It shall + // (in theory) cover the tip here. Otherwise, if we'll be compensating tip here, some + // malicious relayer may use huge tips, effectively depleting account that pay rewards. The + // cost of this attack is nothing. Hence we use zero as tip here. + let tip = Zero::zero(); + + // compute the relayer reward + let reward = FEE::compute_fee(info, post_info, len, tip); + + // finally - register reward in relayers pallet + RelayersPallet::::register_relayer_reward(LID::get(), &relayer, reward); + + Ok(()) + } +} + +/// Extracts expected relay chain state from the call. +fn extract_expected_relay_chain_state(call: &CallOf) -> Option +where + R: GrandpaConfig, + GI: 'static, + >::BridgedChain: Chain, + CallOf: IsSubType, R>>, +{ + if let Some(GrandpaCall::::submit_finality_proof { ref finality_target, .. }) = + call.is_sub_type() + { + return Some(ExpectedRelayChainState { best_block_number: *finality_target.number() }) + } + None +} + +/// Extracts expected parachain state from the call. +fn extract_expected_parachain_state( + call: &CallOf, +) -> Option +where + R: GrandpaConfig + ParachainsConfig, + GI: 'static, + PI: 'static, + PID: Get, + >::BridgedChain: + Chain, + CallOf: IsSubType, R>>, +{ + if let Some(ParachainsCall::::submit_parachain_heads { + ref at_relay_block, + ref parachains, + .. + }) = call.is_sub_type() + { + if parachains.len() != 1 || parachains[0].0 != ParaId(PID::get()) { + return None + } + + return Some(ExpectedParachainState { at_relay_block_number: at_relay_block.0 }) + } + None +} + +/// Extracts messages state from the call. +fn extract_messages_state(call: &CallOf) -> Option +where + R: GrandpaConfig + MessagesConfig, + GI: 'static, + MI: 'static, + LID: Get, + CallOf: IsSubType, R>>, + >::SourceHeaderChain: SourceHeaderChain< + MessagesProof = FromBridgedChainMessagesProof>>, + >, +{ + if let Some(MessagesCall::::receive_messages_proof { ref proof, .. }) = + call.is_sub_type() + { + if LID::get() != proof.lane { + return None + } + + return Some(MessagesState { + best_nonce: MessagesPallet::::inbound_lane_data(proof.lane) + .last_delivered_nonce(), + }) + } + None +} + +/// Returns relay chain state that we are interested in. +fn relay_chain_state() -> Option +where + R: GrandpaConfig, + GI: 'static, + >::BridgedChain: Chain, +{ + GrandpaPallet::::best_finalized_number() + .map(|best_block_number| ExpectedRelayChainState { best_block_number }) +} + +/// Returns parachain state that we are interested in. +fn parachain_state() -> Option +where + R: ParachainsConfig, + PI: 'static, + PID: Get, +{ + ParachainsPallet::::best_parachain_info(ParaId(PID::get())).map(|para_info| { + ExpectedParachainState { + at_relay_block_number: para_info.best_head_hash.at_relay_block_number, + } + }) +} + +/// Returns messages state that we are interested in. +fn messages_state() -> Option +where + R: MessagesConfig, + MI: 'static, + LID: Get, +{ + Some(MessagesState { + best_nonce: MessagesPallet::::inbound_lane_data(LID::get()).last_delivered_nonce(), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_messages::InboundLaneData; + use bp_parachains::{BestParaHeadHash, ParaInfo}; + use bp_polkadot_core::parachains::ParaHeadsProof; + use bp_runtime::HeaderId; + use bp_test_utils::make_default_justification; + use frame_support::{assert_storage_noop, parameter_types, weights::Weight}; + use millau_runtime::{ + RialtoGrandpaInstance, Runtime, RuntimeCall, WithRialtoParachainMessagesInstance, + WithRialtoParachainsInstance, + }; + use sp_runtime::{transaction_validity::InvalidTransaction, DispatchError}; + + parameter_types! { + pub TestParachain: u32 = 1000; + pub TestLaneId: LaneId = [0, 0, 0, 0]; + } + + type TestExtension = RefundRelayerForMessagesFromParachain< + millau_runtime::Runtime, + RialtoGrandpaInstance, + WithRialtoParachainsInstance, + WithRialtoParachainMessagesInstance, + millau_runtime::BridgeRejectObsoleteHeadersAndMessages, + TestParachain, + TestLaneId, + millau_runtime::Runtime, + >; + + fn relayer_account() -> millau_runtime::AccountId { + [0u8; 32].into() + } + + fn initialize_environment( + best_relay_header_number: RelayBlockNumber, + parachain_head_at_relay_header_number: RelayBlockNumber, + best_delivered_message: MessageNonce, + ) { + let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); + pallet_bridge_grandpa::BestFinalized::::put( + best_relay_header, + ); + + let para_id = ParaId(TestParachain::get()); + let para_info = ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: parachain_head_at_relay_header_number, + head_hash: Default::default(), + }, + next_imported_hash_position: 0, + }; + pallet_bridge_parachains::ParasInfo::::insert( + para_id, para_info, + ); + + let lane_id = TestLaneId::get(); + let lane_data = + InboundLaneData { last_confirmed_nonce: best_delivered_message, ..Default::default() }; + pallet_bridge_messages::InboundLanes::::insert(lane_id, lane_data); + } + + fn submit_relay_header_call(relay_header_number: RelayBlockNumber) -> RuntimeCall { + let relay_header = bp_rialto::Header::new( + relay_header_number, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + let relay_justification = make_default_justification(&relay_header); + + RuntimeCall::BridgeRialtoGrandpa(GrandpaCall::submit_finality_proof { + finality_target: Box::new(relay_header), + justification: relay_justification, + }) + } + + fn submit_parachain_head_call( + parachain_head_at_relay_header_number: RelayBlockNumber, + ) -> RuntimeCall { + RuntimeCall::BridgeRialtoParachains(ParachainsCall::submit_parachain_heads { + at_relay_block: (parachain_head_at_relay_header_number, RelayBlockHash::default()), + parachains: vec![(ParaId(TestParachain::get()), [1u8; 32].into())], + parachain_heads_proof: ParaHeadsProof(vec![]), + }) + } + + fn message_delivery_call(best_message: MessageNonce) -> RuntimeCall { + RuntimeCall::BridgeRialtoParachainMessages(MessagesCall::receive_messages_proof { + relayer_id_at_bridged_chain: relayer_account(), + proof: millau_runtime::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof: vec![], + lane: TestLaneId::get(), + nonces_start: best_message, + nonces_end: best_message, + }, + messages_count: 1, + dispatch_weight: Weight::zero(), + }) + } + + fn parachain_finality_and_delivery_batch_call( + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_delivery_call(best_message), + ], + }) + } + + fn all_finality_and_delivery_batch_call( + relay_header_number: RelayBlockNumber, + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call(relay_header_number), + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_delivery_call(best_message), + ], + }) + } + + fn all_finality_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account(), + call_type: CallType::AllFinalityAndDelivery( + ExpectedRelayChainState { best_block_number: 200 }, + ExpectedParachainState { at_relay_block_number: 200 }, + MessagesState { best_nonce: 100 }, + ), + } + } + + fn parachain_finality_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account(), + call_type: CallType::ParachainFinalityAndDelivery( + ExpectedParachainState { at_relay_block_number: 200 }, + MessagesState { best_nonce: 100 }, + ), + } + } + + fn delivery_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account(), + call_type: CallType::Delivery(MessagesState { best_nonce: 100 }), + } + } + + fn run_test(test: impl FnOnce()) { + sp_io::TestExternalities::new(Default::default()).execute_with(|| test()) + } + + fn run_pre_dispatch( + call: RuntimeCall, + ) -> Result>, TransactionValidityError> { + let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData); + extension.pre_dispatch(&relayer_account(), &call, &DispatchInfo::default(), 0) + } + + fn dispatch_info() -> DispatchInfo { + DispatchInfo { + weight: frame_support::weights::constants::WEIGHT_PER_SECOND, + class: frame_support::dispatch::DispatchClass::Normal, + pays_fee: frame_support::dispatch::Pays::Yes, + } + } + + fn post_dispatch_info() -> PostDispatchInfo { + PostDispatchInfo { actual_weight: None, pays_fee: frame_support::dispatch::Pays::Yes } + } + + fn run_post_dispatch( + pre_dispatch_data: Option>, + dispatch_result: DispatchResult, + ) { + let post_dispatch_result = TestExtension::post_dispatch( + Some(pre_dispatch_data), + &dispatch_info(), + &post_dispatch_info(), + 1024, + &dispatch_result, + ); + assert_eq!(post_dispatch_result, Ok(())); + } + + fn expected_reward() -> millau_runtime::Balance { + pallet_transaction_payment::Pallet::::compute_actual_fee( + 1024, + &dispatch_info(), + &post_dispatch_info(), + Zero::zero(), + ) + } + + #[test] + fn pre_dispatch_rejects_batch_with_obsolete_relay_chain_header() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + }); + } + + #[test] + fn pre_dispatch_rejects_batch_with_obsolete_parachain_head() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + }); + } + + #[test] + fn pre_dispatch_rejects_batch_with_obsolete_messages() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + }); + } + + #[test] + fn pre_dispatch_parses_batch_with_relay_chain_and_parachain_headers() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), + Ok(Some(all_finality_pre_dispatch_data())), + ); + }); + } + + #[test] + fn pre_dispatch_parses_batch_with_parachain_header() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), + Ok(Some(parachain_finality_pre_dispatch_data())), + ); + }); + } + + #[test] + fn pre_dispatch_fails_to_parse_batch_with_multiple_parachain_headers() { + run_test(|| { + initialize_environment(100, 100, 100); + + let call = RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + RuntimeCall::BridgeRialtoParachains(ParachainsCall::submit_parachain_heads { + at_relay_block: (100, RelayBlockHash::default()), + parachains: vec![ + (ParaId(TestParachain::get()), [1u8; 32].into()), + (ParaId(TestParachain::get() + 1), [1u8; 32].into()), + ], + parachain_heads_proof: ParaHeadsProof(vec![]), + }), + message_delivery_call(200), + ], + }); + + assert_eq!(run_pre_dispatch(call), Ok(None),); + }); + } + + #[test] + fn pre_dispatch_parses_message_delivery_transaction() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_pre_dispatch(message_delivery_call(200)), + Ok(Some(delivery_pre_dispatch_data())), + ); + }); + } + + #[test] + fn post_dispatch_ignores_unknown_transaction() { + run_test(|| { + assert_storage_noop!(run_post_dispatch(None, Ok(()))); + }); + } + + #[test] + fn post_dispatch_ignores_failed_transaction() { + run_test(|| { + assert_storage_noop!(run_post_dispatch( + Some(all_finality_pre_dispatch_data()), + Err(DispatchError::BadOrigin) + )); + }); + } + + #[test] + fn post_dispatch_ignores_transaction_that_has_not_updated_relay_chain_state() { + run_test(|| { + initialize_environment(100, 200, 200); + + assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); + }); + } + + #[test] + fn post_dispatch_ignores_transaction_that_has_not_updated_parachain_state() { + run_test(|| { + initialize_environment(200, 100, 200); + + assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); + assert_storage_noop!(run_post_dispatch( + Some(parachain_finality_pre_dispatch_data()), + Ok(()) + )); + }); + } + + #[test] + fn post_dispatch_ignores_transaction_that_has_not_delivered_any_messages() { + run_test(|| { + initialize_environment(200, 200, 100); + + assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); + assert_storage_noop!(run_post_dispatch( + Some(parachain_finality_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()))); + }); + } + + #[test] + fn post_dispatch_refunds_relayer_in_all_finality_batch() { + run_test(|| { + initialize_environment(200, 200, 200); + + run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward(relayer_account(), TestLaneId::get()), + Some(expected_reward()), + ); + }); + } + + #[test] + fn post_dispatch_refunds_relayer_in_parachain_finality_batch() { + run_test(|| { + initialize_environment(200, 200, 200); + + run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward(relayer_account(), TestLaneId::get()), + Some(expected_reward()), + ); + }); + } + + #[test] + fn post_dispatch_refunds_relayer_in_message_delivery_transaction() { + run_test(|| { + initialize_environment(200, 200, 200); + + run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward(relayer_account(), TestLaneId::get()), + Some(expected_reward()), + ); + }); + } +} diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 54bf5a8810c4f..f1e4a8da1ecf2 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -540,6 +540,13 @@ pub mod pallet { } } +impl, I: 'static> Pallet { + /// Get the best finalized block number. + pub fn best_finalized_number() -> Option> { + BestFinalized::::get().map(|id| id.number()) + } +} + /// Bridge GRANDPA pallet as header chain. pub type GrandpaChainHeaders = Pallet; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 33e250574ba32..8e394c6bcea33 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -168,10 +168,10 @@ pub mod pallet { } /// Shortcut to messages proof type for Config. - type MessagesProofOf = + pub type MessagesProofOf = <>::SourceHeaderChain as SourceHeaderChain>::MessagesProof; /// Shortcut to messages delivery proof type for Config. - type MessagesDeliveryProofOf = + pub type MessagesDeliveryProofOf = <>::TargetHeaderChain as TargetHeaderChain< >::OutboundPayload, ::AccountId, @@ -631,6 +631,11 @@ pub mod pallet { dispatch_weight: T::MessageDispatch::dispatch_weight(&mut dispatch_message), } } + + /// Return inbound lane data. + pub fn inbound_lane_data(lane: LaneId) -> InboundLaneData { + InboundLanes::::get(lane).0 + } } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 9ca2ac0f48277..1b1b4de52504c 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -401,6 +401,11 @@ pub mod pallet { } impl, I: 'static> Pallet { + /// Get stored parachain info. + pub fn best_parachain_info(parachain: ParaId) -> Option { + ParasInfo::::get(parachain) + } + /// Get best finalized header of the given parachain. pub fn best_parachain_head(parachain: ParaId) -> Option { let best_para_head_hash = ParasInfo::::get(parachain)?.best_head_hash.head_hash; diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 27e7424a97caf..9c07123836381 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -22,6 +22,7 @@ frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-arithmetic = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] @@ -42,6 +43,7 @@ std = [ "log/std", "scale-info/std", "sp-arithmetic/std", + "sp-runtime/std", "sp-std/std", ] runtime-benchmarks = [ diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 7467653710953..11bbeb10845f8 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -109,8 +109,9 @@ pub mod pallet { log::trace!( target: crate::LOG_TARGET, - "Relayer {:?} can now claim reward: {:?}", + "Relayer {:?} can now claim reward for serving lane {:?}: {:?}", relayer, + lane_id, new_reward, ); }); @@ -141,6 +142,7 @@ pub mod pallet { /// Map of the relayer => accumulated reward. #[pallet::storage] + #[pallet::getter(fn relayer_reward)] pub type RelayerRewards = StorageDoubleMap< _, Blake2_128Concat, From f8255469e9e7efe512ae27a50bbc0f101da972b1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 9 Dec 2022 17:19:02 +0300 Subject: [PATCH 0834/1210] New relayer rewards scheme integration (#1652) * relayer rewards integration: initial commit * added refund-relayer-extension to the millau runtime * spelling * spelling again * new -> Default --- bin/millau/runtime/src/lib.rs | 40 +++++++++----- bin/rialto-parachain/runtime/src/lib.rs | 12 ++--- bin/rialto/runtime/src/lib.rs | 12 ++--- .../src/refund_relayer_extension.rs | 11 +++- modules/messages/src/lib.rs | 47 ++++++++++------- modules/messages/src/mock.rs | 52 ++++++++++++++----- modules/relayers/src/payment_adapter.rs | 35 +------------ primitives/messages/src/lib.rs | 8 ++- primitives/messages/src/source_chain.rs | 43 +-------------- primitives/messages/src/target_chain.rs | 34 +++++++++++- relays/client-millau/src/lib.rs | 2 + 11 files changed, 158 insertions(+), 138 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 09171dd640c60..dcb76fc32eb12 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -471,15 +471,15 @@ impl pallet_bridge_messages::Config for Runtime { type InboundPayload = crate::rialto_messages::FromRialtoMessagePayload; type InboundRelayer = bp_rialto::AccountId; + type DeliveryPayments = (); type TargetHeaderChain = crate::rialto_messages::Rialto; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<100_000>, - >; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, + >; type SourceHeaderChain = crate::rialto_messages::Rialto; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; @@ -502,15 +502,15 @@ impl pallet_bridge_messages::Config for Run type InboundPayload = crate::rialto_parachain_messages::FromRialtoParachainMessagePayload; type InboundRelayer = bp_rialto_parachain::AccountId; + type DeliveryPayments = (); type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<100_000>, - >; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<100_000>, + >; type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; @@ -518,6 +518,8 @@ impl pallet_bridge_messages::Config for Run } parameter_types! { + pub const RialtoParachainMessagesLane: bp_messages::LaneId = rialto_parachain_messages::XCM_LANE; + pub const RialtoParachainId: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID; pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME; pub const MaxRialtoParaHeadSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_SIZE; @@ -613,6 +615,19 @@ generate_bridge_reject_obsolete_headers_and_messages! { BridgeRialtoMessages, BridgeRialtoParachainMessages } +/// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. +pub type BridgeRefundRialtoParachainRelayers = + bridge_runtime_common::refund_relayer_extension::RefundRelayerForMessagesFromParachain< + Runtime, + RialtoGrandpaInstance, + WithRialtoParachainsInstance, + WithRialtoParachainMessagesInstance, + BridgeRejectObsoleteHeadersAndMessages, + RialtoParachainId, + RialtoParachainMessagesLane, + Runtime, + >; + /// The address format for describing accounts. pub type Address = AccountId; /// Block header type as expected by this runtime. @@ -634,6 +649,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundRialtoParachainRelayers, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index fd667af738a3e..6a936bd9f0775 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -566,15 +566,15 @@ impl pallet_bridge_messages::Config for Runtime { type InboundPayload = crate::millau_messages::FromMillauMessagePayload; type InboundRelayer = bp_millau::AccountId; + type DeliveryPayments = (); type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<100_000>, - >; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + frame_support::traits::ConstU128<100_000>, + frame_support::traits::ConstU128<100_000>, + >; type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 93e2ad92c18d9..355ccc0b00282 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -453,15 +453,15 @@ impl pallet_bridge_messages::Config for Runtime { type InboundPayload = crate::millau_messages::FromMillauMessagePayload; type InboundRelayer = bp_millau::AccountId; + type DeliveryPayments = (); type TargetHeaderChain = crate::millau_messages::Millau; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type MessageDeliveryAndDispatchPayment = - pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<100_000>, - >; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + frame_support::traits::ConstU128<100_000>, + frame_support::traits::ConstU128<100_000>, + >; type SourceHeaderChain = crate::millau_messages::Millau; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index cb3448d3dd4cd..6b6e2078e0022 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -33,7 +33,7 @@ use codec::{Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, traits::IsSubType, - CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, + CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; use pallet_bridge_grandpa::{ BridgedChain, Call as GrandpaCall, Config as GrandpaConfig, Pallet as GrandpaPallet, @@ -95,7 +95,14 @@ where /// /// Extension does not refund transaction tip due to security reasons. #[derive( - CloneNoBound, Decode, Encode, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, + CloneNoBound, + Decode, + DefaultNoBound, + Encode, + EqNoBound, + PartialEqNoBound, + RuntimeDebugNoBound, + TypeInfo, )] #[scale_info(skip_type_params(RT, GI, PI, MI, BE, PID, LID, FEE))] #[allow(clippy::type_complexity)] // TODO: get rid of that in https://github.com/paritytech/parity-bridges-common/issues/1666 diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 8e394c6bcea33..f2d7f4c728cac 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -52,11 +52,11 @@ use crate::{ use bp_messages::{ source_chain::{ - LaneMessageVerifier, MessageDeliveryAndDispatchPayment, SendMessageArtifacts, - TargetHeaderChain, + DeliveryConfirmationPayments, LaneMessageVerifier, SendMessageArtifacts, TargetHeaderChain, }, target_chain::{ - DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, + DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, + SourceHeaderChain, }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, @@ -143,6 +143,8 @@ pub mod pallet { /// Identifier of relayer that deliver messages to this chain. Relayer reward is paid on the /// bridged chain. type InboundRelayer: Parameter + MaxEncodedLen; + /// Delivery payments. + type DeliveryPayments: DeliveryPayments; // Types that are used by outbound_lane (on source chain). @@ -150,11 +152,8 @@ pub mod pallet { type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. type LaneMessageVerifier: LaneMessageVerifier; - /// Message delivery payment. - type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment< - Self::RuntimeOrigin, - Self::AccountId, - >; + /// Delivery confirmation payments. + type DeliveryConfirmationPayments: DeliveryConfirmationPayments; // Types that are used by inbound_lane (on target chain). @@ -377,9 +376,17 @@ pub mod pallet { messages_received_status.push(lane_messages_received_status); } + // let's now deal with relayer payments + T::DeliveryPayments::pay_reward( + relayer_id_at_this_chain, + total_messages, + valid_messages, + actual_weight, + ); + log::debug!( target: LOG_TARGET, - "Received messages: total={}, valid={}. Weight used: {}/{}", + "Received messages: total={}, valid={}. Weight used: {}/{}.", total_messages, valid_messages, actual_weight, @@ -388,7 +395,7 @@ pub mod pallet { Self::deposit_event(Event::MessagesReceived(messages_received_status)); - Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::No }) } /// Receive messages delivery proof from bridged chain. @@ -475,7 +482,7 @@ pub mod pallet { }); // if some new messages have been confirmed, reward relayers - >::MessageDeliveryAndDispatchPayment::pay_relayers_rewards( + T::DeliveryConfirmationPayments::pay_reward( lane_id, lane_data.relayers, &confirmation_relayer, @@ -879,10 +886,10 @@ mod tests { use super::*; use crate::mock::{ message, message_payload, run_test, unrewarded_relayer, DbWeight, - RuntimeEvent as TestEvent, RuntimeOrigin, TestMessageDeliveryAndDispatchPayment, - TestMessagesDeliveryProof, TestMessagesProof, TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2, - TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, + RuntimeEvent as TestEvent, RuntimeOrigin, TestDeliveryConfirmationPayments, + TestDeliveryPayments, TestMessagesDeliveryProof, TestMessagesProof, TestRuntime, + MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, + TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -1165,6 +1172,8 @@ mod tests { )); assert_eq!(InboundLanes::::get(TEST_LANE_ID).0.last_delivered_nonce(), 1); + + assert!(TestDeliveryPayments::is_reward_paid(1)); }); } @@ -1326,8 +1335,8 @@ mod tests { ..Default::default() }, )); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1)); - assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1)); + assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1)); + assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1)); // this reports delivery of both message 1 and message 2 => reward is paid only to // TEST_RELAYER_B @@ -1352,8 +1361,8 @@ mod tests { ..Default::default() }, )); - assert!(!TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_A, 1)); - assert!(TestMessageDeliveryAndDispatchPayment::is_reward_paid(TEST_RELAYER_B, 1)); + assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1)); + assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1)); }); } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 599d3a6b3793c..3f38d923b280c 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -21,10 +21,10 @@ use crate::Config; use bp_messages::{ calc_relayers_rewards, - source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, TargetHeaderChain}, + source_chain::{DeliveryConfirmationPayments, LaneMessageVerifier, TargetHeaderChain}, target_chain::{ - DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, - SourceHeaderChain, + DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch, + ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, @@ -154,10 +154,11 @@ impl Config for TestRuntime { type InboundPayload = TestPayload; type InboundRelayer = TestRelayer; + type DeliveryPayments = TestDeliveryPayments; type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; - type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment; + type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments; type SourceHeaderChain = TestSourceHeaderChain; type MessageDispatch = TestMessageDispatch; @@ -288,11 +289,38 @@ impl LaneMessageVerifier for TestLaneMessageVerifier } } -/// Message fee payment system that is used in tests. +/// Reward payments at the target chain during delivery transaction. #[derive(Debug, Default)] -pub struct TestMessageDeliveryAndDispatchPayment; +pub struct TestDeliveryPayments; -impl TestMessageDeliveryAndDispatchPayment { +impl TestDeliveryPayments { + /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is + /// cleared after the call. + pub fn is_reward_paid(relayer: AccountId) -> bool { + let key = (b":delivery-relayer-reward:", relayer).encode(); + frame_support::storage::unhashed::take::(&key).is_some() + } +} + +impl DeliveryPayments for TestDeliveryPayments { + type Error = &'static str; + + fn pay_reward( + relayer: AccountId, + _total_messages: MessageNonce, + _valid_messages: MessageNonce, + _actual_weight: Weight, + ) { + let key = (b":delivery-relayer-reward:", relayer).encode(); + frame_support::storage::unhashed::put(&key, &true); + } +} + +/// Reward payments at the source chain during delivery confirmation transaction. +#[derive(Debug, Default)] +pub struct TestDeliveryConfirmationPayments; + +impl TestDeliveryConfirmationPayments { /// Returns true if given relayer has been rewarded with given balance. The reward-paid flag is /// cleared after the call. pub fn is_reward_paid(relayer: AccountId, fee: TestMessageFee) -> bool { @@ -301,18 +329,16 @@ impl TestMessageDeliveryAndDispatchPayment { } } -impl MessageDeliveryAndDispatchPayment - for TestMessageDeliveryAndDispatchPayment -{ +impl DeliveryConfirmationPayments for TestDeliveryConfirmationPayments { type Error = &'static str; - fn pay_relayers_rewards( + fn pay_reward( _lane_id: LaneId, - message_relayers: VecDeque>, + messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, received_range: &RangeInclusive, ) { - let relayers_rewards = calc_relayers_rewards(message_relayers, received_range); + let relayers_rewards = calc_relayers_rewards(messages_relayers, received_range); for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 750f3397e74b7..946b31cf7af41 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -14,14 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Code that allows relayers pallet to be used as a delivery+dispatch payment mechanism -//! for the messages pallet. +//! Code that allows relayers pallet to be used as a payment mechanism for the messages pallet. use crate::{Config, Pallet}; -use bp_messages::source_chain::{ - DeliveryConfirmationPayments, MessageDeliveryAndDispatchPayment, RelayersRewards, -}; +use bp_messages::source_chain::{DeliveryConfirmationPayments, RelayersRewards}; use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; @@ -32,34 +29,6 @@ pub struct DeliveryConfirmationPaymentsAdapter, ); -// TODO (https://github.com/paritytech/parity-bridges-common/pull/1652): this impl must be removed -impl - MessageDeliveryAndDispatchPayment - for DeliveryConfirmationPaymentsAdapter -where - T: Config, -{ - type Error = &'static str; - - fn pay_relayers_rewards( - lane_id: bp_messages::LaneId, - messages_relayers: VecDeque>, - confirmation_relayer: &T::AccountId, - received_range: &RangeInclusive, - ) { - let relayers_rewards = - bp_messages::calc_relayers_rewards::(messages_relayers, received_range); - - register_relayers_rewards::( - confirmation_relayer, - relayers_rewards, - lane_id, - 100_000_u32.into(), - 10_000_u32.into(), - ); - } -} - impl DeliveryConfirmationPayments for DeliveryConfirmationPaymentsAdapter where diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index c288323f94159..e4f3cb5998b6c 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -24,6 +24,7 @@ use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; +use source_chain::RelayersRewards; use sp_core::TypeId; use sp_std::{collections::vec_deque::VecDeque, ops::RangeInclusive, prelude::*}; @@ -364,19 +365,16 @@ pub fn total_unrewarded_messages( pub fn calc_relayers_rewards( messages_relayers: VecDeque>, received_range: &RangeInclusive, -) -> source_chain::RelayersRewards +) -> RelayersRewards where AccountId: sp_std::cmp::Ord, { // remember to reward relayers that have delivered messages // this loop is bounded by `T::MaxUnrewardedRelayerEntriesAtInboundLane` on the bridged chain - let mut relayers_rewards = source_chain::RelayersRewards::new(); + let mut relayers_rewards = RelayersRewards::new(); for entry in messages_relayers { let nonce_begin = sp_std::cmp::max(entry.messages.begin, *received_range.start()); let nonce_end = sp_std::cmp::min(entry.messages.end, *received_range.end()); - - // loop won't proceed if current entry is ahead of received range (begin > end). - // this loop is bound by `T::MaxUnconfirmedMessagesAtInboundLane` on the bridged chain if nonce_end >= nonce_begin { *relayers_rewards.entry(entry.relayer).or_default() += nonce_end - nonce_begin + 1; } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 337fd05251764..d5d7549099c31 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -88,43 +88,6 @@ pub trait LaneMessageVerifier { ) -> Result<(), Self::Error>; } -/// Message delivery payment. It is called as a part of submit-message transaction. Transaction -/// submitter is paying (in source chain tokens/assets) for: -/// -/// 1) submit-message-transaction-fee itself. This fee is not included in the -/// `delivery_and_dispatch_fee` and is withheld by the regular transaction payment mechanism; -/// 2) message-delivery-transaction-fee. It is submitted to the target node by relayer; -/// 3) message-dispatch fee. It is paid by relayer for processing message by target chain; -/// 4) message-receiving-delivery-transaction-fee. It is submitted to the source node -/// by relayer. -pub trait MessageDeliveryAndDispatchPayment { - /// Error type. - type Error: Debug + Into<&'static str>; - - /// Pay rewards for delivering messages to the given relayers. - /// - /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is - /// a relayer that has submitted delivery confirmation transaction. - fn pay_relayers_rewards( - lane_id: LaneId, - messages_relayers: VecDeque>, - confirmation_relayer: &AccountId, - received_range: &RangeInclusive, - ); -} - -impl MessageDeliveryAndDispatchPayment for () { - type Error = &'static str; - - fn pay_relayers_rewards( - _lane_id: LaneId, - _messages_relayers: VecDeque>, - _confirmation_relayer: &AccountId, - _received_range: &RangeInclusive, - ) { - } -} - /// Manages payments that are happening at the source chain during delivery confirmation /// transaction. pub trait DeliveryConfirmationPayments { @@ -233,12 +196,10 @@ impl LaneMessageVerifier for Forbi } } -impl MessageDeliveryAndDispatchPayment - for ForbidOutboundMessages -{ +impl DeliveryConfirmationPayments for ForbidOutboundMessages { type Error = &'static str; - fn pay_relayers_rewards( + fn pay_reward( _lane_id: LaneId, _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 1a3daad404388..1b285b065aa27 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -16,7 +16,7 @@ //! Primitives of messages module, that are used on the target chain. -use crate::{LaneId, Message, MessageKey, MessagePayload, OutboundLaneData}; +use crate::{LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData}; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; @@ -112,6 +112,25 @@ pub trait MessageDispatch { ) -> MessageDispatchResult; } +/// Manages payments that are happening at the target chain during message delivery transaction. +pub trait DeliveryPayments { + /// Error type. + type Error: Debug + Into<&'static str>; + + /// Pay rewards for delivering messages to the given relayer. + /// + /// This method is called during message delivery transaction which has been submitted + /// by the `relayer`. The transaction brings `total_messages` messages but only + /// `valid_messages` have been accepted. The post-dispatch transaction weight is the + /// `actual_weight`. + fn pay_reward( + relayer: AccountId, + total_messages: MessageNonce, + valid_messages: MessageNonce, + actual_weight: Weight, + ); +} + impl Default for ProvedLaneMessages { fn default() -> Self { ProvedLaneMessages { lane_state: None, messages: Vec::new() } @@ -130,6 +149,19 @@ impl From for DispatchMessageData DeliveryPayments for () { + type Error = &'static str; + + fn pay_reward( + _relayer: AccountId, + _total_messages: MessageNonce, + _valid_messages: MessageNonce, + _actual_weight: Weight, + ) { + // this implementation is not rewarding relayer at all + } +} + /// Structure that may be used in place of `SourceHeaderChain` and `MessageDispatch` on chains, /// where inbound messages are forbidden. pub struct ForbidInboundMessages; diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index f8b350d3d0c2e..023d93fb72d92 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -114,6 +114,7 @@ impl ChainWithTransactions for Millau { frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), millau_runtime::BridgeRejectObsoleteHeadersAndMessages, + millau_runtime::BridgeRefundRialtoParachainRelayers::default(), ), ( (), @@ -125,6 +126,7 @@ impl ChainWithTransactions for Millau { (), (), (), + () ), ); let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); From b388080ff93d913c4acee39a8efc2f7500655a8d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 12 Dec 2022 09:15:36 +0300 Subject: [PATCH 0835/1210] Only store header state root (pallet-bridge-parachains) (#1701) * store block number ++ state root in parachains pallet * fixed parachains finality APIs * (test commit) * removed test code * deduplicated code a bit * removed commented code * spelling * Update modules/parachains/src/lib.rs Co-authored-by: Adrian Catangiu * Update modules/parachains/src/lib.rs Co-authored-by: Adrian Catangiu * Update modules/parachains/src/mock.rs Co-authored-by: Adrian Catangiu * added comment Co-authored-by: Adrian Catangiu --- bin/millau/runtime/Cargo.toml | 2 + bin/millau/runtime/src/lib.rs | 34 +-- modules/parachains/Cargo.toml | 1 + modules/parachains/src/lib.rs | 233 +++++++++++------- modules/parachains/src/mock.rs | 120 ++++++++- primitives/chain-rialto/src/lib.rs | 8 +- primitives/chain-rococo/src/lib.rs | 10 +- primitives/chain-westend/Cargo.toml | 2 + primitives/chain-westend/src/lib.rs | 40 ++- primitives/chain-wococo/src/lib.rs | 2 +- primitives/parachains/Cargo.toml | 7 + primitives/parachains/src/lib.rs | 66 ++++- primitives/polkadot-core/src/parachains.rs | 4 +- primitives/runtime/src/chain.rs | 5 +- primitives/runtime/src/lib.rs | 13 +- relays/client-substrate/src/lib.rs | 7 +- relays/finality/src/sync_loop_metrics.rs | 19 +- .../src/parachains/target.rs | 20 +- relays/messages/src/metrics.rs | 14 +- .../parachains/src/parachains_loop_metrics.rs | 13 +- relays/utils/Cargo.toml | 1 + relays/utils/src/lib.rs | 5 +- 22 files changed, 448 insertions(+), 178 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 7605a642cdcc9..d3aabdcba392c 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -16,6 +16,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-parachains = { path = "../../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } @@ -84,6 +85,7 @@ std = [ "beefy-primitives/std", "bp-messages/std", "bp-millau/std", + "bp-parachains/std", "bp-polkadot-core/std", "bp-relayers/std", "bp-rialto/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dcb76fc32eb12..19a8770430a7f 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -33,8 +33,8 @@ pub mod rialto_parachain_messages; pub mod xcm_config; use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; -use bp_runtime::{HeaderId, HeaderIdProvider}; -use codec::Decode; +use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_runtime::HeaderId; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; @@ -522,8 +522,8 @@ parameter_types! { pub const RialtoParachainId: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID; pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME; - pub const MaxRialtoParaHeadSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_SIZE; - pub const MaxWestendParaHeadSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_SIZE; + pub const MaxRialtoParaHeadDataSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; + pub const MaxWestendParaHeadDataSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; } /// Instance of the with-Rialto parachains pallet. @@ -534,9 +534,10 @@ impl pallet_bridge_parachains::Config for Runtime type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; type ParasPalletName = RialtoParasPalletName; - type TrackedParachains = frame_support::traits::Everything; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; type HeadsToKeep = HeadersToKeep; - type MaxParaHeadSize = MaxRialtoParaHeadSize; + type MaxParaHeadDataSize = MaxRialtoParaHeadDataSize; } /// Instance of the with-Westend parachains pallet. @@ -547,9 +548,9 @@ impl pallet_bridge_parachains::Config for Runtime type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; - type TrackedParachains = frame_support::traits::Everything; + type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder; type HeadsToKeep = HeadersToKeep; - type MaxParaHeadSize = MaxWestendParaHeadSize; + type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; } impl pallet_utility::Config for Runtime { @@ -902,28 +903,19 @@ impl_runtime_apis! { impl bp_westend::WestmintFinalityApi for Runtime { fn best_finalized() -> Option> { - // the parachains finality pallet is never decoding parachain heads, so it is - // only done in the integration code - use bp_westend::WESTMINT_PARACHAIN_ID; - let encoded_head = pallet_bridge_parachains::Pallet::< + pallet_bridge_parachains::Pallet::< Runtime, WithWestendParachainsInstance, - >::best_parachain_head(WESTMINT_PARACHAIN_ID.into())?; - let head = bp_westend::Header::decode(&mut &encoded_head.0[..]).ok()?; - Some(head.id()) + >::best_parachain_head_id::().unwrap_or(None) } } impl bp_rialto_parachain::RialtoParachainFinalityApi for Runtime { fn best_finalized() -> Option> { - // the parachains finality pallet is never decoding parachain heads, so it is - // only done in the integration code - let encoded_head = pallet_bridge_parachains::Pallet::< + pallet_bridge_parachains::Pallet::< Runtime, WithRialtoParachainsInstance, - >::best_parachain_head(bp_rialto_parachain::RIALTO_PARACHAIN_ID.into())?; - let head = bp_rialto_parachain::Header::decode(&mut &encoded_head.0[..]).ok()?; - Some(head.id()) + >::best_parachain_head_id::().unwrap_or(None) } } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index ce674459eacfc..3c3ad95fe3427 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -30,6 +30,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", [dev-dependencies] bp-header-chain = { path = "../../primitives/header-chain" } bp-test-utils = { path = "../../primitives/test-utils" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 1b1b4de52504c..bf2ab8dcd647a 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -27,12 +27,10 @@ pub use weights::WeightInfo; pub use weights_ext::WeightInfoExt; use bp_header_chain::HeaderChain; -use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo}; +use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo, ParaStoredHeaderData}; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; -use bp_runtime::{HashOf, HeaderOf, Parachain, StorageProofError}; -use codec::Decode; -use frame_support::{dispatch::PostDispatchInfo, traits::Contains}; -use sp_runtime::traits::Header as HeaderT; +use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain, StorageProofError}; +use frame_support::dispatch::PostDispatchInfo; use sp_std::{marker::PhantomData, vec::Vec}; // Re-export in crate namespace for `construct_runtime!`. @@ -69,7 +67,10 @@ struct UpdateParachainHeadArtifacts { #[frame_support::pallet] pub mod pallet { use super::*; - use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; + use bp_parachains::{ + BestParaHeadHash, ImportedParaHeadsKeyProvider, ParaStoredHeaderDataBuilder, + ParasInfoKeyProvider, + }; use bp_runtime::{ BasicOperatingMode, BoundedStorageValue, OwnedBridgeModule, StorageDoubleMapKeyProvider, StorageMapKeyProvider, @@ -77,9 +78,9 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; - /// Stored parachain head of given parachains pallet. - pub type StoredParaHeadOf = - BoundedStorageValue<>::MaxParaHeadSize, ParaHead>; + /// Stored parachain head data of given parachains pallet. + pub type StoredParaHeadDataOf = + BoundedStorageValue<>::MaxParaHeadDataSize, ParaStoredHeaderData>; /// Weight info of the given parachains pallet. pub type WeightInfoOf = >::WeightInfo; @@ -153,12 +154,18 @@ pub mod pallet { #[pallet::constant] type ParasPalletName: Get<&'static str>; - /// Set of parachains that are tracked by this pallet. + /// Parachain head data builder. + /// + /// We never store parachain heads here, since they may be too big (e.g. because of large + /// digest items). Instead we're using the same approach as `pallet-bridge-grandpa` + /// pallet - we are only storing `bp_messages::StoredHeaderData` (number and state root), + /// which is enough for our applications. However, we work with different parachains here + /// and they can use different primitives (for block numbers and hash). So we can't store + /// it directly. Instead, we're storing `bp_messages::StoredHeaderData` in SCALE-encoded + /// form, wrapping it into `bp_parachains::ParaStoredHeaderData`. /// - /// The set may be extended easily, without requiring any runtime upgrades. Removing tracked - /// parachain requires special handling - pruning existing heads and cleaning related data - /// structures. - type TrackedParachains: Contains; + /// This builder helps to convert from `HeadData` to `bp_parachains::ParaStoredHeaderData`. + type ParaStoredHeaderDataBuilder: ParaStoredHeaderDataBuilder; /// Maximal number of single parachain heads to keep in the storage. /// @@ -170,16 +177,17 @@ pub mod pallet { #[pallet::constant] type HeadsToKeep: Get; - /// Maximal size (in bytes) of the SCALE-encoded parachain head. + /// Maximal size (in bytes) of the SCALE-encoded parachain head data + /// (`bp_parachains::ParaStoredHeaderData`). /// - /// Keep in mind that the size of any tracked parachain header must not exceed this value. - /// So if you're going to track multiple parachains, one of which is storing large digests - /// in its headers, you shall choose this maximal value. + /// Keep in mind that the size of any tracked parachain header data must not exceed this + /// value. So if you're going to track multiple parachains, one of which is using large + /// hashes, you shall choose this maximal value. /// /// There's no mandatory headers in this pallet, so it can't stall if there's some header /// that exceeds this bound. #[pallet::constant] - type MaxParaHeadSize: Get; + type MaxParaHeadDataSize: Get; } /// Optional pallet owner. @@ -212,7 +220,7 @@ pub mod pallet { ::Value, >; - /// Parachain heads which have been imported into the pallet. + /// State roots of parachain heads which have been imported into the pallet. #[pallet::storage] pub type ImportedParaHeads, I: 'static = ()> = StorageDoubleMap< _, @@ -220,7 +228,7 @@ pub mod pallet { ::Key1, ::Hasher2, ::Key2, - StoredParaHeadOf, + StoredParaHeadDataOf, >; /// A ring buffer of imported parachain head hashes. Ordered by the insertion time. @@ -291,17 +299,6 @@ pub mod pallet { sp_trie::StorageProof::new(parachain_heads_proof.0), move |storage| { for (parachain, parachain_head_hash) in parachains { - // if we're not tracking this parachain, we'll just ignore its head proof here - if !T::TrackedParachains::contains(¶chain) { - log::trace!( - target: LOG_TARGET, - "The head of parachain {:?} has been provided, but it is not tracked by the pallet", - parachain, - ); - Self::deposit_event(Event::UntrackedParachainRejected { parachain }); - continue; - } - let parachain_head = match Pallet::::read_parachain_head(&storage, parachain) { Ok(Some(parachain_head)) => parachain_head, Ok(None) => { @@ -349,12 +346,26 @@ pub mod pallet { continue; } + // convert from parachain head into stored parachain head data + let parachain_head_data = match T::ParaStoredHeaderDataBuilder::try_build(parachain, ¶chain_head) { + Some(parachain_head_data) => parachain_head_data, + None => { + log::trace!( + target: LOG_TARGET, + "The head of parachain {:?} has been provided, but it is not tracked by the pallet", + parachain, + ); + Self::deposit_event(Event::UntrackedParachainRejected { parachain }); + continue; + }, + }; + let update_result: Result<_, ()> = ParasInfo::::try_mutate(parachain, |stored_best_head| { let artifacts = Pallet::::update_parachain_head( parachain, stored_best_head.take(), relay_block_number, - parachain_head, + parachain_head_data, parachain_head_hash, )?; *stored_best_head = Some(artifacts.best_head); @@ -406,14 +417,36 @@ pub mod pallet { ParasInfo::::get(parachain) } - /// Get best finalized header of the given parachain. - pub fn best_parachain_head(parachain: ParaId) -> Option { + /// Get best finalized head data of the given parachain. + pub fn best_parachain_head(parachain: ParaId) -> Option { let best_para_head_hash = ParasInfo::::get(parachain)?.best_head_hash.head_hash; ImportedParaHeads::::get(parachain, best_para_head_hash).map(|h| h.into_inner()) } - /// Get parachain head with given hash. - pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option { + /// Get best finalized head hash of the given parachain. + pub fn best_parachain_head_hash(parachain: ParaId) -> Option { + Some(ParasInfo::::get(parachain)?.best_head_hash.head_hash) + } + + /// Get best finalized head id of the given parachain. + pub fn best_parachain_head_id + Parachain>( + ) -> Result>, codec::Error> { + let parachain = ParaId(C::PARACHAIN_ID); + let best_head_hash = match Self::best_parachain_head_hash(parachain) { + Some(best_head_hash) => best_head_hash, + None => return Ok(None), + }; + let encoded_head = match Self::parachain_head(parachain, best_head_hash) { + Some(encoded_head) => encoded_head, + None => return Ok(None), + }; + encoded_head + .decode_parachain_head_data::() + .map(|data| Some(HeaderId(data.number, best_head_hash))) + } + + /// Get parachain head data with given hash. + pub fn parachain_head(parachain: ParaId, hash: ParaHash) -> Option { ImportedParaHeads::::get(parachain, hash).map(|h| h.into_inner()) } @@ -480,7 +513,7 @@ pub mod pallet { parachain: ParaId, stored_best_head: Option, updated_at_relay_block_number: RelayBlockNumber, - updated_head: ParaHead, + updated_head_data: ParaStoredHeaderData, updated_head_hash: ParaHash, ) -> Result { // check if head has been already updated at better relay chain block. Without this @@ -501,28 +534,29 @@ pub mod pallet { return Err(()) } - // verify that the parachain head size is <= `MaxParaHeadSize` - let updated_head = match StoredParaHeadOf::::try_from_inner(updated_head) { - Ok(updated_head) => updated_head, - Err(e) => { - log::trace!( - target: LOG_TARGET, - "{}. The parachain head size for {:?} is {}. It exceeds maximal configured size {}.", - err_log_prefix, - parachain, - e.value_size, - e.maximal_size, - ); - - Self::deposit_event(Event::RejectedLargeParachainHead { - parachain, - parachain_head_hash: updated_head_hash, - parachain_head_size: e.value_size as _, - }); - - return Err(()) - }, - }; + // verify that the parachain head data size is <= `MaxParaHeadDataSize` + let updated_head_data = + match StoredParaHeadDataOf::::try_from_inner(updated_head_data) { + Ok(updated_head_data) => updated_head_data, + Err(e) => { + log::trace!( + target: LOG_TARGET, + "{}. The parachain head data size for {:?} is {}. It exceeds maximal configured size {}.", + err_log_prefix, + parachain, + e.value_size, + e.maximal_size, + ); + + Self::deposit_event(Event::RejectedLargeParachainHead { + parachain, + parachain_head_hash: updated_head_hash, + parachain_head_size: e.value_size as _, + }); + + return Err(()) + }, + }; let next_imported_hash_position = stored_best_head .map_or(0, |stored_best_head| stored_best_head.next_imported_hash_position); @@ -543,7 +577,7 @@ pub mod pallet { next_imported_hash_position, updated_head_hash, ); - ImportedParaHeads::::insert(parachain, updated_head_hash, updated_head); + ImportedParaHeads::::insert(parachain, updated_head_hash, updated_head_data); log::trace!( target: LOG_TARGET, "Updated head of parachain {:?} to {}", @@ -611,8 +645,8 @@ impl, I: 'static, C: Parachain> HeaderChain { fn finalized_header_state_root(hash: HashOf) -> Option> { Pallet::::parachain_head(ParaId(C::PARACHAIN_ID), hash) - .and_then(|head| HeaderOf::::decode(&mut &head.0[..]).ok()) - .map(|h| *h.state_root()) + .and_then(|head| head.decode_parachain_head_data::().ok()) + .map(|h| h.state_root) } } @@ -620,8 +654,9 @@ impl, I: 'static, C: Parachain> HeaderChain mod tests { use super::*; use crate::mock::{ - run_test, test_relay_header, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, - MAXIMAL_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, + run_test, test_relay_header, BigParachainHeader, RegularParachainHasher, + RegularParachainHeader, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, + PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, }; use codec::Encode; @@ -641,7 +676,8 @@ mod tests { weights::Weight, }; use frame_system::{EventRecord, Pallet as System, Phase}; - use sp_runtime::DispatchError; + use sp_core::Hasher; + use sp_runtime::{traits::Header as HeaderT, DispatchError}; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; @@ -716,12 +752,42 @@ mod tests { } fn head_data(parachain: u32, head_number: u32) -> ParaHead { - ParaHead((parachain, head_number).encode()) + ParaHead( + RegularParachainHeader::new( + head_number as _, + Default::default(), + RegularParachainHasher::hash(&(parachain, head_number).encode()), + Default::default(), + Default::default(), + ) + .encode(), + ) } - fn large_head_data(parachain: u32, head_number: u32) -> ParaHead { + fn stored_head_data(parachain: u32, head_number: u32) -> ParaStoredHeaderData { + ParaStoredHeaderData( + (head_number as u64, RegularParachainHasher::hash(&(parachain, head_number).encode())) + .encode(), + ) + } + + fn big_head_data(parachain: u32, head_number: u32) -> ParaHead { ParaHead( - (parachain, head_number, vec![42u8; MAXIMAL_PARACHAIN_HEAD_SIZE as usize]).encode(), + BigParachainHeader::new( + head_number as _, + Default::default(), + RegularParachainHasher::hash(&(parachain, head_number).encode()), + Default::default(), + Default::default(), + ) + .encode(), + ) + } + + fn big_stored_head_data(parachain: u32, head_number: u32) -> ParaStoredHeaderData { + ParaStoredHeaderData( + (head_number as u128, RegularParachainHasher::hash(&(parachain, head_number).encode())) + .encode(), ) } @@ -823,7 +889,7 @@ mod tests { initial_best_head(1).best_head_hash.head_hash ) .map(|h| h.into_inner()), - Some(head_data(1, 0)) + Some(stored_head_data(1, 0)) ); assert_eq!( ImportedParaHeads::::get( @@ -836,7 +902,7 @@ mod tests { assert_eq!( ImportedParaHeads::::get(ParaId(3), head_hash(3, 10)) .map(|h| h.into_inner()), - Some(head_data(3, 10)) + Some(stored_head_data(3, 10)) ); assert_eq!( @@ -886,7 +952,7 @@ mod tests { assert_eq!( ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()) .map(|h| h.into_inner()), - Some(head_data(1, 5)) + Some(stored_head_data(1, 5)) ); assert_eq!( ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()) @@ -921,12 +987,12 @@ mod tests { assert_eq!( ImportedParaHeads::::get(ParaId(1), head_data(1, 5).hash()) .map(|h| h.into_inner()), - Some(head_data(1, 5)) + Some(stored_head_data(1, 5)) ); assert_eq!( ImportedParaHeads::::get(ParaId(1), head_data(1, 10).hash()) .map(|h| h.into_inner()), - Some(head_data(1, 10)) + Some(stored_head_data(1, 10)) ); assert_eq!( System::::events(), @@ -1153,10 +1219,9 @@ mod tests { #[test] fn does_nothing_when_parachain_head_is_too_large() { let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (2, large_head_data(1, 5))]); + prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (4, big_head_data(1, 5))]); run_test(|| { - // start with relay block #0 and try to import head#5 of parachain#1 and untracked - // parachain + // start with relay block #0 and try to import head#5 of parachain#1 and big parachain initialize(state_root); let result = Pallet::::submit_parachain_heads( RuntimeOrigin::signed(1), @@ -1175,7 +1240,7 @@ mod tests { next_imported_hash_position: 1, }) ); - assert_eq!(ParasInfo::::get(ParaId(2)), None); + assert_eq!(ParasInfo::::get(ParaId(4)), None); assert_eq!( System::::events(), vec![ @@ -1190,9 +1255,9 @@ mod tests { EventRecord { phase: Phase::Initialization, event: TestEvent::Parachains(Event::RejectedLargeParachainHead { - parachain: ParaId(2), - parachain_head_hash: large_head_data(1, 5).hash(), - parachain_head_size: large_head_data(1, 5).encoded_size() as u32, + parachain: ParaId(4), + parachain_head_hash: big_head_data(1, 5).hash(), + parachain_head_size: big_stored_head_data(1, 5).encoded_size() as u32, }), topics: vec![], }, @@ -1294,7 +1359,7 @@ mod tests { import_parachain_1_head(0, state_root_5, parachains_5, proof_5).expect("ok"); assert_eq!( Pallet::::best_parachain_head(ParaId(1)), - Some(head_data(1, 5)) + Some(stored_head_data(1, 5)) ); // then if someone is pretending to provide updated head#10 of parachain#1 at relay @@ -1310,7 +1375,7 @@ mod tests { ),); assert_eq!( Pallet::::best_parachain_head(ParaId(1)), - Some(head_data(1, 5)) + Some(stored_head_data(1, 5)) ); // then if someone is pretending to provide updated head#10 of parachain#1 at relay @@ -1326,7 +1391,7 @@ mod tests { ),); assert_eq!( Pallet::::best_parachain_head(ParaId(1)), - Some(head_data(1, 10)) + Some(stored_head_data(1, 10)) ); }); } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 6e8df019fff09..118a9b1d31558 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -15,16 +15,12 @@ // along with Parity Bridges Common. If not, see . use bp_polkadot_core::parachains::ParaId; -use bp_runtime::Chain; -use frame_support::{ - construct_runtime, parameter_types, - traits::{ConstU32, IsInVec}, - weights::Weight, -}; +use bp_runtime::{Chain, Parachain}; +use frame_support::{construct_runtime, parameter_types, traits::ConstU32, weights::Weight}; use sp_runtime::{ testing::{Header, H256}, traits::{BlakeTwo256, Header as HeaderT, IdentityLookup}, - Perbill, + MultiSignature, Perbill, }; use crate as pallet_bridge_parachains; @@ -40,7 +36,109 @@ type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + +pub struct Parachain1; + +impl Chain for Parachain1 { + type BlockNumber = u64; + type Hash = H256; + type Hasher = RegularParachainHasher; + type Header = RegularParachainHeader; + type AccountId = u64; + type Balance = u64; + type Index = u64; + type Signature = MultiSignature; + + fn max_extrinsic_size() -> u32 { + 0 + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +impl Parachain for Parachain1 { + const PARACHAIN_ID: u32 = 1; +} + +pub struct Parachain2; + +impl Chain for Parachain2 { + type BlockNumber = u64; + type Hash = H256; + type Hasher = RegularParachainHasher; + type Header = RegularParachainHeader; + type AccountId = u64; + type Balance = u64; + type Index = u64; + type Signature = MultiSignature; + + fn max_extrinsic_size() -> u32 { + 0 + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +impl Parachain for Parachain2 { + const PARACHAIN_ID: u32 = 2; +} + +pub struct Parachain3; + +impl Chain for Parachain3 { + type BlockNumber = u64; + type Hash = H256; + type Hasher = RegularParachainHasher; + type Header = RegularParachainHeader; + type AccountId = u64; + type Balance = u64; + type Index = u64; + type Signature = MultiSignature; + + fn max_extrinsic_size() -> u32 { + 0 + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +impl Parachain for Parachain3 { + const PARACHAIN_ID: u32 = 3; +} + +// this parachain is using u128 as block number and stored head data size exceeds limit +pub struct BigParachain; + +impl Chain for BigParachain { + type BlockNumber = u128; + type Hash = H256; + type Hasher = RegularParachainHasher; + type Header = BigParachainHeader; + type AccountId = u64; + type Balance = u64; + type Index = u64; + type Signature = MultiSignature; + + fn max_extrinsic_size() -> u32 { + 0 + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +impl Parachain for BigParachain { + const PARACHAIN_ID: u32 = 4; +} construct_runtime! { pub enum TestRuntime where @@ -68,7 +166,7 @@ impl frame_system::Config for TestRuntime { type RuntimeCall = RuntimeCall; type BlockNumber = TestNumber; type Hash = H256; - type Hashing = BlakeTwo256; + type Hashing = RegularParachainHasher; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; @@ -122,9 +220,9 @@ impl pallet_bridge_parachains::Config for TestRuntime { type WeightInfo = (); type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type ParasPalletName = ParasPalletName; - type TrackedParachains = IsInVec; + type ParaStoredHeaderDataBuilder = (Parachain1, Parachain2, Parachain3, BigParachain); type HeadsToKeep = HeadsToKeep; - type MaxParaHeadSize = frame_support::traits::ConstU32; + type MaxParaHeadDataSize = frame_support::traits::ConstU32; } #[derive(Debug)] diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 4aea107777a4f..0b718ec52158e 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -70,8 +70,12 @@ pub const SESSION_LENGTH: BlockNumber = 4; /// Maximal number of GRANDPA authorities at Rialto. pub const MAX_AUTHORITIES_COUNT: u32 = 5; -/// Maximal SCALE-encoded size of parachains headers that are stored at Rialto `Paras` pallet. -pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 1024; +/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Rialto +/// parachains. +/// +/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some +/// reserve. +pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; /// Re-export `time_units` to make usage easier. pub use time_units::*; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 32e4e30ca4abd..57a47211e4ea3 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -35,12 +35,12 @@ pub const PARAS_PALLET_NAME: &str = "Paras"; /// Name of the With-Rococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; -/// Maximal SCALE-encoded size of parachains headers that are stored at Rococo `Paras` pallet. +/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Rococo +/// parachains. /// -/// Let's assume that the largest header is header that enacts new authorities set with -/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have -/// some fixed reserve for other things (digest, block hash and number, ...) as well. -pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; +/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some +/// reserve. +pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; /// Maximal number of GRANDPA authorities at Rococo. /// diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 7d74362b09a1a..75f6727d764fd 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -15,6 +15,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] @@ -22,5 +23,6 @@ default = ["std"] std = [ "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "sp-api/std", ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 6df4d5ff6d542..8a3794b418e02 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -19,11 +19,42 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_finality_runtime_apis; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; +use frame_support::weights::Weight; /// Westend Chain pub type Westend = PolkadotLike; +/// Westmint parachain definition +#[derive(Debug, Clone, Copy)] +pub struct Westmint; + +// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend +// primitives here. +impl Chain for Westmint { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Nonce; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + Westend::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + Westend::max_extrinsic_weight() + } +} + +impl Parachain for Westmint { + const PARACHAIN_ID: u32 = WESTMINT_PARACHAIN_ID; +} + /// Name of the parachains pallet at the Westend runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; @@ -39,10 +70,9 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; /// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet. /// -/// Let's assume that the largest header is header that enacts new authorities set with -/// `MAX_AUTHORITES_COUNT`. Every authority means 32-byte key and 8-byte weight. Let's also have -/// some fixed reserve for other things (digest, block hash and number, ...) as well. -pub const MAX_NESTED_PARACHAIN_HEAD_SIZE: u32 = 4096 + MAX_AUTHORITIES_COUNT * 40; +/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some +/// reserve. +pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; /// Identifier of Westmint parachain at the Westend relay chain. pub const WESTMINT_PARACHAIN_ID: u32 = 2000; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index c4dc6da13f0f7..1cf666c7f9612 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -20,7 +20,7 @@ pub use bp_polkadot_core::*; pub use bp_rococo::{ - SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_SIZE, PARAS_PALLET_NAME, + SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE, PARAS_PALLET_NAME, }; use bp_runtime::decl_bridge_finality_runtime_apis; diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 0aa2adfead184..333f7ad647a67 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -8,10 +8,12 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +impl-trait-for-tuples = "0.2" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -19,14 +21,19 @@ bp-runtime = { path = "../runtime", 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", "codec/std", "frame-support/std", "scale-info/std", "sp-core/std", + "sp-runtime/std", + "sp-std/std", ] diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index f2edebf8a22a7..cafe40da05636 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -18,15 +18,22 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub use bp_header_chain::StoredHeaderData; + use bp_polkadot_core::{ parachains::{ParaHash, ParaHead, ParaId}, BlockNumber as RelayBlockNumber, }; -use bp_runtime::{StorageDoubleMapKeyProvider, StorageMapKeyProvider}; +use bp_runtime::{ + BlockNumberOf, Chain, HashOf, HeaderOf, Parachain, StorageDoubleMapKeyProvider, + StorageMapKeyProvider, +}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; use scale_info::TypeInfo; use sp_core::storage::StorageKey; +use sp_runtime::traits::Header as HeaderT; +use sp_std::{marker::PhantomData, prelude::*}; /// Best known parachain head hash. #[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] @@ -86,5 +93,60 @@ impl StorageDoubleMapKeyProvider for ImportedParaHeadsKeyProvider { type Key1 = ParaId; type Hasher2 = Blake2_128Concat; type Key2 = ParaHash; - type Value = ParaHead; + type Value = ParaStoredHeaderData; +} + +/// Stored data of the parachain head. It is encoded version of the +/// `bp_runtime::StoredHeaderData` structure. +/// +/// We do not know exact structure of the parachain head, so we always store encoded version +/// of the `bp_runtime::StoredHeaderData`. It is only decoded when we talk about specific parachain. +#[derive(Clone, Decode, Encode, PartialEq, RuntimeDebug, TypeInfo)] +pub struct ParaStoredHeaderData(pub Vec); + +impl ParaStoredHeaderData { + /// Decode stored parachain head data. + pub fn decode_parachain_head_data( + &self, + ) -> Result, HashOf>, codec::Error> { + StoredHeaderData::, HashOf>::decode(&mut &self.0[..]) + } +} + +/// Stored parachain head data builder. +pub trait ParaStoredHeaderDataBuilder { + /// Try to build head data from self. + fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option; +} + +/// Helper for using single parachain as `ParaStoredHeaderDataBuilder`. +pub struct SingleParaStoredHeaderDataBuilder(PhantomData); + +impl ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBuilder { + fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option { + if para_id == ParaId(C::PARACHAIN_ID) { + let header = HeaderOf::::decode(&mut ¶_head.0[..]).ok()?; + return Some(ParaStoredHeaderData( + StoredHeaderData { number: *header.number(), state_root: *header.state_root() } + .encode(), + )) + } + None + } +} + +// Tries to build header data from each tuple member, short-circuiting on first successful one. +#[impl_trait_for_tuples::impl_for_tuples(1, 30)] +#[tuple_types_custom_trait_bound(Parachain)] +impl ParaStoredHeaderDataBuilder for C { + fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option { + for_tuples!( #( + let maybe_para_head = SingleParaStoredHeaderDataBuilder::::try_build(para_id, para_head); + if let Some(maybe_para_head) = maybe_para_head { + return Some(maybe_para_head); + } + )* ); + + None + } } diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 51fcd59cae13f..e8f68dd2a9a16 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -66,9 +66,7 @@ impl From for ParaId { /// /// This is an equivalent of the `polkadot_parachain::HeadData`. /// -/// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header. Keep in mind -/// that in Polkadot it is twice-encoded (so `header.encode().encode()`). We'll also do it to keep -/// it binary-compatible (implies hash-compatibility) with other parachain pallets. +/// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header. #[derive( PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, TypeInfo, Default, )] diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index cb5cbad434c51..78e63be405b6f 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -111,10 +111,7 @@ pub trait Chain: Send + Sync + 'static { + AsPrimitive + Default + Saturating - + MaxEncodedLen - // original `sp_runtime::traits::Header::BlockNumber` doesn't have this trait, but - // `sp_runtime::generic::Era` requires block number -> `u64` conversion. - + Into; + + MaxEncodedLen; /// 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` diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 34f521a72739b..5db54b87f7f76 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -27,7 +27,7 @@ use frame_system::RawOrigin; use scale_info::TypeInfo; use sp_core::{hash::H256, storage::StorageKey}; use sp_io::hashing::blake2_256; -use sp_runtime::traits::{BadOrigin, Header as HeaderT}; +use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto}; use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; pub use chain::{ @@ -124,6 +124,9 @@ impl HeaderId { } } +/// Header id used by the chain. +pub type HeaderIdOf = HeaderId, BlockNumberOf>; + /// Generic header id provider. pub trait HeaderIdProvider { // Get the header id. @@ -225,7 +228,9 @@ pub enum TransactionEra { Mortal(HeaderId, u32), } -impl, BlockHash: Copy> TransactionEra { +impl, BlockHash: Copy> + TransactionEra +{ /// Prepare transaction era, based on mortality period and current best block number. pub fn new( best_block_id: HeaderId, @@ -253,8 +258,10 @@ impl, BlockHash: Copy> TransactionEra sp_runtime::generic::Era { match *self { TransactionEra::Immortal => sp_runtime::generic::Era::immortal(), + // `unique_saturated_into` is fine here - mortality `u64::MAX` is not something we + // expect to see on any chain TransactionEra::Mortal(header_id, period) => - sp_runtime::generic::Era::mortal(period as _, header_id.0.into()), + sp_runtime::generic::Era::mortal(period as _, header_id.0.unique_saturated_into()), } } diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 99ff0fbe39447..a5e73d78b4b81 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -44,13 +44,10 @@ pub use crate::{ transaction_tracker::TransactionTracker, }; pub use bp_runtime::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, - IndexOf, SignatureOf, TransactionEra, TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderIdOf, + HeaderOf, IndexOf, SignatureOf, TransactionEra, TransactionEraOf, }; -/// Header id used by the chain. -pub type HeaderIdOf = relay_utils::HeaderId, BlockNumberOf>; - /// Substrate-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { diff --git a/relays/finality/src/sync_loop_metrics.rs b/relays/finality/src/sync_loop_metrics.rs index ae73bbedc4f75..4da1df811f6ec 100644 --- a/relays/finality/src/sync_loop_metrics.rs +++ b/relays/finality/src/sync_loop_metrics.rs @@ -16,7 +16,10 @@ //! Metrics for headers synchronization relay loop. -use relay_utils::metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry}; +use relay_utils::{ + metrics::{metric_name, register, IntGauge, Metric, PrometheusError, Registry}, + UniqueSaturatedInto, +}; /// Headers sync metrics. #[derive(Clone)] @@ -61,13 +64,19 @@ impl SyncLoopMetrics { } /// Update best block number at source. - pub fn update_best_block_at_source>(&self, source_best_number: Number) { - self.best_source_block_number.set(source_best_number.into()); + pub fn update_best_block_at_source>( + &self, + source_best_number: Number, + ) { + self.best_source_block_number.set(source_best_number.unique_saturated_into()); } /// Update best block number at target. - pub fn update_best_block_at_target>(&self, target_best_number: Number) { - self.best_target_block_number.set(target_best_number.into()); + pub fn update_best_block_at_target>( + &self, + target_best_number: Number, + ) { + self.best_target_block_number.set(target_best_number.unique_saturated_into()); } /// Update using-same-fork flag. diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 68fd72765aa35..027a6b7522231 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -33,12 +33,10 @@ use parachains_relay::{ }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, HeaderOf, RelayChain, SignParam, TransactionEra, TransactionTracker, - UnsignedTransaction, + HeaderIdOf, RelayChain, SignParam, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; -use sp_runtime::traits::Header as HeaderT; /// Substrate client as parachain heads source. pub struct ParachainsTarget { @@ -132,7 +130,7 @@ where .map(|para_info| para_info.best_head_hash); if let (Some(metrics), Some(best_para_head_hash)) = (metrics, &best_para_head_hash) { - let imported_para_head = self + let imported_para_head_number = self .client .storage_double_map_value::( P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, @@ -142,10 +140,11 @@ where ) .await .and_then(|maybe_encoded_head| match maybe_encoded_head { - Some(encoded_head) => - HeaderOf::::decode(&mut &encoded_head.0[..]) - .map(Some) - .map_err(Self::Error::ResponseParseFailed), + Some(encoded_head) => encoded_head + .decode_parachain_head_data::() + .map(|head| head.number) + .map(Some) + .map_err(Self::Error::ResponseParseFailed), None => Ok(None), }) .map_err(|e| { @@ -159,9 +158,8 @@ where e }) .unwrap_or(None); - if let Some(imported_para_head) = imported_para_head { - metrics - .update_best_parachain_block_at_target(para_id, *imported_para_head.number()); + if let Some(imported_para_head_number) = imported_para_head_number { + metrics.update_best_parachain_block_at_target(para_id, imported_para_head_number); } } diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 4decb7e092e71..ace4264cacc65 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -65,10 +65,9 @@ impl MessageLaneLoopMetrics { /// Update source client state metrics. pub fn update_source_state(&self, source_client_state: SourceClientState

) { self.source_to_target_finality_metrics - .update_best_block_at_source(source_client_state.best_self.0.into()); - self.target_to_source_finality_metrics.update_best_block_at_target( - source_client_state.best_finalized_peer_at_best_self.0.into(), - ); + .update_best_block_at_source(source_client_state.best_self.0); + self.target_to_source_finality_metrics + .update_best_block_at_target(source_client_state.best_finalized_peer_at_best_self.0); self.target_to_source_finality_metrics.update_using_same_fork( source_client_state.best_finalized_peer_at_best_self.1 == source_client_state.actual_best_finalized_peer_at_best_self.1, @@ -78,10 +77,9 @@ impl MessageLaneLoopMetrics { /// Update target client state metrics. pub fn update_target_state(&self, target_client_state: TargetClientState

) { self.target_to_source_finality_metrics - .update_best_block_at_source(target_client_state.best_self.0.into()); - self.source_to_target_finality_metrics.update_best_block_at_target( - target_client_state.best_finalized_peer_at_best_self.0.into(), - ); + .update_best_block_at_source(target_client_state.best_self.0); + self.source_to_target_finality_metrics + .update_best_block_at_target(target_client_state.best_finalized_peer_at_best_self.0); self.source_to_target_finality_metrics.update_using_same_fork( target_client_state.best_finalized_peer_at_best_self.1 == target_client_state.actual_best_finalized_peer_at_best_self.1, diff --git a/relays/parachains/src/parachains_loop_metrics.rs b/relays/parachains/src/parachains_loop_metrics.rs index ff8bace274439..5df996b4ddd1f 100644 --- a/relays/parachains/src/parachains_loop_metrics.rs +++ b/relays/parachains/src/parachains_loop_metrics.rs @@ -15,8 +15,9 @@ // along with Parity Bridges Common. If not, see . use bp_polkadot_core::parachains::ParaId; -use relay_utils::metrics::{ - metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64, +use relay_utils::{ + metrics::{metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64}, + UniqueSaturatedInto, }; /// Parachains sync metrics. @@ -50,12 +51,12 @@ impl ParachainsLoopMetrics { } /// Update best block number at source. - pub fn update_best_parachain_block_at_source>( + pub fn update_best_parachain_block_at_source>( &self, parachain: ParaId, block_number: Number, ) { - let block_number = block_number.into(); + let block_number = block_number.unique_saturated_into(); let label = parachain_label(¶chain); log::trace!( target: "bridge-metrics", @@ -67,12 +68,12 @@ impl ParachainsLoopMetrics { } /// Update best block number at target. - pub fn update_best_parachain_block_at_target>( + pub fn update_best_parachain_block_at_target>( &self, parachain: ParaId, block_number: Number, ) { - let block_number = block_number.into(); + let block_number = block_number.unique_saturated_into(); let label = parachain_label(¶chain); log::trace!( target: "bridge-metrics", diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ebbfa74c6ff81..09cec37090069 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -29,4 +29,5 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate dependencies +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 42bf86ebf5b37..16e1a18bab7d4 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -19,6 +19,7 @@ pub use bp_runtime::HeaderId; pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; +pub use sp_runtime::traits::UniqueSaturatedInto; use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; @@ -51,7 +52,7 @@ pub mod relay_loop; pub trait BlockNumberBase: 'static + From - + Into + + UniqueSaturatedInto + Ord + Clone + Copy @@ -73,7 +74,7 @@ pub trait BlockNumberBase: impl BlockNumberBase for T where T: 'static + From - + Into + + UniqueSaturatedInto + Ord + Clone + Copy From 67356d33a7aef32f304d7e367d53fca6b5a91f26 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 12 Dec 2022 16:14:31 +0200 Subject: [PATCH 0836/1210] Fix bridge hub rococo/wococo weights (#1712) * Fix bridge hub rococo/wococo weights * Remove SS58Prefix --- .../src/refund_relayer_extension.rs | 2 +- .../chain-bridge-hub-cumulus/Cargo.toml | 41 +++++++ .../chain-bridge-hub-cumulus/src/lib.rs | 106 ++++++++++++++++++ primitives/chain-bridge-hub-rococo/Cargo.toml | 4 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 31 +---- primitives/chain-bridge-hub-wococo/Cargo.toml | 4 +- primitives/chain-bridge-hub-wococo/src/lib.rs | 8 +- relays/bin-substrate/src/chains/millau.rs | 4 - relays/bin-substrate/src/chains/rialto.rs | 4 - .../src/chains/rialto_parachain.rs | 4 - relays/bin-substrate/src/chains/rococo.rs | 8 -- relays/bin-substrate/src/chains/westend.rs | 14 --- relays/bin-substrate/src/chains/wococo.rs | 8 -- relays/bin-substrate/src/cli/mod.rs | 3 - .../src/runtime_wrapper.rs | 1 - .../src/runtime_wrapper.rs | 2 - 16 files changed, 154 insertions(+), 90 deletions(-) create mode 100644 primitives/chain-bridge-hub-cumulus/Cargo.toml create mode 100644 primitives/chain-bridge-hub-cumulus/src/lib.rs diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 6b6e2078e0022..76e15ab3cbc9f 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -608,7 +608,7 @@ mod tests { } fn run_test(test: impl FnOnce()) { - sp_io::TestExternalities::new(Default::default()).execute_with(|| test()) + sp_io::TestExternalities::new(Default::default()).execute_with(test) } fn run_pre_dispatch( diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml new file mode 100644 index 0000000000000..d413ce2ca4ca3 --- /dev/null +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "bp-bridge-hub-cumulus" +description = "Primitives of BridgeHubRococo parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +smallvec = "1.10.0" + +# Bridge Dependencies + +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } + +# Substrate Based Dependencies + +frame-system = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +# Polkadot Dependencies +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } +polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } + +[features] +default = ["std"] +std = [ + "bp-polkadot-core/std", + "bp-messages/std", + "bp-runtime/std", + "frame-system/std", + "frame-support/std", + "sp-api/std", + "sp-std/std", + "polkadot-primitives/std", + "polkadot-runtime-constants/std", +] diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs new file mode 100644 index 0000000000000..264e85a517ec1 --- /dev/null +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -0,0 +1,106 @@ +// Copyright 2022 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 . + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_messages::*; +pub use bp_polkadot_core::{ + AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, + Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, SignedExtensions, + UncheckedExtrinsic, MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, TX_EXTRA_BYTES, +}; +use frame_support::{ + dispatch::DispatchClass, + parameter_types, + sp_runtime::{MultiAddress, MultiSigner}, + weights::{constants, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}, +}; +use frame_system::limits; + +/// All cumulus bridge hubs allow normal extrinsics to fill block up to 75 percent. +/// +/// This is a copy-paste from the cumulus repo's `parachains-common` crate. +pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +/// All cumulus bridge hubs chains allow for 0.5 seconds of compute with a 6-second average block +/// time. +/// +/// This is a copy-paste from the cumulus repo's `parachains-common` crate. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = constants::WEIGHT_PER_SECOND + .saturating_div(2) + .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); + +/// All cumulus bridge hubs assume that about 5 percent of the block weight is consumed by +/// `on_initialize` handlers. This is used to limit the maximal weight of a single extrinsic. +/// +/// This is a copy-paste from the cumulus repo's `parachains-common` crate. +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); + +parameter_types! { + pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio( + 5 * 1024 * 1024, + NORMAL_DISPATCH_RATIO, + ); + + pub const BlockExecutionWeight: Weight = constants::WEIGHT_PER_NANOS.saturating_mul(5_000_000); + + pub const ExtrinsicBaseWeight: Weight = constants::WEIGHT_PER_NANOS.saturating_mul(125_000); + + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have an extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT, + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); +} + +/// [`WeightToFee`] should reflect cumulus/bridge-hub-* [`WeightToFee`] +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + pub const CENTS: Balance = polkadot_runtime_constants::currency::CENTS; + + // In BridgeHub, we map the extrinsic base weight to 1/100 CENT. + let p = CENTS; + let q = 100 * Balance::from(constants::ExtrinsicBaseWeight::get().ref_time()); + smallvec::smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// The address format for describing accounts. +pub type Address = MultiAddress; diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index 51bc88baf0e62..806587bb9a101 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ smallvec = "1.10.0" # Bridge Dependencies -bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } @@ -27,7 +27,7 @@ polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", d [features] default = ["std"] std = [ - "bp-polkadot-core/std", + "bp-bridge-hub-cumulus/std", "bp-messages/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index aa65f378542a6..633a021b63427 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -19,19 +19,14 @@ #![cfg_attr(not(feature = "std"), no_std)] +pub use bp_bridge_hub_cumulus::*; use bp_messages::*; -pub use bp_polkadot_core::*; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; use frame_support::{ dispatch::DispatchClass, - parameter_types, sp_runtime::{MultiAddress, MultiSigner}, - weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, - }, RuntimeDebug, }; use sp_std::prelude::*; @@ -67,26 +62,6 @@ impl Parachain for BridgeHubRococo { const PARACHAIN_ID: u32 = BRIDGE_HUB_ROCOCO_PARACHAIN_ID; } -/// [`WeightToFee`] should reflect cumulus/bridge-hub-rococo-runtime [`WeightToFee`] -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - pub const CENTS: Balance = polkadot_runtime_constants::currency::CENTS; - - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in BridgeHub, we map to 1/10 of that, or 1/100 CENT - let p = CENTS; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - /// Public key of the chain account that may be used to verify signatures. pub type AccountSigner = MultiSigner; @@ -99,9 +74,5 @@ pub const BRIDGE_HUB_ROCOCO_PARACHAIN_ID: u32 = 1013; /// Name of the With-BridgeHubRococo messages pallet instance that is deployed at bridged chains. pub const WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; -parameter_types! { - pub const SS58Prefix: u16 = 42; -} - decl_bridge_finality_runtime_apis!(bridge_hub_rococo); decl_bridge_messages_runtime_apis!(bridge_hub_rococo); diff --git a/primitives/chain-bridge-hub-wococo/Cargo.toml b/primitives/chain-bridge-hub-wococo/Cargo.toml index 94ac501fbd531..24ecdb7adbca1 100644 --- a/primitives/chain-bridge-hub-wococo/Cargo.toml +++ b/primitives/chain-bridge-hub-wococo/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies -bp-bridge-hub-rococo = { path = "../chain-bridge-hub-rococo", default-features = false } +bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } @@ -23,10 +23,10 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ + "bp-bridge-hub-cumulus/std", "bp-runtime/std", "bp-messages/std", "frame-support/std", "sp-api/std", "sp-std/std", - "bp-bridge-hub-rococo/std", ] diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index a2c3f2ad37a32..e9a170223b995 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -23,13 +23,7 @@ #![cfg_attr(not(feature = "std"), no_std)] // Re-export only what is really needed -pub use bp_bridge_hub_rococo::{ - AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, AccountSigner, Address, Balance, - BlockLength, BlockNumber, BlockWeights, Hash, Hasher, Hashing, Header, Index, Nonce, - SS58Prefix, Signature, SignedBlock, SignedExtensions, UncheckedExtrinsic, WeightToFee, - MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - TX_EXTRA_BYTES, -}; +pub use bp_bridge_hub_cumulus::*; use bp_messages::*; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 705755506f78c..aa56d113e14ed 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -56,8 +56,4 @@ impl CliChain for Millau { const RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - millau_runtime::SS58Prefix::get() as u16 - } } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 83bccf626b9ed..a8e8143632e16 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -48,8 +48,4 @@ impl CliChain for Rialto { const RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - rialto_runtime::SS58Prefix::get() as u16 - } } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index a480dc3eebbc6..66d03f212ce76 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -50,8 +50,4 @@ impl CliChain for RialtoParachain { const RUNTIME_VERSION: Option = Some(rialto_parachain_runtime::VERSION); type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - rialto_parachain_runtime::SS58Prefix::get() as u16 - } } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 6a99eab6cb385..68a6b3e7b1db7 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -25,18 +25,10 @@ impl CliChain for Rococo { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - bp_rococo::SS58Prefix::get() as u16 - } } impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - relay_bridge_hub_rococo_client::runtime::SS58Prefix::get() - } } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 1627bc015d323..075f22b698fdf 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -24,24 +24,10 @@ impl CliChain for Westend { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - sp_core::crypto::Ss58AddressFormat::from( - sp_core::crypto::Ss58AddressFormatRegistry::SubstrateAccount, - ) - .into() - } } impl CliChain for Westmint { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - sp_core::crypto::Ss58AddressFormat::from( - sp_core::crypto::Ss58AddressFormatRegistry::SubstrateAccount, - ) - .into() - } } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index c44f3ac811f3f..2edd3dcf606e9 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -25,18 +25,10 @@ impl CliChain for Wococo { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - bp_wococo::SS58Prefix::get() as u16 - } } impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = None; type KeyPair = sp_core::sr25519::Pair; - - fn ss58_format() -> u16 { - relay_bridge_hub_wococo_client::runtime::SS58Prefix::get() - } } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 2086008bc9566..5733aa411d8e7 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -167,9 +167,6 @@ pub trait CliChain: relay_substrate_client::Chain { /// /// In case of chains supporting multiple cryptos, pick one used by the CLI. type KeyPair: sp_core::crypto::Pair; - - /// Numeric value of SS58 format. - fn ss58_format() -> u16; } /// Lane id. diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index 6f83257cf4dc0..0571f82f5a6cb 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -22,7 +22,6 @@ use bp_polkadot_core::PolkadotLike; use codec::{Decode, Encode}; use scale_info::TypeInfo; -pub use bp_bridge_hub_rococo::SS58Prefix; use bp_messages::UnrewardedRelayersState; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::Chain; diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 8d94e7f9026a9..05176af471a9b 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -16,8 +16,6 @@ //! Types that are specific to the BridgeHubWococo runtime. -pub use bp_bridge_hub_wococo::SS58Prefix; - // We reuse everything from rococo runtime wrapper pub type Call = relay_bridge_hub_rococo_client::runtime::Call; pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; From 864444712625f9a1fed9512ec8569bb79c9f3d4e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 12 Dec 2022 17:26:13 +0200 Subject: [PATCH 0837/1210] Remove WeightToFee (#1713) * Remove WeightToFee * Remove leftover --- .../chain-bridge-hub-cumulus/src/lib.rs | 21 +------------------ .../parachain_to_parachain.rs | 2 -- relays/client-bridge-hub-rococo/src/lib.rs | 1 - relays/client-bridge-hub-wococo/src/lib.rs | 1 - relays/client-millau/src/lib.rs | 1 - relays/client-rialto-parachain/src/lib.rs | 1 - relays/client-rialto/src/lib.rs | 1 - relays/client-substrate/src/chain.rs | 5 ----- relays/client-substrate/src/lib.rs | 2 +- 9 files changed, 2 insertions(+), 33 deletions(-) diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 264e85a517ec1..ecf263d4a09c6 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -27,7 +27,7 @@ use frame_support::{ dispatch::DispatchClass, parameter_types, sp_runtime::{MultiAddress, MultiSigner}, - weights::{constants, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}, + weights::constants, }; use frame_system::limits; @@ -80,25 +80,6 @@ parameter_types! { .build_or_panic(); } -/// [`WeightToFee`] should reflect cumulus/bridge-hub-* [`WeightToFee`] -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - pub const CENTS: Balance = polkadot_runtime_constants::currency::CENTS; - - // In BridgeHub, we map the extrinsic base weight to 1/100 CENT. - let p = CENTS; - let q = 100 * Balance::from(constants::ExtrinsicBaseWeight::get().ref_time()); - smallvec::smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - /// Public key of the chain account that may be used to verify signatures. pub type AccountSigner = MultiSigner; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index e7328a837eb99..4ac3a08aeff37 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -#![allow(unused_macros)] // TODO (https://github.com/paritytech/parity-bridges-common/issues/1629): remove me - use async_trait::async_trait; use std::sync::Arc; diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 1de0e26d43661..3863d1c29322e 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -136,7 +136,6 @@ impl ChainWithMessages for BridgeHubRococo { const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightToFee = bp_bridge_hub_rococo::WeightToFee; // TODO: fix (https://github.com/paritytech/parity-bridges-common/issues/1640) type WeightInfo = (); } diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 46bac2e826e3f..ceb1095b34212 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -136,7 +136,6 @@ impl ChainWithMessages for BridgeHubWococo { const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_bridge_hub_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightToFee = bp_bridge_hub_wococo::WeightToFee; // TODO: fix (https://github.com/paritytech/parity-bridges-common/issues/1640) type WeightInfo = (); } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 023d93fb72d92..1fe480fdf2d6f 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -69,7 +69,6 @@ impl ChainWithMessages for Millau { bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightToFee = bp_millau::WeightToFee; type WeightInfo = (); } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 8cf74bdf9b1f5..cfb8d808dfd24 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -89,7 +89,6 @@ impl ChainWithMessages for RialtoParachain { bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightToFee = bp_rialto_parachain::WeightToFee; type WeightInfo = (); } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 23ecbbd47f6d3..6ea500ea00aac 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -88,7 +88,6 @@ impl ChainWithMessages for Rialto { bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightToFee = bp_rialto::WeightToFee; type WeightInfo = (); } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 0e19cf92b778f..27a95a3106de4 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -19,7 +19,6 @@ use bp_runtime::{ Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEra, TransactionEraOf, }; use codec::{Codec, Encode}; -use frame_support::weights::WeightToFee; use jsonrpsee::core::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; @@ -111,16 +110,12 @@ pub trait ChainWithMessages: Chain { /// `ChainWithMessages`. const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; - /// Type that is used by the chain, to convert from weight to fee. - type WeightToFee: WeightToFee; /// Weights of message pallet calls. type WeightInfo: pallet_bridge_messages::WeightInfoExt; } /// Call type used by the chain. pub type CallOf = ::Call; -/// Weight-to-Fee type used by the chain. -pub type WeightToFeeOf = ::WeightToFee; /// Transaction status of the chain. pub type TransactionStatusOf = TransactionStatus, HashOf>; diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index a5e73d78b4b81..7170d58e2c0a7 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -35,7 +35,7 @@ pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, RelayChain, SignParam, - TransactionStatusOf, UnsignedTransaction, WeightToFeeOf, + TransactionStatusOf, UnsignedTransaction, }, client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, From 189e42ab44c4d0fcfe9179764788771b7cc3d78e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 14 Dec 2022 10:56:14 +0300 Subject: [PATCH 0838/1210] fix parachains benchmarks (#1717) --- bin/millau/runtime/src/lib.rs | 5 +++++ modules/parachains/src/benchmarking.rs | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 19a8770430a7f..4513e50121bcd 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1066,6 +1066,11 @@ impl_runtime_apis! { } impl ParachainsConfig for Runtime { + fn parachains() -> Vec { + use bp_runtime::Parachain; + vec![bp_polkadot_core::parachains::ParaId(bp_rialto_parachain::RialtoParachain::PARACHAIN_ID)] + } + fn prepare_parachain_heads_proof( parachains: &[bp_polkadot_core::parachains::ParaId], parachain_head_size: u32, diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index aba296dfc1d5b..29e48132890a1 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -32,6 +32,8 @@ pub struct Pallet, I: 'static>(crate::Pallet); /// Trait that must be implemented by runtime to benchmark the parachains finality pallet. pub trait Config: crate::Config { + /// Returns vector of supported parachains. + fn parachains() -> Vec; /// Generate parachain heads proof and prepare environment for verifying this proof. fn prepare_parachain_heads_proof( parachains: &[ParaId], @@ -53,10 +55,11 @@ benchmarks_instance_pallet! { // Benchmark `submit_parachain_heads` extrinsic with different number of parachains. submit_parachain_heads_with_n_parachains { - let p in 1..1024; + let p in 1..(T::parachains().len() + 1) as u32; let sender = account("sender", 0, 0); - let parachains = (1..=p).map(ParaId).collect::>(); + let mut parachains = T::parachains(); + let _ = parachains.split_off(p as usize - 1); let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, @@ -73,7 +76,7 @@ benchmarks_instance_pallet! { // Benchmark `submit_parachain_heads` extrinsic with 1kb proof size. submit_parachain_heads_with_1kb_proof { let sender = account("sender", 0, 0); - let parachains = vec![ParaId(1)]; + let parachains = vec![T::parachains()[0]]; let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, @@ -90,7 +93,7 @@ benchmarks_instance_pallet! { // Benchmark `submit_parachain_heads` extrinsic with 16kb proof size. submit_parachain_heads_with_16kb_proof { let sender = account("sender", 0, 0); - let parachains = vec![ParaId(1)]; + let parachains = vec![T::parachains()[0]]; let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, From 72131ecc823ae84f20b31dc244e66e21f8569989 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 14 Dec 2022 12:29:09 +0200 Subject: [PATCH 0839/1210] Remove SOURCE_PARACHAIN_PARA_ID (#1716) * Remove SOURCE_PARACHAIN_PARA_ID Remove SubstrateParachainsPipeline::SOURCE_PARACHAIN_PARA_ID * Avoid duplicate ChainBase and ParachainBase implementations * Replace ChainShadow with UnderlyingChainProvider --- bin/runtime-common/src/messages.rs | 9 +--- primitives/runtime/src/chain.rs | 39 +++++++++++++++ primitives/runtime/src/lib.rs | 3 +- .../src/chains/rialto_parachains_to_millau.rs | 2 - .../rococo_parachains_to_bridge_hub_wococo.rs | 2 - .../chains/westend_parachains_to_millau.rs | 2 - .../wococo_parachains_to_bridge_hub_rococo.rs | 2 - relays/bin-substrate/src/cli/bridge.rs | 9 +++- .../src/cli/relay_headers_and_messages/mod.rs | 1 + .../parachain_to_parachain.rs | 21 ++++++--- .../relay_to_parachain.rs | 13 +++-- .../bin-substrate/src/cli/relay_parachains.rs | 10 +++- relays/client-bridge-hub-rococo/src/lib.rs | 26 ++-------- relays/client-bridge-hub-wococo/src/lib.rs | 26 ++-------- relays/client-kusama/src/lib.rs | 23 ++------- relays/client-millau/src/lib.rs | 26 ++-------- relays/client-polkadot/src/lib.rs | 23 ++------- relays/client-rialto-parachain/src/lib.rs | 25 ++-------- relays/client-rialto/src/lib.rs | 25 ++-------- relays/client-rococo/src/lib.rs | 25 ++-------- relays/client-substrate/src/chain.rs | 8 +++- relays/client-substrate/src/lib.rs | 7 +-- relays/client-westend/src/lib.rs | 47 +++---------------- relays/client-wococo/src/lib.rs | 25 ++-------- .../src/on_demand/parachains.rs | 10 ++-- .../lib-substrate-relay/src/parachains/mod.rs | 9 ++-- .../src/parachains/source.rs | 8 ++-- 27 files changed, 154 insertions(+), 272 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index a0a75692ba0a0..ca48a6015f11d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -27,6 +27,7 @@ use bp_messages::{ InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Size, StorageProofChecker}; +pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider}; use codec::{Decode, DecodeLimit, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; @@ -54,12 +55,6 @@ pub trait MessageBridge { type BridgedHeaderChain: HeaderChain>; } -/// A trait that provides the type of the underlying chain. -pub trait UnderlyingChainProvider { - /// Underlying chain type. - type Chain: Chain; -} - /// This chain that has `pallet-bridge-messages` module. pub trait ThisChainWithMessages: UnderlyingChainProvider { /// Call origin on the chain. @@ -87,8 +82,6 @@ pub trait BridgedChainWithMessages: UnderlyingChainProvider { pub type ThisChain = ::ThisChain; /// Bridged chain in context of message bridge. pub type BridgedChain = ::BridgedChain; -/// Underlying chain type. -pub type UnderlyingChainOf = ::Chain; /// Hash used on the chain. pub type HashOf = bp_runtime::HashOf<::Chain>; /// Hasher used on the chain. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 78e63be405b6f..f5771e9fdd57e 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -192,12 +192,51 @@ pub trait Chain: Send + Sync + 'static { fn max_extrinsic_weight() -> Weight; } +/// A trait that provides the type of the underlying chain. +pub trait UnderlyingChainProvider { + /// Underlying chain type. + type Chain: Chain; +} + +impl Chain for T +where + T: Send + Sync + 'static + UnderlyingChainProvider, +{ + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hasher; + type Header = ::Header; + type AccountId = ::AccountId; + type Balance = ::Balance; + type Index = ::Index; + type Signature = ::Signature; + + fn max_extrinsic_size() -> u32 { + ::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + ::max_extrinsic_weight() + } +} + /// Minimal parachain representation that may be used from no_std environment. pub trait Parachain: Chain { /// Parachain identifier. const PARACHAIN_ID: u32; } +impl Parachain for T +where + T: Chain + UnderlyingChainProvider, + ::Chain: Parachain, +{ + const PARACHAIN_ID: u32 = <::Chain as Parachain>::PARACHAIN_ID; +} + +/// Underlying chain type. +pub type UnderlyingChainOf = ::Chain; + /// Block number used by the chain. pub type BlockNumberOf = ::BlockNumber; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 5db54b87f7f76..340088a85b122 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -32,7 +32,8 @@ use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, - HasherOf, HeaderOf, IndexOf, Parachain, SignatureOf, TransactionEraOf, + HasherOf, HeaderOf, IndexOf, Parachain, SignatureOf, TransactionEraOf, UnderlyingChainOf, + UnderlyingChainProvider, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedSub, One}; diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index d1cf853ac775b..b3471ad1a382f 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -40,8 +40,6 @@ impl SubstrateParachainsPipeline for RialtoParachainsToMillau { type TargetChain = Millau; type SubmitParachainHeadsCallBuilder = RialtoParachainsToMillauSubmitParachainHeadsCallBuilder; - - const SOURCE_PARACHAIN_PARA_ID: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID; } /// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs index 23e87194c9165..b028253d8a4f6 100644 --- a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs @@ -39,8 +39,6 @@ impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWococo { type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; type SubmitParachainHeadsCallBuilder = BridgeHubRococoToBridgeHubWococoCallBuilder; - - const SOURCE_PARACHAIN_PARA_ID: u32 = bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID; } pub struct BridgeHubRococoToBridgeHubWococoCallBuilder; diff --git a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs index 73409e65569db..f025f48dcb60a 100644 --- a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs @@ -39,8 +39,6 @@ impl SubstrateParachainsPipeline for WestendParachainsToMillau { type TargetChain = Millau; type SubmitParachainHeadsCallBuilder = WestendParachainsToMillauSubmitParachainHeadsCallBuilder; - - const SOURCE_PARACHAIN_PARA_ID: u32 = bp_westend::WESTMINT_PARACHAIN_ID; } /// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs index caaeab566558b..f821af1a0cfd9 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -39,8 +39,6 @@ impl SubstrateParachainsPipeline for BridgeHubWococoToBridgeHubRococo { type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; type SubmitParachainHeadsCallBuilder = BridgeHubWococoToBridgeHubRococoCallBuilder; - - const SOURCE_PARACHAIN_PARA_ID: u32 = bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID; } pub struct BridgeHubWococoToBridgeHubRococoCallBuilder; diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index c1923f89a8485..0f0c11f39098d 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -17,7 +17,9 @@ use crate::cli::CliChain; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use parachains_relay::ParachainsPipeline; -use relay_substrate_client::{AccountKeyPairOf, Chain, ChainWithTransactions, RelayChain}; +use relay_substrate_client::{ + AccountKeyPairOf, Chain, ChainWithTransactions, Parachain, RelayChain, +}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, @@ -76,7 +78,10 @@ pub trait RelayToRelayHeadersCliBridge: CliBridgeBase { /// Bridge representation that can be used from the CLI for relaying headers /// from a parachain to a relay chain. -pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase { +pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase +where + Self::Source: Parachain, +{ // The `CliBridgeBase` type represents the parachain in this situation. // We need to add an extra type for the relay chain. type SourceRelay: Chain diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index f84174563e146..11cae48d1d987 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -62,6 +62,7 @@ use bp_messages::LaneId; use bp_runtime::{BalanceOf, BlockNumberOf}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithTransactions, Client, + Parachain, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 4ac3a08aeff37..eedebe93c3332 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -25,7 +25,9 @@ use crate::cli::{ use bp_polkadot_core::parachains::ParaHash; use bp_runtime::BlockNumberOf; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client}; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, +}; use sp_core::Pair; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, @@ -42,7 +44,10 @@ use substrate_relay_helper::{ pub struct ParachainToParachainBridge< L2R: MessagesCliBridge + ParachainToRelayHeadersCliBridge, R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge, -> { +> where + ::Source: Parachain, + ::Source: Parachain, +{ /// Parameters that are shared by all bridge types. pub common: Full2WayBridgeCommonParams<::Target, ::Target>, @@ -118,9 +123,9 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { impl [<$left_parachain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain>, + Left: ChainWithTransactions + CliChain> + Parachain, LeftRelay: CliChain, - Right: ChainWithTransactions + CliChain>, + Right: ChainWithTransactions + CliChain> + Parachain, RightRelay: CliChain, L2R: CliBridgeBase + MessagesCliBridge @@ -172,10 +177,14 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { #[async_trait] impl< - Left: Chain + ChainWithTransactions + CliChain>, + Left: Chain + + ChainWithTransactions + + CliChain> + + Parachain, Right: Chain + ChainWithTransactions - + CliChain>, + + CliChain> + + Parachain, LeftRelay: Chain + CliChain, RightRelay: Chain diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 4070783df09bc..22324c1d6ffdf 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -28,7 +28,9 @@ use crate::cli::{ use bp_polkadot_core::parachains::ParaHash; use bp_runtime::BlockNumberOf; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client}; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, +}; use sp_core::Pair; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, @@ -45,7 +47,9 @@ use substrate_relay_helper::{ pub struct RelayToParachainBridge< L2R: MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: MessagesCliBridge + ParachainToRelayHeadersCliBridge, -> { +> where + ::Source: Parachain, +{ /// Parameters that are shared by all bridge types. pub common: Full2WayBridgeCommonParams<::Target, ::Target>, @@ -112,7 +116,7 @@ macro_rules! declare_relay_to_parachain_bridge_schema { impl [<$left_chain $right_parachain HeadersAndMessages>] { async fn into_bridge< Left: ChainWithTransactions + CliChain>, - Right: ChainWithTransactions + CliChain>, + Right: ChainWithTransactions + CliChain> + Parachain, RightRelay: CliChain, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase @@ -165,7 +169,8 @@ impl< Left: ChainWithTransactions + CliChain>, Right: Chain + ChainWithTransactions - + CliChain>, + + CliChain> + + Parachain, RightRelay: Chain + CliChain, L2R: CliBridgeBase diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 286cecc914bc3..1a0bba3fd1f2c 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -26,6 +26,7 @@ use bp_polkadot_core::parachains::ParaId; use parachains_relay::parachains_loop::{ AvailableHeader, ParachainSyncParams, SourceClient, TargetClient, }; +use relay_substrate_client::{Parachain, ParachainBase}; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use std::sync::Arc; use structopt::StructOpt; @@ -38,7 +39,11 @@ use substrate_relay_helper::{ TransactionParams, }; -use crate::cli::{bridge::ParachainToRelayHeadersCliBridge, chain_schema::*, PrometheusParams}; +use crate::cli::{ + bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}, + chain_schema::*, + PrometheusParams, +}; /// Start parachain heads relayer process. #[derive(StructOpt)] @@ -74,6 +79,7 @@ where SourceClient>, ParachainsTarget: TargetClient>, + ::Source: Parachain, { async fn relay_headers(data: RelayParachains) -> anyhow::Result<()> { let source_client = data.source.into_client::().await?; @@ -100,7 +106,7 @@ where target_client, ParachainSyncParams { parachains: vec![ - ParaId(::SOURCE_PARACHAIN_PARA_ID) + ParaId(::SourceParachain::PARACHAIN_ID) ], stall_timeout: std::time::Duration::from_secs(60), strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 3863d1c29322e..7e9047e32ce59 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -16,11 +16,11 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. -use bp_messages::{MessageNonce, Weight}; +use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, SignParam, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, + SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -34,24 +34,8 @@ pub use runtime_wrapper as runtime; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct BridgeHubRococo; -impl ChainBase for BridgeHubRococo { - type BlockNumber = bp_bridge_hub_rococo::BlockNumber; - type Hash = bp_bridge_hub_rococo::Hash; - type Hasher = bp_bridge_hub_rococo::Hashing; - type Header = bp_bridge_hub_rococo::Header; - - type AccountId = bp_bridge_hub_rococo::AccountId; - type Balance = bp_bridge_hub_rococo::Balance; - type Index = bp_bridge_hub_rococo::Nonce; - type Signature = bp_bridge_hub_rococo::Signature; - - fn max_extrinsic_size() -> u32 { - bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_weight() - } +impl UnderlyingChainProvider for BridgeHubRococo { + type Chain = bp_bridge_hub_rococo::BridgeHubRococo; } impl Chain for BridgeHubRococo { diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index ceb1095b34212..516f5d9fb808b 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,11 +16,11 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_messages::{MessageNonce, Weight}; +use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, SignParam, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, + SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -34,24 +34,8 @@ pub use runtime_wrapper as runtime; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct BridgeHubWococo; -impl ChainBase for BridgeHubWococo { - type BlockNumber = bp_bridge_hub_wococo::BlockNumber; - type Hash = bp_bridge_hub_wococo::Hash; - type Hasher = bp_bridge_hub_wococo::Hashing; - type Header = bp_bridge_hub_wococo::Header; - - type AccountId = bp_bridge_hub_wococo::AccountId; - type Balance = bp_bridge_hub_wococo::Balance; - type Index = bp_bridge_hub_wococo::Nonce; - type Signature = bp_bridge_hub_wococo::Signature; - - fn max_extrinsic_size() -> u32 { - bp_bridge_hub_wococo::BridgeHubWococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_bridge_hub_wococo::BridgeHubWococo::max_extrinsic_weight() - } +impl UnderlyingChainProvider for BridgeHubWococo { + type Chain = bp_bridge_hub_wococo::BridgeHubWococo; } impl Chain for BridgeHubWococo { diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 25d7bb76e59bf..cd6e23a460795 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -17,8 +17,7 @@ //! Types used to connect to the Kusama chain. use bp_kusama::AccountInfoStorageMapKeyProvider; -use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use relay_substrate_client::{Chain, ChainWithBalances, ChainWithGrandpa, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -29,24 +28,8 @@ pub type HeaderId = relay_utils::HeaderId u32 { - bp_kusama::Kusama::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_kusama::Kusama::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Kusama { + type Chain = bp_kusama::Kusama; } impl Chain for Kusama { diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 1fe480fdf2d6f..815cd68f39f26 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -18,10 +18,10 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, Error as SubstrateError, IndexOf, SignParam, UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + ChainWithTransactions, Error as SubstrateError, IndexOf, SignParam, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -34,24 +34,8 @@ pub type HeaderId = relay_utils::HeaderId u32 { - bp_millau::Millau::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_millau::Millau::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Millau { + type Chain = bp_millau::Millau; } impl ChainWithGrandpa for Millau { diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 8bba686cfe9e7..ac67d55ab5418 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -17,8 +17,7 @@ //! Types used to connect to the Polkadot chain. use bp_polkadot::AccountInfoStorageMapKeyProvider; -use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa}; +use relay_substrate_client::{Chain, ChainWithBalances, ChainWithGrandpa, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -29,24 +28,8 @@ pub type HeaderId = relay_utils::HeaderId u32 { - bp_polkadot::Polkadot::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_polkadot::Polkadot::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Polkadot { + type Chain = bp_polkadot::Polkadot; } impl Chain for Polkadot { diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index cfb8d808dfd24..16abd6e880881 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -18,10 +18,9 @@ use bp_messages::MessageNonce; use codec::Encode; -use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, SignParam, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, + SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -35,24 +34,8 @@ pub type HeaderId = #[derive(Debug, Clone, Copy)] pub struct RialtoParachain; -impl ChainBase for RialtoParachain { - type BlockNumber = rialto_parachain_runtime::BlockNumber; - type Hash = rialto_parachain_runtime::Hash; - type Hasher = rialto_parachain_runtime::Hashing; - type Header = rialto_parachain_runtime::Header; - - type AccountId = rialto_parachain_runtime::AccountId; - type Balance = rialto_parachain_runtime::Balance; - type Index = rialto_parachain_runtime::Index; - type Signature = rialto_parachain_runtime::Signature; - - fn max_extrinsic_size() -> u32 { - bp_rialto_parachain::RialtoParachain::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_rialto_parachain::RialtoParachain::max_extrinsic_weight() - } +impl UnderlyingChainProvider for RialtoParachain { + type Chain = bp_rialto_parachain::RialtoParachain; } impl Chain for RialtoParachain { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 6ea500ea00aac..4c3a9d1e18eaa 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -18,11 +18,10 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; -use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, IndexOf, RelayChain, SignParam, - UnsignedTransaction, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -35,24 +34,8 @@ pub type HeaderId = relay_utils::HeaderId u32 { - bp_rialto::Rialto::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_rialto::Rialto::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Rialto { + type Chain = bp_rialto::Rialto; } impl Chain for Rialto { diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 38a95042ff3b0..0123fe1d77252 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,8 +16,9 @@ //! Types used to connect to the Rococo-Substrate chain. -use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, RelayChain}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -31,24 +32,8 @@ pub type SyncHeader = relay_substrate_client::SyncHeader; #[derive(Debug, Clone, Copy)] pub struct Rococo; -impl ChainBase for Rococo { - type BlockNumber = bp_rococo::BlockNumber; - type Hash = bp_rococo::Hash; - type Hasher = bp_rococo::Hashing; - type Header = bp_rococo::Header; - - type AccountId = bp_rococo::AccountId; - type Balance = bp_rococo::Balance; - type Index = bp_rococo::Nonce; - type Signature = bp_rococo::Signature; - - fn max_extrinsic_size() -> u32 { - bp_rococo::Rococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_rococo::Rococo::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Rococo { + type Chain = bp_rococo::Rococo; } impl Chain for Rococo { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 27a95a3106de4..10e3a4749e092 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,7 +16,8 @@ use bp_messages::MessageNonce; use bp_runtime::{ - Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEra, TransactionEraOf, + Chain as ChainBase, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra, + TransactionEraOf, UnderlyingChainProvider, }; use codec::{Codec, Encode}; use jsonrpsee::core::{DeserializeOwned, Serialize}; @@ -72,6 +73,11 @@ pub trait RelayChain: Chain { const PARACHAINS_FINALITY_PALLET_NAME: &'static str; } +/// Substrate-based parachain from minimal relay-client point of view. +pub trait Parachain: Chain + ParachainBase {} + +impl Parachain for T where T: UnderlyingChainProvider + Chain + ParachainBase {} + /// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of /// view. /// diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 7170d58e2c0a7..c9926855fd5da 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -34,8 +34,8 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, RelayChain, SignParam, - TransactionStatusOf, UnsignedTransaction, + ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, Parachain, RelayChain, + SignParam, TransactionStatusOf, UnsignedTransaction, }, client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, error::{Error, Result}, @@ -45,7 +45,8 @@ pub use crate::{ }; pub use bp_runtime::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderIdOf, - HeaderOf, IndexOf, SignatureOf, TransactionEra, TransactionEraOf, + HeaderOf, IndexOf, Parachain as ParachainBase, SignatureOf, TransactionEra, TransactionEraOf, + UnderlyingChainProvider, }; /// Substrate-over-websocket connection params. diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 9132a38710a11..6467f431335cf 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,8 +16,9 @@ //! Types used to connect to the Westend chain. -use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, RelayChain}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -31,24 +32,8 @@ pub type SyncHeader = relay_substrate_client::SyncHeader; #[derive(Debug, Clone, Copy)] pub struct Westend; -impl ChainBase for Westend { - type BlockNumber = bp_westend::BlockNumber; - type Hash = bp_westend::Hash; - type Hasher = bp_westend::Hasher; - type Header = bp_westend::Header; - - type AccountId = bp_westend::AccountId; - type Balance = bp_westend::Balance; - type Index = bp_westend::Nonce; - type Signature = bp_westend::Signature; - - fn max_extrinsic_size() -> u32 { - bp_westend::Westend::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_westend::Westend::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Westend { + type Chain = bp_westend::Westend; } impl Chain for Westend { @@ -83,26 +68,8 @@ impl ChainWithBalances for Westend { #[derive(Debug, Clone, Copy)] pub struct Westmint; -// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend -// primitives here. -impl ChainBase for Westmint { - type BlockNumber = bp_westend::BlockNumber; - type Hash = bp_westend::Hash; - type Hasher = bp_westend::Hasher; - type Header = bp_westend::Header; - - type AccountId = bp_westend::AccountId; - type Balance = bp_westend::Balance; - type Index = bp_westend::Nonce; - type Signature = bp_westend::Signature; - - fn max_extrinsic_size() -> u32 { - bp_westend::Westend::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_westend::Westend::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Westmint { + type Chain = bp_westend::Westmint; } // Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 6fc3714f66704..63bd9b8f8963f 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,8 +16,9 @@ //! Types used to connect to the Wococo-Substrate chain. -use frame_support::weights::Weight; -use relay_substrate_client::{Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, RelayChain}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -31,24 +32,8 @@ pub type SyncHeader = relay_substrate_client::SyncHeader; #[derive(Debug, Clone, Copy)] pub struct Wococo; -impl ChainBase for Wococo { - type BlockNumber = bp_wococo::BlockNumber; - type Hash = bp_wococo::Hash; - type Hasher = bp_wococo::Hashing; - type Header = bp_wococo::Header; - - type AccountId = bp_wococo::AccountId; - type Balance = bp_wococo::Balance; - type Index = bp_wococo::Nonce; - type Signature = bp_wococo::Signature; - - fn max_extrinsic_size() -> u32 { - bp_wococo::Wococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_wococo::Wococo::max_extrinsic_weight() - } +impl UnderlyingChainProvider for Wococo { + type Chain = bp_wococo::Wococo; } impl Chain for Wococo { diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 35ef8244ae630..991a84352e7c1 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -39,6 +39,7 @@ use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumbe use parachains_relay::parachains_loop::{AvailableHeader, ParachainSyncParams, TargetClient}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, + ParachainBase, }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, HeaderId, @@ -278,7 +279,7 @@ async fn background_task( parachains_source.clone(), parachains_target.clone(), ParachainSyncParams { - parachains: vec![P::SOURCE_PARACHAIN_PARA_ID.into()], + parachains: vec![P::SourceParachain::PARACHAIN_ID.into()], stall_timeout: std::time::Duration::from_secs(60), strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, }, @@ -386,7 +387,10 @@ where source.client().best_finalized_header().await.map_err(map_source_err)?; let best_finalized_relay_block_id = best_finalized_relay_header.id(); let para_header_at_source = source - .on_chain_para_head_id(best_finalized_relay_block_id, P::SOURCE_PARACHAIN_PARA_ID.into()) + .on_chain_para_head_id( + best_finalized_relay_block_id, + P::SourceParachain::PARACHAIN_ID.into(), + ) .await .map_err(map_source_err)?; @@ -401,7 +405,7 @@ where .map_err(map_target_err)?; let para_header_at_relay_header_at_target = source - .on_chain_para_head_id(relay_header_at_target, P::SOURCE_PARACHAIN_PARA_ID.into()) + .on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into()) .await .map_err(map_source_err)?; diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/relays/lib-substrate-relay/src/parachains/mod.rs index 1d744a30e4ea5..9852e512f7e9c 100644 --- a/relays/lib-substrate-relay/src/parachains/mod.rs +++ b/relays/lib-substrate-relay/src/parachains/mod.rs @@ -24,7 +24,9 @@ use pallet_bridge_parachains::{ RelayBlockHasher, RelayBlockNumber, }; use parachains_relay::ParachainsPipeline; -use relay_substrate_client::{CallOf, Chain, ChainWithTransactions, HeaderIdOf, RelayChain}; +use relay_substrate_client::{ + CallOf, Chain, ChainWithTransactions, HeaderIdOf, Parachain, RelayChain, +}; use std::{fmt::Debug, marker::PhantomData}; pub mod source; @@ -37,7 +39,7 @@ pub mod target; #[async_trait] pub trait SubstrateParachainsPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this parachain are submitted to the `Self::TargetChain`. - type SourceParachain: Chain; + type SourceParachain: Parachain; /// Relay chain that is storing headers of `Self::SourceParachain`. type SourceRelayChain: RelayChain; /// Target chain where `Self::SourceParachain` headers are submitted. @@ -45,9 +47,6 @@ pub trait SubstrateParachainsPipeline: 'static + Clone + Debug + Send + Sync { /// How submit parachains heads call is built? type SubmitParachainHeadsCallBuilder: SubmitParachainHeadsCallBuilder; - - /// Id of the `Self::SourceParachain`, used for registration in `Self::SourceRelayChain`. - const SOURCE_PARACHAIN_PARA_ID: u32; } /// Adapter that allows all `SubstrateParachainsPipeline` to act as `ParachainsPipeline`. diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index b61b893e5bc21..afacd18e2927a 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -29,7 +29,7 @@ use parachains_relay::{ parachains_loop_metrics::ParachainsLoopMetrics, }; use relay_substrate_client::{ - Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, RelayChain, + Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase, RelayChain, }; use relay_utils::relay_loop::Client as RelayClient; @@ -107,11 +107,11 @@ where para_id: ParaId, ) -> Result, Self::Error> { // we don't need to support many parachains now - if para_id.0 != P::SOURCE_PARACHAIN_PARA_ID { + if para_id.0 != P::SourceParachain::PARACHAIN_ID { return Err(SubstrateError::Custom(format!( "Parachain id {} is not matching expected {}", para_id.0, - P::SOURCE_PARACHAIN_PARA_ID, + P::SourceParachain::PARACHAIN_ID, ))) } @@ -144,7 +144,7 @@ where at_block: HeaderIdOf, parachains: &[ParaId], ) -> Result<(ParaHeadsProof, Vec), Self::Error> { - let parachain = ParaId(P::SOURCE_PARACHAIN_PARA_ID); + let parachain = ParaId(P::SourceParachain::PARACHAIN_ID); if parachains != [parachain] { return Err(SubstrateError::Custom(format!( "Trying to prove unexpected parachains {parachains:?}. Expected {parachain:?}", From 366c653e058a37b5382adb449acf8b5bbd87a0aa Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 14 Dec 2022 13:20:45 +0100 Subject: [PATCH 0840/1210] Check origin? (#1718) * Check origin? * Removed ensure_signed * clippy --- modules/grandpa/src/lib.rs | 4 +--- modules/parachains/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index f1e4a8da1ecf2..926594ad79604 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -45,7 +45,6 @@ use bp_header_chain::{ use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{ensure, fail}; -use frame_system::ensure_signed; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::traits::{Header as HeaderT, Zero}; use sp_std::{boxed::Box, convert::TryInto}; @@ -156,12 +155,11 @@ pub mod pallet { justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX), ))] pub fn submit_finality_proof( - origin: OriginFor, + _origin: OriginFor, finality_target: Box>, justification: GrandpaJustification>, ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; - let _ = ensure_signed(origin)?; ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index bf2ab8dcd647a..3cfda0012732b 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -275,6 +275,7 @@ pub mod pallet { parachain_heads_proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; + // we'll need relay chain header to verify that parachains heads are always increasing. let (relay_block_number, relay_block_hash) = at_relay_block; let relay_block = pallet_bridge_grandpa::ImportedHeaders::< From 317f4cceedfb4df402e6dcd3aaebc889fb20498b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 15 Dec 2022 10:24:51 +0300 Subject: [PATCH 0841/1210] tests (#1720) --- .../src/refund_relayer_extension.rs | 80 +++++++++++++++---- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 76e15ab3cbc9f..b7c6f71dca170 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -220,11 +220,19 @@ where fn validate( &self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, + who: &Self::AccountId, + call: &Self::Call, + info: &DispatchInfoOf, + len: usize, ) -> TransactionValidity { + // reject batch transactions with obsolete headers + if let Some(UtilityCall::::batch_all { ref calls }) = call.is_sub_type() { + for nested_call in calls { + let reject_obsolete_transactions = BE::default(); + reject_obsolete_transactions.pre_dispatch(who, nested_call, info, len)?; + } + } + Ok(ValidTransaction::default()) } @@ -232,16 +240,11 @@ where self, who: &Self::AccountId, call: &Self::Call, - post_info: &DispatchInfoOf, + info: &DispatchInfoOf, len: usize, ) -> Result { // reject batch transactions with obsolete headers - if let Some(UtilityCall::::batch_all { ref calls }) = call.is_sub_type() { - for nested_call in calls { - let reject_obsolete_transactions = BE::default(); - reject_obsolete_transactions.pre_dispatch(who, nested_call, post_info, len)?; - } - } + self.validate(who, call, info, len).map(drop)?; // now try to check if tx matches one of types we support let parse_call_type = || { @@ -611,6 +614,11 @@ mod tests { sp_io::TestExternalities::new(Default::default()).execute_with(test) } + fn run_validate(call: RuntimeCall) -> TransactionValidity { + let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData); + extension.validate(&relayer_account(), &call, &DispatchInfo::default(), 0) + } + fn run_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { @@ -654,7 +662,26 @@ mod tests { } #[test] - fn pre_dispatch_rejects_batch_with_obsolete_relay_chain_header() { + fn validate_allows_non_obsolete_transactions() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!(run_validate(message_delivery_call(200)), Ok(ValidTransaction::default()),); + + assert_eq!( + run_validate(parachain_finality_and_delivery_batch_call(200, 200)), + Ok(ValidTransaction::default()), + ); + + assert_eq!( + run_validate(all_finality_and_delivery_batch_call(200, 200, 200)), + Ok(ValidTransaction::default()), + ); + }); + } + + #[test] + fn ext_rejects_batch_with_obsolete_relay_chain_header() { run_test(|| { initialize_environment(100, 100, 100); @@ -662,11 +689,16 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + + assert_eq!( + run_validate(all_finality_and_delivery_batch_call(100, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } #[test] - fn pre_dispatch_rejects_batch_with_obsolete_parachain_head() { + fn ext_rejects_batch_with_obsolete_parachain_head() { run_test(|| { initialize_environment(100, 100, 100); @@ -679,11 +711,21 @@ mod tests { run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + + assert_eq!( + run_validate(all_finality_and_delivery_batch_call(101, 100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_validate(parachain_finality_and_delivery_batch_call(100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } #[test] - fn pre_dispatch_rejects_batch_with_obsolete_messages() { + fn ext_rejects_batch_with_obsolete_messages() { run_test(|| { initialize_environment(100, 100, 100); @@ -696,6 +738,16 @@ mod tests { run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + + assert_eq!( + run_validate(all_finality_and_delivery_batch_call(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_validate(parachain_finality_and_delivery_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } From 848bd7b1870c79d41e98b5d1be5ffdd9d48a6358 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 16 Dec 2022 13:40:00 +0300 Subject: [PATCH 0842/1210] fix pallet names at bridge hubs (#1722) --- relays/client-rococo/src/lib.rs | 2 +- relays/client-wococo/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 0123fe1d77252..a764759906ac4 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -59,5 +59,5 @@ impl ChainWithBalances for Rococo { impl RelayChain for Rococo { const PARAS_PALLET_NAME: &'static str = bp_rococo::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "bridgeRococoParachain"; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeRococoParachain"; } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 63bd9b8f8963f..a3e10729ba093 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -59,5 +59,5 @@ impl ChainWithBalances for Wococo { impl RelayChain for Wococo { const PARAS_PALLET_NAME: &'static str = bp_wococo::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "bridgeWococoParachain"; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWococoParachain"; } From 886e5dd680351d94dcda21d86f07e3fd2d04ce87 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 16 Dec 2022 15:04:36 +0300 Subject: [PATCH 0843/1210] Batch transactions in complex relays (#1669) * batch transactions in message relay: API prototype * get rid of Box and actually submit it * test batch transactions * message_lane_loop_works_with_batch_transactions * removed logger * BatchConfirmationTransaction + BatchDeliveryTransaction * more prototyping * fmt * continue with batch calls * impl BatchCallBuilder for () * BatchDeliveryTransaction impl * BundledBatchCallBuilder * proper impl of BundledBatchCallBuilder + use it in RialtoParachain -> Millau * impl prove_header in OnDemandHeadersRelay * impl OnDemandParachainsRelay::prove_header (needs extensive tests) * added a couple of TODOs * return Result> when asking for more headers * prove headers when reauire_* is called && return proper headers from required_header_id * split parachains::prove_header and test select_headers_to_prove * more traces and leave TODOs * use finality stream in SubstrateFinalitySource::prove_block_finality * prove parachain head at block, selected by headers relay * const ANCIENT_BLOCK_THRESHOLD * TODO -> proof * clippy and spelling * BatchCallBuilder::build_batch_call() returns Result * read first proof from two streams * FailedToFindFinalityProof -> FinalityProofNotFound * changed select_headers_to_prove to version from PR review --- ...ub_rococo_messages_to_bridge_hub_wococo.rs | 3 + ...ub_wococo_messages_to_bridge_hub_rococo.rs | 3 + .../src/chains/millau_messages_to_rialto.rs | 3 + .../millau_messages_to_rialto_parachain.rs | 3 + .../src/chains/rialto_messages_to_millau.rs | 3 + .../rialto_parachain_messages_to_millau.rs | 12 +- .../src/cli/relay_headers_and_messages/mod.rs | 10 +- .../parachain_to_parachain.rs | 17 +- .../relay_to_parachain.rs | 13 +- .../relay_to_relay.rs | 9 +- relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/client.rs | 12 + relays/client-substrate/src/error.rs | 7 + relays/client-substrate/src/lib.rs | 5 +- relays/lib-substrate-relay/Cargo.toml | 1 + .../src/finality/source.rs | 151 +++++++- relays/lib-substrate-relay/src/lib.rs | 52 +++ .../lib-substrate-relay/src/messages_lane.rs | 15 +- .../src/messages_source.rs | 100 +++++- .../src/messages_target.rs | 123 ++++++- .../src/on_demand/headers.rs | 53 ++- .../lib-substrate-relay/src/on_demand/mod.rs | 14 +- .../src/on_demand/parachains.rs | 332 +++++++++++++++++- relays/messages/src/message_lane_loop.rs | 261 ++++++++++++-- relays/messages/src/message_race_delivery.rs | 6 +- relays/messages/src/message_race_loop.rs | 123 ++++++- relays/messages/src/message_race_receiving.rs | 6 +- relays/utils/src/lib.rs | 2 +- 28 files changed, 1189 insertions(+), 151 deletions(-) diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index 6f9f05e663e7e..339be92063e21 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -59,4 +59,7 @@ impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWococoMessageLan BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder; type ReceiveMessagesDeliveryProofCallBuilder = BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = (); } diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index 2b38eccbcb644..3bb2aabde06ba 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -59,4 +59,7 @@ impl SubstrateMessageLane for BridgeHubWococoMessagesToBridgeHubRococoMessageLan BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; type ReceiveMessagesDeliveryProofCallBuilder = BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = (); } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index b9920db53d85d..e6a2ef1a85660 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -41,4 +41,7 @@ impl SubstrateMessageLane for MillauMessagesToRialto { millau_runtime::Runtime, millau_runtime::WithRialtoMessagesInstance, >; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = (); } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index 70cb887fa35d4..0b1d3afb797ce 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -41,4 +41,7 @@ impl SubstrateMessageLane for MillauMessagesToRialtoParachain { millau_runtime::Runtime, millau_runtime::WithRialtoParachainMessagesInstance, >; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = (); } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 80b6b9fdbc6b0..b45239fb9a91e 100644 --- a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -41,4 +41,7 @@ impl SubstrateMessageLane for RialtoMessagesToMillau { rialto_runtime::Runtime, rialto_runtime::WithMillauMessagesInstance, >; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = (); } diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index 5cca26105b87d..8400157b9d651 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -18,9 +18,12 @@ use relay_millau_client::Millau; use relay_rialto_parachain_client::RialtoParachain; -use substrate_relay_helper::messages_lane::{ - DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, - SubstrateMessageLane, +use substrate_relay_helper::{ + messages_lane::{ + DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, + SubstrateMessageLane, + }, + BundledBatchCallBuilder, }; /// Description of RialtoParachain -> Millau messages bridge. @@ -41,4 +44,7 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { rialto_parachain_runtime::Runtime, rialto_parachain_runtime::WithMillauMessagesInstance, >; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = BundledBatchCallBuilder; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 11cae48d1d987..1ee7172228c06 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -59,7 +59,7 @@ use crate::{ declare_chain_cli_schema, }; use bp_messages::LaneId; -use bp_runtime::{BalanceOf, BlockNumberOf}; +use bp_runtime::BalanceOf; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithTransactions, Client, Parachain, @@ -167,8 +167,8 @@ where /// Returns message relay parameters. fn messages_relay_params( &self, - source_to_target_headers_relay: Arc>>, - target_to_source_headers_relay: Arc>>, + source_to_target_headers_relay: Arc>, + target_to_source_headers_relay: Arc>, lane_id: LaneId, ) -> MessagesRelayParams { MessagesRelayParams { @@ -243,8 +243,8 @@ trait Full2WayBridgeBase: Sized + Send + Sync { async fn start_on_demand_headers_relayers( &mut self, ) -> anyhow::Result<( - Arc>>, - Arc>>, + Arc>, + Arc>, )>; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index eedebe93c3332..48fc0fab49b9b 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -23,7 +23,6 @@ use crate::cli::{ CliChain, }; use bp_polkadot_core::parachains::ParaHash; -use bp_runtime::BlockNumberOf; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, @@ -215,8 +214,8 @@ where async fn start_on_demand_headers_relayers( &mut self, ) -> anyhow::Result<( - Arc>>, - Arc>>, + Arc>, + Arc>, )> { self.common.left.accounts.push(TaggedAccount::Headers { id: self.right_headers_to_left_transaction_params.signer.public().into(), @@ -249,31 +248,31 @@ where .await?; let left_relay_to_right_on_demand_headers = - OnDemandHeadersRelay::new::<::RelayFinality>( + OnDemandHeadersRelay::<::RelayFinality>::new( self.left_relay.clone(), self.common.right.client.clone(), self.left_headers_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_relay_to_left_on_demand_headers = - OnDemandHeadersRelay::new::<::RelayFinality>( + OnDemandHeadersRelay::<::RelayFinality>::new( self.right_relay.clone(), self.common.left.client.clone(), self.right_headers_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); - let left_to_right_on_demand_parachains = OnDemandParachainsRelay::new::< + let left_to_right_on_demand_parachains = OnDemandParachainsRelay::< ::ParachainFinality, - >( + >::new( self.left_relay.clone(), self.common.right.client.clone(), self.left_parachains_to_right_transaction_params.clone(), Arc::new(left_relay_to_right_on_demand_headers), ); - let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::< + let right_to_left_on_demand_parachains = OnDemandParachainsRelay::< ::ParachainFinality, - >( + >::new( self.right_relay.clone(), self.common.left.client.clone(), self.right_parachains_to_left_transaction_params.clone(), diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 22324c1d6ffdf..aa4aaf16d70e1 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -26,7 +26,6 @@ use crate::cli::{ CliChain, }; use bp_polkadot_core::parachains::ParaHash; -use bp_runtime::BlockNumberOf; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, @@ -199,8 +198,8 @@ where async fn start_on_demand_headers_relayers( &mut self, ) -> anyhow::Result<( - Arc>>, - Arc>>, + Arc>, + Arc>, )> { self.common.left.accounts.push(TaggedAccount::Headers { id: self.right_headers_to_left_transaction_params.signer.public().into(), @@ -229,22 +228,22 @@ where .await?; let left_to_right_on_demand_headers = - OnDemandHeadersRelay::new::<::Finality>( + OnDemandHeadersRelay::<::Finality>::new( self.common.left.client.clone(), self.common.right.client.clone(), self.left_headers_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_relay_to_left_on_demand_headers = - OnDemandHeadersRelay::new::<::RelayFinality>( + OnDemandHeadersRelay::<::RelayFinality>::new( self.right_relay.clone(), self.common.left.client.clone(), self.right_headers_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); - let right_to_left_on_demand_parachains = OnDemandParachainsRelay::new::< + let right_to_left_on_demand_parachains = OnDemandParachainsRelay::< ::ParachainFinality, - >( + >::new( self.right_relay.clone(), self.common.left.client.clone(), self.right_parachains_to_left_transaction_params.clone(), diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index bda532a2afd6c..625f1e66328d6 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -22,7 +22,6 @@ use crate::cli::{ relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, CliChain, }; -use bp_runtime::BlockNumberOf; use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, ChainWithTransactions}; use sp_core::Pair; use substrate_relay_helper::{ @@ -149,8 +148,8 @@ where async fn start_on_demand_headers_relayers( &mut self, ) -> anyhow::Result<( - Arc>>, - Arc>>, + Arc>, + Arc>, )> { self.common.right.accounts.push(TaggedAccount::Headers { id: self.left_to_right_transaction_params.signer.public().into(), @@ -175,14 +174,14 @@ where .await?; let left_to_right_on_demand_headers = - OnDemandHeadersRelay::new::<::Finality>( + OnDemandHeadersRelay::<::Finality>::new( self.common.left.client.clone(), self.common.right.client.clone(), self.left_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, ); let right_to_left_on_demand_headers = - OnDemandHeadersRelay::new::<::Finality>( + OnDemandHeadersRelay::<::Finality>::new( self.common.right.client.clone(), self.common.left.client.clone(), self.right_to_left_transaction_params.clone(), diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 60ef1c67a26a8..3f5156b76532e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -21,6 +21,7 @@ thiserror = "1.0.26" bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } pallet-bridge-messages = { path = "../../modules/messages" } finality-relay = { path = "../finality" } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 4f783291ee323..07293a7e65375 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -57,6 +57,18 @@ const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_validate_transaction"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; +/// The difference between best block number and number of its ancestor, that is enough +/// for us to consider that ancestor an "ancient" block with dropped state. +/// +/// The relay does not assume that it is connected to the archive node, so it always tries +/// to use the best available chain state. But sometimes it still may use state of some +/// old block. If the state of that block is already dropped, relay will see errors when +/// e.g. it tries to prove something. +/// +/// By default Substrate-based nodes are storing state for last 256 blocks. We'll use +/// half of this value. +pub const ANCIENT_BLOCK_THRESHOLD: u32 = 128; + /// Opaque justifications subscription type. pub struct Subscription(pub(crate) Mutex>>); diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 9323b7572214c..ddea1819fb008 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -16,6 +16,7 @@ //! Substrate node RPC errors. +use bp_polkadot_core::parachains::ParaId; use jsonrpsee::core::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; @@ -45,6 +46,12 @@ pub enum Error { /// Runtime storage is missing some mandatory value. #[error("Mandatory storage value is missing from the runtime storage.")] MissingMandatoryStorageValue, + /// Required parachain head is not present at the relay chain. + #[error("Parachain {0:?} head {1} is missing from the relay chain storage.")] + MissingRequiredParachainHead(ParaId, u64), + /// Failed to find finality proof for the given header. + #[error("Failed to find finality proof for header {0}.")] + FinalityProofNotFound(u64), /// The client we're connected to is not synced, so we can't rely on its state. #[error("Substrate client is not synced {0}.")] ClientNotSynced(Health), diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index c9926855fd5da..dc90737523144 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -37,7 +37,10 @@ pub use crate::{ ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, Parachain, RelayChain, SignParam, TransactionStatusOf, UnsignedTransaction, }, - client::{ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription}, + client::{ + ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription, + ANCIENT_BLOCK_THRESHOLD, + }, error::{Error, Result}, rpc::{SubstrateBeefyFinalityClient, SubstrateFinalityClient, SubstrateGrandpaFinalityClient}, sync_header::SyncHeader, diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index bdf49d42eab44..1dd7cb7b37d2c 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -41,6 +41,7 @@ bp-messages = { path = "../../primitives/messages" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index e75862a8227bc..c8f11d99461ba 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -20,13 +20,18 @@ use crate::finality::{engine::Engine, FinalitySyncPipelineAdapter, SubstrateFina use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; +use bp_header_chain::FinalityProof; use codec::Decode; use finality_relay::SourceClient; -use futures::stream::{unfold, Stream, StreamExt}; +use futures::{ + select, + stream::{try_unfold, unfold, Stream, StreamExt, TryStreamExt}, +}; +use num_traits::One; use relay_substrate_client::{ BlockNumberOf, BlockWithJustification, Chain, Client, Error, HeaderOf, }; -use relay_utils::relay_loop::Client as RelayClient; +use relay_utils::{relay_loop::Client as RelayClient, UniqueSaturatedInto}; use std::pin::Pin; /// Shared updatable reference to the maximal header number that we want to sync from the source. @@ -70,6 +75,111 @@ impl SubstrateFinalitySource

{ // target node may be missing proofs that are already available at the source self.client.best_finalized_header_number().await } + + /// Return header and its justification of the given block or its descendant that + /// has a GRANDPA justification. + /// + /// This method is optimized for cases when `block_number` is close to the best finalized + /// chain block. + pub async fn prove_block_finality( + &self, + block_number: BlockNumberOf, + ) -> Result< + (relay_substrate_client::SyncHeader>, SubstrateFinalityProof

), + Error, + > { + // first, subscribe to proofs + let next_persistent_proof = + self.persistent_proofs_stream(block_number + One::one()).await?.fuse(); + let next_ephemeral_proof = self.ephemeral_proofs_stream(block_number).await?.fuse(); + + // in perfect world we'll need to return justfication for the requested `block_number` + let (header, maybe_proof) = self.header_and_finality_proof(block_number).await?; + if let Some(proof) = maybe_proof { + return Ok((header, proof)) + } + + // otherwise we don't care which header to return, so let's select first + futures::pin_mut!(next_persistent_proof, next_ephemeral_proof); + loop { + select! { + maybe_header_and_proof = next_persistent_proof.next() => match maybe_header_and_proof { + Some(header_and_proof) => return header_and_proof, + None => continue, + }, + maybe_header_and_proof = next_ephemeral_proof.next() => match maybe_header_and_proof { + Some(header_and_proof) => return header_and_proof, + None => continue, + }, + complete => return Err(Error::FinalityProofNotFound(block_number.unique_saturated_into())) + } + } + } + + /// Returns stream of headers and their persistent proofs, starting from given block. + async fn persistent_proofs_stream( + &self, + block_number: BlockNumberOf, + ) -> Result< + impl Stream< + Item = Result< + ( + relay_substrate_client::SyncHeader>, + SubstrateFinalityProof

, + ), + Error, + >, + >, + Error, + > { + let client = self.client.clone(); + let best_finalized_block_number = self.client.best_finalized_header_number().await?; + Ok(try_unfold((client, block_number), move |(client, current_block_number)| async move { + // if we've passed the `best_finalized_block_number`, we no longer need persistent + // justifications + if current_block_number > best_finalized_block_number { + return Ok(None) + } + + let (header, maybe_proof) = + header_and_finality_proof::

(&client, current_block_number).await?; + let next_block_number = current_block_number + One::one(); + let next_state = (client, next_block_number); + + Ok(Some((maybe_proof.map(|proof| (header, proof)), next_state))) + }) + .try_filter_map(|maybe_result| async { Ok(maybe_result) })) + } + + /// Returns stream of headers and their ephemeral proofs, starting from given block. + async fn ephemeral_proofs_stream( + &self, + block_number: BlockNumberOf, + ) -> Result< + impl Stream< + Item = Result< + ( + relay_substrate_client::SyncHeader>, + SubstrateFinalityProof

, + ), + Error, + >, + >, + Error, + > { + let client = self.client.clone(); + Ok(self.finality_proofs().await?.map(Ok).try_filter_map(move |proof| { + let client = client.clone(); + async move { + if proof.target_header_number() < block_number { + return Ok(None) + } + + let header = client.header_by_number(proof.target_header_number()).await?; + Ok(Some((header.into(), proof))) + } + })) + } } impl Clone for SubstrateFinalitySource

{ @@ -119,18 +229,7 @@ impl SourceClient { - let header_hash = self.client.block_hash_by_number(number).await?; - let signed_block = self.client.get_block(Some(header_hash)).await?; - - let justification = signed_block - .justification(P::FinalityEngine::ID) - .map(|raw_justification| { - SubstrateFinalityProof::

::decode(&mut raw_justification.as_slice()) - }) - .transpose() - .map_err(Error::ResponseParseFailed)?; - - Ok((signed_block.header().into(), justification)) + header_and_finality_proof::

(&self.client, number).await } async fn finality_proofs(&self) -> Result { @@ -173,3 +272,27 @@ impl SourceClient( + client: &Client, + number: BlockNumberOf, +) -> Result< + ( + relay_substrate_client::SyncHeader>, + Option>, + ), + Error, +> { + let header_hash = client.block_hash_by_number(number).await?; + let signed_block = client.get_block(Some(header_hash)).await?; + + let justification = signed_block + .justification(P::FinalityEngine::ID) + .map(|raw_justification| { + SubstrateFinalityProof::

::decode(&mut raw_justification.as_slice()) + }) + .transpose() + .map_err(Error::ResponseParseFailed)?; + + Ok((signed_block.header().into(), justification)) +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 62ae756e0031e..2181f0935836f 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -18,6 +18,9 @@ #![warn(missing_docs)] +use relay_substrate_client::Error as SubstrateError; +use std::marker::PhantomData; + pub mod error; pub mod finality; pub mod messages_lane; @@ -96,3 +99,52 @@ impl TaggedAccount { } } } + +/// Batch call builder. +pub trait BatchCallBuilder { + /// Associated error type. + type Error; + /// If `true`, then batch calls are supported at the chain. + const BATCH_CALL_SUPPORTED: bool; + + /// Create batch call from given calls vector. + fn build_batch_call(_calls: Vec) -> Result; +} + +impl BatchCallBuilder for () { + type Error = SubstrateError; + const BATCH_CALL_SUPPORTED: bool = false; + + fn build_batch_call(_calls: Vec) -> Result { + debug_assert!( + false, + "only called if `BATCH_CALL_SUPPORTED` is true;\ + `BATCH_CALL_SUPPORTED` is false;\ + qed" + ); + + Err(SubstrateError::Custom("<() as BatchCallBuilder>::build_batch_call() is called".into())) + } +} + +/// Batch call builder for bundled runtimes. +pub struct BundledBatchCallBuilder(PhantomData); + +impl BatchCallBuilder<::RuntimeCall> for BundledBatchCallBuilder +where + R: pallet_utility::Config::RuntimeCall>, + ::RuntimeCall: From>, +{ + type Error = SubstrateError; + const BATCH_CALL_SUPPORTED: bool = true; + + fn build_batch_call( + mut calls: Vec<::RuntimeCall>, + ) -> Result<::RuntimeCall, SubstrateError> { + Ok(if calls.len() == 1 { + calls.remove(0) + } else { + pallet_utility::Call::batch_all { calls }.into() + }) + } +} diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index da138a3d1258f..8ec78d0ae2cb8 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -20,7 +20,7 @@ use crate::{ messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand::OnDemandRelay, - TransactionParams, + BatchCallBuilder, TransactionParams, }; use async_std::sync::Arc; @@ -35,7 +35,7 @@ use messages_relay::message_lane::MessageLane; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, - ChainWithMessages, ChainWithTransactions, Client, HashOf, + ChainWithMessages, ChainWithTransactions, Client, Error as SubstrateError, HashOf, }; use relay_utils::{ metrics::{GlobalMetrics, MetricsParams, StandaloneMetric}, @@ -55,11 +55,16 @@ pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { type ReceiveMessagesProofCallBuilder: ReceiveMessagesProofCallBuilder; /// How receive messages delivery proof call is built? type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; + + /// How batch calls are built at the source chain? + type SourceBatchCallBuilder: BatchCallBuilder, Error = SubstrateError>; + /// How batch calls are built at the target chain? + type TargetBatchCallBuilder: BatchCallBuilder, Error = SubstrateError>; } /// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. #[derive(Clone, Debug)] -pub(crate) struct MessageLaneAdapter { +pub struct MessageLaneAdapter { _phantom: PhantomData

, } @@ -90,10 +95,10 @@ pub struct MessagesRelayParams { pub target_transaction_params: TransactionParams>, /// Optional on-demand source to target headers relay. pub source_to_target_headers_relay: - Option>>>, + Option>>, /// Optional on-demand target to source headers relay. pub target_to_source_headers_relay: - Option>>>, + Option>>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, /// Metrics parameters. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index bf3779b3b404d..e2876b3107ea2 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -24,7 +24,7 @@ use crate::{ }, messages_target::SubstrateMessagesDeliveryProof, on_demand::OnDemandRelay, - TransactionParams, + BatchCallBuilder, TransactionParams, }; use async_std::sync::Arc; @@ -41,14 +41,14 @@ use frame_support::weights::Weight; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, - SourceClientState, + BatchTransaction, ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, + SourceClient, SourceClientState, }, }; use num_traits::Zero; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, + Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; @@ -68,7 +68,7 @@ pub struct SubstrateMessagesSource { target_client: Client, lane_id: LaneId, transaction_params: TransactionParams>, - target_to_source_headers_relay: Option>>>, + target_to_source_headers_relay: Option>>, } impl SubstrateMessagesSource

{ @@ -79,7 +79,7 @@ impl SubstrateMessagesSource

{ lane_id: LaneId, transaction_params: TransactionParams>, target_to_source_headers_relay: Option< - Arc>>, + Arc>, >, ) -> Self { SubstrateMessagesSource { @@ -140,6 +140,7 @@ impl SourceClient> for SubstrateM where AccountIdOf: From< as Pair>::Public>, { + type BatchTransaction = BatchConfirmationTransaction

; type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { @@ -360,10 +361,93 @@ where .await } - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf>) { + async fn require_target_header_on_source( + &self, + id: TargetHeaderIdOf>, + ) -> Result, SubstrateError> { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { + if P::SourceBatchCallBuilder::BATCH_CALL_SUPPORTED { + return BatchConfirmationTransaction::

::new(self.clone(), id).await.map(Some) + } + target_to_source_headers_relay.require_more_headers(id.0).await; } + + Ok(None) + } +} + +/// Batch transaction that brings target headers + and delivery confirmations to the source node. +pub struct BatchConfirmationTransaction { + messages_source: SubstrateMessagesSource

, + proved_header: TargetHeaderIdOf>, + prove_calls: Vec>, +} + +impl BatchConfirmationTransaction

{ + async fn new( + messages_source: SubstrateMessagesSource

, + required_target_header_on_source: TargetHeaderIdOf>, + ) -> Result { + let (proved_header, prove_calls) = messages_source + .target_to_source_headers_relay + .as_ref() + .expect("BatchConfirmationTransaction is only created when target_to_source_headers_relay is Some; qed") + .prove_header(required_target_header_on_source.0) + .await?; + Ok(Self { messages_source, proved_header, prove_calls }) + } +} + +#[async_trait] +impl + BatchTransaction< + TargetHeaderIdOf>, + as MessageLane>::MessagesReceivingProof, + TransactionTracker>, + SubstrateError, + > for BatchConfirmationTransaction

+where + AccountIdOf: From< as Pair>::Public>, +{ + fn required_header_id(&self) -> TargetHeaderIdOf> { + self.proved_header + } + + async fn append_proof_and_send( + self, + proof: as MessageLane>::MessagesReceivingProof, + ) -> Result>, SubstrateError> { + let mut calls = self.prove_calls; + calls.push( + P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( + proof, false, + ), + ); + let batch_call = P::SourceBatchCallBuilder::build_batch_call(calls)?; + + let (spec_version, transaction_version) = + self.messages_source.source_client.simple_runtime_version().await?; + self.messages_source + .source_client + .submit_and_watch_signed_extrinsic( + self.messages_source.transaction_params.signer.public().into(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash: *self.messages_source.source_client.genesis_hash(), + signer: self.messages_source.transaction_params.signer.clone(), + }, + move |best_block_id, transaction_nonce| { + Ok(UnsignedTransaction::new(batch_call.into(), transaction_nonce).era( + TransactionEra::new( + best_block_id, + self.messages_source.transaction_params.mortality, + ), + )) + }, + ) + .await } } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 22a50acf37eb6..9d80b9166c855 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -22,7 +22,7 @@ use crate::{ messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, on_demand::OnDemandRelay, - TransactionParams, + BatchCallBuilder, TransactionParams, }; use async_std::sync::Arc; @@ -34,10 +34,10 @@ use bp_messages::{ use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, + message_lane_loop::{BatchTransaction, NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, ChainWithMessages, Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, TransactionTracker, UnsignedTransaction, }; @@ -56,7 +56,7 @@ pub struct SubstrateMessagesTarget { lane_id: LaneId, relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, - source_to_target_headers_relay: Option>>>, + source_to_target_headers_relay: Option>>, } impl SubstrateMessagesTarget

{ @@ -68,7 +68,7 @@ impl SubstrateMessagesTarget

{ relayer_id_at_source: AccountIdOf, transaction_params: TransactionParams>, source_to_target_headers_relay: Option< - Arc>>, + Arc>, >, ) -> Self { SubstrateMessagesTarget { @@ -132,6 +132,7 @@ where AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, { + type BatchTransaction = BatchDeliveryTransaction

; type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { @@ -267,32 +268,126 @@ where Ok(NoncesSubmitArtifacts { nonces, tx_tracker }) } - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf>) { + async fn require_source_header_on_target( + &self, + id: SourceHeaderIdOf>, + ) -> Result, SubstrateError> { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { + if P::TargetBatchCallBuilder::BATCH_CALL_SUPPORTED { + return BatchDeliveryTransaction::

::new(self.clone(), id).await.map(Some) + } + source_to_target_headers_relay.require_more_headers(id.0).await; } + + Ok(None) } } -/// Make messages delivery transaction from given proof. -fn make_messages_delivery_transaction( - target_transaction_params: &TransactionParams>, - target_best_block_id: HeaderIdOf, - transaction_nonce: IndexOf, +/// Batch transaction that brings target headers + and delivery confirmations to the source node. +pub struct BatchDeliveryTransaction { + messages_target: SubstrateMessagesTarget

, + proved_header: SourceHeaderIdOf>, + prove_calls: Vec>, +} + +impl BatchDeliveryTransaction

{ + async fn new( + messages_target: SubstrateMessagesTarget

, + required_source_header_on_target: SourceHeaderIdOf>, + ) -> Result { + let (proved_header, prove_calls) = messages_target + .source_to_target_headers_relay + .as_ref() + .expect("BatchDeliveryTransaction is only created when source_to_target_headers_relay is Some; qed") + .prove_header(required_source_header_on_target.0) + .await?; + Ok(Self { messages_target, proved_header, prove_calls }) + } +} + +#[async_trait] +impl + BatchTransaction< + SourceHeaderIdOf>, + as MessageLane>::MessagesProof, + TransactionTracker>, + SubstrateError, + > for BatchDeliveryTransaction

+where + AccountIdOf: From< as Pair>::Public>, +{ + fn required_header_id(&self) -> SourceHeaderIdOf> { + self.proved_header + } + + async fn append_proof_and_send( + self, + proof: as MessageLane>::MessagesProof, + ) -> Result>, SubstrateError> { + let mut calls = self.prove_calls; + calls.push(make_messages_delivery_call::

( + self.messages_target.relayer_id_at_source, + proof.1.nonces_start..=proof.1.nonces_end, + proof, + false, + )); + let batch_call = P::TargetBatchCallBuilder::build_batch_call(calls)?; + + let (spec_version, transaction_version) = + self.messages_target.target_client.simple_runtime_version().await?; + self.messages_target + .target_client + .submit_and_watch_signed_extrinsic( + self.messages_target.transaction_params.signer.public().into(), + SignParam:: { + spec_version, + transaction_version, + genesis_hash: *self.messages_target.target_client.genesis_hash(), + signer: self.messages_target.transaction_params.signer.clone(), + }, + move |best_block_id, transaction_nonce| { + Ok(UnsignedTransaction::new(batch_call.into(), transaction_nonce).era( + TransactionEra::new( + best_block_id, + self.messages_target.transaction_params.mortality, + ), + )) + }, + ) + .await + } +} + +/// Make messages delivery call from given proof. +fn make_messages_delivery_call( relayer_id_at_source: AccountIdOf, nonces: RangeInclusive, proof: SubstrateMessagesProof, trace_call: bool, -) -> Result, SubstrateError> { +) -> CallOf { let messages_count = nonces.end() - nonces.start() + 1; let dispatch_weight = proof.0; - let call = P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( + P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( relayer_id_at_source, proof, messages_count as _, dispatch_weight, trace_call, - ); + ) +} + +/// Make messages delivery transaction from given proof. +fn make_messages_delivery_transaction( + target_transaction_params: &TransactionParams>, + target_best_block_id: HeaderIdOf, + transaction_nonce: IndexOf, + relayer_id_at_source: AccountIdOf, + nonces: RangeInclusive, + proof: SubstrateMessagesProof, + trace_call: bool, +) -> Result, SubstrateError> { + let call = make_messages_delivery_call::

(relayer_id_at_source, nonces, proof, trace_call); Ok(UnsignedTransaction::new(call.into(), transaction_nonce) .era(TransactionEra::new(target_best_block_id, target_transaction_params.mortality))) } diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index c0603cda8cdc1..369520f0e9a41 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -16,15 +16,21 @@ //! On-demand Substrate -> Substrate header finality relay. +use crate::finality::SubmitFinalityProofCallBuilder; + use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::ConsensusLogReader; +use bp_runtime::HeaderIdProvider; use futures::{select, FutureExt}; use num_traits::{One, Zero}; use sp_runtime::traits::Header; use finality_relay::{FinalitySyncParams, TargetClient as FinalityTargetClient}; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client}; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError, + HeaderIdOf, +}; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, STALL_TIMEOUT, @@ -47,16 +53,18 @@ use crate::{ /// relay) needs it to continue its regular work. When enough headers are relayed, on-demand stops /// syncing headers. #[derive(Clone)] -pub struct OnDemandHeadersRelay { +pub struct OnDemandHeadersRelay { /// Relay task name. relay_task_name: String, /// Shared reference to maximal required finalized header number. - required_header_number: RequiredHeaderNumberRef, + required_header_number: RequiredHeaderNumberRef, + /// Client of the source chain. + source_client: Client, } -impl OnDemandHeadersRelay { +impl OnDemandHeadersRelay

{ /// Create new on-demand headers relay. - pub fn new>( + pub fn new( source_client: Client, target_client: Client, target_transaction_params: TransactionParams>, @@ -70,6 +78,7 @@ impl OnDemandHeadersRelay { let this = OnDemandHeadersRelay { relay_task_name: on_demand_headers_relay_name::(), required_header_number: required_header_number.clone(), + source_client: source_client.clone(), }; async_std::task::spawn(async move { background_task::

( @@ -87,23 +96,49 @@ impl OnDemandHeadersRelay { } #[async_trait] -impl OnDemandRelay> - for OnDemandHeadersRelay +impl OnDemandRelay + for OnDemandHeadersRelay

{ - async fn require_more_headers(&self, required_header: BlockNumberOf) { + async fn require_more_headers(&self, required_header: BlockNumberOf) { let mut required_header_number = self.required_header_number.lock().await; if required_header > *required_header_number { log::trace!( target: "bridge", "[{}] More {} headers required. Going to sync up to the {}", self.relay_task_name, - SourceChain::NAME, + P::SourceChain::NAME, required_header, ); *required_header_number = required_header; } } + + async fn prove_header( + &self, + required_header: BlockNumberOf, + ) -> Result<(HeaderIdOf, Vec>), SubstrateError> { + // first find proper header (either `required_header`) or its descendant + let finality_source = SubstrateFinalitySource::

::new(self.source_client.clone(), None); + let (header, proof) = finality_source.prove_block_finality(required_header).await?; + let header_id = header.id(); + + log::debug!( + target: "bridge", + "[{}] Requested to prove {} head {:?}. Selected to prove {} head {:?}", + self.relay_task_name, + P::SourceChain::NAME, + required_header, + P::SourceChain::NAME, + header_id, + ); + + // and then craft the submit-proof call + let call = + P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + + Ok((header_id, vec![call])) + } } /// Background task that is responsible for starting headers relay. diff --git a/relays/lib-substrate-relay/src/on_demand/mod.rs b/relays/lib-substrate-relay/src/on_demand/mod.rs index 7a2dfc9c1532f..eca7d20163d23 100644 --- a/relays/lib-substrate-relay/src/on_demand/mod.rs +++ b/relays/lib-substrate-relay/src/on_demand/mod.rs @@ -18,18 +18,28 @@ //! on-demand pipelines. use async_trait::async_trait; +use relay_substrate_client::{BlockNumberOf, CallOf, Chain, Error as SubstrateError, HeaderIdOf}; pub mod headers; pub mod parachains; /// On-demand headers relay that is relaying finalizing headers only when requested. #[async_trait] -pub trait OnDemandRelay: Send + Sync { +pub trait OnDemandRelay: Send + Sync { /// Ask relay to relay source header with given number to the target chain. /// /// Depending on implementation, on-demand relay may also relay `required_header` ancestors /// (e.g. if they're mandatory), or its descendants. The request is considered complete if /// the best avbailable header at the target chain has number that is larger than or equal /// to the `required_header`. - async fn require_more_headers(&self, required_header: SourceHeaderNumber); + async fn require_more_headers(&self, required_header: BlockNumberOf); + + /// Ask relay to prove source `required_header` to the `TargetChain`. + /// + /// Returns number of header that is proved (it may be the `required_header` or one of its + /// descendants) and calls for delivering the proof. + async fn prove_header( + &self, + required_header: BlockNumberOf, + ) -> Result<(HeaderIdOf, Vec>), SubstrateError>; } diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 991a84352e7c1..cfb9d9c7a9423 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -21,7 +21,7 @@ use crate::{ on_demand::OnDemandRelay, parachains::{ source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter, - SubstrateParachainsPipeline, + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, }, TransactionParams, }; @@ -31,18 +31,21 @@ use async_std::{ sync::{Arc, Mutex}, }; use async_trait::async_trait; -use bp_polkadot_core::parachains::ParaHash; +use bp_polkadot_core::parachains::{ParaHash, ParaId}; use bp_runtime::HeaderIdProvider; use futures::{select, FutureExt}; use num_traits::Zero; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use parachains_relay::parachains_loop::{AvailableHeader, ParachainSyncParams, TargetClient}; +use parachains_relay::parachains_loop::{ + AvailableHeader, ParachainSyncParams, SourceClient, TargetClient, +}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - ParachainBase, + AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError, + HashOf, HeaderIdOf, ParachainBase, ANCIENT_BLOCK_THRESHOLD, }; use relay_utils::{ - metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, HeaderId, + metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, + HeaderId, UniqueSaturatedInto, }; use std::fmt::Debug; @@ -52,25 +55,32 @@ use std::fmt::Debug; /// (e.g. messages relay) needs it to continue its regular work. When enough parachain headers /// are relayed, on-demand stops syncing headers. #[derive(Clone)] -pub struct OnDemandParachainsRelay { +pub struct OnDemandParachainsRelay { /// Relay task name. relay_task_name: String, /// Channel used to communicate with background task and ask for relay of parachain heads. - required_header_number_sender: Sender>, + required_header_number_sender: Sender>, + /// Source relay chain client. + source_relay_client: Client, + /// Target chain client. + target_client: Client, + /// On-demand relay chain relay. + on_demand_source_relay_to_target_headers: + Arc>, } -impl OnDemandParachainsRelay { +impl OnDemandParachainsRelay

{ /// Create new on-demand parachains relay. /// /// Note that the argument is the source relay chain client, not the parachain client. /// That's because parachain finality is determined by the relay chain and we don't /// need to connect to the parachain itself here. - pub fn new>( + pub fn new( source_relay_client: Client, target_client: Client, target_transaction_params: TransactionParams>, on_demand_source_relay_to_target_headers: Arc< - dyn OnDemandRelay>, + dyn OnDemandRelay, >, ) -> Self where @@ -82,8 +92,13 @@ impl OnDemandParachainsRelay { { let (required_header_number_sender, required_header_number_receiver) = unbounded(); let this = OnDemandParachainsRelay { - relay_task_name: on_demand_parachains_relay_name::(), + relay_task_name: on_demand_parachains_relay_name::( + ), required_header_number_sender, + source_relay_client: source_relay_client.clone(), + target_client: target_client.clone(), + on_demand_source_relay_to_target_headers: on_demand_source_relay_to_target_headers + .clone(), }; async_std::task::spawn(async move { background_task::

( @@ -101,23 +116,109 @@ impl OnDemandParachainsRelay { } #[async_trait] -impl OnDemandRelay> - for OnDemandParachainsRelay +impl OnDemandRelay + for OnDemandParachainsRelay

where - SourceParachain: Chain, + P::SourceParachain: Chain, { - async fn require_more_headers(&self, required_header: BlockNumberOf) { + async fn require_more_headers(&self, required_header: BlockNumberOf) { if let Err(e) = self.required_header_number_sender.send(required_header).await { log::trace!( target: "bridge", "[{}] Failed to request {} header {:?}: {:?}", self.relay_task_name, - SourceParachain::NAME, + P::SourceParachain::NAME, required_header, e, ); } } + + /// Ask relay to prove source `required_header` to the `TargetChain`. + async fn prove_header( + &self, + required_parachain_header: BlockNumberOf, + ) -> Result<(HeaderIdOf, Vec>), SubstrateError> { + // select headers to prove + let parachains_source = ParachainsSource::

::new( + self.source_relay_client.clone(), + Arc::new(Mutex::new(AvailableHeader::Missing)), + ); + let env = (self, ¶chains_source); + let (need_to_prove_relay_block, selected_relay_block, selected_parachain_block) = + select_headers_to_prove(env, required_parachain_header).await?; + + log::debug!( + target: "bridge", + "[{}] Requested to prove {} head {:?}. Selected to prove {} head {:?} and {} head {:?}", + self.relay_task_name, + P::SourceParachain::NAME, + required_parachain_header, + P::SourceParachain::NAME, + selected_parachain_block, + P::SourceRelayChain::NAME, + if need_to_prove_relay_block { + Some(selected_relay_block) + } else { + None + }, + ); + + // now let's prove relay chain block (if needed) + let mut calls = Vec::new(); + let mut proved_relay_block = selected_relay_block; + if need_to_prove_relay_block { + let (relay_block, relay_prove_call) = self + .on_demand_source_relay_to_target_headers + .prove_header(selected_relay_block.number()) + .await?; + proved_relay_block = relay_block; + calls.extend(relay_prove_call); + } + + // despite what we've selected before (in `select_headers_to_prove` call), if headers relay + // have chose the different header (e.g. because there's no GRANDPA jusstification for it), + // we need to prove parachain head available at this header + let para_id = ParaId(P::SourceParachain::PARACHAIN_ID); + let mut proved_parachain_block = selected_parachain_block; + if proved_relay_block != selected_relay_block { + proved_parachain_block = parachains_source + .on_chain_para_head_id(proved_relay_block, para_id) + .await? + // this could happen e.g. if parachain has been offboarded? + .ok_or_else(|| { + SubstrateError::MissingRequiredParachainHead( + para_id, + proved_relay_block.number().unique_saturated_into(), + ) + })?; + + log::debug!( + target: "bridge", + "[{}] Selected to prove {} head {:?} and {} head {:?}. Instead proved {} head {:?} and {} head {:?}", + self.relay_task_name, + P::SourceParachain::NAME, + selected_parachain_block, + P::SourceRelayChain::NAME, + selected_relay_block, + P::SourceParachain::NAME, + proved_parachain_block, + P::SourceRelayChain::NAME, + proved_relay_block, + ); + } + + // and finally - prove parachain head + let (para_proof, para_hashes) = + parachains_source.prove_parachain_heads(proved_relay_block, &[para_id]).await?; + calls.push(P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( + proved_relay_block, + para_hashes.into_iter().map(|h| (para_id, h)).collect(), + para_proof, + )); + + Ok((proved_parachain_block, calls)) + } } /// Background task that is responsible for starting parachain headers relay. @@ -126,7 +227,7 @@ async fn background_task( target_client: Client, target_transaction_params: TransactionParams>, on_demand_source_relay_to_target_headers: Arc< - dyn OnDemandRelay>, + dyn OnDemandRelay, >, required_parachain_header_number_receiver: Receiver>, ) where @@ -487,6 +588,125 @@ where RelayState::RelayingParaHeader(para_header_at_source) } +/// Environment for the `select_headers_to_prove` call. +#[async_trait] +trait SelectHeadersToProveEnvironment { + /// Returns associated parachain id. + fn parachain_id(&self) -> ParaId; + /// Returns best finalized relay block. + async fn best_finalized_relay_block_at_source( + &self, + ) -> Result, SubstrateError>; + /// Returns best finalized relay block that is known at `P::TargetChain`. + async fn best_finalized_relay_block_at_target( + &self, + ) -> Result, SubstrateError>; + /// Returns best finalized parachain block at given source relay chain block. + async fn best_finalized_para_block_at_source( + &self, + at_relay_block: HeaderId, + ) -> Result>, SubstrateError>; +} + +#[async_trait] +impl<'a, P: SubstrateParachainsPipeline> + SelectHeadersToProveEnvironment< + BlockNumberOf, + HashOf, + BlockNumberOf, + HashOf, + > for (&'a OnDemandParachainsRelay

, &'a ParachainsSource

) +{ + fn parachain_id(&self) -> ParaId { + ParaId(P::SourceParachain::PARACHAIN_ID) + } + + async fn best_finalized_relay_block_at_source( + &self, + ) -> Result, SubstrateError> { + Ok(self.0.source_relay_client.best_finalized_header().await?.id()) + } + + async fn best_finalized_relay_block_at_target( + &self, + ) -> Result, SubstrateError> { + Ok(crate::messages_source::read_client_state::( + &self.0.target_client, + None, + P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD, + ) + .await? + .best_finalized_peer_at_best_self) + } + + async fn best_finalized_para_block_at_source( + &self, + at_relay_block: HeaderIdOf, + ) -> Result>, SubstrateError> { + self.1.on_chain_para_head_id(at_relay_block, self.parachain_id()).await + } +} + +/// Given request to prove `required_parachain_header`, select actual headers that need to be +/// proved. +async fn select_headers_to_prove( + env: impl SelectHeadersToProveEnvironment, + required_parachain_header: PBN, +) -> Result<(bool, HeaderId, HeaderId), SubstrateError> +where + RBH: Copy, + RBN: BlockNumberBase, + PBH: Copy, + PBN: BlockNumberBase, +{ + // parachains proof also requires relay header proof. Let's first select relay block + // number that we'll be dealing with + let best_finalized_relay_block_at_source = env.best_finalized_relay_block_at_source().await?; + let best_finalized_relay_block_at_target = env.best_finalized_relay_block_at_target().await?; + + // if we can't prove `required_header` even using `best_finalized_relay_block_at_source`, we + // can't do anything here + // (this shall not actually happen, given current code, because we only require finalized + // headers) + let best_possible_parachain_block = env + .best_finalized_para_block_at_source(best_finalized_relay_block_at_source) + .await? + .filter(|best_possible_parachain_block| { + best_possible_parachain_block.number() >= required_parachain_header + }) + .ok_or(SubstrateError::MissingRequiredParachainHead( + env.parachain_id(), + required_parachain_header.unique_saturated_into(), + ))?; + + // now let's check if `required_header` may be proved using + // `best_finalized_relay_block_at_target` + let selection = env + .best_finalized_para_block_at_source(best_finalized_relay_block_at_target) + .await? + .filter(|best_finalized_para_block_at_target| { + best_finalized_para_block_at_target.number() >= required_parachain_header + }) + .map(|best_finalized_para_block_at_target| { + (false, best_finalized_relay_block_at_target, best_finalized_para_block_at_target) + }) + // we don't require source node to be archive, so we can't craft storage proofs using + // ancient headers. So if the `best_finalized_relay_block_at_target` is too ancient, we + // can't craft storage proofs using it + .filter(|(_, selected_relay_block, _)| { + let difference = best_finalized_relay_block_at_source + .number() + .saturating_sub(selected_relay_block.number()); + difference <= RBN::from(ANCIENT_BLOCK_THRESHOLD) + }); + + Ok(selection.unwrap_or(( + true, + best_finalized_relay_block_at_source, + best_possible_parachain_block, + ))) +} + #[cfg(test)] mod tests { use super::*; @@ -705,4 +925,80 @@ mod tests { RelayState::RelayingRelayHeader(800), ); } + + // tuple is: + // + // - best_finalized_relay_block_at_source + // - best_finalized_relay_block_at_target + // - best_finalized_para_block_at_source at best_finalized_relay_block_at_source + // - best_finalized_para_block_at_source at best_finalized_relay_block_at_target + #[async_trait] + impl SelectHeadersToProveEnvironment for (u32, u32, u32, u32) { + fn parachain_id(&self) -> ParaId { + ParaId(0) + } + + async fn best_finalized_relay_block_at_source( + &self, + ) -> Result, SubstrateError> { + Ok(HeaderId(self.0, self.0)) + } + + async fn best_finalized_relay_block_at_target( + &self, + ) -> Result, SubstrateError> { + Ok(HeaderId(self.1, self.1)) + } + + async fn best_finalized_para_block_at_source( + &self, + at_relay_block: HeaderId, + ) -> Result>, SubstrateError> { + if at_relay_block.0 == self.0 { + Ok(Some(HeaderId(self.2, self.2))) + } else if at_relay_block.0 == self.1 { + Ok(Some(HeaderId(self.3, self.3))) + } else { + Ok(None) + } + } + } + + #[async_std::test] + async fn select_headers_to_prove_returns_err_if_required_para_block_is_missing_at_source() { + assert!(matches!( + select_headers_to_prove((20_u32, 10_u32, 200_u32, 100_u32), 300_u32,).await, + Err(SubstrateError::MissingRequiredParachainHead(ParaId(0), 300_u64)), + )); + } + + #[async_std::test] + async fn select_headers_to_prove_fails_to_use_existing_ancient_relay_block() { + assert_eq!( + select_headers_to_prove((220_u32, 10_u32, 200_u32, 100_u32), 100_u32,) + .await + .map_err(drop), + Ok((true, HeaderId(220, 220), HeaderId(200, 200))), + ); + } + + #[async_std::test] + async fn select_headers_to_prove_is_able_to_use_existing_recent_relay_block() { + assert_eq!( + select_headers_to_prove((40_u32, 10_u32, 200_u32, 100_u32), 100_u32,) + .await + .map_err(drop), + Ok((false, HeaderId(10, 10), HeaderId(100, 100))), + ); + } + + #[async_std::test] + async fn select_headers_to_prove_uses_new_relay_block() { + assert_eq!( + select_headers_to_prove((20_u32, 10_u32, 200_u32, 100_u32), 200_u32,) + .await + .map_err(drop), + Ok((true, HeaderId(20, 20), HeaderId(200, 200))), + ); + } } diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 6b28dcbaa602c..f4f91d50ddd8f 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -109,9 +109,28 @@ pub struct NoncesSubmitArtifacts { pub tx_tracker: T, } +/// Batch transaction that already submit some headers and needs to be extended with +/// messages/delivery proof before sending. +#[async_trait] +pub trait BatchTransaction: Send { + /// Header that was required in the original call and which is bundled within this + /// batch transaction. + fn required_header_id(&self) -> HeaderId; + + /// Append proof and send transaction to the connected node. + async fn append_proof_and_send(self, proof: Proof) -> Result; +} + /// Source client trait. #[async_trait] pub trait SourceClient: RelayClient { + /// Type of batch transaction that submits finality and message receiving proof. + type BatchTransaction: BatchTransaction< + TargetHeaderIdOf

, + P::MessagesReceivingProof, + Self::TransactionTracker, + Self::Error, + >; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -156,12 +175,31 @@ pub trait SourceClient: RelayClient { ) -> Result; /// We need given finalized target header on source to continue synchronization. - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf

); + /// + /// We assume that the absence of header `id` has already been checked by caller. + /// + /// The client may return `Some(_)`, which means that nothing has happened yet and + /// the caller must generate and append message receiving proof to the batch transaction + /// to actually send it (along with required header) to the node. + /// + /// If function has returned `None`, it means that the caller now must wait for the + /// appearance of the target header `id` at the source client. + async fn require_target_header_on_source( + &self, + id: TargetHeaderIdOf

, + ) -> Result, Self::Error>; } /// Target client trait. #[async_trait] pub trait TargetClient: RelayClient { + /// Type of batch transaction that submits finality and messages proof. + type BatchTransaction: BatchTransaction< + SourceHeaderIdOf

, + P::MessagesProof, + Self::TransactionTracker, + Self::Error, + >; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -201,7 +239,17 @@ pub trait TargetClient: RelayClient { ) -> Result, Self::Error>; /// We need given finalized source header on target to continue synchronization. - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf

); + /// + /// The client may return `Some(_)`, which means that nothing has happened yet and + /// the caller must generate and append messages proof to the batch transaction + /// to actually send it (along with required header) to the node. + /// + /// If function has returned `None`, it means that the caller now must wait for the + /// appearance of the source header `id` at the target client. + async fn require_source_header_on_target( + &self, + id: SourceHeaderIdOf

, + ) -> Result, Self::Error>; } /// State of the client. @@ -483,6 +531,61 @@ pub(crate) mod tests { type TargetHeaderHash = TestTargetHeaderHash; } + #[derive(Clone, Debug)] + pub struct TestMessagesBatchTransaction { + data: Arc>, + required_header_id: TestSourceHeaderId, + tx_tracker: TestTransactionTracker, + } + + #[async_trait] + impl BatchTransaction + for TestMessagesBatchTransaction + { + fn required_header_id(&self) -> TestSourceHeaderId { + self.required_header_id + } + + async fn append_proof_and_send( + self, + proof: TestMessagesProof, + ) -> Result { + let mut data = self.data.lock(); + data.receive_messages(proof); + Ok(self.tx_tracker) + } + } + + #[derive(Clone, Debug)] + pub struct TestConfirmationBatchTransaction { + data: Arc>, + required_header_id: TestTargetHeaderId, + tx_tracker: TestTransactionTracker, + } + + #[async_trait] + impl + BatchTransaction< + TestTargetHeaderId, + TestMessagesReceivingProof, + TestTransactionTracker, + TestError, + > for TestConfirmationBatchTransaction + { + fn required_header_id(&self) -> TestTargetHeaderId { + self.required_header_id + } + + async fn append_proof_and_send( + self, + proof: TestMessagesReceivingProof, + ) -> Result { + let mut data = self.data.lock(); + data.receive_messages_delivery_proof(proof); + Ok(self.tx_tracker) + } + } + #[derive(Clone, Debug)] pub struct TestTransactionTracker(TrackedTransactionStatus); @@ -517,8 +620,10 @@ pub(crate) mod tests { target_latest_confirmed_received_nonce: MessageNonce, target_tracked_transaction_status: TrackedTransactionStatus, submitted_messages_proofs: Vec, + target_to_source_batch_transaction: Option, target_to_source_header_required: Option, target_to_source_header_requirements: Vec, + source_to_target_batch_transaction: Option, source_to_target_header_required: Option, source_to_target_header_requirements: Vec, } @@ -546,14 +651,38 @@ pub(crate) mod tests { Default::default(), )), submitted_messages_proofs: Vec::new(), + target_to_source_batch_transaction: None, target_to_source_header_required: None, target_to_source_header_requirements: Vec::new(), + source_to_target_batch_transaction: None, source_to_target_header_required: None, source_to_target_header_requirements: Vec::new(), } } } + impl TestClientData { + fn receive_messages(&mut self, proof: TestMessagesProof) { + self.target_state.best_self = + HeaderId(self.target_state.best_self.0 + 1, self.target_state.best_self.1 + 1); + self.target_state.best_finalized_self = self.target_state.best_self; + self.target_latest_received_nonce = *proof.0.end(); + if let Some(target_latest_confirmed_received_nonce) = proof.1 { + self.target_latest_confirmed_received_nonce = + target_latest_confirmed_received_nonce; + } + self.submitted_messages_proofs.push(proof); + } + + fn receive_messages_delivery_proof(&mut self, proof: TestMessagesReceivingProof) { + self.source_state.best_self = + HeaderId(self.source_state.best_self.0 + 1, self.source_state.best_self.1 + 1); + self.source_state.best_finalized_self = self.source_state.best_self; + self.submitted_messages_receiving_proofs.push(proof); + self.source_latest_confirmed_received_nonce = proof; + } + } + #[derive(Clone)] pub struct TestSourceClient { data: Arc>, @@ -588,6 +717,7 @@ pub(crate) mod tests { #[async_trait] impl SourceClient for TestSourceClient { + type BatchTransaction = TestConfirmationBatchTransaction; type TransactionTracker = TestTransactionTracker; async fn state(&self) -> Result, TestError> { @@ -675,21 +805,25 @@ pub(crate) mod tests { ) -> Result { let mut data = self.data.lock(); (self.tick)(&mut data); - data.source_state.best_self = - HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); - data.source_state.best_finalized_self = data.source_state.best_self; - data.submitted_messages_receiving_proofs.push(proof); - data.source_latest_confirmed_received_nonce = proof; + data.receive_messages_delivery_proof(proof); (self.post_tick)(&mut data); Ok(TestTransactionTracker(data.source_tracked_transaction_status)) } - async fn require_target_header_on_source(&self, id: TargetHeaderIdOf) { + async fn require_target_header_on_source( + &self, + id: TargetHeaderIdOf, + ) -> Result, Self::Error> { let mut data = self.data.lock(); data.target_to_source_header_required = Some(id); data.target_to_source_header_requirements.push(id); (self.tick)(&mut data); (self.post_tick)(&mut data); + + Ok(data.target_to_source_batch_transaction.take().map(|mut tx| { + tx.required_header_id = id; + tx + })) } } @@ -727,6 +861,7 @@ pub(crate) mod tests { #[async_trait] impl TargetClient for TestTargetClient { + type BatchTransaction = TestMessagesBatchTransaction; type TransactionTracker = TestTransactionTracker; async fn state(&self) -> Result, TestError> { @@ -798,15 +933,7 @@ pub(crate) mod tests { if data.is_target_fails { return Err(TestError) } - data.target_state.best_self = - HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); - data.target_state.best_finalized_self = data.target_state.best_self; - data.target_latest_received_nonce = *proof.0.end(); - if let Some(target_latest_confirmed_received_nonce) = proof.1 { - data.target_latest_confirmed_received_nonce = - target_latest_confirmed_received_nonce; - } - data.submitted_messages_proofs.push(proof); + data.receive_messages(proof); (self.post_tick)(&mut data); Ok(NoncesSubmitArtifacts { nonces, @@ -814,17 +941,25 @@ pub(crate) mod tests { }) } - async fn require_source_header_on_target(&self, id: SourceHeaderIdOf) { + async fn require_source_header_on_target( + &self, + id: SourceHeaderIdOf, + ) -> Result, Self::Error> { let mut data = self.data.lock(); data.source_to_target_header_required = Some(id); data.source_to_target_header_requirements.push(id); (self.tick)(&mut data); (self.post_tick)(&mut data); + + Ok(data.source_to_target_batch_transaction.take().map(|mut tx| { + tx.required_header_id = id; + tx + })) } } fn run_loop_test( - data: TestClientData, + data: Arc>, source_tick: Arc, source_post_tick: Arc, target_tick: Arc, @@ -832,8 +967,6 @@ pub(crate) mod tests { exit_signal: impl Future + 'static + Send, ) -> TestClientData { async_std::task::block_on(async { - let data = Arc::new(Mutex::new(data)); - let source_client = TestSourceClient { data: data.clone(), tick: source_tick, @@ -876,7 +1009,7 @@ pub(crate) mod tests { // able to deliver messages. let (exit_sender, exit_receiver) = unbounded(); let result = run_loop_test( - TestClientData { + Arc::new(Mutex::new(TestClientData { is_source_fails: true, source_state: ClientState { best_self: HeaderId(0, 0), @@ -893,7 +1026,7 @@ pub(crate) mod tests { }, target_latest_received_nonce: 0, ..Default::default() - }, + })), Arc::new(|data: &mut TestClientData| { if data.is_source_reconnected { data.is_source_fails = false; @@ -929,7 +1062,7 @@ pub(crate) mod tests { let (source_exit_sender, exit_receiver) = unbounded(); let target_exit_sender = source_exit_sender.clone(); let result = run_loop_test( - TestClientData { + Arc::new(Mutex::new(TestClientData { source_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), @@ -947,7 +1080,7 @@ pub(crate) mod tests { target_latest_received_nonce: 0, target_tracked_transaction_status: TrackedTransactionStatus::Lost, ..Default::default() - }, + })), Arc::new(move |data: &mut TestClientData| { if data.is_source_reconnected { data.source_tracked_transaction_status = @@ -980,7 +1113,7 @@ pub(crate) mod tests { // their corresponding nonce won't be udpated => reconnect will happen let (exit_sender, exit_receiver) = unbounded(); let result = run_loop_test( - TestClientData { + Arc::new(Mutex::new(TestClientData { source_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), @@ -996,7 +1129,7 @@ pub(crate) mod tests { }, target_latest_received_nonce: 0, ..Default::default() - }, + })), Arc::new(move |data: &mut TestClientData| { // blocks are produced on every tick data.source_state.best_self = @@ -1054,7 +1187,7 @@ pub(crate) mod tests { fn message_lane_loop_works() { let (exit_sender, exit_receiver) = unbounded(); let result = run_loop_test( - TestClientData { + Arc::new(Mutex::new(TestClientData { source_state: ClientState { best_self: HeaderId(10, 10), best_finalized_self: HeaderId(10, 10), @@ -1070,7 +1203,7 @@ pub(crate) mod tests { }, target_latest_received_nonce: 0, ..Default::default() - }, + })), Arc::new(|data: &mut TestClientData| { // blocks are produced on every tick data.source_state.best_self = @@ -1133,4 +1266,74 @@ pub(crate) mod tests { assert!(!result.target_to_source_header_requirements.is_empty()); assert!(!result.source_to_target_header_requirements.is_empty()); } + + #[test] + fn message_lane_loop_works_with_batch_transactions() { + let (exit_sender, exit_receiver) = unbounded(); + let original_data = Arc::new(Mutex::new(TestClientData { + source_state: ClientState { + best_self: HeaderId(10, 10), + best_finalized_self: HeaderId(10, 10), + best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + }, + source_latest_generated_nonce: 10, + target_state: ClientState { + best_self: HeaderId(0, 0), + best_finalized_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: HeaderId(0, 0), + actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + }, + target_latest_received_nonce: 0, + ..Default::default() + })); + let target_original_data = original_data.clone(); + let source_original_data = original_data.clone(); + let result = run_loop_test( + original_data, + Arc::new(|_| {}), + Arc::new(move |data: &mut TestClientData| { + if let Some(target_to_source_header_required) = + data.target_to_source_header_required.take() + { + data.target_to_source_batch_transaction = + Some(TestConfirmationBatchTransaction { + data: source_original_data.clone(), + required_header_id: target_to_source_header_required, + tx_tracker: TestTransactionTracker::default(), + }) + } + }), + Arc::new(|_| {}), + Arc::new(move |data: &mut TestClientData| { + if let Some(source_to_target_header_required) = + data.source_to_target_header_required.take() + { + data.source_to_target_batch_transaction = Some(TestMessagesBatchTransaction { + data: target_original_data.clone(), + required_header_id: source_to_target_header_required, + tx_tracker: TestTransactionTracker::default(), + }) + } + + if data.source_latest_confirmed_received_nonce == 10 { + exit_sender.unbounded_send(()).unwrap(); + } + }), + exit_receiver.into_future().map(|(_, _)| ()), + ); + + // there are no strict restrictions on when reward confirmation should come + // (because `max_unconfirmed_nonces_at_target` is `100` in tests and this confirmation + // depends on the state of both clients) + // => we do not check it here + assert_eq!(result.submitted_messages_proofs[0].0, 1..=4); + assert_eq!(result.submitted_messages_proofs[1].0, 5..=8); + assert_eq!(result.submitted_messages_proofs[2].0, 9..=10); + assert!(!result.submitted_messages_receiving_proofs.is_empty()); + + // check that we have at least once required new source->target or target->source headers + assert!(!result.target_to_source_header_requirements.is_empty()); + assert!(!result.source_to_target_header_requirements.is_empty()); + } } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index b49a05dac5cf9..660eb333dce5c 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -171,9 +171,13 @@ where { type Error = C::Error; type TargetNoncesData = DeliveryRaceTargetNoncesData; + type BatchTransaction = C::BatchTransaction; type TransactionTracker = C::TransactionTracker; - async fn require_source_header(&self, id: SourceHeaderIdOf

) { + async fn require_source_header( + &self, + id: SourceHeaderIdOf

, + ) -> Result, Self::Error> { self.client.require_source_header_on_target(id).await } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 4f59b635ae6f2..0da2d3baf7f95 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -20,7 +20,7 @@ //! associated data - like messages, lane state, etc) to the target node by //! generating and submitting proof. -use crate::message_lane_loop::{ClientState, NoncesSubmitArtifacts}; +use crate::message_lane_loop::{BatchTransaction, ClientState, NoncesSubmitArtifacts}; use async_trait::async_trait; use bp_messages::MessageNonce; @@ -127,12 +127,29 @@ pub trait TargetClient { type Error: std::fmt::Debug + MaybeConnectionError; /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; + /// Type of batch transaction that submits finality and proof to the target node. + type BatchTransaction: BatchTransaction< + P::SourceHeaderId, + P::Proof, + Self::TransactionTracker, + Self::Error, + >; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker; /// Ask headers relay to relay finalized headers up to (and including) given header /// from race source to race target. - async fn require_source_header(&self, id: P::SourceHeaderId); + /// + /// The client may return `Some(_)`, which means that nothing has happened yet and + /// the caller must generate and append proof to the batch transaction + /// to actually send it (along with required header) to the node. + /// + /// If function has returned `None`, it means that the caller now must wait for the + /// appearance of the required header `id` at the target client. + async fn require_source_header( + &self, + id: P::SourceHeaderId, + ) -> Result, Self::Error>; /// Return nonces that are known to the target client. async fn nonces( @@ -242,6 +259,7 @@ pub async fn run, TC: TargetClient

>( let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = true; let mut source_nonces_required = false; + let mut source_required_header = None; let source_nonces = futures::future::Fuse::terminated(); let source_generate_proof = futures::future::Fuse::terminated(); let source_go_offline_future = futures::future::Fuse::terminated(); @@ -250,6 +268,8 @@ pub async fn run, TC: TargetClient

>( let mut target_client_is_online = true; let mut target_best_nonces_required = false; let mut target_finalized_nonces_required = false; + let mut target_batch_transaction = None; + let target_require_source_header = futures::future::Fuse::terminated(); let target_best_nonces = futures::future::Fuse::terminated(); let target_finalized_nonces = futures::future::Fuse::terminated(); let target_submit_proof = futures::future::Fuse::terminated(); @@ -262,6 +282,7 @@ pub async fn run, TC: TargetClient

>( source_generate_proof, source_go_offline_future, race_target_updated, + target_require_source_header, target_best_nonces, target_finalized_nonces, target_submit_proof, @@ -326,13 +347,10 @@ pub async fn run, TC: TargetClient

>( ).fail_if_connection_error(FailedClient::Source)?; // ask for more headers if we have nonces to deliver and required headers are missing - let required_source_header_id = race_state + source_required_header = race_state .best_finalized_source_header_id_at_best_target .as_ref() - .and_then(|best|strategy.required_source_header_at_target(best)); - if let Some(required_source_header_id) = required_source_header_id { - race_target.require_source_header(required_source_header_id).await; - } + .and_then(|best| strategy.required_source_header_at_target(best)); }, nonces = target_best_nonces => { target_best_nonces_required = false; @@ -378,6 +396,28 @@ pub async fn run, TC: TargetClient

>( }, // proof generation and submission + maybe_batch_transaction = target_require_source_header => { + source_required_header = None; + + target_client_is_online = process_future_result( + maybe_batch_transaction, + &mut target_retry_backoff, + |maybe_batch_transaction: Option| { + log::debug!( + target: "bridge", + "Target {} client has been asked for more {} headers. Batch tx: {:?}", + P::target_name(), + P::source_name(), + maybe_batch_transaction.is_some(), + ); + + target_batch_transaction = maybe_batch_transaction; + }, + &mut target_go_offline_future, + async_std::task::sleep, + || format!("Error asking for source headers at {}", P::target_name()), + ).fail_if_connection_error(FailedClient::Target)?; + }, proof = source_generate_proof => { source_client_is_online = process_future_result( proof, @@ -409,6 +449,7 @@ pub async fn run, TC: TargetClient

>( P::target_name(), ); + target_batch_transaction = None; race_state.nonces_to_submit = None; race_state.nonces_submitted = Some(artifacts.nonces); target_tx_tracker.set(artifacts.tx_tracker.wait().fuse()); @@ -479,8 +520,23 @@ pub async fn run, TC: TargetClient

>( if source_client_is_online { source_client_is_online = false; + // if we've started to submit batch transaction, let's prioritize it + let expected_race_state = + if let Some(ref target_batch_transaction) = target_batch_transaction { + // when selecting nonces for the batch transaction, we assume that the required + // source header is already at the target chain + let required_source_header_at_target = + target_batch_transaction.required_header_id(); + let mut expected_race_state = race_state.clone(); + expected_race_state.best_finalized_source_header_id_at_best_target = + Some(required_source_header_at_target); + expected_race_state + } else { + race_state.clone() + }; + let nonces_to_deliver = - select_nonces_to_deliver(race_state.clone(), &mut strategy).await; + select_nonces_to_deliver(expected_race_state, &mut strategy).await; let best_at_source = strategy.best_at_source(); if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { @@ -491,6 +547,7 @@ pub async fn run, TC: TargetClient

>( nonces_range, at_block, ); + source_generate_proof.set( race_source.generate_proof(at_block, nonces_range, proof_parameters).fuse(), ); @@ -518,17 +575,45 @@ pub async fn run, TC: TargetClient

>( target_client_is_online = false; if let Some((at_block, nonces_range, proof)) = race_state.nonces_to_submit.as_ref() { - log::debug!( - target: "bridge", - "Going to submit proof of messages in range {:?} to {} node", - nonces_range, - P::target_name(), - ); - target_submit_proof.set( - race_target - .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) - .fuse(), - ); + if let Some(target_batch_transaction) = target_batch_transaction.take() { + log::debug!( + target: "bridge", + "Going to submit batch transaction with header {:?} and proof of messages in range {:?} to {} node", + target_batch_transaction.required_header_id(), + nonces_range, + P::target_name(), + ); + + let nonces = nonces_range.clone(); + target_submit_proof.set( + target_batch_transaction + .append_proof_and_send(proof.clone()) + .map(|result| { + result + .map(|tx_tracker| NoncesSubmitArtifacts { nonces, tx_tracker }) + }) + .left_future() + .fuse(), + ); + } else { + log::debug!( + target: "bridge", + "Going to submit proof of messages in range {:?} to {} node", + nonces_range, + P::target_name(), + ); + + target_submit_proof.set( + race_target + .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) + .right_future() + .fuse(), + ); + } + } else if let Some(source_required_header) = source_required_header.clone() { + log::debug!(target: "bridge", "Going to require {} header {:?} at {}", P::source_name(), source_required_header, P::target_name()); + target_require_source_header + .set(race_target.require_source_header(source_required_header).fuse()); } else if target_best_nonces_required { log::debug!(target: "bridge", "Asking {} about best message nonces", P::target_name()); let at_block = race_state diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index c3d65d0e86a4d..c807d76fe521b 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -155,9 +155,13 @@ where { type Error = C::Error; type TargetNoncesData = (); + type BatchTransaction = C::BatchTransaction; type TransactionTracker = C::TransactionTracker; - async fn require_source_header(&self, id: TargetHeaderIdOf

) { + async fn require_source_header( + &self, + id: TargetHeaderIdOf

, + ) -> Result, Self::Error> { self.client.require_target_header_on_source(id).await } diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 16e1a18bab7d4..428ee33494ca4 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -19,7 +19,7 @@ pub use bp_runtime::HeaderId; pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; -pub use sp_runtime::traits::UniqueSaturatedInto; +pub use sp_runtime::traits::{UniqueSaturatedFrom, UniqueSaturatedInto}; use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; From 630cda1d703b212fddd07136fd515029cffbbb6b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 16 Dec 2022 17:08:35 +0300 Subject: [PATCH 0844/1210] remove BatchDeliveryTransaction::new and BatchConfirmationTransaction::new to avoid expects (#1726) --- .../src/messages_source.rs | 23 ++++++------------- .../src/messages_target.rs | 23 ++++++------------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index e2876b3107ea2..28b5e69410efc 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -367,7 +367,13 @@ where ) -> Result, SubstrateError> { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { if P::SourceBatchCallBuilder::BATCH_CALL_SUPPORTED { - return BatchConfirmationTransaction::

::new(self.clone(), id).await.map(Some) + let (proved_header, prove_calls) = + target_to_source_headers_relay.prove_header(id.0).await?; + return Ok(Some(BatchConfirmationTransaction { + messages_source: self.clone(), + proved_header, + prove_calls, + })) } target_to_source_headers_relay.require_more_headers(id.0).await; @@ -384,21 +390,6 @@ pub struct BatchConfirmationTransaction { prove_calls: Vec>, } -impl BatchConfirmationTransaction

{ - async fn new( - messages_source: SubstrateMessagesSource

, - required_target_header_on_source: TargetHeaderIdOf>, - ) -> Result { - let (proved_header, prove_calls) = messages_source - .target_to_source_headers_relay - .as_ref() - .expect("BatchConfirmationTransaction is only created when target_to_source_headers_relay is Some; qed") - .prove_header(required_target_header_on_source.0) - .await?; - Ok(Self { messages_source, proved_header, prove_calls }) - } -} - #[async_trait] impl BatchTransaction< diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 9d80b9166c855..5e67461ab3076 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -274,7 +274,13 @@ where ) -> Result, SubstrateError> { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { if P::TargetBatchCallBuilder::BATCH_CALL_SUPPORTED { - return BatchDeliveryTransaction::

::new(self.clone(), id).await.map(Some) + let (proved_header, prove_calls) = + source_to_target_headers_relay.prove_header(id.0).await?; + return Ok(Some(BatchDeliveryTransaction { + messages_target: self.clone(), + proved_header, + prove_calls, + })) } source_to_target_headers_relay.require_more_headers(id.0).await; @@ -291,21 +297,6 @@ pub struct BatchDeliveryTransaction { prove_calls: Vec>, } -impl BatchDeliveryTransaction

{ - async fn new( - messages_target: SubstrateMessagesTarget

, - required_source_header_on_target: SourceHeaderIdOf>, - ) -> Result { - let (proved_header, prove_calls) = messages_target - .source_to_target_headers_relay - .as_ref() - .expect("BatchDeliveryTransaction is only created when source_to_target_headers_relay is Some; qed") - .prove_header(required_source_header_on_target.0) - .await?; - Ok(Self { messages_target, proved_header, prove_calls }) - } -} - #[async_trait] impl BatchTransaction< From 27b7c9d05cdee8bd5a906d392afe174c65b3ad7e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Dec 2022 13:54:40 +0300 Subject: [PATCH 0845/1210] more traces + remove signer override (#1727) --- .../src/refund_relayer_extension.rs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index b7c6f71dca170..4f01926508774 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -268,7 +268,18 @@ where Some(CallType::Delivery(extract_messages_state::(call)?)) }; - Ok(parse_call_type().map(|call_type| PreDispatchData { relayer: who.clone(), call_type })) + Ok(parse_call_type() + .map(|call_type| { + log::trace!( + target: "runtime::bridge", + "RefundRelayerForMessagesFromParachain from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", + PID::get(), + LID::get(), + call_type, + ); + PreDispatchData { relayer: who.clone(), call_type } + }) + ) } fn post_dispatch( @@ -340,6 +351,15 @@ where // finally - register reward in relayers pallet RelayersPallet::::register_relayer_reward(LID::get(), &relayer, reward); + log::trace!( + target: "runtime::bridge", + "RefundRelayerForMessagesFromParachain from parachain {} via {:?} has registered {:?} reward: {:?}", + PID::get(), + LID::get(), + relayer, + reward, + ); + Ok(()) } } From c9dfabad1236e503c29f67edda62b41a32dca157 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 19 Dec 2022 14:22:50 +0300 Subject: [PATCH 0846/1210] remove messages pallet owner relay argument (#1728) --- relays/bin-substrate/src/cli/chain_schema.rs | 39 ------------------- .../src/cli/relay_headers_and_messages/mod.rs | 28 ------------- .../parachain_to_parachain.rs | 8 ---- .../relay_to_parachain.rs | 9 ----- .../relay_to_relay.rs | 6 --- relays/lib-substrate-relay/src/lib.rs | 11 ------ 6 files changed, 101 deletions(-) diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 8023fd9b0f7f6..6fc0fac18b230 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -15,7 +15,6 @@ // along with Parity Bridges Common. If not, see . -use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames}; @@ -259,40 +258,6 @@ macro_rules! declare_chain_signing_params_cli_schema { }; } -/// Create chain-specific set of messages pallet owner signing parameters. -#[macro_export] -macro_rules! declare_chain_messages_pallet_owner_signing_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = "Parameters required to sign transaction on behalf of owner of the messages pallet at " $chain "."] - #[derive(StructOpt, Debug, PartialEq, Eq)] - pub struct [<$chain MessagesPalletOwnerSigningParams>] { - #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _messages_pallet_owner>]: Option, - #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _messages_pallet_owner_password>]: Option, - } - - #[allow(dead_code)] - impl [<$chain MessagesPalletOwnerSigningParams>] { - /// Parse signing params into chain-specific KeyPair. - pub fn to_keypair(&self) -> anyhow::Result> { - let [<$chain_prefix _messages_pallet_owner>] = match self.[<$chain_prefix _messages_pallet_owner>] { - Some(ref messages_pallet_owner) => messages_pallet_owner, - None => return Ok(None), - }; - Chain::KeyPair::from_string( - [<$chain_prefix _messages_pallet_owner>], - self.[<$chain_prefix _messages_pallet_owner_password>].as_deref() - ).map_err(|e| anyhow::format_err!("{:?}", e)).map(Some) - } - } - } - }; -} - /// Create chain-specific set of configuration objects: connection parameters, /// signing parameters and bridge initialization parameters. #[macro_export] @@ -301,10 +266,6 @@ macro_rules! declare_chain_cli_schema { $crate::declare_chain_runtime_version_params_cli_schema!($chain, $chain_prefix); $crate::declare_chain_connection_params_cli_schema!($chain, $chain_prefix); $crate::declare_chain_signing_params_cli_schema!($chain, $chain_prefix); - $crate::declare_chain_messages_pallet_owner_signing_params_cli_schema!( - $chain, - $chain_prefix - ); }; } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 1ee7172228c06..1a809a1f483c3 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -125,8 +125,6 @@ pub struct BridgeEndCommonParams { pub sign: AccountKeyPairOf, /// Transactions mortality. pub transactions_mortality: Option, - /// Account that "owns" messages pallet. - pub messages_pallet_owner: Option>, /// Accounts, which balances are exposed as metrics by the relay process. pub accounts: Vec>>, } @@ -500,8 +498,6 @@ mod tests { "9944", "--millau-signer", "//Charlie", - "--millau-messages-pallet-owner", - "//RialtoMessagesOwner", "--millau-transactions-mortality", "64", "--rialto-host", @@ -510,8 +506,6 @@ mod tests { "9944", "--rialto-signer", "//Charlie", - "--rialto-messages-pallet-owner", - "//MillauMessagesOwner", "--rialto-transactions-mortality", "64", "--lane", @@ -555,10 +549,6 @@ mod tests { millau_signer_password_file: None, millau_transactions_mortality: Some(64), }, - left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { - millau_messages_pallet_owner: Some("//RialtoMessagesOwner".into()), - millau_messages_pallet_owner_password: None, - }, left_headers_to_right_sign_override: MillauHeadersToRialtoSigningParams { millau_headers_to_rialto_signer: None, millau_headers_to_rialto_signer_password: None, @@ -583,10 +573,6 @@ mod tests { rialto_signer_password_file: None, rialto_transactions_mortality: Some(64), }, - right_messages_pallet_owner: RialtoMessagesPalletOwnerSigningParams { - rialto_messages_pallet_owner: Some("//MillauMessagesOwner".into()), - rialto_messages_pallet_owner_password: None, - }, right_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { rialto_headers_to_millau_signer: None, rialto_headers_to_millau_signer_password: None, @@ -612,8 +598,6 @@ mod tests { "//Iden", "--rialto-headers-to-millau-signer", "//Ken", - "--millau-messages-pallet-owner", - "//RialtoParachainMessagesOwner", "--millau-transactions-mortality", "64", "--rialto-parachain-host", @@ -622,8 +606,6 @@ mod tests { "9944", "--rialto-parachain-signer", "//George", - "--rialto-parachain-messages-pallet-owner", - "//MillauMessagesOwner", "--rialto-parachain-transactions-mortality", "64", "--rialto-host", @@ -667,10 +649,6 @@ mod tests { millau_signer_password_file: None, millau_transactions_mortality: Some(64), }, - left_messages_pallet_owner: MillauMessagesPalletOwnerSigningParams { - millau_messages_pallet_owner: Some("//RialtoParachainMessagesOwner".into()), - millau_messages_pallet_owner_password: None, - }, left_headers_to_right_sign_override: MillauHeadersToRialtoParachainSigningParams { millau_headers_to_rialto_parachain_signer: None, @@ -696,12 +674,6 @@ mod tests { rialto_parachain_signer_password_file: None, rialto_parachain_transactions_mortality: Some(64), }, - right_messages_pallet_owner: RialtoParachainMessagesPalletOwnerSigningParams { - rialto_parachain_messages_pallet_owner: Some( - "//MillauMessagesOwner".into() - ), - rialto_parachain_messages_pallet_owner_password: None, - }, right_relay_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { rialto_headers_to_millau_signer: Some("//Ken".into()), rialto_headers_to_millau_signer_password: None, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 48fc0fab49b9b..f832722c6b346 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -89,9 +89,6 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_parachain SigningParams>], - // signer used to sign parameter update transactions at the left parachain - #[structopt(flatten)] - left_messages_pallet_owner: [<$left_parachain MessagesPalletOwnerSigningParams>], #[structopt(flatten)] right: [<$right_parachain ConnectionParams>], @@ -101,9 +98,6 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$right_parachain SigningParams>], - // signer used to sign parameter update transactions at the right parachain - #[structopt(flatten)] - right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>], // override for right_relay->left-parachain headers signer #[structopt(flatten)] @@ -142,14 +136,12 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { client: self.left.into_client::().await?, sign: self.left_sign.to_keypair::()?, transactions_mortality: self.left_sign.transactions_mortality()?, - messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, accounts: vec![], }, BridgeEndCommonParams { client: self.right.into_client::().await?, sign: self.right_sign.to_keypair::()?, transactions_mortality: self.right_sign.transactions_mortality()?, - messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, accounts: vec![], }, )?, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index aa4aaf16d70e1..281996534e23f 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -83,9 +83,6 @@ macro_rules! declare_relay_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_chain SigningParams>], - // signer used to sign parameter update transactions at the left chain - #[structopt(flatten)] - left_messages_pallet_owner: [<$left_chain MessagesPalletOwnerSigningParams>], #[structopt(flatten)] right: [<$right_parachain ConnectionParams>], @@ -95,10 +92,6 @@ macro_rules! declare_relay_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$right_parachain SigningParams>], - // signer used to sign parameter update transactions at the left chain - #[structopt(flatten)] - right_messages_pallet_owner: [<$right_parachain MessagesPalletOwnerSigningParams>], - // override for right_relay->left headers signer #[structopt(flatten)] @@ -131,14 +124,12 @@ macro_rules! declare_relay_to_parachain_bridge_schema { client: self.left.into_client::().await?, sign: self.left_sign.to_keypair::()?, transactions_mortality: self.left_sign.transactions_mortality()?, - messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, accounts: vec![], }, BridgeEndCommonParams { client: self.right.into_client::().await?, sign: self.right_sign.to_keypair::()?, transactions_mortality: self.right_sign.transactions_mortality()?, - messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, accounts: vec![], }, )?, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index 625f1e66328d6..a2815bb613916 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -64,8 +64,6 @@ macro_rules! declare_relay_to_relay_bridge_schema { right_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], #[structopt(flatten)] left_sign: [<$left_chain SigningParams>], - #[structopt(flatten)] - left_messages_pallet_owner: [<$left_chain MessagesPalletOwnerSigningParams>], // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right: [<$right_chain ConnectionParams>], @@ -74,8 +72,6 @@ macro_rules! declare_relay_to_relay_bridge_schema { left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_chain SigningParams>], #[structopt(flatten)] right_sign: [<$right_chain SigningParams>], - #[structopt(flatten)] - right_messages_pallet_owner: [<$right_chain MessagesPalletOwnerSigningParams>], } impl [<$left_chain $right_chain HeadersAndMessages>] { @@ -94,14 +90,12 @@ macro_rules! declare_relay_to_relay_bridge_schema { client: self.left.into_client::().await?, sign: self.left_sign.to_keypair::()?, transactions_mortality: self.left_sign.transactions_mortality()?, - messages_pallet_owner: self.left_messages_pallet_owner.to_keypair::()?, accounts: vec![], }, BridgeEndCommonParams { client: self.right.into_client::().await?, sign: self.right_sign.to_keypair::()?, transactions_mortality: self.right_sign.transactions_mortality()?, - messages_pallet_owner: self.right_messages_pallet_owner.to_keypair::()?, accounts: vec![], }, )?, diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 2181f0935836f..4f8f9640305a3 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -63,13 +63,6 @@ pub enum TaggedAccount { /// Name of the bridged chain, which sends us messages or delivery confirmations. bridged_chain: String, }, - /// Account, used to sign messages with-bridged-chain pallet parameters update transactions. - MessagesPalletOwner { - /// Account id. - id: AccountId, - /// Name of the chain, bridged using messages pallet at our chain. - bridged_chain: String, - }, } impl TaggedAccount { @@ -79,7 +72,6 @@ impl TaggedAccount { TaggedAccount::Headers { ref id, .. } => id, TaggedAccount::Parachains { ref id, .. } => id, TaggedAccount::Messages { ref id, .. } => id, - TaggedAccount::MessagesPalletOwner { ref id, .. } => id, } } @@ -93,9 +85,6 @@ impl TaggedAccount { TaggedAccount::Messages { ref bridged_chain, .. } => { format!("{bridged_chain}Messages") }, - TaggedAccount::MessagesPalletOwner { ref bridged_chain, .. } => { - format!("{bridged_chain}MessagesPalletOwner") - }, } } } From 7f7ac926e7e885a2cb576d6b007828bbeebc60ca Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 21 Dec 2022 12:54:05 +0300 Subject: [PATCH 0847/1210] Do not require new headers if lane is empty (#1725) * do not require new headers if lane is empty * handle edge case (need proof-of-delivery-confirmations to be able to submit delivery tx) in required_source_header_at_target * clippy --- relays/messages/src/message_race_delivery.rs | 111 +++++++++++++++---- 1 file changed, 90 insertions(+), 21 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 660eb333dce5c..c551a88a1dd1c 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -318,16 +318,31 @@ where &self, current_best: &SourceHeaderIdOf

, ) -> Option> { + let has_nonces_to_deliver = !self.strategy.is_empty(); let header_required_for_messages_delivery = self.strategy.required_source_header_at_target(current_best); - let header_required_for_reward_confirmations_delivery = - self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone()); + let header_required_for_reward_confirmations_delivery = self + .latest_confirmed_nonces_at_source + .back() + .filter(|(id, nonce)| *nonce != 0 && id.0 > current_best.0) + .map(|(id, _)| id.clone()); match ( + has_nonces_to_deliver, header_required_for_messages_delivery, header_required_for_reward_confirmations_delivery, ) { - (Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }), - (a, b) => a.or(b), + // if we need to delver messages and proof-of-delivery-confirmations, then we need to + // select the most recent header to avoid extra roundtrips + (true, Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }), + // if we only need to deliver messages - fine, let's require some source header + // + // if we need new header for proof-of-delivery-confirmations - let's also ask for that. + // Even though it may require additional header, we'll be sure that we won't block the + // lane (sometimes we can't deliver messages without proof-of-delivery-confirmations) + (true, a, b) => a.or(b), + // we never submit delivery transaction without messages, so if `has_nonces_to_deliver` + // if `false`, we don't need any source headers at target + (false, _, _) => None, } } @@ -926,38 +941,58 @@ mod tests { // - all messages [20; 23] have been generated at source block#1; let (mut state, mut strategy) = prepare_strategy(); // - // - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because - // of unrewarded relayers vector capacity; - strategy.max_unconfirmed_nonces_at_target = 2; + // - messages [20; 23] have been delivered assert_eq!( strategy.select_nonces_to_deliver(state.clone()).await, - Some(((20..=21), proof_parameters(false, 2))) + Some(((20..=23), proof_parameters(false, 4))) ); strategy.finalized_target_nonces_updated( TargetClientNonces { - latest_nonce: 21, + latest_nonce: 23, nonces_data: DeliveryRaceTargetNoncesData { confirmed_nonce: 19, unrewarded_relayers: UnrewardedRelayersState { - unrewarded_relayer_entries: 2, - messages_in_oldest_entry: 2, - total_messages: 2, - last_delivered_nonce: 19, + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 4, + total_messages: 4, + last_delivered_nonce: 23, }, }, }, &mut state, ); - assert_eq!(strategy.select_nonces_to_deliver(state).await, None); - // - // - messages [1; 10] receiving confirmation has been delivered at source block#2; - strategy.source_nonces_updated( - header_id(2), - SourceClientNonces { new_nonces: MessageDetailsMap::new(), confirmed_nonce: Some(21) }, - ); + // nothing needs to be delivered now and we don't need any new headers + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); + assert_eq!(strategy.required_source_header_at_target(&header_id(1)), None); + + // now let's generate two more nonces [24; 25] at the soruce; + strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 19, 0)); // - // - so now we'll need to relay source block#11 to be able to accept messages [11; 20]. + // - so now we'll need to relay source block#2 to be able to accept messages [24; 25]. + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2))); + + // let's relay source block#2 + state.best_finalized_source_header_id_at_source = Some(header_id(2)); + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + state.best_target_header_id = Some(header_id(2)); + state.best_finalized_target_header_id = Some(header_id(2)); + + // and ask strategy again => still nothing to deliver, because parallel confirmations + // race need to be pushed further + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); + assert_eq!(strategy.required_source_header_at_target(&header_id(2)), None); + + // let's confirm messages [20; 23] + strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 23, 0)); + + // and ask strategy again => now we have everything required to deliver remaining + // [24; 25] nonces and proof of [20; 23] confirmation + assert_eq!( + strategy.select_nonces_to_deliver(state).await, + Some(((24..=25), proof_parameters(true, 2))), + ); + assert_eq!(strategy.required_source_header_at_target(&header_id(2)), None); } #[async_std::test] @@ -985,4 +1020,38 @@ mod tests { Some(((20..=24), proof_parameters(false, 5))) ); } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn no_source_headers_required_at_target_if_lanes_are_empty() { + let mut strategy = TestStrategy { + max_unrewarded_relayer_entries_at_target: 4, + max_unconfirmed_nonces_at_target: 4, + max_messages_in_single_batch: 4, + max_messages_weight_in_single_batch: Weight::from_ref_time(4), + max_messages_size_in_single_batch: 4, + latest_confirmed_nonces_at_source: VecDeque::new(), + lane_source_client: TestSourceClient::default(), + lane_target_client: TestTargetClient::default(), + metrics_msg: None, + target_nonces: None, + strategy: BasicStrategy::new(), + }; + + let source_header_id = header_id(10); + strategy.source_nonces_updated( + source_header_id, + // MessageDeliveryRaceSource::nonces returns Some(0), because that's how it is + // represented in memory (there's no Options in OutboundLaneState) + source_nonces(1u64..=0u64, 0, 0), + ); + + // even though `latest_confirmed_nonces_at_source` is not empty, new headers are not + // requested + assert_eq!( + strategy.latest_confirmed_nonces_at_source, + VecDeque::from([(source_header_id, 0)]) + ); + assert_eq!(strategy.required_source_header_at_target(&source_header_id), None); + } } From f4ea091c484e02ba4121798b76a596d3cbde7d63 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 22 Dec 2022 08:53:26 +0300 Subject: [PATCH 0848/1210] Updated db weights and some experiments (#1732) * updated weights * also fix off-by-one in benchmarks --- modules/grandpa/src/weights.rs | 18 +++++------ modules/messages/src/weights.rs | 42 +++++++++++++------------- modules/parachains/src/benchmarking.rs | 7 ++++- modules/parachains/src/weights.rs | 30 ++++++++---------- modules/relayers/src/weights.rs | 6 ++-- 5 files changed, 52 insertions(+), 51 deletions(-) diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 6997713face51..d6c3d596d88eb 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_grandpa` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 +//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -59,10 +59,10 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn submit_finality_proof(p: u32, v: u32) -> Weight { - Weight::from_ref_time(198_274_668 as u64) - .saturating_add(Weight::from_ref_time(39_830_948 as u64).saturating_mul(p as u64)) - .saturating_add(Weight::from_ref_time(1_535_681 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(7 as u64)) + Weight::from_ref_time(192_130_822 as u64) + .saturating_add(Weight::from_ref_time(39_781_096 as u64).saturating_mul(p as u64)) + .saturating_add(Weight::from_ref_time(1_365_108 as u64).saturating_mul(v as u64)) + .saturating_add(T::DbWeight::get().reads(6 as u64)) .saturating_add(T::DbWeight::get().writes(6 as u64)) } } @@ -70,10 +70,10 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { fn submit_finality_proof(p: u32, v: u32) -> Weight { - Weight::from_ref_time(198_274_668 as u64) - .saturating_add(Weight::from_ref_time(39_830_948 as u64).saturating_mul(p as u64)) - .saturating_add(Weight::from_ref_time(1_535_681 as u64).saturating_mul(v as u64)) - .saturating_add(RocksDbWeight::get().reads(7 as u64)) + Weight::from_ref_time(192_130_822 as u64) + .saturating_add(Weight::from_ref_time(39_781_096 as u64).saturating_mul(p as u64)) + .saturating_add(Weight::from_ref_time(1_365_108 as u64).saturating_mul(v as u64)) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) .saturating_add(RocksDbWeight::get().writes(6 as u64)) } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 834e0d1f3d646..69fad6051d5d4 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 +//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -66,87 +66,87 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(50_596_000 as u64) + Weight::from_ref_time(60_148_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(77_041_000 as u64) + Weight::from_ref_time(71_836_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(58_331_000 as u64) + Weight::from_ref_time(66_845_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(48_061_000 as u64) + Weight::from_ref_time(69_696_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(101_601_000 as u64) + Weight::from_ref_time(123_646_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(55_108_000 as u64) + Weight::from_ref_time(53_723_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(53_917_000 as u64) + Weight::from_ref_time(54_617_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(57_335_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + Weight::from_ref_time(53_582_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(50_596_000 as u64) + Weight::from_ref_time(60_148_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(77_041_000 as u64) + Weight::from_ref_time(71_836_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(58_331_000 as u64) + Weight::from_ref_time(66_845_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(48_061_000 as u64) + Weight::from_ref_time(69_696_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(101_601_000 as u64) + Weight::from_ref_time(123_646_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(55_108_000 as u64) + Weight::from_ref_time(53_723_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(53_917_000 as u64) + Weight::from_ref_time(54_617_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(57_335_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + Weight::from_ref_time(53_582_000 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } } diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index 29e48132890a1..b156b724afeb3 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -59,7 +59,12 @@ benchmarks_instance_pallet! { let sender = account("sender", 0, 0); let mut parachains = T::parachains(); - let _ = parachains.split_off(p as usize - 1); + let _ = if p <= parachains.len() as u32 { + parachains.split_off(p as usize) + } else { + Default::default() + }; + log::trace!(target: crate::LOG_TARGET, "=== {:?}", parachains.len()); let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 5c9206d0ca0a8..54f468b7636cf 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_parachains` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-11-17, STEPS: 50, REPEAT: 20 +//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -60,20 +60,18 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { - fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { - Weight::from_ref_time(51_173_000 as u64) - .saturating_add(Weight::from_ref_time(24_495_968 as u64).saturating_mul(p as u64)) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(p as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(p as u64))) + fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { + Weight::from_ref_time(52_445_014 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - Weight::from_ref_time(58_175_000 as u64) + Weight::from_ref_time(55_253_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - Weight::from_ref_time(101_796_000 as u64) + Weight::from_ref_time(98_772_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(3 as u64)) } @@ -81,20 +79,18 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { - fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { - Weight::from_ref_time(51_173_000 as u64) - .saturating_add(Weight::from_ref_time(24_495_968 as u64).saturating_mul(p as u64)) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(p as u64))) - .saturating_add(RocksDbWeight::get().writes((3 as u64).saturating_mul(p as u64))) + fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { + Weight::from_ref_time(52_445_014 as u64) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_1kb_proof() -> Weight { - Weight::from_ref_time(58_175_000 as u64) + Weight::from_ref_time(55_253_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(3 as u64)) } fn submit_parachain_heads_with_16kb_proof() -> Weight { - Weight::from_ref_time(101_796_000 as u64) + Weight::from_ref_time(98_772_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(3 as u64)) } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 26a1cfab1e4d6..9bbaa343e1205 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_relayers` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-12-05, STEPS: 50, REPEAT: 20 +//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -59,7 +59,7 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn claim_rewards() -> Weight { - Weight::from_ref_time(64_065_000 as u64) + Weight::from_ref_time(64_832_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } @@ -68,7 +68,7 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { fn claim_rewards() -> Weight { - Weight::from_ref_time(64_065_000 as u64) + Weight::from_ref_time(64_832_000 as u64) .saturating_add(RocksDbWeight::get().reads(2 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } From 28f0a939b8a9c6e40bf96634880e4b08bea0be52 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 27 Dec 2022 15:39:23 +0200 Subject: [PATCH 0849/1210] Replace `BATCH_CALL_SUPPORTED` (#1733) * Simplify submit_and_watch_signed_extrinsic The way submit_and_watch_signed_extrinsic is used now, we can always derive the SignParam from other params. If in the future we need more customization possibilities, we can define a new method. * Simplify submit_signed_extrinsic * Send maybe_batch_tx as a parameter Send `maybe_batch_tx` as a parameter to `submit_proof()`. This way we can deduplicate the logic that submits the extrinsic for `messages_source and `messages_target` and we can simplify the logic in the race loop a bit. * Define BatchProofTransaction Deduplicate BatchConfirmationTransaction and BatchDeliveryTransaction by replacing both of them with BatchProofTransaction * Define ChainWithUtilityPallet and BatchCallBuilderConstructor - Define `ChainWithUtilityPallet` in order to be able to associate the batching functionality with chains - Defining `BatchCallBuilderConstructor` in order to have a more reliable way of checking whether an end of a messages pipeline supports batching or no. `BatchCallBuilderConstructor::new_builder()` returns an `Option`.This is a bit safer because each time a caller tries to start creating a batch call, it will call `new_builder()` and will be required to handle the returned `Option`. Before we only had a bool `BATCH_CALL_SUPPORTED` the caller could have forgetten to check. --- .../rialto_parachain_messages_to_millau.rs | 4 +- relays/bin-substrate/src/cli/init_bridge.rs | 11 +- .../src/cli/register_parachain.rs | 61 ++------ relays/bin-substrate/src/cli/send_message.rs | 34 ++--- relays/client-millau/src/lib.rs | 8 +- relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/chain.rs | 28 ++++ relays/client-substrate/src/client.rs | 33 +++-- relays/client-substrate/src/lib.rs | 5 +- .../src/finality/initialize.rs | 39 +++-- .../src/finality/target.rs | 14 +- relays/lib-substrate-relay/src/lib.rs | 64 ++++---- .../lib-substrate-relay/src/messages_lane.rs | 57 +++++++- .../src/messages_source.rs | 137 ++++------------- .../src/messages_target.rs | 138 ++++-------------- .../src/parachains/target.rs | 12 +- relays/messages/src/message_lane_loop.rs | 65 ++------- relays/messages/src/message_race_delivery.rs | 5 +- relays/messages/src/message_race_loop.rs | 57 +++----- relays/messages/src/message_race_receiving.rs | 7 +- 20 files changed, 288 insertions(+), 492 deletions(-) diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index 8400157b9d651..74db3738e6b00 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -23,7 +23,7 @@ use substrate_relay_helper::{ DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane, }, - BundledBatchCallBuilder, + UtilityPalletBatchCallBuilder, }; /// Description of RialtoParachain -> Millau messages bridge. @@ -46,5 +46,5 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { >; type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = BundledBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 52a3a6fce5a5b..cadc6be4df23f 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -29,7 +29,7 @@ use crate::{ cli::{bridge::CliBridgeBase, chain_schema::*}, }; use bp_runtime::Chain as ChainBase; -use relay_substrate_client::{AccountKeyPairOf, Chain, SignParam, UnsignedTransaction}; +use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -83,17 +83,10 @@ where let target_sign = data.target_sign.to_keypair::()?; let dry_run = data.dry_run; - let (spec_version, transaction_version) = target_client.simple_runtime_version().await?; substrate_relay_helper::finality::initialize::initialize::( source_client, target_client.clone(), - target_sign.public().into(), - SignParam { - spec_version, - transaction_version, - genesis_hash: *target_client.genesis_hash(), - signer: target_sign, - }, + target_sign, move |transaction_nonce, initialization_data| { let call = Self::encode_init_bridge(initialization_data); log::info!( diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 4febc4b04a8e1..1bc9f941ecf29 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -26,7 +26,7 @@ use polkadot_runtime_common::{ paras_registrar::Call as ParaRegistrarCall, slots::Call as ParaSlotsCall, }; use polkadot_runtime_parachains::paras::ParaLifecycle; -use relay_substrate_client::{AccountIdOf, CallOf, Chain, Client, SignParam, UnsignedTransaction}; +use relay_substrate_client::{AccountIdOf, CallOf, Chain, Client, UnsignedTransaction}; use relay_utils::{TrackedTransactionStatus, TransactionTracker}; use rialto_runtime::SudoCall; use sp_core::{ @@ -108,28 +108,16 @@ impl RegisterParachain { log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id - let relay_genesis_hash = *relay_client.genesis_hash(); let relay_sudo_account: AccountIdOf = relay_sign.public().into(); let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve {}.into(); - let reserve_parachain_signer = relay_sign.clone(); - let (spec_version, transaction_version) = relay_client.simple_runtime_version().await?; let reserve_result = relay_client - .submit_and_watch_signed_extrinsic( - relay_sudo_account.clone(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: reserve_parachain_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - reserve_parachain_id_call.into(), - transaction_nonce, - )) - }, - ) + .submit_and_watch_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { + Ok(UnsignedTransaction::new( + reserve_parachain_id_call.into(), + transaction_nonce, + )) + }) .await? .wait() .await; @@ -162,23 +150,10 @@ impl RegisterParachain { validation_code: ParaValidationCode(para_code), } .into(); - let register_parathread_signer = relay_sign.clone(); let register_result = relay_client - .submit_and_watch_signed_extrinsic( - relay_sudo_account.clone(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: register_parathread_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - register_parathread_call.into(), - transaction_nonce, - )) - }, - ) + .submit_and_watch_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { + Ok(UnsignedTransaction::new(register_parathread_call.into(), transaction_nonce)) + }) .await? .wait() .await; @@ -227,20 +202,10 @@ impl RegisterParachain { ), } .into(); - let force_lease_signer = relay_sign.clone(); relay_client - .submit_signed_extrinsic( - relay_sudo_account, - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: force_lease_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce)) - }, - ) + .submit_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { + Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce)) + }) .await?; log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index d492d3422c706..59a36566c0c6e 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -31,8 +31,7 @@ use crate::{ use async_trait::async_trait; use codec::{Decode, Encode}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, SignParam, - UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, UnsignedTransaction, }; use sp_core::Pair; use sp_runtime::AccountId32; @@ -80,28 +79,17 @@ where data.bridge.bridge_instance_index(), )?; - let source_genesis_hash = *source_client.genesis_hash(); - let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; source_client - .submit_signed_extrinsic( - source_sign.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - }, - move |_, transaction_nonce| { - let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); - log::info!( - target: "bridge", - "Sending message to {}. Size: {}", - Self::Target::NAME, - payload_len, - ); - Ok(unsigned) - }, - ) + .submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| { + let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); + log::info!( + target: "bridge", + "Sending message to {}. Size: {}", + Self::Target::NAME, + payload_len, + ); + Ok(unsigned) + }) .await?; Ok(()) diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 815cd68f39f26..fb901a4b2de39 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, Error as SubstrateError, IndexOf, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + FullRuntimeUtilityPallet, IndexOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -149,6 +149,10 @@ impl ChainWithTransactions for Millau { } } +impl ChainWithUtilityPallet for Millau { + type UtilityPallet = FullRuntimeUtilityPallet; +} + /// Millau signing params. pub type SigningParams = sp_core::sr25519::Pair; diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 3f5156b76532e..29b910c11bd7e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -34,6 +34,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 10e3a4749e092..c199540cbfb31 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -234,3 +234,31 @@ impl BlockWithJustification for SignedBlock self.justifications.as_ref().and_then(|j| j.get(engine_id)) } } + +/// Trait that provides functionality defined inside `pallet-utility` +pub trait UtilityPallet { + /// Create batch call from given calls vector. + fn build_batch_call(calls: Vec) -> C::Call; +} + +/// Structure that implements `UtilityPalletProvider` based on a full runtime. +pub struct FullRuntimeUtilityPallet { + _phantom: std::marker::PhantomData, +} + +impl UtilityPallet for FullRuntimeUtilityPallet +where + C: Chain, + R: pallet_utility::Config, + ::RuntimeCall: From>, +{ + fn build_batch_call(calls: Vec) -> C::Call { + pallet_utility::Call::batch_all { calls }.into() + } +} + +/// Substrate-based chain that uses `pallet-utility`. +pub trait ChainWithUtilityPallet: Chain { + /// The utility pallet provider. + type UtilityPallet: UtilityPallet; +} diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 07293a7e65375..c6387d6bce6f8 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -23,8 +23,8 @@ use crate::{ SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, SubstrateTransactionPaymentClient, }, - transaction_stall_timeout, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, - TransactionTracker, UnsignedTransaction, + transaction_stall_timeout, AccountKeyPairOf, ConnectionParams, Error, HashOf, HeaderIdOf, + Result, SignParam, TransactionTracker, UnsignedTransaction, }; use async_std::sync::{Arc, Mutex}; @@ -43,7 +43,7 @@ use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT}; use sp_core::{ storage::{StorageData, StorageKey}, - Bytes, Hasher, + Bytes, Hasher, Pair, }; use sp_runtime::{ traits::Header as HeaderT, @@ -426,6 +426,19 @@ impl Client { .await } + async fn build_sign_params(&self, signer: AccountKeyPairOf) -> Result> + where + C: ChainWithTransactions, + { + let (spec_version, transaction_version) = self.simple_runtime_version().await?; + Ok(SignParam:: { + spec_version, + transaction_version, + genesis_hash: self.genesis_hash, + signer, + }) + } + /// Submit an extrinsic signed by given account. /// /// All calls of this method are synchronized, so there can't be more than one active @@ -435,18 +448,19 @@ impl Client { /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_signed_extrinsic( &self, - extrinsic_signer: C::AccountId, - signing_data: SignParam, + signer: &AccountKeyPairOf, prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, ) -> Result where C: ChainWithTransactions, + C::AccountId: From<::Public>, { let _guard = self.submit_signed_extrinsic_lock.lock().await; - let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let transaction_nonce = self.next_account_index(signer.public().into()).await?; let best_header = self.best_header().await?; + let signing_data = self.build_sign_params(signer.clone()).await?; // By using parent of best block here, we are protecing again best-block reorganizations. // E.g. transaction may have been submitted when the best block was `A[num=100]`. Then it @@ -475,18 +489,19 @@ impl Client { /// after submission. pub async fn submit_and_watch_signed_extrinsic( &self, - extrinsic_signer: C::AccountId, - signing_data: SignParam, + signer: &AccountKeyPairOf, prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, ) -> Result> where C: ChainWithTransactions, + C::AccountId: From<::Public>, { let self_clone = self.clone(); + let signing_data = self.build_sign_params(signer.clone()).await?; let _guard = self.submit_signed_extrinsic_lock.lock().await; - let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let transaction_nonce = self.next_account_index(signer.public().into()).await?; let best_header = self.best_header().await?; let best_header_id = best_header.id(); let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index dc90737523144..e576aca1119d8 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -34,8 +34,9 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, Parachain, RelayChain, - SignParam, TransactionStatusOf, UnsignedTransaction, + ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + FullRuntimeUtilityPallet, Parachain, RelayChain, SignParam, TransactionStatusOf, + UnsignedTransaction, UtilityPallet, }, client::{ ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription, diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index 938f1330b2ead..b5f9b322c7cef 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -22,9 +22,11 @@ //! with this header. use crate::{error::Error, finality::engine::Engine}; +use sp_core::Pair; use relay_substrate_client::{ - Chain, ChainWithTransactions, Client, Error as SubstrateError, SignParam, UnsignedTransaction, + AccountKeyPairOf, Chain, ChainWithTransactions, Client, Error as SubstrateError, + UnsignedTransaction, }; use sp_runtime::traits::Header as HeaderT; @@ -37,8 +39,7 @@ pub async fn initialize< >( source_client: Client, target_client: Client, - target_transactions_signer: TargetChain::AccountId, - target_signing_data: SignParam, + target_signer: AccountKeyPairOf, prepare_initialize_transaction: F, dry_run: bool, ) where @@ -48,12 +49,12 @@ pub async fn initialize< ) -> Result, SubstrateError> + Send + 'static, + TargetChain::AccountId: From<::Public>, { let result = do_initialize::( source_client, target_client, - target_transactions_signer, - target_signing_data, + target_signer, prepare_initialize_transaction, dry_run, ) @@ -87,8 +88,7 @@ async fn do_initialize< >( source_client: Client, target_client: Client, - target_transactions_signer: TargetChain::AccountId, - target_signing_data: SignParam, + target_signer: AccountKeyPairOf, prepare_initialize_transaction: F, dry_run: bool, ) -> Result< @@ -102,6 +102,7 @@ where ) -> Result, SubstrateError> + Send + 'static, + TargetChain::AccountId: From<::Public>, { let is_initialized = E::is_initialized(&target_client) .await @@ -128,20 +129,16 @@ where ); let initialization_tx_hash = target_client - .submit_signed_extrinsic( - target_transactions_signer, - target_signing_data, - move |_, transaction_nonce| { - let tx = prepare_initialize_transaction(transaction_nonce, initialization_data); - if dry_run { - Err(SubstrateError::Custom( - "Not submitting extrinsic in `dry-run` mode!".to_string(), - )) - } else { - tx - } - }, - ) + .submit_signed_extrinsic(&target_signer, move |_, transaction_nonce| { + let tx = prepare_initialize_transaction(transaction_nonce, initialization_data); + if dry_run { + Err(SubstrateError::Custom( + "Not submitting extrinsic in `dry-run` mode!".to_string(), + )) + } else { + tx + } + }) .await .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 09d9ad15f5436..c255c07d148e0 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -27,8 +27,8 @@ use crate::{ use async_trait::async_trait; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, - SyncHeader, TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SyncHeader, + TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -111,20 +111,12 @@ where header: SyncHeader>, proof: SubstrateFinalityProof

, ) -> Result { - let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer.clone(), - }, + &self.transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(call.into(), transaction_nonce) .era(TransactionEra::new(best_block_id, transaction_params.mortality))) diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 4f8f9640305a3..28c538b309a0b 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -18,7 +18,8 @@ #![warn(missing_docs)] -use relay_substrate_client::Error as SubstrateError; +use relay_substrate_client::{Chain, ChainWithUtilityPallet, UtilityPallet}; + use std::marker::PhantomData; pub mod error; @@ -90,50 +91,41 @@ impl TaggedAccount { } /// Batch call builder. -pub trait BatchCallBuilder { - /// Associated error type. - type Error; - /// If `true`, then batch calls are supported at the chain. - const BATCH_CALL_SUPPORTED: bool; - +pub trait BatchCallBuilder: Send { /// Create batch call from given calls vector. - fn build_batch_call(_calls: Vec) -> Result; + fn build_batch_call(&self, _calls: Vec) -> Call; } -impl BatchCallBuilder for () { - type Error = SubstrateError; - const BATCH_CALL_SUPPORTED: bool = false; +/// Batch call builder constructor. +pub trait BatchCallBuilderConstructor { + /// Create a new instance of a batch call builder. + fn new_builder() -> Option>>; +} - fn build_batch_call(_calls: Vec) -> Result { - debug_assert!( - false, - "only called if `BATCH_CALL_SUPPORTED` is true;\ - `BATCH_CALL_SUPPORTED` is false;\ - qed" - ); +/// Batch call builder based on `pallet-utility`. +pub struct UtilityPalletBatchCallBuilder(PhantomData); - Err(SubstrateError::Custom("<() as BatchCallBuilder>::build_batch_call() is called".into())) +impl BatchCallBuilder for UtilityPalletBatchCallBuilder +where + C: ChainWithUtilityPallet, +{ + fn build_batch_call(&self, calls: Vec) -> C::Call { + C::UtilityPallet::build_batch_call(calls) } } -/// Batch call builder for bundled runtimes. -pub struct BundledBatchCallBuilder(PhantomData); - -impl BatchCallBuilder<::RuntimeCall> for BundledBatchCallBuilder +impl BatchCallBuilderConstructor for UtilityPalletBatchCallBuilder where - R: pallet_utility::Config::RuntimeCall>, - ::RuntimeCall: From>, + C: ChainWithUtilityPallet, { - type Error = SubstrateError; - const BATCH_CALL_SUPPORTED: bool = true; - - fn build_batch_call( - mut calls: Vec<::RuntimeCall>, - ) -> Result<::RuntimeCall, SubstrateError> { - Ok(if calls.len() == 1 { - calls.remove(0) - } else { - pallet_utility::Call::batch_all { calls }.into() - }) + fn new_builder() -> Option>> { + Some(Box::new(Self(Default::default()))) + } +} + +/// A `BatchCallBuilderConstructor` that always returns `None`. +impl BatchCallBuilderConstructor for () { + fn new_builder() -> Option>> { + None } } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 8ec78d0ae2cb8..22ff3e7215b68 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -20,18 +20,18 @@ use crate::{ messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand::OnDemandRelay, - BatchCallBuilder, TransactionParams, + BatchCallBuilder, BatchCallBuilderConstructor, TransactionParams, }; use async_std::sync::Arc; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, Chain as _, WeightExtraOps}; +use bp_runtime::{AccountIdOf, Chain as _, HeaderIdOf, WeightExtraOps}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, message_lane_loop::BatchTransaction}; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, @@ -57,9 +57,9 @@ pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; /// How batch calls are built at the source chain? - type SourceBatchCallBuilder: BatchCallBuilder, Error = SubstrateError>; + type SourceBatchCallBuilder: BatchCallBuilderConstructor>; /// How batch calls are built at the target chain? - type TargetBatchCallBuilder: BatchCallBuilder, Error = SubstrateError>; + type TargetBatchCallBuilder: BatchCallBuilderConstructor>; } /// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. @@ -105,6 +105,53 @@ pub struct MessagesRelayParams { pub metrics_params: MetricsParams, } +/// Batch transaction that brings headers + and messages delivery/receiving confirmations to the +/// source node. +pub struct BatchProofTransaction>> { + builder: Box>>, + proved_header: HeaderIdOf, + prove_calls: Vec>, + + /// Using `fn() -> B` in order to avoid implementing `Send` for `B`. + _phantom: PhantomData B>, +} + +impl>> + BatchProofTransaction +{ + /// Creates a new instance of `BatchProofTransaction`. + pub async fn new( + relay: Arc>, + block_num: BlockNumberOf, + ) -> Result, SubstrateError> { + if let Some(builder) = B::new_builder() { + let (proved_header, prove_calls) = relay.prove_header(block_num).await?; + return Ok(Some(Self { + builder, + proved_header, + prove_calls, + _phantom: Default::default(), + })) + } + + Ok(None) + } + + /// Return a batch call that includes the provided call. + pub fn append_call_and_build(mut self, call: CallOf) -> CallOf { + self.prove_calls.push(call); + self.builder.build_batch_call(self.prove_calls) + } +} + +impl>> + BatchTransaction> for BatchProofTransaction +{ + fn required_header_id(&self) -> HeaderIdOf { + self.proved_header + } +} + /// Run Substrate-to-Substrate messages sync loop. pub async fn run(params: MessagesRelayParams

) -> anyhow::Result<()> where diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 28b5e69410efc..0e4a2caa258a4 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -20,11 +20,11 @@ use crate::{ messages_lane::{ - MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, + BatchProofTransaction, MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, + SubstrateMessageLane, }, - messages_target::SubstrateMessagesDeliveryProof, on_demand::OnDemandRelay, - BatchCallBuilder, TransactionParams, + TransactionParams, }; use async_std::sync::Arc; @@ -41,15 +41,15 @@ use frame_support::weights::Weight; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - BatchTransaction, ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, - SourceClient, SourceClientState, + ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, + SourceClientState, }, }; use num_traits::Zero; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, - Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, TransactionEra, TransactionTracker, + UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -140,7 +140,8 @@ impl SourceClient> for SubstrateM where AccountIdOf: From< as Pair>::Public>, { - type BatchTransaction = BatchConfirmationTransaction

; + type BatchTransaction = + BatchProofTransaction; type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { @@ -332,30 +333,27 @@ where async fn submit_messages_receiving_proof( &self, + maybe_batch_tx: Option, _generated_at_block: TargetHeaderIdOf>, proof: as MessageLane>::MessagesReceivingProof, ) -> Result { - let genesis_hash = *self.source_client.genesis_hash(); + let messages_proof_call = + P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( + proof, + maybe_batch_tx.is_none(), + ); + let final_call = match maybe_batch_tx { + Some(batch_tx) => batch_tx.append_call_and_build(messages_proof_call), + None => messages_proof_call, + }; + let transaction_params = self.transaction_params.clone(); - let (spec_version, transaction_version) = - self.source_client.simple_runtime_version().await?; self.source_client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: self.transaction_params.signer.clone(), - }, + &self.transaction_params.signer, move |best_block_id, transaction_nonce| { - make_messages_delivery_proof_transaction::

( - &transaction_params, - best_block_id, - transaction_nonce, - proof, - true, - ) + Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) }, ) .await @@ -366,14 +364,10 @@ where id: TargetHeaderIdOf>, ) -> Result, SubstrateError> { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { - if P::SourceBatchCallBuilder::BATCH_CALL_SUPPORTED { - let (proved_header, prove_calls) = - target_to_source_headers_relay.prove_header(id.0).await?; - return Ok(Some(BatchConfirmationTransaction { - messages_source: self.clone(), - proved_header, - prove_calls, - })) + if let Some(batch_tx) = + BatchProofTransaction::new(target_to_source_headers_relay.clone(), id.0).await? + { + return Ok(Some(batch_tx)) } target_to_source_headers_relay.require_more_headers(id.0).await; @@ -383,65 +377,6 @@ where } } -/// Batch transaction that brings target headers + and delivery confirmations to the source node. -pub struct BatchConfirmationTransaction { - messages_source: SubstrateMessagesSource

, - proved_header: TargetHeaderIdOf>, - prove_calls: Vec>, -} - -#[async_trait] -impl - BatchTransaction< - TargetHeaderIdOf>, - as MessageLane>::MessagesReceivingProof, - TransactionTracker>, - SubstrateError, - > for BatchConfirmationTransaction

-where - AccountIdOf: From< as Pair>::Public>, -{ - fn required_header_id(&self) -> TargetHeaderIdOf> { - self.proved_header - } - - async fn append_proof_and_send( - self, - proof: as MessageLane>::MessagesReceivingProof, - ) -> Result>, SubstrateError> { - let mut calls = self.prove_calls; - calls.push( - P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( - proof, false, - ), - ); - let batch_call = P::SourceBatchCallBuilder::build_batch_call(calls)?; - - let (spec_version, transaction_version) = - self.messages_source.source_client.simple_runtime_version().await?; - self.messages_source - .source_client - .submit_and_watch_signed_extrinsic( - self.messages_source.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: *self.messages_source.source_client.genesis_hash(), - signer: self.messages_source.transaction_params.signer.clone(), - }, - move |best_block_id, transaction_nonce| { - Ok(UnsignedTransaction::new(batch_call.into(), transaction_nonce).era( - TransactionEra::new( - best_block_id, - self.messages_source.transaction_params.mortality, - ), - )) - }, - ) - .await - } -} - /// Ensure that the messages pallet at source chain is active. pub(crate) async fn ensure_messages_pallet_active( client: &Client, @@ -462,22 +397,6 @@ where } } -/// Make messages delivery proof transaction from given proof. -fn make_messages_delivery_proof_transaction( - source_transaction_params: &TransactionParams>, - source_best_block_id: HeaderIdOf, - transaction_nonce: IndexOf, - proof: SubstrateMessagesDeliveryProof, - trace_call: bool, -) -> Result, SubstrateError> { - let call = - P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( - proof, trace_call, - ); - Ok(UnsignedTransaction::new(call.into(), transaction_nonce) - .era(TransactionEra::new(source_best_block_id, source_transaction_params.mortality))) -} - /// Read best blocks from given client. /// /// This function assumes that the chain that is followed by the `self_client` has diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 5e67461ab3076..679f9fc140803 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -19,10 +19,13 @@ //! chain. use crate::{ - messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, + messages_lane::{ + BatchProofTransaction, MessageLaneAdapter, ReceiveMessagesProofCallBuilder, + SubstrateMessageLane, + }, messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, on_demand::OnDemandRelay, - BatchCallBuilder, TransactionParams, + TransactionParams, }; use async_std::sync::Arc; @@ -34,12 +37,11 @@ use bp_messages::{ use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{BatchTransaction, NoncesSubmitArtifacts, TargetClient, TargetClientState}, + message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionTracker, UnsignedTransaction, + Error as SubstrateError, HashOf, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -132,7 +134,8 @@ where AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, { - type BatchTransaction = BatchDeliveryTransaction

; + type BatchTransaction = + BatchProofTransaction; type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { @@ -232,36 +235,30 @@ where async fn submit_messages_proof( &self, + maybe_batch_tx: Option, _generated_at_header: SourceHeaderIdOf>, nonces: RangeInclusive, proof: as MessageLane>::MessagesProof, ) -> Result, SubstrateError> { - let genesis_hash = *self.target_client.genesis_hash(); + let messages_proof_call = make_messages_delivery_call::

( + self.relayer_id_at_source.clone(), + proof.1.nonces_start..=proof.1.nonces_end, + proof, + maybe_batch_tx.is_none(), + ); + let final_call = match maybe_batch_tx { + Some(batch_tx) => batch_tx.append_call_and_build(messages_proof_call), + None => messages_proof_call, + }; + let transaction_params = self.transaction_params.clone(); - let relayer_id_at_source = self.relayer_id_at_source.clone(); - let nonces_clone = nonces.clone(); - let (spec_version, transaction_version) = - self.target_client.simple_runtime_version().await?; let tx_tracker = self .target_client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: self.transaction_params.signer.clone(), - }, + &self.transaction_params.signer, move |best_block_id, transaction_nonce| { - make_messages_delivery_transaction::

( - &transaction_params, - best_block_id, - transaction_nonce, - relayer_id_at_source, - nonces_clone, - proof, - true, - ) + Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) }, ) .await?; @@ -273,14 +270,10 @@ where id: SourceHeaderIdOf>, ) -> Result, SubstrateError> { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { - if P::TargetBatchCallBuilder::BATCH_CALL_SUPPORTED { - let (proved_header, prove_calls) = - source_to_target_headers_relay.prove_header(id.0).await?; - return Ok(Some(BatchDeliveryTransaction { - messages_target: self.clone(), - proved_header, - prove_calls, - })) + if let Some(batch_tx) = + BatchProofTransaction::new(source_to_target_headers_relay.clone(), id.0).await? + { + return Ok(Some(batch_tx)) } source_to_target_headers_relay.require_more_headers(id.0).await; @@ -290,66 +283,6 @@ where } } -/// Batch transaction that brings target headers + and delivery confirmations to the source node. -pub struct BatchDeliveryTransaction { - messages_target: SubstrateMessagesTarget

, - proved_header: SourceHeaderIdOf>, - prove_calls: Vec>, -} - -#[async_trait] -impl - BatchTransaction< - SourceHeaderIdOf>, - as MessageLane>::MessagesProof, - TransactionTracker>, - SubstrateError, - > for BatchDeliveryTransaction

-where - AccountIdOf: From< as Pair>::Public>, -{ - fn required_header_id(&self) -> SourceHeaderIdOf> { - self.proved_header - } - - async fn append_proof_and_send( - self, - proof: as MessageLane>::MessagesProof, - ) -> Result>, SubstrateError> { - let mut calls = self.prove_calls; - calls.push(make_messages_delivery_call::

( - self.messages_target.relayer_id_at_source, - proof.1.nonces_start..=proof.1.nonces_end, - proof, - false, - )); - let batch_call = P::TargetBatchCallBuilder::build_batch_call(calls)?; - - let (spec_version, transaction_version) = - self.messages_target.target_client.simple_runtime_version().await?; - self.messages_target - .target_client - .submit_and_watch_signed_extrinsic( - self.messages_target.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: *self.messages_target.target_client.genesis_hash(), - signer: self.messages_target.transaction_params.signer.clone(), - }, - move |best_block_id, transaction_nonce| { - Ok(UnsignedTransaction::new(batch_call.into(), transaction_nonce).era( - TransactionEra::new( - best_block_id, - self.messages_target.transaction_params.mortality, - ), - )) - }, - ) - .await - } -} - /// Make messages delivery call from given proof. fn make_messages_delivery_call( relayer_id_at_source: AccountIdOf, @@ -367,18 +300,3 @@ fn make_messages_delivery_call( trace_call, ) } - -/// Make messages delivery transaction from given proof. -fn make_messages_delivery_transaction( - target_transaction_params: &TransactionParams>, - target_best_block_id: HeaderIdOf, - transaction_nonce: IndexOf, - relayer_id_at_source: AccountIdOf, - nonces: RangeInclusive, - proof: SubstrateMessagesProof, - trace_call: bool, -) -> Result, SubstrateError> { - let call = make_messages_delivery_call::

(relayer_id_at_source, nonces, proof, trace_call); - Ok(UnsignedTransaction::new(call.into(), transaction_nonce) - .era(TransactionEra::new(target_best_block_id, target_transaction_params.mortality))) -} diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 027a6b7522231..5e765f10ff550 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -33,7 +33,7 @@ use parachains_relay::{ }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, RelayChain, SignParam, TransactionEra, TransactionTracker, UnsignedTransaction, + HeaderIdOf, RelayChain, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -172,9 +172,7 @@ where updated_parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, ) -> Result { - let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( at_relay_block, updated_parachains, @@ -182,13 +180,7 @@ where ); self.client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer, - }, + &transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(call.into(), transaction_nonce) .era(TransactionEra::new(best_block_id, transaction_params.mortality))) diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index f4f91d50ddd8f..521baabb195f8 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -111,26 +111,17 @@ pub struct NoncesSubmitArtifacts { /// Batch transaction that already submit some headers and needs to be extended with /// messages/delivery proof before sending. -#[async_trait] -pub trait BatchTransaction: Send { +pub trait BatchTransaction: Send { /// Header that was required in the original call and which is bundled within this /// batch transaction. fn required_header_id(&self) -> HeaderId; - - /// Append proof and send transaction to the connected node. - async fn append_proof_and_send(self, proof: Proof) -> Result; } /// Source client trait. #[async_trait] pub trait SourceClient: RelayClient { /// Type of batch transaction that submits finality and message receiving proof. - type BatchTransaction: BatchTransaction< - TargetHeaderIdOf

, - P::MessagesReceivingProof, - Self::TransactionTracker, - Self::Error, - >; + type BatchTransaction: BatchTransaction>; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -170,6 +161,7 @@ pub trait SourceClient: RelayClient { /// Submit messages receiving proof. async fn submit_messages_receiving_proof( &self, + maybe_batch_tx: Option, generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, ) -> Result; @@ -194,12 +186,7 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Type of batch transaction that submits finality and messages proof. - type BatchTransaction: BatchTransaction< - SourceHeaderIdOf

, - P::MessagesProof, - Self::TransactionTracker, - Self::Error, - >; + type BatchTransaction: BatchTransaction>; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -233,6 +220,7 @@ pub trait TargetClient: RelayClient { /// Submit messages proof. async fn submit_messages_proof( &self, + maybe_batch_tx: Option, generated_at_header: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, @@ -533,57 +521,26 @@ pub(crate) mod tests { #[derive(Clone, Debug)] pub struct TestMessagesBatchTransaction { - data: Arc>, required_header_id: TestSourceHeaderId, - tx_tracker: TestTransactionTracker, } #[async_trait] - impl BatchTransaction - for TestMessagesBatchTransaction - { + impl BatchTransaction for TestMessagesBatchTransaction { fn required_header_id(&self) -> TestSourceHeaderId { self.required_header_id } - - async fn append_proof_and_send( - self, - proof: TestMessagesProof, - ) -> Result { - let mut data = self.data.lock(); - data.receive_messages(proof); - Ok(self.tx_tracker) - } } #[derive(Clone, Debug)] pub struct TestConfirmationBatchTransaction { - data: Arc>, required_header_id: TestTargetHeaderId, - tx_tracker: TestTransactionTracker, } #[async_trait] - impl - BatchTransaction< - TestTargetHeaderId, - TestMessagesReceivingProof, - TestTransactionTracker, - TestError, - > for TestConfirmationBatchTransaction - { + impl BatchTransaction for TestConfirmationBatchTransaction { fn required_header_id(&self) -> TestTargetHeaderId { self.required_header_id } - - async fn append_proof_and_send( - self, - proof: TestMessagesReceivingProof, - ) -> Result { - let mut data = self.data.lock(); - data.receive_messages_delivery_proof(proof); - Ok(self.tx_tracker) - } } #[derive(Clone, Debug)] @@ -800,6 +757,7 @@ pub(crate) mod tests { async fn submit_messages_receiving_proof( &self, + _maybe_batch_tx: Option, _generated_at_block: TargetHeaderIdOf, proof: TestMessagesReceivingProof, ) -> Result { @@ -924,6 +882,7 @@ pub(crate) mod tests { async fn submit_messages_proof( &self, + _maybe_batch_tx: Option, _generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: TestMessagesProof, @@ -1287,8 +1246,6 @@ pub(crate) mod tests { target_latest_received_nonce: 0, ..Default::default() })); - let target_original_data = original_data.clone(); - let source_original_data = original_data.clone(); let result = run_loop_test( original_data, Arc::new(|_| {}), @@ -1298,9 +1255,7 @@ pub(crate) mod tests { { data.target_to_source_batch_transaction = Some(TestConfirmationBatchTransaction { - data: source_original_data.clone(), required_header_id: target_to_source_header_required, - tx_tracker: TestTransactionTracker::default(), }) } }), @@ -1310,9 +1265,7 @@ pub(crate) mod tests { data.source_to_target_header_required.take() { data.source_to_target_batch_transaction = Some(TestMessagesBatchTransaction { - data: target_original_data.clone(), required_header_id: source_to_target_header_required, - tx_tracker: TestTransactionTracker::default(), }) } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index c551a88a1dd1c..0179a696bc7ff 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -214,11 +214,14 @@ where async fn submit_proof( &self, + maybe_batch_tx: Option, generated_at_block: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result, Self::Error> { - self.client.submit_messages_proof(generated_at_block, nonces, proof).await + self.client + .submit_messages_proof(maybe_batch_tx, generated_at_block, nonces, proof) + .await } } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 0da2d3baf7f95..deac71e5b6efe 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -128,12 +128,7 @@ pub trait TargetClient { /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; /// Type of batch transaction that submits finality and proof to the target node. - type BatchTransaction: BatchTransaction< - P::SourceHeaderId, - P::Proof, - Self::TransactionTracker, - Self::Error, - >; + type BatchTransaction: BatchTransaction; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker; @@ -160,6 +155,7 @@ pub trait TargetClient { /// Submit proof to the target client. async fn submit_proof( &self, + maybe_batch_tx: Option, generated_at_block: P::SourceHeaderId, nonces: RangeInclusive, proof: P::Proof, @@ -575,41 +571,30 @@ pub async fn run, TC: TargetClient

>( target_client_is_online = false; if let Some((at_block, nonces_range, proof)) = race_state.nonces_to_submit.as_ref() { - if let Some(target_batch_transaction) = target_batch_transaction.take() { + log::debug!( + target: "bridge", + "Going to submit proof of messages in range {:?} to {} node", + nonces_range, + P::target_name(), + ); + if let Some(ref target_batch_transaction) = target_batch_transaction { log::debug!( target: "bridge", - "Going to submit batch transaction with header {:?} and proof of messages in range {:?} to {} node", + "This transaction is batched with sending the proof for header {:?}.", target_batch_transaction.required_header_id(), - nonces_range, - P::target_name(), - ); - - let nonces = nonces_range.clone(); - target_submit_proof.set( - target_batch_transaction - .append_proof_and_send(proof.clone()) - .map(|result| { - result - .map(|tx_tracker| NoncesSubmitArtifacts { nonces, tx_tracker }) - }) - .left_future() - .fuse(), - ); - } else { - log::debug!( - target: "bridge", - "Going to submit proof of messages in range {:?} to {} node", - nonces_range, - P::target_name(), - ); - - target_submit_proof.set( - race_target - .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) - .right_future() - .fuse(), ); } + + target_submit_proof.set( + race_target + .submit_proof( + target_batch_transaction.take(), + at_block.clone(), + nonces_range.clone(), + proof.clone(), + ) + .fuse(), + ); } else if let Some(source_required_header) = source_required_header.clone() { log::debug!(target: "bridge", "Going to require {} header {:?} at {}", P::source_name(), source_required_header, P::target_name()); target_require_source_header diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index c807d76fe521b..70a3d7c24772a 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -182,12 +182,15 @@ where async fn submit_proof( &self, + maybe_batch_tx: Option, generated_at_block: TargetHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesReceivingProof, ) -> Result, Self::Error> { - let tx_tracker = - self.client.submit_messages_receiving_proof(generated_at_block, proof).await?; + let tx_tracker = self + .client + .submit_messages_receiving_proof(maybe_batch_tx, generated_at_block, proof) + .await?; Ok(NoncesSubmitArtifacts { nonces, tx_tracker }) } } From c9a84a8124090947cd44ed42020fc4bd666021a2 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 28 Dec 2022 15:47:09 +0200 Subject: [PATCH 0850/1210] Handle `SIGTERM` for the docker containers + relay (#1735) * Handle SIGTERM for some docker containers * Implement SIGTERM handling for the relay --- relays/bin-substrate/Cargo.toml | 2 ++ relays/bin-substrate/src/cli/mod.rs | 36 +++++++++++++++++++++++++++-- relays/bin-substrate/src/main.rs | 5 +--- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 9ae6a98868e39..de1807cdc9708 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -16,6 +16,8 @@ log = "0.4.17" num-format = "0.4" num-traits = "0.2" structopt = "0.3" +signal-hook = "0.3.14" +signal-hook-async-std = "0.2.2" strum = { version = "0.21.0", features = ["derive"] } # Bridge dependencies diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 5733aa411d8e7..4bd735c6334ad 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -18,7 +18,11 @@ use std::convert::TryInto; +use async_std::prelude::*; use codec::{Decode, Encode}; +use futures::{select, FutureExt}; +use signal_hook::consts::*; +use signal_hook_async_std::Signals; use structopt::{clap::arg_enum, StructOpt}; use strum::{EnumString, EnumVariantNames}; @@ -37,6 +41,9 @@ mod relay_messages; mod relay_parachains; mod resubmit_transactions; +/// The target that will be used when publishing logs related to this pallet. +pub const LOG_TARGET: &str = "bridge"; + /// Parse relay CLI args. pub fn parse_args() -> Command { Command::from_args() @@ -100,8 +107,7 @@ impl Command { } /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - self.init_logger(); + async fn do_run(self) -> anyhow::Result<()> { match self { Self::RelayHeaders(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?, @@ -114,6 +120,32 @@ impl Command { } Ok(()) } + + /// Run the command. + pub async fn run(self) { + self.init_logger(); + + let exit_signals = match Signals::new([SIGINT, SIGTERM]) { + Ok(signals) => signals, + Err(e) => { + log::error!(target: LOG_TARGET, "Could not register exit signals: {}", e); + return + }, + }; + let run = self.do_run().fuse(); + futures::pin_mut!(exit_signals, run); + + select! { + signal = exit_signals.next().fuse() => { + log::info!(target: LOG_TARGET, "Received exit signal {:?}", signal); + }, + result = run => { + if let Err(e) = result { + log::error!(target: LOG_TARGET, "substrate-relay: {}", e); + } + }, + } + } } arg_enum! { diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index bc84786ee27f2..8bd89a4193627 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -24,8 +24,5 @@ mod cli; fn main() { let command = cli::parse_args(); let run = command.run(); - let result = async_std::task::block_on(run); - if let Err(error) = result { - log::error!(target: "bridge", "substrate-relay: {}", error); - } + async_std::task::block_on(run); } From f505d7770d34d8a6e20906e6239b5f1f7a23f63d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 29 Dec 2022 11:51:27 +0300 Subject: [PATCH 0851/1210] Expose metrics of on-demand relay chain headers sync from with-parachain complex relays (#1737) * expose metrics of on-demand relay chain headers sync from with-parachain complex relays * spelling * remove renundant arg --- .../relay_headers_and_messages/parachain_to_parachain.rs | 2 ++ .../cli/relay_headers_and_messages/relay_to_parachain.rs | 2 ++ .../src/cli/relay_headers_and_messages/relay_to_relay.rs | 2 ++ relays/lib-substrate-relay/src/on_demand/headers.rs | 8 +++++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index f832722c6b346..3be07404ebe36 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -245,6 +245,7 @@ where self.common.right.client.clone(), self.left_headers_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, + Some(self.common.metrics_params.clone()), ); let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::<::RelayFinality>::new( @@ -252,6 +253,7 @@ where self.common.left.client.clone(), self.right_headers_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, + Some(self.common.metrics_params.clone()), ); let left_to_right_on_demand_parachains = OnDemandParachainsRelay::< diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 281996534e23f..babd39e558bb1 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -224,6 +224,7 @@ where self.common.right.client.clone(), self.left_headers_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, + None, ); let right_relay_to_left_on_demand_headers = OnDemandHeadersRelay::<::RelayFinality>::new( @@ -231,6 +232,7 @@ where self.common.left.client.clone(), self.right_headers_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, + Some(self.common.metrics_params.clone()), ); let right_to_left_on_demand_parachains = OnDemandParachainsRelay::< ::ParachainFinality, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index a2815bb613916..071716dedb859 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -173,6 +173,7 @@ where self.common.right.client.clone(), self.left_to_right_transaction_params.clone(), self.common.shared.only_mandatory_headers, + None, ); let right_to_left_on_demand_headers = OnDemandHeadersRelay::<::Finality>::new( @@ -180,6 +181,7 @@ where self.common.left.client.clone(), self.right_to_left_transaction_params.clone(), self.common.shared.only_mandatory_headers, + None, ); Ok((Arc::new(left_to_right_on_demand_headers), Arc::new(right_to_left_on_demand_headers))) diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 369520f0e9a41..465b03c04a4a4 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -64,11 +64,15 @@ pub struct OnDemandHeadersRelay { impl OnDemandHeadersRelay

{ /// Create new on-demand headers relay. + /// + /// If `metrics_params` is `Some(_)`, the metrics of the finality relay are registered. + /// Otherwise, all required metrics must be exposed outside of this method. pub fn new( source_client: Client, target_client: Client, target_transaction_params: TransactionParams>, only_mandatory_headers: bool, + metrics_params: Option, ) -> Self where AccountIdOf: @@ -87,6 +91,7 @@ impl OnDemandHeadersRelay

{ target_transaction_params, only_mandatory_headers, required_header_number, + metrics_params, ) .await; }); @@ -148,6 +153,7 @@ async fn background_task( target_transaction_params: TransactionParams>, only_mandatory_headers: bool, required_header_number: RequiredHeaderNumberRef, + metrics_params: Option, ) where AccountIdOf: From< as sp_core::Pair>::Public>, { @@ -310,7 +316,7 @@ async fn background_task( stall_timeout, only_mandatory_headers, }, - MetricsParams::disabled(), + metrics_params.clone().unwrap_or_else(|| MetricsParams::disabled()), futures::future::pending(), ) .fuse(), From 1044ecf8fdfb59daba75dc3d7066261c4f51723f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 30 Dec 2022 10:09:58 +0200 Subject: [PATCH 0852/1210] Simplify read_client_state() (#1739) --- relays/client-substrate/src/client.rs | 2 +- .../src/finality/target.rs | 5 +- .../src/messages_source.rs | 53 ++++++------------- .../src/messages_target.rs | 9 +--- .../src/on_demand/parachains.rs | 27 ++++------ 5 files changed, 31 insertions(+), 65 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index c6387d6bce6f8..dd763150267ae 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -254,7 +254,7 @@ impl Client { /// Return number of the best finalized block. pub async fn best_finalized_header_number(&self) -> Result { - Ok(*self.header_by_hash(self.best_finalized_header_hash().await?).await?.number()) + Ok(*self.best_finalized_header().await?.number()) } /// Return header of the best finalized block. diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index c255c07d148e0..951123ae07c7c 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -27,8 +27,8 @@ use crate::{ use async_trait::async_trait; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SyncHeader, - TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Client, Error, HeaderIdOf, HeaderOf, SyncHeader, TransactionEra, + TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -100,7 +100,6 @@ where Ok(crate::messages_source::read_client_state::( &self.client, None, - P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, ) .await? .best_finalized_peer_at_best_self) diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 0e4a2caa258a4..8dceb6df53be7 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -36,7 +36,7 @@ use bp_messages::{ }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; -use codec::{Decode, Encode}; +use codec::Encode; use frame_support::weights::Weight; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, @@ -47,13 +47,12 @@ use messages_relay::{ }; use num_traits::Zero; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + AccountIdOf, AccountKeyPairOf, BalanceOf, Chain, ChainWithMessages, Client, Error as SubstrateError, HashOf, HeaderIdOf, TransactionEra, TransactionTracker, UnsignedTransaction, }; -use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; -use sp_core::{Bytes, Pair}; -use sp_runtime::{traits::Header as HeaderT, DeserializeOwned}; +use relay_utils::relay_loop::Client as RelayClient; +use sp_core::Pair; use std::ops::RangeInclusive; /// Intermediate message proof returned by the source Substrate node. Includes everything @@ -155,12 +154,7 @@ where // we can't relay confirmations if messages pallet at source chain is halted self.ensure_pallet_active().await?; - read_client_state( - &self.source_client, - Some(&self.target_client), - P::TargetChain::BEST_FINALIZED_HEADER_ID_METHOD, - ) - .await + read_client_state(&self.source_client, Some(&self.target_client)).await } async fn latest_generated_nonce( @@ -408,31 +402,21 @@ where pub async fn read_client_state( self_client: &Client, peer_client: Option<&Client>, - best_finalized_header_id_method_name: &str, ) -> Result, HeaderIdOf>, SubstrateError> where SelfChain: Chain, - SelfChain::Header: DeserializeOwned, - SelfChain::Index: DeserializeOwned, PeerChain: Chain, { // let's read our state first: we need best finalized header hash on **this** chain - let self_best_finalized_header_hash = self_client.best_finalized_header_hash().await?; - let self_best_finalized_header = - self_client.header_by_hash(self_best_finalized_header_hash).await?; - let self_best_finalized_id = self_best_finalized_header.id(); - + let self_best_finalized_id = self_client.best_finalized_header().await?.id(); // now let's read our best header on **this** chain - let self_best_header = self_client.best_header().await?; - let self_best_hash = self_best_header.hash(); - let self_best_id = self_best_header.id(); + let self_best_id = self_client.best_header().await?.id(); // now let's read id of best finalized peer header at our best finalized block let peer_on_self_best_finalized_id = best_finalized_peer_header_at_self::( self_client, - self_best_hash, - best_finalized_header_id_method_name, + self_best_id.hash(), ) .await?; @@ -440,7 +424,7 @@ where let actual_peer_on_self_best_finalized_id = match peer_client { Some(peer_client) => { let actual_peer_on_self_best_finalized = - peer_client.header_by_number(peer_on_self_best_finalized_id.0).await?; + peer_client.header_by_number(peer_on_self_best_finalized_id.number()).await?; actual_peer_on_self_best_finalized.id() }, None => peer_on_self_best_finalized_id, @@ -460,27 +444,20 @@ where pub async fn best_finalized_peer_header_at_self( self_client: &Client, at_self_hash: HashOf, - best_finalized_header_id_method_name: &str, ) -> Result, SubstrateError> where SelfChain: Chain, PeerChain: Chain, { // now let's read id of best finalized peer header at our best finalized block - let encoded_best_finalized_peer_on_self = self_client - .state_call( - best_finalized_header_id_method_name.into(), - Bytes(Vec::new()), + self_client + .typed_state_call::<_, Option<_>>( + PeerChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), + (), Some(at_self_hash), ) - .await?; - - Option::, BlockNumberOf>>::decode( - &mut &encoded_best_finalized_peer_on_self.0[..], - ) - .map_err(SubstrateError::ResponseParseFailed)? - .map(Ok) - .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized)) + .await? + .ok_or(SubstrateError::BridgePalletIsNotInitialized) } fn validate_out_msgs_details( diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 679f9fc140803..75119a1de9768 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -40,7 +40,7 @@ use messages_relay::{ message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, ChainWithMessages, Client, + AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, ChainWithMessages, Client, Error as SubstrateError, HashOf, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; @@ -149,12 +149,7 @@ where // we can't relay messages if messages pallet at target chain is halted self.ensure_pallet_active().await?; - read_client_state( - &self.target_client, - Some(&self.source_client), - P::SourceChain::BEST_FINALIZED_HEADER_ID_METHOD, - ) - .await + read_client_state(&self.target_client, Some(&self.source_client)).await } async fn latest_received_nonce( diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index cfb9d9c7a9423..6be3fcb9886e0 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -468,13 +468,11 @@ where }; let best_target_block_hash = target.best_block().await.map_err(map_target_err)?.1; - let para_header_at_target = - best_finalized_peer_header_at_self::( - target.client(), - best_target_block_hash, - P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD, - ) - .await; + let para_header_at_target = best_finalized_peer_header_at_self::< + P::TargetChain, + P::SourceParachain, + >(target.client(), best_target_block_hash) + .await; // if there are no parachain heads at the target (`BridgePalletIsNotInitialized`), we'll need // to submit at least one. Otherwise the pallet will be treated as uninitialized and messages // sync will stall. @@ -496,14 +494,12 @@ where .map_err(map_source_err)?; let relay_header_at_source = best_finalized_relay_block_id.0; - let relay_header_at_target = - best_finalized_peer_header_at_self::( - target.client(), - best_target_block_hash, - P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD, - ) - .await - .map_err(map_target_err)?; + let relay_header_at_target = best_finalized_peer_header_at_self::< + P::TargetChain, + P::SourceRelayChain, + >(target.client(), best_target_block_hash) + .await + .map_err(map_target_err)?; let para_header_at_relay_header_at_target = source .on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into()) @@ -633,7 +629,6 @@ impl<'a, P: SubstrateParachainsPipeline> Ok(crate::messages_source::read_client_state::( &self.0.target_client, None, - P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD, ) .await? .best_finalized_peer_at_best_self) From c0b53e9ec646ff31e80c5e6fdeb320356df6b47e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 30 Dec 2022 12:09:19 +0300 Subject: [PATCH 0853/1210] Use TypedLaneId instead of LaneId (#1738) * TypedLaneId -> LaneId * fix benchmarks compilation --- bin/millau/runtime/src/rialto_messages.rs | 2 +- .../runtime/src/rialto_parachain_messages.rs | 2 +- bin/millau/runtime/src/xcm_config.rs | 2 +- bin/rialto-parachain/runtime/src/lib.rs | 4 +-- .../runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/xcm_config.rs | 6 ++-- bin/runtime-common/src/messages.rs | 4 +-- bin/runtime-common/src/messages_extension.rs | 8 ++--- .../src/refund_relayer_extension.rs | 2 +- modules/messages/src/mock.rs | 6 ++-- modules/relayers/src/benchmarking.rs | 2 +- modules/relayers/src/lib.rs | 8 ++--- modules/relayers/src/mock.rs | 2 +- primitives/messages/src/lib.rs | 30 ++++++++++++++----- primitives/messages/src/storage_keys.rs | 10 +++---- primitives/relayers/src/lib.rs | 12 ++++---- relays/bin-substrate/src/cli/mod.rs | 6 ++-- .../src/messages_source.rs | 3 +- relays/messages/src/message_lane_loop.rs | 2 +- 20 files changed, 65 insertions(+), 50 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index ff4b6ba1dda31..0d80cdd7b1a8a 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -28,7 +28,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto. -pub const XCM_LANE: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index b6e8f52d342e2..097e2798227c8 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -28,7 +28,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto parachain. -pub const XCM_LANE: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index b5e238d28b352..e353137e8236f 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -298,7 +298,7 @@ mod tests { let xcm: Xcm = vec![Instruction::Trap(42)].into(); let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, data: DispatchMessageData { payload: Ok((location, xcm).into()) }, }; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 6a936bd9f0775..e2e9663510ca0 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -832,7 +832,7 @@ mod tests { use crate::millau_messages::WeightCredit; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - MessageKey, + LaneId, MessageKey, }; use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; @@ -875,7 +875,7 @@ mod tests { let xcm: Xcm = vec![Instruction::Trap(42)].into(); let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, data: DispatchMessageData { payload: Ok((location, xcm).into()) }, }; diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 25d37f1598832..e21cf76a82c81 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -31,7 +31,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Millau. -pub const XCM_LANE: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 66480c3168dc9..b2e55ccfa0268 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -28,7 +28,7 @@ use bridge_runtime_common::messages::{self, MessageBridge}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Lane that is used for XCM messages exchange. -pub const XCM_LANE: LaneId = [0, 0, 0, 0]; +pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index feab0f35c79cb..02729f7565914 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -204,7 +204,7 @@ impl XcmBridge for ToMillauBridge { } fn xcm_lane() -> bp_messages::LaneId { - [0, 0, 0, 0] + bp_messages::LaneId([0, 0, 0, 0]) } } @@ -214,7 +214,7 @@ mod tests { use crate::millau_messages::WeightCredit; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - MessageKey, + LaneId, MessageKey, }; use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; @@ -257,7 +257,7 @@ mod tests { let xcm: Xcm = vec![Instruction::Trap(42)].into(); let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: [0, 0, 0, 0], nonce: 1 }, + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, data: DispatchMessageData { payload: Ok((location, xcm).into()) }, }; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index ca48a6015f11d..9aced1c361abd 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -892,7 +892,7 @@ mod tests { OutboundLaneData::default() } - const TEST_LANE_ID: &LaneId = b"test"; + const TEST_LANE_ID: &LaneId = &LaneId(*b"test"); const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { @@ -904,7 +904,7 @@ mod tests { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - b"dsbl", + &LaneId(*b"dsbl"), &test_lane_outbound_data(), ®ular_outbound_message_payload(), ), diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index 28606d58dadfa..0f680f84e493a 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -110,7 +110,7 @@ mod tests { fn deliver_message_10() { pallet_bridge_messages::InboundLanes::::insert( - [0, 0, 0, 0], + bp_messages::LaneId([0, 0, 0, 0]), bp_messages::InboundLaneData { relayers: Default::default(), last_confirmed_nonce: 10 }, ); } @@ -128,7 +128,7 @@ mod tests { proof: FromBridgedChainMessagesProof { bridged_header_hash: Default::default(), storage_proof: vec![], - lane: [0, 0, 0, 0], + lane: bp_messages::LaneId([0, 0, 0, 0]), nonces_start, nonces_end, }, @@ -170,7 +170,7 @@ mod tests { fn confirm_message_10() { pallet_bridge_messages::OutboundLanes::::insert( - [0, 0, 0, 0], + bp_messages::LaneId([0, 0, 0, 0]), bp_messages::OutboundLaneData { oldest_unpruned_nonce: 0, latest_received_nonce: 10, @@ -188,7 +188,7 @@ mod tests { proof: FromBridgedChainMessagesDeliveryProof { bridged_header_hash: Default::default(), storage_proof: Vec::new(), - lane: [0, 0, 0, 0], + lane: bp_messages::LaneId([0, 0, 0, 0]), }, relayers_state: UnrewardedRelayersState { last_delivered_nonce, diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 4f01926508774..b4ed3ca58935e 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -489,7 +489,7 @@ mod tests { parameter_types! { pub TestParachain: u32 = 1000; - pub TestLaneId: LaneId = [0, 0, 0, 0]; + pub TestLaneId: LaneId = LaneId([0, 0, 0, 0]); } type TestExtension = RefundRelayerForMessagesFromParachain< diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 3f38d923b280c..c628ab2cbb327 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -190,13 +190,13 @@ pub const TEST_RELAYER_C: AccountId = 102; pub const TEST_ERROR: &str = "Test error"; /// Lane that we're using in tests. -pub const TEST_LANE_ID: LaneId = [0, 0, 0, 1]; +pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 1]); /// Secondary lane that we're using in tests. -pub const TEST_LANE_ID_2: LaneId = [0, 0, 0, 2]; +pub const TEST_LANE_ID_2: LaneId = LaneId([0, 0, 0, 2]); /// Inactive outbound lane. -pub const TEST_LANE_ID_3: LaneId = [0, 0, 0, 3]; +pub const TEST_LANE_ID_3: LaneId = LaneId([0, 0, 0, 3]); /// Regular message payload. pub const REGULAR_PAYLOAD: TestPayload = message_payload(0, 50); diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index e79dda14acbbb..7195b316bb694 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -38,7 +38,7 @@ pub trait Config: crate::Config { benchmarks! { // Benchmark `claim_rewards` call. claim_rewards { - let lane = [0, 0, 0, 0]; + let lane = LaneId([0, 0, 0, 0]); let relayer: T::AccountId = whitelisted_caller(); let reward = T::Reward::from(REWARD_AMOUNT); diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 11bbeb10845f8..27ffcaf1ea523 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -244,9 +244,9 @@ mod tests { run_test(|| { let lane0_rewards_account = - PayLaneRewardFromAccount::lane_rewards_account([0, 0, 0, 0]); + PayLaneRewardFromAccount::lane_rewards_account(LaneId([0, 0, 0, 0])); let lane1_rewards_account = - PayLaneRewardFromAccount::lane_rewards_account([0, 0, 0, 1]); + PayLaneRewardFromAccount::lane_rewards_account(LaneId([0, 0, 0, 1])); Balances::mint_into(&lane0_rewards_account, 100).unwrap(); Balances::mint_into(&lane1_rewards_account, 100).unwrap(); @@ -254,12 +254,12 @@ mod tests { assert_eq!(Balances::balance(&lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 0); - PayLaneRewardFromAccount::pay_reward(&1, [0, 0, 0, 0], 100).unwrap(); + PayLaneRewardFromAccount::pay_reward(&1, LaneId([0, 0, 0, 0]), 100).unwrap(); assert_eq!(Balances::balance(&lane0_rewards_account), 0); assert_eq!(Balances::balance(&lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 100); - PayLaneRewardFromAccount::pay_reward(&1, [0, 0, 0, 1], 100).unwrap(); + PayLaneRewardFromAccount::pay_reward(&1, LaneId([0, 0, 0, 1]), 100).unwrap(); assert_eq!(Balances::balance(&lane0_rewards_account), 0); assert_eq!(Balances::balance(&lane1_rewards_account), 0); assert_eq!(Balances::balance(&1), 200); diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 4880e90803940..89b3ead04119d 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -96,7 +96,7 @@ impl pallet_bridge_relayers::Config for TestRuntime { } /// Message lane that we're using in tests. -pub const TEST_LANE_ID: LaneId = [0, 0, 0, 0]; +pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); /// Regular relayer that may receive rewards. pub const REGULAR_RELAYER: AccountId = 1; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index e4f3cb5998b6c..7775b3e7dbcce 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -67,16 +67,30 @@ impl OperatingMode for MessagesOperatingMode { } } -/// Lane identifier. -pub type LaneId = [u8; 4]; - /// Lane id which implements `TypeId`. -// TODO (https://github.com/paritytech/parity-bridges-common/issues/1694): -// `LaneId` shall be replaced with this across all codebase (codec-compatible) -#[derive(Decode, Encode, RuntimeDebug)] -pub struct TypedLaneId(pub [u8; 4]); +#[derive( + Clone, + Copy, + Decode, + Default, + Encode, + Eq, + Ord, + PartialOrd, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, +)] +pub struct LaneId(pub [u8; 4]); + +impl AsRef<[u8]> for LaneId { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} -impl TypeId for TypedLaneId { +impl TypeId for LaneId { const TYPE_ID: [u8; 4] = *b"blan"; } diff --git a/primitives/messages/src/storage_keys.rs b/primitives/messages/src/storage_keys.rs index 4db11edec3420..4edf9828cfde0 100644 --- a/primitives/messages/src/storage_keys.rs +++ b/primitives/messages/src/storage_keys.rs @@ -56,7 +56,7 @@ pub fn outbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey bp_runtime::storage_map_final_key::( pallet_prefix, OUTBOUND_LANES_MAP_NAME, - lane, + &lane.encode(), ) } @@ -65,7 +65,7 @@ pub fn inbound_lane_data_key(pallet_prefix: &str, lane: &LaneId) -> StorageKey { bp_runtime::storage_map_final_key::( pallet_prefix, INBOUND_LANES_MAP_NAME, - lane, + &lane.encode(), ) } @@ -91,7 +91,7 @@ mod tests { fn storage_message_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // all previously crafted messages proofs. - let storage_key = message_key("BridgeMessages", b"test", 42).0; + let storage_key = message_key("BridgeMessages", &LaneId(*b"test"), 42).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed018a395e6242c6813b196ca31ed0547ea79446af0e09063bd4a7874aef8a997cec746573742a00000000000000").to_vec(), @@ -104,7 +104,7 @@ mod tests { fn outbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // all previously crafted outbound lane state proofs. - let storage_key = outbound_lane_data_key("BridgeMessages", b"test").0; + let storage_key = outbound_lane_data_key("BridgeMessages", &LaneId(*b"test")).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed0196c246acb9b55077390e3ca723a0ca1f44a8995dd50b6657a037a7839304535b74657374").to_vec(), @@ -117,7 +117,7 @@ mod tests { fn inbound_lane_data_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking // all previously crafted inbound lane state proofs. - let storage_key = inbound_lane_data_key("BridgeMessages", b"test").0; + let storage_key = inbound_lane_data_key("BridgeMessages", &LaneId(*b"test")).0; assert_eq!( storage_key, hex!("dd16c784ebd3390a9bc0357c7511ed01e5f83cf83f2127eb47afdc35d6e43fab44a8995dd50b6657a037a7839304535b74657374").to_vec(), diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index 04c43d5c7813b..d00b5f626e4ab 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -19,7 +19,7 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use bp_messages::{LaneId, TypedLaneId}; +use bp_messages::LaneId; use sp_runtime::{ codec::{Decode, Encode}, traits::AccountIdConversion, @@ -45,7 +45,7 @@ where { /// Return account that pay rewards for serving given lane. pub fn lane_rewards_account(lane_id: LaneId) -> Relayer { - TypedLaneId(lane_id).into_sub_account_truncating(b"bridge-lane") + lane_id.into_sub_account_truncating(b"bridge-lane") } } @@ -72,17 +72,17 @@ mod tests { #[test] fn lanes_are_using_different_accounts() { assert_eq!( - PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account([ + PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account(LaneId([ 0, 0, 0, 0 - ]), + ])), hex_literal::hex!("626c616e000000006272696467652d6c616e6500000000000000000000000000") .into(), ); assert_eq!( - PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account([ + PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account(LaneId([ 0, 0, 0, 1 - ]), + ])), hex_literal::hex!("626c616e000000016272696467652d6c616e6500000000000000000000000000") .into(), ); diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 4bd735c6334ad..6784f1a606593 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -203,11 +203,11 @@ pub trait CliChain: relay_substrate_client::Chain { /// Lane id. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct HexLaneId(pub LaneId); +pub struct HexLaneId(pub [u8; 4]); impl From for LaneId { fn from(lane_id: HexLaneId) -> LaneId { - lane_id.0 + LaneId(lane_id.0) } } @@ -215,7 +215,7 @@ impl std::str::FromStr for HexLaneId { type Err = hex::FromHexError; fn from_str(s: &str) -> Result { - let mut lane_id = LaneId::default(); + let mut lane_id = [0u8; 4]; hex::decode_to_slice(s, &mut lane_id)?; Ok(HexLaneId(lane_id)) } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 8dceb6df53be7..e86f7abdd642a 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -630,7 +630,8 @@ mod tests { msgs_to_refine.push((payload, out_msg_details)); } - let maybe_batches = split_msgs_to_refine::([0, 0, 0, 0], msgs_to_refine); + let maybe_batches = + split_msgs_to_refine::(LaneId([0, 0, 0, 0]), msgs_to_refine); match expected_batches { Ok(expected_batches) => { let batches = maybe_batches.unwrap(); diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 521baabb195f8..e26849bbb9bf1 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -938,7 +938,7 @@ pub(crate) mod tests { }; let _ = run( Params { - lane: [0, 0, 0, 0], + lane: LaneId([0, 0, 0, 0]), source_tick: Duration::from_millis(100), target_tick: Duration::from_millis(100), reconnect_delay: Duration::from_millis(0), From a146987dc6762fd5822e57a01f441c60383aa86b Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 30 Dec 2022 13:48:29 +0200 Subject: [PATCH 0854/1210] Remove CliChain::KeyPair (#1741) --- relays/bin-substrate/src/chains/millau.rs | 2 -- relays/bin-substrate/src/chains/rialto.rs | 2 -- .../bin-substrate/src/chains/rialto_parachain.rs | 2 -- relays/bin-substrate/src/chains/rococo.rs | 4 ---- relays/bin-substrate/src/chains/westend.rs | 4 ---- relays/bin-substrate/src/chains/wococo.rs | 4 ---- relays/bin-substrate/src/cli/bridge.rs | 6 ++---- relays/bin-substrate/src/cli/chain_schema.rs | 15 ++++++++------- relays/bin-substrate/src/cli/mod.rs | 5 ----- .../src/cli/relay_headers_and_messages/mod.rs | 12 ++++-------- .../parachain_to_parachain.rs | 14 ++++---------- .../relay_to_parachain.rs | 11 ++++------- .../relay_headers_and_messages/relay_to_relay.rs | 8 ++++---- relays/bin-substrate/src/cli/relay_messages.rs | 2 +- relays/bin-substrate/src/cli/send_message.rs | 5 +---- 15 files changed, 28 insertions(+), 68 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index aa56d113e14ed..f318274750df9 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -54,6 +54,4 @@ impl CliEncodeMessage for Millau { impl CliChain for Millau { const RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); - - type KeyPair = sp_core::sr25519::Pair; } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index a8e8143632e16..8a473dc303c4c 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -46,6 +46,4 @@ impl CliEncodeMessage for Rialto { impl CliChain for Rialto { const RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); - - type KeyPair = sp_core::sr25519::Pair; } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 66d03f212ce76..7105dc2b7d7c8 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -48,6 +48,4 @@ impl CliEncodeMessage for RialtoParachain { impl CliChain for RialtoParachain { const RUNTIME_VERSION: Option = Some(rialto_parachain_runtime::VERSION); - - type KeyPair = sp_core::sr25519::Pair; } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 68a6b3e7b1db7..6805c021a213e 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -23,12 +23,8 @@ use sp_version::RuntimeVersion; impl CliChain for Rococo { const RUNTIME_VERSION: Option = None; - - type KeyPair = sp_core::sr25519::Pair; } impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = None; - - type KeyPair = sp_core::sr25519::Pair; } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 075f22b698fdf..50ae034957619 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -22,12 +22,8 @@ use sp_version::RuntimeVersion; impl CliChain for Westend { const RUNTIME_VERSION: Option = None; - - type KeyPair = sp_core::sr25519::Pair; } impl CliChain for Westmint { const RUNTIME_VERSION: Option = None; - - type KeyPair = sp_core::sr25519::Pair; } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 2edd3dcf606e9..0bbfa676fe996 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -23,12 +23,8 @@ use sp_version::RuntimeVersion; impl CliChain for Wococo { const RUNTIME_VERSION: Option = None; - - type KeyPair = sp_core::sr25519::Pair; } impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = None; - - type KeyPair = sp_core::sr25519::Pair; } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 0f0c11f39098d..330b498f19c03 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -17,9 +17,7 @@ use crate::cli::CliChain; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use parachains_relay::ParachainsPipeline; -use relay_substrate_client::{ - AccountKeyPairOf, Chain, ChainWithTransactions, Parachain, RelayChain, -}; +use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, @@ -63,7 +61,7 @@ pub trait CliBridgeBase: Sized { /// The source chain. type Source: Chain + CliChain; /// The target chain. - type Target: ChainWithTransactions + CliChain>; + type Target: ChainWithTransactions + CliChain; } /// Bridge representation that can be used from the CLI for relaying headers diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 6fc0fac18b230..3993b74250df6 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -15,6 +15,7 @@ // along with Parity Bridges Common. If not, see . +use relay_substrate_client::{AccountKeyPairOf, ChainWithTransactions}; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames}; @@ -134,16 +135,16 @@ pub trait TransactionParamsProvider { /// Returns `true` if transaction parameters are defined by this provider. fn is_defined(&self) -> bool; /// Returns transaction parameters. - fn transaction_params( + fn transaction_params( &self, - ) -> anyhow::Result>; + ) -> anyhow::Result>>; /// Returns transaction parameters, defined by `self` provider or, if they're not defined, /// defined by `other` provider. - fn transaction_params_or( + fn transaction_params_or( &self, other: &T, - ) -> anyhow::Result> { + ) -> anyhow::Result>> { if self.is_defined() { self.transaction_params::() } else { @@ -201,7 +202,7 @@ macro_rules! declare_chain_signing_params_cli_schema { /// Parse signing params into chain-specific KeyPair. #[allow(dead_code)] - pub fn to_keypair(&self) -> anyhow::Result { + pub fn to_keypair(&self) -> anyhow::Result> { let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { (Some(suri), _) => suri.to_owned(), (None, Some(suri_file)) => std::fs::read_to_string(suri_file) @@ -234,7 +235,7 @@ macro_rules! declare_chain_signing_params_cli_schema { use sp_core::crypto::Pair; - Chain::KeyPair::from_string( + AccountKeyPairOf::::from_string( &suri, suri_password.as_deref() ).map_err(|e| anyhow::format_err!("{:?}", e)) @@ -247,7 +248,7 @@ macro_rules! declare_chain_signing_params_cli_schema { self.[<$chain_prefix _signer>].is_some() || self.[<$chain_prefix _signer_file>].is_some() } - fn transaction_params(&self) -> anyhow::Result> { + fn transaction_params(&self) -> anyhow::Result>> { Ok(TransactionParams { mortality: self.transactions_mortality()?, signer: self.to_keypair::()?, diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 6784f1a606593..e049a050c4772 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -194,11 +194,6 @@ pub trait CliChain: relay_substrate_client::Chain { /// /// can be `None` if relay is not going to submit transactions to that chain. const RUNTIME_VERSION: Option; - - /// Crypto KeyPair type used to send messages. - /// - /// In case of chains supporting multiple cryptos, pick one used by the CLI. - type KeyPair: sp_core::crypto::Pair; } /// Lane id. diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 1a809a1f483c3..fd8a032066d69 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -227,9 +227,9 @@ trait Full2WayBridgeBase: Sized + Send + Sync { /// The CLI params for the bridge. type Params; /// The left relay chain. - type Left: ChainWithTransactions + CliChain>; + type Left: ChainWithTransactions + CliChain; /// The right destination chain (it can be a relay or a parachain). - type Right: ChainWithTransactions + CliChain>; + type Right: ChainWithTransactions + CliChain; /// Reference to common relay parameters. fn common(&self) -> &Full2WayBridgeCommonParams; @@ -259,13 +259,9 @@ where type Base: Full2WayBridgeBase; /// The left relay chain. - type Left: ChainWithTransactions - + ChainWithBalances - + CliChain>; + type Left: ChainWithTransactions + ChainWithBalances + CliChain; /// The right relay chain. - type Right: ChainWithTransactions - + ChainWithBalances - + CliChain>; + type Right: ChainWithTransactions + ChainWithBalances + CliChain; /// Left to Right bridge. type L2R: MessagesCliBridge; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 3be07404ebe36..b4c858e566b2e 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -116,9 +116,9 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { impl [<$left_parachain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain> + Parachain, + Left: ChainWithTransactions + CliChain + Parachain, LeftRelay: CliChain, - Right: ChainWithTransactions + CliChain> + Parachain, + Right: ChainWithTransactions + CliChain + Parachain, RightRelay: CliChain, L2R: CliBridgeBase + MessagesCliBridge @@ -168,14 +168,8 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { #[async_trait] impl< - Left: Chain - + ChainWithTransactions - + CliChain> - + Parachain, - Right: Chain - + ChainWithTransactions - + CliChain> - + Parachain, + Left: Chain + ChainWithTransactions + CliChain + Parachain, + Right: Chain + ChainWithTransactions + CliChain + Parachain, LeftRelay: Chain + CliChain, RightRelay: Chain diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index babd39e558bb1..d632cce08e9c7 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -107,8 +107,8 @@ macro_rules! declare_relay_to_parachain_bridge_schema { impl [<$left_chain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain>, - Right: ChainWithTransactions + CliChain> + Parachain, + Left: ChainWithTransactions + CliChain, + Right: ChainWithTransactions + CliChain + Parachain, RightRelay: CliChain, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase @@ -156,11 +156,8 @@ macro_rules! declare_relay_to_parachain_bridge_schema { #[async_trait] impl< - Left: ChainWithTransactions + CliChain>, - Right: Chain - + ChainWithTransactions - + CliChain> - + Parachain, + Left: ChainWithTransactions + CliChain, + Right: Chain + ChainWithTransactions + CliChain + Parachain, RightRelay: Chain + CliChain, L2R: CliBridgeBase diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index 071716dedb859..fce80492fc071 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -76,8 +76,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { impl [<$left_chain $right_chain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain>, - Right: ChainWithTransactions + CliChain>, + Left: ChainWithTransactions + CliChain, + Right: ChainWithTransactions + CliChain, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, >( @@ -114,8 +114,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { #[async_trait] impl< - Left: ChainWithTransactions + CliChain>, - Right: ChainWithTransactions + CliChain>, + Left: ChainWithTransactions + CliChain, + Right: ChainWithTransactions + CliChain, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 7f4dc34ac8bff..6af042670e74d 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -56,7 +56,7 @@ pub struct RelayMessages { #[async_trait] trait MessagesRelayer: MessagesCliBridge where - Self::Source: ChainWithTransactions + CliChain>, + Self::Source: ChainWithTransactions + CliChain, AccountIdOf: From< as Pair>::Public>, AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 59a36566c0c6e..9f14028c4aee4 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -57,10 +57,7 @@ pub struct SendMessage { #[async_trait] trait MessageSender: MessagesCliBridge where - Self::Source: ChainBase - + ChainWithTransactions - + CliChain> - + CliEncodeMessage, + Self::Source: ChainBase + ChainWithTransactions + CliChain + CliEncodeMessage, ::Balance: Display + From + Into, ::Call: Sync, ::SignedTransaction: Sync, From a06d5ed4f84de404e634b7b74327329ad1990cf0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 30 Dec 2022 15:26:20 +0300 Subject: [PATCH 0855/1210] Make debug display of LaneId compatible with its previous version (#1740) * make {:?} of LaneId compatible with its previous version * fmt * apply review suggestions --- primitives/messages/src/lib.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 7775b3e7dbcce..8262586567f12 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -69,21 +69,16 @@ impl OperatingMode for MessagesOperatingMode { /// Lane id which implements `TypeId`. #[derive( - Clone, - Copy, - Decode, - Default, - Encode, - Eq, - Ord, - PartialOrd, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, + Clone, Copy, Decode, Default, Encode, Eq, Ord, PartialOrd, PartialEq, TypeInfo, MaxEncodedLen, )] pub struct LaneId(pub [u8; 4]); +impl core::fmt::Debug for LaneId { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { + self.0.fmt(fmt) + } +} + impl AsRef<[u8]> for LaneId { fn as_ref(&self) -> &[u8] { &self.0 @@ -458,4 +453,9 @@ mod tests { assert!(delivered_messages.contains_message(150)); assert!(!delivered_messages.contains_message(151)); } + + #[test] + fn lane_id_debug_format_matches_inner_array_format() { + assert_eq!(format!("{:?}", LaneId([0, 0, 0, 0])), format!("{:?}", [0, 0, 0, 0]),); + } } From bfa0a3faff5caf1ab2aa1c15b0ecd2e0ae9d07f0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 4 Jan 2023 15:37:20 +0200 Subject: [PATCH 0856/1210] Improve relayer initialization behaviour (#1743) Wait until the initialization transaction is finalized/lost. --- .../src/finality/initialize.rs | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index b5f9b322c7cef..87052cf7aa47a 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -24,10 +24,12 @@ use crate::{error::Error, finality::engine::Engine}; use sp_core::Pair; +use bp_runtime::HeaderIdOf; use relay_substrate_client::{ AccountKeyPairOf, Chain, ChainWithTransactions, Client, Error as SubstrateError, UnsignedTransaction, }; +use relay_utils::{TrackedTransactionStatus, TransactionTracker}; use sp_runtime::traits::Header as HeaderT; /// Submit headers-bridge initialization transaction. @@ -61,13 +63,26 @@ pub async fn initialize< .await; match result { - Ok(Some(tx_hash)) => log::info!( - target: "bridge", - "Successfully submitted {}-headers bridge initialization transaction to {}: {:?}", - SourceChain::NAME, - TargetChain::NAME, - tx_hash, - ), + Ok(Some(tx_status)) => match tx_status { + TrackedTransactionStatus::Lost => { + log::error!( + target: "bridge", + "Failed to execute {}-headers bridge initialization transaction on {}: {:?}.", + SourceChain::NAME, + TargetChain::NAME, + tx_status + ) + }, + TrackedTransactionStatus::Finalized(_) => { + log::info!( + target: "bridge", + "Successfully executed {}-headers bridge initialization transaction on {}: {:?}.", + SourceChain::NAME, + TargetChain::NAME, + tx_status + ) + }, + }, Ok(None) => (), Err(err) => log::error!( target: "bridge", @@ -92,7 +107,7 @@ async fn do_initialize< prepare_initialize_transaction: F, dry_run: bool, ) -> Result< - Option, + Option>>, Error::Number>, > where @@ -128,8 +143,8 @@ where initialization_data, ); - let initialization_tx_hash = target_client - .submit_signed_extrinsic(&target_signer, move |_, transaction_nonce| { + let tx_status = target_client + .submit_and_watch_signed_extrinsic(&target_signer, move |_, transaction_nonce| { let tx = prepare_initialize_transaction(transaction_nonce, initialization_data); if dry_run { Err(SubstrateError::Custom( @@ -140,7 +155,9 @@ where } }) .await - .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; + .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))? + .wait() + .await; - Ok(Some(initialization_tx_hash)) + Ok(Some(tx_status)) } From e43c9996f61cd05ca1a9a148521b03973348c4bf Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 9 Jan 2023 08:44:47 +0300 Subject: [PATCH 0857/1210] Update project level docs (#1734) * updated project level document * updated high level overview document * GRANDPA finality relay sequence diagram * Parachains Finality Relay Sequence Diagram * Messages Relay Sequence Diagram * Complex Relayer Sequence Diagram * small fix * Polkadot <> Kusama bridge flowchart * remove obsolete files * started polkadot-kusama-bridge-overview.md * continue polkadot-kusama-bridge-overview.md * couple more sections in polkadot-kusama-bridge-overview.md * continue polkadot-kusama-bridge-overview.md * renew deployments readme * fixed review suggestions * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * removed obsolete section * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * typo * Update docs/polkadot-kusama-bridge-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/high-level-overview.md Co-authored-by: Adrian Catangiu * Update docs/polkadot-kusama-bridge-overview.md Co-authored-by: Adrian Catangiu * Update docs/polkadot-kusama-bridge-overview.md Co-authored-by: Adrian Catangiu * Update docs/polkadot-kusama-bridge-overview.md Co-authored-by: Adrian Catangiu * Update docs/polkadot-kusama-bridge-overview.md Co-authored-by: Adrian Catangiu Co-authored-by: Adrian Catangiu --- README.md | 68 ++++--- docs/complex-relay.html | 85 ++++++++ docs/grandpa-finality-relay.html | 47 +++++ docs/high-level-overview.md | 256 +++++++++++++----------- docs/messages-relay.html | 78 ++++++++ docs/parachains-finality-relay.html | 55 +++++ docs/polkadot-kusama-bridge-overview.md | 132 ++++++++++++ docs/polkadot-kusama-bridge.html | 67 +++++++ 8 files changed, 637 insertions(+), 151 deletions(-) create mode 100644 docs/complex-relay.html create mode 100644 docs/grandpa-finality-relay.html create mode 100644 docs/messages-relay.html create mode 100644 docs/parachains-finality-relay.html create mode 100644 docs/polkadot-kusama-bridge-overview.md create mode 100644 docs/polkadot-kusama-bridge.html diff --git a/README.md b/README.md index d45b328b2bdfe..b588502642622 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,6 @@ Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 -**IMPORTANT**: this documentation is outdated and it is mostly related to the previous version of our -bridge. Right there's an ongoing work to make our bridge work with XCM messages. Old bridge is still -available at [encoded-calls-messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) -tag. - ## Contents - [Installation](#installation) @@ -97,7 +92,7 @@ description of the bridge interaction. ## Project Layout -Here's an overview of how the project is laid out. The main bits are the `node`, which is the actual +Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual "blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass messages between chains. @@ -106,16 +101,16 @@ the `relays` which are used to pass messages between chains. │ └── ... ├── deployments // Useful tools for deploying test networks │ └── ... -├── diagrams // Pretty pictures of the project architecture -│ └── ... ├── modules // Substrate Runtime Modules (a.k.a Pallets) +│ ├── beefy // On-Chain BEEFY Light Client (in progress) │ ├── grandpa // On-Chain GRANDPA Light Client │ ├── messages // Cross Chain Message Passing -│ ├── dispatch // Target Chain Message Execution +│ ├── parachains // On-Chain Parachains Light Client +│ ├── relayers // Relayer rewards registry │ └── ... ├── primitives // Code shared between modules, runtimes, and relays │ └── ... -├── relays // Application for sending headers and messages between chains +├── relays // Application for sending finality proofs and messages between chains │ └── ... └── scripts // Useful development and maintenance scripts ``` @@ -127,8 +122,11 @@ on each side of the bridge (source and target chain). There are 2 ways to run the bridge, described below: -- building & running from source -- running a Docker Compose setup (recommended). +- building & running from source: with this option, you'll be able to run the bridge between two standalone +chains that are running GRANDPA finality gadget to achieve finality; + +- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, +complex relays and more. ### Using the Source @@ -204,7 +202,33 @@ You will also see the message lane relayers listening for new messages. To send a message see the ["How to send a message" section](#how-to-send-a-message). -### Full Network Docker Compose Setup +### How to send a message + +In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM +`Trap(43)` message. + +```bash +# In `parity-bridges-common` folder +./scripts/send-message-from-millau-rialto.sh +``` + +After sending a message you will see the following logs showing a message was successfully sent: + +``` +INFO bridge Sending message to Rialto. Size: 5. +TRACE bridge Sent transaction to Millau node: 0x5e68... +``` + +And at the Rialto node logs you'll something like this: + +``` +... runtime::bridge-dispatch: Going to execute message ([0, 0, 0, 0], 1) (...), Trap(43)]) +... runtime::bridge-dispatch: Incoming message ([0, 0, 0, 0], 1) dispatched with result: Incomplete(2000000000, Trap(43)) +``` + +It means that the message has been delivered and successfully dispatched. + +## Full Network Docker Compose Setup For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). @@ -220,24 +244,6 @@ docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external ``` -### How to send a message - -In this section we'll show you how to quickly send a bridge message, if you want to -interact with and test the bridge see more details in [send message](./docs/send-message.md) - -```bash -# In `parity-bridges-common` folder -./scripts/send-message-from-millau-rialto.sh remark -``` - -After sending a message you will see the following logs showing a message was successfully sent: - -``` -INFO bridge Sending message to Rialto. Size: 286. Dispatch weight: 1038000. Fee: 275,002,568 -INFO bridge Signed Millau Call: 0x7904... -TRACE bridge Sent transaction to Millau node: 0x5e68... -``` - ## Community Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat diff --git a/docs/complex-relay.html b/docs/complex-relay.html new file mode 100644 index 0000000000000..21524bfd04913 --- /dev/null +++ b/docs/complex-relay.html @@ -0,0 +1,85 @@ + + + + + + Complex Relay + + +

Complex Relay

+

+ Both Source Chain and Target Chains have Bridge Messages pallets deployed. They also have required + finality pallets deployed - we don't care about finality type here - they can be either Bridge GRANDPA, + or Bridge Parachains finality pallets, or any combination of those.
+

+

+ There are 4-6 relayer subprocesses inside the Complex Relayer. They include two message relayers, + serving the lane in both directions and 2-4 Complex Relayers (depending on the finality type of Source + and Target Chains).
+

+

+ The following diagram shows the way the complex relayer serves the lane in single direction. Everything + below may be applied to the opposite direction if you'll swap the Source and Target Chains. +

+
+ sequenceDiagram + participant Source Chain + participant Complex Relayer + participant Target Chain + + Note right of Source Chain: Finalized: 480, Target Finalized: 50, Sent Messages: 42, Confirmed Messages: 42 + Note left of Target Chain: Finalized: 60, Source Finalized: 420, Received Messages: 42 + + Source Chain ->> Source Chain: someone Sends Message 43 + Source Chain ->> Source Chain: Import and Finalize Block 481 + + Source Chain ->> Complex Relayer: notes new outbound message 43 at Source Chain Block 481 + Note right of Complex Relayer: can't deliver message 43, Source Chain Block 481 is not relayed + Complex Relayer ->> Complex Relayer: asks on-demand Finality Relayer to relay Source Chain Block 481 + + Source Chain ->> Complex Relayer: Read Finality Proof of Block 481 + Complex Relayer ->> Target Chain: Submit Finality Proof of Block 481 + Target Chain ->> Target Chain: Import and Finalize Block 61 + Note left of Target Chain: Finalized: 61, Source Finalized: 481, Received Messages: 42 + + Source Chain ->> Complex Relayer: Read Proof of Message 43 at Block 481 + Complex Relayer ->> Target Chain: Submit Proof of Message 43 at Block 481 + Target Chain ->> Target Chain: Import and Finalize Block 62 + Note left of Target Chain: Finalized: 62, Source Finalized: 481, Received Messages: { rewarded: 42, messages-relayer-account: [43] } + + Target Chain ->> Complex Relayer: notes new unrewarded relayer at Target Chain Block 62 + Note right of Complex Relayer: can't relay delivery confirmations because Target Chain Block 62 is not relayed + Complex Relayer ->> Complex Relayer: asks on-demand Finality Relayer to relay Target Chain Block 62 + + Target Chain ->> Complex Relayer: Read Finality Proof of Block 62 + Complex Relayer ->> Source Chain: Submit Finality Proof of Block 62 + Source Chain ->> Source Chain: Import and Finalize Block 482 + Note right of Source Chain: Finalized: 482, Target Finalized: 62, Confirmed Messages: 42 + + Target Chain ->> Complex Relayer: Read Proof of Message 43 Delivery at Block 62 + Complex Relayer ->> Source Chain: Submit Proof of Message 43 Delivery at Block 612 + Source Chain ->> Source Chain: rewards messages-relayer-account for delivering message [43] + Source Chain ->> Source Chain: prune delivered message 43 from runtime storage + Note right of Source Chain: Finalized: 482, Target Finalized: 61, Confirmed Messages: 43 + + Source Chain ->> Source Chain: someone Sends Message 44 + Source Chain ->> Source Chain: Import and Finalize Block 483 + + Source Chain ->> Complex Relayer: notes new outbound message 44 at Source Chain Block 483 and new confirmed message 43 + Note right of Complex Relayer: can't deliver message 44, Source Chain Block 483 is not relayed + Complex Relayer ->> Complex Relayer: asks on-demand Finality Relayer to relay Source Chain Block 483 + + Source Chain ->> Complex Relayer: Read Finality Proof of Block 483 + Complex Relayer ->> Target Chain: Submit Finality Proof of Block 483 + Target Chain ->> Target Chain: Import and Finalize Block 63 + Note left of Target Chain: Finalized: 63, Source Finalized: 483, Received Messages: { rewarded: 42, messages-relayer-account: [43] } + + Source Chain ->> Complex Relayer: Read Proof of Message 44 and Proof of Message 43 reward at Block 483 + Complex Relayer ->> Target Chain: Submit Proof of Message 44 and Proof of Message 43 reward at Block 483 + Target Chain ->> Target Chain: Import and Finalize Block 64 + Note left of Target Chain: Finalized: 64, Source Finalized: 483, Received Messages: { rewarded: 43, messages-relayer-account: [44] }--> +
+ + + + diff --git a/docs/grandpa-finality-relay.html b/docs/grandpa-finality-relay.html new file mode 100644 index 0000000000000..4136621b1a4bf --- /dev/null +++ b/docs/grandpa-finality-relay.html @@ -0,0 +1,47 @@ + + + + + + GRANDPA Finality Relay + + +

GRANDPA Finality Relay

+

+ Source Chain is running GRANDPA Finality Gadget. Bridge GRANDPA finality pallet is deployed at + Target Chain runtime. Relayer is configured to relay Source Chain finality to Target Chain. +

+
+ sequenceDiagram + participant Source Chain + participant Relayer + participant Target Chain + Note left of Source Chain: Best: 500, Finalized: 480, Authorities Set Index: 42 + Note right of Target Chain: Uninitialized + + Source Chain ->> Relayer: Read Initialization Data + Relayer ->> Target Chain: Initialize Bridge GRANDPA Finality Pallet + Note right of Target Chain: Finalized: 480, Authorities Set Index: 42 + + Source Chain ->> Source Chain: Import Block 501 + Source Chain ->> Source Chain: Import Block 502 + Source Chain ->> Source Chain: Finalize Block 495 + Source Chain ->> Relayer: Read Finality Proof of Block 495 + Relayer ->> Target Chain: Finality Proof of Block 495 + Note right of Target Chain: Finalized: 495, Authorities Set Index: 42 + + Source Chain ->> Source Chain: Import Block 503 that changes Authorities Set to 43 + Source Chain ->> Source Chain: Finalize Block 500 + Note left of Relayer: Relayer Misses Finality Notification for Block 500 + + Source Chain ->> Source Chain: Import Block 504 + Source Chain ->> Source Chain: Finalize Mandatory Block 503 + Source Chain ->> Source Chain: Finalize Block 504 + Source Chain ->> Relayer: Read Finality Proof of Mandatory Block 503 + Relayer ->> Target Chain: Finality Proof of Block 503 + Note right of Target Chain: Finalized: 503, Authorities Set Index: 43 +
+ + + + diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 2642c20c86abb..2c174dbc98a4c 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -1,165 +1,181 @@ # High-Level Bridge Documentation +This document gives a brief, abstract description of main components that may be found in this repository. +If you want to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please +refer to the [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md). + ## Purpose -Trustless connecting between two Substrate-based chains using GRANDPA finality. +This repo contains all components required to build a trustless connection between standalone Substrate chains, +that are using GRANDPA finality, their parachains or any combination of those. On top of this connection, we +offer a messaging pallet that provides means to organize messages exchange. + +On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM messaging](./polkadot-kusama-bridge-overview.md), +[encoded calls messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on. + +## Terminology + +Even though we support (and require) two-way bridging, the documentation will generally talk about +a one-sided interaction. That's to say, we will only talk about syncing finality proofs and messages +from a _source_ chain to a _target_ chain. This is because the two-sided interaction is really just the +one-sided interaction with the source and target chains switched. + +The bridge has both on-chain (pallets) and offchain (relayers) components. + +## On-chain components -## Overview +On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require +deployment at the target chain, while messages pallet needs to be deployed at both, source +and target chains. -Even though we support two-way bridging, the documentation will generally talk about a one-sided -interaction. That's to say, we will only talk about syncing headers and messages from a _source_ -chain to a _target_ chain. This is because the two-sided interaction is really just the one-sided -interaction with the source and target chains switched. +### Bridge GRANDPA Finality Pallet -To understand the full interaction with the bridge, take a look at the -[testing scenarios](./testing-scenarios.md) document. It describes potential use cases and describes -how each of the layers outlined below is involved. +A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth" +about the source chain headers which have been finalized. This is useful for higher level applications. -The bridge is built from various components. Here is a quick overview of the important ones. +The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), +generated by the current authorities set. The GRANDPA protocol itself requires current authorities set to +generate explicit justificaion for the header that enacts next authorities set. Such headers and their finality +proofs are called mandatory in the pallet and relayer pays no fee for such headers submission. -### Header Sync +The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers +he wants to submit (with the exception of mandatory headers). -A light client of the source chain built into the target chain's runtime. It is a single FRAME -pallet. It provides a "source of truth" about the source chain headers which have been finalized. -This is useful for higher level applications. +More: [code](../modules/grandpa/). -### Headers Relayer +### Bridge Parachains Finality Pallet -A standalone application connected to both chains. It submits every source chain header it sees to -the target chain through RPC. +Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their +finality proofs. Instead, they rely on their relay chain finality. The parachain header is considered final, +when it is accepted by the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) +at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay +chain GRANDPA gadget. -### Message Delivery +That said, the bridge parachains pallet accepts storage proof of one or several parachain heads, inserted to the +[`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) +map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras). +To verify this storage proof, the pallet uses relay chain header, imported earlier by the bridge GRANDPA pallet. -A FRAME pallet built on top of the header sync pallet. It allows users to submit messages to the -source chain, which are to be delivered to the target chain. The delivery protocol doesn't care -about the payload more than it has to. Handles replay protection and message ordering. +The pallet may track multiple parachains at once and those parachains may use different primitives. So the +parachain header decoding never happens at the pallet level. For maintaining the headers order, the pallet +uses relay chain header number. -### Message Dispatch +More: [code](../modules/parachains/). -A FRAME pallet responsible for interpreting the payload of delivered messages. +### Bridge Messages Pallet -### Message Relayer +The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the +target chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the +same order they are sent. The pallet supports many lanes. -A standalone application handling delivery of the messages from source chain to the target chain. +The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of +messages that have been received. Inbound lane end stores the number of messages that have been received and +also a map that maps messages to relayers that have delivered those messages to the target chain. -## Processes +The pallet has three main entrypoints: +- the `send_message` may be used by the other runtime pallets to send the messages; +- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the +dispatch code; +- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding +relayers that have delivered the message. -High level sequence charts of the process can be found in [a separate document](./high-level.html). +Many things are abstracted by the pallet: +- the message itself may mean anything, the pallet doesn't care about its content; +- the message dispatch happens during delivery, but it is decoupled from the pallet code; +- the messages proof and messages delivery proof are verified outside of the pallet; +- the relayers incentivization scheme is defined outside of the pallet. -### Substrate (GRANDPA) Header Sync +Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular +storage proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages +pallet, in this case, depends on one of the finality pallets. The messages are XCM messages and we are using +XCM executor to dispatch them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) +document. -The header sync pallet (`pallet-bridge-grandpa`) is an on-chain light client for chains which use -GRANDPA finality. It is part of the target chain's runtime, and accepts finality proofs from the source -chain. Verify GRANDPA finality proofs (a.k.a justifications) and track GRANDPA finality set changes. +More: [code](../modules/messages/). -The pallet does not care about what block production mechanism is used for the source chain -(e.g Aura or BABE) as long as it uses the GRANDPA finality gadget. In fact the pallet does not -necessarily store all produced headers, we only import headers with valid GRANDPA justifications. +### Bridge Relayers Pallet -Referer to the [pallet documentation](../modules/grandpa/src/lib.rs) for more details. +The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When +the rewards are registered and the reward amount is configured outside of the pallet. -#### Header Relayer strategy +More: [code](../modules/relayers/). -There is currently no reward strategy for the relayers at all. They also are not required to be -staked or registered on-chain, unlike in other bridge designs. We consider the header sync to be -an essential part of the bridge and the incentivization should be happening on the higher layers. +## Offchain Components -At the moment, signed transactions are the only way to submit headers to the header sync pallet. -However, in the future we would like to use unsigned transactions for headers delivery. This will -allow transaction de-duplication to be done at the transaction pool level and also remove the cost -for message relayers to run header relayers. +Offchain bridge components are separate processes, called relayers. Relayers are connected both to the +source chain and target chain nodes. Relayers are reading state of the source chain, compare it to the +state of the target chain and, if state at target chain needs to be updated, submits target chain +transaction. -### Message Passing +### GRANDPA Finality Relay -Once header sync is maintained, the target side of the bridge can receive and verify proofs about -events happening on the source chain, or its internal state. On top of this, we built a message -passing protocol which consists of two parts described in following sections: message delivery and -message dispatch. +The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to +the Bridge GRANDPA Finality Pallet, deployed at the target chain. For that, the relay subscribes to +the source chain GRANDPA justifications stream and submits every new justification it sees to the +target chain GRANDPA light client. In addition, relay is searching for mandatory headers and +submits their justifications - without that the pallet will be unable to move forward. -#### Message Lanes Delivery +More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [code](../relays/finality/). -The [Message delivery pallet](../modules/messages/src/lib.rs) is responsible for queueing up -messages and delivering them in order on the target chain. It also dispatches messages, but we will -cover that in the next section. +### Parachains Finality Relay -The pallet supports multiple lanes (channels) where messages can be added. Every lane can be -considered completely independent from others, which allows them to make progress in parallel. -Different lanes can be configured to validated messages differently (e.g higher rewards, specific -types of payload, etc.) and may be associated with a particular "user application" built on top of -the bridge. Note that messages in the same lane MUST be delivered _in the same order_ they were -queued up. +The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the +tracked parachain nodes. The relay looks at the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) +map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) +in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at +the taget chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** +until header `B` or one of its ancestors appears at the target chain. Once it is available, the storage +proof of the map entry is generated and is submitted to the target chain. -The message delivery protocol does not care about the payload it transports and can be coupled -with an arbitrary message dispatch mechanism that will interpret and execute the payload if delivery -conditions are met. Each delivery on the target chain is confirmed back to the source chain by the -relayer. This is so that she can collect the reward for delivering these messages. +As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains +finality relay requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or +any of its children's finality at source won't be relayed at target, and target chain +won't be able to verify generated storage proof. -Users of the pallet add their messages to an "outbound lane" on the source chain. When a block is -finalized message relayers are responsible for reading the current queue of messages and submitting -some (or all) of them to the "inbound lane" of the target chain. Each message has a `nonce` -associated with it, which serves as the ordering of messages. The inbound lane stores the last -delivered nonce to prevent replaying messages. To successfully deliver the message to the inbound lane -on target chain the relayer has to present present a storage proof which shows that the message was -part of the outbound lane on the source chain. +More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/). -During delivery of messages they are immediately dispatched on the target chain and the relayer is -required to declare the correct `weight` to cater for all messages dispatch and pay all required -fees of the target chain. To make sure the relayer is incentivised to do so, on the source chain: -- the user provides a declared dispatch weight of the payload -- the pallet calculates the expected fee on the target chain based on the declared weight -- the pallet converts the target fee into source tokens (based on a price oracle) and reserves - enough tokens to cover for the delivery, dispatch, confirmation and additional relayers reward. +### Messages Relay -If the declared weight turns out to be too low on the target chain the message is delivered but -it immediately fails to dispatch. The fee and reward is collected by the relayer upon confirmation -of delivery. +Messages relay is actually two relays that are running in a single process: messages delivery relay and +delivery confirmation relay. Even though they are more complex and have many caveats, the overall algorithm +is the same as in other relays. -Due to the fact that message lanes require delivery confirmation transactions, they also strictly -require bi-directional header sync (i.e. you can't use message delivery with one-way header sync). +Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new +messages are queued there. Once they appear at the source block `B`, the relay start waiting for the block +`B` or its descendant appear at the target chain. Then the messages storage proof is generated and submitted +to the bridge messages pallet at the target chain. In addition, the transaction may include the storage proof +of the outbound lane state - that proves that relayer rewards have been paid and this data (map of relay +accounts to the delivered messages) may be pruned from the inbound lane state at the target chain. -#### Dispatching Messages +Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new +messages are delivered to the target chain, the corresponding _source chain account_ is inserted to the +map in the inbound lane data. Relay detects that, say, at the target chain block `B` and waits until that +block or its descendant appears at the source chain. Once that happens, the relay crafts a storage proof of +that data and sends it to the messages pallet, deployed at the source chain. -The [Message dispatch pallet](../modules/dispatch/src/lib.rs) is used to perform the actions -specified by messages which have come over the bridge. For Substrate-based chains this means -interpreting the source chain's message as a `Call` on the target chain. +As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages +relay submits transactions to both source and target chains, it requires both _source-to-target_ and +_target-to-source_ finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, +depending on the type of connected chain. -An example `Call` of the target chain would look something like this: +More: [Messages Relay Sequence Diagram](./messages-relay.html), [code](../relays/messages/). -```rust -target_runtime::Call::Balances(target_runtime::pallet_balances::Call::transfer(recipient, amount)) -``` +### Complex Relay -When sending a `Call` it must first be SCALE encoded and then sent to the source chain. The `Call` -is then delivered by the message lane delivery mechanism from the source chain to the target chain. -When a message is received the inbound message lane on the target chain will try and decode the -message payload into a `Call` enum. If it's successful it will be dispatched after we check that the -weight of the call does not exceed the weight declared by the sender. The relayer pays fees for -executing the transaction on the target chain, but her costs should be covered by the sender on the -source chain. +Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory +GRANDPA header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it +sees, will have to pay a (quite large) cost. And if no messages are sent through the bridge, that is just +waste of money. -When dispatching messages there are three Origins which can be used by the target chain: -1. Root Origin -2. Source Origin -3. Target Origin +We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions +that are required for the messages/confirmations delivery. This mode starts two message relays (in both +directions). All required finality relays are also started in a special _on-demand_ mode. In this mode they +do not submit any headers without special request. As always, the only exception is when GRANDPA finality +relay sees the mandatory header - it is submitted without such request. -Senders of a message can indicate which one of the three origins they would like to dispatch their -message with. However, there are restrictions on who/what is allowed to dispatch messages with a -particular origin. +The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations +to be delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and +then message relay may perform its job. If on-demand relay is a parachain finality relay, it also runs its +own on-demand GRANDPA relay, which is used to relay required relay chain headers. -The Root origin represents the source chain's Root account on the target chain. This origin can can -only be dispatched on the target chain if the "send message" request was made by the Root origin of -the source chain - otherwise the message will fail to be dispatched. - -The Source origin represents an account without a private key on the target chain. This account will -be generated/derived using the account ID of the sender on the source chain. We don't necessarily -require the source account id to be associated with a private key on the source chain either. This -is useful for representing things such as source chain proxies or pallets. - -The Target origin represents an account with a private key on the target chain. The sender on the -source chain needs to prove ownership of this account by using their target chain private key to -sign: `(Call, SourceChainAccountId).encode()`. This will be included in the message payload and -verified by the target chain before dispatch. - -See [`CallOrigin` documentation](../primitives/message-dispatch/src/lib.rs) for more details. - -#### Message Relayers Strategy +More: [Complex Relay Sequence Diagram](./complex-relay.html), [code](../relays/bin-substrate/src/cli/relay_headers_and_messages/). diff --git a/docs/messages-relay.html b/docs/messages-relay.html new file mode 100644 index 0000000000000..c4dab9901e03b --- /dev/null +++ b/docs/messages-relay.html @@ -0,0 +1,78 @@ + + + + + + Messages Relay + + +

Messages Relay

+

+ Both Source Chain and Target Chains have Bridge Messages pallets deployed. They also have required + finality pallets deployed - we don't care about finality type here - they can be either Bridge GRANDPA, + or Bridge Parachains finality pallets, or any combination of those. +

+

+ Finality Relayer represents two actual relayers - one relays Source Chain Finality to Target Chain. + And another one relays Target Chain Finality to Source Chain. +

+
+ sequenceDiagram + participant Source Chain + participant Finality Relayer + participant Messages Relayer + participant Target Chain + + Note right of Source Chain: Finalized: 480, Target Finalized: 50, Sent Messages: 42, Confirmed Messages: 42 + Note left of Target Chain: Finalized: 60, Source Finalized: 420, Received Messages: 42 + + Source Chain ->> Source Chain: someone Sends Message 43 + Source Chain ->> Source Chain: Import and Finalize Block 481 + + Source Chain ->> Messages Relayer: notes new outbound message 43 at Source Chain Block 481 + Note right of Messages Relayer: can't deliver message 43, Source Chain Block 481 is not relayed + + Source Chain ->> Finality Relayer: Read Finality Proof of Block 481 + Finality Relayer ->> Target Chain: Submit Finality Proof of Block 481 + Target Chain ->> Target Chain: Import and Finalize Block 61 + Note left of Target Chain: Finalized: 61, Source Finalized: 481, Received Messages: 42 + + Source Chain ->> Messages Relayer: Read Proof of Message 43 at Block 481 + Messages Relayer ->> Target Chain: Submit Proof of Message 43 at Block 481 + Target Chain ->> Target Chain: Import and Finalize Block 62 + Note left of Target Chain: Finalized: 62, Source Finalized: 481, Received Messages: { rewarded: 42, messages-relayer-account: [43] } + + Target Chain ->> Messages Relayer: notes new unrewarded relayer at Target Chain Block 62 + Note right of Messages Relayer: can't relay delivery confirmations because Target Chain Block 62 is not relayed + + Target Chain ->> Finality Relayer: Read Finality Proof of Block 62 + Finality Relayer ->> Source Chain: Submit Finality Proof of Block 62 + Source Chain ->> Source Chain: Import and Finalize Block 482 + Note right of Source Chain: Finalized: 482, Target Finalized: 62, Confirmed Messages: 42 + + Target Chain ->> Messages Relayer: Read Proof of Message 43 Delivery at Block 62 + Messages Relayer ->> Source Chain: Submit Proof of Message 43 Delivery at Block 612 + Source Chain ->> Source Chain: rewards messages-relayer-account for delivering message [43] + Source Chain ->> Source Chain: prune delivered message 43 from runtime storage + Note right of Source Chain: Finalized: 482, Target Finalized: 61, Confirmed Messages: 43 + + Source Chain ->> Source Chain: someone Sends Message 44 + Source Chain ->> Source Chain: Import and Finalize Block 483 + + Source Chain ->> Messages Relayer: notes new outbound message 44 at Source Chain Block 483 and new confirmed message 43 + Note right of Messages Relayer: can't deliver message 44, Source Chain Block 483 is not relayed + + Source Chain ->> Finality Relayer: Read Finality Proof of Block 483 + Finality Relayer ->> Target Chain: Submit Finality Proof of Block 483 + Target Chain ->> Target Chain: Import and Finalize Block 63 + Note left of Target Chain: Finalized: 63, Source Finalized: 483, Received Messages: { rewarded: 42, messages-relayer-account: [43] } + + Source Chain ->> Messages Relayer: Read Proof of Message 44 and Proof of Message 43 reward at Block 483 + Messages Relayer ->> Target Chain: Submit Proof of Message 44 and Proof of Message 43 reward at Block 483 + Target Chain ->> Target Chain: Import and Finalize Block 64 + Note left of Target Chain: Finalized: 64, Source Finalized: 483, Received Messages: { rewarded: 43, messages-relayer-account: [44] } +
+ + + + diff --git a/docs/parachains-finality-relay.html b/docs/parachains-finality-relay.html new file mode 100644 index 0000000000000..4fc1392b87dea --- /dev/null +++ b/docs/parachains-finality-relay.html @@ -0,0 +1,55 @@ + + + + + + Parachains Finality Relay + + +

Parachains Finality Relay

+

+ Source Relay Chain is running GRANDPA Finality Gadget. Source Parachain is a parachain of the Source + Relay Chain. Bridge GRANDPA finality pallet is deployed at Target Chain runtime and is "connected" + to the Source Relay Chain. Bridge Parachains finality pallet is deployed at Target Chain and is + configured to track the Source Parachain. GRANDPA Relayer is configured to relay Source Relay Chain + finality to Target Chain. Parachains Relayer is configured to relay Source Parachain headers finality + to Target Chain. +

+
+ sequenceDiagram + participant Source Parachain + participant Source Relay Chain + participant GRANDPA Relayer + participant Parachains Relayer + participant Target Chain + + Note left of Source Parachain: Best: 125 + Note left of Source Relay Chain: Finalized: 500, Best Parachain at Finalized: 120 + Note right of Target Chain: Best Relay: 480, Best Parachain: 110 + + Source Parachain ->> Source Parachain: Import Block 126 + Source Parachain ->> Source Relay Chain: Receives the Parachain block 126 + + Source Relay Chain ->> Source Relay Chain: Import block 501 + Source Relay Chain ->> Source Relay Chain: Finalize block 501 + Note left of Source Relay Chain: Finalized: 501, Best Parachain at Finalized: 126 + + Source Relay Chain ->> Parachains Relayer: notes new Source Parachain Block 126 + Note left of Parachains Relayer: can't relay Source Parachain Block 126, because it requires at least Source Relay Block 501 at Target Chain + + Source Relay Chain ->> Source Relay Chain: Import block 502 + Source Relay Chain ->> Source Relay Chain: Finalize block 502 + + Source Relay Chain ->> GRANDPA Relayer: read GRANDPA Finality Proof of Block 502 + GRANDPA Relayer ->> Target Chain: submit GRANDPA Finality Proof of Block 502 + Note right of Target Chain: Best Relay: 502, Best Parachain: 110 + + Target Chain ->> Parachains Relayer: notes finalized Source Relay Block 502 at Target Chain + Source Relay Chain ->> Parachains Relayer: read Parachain Finality Proof at Relay Block 502 + Parachains Relayer ->> Target Chain: submit Parachain Finality Proof at Relay Block 502 + Note right of Target Chain: Best Relay: 502, Best Parachain: 126 +
+ + + + diff --git a/docs/polkadot-kusama-bridge-overview.md b/docs/polkadot-kusama-bridge-overview.md new file mode 100644 index 0000000000000..302196718b982 --- /dev/null +++ b/docs/polkadot-kusama-bridge-overview.md @@ -0,0 +1,132 @@ +# Polkadot <> Kusama Bridge Overview + +This document describes how we use all components, described in the [High-Level Bridge Documentation](./high-level-overview.md), +to build the XCM bridge between Kusama and Polkadot. In this case, our components merely work as a XCM transport +(like XCMP/UMP/HRMP), between chains that are not a part of the same consensus system. + +The overall architecture may be seen in [this diagram](./polkadot-kusama-bridge.html). + +## Bridge Hubs + +All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains. +That's why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama +Bridge Hub under Kusama consensus. + +The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to +use our bridge hubs too and have their pallets there. + +The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub. +The runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs. + +## Connecting Parachains + +You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need +to use other parachains transactions, which will use HRMP to deliver message to the Bridge Hub. The Bridge Hub will +just queue this messages in its outbound lane, which is dedicated to deliver messages between two parachains. + +Our first planned bridge will connect the Polkadot' Statemint and Kusama' Statemine. Bridge between those two +parachains would allow Statemint accounts to hold wrapped KSM tokens and Statemine accounts to hold wrapped DOT +tokens. + +For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, +when other parachains will join the bridge, they will be using other lanes for their messages. + +## Running Relayers + +We are planning to run our own complex relayer for the lane 00000000. The relayer will relay Kusama/Polkadot GRANDPA +justifications to the bridge hubs at the other side. It'll also relay finalized Kusama Bridge Hub and Polkadot Bridge +Hub heads. This will only happen when messages will be queued at hubs. So most of time relayer will be idle. + +There's no any active relayer sets, or something like that. Anyone may start its own relayer and relay queued messages. +We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost. +Apart from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have +a mechanism for rewarding relayers. + +### Compensating the Cost of Message Delivery Transactions + +One part of our rewarding scheme is that the cost of message delivery, for honest relayer, is zero. The honest relayer +is the relayer, which is following our rules: + +- we do not reward relayers for submitting GRANDPA finality transactions. The only exception is submitting mandatory + headers (headers which are changing the GRANDPA authorities set) - the cost of such transaction is zero. The relayer + will pay the full cost for submitting all other headers; + +- we do not reward relayers for submitting parachain finality transactions. The relayer will pay the full cost for + submitting parachain finality transactions; + +- we compensate the cost of message delivery transactions that have actually delivered the messages. So if your + transaction has claimed to deliver messages `[42, 43, 44]`, but, because of some reasons, has actually delivered + messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then + the relayer pays the full cost of the transaction; + +- we compensate the cost of message delivery and all required finality calls, if they are part of the same + [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326) + transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used + to prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they + are not linked together, the relayer pays the full transaction cost. + +Please keep in mind that the fee of "zero-cost" transactions is still withdrawn from the relayer account. But the +compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer +may later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call. + +*A side note*: why we don't simply set the cost of useful transactions to zero? That's because the bridge has its cost. +If we won't take any fees, it would mean that the sender is not obliged to pay for its messages. And Bridge Hub +collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later, +in the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section. + +### Message Delivery Confirmation Rewards + +In addition to the "zero-cost" message delivery transactions, the relayer is also rewarded for: + +- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge + Hub.; + +- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms + delivery of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It + receives some fee for confirming messages, delivered by other relayers. + +Both rewards may be claimed using the `pallet_bridge_relayers::claim_rewards` call at the Source Bridge Hub. + +### Who is Rewarding Relayers + +Obviously, there should be someone who is paying relayer rewards. We want bridge transactions to have a cost, so we +can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides +of the bridge to cover relayer rewards. + +Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Statemine (Kusama Parachain) will +have an account at the Polkadot Bridge Hub. The Statemint (Polkadot Parachain) will have an account at the Kusama +Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the +`pallet_bridge_relayers::claim_rewards`. + +Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. +Statemine will only reward relayers that are delivering messages from Statemine. The Statemine sovereign account +is not used to cover rewards of bridging with some other Polkadot Parachain. + +### Multiple Relayers and Rewards + +Our goal is to incentivize running honest relayers. But we have no relayers sets, so at any time anyone may submit +message delivery transaction, hoping that the cost of this transaction will be compensated. So what if some message is +currently queued and two relayers are submitting two identical message delivery transactions at once? Without any +special means, the cost of first included transacton will be compensated and the cost of the other one won't. A honest, +but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which +may be used by other useful transactions. + +To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages! {}](../bin/runtime-common/src/lib.rs) +and [RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are +preventing bridge transactions with obsolete data from including into the block. We are rejecting following +transactions: + +- transactions, that are submitting the GRANDPA justification for the best finalized header, or one of its ancestors; + +- transactions, that are submitting the proof of the current best parachain head, or one of its ancestors; + +- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered, + the transaction is not rejected; + +- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new, + the transaction is not rejected; + +- [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326) + transactions, that have both finality and message delivery calls. All restrictions from the + [Compensating the Cost of Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions) + are applied. diff --git a/docs/polkadot-kusama-bridge.html b/docs/polkadot-kusama-bridge.html new file mode 100644 index 0000000000000..dcbae0e7b1769 --- /dev/null +++ b/docs/polkadot-kusama-bridge.html @@ -0,0 +1,67 @@ + + + + + + Polkadot <> Kusama Bridge + + +

Polkadot <> Kusama Bridge

+

+ Our bridge connects two parachains - Kusama Bridge Hub and Polkadot Bridge Hub. Messages that + are sent over bridge have XCM format and we are using existing architecture to dispatch them. + Since both Polkadot, Kusama and their parachains already have means to exchange XCM messages + within the same consensus system (HRMP, VMP, ...), it means that we are able to connect all those + chains with our bridge. +

+

+ In our architecture, the lane that is used to relay messages over the bridge is determined by + the XCM source and destinations. So e.g. bridge between Statemint and Statemine (and opposite direction) + will use the lane 00000000, bridge between some other Polkadot Parachain and some other Kusama Parachain + will use the lane 00000001 and so on. +

+
+ flowchart LR + subgraph Polkadot Consensus + polkadot(((Polkadot))) + statemint(((Statemint))) + polkadot_bh(((Polkadot Bridge Hub))) + + polkadot---statemint + polkadot---polkadot_bh + + statemint-->|Send Message Using HRMP|polkadot_bh + + polkadot_bh-->|Send Message Using HRMP|statemint + statemint-->|Dispatch the Message|statemint + end + subgraph Kusama Consensus + kusama_bh(((Kusama Bridge Hub))) + statemine(((Statemine))) + kusama(((Kusama))) + + kusama---statemine + kusama---kusama_bh + + kusama_bh-->|Send Message Using HRMP|statemine + statemine-->|Dispatch the Message|statemine + + statemine-->|Send Message Using HRMP|kusama_bh + end + + polkadot_bh<===>|Message is relayed to the Bridged Chain using lane 00000000|kusama_bh + + linkStyle 2 stroke:red + linkStyle 7 stroke:red + linkStyle 8 stroke:red + + linkStyle 3 stroke:green + linkStyle 4 stroke:green + linkStyle 9 stroke:green +
+ + + \ No newline at end of file From 4f81fe1f0b684c72f9c4f317a10db59f6dc84167 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 9 Jan 2023 13:35:35 +0300 Subject: [PATCH 0858/1210] fix nightly clippy (#1746) --- primitives/test-utils/src/keyring.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index f827c729434ec..8b7a2b3925814 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -90,5 +90,5 @@ pub fn test_keyring() -> Vec<(Account, AuthorityWeight)> { /// Get a list of "unique" accounts. pub fn accounts(len: u16) -> Vec { - (0..len).into_iter().map(Account).collect() + (0..len).map(Account).collect() } From e7b06eb110cb3eb1f4d4d63a66dc82778387c065 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 9 Jan 2023 15:29:53 +0200 Subject: [PATCH 0859/1210] Deduplicate pallet call structs used for indirect runtime calls (#1744) * Small changes * Define generic bridge pallets call structs * polkadot-core SignedExtension simplifications - we don't seem to need to pass the Call as a generic param - we can use codec(skip) instead of implementing Encode and Decode * Split BridgeHubRococo and BridgeHubWococo calls * code review fixes --- bin/runtime-common/src/messages.rs | 7 + modules/grandpa/src/lib.rs | 29 +++ modules/messages/src/lib.rs | 67 ++++++- modules/parachains/src/lib.rs | 23 ++- .../chain-bridge-hub-cumulus/Cargo.toml | 8 +- primitives/chain-bridge-hub-rococo/Cargo.toml | 2 - primitives/chain-bridge-hub-wococo/src/lib.rs | 4 - primitives/header-chain/src/lib.rs | 17 +- primitives/messages/src/lib.rs | 12 ++ primitives/parachains/src/lib.rs | 17 +- primitives/polkadot-core/src/lib.rs | 41 +--- primitives/runtime/src/calls.rs | 30 +++ primitives/runtime/src/lib.rs | 1 + relays/bin-substrate/Cargo.toml | 1 + .../rococo_headers_to_bridge_hub_wococo.rs | 2 +- .../wococo_parachains_to_bridge_hub_rococo.rs | 2 +- relays/bin-substrate/src/cli/init_bridge.rs | 2 +- relays/client-bridge-hub-rococo/Cargo.toml | 7 +- relays/client-bridge-hub-rococo/src/lib.rs | 6 +- .../src/runtime_wrapper.rs | 187 ++---------------- relays/client-bridge-hub-wococo/Cargo.toml | 12 +- .../src/runtime_wrapper.rs | 97 ++++++++- relays/client-substrate/src/chain.rs | 4 +- .../src/on_demand/headers.rs | 2 +- 24 files changed, 342 insertions(+), 238 deletions(-) create mode 100644 primitives/runtime/src/calls.rs diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 9aced1c361abd..3e69463480db0 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -692,6 +692,13 @@ pub mod target { } } +/// The `BridgeMessagesCall` used by a chain. +pub type BridgeMessagesCallOf = bp_messages::BridgeMessagesCall< + bp_runtime::AccountIdOf, + target::FromBridgedChainMessagesProof>, + source::FromBridgedChainMessagesDeliveryProof>, +>; + #[cfg(test)] mod tests { use super::*; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 926594ad79604..6853bb9cb3bb0 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -612,6 +612,7 @@ mod tests { run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime, MAX_BRIDGED_AUTHORITIES, }; + use bp_header_chain::BridgeGrandpaCall; use bp_runtime::BasicOperatingMode; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, @@ -1160,5 +1161,33 @@ mod tests { ); } + #[test] + fn test_bridge_grandpa_call_is_correctly_defined() { + let header = test_header(0); + let init_data = InitializationData { + header: Box::new(header.clone()), + authority_list: authority_list(), + set_id: 1, + operating_mode: BasicOperatingMode::Normal, + }; + let justification = make_default_justification(&header); + + let direct_initialize_call = + Call::::initialize { init_data: init_data.clone() }; + let indirect_initialize_call = BridgeGrandpaCall::::initialize(init_data); + assert_eq!(direct_initialize_call.encode(), indirect_initialize_call.encode()); + + let direct_submit_finality_proof_call = Call::::submit_finality_proof { + finality_target: Box::new(header.clone()), + justification: justification.clone(), + }; + let indirect_submit_finality_proof_call = + BridgeGrandpaCall::::submit_finality_proof(Box::new(header), justification); + assert_eq!( + direct_submit_finality_proof_call.encode(), + indirect_submit_finality_proof_call.encode() + ); + } + generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index f2d7f4c728cac..b8d79b83b4187 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -885,13 +885,13 @@ fn verify_and_decode_messages_proof::receive_messages_proof { + relayer_id_at_bridged_chain: account_id, + proof: message_proof.clone(), + messages_count: 1, + dispatch_weight: REGULAR_PAYLOAD.declared_weight, + }; + let indirect_receive_messages_proof_call = BridgeMessagesCall::< + AccountId, + TestMessagesProof, + TestMessagesDeliveryProof, + >::receive_messages_proof( + account_id, + message_proof, + 1, + REGULAR_PAYLOAD.declared_weight, + ); + assert_eq!( + direct_receive_messages_proof_call.encode(), + indirect_receive_messages_proof_call.encode() + ); + + let direct_receive_messages_delivery_proof_call = + Call::::receive_messages_delivery_proof { + proof: message_delivery_proof.clone(), + relayers_state: unrewarded_relayer_state.clone(), + }; + let indirect_receive_messages_delivery_proof_call = BridgeMessagesCall::< + AccountId, + TestMessagesProof, + TestMessagesDeliveryProof, + >::receive_messages_delivery_proof( + message_delivery_proof, + unrewarded_relayer_state, + ); + assert_eq!( + direct_receive_messages_delivery_proof_call.encode(), + indirect_receive_messages_delivery_proof_call.encode() + ); + } + generate_owned_bridge_module_tests!( MessagesOperatingMode::Basic(BasicOperatingMode::Normal), MessagesOperatingMode::Basic(BasicOperatingMode::Halted) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 3cfda0012732b..633b39329a012 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -661,7 +661,9 @@ mod tests { }; use codec::Encode; - use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; + use bp_parachains::{ + BestParaHeadHash, BridgeParachainCall, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider, + }; use bp_runtime::{ record_all_trie_keys, BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider, StorageMapKeyProvider, @@ -1471,5 +1473,24 @@ mod tests { }); } + #[test] + fn test_bridge_parachain_call_is_correctly_defined() { + let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let parachains = vec![(ParaId(2), Default::default())]; + let relay_header_id = (0, test_relay_header(0, state_root).hash()); + + let direct_submit_parachain_heads_call = Call::::submit_parachain_heads { + at_relay_block: relay_header_id, + parachains: parachains.clone(), + parachain_heads_proof: proof.clone(), + }; + let indirect_submit_parachain_heads_call = + BridgeParachainCall::submit_parachain_heads(relay_header_id, parachains, proof); + assert_eq!( + direct_submit_parachain_heads_call.encode(), + indirect_submit_parachain_heads_call.encode() + ); + } + generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); } diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index d413ce2ca4ca3..a4a8f9663df5d 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -7,8 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.10.0" - # Bridge Dependencies bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } @@ -23,15 +21,15 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot Dependencies -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } -polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [features] default = ["std"] std = [ "bp-polkadot-core/std", - "bp-messages/std", "bp-runtime/std", + "bp-messages/std", "frame-system/std", "frame-support/std", "sp-api/std", diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index 806587bb9a101..0cc57f3995906 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -7,8 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -smallvec = "1.10.0" - # Bridge Dependencies bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index e9a170223b995..e04ca3ff22806 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -16,13 +16,9 @@ //! Module with configuration which reflects BridgeHubWococo runtime setup //! (AccountId, Headers, Hashes...) -//! -//! but actually this is just reexported BridgeHubRococo stuff, because they are supposed to be -//! identical, at least uses the same parachain runtime #![cfg_attr(not(feature = "std"), no_std)] -// Re-export only what is really needed pub use bp_bridge_hub_cumulus::*; use bp_messages::*; use bp_runtime::{ diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 9924366326450..dffa7f7dc6e0e 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, StorageProofChecker}; +use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker}; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; use frame_support::PalletError; @@ -169,3 +169,18 @@ impl ConsensusLogReader for GrandpaConsensusLogReader { GrandpaConsensusLogReader::::find_authorities_change(digest).is_some() } } + +/// A minimized version of `pallet-bridge-grandpa::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeGrandpaCall { + /// `pallet-bridge-grandpa::Call::submit_finality_proof` + #[codec(index = 0)] + submit_finality_proof(Box
, justification::GrandpaJustification
), + /// `pallet-bridge-grandpa::Call::initialize` + #[codec(index = 1)] + initialize(InitializationData
), +} + +/// The `BridgeGrandpaCall` used by a chain. +pub type BridgeGrandpaCallOf = BridgeGrandpaCall>; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 8262586567f12..61d475cb46c1b 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -391,6 +391,18 @@ where relayers_rewards } +/// A minimized version of `pallet-bridge-messages::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeMessagesCall { + /// `pallet-bridge-messages::Call::receive_messages_proof` + #[codec(index = 2)] + receive_messages_proof(AccountId, MessagesProof, u32, Weight), + /// `pallet-bridge-messages::Call::receive_messages_delivery_proof` + #[codec(index = 3)] + receive_messages_delivery_proof(MessagesDeliveryProof, UnrewardedRelayersState), +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index cafe40da05636..6b38d648d79d5 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -21,8 +21,8 @@ pub use bp_header_chain::StoredHeaderData; use bp_polkadot_core::{ - parachains::{ParaHash, ParaHead, ParaId}, - BlockNumber as RelayBlockNumber, + parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}, + BlockNumber as RelayBlockNumber, Hash as RelayBlockHash, }; use bp_runtime::{ BlockNumberOf, Chain, HashOf, HeaderOf, Parachain, StorageDoubleMapKeyProvider, @@ -150,3 +150,16 @@ impl ParaStoredHeaderDataBuilder for C { None } } + +/// A minimized version of `pallet-bridge-parachains::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum BridgeParachainCall { + /// `pallet-bridge-parachains::Call::submit_parachain_heads` + #[codec(index = 0)] + submit_parachain_heads( + (RelayBlockNumber, RelayBlockHash), + Vec<(ParaId, ParaHash)>, + ParaHeadsProof, + ), +} diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 9e1f4b0452f9b..57025f2f3f697 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -20,7 +20,7 @@ use bp_messages::MessageNonce; use bp_runtime::{Chain, EncodedOrDecodedCall, StorageMapKeyProvider}; use codec::Compact; use frame_support::{ - dispatch::{DispatchClass, Dispatchable}, + dispatch::DispatchClass, parameter_types, weights::{ constants::{BlockExecutionWeight, WEIGHT_PER_SECOND}, @@ -29,7 +29,7 @@ use frame_support::{ Blake2_128Concat, RuntimeDebug, }; use frame_system::limits; -use scale_info::{StaticTypeInfo, TypeInfo}; +use scale_info::TypeInfo; use sp_core::{storage::StorageKey, Hasher as HasherT}; use sp_runtime::{ generic, @@ -194,7 +194,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< AccountAddress, EncodedOrDecodedCall, Signature, - SignedExtensions, + SignedExtensions, >; /// Account address, used by the Polkadot-like chain. @@ -210,34 +210,18 @@ pub type AdditionalSigned = ((), u32, u32, Hash, Hash, (), (), ()); /// A simplified version of signed extensions meant for producing signed transactions /// and signed payload in the client code. -#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] -pub struct SignedExtensions { +#[derive(codec::Encode, codec::Decode, PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] +pub struct SignedExtensions { encode_payload: SignedExtra, // It may be set to `None` if extensions are decoded. We are never reconstructing transactions // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to // read fields of `encode_payload`. And when resigning transaction, we're reconstructing // `SignedExtensions` from the scratch. + #[codec(skip)] additional_signed: Option, - _data: sp_std::marker::PhantomData, } -impl codec::Encode for SignedExtensions { - fn using_encoded R>(&self, f: F) -> R { - self.encode_payload.using_encoded(f) - } -} - -impl codec::Decode for SignedExtensions { - fn decode(input: &mut I) -> Result { - SignedExtra::decode(input).map(|encode_payload| SignedExtensions { - encode_payload, - additional_signed: None, - _data: Default::default(), - }) - } -} - -impl SignedExtensions { +impl SignedExtensions { pub fn new( spec_version: u32, transaction_version: u32, @@ -267,12 +251,11 @@ impl SignedExtensions { (), (), )), - _data: Default::default(), } } } -impl SignedExtensions { +impl SignedExtensions { /// Return signer nonce, used to craft transaction. pub fn nonce(&self) -> Nonce { self.encode_payload.5.into() @@ -284,15 +267,11 @@ impl SignedExtensions { } } -impl sp_runtime::traits::SignedExtension for SignedExtensions -where - Call: codec::Codec + sp_std::fmt::Debug + Sync + Send + Clone + Eq + PartialEq + StaticTypeInfo, - Call: Dispatchable, -{ +impl sp_runtime::traits::SignedExtension for SignedExtensions { const IDENTIFIER: &'static str = "Not needed."; type AccountId = AccountId; - type Call = Call; + type Call = (); type AdditionalSigned = AdditionalSigned; type Pre = (); diff --git a/primitives/runtime/src/calls.rs b/primitives/runtime/src/calls.rs new file mode 100644 index 0000000000000..194c2126ba3b2 --- /dev/null +++ b/primitives/runtime/src/calls.rs @@ -0,0 +1,30 @@ +// Copyright 2019-2023 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 . + +//! Basic runtime calls. + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_std::vec::Vec; + +/// A minimized version of `frame-system::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum SystemCall { + /// `frame-system::Call::remark` + #[codec(index = 1)] + remark(Vec), +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 340088a85b122..4c3fb152fa736 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -47,6 +47,7 @@ pub use storage_types::BoundedStorageValue; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; +pub mod calls; pub mod messages; mod chain; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index de1807cdc9708..c88b930cbb07b 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -26,6 +26,7 @@ bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } +bp-parachains = { path = "../../primitives/parachains" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs index 2fac858336d92..6cdae2b212b59 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs @@ -33,7 +33,7 @@ substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( RococoFinalityToBridgeHubWococo, RococoFinalityToBridgeHubWococoCallBuilder, relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa, - relay_bridge_hub_wococo_client::runtime::BridgeGrandpaRococoCall::submit_finality_proof + relay_bridge_hub_wococo_client::runtime::BridgeRococoGrandpaCall::submit_finality_proof ); #[async_trait] diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs index f821af1a0cfd9..f79979ff8328b 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -51,7 +51,7 @@ impl SubmitParachainHeadsCallBuilder parachain_heads_proof: ParaHeadsProof, ) -> CallOf { relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoParachain( - relay_bridge_hub_rococo_client::runtime::BridgeParachainCall::submit_parachain_heads( + bp_parachains::BridgeParachainCall::submit_parachain_heads( (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index cadc6be4df23f..322cca1bef52c 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -176,7 +176,7 @@ impl BridgeInitializer for RococoToBridgeHubWococoCliBridge { init_data: >::InitializationData, ) -> ::Call { relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa( - relay_bridge_hub_wococo_client::runtime::BridgeGrandpaRococoCall::initialize(init_data), + relay_bridge_hub_wococo_client::runtime::BridgeRococoGrandpaCall::initialize(init_data), ) } } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 4a01d81e7771f..6872c59f7602b 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -16,14 +16,13 @@ bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-parachains = { path = "../../primitives/parachains" } +bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } +bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } - -[dev-dependencies] -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 7e9047e32ce59..08a9e688487e0 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -132,8 +132,10 @@ mod tests { #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) - .into(), + call: runtime::Call::System(bp_runtime::calls::SystemCall::remark( + b"Hello world!".to_vec(), + )) + .into(), nonce: 777, tip: 888, era: TransactionEra::immortal(), diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index 0571f82f5a6cb..d973bb3bea576 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -18,201 +18,48 @@ //! Types that are specific to the BridgeHubRococo runtime. -use bp_polkadot_core::PolkadotLike; use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_messages::UnrewardedRelayersState; -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use bp_runtime::Chain; +pub use bp_header_chain::BridgeGrandpaCallOf; +pub use bp_parachains::BridgeParachainCall; +pub use bp_runtime::calls::SystemCall; +pub use bridge_runtime_common::messages::BridgeMessagesCallOf; // TODO:check-parameter - check SignedExtension /// Unchecked BridgeHubRococo extrinsic. pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; -/// Rococo Runtime `Call` enum. +// The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. +pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; +// The indirect pallet call used to sync `BridgeHubWococo` messages to `BHRococo`. +pub type BridgeWococoMessagesCall = BridgeMessagesCallOf; + +/// `BridgeHubRococo` Runtime `Call` enum. /// -/// The enum represents a subset of possible `Call`s we can send to Rococo chain. +/// The enum represents a subset of possible `Call`s we can send to `BridgeHubRococo` chain. /// Ideally this code would be auto-generated from metadata, because we want to /// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. /// -/// All entries here (like pretty much in the entire file) must be kept in sync with Rococo -/// `construct_runtime`, so that we maintain SCALE-compatibility. +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `BridgeHubRococo` `construct_runtime`, so that we maintain SCALE-compatibility. /// -/// // TODO:check-parameter -> change bko-bridge-rococo-wococo when merged to master in cumulus -/// See: [link](https://github.com/paritytech/cumulus/blob/bko-bridge-rococo-wococo/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs) +/// // TODO:check-parameter -> change bridge-hub-rococo-wococo when merged to master in cumulus +/// See: [link](https://github.com/paritytech/cumulus/blob/bridge-hub-rococo-wococo/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { - /// System pallet. + #[cfg(test)] #[codec(index = 0)] System(SystemCall), + /// Wococo bridge pallet. #[codec(index = 41)] BridgeWococoGrandpa(BridgeWococoGrandpaCall), - /// Rococo bridge pallet. - #[codec(index = 43)] - BridgeRococoGrandpa(BridgeRococoGrandpaCall), - /// Wococo parachain bridge pallet. #[codec(index = 42)] BridgeWococoParachain(BridgeParachainCall), - /// Rococo parachain bridge pallet. - #[codec(index = 44)] - BridgeRococoParachain(BridgeParachainCall), - /// Wococo messages bridge pallet. #[codec(index = 46)] BridgeWococoMessages(BridgeWococoMessagesCall), - /// Rococo messages bridge pallet. - #[codec(index = 45)] - BridgeRococoMessages(BridgeRococoMessagesCall), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum SystemCall { - #[codec(index = 1)] - remark(Vec), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeWococoGrandpaCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeRococoGrandpaCall { - #[codec(index = 0)] - submit_finality_proof( - Box<::Header>, - bp_header_chain::justification::GrandpaJustification<::Header>, - ), - #[codec(index = 1)] - initialize(bp_header_chain::InitializationData<::Header>), -} - -pub type RelayBlockHash = bp_polkadot_core::Hash; -pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeParachainCall { - #[codec(index = 0)] - submit_parachain_heads( - (RelayBlockNumber, RelayBlockHash), - Vec<(ParaId, ParaHash)>, - ParaHeadsProof, - ), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeWococoMessagesCall { - #[codec(index = 2)] - receive_messages_proof( - relay_substrate_client::AccountIdOf, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< - relay_substrate_client::HashOf, - >, - u32, - bp_messages::Weight, - ), - - #[codec(index = 3)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - relay_substrate_client::HashOf, - >, - UnrewardedRelayersState, - ), -} - -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -#[allow(non_camel_case_types)] -pub enum BridgeRococoMessagesCall { - #[codec(index = 2)] - receive_messages_proof( - relay_substrate_client::AccountIdOf, - bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< - relay_substrate_client::HashOf, - >, - u32, - bp_messages::Weight, - ), - - #[codec(index = 3)] - receive_messages_delivery_proof( - bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - relay_substrate_client::HashOf, - >, - UnrewardedRelayersState, - ), -} - -impl sp_runtime::traits::Dispatchable for Call { - type RuntimeOrigin = (); - type Config = (); - type Info = (); - type PostInfo = (); - - fn dispatch( - self, - _origin: Self::RuntimeOrigin, - ) -> sp_runtime::DispatchResultWithInfo { - unimplemented!("The Call is not expected to be dispatched.") - } -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_runtime::BasicOperatingMode; - use sp_core::hexdisplay::HexDisplay; - use sp_finality_grandpa::AuthorityList; - use sp_runtime::traits::Header; - use std::str::FromStr; - - pub type RelayBlockHasher = bp_polkadot_core::Hasher; - pub type RelayBlockHeader = sp_runtime::generic::Header; - - #[test] - fn encode_decode_calls() { - let header = RelayBlockHeader::new( - 75, - bp_polkadot_core::Hash::from_str( - "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", - ) - .expect("invalid value"), - Default::default(), - ); - let init_data = bp_header_chain::InitializationData { - header: Box::new(header), - authority_list: AuthorityList::default(), - set_id: 6, - operating_mode: BasicOperatingMode::Normal, - }; - let call = BridgeRococoGrandpaCall::initialize(init_data); - let tx = Call::BridgeRococoGrandpa(call); - - // encode call as hex string - let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); - assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); - } } diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index fa28dfde202aa..7c9b90975d6ba 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -12,11 +12,21 @@ relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies +bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } +bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } -relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } +bp-parachains = { path = "../../primitives/parachains" } +bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } + +bridge-runtime-common = { path = "../../bin/runtime-common" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[dev-dependencies] +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 05176af471a9b..c7a92ef9ba445 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -16,11 +16,94 @@ //! Types that are specific to the BridgeHubWococo runtime. -// We reuse everything from rococo runtime wrapper -pub type Call = relay_bridge_hub_rococo_client::runtime::Call; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_header_chain::BridgeGrandpaCallOf; +pub use bp_parachains::BridgeParachainCall; +pub use bp_runtime::calls::SystemCall; +pub use bridge_runtime_common::messages::BridgeMessagesCallOf; + +// TODO:check-parameter - check SignedExtension +/// Unchecked BridgeHubWococo extrinsic. pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; -pub type BridgeGrandpaRococoCall = relay_bridge_hub_rococo_client::runtime::BridgeRococoGrandpaCall; -pub type BridgeParachainCall = relay_bridge_hub_rococo_client::runtime::BridgeParachainCall; -pub type BridgeRococoMessagesCall = - relay_bridge_hub_rococo_client::runtime::BridgeRococoMessagesCall; -pub type SystemCall = relay_bridge_hub_rococo_client::runtime::SystemCall; + +// The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. +pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; +// The indirect pallet call used to sync `BridgeHubRococo` messages to `BridgeHubWococo`. +pub type BridgeRococoMessagesCall = BridgeMessagesCallOf; + +/// `BridgeHubWococo` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `BridgeHubWococo` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `BridgeHubWococo` `construct_runtime`, so that we maintain SCALE-compatibility. +/// +/// TODO:check-parameter -> change bridge-hub-rococo-wococo when merged to master in cumulus +/// See: [link](https://github.com/paritytech/cumulus/blob/bridge-hub-rococo-wococo/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs) +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + #[cfg(test)] + #[codec(index = 0)] + System(SystemCall), + + /// Rococo bridge pallet. + #[codec(index = 43)] + BridgeRococoGrandpa(BridgeRococoGrandpaCall), + /// Rococo parachain bridge pallet. + #[codec(index = 44)] + BridgeRococoParachain(BridgeParachainCall), + /// Rococo messages bridge pallet. + #[codec(index = 45)] + BridgeRococoMessages(BridgeRococoMessagesCall), +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_runtime::BasicOperatingMode; + use sp_core::hexdisplay::HexDisplay; + use sp_finality_grandpa::AuthorityList; + use sp_runtime::traits::Header; + use std::str::FromStr; + + pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; + pub type RelayBlockHasher = bp_polkadot_core::Hasher; + pub type RelayBlockHeader = sp_runtime::generic::Header; + + #[test] + fn encode_decode_calls() { + let header = RelayBlockHeader::new( + 75, + bp_polkadot_core::Hash::from_str( + "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", + ) + .expect("invalid value"), + Default::default(), + ); + let init_data = bp_header_chain::InitializationData { + header: Box::new(header), + authority_list: AuthorityList::default(), + set_id: 6, + operating_mode: BasicOperatingMode::Normal, + }; + let call = BridgeRococoGrandpaCall::initialize(init_data); + let tx = Call::BridgeRococoGrandpa(call); + + // encode call as hex string + let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); + assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); + } +} diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index c199540cbfb31..db08fc1f98ce1 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -26,7 +26,7 @@ use sc_transaction_pool_api::TransactionStatus; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, - traits::{Block as BlockT, Dispatchable, Member}, + traits::{Block as BlockT, Member}, ConsensusEngineId, EncodedJustification, }; use std::{fmt::Debug, time::Duration}; @@ -56,7 +56,7 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Clone + Codec + Dispatchable + Debug + Send; + type Call: Clone + Codec + Debug + Send; } /// Substrate-based relay chain that supports parachains. diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 465b03c04a4a4..75b402aff8732 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -316,7 +316,7 @@ async fn background_task( stall_timeout, only_mandatory_headers, }, - metrics_params.clone().unwrap_or_else(|| MetricsParams::disabled()), + metrics_params.clone().unwrap_or_else(MetricsParams::disabled), futures::future::pending(), ) .fuse(), From 71178c5687d6229778dccce3db9dd0cecdcc8da0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 9 Jan 2023 15:57:05 +0200 Subject: [PATCH 0860/1210] Remove TODO (#1749) --- relays/client-bridge-hub-rococo/src/runtime_wrapper.rs | 3 --- relays/client-bridge-hub-wococo/src/runtime_wrapper.rs | 3 --- 2 files changed, 6 deletions(-) diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index d973bb3bea576..e7136117360a8 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -43,9 +43,6 @@ pub type BridgeWococoMessagesCall = BridgeMessagesCallOf change bridge-hub-rococo-wococo when merged to master in cumulus -/// See: [link](https://github.com/paritytech/cumulus/blob/bridge-hub-rococo-wococo/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index c7a92ef9ba445..5c11d8c7ebf79 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -41,9 +41,6 @@ pub type BridgeRococoMessagesCall = BridgeMessagesCallOf change bridge-hub-rococo-wococo when merged to master in cumulus -/// See: [link](https://github.com/paritytech/cumulus/blob/bridge-hub-rococo-wococo/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs) #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { From ab30ff9a3d5233930947151c9cd07783d49e9e9f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 10 Jan 2023 10:22:48 +0300 Subject: [PATCH 0861/1210] fix nightly clippy again (#1752) --- bin/millau/node/src/service.rs | 2 +- relays/messages/src/message_race_delivery.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 20662d17bb9ca..e86d9e847a02b 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -329,7 +329,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), - rpc_builder: rpc_extensions_builder.clone(), + rpc_builder: rpc_extensions_builder, backend: backend.clone(), system_rpc_tx, config, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 0179a696bc7ff..0d957fd8b7169 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -612,7 +612,6 @@ mod tests { }, ) }) - .into_iter() .collect(), confirmed_nonce: Some(confirmed_nonce), } From 3d4477a678db2a534eac0b1b341cc0254901f8cd Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 10 Jan 2023 17:05:00 +0200 Subject: [PATCH 0862/1210] Use indirect runtime calls for RialtoParachain (#1753) * Use indirect runtime calls for RialtoParachain * Code review fixes --- primitives/runtime/src/lib.rs | 1 - relays/bin-substrate/Cargo.toml | 1 - ...ub_rococo_messages_to_bridge_hub_wococo.rs | 1 - ...ub_wococo_messages_to_bridge_hub_rococo.rs | 1 - .../millau_headers_to_rialto_parachain.rs | 16 +++-- .../millau_messages_to_rialto_parachain.rs | 17 +++-- .../src/chains/rialto_parachain.rs | 16 ++--- .../rialto_parachain_messages_to_millau.rs | 19 +++--- relays/bin-substrate/src/cli/init_bridge.rs | 16 ++--- relays/client-bridge-hub-rococo/Cargo.toml | 1 + relays/client-bridge-hub-rococo/src/lib.rs | 2 +- .../src/runtime_wrapper.rs | 2 +- .../src/runtime_wrapper.rs | 2 +- relays/client-rialto-parachain/Cargo.toml | 12 +++- relays/client-rialto-parachain/src/lib.rs | 68 +++++++------------ .../src/runtime_wrapper.rs | 57 ++++++++++++++++ relays/client-substrate/Cargo.toml | 6 ++ .../client-substrate}/src/calls.rs | 22 +++++- relays/client-substrate/src/lib.rs | 1 + .../lib-substrate-relay/src/messages_lane.rs | 2 +- 20 files changed, 168 insertions(+), 95 deletions(-) create mode 100644 relays/client-rialto-parachain/src/runtime_wrapper.rs rename {primitives/runtime => relays/client-substrate}/src/calls.rs (62%) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 4c3fb152fa736..340088a85b122 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -47,7 +47,6 @@ pub use storage_types::BoundedStorageValue; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; -pub mod calls; pub mod messages; mod chain; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index c88b930cbb07b..0ab3bd5634f1a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -51,7 +51,6 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } relay-wococo-client = { path = "../client-wococo" } -rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } rialto-runtime = { path = "../../bin/rialto/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index 339be92063e21..8422569d009af 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -17,7 +17,6 @@ //! BridgeHubRococo-to-BridgeHubWococo messages sync entrypoint. use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; -use bp_messages::Weight; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_wococo_client::BridgeHubWococo; use substrate_relay_helper::messages_lane::SubstrateMessageLane; diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index 3bb2aabde06ba..96df83cd0b217 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -17,7 +17,6 @@ //! BridgeHubWococo-to-BridgeHubRococo messages sync entrypoint. use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; -use bp_messages::Weight; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_wococo_client::BridgeHubWococo; use substrate_relay_helper::messages_lane::SubstrateMessageLane; diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs index b830ce7fcc4e4..6496167cf7ca9 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -36,10 +36,16 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, - SubstrateFinalitySyncPipeline, + engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, }; +substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( + MillauFinalityToRialtoParachain, + MillauFinalityToRialtoParachainCallBuilder, + relay_rialto_parachain_client::runtime::Call::BridgeMillauGrandpa, + relay_rialto_parachain_client::runtime::BridgeMillauGrandpaCall::submit_finality_proof +); + /// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] pub struct MillauFinalityToRialtoParachain; @@ -49,11 +55,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { type TargetChain = relay_rialto_parachain_client::RialtoParachain; type FinalityEngine = GrandpaFinalityEngine; - type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< - Self, - rialto_parachain_runtime::Runtime, - rialto_parachain_runtime::MillauGrandpaInstance, - >; + type SubmitFinalityProofCallBuilder = MillauFinalityToRialtoParachainCallBuilder; } //// `Millau` to `RialtoParachain` bridge definition. diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index 0b1d3afb797ce..817d0098d9b76 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -19,10 +19,16 @@ use relay_millau_client::Millau; use relay_rialto_parachain_client::RialtoParachain; use substrate_relay_helper::messages_lane::{ - DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, - SubstrateMessageLane, + DirectReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, }; +substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( + MillauMessagesToRialtoParachain, + MillauMessagesToRialtoParachainReceiveMessagesProofCallBuilder, + relay_rialto_parachain_client::runtime::Call::BridgeMillauMessages, + relay_rialto_parachain_client::runtime::BridgeMillauMessagesCall::receive_messages_proof +); + /// Description of Millau -> RialtoParachain messages bridge. #[derive(Clone, Debug)] pub struct MillauMessagesToRialtoParachain; @@ -31,11 +37,8 @@ impl SubstrateMessageLane for MillauMessagesToRialtoParachain { type SourceChain = Millau; type TargetChain = RialtoParachain; - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< - Self, - rialto_parachain_runtime::Runtime, - rialto_parachain_runtime::WithMillauMessagesInstance, - >; + type ReceiveMessagesProofCallBuilder = + MillauMessagesToRialtoParachainReceiveMessagesProofCallBuilder; type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< Self, millau_runtime::Runtime, diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 7105dc2b7d7c8..4d1e1b02e3741 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -18,7 +18,9 @@ use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; +use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; +use relay_substrate_client::calls::XcmCall; use sp_version::RuntimeVersion; use xcm::latest::prelude::*; @@ -29,23 +31,19 @@ impl CliEncodeMessage for RialtoParachain { ) -> anyhow::Result> { let dest = match bridge_instance_index { bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => - (Parent, X1(GlobalConsensus(rialto_parachain_runtime::MillauNetwork::get()))), + (Parent, X1(GlobalConsensus(CustomNetworkId::Millau.as_network_id()))), _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", bridge_instance_index ), }; - Ok(rialto_parachain_runtime::RuntimeCall::PolkadotXcm( - rialto_parachain_runtime::XcmCall::send { - dest: Box::new(dest.into()), - message: Box::new(message), - }, - ) - .into()) + let xcm_call = XcmCall::send(Box::new(dest.into()), Box::new(message)); + + Ok(relay_rialto_parachain_client::runtime::Call::PolkadotXcm(xcm_call).into()) } } impl CliChain for RialtoParachain { - const RUNTIME_VERSION: Option = Some(rialto_parachain_runtime::VERSION); + const RUNTIME_VERSION: Option = None; } diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index 74db3738e6b00..0000a0a754a53 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -19,13 +19,17 @@ use relay_millau_client::Millau; use relay_rialto_parachain_client::RialtoParachain; use substrate_relay_helper::{ - messages_lane::{ - DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, - SubstrateMessageLane, - }, + messages_lane::{DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane}, UtilityPalletBatchCallBuilder, }; +substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( + RialtoParachainMessagesToMillau, + RialtoParachainMessagesToMillauReceiveMessagesDeliveryProofCallBuilder, + relay_rialto_parachain_client::runtime::Call::BridgeMillauMessages, + relay_rialto_parachain_client::runtime::BridgeMillauMessagesCall::receive_messages_delivery_proof +); + /// Description of RialtoParachain -> Millau messages bridge. #[derive(Clone, Debug)] pub struct RialtoParachainMessagesToMillau; @@ -39,11 +43,8 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { millau_runtime::Runtime, millau_runtime::WithRialtoParachainMessagesInstance, >; - type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< - Self, - rialto_parachain_runtime::Runtime, - rialto_parachain_runtime::WithMillauMessagesInstance, - >; + type ReceiveMessagesDeliveryProofCallBuilder = + RialtoParachainMessagesToMillauReceiveMessagesDeliveryProofCallBuilder; type SourceBatchCallBuilder = (); type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 322cca1bef52c..8f4080b338cee 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -29,7 +29,7 @@ use crate::{ cli::{bridge::CliBridgeBase, chain_schema::*}, }; use bp_runtime::Chain as ChainBase; -use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; +use relay_substrate_client::{calls::SudoCall, AccountKeyPairOf, Chain, UnsignedTransaction}; use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -123,13 +123,13 @@ impl BridgeInitializer for MillauToRialtoParachainCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - let initialize_call = rialto_parachain_runtime::BridgeGrandpaCall::< - rialto_parachain_runtime::Runtime, - rialto_parachain_runtime::MillauGrandpaInstance, - >::initialize { - init_data, - }; - rialto_parachain_runtime::SudoCall::sudo { call: Box::new(initialize_call.into()) }.into() + use relay_rialto_parachain_client::runtime; + + let initialize_call = runtime::Call::BridgeMillauGrandpa( + runtime::BridgeMillauGrandpaCall::initialize(init_data), + ); + let sudo_call = SudoCall::sudo(Box::new(initialize_call)); + runtime::Call::Sudo(sudo_call) } } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 6872c59f7602b..e650ba9da7679 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -22,6 +22,7 @@ bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } + # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 08a9e688487e0..653c5af2c5e3f 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -132,7 +132,7 @@ mod tests { #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(bp_runtime::calls::SystemCall::remark( + call: runtime::Call::System(relay_substrate_client::calls::SystemCall::remark( b"Hello world!".to_vec(), )) .into(), diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index e7136117360a8..2c50128201bc1 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -23,8 +23,8 @@ use scale_info::TypeInfo; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; -pub use bp_runtime::calls::SystemCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; +pub use relay_substrate_client::calls::SystemCall; // TODO:check-parameter - check SignedExtension /// Unchecked BridgeHubRococo extrinsic. diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 5c11d8c7ebf79..0d73a91029df5 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -21,8 +21,8 @@ use scale_info::TypeInfo; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; -pub use bp_runtime::calls::SystemCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; +pub use relay_substrate_client::calls::SystemCall; // TODO:check-parameter - check SignedExtension /// Unchecked BridgeHubWococo extrinsic. diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 915d0e786cc75..8ecc915f95347 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -7,14 +7,20 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies +bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } +bp-millau = { path = "../../primitives/chain-millau" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } -rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } +bp-runtime = { path = "../../primitives/runtime" } + +bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } # Substrate Dependencies diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 16abd6e880881..c3fb0da741877 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -16,6 +16,8 @@ //! Types used to connect to the Rialto-Substrate chain. +pub mod runtime_wrapper; + use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -23,12 +25,13 @@ use relay_substrate_client::{ SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use std::time::Duration; -/// Rialto header id. -pub type HeaderId = - relay_utils::HeaderId; +pub use runtime_wrapper as runtime; + +/// The address format for describing accounts. +pub type Address = MultiAddress; /// Rialto parachain definition #[derive(Debug, Clone, Copy)] @@ -46,18 +49,13 @@ impl Chain for RialtoParachain { bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - type SignedBlock = rialto_parachain_runtime::SignedBlock; - type Call = rialto_parachain_runtime::RuntimeCall; + type SignedBlock = bp_polkadot_core::SignedBlock; + type Call = runtime::Call; } impl ChainWithBalances for RialtoParachain { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - use frame_support::storage::generator::StorageMap; - StorageKey( - frame_system::Account::::storage_map_final_key( - account_id, - ), - ) + bp_polkadot_core::AccountInfoStorageMapKeyProvider::final_key(account_id) } } @@ -77,45 +75,30 @@ impl ChainWithMessages for RialtoParachain { impl ChainWithTransactions for RialtoParachain { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic; + type SignedTransaction = bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, unsigned: UnsignedTransaction, ) -> Result { - let raw_payload = SignedPayload::from_raw( + let raw_payload = SignedPayload::new( unsigned.call, - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from( - unsigned.era.frame_era(), - ), - frame_system::CheckNonce::::from(unsigned.nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::< - rialto_parachain_runtime::Runtime, - >::from(unsigned.tip), - ), - ( - (), + bp_polkadot_core::SignedExtensions::new( param.spec_version, param.transaction_version, + unsigned.era, param.genesis_hash, - unsigned.era.signed_payload(param.genesis_hash), - (), - (), - (), + unsigned.nonce, + unsigned.tip, ), - ); + )?; + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(rialto_parachain_runtime::UncheckedExtrinsic::new_signed( - call.into_decoded()?, + Ok(Self::SignedTransaction::new_signed( + call, signer.into_account().into(), signature.into(), extra, @@ -129,14 +112,13 @@ impl ChainWithTransactions for RialtoParachain { fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { tx.signature .as_ref() - .map(|(address, _, _)| { - *address == rialto_parachain_runtime::Address::Id(signer.public().into()) - }) + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) .unwrap_or(false) } - fn parse_transaction(_tx: Self::SignedTransaction) -> Option> { - None + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) } } @@ -144,4 +126,4 @@ impl ChainWithTransactions for RialtoParachain { pub type SigningParams = sp_core::sr25519::Pair; /// RialtoParachain header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; +pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/client-rialto-parachain/src/runtime_wrapper.rs b/relays/client-rialto-parachain/src/runtime_wrapper.rs new file mode 100644 index 0000000000000..b595d145d012d --- /dev/null +++ b/relays/client-rialto-parachain/src/runtime_wrapper.rs @@ -0,0 +1,57 @@ +// 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 . + +//! Types that are specific to the `RialtoParachain` runtime. Normally we could use the full +//! `RialtoParachain` runtime here, since it is constructed in this repo and we have access to it. +//! However we use a wrapped runtime instead in order to test the indirect runtime calls +//! functionality. + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +use bp_header_chain::BridgeGrandpaCallOf; +use bridge_runtime_common::messages::BridgeMessagesCallOf; +use relay_substrate_client::calls::{SudoCall, XcmCall}; + +// The indirect pallet call used to sync `Millau` GRANDPA finality to `RialtoParachain`. +pub type BridgeMillauGrandpaCall = BridgeGrandpaCallOf; +// The indirect pallet call used to sync `Millau` messages to `RialtoParachain`. +pub type BridgeMillauMessagesCall = BridgeMessagesCallOf; + +/// `RialtoParachain` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `RialtoParachain` chain. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `RialtoParachain` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// `Sudo` pallet. + #[codec(index = 2)] + Sudo(SudoCall), + + /// `Xcm` pallet. + #[codec(index = 51)] + PolkadotXcm(XcmCall), + + /// Millau GRANDPA bridge pallet. + #[codec(index = 55)] + BridgeMillauGrandpa(BridgeMillauGrandpaCall), + /// Millau messages bridge pallet. + #[codec(index = 56)] + BridgeMillauMessages(BridgeMillauMessagesCall), +} diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 29b910c11bd7e..f9760a32603e9 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,6 +14,7 @@ jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.7" +scale-info = { version = "2.1.1", features = ["derive"] } tokio = { version = "1.8", features = ["rt-multi-thread"] } thiserror = "1.0.26" @@ -42,10 +43,15 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } +# Polkadot Dependencies + +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } + [features] default = [] test-helpers = [] diff --git a/primitives/runtime/src/calls.rs b/relays/client-substrate/src/calls.rs similarity index 62% rename from primitives/runtime/src/calls.rs rename to relays/client-substrate/src/calls.rs index 194c2126ba3b2..89fc49a209aeb 100644 --- a/primitives/runtime/src/calls.rs +++ b/relays/client-substrate/src/calls.rs @@ -18,7 +18,9 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_std::vec::Vec; +use sp_std::{boxed::Box, vec::Vec}; + +use xcm::{VersionedMultiLocation, VersionedXcm}; /// A minimized version of `frame-system::Call` that can be used without a runtime. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -28,3 +30,21 @@ pub enum SystemCall { #[codec(index = 1)] remark(Vec), } + +/// A minimized version of `pallet-sudo::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum SudoCall { + /// `pallet-sudo::Call::sudo` + #[codec(index = 0)] + sudo(Box), +} + +/// A minimized version of `pallet-xcm::Call`, that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum XcmCall { + /// `pallet-xcm::Call::send` + #[codec(index = 0)] + send(Box, Box>), +} diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index e576aca1119d8..599d9c658b56f 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -25,6 +25,7 @@ mod rpc; mod sync_header; mod transaction_tracker; +pub mod calls; pub mod guard; pub mod metrics; pub mod test_chain; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 22ff3e7215b68..61ea72853f43c 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -330,7 +330,7 @@ macro_rules! generate_mocked_receive_message_proof_call_builder { <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain >, messages_count: u32, - dispatch_weight: Weight, + dispatch_weight: bp_messages::Weight, _trace_call: bool, ) -> relay_substrate_client::CallOf< <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain From a313f95969a41f66cf5b4657d07370cbfb09e309 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 11 Jan 2023 09:39:39 +0300 Subject: [PATCH 0863/1210] Expose relay version metric (#1750) * expose relay version metric * spelling * and clippy * clippy * typo * use version directly and determine git commit * typos and leftovers --- relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/cli/mod.rs | 30 ++++++++++---- relays/bin-substrate/src/cli/relay_headers.rs | 3 +- .../src/cli/relay_headers_and_messages/mod.rs | 2 +- .../bin-substrate/src/cli/relay_messages.rs | 2 +- .../bin-substrate/src/cli/relay_parachains.rs | 3 +- relays/utils/src/metrics.rs | 39 ++++++++++++++++--- 7 files changed, 62 insertions(+), 18 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 0ab3bd5634f1a..a22bf12632c59 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -15,6 +15,7 @@ hex = "0.4" log = "0.4.17" num-format = "0.4" num-traits = "0.2" +rbtag = "0.3" structopt = "0.3" signal-hook = "0.3.14" signal-hook-async-std = "0.2.2" diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index e049a050c4772..9081a397b6b41 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -21,6 +21,7 @@ use std::convert::TryInto; use async_std::prelude::*; use codec::{Decode, Encode}; use futures::{select, FutureExt}; +use rbtag::BuildInfo; use signal_hook::consts::*; use signal_hook_async_std::Signals; use structopt::{clap::arg_enum, StructOpt}; @@ -254,17 +255,30 @@ pub struct PrometheusParams { pub prometheus_port: u16, } -impl From for relay_utils::metrics::MetricsParams { - fn from(cli_params: PrometheusParams) -> relay_utils::metrics::MetricsParams { - if !cli_params.no_prometheus { +/// Struct to get git commit info and build time. +#[derive(BuildInfo)] +struct SubstrateRelayBuildInfo; + +impl PrometheusParams { + /// Tries to convert CLI metrics params into metrics params, used by the relay. + pub fn into_metrics_params(self) -> anyhow::Result { + let metrics_address = if !self.no_prometheus { Some(relay_utils::metrics::MetricsAddress { - host: cli_params.prometheus_host, - port: cli_params.prometheus_port, + host: self.prometheus_host, + port: self.prometheus_port, }) - .into() } else { - None.into() - } + None + }; + + let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); + let relay_commit = SubstrateRelayBuildInfo.get_build_commit(); + relay_utils::metrics::MetricsParams::new( + metrics_address, + relay_version.into(), + relay_commit.into(), + ) + .map_err(|e| anyhow::format_err!("{:?}", e)) } } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 37b805d720b5d..239ab8d62fdd0 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -77,7 +77,8 @@ where let target_transactions_mortality = data.target_sign.target_transactions_mortality; let target_sign = data.target_sign.to_keypair::()?; - let metrics_params: relay_utils::metrics::MetricsParams = data.prometheus_params.into(); + let metrics_params: relay_utils::metrics::MetricsParams = + data.prometheus_params.into_metrics_params()?; GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; let target_transactions_params = substrate_relay_helper::TransactionParams { diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index fd8a032066d69..ea6d6ad9f51a2 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -110,7 +110,7 @@ impl, ) -> anyhow::Result { // Create metrics registry. - let metrics_params = shared.prometheus_params.clone().into(); + let metrics_params = shared.prometheus_params.clone().into_metrics_params()?; let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); Ok(Self { shared, left, right, metrics_params }) diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 6af042670e74d..e0250ef1e472b 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -83,7 +83,7 @@ where source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: data.lane.into(), - metrics_params: data.prometheus_params.into(), + metrics_params: data.prometheus_params.into_metrics_params()?, }) .await .map_err(|e| anyhow::format_err!("{}", e)) diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 1a0bba3fd1f2c..1234b3a3309df 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -98,7 +98,8 @@ where target_transaction_params, ); - let metrics_params: relay_utils::metrics::MetricsParams = data.prometheus_params.into(); + let metrics_params: relay_utils::metrics::MetricsParams = + data.prometheus_params.into_metrics_params()?; GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; parachains_relay::parachains_loop::run( diff --git a/relays/utils/src/metrics.rs b/relays/utils/src/metrics.rs index fa7a79a71c144..2e6c8236da454 100644 --- a/relays/utils/src/metrics.rs +++ b/relays/utils/src/metrics.rs @@ -99,6 +99,39 @@ impl Default for MetricsAddress { } impl MetricsParams { + /// Creates metrics params from metrics address. + pub fn new( + address: Option, + relay_version: String, + relay_commit: String, + ) -> Result { + const BUILD_INFO_METRIC: &str = "substrate_relay_build_info"; + + let registry = Registry::new(); + register( + Gauge::::with_opts( + Opts::new( + BUILD_INFO_METRIC, + "A metric with a constant '1' value labeled by version", + ) + .const_label("version", &relay_version) + .const_label("commit", &relay_commit), + )?, + ®istry, + )? + .set(1); + + log::info!( + target: "bridge", + "Exposed {} metric: version={} commit={}", + BUILD_INFO_METRIC, + relay_version, + relay_commit, + ); + + Ok(MetricsParams { address, registry }) + } + /// Creates metrics params so that metrics are not exposed. pub fn disabled() -> Self { MetricsParams { address: None, registry: Registry::new() } @@ -112,12 +145,6 @@ impl MetricsParams { } } -impl From> for MetricsParams { - fn from(address: Option) -> Self { - MetricsParams { address, registry: Registry::new() } - } -} - /// Returns metric name optionally prefixed with given prefix. pub fn metric_name(prefix: Option<&str>, name: &str) -> String { if let Some(prefix) = prefix { From b6878c4341cca33f1e7818394c923cc00864cea0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 11 Jan 2023 09:45:22 +0200 Subject: [PATCH 0864/1210] Set `R/WococoBridgeHub` bundle runtime version (#1756) * Define SimpleRuntimeVersion * Set R/WococoBridgeHub bundle runtime version --- relays/bin-substrate/src/chains/millau.rs | 5 ++- relays/bin-substrate/src/chains/rialto.rs | 5 ++- .../src/chains/rialto_parachain.rs | 5 +-- relays/bin-substrate/src/chains/rococo.rs | 7 ++-- .../rococo_headers_to_bridge_hub_wococo.rs | 2 +- relays/bin-substrate/src/chains/westend.rs | 6 +-- relays/bin-substrate/src/chains/wococo.rs | 7 ++-- .../wococo_headers_to_bridge_hub_rococo.rs | 2 +- relays/bin-substrate/src/cli/chain_schema.rs | 19 ++++----- relays/bin-substrate/src/cli/mod.rs | 3 +- .../src/cli/resubmit_transactions.rs | 10 ++--- relays/client-substrate/src/client.rs | 41 +++++++++++++------ relays/client-substrate/src/lib.rs | 4 +- .../src/finality/guards.rs | 2 +- 14 files changed, 68 insertions(+), 50 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index f318274750df9..ca9a32a48a54c 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -20,7 +20,7 @@ use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_rialto_parachain::RIALTO_PARACHAIN_ID; use bp_runtime::EncodedOrDecodedCall; use relay_millau_client::Millau; -use sp_version::RuntimeVersion; +use relay_substrate_client::SimpleRuntimeVersion; use xcm::latest::prelude::*; impl CliEncodeMessage for Millau { @@ -53,5 +53,6 @@ impl CliEncodeMessage for Millau { } impl CliChain for Millau { - const RUNTIME_VERSION: Option = Some(millau_runtime::VERSION); + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion::from_runtime_version(&millau_runtime::VERSION)); } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 8a473dc303c4c..e9e2d0b3eaf91 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -19,7 +19,7 @@ use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_rialto_client::Rialto; -use sp_version::RuntimeVersion; +use relay_substrate_client::SimpleRuntimeVersion; use xcm::latest::prelude::*; impl CliEncodeMessage for Rialto { @@ -45,5 +45,6 @@ impl CliEncodeMessage for Rialto { } impl CliChain for Rialto { - const RUNTIME_VERSION: Option = Some(rialto_runtime::VERSION); + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion::from_runtime_version(&rialto_runtime::VERSION)); } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 4d1e1b02e3741..54704e72947b3 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -20,8 +20,7 @@ use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; -use relay_substrate_client::calls::XcmCall; -use sp_version::RuntimeVersion; +use relay_substrate_client::{calls::XcmCall, SimpleRuntimeVersion}; use xcm::latest::prelude::*; impl CliEncodeMessage for RialtoParachain { @@ -45,5 +44,5 @@ impl CliEncodeMessage for RialtoParachain { } impl CliChain for RialtoParachain { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = None; } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 6805c021a213e..633c7cfb29082 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -19,12 +19,13 @@ use crate::cli::CliChain; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_rococo_client::Rococo; -use sp_version::RuntimeVersion; +use relay_substrate_client::SimpleRuntimeVersion; impl CliChain for Rococo { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = None; } impl CliChain for BridgeHubRococo { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 9302, transaction_version: 1 }); } diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs index 6cdae2b212b59..0de1fd9396a81 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs @@ -52,7 +52,7 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { if enable_version_guard { relay_substrate_client::guard::abort_on_spec_version_change( target_client.clone(), - target_client.simple_runtime_version().await?.0, + target_client.simple_runtime_version().await?.spec_version, ); } Ok(()) diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 50ae034957619..9cf639e987486 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -17,13 +17,13 @@ //! Westend chain specification for CLI. use crate::cli::CliChain; +use relay_substrate_client::SimpleRuntimeVersion; use relay_westend_client::{Westend, Westmint}; -use sp_version::RuntimeVersion; impl CliChain for Westend { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = None; } impl CliChain for Westmint { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = None; } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 0bbfa676fe996..66a72e1113404 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -18,13 +18,14 @@ use crate::cli::CliChain; use relay_bridge_hub_wococo_client::BridgeHubWococo; +use relay_substrate_client::SimpleRuntimeVersion; use relay_wococo_client::Wococo; -use sp_version::RuntimeVersion; impl CliChain for Wococo { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = None; } impl CliChain for BridgeHubWococo { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 9302, transaction_version: 1 }); } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs index 6089ae7328cd9..e9054fd31e904 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs @@ -52,7 +52,7 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { if enable_version_guard { relay_substrate_client::guard::abort_on_spec_version_change( target_client.clone(), - target_client.simple_runtime_version().await?.0, + target_client.simple_runtime_version().await?.spec_version, ); } Ok(()) diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 3993b74250df6..bbc95d7dcdbd1 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -20,7 +20,7 @@ use structopt::StructOpt; use strum::{EnumString, EnumVariantNames}; use crate::cli::CliChain; -pub use relay_substrate_client::ChainRuntimeVersion; +pub use relay_substrate_client::{ChainRuntimeVersion, SimpleRuntimeVersion}; use substrate_relay_helper::TransactionParams; #[doc = "Runtime version params."] @@ -57,25 +57,24 @@ macro_rules! declare_chain_runtime_version_params_cli_schema { /// Converts self into `ChainRuntimeVersion`. pub fn into_runtime_version( self, - bundle_runtime_version: Option, + bundle_runtime_version: Option, ) -> anyhow::Result { Ok(match self.[<$chain_prefix _version_mode>] { RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, RuntimeVersionType::Custom => { - let except_spec_version = self.[<$chain_prefix _spec_version>] + let custom_spec_version = self.[<$chain_prefix _spec_version>] .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; - let except_transaction_version = self.[<$chain_prefix _transaction_version>] + let custom_transaction_version = self.[<$chain_prefix _transaction_version>] .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; ChainRuntimeVersion::Custom( - except_spec_version, - except_transaction_version + SimpleRuntimeVersion { + spec_version: custom_spec_version, + transaction_version: custom_transaction_version + } ) }, RuntimeVersionType::Bundle => match bundle_runtime_version { - Some(runtime_version) => ChainRuntimeVersion::Custom( - runtime_version.spec_version, - runtime_version.transaction_version - ), + Some(runtime_version) => ChainRuntimeVersion::Custom(runtime_version), None => ChainRuntimeVersion::Auto }, }) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 9081a397b6b41..17d0262b21bef 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -28,6 +28,7 @@ use structopt::{clap::arg_enum, StructOpt}; use strum::{EnumString, EnumVariantNames}; use bp_messages::LaneId; +use relay_substrate_client::SimpleRuntimeVersion; pub(crate) mod bridge; pub(crate) mod encode_message; @@ -194,7 +195,7 @@ pub trait CliChain: relay_substrate_client::Chain { /// Current version of the chain runtime, known to relay. /// /// can be `None` if relay is not going to submit transactions to that chain. - const RUNTIME_VERSION: Option; + const RUNTIME_VERSION: Option; } /// Lane id. diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index c69f9c8ae4e7b..2fecd19692142 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -403,7 +403,7 @@ async fn update_transaction_tip( })?; let old_tip = unsigned_tx.tip; - let (spec_version, transaction_version) = client.simple_runtime_version().await?; + let runtime_version = client.simple_runtime_version().await?; while current_priority < target_priority { let next_tip = unsigned_tx.tip + tip_step; if next_tip > tip_limit { @@ -425,8 +425,8 @@ async fn update_transaction_tip( at_block.1, C::sign_transaction( SignParam { - spec_version, - transaction_version, + spec_version: runtime_version.spec_version, + transaction_version: runtime_version.transaction_version, genesis_hash: *client.genesis_hash(), signer: transaction_params.signer.clone(), }, @@ -449,8 +449,8 @@ async fn update_transaction_tip( old_tip != unsigned_tx.tip, C::sign_transaction( SignParam { - spec_version, - transaction_version, + spec_version: runtime_version.spec_version, + transaction_version: runtime_version.transaction_version, genesis_hash: *client.genesis_hash(), signer: transaction_params.signer.clone(), }, diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index dd763150267ae..62d6a7c599e8c 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -75,15 +75,32 @@ pub struct Subscription(pub(crate) Mutex; +/// A simple runtime version. It only includes the `spec_version` and `transaction_version`. +#[derive(Copy, Clone, Debug)] +pub struct SimpleRuntimeVersion { + /// Version of the runtime specification. + pub spec_version: u32, + /// All existing dispatches are fully compatible when this number doesn't change. + pub transaction_version: u32, +} + +impl SimpleRuntimeVersion { + /// Create a new instance of `SimpleRuntimeVersion` from a `RuntimeVersion`. + pub const fn from_runtime_version(runtime_version: &RuntimeVersion) -> Self { + Self { + spec_version: runtime_version.spec_version, + transaction_version: runtime_version.transaction_version, + } + } +} + /// Chain runtime version in client #[derive(Clone, Debug)] pub enum ChainRuntimeVersion { /// Auto query from chain. Auto, /// Custom runtime version, defined by user. - /// the first is `spec_version` - /// the second is `transaction_version` - Custom(u32, u32), + Custom(SimpleRuntimeVersion), } /// Substrate client type. @@ -213,16 +230,14 @@ impl Client { impl Client { /// Return simple runtime version, only include `spec_version` and `transaction_version`. - pub async fn simple_runtime_version(&self) -> Result<(u32, u32)> { - let (spec_version, transaction_version) = match self.chain_runtime_version { + pub async fn simple_runtime_version(&self) -> Result { + Ok(match &self.chain_runtime_version { ChainRuntimeVersion::Auto => { let runtime_version = self.runtime_version().await?; - (runtime_version.spec_version, runtime_version.transaction_version) + SimpleRuntimeVersion::from_runtime_version(&runtime_version) }, - ChainRuntimeVersion::Custom(spec_version, transaction_version) => - (spec_version, transaction_version), - }; - Ok((spec_version, transaction_version)) + ChainRuntimeVersion::Custom(version) => *version, + }) } /// Returns true if client is connected to at least one peer and is in synced state. @@ -430,10 +445,10 @@ impl Client { where C: ChainWithTransactions, { - let (spec_version, transaction_version) = self.simple_runtime_version().await?; + let runtime_version = self.simple_runtime_version().await?; Ok(SignParam:: { - spec_version, - transaction_version, + spec_version: runtime_version.spec_version, + transaction_version: runtime_version.transaction_version, genesis_hash: self.genesis_hash, signer, }) diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 599d9c658b56f..ef75e30424625 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -40,8 +40,8 @@ pub use crate::{ UnsignedTransaction, UtilityPallet, }, client::{ - ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription, - ANCIENT_BLOCK_THRESHOLD, + ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, SimpleRuntimeVersion, + Subscription, ANCIENT_BLOCK_THRESHOLD, }, error::{Error, Result}, rpc::{SubstrateBeefyFinalityClient, SubstrateFinalityClient, SubstrateGrandpaFinalityClient}, diff --git a/relays/lib-substrate-relay/src/finality/guards.rs b/relays/lib-substrate-relay/src/finality/guards.rs index 1451b549cc0da..188a03733a382 100644 --- a/relays/lib-substrate-relay/src/finality/guards.rs +++ b/relays/lib-substrate-relay/src/finality/guards.rs @@ -36,7 +36,7 @@ where if enable_version_guard { relay_substrate_client::guard::abort_on_spec_version_change( target_client.clone(), - target_client.simple_runtime_version().await?.0, + target_client.simple_runtime_version().await?.spec_version, ); } relay_substrate_client::guard::abort_when_account_balance_decreased( From 717241ef494cfeea0e1178244905566aac7c5d41 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 11 Jan 2023 11:51:15 +0200 Subject: [PATCH 0865/1210] Remove sp-version dependency from bin-substrate (#1758) --- relays/bin-substrate/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a22bf12632c59..633ab8fe5bd9a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -60,7 +60,6 @@ substrate-relay-helper = { path = "../lib-substrate-relay" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } From 3891f99447f253ab718a254ae1faafa9f70346dd Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 11 Jan 2023 12:43:42 +0100 Subject: [PATCH 0866/1210] `cargo machete` removed unused deps (#1761) --- bin/millau/node/Cargo.toml | 1 - bin/millau/runtime/Cargo.toml | 2 -- bin/rialto-parachain/node/Cargo.toml | 1 - bin/rialto-parachain/runtime/Cargo.toml | 2 -- bin/rialto/runtime/Cargo.toml | 2 -- modules/beefy/Cargo.toml | 4 ---- primitives/beefy/Cargo.toml | 7 ------- primitives/chain-bridge-hub-cumulus/Cargo.toml | 6 ------ primitives/chain-bridge-hub-rococo/Cargo.toml | 4 ---- primitives/messages/Cargo.toml | 1 - relays/bin-substrate/Cargo.toml | 8 -------- relays/client-bridge-hub-rococo/Cargo.toml | 2 -- relays/client-kusama/Cargo.toml | 1 - relays/client-polkadot/Cargo.toml | 1 - relays/client-rialto-parachain/Cargo.toml | 5 ----- relays/client-rococo/Cargo.toml | 1 - relays/client-substrate/Cargo.toml | 2 -- relays/client-westend/Cargo.toml | 1 - relays/client-wococo/Cargo.toml | 1 - relays/lib-substrate-relay/Cargo.toml | 1 - relays/messages/Cargo.toml | 1 - 21 files changed, 54 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index a8d03c6f1a4e9..b022282b3b23c 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -40,7 +40,6 @@ sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index d3aabdcba392c..cf9b0c24d5606 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.3" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies @@ -98,7 +97,6 @@ std = [ "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", - "log/std", "pallet-aura/std", "pallet-balances/std", "pallet-beefy/std", diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 03d1a28c6a495..4ee6a51fbc610 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -56,7 +56,6 @@ sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master ## Substrate Primitive Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 467fbd3699a3d..2327a864c2cbe 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -12,7 +12,6 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} hex-literal = "0.3" -log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge depedencies @@ -95,7 +94,6 @@ std = [ "bp-rialto-parachain/std", "bridge-runtime-common/std", "codec/std", - "log/std", "scale-info/std", "sp-api/std", "sp-std/std", diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 7220e5790a409..ae8d9cc0d4b5b 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge dependencies @@ -93,7 +92,6 @@ std = [ "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", - "log/std", "pallet-authority-discovery/std", "pallet-babe/std", "pallet-balances/std", diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 25905126d5358..923b35410888a 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -18,10 +18,8 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -primitive-types = { version = "0.12.0", default-features = false, features = ["impl-codec"] } sp-core = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -38,14 +36,12 @@ bp-test-utils = { path = "../../primitives/test-utils" } [features] default = ["std"] std = [ - "beefy-merkle-tree/std", "bp-beefy/std", "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", "log/std", - "primitive-types/std", "scale-info/std", "serde", "sp-core/std", diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 6b169e6611321..e619e52cfc22e 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -10,7 +10,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.0.1", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true } -static_assertions = "1.1" # Bridge Dependencies @@ -23,9 +22,6 @@ beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = " frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-application-crypto = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -40,9 +36,6 @@ std = [ "pallet-mmr/std", "scale-info/std", "serde", - "sp-application-crypto/std", - "sp-core/std", - "sp-io/std", "sp-runtime/std", "sp-std/std" ] diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index a4a8f9663df5d..8896522951b7b 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -10,7 +10,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies @@ -18,22 +17,17 @@ bp-messages = { path = "../../primitives/messages", default-features = false } frame-system = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot Dependencies polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [features] default = ["std"] std = [ "bp-polkadot-core/std", - "bp-runtime/std", "bp-messages/std", "frame-system/std", "frame-support/std", "sp-api/std", - "sp-std/std", "polkadot-primitives/std", - "polkadot-runtime-constants/std", ] diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index 0cc57f3995906..85c4225ab55c3 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -19,9 +19,6 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -# Polkadot Dependencies -polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } - [features] default = ["std"] std = [ @@ -31,5 +28,4 @@ std = [ "frame-support/std", "sp-api/std", "sp-std/std", - "polkadot-runtime-constants/std", ] diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 4899a1f22da39..f54090893a678 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -impl-trait-for-tuples = "0.2" scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 633ab8fe5bd9a..4be812be86aef 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -22,9 +22,6 @@ signal-hook-async-std = "0.2.2" strum = { version = "0.21.0", features = ["derive"] } # Bridge dependencies - -bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } -bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } @@ -32,14 +29,9 @@ bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } -bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } -bp-westend = { path = "../../primitives/chain-westend" } -bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } -messages-relay = { path = "../messages" } millau-runtime = { path = "../../bin/millau/runtime" } -pallet-bridge-messages = { path = "../../modules/messages" } pallet-bridge-parachains = { path = "../../modules/parachains" } parachains-relay = { path = "../parachains" } relay-millau-client = { path = "../client-millau" } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index e650ba9da7679..9a9316fa1177e 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -17,8 +17,6 @@ bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-rococo = { path = "../../primitives/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 2efe62d8ec87c..e4d83d88ceb37 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -15,5 +15,4 @@ bp-kusama = { path = "../../primitives/chain-kusama" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index aefbadfdd18af..cc16ec1f5c3a1 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -15,5 +15,4 @@ bp-polkadot = { path = "../../primitives/chain-polkadot" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 8ecc915f95347..f3c4a1d42f8e8 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -16,16 +16,11 @@ bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } -bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 14d3c8ca23259..cc197ba8562e7 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -15,5 +15,4 @@ bp-rococo = { path = "../../primitives/chain-rococo" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index f9760a32603e9..229de0cc09d2f 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -40,11 +40,9 @@ sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "mas sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 57d2ca3b1e756..c60305868ad0f 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -15,5 +15,4 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 5b97694af1c9e..19483ab22fd5c 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -14,5 +14,4 @@ relay-utils = { path = "../utils" } bp-wococo = { path = "../../primitives/chain-wococo" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 1dd7cb7b37d2c..bdf49d42eab44 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -41,7 +41,6 @@ bp-messages = { path = "../../primitives/messages" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 02e453b1c32a4..e144926376c57 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -17,7 +17,6 @@ parking_lot = "0.11.0" # Bridge Dependencies bp-messages = { path = "../../primitives/messages" } -bp-runtime = { path = "../../primitives/runtime" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } From 49d53ca5a0fa45f981402284f797cf023b8db2d6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 Jan 2023 12:02:58 +0300 Subject: [PATCH 0867/1210] fixed receive_delivery_proof_for_two_messages_by_two_relayers (#1764) --- bin/millau/runtime/src/lib.rs | 8 ++++-- modules/messages/src/benchmarking.rs | 6 ++++ modules/messages/src/weights.rs | 42 ++++++++++++++-------------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4513e50121bcd..7914ac41b5334 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -478,7 +478,7 @@ impl pallet_bridge_messages::Config for Runtime { type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<10_000>, >; type SourceHeaderChain = crate::rialto_messages::Rialto; @@ -509,7 +509,7 @@ impl pallet_bridge_messages::Config for Run type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<10_000>, >; type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; @@ -1037,6 +1037,10 @@ impl_runtime_apis! { [0u8; 32].into() } + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + pallet_bridge_relayers::Pallet::::relayer_reward(relayer, &Self::bench_lane_id()).is_some() + } + fn endow_account(account: &Self::AccountId) { pallet_balances::Pallet::::make_free_balance_be( account, diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 36018474a8f8f..62dd1d60caf66 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -69,6 +69,8 @@ pub trait Config: crate::Config { } /// Return id of relayer account at the bridged chain. fn bridged_relayer_id() -> Self::InboundRelayer; + /// Returns true if given relayer has been rewarded for some of its actions. + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool; /// Create given account and give it enough balance for test purposes. fn endow_account(account: &Self::AccountId); /// Prepare messages proof to receive by the module. @@ -287,6 +289,7 @@ benchmarks_instance_pallet! { }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { assert_eq!(OutboundLanes::::get(T::bench_lane_id()).latest_received_nonce, 1); + assert!(T::is_relayer_rewarded(&relayer_id)); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -325,6 +328,7 @@ benchmarks_instance_pallet! { }: receive_messages_delivery_proof(RawOrigin::Signed(relayer_id.clone()), proof, relayers_state) verify { assert_eq!(OutboundLanes::::get(T::bench_lane_id()).latest_received_nonce, 2); + assert!(T::is_relayer_rewarded(&relayer_id)); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -368,6 +372,8 @@ benchmarks_instance_pallet! { }: receive_messages_delivery_proof(RawOrigin::Signed(relayer1_id.clone()), proof, relayers_state) verify { assert_eq!(OutboundLanes::::get(T::bench_lane_id()).latest_received_nonce, 2); + assert!(T::is_relayer_rewarded(&relayer1_id)); + assert!(T::is_relayer_rewarded(&relayer2_id)); } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 69fad6051d5d4..344b9587d6887 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for `pallet_bridge_messages` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 +//! DATE: 2023-01-12, STEPS: 50, REPEAT: 20 //! LOW RANGE: [], HIGH RANGE: [] //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled //! CHAIN: Some("dev"), DB CACHE: 1024 @@ -66,87 +66,87 @@ pub trait WeightInfo { pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(60_148_000 as u64) + Weight::from_ref_time(95_401_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(71_836_000 as u64) + Weight::from_ref_time(127_794_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(66_845_000 as u64) + Weight::from_ref_time(105_698_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(69_696_000 as u64) + Weight::from_ref_time(92_963_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(123_646_000 as u64) + Weight::from_ref_time(158_449_000 as u64) .saturating_add(T::DbWeight::get().reads(3 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(53_723_000 as u64) + Weight::from_ref_time(72_085_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(54_617_000 as u64) + Weight::from_ref_time(70_889_000 as u64) .saturating_add(T::DbWeight::get().reads(4 as u64)) .saturating_add(T::DbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(53_582_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + Weight::from_ref_time(78_211_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) } } // For backwards compatibility and tests impl WeightInfo for () { fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(60_148_000 as u64) + Weight::from_ref_time(95_401_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(71_836_000 as u64) + Weight::from_ref_time(127_794_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(66_845_000 as u64) + Weight::from_ref_time(105_698_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(69_696_000 as u64) + Weight::from_ref_time(92_963_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(123_646_000 as u64) + Weight::from_ref_time(158_449_000 as u64) .saturating_add(RocksDbWeight::get().reads(3 as u64)) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(53_723_000 as u64) + Weight::from_ref_time(72_085_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(54_617_000 as u64) + Weight::from_ref_time(70_889_000 as u64) .saturating_add(RocksDbWeight::get().reads(4 as u64)) .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(53_582_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + Weight::from_ref_time(78_211_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) } } From d51a17e8fcf50728f3195123bccc56192facd0f7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 Jan 2023 15:19:20 +0300 Subject: [PATCH 0868/1210] increase MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX and MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX for RBH/WBH (#1765) * increase MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX and MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX for RBH/WBH * moved MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX and MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX to cumulus bridge primitives * typo --- .../chain-bridge-hub-cumulus/src/lib.rs | 32 +++++++++++++++++-- primitives/polkadot-core/src/lib.rs | 8 ----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index ecf263d4a09c6..0f5f33087edc7 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -20,8 +20,7 @@ use bp_messages::*; pub use bp_polkadot_core::{ AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, SignedExtensions, - UncheckedExtrinsic, MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, TX_EXTRA_BYTES, + UncheckedExtrinsic, TX_EXTRA_BYTES, }; use frame_support::{ dispatch::DispatchClass, @@ -85,3 +84,32 @@ pub type AccountSigner = MultiSigner; /// The address format for describing accounts. pub type Address = MultiAddress; + +// Note about selecting values of two following constants: +// +// Normal transactions have limit of 75% of 1/2 second weight for Cumulus parachains. Let's keep +// some reserve for the rest of stuff there => let's select values that fit in 50% of maximal limit. +// +// Using current constants, the limit would be: +// +// `75% * WEIGHT_REF_TIME_PER_SECOND * 1 / 2 * 50% = 0.75 * 1_000_000_000_000 / 2 * 0.5 = +// 187_500_000_000` +// +// According to (preliminary) weights of messages pallet, cost of additional message is zero and the +// cost of additional relayer is `8_000_000 + db read + db write`. Let's say we want no more than +// 4096 unconfirmed messages (no any scientific justification for that - it just looks large +// enough). And then we can't have more than 4096 relayers. E.g. for 1024 relayers is (using +// `RocksDbWeight`): +// +// `1024 * (8_000_000 + db read + db write) = 1024 * (8_000_000 + 25_000_000 + 100_000_000) = +// 136_192_000_000` +// +// So 1024 looks like good approximation for the number of relayers. If something is wrong in those +// assumptions, or something will change, it shall be caught by the +// `ensure_able_to_receive_confirmation` test. + +/// Maximal number of unrewarded relayer entries at inbound lane for Cumulus-based parachains. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; + +/// Maximal number of unconfirmed messages at inbound lane for Cumulus-based parachains. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 57025f2f3f697..8d9932ea58c52 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -118,14 +118,6 @@ parameter_types! { /// Maximal number of messages in single delivery transaction. pub const MAX_MESSAGES_IN_DELIVERY_TRANSACTION: MessageNonce = 128; -/// Maximal number of unrewarded relayer entries at inbound lane. -pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; - -// TODO [#438] should be selected keeping in mind: -// finality delay on both chains + reward payout cost + messages throughput. -/// Maximal number of unconfirmed messages at inbound lane. -pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 8192; - /// Maximal number of bytes, included in the signed Polkadot-like transaction apart from the encoded /// call itself. /// From 75524a6b2d9e29634a3070ff44e3a7d46527a9fb Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 12 Jan 2023 15:35:33 +0200 Subject: [PATCH 0869/1210] Define method for checking message lane weights (#1766) * Define method for checking message lane weights * Docs for public function * Renamings --- bin/millau/runtime/src/rialto_messages.rs | 33 ++++------------------ bin/rialto/runtime/src/millau_messages.rs | 32 ++++----------------- bin/runtime-common/src/integrity.rs | 34 +++++++++++++++++++++-- 3 files changed, 42 insertions(+), 57 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 0d80cdd7b1a8a..ac203a2f6dde8 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -163,42 +163,19 @@ mod tests { use super::*; use crate::{Runtime, WithRialtoMessagesInstance}; - use bp_runtime::Chain; use bridge_runtime_common::{ assert_complete_bridge_types, integrity::{ - assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, - AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, }, - messages, }; #[test] fn ensure_millau_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::BridgeWeight; - - pallet_bridge_messages::ensure_weights_are_correct::(); - - let max_incoming_message_proof_size = bp_rialto::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_millau::Millau::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - bp_millau::Millau::max_extrinsic_size(), - bp_millau::Millau::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - bp_millau::Millau::max_extrinsic_weight(), - ), - ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint_u32( - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - ); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_millau::Millau::max_extrinsic_size(), - bp_millau::Millau::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, + check_message_lane_weights::( + bp_rialto::EXTRA_STORAGE_PROOF_SIZE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, ); diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index b2e55ccfa0268..90a63a733c33c 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -162,41 +162,19 @@ impl SourceHeaderChain for Millau { mod tests { use super::*; use crate::{MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; - use bp_runtime::Chain; use bridge_runtime_common::{ assert_complete_bridge_types, integrity::{ - assert_complete_bridge_constants, AssertBridgeMessagesPalletConstants, - AssertBridgePalletNames, AssertChainConstants, AssertCompleteBridgeConstants, + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, }, }; #[test] fn ensure_rialto_message_lane_weights_are_correct() { - type Weights = pallet_bridge_messages::weights::BridgeWeight; - - pallet_bridge_messages::ensure_weights_are_correct::(); - - let max_incoming_message_proof_size = bp_millau::EXTRA_STORAGE_PROOF_SIZE.saturating_add( - messages::target::maximal_incoming_message_size(bp_rialto::Rialto::max_extrinsic_size()), - ); - pallet_bridge_messages::ensure_able_to_receive_message::( - bp_rialto::Rialto::max_extrinsic_size(), - bp_rialto::Rialto::max_extrinsic_weight(), - max_incoming_message_proof_size, - messages::target::maximal_incoming_message_dispatch_weight( - bp_rialto::Rialto::max_extrinsic_weight(), - ), - ); - - let max_incoming_inbound_lane_data_proof_size = - bp_messages::InboundLaneData::<()>::encoded_size_hint_u32( - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX as _, - ); - pallet_bridge_messages::ensure_able_to_receive_confirmation::( - bp_rialto::Rialto::max_extrinsic_size(), - bp_rialto::Rialto::max_extrinsic_weight(), - max_incoming_inbound_lane_data_proof_size, + check_message_lane_weights::( + bp_millau::EXTRA_STORAGE_PROOF_SIZE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, ); diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 4c69a29b82170..9c4553ad136ae 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -19,9 +19,9 @@ //! Most of the tests in this module assume that the bridge is using standard (see `crate::messages` //! module for details) configuration. -use crate::messages::MessageBridge; +use crate::{messages, messages::MessageBridge}; -use bp_messages::MessageNonce; +use bp_messages::{InboundLaneData, MessageNonce}; use bp_runtime::{Chain, ChainId}; use codec::Encode; use frame_support::{storage::generator::StorageValue, traits::Get}; @@ -289,3 +289,33 @@ where assert_bridge_messages_pallet_constants::(params.messages_pallet_constants); assert_bridge_pallet_names::(params.pallet_names); } + +/// Check that the message lane weights are correct. +pub fn check_message_lane_weights( + bridged_chain_extra_storage_proof_size: u32, + this_chain_max_unrewarded_relayers: MessageNonce, + this_chain_max_unconfirmed_messages: MessageNonce, +) { + type Weights = pallet_bridge_messages::weights::BridgeWeight; + + pallet_bridge_messages::ensure_weights_are_correct::>(); + + let max_incoming_message_proof_size = bridged_chain_extra_storage_proof_size + .saturating_add(messages::target::maximal_incoming_message_size(C::max_extrinsic_size())); + pallet_bridge_messages::ensure_able_to_receive_message::>( + C::max_extrinsic_size(), + C::max_extrinsic_weight(), + max_incoming_message_proof_size, + messages::target::maximal_incoming_message_dispatch_weight(C::max_extrinsic_weight()), + ); + + let max_incoming_inbound_lane_data_proof_size = + InboundLaneData::<()>::encoded_size_hint_u32(this_chain_max_unrewarded_relayers as _); + pallet_bridge_messages::ensure_able_to_receive_confirmation::>( + C::max_extrinsic_size(), + C::max_extrinsic_weight(), + max_incoming_inbound_lane_data_proof_size, + this_chain_max_unrewarded_relayers, + this_chain_max_unconfirmed_messages, + ); +} From ab28c3a7295d07f7edc922cd56dad1ff7cdb1245 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 13 Jan 2023 23:23:50 +0100 Subject: [PATCH 0870/1210] Bump xcm-v3 + substrate (#1767) * Bump xcm-v3 + substrate * More fixes * Added `#[pallet::call_index` * Fixes for MMR (TODO:plese check) * More call indexes * Cumulus bump * Fixes for mmr * Fixes for weights * Fixes for xcm * MMR fixes + cargo fmt * Fix some rpc errors (bump jsonrpsee version) * Fix cumulus stuff * Fixes cumulus * clippy * more clipy * Fix test + unused deps * PR fixes * cargo update (bump xcm-v3) Co-authored-by: Serban Iorga --- bin/millau/node/Cargo.toml | 8 +- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/node/src/service.rs | 4 +- bin/millau/runtime/Cargo.toml | 5 +- bin/millau/runtime/src/lib.rs | 72 ++----- bin/millau/runtime/src/xcm_config.rs | 13 +- bin/rialto-parachain/node/Cargo.toml | 7 +- bin/rialto-parachain/node/src/cli.rs | 2 + bin/rialto-parachain/node/src/command.rs | 1 - bin/rialto-parachain/node/src/service.rs | 202 +++++++----------- bin/rialto-parachain/runtime/src/lib.rs | 17 +- bin/rialto/node/Cargo.toml | 4 +- bin/rialto/node/src/chain_spec.rs | 2 +- bin/rialto/runtime/Cargo.toml | 6 +- bin/rialto/runtime/src/lib.rs | 100 +++------ bin/rialto/runtime/src/xcm_config.rs | 13 +- bin/runtime-common/src/messages.rs | 10 +- .../src/refund_relayer_extension.rs | 4 +- modules/beefy/Cargo.toml | 2 +- modules/beefy/src/lib.rs | 6 +- modules/beefy/src/mock.rs | 6 +- modules/beefy/src/mock_chain.rs | 6 +- modules/beefy/src/utils.rs | 12 +- modules/grandpa/src/lib.rs | 4 + modules/messages/src/lib.rs | 4 + modules/parachains/src/lib.rs | 3 + modules/relayers/src/lib.rs | 1 + primitives/beefy/Cargo.toml | 4 +- primitives/beefy/src/lib.rs | 22 +- .../chain-bridge-hub-cumulus/src/lib.rs | 7 +- primitives/chain-millau/src/lib.rs | 6 +- primitives/chain-rialto-parachain/src/lib.rs | 6 +- primitives/chain-rialto/src/lib.rs | 6 +- primitives/polkadot-core/src/lib.rs | 6 +- primitives/runtime/src/chain.rs | 4 +- .../lib-substrate-relay/src/messages_lane.rs | 2 +- 36 files changed, 258 insertions(+), 321 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index b022282b3b23c..08661951eed68 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.0.9", features = ["derive"] } -jsonrpsee = { version = "0.15.1", features = ["server"] } +jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.79" # Bridge dependencies @@ -21,14 +21,14 @@ millau-runtime = { path = "../runtime" } beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" } beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master"} sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 2ded668fdeebc..8b0bc28ed1466 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use beefy_primitives::crypto::AuthorityId as BeefyId; use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; +use sp_beefy::crypto::AuthorityId as BeefyId; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index e86d9e847a02b..6ad63387da4f2 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -272,7 +272,7 @@ pub fn new_full(mut config: Configuration) -> Result use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; use beefy_gadget_rpc::{Beefy, BeefyApiServer}; - use pallet_mmr_rpc::{Mmr, MmrApiServer}; + use mmr_rpc::{Mmr, MmrApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use sc_finality_grandpa_rpc::{Grandpa, GrandpaApiServer}; use sc_rpc::DenyUnsafe; @@ -391,7 +391,7 @@ pub fn new_full(mut config: Configuration) -> Result if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; let justifications_protocol_name = beefy_on_demand_justifications_handler.protocol_name(); - let payload_provider = beefy_primitives::mmr::MmrRootProvider::new(client.clone()); + let payload_provider = sp_beefy::mmr::MmrRootProvider::new(client.clone()); let beefy_params = beefy_gadget::BeefyParams { client: client.clone(), backend, diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index cf9b0c24d5606..0e5868f845e78 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -31,7 +31,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -56,7 +56,6 @@ sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { 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-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-offchain = { 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-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -81,7 +80,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ - "beefy-primitives/std", + "sp-beefy/std", "bp-messages/std", "bp-millau/std", "bp-parachains/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 7914ac41b5334..dbff7f5940c64 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -32,7 +32,6 @@ pub mod rialto_messages; pub mod rialto_parachain_messages; pub mod xcm_config; -use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_runtime::HeaderId; use pallet_grandpa::{ @@ -40,9 +39,9 @@ use pallet_grandpa::{ }; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; +use sp_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_mmr_primitives::{DataOrHash, EncodableOpaqueLeaf, Error as MmrError, Proof as MmrProof}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, @@ -64,7 +63,8 @@ pub use frame_support::{ parameter_types, traits::{ConstU32, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, weights::{ - constants::WEIGHT_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, + constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, + Weight, }, RuntimeDebug, StorageValue, }; @@ -281,7 +281,7 @@ parameter_types! { pub struct BeefyDummyDataProvider; -impl beefy_primitives::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { +impl sp_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { fn extra_data() {} } @@ -766,62 +766,30 @@ impl_runtime_apis! { } } - impl beefy_primitives::BeefyApi for Runtime { + impl sp_beefy::BeefyApi for Runtime { fn validator_set() -> Option> { Beefy::validator_set() } } - impl sp_mmr_primitives::MmrApi for Runtime { - fn generate_proof(block_number: BlockNumber) - -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> - { - Mmr::generate_batch_proof(vec![block_number]) - .and_then(|(leaves, proof)| Ok(( - mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), - mmr::BatchProof::into_single_leaf_proof(proof)? - ))) - } - - fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) - -> Result<(), MmrError> - { - let leaf: mmr::Leaf = leaf - .into_opaque_leaf() - .try_decode() - .ok_or(MmrError::Verify)?; - Mmr::verify_leaves(vec![leaf], mmr::Proof::into_batch_proof(proof)) - } - - fn verify_proof_stateless( - root: mmr::Hash, - leaf: EncodableOpaqueLeaf, - proof: MmrProof - ) -> Result<(), MmrError> { - let node = DataOrHash::Data(leaf.into_opaque_leaf()); - pallet_mmr::verify_leaves_proof::( - root, - vec![node], - pallet_mmr::primitives::Proof::into_batch_proof(proof), - ) - } - - fn mmr_root() -> Result { + impl pallet_mmr::primitives::MmrApi< + Block, + mmr::Hash, + BlockNumber, + > for Runtime { + fn mmr_root() -> Result { Ok(Mmr::mmr_root()) } - fn generate_batch_proof(block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { - Mmr::generate_batch_proof(block_numbers) - .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) + fn mmr_leaf_count() -> Result { + Ok(Mmr::mmr_leaves()) } - fn generate_historical_batch_proof( + fn generate_proof( block_numbers: Vec, - best_known_block_number: BlockNumber - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_historical_batch_proof(block_numbers, best_known_block_number).map( + best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { + Mmr::generate_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( leaves @@ -834,7 +802,7 @@ impl_runtime_apis! { ) } - fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) + fn verify_proof(leaves: Vec, proof: mmr::Proof) -> Result<(), mmr::Error> { let leaves = leaves.into_iter().map(|leaf| @@ -844,10 +812,10 @@ impl_runtime_apis! { Mmr::verify_leaves(leaves, proof) } - fn verify_batch_proof_stateless( + fn verify_proof_stateless( root: mmr::Hash, leaves: Vec, - proof: mmr::BatchProof + proof: mmr::Proof ) -> Result<(), mmr::Error> { let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); pallet_mmr::verify_leaves_proof::(root, nodes, proof) diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index e353137e8236f..17bdc43da3d66 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -32,6 +32,7 @@ use bridge_runtime_common::{ use frame_support::{ parameter_types, traits::{ConstU32, Everything, Nothing}, + weights::Weight, }; use xcm::latest::prelude::*; use xcm_builder::{ @@ -97,7 +98,8 @@ pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const BaseXcmWeight: u64 = BASE_XCM_WEIGHT; + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - check `set_proof_size` 0 or 64*1024 or 1026? + pub const BaseXcmWeight: Weight = Weight::from_parts(BASE_XCM_WEIGHT, 0); /// Maximum number of instructions in a single XCM fragment. A sanity check against weight /// calculations getting too crazy. pub const MaxInstructions: u32 = 100; @@ -150,6 +152,7 @@ impl xcm_executor::Config for XcmConfig { type MessageExporter = (); type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -159,6 +162,11 @@ pub type LocalOriginToLocation = ( SignedToAccountId32, ); +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); +} + impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We don't allow any messages to be sent via the transaction yet. This is basically safe to @@ -188,6 +196,9 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = SovereignAccountOf; type MaxLockers = frame_support::traits::ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; } /// With-Rialto bridge. diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 4ee6a51fbc610..7b81de4fd3ac3 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -23,7 +23,7 @@ codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } # RPC related Dependencies -jsonrpsee = { version = "0.15.1", features = ["server"] } +jsonrpsee = { version = "0.16.2", features = ["server"] } # Local Dependencies rialto-parachain-runtime = { path = '../runtime' } @@ -47,8 +47,7 @@ sc-executor = { git = "https://github.com/paritytech/substrate", branch = "maste sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ['wasmtime'] } -sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "master"} sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -74,8 +73,6 @@ cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "master" } # Polkadot dependencies polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 51fa1e9776c38..a003c91113c00 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +#![allow(clippy::large_enum_variant)] + use crate::chain_spec; use clap::Parser; use std::path::PathBuf; diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index dd9e95abbe543..2cb08ec4ea283 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -138,7 +138,6 @@ macro_rules! construct_async_run { runner.async_run(|$config| { let $components = new_partial::< RuntimeApi, - ParachainRuntimeExecutor, _ >( &$config, diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 7dc25f6550d00..254340a8ad4cc 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -30,17 +30,16 @@ use rialto_parachain_runtime::RuntimeApi; // Cumulus Imports use cumulus_client_cli::CollatorOptions; use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::{ParachainBlockImport, ParachainConsensus}; +use cumulus_client_consensus_common::{ + ParachainBlockImport as TParachainBlockImport, ParachainConsensus, +}; use cumulus_client_network::BlockAnnounceValidator; use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; -use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain; -use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult}; -use cumulus_relay_chain_minimal_node::build_minimal_relay_chain_node; -use polkadot_service::CollatorPair; - +use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; +use sc_consensus::ImportQueue; // Substrate Imports use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; use sc_network::{NetworkBlock, NetworkService}; @@ -57,6 +56,12 @@ type Header = sp_runtime::generic::Header; type Hash = sp_core::H256; +type ParachainClient = + TFullClient>; +type ParachainBackend = TFullBackend; +type ParachainBlockImport = + TParachainBlockImport>, ParachainBackend>; + pub type ParachainRuntimeExecutor = ExecutorDispatch; // Our native executor instance. @@ -79,51 +84,39 @@ impl NativeExecutionDispatch for ExecutorDispatch { /// Use this macro if you don't actually need the full service, but just the builder in order to /// be able to perform chain operations. #[allow(clippy::type_complexity)] -pub fn new_partial( +pub fn new_partial( config: &Configuration, build_import_queue: BIQ, ) -> Result< PartialComponents< - TFullClient>, - TFullBackend, + ParachainClient, + ParachainBackend, (), - sc_consensus::DefaultImportQueue< - Block, - TFullClient>, - >, - sc_transaction_pool::FullPool< - Block, - TFullClient>, - >, - (Option, Option), + sc_consensus::DefaultImportQueue>, + sc_transaction_pool::FullPool>, + (ParachainBlockImport, Option, Option), >, sc_service::Error, > where - RuntimeApi: ConstructRuntimeApi>> - + Send - + Sync - + 'static, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys + sp_api::ApiExt< Block, - StateBackend = sc_client_api::StateBackendFor, Block>, + StateBackend = sc_client_api::StateBackendFor, > + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder, - sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, - Executor: NativeExecutionDispatch + 'static, + sc_client_api::StateBackendFor: sp_api::StateBackend, BIQ: FnOnce( - Arc>>, + Arc>, + ParachainBlockImport, &Configuration, Option, &TaskManager, ) -> Result< - sc_consensus::DefaultImportQueue< - Block, - TFullClient>, - >, + sc_consensus::DefaultImportQueue>, sc_service::Error, >, { @@ -138,7 +131,7 @@ where }) .transpose()?; - let executor = sc_executor::NativeElseWasmExecutor::::new( + let executor = sc_executor::NativeElseWasmExecutor::::new( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, @@ -168,8 +161,11 @@ where client.clone(), ); + let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); + let import_queue = build_import_queue( client.clone(), + block_import.clone(), config, telemetry.as_ref().map(|telemetry| telemetry.handle()), &task_manager, @@ -183,38 +179,17 @@ where task_manager, transaction_pool, select_chain: (), - other: (telemetry, telemetry_worker_handle), + other: (block_import, telemetry, telemetry_worker_handle), }; Ok(params) } -async fn build_relay_chain_interface( - polkadot_config: Configuration, - parachain_config: &Configuration, - telemetry_worker_handle: Option, - task_manager: &mut TaskManager, - collator_options: CollatorOptions, - hwbench: Option, -) -> RelayChainResult<(Arc<(dyn RelayChainInterface + 'static)>, Option)> { - match collator_options.relay_chain_rpc_url { - Some(relay_chain_url) => - build_minimal_relay_chain_node(polkadot_config, task_manager, relay_chain_url).await, - None => build_inprocess_relay_chain( - polkadot_config, - parachain_config, - telemetry_worker_handle, - task_manager, - hwbench, - ), - } -} - /// Start a node with the given parachain `Configuration` and relay chain `Configuration`. /// /// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node_impl( +async fn start_node_impl( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, @@ -222,63 +197,45 @@ async fn start_node_impl( rpc_ext_builder: RB, build_import_queue: BIQ, build_consensus: BIC, -) -> sc_service::error::Result<( - TaskManager, - Arc>>, -)> +) -> sc_service::error::Result<(TaskManager, Arc>)> where - RuntimeApi: ConstructRuntimeApi>> - + Send - + Sync - + 'static, + RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys + sp_api::ApiExt< Block, - StateBackend = sc_client_api::StateBackendFor, Block>, + StateBackend = sc_client_api::StateBackendFor, > + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder + cumulus_primitives_core::CollectCollationInfo, - sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, - Executor: NativeExecutionDispatch + 'static, + sc_client_api::StateBackendFor: sp_api::StateBackend, RB: Fn( sc_rpc_api::DenyUnsafe, - Arc>>, - Arc< - sc_transaction_pool::FullPool< - Block, - TFullClient>, - >, - >, + Arc>, + Arc>>, ) -> Result, sc_service::Error> + Send + Clone + 'static, BIQ: FnOnce( - Arc>>, + Arc>, + ParachainBlockImport, &Configuration, Option, &TaskManager, ) -> Result< - sc_consensus::DefaultImportQueue< - Block, - TFullClient>, - >, + sc_consensus::DefaultImportQueue>, sc_service::Error, >, BIC: FnOnce( - Arc>>, + Arc>, + ParachainBlockImport, Option<&Registry>, Option, &TaskManager, Arc, - Arc< - sc_transaction_pool::FullPool< - Block, - TFullClient>, - >, - >, + Arc>>, Arc>, SyncCryptoStorePtr, bool, @@ -286,23 +243,24 @@ where { let parachain_config = prepare_node_config(parachain_config); - let params = new_partial::(¶chain_config, build_import_queue)?; - let (mut telemetry, telemetry_worker_handle) = params.other; + let params = new_partial::(¶chain_config, build_import_queue)?; + let (block_import, mut telemetry, telemetry_worker_handle) = params.other; let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = build_relay_chain_interface( - polkadot_config, - ¶chain_config, - telemetry_worker_handle, - &mut task_manager, - collator_options, - None, - ) - .await - .map_err(|e| match e { - RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, - s => s.to_string().into(), - })?; + let (relay_chain_interface, collator_key) = + cumulus_client_service::build_relay_chain_interface( + polkadot_config, + ¶chain_config, + telemetry_worker_handle, + &mut task_manager, + collator_options, + None, + ) + .await + .map_err(|e| match e { + RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, + s => s.to_string().into(), + })?; let client = params.client.clone(); let backend = params.backend.clone(); @@ -312,14 +270,15 @@ where let validator = parachain_config.role.is_authority(); let prometheus_registry = parachain_config.prometheus_registry().cloned(); let transaction_pool = params.transaction_pool.clone(); - let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); + let import_queue_service = params.import_queue.service(); + let (network, system_rpc_tx, tx_handler_controller, start_network) = sc_service::build_network(sc_service::BuildNetworkParams { config: ¶chain_config, client: client.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), - import_queue: import_queue.clone(), + import_queue: params.import_queue, block_announce_validator_builder: Some(Box::new(|_| { Box::new(block_announce_validator) })), @@ -356,6 +315,7 @@ where if validator { let parachain_consensus = build_consensus( client.clone(), + block_import, prometheus_registry.as_ref(), telemetry.as_ref().map(|t| t.handle()), &task_manager, @@ -377,7 +337,7 @@ where relay_chain_interface, spawner, parachain_consensus, - import_queue, + import_queue: import_queue_service, collator_key: collator_key.expect("Command line arguments do not allow this. qed"), relay_chain_slot_duration, }; @@ -391,7 +351,7 @@ where para_id: id, relay_chain_interface, relay_chain_slot_duration, - import_queue, + import_queue: import_queue_service, }; start_full_node(params)?; @@ -405,17 +365,13 @@ where /// Build the import queue for the the parachain runtime. #[allow(clippy::type_complexity)] pub fn parachain_build_import_queue( - client: Arc>>, + client: Arc>, + block_import: ParachainBlockImport, config: &Configuration, telemetry: Option, task_manager: &TaskManager, -) -> Result< - sc_consensus::DefaultImportQueue< - Block, - TFullClient>, - >, - sc_service::Error, -> { +) -> Result>, sc_service::Error> +{ let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; cumulus_client_consensus_aura::import_queue::< @@ -426,18 +382,18 @@ pub fn parachain_build_import_queue( _, _, >(cumulus_client_consensus_aura::ImportQueueParams { - block_import: ParachainBlockImport::new(client.clone()), + block_import, client, create_inherent_data_providers: move |_, _| async move { - let time = sp_timestamp::InherentDataProvider::from_system_time(); + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *time, + *timestamp, slot_duration, ); - Ok((slot, time)) + Ok((slot, timestamp)) }, registry: config.prometheus_registry(), spawner: &task_manager.spawn_essential_handle(), @@ -452,11 +408,8 @@ pub async fn start_node( polkadot_config: Configuration, collator_options: CollatorOptions, id: ParaId, -) -> sc_service::error::Result<( - TaskManager, - Arc>>, -)> { - start_node_impl::( +) -> sc_service::error::Result<(TaskManager, Arc>)> { + start_node_impl::( parachain_config, polkadot_config, collator_options, @@ -475,6 +428,7 @@ pub async fn start_node( }, parachain_build_import_queue, |client, + block_import, prometheus_registry, telemetry, task_manager, @@ -483,11 +437,13 @@ pub async fn start_node( sync_oracle, keystore, force_authoring| { + let client2 = client.clone(); + let block_import2 = block_import; let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( task_manager.spawn_handle(), - client.clone(), + client, transaction_pool, prometheus_registry, telemetry.clone(), @@ -521,8 +477,8 @@ pub async fn start_node( Ok((slot, time, parachain_inherent)) } }, - block_import: ParachainBlockImport::new(client.clone()), - para_client: client, + block_import: block_import2, + para_client: client2, backoff_authoring_blocks: Option::<()>::None, sync_oracle, keystore, diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index e2e9663510ca0..b9f4c236d861f 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -52,7 +52,9 @@ pub use frame_support::{ match_types, parameter_types, traits::{ConstU32, Everything, IsInVec, Nothing, Randomness}, weights::{ - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, + constants::{ + BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, + }, IdentityFee, Weight, }, StorageValue, @@ -370,7 +372,9 @@ pub type XcmOriginToTransactDispatchOrigin = ( pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; parameter_types! { - pub UnitWeightCost: u64 = BASE_XCM_WEIGHT; + /// The amount of weight an XCM operation takes. This is a safe overestimate. + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - check `set_proof_size` 0 or 64*1024 or 1026? + pub UnitWeightCost: Weight = Weight::from_parts(BASE_XCM_WEIGHT, 0); // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; @@ -419,6 +423,7 @@ impl Config for XcmConfig { type MessageExporter = (); type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -457,6 +462,11 @@ impl XcmBridge for ToMillauBridge { } } +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); +} + impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -477,6 +487,9 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = (); type MaxLockers = frame_support::traits::ConstU32<8>; type UniversalLocation = UniversalLocation; + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 82b073896d987..aec1870efd8dc 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -18,12 +18,12 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["wasmtime"] } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master"} sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 0e9edb38ac03e..5085c2dc71cbe 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use beefy_primitives::crypto::AuthorityId as BeefyId; use frame_support::weights::Weight; use polkadot_primitives::v2::{AssignmentId, ValidatorId}; use rialto_runtime::{ @@ -24,6 +23,7 @@ use rialto_runtime::{ }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use sp_beefy::crypto::AuthorityId as BeefyId; use sp_consensus_babe::AuthorityId as BabeId; use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index ae8d9cc0d4b5b..b4d387e3829b1 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -26,7 +26,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -51,7 +51,6 @@ sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-inherents = { 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-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-offchain = { 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-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -79,7 +78,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ - "beefy-primitives/std", + "sp-beefy/std", "bp-messages/std", "bp-millau/std", "bp-relayers/std", @@ -104,7 +103,6 @@ std = [ "pallet-grandpa/std", "pallet-mmr/std", "pallet-xcm/std", - "sp-mmr-primitives/std", "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 355ccc0b00282..123cd477d9786 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -32,19 +32,15 @@ pub mod millau_messages; pub mod parachains; pub mod xcm_config; -use beefy_primitives::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use bp_runtime::HeaderId; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; -use pallet_mmr::primitives as mmr; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; +use sp_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_mmr_primitives::{ - DataOrHash, EncodableOpaqueLeaf, Error as MmrError, LeafDataProvider, Proof as MmrProof, -}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, @@ -62,7 +58,7 @@ pub use frame_support::{ dispatch::DispatchClass, parameter_types, traits::{ConstU32, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, - weights::{constants::WEIGHT_PER_SECOND, IdentityFee, RuntimeDbWeight, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -269,9 +265,6 @@ impl pallet_grandpa::Config for Runtime { type WeightInfo = (); } -type MmrHash = ::Output; -type MmrHashing = ::Hashing; - impl pallet_mmr::Config for Runtime { const INDEXING_PREFIX: &'static [u8] = b"mmr"; type Hashing = Keccak256; @@ -300,7 +293,7 @@ parameter_types! { pub struct BeefyDummyDataProvider; -impl beefy_primitives::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { +impl sp_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { fn extra_data() {} } @@ -574,6 +567,16 @@ pub type Executive = frame_executive::Executive< AllPalletsWithSystem, >; +/// MMR helper types. +mod mmr { + use super::Runtime; + pub use pallet_mmr::primitives::*; + + pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; + pub type Hash = ::Hash; + pub type Hashing = ::Hashing; +} + impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { @@ -622,66 +625,30 @@ impl_runtime_apis! { } } - impl beefy_primitives::BeefyApi for Runtime { + impl sp_beefy::BeefyApi for Runtime { fn validator_set() -> Option> { Beefy::validator_set() } } - impl sp_mmr_primitives::MmrApi for Runtime { - fn generate_proof(block_number: BlockNumber) - -> Result<(EncodableOpaqueLeaf, MmrProof), MmrError> - { - Mmr::generate_batch_proof(vec![block_number]) - .and_then(|(leaves, proof)| Ok(( - mmr::EncodableOpaqueLeaf::from_leaf(&leaves[0]), - mmr::BatchProof::into_single_leaf_proof(proof)? - ))) - } - - fn verify_proof(leaf: EncodableOpaqueLeaf, proof: MmrProof) - -> Result<(), MmrError> - { - pub type Leaf = < - ::LeafData as LeafDataProvider - >::LeafData; - - let leaf: Leaf = leaf - .into_opaque_leaf() - .try_decode() - .ok_or(MmrError::Verify)?; - Mmr::verify_leaves(vec![leaf], mmr::Proof::into_batch_proof(proof)) - } - - fn verify_proof_stateless( - root: Hash, - leaf: EncodableOpaqueLeaf, - proof: MmrProof - ) -> Result<(), MmrError> { - let node = DataOrHash::Data(leaf.into_opaque_leaf()); - pallet_mmr::verify_leaves_proof::( - root, - vec![node], - pallet_mmr::primitives::Proof::into_batch_proof(proof), - ) - } - - fn mmr_root() -> Result { + impl pallet_mmr::primitives::MmrApi< + Block, + mmr::Hash, + BlockNumber, + > for Runtime { + fn mmr_root() -> Result { Ok(Mmr::mmr_root()) } - fn generate_batch_proof(block_numbers: Vec) - -> Result<(Vec, mmr::BatchProof), mmr::Error> - { - Mmr::generate_batch_proof(block_numbers) - .map(|(leaves, proof)| (leaves.into_iter().map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)).collect(), proof)) + fn mmr_leaf_count() -> Result { + Ok(Mmr::mmr_leaves()) } - fn generate_historical_batch_proof( + fn generate_proof( block_numbers: Vec, - best_known_block_number: BlockNumber - ) -> Result<(Vec, mmr::BatchProof), mmr::Error> { - Mmr::generate_historical_batch_proof(block_numbers, best_known_block_number).map( + best_known_block_number: Option, + ) -> Result<(Vec, mmr::Proof), mmr::Error> { + Mmr::generate_proof(block_numbers, best_known_block_number).map( |(leaves, proof)| { ( leaves @@ -694,26 +661,23 @@ impl_runtime_apis! { ) } - fn verify_batch_proof(leaves: Vec, proof: mmr::BatchProof) + fn verify_proof(leaves: Vec, proof: mmr::Proof) -> Result<(), mmr::Error> { - type Leaf = < - ::LeafData as LeafDataProvider - >::LeafData; let leaves = leaves.into_iter().map(|leaf| leaf.into_opaque_leaf() .try_decode() - .ok_or(mmr::Error::Verify)).collect::, mmr::Error>>()?; + .ok_or(mmr::Error::Verify)).collect::, mmr::Error>>()?; Mmr::verify_leaves(leaves, proof) } - fn verify_batch_proof_stateless( - root: MmrHash, + fn verify_proof_stateless( + root: mmr::Hash, leaves: Vec, - proof: mmr::BatchProof + proof: mmr::Proof ) -> Result<(), mmr::Error> { let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); - pallet_mmr::verify_leaves_proof::(root, nodes, proof) + pallet_mmr::verify_leaves_proof::(root, nodes, proof) } } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 02729f7565914..a86593f47f9d3 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -28,6 +28,7 @@ use bridge_runtime_common::{ use frame_support::{ parameter_types, traits::{ConstU32, Everything, Nothing}, + weights::Weight, }; use xcm::latest::prelude::*; use xcm_builder::{ @@ -91,7 +92,8 @@ pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const BaseXcmWeight: u64 = BASE_XCM_WEIGHT; + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - check `set_proof_size` 0 or 64*1024 or 1026? + pub const BaseXcmWeight: Weight = Weight::from_parts(BASE_XCM_WEIGHT, 0); /// Maximum number of instructions in a single XCM fragment. A sanity check against weight /// calculations getting too crazy. pub const MaxInstructions: u32 = 100; @@ -142,6 +144,7 @@ impl xcm_executor::Config for XcmConfig { type MessageExporter = (); type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -151,6 +154,11 @@ pub type LocalOriginToLocation = ( SignedToAccountId32, ); +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); +} + impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We don't allow any messages to be sent via the transaction yet. This is basically safe to @@ -180,6 +188,9 @@ impl pallet_xcm::Config for Runtime { type TrustedLockers = (); type SovereignAccountOf = SovereignAccountOf; type MaxLockers = frame_support::traits::ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; } /// With-Millau bridge. diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3e69463480db0..3974966daaddf 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -452,7 +452,7 @@ pub mod target { // I have no idea why this method takes `&mut` reference and there's nothing // about that in documentation. Hope it'll only mutate iff error is returned. let weight = XcmWeigher::weight(&mut payload.xcm.1); - let weight = Weight::from_ref_time(weight.unwrap_or_else(|e| { + let weight = weight.unwrap_or_else(|e| { log::debug!( target: "runtime::bridge-dispatch", "Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}", @@ -463,8 +463,8 @@ pub mod target { // we shall return 0 and then the XCM executor will fail to execute XCM // if we'll return something else (e.g. maximal value), the lane may stuck - 0 - })); + Weight::zero() + }); payload.weight = Some(weight); weight @@ -498,8 +498,8 @@ pub mod target { location, xcm, hash, - weight_limit.unwrap_or_else(Weight::zero).ref_time(), - weight_credit.ref_time(), + weight_limit.unwrap_or_else(Weight::zero), + weight_credit, ); Ok(xcm_outcome) }; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index b4ed3ca58935e..0038af975db75 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -648,7 +648,9 @@ mod tests { fn dispatch_info() -> DispatchInfo { DispatchInfo { - weight: frame_support::weights::constants::WEIGHT_PER_SECOND, + weight: Weight::from_ref_time( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + ), class: frame_support::dispatch::DispatchClass::Normal, pays_fee: frame_support::dispatch::Pays::Yes, } diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 923b35410888a..2dca89d82e5db 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.3.2" } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index 5ef58c5a3cbb4..e05a4119463dc 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -152,6 +152,7 @@ pub mod pallet { BridgedMmrHashing: 'static + Send + Sync, { /// Initialize pallet with BEEFY authority set and best known finalized block number. + #[pallet::call_index(0)] #[pallet::weight((T::DbWeight::get().reads_writes(2, 3), DispatchClass::Operational))] pub fn initialize( origin: OriginFor, @@ -169,6 +170,7 @@ pub mod pallet { /// Change `PalletOwner`. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(1)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { >::set_owner(origin, new_owner) @@ -177,6 +179,7 @@ pub mod pallet { /// Halt or resume all pallet operations. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(2)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operating_mode( origin: OriginFor, @@ -193,6 +196,7 @@ pub mod pallet { /// /// If successful in verification, it will update the underlying storage with the data /// provided in the newly submitted commitment. + #[pallet::call_index(3)] #[pallet::weight(0)] pub fn submit_commitment( origin: OriginFor, @@ -410,12 +414,12 @@ pub mod pallet { #[cfg(test)] mod tests { use super::*; - use beefy_primitives::mmr::BeefyAuthoritySet; use bp_runtime::{BasicOperatingMode, OwnedBridgeModuleError}; use bp_test_utils::generate_owned_bridge_module_tests; use frame_support::{assert_noop, assert_ok, traits::Get}; use mock::*; use mock_chain::*; + use sp_beefy::mmr::BeefyAuthoritySet; use sp_runtime::DispatchError; fn next_block() { diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index a07f7962a44d8..1a028f159343b 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -32,7 +32,7 @@ use sp_runtime::{ Perbill, }; -pub use beefy_primitives::crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; +pub use sp_beefy::crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; use sp_core::crypto::Wraps; use sp_runtime::traits::Keccak256; @@ -49,7 +49,7 @@ pub type TestBridgedMmrHashing = BridgedMmrHashing; pub type TestBridgedMmrHash = BridgedMmrHash; pub type TestBridgedBeefyMmrLeafExtra = BridgedBeefyMmrLeafExtra; pub type TestBridgedMmrProof = BridgedMmrProof; -pub type TestBridgedRawMmrLeaf = beefy_primitives::mmr::MmrLeaf< +pub type TestBridgedRawMmrLeaf = sp_beefy::mmr::MmrLeaf< TestBridgedBlockNumber, TestBridgedBlockHash, TestBridgedMmrHash, @@ -138,7 +138,7 @@ impl ChainWithBeefy for TestBridgedChain { type MmrHash = ::Output; type BeefyMmrLeafExtra = (); type AuthorityId = BeefyId; - type Signature = beefy_primitives::crypto::AuthoritySignature; + type Signature = sp_beefy::crypto::AuthoritySignature; type AuthorityIdToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; } diff --git a/modules/beefy/src/mock_chain.rs b/modules/beefy/src/mock_chain.rs index 4896f9bf90925..ca7e84b121a95 100644 --- a/modules/beefy/src/mock_chain.rs +++ b/modules/beefy/src/mock_chain.rs @@ -26,11 +26,11 @@ use crate::{ utils::get_authorities_mmr_root, }; -use beefy_primitives::mmr::{BeefyNextAuthoritySet, MmrLeafVersion}; use bp_beefy::{BeefyPayload, Commitment, ValidatorSetId, MMR_ROOT_PAYLOAD_ID}; use codec::Encode; use pallet_mmr::NodeIndex; use rand::Rng; +use sp_beefy::mmr::{BeefyNextAuthoritySet, MmrLeafVersion}; use sp_core::Pair; use sp_runtime::traits::{Hash, Header as HeaderT}; use std::collections::HashMap; @@ -188,7 +188,7 @@ impl HeaderBuilder { next_validator_keys.iter().map(|pair| pair.public()).collect::>(); let next_validators_mmr_root = get_authorities_mmr_root::(next_validators.iter()); - let leaf = beefy_primitives::mmr::MmrLeaf { + let leaf = sp_beefy::mmr::MmrLeaf { version: MmrLeafVersion::new(1, 0), parent_number_and_hash: (header.number().saturating_sub(1), *header.parent_hash()), beefy_next_authority_set: BeefyNextAuthoritySet { @@ -227,7 +227,7 @@ impl HeaderBuilder { let leaf_index = *self.header.number() - 1; let leaf_count = *self.header.number(); self.leaf_proof = Some(f(TestBridgedMmrProof { - leaf_index, + leaf_indices: vec![leaf_index], leaf_count, items: proof.proof_items().iter().map(|i| i.hash()).collect(), })); diff --git a/modules/beefy/src/utils.rs b/modules/beefy/src/utils.rs index c8a7d2cee140a..11d601ae8860f 100644 --- a/modules/beefy/src/utils.rs +++ b/modules/beefy/src/utils.rs @@ -3,7 +3,7 @@ use crate::{ BridgedBeefyCommitmentHasher, BridgedBeefyMmrLeaf, BridgedBeefySignedCommitment, BridgedChain, BridgedMmrHash, BridgedMmrHashing, BridgedMmrProof, Config, Error, LOG_TARGET, }; -use bp_beefy::{merkle_root, verify_mmr_leaves_proof, BeefyVerify, MmrDataOrHash, MmrProof}; +use bp_beefy::{merkle_root, verify_mmr_leaves_proof, BeefyVerify, MmrDataOrHash}; use codec::Encode; use frame_support::ensure; use sp_runtime::traits::{Convert, Hash}; @@ -131,7 +131,6 @@ pub(crate) fn verify_beefy_mmr_leaf, I: 'static>( mmr_proof: BridgedMmrProof, mmr_root: BridgedMmrHash, ) -> Result<(), Error> { - let mmr_proof_leaf_index = mmr_proof.leaf_index; let mmr_proof_leaf_count = mmr_proof.leaf_count; let mmr_proof_length = mmr_proof.items.len(); @@ -140,16 +139,15 @@ pub(crate) fn verify_beefy_mmr_leaf, I: 'static>( verify_mmr_leaves_proof( mmr_root, vec![BridgedMmrDataOrHash::::Hash(mmr_leaf_hash)], - MmrProof::into_batch_proof(mmr_proof), + mmr_proof, ) .map_err(|e| { log::error!( target: LOG_TARGET, - "MMR proof of leaf {:?} (root: {:?}, leaf: {}, leaf count: {}, len: {}) \ + "MMR proof of leaf {:?} (root: {:?}, leaf count: {}, len: {}) \ verification has failed with error: {:?}", mmr_leaf_hash, mmr_root, - mmr_proof_leaf_index, mmr_proof_leaf_count, mmr_proof_length, e, @@ -163,9 +161,9 @@ pub(crate) fn verify_beefy_mmr_leaf, I: 'static>( mod tests { use super::*; use crate::{mock::*, mock_chain::*, *}; - use beefy_primitives::ValidatorSet; use bp_beefy::{BeefyPayload, MMR_ROOT_PAYLOAD_ID}; use frame_support::{assert_noop, assert_ok}; + use sp_beefy::ValidatorSet; #[test] fn submit_commitment_checks_metadata() { @@ -280,7 +278,7 @@ mod tests { // Fails if mmr proof is incorrect. let mut header = ChainBuilder::new(1).append_finalized_header().to_header(); - header.leaf_proof.leaf_index += 1; + header.leaf_proof.leaf_indices[0] += 1; assert_noop!( import_commitment(header), Error::::MmrProofVerificationFailed, diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 6853bb9cb3bb0..d3335693adfa7 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -150,6 +150,7 @@ pub mod pallet { /// /// If successful in verification, it will write the target header to the underlying storage /// pallet. + #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::submit_finality_proof( justification.commit.precommits.len().try_into().unwrap_or(u32::MAX), justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX), @@ -221,6 +222,7 @@ pub mod pallet { /// This function is only allowed to be called from a trusted origin and writes to storage /// with practically no checks in terms of the validity of the data. It is important that /// you ensure that valid data is being passed in. + #[pallet::call_index(1)] #[pallet::weight((T::DbWeight::get().reads_writes(2, 5), DispatchClass::Operational))] pub fn initialize( origin: OriginFor, @@ -244,6 +246,7 @@ pub mod pallet { /// Change `PalletOwner`. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(2)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { >::set_owner(origin, new_owner) @@ -252,6 +255,7 @@ pub mod pallet { /// Halt or resume all pallet operations. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(3)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operating_mode( origin: OriginFor, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index b8d79b83b4187..680518d9dc8b2 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -226,6 +226,7 @@ pub mod pallet { /// Change `PalletOwner`. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(0)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { >::set_owner(origin, new_owner) @@ -234,6 +235,7 @@ pub mod pallet { /// Halt or resume all/some pallet operations. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(1)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operating_mode( origin: OriginFor, @@ -247,6 +249,7 @@ pub mod pallet { /// The weight of the call assumes that the transaction always brings outbound lane /// state update. Because of that, the submitter (relayer) has no benefit of not including /// this data in the transaction, so reward confirmations lags should be minimal. + #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight))] pub fn receive_messages_proof( origin: OriginFor, @@ -399,6 +402,7 @@ pub mod pallet { } /// Receive messages delivery proof from bridged chain. + #[pallet::call_index(3)] #[pallet::weight(T::WeightInfo::receive_messages_delivery_proof_weight( proof, relayers_state, diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 633b39329a012..47ab91928c7b7 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -263,6 +263,7 @@ pub mod pallet { /// `polkadot-runtime-parachains::paras` pallet instance, deployed at the bridged chain. /// The proof is supposed to be crafted at the `relay_header_hash` that must already be /// imported by corresponding GRANDPA pallet at this chain. + #[pallet::call_index(0)] #[pallet::weight(WeightInfoOf::::submit_parachain_heads_weight( T::DbWeight::get(), parachain_heads_proof, @@ -395,6 +396,7 @@ pub mod pallet { /// Change `PalletOwner`. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(1)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { >::set_owner(origin, new_owner) @@ -403,6 +405,7 @@ pub mod pallet { /// Halt or resume all pallet operations. /// /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(2)] #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] pub fn set_operating_mode( origin: OriginFor, diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 27ffcaf1ea523..b28d17cf5a4fd 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -65,6 +65,7 @@ pub mod pallet { #[pallet::call] impl Pallet { /// Claim accumulated rewards. + #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::claim_rewards())] pub fn claim_rewards(origin: OriginFor, lane_id: LaneId) -> DispatchResult { let relayer = ensure_signed(origin)?; diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index e619e52cfc22e..cc8360c7106ac 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -18,7 +18,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -beefy-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -28,7 +28,6 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ - "beefy-primitives/std", "bp-runtime/std", "codec/std", "frame-support/std", @@ -36,6 +35,7 @@ std = [ "pallet-mmr/std", "scale-info/std", "serde", + "sp-beefy/std", "sp-runtime/std", "sp-std/std" ] diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index a0a096bdce17c..f16c10820070d 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -20,18 +20,18 @@ #![warn(missing_docs)] pub use beefy_merkle_tree::{merkle_root, Keccak256 as BeefyKeccak256}; -pub use beefy_primitives::{ +pub use pallet_beefy_mmr::BeefyEcdsaToEthereum; +pub use pallet_mmr::{ + primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof}, + verify_leaves_proof as verify_mmr_leaves_proof, +}; +pub use sp_beefy::{ crypto::{AuthorityId as EcdsaValidatorId, AuthoritySignature as EcdsaValidatorSignature}, known_payloads::MMR_ROOT_ID as MMR_ROOT_PAYLOAD_ID, mmr::{BeefyAuthoritySet, MmrLeafVersion}, BeefyAuthorityId, BeefyVerify, Commitment, Payload as BeefyPayload, SignedCommitment, ValidatorSet, ValidatorSetId, BEEFY_ENGINE_ID, }; -pub use pallet_beefy_mmr::BeefyEcdsaToEthereum; -pub use pallet_mmr::{ - primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof}, - verify_leaves_proof as verify_mmr_leaves_proof, -}; use bp_runtime::{BasicOperatingMode, BlockNumberOf, Chain, HashOf}; use codec::{Decode, Encode}; @@ -99,7 +99,7 @@ pub type BeefyAuthorityIdOf = ::AuthorityId; /// BEEFY validator set, containing both validator identifiers and the numeric set id. pub type BeefyAuthoritySetOf = ValidatorSet>; /// BEEFY authority set, containing both validator identifiers and the numeric set id. -pub type BeefyAuthoritySetInfoOf = beefy_primitives::mmr::BeefyAuthoritySet>; +pub type BeefyAuthoritySetInfoOf = sp_beefy::mmr::BeefyAuthoritySet>; /// BEEFY validator signature used by given Substrate chain. pub type BeefyValidatorSignatureOf = ::Signature; /// Signed BEEFY commitment used by given Substrate chain. @@ -119,12 +119,8 @@ pub type BeefyMmrLeafExtraOf = ::BeefyMmrLeafExtra; /// the given Substrate chain. pub type BeefyAuthorityIdToMerkleLeafOf = ::AuthorityIdToMerkleLeaf; /// Actual type of leafs in the BEEFY MMR. -pub type BeefyMmrLeafOf = beefy_primitives::mmr::MmrLeaf< - BlockNumberOf, - HashOf, - MmrHashOf, - BeefyMmrLeafExtraOf, ->; +pub type BeefyMmrLeafOf = + sp_beefy::mmr::MmrLeaf, HashOf, MmrHashOf, BeefyMmrLeafExtraOf>; /// Data required for initializing the BEEFY pallet. /// diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 0f5f33087edc7..72faabe43cd98 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -39,7 +39,8 @@ pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// time. /// /// This is a copy-paste from the cumulus repo's `parachains-common` crate. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = constants::WEIGHT_PER_SECOND +// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` +const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_SECOND) .saturating_div(2) .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); @@ -55,9 +56,9 @@ parameter_types! { NORMAL_DISPATCH_RATIO, ); - pub const BlockExecutionWeight: Weight = constants::WEIGHT_PER_NANOS.saturating_mul(5_000_000); + pub const BlockExecutionWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS).saturating_mul(5_000_000); - pub const ExtrinsicBaseWeight: Weight = constants::WEIGHT_PER_NANOS.saturating_mul(125_000); + pub const ExtrinsicBaseWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS).saturating_mul(125_000); pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() .base_block(BlockExecutionWeight::get()) diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 2a4139e07cb99..5c3b7f18ab43f 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -27,7 +27,7 @@ use bp_messages::{ use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, - weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, RuntimeDebug, }; use frame_system::limits; @@ -60,7 +60,9 @@ pub const TX_EXTRA_BYTES: u32 = 103; /// /// This represents 0.5 seconds of compute assuming a target block time of six seconds. // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_div(2); +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) + .set_proof_size(1_000) + .saturating_div(2); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 82b6a12c182a3..8a98ffe70619e 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -24,7 +24,7 @@ use bp_messages::{ use bp_runtime::{decl_bridge_runtime_apis, Chain, Parachain}; use frame_support::{ dispatch::DispatchClass, - weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, RuntimeDebug, }; use frame_system::limits; @@ -55,7 +55,9 @@ pub const TX_EXTRA_BYTES: u32 = 104; /// /// This represents two seconds of compute assuming a target block time of six seconds. // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_mul(2); +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) + .set_proof_size(1_000) + .saturating_mul(2); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 0b718ec52158e..5cf4f85f54a53 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -24,7 +24,7 @@ use bp_messages::{ use bp_runtime::{decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, - weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, RuntimeDebug, }; use frame_system::limits; @@ -49,7 +49,9 @@ pub const TX_EXTRA_BYTES: u32 = 104; /// /// This represents two seconds of compute assuming a target block time of six seconds. // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_mul(2); +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) + .set_proof_size(1_000) + .saturating_mul(2); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 8d9932ea58c52..7558ce762d026 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -23,7 +23,7 @@ use frame_support::{ dispatch::DispatchClass, parameter_types, weights::{ - constants::{BlockExecutionWeight, WEIGHT_PER_SECOND}, + constants::{BlockExecutionWeight, WEIGHT_REF_TIME_PER_SECOND}, Weight, }, Blake2_128Concat, RuntimeDebug, @@ -74,7 +74,9 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND.set_proof_size(1_000).saturating_mul(2); +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) + .set_proof_size(1_000) + .saturating_mul(2); /// All Polkadot-like chains assume that an on-initialize consumes 1 percent of the weight on /// average, hence a single extrinsic will not be allowed to consume more than diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index f5771e9fdd57e..94b3a193c5829 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -21,7 +21,7 @@ use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Ze use sp_runtime::{ traits::{ AtLeast32Bit, AtLeast32BitUnsigned, Hash as HashT, Header as HeaderT, MaybeDisplay, - MaybeMallocSizeOf, MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify, + MaybeSerialize, MaybeSerializeDeserialize, Member, SimpleBitOps, Verify, }, FixedPointOperand, }; @@ -107,7 +107,6 @@ pub trait Chain: Send + Sync + 'static { + MaybeDisplay + AtLeast32BitUnsigned + FromStr - + MaybeMallocSizeOf + AsPrimitive + Default + Saturating @@ -128,7 +127,6 @@ pub trait Chain: Send + Sync + 'static { + SimpleBitOps + AsRef<[u8]> + AsMut<[u8]> - + MaybeMallocSizeOf + MaxEncodedLen; /// A type that fulfills the abstract idea of what a Substrate hasher (a type diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 61ea72853f43c..73d441cfcd381 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -495,7 +495,7 @@ mod tests { // Any significant change in this values should attract additional attention. // // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` - (1024, Weight::from_ref_time(216_609_134_667).set_proof_size(217)), + (1024, Weight::from_ref_time(216_600_684_000).set_proof_size(217)), ); } } From 5cded1f422a9c767a95336de2fb05ea017f20b12 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 16 Jan 2023 10:56:40 +0200 Subject: [PATCH 0871/1210] docs: add Security Policy doc (#1770) Signed-off-by: acatangiu --- SECURITY.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000000..65f2f3bff05dd --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +Thanks for helping make the Parity ecosystem more secure. Security is one of our first priorities. + +## Reporting a vulnerability + +If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it in the public forum as it can cause more damage, rather than giving real help to the ecosystem. + +Security vulnerabilities should be reported by the [contact form](https://security-submission.parity.io/). + +If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information about our Bug Bounty Program. + +**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for information. + From a063c2f7094ae150909aaf6494eed294b8fee11c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 16 Jan 2023 13:42:06 +0300 Subject: [PATCH 0872/1210] added/updated pallet level docs to grandpa and messages pallets (#1771) --- docs/high-level-overview.md | 4 +- modules/grandpa/README.md | 83 +++++++++++ modules/messages/README.md | 286 +++++++----------------------------- 3 files changed, 137 insertions(+), 236 deletions(-) create mode 100644 modules/grandpa/README.md diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 2c174dbc98a4c..5a76347ce4f6c 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -115,7 +115,7 @@ the source chain GRANDPA justifications stream and submits every new justificati target chain GRANDPA light client. In addition, relay is searching for mandatory headers and submits their justifications - without that the pallet will be unable to move forward. -More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [code](../relays/finality/). +More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and code](../relays/finality/). ### Parachains Finality Relay @@ -158,7 +158,7 @@ relay submits transactions to both source and target chains, it requires both _s _target-to-source_ finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, depending on the type of connected chain. -More: [Messages Relay Sequence Diagram](./messages-relay.html), [code](../relays/messages/). +More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and code](../relays/messages/). ### Complex Relay diff --git a/modules/grandpa/README.md b/modules/grandpa/README.md new file mode 100644 index 0000000000000..a4fc68028fb33 --- /dev/null +++ b/modules/grandpa/README.md @@ -0,0 +1,83 @@ +# Bridge GRANDPA Pallet + +The bridge GRANDPA pallet is a light client for the GRANDPA finality gadget, running at the bridged chain. +It may import headers and their GRANDPA finality proofs (justifications) of the bridged chain. Imported +headers then may be used to verify storage proofs by other pallets. This makes the bridge GRANDPA pallet +a basic pallet of all bridges with Substrate-based chains. It is used by all bridge types (bridge between +standalone chains, between parachains and any combination of those) and is used by other bridge pallets. +It is used by the parachains light client (bridge parachains pallet) and by messages pallet. + +## A Brief Introduction into GRANDPA Finality + +You can find detailed information on GRANDPA, by exploring its [repository](https://github.com/paritytech/finality-grandpa). +Here is the minimal reqiuired GRANDPA information to understand how pallet works. + +Any Substrate chain may use different block authorship algorithms (like BABE or Aura) to determine block producers and +generate blocks. This has nothing common with finality, though - the task of block authorship is to coordinate +blocks generation. Any block may be reverted (if there's a fork) if it is not finalized. The finality solution +for (standalone) Substrate-based chains is the GRANDPA finality gadget. If some block is finalized by the gadget, it +can't be reverted. + +In GRANDPA, there are validators, identified by their public keys. They select some generated block and produce +signatures on this block hash. If there are enough (more than `2 / 3 * N`, where `N` is number of validators) +signatures, then the block is considered finalized. The set of signatures for the block is called justification. +Anyone who knows the public keys of validators is able to verify GRANDPA justification and that it is generated +for provided header. + +There are two main things in GRANDPA that help building light clients: + +- there's no need to import all headers of the bridged chain. Light client may import finalized headers or just + some of finalized headders that it consider useful. While the validators set stays the same, the client may + import any header that is finalized by this set; +- when validators set changes, the GRANDPA gadget adds next set to the header. So light client doesn't need to + verify storage proofs when this happens - it only needs to look at the header and see if it changes the set. + Once set is changed, all following justifications are generated by the new set. Header that is changing the + set is called "mandatory" in the pallet. As the name says, the light client need to import all such headers + to be able to operate properly. + +## Pallet Operations + +The main entrypoint of the pallet is the `submit_finality_proof` call. It has two arguments - the finalized +headers and associated GRANDPA justification. The call simply verifies the justification using current +validators set and checks if header is better than the previous best header. If both checks are passed, the +header (only its useful fields) is inserted into the runtime storage and may be used by other pallets to verify +storage proofs. + +The submitter pays regular fee for submitting all headers, except for the mandatory header. Since it is +required for the pallet operations, submitting such header is free. So if you're ok with session-length +lags (meaning that there's exactly 1 mandatory header per session), the cost of pallet calls is zero. + +When the pallet sees mandatory header, it updates the validators set with the set from the header. All +following justifications (until next mandatory header) must be generated by this new set. + +## Pallet Initialization + +As the previous section states, there are two things that are mandatory for pallet operations: best finalized +header and the current validators set. Without it the pallet can't import any headers. But how to provide +initial values for these fields? There are two options. + +First option, while it is easier, doesn't work in all cases. It is to start chain with initial header and +validators set specified in the chain specification. This won't work, however, if we want to add bridge +to already started chain. + +For the latter case we have the `initialize` call. It accepts the initial header and initial validators set. +The call may be called by the governance, root or by the pallet owner (if it is set). + +## Non-Essential Functionality + +There may be a special account in every runtime where the bridge GRANDPA module is deployed. This +account, named 'module owner', is like a module-level sudo account - he's able to halt and +resume all module operations without requiring runtime upgrade. Calls that are related to this +account are: +- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; +- `fn set_operating_mode()`: the module owner (or sudo account) may call this function to stop all + module operations. After this call, all finality proofs will be rejected until further `set_operating_mode` call'. + This call may be used when something extraordinary happens with the bridge; +- `fn initialize()`: module owner may call this function to initialize the bridge. + +If pallet owner is not defined, the governance may be used to make those calls. + +## GRANDPA Finality Relay + +We have an offchain actor, who is watching for GRANDPA justifications and submits them to the bridged chain. +It is the finality relay - you may look at the [crate level documentation and the code](../../relays/finality/). diff --git a/modules/messages/README.md b/modules/messages/README.md index 2dc5629684242..0d1ea7fe44a0f 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -1,10 +1,11 @@ -# Messages Module +# Bridge Messages Pallet -The messages module is used to deliver messages from source chain to target chain. Message is +The messages pallet is used to deliver messages from source chain to target chain. Message is (almost) opaque to the module and the final goal is to hand message to the message dispatch mechanism. ## Contents + - [Overview](#overview) - [Message Workflow](#message-workflow) - [Integrating Message Lane Module into Runtime](#integrating-messages-module-into-runtime) @@ -30,13 +31,22 @@ Single message lane may be seen as a transport channel for single application (o mixed). At the same time the module itself never dictates any lane or message rules. In the end, it is the runtime developer who defines what message lane and message mean for this runtime. +In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane +as a channel of communication between two parachains of different relay chains. For example, lane +`[0, 0, 0, 0]` is used for Statemint <> Statemine communications. Other lanes may be used to bridge +another parachains. + ## Message Workflow -The message "appears" when its submitter calls the `send_message()` function of the module. The -submitter specifies the lane that he's willing to use, the message itself and the fee that he's -willing to pay for the message delivery and dispatch. If a message passes all checks, the nonce is -assigned and the message is stored in the module storage. The message is in an "undelivered" state -now. +The pallet is not intended to be used by end users and provides no public calls to send the message. +Instead, it provides runtime-internal method that allows other pallets (or other runtime code) to queue +outbound messages. + +The message "appears" when some runtime code calls the `send_message()` method of the pallet. +The submitter specifies the lane that he's willing to use and the message itself. If some fee must be +paid for sending the message, it must be paid outside of the pallet. If a message passes all checks +(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and the +message is stored in the module storage. The message is in an "undelivered" state now. We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to both target and source chains. The pallet itself has no assumptions about @@ -94,22 +104,23 @@ to change something in this scheme, get back here for detailed information. The messages module supports instances. Every module instance is supposed to bridge this chain and some bridged chain. To bridge with another chain, using another instance is suggested (this -isn't forced anywhere in the code, though). +isn't forced anywhere in the code, though). Keep in mind, that the pallet may be used to build +virtual channels between multiple chains, as we do in our [Polkadot <> Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). +There, the pallet actually bridges only two parachains - Kusama Bridge Hub and Polkadot +Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages to their +Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper +destination parachain within the bridged chain consensus. Message submitters may track message progress by inspecting module events. When Message is accepted, -the `MessageAccepted` event is emitted in the `send_message()` transaction. The event contains both -message lane identifier and nonce that has been assigned to the message. When a message is delivered -to the target chain, the `MessagesDelivered` event is emitted from the -`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane -identifier, inclusive range of delivered message nonces and their single-bit dispatch results. - -Please note that the meaning of the 'dispatch result' is determined by the message dispatcher at -the target chain. For example, in case of immediate call dispatcher it will be the `true` if call -has been successfully dispatched and `false` if it has only been delivered. This simple mechanism -built into the messages module allows building basic bridge applications, which only care whether -their messages have been successfully dispatched or not. More sophisticated applications may use -their own dispatch result delivery mechanism to deliver something larger than single bit. - +the `MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that +has been assigned to the message. When a message is delivered to the target chain, the `MessagesDelivered` +event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains +the message lane identifier and inclusive range of delivered message nonces. + +The pallet provides no means to get the result of message dispatch at the target chain. If that is +required, it must be done outside of the pallet. For example, XCM messages, when dispatched, have +special instructions to send some data back to the sender. Other dispatchers may use similar +mechanism for that. ### How to plug-in Messages Module to Send Messages to the Bridged Chain? The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with @@ -138,16 +149,12 @@ messages and you may charge zero fee for such messages. You may have some rate l sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation. -The last type is the `pallet_bridge_messages::Config::MessageDeliveryAndDispatchPayment`. When all -checks are made and we have decided to accept the message, we're calling the -`pay_delivery_and_dispatch_fee()` callback, passing the corresponding argument of the `send_message` -function. Later, when message delivery is confirmed, we're calling `pay_relayers_rewards()` -callback, passing accounts of relayers and messages that they have delivered. The simplest -implementation of this trait is in the [`instant_payments.rs`](./src/instant_payments.rs) module and -simply calls `Currency::transfer()` when those callbacks are called. So `Currency` units are -transferred between submitter, 'relayers fund' and relayers accounts. Other implementations may use -more or less sophisticated techniques - the whole relayers incentivization scheme is not a part of -the messages module. +The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation +transaction is received, we call the `pay_reward()` method, passing the range of delivered messages. +You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its +[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible +implementation. It allows you to pay fixed reward for relaying the message and some its portion +for confirming delivery. ### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? @@ -159,7 +166,7 @@ all required traits and will simply reject all transactions, related to outbound The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the -bridged chain as the source or our inbound messages. When relayer sends us a delivery transaction, +bridged chain as the source of our inbound messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are sending messages to the same bridged chain. @@ -168,8 +175,7 @@ The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to di messages. Apart from actually dispatching the message, the implementation must return the correct dispatch weight of the message before dispatch is called. -### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What -shall I do? +### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do? You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from the [`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It @@ -177,13 +183,10 @@ implements all required traits and will simply reject all transactions, related ### What about other Constants in the Messages Module Configuration Trait? -Message is being stored in the source chain storage until its delivery will be confirmed. After -that, we may safely remove the message from the storage. Lane messages are removed (pruned) when -someone sends a new message using the same lane. So the message submitter pays for that pruning. To -avoid pruning too many messages in a single transaction, there's -`pallet_bridge_messages::Config::MaxMessagesToPruneAtOnce` configuration parameter. We will never prune -more than this number of messages in the single transaction. That said, the value should not be too -big to avoid waste of resources when there are no messages to prune. +Two setttings that are used to check messages in the `send_message()` function. The +`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that +may be used to send messages. All messages sent using other lanes are rejected. All messages that have +size above `pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected. To be able to reward the relayer for delivering messages, we store a map of message nonces range => identifier of the relayer that has delivered this range at the target chain runtime storage. If a @@ -219,13 +222,9 @@ large maps, at the same time keeping reserve for future source chain upgrades. ## Non-Essential Functionality -Apart from the message related calls, the module exposes a set of auxiliary calls. They fall in two -groups, described in the next two paragraphs. - There may be a special account in every runtime where the messages module is deployed. This -account, named 'module owner', is like a module-level sudo account - he's able to halt all and -result all module operations without requiring runtime upgrade. The module may have no message -owner, but we suggest to use it at least for initial deployment. To calls that are related to this +account, named 'module owner', is like a module-level sudo account - he's able to halt and +resume all module operations without requiring runtime upgrade. Calls that are related to this account are: - `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; - `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all @@ -235,190 +234,9 @@ account are: - `fn resume_operations()`: module owner may call this function to resume bridge operations. The module will resume its regular operations after this call. -Apart from halting and resuming the bridge, the module owner may also tune module configuration -parameters without runtime upgrades. The set of parameters needs to be designed in advance, though. -The module configuration trait has associated `Parameter` type, which may be e.g. enum and represent -a set of parameters that may be updated by the module owner. For example, if your bridge needs to -convert sums between different tokens, you may define a 'conversion rate' parameter and let the -module owner update this parameter when there are significant changes in the rate. The corresponding -module call is `fn update_pallet_parameter()`. - -## Weights of Module Extrinsics - -The main assumptions behind weight formulas is: -- all possible costs are paid in advance by the message submitter; -- whenever possible, relayer tries to minimize cost of its transactions. So e.g. even though sender - always pays for delivering outbound lane state proof, relayer may not include it in the delivery - transaction (unless messages module on target chain requires that); -- weight formula should incentivize relayer to not to submit any redundant data in the extrinsics - arguments; -- the extrinsic shall never be executing slower (i.e. has larger actual weight) than defined by the - formula. - -### Weight of `send_message` call - -#### Related benchmarks - -| Benchmark | Description | -|-----------------------------------|-----------------------------------------------------| -`send_minimal_message_worst_case` | Sends 0-size message with worst possible conditions | -`send_1_kb_message_worst_case` | Sends 1KB-size message with worst possible conditions | -`send_16_kb_message_worst_case` | Sends 16KB-size message with worst possible conditions | - -#### Weight formula - -The weight formula is: -``` -Weight = BaseWeight + MessageSizeInKilobytes * MessageKiloByteSendWeight -``` - -Where: - -| Component | How it is computed? | Description | -|-----------------------------|------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------| -| `SendMessageOverhead` | `send_minimal_message_worst_case` | Weight of sending minimal (0 bytes) message | -| `MessageKiloByteSendWeight` | `(send_16_kb_message_worst_case - send_1_kb_message_worst_case)/15` | Weight of sending every additional kilobyte of the message | - -### Weight of `receive_messages_proof` call - -#### Related benchmarks - -| Benchmark | Description* | -|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------| -| `receive_single_message_proof` | Receives proof of single `EXPECTED_DEFAULT_MESSAGE_LENGTH` message | -| `receive_two_messages_proof` | Receives proof of two identical `EXPECTED_DEFAULT_MESSAGE_LENGTH` messages | -| `receive_single_message_proof_with_outbound_lane_state` | Receives proof of single `EXPECTED_DEFAULT_MESSAGE_LENGTH` message and proof of outbound lane state at the source chain | -| `receive_single_message_proof_1_kb` | Receives proof of single message. The proof has size of approximately 1KB** | -| `receive_single_message_proof_16_kb` | Receives proof of single message. The proof has size of approximately 16KB** | - -*\* - In all benchmarks all received messages are dispatched and their dispatch cost is near to zero* - -*\*\* - Trie leafs are assumed to have minimal values. The proof is derived from the minimal proof -by including more trie nodes. That's because according to our additioal benchmarks, increasing proof -by including more nodes has slightly larger impact on performance than increasing values stored in leafs*. - -#### Weight formula - -The weight formula is: -``` -Weight = BaseWeight + OutboundStateDeliveryWeight - + MessagesCount * MessageDeliveryWeight - + MessagesDispatchWeight - + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight -``` - -Where: - -| Component | How it is computed? | Description | -|-------------------------------|------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `BaseWeight` | `2*receive_single_message_proof - receive_two_messages_proof` | Weight of receiving and parsing minimal proof | -| `OutboundStateDeliveryWeight` | `receive_single_message_proof_with_outbound_lane_state - receive_single_message_proof` | Additional weight when proof includes outbound lane state | -| `MessageDeliveryWeight` | `receive_two_messages_proof - receive_single_message_proof` | Weight of of parsing and dispatching (without actual dispatch cost) of every message | -| `MessagesCount` | | Provided by relayer | -| `MessagesDispatchWeight` | | Provided by relayer | -| `ActualProofSize` | | Provided by relayer | -| `ExpectedProofSize` | `EXPECTED_DEFAULT_MESSAGE_LENGTH * MessagesCount + EXTRA_STORAGE_PROOF_SIZE` | Size of proof that we are expecting. This only includes `EXTRA_STORAGE_PROOF_SIZE` once, because we assume that intermediate nodes likely to be included in the proof only once. This may be wrong, but since weight of processing proof with many nodes is almost equal to processing proof with large leafs, additional cost will be covered because we're charging for extra proof bytes anyway | -| `ProofByteDeliveryWeight` | `(receive_single_message_proof_16_kb - receive_single_message_proof_1_kb) / (15 * 1024)` | Weight of processing every additional proof byte over `ExpectedProofSize` limit | - -#### Why for every message sent using `send_message` we will be able to craft `receive_messages_proof` transaction? - -We have following checks in `send_message` transaction on the source chain: -- message size should be less than or equal to `2/3` of maximal extrinsic size on the target chain; -- message dispatch weight should be less than or equal to the `1/2` of maximal extrinsic dispatch - weight on the target chain. - -Delivery transaction is an encoded delivery call and signed extensions. So we have `1/3` of maximal -extrinsic size reserved for: -- storage proof, excluding the message itself. Currently, on our test chains, the overhead is always - within `EXTRA_STORAGE_PROOF_SIZE` limits (1024 bytes); -- signed extras and other call arguments (`relayer_id: SourceChain::AccountId`, `messages_count: - u32`, `dispatch_weight: u64`). - -On Millau chain, maximal extrinsic size is `0.75 * 2MB`, so `1/3` is `512KB` (`524_288` bytes). This -should be enough to cover these extra arguments and signed extensions. - -Let's exclude message dispatch cost from single message delivery transaction weight formula: -``` -Weight = BaseWeight + OutboundStateDeliveryWeight + MessageDeliveryWeight - + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight -``` - -So we have `1/2` of maximal extrinsic weight to cover these components. `BaseWeight`, -`OutboundStateDeliveryWeight` and `MessageDeliveryWeight` are determined using benchmarks and are -hardcoded into runtime. Adequate relayer would only include required trie nodes into the proof. So -if message size would be maximal (`2/3` of `MaximalExtrinsicSize`), then the extra proof size would -be `MaximalExtrinsicSize / 3 * 2 - EXPECTED_DEFAULT_MESSAGE_LENGTH`. - -Both conditions are verified by `pallet_bridge_messages::ensure_weights_are_correct` and -`pallet_bridge_messages::ensure_able_to_receive_messages` functions, which must be called from every -runtime's tests. - -#### Post-dispatch weight refunds of the `receive_messages_proof` call - -Weight formula of the `receive_messages_proof` call assumes that the dispatch fee of every message is -paid at the target chain (where call is executed), that every message will be dispatched and that -dispatch weight of the message will be exactly the weight that is returned from the -`MessageDispatch::dispatch_weight` method call. This isn't true for all messages, so the call returns -actual weight used to dispatch messages. - -This actual weight is the weight, returned by the weight formula, minus: -- the weight of undispatched messages, if we have failed to dispatch because of different issues; -- the unspent dispatch weight if the declared weight of some messages is less than their actual post-dispatch weight; -- the pay-dispatch-fee weight for every message that had dispatch fee paid at the source chain. - -The last component is computed as a difference between two benchmarks results - the `receive_single_message_proof` -benchmark (that assumes that the fee is paid during dispatch) and the `receive_single_prepaid_message_proof` -(that assumes that the dispatch fee is already paid). - -### Weight of `receive_messages_delivery_proof` call - -#### Related benchmarks - -| Benchmark | Description | -|-------------------------------------------------------------|------------------------------------------------------------------------------------------| -| `receive_delivery_proof_for_single_message` | Receives proof of single message delivery | -| `receive_delivery_proof_for_two_messages_by_single_relayer` | Receives proof of two messages delivery. Both messages are delivered by the same relayer | -| `receive_delivery_proof_for_two_messages_by_two_relayers` | Receives proof of two messages delivery. Messages are delivered by different relayers | - -#### Weight formula - -The weight formula is: -``` -Weight = BaseWeight + MessagesCount * MessageConfirmationWeight - + RelayersCount * RelayerRewardWeight - + Max(0, ActualProofSize - ExpectedProofSize) * ProofByteDeliveryWeight - + MessagesCount * (DbReadWeight + DbWriteWeight) -``` - -Where: - -| Component | How it is computed? | Description | -|---------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `BaseWeight` | `2*receive_delivery_proof_for_single_message - receive_delivery_proof_for_two_messages_by_single_relayer` | Weight of receiving and parsing minimal delivery proof | -| `MessageDeliveryWeight` | `receive_delivery_proof_for_two_messages_by_single_relayer - receive_delivery_proof_for_single_message` | Weight of confirming every additional message | -| `MessagesCount` | | Provided by relayer | -| `RelayerRewardWeight` | `receive_delivery_proof_for_two_messages_by_two_relayers - receive_delivery_proof_for_two_messages_by_single_relayer` | Weight of rewarding every additional relayer | -| `RelayersCount` | | Provided by relayer | -| `ActualProofSize` | | Provided by relayer | -| `ExpectedProofSize` | `EXTRA_STORAGE_PROOF_SIZE` | Size of proof that we are expecting | -| `ProofByteDeliveryWeight` | `(receive_single_message_proof_16_kb - receive_single_message_proof_1_kb) / (15 * 1024)` | Weight of processing every additional proof byte over `ExpectedProofSize` limit. We're using the same formula, as for message delivery, because proof mechanism is assumed to be the same in both cases | - -#### Post-dispatch weight refunds of the `receive_messages_delivery_proof` call - -Weight formula of the `receive_messages_delivery_proof` call assumes that all messages in the proof -are actually delivered (so there are no already confirmed messages) and every messages is processed -by the `OnDeliveryConfirmed` callback. This means that for every message, we're adding single db read -weight and single db write weight. If, by some reason, messages are not processed by the -`OnDeliveryConfirmed` callback, or their processing is faster than that additional weight, the -difference is refunded to the submitter. - -#### Why we're always able to craft `receive_messages_delivery_proof` transaction? - -There can be at most `::MaxUnconfirmedMessagesAtInboundLane` -messages and at most -`::MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded -relayers in the single delivery confirmation transaction. - -We're checking that this transaction may be crafted in the -`pallet_bridge_messages::ensure_able_to_receive_confirmation` function, which must be called from every -runtime' tests. +If pallet owner is not defined, the governance may be used to make those calls. + +## Messages Relay + +We have an offchain actor, who is watching for new messages and submits them to the bridged chain. +It is the messages relay - you may look at the [crate level documentation and the code](../../relays/messages/). From 2328b8cbeebe07ead03cf367bb06e7c9af8dae5d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 17 Jan 2023 11:07:17 +0300 Subject: [PATCH 0873/1210] Added crate-level docs for the parachains pallet (#1772) * crate-level docs for the parachains pallet * fix typos --- modules/grandpa/README.md | 18 ++++++++ modules/parachains/README.md | 90 ++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 modules/parachains/README.md diff --git a/modules/grandpa/README.md b/modules/grandpa/README.md index a4fc68028fb33..eaa62e8b20601 100644 --- a/modules/grandpa/README.md +++ b/modules/grandpa/README.md @@ -29,6 +29,7 @@ There are two main things in GRANDPA that help building light clients: - there's no need to import all headers of the bridged chain. Light client may import finalized headers or just some of finalized headders that it consider useful. While the validators set stays the same, the client may import any header that is finalized by this set; + - when validators set changes, the GRANDPA gadget adds next set to the header. So light client doesn't need to verify storage proofs when this happens - it only needs to look at the header and see if it changes the set. Once set is changed, all following justifications are generated by the new set. Header that is changing the @@ -69,14 +70,31 @@ There may be a special account in every runtime where the bridge GRANDPA module account, named 'module owner', is like a module-level sudo account - he's able to halt and resume all module operations without requiring runtime upgrade. Calls that are related to this account are: + - `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; + - `fn set_operating_mode()`: the module owner (or sudo account) may call this function to stop all module operations. After this call, all finality proofs will be rejected until further `set_operating_mode` call'. This call may be used when something extraordinary happens with the bridge; + - `fn initialize()`: module owner may call this function to initialize the bridge. If pallet owner is not defined, the governance may be used to make those calls. +## Signed Extension to Reject Obsolete Headers + +It'd be better for anyone (for chain and for submitters) to reject all transactions that are submitting +already known headers to the pallet. This way, we leave block space to other useful transactions and +we don't charge concurrent submitters for their honest actions. + +To deal with that, we have a [signed extension](./src/extension.rs) that may be added to the runtime. +It does exactly what is required - rejects all transactions with already known headers. The submitter +pays nothing for such transactions - they're simply removed from the transaction pool, when the block +is built. + +You may also take a look at the [`generate_bridge_reject_obsolete_headers_and_messages`](../../bin/runtime-common/src/lib.rs) +macro that bundles several similar signed extensions in a single one. + ## GRANDPA Finality Relay We have an offchain actor, who is watching for GRANDPA justifications and submits them to the bridged chain. diff --git a/modules/parachains/README.md b/modules/parachains/README.md new file mode 100644 index 0000000000000..1bd91a3ba776f --- /dev/null +++ b/modules/parachains/README.md @@ -0,0 +1,90 @@ +# Bridge Parachains Pallet + +The bridge parachains pallet is a light client for one or several parachains of the bridged relay chain. +It serves as a source of finalized parachain headers and is used when you need to build a bridge with +a parachain. + +The pallet requires [bridge GRANDPA pallet](../grandpa/) to be deployed at the same chain - it is used +to verify storage proofs, generated at the bridged relay chain. + +## A Brief Introduction into Parachains Finality + +You can find detailed information on parachains finality in the [Polkadot](https://github.com/paritytech/polkadot) +and [Cumulus](https://github.com/paritytech/cumulus) repositories. This section gives a brief overview of how +the parachain finality works and how to build a light client for a parachain. + +The main thing there is that the parachain generates blocks on its own, but it can't achieve finality without +help of its relay chain. Instead, the parachain collators create a block and hand it over to the relay chain +validators. Validators validate the block and register the new parachain head in the +[`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645) +of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet, +deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet, +even though the names are similar. + +And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that +`Heads` map. It does that using relay chain header, that has been previously imported by the +[bridge GRANDPA pallet](../grandpa/). Once the proof is verified, the pallet knows that the given parachain +header has been finalized by the relay chain. The parachain header fields may then be used to verify storage +proofs, coming from the parachain. This allows the pallet to be used e.g. as a source of finality for the messages +pallet. + +## Pallet Operations + +The main entrypoint of the pallet is the `submit_parachain_heads` call. It has three arguments: + +- storage proof of parachain heads from the `Heads` map; + +- parachain identifiers and hashes of their heads from the storage proof; + +- the relay block, at which the storage proof has been generated. + +The pallet may track multiple parachains. And the parachains may use different primitives - one may use 128-bit block +numbers, other - 32-bit. To avoid extra decode operations, the pallet is using relay chain block number to order +parachain headers. Any finalized descendant of finalized relay block `RB`, which has parachain block `PB` in +its `Heads` map, is guaranteed to have either `PB`, or its descendant. So parachain block number grows with relay +block number. + +The pallet may reject parachain head if it already knows better (or the same) head. In addition, pallet rejects +heads of untracked parachains. + +The pallet doesn't track anything behind parachain heads. So it requires no initialization - it is ready to accept +headers right after deployment. + +## Non-Essential Functionality + +There may be a special account in every runtime where the bridge parachains module is deployed. This +account, named 'module owner', is like a module-level sudo account - he's able to halt and +resume all module operations without requiring runtime upgrade. Calls that are related to this +account are: + +- `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; + +- `fn set_operating_mode()`: the module owner (or sudo account) may call this function to stop all + module operations. After this call, all finality proofs will be rejected until further `set_operating_mode` call'. + This call may be used when something extraordinary happens with the bridge. + +If pallet owner is not defined, the governance may be used to make those calls. + +## Signed Extension to Reject Obsolete Headers + +It'd be better for anyone (for chain and for submitters) to reject all transactions that are submitting +already known parachain heads to the pallet. This way, we leave block space to other useful transactions and +we don't charge concurrent submitters for their honest actions. + +To deal with that, we have a [signed extension](./src/extension.rs) that may be added to the runtime. +It does exactly what is required - rejects all transactions with already known heads. The submitter +pays nothing for such transactions - they're simply removed from the transaction pool, when the block +is built. + +The signed extension, however, is a bit limited - it only works with transactions that provide single +parachain head. So it won't work with multiple parachain heads transactions. This fits our needs +for [Kusama <> Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md). If you need to deal +with other transaction formats, you may implement similar extension for your runtime. + +You may also take a look at the [`generate_bridge_reject_obsolete_headers_and_messages`](../../bin/runtime-common/src/lib.rs) +macro that bundles several similar signed extensions in a single one. + +## Parachains Finality Relay + +We have an offchain actor, who is watching for new parachain heads and submits them to the bridged chain. +It is the parachains relay - you may look at the [crate level documentation and the code](../../relays/parachains/). From 79db6856db38ea9ccfca1369999614f0a86a2b14 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 17 Jan 2023 14:40:18 +0300 Subject: [PATCH 0874/1210] update Substrate/Polkadot/Cumulus deps to master (#1775) --- modules/beefy/src/mock.rs | 1 - modules/beefy/src/utils.rs | 8 ++++---- primitives/beefy/src/lib.rs | 19 ++++++++----------- primitives/chain-millau/src/lib.rs | 1 - 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 1a028f159343b..212c6c5d434bf 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -138,7 +138,6 @@ impl ChainWithBeefy for TestBridgedChain { type MmrHash = ::Output; type BeefyMmrLeafExtra = (); type AuthorityId = BeefyId; - type Signature = sp_beefy::crypto::AuthoritySignature; type AuthorityIdToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; } diff --git a/modules/beefy/src/utils.rs b/modules/beefy/src/utils.rs index 11d601ae8860f..028e61e96b453 100644 --- a/modules/beefy/src/utils.rs +++ b/modules/beefy/src/utils.rs @@ -1,9 +1,9 @@ use crate::{ BridgedBeefyAuthorityId, BridgedBeefyAuthoritySet, BridgedBeefyAuthoritySetInfo, - BridgedBeefyCommitmentHasher, BridgedBeefyMmrLeaf, BridgedBeefySignedCommitment, BridgedChain, - BridgedMmrHash, BridgedMmrHashing, BridgedMmrProof, Config, Error, LOG_TARGET, + BridgedBeefyMmrLeaf, BridgedBeefySignedCommitment, BridgedChain, BridgedMmrHash, + BridgedMmrHashing, BridgedMmrProof, Config, Error, LOG_TARGET, }; -use bp_beefy::{merkle_root, verify_mmr_leaves_proof, BeefyVerify, MmrDataOrHash}; +use bp_beefy::{merkle_root, verify_mmr_leaves_proof, BeefyAuthorityId, MmrDataOrHash}; use codec::Encode; use frame_support::ensure; use sp_runtime::traits::{Convert, Hash}; @@ -72,7 +72,7 @@ fn verify_signatures, I: 'static>( authority_set.validators().iter().zip(commitment.signatures.iter()).enumerate() { if let Some(sig) = maybe_sig { - if BeefyVerify::>::verify(sig, &msg, authority) { + if authority.verify(sig, &msg) { missing_signatures = missing_signatures.saturating_sub(1); if missing_signatures == 0 { break diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index f16c10820070d..8b2b05d551fe8 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -29,8 +29,8 @@ pub use sp_beefy::{ crypto::{AuthorityId as EcdsaValidatorId, AuthoritySignature as EcdsaValidatorSignature}, known_payloads::MMR_ROOT_ID as MMR_ROOT_PAYLOAD_ID, mmr::{BeefyAuthoritySet, MmrLeafVersion}, - BeefyAuthorityId, BeefyVerify, Commitment, Payload as BeefyPayload, SignedCommitment, - ValidatorSet, ValidatorSetId, BEEFY_ENGINE_ID, + BeefyAuthorityId, Commitment, Payload as BeefyPayload, SignedCommitment, ValidatorSet, + ValidatorSetId, BEEFY_ENGINE_ID, }; use bp_runtime::{BasicOperatingMode, BlockNumberOf, Chain, HashOf}; @@ -39,7 +39,7 @@ use frame_support::Parameter; use scale_info::TypeInfo; use sp_runtime::{ traits::{Convert, MaybeSerializeDeserialize}, - RuntimeDebug, + RuntimeAppPublic, RuntimeDebug, }; use sp_std::prelude::*; @@ -72,7 +72,8 @@ pub trait ChainWithBeefy: Chain { + Copy + AsRef<[u8]> + Default - + MaybeSerializeDeserialize; + + MaybeSerializeDeserialize + + PartialOrd; /// The type expected for the MMR leaf extra data. type BeefyMmrLeafExtra: Parameter; @@ -80,12 +81,7 @@ pub trait ChainWithBeefy: Chain { /// A way to identify a BEEFY validator. /// /// Corresponds to the `BeefyId` field of the `pallet-beefy` configuration. - type AuthorityId: BeefyAuthorityId + Parameter; - - /// The signature type used by BEEFY. - /// - /// Corresponds to the `BeefyId` field of the `pallet-beefy` configuration. - type Signature: BeefyVerify + Parameter; + type AuthorityId: BeefyAuthorityId + Parameter; /// A way to convert validator id to its raw representation in the BEEFY merkle tree. /// @@ -101,7 +97,8 @@ pub type BeefyAuthoritySetOf = ValidatorSet>; /// BEEFY authority set, containing both validator identifiers and the numeric set id. pub type BeefyAuthoritySetInfoOf = sp_beefy::mmr::BeefyAuthoritySet>; /// BEEFY validator signature used by given Substrate chain. -pub type BeefyValidatorSignatureOf = ::Signature; +pub type BeefyValidatorSignatureOf = + <::AuthorityId as RuntimeAppPublic>::Signature; /// Signed BEEFY commitment used by given Substrate chain. pub type BeefySignedCommitmentOf = SignedCommitment, BeefyValidatorSignatureOf>; diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 5c3b7f18ab43f..afe8fbca69cac 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -162,7 +162,6 @@ impl ChainWithBeefy for Millau { type MmrHash = ::Output; type BeefyMmrLeafExtra = (); type AuthorityId = bp_beefy::EcdsaValidatorId; - type Signature = bp_beefy::EcdsaValidatorSignature; type AuthorityIdToMerkleLeaf = bp_beefy::BeefyEcdsaToEthereum; } From 0ce842be06f5b42925ece504f49156d801ad718c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 17 Jan 2023 14:58:30 +0200 Subject: [PATCH 0875/1210] Define separate signed extension for BHR/BHW (#1776) - Make signed extensions for indirect runtimes more extensible - Define separate signed extension for BHR/BHW --- .../chain-bridge-hub-cumulus/src/lib.rs | 6 +- primitives/polkadot-core/src/lib.rs | 218 ++++++++++-------- primitives/runtime/Cargo.toml | 1 + primitives/runtime/src/extensions.rs | 136 +++++++++++ primitives/runtime/src/lib.rs | 1 + relays/client-bridge-hub-rococo/src/lib.rs | 3 +- .../src/runtime_wrapper.rs | 4 +- relays/client-bridge-hub-wococo/src/lib.rs | 3 +- .../src/runtime_wrapper.rs | 4 +- relays/client-rialto-parachain/src/lib.rs | 6 +- 10 files changed, 278 insertions(+), 104 deletions(-) create mode 100644 primitives/runtime/src/extensions.rs diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 72faabe43cd98..e33131ff8a2e9 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -18,9 +18,9 @@ use bp_messages::*; pub use bp_polkadot_core::{ - AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, - Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, SignedExtensions, - UncheckedExtrinsic, TX_EXTRA_BYTES, + AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, + BridgeSignedExtension, Hash, Hasher, Hashing, Header, Index, Nonce, Perbill, + PolkadotSignedExtension, Signature, SignedBlock, UncheckedExtrinsic, TX_EXTRA_BYTES, }; use frame_support::{ dispatch::DispatchClass, diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 7558ce762d026..3d4b72fccb928 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -18,7 +18,6 @@ use bp_messages::MessageNonce; use bp_runtime::{Chain, EncodedOrDecodedCall, StorageMapKeyProvider}; -use codec::Compact; use frame_support::{ dispatch::DispatchClass, parameter_types, @@ -29,17 +28,16 @@ use frame_support::{ Blake2_128Concat, RuntimeDebug, }; use frame_system::limits; -use scale_info::TypeInfo; use sp_core::{storage::StorageKey, Hasher as HasherT}; use sp_runtime::{ generic, - traits::{BlakeTwo256, DispatchInfoOf, IdentifyAccount, Verify}, - transaction_validity::TransactionValidityError, + traits::{BlakeTwo256, IdentifyAccount, Verify}, MultiAddress, MultiSignature, OpaqueExtrinsic, }; use sp_std::prelude::Vec; // Re-export's to avoid extra substrate dependencies in chain-specific crates. +use bp_runtime::extensions::*; pub use frame_support::{weights::constants::ExtrinsicBaseWeight, Parameter}; pub use sp_runtime::{traits::Convert, Perbill}; @@ -184,39 +182,72 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< - AccountAddress, - EncodedOrDecodedCall, - Signature, - SignedExtensions, ->; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic, Signature, SignedExt>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; -/// A type of the data encoded as part of the transaction. -pub type SignedExtra = - ((), (), (), (), sp_runtime::generic::Era, Compact, (), Compact); - -/// Parameters which are part of the payload used to produce transaction signature, -/// but don't end up in the transaction itself (i.e. inherent part of the runtime). -pub type AdditionalSigned = ((), u32, u32, Hash, Hash, (), (), ()); - -/// A simplified version of signed extensions meant for producing signed transactions -/// and signed payload in the client code. -#[derive(codec::Encode, codec::Decode, PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] -pub struct SignedExtensions { - encode_payload: SignedExtra, - // It may be set to `None` if extensions are decoded. We are never reconstructing transactions - // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to - // read fields of `encode_payload`. And when resigning transaction, we're reconstructing - // `SignedExtensions` from the scratch. - #[codec(skip)] - additional_signed: Option, +/// Polkadot-like chain. +#[derive(RuntimeDebug)] +pub struct PolkadotLike; + +impl Chain for PolkadotLike { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +/// Some functionality associated with the default signed extension used by Polkadot and +/// Polkadot-like chains. +pub trait PolkadotSignedExtension { + fn from_params( + spec_version: u32, + transaction_version: u32, + era: bp_runtime::TransactionEraOf, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + ) -> Self; + + fn nonce(&self) -> Nonce; + + fn tip(&self) -> Balance; } -impl SignedExtensions { - pub fn new( +type DefaultSignedExtra = ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ChargeTransactionPayment, +); + +/// The default signed extension used by Polkadot and Polkadot-like chains. +pub type DefaultSignedExtension = GenericSignedExtension; + +impl PolkadotSignedExtension for DefaultSignedExtension { + fn from_params( spec_version: u32, transaction_version: u32, era: bp_runtime::TransactionEraOf, @@ -224,8 +255,8 @@ impl SignedExtensions { nonce: Nonce, tip: Balance, ) -> Self { - Self { - encode_payload: ( + Self::new( + ( (), // non-zero sender (), // spec version (), // tx version @@ -235,7 +266,7 @@ impl SignedExtensions { (), // Check weight tip.into(), // transaction payment / tip (compact encoding) ), - additional_signed: Some(( + ( (), spec_version, transaction_version, @@ -244,78 +275,79 @@ impl SignedExtensions { (), (), (), - )), - } + ), + ) } -} -impl SignedExtensions { /// Return signer nonce, used to craft transaction. - pub fn nonce(&self) -> Nonce { - self.encode_payload.5.into() + fn nonce(&self) -> Nonce { + self.payload.5.into() } /// Return transaction tip. - pub fn tip(&self) -> Balance { - self.encode_payload.7.into() + fn tip(&self) -> Balance { + self.payload.7.into() } } -impl sp_runtime::traits::SignedExtension for SignedExtensions { - const IDENTIFIER: &'static str = "Not needed."; - - type AccountId = AccountId; - type Call = (); - type AdditionalSigned = AdditionalSigned; - type Pre = (); - - fn additional_signed( - &self, - ) -> Result { - // we shall not ever see this error in relay, because we are never signing decoded - // transactions. Instead we're constructing and signing new transactions. So the error code - // is kinda random here - self.additional_signed - .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( - frame_support::unsigned::UnknownTransaction::Custom(0xFF), - )) - } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) +type BridgeSignedExtra = ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, +); + +/// The default signed extension used by Polkadot and Polkadot-like chains with bridging. +pub type BridgeSignedExtension = GenericSignedExtension; + +impl PolkadotSignedExtension for BridgeSignedExtension { + fn from_params( + spec_version: u32, + transaction_version: u32, + era: bp_runtime::TransactionEraOf, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + ) -> Self { + Self::new( + ( + (), // non-zero sender + (), // spec version + (), // tx version + (), // genesis + era.frame_era(), // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + tip.into(), // transaction payment / tip (compact encoding) + (), // bridge reject obsolete headers and msgs + ), + ( + (), + spec_version, + transaction_version, + genesis_hash, + era.signed_payload(genesis_hash), + (), + (), + (), + (), + ), + ) } -} - -/// Polkadot-like chain. -#[derive(RuntimeDebug)] -pub struct PolkadotLike; - -impl Chain for PolkadotLike { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - type AccountId = AccountId; - type Balance = Balance; - type Index = Index; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) + /// Return signer nonce, used to craft transaction. + fn nonce(&self) -> Nonce { + self.payload.5.into() } - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) + /// Return transaction tip. + fn tip(&self) -> Balance { + self.payload.7.into() } } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 79f2b9fe03c5c..f8d698696deea 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } hash-db = { version = "0.15.2", default-features = false } +impl-trait-for-tuples = "0.2.2" num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs new file mode 100644 index 0000000000000..287f484db4a2a --- /dev/null +++ b/primitives/runtime/src/extensions.rs @@ -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 . + +//! Primitives that may be used for creating signed extensions for indirect runtimes. + +use crate::{BalanceOf, HashOf}; +use codec::{Compact, Decode, Encode}; +use impl_trait_for_tuples::impl_for_tuples; +use scale_info::{StaticTypeInfo, TypeInfo}; +use sp_runtime::{ + traits::{DispatchInfoOf, SignedExtension}, + transaction_validity::TransactionValidityError, +}; +use sp_std::{fmt::Debug, marker::PhantomData}; + +/// Trait that describes some properties of a `SignedExtension` that are needed in order to send a +/// transaction to the chain. +pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo { + /// A type of the data encoded as part of the transaction. + type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; + /// Parameters which are part of the payload used to produce transaction signature, + /// but don't end up in the transaction itself (i.e. inherent part of the runtime). + type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo; +} + +// An implementation of `SignedExtensionSchema` using generic params. +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] +pub struct GenericSignedExtensionSchema(PhantomData<(P, S)>); + +impl SignedExtensionSchema for GenericSignedExtensionSchema +where + P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, + S: Encode + Debug + Eq + Clone + StaticTypeInfo, +{ + type Payload = P; + type AdditionalSigned = S; +} + +/// The `SignedExtensionSchema` for `frame_system::CheckNonZeroSender`. +pub type CheckNonZeroSender = GenericSignedExtensionSchema<(), ()>; + +/// The `SignedExtensionSchema` for `frame_system::CheckSpecVersion`. +pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>; + +/// The `SignedExtensionSchema` for `frame_system::CheckTxVersion`. +pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>; + +/// The `SignedExtensionSchema` for `frame_system::CheckGenesis`. +pub type CheckGenesis = GenericSignedExtensionSchema<(), HashOf>; + +/// The `SignedExtensionSchema` for `frame_system::CheckEra`. +pub type CheckEra = GenericSignedExtensionSchema>; + +/// The `SignedExtensionSchema` for `frame_system::CheckNonce`. +pub type CheckNonce = GenericSignedExtensionSchema, ()>; + +/// The `SignedExtensionSchema` for `frame_system::CheckWeight`. +pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; + +/// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. +pub type ChargeTransactionPayment = GenericSignedExtensionSchema>, ()>; + +/// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. +pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; + +#[impl_for_tuples(1, 12)] +impl SignedExtensionSchema for Tuple { + for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); + for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); +} + +/// A simplified version of signed extensions meant for producing signed transactions +/// and signed payloads in the client code. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub struct GenericSignedExtension { + pub payload: S::Payload, + #[codec(skip)] + // It may be set to `None` if extensions are decoded. We are never reconstructing transactions + // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to + // read fields of the `payload`. And when resigning transaction, we're reconstructing + // `SignedExtensions` from the scratch. + additional_signed: Option, +} + +impl GenericSignedExtension { + pub fn new(payload: S::Payload, additional_signed: S::AdditionalSigned) -> Self { + Self { payload, additional_signed: Some(additional_signed) } + } +} + +impl SignedExtension for GenericSignedExtension +where + S: SignedExtensionSchema, + S::Payload: Send + Sync, + S::AdditionalSigned: Send + Sync, +{ + const IDENTIFIER: &'static str = "Not needed."; + type AccountId = (); + type Call = (); + type AdditionalSigned = S::AdditionalSigned; + type Pre = (); + + fn additional_signed(&self) -> Result { + // we shall not ever see this error in relay, because we are never signing decoded + // transactions. Instead we're constructing and signing new transactions. So the error code + // is kinda random here + self.additional_signed.clone().ok_or( + frame_support::unsigned::TransactionValidityError::Unknown( + frame_support::unsigned::UnknownTransaction::Custom(0xFF), + ), + ) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } +} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 340088a85b122..5eb1de2e3ac6d 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -47,6 +47,7 @@ pub use storage_types::BoundedStorageValue; #[cfg(feature = "std")] pub use storage_proof::craft_valid_storage_proof; +pub mod extensions; pub mod messages; mod chain; diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 653c5af2c5e3f..8e6e971292599 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. +use bp_bridge_hub_wococo::PolkadotSignedExtension; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -65,7 +66,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_rococo::SignedExtensions::new( + bp_bridge_hub_rococo::BridgeSignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index 2c50128201bc1..1bb32a4089c83 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -21,14 +21,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; +use bp_bridge_hub_rococo::BridgeSignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::SystemCall; -// TODO:check-parameter - check SignedExtension /// Unchecked BridgeHubRococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; // The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 516f5d9fb808b..3fd8187fa1fea 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. +use bp_bridge_hub_wococo::PolkadotSignedExtension; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -65,7 +66,7 @@ impl ChainWithTransactions for BridgeHubWococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_wococo::SignedExtensions::new( + bp_bridge_hub_wococo::BridgeSignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 0d73a91029df5..2158ad0e65901 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -19,14 +19,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; +use bp_bridge_hub_wococo::BridgeSignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::SystemCall; -// TODO:check-parameter - check SignedExtension /// Unchecked BridgeHubWococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; // The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index c3fb0da741877..ebaac73e03600 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -19,6 +19,7 @@ pub mod runtime_wrapper; use bp_messages::MessageNonce; +use bp_polkadot_core::{DefaultSignedExtension, PolkadotSignedExtension}; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, @@ -75,7 +76,8 @@ impl ChainWithMessages for RialtoParachain { impl ChainWithTransactions for RialtoParachain { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_polkadot_core::UncheckedExtrinsic; + type SignedTransaction = + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -83,7 +85,7 @@ impl ChainWithTransactions for RialtoParachain { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot_core::SignedExtensions::new( + bp_polkadot_core::DefaultSignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, From 1631d88736ac1804a01c08ac576cd9d5720d5a59 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Jan 2023 09:56:30 +0300 Subject: [PATCH 0876/1210] Crate-level documentation on finality relays and relayers pallet (#1773) * started crate-level documentation on relays and relayers pallet * fixes in finality and parachain finality relay docs * fix links * grammar fixes --- docs/high-level-overview.md | 8 ++-- modules/relayers/README.md | 14 ++++++ modules/shift-session-manager/README.md | 10 +++++ relays/finality/README.md | 58 +++++++++++++++++++++++++ relays/parachains/README.md | 49 +++++++++++++++++++++ 5 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 modules/relayers/README.md create mode 100644 modules/shift-session-manager/README.md create mode 100644 relays/finality/README.md create mode 100644 relays/parachains/README.md diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 5a76347ce4f6c..f280671925612 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -41,7 +41,7 @@ proofs are called mandatory in the pallet and relayer pays no fee for such heade The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers he wants to submit (with the exception of mandatory headers). -More: [code](../modules/grandpa/). +More: [pallet level documentation and code](../modules/grandpa/). ### Bridge Parachains Finality Pallet @@ -60,7 +60,7 @@ The pallet may track multiple parachains at once and those parachains may use di parachain header decoding never happens at the pallet level. For maintaining the headers order, the pallet uses relay chain header number. -More: [code](../modules/parachains/). +More: [pallet level documentation and code](../modules/parachains/). ### Bridge Messages Pallet @@ -91,14 +91,14 @@ pallet, in this case, depends on one of the finality pallets. The messages are X XCM executor to dispatch them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) document. -More: [code](../modules/messages/). +More: [pallet level documentation and code](../modules/messages/). ### Bridge Relayers Pallet The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When the rewards are registered and the reward amount is configured outside of the pallet. -More: [code](../modules/relayers/). +More: [pallet level documentation and code](../modules/relayers/). ## Offchain Components diff --git a/modules/relayers/README.md b/modules/relayers/README.md new file mode 100644 index 0000000000000..656200f448651 --- /dev/null +++ b/modules/relayers/README.md @@ -0,0 +1,14 @@ +# Bridge Relayers Pallet + +The pallet serves as a storage for pending bridge relayer rewards. Any runtime component may register reward +to some relayer for doing some useful job at some messages lane. Later, the relayer may claim its rewards +using the `claim_rewards` call. + +The reward payment procedure is abstracted from the pallet code. One of possible implementations, is the +[`PayLaneRewardFromAccount`](../../primitives/relayers/src/lib.rs), which just does a `Currency::transfer` +call to relayer account from the relayer-rewards account, determined by the message lane id. + +We have two examples of how this pallet is used in production. Rewards are registered at the target chain to +compensate fees of message delivery transactions (and linked finality delivery calls). At the source chain, rewards +are registered during delivery confirmation transactions. You may find more information about that in the +[Kusama <> Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) documentation. diff --git a/modules/shift-session-manager/README.md b/modules/shift-session-manager/README.md new file mode 100644 index 0000000000000..8dfbfd416e3cc --- /dev/null +++ b/modules/shift-session-manager/README.md @@ -0,0 +1,10 @@ +# Shift Session Manager Pallet + +**THIS PALLET IS NOT INTENDED TO BE USED IN PRODUCTION** + +The pallet does not provide any calls or runtime storage entries. It only provides implementation of the +`pallet_session::SessionManager`. This implementation, starting from session `3` selects two thirds of initial +validators and changes the set on every session. We are using it at our testnets ([Rialto](../../bin/rialto/) and +[Millau](../../bin/millau/)) to be sure that the set changes every session. On well-known production chains +(like Kusama and Polkadot) the alternative is the set of [nPoS](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html) +pallets, which selects validators, based on their nominations. diff --git a/relays/finality/README.md b/relays/finality/README.md new file mode 100644 index 0000000000000..edfd00192bc87 --- /dev/null +++ b/relays/finality/README.md @@ -0,0 +1,58 @@ +# GRANDPA Finality Relay + +The finality relay is able to work with different finality engines. In the modern Substrate world they are GRANDPA +and BEEFY. Let's talk about GRANDPA here, because BEEFY relay and bridge BEEFY pallet are in development. + +In general, the relay works as follows: it connects to the source and target chain. The source chain must have the +[GRANDPA gadget](https://github.com/paritytech/finality-grandpa) running (so it can't be a parachain). The target +chain must have the [bridge GRANDPA pallet](../../modules/grandpa/) deployed at its runtime. The relay subscribes +to the GRANDPA finality notifications at the source chain and when the new justification is received, it is submitted +to the pallet at the target chain. + +Apart from that, the relay is watching for every source header that is missing at target. If it finds the missing +mandatory header (header that is changing the current GRANDPA validators set), it submits the justification for +this header. The case when the source node can't return the mandatory justification is considered a fatal error, +because the pallet can't proceed without it. + +More: [GRANDPA Finality Relay Sequence Diagram](../../docs/grandpa-finality-relay.html). + +## How to Use the Finality Relay + +The most important trait is the [`FinalitySyncPipeline`](./src/lib.rs), which defines the basic primitives of the +source chain (like block hash and number) and the type of finality proof (GRANDPA jusitfication or MMR proof). Once +that is defined, there are two other traits - [`SourceClient`](./src/finality_loop.rs) and +[`TarggetClient`](./src/finality_loop.rs). + +The `SourceClient` represents the Substrate node client that connects to the source chain. The client need to +be able to return the best finalized header number, finalized header and its finality proof and the stream of +finality proofs. + +The `TargetClient` implementation must be able to craft finality delivery transaction and submit it to the target +node. The transaction is then tracked by the relay until it is mined and finalized. + +The main entrypoint for the crate is the [`run` function](./src/finality_loop.rs), which takes source and target +clients and [`FinalitySyncParams`](./src/finality_loop.rs) parameters. The most imporant parameter is the +`only_mandatory_headers` - it it is set to `true`, the relay will only submit mandatory headers. Since transactions +with mandatory headers are fee-free, the cost of running such relay is zero (in terms of fees). + +## Finality Relay Metrics + +Finality relay provides several metrics. Metrics names depend on names of source and target chains. The list below +shows metrics names for Rialto (source chain) to Millau (target chain) finality relay. For other chains, simply +change chain names. So the metrics are: + +- `Rialto_to_Millau_Sync_best_source_block_number` - returns best finalized source chain (Rialto) block number, known + to the relay. If relay is running in [on-demand mode](../bin-substrate/src/cli/relay_headers_and_messages/), the + number may not match (it may be far behind) the actual best finalized number; + +- `Rialto_to_Millau_Sync_best_source_at_target_block_number` - returns best finalized source chain (Rialto) block + number that is known to the bridge GRANDPA pallet at the target chain. + +- `Rialto_to_Millau_Sync_is_source_and_source_at_target_using_different_forks` - if this metrics is set to `1`, then + the best source chain header, known to the target chain doesn't match the same-number-header at the source chain. + It means that the GRANDPA validators set has crafted the duplicate justification and it has been submitted to the + target chain. Normally (if majority of validators are honest and if you're running finality relay without large + breaks) this shall not happen and the metric will have `0` value. + +If relay operates properly, you should see that the `Rialto_to_Millau_Sync_best_source_at_target_block_number` +tries to reach the `Rialto_to_Millau_Sync_best_source_block_number`. And the latter one always increases. \ No newline at end of file diff --git a/relays/parachains/README.md b/relays/parachains/README.md new file mode 100644 index 0000000000000..6cb68f2209f6a --- /dev/null +++ b/relays/parachains/README.md @@ -0,0 +1,49 @@ +# Parachains Finality Relay + +The parachains finality relay works with two chains - source relay chain and target chain (which may be standalone +chain, relay chain or a parachain). The source chain must have the +[`paras` pallet](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) deployed at its +runtime. The target chain must have the [bridge parachains pallet](../../modules/parachains/) deployed at its runtime. + +The relay is configured to submit heads of one or several parachains. It pokes source chain periodically and compares +parachain heads that are known to the source relay chain to heads at the target chain. If there are new heads, +the relay submits them to the target chain. + +More: [Parachains Finality Relay Sequence Diagram](../../docs/parachains-finality-relay.html). + +## How to Use the Parachains Finality Relay + +There are only two traits that need to be implemented. The [`SourceChain`](./src/parachains_loop.rs) implementation +is supposed to connect to the source chain node. It must be able to read parachain heads from the `Heads` map of +the [`paras` pallet](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet. +It also must create storage proofs of `Heads` map entries, when required. + +The [`TargetChain`](./src/parachains_loop.rs) implementation connects to the target chain node. It must be able +to return the best known head of given parachain. When required, it must be able to craft and submit parachains +finality delivery transaction to the target node. + +The main entrypoint for the crate is the [`run` function](./src/parachains_loop.rs), which takes source and target +clients and [`ParachainSyncParams`](./src/parachains_loop.rs) parameters. The most imporant parameter is the +`parachains` - it it the set of parachains, which relay tracks and updates. The other important parameter that +may affect the relay operational costs is the `strategy`. If it is set to `Any`, then the finality delivery +transaction is submitted if at least one of tracked parachain heads is updated. The other option is `All`. Then +the relay waits until all tracked parachain heads are updated and submits them all in a single finality delivery +transaction. + +## Parachain Finality Relay Metrics + +Every parachain in Polkadot is identified by the 32-bit number. All metrics, exposed by the parachains finality +relay have the `parachain` label, which is set to the parachain id. And the metrics are prefixed with the prefix, +that depends on the name of the source relay and target chains. The list below shows metrics names for +Rialto (source relay chain) to Millau (target chain) parachains finality relay. For other chains, simply +change chain names. So the metrics are: + +- `Rialto_to_Millau_Parachains_best_parachain_block_number_at_source` - returns best known parachain block + number, registered in the `paras` pallet at the source relay chain (Rialto in our example); + +- `Rialto_to_Millau_Parachains_best_parachain_block_number_at_target` - returns best known parachain block + number, registered in the bridge parachains pallet at the target chain (Millau in our example). + +If relay operates properly, you should see that the `Rialto_to_Millau_Parachains_best_parachain_block_number_at_target` +tries to reach the `Rialto_to_Millau_Parachains_best_parachain_block_number_at_source`. And the latter one +always increases. From 31a19230810b0f5f409f80d0881c8e94a882516e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Jan 2023 09:56:53 +0300 Subject: [PATCH 0877/1210] Relayer reward metric (#1742) * use StorageDoubleMapKeyProvider in RelayerRewards * add metrics * clippy * fixed alerts that have caused missing dashboards * fix metric name * fix metric name again * add new metrics to the RialtoParachain <> Millau maintenance dashboard * remove obsolete dashboard --- modules/relayers/Cargo.toml | 2 + modules/relayers/src/lib.rs | 17 ++++-- primitives/relayers/Cargo.toml | 2 + primitives/relayers/src/lib.rs | 22 ++++++- .../src/cli/relay_headers_and_messages/mod.rs | 26 +++++--- relays/client-bridge-hub-rococo/src/lib.rs | 1 + relays/client-bridge-hub-wococo/src/lib.rs | 1 + relays/client-millau/src/lib.rs | 2 + relays/client-rialto-parachain/src/lib.rs | 2 + relays/client-rialto/src/lib.rs | 2 + relays/client-substrate/src/chain.rs | 10 ++++ relays/lib-substrate-relay/Cargo.toml | 2 + .../src/messages_metrics.rs | 59 +++++++++++++++++-- 13 files changed, 127 insertions(+), 21 deletions(-) diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 9c07123836381..732adbf4faa6c 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -15,6 +15,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" bp-messages = { path = "../../primitives/messages", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies @@ -37,6 +38,7 @@ default = ["std"] std = [ "bp-messages/std", "bp-relayers/std", + "bp-runtime/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index b28d17cf5a4fd..7132914a4ae85 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -21,7 +21,8 @@ #![warn(missing_docs)] use bp_messages::LaneId; -use bp_relayers::PaymentProcedure; +use bp_relayers::{PaymentProcedure, RelayerRewardsKeyProvider}; +use bp_runtime::StorageDoubleMapKeyProvider; use frame_support::sp_runtime::Saturating; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; use sp_std::marker::PhantomData; @@ -46,6 +47,10 @@ pub mod pallet { use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; + /// `RelayerRewardsKeyProvider` for given configuration. + type RelayerRewardsKeyProviderOf = + RelayerRewardsKeyProvider<::AccountId, ::Reward>; + #[pallet::config] pub trait Config: frame_system::Config { /// The overarching event type. @@ -146,11 +151,11 @@ pub mod pallet { #[pallet::getter(fn relayer_reward)] pub type RelayerRewards = StorageDoubleMap< _, - Blake2_128Concat, - T::AccountId, - Identity, - LaneId, - T::Reward, + as StorageDoubleMapKeyProvider>::Hasher1, + as StorageDoubleMapKeyProvider>::Key1, + as StorageDoubleMapKeyProvider>::Hasher2, + as StorageDoubleMapKeyProvider>::Key2, + as StorageDoubleMapKeyProvider>::Value, OptionQuery, >; } diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 4f893f9f83ebc..acede813995d1 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies @@ -27,6 +28,7 @@ hex-literal = "0.3" default = ["std"] std = [ "bp-messages/std", + "bp-runtime/std", "frame-support/std", "sp-runtime/std", "sp-std/std", diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index d00b5f626e4ab..207908296cbf5 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -20,8 +20,10 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::LaneId; +use bp_runtime::StorageDoubleMapKeyProvider; +use frame_support::{Blake2_128Concat, Identity}; use sp_runtime::{ - codec::{Decode, Encode}, + codec::{Codec, Decode, Encode, EncodeLike}, traits::AccountIdConversion, }; use sp_std::{fmt::Debug, marker::PhantomData}; @@ -65,6 +67,24 @@ where } } +/// Can be use to access the runtime storage key within the `RelayerRewards` map of the relayers +/// pallet. +pub struct RelayerRewardsKeyProvider(PhantomData<(AccountId, Reward)>); + +impl StorageDoubleMapKeyProvider for RelayerRewardsKeyProvider +where + AccountId: Codec + EncodeLike, + Reward: Codec + EncodeLike, +{ + const MAP_NAME: &'static str = "RelayerRewards"; + + type Hasher1 = Blake2_128Concat; + type Key1 = AccountId; + type Hasher2 = Identity; + type Key2 = LaneId; + type Value = Reward; +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index ea6d6ad9f51a2..193632c28b427 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -61,8 +61,8 @@ use crate::{ use bp_messages::LaneId; use bp_runtime::BalanceOf; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithTransactions, Client, - Parachain, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithMessages, + ChainWithTransactions, Client, Parachain, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; @@ -259,9 +259,9 @@ where type Base: Full2WayBridgeBase; /// The left relay chain. - type Left: ChainWithTransactions + ChainWithBalances + CliChain; + type Left: ChainWithTransactions + ChainWithBalances + ChainWithMessages + CliChain; /// The right relay chain. - type Right: ChainWithTransactions + ChainWithBalances + CliChain; + type Right: ChainWithTransactions + ChainWithBalances + ChainWithMessages + CliChain; /// Left to Right bridge. type L2R: MessagesCliBridge; @@ -317,28 +317,36 @@ where self.mut_base().start_on_demand_headers_relayers().await?; // add balance-related metrics + let lanes = self + .base() + .common() + .shared + .lane + .iter() + .cloned() + .map(Into::into) + .collect::>(); { let common = self.mut_base().mut_common(); - substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Right>( common.left.client.clone(), &mut common.metrics_params, &common.left.accounts, + &lanes, ) .await?; - substrate_relay_helper::messages_metrics::add_relay_balances_metrics( + substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Left>( common.right.client.clone(), &mut common.metrics_params, &common.right.accounts, + &lanes, ) .await?; } - let lanes = self.base().common().shared.lane.clone(); // Need 2x capacity since we consider both directions for each lane let mut message_relays = Vec::with_capacity(lanes.len() * 2); for lane in lanes { - let lane = lane.into(); - let left_to_right_messages = substrate_relay_helper::messages_lane::run::< ::MessagesLane, >(self.left_to_right().messages_relay_params( diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 8e6e971292599..806a492b7f8ee 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -110,6 +110,7 @@ impl ChainWithTransactions for BridgeHubRococo { impl ChainWithMessages for BridgeHubRococo { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 3fd8187fa1fea..40f50ce1e3862 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -110,6 +110,7 @@ impl ChainWithTransactions for BridgeHubWococo { impl ChainWithMessages for BridgeHubWococo { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_bridge_hub_wococo::WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_wococo::TO_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index fb901a4b2de39..34bbea92d57e9 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -45,6 +45,8 @@ impl ChainWithGrandpa for Millau { impl ChainWithMessages for Millau { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; + // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): change the name + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some("BridgeRelayers"); const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index ebaac73e03600..739b33838b5be 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -63,6 +63,8 @@ impl ChainWithBalances for RialtoParachain { impl ChainWithMessages for RialtoParachain { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; + // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): change the name + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some("BridgeRelayers"); const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto_parachain::TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 4c3a9d1e18eaa..8ad31de4d583a 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -63,6 +63,8 @@ impl ChainWithGrandpa for Rialto { impl ChainWithMessages for Rialto { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; + // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): change the name + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some("BridgeRelayers"); const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index db08fc1f98ce1..4ec5edfc41bcf 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -101,6 +101,16 @@ pub trait ChainWithMessages: Chain { /// the same name. const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str; + // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): check all the names + // after the issue is fixed - all names must be changed + + /// Name of the bridge relayers pallet (used in `construct_runtime` macro call) that is deployed + /// at some other chain to bridge with this `ChainWithMessages`. + /// + /// We assume that all chains that are bridging with this `ChainWithMessages` are using + /// the same name. + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str>; + /// Name of the `ToOutboundLaneApi::message_details` runtime API method. /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index bdf49d42eab44..e044be0957c74 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -12,6 +12,7 @@ async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.12" +hex = "0.4" num-traits = "0.2" log = "0.4.17" @@ -20,6 +21,7 @@ log = "0.4.17" bp-header-chain = { path = "../../primitives/header-chain" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-relayers = { path = "../../primitives/relayers" } bridge-runtime-common = { path = "../../bin/runtime-common" } finality-grandpa = { version = "0.16.0" } diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 37a6d67baae43..943f3b7c3694f 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -18,12 +18,15 @@ use crate::TaggedAccount; +use bp_messages::LaneId; +use bp_runtime::StorageDoubleMapKeyProvider; use codec::Decode; use frame_system::AccountInfo; use pallet_balances::AccountData; use relay_substrate_client::{ metrics::{FloatStorageValue, FloatStorageValueMetric}, - AccountIdOf, BalanceOf, Chain, ChainWithBalances, Client, Error as SubstrateError, IndexOf, + AccountIdOf, BalanceOf, Chain, ChainWithBalances, ChainWithMessages, Client, + Error as SubstrateError, IndexOf, }; use relay_utils::metrics::{MetricsParams, StandaloneMetric}; use sp_core::storage::StorageData; @@ -31,10 +34,11 @@ use sp_runtime::{FixedPointNumber, FixedU128}; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; /// Add relay accounts balance metrics. -pub async fn add_relay_balances_metrics( +pub async fn add_relay_balances_metrics( client: Client, metrics: &mut MetricsParams, relay_accounts: &Vec>>, + lanes: &[LaneId], ) -> anyhow::Result<()> where BalanceOf: Into + std::fmt::Debug, @@ -68,13 +72,30 @@ where for account in relay_accounts { let relay_account_balance_metric = FloatStorageValueMetric::new( - FreeAccountBalance:: { token_decimals, _phantom: Default::default() }, + AccountBalanceFromAccountInfo:: { token_decimals, _phantom: Default::default() }, client.clone(), C::account_info_storage_key(account.id()), format!("at_{}_relay_{}_balance", C::NAME, account.tag()), format!("Balance of the {} relay account at the {}", account.tag(), C::NAME), )?; relay_account_balance_metric.register_and_spawn(&metrics.registry)?; + + if let Some(relayers_pallet_name) = BC::WITH_CHAIN_RELAYERS_PALLET_NAME { + for lane in lanes { + let relay_account_reward_metric = FloatStorageValueMetric::new( + AccountBalance:: { token_decimals, _phantom: Default::default() }, + client.clone(), + bp_relayers::RelayerRewardsKeyProvider::, BalanceOf>::final_key( + relayers_pallet_name, + account.id(), + lane, + ), + format!("at_{}_relay_{}_reward_for_lane_{}_with_{}", C::NAME, account.tag(), hex::encode(lane.as_ref()), BC::NAME), + format!("Reward of the {} relay account for serving lane {:?} with {} at the {}", account.tag(), lane, BC::NAME, C::NAME), + )?; + relay_account_reward_metric.register_and_spawn(&metrics.registry)?; + } + } } Ok(()) @@ -82,12 +103,12 @@ where /// Adapter for `FloatStorageValueMetric` to decode account free balance. #[derive(Clone, Debug)] -struct FreeAccountBalance { +struct AccountBalanceFromAccountInfo { token_decimals: u32, _phantom: PhantomData, } -impl FloatStorageValue for FreeAccountBalance +impl FloatStorageValue for AccountBalanceFromAccountInfo where C: Chain, BalanceOf: Into, @@ -110,6 +131,34 @@ where } } +/// Adapter for `FloatStorageValueMetric` to decode account free balance. +#[derive(Clone, Debug)] +struct AccountBalance { + token_decimals: u32, + _phantom: PhantomData, +} + +impl FloatStorageValue for AccountBalance +where + C: Chain, + BalanceOf: Into, +{ + type Value = FixedU128; + + fn decode( + &self, + maybe_raw_value: Option, + ) -> Result, SubstrateError> { + maybe_raw_value + .map(|raw_value| { + BalanceOf::::decode(&mut &raw_value.0[..]) + .map_err(SubstrateError::ResponseParseFailed) + .map(|balance| convert_to_token_balance(balance.into(), self.token_decimals)) + }) + .transpose() + } +} + /// Convert from raw `u128` balance (nominated in smallest chain token units) to the float regular /// tokens value. fn convert_to_token_balance(balance: u128, token_decimals: u32) -> FixedU128 { From 2fc36d7f37b098875bb4ea211270ab74729f57db Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Jan 2023 11:52:54 +0300 Subject: [PATCH 0878/1210] Default impl for some methods in messages benchmarking pallet config (#1777) * default impl for some methods in messages benchmarking pallet config * typo --- bin/millau/runtime/src/lib.rs | 19 ++------------ modules/messages/src/benchmarking.rs | 39 +++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dbff7f5940c64..6c401b9a94bde 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1001,21 +1001,6 @@ impl_runtime_apis! { use rialto_messages::WithRialtoMessageBridge; impl MessagesConfig for Runtime { - fn bridged_relayer_id() -> Self::InboundRelayer { - [0u8; 32].into() - } - - fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - pallet_bridge_relayers::Pallet::::relayer_reward(relayer, &Self::bench_lane_id()).is_some() - } - - fn endow_account(account: &Self::AccountId) { - pallet_balances::Pallet::::make_free_balance_be( - account, - Balance::MAX / 100, - ); - } - fn prepare_message_proof( params: MessageProofParams, ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { @@ -1032,8 +1017,8 @@ impl_runtime_apis! { ) } - fn is_message_dispatched(_nonce: bp_messages::MessageNonce) -> bool { - true + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + pallet_bridge_relayers::Pallet::::relayer_reward(relayer, &Self::bench_lane_id()).is_some() } } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 62dd1d60caf66..a89cb3a8ef038 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -27,9 +27,11 @@ use bp_messages::{ UnrewardedRelayersState, }; use bp_runtime::StorageProofSize; +use codec::Decode; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::weights::Weight; use frame_system::RawOrigin; +use sp_runtime::traits::TrailingZeroInput; use sp_std::{ops::RangeInclusive, prelude::*}; const SEED: u32 = 0; @@ -64,15 +66,26 @@ pub struct MessageDeliveryProofParams { /// Trait that must be implemented by runtime. pub trait Config: crate::Config { /// Lane id to use in benchmarks. + /// + /// By default, lane 00000000 is used. fn bench_lane_id() -> LaneId { - Default::default() + LaneId([0, 0, 0, 0]) } + /// Return id of relayer account at the bridged chain. - fn bridged_relayer_id() -> Self::InboundRelayer; - /// Returns true if given relayer has been rewarded for some of its actions. - fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool; - /// Create given account and give it enough balance for test purposes. - fn endow_account(account: &Self::AccountId); + /// + /// By default, zero account is returned. + fn bridged_relayer_id() -> Self::InboundRelayer { + Self::InboundRelayer::decode(&mut TrailingZeroInput::zeroes()).unwrap() + } + + /// Create given account and give it enough balance for test purposes. Used to create + /// relayer account at the target chain. Is strictly necessary when your rewards scheme + /// assumes that the relayer account must exist. + /// + /// Does nothing by default. + fn endow_account(_account: &Self::AccountId) {} + /// Prepare messages proof to receive by the module. fn prepare_message_proof( params: MessageProofParams, @@ -81,8 +94,20 @@ pub trait Config: crate::Config { fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> >::MessagesDeliveryProof; + /// Returns true if message has been dispatched (either successfully or not). - fn is_message_dispatched(nonce: MessageNonce) -> bool; + /// + /// We assume that messages have near-zero dispatch weight, so most of times it + /// is hard to determine whether messages has been dispatched or not. For example, + /// XCM message can be a call that leaves entry in `frame_system::Events` vector, + /// but not all XCM messages do that and we don't want to include weight of this + /// action to the base weight of message delivery. Hence, the default `true` return + /// value. + fn is_message_dispatched(_nonce: MessageNonce) -> bool { + true + } + /// Returns true if given relayer has been rewarded for some of its actions. + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool; } benchmarks_instance_pallet! { From fc491e2b910ff8edd3f16ed7b56fdabb087b3eac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 18 Jan 2023 12:33:59 +0300 Subject: [PATCH 0879/1210] add try-runtime feature to pallets (#1779) --- modules/beefy/Cargo.toml | 4 ++++ modules/grandpa/Cargo.toml | 4 ++++ modules/messages/Cargo.toml | 4 ++++ modules/parachains/Cargo.toml | 4 ++++ modules/relayers/Cargo.toml | 4 ++++ modules/shift-session-manager/Cargo.toml | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 2dca89d82e5db..1908bd50c8a27 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -48,3 +48,7 @@ std = [ "sp-runtime/std", "sp-std/std", ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 45f314a0bbd3b..9e260a335379c 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -57,3 +57,7 @@ runtime-benchmarks = [ "bp-test-utils", "frame-benchmarking/runtime-benchmarks", ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 0c2fecb0be3eb..afa8b92b22827 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -50,3 +50,7 @@ std = [ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 3c3ad95fe3427..c25956248d054 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -54,3 +54,7 @@ std = [ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 732adbf4faa6c..c7ea1e544f2d4 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -51,3 +51,7 @@ std = [ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 5dae3e00fd3b8..504adfae41697 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -33,3 +33,7 @@ std = [ "sp-staking/std", "sp-std/std", ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] From e7719e584b33ff68f75370672018d8763472dd3f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 18 Jan 2023 12:47:20 +0200 Subject: [PATCH 0880/1210] Add integrity check for signed extensions (#1780) * Add integrity check for signed extensions * Remove unneeded type specification --- bin/rialto-parachain/runtime/Cargo.toml | 3 +++ bin/rialto-parachain/runtime/src/lib.rs | 26 ++++++++++++++++++- bin/runtime-common/src/integrity.rs | 13 ++++++++++ .../chain-bridge-hub-cumulus/src/lib.rs | 8 +++--- primitives/chain-rialto-parachain/Cargo.toml | 1 + primitives/chain-rialto-parachain/src/lib.rs | 2 ++ primitives/polkadot-core/src/lib.rs | 8 +++--- primitives/runtime/src/extensions.rs | 4 +-- relays/client-bridge-hub-rococo/src/lib.rs | 2 +- .../src/runtime_wrapper.rs | 4 +-- relays/client-bridge-hub-wococo/src/lib.rs | 2 +- .../src/runtime_wrapper.rs | 4 +-- relays/client-rialto-parachain/src/lib.rs | 6 ++--- 13 files changed, 64 insertions(+), 19 deletions(-) diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 2327a864c2cbe..b91e1cd2751a3 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -75,6 +75,9 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +[dev-dependencies] +bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } + [features] default = ['std'] runtime-benchmarks = [ diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index b9f4c236d861f..5ad8506acbf3e 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -848,8 +848,11 @@ mod tests { LaneId, MessageKey, }; use bp_runtime::messages::MessageDispatchResult; - use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + use bridge_runtime_common::{ + integrity::check_additional_signed, messages::target::FromBridgedChainMessageDispatch, + }; use codec::Encode; + use sp_runtime::generic::Era; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -909,4 +912,25 @@ mod tests { ); }) } + + #[test] + fn ensure_signed_extension_definition_is_correct() { + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + ); + let indirect_payload = bp_rialto_parachain::SignedExtension::new( + ((), (), (), (), Era::Immortal, 10.into(), (), 10.into()), + None, + ); + assert_eq!(payload.encode(), indirect_payload.encode()); + + check_additional_signed::(); + } } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 9c4553ad136ae..e8e3e7f87cc60 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -26,6 +26,7 @@ use bp_runtime::{Chain, ChainId}; use codec::Encode; use frame_support::{storage::generator::StorageValue, traits::Get}; use frame_system::limits; +use sp_runtime::traits::SignedExtension; /// Macro that ensures that the runtime configuration and chain primitives crate are sharing /// the same types (index, block number, hash, hasher, account id and header). @@ -319,3 +320,15 @@ pub fn check_message_lane_weights( this_chain_max_unconfirmed_messages, ); } + +/// Check that the `AdditionalSigned` type of a wrapped runtime is the same as the one of the +/// corresponding actual runtime. +/// +/// This method doesn't perform any `assert`. If the condition is not true it will generate a +/// compile-time error. +pub fn check_additional_signed() +where + SignedExt: SignedExtension, + IndirectSignedExt: SignedExtension, +{ +} diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index e33131ff8a2e9..286fbdbebc353 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -18,9 +18,9 @@ use bp_messages::*; pub use bp_polkadot_core::{ - AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, - BridgeSignedExtension, Hash, Hasher, Hashing, Header, Index, Nonce, Perbill, - PolkadotSignedExtension, Signature, SignedBlock, UncheckedExtrinsic, TX_EXTRA_BYTES, + AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, + Hashing, Header, Index, Nonce, Perbill, PolkadotSignedExtension, Signature, SignedBlock, + UncheckedExtrinsic, TX_EXTRA_BYTES, }; use frame_support::{ dispatch::DispatchClass, @@ -86,6 +86,8 @@ pub type AccountSigner = MultiSigner; /// The address format for describing accounts. pub type Address = MultiAddress; +pub use bp_polkadot_core::BridgeSignedExtension as SignedExtension; + // Note about selecting values of two following constants: // // Normal transactions have limit of 75% of 1/2 second weight for Cumulus parachains. Let's keep diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index a15c40929579b..ed7c5c0796002 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 8a98ffe70619e..d39fe25378369 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -133,6 +133,8 @@ impl Parachain for RialtoParachain { const PARACHAIN_ID: u32 = RIALTO_PARACHAIN_ID; } +pub use bp_polkadot_core::DefaultSignedExtension as SignedExtension; + frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 3d4b72fccb928..d5a9b5de817be 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -266,7 +266,7 @@ impl PolkadotSignedExtension for DefaultSignedExtension { (), // Check weight tip.into(), // transaction payment / tip (compact encoding) ), - ( + Some(( (), spec_version, transaction_version, @@ -275,7 +275,7 @@ impl PolkadotSignedExtension for DefaultSignedExtension { (), (), (), - ), + )), ) } @@ -326,7 +326,7 @@ impl PolkadotSignedExtension for BridgeSignedExtension { tip.into(), // transaction payment / tip (compact encoding) (), // bridge reject obsolete headers and msgs ), - ( + Some(( (), spec_version, transaction_version, @@ -336,7 +336,7 @@ impl PolkadotSignedExtension for BridgeSignedExtension { (), (), (), - ), + )), ) } diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index 287f484db4a2a..eefe10f705757 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -96,8 +96,8 @@ pub struct GenericSignedExtension { } impl GenericSignedExtension { - pub fn new(payload: S::Payload, additional_signed: S::AdditionalSigned) -> Self { - Self { payload, additional_signed: Some(additional_signed) } + pub fn new(payload: S::Payload, additional_signed: Option) -> Self { + Self { payload, additional_signed } } } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 806a492b7f8ee..b14a9baa61deb 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -66,7 +66,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_rococo::BridgeSignedExtension::from_params( + bp_bridge_hub_rococo::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index 1bb32a4089c83..7f526a35aa941 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -21,14 +21,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_bridge_hub_rococo::BridgeSignedExtension; +use bp_bridge_hub_rococo::SignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::SystemCall; /// Unchecked BridgeHubRococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; // The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 40f50ce1e3862..abc820ed6247c 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -66,7 +66,7 @@ impl ChainWithTransactions for BridgeHubWococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_wococo::BridgeSignedExtension::from_params( + bp_bridge_hub_wococo::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 2158ad0e65901..85f77a6377ef7 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -19,14 +19,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_bridge_hub_wococo::BridgeSignedExtension; +use bp_bridge_hub_wococo::SignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::SystemCall; /// Unchecked BridgeHubWococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; // The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 739b33838b5be..d6efd6581b24d 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -19,7 +19,7 @@ pub mod runtime_wrapper; use bp_messages::MessageNonce; -use bp_polkadot_core::{DefaultSignedExtension, PolkadotSignedExtension}; +use bp_polkadot_core::PolkadotSignedExtension; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, @@ -79,7 +79,7 @@ impl ChainWithMessages for RialtoParachain { impl ChainWithTransactions for RialtoParachain { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -87,7 +87,7 @@ impl ChainWithTransactions for RialtoParachain { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot_core::DefaultSignedExtension::from_params( + bp_rialto_parachain::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, From ff319a81a3a13c18570ef044dbf0f65d41558893 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 19 Jan 2023 16:05:16 +0100 Subject: [PATCH 0881/1210] Removed unecesserry test + substrate/polkadot (#1787) * just update polkadot version * Removed unecesserry test + substrate/polkadot --- primitives/test-utils/Cargo.toml | 3 --- primitives/test-utils/src/lib.rs | 44 -------------------------------- 2 files changed, 47 deletions(-) diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 2bc77e632e5f1..0a591334577af 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -15,9 +15,6 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -[dev-dependencies] -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } - [features] default = ["std"] std = [ diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index e0d06ce9970a4..c1e95ec6fefdc 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -299,47 +299,3 @@ macro_rules! generate_owned_bridge_module_tests { } }; } - -#[cfg(test)] -mod tests { - use codec::Encode; - use sp_application_crypto::sp_core::{hexdisplay, hexdisplay::HexDisplay}; - use xcm::VersionedXcm; - - fn print_xcm(xcm: &VersionedXcm) { - println!("-----------------"); - println!("xcm (plain): {xcm:?}"); - println!("xcm (bytes): {:?}", xcm.encode()); - println!("xcm (hex): {:?}", hexdisplay::HexDisplay::from(&xcm.encode())); - } - - fn as_hex(xcm: &VersionedXcm) -> String { - HexDisplay::from(&xcm.encode()).to_string() - } - - pub type RuntimeCall = (); - - #[test] - fn generate_versioned_xcm_message_hex_bytes() { - let xcm: xcm::v2::Xcm = xcm::v2::Xcm(vec![xcm::v2::Instruction::Trap(43)]); - let xcm: VersionedXcm = From::from(xcm); - print_xcm(&xcm); - assert_eq!("020419ac", format!("{}", as_hex(&xcm))); - - let xcm: xcm::v3::Xcm = vec![xcm::v3::Instruction::Trap(43)].into(); - let xcm: VersionedXcm = From::from(xcm); - print_xcm(&xcm); - assert_eq!("030419ac", format!("{}", as_hex(&xcm))); - - let xcm: xcm::v3::Xcm = vec![ - xcm::v3::Instruction::ClearError, - xcm::v3::Instruction::ClearTopic, - xcm::v3::Instruction::ClearTransactStatus, - xcm::v3::Instruction::Trap(43), - ] - .into(); - let xcm: VersionedXcm = From::from(xcm); - print_xcm(&xcm); - assert_eq!("0310172c2319ac", format!("{}", as_hex(&xcm))); - } -} From 589a327f4800415c79064e5769a2592f7b345203 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 19 Jan 2023 18:49:44 +0200 Subject: [PATCH 0882/1210] Expose EXTRA_STORAGE_PROOF_SIZE in bp-bridge-hub-cumulus (#1788) We need this for the integrity tests in cumulus. --- primitives/chain-bridge-hub-cumulus/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 286fbdbebc353..6eab5a53a0441 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -20,7 +20,7 @@ use bp_messages::*; pub use bp_polkadot_core::{ AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, Hashing, Header, Index, Nonce, Perbill, PolkadotSignedExtension, Signature, SignedBlock, - UncheckedExtrinsic, TX_EXTRA_BYTES, + UncheckedExtrinsic, EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, }; use frame_support::{ dispatch::DispatchClass, From 82e1083539cfe5358148e189d054d934c4b0427b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 20 Jan 2023 11:39:36 +0300 Subject: [PATCH 0883/1210] Remove chain-specific dependencies from crates that will be used in Cumulus (#1783) * leave-modules.sh * remove bp-rialto dependency from bp-relayers * update leave-modules.sh * fix Cargo.toml of pallet-bridge-relayers * update leave-modules.sh * remove bp-rialto and millau-runtime frombridge-runtime-common Cargo.toml * update leave-modules.sh * remove chain dependencies from bridge-runtime-common crate * fix tests * cleanup script * rename script * kind of success message * remove leave-modules.sh * use TargetHeaderChainAdapter and SourceHeaderChainAdapter in our testnets * update script --- bin/millau/runtime/src/lib.rs | 8 +- bin/millau/runtime/src/rialto_messages.rs | 51 +-- .../runtime/src/rialto_parachain_messages.rs | 64 +-- bin/rialto-parachain/runtime/src/lib.rs | 4 +- .../runtime/src/millau_messages.rs | 51 +-- bin/rialto/runtime/src/lib.rs | 4 +- bin/rialto/runtime/src/millau_messages.rs | 51 +-- bin/runtime-common/Cargo.toml | 5 +- bin/runtime-common/src/integrity.rs | 8 +- bin/runtime-common/src/lib.rs | 1 + bin/runtime-common/src/messages.rs | 305 ++++--------- .../src/messages_benchmarking.rs | 1 - bin/runtime-common/src/messages_extension.rs | 54 ++- bin/runtime-common/src/mock.rs | 422 ++++++++++++++++++ .../src/refund_relayer_extension.rs | 95 ++-- modules/relayers/Cargo.toml | 1 + primitives/messages/src/target_chain.rs | 18 +- primitives/relayers/Cargo.toml | 1 - primitives/relayers/src/lib.rs | 17 +- relays/bin-substrate/src/chains/mod.rs | 6 +- 20 files changed, 660 insertions(+), 507 deletions(-) create mode 100644 bin/runtime-common/src/mock.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 6c401b9a94bde..5aba458216d29 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -473,7 +473,7 @@ impl pallet_bridge_messages::Config for Runtime { type InboundRelayer = bp_rialto::AccountId; type DeliveryPayments = (); - type TargetHeaderChain = crate::rialto_messages::Rialto; + type TargetHeaderChain = crate::rialto_messages::RialtoAsTargetHeaderChain; type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, @@ -481,7 +481,7 @@ impl pallet_bridge_messages::Config for Runtime { frame_support::traits::ConstU64<10_000>, >; - type SourceHeaderChain = crate::rialto_messages::Rialto; + type SourceHeaderChain = crate::rialto_messages::RialtoAsSourceHeaderChain; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; type BridgedChainId = RialtoChainId; } @@ -504,7 +504,7 @@ impl pallet_bridge_messages::Config for Run type InboundRelayer = bp_rialto_parachain::AccountId; type DeliveryPayments = (); - type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachain; + type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsTargetHeaderChain; type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, @@ -512,7 +512,7 @@ impl pallet_bridge_messages::Config for Run frame_support::traits::ConstU64<10_000>, >; - type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachain; + type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsSourceHeaderChain; type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; type BridgedChainId = RialtoParachainChainId; } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index ac203a2f6dde8..1bc361d58823d 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -18,13 +18,11 @@ use crate::{RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; -use bp_messages::{ - source_chain::TargetHeaderChain, - target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, -}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge}; +use bridge_runtime_common::messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto. @@ -110,6 +108,10 @@ impl messages::ThisChainWithMessages for Millau { /// Rialto chain from message lane point of view. #[derive(RuntimeDebug, Clone, Copy)] pub struct Rialto; +/// Rialto as source header chain. +pub type RialtoAsSourceHeaderChain = SourceHeaderChainAdapter; +/// Rialto as target header chain. +pub type RialtoAsTargetHeaderChain = TargetHeaderChainAdapter; impl messages::UnderlyingChainProvider for Rialto { type Chain = bp_rialto::Rialto; @@ -121,43 +123,6 @@ impl messages::BridgedChainWithMessages for Rialto { } } -impl TargetHeaderChain for Rialto { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof or one or several keys; - // - id of the lane we prove state of. - type MessagesDeliveryProof = ToRialtoMessagesDeliveryProof; - - fn verify_message(payload: &ToRialtoMessagePayload) -> Result<(), Self::Error> { - messages::source::verify_chain_message::(payload) - } - - fn verify_messages_delivery_proof( - proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::(proof) - } -} - -impl SourceHeaderChain for Rialto { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof or one or several keys; - // - id of the lane we prove messages for; - // - inclusive range of messages nonces that are proved. - type MessagesProof = FromRialtoMessagesProof; - - fn verify_messages_proof( - proof: Self::MessagesProof, - messages_count: u32, - ) -> Result, Self::Error> { - messages::target::verify_messages_proof::(proof, messages_count) - .map_err(Into::into) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 097e2798227c8..d19e413640837 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -18,13 +18,11 @@ use crate::{Runtime, RuntimeCall, RuntimeOrigin, WithRialtoParachainsInstance}; -use bp_messages::{ - source_chain::TargetHeaderChain, - target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, -}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge}; +use bridge_runtime_common::messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Rialto parachain. @@ -53,14 +51,6 @@ pub type ToRialtoParachainMessageVerifier = pub type FromRialtoParachainMessagePayload = messages::target::FromBridgedChainMessagePayload; -/// Messages proof for RialtoParachain -> Millau messages. -type FromRialtoParachainMessagesProof = - messages::target::FromBridgedChainMessagesProof; - -/// Messages delivery proof for Millau -> RialtoParachain messages. -type ToRialtoParachainMessagesDeliveryProof = - messages::source::FromBridgedChainMessagesDeliveryProof; - /// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChainMessageDispatch< WithRialtoParachainMessageBridge, @@ -115,6 +105,12 @@ impl messages::ThisChainWithMessages for Millau { /// RialtoParachain chain from message lane point of view. #[derive(RuntimeDebug, Clone, Copy)] pub struct RialtoParachain; +/// RialtoParachain as source header chain. +pub type RialtoParachainAsSourceHeaderChain = + SourceHeaderChainAdapter; +/// RialtoParachain as target header chain. +pub type RialtoParachainAsTargetHeaderChain = + TargetHeaderChainAdapter; impl messages::UnderlyingChainProvider for RialtoParachain { type Chain = bp_rialto_parachain::RialtoParachain; @@ -125,43 +121,3 @@ impl messages::BridgedChainWithMessages for RialtoParachain { true } } - -impl TargetHeaderChain for RialtoParachain { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof or one or several keys; - // - id of the lane we prove state of. - type MessagesDeliveryProof = ToRialtoParachainMessagesDeliveryProof; - - fn verify_message(payload: &ToRialtoParachainMessagePayload) -> Result<(), Self::Error> { - messages::source::verify_chain_message::(payload) - } - - fn verify_messages_delivery_proof( - proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::(proof) - } -} - -impl SourceHeaderChain for RialtoParachain { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof or one or several keys; - // - id of the lane we prove messages for; - // - inclusive range of messages nonces that are proved. - type MessagesProof = FromRialtoParachainMessagesProof; - - fn verify_messages_proof( - proof: Self::MessagesProof, - messages_count: u32, - ) -> Result, Self::Error> { - messages::target::verify_messages_proof::( - proof, - messages_count, - ) - .map_err(Into::into) - } -} diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 5ad8506acbf3e..2bc787c495358 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -581,7 +581,7 @@ impl pallet_bridge_messages::Config for Runtime { type InboundRelayer = bp_millau::AccountId; type DeliveryPayments = (); - type TargetHeaderChain = crate::millau_messages::Millau; + type TargetHeaderChain = crate::millau_messages::MillauAsTargetHeaderChain; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, @@ -589,7 +589,7 @@ impl pallet_bridge_messages::Config for Runtime { frame_support::traits::ConstU128<100_000>, >; - type SourceHeaderChain = crate::millau_messages::Millau; + type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; type BridgedChainId = BridgedChainId; } diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index e21cf76a82c81..850ec1da60db8 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -21,13 +21,11 @@ use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; -use bp_messages::{ - source_chain::TargetHeaderChain, - target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, -}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge}; +use bridge_runtime_common::messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Default lane that is used to send messages to Millau. @@ -114,6 +112,10 @@ impl messages::ThisChainWithMessages for RialtoParachain { /// Millau chain from message lane point of view. #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; +/// Millau as source header chain. +pub type MillauAsSourceHeaderChain = SourceHeaderChainAdapter; +/// Millau as target header chain. +pub type MillauAsTargetHeaderChain = TargetHeaderChainAdapter; impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; @@ -124,40 +126,3 @@ impl messages::BridgedChainWithMessages for Millau { true } } - -impl TargetHeaderChain for Millau { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof of one or several keys; - // - id of the lane we prove state of. - type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; - - fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { - messages::source::verify_chain_message::(payload) - } - - fn verify_messages_delivery_proof( - proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::(proof) - } -} - -impl SourceHeaderChain for Millau { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof of one or several keys; - // - id of the lane we prove messages for; - // - inclusive range of messages nonces that are proved. - type MessagesProof = FromMillauMessagesProof; - - fn verify_messages_proof( - proof: Self::MessagesProof, - messages_count: u32, - ) -> Result, Self::Error> { - messages::target::verify_messages_proof::(proof, messages_count) - .map_err(Into::into) - } -} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 123cd477d9786..d9b07d582fb20 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -448,7 +448,7 @@ impl pallet_bridge_messages::Config for Runtime { type InboundRelayer = bp_millau::AccountId; type DeliveryPayments = (); - type TargetHeaderChain = crate::millau_messages::Millau; + type TargetHeaderChain = crate::millau_messages::MillauAsTargetHeaderChain; type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, @@ -456,7 +456,7 @@ impl pallet_bridge_messages::Config for Runtime { frame_support::traits::ConstU128<100_000>, >; - type SourceHeaderChain = crate::millau_messages::Millau; + type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; type BridgedChainId = BridgedChainId; } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 90a63a733c33c..09fbe46453df9 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -18,13 +18,11 @@ use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; -use bp_messages::{ - source_chain::TargetHeaderChain, - target_chain::{ProvedMessages, SourceHeaderChain}, - InboundLaneData, LaneId, Message, MessageNonce, -}; +use bp_messages::{LaneId, MessageNonce}; use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{self, MessageBridge}; +use bridge_runtime_common::messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +}; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; /// Lane that is used for XCM messages exchange. @@ -110,6 +108,10 @@ impl messages::ThisChainWithMessages for Rialto { /// Millau chain from message lane point of view. #[derive(RuntimeDebug, Clone, Copy)] pub struct Millau; +/// Millau as source header chain. +pub type MillauAsSourceHeaderChain = SourceHeaderChainAdapter; +/// Millau as target header chain. +pub type MillauAsTargetHeaderChain = TargetHeaderChainAdapter; impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; @@ -121,43 +123,6 @@ impl messages::BridgedChainWithMessages for Millau { } } -impl TargetHeaderChain for Millau { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof of one or several keys; - // - id of the lane we prove state of. - type MessagesDeliveryProof = ToMillauMessagesDeliveryProof; - - fn verify_message(payload: &ToMillauMessagePayload) -> Result<(), Self::Error> { - messages::source::verify_chain_message::(payload) - } - - fn verify_messages_delivery_proof( - proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - messages::source::verify_messages_delivery_proof::(proof) - } -} - -impl SourceHeaderChain for Millau { - type Error = &'static str; - // The proof is: - // - hash of the header this proof has been created with; - // - the storage proof of one or several keys; - // - id of the lane we prove messages for; - // - inclusive range of messages nonces that are proved. - type MessagesProof = FromMillauMessagesProof; - - fn verify_messages_proof( - proof: Self::MessagesProof, - messages_count: u32, - ) -> Result, Self::Error> { - messages::target::verify_messages_proof::(proof, messages_count) - .map_err(Into::into) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 9153d7a05dda8..9e8e6b29db226 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -29,7 +29,6 @@ pallet-bridge-relayers = { path = "../../modules/relayers", default-features = f frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -46,9 +45,8 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] -bp-rialto = { path = "../../primitives/chain-rialto" } bp-test-utils = { path = "../../primitives/test-utils" } -millau-runtime = { path = "../millau/runtime" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] @@ -82,7 +80,6 @@ std = [ "xcm-executor/std", ] runtime-benchmarks = [ - "pallet-balances", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index e8e3e7f87cc60..45387b5a16839 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -81,8 +81,8 @@ macro_rules! assert_bridge_messages_pallet_types( // configuration is used), or something has broke existing configuration (meaning that all bridged chains // and relays will stop functioning) use $crate::messages::{ - source::FromThisChainMessagePayload, - target::FromBridgedChainMessagePayload, + source::{FromThisChainMessagePayload, TargetHeaderChainAdapter}, + target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter}, AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, }; use pallet_bridge_messages::Config as MessagesConfig; @@ -93,8 +93,8 @@ macro_rules! assert_bridge_messages_pallet_types( assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload>>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, BridgedChain<$bridge>); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::SourceHeaderChain, BridgedChain<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, TargetHeaderChainAdapter<$bridge>); + assert_type_eq_all!(<$r as MessagesConfig<$i>>::SourceHeaderChain, SourceHeaderChainAdapter<$bridge>); } } ); diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index f8d2e7a039ebb..9f31450bd28a4 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -30,6 +30,7 @@ pub mod parachains_benchmarking; pub mod refund_relayer_extension; mod messages_generation; +mod mock; #[cfg(feature = "integrity-test")] pub mod integrity; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 3974966daaddf..0d38e4b0d2504 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -22,8 +22,10 @@ use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ - source_chain::LaneMessageVerifier, - target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages}, + source_chain::{LaneMessageVerifier, TargetHeaderChain}, + target_chain::{ + DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, + }, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Size, StorageProofChecker}; @@ -212,6 +214,26 @@ pub mod source { ) } + /// `TargetHeaderChain` implementation that is using default types and perform default checks. + pub struct TargetHeaderChainAdapter(PhantomData); + + impl TargetHeaderChain>> + for TargetHeaderChainAdapter + { + type Error = &'static str; + type MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof>>; + + fn verify_message(payload: &FromThisChainMessagePayload) -> Result<(), Self::Error> { + verify_chain_message::(payload) + } + + fn verify_messages_delivery_proof( + proof: Self::MessagesDeliveryProof, + ) -> Result<(LaneId, InboundLaneData>>), Self::Error> { + verify_messages_delivery_proof::(proof) + } + } + /// Do basic Bridged-chain specific verification of This -> Bridged chain message. /// /// Ok result from this function means that the delivery transaction with this message @@ -549,6 +571,21 @@ pub mod target { maximal_extrinsic_size / 3 * 2 } + /// `SourceHeaderChain` implementation that is using default types and perform default checks. + pub struct SourceHeaderChainAdapter(PhantomData); + + impl SourceHeaderChain for SourceHeaderChainAdapter { + type Error = &'static str; + type MessagesProof = FromBridgedChainMessagesProof>>; + + fn verify_messages_proof( + proof: Self::MessagesProof, + messages_count: u32, + ) -> Result, Self::Error> { + verify_messages_proof::(proof, messages_count).map_err(Into::into) + } + } + /// Verify proof of Bridged -> This chain messages. /// /// This function is used when Bridged chain is directly using GRANDPA finality. For Bridged @@ -702,206 +739,22 @@ pub type BridgeMessagesCallOf = bp_messages::BridgeMessagesCall< #[cfg(test)] mod tests { use super::*; - use crate::messages_generation::{ - encode_all_messages, encode_lane_data, prepare_messages_storage_proof, + use crate::{ + messages_generation::{ + encode_all_messages, encode_lane_data, prepare_messages_storage_proof, + }, + mock::*, }; - use codec::{Decode, Encode}; - use frame_support::weights::Weight; + use bp_header_chain::StoredHeaderDataBuilder; + use bp_runtime::HeaderId; + use codec::Encode; use sp_core::H256; - use sp_runtime::traits::{BlakeTwo256, Header as _}; - use std::cell::RefCell; - - const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; - const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; - const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; - - /// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from - /// BridgedChain. - #[derive(Debug, PartialEq, Eq)] - struct OnThisChainBridge; - - impl MessageBridge for OnThisChainBridge { - const THIS_CHAIN_ID: ChainId = *b"this"; - const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; - - type ThisChain = ThisChain; - type BridgedChain = BridgedChain; - type BridgedHeaderChain = BridgedHeaderChain; - } - - /// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from - /// ThisChain; - #[derive(Debug, PartialEq, Eq)] - struct OnBridgedChainBridge; - - impl MessageBridge for OnBridgedChainBridge { - const THIS_CHAIN_ID: ChainId = *b"brdg"; - const BRIDGED_CHAIN_ID: ChainId = *b"this"; - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; - - type ThisChain = BridgedChain; - type BridgedChain = ThisChain; - type BridgedHeaderChain = ThisHeaderChain; - } - - #[derive(Clone, Debug)] - struct ThisChainOrigin(Result, ()>); - - impl From - for Result, ThisChainOrigin> - { - fn from( - origin: ThisChainOrigin, - ) -> Result, ThisChainOrigin> { - origin.clone().0.map_err(|_| origin) - } - } - - #[derive(Clone, Debug)] - struct BridgedChainOrigin; - - impl From - for Result, BridgedChainOrigin> - { - fn from( - _origin: BridgedChainOrigin, - ) -> Result, BridgedChainOrigin> { - unreachable!() - } - } - - struct ThisUnderlyingChain; - type ThisChainHeader = sp_runtime::generic::Header; - type ThisChainAccountId = u32; - type ThisChainBalance = u32; - #[derive(Decode, Encode)] - struct ThisChainCall; - - impl Chain for ThisUnderlyingChain { - type BlockNumber = u64; - type Hash = H256; - type Hasher = BlakeTwo256; - type Header = ThisChainHeader; - type AccountId = ThisChainAccountId; - type Balance = ThisChainBalance; - type Index = u32; - type Signature = sp_runtime::MultiSignature; - - fn max_extrinsic_size() -> u32 { - BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE - } - - fn max_extrinsic_weight() -> Weight { - Weight::zero() - } - } - - struct ThisChain; - - impl UnderlyingChainProvider for ThisChain { - type Chain = ThisUnderlyingChain; - } - - impl ThisChainWithMessages for ThisChain { - type RuntimeOrigin = ThisChainOrigin; - type RuntimeCall = ThisChainCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - lane == TEST_LANE_ID - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE - } - } - - impl BridgedChainWithMessages for ThisChain { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - unreachable!() - } - } - - struct BridgedUnderlyingChain; - type BridgedChainHeader = sp_runtime::generic::Header; - type BridgedChainAccountId = u128; - type BridgedChainBalance = u128; - #[derive(Decode, Encode)] - struct BridgedChainCall; - - impl Chain for BridgedUnderlyingChain { - type BlockNumber = u64; - type Hash = H256; - type Hasher = BlakeTwo256; - type Header = BridgedChainHeader; - type AccountId = BridgedChainAccountId; - type Balance = BridgedChainBalance; - type Index = u32; - type Signature = sp_runtime::MultiSignature; - - fn max_extrinsic_size() -> u32 { - BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE - } - fn max_extrinsic_weight() -> Weight { - Weight::zero() - } - } - - struct BridgedChain; - - impl UnderlyingChainProvider for BridgedChain { - type Chain = BridgedUnderlyingChain; - } - - impl ThisChainWithMessages for BridgedChain { - type RuntimeOrigin = BridgedChainOrigin; - type RuntimeCall = BridgedChainCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - unreachable!() - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - unreachable!() - } - } - - impl BridgedChainWithMessages for BridgedChain { - fn verify_dispatch_weight(message_payload: &[u8]) -> bool { - message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && - message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT - } - } - - thread_local! { - static TEST_BRIDGED_HEADER: RefCell> = RefCell::new(None); - } - - struct BridgedHeaderChain; - - impl HeaderChain for BridgedHeaderChain { - fn finalized_header_state_root( - _hash: HashOf, - ) -> Option> { - TEST_BRIDGED_HEADER.with(|h| h.borrow().clone()).map(|h| *h.state_root()) - } - } - - struct ThisHeaderChain; - - impl HeaderChain for ThisHeaderChain { - fn finalized_header_state_root(_hash: HashOf) -> Option> { - unreachable!() - } - } + use sp_runtime::traits::Header as _; fn test_lane_outbound_data() -> OutboundLaneData { OutboundLaneData::default() } - const TEST_LANE_ID: &LaneId = &LaneId(*b"test"); - const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; - fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { vec![42] } @@ -910,7 +763,7 @@ mod tests { fn message_is_rejected_when_sent_using_disabled_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), + &frame_system::RawOrigin::Root.into(), &LaneId(*b"dsbl"), &test_lane_outbound_data(), ®ular_outbound_message_payload(), @@ -923,8 +776,8 @@ mod tests { fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { assert_eq!( source::FromThisChainMessageVerifier::::verify_message( - &ThisChainOrigin(Ok(frame_system::RawOrigin::Root)), - TEST_LANE_ID, + &frame_system::RawOrigin::Root.into(), + &TEST_LANE_ID, &OutboundLaneData { latest_received_nonce: 100, latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1, @@ -986,7 +839,7 @@ mod tests { test: impl Fn(target::FromBridgedChainMessagesProof) -> R, ) -> R { let (state_root, storage_proof) = prepare_messages_storage_proof::( - *TEST_LANE_ID, + TEST_LANE_ID, 1..=nonces_end, outbound_lane_data, bp_runtime::StorageProofSize::Minimal(0), @@ -995,22 +848,31 @@ mod tests { encode_outbound_lane_data, ); - TEST_BRIDGED_HEADER.with(|h| { - *h.borrow_mut() = Some(BridgedChainHeader::new( + sp_io::TestExternalities::new(Default::default()).execute_with(move || { + let bridged_header = BridgedChainHeader::new( 0, Default::default(), state_root, Default::default(), Default::default(), - )) - }); + ); + let bridged_header_hash = bridged_header.hash(); - test(target::FromBridgedChainMessagesProof { - bridged_header_hash: Default::default(), - storage_proof, - lane: *TEST_LANE_ID, - nonces_start: 1, - nonces_end, + pallet_bridge_grandpa::BestFinalized::::put(HeaderId( + 0, + bridged_header_hash, + )); + pallet_bridge_grandpa::ImportedHeaders::::insert( + bridged_header_hash, + bridged_header.build(), + ); + test(target::FromBridgedChainMessagesProof { + bridged_header_hash, + storage_proof, + lane: TEST_LANE_ID, + nonces_start: 1, + nonces_end, + }) }) } @@ -1038,7 +900,9 @@ mod tests { fn message_proof_is_rejected_if_header_is_missing_from_the_chain() { assert_eq!( using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { - TEST_BRIDGED_HEADER.with(|h| *h.borrow_mut() = None); + let bridged_header_hash = + pallet_bridge_grandpa::BestFinalized::::get().unwrap().1; + pallet_bridge_grandpa::ImportedHeaders::::remove(bridged_header_hash); target::verify_messages_proof::(proof, 10) }), Err(target::MessageProofError::HeaderChain(HeaderChainError::UnknownHeader)), @@ -1049,8 +913,19 @@ mod tests { fn message_proof_is_rejected_if_header_state_root_mismatches() { assert_eq!( using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { - TEST_BRIDGED_HEADER - .with(|h| h.borrow_mut().as_mut().unwrap().state_root = Default::default()); + let bridged_header_hash = + pallet_bridge_grandpa::BestFinalized::::get().unwrap().1; + pallet_bridge_grandpa::ImportedHeaders::::insert( + bridged_header_hash, + BridgedChainHeader::new( + 0, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ) + .build(), + ); target::verify_messages_proof::(proof, 10) }), Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageRootMismatch)), @@ -1138,7 +1013,7 @@ mod tests { |proof| target::verify_messages_proof::(proof, 0), ), Ok(vec![( - *TEST_LANE_ID, + TEST_LANE_ID, ProvedLaneMessages { lane_state: Some(OutboundLaneData { oldest_unpruned_nonce: 1, @@ -1168,7 +1043,7 @@ mod tests { |proof| target::verify_messages_proof::(proof, 1), ), Ok(vec![( - *TEST_LANE_ID, + TEST_LANE_ID, ProvedLaneMessages { lane_state: Some(OutboundLaneData { oldest_unpruned_nonce: 1, @@ -1176,7 +1051,7 @@ mod tests { latest_generated_nonce: 1, }), messages: vec![Message { - key: MessageKey { lane_id: *TEST_LANE_ID, nonce: 1 }, + key: MessageKey { lane_id: TEST_LANE_ID, nonce: 1 }, payload: vec![42], }], }, diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 919c03583b882..afe95422d185f 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -48,7 +48,6 @@ pub fn prepare_message_proof( ) -> (FromBridgedChainMessagesProof>>, Weight) where R: frame_system::Config>> - + pallet_balances::Config>> + pallet_bridge_grandpa::Config, R::BridgedChain: bp_runtime::Chain>, Header = BH>, B: MessageBridge, diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_extension.rs index 0f680f84e493a..1e207dc605b36 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_extension.rs @@ -96,20 +96,17 @@ impl< #[cfg(test)] mod tests { - use bp_messages::UnrewardedRelayersState; - use millau_runtime::{ - bridge_runtime_common::{ - messages::{ - source::FromBridgedChainMessagesDeliveryProof, - target::FromBridgedChainMessagesProof, - }, - BridgeRuntimeFilterCall, + use crate::{ + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }, - Runtime, RuntimeCall, WithRialtoMessagesInstance, + mock::{TestRuntime, ThisChainRuntimeCall}, + BridgeRuntimeFilterCall, }; + use bp_messages::UnrewardedRelayersState; fn deliver_message_10() { - pallet_bridge_messages::InboundLanes::::insert( + pallet_bridge_messages::InboundLanes::::insert( bp_messages::LaneId([0, 0, 0, 0]), bp_messages::InboundLaneData { relayers: Default::default(), last_confirmed_nonce: 10 }, ); @@ -119,10 +116,10 @@ mod tests { nonces_start: bp_messages::MessageNonce, nonces_end: bp_messages::MessageNonce, ) -> bool { - pallet_bridge_messages::Pallet::::validate( - &RuntimeCall::BridgeRialtoMessages( - pallet_bridge_messages::Call::::receive_messages_proof { - relayer_id_at_bridged_chain: [0u8; 32].into(), + pallet_bridge_messages::Pallet::::validate( + &ThisChainRuntimeCall::BridgeMessages( + pallet_bridge_messages::Call::::receive_messages_proof { + relayer_id_at_bridged_chain: 42, messages_count: (nonces_end - nonces_start + 1) as u32, dispatch_weight: frame_support::weights::Weight::zero(), proof: FromBridgedChainMessagesProof { @@ -169,7 +166,7 @@ mod tests { } fn confirm_message_10() { - pallet_bridge_messages::OutboundLanes::::insert( + pallet_bridge_messages::OutboundLanes::::insert( bp_messages::LaneId([0, 0, 0, 0]), bp_messages::OutboundLaneData { oldest_unpruned_nonce: 0, @@ -180,21 +177,20 @@ mod tests { } fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool { - pallet_bridge_messages::Pallet::::validate( - &RuntimeCall::BridgeRialtoMessages(pallet_bridge_messages::Call::< - Runtime, - WithRialtoMessagesInstance, - >::receive_messages_delivery_proof { - proof: FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: Default::default(), - storage_proof: Vec::new(), - lane: bp_messages::LaneId([0, 0, 0, 0]), - }, - relayers_state: UnrewardedRelayersState { - last_delivered_nonce, - ..Default::default() + pallet_bridge_messages::Pallet::::validate( + &ThisChainRuntimeCall::BridgeMessages( + pallet_bridge_messages::Call::::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: Vec::new(), + lane: bp_messages::LaneId([0, 0, 0, 0]), + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce, + ..Default::default() + }, }, - }), + ), ) .is_ok() } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs new file mode 100644 index 0000000000000..d4b177510bf3a --- /dev/null +++ b/bin/runtime-common/src/mock.rs @@ -0,0 +1,422 @@ +// 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 . + +//! A mock runtime for testing different stuff in the crate. We've been using Millau +//! runtime for that before, but it has two drawbacks: +//! +//! - circular dependencies between this crate and Millau runtime; +//! +//! - we can't use (e.g. as git subtree or by copying) this crate in repo without Millau. + +#![cfg(test)] + +use crate::messages::{ + source::{ + FromThisChainMaximalOutboundPayloadSize, FromThisChainMessagePayload, + FromThisChainMessageVerifier, TargetHeaderChainAdapter, + }, + target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter}, + BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages, +}; + +use bp_header_chain::HeaderChain; +use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; +use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; +use codec::{Decode, Encode}; +use frame_support::{ + parameter_types, + weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight}, +}; +use pallet_transaction_payment::Multiplier; +use sp_runtime::{ + testing::H256, + traits::{BlakeTwo256, ConstU32, ConstU64, ConstU8, IdentityLookup}, + FixedPointNumber, Perquintill, +}; + +/// Account identifier at `ThisChain`. +pub type ThisChainAccountId = u64; +/// Balance at `ThisChain`. +pub type ThisChainBalance = u64; +/// Block number at `ThisChain`. +pub type ThisChainBlockNumber = u32; +/// Hash at `ThisChain`. +pub type ThisChainHash = H256; +/// Hasher at `ThisChain`. +pub type ThisChainHasher = BlakeTwo256; +/// Runtime call at `ThisChain`. +pub type ThisChainRuntimeCall = RuntimeCall; +/// Runtime call origin at `ThisChain`. +pub type ThisChainCallOrigin = RuntimeOrigin; +/// Header of `ThisChain`. +pub type ThisChainHeader = sp_runtime::generic::Header; +/// Block of `ThisChain`. +pub type ThisChainBlock = frame_system::mocking::MockBlock; +/// Unchecked extrinsic of `ThisChain`. +pub type ThisChainUncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + +/// Account identifier at the `BridgedChain`. +pub type BridgedChainAccountId = u128; +/// Balance at the `BridgedChain`. +pub type BridgedChainBalance = u128; +/// Block number at the `BridgedChain`. +pub type BridgedChainBlockNumber = u32; +/// Hash at the `BridgedChain`. +pub type BridgedChainHash = H256; +/// Hasher at the `BridgedChain`. +pub type BridgedChainHasher = BlakeTwo256; +/// Header of the `BridgedChain`. +pub type BridgedChainHeader = + sp_runtime::generic::Header; + +/// Message lane used in tests. +pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +/// Maximal number of queued messages at the test lane. +pub const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; +/// Minimal extrinsic weight at the `BridgedChain`. +pub const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; +/// Maximal extrinsic weight at the `BridgedChain`. +pub const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; +/// Maximal extrinsic size at the `BridgedChain`. +pub const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; + +frame_support::construct_runtime! { + pub enum TestRuntime where + Block = ThisChainBlock, + NodeBlock = ThisChainBlock, + UncheckedExtrinsic = ThisChainUncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Utility: pallet_utility, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, + BridgeGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeParachains: pallet_bridge_parachains::{Pallet, Call, Storage, Event}, + BridgeMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, + } +} + +crate::generate_bridge_reject_obsolete_headers_and_messages! { + ThisChainRuntimeCall, ThisChainAccountId, + BridgeGrandpa, BridgeParachains, BridgeMessages +} + +parameter_types! { + pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID]; + pub const BridgedChainId: ChainId = *b"brdg"; + pub const BridgedParasPalletName: &'static str = "Paras"; + pub const ExistentialDeposit: ThisChainBalance = 500; + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + pub const TransactionBaseFee: ThisChainBalance = 0; + pub const TransactionByteFee: ThisChainBalance = 1; + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); + pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); + pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); +} + +impl frame_system::Config for TestRuntime { + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type RuntimeCall = RuntimeCall; + type BlockNumber = ThisChainBlockNumber; + type Hash = ThisChainHash; + type Hashing = ThisChainHasher; + type AccountId = ThisChainAccountId; + type Lookup = IdentityLookup; + type Header = ThisChainHeader; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU32<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = frame_support::traits::Everything; + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = DbWeight; + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_utility::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + +impl pallet_balances::Config for TestRuntime { + type Balance = ThisChainBalance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_transaction_payment::Config for TestRuntime { + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< + TestRuntime, + TargetBlockFullness, + AdjustmentVariable, + MinimumMultiplier, + MaximumMultiplier, + >; + type RuntimeEvent = RuntimeEvent; +} + +impl pallet_bridge_grandpa::Config for TestRuntime { + type BridgedChain = BridgedUnderlyingChain; + type MaxRequests = ConstU32<50>; + type HeadersToKeep = ConstU32<8>; + type MaxBridgedAuthorities = ConstU32<1024>; + type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; +} + +impl pallet_bridge_parachains::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type BridgesGrandpaPalletInstance = (); + type ParasPalletName = BridgedParasPalletName; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; + type HeadsToKeep = ConstU32<8>; + type MaxParaHeadDataSize = ConstU32<1024>; + type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; +} + +impl pallet_bridge_messages::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; + type ActiveOutboundLanes = ActiveOutboundLanes; + type MaxUnrewardedRelayerEntriesAtInboundLane = ConstU64<16>; + type MaxUnconfirmedMessagesAtInboundLane = ConstU64<16>; + + type MaximalOutboundPayloadSize = FromThisChainMaximalOutboundPayloadSize; + type OutboundPayload = FromThisChainMessagePayload; + + type InboundPayload = FromBridgedChainMessagePayload; + type InboundRelayer = BridgedChainAccountId; + type DeliveryPayments = (); + + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = FromThisChainMessageVerifier; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + TestRuntime, + frame_support::traits::ConstU64<100_000>, + frame_support::traits::ConstU64<10_000>, + >; + + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = + ForbidInboundMessages<(), FromBridgedChainMessagePayload>; + type BridgedChainId = BridgedChainId; +} + +impl pallet_bridge_relayers::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type Reward = ThisChainBalance; + type PaymentProcedure = (); + type WeightInfo = (); +} + +/// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from +/// BridgedChain. +#[derive(Debug, PartialEq, Eq)] +pub struct OnThisChainBridge; + +impl MessageBridge for OnThisChainBridge { + const THIS_CHAIN_ID: ChainId = *b"this"; + const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; + + type ThisChain = ThisChain; + type BridgedChain = BridgedChain; + type BridgedHeaderChain = pallet_bridge_grandpa::GrandpaChainHeaders; +} + +/// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from +/// ThisChain; +#[derive(Debug, PartialEq, Eq)] +pub struct OnBridgedChainBridge; + +impl MessageBridge for OnBridgedChainBridge { + const THIS_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_CHAIN_ID: ChainId = *b"this"; + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; + + type ThisChain = BridgedChain; + type BridgedChain = ThisChain; + type BridgedHeaderChain = ThisHeaderChain; +} + +/// Dummy implementation of `HeaderChain` for `ThisChain` at the `BridgedChain`. +pub struct ThisHeaderChain; + +impl HeaderChain for ThisHeaderChain { + fn finalized_header_state_root(_hash: HashOf) -> Option> { + unreachable!() + } +} + +/// Call origin at `BridgedChain`. +#[derive(Clone, Debug)] +pub struct BridgedChainOrigin; + +impl From + for Result, BridgedChainOrigin> +{ + fn from( + _origin: BridgedChainOrigin, + ) -> Result, BridgedChainOrigin> { + unreachable!() + } +} + +/// Underlying chain of `ThisChain`. +pub struct ThisUnderlyingChain; + +impl Chain for ThisUnderlyingChain { + type BlockNumber = ThisChainBlockNumber; + type Hash = ThisChainHash; + type Hasher = ThisChainHasher; + type Header = ThisChainHeader; + type AccountId = ThisChainAccountId; + type Balance = ThisChainBalance; + type Index = u32; + type Signature = sp_runtime::MultiSignature; + + fn max_extrinsic_size() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +/// The chain where we are in tests. +pub struct ThisChain; + +impl UnderlyingChainProvider for ThisChain { + type Chain = ThisUnderlyingChain; +} + +impl ThisChainWithMessages for ThisChain { + type RuntimeOrigin = ThisChainCallOrigin; + type RuntimeCall = ThisChainRuntimeCall; + + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { + *lane == TEST_LANE_ID + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + } +} + +impl BridgedChainWithMessages for ThisChain { + fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { + unreachable!() + } +} + +/// Underlying chain of `BridgedChain`. +pub struct BridgedUnderlyingChain; +/// Some parachain under `BridgedChain` consensus. +pub struct BridgedUnderlyingParachain; +/// Runtime call of the `BridgedChain`. +#[derive(Decode, Encode)] +pub struct BridgedChainCall; + +impl Chain for BridgedUnderlyingChain { + type BlockNumber = BridgedChainBlockNumber; + type Hash = BridgedChainHash; + type Hasher = BridgedChainHasher; + type Header = BridgedChainHeader; + type AccountId = BridgedChainAccountId; + type Balance = BridgedChainBalance; + type Index = u32; + type Signature = sp_runtime::MultiSignature; + + fn max_extrinsic_size() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +impl Chain for BridgedUnderlyingParachain { + type BlockNumber = BridgedChainBlockNumber; + type Hash = BridgedChainHash; + type Hasher = BridgedChainHasher; + type Header = BridgedChainHeader; + type AccountId = BridgedChainAccountId; + type Balance = BridgedChainBalance; + type Index = u32; + type Signature = sp_runtime::MultiSignature; + + fn max_extrinsic_size() -> u32 { + BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } +} + +impl Parachain for BridgedUnderlyingParachain { + const PARACHAIN_ID: u32 = 42; +} + +/// The other, bridged chain, used in tests. +pub struct BridgedChain; + +impl UnderlyingChainProvider for BridgedChain { + type Chain = BridgedUnderlyingChain; +} + +impl ThisChainWithMessages for BridgedChain { + type RuntimeOrigin = BridgedChainOrigin; + type RuntimeCall = BridgedChainCall; + + fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { + unreachable!() + } + + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { + unreachable!() + } +} + +impl BridgedChainWithMessages for BridgedChain { + fn verify_dispatch_weight(message_payload: &[u8]) -> bool { + message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && + message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT + } +} diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 0038af975db75..51a7db3b53b00 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -19,12 +19,7 @@ //! with calls that are: delivering new messsage and all necessary underlying headers //! (parachain or relay chain). -// hack because we have circular (test-level) dependency between `millau-runtime` -// and `bridge-runtime-common` crates -#[cfg(not(test))] use crate::messages::target::FromBridgedChainMessagesProof; -#[cfg(test)] -use millau_runtime::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use bp_messages::{target_chain::SourceHeaderChain, LaneId, MessageNonce}; use bp_polkadot_core::parachains::ParaId; @@ -475,36 +470,37 @@ where #[cfg(test)] mod tests { use super::*; + use crate::{messages::target::FromBridgedChainMessagesProof, mock::*}; use bp_messages::InboundLaneData; use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::ParaHeadsProof; use bp_runtime::HeaderId; use bp_test_utils::make_default_justification; use frame_support::{assert_storage_noop, parameter_types, weights::Weight}; - use millau_runtime::{ - RialtoGrandpaInstance, Runtime, RuntimeCall, WithRialtoParachainMessagesInstance, - WithRialtoParachainsInstance, - }; use sp_runtime::{transaction_validity::InvalidTransaction, DispatchError}; parameter_types! { pub TestParachain: u32 = 1000; - pub TestLaneId: LaneId = LaneId([0, 0, 0, 0]); + pub TestLaneId: LaneId = TEST_LANE_ID; } type TestExtension = RefundRelayerForMessagesFromParachain< - millau_runtime::Runtime, - RialtoGrandpaInstance, - WithRialtoParachainsInstance, - WithRialtoParachainMessagesInstance, - millau_runtime::BridgeRejectObsoleteHeadersAndMessages, + TestRuntime, + (), + (), + (), + BridgeRejectObsoleteHeadersAndMessages, TestParachain, TestLaneId, - millau_runtime::Runtime, + TestRuntime, >; - fn relayer_account() -> millau_runtime::AccountId { - [0u8; 32].into() + fn relayer_account_at_this_chain() -> ThisChainAccountId { + 0 + } + + fn relayer_account_at_bridged_chain() -> BridgedChainAccountId { + 0 } fn initialize_environment( @@ -513,9 +509,7 @@ mod tests { best_delivered_message: MessageNonce, ) { let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); - pallet_bridge_grandpa::BestFinalized::::put( - best_relay_header, - ); + pallet_bridge_grandpa::BestFinalized::::put(best_relay_header); let para_id = ParaId(TestParachain::get()); let para_info = ParaInfo { @@ -525,18 +519,16 @@ mod tests { }, next_imported_hash_position: 0, }; - pallet_bridge_parachains::ParasInfo::::insert( - para_id, para_info, - ); + pallet_bridge_parachains::ParasInfo::::insert(para_id, para_info); let lane_id = TestLaneId::get(); let lane_data = InboundLaneData { last_confirmed_nonce: best_delivered_message, ..Default::default() }; - pallet_bridge_messages::InboundLanes::::insert(lane_id, lane_data); + pallet_bridge_messages::InboundLanes::::insert(lane_id, lane_data); } fn submit_relay_header_call(relay_header_number: RelayBlockNumber) -> RuntimeCall { - let relay_header = bp_rialto::Header::new( + let relay_header = BridgedChainHeader::new( relay_header_number, Default::default(), Default::default(), @@ -545,7 +537,7 @@ mod tests { ); let relay_justification = make_default_justification(&relay_header); - RuntimeCall::BridgeRialtoGrandpa(GrandpaCall::submit_finality_proof { + RuntimeCall::BridgeGrandpa(GrandpaCall::submit_finality_proof { finality_target: Box::new(relay_header), justification: relay_justification, }) @@ -554,7 +546,7 @@ mod tests { fn submit_parachain_head_call( parachain_head_at_relay_header_number: RelayBlockNumber, ) -> RuntimeCall { - RuntimeCall::BridgeRialtoParachains(ParachainsCall::submit_parachain_heads { + RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads { at_relay_block: (parachain_head_at_relay_header_number, RelayBlockHash::default()), parachains: vec![(ParaId(TestParachain::get()), [1u8; 32].into())], parachain_heads_proof: ParaHeadsProof(vec![]), @@ -562,9 +554,9 @@ mod tests { } fn message_delivery_call(best_message: MessageNonce) -> RuntimeCall { - RuntimeCall::BridgeRialtoParachainMessages(MessagesCall::receive_messages_proof { - relayer_id_at_bridged_chain: relayer_account(), - proof: millau_runtime::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof { + RuntimeCall::BridgeMessages(MessagesCall::receive_messages_proof { + relayer_id_at_bridged_chain: relayer_account_at_bridged_chain(), + proof: FromBridgedChainMessagesProof { bridged_header_hash: Default::default(), storage_proof: vec![], lane: TestLaneId::get(), @@ -602,9 +594,9 @@ mod tests { }) } - fn all_finality_pre_dispatch_data() -> PreDispatchData { + fn all_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { - relayer: relayer_account(), + relayer: relayer_account_at_this_chain(), call_type: CallType::AllFinalityAndDelivery( ExpectedRelayChainState { best_block_number: 200 }, ExpectedParachainState { at_relay_block_number: 200 }, @@ -613,9 +605,9 @@ mod tests { } } - fn parachain_finality_pre_dispatch_data() -> PreDispatchData { + fn parachain_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { - relayer: relayer_account(), + relayer: relayer_account_at_this_chain(), call_type: CallType::ParachainFinalityAndDelivery( ExpectedParachainState { at_relay_block_number: 200 }, MessagesState { best_nonce: 100 }, @@ -623,9 +615,9 @@ mod tests { } } - fn delivery_pre_dispatch_data() -> PreDispatchData { + fn delivery_pre_dispatch_data() -> PreDispatchData { PreDispatchData { - relayer: relayer_account(), + relayer: relayer_account_at_this_chain(), call_type: CallType::Delivery(MessagesState { best_nonce: 100 }), } } @@ -636,14 +628,14 @@ mod tests { fn run_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData); - extension.validate(&relayer_account(), &call, &DispatchInfo::default(), 0) + extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_pre_dispatch( call: RuntimeCall, - ) -> Result>, TransactionValidityError> { + ) -> Result>, TransactionValidityError> { let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData); - extension.pre_dispatch(&relayer_account(), &call, &DispatchInfo::default(), 0) + extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn dispatch_info() -> DispatchInfo { @@ -661,7 +653,7 @@ mod tests { } fn run_post_dispatch( - pre_dispatch_data: Option>, + pre_dispatch_data: Option>, dispatch_result: DispatchResult, ) { let post_dispatch_result = TestExtension::post_dispatch( @@ -674,8 +666,8 @@ mod tests { assert_eq!(post_dispatch_result, Ok(())); } - fn expected_reward() -> millau_runtime::Balance { - pallet_transaction_payment::Pallet::::compute_actual_fee( + fn expected_reward() -> ThisChainBalance { + pallet_transaction_payment::Pallet::::compute_actual_fee( 1024, &dispatch_info(), &post_dispatch_info(), @@ -804,7 +796,7 @@ mod tests { let call = RuntimeCall::Utility(UtilityCall::batch_all { calls: vec![ - RuntimeCall::BridgeRialtoParachains(ParachainsCall::submit_parachain_heads { + RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads { at_relay_block: (100, RelayBlockHash::default()), parachains: vec![ (ParaId(TestParachain::get()), [1u8; 32].into()), @@ -892,7 +884,10 @@ mod tests { run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())); assert_eq!( - RelayersPallet::::relayer_reward(relayer_account(), TestLaneId::get()), + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + TestLaneId::get() + ), Some(expected_reward()), ); }); @@ -905,7 +900,10 @@ mod tests { run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(())); assert_eq!( - RelayersPallet::::relayer_reward(relayer_account(), TestLaneId::get()), + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + TestLaneId::get() + ), Some(expected_reward()), ); }); @@ -918,7 +916,10 @@ mod tests { run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())); assert_eq!( - RelayersPallet::::relayer_reward(relayer_account(), TestLaneId::get()), + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + TestLaneId::get() + ), Some(expected_reward()), ); }); diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index c7ea1e544f2d4..954818a3b5052 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -40,6 +40,7 @@ std = [ "bp-relayers/std", "bp-runtime/std", "codec/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", "log/std", diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 1b285b065aa27..6604d425cfc4a 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -22,7 +22,7 @@ use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; use frame_support::{weights::Weight, Parameter, RuntimeDebug}; use scale_info::TypeInfo; -use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, prelude::*}; +use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, marker::PhantomData, prelude::*}; /// Proved messages from the source chain. pub type ProvedMessages = BTreeMap>; @@ -164,15 +164,19 @@ impl DeliveryPayments for () { /// Structure that may be used in place of `SourceHeaderChain` and `MessageDispatch` on chains, /// where inbound messages are forbidden. -pub struct ForbidInboundMessages; +pub struct ForbidInboundMessages( + PhantomData<(MessagesProof, DispatchPayload)>, +); /// Error message that is used in `ForbidOutboundMessages` implementation. const ALL_INBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all inbound messages"; -impl SourceHeaderChain for ForbidInboundMessages { +impl SourceHeaderChain + for ForbidInboundMessages +{ type Error = &'static str; - type MessagesProof = (); + type MessagesProof = MessagesProof; fn verify_messages_proof( _proof: Self::MessagesProof, @@ -182,8 +186,10 @@ impl SourceHeaderChain for ForbidInboundMessages { } } -impl MessageDispatch for ForbidInboundMessages { - type DispatchPayload = (); +impl MessageDispatch + for ForbidInboundMessages +{ + type DispatchPayload = DispatchPayload; type DispatchLevelResult = (); fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index acede813995d1..7479811a57d7b 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -20,7 +20,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -bp-rialto = { path = "../chain-rialto" } hex = "0.4" hex-literal = "0.3" diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index 207908296cbf5..70a91ee941a0d 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -37,6 +37,14 @@ pub trait PaymentProcedure { fn pay_reward(relayer: &Relayer, lane_id: LaneId, reward: Reward) -> Result<(), Self::Error>; } +impl PaymentProcedure for () { + type Error = &'static str; + + fn pay_reward(_: &Relayer, _: LaneId, _: Reward) -> Result<(), Self::Error> { + Ok(()) + } +} + /// Reward payment procedure that does `balances::transfer` call from the account, derived from /// given lane. pub struct PayLaneRewardFromAccount(PhantomData<(T, Relayer)>); @@ -88,21 +96,18 @@ where #[cfg(test)] mod tests { use super::*; + use sp_runtime::testing::H256; #[test] fn lanes_are_using_different_accounts() { assert_eq!( - PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account(LaneId([ - 0, 0, 0, 0 - ])), + PayLaneRewardFromAccount::<(), H256>::lane_rewards_account(LaneId([0, 0, 0, 0])), hex_literal::hex!("626c616e000000006272696467652d6c616e6500000000000000000000000000") .into(), ); assert_eq!( - PayLaneRewardFromAccount::<(), bp_rialto::AccountId>::lane_rewards_account(LaneId([ - 0, 0, 0, 1 - ])), + PayLaneRewardFromAccount::<(), H256>::lane_rewards_account(LaneId([0, 0, 0, 1])), hex_literal::hex!("626c616e000000016272696467652d6c616e6500000000000000000000000000") .into(), ); diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 7caba7561ddc1..7aad5f44e8908 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -52,7 +52,7 @@ mod tests { #[test] fn maximal_rialto_to_millau_message_size_is_computed_correctly() { - use rialto_runtime::millau_messages::Millau; + use rialto_runtime::millau_messages::MillauAsTargetHeaderChain; let maximal_message_size = encode_message::compute_maximal_message_size( bp_rialto::Rialto::max_extrinsic_size(), @@ -60,10 +60,10 @@ mod tests { ); let message = vec![42; maximal_message_size as _]; - assert_eq!(Millau::verify_message(&message), Ok(())); + assert_eq!(MillauAsTargetHeaderChain::verify_message(&message), Ok(())); let message = vec![42; (maximal_message_size + 1) as _]; - assert!(Millau::verify_message(&message).is_err()); + assert!(MillauAsTargetHeaderChain::verify_message(&message).is_err()); } #[test] From 0d4ab2abaae7e751f11d1f5778d9e675415d30e1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 20 Jan 2023 12:14:20 +0300 Subject: [PATCH 0884/1210] No wildcard patterns in Cargo.toml (#1789) * dependabot doesn't support wildcard patterns in cargo.toml and we want dependabot * spelling for "fresh" crates * and fmt * spelling again --- bin/runtime-common/src/integrity.rs | 4 ++-- bin/runtime-common/src/messages.rs | 6 +++--- bin/runtime-common/src/mock.rs | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 45387b5a16839..11c6cb90a8361 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -101,8 +101,8 @@ macro_rules! assert_bridge_messages_pallet_types( /// Macro that combines four other macro calls - `assert_chain_types`, `assert_bridge_types`, /// `assert_bridge_grandpa_pallet_types` and `assert_bridge_messages_pallet_types`. It may be used -/// at the chain that is implemeting complete standard messages bridge (i.e. with bridge GRANDPA and -/// messages pallets deployed). +/// at the chain that is implementing complete standard messages bridge (i.e. with bridge GRANDPA +/// and messages pallets deployed). #[macro_export] macro_rules! assert_complete_bridge_types( ( diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 0d38e4b0d2504..8c97198393def 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -163,13 +163,13 @@ pub mod source { #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); - /// The error message returned from LaneMessageVerifier when outbound lane is disabled. + /// The error message returned from `LaneMessageVerifier` when outbound lane is disabled. pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = "The outbound message lane has rejected the message."; - /// The error message returned from LaneMessageVerifier when too many pending messages at the + /// The error message returned from `LaneMessageVerifier` when too many pending messages at the /// lane. pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; - /// The error message returned from LaneMessageVerifier when call origin is mismatch. + /// The error message returned from `LaneMessageVerifier` when call origin is mismatch. pub const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; impl LaneMessageVerifier>, FromThisChainMessagePayload> diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index d4b177510bf3a..51b03447c6383 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -245,8 +245,8 @@ impl pallet_bridge_relayers::Config for TestRuntime { type WeightInfo = (); } -/// Bridge that is deployed on ThisChain and allows sending/receiving messages to/from -/// BridgedChain. +/// Bridge that is deployed on `ThisChain` and allows sending/receiving messages to/from +/// `BridgedChain`. #[derive(Debug, PartialEq, Eq)] pub struct OnThisChainBridge; @@ -260,8 +260,8 @@ impl MessageBridge for OnThisChainBridge { type BridgedHeaderChain = pallet_bridge_grandpa::GrandpaChainHeaders; } -/// Bridge that is deployed on BridgedChain and allows sending/receiving messages to/from -/// ThisChain; +/// Bridge that is deployed on `BridgedChain` and allows sending/receiving messages to/from +/// `ThisChain`. #[derive(Debug, PartialEq, Eq)] pub struct OnBridgedChainBridge; From 3eddbd65f4ae4940ad7bb2b7a2b8f1c13c724745 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:25:38 +0000 Subject: [PATCH 0885/1210] Bump clap from 4.1.0 to 4.1.1 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 08661951eed68..508f5714a582a 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.0.9", features = ["derive"] } +clap = { version = "4.1.1", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.79" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 7b81de4fd3ac3..a693129109118 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.0.9", features = ["derive"] } +clap = { version = "4.1.1", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index aec1870efd8dc..5c93a93e0a767 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.0.9", features = ["derive"] } +clap = { version = "4.1.1", features = ["derive"] } serde_json = "1.0.79" # Bridge dependencies From 6c09c10f260d70c7e2421c3054f6e1537e36c596 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:26:14 +0000 Subject: [PATCH 0886/1210] Bump tokio from 1.24.1 to 1.24.2 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.24.1 to 1.24.2. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/commits) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 229de0cc09d2f..a16de01713ba6 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.17" num-traits = "0.2" rand = "0.7" scale-info = { version = "2.1.1", features = ["derive"] } -tokio = { version = "1.8", features = ["rt-multi-thread"] } +tokio = { version = "1.24", features = ["rt-multi-thread"] } thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 09cec37090069..5a1e50590254d 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.15" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.8", features = ["rt"] } +tokio = { version = "1.24", features = ["rt"] } thiserror = "1.0.26" # Bridge dependencies From 14931cc6fe599294e598c29bb8e2d1aea63f34e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:26:46 +0000 Subject: [PATCH 0887/1210] Bump strum from 0.21.0 to 0.24.1 Bumps [strum](https://github.com/Peternator7/strum) from 0.21.0 to 0.24.1. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 4be812be86aef..050be02e37eaf 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -19,7 +19,7 @@ rbtag = "0.3" structopt = "0.3" signal-hook = "0.3.14" signal-hook-async-std = "0.2.2" -strum = { version = "0.21.0", features = ["derive"] } +strum = { version = "0.24.1", features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } From c673f2bf010dcc3ca8ac98570762d9210e9740ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:27:20 +0000 Subject: [PATCH 0888/1210] Bump backoff from 0.2.1 to 0.4.0 Bumps [backoff](https://github.com/ihrwein/backoff) from 0.2.1 to 0.4.0. - [Release notes](https://github.com/ihrwein/backoff/releases) - [Commits](https://github.com/ihrwein/backoff/compare/v0.2.1...v0.4.0) --- updated-dependencies: - dependency-name: backoff dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/finality/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index ae4be5b5524d5..f25babee7d8a2 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -9,7 +9,7 @@ description = "Finality proofs relay" [dependencies] async-std = "1.6.5" async-trait = "0.1" -backoff = "0.2" +backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.5" log = "0.4.17" diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 5a1e50590254d..d52901df3c36f 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -10,7 +10,7 @@ ansi_term = "0.12" anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1" -backoff = "0.2" +backoff = "0.4" isahc = "1.2" env_logger = "0.8.2" futures = "0.3.5" From 582aa9eb824adfcf8c032d03a86e4c788f3d784f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:27:55 +0000 Subject: [PATCH 0889/1210] Bump parking_lot from 0.11.2 to 0.12.1 Bumps [parking_lot](https://github.com/Amanieu/parking_lot) from 0.11.2 to 0.12.1. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/0.11.2...0.12.1) --- updated-dependencies: - dependency-name: parking_lot dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/finality/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index f25babee7d8a2..401a02b2ca14f 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -17,4 +17,4 @@ num-traits = "0.2" relay-utils = { path = "../utils" } [dev-dependencies] -parking_lot = "0.11.0" +parking_lot = "0.12.1" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index e144926376c57..e4564dac15f29 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -12,7 +12,7 @@ futures = "0.3.5" hex = "0.4" log = "0.4.17" num-traits = "0.2" -parking_lot = "0.11.0" +parking_lot = "0.12.1" # Bridge Dependencies From 3e758d89e3921ff7687461c9d75395c183427732 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:28:21 +0000 Subject: [PATCH 0890/1210] Bump jsonpath_lib from 0.2.6 to 0.3.0 Bumps [jsonpath_lib](https://github.com/freestrings/jsonpath) from 0.2.6 to 0.3.0. - [Release notes](https://github.com/freestrings/jsonpath/releases) - [Commits](https://github.com/freestrings/jsonpath/compare/v0.2.6...0.3.0) --- updated-dependencies: - dependency-name: jsonpath_lib dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index d52901df3c36f..debdbb5ee08c0 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -14,7 +14,7 @@ backoff = "0.4" isahc = "1.2" env_logger = "0.8.2" futures = "0.3.5" -jsonpath_lib = "0.2" +jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" serde_json = "1.0" From 2b02958de33255652998aca85707370ddc1f52de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:31:43 +0000 Subject: [PATCH 0891/1210] Bump impl-serde from 0.3.2 to 0.4.0 Bumps [impl-serde](https://github.com/paritytech/parity-common) from 0.3.2 to 0.4.0. - [Release notes](https://github.com/paritytech/parity-common/releases) - [Commits](https://github.com/paritytech/parity-common/compare/impl-serde-v0.3.2...impl-serde-v0.4.0) --- updated-dependencies: - dependency-name: impl-serde dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/chain-millau/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index b422e1545d670..c58800b63c910 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -16,7 +16,7 @@ bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.7.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } -impl-serde = { version = "0.3.1", optional = true } +impl-serde = { version = "0.4.0", optional = true } parity-util-mem = { version = "0.12", default-features = false, features = ["primitive-types"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } From 3bea84efa3abacca6e09b8f2e4e9309e2d8e75ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:29:08 +0000 Subject: [PATCH 0892/1210] Bump fixed-hash from 0.7.0 to 0.8.0 Bumps [fixed-hash](https://github.com/paritytech/parity-common) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/paritytech/parity-common/releases) - [Commits](https://github.com/paritytech/parity-common/compare/fixed-hash-v0.7.0...fixed-hash-v0.8.0) --- updated-dependencies: - dependency-name: fixed-hash dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/chain-millau/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index c58800b63c910..abcbd0f512332 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -13,7 +13,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-beefy = { path = "../beefy", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } -fixed-hash = { version = "0.7.0", default-features = false } +fixed-hash = { version = "0.8.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", optional = true } From f0f3c6afbcc444335ae55bc1b703b95601c64e5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:31:04 +0000 Subject: [PATCH 0893/1210] Bump async-trait from 0.1.61 to 0.1.62 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.61 to 0.1.62. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.61...0.1.62) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 2af091c7ebb63..1909630a6fb88 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.40" +async-trait = "0.1.62" futures = "0.3.5" log = "0.4.17" relay-utils = { path = "../utils" } From f7af3b649b13e7a4daec0218e7b5790da52b6ec0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:55:18 +0000 Subject: [PATCH 0894/1210] Bump env_logger from 0.8.4 to 0.10.0 Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.8.4 to 0.10.0. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.8.4...v0.10.0) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 0e5868f845e78..07e3e135aca4b 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -71,7 +71,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "maste [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } -env_logger = "0.8" +env_logger = "0.10" static_assertions = "1.1" [build-dependencies] diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index b4d387e3829b1..d5d018fb86414 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -69,7 +69,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "maste [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } -env_logger = "0.8" +env_logger = "0.10" static_assertions = "1.1" [build-dependencies] diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index debdbb5ee08c0..a3e24b4a6e934 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -12,7 +12,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" isahc = "1.2" -env_logger = "0.8.2" +env_logger = "0.10.0" futures = "0.3.5" jsonpath_lib = "0.3" log = "0.4.17" From 9fdfb9333f95490af62bf833cdca66acf93adac5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 09:28:29 +0000 Subject: [PATCH 0895/1210] Bump sysinfo from 0.15.9 to 0.27.7 Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.15.9 to 0.27.7. - [Release notes](https://github.com/GuillaumeGomez/sysinfo/releases) - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/commits) --- updated-dependencies: - dependency-name: sysinfo dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index a3e24b4a6e934..0ad6168bb8457 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -18,7 +18,7 @@ jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" serde_json = "1.0" -sysinfo = "0.15" +sysinfo = "0.27" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.24", features = ["rt"] } thiserror = "1.0.26" From 957f8bb094e02e5c6ed9dd3ebacc92b90f7609bc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 20 Jan 2023 13:09:15 +0300 Subject: [PATCH 0896/1210] fix compilation --- relays/utils/src/metrics/global.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs index df90a2c482347..f7d3e25c96479 100644 --- a/relays/utils/src/metrics/global.rs +++ b/relays/utils/src/metrics/global.rs @@ -73,7 +73,7 @@ impl StandaloneMetric for GlobalMetrics { async fn update(&self) { // update system-wide metrics let mut system = self.system.lock().await; - let load = system.get_load_average(); + let load = system.load_average(); self.system_average_load.with_label_values(&["1min"]).set(load.one); self.system_average_load.with_label_values(&["5min"]).set(load.five); self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); @@ -85,7 +85,7 @@ impl StandaloneMetric for GlobalMetrics { qed", ); let is_process_refreshed = system.refresh_process(pid); - match (is_process_refreshed, system.get_process(pid)) { + match (is_process_refreshed, system.process(pid)) { (true, Some(process_info)) => { let cpu_usage = process_info.cpu_usage() as f64; let memory_usage = process_info.memory() * 1024; From 4866d041636d132dae22f6cc6abc4b5d620542d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 10:41:46 +0200 Subject: [PATCH 0897/1210] Bump async-trait from 0.1.62 to 0.1.63 (#1811) Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.62 to 0.1.63. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.62...0.1.63) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 1909630a6fb88..a6e74ecb581c1 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.62" +async-trait = "0.1.63" futures = "0.3.5" log = "0.4.17" relay-utils = { path = "../utils" } From 9d6ee2b126a4ad9bc36b05bd1af13660bbf3879f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 24 Jan 2023 12:33:57 +0200 Subject: [PATCH 0898/1210] Update bundled runtime version for bridge hub r/wococo (#1814) --- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/chains/wococo.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 633c7cfb29082..ab3de4dbb6bd4 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,5 +27,5 @@ impl CliChain for Rococo { impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9302, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9370, transaction_version: 1 }); } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 66a72e1113404..68d5e56554471 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -27,5 +27,5 @@ impl CliChain for Wococo { impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9302, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9370, transaction_version: 1 }); } From d7406ac3d07bb97aec5b19ea41cbb1d502f60889 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 15:01:10 +0000 Subject: [PATCH 0899/1210] Bump clap from 4.1.1 to 4.1.3 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.1 to 4.1.3. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.1.1...v4.1.3) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 508f5714a582a..6fad92ef59236 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.1", features = ["derive"] } +clap = { version = "4.1.3", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.79" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index a693129109118..c3441512721a9 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.1.1", features = ["derive"] } +clap = { version = "4.1.3", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 5c93a93e0a767..588e09851d6ea 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.1", features = ["derive"] } +clap = { version = "4.1.3", features = ["derive"] } serde_json = "1.0.79" # Bridge dependencies From 1a376db5e890848742badb65dc8fe639a891bca2 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 25 Jan 2023 10:24:02 +0200 Subject: [PATCH 0900/1210] Remove InboundPayload check (#1816) --- bin/runtime-common/src/integrity.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 11c6cb90a8361..51fb50df7e104 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -90,7 +90,6 @@ macro_rules! assert_bridge_messages_pallet_types( assert_type_eq_all!(<$r as MessagesConfig<$i>>::OutboundPayload, FromThisChainMessagePayload); - assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundPayload, FromBridgedChainMessagePayload>>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::InboundRelayer, AccountIdOf>); assert_type_eq_all!(<$r as MessagesConfig<$i>>::TargetHeaderChain, TargetHeaderChainAdapter<$bridge>); From ed8b1b12be56129021b937e0c33cd9fec192b8e9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 Jan 2023 15:55:42 +0300 Subject: [PATCH 0901/1210] Functions to benchmark messages pallet with linked to parachain (#1817) * functions to benchmark messages pallet with linked to parachain * unused imports * fmt --- bin/millau/runtime/src/lib.rs | 6 +- bin/runtime-common/Cargo.toml | 1 + .../src/messages_benchmarking.rs | 201 ++++++++++++++---- modules/parachains/src/lib.rs | 26 +++ 4 files changed, 186 insertions(+), 48 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 5aba458216d29..b0dc28cf27ed8 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -983,7 +983,7 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof, prepare_message_proof}; + use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_grandpa_chain, prepare_message_proof_from_grandpa_chain}; use pallet_bridge_messages::benchmarking::{ Pallet as MessagesBench, Config as MessagesConfig, @@ -1004,7 +1004,7 @@ impl_runtime_apis! { fn prepare_message_proof( params: MessageProofParams, ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { - prepare_message_proof::( + prepare_message_proof_from_grandpa_chain::( params, ) } @@ -1012,7 +1012,7 @@ impl_runtime_apis! { fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> rialto_messages::ToRialtoMessagesDeliveryProof { - prepare_message_delivery_proof::( + prepare_message_delivery_proof_from_grandpa_chain::( params, ) } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 9e8e6b29db226..7d53867164617 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -82,6 +82,7 @@ std = [ runtime-benchmarks = [ "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] integrity-test = [ diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index afe95422d185f..e7ca26d952ea8 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -22,7 +22,7 @@ use crate::{ messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - AccountIdOf, BalanceOf, BridgedChain, CallOf, HashOf, MessageBridge, ThisChain, + AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof, ThisChain, }, messages_generation::{ encode_all_messages, encode_lane_data, grow_trie, prepare_messages_storage_proof, @@ -30,52 +30,46 @@ use crate::{ }; use bp_messages::storage_keys; -use bp_runtime::{record_all_trie_keys, StorageProofSize}; +use bp_polkadot_core::parachains::ParaHash; +use bp_runtime::{record_all_trie_keys, Chain, Parachain, StorageProofSize, UnderlyingChainOf}; use codec::Encode; -use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; +use frame_support::weights::Weight; use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; -use sp_core::Hasher; -use sp_runtime::traits::{Header, MaybeSerializeDeserialize, Zero}; -use sp_std::{fmt::Debug, prelude::*}; +use sp_runtime::traits::{Header, Zero}; +use sp_std::prelude::*; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; /// Prepare proof of messages for the `receive_messages_proof` call. /// /// In addition to returning valid messages proof, environment is prepared to verify this message /// proof. -pub fn prepare_message_proof( +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses GRANDPA finality. For parachains, please use the `prepare_message_proof_from_parachain` +/// function. +pub fn prepare_message_proof_from_grandpa_chain( params: MessageProofParams, ) -> (FromBridgedChainMessagesProof>>, Weight) where - R: frame_system::Config>> - + pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain>, Header = BH>, - B: MessageBridge, - BI: 'static, + R: pallet_bridge_grandpa::Config>>, FI: 'static, - BH: Header>>, - BHH: Hasher>>, - AccountIdOf>: PartialEq + sp_std::fmt::Debug, - AccountIdOf>: From<[u8; 32]>, - BalanceOf>: Debug + MaybeSerializeDeserialize, - CallOf>: From> + GetDispatchInfo, - HashOf>: Copy + Default, + B: MessageBridge, { - let message_payload = match params.size { - StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }; - - // finally - prepare storage proof and update environment + // prepare storage proof let (state_root, storage_proof) = prepare_messages_storage_proof::( params.lane, params.message_nonces.clone(), params.outbound_lane_data, params.size, - message_payload, + match params.size { + StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }, encode_all_messages, encode_lane_data, ); + + // update runtime storage let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); ( @@ -90,18 +84,115 @@ where ) } +/// Prepare proof of messages for the `receive_messages_proof` call. +/// +/// In addition to returning valid messages proof, environment is prepared to verify this message +/// proof. +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses parachain finality. For GRANDPA chains, please use the +/// `prepare_message_proof_from_grandpa_chain` function. +pub fn prepare_message_proof_from_parachain( + params: MessageProofParams, +) -> (FromBridgedChainMessagesProof>>, Weight) +where + R: pallet_bridge_parachains::Config, + PI: 'static, + B: MessageBridge, + UnderlyingChainOf>: Chain + Parachain, +{ + // prepare storage proof + let (state_root, storage_proof) = prepare_messages_storage_proof::( + params.lane, + params.message_nonces.clone(), + params.outbound_lane_data, + params.size, + match params.size { + StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], + _ => vec![], + }, + encode_all_messages, + encode_lane_data, + ); + + // update runtime storage + let (_, bridged_header_hash) = + insert_header_to_parachains_pallet::>>(state_root); + + ( + FromBridgedChainMessagesProof { + bridged_header_hash, + storage_proof, + lane: params.lane, + nonces_start: *params.message_nonces.start(), + nonces_end: *params.message_nonces.end(), + }, + Weight::zero(), + ) +} + /// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. -pub fn prepare_message_delivery_proof( +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses GRANDPA finality. For parachains, please use the +/// `prepare_message_delivery_proof_from_parachain` function. +pub fn prepare_message_delivery_proof_from_grandpa_chain( params: MessageDeliveryProofParams>>, ) -> FromBridgedChainMessagesDeliveryProof>> where - R: pallet_bridge_grandpa::Config, - R::BridgedChain: bp_runtime::Chain>, Header = BH>, + R: pallet_bridge_grandpa::Config>>, FI: 'static, B: MessageBridge, - BH: Header>>, - BHH: Hasher>>, - HashOf>: Copy + Default, +{ + // prepare storage proof + let lane = params.lane; + let (state_root, storage_proof) = prepare_message_delivery_proof::(params); + + // update runtime storage + let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); + + FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: bridged_header_hash.into(), + storage_proof, + lane, + } +} + +/// Prepare proof of messages delivery for the `receive_messages_delivery_proof` call. +/// +/// This method is intended to be used when benchmarking pallet, linked to the chain that +/// uses parachain finality. For GRANDPA chains, please use the +/// `prepare_message_delivery_proof_from_grandpa_chain` function. +pub fn prepare_message_delivery_proof_from_parachain( + params: MessageDeliveryProofParams>>, +) -> FromBridgedChainMessagesDeliveryProof>> +where + R: pallet_bridge_parachains::Config, + PI: 'static, + B: MessageBridge, + UnderlyingChainOf>: Chain + Parachain, +{ + // prepare storage proof + let lane = params.lane; + let (state_root, storage_proof) = prepare_message_delivery_proof::(params); + + // update runtime storage + let (_, bridged_header_hash) = + insert_header_to_parachains_pallet::>>(state_root); + + FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: bridged_header_hash.into(), + storage_proof, + lane, + } +} + +/// Prepare in-memory message delivery proof, without inserting anything to the runtime storage. +fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams>>, +) -> (HashOf>, RawStorageProof) +where + B: MessageBridge, { // prepare Bridged chain storage with inbound lane state let storage_key = @@ -109,7 +200,8 @@ where let mut root = Default::default(); let mut mdb = MemoryDB::default(); { - let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); + let mut trie = + TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); @@ -117,20 +209,17 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); + let mut proof_recorder = Recorder::>>>::new(); + record_all_trie_keys::>>, _>( + &mdb, + &root, + &mut proof_recorder, + ) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); - // finally insert header with given state root to our storage - let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(root); - - FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: bridged_header_hash.into(), - storage_proof, - lane: params.lane, - } + (root, storage_proof) } /// Insert header to the bridge GRANDPA pallet. @@ -154,3 +243,25 @@ where pallet_bridge_grandpa::initialize_for_benchmarks::(bridged_header); (bridged_block_number, bridged_header_hash) } + +/// Insert header to the bridge parachains pallet. +pub(crate) fn insert_header_to_parachains_pallet( + state_root: bp_runtime::HashOf, +) -> (bp_runtime::BlockNumberOf, bp_runtime::HashOf) +where + R: pallet_bridge_parachains::Config, + PI: 'static, + PC: Chain + Parachain, +{ + let bridged_block_number = Zero::zero(); + let bridged_header = bp_runtime::HeaderOf::::new( + bridged_block_number, + Default::default(), + state_root, + Default::default(), + Default::default(), + ); + let bridged_header_hash = bridged_header.hash(); + pallet_bridge_parachains::initialize_for_benchmarks::(bridged_header); + (bridged_block_number, bridged_header_hash) +} diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 47ab91928c7b7..06a1f82e7b0b1 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -33,6 +33,13 @@ use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain, StorageProofErr use frame_support::dispatch::PostDispatchInfo; use sp_std::{marker::PhantomData, vec::Vec}; +#[cfg(feature = "runtime-benchmarks")] +use bp_parachains::ParaStoredHeaderDataBuilder; +#[cfg(feature = "runtime-benchmarks")] +use bp_runtime::HeaderOf; +#[cfg(feature = "runtime-benchmarks")] +use codec::Encode; + // Re-export in crate namespace for `construct_runtime!`. pub use pallet::*; @@ -654,6 +661,25 @@ impl, I: 'static, C: Parachain> HeaderChain } } +/// (Re)initialize pallet with given header for using it in `pallet-bridge-messages` benchmarks. +#[cfg(feature = "runtime-benchmarks")] +pub fn initialize_for_benchmarks, I: 'static, PC: Parachain>( + header: HeaderOf, +) { + let parachain = ParaId(PC::PARACHAIN_ID); + let parachain_head = ParaHead(header.encode()); + let updated_head_data = T::ParaStoredHeaderDataBuilder::try_build(parachain, ¶chain_head) + .expect("failed to build stored parachain head in benchmarks"); + Pallet::::update_parachain_head( + parachain, + None, + 0, + updated_head_data, + parachain_head.hash(), + ) + .expect("failed to insert parachain head in benchmarks"); +} + #[cfg(test)] mod tests { use super::*; From 21b85a5817dfe7b5099710d627353e7637312343 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 25 Jan 2023 17:43:19 +0300 Subject: [PATCH 0902/1210] do not call best_finalized_para_block_at_source for ancient block (#1819) --- .../src/on_demand/parachains.rs | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 6be3fcb9886e0..c36eef998238f 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -674,26 +674,29 @@ where required_parachain_header.unique_saturated_into(), ))?; + // we don't require source node to be archive, so we can't craft storage proofs using + // ancient headers. So if the `best_finalized_relay_block_at_target` is too ancient, we + // can't craft storage proofs using it + let may_use_state_at_best_finalized_relay_block_at_target = + best_finalized_relay_block_at_source + .number() + .saturating_sub(best_finalized_relay_block_at_target.number()) <= + RBN::from(ANCIENT_BLOCK_THRESHOLD); + // now let's check if `required_header` may be proved using // `best_finalized_relay_block_at_target` - let selection = env - .best_finalized_para_block_at_source(best_finalized_relay_block_at_target) - .await? - .filter(|best_finalized_para_block_at_target| { - best_finalized_para_block_at_target.number() >= required_parachain_header - }) - .map(|best_finalized_para_block_at_target| { - (false, best_finalized_relay_block_at_target, best_finalized_para_block_at_target) - }) - // we don't require source node to be archive, so we can't craft storage proofs using - // ancient headers. So if the `best_finalized_relay_block_at_target` is too ancient, we - // can't craft storage proofs using it - .filter(|(_, selected_relay_block, _)| { - let difference = best_finalized_relay_block_at_source - .number() - .saturating_sub(selected_relay_block.number()); - difference <= RBN::from(ANCIENT_BLOCK_THRESHOLD) - }); + let selection = if may_use_state_at_best_finalized_relay_block_at_target { + env.best_finalized_para_block_at_source(best_finalized_relay_block_at_target) + .await? + .filter(|best_finalized_para_block_at_target| { + best_finalized_para_block_at_target.number() >= required_parachain_header + }) + .map(|best_finalized_para_block_at_target| { + (false, best_finalized_relay_block_at_target, best_finalized_para_block_at_target) + }) + } else { + None + }; Ok(selection.unwrap_or(( true, From 9e797613b4ceb2fc63f9c398dcb15a0cc15b05e0 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Jan 2023 13:11:40 +0200 Subject: [PATCH 0903/1210] docs: fix broken link and minor nits (#1821) --- modules/messages/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/messages/README.md b/modules/messages/README.md index 0d1ea7fe44a0f..1cca1151c6e3c 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -43,10 +43,10 @@ Instead, it provides runtime-internal method that allows other pallets (or other outbound messages. The message "appears" when some runtime code calls the `send_message()` method of the pallet. -The submitter specifies the lane that he's willing to use and the message itself. If some fee must be -paid for sending the message, it must be paid outside of the pallet. If a message passes all checks -(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and the -message is stored in the module storage. The message is in an "undelivered" state now. +The submitter specifies the lane that they're willing to use and the message itself. If some fee must +be paid for sending the message, it must be paid outside of the pallet. If a message passes all checks +(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and +the message is stored in the module storage. The message is in an "undelivered" state now. We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to both target and source chains. The pallet itself has no assumptions about @@ -57,17 +57,17 @@ for details. Eventually, some relayer would notice this message in the "undelivered" state and it would decide to deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery transaction) for the messages module instance, deployed at the target chain. Relayer provides -his account id at the source chain, the proof of message (or several messages), the number of +its account id at the source chain, the proof of message (or several messages), the number of messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the message is considered "delivered". Once a message is delivered, the relayer may want to confirm delivery back to the source chain. -There are two reasons why he would want to do that. The first is that we intentionally limit number +There are two reasons why it would want to do that. The first is that we intentionally limit number of "delivered", but not yet "confirmed" messages at inbound lanes (see [What about other Constants in the Messages Module Configuration Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). So at some point, the target chain may stop accepting new messages until relayers confirm some of -these. The second is that if the relayer wants to be rewarded for delivery, he must prove the fact -that he has actually delivered the message. And this proof may only be generated after the delivery +these. The second is that if the relayer wants to be rewarded for delivery, it must prove the fact +that it has actually delivered the message. And this proof may only be generated after the delivery transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka confirmation transaction) for the messages module instance, deployed at the source chain. Once this transaction is mined, the message is considered "confirmed". @@ -84,8 +84,8 @@ relayer sometimes includes a nonce of the latest "confirmed" message in the next As it has been said above, the messages module supports both outbound and inbound message lanes. So if we will integrate a module in some runtime, it may act as the source chain runtime for outbound messages and as the target chain runtime for inbound messages. In this section, we'll -sometimes refer to the chain we're currently integrating with, as this chain and the other chain as -bridged chain. +sometimes refer to the chain we're currently integrating with, as "this chain" and the other +chain as "bridged chain". Messages module doesn't simply accept transactions that are claiming that the bridged chain has some updated data for us. Instead of this, the module assumes that the bridged chain is able to @@ -96,7 +96,7 @@ transaction proofs, Substrate header digests or anything else that may be proved **IMPORTANT NOTE**: everything below in this chapter describes details of the messages module configuration. But if you interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at the -[bridge-runtime-common](../../bin/runtime-common/README.md) crate. This crate is providing a lot of +[bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of helpers for integration, which may be directly used from within your runtime. Then if you'll decide to change something in this scheme, get back here for detailed information. From 8acefc529b1c0307d8977e0ef46f56c34eea1ac4 Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Fri, 27 Jan 2023 12:21:40 +0100 Subject: [PATCH 0904/1210] Fix: typos (#1822) * Fix: typos Fix: typos * Fix: typos Fix: typos * Fix: typo Fix: typo * Fix: typos Fix: typos * Fix: typos Fix: typos --- docs/high-level-overview.md | 4 ++-- docs/polkadot-kusama-bridge-overview.md | 6 +++--- modules/messages/README.md | 6 +++--- relays/finality/README.md | 10 +++++----- relays/parachains/README.md | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index f280671925612..449224124afd7 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -35,7 +35,7 @@ about the source chain headers which have been finalized. This is useful for hig The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), generated by the current authorities set. The GRANDPA protocol itself requires current authorities set to -generate explicit justificaion for the header that enacts next authorities set. Such headers and their finality +generate explicit justification for the header that enacts next authorities set. Such headers and their finality proofs are called mandatory in the pallet and relayer pays no fee for such headers submission. The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers @@ -123,7 +123,7 @@ The relay connects to the source _relay_ chain and the target chain nodes. It do tracked parachain nodes. The relay looks at the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at -the taget chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** +the target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** until header `B` or one of its ancestors appears at the target chain. Once it is available, the storage proof of the map entry is generated and is submitted to the target chain. diff --git a/docs/polkadot-kusama-bridge-overview.md b/docs/polkadot-kusama-bridge-overview.md index 302196718b982..9f407b6ba00a3 100644 --- a/docs/polkadot-kusama-bridge-overview.md +++ b/docs/polkadot-kusama-bridge-overview.md @@ -21,8 +21,8 @@ The runtime will have minimal set of non-bridge pallets, so there's not much you ## Connecting Parachains You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need -to use other parachains transactions, which will use HRMP to deliver message to the Bridge Hub. The Bridge Hub will -just queue this messages in its outbound lane, which is dedicated to deliver messages between two parachains. +to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will +just queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. Our first planned bridge will connect the Polkadot' Statemint and Kusama' Statemine. Bridge between those two parachains would allow Statemint accounts to hold wrapped KSM tokens and Statemine accounts to hold wrapped DOT @@ -107,7 +107,7 @@ is not used to cover rewards of bridging with some other Polkadot Parachain. Our goal is to incentivize running honest relayers. But we have no relayers sets, so at any time anyone may submit message delivery transaction, hoping that the cost of this transaction will be compensated. So what if some message is currently queued and two relayers are submitting two identical message delivery transactions at once? Without any -special means, the cost of first included transacton will be compensated and the cost of the other one won't. A honest, +special means, the cost of first included transaction will be compensated and the cost of the other one won't. A honest, but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which may be used by other useful transactions. diff --git a/modules/messages/README.md b/modules/messages/README.md index 1cca1151c6e3c..b717db6ad6285 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -94,7 +94,7 @@ In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other b transaction proofs, Substrate header digests or anything else that may be proved. **IMPORTANT NOTE**: everything below in this chapter describes details of the messages module -configuration. But if you interested in well-probed and relatively easy integration of two +configuration. But if you're interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at the [bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of helpers for integration, which may be directly used from within your runtime. Then if you'll decide @@ -153,7 +153,7 @@ The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPaymen transaction is received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its [`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible -implementation. It allows you to pay fixed reward for relaying the message and some its portion +implementation. It allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery. ### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? @@ -183,7 +183,7 @@ implements all required traits and will simply reject all transactions, related ### What about other Constants in the Messages Module Configuration Trait? -Two setttings that are used to check messages in the `send_message()` function. The +Two settings that are used to check messages in the `send_message()` function. The `pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that may be used to send messages. All messages sent using other lanes are rejected. All messages that have size above `pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected. diff --git a/relays/finality/README.md b/relays/finality/README.md index edfd00192bc87..effc3db6b12b8 100644 --- a/relays/finality/README.md +++ b/relays/finality/README.md @@ -19,11 +19,11 @@ More: [GRANDPA Finality Relay Sequence Diagram](../../docs/grandpa-finality-rela ## How to Use the Finality Relay The most important trait is the [`FinalitySyncPipeline`](./src/lib.rs), which defines the basic primitives of the -source chain (like block hash and number) and the type of finality proof (GRANDPA jusitfication or MMR proof). Once +source chain (like block hash and number) and the type of finality proof (GRANDPA justification or MMR proof). Once that is defined, there are two other traits - [`SourceClient`](./src/finality_loop.rs) and [`TarggetClient`](./src/finality_loop.rs). -The `SourceClient` represents the Substrate node client that connects to the source chain. The client need to +The `SourceClient` represents the Substrate node client that connects to the source chain. The client needs to be able to return the best finalized header number, finalized header and its finality proof and the stream of finality proofs. @@ -31,8 +31,8 @@ The `TargetClient` implementation must be able to craft finality delivery transa node. The transaction is then tracked by the relay until it is mined and finalized. The main entrypoint for the crate is the [`run` function](./src/finality_loop.rs), which takes source and target -clients and [`FinalitySyncParams`](./src/finality_loop.rs) parameters. The most imporant parameter is the -`only_mandatory_headers` - it it is set to `true`, the relay will only submit mandatory headers. Since transactions +clients and [`FinalitySyncParams`](./src/finality_loop.rs) parameters. The most important parameter is the +`only_mandatory_headers` - it is set to `true`, the relay will only submit mandatory headers. Since transactions with mandatory headers are fee-free, the cost of running such relay is zero (in terms of fees). ## Finality Relay Metrics @@ -55,4 +55,4 @@ change chain names. So the metrics are: breaks) this shall not happen and the metric will have `0` value. If relay operates properly, you should see that the `Rialto_to_Millau_Sync_best_source_at_target_block_number` -tries to reach the `Rialto_to_Millau_Sync_best_source_block_number`. And the latter one always increases. \ No newline at end of file +tries to reach the `Rialto_to_Millau_Sync_best_source_block_number`. And the latter one always increases. diff --git a/relays/parachains/README.md b/relays/parachains/README.md index 6cb68f2209f6a..9093dc617dc65 100644 --- a/relays/parachains/README.md +++ b/relays/parachains/README.md @@ -24,7 +24,7 @@ finality delivery transaction to the target node. The main entrypoint for the crate is the [`run` function](./src/parachains_loop.rs), which takes source and target clients and [`ParachainSyncParams`](./src/parachains_loop.rs) parameters. The most imporant parameter is the -`parachains` - it it the set of parachains, which relay tracks and updates. The other important parameter that +`parachains` - it is the set of parachains, which relay tracks and updates. The other important parameter that may affect the relay operational costs is the `strategy`. If it is set to `Any`, then the finality delivery transaction is submitted if at least one of tracked parachain heads is updated. The other option is `All`. Then the relay waits until all tracked parachain heads are updated and submits them all in a single finality delivery From a9985c0aa676f404ee441a28f59f0362d0705462 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 27 Jan 2023 14:13:25 +0200 Subject: [PATCH 0905/1210] Use named parameters for indirect calls (#1823) --- modules/grandpa/src/lib.rs | 7 +++++-- modules/messages/src/lib.rs | 20 +++++++++--------- modules/parachains/src/lib.rs | 7 +++++-- primitives/header-chain/src/lib.rs | 7 +++++-- primitives/messages/src/lib.rs | 12 +++++++++-- primitives/parachains/src/lib.rs | 10 ++++----- .../rococo_parachains_to_bridge_hub_wococo.rs | 6 +++--- .../wococo_parachains_to_bridge_hub_rococo.rs | 6 +++--- relays/bin-substrate/src/cli/init_bridge.rs | 15 ++++++++----- .../src/runtime_wrapper.rs | 2 +- .../lib-substrate-relay/src/finality/mod.rs | 7 ++++++- .../lib-substrate-relay/src/messages_lane.rs | 21 ++++++++++++------- 12 files changed, 77 insertions(+), 43 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index d3335693adfa7..3cf67349b474a 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -1178,7 +1178,7 @@ mod tests { let direct_initialize_call = Call::::initialize { init_data: init_data.clone() }; - let indirect_initialize_call = BridgeGrandpaCall::::initialize(init_data); + let indirect_initialize_call = BridgeGrandpaCall::::initialize { init_data }; assert_eq!(direct_initialize_call.encode(), indirect_initialize_call.encode()); let direct_submit_finality_proof_call = Call::::submit_finality_proof { @@ -1186,7 +1186,10 @@ mod tests { justification: justification.clone(), }; let indirect_submit_finality_proof_call = - BridgeGrandpaCall::::submit_finality_proof(Box::new(header), justification); + BridgeGrandpaCall::::submit_finality_proof { + finality_target: Box::new(header), + justification, + }; assert_eq!( direct_submit_finality_proof_call.encode(), indirect_submit_finality_proof_call.encode() diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 680518d9dc8b2..ec895955076c0 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1928,12 +1928,12 @@ mod tests { AccountId, TestMessagesProof, TestMessagesDeliveryProof, - >::receive_messages_proof( - account_id, - message_proof, - 1, - REGULAR_PAYLOAD.declared_weight, - ); + >::receive_messages_proof { + relayer_id_at_bridged_chain: account_id, + proof: message_proof, + messages_count: 1, + dispatch_weight: REGULAR_PAYLOAD.declared_weight, + }; assert_eq!( direct_receive_messages_proof_call.encode(), indirect_receive_messages_proof_call.encode() @@ -1948,10 +1948,10 @@ mod tests { AccountId, TestMessagesProof, TestMessagesDeliveryProof, - >::receive_messages_delivery_proof( - message_delivery_proof, - unrewarded_relayer_state, - ); + >::receive_messages_delivery_proof { + proof: message_delivery_proof, + relayers_state: unrewarded_relayer_state, + }; assert_eq!( direct_receive_messages_delivery_proof_call.encode(), indirect_receive_messages_delivery_proof_call.encode() diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 06a1f82e7b0b1..e2f2cbf2d499c 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -1513,8 +1513,11 @@ mod tests { parachains: parachains.clone(), parachain_heads_proof: proof.clone(), }; - let indirect_submit_parachain_heads_call = - BridgeParachainCall::submit_parachain_heads(relay_header_id, parachains, proof); + let indirect_submit_parachain_heads_call = BridgeParachainCall::submit_parachain_heads { + at_relay_block: relay_header_id, + parachains, + parachain_heads_proof: proof, + }; assert_eq!( direct_submit_parachain_heads_call.encode(), indirect_submit_parachain_heads_call.encode() diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index dffa7f7dc6e0e..14e9395c03c09 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -176,10 +176,13 @@ impl ConsensusLogReader for GrandpaConsensusLogReader { pub enum BridgeGrandpaCall { /// `pallet-bridge-grandpa::Call::submit_finality_proof` #[codec(index = 0)] - submit_finality_proof(Box
, justification::GrandpaJustification
), + submit_finality_proof { + finality_target: Box
, + justification: justification::GrandpaJustification
, + }, /// `pallet-bridge-grandpa::Call::initialize` #[codec(index = 1)] - initialize(InitializationData
), + initialize { init_data: InitializationData
}, } /// The `BridgeGrandpaCall` used by a chain. diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 61d475cb46c1b..754349d634eef 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -397,10 +397,18 @@ where pub enum BridgeMessagesCall { /// `pallet-bridge-messages::Call::receive_messages_proof` #[codec(index = 2)] - receive_messages_proof(AccountId, MessagesProof, u32, Weight), + receive_messages_proof { + relayer_id_at_bridged_chain: AccountId, + proof: MessagesProof, + messages_count: u32, + dispatch_weight: Weight, + }, /// `pallet-bridge-messages::Call::receive_messages_delivery_proof` #[codec(index = 3)] - receive_messages_delivery_proof(MessagesDeliveryProof, UnrewardedRelayersState), + receive_messages_delivery_proof { + proof: MessagesDeliveryProof, + relayers_state: UnrewardedRelayersState, + }, } #[cfg(test)] diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index 6b38d648d79d5..388a995fae6de 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -157,9 +157,9 @@ impl ParaStoredHeaderDataBuilder for C { pub enum BridgeParachainCall { /// `pallet-bridge-parachains::Call::submit_parachain_heads` #[codec(index = 0)] - submit_parachain_heads( - (RelayBlockNumber, RelayBlockHash), - Vec<(ParaId, ParaHash)>, - ParaHeadsProof, - ), + submit_parachain_heads { + at_relay_block: (RelayBlockNumber, RelayBlockHash), + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + }, } diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs index b028253d8a4f6..098aed417c662 100644 --- a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs @@ -51,11 +51,11 @@ impl SubmitParachainHeadsCallBuilder parachain_heads_proof: ParaHeadsProof, ) -> CallOf { relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoParachain( - relay_bridge_hub_wococo_client::runtime::BridgeParachainCall::submit_parachain_heads( - (at_relay_block.0, at_relay_block.1), + relay_bridge_hub_wococo_client::runtime::BridgeParachainCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, - ), + }, ) } } diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs index f79979ff8328b..683e7705dd6ac 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -51,11 +51,11 @@ impl SubmitParachainHeadsCallBuilder parachain_heads_proof: ParaHeadsProof, ) -> CallOf { relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoParachain( - bp_parachains::BridgeParachainCall::submit_parachain_heads( - (at_relay_block.0, at_relay_block.1), + bp_parachains::BridgeParachainCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, - ), + }, ) } } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 8f4080b338cee..3e9ddfdb94fd8 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -125,9 +125,10 @@ impl BridgeInitializer for MillauToRialtoParachainCliBridge { ) -> ::Call { use relay_rialto_parachain_client::runtime; - let initialize_call = runtime::Call::BridgeMillauGrandpa( - runtime::BridgeMillauGrandpaCall::initialize(init_data), - ); + let initialize_call = + runtime::Call::BridgeMillauGrandpa(runtime::BridgeMillauGrandpaCall::initialize { + init_data, + }); let sudo_call = SudoCall::sudo(Box::new(initialize_call)); runtime::Call::Sudo(sudo_call) } @@ -176,7 +177,9 @@ impl BridgeInitializer for RococoToBridgeHubWococoCliBridge { init_data: >::InitializationData, ) -> ::Call { relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa( - relay_bridge_hub_wococo_client::runtime::BridgeRococoGrandpaCall::initialize(init_data), + relay_bridge_hub_wococo_client::runtime::BridgeRococoGrandpaCall::initialize { + init_data, + }, ) } } @@ -188,7 +191,9 @@ impl BridgeInitializer for WococoToBridgeHubRococoCliBridge { init_data: >::InitializationData, ) -> ::Call { relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoGrandpa( - relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::initialize(init_data), + relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::initialize { + init_data, + }, ) } } diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 85f77a6377ef7..17cc4cbd4e8f8 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -96,7 +96,7 @@ mod tests { set_id: 6, operating_mode: BasicOperatingMode::Normal, }; - let call = BridgeRococoGrandpaCall::initialize(init_data); + let call = BridgeRococoGrandpaCall::initialize { init_data }; let tx = Call::BridgeRococoGrandpa(call); // encode call as hex string diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index 5d7b52cd1dec7..f529e20912a3e 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -156,7 +156,12 @@ macro_rules! generate_mocked_submit_finality_proof_call_builder { ) -> relay_substrate_client::CallOf< <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::TargetChain > { - $bridge_grandpa($submit_finality_proof(Box::new(header.into_inner()), proof)) + bp_runtime::paste::item! { + $bridge_grandpa($submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof + }) + } } } }; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 73d441cfcd381..a0cd9b4375656 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -335,12 +335,14 @@ macro_rules! generate_mocked_receive_message_proof_call_builder { ) -> relay_substrate_client::CallOf< <$pipeline as $crate::messages_lane::SubstrateMessageLane>::TargetChain > { - $bridge_messages($receive_messages_proof( - relayer_id_at_source, - proof.1, - messages_count, - dispatch_weight, - )) + bp_runtime::paste::item! { + $bridge_messages($receive_messages_proof { + relayer_id_at_bridged_chain: relayer_id_at_source, + proof: proof.1, + messages_count: messages_count, + dispatch_weight: dispatch_weight, + }) + } } } }; @@ -424,7 +426,12 @@ macro_rules! generate_mocked_receive_message_delivery_proof_call_builder { ) -> relay_substrate_client::CallOf< <$pipeline as $crate::messages_lane::SubstrateMessageLane>::SourceChain > { - $bridge_messages($receive_messages_delivery_proof(proof.1, proof.0)) + bp_runtime::paste::item! { + $bridge_messages($receive_messages_delivery_proof { + proof: proof.1, + relayers_state: proof.0 + }) + } } } }; From aa80a1e74724e29abf8e0af25038e3958da12f80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 02:13:14 +0000 Subject: [PATCH 0906/1210] Bump clap from 4.1.3 to 4.1.4 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.3 to 4.1.4. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.1.3...v4.1.4) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 6fad92ef59236..f2c0762d3d283 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.3", features = ["derive"] } +clap = { version = "4.1.4", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.79" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index c3441512721a9..5e1eba1fee55f 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.1.3", features = ["derive"] } +clap = { version = "4.1.4", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 588e09851d6ea..88c354f9c15db 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.3", features = ["derive"] } +clap = { version = "4.1.4", features = ["derive"] } serde_json = "1.0.79" # Bridge dependencies From c74d73be9ff392209595778289b2d1c04192e1af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 02:14:29 +0000 Subject: [PATCH 0907/1210] Bump tokio from 1.24.2 to 1.25.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.24.2 to 1.25.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/commits/tokio-1.25.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index a16de01713ba6..9b3a58f27c296 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.17" num-traits = "0.2" rand = "0.7" scale-info = { version = "2.1.1", features = ["derive"] } -tokio = { version = "1.24", features = ["rt-multi-thread"] } +tokio = { version = "1.25", features = ["rt-multi-thread"] } thiserror = "1.0.26" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 0ad6168bb8457..0909bfee7a9fa 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.27" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.24", features = ["rt"] } +tokio = { version = "1.25", features = ["rt"] } thiserror = "1.0.26" # Bridge dependencies From 2716336f569aed9999bf19f0d8707bb2f954bbd9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 Jan 2023 12:32:07 +0300 Subject: [PATCH 0908/1210] Reconnect source client (#1826) * reconnect source client * fix test --- relays/parachains/src/parachains_loop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 3ef9a7f7a731c..7b62e72ca2930 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -243,7 +243,7 @@ where P::SourceChain::NAME, e, ); - return Err(FailedClient::Target) + return Err(FailedClient::Source) }, } @@ -844,7 +844,7 @@ mod tests { None, futures::future::pending(), )), - Err(FailedClient::Target), + Err(FailedClient::Source), ); } From aa54d3e72762b6d0b80021d672e17233e4dea29f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 Jan 2023 12:34:52 +0300 Subject: [PATCH 0909/1210] Do not read parachain heads from ancient relay headers (#1827) * do not read parachain heads from ancient relay headers * revert test change --- relays/client-substrate/src/client.rs | 7 ++++- relays/client-substrate/src/lib.rs | 4 +-- .../src/on_demand/parachains.rs | 29 ++++++++++++------- .../src/parachains/source.rs | 11 ++++++- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 62d6a7c599e8c..1a4aeb583cd41 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -37,7 +37,7 @@ use jsonrpsee::{ core::DeserializeOwned, ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; -use num_traits::{Bounded, Zero}; +use num_traits::{Bounded, Saturating, Zero}; use pallet_balances::AccountData; use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT}; @@ -69,6 +69,11 @@ const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// half of this value. pub const ANCIENT_BLOCK_THRESHOLD: u32 = 128; +/// Returns `true` if we think that the state is already discarded for given block. +pub fn is_ancient_block + PartialOrd + Saturating>(block: N, best: N) -> bool { + best.saturating_sub(block) >= N::from(ANCIENT_BLOCK_THRESHOLD) +} + /// Opaque justifications subscription type. pub struct Subscription(pub(crate) Mutex>>); diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index ef75e30424625..c1a96c487c4b7 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -40,8 +40,8 @@ pub use crate::{ UnsignedTransaction, UtilityPallet, }, client::{ - ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, SimpleRuntimeVersion, - Subscription, ANCIENT_BLOCK_THRESHOLD, + is_ancient_block, ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, + SimpleRuntimeVersion, Subscription, ANCIENT_BLOCK_THRESHOLD, }, error::{Error, Result}, rpc::{SubstrateBeefyFinalityClient, SubstrateFinalityClient, SubstrateGrandpaFinalityClient}, diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index c36eef998238f..b6c30d56ee118 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -40,8 +40,8 @@ use parachains_relay::parachains_loop::{ AvailableHeader, ParachainSyncParams, SourceClient, TargetClient, }; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError, - HashOf, HeaderIdOf, ParachainBase, ANCIENT_BLOCK_THRESHOLD, + is_ancient_block, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, + Error as SubstrateError, HashOf, HeaderIdOf, ParachainBase, }; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, BlockNumberBase, FailedClient, @@ -501,10 +501,18 @@ where .await .map_err(map_target_err)?; - let para_header_at_relay_header_at_target = source - .on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into()) - .await - .map_err(map_source_err)?; + // if relay header at target is too old, then its state may already be discarded at the source + // => just use `None` in this case + let is_relay_header_at_target_ancient = + is_ancient_block(relay_header_at_target.number(), relay_header_at_source); + let para_header_at_relay_header_at_target = if is_relay_header_at_target_ancient { + None + } else { + source + .on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into()) + .await + .map_err(map_source_err)? + }; Ok(RelayData { required_para_header: required_header_number, @@ -677,11 +685,10 @@ where // we don't require source node to be archive, so we can't craft storage proofs using // ancient headers. So if the `best_finalized_relay_block_at_target` is too ancient, we // can't craft storage proofs using it - let may_use_state_at_best_finalized_relay_block_at_target = - best_finalized_relay_block_at_source - .number() - .saturating_sub(best_finalized_relay_block_at_target.number()) <= - RBN::from(ANCIENT_BLOCK_THRESHOLD); + let may_use_state_at_best_finalized_relay_block_at_target = !is_ancient_block( + best_finalized_relay_block_at_target.number(), + best_finalized_relay_block_at_source.number(), + ); // now let's check if `required_header` may be proved using // `best_finalized_relay_block_at_target` diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index afacd18e2927a..90776902dd6f9 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -29,7 +29,8 @@ use parachains_relay::{ parachains_loop_metrics::ParachainsLoopMetrics, }; use relay_substrate_client::{ - Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase, RelayChain, + is_ancient_block, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase, + RelayChain, }; use relay_utils::relay_loop::Client as RelayClient; @@ -115,6 +116,14 @@ where ))) } + // if requested relay header is ancient, then we don't even want to try to read the + // parachain head - we simply return `Unavailable` + let best_block_number = self.client.best_finalized_header_number().await?; + if is_ancient_block(at_block.number(), best_block_number) { + return Ok(AvailableHeader::Unavailable) + } + + // else - try to read head from the source client let mut para_head_id = AvailableHeader::Missing; if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block, para_id).await? { // Never return head that is larger than requested. This way we'll never sync From 33f6b17ceb8eaff67ffd711b6b615d3bb9f8e869 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 30 Jan 2023 16:10:00 +0300 Subject: [PATCH 0910/1210] Use specific error for case when para head is missing from the bridge pallet (#1829) * use specific error for case when para head is missing from the bridge pallet * fix match to support both error types --- relays/client-substrate/src/error.rs | 3 +++ relays/lib-substrate-relay/src/on_demand/parachains.rs | 7 ++++--- relays/lib-substrate-relay/src/parachains/target.rs | 7 +++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index ddea1819fb008..3b83f917bf8e8 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -61,6 +61,9 @@ pub enum Error { /// The bridge pallet is not yet initialized and all transactions will be rejected. #[error("Bridge pallet is not initialized.")] BridgePalletIsNotInitialized, + /// There's no best head of the parachain at the `pallet-bridge-parachains` at the target side. + #[error("No head of the ParaId({0}) at the bridge parachains pallet at {1}.")] + NoParachainHeadAtTarget(u32, String), /// An error has happened when we have tried to parse storage proof. #[error("Error when parsing storage proof: {0:?}.")] StorageProofError(bp_runtime::StorageProofError), diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index b6c30d56ee118..58ae5ae12a0b7 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -473,12 +473,13 @@ where P::SourceParachain, >(target.client(), best_target_block_hash) .await; - // if there are no parachain heads at the target (`BridgePalletIsNotInitialized`), we'll need - // to submit at least one. Otherwise the pallet will be treated as uninitialized and messages + // if there are no parachain heads at the target (`NoParachainHeadAtTarget`), we'll need to + // submit at least one. Otherwise the pallet will be treated as uninitialized and messages // sync will stall. let para_header_at_target = match para_header_at_target { Ok(para_header_at_target) => Some(para_header_at_target.0), - Err(SubstrateError::BridgePalletIsNotInitialized) => None, + Err(SubstrateError::BridgePalletIsNotInitialized) | + Err(SubstrateError::NoParachainHeadAtTarget(_, _)) => None, Err(e) => return Err(map_target_err(e)), }; diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 5e765f10ff550..7f6cdf8f9251f 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -33,7 +33,7 @@ use parachains_relay::{ }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, RelayChain, TransactionEra, TransactionTracker, UnsignedTransaction, + HeaderIdOf, ParachainBase, RelayChain, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -110,7 +110,10 @@ where ) .map_err(SubstrateError::ResponseParseFailed)? .map(Ok) - .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized)) + .unwrap_or(Err(SubstrateError::NoParachainHeadAtTarget( + P::SourceParachain::PARACHAIN_ID, + P::TargetChain::NAME.into(), + ))) } async fn parachain_head( From a95ac162f96e7b1150272ae12f73e4e412d1a769 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 31 Jan 2023 11:08:08 +0300 Subject: [PATCH 0911/1210] bump bridge hub versions (#1830) --- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/chains/wococo.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index ab3de4dbb6bd4..b1e8d1bef85ed 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,5 +27,5 @@ impl CliChain for Rococo { impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9370, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9371, transaction_version: 1 }); } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 68d5e56554471..cb8dff620a571 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -27,5 +27,5 @@ impl CliChain for Wococo { impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9370, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9371, transaction_version: 1 }); } From 9bb75c389d6195a799750f82e8014ce09e0d38bb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 31 Jan 2023 11:49:40 +0300 Subject: [PATCH 0912/1210] Use GitLab env vars to get git commit (#1831) * use GitLab env vars to get git commit * compile_error to test it * Revert "compile_error to test it" This reverts commit 67d4782298d3cdfbe1a28231042bba6444316e8a. --- relays/bin-substrate/src/cli/mod.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 17d0262b21bef..a5b90744067a0 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -260,6 +260,22 @@ pub struct PrometheusParams { #[derive(BuildInfo)] struct SubstrateRelayBuildInfo; +impl SubstrateRelayBuildInfo { + /// Get git commit in form ``. + pub fn get_git_commit() -> String { + // on gitlab we use images without git installed, so we can't use `rbtag` there + // locally we don't have `CI_*` env variables, so we can't rely on them + // => we are using `CI_*` env variables or else `rbtag` + let maybe_sha_from_ci = option_env!("CI_COMMIT_SHORT_SHA"); + maybe_sha_from_ci + .map(|short_sha| { + // we assume that on CI the copy is always clean + format!("{short_sha}-clean") + }) + .unwrap_or_else(|| SubstrateRelayBuildInfo.get_build_commit().into()) + } +} + impl PrometheusParams { /// Tries to convert CLI metrics params into metrics params, used by the relay. pub fn into_metrics_params(self) -> anyhow::Result { @@ -273,11 +289,11 @@ impl PrometheusParams { }; let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); - let relay_commit = SubstrateRelayBuildInfo.get_build_commit(); + let relay_commit = SubstrateRelayBuildInfo::get_git_commit(); relay_utils::metrics::MetricsParams::new( metrics_address, relay_version.into(), - relay_commit.into(), + relay_commit, ) .map_err(|e| anyhow::format_err!("{:?}", e)) } From b951585316ebdfef7507fd36ac84e9d7adf6d0a0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 31 Jan 2023 18:25:06 +0300 Subject: [PATCH 0913/1210] Fix on demand parachains relay when no parachain head at target (#1834) * `best_finalized_peer_at_best_self` in messages relay is now Option<> - before it was an error, which effectively blocked the lane * unnecessary mut * clone on return --- .../src/finality/target.rs | 3 +- .../src/messages_source.rs | 22 ++--- .../src/on_demand/parachains.rs | 94 ++++++++++++------- relays/messages/src/message_lane_loop.rs | 89 ++++++++++-------- relays/messages/src/message_race_loop.rs | 2 +- relays/messages/src/metrics.rs | 38 +++++--- 6 files changed, 150 insertions(+), 98 deletions(-) diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 951123ae07c7c..9c6ec7c3055ed 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -102,7 +102,8 @@ where None, ) .await? - .best_finalized_peer_at_best_self) + .best_finalized_peer_at_best_self + .ok_or(Error::BridgePalletIsNotInitialized)?) } async fn submit_finality_proof( diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index e86f7abdd642a..8d2ac5874fe60 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -421,14 +421,15 @@ where .await?; // read actual header, matching the `peer_on_self_best_finalized_id` from the peer chain - let actual_peer_on_self_best_finalized_id = match peer_client { - Some(peer_client) => { - let actual_peer_on_self_best_finalized = - peer_client.header_by_number(peer_on_self_best_finalized_id.number()).await?; - actual_peer_on_self_best_finalized.id() - }, - None => peer_on_self_best_finalized_id, - }; + let actual_peer_on_self_best_finalized_id = + match (peer_client, peer_on_self_best_finalized_id.as_ref()) { + (Some(peer_client), Some(peer_on_self_best_finalized_id)) => { + let actual_peer_on_self_best_finalized = + peer_client.header_by_number(peer_on_self_best_finalized_id.number()).await?; + Some(actual_peer_on_self_best_finalized.id()) + }, + _ => peer_on_self_best_finalized_id, + }; Ok(ClientState { best_self: self_best_id, @@ -444,7 +445,7 @@ where pub async fn best_finalized_peer_header_at_self( self_client: &Client, at_self_hash: HashOf, -) -> Result, SubstrateError> +) -> Result>, SubstrateError> where SelfChain: Chain, PeerChain: Chain, @@ -456,8 +457,7 @@ where (), Some(at_self_hash), ) - .await? - .ok_or(SubstrateError::BridgePalletIsNotInitialized) + .await } fn validate_out_msgs_details( diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 58ae5ae12a0b7..b1270108c8038 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -422,11 +422,14 @@ struct RelayData { pub para_header_at_source: Option>, /// Parachain header, that is available at the source relay chain at `relay_header_at_target` /// block. + /// + /// May be `None` if there's no `relay_header_at_target` yet, or if the + /// `relay_header_at_target` is too old and we think its state has been pruned. pub para_header_at_relay_header_at_target: Option>, /// Relay header number at the source chain. pub relay_header_at_source: RelayNumber, /// Relay header number at the target chain. - pub relay_header_at_target: RelayNumber, + pub relay_header_at_target: Option, } /// Read required data from source and target clients. @@ -477,9 +480,8 @@ where // submit at least one. Otherwise the pallet will be treated as uninitialized and messages // sync will stall. let para_header_at_target = match para_header_at_target { - Ok(para_header_at_target) => Some(para_header_at_target.0), - Err(SubstrateError::BridgePalletIsNotInitialized) | - Err(SubstrateError::NoParachainHeadAtTarget(_, _)) => None, + Ok(Some(para_header_at_target)) => Some(para_header_at_target.0), + Ok(None) => None, Err(e) => return Err(map_target_err(e)), }; @@ -502,25 +504,34 @@ where .await .map_err(map_target_err)?; - // if relay header at target is too old, then its state may already be discarded at the source + // if relay header at target is too old then its state may already be discarded at the source // => just use `None` in this case - let is_relay_header_at_target_ancient = - is_ancient_block(relay_header_at_target.number(), relay_header_at_source); - let para_header_at_relay_header_at_target = if is_relay_header_at_target_ancient { - None - } else { - source - .on_chain_para_head_id(relay_header_at_target, P::SourceParachain::PARACHAIN_ID.into()) - .await - .map_err(map_source_err)? - }; + // + // the same is for case when there's no relay header at target at all + let available_relay_header_at_target = + relay_header_at_target.filter(|relay_header_at_target| { + !is_ancient_block(relay_header_at_target.number(), relay_header_at_source) + }); + let para_header_at_relay_header_at_target = + if let Some(available_relay_header_at_target) = available_relay_header_at_target { + source + .on_chain_para_head_id( + available_relay_header_at_target, + P::SourceParachain::PARACHAIN_ID.into(), + ) + .await + .map_err(map_source_err)? + } else { + None + }; Ok(RelayData { required_para_header: required_header_number, para_header_at_target, para_header_at_source, relay_header_at_source, - relay_header_at_target: relay_header_at_target.0, + relay_header_at_target: relay_header_at_target + .map(|relay_header_at_target| relay_header_at_target.0), para_header_at_relay_header_at_target, }) } @@ -528,25 +539,35 @@ where /// Select relay and parachain headers that need to be relayed. fn select_headers_to_relay( data: &RelayData, - mut state: RelayState, + state: RelayState, ) -> RelayState where ParaHash: Clone, ParaNumber: Copy + PartialOrd + Zero, RelayNumber: Copy + Debug + Ord, { + // we can't do anything until **relay chain** bridge GRANDPA pallet is not initialized at the + // target chain + let relay_header_at_target = match data.relay_header_at_target { + Some(relay_header_at_target) => relay_header_at_target, + None => return RelayState::Idle, + }; + // Process the `RelayingRelayHeader` state. if let &RelayState::RelayingRelayHeader(relay_header_number) = &state { - if data.relay_header_at_target < relay_header_number { + if relay_header_at_target < relay_header_number { // The required relay header hasn't yet been relayed. Ask / wait for it. return state } // We may switch to `RelayingParaHeader` if parachain head is available. - state = data - .para_header_at_relay_header_at_target - .clone() - .map_or(RelayState::Idle, RelayState::RelayingParaHeader); + if let Some(para_header_at_relay_header_at_target) = + data.para_header_at_relay_header_at_target.as_ref() + { + return RelayState::RelayingParaHeader(para_header_at_relay_header_at_target.clone()) + } + + // else use the regular process - e.g. we may require to deliver new relay header first } // Process the `RelayingParaHeader` state. @@ -585,7 +606,7 @@ where // its ancestor // we need relay chain header first - if data.relay_header_at_target < data.relay_header_at_source { + if relay_header_at_target < data.relay_header_at_source { return RelayState::RelayingRelayHeader(data.relay_header_at_source) } @@ -640,7 +661,8 @@ impl<'a, P: SubstrateParachainsPipeline> None, ) .await? - .best_finalized_peer_at_best_self) + .best_finalized_peer_at_best_self + .ok_or(SubstrateError::BridgePalletIsNotInitialized)?) } async fn best_finalized_para_block_at_source( @@ -726,7 +748,7 @@ mod tests { para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 700, + relay_header_at_target: Some(700), para_header_at_relay_header_at_target: Some(HeaderId(100, 100)), }, RelayState::RelayingRelayHeader(750), @@ -744,7 +766,7 @@ mod tests { para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 750, + relay_header_at_target: Some(750), para_header_at_relay_header_at_target: Some(HeaderId(100, 100)), }, RelayState::RelayingRelayHeader(750), @@ -762,7 +784,7 @@ mod tests { para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 780, + relay_header_at_target: Some(780), para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::RelayingRelayHeader(750), @@ -779,7 +801,7 @@ mod tests { para_header_at_target: Some(50), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 780, + relay_header_at_target: Some(780), para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::RelayingParaHeader(HeaderId(105, 105)), @@ -797,7 +819,7 @@ mod tests { para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 780, + relay_header_at_target: Some(780), para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, @@ -815,7 +837,7 @@ mod tests { para_header_at_target: Some(105), para_header_at_source: None, relay_header_at_source: 800, - relay_header_at_target: 780, + relay_header_at_target: Some(780), para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, @@ -833,7 +855,7 @@ mod tests { para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(110, 110)), relay_header_at_source: 800, - relay_header_at_target: 780, + relay_header_at_target: Some(780), para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, @@ -851,7 +873,7 @@ mod tests { para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, - relay_header_at_target: 780, + relay_header_at_target: Some(780), para_header_at_relay_header_at_target: Some(HeaderId(105, 105)), }, RelayState::Idle, @@ -869,7 +891,7 @@ mod tests { para_header_at_target: Some(105), para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, - relay_header_at_target: 800, + relay_header_at_target: Some(800), para_header_at_relay_header_at_target: Some(HeaderId(125, 125)), }, RelayState::Idle, @@ -887,7 +909,7 @@ mod tests { para_header_at_target: Some(105), para_header_at_source: None, relay_header_at_source: 800, - relay_header_at_target: 800, + relay_header_at_target: Some(800), para_header_at_relay_header_at_target: None, }, RelayState::RelayingRelayHeader(800), @@ -905,7 +927,7 @@ mod tests { para_header_at_target: None, para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, - relay_header_at_target: 800, + relay_header_at_target: Some(800), para_header_at_relay_header_at_target: Some(HeaderId(125, 125)), }, RelayState::Idle, @@ -923,7 +945,7 @@ mod tests { para_header_at_target: None, para_header_at_source: Some(HeaderId(125, 125)), relay_header_at_source: 800, - relay_header_at_target: 700, + relay_header_at_target: Some(700), para_header_at_relay_header_at_target: Some(HeaderId(125, 125)), }, RelayState::Idle, diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index e26849bbb9bf1..5e5085bbd5dcb 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -249,10 +249,13 @@ pub struct ClientState { pub best_finalized_self: SelfHeaderId, /// Best finalized header id of the peer chain read at the best block of this chain (at /// `best_finalized_self`). - pub best_finalized_peer_at_best_self: PeerHeaderId, + /// + /// It may be `None` e,g. if peer is a parachain and we haven't yet relayed any parachain + /// heads. + pub best_finalized_peer_at_best_self: Option, /// Header id of the peer chain with the number, matching the /// `best_finalized_peer_at_best_self`. - pub actual_best_finalized_peer_at_best_self: PeerHeaderId, + pub actual_best_finalized_peer_at_best_self: Option, } /// State of source client in one-way message lane. @@ -973,15 +976,15 @@ pub(crate) mod tests { source_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, source_latest_generated_nonce: 1, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, target_latest_received_nonce: 0, ..Default::default() @@ -997,11 +1000,11 @@ pub(crate) mod tests { if data.is_target_reconnected { data.is_target_fails = false; } - if data.target_state.best_finalized_peer_at_best_self.0 < 10 { - data.target_state.best_finalized_peer_at_best_self = HeaderId( - data.target_state.best_finalized_peer_at_best_self.0 + 1, - data.target_state.best_finalized_peer_at_best_self.0 + 1, - ); + if data.target_state.best_finalized_peer_at_best_self.unwrap().0 < 10 { + data.target_state.best_finalized_peer_at_best_self = Some(HeaderId( + data.target_state.best_finalized_peer_at_best_self.unwrap().0 + 1, + data.target_state.best_finalized_peer_at_best_self.unwrap().0 + 1, + )); } if !data.submitted_messages_proofs.is_empty() { exit_sender.unbounded_send(()).unwrap(); @@ -1025,16 +1028,16 @@ pub(crate) mod tests { source_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, source_latest_generated_nonce: 1, source_tracked_transaction_status: TrackedTransactionStatus::Lost, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, target_latest_received_nonce: 0, target_tracked_transaction_status: TrackedTransactionStatus::Lost, @@ -1076,15 +1079,15 @@ pub(crate) mod tests { source_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, source_latest_generated_nonce: 1, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, target_latest_received_nonce: 0, ..Default::default() @@ -1096,8 +1099,11 @@ pub(crate) mod tests { data.source_state.best_finalized_self = data.source_state.best_self; // syncing target headers -> source chain if let Some(last_requirement) = data.target_to_source_header_requirements.last() { - if *last_requirement != data.source_state.best_finalized_peer_at_best_self { - data.source_state.best_finalized_peer_at_best_self = *last_requirement; + if *last_requirement != + data.source_state.best_finalized_peer_at_best_self.unwrap() + { + data.source_state.best_finalized_peer_at_best_self = + Some(*last_requirement); } } }), @@ -1116,8 +1122,11 @@ pub(crate) mod tests { data.target_state.best_finalized_self = data.target_state.best_self; // syncing source headers -> target chain if let Some(last_requirement) = data.source_to_target_header_requirements.last() { - if *last_requirement != data.target_state.best_finalized_peer_at_best_self { - data.target_state.best_finalized_peer_at_best_self = *last_requirement; + if *last_requirement != + data.target_state.best_finalized_peer_at_best_self.unwrap() + { + data.target_state.best_finalized_peer_at_best_self = + Some(*last_requirement); } } // if source has received all messages receiving confirmations => stop @@ -1150,15 +1159,15 @@ pub(crate) mod tests { source_state: ClientState { best_self: HeaderId(10, 10), best_finalized_self: HeaderId(10, 10), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, source_latest_generated_nonce: 10, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, target_latest_received_nonce: 0, ..Default::default() @@ -1171,15 +1180,18 @@ pub(crate) mod tests { // headers relay must only be started when we need new target headers at source node if data.target_to_source_header_required.is_some() { assert!( - data.source_state.best_finalized_peer_at_best_self.0 < + data.source_state.best_finalized_peer_at_best_self.unwrap().0 < data.target_state.best_self.0 ); data.target_to_source_header_required = None; } // syncing target headers -> source chain if let Some(last_requirement) = data.target_to_source_header_requirements.last() { - if *last_requirement != data.source_state.best_finalized_peer_at_best_self { - data.source_state.best_finalized_peer_at_best_self = *last_requirement; + if *last_requirement != + data.source_state.best_finalized_peer_at_best_self.unwrap() + { + data.source_state.best_finalized_peer_at_best_self = + Some(*last_requirement); } } }), @@ -1192,15 +1204,18 @@ pub(crate) mod tests { // headers relay must only be started when we need new source headers at target node if data.source_to_target_header_required.is_some() { assert!( - data.target_state.best_finalized_peer_at_best_self.0 < + data.target_state.best_finalized_peer_at_best_self.unwrap().0 < data.source_state.best_self.0 ); data.source_to_target_header_required = None; } // syncing source headers -> target chain if let Some(last_requirement) = data.source_to_target_header_requirements.last() { - if *last_requirement != data.target_state.best_finalized_peer_at_best_self { - data.target_state.best_finalized_peer_at_best_self = *last_requirement; + if *last_requirement != + data.target_state.best_finalized_peer_at_best_self.unwrap() + { + data.target_state.best_finalized_peer_at_best_self = + Some(*last_requirement); } } // if source has received all messages receiving confirmations => stop @@ -1233,15 +1248,15 @@ pub(crate) mod tests { source_state: ClientState { best_self: HeaderId(10, 10), best_finalized_self: HeaderId(10, 10), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, source_latest_generated_nonce: 10, target_state: ClientState { best_self: HeaderId(0, 0), best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: HeaderId(0, 0), - actual_best_finalized_peer_at_best_self: HeaderId(0, 0), + best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), + actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), }, target_latest_received_nonce: 0, ..Default::default() diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index deac71e5b6efe..2988ab231d932 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -308,7 +308,7 @@ pub async fn run, TC: TargetClient

>( target_best_nonces_required = true; race_state.best_target_header_id = Some(target_state.best_self); race_state.best_finalized_source_header_id_at_best_target - = Some(target_state.best_finalized_peer_at_best_self); + = target_state.best_finalized_peer_at_best_self; } let is_target_finalized_state_updated = race_state.best_finalized_target_header_id.as_ref() diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index ace4264cacc65..20c6986b4747c 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -66,24 +66,38 @@ impl MessageLaneLoopMetrics { pub fn update_source_state(&self, source_client_state: SourceClientState

) { self.source_to_target_finality_metrics .update_best_block_at_source(source_client_state.best_self.0); - self.target_to_source_finality_metrics - .update_best_block_at_target(source_client_state.best_finalized_peer_at_best_self.0); - self.target_to_source_finality_metrics.update_using_same_fork( - source_client_state.best_finalized_peer_at_best_self.1 == - source_client_state.actual_best_finalized_peer_at_best_self.1, - ); + if let Some(best_finalized_peer_at_best_self) = + source_client_state.best_finalized_peer_at_best_self + { + self.target_to_source_finality_metrics + .update_best_block_at_target(best_finalized_peer_at_best_self.0); + if let Some(actual_best_finalized_peer_at_best_self) = + source_client_state.actual_best_finalized_peer_at_best_self + { + self.target_to_source_finality_metrics.update_using_same_fork( + best_finalized_peer_at_best_self.1 == actual_best_finalized_peer_at_best_self.1, + ); + } + } } /// Update target client state metrics. pub fn update_target_state(&self, target_client_state: TargetClientState

) { self.target_to_source_finality_metrics .update_best_block_at_source(target_client_state.best_self.0); - self.source_to_target_finality_metrics - .update_best_block_at_target(target_client_state.best_finalized_peer_at_best_self.0); - self.source_to_target_finality_metrics.update_using_same_fork( - target_client_state.best_finalized_peer_at_best_self.1 == - target_client_state.actual_best_finalized_peer_at_best_self.1, - ); + if let Some(best_finalized_peer_at_best_self) = + target_client_state.best_finalized_peer_at_best_self + { + self.source_to_target_finality_metrics + .update_best_block_at_target(best_finalized_peer_at_best_self.0); + if let Some(actual_best_finalized_peer_at_best_self) = + target_client_state.actual_best_finalized_peer_at_best_self + { + self.source_to_target_finality_metrics.update_using_same_fork( + best_finalized_peer_at_best_self.1 == actual_best_finalized_peer_at_best_self.1, + ); + } + } } /// Update latest generated nonce at source. From 8273c5ca84224024633d756b54d80fed03361678 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 31 Jan 2023 18:53:09 +0300 Subject: [PATCH 0914/1210] fix bridge hubs blocks interval (#1836) --- primitives/chain-bridge-hub-cumulus/Cargo.toml | 2 ++ primitives/chain-bridge-hub-cumulus/src/lib.rs | 6 ++++++ relays/client-bridge-hub-rococo/src/lib.rs | 3 ++- relays/client-bridge-hub-wococo/src/lib.rs | 4 ++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index 8896522951b7b..cb7f55d33619b 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -17,6 +17,7 @@ bp-messages = { path = "../../primitives/messages", default-features = false } frame-system = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot Dependencies polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } @@ -29,5 +30,6 @@ std = [ "frame-system/std", "frame-support/std", "sp-api/std", + "sp-std/std", "polkadot-primitives/std", ] diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 6eab5a53a0441..74c6618275511 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -29,6 +29,12 @@ use frame_support::{ weights::constants, }; use frame_system::limits; +use sp_std::time::Duration; + +/// Average block interval in Cumulus-based parachains. +/// +/// Corresponds to the `MILLISECS_PER_BLOCK` from `parachains_common` crate. +pub const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(12); /// All cumulus bridge hubs allow normal extrinsics to fill block up to 75 percent. /// diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index b14a9baa61deb..80c075cd0d5fd 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. +use bp_bridge_hub_rococo::AVERAGE_BLOCK_INTERVAL; use bp_bridge_hub_wococo::PolkadotSignedExtension; use bp_messages::MessageNonce; use codec::Encode; @@ -44,7 +45,7 @@ impl Chain for BridgeHubRococo { const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_rococo::SignedBlock; type Call = runtime::Call; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index abc820ed6247c..7af310bfd4176 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_bridge_hub_wococo::PolkadotSignedExtension; +use bp_bridge_hub_wococo::{PolkadotSignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -44,7 +44,7 @@ impl Chain for BridgeHubWococo { const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_wococo::BEST_FINALIZED_BRIDGE_HUB_WOCOCO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_wococo::SignedBlock; type Call = runtime::Call; From 1c779903be9921aff4b861124dfbded25112d88e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 31 Jan 2023 18:10:37 +0200 Subject: [PATCH 0915/1210] Change some macro names (#1837) Change the names of the macros used for generating indirect runtime calls Signed-off-by: Serban Iorga --- .../chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs | 4 ++-- .../chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs | 4 ++-- .../src/chains/millau_headers_to_rialto_parachain.rs | 2 +- .../src/chains/millau_messages_to_rialto_parachain.rs | 2 +- .../src/chains/rialto_parachain_messages_to_millau.rs | 2 +- .../src/chains/rococo_headers_to_bridge_hub_wococo.rs | 2 +- .../src/chains/wococo_headers_to_bridge_hub_rococo.rs | 2 +- relays/lib-substrate-relay/src/finality/mod.rs | 2 +- relays/lib-substrate-relay/src/messages_lane.rs | 4 ++-- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index 8422569d009af..b48ace58987d1 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -32,14 +32,14 @@ impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { type MessagesLane = BridgeHubRococoMessagesToBridgeHubWococoMessageLane; } -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( +substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubRococoMessagesToBridgeHubWococoMessageLane, BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder, relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoMessages, relay_bridge_hub_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof ); -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubRococoMessagesToBridgeHubWococoMessageLane, BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoMessages, diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index 96df83cd0b217..3bcf62de333ad 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -32,14 +32,14 @@ impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { type MessagesLane = BridgeHubWococoMessagesToBridgeHubRococoMessageLane; } -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( +substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubWococoMessagesToBridgeHubRococoMessageLane, BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoMessages, relay_bridge_hub_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof ); -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubWococoMessagesToBridgeHubRococoMessageLane, BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoMessages, diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs index 6496167cf7ca9..66f0a1fc437e3 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -39,7 +39,7 @@ use substrate_relay_helper::finality::{ engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, }; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( +substrate_relay_helper::generate_submit_finality_proof_call_builder!( MillauFinalityToRialtoParachain, MillauFinalityToRialtoParachainCallBuilder, relay_rialto_parachain_client::runtime::Call::BridgeMillauGrandpa, diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index 817d0098d9b76..3c345b94f1b97 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -22,7 +22,7 @@ use substrate_relay_helper::messages_lane::{ DirectReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, }; -substrate_relay_helper::generate_mocked_receive_message_proof_call_builder!( +substrate_relay_helper::generate_receive_message_proof_call_builder!( MillauMessagesToRialtoParachain, MillauMessagesToRialtoParachainReceiveMessagesProofCallBuilder, relay_rialto_parachain_client::runtime::Call::BridgeMillauMessages, diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index 0000a0a754a53..f1645d4244c7e 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -23,7 +23,7 @@ use substrate_relay_helper::{ UtilityPalletBatchCallBuilder, }; -substrate_relay_helper::generate_mocked_receive_message_delivery_proof_call_builder!( +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( RialtoParachainMessagesToMillau, RialtoParachainMessagesToMillauReceiveMessagesDeliveryProofCallBuilder, relay_rialto_parachain_client::runtime::Call::BridgeMillauMessages, diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs index 0de1fd9396a81..2272144311c6d 100644 --- a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs @@ -29,7 +29,7 @@ use substrate_relay_helper::{ #[derive(Clone, Debug)] pub struct RococoFinalityToBridgeHubWococo; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( +substrate_relay_helper::generate_submit_finality_proof_call_builder!( RococoFinalityToBridgeHubWococo, RococoFinalityToBridgeHubWococoCallBuilder, relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa, diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs index e9054fd31e904..3904300958216 100644 --- a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs @@ -29,7 +29,7 @@ use substrate_relay_helper::{ #[derive(Clone, Debug)] pub struct WococoFinalityToBridgeHubRococo; -substrate_relay_helper::generate_mocked_submit_finality_proof_call_builder!( +substrate_relay_helper::generate_submit_finality_proof_call_builder!( WococoFinalityToBridgeHubRococo, WococoFinalityToBridgeHubRococoCallBuilder, relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoGrandpa, diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index f529e20912a3e..b0f0ee4e52cc7 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -135,7 +135,7 @@ where /// the variant for the `submit_finality_proof` call within that first option. #[rustfmt::skip] #[macro_export] -macro_rules! generate_mocked_submit_finality_proof_call_builder { +macro_rules! generate_submit_finality_proof_call_builder { ($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => { pub struct $mocked_builder; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index a0cd9b4375656..b41ee2072e040 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -315,7 +315,7 @@ where /// the variant for the `receive_messages_proof` call within that first option. #[rustfmt::skip] #[macro_export] -macro_rules! generate_mocked_receive_message_proof_call_builder { +macro_rules! generate_receive_message_proof_call_builder { ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_proof:path) => { pub struct $mocked_builder; @@ -411,7 +411,7 @@ where /// the variant for the `receive_messages_delivery_proof` call within that first option. #[rustfmt::skip] #[macro_export] -macro_rules! generate_mocked_receive_message_delivery_proof_call_builder { +macro_rules! generate_receive_message_delivery_proof_call_builder { ($pipeline:ident, $mocked_builder:ident, $bridge_messages:path, $receive_messages_delivery_proof:path) => { pub struct $mocked_builder; From 3e0b162d127c5bf1bffb90109888a1e1b579a119 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Feb 2023 12:00:50 +0300 Subject: [PATCH 0916/1210] fix bridge-runtime-common build (#1839) --- bin/runtime-common/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 7d53867164617..27e305751e4e8 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -83,6 +83,7 @@ runtime-benchmarks = [ "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] integrity-test = [ From 85e72c54d1a71fc3874682b2727c35a707d57d16 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 3 Feb 2023 12:12:49 +0200 Subject: [PATCH 0917/1210] Add tool for auto generating runtime code from metadata (#1812) * Create CLI tool for generating indirect runtimes code * Use the generated runtime for rialto parachain * Avoid autogenerated files when executing cargo spellcheck * Fix clippy warning --- primitives/chain-millau/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- .../millau_headers_to_rialto_parachain.rs | 4 +- .../millau_messages_to_rialto_parachain.rs | 4 +- .../src/chains/rialto_parachain.rs | 12 +- .../rialto_parachain_messages_to_millau.rs | 4 +- relays/bin-substrate/src/cli/init_bridge.rs | 14 +- relays/client-rialto-parachain/Cargo.toml | 2 + .../src/codegen_runtime.rs | 9830 +++++++++++++++++ relays/client-rialto-parachain/src/lib.rs | 14 +- .../src/runtime_wrapper.rs | 57 - 11 files changed, 9866 insertions(+), 79 deletions(-) create mode 100644 relays/client-rialto-parachain/src/codegen_runtime.rs delete mode 100644 relays/client-rialto-parachain/src/runtime_wrapper.rs diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index abcbd0f512332..1032e46b65812 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -17,7 +17,7 @@ fixed-hash = { version = "0.8.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", optional = true } -parity-util-mem = { version = "0.12", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index a9db53a8bf01e..9a68e8ccc2db6 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -parity-util-mem = { version = "0.12.0", optional = true } +parity-util-mem = { version = "0.11.0", optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs index 66f0a1fc437e3..4a99d73147b29 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs @@ -42,8 +42,8 @@ use substrate_relay_helper::finality::{ substrate_relay_helper::generate_submit_finality_proof_call_builder!( MillauFinalityToRialtoParachain, MillauFinalityToRialtoParachainCallBuilder, - relay_rialto_parachain_client::runtime::Call::BridgeMillauGrandpa, - relay_rialto_parachain_client::runtime::BridgeMillauGrandpaCall::submit_finality_proof + relay_rialto_parachain_client::RuntimeCall::BridgeMillauGrandpa, + relay_rialto_parachain_client::BridgeGrandpaCall::submit_finality_proof ); /// Description of Millau -> Rialto finalized headers bridge. diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index 3c345b94f1b97..5dbe1d69d1346 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -25,8 +25,8 @@ use substrate_relay_helper::messages_lane::{ substrate_relay_helper::generate_receive_message_proof_call_builder!( MillauMessagesToRialtoParachain, MillauMessagesToRialtoParachainReceiveMessagesProofCallBuilder, - relay_rialto_parachain_client::runtime::Call::BridgeMillauMessages, - relay_rialto_parachain_client::runtime::BridgeMillauMessagesCall::receive_messages_proof + relay_rialto_parachain_client::RuntimeCall::BridgeMillauMessages, + relay_rialto_parachain_client::BridgeMessagesCall::receive_messages_proof ); /// Description of Millau -> RialtoParachain messages bridge. diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 54704e72947b3..1a5ea2e784e47 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -20,7 +20,7 @@ use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; -use relay_substrate_client::{calls::XcmCall, SimpleRuntimeVersion}; +use relay_substrate_client::SimpleRuntimeVersion; use xcm::latest::prelude::*; impl CliEncodeMessage for RialtoParachain { @@ -28,6 +28,9 @@ impl CliEncodeMessage for RialtoParachain { message: xcm::VersionedXcm<()>, bridge_instance_index: u8, ) -> anyhow::Result> { + type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; + type XcmCall = relay_rialto_parachain_client::runtime_types::pallet_xcm::pallet::Call; + let dest = match bridge_instance_index { bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => (Parent, X1(GlobalConsensus(CustomNetworkId::Millau.as_network_id()))), @@ -37,9 +40,12 @@ impl CliEncodeMessage for RialtoParachain { ), }; - let xcm_call = XcmCall::send(Box::new(dest.into()), Box::new(message)); + let xcm_call = XcmCall::send { + dest: Box::new(unsafe { std::mem::transmute(xcm::VersionedMultiLocation::from(dest)) }), + message: Box::new(unsafe { std::mem::transmute(message) }), + }; - Ok(relay_rialto_parachain_client::runtime::Call::PolkadotXcm(xcm_call).into()) + Ok(RuntimeCall::PolkadotXcm(xcm_call).into()) } } diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index f1645d4244c7e..e19953eac554d 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -26,8 +26,8 @@ use substrate_relay_helper::{ substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( RialtoParachainMessagesToMillau, RialtoParachainMessagesToMillauReceiveMessagesDeliveryProofCallBuilder, - relay_rialto_parachain_client::runtime::Call::BridgeMillauMessages, - relay_rialto_parachain_client::runtime::BridgeMillauMessagesCall::receive_messages_delivery_proof + relay_rialto_parachain_client::RuntimeCall::BridgeMillauMessages, + relay_rialto_parachain_client::BridgeMessagesCall::receive_messages_delivery_proof ); /// Description of RialtoParachain -> Millau messages bridge. diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 3e9ddfdb94fd8..d6df1eaeeaa14 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -29,7 +29,7 @@ use crate::{ cli::{bridge::CliBridgeBase, chain_schema::*}, }; use bp_runtime::Chain as ChainBase; -use relay_substrate_client::{calls::SudoCall, AccountKeyPairOf, Chain, UnsignedTransaction}; +use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -123,14 +123,14 @@ impl BridgeInitializer for MillauToRialtoParachainCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - use relay_rialto_parachain_client::runtime; + type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; + type BridgeGrandpaCall = relay_rialto_parachain_client::BridgeGrandpaCall; + type SudoCall = relay_rialto_parachain_client::SudoCall; let initialize_call = - runtime::Call::BridgeMillauGrandpa(runtime::BridgeMillauGrandpaCall::initialize { - init_data, - }); - let sudo_call = SudoCall::sudo(Box::new(initialize_call)); - runtime::Call::Sudo(sudo_call) + RuntimeCall::BridgeMillauGrandpa(BridgeGrandpaCall::initialize { init_data }); + + RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(initialize_call) }) } } diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index f3c4a1d42f8e8..96929d55cc83d 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +subxt = { git = "https://github.com/paritytech/subxt", branch = "master" } # Bridge dependencies @@ -24,3 +25,4 @@ relay-substrate-client = { path = "../client-substrate" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs new file mode 100644 index 0000000000000..16a539f28435c --- /dev/null +++ b/relays/client-rialto-parachain/src/codegen_runtime.rs @@ -0,0 +1,9830 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url http://localhost:20433 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub static PALLETS: [&str; 17usize] = [ + "System", + "Timestamp", + "Sudo", + "RandomnessCollectiveFlip", + "TransactionPayment", + "ParachainSystem", + "ParachainInfo", + "Balances", + "Aura", + "AuraExt", + "XcmpQueue", + "PolkadotXcm", + "CumulusXcm", + "DmpQueue", + "BridgeRelayers", + "BridgeMillauGrandpa", + "BridgeMillauMessages", + ]; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum Event { + #[codec(index = 0)] + System(system::Event), + #[codec(index = 2)] + Sudo(sudo::Event), + #[codec(index = 4)] + TransactionPayment(transaction_payment::Event), + #[codec(index = 20)] + ParachainSystem(parachain_system::Event), + #[codec(index = 30)] + Balances(balances::Event), + #[codec(index = 50)] + XcmpQueue(xcmp_queue::Event), + #[codec(index = 51)] + PolkadotXcm(polkadot_xcm::Event), + #[codec(index = 52)] + CumulusXcm(cumulus_xcm::Event), + #[codec(index = 53)] + DmpQueue(dmp_queue::Event), + #[codec(index = 54)] + BridgeRelayers(bridge_relayers::Event), + #[codec(index = 56)] + BridgeMillauMessages(bridge_millau_messages::Event), + } + pub mod system { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Remark { + pub remark: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct SetHeapPages { + pub pages: ::core::primitive::u64, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetCode { + pub code: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetCodeWithoutChecks { + pub code: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetStorage { + pub items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct KillStorage { + pub keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct KillPrefix { + pub prefix: ::std::vec::Vec<::core::primitive::u8>, + pub subkeys: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct RemarkWithEvent { + pub remark: ::std::vec::Vec<::core::primitive::u8>, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Make some on-chain remark."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(1)`"] + #[doc = "# "] + pub fn remark( + &self, + remark: ::std::vec::Vec<::core::primitive::u8>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "remark", + Remark { remark }, + [ + 101u8, 80u8, 195u8, 226u8, 224u8, 247u8, 60u8, 128u8, 3u8, 101u8, 51u8, + 147u8, 96u8, 126u8, 76u8, 230u8, 194u8, 227u8, 191u8, 73u8, 160u8, + 146u8, 87u8, 147u8, 243u8, 28u8, 228u8, 116u8, 224u8, 181u8, 129u8, + 160u8, + ], + ) + } + #[doc = "Set the number of pages in the WebAssembly environment's heap."] + pub fn set_heap_pages( + &self, + pages: ::core::primitive::u64, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "set_heap_pages", + SetHeapPages { pages }, + [ + 43u8, 103u8, 128u8, 49u8, 156u8, 136u8, 11u8, 204u8, 80u8, 6u8, 244u8, + 86u8, 171u8, 44u8, 140u8, 225u8, 142u8, 198u8, 43u8, 87u8, 26u8, 45u8, + 125u8, 222u8, 165u8, 254u8, 172u8, 158u8, 39u8, 178u8, 86u8, 87u8, + ], + ) + } + #[doc = "Set the new runtime code."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code`"] + #[doc = "- 1 call to `can_set_code`: `O(S)` (calls `sp_io::misc::runtime_version` which is"] + #[doc = " expensive)."] + #[doc = "- 1 storage write (codec `O(C)`)."] + #[doc = "- 1 digest item."] + #[doc = "- 1 event."] + #[doc = "The weight of this function is dependent on the runtime, but generally this is very"] + #[doc = "expensive. We will treat this as a full block."] + #[doc = "# "] + pub fn set_code( + &self, + code: ::std::vec::Vec<::core::primitive::u8>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "set_code", + SetCode { code }, + [ + 27u8, 104u8, 244u8, 205u8, 188u8, 254u8, 121u8, 13u8, 106u8, 120u8, + 244u8, 108u8, 97u8, 84u8, 100u8, 68u8, 26u8, 69u8, 93u8, 128u8, 107u8, + 4u8, 3u8, 142u8, 13u8, 134u8, 196u8, 62u8, 113u8, 181u8, 14u8, 40u8, + ], + ) + } + #[doc = "Set the new runtime code without doing any checks of the given `code`."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(C)` where `C` length of `code`"] + #[doc = "- 1 storage write (codec `O(C)`)."] + #[doc = "- 1 digest item."] + #[doc = "- 1 event."] + #[doc = "The weight of this function is dependent on the runtime. We will treat this as a full"] + #[doc = "block. # "] + pub fn set_code_without_checks( + &self, + code: ::std::vec::Vec<::core::primitive::u8>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "set_code_without_checks", + SetCodeWithoutChecks { code }, + [ + 102u8, 160u8, 125u8, 235u8, 30u8, 23u8, 45u8, 239u8, 112u8, 148u8, + 159u8, 158u8, 42u8, 93u8, 206u8, 94u8, 80u8, 250u8, 66u8, 195u8, 60u8, + 40u8, 142u8, 169u8, 183u8, 80u8, 80u8, 96u8, 3u8, 231u8, 99u8, 216u8, + ], + ) + } + #[doc = "Set some items of storage."] + pub fn set_storage( + &self, + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "set_storage", + SetStorage { items }, + [ + 74u8, 43u8, 106u8, 255u8, 50u8, 151u8, 192u8, 155u8, 14u8, 90u8, 19u8, + 45u8, 165u8, 16u8, 235u8, 242u8, 21u8, 131u8, 33u8, 172u8, 119u8, 78u8, + 140u8, 10u8, 107u8, 202u8, 122u8, 235u8, 181u8, 191u8, 22u8, 116u8, + ], + ) + } + #[doc = "Kill some items from storage."] + pub fn kill_storage( + &self, + keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "kill_storage", + KillStorage { keys }, + [ + 174u8, 174u8, 13u8, 174u8, 75u8, 138u8, 128u8, 235u8, 222u8, 216u8, + 85u8, 18u8, 198u8, 1u8, 138u8, 70u8, 19u8, 108u8, 209u8, 41u8, 228u8, + 67u8, 130u8, 230u8, 160u8, 207u8, 11u8, 180u8, 139u8, 242u8, 41u8, + 15u8, + ], + ) + } + #[doc = "Kill all storage items with a key that starts with the given prefix."] + #[doc = ""] + #[doc = "**NOTE:** We rely on the Root origin to provide us the number of subkeys under"] + #[doc = "the prefix we are removing to accurately calculate the weight of this function."] + pub fn kill_prefix( + &self, + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "kill_prefix", + KillPrefix { prefix, subkeys }, + [ + 203u8, 116u8, 217u8, 42u8, 154u8, 215u8, 77u8, 217u8, 13u8, 22u8, + 193u8, 2u8, 128u8, 115u8, 179u8, 115u8, 187u8, 218u8, 129u8, 34u8, + 80u8, 4u8, 173u8, 120u8, 92u8, 35u8, 237u8, 112u8, 201u8, 207u8, 200u8, + 48u8, + ], + ) + } + #[doc = "Make some on-chain remark and emit event."] + pub fn remark_with_event( + &self, + remark: ::std::vec::Vec<::core::primitive::u8>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "System", + "remark_with_event", + RemarkWithEvent { remark }, + [ + 123u8, 225u8, 180u8, 179u8, 144u8, 74u8, 27u8, 85u8, 101u8, 75u8, + 134u8, 44u8, 181u8, 25u8, 183u8, 158u8, 14u8, 213u8, 56u8, 225u8, + 136u8, 88u8, 26u8, 114u8, 178u8, 43u8, 176u8, 43u8, 240u8, 84u8, 116u8, + 46u8, + ], + ) + } + } + } + #[doc = "Event for the System pallet."] + pub type Event = runtime_types::frame_system::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An extrinsic completed successfully."] + pub struct ExtrinsicSuccess { + pub dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + } + impl ::subxt::events::StaticEvent for ExtrinsicSuccess { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "ExtrinsicSuccess"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An extrinsic failed."] + pub struct ExtrinsicFailed { + pub dispatch_error: runtime_types::sp_runtime::DispatchError, + pub dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + } + impl ::subxt::events::StaticEvent for ExtrinsicFailed { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "ExtrinsicFailed"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "`:code` was updated."] + pub struct CodeUpdated; + impl ::subxt::events::StaticEvent for CodeUpdated { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "CodeUpdated"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A new account was created."] + pub struct NewAccount { + pub account: ::sp_core::crypto::AccountId32, + } + impl ::subxt::events::StaticEvent for NewAccount { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "NewAccount"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An account was reaped."] + pub struct KilledAccount { + pub account: ::sp_core::crypto::AccountId32, + } + impl ::subxt::events::StaticEvent for KilledAccount { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "KilledAccount"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "On on-chain remark happened."] + pub struct Remarked { + pub sender: ::sp_core::crypto::AccountId32, + pub hash: ::subxt::utils::H256, + } + impl ::subxt::events::StaticEvent for Remarked { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "Remarked"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " The full account information for a particular account ID."] + pub fn account( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::frame_system::AccountInfo< + ::core::primitive::u32, + runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "Account", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 176u8, 187u8, 21u8, 220u8, 159u8, 204u8, 127u8, 14u8, 21u8, 69u8, 77u8, + 114u8, 230u8, 141u8, 107u8, 79u8, 23u8, 16u8, 174u8, 243u8, 252u8, + 42u8, 65u8, 120u8, 229u8, 38u8, 210u8, 255u8, 22u8, 40u8, 109u8, 223u8, + ], + ) + } + #[doc = " The full account information for a particular account ID."] + pub fn account_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::frame_system::AccountInfo< + ::core::primitive::u32, + runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + >, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "Account", + Vec::new(), + [ + 176u8, 187u8, 21u8, 220u8, 159u8, 204u8, 127u8, 14u8, 21u8, 69u8, 77u8, + 114u8, 230u8, 141u8, 107u8, 79u8, 23u8, 16u8, 174u8, 243u8, 252u8, + 42u8, 65u8, 120u8, 229u8, 38u8, 210u8, 255u8, 22u8, 40u8, 109u8, 223u8, + ], + ) + } + #[doc = " Total extrinsics count for the current block."] + pub fn extrinsic_count( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "ExtrinsicCount", + vec![], + [ + 223u8, 60u8, 201u8, 120u8, 36u8, 44u8, 180u8, 210u8, 242u8, 53u8, + 222u8, 154u8, 123u8, 176u8, 249u8, 8u8, 225u8, 28u8, 232u8, 4u8, 136u8, + 41u8, 151u8, 82u8, 189u8, 149u8, 49u8, 166u8, 139u8, 9u8, 163u8, 231u8, + ], + ) + } + #[doc = " The current weight for the block."] + pub fn block_weight( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::frame_support::dispatch::PerDispatchClass< + ::sp_weights::Weight, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "BlockWeight", + vec![], + [ + 120u8, 67u8, 71u8, 163u8, 36u8, 202u8, 52u8, 106u8, 143u8, 155u8, + 144u8, 87u8, 142u8, 241u8, 232u8, 183u8, 56u8, 235u8, 27u8, 237u8, + 20u8, 202u8, 33u8, 85u8, 189u8, 0u8, 28u8, 52u8, 198u8, 40u8, 219u8, + 54u8, + ], + ) + } + #[doc = " Total length (in bytes) for all extrinsics put together, for the current block."] + pub fn all_extrinsics_len( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "AllExtrinsicsLen", + vec![], + [ + 202u8, 145u8, 209u8, 225u8, 40u8, 220u8, 174u8, 74u8, 93u8, 164u8, + 254u8, 248u8, 254u8, 192u8, 32u8, 117u8, 96u8, 149u8, 53u8, 145u8, + 219u8, 64u8, 234u8, 18u8, 217u8, 200u8, 203u8, 141u8, 145u8, 28u8, + 134u8, 60u8, + ], + ) + } + #[doc = " Map of block numbers to block hashes."] + pub fn block_hash( + &self, + _0: impl ::std::borrow::Borrow<::core::primitive::u32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "BlockHash", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Twox64Concat, + )], + [ + 50u8, 112u8, 176u8, 239u8, 175u8, 18u8, 205u8, 20u8, 241u8, 195u8, + 21u8, 228u8, 186u8, 57u8, 200u8, 25u8, 38u8, 44u8, 106u8, 20u8, 168u8, + 80u8, 76u8, 235u8, 12u8, 51u8, 137u8, 149u8, 200u8, 4u8, 220u8, 237u8, + ], + ) + } + #[doc = " Map of block numbers to block hashes."] + pub fn block_hash_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "BlockHash", + Vec::new(), + [ + 50u8, 112u8, 176u8, 239u8, 175u8, 18u8, 205u8, 20u8, 241u8, 195u8, + 21u8, 228u8, 186u8, 57u8, 200u8, 25u8, 38u8, 44u8, 106u8, 20u8, 168u8, + 80u8, 76u8, 235u8, 12u8, 51u8, 137u8, 149u8, 200u8, 4u8, 220u8, 237u8, + ], + ) + } + #[doc = " Extrinsics data for the current block (maps an extrinsic's index to its data)."] + pub fn extrinsic_data( + &self, + _0: impl ::std::borrow::Borrow<::core::primitive::u32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "ExtrinsicData", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Twox64Concat, + )], + [ + 210u8, 224u8, 211u8, 186u8, 118u8, 210u8, 185u8, 194u8, 238u8, 211u8, + 254u8, 73u8, 67u8, 184u8, 31u8, 229u8, 168u8, 125u8, 98u8, 23u8, 241u8, + 59u8, 49u8, 86u8, 126u8, 9u8, 114u8, 163u8, 160u8, 62u8, 50u8, 67u8, + ], + ) + } + #[doc = " Extrinsics data for the current block (maps an extrinsic's index to its data)."] + pub fn extrinsic_data_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "ExtrinsicData", + Vec::new(), + [ + 210u8, 224u8, 211u8, 186u8, 118u8, 210u8, 185u8, 194u8, 238u8, 211u8, + 254u8, 73u8, 67u8, 184u8, 31u8, 229u8, 168u8, 125u8, 98u8, 23u8, 241u8, + 59u8, 49u8, 86u8, 126u8, 9u8, 114u8, 163u8, 160u8, 62u8, 50u8, 67u8, + ], + ) + } + #[doc = " The current block number being processed. Set by `execute_block`."] + pub fn number( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "Number", + vec![], + [ + 228u8, 96u8, 102u8, 190u8, 252u8, 130u8, 239u8, 172u8, 126u8, 235u8, + 246u8, 139u8, 208u8, 15u8, 88u8, 245u8, 141u8, 232u8, 43u8, 204u8, + 36u8, 87u8, 211u8, 141u8, 187u8, 68u8, 236u8, 70u8, 193u8, 235u8, + 164u8, 191u8, + ], + ) + } + #[doc = " Hash of the previous block."] + pub fn parent_hash( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "ParentHash", + vec![], + [ + 232u8, 206u8, 177u8, 119u8, 38u8, 57u8, 233u8, 50u8, 225u8, 49u8, + 169u8, 176u8, 210u8, 51u8, 231u8, 176u8, 234u8, 186u8, 188u8, 112u8, + 15u8, 152u8, 195u8, 232u8, 201u8, 97u8, 208u8, 249u8, 9u8, 163u8, 69u8, + 36u8, + ], + ) + } + #[doc = " Digest of the current block, also part of the block header."] + pub fn digest( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::sp_runtime::generic::Digest>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "Digest", + vec![], + [ + 83u8, 141u8, 200u8, 132u8, 182u8, 55u8, 197u8, 122u8, 13u8, 159u8, + 31u8, 42u8, 60u8, 191u8, 89u8, 221u8, 242u8, 47u8, 199u8, 213u8, 48u8, + 216u8, 131u8, 168u8, 245u8, 82u8, 56u8, 190u8, 62u8, 69u8, 96u8, 37u8, + ], + ) + } + #[doc = " Events deposited for the current block."] + #[doc = ""] + #[doc = " NOTE: The item is unbound and should therefore never be read on chain."] + #[doc = " It could otherwise inflate the PoV size of a block."] + #[doc = ""] + #[doc = " Events have a large in-memory size. Box the events to not go out-of-memory"] + #[doc = " just in case someone still reads them from within the runtime."] + pub fn events( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec< + runtime_types::frame_system::EventRecord< + runtime_types::rialto_parachain_runtime::RuntimeEvent, + ::subxt::utils::H256, + >, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "Events", + vec![], + [ + 4u8, 71u8, 59u8, 55u8, 39u8, 106u8, 211u8, 249u8, 109u8, 197u8, 134u8, + 138u8, 5u8, 188u8, 131u8, 120u8, 65u8, 30u8, 151u8, 104u8, 238u8, 32u8, + 251u8, 122u8, 104u8, 218u8, 7u8, 84u8, 253u8, 65u8, 48u8, 185u8, + ], + ) + } + #[doc = " The number of events in the `Events` list."] + pub fn event_count( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "EventCount", + vec![], + [ + 236u8, 93u8, 90u8, 177u8, 250u8, 211u8, 138u8, 187u8, 26u8, 208u8, + 203u8, 113u8, 221u8, 233u8, 227u8, 9u8, 249u8, 25u8, 202u8, 185u8, + 161u8, 144u8, 167u8, 104u8, 127u8, 187u8, 38u8, 18u8, 52u8, 61u8, 66u8, + 112u8, + ], + ) + } + #[doc = " Mapping between a topic (represented by T::Hash) and a vector of indexes"] + #[doc = " of events in the `>` list."] + #[doc = ""] + #[doc = " All topic vectors have deterministic storage locations depending on the topic. This"] + #[doc = " allows light-clients to leverage the changes trie storage tracking mechanism and"] + #[doc = " in case of changes fetch the list of events of interest."] + #[doc = ""] + #[doc = " The value has the type `(T::BlockNumber, EventIndex)` because if we used only just"] + #[doc = " the `EventIndex` then in case if the topic has the same contents on the next block"] + #[doc = " no notification will be triggered thus the event might be lost."] + pub fn event_topics( + &self, + _0: impl ::std::borrow::Borrow<::subxt::utils::H256>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec<(::core::primitive::u32, ::core::primitive::u32)>, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "EventTopics", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 205u8, 90u8, 142u8, 190u8, 176u8, 37u8, 94u8, 82u8, 98u8, 1u8, 129u8, + 63u8, 246u8, 101u8, 130u8, 58u8, 216u8, 16u8, 139u8, 196u8, 154u8, + 111u8, 110u8, 178u8, 24u8, 44u8, 183u8, 176u8, 232u8, 82u8, 223u8, + 38u8, + ], + ) + } + #[doc = " Mapping between a topic (represented by T::Hash) and a vector of indexes"] + #[doc = " of events in the `>` list."] + #[doc = ""] + #[doc = " All topic vectors have deterministic storage locations depending on the topic. This"] + #[doc = " allows light-clients to leverage the changes trie storage tracking mechanism and"] + #[doc = " in case of changes fetch the list of events of interest."] + #[doc = ""] + #[doc = " The value has the type `(T::BlockNumber, EventIndex)` because if we used only just"] + #[doc = " the `EventIndex` then in case if the topic has the same contents on the next block"] + #[doc = " no notification will be triggered thus the event might be lost."] + pub fn event_topics_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec<(::core::primitive::u32, ::core::primitive::u32)>, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "EventTopics", + Vec::new(), + [ + 205u8, 90u8, 142u8, 190u8, 176u8, 37u8, 94u8, 82u8, 98u8, 1u8, 129u8, + 63u8, 246u8, 101u8, 130u8, 58u8, 216u8, 16u8, 139u8, 196u8, 154u8, + 111u8, 110u8, 178u8, 24u8, 44u8, 183u8, 176u8, 232u8, 82u8, 223u8, + 38u8, + ], + ) + } + #[doc = " Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened."] + pub fn last_runtime_upgrade( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::frame_system::LastRuntimeUpgradeInfo, + >, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "LastRuntimeUpgrade", + vec![], + [ + 52u8, 37u8, 117u8, 111u8, 57u8, 130u8, 196u8, 14u8, 99u8, 77u8, 91u8, + 126u8, 178u8, 249u8, 78u8, 34u8, 9u8, 194u8, 92u8, 105u8, 113u8, 81u8, + 185u8, 127u8, 245u8, 184u8, 60u8, 29u8, 234u8, 182u8, 96u8, 196u8, + ], + ) + } + #[doc = " True if we have upgraded so that `type RefCount` is `u32`. False (default) if not."] + pub fn upgraded_to_u32_ref_count( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "UpgradedToU32RefCount", + vec![], + [ + 171u8, 88u8, 244u8, 92u8, 122u8, 67u8, 27u8, 18u8, 59u8, 175u8, 175u8, + 178u8, 20u8, 150u8, 213u8, 59u8, 222u8, 141u8, 32u8, 107u8, 3u8, 114u8, + 83u8, 250u8, 180u8, 233u8, 152u8, 54u8, 187u8, 99u8, 131u8, 204u8, + ], + ) + } + #[doc = " True if we have upgraded so that AccountInfo contains three types of `RefCount`. False"] + #[doc = " (default) if not."] + pub fn upgraded_to_triple_ref_count( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "UpgradedToTripleRefCount", + vec![], + [ + 90u8, 33u8, 56u8, 86u8, 90u8, 101u8, 89u8, 133u8, 203u8, 56u8, 201u8, + 210u8, 244u8, 232u8, 150u8, 18u8, 51u8, 105u8, 14u8, 230u8, 103u8, + 155u8, 246u8, 99u8, 53u8, 207u8, 225u8, 128u8, 186u8, 76u8, 40u8, + 185u8, + ], + ) + } + #[doc = " The execution phase of the block."] + pub fn execution_phase( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "System", + "ExecutionPhase", + vec![], + [ + 230u8, 183u8, 221u8, 135u8, 226u8, 223u8, 55u8, 104u8, 138u8, 224u8, + 103u8, 156u8, 222u8, 99u8, 203u8, 199u8, 164u8, 168u8, 193u8, 133u8, + 201u8, 155u8, 63u8, 95u8, 17u8, 206u8, 165u8, 123u8, 161u8, 33u8, + 172u8, 93u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " Block & extrinsics weights: base values and limits."] + pub fn block_weights( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::frame_system::limits::BlockWeights, + >, + > { + ::subxt::constants::StaticConstantAddress::new( + "System", + "BlockWeights", + [ + 118u8, 253u8, 239u8, 217u8, 145u8, 115u8, 85u8, 86u8, 172u8, 248u8, + 139u8, 32u8, 158u8, 126u8, 172u8, 188u8, 197u8, 105u8, 145u8, 235u8, + 171u8, 50u8, 31u8, 225u8, 167u8, 187u8, 241u8, 87u8, 6u8, 17u8, 234u8, + 185u8, + ], + ) + } + #[doc = " The maximum length of a block (in bytes)."] + pub fn block_length( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::frame_system::limits::BlockLength, + >, + > { + ::subxt::constants::StaticConstantAddress::new( + "System", + "BlockLength", + [ + 116u8, 184u8, 225u8, 228u8, 207u8, 203u8, 4u8, 220u8, 234u8, 198u8, + 150u8, 108u8, 205u8, 87u8, 194u8, 131u8, 229u8, 51u8, 140u8, 4u8, 47u8, + 12u8, 200u8, 144u8, 153u8, 62u8, 51u8, 39u8, 138u8, 205u8, 203u8, + 236u8, + ], + ) + } + #[doc = " Maximum number of block number to block hash mappings to keep (oldest pruned first)."] + pub fn block_hash_count( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "System", + "BlockHashCount", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " The weight of runtime database operations the runtime can invoke."] + pub fn db_weight( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType, + > { + ::subxt::constants::StaticConstantAddress::new( + "System", + "DbWeight", + [ + 124u8, 162u8, 190u8, 149u8, 49u8, 177u8, 162u8, 231u8, 62u8, 167u8, + 199u8, 181u8, 43u8, 232u8, 185u8, 116u8, 195u8, 51u8, 233u8, 223u8, + 20u8, 129u8, 246u8, 13u8, 65u8, 180u8, 64u8, 9u8, 157u8, 59u8, 245u8, + 118u8, + ], + ) + } + #[doc = " Get the chain's current version."] + pub fn version( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType, + > { + ::subxt::constants::StaticConstantAddress::new( + "System", + "Version", + [ + 93u8, 98u8, 57u8, 243u8, 229u8, 8u8, 234u8, 231u8, 72u8, 230u8, 139u8, + 47u8, 63u8, 181u8, 17u8, 2u8, 220u8, 231u8, 104u8, 237u8, 185u8, 143u8, + 165u8, 253u8, 188u8, 76u8, 147u8, 12u8, 170u8, 26u8, 74u8, 200u8, + ], + ) + } + #[doc = " The designated SS58 prefix of this chain."] + #[doc = ""] + #[doc = " This replaces the \"ss58Format\" property declared in the chain spec. Reason is"] + #[doc = " that the runtime should know about the prefix in order to make use of it as"] + #[doc = " an identifier of the chain."] + pub fn ss58_prefix( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u16>, + > { + ::subxt::constants::StaticConstantAddress::new( + "System", + "SS58Prefix", + [ + 116u8, 33u8, 2u8, 170u8, 181u8, 147u8, 171u8, 169u8, 167u8, 227u8, + 41u8, 144u8, 11u8, 236u8, 82u8, 100u8, 74u8, 60u8, 184u8, 72u8, 169u8, + 90u8, 208u8, 135u8, 15u8, 117u8, 10u8, 123u8, 128u8, 193u8, 29u8, 70u8, + ], + ) + } + } + } + } + pub mod timestamp { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Set { + #[codec(compact)] + pub now: ::core::primitive::u64, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Set the current time."] + #[doc = ""] + #[doc = "This call should be invoked exactly once per block. It will panic at the finalization"] + #[doc = "phase, if this call hasn't been invoked by that time."] + #[doc = ""] + #[doc = "The timestamp should be greater than the previous one by the amount specified by"] + #[doc = "`MinimumPeriod`."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be `Inherent`."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(1)` (Note that implementations of `OnTimestampSet` must also be `O(1)`)"] + #[doc = "- 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in"] + #[doc = " `on_finalize`)"] + #[doc = "- 1 event handler `on_timestamp_set`. Must be `O(1)`."] + #[doc = "# "] + pub fn set( + &self, + now: ::core::primitive::u64, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Timestamp", + "set", + Set { now }, + [ + 6u8, 97u8, 172u8, 236u8, 118u8, 238u8, 228u8, 114u8, 15u8, 115u8, + 102u8, 85u8, 66u8, 151u8, 16u8, 33u8, 187u8, 17u8, 166u8, 88u8, 127u8, + 214u8, 182u8, 51u8, 168u8, 88u8, 43u8, 101u8, 185u8, 8u8, 1u8, 28u8, + ], + ) + } + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " Current time for the current block."] + pub fn now( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u64>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Timestamp", + "Now", + vec![], + [ + 148u8, 53u8, 50u8, 54u8, 13u8, 161u8, 57u8, 150u8, 16u8, 83u8, 144u8, + 221u8, 59u8, 75u8, 158u8, 130u8, 39u8, 123u8, 106u8, 134u8, 202u8, + 185u8, 83u8, 85u8, 60u8, 41u8, 120u8, 96u8, 210u8, 34u8, 2u8, 250u8, + ], + ) + } + #[doc = " Did the timestamp get updated in this block?"] + pub fn did_update( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Timestamp", + "DidUpdate", + vec![], + [ + 70u8, 13u8, 92u8, 186u8, 80u8, 151u8, 167u8, 90u8, 158u8, 232u8, 175u8, + 13u8, 103u8, 135u8, 2u8, 78u8, 16u8, 6u8, 39u8, 158u8, 167u8, 85u8, + 27u8, 47u8, 122u8, 73u8, 127u8, 26u8, 35u8, 168u8, 72u8, 204u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " The minimum period between blocks. Beware that this is different to the *expected*"] + #[doc = " period that the block production apparatus provides. Your chosen consensus system will"] + #[doc = " generally work with this to determine a sensible block time. e.g. For Aura, it will be"] + #[doc = " double this period on default settings."] + pub fn minimum_period( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u64>, + > { + ::subxt::constants::StaticConstantAddress::new( + "Timestamp", + "MinimumPeriod", + [ + 128u8, 214u8, 205u8, 242u8, 181u8, 142u8, 124u8, 231u8, 190u8, 146u8, + 59u8, 226u8, 157u8, 101u8, 103u8, 117u8, 249u8, 65u8, 18u8, 191u8, + 103u8, 119u8, 53u8, 85u8, 81u8, 96u8, 220u8, 42u8, 184u8, 239u8, 42u8, + 246u8, + ], + ) + } + } + } + } + pub mod sudo { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Sudo { + pub call: ::std::boxed::Box, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SudoUncheckedWeight { + pub call: ::std::boxed::Box, + pub weight: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetKey { + pub new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SudoAs { + pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pub call: ::std::boxed::Box, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- Limited storage reads."] + #[doc = "- One DB write (event)."] + #[doc = "- Weight of derivative `call` execution + 10,000."] + #[doc = "# "] + pub fn sudo( + &self, + call: runtime_types::rialto_parachain_runtime::RuntimeCall, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Sudo", + "sudo", + Sudo { call: ::std::boxed::Box::new(call) }, + [ + 229u8, 162u8, 204u8, 182u8, 225u8, 254u8, 3u8, 66u8, 233u8, 49u8, 60u8, + 73u8, 182u8, 192u8, 90u8, 122u8, 176u8, 63u8, 200u8, 64u8, 111u8, + 155u8, 223u8, 233u8, 51u8, 220u8, 157u8, 192u8, 74u8, 236u8, 150u8, + 222u8, + ], + ) + } + #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] + #[doc = "This function does not check the weight of the call, and instead allows the"] + #[doc = "Sudo user to specify the weight of the call."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- The weight of this call is defined by the caller."] + #[doc = "# "] + pub fn sudo_unchecked_weight( + &self, + call: runtime_types::rialto_parachain_runtime::RuntimeCall, + weight: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Sudo", + "sudo_unchecked_weight", + SudoUncheckedWeight { call: ::std::boxed::Box::new(call), weight }, + [ + 161u8, 202u8, 77u8, 33u8, 112u8, 211u8, 100u8, 184u8, 205u8, 250u8, + 70u8, 16u8, 39u8, 213u8, 108u8, 2u8, 195u8, 255u8, 15u8, 72u8, 142u8, + 180u8, 26u8, 203u8, 73u8, 81u8, 10u8, 29u8, 34u8, 101u8, 47u8, 99u8, + ], + ) + } + #[doc = "Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo"] + #[doc = "key."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- Limited storage reads."] + #[doc = "- One DB change."] + #[doc = "# "] + pub fn set_key( + &self, + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Sudo", + "set_key", + SetKey { new }, + [ + 23u8, 224u8, 218u8, 169u8, 8u8, 28u8, 111u8, 199u8, 26u8, 88u8, 225u8, + 105u8, 17u8, 19u8, 87u8, 156u8, 97u8, 67u8, 89u8, 173u8, 70u8, 0u8, + 5u8, 246u8, 198u8, 135u8, 182u8, 180u8, 44u8, 9u8, 212u8, 95u8, + ], + ) + } + #[doc = "Authenticates the sudo key and dispatches a function call with `Signed` origin from"] + #[doc = "a given account."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- Limited storage reads."] + #[doc = "- One DB write (event)."] + #[doc = "- Weight of derivative `call` execution + 10,000."] + #[doc = "# "] + pub fn sudo_as( + &self, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: runtime_types::rialto_parachain_runtime::RuntimeCall, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Sudo", + "sudo_as", + SudoAs { who, call: ::std::boxed::Box::new(call) }, + [ + 100u8, 104u8, 192u8, 203u8, 123u8, 243u8, 209u8, 131u8, 26u8, 247u8, + 84u8, 157u8, 133u8, 227u8, 210u8, 237u8, 58u8, 23u8, 139u8, 213u8, + 134u8, 19u8, 12u8, 31u8, 219u8, 212u8, 230u8, 37u8, 152u8, 199u8, + 220u8, 163u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_sudo::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A sudo just took place. \\[result\\]"] + pub struct Sudid { + pub sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + } + impl ::subxt::events::StaticEvent for Sudid { + const PALLET: &'static str = "Sudo"; + const EVENT: &'static str = "Sudid"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "The \\[sudoer\\] just switched identity; the old key is supplied if one existed."] + pub struct KeyChanged { + pub old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, + } + impl ::subxt::events::StaticEvent for KeyChanged { + const PALLET: &'static str = "Sudo"; + const EVENT: &'static str = "KeyChanged"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A sudo just took place. \\[result\\]"] + pub struct SudoAsDone { + pub sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + } + impl ::subxt::events::StaticEvent for SudoAsDone { + const PALLET: &'static str = "Sudo"; + const EVENT: &'static str = "SudoAsDone"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " The `AccountId` of the sudo key."] + pub fn key( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::sp_core::crypto::AccountId32>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Sudo", + "Key", + vec![], + [ + 244u8, 73u8, 188u8, 136u8, 218u8, 163u8, 68u8, 179u8, 122u8, 173u8, + 34u8, 108u8, 137u8, 28u8, 182u8, 16u8, 196u8, 92u8, 138u8, 34u8, 102u8, + 80u8, 199u8, 88u8, 107u8, 207u8, 36u8, 22u8, 168u8, 167u8, 20u8, 142u8, + ], + ) + } + } + } + } + pub mod randomness_collective_flip { + use super::{root_mod, runtime_types}; + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " Series of block headers from the last 81 blocks that acts as random seed material. This"] + #[doc = " is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of"] + #[doc = " the oldest hash."] + pub fn random_material( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + ::subxt::utils::H256, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "RandomnessCollectiveFlip", + "RandomMaterial", + vec![], + [ + 152u8, 126u8, 73u8, 88u8, 54u8, 147u8, 6u8, 19u8, 214u8, 40u8, 159u8, + 30u8, 236u8, 61u8, 240u8, 65u8, 178u8, 94u8, 146u8, 152u8, 135u8, + 252u8, 160u8, 86u8, 123u8, 114u8, 251u8, 140u8, 98u8, 143u8, 217u8, + 242u8, + ], + ) + } + } + } + } + pub mod transaction_payment { + use super::{root_mod, runtime_types}; + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_transaction_payment::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,"] + #[doc = "has been paid by `who`."] + pub struct TransactionFeePaid { + pub who: ::sp_core::crypto::AccountId32, + pub actual_fee: ::core::primitive::u128, + pub tip: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for TransactionFeePaid { + const PALLET: &'static str = "TransactionPayment"; + const EVENT: &'static str = "TransactionFeePaid"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + pub fn next_fee_multiplier( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_arithmetic::fixed_point::FixedU128, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "TransactionPayment", + "NextFeeMultiplier", + vec![], + [ + 210u8, 0u8, 206u8, 165u8, 183u8, 10u8, 206u8, 52u8, 14u8, 90u8, 218u8, + 197u8, 189u8, 125u8, 113u8, 216u8, 52u8, 161u8, 45u8, 24u8, 245u8, + 237u8, 121u8, 41u8, 106u8, 29u8, 45u8, 129u8, 250u8, 203u8, 206u8, + 180u8, + ], + ) + } + pub fn storage_version( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::pallet_transaction_payment::Releases, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "TransactionPayment", + "StorageVersion", + vec![], + [ + 219u8, 243u8, 82u8, 176u8, 65u8, 5u8, 132u8, 114u8, 8u8, 82u8, 176u8, + 200u8, 97u8, 150u8, 177u8, 164u8, 166u8, 11u8, 34u8, 12u8, 12u8, 198u8, + 58u8, 191u8, 186u8, 221u8, 221u8, 119u8, 181u8, 253u8, 154u8, 228u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " A fee mulitplier for `Operational` extrinsics to compute \"virtual tip\" to boost their"] + #[doc = " `priority`"] + #[doc = ""] + #[doc = " This value is multipled by the `final_fee` to obtain a \"virtual tip\" that is later"] + #[doc = " added to a tip component in regular `priority` calculations."] + #[doc = " It means that a `Normal` transaction can front-run a similarly-sized `Operational`"] + #[doc = " extrinsic (with no tip), by including a tip value greater than the virtual tip."] + #[doc = ""] + #[doc = " ```rust,ignore"] + #[doc = " // For `Normal`"] + #[doc = " let priority = priority_calc(tip);"] + #[doc = ""] + #[doc = " // For `Operational`"] + #[doc = " let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier;"] + #[doc = " let priority = priority_calc(tip + virtual_tip);"] + #[doc = " ```"] + #[doc = ""] + #[doc = " Note that since we use `final_fee` the multiplier applies also to the regular `tip`"] + #[doc = " sent with the transaction. So, not only does the transaction get a priority bump based"] + #[doc = " on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational`"] + #[doc = " transactions."] + pub fn operational_fee_multiplier( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u8>, + > { + ::subxt::constants::StaticConstantAddress::new( + "TransactionPayment", + "OperationalFeeMultiplier", + [ + 141u8, 130u8, 11u8, 35u8, 226u8, 114u8, 92u8, 179u8, 168u8, 110u8, + 28u8, 91u8, 221u8, 64u8, 4u8, 148u8, 201u8, 193u8, 185u8, 66u8, 226u8, + 114u8, 97u8, 79u8, 62u8, 212u8, 202u8, 114u8, 237u8, 228u8, 183u8, + 165u8, + ], + ) + } + } + } + } + pub mod parachain_system { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetValidationData { + pub data: + runtime_types::cumulus_primitives_parachain_inherent::ParachainInherentData, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SudoSendUpwardMessage { + pub message: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct AuthorizeUpgrade { + pub code_hash: ::subxt::utils::H256, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct EnactAuthorizedUpgrade { + pub code: ::std::vec::Vec<::core::primitive::u8>, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Set the current validation data."] + #[doc = ""] + #[doc = "This should be invoked exactly once per block. It will panic at the finalization"] + #[doc = "phase if the call was not invoked."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be `Inherent`"] + #[doc = ""] + #[doc = "As a side effect, this function upgrades the current validation function"] + #[doc = "if the appropriate time has come."] + pub fn set_validation_data( + &self, + data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "ParachainSystem", + "set_validation_data", + SetValidationData { data }, + [ + 200u8, 80u8, 163u8, 177u8, 184u8, 117u8, 61u8, 203u8, 244u8, 214u8, + 106u8, 151u8, 128u8, 131u8, 254u8, 120u8, 254u8, 76u8, 104u8, 39u8, + 215u8, 227u8, 233u8, 254u8, 26u8, 62u8, 17u8, 42u8, 19u8, 127u8, 108u8, + 242u8, + ], + ) + } + pub fn sudo_send_upward_message( + &self, + message: ::std::vec::Vec<::core::primitive::u8>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "ParachainSystem", + "sudo_send_upward_message", + SudoSendUpwardMessage { message }, + [ + 127u8, 79u8, 45u8, 183u8, 190u8, 205u8, 184u8, 169u8, 255u8, 191u8, + 86u8, 154u8, 134u8, 25u8, 249u8, 63u8, 47u8, 194u8, 108u8, 62u8, 60u8, + 170u8, 81u8, 240u8, 113u8, 48u8, 181u8, 171u8, 95u8, 63u8, 26u8, 222u8, + ], + ) + } + pub fn authorize_upgrade( + &self, + code_hash: ::subxt::utils::H256, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "ParachainSystem", + "authorize_upgrade", + AuthorizeUpgrade { code_hash }, + [ + 52u8, 152u8, 69u8, 207u8, 143u8, 113u8, 163u8, 11u8, 181u8, 182u8, + 124u8, 101u8, 207u8, 19u8, 59u8, 81u8, 129u8, 29u8, 79u8, 115u8, 90u8, + 83u8, 225u8, 124u8, 21u8, 108u8, 99u8, 194u8, 78u8, 83u8, 252u8, 163u8, + ], + ) + } + pub fn enact_authorized_upgrade( + &self, + code: ::std::vec::Vec<::core::primitive::u8>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "ParachainSystem", + "enact_authorized_upgrade", + EnactAuthorizedUpgrade { code }, + [ + 43u8, 157u8, 1u8, 230u8, 134u8, 72u8, 230u8, 35u8, 159u8, 13u8, 201u8, + 134u8, 184u8, 94u8, 167u8, 13u8, 108u8, 157u8, 145u8, 166u8, 119u8, + 37u8, 51u8, 121u8, 252u8, 255u8, 48u8, 251u8, 126u8, 152u8, 247u8, 5u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::cumulus_pallet_parachain_system::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "The validation function has been scheduled to apply."] + pub struct ValidationFunctionStored; + impl ::subxt::events::StaticEvent for ValidationFunctionStored { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "ValidationFunctionStored"; + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "The validation function was applied as of the contained relay chain block number."] + pub struct ValidationFunctionApplied { + pub relay_chain_block_num: ::core::primitive::u32, + } + impl ::subxt::events::StaticEvent for ValidationFunctionApplied { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "ValidationFunctionApplied"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "The relay-chain aborted the upgrade process."] + pub struct ValidationFunctionDiscarded; + impl ::subxt::events::StaticEvent for ValidationFunctionDiscarded { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "ValidationFunctionDiscarded"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An upgrade has been authorized."] + pub struct UpgradeAuthorized { + pub code_hash: ::subxt::utils::H256, + } + impl ::subxt::events::StaticEvent for UpgradeAuthorized { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "UpgradeAuthorized"; + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Some downward messages have been received and will be processed."] + pub struct DownwardMessagesReceived { + pub count: ::core::primitive::u32, + } + impl ::subxt::events::StaticEvent for DownwardMessagesReceived { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "DownwardMessagesReceived"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward messages were processed using the given weight."] + pub struct DownwardMessagesProcessed { + pub weight_used: ::sp_weights::Weight, + pub dmq_head: ::subxt::utils::H256, + } + impl ::subxt::events::StaticEvent for DownwardMessagesProcessed { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "DownwardMessagesProcessed"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An upward message was sent to the relay chain."] + pub struct UpwardMessageSent { + pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + } + impl ::subxt::events::StaticEvent for UpwardMessageSent { + const PALLET: &'static str = "ParachainSystem"; + const EVENT: &'static str = "UpwardMessageSent"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " In case of a scheduled upgrade, this storage field contains the validation code to be applied."] + #[doc = ""] + #[doc = " As soon as the relay chain gives us the go-ahead signal, we will overwrite the [`:code`][well_known_keys::CODE]"] + #[doc = " which will result the next block process with the new validation code. This concludes the upgrade process."] + #[doc = ""] + #[doc = " [well_known_keys::CODE]: sp_core::storage::well_known_keys::CODE"] + pub fn pending_validation_code( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "PendingValidationCode", + vec![], + [ + 162u8, 35u8, 108u8, 76u8, 160u8, 93u8, 215u8, 84u8, 20u8, 249u8, 57u8, + 187u8, 88u8, 161u8, 15u8, 131u8, 213u8, 89u8, 140u8, 20u8, 227u8, + 204u8, 79u8, 176u8, 114u8, 119u8, 8u8, 7u8, 64u8, 15u8, 90u8, 92u8, + ], + ) + } + #[doc = " Validation code that is set by the parachain and is to be communicated to collator and"] + #[doc = " consequently the relay-chain."] + #[doc = ""] + #[doc = " This will be cleared in `on_initialize` of each new block if no other pallet already set"] + #[doc = " the value."] + pub fn new_validation_code( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "NewValidationCode", + vec![], + [ + 224u8, 174u8, 53u8, 106u8, 240u8, 49u8, 48u8, 79u8, 219u8, 74u8, 142u8, + 166u8, 92u8, 204u8, 244u8, 200u8, 43u8, 169u8, 177u8, 207u8, 190u8, + 106u8, 180u8, 65u8, 245u8, 131u8, 134u8, 4u8, 53u8, 45u8, 76u8, 3u8, + ], + ) + } + #[doc = " The [`PersistedValidationData`] set for this block."] + #[doc = " This value is expected to be set only once per block and it's never stored"] + #[doc = " in the trie."] + pub fn validation_data( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::polkadot_primitives::v2::PersistedValidationData< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "ValidationData", + vec![], + [ + 112u8, 58u8, 240u8, 81u8, 219u8, 110u8, 244u8, 186u8, 251u8, 90u8, + 195u8, 217u8, 229u8, 102u8, 233u8, 24u8, 109u8, 96u8, 219u8, 72u8, + 139u8, 93u8, 58u8, 140u8, 40u8, 110u8, 167u8, 98u8, 199u8, 12u8, 138u8, + 131u8, + ], + ) + } + #[doc = " Were the validation data set to notify the relay chain?"] + pub fn did_set_validation_code( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "DidSetValidationCode", + vec![], + [ + 89u8, 83u8, 74u8, 174u8, 234u8, 188u8, 149u8, 78u8, 140u8, 17u8, 92u8, + 165u8, 243u8, 87u8, 59u8, 97u8, 135u8, 81u8, 192u8, 86u8, 193u8, 187u8, + 113u8, 22u8, 108u8, 83u8, 242u8, 208u8, 174u8, 40u8, 49u8, 245u8, + ], + ) + } + #[doc = " The relay chain block number associated with the last parachain block."] + pub fn last_relay_chain_block_number( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "LastRelayChainBlockNumber", + vec![], + [ + 68u8, 121u8, 6u8, 159u8, 181u8, 94u8, 151u8, 215u8, 225u8, 244u8, 4u8, + 158u8, 216u8, 85u8, 55u8, 228u8, 197u8, 35u8, 200u8, 33u8, 29u8, 182u8, + 17u8, 83u8, 59u8, 63u8, 25u8, 180u8, 132u8, 23u8, 97u8, 252u8, + ], + ) + } + #[doc = " An option which indicates if the relay-chain restricts signalling a validation code upgrade."] + #[doc = " In other words, if this is `Some` and [`NewValidationCode`] is `Some` then the produced"] + #[doc = " candidate will be invalid."] + #[doc = ""] + #[doc = " This storage item is a mirror of the corresponding value for the current parachain from the"] + #[doc = " relay-chain. This value is ephemeral which means it doesn't hit the storage. This value is"] + #[doc = " set after the inherent."] + pub fn upgrade_restriction_signal( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::core::option::Option< + runtime_types::polkadot_primitives::v2::UpgradeRestriction, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "UpgradeRestrictionSignal", + vec![], + [ + 61u8, 3u8, 26u8, 6u8, 88u8, 114u8, 109u8, 63u8, 7u8, 115u8, 245u8, + 198u8, 73u8, 234u8, 28u8, 228u8, 126u8, 27u8, 151u8, 18u8, 133u8, 54u8, + 144u8, 149u8, 246u8, 43u8, 83u8, 47u8, 77u8, 238u8, 10u8, 196u8, + ], + ) + } + #[doc = " The state proof for the last relay parent block."] + #[doc = ""] + #[doc = " This field is meant to be updated each block with the validation data inherent. Therefore,"] + #[doc = " before processing of the inherent, e.g. in `on_initialize` this data may be stale."] + #[doc = ""] + #[doc = " This data is also absent from the genesis."] + pub fn relay_state_proof( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_trie::storage_proof::StorageProof, + >, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "RelayStateProof", + vec![], + [ + 35u8, 124u8, 167u8, 221u8, 162u8, 145u8, 158u8, 186u8, 57u8, 154u8, + 225u8, 6u8, 176u8, 13u8, 178u8, 195u8, 209u8, 122u8, 221u8, 26u8, + 155u8, 126u8, 153u8, 246u8, 101u8, 221u8, 61u8, 145u8, 211u8, 236u8, + 48u8, 130u8, + ], + ) + } + #[doc = " The snapshot of some state related to messaging relevant to the current parachain as per"] + #[doc = " the relay parent."] + #[doc = ""] + #[doc = " This field is meant to be updated each block with the validation data inherent. Therefore,"] + #[doc = " before processing of the inherent, e.g. in `on_initialize` this data may be stale."] + #[doc = ""] + #[doc = " This data is also absent from the genesis."] pub fn relevant_messaging_state (& self ,) -> :: subxt :: storage :: address :: StaticStorageAddress :: < :: subxt :: metadata :: DecodeStaticType < runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: MessagingStateSnapshot > , :: subxt :: storage :: address :: Yes , () , () >{ + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "RelevantMessagingState", + vec![], + [ + 68u8, 241u8, 114u8, 83u8, 200u8, 99u8, 8u8, 244u8, 110u8, 134u8, 106u8, + 153u8, 17u8, 90u8, 184u8, 157u8, 100u8, 140u8, 157u8, 83u8, 25u8, + 166u8, 173u8, 31u8, 221u8, 24u8, 236u8, 85u8, 176u8, 223u8, 237u8, + 65u8, + ], + ) + } + #[doc = " The parachain host configuration that was obtained from the relay parent."] + #[doc = ""] + #[doc = " This field is meant to be updated each block with the validation data inherent. Therefore,"] + #[doc = " before processing of the inherent, e.g. in `on_initialize` this data may be stale."] + #[doc = ""] + #[doc = " This data is also absent from the genesis."] + pub fn host_configuration( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::polkadot_primitives::v2::AbridgedHostConfiguration, + >, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "HostConfiguration", + vec![], + [ + 104u8, 200u8, 30u8, 202u8, 119u8, 204u8, 233u8, 20u8, 67u8, 199u8, + 47u8, 166u8, 254u8, 152u8, 10u8, 187u8, 240u8, 255u8, 148u8, 201u8, + 134u8, 41u8, 130u8, 201u8, 112u8, 65u8, 68u8, 103u8, 56u8, 123u8, + 178u8, 113u8, + ], + ) + } + #[doc = " The last downward message queue chain head we have observed."] + #[doc = ""] + #[doc = " This value is loaded before and saved after processing inbound downward messages carried"] + #[doc = " by the system inherent."] + pub fn last_dmq_mqc_head( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::cumulus_primitives_parachain_inherent::MessageQueueChain, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "LastDmqMqcHead", + vec![], + [ + 176u8, 255u8, 246u8, 125u8, 36u8, 120u8, 24u8, 44u8, 26u8, 64u8, 236u8, + 210u8, 189u8, 237u8, 50u8, 78u8, 45u8, 139u8, 58u8, 141u8, 112u8, + 253u8, 178u8, 198u8, 87u8, 71u8, 77u8, 248u8, 21u8, 145u8, 187u8, 52u8, + ], + ) + } + #[doc = " The message queue chain heads we have observed per each channel incoming channel."] + #[doc = ""] + #[doc = " This value is loaded before and saved after processing inbound downward messages carried"] + #[doc = " by the system inherent."] + pub fn last_hrmp_mqc_heads( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::subxt::utils::KeyedVec< + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::cumulus_primitives_parachain_inherent::MessageQueueChain, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "LastHrmpMqcHeads", + vec![], + [ + 55u8, 179u8, 35u8, 16u8, 173u8, 0u8, 122u8, 179u8, 236u8, 98u8, 9u8, + 112u8, 11u8, 219u8, 241u8, 89u8, 131u8, 198u8, 64u8, 139u8, 103u8, + 158u8, 77u8, 107u8, 83u8, 236u8, 255u8, 208u8, 47u8, 61u8, 219u8, + 240u8, + ], + ) + } + #[doc = " Number of downward messages processed in a block."] + #[doc = ""] + #[doc = " This will be cleared in `on_initialize` of each new block."] + pub fn processed_downward_messages( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "ProcessedDownwardMessages", + vec![], + [ + 48u8, 177u8, 84u8, 228u8, 101u8, 235u8, 181u8, 27u8, 66u8, 55u8, 50u8, + 146u8, 245u8, 223u8, 77u8, 132u8, 178u8, 80u8, 74u8, 90u8, 166u8, 81u8, + 109u8, 25u8, 91u8, 69u8, 5u8, 69u8, 123u8, 197u8, 160u8, 146u8, + ], + ) + } + #[doc = " HRMP watermark that was set in a block."] + #[doc = ""] + #[doc = " This will be cleared in `on_initialize` of each new block."] + pub fn hrmp_watermark( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "HrmpWatermark", + vec![], + [ + 189u8, 59u8, 183u8, 195u8, 69u8, 185u8, 241u8, 226u8, 62u8, 204u8, + 230u8, 77u8, 102u8, 75u8, 86u8, 157u8, 249u8, 140u8, 219u8, 72u8, 94u8, + 64u8, 176u8, 72u8, 34u8, 205u8, 114u8, 103u8, 231u8, 233u8, 206u8, + 111u8, + ], + ) + } + #[doc = " HRMP messages that were sent in a block."] + #[doc = ""] + #[doc = " This will be cleared in `on_initialize` of each new block."] + pub fn hrmp_outbound_messages( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain::primitives::Id, + >, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "HrmpOutboundMessages", + vec![], + [ + 74u8, 86u8, 173u8, 248u8, 90u8, 230u8, 71u8, 225u8, 127u8, 164u8, + 221u8, 62u8, 146u8, 13u8, 73u8, 9u8, 98u8, 168u8, 6u8, 14u8, 97u8, + 166u8, 45u8, 70u8, 62u8, 210u8, 9u8, 32u8, 83u8, 18u8, 4u8, 201u8, + ], + ) + } + #[doc = " Upward messages that were sent in a block."] + #[doc = ""] + #[doc = " This will be cleared in `on_initialize` of each new block."] + pub fn upward_messages( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "UpwardMessages", + vec![], + [ + 129u8, 208u8, 187u8, 36u8, 48u8, 108u8, 135u8, 56u8, 204u8, 60u8, + 100u8, 158u8, 113u8, 238u8, 46u8, 92u8, 228u8, 41u8, 178u8, 177u8, + 208u8, 195u8, 148u8, 149u8, 127u8, 21u8, 93u8, 92u8, 29u8, 115u8, 10u8, + 248u8, + ], + ) + } + #[doc = " Upward messages that are still pending and not yet send to the relay chain."] + pub fn pending_upward_messages( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "PendingUpwardMessages", + vec![], + [ + 223u8, 46u8, 224u8, 227u8, 222u8, 119u8, 225u8, 244u8, 59u8, 87u8, + 127u8, 19u8, 217u8, 237u8, 103u8, 61u8, 6u8, 210u8, 107u8, 201u8, + 117u8, 25u8, 85u8, 248u8, 36u8, 231u8, 28u8, 202u8, 41u8, 140u8, 208u8, + 254u8, + ], + ) + } + #[doc = " The number of HRMP messages we observed in `on_initialize` and thus used that number for"] + #[doc = " announcing the weight of `on_initialize` and `on_finalize`."] + pub fn announced_hrmp_messages_per_candidate( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "AnnouncedHrmpMessagesPerCandidate", + vec![], + [ + 132u8, 61u8, 162u8, 129u8, 251u8, 243u8, 20u8, 144u8, 162u8, 73u8, + 237u8, 51u8, 248u8, 41u8, 127u8, 171u8, 180u8, 79u8, 137u8, 23u8, 66u8, + 134u8, 106u8, 222u8, 182u8, 154u8, 0u8, 145u8, 184u8, 156u8, 36u8, + 97u8, + ], + ) + } + #[doc = " The weight we reserve at the beginning of the block for processing XCMP messages. This"] + #[doc = " overrides the amount set in the Config trait."] + pub fn reserved_xcmp_weight_override( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::sp_weights::Weight>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "ReservedXcmpWeightOverride", + vec![], + [ + 180u8, 90u8, 34u8, 178u8, 1u8, 242u8, 211u8, 97u8, 100u8, 34u8, 39u8, + 42u8, 142u8, 249u8, 236u8, 194u8, 244u8, 164u8, 96u8, 54u8, 98u8, 46u8, + 92u8, 196u8, 185u8, 51u8, 231u8, 234u8, 249u8, 143u8, 244u8, 64u8, + ], + ) + } + #[doc = " The weight we reserve at the beginning of the block for processing DMP messages. This"] + #[doc = " overrides the amount set in the Config trait."] + pub fn reserved_dmp_weight_override( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::sp_weights::Weight>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "ReservedDmpWeightOverride", + vec![], + [ + 90u8, 122u8, 168u8, 240u8, 95u8, 195u8, 160u8, 109u8, 175u8, 170u8, + 227u8, 44u8, 139u8, 176u8, 32u8, 161u8, 57u8, 233u8, 56u8, 55u8, 123u8, + 168u8, 174u8, 96u8, 159u8, 62u8, 186u8, 186u8, 17u8, 70u8, 57u8, 246u8, + ], + ) + } + #[doc = " The next authorized upgrade, if there is one."] + pub fn authorized_upgrade( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "AuthorizedUpgrade", + vec![], + [ + 136u8, 238u8, 241u8, 144u8, 252u8, 61u8, 101u8, 171u8, 234u8, 160u8, + 145u8, 210u8, 69u8, 29u8, 204u8, 166u8, 250u8, 101u8, 254u8, 32u8, + 96u8, 197u8, 222u8, 212u8, 50u8, 189u8, 25u8, 7u8, 48u8, 183u8, 234u8, + 95u8, + ], + ) + } + #[doc = " A custom head data that should be returned as result of `validate_block`."] + #[doc = ""] + #[doc = " See [`Pallet::set_custom_validation_head_data`] for more information."] + pub fn custom_validation_head_data( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainSystem", + "CustomValidationHeadData", + vec![], + [ + 189u8, 150u8, 234u8, 128u8, 111u8, 27u8, 173u8, 92u8, 109u8, 4u8, 98u8, + 103u8, 158u8, 19u8, 16u8, 5u8, 107u8, 135u8, 126u8, 170u8, 62u8, 64u8, + 149u8, 80u8, 33u8, 17u8, 83u8, 22u8, 176u8, 118u8, 26u8, 223u8, + ], + ) + } + } + } + } + pub mod parachain_info { + use super::{root_mod, runtime_types}; + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + pub fn parachain_id( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::polkadot_parachain::primitives::Id, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "ParachainInfo", + "ParachainId", + vec![], + [ + 151u8, 191u8, 241u8, 118u8, 192u8, 47u8, 166u8, 151u8, 217u8, 240u8, + 165u8, 232u8, 51u8, 113u8, 243u8, 1u8, 89u8, 240u8, 11u8, 1u8, 77u8, + 104u8, 12u8, 56u8, 17u8, 135u8, 214u8, 19u8, 114u8, 135u8, 66u8, 76u8, + ], + ) + } + } + } + } + pub mod balances { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Transfer { + pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + pub value: ::core::primitive::u128, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetBalance { + pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + pub new_free: ::core::primitive::u128, + #[codec(compact)] + pub new_reserved: ::core::primitive::u128, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceTransfer { + pub source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + pub value: ::core::primitive::u128, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct TransferKeepAlive { + pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + pub value: ::core::primitive::u128, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct TransferAll { + pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pub keep_alive: ::core::primitive::bool, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceUnreserve { + pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pub amount: ::core::primitive::u128, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Transfer some liquid free balance to another account."] + #[doc = ""] + #[doc = "`transfer` will set the `FreeBalance` of the sender and receiver."] + #[doc = "If the sender's account is below the existential deposit as a result"] + #[doc = "of the transfer, the account will be reaped."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be `Signed` by the transactor."] + #[doc = ""] + #[doc = "# "] + #[doc = "- Dependent on arguments but not critical, given proper implementations for input config"] + #[doc = " types. See related functions below."] + #[doc = "- It contains a limited number of reads and writes internally and no complex"] + #[doc = " computation."] + #[doc = ""] + #[doc = "Related functions:"] + #[doc = ""] + #[doc = " - `ensure_can_withdraw` is always called internally but has a bounded complexity."] + #[doc = " - Transferring balances to accounts that did not exist before will cause"] + #[doc = " `T::OnNewAccount::on_new_account` to be called."] + #[doc = " - Removing enough funds from an account will trigger `T::DustRemoval::on_unbalanced`."] + #[doc = " - `transfer_keep_alive` works the same way as `transfer`, but has an additional check"] + #[doc = " that the transfer will not kill the origin account."] + #[doc = "---------------------------------"] + #[doc = "- Origin account is already in memory, so no DB operations for them."] + #[doc = "# "] + pub fn transfer( + &self, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + value: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "transfer", + Transfer { dest, value }, + [ + 111u8, 222u8, 32u8, 56u8, 171u8, 77u8, 252u8, 29u8, 194u8, 155u8, + 200u8, 192u8, 198u8, 81u8, 23u8, 115u8, 236u8, 91u8, 218u8, 114u8, + 107u8, 141u8, 138u8, 100u8, 237u8, 21u8, 58u8, 172u8, 3u8, 20u8, 216u8, + 38u8, + ], + ) + } + #[doc = "Set the balances of a given account."] + #[doc = ""] + #[doc = "This will alter `FreeBalance` and `ReservedBalance` in storage. it will"] + #[doc = "also alter the total issuance of the system (`TotalIssuance`) appropriately."] + #[doc = "If the new free or reserved balance is below the existential deposit,"] + #[doc = "it will reset the account nonce (`frame_system::AccountNonce`)."] + #[doc = ""] + #[doc = "The dispatch origin for this call is `root`."] + pub fn set_balance( + &self, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + new_free: ::core::primitive::u128, + new_reserved: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "set_balance", + SetBalance { who, new_free, new_reserved }, + [ + 234u8, 215u8, 97u8, 98u8, 243u8, 199u8, 57u8, 76u8, 59u8, 161u8, 118u8, + 207u8, 34u8, 197u8, 198u8, 61u8, 231u8, 210u8, 169u8, 235u8, 150u8, + 137u8, 173u8, 49u8, 28u8, 77u8, 84u8, 149u8, 143u8, 210u8, 139u8, + 193u8, + ], + ) + } + #[doc = "Exactly as `transfer`, except the origin must be root and the source account may be"] + #[doc = "specified."] + #[doc = "# "] + #[doc = "- Same as transfer, but additional read and write because the source account is not"] + #[doc = " assumed to be in the overlay."] + #[doc = "# "] + pub fn force_transfer( + &self, + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + value: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "force_transfer", + ForceTransfer { source, dest, value }, + [ + 79u8, 174u8, 212u8, 108u8, 184u8, 33u8, 170u8, 29u8, 232u8, 254u8, + 195u8, 218u8, 221u8, 134u8, 57u8, 99u8, 6u8, 70u8, 181u8, 227u8, 56u8, + 239u8, 243u8, 158u8, 157u8, 245u8, 36u8, 162u8, 11u8, 237u8, 147u8, + 15u8, + ], + ) + } + #[doc = "Same as the [`transfer`] call, but with a check that the transfer will not kill the"] + #[doc = "origin account."] + #[doc = ""] + #[doc = "99% of the time you want [`transfer`] instead."] + #[doc = ""] + #[doc = "[`transfer`]: struct.Pallet.html#method.transfer"] + pub fn transfer_keep_alive( + &self, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + value: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "transfer_keep_alive", + TransferKeepAlive { dest, value }, + [ + 112u8, 179u8, 75u8, 168u8, 193u8, 221u8, 9u8, 82u8, 190u8, 113u8, + 253u8, 13u8, 130u8, 134u8, 170u8, 216u8, 136u8, 111u8, 242u8, 220u8, + 202u8, 112u8, 47u8, 79u8, 73u8, 244u8, 226u8, 59u8, 240u8, 188u8, + 210u8, 208u8, + ], + ) + } + #[doc = "Transfer the entire transferable balance from the caller account."] + #[doc = ""] + #[doc = "NOTE: This function only attempts to transfer _transferable_ balances. This means that"] + #[doc = "any locked, reserved, or existential deposits (when `keep_alive` is `true`), will not be"] + #[doc = "transferred by this function. To ensure that this function results in a killed account,"] + #[doc = "you might need to prepare the account by removing any reference counters, storage"] + #[doc = "deposits, etc..."] + #[doc = ""] + #[doc = "The dispatch origin of this call must be Signed."] + #[doc = ""] + #[doc = "- `dest`: The recipient of the transfer."] + #[doc = "- `keep_alive`: A boolean to determine if the `transfer_all` operation should send all"] + #[doc = " of the funds the account has, causing the sender account to be killed (false), or"] + #[doc = " transfer everything except at least the existential deposit, which will guarantee to"] + #[doc = " keep the sender account alive (true). # "] + #[doc = "- O(1). Just like transfer, but reading the user's transferable balance first."] + #[doc = " #"] + pub fn transfer_all( + &self, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "transfer_all", + TransferAll { dest, keep_alive }, + [ + 46u8, 129u8, 29u8, 177u8, 221u8, 107u8, 245u8, 69u8, 238u8, 126u8, + 145u8, 26u8, 219u8, 208u8, 14u8, 80u8, 149u8, 1u8, 214u8, 63u8, 67u8, + 201u8, 144u8, 45u8, 129u8, 145u8, 174u8, 71u8, 238u8, 113u8, 208u8, + 34u8, + ], + ) + } + #[doc = "Unreserve some balance from a user by force."] + #[doc = ""] + #[doc = "Can only be called by ROOT."] + pub fn force_unreserve( + &self, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "force_unreserve", + ForceUnreserve { who, amount }, + [ + 160u8, 146u8, 137u8, 76u8, 157u8, 187u8, 66u8, 148u8, 207u8, 76u8, + 32u8, 254u8, 82u8, 215u8, 35u8, 161u8, 213u8, 52u8, 32u8, 98u8, 102u8, + 106u8, 234u8, 123u8, 6u8, 175u8, 184u8, 188u8, 174u8, 106u8, 176u8, + 78u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_balances::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An account was created with some free balance."] + pub struct Endowed { + pub account: ::sp_core::crypto::AccountId32, + pub free_balance: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Endowed { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Endowed"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An account was removed whose balance was non-zero but below ExistentialDeposit,"] + #[doc = "resulting in an outright loss."] + pub struct DustLost { + pub account: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for DustLost { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "DustLost"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Transfer succeeded."] + pub struct Transfer { + pub from: ::sp_core::crypto::AccountId32, + pub to: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Transfer { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Transfer"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A balance was set by root."] + pub struct BalanceSet { + pub who: ::sp_core::crypto::AccountId32, + pub free: ::core::primitive::u128, + pub reserved: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for BalanceSet { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "BalanceSet"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some balance was reserved (moved from free to reserved)."] + pub struct Reserved { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Reserved { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Reserved"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some balance was unreserved (moved from reserved to free)."] + pub struct Unreserved { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Unreserved { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Unreserved"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some balance was moved from the reserve of the first account to the second account."] + #[doc = "Final argument indicates the destination balance type."] + pub struct ReserveRepatriated { + pub from: ::sp_core::crypto::AccountId32, + pub to: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + pub destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + } + impl ::subxt::events::StaticEvent for ReserveRepatriated { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "ReserveRepatriated"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was deposited (e.g. for transaction fees)."] + pub struct Deposit { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Deposit { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Deposit"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was withdrawn from the account (e.g. for transaction fees)."] + pub struct Withdraw { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Withdraw { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Withdraw"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was removed from the account (e.g. for misbehavior)."] + pub struct Slashed { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Slashed { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Slashed"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " The total units issued in the system."] + pub fn total_issuance( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "TotalIssuance", + vec![], + [ + 1u8, 206u8, 252u8, 237u8, 6u8, 30u8, 20u8, 232u8, 164u8, 115u8, 51u8, + 156u8, 156u8, 206u8, 241u8, 187u8, 44u8, 84u8, 25u8, 164u8, 235u8, + 20u8, 86u8, 242u8, 124u8, 23u8, 28u8, 140u8, 26u8, 73u8, 231u8, 51u8, + ], + ) + } + #[doc = " The total units of outstanding deactivated balance in the system."] + pub fn inactive_issuance( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "InactiveIssuance", + vec![], + [ + 74u8, 203u8, 111u8, 142u8, 225u8, 104u8, 173u8, 51u8, 226u8, 12u8, + 85u8, 135u8, 41u8, 206u8, 177u8, 238u8, 94u8, 246u8, 184u8, 250u8, + 140u8, 213u8, 91u8, 118u8, 163u8, 111u8, 211u8, 46u8, 204u8, 160u8, + 154u8, 21u8, + ], + ) + } + #[doc = " The Balances pallet example of storing the balance of an account."] + #[doc = ""] + #[doc = " # Example"] + #[doc = ""] + #[doc = " ```nocompile"] + #[doc = " impl pallet_balances::Config for Runtime {"] + #[doc = " type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData>"] + #[doc = " }"] + #[doc = " ```"] + #[doc = ""] + #[doc = " You can also store the balance of an account in the `System` pallet."] + #[doc = ""] + #[doc = " # Example"] + #[doc = ""] + #[doc = " ```nocompile"] + #[doc = " impl pallet_balances::Config for Runtime {"] + #[doc = " type AccountStore = System"] + #[doc = " }"] + #[doc = " ```"] + #[doc = ""] + #[doc = " But this comes with tradeoffs, storing account balances in the system pallet stores"] + #[doc = " `frame_system` data alongside the account data contrary to storing account balances in the"] + #[doc = " `Balances` pallet, which uses a `StorageMap` to store balances data only."] + #[doc = " NOTE: This is only used in the case that this pallet is used to store balances."] + pub fn account( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Account", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 246u8, 154u8, 253u8, 71u8, 192u8, 192u8, 192u8, 236u8, 128u8, 80u8, + 40u8, 252u8, 201u8, 43u8, 3u8, 131u8, 19u8, 49u8, 141u8, 240u8, 172u8, + 217u8, 215u8, 109u8, 87u8, 135u8, 248u8, 57u8, 98u8, 185u8, 22u8, 4u8, + ], + ) + } + #[doc = " The Balances pallet example of storing the balance of an account."] + #[doc = ""] + #[doc = " # Example"] + #[doc = ""] + #[doc = " ```nocompile"] + #[doc = " impl pallet_balances::Config for Runtime {"] + #[doc = " type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData>"] + #[doc = " }"] + #[doc = " ```"] + #[doc = ""] + #[doc = " You can also store the balance of an account in the `System` pallet."] + #[doc = ""] + #[doc = " # Example"] + #[doc = ""] + #[doc = " ```nocompile"] + #[doc = " impl pallet_balances::Config for Runtime {"] + #[doc = " type AccountStore = System"] + #[doc = " }"] + #[doc = " ```"] + #[doc = ""] + #[doc = " But this comes with tradeoffs, storing account balances in the system pallet stores"] + #[doc = " `frame_system` data alongside the account data contrary to storing account balances in the"] + #[doc = " `Balances` pallet, which uses a `StorageMap` to store balances data only."] + #[doc = " NOTE: This is only used in the case that this pallet is used to store balances."] + pub fn account_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Account", + Vec::new(), + [ + 246u8, 154u8, 253u8, 71u8, 192u8, 192u8, 192u8, 236u8, 128u8, 80u8, + 40u8, 252u8, 201u8, 43u8, 3u8, 131u8, 19u8, 49u8, 141u8, 240u8, 172u8, + 217u8, 215u8, 109u8, 87u8, 135u8, 248u8, 57u8, 98u8, 185u8, 22u8, 4u8, + ], + ) + } + #[doc = " Any liquidity locks on some account balances."] + #[doc = " NOTE: Should only be accessed when setting, changing and freeing a lock."] + pub fn locks( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + runtime_types::pallet_balances::BalanceLock<::core::primitive::u128>, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Locks", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 216u8, 253u8, 87u8, 73u8, 24u8, 218u8, 35u8, 0u8, 244u8, 134u8, 195u8, + 58u8, 255u8, 64u8, 153u8, 212u8, 210u8, 232u8, 4u8, 122u8, 90u8, 212u8, + 136u8, 14u8, 127u8, 232u8, 8u8, 192u8, 40u8, 233u8, 18u8, 250u8, + ], + ) + } + #[doc = " Any liquidity locks on some account balances."] + #[doc = " NOTE: Should only be accessed when setting, changing and freeing a lock."] + pub fn locks_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + runtime_types::pallet_balances::BalanceLock<::core::primitive::u128>, + >, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Locks", + Vec::new(), + [ + 216u8, 253u8, 87u8, 73u8, 24u8, 218u8, 35u8, 0u8, 244u8, 134u8, 195u8, + 58u8, 255u8, 64u8, 153u8, 212u8, 210u8, 232u8, 4u8, 122u8, 90u8, 212u8, + 136u8, 14u8, 127u8, 232u8, 8u8, 192u8, 40u8, 233u8, 18u8, 250u8, + ], + ) + } + #[doc = " Named reserves on some account balances."] + pub fn reserves( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + runtime_types::pallet_balances::ReserveData< + [::core::primitive::u8; 8usize], + ::core::primitive::u128, + >, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Reserves", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 17u8, 32u8, 191u8, 46u8, 76u8, 220u8, 101u8, 100u8, 42u8, 250u8, 128u8, + 167u8, 117u8, 44u8, 85u8, 96u8, 105u8, 216u8, 16u8, 147u8, 74u8, 55u8, + 183u8, 94u8, 160u8, 177u8, 26u8, 187u8, 71u8, 197u8, 187u8, 163u8, + ], + ) + } + #[doc = " Named reserves on some account balances."] + pub fn reserves_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + runtime_types::pallet_balances::ReserveData< + [::core::primitive::u8; 8usize], + ::core::primitive::u128, + >, + >, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Reserves", + Vec::new(), + [ + 17u8, 32u8, 191u8, 46u8, 76u8, 220u8, 101u8, 100u8, 42u8, 250u8, 128u8, + 167u8, 117u8, 44u8, 85u8, 96u8, 105u8, 216u8, 16u8, 147u8, 74u8, 55u8, + 183u8, 94u8, 160u8, 177u8, 26u8, 187u8, 71u8, 197u8, 187u8, 163u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " The minimum amount required to keep an account open."] + pub fn existential_deposit( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, + > { + ::subxt::constants::StaticConstantAddress::new( + "Balances", + "ExistentialDeposit", + [ + 84u8, 157u8, 140u8, 4u8, 93u8, 57u8, 29u8, 133u8, 105u8, 200u8, 214u8, + 27u8, 144u8, 208u8, 218u8, 160u8, 130u8, 109u8, 101u8, 54u8, 210u8, + 136u8, 71u8, 63u8, 49u8, 237u8, 234u8, 15u8, 178u8, 98u8, 148u8, 156u8, + ], + ) + } + #[doc = " The maximum number of locks that should exist on an account."] + #[doc = " Not strictly enforced, but used for weight estimation."] + pub fn max_locks( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "Balances", + "MaxLocks", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " The maximum number of named reserves that can exist on an account."] + pub fn max_reserves( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "Balances", + "MaxReserves", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + } + } + } + pub mod aura { + use super::{root_mod, runtime_types}; + } + pub mod aura_ext { + use super::{root_mod, runtime_types}; + } + pub mod xcmp_queue { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ServiceOverweight { + pub index: ::core::primitive::u64, + pub weight_limit: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SuspendXcmExecution; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ResumeXcmExecution; + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct UpdateSuspendThreshold { + pub new: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct UpdateDropThreshold { + pub new: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct UpdateResumeThreshold { + pub new: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct UpdateThresholdWeight { + pub new: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct UpdateWeightRestrictDecay { + pub new: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct UpdateXcmpMaxIndividualWeight { + pub new: ::sp_weights::Weight, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Services a single overweight XCM."] + #[doc = ""] + #[doc = "- `origin`: Must pass `ExecuteOverweightOrigin`."] + #[doc = "- `index`: The index of the overweight XCM to service"] + #[doc = "- `weight_limit`: The amount of weight that XCM execution may take."] + #[doc = ""] + #[doc = "Errors:"] + #[doc = "- `BadOverweightIndex`: XCM under `index` is not found in the `Overweight` storage map."] + #[doc = "- `BadXcm`: XCM under `index` cannot be properly decoded into a valid XCM format."] + #[doc = "- `WeightOverLimit`: XCM execution may use greater `weight_limit`."] + #[doc = ""] + #[doc = "Events:"] + #[doc = "- `OverweightServiced`: On success."] + pub fn service_overweight( + &self, + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "service_overweight", + ServiceOverweight { index, weight_limit }, + [ + 121u8, 236u8, 235u8, 23u8, 210u8, 238u8, 238u8, 122u8, 15u8, 86u8, + 34u8, 119u8, 105u8, 100u8, 214u8, 236u8, 117u8, 39u8, 254u8, 235u8, + 189u8, 15u8, 72u8, 74u8, 225u8, 134u8, 148u8, 126u8, 31u8, 203u8, + 144u8, 106u8, + ], + ) + } + #[doc = "Suspends all XCM executions for the XCMP queue, regardless of the sender's origin."] + #[doc = ""] + #[doc = "- `origin`: Must pass `ControllerOrigin`."] + pub fn suspend_xcm_execution( + &self, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "suspend_xcm_execution", + SuspendXcmExecution {}, + [ + 139u8, 76u8, 166u8, 86u8, 106u8, 144u8, 16u8, 47u8, 105u8, 185u8, 7u8, + 7u8, 63u8, 14u8, 250u8, 236u8, 99u8, 121u8, 101u8, 143u8, 28u8, 175u8, + 108u8, 197u8, 226u8, 43u8, 103u8, 92u8, 186u8, 12u8, 51u8, 153u8, + ], + ) + } + #[doc = "Resumes all XCM executions for the XCMP queue."] + #[doc = ""] + #[doc = "Note that this function doesn't change the status of the in/out bound channels."] + #[doc = ""] + #[doc = "- `origin`: Must pass `ControllerOrigin`."] + pub fn resume_xcm_execution( + &self, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "resume_xcm_execution", + ResumeXcmExecution {}, + [ + 67u8, 111u8, 47u8, 237u8, 79u8, 42u8, 90u8, 56u8, 245u8, 2u8, 20u8, + 23u8, 33u8, 121u8, 135u8, 50u8, 204u8, 147u8, 195u8, 80u8, 177u8, + 202u8, 8u8, 160u8, 164u8, 138u8, 64u8, 252u8, 178u8, 63u8, 102u8, + 245u8, + ], + ) + } + #[doc = "Overwrites the number of pages of messages which must be in the queue for the other side to be told to"] + #[doc = "suspend their sending."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.suspend_value`"] + pub fn update_suspend_threshold( + &self, + new: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "update_suspend_threshold", + UpdateSuspendThreshold { new }, + [ + 155u8, 120u8, 9u8, 228u8, 110u8, 62u8, 233u8, 36u8, 57u8, 85u8, 19u8, + 67u8, 246u8, 88u8, 81u8, 116u8, 243u8, 236u8, 174u8, 130u8, 8u8, 246u8, + 254u8, 97u8, 155u8, 207u8, 123u8, 60u8, 164u8, 14u8, 196u8, 97u8, + ], + ) + } + #[doc = "Overwrites the number of pages of messages which must be in the queue after which we drop any further"] + #[doc = "messages from the channel."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.drop_threshold`"] + pub fn update_drop_threshold( + &self, + new: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "update_drop_threshold", + UpdateDropThreshold { new }, + [ + 146u8, 177u8, 164u8, 96u8, 247u8, 182u8, 229u8, 175u8, 194u8, 101u8, + 186u8, 168u8, 94u8, 114u8, 172u8, 119u8, 35u8, 222u8, 175u8, 21u8, + 67u8, 61u8, 216u8, 144u8, 194u8, 10u8, 181u8, 62u8, 166u8, 198u8, + 138u8, 243u8, + ], + ) + } + #[doc = "Overwrites the number of pages of messages which the queue must be reduced to before it signals that"] + #[doc = "message sending may recommence after it has been suspended."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.resume_threshold`"] + pub fn update_resume_threshold( + &self, + new: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "update_resume_threshold", + UpdateResumeThreshold { new }, + [ + 231u8, 128u8, 80u8, 179u8, 61u8, 50u8, 103u8, 209u8, 103u8, 55u8, + 101u8, 113u8, 150u8, 10u8, 202u8, 7u8, 0u8, 77u8, 58u8, 4u8, 227u8, + 17u8, 225u8, 112u8, 121u8, 203u8, 184u8, 113u8, 231u8, 156u8, 174u8, + 154u8, + ], + ) + } + #[doc = "Overwrites the amount of remaining weight under which we stop processing messages."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.threshold_weight`"] + pub fn update_threshold_weight( + &self, + new: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "update_threshold_weight", + UpdateThresholdWeight { new }, + [ + 14u8, 144u8, 112u8, 207u8, 195u8, 208u8, 184u8, 164u8, 94u8, 41u8, 8u8, + 58u8, 180u8, 80u8, 239u8, 39u8, 210u8, 159u8, 114u8, 169u8, 152u8, + 176u8, 26u8, 161u8, 32u8, 43u8, 250u8, 156u8, 56u8, 21u8, 43u8, 159u8, + ], + ) + } + #[doc = "Overwrites the speed to which the available weight approaches the maximum weight."] + #[doc = "A lower number results in a faster progression. A value of 1 makes the entire weight available initially."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.weight_restrict_decay`."] + pub fn update_weight_restrict_decay( + &self, + new: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "update_weight_restrict_decay", + UpdateWeightRestrictDecay { new }, + [ + 42u8, 53u8, 83u8, 191u8, 51u8, 227u8, 210u8, 193u8, 142u8, 218u8, + 244u8, 177u8, 19u8, 87u8, 148u8, 177u8, 231u8, 197u8, 196u8, 255u8, + 41u8, 130u8, 245u8, 139u8, 107u8, 212u8, 90u8, 161u8, 82u8, 248u8, + 160u8, 223u8, + ], + ) + } + #[doc = "Overwrite the maximum amount of weight any individual message may consume."] + #[doc = "Messages above this weight go into the overweight queue and may only be serviced explicitly."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.xcmp_max_individual_weight`."] + pub fn update_xcmp_max_individual_weight( + &self, + new: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "XcmpQueue", + "update_xcmp_max_individual_weight", + UpdateXcmpMaxIndividualWeight { new }, + [ + 148u8, 185u8, 89u8, 36u8, 152u8, 220u8, 248u8, 233u8, 236u8, 82u8, + 170u8, 111u8, 225u8, 142u8, 25u8, 211u8, 72u8, 248u8, 250u8, 14u8, + 45u8, 72u8, 78u8, 95u8, 92u8, 196u8, 245u8, 104u8, 112u8, 128u8, 27u8, + 109u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::cumulus_pallet_xcmp_queue::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some XCM was executed ok."] + pub struct Success { + pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + pub weight: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for Success { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "Success"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some XCM failed."] + pub struct Fail { + pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + pub error: runtime_types::xcm::v3::traits::Error, + pub weight: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for Fail { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "Fail"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Bad XCM version used."] + pub struct BadVersion { + pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + } + impl ::subxt::events::StaticEvent for BadVersion { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "BadVersion"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Bad XCM format used."] + pub struct BadFormat { + pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + } + impl ::subxt::events::StaticEvent for BadFormat { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "BadFormat"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An HRMP message was sent to a sibling parachain."] + pub struct XcmpMessageSent { + pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + } + impl ::subxt::events::StaticEvent for XcmpMessageSent { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "XcmpMessageSent"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An XCM exceeded the individual message weight budget."] + pub struct OverweightEnqueued { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub sent_at: ::core::primitive::u32, + pub index: ::core::primitive::u64, + pub required: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for OverweightEnqueued { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "OverweightEnqueued"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An XCM from the overweight queue was executed with the given actual weight used."] + pub struct OverweightServiced { + pub index: ::core::primitive::u64, + pub used: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for OverweightServiced { + const PALLET: &'static str = "XcmpQueue"; + const EVENT: &'static str = "OverweightServiced"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " Status of the inbound XCMP channels."] + pub fn inbound_xcmp_status( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec< + runtime_types::cumulus_pallet_xcmp_queue::InboundChannelDetails, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "InboundXcmpStatus", + vec![], + [ + 183u8, 198u8, 237u8, 153u8, 132u8, 201u8, 87u8, 182u8, 121u8, 164u8, + 129u8, 241u8, 58u8, 192u8, 115u8, 152u8, 7u8, 33u8, 95u8, 51u8, 2u8, + 176u8, 144u8, 12u8, 125u8, 83u8, 92u8, 198u8, 211u8, 101u8, 28u8, 50u8, + ], + ) + } + #[doc = " Inbound aggregate XCMP messages. It can only be one per ParaId/block."] + pub fn inbound_xcmp_messages( + &self, + _0: impl ::std::borrow::Borrow, + _1: impl ::std::borrow::Borrow<::core::primitive::u32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "InboundXcmpMessages", + vec![ + ::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + ), + ::subxt::storage::address::StorageMapKey::new( + _1.borrow(), + ::subxt::storage::address::StorageHasher::Twox64Concat, + ), + ], + [ + 157u8, 232u8, 222u8, 97u8, 218u8, 96u8, 96u8, 90u8, 216u8, 205u8, 39u8, + 130u8, 109u8, 152u8, 127u8, 57u8, 54u8, 63u8, 104u8, 135u8, 33u8, + 175u8, 197u8, 166u8, 238u8, 22u8, 137u8, 162u8, 226u8, 199u8, 87u8, + 25u8, + ], + ) + } + #[doc = " Inbound aggregate XCMP messages. It can only be one per ParaId/block."] + pub fn inbound_xcmp_messages_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "InboundXcmpMessages", + Vec::new(), + [ + 157u8, 232u8, 222u8, 97u8, 218u8, 96u8, 96u8, 90u8, 216u8, 205u8, 39u8, + 130u8, 109u8, 152u8, 127u8, 57u8, 54u8, 63u8, 104u8, 135u8, 33u8, + 175u8, 197u8, 166u8, 238u8, 22u8, 137u8, 162u8, 226u8, 199u8, 87u8, + 25u8, + ], + ) + } + #[doc = " The non-empty XCMP channels in order of becoming non-empty, and the index of the first"] + #[doc = " and last outbound message. If the two indices are equal, then it indicates an empty"] + #[doc = " queue and there must be a non-`Ok` `OutboundStatus`. We assume queues grow no greater"] + #[doc = " than 65535 items. Queue indices for normal messages begin at one; zero is reserved in"] + #[doc = " case of the need to send a high-priority signal message this block."] + #[doc = " The bool is true if there is a signal message waiting to be sent."] + pub fn outbound_xcmp_status( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec< + runtime_types::cumulus_pallet_xcmp_queue::OutboundChannelDetails, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "OutboundXcmpStatus", + vec![], + [ + 238u8, 120u8, 185u8, 141u8, 82u8, 159u8, 41u8, 68u8, 204u8, 15u8, 46u8, + 152u8, 144u8, 74u8, 250u8, 83u8, 71u8, 105u8, 54u8, 53u8, 226u8, 87u8, + 14u8, 202u8, 58u8, 160u8, 54u8, 162u8, 239u8, 248u8, 227u8, 116u8, + ], + ) + } + #[doc = " The messages outbound in a given XCMP channel."] + pub fn outbound_xcmp_messages( + &self, + _0: impl ::std::borrow::Borrow, + _1: impl ::std::borrow::Borrow<::core::primitive::u16>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "OutboundXcmpMessages", + vec![ + ::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + ), + ::subxt::storage::address::StorageMapKey::new( + _1.borrow(), + ::subxt::storage::address::StorageHasher::Twox64Concat, + ), + ], + [ + 50u8, 182u8, 237u8, 191u8, 106u8, 67u8, 54u8, 1u8, 17u8, 107u8, 70u8, + 90u8, 202u8, 8u8, 63u8, 184u8, 171u8, 111u8, 192u8, 196u8, 7u8, 31u8, + 186u8, 68u8, 31u8, 63u8, 71u8, 61u8, 83u8, 223u8, 79u8, 200u8, + ], + ) + } + #[doc = " The messages outbound in a given XCMP channel."] + pub fn outbound_xcmp_messages_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "OutboundXcmpMessages", + Vec::new(), + [ + 50u8, 182u8, 237u8, 191u8, 106u8, 67u8, 54u8, 1u8, 17u8, 107u8, 70u8, + 90u8, 202u8, 8u8, 63u8, 184u8, 171u8, 111u8, 192u8, 196u8, 7u8, 31u8, + 186u8, 68u8, 31u8, 63u8, 71u8, 61u8, 83u8, 223u8, 79u8, 200u8, + ], + ) + } + #[doc = " Any signal messages waiting to be sent."] + pub fn signal_messages( + &self, + _0: impl ::std::borrow::Borrow, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "SignalMessages", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 156u8, 242u8, 186u8, 89u8, 177u8, 195u8, 90u8, 121u8, 94u8, 106u8, + 222u8, 78u8, 19u8, 162u8, 179u8, 96u8, 38u8, 113u8, 209u8, 148u8, 29u8, + 110u8, 106u8, 167u8, 162u8, 96u8, 221u8, 20u8, 33u8, 179u8, 168u8, + 142u8, + ], + ) + } + #[doc = " Any signal messages waiting to be sent."] + pub fn signal_messages_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "SignalMessages", + Vec::new(), + [ + 156u8, 242u8, 186u8, 89u8, 177u8, 195u8, 90u8, 121u8, 94u8, 106u8, + 222u8, 78u8, 19u8, 162u8, 179u8, 96u8, 38u8, 113u8, 209u8, 148u8, 29u8, + 110u8, 106u8, 167u8, 162u8, 96u8, 221u8, 20u8, 33u8, 179u8, 168u8, + 142u8, + ], + ) + } + #[doc = " The configuration which controls the dynamics of the outbound queue."] + pub fn queue_config( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::cumulus_pallet_xcmp_queue::QueueConfigData, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "QueueConfig", + vec![], + [ + 154u8, 172u8, 227u8, 208u8, 130u8, 93u8, 173u8, 129u8, 33u8, 75u8, + 180u8, 100u8, 35u8, 154u8, 40u8, 188u8, 86u8, 53u8, 74u8, 118u8, 131u8, + 159u8, 240u8, 159u8, 185u8, 45u8, 165u8, 6u8, 90u8, 125u8, 77u8, 253u8, + ], + ) + } + #[doc = " The messages that exceeded max individual message weight budget."] + #[doc = ""] + #[doc = " These message stay in this storage map until they are manually dispatched via"] + #[doc = " `service_overweight`."] + pub fn overweight( + &self, + _0: impl ::std::borrow::Borrow<::core::primitive::u64>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<( + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::std::vec::Vec<::core::primitive::u8>, + )>, + ::subxt::storage::address::Yes, + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "Overweight", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Twox64Concat, + )], + [ + 222u8, 249u8, 232u8, 110u8, 117u8, 229u8, 165u8, 164u8, 219u8, 219u8, + 149u8, 204u8, 25u8, 78u8, 204u8, 116u8, 111u8, 114u8, 120u8, 222u8, + 56u8, 77u8, 122u8, 147u8, 108u8, 15u8, 94u8, 161u8, 212u8, 50u8, 7u8, + 7u8, + ], + ) + } + #[doc = " The messages that exceeded max individual message weight budget."] + #[doc = ""] + #[doc = " These message stay in this storage map until they are manually dispatched via"] + #[doc = " `service_overweight`."] + pub fn overweight_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<( + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::std::vec::Vec<::core::primitive::u8>, + )>, + (), + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "Overweight", + Vec::new(), + [ + 222u8, 249u8, 232u8, 110u8, 117u8, 229u8, 165u8, 164u8, 219u8, 219u8, + 149u8, 204u8, 25u8, 78u8, 204u8, 116u8, 111u8, 114u8, 120u8, 222u8, + 56u8, 77u8, 122u8, 147u8, 108u8, 15u8, 94u8, 161u8, 212u8, 50u8, 7u8, + 7u8, + ], + ) + } + #[doc = "Counter for the related counted storage map"] + pub fn counter_for_overweight( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "CounterForOverweight", + vec![], + [ + 148u8, 226u8, 248u8, 107u8, 165u8, 97u8, 218u8, 160u8, 127u8, 48u8, + 185u8, 251u8, 35u8, 137u8, 119u8, 251u8, 151u8, 167u8, 189u8, 66u8, + 80u8, 74u8, 134u8, 129u8, 222u8, 180u8, 51u8, 182u8, 50u8, 110u8, 10u8, + 43u8, + ], + ) + } + #[doc = " The number of overweight messages ever recorded in `Overweight`. Also doubles as the next"] + #[doc = " available free overweight index."] + pub fn overweight_count( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u64>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "OverweightCount", + vec![], + [ + 102u8, 180u8, 196u8, 148u8, 115u8, 62u8, 46u8, 238u8, 97u8, 116u8, + 117u8, 42u8, 14u8, 5u8, 72u8, 237u8, 230u8, 46u8, 150u8, 126u8, 89u8, + 64u8, 233u8, 166u8, 180u8, 137u8, 52u8, 233u8, 252u8, 255u8, 36u8, + 20u8, + ], + ) + } + #[doc = " Whether or not the XCMP queue is suspended from executing incoming XCMs or not."] + pub fn queue_suspended( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "XcmpQueue", + "QueueSuspended", + vec![], + [ + 23u8, 37u8, 48u8, 112u8, 222u8, 17u8, 252u8, 65u8, 160u8, 217u8, 218u8, + 30u8, 2u8, 1u8, 204u8, 0u8, 251u8, 17u8, 138u8, 197u8, 164u8, 50u8, + 122u8, 0u8, 31u8, 238u8, 147u8, 213u8, 30u8, 132u8, 184u8, 215u8, + ], + ) + } + } + } + } + pub mod polkadot_xcm { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Send { + pub dest: ::std::boxed::Box, + pub message: ::std::boxed::Box, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct TeleportAssets { + pub dest: ::std::boxed::Box, + pub beneficiary: ::std::boxed::Box, + pub assets: ::std::boxed::Box, + pub fee_asset_item: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ReserveTransferAssets { + pub dest: ::std::boxed::Box, + pub beneficiary: ::std::boxed::Box, + pub assets: ::std::boxed::Box, + pub fee_asset_item: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Execute { + pub message: ::std::boxed::Box, + pub max_weight: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceXcmVersion { + pub location: + ::std::boxed::Box, + pub xcm_version: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceDefaultXcmVersion { + pub maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceSubscribeVersionNotify { + pub location: ::std::boxed::Box, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceUnsubscribeVersionNotify { + pub location: ::std::boxed::Box, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct LimitedReserveTransferAssets { + pub dest: ::std::boxed::Box, + pub beneficiary: ::std::boxed::Box, + pub assets: ::std::boxed::Box, + pub fee_asset_item: ::core::primitive::u32, + pub weight_limit: runtime_types::xcm::v3::WeightLimit, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct LimitedTeleportAssets { + pub dest: ::std::boxed::Box, + pub beneficiary: ::std::boxed::Box, + pub assets: ::std::boxed::Box, + pub fee_asset_item: ::core::primitive::u32, + pub weight_limit: runtime_types::xcm::v3::WeightLimit, + } + pub struct TransactionApi; + impl TransactionApi { + pub fn send( + &self, + dest: runtime_types::xcm::VersionedMultiLocation, + message: runtime_types::xcm::VersionedXcm, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "send", + Send { + dest: ::std::boxed::Box::new(dest), + message: ::std::boxed::Box::new(message), + }, + [ + 26u8, 89u8, 11u8, 127u8, 105u8, 218u8, 45u8, 49u8, 234u8, 4u8, 72u8, + 86u8, 134u8, 227u8, 122u8, 187u8, 183u8, 63u8, 27u8, 203u8, 123u8, + 200u8, 64u8, 192u8, 64u8, 204u8, 68u8, 98u8, 27u8, 234u8, 176u8, 93u8, + ], + ) + } + #[doc = "Teleport some assets from the local chain to some destination chain."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] + #[doc = "with all fees taken as needed from the asset."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] + #[doc = " `dest` side. May not be empty."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + pub fn teleport_assets( + &self, + dest: runtime_types::xcm::VersionedMultiLocation, + beneficiary: runtime_types::xcm::VersionedMultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + fee_asset_item: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "teleport_assets", + TeleportAssets { + dest: ::std::boxed::Box::new(dest), + beneficiary: ::std::boxed::Box::new(beneficiary), + assets: ::std::boxed::Box::new(assets), + fee_asset_item, + }, + [ + 18u8, 130u8, 117u8, 55u8, 235u8, 117u8, 250u8, 246u8, 109u8, 145u8, + 160u8, 184u8, 72u8, 76u8, 61u8, 229u8, 50u8, 94u8, 60u8, 202u8, 25u8, + 180u8, 228u8, 63u8, 171u8, 182u8, 224u8, 146u8, 196u8, 203u8, 243u8, + 70u8, + ], + ) + } + #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] + #[doc = "chain and forward a notification XCM."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] + #[doc = "with all fees taken as needed from the asset."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] + #[doc = " `dest` side."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + pub fn reserve_transfer_assets( + &self, + dest: runtime_types::xcm::VersionedMultiLocation, + beneficiary: runtime_types::xcm::VersionedMultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + fee_asset_item: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "reserve_transfer_assets", + ReserveTransferAssets { + dest: ::std::boxed::Box::new(dest), + beneficiary: ::std::boxed::Box::new(beneficiary), + assets: ::std::boxed::Box::new(assets), + fee_asset_item, + }, + [ + 233u8, 36u8, 82u8, 54u8, 27u8, 201u8, 7u8, 145u8, 212u8, 107u8, 150u8, + 124u8, 125u8, 135u8, 226u8, 60u8, 133u8, 157u8, 202u8, 114u8, 102u8, + 67u8, 170u8, 66u8, 133u8, 228u8, 66u8, 45u8, 55u8, 188u8, 0u8, 19u8, + ], + ) + } + #[doc = "Execute an XCM message from a local, signed, origin."] + #[doc = ""] + #[doc = "An event is deposited indicating whether `msg` could be executed completely or only"] + #[doc = "partially."] + #[doc = ""] + #[doc = "No more than `max_weight` will be used in its attempted execution. If this is less than the"] + #[doc = "maximum amount of weight that the message could take to be executed, then no execution"] + #[doc = "attempt will be made."] + #[doc = ""] + #[doc = "NOTE: A successful return to this does *not* imply that the `msg` was executed successfully"] + #[doc = "to completion; only that *some* of it was executed."] + pub fn execute( + &self, + message: runtime_types::xcm::VersionedXcm, + max_weight: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "execute", + Execute { message: ::std::boxed::Box::new(message), max_weight }, + [ + 144u8, 56u8, 199u8, 18u8, 111u8, 10u8, 128u8, 179u8, 178u8, 216u8, + 119u8, 103u8, 11u8, 218u8, 221u8, 181u8, 129u8, 24u8, 192u8, 66u8, + 219u8, 239u8, 33u8, 161u8, 3u8, 51u8, 25u8, 177u8, 169u8, 188u8, 197u8, + 33u8, + ], + ) + } + #[doc = "Extoll that a particular destination can be communicated with through a particular"] + #[doc = "version of XCM."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `location`: The destination that is being described."] + #[doc = "- `xcm_version`: The latest version of XCM that `location` supports."] + pub fn force_xcm_version( + &self, + location: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm_version: ::core::primitive::u32, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "force_xcm_version", + ForceXcmVersion { location: ::std::boxed::Box::new(location), xcm_version }, + [ + 150u8, 120u8, 133u8, 146u8, 71u8, 43u8, 247u8, 59u8, 124u8, 234u8, + 125u8, 149u8, 216u8, 199u8, 137u8, 17u8, 87u8, 220u8, 110u8, 154u8, + 95u8, 92u8, 251u8, 180u8, 253u8, 1u8, 200u8, 98u8, 36u8, 48u8, 231u8, + 3u8, + ], + ) + } + #[doc = "Set a safe XCM version (the version that XCM should be encoded with if the most recent"] + #[doc = "version a destination can accept is unknown)."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `maybe_xcm_version`: The default XCM encoding version, or `None` to disable."] + pub fn force_default_xcm_version( + &self, + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "force_default_xcm_version", + ForceDefaultXcmVersion { maybe_xcm_version }, + [ + 38u8, 36u8, 59u8, 231u8, 18u8, 79u8, 76u8, 9u8, 200u8, 125u8, 214u8, + 166u8, 37u8, 99u8, 111u8, 161u8, 135u8, 2u8, 133u8, 157u8, 165u8, 18u8, + 152u8, 81u8, 209u8, 255u8, 137u8, 237u8, 28u8, 126u8, 224u8, 141u8, + ], + ) + } + #[doc = "Ask a location to notify us regarding their XCM version and any changes to it."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `location`: The location to which we should subscribe for XCM version notifications."] + pub fn force_subscribe_version_notify( + &self, + location: runtime_types::xcm::VersionedMultiLocation, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "force_subscribe_version_notify", + ForceSubscribeVersionNotify { location: ::std::boxed::Box::new(location) }, + [ + 44u8, 16u8, 170u8, 133u8, 130u8, 247u8, 158u8, 196u8, 23u8, 250u8, + 128u8, 106u8, 40u8, 44u8, 245u8, 45u8, 170u8, 223u8, 15u8, 12u8, 204u8, + 159u8, 92u8, 154u8, 186u8, 107u8, 13u8, 70u8, 17u8, 174u8, 192u8, + 111u8, + ], + ) + } + #[doc = "Require that a particular destination should no longer notify us regarding any XCM"] + #[doc = "version changes."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `location`: The location to which we are currently subscribed for XCM version"] + #[doc = " notifications which we no longer desire."] + pub fn force_unsubscribe_version_notify( + &self, + location: runtime_types::xcm::VersionedMultiLocation, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "force_unsubscribe_version_notify", + ForceUnsubscribeVersionNotify { + location: ::std::boxed::Box::new(location), + }, + [ + 77u8, 123u8, 3u8, 212u8, 40u8, 117u8, 46u8, 241u8, 174u8, 0u8, 131u8, + 242u8, 193u8, 177u8, 104u8, 161u8, 42u8, 54u8, 252u8, 70u8, 209u8, + 47u8, 87u8, 181u8, 75u8, 177u8, 157u8, 90u8, 145u8, 110u8, 121u8, + 208u8, + ], + ) + } + #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] + #[doc = "chain and forward a notification XCM."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] + #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] + #[doc = "at risk."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] + #[doc = " `dest` side."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] + pub fn limited_reserve_transfer_assets( + &self, + dest: runtime_types::xcm::VersionedMultiLocation, + beneficiary: runtime_types::xcm::VersionedMultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "limited_reserve_transfer_assets", + LimitedReserveTransferAssets { + dest: ::std::boxed::Box::new(dest), + beneficiary: ::std::boxed::Box::new(beneficiary), + assets: ::std::boxed::Box::new(assets), + fee_asset_item, + weight_limit, + }, + [ + 71u8, 241u8, 225u8, 54u8, 199u8, 145u8, 122u8, 171u8, 17u8, 54u8, 20u8, + 80u8, 102u8, 131u8, 241u8, 79u8, 5u8, 3u8, 193u8, 26u8, 22u8, 180u8, + 237u8, 226u8, 109u8, 219u8, 185u8, 161u8, 153u8, 79u8, 102u8, 93u8, + ], + ) + } + #[doc = "Teleport some assets from the local chain to some destination chain."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] + #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] + #[doc = "at risk."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] + #[doc = " `dest` side. May not be empty."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] + pub fn limited_teleport_assets( + &self, + dest: runtime_types::xcm::VersionedMultiLocation, + beneficiary: runtime_types::xcm::VersionedMultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "PolkadotXcm", + "limited_teleport_assets", + LimitedTeleportAssets { + dest: ::std::boxed::Box::new(dest), + beneficiary: ::std::boxed::Box::new(beneficiary), + assets: ::std::boxed::Box::new(assets), + fee_asset_item, + weight_limit, + }, + [ + 157u8, 57u8, 28u8, 124u8, 235u8, 202u8, 68u8, 125u8, 203u8, 246u8, + 109u8, 4u8, 199u8, 14u8, 103u8, 38u8, 67u8, 185u8, 81u8, 67u8, 124u8, + 64u8, 197u8, 45u8, 101u8, 199u8, 73u8, 196u8, 162u8, 36u8, 100u8, + 107u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_xcm::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Execution of an XCM message was attempted."] + #[doc = ""] + #[doc = "\\[ outcome \\]"] + pub struct Attempted(pub runtime_types::xcm::v3::traits::Outcome); + impl ::subxt::events::StaticEvent for Attempted { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "Attempted"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A XCM message was sent."] + #[doc = ""] + #[doc = "\\[ origin, destination, message \\]"] + pub struct Sent( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::v3::Xcm, + ); + impl ::subxt::events::StaticEvent for Sent { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "Sent"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Query response received which does not match a registered query. This may be because a"] + #[doc = "matching query was never registered, it may be because it is a duplicate response, or"] + #[doc = "because the query timed out."] + #[doc = ""] + #[doc = "\\[ origin location, id \\]"] + pub struct UnexpectedResponse( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u64, + ); + impl ::subxt::events::StaticEvent for UnexpectedResponse { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "UnexpectedResponse"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Query response has been received and is ready for taking with `take_response`. There is"] + #[doc = "no registered notification call."] + #[doc = ""] + #[doc = "\\[ id, response \\]"] + pub struct ResponseReady( + pub ::core::primitive::u64, + pub runtime_types::xcm::v3::Response, + ); + impl ::subxt::events::StaticEvent for ResponseReady { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "ResponseReady"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Query response has been received and query is removed. The registered notification has"] + #[doc = "been dispatched and executed successfully."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index \\]"] + pub struct Notified( + pub ::core::primitive::u64, + pub ::core::primitive::u8, + pub ::core::primitive::u8, + ); + impl ::subxt::events::StaticEvent for Notified { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "Notified"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Query response has been received and query is removed. The registered notification could"] + #[doc = "not be dispatched because the dispatch weight is greater than the maximum weight"] + #[doc = "originally budgeted by this runtime for the query result."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index, actual weight, max budgeted weight \\]"] + pub struct NotifyOverweight( + pub ::core::primitive::u64, + pub ::core::primitive::u8, + pub ::core::primitive::u8, + pub ::sp_weights::Weight, + pub ::sp_weights::Weight, + ); + impl ::subxt::events::StaticEvent for NotifyOverweight { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "NotifyOverweight"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Query response has been received and query is removed. There was a general error with"] + #[doc = "dispatching the notification call."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index \\]"] + pub struct NotifyDispatchError( + pub ::core::primitive::u64, + pub ::core::primitive::u8, + pub ::core::primitive::u8, + ); + impl ::subxt::events::StaticEvent for NotifyDispatchError { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "NotifyDispatchError"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Query response has been received and query is removed. The dispatch was unable to be"] + #[doc = "decoded into a `Call`; this might be due to dispatch function having a signature which"] + #[doc = "is not `(origin, QueryId, Response)`."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index \\]"] + pub struct NotifyDecodeFailed( + pub ::core::primitive::u64, + pub ::core::primitive::u8, + pub ::core::primitive::u8, + ); + impl ::subxt::events::StaticEvent for NotifyDecodeFailed { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "NotifyDecodeFailed"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Expected query response has been received but the origin location of the response does"] + #[doc = "not match that expected. The query remains registered for a later, valid, response to"] + #[doc = "be received and acted upon."] + #[doc = ""] + #[doc = "\\[ origin location, id, expected location \\]"] + pub struct InvalidResponder( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u64, + pub ::core::option::Option, + ); + impl ::subxt::events::StaticEvent for InvalidResponder { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "InvalidResponder"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Expected query response has been received but the expected origin location placed in"] + #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] + #[doc = ""] + #[doc = "This is unexpected (since a location placed in storage in a previously executing"] + #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] + #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] + #[doc = "needed."] + #[doc = ""] + #[doc = "\\[ origin location, id \\]"] + pub struct InvalidResponderVersion( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u64, + ); + impl ::subxt::events::StaticEvent for InvalidResponderVersion { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "InvalidResponderVersion"; + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Received query response has been read and removed."] + #[doc = ""] + #[doc = "\\[ id \\]"] + pub struct ResponseTaken(pub ::core::primitive::u64); + impl ::subxt::events::StaticEvent for ResponseTaken { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "ResponseTaken"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some assets have been placed in an asset trap."] + #[doc = ""] + #[doc = "\\[ hash, origin, assets \\]"] + pub struct AssetsTrapped( + pub ::subxt::utils::H256, + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::VersionedMultiAssets, + ); + impl ::subxt::events::StaticEvent for AssetsTrapped { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "AssetsTrapped"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An XCM version change notification message has been attempted to be sent."] + #[doc = ""] + #[doc = "The cost of sending it (borne by the chain) is included."] + #[doc = ""] + #[doc = "\\[ destination, result, cost \\]"] + pub struct VersionChangeNotified( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u32, + pub runtime_types::xcm::v3::multiasset::MultiAssets, + ); + impl ::subxt::events::StaticEvent for VersionChangeNotified { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "VersionChangeNotified"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "The supported version of a location has been changed. This might be through an"] + #[doc = "automatic notification or a manual intervention."] + #[doc = ""] + #[doc = "\\[ location, XCM version \\]"] + pub struct SupportedVersionChanged( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u32, + ); + impl ::subxt::events::StaticEvent for SupportedVersionChanged { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "SupportedVersionChanged"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A given location which had a version change subscription was dropped owing to an error"] + #[doc = "sending the notification to it."] + #[doc = ""] + #[doc = "\\[ location, query ID, error \\]"] + pub struct NotifyTargetSendFail( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u64, + pub runtime_types::xcm::v3::traits::Error, + ); + impl ::subxt::events::StaticEvent for NotifyTargetSendFail { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "NotifyTargetSendFail"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A given location which had a version change subscription was dropped owing to an error"] + #[doc = "migrating the location to our new XCM format."] + #[doc = ""] + #[doc = "\\[ location, query ID \\]"] + pub struct NotifyTargetMigrationFail( + pub runtime_types::xcm::VersionedMultiLocation, + pub ::core::primitive::u64, + ); + impl ::subxt::events::StaticEvent for NotifyTargetMigrationFail { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "NotifyTargetMigrationFail"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Expected query response has been received but the expected querier location placed in"] + #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] + #[doc = ""] + #[doc = "This is unexpected (since a location placed in storage in a previously executing"] + #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] + #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] + #[doc = "needed."] + #[doc = ""] + #[doc = "\\[ origin location, id \\]"] + pub struct InvalidQuerierVersion( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u64, + ); + impl ::subxt::events::StaticEvent for InvalidQuerierVersion { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "InvalidQuerierVersion"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Expected query response has been received but the querier location of the response does"] + #[doc = "not match the expected. The query remains registered for a later, valid, response to"] + #[doc = "be received and acted upon."] + #[doc = ""] + #[doc = "\\[ origin location, id, expected querier, maybe actual querier \\]"] + pub struct InvalidQuerier( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::primitive::u64, + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub ::core::option::Option, + ); + impl ::subxt::events::StaticEvent for InvalidQuerier { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "InvalidQuerier"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "A remote has requested XCM version change notification from us and we have honored it."] + #[doc = "A version information message is sent to them and its cost is included."] + #[doc = ""] + #[doc = "\\[ destination location, cost \\]"] + pub struct VersionNotifyStarted( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::v3::multiasset::MultiAssets, + ); + impl ::subxt::events::StaticEvent for VersionNotifyStarted { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "VersionNotifyStarted"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "We have requested that a remote chain sends us XCM version change notifications."] + #[doc = ""] + #[doc = "\\[ destination location, cost \\]"] + pub struct VersionNotifyRequested( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::v3::multiasset::MultiAssets, + ); + impl ::subxt::events::StaticEvent for VersionNotifyRequested { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "VersionNotifyRequested"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "We have requested that a remote chain stops sending us XCM version change notifications."] + #[doc = ""] + #[doc = "\\[ destination location, cost \\]"] + pub struct VersionNotifyUnrequested( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::v3::multiasset::MultiAssets, + ); + impl ::subxt::events::StaticEvent for VersionNotifyUnrequested { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "VersionNotifyUnrequested"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Fees were paid from a location for an operation (often for using `SendXcm`)."] + #[doc = ""] + #[doc = "\\[ paying location, fees \\]"] + pub struct FeesPaid( + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::v3::multiasset::MultiAssets, + ); + impl ::subxt::events::StaticEvent for FeesPaid { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "FeesPaid"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some assets have been claimed from an asset trap"] + #[doc = ""] + #[doc = "\\[ hash, origin, assets \\]"] + pub struct AssetsClaimed( + pub ::subxt::utils::H256, + pub runtime_types::xcm::v3::multilocation::MultiLocation, + pub runtime_types::xcm::VersionedMultiAssets, + ); + impl ::subxt::events::StaticEvent for AssetsClaimed { + const PALLET: &'static str = "PolkadotXcm"; + const EVENT: &'static str = "AssetsClaimed"; + } + } + } + pub mod cumulus_xcm { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + pub struct TransactionApi; + impl TransactionApi {} + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::cumulus_pallet_xcm::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message is invalid XCM."] + #[doc = "\\[ id \\]"] + pub struct InvalidFormat(pub [::core::primitive::u8; 32usize]); + impl ::subxt::events::StaticEvent for InvalidFormat { + const PALLET: &'static str = "CumulusXcm"; + const EVENT: &'static str = "InvalidFormat"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message is unsupported version of XCM."] + #[doc = "\\[ id \\]"] + pub struct UnsupportedVersion(pub [::core::primitive::u8; 32usize]); + impl ::subxt::events::StaticEvent for UnsupportedVersion { + const PALLET: &'static str = "CumulusXcm"; + const EVENT: &'static str = "UnsupportedVersion"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message executed with the given outcome."] + #[doc = "\\[ id, outcome \\]"] + pub struct ExecutedDownward( + pub [::core::primitive::u8; 32usize], + pub runtime_types::xcm::v3::traits::Outcome, + ); + impl ::subxt::events::StaticEvent for ExecutedDownward { + const PALLET: &'static str = "CumulusXcm"; + const EVENT: &'static str = "ExecutedDownward"; + } + } + } + pub mod dmp_queue { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ServiceOverweight { + pub index: ::core::primitive::u64, + pub weight_limit: ::sp_weights::Weight, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Service a single overweight message."] + pub fn service_overweight( + &self, + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "DmpQueue", + "service_overweight", + ServiceOverweight { index, weight_limit }, + [ + 121u8, 236u8, 235u8, 23u8, 210u8, 238u8, 238u8, 122u8, 15u8, 86u8, + 34u8, 119u8, 105u8, 100u8, 214u8, 236u8, 117u8, 39u8, 254u8, 235u8, + 189u8, 15u8, 72u8, 74u8, 225u8, 134u8, 148u8, 126u8, 31u8, 203u8, + 144u8, 106u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::cumulus_pallet_dmp_queue::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message is invalid XCM."] + pub struct InvalidFormat { + pub message_id: [::core::primitive::u8; 32usize], + } + impl ::subxt::events::StaticEvent for InvalidFormat { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "InvalidFormat"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message is unsupported version of XCM."] + pub struct UnsupportedVersion { + pub message_id: [::core::primitive::u8; 32usize], + } + impl ::subxt::events::StaticEvent for UnsupportedVersion { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "UnsupportedVersion"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message executed with the given outcome."] + pub struct ExecutedDownward { + pub message_id: [::core::primitive::u8; 32usize], + pub outcome: runtime_types::xcm::v3::traits::Outcome, + } + impl ::subxt::events::StaticEvent for ExecutedDownward { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "ExecutedDownward"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "The weight limit for handling downward messages was reached."] + pub struct WeightExhausted { + pub message_id: [::core::primitive::u8; 32usize], + pub remaining_weight: ::sp_weights::Weight, + pub required_weight: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for WeightExhausted { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "WeightExhausted"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message is overweight and was placed in the overweight queue."] + pub struct OverweightEnqueued { + pub message_id: [::core::primitive::u8; 32usize], + pub overweight_index: ::core::primitive::u64, + pub required_weight: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for OverweightEnqueued { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "OverweightEnqueued"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Downward message from the overweight queue was executed."] + pub struct OverweightServiced { + pub overweight_index: ::core::primitive::u64, + pub weight_used: ::sp_weights::Weight, + } + impl ::subxt::events::StaticEvent for OverweightServiced { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "OverweightServiced"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " The configuration."] + pub fn configuration( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::cumulus_pallet_dmp_queue::ConfigData, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "Configuration", + vec![], + [ + 133u8, 113u8, 115u8, 164u8, 128u8, 145u8, 234u8, 106u8, 150u8, 54u8, + 247u8, 135u8, 181u8, 197u8, 178u8, 30u8, 204u8, 46u8, 6u8, 137u8, 82u8, + 1u8, 75u8, 171u8, 7u8, 157u8, 3u8, 19u8, 92u8, 10u8, 234u8, 66u8, + ], + ) + } + #[doc = " The page index."] + pub fn page_index( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::cumulus_pallet_dmp_queue::PageIndexData, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "PageIndex", + vec![], + [ + 94u8, 132u8, 34u8, 67u8, 10u8, 22u8, 235u8, 96u8, 168u8, 26u8, 57u8, + 200u8, 130u8, 218u8, 37u8, 71u8, 28u8, 119u8, 78u8, 107u8, 209u8, + 120u8, 190u8, 2u8, 101u8, 215u8, 122u8, 187u8, 94u8, 38u8, 255u8, + 234u8, + ], + ) + } + #[doc = " The queue pages."] + pub fn pages( + &self, + _0: impl ::std::borrow::Borrow<::core::primitive::u32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec<( + ::core::primitive::u32, + ::std::vec::Vec<::core::primitive::u8>, + )>, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "Pages", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 228u8, 86u8, 33u8, 107u8, 248u8, 4u8, 223u8, 175u8, 222u8, 25u8, 204u8, + 42u8, 235u8, 21u8, 215u8, 91u8, 167u8, 14u8, 133u8, 151u8, 190u8, 57u8, + 138u8, 208u8, 79u8, 244u8, 132u8, 14u8, 48u8, 247u8, 171u8, 108u8, + ], + ) + } + #[doc = " The queue pages."] + pub fn pages_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + ::std::vec::Vec<( + ::core::primitive::u32, + ::std::vec::Vec<::core::primitive::u8>, + )>, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "Pages", + Vec::new(), + [ + 228u8, 86u8, 33u8, 107u8, 248u8, 4u8, 223u8, 175u8, 222u8, 25u8, 204u8, + 42u8, 235u8, 21u8, 215u8, 91u8, 167u8, 14u8, 133u8, 151u8, 190u8, 57u8, + 138u8, 208u8, 79u8, 244u8, 132u8, 14u8, 48u8, 247u8, 171u8, 108u8, + ], + ) + } + #[doc = " The overweight messages."] + pub fn overweight( + &self, + _0: impl ::std::borrow::Borrow<::core::primitive::u64>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<( + ::core::primitive::u32, + ::std::vec::Vec<::core::primitive::u8>, + )>, + ::subxt::storage::address::Yes, + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "Overweight", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 222u8, 85u8, 143u8, 49u8, 42u8, 248u8, 138u8, 163u8, 46u8, 199u8, + 188u8, 61u8, 137u8, 135u8, 127u8, 146u8, 210u8, 254u8, 121u8, 42u8, + 112u8, 114u8, 22u8, 228u8, 207u8, 207u8, 245u8, 175u8, 152u8, 140u8, + 225u8, 237u8, + ], + ) + } + #[doc = " The overweight messages."] + pub fn overweight_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<( + ::core::primitive::u32, + ::std::vec::Vec<::core::primitive::u8>, + )>, + (), + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "Overweight", + Vec::new(), + [ + 222u8, 85u8, 143u8, 49u8, 42u8, 248u8, 138u8, 163u8, 46u8, 199u8, + 188u8, 61u8, 137u8, 135u8, 127u8, 146u8, 210u8, 254u8, 121u8, 42u8, + 112u8, 114u8, 22u8, 228u8, 207u8, 207u8, 245u8, 175u8, 152u8, 140u8, + 225u8, 237u8, + ], + ) + } + #[doc = "Counter for the related counted storage map"] + pub fn counter_for_overweight( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "DmpQueue", + "CounterForOverweight", + vec![], + [ + 148u8, 226u8, 248u8, 107u8, 165u8, 97u8, 218u8, 160u8, 127u8, 48u8, + 185u8, 251u8, 35u8, 137u8, 119u8, 251u8, 151u8, 167u8, 189u8, 66u8, + 80u8, 74u8, 134u8, 129u8, 222u8, 180u8, 51u8, 182u8, 50u8, 110u8, 10u8, + 43u8, + ], + ) + } + } + } + } + pub mod bridge_relayers { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ClaimRewards { + pub lane_id: runtime_types::bp_messages::LaneId, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Claim accumulated rewards."] + pub fn claim_rewards( + &self, + lane_id: runtime_types::bp_messages::LaneId, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeRelayers", + "claim_rewards", + ClaimRewards { lane_id }, + [ + 119u8, 55u8, 12u8, 215u8, 255u8, 17u8, 1u8, 92u8, 187u8, 154u8, 120u8, + 10u8, 51u8, 16u8, 160u8, 18u8, 194u8, 236u8, 95u8, 173u8, 64u8, 75u8, + 251u8, 68u8, 235u8, 116u8, 69u8, 240u8, 186u8, 153u8, 118u8, 17u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_bridge_relayers::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Reward has been paid to the relayer."] + pub struct RewardPaid { + pub relayer: ::sp_core::crypto::AccountId32, + pub lane_id: runtime_types::bp_messages::LaneId, + pub reward: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for RewardPaid { + const PALLET: &'static str = "BridgeRelayers"; + const EVENT: &'static str = "RewardPaid"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " Map of the relayer => accumulated reward."] + pub fn relayer_rewards( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + _1: impl ::std::borrow::Borrow, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, + ::subxt::storage::address::Yes, + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeRelayers", + "RelayerRewards", + vec![ + ::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + ), + ::subxt::storage::address::StorageMapKey::new( + _1.borrow(), + ::subxt::storage::address::StorageHasher::Identity, + ), + ], + [ + 79u8, 50u8, 107u8, 107u8, 201u8, 181u8, 235u8, 111u8, 185u8, 125u8, + 108u8, 204u8, 163u8, 11u8, 69u8, 236u8, 90u8, 232u8, 9u8, 225u8, 210u8, + 142u8, 175u8, 166u8, 159u8, 74u8, 112u8, 249u8, 16u8, 115u8, 144u8, + 177u8, + ], + ) + } + #[doc = " Map of the relayer => accumulated reward."] + pub fn relayer_rewards_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, + (), + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeRelayers", + "RelayerRewards", + Vec::new(), + [ + 79u8, 50u8, 107u8, 107u8, 201u8, 181u8, 235u8, 111u8, 185u8, 125u8, + 108u8, 204u8, 163u8, 11u8, 69u8, 236u8, 90u8, 232u8, 9u8, 225u8, 210u8, + 142u8, 175u8, 166u8, 159u8, 74u8, 112u8, 249u8, 16u8, 115u8, 144u8, + 177u8, + ], + ) + } + } + } + } + pub mod bridge_millau_grandpa { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SubmitFinalityProof { + pub finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + pub justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Initialize { + pub init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetOwner { + pub new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetOperatingMode { + pub operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Verify a target header is finalized according to the given finality proof."] + #[doc = ""] + #[doc = "It will use the underlying storage pallet to fetch information about the current"] + #[doc = "authorities and best finalized header in order to verify that the header is finalized."] + #[doc = ""] + #[doc = "If successful in verification, it will write the target header to the underlying storage"] + #[doc = "pallet."] + pub fn submit_finality_proof( + &self, + finality_target: ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauGrandpa", + "submit_finality_proof", + SubmitFinalityProof { + finality_target: ::std::boxed::Box::new(finality_target), + justification, + }, + [ + 3u8, 161u8, 243u8, 208u8, 245u8, 135u8, 86u8, 233u8, 103u8, 140u8, + 81u8, 3u8, 119u8, 185u8, 68u8, 167u8, 208u8, 155u8, 169u8, 201u8, + 209u8, 248u8, 162u8, 45u8, 155u8, 225u8, 173u8, 62u8, 156u8, 171u8, + 19u8, 190u8, + ], + ) + } + #[doc = "Bootstrap the bridge pallet with an initial header and authority set from which to sync."] + #[doc = ""] + #[doc = "The initial configuration provided does not need to be the genesis header of the bridged"] + #[doc = "chain, it can be any arbitrary header. You can also provide the next scheduled set"] + #[doc = "change if it is already know."] + #[doc = ""] + #[doc = "This function is only allowed to be called from a trusted origin and writes to storage"] + #[doc = "with practically no checks in terms of the validity of the data. It is important that"] + #[doc = "you ensure that valid data is being passed in."] + pub fn initialize( + &self, + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauGrandpa", + "initialize", + Initialize { init_data }, + [ + 244u8, 188u8, 202u8, 145u8, 218u8, 91u8, 74u8, 80u8, 41u8, 185u8, + 239u8, 178u8, 231u8, 128u8, 198u8, 90u8, 135u8, 219u8, 200u8, 23u8, + 194u8, 47u8, 61u8, 222u8, 194u8, 84u8, 142u8, 37u8, 64u8, 37u8, 69u8, + 198u8, + ], + ) + } + #[doc = "Change `PalletOwner`."] + #[doc = ""] + #[doc = "May only be called either by root, or by `PalletOwner`."] + pub fn set_owner( + &self, + new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauGrandpa", + "set_owner", + SetOwner { new_owner }, + [ + 100u8, 221u8, 84u8, 142u8, 158u8, 5u8, 47u8, 212u8, 9u8, 35u8, 82u8, + 135u8, 108u8, 238u8, 231u8, 197u8, 77u8, 219u8, 176u8, 222u8, 88u8, + 167u8, 152u8, 34u8, 177u8, 244u8, 160u8, 195u8, 211u8, 3u8, 66u8, + 253u8, + ], + ) + } + #[doc = "Halt or resume all pallet operations."] + #[doc = ""] + #[doc = "May only be called either by root, or by `PalletOwner`."] + pub fn set_operating_mode( + &self, + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauGrandpa", + "set_operating_mode", + SetOperatingMode { operating_mode }, + [ + 128u8, 25u8, 81u8, 145u8, 111u8, 185u8, 226u8, 152u8, 18u8, 51u8, 89u8, + 236u8, 200u8, 157u8, 157u8, 186u8, 207u8, 208u8, 152u8, 168u8, 12u8, + 39u8, 249u8, 48u8, 195u8, 160u8, 54u8, 73u8, 30u8, 230u8, 25u8, 46u8, + ], + ) + } + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " The current number of requests which have written to storage."] + #[doc = ""] + #[doc = " If the `RequestCount` hits `MaxRequests`, no more calls will be allowed to the pallet until"] + #[doc = " the request capacity is increased."] + #[doc = ""] + #[doc = " The `RequestCount` is decreased by one at the beginning of every block. This is to ensure"] + #[doc = " that the pallet can always make progress."] + pub fn request_count( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "RequestCount", + vec![], + [ + 100u8, 156u8, 98u8, 176u8, 229u8, 85u8, 81u8, 159u8, 120u8, 156u8, + 33u8, 179u8, 224u8, 237u8, 52u8, 198u8, 81u8, 81u8, 10u8, 180u8, 53u8, + 141u8, 96u8, 4u8, 39u8, 217u8, 58u8, 9u8, 57u8, 79u8, 47u8, 201u8, + ], + ) + } + #[doc = " Hash of the header used to bootstrap the pallet."] + pub fn initial_hash( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::bp_millau::MillauHash>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "InitialHash", + vec![], + [ + 167u8, 131u8, 64u8, 215u8, 102u8, 70u8, 21u8, 34u8, 254u8, 233u8, 2u8, + 49u8, 253u8, 67u8, 235u8, 10u8, 21u8, 223u8, 220u8, 198u8, 180u8, + 137u8, 88u8, 251u8, 230u8, 108u8, 9u8, 104u8, 101u8, 105u8, 38u8, + 138u8, + ], + ) + } + #[doc = " Hash of the best finalized header."] + pub fn best_finalized( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_runtime::HeaderId< + ::bp_millau::MillauHash, + ::core::primitive::u64, + >, + >, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "BestFinalized", + vec![], + [ + 61u8, 173u8, 97u8, 223u8, 180u8, 235u8, 85u8, 126u8, 217u8, 228u8, + 87u8, 174u8, 116u8, 156u8, 162u8, 252u8, 100u8, 200u8, 138u8, 14u8, + 102u8, 177u8, 66u8, 164u8, 216u8, 114u8, 18u8, 223u8, 94u8, 78u8, + 107u8, 58u8, + ], + ) + } + #[doc = " A ring buffer of imported hashes. Ordered by the insertion time."] + pub fn imported_hashes( + &self, + _0: impl ::std::borrow::Borrow<::core::primitive::u32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::bp_millau::MillauHash>, + ::subxt::storage::address::Yes, + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "ImportedHashes", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Identity, + )], + [ + 249u8, 185u8, 202u8, 36u8, 40u8, 197u8, 111u8, 168u8, 136u8, 138u8, + 84u8, 135u8, 69u8, 34u8, 181u8, 46u8, 158u8, 16u8, 150u8, 190u8, 81u8, + 53u8, 239u8, 199u8, 83u8, 93u8, 197u8, 205u8, 129u8, 173u8, 141u8, + 43u8, + ], + ) + } + #[doc = " A ring buffer of imported hashes. Ordered by the insertion time."] + pub fn imported_hashes_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::bp_millau::MillauHash>, + (), + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "ImportedHashes", + Vec::new(), + [ + 249u8, 185u8, 202u8, 36u8, 40u8, 197u8, 111u8, 168u8, 136u8, 138u8, + 84u8, 135u8, 69u8, 34u8, 181u8, 46u8, 158u8, 16u8, 150u8, 190u8, 81u8, + 53u8, 239u8, 199u8, 83u8, 93u8, 197u8, 205u8, 129u8, 173u8, 141u8, + 43u8, + ], + ) + } + #[doc = " Current ring buffer position."] + pub fn imported_hashes_pointer( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "ImportedHashesPointer", + vec![], + [ + 159u8, 83u8, 35u8, 45u8, 27u8, 249u8, 155u8, 131u8, 181u8, 196u8, + 224u8, 26u8, 92u8, 132u8, 127u8, 237u8, 13u8, 142u8, 196u8, 147u8, + 221u8, 216u8, 11u8, 78u8, 190u8, 241u8, 201u8, 96u8, 74u8, 185u8, + 208u8, 42u8, + ], + ) + } + #[doc = " Relevant fields of imported headers."] + pub fn imported_headers( + &self, + _0: impl ::std::borrow::Borrow<::bp_millau::MillauHash>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_header_chain::StoredHeaderData< + ::core::primitive::u64, + ::bp_millau::MillauHash, + >, + >, + ::subxt::storage::address::Yes, + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "ImportedHeaders", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Identity, + )], + [ + 109u8, 41u8, 102u8, 223u8, 133u8, 169u8, 46u8, 221u8, 235u8, 67u8, + 28u8, 192u8, 2u8, 242u8, 215u8, 166u8, 227u8, 182u8, 136u8, 217u8, + 61u8, 10u8, 246u8, 70u8, 17u8, 246u8, 223u8, 113u8, 9u8, 136u8, 181u8, + 242u8, + ], + ) + } + #[doc = " Relevant fields of imported headers."] + pub fn imported_headers_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_header_chain::StoredHeaderData< + ::core::primitive::u64, + ::bp_millau::MillauHash, + >, + >, + (), + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "ImportedHeaders", + Vec::new(), + [ + 109u8, 41u8, 102u8, 223u8, 133u8, 169u8, 46u8, 221u8, 235u8, 67u8, + 28u8, 192u8, 2u8, 242u8, 215u8, 166u8, 227u8, 182u8, 136u8, 217u8, + 61u8, 10u8, 246u8, 70u8, 17u8, 246u8, 223u8, 113u8, 9u8, 136u8, 181u8, + 242u8, + ], + ) + } + #[doc = " The current GRANDPA Authority set."] + pub fn current_authority_set( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::pallet_bridge_grandpa::storage_types::StoredAuthoritySet, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "CurrentAuthoritySet", + vec![], + [ + 249u8, 40u8, 229u8, 120u8, 141u8, 219u8, 206u8, 5u8, 54u8, 121u8, + 207u8, 77u8, 8u8, 80u8, 105u8, 107u8, 151u8, 111u8, 82u8, 119u8, 8u8, + 31u8, 104u8, 82u8, 92u8, 156u8, 37u8, 160u8, 235u8, 64u8, 62u8, 94u8, + ], + ) + } + #[doc = " Optional pallet owner."] + #[doc = ""] + #[doc = " Pallet owner has a right to halt all pallet operations and then resume it. If it is"] + #[doc = " `None`, then there are no direct ways to halt/resume pallet operations, but other"] + #[doc = " runtime methods may still be used to do that (i.e. democracy::referendum to update halt"] + #[doc = " flag directly or call the `halt_operations`)."] + pub fn pallet_owner( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::sp_core::crypto::AccountId32>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "PalletOwner", + vec![], + [ + 89u8, 42u8, 74u8, 119u8, 21u8, 164u8, 30u8, 115u8, 207u8, 126u8, 98u8, + 16u8, 162u8, 214u8, 67u8, 172u8, 178u8, 223u8, 139u8, 121u8, 174u8, + 89u8, 215u8, 75u8, 200u8, 161u8, 61u8, 195u8, 65u8, 222u8, 246u8, + 233u8, + ], + ) + } + #[doc = " The current operating mode of the pallet."] + #[doc = ""] + #[doc = " Depending on the mode either all, or no transactions will be allowed."] + pub fn pallet_operating_mode( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_runtime::BasicOperatingMode, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauGrandpa", + "PalletOperatingMode", + vec![], + [ + 218u8, 66u8, 212u8, 71u8, 38u8, 152u8, 55u8, 129u8, 125u8, 231u8, 91u8, + 216u8, 157u8, 141u8, 173u8, 146u8, 30u8, 40u8, 132u8, 107u8, 97u8, + 39u8, 36u8, 81u8, 231u8, 222u8, 113u8, 136u8, 233u8, 212u8, 225u8, + 75u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " The upper bound on the number of requests allowed by the pallet."] + #[doc = ""] + #[doc = " A request refers to an action which writes a header to storage."] + #[doc = ""] + #[doc = " Once this bound is reached the pallet will not allow any dispatchables to be called"] + #[doc = " until the request count has decreased."] + pub fn max_requests( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "BridgeMillauGrandpa", + "MaxRequests", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " Maximal number of finalized headers to keep in the storage."] + #[doc = ""] + #[doc = " The setting is there to prevent growing the on-chain state indefinitely. Note"] + #[doc = " the setting does not relate to block numbers - we will simply keep as much items"] + #[doc = " in the storage, so it doesn't guarantee any fixed timeframe for finality headers."] + #[doc = ""] + #[doc = " Incautious change of this constant may lead to orphan entries in the runtime storage."] + pub fn headers_to_keep( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "BridgeMillauGrandpa", + "HeadersToKeep", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " Max number of authorities at the bridged chain."] + pub fn max_bridged_authorities( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "BridgeMillauGrandpa", + "MaxBridgedAuthorities", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + } + } + } + pub mod bridge_millau_messages { + use super::{root_mod, runtime_types}; + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub mod calls { + use super::{root_mod, runtime_types}; + type DispatchError = runtime_types::sp_runtime::DispatchError; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetOwner { + pub new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SetOperatingMode { + pub operating_mode: runtime_types::bp_messages::MessagesOperatingMode, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ReceiveMessagesProof { + pub relayer_id_at_bridged_chain: ::sp_core::crypto::AccountId32, + pub proof: ::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< + ::bp_millau::MillauHash, + >, + pub messages_count: ::core::primitive::u32, + pub dispatch_weight: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ReceiveMessagesDeliveryProof { pub proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , pub relayers_state : :: bp_messages :: UnrewardedRelayersState , } + pub struct TransactionApi; + impl TransactionApi { + #[doc = "Change `PalletOwner`."] + #[doc = ""] + #[doc = "May only be called either by root, or by `PalletOwner`."] + pub fn set_owner( + &self, + new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauMessages", + "set_owner", + SetOwner { new_owner }, + [ + 100u8, 221u8, 84u8, 142u8, 158u8, 5u8, 47u8, 212u8, 9u8, 35u8, 82u8, + 135u8, 108u8, 238u8, 231u8, 197u8, 77u8, 219u8, 176u8, 222u8, 88u8, + 167u8, 152u8, 34u8, 177u8, 244u8, 160u8, 195u8, 211u8, 3u8, 66u8, + 253u8, + ], + ) + } + #[doc = "Halt or resume all/some pallet operations."] + #[doc = ""] + #[doc = "May only be called either by root, or by `PalletOwner`."] + pub fn set_operating_mode( + &self, + operating_mode: runtime_types::bp_messages::MessagesOperatingMode, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauMessages", + "set_operating_mode", + SetOperatingMode { operating_mode }, + [ + 236u8, 230u8, 127u8, 17u8, 145u8, 186u8, 102u8, 200u8, 227u8, 208u8, + 230u8, 121u8, 102u8, 199u8, 123u8, 118u8, 199u8, 160u8, 131u8, 116u8, + 102u8, 167u8, 119u8, 144u8, 70u8, 114u8, 0u8, 223u8, 54u8, 197u8, 39u8, + 58u8, + ], + ) + } + #[doc = "Receive messages proof from bridged chain."] + #[doc = ""] + #[doc = "The weight of the call assumes that the transaction always brings outbound lane"] + #[doc = "state update. Because of that, the submitter (relayer) has no benefit of not including"] + #[doc = "this data in the transaction, so reward confirmations lags should be minimal."] + pub fn receive_messages_proof( + &self, + relayer_id_at_bridged_chain: ::sp_core::crypto::AccountId32, + proof: ::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< + ::bp_millau::MillauHash, + >, + messages_count: ::core::primitive::u32, + dispatch_weight: ::sp_weights::Weight, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauMessages", + "receive_messages_proof", + ReceiveMessagesProof { + relayer_id_at_bridged_chain, + proof, + messages_count, + dispatch_weight, + }, + [ + 14u8, 23u8, 191u8, 242u8, 252u8, 163u8, 87u8, 149u8, 211u8, 25u8, + 112u8, 192u8, 206u8, 49u8, 135u8, 124u8, 79u8, 92u8, 204u8, 39u8, 80u8, + 139u8, 155u8, 124u8, 134u8, 1u8, 66u8, 68u8, 213u8, 85u8, 42u8, 250u8, + ], + ) + } + #[doc = "Receive messages delivery proof from bridged chain."] + pub fn receive_messages_delivery_proof( + &self, + proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash >, + relayers_state: ::bp_messages::UnrewardedRelayersState, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "BridgeMillauMessages", + "receive_messages_delivery_proof", + ReceiveMessagesDeliveryProof { proof, relayers_state }, + [ + 216u8, 113u8, 64u8, 20u8, 16u8, 64u8, 144u8, 143u8, 105u8, 30u8, 192u8, + 89u8, 74u8, 34u8, 56u8, 151u8, 20u8, 234u8, 14u8, 211u8, 64u8, 103u8, + 218u8, 164u8, 69u8, 107u8, 6u8, 119u8, 13u8, 90u8, 150u8, 24u8, + ], + ) + } + } + } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_bridge_messages::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Message has been accepted and is waiting to be delivered."] + pub struct MessageAccepted { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + impl ::subxt::events::StaticEvent for MessageAccepted { + const PALLET: &'static str = "BridgeMillauMessages"; + const EVENT: &'static str = "MessageAccepted"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Messages have been received from the bridged chain."] + pub struct MessagesReceived( + pub ::std::vec::Vec>, + ); + impl ::subxt::events::StaticEvent for MessagesReceived { + const PALLET: &'static str = "BridgeMillauMessages"; + const EVENT: &'static str = "MessagesReceived"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Messages in the inclusive range have been delivered to the bridged chain."] + pub struct MessagesDelivered { + pub lane_id: runtime_types::bp_messages::LaneId, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + impl ::subxt::events::StaticEvent for MessagesDelivered { + const PALLET: &'static str = "BridgeMillauMessages"; + const EVENT: &'static str = "MessagesDelivered"; + } + } + pub mod storage { + use super::runtime_types; + pub struct StorageApi; + impl StorageApi { + #[doc = " Optional pallet owner."] + #[doc = ""] + #[doc = " Pallet owner has a right to halt all pallet operations and then resume it. If it is"] + #[doc = " `None`, then there are no direct ways to halt/resume pallet operations, but other"] + #[doc = " runtime methods may still be used to do that (i.e. democracy::referendum to update halt"] + #[doc = " flag directly or call the `halt_operations`)."] + pub fn pallet_owner( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType<::sp_core::crypto::AccountId32>, + ::subxt::storage::address::Yes, + (), + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "PalletOwner", + vec![], + [ + 89u8, 42u8, 74u8, 119u8, 21u8, 164u8, 30u8, 115u8, 207u8, 126u8, 98u8, + 16u8, 162u8, 214u8, 67u8, 172u8, 178u8, 223u8, 139u8, 121u8, 174u8, + 89u8, 215u8, 75u8, 200u8, 161u8, 61u8, 195u8, 65u8, 222u8, 246u8, + 233u8, + ], + ) + } + #[doc = " The current operating mode of the pallet."] + #[doc = ""] + #[doc = " Depending on the mode either all, some, or no transactions will be allowed."] + pub fn pallet_operating_mode( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_messages::MessagesOperatingMode, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + (), + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "PalletOperatingMode", + vec![], + [ + 215u8, 195u8, 85u8, 231u8, 158u8, 22u8, 160u8, 132u8, 69u8, 206u8, + 238u8, 14u8, 56u8, 100u8, 134u8, 41u8, 58u8, 120u8, 225u8, 164u8, + 173u8, 87u8, 22u8, 123u8, 102u8, 167u8, 68u8, 70u8, 184u8, 131u8, + 232u8, 65u8, + ], + ) + } + #[doc = " Map of lane id => inbound lane data."] + pub fn inbound_lanes( + &self, + _0: impl ::std::borrow::Borrow, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_messages::InboundLaneData<::sp_core::crypto::AccountId32>, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "InboundLanes", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 38u8, 58u8, 110u8, 130u8, 112u8, 76u8, 231u8, 76u8, 56u8, 241u8, 183u8, + 153u8, 112u8, 41u8, 248u8, 208u8, 217u8, 57u8, 102u8, 30u8, 107u8, + 98u8, 59u8, 78u8, 56u8, 119u8, 186u8, 183u8, 213u8, 72u8, 199u8, 90u8, + ], + ) + } + #[doc = " Map of lane id => inbound lane data."] + pub fn inbound_lanes_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_messages::InboundLaneData<::sp_core::crypto::AccountId32>, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "InboundLanes", + Vec::new(), + [ + 38u8, 58u8, 110u8, 130u8, 112u8, 76u8, 231u8, 76u8, 56u8, 241u8, 183u8, + 153u8, 112u8, 41u8, 248u8, 208u8, 217u8, 57u8, 102u8, 30u8, 107u8, + 98u8, 59u8, 78u8, 56u8, 119u8, 186u8, 183u8, 213u8, 72u8, 199u8, 90u8, + ], + ) + } + #[doc = " Map of lane id => outbound lane data."] + pub fn outbound_lanes( + &self, + _0: impl ::std::borrow::Borrow, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_messages::OutboundLaneData, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "OutboundLanes", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 67u8, 155u8, 173u8, 244u8, 80u8, 38u8, 26u8, 71u8, 51u8, 150u8, 86u8, + 146u8, 132u8, 122u8, 70u8, 122u8, 172u8, 246u8, 106u8, 232u8, 149u8, + 227u8, 240u8, 146u8, 51u8, 184u8, 30u8, 182u8, 200u8, 43u8, 190u8, + 38u8, + ], + ) + } + #[doc = " Map of lane id => outbound lane data."] + pub fn outbound_lanes_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bp_messages::OutboundLaneData, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "OutboundLanes", + Vec::new(), + [ + 67u8, 155u8, 173u8, 244u8, 80u8, 38u8, 26u8, 71u8, 51u8, 150u8, 86u8, + 146u8, 132u8, 122u8, 70u8, 122u8, 172u8, 246u8, 106u8, 232u8, 149u8, + 227u8, 240u8, 146u8, 51u8, 184u8, 30u8, 182u8, 200u8, 43u8, 190u8, + 38u8, + ], + ) + } + #[doc = " All queued outbound messages."] + pub fn outbound_messages( + &self, + _0: impl ::std::borrow::Borrow, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + >, + ::subxt::storage::address::Yes, + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "OutboundMessages", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 44u8, 35u8, 2u8, 25u8, 91u8, 101u8, 152u8, 23u8, 48u8, 250u8, 178u8, + 15u8, 194u8, 118u8, 146u8, 1u8, 112u8, 83u8, 243u8, 166u8, 124u8, + 153u8, 48u8, 193u8, 43u8, 31u8, 33u8, 72u8, 228u8, 113u8, 86u8, 217u8, + ], + ) + } + #[doc = " All queued outbound messages."] + pub fn outbound_messages_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + >, + (), + (), + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "BridgeMillauMessages", + "OutboundMessages", + Vec::new(), + [ + 44u8, 35u8, 2u8, 25u8, 91u8, 101u8, 152u8, 23u8, 48u8, 250u8, 178u8, + 15u8, 194u8, 118u8, 146u8, 1u8, 112u8, 83u8, 243u8, 166u8, 124u8, + 153u8, 48u8, 193u8, 43u8, 31u8, 33u8, 72u8, 228u8, 113u8, 86u8, 217u8, + ], + ) + } + } + } + pub mod constants { + use super::runtime_types; + pub struct ConstantsApi; + impl ConstantsApi { + #[doc = " Gets the chain id value from the instance."] + pub fn bridged_chain_id( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<[::core::primitive::u8; 4usize]>, + > { + ::subxt::constants::StaticConstantAddress::new( + "BridgeMillauMessages", + "BridgedChainId", + [ + 101u8, 157u8, 37u8, 163u8, 190u8, 134u8, 129u8, 212u8, 240u8, 135u8, + 174u8, 76u8, 220u8, 179u8, 252u8, 69u8, 65u8, 253u8, 69u8, 214u8, 61u8, + 249u8, 4u8, 38u8, 181u8, 237u8, 25u8, 131u8, 242u8, 20u8, 17u8, 152u8, + ], + ) + } + #[doc = " Maximal encoded size of the outbound payload."] + pub fn maximal_outbound_payload_size( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "BridgeMillauMessages", + "MaximalOutboundPayloadSize", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + } + } + } + pub mod runtime_types { + use super::runtime_types; + pub mod bp_header_chain { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct StoredHeaderData<_0, _1> { + pub number: _0, + pub state_root: _1, + } + } + pub mod bp_messages { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct DeliveredMessages { + pub begin: ::core::primitive::u64, + pub end: ::core::primitive::u64, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct InboundLaneData<_0> { + pub relayers: ::std::vec::Vec>, + pub last_confirmed_nonce: ::core::primitive::u64, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct LaneId(pub [::core::primitive::u8; 4usize]); + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct MessageKey { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum MessagesOperatingMode { + #[codec(index = 0)] + Basic(runtime_types::bp_runtime::BasicOperatingMode), + #[codec(index = 1)] + RejectingOutboundMessages, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct OutboundLaneData { + pub oldest_unpruned_nonce: ::core::primitive::u64, + pub latest_received_nonce: ::core::primitive::u64, + pub latest_generated_nonce: ::core::primitive::u64, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum ReceivalResult<_0> { + #[codec(index = 0)] + Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), + #[codec(index = 1)] + InvalidNonce, + #[codec(index = 2)] + TooManyUnrewardedRelayers, + #[codec(index = 3)] + TooManyUnconfirmedMessages, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ReceivedMessages<_0> { + pub lane: runtime_types::bp_messages::LaneId, + pub receive_results: ::std::vec::Vec<( + ::core::primitive::u64, + runtime_types::bp_messages::ReceivalResult<_0>, + )>, + pub skipped_for_not_enough_weight: ::std::vec::Vec<::core::primitive::u64>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct UnrewardedRelayer<_0> { + pub relayer: _0, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + } + pub mod bp_runtime { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MessageDispatchResult<_0> { + pub unspent_weight: ::sp_weights::Weight, + pub dispatch_level_result: _0, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct HeaderId<_0, _1>(pub _1, pub _0); + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum OwnedBridgeModuleError { + #[codec(index = 0)] + Halted, + } + } + pub mod cumulus_pallet_dmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Service a single overweight message."] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "The message index given is unknown."] + Unknown, + #[codec(index = 1)] + #[doc = "The amount of weight given is possibly not enough for executing the message."] + OverLimit, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Downward message is invalid XCM."] + InvalidFormat { message_id: [::core::primitive::u8; 32usize] }, + #[codec(index = 1)] + #[doc = "Downward message is unsupported version of XCM."] + UnsupportedVersion { message_id: [::core::primitive::u8; 32usize] }, + #[codec(index = 2)] + #[doc = "Downward message executed with the given outcome."] + ExecutedDownward { + message_id: [::core::primitive::u8; 32usize], + outcome: runtime_types::xcm::v3::traits::Outcome, + }, + #[codec(index = 3)] + #[doc = "The weight limit for handling downward messages was reached."] + WeightExhausted { + message_id: [::core::primitive::u8; 32usize], + remaining_weight: ::sp_weights::Weight, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + #[doc = "Downward message is overweight and was placed in the overweight queue."] + OverweightEnqueued { + message_id: [::core::primitive::u8; 32usize], + overweight_index: ::core::primitive::u64, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 5)] + #[doc = "Downward message from the overweight queue was executed."] + OverweightServiced { + overweight_index: ::core::primitive::u64, + weight_used: ::sp_weights::Weight, + }, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ConfigData { + pub max_individual: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct PageIndexData { + pub begin_used: ::core::primitive::u32, + pub end_used: ::core::primitive::u32, + pub overweight_count: ::core::primitive::u64, + } + } + pub mod cumulus_pallet_parachain_system { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + # [codec (index = 0)] # [doc = "Set the current validation data."] # [doc = ""] # [doc = "This should be invoked exactly once per block. It will panic at the finalization"] # [doc = "phase if the call was not invoked."] # [doc = ""] # [doc = "The dispatch origin for this call must be `Inherent`"] # [doc = ""] # [doc = "As a side effect, this function upgrades the current validation function"] # [doc = "if the appropriate time has come."] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "Attempt to upgrade validation function while existing upgrade pending"] + OverlappingUpgrades, + #[codec(index = 1)] + #[doc = "Polkadot currently prohibits this parachain from upgrading its validation function"] + ProhibitedByPolkadot, + #[codec(index = 2)] + #[doc = "The supplied validation function has compiled into a blob larger than Polkadot is"] + #[doc = "willing to run"] + TooBig, + #[codec(index = 3)] + #[doc = "The inherent which supplies the validation data did not run this block"] + ValidationDataNotAvailable, + #[codec(index = 4)] + #[doc = "The inherent which supplies the host configuration did not run this block"] + HostConfigurationNotAvailable, + #[codec(index = 5)] + #[doc = "No validation function upgrade is currently scheduled."] + NotScheduled, + #[codec(index = 6)] + #[doc = "No code upgrade has been authorized."] + NothingAuthorized, + #[codec(index = 7)] + #[doc = "The given code upgrade has not been authorized."] + Unauthorized, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "The validation function has been scheduled to apply."] + ValidationFunctionStored, + #[codec(index = 1)] + #[doc = "The validation function was applied as of the contained relay chain block number."] + ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, + #[codec(index = 2)] + #[doc = "The relay-chain aborted the upgrade process."] + ValidationFunctionDiscarded, + #[codec(index = 3)] + #[doc = "An upgrade has been authorized."] + UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + #[doc = "Some downward messages have been received and will be processed."] + DownwardMessagesReceived { count: ::core::primitive::u32 }, + #[codec(index = 5)] + #[doc = "Downward messages were processed using the given weight."] + DownwardMessagesProcessed { + weight_used: ::sp_weights::Weight, + dmq_head: ::subxt::utils::H256, + }, + #[codec(index = 6)] + #[doc = "An upward message was sent to the relay chain."] + UpwardMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + pub mod relay_state_snapshot { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MessagingStateSnapshot { + pub dmq_mqc_head: ::subxt::utils::H256, + pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), + pub ingress_channels: ::std::vec::Vec<( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_primitives::v2::AbridgedHrmpChannel, + )>, + pub egress_channels: ::std::vec::Vec<( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_primitives::v2::AbridgedHrmpChannel, + )>, + } + } + } + pub mod cumulus_pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call {} + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error {} + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Downward message is invalid XCM."] + #[doc = "\\[ id \\]"] + InvalidFormat([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + #[doc = "Downward message is unsupported version of XCM."] + #[doc = "\\[ id \\]"] + UnsupportedVersion([::core::primitive::u8; 32usize]), + #[codec(index = 2)] + #[doc = "Downward message executed with the given outcome."] + #[doc = "\\[ id, outcome \\]"] + ExecutedDownward( + [::core::primitive::u8; 32usize], + runtime_types::xcm::v3::traits::Outcome, + ), + } + } + } + pub mod cumulus_pallet_xcmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Services a single overweight XCM."] + #[doc = ""] + #[doc = "- `origin`: Must pass `ExecuteOverweightOrigin`."] + #[doc = "- `index`: The index of the overweight XCM to service"] + #[doc = "- `weight_limit`: The amount of weight that XCM execution may take."] + #[doc = ""] + #[doc = "Errors:"] + #[doc = "- `BadOverweightIndex`: XCM under `index` is not found in the `Overweight` storage map."] + #[doc = "- `BadXcm`: XCM under `index` cannot be properly decoded into a valid XCM format."] + #[doc = "- `WeightOverLimit`: XCM execution may use greater `weight_limit`."] + #[doc = ""] + #[doc = "Events:"] + #[doc = "- `OverweightServiced`: On success."] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + #[codec(index = 1)] + #[doc = "Suspends all XCM executions for the XCMP queue, regardless of the sender's origin."] + #[doc = ""] + #[doc = "- `origin`: Must pass `ControllerOrigin`."] + suspend_xcm_execution, + #[codec(index = 2)] + #[doc = "Resumes all XCM executions for the XCMP queue."] + #[doc = ""] + #[doc = "Note that this function doesn't change the status of the in/out bound channels."] + #[doc = ""] + #[doc = "- `origin`: Must pass `ControllerOrigin`."] + resume_xcm_execution, + #[codec(index = 3)] + #[doc = "Overwrites the number of pages of messages which must be in the queue for the other side to be told to"] + #[doc = "suspend their sending."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.suspend_value`"] + update_suspend_threshold { new: ::core::primitive::u32 }, + #[codec(index = 4)] + #[doc = "Overwrites the number of pages of messages which must be in the queue after which we drop any further"] + #[doc = "messages from the channel."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.drop_threshold`"] + update_drop_threshold { new: ::core::primitive::u32 }, + #[codec(index = 5)] + #[doc = "Overwrites the number of pages of messages which the queue must be reduced to before it signals that"] + #[doc = "message sending may recommence after it has been suspended."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.resume_threshold`"] + update_resume_threshold { new: ::core::primitive::u32 }, + #[codec(index = 6)] + #[doc = "Overwrites the amount of remaining weight under which we stop processing messages."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.threshold_weight`"] + update_threshold_weight { new: ::sp_weights::Weight }, + #[codec(index = 7)] + #[doc = "Overwrites the speed to which the available weight approaches the maximum weight."] + #[doc = "A lower number results in a faster progression. A value of 1 makes the entire weight available initially."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.weight_restrict_decay`."] + update_weight_restrict_decay { new: ::sp_weights::Weight }, + #[codec(index = 8)] + #[doc = "Overwrite the maximum amount of weight any individual message may consume."] + #[doc = "Messages above this weight go into the overweight queue and may only be serviced explicitly."] + #[doc = ""] + #[doc = "- `origin`: Must pass `Root`."] + #[doc = "- `new`: Desired value for `QueueConfigData.xcmp_max_individual_weight`."] + update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "Failed to send XCM message."] + FailedToSend, + #[codec(index = 1)] + #[doc = "Bad XCM origin."] + BadXcmOrigin, + #[codec(index = 2)] + #[doc = "Bad XCM data."] + BadXcm, + #[codec(index = 3)] + #[doc = "Bad overweight index."] + BadOverweightIndex, + #[codec(index = 4)] + #[doc = "Provided weight is possibly not enough to execute the message."] + WeightOverLimit, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Some XCM was executed ok."] + Success { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + weight: ::sp_weights::Weight, + }, + #[codec(index = 1)] + #[doc = "Some XCM failed."] + Fail { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + error: runtime_types::xcm::v3::traits::Error, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + #[doc = "Bad XCM version used."] + BadVersion { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 3)] + #[doc = "Bad XCM format used."] + BadFormat { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 4)] + #[doc = "An HRMP message was sent to a sibling parachain."] + XcmpMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 5)] + #[doc = "An XCM exceeded the individual message weight budget."] + OverweightEnqueued { + sender: runtime_types::polkadot_parachain::primitives::Id, + sent_at: ::core::primitive::u32, + index: ::core::primitive::u64, + required: ::sp_weights::Weight, + }, + #[codec(index = 6)] + #[doc = "An XCM from the overweight queue was executed with the given actual weight used."] + OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct InboundChannelDetails { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, + pub message_metadata: ::std::vec::Vec<( + ::core::primitive::u32, + runtime_types::polkadot_parachain::primitives::XcmpMessageFormat, + )>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum InboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct OutboundChannelDetails { + pub recipient: runtime_types::polkadot_parachain::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, + pub signals_exist: ::core::primitive::bool, + pub first_index: ::core::primitive::u16, + pub last_index: ::core::primitive::u16, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum OutboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct QueueConfigData { + pub suspend_threshold: ::core::primitive::u32, + pub drop_threshold: ::core::primitive::u32, + pub resume_threshold: ::core::primitive::u32, + pub threshold_weight: ::sp_weights::Weight, + pub weight_restrict_decay: ::sp_weights::Weight, + pub xcmp_max_individual_weight: ::sp_weights::Weight, + } + } + pub mod cumulus_primitives_parachain_inherent { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct MessageQueueChain(pub ::subxt::utils::H256); + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ParachainInherentData { + pub validation_data: + runtime_types::polkadot_primitives::v2::PersistedValidationData< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, + pub downward_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundDownwardMessage< + ::core::primitive::u32, + >, + >, + pub horizontal_messages: ::subxt::utils::KeyedVec< + runtime_types::polkadot_parachain::primitives::Id, + ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundHrmpMessage< + ::core::primitive::u32, + >, + >, + >, + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Commit<_0, _1, _2, _3> { + pub target_hash: _0, + pub target_number: _1, + pub precommits: ::std::vec::Vec< + runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, + >, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct SignedPrecommit<_0, _1, _2, _3> { + pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, + pub signature: _2, + pub id: _3, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + } + pub mod traits { + use super::runtime_types; + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Make some on-chain remark."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(1)`"] + #[doc = "# "] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + #[doc = "Set the number of pages in the WebAssembly environment's heap."] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + #[doc = "Set the new runtime code."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code`"] + #[doc = "- 1 call to `can_set_code`: `O(S)` (calls `sp_io::misc::runtime_version` which is"] + #[doc = " expensive)."] + #[doc = "- 1 storage write (codec `O(C)`)."] + #[doc = "- 1 digest item."] + #[doc = "- 1 event."] + #[doc = "The weight of this function is dependent on the runtime, but generally this is very"] + #[doc = "expensive. We will treat this as a full block."] + #[doc = "# "] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + #[doc = "Set the new runtime code without doing any checks of the given `code`."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(C)` where `C` length of `code`"] + #[doc = "- 1 storage write (codec `O(C)`)."] + #[doc = "- 1 digest item."] + #[doc = "- 1 event."] + #[doc = "The weight of this function is dependent on the runtime. We will treat this as a full"] + #[doc = "block. # "] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + #[doc = "Set some items of storage."] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + #[doc = "Kill some items from storage."] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + #[doc = "Kill all storage items with a key that starts with the given prefix."] + #[doc = ""] + #[doc = "**NOTE:** We rely on the Root origin to provide us the number of subkeys under"] + #[doc = "the prefix we are removing to accurately calculate the weight of this function."] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + #[doc = "Make some on-chain remark and emit event."] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Error for the System pallet"] + pub enum Error { + #[codec(index = 0)] + #[doc = "The name of specification does not match between the current runtime"] + #[doc = "and the new runtime."] + InvalidSpecName, + #[codec(index = 1)] + #[doc = "The specification version is not allowed to decrease between the current runtime"] + #[doc = "and the new runtime."] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + #[doc = "Failed to extract the runtime version from the new runtime."] + #[doc = ""] + #[doc = "Either calling `Core_version` or decoding `RuntimeVersion` failed."] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + #[doc = "Suicide called when the account has non-default composite data."] + NonDefaultComposite, + #[codec(index = 4)] + #[doc = "There is a non-zero reference count preventing the account from being purged."] + NonZeroRefCount, + #[codec(index = 5)] + #[doc = "The origin filter prevent the call to be dispatched."] + CallFiltered, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Event for the System pallet."] + pub enum Event { + #[codec(index = 0)] + #[doc = "An extrinsic completed successfully."] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + #[doc = "An extrinsic failed."] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + #[doc = "`:code` was updated."] + CodeUpdated, + #[codec(index = 3)] + #[doc = "A new account was created."] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + #[doc = "An account was reaped."] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + #[doc = "On on-chain remark happened."] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Transfer some liquid free balance to another account."] + #[doc = ""] + #[doc = "`transfer` will set the `FreeBalance` of the sender and receiver."] + #[doc = "If the sender's account is below the existential deposit as a result"] + #[doc = "of the transfer, the account will be reaped."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be `Signed` by the transactor."] + #[doc = ""] + #[doc = "# "] + #[doc = "- Dependent on arguments but not critical, given proper implementations for input config"] + #[doc = " types. See related functions below."] + #[doc = "- It contains a limited number of reads and writes internally and no complex"] + #[doc = " computation."] + #[doc = ""] + #[doc = "Related functions:"] + #[doc = ""] + #[doc = " - `ensure_can_withdraw` is always called internally but has a bounded complexity."] + #[doc = " - Transferring balances to accounts that did not exist before will cause"] + #[doc = " `T::OnNewAccount::on_new_account` to be called."] + #[doc = " - Removing enough funds from an account will trigger `T::DustRemoval::on_unbalanced`."] + #[doc = " - `transfer_keep_alive` works the same way as `transfer`, but has an additional check"] + #[doc = " that the transfer will not kill the origin account."] + #[doc = "---------------------------------"] + #[doc = "- Origin account is already in memory, so no DB operations for them."] + #[doc = "# "] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + #[doc = "Set the balances of a given account."] + #[doc = ""] + #[doc = "This will alter `FreeBalance` and `ReservedBalance` in storage. it will"] + #[doc = "also alter the total issuance of the system (`TotalIssuance`) appropriately."] + #[doc = "If the new free or reserved balance is below the existential deposit,"] + #[doc = "it will reset the account nonce (`frame_system::AccountNonce`)."] + #[doc = ""] + #[doc = "The dispatch origin for this call is `root`."] + set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + #[codec(compact)] + new_reserved: ::core::primitive::u128, + }, + #[codec(index = 2)] + #[doc = "Exactly as `transfer`, except the origin must be root and the source account may be"] + #[doc = "specified."] + #[doc = "# "] + #[doc = "- Same as transfer, but additional read and write because the source account is not"] + #[doc = " assumed to be in the overlay."] + #[doc = "# "] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + #[doc = "Same as the [`transfer`] call, but with a check that the transfer will not kill the"] + #[doc = "origin account."] + #[doc = ""] + #[doc = "99% of the time you want [`transfer`] instead."] + #[doc = ""] + #[doc = "[`transfer`]: struct.Pallet.html#method.transfer"] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + #[doc = "Transfer the entire transferable balance from the caller account."] + #[doc = ""] + #[doc = "NOTE: This function only attempts to transfer _transferable_ balances. This means that"] + #[doc = "any locked, reserved, or existential deposits (when `keep_alive` is `true`), will not be"] + #[doc = "transferred by this function. To ensure that this function results in a killed account,"] + #[doc = "you might need to prepare the account by removing any reference counters, storage"] + #[doc = "deposits, etc..."] + #[doc = ""] + #[doc = "The dispatch origin of this call must be Signed."] + #[doc = ""] + #[doc = "- `dest`: The recipient of the transfer."] + #[doc = "- `keep_alive`: A boolean to determine if the `transfer_all` operation should send all"] + #[doc = " of the funds the account has, causing the sender account to be killed (false), or"] + #[doc = " transfer everything except at least the existential deposit, which will guarantee to"] + #[doc = " keep the sender account alive (true). # "] + #[doc = "- O(1). Just like transfer, but reading the user's transferable balance first."] + #[doc = " #"] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + #[doc = "Unreserve some balance from a user by force."] + #[doc = ""] + #[doc = "Can only be called by ROOT."] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "Vesting balance too high to send value"] + VestingBalance, + #[codec(index = 1)] + #[doc = "Account liquidity restrictions prevent withdrawal"] + LiquidityRestrictions, + #[codec(index = 2)] + #[doc = "Balance too low to send value."] + InsufficientBalance, + #[codec(index = 3)] + #[doc = "Value too low to create account due to existential deposit"] + ExistentialDeposit, + #[codec(index = 4)] + #[doc = "Transfer/payment would kill account"] + KeepAlive, + #[codec(index = 5)] + #[doc = "A vesting schedule already exists for this account"] + ExistingVestingSchedule, + #[codec(index = 6)] + #[doc = "Beneficiary account must pre-exist"] + DeadAccount, + #[codec(index = 7)] + #[doc = "Number of named reserves exceed MaxReserves"] + TooManyReserves, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "An account was created with some free balance."] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + #[doc = "An account was removed whose balance was non-zero but below ExistentialDeposit,"] + #[doc = "resulting in an outright loss."] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + #[doc = "Transfer succeeded."] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + #[doc = "A balance was set by root."] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + reserved: ::core::primitive::u128, + }, + #[codec(index = 4)] + #[doc = "Some balance was reserved (moved from free to reserved)."] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + #[doc = "Some balance was unreserved (moved from reserved to free)."] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + #[doc = "Some balance was moved from the reserve of the first account to the second account."] + #[doc = "Final argument indicates the destination balance type."] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + #[doc = "Some amount was deposited (e.g. for transaction fees)."] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + #[doc = "Some amount was withdrawn from the account (e.g. for transaction fees)."] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + #[doc = "Some amount was removed from the account (e.g. for misbehavior)."] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub misc_frozen: _0, + pub fee_frozen: _0, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::Reasons, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + pub mod pallet_bridge_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Verify a target header is finalized according to the given finality proof."] + #[doc = ""] + #[doc = "It will use the underlying storage pallet to fetch information about the current"] + #[doc = "authorities and best finalized header in order to verify that the header is finalized."] + #[doc = ""] + #[doc = "If successful in verification, it will write the target header to the underlying storage"] + #[doc = "pallet."] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + }, + #[codec(index = 1)] + #[doc = "Bootstrap the bridge pallet with an initial header and authority set from which to sync."] + #[doc = ""] + #[doc = "The initial configuration provided does not need to be the genesis header of the bridged"] + #[doc = "chain, it can be any arbitrary header. You can also provide the next scheduled set"] + #[doc = "change if it is already know."] + #[doc = ""] + #[doc = "This function is only allowed to be called from a trusted origin and writes to storage"] + #[doc = "with practically no checks in terms of the validity of the data. It is important that"] + #[doc = "you ensure that valid data is being passed in."] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u64, + ::bp_millau::BlakeTwoAndKeccak256, + >, + >, + }, + #[codec(index = 2)] + #[doc = "Change `PalletOwner`."] + #[doc = ""] + #[doc = "May only be called either by root, or by `PalletOwner`."] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + #[doc = "Halt or resume all pallet operations."] + #[doc = ""] + #[doc = "May only be called either by root, or by `PalletOwner`."] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "The given justification is invalid for the given header."] + InvalidJustification, + #[codec(index = 1)] + #[doc = "The authority set from the underlying header chain is invalid."] + InvalidAuthoritySet, + #[codec(index = 2)] + #[doc = "There are too many requests for the current window to handle."] + TooManyRequests, + #[codec(index = 3)] + #[doc = "The header being imported is older than the best finalized header known to the pallet."] + OldHeader, + #[codec(index = 4)] + #[doc = "The scheduled authority set change found in the header is unsupported by the pallet."] + #[doc = ""] + #[doc = "This is the case for non-standard (e.g forced) authority set changes."] + UnsupportedScheduledChange, + #[codec(index = 5)] + #[doc = "The pallet is not yet initialized."] + NotInitialized, + #[codec(index = 6)] + #[doc = "The pallet has already been initialized."] + AlreadyInitialized, + #[codec(index = 7)] + #[doc = "Too many authorities in the set."] + TooManyAuthoritiesInSet, + #[codec(index = 8)] + #[doc = "Error generated by the `OwnedBridgeModule` trait."] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + } + pub mod storage_types { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct StoredAuthoritySet { + pub authorities: runtime_types::sp_core::bounded::bounded_vec::BoundedVec<( + runtime_types::sp_finality_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + } + } + pub mod pallet_bridge_messages { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + # [codec (index = 0)] # [doc = "Change `PalletOwner`."] # [doc = ""] # [doc = "May only be called either by root, or by `PalletOwner`."] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] # [doc = "Halt or resume all/some pallet operations."] # [doc = ""] # [doc = "May only be called either by root, or by `PalletOwner`."] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] # [doc = "Receive messages proof from bridged chain."] # [doc = ""] # [doc = "The weight of the call assumes that the transaction always brings outbound lane"] # [doc = "state update. Because of that, the submitter (relayer) has no benefit of not including"] # [doc = "this data in the transaction, so reward confirmations lags should be minimal."] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: bp_millau :: MillauHash > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] # [doc = "Receive messages delivery proof from bridged chain."] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "Pallet is not in Normal operating mode."] + NotOperatingNormally, + #[codec(index = 1)] + #[doc = "The outbound lane is inactive."] + InactiveOutboundLane, + #[codec(index = 2)] + #[doc = "The message is too large to be sent over the bridge."] + MessageIsTooLarge, + #[codec(index = 3)] + #[doc = "Message has been treated as invalid by chain verifier."] + MessageRejectedByChainVerifier, + #[codec(index = 4)] + #[doc = "Message has been treated as invalid by lane verifier."] + MessageRejectedByLaneVerifier, + #[codec(index = 5)] + #[doc = "Submitter has failed to pay fee for delivering and dispatching messages."] + FailedToWithdrawMessageFee, + #[codec(index = 6)] + #[doc = "The transaction brings too many messages."] + TooManyMessagesInTheProof, + #[codec(index = 7)] + #[doc = "Invalid messages has been submitted."] + InvalidMessagesProof, + #[codec(index = 8)] + #[doc = "Invalid messages delivery proof has been submitted."] + InvalidMessagesDeliveryProof, + #[codec(index = 9)] + #[doc = "The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane)."] + InvalidUnrewardedRelayers, + #[codec(index = 10)] + #[doc = "The relayer has declared invalid unrewarded relayers state in the"] + #[doc = "`receive_messages_delivery_proof` call."] + InvalidUnrewardedRelayersState, + #[codec(index = 11)] + #[doc = "The message someone is trying to work with (i.e. increase fee) is already-delivered."] + MessageIsAlreadyDelivered, + #[codec(index = 12)] + #[doc = "The message someone is trying to work with (i.e. increase fee) is not yet sent."] + MessageIsNotYetSent, + #[codec(index = 13)] + #[doc = "The number of actually confirmed messages is going to be larger than the number of"] + #[doc = "messages in the proof. This may mean that this or bridged chain storage is corrupted."] + TryingToConfirmMoreMessagesThanExpected, + #[codec(index = 14)] + #[doc = "Error generated by the `OwnedBridgeModule` trait."] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Message has been accepted and is waiting to be delivered."] + MessageAccepted { + lane_id: runtime_types::bp_messages::LaneId, + nonce: ::core::primitive::u64, + }, + #[codec(index = 1)] + #[doc = "Messages have been received from the bridged chain."] + MessagesReceived( + ::std::vec::Vec>, + ), + #[codec(index = 2)] + #[doc = "Messages in the inclusive range have been delivered to the bridged chain."] + MessagesDelivered { + lane_id: runtime_types::bp_messages::LaneId, + messages: runtime_types::bp_messages::DeliveredMessages, + }, + } + } + } + pub mod pallet_bridge_relayers { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Claim accumulated rewards."] + claim_rewards { lane_id: runtime_types::bp_messages::LaneId }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "No reward can be claimed by given relayer."] + NoRewardForRelayer, + #[codec(index = 1)] + #[doc = "Reward payment procedure has failed."] + FailedToPayReward, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Reward has been paid to the relayer."] + RewardPaid { + relayer: ::sp_core::crypto::AccountId32, + lane_id: runtime_types::bp_messages::LaneId, + reward: ::core::primitive::u128, + }, + } + } + } + pub mod pallet_sudo { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- Limited storage reads."] + #[doc = "- One DB write (event)."] + #[doc = "- Weight of derivative `call` execution + 10,000."] + #[doc = "# "] + sudo { + call: + ::std::boxed::Box, + }, + #[codec(index = 1)] + #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] + #[doc = "This function does not check the weight of the call, and instead allows the"] + #[doc = "Sudo user to specify the weight of the call."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- The weight of this call is defined by the caller."] + #[doc = "# "] + sudo_unchecked_weight { + call: + ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + #[doc = "Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo"] + #[doc = "key."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- Limited storage reads."] + #[doc = "- One DB change."] + #[doc = "# "] + set_key { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + #[doc = "Authenticates the sudo key and dispatches a function call with `Signed` origin from"] + #[doc = "a given account."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be _Signed_."] + #[doc = ""] + #[doc = "# "] + #[doc = "- O(1)."] + #[doc = "- Limited storage reads."] + #[doc = "- One DB write (event)."] + #[doc = "- Weight of derivative `call` execution + 10,000."] + #[doc = "# "] + sudo_as { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: + ::std::boxed::Box, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Error for the Sudo pallet"] + pub enum Error { + #[codec(index = 0)] + #[doc = "Sender must be the Sudo account"] + RequireSudo, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "A sudo just took place. \\[result\\]"] + Sudid { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + #[doc = "The \\[sudoer\\] just switched identity; the old key is supplied if one existed."] + KeyChanged { + old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 2)] + #[doc = "A sudo just took place. \\[result\\]"] + SudoAsDone { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + #[doc = "Set the current time."] + #[doc = ""] + #[doc = "This call should be invoked exactly once per block. It will panic at the finalization"] + #[doc = "phase, if this call hasn't been invoked by that time."] + #[doc = ""] + #[doc = "The timestamp should be greater than the previous one by the amount specified by"] + #[doc = "`MinimumPeriod`."] + #[doc = ""] + #[doc = "The dispatch origin for this call must be `Inherent`."] + #[doc = ""] + #[doc = "# "] + #[doc = "- `O(1)` (Note that implementations of `OnTimestampSet` must also be `O(1)`)"] + #[doc = "- 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in"] + #[doc = " `on_finalize`)"] + #[doc = "- 1 event handler `on_timestamp_set`. Must be `O(1)`."] + #[doc = "# "] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,"] + #[doc = "has been paid by `who`."] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + #[doc = "Teleport some assets from the local chain to some destination chain."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] + #[doc = "with all fees taken as needed from the asset."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] + #[doc = " `dest` side. May not be empty."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] + #[doc = "chain and forward a notification XCM."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] + #[doc = "with all fees taken as needed from the asset."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] + #[doc = " `dest` side."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + #[doc = "Execute an XCM message from a local, signed, origin."] + #[doc = ""] + #[doc = "An event is deposited indicating whether `msg` could be executed completely or only"] + #[doc = "partially."] + #[doc = ""] + #[doc = "No more than `max_weight` will be used in its attempted execution. If this is less than the"] + #[doc = "maximum amount of weight that the message could take to be executed, then no execution"] + #[doc = "attempt will be made."] + #[doc = ""] + #[doc = "NOTE: A successful return to this does *not* imply that the `msg` was executed successfully"] + #[doc = "to completion; only that *some* of it was executed."] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + #[doc = "Extoll that a particular destination can be communicated with through a particular"] + #[doc = "version of XCM."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `location`: The destination that is being described."] + #[doc = "- `xcm_version`: The latest version of XCM that `location` supports."] + force_xcm_version { + location: + ::std::boxed::Box, + xcm_version: ::core::primitive::u32, + }, + #[codec(index = 5)] + #[doc = "Set a safe XCM version (the version that XCM should be encoded with if the most recent"] + #[doc = "version a destination can accept is unknown)."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `maybe_xcm_version`: The default XCM encoding version, or `None` to disable."] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + #[doc = "Ask a location to notify us regarding their XCM version and any changes to it."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `location`: The location to which we should subscribe for XCM version notifications."] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + #[doc = "Require that a particular destination should no longer notify us regarding any XCM"] + #[doc = "version changes."] + #[doc = ""] + #[doc = "- `origin`: Must be Root."] + #[doc = "- `location`: The location to which we are currently subscribed for XCM version"] + #[doc = " notifications which we no longer desire."] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] + #[doc = "chain and forward a notification XCM."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] + #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] + #[doc = "at risk."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] + #[doc = " `dest` side."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + #[doc = "Teleport some assets from the local chain to some destination chain."] + #[doc = ""] + #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] + #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] + #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] + #[doc = "at risk."] + #[doc = ""] + #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] + #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] + #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] + #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] + #[doc = " an `AccountId32` value."] + #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] + #[doc = " `dest` side. May not be empty."] + #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] + #[doc = " fees."] + #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + pub enum Error { + #[codec(index = 0)] + #[doc = "The desired destination was unreachable, generally because there is a no way of routing"] + #[doc = "to it."] + Unreachable, + #[codec(index = 1)] + #[doc = "There was some other issue (i.e. not to do with routing) in sending the message. Perhaps"] + #[doc = "a lack of space for buffering the message."] + SendFailure, + #[codec(index = 2)] + #[doc = "The message execution fails the filter."] + Filtered, + #[codec(index = 3)] + #[doc = "The message's weight could not be determined."] + UnweighableMessage, + #[codec(index = 4)] + #[doc = "The destination `MultiLocation` provided cannot be inverted."] + DestinationNotInvertible, + #[codec(index = 5)] + #[doc = "The assets to be sent are empty."] + Empty, + #[codec(index = 6)] + #[doc = "Could not re-anchor the assets to declare the fees for the destination chain."] + CannotReanchor, + #[codec(index = 7)] + #[doc = "Too many assets have been attempted for transfer."] + TooManyAssets, + #[codec(index = 8)] + #[doc = "Origin is invalid for sending."] + InvalidOrigin, + #[codec(index = 9)] + #[doc = "The version of the `Versioned` value used is not able to be interpreted."] + BadVersion, + #[codec(index = 10)] + #[doc = "The given location could not be used (e.g. because it cannot be expressed in the"] + #[doc = "desired version of XCM)."] + BadLocation, + #[codec(index = 11)] + #[doc = "The referenced subscription could not be found."] + NoSubscription, + #[codec(index = 12)] + #[doc = "The location is invalid since it already has a subscription from us."] + AlreadySubscribed, + #[codec(index = 13)] + #[doc = "Invalid asset for the operation."] + InvalidAsset, + #[codec(index = 14)] + #[doc = "The owner does not own (all) of the asset that they wish to do the operation on."] + LowBalance, + #[codec(index = 15)] + #[doc = "The asset owner has too many locks on the asset."] + TooManyLocks, + #[codec(index = 16)] + #[doc = "The given account is not an identifiable sovereign account for any location."] + AccountNotSovereign, + #[codec(index = 17)] + #[doc = "The operation required fees to be paid which the initiator could not meet."] + FeesNotMet, + #[codec(index = 18)] + #[doc = "A remote lock with the corresponding data could not be found."] + LockNotFound, + #[codec(index = 19)] + #[doc = "The unlock operation cannot succeed because there are still users of the lock."] + InUse, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Execution of an XCM message was attempted."] + #[doc = ""] + #[doc = "\\[ outcome \\]"] + Attempted(runtime_types::xcm::v3::traits::Outcome), + #[codec(index = 1)] + #[doc = "A XCM message was sent."] + #[doc = ""] + #[doc = "\\[ origin, destination, message \\]"] + Sent( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::Xcm, + ), + #[codec(index = 2)] + #[doc = "Query response received which does not match a registered query. This may be because a"] + #[doc = "matching query was never registered, it may be because it is a duplicate response, or"] + #[doc = "because the query timed out."] + #[doc = ""] + #[doc = "\\[ origin location, id \\]"] + UnexpectedResponse( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 3)] + #[doc = "Query response has been received and is ready for taking with `take_response`. There is"] + #[doc = "no registered notification call."] + #[doc = ""] + #[doc = "\\[ id, response \\]"] + ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + #[codec(index = 4)] + #[doc = "Query response has been received and query is removed. The registered notification has"] + #[doc = "been dispatched and executed successfully."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index \\]"] + Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + #[codec(index = 5)] + #[doc = "Query response has been received and query is removed. The registered notification could"] + #[doc = "not be dispatched because the dispatch weight is greater than the maximum weight"] + #[doc = "originally budgeted by this runtime for the query result."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index, actual weight, max budgeted weight \\]"] + NotifyOverweight( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ::sp_weights::Weight, + ::sp_weights::Weight, + ), + #[codec(index = 6)] + #[doc = "Query response has been received and query is removed. There was a general error with"] + #[doc = "dispatching the notification call."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index \\]"] + NotifyDispatchError( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 7)] + #[doc = "Query response has been received and query is removed. The dispatch was unable to be"] + #[doc = "decoded into a `Call`; this might be due to dispatch function having a signature which"] + #[doc = "is not `(origin, QueryId, Response)`."] + #[doc = ""] + #[doc = "\\[ id, pallet index, call index \\]"] + NotifyDecodeFailed( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 8)] + #[doc = "Expected query response has been received but the origin location of the response does"] + #[doc = "not match that expected. The query remains registered for a later, valid, response to"] + #[doc = "be received and acted upon."] + #[doc = ""] + #[doc = "\\[ origin location, id, expected location \\]"] + InvalidResponder( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 9)] + #[doc = "Expected query response has been received but the expected origin location placed in"] + #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] + #[doc = ""] + #[doc = "This is unexpected (since a location placed in storage in a previously executing"] + #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] + #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] + #[doc = "needed."] + #[doc = ""] + #[doc = "\\[ origin location, id \\]"] + InvalidResponderVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 10)] + #[doc = "Received query response has been read and removed."] + #[doc = ""] + #[doc = "\\[ id \\]"] + ResponseTaken(::core::primitive::u64), + #[codec(index = 11)] + #[doc = "Some assets have been placed in an asset trap."] + #[doc = ""] + #[doc = "\\[ hash, origin, assets \\]"] + AssetsTrapped( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + #[codec(index = 12)] + #[doc = "An XCM version change notification message has been attempted to be sent."] + #[doc = ""] + #[doc = "The cost of sending it (borne by the chain) is included."] + #[doc = ""] + #[doc = "\\[ destination, result, cost \\]"] + VersionChangeNotified( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 13)] + #[doc = "The supported version of a location has been changed. This might be through an"] + #[doc = "automatic notification or a manual intervention."] + #[doc = ""] + #[doc = "\\[ location, XCM version \\]"] + SupportedVersionChanged( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + ), + #[codec(index = 14)] + #[doc = "A given location which had a version change subscription was dropped owing to an error"] + #[doc = "sending the notification to it."] + #[doc = ""] + #[doc = "\\[ location, query ID, error \\]"] + NotifyTargetSendFail( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::traits::Error, + ), + #[codec(index = 15)] + #[doc = "A given location which had a version change subscription was dropped owing to an error"] + #[doc = "migrating the location to our new XCM format."] + #[doc = ""] + #[doc = "\\[ location, query ID \\]"] + NotifyTargetMigrationFail( + runtime_types::xcm::VersionedMultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 16)] + #[doc = "Expected query response has been received but the expected querier location placed in"] + #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] + #[doc = ""] + #[doc = "This is unexpected (since a location placed in storage in a previously executing"] + #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] + #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] + #[doc = "needed."] + #[doc = ""] + #[doc = "\\[ origin location, id \\]"] + InvalidQuerierVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 17)] + #[doc = "Expected query response has been received but the querier location of the response does"] + #[doc = "not match the expected. The query remains registered for a later, valid, response to"] + #[doc = "be received and acted upon."] + #[doc = ""] + #[doc = "\\[ origin location, id, expected querier, maybe actual querier \\]"] + InvalidQuerier( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 18)] + #[doc = "A remote has requested XCM version change notification from us and we have honored it."] + #[doc = "A version information message is sent to them and its cost is included."] + #[doc = ""] + #[doc = "\\[ destination location, cost \\]"] + VersionNotifyStarted( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 19)] + #[doc = "We have requested that a remote chain sends us XCM version change notifications."] + #[doc = ""] + #[doc = "\\[ destination location, cost \\]"] + VersionNotifyRequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 20)] + #[doc = "We have requested that a remote chain stops sending us XCM version change notifications."] + #[doc = ""] + #[doc = "\\[ destination location, cost \\]"] + VersionNotifyUnrequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 21)] + #[doc = "Fees were paid from a location for an operation (often for using `SendXcm`)."] + #[doc = ""] + #[doc = "\\[ paying location, fees \\]"] + FeesPaid( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 22)] + #[doc = "Some assets have been claimed from an asset trap"] + #[doc = ""] + #[doc = "\\[ hash, origin, assets \\]"] + AssetsClaimed( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum XcmpMessageFormat { + #[codec(index = 0)] + ConcatenatedVersionedXcm, + #[codec(index = 1)] + ConcatenatedEncodedBlob, + #[codec(index = 2)] + Signals, + } + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v2 { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct AbridgedHostConfiguration { + pub max_code_size: ::core::primitive::u32, + pub max_head_data_size: ::core::primitive::u32, + pub max_upward_queue_count: ::core::primitive::u32, + pub max_upward_queue_size: ::core::primitive::u32, + pub max_upward_message_size: ::core::primitive::u32, + pub max_upward_message_num_per_candidate: ::core::primitive::u32, + pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, + pub validation_upgrade_cooldown: ::core::primitive::u32, + pub validation_upgrade_delay: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct AbridgedHrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct PersistedValidationData<_0, _1> { + pub parent_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub relay_parent_number: _1, + pub relay_parent_storage_root: _0, + pub max_pov_size: _1, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + } + } + pub mod rialto_parachain_runtime { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Runtime; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 2)] + Sudo(runtime_types::pallet_sudo::pallet::Call), + #[codec(index = 20)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), + #[codec(index = 30)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 50)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), + #[codec(index = 51)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 52)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Call), + #[codec(index = 53)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), + #[codec(index = 54)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + #[codec(index = 55)] + BridgeMillauGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 56)] + BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Call), + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 2)] + Sudo(runtime_types::pallet_sudo::pallet::Event), + #[codec(index = 4)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 20)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), + #[codec(index = 30)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 50)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), + #[codec(index = 51)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 52)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), + #[codec(index = 53)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), + #[codec(index = 54)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 56)] + BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Event), + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_core { + use super::runtime_types; + pub mod bounded { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod ecdsa { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + } + pub mod sp_finality_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, + ); + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum TokenError { + #[codec(index = 0)] + NoFunds, + #[codec(index = 1)] + WouldDie, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_trie { + use super::runtime_types; + pub mod storage_proof { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct StorageProof { + pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Xcm(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey([::core::primitive::u8; 32usize]), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 2)] + TruncatedError(::std::vec::Vec<::core::primitive::u8>), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: ::std::vec::Vec<::core::primitive::u8>, + pub module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct QueryResponseInfo { + pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo(runtime_types::xcm::v3::VecPalletInfo), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct VecPalletInfo(pub ::std::vec::Vec); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct Xcm(pub ::std::vec::Vec); + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum VersionedMultiAssets { + #[codec(index = 0)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum VersionedMultiLocation { + #[codec(index = 0)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + V3(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + } + } + #[doc = r" The default error type returned when there is a runtime issue,"] + #[doc = r" exposed here for ease of use."] + pub type DispatchError = runtime_types::sp_runtime::DispatchError; + pub fn constants() -> ConstantsApi { + ConstantsApi + } + pub fn storage() -> StorageApi { + StorageApi + } + pub fn tx() -> TransactionApi { + TransactionApi + } + pub struct ConstantsApi; + impl ConstantsApi { + pub fn system(&self) -> system::constants::ConstantsApi { + system::constants::ConstantsApi + } + pub fn timestamp(&self) -> timestamp::constants::ConstantsApi { + timestamp::constants::ConstantsApi + } + pub fn transaction_payment(&self) -> transaction_payment::constants::ConstantsApi { + transaction_payment::constants::ConstantsApi + } + pub fn balances(&self) -> balances::constants::ConstantsApi { + balances::constants::ConstantsApi + } + pub fn bridge_millau_grandpa(&self) -> bridge_millau_grandpa::constants::ConstantsApi { + bridge_millau_grandpa::constants::ConstantsApi + } + pub fn bridge_millau_messages(&self) -> bridge_millau_messages::constants::ConstantsApi { + bridge_millau_messages::constants::ConstantsApi + } + } + pub struct StorageApi; + impl StorageApi { + pub fn system(&self) -> system::storage::StorageApi { + system::storage::StorageApi + } + pub fn timestamp(&self) -> timestamp::storage::StorageApi { + timestamp::storage::StorageApi + } + pub fn sudo(&self) -> sudo::storage::StorageApi { + sudo::storage::StorageApi + } + pub fn randomness_collective_flip( + &self, + ) -> randomness_collective_flip::storage::StorageApi { + randomness_collective_flip::storage::StorageApi + } + pub fn transaction_payment(&self) -> transaction_payment::storage::StorageApi { + transaction_payment::storage::StorageApi + } + pub fn parachain_system(&self) -> parachain_system::storage::StorageApi { + parachain_system::storage::StorageApi + } + pub fn parachain_info(&self) -> parachain_info::storage::StorageApi { + parachain_info::storage::StorageApi + } + pub fn balances(&self) -> balances::storage::StorageApi { + balances::storage::StorageApi + } + pub fn xcmp_queue(&self) -> xcmp_queue::storage::StorageApi { + xcmp_queue::storage::StorageApi + } + pub fn dmp_queue(&self) -> dmp_queue::storage::StorageApi { + dmp_queue::storage::StorageApi + } + pub fn bridge_relayers(&self) -> bridge_relayers::storage::StorageApi { + bridge_relayers::storage::StorageApi + } + pub fn bridge_millau_grandpa(&self) -> bridge_millau_grandpa::storage::StorageApi { + bridge_millau_grandpa::storage::StorageApi + } + pub fn bridge_millau_messages(&self) -> bridge_millau_messages::storage::StorageApi { + bridge_millau_messages::storage::StorageApi + } + } + pub struct TransactionApi; + impl TransactionApi { + pub fn system(&self) -> system::calls::TransactionApi { + system::calls::TransactionApi + } + pub fn timestamp(&self) -> timestamp::calls::TransactionApi { + timestamp::calls::TransactionApi + } + pub fn sudo(&self) -> sudo::calls::TransactionApi { + sudo::calls::TransactionApi + } + pub fn parachain_system(&self) -> parachain_system::calls::TransactionApi { + parachain_system::calls::TransactionApi + } + pub fn balances(&self) -> balances::calls::TransactionApi { + balances::calls::TransactionApi + } + pub fn xcmp_queue(&self) -> xcmp_queue::calls::TransactionApi { + xcmp_queue::calls::TransactionApi + } + pub fn polkadot_xcm(&self) -> polkadot_xcm::calls::TransactionApi { + polkadot_xcm::calls::TransactionApi + } + pub fn cumulus_xcm(&self) -> cumulus_xcm::calls::TransactionApi { + cumulus_xcm::calls::TransactionApi + } + pub fn dmp_queue(&self) -> dmp_queue::calls::TransactionApi { + dmp_queue::calls::TransactionApi + } + pub fn bridge_relayers(&self) -> bridge_relayers::calls::TransactionApi { + bridge_relayers::calls::TransactionApi + } + pub fn bridge_millau_grandpa(&self) -> bridge_millau_grandpa::calls::TransactionApi { + bridge_millau_grandpa::calls::TransactionApi + } + pub fn bridge_millau_messages(&self) -> bridge_millau_messages::calls::TransactionApi { + bridge_millau_messages::calls::TransactionApi + } + } + #[doc = r" check whether the Client you are using is aligned with the statically generated codegen."] + pub fn validate_codegen>( + client: &C, + ) -> Result<(), ::subxt::error::MetadataError> { + let runtime_metadata_hash = client.metadata().metadata_hash(&PALLETS); + if runtime_metadata_hash != + [ + 29u8, 217u8, 238u8, 58u8, 9u8, 201u8, 174u8, 206u8, 19u8, 133u8, 133u8, 32u8, + 139u8, 251u8, 132u8, 7u8, 135u8, 118u8, 231u8, 231u8, 9u8, 150u8, 246u8, 171u8, + 190u8, 93u8, 114u8, 63u8, 86u8, 200u8, 148u8, 126u8, + ] { + Err(::subxt::error::MetadataError::IncompatibleMetadata) + } else { + Ok(()) + } + } +} diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index d6efd6581b24d..2c3792725c389 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the Rialto-Substrate chain. -pub mod runtime_wrapper; +pub mod codegen_runtime; use bp_messages::MessageNonce; use bp_polkadot_core::PolkadotSignedExtension; @@ -29,7 +29,12 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use std::time::Duration; -pub use runtime_wrapper as runtime; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::rialto_parachain_runtime::RuntimeCall; +pub type SudoCall = runtime_types::pallet_sudo::pallet::Call; +pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; /// The address format for describing accounts. pub type Address = MultiAddress; @@ -51,12 +56,13 @@ impl Chain for RialtoParachain { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); type SignedBlock = bp_polkadot_core::SignedBlock; - type Call = runtime::Call; + type Call = runtime_types::rialto_parachain_runtime::RuntimeCall; } impl ChainWithBalances for RialtoParachain { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_polkadot_core::AccountInfoStorageMapKeyProvider::final_key(account_id) + let key = codegen_runtime::api::storage().system().account(account_id); + StorageKey(key.to_bytes()) } } diff --git a/relays/client-rialto-parachain/src/runtime_wrapper.rs b/relays/client-rialto-parachain/src/runtime_wrapper.rs deleted file mode 100644 index b595d145d012d..0000000000000 --- a/relays/client-rialto-parachain/src/runtime_wrapper.rs +++ /dev/null @@ -1,57 +0,0 @@ -// 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 . - -//! Types that are specific to the `RialtoParachain` runtime. Normally we could use the full -//! `RialtoParachain` runtime here, since it is constructed in this repo and we have access to it. -//! However we use a wrapped runtime instead in order to test the indirect runtime calls -//! functionality. - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -use bp_header_chain::BridgeGrandpaCallOf; -use bridge_runtime_common::messages::BridgeMessagesCallOf; -use relay_substrate_client::calls::{SudoCall, XcmCall}; - -// The indirect pallet call used to sync `Millau` GRANDPA finality to `RialtoParachain`. -pub type BridgeMillauGrandpaCall = BridgeGrandpaCallOf; -// The indirect pallet call used to sync `Millau` messages to `RialtoParachain`. -pub type BridgeMillauMessagesCall = BridgeMessagesCallOf; - -/// `RialtoParachain` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `RialtoParachain` chain. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `RialtoParachain` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// `Sudo` pallet. - #[codec(index = 2)] - Sudo(SudoCall), - - /// `Xcm` pallet. - #[codec(index = 51)] - PolkadotXcm(XcmCall), - - /// Millau GRANDPA bridge pallet. - #[codec(index = 55)] - BridgeMillauGrandpa(BridgeMillauGrandpaCall), - /// Millau messages bridge pallet. - #[codec(index = 56)] - BridgeMillauMessages(BridgeMillauMessagesCall), -} From 4140846e44fd165dc3a9f1534560288873a19fda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:21:47 +0000 Subject: [PATCH 0918/1210] Bump futures from 0.3.25 to 0.3.26 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.25 to 0.3.26. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.25...0.3.26) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 050be02e37eaf..1a16f3466f398 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.12" +futures = "0.3.26" hex = "0.4" log = "0.4.17" num-format = "0.4" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 9b3a58f27c296..49201defdd1d6 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.7" +futures = "0.3.26" jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 401a02b2ca14f..c3e32eb59b271 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } -futures = "0.3.5" +futures = "0.3.26" log = "0.4.17" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index e044be0957c74..933c9f859a0e3 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,7 @@ thiserror = "1.0.26" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.12" +futures = "0.3.26" hex = "0.4" num-traits = "0.2" log = "0.4.17" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index e4564dac15f29..c4d2459e5cad0 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" -futures = "0.3.5" +futures = "0.3.26" hex = "0.4" log = "0.4.17" num-traits = "0.2" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index a6e74ecb581c1..55124930db563 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" async-trait = "0.1.63" -futures = "0.3.5" +futures = "0.3.26" log = "0.4.17" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 0909bfee7a9fa..57eeb7fbc8c07 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1" backoff = "0.4" isahc = "1.2" env_logger = "0.10.0" -futures = "0.3.5" +futures = "0.3.26" jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" From 8ef52de8310c6c3ccd1390008662327309a8c6e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 02:26:29 +0000 Subject: [PATCH 0919/1210] Bump trie-db from 0.24.0 to 0.25.0 Bumps [trie-db](https://github.com/paritytech/trie) from 0.24.0 to 0.25.0. - [Release notes](https://github.com/paritytech/trie/releases) - [Commits](https://github.com/paritytech/trie/commits/trie-db-v0.25.0) --- updated-dependencies: - dependency-name: trie-db dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index f8d698696deea..515d6e1a6c4a9 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master 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 } -trie-db = { version = "0.24.0", default-features = false } +trie-db = { version = "0.25.0", default-features = false } [dev-dependencies] hex-literal = "0.3" From b5370e9c45d967db692d048c6d0088a32ffb345c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 09:28:14 +0300 Subject: [PATCH 0920/1210] Bump serde_json from 1.0.91 to 1.0.92 (#1845) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.91 to 1.0.92. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.91...v1.0.92) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index f2c0762d3d283..af2c50eb4804b 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.4", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.79" +serde_json = "1.0.92" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 88c354f9c15db..bf8b348473235 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.4", features = ["derive"] } -serde_json = "1.0.79" +serde_json = "1.0.92" # Bridge dependencies From 15b3945143183d385c356d6bbf5af46c85aa0215 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 06:31:42 +0000 Subject: [PATCH 0921/1210] Bump async-trait from 0.1.63 to 0.1.64 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.63 to 0.1.64. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.63...0.1.64) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 55124930db563..093fc0b94e3fa 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.63" +async-trait = "0.1.64" futures = "0.3.26" log = "0.4.17" relay-utils = { path = "../utils" } From 20c37fc61f9a53c4c67ff106f840dc24421b6741 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Feb 2023 13:20:52 +0300 Subject: [PATCH 0922/1210] Update Substrate/Polkadot/Cumulus dependencies + weights v2 (#1850) * cargo update * weights v2 * clippy * no spellcheck for weights.rs * fix proof_size component in MAXIMUM_BLOCK_WEIGHT constants * "fix" proof_size in select_delivery_transaction_limits_works * spellcheck --- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/node/src/cli.rs | 1 + bin/millau/node/src/service.rs | 2 +- bin/millau/runtime/src/lib.rs | 15 +- bin/rialto-parachain/runtime/src/lib.rs | 6 + bin/rialto/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/cli.rs | 1 + bin/rialto/runtime/src/lib.rs | 15 +- modules/grandpa/src/weights.rs | 120 ++++- modules/messages/src/weights.rs | 456 +++++++++++++++--- modules/parachains/src/weights.rs | 228 ++++++++- modules/relayers/src/weights.rs | 50 +- primitives/beefy/Cargo.toml | 2 +- primitives/beefy/src/lib.rs | 2 +- primitives/chain-millau/src/lib.rs | 8 +- primitives/chain-rialto-parachain/src/lib.rs | 8 +- primitives/chain-rialto/src/lib.rs | 8 +- primitives/polkadot-core/src/lib.rs | 6 +- .../lib-substrate-relay/src/messages_lane.rs | 8 +- 19 files changed, 807 insertions(+), 133 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 8b0bc28ed1466..9cd01167e13ba 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -202,7 +202,7 @@ fn testnet_genesis( balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, aura: AuraConfig { authorities: Vec::new() }, - beefy: BeefyConfig { authorities: Vec::new() }, + beefy: BeefyConfig { authorities: Vec::new(), genesis_block: Some(0) }, grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs index 0280254bcada8..12499b5718d6d 100644 --- a/bin/millau/node/src/cli.rs +++ b/bin/millau/node/src/cli.rs @@ -28,6 +28,7 @@ pub struct Cli { /// Possible subcommands of the main binary. #[derive(Debug, Parser)] +#[allow(clippy::large_enum_variant)] pub enum Subcommand { /// Key management CLI utilities #[clap(subcommand)] diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 6ad63387da4f2..8b0bc828957f0 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -125,7 +125,7 @@ pub fn new_partial( let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( client.clone(), - &(client.clone() as Arc<_>), + &client, select_chain.clone(), telemetry.as_ref().map(|x| x.handle()), )?; diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b0dc28cf27ed8..b590a2399d09a 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -61,7 +61,9 @@ pub use frame_support::{ construct_runtime, dispatch::DispatchClass, parameter_types, - traits::{ConstU32, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, + traits::{ + ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, + }, weights::{ constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, @@ -240,6 +242,7 @@ impl pallet_grandpa::Config for Runtime { // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); type MaxAuthorities = ConstU32<10>; + type MaxSetIdSessionEntries = ConstU64<0>; } /// MMR helper types. @@ -752,6 +755,12 @@ impl_runtime_apis! { fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { TransactionPayment::query_fee_details(uxt, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } } impl sp_session::SessionKeys for Runtime { @@ -767,6 +776,10 @@ impl_runtime_apis! { } impl sp_beefy::BeefyApi for Runtime { + fn beefy_genesis() -> Option { + Beefy::genesis_block() + } + fn validator_set() -> Option> { Beefy::validator_set() } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 2bc787c495358..6fd6c24ebeb17 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -735,6 +735,12 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } } impl bp_millau::MillauFinalityApi for Runtime { diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 5085c2dc71cbe..6d6d21fc14bef 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -213,7 +213,7 @@ fn testnet_genesis( authorities: Vec::new(), epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), }, - beefy: BeefyConfig { authorities: Vec::new() }, + beefy: BeefyConfig { authorities: Vec::new(), genesis_block: Some(0) }, grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 0cdd25417e7f0..98323c9d9ca65 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -28,6 +28,7 @@ pub struct Cli { /// Possible subcommands of the main binary. #[derive(Debug, Parser)] +#[allow(clippy::large_enum_variant)] pub enum Subcommand { /// Key management CLI utilities #[clap(subcommand)] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index d9b07d582fb20..5ead9b32dc13f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -57,7 +57,9 @@ pub use frame_support::{ construct_runtime, dispatch::DispatchClass, parameter_types, - traits::{ConstU32, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem}, + traits::{ + ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, + }, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, RuntimeDbWeight, Weight}, StorageValue, }; @@ -263,6 +265,7 @@ impl pallet_grandpa::Config for Runtime { type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); + type MaxSetIdSessionEntries = ConstU64<0>; } impl pallet_mmr::Config for Runtime { @@ -626,6 +629,10 @@ impl_runtime_apis! { } impl sp_beefy::BeefyApi for Runtime { + fn beefy_genesis() -> Option { + Beefy::genesis_block() + } + fn validator_set() -> Option> { Beefy::validator_set() } @@ -864,6 +871,12 @@ impl_runtime_apis! { fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { TransactionPayment::query_fee_details(uxt, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } } impl sp_session::SessionKeys for Runtime { diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index d6c3d596d88eb..3c3a62083832d 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for `pallet_bridge_grandpa` +//! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 -//! LOW RANGE: [], HIGH RANGE: [] -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 1024 +//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // target/release/millau-bridge-node @@ -48,7 +48,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for `pallet_bridge_grandpa`. +/// Weight functions needed for pallet_bridge_grandpa. pub trait WeightInfo { fn submit_finality_proof(p: u32, v: u32) -> Weight; } @@ -58,22 +58,110 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { + /// Storage: BridgeRialtoGrandpa PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa RequestCount (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa RequestCount (max_values: Some(1), max_size: Some(4), added: 499, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa BestFinalized (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: + /// 531, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa CurrentAuthoritySet (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(40970), + /// added: 41465, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHashesPointer (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), + /// added: 499, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: None, max_size: Some(36), added: + /// 2511, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// The range of component `p` is `[51, 102]`. + /// + /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { - Weight::from_ref_time(192_130_822 as u64) - .saturating_add(Weight::from_ref_time(39_781_096 as u64).saturating_mul(p as u64)) - .saturating_add(Weight::from_ref_time(1_365_108 as u64).saturating_mul(v as u64)) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) + // Proof Size summary in bytes: + // Measured: `2524 + p * (40 ±0)` + // Estimated: `46001` + // Minimum execution time: 2_282_140 nanoseconds. + Weight::from_parts(142_496_714, 46001) + // Standard Error: 32_796 + .saturating_add(Weight::from_ref_time(40_232_935).saturating_mul(p.into())) + // Standard Error: 33_574 + .saturating_add(Weight::from_ref_time(1_185_407).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(6_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { + /// Storage: BridgeRialtoGrandpa PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa RequestCount (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa RequestCount (max_values: Some(1), max_size: Some(4), added: 499, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa BestFinalized (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: + /// 531, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa CurrentAuthoritySet (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(40970), + /// added: 41465, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHashesPointer (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), + /// added: 499, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: None, max_size: Some(36), added: + /// 2511, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// The range of component `p` is `[51, 102]`. + /// + /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { - Weight::from_ref_time(192_130_822 as u64) - .saturating_add(Weight::from_ref_time(39_781_096 as u64).saturating_mul(p as u64)) - .saturating_add(Weight::from_ref_time(1_365_108 as u64).saturating_mul(v as u64)) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().writes(6 as u64)) + // Proof Size summary in bytes: + // Measured: `2524 + p * (40 ±0)` + // Estimated: `46001` + // Minimum execution time: 2_282_140 nanoseconds. + Weight::from_parts(142_496_714, 46001) + // Standard Error: 32_796 + .saturating_add(Weight::from_ref_time(40_232_935).saturating_mul(p.into())) + // Standard Error: 33_574 + .saturating_add(Weight::from_ref_time(1_185_407).saturating_mul(v.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(6_u64)) } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 344b9587d6887..0e25850888571 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for `pallet_bridge_messages` +//! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-12, STEPS: 50, REPEAT: 20 -//! LOW RANGE: [], HIGH RANGE: [] -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 1024 +//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // target/release/millau-bridge-node @@ -48,7 +48,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for `pallet_bridge_messages`. +/// Weight functions needed for pallet_bridge_messages. pub trait WeightInfo { fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; @@ -65,88 +65,436 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// Storage: Balances TotalIssuance (r:1 w:1) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(95_401_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `693` + // Estimated: `55198` + // Minimum execution time: 47_968 nanoseconds. + Weight::from_parts(48_937_000, 55198) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// Storage: Balances TotalIssuance (r:1 w:1) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(127_794_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `693` + // Estimated: `55198` + // Minimum execution time: 63_831 nanoseconds. + Weight::from_parts(85_093_000, 55198) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// Storage: Balances TotalIssuance (r:1 w:1) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(105_698_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `693` + // Estimated: `55198` + // Minimum execution time: 53_775 nanoseconds. + Weight::from_parts(55_113_000, 55198) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(92_963_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `54695` + // Minimum execution time: 54_314 nanoseconds. + Weight::from_parts(55_804_000, 54695) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(158_449_000 as u64) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `54695` + // Minimum execution time: 103_050 nanoseconds. + Weight::from_parts(106_715_000, 54695) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: + /// 2519, mode: MaxEncodedLen) + /// + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(72_085_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `579` + // Estimated: `8094` + // Minimum execution time: 42_111 nanoseconds. + Weight::from_parts(43_168_000, 8094) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: + /// 2519, mode: MaxEncodedLen) + /// + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(70_889_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `596` + // Estimated: `8094` + // Minimum execution time: 40_094 nanoseconds. + Weight::from_parts(41_140_000, 8094) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: + /// 2519, mode: MaxEncodedLen) + /// + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(78_211_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Proof Size summary in bytes: + // Measured: `596` + // Estimated: `10629` + // Minimum execution time: 42_498 nanoseconds. + Weight::from_parts(43_494_000, 10629) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// Storage: Balances TotalIssuance (r:1 w:1) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) fn receive_single_message_proof() -> Weight { - Weight::from_ref_time(95_401_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `693` + // Estimated: `55198` + // Minimum execution time: 47_968 nanoseconds. + Weight::from_parts(48_937_000, 55198) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// Storage: Balances TotalIssuance (r:1 w:1) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) fn receive_two_messages_proof() -> Weight { - Weight::from_ref_time(127_794_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `693` + // Estimated: `55198` + // Minimum execution time: 63_831 nanoseconds. + Weight::from_parts(85_093_000, 55198) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// Storage: Balances TotalIssuance (r:1 w:1) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - Weight::from_ref_time(105_698_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `693` + // Estimated: `55198` + // Minimum execution time: 53_775 nanoseconds. + Weight::from_parts(55_113_000, 55198) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_1_kb() -> Weight { - Weight::from_ref_time(92_963_000 as u64) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `54695` + // Minimum execution time: 54_314 nanoseconds. + Weight::from_parts(55_804_000, 54695) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_16_kb() -> Weight { - Weight::from_ref_time(158_449_000 as u64) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `54695` + // Minimum execution time: 103_050 nanoseconds. + Weight::from_parts(106_715_000, 54695) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: + /// 2519, mode: MaxEncodedLen) + /// + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) fn receive_delivery_proof_for_single_message() -> Weight { - Weight::from_ref_time(72_085_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `579` + // Estimated: `8094` + // Minimum execution time: 42_111 nanoseconds. + Weight::from_parts(43_168_000, 8094) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: + /// 2519, mode: MaxEncodedLen) + /// + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - Weight::from_ref_time(70_889_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `596` + // Estimated: `8094` + // Minimum execution time: 40_094 nanoseconds. + Weight::from_parts(41_140_000, 8094) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: + /// 2519, mode: MaxEncodedLen) + /// + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - Weight::from_ref_time(78_211_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + // Proof Size summary in bytes: + // Measured: `596` + // Estimated: `10629` + // Minimum execution time: 42_498 nanoseconds. + Weight::from_parts(43_494_000, 10629) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } } diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 54f468b7636cf..f6dc73d40c32d 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for `pallet_bridge_parachains` +//! Autogenerated weights for pallet_bridge_parachains //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 -//! LOW RANGE: [], HIGH RANGE: [] -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 1024 +//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // target/release/millau-bridge-node @@ -48,7 +48,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for `pallet_bridge_parachains`. +/// Weight functions needed for pallet_bridge_parachains. pub trait WeightInfo { fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight; fn submit_parachain_heads_with_1kb_proof() -> Weight; @@ -60,38 +60,214 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { - fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { - Weight::from_ref_time(52_445_014 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), + /// added: 2539, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), + /// added: 2671, mode: MaxEncodedLen) + /// + /// The range of component `p` is `[1, 2]`. + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { + // Proof Size summary in bytes: + // Measured: `366` + // Estimated: `8113` + // Minimum execution time: 35_348 nanoseconds. + Weight::from_parts(36_906_961, 8113) + // Standard Error: 136_143 + .saturating_add(Weight::from_ref_time(148_169).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), + /// added: 2539, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), + /// added: 2671, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { - Weight::from_ref_time(55_253_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Proof Size summary in bytes: + // Measured: `366` + // Estimated: `8113` + // Minimum execution time: 43_295 nanoseconds. + Weight::from_parts(48_018_000, 8113) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), + /// added: 2539, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), + /// added: 2671, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { - Weight::from_ref_time(98_772_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) + // Proof Size summary in bytes: + // Measured: `366` + // Estimated: `8113` + // Minimum execution time: 86_112 nanoseconds. + Weight::from_parts(88_901_000, 8113) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { - fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { - Weight::from_ref_time(52_445_014 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), + /// added: 2539, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), + /// added: 2671, mode: MaxEncodedLen) + /// + /// The range of component `p` is `[1, 2]`. + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { + // Proof Size summary in bytes: + // Measured: `366` + // Estimated: `8113` + // Minimum execution time: 35_348 nanoseconds. + Weight::from_parts(36_906_961, 8113) + // Standard Error: 136_143 + .saturating_add(Weight::from_ref_time(148_169).saturating_mul(p.into())) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), + /// added: 2539, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), + /// added: 2671, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { - Weight::from_ref_time(55_253_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + // Proof Size summary in bytes: + // Measured: `366` + // Estimated: `8113` + // Minimum execution time: 43_295 nanoseconds. + Weight::from_parts(48_018_000, 8113) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// added: 496, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: + /// 2543, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), + /// added: 2539, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), + /// added: 2671, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { - Weight::from_ref_time(98_772_000 as u64) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) + // Proof Size summary in bytes: + // Measured: `366` + // Estimated: `8113` + // Minimum execution time: 86_112 nanoseconds. + Weight::from_parts(88_901_000, 8113) + .saturating_add(RocksDbWeight::get().reads(4_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) } } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 9bbaa343e1205..fdaeee4f22a3e 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for `pallet_bridge_relayers` +//! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-12-21, STEPS: 50, REPEAT: 20 -//! LOW RANGE: [], HIGH RANGE: [] -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled -//! CHAIN: Some("dev"), DB CACHE: 1024 +//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: // target/release/millau-bridge-node @@ -48,7 +48,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for `pallet_bridge_relayers`. +/// Weight functions needed for pallet_bridge_relayers. pub trait WeightInfo { fn claim_rewards() -> Weight; } @@ -58,18 +58,44 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: System Account (r:1 w:1) + /// + /// Proof: System Account (max_values: None, max_size: Some(96), added: 2571, mode: + /// MaxEncodedLen) fn claim_rewards() -> Weight { - Weight::from_ref_time(64_832_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `534` + // Estimated: `5106` + // Minimum execution time: 48_239 nanoseconds. + Weight::from_parts(50_579_000, 5106) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) } } // For backwards compatibility and tests impl WeightInfo for () { + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// mode: MaxEncodedLen) + /// + /// Storage: System Account (r:1 w:1) + /// + /// Proof: System Account (max_values: None, max_size: Some(96), added: 2571, mode: + /// MaxEncodedLen) fn claim_rewards() -> Weight { - Weight::from_ref_time(64_832_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) + // Proof Size summary in bytes: + // Measured: `534` + // Estimated: `5106` + // Minimum execution time: 48_239 nanoseconds. + Weight::from_parts(50_579_000, 5106) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) } } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index cc8360c7106ac..58cc268e698c9 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -17,7 +17,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -beefy-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +binary-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index 8b2b05d551fe8..042d1d0e66134 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -pub use beefy_merkle_tree::{merkle_root, Keccak256 as BeefyKeccak256}; +pub use binary_merkle_tree::merkle_root; pub use pallet_beefy_mmr::BeefyEcdsaToEthereum; pub use pallet_mmr::{ primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof}, diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index afe8fbca69cac..73515a7f4097b 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -59,10 +59,10 @@ pub const TX_EXTRA_BYTES: u32 = 103; /// Maximum weight of single Millau block. /// /// This represents 0.5 seconds of compute assuming a target block time of six seconds. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) - .set_proof_size(1_000) - .saturating_div(2); +/// +/// Max PoV size is set to max value, since it isn't important for relay/standalone chains. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), u64::MAX); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index d39fe25378369..e49f3d14dc5f2 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -54,10 +54,10 @@ pub const TX_EXTRA_BYTES: u32 = 104; /// Maximal weight of single RialtoParachain block. /// /// This represents two seconds of compute assuming a target block time of six seconds. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) - .set_proof_size(1_000) - .saturating_mul(2); +/// +/// Max PoV size is set to `5Mb` as all Cumulus-based parachains do. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), 5 * 1024 * 1024); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 5cf4f85f54a53..ca0a3dfee88d6 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -48,10 +48,10 @@ pub const TX_EXTRA_BYTES: u32 = 104; /// Maximal weight of single Rialto block. /// /// This represents two seconds of compute assuming a target block time of six seconds. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) - .set_proof_size(1_000) - .saturating_mul(2); +/// +/// Max PoV size is set to max value, since it isn't important for relay/standalone chains. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX); /// Represents the portion of a block that will be used by Normal extrinsics. pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index d5a9b5de817be..1d9e9f7a009c7 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -71,10 +71,8 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// All Polkadot-like chains allow 2 seconds of compute with a 6-second average block time. /// /// This is a copy-paste from the Polkadot repo's `polkadot-runtime-common` crate. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` -pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) - .set_proof_size(1_000) - .saturating_mul(2); +pub const MAXIMUM_BLOCK_WEIGHT: Weight = + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX); /// All Polkadot-like chains assume that an on-initialize consumes 1 percent of the weight on /// average, hence a single extrinsic will not be allowed to consume more than diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index b41ee2072e040..16fb1301ea043 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -501,8 +501,12 @@ mod tests { // // Any significant change in this values should attract additional attention. // - // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` - (1024, Weight::from_ref_time(216_600_684_000).set_proof_size(217)), + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - the `proof_size` + // component is too large here! + ( + 1024, + Weight::from_ref_time(216_600_106_667).set_proof_size(7_993_589_098_607_472_367) + ), ); } } From 6a1c1c1999ee03a075ac01d6e49e39117d79d74a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Feb 2023 15:39:26 +0300 Subject: [PATCH 0923/1210] Decrease number of GRANDPA authorities in Polkadot-like chains from 100_000 to 2_048 (#1852) * decrease number of GRANDPA authorities in Polkadot-like chains from 100_000 to 2048 * spelling --- primitives/chain-rococo/src/lib.rs | 5 ----- primitives/chain-westend/src/lib.rs | 5 ----- primitives/polkadot-core/src/lib.rs | 10 ++++++++++ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 57a47211e4ea3..41fc65e0e93d1 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -42,9 +42,4 @@ pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -/// Maximal number of GRANDPA authorities at Rococo. -/// -/// Corresponds to the `MaxAuthorities` constant value from the Rococo runtime configuration. -pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; - decl_bridge_finality_runtime_apis!(rococo); diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 8a3794b418e02..910a6c4acbd01 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -63,11 +63,6 @@ pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; /// Name of the With-Westend parachains bridge pallet instance that is deployed at bridged chains. pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains"; -/// Maximal number of GRANDPA authorities at Westend. -/// -/// Corresponds to the `MaxAuthorities` constant value from the Westend runtime configuration. -pub const MAX_AUTHORITIES_COUNT: u32 = 100_000; - /// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet. /// /// It includes the block number and state root, so it shall be near 40 bytes, but let's have some diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 1d9e9f7a009c7..b13ceb5df50d4 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -43,6 +43,16 @@ pub use sp_runtime::{traits::Convert, Perbill}; pub mod parachains; +/// Maximal number of GRANDPA authorities at Polkadot-like chains. +/// +/// Ideally, we would set it to the value of `MaxAuthorities` constant from bridged runtime +/// configurations. But right now it is set to the `100_000`, which makes PoV size for +/// our bridge hub parachains huge. So let's stick to the real-world value here. +/// +/// Right now both Kusama and Polkadot aim to have around 1000 validators. Let's be safe here and +/// take twice as much here. +pub const MAX_AUTHORITIES_COUNT: u32 = 2_048; + /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Polkadot-like chain. This mostly depends on number of entries in the storage trie. /// Some reserve is reserved to account future chain growth. From 2635c6fa4756fd7d9de2c1619cffeb39298ebfb2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 6 Feb 2023 15:56:34 +0300 Subject: [PATCH 0924/1210] Fix `HeadersToKeep` and `MaxBridgedAuthorities` in Millau benchmarks (#1851) * fix `HeadersToKeep` and `MaxBridgedAuthorities` in Millau benchmarks * typo * impl review suggestion --- bin/millau/runtime/src/lib.rs | 22 ++----------- bin/rialto-parachain/runtime/src/lib.rs | 4 +-- bin/rialto/runtime/src/lib.rs | 4 +-- modules/grandpa/src/benchmarking.rs | 33 ++++++++++--------- modules/grandpa/src/lib.rs | 21 ++++++++++-- modules/grandpa/src/weights.rs | 44 ++++++++++++------------- 6 files changed, 65 insertions(+), 63 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b590a2399d09a..2119fa04610be 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -387,30 +387,12 @@ impl pallet_bridge_relayers::Config for Runtime { type WeightInfo = (); } -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - /// Number of headers to keep in benchmarks. - /// - /// In benchmarks we always populate with full number of `HeadersToKeep` to make sure that - /// pruning is taken into account. - /// - /// Note: This is lower than regular value, to speed up benchmarking setup. - pub const HeadersToKeep: u32 = 1024; - /// Maximal number of authorities at Rialto. - /// - /// In benchmarks we're using sets of up to `1024` authorities to prepare for possible - /// upgrades in the future and see if performance degrades when number of authorities - /// grow. - pub const MaxAuthoritiesAtRialto: u32 = pallet_bridge_grandpa::benchmarking::MAX_VALIDATOR_SET_SIZE; -} - -#[cfg(not(feature = "runtime-benchmarks"))] parameter_types! { /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a - /// week. - pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS; + /// day. + pub const HeadersToKeep: u32 = bp_rialto::DAYS; /// Maximal number of authorities at Rialto. pub const MaxAuthoritiesAtRialto: u32 = bp_rialto::MAX_AUTHORITIES_COUNT; } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 6fd6c24ebeb17..be457d950415f 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -533,8 +533,8 @@ parameter_types! { /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a - /// week. - pub const HeadersToKeep: u32 = 7 * bp_millau::DAYS as u32; + /// day. + pub const HeadersToKeep: u32 = bp_millau::DAYS as u32; /// Maximal number of authorities at Millau. pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 5ead9b32dc13f..cb3b6d604866b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -401,8 +401,8 @@ parameter_types! { /// Number of headers to keep. /// /// Assuming the worst case of every header being finalized, we will keep headers at least for a - /// week. - pub const HeadersToKeep: u32 = 7 * bp_rialto::DAYS; + /// day. + pub const HeadersToKeep: u32 = bp_rialto::DAYS; /// Maximal number of authorities at Millau. pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index e937f7a0bf414..84a80eace2458 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -53,26 +53,29 @@ use sp_finality_grandpa::AuthorityId; use sp_runtime::traits::Zero; use sp_std::vec::Vec; -// The maximum number of vote ancestries to include in a justification. -// -// In practice this would be limited by the session length (number of blocks a single authority set -// can produce) of a given chain. +/// The maximum number of vote ancestries to include in a justification. +/// +/// In practice this would be limited by the session length (number of blocks a single authority set +/// can produce) of a given chain. const MAX_VOTE_ANCESTRIES: u32 = 1000; -// The maximum number of pre-commits to include in a justification. In practice this scales with the -// number of validators. -pub const MAX_VALIDATOR_SET_SIZE: u32 = 1024; - -// `1..MAX_VALIDATOR_SET_SIZE` and `1..MAX_VOTE_ANCESTRIES` are too large && benchmarks are -// running for almost 40m (steps=50, repeat=20) on a decent laptop, which is too much. Since -// we're building linear function here, let's just select some limited subrange for benchmarking. -const VALIDATOR_SET_SIZE_RANGE_BEGIN: u32 = MAX_VALIDATOR_SET_SIZE / 20; -const VALIDATOR_SET_SIZE_RANGE_END: u32 = - VALIDATOR_SET_SIZE_RANGE_BEGIN + VALIDATOR_SET_SIZE_RANGE_BEGIN; +// `1..MAX_VOTE_ANCESTRIES` is too large && benchmarks are running for almost 40m (steps=50, +// repeat=20) on a decent laptop, which is too much. Since we're building linear function here, +// let's just select some limited subrange for benchmarking. const MAX_VOTE_ANCESTRIES_RANGE_BEGIN: u32 = MAX_VOTE_ANCESTRIES / 20; const MAX_VOTE_ANCESTRIES_RANGE_END: u32 = MAX_VOTE_ANCESTRIES_RANGE_BEGIN + MAX_VOTE_ANCESTRIES_RANGE_BEGIN; +// the same with validators - if there are too much validators, let's run benchmarks on subrange +fn validator_set_range_end, I: 'static>() -> u32 { + let max_bridged_authorities = T::MaxBridgedAuthorities::get(); + if max_bridged_authorities > 128 { + sp_std::cmp::max(128, max_bridged_authorities / 5) + } else { + max_bridged_authorities + } +} + /// Returns number of first header to be imported. /// /// Since we bootstrap the pallet with `HeadersToKeep` already imported headers, @@ -117,7 +120,7 @@ benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to // annotate the weight in the pallet. submit_finality_proof { - let p in VALIDATOR_SET_SIZE_RANGE_BEGIN..VALIDATOR_SET_SIZE_RANGE_END; + let p in 1 .. validator_set_range_end::(); let v in MAX_VOTE_ANCESTRIES_RANGE_BEGIN..MAX_VOTE_ANCESTRIES_RANGE_END; let caller: T::AccountId = whitelisted_caller(); let (header, justification) = prepare_benchmark_data::(p, v); diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 3cf67349b474a..493475cf4ed39 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -104,6 +104,9 @@ pub mod pallet { #[pallet::constant] type MaxRequests: Get; + // Avoid using `HeadersToKeep` directly in the pallet code. Use `headers_to_keep` function + // instead. + /// Maximal number of finalized headers to keep in the storage. /// /// The setting is there to prevent growing the on-chain state indefinitely. Note @@ -464,6 +467,20 @@ pub mod pallet { })?) } + /// Return number of headers to keep in the runtime storage. + #[cfg(not(feature = "runtime-benchmarks"))] + pub(crate) fn headers_to_keep, I: 'static>() -> u32 { + T::HeadersToKeep::get() + } + + /// Return number of headers to keep in the runtime storage. + #[cfg(feature = "runtime-benchmarks")] + pub(crate) fn headers_to_keep, I: 'static>() -> u32 { + // every db operation (significantly) slows down benchmarks, so let's keep as min as + // possible + 2 + } + /// Import a previously verified header to the storage. /// /// Note this function solely takes care of updating the storage and pruning old entries, @@ -479,7 +496,7 @@ pub mod pallet { >::insert(index, hash); // Update ring buffer pointer and remove old header. - >::put((index + 1) % T::HeadersToKeep::get()); + >::put((index + 1) % headers_to_keep::()); if let Ok(hash) = pruning { log::debug!(target: LOG_TARGET, "Pruning old header: {:?}.", hash); >::remove(hash); @@ -523,7 +540,7 @@ pub mod pallet { init_params: super::InitializationData>, ) { let start_number = *init_params.header.number(); - let end_number = start_number + T::HeadersToKeep::get().into(); + let end_number = start_number + headers_to_keep::().into(); initialize_bridge::(init_params).expect("benchmarks are correct"); let mut number = start_number; diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 3c3a62083832d..e8971d69b484b 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -75,8 +75,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa CurrentAuthoritySet (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(40970), - /// added: 41465, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(209), + /// added: 704, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoGrandpa ImportedHashesPointer (r:1 w:1) /// @@ -93,19 +93,19 @@ impl WeightInfo for BridgeWeight { /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: /// 2543, mode: MaxEncodedLen) /// - /// The range of component `p` is `[51, 102]`. + /// The range of component `p` is `[1, 5]`. /// /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { // Proof Size summary in bytes: - // Measured: `2524 + p * (40 ±0)` - // Estimated: `46001` - // Minimum execution time: 2_282_140 nanoseconds. - Weight::from_parts(142_496_714, 46001) - // Standard Error: 32_796 - .saturating_add(Weight::from_ref_time(40_232_935).saturating_mul(p.into())) - // Standard Error: 33_574 - .saturating_add(Weight::from_ref_time(1_185_407).saturating_mul(v.into())) + // Measured: `459 + p * (40 ±0)` + // Estimated: `5240` + // Minimum execution time: 368_734 nanoseconds. + Weight::from_parts(64_214_587, 5240) + // Standard Error: 226_504 + .saturating_add(Weight::from_ref_time(41_231_918).saturating_mul(p.into())) + // Standard Error: 20_667 + .saturating_add(Weight::from_ref_time(2_770_962).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -130,8 +130,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa CurrentAuthoritySet (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(40970), - /// added: 41465, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(209), + /// added: 704, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoGrandpa ImportedHashesPointer (r:1 w:1) /// @@ -148,19 +148,19 @@ impl WeightInfo for () { /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: /// 2543, mode: MaxEncodedLen) /// - /// The range of component `p` is `[51, 102]`. + /// The range of component `p` is `[1, 5]`. /// /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { // Proof Size summary in bytes: - // Measured: `2524 + p * (40 ±0)` - // Estimated: `46001` - // Minimum execution time: 2_282_140 nanoseconds. - Weight::from_parts(142_496_714, 46001) - // Standard Error: 32_796 - .saturating_add(Weight::from_ref_time(40_232_935).saturating_mul(p.into())) - // Standard Error: 33_574 - .saturating_add(Weight::from_ref_time(1_185_407).saturating_mul(v.into())) + // Measured: `459 + p * (40 ±0)` + // Estimated: `5240` + // Minimum execution time: 368_734 nanoseconds. + Weight::from_parts(64_214_587, 5240) + // Standard Error: 226_504 + .saturating_add(Weight::from_ref_time(41_231_918).saturating_mul(p.into())) + // Standard Error: 20_667 + .saturating_add(Weight::from_ref_time(2_770_962).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } From 193fe1377b62f1303aed1950ba35c762605a9f6b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Feb 2023 10:38:36 +0300 Subject: [PATCH 0925/1210] changed some tests for weights v2 (#1855) --- modules/messages/src/weights_ext.rs | 14 ++++++++++++++ relays/lib-substrate-relay/Cargo.toml | 2 +- relays/lib-substrate-relay/src/messages_lane.rs | 16 +++++++--------- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index b763ca69024e8..b2133f06460c4 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -45,6 +45,20 @@ pub fn ensure_weights_are_correct() { // verify `receive_messages_delivery_proof` weight components assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::zero()); assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); + + // verify `receive_message_proof` weight + let receive_messages_proof_weight = + W::receive_messages_proof_weight(&PreComputedSize(1), 10, Weight::from_ref_time(0)); + assert_ne!(receive_messages_proof_weight.ref_time(), 0); + assert_ne!(receive_messages_proof_weight.proof_size(), 0); + + // verify `receive_message_proof` weight + let receive_messages_delivery_proof_weight = W::receive_messages_delivery_proof_weight( + &PreComputedSize(1), + &UnrewardedRelayersState::default(), + ); + assert_ne!(receive_messages_delivery_proof_weight.ref_time(), 0); + assert_ne!(receive_messages_delivery_proof_weight.proof_size(), 0); } /// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain. diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 933c9f859a0e3..96fe9356fa0fc 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -48,8 +48,8 @@ sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] -bp-millau = { path = "../../primitives/chain-millau" } bp-rialto = { path = "../../primitives/chain-rialto" } +bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 16fb1301ea043..1a4f65ff51e10 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -487,10 +487,14 @@ mod tests { pallet_bridge_messages::weights::BridgeWeight; #[test] - fn select_delivery_transaction_limits_works() { + fn select_delivery_transaction_limits_is_sane() { + // we want to check the `proof_size` component here too. But for Rialto and Millau + // it is set to `u64::MAX` (as for Polkadot and other relay/standalone chains). + // So let's use RialtoParachain limits here - it has `proof_size` limit as all + // Cumulus-based parachains do. let (max_count, max_weight) = select_delivery_transaction_limits::( - bp_millau::Millau::max_extrinsic_weight(), + bp_rialto_parachain::RialtoParachain::max_extrinsic_weight(), bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, ); assert_eq!( @@ -500,13 +504,7 @@ mod tests { // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. // // Any significant change in this values should attract additional attention. - // - // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - the `proof_size` - // component is too large here! - ( - 1024, - Weight::from_ref_time(216_600_106_667).set_proof_size(7_993_589_098_607_472_367) - ), + (1024, Weight::from_parts(866_600_106_667, 2_271_915)), ); } } From dcc395996ebd8f2b9d5fc540b25f96e6e22c4f6c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 7 Feb 2023 09:52:05 +0200 Subject: [PATCH 0926/1210] Use parity-util-mem 0.12.0 (#1856) --- primitives/chain-millau/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 1032e46b65812..7600781d89169 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -17,7 +17,7 @@ fixed-hash = { version = "0.8.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", optional = true } -parity-util-mem = { version = "0.11.0", default-features = false, features = ["primitive-types"] } +parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 9a68e8ccc2db6..a9db53a8bf01e 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -parity-util-mem = { version = "0.11.0", optional = true } +parity-util-mem = { version = "0.12.0", optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } From a569173b07ef3731b9ffd840c4ab35e8f0aec202 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Feb 2023 11:30:34 +0300 Subject: [PATCH 0927/1210] fixed BEEFY genesis (#1858) --- bin/millau/node/src/chain_spec.rs | 2 +- bin/rialto/node/src/chain_spec.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 9cd01167e13ba..d18634eb9836d 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -202,7 +202,7 @@ fn testnet_genesis( balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, aura: AuraConfig { authorities: Vec::new() }, - beefy: BeefyConfig { authorities: Vec::new(), genesis_block: Some(0) }, + beefy: BeefyConfig::default(), grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 6d6d21fc14bef..345778755adb5 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -213,7 +213,7 @@ fn testnet_genesis( authorities: Vec::new(), epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), }, - beefy: BeefyConfig { authorities: Vec::new(), genesis_block: Some(0) }, + beefy: BeefyConfig::default(), grandpa: GrandpaConfig { authorities: Vec::new() }, sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { From 2db3e56aa097b8efe3450622ef2ee9b9509b9587 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Feb 2023 12:38:25 +0300 Subject: [PATCH 0928/1210] Message delivery transaction is not free!!! (#1859) * message delivery transaction is not free!!! * test pays_fee --- modules/messages/src/lib.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index ec895955076c0..21e5a6a9a8548 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -398,7 +398,7 @@ pub mod pallet { Self::deposit_event(Event::MessagesReceived(messages_received_status)); - Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::No }) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } /// Receive messages delivery proof from bridged chain. @@ -899,6 +899,7 @@ mod tests { use bp_test_utils::generate_owned_bridge_module_tests; use frame_support::{ assert_noop, assert_ok, + dispatch::Pays, storage::generator::{StorageMap, StorageValue}, traits::Hooks, weights::Weight, @@ -1543,16 +1544,19 @@ mod tests { messages_count, REGULAR_PAYLOAD.declared_weight, ); - let post_dispatch_weight = Pallet::::receive_messages_proof( + let result = Pallet::::receive_messages_proof( RuntimeOrigin::signed(1), TEST_RELAYER_A, proof, messages_count, REGULAR_PAYLOAD.declared_weight, ) - .expect("delivery has failed") - .actual_weight - .expect("receive_messages_proof always returns Some"); + .expect("delivery has failed"); + let post_dispatch_weight = + result.actual_weight.expect("receive_messages_proof always returns Some"); + + // message delivery transactions are never free + assert_eq!(result.pays_fee, Pays::Yes); (pre_dispatch_weight, post_dispatch_weight) } From 6abbf65c9a498f82675aeb268b0ab6ce71a30262 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Feb 2023 15:56:48 +0300 Subject: [PATCH 0929/1210] fixed TODOs for weights v2 (#1860) --- bin/millau/runtime/src/rialto_messages.rs | 4 +- .../runtime/src/rialto_parachain_messages.rs | 4 +- bin/millau/runtime/src/xcm_config.rs | 13 ++---- bin/rialto-parachain/runtime/src/lib.rs | 13 ++---- .../runtime/src/millau_messages.rs | 4 +- bin/rialto/node/src/chain_spec.rs | 5 ++- bin/rialto/runtime/src/millau_messages.rs | 4 +- bin/rialto/runtime/src/parachains.rs | 43 +------------------ bin/rialto/runtime/src/xcm_config.rs | 13 ++---- modules/messages/src/lib.rs | 14 +++--- modules/messages/src/mock.rs | 2 +- modules/messages/src/weights_ext.rs | 2 +- .../chain-bridge-hub-cumulus/src/lib.rs | 10 +++-- 13 files changed, 35 insertions(+), 96 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 1bc361d58823d..62ad919d96cc7 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -30,14 +30,14 @@ pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); parameter_types! { /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); + pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; } /// Message payload for Millau -> Rialto messages. diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index d19e413640837..1cfdc9c8f4940 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -30,14 +30,14 @@ pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); parameter_types! { /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); + pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; } /// Message payload for Millau -> RialtoParachain messages. diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 17bdc43da3d66..aaaa7bf642db3 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -93,13 +93,9 @@ type LocalOriginConverter = ( SignedAccountId32AsNative, ); -/// The amount of weight an XCM operation takes. This is a safe overestimate. -pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; - parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - check `set_proof_size` 0 or 64*1024 or 1026? - pub const BaseXcmWeight: Weight = Weight::from_parts(BASE_XCM_WEIGHT, 0); + pub const BaseXcmWeight: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); /// Maximum number of instructions in a single XCM fragment. A sanity check against weight /// calculations getting too crazy. pub const MaxInstructions: u32 = 100; @@ -314,17 +310,14 @@ mod tests { }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!( - dispatch_weight, - frame_support::weights::Weight::from_ref_time(1_000_000_000) - ); + assert_eq!(dispatch_weight, BaseXcmWeight::get()); let dispatch_result = MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert_eq!( dispatch_result, MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::from_ref_time(0), + unspent_weight: frame_support::weights::Weight::zero(), dispatch_level_result: (), } ); diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index be457d950415f..ba1aa05463b1c 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -368,13 +368,9 @@ pub type XcmOriginToTransactDispatchOrigin = ( // TODO: until https://github.com/paritytech/parity-bridges-common/issues/1417 is fixed (in either way), // the following constant must match the similar constant in the Millau runtime. -/// One XCM operation is `1_000_000_000` weight - almost certainly a conservative estimate. -pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; - parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - check `set_proof_size` 0 or 64*1024 or 1026? - pub UnitWeightCost: Weight = Weight::from_parts(BASE_XCM_WEIGHT, 0); + pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 64 * 1024); // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; @@ -902,17 +898,14 @@ mod tests { }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!( - dispatch_weight, - frame_support::weights::Weight::from_ref_time(1_000_000_000) - ); + assert_eq!(dispatch_weight, UnitWeightCost::get()); let dispatch_result = MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert_eq!( dispatch_result, MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::from_ref_time(0), + unspent_weight: frame_support::weights::Weight::zero(), dispatch_level_result: (), } ); diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 850ec1da60db8..ee7a089992ebb 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -33,14 +33,14 @@ pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::UnitWeightCost::get().saturating_mul(2); parameter_types! { /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); + pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; } /// Message payload for RialtoParachain -> Millau messages. diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 345778755adb5..cfc0ed62e1061 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -253,7 +253,10 @@ fn testnet_genesis( max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, max_downward_message_size: 1024 * 1024, - ump_service_total_weight: Weight::from_ref_time(100_000_000_000), + ump_service_total_weight: Weight::from_parts( + 100_000_000_000, + polkadot_primitives::v2::MAX_POV_SIZE as u64, + ), max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 09fbe46453df9..4774d871b788a 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -30,14 +30,14 @@ pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); /// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual /// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: u64 = 2 * crate::xcm_config::BASE_XCM_WEIGHT; +pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); parameter_types! { /// Weight credit for our test messages. /// /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = Weight::from_ref_time(BASE_XCM_WEIGHT_TWICE); + pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; } /// Message payload for Rialto -> Millau messages. diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 1c7280198a421..9a3346eafd870 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -21,7 +21,7 @@ use crate::{ RuntimeOrigin, ShiftSessionManager, Slots, UncheckedExtrinsic, }; -use frame_support::{parameter_types, traits::KeyOwnerProofSystem, weights::Weight}; +use frame_support::{parameter_types, traits::KeyOwnerProofSystem}; use frame_system::EnsureRoot; use polkadot_primitives::v2::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; @@ -163,44 +163,3 @@ impl slots::Config for Runtime { } impl paras_sudo_wrapper::Config for Runtime {} - -pub struct ZeroWeights; - -impl polkadot_runtime_common::paras_registrar::WeightInfo for ZeroWeights { - fn reserve() -> Weight { - Weight::from_ref_time(0) - } - fn register() -> Weight { - Weight::from_ref_time(0) - } - fn force_register() -> Weight { - Weight::from_ref_time(0) - } - fn deregister() -> Weight { - Weight::from_ref_time(0) - } - fn swap() -> Weight { - Weight::from_ref_time(0) - } - fn schedule_code_upgrade(_: u32) -> Weight { - Weight::from_ref_time(0) - } - fn set_current_head(_: u32) -> Weight { - Weight::from_ref_time(0) - } -} - -impl polkadot_runtime_common::slots::WeightInfo for ZeroWeights { - fn force_lease() -> Weight { - Weight::from_ref_time(0) - } - fn manage_lease_period_start(_c: u32, _t: u32) -> Weight { - Weight::from_ref_time(0) - } - fn clear_all_leases() -> Weight { - Weight::from_ref_time(0) - } - fn trigger_onboard() -> Weight { - Weight::from_ref_time(0) - } -} diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index a86593f47f9d3..174ece0472518 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -87,13 +87,9 @@ type LocalOriginConverter = ( SignedAccountId32AsNative, ); -/// The amount of weight an XCM operation takes. This is a safe overestimate. -pub const BASE_XCM_WEIGHT: u64 = 1_000_000_000; - parameter_types! { /// The amount of weight an XCM operation takes. This is a safe overestimate. - // TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - check `set_proof_size` 0 or 64*1024 or 1026? - pub const BaseXcmWeight: Weight = Weight::from_parts(BASE_XCM_WEIGHT, 0); + pub const BaseXcmWeight: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); /// Maximum number of instructions in a single XCM fragment. A sanity check against weight /// calculations getting too crazy. pub const MaxInstructions: u32 = 100; @@ -273,17 +269,14 @@ mod tests { }; let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!( - dispatch_weight, - frame_support::weights::Weight::from_ref_time(1_000_000_000) - ); + assert_eq!(dispatch_weight, BaseXcmWeight::get()); let dispatch_result = MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert_eq!( dispatch_result, MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::from_ref_time(0), + unspent_weight: frame_support::weights::Weight::zero(), dispatch_level_result: (), } ); diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 21e5a6a9a8548..eaa681df38f0e 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1271,7 +1271,7 @@ mod tests { TEST_RELAYER_A, Err(()).into(), 1, - Weight::from_ref_time(0), + Weight::zero(), ), Error::::InvalidMessagesProof, ); @@ -1287,7 +1287,7 @@ mod tests { TEST_RELAYER_A, Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), u32::MAX, - Weight::from_ref_time(0), + Weight::zero(), ), Error::::TooManyMessagesInTheProof, ); @@ -1479,8 +1479,8 @@ mod tests { TEST_RELAYER_A, Ok(vec![invalid_message]).into(), 1, - Weight::from_ref_time(0), /* weight may be zero in this case (all messages are - * improperly encoded) */ + Weight::zero(), /* weight may be zero in this case (all messages are + * improperly encoded) */ ),); assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 1,); @@ -1710,11 +1710,7 @@ mod tests { Pallet::::inbound_message_data( TEST_LANE_ID, REGULAR_PAYLOAD.encode(), - OutboundMessageDetails { - nonce: 0, - dispatch_weight: Weight::from_ref_time(0), - size: 0, - }, + OutboundMessageDetails { nonce: 0, dispatch_weight: Weight::zero(), size: 0 }, ), InboundMessageDetails { dispatch_weight: REGULAR_PAYLOAD.declared_weight }, ); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index c628ab2cbb327..bd10de09c7f24 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -374,7 +374,7 @@ impl MessageDispatch for TestMessageDispatch { fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { Ok(payload) => payload.declared_weight, - Err(_) => Weight::from_ref_time(0), + Err(_) => Weight::zero(), } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index b2133f06460c4..c764f5b8f6563 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -48,7 +48,7 @@ pub fn ensure_weights_are_correct() { // verify `receive_message_proof` weight let receive_messages_proof_weight = - W::receive_messages_proof_weight(&PreComputedSize(1), 10, Weight::from_ref_time(0)); + W::receive_messages_proof_weight(&PreComputedSize(1), 10, Weight::zero()); assert_ne!(receive_messages_proof_weight.ref_time(), 0); assert_ne!(receive_messages_proof_weight.proof_size(), 0); diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 74c6618275511..dfa5afe2a5b8d 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -45,7 +45,6 @@ pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// time. /// /// This is a copy-paste from the cumulus repo's `parachains-common` crate. -// TODO: https://github.com/paritytech/parity-bridges-common/issues/1543 - remove `set_proof_size` const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_SECOND) .saturating_div(2) .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); @@ -62,9 +61,12 @@ parameter_types! { NORMAL_DISPATCH_RATIO, ); - pub const BlockExecutionWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS).saturating_mul(5_000_000); - - pub const ExtrinsicBaseWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS).saturating_mul(125_000); + /// Importing a block with 0 Extrinsics. + pub const BlockExecutionWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS) + .saturating_mul(5_000_000); + /// Executing a NO-OP `System::remarks` Extrinsic. + pub const ExtrinsicBaseWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS) + .saturating_mul(125_000); pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() .base_block(BlockExecutionWeight::get()) From 9524dfb5d426c6d32ab6961f52839f07540648d6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 8 Feb 2023 09:16:37 +0300 Subject: [PATCH 0930/1210] MaxValues limit for storage maps in the pallet-bridge-grandpa (#1861) * MaxValues limit for storage maps in the pallet-bridge-grandpa * remove use from the future PR --- modules/grandpa/src/benchmarking.rs | 24 +++---- modules/grandpa/src/lib.rs | 105 +++++++++++++--------------- modules/grandpa/src/weights.rs | 50 ++++++------- 3 files changed, 87 insertions(+), 92 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 84a80eace2458..710a7e0952c61 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -50,7 +50,7 @@ use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; use frame_support::traits::Get; use frame_system::RawOrigin; use sp_finality_grandpa::AuthorityId; -use sp_runtime::traits::Zero; +use sp_runtime::traits::{One, Zero}; use sp_std::vec::Vec; /// The maximum number of vote ancestries to include in a justification. @@ -76,14 +76,6 @@ fn validator_set_range_end, I: 'static>() -> u32 { } } -/// Returns number of first header to be imported. -/// -/// Since we bootstrap the pallet with `HeadersToKeep` already imported headers, -/// this function computes the next expected header number to import. -fn header_number, I: 'static, N: From>() -> N { - (T::HeadersToKeep::get() + 1).into() -} - /// Prepare header and its justification to submit using `submit_finality_proof`. fn prepare_benchmark_data, I: 'static>( precommits: u32, @@ -94,16 +86,19 @@ fn prepare_benchmark_data, I: 'static>( .map(|id| (AuthorityId::from(*id), 1)) .collect::>(); + let genesis_header: BridgedHeader = bp_test_utils::test_header(Zero::zero()); + let genesis_hash = genesis_header.hash(); let init_data = InitializationData { - header: Box::new(bp_test_utils::test_header(Zero::zero())), + header: Box::new(genesis_header), authority_list, set_id: TEST_GRANDPA_SET_ID, operating_mode: BasicOperatingMode::Normal, }; bootstrap_bridge::(init_data); + assert!(>::contains_key(genesis_hash)); - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); + let header: BridgedHeader = bp_test_utils::test_header(One::one()); let params = JustificationGeneratorParams { header: header.clone(), round: TEST_GRANDPA_ROUND, @@ -126,10 +121,15 @@ benchmarks_instance_pallet! { let (header, justification) = prepare_benchmark_data::(p, v); }: submit_finality_proof(RawOrigin::Signed(caller), Box::new(header), justification) verify { - let header: BridgedHeader = bp_test_utils::test_header(header_number::()); + let genesis_header: BridgedHeader = bp_test_utils::test_header(Zero::zero()); + let header: BridgedHeader = bp_test_utils::test_header(One::one()); let expected_hash = header.hash(); + // check that the header#1 has been inserted assert_eq!(>::get().unwrap().1, expected_hash); assert!(>::contains_key(expected_hash)); + + // check that the header#0 has been pruned + assert!(!>::contains_key(genesis_header.hash())); } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 493475cf4ed39..6128030d09063 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -104,9 +104,6 @@ pub mod pallet { #[pallet::constant] type MaxRequests: Get; - // Avoid using `HeadersToKeep` directly in the pallet code. Use `headers_to_keep` function - // instead. - /// Maximal number of finalized headers to keep in the storage. /// /// The setting is there to prevent growing the on-chain state indefinitely. Note @@ -292,8 +289,14 @@ pub mod pallet { /// A ring buffer of imported hashes. Ordered by the insertion time. #[pallet::storage] - pub(super) type ImportedHashes, I: 'static = ()> = - StorageMap<_, Identity, u32, BridgedBlockHash>; + pub(super) type ImportedHashes, I: 'static = ()> = StorageMap< + Hasher = Identity, + Key = u32, + Value = BridgedBlockHash, + QueryKind = OptionQuery, + OnEmpty = GetDefault, + MaxValues = MaybeHeadersToKeep, + >; /// Current ring buffer position. #[pallet::storage] @@ -302,8 +305,14 @@ pub mod pallet { /// Relevant fields of imported headers. #[pallet::storage] - pub type ImportedHeaders, I: 'static = ()> = - StorageMap<_, Identity, BridgedBlockHash, BridgedStoredHeaderData>; + pub type ImportedHeaders, I: 'static = ()> = StorageMap< + Hasher = Identity, + Key = BridgedBlockHash, + Value = BridgedStoredHeaderData, + QueryKind = OptionQuery, + OnEmpty = GetDefault, + MaxValues = MaybeHeadersToKeep, + >; /// The current GRANDPA Authority set. #[pallet::storage] @@ -467,20 +476,6 @@ pub mod pallet { })?) } - /// Return number of headers to keep in the runtime storage. - #[cfg(not(feature = "runtime-benchmarks"))] - pub(crate) fn headers_to_keep, I: 'static>() -> u32 { - T::HeadersToKeep::get() - } - - /// Return number of headers to keep in the runtime storage. - #[cfg(feature = "runtime-benchmarks")] - pub(crate) fn headers_to_keep, I: 'static>() -> u32 { - // every db operation (significantly) slows down benchmarks, so let's keep as min as - // possible - 2 - } - /// Import a previously verified header to the storage. /// /// Note this function solely takes care of updating the storage and pruning old entries, @@ -496,7 +491,7 @@ pub mod pallet { >::insert(index, hash); // Update ring buffer pointer and remove old header. - >::put((index + 1) % headers_to_keep::()); + >::put((index + 1) % T::HeadersToKeep::get()); if let Ok(hash) = pruning { log::debug!(target: LOG_TARGET, "Pruning old header: {:?}.", hash); >::remove(hash); @@ -535,27 +530,35 @@ pub mod pallet { Ok(()) } + /// Adapter for using `Config::HeadersToKeep` as `MaxValues` bound in our storage maps. + pub struct MaybeHeadersToKeep(PhantomData<(T, I)>); + + // this implementation is required to use the struct as `MaxValues` + impl, I: 'static> Get> for MaybeHeadersToKeep { + fn get() -> Option { + Some(T::HeadersToKeep::get()) + } + } + + /// Initialize pallet so that it is ready for inserting new header. + /// + /// The function makes sure that the new insertion will cause the pruning of some old header. + /// + /// Returns parent header for the new header. #[cfg(feature = "runtime-benchmarks")] pub(crate) fn bootstrap_bridge, I: 'static>( init_params: super::InitializationData>, - ) { - let start_number = *init_params.header.number(); - let end_number = start_number + headers_to_keep::().into(); + ) -> BridgedHeader { + let start_header = init_params.header.clone(); initialize_bridge::(init_params).expect("benchmarks are correct"); - let mut number = start_number; - while number < end_number { - number = number + sp_runtime::traits::One::one(); - let header = >::new( - number, - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ); - let hash = header.hash(); - insert_header::(header, hash); - } + // the most obvious way to cause pruning during next insertion would be to insert + // `HeadersToKeep` headers. But it'll make our benchmarks slow. So we will just play with + // our pruning ring-buffer. + assert_eq!(ImportedHashesPointer::::get(), 1); + ImportedHashesPointer::::put(0); + + *start_header } } @@ -816,13 +819,9 @@ mod tests { fn succesfully_imports_header_with_valid_finality() { run_test(|| { initialize_substrate_bridge(); - assert_ok!( - submit_finality_proof(1), - PostDispatchInfo { - actual_weight: None, - pays_fee: frame_support::dispatch::Pays::Yes, - }, - ); + let result = submit_finality_proof(1); + assert_ok!(result); + assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes); let header = test_header(1); assert_eq!(>::get().unwrap().1, header.hash()); @@ -929,17 +928,13 @@ mod tests { let justification = make_default_justification(&header); // Let's import our test header - assert_ok!( - Pallet::::submit_finality_proof( - RuntimeOrigin::signed(1), - Box::new(header.clone()), - justification - ), - PostDispatchInfo { - actual_weight: None, - pays_fee: frame_support::dispatch::Pays::No, - }, + let result = Pallet::::submit_finality_proof( + RuntimeOrigin::signed(1), + Box::new(header.clone()), + justification, ); + assert_ok!(result); + assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::No); // Make sure that our header is the best finalized assert_eq!(>::get().unwrap().1, header.hash()); diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index e8971d69b484b..44b4ebd37fbaf 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -85,27 +85,27 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: None, max_size: Some(36), added: - /// 2511, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36), + /// added: 2016, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 5]`. /// /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { // Proof Size summary in bytes: - // Measured: `459 + p * (40 ±0)` - // Estimated: `5240` - // Minimum execution time: 368_734 nanoseconds. - Weight::from_parts(64_214_587, 5240) - // Standard Error: 226_504 - .saturating_add(Weight::from_ref_time(41_231_918).saturating_mul(p.into())) - // Standard Error: 20_667 - .saturating_add(Weight::from_ref_time(2_770_962).saturating_mul(v.into())) + // Measured: `416 + p * (40 ±0)` + // Estimated: `4745` + // Minimum execution time: 221_703 nanoseconds. + Weight::from_parts(39_358_497, 4745) + // Standard Error: 85_573 + .saturating_add(Weight::from_ref_time(40_593_280).saturating_mul(p.into())) + // Standard Error: 7_808 + .saturating_add(Weight::from_ref_time(1_529_400).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -140,27 +140,27 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: None, max_size: Some(36), added: - /// 2511, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36), + /// added: 2016, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 5]`. /// /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { // Proof Size summary in bytes: - // Measured: `459 + p * (40 ±0)` - // Estimated: `5240` - // Minimum execution time: 368_734 nanoseconds. - Weight::from_parts(64_214_587, 5240) - // Standard Error: 226_504 - .saturating_add(Weight::from_ref_time(41_231_918).saturating_mul(p.into())) - // Standard Error: 20_667 - .saturating_add(Weight::from_ref_time(2_770_962).saturating_mul(v.into())) + // Measured: `416 + p * (40 ±0)` + // Estimated: `4745` + // Minimum execution time: 221_703 nanoseconds. + Weight::from_parts(39_358_497, 4745) + // Standard Error: 85_573 + .saturating_add(Weight::from_ref_time(40_593_280).saturating_mul(p.into())) + // Standard Error: 7_808 + .saturating_add(Weight::from_ref_time(1_529_400).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } From 7db57212c25590bde2fa31bdeef4c8f85b402f99 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Feb 2023 14:09:37 +0300 Subject: [PATCH 0931/1210] "refund" proof size in GRANDPa pallet (#1863) * "refund" proof size in GRANDPa pallet * clippy * extra_proof_size_bytes_works * use saturated_into * fix review comments --- modules/grandpa/src/lib.rs | 45 ++++++++++++++++++--- modules/grandpa/src/mock.rs | 2 +- modules/grandpa/src/storage_types.rs | 58 +++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 8 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 6128030d09063..5063ea314383a 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -44,9 +44,12 @@ use bp_header_chain::{ }; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{ensure, fail}; +use frame_support::{dispatch::PostDispatchInfo, ensure, fail}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; -use sp_runtime::traits::{Header as HeaderT, Zero}; +use sp_runtime::{ + traits::{Header as HeaderT, Zero}, + SaturatedConversion, +}; use sp_std::{boxed::Box, convert::TryInto}; mod extension; @@ -152,8 +155,8 @@ pub mod pallet { /// pallet. #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::submit_finality_proof( - justification.commit.precommits.len().try_into().unwrap_or(u32::MAX), - justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX), + justification.commit.precommits.len().saturated_into(), + justification.votes_ancestries.len().saturated_into(), ))] pub fn submit_finality_proof( _origin: OriginFor, @@ -189,6 +192,7 @@ pub mod pallet { ensure!(best_finalized_number < *number, >::OldHeader); let authority_set = >::get(); + let unused_proof_size = authority_set.unused_proof_size(); let set_id = authority_set.set_id; verify_justification::(&justification, hash, *number, authority_set.into())?; @@ -210,7 +214,18 @@ pub mod pallet { let is_mandatory_header = is_authorities_change_enacted; let pays_fee = if is_mandatory_header { Pays::No } else { Pays::Yes }; - Ok(pays_fee.into()) + // the proof size component of the call weight assumes that there are + // `MaxBridgedAuthorities` in the `CurrentAuthoritySet` (we use `MaxEncodedLen` + // estimation). But if their number is lower, then we may "refund" some `proof_size`, + // making proof smaller and leaving block space to other useful transactions + let pre_dispatch_weight = T::WeightInfo::submit_finality_proof( + justification.commit.precommits.len().saturated_into(), + justification.votes_ancestries.len().saturated_into(), + ); + let actual_weight = pre_dispatch_weight + .set_proof_size(pre_dispatch_weight.proof_size().saturating_sub(unused_proof_size)); + + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. @@ -819,9 +834,27 @@ mod tests { fn succesfully_imports_header_with_valid_finality() { run_test(|| { initialize_substrate_bridge(); - let result = submit_finality_proof(1); + + let header_number = 1; + let header = test_header(header_number.into()); + let justification = make_default_justification(&header); + + let pre_dispatch_weight = ::WeightInfo::submit_finality_proof( + justification.commit.precommits.len().try_into().unwrap_or(u32::MAX), + justification.votes_ancestries.len().try_into().unwrap_or(u32::MAX), + ); + + let result = submit_finality_proof(header_number); assert_ok!(result); assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes); + // our test config assumes 2048 max authorities and we are just using couple + let pre_dispatch_proof_size = pre_dispatch_weight.proof_size(); + let actual_proof_size = result.unwrap().actual_weight.unwrap().proof_size(); + assert!(actual_proof_size > 0); + assert!( + actual_proof_size < pre_dispatch_proof_size, + "Actual proof size {actual_proof_size} must be less than the pre-dispatch {pre_dispatch_proof_size}", + ); let header = test_header(1); assert_eq!(>::get().unwrap().1, header.hash()); diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index ba6f176e8234c..8757093ee682e 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -33,7 +33,7 @@ pub type TestNumber = crate::BridgedBlockNumber; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -pub const MAX_BRIDGED_AUTHORITIES: u32 = 2048; +pub const MAX_BRIDGED_AUTHORITIES: u32 = 5; use crate as grandpa; diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index d930dbadbc639..732e72e2c0d62 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -20,7 +20,7 @@ use crate::Config; use bp_header_chain::AuthoritySet; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{BoundedVec, RuntimeDebugNoBound}; +use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; @@ -45,6 +45,24 @@ impl, I: 'static> StoredAuthoritySet { pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result { Ok(Self { authorities: TryFrom::try_from(authorities).map_err(drop)?, set_id }) } + + /// Returns number of bytes that may be subtracted from the PoV component of + /// `submit_finality_proof` call, because the actual authorities set is smaller than the maximal + /// configured. + /// + /// Maximal authorities set size is configured by the `MaxBridgedAuthorities` constant from + /// the pallet configuration. The PoV of the call includes the size of maximal authorities + /// count. If the actual size is smaller, we may subtract extra bytes from this component. + pub fn unused_proof_size(&self) -> u64 { + // we can only safely estimate bytes that are occupied by the authority data itself. We have + // no means here to compute PoV bytes, occupied by extra trie nodes or extra bytes in the + // whole set encoding + let single_authority_max_encoded_len = + <(AuthorityId, AuthorityWeight)>::max_encoded_len() as u64; + let extra_authorities = + T::MaxBridgedAuthorities::get().saturating_sub(self.authorities.len() as _); + single_authority_max_encoded_len.saturating_mul(extra_authorities as u64) + } } impl, I: 'static> PartialEq for StoredAuthoritySet { @@ -64,3 +82,41 @@ impl, I: 'static> From> for AuthoritySet { AuthoritySet { authorities: t.authorities.into(), set_id: t.set_id } } } + +#[cfg(test)] +mod tests { + use crate::mock::{TestRuntime, MAX_BRIDGED_AUTHORITIES}; + use bp_test_utils::authority_list; + + type StoredAuthoritySet = super::StoredAuthoritySet; + + #[test] + fn unused_proof_size_works() { + let authority_entry = authority_list().pop().unwrap(); + + // when we have exactly `MaxBridgedAuthorities` authorities + assert_eq!( + StoredAuthoritySet::try_new( + vec![authority_entry.clone(); MAX_BRIDGED_AUTHORITIES as usize], + 0, + ) + .unwrap() + .unused_proof_size(), + 0, + ); + + // when we have less than `MaxBridgedAuthorities` authorities + assert_eq!( + StoredAuthoritySet::try_new( + vec![authority_entry; MAX_BRIDGED_AUTHORITIES as usize - 1], + 0, + ) + .unwrap() + .unused_proof_size(), + 40, + ); + + // and we can't have more than `MaxBridgedAuthorities` authorities in the bounded vec, so + // no test for this case + } +} From ee66171e4b2207283563f6c047fecb15f8e67681 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 9 Feb 2023 14:09:45 +0300 Subject: [PATCH 0932/1210] MaxValues for maps in parachain maps (#1868) * MaxValues for maps in parachain maps * fix compilation --- modules/grandpa/src/lib.rs | 6 ++ modules/parachains/src/lib.rs | 70 ++++++++++++--- modules/parachains/src/mock.rs | 2 + modules/parachains/src/weights.rs | 142 +++++++++++++++--------------- primitives/parachains/src/lib.rs | 17 +++- 5 files changed, 153 insertions(+), 84 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 5063ea314383a..09b7f55a73c02 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -662,6 +662,7 @@ mod tests { assert_err, assert_noop, assert_ok, dispatch::PostDispatchInfo, storage::generator::StorageValue, }; + use sp_core::Get; use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { @@ -1242,4 +1243,9 @@ mod tests { } generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); + + #[test] + fn maybe_headers_to_keep_returns_correct_value() { + assert_eq!(MaybeHeadersToKeep::::get(), Some(mock::HeadersToKeep::get())); + } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index e2f2cbf2d499c..1f060e675cb5d 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -221,27 +221,39 @@ pub mod pallet { /// - the head of the `ImportedParaHashes` ring buffer #[pallet::storage] pub type ParasInfo, I: 'static = ()> = StorageMap< - _, - ::Hasher, - ::Key, - ::Value, + Hasher = ::Hasher, + Key = ::Key, + Value = ::Value, + QueryKind = OptionQuery, + OnEmpty = GetDefault, + MaxValues = MaybeMaxParachains, >; /// State roots of parachain heads which have been imported into the pallet. #[pallet::storage] pub type ImportedParaHeads, I: 'static = ()> = StorageDoubleMap< - _, - ::Hasher1, - ::Key1, - ::Hasher2, - ::Key2, - StoredParaHeadDataOf, + Hasher1 = ::Hasher1, + Key1 = ::Key1, + Hasher2 = ::Hasher2, + Key2 = ::Key2, + Value = StoredParaHeadDataOf, + QueryKind = OptionQuery, + OnEmpty = GetDefault, + MaxValues = MaybeMaxTotalParachainHashes, >; /// A ring buffer of imported parachain head hashes. Ordered by the insertion time. #[pallet::storage] - pub(super) type ImportedParaHashes, I: 'static = ()> = - StorageDoubleMap<_, Blake2_128Concat, ParaId, Twox64Concat, u32, ParaHash>; + pub(super) type ImportedParaHashes, I: 'static = ()> = StorageDoubleMap< + Hasher1 = Blake2_128Concat, + Key1 = ParaId, + Hasher2 = Twox64Concat, + Key2 = u32, + Value = ParaHash, + QueryKind = OptionQuery, + OnEmpty = GetDefault, + MaxValues = MaybeMaxTotalParachainHashes, + >; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -646,6 +658,27 @@ pub mod pallet { } } } + + /// Returns maximal number of parachains, supported by the pallet. + pub struct MaybeMaxParachains(PhantomData<(T, I)>); + + impl, I: 'static> Get> for MaybeMaxParachains { + fn get() -> Option { + Some(T::ParaStoredHeaderDataBuilder::supported_parachains()) + } + } + + /// Returns total number of all parachains hashes/heads, stored by the pallet. + pub struct MaybeMaxTotalParachainHashes(PhantomData<(T, I)>); + + impl, I: 'static> Get> for MaybeMaxTotalParachainHashes { + fn get() -> Option { + Some( + T::ParaStoredHeaderDataBuilder::supported_parachains() + .saturating_mul(T::HeadsToKeep::get()), + ) + } + } } /// Single parachain header chain adapter. @@ -1525,4 +1558,17 @@ mod tests { } generate_owned_bridge_module_tests!(BasicOperatingMode::Normal, BasicOperatingMode::Halted); + + #[test] + fn maybe_max_parachains_returns_correct_value() { + assert_eq!(MaybeMaxParachains::::get(), Some(mock::TOTAL_PARACHAINS)); + } + + #[test] + fn maybe_max_total_parachain_hashes_returns_correct_value() { + assert_eq!( + MaybeMaxTotalParachainHashes::::get(), + Some(mock::TOTAL_PARACHAINS * mock::HeadsToKeep::get()), + ); + } } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 118a9b1d31558..8248964263c06 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -38,6 +38,8 @@ pub const PARAS_PALLET_NAME: &str = "Paras"; pub const UNTRACKED_PARACHAIN_ID: u32 = 10; // use exact expected encoded size: `vec_len_size + header_number_size + state_root_hash_size` pub const MAXIMAL_PARACHAIN_HEAD_DATA_SIZE: u32 = 1 + 8 + 32; +// total parachains that we use in tests +pub const TOTAL_PARACHAINS: u32 = 4; pub type RegularParachainHeader = sp_runtime::testing::Header; pub type RegularParachainHasher = BlakeTwo256; diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index f6dc73d40c32d..5ee1e4d36212f 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_parachains //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -67,33 +67,33 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, - /// mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// 555, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), - /// added: 2539, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: + /// Some(64), added: 2044, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), - /// added: 2671, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: + /// Some(196), added: 2176, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `8113` - // Minimum execution time: 35_348 nanoseconds. - Weight::from_parts(36_906_961, 8113) - // Standard Error: 136_143 - .saturating_add(Weight::from_ref_time(148_169).saturating_mul(p.into())) + // Estimated: `5143` + // Minimum execution time: 35_160 nanoseconds. + Weight::from_parts(36_951_585, 5143) + // Standard Error: 336_932 + .saturating_add(Weight::from_ref_time(407_557).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -104,29 +104,29 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, - /// mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// 555, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), - /// added: 2539, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: + /// Some(64), added: 2044, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), - /// added: 2671, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: + /// Some(196), added: 2176, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `8113` - // Minimum execution time: 43_295 nanoseconds. - Weight::from_parts(48_018_000, 8113) + // Estimated: `5143` + // Minimum execution time: 42_276 nanoseconds. + Weight::from_parts(43_525_000, 5143) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -137,29 +137,29 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, - /// mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// 555, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), - /// added: 2539, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: + /// Some(64), added: 2044, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), - /// added: 2671, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: + /// Some(196), added: 2176, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `8113` - // Minimum execution time: 86_112 nanoseconds. - Weight::from_parts(88_901_000, 8113) + // Estimated: `5143` + // Minimum execution time: 85_824 nanoseconds. + Weight::from_parts(87_335_000, 5143) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -174,33 +174,33 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, - /// mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// 555, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), - /// added: 2539, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: + /// Some(64), added: 2044, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), - /// added: 2671, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: + /// Some(196), added: 2176, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `8113` - // Minimum execution time: 35_348 nanoseconds. - Weight::from_parts(36_906_961, 8113) - // Standard Error: 136_143 - .saturating_add(Weight::from_ref_time(148_169).saturating_mul(p.into())) + // Estimated: `5143` + // Minimum execution time: 35_160 nanoseconds. + Weight::from_parts(36_951_585, 5143) + // Standard Error: 336_932 + .saturating_add(Weight::from_ref_time(407_557).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -211,29 +211,29 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, - /// mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// 555, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), - /// added: 2539, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: + /// Some(64), added: 2044, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), - /// added: 2671, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: + /// Some(196), added: 2176, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `8113` - // Minimum execution time: 43_295 nanoseconds. - Weight::from_parts(48_018_000, 8113) + // Estimated: `5143` + // Minimum execution time: 42_276 nanoseconds. + Weight::from_parts(43_525_000, 5143) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -244,29 +244,29 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: None, max_size: Some(60), added: 2535, - /// mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// 555, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: None, max_size: Some(64), - /// added: 2539, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: + /// Some(64), added: 2044, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: None, max_size: Some(196), - /// added: 2671, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: + /// Some(196), added: 2176, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `8113` - // Minimum execution time: 86_112 nanoseconds. - Weight::from_parts(88_901_000, 8113) + // Estimated: `5143` + // Minimum execution time: 85_824 nanoseconds. + Weight::from_parts(87_335_000, 5143) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index 388a995fae6de..e619fc7b641af 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -115,7 +115,10 @@ impl ParaStoredHeaderData { /// Stored parachain head data builder. pub trait ParaStoredHeaderDataBuilder { - /// Try to build head data from self. + /// Return number of parachains that are supported by this builder. + fn supported_parachains() -> u32; + + /// Try to build head data from encoded head of parachain with given id. fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option; } @@ -123,6 +126,10 @@ pub trait ParaStoredHeaderDataBuilder { pub struct SingleParaStoredHeaderDataBuilder(PhantomData); impl ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBuilder { + fn supported_parachains() -> u32 { + 1 + } + fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option { if para_id == ParaId(C::PARACHAIN_ID) { let header = HeaderOf::::decode(&mut ¶_head.0[..]).ok()?; @@ -139,6 +146,14 @@ impl ParaStoredHeaderDataBuilder for SingleParaStoredHeaderDataBui #[impl_trait_for_tuples::impl_for_tuples(1, 30)] #[tuple_types_custom_trait_bound(Parachain)] impl ParaStoredHeaderDataBuilder for C { + fn supported_parachains() -> u32 { + let mut result = 0; + for_tuples!( #( + result += SingleParaStoredHeaderDataBuilder::::supported_parachains(); + )* ); + result + } + fn try_build(para_id: ParaId, para_head: &ParaHead) -> Option { for_tuples!( #( let maybe_para_head = SingleParaStoredHeaderDataBuilder::::try_build(para_id, para_head); From f8e1047e1d2c6a3e298fa99b016682951ba23c5f Mon Sep 17 00:00:00 2001 From: cuteolaf <53915161+cuteolaf@users.noreply.github.com> Date: Sun, 12 Feb 2023 22:39:01 -0800 Subject: [PATCH 0933/1210] Update README.md (#1872) --- relays/finality/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/finality/README.md b/relays/finality/README.md index effc3db6b12b8..444056e756303 100644 --- a/relays/finality/README.md +++ b/relays/finality/README.md @@ -21,7 +21,7 @@ More: [GRANDPA Finality Relay Sequence Diagram](../../docs/grandpa-finality-rela The most important trait is the [`FinalitySyncPipeline`](./src/lib.rs), which defines the basic primitives of the source chain (like block hash and number) and the type of finality proof (GRANDPA justification or MMR proof). Once that is defined, there are two other traits - [`SourceClient`](./src/finality_loop.rs) and -[`TarggetClient`](./src/finality_loop.rs). +[`TargetClient`](./src/finality_loop.rs). The `SourceClient` represents the Substrate node client that connects to the source chain. The client needs to be able to return the best finalized header number, finalized header and its finality proof and the stream of From b0d4bf6979a89419026ad8781ea820fa8bd49a31 Mon Sep 17 00:00:00 2001 From: cuteolaf <53915161+cuteolaf@users.noreply.github.com> Date: Sun, 12 Feb 2023 22:42:38 -0800 Subject: [PATCH 0934/1210] update parachains relay doc (#1874) --- relays/parachains/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/README.md b/relays/parachains/README.md index 9093dc617dc65..fc5ad03fb340d 100644 --- a/relays/parachains/README.md +++ b/relays/parachains/README.md @@ -15,7 +15,7 @@ More: [Parachains Finality Relay Sequence Diagram](../../docs/parachains-finalit There are only two traits that need to be implemented. The [`SourceChain`](./src/parachains_loop.rs) implementation is supposed to connect to the source chain node. It must be able to read parachain heads from the `Heads` map of -the [`paras` pallet](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet. +the [`paras` pallet](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras). It also must create storage proofs of `Heads` map entries, when required. The [`TargetChain`](./src/parachains_loop.rs) implementation connects to the target chain node. It must be able From 257ccc94122df0990793d1702d3c19eabde50044 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 03:24:09 +0000 Subject: [PATCH 0935/1210] Bump serde_json from 1.0.92 to 1.0.93 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.92 to 1.0.93. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.92...v1.0.93) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index af2c50eb4804b..fea96c9b11f15 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.4", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.92" +serde_json = "1.0.93" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index bf8b348473235..d03deaaabefad 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.4", features = ["derive"] } -serde_json = "1.0.92" +serde_json = "1.0.93" # Bridge dependencies From acda8e7fdd825b66a33ac91d71f13803a02f1968 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 03:25:12 +0000 Subject: [PATCH 0936/1210] Bump signal-hook from 0.3.14 to 0.3.15 Bumps [signal-hook](https://github.com/vorner/signal-hook) from 0.3.14 to 0.3.15. - [Release notes](https://github.com/vorner/signal-hook/releases) - [Changelog](https://github.com/vorner/signal-hook/blob/master/CHANGELOG.md) - [Commits](https://github.com/vorner/signal-hook/compare/v0.3.14...v0.3.15) --- updated-dependencies: - dependency-name: signal-hook dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 1a16f3466f398..0dc201588306a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -17,7 +17,7 @@ num-format = "0.4" num-traits = "0.2" rbtag = "0.3" structopt = "0.3" -signal-hook = "0.3.14" +signal-hook = "0.3.15" signal-hook-async-std = "0.2.2" strum = { version = "0.24.1", features = ["derive"] } From 0b9188b909916e8e9c4c46ecf11077df72a3fc93 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Feb 2023 15:26:25 +0300 Subject: [PATCH 0937/1210] More tests for message pallet weights (#1870) * more tests for message pallet weights * move tests to ensure_weights_are_correct * removed extra tests --- modules/messages/src/mock.rs | 5 +- modules/messages/src/weights.rs | 162 ++++++++++++++-------------- modules/messages/src/weights_ext.rs | 157 +++++++++++++++++++++++++-- 3 files changed, 235 insertions(+), 89 deletions(-) diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index bd10de09c7f24..084262c790532 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -34,7 +34,7 @@ use codec::{Decode, Encode}; use frame_support::{ parameter_types, traits::ConstU64, - weights::{RuntimeDbWeight, Weight}, + weights::{constants::RocksDbWeight, Weight}, }; use scale_info::TypeInfo; use sp_core::H256; @@ -92,9 +92,10 @@ parameter_types! { pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; } +pub type DbWeight = RocksDbWeight; + impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; type Index = u64; diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 0e25850888571..10750aabcd365 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -72,8 +72,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -87,9 +87,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: // Measured: `693` - // Estimated: `55198` - // Minimum execution time: 47_968 nanoseconds. - Weight::from_parts(48_937_000, 55198) + // Estimated: `54703` + // Minimum execution time: 76_449 nanoseconds. + Weight::from_parts(127_110_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -100,8 +100,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -115,9 +115,9 @@ impl WeightInfo for BridgeWeight { fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: // Measured: `693` - // Estimated: `55198` - // Minimum execution time: 63_831 nanoseconds. - Weight::from_parts(85_093_000, 55198) + // Estimated: `54703` + // Minimum execution time: 102_297 nanoseconds. + Weight::from_parts(108_619_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -128,8 +128,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -143,9 +143,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: // Measured: `693` - // Estimated: `55198` - // Minimum execution time: 53_775 nanoseconds. - Weight::from_parts(55_113_000, 55198) + // Estimated: `54703` + // Minimum execution time: 84_911 nanoseconds. + Weight::from_parts(87_518_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -156,8 +156,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -166,9 +166,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54695` - // Minimum execution time: 54_314 nanoseconds. - Weight::from_parts(55_804_000, 54695) + // Estimated: `54200` + // Minimum execution time: 79_805 nanoseconds. + Weight::from_parts(84_148_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -179,8 +179,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -189,9 +189,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54695` - // Minimum execution time: 103_050 nanoseconds. - Weight::from_parts(106_715_000, 54695) + // Estimated: `54200` + // Minimum execution time: 141_515 nanoseconds. + Weight::from_parts(150_421_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -202,8 +202,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// @@ -217,9 +217,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `8094` - // Minimum execution time: 42_111 nanoseconds. - Weight::from_parts(43_168_000, 8094) + // Estimated: `7599` + // Minimum execution time: 54_740 nanoseconds. + Weight::from_parts(56_637_000, 7599) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -230,8 +230,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// @@ -245,9 +245,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8094` - // Minimum execution time: 40_094 nanoseconds. - Weight::from_parts(41_140_000, 8094) + // Estimated: `7599` + // Minimum execution time: 54_583 nanoseconds. + Weight::from_parts(56_205_000, 7599) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -258,8 +258,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// @@ -273,9 +273,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `10629` - // Minimum execution time: 42_498 nanoseconds. - Weight::from_parts(43_494_000, 10629) + // Estimated: `10134` + // Minimum execution time: 59_426 nanoseconds. + Weight::from_parts(61_911_000, 10134) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -290,8 +290,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -305,9 +305,9 @@ impl WeightInfo for () { fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: // Measured: `693` - // Estimated: `55198` - // Minimum execution time: 47_968 nanoseconds. - Weight::from_parts(48_937_000, 55198) + // Estimated: `54703` + // Minimum execution time: 76_449 nanoseconds. + Weight::from_parts(127_110_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -318,8 +318,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -333,9 +333,9 @@ impl WeightInfo for () { fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: // Measured: `693` - // Estimated: `55198` - // Minimum execution time: 63_831 nanoseconds. - Weight::from_parts(85_093_000, 55198) + // Estimated: `54703` + // Minimum execution time: 102_297 nanoseconds. + Weight::from_parts(108_619_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -346,8 +346,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -361,9 +361,9 @@ impl WeightInfo for () { fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: // Measured: `693` - // Estimated: `55198` - // Minimum execution time: 53_775 nanoseconds. - Weight::from_parts(55_113_000, 55198) + // Estimated: `54703` + // Minimum execution time: 84_911 nanoseconds. + Weight::from_parts(87_518_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -374,8 +374,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -384,9 +384,9 @@ impl WeightInfo for () { fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54695` - // Minimum execution time: 54_314 nanoseconds. - Weight::from_parts(55_804_000, 54695) + // Estimated: `54200` + // Minimum execution time: 79_805 nanoseconds. + Weight::from_parts(84_148_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -397,8 +397,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) /// @@ -407,9 +407,9 @@ impl WeightInfo for () { fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54695` - // Minimum execution time: 103_050 nanoseconds. - Weight::from_parts(106_715_000, 54695) + // Estimated: `54200` + // Minimum execution time: 141_515 nanoseconds. + Weight::from_parts(150_421_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -420,8 +420,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// @@ -435,9 +435,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `8094` - // Minimum execution time: 42_111 nanoseconds. - Weight::from_parts(43_168_000, 8094) + // Estimated: `7599` + // Minimum execution time: 54_740 nanoseconds. + Weight::from_parts(56_637_000, 7599) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -448,8 +448,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// @@ -463,9 +463,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8094` - // Minimum execution time: 40_094 nanoseconds. - Weight::from_parts(41_140_000, 8094) + // Estimated: `7599` + // Minimum execution time: 54_583 nanoseconds. + Weight::from_parts(56_205_000, 7599) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -476,8 +476,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: None, max_size: Some(68), added: - /// 2543, mode: MaxEncodedLen) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// @@ -491,9 +491,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `10629` - // Minimum execution time: 42_498 nanoseconds. - Weight::from_parts(43_494_000, 10629) + // Estimated: `10134` + // Minimum execution time: 59_426 nanoseconds. + Weight::from_parts(61_911_000, 10134) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index c764f5b8f6563..5598706b5dbf2 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -36,21 +36,43 @@ pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Ensure that weights from `WeightInfoExt` implementation are looking correct. pub fn ensure_weights_are_correct() { + // all components of weight formulae must have zero `proof_size`, because the `proof_size` is + // benchmarked using `MaxEncodedLen` approach and there are no components that cause additional + // db reads + // verify `receive_messages_proof` weight components - assert_ne!(W::receive_messages_proof_overhead(), Weight::zero()); - assert_ne!(W::receive_messages_proof_messages_overhead(1), Weight::zero()); - assert_ne!(W::receive_messages_proof_outbound_lane_state_overhead(), Weight::zero()); - assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); + assert_ne!(W::receive_messages_proof_overhead().ref_time(), 0); + assert_ne!(W::receive_messages_proof_overhead().proof_size(), 0); + // W::receive_messages_proof_messages_overhead(1).ref_time() may be zero because: + // the message processing code (`InboundLane::receive_message`) is minimal and may not be + // accounted by our benchmarks + assert_eq!(W::receive_messages_proof_messages_overhead(1).proof_size(), 0); + // W::receive_messages_proof_outbound_lane_state_overhead().ref_time() may be zero because: + // the outbound lane state processing code (`InboundLane::receive_state_update`) is minimal and + // may not be accounted by our benchmarks + assert_eq!(W::receive_messages_proof_outbound_lane_state_overhead().proof_size(), 0); + assert_ne!(W::storage_proof_size_overhead(1).ref_time(), 0); + assert_eq!(W::storage_proof_size_overhead(1).proof_size(), 0); // verify `receive_messages_delivery_proof` weight components - assert_ne!(W::receive_messages_delivery_proof_overhead(), Weight::zero()); - assert_ne!(W::storage_proof_size_overhead(1), Weight::zero()); + assert_ne!(W::receive_messages_delivery_proof_overhead().ref_time(), 0); + assert_ne!(W::receive_messages_delivery_proof_overhead().proof_size(), 0); + // W::receive_messages_delivery_proof_messages_overhead(1).ref_time() may be zero because: + // there's no code that iterates over confirmed messages in confirmation transaction + assert_eq!(W::receive_messages_delivery_proof_messages_overhead(1).proof_size(), 0); + assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1).ref_time(), 0); + // W::receive_messages_delivery_proof_relayers_overhead(1).proof_size() is an exception + // it may or may not cause additional db reads, so proof size may vary + assert_ne!(W::storage_proof_size_overhead(1).ref_time(), 0); + assert_eq!(W::storage_proof_size_overhead(1).proof_size(), 0); // verify `receive_message_proof` weight let receive_messages_proof_weight = W::receive_messages_proof_weight(&PreComputedSize(1), 10, Weight::zero()); assert_ne!(receive_messages_proof_weight.ref_time(), 0); assert_ne!(receive_messages_proof_weight.proof_size(), 0); + messages_proof_size_does_not_affect_proof_size::(); + messages_count_does_not_affect_proof_size::(); // verify `receive_message_proof` weight let receive_messages_delivery_proof_weight = W::receive_messages_delivery_proof_weight( @@ -59,6 +81,8 @@ pub fn ensure_weights_are_correct() { ); assert_ne!(receive_messages_delivery_proof_weight.ref_time(), 0); assert_ne!(receive_messages_delivery_proof_weight.proof_size(), 0); + messages_delivery_proof_size_does_not_affect_proof_size::(); + total_messages_in_delivery_proof_does_not_affect_proof_size::(); } /// Ensure that we're able to receive maximal (by-size and by-weight) message from other chain. @@ -122,6 +146,116 @@ pub fn ensure_able_to_receive_confirmation( ); } +/// Panics if `proof_size` of message delivery call depends on the message proof size. +fn messages_proof_size_does_not_affect_proof_size() { + let dispatch_weight = Weight::zero(); + let weight_when_proof_size_is_8k = + W::receive_messages_proof_weight(&PreComputedSize(8 * 1024), 1, dispatch_weight); + let weight_when_proof_size_is_16k = + W::receive_messages_proof_weight(&PreComputedSize(16 * 1024), 1, dispatch_weight); + + ensure_weight_components_are_not_zero(weight_when_proof_size_is_8k); + ensure_weight_components_are_not_zero(weight_when_proof_size_is_16k); + ensure_proof_size_is_the_same( + weight_when_proof_size_is_8k, + weight_when_proof_size_is_16k, + "Messages proof size does not affect values that we read from our storage", + ); +} + +/// Panics if `proof_size` of message delivery call depends on the messages count. +/// +/// In practice, it will depend on the messages count, because most probably every +/// message will read something from db during dispatch. But this must be accounted +/// by the `dispatch_weight`. +fn messages_count_does_not_affect_proof_size() { + let messages_proof_size = PreComputedSize(8 * 1024); + let dispatch_weight = Weight::zero(); + let weight_of_one_incoming_message = + W::receive_messages_proof_weight(&messages_proof_size, 1, dispatch_weight); + let weight_of_two_incoming_messages = + W::receive_messages_proof_weight(&messages_proof_size, 2, dispatch_weight); + + ensure_weight_components_are_not_zero(weight_of_one_incoming_message); + ensure_weight_components_are_not_zero(weight_of_two_incoming_messages); + ensure_proof_size_is_the_same( + weight_of_one_incoming_message, + weight_of_two_incoming_messages, + "Number of same-lane incoming messages does not affect values that we read from our storage", + ); +} + +/// Panics if `proof_size` of delivery confirmation call depends on the delivery proof size. +fn messages_delivery_proof_size_does_not_affect_proof_size() { + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + last_delivered_nonce: 1, + }; + let weight_when_proof_size_is_8k = + W::receive_messages_delivery_proof_weight(&PreComputedSize(8 * 1024), &relayers_state); + let weight_when_proof_size_is_16k = + W::receive_messages_delivery_proof_weight(&PreComputedSize(16 * 1024), &relayers_state); + + ensure_weight_components_are_not_zero(weight_when_proof_size_is_8k); + ensure_weight_components_are_not_zero(weight_when_proof_size_is_16k); + ensure_proof_size_is_the_same( + weight_when_proof_size_is_8k, + weight_when_proof_size_is_16k, + "Messages delivery proof size does not affect values that we read from our storage", + ); +} + +/// Panics if `proof_size` of delivery confirmation call depends on the number of confirmed +/// messages. +fn total_messages_in_delivery_proof_does_not_affect_proof_size() { + let proof_size = PreComputedSize(8 * 1024); + let weight_when_1k_messages_confirmed = W::receive_messages_delivery_proof_weight( + &proof_size, + &UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1024, + last_delivered_nonce: 1, + }, + ); + let weight_when_2k_messages_confirmed = W::receive_messages_delivery_proof_weight( + &proof_size, + &UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 2048, + last_delivered_nonce: 1, + }, + ); + + ensure_weight_components_are_not_zero(weight_when_1k_messages_confirmed); + ensure_weight_components_are_not_zero(weight_when_2k_messages_confirmed); + ensure_proof_size_is_the_same( + weight_when_1k_messages_confirmed, + weight_when_2k_messages_confirmed, + "More messages in delivery proof does not affect values that we read from our storage", + ); +} + +/// Panics if either Weight' `proof_size` or `ref_time` are zero. +fn ensure_weight_components_are_not_zero(weight: Weight) { + assert_ne!(weight.ref_time(), 0); + assert_ne!(weight.proof_size(), 0); +} + +/// Panics if `proof_size` of `weight1` is not equal to `proof_size` of `weight2`. +fn ensure_proof_size_is_the_same(weight1: Weight, weight2: Weight, msg: &str) { + assert_eq!( + weight1.proof_size(), + weight2.proof_size(), + "{msg}: {} must be equal to {}", + weight1.proof_size(), + weight2.proof_size(), + ); +} + /// Extended weight info. pub trait WeightInfoExt: WeightInfo { /// Size of proof that is already included in the single message delivery weight. @@ -282,3 +416,14 @@ impl WeightInfoExt for crate::weights::BridgeWeight EXTRA_STORAGE_PROOF_SIZE } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{mock::TestRuntime, weights::BridgeWeight}; + + #[test] + fn ensure_default_weights_are_correct() { + ensure_weights_are_correct::>(); + } +} From 9540e5653737fe84d9eff90f1bb6f0c1102dce41 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 13 Feb 2023 16:48:54 +0300 Subject: [PATCH 0938/1210] MaxValues for OutboundLanes map (#1871) --- modules/messages/src/lib.rs | 27 ++++++++- modules/messages/src/weights.rs | 100 ++++++++++++++++---------------- 2 files changed, 75 insertions(+), 52 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index eaa681df38f0e..70865cf17c514 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -583,8 +583,14 @@ pub mod pallet { /// Map of lane id => outbound lane data. #[pallet::storage] - pub type OutboundLanes, I: 'static = ()> = - StorageMap<_, Blake2_128Concat, LaneId, OutboundLaneData, ValueQuery>; + pub type OutboundLanes, I: 'static = ()> = StorageMap< + Hasher = Blake2_128Concat, + Key = LaneId, + Value = OutboundLaneData, + QueryKind = ValueQuery, + OnEmpty = GetDefault, + MaxValues = MaybeOutboundLanesCount, + >; /// All queued outbound messages. #[pallet::storage] @@ -648,6 +654,15 @@ pub mod pallet { InboundLanes::::get(lane).0 } } + + /// Get-parameter that returns number of active outbound lanes that the pallet maintains. + pub struct MaybeOutboundLanesCount(PhantomData<(T, I)>); + + impl, I: 'static> Get> for MaybeOutboundLanesCount { + fn get() -> Option { + Some(T::ActiveOutboundLanes::get().len() as u32) + } + } } impl bp_messages::source_chain::MessagesBridge @@ -1962,4 +1977,12 @@ mod tests { MessagesOperatingMode::Basic(BasicOperatingMode::Normal), MessagesOperatingMode::Basic(BasicOperatingMode::Halted) ); + + #[test] + fn maybe_outbound_lanes_count_returns_correct_value() { + assert_eq!( + MaybeOutboundLanesCount::::get(), + Some(mock::ActiveOutboundLanes::get().len() as u32) + ); + } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 10750aabcd365..f18285f3dfee4 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -88,8 +88,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 76_449 nanoseconds. - Weight::from_parts(127_110_000, 54703) + // Minimum execution time: 50_655 nanoseconds. + Weight::from_parts(60_502_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -116,8 +116,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 102_297 nanoseconds. - Weight::from_parts(108_619_000, 54703) + // Minimum execution time: 58_861 nanoseconds. + Weight::from_parts(60_288_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -144,8 +144,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 84_911 nanoseconds. - Weight::from_parts(87_518_000, 54703) + // Minimum execution time: 53_459 nanoseconds. + Weight::from_parts(54_577_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -167,8 +167,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 79_805 nanoseconds. - Weight::from_parts(84_148_000, 54200) + // Minimum execution time: 54_011 nanoseconds. + Weight::from_parts(55_573_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -190,8 +190,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 141_515 nanoseconds. - Weight::from_parts(150_421_000, 54200) + // Minimum execution time: 105_856 nanoseconds. + Weight::from_parts(109_112_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -207,8 +207,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: - /// 2519, mode: MaxEncodedLen) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// @@ -217,9 +217,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `7599` - // Minimum execution time: 54_740 nanoseconds. - Weight::from_parts(56_637_000, 7599) + // Estimated: `5619` + // Minimum execution time: 40_894 nanoseconds. + Weight::from_parts(41_766_000, 5619) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -235,8 +235,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: - /// 2519, mode: MaxEncodedLen) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// @@ -245,9 +245,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `7599` - // Minimum execution time: 54_583 nanoseconds. - Weight::from_parts(56_205_000, 7599) + // Estimated: `5619` + // Minimum execution time: 39_996 nanoseconds. + Weight::from_parts(41_452_000, 5619) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -263,8 +263,8 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: - /// 2519, mode: MaxEncodedLen) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) /// @@ -273,9 +273,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `10134` - // Minimum execution time: 59_426 nanoseconds. - Weight::from_parts(61_911_000, 10134) + // Estimated: `8154` + // Minimum execution time: 42_281 nanoseconds. + Weight::from_parts(43_593_000, 8154) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -306,8 +306,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 76_449 nanoseconds. - Weight::from_parts(127_110_000, 54703) + // Minimum execution time: 50_655 nanoseconds. + Weight::from_parts(60_502_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -334,8 +334,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 102_297 nanoseconds. - Weight::from_parts(108_619_000, 54703) + // Minimum execution time: 58_861 nanoseconds. + Weight::from_parts(60_288_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -362,8 +362,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 84_911 nanoseconds. - Weight::from_parts(87_518_000, 54703) + // Minimum execution time: 53_459 nanoseconds. + Weight::from_parts(54_577_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -385,8 +385,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 79_805 nanoseconds. - Weight::from_parts(84_148_000, 54200) + // Minimum execution time: 54_011 nanoseconds. + Weight::from_parts(55_573_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -408,8 +408,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 141_515 nanoseconds. - Weight::from_parts(150_421_000, 54200) + // Minimum execution time: 105_856 nanoseconds. + Weight::from_parts(109_112_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -425,8 +425,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: - /// 2519, mode: MaxEncodedLen) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// @@ -435,9 +435,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `7599` - // Minimum execution time: 54_740 nanoseconds. - Weight::from_parts(56_637_000, 7599) + // Estimated: `5619` + // Minimum execution time: 40_894 nanoseconds. + Weight::from_parts(41_766_000, 5619) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -453,8 +453,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: - /// 2519, mode: MaxEncodedLen) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// @@ -463,9 +463,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `7599` - // Minimum execution time: 54_583 nanoseconds. - Weight::from_parts(56_205_000, 7599) + // Estimated: `5619` + // Minimum execution time: 39_996 nanoseconds. + Weight::from_parts(41_452_000, 5619) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -481,8 +481,8 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: None, max_size: Some(44), added: - /// 2519, mode: MaxEncodedLen) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) /// @@ -491,9 +491,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `10134` - // Minimum execution time: 59_426 nanoseconds. - Weight::from_parts(61_911_000, 10134) + // Estimated: `8154` + // Minimum execution time: 42_281 nanoseconds. + Weight::from_parts(43_593_000, 8154) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } From 2c15b94c8527a84a55b7bd488ec470aaaedb9ed8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Feb 2023 10:39:02 +0300 Subject: [PATCH 0939/1210] clippy fixes (#1880) --- relays/messages/src/message_race_delivery.rs | 8 ++++---- relays/messages/src/message_race_receiving.rs | 4 ++-- relays/messages/src/metrics.rs | 11 ++++------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 0d957fd8b7169..c704a7b561072 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -124,8 +124,8 @@ where self.client.latest_confirmed_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_source_latest_generated_nonce::

(latest_generated_nonce); - metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); + metrics_msg.update_source_latest_generated_nonce(latest_generated_nonce); + metrics_msg.update_source_latest_confirmed_nonce(latest_confirmed_nonce); } let new_nonces = if latest_generated_nonce > prev_latest_nonce { @@ -195,8 +195,8 @@ where if update_metrics { if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); - metrics_msg.update_target_latest_confirmed_nonce::

(latest_confirmed_nonce); + metrics_msg.update_target_latest_received_nonce(latest_received_nonce); + metrics_msg.update_target_latest_confirmed_nonce(latest_confirmed_nonce); } } diff --git a/relays/messages/src/message_race_receiving.rs b/relays/messages/src/message_race_receiving.rs index 70a3d7c24772a..e6497a1b79eb7 100644 --- a/relays/messages/src/message_race_receiving.rs +++ b/relays/messages/src/message_race_receiving.rs @@ -112,7 +112,7 @@ where ) -> Result<(TargetHeaderIdOf

, SourceClientNonces), Self::Error> { let (at_block, latest_received_nonce) = self.client.latest_received_nonce(at_block).await?; if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_target_latest_received_nonce::

(latest_received_nonce); + metrics_msg.update_target_latest_received_nonce(latest_received_nonce); } Ok(( at_block, @@ -174,7 +174,7 @@ where self.client.latest_confirmed_received_nonce(at_block).await?; if update_metrics { if let Some(metrics_msg) = self.metrics_msg.as_ref() { - metrics_msg.update_source_latest_confirmed_nonce::

(latest_confirmed_nonce); + metrics_msg.update_source_latest_confirmed_nonce(latest_confirmed_nonce); } } Ok((at_block, TargetClientNonces { latest_nonce: latest_confirmed_nonce, nonces_data: () })) diff --git a/relays/messages/src/metrics.rs b/relays/messages/src/metrics.rs index 20c6986b4747c..69d80d178de80 100644 --- a/relays/messages/src/metrics.rs +++ b/relays/messages/src/metrics.rs @@ -101,7 +101,7 @@ impl MessageLaneLoopMetrics { } /// Update latest generated nonce at source. - pub fn update_source_latest_generated_nonce( + pub fn update_source_latest_generated_nonce( &self, source_latest_generated_nonce: MessageNonce, ) { @@ -111,7 +111,7 @@ impl MessageLaneLoopMetrics { } /// Update the latest confirmed nonce at source. - pub fn update_source_latest_confirmed_nonce( + pub fn update_source_latest_confirmed_nonce( &self, source_latest_confirmed_nonce: MessageNonce, ) { @@ -121,17 +121,14 @@ impl MessageLaneLoopMetrics { } /// Update the latest received nonce at target. - pub fn update_target_latest_received_nonce( - &self, - target_latest_generated_nonce: MessageNonce, - ) { + pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: MessageNonce) { self.lane_state_nonces .with_label_values(&["target_latest_received"]) .set(target_latest_generated_nonce); } /// Update the latest confirmed nonce at target. - pub fn update_target_latest_confirmed_nonce( + pub fn update_target_latest_confirmed_nonce( &self, target_latest_confirmed_nonce: MessageNonce, ) { From 5908acab3b40ed5f4716a0165e7d4fea2f2d2856 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 14 Feb 2023 15:26:35 +0200 Subject: [PATCH 0940/1210] RefundRelayerForMessagesFromParachain improvements (#1879) * RefundRelayerForMessagesFromParachain improvements * Address code review comments --- bin/millau/runtime/src/lib.rs | 1 - bin/runtime-common/src/lib.rs | 40 +- ...ages_extension.rs => messages_call_ext.rs} | 155 ++++--- .../src/refund_relayer_extension.rs | 431 +++++++----------- modules/grandpa/README.md | 2 +- modules/grandpa/src/call_ext.rs | 163 +++++++ modules/grandpa/src/extension.rs | 117 ----- modules/grandpa/src/lib.rs | 24 +- modules/parachains/README.md | 2 +- modules/parachains/src/call_ext.rs | 243 ++++++++++ modules/parachains/src/extension.rs | 166 ------- modules/parachains/src/lib.rs | 126 ++--- primitives/runtime/src/lib.rs | 7 - 13 files changed, 753 insertions(+), 724 deletions(-) rename bin/runtime-common/src/{messages_extension.rs => messages_call_ext.rs} (57%) create mode 100644 modules/grandpa/src/call_ext.rs delete mode 100644 modules/grandpa/src/extension.rs create mode 100644 modules/parachains/src/call_ext.rs delete mode 100644 modules/parachains/src/extension.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2119fa04610be..8f82e645f9e02 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -608,7 +608,6 @@ pub type BridgeRefundRialtoParachainRelayers = RialtoGrandpaInstance, WithRialtoParachainsInstance, WithRialtoParachainMessagesInstance, - BridgeRejectObsoleteHeadersAndMessages, RialtoParachainId, RialtoParachainMessagesLane, Runtime, diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 9f31450bd28a4..32ea500db3ed8 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -18,14 +18,16 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_runtime::FilterCall; +use crate::messages_call_ext::MessagesCallSubType; +use pallet_bridge_grandpa::CallSubType as GrandpaCallSubType; +use pallet_bridge_parachains::CallSubType as ParachainsCallSubtype; use sp_runtime::transaction_validity::TransactionValidity; use xcm::v3::NetworkId; pub mod messages; pub mod messages_api; pub mod messages_benchmarking; -pub mod messages_extension; +pub mod messages_call_ext; pub mod parachains_benchmarking; pub mod refund_relayer_extension; @@ -44,21 +46,39 @@ pub trait BridgeRuntimeFilterCall { fn validate(call: &Call) -> TransactionValidity; } -impl BridgeRuntimeFilterCall for pallet_bridge_grandpa::Pallet +impl BridgeRuntimeFilterCall for pallet_bridge_grandpa::Pallet where - pallet_bridge_grandpa::Pallet: FilterCall, + T: pallet_bridge_grandpa::Config, + T::RuntimeCall: GrandpaCallSubType, { - fn validate(call: &Call) -> TransactionValidity { - as FilterCall>::validate(call) + fn validate(call: &T::RuntimeCall) -> TransactionValidity { + GrandpaCallSubType::::check_obsolete_submit_finality_proof(call) } } -impl BridgeRuntimeFilterCall for pallet_bridge_parachains::Pallet +impl BridgeRuntimeFilterCall + for pallet_bridge_parachains::Pallet where - pallet_bridge_parachains::Pallet: FilterCall, + T: pallet_bridge_parachains::Config, + T::RuntimeCall: ParachainsCallSubtype, { - fn validate(call: &Call) -> TransactionValidity { - as FilterCall>::validate(call) + fn validate(call: &T::RuntimeCall) -> TransactionValidity { + ParachainsCallSubtype::::check_obsolete_submit_parachain_heads(call) + } +} + +impl, I: 'static> BridgeRuntimeFilterCall + for pallet_bridge_messages::Pallet +where + T::RuntimeCall: MessagesCallSubType, +{ + /// Validate messages in order to avoid "mining" messages delivery and delivery confirmation + /// transactions, that are delivering outdated messages/confirmations. Without this validation, + /// even honest relayers may lose their funds if there are multiple relays running and + /// submitting the same messages/confirmations. + fn validate(call: &T::RuntimeCall) -> TransactionValidity { + call.check_obsolete_receive_messages_proof()?; + call.check_obsolete_receive_messages_delivery_proof() } } diff --git a/bin/runtime-common/src/messages_extension.rs b/bin/runtime-common/src/messages_call_ext.rs similarity index 57% rename from bin/runtime-common/src/messages_extension.rs rename to bin/runtime-common/src/messages_call_ext.rs index 1e207dc605b36..20e604142d944 100644 --- a/bin/runtime-common/src/messages_extension.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -14,20 +14,56 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - messages::{ - source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - }, - BridgeRuntimeFilterCall, +use crate::messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; +use bp_messages::{LaneId, MessageNonce}; use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; use pallet_bridge_messages::{Config, Pallet}; -use sp_runtime::transaction_validity::TransactionValidity; +use sp_runtime::{transaction_validity::TransactionValidity, RuntimeDebug}; + +/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. +#[derive(Copy, Clone, PartialEq, RuntimeDebug)] +pub struct ReceiveMessagesProofInfo { + pub lane_id: LaneId, + pub best_proof_nonce: MessageNonce, + pub best_stored_nonce: MessageNonce, +} + +/// Helper struct that provides methods for working with the `ReceiveMessagesProof` call. +pub struct ReceiveMessagesProofHelper, I: 'static> { + pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, +} + +impl, I: 'static> ReceiveMessagesProofHelper { + /// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that + /// it contained. + pub fn was_partially_successful(info: &ReceiveMessagesProofInfo) -> bool { + let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(info.lane_id); + inbound_lane_data.last_delivered_nonce() > info.best_stored_nonce + } +} + +/// Trait representing a call that is a sub type of `pallet_bridge_messages::Call`. +pub trait MessagesCallSubType, I: 'static>: + IsSubType, T>> +{ + /// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call. + fn receive_messages_proof_info(&self) -> Option; + + /// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call, + /// if the call is for the provided lane. + fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option; + + /// Check that a `ReceiveMessagesProof` call is trying to deliver at least some messages that + /// are better than the ones we know of. + fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity; + + /// Check that a `ReceiveMessagesDeliveryProof` call is trying to deliver at least some message + /// confirmations that are better than the ones we know of. + fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity; +} -/// Validate messages in order to avoid "mining" messages delivery and delivery confirmation -/// transactions, that are delivering outdated messages/confirmations. Without this validation, -/// even honest relayers may lose their funds if there are multiple relays running and submitting -/// the same messages/confirmations. impl< BridgedHeaderHash, SourceHeaderChain: bp_messages::target_chain::SourceHeaderChain< @@ -42,52 +78,69 @@ impl< T: frame_system::Config + Config, I: 'static, - > BridgeRuntimeFilterCall for Pallet + > MessagesCallSubType for T::RuntimeCall { - fn validate(call: &Call) -> TransactionValidity { - match call.is_sub_type() { - Some(pallet_bridge_messages::Call::::receive_messages_proof { - ref proof, - .. - }) => { - let inbound_lane_data = - pallet_bridge_messages::InboundLanes::::get(proof.lane); - if proof.nonces_end <= inbound_lane_data.last_delivered_nonce() { - log::trace!( - target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages delivery transaction: \ + fn receive_messages_proof_info(&self) -> Option { + if let Some(pallet_bridge_messages::Call::::receive_messages_proof { + ref proof, + .. + }) = self.is_sub_type() + { + let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(proof.lane); + + return Some(ReceiveMessagesProofInfo { + lane_id: proof.lane, + best_proof_nonce: proof.nonces_end, + best_stored_nonce: inbound_lane_data.last_delivered_nonce(), + }) + } + + None + } + + fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option { + self.receive_messages_proof_info().filter(|info| info.lane_id == lane_id) + } + + fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity { + if let Some(proof_info) = self.receive_messages_proof_info() { + if proof_info.best_proof_nonce <= proof_info.best_stored_nonce { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages delivery transaction: \ lane {:?}, bundled {:?}, best {:?}", - proof.lane, - proof.nonces_end, - inbound_lane_data.last_delivered_nonce(), - ); + proof_info.lane_id, + proof_info.best_proof_nonce, + proof_info.best_stored_nonce, + ); - return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - }, - Some(pallet_bridge_messages::Call::::receive_messages_delivery_proof { - ref proof, - ref relayers_state, - .. - }) => { - let latest_delivered_nonce = relayers_state.last_delivered_nonce; - - let outbound_lane_data = - pallet_bridge_messages::OutboundLanes::::get(proof.lane); - if latest_delivered_nonce <= outbound_lane_data.latest_received_nonce { - log::trace!( - target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages confirmation transaction: \ + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + } + } + + Ok(sp_runtime::transaction_validity::ValidTransaction::default()) + } + + fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity { + if let Some(pallet_bridge_messages::Call::::receive_messages_delivery_proof { + ref proof, + ref relayers_state, + .. + }) = self.is_sub_type() + { + let outbound_lane_data = pallet_bridge_messages::OutboundLanes::::get(proof.lane); + if relayers_state.last_delivered_nonce <= outbound_lane_data.latest_received_nonce { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages confirmation transaction: \ lane {:?}, bundled {:?}, best {:?}", - proof.lane, - latest_delivered_nonce, - outbound_lane_data.latest_received_nonce, - ); + proof.lane, + relayers_state.last_delivered_nonce, + outbound_lane_data.latest_received_nonce, + ); - return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - }, - _ => {}, + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + } } Ok(sp_runtime::transaction_validity::ValidTransaction::default()) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 51a7db3b53b00..ac65617483d56 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -19,37 +19,32 @@ //! with calls that are: delivering new messsage and all necessary underlying headers //! (parachain or relay chain). -use crate::messages::target::FromBridgedChainMessagesProof; - -use bp_messages::{target_chain::SourceHeaderChain, LaneId, MessageNonce}; -use bp_polkadot_core::parachains::ParaId; -use bp_runtime::{Chain, HashOf}; +use crate::messages_call_ext::{ + MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo, +}; +use bp_messages::LaneId; use codec::{Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, traits::IsSubType, CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; -use pallet_bridge_grandpa::{ - BridgedChain, Call as GrandpaCall, Config as GrandpaConfig, Pallet as GrandpaPallet, -}; -use pallet_bridge_messages::{ - Call as MessagesCall, Config as MessagesConfig, Pallet as MessagesPallet, -}; +use pallet_bridge_grandpa::{CallSubType as GrandpaCallSubType, SubmitFinalityProofHelper}; +use pallet_bridge_messages::Config as MessagesConfig; use pallet_bridge_parachains::{ - Call as ParachainsCall, Config as ParachainsConfig, Pallet as ParachainsPallet, RelayBlockHash, - RelayBlockHasher, RelayBlockNumber, + BoundedBridgeGrandpaConfig, CallSubType as ParachainsCallSubType, Config as ParachainsConfig, + RelayBlockNumber, SubmitParachainHeadsHelper, SubmitParachainHeadsInfo, }; use pallet_bridge_relayers::{Config as RelayersConfig, Pallet as RelayersPallet}; use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTransaction}; use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Get, Header as HeaderT, PostDispatchInfoOf, SignedExtension, Zero}, + traits::{DispatchInfoOf, Get, PostDispatchInfoOf, SignedExtension, Zero}, transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, DispatchResult, FixedPointOperand, }; -use sp_std::marker::PhantomData; +use sp_std::{marker::PhantomData, vec, vec::Vec}; // TODO (https://github.com/paritytech/parity-bridges-common/issues/1667): // support multiple bridges in this extension @@ -81,6 +76,7 @@ where pallet_transaction_payment::Pallet::::compute_actual_fee(len as _, info, post_info, tip) } } + /// Signed extension that refunds relayer for new messages coming from the parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) @@ -99,18 +95,40 @@ where RuntimeDebugNoBound, TypeInfo, )] -#[scale_info(skip_type_params(RT, GI, PI, MI, BE, PID, LID, FEE))] -#[allow(clippy::type_complexity)] // TODO: get rid of that in https://github.com/paritytech/parity-bridges-common/issues/1666 -pub struct RefundRelayerForMessagesFromParachain( - PhantomData<(RT, GI, PI, MI, BE, PID, LID, FEE)>, +#[scale_info(skip_type_params(RT, GI, PI, MI, PID, LID, FEE))] +pub struct RefundRelayerForMessagesFromParachain( + PhantomData<(RT, GI, PI, MI, PID, LID, FEE)>, ); +impl + RefundRelayerForMessagesFromParachain +where + R: UtilityConfig>, + CallOf: IsSubType, R>>, +{ + fn expand_call<'a>(&self, call: &'a CallOf) -> Option>> { + let calls = match call.is_sub_type() { + Some(UtilityCall::::batch_all { ref calls }) => { + if calls.len() > 3 { + return None + } + + calls.iter().collect() + }, + Some(_) => return None, + None => vec![call], + }; + + Some(calls) + } +} + /// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`. #[derive(PartialEq)] #[cfg_attr(test, derive(Debug))] pub struct PreDispatchData { /// Transaction submitter (relayer) account. - pub relayer: AccountId, + relayer: AccountId, /// Type of the call. pub call_type: CallType, } @@ -119,89 +137,51 @@ pub struct PreDispatchData { #[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] pub enum CallType { /// Relay chain finality + parachain finality + message delivery calls. - AllFinalityAndDelivery(ExpectedRelayChainState, ExpectedParachainState, MessagesState), + AllFinalityAndDelivery(RelayBlockNumber, SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), /// Parachain finality + message delivery calls. - ParachainFinalityAndDelivery(ExpectedParachainState, MessagesState), + ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), /// Standalone message delivery call. - Delivery(MessagesState), + Delivery(ReceiveMessagesProofInfo), } impl CallType { /// Returns the pre-dispatch messages pallet state. - fn pre_dispatch_messages_state(&self) -> MessagesState { + fn receive_messages_proof_info(&self) -> ReceiveMessagesProofInfo { match *self { - Self::AllFinalityAndDelivery(_, _, messages_state) => messages_state, - Self::ParachainFinalityAndDelivery(_, messages_state) => messages_state, - Self::Delivery(messages_state) => messages_state, + Self::AllFinalityAndDelivery(_, _, info) => info, + Self::ParachainFinalityAndDelivery(_, info) => info, + Self::Delivery(info) => info, } } } -/// Expected post-dispatch state of the relay chain pallet. -#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] -pub struct ExpectedRelayChainState { - /// Best known relay chain block number. - pub best_block_number: RelayBlockNumber, -} - -/// Expected post-dispatch state of the parachain pallet. -#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] -pub struct ExpectedParachainState { - /// At which relay block the parachain head has been updated? - pub at_relay_block_number: RelayBlockNumber, -} - -/// Pre-dispatch state of messages pallet. -/// -/// This struct is for pre-dispatch state of the pallet, not the expected post-dispatch state. -/// That's because message delivery transaction may deliver some of messages that it brings. -/// If this happens, we consider it "helpful" and refund its cost. If transaction fails to -/// deliver at least one message, it is considered wrong and is not refunded. -#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] -pub struct MessagesState { - /// Best delivered message nonce. - pub best_nonce: MessageNonce, -} - // without this typedef rustfmt fails with internal err type BalanceOf = <::OnChargeTransaction as OnChargeTransaction>::Balance; type CallOf = ::RuntimeCall; -impl SignedExtension - for RefundRelayerForMessagesFromParachain +impl SignedExtension + for RefundRelayerForMessagesFromParachain where R: 'static + Send + Sync - + frame_system::Config + UtilityConfig> - + GrandpaConfig + + BoundedBridgeGrandpaConfig + ParachainsConfig + MessagesConfig + RelayersConfig, GI: 'static + Send + Sync, PI: 'static + Send + Sync, MI: 'static + Send + Sync, - BE: 'static - + Send - + Sync - + Default - + SignedExtension>, PID: 'static + Send + Sync + Get, LID: 'static + Send + Sync + Get, FEE: 'static + Send + Sync + TransactionFeeCalculation<::Reward>, - ::RuntimeCall: - Dispatchable, - CallOf: IsSubType, R>> - + IsSubType, R>> - + IsSubType, R>> - + IsSubType, R>>, - >::BridgedChain: - Chain, - >::SourceHeaderChain: SourceHeaderChain< - MessagesProof = FromBridgedChainMessagesProof>>, - >, + CallOf: Dispatchable + + IsSubType, R>> + + GrandpaCallSubType + + ParachainsCallSubType + + MessagesCallSubType, { const IDENTIFIER: &'static str = "RefundRelayerForMessagesFromParachain"; type AccountId = R::AccountId; @@ -215,17 +195,20 @@ where fn validate( &self, - who: &Self::AccountId, + _who: &Self::AccountId, call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + _info: &DispatchInfoOf, + _len: usize, ) -> TransactionValidity { - // reject batch transactions with obsolete headers - if let Some(UtilityCall::::batch_all { ref calls }) = call.is_sub_type() { - for nested_call in calls { - let reject_obsolete_transactions = BE::default(); - reject_obsolete_transactions.pre_dispatch(who, nested_call, info, len)?; - } + let calls = match self.expand_call(call) { + Some(calls) => calls, + None => return Ok(ValidTransaction::default()), + }; + + for call in calls { + call.check_obsolete_submit_finality_proof()?; + call.check_obsolete_submit_parachain_heads()?; + call.check_obsolete_receive_messages_proof()?; } Ok(ValidTransaction::default()) @@ -241,40 +224,37 @@ where // reject batch transactions with obsolete headers self.validate(who, call, info, len).map(drop)?; - // now try to check if tx matches one of types we support + // Try to check if the tx matches one of types we support. let parse_call_type = || { - if let Some(UtilityCall::::batch_all { ref calls }) = call.is_sub_type() { - if calls.len() == 3 { - return Some(CallType::AllFinalityAndDelivery( - extract_expected_relay_chain_state::(&calls[0])?, - extract_expected_parachain_state::(&calls[1])?, - extract_messages_state::(&calls[2])?, - )) - } - if calls.len() == 2 { - return Some(CallType::ParachainFinalityAndDelivery( - extract_expected_parachain_state::(&calls[0])?, - extract_messages_state::(&calls[1])?, - )) - } - return None + let mut calls = self.expand_call(call)?.into_iter(); + match calls.len() { + 3 => Some(CallType::AllFinalityAndDelivery( + calls.next()?.submit_finality_proof_info()?, + calls.next()?.submit_parachain_heads_info_for(PID::get())?, + calls.next()?.receive_messages_proof_info_for(LID::get())?, + )), + 2 => Some(CallType::ParachainFinalityAndDelivery( + calls.next()?.submit_parachain_heads_info_for(PID::get())?, + calls.next()?.receive_messages_proof_info_for(LID::get())?, + )), + 1 => Some(CallType::Delivery( + calls.next()?.receive_messages_proof_info_for(LID::get())?, + )), + _ => None, } - - Some(CallType::Delivery(extract_messages_state::(call)?)) }; - Ok(parse_call_type() - .map(|call_type| { - log::trace!( - target: "runtime::bridge", - "RefundRelayerForMessagesFromParachain from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", - PID::get(), - LID::get(), - call_type, - ); - PreDispatchData { relayer: who.clone(), call_type } - }) - ) + Ok(parse_call_type().map(|call_type| { + log::trace!( + target: "runtime::bridge", + "RefundRelayerForMessagesFromParachain from parachain {} via {:?} \ + parsed bridge transaction in pre-dispatch: {:?}", + PID::get(), + LID::get(), + call_type, + ); + PreDispatchData { relayer: who.clone(), call_type } + })) } fn post_dispatch( @@ -284,40 +264,37 @@ where len: usize, result: &DispatchResult, ) -> Result<(), TransactionValidityError> { - // we never refund anything if it is not bridge transaction or if it is a bridge - // transaction that we do not support here + // We don't refund anything if the transaction has failed. + if result.is_err() { + return Ok(()) + } + + // We don't refund anything for transactions that we don't support. let (relayer, call_type) = match pre { Some(Some(pre)) => (pre.relayer, pre.call_type), _ => return Ok(()), }; - // we never refund anything if transaction has failed - if result.is_err() { - return Ok(()) - } - // check if relay chain state has been updated - if let CallType::AllFinalityAndDelivery(expected_relay_chain_state, _, _) = call_type { - let actual_relay_chain_state = relay_chain_state::(); - if actual_relay_chain_state != Some(expected_relay_chain_state) { + if let CallType::AllFinalityAndDelivery(relay_block_number, _, _) = call_type { + if !SubmitFinalityProofHelper::::was_successful(relay_block_number) { // we only refund relayer if all calls have updated chain state return Ok(()) } - // there's a conflict between how bridge GRANDPA pallet works and the - // `AllFinalityAndDelivery` transaction. If relay chain header is mandatory, the GRANDPA - // pallet returns `Pays::No`, because such transaction is mandatory for operating the - // bridge. But `utility.batchAll` transaction always requires payment. But in both cases - // we'll refund relayer - either explicitly here, or using `Pays::No` if he's choosing + // there's a conflict between how bridge GRANDPA pallet works and a `utility.batchAll` + // transaction. If relay chain header is mandatory, the GRANDPA pallet returns + // `Pays::No`, because such transaction is mandatory for operating the bridge. But + // `utility.batchAll` transaction always requires payment. But in both cases we'll + // refund relayer - either explicitly here, or using `Pays::No` if he's choosing // to submit dedicated transaction. } // check if parachain state has been updated match call_type { - CallType::AllFinalityAndDelivery(_, expected_parachain_state, _) | - CallType::ParachainFinalityAndDelivery(expected_parachain_state, _) => { - let actual_parachain_state = parachain_state::(); - if actual_parachain_state != Some(expected_parachain_state) { + CallType::AllFinalityAndDelivery(_, parachain_heads_info, _) | + CallType::ParachainFinalityAndDelivery(parachain_heads_info, _) => { + if !SubmitParachainHeadsHelper::::was_successful(¶chain_heads_info) { // we only refund relayer if all calls have updated chain state return Ok(()) } @@ -325,11 +302,10 @@ where _ => (), } - // check if messages have been delivered - let actual_messages_state = messages_state::(); - let pre_dispatch_messages_state = call_type.pre_dispatch_messages_state(); - if actual_messages_state == Some(pre_dispatch_messages_state) { - // we only refund relayer if all calls have updated chain state + // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that + // it contained. If this happens, we consider the transaction "helpful" and refund it. + let messages_proof_info = call_type.receive_messages_proof_info(); + if !ReceiveMessagesProofHelper::::was_partially_successful(&messages_proof_info) { return Ok(()) } @@ -359,125 +335,22 @@ where } } -/// Extracts expected relay chain state from the call. -fn extract_expected_relay_chain_state(call: &CallOf) -> Option -where - R: GrandpaConfig, - GI: 'static, - >::BridgedChain: Chain, - CallOf: IsSubType, R>>, -{ - if let Some(GrandpaCall::::submit_finality_proof { ref finality_target, .. }) = - call.is_sub_type() - { - return Some(ExpectedRelayChainState { best_block_number: *finality_target.number() }) - } - None -} - -/// Extracts expected parachain state from the call. -fn extract_expected_parachain_state( - call: &CallOf, -) -> Option -where - R: GrandpaConfig + ParachainsConfig, - GI: 'static, - PI: 'static, - PID: Get, - >::BridgedChain: - Chain, - CallOf: IsSubType, R>>, -{ - if let Some(ParachainsCall::::submit_parachain_heads { - ref at_relay_block, - ref parachains, - .. - }) = call.is_sub_type() - { - if parachains.len() != 1 || parachains[0].0 != ParaId(PID::get()) { - return None - } - - return Some(ExpectedParachainState { at_relay_block_number: at_relay_block.0 }) - } - None -} - -/// Extracts messages state from the call. -fn extract_messages_state(call: &CallOf) -> Option -where - R: GrandpaConfig + MessagesConfig, - GI: 'static, - MI: 'static, - LID: Get, - CallOf: IsSubType, R>>, - >::SourceHeaderChain: SourceHeaderChain< - MessagesProof = FromBridgedChainMessagesProof>>, - >, -{ - if let Some(MessagesCall::::receive_messages_proof { ref proof, .. }) = - call.is_sub_type() - { - if LID::get() != proof.lane { - return None - } - - return Some(MessagesState { - best_nonce: MessagesPallet::::inbound_lane_data(proof.lane) - .last_delivered_nonce(), - }) - } - None -} - -/// Returns relay chain state that we are interested in. -fn relay_chain_state() -> Option -where - R: GrandpaConfig, - GI: 'static, - >::BridgedChain: Chain, -{ - GrandpaPallet::::best_finalized_number() - .map(|best_block_number| ExpectedRelayChainState { best_block_number }) -} - -/// Returns parachain state that we are interested in. -fn parachain_state() -> Option -where - R: ParachainsConfig, - PI: 'static, - PID: Get, -{ - ParachainsPallet::::best_parachain_info(ParaId(PID::get())).map(|para_info| { - ExpectedParachainState { - at_relay_block_number: para_info.best_head_hash.at_relay_block_number, - } - }) -} - -/// Returns messages state that we are interested in. -fn messages_state() -> Option -where - R: MessagesConfig, - MI: 'static, - LID: Get, -{ - Some(MessagesState { - best_nonce: MessagesPallet::::inbound_lane_data(LID::get()).last_delivered_nonce(), - }) -} - #[cfg(test)] mod tests { use super::*; use crate::{messages::target::FromBridgedChainMessagesProof, mock::*}; - use bp_messages::InboundLaneData; + use bp_messages::{InboundLaneData, MessageNonce}; use bp_parachains::{BestParaHeadHash, ParaInfo}; - use bp_polkadot_core::parachains::ParaHeadsProof; + use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderId; use bp_test_utils::make_default_justification; use frame_support::{assert_storage_noop, parameter_types, weights::Weight}; - use sp_runtime::{transaction_validity::InvalidTransaction, DispatchError}; + use pallet_bridge_grandpa::Call as GrandpaCall; + use pallet_bridge_messages::Call as MessagesCall; + use pallet_bridge_parachains::{Call as ParachainsCall, RelayBlockHash}; + use sp_runtime::{ + traits::Header as HeaderT, transaction_validity::InvalidTransaction, DispatchError, + }; parameter_types! { pub TestParachain: u32 = 1000; @@ -489,7 +362,6 @@ mod tests { (), (), (), - BridgeRejectObsoleteHeadersAndMessages, TestParachain, TestLaneId, TestRuntime, @@ -506,6 +378,7 @@ mod tests { fn initialize_environment( best_relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, + parachain_head_hash: ParaHash, best_delivered_message: MessageNonce, ) { let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); @@ -515,7 +388,7 @@ mod tests { let para_info = ParaInfo { best_head_hash: BestParaHeadHash { at_relay_block_number: parachain_head_at_relay_header_number, - head_hash: Default::default(), + head_hash: parachain_head_hash, }, next_imported_hash_position: 0, }; @@ -598,9 +471,17 @@ mod tests { PreDispatchData { relayer: relayer_account_at_this_chain(), call_type: CallType::AllFinalityAndDelivery( - ExpectedRelayChainState { best_block_number: 200 }, - ExpectedParachainState { at_relay_block_number: 200 }, - MessagesState { best_nonce: 100 }, + 200, + SubmitParachainHeadsInfo { + at_relay_block_number: 200, + para_id: ParaId(TestParachain::get()), + para_head_hash: [1u8; 32].into(), + }, + ReceiveMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_proof_nonce: 200, + best_stored_nonce: 100, + }, ), } } @@ -609,8 +490,16 @@ mod tests { PreDispatchData { relayer: relayer_account_at_this_chain(), call_type: CallType::ParachainFinalityAndDelivery( - ExpectedParachainState { at_relay_block_number: 200 }, - MessagesState { best_nonce: 100 }, + SubmitParachainHeadsInfo { + at_relay_block_number: 200, + para_id: ParaId(TestParachain::get()), + para_head_hash: [1u8; 32].into(), + }, + ReceiveMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_proof_nonce: 200, + best_stored_nonce: 100, + }, ), } } @@ -618,7 +507,11 @@ mod tests { fn delivery_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_type: CallType::Delivery(MessagesState { best_nonce: 100 }), + call_type: CallType::Delivery(ReceiveMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_proof_nonce: 200, + best_stored_nonce: 100, + }), } } @@ -678,7 +571,7 @@ mod tests { #[test] fn validate_allows_non_obsolete_transactions() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!(run_validate(message_delivery_call(200)), Ok(ValidTransaction::default()),); @@ -697,7 +590,7 @@ mod tests { #[test] fn ext_rejects_batch_with_obsolete_relay_chain_header() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)), @@ -714,7 +607,7 @@ mod tests { #[test] fn ext_rejects_batch_with_obsolete_parachain_head() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)), @@ -741,7 +634,7 @@ mod tests { #[test] fn ext_rejects_batch_with_obsolete_messages() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)), @@ -768,7 +661,7 @@ mod tests { #[test] fn pre_dispatch_parses_batch_with_relay_chain_and_parachain_headers() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), @@ -780,7 +673,7 @@ mod tests { #[test] fn pre_dispatch_parses_batch_with_parachain_header() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!( run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), @@ -792,7 +685,7 @@ mod tests { #[test] fn pre_dispatch_fails_to_parse_batch_with_multiple_parachain_headers() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); let call = RuntimeCall::Utility(UtilityCall::batch_all { calls: vec![ @@ -815,7 +708,7 @@ mod tests { #[test] fn pre_dispatch_parses_message_delivery_transaction() { run_test(|| { - initialize_environment(100, 100, 100); + initialize_environment(100, 100, Default::default(), 100); assert_eq!( run_pre_dispatch(message_delivery_call(200)), @@ -844,7 +737,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_updated_relay_chain_state() { run_test(|| { - initialize_environment(100, 200, 200); + initialize_environment(100, 200, Default::default(), 200); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); }); @@ -853,7 +746,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_updated_parachain_state() { run_test(|| { - initialize_environment(200, 100, 200); + initialize_environment(200, 100, Default::default(), 200); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); assert_storage_noop!(run_post_dispatch( @@ -866,7 +759,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_delivered_any_messages() { run_test(|| { - initialize_environment(200, 200, 100); + initialize_environment(200, 200, Default::default(), 100); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); assert_storage_noop!(run_post_dispatch( @@ -880,7 +773,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_all_finality_batch() { run_test(|| { - initialize_environment(200, 200, 200); + initialize_environment(200, 200, [1u8; 32].into(), 200); run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())); assert_eq!( @@ -896,7 +789,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_parachain_finality_batch() { run_test(|| { - initialize_environment(200, 200, 200); + initialize_environment(200, 200, [1u8; 32].into(), 200); run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(())); assert_eq!( @@ -912,7 +805,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_message_delivery_transaction() { run_test(|| { - initialize_environment(200, 200, 200); + initialize_environment(200, 200, Default::default(), 200); run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())); assert_eq!( diff --git a/modules/grandpa/README.md b/modules/grandpa/README.md index eaa62e8b20601..27b4d2389c408 100644 --- a/modules/grandpa/README.md +++ b/modules/grandpa/README.md @@ -87,7 +87,7 @@ It'd be better for anyone (for chain and for submitters) to reject all transacti already known headers to the pallet. This way, we leave block space to other useful transactions and we don't charge concurrent submitters for their honest actions. -To deal with that, we have a [signed extension](./src/extension.rs) that may be added to the runtime. +To deal with that, we have a [signed extension](./src/call_ext) that may be added to the runtime. It does exactly what is required - rejects all transactions with already known headers. The submitter pays nothing for such transactions - they're simply removed from the transaction pool, when the block is built. diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs new file mode 100644 index 0000000000000..42c276f5f6c2c --- /dev/null +++ b/modules/grandpa/src/call_ext.rs @@ -0,0 +1,163 @@ +// Copyright 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 . + +use crate::{Config, Error, Pallet}; +use bp_runtime::BlockNumberOf; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use sp_runtime::{ + traits::Header, + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, +}; + +/// Helper struct that provides methods for working with the `SubmitFinalityProof` call. +pub struct SubmitFinalityProofHelper, I: 'static> { + pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, +} + +impl, I: 'static> SubmitFinalityProofHelper { + /// Check that the GRANDPA head provided by the `SubmitFinalityProof` is better than the best + /// one we know. + pub fn check_obsolete( + finality_target: BlockNumberOf, + ) -> Result<(), Error> { + let best_finalized = crate::BestFinalized::::get().ok_or_else(|| { + log::trace!( + target: crate::LOG_TARGET, + "Cannot finalize header {:?} because pallet is not yet initialized", + finality_target, + ); + >::NotInitialized + })?; + + if best_finalized.number() >= finality_target { + log::trace!( + target: crate::LOG_TARGET, + "Cannot finalize obsolete header: bundled {:?}, best {:?}", + finality_target, + best_finalized, + ); + + return Err(Error::::OldHeader) + } + + Ok(()) + } + + /// Check if the `SubmitFinalityProof` was successfully executed. + pub fn was_successful(finality_target: BlockNumberOf) -> bool { + match crate::BestFinalized::::get() { + Some(best_finalized) => best_finalized.number() == finality_target, + None => false, + } + } +} + +/// Trait representing a call that is a sub type of this pallet's call. +pub trait CallSubType, I: 'static>: + IsSubType, T>> +{ + /// Extract the finality target from a `SubmitParachainHeads` call. + fn submit_finality_proof_info(&self) -> Option> { + if let Some(crate::Call::::submit_finality_proof { finality_target, .. }) = + self.is_sub_type() + { + return Some(*finality_target.number()) + } + + None + } + + /// Validate Grandpa headers in order to avoid "mining" transactions that provide outdated + /// bridged chain headers. Without this validation, even honest relayers may lose their funds + /// if there are multiple relays running and submitting the same information. + fn check_obsolete_submit_finality_proof(&self) -> TransactionValidity + where + Self: Sized, + { + let finality_target = match self.submit_finality_proof_info() { + Some(finality_proof) => finality_proof, + _ => return Ok(ValidTransaction::default()), + }; + + match SubmitFinalityProofHelper::::check_obsolete(finality_target) { + Ok(_) => Ok(ValidTransaction::default()), + Err(Error::::OldHeader) => InvalidTransaction::Stale.into(), + Err(_) => InvalidTransaction::Call.into(), + } + } +} + +impl, I: 'static> CallSubType for T::RuntimeCall where + T::RuntimeCall: IsSubType, T>> +{ +} + +#[cfg(test)] +mod tests { + use crate::{ + call_ext::CallSubType, + mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime}, + BestFinalized, + }; + use bp_runtime::HeaderId; + use bp_test_utils::make_default_justification; + + fn validate_block_submit(num: TestNumber) -> bool { + let bridge_grandpa_call = crate::Call::::submit_finality_proof { + finality_target: Box::new(test_header(num)), + justification: make_default_justification(&test_header(num)), + }; + RuntimeCall::check_obsolete_submit_finality_proof(&RuntimeCall::Grandpa( + bridge_grandpa_call, + )) + .is_ok() + } + + fn sync_to_header_10() { + let header10_hash = sp_core::H256::default(); + BestFinalized::::put(HeaderId(10, header10_hash)); + } + + #[test] + fn extension_rejects_obsolete_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#5 => tx is + // rejected + sync_to_header_10(); + assert!(!validate_block_submit(5)); + }); + } + + #[test] + fn extension_rejects_same_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#10 => tx is + // rejected + sync_to_header_10(); + assert!(!validate_block_submit(10)); + }); + } + + #[test] + fn extension_accepts_new_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#15 => tx is + // accepted + sync_to_header_10(); + assert!(validate_block_submit(15)); + }); + } +} diff --git a/modules/grandpa/src/extension.rs b/modules/grandpa/src/extension.rs deleted file mode 100644 index 87075ee5d588d..0000000000000 --- a/modules/grandpa/src/extension.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 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 . - -use crate::{Config, Pallet}; -use bp_runtime::FilterCall; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; -use sp_runtime::{ - traits::Header, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, -}; - -/// Validate Grandpa headers in order to avoid "mining" transactions that provide outdated -/// bridged chain headers. Without this validation, even honest relayers may lose their funds -/// if there are multiple relays running and submitting the same information. -impl< - Call: IsSubType, T>>, - T: frame_system::Config + Config, - I: 'static, - > FilterCall for Pallet -{ - fn validate(call: &::RuntimeCall) -> TransactionValidity { - let bundled_block_number = match call.is_sub_type() { - Some(crate::Call::::submit_finality_proof { ref finality_target, .. }) => - *finality_target.number(), - _ => return Ok(ValidTransaction::default()), - }; - - let best_finalized = crate::BestFinalized::::get(); - let best_finalized_number = match best_finalized { - Some(best_finalized_id) => best_finalized_id.number(), - None => return InvalidTransaction::Call.into(), - }; - - if best_finalized_number >= bundled_block_number { - log::trace!( - target: crate::LOG_TARGET, - "Rejecting obsolete bridged header: bundled {:?}, best {:?}", - bundled_block_number, - best_finalized_number, - ); - - return InvalidTransaction::Stale.into() - } - - Ok(ValidTransaction::default()) - } -} - -#[cfg(test)] -mod tests { - use super::FilterCall; - use crate::{ - mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime}, - BestFinalized, - }; - use bp_runtime::HeaderId; - use bp_test_utils::make_default_justification; - - fn validate_block_submit(num: TestNumber) -> bool { - crate::Pallet::::validate(&RuntimeCall::Grandpa(crate::Call::< - TestRuntime, - (), - >::submit_finality_proof { - finality_target: Box::new(test_header(num)), - justification: make_default_justification(&test_header(num)), - })) - .is_ok() - } - - fn sync_to_header_10() { - let header10_hash = sp_core::H256::default(); - BestFinalized::::put(HeaderId(10, header10_hash)); - } - - #[test] - fn extension_rejects_obsolete_header() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#5 => tx is - // rejected - sync_to_header_10(); - assert!(!validate_block_submit(5)); - }); - } - - #[test] - fn extension_rejects_same_header() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#10 => tx is - // rejected - sync_to_header_10(); - assert!(!validate_block_submit(10)); - }); - } - - #[test] - fn extension_accepts_new_header() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#15 => tx is - // accepted - sync_to_header_10(); - assert!(validate_block_submit(15)); - }); - } -} diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 09b7f55a73c02..c2b7943479588 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -44,7 +44,7 @@ use bp_header_chain::{ }; use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{dispatch::PostDispatchInfo, ensure, fail}; +use frame_support::{dispatch::PostDispatchInfo, ensure}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, @@ -52,7 +52,7 @@ use sp_runtime::{ }; use sp_std::{boxed::Box, convert::TryInto}; -mod extension; +mod call_ext; #[cfg(test)] mod mock; mod storage_types; @@ -64,6 +64,7 @@ pub mod weights; pub mod benchmarking; // Re-export in crate namespace for `construct_runtime!` +pub use call_ext::*; pub use pallet::*; pub use weights::WeightInfo; @@ -154,7 +155,7 @@ pub mod pallet { /// If successful in verification, it will write the target header to the underlying storage /// pallet. #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::submit_finality_proof( + #[pallet::weight(::submit_finality_proof( justification.commit.precommits.len().saturated_into(), justification.votes_ancestries.len().saturated_into(), ))] @@ -174,22 +175,7 @@ pub mod pallet { finality_target ); - let best_finalized_number = match BestFinalized::::get() { - Some(best_finalized_id) => best_finalized_id.number(), - None => { - log::error!( - target: LOG_TARGET, - "Cannot finalize header {:?} because pallet is not yet initialized", - finality_target, - ); - fail!(>::NotInitialized); - }, - }; - - // We do a quick check here to ensure that our header chain is making progress and isn't - // "travelling back in time" (which could be indicative of something bad, e.g a - // hard-fork). - ensure!(best_finalized_number < *number, >::OldHeader); + SubmitFinalityProofHelper::::check_obsolete(*number)?; let authority_set = >::get(); let unused_proof_size = authority_set.unused_proof_size(); diff --git a/modules/parachains/README.md b/modules/parachains/README.md index 1bd91a3ba776f..5982c65ad3166 100644 --- a/modules/parachains/README.md +++ b/modules/parachains/README.md @@ -71,7 +71,7 @@ It'd be better for anyone (for chain and for submitters) to reject all transacti already known parachain heads to the pallet. This way, we leave block space to other useful transactions and we don't charge concurrent submitters for their honest actions. -To deal with that, we have a [signed extension](./src/extension.rs) that may be added to the runtime. +To deal with that, we have a [signed extension](./src/call_ext) that may be added to the runtime. It does exactly what is required - rejects all transactions with already known heads. The submitter pays nothing for such transactions - they're simply removed from the transaction pool, when the block is built. diff --git a/modules/parachains/src/call_ext.rs b/modules/parachains/src/call_ext.rs new file mode 100644 index 0000000000000..41649336579e0 --- /dev/null +++ b/modules/parachains/src/call_ext.rs @@ -0,0 +1,243 @@ +// Copyright 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 . + +use crate::{Config, Pallet, RelayBlockNumber}; +use bp_parachains::BestParaHeadHash; +use bp_polkadot_core::parachains::{ParaHash, ParaId}; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use sp_runtime::{ + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + RuntimeDebug, +}; + +/// Info about a `SubmitParachainHeads` call which tries to update a single parachain. +#[derive(Copy, Clone, PartialEq, RuntimeDebug)] +pub struct SubmitParachainHeadsInfo { + pub at_relay_block_number: RelayBlockNumber, + pub para_id: ParaId, + pub para_head_hash: ParaHash, +} + +/// Helper struct that provides methods for working with the `SubmitParachainHeads` call. +pub struct SubmitParachainHeadsHelper, I: 'static> { + pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, +} + +impl, I: 'static> SubmitParachainHeadsHelper { + /// Check if the para head provided by the `SubmitParachainHeads` is better than the best one + /// we know. + pub fn is_obsolete(update: &SubmitParachainHeadsInfo) -> bool { + let stored_best_head = match crate::ParasInfo::::get(update.para_id) { + Some(stored_best_head) => stored_best_head, + None => return false, + }; + + if stored_best_head.best_head_hash.at_relay_block_number >= update.at_relay_block_number { + log::trace!( + target: crate::LOG_TARGET, + "The parachain head can't be updated. The parachain head for {:?} \ + was already updated at better relay chain block {} >= {}.", + update.para_id, + stored_best_head.best_head_hash.at_relay_block_number, + update.at_relay_block_number + ); + return true + } + + if stored_best_head.best_head_hash.head_hash == update.para_head_hash { + log::trace!( + target: crate::LOG_TARGET, + "The parachain head can't be updated. The parachain head hash for {:?} \ + was already updated to {} at block {} < {}.", + update.para_id, + update.para_head_hash, + stored_best_head.best_head_hash.at_relay_block_number, + update.at_relay_block_number + ); + return true + } + + false + } + + /// Check if the `SubmitParachainHeads` was successfully executed. + pub fn was_successful(update: &SubmitParachainHeadsInfo) -> bool { + match crate::ParasInfo::::get(update.para_id) { + Some(stored_best_head) => + stored_best_head.best_head_hash == + BestParaHeadHash { + at_relay_block_number: update.at_relay_block_number, + head_hash: update.para_head_hash, + }, + None => false, + } + } +} + +/// Trait representing a call that is a sub type of this pallet's call. +pub trait CallSubType, I: 'static>: + IsSubType, T>> +{ + /// Create a new instance of `SubmitParachainHeadsInfo` from a `SubmitParachainHeads` call with + /// one single parachain entry. + fn one_entry_submit_parachain_heads_info(&self) -> Option { + if let Some(crate::Call::::submit_parachain_heads { + ref at_relay_block, + ref parachains, + .. + }) = self.is_sub_type() + { + if let &[(para_id, para_head_hash)] = parachains.as_slice() { + return Some(SubmitParachainHeadsInfo { + at_relay_block_number: at_relay_block.0, + para_id, + para_head_hash, + }) + } + } + + None + } + + /// Create a new instance of `SubmitParachainHeadsInfo` from a `SubmitParachainHeads` call with + /// one single parachain entry, if the entry is for the provided parachain id. + fn submit_parachain_heads_info_for(&self, para_id: u32) -> Option { + self.one_entry_submit_parachain_heads_info() + .filter(|update| update.para_id.0 == para_id) + } + + /// Validate parachain heads in order to avoid "mining" transactions that provide + /// outdated bridged parachain heads. Without this validation, even honest relayers + /// may lose their funds if there are multiple relays running and submitting the + /// same information. + /// + /// This validation only works with transactions that are updating single parachain + /// head. We can't use unbounded validation - it may take too long and either break + /// block production, or "eat" significant portion of block production time literally + /// for nothing. In addition, the single-parachain-head-per-transaction is how the + /// pallet will be used in our environment. + fn check_obsolete_submit_parachain_heads(&self) -> TransactionValidity + where + Self: Sized, + { + let update = match self.one_entry_submit_parachain_heads_info() { + Some(update) => update, + None => return Ok(ValidTransaction::default()), + }; + + if SubmitParachainHeadsHelper::::is_obsolete(&update) { + return InvalidTransaction::Stale.into() + } + + Ok(ValidTransaction::default()) + } +} + +impl CallSubType for T::RuntimeCall +where + T: Config, + T::RuntimeCall: IsSubType, T>>, +{ +} + +#[cfg(test)] +mod tests { + use crate::{ + mock::{run_test, RuntimeCall, TestRuntime}, + CallSubType, ParaInfo, ParasInfo, RelayBlockNumber, + }; + use bp_parachains::BestParaHeadHash; + use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; + + fn validate_submit_parachain_heads( + num: RelayBlockNumber, + parachains: Vec<(ParaId, ParaHash)>, + ) -> bool { + RuntimeCall::Parachains(crate::Call::::submit_parachain_heads { + at_relay_block: (num, Default::default()), + parachains, + parachain_heads_proof: ParaHeadsProof(Vec::new()), + }) + .check_obsolete_submit_parachain_heads() + .is_ok() + } + + fn sync_to_relay_header_10() { + ParasInfo::::insert( + ParaId(1), + ParaInfo { + best_head_hash: BestParaHeadHash { + at_relay_block_number: 10, + head_hash: [1u8; 32].into(), + }, + next_imported_hash_position: 0, + }, + ); + } + + #[test] + fn extension_rejects_header_from_the_obsolete_relay_block() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#5 => tx is + // rejected + sync_to_relay_header_10(); + assert!(!validate_submit_parachain_heads(5, vec![(ParaId(1), [1u8; 32].into())])); + }); + } + + #[test] + fn extension_rejects_header_from_the_same_relay_block() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#10 => tx is + // rejected + sync_to_relay_header_10(); + assert!(!validate_submit_parachain_heads(10, vec![(ParaId(1), [1u8; 32].into())])); + }); + } + + #[test] + fn extension_rejects_header_from_new_relay_block_with_same_hash() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#10 => tx is + // rejected + sync_to_relay_header_10(); + assert!(!validate_submit_parachain_heads(20, vec![(ParaId(1), [1u8; 32].into())])); + }); + } + + #[test] + fn extension_accepts_new_header() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#15 => tx is + // accepted + sync_to_relay_header_10(); + assert!(validate_submit_parachain_heads(15, vec![(ParaId(1), [2u8; 32].into())])); + }); + } + + #[test] + fn extension_accepts_if_more_than_one_parachain_is_submitted() { + run_test(|| { + // when current best finalized is #10 and we're trying to import header#5, but another + // parachain head is also supplied => tx is accepted + sync_to_relay_header_10(); + assert!(validate_submit_parachain_heads( + 5, + vec![(ParaId(1), [1u8; 32].into()), (ParaId(2), [1u8; 32].into())] + )); + }); + } +} diff --git a/modules/parachains/src/extension.rs b/modules/parachains/src/extension.rs deleted file mode 100644 index 5c2f54257ff8c..0000000000000 --- a/modules/parachains/src/extension.rs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 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 . - -use crate::{Config, Pallet, RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use bp_runtime::FilterCall; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; -use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}; - -/// Validate parachain heads in order to avoid "mining" transactions that provide -/// outdated bridged parachain heads. Without this validation, even honest relayers -/// may lose their funds if there are multiple relays running and submitting the -/// same information. -/// -/// This validation only works with transactions that are updating single parachain -/// head. We can't use unbounded validation - it may take too long and either break -/// block production, or "eat" significant portion of block production time literally -/// for nothing. In addition, the single-parachain-head-per-transaction is how the -/// pallet will be used in our environment. -impl< - Call: IsSubType, T>>, - T: frame_system::Config + Config, - I: 'static, - > FilterCall for Pallet -where - >::BridgedChain: - bp_runtime::Chain< - BlockNumber = RelayBlockNumber, - Hash = RelayBlockHash, - Hasher = RelayBlockHasher, - >, -{ - fn validate(call: &Call) -> TransactionValidity { - let (updated_at_relay_block_number, parachains) = match call.is_sub_type() { - Some(crate::Call::::submit_parachain_heads { - ref at_relay_block, - ref parachains, - .. - }) => (at_relay_block.0, parachains), - _ => return Ok(ValidTransaction::default()), - }; - let (parachain, parachain_head_hash) = match parachains.as_slice() { - &[(parachain, parachain_head_hash)] => (parachain, parachain_head_hash), - _ => return Ok(ValidTransaction::default()), - }; - - let maybe_stored_best_head = crate::ParasInfo::::get(parachain); - let is_valid = Self::validate_updated_parachain_head( - parachain, - &maybe_stored_best_head, - updated_at_relay_block_number, - parachain_head_hash, - "Rejecting obsolete parachain-head transaction", - ); - - if is_valid { - Ok(ValidTransaction::default()) - } else { - InvalidTransaction::Stale.into() - } - } -} - -#[cfg(test)] -mod tests { - use crate::{ - extension::FilterCall, - mock::{run_test, RuntimeCall, TestRuntime}, - ParaInfo, ParasInfo, RelayBlockNumber, - }; - use bp_parachains::BestParaHeadHash; - use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; - - fn validate_submit_parachain_heads( - num: RelayBlockNumber, - parachains: Vec<(ParaId, ParaHash)>, - ) -> bool { - crate::Pallet::::validate(&RuntimeCall::Parachains(crate::Call::< - TestRuntime, - (), - >::submit_parachain_heads { - at_relay_block: (num, Default::default()), - parachains, - parachain_heads_proof: ParaHeadsProof(Vec::new()), - })) - .is_ok() - } - - fn sync_to_relay_header_10() { - ParasInfo::::insert( - ParaId(1), - ParaInfo { - best_head_hash: BestParaHeadHash { - at_relay_block_number: 10, - head_hash: [1u8; 32].into(), - }, - next_imported_hash_position: 0, - }, - ); - } - - #[test] - fn extension_rejects_header_from_the_obsolete_relay_block() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#5 => tx is - // rejected - sync_to_relay_header_10(); - assert!(!validate_submit_parachain_heads(5, vec![(ParaId(1), [1u8; 32].into())])); - }); - } - - #[test] - fn extension_rejects_header_from_the_same_relay_block() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#10 => tx is - // rejected - sync_to_relay_header_10(); - assert!(!validate_submit_parachain_heads(10, vec![(ParaId(1), [1u8; 32].into())])); - }); - } - - #[test] - fn extension_rejects_header_from_new_relay_block_with_same_hash() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#10 => tx is - // rejected - sync_to_relay_header_10(); - assert!(!validate_submit_parachain_heads(20, vec![(ParaId(1), [1u8; 32].into())])); - }); - } - - #[test] - fn extension_accepts_new_header() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#15 => tx is - // accepted - sync_to_relay_header_10(); - assert!(validate_submit_parachain_heads(15, vec![(ParaId(1), [2u8; 32].into())])); - }); - } - - #[test] - fn extension_accepts_if_more_than_one_parachain_is_submitted() { - run_test(|| { - // when current best finalized is #10 and we're trying to import header#5, but another - // parachain head is also supplied => tx is accepted - sync_to_relay_header_10(); - assert!(validate_submit_parachain_heads( - 5, - vec![(ParaId(1), [1u8; 32].into()), (ParaId(2), [1u8; 32].into())] - )); - }); - } -} diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 1f060e675cb5d..6875a3690f6af 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -41,6 +41,7 @@ use bp_runtime::HeaderOf; use codec::Encode; // Re-export in crate namespace for `construct_runtime!`. +pub use call_ext::*; pub use pallet::*; pub mod weights; @@ -49,7 +50,7 @@ pub mod weights_ext; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; -mod extension; +mod call_ext; #[cfg(test)] mod mock; @@ -136,10 +137,30 @@ pub mod pallet { BridgeModule(bp_runtime::OwnedBridgeModuleError), } + /// Convenience trait for defining `BridgedChain` bounds. + pub trait BoundedBridgeGrandpaConfig: + pallet_bridge_grandpa::Config + { + type BridgedRelayChain: Chain< + BlockNumber = RelayBlockNumber, + Hash = RelayBlockHash, + Hasher = RelayBlockHasher, + >; + } + + impl BoundedBridgeGrandpaConfig for T + where + T: pallet_bridge_grandpa::Config, + T::BridgedChain: + Chain, + { + type BridgedRelayChain = T::BridgedChain; + } + #[pallet::config] #[pallet::disable_frame_system_supertrait_check] pub trait Config: - pallet_bridge_grandpa::Config + BoundedBridgeGrandpaConfig { /// The overarching event type. type RuntimeEvent: From> @@ -267,15 +288,7 @@ pub mod pallet { } #[pallet::call] - impl, I: 'static> Pallet - where - >::BridgedChain: - bp_runtime::Chain< - BlockNumber = RelayBlockNumber, - Hash = RelayBlockHash, - Hasher = RelayBlockHasher, - >, - { + impl, I: 'static> Pallet { /// Submit proof of one or several parachain heads. /// /// The proof is supposed to be proof of some `Heads` entries from the @@ -483,89 +496,38 @@ pub mod pallet { storage.read_and_decode_value(parachain_head_key.0.as_ref()) } - /// Check if para head has been already updated at better relay chain block. - /// Without this check, we may import heads in random order. - /// - /// Returns `true` if the pallet is ready to import given parachain head. - /// Returns `false` if the pallet already knows the same or better parachain head. - #[must_use] - pub fn validate_updated_parachain_head( - parachain: ParaId, - maybe_stored_best_head: &Option, - updated_at_relay_block_number: RelayBlockNumber, - updated_head_hash: ParaHash, - err_log_prefix: &str, - ) -> bool { - let stored_best_head = match maybe_stored_best_head { - Some(stored_best_head) => stored_best_head, - None => return true, - }; - - if stored_best_head.best_head_hash.at_relay_block_number >= - updated_at_relay_block_number - { - log::trace!( - target: LOG_TARGET, - "{}. The parachain head for {:?} was already updated at better relay chain block {} >= {}.", - err_log_prefix, - parachain, - stored_best_head.best_head_hash.at_relay_block_number, - updated_at_relay_block_number - ); - return false - } - - if stored_best_head.best_head_hash.head_hash == updated_head_hash { - log::trace!( - target: LOG_TARGET, - "{}. The parachain head hash for {:?} was already updated to {} at block {} < {}.", - err_log_prefix, - parachain, - updated_head_hash, - stored_best_head.best_head_hash.at_relay_block_number, - updated_at_relay_block_number - ); - return false - } - - true - } - /// Try to update parachain head. pub(super) fn update_parachain_head( parachain: ParaId, stored_best_head: Option, - updated_at_relay_block_number: RelayBlockNumber, - updated_head_data: ParaStoredHeaderData, - updated_head_hash: ParaHash, + new_at_relay_block_number: RelayBlockNumber, + new_head_data: ParaStoredHeaderData, + new_head_hash: ParaHash, ) -> Result { // check if head has been already updated at better relay chain block. Without this // check, we may import heads in random order - let err_log_prefix = "The parachain head can't be updated"; - let is_valid = Self::validate_updated_parachain_head( - parachain, - &stored_best_head, - updated_at_relay_block_number, - updated_head_hash, - err_log_prefix, - ); - if !is_valid { + let update = SubmitParachainHeadsInfo { + at_relay_block_number: new_at_relay_block_number, + para_id: parachain, + para_head_hash: new_head_hash, + }; + if SubmitParachainHeadsHelper::::is_obsolete(&update) { Self::deposit_event(Event::RejectedObsoleteParachainHead { parachain, - parachain_head_hash: updated_head_hash, + parachain_head_hash: new_head_hash, }); return Err(()) } // verify that the parachain head data size is <= `MaxParaHeadDataSize` let updated_head_data = - match StoredParaHeadDataOf::::try_from_inner(updated_head_data) { + match StoredParaHeadDataOf::::try_from_inner(new_head_data) { Ok(updated_head_data) => updated_head_data, Err(e) => { log::trace!( target: LOG_TARGET, - "{}. The parachain head data size for {:?} is {}. It exceeds maximal configured size {}.", - err_log_prefix, + "The parachain head can't be updated. The parachain head data size \ + for {:?} is {}. It exceeds maximal configured size {}.", parachain, e.value_size, e.maximal_size, @@ -573,7 +535,7 @@ pub mod pallet { Self::deposit_event(Event::RejectedLargeParachainHead { parachain, - parachain_head_hash: updated_head_hash, + parachain_head_hash: new_head_hash, parachain_head_size: e.value_size as _, }); @@ -589,8 +551,8 @@ pub mod pallet { ImportedParaHashes::::try_get(parachain, next_imported_hash_position); let updated_best_para_head = ParaInfo { best_head_hash: BestParaHeadHash { - at_relay_block_number: updated_at_relay_block_number, - head_hash: updated_head_hash, + at_relay_block_number: new_at_relay_block_number, + head_hash: new_head_hash, }, next_imported_hash_position: (next_imported_hash_position + 1) % T::HeadsToKeep::get(), @@ -598,14 +560,14 @@ pub mod pallet { ImportedParaHashes::::insert( parachain, next_imported_hash_position, - updated_head_hash, + new_head_hash, ); - ImportedParaHeads::::insert(parachain, updated_head_hash, updated_head_data); + ImportedParaHeads::::insert(parachain, new_head_hash, updated_head_data); log::trace!( target: LOG_TARGET, "Updated head of parachain {:?} to {}", parachain, - updated_head_hash, + new_head_hash, ); // remove old head @@ -621,7 +583,7 @@ pub mod pallet { } Self::deposit_event(Event::UpdatedParachainHead { parachain, - parachain_head_hash: updated_head_hash, + parachain_head_hash: new_head_hash, }); Ok(UpdateParachainHeadArtifacts { best_head: updated_best_para_head, prune_happened }) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 5eb1de2e3ac6d..83ffd238ab502 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -37,7 +37,6 @@ pub use chain::{ }; pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedSub, One}; -use sp_runtime::transaction_validity::TransactionValidity; pub use storage_proof::{ record_all_keys as record_all_trie_keys, Error as StorageProofError, ProofSize as StorageProofSize, StorageProofChecker, @@ -490,12 +489,6 @@ pub trait OwnedBridgeModule { } } -/// A trait for querying whether a runtime call is valid. -pub trait FilterCall { - /// Checks if a runtime call is valid. - fn validate(call: &Call) -> TransactionValidity; -} - /// All extra operations with weights that we need in bridges. pub trait WeightExtraOps { /// Checked division of individual components of two weights. From 1ead35c546be94dfa91f97edb0cf8e6850af90c4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 15 Feb 2023 17:47:38 +0300 Subject: [PATCH 0941/1210] Refund extra proof bytes in message delivery transaction (#1864) * refund extra proof bytes in message delivery transaction * Update modules/messages/src/lib.rs Co-authored-by: Adrian Catangiu * more tests --------- Co-authored-by: Adrian Catangiu --- modules/messages/src/inbound_lane.rs | 5 + modules/messages/src/lib.rs | 151 ++++++++++++++++++++++++++- 2 files changed, 151 insertions(+), 5 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 00c63b5d670a4..3f64ab765b5da 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -117,6 +117,11 @@ impl InboundLane { InboundLane { storage } } + /// Returns storage reference. + pub fn storage(&self) -> &S { + &self.storage + } + /// Receive state of the corresponding outbound lane. pub fn receive_state_update( &mut self, diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 70865cf17c514..cc9033d105812 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -303,6 +303,13 @@ pub mod pallet { for (lane_id, lane_data) in messages { let mut lane = inbound_lane::(lane_id); + // subtract extra storage proof bytes from the actual PoV size - there may be + // less unrewarded relayers than the maximal configured value + let lane_extra_proof_size_bytes = lane.storage().extra_proof_size_bytes(); + actual_weight = actual_weight.set_proof_size( + actual_weight.proof_size().saturating_sub(lane_extra_proof_size_bytes), + ); + if let Some(lane_state) = lane_data.lane_state { let updated_latest_confirmed_nonce = lane.receive_state_update(lane_state); if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { @@ -796,6 +803,25 @@ struct RuntimeInboundLaneStorage, I: 'static = ()> { _phantom: PhantomData, } +impl, I: 'static> RuntimeInboundLaneStorage { + /// Returns number of bytes that may be subtracted from the PoV component of + /// `receive_messages_proof` call, because the actual inbound lane state is smaller than the + /// maximal configured. + /// + /// Maximal inbound lane state set size is configured by the + /// `MaxUnrewardedRelayerEntriesAtInboundLane` constant from the pallet configuration. The PoV + /// of the call includes the maximal size of inbound lane state. If the actual size is smaller, + /// we may subtract extra bytes from this component. + pub fn extra_proof_size_bytes(&self) -> u64 { + let max_encoded_len = StoredInboundLaneData::::max_encoded_len(); + let relayers_count = self.data().relayers.len(); + let actual_encoded_len = + InboundLaneData::::encoded_size_hint(relayers_count) + .unwrap_or(usize::MAX); + max_encoded_len.saturating_sub(actual_encoded_len) as _ + } +} + impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage { type Relayer = T::InboundRelayer; @@ -906,9 +932,9 @@ mod tests { use crate::mock::{ message, message_payload, run_test, unrewarded_relayer, AccountId, DbWeight, RuntimeEvent as TestEvent, RuntimeOrigin, TestDeliveryConfirmationPayments, - TestDeliveryPayments, TestMessagesDeliveryProof, TestMessagesProof, TestRuntime, - MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, - TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, + TestDeliveryPayments, TestMessagesDeliveryProof, TestMessagesProof, TestRelayer, + TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, + TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, }; use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -1543,7 +1569,7 @@ mod tests { } #[test] - fn weight_refund_from_receive_messages_proof_works() { + fn ref_time_refund_from_receive_messages_proof_works() { run_test(|| { fn submit_with_unspent_weight( nonce: MessageNonce, @@ -1598,7 +1624,7 @@ mod tests { // when there's no unspent weight let (pre, post) = submit_with_unspent_weight(4, 0); - assert_eq!(post, pre); + assert_eq!(post.ref_time(), pre.ref_time()); // when dispatch is returning `unspent_weight < declared_weight` let (pre, post) = submit_with_unspent_weight(5, 1); @@ -1606,6 +1632,84 @@ mod tests { }); } + #[test] + fn proof_size_refund_from_receive_messages_proof_works() { + run_test(|| { + let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; + + // if there's maximal number of unrewarded relayer entries at the inbound lane, then + // `proof_size` is unchanged in post-dispatch weight + let proof: TestMessagesProof = Ok(vec![message(101, REGULAR_PAYLOAD)]).into(); + let messages_count = 1; + let pre_dispatch_weight = + ::WeightInfo::receive_messages_proof_weight( + &proof, + messages_count, + REGULAR_PAYLOAD.declared_weight, + ); + InboundLanes::::insert( + TEST_LANE_ID, + StoredInboundLaneData(InboundLaneData { + relayers: vec![ + UnrewardedRelayer { + relayer: 42, + messages: DeliveredMessages { begin: 0, end: 100 } + }; + max_entries + ] + .into_iter() + .collect(), + last_confirmed_nonce: 0, + }), + ); + let post_dispatch_weight = Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + proof.clone(), + messages_count, + REGULAR_PAYLOAD.declared_weight, + ) + .unwrap() + .actual_weight + .unwrap(); + assert_eq!(post_dispatch_weight.proof_size(), pre_dispatch_weight.proof_size()); + + // if count of unrewarded relayer entries is less than maximal, then some `proof_size` + // must be refunded + InboundLanes::::insert( + TEST_LANE_ID, + StoredInboundLaneData(InboundLaneData { + relayers: vec![ + UnrewardedRelayer { + relayer: 42, + messages: DeliveredMessages { begin: 0, end: 100 } + }; + max_entries - 1 + ] + .into_iter() + .collect(), + last_confirmed_nonce: 0, + }), + ); + let post_dispatch_weight = Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + proof, + messages_count, + REGULAR_PAYLOAD.declared_weight, + ) + .unwrap() + .actual_weight + .unwrap(); + assert!( + post_dispatch_weight.proof_size() < pre_dispatch_weight.proof_size(), + "Expected post-dispatch PoV {} to be less than pre-dispatch PoV {}", + post_dispatch_weight.proof_size(), + pre_dispatch_weight.proof_size(), + ); + }); + } + #[test] fn messages_delivered_callbacks_are_called() { run_test(|| { @@ -1978,6 +2082,43 @@ mod tests { MessagesOperatingMode::Basic(BasicOperatingMode::Halted) ); + #[test] + fn inbound_storage_extra_proof_size_bytes_works() { + fn relayer_entry() -> UnrewardedRelayer { + UnrewardedRelayer { relayer: 42u64, messages: DeliveredMessages { begin: 0, end: 100 } } + } + + fn storage(relayer_entries: usize) -> RuntimeInboundLaneStorage { + RuntimeInboundLaneStorage { + lane_id: Default::default(), + cached_data: RefCell::new(Some(InboundLaneData { + relayers: vec![relayer_entry(); relayer_entries].into_iter().collect(), + last_confirmed_nonce: 0, + })), + _phantom: Default::default(), + } + } + + let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; + + // when we have exactly `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers + assert_eq!(storage(max_entries).extra_proof_size_bytes(), 0); + + // when we have less than `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers + assert_eq!( + storage(max_entries - 1).extra_proof_size_bytes(), + relayer_entry().encode().len() as u64 + ); + assert_eq!( + storage(max_entries - 2).extra_proof_size_bytes(), + 2 * relayer_entry().encode().len() as u64 + ); + + // when we have more than `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers + // (shall not happen in practice) + assert_eq!(storage(max_entries + 1).extra_proof_size_bytes(), 0); + } + #[test] fn maybe_outbound_lanes_count_returns_correct_value() { assert_eq!( From 5279fc9978e3043cb2bfff7a4c8d4ed2851293a3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 15 Feb 2023 18:15:05 +0300 Subject: [PATCH 0942/1210] Reject storage proofs with unused nodes: begin (#1878) * reject storage proofs with unused nodes: begin * fix ignores_parachain_head_if_it_is_missing_from_storage_proof * message_proof_is_rejected_if_it_has_duplicate_trie_nodes && message_proof_is_rejected_if_it_has_unused_trie_nodes * proof_with_duplicate_items_is_rejected and proof_with_unused_items_is_rejected * clippy * fix benchmarks compilation * impl From for &'static str * fix review comments * added comment --- bin/runtime-common/src/messages.rs | 68 ++++++++-- .../src/messages_benchmarking.rs | 20 ++- bin/runtime-common/src/messages_generation.rs | 23 ++-- .../src/parachains_benchmarking.rs | 6 +- modules/grandpa/src/lib.rs | 2 +- modules/parachains/src/lib.rs | 34 +++-- primitives/header-chain/Cargo.toml | 2 - primitives/header-chain/src/lib.rs | 19 +-- primitives/polkadot-core/src/parachains.rs | 4 +- primitives/runtime/src/lib.rs | 2 +- primitives/runtime/src/storage_proof.rs | 123 +++++++++++++++--- 11 files changed, 217 insertions(+), 86 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 8c97198393def..ceedee12afabf 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -20,6 +20,8 @@ //! pallet is used to dispatch incoming messages. Message identified by a tuple //! of to elements - message lane id and message nonce. +pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider}; + use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ source_chain::{LaneMessageVerifier, TargetHeaderChain}, @@ -28,14 +30,15 @@ use bp_messages::{ }, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; -use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, Size, StorageProofChecker}; -pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider}; +use bp_runtime::{ + messages::MessageDispatchResult, Chain, ChainId, RawStorageProof, Size, StorageProofChecker, + StorageProofError, +}; use codec::{Decode, DecodeLimit, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; -use sp_trie::StorageProof; use xcm::latest::prelude::*; /// Bidirectional message bridge. @@ -97,9 +100,6 @@ pub type OriginOf = ::RuntimeOrigin; /// Type of call that is used on this chain. pub type CallOf = ::RuntimeCall; -/// Raw storage proof type (just raw trie nodes). -pub type RawStorageProof = Vec>; - /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -274,8 +274,8 @@ pub mod source { proof; B::BridgedHeaderChain::parse_finalized_storage_proof( bridged_header_hash, - StorageProof::new(storage_proof), - |storage| { + storage_proof, + |mut storage| { // Messages delivery proof is just proof of single storage key read => any error // is fatal. let storage_inbound_lane_data_key = @@ -290,6 +290,11 @@ pub mod source { let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) .map_err(|_| "Failed to decode inbound lane state from the proof")?; + // check that the storage proof doesn't have any untouched trie nodes + storage + .ensure_no_unused_nodes() + .map_err(|_| "Messages delivery proof has unused trie nodes")?; + Ok((lane, inbound_lane_data)) }, ) @@ -608,9 +613,9 @@ pub mod target { B::BridgedHeaderChain::parse_finalized_storage_proof( bridged_header_hash, - StorageProof::new(storage_proof), + storage_proof, |storage| { - let parser = + let mut parser = StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default() }; // receiving proofs where end < begin is ok (if proof includes outbound lane state) @@ -661,6 +666,12 @@ pub mod target { return Err(MessageProofError::Empty) } + // check that the storage proof doesn't have any untouched trie nodes + parser + .storage + .ensure_no_unused_nodes() + .map_err(MessageProofError::StorageProof)?; + // We only support single lane messages in this generated_schema let mut proved_messages = ProvedMessages::new(); proved_messages.insert(lane, proved_lane_messages); @@ -686,6 +697,8 @@ pub mod target { FailedToDecodeMessage, /// Failed to decode outbound lane data from the proof. FailedToDecodeOutboundLaneState, + /// Storage proof related error. + StorageProof(StorageProofError), } impl From for &'static str { @@ -700,6 +713,7 @@ pub mod target { "Failed to decode message from the proof", MessageProofError::FailedToDecodeOutboundLaneState => "Failed to decode outbound lane data from the proof", + MessageProofError::StorageProof(_) => "Invalid storage proof", } } } @@ -710,7 +724,7 @@ pub mod target { } impl StorageProofCheckerAdapter { - fn read_raw_outbound_lane_data(&self, lane_id: &LaneId) -> Option> { + fn read_raw_outbound_lane_data(&mut self, lane_id: &LaneId) -> Option> { let storage_outbound_lane_data_key = bp_messages::storage_keys::outbound_lane_data_key( B::BRIDGED_MESSAGES_PALLET_NAME, lane_id, @@ -718,7 +732,7 @@ pub mod target { self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()? } - fn read_raw_message(&self, message_key: &MessageKey) -> Option> { + fn read_raw_message(&mut self, message_key: &MessageKey) -> Option> { let storage_message_key = bp_messages::storage_keys::message_key( B::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, @@ -928,7 +942,35 @@ mod tests { ); target::verify_messages_proof::(proof, 10) }), - Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageRootMismatch)), + Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageProof( + StorageProofError::StorageRootMismatch + ))), + ); + } + + #[test] + fn message_proof_is_rejected_if_it_has_duplicate_trie_nodes() { + assert_eq!( + using_messages_proof(10, None, encode_all_messages, encode_lane_data, |mut proof| { + let node = proof.storage_proof.pop().unwrap(); + proof.storage_proof.push(node.clone()); + proof.storage_proof.push(node); + target::verify_messages_proof::(proof, 10) + },), + Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageProof( + StorageProofError::DuplicateNodesInProof + ))), + ); + } + + #[test] + fn message_proof_is_rejected_if_it_has_unused_trie_nodes() { + assert_eq!( + using_messages_proof(10, None, encode_all_messages, encode_lane_data, |mut proof| { + proof.storage_proof.push(vec![42]); + target::verify_messages_proof::(proof, 10) + },), + Err(target::MessageProofError::StorageProof(StorageProofError::UnusedNodesInTheProof)), ); } diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index e7ca26d952ea8..1588c77633e23 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -22,7 +22,7 @@ use crate::{ messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof, ThisChain, + AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, ThisChain, }, messages_generation::{ encode_all_messages, encode_lane_data, grow_trie, prepare_messages_storage_proof, @@ -31,13 +31,15 @@ use crate::{ use bp_messages::storage_keys; use bp_polkadot_core::parachains::ParaHash; -use bp_runtime::{record_all_trie_keys, Chain, Parachain, StorageProofSize, UnderlyingChainOf}; +use bp_runtime::{ + record_all_trie_keys, Chain, Parachain, RawStorageProof, StorageProofSize, UnderlyingChainOf, +}; use codec::Encode; use frame_support::weights::Weight; use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; use sp_runtime::traits::{Header, Zero}; use sp_std::prelude::*; -use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; /// Prepare proof of messages for the `receive_messages_proof` call. /// @@ -209,15 +211,9 @@ where root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>>>::new(); - record_all_trie_keys::>>, _>( - &mdb, - &root, - &mut proof_recorder, - ) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + let storage_proof = record_all_trie_keys::>>, _>(&mdb, &root) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); (root, storage_proof) } diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs index 560033d122a84..aec97c2280047 100644 --- a/bin/runtime-common/src/messages_generation.rs +++ b/bin/runtime-common/src/messages_generation.rs @@ -18,16 +18,16 @@ #![cfg(any(feature = "runtime-benchmarks", test))] -use crate::messages::{BridgedChain, HashOf, HasherOf, MessageBridge, RawStorageProof}; +use crate::messages::{BridgedChain, HashOf, HasherOf, MessageBridge}; use bp_messages::{ storage_keys, LaneId, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; -use bp_runtime::{record_all_trie_keys, StorageProofSize}; +use bp_runtime::{record_all_trie_keys, RawStorageProof, StorageProofSize}; use codec::Encode; use sp_core::Hasher; use sp_std::{ops::RangeInclusive, prelude::*}; -use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; /// Simple and correct message data encode function. pub(crate) fn encode_all_messages(_: MessageNonce, m: &MessagePayload) -> Option> { @@ -97,15 +97,9 @@ where root = grow_trie(root, &mut mdb, size); // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>>>::new(); - record_all_trie_keys::>>, _>( - &mdb, - &root, - &mut proof_recorder, - ) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); + let storage_proof = record_all_trie_keys::>>, _>(&mdb, &root) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); (root, storage_proof) } @@ -125,11 +119,10 @@ pub fn grow_trie( let mut key_index = 0; loop { // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(mdb, &root, &mut proof_recorder) + let storage_proof = record_all_trie_keys::, _>(mdb, &root) .map_err(|_| "record_all_trie_keys has failed") .expect("record_all_trie_keys should not fail in benchmarks"); - let size: usize = proof_recorder.drain().into_iter().map(|n| n.data.len()).sum(); + let size: usize = storage_proof.iter().map(|n| n.len()).sum(); if size > minimal_trie_size as _ { return root } diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index fcd32ea28b86e..e549e4f79b9f3 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -29,7 +29,7 @@ use codec::Encode; use frame_support::traits::Get; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use sp_std::prelude::*; -use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; /// Prepare proof of messages for the `receive_messages_proof` call. /// @@ -72,11 +72,9 @@ where state_root = grow_trie(state_root, &mut mdb, size); // generate heads storage proof - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(&mdb, &state_root, &mut proof_recorder) + let proof = record_all_trie_keys::, _>(&mdb, &state_root) .map_err(|_| "record_all_trie_keys has failed") .expect("record_all_trie_keys should not fail in benchmarks"); - let proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); let (relay_block_number, relay_block_hash) = insert_header_to_grandpa_pallet::(state_root); diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index c2b7943479588..fca0cb1b758c7 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -1050,7 +1050,7 @@ mod tests { assert_noop!( Pallet::::parse_finalized_storage_proof( Default::default(), - sp_trie::StorageProof::new(vec![]), + vec![], |_| (), ), bp_header_chain::HeaderChainError::UnknownHeader, diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 6875a3690f6af..b9bbaac7ca3d4 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -330,10 +330,10 @@ pub mod pallet { pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( relay_block_hash, - sp_trie::StorageProof::new(parachain_heads_proof.0), - move |storage| { + parachain_heads_proof.0, + move |mut storage| { for (parachain, parachain_head_hash) in parachains { - let parachain_head = match Pallet::::read_parachain_head(&storage, parachain) { + let parachain_head = match Pallet::::read_parachain_head(&mut storage, parachain) { Ok(Some(parachain_head)) => parachain_head, Ok(None) => { log::trace!( @@ -381,7 +381,10 @@ pub mod pallet { } // convert from parachain head into stored parachain head data - let parachain_head_data = match T::ParaStoredHeaderDataBuilder::try_build(parachain, ¶chain_head) { + let parachain_head_data = match T::ParaStoredHeaderDataBuilder::try_build( + parachain, + ¶chain_head, + ) { Some(parachain_head_data) => parachain_head_data, None => { log::trace!( @@ -418,9 +421,20 @@ pub mod pallet { .saturating_sub(WeightInfoOf::::parachain_head_pruning_weight(T::DbWeight::get())); } } + + // even though we may have accepted some parachain heads, we can't allow relayers to submit + // proof with unused trie nodes + // => treat this as an error + // + // (we can throw error here, because now all our calls are transactional) + storage.ensure_no_unused_nodes() }, ) - .map_err(|_| Error::::InvalidStorageProof)?; + .and_then(|r| r.map_err(bp_header_chain::HeaderChainError::StorageProof)) + .map_err(|e| { + log::trace!(target: LOG_TARGET, "Parachain heads storage proof is invalid: {:?}", e); + Error::::InvalidStorageProof + })?; Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } @@ -488,7 +502,7 @@ pub mod pallet { /// Read parachain head from storage proof. fn read_parachain_head( - storage: &bp_runtime::StorageProofChecker, + storage: &mut bp_runtime::StorageProofChecker, parachain: ParaId, ) -> Result, StorageProofError> { let parachain_head_key = @@ -705,7 +719,7 @@ mod tests { use frame_system::{EventRecord, Pallet as System, Phase}; use sp_core::Hasher; use sp_runtime::{traits::Header as HeaderT, DispatchError}; - use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, Recorder, TrieMut}; + use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type WeightInfo = ::WeightInfo; @@ -759,11 +773,9 @@ mod tests { } // generate storage proof to be delivered to This chain - let mut proof_recorder = Recorder::>::new(); - record_all_trie_keys::, _>(&mdb, &root, &mut proof_recorder) + let storage_proof = record_all_trie_keys::, _>(&mdb, &root) .map_err(|_| "record_all_trie_keys has failed") .expect("record_all_trie_keys should not fail in benchmarks"); - let storage_proof = proof_recorder.drain().into_iter().map(|n| n.data.to_vec()).collect(); (root, ParaHeadsProof(storage_proof), parachains) } @@ -1447,7 +1459,7 @@ mod tests { #[test] fn ignores_parachain_head_if_it_is_missing_from_storage_proof() { - let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let (state_root, proof, _) = prepare_parachain_heads_proof(vec![]); let parachains = vec![(ParaId(2), Default::default())]; run_test(|| { initialize(state_root); diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 3b7ea58cb96a7..be87cce460e38 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -23,7 +23,6 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", sp-finality-grandpa = { 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-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] bp-test-utils = { path = "../test-utils" } @@ -43,5 +42,4 @@ std = [ "sp-finality-grandpa/std", "sp-runtime/std", "sp-std/std", - "sp-trie/std", ] diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 14e9395c03c09..49d1ae894068f 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,35 +19,36 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_runtime::{BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, StorageProofChecker}; +use bp_runtime::{ + BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker, + StorageProofError, +}; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; -use frame_support::PalletError; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; use sp_std::boxed::Box; -use sp_trie::StorageProof; pub mod justification; pub mod storage_keys; /// Header chain error. -#[derive(Clone, Copy, Decode, Encode, Eq, PalletError, PartialEq, RuntimeDebug, TypeInfo)] +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] pub enum HeaderChainError { /// Header with given hash is missing from the chain. UnknownHeader, - /// The storage proof doesn't contains storage root. - StorageRootMismatch, + /// Storage proof related error. + StorageProof(StorageProofError), } impl From for &'static str { fn from(err: HeaderChainError) -> &'static str { match err { HeaderChainError::UnknownHeader => "UnknownHeader", - HeaderChainError::StorageRootMismatch => "StorageRootMismatch", + HeaderChainError::StorageProof(e) => e.into(), } } } @@ -83,13 +84,13 @@ pub trait HeaderChain { /// Parse storage proof using finalized header. fn parse_finalized_storage_proof( header_hash: HashOf, - storage_proof: StorageProof, + storage_proof: RawStorageProof, parse: impl FnOnce(StorageProofChecker>) -> R, ) -> Result { let state_root = Self::finalized_header_state_root(header_hash) .ok_or(HeaderChainError::UnknownHeader)?; let storage_proof_checker = bp_runtime::StorageProofChecker::new(state_root, storage_proof) - .map_err(|_| HeaderChainError::StorageRootMismatch)?; + .map_err(HeaderChainError::StorageProof)?; Ok(parse(storage_proof_checker)) } diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index e8f68dd2a9a16..0b410dff49f75 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -22,7 +22,7 @@ //! chains. Having pallets that are referencing polkadot, would mean that there may //! be two versions of polkadot crates included in the runtime. Which is bad. -use bp_runtime::Size; +use bp_runtime::{RawStorageProof, Size}; use codec::{CompactAs, Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; @@ -88,7 +88,7 @@ pub type ParaHasher = crate::Hasher; /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] -pub struct ParaHeadsProof(pub Vec>); +pub struct ParaHeadsProof(pub RawStorageProof); impl Size for ParaHeadsProof { fn size(&self) -> u32 { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 83ffd238ab502..75151ccb72372 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -39,7 +39,7 @@ pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedSub, One}; pub use storage_proof::{ record_all_keys as record_all_trie_keys, Error as StorageProofError, - ProofSize as StorageProofSize, StorageProofChecker, + ProofSize as StorageProofSize, RawStorageProof, StorageProofChecker, }; pub use storage_types::BoundedStorageValue; diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index e1465d2fa1657..133a51ce6e7f5 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -16,15 +16,18 @@ //! Logic for checking Substrate storage proofs. -use codec::Decode; +use codec::{Decode, Encode}; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; -use sp_std::{boxed::Box, vec::Vec}; +use sp_std::{boxed::Box, collections::btree_set::BTreeSet, vec::Vec}; use sp_trie::{ read_trie_value, LayoutV1, MemoryDB, Recorder, StorageProof, Trie, TrieConfiguration, TrieDBBuilder, TrieError, TrieHash, }; +/// Raw storage proof type (just raw trie nodes). +pub type RawStorageProof = Vec>; + /// Storage proof size requirements. /// /// This is currently used by benchmarks when generating storage proofs. @@ -48,8 +51,10 @@ pub struct StorageProofChecker where H: Hasher, { + proof_nodes_count: usize, root: H::Out, db: MemoryDB, + recorder: Recorder>, } impl StorageProofChecker @@ -59,28 +64,59 @@ where /// 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 { + pub fn new(root: H::Out, proof: RawStorageProof) -> Result { + // 1. we don't want extra items in the storage proof + // 2. `StorageProof` is storing all trie nodes in the `BTreeSet` + // + // => someone could simply add duplicate items to the proof and we won't be + // able to detect that by just using `StorageProof` + // + // => let's check it when we are converting our "raw proof" into `StorageProof` + let proof_nodes_count = proof.len(); + let proof = StorageProof::new(proof); + if proof_nodes_count != proof.iter_nodes().count() { + return Err(Error::DuplicateNodesInProof) + } + let db = proof.into_memory_db(); if !db.contains(&root, EMPTY_PREFIX) { return Err(Error::StorageRootMismatch) } - let checker = StorageProofChecker { root, db }; + let recorder = Recorder::default(); + let checker = StorageProofChecker { proof_nodes_count, root, db, recorder }; Ok(checker) } + /// Returns error if the proof has some nodes that are left intact by previous `read_value` + /// calls. + pub fn ensure_no_unused_nodes(mut self) -> Result<(), Error> { + let visited_nodes = self + .recorder + .drain() + .into_iter() + .map(|record| record.data) + .collect::>(); + let visited_nodes_count = visited_nodes.len(); + if self.proof_nodes_count == visited_nodes_count { + Ok(()) + } else { + Err(Error::UnusedNodesInTheProof) + } + } + /// Reads a value from the available subset of storage. If the value cannot be read due to an /// incomplete or otherwise invalid proof, this function returns an error. - pub fn read_value(&self, key: &[u8]) -> Result>, Error> { + pub fn read_value(&mut self, key: &[u8]) -> Result>, Error> { // LayoutV1 or LayoutV0 is identical for proof that only read values. - read_trie_value::, _>(&self.db, &self.root, key, None, None) + read_trie_value::, _>(&self.db, &self.root, key, Some(&mut self.recorder), None) .map_err(|_| Error::StorageValueUnavailable) } /// Reads and decodes a value from the available subset of storage. If the value cannot be read /// due to an incomplete or otherwise invalid proof, this function returns an error. If value is /// read, but decoding fails, this function returns an error. - pub fn read_and_decode_value(&self, key: &[u8]) -> Result, Error> { + pub fn read_and_decode_value(&mut self, key: &[u8]) -> Result, Error> { self.read_value(key).and_then(|v| { v.map(|v| T::decode(&mut &v[..]).map_err(Error::StorageValueDecodeFailed)) .transpose() @@ -88,19 +124,39 @@ where } } -#[derive(Eq, RuntimeDebug, PartialEq)] +/// Storage proof related errors. +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] pub enum Error { + /// Duplicate trie nodes are found in the proof. + DuplicateNodesInProof, + /// Unused trie nodes are found in the proof. + UnusedNodesInTheProof, + /// Expected storage root is missing from the proof. StorageRootMismatch, + /// Unable to reach expected storage value using provided trie nodes. StorageValueUnavailable, + /// Failed to decode storage value. StorageValueDecodeFailed(codec::Error), } +impl From for &'static str { + fn from(err: Error) -> &'static str { + match err { + Error::DuplicateNodesInProof => "Storage proof contains duplicate nodes", + Error::UnusedNodesInTheProof => "Storage proof contains unused nodes", + Error::StorageRootMismatch => "Storage root is missing from the storage proof", + Error::StorageValueUnavailable => "Storage value is missing from the storage proof", + Error::StorageValueDecodeFailed(_) => + "Failed to decode storage value from the storage proof", + } + } +} + /// 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 codec::Encode; +pub fn craft_valid_storage_proof() -> (sp_core::H256, RawStorageProof) { use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; let state_version = sp_runtime::StateVersion::default(); @@ -121,25 +177,33 @@ pub fn craft_valid_storage_proof() -> (sp_core::H256, StorageProof) { let proof = prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key4"[..], &b"key22"[..]]).unwrap(); - (root, proof) + (root, proof.into_nodes().into_iter().collect()) } /// Record all keys for a given root. pub fn record_all_keys( db: &DB, root: &TrieHash, - recorder: &mut Recorder, -) -> Result<(), Box>> +) -> Result>> where DB: hash_db::HashDBRef, { - let trie = TrieDBBuilder::::new(db, root).with_recorder(recorder).build(); + let mut recorder = Recorder::::new(); + let trie = TrieDBBuilder::::new(db, root).with_recorder(&mut recorder).build(); for x in trie.iter()? { let (key, _) = x?; trie.get(&key)?; } - Ok(()) + // recorder may record the same trie node multiple times and we don't want duplicate nodes + // in our proofs => let's deduplicate it by collecting to the BTreeSet first + Ok(recorder + .drain() + .into_iter() + .map(|n| n.data.to_vec()) + .collect::>() + .into_iter() + .collect()) } #[cfg(test)] @@ -152,7 +216,7 @@ pub mod tests { let (root, proof) = craft_valid_storage_proof(); // check proof in runtime - let checker = + let mut checker = >::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()))); @@ -171,4 +235,31 @@ pub mod tests { Some(Error::StorageRootMismatch) ); } + + #[test] + fn proof_with_duplicate_items_is_rejected() { + let (root, mut proof) = craft_valid_storage_proof(); + proof.push(proof.first().unwrap().clone()); + + assert_eq!( + StorageProofChecker::::new(root, proof).map(drop), + Err(Error::DuplicateNodesInProof), + ); + } + + #[test] + fn proof_with_unused_items_is_rejected() { + let (root, proof) = craft_valid_storage_proof(); + + let mut checker = + StorageProofChecker::::new(root, proof.clone()).unwrap(); + checker.read_value(b"key1").unwrap(); + checker.read_value(b"key2").unwrap(); + checker.read_value(b"key4").unwrap(); + checker.read_value(b"key22").unwrap(); + assert_eq!(checker.ensure_no_unused_nodes(), Ok(())); + + let checker = StorageProofChecker::::new(root, proof).unwrap(); + assert_eq!(checker.ensure_no_unused_nodes(), Err(Error::UnusedNodesInTheProof)); + } } From bf4ca417814b2b2c8489473100229a7b28f83eb5 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 16 Feb 2023 11:16:02 +0300 Subject: [PATCH 0943/1210] Fix clippy issues (#1884) * fix clippy issues * fix? * fix? * forget about extra_unused_type_parameters lint for now --- bin/millau/runtime/src/rialto_messages.rs | 1 - bin/rialto/runtime/src/millau_messages.rs | 1 - bin/runtime-common/src/integrity.rs | 8 +++----- modules/beefy/src/utils.rs | 4 ++-- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 62ad919d96cc7..919fac868996f 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -162,7 +162,6 @@ mod tests { RialtoGrandpaInstance, WithRialtoMessagesInstance, WithRialtoMessageBridge, - bp_millau::Millau, >(AssertCompleteBridgeConstants { this_chain_constants: AssertChainConstants { block_length: bp_millau::BlockLength::get(), diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 4774d871b788a..ff08c08029ae9 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -161,7 +161,6 @@ mod tests { MillauGrandpaInstance, WithMillauMessagesInstance, WithMillauMessageBridge, - bp_rialto::Rialto, >(AssertCompleteBridgeConstants { this_chain_constants: AssertChainConstants { block_length: bp_rialto::BlockLength::get(), diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 51fb50df7e104..5a2c796ee43b9 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -141,10 +141,9 @@ pub struct AssertChainConstants { /// /// 1) block weight limits are matching; /// 2) block size limits are matching. -pub fn assert_chain_constants(params: AssertChainConstants) +pub fn assert_chain_constants(params: AssertChainConstants) where R: frame_system::Config, - C: Chain, { // we don't check runtime version here, because in our case we'll be building relay from one // repo and runtime will live in another repo, along with outdated relay version. To avoid @@ -274,7 +273,7 @@ pub struct AssertCompleteBridgeConstants<'a> { /// All bridge-related constants tests for the complete standard messages bridge (i.e. with bridge /// GRANDPA and messages pallets deployed). -pub fn assert_complete_bridge_constants(params: AssertCompleteBridgeConstants) +pub fn assert_complete_bridge_constants(params: AssertCompleteBridgeConstants) where R: frame_system::Config + pallet_bridge_grandpa::Config @@ -282,9 +281,8 @@ where GI: 'static, MI: 'static, B: MessageBridge, - This: Chain, { - assert_chain_constants::(params.this_chain_constants); + assert_chain_constants::(params.this_chain_constants); assert_bridge_grandpa_pallet_constants::(); assert_bridge_messages_pallet_constants::(params.messages_pallet_constants); assert_bridge_pallet_names::(params.pallet_names); diff --git a/modules/beefy/src/utils.rs b/modules/beefy/src/utils.rs index 028e61e96b453..fac9a2c92e6c0 100644 --- a/modules/beefy/src/utils.rs +++ b/modules/beefy/src/utils.rs @@ -52,7 +52,7 @@ fn verify_authority_set, I: 'static>( /// /// We're using 'conservative' approach here, where signatures of `2/3+1` validators are /// required.. -pub(crate) fn signatures_required, I: 'static>(validators_len: usize) -> usize { +pub(crate) fn signatures_required(validators_len: usize) -> usize { validators_len - validators_len.saturating_sub(1) / 3 } @@ -67,7 +67,7 @@ fn verify_signatures, I: 'static>( // Ensure that the commitment was signed by enough authorities. let msg = commitment.commitment.encode(); - let mut missing_signatures = signatures_required::(authority_set.len()); + let mut missing_signatures = signatures_required(authority_set.len()); for (idx, (authority, maybe_sig)) in authority_set.validators().iter().zip(commitment.signatures.iter()).enumerate() { From f3f80e1c65acf9188ca8f4acfcf5a9c608cf4197 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 16 Feb 2023 15:20:45 +0300 Subject: [PATCH 0944/1210] ChainWithGrandpa in primitives (#1885) * ChainWithGrandpa in primitives * clippy ++ spelling * fix benchmarks comppilation --- bin/millau/runtime/src/lib.rs | 27 +++----------- bin/rialto-parachain/runtime/src/lib.rs | 14 +------- bin/rialto/runtime/src/lib.rs | 14 +------- bin/runtime-common/src/mock.rs | 11 ++++-- modules/grandpa/src/benchmarking.rs | 3 +- modules/grandpa/src/lib.rs | 14 +++----- modules/grandpa/src/mock.rs | 18 ++++++++-- modules/grandpa/src/storage_types.rs | 16 +++++++-- modules/parachains/src/mock.rs | 19 ++++++++-- primitives/chain-kusama/Cargo.toml | 4 +++ primitives/chain-kusama/src/lib.rs | 36 +++++++++++++++++-- primitives/chain-millau/Cargo.toml | 13 ++++--- primitives/chain-millau/src/lib.rs | 31 ++++++++++++++++ primitives/chain-polkadot/Cargo.toml | 5 +++ primitives/chain-polkadot/src/lib.rs | 36 +++++++++++++++++-- primitives/chain-rialto/Cargo.toml | 2 ++ primitives/chain-rialto/src/lib.rs | 31 ++++++++++++++++ primitives/chain-rococo/Cargo.toml | 6 +++- primitives/chain-rococo/src/lib.rs | 37 +++++++++++++++++-- primitives/chain-westend/Cargo.toml | 2 ++ primitives/chain-westend/src/lib.rs | 33 ++++++++++++++++- primitives/chain-wococo/Cargo.toml | 6 ++++ primitives/chain-wococo/src/lib.rs | 36 +++++++++++++++++-- primitives/header-chain/src/lib.rs | 47 ++++++++++++++++++++++++- primitives/polkadot-core/src/lib.rs | 22 ++++++++++++ relays/client-kusama/src/lib.rs | 6 +--- relays/client-millau/src/lib.rs | 10 ++---- relays/client-polkadot/src/lib.rs | 7 +--- relays/client-rialto/src/lib.rs | 10 ++---- relays/client-rococo/src/lib.rs | 8 +---- relays/client-substrate/src/chain.rs | 19 +++++++--- relays/client-westend/src/lib.rs | 9 +---- relays/client-wococo/src/lib.rs | 8 +---- 33 files changed, 421 insertions(+), 139 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8f82e645f9e02..5a18f8b12c039 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -387,21 +387,6 @@ impl pallet_bridge_relayers::Config for Runtime { type WeightInfo = (); } -parameter_types! { - /// Number of headers to keep. - /// - /// Assuming the worst case of every header being finalized, we will keep headers at least for a - /// day. - pub const HeadersToKeep: u32 = bp_rialto::DAYS; - /// Maximal number of authorities at Rialto. - pub const MaxAuthoritiesAtRialto: u32 = bp_rialto::MAX_AUTHORITIES_COUNT; -} - -parameter_types! { - /// Maximal number of authorities at Westend. - pub const MaxAuthoritiesAtWestend: u32 = bp_westend::MAX_AUTHORITIES_COUNT; -} - pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_rialto::Rialto; @@ -410,9 +395,7 @@ impl pallet_bridge_grandpa::Config for Runtime { // Note that once this is hit the pallet will essentially throttle incoming requests down to one // call per block. type MaxRequests = ConstU32<50>; - type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = MaxAuthoritiesAtRialto; - + type HeadersToKeep = ConstU32<{ bp_rialto::DAYS }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -420,9 +403,7 @@ pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_westend::Westend; type MaxRequests = ConstU32<50>; - type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = MaxAuthoritiesAtWestend; - + type HeadersToKeep = ConstU32<{ bp_westend::DAYS }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -521,7 +502,7 @@ impl pallet_bridge_parachains::Config for Runtime type ParasPalletName = RialtoParasPalletName; type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder; - type HeadsToKeep = HeadersToKeep; + type HeadsToKeep = ConstU32<1024>; type MaxParaHeadDataSize = MaxRialtoParaHeadDataSize; } @@ -534,7 +515,7 @@ impl pallet_bridge_parachains::Config for Runtime type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder; - type HeadsToKeep = HeadersToKeep; + type HeadsToKeep = ConstU32<1024>; type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index ba1aa05463b1c..5eeddf41e5247 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -525,17 +525,6 @@ impl pallet_bridge_relayers::Config for Runtime { type WeightInfo = (); } -parameter_types! { - /// Number of headers to keep. - /// - /// Assuming the worst case of every header being finalized, we will keep headers at least for a - /// day. - pub const HeadersToKeep: u32 = bp_millau::DAYS as u32; - - /// Maximal number of authorities at Millau. - pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; -} - pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; @@ -544,8 +533,7 @@ impl pallet_bridge_grandpa::Config for Runtime { /// Note that once this is hit the pallet will essentially throttle incoming requests down to /// one call per block. type MaxRequests = ConstU32<50>; - type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; + type HeadersToKeep = ConstU32<{ bp_millau::DAYS as u32 }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index cb3b6d604866b..3959dbea1aae3 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -397,17 +397,6 @@ impl pallet_bridge_relayers::Config for Runtime { type WeightInfo = (); } -parameter_types! { - /// Number of headers to keep. - /// - /// Assuming the worst case of every header being finalized, we will keep headers at least for a - /// day. - pub const HeadersToKeep: u32 = bp_rialto::DAYS; - - /// Maximal number of authorities at Millau. - pub const MaxAuthoritiesAtMillau: u32 = bp_millau::MAX_AUTHORITIES_COUNT; -} - pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type BridgedChain = bp_millau::Millau; @@ -416,8 +405,7 @@ impl pallet_bridge_grandpa::Config for Runtime { /// Note that once this is hit the pallet will essentially throttle incoming requests down to /// one call per block. type MaxRequests = ConstU32<50>; - type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = MaxAuthoritiesAtMillau; + type HeadersToKeep = ConstU32<{ bp_millau::DAYS as u32 }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 51b03447c6383..a5ae9131f031f 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -32,7 +32,7 @@ use crate::messages::{ BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages, }; -use bp_header_chain::HeaderChain; +use bp_header_chain::{ChainWithGrandpa, HeaderChain}; use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; @@ -195,7 +195,6 @@ impl pallet_bridge_grandpa::Config for TestRuntime { type BridgedChain = BridgedUnderlyingChain; type MaxRequests = ConstU32<50>; type HeadersToKeep = ConstU32<8>; - type MaxBridgedAuthorities = ConstU32<1024>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -372,6 +371,14 @@ impl Chain for BridgedUnderlyingChain { } } +impl ChainWithGrandpa for BridgedUnderlyingChain { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; + const MAX_AUTHORITIES_COUNT: u32 = 16; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const MAX_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; +} + impl Chain for BridgedUnderlyingParachain { type BlockNumber = BridgedChainBlockNumber; type Hash = BridgedChainHash; diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 710a7e0952c61..337943bee4edc 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -47,7 +47,6 @@ use bp_test_utils::{ TEST_GRANDPA_SET_ID, }; use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; -use frame_support::traits::Get; use frame_system::RawOrigin; use sp_finality_grandpa::AuthorityId; use sp_runtime::traits::{One, Zero}; @@ -68,7 +67,7 @@ const MAX_VOTE_ANCESTRIES_RANGE_END: u32 = // the same with validators - if there are too much validators, let's run benchmarks on subrange fn validator_set_range_end, I: 'static>() -> u32 { - let max_bridged_authorities = T::MaxBridgedAuthorities::get(); + let max_bridged_authorities = T::BridgedChain::MAX_AUTHORITIES_COUNT; if max_bridged_authorities > 128 { sp_std::cmp::max(128, max_bridged_authorities / 5) } else { diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index fca0cb1b758c7..197726dd47a5e 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -39,10 +39,10 @@ use storage_types::StoredAuthoritySet; use bp_header_chain::{ - justification::GrandpaJustification, HeaderChain, InitializationData, StoredHeaderData, - StoredHeaderDataBuilder, + justification::GrandpaJustification, ChainWithGrandpa, HeaderChain, InitializationData, + StoredHeaderData, StoredHeaderDataBuilder, }; -use bp_runtime::{BlockNumberOf, Chain, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; +use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{dispatch::PostDispatchInfo, ensure}; use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; @@ -97,7 +97,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { /// The chain we are bridging to here. - type BridgedChain: Chain; + type BridgedChain: ChainWithGrandpa; /// The upper bound on the number of requests allowed by the pallet. /// @@ -118,10 +118,6 @@ pub mod pallet { #[pallet::constant] type HeadersToKeep: Get; - /// Max number of authorities at the bridged chain. - #[pallet::constant] - type MaxBridgedAuthorities: Get; - /// Weights gathered through benchmarking. type WeightInfo: WeightInfo; } @@ -513,7 +509,7 @@ pub mod pallet { target: LOG_TARGET, "Failed to initialize bridge. Number of authorities in the set {} is larger than the configured value {}", authority_set_length, - T::MaxBridgedAuthorities::get(), + T::BridgedChain::MAX_AUTHORITIES_COUNT, ); Error::TooManyAuthoritiesInSet diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 8757093ee682e..f0ae2583529d5 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -17,8 +17,13 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] +use bp_header_chain::ChainWithGrandpa; use bp_runtime::Chain; -use frame_support::{construct_runtime, parameter_types, traits::ConstU64, weights::Weight}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{ConstU32, ConstU64}, + weights::Weight, +}; use sp_core::sr25519::Signature; use sp_runtime::{ testing::{Header, H256}, @@ -78,7 +83,7 @@ impl frame_system::Config for TestRuntime { type BlockLength = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } parameter_types! { @@ -92,7 +97,6 @@ impl grandpa::Config for TestRuntime { type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = frame_support::traits::ConstU32; type WeightInfo = (); } @@ -118,6 +122,14 @@ impl Chain for TestBridgedChain { } } +impl ChainWithGrandpa for TestBridgedChain { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; + const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const MAX_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; +} + pub fn run_test(test: impl FnOnce() -> T) -> T { sp_io::TestExternalities::new(Default::default()).execute_with(test) } diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index 732e72e2c0d62..918c131289c5b 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -18,22 +18,32 @@ use crate::Config; -use bp_header_chain::AuthoritySet; +use bp_header_chain::{AuthoritySet, ChainWithGrandpa}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; +use sp_std::marker::PhantomData; /// A bounded list of Grandpa authorities with associated weights. pub type StoredAuthorityList = BoundedVec<(AuthorityId, AuthorityWeight), MaxBridgedAuthorities>; +/// Adapter for using `T::BridgedChain::MAX_BRIDGED_AUTHORITIES` in `BoundedVec`. +pub struct StoredAuthorityListLimit(PhantomData<(T, I)>); + +impl, I: 'static> Get for StoredAuthorityListLimit { + fn get() -> u32 { + T::BridgedChain::MAX_AUTHORITIES_COUNT + } +} + /// A bounded GRANDPA Authority List and ID. #[derive(Clone, Decode, Encode, Eq, TypeInfo, MaxEncodedLen, RuntimeDebugNoBound)] #[scale_info(skip_type_params(T, I))] pub struct StoredAuthoritySet, I: 'static> { /// List of GRANDPA authorities for the current round. - pub authorities: StoredAuthorityList<>::MaxBridgedAuthorities>, + pub authorities: StoredAuthorityList>, /// Monotonic identifier of the current GRANDPA authority set. pub set_id: SetId, } @@ -60,7 +70,7 @@ impl, I: 'static> StoredAuthoritySet { let single_authority_max_encoded_len = <(AuthorityId, AuthorityWeight)>::max_encoded_len() as u64; let extra_authorities = - T::MaxBridgedAuthorities::get().saturating_sub(self.authorities.len() as _); + T::BridgedChain::MAX_AUTHORITIES_COUNT.saturating_sub(self.authorities.len() as _); single_authority_max_encoded_len.saturating_mul(extra_authorities as u64) } } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 8248964263c06..0e8261f689915 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use bp_header_chain::ChainWithGrandpa; use bp_polkadot_core::parachains::ParaId; use bp_runtime::{Chain, Parachain}; use frame_support::{construct_runtime, parameter_types, traits::ConstU32, weights::Weight}; @@ -199,7 +200,6 @@ impl pallet_bridge_grandpa::Config for TestRun type BridgedChain = TestBridgedChain; type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; type WeightInfo = (); } @@ -207,7 +207,6 @@ impl pallet_bridge_grandpa::Config for TestRun type BridgedChain = TestBridgedChain; type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; - type MaxBridgedAuthorities = frame_support::traits::ConstU32<5>; type WeightInfo = (); } @@ -250,6 +249,14 @@ impl Chain for TestBridgedChain { } } +impl ChainWithGrandpa for TestBridgedChain { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; + const MAX_AUTHORITIES_COUNT: u32 = 16; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const MAX_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; +} + #[derive(Debug)] pub struct OtherBridgedChain; @@ -273,6 +280,14 @@ impl Chain for OtherBridgedChain { } } +impl ChainWithGrandpa for OtherBridgedChain { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; + const MAX_AUTHORITIES_COUNT: u32 = 16; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const MAX_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; +} + pub fn run_test(test: impl FnOnce() -> T) -> T { sp_io::TestExternalities::new(Default::default()).execute_with(|| { System::set_block_number(1); diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 3bca5f4c3f077..7f48ded1a37e6 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -10,17 +10,21 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "sp-api/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 27d5f125ee266..9ada688bf11b5 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -19,10 +19,42 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_finality_runtime_apis; + +use bp_header_chain::ChainWithGrandpa; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use frame_support::weights::Weight; /// Kusama Chain -pub type Kusama = PolkadotLike; +pub struct Kusama; + +impl Chain for Kusama { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hasher; + type Header = ::Header; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Index = ::Index; + type Signature = ::Signature; + + fn max_extrinsic_size() -> u32 { + PolkadotLike::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + PolkadotLike::max_extrinsic_weight() + } +} + +impl ChainWithGrandpa for Kusama { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_KUSAMA_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} /// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 7600781d89169..00d5a02d47c49 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -8,11 +8,6 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -# Bridge Dependencies - -bp-beefy = { path = "../beefy", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } fixed-hash = { version = "0.8.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } @@ -21,6 +16,13 @@ parity-util-mem = { version = "0.12.0", default-features = false, features = ["p scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } +# Bridge Dependencies + +bp-beefy = { path = "../beefy", default-features = false } +bp-header-chain = { path = "../header-chain", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + # Substrate Based Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -36,6 +38,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default = ["std"] std = [ "bp-beefy/std", + "bp-header-chain/std", "bp-messages/std", "bp-runtime/std", "fixed-hash/std", diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 73515a7f4097b..81ed54362631b 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -21,6 +21,7 @@ mod millau_hash; use bp_beefy::ChainWithBeefy; +use bp_header_chain::ChainWithGrandpa; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; @@ -83,6 +84,27 @@ pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; /// Maximal number of GRANDPA authorities at Millau. pub const MAX_AUTHORITIES_COUNT: u32 = 5; +/// Reasonable number of headers in the `votes_ancestries` on Millau chain. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + +/// Approximate average header size in `votes_ancestries` field of justification on Millau chain. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; + +/// Approximate maximal header size on Millau chain. +/// +/// We expect maximal header to have digest item with the new authorities set for every consensus +/// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also +/// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT + .saturating_mul(3) + .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); + /// Re-export `time_units` to make usage easier. pub use time_units::*; @@ -156,6 +178,15 @@ impl Chain for Millau { } } +impl ChainWithGrandpa for Millau { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_MILLAU_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} + impl ChainWithBeefy for Millau { type CommitmentHasher = Keccak256; type MmrHashing = Keccak256; diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index b26093a05706e..def26bdda1c88 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -7,19 +7,24 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] + # Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", + "frame-support/std", "sp-api/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 0cada4e49a9be..e1600102fcd46 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -19,10 +19,42 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_finality_runtime_apis; + +use bp_header_chain::ChainWithGrandpa; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use frame_support::weights::Weight; /// Polkadot Chain -pub type Polkadot = PolkadotLike; +pub struct Polkadot; + +impl Chain for Polkadot { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hasher; + type Header = ::Header; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Index = ::Index; + type Signature = ::Signature; + + fn max_extrinsic_size() -> u32 { + PolkadotLike::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + PolkadotLike::max_extrinsic_weight() + } +} + +impl ChainWithGrandpa for Polkadot { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_POLKADOT_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} /// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index 663f9076657dd..0a70e0504c97a 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -25,6 +26,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-messages/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index ca0a3dfee88d6..a1c4a7267a7bd 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -18,6 +18,7 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] +use bp_header_chain::ChainWithGrandpa; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; @@ -72,6 +73,27 @@ pub const SESSION_LENGTH: BlockNumber = 4; /// Maximal number of GRANDPA authorities at Rialto. pub const MAX_AUTHORITIES_COUNT: u32 = 5; +/// Reasonable number of headers in the `votes_ancestries` on Rialto chain. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + +/// Approximate average header size in `votes_ancestries` field of justification on Rialto chain. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; + +/// Approximate maximal header size on Rialto chain. +/// +/// We expect maximal header to have digest item with the new authorities set for every consensus +/// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also +/// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT + .saturating_mul(3) + .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); + /// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Rialto /// parachains. /// @@ -160,6 +182,15 @@ impl Chain for Rialto { } } +impl ChainWithGrandpa for Rialto { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_RIALTO_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} + frame_support::parameter_types! { pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 73a2450cd17d7..4e21bd38b7acb 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -9,18 +9,22 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies + +bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies + sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", - "sp-api/std", "frame-support/std", + "sp-api/std", ] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 41fc65e0e93d1..0cb0b1d41e6dc 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -19,11 +19,42 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; -use bp_runtime::decl_bridge_finality_runtime_apis; -use frame_support::parameter_types; + +use bp_header_chain::ChainWithGrandpa; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use frame_support::{parameter_types, weights::Weight}; /// Rococo Chain -pub type Rococo = PolkadotLike; +pub struct Rococo; + +impl Chain for Rococo { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hasher; + type Header = ::Header; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Index = ::Index; + type Signature = ::Signature; + + fn max_extrinsic_size() -> u32 { + PolkadotLike::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + PolkadotLike::max_extrinsic_weight() + } +} + +impl ChainWithGrandpa for Rococo { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_ROCOCO_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} parameter_types! { pub const SS58Prefix: u8 = 42; diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 75f6727d764fd..13a2e597f9d86 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies +bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -21,6 +22,7 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 910a6c4acbd01..b6d41ece2868d 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -19,11 +19,42 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; + +use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; use frame_support::weights::Weight; /// Westend Chain -pub type Westend = PolkadotLike; +pub struct Westend; + +impl Chain for Westend { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hasher; + type Header = ::Header; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Index = ::Index; + type Signature = ::Signature; + + fn max_extrinsic_size() -> u32 { + PolkadotLike::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + PolkadotLike::max_extrinsic_weight() + } +} + +impl ChainWithGrandpa for Westend { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_WESTEND_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} /// Westmint parachain definition #[derive(Debug, Clone, Copy)] diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 6b741cd4b73c6..25fd7b9fd947a 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -9,18 +9,24 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] # Bridge Dependencies + +bp-header-chain = { path = "../header-chain", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } bp-rococo = { path = "../chain-rococo", default-features = false } # Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] std = [ + "bp-header-chain/std", "bp-polkadot-core/std", "bp-runtime/std", "bp-rococo/std", + "frame-support/std", "sp-api/std", ] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 1cf666c7f9612..2df019496ab14 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -22,10 +22,42 @@ pub use bp_polkadot_core::*; pub use bp_rococo::{ SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE, PARAS_PALLET_NAME, }; -use bp_runtime::decl_bridge_finality_runtime_apis; + +use bp_header_chain::ChainWithGrandpa; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use frame_support::weights::Weight; /// Wococo Chain -pub type Wococo = PolkadotLike; +pub struct Wococo; + +impl Chain for Wococo { + type BlockNumber = ::BlockNumber; + type Hash = ::Hash; + type Hasher = ::Hasher; + type Header = ::Header; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Index = ::Index; + type Signature = ::Signature; + + fn max_extrinsic_size() -> u32 { + PolkadotLike::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + PolkadotLike::max_extrinsic_weight() + } +} + +impl ChainWithGrandpa for Wococo { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_WOCOCO_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 49d1ae894068f..cafb8e7a3c86f 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -119,7 +119,7 @@ impl AuthoritySet { } } -/// Data required for initializing the bridge pallet. +/// Data required for initializing the GRANDPA bridge pallet. /// /// The bridge needs to know where to start its sync from, and this provides that initial context. #[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone, TypeInfo)] @@ -188,3 +188,48 @@ pub enum BridgeGrandpaCall { /// The `BridgeGrandpaCall` used by a chain. pub type BridgeGrandpaCallOf = BridgeGrandpaCall>; + +/// Substrate-based chain that is using direct GRANDPA finality. +/// +/// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement +/// this trait. +pub trait ChainWithGrandpa: Chain { + /// Name of the bridge GRANDPA pallet (used in `construct_runtime` macro call) that is deployed + /// at some other chain to bridge with this `ChainWithGrandpa`. + /// + /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using + /// the same name. + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str; + + /// Max number of GRANDPA authorities at the chain. + /// + /// This is a strict constant. If bridged chain will have more authorities than that, + /// the GRANDPA bridge pallet may halt. + const MAX_AUTHORITIES_COUNT: u32; + + /// Max reasonable number of headers in `votes_ancestries` vector of the GRANDPA justification. + /// + /// This isn't a strict limit. The relay may submit justifications with more headers in its + /// ancestry and the pallet will accept such justification. The limit is only used to compute + /// maximal refund amount and submitting justifications which exceed the limit, may be costly + /// to submitter. + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32; + + /// Maximal size of the chain header. The header may be the header that enacts new GRANDPA + /// authorities set (so it has large digest inside). + /// + /// This isn't a strict limit. The relay may submit larger headers and the pallet will accept + /// the call. The limit is only used to compute maximal refund amount and doing calls which + /// exceed the limit, may be costly to submitter. + const MAX_HEADER_SIZE: u32; + + /// Average size of the chain header from justification ancestry. We don't expect to see there + /// headers that change GRANDPA authorities set (GRANDPA will probably be able to finalize at + /// least one additional header per session on non test chains), so this is average size of + /// headers that aren't changing the set. + /// + /// This isn't a strict limit. The relay may submit justifications with larger headers in its + /// ancestry and the pallet will accept the call. The limit is only used to compute maximal + /// refund amount and doing calls which exceed the limit, may be costly to submitter. + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; +} diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index b13ceb5df50d4..3b1712042d808 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -53,6 +53,28 @@ pub mod parachains; /// take twice as much here. pub const MAX_AUTHORITIES_COUNT: u32 = 2_048; +/// Reasonable number of headers in the `votes_ancestries` on Polkadot-like chains. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + +/// Approximate average header size in `votes_ancestries` field of justification on Polkadot-like +/// chains. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; + +/// Approximate maximal header size on Polkadot-like chains. +/// +/// We expect maximal header to have digest item with the new authorities set for every consensus +/// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also +/// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. +/// +/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT + .saturating_mul(3) + .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); + /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Polkadot-like chain. This mostly depends on number of entries in the storage trie. /// Some reserve is reserved to account future chain growth. diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index cd6e23a460795..83f6b30f4cb29 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Kusama chain. use bp_kusama::AccountInfoStorageMapKeyProvider; -use relay_substrate_client::{Chain, ChainWithBalances, ChainWithGrandpa, UnderlyingChainProvider}; +use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -43,10 +43,6 @@ impl Chain for Kusama { type Call = (); } -impl ChainWithGrandpa for Kusama { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME; -} - impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 34bbea92d57e9..711b4f32cc632 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -19,9 +19,9 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - FullRuntimeUtilityPallet, IndexOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, + ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, IndexOf, SignParam, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -38,10 +38,6 @@ impl UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } -impl ChainWithGrandpa for Millau { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME; -} - impl ChainWithMessages for Millau { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index ac67d55ab5418..19326dd4c7303 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Polkadot chain. use bp_polkadot::AccountInfoStorageMapKeyProvider; -use relay_substrate_client::{Chain, ChainWithBalances, ChainWithGrandpa, UnderlyingChainProvider}; +use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -43,11 +43,6 @@ impl Chain for Polkadot { type Call = (); } -impl ChainWithGrandpa for Polkadot { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = - bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME; -} - impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 8ad31de4d583a..39cc2721ddbf5 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -19,9 +19,9 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, Error as SubstrateError, IndexOf, RelayChain, SignParam, - UnderlyingChainProvider, UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, + Error as SubstrateError, IndexOf, RelayChain, SignParam, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -56,10 +56,6 @@ impl RelayChain for Rialto { bp_rialto::WITH_RIALTO_BRIDGE_PARAS_PALLET_NAME; } -impl ChainWithGrandpa for Rialto { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME; -} - impl ChainWithMessages for Rialto { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index a764759906ac4..a0730026e04c6 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,9 +16,7 @@ //! Types used to connect to the Rococo-Substrate chain. -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, -}; +use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -47,10 +45,6 @@ impl Chain for Rococo { type Call = (); } -impl ChainWithGrandpa for Rococo { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_rococo::WITH_ROCOCO_GRANDPA_PALLET_NAME; -} - impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 4ec5edfc41bcf..b9c5793842efd 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -73,11 +73,6 @@ pub trait RelayChain: Chain { const PARACHAINS_FINALITY_PALLET_NAME: &'static str; } -/// Substrate-based parachain from minimal relay-client point of view. -pub trait Parachain: Chain + ParachainBase {} - -impl Parachain for T where T: UnderlyingChainProvider + Chain + ParachainBase {} - /// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of /// view. /// @@ -92,6 +87,20 @@ pub trait ChainWithGrandpa: Chain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str; } +impl ChainWithGrandpa for T +where + T: Chain + UnderlyingChainProvider, + T::Chain: bp_header_chain::ChainWithGrandpa, +{ + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + ::WITH_CHAIN_GRANDPA_PALLET_NAME; +} + +/// Substrate-based parachain from minimal relay-client point of view. +pub trait Parachain: Chain + ParachainBase {} + +impl Parachain for T where T: UnderlyingChainProvider + Chain + ParachainBase {} + /// Substrate-based chain with messaging support from minimal relay-client point of view. pub trait ChainWithMessages: Chain { /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 6467f431335cf..a8a8df36b8bf9 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,9 +16,7 @@ //! Types used to connect to the Westend chain. -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, -}; +use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -53,11 +51,6 @@ impl RelayChain for Westend { bp_westend::WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME; } -impl ChainWithGrandpa for Westend { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = - bp_westend::WITH_WESTEND_GRANDPA_PALLET_NAME; -} - impl ChainWithBalances for Westend { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_westend::AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index a3e10729ba093..8f30572db63af 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,9 +16,7 @@ //! Types used to connect to the Wococo-Substrate chain. -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, -}; +use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -47,10 +45,6 @@ impl Chain for Wococo { type Call = (); } -impl ChainWithGrandpa for Wococo { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = bp_wococo::WITH_WOCOCO_GRANDPA_PALLET_NAME; -} - impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) From 8e56fa11b3c872284ff38dce525c8a1ed93d1314 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 16 Feb 2023 14:49:48 +0100 Subject: [PATCH 0945/1210] Make `weights::WeightInfo` pub (#1886) --- modules/relayers/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 7132914a4ae85..2ceebd0336e09 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -26,10 +26,10 @@ use bp_runtime::StorageDoubleMapKeyProvider; use frame_support::sp_runtime::Saturating; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; use sp_std::marker::PhantomData; -use weights::WeightInfo; pub use pallet::*; pub use payment_adapter::DeliveryConfirmationPaymentsAdapter; +pub use weights::WeightInfo; pub mod benchmarking; From 2bcea5eb5de1eb04152a15dc17aae8d8bd809d76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 03:12:34 +0000 Subject: [PATCH 0946/1210] Bump trie-db from 0.25.0 to 0.25.1 Bumps [trie-db](https://github.com/paritytech/trie) from 0.25.0 to 0.25.1. - [Release notes](https://github.com/paritytech/trie/releases) - [Commits](https://github.com/paritytech/trie/compare/trie-db-v0.25.0...trie-db-v0.25.1) --- updated-dependencies: - dependency-name: trie-db dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- primitives/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 515d6e1a6c4a9..c8829a508d9d0 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master 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 } -trie-db = { version = "0.25.0", default-features = false } +trie-db = { version = "0.25.1", default-features = false } [dev-dependencies] hex-literal = "0.3" From 13c8f3f6d6496250440a16c8447acb0c05a76306 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 03:12:53 +0000 Subject: [PATCH 0947/1210] Bump sysinfo from 0.27.7 to 0.28.0 Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.27.7 to 0.28.0. - [Release notes](https://github.com/GuillaumeGomez/sysinfo/releases) - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/commits) --- updated-dependencies: - dependency-name: sysinfo dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 57eeb7fbc8c07..1d7422d5a8c6b 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -18,7 +18,7 @@ jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" serde_json = "1.0" -sysinfo = "0.27" +sysinfo = "0.28" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.25", features = ["rt"] } thiserror = "1.0.26" From 6b8c9a7c7d4bebc02c48e84774e55f4866b718de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 03:13:29 +0000 Subject: [PATCH 0948/1210] Bump clap from 4.1.4 to 4.1.6 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.4 to 4.1.6. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.1.4...v4.1.6) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index fea96c9b11f15..3d3d238943d09 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.4", features = ["derive"] } +clap = { version = "4.1.6", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.93" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 5e1eba1fee55f..c20b7f248cc22 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.1.4", features = ["derive"] } +clap = { version = "4.1.6", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index d03deaaabefad..556088498f766 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.4", features = ["derive"] } +clap = { version = "4.1.6", features = ["derive"] } serde_json = "1.0.93" # Bridge dependencies From a563319bd2488127a86cce8d52022d909657f513 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 20 Feb 2023 11:27:39 +0300 Subject: [PATCH 0949/1210] use complex transactions on RBH/WBH bridge hubs (#1893) --- ..._hub_rococo_messages_to_bridge_hub_wococo.rs | 6 +++--- ..._hub_wococo_messages_to_bridge_hub_rococo.rs | 6 +++--- relays/client-bridge-hub-rococo/src/lib.rs | 9 +++++++-- .../src/runtime_wrapper.rs | 11 ++++++++++- relays/client-bridge-hub-wococo/src/lib.rs | 9 +++++++-- .../src/runtime_wrapper.rs | 11 ++++++++++- relays/client-substrate/src/calls.rs | 9 +++++++++ relays/client-substrate/src/chain.rs | 17 +++++++++++++++++ relays/client-substrate/src/lib.rs | 4 ++-- 9 files changed, 68 insertions(+), 14 deletions(-) diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index b48ace58987d1..9e4b5b15fd6d4 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -19,7 +19,7 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_wococo_client::BridgeHubWococo; -use substrate_relay_helper::messages_lane::SubstrateMessageLane; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; pub struct BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} @@ -59,6 +59,6 @@ impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWococoMessageLan type ReceiveMessagesDeliveryProofCallBuilder = BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = (); + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; } diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index 3bcf62de333ad..fb5a81c021e19 100644 --- a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -19,7 +19,7 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_wococo_client::BridgeHubWococo; -use substrate_relay_helper::messages_lane::SubstrateMessageLane; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; pub struct BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} @@ -59,6 +59,6 @@ impl SubstrateMessageLane for BridgeHubWococoMessagesToBridgeHubRococoMessageLan type ReceiveMessagesDeliveryProofCallBuilder = BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = (); + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 80c075cd0d5fd..d2e421423a5a8 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -21,8 +21,9 @@ use bp_bridge_hub_wococo::PolkadotSignedExtension; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, - SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -57,6 +58,10 @@ impl ChainWithBalances for BridgeHubRococo { } } +impl ChainWithUtilityPallet for BridgeHubRococo { + type UtilityPallet = MockedRuntimeUtilityPallet; +} + impl ChainWithTransactions for BridgeHubRococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = runtime::UncheckedExtrinsic; diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index 7f526a35aa941..fc945d8c95072 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -25,7 +25,7 @@ use bp_bridge_hub_rococo::SignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::SystemCall; +pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubRococo extrinsic. pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; @@ -49,6 +49,9 @@ pub enum Call { #[cfg(test)] #[codec(index = 0)] System(SystemCall), + /// Utility pallet. + #[codec(index = 40)] + Utility(UtilityCall), /// Wococo bridge pallet. #[codec(index = 41)] @@ -60,3 +63,9 @@ pub enum Call { #[codec(index = 46)] BridgeWococoMessages(BridgeWococoMessagesCall), } + +impl From> for Call { + fn from(call: UtilityCall) -> Call { + Call::Utility(call) + } +} diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 7af310bfd4176..2c211ae86cf44 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -20,8 +20,9 @@ use bp_bridge_hub_wococo::{PolkadotSignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, - SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -56,6 +57,10 @@ impl ChainWithBalances for BridgeHubWococo { } } +impl ChainWithUtilityPallet for BridgeHubWococo { + type UtilityPallet = MockedRuntimeUtilityPallet; +} + impl ChainWithTransactions for BridgeHubWococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = runtime::UncheckedExtrinsic; diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 17cc4cbd4e8f8..c16e7d1a45bce 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -23,7 +23,7 @@ use bp_bridge_hub_wococo::SignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::SystemCall; +pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubWococo extrinsic. pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; @@ -47,6 +47,9 @@ pub enum Call { #[cfg(test)] #[codec(index = 0)] System(SystemCall), + /// Utility pallet. + #[codec(index = 40)] + Utility(UtilityCall), /// Rococo bridge pallet. #[codec(index = 43)] @@ -59,6 +62,12 @@ pub enum Call { BridgeRococoMessages(BridgeRococoMessagesCall), } +impl From> for Call { + fn from(call: UtilityCall) -> Call { + Call::Utility(call) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/relays/client-substrate/src/calls.rs b/relays/client-substrate/src/calls.rs index 89fc49a209aeb..4e0ae9d99d2e6 100644 --- a/relays/client-substrate/src/calls.rs +++ b/relays/client-substrate/src/calls.rs @@ -31,6 +31,15 @@ pub enum SystemCall { remark(Vec), } +/// A minimized version of `pallet-utility::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum UtilityCall { + /// `pallet-utility::Call::batch_all` + #[codec(index = 2)] + batch_all(Vec), +} + /// A minimized version of `pallet-sudo::Call` that can be used without a runtime. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index b9c5793842efd..ebd9e7172d895 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use crate::calls::UtilityCall; + use bp_messages::MessageNonce; use bp_runtime::{ Chain as ChainBase, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra, @@ -276,6 +278,21 @@ where } } +/// Structure that implements `UtilityPalletProvider` based on a call conversion. +pub struct MockedRuntimeUtilityPallet { + _phantom: std::marker::PhantomData, +} + +impl UtilityPallet for MockedRuntimeUtilityPallet +where + C: Chain, + C::Call: From>, +{ + fn build_batch_call(calls: Vec) -> C::Call { + UtilityCall::batch_all(calls).into() + } +} + /// Substrate-based chain that uses `pallet-utility`. pub trait ChainWithUtilityPallet: Chain { /// The utility pallet provider. diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index c1a96c487c4b7..c8d8b6f8129f9 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -36,8 +36,8 @@ pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - FullRuntimeUtilityPallet, Parachain, RelayChain, SignParam, TransactionStatusOf, - UnsignedTransaction, UtilityPallet, + FullRuntimeUtilityPallet, MockedRuntimeUtilityPallet, Parachain, RelayChain, SignParam, + TransactionStatusOf, UnsignedTransaction, UtilityPallet, }, client::{ is_ancient_block, ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, From 3985977350853e0f31a39a3f3dccbaa3e6ce67d2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 20 Feb 2023 11:57:54 +0300 Subject: [PATCH 0950/1210] optimize justification before submit (#1887) * optimize justification before submit * fmt * spelling * clippy * fmt again * aaand compilation * clippy --- modules/grandpa/src/lib.rs | 5 + primitives/header-chain/src/justification.rs | 121 +++++++++++++++++- primitives/header-chain/src/storage_keys.rs | 26 ++++ .../header-chain/tests/justification.rs | 86 ++++++++++++- primitives/test-utils/src/lib.rs | 5 +- .../src/finality/engine.rs | 51 +++++++- .../src/finality/target.rs | 4 + 7 files changed, 290 insertions(+), 8 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 197726dd47a5e..b11da53f7b3b7 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -1187,6 +1187,11 @@ mod tests { bp_header_chain::storage_keys::pallet_operating_mode_key("Grandpa").0, ); + assert_eq!( + CurrentAuthoritySet::::storage_value_final_key().to_vec(), + bp_header_chain::storage_keys::current_authority_set_key("Grandpa").0, + ); + assert_eq!( BestFinalized::::storage_value_final_key().to_vec(), bp_header_chain::storage_keys::best_finalized_key("Grandpa").0, diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index dadd48a485029..43adc80125446 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -71,6 +71,14 @@ pub enum Error { ExtraHeadersInVotesAncestries, } +/// Given GRANDPA authorities set size, return number of valid authorities votes that the +/// justification must have to be valid. +/// +/// This function assumes that all authorities have the same vote weight. +pub fn required_justification_precommits(authorities_set_length: u32) -> u32 { + authorities_set_length - authorities_set_length.saturating_sub(1) / 3 +} + /// Decode justification target. pub fn decode_justification_target( raw_justification: &[u8], @@ -80,6 +88,27 @@ pub fn decode_justification_target( .map_err(|_| Error::JustificationDecode) } +/// Verify and optimize given justification by removing unknown and duplicate votes. +pub fn optimize_justification( + finalized_target: (Header::Hash, Header::Number), + authorities_set_id: SetId, + authorities_set: &VoterSet, + justification: GrandpaJustification

, +) -> Result, Error> +where + Header::Number: finality_grandpa::BlockNumberOps, +{ + let mut optimizer = OptimizationCallbacks(Vec::new()); + verify_justification_with_callbacks( + finalized_target, + authorities_set_id, + authorities_set, + &justification, + &mut optimizer, + )?; + Ok(optimizer.optimize(justification)) +} + /// Verify that justification, that is generated by given authority set, finalizes given header. pub fn verify_justification( finalized_target: (Header::Hash, Header::Number), @@ -87,6 +116,83 @@ pub fn verify_justification( authorities_set: &VoterSet, justification: &GrandpaJustification
, ) -> Result<(), Error> +where + Header::Number: finality_grandpa::BlockNumberOps, +{ + verify_justification_with_callbacks( + finalized_target, + authorities_set_id, + authorities_set, + justification, + &mut (), + ) +} + +/// Verification callbacks. +trait VerificationCallbacks { + /// Called when we see a precommit from unknown authority. + fn on_unkown_authority(&mut self, precommit_idx: usize) -> Result<(), Error>; + /// Called when we see a precommit with duplicate vote from known authority. + fn on_duplicate_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; + /// Called when we see a precommit after we've collected enough votes from authorities. + fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; +} + +/// Verification callbacks for justification optimization. +struct OptimizationCallbacks(Vec); + +impl OptimizationCallbacks { + fn optimize( + self, + mut justification: GrandpaJustification
, + ) -> GrandpaJustification
{ + for invalid_precommit_idx in self.0.into_iter().rev() { + justification.commit.precommits.remove(invalid_precommit_idx); + } + justification + } +} + +impl VerificationCallbacks for OptimizationCallbacks { + fn on_unkown_authority(&mut self, precommit_idx: usize) -> Result<(), Error> { + self.0.push(precommit_idx); + Ok(()) + } + + fn on_duplicate_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { + self.0.push(precommit_idx); + Ok(()) + } + + fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { + self.0.push(precommit_idx); + Ok(()) + } +} + +// this implementation will be removed in https://github.com/paritytech/parity-bridges-common/pull/1882 +impl VerificationCallbacks for () { + fn on_unkown_authority(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Ok(()) + } + + fn on_duplicate_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Ok(()) + } + + fn on_redundant_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Ok(()) + } +} + +/// Verify that justification, that is generated by given authority set, finalizes given header. +fn verify_justification_with_callbacks( + finalized_target: (Header::Hash, Header::Number), + authorities_set_id: SetId, + authorities_set: &VoterSet, + justification: &GrandpaJustification
, + callbacks: &mut C, +) -> Result<(), Error> where Header::Number: finality_grandpa::BlockNumberOps, { @@ -95,17 +201,23 @@ where return Err(Error::InvalidJustificationTarget) } + let threshold = authorities_set.threshold().0.into(); let mut chain = AncestryChain::new(&justification.votes_ancestries); let mut signature_buffer = Vec::new(); let mut votes = BTreeSet::new(); let mut cumulative_weight = 0u64; - for signed in &justification.commit.precommits { + for (precommit_idx, signed) in justification.commit.precommits.iter().enumerate() { + // if we have collected enough precommits, we probabably want to fail/remove extra + // precommits + if cumulative_weight > threshold { + callbacks.on_redundant_authority_vote(precommit_idx)?; + } + // authority must be in the set let authority_info = match authorities_set.get(&signed.id) { Some(authority_info) => authority_info, None => { - // just ignore precommit from unknown authority as - // `finality_grandpa::import_precommit` does + callbacks.on_unkown_authority(precommit_idx)?; continue }, }; @@ -116,6 +228,7 @@ where // `finality-grandpa` crate (mostly related to reporting equivocations). But the only thing // that we care about is that only first vote from the authority is accepted if !votes.insert(signed.id.clone()) { + callbacks.on_duplicate_authority_vote(precommit_idx)?; continue } @@ -142,6 +255,7 @@ where thus we'll never overflow the u64::MAX;\ qed", ); + // verify authority signature if !sp_finality_grandpa::check_message_signature_with_buffer( &finality_grandpa::Message::Precommit(signed.precommit.clone()), @@ -162,7 +276,6 @@ where // check that the cumulative weight of validators voted for the justification target (or one // of its descendents) is larger than required threshold. - let threshold = authorities_set.threshold().0.into(); if cumulative_weight >= threshold { Ok(()) } else { diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs index bb642b1817f75..c4dbe53bd9a7f 100644 --- a/primitives/header-chain/src/storage_keys.rs +++ b/primitives/header-chain/src/storage_keys.rs @@ -20,6 +20,8 @@ pub const PALLET_OPERATING_MODE_VALUE_NAME: &str = "PalletOperatingMode"; /// Name of the `BestFinalized` storage value. pub const BEST_FINALIZED_VALUE_NAME: &str = "BestFinalized"; +/// Name of the `CurrentAuthoritySet` storage value. +pub const CURRENT_AUTHORITY_SET_VALUE_NAME: &str = "CurrentAuthoritySet"; use sp_core::storage::StorageKey; @@ -34,6 +36,17 @@ pub fn pallet_operating_mode_key(pallet_prefix: &str) -> StorageKey { ) } +/// Storage key of the `CurrentAuthoritySet` variable in the runtime storage. +pub fn current_authority_set_key(pallet_prefix: &str) -> StorageKey { + StorageKey( + bp_runtime::storage_value_final_key( + pallet_prefix.as_bytes(), + CURRENT_AUTHORITY_SET_VALUE_NAME.as_bytes(), + ) + .to_vec(), + ) +} + /// Storage key of the best finalized header number and hash value in the runtime storage. pub fn best_finalized_key(pallet_prefix: &str) -> StorageKey { StorageKey( @@ -63,6 +76,19 @@ mod tests { ); } + #[test] + fn current_authority_set_key_computed_properly() { + // If this test fails, then something has been changed in module storage that is breaking + // compatibility with previous pallet. + let storage_key = current_authority_set_key("BridgeGrandpa").0; + assert_eq!( + storage_key, + hex!("0b06f475eddb98cf933a12262e0388de24a7b8b5717ea33346fa595a66ccbcb0").to_vec(), + "Unexpected storage key: {}", + hex::encode(&storage_key), + ); + } + #[test] fn best_finalized_key_computed_properly() { // If this test fails, then something has been changed in module storage that is breaking diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 5b4981a0f69a8..e18163313c936 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -16,7 +16,7 @@ //! Tests for Grandpa Justification code. -use bp_header_chain::justification::{verify_justification, Error}; +use bp_header_chain::justification::{optimize_justification, verify_justification, Error}; use bp_test_utils::*; type TestHeader = sp_runtime::testing::Header; @@ -190,3 +190,87 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { Err(Error::TooLowCumulativeWeight), ); } + +#[test] +fn optimizer_does_noting_with_minimal_justification() { + let justification = make_default_justification::(&test_header(1)); + + let num_precommits_before = justification.commit.precommits.len(); + let justification = optimize_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + justification, + ) + .unwrap(); + let num_precommits_after = justification.commit.precommits.len(); + + assert_eq!(num_precommits_before, num_precommits_after); +} + +#[test] +fn unknown_authority_votes_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(1)); + justification.commit.precommits.push(signed_precommit::( + &bp_test_utils::Account(42), + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); + + let num_precommits_before = justification.commit.precommits.len(); + let justification = optimize_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + justification, + ) + .unwrap(); + let num_precommits_after = justification.commit.precommits.len(); + + assert_eq!(num_precommits_before - 1, num_precommits_after); +} + +#[test] +fn duplicate_authority_votes_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(1)); + justification + .commit + .precommits + .push(justification.commit.precommits.first().cloned().unwrap()); + + let num_precommits_before = justification.commit.precommits.len(); + let justification = optimize_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + justification, + ) + .unwrap(); + let num_precommits_after = justification.commit.precommits.len(); + + assert_eq!(num_precommits_before - 1, num_precommits_after); +} + +#[test] +fn redundant_authority_votes_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(1)); + justification.commit.precommits.push(signed_precommit::( + &EVE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); + + let num_precommits_before = justification.commit.precommits.len(); + let justification = optimize_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + justification, + ) + .unwrap(); + let num_precommits_after = justification.commit.precommits.len(); + + assert_eq!(num_precommits_before - 1, num_precommits_after); +} diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index c1e95ec6fefdc..a6bb3d9b8feb6 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -18,7 +18,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_header_chain::justification::GrandpaJustification; +use bp_header_chain::justification::{required_justification_precommits, GrandpaJustification}; use codec::Encode; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId}; use sp_runtime::traits::{Header as HeaderT, One, Zero}; @@ -57,11 +57,12 @@ pub struct JustificationGeneratorParams { impl Default for JustificationGeneratorParams { fn default() -> Self { + let required_signatures = required_justification_precommits(test_keyring().len() as _); Self { header: test_header(One::one()), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: test_keyring(), + authorities: test_keyring().into_iter().take(required_signatures as _).collect(), ancestors: 2, forks: 1, } diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 4c2da5a53195d..f5ac8539a689e 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -22,7 +22,7 @@ use bp_header_chain::{ justification::{verify_justification, GrandpaJustification}, ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader, }; -use bp_runtime::{BasicOperatingMode, OperatingMode}; +use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode}; use codec::{Decode, Encode}; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; @@ -87,6 +87,13 @@ pub trait Engine: Send { client.subscribe_finality_justifications::().await } + /// Optimize finality proof before sending it to the target node. + async fn optimize_proof( + target_client: &Client, + header: &C::Header, + proof: Self::FinalityProof, + ) -> Result; + /// Prepare initialization data for the finality bridge pallet. async fn prepare_initialization_data( client: Client, @@ -139,6 +146,48 @@ impl Engine for Grandpa { bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } + async fn optimize_proof( + target_client: &Client, + header: &C::Header, + proof: Self::FinalityProof, + ) -> Result { + let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key( + C::WITH_CHAIN_GRANDPA_PALLET_NAME, + ); + let (authority_set, authority_set_id): ( + sp_finality_grandpa::AuthorityList, + sp_finality_grandpa::SetId, + ) = target_client + .storage_value(current_authority_set_key, None) + .await? + .map(Ok) + .unwrap_or(Err(SubstrateError::Custom(format!( + "{} `CurrentAuthoritySet` is missing from the {} storage", + C::NAME, + TargetChain::NAME, + ))))?; + let authority_set = + finality_grandpa::voter_set::VoterSet::new(authority_set).expect("TODO"); + // we're risking with race here - we have decided to submit justification some time ago and + // actual authorities set (which we have read now) may have changed, so this + // `optimize_justification` may fail. But if target chain is configured properly, it'll fail + // anyway, after we submit transaction and failing earlier is better. So - it is fine + bp_header_chain::justification::optimize_justification( + (header.hash(), *header.number()), + authority_set_id, + &authority_set, + proof, + ) + .map_err(|e| { + SubstrateError::Custom(format!( + "Failed to optimize {} GRANDPA jutification for header {:?}: {:?}", + C::NAME, + header.id(), + e, + )) + }) + } + /// Prepare initialization data for the GRANDPA verifier pallet. async fn prepare_initialization_data( source_client: Client, diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 9c6ec7c3055ed..81a22520fa951 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -111,6 +111,10 @@ where header: SyncHeader>, proof: SubstrateFinalityProof

, ) -> Result { + // runtime module at target chain may require optimized finality proof + let proof = P::FinalityEngine::optimize_proof(&self.client, &header, proof).await?; + + // now we may submit optimized finality proof let transaction_params = self.transaction_params.clone(); let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); From 5945eba82584e6c477c578ec1853d205c12ac07e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 20 Feb 2023 16:36:13 +0200 Subject: [PATCH 0951/1210] RefundRelayerForMessagesFromParachain improvements (#1895) * RefundRelayerForMessagesFromParachain changes - some renamings and cosmetics - removing the GI generic param since we can get it from the parachains config - merging (Parachains Instance, Parachain Id) and (Messages Instance, Messages lane Id) generic params - removing unnecessay derives - renaming for the `TransactionFeeCalculation` and defining `ActualFeeRefund` concrete implementation - adding support for multiple RefundRelayerForMessagesFromParachain (by adding a `StaticStrProvider` generic param) * Revert to using RuntimeDebug --- bin/millau/runtime/src/lib.rs | 28 +- bin/runtime-common/src/messages_call_ext.rs | 6 +- .../src/refund_relayer_extension.rs | 347 ++++++++++-------- modules/parachains/src/call_ext.rs | 9 +- primitives/runtime/src/lib.rs | 24 ++ relays/client-millau/src/lib.rs | 2 +- 6 files changed, 247 insertions(+), 169 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 5a18f8b12c039..369bea2b1fafb 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -80,7 +80,13 @@ pub use pallet_sudo::Call as SudoCall; pub use pallet_timestamp::Call as TimestampCall; pub use pallet_xcm::Call as XcmCall; -use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages; +use bridge_runtime_common::{ + generate_bridge_reject_obsolete_headers_and_messages, + refund_relayer_extension::{ + ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane, + RefundableParachain, + }, +}; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; @@ -582,17 +588,15 @@ generate_bridge_reject_obsolete_headers_and_messages! { BridgeRialtoMessages, BridgeRialtoParachainMessages } +bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); /// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. -pub type BridgeRefundRialtoParachainRelayers = - bridge_runtime_common::refund_relayer_extension::RefundRelayerForMessagesFromParachain< - Runtime, - RialtoGrandpaInstance, - WithRialtoParachainsInstance, - WithRialtoParachainMessagesInstance, - RialtoParachainId, - RialtoParachainMessagesLane, - Runtime, - >; +pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< + Runtime, + RefundableParachain, + RefundableMessagesLane, + ActualFeeRefund, + StrBridgeRefundRialtoPara2000Lane0Msgs, +>; /// The address format for describing accounts. pub type Address = AccountId; @@ -615,7 +619,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, BridgeRejectObsoleteHeadersAndMessages, - BridgeRefundRialtoParachainRelayers, + BridgeRefundRialtoParachainMessages, ); /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 20e604142d944..740d17129c894 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -18,12 +18,12 @@ use crate::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use bp_messages::{LaneId, MessageNonce}; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; use pallet_bridge_messages::{Config, Pallet}; -use sp_runtime::{transaction_validity::TransactionValidity, RuntimeDebug}; +use sp_runtime::transaction_validity::TransactionValidity; /// Info about a `ReceiveMessagesProof` call which tries to update a single lane. -#[derive(Copy, Clone, PartialEq, RuntimeDebug)] +#[derive(PartialEq, RuntimeDebug)] pub struct ReceiveMessagesProofInfo { pub lane_id: LaneId, pub best_proof_nonce: MessageNonce, diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index ac65617483d56..9efeedf24dd59 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -23,6 +23,7 @@ use crate::messages_call_ext::{ MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo, }; use bp_messages::LaneId; +use bp_runtime::StaticStrProvider; use codec::{Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, @@ -46,28 +47,77 @@ use sp_runtime::{ }; use sp_std::{marker::PhantomData, vec, vec::Vec}; -// TODO (https://github.com/paritytech/parity-bridges-common/issues/1667): -// support multiple bridges in this extension +// without this typedef rustfmt fails with internal err +type BalanceOf = + <::OnChargeTransaction as OnChargeTransaction>::Balance; +type CallOf = ::RuntimeCall; + +/// Trait identifying a bridged parachain. A relayer might be refunded for delivering messages +/// coming from this parachain. +trait RefundableParachainId { + /// The instance of the bridge parachains pallet. + type Instance; + /// The parachain Id. + type Id: Get; +} -/// Transaction fee calculation. -pub trait TransactionFeeCalculation { - /// Compute fee that is paid for given transaction. The fee is later refunded to relayer. - fn compute_fee( +/// Default implementation of `RefundableParachainId`. +pub struct RefundableParachain(PhantomData<(Instance, Id)>); + +impl RefundableParachainId for RefundableParachain +where + Id: Get, +{ + type Instance = Instance; + type Id = Id; +} + +/// Trait identifying a bridged messages lane. A relayer might be refunded for delivering messages +/// coming from this lane. +trait RefundableMessagesLaneId { + /// The instance of the bridge messages pallet. + type Instance; + /// The messages lane id. + type Id: Get; +} + +/// Default implementation of `RefundableMessagesLaneId`. +pub struct RefundableMessagesLane(PhantomData<(Instance, Id)>); + +impl RefundableMessagesLaneId for RefundableMessagesLane +where + Id: Get, +{ + type Instance = Instance; + type Id = Id; +} + +/// Refund calculator. +pub trait RefundCalculator { + // The underlying integer type in which the refund is calculated. + type Balance; + + /// Compute refund for given transaction. + fn compute_refund( info: &DispatchInfo, post_info: &PostDispatchInfo, len: usize, - tip: Balance, - ) -> Balance; + tip: Self::Balance, + ) -> Self::Balance; } -impl TransactionFeeCalculation> for R +/// `RefundCalculator` implementation which refunds the actual transaction fee. +pub struct ActualFeeRefund(PhantomData); + +impl RefundCalculator for ActualFeeRefund where R: TransactionPaymentConfig, - ::RuntimeCall: - Dispatchable, + CallOf: Dispatchable, BalanceOf: FixedPointOperand, { - fn compute_fee( + type Balance = BalanceOf; + + fn compute_refund( info: &DispatchInfo, post_info: &PostDispatchInfo, len: usize, @@ -77,7 +127,55 @@ where } } -/// Signed extension that refunds relayer for new messages coming from the parachain. +/// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`. +#[cfg_attr(test, derive(Debug, PartialEq))] +pub struct PreDispatchData { + /// Transaction submitter (relayer) account. + relayer: AccountId, + /// Type of the call. + call_info: CallInfo, +} + +/// Type of the call that the extension recognizes. +#[derive(RuntimeDebugNoBound, PartialEq)] +pub enum CallInfo { + /// Relay chain finality + parachain finality + message delivery calls. + AllFinalityAndDelivery(RelayBlockNumber, SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), + /// Parachain finality + message delivery calls. + ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), + /// Standalone message delivery call. + Delivery(ReceiveMessagesProofInfo), +} + +impl CallInfo { + /// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call. + fn submit_finality_proof_info(&self) -> Option { + match *self { + Self::AllFinalityAndDelivery(info, _, _) => Some(info), + _ => None, + } + } + + /// Returns the pre-dispatch `SubmitParachainHeadsInfo`. + fn submit_parachain_heads_info(&self) -> Option<&SubmitParachainHeadsInfo> { + match self { + Self::AllFinalityAndDelivery(_, info, _) => Some(info), + Self::ParachainFinalityAndDelivery(info, _) => Some(info), + _ => None, + } + } + + /// Returns the pre-dispatch `ReceiveMessagesProofInfo`. + fn receive_messages_proof_info(&self) -> &ReceiveMessagesProofInfo { + match self { + Self::AllFinalityAndDelivery(_, _, info) => info, + Self::ParachainFinalityAndDelivery(_, info) => info, + Self::Delivery(info) => info, + } + } +} + +/// Signed extension that refunds a relayer for new messages coming from a parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and @@ -86,29 +184,29 @@ where /// /// Extension does not refund transaction tip due to security reasons. #[derive( + DefaultNoBound, CloneNoBound, Decode, - DefaultNoBound, Encode, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, )] -#[scale_info(skip_type_params(RT, GI, PI, MI, PID, LID, FEE))] -pub struct RefundRelayerForMessagesFromParachain( - PhantomData<(RT, GI, PI, MI, PID, LID, FEE)>, +#[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Id))] +pub struct RefundBridgedParachainMessages( + PhantomData<(Runtime, Para, Msgs, Refund, Id)>, ); -impl - RefundRelayerForMessagesFromParachain +impl + RefundBridgedParachainMessages where - R: UtilityConfig>, - CallOf: IsSubType, R>>, + Runtime: UtilityConfig>, + CallOf: IsSubType, Runtime>>, { - fn expand_call<'a>(&self, call: &'a CallOf) -> Option>> { + fn expand_call<'a>(&self, call: &'a CallOf) -> Option>> { let calls = match call.is_sub_type() { - Some(UtilityCall::::batch_all { ref calls }) => { + Some(UtilityCall::::batch_all { ref calls }) => { if calls.len() > 3 { return None } @@ -123,71 +221,30 @@ where } } -/// Data that is crafted in `pre_dispatch` method and used at `post_dispatch`. -#[derive(PartialEq)] -#[cfg_attr(test, derive(Debug))] -pub struct PreDispatchData { - /// Transaction submitter (relayer) account. - relayer: AccountId, - /// Type of the call. - pub call_type: CallType, -} - -/// Type of the call that the extension recognizes. -#[derive(Clone, Copy, PartialEq, RuntimeDebugNoBound)] -pub enum CallType { - /// Relay chain finality + parachain finality + message delivery calls. - AllFinalityAndDelivery(RelayBlockNumber, SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), - /// Parachain finality + message delivery calls. - ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), - /// Standalone message delivery call. - Delivery(ReceiveMessagesProofInfo), -} - -impl CallType { - /// Returns the pre-dispatch messages pallet state. - fn receive_messages_proof_info(&self) -> ReceiveMessagesProofInfo { - match *self { - Self::AllFinalityAndDelivery(_, _, info) => info, - Self::ParachainFinalityAndDelivery(_, info) => info, - Self::Delivery(info) => info, - } - } -} - -// without this typedef rustfmt fails with internal err -type BalanceOf = - <::OnChargeTransaction as OnChargeTransaction>::Balance; -type CallOf = ::RuntimeCall; - -impl SignedExtension - for RefundRelayerForMessagesFromParachain +impl SignedExtension + for RefundBridgedParachainMessages where - R: 'static - + Send - + Sync - + UtilityConfig> - + BoundedBridgeGrandpaConfig - + ParachainsConfig - + MessagesConfig + Self: 'static + Send + Sync, + Runtime: UtilityConfig> + + BoundedBridgeGrandpaConfig + + ParachainsConfig + + MessagesConfig + RelayersConfig, - GI: 'static + Send + Sync, - PI: 'static + Send + Sync, - MI: 'static + Send + Sync, - PID: 'static + Send + Sync + Get, - LID: 'static + Send + Sync + Get, - FEE: 'static + Send + Sync + TransactionFeeCalculation<::Reward>, - CallOf: Dispatchable - + IsSubType, R>> - + GrandpaCallSubType - + ParachainsCallSubType - + MessagesCallSubType, + Para: RefundableParachainId, + Msgs: RefundableMessagesLaneId, + Refund: RefundCalculator, + Id: StaticStrProvider, + CallOf: Dispatchable + + IsSubType, Runtime>> + + GrandpaCallSubType + + ParachainsCallSubType + + MessagesCallSubType, { - const IDENTIFIER: &'static str = "RefundRelayerForMessagesFromParachain"; - type AccountId = R::AccountId; - type Call = CallOf; + const IDENTIFIER: &'static str = Id::STR; + type AccountId = Runtime::AccountId; + type Call = CallOf; type AdditionalSigned = (); - type Pre = Option>; + type Pre = Option>; fn additional_signed(&self) -> Result<(), TransactionValidityError> { Ok(()) @@ -200,15 +257,12 @@ where _info: &DispatchInfoOf, _len: usize, ) -> TransactionValidity { - let calls = match self.expand_call(call) { - Some(calls) => calls, - None => return Ok(ValidTransaction::default()), - }; - - for call in calls { - call.check_obsolete_submit_finality_proof()?; - call.check_obsolete_submit_parachain_heads()?; - call.check_obsolete_receive_messages_proof()?; + if let Some(calls) = self.expand_call(call) { + for nested_call in calls { + nested_call.check_obsolete_submit_finality_proof()?; + nested_call.check_obsolete_submit_parachain_heads()?; + nested_call.check_obsolete_receive_messages_proof()?; + } } Ok(ValidTransaction::default()) @@ -225,35 +279,35 @@ where self.validate(who, call, info, len).map(drop)?; // Try to check if the tx matches one of types we support. - let parse_call_type = || { + let parse_call = || { let mut calls = self.expand_call(call)?.into_iter(); match calls.len() { - 3 => Some(CallType::AllFinalityAndDelivery( + 3 => Some(CallInfo::AllFinalityAndDelivery( calls.next()?.submit_finality_proof_info()?, - calls.next()?.submit_parachain_heads_info_for(PID::get())?, - calls.next()?.receive_messages_proof_info_for(LID::get())?, + calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, + calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, )), - 2 => Some(CallType::ParachainFinalityAndDelivery( - calls.next()?.submit_parachain_heads_info_for(PID::get())?, - calls.next()?.receive_messages_proof_info_for(LID::get())?, + 2 => Some(CallInfo::ParachainFinalityAndDelivery( + calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, + calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, )), - 1 => Some(CallType::Delivery( - calls.next()?.receive_messages_proof_info_for(LID::get())?, + 1 => Some(CallInfo::Delivery( + calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, )), _ => None, } }; - Ok(parse_call_type().map(|call_type| { + Ok(parse_call().map(|call_info| { log::trace!( target: "runtime::bridge", - "RefundRelayerForMessagesFromParachain from parachain {} via {:?} \ - parsed bridge transaction in pre-dispatch: {:?}", - PID::get(), - LID::get(), - call_type, + "{} from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + call_info, ); - PreDispatchData { relayer: who.clone(), call_type } + PreDispatchData { relayer: who.clone(), call_info } })) } @@ -270,14 +324,14 @@ where } // We don't refund anything for transactions that we don't support. - let (relayer, call_type) = match pre { - Some(Some(pre)) => (pre.relayer, pre.call_type), + let (relayer, call_info) = match pre { + Some(Some(pre)) => (pre.relayer, pre.call_info), _ => return Ok(()), }; // check if relay chain state has been updated - if let CallType::AllFinalityAndDelivery(relay_block_number, _, _) = call_type { - if !SubmitFinalityProofHelper::::was_successful(relay_block_number) { + if let Some(relay_block_number) = call_info.submit_finality_proof_info() { + if !SubmitFinalityProofHelper::::was_successful(relay_block_number) { // we only refund relayer if all calls have updated chain state return Ok(()) } @@ -291,44 +345,44 @@ where } // check if parachain state has been updated - match call_type { - CallType::AllFinalityAndDelivery(_, parachain_heads_info, _) | - CallType::ParachainFinalityAndDelivery(parachain_heads_info, _) => { - if !SubmitParachainHeadsHelper::::was_successful(¶chain_heads_info) { - // we only refund relayer if all calls have updated chain state - return Ok(()) - } - }, - _ => (), + if let Some(para_proof_info) = call_info.submit_parachain_heads_info() { + if !SubmitParachainHeadsHelper::::was_successful( + para_proof_info, + ) { + // we only refund relayer if all calls have updated chain state + return Ok(()) + } } // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that // it contained. If this happens, we consider the transaction "helpful" and refund it. - let messages_proof_info = call_type.receive_messages_proof_info(); - if !ReceiveMessagesProofHelper::::was_partially_successful(&messages_proof_info) { + let msgs_proof_info = call_info.receive_messages_proof_info(); + if !ReceiveMessagesProofHelper::::was_partially_successful( + msgs_proof_info, + ) { return Ok(()) } // regarding the tip - refund that happens here (at this side of the bridge) isn't the whole // relayer compensation. He'll receive some amount at the other side of the bridge. It shall - // (in theory) cover the tip here. Otherwise, if we'll be compensating tip here, some + // (in theory) cover the tip there. Otherwise, if we'll be compensating tip here, some // malicious relayer may use huge tips, effectively depleting account that pay rewards. The // cost of this attack is nothing. Hence we use zero as tip here. let tip = Zero::zero(); - // compute the relayer reward - let reward = FEE::compute_fee(info, post_info, len, tip); - - // finally - register reward in relayers pallet - RelayersPallet::::register_relayer_reward(LID::get(), &relayer, reward); + // compute the relayer refund + let refund = Refund::compute_refund(info, post_info, len, tip); + // finally - register refund in relayers pallet + RelayersPallet::::register_relayer_reward(Msgs::Id::get(), &relayer, refund); log::trace!( target: "runtime::bridge", - "RefundRelayerForMessagesFromParachain from parachain {} via {:?} has registered {:?} reward: {:?}", - PID::get(), - LID::get(), + "{} from parachain {} via {:?} has registered reward: {:?} for {:?}", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + refund, relayer, - reward, ); Ok(()) @@ -353,18 +407,17 @@ mod tests { }; parameter_types! { - pub TestParachain: u32 = 1000; + TestParachain: u32 = 1000; pub TestLaneId: LaneId = TEST_LANE_ID; } - type TestExtension = RefundRelayerForMessagesFromParachain< - TestRuntime, - (), - (), - (), - TestParachain, - TestLaneId, + bp_runtime::generate_static_str_provider!(TestExtension); + type TestExtension = RefundBridgedParachainMessages< TestRuntime, + RefundableParachain<(), TestParachain>, + RefundableMessagesLane<(), TestLaneId>, + ActualFeeRefund, + StrTestExtension, >; fn relayer_account_at_this_chain() -> ThisChainAccountId { @@ -470,7 +523,7 @@ mod tests { fn all_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_type: CallType::AllFinalityAndDelivery( + call_info: CallInfo::AllFinalityAndDelivery( 200, SubmitParachainHeadsInfo { at_relay_block_number: 200, @@ -489,7 +542,7 @@ mod tests { fn parachain_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_type: CallType::ParachainFinalityAndDelivery( + call_info: CallInfo::ParachainFinalityAndDelivery( SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), @@ -507,7 +560,7 @@ mod tests { fn delivery_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_type: CallType::Delivery(ReceiveMessagesProofInfo { + call_info: CallInfo::Delivery(ReceiveMessagesProofInfo { lane_id: TEST_LANE_ID, best_proof_nonce: 200, best_stored_nonce: 100, @@ -520,14 +573,14 @@ mod tests { } fn run_validate(call: RuntimeCall) -> TransactionValidity { - let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData); + let extension: TestExtension = RefundBridgedParachainMessages(PhantomData); extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { - let extension: TestExtension = RefundRelayerForMessagesFromParachain(PhantomData); + let extension: TestExtension = RefundBridgedParachainMessages(PhantomData); extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } diff --git a/modules/parachains/src/call_ext.rs b/modules/parachains/src/call_ext.rs index 41649336579e0..5aed9e80ba0eb 100644 --- a/modules/parachains/src/call_ext.rs +++ b/modules/parachains/src/call_ext.rs @@ -17,14 +17,11 @@ use crate::{Config, Pallet, RelayBlockNumber}; use bp_parachains::BestParaHeadHash; use bp_polkadot_core::parachains::{ParaHash, ParaId}; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; -use sp_runtime::{ - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, - RuntimeDebug, -}; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; +use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}; /// Info about a `SubmitParachainHeads` call which tries to update a single parachain. -#[derive(Copy, Clone, PartialEq, RuntimeDebug)] +#[derive(PartialEq, RuntimeDebug)] pub struct SubmitParachainHeadsInfo { pub at_relay_block_number: RelayBlockNumber, pub para_id: ParaId, diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 75151ccb72372..0121b4ab84eb2 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -507,6 +507,24 @@ impl WeightExtraOps for Weight { } } +/// Trait that provides a static `str`. +pub trait StaticStrProvider { + const STR: &'static str; +} + +#[macro_export] +macro_rules! generate_static_str_provider { + ($str:expr) => { + $crate::paste::item! { + pub struct []; + + impl $crate::StaticStrProvider for [] { + const STR: &'static str = stringify!($str); + } + } + }; +} + #[cfg(test)] mod tests { use super::*; @@ -531,4 +549,10 @@ mod tests { ), ); } + + #[test] + fn generate_static_str_provider_works() { + generate_static_str_provider!(Test); + assert_eq!(StrTest::STR, "Test"); + } } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 711b4f32cc632..4c4c1370a6a56 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -95,7 +95,7 @@ impl ChainWithTransactions for Millau { frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), millau_runtime::BridgeRejectObsoleteHeadersAndMessages, - millau_runtime::BridgeRefundRialtoParachainRelayers::default(), + millau_runtime::BridgeRefundRialtoParachainMessages::default(), ), ( (), From 16e91c782b3a89ab2f62d10f3af356bf43eaa4e5 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 21 Feb 2023 12:22:59 +0100 Subject: [PATCH 0952/1210] Rewards refund for relaying BridgeHubRococo/BridgeHubWococo (#1894) * Rewards refund for relaying BridgeHubRococo/BridgeHubWococo * spellcheck + clippy * RefundBridgedParachainMessages move to bp-runtime * Dedicated RewardingBridgeSignedExtra for Rococo/Wococo shared runtime with two instances of `RefundBridgedParachainMessages` * RefundBridgedParachainMessages with Tuple support for multiple * Fix additional_signed * revert fix * Refactor to `RefundBridgedParachainMessagesSchema` * removed unused deps --- .../chain-bridge-hub-cumulus/Cargo.toml | 2 + .../chain-bridge-hub-cumulus/src/lib.rs | 73 ++++++++++++++++++- primitives/runtime/src/extensions.rs | 9 +++ relays/client-bridge-hub-rococo/src/lib.rs | 13 +++- .../src/runtime_wrapper.rs | 9 ++- relays/client-bridge-hub-wococo/src/lib.rs | 14 +++- .../src/runtime_wrapper.rs | 7 +- 7 files changed, 111 insertions(+), 16 deletions(-) diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index cb7f55d33619b..2bbe3d029a37a 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies @@ -27,6 +28,7 @@ default = ["std"] std = [ "bp-polkadot-core/std", "bp-messages/std", + "bp-runtime/std", "frame-system/std", "frame-support/std", "sp-api/std", diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index dfa5afe2a5b8d..3a05cb48b3b87 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -19,8 +19,8 @@ use bp_messages::*; pub use bp_polkadot_core::{ AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, - Hashing, Header, Index, Nonce, Perbill, PolkadotSignedExtension, Signature, SignedBlock, - UncheckedExtrinsic, EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, + Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, + EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, }; use frame_support::{ dispatch::DispatchClass, @@ -124,3 +124,72 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane for Cumulus-based parachains. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; + +/// Module with rewarding bridge signed extension support +pub mod rewarding_bridge_signed_extension { + use super::*; + use bp_polkadot_core::PolkadotLike; + use bp_runtime::extensions::*; + + type RewardingBridgeSignedExtra = ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + RefundBridgedParachainMessagesSchema, + ); + + /// The signed extension used by Cumulus and Cumulus-like parachain with bridging and rewarding. + pub type RewardingBridgeSignedExtension = GenericSignedExtension; + + pub fn from_params( + spec_version: u32, + transaction_version: u32, + era: bp_runtime::TransactionEraOf, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + ) -> RewardingBridgeSignedExtension { + GenericSignedExtension::::new( + ( + (), // non-zero sender + (), // spec version + (), // tx version + (), // genesis + era.frame_era(), // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + tip.into(), // transaction payment / tip (compact encoding) + (), // bridge reject obsolete headers and msgs + (), // bridge register reward to relayer for message passing + ), + Some(( + (), + spec_version, + transaction_version, + genesis_hash, + era.signed_payload(genesis_hash), + (), + (), + (), + (), + (), + )), + ) + } + + /// Return signer nonce, used to craft transaction. + pub fn nonce(sign_ext: &RewardingBridgeSignedExtension) -> Nonce { + sign_ext.payload.5.into() + } + + /// Return transaction tip. + pub fn tip(sign_ext: &RewardingBridgeSignedExtension) -> Balance { + sign_ext.payload.7.into() + } +} diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index eefe10f705757..ea51d03741c63 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -76,6 +76,15 @@ pub type ChargeTransactionPayment = GenericSignedExtensionSchema; +/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`. +/// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as +/// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), +/// ())` is the same. So runtime can contains any kind of tuple: +/// `(BridgeRefundBridgeHubRococoMessages)` +/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWococoMessages)` +/// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` +pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; + #[impl_for_tuples(1, 12)] impl SignedExtensionSchema for Tuple { for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index d2e421423a5a8..b6b844021e0c0 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -17,7 +17,6 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. use bp_bridge_hub_rococo::AVERAGE_BLOCK_INTERVAL; -use bp_bridge_hub_wococo::PolkadotSignedExtension; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -72,7 +71,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_rococo::SignedExtension::from_params( + runtime::rewarding_bridge_signed_extension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -86,7 +85,7 @@ impl ChainWithTransactions for BridgeHubRococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(bp_bridge_hub_rococo::UncheckedExtrinsic::new_signed( + Ok(runtime::UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -109,7 +108,13 @@ impl ChainWithTransactions for BridgeHubRococo { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + Some( + UnsignedTransaction::new( + tx.function, + runtime::rewarding_bridge_signed_extension::nonce(extra), + ) + .tip(runtime::rewarding_bridge_signed_extension::tip(extra)), + ) } } diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index fc945d8c95072..711306b0127fe 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -14,21 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// TODO: join with primitives do we need this here or move to the primitives? - //! Types that are specific to the BridgeHubRococo runtime. use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_bridge_hub_rococo::SignedExtension; +pub use bp_bridge_hub_rococo::rewarding_bridge_signed_extension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubRococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic< + Call, + rewarding_bridge_signed_extension::RewardingBridgeSignedExtension, +>; // The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 2c211ae86cf44..a466df3549510 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_bridge_hub_wococo::{PolkadotSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_wococo::AVERAGE_BLOCK_INTERVAL; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -71,7 +71,7 @@ impl ChainWithTransactions for BridgeHubWococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_wococo::SignedExtension::from_params( + runtime::rewarding_bridge_signed_extension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -85,7 +85,7 @@ impl ChainWithTransactions for BridgeHubWococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(bp_bridge_hub_wococo::UncheckedExtrinsic::new_signed( + Ok(runtime::UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -108,7 +108,13 @@ impl ChainWithTransactions for BridgeHubWococo { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + Some( + UnsignedTransaction::new( + tx.function, + runtime::rewarding_bridge_signed_extension::nonce(extra), + ) + .tip(runtime::rewarding_bridge_signed_extension::tip(extra)), + ) } } diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index c16e7d1a45bce..13fb1a7e6ab4b 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -19,14 +19,17 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_bridge_hub_wococo::SignedExtension; +pub use bp_bridge_hub_wococo::rewarding_bridge_signed_extension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubWococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic< + Call, + rewarding_bridge_signed_extension::RewardingBridgeSignedExtension, +>; // The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; From 412bf85047cf2d75b670e9b14589337e952881ac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Feb 2023 09:51:11 +0300 Subject: [PATCH 0953/1210] Weight+size limits for bridge GRANDPA pallet calls (#1882) * weight+size limits for bridge GRANDPA pallet calls * continue * fixed all tests * some changes to refund computations * post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight * - dup code * do not return Pays::No if call is above weight/size limits * relayer_pays_tx_fee_when_submitting_huge_mandatory_header and relayer_pays_tx_fee_when_submitting_justification_with_long_ancestry_votes * clippy * fmt * clippy * small change in docs * fixed GRANDPA-limits constants for Polkadot-like chains * clippy * clippy + spelling * Update primitives/polkadot-core/src/lib.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * reverted unnecessary change * GrandpaJustification::max_reasonable_size --------- Co-authored-by: Adrian Catangiu --- .../src/refund_relayer_extension.rs | 98 +++++++++- modules/grandpa/src/call_ext.rs | 172 ++++++++++++++++-- modules/grandpa/src/lib.rs | 79 +++++++- modules/grandpa/src/storage_types.rs | 10 +- modules/parachains/src/call_ext.rs | 5 +- modules/parachains/src/mock.rs | 4 +- primitives/header-chain/src/justification.rs | 88 +++++++-- .../tests/implementation_match.rs | 134 +++++++++++--- .../header-chain/tests/justification.rs | 13 +- primitives/polkadot-core/src/lib.rs | 29 +-- 10 files changed, 540 insertions(+), 92 deletions(-) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 9efeedf24dd59..df4eae6f7370b 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -28,9 +28,12 @@ use codec::{Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, traits::IsSubType, + weights::Weight, CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; -use pallet_bridge_grandpa::{CallSubType as GrandpaCallSubType, SubmitFinalityProofHelper}; +use pallet_bridge_grandpa::{ + CallSubType as GrandpaCallSubType, SubmitFinalityProofHelper, SubmitFinalityProofInfo, +}; use pallet_bridge_messages::Config as MessagesConfig; use pallet_bridge_parachains::{ BoundedBridgeGrandpaConfig, CallSubType as ParachainsCallSubType, Config as ParachainsConfig, @@ -140,7 +143,11 @@ pub struct PreDispatchData { #[derive(RuntimeDebugNoBound, PartialEq)] pub enum CallInfo { /// Relay chain finality + parachain finality + message delivery calls. - AllFinalityAndDelivery(RelayBlockNumber, SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), + AllFinalityAndDelivery( + SubmitFinalityProofInfo, + SubmitParachainHeadsInfo, + ReceiveMessagesProofInfo, + ), /// Parachain finality + message delivery calls. ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), /// Standalone message delivery call. @@ -149,7 +156,7 @@ pub enum CallInfo { impl CallInfo { /// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call. - fn submit_finality_proof_info(&self) -> Option { + fn submit_finality_proof_info(&self) -> Option> { match *self { Self::AllFinalityAndDelivery(info, _, _) => Some(info), _ => None, @@ -318,6 +325,9 @@ where len: usize, result: &DispatchResult, ) -> Result<(), TransactionValidityError> { + let mut extra_weight = Weight::zero(); + let mut extra_size = 0; + // We don't refund anything if the transaction has failed. if result.is_err() { return Ok(()) @@ -330,8 +340,10 @@ where }; // check if relay chain state has been updated - if let Some(relay_block_number) = call_info.submit_finality_proof_info() { - if !SubmitFinalityProofHelper::::was_successful(relay_block_number) { + if let Some(finality_proof_info) = call_info.submit_finality_proof_info() { + if !SubmitFinalityProofHelper::::was_successful( + finality_proof_info.block_number, + ) { // we only refund relayer if all calls have updated chain state return Ok(()) } @@ -342,6 +354,11 @@ where // `utility.batchAll` transaction always requires payment. But in both cases we'll // refund relayer - either explicitly here, or using `Pays::No` if he's choosing // to submit dedicated transaction. + + // submitter has means to include extra weight/bytes in the `submit_finality_proof` + // call, so let's subtract extra weight/size to avoid refunding for this extra stuff + extra_weight = finality_proof_info.extra_weight; + extra_size = finality_proof_info.extra_size; } // check if parachain state has been updated @@ -370,8 +387,15 @@ where // cost of this attack is nothing. Hence we use zero as tip here. let tip = Zero::zero(); + // decrease post-dispatch weight/size using extra weight/size that we know now + let post_info_len = len.saturating_sub(extra_size as usize); + let mut post_info = *post_info; + post_info.actual_weight = + Some(post_info.actual_weight.unwrap_or(info.weight).saturating_sub(extra_weight)); + // compute the relayer refund - let refund = Refund::compute_refund(info, post_info, len, tip); + let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); + // finally - register refund in relayers pallet RelayersPallet::::register_relayer_reward(Msgs::Id::get(), &relayer, refund); @@ -397,9 +421,9 @@ mod tests { use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderId; - use bp_test_utils::make_default_justification; + use bp_test_utils::{make_default_justification, test_keyring}; use frame_support::{assert_storage_noop, parameter_types, weights::Weight}; - use pallet_bridge_grandpa::Call as GrandpaCall; + use pallet_bridge_grandpa::{Call as GrandpaCall, StoredAuthoritySet}; use pallet_bridge_messages::Call as MessagesCall; use pallet_bridge_parachains::{Call as ParachainsCall, RelayBlockHash}; use sp_runtime::{ @@ -434,7 +458,11 @@ mod tests { parachain_head_hash: ParaHash, best_delivered_message: MessageNonce, ) { + let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect(); let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); + pallet_bridge_grandpa::CurrentAuthoritySet::::put( + StoredAuthoritySet::try_new(authorities, 0).unwrap(), + ); pallet_bridge_grandpa::BestFinalized::::put(best_relay_header); let para_id = ParaId(TestParachain::get()); @@ -524,7 +552,11 @@ mod tests { PreDispatchData { relayer: relayer_account_at_this_chain(), call_info: CallInfo::AllFinalityAndDelivery( - 200, + SubmitFinalityProofInfo { + block_number: 200, + extra_weight: Weight::zero(), + extra_size: 0, + }, SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), @@ -823,6 +855,54 @@ mod tests { }); } + #[test] + fn post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight() { + run_test(|| { + initialize_environment(200, 200, [1u8; 32].into(), 200); + + let mut dispatch_info = dispatch_info(); + dispatch_info.weight = Weight::from_ref_time( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2, + ); + + // without any size/weight refund: we expect regular reward + let pre_dispatch_data = all_finality_pre_dispatch_data(); + let regular_reward = expected_reward(); + run_post_dispatch(Some(pre_dispatch_data), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + TestLaneId::get() + ), + Some(regular_reward), + ); + + // now repeat the same with size+weight refund: we expect smaller reward + let mut pre_dispatch_data = all_finality_pre_dispatch_data(); + match pre_dispatch_data.call_info { + CallInfo::AllFinalityAndDelivery(ref mut info, ..) => { + info.extra_weight.set_ref_time( + frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + ); + info.extra_size = 32; + }, + _ => unreachable!(), + } + run_post_dispatch(Some(pre_dispatch_data), Ok(())); + let reward_after_two_calls = RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + TestLaneId::get(), + ) + .unwrap(); + assert!( + reward_after_two_calls < 2 * regular_reward, + "{} must be < 2 * {}", + reward_after_two_calls, + 2 * regular_reward, + ); + }); + } + #[test] fn post_dispatch_refunds_relayer_in_all_finality_batch() { run_test(|| { diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index 42c276f5f6c2c..b57aebb1ac1e7 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -14,17 +14,46 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{Config, Error, Pallet}; +use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet}; +use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa}; use bp_runtime::BlockNumberOf; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use codec::Encode; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight, RuntimeDebug}; use sp_runtime::{ - traits::Header, + traits::{Header, Zero}, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + SaturatedConversion, }; +/// Info about a `SubmitParachainHeads` call which tries to update a single parachain. +#[derive(Copy, Clone, PartialEq, RuntimeDebug)] +pub struct SubmitFinalityProofInfo { + /// Number of the finality target. + pub block_number: N, + /// Extra weight that we assume is included in the call. + /// + /// We have some assumptions about headers and justifications of the bridged chain. + /// We know that if our assumptions are correct, then the call must not have the + /// weight above some limit. The fee paid for weight above that limit, is never refunded. + pub extra_weight: Weight, + /// Extra size (in bytes) that we assume are included in the call. + /// + /// We have some assumptions about headers and justifications of the bridged chain. + /// We know that if our assumptions are correct, then the call must not have the + /// weight above some limit. The fee paid for bytes above that limit, is never refunded. + pub extra_size: u32, +} + +impl SubmitFinalityProofInfo { + /// Returns `true` if call size/weight is below our estimations for regular calls. + pub fn fits_limits(&self) -> bool { + self.extra_weight.is_zero() && self.extra_size.is_zero() + } +} + /// Helper struct that provides methods for working with the `SubmitFinalityProof` call. pub struct SubmitFinalityProofHelper, I: 'static> { - pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, + _phantom_data: sp_std::marker::PhantomData<(T, I)>, } impl, I: 'static> SubmitFinalityProofHelper { @@ -69,12 +98,17 @@ impl, I: 'static> SubmitFinalityProofHelper { pub trait CallSubType, I: 'static>: IsSubType, T>> { - /// Extract the finality target from a `SubmitParachainHeads` call. - fn submit_finality_proof_info(&self) -> Option> { - if let Some(crate::Call::::submit_finality_proof { finality_target, .. }) = + /// Extract finality proof info from a runtime call. + fn submit_finality_proof_info( + &self, + ) -> Option>> { + if let Some(crate::Call::::submit_finality_proof { finality_target, justification }) = self.is_sub_type() { - return Some(*finality_target.number()) + return Some(submit_finality_proof_info_from_args::( + finality_target, + justification, + )) } None @@ -92,7 +126,7 @@ pub trait CallSubType, I: 'static>: _ => return Ok(ValidTransaction::default()), }; - match SubmitFinalityProofHelper::::check_obsolete(finality_target) { + match SubmitFinalityProofHelper::::check_obsolete(finality_target.block_number) { Ok(_) => Ok(ValidTransaction::default()), Err(Error::::OldHeader) => InvalidTransaction::Stale.into(), Err(_) => InvalidTransaction::Call.into(), @@ -105,15 +139,66 @@ impl, I: 'static> CallSubType for T::RuntimeCall where { } +/// Extract finality proof info from the submitted header and justification. +pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( + finality_target: &BridgedHeader, + justification: &GrandpaJustification>, +) -> SubmitFinalityProofInfo> { + let block_number = *finality_target.number(); + + // the `submit_finality_proof` call will reject justifications with invalid, duplicate, + // unknown and extra signatures. It'll also reject justifications with less than necessary + // signatures. So we do not care about extra weight because of additional signatures here. + let precommits_len = justification.commit.precommits.len().saturated_into(); + let required_precommits = precommits_len; + + // We do care about extra weight because of more-than-expected headers in the votes + // ancestries. But we have problems computing extra weight for additional headers (weight of + // additional header is too small, so that our benchmarks aren't detecting that). So if there + // are more than expected headers in votes ancestries, we will treat the whole call weight + // as an extra weight. + let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); + let extra_weight = + if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY { + T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) + } else { + Weight::zero() + }; + + // we can estimate extra call size easily, without any additional significant overhead + let actual_call_size: u32 = finality_target + .encoded_size() + .saturating_add(justification.encoded_size()) + .saturated_into(); + let max_expected_call_size = max_expected_call_size::(required_precommits); + let extra_size = actual_call_size.saturating_sub(max_expected_call_size); + + SubmitFinalityProofInfo { block_number, extra_weight, extra_size } +} + +/// Returns maximal expected size of `submit_finality_proof` call arguments. +fn max_expected_call_size, I: 'static>(required_precommits: u32) -> u32 { + let max_expected_justification_size = + GrandpaJustification::max_reasonable_size::(required_precommits); + + // call arguments are header and justification + T::BridgedChain::MAX_HEADER_SIZE.saturating_add(max_expected_justification_size) +} + #[cfg(test)] mod tests { use crate::{ call_ext::CallSubType, - mock::{run_test, test_header, RuntimeCall, TestNumber, TestRuntime}, - BestFinalized, + mock::{run_test, test_header, RuntimeCall, TestBridgedChain, TestNumber, TestRuntime}, + BestFinalized, Config, WeightInfo, }; + use bp_header_chain::ChainWithGrandpa; use bp_runtime::HeaderId; - use bp_test_utils::make_default_justification; + use bp_test_utils::{ + make_default_justification, make_justification_for_header, JustificationGeneratorParams, + }; + use frame_support::weights::Weight; + use sp_runtime::{testing::DigestItem, traits::Header as _, SaturatedConversion}; fn validate_block_submit(num: TestNumber) -> bool { let bridge_grandpa_call = crate::Call::::submit_finality_proof { @@ -160,4 +245,67 @@ mod tests { assert!(validate_block_submit(15)); }); } + + #[test] + fn extension_returns_correct_extra_size_if_call_arguments_are_too_large() { + // when call arguments are below our limit => no refund + let small_finality_target = test_header(1); + let justification_params = JustificationGeneratorParams { + header: small_finality_target.clone(), + ..Default::default() + }; + let small_justification = make_justification_for_header(justification_params); + let small_call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + finality_target: Box::new(small_finality_target), + justification: small_justification, + }); + assert_eq!(small_call.submit_finality_proof_info().unwrap().extra_size, 0); + + // when call arguments are too large => partial refund + let mut large_finality_target = test_header(1); + large_finality_target + .digest_mut() + .push(DigestItem::Other(vec![42u8; 1024 * 1024])); + let justification_params = JustificationGeneratorParams { + header: large_finality_target.clone(), + ..Default::default() + }; + let large_justification = make_justification_for_header(justification_params); + let large_call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + finality_target: Box::new(large_finality_target), + justification: large_justification, + }); + assert_ne!(large_call.submit_finality_proof_info().unwrap().extra_size, 0); + } + + #[test] + fn extension_returns_correct_extra_weight_if_there_are_too_many_headers_in_votes_ancestry() { + let finality_target = test_header(1); + let mut justification_params = JustificationGeneratorParams { + header: finality_target.clone(), + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, + ..Default::default() + }; + + // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY` headers => no refund + let justification = make_justification_for_header(justification_params.clone()); + let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + finality_target: Box::new(finality_target.clone()), + justification, + }); + assert_eq!(call.submit_finality_proof_info().unwrap().extra_weight, Weight::zero()); + + // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + 1` headers => full refund + justification_params.ancestors += 1; + let justification = make_justification_for_header(justification_params); + let call_weight = ::WeightInfo::submit_finality_proof( + justification.commit.precommits.len().saturated_into(), + justification.votes_ancestries.len().saturated_into(), + ); + let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + finality_target: Box::new(finality_target), + justification, + }); + assert_eq!(call.submit_finality_proof_info().unwrap().extra_weight, call_weight); + } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index b11da53f7b3b7..e94d91a5c16a2 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -36,7 +36,7 @@ // Runtime-generated enums #![allow(clippy::large_enum_variant)] -use storage_types::StoredAuthoritySet; +pub use storage_types::StoredAuthoritySet; use bp_header_chain::{ justification::GrandpaJustification, ChainWithGrandpa, HeaderChain, InitializationData, @@ -180,6 +180,9 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; + let may_refund_call_fee = is_authorities_change_enacted && + submit_finality_proof_info_from_args::(&*finality_target, &justification) + .fits_limits(); >::mutate(|count| *count += 1); insert_header::(*finality_target, hash); log::info!( @@ -193,8 +196,10 @@ pub mod pallet { // // We don't want to charge extra costs for mandatory operations. So relayer is not // paying fee for mandatory headers import transactions. - let is_mandatory_header = is_authorities_change_enacted; - let pays_fee = if is_mandatory_header { Pays::No } else { Pays::Yes }; + // + // If size/weight of the call is exceeds our estimated limits, the relayer still needs + // to pay for the transaction. + let pays_fee = if may_refund_call_fee { Pays::No } else { Pays::Yes }; // the proof size component of the call weight assumes that there are // `MaxBridgedAuthorities` in the `CurrentAuthoritySet` (we use `MaxEncodedLen` @@ -313,7 +318,7 @@ pub mod pallet { /// The current GRANDPA Authority set. #[pallet::storage] - pub(super) type CurrentAuthoritySet, I: 'static = ()> = + pub type CurrentAuthoritySet, I: 'static = ()> = StorageValue<_, StoredAuthoritySet, ValueQuery>; /// Optional pallet owner. @@ -504,7 +509,7 @@ pub mod pallet { init_params; let authority_set_length = authority_list.len(); let authority_set = StoredAuthoritySet::::try_new(authority_list, set_id) - .map_err(|_| { + .map_err(|e| { log::error!( target: LOG_TARGET, "Failed to initialize bridge. Number of authorities in the set {} is larger than the configured value {}", @@ -512,7 +517,7 @@ pub mod pallet { T::BridgedChain::MAX_AUTHORITIES_COUNT, ); - Error::TooManyAuthoritiesInSet + e })?; let initial_hash = header.hash(); @@ -630,8 +635,8 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader mod tests { use super::*; use crate::mock::{ - run_test, test_header, RuntimeOrigin, TestHeader, TestNumber, TestRuntime, - MAX_BRIDGED_AUTHORITIES, + run_test, test_header, RuntimeOrigin, TestBridgedChain, TestHeader, TestNumber, + TestRuntime, MAX_BRIDGED_AUTHORITIES, }; use bp_header_chain::BridgeGrandpaCall; use bp_runtime::BasicOperatingMode; @@ -965,6 +970,64 @@ mod tests { }) } + #[test] + fn relayer_pays_tx_fee_when_submitting_huge_mandatory_header() { + run_test(|| { + initialize_substrate_bridge(); + + // let's prepare a huge authorities change header, which is definitely above size limits + let mut header = test_header(2); + header.digest = change_log(0); + header.digest.push(DigestItem::Other(vec![42u8; 1024 * 1024])); + let justification = make_default_justification(&header); + + // without large digest item ^^^ the relayer would have paid zero transaction fee + // (`Pays::No`) + let result = Pallet::::submit_finality_proof( + RuntimeOrigin::signed(1), + Box::new(header.clone()), + justification, + ); + assert_ok!(result); + assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes); + + // Make sure that our header is the best finalized + assert_eq!(>::get().unwrap().1, header.hash()); + assert!(>::contains_key(header.hash())); + }) + } + + #[test] + fn relayer_pays_tx_fee_when_submitting_justification_with_long_ancestry_votes() { + run_test(|| { + initialize_substrate_bridge(); + + // let's prepare a huge authorities change header, which is definitely above weight + // limits + let mut header = test_header(2); + header.digest = change_log(0); + let justification = make_justification_for_header(JustificationGeneratorParams { + header: header.clone(), + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + 1, + ..Default::default() + }); + + // without many headers in votes ancestries ^^^ the relayer would have paid zero + // transaction fee (`Pays::No`) + let result = Pallet::::submit_finality_proof( + RuntimeOrigin::signed(1), + Box::new(header.clone()), + justification, + ); + assert_ok!(result); + assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes); + + // Make sure that our header is the best finalized + assert_eq!(>::get().unwrap().1, header.hash()); + assert!(>::contains_key(header.hash())); + }) + } + #[test] fn importing_header_rejects_header_with_scheduled_change_delay() { run_test(|| { diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index 918c131289c5b..d674f1a7b0ad6 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -16,7 +16,7 @@ //! Wrappers for public types that are implementing `MaxEncodedLen` -use crate::Config; +use crate::{Config, Error}; use bp_header_chain::{AuthoritySet, ChainWithGrandpa}; use codec::{Decode, Encode, MaxEncodedLen}; @@ -52,8 +52,12 @@ impl, I: 'static> StoredAuthoritySet { /// Try to create a new bounded GRANDPA Authority Set from unbounded list. /// /// Returns error if number of authorities in the provided list is too large. - pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result { - Ok(Self { authorities: TryFrom::try_from(authorities).map_err(drop)?, set_id }) + pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result> { + Ok(Self { + authorities: TryFrom::try_from(authorities) + .map_err(|_| Error::TooManyAuthoritiesInSet)?, + set_id, + }) } /// Returns number of bytes that may be subtracted from the PoV component of diff --git a/modules/parachains/src/call_ext.rs b/modules/parachains/src/call_ext.rs index 5aed9e80ba0eb..ee3770146c260 100644 --- a/modules/parachains/src/call_ext.rs +++ b/modules/parachains/src/call_ext.rs @@ -23,14 +23,17 @@ use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, /// Info about a `SubmitParachainHeads` call which tries to update a single parachain. #[derive(PartialEq, RuntimeDebug)] pub struct SubmitParachainHeadsInfo { + /// Number of the finalized relay block that has been used to prove parachain finality. pub at_relay_block_number: RelayBlockNumber, + /// Parachain identifier. pub para_id: ParaId, + /// Hash of the bundled parachain head. pub para_head_hash: ParaHash, } /// Helper struct that provides methods for working with the `SubmitParachainHeads` call. pub struct SubmitParachainHeadsHelper, I: 'static> { - pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, + _phantom_data: sp_std::marker::PhantomData<(T, I)>, } impl, I: 'static> SubmitParachainHeadsHelper { diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 0e8261f689915..aabcdcdd364ce 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -187,7 +187,7 @@ impl frame_system::Config for TestRuntime { type BlockLength = (); type SS58Prefix = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type MaxConsumers = ConstU32<16>; } parameter_types! { @@ -223,7 +223,7 @@ impl pallet_bridge_parachains::Config for TestRuntime { type ParasPalletName = ParasPalletName; type ParaStoredHeaderDataBuilder = (Parachain1, Parachain2, Parachain3, BigParachain); type HeadsToKeep = HeadsToKeep; - type MaxParaHeadDataSize = frame_support::traits::ConstU32; + type MaxParaHeadDataSize = ConstU32; } #[derive(Debug)] diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 43adc80125446..1e34f365621b9 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -19,12 +19,15 @@ //! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin //! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. -use codec::{Decode, Encode}; +use crate::ChainWithGrandpa; + +use bp_runtime::{BlockNumberOf, Chain, HashOf}; +use codec::{Decode, Encode, MaxEncodedLen}; use finality_grandpa::voter_set::VoterSet; use frame_support::RuntimeDebug; use scale_info::TypeInfo; use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; -use sp_runtime::traits::Header as HeaderT; +use sp_runtime::{traits::Header as HeaderT, SaturatedConversion}; use sp_std::{ collections::{btree_map::BTreeMap, btree_set::BTreeSet}, prelude::*, @@ -46,6 +49,43 @@ pub struct GrandpaJustification { pub votes_ancestries: Vec

, } +impl GrandpaJustification { + /// Returns reasonable size of justification using constants from the provided chain. + /// + /// An imprecise analogue of `MaxEncodedLen` implementation. We don't use it for + /// any precise calculations - that's just an estimation. + pub fn max_reasonable_size(required_precommits: u32) -> u32 + where + C: Chain
+ ChainWithGrandpa, + { + // we don't need precise results here - just estimations, so some details + // are removed from computations (e.g. bytes required to encode vector length) + + // structures in `finality_grandpa` crate are not implementing `MaxEncodedLength`, so + // here's our estimation for the `finality_grandpa::Commit` struct size + // + // precommit is: hash + number + // signed precommit is: precommit + signature (64b) + authority id + // commit is: hash + number + vec of signed precommits + let signed_precommit_size: u32 = BlockNumberOf::::max_encoded_len() + .saturating_add(HashOf::::max_encoded_len().saturated_into()) + .saturating_add(64) + .saturating_add(AuthorityId::max_encoded_len().saturated_into()) + .saturated_into(); + let max_expected_signed_commit_size = signed_precommit_size + .saturating_mul(required_precommits) + .saturating_add(BlockNumberOf::::max_encoded_len().saturated_into()) + .saturating_add(HashOf::::max_encoded_len().saturated_into()); + + // justification is a signed GRANDPA commit, `votes_ancestries` vector and round number + let max_expected_votes_ancestries_size = C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + .saturating_mul(C::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); + + 8u32.saturating_add(max_expected_signed_commit_size) + .saturating_add(max_expected_votes_ancestries_size) + } +} + impl crate::FinalityProof for GrandpaJustification { fn target_header_number(&self) -> H::Number { self.commit.target_number @@ -59,6 +99,12 @@ pub enum Error { JustificationDecode, /// Justification is finalizing unexpected header. InvalidJustificationTarget, + /// Justification contains redundant votes. + RedundantVotesInJustification, + /// Justification contains unknown authority precommit. + UnknownAuthorityVote, + /// Justification contains duplicate authority precommit. + DuplicateAuthorityVote, /// The authority has provided an invalid signature. InvalidAuthoritySignature, /// The justification contains precommit for header that is not a descendant of the commit @@ -124,7 +170,7 @@ where authorities_set_id, authorities_set, justification, - &mut (), + &mut StrictVerificationCallbacks, ) } @@ -138,6 +184,23 @@ trait VerificationCallbacks { fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; } +/// Verification callbacks that reject all unknown, duplicate or redundant votes. +struct StrictVerificationCallbacks; + +impl VerificationCallbacks for StrictVerificationCallbacks { + fn on_unkown_authority(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Err(Error::UnknownAuthorityVote) + } + + fn on_duplicate_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Err(Error::DuplicateAuthorityVote) + } + + fn on_redundant_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Err(Error::RedundantVotesInJustification) + } +} + /// Verification callbacks for justification optimization. struct OptimizationCallbacks(Vec); @@ -170,21 +233,6 @@ impl VerificationCallbacks for OptimizationCallbacks { } } -// this implementation will be removed in https://github.com/paritytech/parity-bridges-common/pull/1882 -impl VerificationCallbacks for () { - fn on_unkown_authority(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Ok(()) - } - - fn on_duplicate_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Ok(()) - } - - fn on_redundant_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Ok(()) - } -} - /// Verify that justification, that is generated by given authority set, finalizes given header. fn verify_justification_with_callbacks( finalized_target: (Header::Hash, Header::Number), @@ -206,11 +254,13 @@ where let mut signature_buffer = Vec::new(); let mut votes = BTreeSet::new(); let mut cumulative_weight = 0u64; + for (precommit_idx, signed) in justification.commit.precommits.iter().enumerate() { // if we have collected enough precommits, we probabably want to fail/remove extra // precommits - if cumulative_weight > threshold { + if cumulative_weight >= threshold { callbacks.on_redundant_authority_vote(precommit_idx)?; + continue } // authority must be in the set diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index aaa19d4b918bb..5d0fa35c37683 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -15,7 +15,8 @@ // along with Parity Bridges Common. If not, see . //! Tests inside this module are made to ensure that our custom justification verification -//! implementation works exactly as `fn finality_grandpa::validate_commit`. +//! implementation works similar to the [`finality_grandpa::validate_commit`] and explicitly +//! show where we behave different. //! //! Some of tests in this module may partially duplicate tests from `justification.rs`, //! but their purpose is different. @@ -23,7 +24,7 @@ use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; use bp_test_utils::{ header_id, make_justification_for_header, signed_precommit, test_header, Account, - JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, TEST_GRANDPA_SET_ID, + JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE, TEST_GRANDPA_SET_ID, }; use finality_grandpa::voter_set::VoterSet; use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; @@ -172,7 +173,42 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { } #[test] -fn same_result_when_justification_contains_duplicate_vote() { +fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_target() { + // just remove one authority from the minimal set and we shall not reach the threshold + let mut authorities_set = minimal_accounts_set(); + authorities_set.pop(); + let justification = make_justification_for_header(JustificationGeneratorParams { + header: test_header(1), + authorities: authorities_set, + ..Default::default() + }); + + // our implementation returns an error + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Err(Error::TooLowCumulativeWeight), + ); + // original implementation returns `Ok(validation_result)` + // with `validation_result.is_valid() == false`. + let result = finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .unwrap(); + + assert!(!result.is_valid()); +} + +// tests below are our differences with the original implementation + +#[test] +fn different_result_when_justification_contains_duplicate_vote() { let mut justification = make_justification_for_header(JustificationGeneratorParams { header: test_header(1), authorities: minimal_accounts_set(), @@ -181,10 +217,11 @@ fn same_result_when_justification_contains_duplicate_vote() { }); // the justification may contain exactly the same vote (i.e. same precommit and same signature) // multiple times && it isn't treated as an error by original implementation + let last_precommit = justification.commit.precommits.pop().unwrap(); justification.commit.precommits.push(justification.commit.precommits[0].clone()); - justification.commit.precommits.push(justification.commit.precommits[0].clone()); + justification.commit.precommits.push(last_precommit); - // our implementation succeeds + // our implementation fails assert_eq!( verify_justification::( header_id::(1), @@ -192,7 +229,7 @@ fn same_result_when_justification_contains_duplicate_vote() { &full_voter_set(), &justification, ), - Ok(()), + Err(Error::DuplicateAuthorityVote), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -207,7 +244,7 @@ fn same_result_when_justification_contains_duplicate_vote() { } #[test] -fn same_result_when_authority_equivocates_once_in_a_round() { +fn different_results_when_authority_equivocates_once_in_a_round() { let mut justification = make_justification_for_header(JustificationGeneratorParams { header: test_header(1), authorities: minimal_accounts_set(), @@ -216,14 +253,16 @@ fn same_result_when_authority_equivocates_once_in_a_round() { }); // the justification original implementation allows authority to submit two different // votes in a single round, of which only first is 'accepted' + let last_precommit = justification.commit.precommits.pop().unwrap(); justification.commit.precommits.push(signed_precommit::( &ALICE, header_id::(1), justification.round, TEST_GRANDPA_SET_ID, )); + justification.commit.precommits.push(last_precommit); - // our implementation succeeds + // our implementation fails assert_eq!( verify_justification::( header_id::(1), @@ -231,7 +270,7 @@ fn same_result_when_authority_equivocates_once_in_a_round() { &full_voter_set(), &justification, ), - Ok(()), + Err(Error::DuplicateAuthorityVote), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -246,7 +285,7 @@ fn same_result_when_authority_equivocates_once_in_a_round() { } #[test] -fn same_result_when_authority_equivocates_twice_in_a_round() { +fn different_results_when_authority_equivocates_twice_in_a_round() { let mut justification = make_justification_for_header(JustificationGeneratorParams { header: test_header(1), authorities: minimal_accounts_set(), @@ -259,6 +298,8 @@ fn same_result_when_authority_equivocates_twice_in_a_round() { // but there's also a code that prevents this from happening: // https://github.com/paritytech/finality-grandpa/blob/6aeea2d1159d0f418f0b86e70739f2130629ca09/src/round.rs#L287 // => so now we are also just ignoring all votes from the same authority, except the first one + let last_precommit = justification.commit.precommits.pop().unwrap(); + let prev_last_precommit = justification.commit.precommits.pop().unwrap(); justification.commit.precommits.push(signed_precommit::( &ALICE, header_id::(1), @@ -271,8 +312,10 @@ fn same_result_when_authority_equivocates_twice_in_a_round() { justification.round, TEST_GRANDPA_SET_ID, )); + justification.commit.precommits.push(last_precommit); + justification.commit.precommits.push(prev_last_precommit); - // our implementation succeeds + // our implementation fails assert_eq!( verify_justification::( header_id::(1), @@ -280,7 +323,7 @@ fn same_result_when_authority_equivocates_twice_in_a_round() { &full_voter_set(), &justification, ), - Ok(()), + Err(Error::DuplicateAuthorityVote), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -295,17 +338,23 @@ fn same_result_when_authority_equivocates_twice_in_a_round() { } #[test] -fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_target() { - // just remove one authority from the minimal set and we shall not reach the threshold - let mut authorities_set = minimal_accounts_set(); - authorities_set.pop(); - let justification = make_justification_for_header(JustificationGeneratorParams { +fn different_results_when_there_are_more_than_enough_votes() { + let mut justification = make_justification_for_header(JustificationGeneratorParams { header: test_header(1), - authorities: authorities_set, + authorities: minimal_accounts_set(), + ancestors: 0, ..Default::default() }); + // the reference implementation just keep verifying signatures even if we have + // collected enough votes. We are not + justification.commit.precommits.push(signed_precommit::( + &EVE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); - // our implementation returns an error + // our implementation fails assert_eq!( verify_justification::( header_id::(1), @@ -313,10 +362,10 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta &full_voter_set(), &justification, ), - Err(Error::TooLowCumulativeWeight), + Err(Error::RedundantVotesInJustification), ); // original implementation returns `Ok(validation_result)` - // with `validation_result.is_valid() == false`. + // with `validation_result.is_valid() == true`. let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), @@ -324,5 +373,46 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta ) .unwrap(); - assert!(!result.is_valid()); + assert!(result.is_valid()); +} + +#[test] +fn different_results_when_there_is_a_vote_of_unknown_authority() { + let mut justification = make_justification_for_header(JustificationGeneratorParams { + header: test_header(1), + authorities: minimal_accounts_set(), + ancestors: 0, + ..Default::default() + }); + // the reference implementation just keep verifying signatures even if we have + // collected enough votes. We are not + let last_precommit = justification.commit.precommits.pop().unwrap(); + justification.commit.precommits.push(signed_precommit::( + &FERDIE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + )); + justification.commit.precommits.push(last_precommit); + + // our implementation fails + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &full_voter_set(), + &justification, + ), + Err(Error::UnknownAuthorityVote), + ); + // original implementation returns `Ok(validation_result)` + // with `validation_result.is_valid() == true`. + let result = finality_grandpa::validate_commit( + &justification.commit, + &full_voter_set(), + &AncestryChain::new(&justification.votes_ancestries), + ) + .unwrap(); + + assert!(result.is_valid()); } diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index e18163313c936..f01f4ea2f10ce 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -16,14 +16,16 @@ //! Tests for Grandpa Justification code. -use bp_header_chain::justification::{optimize_justification, verify_justification, Error}; +use bp_header_chain::justification::{ + optimize_justification, required_justification_precommits, verify_justification, Error, +}; use bp_test_utils::*; type TestHeader = sp_runtime::testing::Header; #[test] fn valid_justification_accepted() { - let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1)]; + let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)]; let params = JustificationGeneratorParams { header: test_header(1), round: TEST_GRANDPA_ROUND, @@ -54,7 +56,7 @@ fn valid_justification_accepted_with_single_fork() { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1), (EVE, 1)], + authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)], ancestors: 5, forks: 1, }; @@ -76,15 +78,16 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() { use sp_finality_grandpa::AuthorityId; let n = 15; + let required_signatures = required_justification_precommits(n as _); let authorities = accounts(n).iter().map(|k| (*k, 1)).collect::>(); let params = JustificationGeneratorParams { header: test_header(1), round: TEST_GRANDPA_ROUND, set_id: TEST_GRANDPA_SET_ID, - authorities: authorities.clone(), + authorities: authorities.clone().into_iter().take(required_signatures as _).collect(), ancestors: n.into(), - forks: n.into(), + forks: required_signatures, }; let authorities = authorities diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 3b1712042d808..10da6cd9b3555 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -50,30 +50,37 @@ pub mod parachains; /// our bridge hub parachains huge. So let's stick to the real-world value here. /// /// Right now both Kusama and Polkadot aim to have around 1000 validators. Let's be safe here and -/// take twice as much here. -pub const MAX_AUTHORITIES_COUNT: u32 = 2_048; +/// take a bit more here. +pub const MAX_AUTHORITIES_COUNT: u32 = 1_256; /// Reasonable number of headers in the `votes_ancestries` on Polkadot-like chains. /// /// See [`bp_header_chain::ChainWithGrandpa`] for more details. -pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; +/// +/// This value comes from recent (February, 2023) Kusama and Polkadot headers. There are no +/// justifications with any additional headers in votes ancestry, so reasonable headers may +/// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some +/// reserve here. +pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; /// Approximate average header size in `votes_ancestries` field of justification on Polkadot-like /// chains. /// /// See [`bp_header_chain::ChainWithGrandpa`] for more details. -pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; +/// +/// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but some +/// non-mandatory headers has size `40kb` (they contain the BABE epoch descriptor with all +/// authorities - just like our mandatory header). Since we assume `2` headers in justification +/// votes ancestry, let's set average header to `40kb / 2`. +pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024; /// Approximate maximal header size on Polkadot-like chains. /// -/// We expect maximal header to have digest item with the new authorities set for every consensus -/// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also -/// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. -/// /// See [`bp_header_chain::ChainWithGrandpa`] for more details. -pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT - .saturating_mul(3) - .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); +/// +/// This value comes from recent (February, 2023) Kusama headers. Maximal header is a mandatory +/// header. In its SCALE-encoded form it is `80348` bytes. Let's have some reserve here. +pub const MAX_HEADER_SIZE: u32 = 90_000; /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Polkadot-like chain. This mostly depends on number of entries in the storage trie. From d7642ff67d716ca47758601a3cd54c36129424d9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Feb 2023 10:08:50 +0300 Subject: [PATCH 0954/1210] Wrap confirmation and finality transactions into batch_all in Millau -> RialtoParachain bridge (#1898) * wrap confirmation and finality transactions into batch_all in RialtoParachain<>Millau * review comments --- .../chains/millau_messages_to_rialto_parachain.rs | 7 ++++--- relays/messages/src/message_race_loop.rs | 13 +++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs index 5dbe1d69d1346..8fedd22a40abe 100644 --- a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs @@ -18,8 +18,9 @@ use relay_millau_client::Millau; use relay_rialto_parachain_client::RialtoParachain; -use substrate_relay_helper::messages_lane::{ - DirectReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, +use substrate_relay_helper::{ + messages_lane::{DirectReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane}, + UtilityPalletBatchCallBuilder, }; substrate_relay_helper::generate_receive_message_proof_call_builder!( @@ -45,6 +46,6 @@ impl SubstrateMessageLane for MillauMessagesToRialtoParachain { millau_runtime::WithRialtoParachainMessagesInstance, >; - type SourceBatchCallBuilder = (); + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; type TargetBatchCallBuilder = (); } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 2988ab231d932..3d995a0a3620e 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -573,17 +573,14 @@ pub async fn run, TC: TargetClient

>( if let Some((at_block, nonces_range, proof)) = race_state.nonces_to_submit.as_ref() { log::debug!( target: "bridge", - "Going to submit proof of messages in range {:?} to {} node", + "Going to submit proof of messages in range {:?} to {} node{}", nonces_range, P::target_name(), + target_batch_transaction.as_ref().map(|tx| format!( + ". This transaction is batched with sending the proof for header {:?}.", + tx.required_header_id()) + ).unwrap_or_default(), ); - if let Some(ref target_batch_transaction) = target_batch_transaction { - log::debug!( - target: "bridge", - "This transaction is batched with sending the proof for header {:?}.", - target_batch_transaction.required_header_id(), - ); - } target_submit_proof.set( race_target From 4339091e60a3a1f590bdac96022c58bcc85e4311 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Feb 2023 14:16:02 +0300 Subject: [PATCH 0955/1210] get rid of ChainWithMessages::WeightInfo, because we can't have exact weights for "external chains" (#1899) --- modules/messages/src/lib.rs | 1 + relays/client-bridge-hub-rococo/src/lib.rs | 3 - relays/client-bridge-hub-wococo/src/lib.rs | 3 - relays/client-millau/src/lib.rs | 1 - relays/client-rialto-parachain/src/lib.rs | 1 - relays/client-rialto/src/lib.rs | 1 - relays/client-substrate/src/chain.rs | 3 - relays/client-substrate/src/client.rs | 50 +++--- .../lib-substrate-relay/src/messages_lane.rs | 147 ++++++++++++------ 9 files changed, 121 insertions(+), 89 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index cc9033d105812..68af302444561 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -43,6 +43,7 @@ pub use weights::WeightInfo; pub use weights_ext::{ ensure_able_to_receive_confirmation, ensure_able_to_receive_message, ensure_weights_are_correct, WeightInfoExt, EXPECTED_DEFAULT_MESSAGE_LENGTH, + EXTRA_STORAGE_PROOF_SIZE, }; use crate::{ diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index b6b844021e0c0..c8963f968d002 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -132,9 +132,6 @@ impl ChainWithMessages for BridgeHubRococo { bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - - // TODO: fix (https://github.com/paritytech/parity-bridges-common/issues/1640) - type WeightInfo = (); } #[cfg(test)] diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index a466df3549510..7f23c0d93d2af 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -132,9 +132,6 @@ impl ChainWithMessages for BridgeHubWococo { bp_bridge_hub_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_bridge_hub_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - - // TODO: fix (https://github.com/paritytech/parity-bridges-common/issues/1640) - type WeightInfo = (); } #[cfg(test)] diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 4c4c1370a6a56..9df21b1d503e6 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -51,7 +51,6 @@ impl ChainWithMessages for Millau { bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); } impl Chain for Millau { diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 2c3792725c389..654848da2a736 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -79,7 +79,6 @@ impl ChainWithMessages for RialtoParachain { bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); } impl ChainWithTransactions for RialtoParachain { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 39cc2721ddbf5..b822dfe7d89f3 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -69,7 +69,6 @@ impl ChainWithMessages for Rialto { bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - type WeightInfo = (); } impl ChainWithBalances for Rialto { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index ebd9e7172d895..b55ae71cbf87f 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -136,9 +136,6 @@ pub trait ChainWithMessages: Chain { /// Maximal number of unconfirmed messages in a single confirmation transaction at this /// `ChainWithMessages`. const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; - - /// Weights of message pallet calls. - type WeightInfo: pallet_bridge_messages::WeightInfoExt; } /// Call type used by the chain. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 1a4aeb583cd41..bddd53b39f8c4 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -21,7 +21,6 @@ use crate::{ rpc::{ SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient, SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, - SubstrateTransactionPaymentClient, }, transaction_stall_timeout, AccountKeyPairOf, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, TransactionTracker, UnsignedTransaction, @@ -31,15 +30,16 @@ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider, StorageMapKeyProvider}; use codec::{Decode, Encode}; +use frame_support::weights::Weight; use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; use jsonrpsee::{ core::DeserializeOwned, ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; -use num_traits::{Bounded, Saturating, Zero}; +use num_traits::{Saturating, Zero}; use pallet_balances::AccountData; -use pallet_transaction_payment::InclusionFee; +use pallet_transaction_payment::RuntimeDispatchInfo; use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT}; use sp_core::{ storage::{StorageData, StorageKey}, @@ -51,10 +51,11 @@ use sp_runtime::{ }; use sp_trie::StorageProof; use sp_version::RuntimeVersion; -use std::{convert::TryFrom, future::Future}; +use std::future::Future; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_validate_transaction"; +const SUB_API_TX_PAYMENT_QUERY_INFO: &str = "TransactionPaymentApi_query_info"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; /// The difference between best block number and number of its ancestor, that is enough @@ -591,33 +592,24 @@ impl Client { .await } - /// Estimate fee that will be spent on given extrinsic. - pub async fn estimate_extrinsic_fee( + /// Returns weight of the given transaction. + pub async fn extimate_extrinsic_weight( &self, - transaction: Bytes, - ) -> Result> { + transaction: SignedTransaction, + ) -> Result { self.jsonrpsee_execute(move |client| async move { - let fee_details = - SubstrateTransactionPaymentClient::::fee_details(&*client, transaction, None) - .await?; - let inclusion_fee = fee_details - .inclusion_fee - .map(|inclusion_fee| InclusionFee { - base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256()) - .unwrap_or_else(|_| C::Balance::max_value()), - adjusted_weight_fee: C::Balance::try_from( - inclusion_fee.adjusted_weight_fee.into_u256(), - ) - .unwrap_or_else(|_| C::Balance::max_value()), - }) - .unwrap_or_else(|| InclusionFee { - base_fee: Zero::zero(), - len_fee: Zero::zero(), - adjusted_weight_fee: Zero::zero(), - }); - Ok(inclusion_fee) + let transaction_len = transaction.encoded_size() as u32; + + let call = SUB_API_TX_PAYMENT_QUERY_INFO.to_string(); + let data = Bytes((transaction, transaction_len).encode()); + + let encoded_response = + SubstrateStateClient::::call(&*client, call, data, None).await?; + let dispatch_info = + RuntimeDispatchInfo::::decode(&mut &encoded_response.0[..]) + .map_err(Error::ResponseParseFailed)?; + + Ok(dispatch_info.weight) }) .await } diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 1a4f65ff51e10..0a7a3566d20f1 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -25,7 +25,9 @@ use crate::{ use async_std::sync::Arc; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, Chain as _, HeaderIdOf, WeightExtraOps}; +use bp_runtime::{ + AccountIdOf, Chain as _, EncodedOrDecodedCall, HeaderIdOf, TransactionEra, WeightExtraOps, +}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -35,13 +37,15 @@ use messages_relay::{message_lane::MessageLane, message_lane_loop::BatchTransact use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, - ChainWithMessages, ChainWithTransactions, Client, Error as SubstrateError, HashOf, + ChainWithMessages, ChainWithTransactions, Client, Error as SubstrateError, HashOf, SignParam, + UnsignedTransaction, }; use relay_utils::{ metrics::{GlobalMetrics, MetricsParams, StandaloneMetric}, STALL_TIMEOUT, }; use sp_core::Pair; +use sp_runtime::traits::Zero; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; /// Substrate -> Substrate messages synchronization pipeline. @@ -159,25 +163,25 @@ where AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, { - let source_client = params.source_client; - let target_client = params.target_client; - let relayer_id_at_source: AccountIdOf = - params.source_transaction_params.signer.public().into(); - // 2/3 is reserved for proofs and tx overhead let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3; // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using // weights from Rialto and then simply dividing it by x2. let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - crate::messages_lane::select_delivery_transaction_limits::< - ::WeightInfo, - >( + select_delivery_transaction_limits_rpc::

( + ¶ms, P::TargetChain::max_extrinsic_weight(), P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - ); + ) + .await?; let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); + let source_client = params.source_client; + let target_client = params.target_client; + let relayer_id_at_source: AccountIdOf = + params.source_transaction_params.signer.public().into(); + log::info!( target: "bridge", "Starting {} -> {} messages relay.\n\t\ @@ -437,12 +441,15 @@ macro_rules! generate_receive_message_delivery_proof_call_builder { }; } -/// Returns maximal number of messages and their maximal cumulative dispatch weight, based -/// on given chain parameters. -pub fn select_delivery_transaction_limits( +/// Returns maximal number of messages and their maximal cumulative dispatch weight. +async fn select_delivery_transaction_limits_rpc( + params: &MessagesRelayParams

, max_extrinsic_weight: Weight, max_unconfirmed_messages_at_inbound_lane: MessageNonce, -) -> (MessageNonce, Weight) { +) -> anyhow::Result<(MessageNonce, Weight)> +where + AccountIdOf: From< as Pair>::Public>, +{ // We may try to guess accurate value, based on maximal number of messages and per-message // weight overhead, but the relay loop isn't using this info in a super-accurate way anyway. // So just a rough guess: let's say 1/3 of max tx weight is for tx itself and the rest is @@ -455,13 +462,35 @@ pub fn select_delivery_transaction_limits(params, 0)?; + let delivery_tx_with_zero_messages_weight = params + .target_client + .extimate_extrinsic_weight(delivery_tx_with_zero_messages) + .await + .map_err(|e| { + anyhow::format_err!("Failed to estimate delivery extrinsic weight: {:?}", e) + })?; + + // weight of single message delivery with outbound lane state + let delivery_tx_with_one_message = dummy_messages_delivery_transaction::

(params, 1)?; + let delivery_tx_with_one_message_weight = params + .target_client + .extimate_extrinsic_weight(delivery_tx_with_one_message) + .await + .map_err(|e| { + anyhow::format_err!("Failed to estimate delivery extrinsic weight: {:?}", e) + })?; + + // message overhead is roughly `delivery_tx_with_one_message_weight - + // delivery_tx_with_zero_messages_weight` + let delivery_tx_weight_rest = weight_for_delivery_tx - delivery_tx_with_zero_messages_weight; + let delivery_tx_message_overhead = + delivery_tx_with_one_message_weight.saturating_sub(delivery_tx_with_zero_messages_weight); let max_number_of_messages = std::cmp::min( delivery_tx_weight_rest - .min_components_checked_div(W::receive_messages_proof_messages_overhead(1)) + .min_components_checked_div(delivery_tx_message_overhead) .unwrap_or(u64::MAX), max_unconfirmed_messages_at_inbound_lane, ); @@ -475,36 +504,58 @@ pub fn select_delivery_transaction_limits; - - #[test] - fn select_delivery_transaction_limits_is_sane() { - // we want to check the `proof_size` component here too. But for Rialto and Millau - // it is set to `u64::MAX` (as for Polkadot and other relay/standalone chains). - // So let's use RialtoParachain limits here - it has `proof_size` limit as all - // Cumulus-based parachains do. - let (max_count, max_weight) = - select_delivery_transaction_limits::( - bp_rialto_parachain::RialtoParachain::max_extrinsic_weight(), - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - ); - assert_eq!( - (max_count, max_weight), - // We don't actually care about these values, so feel free to update them whenever test - // fails. The only thing to do before that is to ensure that new values looks sane: - // i.e. weight reserved for messages dispatch allows dispatch of non-trivial messages. - // - // Any significant change in this values should attract additional attention. - (1024, Weight::from_parts(866_600_106_667, 2_271_915)), +/// Returns dummy message delivery transaction with zero messages and `1kb` proof. +fn dummy_messages_delivery_transaction( + params: &MessagesRelayParams

, + messages: u32, +) -> anyhow::Result<::SignedTransaction> +where + AccountIdOf: From< as Pair>::Public>, +{ + // we don't care about any call values here, because all that the estimation RPC does + // is calls `GetDispatchInfo::get_dispatch_info` for the wrapped call. So we only are + // interested in values that affect call weight - e.g. number of messages and the + // storage proof size + + let dummy_messages_delivery_call = + P::ReceiveMessagesProofCallBuilder::build_receive_messages_proof_call( + params.source_transaction_params.signer.public().into(), + ( + Weight::zero(), + FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + // we may use per-chain `EXTRA_STORAGE_PROOF_SIZE`, but since we don't need + // exact values, this global estimation is fine + storage_proof: vec![vec![ + 42u8; + pallet_bridge_messages::EXTRA_STORAGE_PROOF_SIZE + as usize + ]], + lane: Default::default(), + nonces_start: 1, + nonces_end: messages as u64, + }, + ), + messages, + Weight::zero(), + false, ); - } + P::TargetChain::sign_transaction( + SignParam { + spec_version: 0, + transaction_version: 0, + genesis_hash: Default::default(), + signer: params.target_transaction_params.signer.clone(), + }, + UnsignedTransaction { + call: EncodedOrDecodedCall::Decoded(dummy_messages_delivery_call), + nonce: Zero::zero(), + tip: Zero::zero(), + era: TransactionEra::Immortal, + }, + ) + .map_err(Into::into) } From 027555b224f50ebcf352e4678c61f5eb1f96c5d7 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 23 Feb 2023 08:17:07 +0200 Subject: [PATCH 0956/1210] Fix init-bridge (#1900) --- modules/grandpa/src/lib.rs | 2 +- primitives/header-chain/src/justification.rs | 2 +- primitives/header-chain/tests/justification.rs | 11 ++++++----- relays/lib-substrate-relay/src/finality/engine.rs | 8 ++++---- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index e94d91a5c16a2..4304e82eeb103 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -181,7 +181,7 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; let may_refund_call_fee = is_authorities_change_enacted && - submit_finality_proof_info_from_args::(&*finality_target, &justification) + submit_finality_proof_info_from_args::(&finality_target, &justification) .fits_limits(); >::mutate(|count| *count += 1); insert_header::(*finality_target, hash); diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 1e34f365621b9..88dac0acf9f6d 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -135,7 +135,7 @@ pub fn decode_justification_target( } /// Verify and optimize given justification by removing unknown and duplicate votes. -pub fn optimize_justification( +pub fn verify_and_optimize_justification( finalized_target: (Header::Hash, Header::Number), authorities_set_id: SetId, authorities_set: &VoterSet, diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index f01f4ea2f10ce..52fa33ae97491 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -17,7 +17,8 @@ //! Tests for Grandpa Justification code. use bp_header_chain::justification::{ - optimize_justification, required_justification_precommits, verify_justification, Error, + required_justification_precommits, verify_and_optimize_justification, verify_justification, + Error, }; use bp_test_utils::*; @@ -199,7 +200,7 @@ fn optimizer_does_noting_with_minimal_justification() { let justification = make_default_justification::(&test_header(1)); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), @@ -222,7 +223,7 @@ fn unknown_authority_votes_are_removed_by_optimizer() { )); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), @@ -243,7 +244,7 @@ fn duplicate_authority_votes_are_removed_by_optimizer() { .push(justification.commit.precommits.first().cloned().unwrap()); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), @@ -266,7 +267,7 @@ fn redundant_authority_votes_are_removed_by_optimizer() { )); let num_precommits_before = justification.commit.precommits.len(); - let justification = optimize_justification::( + let justification = verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index f5ac8539a689e..4fc503011bba1 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -19,7 +19,7 @@ use crate::error::Error; use async_trait::async_trait; use bp_header_chain::{ - justification::{verify_justification, GrandpaJustification}, + justification::{verify_and_optimize_justification, GrandpaJustification}, ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader, }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode}; @@ -172,7 +172,7 @@ impl Engine for Grandpa { // actual authorities set (which we have read now) may have changed, so this // `optimize_justification` may fail. But if target chain is configured properly, it'll fail // anyway, after we submit transaction and failing earlier is better. So - it is fine - bp_header_chain::justification::optimize_justification( + verify_and_optimize_justification( (header.hash(), *header.number()), authority_set_id, &authority_set, @@ -272,11 +272,11 @@ impl Engine for Grandpa { initial_authorities_set_id, ); - let is_valid_set_id = verify_justification::( + let is_valid_set_id = verify_and_optimize_justification( (initial_header_hash, initial_header_number), initial_authorities_set_id, &authorities_for_verification, - &justification, + justification.clone(), ) .is_ok(); From f558c1cc7a5a3314c7e4858311571839d68507d1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 24 Feb 2023 09:01:13 +0300 Subject: [PATCH 0957/1210] Do not stall on lost transaction (#1903) * `select_nonces_to_deliver` is no longer `&mut self` * reset submitted nonces on lost transaction * clippy * fmt --- relays/messages/src/message_lane_loop.rs | 53 -------------------- relays/messages/src/message_race_delivery.rs | 19 +++---- relays/messages/src/message_race_loop.rs | 28 +++++++---- relays/messages/src/message_race_strategy.rs | 18 +++---- 4 files changed, 36 insertions(+), 82 deletions(-) diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 5e5085bbd5dcb..2903435dda5b8 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -1017,58 +1017,6 @@ pub(crate) mod tests { assert_eq!(result.submitted_messages_proofs, vec![(1..=1, None)],); } - #[test] - fn message_lane_loop_is_able_to_recover_from_race_stall() { - // with this configuration, both source and target clients will lose their transactions => - // reconnect will happen - let (source_exit_sender, exit_receiver) = unbounded(); - let target_exit_sender = source_exit_sender.clone(); - let result = run_loop_test( - Arc::new(Mutex::new(TestClientData { - source_state: ClientState { - best_self: HeaderId(0, 0), - best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), - actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), - }, - source_latest_generated_nonce: 1, - source_tracked_transaction_status: TrackedTransactionStatus::Lost, - target_state: ClientState { - best_self: HeaderId(0, 0), - best_finalized_self: HeaderId(0, 0), - best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), - actual_best_finalized_peer_at_best_self: Some(HeaderId(0, 0)), - }, - target_latest_received_nonce: 0, - target_tracked_transaction_status: TrackedTransactionStatus::Lost, - ..Default::default() - })), - Arc::new(move |data: &mut TestClientData| { - if data.is_source_reconnected { - data.source_tracked_transaction_status = - TrackedTransactionStatus::Finalized(Default::default()); - } - if data.is_source_reconnected && data.is_target_reconnected { - source_exit_sender.unbounded_send(()).unwrap(); - } - }), - Arc::new(|_| {}), - Arc::new(move |data: &mut TestClientData| { - if data.is_target_reconnected { - data.target_tracked_transaction_status = - TrackedTransactionStatus::Finalized(Default::default()); - } - if data.is_source_reconnected && data.is_target_reconnected { - target_exit_sender.unbounded_send(()).unwrap(); - } - }), - Arc::new(|_| {}), - exit_receiver.into_future().map(|(_, _)| ()), - ); - - assert!(result.is_source_reconnected); - } - #[test] fn message_lane_loop_is_able_to_recover_from_unsuccessful_transaction() { // with this configuration, both source and target clients will mine their transactions, but @@ -1146,7 +1094,6 @@ pub(crate) mod tests { exit_receiver.into_future().map(|(_, _)| ()), ); - assert!(result.is_source_reconnected); assert_eq!(result.submitted_messages_proofs.len(), 2); assert_eq!(result.submitted_messages_receiving_proofs.len(), 2); } diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index c704a7b561072..8b8e690ec4a2e 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -292,11 +292,16 @@ impl std::fmt::Debug for MessageDeliveryStrategy MessageDeliveryStrategy { /// Returns total weight of all undelivered messages. - fn total_queued_dispatch_weight(&self) -> Weight { + fn dispatch_weight_for_range(&self, range: &RangeInclusive) -> Weight { self.strategy .source_queue() .iter() - .flat_map(|(_, range)| range.values().map(|details| details.dispatch_weight)) + .flat_map(|(_, subrange)| { + subrange + .iter() + .filter(|(nonce, _)| range.contains(nonce)) + .map(|(_, details)| details.dispatch_weight) + }) .fold(Weight::zero(), |total, weight| total.saturating_add(weight)) } } @@ -424,7 +429,7 @@ where } async fn select_nonces_to_deliver( - &mut self, + &self, race_state: RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) -> Option<(RangeInclusive, Self::ProofParameters)> { let best_finalized_source_header_id_at_best_target = @@ -526,7 +531,6 @@ where let maximal_source_queue_index = self.strategy.maximal_available_source_queue_index(race_state)?; - let previous_total_dispatch_weight = self.total_queued_dispatch_weight(); let source_queue = self.strategy.source_queue(); let reference = RelayMessagesBatchReference { @@ -544,10 +548,7 @@ where let range_begin = source_queue[0].1.begin(); let selected_nonces = range_begin..=range_end; - self.strategy.remove_le_nonces_from_source_queue(range_end); - - let new_total_dispatch_weight = self.total_queued_dispatch_weight(); - let dispatch_weight = previous_total_dispatch_weight - new_total_dispatch_weight; + let dispatch_weight = self.dispatch_weight_for_range(&selected_nonces); Some(( selected_nonces, @@ -707,7 +708,7 @@ mod tests { #[async_std::test] async fn message_delivery_strategy_selects_messages_to_deliver() { - let (state, mut strategy) = prepare_strategy(); + let (state, strategy) = prepare_strategy(); // both sides are ready to relay new messages assert_eq!( diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 3d995a0a3620e..50f71ea050bb5 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -211,7 +211,7 @@ pub trait RaceStrategy: Debug { /// data) from source to target node. /// Additionally, parameters required to generate proof are returned. async fn select_nonces_to_deliver( - &mut self, + &self, race_state: RaceState, ) -> Option<(RangeInclusive, Self::ProofParameters)>; } @@ -234,6 +234,13 @@ pub struct RaceState { pub nonces_submitted: Option>, } +impl RaceState { + /// Reset `nonces_submitted` to `None`. + fn reset_submitted(&mut self) { + self.nonces_submitted = None; + } +} + /// Run race loop until connection with target or source node is lost. pub async fn run, TC: TargetClient

>( race_source: SC, @@ -460,7 +467,7 @@ pub async fn run, TC: TargetClient

>( (TrackedTransactionStatus::Finalized(at_block), Some(nonces_submitted)) => { // our transaction has been mined, but was it successful or not? let's check the best // nonce at the target node. - race_target.nonces(at_block, false) + let _ = race_target.nonces(at_block, false) .await .map_err(|e| format!("failed to read nonces from target node: {e:?}")) .and_then(|(_, nonces_at_target)| { @@ -477,26 +484,26 @@ pub async fn run, TC: TargetClient

>( .map_err(|e| { log::error!( target: "bridge", - "{} -> {} race has stalled. Transaction failed: {}. Going to restart", + "{} -> {} race transaction failed: {}", P::source_name(), P::target_name(), e, ); - FailedClient::Both - })?; + race_state.reset_submitted(); + }); }, (TrackedTransactionStatus::Lost, _) => { log::warn!( target: "bridge", - "{} -> {} race has stalled. State: {:?}. Strategy: {:?}", + "{} -> {} race transaction has been lost. State: {:?}. Strategy: {:?}", P::source_name(), P::target_name(), race_state, strategy, ); - return Err(FailedClient::Both); + race_state.reset_submitted(); }, _ => (), } @@ -531,8 +538,7 @@ pub async fn run, TC: TargetClient

>( race_state.clone() }; - let nonces_to_deliver = - select_nonces_to_deliver(expected_race_state, &mut strategy).await; + let nonces_to_deliver = select_nonces_to_deliver(expected_race_state, &strategy).await; let best_at_source = strategy.best_at_source(); if let Some((at_block, nonces_range, proof_parameters)) = nonces_to_deliver { @@ -665,7 +671,7 @@ where async fn select_nonces_to_deliver( race_state: RaceState, - strategy: &mut Strategy, + strategy: &Strategy, ) -> Option<(SourceHeaderId, RangeInclusive, Strategy::ProofParameters)> where SourceHeaderId: Clone, @@ -723,7 +729,7 @@ mod tests { // the proof will be generated on source, but using BEST_AT_TARGET block assert_eq!( - select_nonces_to_deliver(race_state, &mut strategy).await, + select_nonces_to_deliver(race_state, &strategy).await, Some((HeaderId(BEST_AT_TARGET, BEST_AT_TARGET), 6..=10, (),)) ); } diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 9b9091b979f66..9a53a487d94f8 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -136,7 +136,7 @@ impl< } /// Remove all nonces that are less than or equal to given nonce from the source queue. - pub fn remove_le_nonces_from_source_queue(&mut self, nonce: MessageNonce) { + fn remove_le_nonces_from_source_queue(&mut self, nonce: MessageNonce) { while let Some((queued_at, queued_range)) = self.source_queue.pop_front() { if let Some(range_to_requeue) = queued_range.greater_than(nonce) { self.source_queue.push_front((queued_at, range_to_requeue)); @@ -168,12 +168,12 @@ impl< SourceNoncesRange, Proof, > where - SourceHeaderHash: Clone + Debug + Send, - SourceHeaderNumber: Clone + Ord + Debug + Send, - SourceNoncesRange: NoncesRange + Debug + Send, - TargetHeaderHash: Debug + Send, - TargetHeaderNumber: Debug + Send, - Proof: Debug + Send, + SourceHeaderHash: Clone + Debug + Send + Sync, + SourceHeaderNumber: Clone + Ord + Debug + Send + Sync, + SourceNoncesRange: NoncesRange + Debug + Send + Sync, + TargetHeaderHash: Debug + Send + Sync, + TargetHeaderNumber: Debug + Send + Sync, + Proof: Debug + Send + Sync, { type SourceNoncesRange = SourceNoncesRange; type ProofParameters = (); @@ -284,6 +284,7 @@ impl< Proof, >, ) { + self.remove_le_nonces_from_source_queue(nonces.latest_nonce); // TODO: does it means that we'll try to submit old nonces in next tx??? self.best_target_nonce = Some(std::cmp::max( self.best_target_nonce.unwrap_or(nonces.latest_nonce), nonces.latest_nonce, @@ -291,7 +292,7 @@ impl< } async fn select_nonces_to_deliver( - &mut self, + &self, race_state: RaceState< HeaderId, HeaderId, @@ -301,7 +302,6 @@ impl< let maximal_source_queue_index = self.maximal_available_source_queue_index(race_state)?; let range_begin = self.source_queue[0].1.begin(); let range_end = self.source_queue[maximal_source_queue_index].1.end(); - self.remove_le_nonces_from_source_queue(range_end); Some((range_begin..=range_end, ())) } } From a4139e330624f8969e1d494c76c8afcf0ce3f907 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 03:11:20 +0000 Subject: [PATCH 0958/1210] Bump trie-db from 0.25.1 to 0.26.0 Bumps [trie-db](https://github.com/paritytech/trie) from 0.25.1 to 0.26.0. - [Release notes](https://github.com/paritytech/trie/releases) - [Commits](https://github.com/paritytech/trie/compare/trie-db-v0.25.1...trie-db-v0.26.0) --- updated-dependencies: - dependency-name: trie-db dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index c8829a508d9d0..3cd2fdd35ca4f 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master 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 } -trie-db = { version = "0.25.1", default-features = false } +trie-db = { version = "0.26.0", default-features = false } [dev-dependencies] hex-literal = "0.3" From a6d3a64e03f1424481dc524da665e1c99d77fb53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 03:12:33 +0000 Subject: [PATCH 0959/1210] Bump rand from 0.7.3 to 0.8.5 Bumps [rand](https://github.com/rust-random/rand) from 0.7.3 to 0.8.5. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/0.7.3...0.8.5) --- updated-dependencies: - dependency-name: rand dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 49201defdd1d6..b8b7e79e352c5 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -13,7 +13,7 @@ futures = "0.3.26" jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" -rand = "0.7" +rand = "0.8" scale-info = { version = "2.1.1", features = ["derive"] } tokio = { version = "1.25", features = ["rt-multi-thread"] } thiserror = "1.0.26" From 12b483c70cdac97fe82013388bda1cf251da7344 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 03:14:14 +0000 Subject: [PATCH 0960/1210] Bump jsonrpsee from 0.15.1 to 0.16.2 Bumps [jsonrpsee](https://github.com/paritytech/jsonrpsee) from 0.15.1 to 0.16.2. - [Release notes](https://github.com/paritytech/jsonrpsee/releases) - [Changelog](https://github.com/paritytech/jsonrpsee/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/jsonrpsee/compare/v0.15.1...v0.16.2) --- updated-dependencies: - dependency-name: jsonrpsee dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index b8b7e79e352c5..7e7eba5ec2bc8 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -10,7 +10,7 @@ async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.26" -jsonrpsee = { version = "0.15", features = ["macros", "ws-client"] } +jsonrpsee = { version = "0.16", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.8" From 19ae9cb214fb8fb38ecdb4b35732aa55c0af9d82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 03:21:42 +0000 Subject: [PATCH 0961/1210] Bump tempfile from 3.3.0 to 3.4.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/commits) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 0dc201588306a..9db0e30c52d2e 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -65,5 +65,5 @@ xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", defau bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -tempfile = "3.2" +tempfile = "3.4" finality-grandpa = { version = "0.16.0" } From d032566b64dd3ecd439f644977c661251d9c3b3c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Feb 2023 11:19:23 +0300 Subject: [PATCH 0962/1210] fix nightly clippy issues (#1915) --- relays/bin-substrate/src/cli/resubmit_transactions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs index 2fecd19692142..c5b20e939c1fa 100644 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -90,7 +90,6 @@ macro_rules! select_bridge { match $bridge { RelayChain::Millau => { type Target = relay_millau_client::Millau; - type TargetSign = relay_millau_client::Millau; $generic }, From ed218927213fd9481a2de9e851bbcd79b8380a6f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 28 Feb 2023 11:31:54 +0200 Subject: [PATCH 0963/1210] Relayers pallet: extend payment source id (#1907) * Add Chain::ID const * Relayers pallet: extend payment source id * Addressed code review comments * Fix benchmarks * Fix dashboards * Renamings * Fix compilation --- bin/millau/runtime/src/lib.rs | 23 ++- bin/rialto-parachain/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/lib.rs | 3 +- bin/runtime-common/Cargo.toml | 1 + bin/runtime-common/src/mock.rs | 9 +- .../src/refund_relayer_extension.rs | 22 ++- modules/relayers/Cargo.toml | 1 + modules/relayers/src/benchmarking.rs | 12 +- modules/relayers/src/lib.rs | 146 +++++++++++------- modules/relayers/src/mock.rs | 7 +- modules/relayers/src/payment_adapter.rs | 73 ++++++--- modules/relayers/src/weights.rs | 24 +-- primitives/relayers/Cargo.toml | 2 + primitives/relayers/src/lib.rs | 122 ++++++++++++--- primitives/runtime/src/lib.rs | 6 + relays/client-bridge-hub-rococo/Cargo.toml | 1 + relays/client-bridge-hub-rococo/src/lib.rs | 2 + relays/client-bridge-hub-wococo/src/lib.rs | 2 + relays/client-kusama/Cargo.toml | 1 + relays/client-kusama/src/lib.rs | 2 + relays/client-millau/Cargo.toml | 1 + relays/client-millau/src/lib.rs | 2 + relays/client-polkadot/Cargo.toml | 1 + relays/client-polkadot/src/lib.rs | 2 + relays/client-rialto-parachain/Cargo.toml | 1 + relays/client-rialto-parachain/src/lib.rs | 2 + relays/client-rialto/Cargo.toml | 1 + relays/client-rialto/src/lib.rs | 2 + relays/client-rococo/Cargo.toml | 1 + relays/client-rococo/src/lib.rs | 2 + relays/client-substrate/src/chain.rs | 6 +- relays/client-substrate/src/test_chain.rs | 2 + relays/client-westend/Cargo.toml | 1 + relays/client-westend/src/lib.rs | 3 + relays/client-wococo/Cargo.toml | 1 + relays/client-wococo/src/lib.rs | 2 + .../src/messages_metrics.rs | 24 ++- 37 files changed, 377 insertions(+), 139 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 369bea2b1fafb..fdbcddc0f3828 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -33,6 +33,8 @@ pub mod rialto_parachain_messages; pub mod xcm_config; use bp_parachains::SingleParaStoredHeaderDataBuilder; +#[cfg(feature = "runtime-benchmarks")] +use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::HeaderId; use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, @@ -389,7 +391,7 @@ impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = - bp_relayers::PayLaneRewardFromAccount, AccountId>; + bp_relayers::PayRewardFromAccount, AccountId>; type WeightInfo = (); } @@ -449,6 +451,7 @@ impl pallet_bridge_messages::Config for Runtime { type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, + WithRialtoMessagesInstance, frame_support::traits::ConstU64<100_000>, frame_support::traits::ConstU64<10_000>, >; @@ -480,6 +483,7 @@ impl pallet_bridge_messages::Config for Run type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, + WithRialtoParachainMessagesInstance, frame_support::traits::ConstU64<100_000>, frame_support::traits::ConstU64<10_000>, >; @@ -997,7 +1001,14 @@ impl_runtime_apis! { } fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - pallet_bridge_relayers::Pallet::::relayer_reward(relayer, &Self::bench_lane_id()).is_some() + use bridge_runtime_common::messages::MessageBridge; + + let lane = Self::bench_lane_id(); + let bridged_chain_id = WithRialtoMessageBridge::BRIDGED_CHAIN_ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) + ).is_some() } } @@ -1027,15 +1038,15 @@ impl_runtime_apis! { impl RelayersConfig for Runtime { fn prepare_environment( - lane: bp_messages::LaneId, + account_params: RewardsAccountParams, reward: Balance, ) { use frame_support::traits::fungible::Mutate; - let lane_rewards_account = bp_relayers::PayLaneRewardFromAccount::< + let rewards_account = bp_relayers::PayRewardFromAccount::< Balances, AccountId - >::lane_rewards_account(lane); - Balances::mint_into(&lane_rewards_account, reward).unwrap(); + >::rewards_account(account_params); + Balances::mint_into(&rewards_account, reward).unwrap(); } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 5eeddf41e5247..f2e408def3097 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -521,7 +521,7 @@ impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = - bp_relayers::PayLaneRewardFromAccount, AccountId>; + bp_relayers::PayRewardFromAccount, AccountId>; type WeightInfo = (); } @@ -569,6 +569,7 @@ impl pallet_bridge_messages::Config for Runtime { type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, + WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, frame_support::traits::ConstU128<100_000>, >; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 3959dbea1aae3..c090bb59b9228 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -393,7 +393,7 @@ impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = - bp_relayers::PayLaneRewardFromAccount, AccountId>; + bp_relayers::PayRewardFromAccount, AccountId>; type WeightInfo = (); } @@ -443,6 +443,7 @@ impl pallet_bridge_messages::Config for Runtime { type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< Runtime, + WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, frame_support::traits::ConstU128<100_000>, >; diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 27e305751e4e8..dde9e70f576ae 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -19,6 +19,7 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f bp-messages = { path = "../../primitives/messages", default-features = false } bp-parachains = { path = "../../primitives/parachains", default-features = false } bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index a5ae9131f031f..29c540bc66463 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -85,6 +85,8 @@ pub type BridgedChainHeader = /// Message lane used in tests. pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +/// Bridged chain id used in tests. +pub const TEST_BRIDGED_CHAIN_ID: ChainId = *b"brdg"; /// Maximal number of queued messages at the test lane. pub const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; /// Minimal extrinsic weight at the `BridgedChain`. @@ -118,7 +120,7 @@ crate::generate_bridge_reject_obsolete_headers_and_messages! { parameter_types! { pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID]; - pub const BridgedChainId: ChainId = *b"brdg"; + pub const BridgedChainId: ChainId = TEST_BRIDGED_CHAIN_ID; pub const BridgedParasPalletName: &'static str = "Paras"; pub const ExistentialDeposit: ThisChainBalance = 500; pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; @@ -227,6 +229,7 @@ impl pallet_bridge_messages::Config for TestRuntime { type LaneMessageVerifier = FromThisChainMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< TestRuntime, + (), frame_support::traits::ConstU64<100_000>, frame_support::traits::ConstU64<10_000>, >; @@ -251,7 +254,7 @@ pub struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { const THIS_CHAIN_ID: ChainId = *b"this"; - const BRIDGED_CHAIN_ID: ChainId = *b"brdg"; + const BRIDGED_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = ThisChain; @@ -265,7 +268,7 @@ impl MessageBridge for OnThisChainBridge { pub struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { - const THIS_CHAIN_ID: ChainId = *b"brdg"; + const THIS_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; const BRIDGED_CHAIN_ID: ChainId = *b"this"; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index df4eae6f7370b..aa03082e9f57d 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -23,6 +23,7 @@ use crate::messages_call_ext::{ MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo, }; use bp_messages::LaneId; +use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::StaticStrProvider; use codec::{Decode, Encode}; use frame_support::{ @@ -397,7 +398,15 @@ where let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); // finally - register refund in relayers pallet - RelayersPallet::::register_relayer_reward(Msgs::Id::get(), &relayer, refund); + RelayersPallet::::register_relayer_reward( + RewardsAccountParams::new( + Msgs::Id::get(), + Runtime::BridgedChainId::get(), + RewardsAccountOwner::ThisChain, + ), + &relayer, + refund, + ); log::trace!( target: "runtime::bridge", @@ -433,6 +442,7 @@ mod tests { parameter_types! { TestParachain: u32 = 1000; pub TestLaneId: LaneId = TEST_LANE_ID; + pub DirectedTestLaneId: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::ThisChain); } bp_runtime::generate_static_str_provider!(TestExtension); @@ -872,7 +882,7 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + DirectedTestLaneId::get() ), Some(regular_reward), ); @@ -891,7 +901,7 @@ mod tests { run_post_dispatch(Some(pre_dispatch_data), Ok(())); let reward_after_two_calls = RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get(), + DirectedTestLaneId::get(), ) .unwrap(); assert!( @@ -912,7 +922,7 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + DirectedTestLaneId::get() ), Some(expected_reward()), ); @@ -928,7 +938,7 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + DirectedTestLaneId::get() ), Some(expected_reward()), ); @@ -944,7 +954,7 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - TestLaneId::get() + DirectedTestLaneId::get() ), Some(expected_reward()), ); diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 954818a3b5052..200fbbca3093b 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -16,6 +16,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" bp-messages = { path = "../../primitives/messages", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } +pallet-bridge-messages = { path = "../messages", default-features = false } # Substrate Dependencies diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index 7195b316bb694..7dcf77eb958ea 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -20,6 +20,8 @@ use crate::*; +use bp_messages::LaneId; +use bp_relayers::RewardsAccountOwner; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_system::RawOrigin; @@ -32,19 +34,21 @@ pub struct Pallet(crate::Pallet); /// Trait that must be implemented by runtime. pub trait Config: crate::Config { /// Prepare environment for paying given reward for serving given lane. - fn prepare_environment(lane: LaneId, reward: Self::Reward); + fn prepare_environment(account_params: RewardsAccountParams, reward: Self::Reward); } benchmarks! { // Benchmark `claim_rewards` call. claim_rewards { let lane = LaneId([0, 0, 0, 0]); + let account_params = + RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain); let relayer: T::AccountId = whitelisted_caller(); let reward = T::Reward::from(REWARD_AMOUNT); - T::prepare_environment(lane, reward); - RelayerRewards::::insert(&relayer, lane, reward); - }: _(RawOrigin::Signed(relayer), lane) + T::prepare_environment(account_params, reward); + RelayerRewards::::insert(&relayer, account_params, reward); + }: _(RawOrigin::Signed(relayer), account_params) verify { // we can't check anything here, because `PaymentProcedure` is responsible for // payment logic, so we assume that if call has succeeded, the procedure has diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 2ceebd0336e09..3d32e3c7a1469 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -20,8 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_messages::LaneId; -use bp_relayers::{PaymentProcedure, RelayerRewardsKeyProvider}; +use bp_relayers::{PaymentProcedure, RelayerRewardsKeyProvider, RewardsAccountParams}; use bp_runtime::StorageDoubleMapKeyProvider; use frame_support::sp_runtime::Saturating; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; @@ -72,28 +71,32 @@ pub mod pallet { /// Claim accumulated rewards. #[pallet::call_index(0)] #[pallet::weight(T::WeightInfo::claim_rewards())] - pub fn claim_rewards(origin: OriginFor, lane_id: LaneId) -> DispatchResult { + pub fn claim_rewards( + origin: OriginFor, + rewards_account_params: RewardsAccountParams, + ) -> DispatchResult { let relayer = ensure_signed(origin)?; RelayerRewards::::try_mutate_exists( &relayer, - lane_id, + rewards_account_params, |maybe_reward| -> DispatchResult { let reward = maybe_reward.take().ok_or(Error::::NoRewardForRelayer)?; - T::PaymentProcedure::pay_reward(&relayer, lane_id, reward).map_err(|e| { - log::trace!( - target: LOG_TARGET, - "Failed to pay {:?} rewards to {:?}: {:?}", - lane_id, - relayer, - e, - ); - Error::::FailedToPayReward - })?; + T::PaymentProcedure::pay_reward(&relayer, rewards_account_params, reward) + .map_err(|e| { + log::trace!( + target: LOG_TARGET, + "Failed to pay {:?} rewards to {:?}: {:?}", + rewards_account_params, + relayer, + e, + ); + Error::::FailedToPayReward + })?; Self::deposit_event(Event::::RewardPaid { relayer: relayer.clone(), - lane_id, + rewards_account_params, reward, }); Ok(()) @@ -104,23 +107,31 @@ pub mod pallet { impl Pallet { /// Register reward for given relayer. - pub fn register_relayer_reward(lane_id: LaneId, relayer: &T::AccountId, reward: T::Reward) { + pub fn register_relayer_reward( + rewards_account_params: RewardsAccountParams, + relayer: &T::AccountId, + reward: T::Reward, + ) { if reward.is_zero() { return } - RelayerRewards::::mutate(relayer, lane_id, |old_reward: &mut Option| { - let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); - *old_reward = Some(new_reward); - - log::trace!( - target: crate::LOG_TARGET, - "Relayer {:?} can now claim reward for serving lane {:?}: {:?}", - relayer, - lane_id, - new_reward, - ); - }); + RelayerRewards::::mutate( + relayer, + rewards_account_params, + |old_reward: &mut Option| { + let new_reward = old_reward.unwrap_or_else(Zero::zero).saturating_add(reward); + *old_reward = Some(new_reward); + + log::trace!( + target: crate::LOG_TARGET, + "Relayer {:?} can now claim reward for serving payer {:?}: {:?}", + relayer, + rewards_account_params, + new_reward, + ); + }, + ); } } @@ -131,8 +142,8 @@ pub mod pallet { RewardPaid { /// Relayer account that has been rewarded. relayer: T::AccountId, - /// Relayer has received reward for serving this lane. - lane_id: LaneId, + /// Relayer has received reward from this account. + rewards_account_params: RewardsAccountParams, /// Reward amount. reward: T::Reward, }, @@ -166,6 +177,8 @@ mod tests { use mock::{RuntimeEvent as TestEvent, *}; use crate::Event::RewardPaid; + use bp_messages::LaneId; + use bp_relayers::RewardsAccountOwner; use frame_support::{ assert_noop, assert_ok, traits::fungible::{Inspect, Mutate}, @@ -182,7 +195,10 @@ mod tests { fn root_cant_claim_anything() { run_test(|| { assert_noop!( - Pallet::::claim_rewards(RuntimeOrigin::root(), TEST_LANE_ID), + Pallet::::claim_rewards( + RuntimeOrigin::root(), + TEST_REWARDS_ACCOUNT_PARAMS + ), DispatchError::BadOrigin, ); }); @@ -194,7 +210,7 @@ mod tests { assert_noop!( Pallet::::claim_rewards( RuntimeOrigin::signed(REGULAR_RELAYER), - TEST_LANE_ID + TEST_REWARDS_ACCOUNT_PARAMS ), Error::::NoRewardForRelayer, ); @@ -204,11 +220,15 @@ mod tests { #[test] fn relayer_cant_claim_if_payment_procedure_fails() { run_test(|| { - RelayerRewards::::insert(FAILING_RELAYER, TEST_LANE_ID, 100); + RelayerRewards::::insert( + FAILING_RELAYER, + TEST_REWARDS_ACCOUNT_PARAMS, + 100, + ); assert_noop!( Pallet::::claim_rewards( RuntimeOrigin::signed(FAILING_RELAYER), - TEST_LANE_ID + TEST_REWARDS_ACCOUNT_PARAMS ), Error::::FailedToPayReward, ); @@ -220,12 +240,19 @@ mod tests { run_test(|| { get_ready_for_events(); - RelayerRewards::::insert(REGULAR_RELAYER, TEST_LANE_ID, 100); + RelayerRewards::::insert( + REGULAR_RELAYER, + TEST_REWARDS_ACCOUNT_PARAMS, + 100, + ); assert_ok!(Pallet::::claim_rewards( RuntimeOrigin::signed(REGULAR_RELAYER), - TEST_LANE_ID + TEST_REWARDS_ACCOUNT_PARAMS )); - assert_eq!(RelayerRewards::::get(REGULAR_RELAYER, TEST_LANE_ID), None); + assert_eq!( + RelayerRewards::::get(REGULAR_RELAYER, TEST_REWARDS_ACCOUNT_PARAMS), + None + ); //Check if the `RewardPaid` event was emitted. assert_eq!( @@ -234,7 +261,7 @@ mod tests { phase: Phase::Initialization, event: TestEvent::Relayers(RewardPaid { relayer: REGULAR_RELAYER, - lane_id: TEST_LANE_ID, + rewards_account_params: TEST_REWARDS_ACCOUNT_PARAMS, reward: 100 }), topics: vec![], @@ -244,30 +271,39 @@ mod tests { } #[test] - fn pay_lane_reward_from_account_actually_pays_reward() { + fn pay_reward_from_account_actually_pays_reward() { type Balances = pallet_balances::Pallet; - type PayLaneRewardFromAccount = bp_relayers::PayLaneRewardFromAccount; + type PayLaneRewardFromAccount = bp_relayers::PayRewardFromAccount; run_test(|| { - let lane0_rewards_account = - PayLaneRewardFromAccount::lane_rewards_account(LaneId([0, 0, 0, 0])); - let lane1_rewards_account = - PayLaneRewardFromAccount::lane_rewards_account(LaneId([0, 0, 0, 1])); - - Balances::mint_into(&lane0_rewards_account, 100).unwrap(); - Balances::mint_into(&lane1_rewards_account, 100).unwrap(); - assert_eq!(Balances::balance(&lane0_rewards_account), 100); - assert_eq!(Balances::balance(&lane1_rewards_account), 100); + let in_lane_0 = RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::ThisChain, + ); + let out_lane_1 = RewardsAccountParams::new( + LaneId([0, 0, 0, 1]), + *b"test", + RewardsAccountOwner::BridgedChain, + ); + + let in_lane0_rewards_account = PayLaneRewardFromAccount::rewards_account(in_lane_0); + let out_lane1_rewards_account = PayLaneRewardFromAccount::rewards_account(out_lane_1); + + Balances::mint_into(&in_lane0_rewards_account, 100).unwrap(); + Balances::mint_into(&out_lane1_rewards_account, 100).unwrap(); + assert_eq!(Balances::balance(&in_lane0_rewards_account), 100); + assert_eq!(Balances::balance(&out_lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 0); - PayLaneRewardFromAccount::pay_reward(&1, LaneId([0, 0, 0, 0]), 100).unwrap(); - assert_eq!(Balances::balance(&lane0_rewards_account), 0); - assert_eq!(Balances::balance(&lane1_rewards_account), 100); + PayLaneRewardFromAccount::pay_reward(&1, in_lane_0, 100).unwrap(); + assert_eq!(Balances::balance(&in_lane0_rewards_account), 0); + assert_eq!(Balances::balance(&out_lane1_rewards_account), 100); assert_eq!(Balances::balance(&1), 100); - PayLaneRewardFromAccount::pay_reward(&1, LaneId([0, 0, 0, 1]), 100).unwrap(); - assert_eq!(Balances::balance(&lane0_rewards_account), 0); - assert_eq!(Balances::balance(&lane1_rewards_account), 0); + PayLaneRewardFromAccount::pay_reward(&1, out_lane_1, 100).unwrap(); + assert_eq!(Balances::balance(&in_lane0_rewards_account), 0); + assert_eq!(Balances::balance(&out_lane1_rewards_account), 0); assert_eq!(Balances::balance(&1), 200); }); } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 89b3ead04119d..c40c86f1db547 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -19,7 +19,7 @@ use crate as pallet_bridge_relayers; use bp_messages::LaneId; -use bp_relayers::PaymentProcedure; +use bp_relayers::{PaymentProcedure, RewardsAccountOwner, RewardsAccountParams}; use frame_support::{parameter_types, weights::RuntimeDbWeight}; use sp_core::H256; use sp_runtime::{ @@ -96,7 +96,8 @@ impl pallet_bridge_relayers::Config for TestRuntime { } /// Message lane that we're using in tests. -pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +pub const TEST_REWARDS_ACCOUNT_PARAMS: RewardsAccountParams = + RewardsAccountParams::new(LaneId([0, 0, 0, 0]), *b"test", RewardsAccountOwner::ThisChain); /// Regular relayer that may receive rewards. pub const REGULAR_RELAYER: AccountId = 1; @@ -112,7 +113,7 @@ impl PaymentProcedure for TestPaymentProcedure { fn pay_reward( relayer: &AccountId, - _lane_id: LaneId, + _lane_id: RewardsAccountParams, _reward: Balance, ) -> Result<(), Self::Error> { match *relayer { diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 946b31cf7af41..cfd07cd6ccc23 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -18,28 +18,33 @@ use crate::{Config, Pallet}; -use bp_messages::source_chain::{DeliveryConfirmationPayments, RelayersRewards}; +use bp_messages::{ + source_chain::{DeliveryConfirmationPayments, RelayersRewards}, + LaneId, +}; +use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism /// for the messages pallet. -pub struct DeliveryConfirmationPaymentsAdapter( - PhantomData<(T, DeliveryReward, ConfirmationReward)>, +pub struct DeliveryConfirmationPaymentsAdapter( + PhantomData<(T, MI, DeliveryReward, ConfirmationReward)>, ); -impl DeliveryConfirmationPayments - for DeliveryConfirmationPaymentsAdapter +impl DeliveryConfirmationPayments + for DeliveryConfirmationPaymentsAdapter where - T: Config, + T: Config + pallet_bridge_messages::Config, + MI: 'static, DeliveryReward: Get, ConfirmationReward: Get, { type Error = &'static str; fn pay_reward( - lane_id: bp_messages::LaneId, + lane_id: LaneId, messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, received_range: &RangeInclusive, @@ -50,7 +55,11 @@ where register_relayers_rewards::( confirmation_relayer, relayers_rewards, - lane_id, + RewardsAccountParams::new( + lane_id, + T::BridgedChainId::get(), + RewardsAccountOwner::BridgedChain, + ), DeliveryReward::get(), ConfirmationReward::get(), ); @@ -61,7 +70,7 @@ where fn register_relayers_rewards( confirmation_relayer: &T::AccountId, relayers_rewards: RelayersRewards, - lane_id: bp_messages::LaneId, + lane_id: RewardsAccountParams, delivery_fee: T::Reward, confirmation_fee: T::Reward, ) { @@ -121,13 +130,19 @@ mod tests { register_relayers_rewards::( &RELAYER_2, relayers_rewards(), - TEST_LANE_ID, + TEST_REWARDS_ACCOUNT_PARAMS, 50, 10, ); - assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), Some(170)); + assert_eq!( + RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), + Some(80) + ); + assert_eq!( + RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), + Some(170) + ); }); } @@ -137,14 +152,23 @@ mod tests { register_relayers_rewards::( &RELAYER_3, relayers_rewards(), - TEST_LANE_ID, + TEST_REWARDS_ACCOUNT_PARAMS, 50, 10, ); - assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), Some(80)); - assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), Some(120)); - assert_eq!(RelayerRewards::::get(RELAYER_3, TEST_LANE_ID), Some(50)); + assert_eq!( + RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), + Some(80) + ); + assert_eq!( + RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), + Some(120) + ); + assert_eq!( + RelayerRewards::::get(RELAYER_3, TEST_REWARDS_ACCOUNT_PARAMS), + Some(50) + ); }); } @@ -154,14 +178,23 @@ mod tests { register_relayers_rewards::( &RELAYER_3, relayers_rewards(), - TEST_LANE_ID, + TEST_REWARDS_ACCOUNT_PARAMS, 50, 1000, ); - assert_eq!(RelayerRewards::::get(RELAYER_1, TEST_LANE_ID), None); - assert_eq!(RelayerRewards::::get(RELAYER_2, TEST_LANE_ID), None); - assert_eq!(RelayerRewards::::get(RELAYER_3, TEST_LANE_ID), Some(250)); + assert_eq!( + RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), + None + ); + assert_eq!( + RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), + None + ); + assert_eq!( + RelayerRewards::::get(RELAYER_3, TEST_REWARDS_ACCOUNT_PARAMS), + Some(250) + ); }); } } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index fdaeee4f22a3e..572935f63025e 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-02-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! HOSTNAME: `serban-ROG-Zephyrus`, CPU: `12th Gen Intel(R) Core(TM) i7-12700H` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -60,7 +60,7 @@ pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) /// /// Storage: System Account (r:1 w:1) @@ -69,10 +69,10 @@ impl WeightInfo for BridgeWeight { /// MaxEncodedLen) fn claim_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `534` - // Estimated: `5106` - // Minimum execution time: 48_239 nanoseconds. - Weight::from_parts(50_579_000, 5106) + // Measured: `275` + // Estimated: `5111` + // Minimum execution time: 43_031 nanoseconds. + Weight::from_parts(44_527_000, 5111) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -82,7 +82,7 @@ impl WeightInfo for BridgeWeight { impl WeightInfo for () { /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) /// /// Storage: System Account (r:1 w:1) @@ -91,10 +91,10 @@ impl WeightInfo for () { /// MaxEncodedLen) fn claim_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `534` - // Estimated: `5106` - // Minimum execution time: 48_239 nanoseconds. - Weight::from_parts(50_579_000, 5106) + // Measured: `275` + // Estimated: `5111` + // Minimum execution time: 43_031 nanoseconds. + Weight::from_parts(44_527_000, 5111) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 7479811a57d7b..ee91361a4e279 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index 70a91ee941a0d..fb35095841502 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -20,46 +20,95 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::LaneId; -use bp_runtime::StorageDoubleMapKeyProvider; +use bp_runtime::{ChainId, StorageDoubleMapKeyProvider}; use frame_support::{Blake2_128Concat, Identity}; +use scale_info::TypeInfo; use sp_runtime::{ - codec::{Codec, Decode, Encode, EncodeLike}, + codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}, traits::AccountIdConversion, + TypeId, }; use sp_std::{fmt::Debug, marker::PhantomData}; +/// The owner of the sovereign account that should pay the rewards. +/// +/// Each of the 2 final points connected by a bridge owns a sovereign account at each end of the +/// bridge. So here, at this end of the bridge there can be 2 sovereign accounts that pay rewards. +#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub enum RewardsAccountOwner { + /// The sovereign account of the final chain on this end of the bridge. + ThisChain, + /// The sovereign account of the final chain on the other end of the bridge. + BridgedChain, +} + +/// Structure used to identify the account that pays a reward to the relayer. +/// +/// A bridge connects 2 bridge ends. Each one is located on a separate relay chain. The bridge ends +/// can be the final destinations of the bridge, or they can be intermediary points +/// (e.g. a bridge hub) used to forward messages between pairs of parachains on the bridged relay +/// chains. A pair of such parachains is connected using a bridge lane. Each of the 2 final +/// destinations of a bridge lane must have a sovereign account at each end of the bridge and each +/// of the sovereign accounts will pay rewards for different operations. So we need multiple +/// parameters to identify the account that pays a reward to the relayer. +#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub struct RewardsAccountParams { + lane_id: LaneId, + bridged_chain_id: ChainId, + owner: RewardsAccountOwner, +} + +impl RewardsAccountParams { + /// Create a new instance of `RewardsAccountParams`. + pub const fn new( + lane_id: LaneId, + bridged_chain_id: ChainId, + owner: RewardsAccountOwner, + ) -> Self { + Self { lane_id, bridged_chain_id, owner } + } +} + +impl TypeId for RewardsAccountParams { + const TYPE_ID: [u8; 4] = *b"brap"; +} + /// Reward payment procedure. pub trait PaymentProcedure { /// Error that may be returned by the procedure. type Error: Debug; - /// Pay reward to the relayer for serving given message lane. - fn pay_reward(relayer: &Relayer, lane_id: LaneId, reward: Reward) -> Result<(), Self::Error>; + /// Pay reward to the relayer from the account with provided params. + fn pay_reward( + relayer: &Relayer, + rewards_account_params: RewardsAccountParams, + reward: Reward, + ) -> Result<(), Self::Error>; } impl PaymentProcedure for () { type Error = &'static str; - fn pay_reward(_: &Relayer, _: LaneId, _: Reward) -> Result<(), Self::Error> { + fn pay_reward(_: &Relayer, _: RewardsAccountParams, _: Reward) -> Result<(), Self::Error> { Ok(()) } } /// Reward payment procedure that does `balances::transfer` call from the account, derived from -/// given lane. -pub struct PayLaneRewardFromAccount(PhantomData<(T, Relayer)>); +/// given params. +pub struct PayRewardFromAccount(PhantomData<(T, Relayer)>); -impl PayLaneRewardFromAccount +impl PayRewardFromAccount where Relayer: Decode + Encode, { - /// Return account that pay rewards for serving given lane. - pub fn lane_rewards_account(lane_id: LaneId) -> Relayer { - lane_id.into_sub_account_truncating(b"bridge-lane") + /// Return account that pays rewards based on the provided parameters. + pub fn rewards_account(params: RewardsAccountParams) -> Relayer { + params.into_sub_account_truncating(b"rewards-account") } } -impl PaymentProcedure for PayLaneRewardFromAccount +impl PaymentProcedure for PayRewardFromAccount where T: frame_support::traits::fungible::Transfer, Relayer: Decode + Encode, @@ -68,10 +117,11 @@ where fn pay_reward( relayer: &Relayer, - lane_id: LaneId, + rewards_account_params: RewardsAccountParams, reward: T::Balance, ) -> Result<(), Self::Error> { - T::transfer(&Self::lane_rewards_account(lane_id), relayer, reward, false).map(drop) + T::transfer(&Self::rewards_account(rewards_account_params), relayer, reward, false) + .map(drop) } } @@ -89,26 +139,58 @@ where type Hasher1 = Blake2_128Concat; type Key1 = AccountId; type Hasher2 = Identity; - type Key2 = LaneId; + type Key2 = RewardsAccountParams; type Value = Reward; } #[cfg(test)] mod tests { use super::*; + use bp_messages::LaneId; use sp_runtime::testing::H256; #[test] - fn lanes_are_using_different_accounts() { + fn different_lanes_are_using_different_accounts() { + assert_eq!( + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::ThisChain + )), + hex_literal::hex!("62726170000000007465737400726577617264732d6163636f756e7400000000") + .into(), + ); + + assert_eq!( + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 1]), + *b"test", + RewardsAccountOwner::ThisChain + )), + hex_literal::hex!("62726170000000017465737400726577617264732d6163636f756e7400000000") + .into(), + ); + } + + #[test] + fn different_directions_are_using_different_accounts() { assert_eq!( - PayLaneRewardFromAccount::<(), H256>::lane_rewards_account(LaneId([0, 0, 0, 0])), - hex_literal::hex!("626c616e000000006272696467652d6c616e6500000000000000000000000000") + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::ThisChain + )), + hex_literal::hex!("62726170000000007465737400726577617264732d6163636f756e7400000000") .into(), ); assert_eq!( - PayLaneRewardFromAccount::<(), H256>::lane_rewards_account(LaneId([0, 0, 0, 1])), - hex_literal::hex!("626c616e000000016272696467652d6c616e6500000000000000000000000000") + PayRewardFromAccount::<(), H256>::rewards_account(RewardsAccountParams::new( + LaneId([0, 0, 0, 0]), + *b"test", + RewardsAccountOwner::BridgedChain + )), + hex_literal::hex!("62726170000000007465737401726577617264732d6163636f756e7400000000") .into(), ); } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 0121b4ab84eb2..2d29b5aff0ab9 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -74,6 +74,12 @@ pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; /// Bridge-with-Kusama instance id. pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; +/// Bridge-with-Westend instance id. +pub const WESTEND_CHAIN_ID: ChainId = *b"wend"; + +/// Bridge-with-Westend instance id. +pub const WESTMINT_CHAIN_ID: ChainId = *b"wmnt"; + /// Bridge-with-Rococo instance id. pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 9a9316fa1177e..78c3533971c70 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -17,6 +17,7 @@ bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } +bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index c8963f968d002..02c389ffa29d2 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -18,6 +18,7 @@ use bp_bridge_hub_rococo::AVERAGE_BLOCK_INTERVAL; use bp_messages::MessageNonce; +use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, @@ -41,6 +42,7 @@ impl UnderlyingChainProvider for BridgeHubRococo { } impl Chain for BridgeHubRococo { + const ID: ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID; const NAME: &'static str = "BridgeHubRococo"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 7f23c0d93d2af..359692b0e3f9a 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -18,6 +18,7 @@ use bp_bridge_hub_wococo::AVERAGE_BLOCK_INTERVAL; use bp_messages::MessageNonce; +use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, @@ -41,6 +42,7 @@ impl UnderlyingChainProvider for BridgeHubWococo { } impl Chain for BridgeHubWococo { + const ID: ChainId = bp_runtime::BRIDGE_HUB_WOCOCO_CHAIN_ID; const NAME: &'static str = "BridgeHubWococo"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index e4d83d88ceb37..302f530eb4e96 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies bp-kusama = { path = "../../primitives/chain-kusama" } +bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 83f6b30f4cb29..4b631b6052b79 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -17,6 +17,7 @@ //! Types used to connect to the Kusama chain. use bp_kusama::AccountInfoStorageMapKeyProvider; +use bp_runtime::ChainId; use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -33,6 +34,7 @@ impl UnderlyingChainProvider for Kusama { } impl Chain for Kusama { + const ID: ChainId = bp_runtime::KUSAMA_CHAIN_ID; const NAME: &'static str = "Kusama"; const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 66395d5de897c..fe5482e5b6721 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -14,6 +14,7 @@ relay-utils = { path = "../utils" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } +bp-runtime = { path = "../../primitives/runtime" } millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 9df21b1d503e6..1c8a0f984ef0a 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -17,6 +17,7 @@ //! Types used to connect to the Millau-Substrate chain. use bp_messages::MessageNonce; +use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, @@ -54,6 +55,7 @@ impl ChainWithMessages for Millau { } impl Chain for Millau { + const ID: ChainId = bp_runtime::MILLAU_CHAIN_ID; const NAME: &'static str = "Millau"; // Rialto token has no value, but we associate it with KSM token const TOKEN_ID: Option<&'static str> = Some("kusama"); diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index cc16ec1f5c3a1..0d3a30949cbbb 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 19326dd4c7303..08837bdcec2f6 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -17,6 +17,7 @@ //! Types used to connect to the Polkadot chain. use bp_polkadot::AccountInfoStorageMapKeyProvider; +use bp_runtime::ChainId; use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -33,6 +34,7 @@ impl UnderlyingChainProvider for Polkadot { } impl Chain for Polkadot { + const ID: ChainId = bp_runtime::POLKADOT_CHAIN_ID; const NAME: &'static str = "Polkadot"; const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 96929d55cc83d..c1a6b5d69aaf1 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -17,6 +17,7 @@ bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } +bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 654848da2a736..27673dc23be1d 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -20,6 +20,7 @@ pub mod codegen_runtime; use bp_messages::MessageNonce; use bp_polkadot_core::PolkadotSignedExtension; +use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, @@ -48,6 +49,7 @@ impl UnderlyingChainProvider for RialtoParachain { } impl Chain for RialtoParachain { + const ID: ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; const NAME: &'static str = "RialtoParachain"; // RialtoParachain token has no value, but we associate it with DOT token const TOKEN_ID: Option<&'static str> = Some("polkadot"); diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index ef339feb8a556..c1ae0dfabe7ec 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -14,6 +14,7 @@ relay-utils = { path = "../utils" } bp-messages = { path = "../../primitives/messages" } bp-rialto = { path = "../../primitives/chain-rialto" } +bp-runtime = { path = "../../primitives/runtime" } rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index b822dfe7d89f3..7fe735b4adcac 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -17,6 +17,7 @@ //! Types used to connect to the Rialto-Substrate chain. use bp_messages::MessageNonce; +use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, @@ -39,6 +40,7 @@ impl UnderlyingChainProvider for Rialto { } impl Chain for Rialto { + const ID: ChainId = bp_runtime::RIALTO_CHAIN_ID; const NAME: &'static str = "Rialto"; // Rialto token has no value, but we associate it with DOT token const TOKEN_ID: Option<&'static str> = Some("polkadot"); diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index cc197ba8562e7..2a5b556dce22c 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -12,6 +12,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index a0730026e04c6..5049778a5420d 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Rococo-Substrate chain. +use bp_runtime::ChainId; use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -35,6 +36,7 @@ impl UnderlyingChainProvider for Rococo { } impl Chain for Rococo { + const ID: ChainId = bp_runtime::ROCOCO_CHAIN_ID; const NAME: &'static str = "Rococo"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index b55ae71cbf87f..bc38d1ec9323e 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -18,8 +18,8 @@ use crate::calls::UtilityCall; use bp_messages::MessageNonce; use bp_runtime::{ - Chain as ChainBase, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra, - TransactionEraOf, UnderlyingChainProvider, + Chain as ChainBase, ChainId, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, + TransactionEra, TransactionEraOf, UnderlyingChainProvider, }; use codec::{Codec, Encode}; use jsonrpsee::core::{DeserializeOwned, Serialize}; @@ -35,6 +35,8 @@ use std::{fmt::Debug, time::Duration}; /// Substrate-based chain from minimal relay-client point of view. pub trait Chain: ChainBase + Clone { + /// Chain id. + const ID: ChainId; /// Chain name. const NAME: &'static str; /// Identifier of the basic token of the chain (if applicable). diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 4589687d39de1..9bc6c5ae15cc4 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -22,6 +22,7 @@ #![cfg(any(feature = "test-helpers", test))] use crate::{Chain, ChainWithBalances}; +use bp_runtime::ChainId; use frame_support::weights::Weight; use std::time::Duration; @@ -50,6 +51,7 @@ impl bp_runtime::Chain for TestChain { } impl Chain for TestChain { + const ID: ChainId = *b"test"; const NAME: &'static str = "Test"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod"; diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index c60305868ad0f..351013bd86446 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -11,6 +11,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies +bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index a8a8df36b8bf9..6db8eaf95e40d 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Westend chain. +use bp_runtime::ChainId; use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -35,6 +36,7 @@ impl UnderlyingChainProvider for Westend { } impl Chain for Westend { + const ID: ChainId = bp_runtime::WESTEND_CHAIN_ID; const NAME: &'static str = "Westend"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = @@ -68,6 +70,7 @@ impl UnderlyingChainProvider for Westmint { // Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend // primitives here. impl Chain for Westmint { + const ID: ChainId = bp_runtime::WESTMINT_CHAIN_ID; const NAME: &'static str = "Westmint"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 19483ab22fd5c..78a5afe17cabc 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -11,6 +11,7 @@ relay-utils = { path = "../utils" } # Bridge dependencies +bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } # Substrate Dependencies diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 8f30572db63af..582c34ef85363 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,6 +16,7 @@ //! Types used to connect to the Wococo-Substrate chain. +use bp_runtime::ChainId; use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -35,6 +36,7 @@ impl UnderlyingChainProvider for Wococo { } impl Chain for Wococo { + const ID: ChainId = bp_runtime::WOCOCO_CHAIN_ID; const NAME: &'static str = "Wococo"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 943f3b7c3694f..33d855a026318 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -19,6 +19,7 @@ use crate::TaggedAccount; use bp_messages::LaneId; +use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::StorageDoubleMapKeyProvider; use codec::Decode; use frame_system::AccountInfo; @@ -82,18 +83,29 @@ where if let Some(relayers_pallet_name) = BC::WITH_CHAIN_RELAYERS_PALLET_NAME { for lane in lanes { - let relay_account_reward_metric = FloatStorageValueMetric::new( + FloatStorageValueMetric::new( AccountBalance:: { token_decimals, _phantom: Default::default() }, client.clone(), bp_relayers::RelayerRewardsKeyProvider::, BalanceOf>::final_key( relayers_pallet_name, account.id(), - lane, + &RewardsAccountParams::new(*lane, BC::ID, RewardsAccountOwner::ThisChain), ), - format!("at_{}_relay_{}_reward_for_lane_{}_with_{}", C::NAME, account.tag(), hex::encode(lane.as_ref()), BC::NAME), - format!("Reward of the {} relay account for serving lane {:?} with {} at the {}", account.tag(), lane, BC::NAME, C::NAME), - )?; - relay_account_reward_metric.register_and_spawn(&metrics.registry)?; + format!("at_{}_relay_{}_reward_for_msgs_from_{}_on_lane_{}", C::NAME, account.tag(), BC::NAME, hex::encode(lane.as_ref())), + format!("Reward of the {} relay account at {} for delivering messages from {} on lane {:?}", account.tag(), C::NAME, BC::NAME, lane), + )?.register_and_spawn(&metrics.registry)?; + + FloatStorageValueMetric::new( + AccountBalance:: { token_decimals, _phantom: Default::default() }, + client.clone(), + bp_relayers::RelayerRewardsKeyProvider::, BalanceOf>::final_key( + relayers_pallet_name, + account.id(), + &RewardsAccountParams::new(*lane, BC::ID, RewardsAccountOwner::BridgedChain), + ), + format!("at_{}_relay_{}_reward_for_msgs_to_{}_on_lane_{}", C::NAME, account.tag(), BC::NAME, hex::encode(lane.as_ref())), + format!("Reward of the {} relay account at {} for delivering messages confirmations from {} on lane {:?}", account.tag(), C::NAME, BC::NAME, lane), + )?.register_and_spawn(&metrics.registry)?; } } } From 0eb3e34151b9532999f6c131e0cffbf8ae057987 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 28 Feb 2023 13:54:12 +0200 Subject: [PATCH 0964/1210] Refund messages confirmation tx (#1904) * Refund messages confirmation tx * Fixes --- bin/millau/runtime/src/lib.rs | 2 - bin/rialto-parachain/runtime/src/lib.rs | 1 - bin/rialto/runtime/src/lib.rs | 1 - bin/runtime-common/src/lib.rs | 3 +- bin/runtime-common/src/messages_call_ext.rs | 219 +++++++----- bin/runtime-common/src/mock.rs | 3 +- .../src/refund_relayer_extension.rs | 321 ++++++++++++++---- modules/relayers/src/payment_adapter.rs | 67 +--- 8 files changed, 407 insertions(+), 210 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index fdbcddc0f3828..3e46d6ba15a62 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -453,7 +453,6 @@ impl pallet_bridge_messages::Config for Runtime { Runtime, WithRialtoMessagesInstance, frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<10_000>, >; type SourceHeaderChain = crate::rialto_messages::RialtoAsSourceHeaderChain; @@ -485,7 +484,6 @@ impl pallet_bridge_messages::Config for Run Runtime, WithRialtoParachainMessagesInstance, frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<10_000>, >; type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsSourceHeaderChain; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index f2e408def3097..593c7b21228d5 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -571,7 +571,6 @@ impl pallet_bridge_messages::Config for Runtime { Runtime, WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, - frame_support::traits::ConstU128<100_000>, >; type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index c090bb59b9228..9873a6fd85593 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -445,7 +445,6 @@ impl pallet_bridge_messages::Config for Runtime { Runtime, WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, - frame_support::traits::ConstU128<100_000>, >; type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 32ea500db3ed8..d9c87049077ae 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -77,8 +77,7 @@ where /// even honest relayers may lose their funds if there are multiple relays running and /// submitting the same messages/confirmations. fn validate(call: &T::RuntimeCall) -> TransactionValidity { - call.check_obsolete_receive_messages_proof()?; - call.check_obsolete_receive_messages_delivery_proof() + call.check_obsolete_call() } } diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 740d17129c894..588afad106da6 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -22,25 +22,57 @@ use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; use pallet_bridge_messages::{Config, Pallet}; use sp_runtime::transaction_validity::TransactionValidity; -/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. +/// Generic info about a messages delivery/confirmation proof. #[derive(PartialEq, RuntimeDebug)] -pub struct ReceiveMessagesProofInfo { +pub struct BaseMessagesProofInfo { pub lane_id: LaneId, - pub best_proof_nonce: MessageNonce, + pub best_bundled_nonce: MessageNonce, pub best_stored_nonce: MessageNonce, } -/// Helper struct that provides methods for working with the `ReceiveMessagesProof` call. -pub struct ReceiveMessagesProofHelper, I: 'static> { +impl BaseMessagesProofInfo { + fn is_obsolete(&self) -> bool { + self.best_bundled_nonce <= self.best_stored_nonce + } +} + +/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub struct ReceiveMessagesProofInfo(pub BaseMessagesProofInfo); + +/// Info about a `ReceiveMessagesDeliveryProof` call which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub struct ReceiveMessagesDeliveryProofInfo(pub BaseMessagesProofInfo); + +/// Info about a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call +/// which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub enum CallInfo { + ReceiveMessagesProof(ReceiveMessagesProofInfo), + ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo), +} + +/// Helper struct that provides methods for working with a call supported by `CallInfo`. +pub struct CallHelper, I: 'static> { pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, } -impl, I: 'static> ReceiveMessagesProofHelper { - /// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that - /// it contained. - pub fn was_partially_successful(info: &ReceiveMessagesProofInfo) -> bool { - let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(info.lane_id); - inbound_lane_data.last_delivered_nonce() > info.best_stored_nonce +impl, I: 'static> CallHelper { + /// Check if a call delivered proof/confirmation for at least some of the messages that it + /// contained. + pub fn was_partially_successful(info: &CallInfo) -> bool { + match info { + CallInfo::ReceiveMessagesProof(info) => { + let inbound_lane_data = + pallet_bridge_messages::InboundLanes::::get(info.0.lane_id); + inbound_lane_data.last_delivered_nonce() > info.0.best_stored_nonce + }, + CallInfo::ReceiveMessagesDeliveryProof(info) => { + let outbound_lane_data = + pallet_bridge_messages::OutboundLanes::::get(info.0.lane_id); + outbound_lane_data.latest_received_nonce > info.0.best_stored_nonce + }, + } } } @@ -51,17 +83,21 @@ pub trait MessagesCallSubType, I: 'static>: /// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call. fn receive_messages_proof_info(&self) -> Option; - /// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call, - /// if the call is for the provided lane. - fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option; + /// Create a new instance of `ReceiveMessagesDeliveryProofInfo` from + /// a `ReceiveMessagesDeliveryProof` call. + fn receive_messages_delivery_proof_info(&self) -> Option; + + /// Create a new instance of `CallInfo` from a `ReceiveMessagesProof` + /// or a `ReceiveMessagesDeliveryProof` call. + fn call_info(&self) -> Option; - /// Check that a `ReceiveMessagesProof` call is trying to deliver at least some messages that - /// are better than the ones we know of. - fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity; + /// Create a new instance of `CallInfo` from a `ReceiveMessagesProof` + /// or a `ReceiveMessagesDeliveryProof` call, if the call is for the provided lane. + fn call_info_for(&self, lane_id: LaneId) -> Option; - /// Check that a `ReceiveMessagesDeliveryProof` call is trying to deliver at least some message - /// confirmations that are better than the ones we know of. - fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity; + /// Check that a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call is trying + /// to deliver/confirm at least some messages that are better than the ones we know of. + fn check_obsolete_call(&self) -> TransactionValidity; } impl< @@ -88,40 +124,17 @@ impl< { let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(proof.lane); - return Some(ReceiveMessagesProofInfo { + return Some(ReceiveMessagesProofInfo(BaseMessagesProofInfo { lane_id: proof.lane, - best_proof_nonce: proof.nonces_end, + best_bundled_nonce: proof.nonces_end, best_stored_nonce: inbound_lane_data.last_delivered_nonce(), - }) + })) } None } - fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option { - self.receive_messages_proof_info().filter(|info| info.lane_id == lane_id) - } - - fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity { - if let Some(proof_info) = self.receive_messages_proof_info() { - if proof_info.best_proof_nonce <= proof_info.best_stored_nonce { - log::trace!( - target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages delivery transaction: \ - lane {:?}, bundled {:?}, best {:?}", - proof_info.lane_id, - proof_info.best_proof_nonce, - proof_info.best_stored_nonce, - ); - - return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } - } - - Ok(sp_runtime::transaction_validity::ValidTransaction::default()) - } - - fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity { + fn receive_messages_delivery_proof_info(&self) -> Option { if let Some(pallet_bridge_messages::Call::::receive_messages_delivery_proof { ref proof, ref relayers_state, @@ -129,18 +142,62 @@ impl< }) = self.is_sub_type() { let outbound_lane_data = pallet_bridge_messages::OutboundLanes::::get(proof.lane); - if relayers_state.last_delivered_nonce <= outbound_lane_data.latest_received_nonce { + + return Some(ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { + lane_id: proof.lane, + best_bundled_nonce: relayers_state.last_delivered_nonce, + best_stored_nonce: outbound_lane_data.latest_received_nonce, + })) + } + + None + } + + fn call_info(&self) -> Option { + if let Some(info) = self.receive_messages_proof_info() { + return Some(CallInfo::ReceiveMessagesProof(info)) + } + + if let Some(info) = self.receive_messages_delivery_proof_info() { + return Some(CallInfo::ReceiveMessagesDeliveryProof(info)) + } + + None + } + + fn call_info_for(&self, lane_id: LaneId) -> Option { + self.call_info().filter(|info| { + let actual_lane_id = match info { + CallInfo::ReceiveMessagesProof(info) => info.0.lane_id, + CallInfo::ReceiveMessagesDeliveryProof(info) => info.0.lane_id, + }; + actual_lane_id == lane_id + }) + } + + fn check_obsolete_call(&self) -> TransactionValidity { + match self.call_info() { + Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.0.is_obsolete() => { log::trace!( target: pallet_bridge_messages::LOG_TARGET, - "Rejecting obsolete messages confirmation transaction: \ - lane {:?}, bundled {:?}, best {:?}", - proof.lane, - relayers_state.last_delivered_nonce, - outbound_lane_data.latest_received_nonce, + "Rejecting obsolete messages delivery transaction: {:?}", + proof_info ); return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() - } + }, + Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info)) + if proof_info.0.is_obsolete() => + { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting obsolete messages confirmation transaction: {:?}", + proof_info, + ); + + return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() + }, + _ => {}, } Ok(sp_runtime::transaction_validity::ValidTransaction::default()) @@ -153,8 +210,8 @@ mod tests { messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }, + messages_call_ext::MessagesCallSubType, mock::{TestRuntime, ThisChainRuntimeCall}, - BridgeRuntimeFilterCall, }; use bp_messages::UnrewardedRelayersState; @@ -169,22 +226,21 @@ mod tests { nonces_start: bp_messages::MessageNonce, nonces_end: bp_messages::MessageNonce, ) -> bool { - pallet_bridge_messages::Pallet::::validate( - &ThisChainRuntimeCall::BridgeMessages( - pallet_bridge_messages::Call::::receive_messages_proof { - relayer_id_at_bridged_chain: 42, - messages_count: (nonces_end - nonces_start + 1) as u32, - dispatch_weight: frame_support::weights::Weight::zero(), - proof: FromBridgedChainMessagesProof { - bridged_header_hash: Default::default(), - storage_proof: vec![], - lane: bp_messages::LaneId([0, 0, 0, 0]), - nonces_start, - nonces_end, - }, + ThisChainRuntimeCall::BridgeMessages( + pallet_bridge_messages::Call::::receive_messages_proof { + relayer_id_at_bridged_chain: 42, + messages_count: (nonces_end - nonces_start + 1) as u32, + dispatch_weight: frame_support::weights::Weight::zero(), + proof: FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof: vec![], + lane: bp_messages::LaneId([0, 0, 0, 0]), + nonces_start, + nonces_end, }, - ), + }, ) + .check_obsolete_call() .is_ok() } @@ -230,21 +286,20 @@ mod tests { } fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool { - pallet_bridge_messages::Pallet::::validate( - &ThisChainRuntimeCall::BridgeMessages( - pallet_bridge_messages::Call::::receive_messages_delivery_proof { - proof: FromBridgedChainMessagesDeliveryProof { - bridged_header_hash: Default::default(), - storage_proof: Vec::new(), - lane: bp_messages::LaneId([0, 0, 0, 0]), - }, - relayers_state: UnrewardedRelayersState { - last_delivered_nonce, - ..Default::default() - }, + ThisChainRuntimeCall::BridgeMessages( + pallet_bridge_messages::Call::::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: Vec::new(), + lane: bp_messages::LaneId([0, 0, 0, 0]), + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce, + ..Default::default() }, - ), + }, ) + .check_obsolete_call() .is_ok() } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 29c540bc66463..c2cd8e9ba8308 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -230,8 +230,7 @@ impl pallet_bridge_messages::Config for TestRuntime { type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< TestRuntime, (), - frame_support::traits::ConstU64<100_000>, - frame_support::traits::ConstU64<10_000>, + ConstU64<100_000>, >; type SourceHeaderChain = SourceHeaderChainAdapter; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index aa03082e9f57d..0a61f4fdd023f 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -20,7 +20,7 @@ //! (parachain or relay chain). use crate::messages_call_ext::{ - MessagesCallSubType, ReceiveMessagesProofHelper, ReceiveMessagesProofInfo, + CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo, MessagesCallSubType, }; use bp_messages::LaneId; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; @@ -143,23 +143,23 @@ pub struct PreDispatchData { /// Type of the call that the extension recognizes. #[derive(RuntimeDebugNoBound, PartialEq)] pub enum CallInfo { - /// Relay chain finality + parachain finality + message delivery calls. - AllFinalityAndDelivery( + /// Relay chain finality + parachain finality + message delivery/confirmation calls. + AllFinalityAndMsgs( SubmitFinalityProofInfo, SubmitParachainHeadsInfo, - ReceiveMessagesProofInfo, + MessagesCallInfo, ), - /// Parachain finality + message delivery calls. - ParachainFinalityAndDelivery(SubmitParachainHeadsInfo, ReceiveMessagesProofInfo), - /// Standalone message delivery call. - Delivery(ReceiveMessagesProofInfo), + /// Parachain finality + message delivery/confirmation calls. + ParachainFinalityAndMsgs(SubmitParachainHeadsInfo, MessagesCallInfo), + /// Standalone message delivery/confirmation call. + Msgs(MessagesCallInfo), } impl CallInfo { /// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call. fn submit_finality_proof_info(&self) -> Option> { match *self { - Self::AllFinalityAndDelivery(info, _, _) => Some(info), + Self::AllFinalityAndMsgs(info, _, _) => Some(info), _ => None, } } @@ -167,18 +167,18 @@ impl CallInfo { /// Returns the pre-dispatch `SubmitParachainHeadsInfo`. fn submit_parachain_heads_info(&self) -> Option<&SubmitParachainHeadsInfo> { match self { - Self::AllFinalityAndDelivery(_, info, _) => Some(info), - Self::ParachainFinalityAndDelivery(info, _) => Some(info), + Self::AllFinalityAndMsgs(_, info, _) => Some(info), + Self::ParachainFinalityAndMsgs(info, _) => Some(info), _ => None, } } /// Returns the pre-dispatch `ReceiveMessagesProofInfo`. - fn receive_messages_proof_info(&self) -> &ReceiveMessagesProofInfo { + fn messages_call_info(&self) -> &MessagesCallInfo { match self { - Self::AllFinalityAndDelivery(_, _, info) => info, - Self::ParachainFinalityAndDelivery(_, info) => info, - Self::Delivery(info) => info, + Self::AllFinalityAndMsgs(_, _, info) => info, + Self::ParachainFinalityAndMsgs(_, info) => info, + Self::Msgs(info) => info, } } } @@ -269,7 +269,7 @@ where for nested_call in calls { nested_call.check_obsolete_submit_finality_proof()?; nested_call.check_obsolete_submit_parachain_heads()?; - nested_call.check_obsolete_receive_messages_proof()?; + nested_call.check_obsolete_call()?; } } @@ -290,18 +290,16 @@ where let parse_call = || { let mut calls = self.expand_call(call)?.into_iter(); match calls.len() { - 3 => Some(CallInfo::AllFinalityAndDelivery( + 3 => Some(CallInfo::AllFinalityAndMsgs( calls.next()?.submit_finality_proof_info()?, calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, - calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, + calls.next()?.call_info_for(Msgs::Id::get())?, )), - 2 => Some(CallInfo::ParachainFinalityAndDelivery( + 2 => Some(CallInfo::ParachainFinalityAndMsgs( calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, - calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, - )), - 1 => Some(CallInfo::Delivery( - calls.next()?.receive_messages_proof_info_for(Msgs::Id::get())?, + calls.next()?.call_info_for(Msgs::Id::get())?, )), + 1 => Some(CallInfo::Msgs(calls.next()?.call_info_for(Msgs::Id::get())?)), _ => None, } }; @@ -374,10 +372,9 @@ where // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that // it contained. If this happens, we consider the transaction "helpful" and refund it. - let msgs_proof_info = call_info.receive_messages_proof_info(); - if !ReceiveMessagesProofHelper::::was_partially_successful( - msgs_proof_info, - ) { + let msgs_call_info = call_info.messages_call_info(); + if !MessagesCallHelper::::was_partially_successful(msgs_call_info) + { return Ok(()) } @@ -398,11 +395,15 @@ where let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); // finally - register refund in relayers pallet + let rewards_account_owner = match msgs_call_info { + MessagesCallInfo::ReceiveMessagesProof(_) => RewardsAccountOwner::ThisChain, + MessagesCallInfo::ReceiveMessagesDeliveryProof(_) => RewardsAccountOwner::BridgedChain, + }; RelayersPallet::::register_relayer_reward( RewardsAccountParams::new( Msgs::Id::get(), Runtime::BridgedChainId::get(), - RewardsAccountOwner::ThisChain, + rewards_account_owner, ), &relayer, refund, @@ -425,8 +426,16 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{messages::target::FromBridgedChainMessagesProof, mock::*}; - use bp_messages::{InboundLaneData, MessageNonce}; + use crate::{ + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + }, + messages_call_ext::{ + BaseMessagesProofInfo, ReceiveMessagesDeliveryProofInfo, ReceiveMessagesProofInfo, + }, + mock::*, + }; + use bp_messages::{InboundLaneData, MessageNonce, OutboundLaneData, UnrewardedRelayersState}; use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderId; @@ -442,7 +451,8 @@ mod tests { parameter_types! { TestParachain: u32 = 1000; pub TestLaneId: LaneId = TEST_LANE_ID; - pub DirectedTestLaneId: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::ThisChain); + pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::ThisChain); + pub MsgDeliveryProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::BridgedChain); } bp_runtime::generate_static_str_provider!(TestExtension); @@ -466,7 +476,7 @@ mod tests { best_relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, parachain_head_hash: ParaHash, - best_delivered_message: MessageNonce, + best_message: MessageNonce, ) { let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect(); let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); @@ -486,9 +496,13 @@ mod tests { pallet_bridge_parachains::ParasInfo::::insert(para_id, para_info); let lane_id = TestLaneId::get(); - let lane_data = - InboundLaneData { last_confirmed_nonce: best_delivered_message, ..Default::default() }; - pallet_bridge_messages::InboundLanes::::insert(lane_id, lane_data); + let in_lane_data = + InboundLaneData { last_confirmed_nonce: best_message, ..Default::default() }; + pallet_bridge_messages::InboundLanes::::insert(lane_id, in_lane_data); + + let out_lane_data = + OutboundLaneData { latest_received_nonce: best_message, ..Default::default() }; + pallet_bridge_messages::OutboundLanes::::insert(lane_id, out_lane_data); } fn submit_relay_header_call(relay_header_number: RelayBlockNumber) -> RuntimeCall { @@ -532,6 +546,20 @@ mod tests { }) } + fn message_confirmation_call(best_message: MessageNonce) -> RuntimeCall { + RuntimeCall::BridgeMessages(MessagesCall::receive_messages_delivery_proof { + proof: FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: vec![], + lane: TestLaneId::get(), + }, + relayers_state: UnrewardedRelayersState { + last_delivered_nonce: best_message, + ..Default::default() + }, + }) + } + fn parachain_finality_and_delivery_batch_call( parachain_head_at_relay_header_number: RelayBlockNumber, best_message: MessageNonce, @@ -544,6 +572,18 @@ mod tests { }) } + fn parachain_finality_and_confirmation_batch_call( + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_and_delivery_batch_call( relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, @@ -558,10 +598,24 @@ mod tests { }) } + fn all_finality_and_confirmation_batch_call( + relay_header_number: RelayBlockNumber, + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call(relay_header_number), + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_info: CallInfo::AllFinalityAndDelivery( + call_info: CallInfo::AllFinalityAndMsgs( SubmitFinalityProofInfo { block_number: 200, extra_weight: Weight::zero(), @@ -572,11 +626,38 @@ mod tests { para_id: ParaId(TestParachain::get()), para_head_hash: [1u8; 32].into(), }, - ReceiveMessagesProofInfo { - lane_id: TEST_LANE_ID, - best_proof_nonce: 200, - best_stored_nonce: 100, + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), + ), + } + } + + fn all_finality_confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::AllFinalityAndMsgs( + SubmitFinalityProofInfo { + block_number: 200, + extra_weight: Weight::zero(), + extra_size: 0, }, + SubmitParachainHeadsInfo { + at_relay_block_number: 200, + para_id: ParaId(TestParachain::get()), + para_head_hash: [1u8; 32].into(), + }, + MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), ), } } @@ -584,17 +665,39 @@ mod tests { fn parachain_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_info: CallInfo::ParachainFinalityAndDelivery( + call_info: CallInfo::ParachainFinalityAndMsgs( SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), para_head_hash: [1u8; 32].into(), }, - ReceiveMessagesProofInfo { - lane_id: TEST_LANE_ID, - best_proof_nonce: 200, - best_stored_nonce: 100, + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), + ), + } + } + + fn parachain_finality_confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::ParachainFinalityAndMsgs( + SubmitParachainHeadsInfo { + at_relay_block_number: 200, + para_id: ParaId(TestParachain::get()), + para_head_hash: [1u8; 32].into(), }, + MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }, + )), ), } } @@ -602,11 +705,26 @@ mod tests { fn delivery_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), - call_info: CallInfo::Delivery(ReceiveMessagesProofInfo { - lane_id: TEST_LANE_ID, - best_proof_nonce: 200, - best_stored_nonce: 100, - }), + call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesProof( + ReceiveMessagesProofInfo(BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }), + )), + } + } + + fn confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesDeliveryProof( + ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + best_bundled_nonce: 200, + best_stored_nonce: 100, + }), + )), } } @@ -669,16 +787,28 @@ mod tests { initialize_environment(100, 100, Default::default(), 100); assert_eq!(run_validate(message_delivery_call(200)), Ok(ValidTransaction::default()),); + assert_eq!( + run_validate(message_confirmation_call(200)), + Ok(ValidTransaction::default()), + ); assert_eq!( run_validate(parachain_finality_and_delivery_batch_call(200, 200)), Ok(ValidTransaction::default()), ); + assert_eq!( + run_validate(parachain_finality_and_confirmation_batch_call(200, 200)), + Ok(ValidTransaction::default()), + ); assert_eq!( run_validate(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(ValidTransaction::default()), ); + assert_eq!( + run_validate(all_finality_and_confirmation_batch_call(200, 200, 200)), + Ok(ValidTransaction::default()), + ); }); } @@ -708,17 +838,15 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); - assert_eq!( - run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), + run_validate(all_finality_and_delivery_batch_call(101, 100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); assert_eq!( - run_validate(all_finality_and_delivery_batch_call(101, 100, 200)), + run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); - assert_eq!( run_validate(parachain_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), @@ -735,9 +863,8 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); - assert_eq!( - run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); @@ -745,11 +872,28 @@ mod tests { run_validate(all_finality_and_delivery_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(all_finality_and_confirmation_batch_call(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + assert_eq!( + run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_validate(parachain_finality_and_delivery_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(parachain_finality_and_confirmation_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } @@ -762,6 +906,10 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(Some(all_finality_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), + Ok(Some(all_finality_confirmation_pre_dispatch_data())), + ); }); } @@ -774,6 +922,10 @@ mod tests { run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), Ok(Some(parachain_finality_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)), + Ok(Some(parachain_finality_confirmation_pre_dispatch_data())), + ); }); } @@ -801,7 +953,7 @@ mod tests { } #[test] - fn pre_dispatch_parses_message_delivery_transaction() { + fn pre_dispatch_parses_message_transaction() { run_test(|| { initialize_environment(100, 100, Default::default(), 100); @@ -809,6 +961,10 @@ mod tests { run_pre_dispatch(message_delivery_call(200)), Ok(Some(delivery_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(message_confirmation_call(200)), + Ok(Some(confirmation_pre_dispatch_data())), + ); }); } @@ -862,6 +1018,16 @@ mod tests { Ok(()) )); assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()))); + + assert_storage_noop!(run_post_dispatch( + Some(all_finality_confirmation_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch( + Some(parachain_finality_confirmation_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()))); }); } @@ -882,7 +1048,7 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - DirectedTestLaneId::get() + MsgProofsRewardsAccount::get() ), Some(regular_reward), ); @@ -890,7 +1056,7 @@ mod tests { // now repeat the same with size+weight refund: we expect smaller reward let mut pre_dispatch_data = all_finality_pre_dispatch_data(); match pre_dispatch_data.call_info { - CallInfo::AllFinalityAndDelivery(ref mut info, ..) => { + CallInfo::AllFinalityAndMsgs(ref mut info, ..) => { info.extra_weight.set_ref_time( frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, ); @@ -901,7 +1067,7 @@ mod tests { run_post_dispatch(Some(pre_dispatch_data), Ok(())); let reward_after_two_calls = RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - DirectedTestLaneId::get(), + MsgProofsRewardsAccount::get(), ) .unwrap(); assert!( @@ -922,7 +1088,16 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - DirectedTestLaneId::get() + MsgProofsRewardsAccount::get() + ), + Some(expected_reward()), + ); + + run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + MsgDeliveryProofsRewardsAccount::get() ), Some(expected_reward()), ); @@ -938,7 +1113,16 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - DirectedTestLaneId::get() + MsgProofsRewardsAccount::get() + ), + Some(expected_reward()), + ); + + run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + MsgDeliveryProofsRewardsAccount::get() ), Some(expected_reward()), ); @@ -946,7 +1130,7 @@ mod tests { } #[test] - fn post_dispatch_refunds_relayer_in_message_delivery_transaction() { + fn post_dispatch_refunds_relayer_in_message_transaction() { run_test(|| { initialize_environment(200, 200, Default::default(), 200); @@ -954,7 +1138,16 @@ mod tests { assert_eq!( RelayersPallet::::relayer_reward( relayer_account_at_this_chain(), - DirectedTestLaneId::get() + MsgProofsRewardsAccount::get() + ), + Some(expected_reward()), + ); + + run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())); + assert_eq!( + RelayersPallet::::relayer_reward( + relayer_account_at_this_chain(), + MsgDeliveryProofsRewardsAccount::get() ), Some(expected_reward()), ); diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index cfd07cd6ccc23..2752044958b4f 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -24,22 +24,21 @@ use bp_messages::{ }; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; -use sp_arithmetic::traits::{Saturating, UniqueSaturatedFrom, Zero}; +use sp_arithmetic::traits::{Saturating, Zero}; use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Adapter that allows relayers pallet to be used as a delivery+dispatch payment mechanism /// for the messages pallet. -pub struct DeliveryConfirmationPaymentsAdapter( - PhantomData<(T, MI, DeliveryReward, ConfirmationReward)>, +pub struct DeliveryConfirmationPaymentsAdapter( + PhantomData<(T, MI, DeliveryReward)>, ); -impl DeliveryConfirmationPayments - for DeliveryConfirmationPaymentsAdapter +impl DeliveryConfirmationPayments + for DeliveryConfirmationPaymentsAdapter where T: Config + pallet_bridge_messages::Config, MI: 'static, DeliveryReward: Get, - ConfirmationReward: Get, { type Error = &'static str; @@ -61,7 +60,6 @@ where RewardsAccountOwner::BridgedChain, ), DeliveryReward::get(), - ConfirmationReward::get(), ); } } @@ -72,32 +70,17 @@ fn register_relayers_rewards( relayers_rewards: RelayersRewards, lane_id: RewardsAccountParams, delivery_fee: T::Reward, - confirmation_fee: T::Reward, ) { // reward every relayer except `confirmation_relayer` let mut confirmation_relayer_reward = T::Reward::zero(); for (relayer, messages) in relayers_rewards { // sane runtime configurations guarantee that the number of messages will be below // `u32::MAX` - let mut relayer_reward = - T::Reward::unique_saturated_from(messages).saturating_mul(delivery_fee); + let relayer_reward = T::Reward::saturated_from(messages).saturating_mul(delivery_fee); if relayer != *confirmation_relayer { - // If delivery confirmation is submitted by other relayer, let's deduct confirmation fee - // from relayer reward. - // - // If confirmation fee has been increased (or if it was the only component of message - // fee), then messages relayer may receive zero reward. - let mut confirmation_reward = - T::Reward::saturated_from(messages).saturating_mul(confirmation_fee); - confirmation_reward = sp_std::cmp::min(confirmation_reward, relayer_reward); - relayer_reward = relayer_reward.saturating_sub(confirmation_reward); - confirmation_relayer_reward = - confirmation_relayer_reward.saturating_add(confirmation_reward); Pallet::::register_relayer_reward(lane_id, &relayer, relayer_reward); } else { - // If delivery confirmation is submitted by this relayer, let's add confirmation fee - // from other relayers to this relayer reward. confirmation_relayer_reward = confirmation_relayer_reward.saturating_add(relayer_reward); } @@ -132,69 +115,41 @@ mod tests { relayers_rewards(), TEST_REWARDS_ACCOUNT_PARAMS, 50, - 10, ); assert_eq!( RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), - Some(80) + Some(100) ); assert_eq!( RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), - Some(170) + Some(150) ); }); } #[test] - fn confirmation_relayer_is_rewarded_if_it_has_not_delivered_any_delivered_messages() { + fn confirmation_relayer_is_not_rewarded_if_it_has_not_delivered_any_messages() { run_test(|| { register_relayers_rewards::( &RELAYER_3, relayers_rewards(), TEST_REWARDS_ACCOUNT_PARAMS, 50, - 10, ); assert_eq!( RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), - Some(80) + Some(100) ); assert_eq!( RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), - Some(120) + Some(150) ); assert_eq!( RelayerRewards::::get(RELAYER_3, TEST_REWARDS_ACCOUNT_PARAMS), - Some(50) - ); - }); - } - - #[test] - fn only_confirmation_relayer_is_rewarded_if_confirmation_fee_has_significantly_increased() { - run_test(|| { - register_relayers_rewards::( - &RELAYER_3, - relayers_rewards(), - TEST_REWARDS_ACCOUNT_PARAMS, - 50, - 1000, - ); - - assert_eq!( - RelayerRewards::::get(RELAYER_1, TEST_REWARDS_ACCOUNT_PARAMS), None ); - assert_eq!( - RelayerRewards::::get(RELAYER_2, TEST_REWARDS_ACCOUNT_PARAMS), - None - ); - assert_eq!( - RelayerRewards::::get(RELAYER_3, TEST_REWARDS_ACCOUNT_PARAMS), - Some(250) - ); }); } } From 23dd732ccf5ea4d13b741075d14a47d6e4d93e9f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Mar 2023 13:26:13 +0300 Subject: [PATCH 0965/1210] Fix multiple parachain headers submission for single message delivery (#1916) * switch off parachains relay when we don't need to relay parachains (temp solution) * parachains relay now only works with single parachain * fix usages of parachains relay * revert hacky fix * fixes * fixed Westmint parachain ID * fixed metrics * fixed compilation * fmt * clippy * call -> typed_state_call --- primitives/chain-westend/src/lib.rs | 2 +- .../src/chains/rialto_parachains_to_millau.rs | 6 - .../rococo_parachains_to_bridge_hub_wococo.rs | 6 - .../chains/westend_parachains_to_millau.rs | 6 - .../wococo_parachains_to_bridge_hub_rococo.rs | 6 - relays/bin-substrate/src/cli/bridge.rs | 9 +- .../bin-substrate/src/cli/relay_parachains.rs | 19 +- relays/client-substrate/src/chain.rs | 2 +- relays/client-substrate/src/test_chain.rs | 48 + .../src/on_demand/parachains.rs | 56 +- .../lib-substrate-relay/src/parachains/mod.rs | 3 +- .../src/parachains/source.rs | 42 +- .../src/parachains/target.rs | 94 +- relays/parachains/Cargo.toml | 1 - relays/parachains/src/lib.rs | 6 +- relays/parachains/src/parachains_loop.rs | 870 ++++++------------ .../parachains/src/parachains_loop_metrics.rs | 43 +- 17 files changed, 418 insertions(+), 801 deletions(-) diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index b6d41ece2868d..74e8895aff906 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -101,7 +101,7 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; /// Identifier of Westmint parachain at the Westend relay chain. -pub const WESTMINT_PARACHAIN_ID: u32 = 2000; +pub const WESTMINT_PARACHAIN_ID: u32 = 1000; decl_bridge_finality_runtime_apis!(westend); diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs index b3471ad1a382f..37eb848fe5f8e 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs @@ -17,7 +17,6 @@ //! Rialto-to-Millau parachains sync entrypoint. use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; -use parachains_relay::ParachainsPipeline; use relay_millau_client::Millau; use relay_rialto_client::Rialto; use relay_rialto_parachain_client::RialtoParachain; @@ -29,11 +28,6 @@ use substrate_relay_helper::parachains::{ #[derive(Clone, Debug)] pub struct RialtoParachainsToMillau; -impl ParachainsPipeline for RialtoParachainsToMillau { - type SourceChain = Rialto; - type TargetChain = Millau; -} - impl SubstrateParachainsPipeline for RialtoParachainsToMillau { type SourceParachain = RialtoParachain; type SourceRelayChain = Rialto; diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs index 098aed417c662..ba0c10beae424 100644 --- a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs @@ -18,7 +18,6 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use parachains_relay::ParachainsPipeline; use relay_substrate_client::{CallOf, HeaderIdOf}; use substrate_relay_helper::parachains::{ SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, @@ -28,11 +27,6 @@ use substrate_relay_helper::parachains::{ #[derive(Clone, Debug)] pub struct BridgeHubRococoToBridgeHubWococo; -impl ParachainsPipeline for BridgeHubRococoToBridgeHubWococo { - type SourceChain = relay_rococo_client::Rococo; - type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; -} - impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWococo { type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo; type SourceRelayChain = relay_rococo_client::Rococo; diff --git a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs index f025f48dcb60a..abd9e6137bb32 100644 --- a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs @@ -17,7 +17,6 @@ //! Westend-to-Millau parachains sync entrypoint. use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; -use parachains_relay::ParachainsPipeline; use relay_millau_client::Millau; use relay_westend_client::{Westend, Westmint}; use substrate_relay_helper::parachains::{ @@ -28,11 +27,6 @@ use substrate_relay_helper::parachains::{ #[derive(Clone, Debug)] pub struct WestendParachainsToMillau; -impl ParachainsPipeline for WestendParachainsToMillau { - type SourceChain = Westend; - type TargetChain = Millau; -} - impl SubstrateParachainsPipeline for WestendParachainsToMillau { type SourceParachain = Westmint; type SourceRelayChain = Westend; diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs index 683e7705dd6ac..028d8c9e17dba 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs @@ -18,7 +18,6 @@ use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use parachains_relay::ParachainsPipeline; use relay_substrate_client::{CallOf, HeaderIdOf}; use substrate_relay_helper::parachains::{ SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, @@ -28,11 +27,6 @@ use substrate_relay_helper::parachains::{ #[derive(Clone, Debug)] pub struct BridgeHubWococoToBridgeHubRococo; -impl ParachainsPipeline for BridgeHubWococoToBridgeHubRococo { - type SourceChain = relay_wococo_client::Wococo; - type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; -} - impl SubstrateParachainsPipeline for BridgeHubWococoToBridgeHubRococo { type SourceParachain = relay_bridge_hub_wococo_client::BridgeHubWococo; type SourceRelayChain = relay_wococo_client::Wococo; diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 330b498f19c03..208f67c527be6 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -16,7 +16,6 @@ use crate::cli::CliChain; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use parachains_relay::ParachainsPipeline; use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ @@ -87,10 +86,10 @@ where + RelayChain; /// Finality proofs synchronization pipeline (source parachain -> target). type ParachainFinality: SubstrateParachainsPipeline< - SourceRelayChain = Self::SourceRelay, - SourceParachain = Self::Source, - TargetChain = Self::Target, - > + ParachainsPipeline; + SourceRelayChain = Self::SourceRelay, + SourceParachain = Self::Source, + TargetChain = Self::Target, + >; /// Finality proofs synchronization pipeline (source relay chain -> target). type RelayFinality: SubstrateFinalitySyncPipeline< SourceChain = Self::SourceRelay, diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 1234b3a3309df..4e59dc14733fc 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -22,20 +22,14 @@ use crate::chains::{ }; use async_std::sync::Mutex; use async_trait::async_trait; -use bp_polkadot_core::parachains::ParaId; -use parachains_relay::parachains_loop::{ - AvailableHeader, ParachainSyncParams, SourceClient, TargetClient, -}; -use relay_substrate_client::{Parachain, ParachainBase}; +use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; +use relay_substrate_client::Parachain; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use std::sync::Arc; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; use substrate_relay_helper::{ - parachains::{ - source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter, - SubstrateParachainsPipeline, - }, + parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, TransactionParams, }; @@ -105,13 +99,6 @@ where parachains_relay::parachains_loop::run( source_client, target_client, - ParachainSyncParams { - parachains: vec![ - ParaId(::SourceParachain::PARACHAIN_ID) - ], - stall_timeout: std::time::Duration::from_secs(60), - strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, - }, metrics_params, futures::future::pending(), ) diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index bc38d1ec9323e..6ab353921efca 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -72,7 +72,7 @@ pub trait RelayChain: Chain { /// Name of the bridge parachains pallet (used in `construct_runtime` macro call) that is /// deployed at the **bridged** chain. /// - /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using + /// We assume that all chains that are bridging with this `RelayChain` are using /// the same name. const PARACHAINS_FINALITY_PALLET_NAME: &'static str; } diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 9bc6c5ae15cc4..10c31804992a8 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -68,3 +68,51 @@ impl ChainWithBalances for TestChain { unreachable!() } } + +/// Primitives-level parachain that may be used in tests. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TestParachainBase; + +impl bp_runtime::Chain for TestParachainBase { + type BlockNumber = u32; + type Hash = sp_core::H256; + type Hasher = sp_runtime::traits::BlakeTwo256; + type Header = sp_runtime::generic::Header; + + type AccountId = u32; + type Balance = u32; + type Index = u32; + type Signature = sp_runtime::testing::TestSignature; + + fn max_extrinsic_size() -> u32 { + unreachable!() + } + + fn max_extrinsic_weight() -> Weight { + unreachable!() + } +} + +impl bp_runtime::Parachain for TestParachainBase { + const PARACHAIN_ID: u32 = 1000; +} + +/// Parachain that may be used in tests. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TestParachain; + +impl bp_runtime::UnderlyingChainProvider for TestParachain { + type Chain = TestParachainBase; +} + +impl Chain for TestParachain { + const NAME: &'static str = "TestParachain"; + const TOKEN_ID: Option<&'static str> = None; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestParachainMethod"; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); + + type SignedBlock = sp_runtime::generic::SignedBlock< + sp_runtime::generic::Block, + >; + type Call = (); +} diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index b1270108c8038..672530de3a58c 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -36,9 +36,7 @@ use bp_runtime::HeaderIdProvider; use futures::{select, FutureExt}; use num_traits::Zero; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use parachains_relay::parachains_loop::{ - AvailableHeader, ParachainSyncParams, SourceClient, TargetClient, -}; +use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; use relay_substrate_client::{ is_ancient_block, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf, ParachainBase, @@ -183,7 +181,7 @@ where let mut proved_parachain_block = selected_parachain_block; if proved_relay_block != selected_relay_block { proved_parachain_block = parachains_source - .on_chain_para_head_id(proved_relay_block, para_id) + .on_chain_para_head_id(proved_relay_block) .await? // this could happen e.g. if parachain has been offboarded? .ok_or_else(|| { @@ -209,11 +207,11 @@ where } // and finally - prove parachain head - let (para_proof, para_hashes) = - parachains_source.prove_parachain_heads(proved_relay_block, &[para_id]).await?; + let (para_proof, para_hash) = + parachains_source.prove_parachain_head(proved_relay_block).await?; calls.push(P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( proved_relay_block, - para_hashes.into_iter().map(|h| (para_id, h)).collect(), + vec![(para_id, para_hash)], para_proof, )); @@ -241,16 +239,14 @@ async fn background_task( let mut relay_state = RelayState::Idle; let mut required_parachain_header_number = Zero::zero(); - let required_para_header_number_ref = Arc::new(Mutex::new(AvailableHeader::Unavailable)); + let required_para_header_ref = Arc::new(Mutex::new(AvailableHeader::Unavailable)); let mut restart_relay = true; let parachains_relay_task = futures::future::Fuse::terminated(); futures::pin_mut!(parachains_relay_task); - let mut parachains_source = ParachainsSource::

::new( - source_relay_client.clone(), - required_para_header_number_ref.clone(), - ); + let mut parachains_source = + ParachainsSource::

::new(source_relay_client.clone(), required_para_header_ref.clone()); let mut parachains_target = ParachainsTarget::

::new(target_client.clone(), target_transaction_params.clone()); @@ -271,13 +267,20 @@ async fn background_task( }, }; - // keep in mind that we are not updating `required_para_header_number_ref` here, because + // keep in mind that we are not updating `required_para_header_ref` here, because // then we'll be submitting all previous headers as well (while required relay headers are // delivered) and we want to avoid that (to reduce cost) - required_parachain_header_number = std::cmp::max( - required_parachain_header_number, - new_required_parachain_header_number, - ); + if new_required_parachain_header_number > required_parachain_header_number { + log::trace!( + target: "bridge", + "[{}] More {} headers required. Going to sync up to the {}", + relay_task_name, + P::SourceParachain::NAME, + new_required_parachain_header_number, + ); + + required_parachain_header_number = new_required_parachain_header_number; + } }, _ = async_std::task::sleep(P::TargetChain::AVERAGE_BLOCK_INTERVAL).fuse() => {}, _ = parachains_relay_task => { @@ -351,7 +354,7 @@ async fn background_task( .await; }, RelayState::RelayingParaHeader(required_para_header) => { - *required_para_header_number_ref.lock().await = + *required_para_header_ref.lock().await = AvailableHeader::Available(required_para_header); }, } @@ -379,11 +382,6 @@ async fn background_task( parachains_relay::parachains_loop::run( parachains_source.clone(), parachains_target.clone(), - ParachainSyncParams { - parachains: vec![P::SourceParachain::PARACHAIN_ID.into()], - stall_timeout: std::time::Duration::from_secs(60), - strategy: parachains_relay::parachains_loop::ParachainSyncStrategy::Any, - }, MetricsParams::disabled(), futures::future::pending(), ) @@ -489,10 +487,7 @@ where source.client().best_finalized_header().await.map_err(map_source_err)?; let best_finalized_relay_block_id = best_finalized_relay_header.id(); let para_header_at_source = source - .on_chain_para_head_id( - best_finalized_relay_block_id, - P::SourceParachain::PARACHAIN_ID.into(), - ) + .on_chain_para_head_id(best_finalized_relay_block_id) .await .map_err(map_source_err)?; @@ -515,10 +510,7 @@ where let para_header_at_relay_header_at_target = if let Some(available_relay_header_at_target) = available_relay_header_at_target { source - .on_chain_para_head_id( - available_relay_header_at_target, - P::SourceParachain::PARACHAIN_ID.into(), - ) + .on_chain_para_head_id(available_relay_header_at_target) .await .map_err(map_source_err)? } else { @@ -669,7 +661,7 @@ impl<'a, P: SubstrateParachainsPipeline> &self, at_relay_block: HeaderIdOf, ) -> Result>, SubstrateError> { - self.1.on_chain_para_head_id(at_relay_block, self.parachain_id()).await + self.1.on_chain_para_head_id(at_relay_block).await } } diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/relays/lib-substrate-relay/src/parachains/mod.rs index 9852e512f7e9c..722f9b61f9f08 100644 --- a/relays/lib-substrate-relay/src/parachains/mod.rs +++ b/relays/lib-substrate-relay/src/parachains/mod.rs @@ -56,7 +56,8 @@ pub struct ParachainsPipelineAdapter { } impl ParachainsPipeline for ParachainsPipelineAdapter

{ - type SourceChain = P::SourceRelayChain; + type SourceParachain = P::SourceParachain; + type SourceRelayChain = P::SourceRelayChain; type TargetChain = P::TargetChain; } diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index 90776902dd6f9..146c5840cd51f 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -24,10 +24,7 @@ use bp_parachains::parachain_head_storage_key_at_source; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::HeaderIdProvider; use codec::Decode; -use parachains_relay::{ - parachains_loop::{AvailableHeader, SourceClient}, - parachains_loop_metrics::ParachainsLoopMetrics, -}; +use parachains_relay::parachains_loop::{AvailableHeader, SourceClient}; use relay_substrate_client::{ is_ancient_block, Chain, Client, Error as SubstrateError, HeaderIdOf, HeaderOf, ParachainBase, RelayChain, @@ -63,8 +60,8 @@ impl ParachainsSource

{ pub async fn on_chain_para_head_id( &self, at_block: HeaderIdOf, - para_id: ParaId, ) -> Result>, SubstrateError> { + let para_id = ParaId(P::SourceParachain::PARACHAIN_ID); let storage_key = parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, para_id); let para_head = self.client.raw_storage_value(storage_key, Some(at_block.1)).await?; @@ -104,18 +101,7 @@ where async fn parachain_head( &self, at_block: HeaderIdOf, - metrics: Option<&ParachainsLoopMetrics>, - para_id: ParaId, - ) -> Result, Self::Error> { - // we don't need to support many parachains now - if para_id.0 != P::SourceParachain::PARACHAIN_ID { - return Err(SubstrateError::Custom(format!( - "Parachain id {} is not matching expected {}", - para_id.0, - P::SourceParachain::PARACHAIN_ID, - ))) - } - + ) -> Result>, Self::Error> { // if requested relay header is ancient, then we don't even want to try to read the // parachain head - we simply return `Unavailable` let best_block_number = self.client.best_finalized_header_number().await?; @@ -125,7 +111,7 @@ where // else - try to read head from the source client let mut para_head_id = AvailableHeader::Missing; - if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block, para_id).await? { + if let Some(on_chain_para_head_id) = self.on_chain_para_head_id(at_block).await? { // Never return head that is larger than requested. This way we'll never sync // headers past `max_header_id`. para_head_id = match *self.max_head_id.lock().await { @@ -141,26 +127,14 @@ where } } - if let (Some(metrics), AvailableHeader::Available(para_head_id)) = (metrics, para_head_id) { - metrics.update_best_parachain_block_at_source(para_id, para_head_id.0); - } - - Ok(para_head_id.map(|para_head_id| para_head_id.1)) + Ok(para_head_id) } - async fn prove_parachain_heads( + async fn prove_parachain_head( &self, at_block: HeaderIdOf, - parachains: &[ParaId], - ) -> Result<(ParaHeadsProof, Vec), Self::Error> { + ) -> Result<(ParaHeadsProof, ParaHash), Self::Error> { let parachain = ParaId(P::SourceParachain::PARACHAIN_ID); - if parachains != [parachain] { - return Err(SubstrateError::Custom(format!( - "Trying to prove unexpected parachains {parachains:?}. Expected {parachain:?}", - ))) - } - - let parachain = parachains[0]; let storage_key = parachain_head_storage_key_at_source(P::SourceRelayChain::PARAS_PALLET_NAME, parachain); let parachain_heads_proof = self @@ -190,6 +164,6 @@ where })?; let parachain_head_hash = parachain_head.hash(); - Ok((ParaHeadsProof(parachain_heads_proof), vec![parachain_head_hash])) + Ok((ParaHeadsProof(parachain_heads_proof), parachain_head_hash)) } } diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/relays/lib-substrate-relay/src/parachains/target.rs index 7f6cdf8f9251f..6df7bc0a742a9 100644 --- a/relays/lib-substrate-relay/src/parachains/target.rs +++ b/relays/lib-substrate-relay/src/parachains/target.rs @@ -24,18 +24,15 @@ use crate::{ }; use async_trait::async_trait; -use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::HeaderIdProvider; use codec::Decode; -use parachains_relay::{ - parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics, -}; +use parachains_relay::parachains_loop::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, ParachainBase, RelayChain, TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, Client, Error as SubstrateError, HeaderIdOf, + ParachainBase, TransactionEra, TransactionTracker, UnsignedTransaction, }; -use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; +use relay_utils::relay_loop::Client as RelayClient; use sp_core::{Bytes, Pair}; /// Substrate client as parachain heads source. @@ -92,93 +89,50 @@ where Ok(best_id) } - async fn best_finalized_source_block( + async fn best_finalized_source_relay_chain_block( &self, at_block: &HeaderIdOf, ) -> Result, Self::Error> { - let encoded_best_finalized_source_block = self - .client - .state_call( + self.client + .typed_state_call::<_, Option>>( P::SourceRelayChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), - Bytes(Vec::new()), + (), Some(at_block.1), ) - .await?; - - Option::, BlockNumberOf>>::decode( - &mut &encoded_best_finalized_source_block.0[..], - ) - .map_err(SubstrateError::ResponseParseFailed)? - .map(Ok) - .unwrap_or(Err(SubstrateError::NoParachainHeadAtTarget( - P::SourceParachain::PARACHAIN_ID, - P::TargetChain::NAME.into(), - ))) + .await? + .map(Ok) + .unwrap_or(Err(SubstrateError::BridgePalletIsNotInitialized)) } async fn parachain_head( &self, at_block: HeaderIdOf, - metrics: Option<&ParachainsLoopMetrics>, - para_id: ParaId, - ) -> Result, Self::Error> { - let best_para_head_hash: Option = self + ) -> Result>, Self::Error> { + let encoded_best_finalized_source_para_block = self .client - .storage_map_value::( - P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, - ¶_id, + .state_call( + P::SourceParachain::BEST_FINALIZED_HEADER_ID_METHOD.into(), + Bytes(Vec::new()), Some(at_block.1), ) - .await? - .map(|para_info| para_info.best_head_hash); - - if let (Some(metrics), Some(best_para_head_hash)) = (metrics, &best_para_head_hash) { - let imported_para_head_number = self - .client - .storage_double_map_value::( - P::SourceRelayChain::PARACHAINS_FINALITY_PALLET_NAME, - ¶_id, - &best_para_head_hash.head_hash, - Some(at_block.1), - ) - .await - .and_then(|maybe_encoded_head| match maybe_encoded_head { - Some(encoded_head) => encoded_head - .decode_parachain_head_data::() - .map(|head| head.number) - .map(Some) - .map_err(Self::Error::ResponseParseFailed), - None => Ok(None), - }) - .map_err(|e| { - log::error!( - target: "bridge-metrics", - "Failed to read or decode {} parachain header at {}: {:?}. Metric will have obsolete value", - P::SourceParachain::NAME, - P::TargetChain::NAME, - e, - ); - e - }) - .unwrap_or(None); - if let Some(imported_para_head_number) = imported_para_head_number { - metrics.update_best_parachain_block_at_target(para_id, imported_para_head_number); - } - } + .await?; - Ok(best_para_head_hash) + Ok(Option::>::decode( + &mut &encoded_best_finalized_source_para_block.0[..], + ) + .map_err(SubstrateError::ResponseParseFailed)?) } - async fn submit_parachain_heads_proof( + async fn submit_parachain_head_proof( &self, at_relay_block: HeaderIdOf, - updated_parachains: Vec<(ParaId, ParaHash)>, + updated_head_hash: ParaHash, proof: ParaHeadsProof, ) -> Result { let transaction_params = self.transaction_params.clone(); let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( at_relay_block, - updated_parachains, + vec![(ParaId(P::SourceParachain::PARACHAIN_ID), updated_head_hash)], proof, ); self.client diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 093fc0b94e3fa..d2938389ca77e 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -14,7 +14,6 @@ relay-utils = { path = "../utils" } # Bridge dependencies -bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/parachains/src/lib.rs b/relays/parachains/src/lib.rs index 94b3ce3ec7669..81ea983a6f76a 100644 --- a/relays/parachains/src/lib.rs +++ b/relays/parachains/src/lib.rs @@ -16,7 +16,7 @@ use std::fmt::Debug; -use relay_substrate_client::Chain; +use relay_substrate_client::{Chain, Parachain}; pub mod parachains_loop; pub mod parachains_loop_metrics; @@ -24,7 +24,9 @@ pub mod parachains_loop_metrics; /// Finality proofs synchronization pipeline. pub trait ParachainsPipeline: 'static + Clone + Debug + Send + Sync { /// Relay chain which is storing parachain heads in its `paras` module. - type SourceChain: Chain; + type SourceRelayChain: Chain; + /// Parachain which headers we are syncing here. + type SourceParachain: Parachain; /// Target chain (either relay or para) which wants to know about new parachain heads. type TargetChain: Chain; } diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 7b62e72ca2930..9b9038fd9761a 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -17,7 +17,6 @@ use crate::{parachains_loop_metrics::ParachainsLoopMetrics, ParachainsPipeline}; use async_trait::async_trait; -use bp_parachains::BestParaHeadHash; use bp_polkadot_core::{ parachains::{ParaHash, ParaHeadsProof, ParaId}, BlockNumber as RelayBlockNumber, @@ -26,44 +25,17 @@ use futures::{ future::{FutureExt, Shared}, poll, select_biased, }; -use relay_substrate_client::{BlockNumberOf, Chain, HeaderIdOf}; +use relay_substrate_client::{Chain, HeaderIdOf, ParachainBase}; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, TrackedTransactionStatus, TransactionTracker, }; -use std::{ - collections::{BTreeMap, BTreeSet}, - future::Future, - pin::Pin, - task::Poll, - time::Duration, -}; - -/// Parachain heads synchronization params. -#[derive(Clone, Debug)] -pub struct ParachainSyncParams { - /// Parachains that we're relaying here. - pub parachains: Vec, - /// Parachain heads update strategy. - pub strategy: ParachainSyncStrategy, - /// Stall timeout. If we have submitted transaction and we see no state updates for this - /// period, we consider our transaction lost. - pub stall_timeout: Duration, -} - -/// Parachain heads update strategy. -#[derive(Clone, Copy, Debug)] -pub enum ParachainSyncStrategy { - /// Update whenever any parachain head is updated. - Any, - /// Wait till all parachain heads are updated. - All, -} +use std::{future::Future, pin::Pin, task::Poll}; /// Parachain header availability at a certain chain. #[derive(Clone, Copy, Debug)] pub enum AvailableHeader { - /// The client refuses to report parachain head at this moment. + /// The client can not report actual parachain head at this moment. /// /// It is a "mild" error, which may appear when e.g. on-demand parachains relay is used. /// This variant must be treated as "we don't want to update parachain head value at the @@ -78,15 +50,20 @@ pub enum AvailableHeader { } impl AvailableHeader { - /// Transform contained value. - pub fn map(self, f: F) -> AvailableHeader - where - F: FnOnce(T) -> U, - { - match self { - AvailableHeader::Unavailable => AvailableHeader::Unavailable, - AvailableHeader::Missing => AvailableHeader::Missing, - AvailableHeader::Available(val) => AvailableHeader::Available(f(val)), + /// Return available header. + pub fn as_available(&self) -> Option<&T> { + match *self { + AvailableHeader::Available(ref header) => Some(header), + _ => None, + } + } +} + +impl From> for AvailableHeader { + fn from(maybe_header: Option) -> AvailableHeader { + match maybe_header { + Some(header) => AvailableHeader::Available(header), + None => AvailableHeader::Missing, } } } @@ -97,27 +74,17 @@ pub trait SourceClient: RelayClient { /// Returns `Ok(true)` if client is in synced state. async fn ensure_synced(&self) -> Result; - /// Get parachain head hash at given block. - /// - /// The implementation may call `ParachainsLoopMetrics::update_best_parachain_block_at_source` - /// on provided `metrics` object to update corresponding metric value. + /// Get parachain head id at given block. async fn parachain_head( &self, - at_block: HeaderIdOf, - metrics: Option<&ParachainsLoopMetrics>, - para_id: ParaId, - ) -> Result, Self::Error>; + at_block: HeaderIdOf, + ) -> Result>, Self::Error>; - /// Get parachain heads proof. - /// - /// The number and order of entries in the resulting parachain head hashes vector must match the - /// number and order of parachains in the `parachains` vector. The incorrect implementation will - /// result in panic. - async fn prove_parachain_heads( + /// Get parachain head proof at given block. + async fn prove_parachain_head( &self, - at_block: HeaderIdOf, - parachains: &[ParaId], - ) -> Result<(ParaHeadsProof, Vec), Self::Error>; + at_block: HeaderIdOf, + ) -> Result<(ParaHeadsProof, ParaHash), Self::Error>; } /// Target client used in parachain heads synchronization loop. @@ -129,28 +96,23 @@ pub trait TargetClient: RelayClient { /// Get best block id. async fn best_block(&self) -> Result, Self::Error>; - /// Get best finalized source block id. - async fn best_finalized_source_block( + /// Get best finalized source relay chain block id. + async fn best_finalized_source_relay_chain_block( &self, at_block: &HeaderIdOf, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; - /// Get parachain head hash at given block. - /// - /// The implementation may call `ParachainsLoopMetrics::update_best_parachain_block_at_target` - /// on provided `metrics` object to update corresponding metric value. + /// Get parachain head id at given block. async fn parachain_head( &self, at_block: HeaderIdOf, - metrics: Option<&ParachainsLoopMetrics>, - para_id: ParaId, - ) -> Result, Self::Error>; + ) -> Result>, Self::Error>; /// Submit parachain heads proof. - async fn submit_parachain_heads_proof( + async fn submit_parachain_head_proof( &self, - at_source_block: HeaderIdOf, - updated_parachains: Vec<(ParaId, ParaHash)>, + at_source_block: HeaderIdOf, + para_head_hash: ParaHash, proof: ParaHeadsProof, ) -> Result; } @@ -158,19 +120,23 @@ pub trait TargetClient: RelayClient { /// Return prefix that will be used by default to expose Prometheus metrics of the parachains /// sync loop. pub fn metrics_prefix() -> String { - format!("{}_to_{}_Parachains", P::SourceChain::NAME, P::TargetChain::NAME) + format!( + "{}_to_{}_Parachains_{}", + P::SourceRelayChain::NAME, + P::TargetChain::NAME, + P::SourceParachain::PARACHAIN_ID + ) } /// Run parachain heads synchronization. pub async fn run( source_client: impl SourceClient

, target_client: impl TargetClient

, - sync_params: ParachainSyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, ) -> Result<(), relay_utils::Error> where - P::SourceChain: Chain, + P::SourceRelayChain: Chain, { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) @@ -179,13 +145,7 @@ where .expose() .await? .run(metrics_prefix::

(), move |source_client, target_client, metrics| { - run_until_connection_lost( - source_client, - target_client, - sync_params.clone(), - metrics, - exit_signal.clone(), - ) + run_until_connection_lost(source_client, target_client, metrics, exit_signal.clone()) }) .await } @@ -194,16 +154,15 @@ where async fn run_until_connection_lost( source_client: impl SourceClient

, target_client: impl TargetClient

, - sync_params: ParachainSyncParams, metrics: Option, exit_signal: impl Future + Send, ) -> Result<(), FailedClient> where - P::SourceChain: Chain, + P::SourceRelayChain: Chain, { let exit_signal = exit_signal.fuse(); let min_block_interval = std::cmp::min( - P::SourceChain::AVERAGE_BLOCK_INTERVAL, + P::SourceRelayChain::AVERAGE_BLOCK_INTERVAL, P::TargetChain::AVERAGE_BLOCK_INTERVAL, ); @@ -232,7 +191,7 @@ where log::warn!( target: "bridge", "{} client is syncing. Won't do anything until it is synced", - P::SourceChain::NAME, + P::SourceRelayChain::NAME, ); continue }, @@ -240,7 +199,7 @@ where log::warn!( target: "bridge", "{} client has failed to return its sync status: {:?}", - P::SourceChain::NAME, + P::SourceRelayChain::NAME, e, ); return Err(FailedClient::Source) @@ -249,33 +208,28 @@ where // if we have active transaction, we'll need to wait until it is mined or dropped let best_target_block = target_client.best_block().await.map_err(|e| { - log::warn!(target: "bridge", "Failed to read best {} block: {:?}", P::SourceChain::NAME, e); + log::warn!(target: "bridge", "Failed to read best {} block: {:?}", P::SourceRelayChain::NAME, e); FailedClient::Target })?; - let heads_at_target = read_heads_at_target( - &target_client, - metrics.as_ref(), - &best_target_block, - &sync_params.parachains, - ) - .await?; + let head_at_target = + read_head_at_target(&target_client, metrics.as_ref(), &best_target_block).await?; // check if our transaction has been mined if let Some(tracker) = submitted_heads_tracker.take() { - match tracker.update(&best_target_block, &heads_at_target).await { - SubmittedHeadsStatus::Waiting(tracker) => { + match tracker.update(&best_target_block, &head_at_target).await { + SubmittedHeadStatus::Waiting(tracker) => { // no news about our transaction and we shall keep waiting submitted_heads_tracker = Some(tracker); continue }, - SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized(_)) => { + SubmittedHeadStatus::Final(TrackedTransactionStatus::Finalized(_)) => { // all heads have been updated, we don't need this tracker anymore }, - SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) => { + SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost) => { log::warn!( target: "bridge", "Parachains synchronization from {} to {} has stalled. Going to restart", - P::SourceChain::NAME, + P::SourceRelayChain::NAME, P::TargetChain::NAME, ); @@ -287,247 +241,201 @@ where // we have no active transaction and may need to update heads, but do we have something for // update? let best_finalized_relay_block = target_client - .best_finalized_source_block(&best_target_block) + .best_finalized_source_relay_chain_block(&best_target_block) .await .map_err(|e| { log::warn!( target: "bridge", "Failed to read best finalized {} block from {}: {:?}", - P::SourceChain::NAME, + P::SourceRelayChain::NAME, P::TargetChain::NAME, e, ); FailedClient::Target })?; - let heads_at_source = read_heads_at_source( - &source_client, - metrics.as_ref(), - &best_finalized_relay_block, - &sync_params.parachains, - ) - .await?; - let updated_ids = select_parachains_to_update::

( - heads_at_source, - heads_at_target, - best_finalized_relay_block, - ); - let is_update_required = is_update_required(&sync_params, &updated_ids); - - log::info!( - target: "bridge", - "Total {} parachains: {}. Up-to-date at {}: {}. Needs update at {}: {}.", - P::SourceChain::NAME, - sync_params.parachains.len(), - P::TargetChain::NAME, - sync_params.parachains.len() - updated_ids.len(), - P::TargetChain::NAME, - updated_ids.len(), - ); + let head_at_source = + read_head_at_source(&source_client, metrics.as_ref(), &best_finalized_relay_block) + .await?; + let is_update_required = is_update_required::

(head_at_source, head_at_target); if is_update_required { - let (heads_proofs, head_hashes) = source_client - .prove_parachain_heads(best_finalized_relay_block, &updated_ids) + let (head_proof, head_hash) = source_client + .prove_parachain_head(best_finalized_relay_block) .await .map_err(|e| { log::warn!( target: "bridge", - "Failed to prove {} parachain heads: {:?}", - P::SourceChain::NAME, + "Failed to prove {} parachain ParaId({}) heads: {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, e, ); FailedClient::Source })?; log::info!( target: "bridge", - "Submitting {} parachain heads update transaction to {}", - P::SourceChain::NAME, + "Submitting {} parachain ParaId({}) head update transaction to {}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, P::TargetChain::NAME, ); - assert_eq!( - head_hashes.len(), - updated_ids.len(), - "Incorrect parachains SourceClient implementation" - ); - let transaction_tracker = target_client - .submit_parachain_heads_proof( - best_finalized_relay_block, - updated_ids.iter().cloned().zip(head_hashes).collect(), - heads_proofs, - ) + .submit_parachain_head_proof(best_finalized_relay_block, head_hash, head_proof) .await .map_err(|e| { log::warn!( target: "bridge", - "Failed to submit {} parachain heads proof to {}: {:?}", - P::SourceChain::NAME, + "Failed to submit {} parachain ParaId({}) heads proof to {}: {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, P::TargetChain::NAME, e, ); FailedClient::Target })?; - submitted_heads_tracker = Some(SubmittedHeadsTracker::

::new( - updated_ids, - best_finalized_relay_block.0, - transaction_tracker, - )); + submitted_heads_tracker = + Some(SubmittedHeadsTracker::

::new(head_at_source, transaction_tracker)); } } } -/// Given heads at source and target clients, returns set of heads that are out of sync. -fn select_parachains_to_update( - heads_at_source: BTreeMap>, - heads_at_target: BTreeMap>, - best_finalized_relay_block: HeaderIdOf, -) -> Vec +/// Returns `true` if we need to submit parachain-head-update transaction. +fn is_update_required( + head_at_source: AvailableHeader>, + head_at_target: Option>, +) -> bool where - P::SourceChain: Chain, + P::SourceRelayChain: Chain, { log::trace!( target: "bridge", - "Selecting {} parachains to update at {} (relay block: {:?}):\n\t\ + "Checking if {} parachain ParaId({}) needs update at {}:\n\t\ At {}: {:?}\n\t\ At {}: {:?}", - P::SourceChain::NAME, + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, P::TargetChain::NAME, - best_finalized_relay_block, - P::SourceChain::NAME, - heads_at_source, + P::SourceRelayChain::NAME, + head_at_source, P::TargetChain::NAME, - heads_at_target, + head_at_target, ); - heads_at_source - .into_iter() - .zip(heads_at_target.into_iter()) - .filter(|((para, head_at_source), (_, head_at_target))| { - let needs_update = match (head_at_source, head_at_target) { - (AvailableHeader::Unavailable, _) => { - // source client has politely asked us not to update current parachain head - // at the target chain - false - }, - (AvailableHeader::Available(head_at_source), Some(head_at_target)) - if head_at_target.at_relay_block_number < best_finalized_relay_block.0 && - head_at_target.head_hash != *head_at_source => - { - // source client knows head that is better than the head known to the target - // client - true - }, - (AvailableHeader::Available(_), Some(_)) => { - // this is normal case when relay has recently updated heads, when parachain is - // not progressing, or when our source client is still syncing - false - }, - (AvailableHeader::Available(_), None) => { - // parachain is not yet known to the target client. This is true when parachain - // or bridge has been just onboarded/started - true - }, - (AvailableHeader::Missing, Some(_)) => { - // parachain/parathread has been offboarded removed from the system. It needs to - // be propageted to the target client - true - }, - (AvailableHeader::Missing, None) => { - // all's good - parachain is unknown to both clients - false - }, - }; - if needs_update { - log::trace!( - target: "bridge", - "{} parachain {:?} needs update at {}: {:?} vs {:?}", - P::SourceChain::NAME, - para, - P::TargetChain::NAME, - head_at_source, - head_at_target, - ); - } - - needs_update - }) - .map(|((para, _), _)| para) - .collect() -} + let needs_update = match (head_at_source, head_at_target) { + (AvailableHeader::Unavailable, _) => { + // source client has politely asked us not to update current parachain head + // at the target chain + false + }, + (AvailableHeader::Available(head_at_source), Some(head_at_target)) + if head_at_source.number() > head_at_target.number() => + { + // source client knows head that is better than the head known to the target + // client + true + }, + (AvailableHeader::Available(_), Some(_)) => { + // this is normal case when relay has recently updated heads, when parachain is + // not progressing, or when our source client is still syncing + false + }, + (AvailableHeader::Available(_), None) => { + // parachain is not yet known to the target client. This is true when parachain + // or bridge has been just onboarded/started + true + }, + (AvailableHeader::Missing, Some(_)) => { + // parachain/parathread has been offboarded removed from the system. It needs to + // be propageted to the target client + true + }, + (AvailableHeader::Missing, None) => { + // all's good - parachain is unknown to both clients + false + }, + }; -/// Returns true if we need to submit update transactions to the target node. -fn is_update_required(sync_params: &ParachainSyncParams, updated_ids: &[ParaId]) -> bool { - match sync_params.strategy { - ParachainSyncStrategy::All => updated_ids.len() == sync_params.parachains.len(), - ParachainSyncStrategy::Any => !updated_ids.is_empty(), + if needs_update { + log::trace!( + target: "bridge", + "{} parachain ParaId({}) needs update at {}: {:?} vs {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, + P::TargetChain::NAME, + head_at_source, + head_at_target, + ); } + + needs_update } -/// Reads given parachains heads from the source client. -/// -/// Guarantees that the returning map will have an entry for every parachain from `parachains`. -async fn read_heads_at_source( +/// Reads parachain head from the source client. +async fn read_head_at_source( source_client: &impl SourceClient

, metrics: Option<&ParachainsLoopMetrics>, - at_relay_block: &HeaderIdOf, - parachains: &[ParaId], -) -> Result>, FailedClient> { - let mut para_head_hashes = BTreeMap::new(); - for para in parachains { - let para_head = source_client.parachain_head(*at_relay_block, metrics, *para).await; - match para_head { - Ok(para_head) => { - para_head_hashes.insert(*para, para_head); - }, - Err(e) => { - log::warn!( - target: "bridge", - "Failed to read head of {} parachain {:?}: {:?}", - P::SourceChain::NAME, - para, - e, + at_relay_block: &HeaderIdOf, +) -> Result>, FailedClient> { + let para_head = source_client.parachain_head(*at_relay_block).await; + match para_head { + Ok(AvailableHeader::Available(para_head)) => { + if let Some(metrics) = metrics { + metrics.update_best_parachain_block_at_source( + ParaId(P::SourceParachain::PARACHAIN_ID), + para_head.number(), ); - return Err(FailedClient::Source) - }, - } + } + Ok(AvailableHeader::Available(para_head)) + }, + Ok(r) => Ok(r), + Err(e) => { + log::warn!( + target: "bridge", + "Failed to read head of {} parachain ParaId({:?}): {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, + e, + ); + Err(FailedClient::Source) + }, } - Ok(para_head_hashes) } -/// Reads given parachains heads from the source client. -/// -/// Guarantees that the returning map will have an entry for every parachain from `parachains`. -async fn read_heads_at_target( +/// Reads parachain head from the target client. +async fn read_head_at_target( target_client: &impl TargetClient

, metrics: Option<&ParachainsLoopMetrics>, at_block: &HeaderIdOf, - parachains: &[ParaId], -) -> Result>, FailedClient> { - let mut para_best_head_hashes = BTreeMap::new(); - for para in parachains { - let para_best_head = target_client.parachain_head(*at_block, metrics, *para).await; - match para_best_head { - Ok(para_best_head) => { - para_best_head_hashes.insert(*para, para_best_head); - }, - Err(e) => { - log::warn!( - target: "bridge", - "Failed to read head of {} parachain {:?} at {}: {:?}", - P::SourceChain::NAME, - para, - P::TargetChain::NAME, - e, +) -> Result>, FailedClient> { + let para_head_id = target_client.parachain_head(*at_block).await; + match para_head_id { + Ok(Some(para_head_id)) => { + if let Some(metrics) = metrics { + metrics.update_best_parachain_block_at_target( + ParaId(P::SourceParachain::PARACHAIN_ID), + para_head_id.number(), ); - return Err(FailedClient::Target) - }, - } + } + Ok(Some(para_head_id)) + }, + Ok(None) => Ok(None), + Err(e) => { + log::warn!( + target: "bridge", + "Failed to read head of {} parachain ParaId({}) at {}: {:?}", + P::SourceRelayChain::NAME, + P::SourceParachain::PARACHAIN_ID, + P::TargetChain::NAME, + e, + ); + Err(FailedClient::Target) + }, } - Ok(para_best_head_hashes) } /// Submitted heads status. -enum SubmittedHeadsStatus { +enum SubmittedHeadStatus { /// Heads are not yet updated. Waiting(SubmittedHeadsTracker

), /// Heads transaction has either been finalized or lost (i.e. received its "final" status). @@ -551,66 +459,50 @@ type SharedTransactionTracker

= Shared< /// Submitted parachain heads transaction. struct SubmittedHeadsTracker { - /// Ids of parachains which heads were updated in the tracked transaction. - awaiting_update: BTreeSet, - /// Number of relay chain block that has been used to craft parachain heads proof. - relay_block_number: BlockNumberOf, + /// Parachain header id that we have submitted. + submitted_head: AvailableHeader>, /// Future that waits for submitted transaction finality or loss. /// /// It needs to be shared because of `poll` macro and our consuming `update` method. transaction_tracker: SharedTransactionTracker

, } -impl SubmittedHeadsTracker

-where - P::SourceChain: Chain, -{ +impl SubmittedHeadsTracker

{ /// Creates new parachain heads transaction tracker. pub fn new( - awaiting_update: impl IntoIterator, - relay_block_number: BlockNumberOf, + submitted_head: AvailableHeader>, transaction_tracker: impl TransactionTracker> + 'static, ) -> Self { SubmittedHeadsTracker { - awaiting_update: awaiting_update.into_iter().collect(), - relay_block_number, + submitted_head, transaction_tracker: transaction_tracker.wait().fuse().boxed().shared(), } } /// Returns `None` if all submitted parachain heads have been updated. pub async fn update( - mut self, + self, at_target_block: &HeaderIdOf, - heads_at_target: &BTreeMap>, - ) -> SubmittedHeadsStatus

{ - // remove all pending heads that were synced - for (para, best_para_head) in heads_at_target { - if best_para_head - .as_ref() - .map(|best_para_head| { - best_para_head.at_relay_block_number >= self.relay_block_number - }) - .unwrap_or(false) - { - self.awaiting_update.remove(para); - - log::trace!( - target: "bridge", - "Head of parachain {:?} has been updated at {}: {:?}. Outdated parachains remaining: {}", - para, - P::TargetChain::NAME, - best_para_head, - self.awaiting_update.len(), - ); - } - } + head_at_target: &Option>, + ) -> SubmittedHeadStatus

{ + // check if our head has been updated + let is_head_updated = match (self.submitted_head, head_at_target) { + (AvailableHeader::Available(submitted_head), Some(head_at_target)) + if head_at_target.number() >= submitted_head.number() => + true, + (AvailableHeader::Missing, None) => true, + _ => false, + }; + if is_head_updated { + log::trace!( + target: "bridge", + "Head of parachain ParaId({}) has been updated at {}: {:?}", + P::SourceParachain::PARACHAIN_ID, + P::TargetChain::NAME, + head_at_target, + ); - // if we have synced all required heads, we are done - if self.awaiting_update.is_empty() { - return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized( - *at_target_block, - )) + return SubmittedHeadStatus::Final(TrackedTransactionStatus::Finalized(*at_target_block)) } // if underlying transaction tracker has reported that the transaction is lost, we may @@ -618,16 +510,16 @@ where let transaction_tracker = self.transaction_tracker.clone(); match poll!(transaction_tracker) { Poll::Ready(TrackedTransactionStatus::Lost) => - return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost), + return SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost), Poll::Ready(TrackedTransactionStatus::Finalized(_)) => { // so we are here and our transaction is mined+finalized, but some of heads were not // updated => we're considering our loop as stalled - return SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost) + return SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost) }, _ => (), } - SubmittedHeadsStatus::Waiting(self) + SubmittedHeadStatus::Waiting(self) } } @@ -637,18 +529,16 @@ mod tests { use async_std::sync::{Arc, Mutex}; use codec::Encode; use futures::{SinkExt, StreamExt}; - use relay_substrate_client::test_chain::TestChain; + use relay_substrate_client::test_chain::{TestChain, TestParachain}; use relay_utils::{HeaderId, MaybeConnectionError}; use sp_core::H256; - const PARA_ID: u32 = 0; - const PARA_0_HASH: ParaHash = H256([1u8; 32]); - const PARA_1_HASH: ParaHash = H256([2u8; 32]); + const PARA_10_HASH: ParaHash = H256([10u8; 32]); + const PARA_20_HASH: ParaHash = H256([20u8; 32]); #[derive(Clone, Debug)] enum TestError { Error, - MissingParachainHeadProof, } impl MaybeConnectionError for TestError { @@ -661,7 +551,8 @@ mod tests { struct TestParachainsPipeline; impl ParachainsPipeline for TestParachainsPipeline { - type SourceChain = TestChain; + type SourceRelayChain = TestChain; + type SourceParachain = TestParachain; type TargetChain = TestChain; } @@ -688,12 +579,12 @@ mod tests { #[derive(Clone, Debug)] struct TestClientData { source_sync_status: Result, - source_heads: BTreeMap, TestError>>, - source_proofs: BTreeMap, TestError>>, + source_head: Result>, TestError>, + source_proof: Result<(), TestError>, target_best_block: Result, TestError>, target_best_finalized_source_block: Result, TestError>, - target_heads: BTreeMap>, + target_head: Result>, TestError>, target_submit_result: Result<(), TestError>, exit_signal_sender: Option>>, @@ -703,14 +594,12 @@ mod tests { pub fn minimal() -> Self { TestClientData { source_sync_status: Ok(true), - source_heads: vec![(PARA_ID, Ok(AvailableHeader::Available(PARA_0_HASH)))] - .into_iter() - .collect(), - source_proofs: vec![(PARA_ID, Ok(PARA_0_HASH.encode()))].into_iter().collect(), + source_head: Ok(AvailableHeader::Available(HeaderId(0, PARA_20_HASH))), + source_proof: Ok(()), target_best_block: Ok(HeaderId(0, Default::default())), target_best_finalized_source_block: Ok(HeaderId(0, Default::default())), - target_heads: BTreeMap::new(), + target_head: Ok(None), target_submit_result: Ok(()), exit_signal_sender: None, @@ -750,34 +639,17 @@ mod tests { async fn parachain_head( &self, _at_block: HeaderIdOf, - _metrics: Option<&ParachainsLoopMetrics>, - para_id: ParaId, - ) -> Result, TestError> { - match self.data.lock().await.source_heads.get(¶_id.0).cloned() { - Some(result) => result, - None => Ok(AvailableHeader::Missing), - } + ) -> Result>, TestError> { + self.data.lock().await.source_head.clone() } - async fn prove_parachain_heads( + async fn prove_parachain_head( &self, _at_block: HeaderIdOf, - parachains: &[ParaId], - ) -> Result<(ParaHeadsProof, Vec), TestError> { - let mut proofs = Vec::new(); - for para_id in parachains { - proofs.push( - self.data - .lock() - .await - .source_proofs - .get(¶_id.0) - .cloned() - .transpose()? - .ok_or(TestError::MissingParachainHeadProof)?, - ); - } - Ok((ParaHeadsProof(proofs), vec![Default::default(); parachains.len()])) + ) -> Result<(ParaHeadsProof, ParaHash), TestError> { + let head = *self.data.lock().await.source_head.clone()?.as_available().unwrap(); + let proof = (ParaHeadsProof(vec![head.hash().encode()]), head.hash()); + self.data.lock().await.source_proof.clone().map(|_| proof) } } @@ -789,7 +661,7 @@ mod tests { self.data.lock().await.target_best_block.clone() } - async fn best_finalized_source_block( + async fn best_finalized_source_relay_chain_block( &self, _at_block: &HeaderIdOf, ) -> Result, TestError> { @@ -799,16 +671,14 @@ mod tests { async fn parachain_head( &self, _at_block: HeaderIdOf, - _metrics: Option<&ParachainsLoopMetrics>, - para_id: ParaId, - ) -> Result, TestError> { - self.data.lock().await.target_heads.get(¶_id.0).cloned().transpose() + ) -> Result>, TestError> { + self.data.lock().await.target_head.clone() } - async fn submit_parachain_heads_proof( + async fn submit_parachain_head_proof( &self, _at_source_block: HeaderIdOf, - _updated_parachains: Vec<(ParaId, ParaHash)>, + _updated_parachain_head: ParaHash, _proof: ParaHeadsProof, ) -> Result { let mut data = self.data.lock().await; @@ -823,14 +693,6 @@ mod tests { } } - fn default_sync_params() -> ParachainSyncParams { - ParachainSyncParams { - parachains: vec![ParaId(PARA_ID)], - strategy: ParachainSyncStrategy::Any, - stall_timeout: Duration::from_secs(60), - } - } - #[test] fn when_source_client_fails_to_return_sync_state() { let mut test_source_client = TestClientData::minimal(); @@ -840,7 +702,6 @@ mod tests { async_std::task::block_on(run_until_connection_lost( TestClient::from(test_source_client), TestClient::from(TestClientData::minimal()), - default_sync_params(), None, futures::future::pending(), )), @@ -857,7 +718,6 @@ mod tests { async_std::task::block_on(run_until_connection_lost( TestClient::from(TestClientData::minimal()), TestClient::from(test_target_client), - default_sync_params(), None, futures::future::pending(), )), @@ -868,13 +728,12 @@ mod tests { #[test] fn when_target_client_fails_to_read_heads() { let mut test_target_client = TestClientData::minimal(); - test_target_client.target_heads.insert(PARA_ID, Err(TestError::Error)); + test_target_client.target_head = Err(TestError::Error); assert_eq!( async_std::task::block_on(run_until_connection_lost( TestClient::from(TestClientData::minimal()), TestClient::from(test_target_client), - default_sync_params(), None, futures::future::pending(), )), @@ -891,7 +750,6 @@ mod tests { async_std::task::block_on(run_until_connection_lost( TestClient::from(TestClientData::minimal()), TestClient::from(test_target_client), - default_sync_params(), None, futures::future::pending(), )), @@ -902,13 +760,12 @@ mod tests { #[test] fn when_source_client_fails_to_read_heads() { let mut test_source_client = TestClientData::minimal(); - test_source_client.source_heads.insert(PARA_ID, Err(TestError::Error)); + test_source_client.source_head = Err(TestError::Error); assert_eq!( async_std::task::block_on(run_until_connection_lost( TestClient::from(test_source_client), TestClient::from(TestClientData::minimal()), - default_sync_params(), None, futures::future::pending(), )), @@ -919,13 +776,12 @@ mod tests { #[test] fn when_source_client_fails_to_prove_heads() { let mut test_source_client = TestClientData::minimal(); - test_source_client.source_proofs.insert(PARA_ID, Err(TestError::Error)); + test_source_client.source_proof = Err(TestError::Error); assert_eq!( async_std::task::block_on(run_until_connection_lost( TestClient::from(test_source_client), TestClient::from(TestClientData::minimal()), - default_sync_params(), None, futures::future::pending(), )), @@ -942,7 +798,6 @@ mod tests { async_std::task::block_on(run_until_connection_lost( TestClient::from(TestClientData::minimal()), TestClient::from(test_target_client), - default_sync_params(), None, futures::future::pending(), )), @@ -957,7 +812,6 @@ mod tests { async_std::task::block_on(run_until_connection_lost( TestClient::from(TestClientData::minimal()), TestClient::from(TestClientData::with_exit_signal_sender(exit_signal_sender)), - default_sync_params(), None, exit_signal.into_future().map(|(_, _)| ()), )), @@ -965,111 +819,62 @@ mod tests { ); } - const PARA_1_ID: u32 = PARA_ID + 1; - const SOURCE_BLOCK_NUMBER: u32 = 100; - fn test_tx_tracker() -> SubmittedHeadsTracker { SubmittedHeadsTracker::new( - vec![ParaId(PARA_ID), ParaId(PARA_1_ID)], - SOURCE_BLOCK_NUMBER, + AvailableHeader::Available(HeaderId(20, PARA_20_HASH)), TestTransactionTracker(None), ) } - fn all_expected_tracker_heads() -> BTreeMap> { - vec![ - ( - ParaId(PARA_ID), - Some(BestParaHeadHash { - at_relay_block_number: SOURCE_BLOCK_NUMBER, - head_hash: PARA_0_HASH, - }), - ), - ( - ParaId(PARA_1_ID), - Some(BestParaHeadHash { - at_relay_block_number: SOURCE_BLOCK_NUMBER, - head_hash: PARA_0_HASH, - }), - ), - ] - .into_iter() - .collect() - } - - impl From> for Option> { - fn from(status: SubmittedHeadsStatus) -> Option> { + impl From> for Option<()> { + fn from(status: SubmittedHeadStatus) -> Option<()> { match status { - SubmittedHeadsStatus::Waiting(tracker) => Some(tracker.awaiting_update), + SubmittedHeadStatus::Waiting(_) => Some(()), _ => None, } } } #[async_std::test] - async fn tx_tracker_update_when_nothing_is_updated() { + async fn tx_tracker_update_when_head_at_target_has_none_value() { assert_eq!( - Some(test_tx_tracker().awaiting_update), + Some(()), test_tx_tracker() - .update(&HeaderId(0, Default::default()), &vec![].into_iter().collect()) + .update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH))) .await .into(), ); } #[async_std::test] - async fn tx_tracker_update_when_one_of_heads_is_updated_to_previous_value() { + async fn tx_tracker_update_when_head_at_target_has_old_value() { assert_eq!( - Some(test_tx_tracker().awaiting_update), + Some(()), test_tx_tracker() - .update( - &HeaderId(0, Default::default()), - &vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { - at_relay_block_number: SOURCE_BLOCK_NUMBER - 1, - head_hash: PARA_0_HASH, - }) - )] - .into_iter() - .collect() - ) + .update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH))) .await .into(), ); } #[async_std::test] - async fn tx_tracker_update_when_one_of_heads_is_updated() { - assert_eq!( - Some(vec![ParaId(PARA_1_ID)].into_iter().collect::>()), + async fn tx_tracker_update_when_head_at_target_has_same_value() { + assert!(matches!( test_tx_tracker() - .update( - &HeaderId(0, Default::default()), - &vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { - at_relay_block_number: SOURCE_BLOCK_NUMBER, - head_hash: PARA_0_HASH, - }) - )] - .into_iter() - .collect() - ) - .await - .into(), - ); + .update(&HeaderId(0, Default::default()), &Some(HeaderId(20, PARA_20_HASH))) + .await, + SubmittedHeadStatus::Final(TrackedTransactionStatus::Finalized(_)), + )); } #[async_std::test] - async fn tx_tracker_update_when_all_heads_are_updated() { - assert_eq!( - Option::>::None, + async fn tx_tracker_update_when_head_at_target_has_better_value() { + assert!(matches!( test_tx_tracker() - .update(&HeaderId(0, Default::default()), &all_expected_tracker_heads()) - .await - .into(), - ); + .update(&HeaderId(0, Default::default()), &Some(HeaderId(30, PARA_20_HASH))) + .await, + SubmittedHeadStatus::Final(TrackedTransactionStatus::Finalized(_)), + )); } #[async_std::test] @@ -1079,9 +884,9 @@ mod tests { futures::future::ready(TrackedTransactionStatus::Lost).boxed().shared(); assert!(matches!( tx_tracker - .update(&HeaderId(0, Default::default()), &vec![].into_iter().collect()) + .update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH))) .await, - SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost), + SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost), )); } @@ -1094,162 +899,55 @@ mod tests { .shared(); assert!(matches!( tx_tracker - .update(&HeaderId(0, Default::default()), &vec![].into_iter().collect()) + .update(&HeaderId(0, Default::default()), &Some(HeaderId(10, PARA_10_HASH))) .await, - SubmittedHeadsStatus::Final(TrackedTransactionStatus::Lost), + SubmittedHeadStatus::Final(TrackedTransactionStatus::Lost), )); } - #[async_std::test] - async fn tx_tracker_update_when_tx_is_finalized_and_heads_are_updated() { - let mut tx_tracker = test_tx_tracker(); - tx_tracker.transaction_tracker = - futures::future::ready(TrackedTransactionStatus::Finalized(Default::default())) - .boxed() - .shared(); - assert!(matches!( - tx_tracker - .update(&HeaderId(0, Default::default()), &all_expected_tracker_heads()) - .await, - SubmittedHeadsStatus::Final(TrackedTransactionStatus::Finalized(_)), + #[test] + fn parachain_is_not_updated_if_it_is_unavailable() { + assert!(!is_update_required::(AvailableHeader::Unavailable, None)); + assert!(!is_update_required::( + AvailableHeader::Unavailable, + Some(HeaderId(10, PARA_10_HASH)) )); } #[test] fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Missing)].into_iter().collect(), - vec![(ParaId(PARA_ID), None)].into_iter().collect(), - HeaderId(10, Default::default()), - ), - Vec::::new(), - ); - } - - #[test] - fn parachain_is_not_updated_if_it_has_been_updated_at_better_relay_block() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_0_HASH))] - .into_iter() - .collect(), - vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { at_relay_block_number: 20, head_hash: PARA_1_HASH }) - )] - .into_iter() - .collect(), - HeaderId(10, Default::default()), - ), - Vec::::new(), - ); + assert!(!is_update_required::(AvailableHeader::Missing, None),); } #[test] - fn parachain_is_not_updated_if_hash_is_the_same_at_next_relay_block() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_0_HASH))] - .into_iter() - .collect(), - vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) - )] - .into_iter() - .collect(), - HeaderId(10, Default::default()), - ), - Vec::::new(), - ); + fn parachain_is_not_updated_if_target_has_better_head() { + assert!(!is_update_required::( + AvailableHeader::Available(HeaderId(10, Default::default())), + Some(HeaderId(20, Default::default())), + ),); } #[test] fn parachain_is_updated_after_offboarding() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Missing)].into_iter().collect(), - vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { - at_relay_block_number: 0, - head_hash: Default::default(), - }) - )] - .into_iter() - .collect(), - HeaderId(10, Default::default()), - ), - vec![ParaId(PARA_ID)], - ); + assert!(is_update_required::( + AvailableHeader::Missing, + Some(HeaderId(20, Default::default())), + ),); } #[test] fn parachain_is_updated_after_onboarding() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_0_HASH))] - .into_iter() - .collect(), - vec![(ParaId(PARA_ID), None)].into_iter().collect(), - HeaderId(10, Default::default()), - ), - vec![ParaId(PARA_ID)], - ); + assert!(is_update_required::( + AvailableHeader::Available(HeaderId(30, Default::default())), + None, + ),); } #[test] fn parachain_is_updated_if_newer_head_is_known() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Available(PARA_1_HASH))] - .into_iter() - .collect(), - vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) - )] - .into_iter() - .collect(), - HeaderId(10, Default::default()), - ), - vec![ParaId(PARA_ID)], - ); - } - - #[test] - fn parachain_is_not_updated_if_source_head_is_unavailable() { - assert_eq!( - select_parachains_to_update::( - vec![(ParaId(PARA_ID), AvailableHeader::Unavailable)].into_iter().collect(), - vec![( - ParaId(PARA_ID), - Some(BestParaHeadHash { at_relay_block_number: 0, head_hash: PARA_0_HASH }) - )] - .into_iter() - .collect(), - HeaderId(10, Default::default()), - ), - vec![], - ); - } - - #[test] - fn is_update_required_works() { - let mut sync_params = ParachainSyncParams { - parachains: vec![ParaId(PARA_ID), ParaId(PARA_1_ID)], - strategy: ParachainSyncStrategy::Any, - stall_timeout: Duration::from_secs(60), - }; - - assert!(!is_update_required(&sync_params, &[])); - assert!(is_update_required(&sync_params, &[ParaId(PARA_ID)])); - assert!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)])); - - sync_params.strategy = ParachainSyncStrategy::All; - assert!(!is_update_required(&sync_params, &[])); - assert!(!is_update_required(&sync_params, &[ParaId(PARA_ID)])); - assert!(is_update_required(&sync_params, &[ParaId(PARA_ID), ParaId(PARA_1_ID)])); + assert!(is_update_required::( + AvailableHeader::Available(HeaderId(40, Default::default())), + Some(HeaderId(30, Default::default())), + ),); } } diff --git a/relays/parachains/src/parachains_loop_metrics.rs b/relays/parachains/src/parachains_loop_metrics.rs index 5df996b4ddd1f..8138a43b3b3dc 100644 --- a/relays/parachains/src/parachains_loop_metrics.rs +++ b/relays/parachains/src/parachains_loop_metrics.rs @@ -16,7 +16,7 @@ use bp_polkadot_core::parachains::ParaId; use relay_utils::{ - metrics::{metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64}, + metrics::{metric_name, register, Gauge, Metric, PrometheusError, Registry, U64}, UniqueSaturatedInto, }; @@ -24,28 +24,22 @@ use relay_utils::{ #[derive(Clone)] pub struct ParachainsLoopMetrics { /// Best parachains header numbers at the source. - best_source_block_numbers: GaugeVec, + best_source_block_numbers: Gauge, /// Best parachains header numbers at the target. - best_target_block_numbers: GaugeVec, + best_target_block_numbers: Gauge, } impl ParachainsLoopMetrics { /// Create and register parachains loop metrics. pub fn new(prefix: Option<&str>) -> Result { Ok(ParachainsLoopMetrics { - best_source_block_numbers: GaugeVec::new( - Opts::new( - metric_name(prefix, "best_parachain_block_number_at_source"), - "Best parachain block numbers at the source relay chain".to_string(), - ), - &["parachain"], + best_source_block_numbers: Gauge::new( + metric_name(prefix, "best_parachain_block_number_at_source"), + "Best parachain block numbers at the source relay chain".to_string(), )?, - best_target_block_numbers: GaugeVec::new( - Opts::new( - metric_name(prefix, "best_parachain_block_number_at_target"), - "Best parachain block numbers at the target chain".to_string(), - ), - &["parachain"], + best_target_block_numbers: Gauge::new( + metric_name(prefix, "best_parachain_block_number_at_target"), + "Best parachain block numbers at the target chain".to_string(), )?, }) } @@ -57,14 +51,13 @@ impl ParachainsLoopMetrics { block_number: Number, ) { let block_number = block_number.unique_saturated_into(); - let label = parachain_label(¶chain); log::trace!( target: "bridge-metrics", - "Updated value of metric 'best_parachain_block_number_at_source[{}]': {:?}", - label, + "Updated value of metric 'best_parachain_block_number_at_source[{:?}]': {:?}", + parachain, block_number, ); - self.best_source_block_numbers.with_label_values(&[&label]).set(block_number); + self.best_source_block_numbers.set(block_number); } /// Update best block number at target. @@ -74,14 +67,13 @@ impl ParachainsLoopMetrics { block_number: Number, ) { let block_number = block_number.unique_saturated_into(); - let label = parachain_label(¶chain); log::trace!( target: "bridge-metrics", - "Updated value of metric 'best_parachain_block_number_at_target[{}]': {:?}", - label, + "Updated value of metric 'best_parachain_block_number_at_target[{:?}]': {:?}", + parachain, block_number, ); - self.best_target_block_numbers.with_label_values(&[&label]).set(block_number); + self.best_target_block_numbers.set(block_number); } } @@ -92,8 +84,3 @@ impl Metric for ParachainsLoopMetrics { Ok(()) } } - -/// Return metric label for the parachain. -fn parachain_label(parachain: &ParaId) -> String { - format!("para_{}", parachain.0) -} From a86726a21b4b5285a70701733ec21cb67207355a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Mar 2023 14:49:33 +0300 Subject: [PATCH 0966/1210] fix master compilation (#1920) --- relays/client-substrate/src/test_chain.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 10c31804992a8..d33cb1de68123 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -106,6 +106,7 @@ impl bp_runtime::UnderlyingChainProvider for TestParachain { } impl Chain for TestParachain { + const ID: ChainId = *b"test"; const NAME: &'static str = "TestParachain"; const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestParachainMethod"; From 9fa695d883b466b4a9c302b05b7cb483573950b1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Mar 2023 15:42:04 +0300 Subject: [PATCH 0967/1210] Fix benchmarks (#1919) * fixed benchmarks broken by rejecting storage proofs with excessive trie nodes and justifications with extra prevotes * update weights * fmt * accidental paste * revert changes to millau runtime (separate PR) * revert comment change --- .../src/messages_benchmarking.rs | 7 +- bin/runtime-common/src/messages_generation.rs | 52 ++++------ .../src/parachains_benchmarking.rs | 13 ++- modules/grandpa/src/benchmarking.rs | 13 ++- modules/grandpa/src/weights.rs | 34 +++---- modules/messages/src/benchmarking.rs | 4 +- modules/messages/src/weights.rs | 90 +++++++++--------- modules/parachains/src/benchmarking.rs | 4 +- modules/parachains/src/weights.rs | 94 +++++++++---------- modules/relayers/src/weights.rs | 12 +-- primitives/runtime/src/storage_proof.rs | 9 +- 11 files changed, 159 insertions(+), 173 deletions(-) diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 1588c77633e23..028172e7ab42f 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -25,7 +25,7 @@ use crate::{ AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, ThisChain, }, messages_generation::{ - encode_all_messages, encode_lane_data, grow_trie, prepare_messages_storage_proof, + encode_all_messages, encode_lane_data, grow_trie_leaf_value, prepare_messages_storage_proof, }, }; @@ -204,11 +204,12 @@ where { let mut trie = TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); - trie.insert(&storage_key, ¶ms.inbound_lane_data.encode()) + let inbound_lane_data = + grow_trie_leaf_value(params.inbound_lane_data.encode(), params.size); + trie.insert(&storage_key, &inbound_lane_data) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); } - root = grow_trie(root, &mut mdb, params.size); // generate storage proof to be delivered to This chain let storage_proof = record_all_trie_keys::>>, _>(&mdb, &root) diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs index aec97c2280047..29a869a5c871a 100644 --- a/bin/runtime-common/src/messages_generation.rs +++ b/bin/runtime-common/src/messages_generation.rs @@ -25,7 +25,6 @@ use bp_messages::{ }; use bp_runtime::{record_all_trie_keys, RawStorageProof, StorageProofSize}; use codec::Encode; -use sp_core::Hasher; use sp_std::{ops::RangeInclusive, prelude::*}; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; @@ -65,10 +64,15 @@ where TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); // insert messages - for nonce in message_nonces { + for (i, nonce) in message_nonces.into_iter().enumerate() { let message_key = MessageKey { lane_id: lane, nonce }; let message_payload = match encode_message(nonce, &message_payload) { - Some(message_payload) => message_payload, + Some(message_payload) => + if i == 0 { + grow_trie_leaf_value(message_payload, size) + } else { + message_payload + }, None => continue, }; let storage_key = storage_keys::message_key( @@ -94,46 +98,22 @@ where storage_keys.push(storage_key); } } - root = grow_trie(root, &mut mdb, size); // generate storage proof to be delivered to This chain let storage_proof = record_all_trie_keys::>>, _>(&mdb, &root) .map_err(|_| "record_all_trie_keys has failed") .expect("record_all_trie_keys should not fail in benchmarks"); - (root, storage_proof) } -/// Populate trie with dummy keys+values until trie has at least given size. -pub fn grow_trie( - mut root: H::Out, - mdb: &mut MemoryDB, - trie_size: StorageProofSize, -) -> H::Out { - let (iterations, leaf_size, minimal_trie_size) = match trie_size { - StorageProofSize::Minimal(_) => return root, - StorageProofSize::HasLargeLeaf(size) => (1, size, size), - StorageProofSize::HasExtraNodes(size) => (8, 1, size), - }; - - let mut key_index = 0; - loop { - // generate storage proof to be delivered to This chain - let storage_proof = record_all_trie_keys::, _>(mdb, &root) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - let size: usize = storage_proof.iter().map(|n| n.len()).sum(); - if size > minimal_trie_size as _ { - return root - } - - let mut trie = TrieDBMutBuilderV1::::from_existing(mdb, &mut root).build(); - for _ in 0..iterations { - trie.insert(&key_index.encode(), &vec![42u8; leaf_size as _]) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - key_index += 1; - } - trie.commit(); +/// Add extra data to the trie leaf value so that it'll be of given size. +pub fn grow_trie_leaf_value(mut value: Vec, size: StorageProofSize) -> Vec { + match size { + StorageProofSize::Minimal(_) => (), + StorageProofSize::HasLargeLeaf(size) if size as usize > value.len() => { + value.extend(sp_std::iter::repeat(42u8).take(size as usize - value.len())); + }, + StorageProofSize::HasLargeLeaf(_) => (), } + value } diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index e549e4f79b9f3..aad53673c3ad3 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -19,7 +19,8 @@ #![cfg(feature = "runtime-benchmarks")] use crate::{ - messages_benchmarking::insert_header_to_grandpa_pallet, messages_generation::grow_trie, + messages_benchmarking::insert_header_to_grandpa_pallet, + messages_generation::grow_trie_leaf_value, }; use bp_parachains::parachain_head_storage_key_at_source; @@ -59,17 +60,21 @@ where TrieDBMutBuilderV1::::new(&mut mdb, &mut state_root).build(); // insert parachain heads - for parachain in parachains { + for (i, parachain) in parachains.into_iter().enumerate() { let storage_key = parachain_head_storage_key_at_source(R::ParasPalletName::get(), *parachain); - trie.insert(&storage_key.0, ¶chain_head.encode()) + let leaf_data = if i == 0 { + grow_trie_leaf_value(parachain_head.encode(), size) + } else { + parachain_head.encode() + }; + trie.insert(&storage_key.0, &leaf_data) .map_err(|_| "TrieMut::insert has failed") .expect("TrieMut::insert should not fail in benchmarks"); storage_keys.push(storage_key); parachain_heads.push((*parachain, parachain_head.hash())) } } - state_root = grow_trie(state_root, &mut mdb, size); // generate heads storage proof let proof = record_all_trie_keys::, _>(&mdb, &state_root) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 337943bee4edc..f79deb7e7527c 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -41,6 +41,7 @@ use crate::*; +use bp_header_chain::justification::required_justification_precommits; use bp_runtime::BasicOperatingMode; use bp_test_utils::{ accounts, make_justification_for_header, JustificationGeneratorParams, TEST_GRANDPA_ROUND, @@ -66,13 +67,14 @@ const MAX_VOTE_ANCESTRIES_RANGE_END: u32 = MAX_VOTE_ANCESTRIES_RANGE_BEGIN + MAX_VOTE_ANCESTRIES_RANGE_BEGIN; // the same with validators - if there are too much validators, let's run benchmarks on subrange -fn validator_set_range_end, I: 'static>() -> u32 { +fn precommits_range_end, I: 'static>() -> u32 { let max_bridged_authorities = T::BridgedChain::MAX_AUTHORITIES_COUNT; if max_bridged_authorities > 128 { sp_std::cmp::max(128, max_bridged_authorities / 5) } else { max_bridged_authorities - } + }; + required_justification_precommits(max_bridged_authorities) } /// Prepare header and its justification to submit using `submit_finality_proof`. @@ -80,7 +82,10 @@ fn prepare_benchmark_data, I: 'static>( precommits: u32, ancestors: u32, ) -> (BridgedHeader, GrandpaJustification>) { - let authority_list = accounts(precommits as u16) + // going from precommits to total authorities count + let total_authorities_count = (3 * precommits - 1) / 2; + + let authority_list = accounts(total_authorities_count as u16) .iter() .map(|id| (AuthorityId::from(*id), 1)) .collect::>(); @@ -114,7 +119,7 @@ benchmarks_instance_pallet! { // This is the "gold standard" benchmark for this extrinsic, and it's what should be used to // annotate the weight in the pallet. submit_finality_proof { - let p in 1 .. validator_set_range_end::(); + let p in 1 .. precommits_range_end::(); let v in MAX_VOTE_ANCESTRIES_RANGE_BEGIN..MAX_VOTE_ANCESTRIES_RANGE_END; let caller: T::AccountId = whitelisted_caller(); let (header, justification) = prepare_benchmark_data::(p, v); diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 44b4ebd37fbaf..8896674c0112f 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -93,19 +93,19 @@ impl WeightInfo for BridgeWeight { /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// The range of component `p` is `[1, 5]`. + /// The range of component `p` is `[1, 4]`. /// /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { // Proof Size summary in bytes: - // Measured: `416 + p * (40 ±0)` + // Measured: `394 + p * (60 ±0)` // Estimated: `4745` - // Minimum execution time: 221_703 nanoseconds. - Weight::from_parts(39_358_497, 4745) - // Standard Error: 85_573 - .saturating_add(Weight::from_ref_time(40_593_280).saturating_mul(p.into())) - // Standard Error: 7_808 - .saturating_add(Weight::from_ref_time(1_529_400).saturating_mul(v.into())) + // Minimum execution time: 221_810 nanoseconds. + Weight::from_parts(33_157_392, 4745) + // Standard Error: 109_045 + .saturating_add(Weight::from_ref_time(41_100_656).saturating_mul(p.into())) + // Standard Error: 7_754 + .saturating_add(Weight::from_ref_time(1_534_466).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -148,19 +148,19 @@ impl WeightInfo for () { /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// The range of component `p` is `[1, 5]`. + /// The range of component `p` is `[1, 4]`. /// /// The range of component `v` is `[50, 100]`. fn submit_finality_proof(p: u32, v: u32) -> Weight { // Proof Size summary in bytes: - // Measured: `416 + p * (40 ±0)` + // Measured: `394 + p * (60 ±0)` // Estimated: `4745` - // Minimum execution time: 221_703 nanoseconds. - Weight::from_parts(39_358_497, 4745) - // Standard Error: 85_573 - .saturating_add(Weight::from_ref_time(40_593_280).saturating_mul(p.into())) - // Standard Error: 7_808 - .saturating_add(Weight::from_ref_time(1_529_400).saturating_mul(v.into())) + // Minimum execution time: 221_810 nanoseconds. + Weight::from_parts(33_157_392, 4745) + // Standard Error: 109_045 + .saturating_add(Weight::from_ref_time(41_100_656).saturating_mul(p.into())) + // Standard Error: 7_754 + .saturating_add(Weight::from_ref_time(1_534_466).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index a89cb3a8ef038..955dd3da2c57b 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -238,7 +238,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: StorageProofSize::HasExtraNodes(1024), + size: StorageProofSize::HasLargeLeaf(1024), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { @@ -272,7 +272,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, - size: StorageProofSize::HasExtraNodes(16 * 1024), + size: StorageProofSize::HasLargeLeaf(16 * 1024), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) verify { diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index f18285f3dfee4..8a85c8e6b2d25 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -88,8 +88,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 50_655 nanoseconds. - Weight::from_parts(60_502_000, 54703) + // Minimum execution time: 48_426 nanoseconds. + Weight::from_parts(50_113_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -116,8 +116,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 58_861 nanoseconds. - Weight::from_parts(60_288_000, 54703) + // Minimum execution time: 59_739 nanoseconds. + Weight::from_parts(61_704_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -144,8 +144,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 53_459 nanoseconds. - Weight::from_parts(54_577_000, 54703) + // Minimum execution time: 53_760 nanoseconds. + Weight::from_parts(55_645_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -167,8 +167,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 54_011 nanoseconds. - Weight::from_parts(55_573_000, 54200) + // Minimum execution time: 49_582 nanoseconds. + Weight::from_parts(51_250_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -190,8 +190,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 105_856 nanoseconds. - Weight::from_parts(109_112_000, 54200) + // Minimum execution time: 76_418 nanoseconds. + Weight::from_parts(77_877_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -212,14 +212,14 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `5619` - // Minimum execution time: 40_894 nanoseconds. - Weight::from_parts(41_766_000, 5619) + // Estimated: `5624` + // Minimum execution time: 41_795 nanoseconds. + Weight::from_parts(43_683_000, 5624) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -240,14 +240,14 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `5619` - // Minimum execution time: 39_996 nanoseconds. - Weight::from_parts(41_452_000, 5619) + // Estimated: `5624` + // Minimum execution time: 39_946 nanoseconds. + Weight::from_parts(41_509_000, 5624) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -268,14 +268,14 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8154` - // Minimum execution time: 42_281 nanoseconds. - Weight::from_parts(43_593_000, 8154) + // Estimated: `8164` + // Minimum execution time: 42_882 nanoseconds. + Weight::from_parts(44_367_000, 8164) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -306,8 +306,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 50_655 nanoseconds. - Weight::from_parts(60_502_000, 54703) + // Minimum execution time: 48_426 nanoseconds. + Weight::from_parts(50_113_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -334,8 +334,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 58_861 nanoseconds. - Weight::from_parts(60_288_000, 54703) + // Minimum execution time: 59_739 nanoseconds. + Weight::from_parts(61_704_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -362,8 +362,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 53_459 nanoseconds. - Weight::from_parts(54_577_000, 54703) + // Minimum execution time: 53_760 nanoseconds. + Weight::from_parts(55_645_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -385,8 +385,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 54_011 nanoseconds. - Weight::from_parts(55_573_000, 54200) + // Minimum execution time: 49_582 nanoseconds. + Weight::from_parts(51_250_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -408,8 +408,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 105_856 nanoseconds. - Weight::from_parts(109_112_000, 54200) + // Minimum execution time: 76_418 nanoseconds. + Weight::from_parts(77_877_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -430,14 +430,14 @@ impl WeightInfo for () { /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `5619` - // Minimum execution time: 40_894 nanoseconds. - Weight::from_parts(41_766_000, 5619) + // Estimated: `5624` + // Minimum execution time: 41_795 nanoseconds. + Weight::from_parts(43_683_000, 5624) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -458,14 +458,14 @@ impl WeightInfo for () { /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `5619` - // Minimum execution time: 39_996 nanoseconds. - Weight::from_parts(41_452_000, 5619) + // Estimated: `5624` + // Minimum execution time: 39_946 nanoseconds. + Weight::from_parts(41_509_000, 5624) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -486,14 +486,14 @@ impl WeightInfo for () { /// /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) /// - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(60), added: 2535, + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8154` - // Minimum execution time: 42_281 nanoseconds. - Weight::from_parts(43_593_000, 8154) + // Estimated: `8164` + // Minimum execution time: 42_882 nanoseconds. + Weight::from_parts(44_367_000, 8164) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index b156b724afeb3..83cfba0b8c6b0 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -85,7 +85,7 @@ benchmarks_instance_pallet! { let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, - StorageProofSize::HasExtraNodes(1024), + StorageProofSize::HasLargeLeaf(1024), ); let at_relay_block = (relay_block_number, relay_block_hash); }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof) @@ -102,7 +102,7 @@ benchmarks_instance_pallet! { let (relay_block_number, relay_block_hash, parachain_heads_proof, parachains_heads) = T::prepare_parachain_heads_proof( ¶chains, DEFAULT_PARACHAIN_HEAD_SIZE, - StorageProofSize::HasExtraNodes(16 * 1024), + StorageProofSize::HasLargeLeaf(16 * 1024), ); let at_relay_block = (relay_block_number, relay_block_hash); }: submit_parachain_heads(RawOrigin::Signed(sender), at_relay_block, parachains_heads, parachain_heads_proof) diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 5ee1e4d36212f..cce2febcf4f0a 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_parachains //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -77,23 +77,21 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: - /// Some(64), added: 2044, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Some(64), added: 1549, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: - /// Some(196), added: 2176, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Some(196), added: 1681, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. - fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { + fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `5143` - // Minimum execution time: 35_160 nanoseconds. - Weight::from_parts(36_951_585, 5143) - // Standard Error: 336_932 - .saturating_add(Weight::from_ref_time(407_557).saturating_mul(p.into())) + // Estimated: `4648` + // Minimum execution time: 36_567 nanoseconds. + Weight::from_parts(38_887_022, 4648) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -114,19 +112,19 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: - /// Some(64), added: 2044, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Some(64), added: 1549, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: - /// Some(196), added: 2176, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `5143` - // Minimum execution time: 42_276 nanoseconds. - Weight::from_parts(43_525_000, 5143) + // Estimated: `4648` + // Minimum execution time: 37_910 nanoseconds. + Weight::from_parts(38_967_000, 4648) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -147,19 +145,19 @@ impl WeightInfo for BridgeWeight { /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: - /// Some(64), added: 2044, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Some(64), added: 1549, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: - /// Some(196), added: 2176, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `5143` - // Minimum execution time: 85_824 nanoseconds. - Weight::from_parts(87_335_000, 5143) + // Estimated: `4648` + // Minimum execution time: 62_823 nanoseconds. + Weight::from_parts(64_658_000, 4648) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -184,23 +182,21 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: - /// Some(64), added: 2044, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Some(64), added: 1549, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: - /// Some(196), added: 2176, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Some(196), added: 1681, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. - fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { + fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `5143` - // Minimum execution time: 35_160 nanoseconds. - Weight::from_parts(36_951_585, 5143) - // Standard Error: 336_932 - .saturating_add(Weight::from_ref_time(407_557).saturating_mul(p.into())) + // Estimated: `4648` + // Minimum execution time: 36_567 nanoseconds. + Weight::from_parts(38_887_022, 4648) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -221,19 +217,19 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: - /// Some(64), added: 2044, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Some(64), added: 1549, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: - /// Some(196), added: 2176, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `5143` - // Minimum execution time: 42_276 nanoseconds. - Weight::from_parts(43_525_000, 5143) + // Estimated: `4648` + // Minimum execution time: 37_910 nanoseconds. + Weight::from_parts(38_967_000, 4648) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -254,19 +250,19 @@ impl WeightInfo for () { /// /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(14400), max_size: - /// Some(64), added: 2044, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Some(64), added: 1549, mode: MaxEncodedLen) /// /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(14400), max_size: - /// Some(196), added: 2176, mode: MaxEncodedLen) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { // Proof Size summary in bytes: // Measured: `366` - // Estimated: `5143` - // Minimum execution time: 85_824 nanoseconds. - Weight::from_parts(87_335_000, 5143) + // Estimated: `4648` + // Minimum execution time: 62_823 nanoseconds. + Weight::from_parts(64_658_000, 4648) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 572935f63025e..5b6a70854e149 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `serban-ROG-Zephyrus`, CPU: `12th Gen Intel(R) Core(TM) i7-12700H` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -71,8 +71,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `5111` - // Minimum execution time: 43_031 nanoseconds. - Weight::from_parts(44_527_000, 5111) + // Minimum execution time: 48_688 nanoseconds. + Weight::from_parts(50_457_000, 5111) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -93,8 +93,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `275` // Estimated: `5111` - // Minimum execution time: 43_031 nanoseconds. - Weight::from_parts(44_527_000, 5111) + // Minimum execution time: 48_688 nanoseconds. + Weight::from_parts(50_457_000, 5111) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 133a51ce6e7f5..aa9c3088fa42f 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -16,7 +16,7 @@ //! Logic for checking Substrate storage proofs. -use codec::{Decode, Encode}; +use codec::Decode; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; use sp_runtime::RuntimeDebug; use sp_std::{boxed::Box, collections::btree_set::BTreeSet, vec::Vec}; @@ -36,9 +36,6 @@ pub enum ProofSize { /// The proof is expected to be minimal. If value size may be changed, then it is expected to /// have given size. Minimal(u32), - /// The proof is expected to have at least given size and grow by increasing number of trie - /// nodes included in the proof. - HasExtraNodes(u32), /// The proof is expected to have at least given size and grow by increasing value that is /// stored in the trie. HasLargeLeaf(u32), @@ -46,7 +43,8 @@ pub enum ProofSize { /// 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. +/// authentication against a known Merkle root as well as the values in the +/// database themselves. pub struct StorageProofChecker where H: Hasher, @@ -157,6 +155,7 @@ impl From for &'static str { /// NOTE: This should only be used for **testing**. #[cfg(feature = "std")] pub fn craft_valid_storage_proof() -> (sp_core::H256, RawStorageProof) { + use codec::Encode; use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; let state_version = sp_runtime::StateVersion::default(); From f1ab461bc84f5bd3127a81bb978c99cc6fc0fe1f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 1 Mar 2023 15:44:10 +0200 Subject: [PATCH 0968/1210] Update BHR and BHW spec version (#1922) * Update BHR and BHW spec version * Remove docs in verify-pallets-build.sh * Remove only docs/dockerhub-* --- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/chains/wococo.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index b1e8d1bef85ed..166e6edbad360 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,5 +27,5 @@ impl CliChain for Rococo { impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9371, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9372, transaction_version: 1 }); } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index cb8dff620a571..b6eceb8614e83 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -27,5 +27,5 @@ impl CliChain for Wococo { impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9371, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9372, transaction_version: 1 }); } From f5e874752e2598f582f0d5db0a1d79af079d149c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 1 Mar 2023 17:53:11 +0300 Subject: [PATCH 0969/1210] Verify with-parachain message benchmarks on CI (#1923) * verify with-parachain message benchmarks on CI * trigger CI * Revert "trigger CI" This reverts commit 188cd01563bc8b3537d042c6c8d5181b7cfcdac8. --- bin/millau/runtime/src/lib.rs | 77 +++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 3e46d6ba15a62..beb2a4063a800 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -933,9 +933,10 @@ impl_runtime_apis! { let mut list = Vec::::new(); - list_benchmark!(list, extra, pallet_bridge_messages, MessagesBench::); + list_benchmark!(list, extra, RialtoParachainMessages, MessagesBench::); + list_benchmark!(list, extra, RialtoMessages, MessagesBench::); list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); - list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::); + list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::); list_benchmark!(list, extra, pallet_bridge_relayers, RelayersBench::); let storage_info = AllPalletsWithSystem::storage_info(); @@ -964,7 +965,12 @@ impl_runtime_apis! { let mut batches = Vec::::new(); let params = (&config, &whitelist); - use bridge_runtime_common::messages_benchmarking::{prepare_message_delivery_proof_from_grandpa_chain, prepare_message_proof_from_grandpa_chain}; + use bridge_runtime_common::messages_benchmarking::{ + prepare_message_delivery_proof_from_grandpa_chain, + prepare_message_delivery_proof_from_parachain, + prepare_message_proof_from_grandpa_chain, + prepare_message_proof_from_parachain, + }; use pallet_bridge_messages::benchmarking::{ Pallet as MessagesBench, Config as MessagesConfig, @@ -980,28 +986,66 @@ impl_runtime_apis! { Config as RelayersConfig, }; use rialto_messages::WithRialtoMessageBridge; + use rialto_parachain_messages::WithRialtoParachainMessageBridge; + + impl MessagesConfig for Runtime { + fn prepare_message_proof( + params: MessageProofParams, + ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { + prepare_message_proof_from_parachain::< + Runtime, + WithRialtoParachainsInstance, + WithRialtoParachainMessageBridge, + >(params) + } + + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> rialto_messages::ToRialtoMessagesDeliveryProof { + prepare_message_delivery_proof_from_parachain::< + Runtime, + WithRialtoParachainsInstance, + WithRialtoParachainMessageBridge, + >(params) + } + + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + use bridge_runtime_common::messages::MessageBridge; + + let lane = >::bench_lane_id(); + let bridged_chain_id = WithRialtoParachainMessageBridge::BRIDGED_CHAIN_ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) + ).is_some() + } + } impl MessagesConfig for Runtime { fn prepare_message_proof( params: MessageProofParams, ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { - prepare_message_proof_from_grandpa_chain::( - params, - ) + prepare_message_proof_from_grandpa_chain::< + Runtime, + RialtoGrandpaInstance, + WithRialtoMessageBridge, + >(params) } fn prepare_message_delivery_proof( params: MessageDeliveryProofParams, ) -> rialto_messages::ToRialtoMessagesDeliveryProof { - prepare_message_delivery_proof_from_grandpa_chain::( - params, - ) + prepare_message_delivery_proof_from_grandpa_chain::< + Runtime, + RialtoGrandpaInstance, + WithRialtoMessageBridge, + >(params) } fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { use bridge_runtime_common::messages::MessageBridge; - let lane = Self::bench_lane_id(); + let lane = >::bench_lane_id(); let bridged_chain_id = WithRialtoMessageBridge::BRIDGED_CHAIN_ID; pallet_bridge_relayers::Pallet::::relayer_reward( relayer, @@ -1026,7 +1070,10 @@ impl_runtime_apis! { bp_polkadot_core::parachains::ParaHeadsProof, Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, ) { - bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::( + bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::< + Runtime, + WithRialtoParachainsInstance, + >( parachains, parachain_head_size, proof_size, @@ -1051,7 +1098,13 @@ impl_runtime_apis! { add_benchmark!( params, batches, - pallet_bridge_messages, + RialtoParachainMessages, + MessagesBench:: + ); + add_benchmark!( + params, + batches, + RialtoMessages, MessagesBench:: ); add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); From c5e59c92539bde0a4365c5ded2b4ef54022fc96b Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 1 Mar 2023 18:24:48 +0200 Subject: [PATCH 0970/1210] Remove subxt dependency features (#1924) --- relays/client-rialto-parachain/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index c1a6b5d69aaf1..807da290d249c 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -subxt = { git = "https://github.com/paritytech/subxt", branch = "master" } +subxt = { git = "https://github.com/paritytech/subxt", branch = "master", default-features = false, features = [] } # Bridge dependencies From c9a586490c3399f09519aa6bf6353f089a31edc2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 2 Mar 2023 11:21:10 +0300 Subject: [PATCH 0971/1210] get rid of obsolete weight functions (#1926) --- .../src/refund_relayer_extension.rs | 6 +- modules/beefy/src/lib.rs | 2 +- modules/beefy/src/mock.rs | 2 +- modules/grandpa/src/mock.rs | 2 +- modules/grandpa/src/weights.rs | 26 +++---- modules/messages/src/mock.rs | 6 +- modules/messages/src/weights.rs | 74 +++++++++---------- modules/parachains/src/mock.rs | 2 +- modules/parachains/src/weights.rs | 34 +++++---- modules/relayers/src/weights.rs | 10 +-- modules/shift-session-manager/src/lib.rs | 2 +- .../chain-bridge-hub-cumulus/src/lib.rs | 6 +- relays/messages/src/message_lane_loop.rs | 4 +- relays/messages/src/message_race_delivery.rs | 16 ++-- 14 files changed, 99 insertions(+), 93 deletions(-) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 0a61f4fdd023f..7be97f19ad2ab 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -746,8 +746,9 @@ mod tests { fn dispatch_info() -> DispatchInfo { DispatchInfo { - weight: Weight::from_ref_time( + weight: Weight::from_parts( frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND, + 0, ), class: frame_support::dispatch::DispatchClass::Normal, pays_fee: frame_support::dispatch::Pays::Yes, @@ -1037,8 +1038,9 @@ mod tests { initialize_environment(200, 200, [1u8; 32].into(), 200); let mut dispatch_info = dispatch_info(); - dispatch_info.weight = Weight::from_ref_time( + dispatch_info.weight = Weight::from_parts( frame_support::weights::constants::WEIGHT_REF_TIME_PER_SECOND * 2, + 0, ); // without any size/weight refund: we expect regular reward diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index e05a4119463dc..a717acfe914fd 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -133,7 +133,7 @@ pub mod pallet { fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { >::mutate(|count| *count = count.saturating_sub(1)); - Weight::from_ref_time(0) + Weight::from_parts(0, 0) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 212c6c5d434bf..551800090f7d5 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -72,7 +72,7 @@ construct_runtime! { } parameter_types! { - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index f0ae2583529d5..acedfc3582c24 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -54,7 +54,7 @@ construct_runtime! { } parameter_types! { - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 8896674c0112f..089aee8b56951 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_grandpa //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -100,12 +100,12 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `394 + p * (60 ±0)` // Estimated: `4745` - // Minimum execution time: 221_810 nanoseconds. - Weight::from_parts(33_157_392, 4745) - // Standard Error: 109_045 - .saturating_add(Weight::from_ref_time(41_100_656).saturating_mul(p.into())) - // Standard Error: 7_754 - .saturating_add(Weight::from_ref_time(1_534_466).saturating_mul(v.into())) + // Minimum execution time: 228_072 nanoseconds. + Weight::from_parts(57_853_228, 4745) + // Standard Error: 149_421 + .saturating_add(Weight::from_parts(36_708_702, 0).saturating_mul(p.into())) + // Standard Error: 10_625 + .saturating_add(Weight::from_parts(1_469_032, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -155,12 +155,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `394 + p * (60 ±0)` // Estimated: `4745` - // Minimum execution time: 221_810 nanoseconds. - Weight::from_parts(33_157_392, 4745) - // Standard Error: 109_045 - .saturating_add(Weight::from_ref_time(41_100_656).saturating_mul(p.into())) - // Standard Error: 7_754 - .saturating_add(Weight::from_ref_time(1_534_466).saturating_mul(v.into())) + // Minimum execution time: 228_072 nanoseconds. + Weight::from_parts(57_853_228, 4745) + // Standard Error: 149_421 + .saturating_add(Weight::from_parts(36_708_702, 0).saturating_mul(p.into())) + // Standard Error: 10_625 + .saturating_add(Weight::from_parts(1_469_032, 0).saturating_mul(v.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 084262c790532..a31ee2b940134 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -89,7 +89,7 @@ frame_support::construct_runtime! { parameter_types! { pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } @@ -410,7 +410,7 @@ pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { TestPayload { id, reject_by_lane_verifier: false, - declared_weight: Weight::from_ref_time(declared_weight), + declared_weight: Weight::from_parts(declared_weight, 0), dispatch_result: dispatch_result(0), extra: Vec::new(), } @@ -421,7 +421,7 @@ pub const fn dispatch_result( unspent_weight: u64, ) -> MessageDispatchResult { MessageDispatchResult { - unspent_weight: Weight::from_ref_time(unspent_weight), + unspent_weight: Weight::from_parts(unspent_weight, 0), dispatch_level_result: (), } } diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 8a85c8e6b2d25..4b2e5b48ee256 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for pallet_bridge_messages +//! Autogenerated weights for RialtoMessages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -29,7 +29,7 @@ // --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_bridge_messages +// --pallet=RialtoMessages // --extrinsic=* // --execution=wasm // --wasm-execution=Compiled @@ -48,7 +48,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_bridge_messages. +/// Weight functions needed for RialtoMessages. pub trait WeightInfo { fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; @@ -60,7 +60,7 @@ pub trait WeightInfo { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; } -/// Weights for `pallet_bridge_messages` that are generated using one of the Bridge testnets. +/// Weights for `RialtoMessages` that are generated using one of the Bridge testnets. /// /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); @@ -88,8 +88,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 48_426 nanoseconds. - Weight::from_parts(50_113_000, 54703) + // Minimum execution time: 48_058 nanoseconds. + Weight::from_parts(50_422_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -116,8 +116,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 59_739 nanoseconds. - Weight::from_parts(61_704_000, 54703) + // Minimum execution time: 59_371 nanoseconds. + Weight::from_parts(61_726_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -144,8 +144,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 53_760 nanoseconds. - Weight::from_parts(55_645_000, 54703) + // Minimum execution time: 53_398 nanoseconds. + Weight::from_parts(54_351_000, 54703) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -167,8 +167,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 49_582 nanoseconds. - Weight::from_parts(51_250_000, 54200) + // Minimum execution time: 50_064 nanoseconds. + Weight::from_parts(51_306_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -190,8 +190,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 76_418 nanoseconds. - Weight::from_parts(77_877_000, 54200) + // Minimum execution time: 75_403 nanoseconds. + Weight::from_parts(77_006_000, 54200) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -218,8 +218,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `579` // Estimated: `5624` - // Minimum execution time: 41_795 nanoseconds. - Weight::from_parts(43_683_000, 5624) + // Minimum execution time: 41_670 nanoseconds. + Weight::from_parts(42_863_000, 5624) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -246,8 +246,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `596` // Estimated: `5624` - // Minimum execution time: 39_946 nanoseconds. - Weight::from_parts(41_509_000, 5624) + // Minimum execution time: 40_928 nanoseconds. + Weight::from_parts(42_165_000, 5624) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -274,8 +274,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `596` // Estimated: `8164` - // Minimum execution time: 42_882 nanoseconds. - Weight::from_parts(44_367_000, 8164) + // Minimum execution time: 44_022 nanoseconds. + Weight::from_parts(44_657_000, 8164) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -306,8 +306,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 48_426 nanoseconds. - Weight::from_parts(50_113_000, 54703) + // Minimum execution time: 48_058 nanoseconds. + Weight::from_parts(50_422_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -334,8 +334,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 59_739 nanoseconds. - Weight::from_parts(61_704_000, 54703) + // Minimum execution time: 59_371 nanoseconds. + Weight::from_parts(61_726_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -362,8 +362,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `693` // Estimated: `54703` - // Minimum execution time: 53_760 nanoseconds. - Weight::from_parts(55_645_000, 54703) + // Minimum execution time: 53_398 nanoseconds. + Weight::from_parts(54_351_000, 54703) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -385,8 +385,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 49_582 nanoseconds. - Weight::from_parts(51_250_000, 54200) + // Minimum execution time: 50_064 nanoseconds. + Weight::from_parts(51_306_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -408,8 +408,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `618` // Estimated: `54200` - // Minimum execution time: 76_418 nanoseconds. - Weight::from_parts(77_877_000, 54200) + // Minimum execution time: 75_403 nanoseconds. + Weight::from_parts(77_006_000, 54200) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -436,8 +436,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `579` // Estimated: `5624` - // Minimum execution time: 41_795 nanoseconds. - Weight::from_parts(43_683_000, 5624) + // Minimum execution time: 41_670 nanoseconds. + Weight::from_parts(42_863_000, 5624) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -464,8 +464,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `596` // Estimated: `5624` - // Minimum execution time: 39_946 nanoseconds. - Weight::from_parts(41_509_000, 5624) + // Minimum execution time: 40_928 nanoseconds. + Weight::from_parts(42_165_000, 5624) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -492,8 +492,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `596` // Estimated: `8164` - // Minimum execution time: 42_882 nanoseconds. - Weight::from_parts(44_367_000, 8164) + // Minimum execution time: 44_022 nanoseconds. + Weight::from_parts(44_657_000, 8164) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index aabcdcdd364ce..83d347018e45e 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -158,7 +158,7 @@ construct_runtime! { parameter_types! { pub const BlockHashCount: TestNumber = 250; - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index cce2febcf4f0a..54a835cbc8738 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_parachains //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -86,12 +86,14 @@ impl WeightInfo for BridgeWeight { /// Some(196), added: 1681, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. - fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { // Proof Size summary in bytes: // Measured: `366` // Estimated: `4648` - // Minimum execution time: 36_567 nanoseconds. - Weight::from_parts(38_887_022, 4648) + // Minimum execution time: 36_701 nanoseconds. + Weight::from_parts(38_597_828, 4648) + // Standard Error: 190_859 + .saturating_add(Weight::from_parts(60_685, 0).saturating_mul(p.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -123,8 +125,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `366` // Estimated: `4648` - // Minimum execution time: 37_910 nanoseconds. - Weight::from_parts(38_967_000, 4648) + // Minimum execution time: 38_189 nanoseconds. + Weight::from_parts(39_252_000, 4648) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -156,8 +158,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `366` // Estimated: `4648` - // Minimum execution time: 62_823 nanoseconds. - Weight::from_parts(64_658_000, 4648) + // Minimum execution time: 62_868 nanoseconds. + Weight::from_parts(63_581_000, 4648) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -191,12 +193,14 @@ impl WeightInfo for () { /// Some(196), added: 1681, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. - fn submit_parachain_heads_with_n_parachains(_p: u32) -> Weight { + fn submit_parachain_heads_with_n_parachains(p: u32) -> Weight { // Proof Size summary in bytes: // Measured: `366` // Estimated: `4648` - // Minimum execution time: 36_567 nanoseconds. - Weight::from_parts(38_887_022, 4648) + // Minimum execution time: 36_701 nanoseconds. + Weight::from_parts(38_597_828, 4648) + // Standard Error: 190_859 + .saturating_add(Weight::from_parts(60_685, 0).saturating_mul(p.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -228,8 +232,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `366` // Estimated: `4648` - // Minimum execution time: 37_910 nanoseconds. - Weight::from_parts(38_967_000, 4648) + // Minimum execution time: 38_189 nanoseconds. + Weight::from_parts(39_252_000, 4648) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -261,8 +265,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `366` // Estimated: `4648` - // Minimum execution time: 62_823 nanoseconds. - Weight::from_parts(64_658_000, 4648) + // Minimum execution time: 62_868 nanoseconds. + Weight::from_parts(63_581_000, 4648) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 5b6a70854e149..1f111aaf1367d 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -71,8 +71,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `275` // Estimated: `5111` - // Minimum execution time: 48_688 nanoseconds. - Weight::from_parts(50_457_000, 5111) + // Minimum execution time: 48_639 nanoseconds. + Weight::from_parts(49_600_000, 5111) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -93,8 +93,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `275` // Estimated: `5111` - // Minimum execution time: 48_688 nanoseconds. - Weight::from_parts(50_457_000, 5111) + // Minimum execution time: 48_639 nanoseconds. + Weight::from_parts(49_600_000, 5111) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index dce6005ab549d..63656c81eed16 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -152,7 +152,7 @@ mod tests { } parameter_types! { - pub const MaximumBlockWeight: Weight = Weight::from_ref_time(1024); + pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); } diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 3a05cb48b3b87..cbdd36c2e4ae3 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -45,7 +45,7 @@ pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// time. /// /// This is a copy-paste from the cumulus repo's `parachains-common` crate. -const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_SECOND) +const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_SECOND, 0) .saturating_div(2) .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); @@ -62,10 +62,10 @@ parameter_types! { ); /// Importing a block with 0 Extrinsics. - pub const BlockExecutionWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS) + pub const BlockExecutionWeight: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS, 0) .saturating_mul(5_000_000); /// Executing a NO-OP `System::remarks` Extrinsic. - pub const ExtrinsicBaseWeight: Weight = Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS) + pub const ExtrinsicBaseWeight: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS, 0) .saturating_mul(125_000); pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 2903435dda5b8..0533e51d5db47 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -723,7 +723,7 @@ pub(crate) mod tests { ( nonce, MessageDetails { - dispatch_weight: Weight::from_ref_time(1), + dispatch_weight: Weight::from_parts(1, 0), size: 1, reward: 1, }, @@ -949,7 +949,7 @@ pub(crate) mod tests { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: Weight::from_ref_time(4), + max_messages_weight_in_single_batch: Weight::from_parts(4, 0), max_messages_size_in_single_batch: 4, }, }, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 8b8e690ec4a2e..d25a2413b0db1 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -588,7 +588,7 @@ mod tests { use super::*; - const DEFAULT_DISPATCH_WEIGHT: Weight = Weight::from_ref_time(1); + const DEFAULT_DISPATCH_WEIGHT: Weight = Weight::from_parts(1, 0); const DEFAULT_SIZE: u32 = 1; type TestRaceState = RaceState; @@ -632,7 +632,7 @@ mod tests { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: Weight::from_ref_time(4), + max_messages_weight_in_single_batch: Weight::from_parts(4, 0), max_messages_size_in_single_batch: 4, latest_confirmed_nonces_at_source: vec![(header_id(1), 19)].into_iter().collect(), lane_source_client: TestSourceClient::default(), @@ -671,7 +671,7 @@ mod tests { fn proof_parameters(state_required: bool, weight: u32) -> MessageProofParameters { MessageProofParameters { outbound_state_proof_required: state_required, - dispatch_weight: Weight::from_ref_time(weight as u64), + dispatch_weight: Weight::from_parts(weight as u64, 0), } } @@ -685,7 +685,7 @@ mod tests { ( idx, MessageDetails { - dispatch_weight: Weight::from_ref_time(idx), + dispatch_weight: Weight::from_parts(idx, 0), size: idx as _, reward: idx as _, }, @@ -813,7 +813,7 @@ mod tests { let (state, mut strategy) = prepare_strategy(); // not all queued messages may fit in the batch, because batch has max weight - strategy.max_messages_weight_in_single_batch = Weight::from_ref_time(3); + strategy.max_messages_weight_in_single_batch = Weight::from_parts(3, 0); assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=22), proof_parameters(false, 3))) @@ -828,7 +828,7 @@ mod tests { // first message doesn't fit in the batch, because it has weight (10) that overflows max // weight (4) strategy.strategy.source_queue_mut()[0].1.get_mut(&20).unwrap().dispatch_weight = - Weight::from_ref_time(10); + Weight::from_parts(10, 0); assert_eq!( strategy.select_nonces_to_deliver(state).await, Some(((20..=20), proof_parameters(false, 10))) @@ -1014,7 +1014,7 @@ mod tests { strategy.max_unrewarded_relayer_entries_at_target = 100; strategy.max_unconfirmed_nonces_at_target = 100; strategy.max_messages_in_single_batch = 5; - strategy.max_messages_weight_in_single_batch = Weight::from_ref_time(100); + strategy.max_messages_weight_in_single_batch = Weight::from_parts(100, 0); strategy.max_messages_size_in_single_batch = 100; state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); @@ -1031,7 +1031,7 @@ mod tests { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, max_messages_in_single_batch: 4, - max_messages_weight_in_single_batch: Weight::from_ref_time(4), + max_messages_weight_in_single_batch: Weight::from_parts(4, 0), max_messages_size_in_single_batch: 4, latest_confirmed_nonces_at_source: VecDeque::new(), lane_source_client: TestSourceClient::default(), From fedfc968d1e010ec7cae2741b1e05f705949bc00 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 2 Mar 2023 17:02:49 +0300 Subject: [PATCH 0972/1210] Reconnect on-demand clients from MessagesSource::reconnect and MessagesTarget::reconnect (#1927) * reconnect on-demand clients from MessagesSource::reconnect and MessagesTarget::reconnect * add issue reference * fmt --- .../lib-substrate-relay/src/messages_source.rs | 16 +++++++++++++++- .../lib-substrate-relay/src/messages_target.rs | 16 +++++++++++++++- .../lib-substrate-relay/src/on_demand/headers.rs | 10 ++++++++++ relays/lib-substrate-relay/src/on_demand/mod.rs | 3 +++ .../src/on_demand/parachains.rs | 9 +++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 8d2ac5874fe60..a151af8ee8277 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -129,8 +129,22 @@ impl RelayClient for SubstrateMessagesSource

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { + // since the client calls RPC methods on both sides, we need to reconnect both self.source_client.reconnect().await?; - self.target_client.reconnect().await + self.target_client.reconnect().await?; + + // call reconnect on on-demand headers relay, because we may use different chains there + // and the error that has lead to reconnect may have came from those other chains + // (see `require_target_header_on_source`) + // + // this may lead to multiple reconnects to the same node during the same call and it + // needs to be addressed in the future + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1928 + if let Some(ref mut target_to_source_headers_relay) = self.target_to_source_headers_relay { + target_to_source_headers_relay.reconnect().await?; + } + + Ok(()) } } diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 75119a1de9768..7b0d9d63fb786 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -123,8 +123,22 @@ impl RelayClient for SubstrateMessagesTarget

{ type Error = SubstrateError; async fn reconnect(&mut self) -> Result<(), SubstrateError> { + // since the client calls RPC methods on both sides, we need to reconnect both self.target_client.reconnect().await?; - self.source_client.reconnect().await + self.source_client.reconnect().await?; + + // call reconnect on on-demand headers relay, because we may use different chains there + // and the error that has lead to reconnect may have came from those other chains + // (see `require_source_header_on_target`) + // + // this may lead to multiple reconnects to the same node during the same call and it + // needs to be addressed in the future + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1928 + if let Some(ref mut source_to_target_headers_relay) = self.source_to_target_headers_relay { + source_to_target_headers_relay.reconnect().await?; + } + + Ok(()) } } diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 75b402aff8732..090019f087f6c 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -60,6 +60,8 @@ pub struct OnDemandHeadersRelay { required_header_number: RequiredHeaderNumberRef, /// Client of the source chain. source_client: Client, + /// Client of the target chain. + target_client: Client, } impl OnDemandHeadersRelay

{ @@ -83,6 +85,7 @@ impl OnDemandHeadersRelay

{ relay_task_name: on_demand_headers_relay_name::(), required_header_number: required_header_number.clone(), source_client: source_client.clone(), + target_client: target_client.clone(), }; async_std::task::spawn(async move { background_task::

( @@ -104,6 +107,13 @@ impl OnDemandHeadersRelay

{ impl OnDemandRelay for OnDemandHeadersRelay

{ + async fn reconnect(&self) -> Result<(), SubstrateError> { + // using clone is fine here (to avoid mut requirement), because clone on Client clones + // internal references + self.source_client.clone().reconnect().await?; + self.target_client.clone().reconnect().await + } + async fn require_more_headers(&self, required_header: BlockNumberOf) { let mut required_header_number = self.required_header_number.lock().await; if required_header > *required_header_number { diff --git a/relays/lib-substrate-relay/src/on_demand/mod.rs b/relays/lib-substrate-relay/src/on_demand/mod.rs index eca7d20163d23..00bb33d674093 100644 --- a/relays/lib-substrate-relay/src/on_demand/mod.rs +++ b/relays/lib-substrate-relay/src/on_demand/mod.rs @@ -26,6 +26,9 @@ pub mod parachains; /// On-demand headers relay that is relaying finalizing headers only when requested. #[async_trait] pub trait OnDemandRelay: Send + Sync { + /// Reconnect to source and target nodes. + async fn reconnect(&self) -> Result<(), SubstrateError>; + /// Ask relay to relay source header with given number to the target chain. /// /// Depending on implementation, on-demand relay may also relay `required_header` ancestors diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 672530de3a58c..4c205770d4acb 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -119,6 +119,15 @@ impl OnDemandRelay, { + async fn reconnect(&self) -> Result<(), SubstrateError> { + // using clone is fine here (to avoid mut requirement), because clone on Client clones + // internal references + self.source_relay_client.clone().reconnect().await?; + self.target_client.clone().reconnect().await?; + // we'll probably need to reconnect relay chain relayer clients also + self.on_demand_source_relay_to_target_headers.reconnect().await + } + async fn require_more_headers(&self, required_header: BlockNumberOf) { if let Err(e) = self.required_header_number_sender.send(required_header).await { log::trace!( From cb492ad951ccc721828a9c12b0105fccf7c4a0d7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 3 Mar 2023 11:27:05 +0300 Subject: [PATCH 0973/1210] Improve some relay errors readability (#1930) * improve some relay errors readability * clippy --- relays/client-substrate/src/client.rs | 28 ++++++++++- relays/client-substrate/src/error.rs | 67 +++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index bddd53b39f8c4..80db593acbfa4 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -271,6 +271,10 @@ impl Client { Ok(SubstrateChainClient::::finalized_head(&*client).await?) }) .await + .map_err(|e| Error::FailedToReadBestFinalizedHeaderHash { + chain: C::NAME.into(), + error: e.boxed(), + }) } /// Return number of the best finalized block. @@ -292,6 +296,7 @@ impl Client { Ok(SubstrateChainClient::::header(&*client, None).await?) }) .await + .map_err(|e| Error::FailedToReadBestHeader { chain: C::NAME.into(), error: e.boxed() }) } /// Get a Substrate block from its hash. @@ -311,6 +316,11 @@ impl Client { Ok(SubstrateChainClient::::header(&*client, Some(block_hash)).await?) }) .await + .map_err(|e| Error::FailedToReadHeaderByHash { + chain: C::NAME.into(), + hash: format!("{block_hash}"), + error: e.boxed(), + }) } /// Get a Substrate block hash by its number. @@ -394,10 +404,17 @@ impl Client { storage_key: StorageKey, block_hash: Option, ) -> Result> { + let cloned_storage_key = storage_key.clone(); self.jsonrpsee_execute(move |client| async move { - Ok(SubstrateStateClient::::storage(&*client, storage_key, block_hash).await?) + Ok(SubstrateStateClient::::storage(&*client, storage_key.clone(), block_hash) + .await?) }) .await + .map_err(|e| Error::FailedToReadRuntimeStorageValue { + chain: C::NAME.into(), + key: cloned_storage_key, + error: e.boxed(), + }) } /// Return native tokens balance of the account. @@ -640,7 +657,14 @@ impl Client { input: Input, at_block: Option, ) -> Result { - let encoded_output = self.state_call(method_name, Bytes(input.encode()), at_block).await?; + let encoded_output = self + .state_call(method_name.clone(), Bytes(input.encode()), at_block) + .await + .map_err(|e| Error::ErrorExecutingRuntimeCall { + chain: C::NAME.into(), + method: method_name, + error: e.boxed(), + })?; Output::decode(&mut &encoded_output.0[..]).map_err(Error::ResponseParseFailed) } diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 3b83f917bf8e8..54247c5dc1768 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -20,6 +20,7 @@ use bp_polkadot_core::parachains::ParaId; use jsonrpsee::core::Error as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; +use sp_core::storage::StorageKey; use sp_runtime::transaction_validity::TransactionValidityError; use thiserror::Error; @@ -55,6 +56,52 @@ pub enum Error { /// The client we're connected to is not synced, so we can't rely on its state. #[error("Substrate client is not synced {0}.")] ClientNotSynced(Health), + /// Failed to read best finalized header hash from given chain. + #[error("Failed to read best finalized header hash of {chain}: {error:?}.")] + FailedToReadBestFinalizedHeaderHash { + /// Name of the chain where the error has happened. + chain: String, + /// Underlying error. + error: Box, + }, + /// Failed to read best finalized header from given chain. + #[error("Failed to read best header of {chain}: {error:?}.")] + FailedToReadBestHeader { + /// Name of the chain where the error has happened. + chain: String, + /// Underlying error. + error: Box, + }, + /// Failed to read header by hash from given chain. + #[error("Failed to read header {hash} of {chain}: {error:?}.")] + FailedToReadHeaderByHash { + /// Name of the chain where the error has happened. + chain: String, + /// Hash of the header we've tried to read. + hash: String, + /// Underlying error. + error: Box, + }, + /// Failed to execute runtime call at given chain. + #[error("Failed to execute runtime call {method} at {chain}: {error:?}.")] + ErrorExecutingRuntimeCall { + /// Name of the chain where the error has happened. + chain: String, + /// Runtime method name. + method: String, + /// Underlying error. + error: Box, + }, + /// Failed to read sotrage value at given chain. + #[error("Failed to read storage value {key:?} at {chain}: {error:?}.")] + FailedToReadRuntimeStorageValue { + /// Name of the chain where the error has happened. + chain: String, + /// Runtime storage key + key: StorageKey, + /// Underlying error. + error: Box, + }, /// The bridge pallet is halted and all transactions will be rejected. #[error("Bridge pallet is halted.")] BridgePalletIsHalted, @@ -81,16 +128,28 @@ impl From for Error { } } +impl Error { + /// Box the error. + pub fn boxed(self) -> Box { + Box::new(self) + } +} + impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { - matches!( - *self, + match *self { Error::RpcError(RpcError::Transport(_)) // right now if connection to the ws server is dropped (after it is already established), // we're getting this error | Error::RpcError(RpcError::Internal(_)) | Error::RpcError(RpcError::RestartNeeded(_)) - | Error::ClientNotSynced(_), - ) + | Error::ClientNotSynced(_) => true, + Error::FailedToReadBestFinalizedHeaderHash { ref error, .. } => error.is_connection_error(), + Error::FailedToReadBestHeader { ref error, .. } => error.is_connection_error(), + Error::FailedToReadHeaderByHash { ref error, .. } => error.is_connection_error(), + Error::ErrorExecutingRuntimeCall { ref error, .. } => error.is_connection_error(), + Error::FailedToReadRuntimeStorageValue { ref error, .. } => error.is_connection_error(), + _ => false, + } } } From f134390cb0a0a586f55dd5f5088f0fa4609f8785 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 03:01:34 +0000 Subject: [PATCH 0974/1210] Bump thiserror from 1.0.38 to 1.0.39 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.38 to 1.0.39. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.38...1.0.39) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 7e7eba5ec2bc8..72dfdcbcd9195 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -16,7 +16,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.1.1", features = ["derive"] } tokio = { version = "1.25", features = ["rt-multi-thread"] } -thiserror = "1.0.26" +thiserror = "1.0.39" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 96fe9356fa0fc..ef41561d88821 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.26" +thiserror = "1.0.39" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 1d7422d5a8c6b..893d70c6df25d 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1.0" sysinfo = "0.28" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.25", features = ["rt"] } -thiserror = "1.0.26" +thiserror = "1.0.39" # Bridge dependencies From c31190478947113bf419fe52aff49641e44dc5d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 03:11:36 +0000 Subject: [PATCH 0975/1210] Bump serde_json from 1.0.93 to 1.0.94 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.93 to 1.0.94. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.93...v1.0.94) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3d3d238943d09..bf169ebe40d98 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.6", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.93" +serde_json = "1.0.94" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 556088498f766..5d68714235b22 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.6", features = ["derive"] } -serde_json = "1.0.93" +serde_json = "1.0.94" # Bridge dependencies From c7a7913b8b248516cf68e8ee41cb343269edba96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 07:49:43 +0000 Subject: [PATCH 0976/1210] Bump async-trait from 0.1.64 to 0.1.66 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.64 to 0.1.66. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.64...0.1.66) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index d2938389ca77e..6800ca8dbfbb3 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.64" +async-trait = "0.1.66" futures = "0.3.26" log = "0.4.17" relay-utils = { path = "../utils" } From 9d37315feddb763f340a0c2ae3023318da8a0b3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 07:46:25 +0000 Subject: [PATCH 0977/1210] Bump tokio from 1.25.0 to 1.26.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.25.0 to 1.26.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.25.0...tokio-1.26.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 72dfdcbcd9195..5b6e08b5875b2 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.17" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.1.1", features = ["derive"] } -tokio = { version = "1.25", features = ["rt-multi-thread"] } +tokio = { version = "1.26", features = ["rt-multi-thread"] } thiserror = "1.0.39" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 893d70c6df25d..3a68ea25eb143 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.28" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.25", features = ["rt"] } +tokio = { version = "1.26", features = ["rt"] } thiserror = "1.0.39" # Bridge dependencies From 11412841d08ce7676b521b889ca55949be593828 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Mar 2023 13:47:11 +0300 Subject: [PATCH 0978/1210] Fix invalid messages relay delivery transactions (#1940) * + failing test: previous_nonces_are_selected_if_reorg_happens_at_target_chain * maybe fix for the issue? * another fix * previous_nonces_are_selected_if_reorg_happens_at_target_chain for MessageDeliveryStrategy * remove commented code * spelling --- relays/messages/src/message_race_delivery.rs | 110 +++++++++++-- relays/messages/src/message_race_limits.rs | 20 ++- relays/messages/src/message_race_strategy.rs | 162 +++++++++++++------ 3 files changed, 220 insertions(+), 72 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index d25a2413b0db1..b50e6c0841ead 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -255,7 +255,7 @@ struct MessageDeliveryStrategy { /// Latest confirmed nonces at the source client + the header id where we have first met this /// nonce. latest_confirmed_nonces_at_source: VecDeque<(SourceHeaderIdOf

, MessageNonce)>, - /// Target nonces from the source client. + /// Target nonces available at the **best** block of the target chain. target_nonces: Option>, /// Basic delivery strategy. strategy: MessageDeliveryStrategyBase

, @@ -387,13 +387,11 @@ where race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) { // best target nonces must always be ge than finalized target nonces - let mut target_nonces = self.target_nonces.take().unwrap_or_else(|| nonces.clone()); - target_nonces.nonces_data = nonces.nonces_data.clone(); - target_nonces.latest_nonce = std::cmp::max(target_nonces.latest_nonce, nonces.latest_nonce); - self.target_nonces = Some(target_nonces); + let latest_nonce = nonces.latest_nonce; + self.target_nonces = Some(nonces); self.strategy.best_target_nonces_updated( - TargetClientNonces { latest_nonce: nonces.latest_nonce, nonces_data: () }, + TargetClientNonces { latest_nonce, nonces_data: () }, race_state, ) } @@ -432,6 +430,7 @@ where &self, race_state: RaceState, TargetHeaderIdOf

, P::MessagesProof>, ) -> Option<(RangeInclusive, Self::ProofParameters)> { + let best_target_nonce = self.strategy.best_at_target()?; let best_finalized_source_header_id_at_best_target = race_state.best_finalized_source_header_id_at_best_target.clone()?; let latest_confirmed_nonce_at_source = self @@ -439,7 +438,8 @@ where .iter() .take_while(|(id, _)| id.0 <= best_finalized_source_header_id_at_best_target.0) .last() - .map(|(_, nonce)| *nonce)?; + .map(|(_, nonce)| *nonce) + .unwrap_or(best_target_nonce); let target_nonces = self.target_nonces.as_ref()?; // There's additional condition in the message delivery race: target would reject messages @@ -529,8 +529,8 @@ where let lane_source_client = self.lane_source_client.clone(); let lane_target_client = self.lane_target_client.clone(); - let maximal_source_queue_index = - self.strategy.maximal_available_source_queue_index(race_state)?; + let available_source_queue_indices = + self.strategy.available_source_queue_indices(race_state)?; let source_queue = self.strategy.source_queue(); let reference = RelayMessagesBatchReference { @@ -539,15 +539,13 @@ where max_messages_size_in_single_batch, lane_source_client: lane_source_client.clone(), lane_target_client: lane_target_client.clone(), + best_target_nonce, nonces_queue: source_queue.clone(), - nonces_queue_range: 0..maximal_source_queue_index + 1, + nonces_queue_range: available_source_queue_indices, metrics: self.metrics_msg.clone(), }; - let range_end = MessageRaceLimits::decide(reference).await?; - - let range_begin = source_queue[0].1.begin(); - let selected_nonces = range_begin..=range_end; + let selected_nonces = MessageRaceLimits::decide(reference).await?; let dispatch_weight = self.dispatch_weight_for_range(&selected_nonces); Some(( @@ -1057,4 +1055,88 @@ mod tests { ); assert_eq!(strategy.required_source_header_at_target(&source_header_id), None); } + + #[async_std::test] + async fn previous_nonces_are_selected_if_reorg_happens_at_target_chain() { + // this is the copy of the similar test in the `mesage_race_strategy.rs`, but it also tests + // that the `MessageDeliveryStrategy` acts properly in the similar scenario + + // tune parameters to allow 5 nonces per delivery transaction + let (mut state, mut strategy) = prepare_strategy(); + strategy.max_unrewarded_relayer_entries_at_target = 5; + strategy.max_unconfirmed_nonces_at_target = 5; + strategy.max_messages_in_single_batch = 5; + strategy.max_messages_weight_in_single_batch = Weight::from_parts(5, 0); + strategy.max_messages_size_in_single_batch = 5; + + // in this state we have 4 available nonces for delivery + assert_eq!( + strategy.select_nonces_to_deliver(state.clone()).await, + Some(( + 20..=23, + MessageProofParameters { + outbound_state_proof_required: false, + dispatch_weight: Weight::from_parts(4, 0), + } + )), + ); + + // let's say we have submitted 20..=23 + state.nonces_submitted = Some(20..=23); + + // then new nonce 24 appear at the source block 2 + let new_nonce_24 = vec![( + 24, + MessageDetails { dispatch_weight: Weight::from_parts(1, 0), size: 0, reward: 0 }, + )] + .into_iter() + .collect(); + let source_header_2 = header_id(2); + state.best_finalized_source_header_id_at_source = Some(source_header_2); + strategy.source_nonces_updated( + source_header_2, + SourceClientNonces { new_nonces: new_nonce_24, confirmed_nonce: None }, + ); + // and nonce 23 appear at the best block of the target node (best finalized still has 0 + // nonces) + let target_nonces_data = DeliveryRaceTargetNoncesData { + confirmed_nonce: 19, + unrewarded_relayers: UnrewardedRelayersState::default(), + }; + let target_header_2 = header_id(2); + state.best_target_header_id = Some(target_header_2); + strategy.best_target_nonces_updated( + TargetClientNonces { latest_nonce: 23, nonces_data: target_nonces_data.clone() }, + &mut state, + ); + + // then best target header is retracted + strategy.best_target_nonces_updated( + TargetClientNonces { latest_nonce: 19, nonces_data: target_nonces_data.clone() }, + &mut state, + ); + + // ... and some fork with 19 delivered nonces is finalized + let target_header_2_fork = header_id(2_1); + state.best_finalized_source_header_id_at_source = Some(source_header_2); + state.best_finalized_source_header_id_at_best_target = Some(source_header_2); + state.best_target_header_id = Some(target_header_2_fork); + state.best_finalized_target_header_id = Some(target_header_2_fork); + strategy.finalized_target_nonces_updated( + TargetClientNonces { latest_nonce: 19, nonces_data: target_nonces_data.clone() }, + &mut state, + ); + + // now we have to select nonces 20..=23 for delivery again + assert_eq!( + strategy.select_nonces_to_deliver(state.clone()).await, + Some(( + 20..=24, + MessageProofParameters { + outbound_state_proof_required: false, + dispatch_weight: Weight::from_parts(5, 0), + } + )), + ); + } } diff --git a/relays/messages/src/message_race_limits.rs b/relays/messages/src/message_race_limits.rs index a28d9ba63da96..873bb6aad0425 100644 --- a/relays/messages/src/message_race_limits.rs +++ b/relays/messages/src/message_race_limits.rs @@ -17,7 +17,7 @@ //! enforcement strategy use num_traits::Zero; -use std::ops::Range; +use std::ops::RangeInclusive; use bp_messages::{MessageNonce, Weight}; @@ -76,14 +76,17 @@ pub struct RelayMessagesBatchReference< pub lane_target_client: TargetClient, /// Metrics reference. pub metrics: Option, + /// Best available nonce at the **best** target block. We do not want to deliver nonces + /// less than this nonce, even though the block may be retracted. + pub best_target_nonce: MessageNonce, /// Source queue. pub nonces_queue: SourceRangesQueue< P::SourceHeaderHash, P::SourceHeaderNumber, MessageDetailsMap, >, - /// Source queue range - pub nonces_queue_range: Range, + /// Range of indices within the `nonces_queue` that are available for selection. + pub nonces_queue_range: RangeInclusive, } /// Limits of the message race transactions. @@ -97,14 +100,16 @@ impl MessageRaceLimits { TargetClient: MessageLaneTargetClient

, >( reference: RelayMessagesBatchReference, - ) -> Option { + ) -> Option> { let mut hard_selected_count = 0; let mut selected_weight = Weight::zero(); let mut selected_count: MessageNonce = 0; - let hard_selected_begin_nonce = - reference.nonces_queue[reference.nonces_queue_range.start].1.begin(); + let hard_selected_begin_nonce = std::cmp::max( + reference.best_target_nonce + 1, + reference.nonces_queue[*reference.nonces_queue_range.start()].1.begin(), + ); // relay reference let mut relay_reference = RelayReference { @@ -129,6 +134,7 @@ impl MessageRaceLimits { .nonces_queue .range(reference.nonces_queue_range.clone()) .flat_map(|(_, ready_nonces)| ready_nonces.iter()) + .filter(|(nonce, _)| **nonce >= hard_selected_begin_nonce) .enumerate(); for (index, (nonce, details)) in all_ready_nonces { relay_reference.index = index; @@ -192,7 +198,7 @@ impl MessageRaceLimits { if hard_selected_count != 0 { let selected_max_nonce = hard_selected_begin_nonce + hard_selected_count as MessageNonce - 1; - Some(selected_max_nonce) + Some(hard_selected_begin_nonce..=selected_max_nonce) } else { None } diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 9a53a487d94f8..479ffe5132907 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -41,8 +41,11 @@ pub struct BasicStrategy< Proof, > { /// All queued nonces. + /// + /// The queue may contain already delivered nonces. We only remove entries from this + /// queue after corresponding nonces are finalized by the target chain. source_queue: SourceRangesQueue, - /// The best nonce known to target node (at its best block). `None` if it has not been received + /// The best nonce known to target node at its best block. `None` if it has not been received /// yet. best_target_nonce: Option, /// Unused generic types dump. @@ -93,21 +96,26 @@ impl< &mut self.source_queue } - /// Returns index of the latest source queue entry, that may be delivered to the target node. + /// Returns indices of source queue entries, which may be delivered to the target node. + /// + /// The function may skip some nonces from the queue front if nonces from this entry are + /// already available at the **best** target block. After this block is finalized, the entry + /// will be removed from the queue. /// - /// Returns `None` if no entries may be delivered. All entries before and including the - /// `Some(_)` index are guaranteed to be witnessed at source blocks that are known to be - /// finalized at the target node. - pub fn maximal_available_source_queue_index( + /// All entries before and including the range end index, are guaranteed to be witnessed + /// at source blocks that are known to be finalized at the target node. + /// + /// Returns `None` if no entries may be delivered. + pub fn available_source_queue_indices( &self, race_state: RaceState< HeaderId, HeaderId, Proof, >, - ) -> Option { + ) -> Option> { // if we do not know best nonce at target node, we can't select anything - let _ = self.best_target_nonce?; + let best_target_nonce = self.best_target_nonce?; // if we have already selected nonces that we want to submit, do nothing if race_state.nonces_to_submit.is_some() { @@ -119,6 +127,15 @@ impl< return None } + // find first entry that may be delivered to the target node + let begin_index = self + .source_queue + .iter() + .enumerate() + .skip_while(|(_, (_, nonces))| nonces.end() <= best_target_nonce) + .map(|(index, _)| index) + .next()?; + // 1) we want to deliver all nonces, starting from `target_nonce + 1` // 2) we can't deliver new nonce until header, that has emitted this nonce, is finalized // by target client @@ -127,12 +144,16 @@ impl< // => let's first select range of entries inside deque that are already finalized at // the target client and pass this range to the selector let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target?; - self.source_queue + let end_index = self + .source_queue .iter() .enumerate() + .skip(begin_index) .take_while(|(_, (queued_at, _))| queued_at.0 <= best_header_at_target.0) .map(|(index, _)| index) - .last() + .last()?; + + Some(begin_index..=end_index) } /// Remove all nonces that are less than or equal to given nonce from the source queue. @@ -237,22 +258,6 @@ impl< ) { let nonce = nonces.latest_nonce; - if let Some(best_target_nonce) = self.best_target_nonce { - if nonce < best_target_nonce { - return - } - } - - while let Some(true) = self.source_queue.front().map(|(_, range)| range.begin() <= nonce) { - let maybe_subrange = self.source_queue.pop_front().and_then(|(at_block, range)| { - range.greater_than(nonce).map(|subrange| (at_block, subrange)) - }); - if let Some((at_block, subrange)) = maybe_subrange { - self.source_queue.push_front((at_block, subrange)); - break - } - } - let need_to_select_new_nonces = race_state .nonces_to_submit .as_ref() @@ -271,8 +276,7 @@ impl< race_state.nonces_submitted = None; } - self.best_target_nonce = - Some(std::cmp::max(self.best_target_nonce.unwrap_or(nonces.latest_nonce), nonce)); + self.best_target_nonce = Some(nonce); } fn finalized_target_nonces_updated( @@ -284,7 +288,7 @@ impl< Proof, >, ) { - self.remove_le_nonces_from_source_queue(nonces.latest_nonce); // TODO: does it means that we'll try to submit old nonces in next tx??? + self.remove_le_nonces_from_source_queue(nonces.latest_nonce); self.best_target_nonce = Some(std::cmp::max( self.best_target_nonce.unwrap_or(nonces.latest_nonce), nonces.latest_nonce, @@ -299,9 +303,12 @@ impl< Proof, >, ) -> Option<(RangeInclusive, Self::ProofParameters)> { - let maximal_source_queue_index = self.maximal_available_source_queue_index(race_state)?; - let range_begin = self.source_queue[0].1.begin(); - let range_end = self.source_queue[maximal_source_queue_index].1.end(); + let available_indices = self.available_source_queue_indices(race_state)?; + let range_begin = std::cmp::max( + self.best_target_nonce? + 1, + self.source_queue[*available_indices.start()].1.begin(), + ); + let range_end = self.source_queue[*available_indices.end()].1.end(); Some((range_begin..=range_end, ())) } } @@ -351,7 +358,7 @@ mod tests { strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); assert_eq!(strategy.best_at_source(), None); strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); - assert_eq!(strategy.source_queue, vec![]); + assert_eq!(strategy.source_queue, vec![(header_id(1), 1..=5)]); assert_eq!(strategy.best_at_source(), Some(10)); } @@ -372,16 +379,6 @@ mod tests { assert_eq!(strategy.source_queue, vec![(header_id(1), 1..=5)]); } - #[test] - fn target_nonce_is_never_lower_than_latest_known_target_nonce() { - let mut strategy = BasicStrategy::::new(); - assert_eq!(strategy.best_target_nonce, None); - strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); - assert_eq!(strategy.best_target_nonce, Some(10)); - strategy.best_target_nonces_updated(target_nonces(5), &mut Default::default()); - assert_eq!(strategy.best_target_nonce, Some(10)); - } - #[test] fn updated_target_nonce_removes_queued_entries() { let mut strategy = BasicStrategy::::new(); @@ -389,9 +386,9 @@ mod tests { strategy.source_nonces_updated(header_id(2), source_nonces(6..=10)); strategy.source_nonces_updated(header_id(3), source_nonces(11..=15)); strategy.source_nonces_updated(header_id(4), source_nonces(16..=20)); - strategy.best_target_nonces_updated(target_nonces(15), &mut Default::default()); + strategy.finalized_target_nonces_updated(target_nonces(15), &mut Default::default()); assert_eq!(strategy.source_queue, vec![(header_id(4), 16..=20)]); - strategy.best_target_nonces_updated(target_nonces(17), &mut Default::default()); + strategy.finalized_target_nonces_updated(target_nonces(17), &mut Default::default()); assert_eq!(strategy.source_queue, vec![(header_id(4), 18..=20)]); } @@ -459,7 +456,7 @@ mod tests { } #[test] - fn maximal_available_source_queue_index_works() { + fn available_source_queue_indices_works() { let mut state = RaceState::<_, _, TestMessagesProof>::default(); let mut strategy = BasicStrategy::::new(); strategy.best_target_nonces_updated(target_nonces(0), &mut state); @@ -468,19 +465,19 @@ mod tests { strategy.source_nonces_updated(header_id(3), source_nonces(7..=9)); state.best_finalized_source_header_id_at_best_target = Some(header_id(0)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), None); + assert_eq!(strategy.available_source_queue_indices(state.clone()), None); state.best_finalized_source_header_id_at_best_target = Some(header_id(1)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(0)); + assert_eq!(strategy.available_source_queue_indices(state.clone()), Some(0..=0)); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(1)); + assert_eq!(strategy.available_source_queue_indices(state.clone()), Some(0..=1)); state.best_finalized_source_header_id_at_best_target = Some(header_id(3)); - assert_eq!(strategy.maximal_available_source_queue_index(state.clone()), Some(2)); + assert_eq!(strategy.available_source_queue_indices(state.clone()), Some(0..=2)); state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); - assert_eq!(strategy.maximal_available_source_queue_index(state), Some(2)); + assert_eq!(strategy.available_source_queue_indices(state), Some(0..=2)); } #[test] @@ -514,4 +511,67 @@ mod tests { strategy.remove_le_nonces_from_source_queue(100); assert_eq!(source_queue_nonces(&strategy.source_queue), Vec::::new(),); } + + #[async_std::test] + async fn previous_nonces_are_selected_if_reorg_happens_at_target_chain() { + let source_header_1 = header_id(1); + let target_header_1 = header_id(1); + + // we start in perfec sync state - all headers are synced and finalized on both ends + let mut state = RaceState::<_, _, TestMessagesProof> { + best_finalized_source_header_id_at_source: Some(source_header_1), + best_finalized_source_header_id_at_best_target: Some(source_header_1), + best_target_header_id: Some(target_header_1), + best_finalized_target_header_id: Some(target_header_1), + nonces_to_submit: None, + nonces_submitted: None, + }; + + // in this state we have 1 available nonce for delivery + let mut strategy = BasicStrategy:: { + source_queue: vec![(header_id(1), 1..=1)].into_iter().collect(), + best_target_nonce: Some(0), + _phantom: PhantomData, + }; + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((1..=1, ())),); + + // let's say we have submitted 1..=1 + state.nonces_submitted = Some(1..=1); + + // then new nonce 2 appear at the source block 2 + let source_header_2 = header_id(2); + state.best_finalized_source_header_id_at_source = Some(source_header_2); + strategy.source_nonces_updated( + source_header_2, + SourceClientNonces { new_nonces: 2..=2, confirmed_nonce: None }, + ); + // and nonce 1 appear at the best block of the target node (best finalized still has 0 + // nonces) + let target_header_2 = header_id(2); + state.best_target_header_id = Some(target_header_2); + strategy.best_target_nonces_updated( + TargetClientNonces { latest_nonce: 1, nonces_data: () }, + &mut state, + ); + + // then best target header is retracted + strategy.best_target_nonces_updated( + TargetClientNonces { latest_nonce: 0, nonces_data: () }, + &mut state, + ); + + // ... and some fork with zero delivered nonces is finalized + let target_header_2_fork = header_id(2_1); + state.best_finalized_source_header_id_at_source = Some(source_header_2); + state.best_finalized_source_header_id_at_best_target = Some(source_header_2); + state.best_target_header_id = Some(target_header_2_fork); + state.best_finalized_target_header_id = Some(target_header_2_fork); + strategy.finalized_target_nonces_updated( + TargetClientNonces { latest_nonce: 0, nonces_data: () }, + &mut state, + ); + + // now we have to select nonce 1 for delivery again + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, Some((1..=2, ())),); + } } From 5ece831c7fbb34f31fc9f58714f069d78d3229e9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 7 Mar 2023 17:37:20 +0300 Subject: [PATCH 0979/1210] Actually clone client data by reference when cloning the client (#1941) * actually clone client data by reference when clonning the client * spelling * clippy --- relays/client-substrate/src/client.rs | 56 +++++++++++++++------------ 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 80db593acbfa4..6a381c4e97717 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -26,7 +26,7 @@ use crate::{ Result, SignParam, TransactionTracker, UnsignedTransaction, }; -use async_std::sync::{Arc, Mutex}; +use async_std::sync::{Arc, Mutex, RwLock}; use async_trait::async_trait; use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider, StorageMapKeyProvider}; use codec::{Decode, Encode}; @@ -111,23 +111,31 @@ pub enum ChainRuntimeVersion { /// Substrate client type. /// -/// Cloning `Client` is a cheap operation. +/// Cloning `Client` is a cheap operation that only clones internal references. Different +/// clones of the same client are guaranteed to use the same references. pub struct Client { - /// Tokio runtime handle. - tokio: Arc, + // Lock order: `submit_signed_extrinsic_lock`, `data` /// Client connection params. params: Arc, - /// Substrate RPC client. - client: Arc, - /// Genesis block hash. - genesis_hash: HashOf, + /// Saved chain runtime version. + chain_runtime_version: ChainRuntimeVersion, /// If several tasks are submitting their transactions simultaneously using /// `submit_signed_extrinsic` method, they may get the same transaction nonce. So one of /// transactions will be rejected from the pool. This lock is here to prevent situations like /// that. submit_signed_extrinsic_lock: Arc>, - /// Saved chain runtime version - chain_runtime_version: ChainRuntimeVersion, + /// Genesis block hash. + genesis_hash: HashOf, + /// Shared dynamic data. + data: Arc>, +} + +/// Client data, shared by all `Client` clones. +struct ClientData { + /// Tokio runtime handle. + tokio: Arc, + /// Substrate RPC client. + client: Arc, } #[async_trait] @@ -135,9 +143,10 @@ impl relay_utils::relay_loop::Client for Client { type Error = Error; async fn reconnect(&mut self) -> Result<()> { + let mut data = self.data.write().await; let (tokio, client) = Self::build_client(&self.params).await?; - self.tokio = tokio; - self.client = client; + data.tokio = tokio; + data.client = client; Ok(()) } } @@ -145,12 +154,11 @@ impl relay_utils::relay_loop::Client for Client { impl Clone for Client { fn clone(&self) -> Self { Client { - tokio: self.tokio.clone(), params: self.params.clone(), - client: self.client.clone(), - genesis_hash: self.genesis_hash, - submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(), chain_runtime_version: self.chain_runtime_version.clone(), + submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(), + genesis_hash: self.genesis_hash, + data: self.data.clone(), } } } @@ -199,12 +207,11 @@ impl Client { let chain_runtime_version = params.chain_runtime_version.clone(); Ok(Self { - tokio, params, - client, - genesis_hash, - submit_signed_extrinsic_lock: Arc::new(Mutex::new(())), chain_runtime_version, + submit_signed_extrinsic_lock: Arc::new(Mutex::new(())), + genesis_hash, + data: Arc::new(RwLock::new(ClientData { tokio, client })), }) } @@ -572,7 +579,7 @@ impl Client { Ok((tracker, subscription)) }) .await?; - self.tokio.spawn(Subscription::background_worker( + self.data.read().await.tokio.spawn(Subscription::background_worker( C::NAME.into(), "extrinsic".into(), subscription, @@ -719,7 +726,7 @@ impl Client { }) .await?; let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); - self.tokio.spawn(Subscription::background_worker( + self.data.read().await.tokio.spawn(Subscription::background_worker( C::NAME.into(), "justification".into(), subscription, @@ -735,8 +742,9 @@ impl Client { F: Future> + Send, T: Send + 'static, { - let client = self.client.clone(); - self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? + let data = self.data.read().await; + let client = data.client.clone(); + data.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? } /// Returns `true` if version guard can be started. From b66ffe677d9260900f4b595030fca47e94174a6c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 8 Mar 2023 15:12:14 +0300 Subject: [PATCH 0980/1210] optimize justifications before they're included into complex transaction (#1949) --- relays/lib-substrate-relay/src/on_demand/headers.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 090019f087f6c..aded79a857af2 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -138,6 +138,9 @@ impl OnDemandRelay Date: Thu, 9 Mar 2023 12:56:07 +0200 Subject: [PATCH 0981/1210] Some error improvements (#1956) * Use `HeaderChainError` in parachains module * Use MessageProofError instead of 'static str in some places * Avoid implementing Into<'static str> for some errors We avoid deriving `Debug` for the structs that we use in the runtime and we derive `RuntimeDebug` instead in order to avoid bloating th eruntime with static strs. But implementing `Into<'static str>` does the same. So in some places it makes sense to replace `Into<'static str>` with `Debug`. * Move the messages error definition Move the messages error definition outside of `mod target` --- bin/runtime-common/src/messages.rs | 170 +++++++++++------------- modules/parachains/src/lib.rs | 14 +- primitives/header-chain/src/lib.rs | 12 +- primitives/messages/src/source_chain.rs | 2 +- primitives/messages/src/target_chain.rs | 2 +- primitives/runtime/src/lib.rs | 31 +++++ primitives/runtime/src/storage_proof.rs | 46 ++++--- 7 files changed, 145 insertions(+), 132 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index ceedee12afabf..4eb44ea85ed45 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -100,6 +100,29 @@ pub type OriginOf = ::RuntimeOrigin; /// Type of call that is used on this chain. pub type CallOf = ::RuntimeCall; +/// Error that happens during message verification. +#[derive(Debug, PartialEq, Eq)] +pub enum Error { + /// The message proof is empty. + EmptyMessageProof, + /// Error returned by the bridged header chain. + HeaderChain(HeaderChainError), + /// Error returned while reading/decoding inbound lane data from the storage proof. + InboundLaneStorage(StorageProofError), + /// The declared message weight is incorrect. + InvalidMessageWeight, + /// Declared messages count doesn't match actual value. + MessagesCountMismatch, + /// Error returned while reading/decoding message data from the storage proof. + MessageStorage(StorageProofError), + /// The message is too large. + MessageTooLarge, + /// Error returned while reading/decoding outbound lane data from the storage proof. + OutboundLaneStorage(StorageProofError), + /// Storage proof related error. + StorageProof(StorageProofError), +} + /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -169,8 +192,6 @@ pub mod source { /// The error message returned from `LaneMessageVerifier` when too many pending messages at the /// lane. pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; - /// The error message returned from `LaneMessageVerifier` when call origin is mismatch. - pub const BAD_ORIGIN: &str = "Unable to match the source origin to expected target origin."; impl LaneMessageVerifier>, FromThisChainMessagePayload> for FromThisChainMessageVerifier @@ -220,7 +241,7 @@ pub mod source { impl TargetHeaderChain>> for TargetHeaderChainAdapter { - type Error = &'static str; + type Error = Error; type MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof>>; fn verify_message(payload: &FromThisChainMessagePayload) -> Result<(), Self::Error> { @@ -241,9 +262,9 @@ pub mod source { /// check) that would reject message (see `FromThisChainMessageVerifier`). pub fn verify_chain_message( payload: &FromThisChainMessagePayload, - ) -> Result<(), &'static str> { + ) -> Result<(), Error> { if !BridgedChain::::verify_dispatch_weight(payload) { - return Err("Incorrect message weight declared") + return Err(Error::InvalidMessageWeight) } // The maximal size of extrinsic at Substrate-based chain depends on the @@ -257,7 +278,7 @@ pub mod source { // transaction also contains signatures and signed extensions. Because of this, we reserve // 1/3 of the the maximal extrinsic weight for this data. if payload.len() > maximal_message_size::() as usize { - return Err("The message is too large to be sent over the lane") + return Err(Error::MessageTooLarge) } Ok(()) @@ -269,7 +290,7 @@ pub mod source { /// parachains, please use the `verify_messages_delivery_proof_from_parachain`. pub fn verify_messages_delivery_proof( proof: FromBridgedChainMessagesDeliveryProof>>, - ) -> Result, &'static str> { + ) -> Result, Error> { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = proof; B::BridgedHeaderChain::parse_finalized_storage_proof( @@ -283,22 +304,17 @@ pub mod source { B::BRIDGED_MESSAGES_PALLET_NAME, &lane, ); - let raw_inbound_lane_data = storage - .read_value(storage_inbound_lane_data_key.0.as_ref()) - .map_err(|_| "Failed to read inbound lane state from storage proof")? - .ok_or("Inbound lane state is missing from the messages proof")?; - let inbound_lane_data = InboundLaneData::decode(&mut &raw_inbound_lane_data[..]) - .map_err(|_| "Failed to decode inbound lane state from the proof")?; + let inbound_lane_data = storage + .read_and_decode_mandatory_value(storage_inbound_lane_data_key.0.as_ref()) + .map_err(Error::InboundLaneStorage)?; // check that the storage proof doesn't have any untouched trie nodes - storage - .ensure_no_unused_nodes() - .map_err(|_| "Messages delivery proof has unused trie nodes")?; + storage.ensure_no_unused_nodes().map_err(Error::StorageProof)?; Ok((lane, inbound_lane_data)) }, ) - .map_err(<&'static str>::from)? + .map_err(Error::HeaderChain)? } /// XCM bridge. @@ -580,14 +596,14 @@ pub mod target { pub struct SourceHeaderChainAdapter(PhantomData); impl SourceHeaderChain for SourceHeaderChainAdapter { - type Error = &'static str; + type Error = Error; type MessagesProof = FromBridgedChainMessagesProof>>; fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, ) -> Result, Self::Error> { - verify_messages_proof::(proof, messages_count).map_err(Into::into) + verify_messages_proof::(proof, messages_count) } } @@ -602,7 +618,7 @@ pub mod target { pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof>>, messages_count: u32, - ) -> Result, MessageProofError> { + ) -> Result, Error> { let FromBridgedChainMessagesProof { bridged_header_hash, storage_proof, @@ -625,7 +641,7 @@ pub mod target { // (this bounds maximal capacity of messages vec below) let messages_in_the_proof = nonces_difference.saturating_add(1); if messages_in_the_proof != MessageNonce::from(messages_count) { - return Err(MessageProofError::MessagesCountMismatch) + return Err(Error::MessagesCountMismatch) } messages_in_the_proof @@ -640,37 +656,26 @@ pub mod target { let mut messages = Vec::with_capacity(messages_in_the_proof as _); for nonce in nonces_start..=nonces_end { let message_key = MessageKey { lane_id: lane, nonce }; - let raw_message_data = parser - .read_raw_message(&message_key) - .ok_or(MessageProofError::MissingRequiredMessage)?; - let payload = MessagePayload::decode(&mut &raw_message_data[..]) - .map_err(|_| MessageProofError::FailedToDecodeMessage)?; - messages.push(Message { key: message_key, payload }); + let message_payload = parser.read_and_decode_message_payload(&message_key)?; + messages.push(Message { key: message_key, payload: message_payload }); } // Now let's check if proof contains outbound lane state proof. It is optional, so // we simply ignore `read_value` errors and missing value. - let mut proved_lane_messages = ProvedLaneMessages { lane_state: None, messages }; - let raw_outbound_lane_data = parser.read_raw_outbound_lane_data(&lane); - if let Some(raw_outbound_lane_data) = raw_outbound_lane_data { - proved_lane_messages.lane_state = Some( - OutboundLaneData::decode(&mut &raw_outbound_lane_data[..]) - .map_err(|_| MessageProofError::FailedToDecodeOutboundLaneState)?, - ); - } + let proved_lane_messages = ProvedLaneMessages { + lane_state: parser.read_and_decode_outbound_lane_data(&lane)?, + messages, + }; // Now we may actually check if the proof is empty or not. if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { - return Err(MessageProofError::Empty) + return Err(Error::EmptyMessageProof) } // check that the storage proof doesn't have any untouched trie nodes - parser - .storage - .ensure_no_unused_nodes() - .map_err(MessageProofError::StorageProof)?; + parser.storage.ensure_no_unused_nodes().map_err(Error::StorageProof)?; // We only support single lane messages in this generated_schema let mut proved_messages = ProvedMessages::new(); @@ -679,43 +684,7 @@ pub mod target { Ok(proved_messages) }, ) - .map_err(MessageProofError::HeaderChain)? - } - - /// Error that happens during message proof verification. - #[derive(Debug, PartialEq, Eq)] - pub enum MessageProofError { - /// Error returned by the bridged header chain. - HeaderChain(HeaderChainError), - /// The message proof is empty. - Empty, - /// Declared messages count doesn't match actual value. - MessagesCountMismatch, - /// Message is missing from the proof. - MissingRequiredMessage, - /// Failed to decode message from the proof. - FailedToDecodeMessage, - /// Failed to decode outbound lane data from the proof. - FailedToDecodeOutboundLaneState, - /// Storage proof related error. - StorageProof(StorageProofError), - } - - impl From for &'static str { - fn from(err: MessageProofError) -> &'static str { - match err { - MessageProofError::HeaderChain(err) => err.into(), - MessageProofError::Empty => "Messages proof is empty", - MessageProofError::MessagesCountMismatch => - "Declared messages count doesn't match actual value", - MessageProofError::MissingRequiredMessage => "Message is missing from the proof", - MessageProofError::FailedToDecodeMessage => - "Failed to decode message from the proof", - MessageProofError::FailedToDecodeOutboundLaneState => - "Failed to decode outbound lane data from the proof", - MessageProofError::StorageProof(_) => "Invalid storage proof", - } - } + .map_err(Error::HeaderChain)? } struct StorageProofCheckerAdapter { @@ -724,21 +693,32 @@ pub mod target { } impl StorageProofCheckerAdapter { - fn read_raw_outbound_lane_data(&mut self, lane_id: &LaneId) -> Option> { + fn read_and_decode_outbound_lane_data( + &mut self, + lane_id: &LaneId, + ) -> Result, Error> { let storage_outbound_lane_data_key = bp_messages::storage_keys::outbound_lane_data_key( B::BRIDGED_MESSAGES_PALLET_NAME, lane_id, ); - self.storage.read_value(storage_outbound_lane_data_key.0.as_ref()).ok()? + + self.storage + .read_and_decode_opt_value(storage_outbound_lane_data_key.0.as_ref()) + .map_err(Error::OutboundLaneStorage) } - fn read_raw_message(&mut self, message_key: &MessageKey) -> Option> { + fn read_and_decode_message_payload( + &mut self, + message_key: &MessageKey, + ) -> Result { let storage_message_key = bp_messages::storage_keys::message_key( B::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, message_key.nonce, ); - self.storage.read_value(storage_message_key.0.as_ref()).ok()? + self.storage + .read_and_decode_mandatory_value(storage_message_key.0.as_ref()) + .map_err(Error::MessageStorage) } } } @@ -896,7 +876,7 @@ mod tests { using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { target::verify_messages_proof::(proof, 5) }), - Err(target::MessageProofError::MessagesCountMismatch), + Err(Error::MessagesCountMismatch), ); } @@ -906,7 +886,7 @@ mod tests { using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { target::verify_messages_proof::(proof, 15) }), - Err(target::MessageProofError::MessagesCountMismatch), + Err(Error::MessagesCountMismatch), ); } @@ -919,7 +899,7 @@ mod tests { pallet_bridge_grandpa::ImportedHeaders::::remove(bridged_header_hash); target::verify_messages_proof::(proof, 10) }), - Err(target::MessageProofError::HeaderChain(HeaderChainError::UnknownHeader)), + Err(Error::HeaderChain(HeaderChainError::UnknownHeader)), ); } @@ -942,7 +922,7 @@ mod tests { ); target::verify_messages_proof::(proof, 10) }), - Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageProof( + Err(Error::HeaderChain(HeaderChainError::StorageProof( StorageProofError::StorageRootMismatch ))), ); @@ -957,7 +937,7 @@ mod tests { proof.storage_proof.push(node); target::verify_messages_proof::(proof, 10) },), - Err(target::MessageProofError::HeaderChain(HeaderChainError::StorageProof( + Err(Error::HeaderChain(HeaderChainError::StorageProof( StorageProofError::DuplicateNodesInProof ))), ); @@ -970,13 +950,13 @@ mod tests { proof.storage_proof.push(vec![42]); target::verify_messages_proof::(proof, 10) },), - Err(target::MessageProofError::StorageProof(StorageProofError::UnusedNodesInTheProof)), + Err(Error::StorageProof(StorageProofError::UnusedNodesInTheProof)), ); } #[test] fn message_proof_is_rejected_if_required_message_is_missing() { - assert_eq!( + matches!( using_messages_proof( 10, None, @@ -984,13 +964,13 @@ mod tests { encode_lane_data, |proof| target::verify_messages_proof::(proof, 10) ), - Err(target::MessageProofError::MissingRequiredMessage), + Err(Error::MessageStorage(StorageProofError::StorageValueEmpty)), ); } #[test] fn message_proof_is_rejected_if_message_decode_fails() { - assert_eq!( + matches!( using_messages_proof( 10, None, @@ -1004,13 +984,13 @@ mod tests { encode_lane_data, |proof| target::verify_messages_proof::(proof, 10), ), - Err(target::MessageProofError::FailedToDecodeMessage), + Err(Error::MessageStorage(StorageProofError::StorageValueDecodeFailed(_))), ); } #[test] fn message_proof_is_rejected_if_outbound_lane_state_decode_fails() { - assert_eq!( + matches!( using_messages_proof( 10, Some(OutboundLaneData { @@ -1026,7 +1006,7 @@ mod tests { }, |proof| target::verify_messages_proof::(proof, 10), ), - Err(target::MessageProofError::FailedToDecodeOutboundLaneState), + Err(Error::OutboundLaneStorage(StorageProofError::StorageValueDecodeFailed(_))), ); } @@ -1036,7 +1016,7 @@ mod tests { using_messages_proof(0, None, encode_all_messages, encode_lane_data, |proof| { target::verify_messages_proof::(proof, 0) },), - Err(target::MessageProofError::Empty), + Err(Error::EmptyMessageProof), ); } @@ -1110,7 +1090,7 @@ mod tests { proof.nonces_end = u64::MAX; target::verify_messages_proof::(proof, u32::MAX) },), - Err(target::MessageProofError::MessagesCountMismatch), + Err(Error::MessagesCountMismatch), ); } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index b9bbaac7ca3d4..98556f737bac3 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -26,7 +26,7 @@ pub use weights::WeightInfo; pub use weights_ext::WeightInfoExt; -use bp_header_chain::HeaderChain; +use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo, ParaStoredHeaderData}; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain, StorageProofError}; @@ -125,8 +125,8 @@ pub mod pallet { UnknownRelayChainBlock, /// The number of stored relay block is different from what the relayer has provided. InvalidRelayChainBlockNumber, - /// Invalid storage proof has been passed. - InvalidStorageProof, + /// Error generated by a method defined in `bp-header-chain`. + HeaderChain(HeaderChainError), /// Given parachain head is unknown. UnknownParaHead, /// The storage proof doesn't contains storage root. So it is invalid for given header. @@ -430,10 +430,10 @@ pub mod pallet { storage.ensure_no_unused_nodes() }, ) - .and_then(|r| r.map_err(bp_header_chain::HeaderChainError::StorageProof)) + .and_then(|r| r.map_err(HeaderChainError::StorageProof)) .map_err(|e| { log::trace!(target: LOG_TARGET, "Parachain heads storage proof is invalid: {:?}", e); - Error::::InvalidStorageProof + Error::::HeaderChain(e) })?; Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) @@ -1379,7 +1379,9 @@ mod tests { // try to import head#5 of parachain#1 at relay chain block #0 assert_noop!( import_parachain_1_head(0, Default::default(), parachains, proof), - Error::::InvalidStorageProof + Error::::HeaderChain(HeaderChainError::StorageProof( + StorageProofError::StorageRootMismatch + )) ); }); } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index cafb8e7a3c86f..5d05a1b15d8fa 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -25,6 +25,7 @@ use bp_runtime::{ }; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; +use frame_support::PalletError; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -36,7 +37,7 @@ pub mod justification; pub mod storage_keys; /// Header chain error. -#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +#[derive(Clone, Decode, Encode, Eq, PartialEq, PalletError, Debug, TypeInfo)] pub enum HeaderChainError { /// Header with given hash is missing from the chain. UnknownHeader, @@ -44,15 +45,6 @@ pub enum HeaderChainError { StorageProof(StorageProofError), } -impl From for &'static str { - fn from(err: HeaderChainError) -> &'static str { - match err { - HeaderChainError::UnknownHeader => "UnknownHeader", - HeaderChainError::StorageProof(e) => e.into(), - } - } -} - /// Header data that we're storing on-chain. /// /// Even though we may store full header, our applications (XCM) only use couple of header diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index d5d7549099c31..881bd92f5f955 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -41,7 +41,7 @@ pub type RelayersRewards = BTreeMap; /// type used by the source chain. pub trait TargetHeaderChain { /// Error type. - type Error: Debug + Into<&'static str>; + type Error: Debug; /// Proof that messages have been received by target chain. type MessagesDeliveryProof: Parameter + Size; diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 6604d425cfc4a..8496b90214c40 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -59,7 +59,7 @@ pub struct DispatchMessage { /// that's stuck) and/or processing messages without paying fees. pub trait SourceHeaderChain { /// Error type. - type Error: Debug + Into<&'static str>; + type Error: Debug; /// Proof that messages are sent from source chain. This may also include proof /// of corresponding outbound lane states. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 2d29b5aff0ab9..ece925d795273 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -531,6 +531,37 @@ macro_rules! generate_static_str_provider { }; } +#[derive(Encode, Decode, Clone, Eq, PartialEq, PalletError, TypeInfo)] +#[scale_info(skip_type_params(T))] +pub struct StrippableError { + _phantom_data: sp_std::marker::PhantomData, + #[codec(skip)] + #[cfg(feature = "std")] + message: String, +} + +impl From for StrippableError { + fn from(err: T) -> Self { + Self { + _phantom_data: Default::default(), + #[cfg(feature = "std")] + message: format!("{:?}", err), + } + } +} + +impl Debug for StrippableError { + #[cfg(feature = "std")] + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + f.write_str(&self.message) + } + + #[cfg(not(feature = "std"))] + fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result { + f.write_str("Stripped error") + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index aa9c3088fa42f..09641376666af 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -16,9 +16,11 @@ //! Logic for checking Substrate storage proofs. -use codec::Decode; +use crate::StrippableError; +use codec::{Decode, Encode}; +use frame_support::PalletError; use hash_db::{HashDB, Hasher, EMPTY_PREFIX}; -use sp_runtime::RuntimeDebug; +use scale_info::TypeInfo; use sp_std::{boxed::Box, collections::btree_set::BTreeSet, vec::Vec}; use sp_trie::{ read_trie_value, LayoutV1, MemoryDB, Recorder, StorageProof, Trie, TrieConfiguration, @@ -116,14 +118,32 @@ where /// read, but decoding fails, this function returns an error. pub fn read_and_decode_value(&mut self, key: &[u8]) -> Result, Error> { self.read_value(key).and_then(|v| { - v.map(|v| T::decode(&mut &v[..]).map_err(Error::StorageValueDecodeFailed)) + v.map(|v| T::decode(&mut &v[..]).map_err(|e| Error::StorageValueDecodeFailed(e.into()))) .transpose() }) } + + /// Reads and decodes a value from the available subset of storage. If the value cannot be read + /// due to an incomplete or otherwise invalid proof, or if the value is `None`, this function + /// returns an error. If value is read, but decoding fails, this function returns an error. + pub fn read_and_decode_mandatory_value(&mut self, key: &[u8]) -> Result { + self.read_and_decode_value(key)?.ok_or(Error::StorageValueEmpty) + } + + /// Reads and decodes a value from the available subset of storage. If the value cannot be read + /// due to an incomplete or otherwise invalid proof, this function returns `Ok(None)`. + /// If value is read, but decoding fails, this function returns an error. + pub fn read_and_decode_opt_value(&mut self, key: &[u8]) -> Result, Error> { + match self.read_and_decode_value(key) { + Ok(outbound_lane_data) => Ok(outbound_lane_data), + Err(Error::StorageValueUnavailable) => Ok(None), + Err(e) => Err(e), + } + } } /// Storage proof related errors. -#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +#[derive(Encode, Decode, Clone, Eq, PartialEq, PalletError, Debug, TypeInfo)] pub enum Error { /// Duplicate trie nodes are found in the proof. DuplicateNodesInProof, @@ -133,21 +153,10 @@ pub enum Error { StorageRootMismatch, /// Unable to reach expected storage value using provided trie nodes. StorageValueUnavailable, + /// The storage value is `None`. + StorageValueEmpty, /// Failed to decode storage value. - StorageValueDecodeFailed(codec::Error), -} - -impl From for &'static str { - fn from(err: Error) -> &'static str { - match err { - Error::DuplicateNodesInProof => "Storage proof contains duplicate nodes", - Error::UnusedNodesInTheProof => "Storage proof contains unused nodes", - Error::StorageRootMismatch => "Storage root is missing from the storage proof", - Error::StorageValueUnavailable => "Storage value is missing from the storage proof", - Error::StorageValueDecodeFailed(_) => - "Failed to decode storage value from the storage proof", - } - } + StorageValueDecodeFailed(StrippableError), } /// Return valid storage proof and state root. @@ -155,7 +164,6 @@ impl From for &'static str { /// NOTE: This should only be used for **testing**. #[cfg(feature = "std")] pub fn craft_valid_storage_proof() -> (sp_core::H256, RawStorageProof) { - use codec::Encode; use sp_state_machine::{backend::Backend, prove_read, InMemoryBackend}; let state_version = sp_runtime::StateVersion::default(); From f3c0a9d2c6bd81d341171f25b6eb286d507147dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 03:00:15 +0000 Subject: [PATCH 0982/1210] Bump futures from 0.3.26 to 0.3.27 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.26 to 0.3.27. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.26...0.3.27) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 9db0e30c52d2e..86974b282d9d6 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.26" +futures = "0.3.27" hex = "0.4" log = "0.4.17" num-format = "0.4" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 5b6e08b5875b2..1a80a54f96555 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.26" +futures = "0.3.27" jsonrpsee = { version = "0.16", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index c3e32eb59b271..287798431fef5 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } -futures = "0.3.26" +futures = "0.3.27" log = "0.4.17" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index ef41561d88821..bb19515964752 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,7 @@ thiserror = "1.0.39" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.26" +futures = "0.3.27" hex = "0.4" num-traits = "0.2" log = "0.4.17" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index c4d2459e5cad0..efb6c6c85854d 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" -futures = "0.3.26" +futures = "0.3.27" hex = "0.4" log = "0.4.17" num-traits = "0.2" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 6800ca8dbfbb3..5481ce7edf870 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" async-trait = "0.1.66" -futures = "0.3.26" +futures = "0.3.27" log = "0.4.17" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 3a68ea25eb143..d8b66db2abcac 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1" backoff = "0.4" isahc = "1.2" env_logger = "0.10.0" -futures = "0.3.26" +futures = "0.3.27" jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" From bb13c1829ed41fcf746b06bc753b903b42a8072d Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 13 Mar 2023 15:11:10 +0100 Subject: [PATCH 0983/1210] Backport xcm bridging extensions to the bridge repo (#1813) * Backport xcm bridging extensions to the bridge repo * Fixes * Fixes --- bin/runtime-common/src/lib.rs | 3 + bin/runtime-common/src/messages.rs | 10 +- .../src/messages_xcm_extension.rs | 181 ++++++++++++++++++ 3 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 bin/runtime-common/src/messages_xcm_extension.rs diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index d9c87049077ae..ed486c04abccb 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -28,6 +28,7 @@ pub mod messages; pub mod messages_api; pub mod messages_benchmarking; pub mod messages_call_ext; +pub mod messages_xcm_extension; pub mod parachains_benchmarking; pub mod refund_relayer_extension; @@ -37,6 +38,8 @@ mod mock; #[cfg(feature = "integrity-test")] pub mod integrity; +const LOG_TARGET_BRIDGE_DISPATCH: &str = "runtime::bridge-dispatch"; + /// A duplication of the `FilterCall` trait. /// /// We need this trait in order to be able to implement it for the messages pallet, diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 4eb44ea85ed45..4493ac66742f0 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -497,7 +497,7 @@ pub mod target { let weight = XcmWeigher::weight(&mut payload.xcm.1); let weight = weight.unwrap_or_else(|e| { log::debug!( - target: "runtime::bridge-dispatch", + target: crate::LOG_TARGET_BRIDGE_DISPATCH, "Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}", message.key.lane_id, message.key.nonce, @@ -525,7 +525,7 @@ pub mod target { let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } = message.data.payload?; log::trace!( - target: "runtime::bridge-dispatch", + target: crate::LOG_TARGET_BRIDGE_DISPATCH, "Going to execute message {:?} (weight limit: {:?}): {:?} {:?}", message_id, weight_limit, @@ -551,7 +551,7 @@ pub mod target { match xcm_outcome { Ok(outcome) => { log::trace!( - target: "runtime::bridge-dispatch", + target: crate::LOG_TARGET_BRIDGE_DISPATCH, "Incoming message {:?} dispatched with result: {:?}", message_id, outcome, @@ -560,7 +560,7 @@ pub mod target { Ok(_weight) => (), Err(e) => { log::error!( - target: "runtime::bridge-dispatch", + target: crate::LOG_TARGET_BRIDGE_DISPATCH, "Incoming message {:?} was not dispatched, error: {:?}", message_id, e, @@ -570,7 +570,7 @@ pub mod target { }, Err(e) => { log::error!( - target: "runtime::bridge-dispatch", + target: crate::LOG_TARGET_BRIDGE_DISPATCH, "Incoming message {:?} was not dispatched, codec error: {:?}", message_id, e, diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs new file mode 100644 index 0000000000000..7163d8a535767 --- /dev/null +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -0,0 +1,181 @@ +// Copyright 2023 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 . + +//! Module provides utilities for easier XCM handling, e.g: +//! [`XcmExecutor`] -> [`MessageSender`] -> +//! | +//! +//! | +//! [`XcmRouter`] <- [`MessageDispatch`] <- + +use bp_messages::{ + source_chain::MessagesBridge, + target_chain::{DispatchMessage, MessageDispatch}, + LaneId, +}; +use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; +use codec::{Decode, Encode}; +use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound}; +use scale_info::TypeInfo; +use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; + +/// Plain "XCM" payload, which we transfer through bridge +pub type XcmAsPlainPayload = sp_std::prelude::Vec; + +/// Message dispatch result type for single message +#[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] +pub enum XcmBlobMessageDispatchResult { + InvalidPayload, + Dispatched, + NotDispatched(#[codec(skip)] &'static str), +} + +/// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages +pub struct XcmBlobMessageDispatch< + SourceBridgeHubChain, + TargetBridgeHubChain, + DispatchBlob, + DispatchBlobWeigher, +> { + _marker: sp_std::marker::PhantomData<( + SourceBridgeHubChain, + TargetBridgeHubChain, + DispatchBlob, + DispatchBlobWeigher, + )>, +} + +impl< + SourceBridgeHubChain: Chain, + TargetBridgeHubChain: Chain, + BlobDispatcher: DispatchBlob, + DispatchBlobWeigher: Get, + > MessageDispatch> + for XcmBlobMessageDispatch< + SourceBridgeHubChain, + TargetBridgeHubChain, + BlobDispatcher, + DispatchBlobWeigher, + > +{ + type DispatchPayload = XcmAsPlainPayload; + type DispatchLevelResult = XcmBlobMessageDispatchResult; + + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + DispatchBlobWeigher::get() + } + + fn dispatch( + _relayer_account: &AccountIdOf, + message: DispatchMessage, + ) -> MessageDispatchResult { + let payload = match message.data.payload { + Ok(payload) => payload, + Err(e) => { + log::error!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "[XcmBlobMessageDispatch] payload error: {:?} - message_nonce: {:?}", + e, + message.key.nonce + ); + return MessageDispatchResult { + // TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629 + unspent_weight: Weight::zero(), + dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload, + } + }, + }; + let dispatch_level_result = match BlobDispatcher::dispatch_blob(payload) { + Ok(_) => { + log::debug!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob was ok - message_nonce: {:?}", + message.key.nonce + ); + XcmBlobMessageDispatchResult::Dispatched + }, + Err(e) => { + let e = match e { + DispatchBlobError::Unbridgable => "DispatchBlobError::Unbridgable", + DispatchBlobError::InvalidEncoding => "DispatchBlobError::InvalidEncoding", + DispatchBlobError::UnsupportedLocationVersion => + "DispatchBlobError::UnsupportedLocationVersion", + DispatchBlobError::UnsupportedXcmVersion => + "DispatchBlobError::UnsupportedXcmVersion", + DispatchBlobError::RoutingError => "DispatchBlobError::RoutingError", + DispatchBlobError::NonUniversalDestination => + "DispatchBlobError::NonUniversalDestination", + DispatchBlobError::WrongGlobal => "DispatchBlobError::WrongGlobal", + }; + log::error!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}", + e, message.key.nonce + ); + XcmBlobMessageDispatchResult::NotDispatched(e) + }, + }; + MessageDispatchResult { + // TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629 + unspent_weight: Weight::zero(), + dispatch_level_result, + } + } +} + +/// [`XcmBlobHauler`] is responsible for sending messages to the bridge "point-to-point link" from +/// one side, where on the other it can be dispatched by [`XcmBlobMessageDispatch`]. +pub trait XcmBlobHauler { + /// Runtime message sender adapter. + type MessageSender: MessagesBridge; + + /// Runtime message sender origin, which is used by [`MessageSender`]. + type MessageSenderOrigin; + /// Our location within the Consensus Universe. + fn message_sender_origin() -> Self::MessageSenderOrigin; + + /// Return message lane (as "point-to-point link") used to deliver XCM messages. + fn xcm_lane() -> LaneId; +} + +/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`MessageSender`] and makes sure that +/// XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed. +pub struct XcmBlobHaulerAdapter(sp_std::marker::PhantomData); +impl> HaulBlob + for XcmBlobHaulerAdapter +{ + fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { + let lane = H::xcm_lane(); + let result = H::MessageSender::send_message(H::message_sender_origin(), lane, blob); + let result = result + .map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256)); + match &result { + Ok(result) => log::info!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "haul_blob result - ok: {:?} on lane: {:?}", + result, + lane + ), + Err(error) => log::error!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "haul_blob result - error: {:?} on lane: {:?}", + error, + lane + ), + }; + result.map(|_| ()).map_err(|_| HaulBlobError::Transport("MessageSenderError")) + } +} From 5a425275e18725db836b4148be36e5b8934d52da Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 14 Mar 2023 13:03:40 +0100 Subject: [PATCH 0984/1210] Bump substrate/polkadot/cumulus (#1962) * Bump substrate/polkadot/cumulus * sp_finality_grandpa - >sp_consensus_grandpa * sp_beefy -> sp_consensus_beefy * pallet_randomness_collective_flip -> pallet_insecure_randomness_collective_flip * fix * Cumulus parachain stuff * Cumulus parachain stuff one more * Millau/Rialto runtimes * Removed pallet_insecure_randomness_collective_flip * Millau node * Removed session historial * TMP: just try disable all fetches * Docs in gitlab.yml --- bin/millau/node/Cargo.toml | 13 ++-- bin/millau/node/src/chain_spec.rs | 4 +- bin/millau/node/src/service.rs | 65 +++++++++++-------- bin/millau/runtime/Cargo.toml | 8 +-- bin/millau/runtime/src/lib.rs | 39 ++++++----- bin/rialto-parachain/node/Cargo.toml | 1 + bin/rialto-parachain/node/src/service.rs | 30 +++++---- bin/rialto-parachain/runtime/Cargo.toml | 2 - bin/rialto-parachain/runtime/src/lib.rs | 3 - bin/rialto/node/Cargo.toml | 4 +- bin/rialto/node/src/chain_spec.rs | 4 +- bin/rialto/runtime/Cargo.toml | 7 +- bin/rialto/runtime/src/lib.rs | 61 +++++++++-------- modules/beefy/Cargo.toml | 2 +- modules/beefy/src/lib.rs | 2 +- modules/beefy/src/mock.rs | 4 +- modules/beefy/src/mock_chain.rs | 4 +- modules/beefy/src/utils.rs | 2 +- modules/grandpa/Cargo.toml | 4 +- modules/grandpa/src/benchmarking.rs | 2 +- modules/grandpa/src/lib.rs | 14 ++-- modules/grandpa/src/storage_types.rs | 2 +- primitives/beefy/Cargo.toml | 4 +- primitives/beefy/src/lib.rs | 14 ++-- primitives/header-chain/Cargo.toml | 4 +- primitives/header-chain/src/justification.rs | 6 +- primitives/header-chain/src/lib.rs | 4 +- .../tests/implementation_match.rs | 2 +- .../header-chain/tests/justification.rs | 2 +- primitives/test-utils/Cargo.toml | 4 +- primitives/test-utils/src/keyring.rs | 2 +- primitives/test-utils/src/lib.rs | 4 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- .../src/runtime_wrapper.rs | 2 +- .../src/codegen_runtime.rs | 4 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/lib-substrate-relay/src/error.rs | 2 +- .../src/finality/engine.rs | 6 +- 38 files changed, 184 insertions(+), 157 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index bf169ebe40d98..cca94bbe7b10e 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -19,9 +19,9 @@ millau-runtime = { path = "../runtime" } # Substrate Dependencies -beefy-gadget = { git = "https://github.com/paritytech/substrate", branch = "master" } -beefy-gadget-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-beefy-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -33,8 +33,8 @@ sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "mas sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-finality-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -42,10 +42,11 @@ sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "mast sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "master" } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index d18634eb9836d..8669ca92cc801 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -19,10 +19,10 @@ use millau_runtime::{ BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; -use sp_beefy::crypto::AuthorityId as BeefyId; use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_consensus_beefy::crypto::AuthorityId as BeefyId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; -use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; /// "Names" of the authorities accounts at local testnet. diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 8b0bc828957f0..f8e6d34933dd5 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -20,8 +20,8 @@ use jsonrpsee::RpcModule; use millau_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::BlockBackend; use sc_consensus_aura::{CompatibilityMode, ImportQueueParams, SlotProportion, StartAuraParams}; +use sc_consensus_grandpa::SharedVoterState; pub use sc_executor::NativeElseWasmExecutor; -use sc_finality_grandpa::SharedVoterState; use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; @@ -64,15 +64,15 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport< + sc_consensus_grandpa::GrandpaBlockImport< FullBackend, Block, FullClient, FullSelectChain, >, - sc_finality_grandpa::LinkHalf, - beefy_gadget::BeefyVoterLinks, - beefy_gadget::BeefyRPCLinks, + sc_consensus_grandpa::LinkHalf, + sc_consensus_beefy::BeefyVoterLinks, + sc_consensus_beefy::BeefyRPCLinks, Option, ), >, @@ -123,7 +123,7 @@ pub fn new_partial( client.clone(), ); - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( client.clone(), &client, select_chain.clone(), @@ -131,10 +131,11 @@ pub fn new_partial( )?; let (beefy_block_import, beefy_voter_links, beefy_rpc_links) = - beefy_gadget::beefy_block_import_and_links( + sc_consensus_beefy::beefy_block_import_and_links( grandpa_block_import.clone(), backend.clone(), client.clone(), + config.prometheus_registry().cloned(), ); let slot_duration = sc_consensus_aura::slot_duration(&*client)?; @@ -183,6 +184,8 @@ fn remote_keystore(_url: &str) -> Result, &'static str> { /// Builds a new service for a full client. pub fn new_full(mut config: Configuration) -> Result { + use sc_network_common::sync::warp::WarpSyncParams; + let sc_service::PartialComponents { client, backend, @@ -209,38 +212,41 @@ pub fn new_full(mut config: Configuration) -> Result // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change // anything in terms of behaviour, but makes the logs more consistent with the other // Substrate nodes. - let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( + let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), &config.chain_spec, ); config .network .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + .push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); let beefy_gossip_proto_name = - beefy_gadget::gossip_protocol_name(genesis_hash, config.chain_spec.fork_id()); + sc_consensus_beefy::gossip_protocol_name(genesis_hash, config.chain_spec.fork_id()); // `beefy_on_demand_justifications_handler` is given to `beefy-gadget` task to be run, // while `beefy_req_resp_cfg` is added to `config.network.request_response_protocols`. let (beefy_on_demand_justifications_handler, beefy_req_resp_cfg) = - beefy_gadget::communication::request_response::BeefyJustifsRequestHandler::new( + sc_consensus_beefy::communication::request_response::BeefyJustifsRequestHandler::new( genesis_hash, config.chain_spec.fork_id(), client.clone(), + config.prometheus_registry().cloned(), ); config .network .extra_sets - .push(beefy_gadget::communication::beefy_peers_set_config(beefy_gossip_proto_name.clone())); + .push(sc_consensus_beefy::communication::beefy_peers_set_config( + beefy_gossip_proto_name.clone(), + )); config.network.request_response_protocols.push(beefy_req_resp_cfg); - let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( + let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), Vec::default(), )); - let (network, system_rpc_tx, tx_handler_controller, network_starter) = + let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -248,7 +254,7 @@ pub fn new_full(mut config: Configuration) -> Result spawn_handle: task_manager.spawn_handle(), import_queue, block_announce_validator_builder: None, - warp_sync: Some(warp_sync), + warp_sync_params: Some(WarpSyncParams::WithProvider(warp_sync)), })?; if config.offchain_worker.enabled { @@ -269,12 +275,12 @@ pub fn new_full(mut config: Configuration) -> Result let shared_voter_state = SharedVoterState::empty(); let rpc_extensions_builder = { - use sc_finality_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; + use sc_consensus_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; - use beefy_gadget_rpc::{Beefy, BeefyApiServer}; use mmr_rpc::{Mmr, MmrApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use sc_finality_grandpa_rpc::{Grandpa, GrandpaApiServer}; + use sc_consensus_beefy_rpc::{Beefy, BeefyApiServer}; + use sc_consensus_grandpa_rpc::{Grandpa, GrandpaApiServer}; use sc_rpc::DenyUnsafe; use substrate_frame_rpc_system::{System, SystemApiServer}; @@ -329,6 +335,7 @@ pub fn new_full(mut config: Configuration) -> Result keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), + sync_service: sync_service.clone(), rpc_builder: rpc_extensions_builder, backend: backend.clone(), system_rpc_tx, @@ -369,8 +376,8 @@ pub fn new_full(mut config: Configuration) -> Result force_authoring, backoff_authoring_blocks, keystore: keystore_container.sync_keystore(), - sync_oracle: network.clone(), - justification_sync_link: network.clone(), + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -391,15 +398,16 @@ pub fn new_full(mut config: Configuration) -> Result if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; let justifications_protocol_name = beefy_on_demand_justifications_handler.protocol_name(); - let payload_provider = sp_beefy::mmr::MmrRootProvider::new(client.clone()); - let beefy_params = beefy_gadget::BeefyParams { + let payload_provider = sp_consensus_beefy::mmr::MmrRootProvider::new(client.clone()); + let beefy_params = sc_consensus_beefy::BeefyParams { client: client.clone(), backend, payload_provider, runtime: client, key_store: keystore.clone(), - network_params: beefy_gadget::BeefyNetworkParams { + network_params: sc_consensus_beefy::BeefyNetworkParams { network: network.clone(), + sync: sync_service.clone(), gossip_protocol_name: beefy_gossip_proto_name, justifications_protocol_name, _phantom: core::marker::PhantomData::, @@ -414,10 +422,10 @@ pub fn new_full(mut config: Configuration) -> Result task_manager.spawn_essential_handle().spawn_blocking( "beefy-gadget", None, - beefy_gadget::start_beefy_gadget::<_, _, _, _, _, _>(beefy_params), + sc_consensus_beefy::start_beefy_gadget::<_, _, _, _, _, _, _>(beefy_params), ); - let grandpa_config = sc_finality_grandpa::Config { + let grandpa_config = sc_consensus_grandpa::Config { // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), justification_period: 512, @@ -436,11 +444,12 @@ pub fn new_full(mut config: Configuration) -> Result // and vote data availability than the observer. The observer has not // been tested extensively yet and having most nodes in a network run it // could lead to finality stalls. - let grandpa_config = sc_finality_grandpa::GrandpaParams { + let grandpa_config = sc_consensus_grandpa::GrandpaParams { config: grandpa_config, link: grandpa_link, network, - voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), + sync: sync_service, + voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state, telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -451,7 +460,7 @@ pub fn new_full(mut config: Configuration) -> Result task_manager.spawn_essential_handle().spawn_blocking( "grandpa-voter", None, - sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, + sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, ); } diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 07e3e135aca4b..2f828393336f5 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -31,7 +31,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -43,8 +43,7 @@ pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["historical"]} pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -80,7 +79,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ - "sp-beefy/std", + "sp-consensus-beefy/std", "bp-messages/std", "bp-millau/std", "bp-parachains/std", @@ -106,7 +105,6 @@ std = [ "pallet-bridge-relayers/std", "pallet-grandpa/std", "pallet-mmr/std", - "pallet-randomness-collective-flip/std", "pallet-session/std", "pallet-shift-session-manager/std", "pallet-sudo/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index beb2a4063a800..21fff0e564e4c 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -41,9 +41,9 @@ use pallet_grandpa::{ }; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; -use sp_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_consensus_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; +use sp_core::OpaqueMetadata; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, @@ -223,8 +223,6 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; } -impl pallet_randomness_collective_flip::Config for Runtime {} - impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type MaxAuthorities = ConstU32<10>; @@ -234,23 +232,21 @@ impl pallet_aura::Config for Runtime { impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; type MaxAuthorities = ConstU32<10>; + type MaxSetIdSessionEntries = ConstU64<0>; type OnNewValidatorSet = MmrLeaf; + type WeightInfo = (); + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type KeyOwnerProofSystem = (); - type KeyOwnerProof = - >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); type MaxAuthorities = ConstU32<10>; type MaxSetIdSessionEntries = ConstU64<0>; + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } /// MMR helper types. @@ -292,7 +288,7 @@ parameter_types! { pub struct BeefyDummyDataProvider; -impl sp_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { +impl sp_consensus_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { fn extra_data() {} } @@ -555,7 +551,6 @@ construct_runtime!( Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, // BEEFY Bridges support. Beefy: pallet_beefy::{Pallet, Storage, Config}, @@ -743,7 +738,7 @@ impl_runtime_apis! { } } - impl sp_beefy::BeefyApi for Runtime { + impl sp_consensus_beefy::BeefyApi for Runtime { fn beefy_genesis() -> Option { Beefy::genesis_block() } @@ -751,6 +746,20 @@ impl_runtime_apis! { fn validator_set() -> Option> { Beefy::validator_set() } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: sp_consensus_beefy::EquivocationProof< + NumberFor, + sp_consensus_beefy::crypto::AuthorityId, + sp_consensus_beefy::crypto::Signature + >, + _key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof, + ) -> Option<()> { None } + + fn generate_key_ownership_proof( + _set_id: sp_consensus_beefy::ValidatorSetId, + _authority_id: sp_consensus_beefy::crypto::AuthorityId, + ) -> Option { None } } impl pallet_mmr::primitives::MmrApi< diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index c20b7f248cc22..4cdaa93bad0ef 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -45,6 +45,7 @@ sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "mas sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-network-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master"} diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 254340a8ad4cc..7e7fa2ed09be8 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -38,11 +38,12 @@ use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; -use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; +use cumulus_relay_chain_interface::RelayChainInterface; use sc_consensus::ImportQueue; // Substrate Imports use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; -use sc_network::{NetworkBlock, NetworkService}; +use sc_network::NetworkBlock; +use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; use sp_api::ConstructRuntimeApi; @@ -54,7 +55,6 @@ use substrate_prometheus_endpoint::Registry; type BlockNumber = u32; type Header = sp_runtime::generic::Header; pub type Block = sp_runtime::generic::Block; -type Hash = sp_core::H256; type ParachainClient = TFullClient>; @@ -236,7 +236,7 @@ where &TaskManager, Arc, Arc>>, - Arc>, + Arc>, SyncCryptoStorePtr, bool, ) -> Result>, sc_service::Error>, @@ -257,10 +257,7 @@ where None, ) .await - .map_err(|e| match e { - RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, - s => s.to_string().into(), - })?; + .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; let client = params.client.clone(); let backend = params.backend.clone(); @@ -272,7 +269,7 @@ where let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); - let (network, system_rpc_tx, tx_handler_controller, start_network) = + let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: ¶chain_config, client: client.clone(), @@ -282,7 +279,7 @@ where block_announce_validator_builder: Some(Box::new(|_| { Box::new(block_announce_validator) })), - warp_sync: None, + warp_sync_params: None, })?; let rpc_client = client.clone(); @@ -300,18 +297,23 @@ where keystore: params.keystore_container.sync_keystore(), backend: backend.clone(), network: network.clone(), + sync_service: sync_service.clone(), system_rpc_tx, tx_handler_controller, telemetry: telemetry.as_mut(), })?; let announce_block = { - let network = network.clone(); - Arc::new(move |hash, data| network.announce_block(hash, data)) + let sync_service = sync_service.clone(); + Arc::new(move |hash, data| sync_service.announce_block(hash, data)) }; let relay_chain_slot_duration = Duration::from_secs(6); + let overseer_handle = relay_chain_interface + .overseer_handle() + .map_err(|e| sc_service::Error::Application(Box::new(e)))?; + if validator { let parachain_consensus = build_consensus( client.clone(), @@ -321,7 +323,7 @@ where &task_manager, relay_chain_interface.clone(), transaction_pool, - network, + sync_service, params.keystore_container.sync_keystore(), force_authoring, )?; @@ -340,6 +342,7 @@ where import_queue: import_queue_service, collator_key: collator_key.expect("Command line arguments do not allow this. qed"), relay_chain_slot_duration, + recovery_handle: Box::new(overseer_handle), }; start_collator(params).await?; @@ -352,6 +355,7 @@ where relay_chain_interface, relay_chain_slot_duration, import_queue: import_queue_service, + recovery_handle: Box::new(overseer_handle), }; start_full_node(params)?; diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index b91e1cd2751a3..ec8955e7fd1b0 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -52,7 +52,6 @@ frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate" ## Substrate Pallet Dependencies pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -116,7 +115,6 @@ std = [ "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-relayers/std", - "pallet-randomness-collective-flip/std", "pallet-timestamp/std", "pallet-sudo/std", "pallet-transaction-payment/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 593c7b21228d5..d8e087c5a6a9e 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -302,8 +302,6 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} -impl pallet_randomness_collective_flip::Config for Runtime {} - parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); @@ -588,7 +586,6 @@ construct_runtime!( System: frame_system::{Pallet, Call, Storage, Config, Event}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event}, - RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 20, diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 5d68714235b22..be83e02424aa2 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -18,7 +18,7 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies -sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -29,7 +29,7 @@ sc-service = { git = "https://github.com/paritytech/substrate", branch = "master sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index cfc0ed62e1061..c51ca1197f61c 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -23,10 +23,10 @@ use rialto_runtime::{ }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_beefy::crypto::AuthorityId as BeefyId; use sp_consensus_babe::AuthorityId as BabeId; +use sp_consensus_beefy::crypto::AuthorityId as BeefyId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; -use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; /// "Names" of the authorities accounts at local testnet. diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index d5d018fb86414..4f0f64cbc9597 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -26,7 +26,7 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -39,7 +39,7 @@ pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["historical"]} pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -78,7 +78,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [features] default = ["std"] std = [ - "sp-beefy/std", + "sp-consensus-beefy/std", "bp-messages/std", "bp-millau/std", "bp-relayers/std", @@ -103,6 +103,7 @@ std = [ "pallet-grandpa/std", "pallet-mmr/std", "pallet-xcm/std", + "pallet-session/std", "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9873a6fd85593..9db181e284035 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -39,8 +39,8 @@ use pallet_grandpa::{ use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_consensus_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; +use sp_core::OpaqueMetadata; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, @@ -225,56 +225,47 @@ parameter_types! { impl pallet_babe::Config for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; - type MaxAuthorities = ConstU32<10>; - // session module is the trigger type EpochChangeTrigger = pallet_babe::ExternalTrigger; - // equivocation related configuration - we don't expect any equivocations in our testnets - type KeyOwnerProofSystem = (); - type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type HandleEquivocation = (); - type DisabledValidators = (); + type WeightInfo = (); + + type MaxAuthorities = ConstU32<10>; + + // equivocation related configuration - we don't expect any equivocations in our testnets + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } impl pallet_beefy::Config for Runtime { type BeefyId = BeefyId; type MaxAuthorities = ConstU32<10>; + type MaxSetIdSessionEntries = ConstU64<0>; type OnNewValidatorSet = MmrLeaf; + type WeightInfo = (); + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type MaxAuthorities = ConstU32<10>; - type KeyOwnerProofSystem = (); - type KeyOwnerProof = - >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type HandleEquivocation = (); // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) type WeightInfo = (); + type MaxAuthorities = ConstU32<10>; type MaxSetIdSessionEntries = ConstU64<0>; + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } impl pallet_mmr::Config for Runtime { const INDEXING_PREFIX: &'static [u8] = b"mmr"; type Hashing = Keccak256; type Hash = ::Output; + type LeafData = pallet_beefy_mmr::Pallet; type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; type WeightInfo = (); - type LeafData = pallet_beefy_mmr::Pallet; } parameter_types! { @@ -296,7 +287,7 @@ parameter_types! { pub struct BeefyDummyDataProvider; -impl sp_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { +impl sp_consensus_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { fn extra_data() {} } @@ -616,7 +607,7 @@ impl_runtime_apis! { } } - impl sp_beefy::BeefyApi for Runtime { + impl sp_consensus_beefy::BeefyApi for Runtime { fn beefy_genesis() -> Option { Beefy::genesis_block() } @@ -624,6 +615,20 @@ impl_runtime_apis! { fn validator_set() -> Option> { Beefy::validator_set() } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: sp_consensus_beefy::EquivocationProof< + NumberFor, + sp_consensus_beefy::crypto::AuthorityId, + sp_consensus_beefy::crypto::Signature + >, + _key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof, + ) -> Option<()> { None } + + fn generate_key_ownership_proof( + _set_id: sp_consensus_beefy::ValidatorSetId, + _authority_id: sp_consensus_beefy::crypto::AuthorityId, + ) -> Option { None } } impl pallet_mmr::primitives::MmrApi< diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 1908bd50c8a27..b50ac723db2a6 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.3.2" } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index a717acfe914fd..a3a68928bc5bc 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -419,7 +419,7 @@ mod tests { use frame_support::{assert_noop, assert_ok, traits::Get}; use mock::*; use mock_chain::*; - use sp_beefy::mmr::BeefyAuthoritySet; + use sp_consensus_beefy::mmr::BeefyAuthoritySet; use sp_runtime::DispatchError; fn next_block() { diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 551800090f7d5..1ffccc5dfbc5c 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -32,7 +32,7 @@ use sp_runtime::{ Perbill, }; -pub use sp_beefy::crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; +pub use sp_consensus_beefy::crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; use sp_core::crypto::Wraps; use sp_runtime::traits::Keccak256; @@ -49,7 +49,7 @@ pub type TestBridgedMmrHashing = BridgedMmrHashing; pub type TestBridgedMmrHash = BridgedMmrHash; pub type TestBridgedBeefyMmrLeafExtra = BridgedBeefyMmrLeafExtra; pub type TestBridgedMmrProof = BridgedMmrProof; -pub type TestBridgedRawMmrLeaf = sp_beefy::mmr::MmrLeaf< +pub type TestBridgedRawMmrLeaf = sp_consensus_beefy::mmr::MmrLeaf< TestBridgedBlockNumber, TestBridgedBlockHash, TestBridgedMmrHash, diff --git a/modules/beefy/src/mock_chain.rs b/modules/beefy/src/mock_chain.rs index ca7e84b121a95..c736aed074247 100644 --- a/modules/beefy/src/mock_chain.rs +++ b/modules/beefy/src/mock_chain.rs @@ -30,7 +30,7 @@ use bp_beefy::{BeefyPayload, Commitment, ValidatorSetId, MMR_ROOT_PAYLOAD_ID}; use codec::Encode; use pallet_mmr::NodeIndex; use rand::Rng; -use sp_beefy::mmr::{BeefyNextAuthoritySet, MmrLeafVersion}; +use sp_consensus_beefy::mmr::{BeefyNextAuthoritySet, MmrLeafVersion}; use sp_core::Pair; use sp_runtime::traits::{Hash, Header as HeaderT}; use std::collections::HashMap; @@ -188,7 +188,7 @@ impl HeaderBuilder { next_validator_keys.iter().map(|pair| pair.public()).collect::>(); let next_validators_mmr_root = get_authorities_mmr_root::(next_validators.iter()); - let leaf = sp_beefy::mmr::MmrLeaf { + let leaf = sp_consensus_beefy::mmr::MmrLeaf { version: MmrLeafVersion::new(1, 0), parent_number_and_hash: (header.number().saturating_sub(1), *header.parent_hash()), beefy_next_authority_set: BeefyNextAuthoritySet { diff --git a/modules/beefy/src/utils.rs b/modules/beefy/src/utils.rs index fac9a2c92e6c0..45e14ecbfe0b6 100644 --- a/modules/beefy/src/utils.rs +++ b/modules/beefy/src/utils.rs @@ -163,7 +163,7 @@ mod tests { use crate::{mock::*, mock_chain::*, *}; use bp_beefy::{BeefyPayload, MMR_ROOT_PAYLOAD_ID}; use frame_support::{assert_noop, assert_ok}; - use sp_beefy::ValidatorSet; + use sp_consensus_beefy::ValidatorSet; #[test] fn submit_commitment_checks_metadata() { diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 9e260a335379c..095c1d9f4e4b1 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -22,7 +22,7 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-grandpa = { 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-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 } @@ -48,7 +48,7 @@ std = [ "frame-benchmarking/std", "log/std", "scale-info/std", - "sp-finality-grandpa/std", + "sp-consensus-grandpa/std", "sp-runtime/std", "sp-std/std", "sp-trie/std", diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index f79deb7e7527c..5b9faea2a9965 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -49,7 +49,7 @@ use bp_test_utils::{ }; use frame_benchmarking::{benchmarks_instance_pallet, whitelisted_caller}; use frame_system::RawOrigin; -use sp_finality_grandpa::AuthorityId; +use sp_consensus_grandpa::AuthorityId; use sp_runtime::traits::{One, Zero}; use sp_std::vec::Vec; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 4304e82eeb103..2b9e49d4c95e1 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -45,7 +45,7 @@ use bp_header_chain::{ use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{dispatch::PostDispatchInfo, ensure}; -use sp_finality_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; +use sp_consensus_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, SaturatedConversion, @@ -403,7 +403,7 @@ pub mod pallet { /// Returned value will indicate if a change was enacted or not. pub(crate) fn try_enact_authority_change, I: 'static>( header: &BridgedHeader, - current_set_id: sp_finality_grandpa::SetId, + current_set_id: sp_consensus_grandpa::SetId, ) -> Result { let mut change_enacted = false; @@ -584,7 +584,7 @@ impl, I: 'static> HeaderChain> for GrandpaChainH pub(crate) fn find_scheduled_change( header: &H, -) -> Option> { +) -> Option> { use sp_runtime::generic::OpaqueDigestItemId; let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); @@ -603,7 +603,7 @@ pub(crate) fn find_scheduled_change( /// extracts it. pub(crate) fn find_forced_change( header: &H, -) -> Option<(H::Number, sp_finality_grandpa::ScheduledChange)> { +) -> Option<(H::Number, sp_consensus_grandpa::ScheduledChange)> { use sp_runtime::generic::OpaqueDigestItemId; let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); @@ -695,7 +695,7 @@ mod tests { fn change_log(delay: u64) -> Digest { let consensus_log = - ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + ConsensusLog::::ScheduledChange(sp_consensus_grandpa::ScheduledChange { next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], delay, }); @@ -706,7 +706,7 @@ mod tests { fn forced_change_log(delay: u64) -> Digest { let consensus_log = ConsensusLog::::ForcedChange( delay, - sp_finality_grandpa::ScheduledChange { + sp_consensus_grandpa::ScheduledChange { next_authorities: vec![(ALICE.into(), 1), (BOB.into(), 1)], delay, }, @@ -717,7 +717,7 @@ mod tests { fn many_authorities_log() -> Digest { let consensus_log = - ConsensusLog::::ScheduledChange(sp_finality_grandpa::ScheduledChange { + ConsensusLog::::ScheduledChange(sp_consensus_grandpa::ScheduledChange { next_authorities: std::iter::repeat((ALICE.into(), 1)) .take(MAX_BRIDGED_AUTHORITIES as usize + 1) .collect(), diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index d674f1a7b0ad6..704482863350b 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -22,7 +22,7 @@ use bp_header_chain::{AuthoritySet, ChainWithGrandpa}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound}; use scale_info::TypeInfo; -use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; +use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; use sp_std::marker::PhantomData; /// A bounded list of Grandpa authorities with associated weights. diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 58cc268e698c9..4b4044252ca99 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -18,7 +18,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies binary-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -35,7 +35,7 @@ std = [ "pallet-mmr/std", "scale-info/std", "serde", - "sp-beefy/std", + "sp-consensus-beefy/std", "sp-runtime/std", "sp-std/std" ] diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index 042d1d0e66134..de260d45eca68 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -25,7 +25,7 @@ pub use pallet_mmr::{ primitives::{DataOrHash as MmrDataOrHash, Proof as MmrProof}, verify_leaves_proof as verify_mmr_leaves_proof, }; -pub use sp_beefy::{ +pub use sp_consensus_beefy::{ crypto::{AuthorityId as EcdsaValidatorId, AuthoritySignature as EcdsaValidatorSignature}, known_payloads::MMR_ROOT_ID as MMR_ROOT_PAYLOAD_ID, mmr::{BeefyAuthoritySet, MmrLeafVersion}, @@ -51,7 +51,7 @@ use sp_std::prelude::*; pub trait ChainWithBeefy: Chain { /// The hashing algorithm used to compute the digest of the BEEFY commitment. /// - /// Corresponds to the hashing algorithm, used by `beefy_gadget::BeefyKeystore`. + /// Corresponds to the hashing algorithm, used by `sc_consensus_beefy::BeefyKeystore`. type CommitmentHasher: sp_runtime::traits::Hash; /// The hashing algorithm used to build the MMR. @@ -95,7 +95,7 @@ pub type BeefyAuthorityIdOf = ::AuthorityId; /// BEEFY validator set, containing both validator identifiers and the numeric set id. pub type BeefyAuthoritySetOf = ValidatorSet>; /// BEEFY authority set, containing both validator identifiers and the numeric set id. -pub type BeefyAuthoritySetInfoOf = sp_beefy::mmr::BeefyAuthoritySet>; +pub type BeefyAuthoritySetInfoOf = sp_consensus_beefy::mmr::BeefyAuthoritySet>; /// BEEFY validator signature used by given Substrate chain. pub type BeefyValidatorSignatureOf = <::AuthorityId as RuntimeAppPublic>::Signature; @@ -116,8 +116,12 @@ pub type BeefyMmrLeafExtraOf = ::BeefyMmrLeafExtra; /// the given Substrate chain. pub type BeefyAuthorityIdToMerkleLeafOf = ::AuthorityIdToMerkleLeaf; /// Actual type of leafs in the BEEFY MMR. -pub type BeefyMmrLeafOf = - sp_beefy::mmr::MmrLeaf, HashOf, MmrHashOf, BeefyMmrLeafExtraOf>; +pub type BeefyMmrLeafOf = sp_consensus_beefy::mmr::MmrLeaf< + BlockNumberOf, + HashOf, + MmrHashOf, + BeefyMmrLeafExtraOf, +>; /// Data required for initializing the BEEFY pallet. /// diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index be87cce460e38..0335836e328b4 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -20,7 +20,7 @@ bp-runtime = { path = "../runtime", 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-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-grandpa = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -39,7 +39,7 @@ std = [ "frame-support/std", "scale-info/std", "sp-core/std", - "sp-finality-grandpa/std", + "sp-consensus-grandpa/std", "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 88dac0acf9f6d..06ed782763dfc 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -17,7 +17,7 @@ //! Pallet for checking GRANDPA Finality Proofs. //! //! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin -//! will ever be moved to the sp_finality_grandpa, we should reuse that implementation. +//! will ever be moved to the sp_consensus_grandpa, we should reuse that implementation. use crate::ChainWithGrandpa; @@ -26,7 +26,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use finality_grandpa::voter_set::VoterSet; use frame_support::RuntimeDebug; use scale_info::TypeInfo; -use sp_finality_grandpa::{AuthorityId, AuthoritySignature, SetId}; +use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::{traits::Header as HeaderT, SaturatedConversion}; use sp_std::{ collections::{btree_map::BTreeMap, btree_set::BTreeSet}, @@ -307,7 +307,7 @@ where ); // verify authority signature - if !sp_finality_grandpa::check_message_signature_with_buffer( + if !sp_consensus_grandpa::check_message_signature_with_buffer( &finality_grandpa::Message::Precommit(signed.precommit.clone()), &signed.id, &signed.signature, diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5d05a1b15d8fa..5e2bbad242e5b 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::PalletError; use scale_info::TypeInfo; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -use sp_finality_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; +use sp_consensus_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; use sp_std::boxed::Box; @@ -145,7 +145,7 @@ pub struct GrandpaConsensusLogReader(sp_std::marker::PhantomData impl GrandpaConsensusLogReader { pub fn find_authorities_change( digest: &Digest, - ) -> Option> { + ) -> Option> { // find the first consensus digest with the right ID which converts to // the right kind of consensus log. digest diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index 5d0fa35c37683..c70683b173d1f 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -27,7 +27,7 @@ use bp_test_utils::{ JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE, TEST_GRANDPA_SET_ID, }; use finality_grandpa::voter_set::VoterSet; -use sp_finality_grandpa::{AuthorityId, AuthorityWeight}; +use sp_consensus_grandpa::{AuthorityId, AuthorityWeight}; use sp_runtime::traits::Header as HeaderT; type TestHeader = sp_runtime::testing::Header; diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 52fa33ae97491..3cd63b935d00e 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -76,7 +76,7 @@ fn valid_justification_accepted_with_single_fork() { #[test] fn valid_justification_accepted_with_arbitrary_number_of_authorities() { use finality_grandpa::voter_set::VoterSet; - use sp_finality_grandpa::AuthorityId; + use sp_consensus_grandpa::AuthorityId; let n = 15; let required_signatures = required_justification_precommits(n as _); diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 0a591334577af..8307534093f1f 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.16.0", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-grandpa = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -23,7 +23,7 @@ std = [ "ed25519-dalek/std", "finality-grandpa/std", "sp-application-crypto/std", - "sp-finality-grandpa/std", + "sp-consensus-grandpa/std", "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index 8b7a2b3925814..b1782109668ae 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -19,7 +19,7 @@ use codec::Encode; use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; use finality_grandpa::voter_set::VoterSet; -use sp_finality_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; +use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index a6bb3d9b8feb6..6bb4adbf45092 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -20,7 +20,7 @@ use bp_header_chain::justification::{required_justification_precommits, GrandpaJustification}; use codec::Encode; -use sp_finality_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId}; +use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId}; use sp_runtime::traits::{Header as HeaderT, One, Zero}; use sp_std::prelude::*; @@ -170,7 +170,7 @@ pub fn signed_precommit( ) -> finality_grandpa::SignedPrecommit { let precommit = finality_grandpa::Precommit { target_hash: target.0, target_number: target.1 }; - let encoded = sp_finality_grandpa::localized_payload( + let encoded = sp_consensus_grandpa::localized_payload( round, set_id, &finality_grandpa::Message::Precommit(precommit.clone()), diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index 7c9b90975d6ba..8164ae5afed21 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -29,4 +29,4 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master [dev-dependencies] bp-polkadot-core = { path = "../../primitives/polkadot-core" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 13fb1a7e6ab4b..374dd5b44ce8c 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -75,8 +75,8 @@ impl From> for Call { mod tests { use super::*; use bp_runtime::BasicOperatingMode; + use sp_consensus_grandpa::AuthorityList; use sp_core::hexdisplay::HexDisplay; - use sp_finality_grandpa::AuthorityList; use sp_runtime::traits::Header; use std::str::FromStr; diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs index 16a539f28435c..d725aafd41553 100644 --- a/relays/client-rialto-parachain/src/codegen_runtime.rs +++ b/relays/client-rialto-parachain/src/codegen_runtime.rs @@ -7034,7 +7034,7 @@ pub mod api { )] pub struct StoredAuthoritySet { pub authorities: runtime_types::sp_core::bounded::bounded_vec::BoundedVec<( - runtime_types::sp_finality_grandpa::app::Public, + runtime_types::sp_consensus_grandpa::app::Public, ::core::primitive::u64, )>, pub set_id: ::core::primitive::u64, @@ -8115,7 +8115,7 @@ pub mod api { pub struct Signature(pub [::core::primitive::u8; 64usize]); } } - pub mod sp_finality_grandpa { + pub mod sp_consensus_grandpa { use super::runtime_types; pub mod app { use super::runtime_types; diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index bb19515964752..9c336056dc644 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -44,7 +44,7 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] diff --git a/relays/lib-substrate-relay/src/error.rs b/relays/lib-substrate-relay/src/error.rs index b41870a181d93..2ebd9130f3912 100644 --- a/relays/lib-substrate-relay/src/error.rs +++ b/relays/lib-substrate-relay/src/error.rs @@ -17,7 +17,7 @@ //! Relay errors. use relay_substrate_client as client; -use sp_finality_grandpa::AuthorityList; +use sp_consensus_grandpa::AuthorityList; use sp_runtime::traits::MaybeDisplay; use std::fmt::Debug; use thiserror::Error; diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 4fc503011bba1..f2ddd32db8600 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -30,8 +30,8 @@ use relay_substrate_client::{ BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, HeaderOf, Subscription, SubstrateFinalityClient, SubstrateGrandpaFinalityClient, }; +use sp_consensus_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID}; use sp_core::{storage::StorageKey, Bytes}; -use sp_finality_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header, ConsensusEngineId}; use std::marker::PhantomData; @@ -155,8 +155,8 @@ impl Engine for Grandpa { C::WITH_CHAIN_GRANDPA_PALLET_NAME, ); let (authority_set, authority_set_id): ( - sp_finality_grandpa::AuthorityList, - sp_finality_grandpa::SetId, + sp_consensus_grandpa::AuthorityList, + sp_consensus_grandpa::SetId, ) = target_client .storage_value(current_authority_set_key, None) .await? From 75c26916343aebb97b9bfddc4451e76689a0ec32 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 14 Mar 2023 13:45:13 +0100 Subject: [PATCH 0985/1210] Removed deprecated `#[pallet::generate_store(pub(super) trait Store)]` according to latest Cumulus (#1964) --- modules/messages/src/lib.rs | 1 - modules/parachains/src/lib.rs | 1 - modules/relayers/src/lib.rs | 1 - modules/shift-session-manager/src/lib.rs | 1 - 4 files changed, 4 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 68af302444561..a9a25fb96220d 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -178,7 +178,6 @@ pub mod pallet { >>::MessagesDeliveryProof; #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(PhantomData<(T, I)>); impl, I: 'static> OwnedBridgeModule for Pallet { diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 98556f737bac3..20a9ef9b95bd3 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -277,7 +277,6 @@ pub mod pallet { >; #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(PhantomData<(T, I)>); impl, I: 'static> OwnedBridgeModule for Pallet { diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 3d32e3c7a1469..bd33b811b3043 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -63,7 +63,6 @@ pub mod pallet { } #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(PhantomData); #[pallet::call] diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 63656c81eed16..1c38a52b0c21e 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -35,7 +35,6 @@ pub mod pallet { pub trait Config: pallet_session::Config {} #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] #[pallet::without_storage_info] pub struct Pallet(PhantomData); From 43c1dc493c752f1073d70fac4e864cf45818e5f2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Mar 2023 17:11:03 +0300 Subject: [PATCH 0986/1210] Fix invalid batch transaction (#1957) * fix invalid batch transaction * RaceState is now trait * clippy --- relays/lib-substrate-relay/src/lib.rs | 28 ++- .../lib-substrate-relay/src/messages_lane.rs | 13 +- relays/messages/src/message_lane_loop.rs | 13 +- relays/messages/src/message_race_delivery.rs | 66 ++++--- relays/messages/src/message_race_loop.rs | 176 +++++++++++++----- relays/messages/src/message_race_strategy.rs | 103 +++++----- 6 files changed, 275 insertions(+), 124 deletions(-) diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 28c538b309a0b..37a4d602e598d 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -91,18 +91,21 @@ impl TaggedAccount { } /// Batch call builder. -pub trait BatchCallBuilder: Send { +pub trait BatchCallBuilder: Clone + Send { /// Create batch call from given calls vector. fn build_batch_call(&self, _calls: Vec) -> Call; } /// Batch call builder constructor. -pub trait BatchCallBuilderConstructor { +pub trait BatchCallBuilderConstructor: Clone { + /// Call builder, used by this constructor. + type CallBuilder: BatchCallBuilder; /// Create a new instance of a batch call builder. - fn new_builder() -> Option>>; + fn new_builder() -> Option; } /// Batch call builder based on `pallet-utility`. +#[derive(Clone)] pub struct UtilityPalletBatchCallBuilder(PhantomData); impl BatchCallBuilder for UtilityPalletBatchCallBuilder @@ -118,14 +121,25 @@ impl BatchCallBuilderConstructor for UtilityPalletBatchCallBu where C: ChainWithUtilityPallet, { - fn new_builder() -> Option>> { - Some(Box::new(Self(Default::default()))) + type CallBuilder = Self; + + fn new_builder() -> Option { + Some(Self(Default::default())) } } -/// A `BatchCallBuilderConstructor` that always returns `None`. +// A `BatchCallBuilderConstructor` that always returns `None`. impl BatchCallBuilderConstructor for () { - fn new_builder() -> Option>> { + type CallBuilder = (); + fn new_builder() -> Option { None } } + +// Dummy `BatchCallBuilder` implementation that must never be used outside +// of the `impl BatchCallBuilderConstructor for ()` code. +impl BatchCallBuilder for () { + fn build_batch_call(&self, _calls: Vec) -> Call { + unreachable!("never called, because ()::new_builder() returns None; qed") + } +} diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 0a7a3566d20f1..b86a2629b0751 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -111,8 +111,9 @@ pub struct MessagesRelayParams { /// Batch transaction that brings headers + and messages delivery/receiving confirmations to the /// source node. +#[derive(Clone)] pub struct BatchProofTransaction>> { - builder: Box>>, + builder: B::CallBuilder, proved_header: HeaderIdOf, prove_calls: Vec>, @@ -120,6 +121,16 @@ pub struct BatchProofTransaction B>, } +impl>> std::fmt::Debug + for BatchProofTransaction +{ + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + fmt.debug_struct("BatchProofTransaction") + .field("proved_header", &self.proved_header) + .finish() + } +} + impl>> BatchProofTransaction { diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index 0533e51d5db47..ba86f05ffd32a 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -111,7 +111,7 @@ pub struct NoncesSubmitArtifacts { /// Batch transaction that already submit some headers and needs to be extended with /// messages/delivery proof before sending. -pub trait BatchTransaction: Send { +pub trait BatchTransaction: Debug + Send { /// Header that was required in the original call and which is bundled within this /// batch transaction. fn required_header_id(&self) -> HeaderId; @@ -121,7 +121,7 @@ pub trait BatchTransaction: Send { #[async_trait] pub trait SourceClient: RelayClient { /// Type of batch transaction that submits finality and message receiving proof. - type BatchTransaction: BatchTransaction>; + type BatchTransaction: BatchTransaction> + Clone; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -186,7 +186,7 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Type of batch transaction that submits finality and messages proof. - type BatchTransaction: BatchTransaction>; + type BatchTransaction: BatchTransaction> + Clone; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -1212,6 +1212,9 @@ pub(crate) mod tests { original_data, Arc::new(|_| {}), Arc::new(move |data: &mut TestClientData| { + data.source_state.best_self = + HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); + data.source_state.best_finalized_self = data.source_state.best_self; if let Some(target_to_source_header_required) = data.target_to_source_header_required.take() { @@ -1223,6 +1226,10 @@ pub(crate) mod tests { }), Arc::new(|_| {}), Arc::new(move |data: &mut TestClientData| { + data.target_state.best_self = + HeaderId(data.target_state.best_self.0 + 1, data.target_state.best_self.1 + 1); + data.target_state.best_finalized_self = data.target_state.best_self; + if let Some(source_to_target_header_required) = data.source_to_target_header_required.take() { diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index b50e6c0841ead..7a245858b32d8 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -322,13 +322,19 @@ where self.strategy.is_empty() } - fn required_source_header_at_target( + fn required_source_header_at_target, TargetHeaderIdOf

>>( &self, current_best: &SourceHeaderIdOf

, + race_state: RS, ) -> Option> { + // we have already submitted something - let's wait until it is mined + if race_state.nonces_submitted().is_some() { + return None + } + let has_nonces_to_deliver = !self.strategy.is_empty(); let header_required_for_messages_delivery = - self.strategy.required_source_header_at_target(current_best); + self.strategy.required_source_header_at_target(current_best, race_state); let header_required_for_reward_confirmations_delivery = self .latest_confirmed_nonces_at_source .back() @@ -381,10 +387,10 @@ where self.strategy.source_nonces_updated(at_block, nonces) } - fn best_target_nonces_updated( + fn best_target_nonces_updated, TargetHeaderIdOf

>>( &mut self, nonces: TargetClientNonces, - race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, + race_state: &mut RS, ) { // best target nonces must always be ge than finalized target nonces let latest_nonce = nonces.latest_nonce; @@ -396,13 +402,13 @@ where ) } - fn finalized_target_nonces_updated( + fn finalized_target_nonces_updated, TargetHeaderIdOf

>>( &mut self, nonces: TargetClientNonces, - race_state: &mut RaceState, TargetHeaderIdOf

, P::MessagesProof>, + race_state: &mut RS, ) { if let Some(ref best_finalized_source_header_id_at_best_target) = - race_state.best_finalized_source_header_id_at_best_target + race_state.best_finalized_source_header_id_at_best_target() { let oldest_header_number_to_keep = best_finalized_source_header_id_at_best_target.0; while self @@ -426,13 +432,13 @@ where ) } - async fn select_nonces_to_deliver( + async fn select_nonces_to_deliver, TargetHeaderIdOf

>>( &self, - race_state: RaceState, TargetHeaderIdOf

, P::MessagesProof>, + race_state: RS, ) -> Option<(RangeInclusive, Self::ProofParameters)> { let best_target_nonce = self.strategy.best_at_target()?; let best_finalized_source_header_id_at_best_target = - race_state.best_finalized_source_header_id_at_best_target.clone()?; + race_state.best_finalized_source_header_id_at_best_target()?; let latest_confirmed_nonce_at_source = self .latest_confirmed_nonces_at_source .iter() @@ -576,12 +582,16 @@ impl NoncesRange for MessageDetailsMap; + type TestRaceState = RaceStateImpl< + TestSourceHeaderId, + TestTargetHeaderId, + TestMessagesProof, + TestMessagesBatchTransaction, + >; type TestStrategy = MessageDeliveryStrategy; @@ -617,12 +632,13 @@ mod tests { } fn prepare_strategy() -> (TestRaceState, TestStrategy) { - let mut race_state = RaceState { + let mut race_state = RaceStateImpl { best_finalized_source_header_id_at_source: Some(header_id(1)), best_finalized_source_header_id_at_best_target: Some(header_id(1)), best_target_header_id: Some(header_id(1)), best_finalized_target_header_id: Some(header_id(1)), nonces_to_submit: None, + nonces_to_submit_batch: None, nonces_submitted: None, }; @@ -964,14 +980,17 @@ mod tests { ); // nothing needs to be delivered now and we don't need any new headers assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - assert_eq!(strategy.required_source_header_at_target(&header_id(1)), None); + assert_eq!(strategy.required_source_header_at_target(&header_id(1), state.clone()), None); // now let's generate two more nonces [24; 25] at the soruce; strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 19, 0)); // // - so now we'll need to relay source block#2 to be able to accept messages [24; 25]. assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2))); + assert_eq!( + strategy.required_source_header_at_target(&header_id(1), state.clone()), + Some(header_id(2)) + ); // let's relay source block#2 state.best_finalized_source_header_id_at_source = Some(header_id(2)); @@ -982,7 +1001,7 @@ mod tests { // and ask strategy again => still nothing to deliver, because parallel confirmations // race need to be pushed further assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - assert_eq!(strategy.required_source_header_at_target(&header_id(2)), None); + assert_eq!(strategy.required_source_header_at_target(&header_id(2), state.clone()), None); // let's confirm messages [20; 23] strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 23, 0)); @@ -990,10 +1009,10 @@ mod tests { // and ask strategy again => now we have everything required to deliver remaining // [24; 25] nonces and proof of [20; 23] confirmation assert_eq!( - strategy.select_nonces_to_deliver(state).await, + strategy.select_nonces_to_deliver(state.clone()).await, Some(((24..=25), proof_parameters(true, 2))), ); - assert_eq!(strategy.required_source_header_at_target(&header_id(2)), None); + assert_eq!(strategy.required_source_header_at_target(&header_id(2), state), None); } #[async_std::test] @@ -1025,6 +1044,7 @@ mod tests { #[test] #[allow(clippy::reversed_empty_ranges)] fn no_source_headers_required_at_target_if_lanes_are_empty() { + let (state, _) = prepare_strategy(); let mut strategy = TestStrategy { max_unrewarded_relayer_entries_at_target: 4, max_unconfirmed_nonces_at_target: 4, @@ -1053,7 +1073,7 @@ mod tests { strategy.latest_confirmed_nonces_at_source, VecDeque::from([(source_header_id, 0)]) ); - assert_eq!(strategy.required_source_header_at_target(&source_header_id), None); + assert_eq!(strategy.required_source_header_at_target(&source_header_id, state), None); } #[async_std::test] diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 50f71ea050bb5..7e3f84dd5d119 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -25,7 +25,7 @@ use crate::message_lane_loop::{BatchTransaction, ClientState, NoncesSubmitArtifa use async_trait::async_trait; use bp_messages::MessageNonce; use futures::{ - future::FutureExt, + future::{FutureExt, TryFutureExt}, stream::{FusedStream, StreamExt}, }; use relay_utils::{ @@ -41,14 +41,14 @@ use std::{ /// One of races within lane. pub trait MessageRace { /// Header id of the race source. - type SourceHeaderId: Debug + Clone + PartialEq; + type SourceHeaderId: Debug + Clone + PartialEq + Send; /// Header id of the race source. - type TargetHeaderId: Debug + Clone + PartialEq; + type TargetHeaderId: Debug + Clone + PartialEq + Send; /// Message nonce used in the race. type MessageNonce: Debug + Clone; /// Proof that is generated and delivered in this race. - type Proof: Debug + Clone; + type Proof: Debug + Clone + Send; /// Name of the race source. fn source_name() -> String; @@ -128,7 +128,7 @@ pub trait TargetClient { /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; /// Type of batch transaction that submits finality and proof to the target node. - type BatchTransaction: BatchTransaction; + type BatchTransaction: BatchTransaction + Clone; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker; @@ -175,9 +175,10 @@ pub trait RaceStrategy: Debug { /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; /// Return id of source header that is required to be on target to continue synchronization. - fn required_source_header_at_target( + fn required_source_header_at_target>( &self, current_best: &SourceHeaderId, + race_state: RS, ) -> Option; /// Return the best nonce at source node. /// @@ -196,29 +197,53 @@ pub trait RaceStrategy: Debug { nonces: SourceClientNonces, ); /// Called when best nonces are updated at target node of the race. - fn best_target_nonces_updated( + fn best_target_nonces_updated>( &mut self, nonces: TargetClientNonces, - race_state: &mut RaceState, + race_state: &mut RS, ); /// Called when finalized nonces are updated at target node of the race. - fn finalized_target_nonces_updated( + fn finalized_target_nonces_updated>( &mut self, nonces: TargetClientNonces, - race_state: &mut RaceState, + race_state: &mut RS, ); /// Should return `Some(nonces)` if we need to deliver proof of `nonces` (and associated /// data) from source to target node. /// Additionally, parameters required to generate proof are returned. - async fn select_nonces_to_deliver( + async fn select_nonces_to_deliver>( &self, - race_state: RaceState, + race_state: RS, ) -> Option<(RangeInclusive, Self::ProofParameters)>; } /// State of the race. +pub trait RaceState: Send { + /// Best finalized source header id at the source client. + fn best_finalized_source_header_id_at_source(&self) -> Option; + /// Best finalized source header id at the best block on the target + /// client (at the `best_finalized_source_header_id_at_best_target`). + fn best_finalized_source_header_id_at_best_target(&self) -> Option; + /// The best header id at the target client. + fn best_target_header_id(&self) -> Option; + /// Best finalized header id at the target client. + fn best_finalized_target_header_id(&self) -> Option; + + /// Returns `true` if we have selected nonces to submit to the target node. + fn nonces_to_submit(&self) -> Option>; + /// Reset our nonces selection. + fn reset_nonces_to_submit(&mut self); + + /// Returns `true` if we have submitted some nonces to the target node and are + /// waiting for them to appear there. + fn nonces_submitted(&self) -> Option>; + /// Reset our nonces submission. + fn reset_nonces_submitted(&mut self); +} + +/// State of the race and prepared batch transaction (if available). #[derive(Debug, Clone)] -pub struct RaceState { +pub(crate) struct RaceStateImpl { /// Best finalized source header id at the source client. pub best_finalized_source_header_id_at_source: Option, /// Best finalized source header id at the best block on the target @@ -230,13 +255,67 @@ pub struct RaceState { pub best_finalized_target_header_id: Option, /// Range of nonces that we have selected to submit. pub nonces_to_submit: Option<(SourceHeaderId, RangeInclusive, Proof)>, + /// Batch transaction ready to include and deliver selected `nonces_to_submit` from the + /// `state`. + pub nonces_to_submit_batch: Option, /// Range of nonces that is currently submitted. pub nonces_submitted: Option>, } -impl RaceState { - /// Reset `nonces_submitted` to `None`. - fn reset_submitted(&mut self) { +impl Default + for RaceStateImpl +{ + fn default() -> Self { + RaceStateImpl { + best_finalized_source_header_id_at_source: None, + best_finalized_source_header_id_at_best_target: None, + best_target_header_id: None, + best_finalized_target_header_id: None, + nonces_to_submit: None, + nonces_to_submit_batch: None, + nonces_submitted: None, + } + } +} + +impl RaceState + for RaceStateImpl +where + SourceHeaderId: Clone + Send, + TargetHeaderId: Clone + Send, + Proof: Clone + Send, + BatchTx: Clone + Send, +{ + fn best_finalized_source_header_id_at_source(&self) -> Option { + self.best_finalized_source_header_id_at_source.clone() + } + + fn best_finalized_source_header_id_at_best_target(&self) -> Option { + self.best_finalized_source_header_id_at_best_target.clone() + } + + fn best_target_header_id(&self) -> Option { + self.best_target_header_id.clone() + } + + fn best_finalized_target_header_id(&self) -> Option { + self.best_finalized_target_header_id.clone() + } + + fn nonces_to_submit(&self) -> Option> { + self.nonces_to_submit.as_ref().map(|(_, nonces, _)| nonces.clone()) + } + + fn reset_nonces_to_submit(&mut self) { + self.nonces_to_submit = None; + self.nonces_to_submit_batch = None; + } + + fn nonces_submitted(&self) -> Option> { + self.nonces_submitted.clone() + } + + fn reset_nonces_submitted(&mut self) { self.nonces_submitted = None; } } @@ -257,7 +336,7 @@ pub async fn run, TC: TargetClient

>( >, ) -> Result<(), FailedClient> { let mut progress_context = Instant::now(); - let mut race_state = RaceState::default(); + let mut race_state = RaceStateImpl::default(); let mut source_retry_backoff = retry_backoff(); let mut source_client_is_online = true; @@ -302,7 +381,8 @@ pub async fn run, TC: TargetClient

>( != Some(&source_state.best_finalized_self); if is_source_state_updated { source_nonces_required = true; - race_state.best_finalized_source_header_id_at_source = Some(source_state.best_finalized_self); + race_state.best_finalized_source_header_id_at_source + = Some(source_state.best_finalized_self); } } }, @@ -353,7 +433,7 @@ pub async fn run, TC: TargetClient

>( source_required_header = race_state .best_finalized_source_header_id_at_best_target .as_ref() - .and_then(|best| strategy.required_source_header_at_target(best)); + .and_then(|best| strategy.required_source_header_at_target(best, race_state.clone())); }, nonces = target_best_nonces => { target_best_nonces_required = false; @@ -408,10 +488,13 @@ pub async fn run, TC: TargetClient

>( |maybe_batch_transaction: Option| { log::debug!( target: "bridge", - "Target {} client has been asked for more {} headers. Batch tx: {:?}", + "Target {} client has been asked for more {} headers. Batch tx: {}", P::target_name(), P::source_name(), - maybe_batch_transaction.is_some(), + maybe_batch_transaction + .as_ref() + .map(|bt| format!("yes ({:?})", bt.required_header_id())) + .unwrap_or_else(|| "no".into()), ); target_batch_transaction = maybe_batch_transaction; @@ -425,7 +508,7 @@ pub async fn run, TC: TargetClient

>( source_client_is_online = process_future_result( proof, &mut source_retry_backoff, - |(at_block, nonces_range, proof)| { + |(at_block, nonces_range, proof, batch_transaction)| { log::debug!( target: "bridge", "Received proof for nonces in range {:?} from {}", @@ -434,6 +517,7 @@ pub async fn run, TC: TargetClient

>( ); race_state.nonces_to_submit = Some((at_block, nonces_range, proof)); + race_state.nonces_to_submit_batch = batch_transaction; }, &mut source_go_offline_future, async_std::task::sleep, @@ -452,8 +536,7 @@ pub async fn run, TC: TargetClient

>( P::target_name(), ); - target_batch_transaction = None; - race_state.nonces_to_submit = None; + race_state.reset_nonces_to_submit(); race_state.nonces_submitted = Some(artifacts.nonces); target_tx_tracker.set(artifacts.tx_tracker.wait().fuse()); }, @@ -490,7 +573,7 @@ pub async fn run, TC: TargetClient

>( e, ); - race_state.reset_submitted(); + race_state.reset_nonces_submitted(); }); }, (TrackedTransactionStatus::Lost, _) => { @@ -503,7 +586,7 @@ pub async fn run, TC: TargetClient

>( strategy, ); - race_state.reset_submitted(); + race_state.reset_nonces_submitted(); }, _ => (), } @@ -524,6 +607,12 @@ pub async fn run, TC: TargetClient

>( source_client_is_online = false; // if we've started to submit batch transaction, let's prioritize it + // + // we're using `take` here, because we don't need batch transaction (i.e. some + // underlying finality proof) anymore for our future calls - we were unable to + // use it for our current state, so why would we need to keep an obsolete proof + // for the future? + let target_batch_transaction = target_batch_transaction.take(); let expected_race_state = if let Some(ref target_batch_transaction) = target_batch_transaction { // when selecting nonces for the batch transaction, we assume that the required @@ -551,7 +640,12 @@ pub async fn run, TC: TargetClient

>( ); source_generate_proof.set( - race_source.generate_proof(at_block, nonces_range, proof_parameters).fuse(), + race_source + .generate_proof(at_block, nonces_range, proof_parameters) + .and_then(|(at_source_block, nonces, proof)| async { + Ok((at_source_block, nonces, proof, target_batch_transaction)) + }) + .fuse(), ); } else if source_nonces_required && best_at_source.is_some() { log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); @@ -582,7 +676,7 @@ pub async fn run, TC: TargetClient

>( "Going to submit proof of messages in range {:?} to {} node{}", nonces_range, P::target_name(), - target_batch_transaction.as_ref().map(|tx| format!( + race_state.nonces_to_submit_batch.as_ref().map(|tx| format!( ". This transaction is batched with sending the proof for header {:?}.", tx.required_header_id()) ).unwrap_or_default(), @@ -591,7 +685,7 @@ pub async fn run, TC: TargetClient

>( target_submit_proof.set( race_target .submit_proof( - target_batch_transaction.take(), + race_state.nonces_to_submit_batch.clone(), at_block.clone(), nonces_range.clone(), proof.clone(), @@ -628,21 +722,6 @@ pub async fn run, TC: TargetClient

>( } } -impl Default - for RaceState -{ - fn default() -> Self { - RaceState { - best_finalized_source_header_id_at_source: None, - best_finalized_source_header_id_at_best_target: None, - best_target_header_id: None, - best_finalized_target_header_id: None, - nonces_to_submit: None, - nonces_submitted: None, - } - } -} - /// Print race progress. fn print_race_progress(prev_time: Instant, strategy: &S) -> Instant where @@ -670,7 +749,7 @@ where } async fn select_nonces_to_deliver( - race_state: RaceState, + race_state: impl RaceState, strategy: &Strategy, ) -> Option<(SourceHeaderId, RangeInclusive, Strategy::ProofParameters)> where @@ -678,7 +757,7 @@ where Strategy: RaceStrategy, { let best_finalized_source_header_id_at_best_target = - race_state.best_finalized_source_header_id_at_best_target.clone()?; + race_state.best_finalized_source_header_id_at_best_target()?; strategy .select_nonces_to_deliver(race_state) .await @@ -701,7 +780,7 @@ mod tests { // target node only knows about source' BEST_AT_TARGET block // source node has BEST_AT_SOURCE > BEST_AT_TARGET block - let mut race_state = RaceState::<_, _, ()> { + let mut race_state = RaceStateImpl::<_, _, (), ()> { best_finalized_source_header_id_at_source: Some(HeaderId( BEST_AT_SOURCE, BEST_AT_SOURCE, @@ -713,11 +792,12 @@ mod tests { best_target_header_id: Some(HeaderId(0, 0)), best_finalized_target_header_id: Some(HeaderId(0, 0)), nonces_to_submit: None, + nonces_to_submit_batch: None, nonces_submitted: None, }; // we have some nonces to deliver and they're generated at GENERATED_AT < BEST_AT_SOURCE - let mut strategy = BasicStrategy::new(); + let mut strategy = BasicStrategy::<_, _, _, _, _, ()>::new(); strategy.source_nonces_updated( HeaderId(GENERATED_AT, GENERATED_AT), SourceClientNonces { new_nonces: 0..=10, confirmed_nonce: None }, diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 479ffe5132907..e6016448c95cc 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -106,24 +106,25 @@ impl< /// at source blocks that are known to be finalized at the target node. /// /// Returns `None` if no entries may be delivered. - pub fn available_source_queue_indices( - &self, - race_state: RaceState< + pub fn available_source_queue_indices< + RS: RaceState< HeaderId, HeaderId, - Proof, >, + >( + &self, + race_state: RS, ) -> Option> { // if we do not know best nonce at target node, we can't select anything let best_target_nonce = self.best_target_nonce?; // if we have already selected nonces that we want to submit, do nothing - if race_state.nonces_to_submit.is_some() { + if race_state.nonces_to_submit().is_some() { return None } // if we already submitted some nonces, do nothing - if race_state.nonces_submitted.is_some() { + if race_state.nonces_submitted().is_some() { return None } @@ -143,7 +144,7 @@ impl< // // => let's first select range of entries inside deque that are already finalized at // the target client and pass this range to the selector - let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target?; + let best_header_at_target = race_state.best_finalized_source_header_id_at_best_target()?; let end_index = self .source_queue .iter() @@ -204,9 +205,15 @@ impl< self.source_queue.is_empty() } - fn required_source_header_at_target( + fn required_source_header_at_target< + RS: RaceState< + HeaderId, + HeaderId, + >, + >( &self, current_best: &HeaderId, + _race_state: RS, ) -> Option> { self.source_queue .back() @@ -247,46 +254,46 @@ impl< ) } - fn best_target_nonces_updated( - &mut self, - nonces: TargetClientNonces<()>, - race_state: &mut RaceState< + fn best_target_nonces_updated< + RS: RaceState< HeaderId, HeaderId, - Proof, >, + >( + &mut self, + nonces: TargetClientNonces<()>, + race_state: &mut RS, ) { let nonce = nonces.latest_nonce; let need_to_select_new_nonces = race_state - .nonces_to_submit - .as_ref() - .map(|(_, nonces, _)| *nonces.end() <= nonce) + .nonces_to_submit() + .map(|nonces| *nonces.end() <= nonce) .unwrap_or(false); if need_to_select_new_nonces { - race_state.nonces_to_submit = None; + race_state.reset_nonces_to_submit(); } let need_new_nonces_to_submit = race_state - .nonces_submitted - .as_ref() + .nonces_submitted() .map(|nonces| *nonces.end() <= nonce) .unwrap_or(false); if need_new_nonces_to_submit { - race_state.nonces_submitted = None; + race_state.reset_nonces_submitted(); } self.best_target_nonce = Some(nonce); } - fn finalized_target_nonces_updated( - &mut self, - nonces: TargetClientNonces<()>, - _race_state: &mut RaceState< + fn finalized_target_nonces_updated< + RS: RaceState< HeaderId, HeaderId, - Proof, >, + >( + &mut self, + nonces: TargetClientNonces<()>, + _race_state: &mut RS, ) { self.remove_le_nonces_from_source_queue(nonces.latest_nonce); self.best_target_nonce = Some(std::cmp::max( @@ -295,13 +302,14 @@ impl< )); } - async fn select_nonces_to_deliver( - &self, - race_state: RaceState< + async fn select_nonces_to_deliver< + RS: RaceState< HeaderId, HeaderId, - Proof, >, + >( + &self, + race_state: RS, ) -> Option<(RangeInclusive, Self::ProofParameters)> { let available_indices = self.available_source_queue_indices(race_state)?; let range_begin = std::cmp::max( @@ -317,15 +325,23 @@ impl< mod tests { use super::*; use crate::{ - message_lane::MessageLane, + message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::tests::{ header_id, TestMessageLane, TestMessagesProof, TestSourceHeaderHash, TestSourceHeaderNumber, }, + message_race_loop::RaceStateImpl, }; type SourceNoncesRange = RangeInclusive; + type TestRaceStateImpl = RaceStateImpl< + SourceHeaderIdOf, + TargetHeaderIdOf, + TestMessagesProof, + (), + >; + type BasicStrategy

= super::BasicStrategy<

::SourceHeaderNumber,

::SourceHeaderHash, @@ -357,7 +373,7 @@ mod tests { assert_eq!(strategy.best_at_source(), None); strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); assert_eq!(strategy.best_at_source(), None); - strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); + strategy.best_target_nonces_updated(target_nonces(10), &mut TestRaceStateImpl::default()); assert_eq!(strategy.source_queue, vec![(header_id(1), 1..=5)]); assert_eq!(strategy.best_at_source(), Some(10)); } @@ -365,7 +381,7 @@ mod tests { #[test] fn source_nonce_is_never_lower_than_known_target_nonce() { let mut strategy = BasicStrategy::::new(); - strategy.best_target_nonces_updated(target_nonces(10), &mut Default::default()); + strategy.best_target_nonces_updated(target_nonces(10), &mut TestRaceStateImpl::default()); strategy.source_nonces_updated(header_id(1), source_nonces(1..=5)); assert_eq!(strategy.source_queue, vec![]); } @@ -386,15 +402,17 @@ mod tests { strategy.source_nonces_updated(header_id(2), source_nonces(6..=10)); strategy.source_nonces_updated(header_id(3), source_nonces(11..=15)); strategy.source_nonces_updated(header_id(4), source_nonces(16..=20)); - strategy.finalized_target_nonces_updated(target_nonces(15), &mut Default::default()); + strategy + .finalized_target_nonces_updated(target_nonces(15), &mut TestRaceStateImpl::default()); assert_eq!(strategy.source_queue, vec![(header_id(4), 16..=20)]); - strategy.finalized_target_nonces_updated(target_nonces(17), &mut Default::default()); + strategy + .finalized_target_nonces_updated(target_nonces(17), &mut TestRaceStateImpl::default()); assert_eq!(strategy.source_queue, vec![(header_id(4), 18..=20)]); } #[test] fn selected_nonces_are_dropped_on_target_nonce_update() { - let mut state = RaceState::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); strategy.best_target_nonces_updated(target_nonces(7), &mut state); @@ -405,7 +423,7 @@ mod tests { #[test] fn submitted_nonces_are_dropped_on_target_nonce_update() { - let mut state = RaceState::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(5..=10); strategy.best_target_nonces_updated(target_nonces(7), &mut state); @@ -416,7 +434,7 @@ mod tests { #[async_std::test] async fn nothing_is_selected_if_something_is_already_selected() { - let mut state = RaceState::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 1..=10, (1..=10, None))); strategy.best_target_nonces_updated(target_nonces(0), &mut state); @@ -426,7 +444,7 @@ mod tests { #[async_std::test] async fn nothing_is_selected_if_something_is_already_submitted() { - let mut state = RaceState::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(1..=10); strategy.best_target_nonces_updated(target_nonces(0), &mut state); @@ -436,7 +454,7 @@ mod tests { #[async_std::test] async fn select_nonces_to_deliver_works() { - let mut state = RaceState::<_, _, TestMessagesProof>::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=1)); @@ -457,7 +475,7 @@ mod tests { #[test] fn available_source_queue_indices_works() { - let mut state = RaceState::<_, _, TestMessagesProof>::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=3)); @@ -482,7 +500,7 @@ mod tests { #[test] fn remove_le_nonces_from_source_queue_works() { - let mut state = RaceState::<_, _, TestMessagesProof>::default(); + let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); strategy.best_target_nonces_updated(target_nonces(0), &mut state); strategy.source_nonces_updated(header_id(1), source_nonces(1..=3)); @@ -518,12 +536,13 @@ mod tests { let target_header_1 = header_id(1); // we start in perfec sync state - all headers are synced and finalized on both ends - let mut state = RaceState::<_, _, TestMessagesProof> { + let mut state = TestRaceStateImpl { best_finalized_source_header_id_at_source: Some(source_header_1), best_finalized_source_header_id_at_best_target: Some(source_header_1), best_target_header_id: Some(target_header_1), best_finalized_target_header_id: Some(target_header_1), nonces_to_submit: None, + nonces_to_submit_batch: None, nonces_submitted: None, }; From 61642d4eaf47a29e678469469de66f22f4f3795e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 15 Mar 2023 14:39:28 +0300 Subject: [PATCH 0987/1210] enable relayer rewards metrics at bridge hubs (#1965) --- primitives/chain-bridge-hub-rococo/src/lib.rs | 4 ++++ primitives/chain-bridge-hub-wococo/src/lib.rs | 4 ++++ relays/client-bridge-hub-rococo/src/lib.rs | 3 ++- relays/client-bridge-hub-wococo/src/lib.rs | 3 ++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 633a021b63427..936e4d1beb7f8 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -74,5 +74,9 @@ pub const BRIDGE_HUB_ROCOCO_PARACHAIN_ID: u32 = 1013; /// Name of the With-BridgeHubRococo messages pallet instance that is deployed at bridged chains. pub const WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessages"; +/// Name of the With-BridgeHubRococo bridge-relayers pallet instance that is deployed at bridged +/// chains. +pub const WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; + decl_bridge_finality_runtime_apis!(bridge_hub_rococo); decl_bridge_messages_runtime_apis!(bridge_hub_rococo); diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index e04ca3ff22806..00704995c5ebf 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -64,5 +64,9 @@ pub const BRIDGE_HUB_WOCOCO_PARACHAIN_ID: u32 = 1014; /// Name of the With-BridgeHubWococo messages pallet instance that is deployed at bridged chains. pub const WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; +/// Name of the With-BridgeHubWococo bridge-relayers pallet instance that is deployed at bridged +/// chains. +pub const WITH_BRIDGE_HUB_WOCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; + decl_bridge_finality_runtime_apis!(bridge_hub_wococo); decl_bridge_messages_runtime_apis!(bridge_hub_wococo); diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 02c389ffa29d2..a8238454e74ec 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -123,7 +123,8 @@ impl ChainWithTransactions for BridgeHubRococo { impl ChainWithMessages for BridgeHubRococo { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME; - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = + Some(bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME); const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 359692b0e3f9a..27729737310a8 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -123,7 +123,8 @@ impl ChainWithTransactions for BridgeHubWococo { impl ChainWithMessages for BridgeHubWococo { const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = bp_bridge_hub_wococo::WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME; - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = + Some(bp_bridge_hub_wococo::WITH_BRIDGE_HUB_WOCOCO_RELAYERS_PALLET_NAME); const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_wococo::TO_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; From 9fde0a90fc8cbe0ba7efe4950aae06ffb9453fa7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 16 Mar 2023 14:48:27 +0300 Subject: [PATCH 0988/1210] added UpdatedBestFinalizedHeader event to pallet-bridge-grandpa (#1967) --- bin/millau/runtime/src/lib.rs | 6 ++- bin/rialto-parachain/runtime/src/lib.rs | 3 +- bin/rialto/runtime/src/lib.rs | 3 +- bin/runtime-common/src/mock.rs | 3 +- modules/grandpa/src/lib.rs | 42 +++++++++++++-- modules/grandpa/src/mock.rs | 5 +- modules/parachains/src/lib.rs | 72 ++++++++++++++++++++----- modules/parachains/src/mock.rs | 6 ++- 8 files changed, 114 insertions(+), 26 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 21fff0e564e4c..574b0569875c6 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -393,6 +393,7 @@ impl pallet_bridge_relayers::Config for Runtime { pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_rialto::Rialto; // This is a pretty unscientific cap. // @@ -405,6 +406,7 @@ impl pallet_bridge_grandpa::Config for Runtime { pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_westend::Westend; type MaxRequests = ConstU32<50>; type HeadersToKeep = ConstU32<{ bp_westend::DAYS }>; @@ -559,11 +561,11 @@ construct_runtime!( // Rialto bridge modules. BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, // Westend bridge modules. - BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage}, + BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage, Event}, BridgeWestendParachains: pallet_bridge_parachains::::{Pallet, Call, Storage, Event}, // RialtoParachain bridge modules. diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index d8e087c5a6a9e..2621b0096a7f4 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -525,6 +525,7 @@ impl pallet_bridge_relayers::Config for Runtime { pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_millau::Millau; /// This is a pretty unscientific cap. /// @@ -604,7 +605,7 @@ construct_runtime!( // Millau bridge modules. BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, } ); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9db181e284035..bdc205bec1405 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -390,6 +390,7 @@ impl pallet_bridge_relayers::Config for Runtime { pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_millau::Millau; /// This is a pretty unscientific cap. /// @@ -479,7 +480,7 @@ construct_runtime!( // Millau bridge modules. BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, // Millau bridge modules (BEEFY based). diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index c2cd8e9ba8308..056fd3a2ccf09 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -107,7 +107,7 @@ frame_support::construct_runtime! { Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage}, + BridgeGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, BridgeParachains: pallet_bridge_parachains::{Pallet, Call, Storage, Event}, BridgeMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, } @@ -194,6 +194,7 @@ impl pallet_transaction_payment::Config for TestRuntime { } impl pallet_bridge_grandpa::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = BridgedUnderlyingChain; type MaxRequests = ConstU32<50>; type HeadersToKeep = ConstU32<8>; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 2b9e49d4c95e1..2d81f3106fc9d 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -96,6 +96,10 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + + IsType<::RuntimeEvent>; + /// The chain we are bridging to here. type BridgedChain: ChainWithGrandpa; @@ -164,19 +168,19 @@ pub mod pallet { ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); - let (hash, number) = (finality_target.hash(), finality_target.number()); + let (hash, number) = (finality_target.hash(), *finality_target.number()); log::trace!( target: LOG_TARGET, "Going to try and finalize header {:?}", finality_target ); - SubmitFinalityProofHelper::::check_obsolete(*number)?; + SubmitFinalityProofHelper::::check_obsolete(number)?; let authority_set = >::get(); let unused_proof_size = authority_set.unused_proof_size(); let set_id = authority_set.set_id; - verify_justification::(&justification, hash, *number, authority_set.into())?; + verify_justification::(&justification, hash, number, authority_set.into())?; let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; @@ -212,6 +216,8 @@ pub mod pallet { let actual_weight = pre_dispatch_weight .set_proof_size(pre_dispatch_weight.proof_size().saturating_sub(unused_proof_size)); + Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash }); + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } @@ -370,6 +376,16 @@ pub mod pallet { } } + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event, I: 'static = ()> { + /// Best finalized chain header has been updated to the header with given number and hash. + UpdatedBestFinalizedHeader { + number: BridgedBlockNumber, + hash: BridgedBlockHash, + }, + } + #[pallet::error] pub enum Error { /// The given justification is invalid for the given header. @@ -635,8 +651,8 @@ pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader mod tests { use super::*; use crate::mock::{ - run_test, test_header, RuntimeOrigin, TestBridgedChain, TestHeader, TestNumber, - TestRuntime, MAX_BRIDGED_AUTHORITIES, + run_test, test_header, RuntimeEvent as TestEvent, RuntimeOrigin, System, TestBridgedChain, + TestHeader, TestNumber, TestRuntime, MAX_BRIDGED_AUTHORITIES, }; use bp_header_chain::BridgeGrandpaCall; use bp_runtime::BasicOperatingMode; @@ -649,10 +665,14 @@ mod tests { assert_err, assert_noop, assert_ok, dispatch::PostDispatchInfo, storage::generator::StorageValue, }; + use frame_system::{EventRecord, Phase}; use sp_core::Get; use sp_runtime::{Digest, DigestItem, DispatchError}; fn initialize_substrate_bridge() { + System::set_block_number(1); + System::reset_events(); + assert_ok!(init_with_origin(RuntimeOrigin::root())); } @@ -847,6 +867,18 @@ mod tests { let header = test_header(1); assert_eq!(>::get().unwrap().1, header.hash()); assert!(>::contains_key(header.hash())); + + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { + number: *header.number(), + hash: header.hash(), + }), + topics: vec![], + }], + ); }) } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index acedfc3582c24..b10f5d86c3de2 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -49,7 +49,7 @@ construct_runtime! { UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Grandpa: grandpa::{Pallet, Call}, + Grandpa: grandpa::{Pallet, Call, Event}, } } @@ -69,7 +69,7 @@ impl frame_system::Config for TestRuntime { type AccountId = AccountId; type Lookup = IdentityLookup; type Header = Header; - type RuntimeEvent = (); + type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<250>; type Version = (); type PalletInfo = PalletInfo; @@ -94,6 +94,7 @@ parameter_types! { } impl grandpa::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = TestBridgedChain; type MaxRequests = MaxRequests; type HeadersToKeep = HeadersToKeep; diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 20a9ef9b95bd3..e72e2aec8c202 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -735,14 +735,18 @@ mod tests { }, ) .unwrap(); + + System::::set_block_number(1); + System::::reset_events(); } - fn proceed(num: RelayBlockNumber, state_root: RelayBlockHash) { + fn proceed(num: RelayBlockNumber, state_root: RelayBlockHash) -> ParaHash { pallet_bridge_grandpa::Pallet::::on_initialize( 0, ); let header = test_relay_header(num, state_root); + let hash = header.hash(); let justification = make_default_justification(&header); assert_ok!( pallet_bridge_grandpa::Pallet::::submit_finality_proof( @@ -751,6 +755,8 @@ mod tests { justification, ) ); + + hash } fn prepare_parachain_heads_proof( @@ -1010,7 +1016,7 @@ mod tests { ); // import head#10 of parachain#1 at relay block #1 - proceed(1, state_root_10); + let relay_1_hash = proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( ParasInfo::::get(ParaId(1)), @@ -1043,6 +1049,16 @@ mod tests { }), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Grandpa1( + pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { + number: 1, + hash: relay_1_hash, + } + ), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: TestEvent::Parachains(Event::UpdatedParachainHead { @@ -1155,7 +1171,7 @@ mod tests { // try to import head#0 of parachain#1 at relay block#1 // => call succeeds, but nothing is changed - proceed(1, state_root); + let relay_1_hash = proceed(1, state_root); assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); assert_eq!( @@ -1169,6 +1185,16 @@ mod tests { }), topics: vec![], }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Grandpa1( + pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { + number: 1, + hash: relay_1_hash, + } + ), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: TestEvent::Parachains(Event::RejectedObsoleteParachainHead { @@ -1193,7 +1219,7 @@ mod tests { initialize(state_root_5); // head#10 of parachain#1 at relay block#1 - proceed(1, state_root_10); + let relay_1_hash = proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( ParasInfo::::get(ParaId(1)), @@ -1207,14 +1233,26 @@ mod tests { ); assert_eq!( System::::events(), - vec![EventRecord { - phase: Phase::Initialization, - event: TestEvent::Parachains(Event::UpdatedParachainHead { - parachain: ParaId(1), - parachain_head_hash: head_data(1, 10).hash(), - }), - topics: vec![], - }], + vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Grandpa1( + pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { + number: 1, + hash: relay_1_hash, + } + ), + topics: vec![], + }, + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Parachains(Event::UpdatedParachainHead { + parachain: ParaId(1), + parachain_head_hash: head_data(1, 10).hash(), + }), + topics: vec![], + } + ], ); // now try to import head#5 at relay block#0 @@ -1233,6 +1271,16 @@ mod tests { assert_eq!( System::::events(), vec![ + EventRecord { + phase: Phase::Initialization, + event: TestEvent::Grandpa1( + pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { + number: 1, + hash: relay_1_hash, + } + ), + topics: vec![], + }, EventRecord { phase: Phase::Initialization, event: TestEvent::Parachains(Event::UpdatedParachainHead { diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 83d347018e45e..c19ce98eba2fe 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -150,8 +150,8 @@ construct_runtime! { UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - Grandpa1: pallet_bridge_grandpa::::{Pallet}, - Grandpa2: pallet_bridge_grandpa::::{Pallet}, + Grandpa1: pallet_bridge_grandpa::::{Pallet, Event}, + Grandpa2: pallet_bridge_grandpa::::{Pallet, Event}, Parachains: pallet_bridge_parachains::{Call, Pallet, Event}, } } @@ -197,6 +197,7 @@ parameter_types! { } impl pallet_bridge_grandpa::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = TestBridgedChain; type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; @@ -204,6 +205,7 @@ impl pallet_bridge_grandpa::Config for TestRun } impl pallet_bridge_grandpa::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; type BridgedChain = TestBridgedChain; type MaxRequests = ConstU32<2>; type HeadersToKeep = HeadersToKeep; From e5700e2e270d54fd8212f8eb981fe39378c3f56b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 17 Mar 2023 17:13:44 +0300 Subject: [PATCH 0989/1210] move signed extension stuff from prolkadot-core primitives to bridge-hub-cumulus-primitives (#1968) --- bin/rialto-parachain/runtime/src/lib.rs | 55 ++++++- .../chain-bridge-hub-cumulus/src/lib.rs | 89 +++++++----- primitives/chain-rialto-parachain/Cargo.toml | 2 + primitives/chain-rialto-parachain/src/lib.rs | 4 +- primitives/polkadot-core/src/lib.rs | 137 ------------------ primitives/runtime/src/extensions.rs | 9 +- relays/client-bridge-hub-rococo/src/lib.rs | 12 +- .../src/runtime_wrapper.rs | 7 +- relays/client-bridge-hub-wococo/src/lib.rs | 12 +- .../src/runtime_wrapper.rs | 7 +- relays/client-rialto-parachain/Cargo.toml | 1 + relays/client-rialto-parachain/src/lib.rs | 2 +- 12 files changed, 127 insertions(+), 210 deletions(-) diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 2621b0096a7f4..3614bacdc10ad 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -28,14 +28,19 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); use crate::millau_messages::{WithMillauMessageBridge, XCM_LANE}; -use bridge_runtime_common::messages::source::{XcmBridge, XcmBridgeAdapter}; +use bridge_runtime_common::{ + generate_bridge_reject_obsolete_headers_and_messages, + messages::source::{XcmBridge, XcmBridgeAdapter}, +}; +use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::AnyRelayNumber; +use scale_info::TypeInfo; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT}, - transaction_validity::{TransactionSource, TransactionValidity}, + traits::{AccountIdLookup, Block as BlockT, DispatchInfoOf, SignedExtension}, + transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, ApplyExtrinsicResult, }; @@ -93,6 +98,44 @@ use xcm_executor::{Config, XcmExecutor}; pub mod millau_messages; +// generate signed extension that rejects obsolete bridge transactions +generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Grandpa + BridgeMillauGrandpa, + // Messages + BridgeMillauMessages +} + +/// Dummy signed extension that does nothing. +/// +/// We're using it to have the same set of signed extensions on all parachains with bridge pallets +/// deployed (bridge hubs and rialto parachain). +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub struct DummyBridgeRefundMillauMessages; + +impl SignedExtension for DummyBridgeRefundMillauMessages { + const IDENTIFIER: &'static str = "DummyBridgeRefundMillauMessages"; + type AccountId = AccountId; + type Call = RuntimeCall; + type AdditionalSigned = (); + type Pre = (); + + fn additional_signed(&self) -> Result { + Ok(()) + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } +} + /// The address format for describing accounts. pub type Address = MultiAddress; /// Block type as expected by this runtime. @@ -111,6 +154,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + DummyBridgeRefundMillauMessages, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = @@ -909,9 +954,11 @@ mod tests { frame_system::CheckNonce::from(10), frame_system::CheckWeight::new(), pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages, + DummyBridgeRefundMillauMessages, ); let indirect_payload = bp_rialto_parachain::SignedExtension::new( - ((), (), (), (), Era::Immortal, 10.into(), (), 10.into()), + ((), (), (), (), Era::Immortal, 10.into(), (), 10.into(), (), ()), None, ); assert_eq!(payload.encode(), indirect_payload.encode()); diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index cbdd36c2e4ae3..5a745fdaba470 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -16,12 +16,18 @@ #![cfg_attr(not(feature = "std"), no_std)] -use bp_messages::*; pub use bp_polkadot_core::{ AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, }; + +use bp_messages::*; +use bp_runtime::extensions::{ + BridgeRejectObsoleteHeadersAndMessages, ChargeTransactionPayment, CheckEra, CheckGenesis, + CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, CheckWeight, + GenericSignedExtension, RefundBridgedParachainMessagesSchema, +}; use frame_support::{ dispatch::DispatchClass, parameter_types, @@ -94,8 +100,6 @@ pub type AccountSigner = MultiSigner; /// The address format for describing accounts. pub type Address = MultiAddress; -pub use bp_polkadot_core::BridgeSignedExtension as SignedExtension; - // Note about selecting values of two following constants: // // Normal transactions have limit of 75% of 1/2 second weight for Cumulus parachains. Let's keep @@ -125,37 +129,54 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane for Cumulus-based parachains. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; -/// Module with rewarding bridge signed extension support -pub mod rewarding_bridge_signed_extension { - use super::*; - use bp_polkadot_core::PolkadotLike; - use bp_runtime::extensions::*; - - type RewardingBridgeSignedExtra = ( - CheckNonZeroSender, - CheckSpecVersion, - CheckTxVersion, - CheckGenesis, - CheckEra, - CheckNonce, - CheckWeight, - ChargeTransactionPayment, - BridgeRejectObsoleteHeadersAndMessages, - RefundBridgedParachainMessagesSchema, - ); +/// Extra signed extension data that is used by all bridge hubs. +pub type SignedExtra = ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + RefundBridgedParachainMessagesSchema, +); + +/// Signed extension that is used by all bridge hubs. +pub type SignedExtension = GenericSignedExtension; + +/// Helper trait to define some extra methods on bridge hubs signed extension (and +/// overcome Rust limitations). +pub trait BridgeHubSignedExtension { + /// Create signed extension from its components. + fn from_params( + spec_version: u32, + transaction_version: u32, + era: bp_runtime::TransactionEra, + genesis_hash: Hash, + nonce: Index, + tip: Balance, + ) -> Self; - /// The signed extension used by Cumulus and Cumulus-like parachain with bridging and rewarding. - pub type RewardingBridgeSignedExtension = GenericSignedExtension; + /// Return transaction nonce. + fn nonce(&self) -> Index; + + /// Return transaction tip. + fn tip(&self) -> Balance; +} - pub fn from_params( +impl BridgeHubSignedExtension for SignedExtension { + /// Create signed extension from its components. + fn from_params( spec_version: u32, transaction_version: u32, - era: bp_runtime::TransactionEraOf, + era: bp_runtime::TransactionEra, genesis_hash: Hash, - nonce: Nonce, + nonce: Index, tip: Balance, - ) -> RewardingBridgeSignedExtension { - GenericSignedExtension::::new( + ) -> Self { + GenericSignedExtension::new( ( (), // non-zero sender (), // spec version @@ -166,7 +187,7 @@ pub mod rewarding_bridge_signed_extension { (), // Check weight tip.into(), // transaction payment / tip (compact encoding) (), // bridge reject obsolete headers and msgs - (), // bridge register reward to relayer for message passing + (), // bridge reward to relayer for message passing ), Some(( (), @@ -183,13 +204,13 @@ pub mod rewarding_bridge_signed_extension { ) } - /// Return signer nonce, used to craft transaction. - pub fn nonce(sign_ext: &RewardingBridgeSignedExtension) -> Nonce { - sign_ext.payload.5.into() + /// Return transaction nonce. + fn nonce(&self) -> Index { + self.payload.5 .0 } /// Return transaction tip. - pub fn tip(sign_ext: &RewardingBridgeSignedExtension) -> Balance { - sign_ext.payload.7.into() + fn tip(&self) -> Balance { + self.payload.7 .0 } } diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index ed7c5c0796002..3335c6bcc4109 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # Bridge Dependencies +bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } bp-messages = { path = "../messages", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } @@ -26,6 +27,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [features] default = ["std"] std = [ + "bp-bridge-hub-cumulus/std", "bp-messages/std", "bp-runtime/std", "frame-support/std", diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index e49f3d14dc5f2..67b1a135f34a9 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -133,7 +133,9 @@ impl Parachain for RialtoParachain { const PARACHAIN_ID: u32 = RIALTO_PARACHAIN_ID; } -pub use bp_polkadot_core::DefaultSignedExtension as SignedExtension; +// Technically this is incorrect, because rialto-parachain isn't a bridge hub, but we're +// trying to keep it close to the bridge hubs code (at least in this aspect). +pub use bp_bridge_hub_cumulus::SignedExtension; frame_support::parameter_types! { pub BlockLength: limits::BlockLength = diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 10da6cd9b3555..eae2d49a6fdbe 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -37,7 +37,6 @@ use sp_runtime::{ use sp_std::prelude::Vec; // Re-export's to avoid extra substrate dependencies in chain-specific crates. -use bp_runtime::extensions::*; pub use frame_support::{weights::constants::ExtrinsicBaseWeight, Parameter}; pub use sp_runtime::{traits::Convert, Perbill}; @@ -252,142 +251,6 @@ impl Chain for PolkadotLike { } } -/// Some functionality associated with the default signed extension used by Polkadot and -/// Polkadot-like chains. -pub trait PolkadotSignedExtension { - fn from_params( - spec_version: u32, - transaction_version: u32, - era: bp_runtime::TransactionEraOf, - genesis_hash: Hash, - nonce: Nonce, - tip: Balance, - ) -> Self; - - fn nonce(&self) -> Nonce; - - fn tip(&self) -> Balance; -} - -type DefaultSignedExtra = ( - CheckNonZeroSender, - CheckSpecVersion, - CheckTxVersion, - CheckGenesis, - CheckEra, - CheckNonce, - CheckWeight, - ChargeTransactionPayment, -); - -/// The default signed extension used by Polkadot and Polkadot-like chains. -pub type DefaultSignedExtension = GenericSignedExtension; - -impl PolkadotSignedExtension for DefaultSignedExtension { - fn from_params( - spec_version: u32, - transaction_version: u32, - era: bp_runtime::TransactionEraOf, - genesis_hash: Hash, - nonce: Nonce, - tip: Balance, - ) -> Self { - Self::new( - ( - (), // non-zero sender - (), // spec version - (), // tx version - (), // genesis - era.frame_era(), // era - nonce.into(), // nonce (compact encoding) - (), // Check weight - tip.into(), // transaction payment / tip (compact encoding) - ), - Some(( - (), - spec_version, - transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), - (), - (), - (), - )), - ) - } - - /// Return signer nonce, used to craft transaction. - fn nonce(&self) -> Nonce { - self.payload.5.into() - } - - /// Return transaction tip. - fn tip(&self) -> Balance { - self.payload.7.into() - } -} - -type BridgeSignedExtra = ( - CheckNonZeroSender, - CheckSpecVersion, - CheckTxVersion, - CheckGenesis, - CheckEra, - CheckNonce, - CheckWeight, - ChargeTransactionPayment, - BridgeRejectObsoleteHeadersAndMessages, -); - -/// The default signed extension used by Polkadot and Polkadot-like chains with bridging. -pub type BridgeSignedExtension = GenericSignedExtension; - -impl PolkadotSignedExtension for BridgeSignedExtension { - fn from_params( - spec_version: u32, - transaction_version: u32, - era: bp_runtime::TransactionEraOf, - genesis_hash: Hash, - nonce: Nonce, - tip: Balance, - ) -> Self { - Self::new( - ( - (), // non-zero sender - (), // spec version - (), // tx version - (), // genesis - era.frame_era(), // era - nonce.into(), // nonce (compact encoding) - (), // Check weight - tip.into(), // transaction payment / tip (compact encoding) - (), // bridge reject obsolete headers and msgs - ), - Some(( - (), - spec_version, - transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), - (), - (), - (), - (), - )), - ) - } - - /// Return signer nonce, used to craft transaction. - fn nonce(&self) -> Nonce { - self.payload.5.into() - } - - /// Return transaction tip. - fn tip(&self) -> Balance { - self.payload.7.into() - } -} - /// Provides a storage key for account data. /// /// We need to use this approach when we don't have access to the runtime. diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index ea51d03741c63..96ee9d1e6ec91 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -16,7 +16,6 @@ //! Primitives that may be used for creating signed extensions for indirect runtimes. -use crate::{BalanceOf, HashOf}; use codec::{Compact, Decode, Encode}; use impl_trait_for_tuples::impl_for_tuples; use scale_info::{StaticTypeInfo, TypeInfo}; @@ -59,19 +58,19 @@ pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>; pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>; /// The `SignedExtensionSchema` for `frame_system::CheckGenesis`. -pub type CheckGenesis = GenericSignedExtensionSchema<(), HashOf>; +pub type CheckGenesis = GenericSignedExtensionSchema<(), Hash>; /// The `SignedExtensionSchema` for `frame_system::CheckEra`. -pub type CheckEra = GenericSignedExtensionSchema>; +pub type CheckEra = GenericSignedExtensionSchema; /// The `SignedExtensionSchema` for `frame_system::CheckNonce`. -pub type CheckNonce = GenericSignedExtensionSchema, ()>; +pub type CheckNonce = GenericSignedExtensionSchema, ()>; /// The `SignedExtensionSchema` for `frame_system::CheckWeight`. pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; /// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. -pub type ChargeTransactionPayment = GenericSignedExtensionSchema>, ()>; +pub type ChargeTransactionPayment = GenericSignedExtensionSchema, ()>; /// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index a8238454e74ec..87d461b976109 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. -use bp_bridge_hub_rococo::AVERAGE_BLOCK_INTERVAL; +use bp_bridge_hub_rococo::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; use bp_runtime::ChainId; use codec::Encode; @@ -73,7 +73,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::rewarding_bridge_signed_extension::from_params( + runtime::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -110,13 +110,7 @@ impl ChainWithTransactions for BridgeHubRococo { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some( - UnsignedTransaction::new( - tx.function, - runtime::rewarding_bridge_signed_extension::nonce(extra), - ) - .tip(runtime::rewarding_bridge_signed_extension::tip(extra)), - ) + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) } } diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index 711306b0127fe..26e0bd9da5e29 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -19,17 +19,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -pub use bp_bridge_hub_rococo::rewarding_bridge_signed_extension; +pub use bp_bridge_hub_rococo::SignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubRococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic< - Call, - rewarding_bridge_signed_extension::RewardingBridgeSignedExtension, ->; +pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; // The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 27729737310a8..e9864bf98857a 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_bridge_hub_wococo::AVERAGE_BLOCK_INTERVAL; +use bp_bridge_hub_wococo::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; use bp_runtime::ChainId; use codec::Encode; @@ -73,7 +73,7 @@ impl ChainWithTransactions for BridgeHubWococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::rewarding_bridge_signed_extension::from_params( + runtime::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -110,13 +110,7 @@ impl ChainWithTransactions for BridgeHubWococo { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some( - UnsignedTransaction::new( - tx.function, - runtime::rewarding_bridge_signed_extension::nonce(extra), - ) - .tip(runtime::rewarding_bridge_signed_extension::tip(extra)), - ) + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) } } diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index 374dd5b44ce8c..b9803955922db 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -19,17 +19,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -pub use bp_bridge_hub_wococo::rewarding_bridge_signed_extension; +pub use bp_bridge_hub_wococo::SignedExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubWococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic< - Call, - rewarding_bridge_signed_extension::RewardingBridgeSignedExtension, ->; +pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; // The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 807da290d249c..02a9c70ce5e5d 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -12,6 +12,7 @@ subxt = { git = "https://github.com/paritytech/subxt", branch = "master", defaul # Bridge dependencies +bp-bridge-hub-cumulus = { path = "../../primitives/chain-bridge-hub-cumulus" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-millau = { path = "../../primitives/chain-millau" } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 27673dc23be1d..5334c59d3c190 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; +use bp_bridge_hub_cumulus::BridgeHubSignedExtension; use bp_messages::MessageNonce; -use bp_polkadot_core::PolkadotSignedExtension; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ From 10688d21f8ea4937091a49ee37ad834438cacacb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 02:59:30 +0000 Subject: [PATCH 0990/1210] Bump trie-db from 0.26.0 to 0.27.1 Bumps [trie-db](https://github.com/paritytech/trie) from 0.26.0 to 0.27.1. - [Release notes](https://github.com/paritytech/trie/releases) - [Commits](https://github.com/paritytech/trie/compare/trie-db-v0.26.0...trie-db-v0.27.1) --- updated-dependencies: - dependency-name: trie-db dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 3cd2fdd35ca4f..5ec7a353fdfe3 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master 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 } -trie-db = { version = "0.26.0", default-features = false } +trie-db = { version = "0.27.1", default-features = false } [dev-dependencies] hex-literal = "0.3" From 6144a34c368f978d892e86963168e47c978a2bd1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 03:00:18 +0000 Subject: [PATCH 0991/1210] Bump async-trait from 0.1.66 to 0.1.67 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.66 to 0.1.67. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.66...0.1.67) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 5481ce7edf870..d683c131b6e4e 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.66" +async-trait = "0.1.67" futures = "0.3.27" log = "0.4.17" relay-utils = { path = "../utils" } From b6b44aea88943dcbd2e05a45e22eba22188ac1f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 03:05:59 +0000 Subject: [PATCH 0992/1210] Bump finality-grandpa from 0.16.1 to 0.16.2 Bumps [finality-grandpa](https://github.com/paritytech/finality-grandpa) from 0.16.1 to 0.16.2. - [Release notes](https://github.com/paritytech/finality-grandpa/releases) - [Commits](https://github.com/paritytech/finality-grandpa/compare/v0.16.1...v0.16.2) --- updated-dependencies: - dependency-name: finality-grandpa dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- modules/grandpa/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 095c1d9f4e4b1..0a737ef633a85 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -finality-grandpa = { version = "0.16.0", default-features = false } +finality-grandpa = { version = "0.16.2", default-features = false } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 0335836e328b4..ca2f4ad88d309 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -finality-grandpa = { version = "0.16.0", default-features = false } +finality-grandpa = { version = "0.16.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 8307534093f1f..5ed835857d1c2 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-header-chain = { path = "../header-chain", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } -finality-grandpa = { version = "0.16.0", default-features = false } +finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 86974b282d9d6..b7453c7aef002 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -66,4 +66,4 @@ bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempfile = "3.4" -finality-grandpa = { version = "0.16.0" } +finality-grandpa = { version = "0.16.2" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 9c336056dc644..387c67cbcc80e 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -24,7 +24,7 @@ bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-relayers = { path = "../../primitives/relayers" } bridge-runtime-common = { path = "../../bin/runtime-common" } -finality-grandpa = { version = "0.16.0" } +finality-grandpa = { version = "0.16.2" } finality-relay = { path = "../finality" } parachains-relay = { path = "../parachains" } relay-utils = { path = "../utils" } From 976f3c7fc1011b61a7aef85f3aa40f4222afefa3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 03:06:46 +0000 Subject: [PATCH 0993/1210] Bump clap from 4.1.8 to 4.1.11 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.8 to 4.1.11. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.1.8...v4.1.11) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index cca94bbe7b10e..063fedc5e64dd 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.6", features = ["derive"] } +clap = { version = "4.1.11", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.94" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 4cdaa93bad0ef..84e804f484e25 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.1.6", features = ["derive"] } +clap = { version = "4.1.11", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index be83e02424aa2..8658dd95ec5e6 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.6", features = ["derive"] } +clap = { version = "4.1.11", features = ["derive"] } serde_json = "1.0.94" # Bridge dependencies From 3b87aaffc7a97e63fb114ba173534703dce15adb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 06:55:22 +0000 Subject: [PATCH 0994/1210] Bump thiserror from 1.0.39 to 1.0.40 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.39 to 1.0.40. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.39...1.0.40) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 1a80a54f96555..ce83817a9956a 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -16,7 +16,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.1.1", features = ["derive"] } tokio = { version = "1.26", features = ["rt-multi-thread"] } -thiserror = "1.0.39" +thiserror = "1.0.40" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 387c67cbcc80e..17c75220f6d38 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.39" +thiserror = "1.0.40" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index d8b66db2abcac..91bd9e20d6594 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1.0" sysinfo = "0.28" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.26", features = ["rt"] } -thiserror = "1.0.39" +thiserror = "1.0.40" # Bridge dependencies From 12baac981d9e3772210c29a5063dfe772d472fb8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 20 Mar 2023 17:49:48 +0300 Subject: [PATCH 0995/1210] Kusama <> Polkadot relay prototype (#1982) * moved bridge declarations to dedicated folder * Kusama <> Polkadot bridges declaration * support for Kusama <> Polkadot bridge in CLI * update dictionary --- primitives/chain-bridge-hub-kusama/Cargo.toml | 31 ++++ primitives/chain-bridge-hub-kusama/src/lib.rs | 84 +++++++++ .../chain-bridge-hub-polkadot/Cargo.toml | 32 ++++ .../chain-bridge-hub-polkadot/src/lib.rs | 75 ++++++++ primitives/chain-kusama/src/lib.rs | 3 + primitives/chain-polkadot/src/lib.rs | 3 + primitives/runtime/src/lib.rs | 71 ++------ relays/bin-substrate/Cargo.toml | 4 + ..._kusama_messages_to_bridge_hub_polkadot.rs | 65 +++++++ ..._polkadot_messages_to_bridge_hub_kusama.rs | 65 +++++++ .../kusama_headers_to_bridge_hub_polkadot.rs | 72 ++++++++ ...usama_parachains_to_bridge_hub_polkadot.rs | 75 ++++++++ .../src/bridges/kusama_polkadot/mod.rs | 24 +++ .../polkadot_headers_to_bridge_hub_kusama.rs | 72 ++++++++ ...olkadot_parachains_to_bridge_hub_kusama.rs | 75 ++++++++ relays/bin-substrate/src/bridges/mod.rs | 23 +++ .../millau_headers_to_rialto.rs | 3 +- .../millau_messages_to_rialto.rs | 0 .../src/bridges/rialto_millau/mod.rs | 22 +++ .../rialto_headers_to_millau.rs | 3 +- .../rialto_messages_to_millau.rs | 0 .../millau_headers_to_rialto_parachain.rs | 2 +- .../millau_messages_to_rialto_parachain.rs | 0 .../bridges/rialto_parachain_millau/mod.rs | 22 +++ .../rialto_parachain_messages_to_millau.rs | 0 .../rialto_parachains_to_millau.rs | 5 +- ...ub_rococo_messages_to_bridge_hub_wococo.rs | 0 ...ub_wococo_messages_to_bridge_hub_rococo.rs | 0 .../src/bridges/rococo_wococo/mod.rs | 24 +++ .../rococo_headers_to_bridge_hub_wococo.rs | 0 .../rococo_parachains_to_bridge_hub_wococo.rs | 4 +- .../wococo_headers_to_bridge_hub_rococo.rs | 0 .../wococo_parachains_to_bridge_hub_rococo.rs | 4 +- .../src/bridges/westend_millau/mod.rs | 20 +++ .../westend_headers_to_millau.rs | 0 .../westend_parachains_to_millau.rs | 3 +- relays/bin-substrate/src/chains/kusama.rs | 32 ++++ relays/bin-substrate/src/chains/mod.rs | 19 +- relays/bin-substrate/src/chains/polkadot.rs | 32 ++++ relays/bin-substrate/src/cli/bridge.rs | 7 +- relays/bin-substrate/src/cli/init_bridge.rs | 18 +- relays/bin-substrate/src/cli/relay_headers.rs | 30 +++- .../src/cli/relay_headers_and_messages/mod.rs | 20 ++- .../bin-substrate/src/cli/relay_messages.rs | 30 +++- .../bin-substrate/src/cli/relay_parachains.rs | 46 +++-- relays/bin-substrate/src/cli/send_message.rs | 20 ++- relays/bin-substrate/src/main.rs | 1 + relays/client-bridge-hub-kusama/Cargo.toml | 28 +++ relays/client-bridge-hub-kusama/src/lib.rs | 162 ++++++++++++++++++ .../src/runtime_wrapper.rs | 74 ++++++++ relays/client-bridge-hub-polkadot/Cargo.toml | 32 ++++ relays/client-bridge-hub-polkadot/src/lib.rs | 160 +++++++++++++++++ .../src/runtime_wrapper.rs | 119 +++++++++++++ relays/client-bridge-hub-rococo/src/lib.rs | 1 - relays/client-bridge-hub-wococo/src/lib.rs | 1 - relays/client-kusama/src/lib.rs | 13 +- relays/client-millau/src/lib.rs | 2 - relays/client-polkadot/src/lib.rs | 13 +- relays/client-rialto-parachain/src/lib.rs | 2 - relays/client-rialto/src/lib.rs | 2 - relays/client-rococo/src/lib.rs | 1 - relays/client-substrate/src/chain.rs | 5 - relays/client-substrate/src/test_chain.rs | 2 - relays/client-westend/src/lib.rs | 2 - relays/client-wococo/src/lib.rs | 1 - 65 files changed, 1600 insertions(+), 161 deletions(-) create mode 100644 primitives/chain-bridge-hub-kusama/Cargo.toml create mode 100644 primitives/chain-bridge-hub-kusama/src/lib.rs create mode 100644 primitives/chain-bridge-hub-polkadot/Cargo.toml create mode 100644 primitives/chain-bridge-hub-polkadot/src/lib.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs create mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs create mode 100644 relays/bin-substrate/src/bridges/mod.rs rename relays/bin-substrate/src/{chains => bridges/rialto_millau}/millau_headers_to_rialto.rs (94%) rename relays/bin-substrate/src/{chains => bridges/rialto_millau}/millau_messages_to_rialto.rs (100%) create mode 100644 relays/bin-substrate/src/bridges/rialto_millau/mod.rs rename relays/bin-substrate/src/{chains => bridges/rialto_millau}/rialto_headers_to_millau.rs (94%) rename relays/bin-substrate/src/{chains => bridges/rialto_millau}/rialto_messages_to_millau.rs (100%) rename relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/millau_headers_to_rialto_parachain.rs (96%) rename relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/millau_messages_to_rialto_parachain.rs (100%) create mode 100644 relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs rename relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/rialto_parachain_messages_to_millau.rs (100%) rename relays/bin-substrate/src/{chains => bridges/rialto_parachain_millau}/rialto_parachains_to_millau.rs (91%) rename relays/bin-substrate/src/{chains => bridges/rococo_wococo}/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs (100%) rename relays/bin-substrate/src/{chains => bridges/rococo_wococo}/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs (100%) create mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/mod.rs rename relays/bin-substrate/src/{chains => bridges/rococo_wococo}/rococo_headers_to_bridge_hub_wococo.rs (100%) rename relays/bin-substrate/src/{chains => bridges/rococo_wococo}/rococo_parachains_to_bridge_hub_wococo.rs (92%) rename relays/bin-substrate/src/{chains => bridges/rococo_wococo}/wococo_headers_to_bridge_hub_rococo.rs (100%) rename relays/bin-substrate/src/{chains => bridges/rococo_wococo}/wococo_parachains_to_bridge_hub_rococo.rs (92%) create mode 100644 relays/bin-substrate/src/bridges/westend_millau/mod.rs rename relays/bin-substrate/src/{chains => bridges/westend_millau}/westend_headers_to_millau.rs (100%) rename relays/bin-substrate/src/{chains => bridges/westend_millau}/westend_parachains_to_millau.rs (95%) create mode 100644 relays/bin-substrate/src/chains/kusama.rs create mode 100644 relays/bin-substrate/src/chains/polkadot.rs create mode 100644 relays/client-bridge-hub-kusama/Cargo.toml create mode 100644 relays/client-bridge-hub-kusama/src/lib.rs create mode 100644 relays/client-bridge-hub-kusama/src/runtime_wrapper.rs create mode 100644 relays/client-bridge-hub-polkadot/Cargo.toml create mode 100644 relays/client-bridge-hub-polkadot/src/lib.rs create mode 100644 relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml new file mode 100644 index 0000000000000..6d4334eaa57f0 --- /dev/null +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "bp-bridge-hub-kusama" +description = "Primitives of BridgeHubRococo parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +# Bridge Dependencies + +bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-bridge-hub-cumulus/std", + "bp-messages/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs new file mode 100644 index 0000000000000..6ca2cd047fb7e --- /dev/null +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -0,0 +1,84 @@ +// Copyright 2022 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 . + +//! Module with configuration which reflects BridgeHubKusama runtime setup (AccountId, Headers, +//! Hashes...) + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use bp_bridge_hub_cumulus::*; +use bp_messages::*; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, +}; +use frame_support::{ + dispatch::DispatchClass, + sp_runtime::{MultiAddress, MultiSigner}, + RuntimeDebug, +}; +use sp_std::prelude::*; + +/// BridgeHubKusama parachain. +#[derive(RuntimeDebug)] +pub struct BridgeHubKusama; + +impl Chain for BridgeHubKusama { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +impl Parachain for BridgeHubKusama { + const PARACHAIN_ID: u32 = BRIDGE_HUB_KUSAMA_PARACHAIN_ID; +} + +/// Public key of the chain account that may be used to verify signatures. +pub type AccountSigner = MultiSigner; + +/// The address format for describing accounts. +pub type Address = MultiAddress; + +/// Identifier of BridgeHubKusama in the Kusama relay chain. +pub const BRIDGE_HUB_KUSAMA_PARACHAIN_ID: u32 = 1002; + +/// Name of the With-BridgeHubKusama messages pallet instance that is deployed at bridged chains. +// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) +pub const WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; + +/// Name of the With-BridgeHubKusama bridge-relayers pallet instance that is deployed at bridged +/// chains. +// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) +pub const WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; + +decl_bridge_finality_runtime_apis!(bridge_hub_kusama); +decl_bridge_messages_runtime_apis!(bridge_hub_kusama); diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml new file mode 100644 index 0000000000000..2a0ab3213c85b --- /dev/null +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "bp-bridge-hub-polkadot" +description = "Primitives of BridgeHubWococo parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-bridge-hub-cumulus/std", + "bp-runtime/std", + "bp-messages/std", + "frame-support/std", + "sp-api/std", + "sp-std/std", +] diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs new file mode 100644 index 0000000000000..646fb0a6e4186 --- /dev/null +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -0,0 +1,75 @@ +// 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 . + +//! Module with configuration which reflects BridgeHubPolkadot runtime setup +//! (AccountId, Headers, Hashes...) + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use bp_bridge_hub_cumulus::*; +use bp_messages::*; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, +}; +use frame_support::{dispatch::DispatchClass, RuntimeDebug}; +use sp_std::prelude::*; + +/// BridgeHubPolkadot parachain. +#[derive(RuntimeDebug)] +pub struct BridgeHubPolkadot; + +impl Chain for BridgeHubPolkadot { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Index = Index; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +impl Parachain for BridgeHubPolkadot { + const PARACHAIN_ID: u32 = BRIDGE_HUB_POLKADOT_PARACHAIN_ID; +} + +/// Identifier of BridgeHubPolkadot in the Polkadot relay chain. +// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) +pub const BRIDGE_HUB_POLKADOT_PARACHAIN_ID: u32 = 1002; + +/// Name of the With-BridgeHubPolkadot messages pallet instance that is deployed at bridged chains. +// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) +pub const WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; + +/// Name of the With-BridgeHubPolkadot bridge-relayers pallet instance that is deployed at bridged +/// chains. +// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) +pub const WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; + +decl_bridge_finality_runtime_apis!(bridge_hub_polkadot); +decl_bridge_messages_runtime_apis!(bridge_hub_polkadot); diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 9ada688bf11b5..8e5aec8afda33 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -56,6 +56,9 @@ impl ChainWithGrandpa for Kusama { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } +/// Name of the parachains pallet in the Kusama runtime. +pub const PARAS_PALLET_NAME: &str = "Paras"; + /// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index e1600102fcd46..92995601698d0 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -56,6 +56,9 @@ impl ChainWithGrandpa for Polkadot { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } +/// Name of the parachains pallet in the Polkadot runtime. +pub const PARAS_PALLET_NAME: &str = "Paras"; + /// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index ece925d795273..1d2373de6d350 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -25,8 +25,7 @@ use frame_support::{ }; use frame_system::RawOrigin; use scale_info::TypeInfo; -use sp_core::{hash::H256, storage::StorageKey}; -use sp_io::hashing::blake2_256; +use sp_core::storage::StorageKey; use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto}; use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; @@ -59,47 +58,44 @@ pub use sp_runtime::paste; /// Use this when something must be shared among all instances. pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0]; -/// Bridge-with-Rialto instance id. +/// Rialto chain id. pub const RIALTO_CHAIN_ID: ChainId = *b"rlto"; -/// Bridge-with-RialtoParachain instance id. +/// RialtoParachain chain id. pub const RIALTO_PARACHAIN_CHAIN_ID: ChainId = *b"rlpa"; -/// Bridge-with-Millau instance id. +/// Millau chain id. pub const MILLAU_CHAIN_ID: ChainId = *b"mlau"; -/// Bridge-with-Polkadot instance id. +/// Polkadot chain id. pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; -/// Bridge-with-Kusama instance id. +/// Kusama chain id. pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; -/// Bridge-with-Westend instance id. +/// Westend chain id. pub const WESTEND_CHAIN_ID: ChainId = *b"wend"; -/// Bridge-with-Westend instance id. +/// Westend chain id. pub const WESTMINT_CHAIN_ID: ChainId = *b"wmnt"; -/// Bridge-with-Rococo instance id. +/// Rococo chain id. pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; -/// Bridge-with-Wococo instance id. +/// Wococo chain id. pub const WOCOCO_CHAIN_ID: ChainId = *b"woco"; -/// Bridge-with-BridgeHubRococo instance id. +/// BridgeHubRococo chain id. pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro"; -/// Bridge-with-BridgeHubWococo instance id. +/// BridgeHubWococo chain id. pub const BRIDGE_HUB_WOCOCO_CHAIN_ID: ChainId = *b"bhwo"; -/// Call-dispatch module prefix. -pub const CALL_DISPATCH_MODULE_PREFIX: &[u8] = b"pallet-bridge/dispatch"; +/// BridgeHubKusama chain id. +pub const BRIDGE_HUB_KUSAMA_CHAIN_ID: ChainId = *b"bhks"; -/// 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"; +/// BridgeHubPolkadot chain id. +pub const BRIDGE_HUB_POLKADOT_CHAIN_ID: ChainId = *b"bhwo"; /// Generic header Id. #[derive( @@ -164,41 +160,6 @@ impl HeaderIdProvider

for Header { /// used for that. pub type ChainId = [u8; 4]; -/// Type of accounts on the source chain. -pub enum SourceAccount { - /// An account that belongs to Root (privileged origin). - Root, - /// 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.). - 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 successfully 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(bridge_id: ChainId, id: SourceAccount) -> 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() -} - /// Anything that has size. pub trait Size { /// Return size of this object (in bytes). diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index b7453c7aef002..6984cfed00c77 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -37,8 +37,12 @@ parachains-relay = { path = "../parachains" } relay-millau-client = { path = "../client-millau" } relay-rialto-client = { path = "../client-rialto" } relay-rialto-parachain-client = { path = "../client-rialto-parachain" } +relay-bridge-hub-kusama-client = { path = "../client-bridge-hub-kusama" } +relay-bridge-hub-polkadot-client = { path = "../client-bridge-hub-polkadot" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } +relay-kusama-client = { path = "../client-kusama" } +relay-polkadot-client = { path = "../client-polkadot" } relay-rococo-client = { path = "../client-rococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs new file mode 100644 index 0000000000000..9abec22b98109 --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs @@ -0,0 +1,65 @@ +// Copyright 2022 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 . + +//! BridgeHubKusama-to-BridgeHubPolkadot messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_bridge_hub_kusama_client::BridgeHubKusama; +use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +/// BridgeHubKusama-to-BridgeHubPolkadot messages bridge. +pub struct BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge { + type Source = BridgeHubKusama; + type Target = BridgeHubPolkadot; +} + +impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge { + type MessagesLane = BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane, + BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_bridge_hub_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane, + BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_bridge_hub_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof +); + +/// BridgeHubKusama-to-BridgeHubPolkadot messages lane. +#[derive(Clone, Debug)] +pub struct BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane; + +impl SubstrateMessageLane for BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane { + type SourceChain = BridgeHubKusama; + type TargetChain = BridgeHubPolkadot; + + type ReceiveMessagesProofCallBuilder = + BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; +} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs new file mode 100644 index 0000000000000..191a84b27c270 --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs @@ -0,0 +1,65 @@ +// Copyright 2022 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 . + +//! BridgeHubPolkadot-to-BridgeHubKusama messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_bridge_hub_kusama_client::BridgeHubKusama; +use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +/// BridgeHubPolkadot-to-BridgeHubKusama messages bridge. +pub struct BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge { + type Source = BridgeHubPolkadot; + type Target = BridgeHubKusama; +} + +impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge { + type MessagesLane = BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane, + BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotMessages, + relay_bridge_hub_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane, + BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaMessages, + relay_bridge_hub_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof +); + +/// BridgeHubPolkadot-to-BridgeHubKusama messages lane. +#[derive(Clone, Debug)] +pub struct BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane; + +impl SubstrateMessageLane for BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane { + type SourceChain = BridgeHubPolkadot; + type TargetChain = BridgeHubKusama; + + type ReceiveMessagesProofCallBuilder = + BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; +} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs new file mode 100644 index 0000000000000..1cfaf922692f6 --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -0,0 +1,72 @@ +// Copyright 2022 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 . + +//! Kusama-to-BridgeHubPolkadot headers sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, +}; + +/// Description of Kusama -> PolkadotBridgeHub finalized headers bridge. +#[derive(Clone, Debug)] +pub struct KusamaFinalityToBridgeHubPolkadot; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + KusamaFinalityToBridgeHubPolkadot, + KusamaFinalityToBridgeHubPolkadotCallBuilder, + relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaGrandpa, + relay_bridge_hub_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof +); + +#[async_trait] +impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { + type SourceChain = relay_kusama_client::Kusama; + type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = KusamaFinalityToBridgeHubPolkadotCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } +} + +/// `Kusama` to BridgeHub `Polkadot` bridge definition. +pub struct KusamaToBridgeHubPolkadotCliBridge {} + +impl CliBridgeBase for KusamaToBridgeHubPolkadotCliBridge { + type Source = relay_kusama_client::Kusama; + type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +} + +impl RelayToRelayHeadersCliBridge for KusamaToBridgeHubPolkadotCliBridge { + type Finality = KusamaFinalityToBridgeHubPolkadot; +} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs new file mode 100644 index 0000000000000..e5936640cb3b8 --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs @@ -0,0 +1,75 @@ +// 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 . + +//! Kusama-to-BridgeHubPolkadot parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::parachains::{ + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// Kusama-to-BridgeHubPolkadot parachain sync description. +#[derive(Clone, Debug)] +pub struct BridgeHubKusamaToBridgeHubPolkadot; + +impl SubstrateParachainsPipeline for BridgeHubKusamaToBridgeHubPolkadot { + type SourceParachain = relay_bridge_hub_kusama_client::BridgeHubKusama; + type SourceRelayChain = relay_kusama_client::Kusama; + type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + + type SubmitParachainHeadsCallBuilder = BridgeHubKusamaToBridgeHubPolkadotCallBuilder; +} + +pub struct BridgeHubKusamaToBridgeHubPolkadotCallBuilder; +impl SubmitParachainHeadsCallBuilder + for BridgeHubKusamaToBridgeHubPolkadotCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaParachain( + relay_bridge_hub_polkadot_client::runtime::BridgeParachainCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + }, + ) + } +} + +/// Kusama-to-BridgeHubPolkadot parachain sync description for the CLI. +pub struct BridgeHubKusamaToBridgeHubPolkadotCliBridge {} + +impl ParachainToRelayHeadersCliBridge for BridgeHubKusamaToBridgeHubPolkadotCliBridge { + type SourceRelay = relay_kusama_client::Kusama; + type ParachainFinality = BridgeHubKusamaToBridgeHubPolkadot; + type RelayFinality = + crate::bridges::kusama_polkadot::kusama_headers_to_bridge_hub_polkadot::KusamaFinalityToBridgeHubPolkadot; +} + +impl CliBridgeBase for BridgeHubKusamaToBridgeHubPolkadotCliBridge { + type Source = relay_bridge_hub_kusama_client::BridgeHubKusama; + type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +} + +impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotCliBridge { + type MessagesLane = + crate::bridges::kusama_polkadot::bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane; +} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs new file mode 100644 index 0000000000000..65cd8d9ded6cd --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs @@ -0,0 +1,24 @@ +// 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 . + +//! Declaration of all bridges between Kusama Bridge Hub and Polkadot Bridge Hub. + +pub mod bridge_hub_kusama_messages_to_bridge_hub_polkadot; +pub mod bridge_hub_polkadot_messages_to_bridge_hub_kusama; +pub mod kusama_headers_to_bridge_hub_polkadot; +pub mod kusama_parachains_to_bridge_hub_polkadot; +pub mod polkadot_headers_to_bridge_hub_kusama; +pub mod polkadot_parachains_to_bridge_hub_kusama; diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs new file mode 100644 index 0000000000000..6827c24768cb8 --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -0,0 +1,72 @@ +// Copyright 2022 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 . + +//! Polkadot-to-KusamaBridgeHub headers sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + TransactionParams, +}; + +/// Description of Polkadot -> KusamaBridgeHub finalized headers bridge. +#[derive(Clone, Debug)] +pub struct PolkadotFinalityToBridgeHubKusama; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + PolkadotFinalityToBridgeHubKusama, + PolkadotFinalityToBridgeHubKusamaCallBuilder, + relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotGrandpa, + relay_bridge_hub_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof +); + +#[async_trait] +impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { + type SourceChain = relay_polkadot_client::Polkadot; + type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama; + + type FinalityEngine = GrandpaFinalityEngine; + type SubmitFinalityProofCallBuilder = PolkadotFinalityToBridgeHubKusamaCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } +} + +/// `Polkadot` to BridgeHub `Kusama` bridge definition. +pub struct PolkadotToBridgeHubKusamaCliBridge {} + +impl CliBridgeBase for PolkadotToBridgeHubKusamaCliBridge { + type Source = relay_polkadot_client::Polkadot; + type Target = relay_bridge_hub_kusama_client::BridgeHubKusama; +} + +impl RelayToRelayHeadersCliBridge for PolkadotToBridgeHubKusamaCliBridge { + type Finality = PolkadotFinalityToBridgeHubKusama; +} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs new file mode 100644 index 0000000000000..f2a7f7309cf1d --- /dev/null +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs @@ -0,0 +1,75 @@ +// 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 . + +//! Polkadot-to-BridgeHubKusama parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::parachains::{ + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// Polkadot-to-BridgeHubKusama parachain sync description. +#[derive(Clone, Debug)] +pub struct BridgeHubPolkadotToBridgeHubKusama; + +impl SubstrateParachainsPipeline for BridgeHubPolkadotToBridgeHubKusama { + type SourceParachain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + type SourceRelayChain = relay_polkadot_client::Polkadot; + type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama; + + type SubmitParachainHeadsCallBuilder = BridgeHubPolkadotToBridgeHubKusamaCallBuilder; +} + +pub struct BridgeHubPolkadotToBridgeHubKusamaCallBuilder; +impl SubmitParachainHeadsCallBuilder + for BridgeHubPolkadotToBridgeHubKusamaCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotParachain( + bp_parachains::BridgeParachainCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + }, + ) + } +} + +/// Polkadot-to-BridgeHubKusama parachain sync description for the CLI. +pub struct BridgeHubPolkadotToBridgeHubKusamaCliBridge {} + +impl ParachainToRelayHeadersCliBridge for BridgeHubPolkadotToBridgeHubKusamaCliBridge { + type SourceRelay = relay_polkadot_client::Polkadot; + type ParachainFinality = BridgeHubPolkadotToBridgeHubKusama; + type RelayFinality = + crate::bridges::kusama_polkadot::polkadot_headers_to_bridge_hub_kusama::PolkadotFinalityToBridgeHubKusama; +} + +impl CliBridgeBase for BridgeHubPolkadotToBridgeHubKusamaCliBridge { + type Source = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + type Target = relay_bridge_hub_kusama_client::BridgeHubKusama; +} + +impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaCliBridge { + type MessagesLane = + crate::bridges::kusama_polkadot::bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane; +} diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs new file mode 100644 index 0000000000000..62e69cc0e5fbd --- /dev/null +++ b/relays/bin-substrate/src/bridges/mod.rs @@ -0,0 +1,23 @@ +// 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 . + +//! Declaration of all bridges that the relay is able to serve. + +pub mod kusama_polkadot; +pub mod rialto_millau; +pub mod rialto_parachain_millau; +pub mod rococo_wococo; +pub mod westend_millau; diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs similarity index 94% rename from relays/bin-substrate/src/chains/millau_headers_to_rialto.rs rename to relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs index e136b800b17a8..f805b29c6a943 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs @@ -51,5 +51,6 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { } impl MessagesCliBridge for MillauToRialtoCliBridge { - type MessagesLane = crate::chains::millau_messages_to_rialto::MillauMessagesToRialto; + type MessagesLane = + crate::bridges::rialto_millau::millau_messages_to_rialto::MillauMessagesToRialto; } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs similarity index 100% rename from relays/bin-substrate/src/chains/millau_messages_to_rialto.rs rename to relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs diff --git a/relays/bin-substrate/src/bridges/rialto_millau/mod.rs b/relays/bin-substrate/src/bridges/rialto_millau/mod.rs new file mode 100644 index 0000000000000..2353b58ce616e --- /dev/null +++ b/relays/bin-substrate/src/bridges/rialto_millau/mod.rs @@ -0,0 +1,22 @@ +// 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 . + +//! Declaration of all bridges between Rialto and Millau. + +pub mod millau_headers_to_rialto; +pub mod millau_messages_to_rialto; +pub mod rialto_headers_to_millau; +pub mod rialto_messages_to_millau; diff --git a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs similarity index 94% rename from relays/bin-substrate/src/chains/rialto_headers_to_millau.rs rename to relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs index 208b2638af01e..7c979f5279567 100644 --- a/relays/bin-substrate/src/chains/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs @@ -51,5 +51,6 @@ impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { } impl MessagesCliBridge for RialtoToMillauCliBridge { - type MessagesLane = crate::chains::rialto_messages_to_millau::RialtoMessagesToMillau; + type MessagesLane = + crate::bridges::rialto_millau::rialto_messages_to_millau::RialtoMessagesToMillau; } diff --git a/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs similarity index 100% rename from relays/bin-substrate/src/chains/rialto_messages_to_millau.rs rename to relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs diff --git a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs similarity index 96% rename from relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs rename to relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs index 4a99d73147b29..d1c090c0797e0 100644 --- a/relays/bin-substrate/src/chains/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs @@ -72,5 +72,5 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { impl MessagesCliBridge for MillauToRialtoParachainCliBridge { type MessagesLane = - crate::chains::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; + crate::bridges::rialto_parachain_millau::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; } diff --git a/relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs similarity index 100% rename from relays/bin-substrate/src/chains/millau_messages_to_rialto_parachain.rs rename to relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs new file mode 100644 index 0000000000000..f0613d1511eb3 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs @@ -0,0 +1,22 @@ +// 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 . + +//! Declaration of all bridges between Rialto Parachain and Millau. + +pub mod millau_headers_to_rialto_parachain; +pub mod millau_messages_to_rialto_parachain; +pub mod rialto_parachain_messages_to_millau; +pub mod rialto_parachains_to_millau; diff --git a/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs similarity index 100% rename from relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs rename to relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs diff --git a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs similarity index 91% rename from relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs rename to relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs index 37eb848fe5f8e..04f2b5aa7c745 100644 --- a/relays/bin-substrate/src/chains/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs @@ -55,10 +55,11 @@ impl CliBridgeBase for RialtoParachainToMillauCliBridge { impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge { type SourceRelay = Rialto; type ParachainFinality = RialtoParachainsToMillau; - type RelayFinality = crate::chains::rialto_headers_to_millau::RialtoFinalityToMillau; + type RelayFinality = + crate::bridges::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; } impl MessagesCliBridge for RialtoParachainToMillauCliBridge { type MessagesLane = - crate::chains::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; + crate::bridges::rialto_parachain_millau::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; } diff --git a/relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs similarity index 100% rename from relays/bin-substrate/src/chains/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs rename to relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs diff --git a/relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs similarity index 100% rename from relays/bin-substrate/src/chains/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs rename to relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs b/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs new file mode 100644 index 0000000000000..64330a92252cd --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs @@ -0,0 +1,24 @@ +// 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 . + +//! Declaration of all bridges between Rococo Bridge Hub and Wococo Bridge Hub. + +pub mod bridge_hub_rococo_messages_to_bridge_hub_wococo; +pub mod bridge_hub_wococo_messages_to_bridge_hub_rococo; +pub mod rococo_headers_to_bridge_hub_wococo; +pub mod rococo_parachains_to_bridge_hub_wococo; +pub mod wococo_headers_to_bridge_hub_rococo; +pub mod wococo_parachains_to_bridge_hub_rococo; diff --git a/relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs similarity index 100% rename from relays/bin-substrate/src/chains/rococo_headers_to_bridge_hub_wococo.rs rename to relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs diff --git a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs similarity index 92% rename from relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs rename to relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs index ba0c10beae424..78b4ff35a7d45 100644 --- a/relays/bin-substrate/src/chains/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs @@ -61,7 +61,7 @@ impl ParachainToRelayHeadersCliBridge for BridgeHubRococoToBridgeHubWococoCliBri type SourceRelay = relay_rococo_client::Rococo; type ParachainFinality = BridgeHubRococoToBridgeHubWococo; type RelayFinality = - crate::chains::rococo_headers_to_bridge_hub_wococo::RococoFinalityToBridgeHubWococo; + crate::bridges::rococo_wococo::rococo_headers_to_bridge_hub_wococo::RococoFinalityToBridgeHubWococo; } impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge { @@ -71,5 +71,5 @@ impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge { impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge { type MessagesLane = - crate::chains::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane; + crate::bridges::rococo_wococo::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane; } diff --git a/relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs similarity index 100% rename from relays/bin-substrate/src/chains/wococo_headers_to_bridge_hub_rococo.rs rename to relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs diff --git a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs similarity index 92% rename from relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs rename to relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs index 028d8c9e17dba..bc76e377c9214 100644 --- a/relays/bin-substrate/src/chains/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs @@ -61,7 +61,7 @@ impl ParachainToRelayHeadersCliBridge for BridgeHubWococoToBridgeHubRococoCliBri type SourceRelay = relay_wococo_client::Wococo; type ParachainFinality = BridgeHubWococoToBridgeHubRococo; type RelayFinality = - crate::chains::wococo_headers_to_bridge_hub_rococo::WococoFinalityToBridgeHubRococo; + crate::bridges::rococo_wococo::wococo_headers_to_bridge_hub_rococo::WococoFinalityToBridgeHubRococo; } impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge { @@ -71,5 +71,5 @@ impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge { impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge { type MessagesLane = - crate::chains::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane; + crate::bridges::rococo_wococo::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane; } diff --git a/relays/bin-substrate/src/bridges/westend_millau/mod.rs b/relays/bin-substrate/src/bridges/westend_millau/mod.rs new file mode 100644 index 0000000000000..10bc19241ce12 --- /dev/null +++ b/relays/bin-substrate/src/bridges/westend_millau/mod.rs @@ -0,0 +1,20 @@ +// 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 . + +//! Declaration of all bridges between Westend and Millau. + +pub mod westend_headers_to_millau; +pub mod westend_parachains_to_millau; diff --git a/relays/bin-substrate/src/chains/westend_headers_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs similarity index 100% rename from relays/bin-substrate/src/chains/westend_headers_to_millau.rs rename to relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs diff --git a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs similarity index 95% rename from relays/bin-substrate/src/chains/westend_parachains_to_millau.rs rename to relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs index abd9e6137bb32..0556ecab368eb 100644 --- a/relays/bin-substrate/src/chains/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs @@ -49,7 +49,8 @@ pub struct WestmintToMillauCliBridge {} impl ParachainToRelayHeadersCliBridge for WestmintToMillauCliBridge { type SourceRelay = Westend; type ParachainFinality = WestendParachainsToMillau; - type RelayFinality = crate::chains::westend_headers_to_millau::WestendFinalityToMillau; + type RelayFinality = + crate::bridges::westend_millau::westend_headers_to_millau::WestendFinalityToMillau; } impl CliBridgeBase for WestmintToMillauCliBridge { diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs new file mode 100644 index 0000000000000..6d5a4764f91ec --- /dev/null +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -0,0 +1,32 @@ +// Copyright 2022 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 . + +//! Kusama + Kusama parachains specification for CLI. + +use crate::cli::CliChain; +use relay_bridge_hub_kusama_client::BridgeHubKusama; +use relay_kusama_client::Kusama; +use relay_substrate_client::SimpleRuntimeVersion; + +impl CliChain for Kusama { + const RUNTIME_VERSION: Option = None; +} + +impl CliChain for BridgeHubKusama { + // TODO: fix me (https://github.com/paritytech/parity-bridges-common/issues/1945) + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 4242, transaction_version: 42 }); +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 7aad5f44e8908..b1a91ed1e85cb 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -16,24 +16,9 @@ //! Chain-specific relayer configuration. -pub mod bridge_hub_rococo_messages_to_bridge_hub_wococo; -pub mod bridge_hub_wococo_messages_to_bridge_hub_rococo; -pub mod millau_headers_to_rialto; -pub mod millau_headers_to_rialto_parachain; -pub mod millau_messages_to_rialto; -pub mod millau_messages_to_rialto_parachain; -pub mod rialto_headers_to_millau; -pub mod rialto_messages_to_millau; -pub mod rialto_parachain_messages_to_millau; -pub mod rialto_parachains_to_millau; -pub mod rococo_headers_to_bridge_hub_wococo; -pub mod rococo_parachains_to_bridge_hub_wococo; -pub mod westend_headers_to_millau; -pub mod westend_parachains_to_millau; -pub mod wococo_headers_to_bridge_hub_rococo; -pub mod wococo_parachains_to_bridge_hub_rococo; - +mod kusama; mod millau; +mod polkadot; mod rialto; mod rialto_parachain; mod rococo; diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs new file mode 100644 index 0000000000000..4fe5a48398bcd --- /dev/null +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -0,0 +1,32 @@ +// Copyright 2022 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 . + +//! Polkadot + Polkadot parachains specification for CLI. + +use crate::cli::CliChain; +use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +use relay_polkadot_client::Polkadot; +use relay_substrate_client::SimpleRuntimeVersion; + +impl CliChain for Polkadot { + const RUNTIME_VERSION: Option = None; +} + +impl CliChain for BridgeHubPolkadot { + // TODO: fix me (https://github.com/paritytech/parity-bridges-common/issues/1945) + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 4242, transaction_version: 42 }); +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 208f67c527be6..a3cacec331394 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -33,6 +33,8 @@ pub enum FullBridge { RialtoParachainToMillau, BridgeHubRococoToBridgeHubWococo, BridgeHubWococoToBridgeHubRococo, + BridgeHubKusamaToBridgeHubPolkadot, + BridgeHubPolkadotToBridgeHubKusama, } impl FullBridge { @@ -43,7 +45,10 @@ impl FullBridge { Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, - Self::BridgeHubRococoToBridgeHubWococo | Self::BridgeHubWococoToBridgeHubRococo => + Self::BridgeHubRococoToBridgeHubWococo | + Self::BridgeHubWococoToBridgeHubRococo | + Self::BridgeHubKusamaToBridgeHubPolkadot | + Self::BridgeHubPolkadotToBridgeHubKusama => unimplemented!("Relay doesn't support send-message subcommand on bridge hubs"), } } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index d6df1eaeeaa14..95cd02f6c6fcc 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -18,13 +18,17 @@ use async_trait::async_trait; use codec::Encode; use crate::{ - chains::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, - westend_headers_to_millau::WestendToMillauCliBridge, - wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, + bridges::{ + rialto_millau::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + }, + rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rococo_wococo::{ + rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, + wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, + }, + westend_millau::westend_headers_to_millau::WestendToMillauCliBridge, }, cli::{bridge::CliBridgeBase, chain_schema::*}, }; diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 239ab8d62fdd0..fbe360d3cd780 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -20,13 +20,21 @@ use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; -use crate::chains::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, - westend_headers_to_millau::WestendToMillauCliBridge, - wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, +use crate::bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, + rialto_millau::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + }, + rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rococo_wococo::{ + rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, + wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, + }, + westend_millau::westend_headers_to_millau::WestendToMillauCliBridge, }; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; @@ -63,6 +71,8 @@ pub enum RelayHeadersBridge { MillauToRialtoParachain, RococoToBridgeHubWococo, WococoToBridgeHubRococo, + KusamaToBridgeHubPolkadot, + PolkadotToBridgeHubKusama, } #[async_trait] @@ -109,6 +119,8 @@ impl HeadersRelayer for WestendToMillauCliBridge {} impl HeadersRelayer for MillauToRialtoParachainCliBridge {} impl HeadersRelayer for RococoToBridgeHubWococoCliBridge {} impl HeadersRelayer for WococoToBridgeHubRococoCliBridge {} +impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} +impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} impl RelayHeaders { /// Run the command. @@ -123,6 +135,10 @@ impl RelayHeaders { RococoToBridgeHubWococoCliBridge::relay_headers(self), RelayHeadersBridge::WococoToBridgeHubRococo => WococoToBridgeHubRococoCliBridge::relay_headers(self), + RelayHeadersBridge::KusamaToBridgeHubPolkadot => + KusamaToBridgeHubPolkadotCliBridge::relay_headers(self), + RelayHeadersBridge::PolkadotToBridgeHubKusama => + PolkadotToBridgeHubKusamaCliBridge::relay_headers(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 193632c28b427..5384c8ff9e9fd 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -39,13 +39,19 @@ use relay_to_parachain::*; use relay_to_relay::*; use crate::{ - chains::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, - rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, - wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, + bridges::{ + rialto_millau::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + }, + rialto_parachain_millau::{ + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + }, + rococo_wococo::{ + rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, + wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, + }, }, cli::{ bridge::{ diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index e0250ef1e472b..1624524e4a5b1 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -19,13 +19,23 @@ use sp_core::Pair; use structopt::StructOpt; use strum::VariantNames; -use crate::chains::{ - bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge, - bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge, - millau_headers_to_rialto::MillauToRialtoCliBridge, - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, +use crate::bridges::{ + kusama_polkadot::{ + bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge, + bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge, + }, + rialto_millau::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + }, + rialto_parachain_millau::{ + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + }, + rococo_wococo::{ + bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge, + bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge, + }, }; use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions}; use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; @@ -96,6 +106,8 @@ impl MessagesRelayer for MillauToRialtoParachainCliBridge {} impl MessagesRelayer for RialtoParachainToMillauCliBridge {} impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} +impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} +impl MessagesRelayer for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} impl RelayMessages { /// Run the command. @@ -111,6 +123,10 @@ impl RelayMessages { BridgeHubRococoToBridgeHubWococoMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubWococoToBridgeHubRococo => BridgeHubWococoToBridgeHubRococoMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubKusamaToBridgeHubPolkadot => + BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubPolkadotToBridgeHubKusama => + BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 4e59dc14733fc..8c2aa1cc8c1f6 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -14,11 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::chains::{ - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, - rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, - westend_parachains_to_millau::WestmintToMillauCliBridge, - wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, +use crate::bridges::{ + kusama_polkadot::{ + kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, + polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, + }, + rialto_parachain_millau::rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + rococo_wococo::{ + rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, + wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, + }, + westend_millau::westend_parachains_to_millau::WestmintToMillauCliBridge, }; use async_std::sync::Mutex; use async_trait::async_trait; @@ -60,10 +66,11 @@ pub struct RelayParachains { #[strum(serialize_all = "kebab_case")] pub enum RelayParachainsBridge { RialtoToMillau, - // TODO:check-parameter - rename to WestmintToMillau? WestendToMillau, - BridgeHubRococoToBridgeHubWococo, - BridgeHubWococoToBridgeHubRococo, + RococoToBridgeHubWococo, + WococoToBridgeHubRococo, + KusamaToBridgeHubPolkadot, + PolkadotToBridgeHubKusama, } #[async_trait] @@ -75,7 +82,7 @@ where TargetClient>, ::Source: Parachain, { - async fn relay_headers(data: RelayParachains) -> anyhow::Result<()> { + async fn relay_parachains(data: RelayParachains) -> anyhow::Result<()> { let source_client = data.source.into_client::().await?; let source_client = ParachainsSource::::new( source_client, @@ -108,25 +115,28 @@ where } impl ParachainsRelayer for RialtoParachainToMillauCliBridge {} - impl ParachainsRelayer for WestmintToMillauCliBridge {} - impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} - impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} +impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} +impl ParachainsRelayer for BridgeHubPolkadotToBridgeHubKusamaCliBridge {} impl RelayParachains { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { RelayParachainsBridge::RialtoToMillau => - RialtoParachainToMillauCliBridge::relay_headers(self), + RialtoParachainToMillauCliBridge::relay_parachains(self), RelayParachainsBridge::WestendToMillau => - WestmintToMillauCliBridge::relay_headers(self), - RelayParachainsBridge::BridgeHubRococoToBridgeHubWococo => - BridgeHubRococoToBridgeHubWococoCliBridge::relay_headers(self), - RelayParachainsBridge::BridgeHubWococoToBridgeHubRococo => - BridgeHubWococoToBridgeHubRococoCliBridge::relay_headers(self), + WestmintToMillauCliBridge::relay_parachains(self), + RelayParachainsBridge::RococoToBridgeHubWococo => + BridgeHubRococoToBridgeHubWococoCliBridge::relay_parachains(self), + RelayParachainsBridge::WococoToBridgeHubRococo => + BridgeHubWococoToBridgeHubRococoCliBridge::relay_parachains(self), + RelayParachainsBridge::KusamaToBridgeHubPolkadot => + BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self), + RelayParachainsBridge::PolkadotToBridgeHubKusama => + BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self), } .await } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 9f14028c4aee4..09d7f72b7f4b5 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -15,11 +15,15 @@ // along with Parity Bridges Common. If not, see . use crate::{ - chains::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + bridges::{ + rialto_millau::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + }, + rialto_parachain_millau::{ + millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + }, }, cli::{ bridge::{FullBridge, MessagesCliBridge}, @@ -114,6 +118,12 @@ impl SendMessage { FullBridge::BridgeHubWococoToBridgeHubRococo => unimplemented!( "Sending message from BridgeHubWococo to BridgeHubRococo is not supported" ), + FullBridge::BridgeHubKusamaToBridgeHubPolkadot => unimplemented!( + "Sending message from BridgeHubKusama to BridgeHubPolkadot is not supported" + ), + FullBridge::BridgeHubPolkadotToBridgeHubKusama => unimplemented!( + "Sending message from BridgeHubPolkadot to BridgeHubKusama is not supported" + ), } .await } diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 8bd89a4193627..33a423b076628 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -18,6 +18,7 @@ #![warn(missing_docs)] +mod bridges; mod chains; mod cli; diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml new file mode 100644 index 0000000000000..3485323ca6c51 --- /dev/null +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "relay-bridge-hub-kusama-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +relay-substrate-client = { path = "../client-substrate" } + +# Bridge dependencies + +bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } +bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } +bp-parachains = { path = "../../primitives/parachains" } +bp-runtime = { path = "../../primitives/runtime" } +bp-polkadot = { path = "../../primitives/chain-polkadot" } + +bridge-runtime-common = { path = "../../bin/runtime-common" } + +# Substrate Dependencies + +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs new file mode 100644 index 0000000000000..6549a32ca7956 --- /dev/null +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -0,0 +1,162 @@ +// Copyright 2022 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 . + +//! Types used to connect to the BridgeHub-Kusama-Substrate parachain. + +use bp_bridge_hub_kusama::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_messages::MessageNonce; +use bp_runtime::ChainId; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, + UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Re-export runtime wrapper +pub mod runtime_wrapper; +pub use runtime_wrapper as runtime; + +/// Kusama chain definition +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BridgeHubKusama; + +impl UnderlyingChainProvider for BridgeHubKusama { + type Chain = bp_bridge_hub_kusama::BridgeHubKusama; +} + +impl Chain for BridgeHubKusama { + const ID: ChainId = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID; + const NAME: &'static str = "BridgeHubKusama"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_bridge_hub_kusama::BEST_FINALIZED_BRIDGE_HUB_KUSAMA_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; + + type SignedBlock = bp_bridge_hub_kusama::SignedBlock; + type Call = runtime::Call; +} + +impl ChainWithBalances for BridgeHubKusama { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + bp_bridge_hub_kusama::AccountInfoStorageMapKeyProvider::final_key(account_id) + } +} + +impl ChainWithUtilityPallet for BridgeHubKusama { + type UtilityPallet = MockedRuntimeUtilityPallet; +} + +impl ChainWithTransactions for BridgeHubKusama { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = runtime::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + runtime::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(runtime::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + *address == bp_bridge_hub_kusama::Address::Id(signer.public().into()) + }) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} + +impl ChainWithMessages for BridgeHubKusama { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = + Some(bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME); + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_kusama::TO_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: runtime::Call::System(relay_substrate_client::calls::SystemCall::remark( + b"Hello world!".to_vec(), + )) + .into(), + nonce: 777, + tip: 888, + era: TransactionEra::immortal(), + }; + let signed_transaction = BridgeHubKusama::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) + .unwrap(); + let parsed_transaction = BridgeHubKusama::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs new file mode 100644 index 0000000000000..18bdafc0f04de --- /dev/null +++ b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs @@ -0,0 +1,74 @@ +// 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 . + +//! Types that are specific to the BridgeHubKusama runtime. +// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945) + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_bridge_hub_kusama::SignedExtension; +pub use bp_header_chain::BridgeGrandpaCallOf; +pub use bp_parachains::BridgeParachainCall; +pub use bridge_runtime_common::messages::BridgeMessagesCallOf; +pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; + +/// Unchecked BridgeHubKusama extrinsic. +pub type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; + +// The indirect pallet call used to sync `Polkadot` GRANDPA finality to `BHKusama`. +pub type BridgePolkadotGrandpaCall = BridgeGrandpaCallOf; +// The indirect pallet call used to sync `BridgeHubPolkadot` messages to `BHKusama`. +pub type BridgePolkadotMessagesCall = + BridgeMessagesCallOf; + +/// `BridgeHubKusama` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `BridgeHubKusama` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `BridgeHubKusama` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + #[cfg(test)] + #[codec(index = 0)] + System(SystemCall), + /// Utility pallet. + #[codec(index = 40)] + Utility(UtilityCall), + + /// Polkadot bridge pallet. + // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) + #[codec(index = 41)] + BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), + /// Polkadot parachain bridge pallet. + // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) + #[codec(index = 42)] + BridgePolkadotParachain(BridgeParachainCall), + /// Polkadot messages bridge pallet. + // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) + #[codec(index = 46)] + BridgePolkadotMessages(BridgePolkadotMessagesCall), +} + +impl From> for Call { + fn from(call: UtilityCall) -> Call { + Call::Utility(call) + } +} diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml new file mode 100644 index 0000000000000..dee3147eb35a3 --- /dev/null +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "relay-bridge-hub-polkadot-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +relay-substrate-client = { path = "../client-substrate" } + +# Bridge dependencies + +bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } +bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } +bp-parachains = { path = "../../primitives/parachains" } +bp-kusama = { path = "../../primitives/chain-kusama" } +bp-runtime = { path = "../../primitives/runtime" } + +bridge-runtime-common = { path = "../../bin/runtime-common" } + +# Substrate Dependencies + +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[dev-dependencies] +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs new file mode 100644 index 0000000000000..6428b055dd5a2 --- /dev/null +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -0,0 +1,160 @@ +// Copyright 2022 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 . + +//! Types used to connect to the BridgeHub-Polkadot-Substrate parachain. + +use bp_bridge_hub_polkadot::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_messages::MessageNonce; +use bp_runtime::ChainId; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, + UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Re-export runtime wrapper +pub mod runtime_wrapper; +pub use runtime_wrapper as runtime; + +/// Polkadot chain definition +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BridgeHubPolkadot; + +impl UnderlyingChainProvider for BridgeHubPolkadot { + type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; +} + +impl Chain for BridgeHubPolkadot { + const ID: ChainId = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID; + const NAME: &'static str = "BridgeHubPolkadot"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_bridge_hub_polkadot::BEST_FINALIZED_BRIDGE_HUB_POLKADOT_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; + + type SignedBlock = bp_bridge_hub_polkadot::SignedBlock; + type Call = runtime::Call; +} + +impl ChainWithBalances for BridgeHubPolkadot { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + bp_bridge_hub_polkadot::AccountInfoStorageMapKeyProvider::final_key(account_id) + } +} + +impl ChainWithUtilityPallet for BridgeHubPolkadot { + type UtilityPallet = MockedRuntimeUtilityPallet; +} + +impl ChainWithTransactions for BridgeHubPolkadot { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = runtime::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + runtime::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(runtime::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + *address == bp_bridge_hub_polkadot::Address::Id(signer.public().into()) + }) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} + +impl ChainWithMessages for BridgeHubPolkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = + Some(bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME); + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_polkadot::TO_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + .into(), + nonce: 777, + tip: 888, + era: TransactionEra::immortal(), + }; + let signed_transaction = BridgeHubPolkadot::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) + .unwrap(); + let parsed_transaction = BridgeHubPolkadot::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs new file mode 100644 index 0000000000000..5afac61dbb3fc --- /dev/null +++ b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs @@ -0,0 +1,119 @@ +// 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 . + +//! Types that are specific to the BridgeHubPolkadot runtime. +// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945) + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_bridge_hub_polkadot::SignedExtension; +pub use bp_header_chain::BridgeGrandpaCallOf; +pub use bp_parachains::BridgeParachainCall; +pub use bridge_runtime_common::messages::BridgeMessagesCallOf; +pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; + +/// Unchecked BridgeHubPolkadot extrinsic. +pub type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; + +// The indirect pallet call used to sync `Kusama` GRANDPA finality to `BHPolkadot`. +pub type BridgeKusamaGrandpaCall = BridgeGrandpaCallOf; +// The indirect pallet call used to sync `BridgeHubKusama` messages to `BridgeHubPolkadot`. +pub type BridgeKusamaMessagesCall = BridgeMessagesCallOf; + +/// `BridgeHubPolkadot` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `BridgeHubPolkadot` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `BridgeHubPolkadot` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + #[cfg(test)] + #[codec(index = 0)] + System(SystemCall), + /// Utility pallet. + #[codec(index = 40)] + Utility(UtilityCall), + + /// Kusama bridge pallet. + // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) + #[codec(index = 43)] + BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), + /// Kusama parachain bridge pallet. + // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) + #[codec(index = 44)] + BridgeKusamaParachain(BridgeParachainCall), + /// Kusama messages bridge pallet. + // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) + #[codec(index = 45)] + BridgeKusamaMessages(BridgeKusamaMessagesCall), +} + +impl From> for Call { + fn from(call: UtilityCall) -> Call { + Call::Utility(call) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_runtime::BasicOperatingMode; + use sp_consensus_grandpa::AuthorityList; + use sp_core::hexdisplay::HexDisplay; + use sp_runtime::traits::Header; + use std::str::FromStr; + + pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; + pub type RelayBlockHasher = bp_polkadot_core::Hasher; + pub type RelayBlockHeader = sp_runtime::generic::Header; + + #[test] + fn encode_decode_calls() { + let header = RelayBlockHeader::new( + 75, + bp_polkadot_core::Hash::from_str( + "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", + ) + .expect("invalid value"), + Default::default(), + ); + let init_data = bp_header_chain::InitializationData { + header: Box::new(header), + authority_list: AuthorityList::default(), + set_id: 6, + operating_mode: BasicOperatingMode::Normal, + }; + let call = BridgeKusamaGrandpaCall::initialize { init_data }; + let tx = Call::BridgeKusamaGrandpa(call); + + // encode call as hex string + let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); + assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); + } +} diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 87d461b976109..bc2ec3aca41e6 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -44,7 +44,6 @@ impl UnderlyingChainProvider for BridgeHubRococo { impl Chain for BridgeHubRococo { const ID: ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID; const NAME: &'static str = "BridgeHubRococo"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index e9864bf98857a..c9acc47dd954d 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -44,7 +44,6 @@ impl UnderlyingChainProvider for BridgeHubWococo { impl Chain for BridgeHubWococo { const ID: ChainId = bp_runtime::BRIDGE_HUB_WOCOCO_CHAIN_ID; const NAME: &'static str = "BridgeHubWococo"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_wococo::BEST_FINALIZED_BRIDGE_HUB_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 4b631b6052b79..99a52b4baf434 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -18,13 +18,16 @@ use bp_kusama::AccountInfoStorageMapKeyProvider; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider}; +use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; /// Kusama header id. pub type HeaderId = relay_utils::HeaderId; +/// Kusama header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + /// Kusama chain definition #[derive(Debug, Clone, Copy)] pub struct Kusama; @@ -36,7 +39,6 @@ impl UnderlyingChainProvider for Kusama { impl Chain for Kusama { const ID: ChainId = bp_runtime::KUSAMA_CHAIN_ID; const NAME: &'static str = "Kusama"; - const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -51,5 +53,8 @@ impl ChainWithBalances for Kusama { } } -/// Kusama header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; +impl RelayChain for Kusama { + const PARAS_PALLET_NAME: &'static str = bp_kusama::PARAS_PALLET_NAME; + // TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeKusamaParachain"; +} diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 1c8a0f984ef0a..ce42d004bb807 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -57,8 +57,6 @@ impl ChainWithMessages for Millau { impl Chain for Millau { const ID: ChainId = bp_runtime::MILLAU_CHAIN_ID; const NAME: &'static str = "Millau"; - // Rialto token has no value, but we associate it with KSM token - const TOKEN_ID: Option<&'static str> = Some("kusama"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 08837bdcec2f6..7f8615e0cd0ef 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -18,13 +18,16 @@ use bp_polkadot::AccountInfoStorageMapKeyProvider; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, UnderlyingChainProvider}; +use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; use sp_core::storage::StorageKey; use std::time::Duration; /// Polkadot header id. pub type HeaderId = relay_utils::HeaderId; +/// Polkadot header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + /// Polkadot chain definition #[derive(Debug, Clone, Copy)] pub struct Polkadot; @@ -36,7 +39,6 @@ impl UnderlyingChainProvider for Polkadot { impl Chain for Polkadot { const ID: ChainId = bp_runtime::POLKADOT_CHAIN_ID; const NAME: &'static str = "Polkadot"; - const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -51,5 +53,8 @@ impl ChainWithBalances for Polkadot { } } -/// Polkadot header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; +impl RelayChain for Polkadot { + const PARAS_PALLET_NAME: &'static str = bp_polkadot::PARAS_PALLET_NAME; + // TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgePolkadotParachain"; +} diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index 5334c59d3c190..ddb54fbefc06d 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -51,8 +51,6 @@ impl UnderlyingChainProvider for RialtoParachain { impl Chain for RialtoParachain { const ID: ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; const NAME: &'static str = "RialtoParachain"; - // RialtoParachain token has no value, but we associate it with DOT token - const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 7fe735b4adcac..f8f696068fe90 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -42,8 +42,6 @@ impl UnderlyingChainProvider for Rialto { impl Chain for Rialto { const ID: ChainId = bp_runtime::RIALTO_CHAIN_ID; const NAME: &'static str = "Rialto"; - // Rialto token has no value, but we associate it with DOT token - const TOKEN_ID: Option<&'static str> = Some("polkadot"); const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5049778a5420d..ede1bf1ded4e5 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -38,7 +38,6 @@ impl UnderlyingChainProvider for Rococo { impl Chain for Rococo { const ID: ChainId = bp_runtime::ROCOCO_CHAIN_ID; const NAME: &'static str = "Rococo"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 6ab353921efca..8c7dc00aa67bb 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -39,11 +39,6 @@ pub trait Chain: ChainBase + Clone { const ID: ChainId; /// Chain name. const NAME: &'static str; - /// Identifier of the basic token of the chain (if applicable). - /// - /// This identifier is used to fetch token price. In case of testnets, you may either - /// set it to `None`, or associate testnet with one of the existing tokens. - const TOKEN_ID: Option<&'static str>; /// Name of the runtime API method that is returning best known finalized header number /// and hash (as tuple). /// diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index d33cb1de68123..64c7590ee5250 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -53,7 +53,6 @@ impl bp_runtime::Chain for TestChain { impl Chain for TestChain { const ID: ChainId = *b"test"; const NAME: &'static str = "Test"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); @@ -108,7 +107,6 @@ impl bp_runtime::UnderlyingChainProvider for TestParachain { impl Chain for TestParachain { const ID: ChainId = *b"test"; const NAME: &'static str = "TestParachain"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestParachainMethod"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 6db8eaf95e40d..6013bfad128a5 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -38,7 +38,6 @@ impl UnderlyingChainProvider for Westend { impl Chain for Westend { const ID: ChainId = bp_runtime::WESTEND_CHAIN_ID; const NAME: &'static str = "Westend"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); @@ -72,7 +71,6 @@ impl UnderlyingChainProvider for Westmint { impl Chain for Westmint { const ID: ChainId = bp_runtime::WESTMINT_CHAIN_ID; const NAME: &'static str = "Westmint"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTMINT_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 582c34ef85363..2f0d6b22f9291 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -38,7 +38,6 @@ impl UnderlyingChainProvider for Wococo { impl Chain for Wococo { const ID: ChainId = bp_runtime::WOCOCO_CHAIN_ID; const NAME: &'static str = "Wococo"; - const TOKEN_ID: Option<&'static str> = None; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); From 5759757c0cca23d3c6632a19ed632cba651a65f3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 22 Mar 2023 17:32:23 +0300 Subject: [PATCH 0996/1210] remove invalid weight, returned by send_message (#1984) --- modules/messages/src/lib.rs | 23 ++++------------------- primitives/messages/src/source_chain.rs | 6 ++---- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a9a25fb96220d..3faf00b9e75bf 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -749,15 +749,7 @@ fn send_message, I: 'static>( Pallet::::deposit_event(Event::MessageAccepted { lane_id, nonce }); - // we may introduce benchmarks for that, but no heavy ops planned here apart from - // db reads and writes. There are currently 2 db reads and 2 db writes: - // - one db read for operation mode check (`ensure_normal_operating_mode`); - // - one db read for outbound lane state (`outbound_lane`); - // - one db write for outbound lane state (`send_message`); - // - one db write for the message (`send_message`); - let actual_weight = T::DbWeight::get().reads_writes(2, 2); - - Ok(SendMessageArtifacts { nonce, weight: actual_weight }) + Ok(SendMessageArtifacts { nonce }) } /// Ensure that the pallet is in normal operational mode. @@ -970,18 +962,13 @@ mod tests { } } - fn send_regular_message() -> Weight { + fn send_regular_message() { get_ready_for_events(); let message_nonce = outbound_lane::(TEST_LANE_ID).data().latest_generated_nonce + 1; - let weight = send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - ) - .expect("send_message has failed") - .weight; + send_message::(RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD) + .expect("send_message has failed"); // check event with assigned nonce assert_eq!( @@ -995,8 +982,6 @@ mod tests { topics: vec![], }], ); - - weight } fn receive_messages_delivery_proof() { diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 881bd92f5f955..83f27843d6389 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -20,7 +20,7 @@ use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; use crate::UnrewardedRelayer; use bp_runtime::Size; -use frame_support::{weights::Weight, Parameter, RuntimeDebug}; +use frame_support::{Parameter, RuntimeDebug}; use sp_std::{ collections::{btree_map::BTreeMap, vec_deque::VecDeque}, fmt::Debug, @@ -124,8 +124,6 @@ impl DeliveryConfirmationPayments for () { pub struct SendMessageArtifacts { /// Nonce of the message. pub nonce: MessageNonce, - /// Actual weight of send message call. - pub weight: Weight, } /// Messages bridge API to be used from other pallets. @@ -155,7 +153,7 @@ impl MessagesBridge for NoopMessag _lane: LaneId, _message: Payload, ) -> Result { - Ok(SendMessageArtifacts { nonce: 0, weight: Weight::zero() }) + Ok(SendMessageArtifacts { nonce: 0 }) } } From 23ad7fa601e5545deacd8d1692178bed25ddab36 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 22 Mar 2023 16:47:04 +0200 Subject: [PATCH 0997/1210] minor cosmetic updates (#1985) --- .../src/messages_xcm_extension.rs | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 7163d8a535767..42ac67a0f26ac 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -159,23 +159,24 @@ impl> HaulBlo { fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { let lane = H::xcm_lane(); - let result = H::MessageSender::send_message(H::message_sender_origin(), lane, blob); - let result = result - .map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256)); - match &result { - Ok(result) => log::info!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - ok: {:?} on lane: {:?}", - result, - lane - ), - Err(error) => log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - error: {:?} on lane: {:?}", - error, - lane - ), - }; - result.map(|_| ()).map_err(|_| HaulBlobError::Transport("MessageSenderError")) + H::MessageSender::send_message(H::message_sender_origin(), lane, blob) + .map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256)) + .map(|result| { + log::info!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "haul_blob result - ok: {:?} on lane: {:?}", + result, + lane + ) + }) + .map_err(|error| { + log::error!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "haul_blob result - error: {:?} on lane: {:?}", + error, + lane + ); + HaulBlobError::Transport("MessageSenderError") + }) } } From db958ecb46bd2f533b00cb810aa22a72ccbcc36f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 23 Mar 2023 10:44:53 +0300 Subject: [PATCH 0998/1210] Remove deprecated code from bridge-runtime-common (#1983) * removed FromBridgedChainMessageDispatch in favor of XcmBlobMessageDispatch * use HaulBlobExporter/HaulBlobExporterAdapter instead of XcmBridge/XcmBridgeAdapter * tests for sending/dispatching messages * use new schema in testnet bridges + some cleanup * clippy * spelling + added TODO * cleanup some checks * benchmarks compilation * all is XCM * updated README.md * ref issue from TODO --- README.md | 9 +- bin/millau/runtime/src/lib.rs | 8 +- bin/millau/runtime/src/rialto_messages.rs | 68 ++-- .../runtime/src/rialto_parachain_messages.rs | 70 ++-- bin/millau/runtime/src/xcm_config.rs | 304 +++++++++------ bin/rialto-parachain/runtime/Cargo.toml | 2 + bin/rialto-parachain/runtime/src/lib.rs | 177 ++++----- .../runtime/src/millau_messages.rs | 64 ++-- bin/rialto/runtime/src/millau_messages.rs | 68 ++-- bin/rialto/runtime/src/xcm_config.rs | 177 +++++---- bin/runtime-common/src/integrity.rs | 2 +- bin/runtime-common/src/messages.rs | 355 ++---------------- .../src/messages_xcm_extension.rs | 32 +- bin/runtime-common/src/mock.rs | 46 +-- primitives/runtime/src/lib.rs | 4 +- relays/bin-substrate/src/chains/millau.rs | 29 +- relays/bin-substrate/src/chains/rialto.rs | 21 +- .../src/chains/rialto_parachain.rs | 22 +- relays/bin-substrate/src/cli/bridge.rs | 22 -- .../bin-substrate/src/cli/encode_message.rs | 18 +- relays/bin-substrate/src/cli/send_message.rs | 7 +- 21 files changed, 610 insertions(+), 895 deletions(-) diff --git a/README.md b/README.md index b588502642622..aab6007d2cd24 100644 --- a/README.md +++ b/README.md @@ -215,18 +215,19 @@ In this section we'll show you how to quickly send a bridge message. The message After sending a message you will see the following logs showing a message was successfully sent: ``` -INFO bridge Sending message to Rialto. Size: 5. +INFO bridge Sending message to Rialto. Size: 11. TRACE bridge Sent transaction to Millau node: 0x5e68... ``` And at the Rialto node logs you'll something like this: ``` -... runtime::bridge-dispatch: Going to execute message ([0, 0, 0, 0], 1) (...), Trap(43)]) -... runtime::bridge-dispatch: Incoming message ([0, 0, 0, 0], 1) dispatched with result: Incomplete(2000000000, Trap(43)) +... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: 48559)/Weight(ref_time: 1215065371, proof_size: 54703). ``` -It means that the message has been delivered and successfully dispatched. +It means that the message has been delivered and dispatched. Message may be dispatched with an +error, though - the goal of our test bridge is to ensure that messages are successfully delivered +and all involved components are working. ## Full Network Docker Compose Setup diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 574b0569875c6..f08f5e1c7496b 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1021,10 +1021,8 @@ impl_runtime_apis! { } fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - use bridge_runtime_common::messages::MessageBridge; - let lane = >::bench_lane_id(); - let bridged_chain_id = WithRialtoParachainMessageBridge::BRIDGED_CHAIN_ID; + let bridged_chain_id = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; pallet_bridge_relayers::Pallet::::relayer_reward( relayer, RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) @@ -1054,10 +1052,8 @@ impl_runtime_apis! { } fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - use bridge_runtime_common::messages::MessageBridge; - let lane = >::bench_lane_id(); - let bridged_chain_id = WithRialtoMessageBridge::BRIDGED_CHAIN_ID; + let bridged_chain_id = bp_runtime::RIALTO_CHAIN_ID; pallet_bridge_relayers::Pallet::::relayer_reward( relayer, RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 919fac868996f..311805c984921 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -16,14 +16,18 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{RialtoGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use crate::{RialtoGrandpaInstance, Runtime, RuntimeOrigin, WithRialtoMessagesInstance}; + +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -48,7 +52,7 @@ pub type ToRialtoMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Messages proof for Rialto -> Millau messages. pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -58,12 +62,13 @@ pub type ToRialtoMessagesDeliveryProof = messages::source::FromBridgedChainMessagesDeliveryProof; /// Call-dispatch based message dispatch for Rialto -> Millau messages. -pub type FromRialtoMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithRialtoMessageBridge, - xcm_executor::XcmExecutor, - crate::xcm_config::XcmWeigher, - WeightCredit, ->; +pub type FromRialtoMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_millau::Millau, + bp_rialto::Rialto, + crate::xcm_config::OnMillauBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + >; /// Maximal outbound payload size of Millau -> Rialto messages. pub type ToRialtoMaximalOutboundPayloadSize = @@ -74,8 +79,6 @@ pub type ToRialtoMaximalOutboundPayloadSize = pub struct WithRialtoMessageBridge; impl MessageBridge for WithRialtoMessageBridge { - const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; @@ -94,15 +97,6 @@ impl messages::UnderlyingChainProvider for Millau { impl messages::ThisChainWithMessages for Millau { type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// Rialto chain from message lane point of view. @@ -117,9 +111,29 @@ impl messages::UnderlyingChainProvider for Rialto { type Chain = bp_rialto::Rialto; } -impl messages::BridgedChainWithMessages for Rialto { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for Rialto {} + +/// Export XCM messages to be relayed to Rialto. +pub type ToRialtoBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + crate::xcm_config::RialtoNetwork, + (), +>; + +/// To-Rialto XCM hauler. +pub struct ToRialtoXcmBlobHauler; + +impl XcmBlobHauler for ToRialtoXcmBlobHauler { + type MessageSender = pallet_bridge_messages::Pallet; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) + .into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 1cfdc9c8f4940..17495e26ae218 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -16,14 +16,20 @@ //! Everything required to serve Millau <-> RialtoParachain messages. -use crate::{Runtime, RuntimeCall, RuntimeOrigin, WithRialtoParachainsInstance}; +use crate::{ + Runtime, RuntimeOrigin, WithRialtoParachainMessagesInstance, WithRialtoParachainsInstance, +}; -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto parachain. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -48,16 +54,16 @@ pub type ToRialtoParachainMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessagePayload = - messages::target::FromBridgedChainMessagePayload; +pub type FromRialtoParachainMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithRialtoParachainMessageBridge, - xcm_executor::XcmExecutor, - crate::xcm_config::XcmWeigher, - WeightCredit, ->; +pub type FromRialtoParachainMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_millau::Millau, + bp_rialto::Rialto, + crate::xcm_config::OnMillauBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + >; /// Maximal outbound payload size of Millau -> RialtoParachain messages. pub type ToRialtoParachainMaximalOutboundPayloadSize = @@ -68,8 +74,6 @@ pub type ToRialtoParachainMaximalOutboundPayloadSize = pub struct WithRialtoParachainMessageBridge; impl MessageBridge for WithRialtoParachainMessageBridge { - const THIS_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; type ThisChain = Millau; @@ -90,16 +94,7 @@ impl messages::UnderlyingChainProvider for Millau { } impl messages::ThisChainWithMessages for Millau { - type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// RialtoParachain chain from message lane point of view. @@ -116,8 +111,29 @@ impl messages::UnderlyingChainProvider for RialtoParachain { type Chain = bp_rialto_parachain::RialtoParachain; } -impl messages::BridgedChainWithMessages for RialtoParachain { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for RialtoParachain {} + +/// Export XCM messages to be relayed to Rialto. +pub type ToRialtoParachainBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + crate::xcm_config::RialtoParachainNetwork, + (), +>; + +/// To-RialtoParachain XCM hauler. +pub struct ToRialtoParachainXcmBlobHauler; + +impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { + type MessageSender = + pallet_bridge_messages::Pallet; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) + .into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index aaaa7bf642db3..c477a684526d6 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -17,18 +17,12 @@ //! XCM configurations for the Millau runtime. use super::{ - rialto_messages::{WithRialtoMessageBridge, XCM_LANE}, - rialto_parachain_messages::{WithRialtoParachainMessageBridge, XCM_LANE as XCM_LANE_PARACHAIN}, - AccountId, AllPalletsWithSystem, Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, XcmPallet, + rialto_messages::ToRialtoBlobExporter, + rialto_parachain_messages::ToRialtoParachainBlobExporter, AccountId, AllPalletsWithSystem, + Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, }; -use bp_messages::LaneId; use bp_millau::WeightToFee; -use bp_rialto_parachain::RIALTO_PARACHAIN_ID; -use bridge_runtime_common::{ - messages::source::{XcmBridge, XcmBridgeAdapter}, - CustomNetworkId, -}; +use bridge_runtime_common::CustomNetworkId; use frame_support::{ parameter_types, traits::{ConstU32, Everything, Nothing}, @@ -36,10 +30,11 @@ use frame_support::{ }; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, }; +use xcm_executor::traits::ExportXcm; parameter_types! { /// The location of the `MLAU` token, from the context of this chain. Since this token is native to this @@ -101,32 +96,28 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our -/// individual routers. -pub type XcmRouter = ( - // Router to send messages to Rialto. - XcmBridgeAdapter, - // Router to send messages to RialtoParachains. - XcmBridgeAdapter, -); +/// The XCM router. We are not sending messages to sibling/parent/child chains here. +pub type XcmRouter = (); /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( // Weight that is paid for may be consumed. TakeWeightCredit, - // If the message is one that immediately attemps to pay for execution, then allow it. - AllowTopLevelPaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, ); +/// Dispatches received XCM messages from other chain. +pub type OnMillauBlobDispatcher = xcm_builder::BridgeBlobDispatcher< + crate::xcm_config::XcmRouter, + crate::xcm_config::UniversalLocation, +>; + /// XCM weigher type. pub type XcmWeigher = xcm_builder::FixedWeightBounds; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type XcmSender = (); type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; type IsReserve = (); @@ -145,7 +136,7 @@ impl xcm_executor::Config for XcmConfig { type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToRialtoOrRialtoParachainSwitchExporter; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -160,7 +151,7 @@ pub type LocalOriginToLocation = ( #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); + pub ReachableDest: Option = None; } impl pallet_xcm::Config for Runtime { @@ -170,7 +161,7 @@ impl pallet_xcm::Config for Runtime { // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will // make `DescendOrigin` a bit more useful. type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmRouter = XcmRouter; + type XcmRouter = (); // Anyone can execute XCM messages locally. type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmExecuteFilter = Everything; @@ -197,70 +188,66 @@ impl pallet_xcm::Config for Runtime { type ReachableDest = ReachableDest; } -/// With-Rialto bridge. -pub struct ToRialtoBridge; - -impl XcmBridge for ToRialtoBridge { - type MessageBridge = WithRialtoMessageBridge; - type MessageSender = pallet_bridge_messages::Pallet; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() +pub struct ToRialtoOrRialtoParachainSwitchExporter; + +impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { + type Ticket = (NetworkId, (sp_std::prelude::Vec, XcmHash)); + + fn validate( + network: NetworkId, + channel: u32, + universal_source: &mut Option, + destination: &mut Option, + message: &mut Option>, + ) -> SendResult { + if network == RialtoNetwork::get() { + ToRialtoBlobExporter::validate(network, channel, universal_source, destination, message) + .map(|result| ((RialtoNetwork::get(), result.0), result.1)) + } else if network == RialtoParachainNetwork::get() { + ToRialtoParachainBlobExporter::validate( + network, + channel, + universal_source, + destination, + message, + ) + .map(|result| ((RialtoParachainNetwork::get(), result.0), result.1)) + } else { + Err(SendError::Unroutable) + } } - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == RialtoNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = RialtoNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> LaneId { - XCM_LANE - } -} - -/// With-RialtoParachain bridge. -pub struct ToRialtoParachainBridge; - -impl XcmBridge for ToRialtoParachainBridge { - type MessageBridge = WithRialtoParachainMessageBridge; - type MessageSender = - pallet_bridge_messages::Pallet; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() - } - - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X2(GlobalConsensus(r), Parachain(RIALTO_PARACHAIN_ID)) } if r == RialtoNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = RialtoParachainNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> LaneId { - XCM_LANE_PARACHAIN + fn deliver(ticket: Self::Ticket) -> Result { + let (network, ticket) = ticket; + if network == RialtoNetwork::get() { + ToRialtoBlobExporter::deliver(ticket) + } else if network == RialtoParachainNetwork::get() { + ToRialtoParachainBlobExporter::deliver(ticket) + } else { + Err(SendError::Unroutable) + } } } #[cfg(test)] mod tests { use super::*; - use crate::rialto_messages::WeightCredit; + use crate::{ + rialto_messages::FromRialtoMessageDispatch, + rialto_parachain_messages::FromRialtoParachainMessageDispatch, DbWeight, + WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, + }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - MessageKey, + LaneId, MessageKey, + }; + use bridge_runtime_common::messages_xcm_extension::{ + XcmBlobMessageDispatchResult, XcmRouterWeigher, }; - use bp_runtime::messages::MessageDispatchResult; - use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; use codec::Encode; + use pallet_bridge_messages::OutboundLanes; + use sp_core::Get; + use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -268,59 +255,128 @@ mod tests { ) } + fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm { + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: vec![Instruction::Trap(42)].into(), + }] + .into() + } + #[test] - fn xcm_messages_are_sent_using_bridge_router() { + fn xcm_messages_to_rialto_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); - let expected_hash = - ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - - // message 1 to Rialto - let dest = (Parent, X1(GlobalConsensus(RialtoNetwork::get()))); - let send_result = send_xcm::(dest.into(), xcm.clone()); - assert_eq!(send_result, Ok((expected_hash, expected_fee.clone()))); - - // message 2 to RialtoParachain (expected hash is the same, since other lane is used) - let dest = - (Parent, X2(GlobalConsensus(RialtoNetwork::get()), Parachain(RIALTO_PARACHAIN_ID))); - let send_result = send_xcm::(dest.into(), xcm); - assert_eq!(send_result, Ok((expected_hash, expected_fee))); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::::get( + crate::rialto_messages::XCM_LANE + ) + .latest_generated_nonce, + 0, + ); + + // export message instruction "sends" message to Rialto + XcmExecutor::::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(RialtoNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued + assert_eq!( + OutboundLanes::::get( + crate::rialto_messages::XCM_LANE + ) + .latest_generated_nonce, + 1, + ); }) } #[test] - fn xcm_messages_from_rialto_are_dispatched() { - type XcmExecutor = xcm_executor::XcmExecutor; - type MessageDispatcher = FromBridgedChainMessageDispatch< - WithRialtoMessageBridge, - XcmExecutor, - XcmWeigher, - WeightCredit, - >; - + fn xcm_messages_to_rialto_parachain_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - let location: MultiLocation = - (Parent, X1(GlobalConsensus(RialtoNetwork::get()))).into(); - let xcm: Xcm = vec![Instruction::Trap(42)].into(); - - let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()) }, - }; - - let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, BaseXcmWeight::get()); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::::get( + crate::rialto_parachain_messages::XCM_LANE + ) + .latest_generated_nonce, + 0, + ); - let dispatch_result = - MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + // export message instruction "sends" message to Rialto + XcmExecutor::::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(RialtoParachainNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued assert_eq!( - dispatch_result, - MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::zero(), - dispatch_level_result: (), - } + OutboundLanes::::get( + crate::rialto_parachain_messages::XCM_LANE + ) + .latest_generated_nonce, + 1, ); }) } + + fn prepare_inbound_bridge_message() -> DispatchMessage> { + let xcm = xcm::VersionedXcm::::V3(vec![Instruction::Trap(42)].into()); + let location = + xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + let bridge_message = (location, xcm).encode(); + DispatchMessage { + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, + data: DispatchMessageData { payload: Ok(bridge_message) }, + } + } + + #[test] + fn xcm_messages_from_rialto_are_dispatched() { + let mut incoming_message = prepare_inbound_bridge_message(); + + let dispatch_weight = FromRialtoMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch + let dispatch_result = + FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + } + + #[test] + fn xcm_messages_from_rialto_parachain_are_dispatched() { + let mut incoming_message = prepare_inbound_bridge_message(); + + let dispatch_weight = + FromRialtoParachainMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch + let dispatch_result = + FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + } } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index ec8955e7fd1b0..ed193b4e68157 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -111,6 +111,7 @@ std = [ "frame-support/std", "frame-executive/std", "frame-system/std", + "frame-system-rpc-runtime-api/std", "pallet-balances/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", @@ -118,6 +119,7 @@ std = [ "pallet-timestamp/std", "pallet-sudo/std", "pallet-transaction-payment/std", + "pallet-transaction-payment-rpc-runtime-api/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 3614bacdc10ad..58c6a8c673f9b 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -26,12 +26,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -use crate::millau_messages::{WithMillauMessageBridge, XCM_LANE}; - -use bridge_runtime_common::{ - generate_bridge_reject_obsolete_headers_and_messages, - messages::source::{XcmBridge, XcmBridgeAdapter}, -}; +use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::AnyRelayNumber; use scale_info::TypeInfo; @@ -88,11 +83,10 @@ use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, - EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentAsSuperuser, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, + AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, + NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; use xcm_executor::{Config, XcmExecutor}; @@ -351,7 +345,7 @@ parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); pub RelayOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = X1(Parachain(ParachainInfo::parachain_id().into())); + pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); /// The Millau network ID. pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); /// The RialtoParachain network ID. @@ -412,8 +406,8 @@ pub type XcmOriginToTransactDispatchOrigin = ( // the following constant must match the similar constant in the Millau runtime. parameter_types! { - /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 64 * 1024); + /// The amount of weight an XCM operation takes. We don't care much about those values as we're on testnet. + pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 1024); // One UNIT buys 1 second of weight. pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); pub const MaxInstructions: u32 = 100; @@ -428,12 +422,11 @@ match_types! { }; } -pub type Barrier = ( - TakeWeightCredit, - AllowTopLevelPaidExecutionFrom, - AllowUnpaidExecutionFrom, - // ^^^ Parent & its unit plurality gets free execution -); +pub type Barrier = TakeWeightCredit; + +/// Dispatches received XCM messages from other chain. +pub type OnRialtoParachainBlobDispatcher = + xcm_builder::BridgeBlobDispatcher; /// XCM weigher type. pub type XcmWeigher = FixedWeightBounds; @@ -441,7 +434,7 @@ pub type XcmWeigher = FixedWeightBounds; -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = ( - // Bridge is used to communicate with other relay chain (Millau). - XcmBridgeAdapter, -); - -/// With-Millau bridge. -pub struct ToMillauBridge; - -impl XcmBridge for ToMillauBridge { - type MessageBridge = WithMillauMessageBridge; - type MessageSender = pallet_bridge_messages::Pallet; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() - } - - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = MillauNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> bp_messages::LaneId { - XCM_LANE - } -} +/// The XCM router. We are not sending messages to sibling/parent/child chains here. +pub type XcmRouter = (); #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); + pub ReachableDest: Option = None; } impl pallet_xcm::Config for Runtime { @@ -875,17 +838,20 @@ cumulus_pallet_parachain_system::register_validate_block!( #[cfg(test)] mod tests { use super::*; - use crate::millau_messages::WeightCredit; + use crate::millau_messages::{FromMillauMessageDispatch, XCM_LANE}; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bp_runtime::messages::MessageDispatchResult; use bridge_runtime_common::{ - integrity::check_additional_signed, messages::target::FromBridgedChainMessageDispatch, + integrity::check_additional_signed, + messages_xcm_extension::{XcmBlobMessageDispatchResult, XcmRouterWeigher}, }; use codec::Encode; + use pallet_bridge_messages::OutboundLanes; + use sp_core::Get; use sp_runtime::generic::Era; + use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -893,54 +859,75 @@ mod tests { ) } + fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm { + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: vec![Instruction::Trap(42)].into(), + }] + .into() + } + #[test] - fn xcm_messages_to_millau_are_sent() { + fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - // the encoded message (origin ++ xcm) is 0x010109020419A8 - let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); - let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - - let send_result = send_xcm::(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, Fungibility::Fungible(1_000_000_u128))); - let expected_hash = - ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - assert_eq!(send_result, Ok((expected_hash, expected_fee)),); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::::get(XCM_LANE) + .latest_generated_nonce, + 0, + ); + + // export message instruction "sends" message to Rialto + XcmExecutor::::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(MillauNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued + assert_eq!( + OutboundLanes::::get(XCM_LANE) + .latest_generated_nonce, + 1, + ); }) } + fn prepare_inbound_bridge_message() -> DispatchMessage> { + let xcm = xcm::VersionedXcm::::V3(vec![Instruction::Trap(42)].into()); + let location = + xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + let bridge_message = (location, xcm).encode(); + DispatchMessage { + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, + data: DispatchMessageData { payload: Ok(bridge_message) }, + } + } + #[test] fn xcm_messages_from_millau_are_dispatched() { - type XcmExecutor = xcm_executor::XcmExecutor; - type MessageDispatcher = FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - XcmExecutor, - XcmWeigher, - WeightCredit, - >; - new_test_ext().execute_with(|| { - let location: MultiLocation = - (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); - let xcm: Xcm = vec![Instruction::Trap(42)].into(); + let mut incoming_message = prepare_inbound_bridge_message(); - let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()) }, - }; - - let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, UnitWeightCost::get()); + let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::<()>::get()); + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch let dispatch_result = - MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); - assert_eq!( - dispatch_result, - MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::zero(), - dispatch_level_result: (), - } - ); - }) + FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + }); } #[test] diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index ee7a089992ebb..3fff141bf8484 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -19,14 +19,18 @@ // TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. // Should be extracted to a separate crate and reused here. -use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance}; + +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Millau. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -51,15 +55,16 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> RialtoParachain messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. -pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - xcm_executor::XcmExecutor, - crate::XcmWeigher, - WeightCredit, ->; +pub type FromMillauMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_rialto_parachain::RialtoParachain, + bp_millau::Millau, + crate::OnRialtoParachainBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<()>, + >; /// Messages proof for Millau -> RialtoParachain messages. pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -77,8 +82,6 @@ pub type ToMillauMaximalOutboundPayloadSize = pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const THIS_CHAIN_ID: ChainId = RIALTO_PARACHAIN_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; @@ -97,16 +100,7 @@ impl messages::UnderlyingChainProvider for RialtoParachain { } impl messages::ThisChainWithMessages for RialtoParachain { - type RuntimeCall = RuntimeCall; type RuntimeOrigin = RuntimeOrigin; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// Millau chain from message lane point of view. @@ -121,8 +115,24 @@ impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } -impl messages::BridgedChainWithMessages for Millau { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for Millau {} + +/// Export XCM messages to be relayed to Millau. +pub type ToMillauBlobExporter = + HaulBlobExporter, crate::MillauNetwork, ()>; + +/// To-Millau XCM hauler. +pub struct ToMillauXcmBlobHauler; + +impl XcmBlobHauler for ToMillauXcmBlobHauler { + type MessageSender = pallet_bridge_messages::Pallet; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::UniversalLocation::get())).into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index ff08c08029ae9..9d0c4f97c898c 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -16,14 +16,18 @@ //! Everything required to serve Millau <-> Rialto messages. -use crate::{MillauGrandpaInstance, Runtime, RuntimeCall, RuntimeOrigin}; - -use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{ChainId, MILLAU_CHAIN_ID, RIALTO_CHAIN_ID}; -use bridge_runtime_common::messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, +use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance}; + +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages::{ + self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, + }, + messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; +use xcm_builder::HaulBlobExporter; /// Lane that is used for XCM messages exchange. pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); @@ -48,15 +52,16 @@ pub type ToMillauMessageVerifier = messages::source::FromThisChainMessageVerifier; /// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; +pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; /// Call-dispatch based message dispatch for Millau -> Rialto messages. -pub type FromMillauMessageDispatch = messages::target::FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - xcm_executor::XcmExecutor, - crate::xcm_config::XcmWeigher, - WeightCredit, ->; +pub type FromMillauMessageDispatch = + bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< + bp_rialto::Rialto, + bp_millau::Millau, + crate::xcm_config::OnRialtoBlobDispatcher, + bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + >; /// Messages proof for Millau -> Rialto messages. pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; @@ -74,8 +79,6 @@ pub type ToMillauMaximalOutboundPayloadSize = pub struct WithMillauMessageBridge; impl MessageBridge for WithMillauMessageBridge { - const THIS_CHAIN_ID: ChainId = RIALTO_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = MILLAU_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; type ThisChain = Rialto; @@ -94,15 +97,6 @@ impl messages::UnderlyingChainProvider for Rialto { impl messages::ThisChainWithMessages for Rialto { type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - true - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MessageNonce::MAX - } } /// Millau chain from message lane point of view. @@ -117,9 +111,29 @@ impl messages::UnderlyingChainProvider for Millau { type Chain = bp_millau::Millau; } -impl messages::BridgedChainWithMessages for Millau { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - true +impl messages::BridgedChainWithMessages for Millau {} + +/// Export XCM messages to be relayed to Millau. +pub type ToMillauBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + crate::xcm_config::MillauNetwork, + (), +>; + +/// To-Millau XCM hauler. +pub struct ToMillauXcmBlobHauler; + +impl XcmBlobHauler for ToMillauXcmBlobHauler { + type MessageSender = pallet_bridge_messages::Pallet; + type MessageSenderOrigin = RuntimeOrigin; + + fn message_sender_origin() -> RuntimeOrigin { + pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) + .into() + } + + fn xcm_lane() -> LaneId { + XCM_LANE } } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 174ece0472518..64a5a896f95e1 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -17,14 +17,11 @@ //! XCM configurations for the Rialto runtime. use super::{ - millau_messages::WithMillauMessageBridge, AccountId, AllPalletsWithSystem, Balances, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, WithMillauMessagesInstance, XcmPallet, + millau_messages::ToMillauBlobExporter, AccountId, AllPalletsWithSystem, Balances, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, }; use bp_rialto::WeightToFee; -use bridge_runtime_common::{ - messages::source::{XcmBridge, XcmBridgeAdapter}, - CustomNetworkId, -}; +use bridge_runtime_common::CustomNetworkId; use frame_support::{ parameter_types, traits::{ConstU32, Everything, Nothing}, @@ -32,9 +29,9 @@ use frame_support::{ }; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, }; parameter_types! { @@ -95,30 +92,28 @@ parameter_types! { pub const MaxInstructions: u32 = 100; } -/// The XCM router. When we want to send an XCM message, we use this type. It amalgamates all of our -/// individual routers. -pub type XcmRouter = ( - // Router to send messages to Millau. - XcmBridgeAdapter, -); +/// The XCM router. We are not sending messages to sibling/parent/child chains here. +pub type XcmRouter = (); /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( // Weight that is paid for may be consumed. TakeWeightCredit, - // If the message is one that immediately attemps to pay for execution, then allow it. - AllowTopLevelPaidExecutionFrom, - // Expected responses are OK. - AllowKnownQueryResponses, ); +/// Dispatches received XCM messages from other chain. +pub type OnRialtoBlobDispatcher = xcm_builder::BridgeBlobDispatcher< + crate::xcm_config::XcmRouter, + crate::xcm_config::UniversalLocation, +>; + /// Incoming XCM weigher type. pub type XcmWeigher = xcm_builder::FixedWeightBounds; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type XcmSender = (); type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; type IsReserve = (); @@ -137,7 +132,7 @@ impl xcm_executor::Config for XcmConfig { type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = ConstU32<64>; type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToMillauBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; @@ -152,7 +147,7 @@ pub type LocalOriginToLocation = ( #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option = todo!("We dont use benchmarks for pallet_xcm, so if you hit this message, you need to remove this and define value instead"); + pub ReachableDest: Option = None; } impl pallet_xcm::Config for Runtime { @@ -189,43 +184,24 @@ impl pallet_xcm::Config for Runtime { type ReachableDest = ReachableDest; } -/// With-Millau bridge. -pub struct ToMillauBridge; - -impl XcmBridge for ToMillauBridge { - type MessageBridge = WithMillauMessageBridge; - type MessageSender = pallet_bridge_messages::Pallet; - - fn universal_location() -> InteriorMultiLocation { - UniversalLocation::get() - } - - fn verify_destination(dest: &MultiLocation) -> bool { - matches!(*dest, MultiLocation { parents: 1, interior: X1(GlobalConsensus(r)) } if r == MillauNetwork::get()) - } - - fn build_destination() -> MultiLocation { - let dest: InteriorMultiLocation = MillauNetwork::get().into(); - let here = UniversalLocation::get(); - dest.relative_to(&here) - } - - fn xcm_lane() -> bp_messages::LaneId { - bp_messages::LaneId([0, 0, 0, 0]) - } -} - #[cfg(test)] mod tests { use super::*; - use crate::millau_messages::WeightCredit; + use crate::{ + millau_messages::{FromMillauMessageDispatch, XCM_LANE}, + DbWeight, WithMillauMessagesInstance, + }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bp_runtime::messages::MessageDispatchResult; - use bridge_runtime_common::messages::target::FromBridgedChainMessageDispatch; + use bridge_runtime_common::messages_xcm_extension::{ + XcmBlobMessageDispatchResult, XcmRouterWeigher, + }; use codec::Encode; + use pallet_bridge_messages::OutboundLanes; + use sp_core::Get; + use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( @@ -233,53 +209,72 @@ mod tests { ) } - #[test] - fn xcm_messages_to_millau_are_sent() { - new_test_ext().execute_with(|| { - // the encoded message (origin ++ xcm) is 0x010109030419A8 - let dest = (Parent, X1(GlobalConsensus(MillauNetwork::get()))); - let xcm: Xcm<()> = vec![Instruction::Trap(42)].into(); - - let send_result = send_xcm::(dest.into(), xcm); - let expected_fee = MultiAssets::from((Here, 1_000_000_u128)); - let expected_hash = - ([0u8, 0u8, 0u8, 0u8], 1u64).using_encoded(sp_io::hashing::blake2_256); - assert_eq!(send_result, Ok((expected_hash, expected_fee)),); - }) + fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm { + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: vec![Instruction::Trap(42)].into(), + }] + .into() } #[test] - fn xcm_messages_from_millau_are_dispatched() { - type XcmExecutor = xcm_executor::XcmExecutor; - type MessageDispatcher = FromBridgedChainMessageDispatch< - WithMillauMessageBridge, - XcmExecutor, - XcmWeigher, - WeightCredit, - >; - + fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { new_test_ext().execute_with(|| { - let location: MultiLocation = - (Parent, X1(GlobalConsensus(MillauNetwork::get()))).into(); - let xcm: Xcm = vec![Instruction::Trap(42)].into(); - - let mut incoming_message = DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok((location, xcm).into()) }, - }; - - let dispatch_weight = MessageDispatcher::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, BaseXcmWeight::get()); + // ensure that the there are no messages queued + assert_eq!( + OutboundLanes::::get(XCM_LANE) + .latest_generated_nonce, + 0, + ); - let dispatch_result = - MessageDispatcher::dispatch(&AccountId::from([0u8; 32]), incoming_message); + // export message instruction "sends" message to Rialto + XcmExecutor::::execute_xcm_in_credit( + Here, + prepare_outbound_xcm_message(MillauNetwork::get()), + Default::default(), + Weight::MAX, + Weight::MAX, + ) + .ensure_complete() + .expect("runtime configuration must be correct"); + + // ensure that the message has been queued assert_eq!( - dispatch_result, - MessageDispatchResult { - unspent_weight: frame_support::weights::Weight::zero(), - dispatch_level_result: (), - } + OutboundLanes::::get(XCM_LANE) + .latest_generated_nonce, + 1, ); }) } + + fn prepare_inbound_bridge_message() -> DispatchMessage> { + let xcm = xcm::VersionedXcm::::V3(vec![Instruction::Trap(42)].into()); + let location = + xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + let bridge_message = (location, xcm).encode(); + DispatchMessage { + key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, + data: DispatchMessageData { payload: Ok(bridge_message) }, + } + } + + #[test] + fn xcm_messages_from_millau_are_dispatched() { + let mut incoming_message = prepare_inbound_bridge_message(); + + let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); + assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + + // we care only about handing message to the XCM dispatcher, so we don't care about its + // actual dispatch + let dispatch_result = + FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + assert!(matches!( + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), + )); + } } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 5a2c796ee43b9..96716fe851cb2 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -83,7 +83,7 @@ macro_rules! assert_bridge_messages_pallet_types( use $crate::messages::{ source::{FromThisChainMessagePayload, TargetHeaderChainAdapter}, target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter}, - AccountIdOf, BalanceOf, BridgedChain, CallOf, ThisChain, + AccountIdOf, BalanceOf, BridgedChain, ThisChain, }; use pallet_bridge_messages::Config as MessagesConfig; use static_assertions::assert_type_eq_all; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 4493ac66742f0..9d2e5811380c5 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -25,28 +25,18 @@ pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider}; use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ source_chain::{LaneMessageVerifier, TargetHeaderChain}, - target_chain::{ - DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, - }, + target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, }; -use bp_runtime::{ - messages::MessageDispatchResult, Chain, ChainId, RawStorageProof, Size, StorageProofChecker, - StorageProofError, -}; -use codec::{Decode, DecodeLimit, Encode}; +use bp_runtime::{Chain, RawStorageProof, Size, StorageProofChecker, StorageProofError}; +use codec::{Decode, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; -use xcm::latest::prelude::*; /// Bidirectional message bridge. pub trait MessageBridge { - /// Identifier of this chain. - const THIS_CHAIN_ID: ChainId; - /// Identifier of the Bridged chain. - const BRIDGED_CHAIN_ID: ChainId; /// Name of the paired messages pallet instance at the Bridged chain. /// /// Should be the name that is used in the `construct_runtime!()` macro. @@ -64,24 +54,10 @@ pub trait MessageBridge { pub trait ThisChainWithMessages: UnderlyingChainProvider { /// Call origin on the chain. type RuntimeOrigin; - /// Call type on the chain. - type RuntimeCall: Encode + Decode; - - /// Do we accept message sent by given origin to given lane? - fn is_message_accepted(origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool; - - /// Maximal number of pending (not yet delivered) messages at This chain. - /// - /// Any messages over this limit, will be rejected. - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce; } /// Bridged chain that has `pallet-bridge-messages` module. -pub trait BridgedChainWithMessages: UnderlyingChainProvider { - /// Returns `true` if message dispatch weight is withing expected limits. `false` means - /// that the message is too heavy to be sent over the bridge and shall be rejected. - fn verify_dispatch_weight(message_payload: &[u8]) -> bool; -} +pub trait BridgedChainWithMessages: UnderlyingChainProvider {} /// This chain in context of message bridge. pub type ThisChain = ::ThisChain; @@ -97,8 +73,6 @@ pub type AccountIdOf = bp_runtime::AccountIdOf>; pub type BalanceOf = bp_runtime::BalanceOf>; /// Type of origin that is used on the chain. pub type OriginOf = ::RuntimeOrigin; -/// Type of call that is used on this chain. -pub type CallOf = ::RuntimeCall; /// Error that happens during message verification. #[derive(Debug, PartialEq, Eq)] @@ -128,7 +102,7 @@ pub mod source { use super::*; /// Message payload for This -> Bridged chain messages. - pub type FromThisChainMessagePayload = Vec; + pub type FromThisChainMessagePayload = crate::messages_xcm_extension::XcmAsPlainPayload; /// Maximal size of outbound message payload. pub struct FromThisChainMaximalOutboundPayloadSize(PhantomData); @@ -186,13 +160,6 @@ pub mod source { #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); - /// The error message returned from `LaneMessageVerifier` when outbound lane is disabled. - pub const MESSAGE_REJECTED_BY_OUTBOUND_LANE: &str = - "The outbound message lane has rejected the message."; - /// The error message returned from `LaneMessageVerifier` when too many pending messages at the - /// lane. - pub const TOO_MANY_PENDING_MESSAGES: &str = "Too many pending messages at the lane."; - impl LaneMessageVerifier>, FromThisChainMessagePayload> for FromThisChainMessageVerifier where @@ -205,24 +172,16 @@ pub mod source { type Error = &'static str; fn verify_message( - submitter: &OriginOf>, - lane: &LaneId, - lane_outbound_data: &OutboundLaneData, + _submitter: &OriginOf>, + _lane: &LaneId, + _lane_outbound_data: &OutboundLaneData, _payload: &FromThisChainMessagePayload, ) -> Result<(), Self::Error> { - // reject message if lane is blocked - if !ThisChain::::is_message_accepted(submitter, lane) { - return Err(MESSAGE_REJECTED_BY_OUTBOUND_LANE) - } - - // reject message if there are too many pending messages at this lane - let max_pending_messages = ThisChain::::maximal_pending_messages_at_outbound_lane(); - let pending_messages = lane_outbound_data - .latest_generated_nonce - .saturating_sub(lane_outbound_data.latest_received_nonce); - if pending_messages > max_pending_messages { - return Err(TOO_MANY_PENDING_MESSAGES) - } + // IMPORTANT: any error that is returned here is fatal for the bridge, because + // this code is executed at the bridge hub and message sender actually lives + // at some sibling parachain. So we are failing **after** the message has been + // sent and we can't report it back to sender (unless error report mechanism is + // embedded into message and its dispatcher). Ok(()) } @@ -263,9 +222,15 @@ pub mod source { pub fn verify_chain_message( payload: &FromThisChainMessagePayload, ) -> Result<(), Error> { - if !BridgedChain::::verify_dispatch_weight(payload) { - return Err(Error::InvalidMessageWeight) - } + // IMPORTANT: any error that is returned here is fatal for the bridge, because + // this code is executed at the bridge hub and message sender actually lives + // at some sibling parachain. So we are failing **after** the message has been + // sent and we can't report it back to sender (unless error report mechanism is + // embedded into message and its dispatcher). + + // apart from maximal message size check (see below), we should also check the message + // dispatch weight here. But we assume that the bridged chain will just push the message + // to some queue (XCMP, UMP, DMP), so the weight is constant and fits the block. // The maximal size of extrinsic at Substrate-based chain depends on the // `frame_system::Config::MaximumBlockLength` and @@ -316,92 +281,6 @@ pub mod source { ) .map_err(Error::HeaderChain)? } - - /// XCM bridge. - pub trait XcmBridge { - /// Runtime message bridge configuration. - type MessageBridge: MessageBridge; - /// Runtime message sender adapter. - type MessageSender: bp_messages::source_chain::MessagesBridge< - OriginOf>, - FromThisChainMessagePayload, - >; - - /// Our location within the Consensus Universe. - fn universal_location() -> InteriorMultiLocation; - /// Verify that the adapter is responsible for handling given XCM destination. - fn verify_destination(dest: &MultiLocation) -> bool; - /// Build route from this chain to the XCM destination. - fn build_destination() -> MultiLocation; - /// Return message lane used to deliver XCM messages. - fn xcm_lane() -> LaneId; - } - - /// XCM bridge adapter for `bridge-messages` pallet. - pub struct XcmBridgeAdapter(PhantomData); - - impl SendXcm for XcmBridgeAdapter - where - BalanceOf>: Into, - OriginOf>: From, - { - type Ticket = FromThisChainMessagePayload; - - fn validate( - dest: &mut Option, - msg: &mut Option>, - ) -> SendResult { - let d = dest.take().ok_or(SendError::MissingArgument)?; - if !T::verify_destination(&d) { - *dest = Some(d); - return Err(SendError::NotApplicable) - } - - let route = T::build_destination(); - let msg = (route, msg.take().ok_or(SendError::MissingArgument)?).encode(); - - // let's just take fixed (out of thin air) fee per message in our test bridges - // (this code won't be used in production anyway) - let fee_assets = MultiAssets::from((Here, 1_000_000_u128)); - - Ok((msg, fee_assets)) - } - - fn deliver(ticket: Self::Ticket) -> Result { - use bp_messages::source_chain::MessagesBridge; - - let lane = T::xcm_lane(); - let msg = ticket; - let result = T::MessageSender::send_message( - pallet_xcm::Origin::from(MultiLocation::from(T::universal_location())).into(), - lane, - msg, - ); - result - .map(|artifacts| { - let hash = (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256); - log::debug!( - target: "runtime::bridge", - "Sent XCM message {:?}/{} to {:?}: {:?}", - lane, - artifacts.nonce, - T::MessageBridge::BRIDGED_CHAIN_ID, - hash, - ); - hash - }) - .map_err(|e| { - log::debug!( - target: "runtime::bridge", - "Failed to send XCM message over lane {:?} to {:?}: {:?}", - lane, - T::MessageBridge::BRIDGED_CHAIN_ID, - e, - ); - SendError::Transport("Bridge has rejected the message") - }) - } - } } /// Sub-module that is declaring types required for processing Bridged -> This chain messages. @@ -409,35 +288,7 @@ pub mod target { use super::*; /// Decoded Bridged -> This message payload. - #[derive(RuntimeDebug, PartialEq, Eq)] - pub struct FromBridgedChainMessagePayload { - /// Data that is actually sent over the wire. - pub xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm), - /// Weight of the message, computed by the weigher. Unknown initially. - pub weight: Option, - } - - impl Decode for FromBridgedChainMessagePayload { - fn decode(input: &mut I) -> Result { - let _: codec::Compact = Decode::decode(input)?; - type XcmPairType = (xcm::v3::MultiLocation, xcm::v3::Xcm); - Ok(FromBridgedChainMessagePayload { - xcm: XcmPairType::::decode_with_depth_limit( - sp_api::MAX_EXTRINSIC_DEPTH, - input, - )?, - weight: None, - }) - } - } - - impl From<(xcm::v3::MultiLocation, xcm::v3::Xcm)> - for FromBridgedChainMessagePayload - { - fn from(xcm: (xcm::v3::MultiLocation, xcm::v3::Xcm)) -> Self { - FromBridgedChainMessagePayload { xcm, weight: None } - } - } + pub type FromBridgedChainMessagePayload = crate::messages_xcm_extension::XcmAsPlainPayload; /// Messages proof from bridged chain: /// @@ -470,118 +321,6 @@ pub mod target { } } - /// Dispatching Bridged -> This chain messages. - #[derive(RuntimeDebug, Clone, Copy)] - pub struct FromBridgedChainMessageDispatch { - _marker: PhantomData<(B, XcmExecutor, XcmWeigher, WeightCredit)>, - } - - impl - MessageDispatch>> - for FromBridgedChainMessageDispatch - where - XcmExecutor: xcm::v3::ExecuteXcm>>, - XcmWeigher: xcm_executor::traits::WeightBounds>>, - WeightCredit: Get, - { - type DispatchPayload = FromBridgedChainMessagePayload>>; - type DispatchLevelResult = (); - - fn dispatch_weight( - message: &mut DispatchMessage, - ) -> frame_support::weights::Weight { - match message.data.payload { - Ok(ref mut payload) => { - // I have no idea why this method takes `&mut` reference and there's nothing - // about that in documentation. Hope it'll only mutate iff error is returned. - let weight = XcmWeigher::weight(&mut payload.xcm.1); - let weight = weight.unwrap_or_else(|e| { - log::debug!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Failed to compute dispatch weight of incoming XCM message {:?}/{}: {:?}", - message.key.lane_id, - message.key.nonce, - e, - ); - - // we shall return 0 and then the XCM executor will fail to execute XCM - // if we'll return something else (e.g. maximal value), the lane may stuck - Weight::zero() - }); - - payload.weight = Some(weight); - weight - }, - _ => Weight::zero(), - } - } - - fn dispatch( - _relayer_account: &AccountIdOf>, - message: DispatchMessage, - ) -> MessageDispatchResult { - let message_id = (message.key.lane_id, message.key.nonce); - let do_dispatch = move || -> sp_std::result::Result { - let FromBridgedChainMessagePayload { xcm: (location, xcm), weight: weight_limit } = - message.data.payload?; - log::trace!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Going to execute message {:?} (weight limit: {:?}): {:?} {:?}", - message_id, - weight_limit, - location, - xcm, - ); - let hash = message_id.using_encoded(sp_io::hashing::blake2_256); - - // if this cod will end up in production, this most likely needs to be set to zero - let weight_credit = WeightCredit::get(); - - let xcm_outcome = XcmExecutor::execute_xcm_in_credit( - location, - xcm, - hash, - weight_limit.unwrap_or_else(Weight::zero), - weight_credit, - ); - Ok(xcm_outcome) - }; - - let xcm_outcome = do_dispatch(); - match xcm_outcome { - Ok(outcome) => { - log::trace!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Incoming message {:?} dispatched with result: {:?}", - message_id, - outcome, - ); - match outcome.ensure_execution() { - Ok(_weight) => (), - Err(e) => { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Incoming message {:?} was not dispatched, error: {:?}", - message_id, - e, - ); - }, - } - }, - Err(e) => { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "Incoming message {:?} was not dispatched, codec error: {:?}", - message_id, - e, - ); - }, - } - - MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } - } - } - /// Return maximal dispatch weight of the message we're able to receive. pub fn maximal_incoming_message_dispatch_weight(maximal_extrinsic_weight: Weight) -> Weight { maximal_extrinsic_weight / 2 @@ -745,54 +484,6 @@ mod tests { use sp_core::H256; use sp_runtime::traits::Header as _; - fn test_lane_outbound_data() -> OutboundLaneData { - OutboundLaneData::default() - } - - fn regular_outbound_message_payload() -> source::FromThisChainMessagePayload { - vec![42] - } - - #[test] - fn message_is_rejected_when_sent_using_disabled_lane() { - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &frame_system::RawOrigin::Root.into(), - &LaneId(*b"dsbl"), - &test_lane_outbound_data(), - ®ular_outbound_message_payload(), - ), - Err(source::MESSAGE_REJECTED_BY_OUTBOUND_LANE) - ); - } - - #[test] - fn message_is_rejected_when_there_are_too_many_pending_messages_at_outbound_lane() { - assert_eq!( - source::FromThisChainMessageVerifier::::verify_message( - &frame_system::RawOrigin::Root.into(), - &TEST_LANE_ID, - &OutboundLaneData { - latest_received_nonce: 100, - latest_generated_nonce: 100 + MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE + 1, - ..Default::default() - }, - ®ular_outbound_message_payload(), - ), - Err(source::TOO_MANY_PENDING_MESSAGES) - ); - } - - #[test] - fn verify_chain_message_rejects_message_with_too_small_declared_weight() { - assert!(source::verify_chain_message::(&vec![ - 42; - BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT - - 1 - ]) - .is_err()); - } - #[test] fn verify_chain_message_rejects_message_with_too_large_declared_weight() { assert!(source::verify_chain_message::(&vec![ diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 42ac67a0f26ac..a8ca86c85c3e4 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -28,13 +28,43 @@ use bp_messages::{ }; use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; use codec::{Decode, Encode}; -use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound}; +use frame_support::{ + dispatch::Weight, traits::Get, weights::RuntimeDbWeight, CloneNoBound, EqNoBound, + PartialEqNoBound, +}; use scale_info::TypeInfo; +use sp_std::marker::PhantomData; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; /// Plain "XCM" payload, which we transfer through bridge pub type XcmAsPlainPayload = sp_std::prelude::Vec; +// TODO: below are just rough estimations. Other things also happen there (including hashing and so +// on). Shall we do some benchmarking??? TODO: add proof_size component here +// https://github.com/paritytech/parity-bridges-common/issues/1986 + +/// Simple weigher for incoming XCM dispatch at **bridge hubs** to use with +/// `XcmBlobMessageDispatch`. +/// +/// By our design, message at bridge hub is simply pushed to some other queue. This implementation +/// is for this case only. If your runtime performs some other actions with incoming XCM messages, +/// you shall use your own implementation. +/// +/// If message is redirected to the relay chain, then `ParentAsUmp` is used and it roughly does +/// 1 db read and 1 db write (in its `send_upward_message` method). +/// +/// If message is redirected to some sibling parachain, then `XcmpQueue` is used and +/// it roughly does 2 db reads and 2 db writes (in its `SendXcm` implementation). +/// +/// The difference is not that big, so let's choose maximal. +pub struct XcmRouterWeigher(PhantomData); + +impl> Get for XcmRouterWeigher { + fn get() -> Weight { + T::get().reads_writes(2, 2) + } +} + /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] pub enum XcmBlobMessageDispatchResult { diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 056fd3a2ccf09..5c2c967c060a8 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -33,7 +33,7 @@ use crate::messages::{ }; use bp_header_chain::{ChainWithGrandpa, HeaderChain}; -use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; +use bp_messages::{target_chain::ForbidInboundMessages, LaneId}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; use codec::{Decode, Encode}; @@ -87,10 +87,6 @@ pub type BridgedChainHeader = pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); /// Bridged chain id used in tests. pub const TEST_BRIDGED_CHAIN_ID: ChainId = *b"brdg"; -/// Maximal number of queued messages at the test lane. -pub const MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE: MessageNonce = 32; -/// Minimal extrinsic weight at the `BridgedChain`. -pub const BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT: usize = 5; /// Maximal extrinsic weight at the `BridgedChain`. pub const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; /// Maximal extrinsic size at the `BridgedChain`. @@ -222,7 +218,7 @@ impl pallet_bridge_messages::Config for TestRuntime { type MaximalOutboundPayloadSize = FromThisChainMaximalOutboundPayloadSize; type OutboundPayload = FromThisChainMessagePayload; - type InboundPayload = FromBridgedChainMessagePayload; + type InboundPayload = FromBridgedChainMessagePayload; type InboundRelayer = BridgedChainAccountId; type DeliveryPayments = (); @@ -235,8 +231,7 @@ impl pallet_bridge_messages::Config for TestRuntime { >; type SourceHeaderChain = SourceHeaderChainAdapter; - type MessageDispatch = - ForbidInboundMessages<(), FromBridgedChainMessagePayload>; + type MessageDispatch = ForbidInboundMessages<(), FromBridgedChainMessagePayload>; type BridgedChainId = BridgedChainId; } @@ -253,8 +248,6 @@ impl pallet_bridge_relayers::Config for TestRuntime { pub struct OnThisChainBridge; impl MessageBridge for OnThisChainBridge { - const THIS_CHAIN_ID: ChainId = *b"this"; - const BRIDGED_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = ThisChain; @@ -268,8 +261,6 @@ impl MessageBridge for OnThisChainBridge { pub struct OnBridgedChainBridge; impl MessageBridge for OnBridgedChainBridge { - const THIS_CHAIN_ID: ChainId = TEST_BRIDGED_CHAIN_ID; - const BRIDGED_CHAIN_ID: ChainId = *b"this"; const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; type ThisChain = BridgedChain; @@ -331,22 +322,9 @@ impl UnderlyingChainProvider for ThisChain { impl ThisChainWithMessages for ThisChain { type RuntimeOrigin = ThisChainCallOrigin; - type RuntimeCall = ThisChainRuntimeCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, lane: &LaneId) -> bool { - *lane == TEST_LANE_ID - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - MAXIMAL_PENDING_MESSAGES_AT_TEST_LANE - } } -impl BridgedChainWithMessages for ThisChain { - fn verify_dispatch_weight(_message_payload: &[u8]) -> bool { - unreachable!() - } -} +impl BridgedChainWithMessages for ThisChain {} /// Underlying chain of `BridgedChain`. pub struct BridgedUnderlyingChain; @@ -413,20 +391,6 @@ impl UnderlyingChainProvider for BridgedChain { impl ThisChainWithMessages for BridgedChain { type RuntimeOrigin = BridgedChainOrigin; - type RuntimeCall = BridgedChainCall; - - fn is_message_accepted(_send_origin: &Self::RuntimeOrigin, _lane: &LaneId) -> bool { - unreachable!() - } - - fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { - unreachable!() - } } -impl BridgedChainWithMessages for BridgedChain { - fn verify_dispatch_weight(message_payload: &[u8]) -> bool { - message_payload.len() >= BRIDGED_CHAIN_MIN_EXTRINSIC_WEIGHT && - message_payload.len() <= BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT - } -} +impl BridgedChainWithMessages for BridgedChain {} diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 1d2373de6d350..d4f551ce57a0b 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -502,11 +502,11 @@ pub struct StrippableError { } impl From for StrippableError { - fn from(err: T) -> Self { + fn from(_err: T) -> Self { Self { _phantom_data: Default::default(), #[cfg(feature = "std")] - message: format!("{:?}", err), + message: format!("{:?}", _err), } } } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index ca9a32a48a54c..44416195c6a44 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -16,37 +16,18 @@ //! Millau chain specification for CLI. -use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; -use bp_rialto_parachain::RIALTO_PARACHAIN_ID; +use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_millau_client::Millau; use relay_substrate_client::SimpleRuntimeVersion; -use xcm::latest::prelude::*; impl CliEncodeMessage for Millau { - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + fn encode_execute_xcm( + message: xcm::VersionedXcm, ) -> anyhow::Result> { - let dest = match bridge_instance_index { - bridge::MILLAU_TO_RIALTO_INDEX => - (Parent, X1(GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()))), - bridge::MILLAU_TO_RIALTO_PARACHAIN_INDEX => ( - Parent, - X2( - GlobalConsensus(millau_runtime::xcm_config::RialtoNetwork::get()), - Parachain(RIALTO_PARACHAIN_ID), - ), - ), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }; - - Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::send { - dest: Box::new(dest.into()), + Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::execute { message: Box::new(message), + max_weight: Self::estimate_execute_xcm_weight(), }) .into()) } diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index e9e2d0b3eaf91..34a448ae4cb13 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -16,29 +16,18 @@ //! Rialto chain specification for CLI. -use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; +use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; use relay_rialto_client::Rialto; use relay_substrate_client::SimpleRuntimeVersion; -use xcm::latest::prelude::*; impl CliEncodeMessage for Rialto { - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + fn encode_execute_xcm( + message: xcm::VersionedXcm, ) -> anyhow::Result> { - let dest = match bridge_instance_index { - bridge::RIALTO_TO_MILLAU_INDEX => - (Parent, X1(GlobalConsensus(rialto_runtime::xcm_config::MillauNetwork::get()))), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }; - - Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::send { - dest: Box::new(dest.into()), + Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::execute { message: Box::new(message), + max_weight: Self::estimate_execute_xcm_weight(), }) .into()) } diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 1a5ea2e784e47..8ea2c1ffd433c 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -16,33 +16,21 @@ //! Rialto parachain specification for CLI. -use crate::cli::{bridge, encode_message::CliEncodeMessage, CliChain}; +use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; -use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; use relay_substrate_client::SimpleRuntimeVersion; -use xcm::latest::prelude::*; impl CliEncodeMessage for RialtoParachain { - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + fn encode_execute_xcm( + message: xcm::VersionedXcm, ) -> anyhow::Result> { type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; type XcmCall = relay_rialto_parachain_client::runtime_types::pallet_xcm::pallet::Call; - let dest = match bridge_instance_index { - bridge::RIALTO_PARACHAIN_TO_MILLAU_INDEX => - (Parent, X1(GlobalConsensus(CustomNetworkId::Millau.as_network_id()))), - _ => anyhow::bail!( - "Unsupported target bridge pallet with instance index: {}", - bridge_instance_index - ), - }; - - let xcm_call = XcmCall::send { - dest: Box::new(unsafe { std::mem::transmute(xcm::VersionedMultiLocation::from(dest)) }), + let xcm_call = XcmCall::execute { message: Box::new(unsafe { std::mem::transmute(message) }), + max_weight: Self::estimate_execute_xcm_weight(), }; Ok(RuntimeCall::PolkadotXcm(xcm_call).into()) diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index a3cacec331394..62c71183a4801 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -37,28 +37,6 @@ pub enum FullBridge { BridgeHubPolkadotToBridgeHubKusama, } -impl FullBridge { - /// Return instance index of the bridge pallet in source runtime. - pub fn bridge_instance_index(&self) -> u8 { - match self { - Self::MillauToRialto => MILLAU_TO_RIALTO_INDEX, - Self::RialtoToMillau => RIALTO_TO_MILLAU_INDEX, - Self::MillauToRialtoParachain => MILLAU_TO_RIALTO_PARACHAIN_INDEX, - Self::RialtoParachainToMillau => RIALTO_PARACHAIN_TO_MILLAU_INDEX, - Self::BridgeHubRococoToBridgeHubWococo | - Self::BridgeHubWococoToBridgeHubRococo | - Self::BridgeHubKusamaToBridgeHubPolkadot | - Self::BridgeHubPolkadotToBridgeHubKusama => - unimplemented!("Relay doesn't support send-message subcommand on bridge hubs"), - } - } -} - -pub const RIALTO_TO_MILLAU_INDEX: u8 = 0; -pub const MILLAU_TO_RIALTO_INDEX: u8 = 0; -pub const MILLAU_TO_RIALTO_PARACHAIN_INDEX: u8 = 1; -pub const RIALTO_PARACHAIN_TO_MILLAU_INDEX: u8 = 0; - /// Minimal bridge representation that can be used from the CLI. /// It connects a source chain to a target chain. pub trait CliBridgeBase: Sized { diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index c7ca5d51f7993..9abf8b2df6dda 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -17,6 +17,7 @@ use crate::cli::{ExplicitOrMaximal, HexBytes}; use bp_runtime::EncodedOrDecodedCall; use codec::Encode; +use frame_support::weights::Weight; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -42,11 +43,16 @@ pub enum Message { pub type RawMessage = Vec; pub trait CliEncodeMessage: Chain { - /// Encode a send XCM call of the XCM pallet. - fn encode_send_xcm( - message: xcm::VersionedXcm<()>, - bridge_instance_index: u8, + /// Encode an `execute` XCM call of the XCM pallet. + fn encode_execute_xcm( + message: xcm::VersionedXcm, ) -> anyhow::Result>; + + /// Estimate value of `max_weight` argument for the `execute` XCM call of the XCM pallet. + fn estimate_execute_xcm_weight() -> Weight { + // we are only executing XCM on our testnets and 1/100 of max extrinsic weight is ok + Self::max_extrinsic_weight() / 100 + } } /// Encode message payload passed through CLI flags. @@ -125,7 +131,7 @@ mod tests { .unwrap(); assert_eq!(msg.len(), 100); // check that it decodes to valid xcm - let _ = decode_xcm(msg).unwrap(); + let _ = decode_xcm::<()>(msg).unwrap(); } #[test] @@ -140,6 +146,6 @@ mod tests { .unwrap(); assert_eq!(msg.len(), maximal_size as usize); // check that it decodes to valid xcm - let _ = decode_xcm(msg).unwrap(); + let _ = decode_xcm::<()>(msg).unwrap(); } } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 09d7f72b7f4b5..8f76e501f6968 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -75,10 +75,7 @@ where let source_sign = data.source_sign.to_keypair::()?; let payload_len = payload.encoded_size(); - let send_message_call = Self::Source::encode_send_xcm( - decode_xcm(payload)?, - data.bridge.bridge_instance_index(), - )?; + let send_message_call = Self::Source::encode_execute_xcm(decode_xcm(payload)?)?; source_client .submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| { @@ -130,7 +127,7 @@ impl SendMessage { } /// Decode SCALE encoded raw XCM message. -pub(crate) fn decode_xcm(message: RawMessage) -> anyhow::Result> { +pub(crate) fn decode_xcm(message: RawMessage) -> anyhow::Result> { Decode::decode(&mut &message[..]) .map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e)) } From 2b0fba7fe96710c08f1305d994d07b70703f82d4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 24 Mar 2023 13:45:39 +0300 Subject: [PATCH 0999/1210] Added receive_single_message_proof_with_dispatch benchmark (#1990) * added receive_single_message_proof_with_dispatch benchmark * clippy --- bin/millau/runtime/src/lib.rs | 4 +- bin/millau/runtime/src/rialto_messages.rs | 2 +- .../runtime/src/rialto_parachain_messages.rs | 2 +- bin/millau/runtime/src/xcm_config.rs | 21 +- bin/rialto-parachain/runtime/src/lib.rs | 9 +- .../runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/rialto/runtime/src/xcm_config.rs | 12 +- .../src/messages_benchmarking.rs | 53 ++++- .../src/messages_xcm_extension.rs | 70 ++---- modules/messages/src/benchmarking.rs | 93 +++++--- modules/messages/src/weights.rs | 219 ++++++++++-------- modules/messages/src/weights_ext.rs | 15 ++ 13 files changed, 276 insertions(+), 228 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f08f5e1c7496b..8ed2f0a97e478 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1007,7 +1007,7 @@ impl_runtime_apis! { Runtime, WithRialtoParachainsInstance, WithRialtoParachainMessageBridge, - >(params) + >(params, xcm::v3::Junctions::Here) } fn prepare_message_delivery_proof( @@ -1038,7 +1038,7 @@ impl_runtime_apis! { Runtime, RialtoGrandpaInstance, WithRialtoMessageBridge, - >(params) + >(params, xcm::v3::Junctions::Here) } fn prepare_message_delivery_proof( diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 311805c984921..84535283d4847 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -67,7 +67,7 @@ pub type FromRialtoMessageDispatch = bp_millau::Millau, bp_rialto::Rialto, crate::xcm_config::OnMillauBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + (), >; /// Maximal outbound payload size of Millau -> Rialto messages. diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 17495e26ae218..b3d33c1cefd70 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -62,7 +62,7 @@ pub type FromRialtoParachainMessageDispatch = bp_millau::Millau, bp_rialto::Rialto, crate::xcm_config::OnMillauBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + (), >; /// Maximal outbound payload size of Millau -> RialtoParachain messages. diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index c477a684526d6..384835f8bbcb3 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -233,20 +233,16 @@ impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { mod tests { use super::*; use crate::{ - rialto_messages::FromRialtoMessageDispatch, - rialto_parachain_messages::FromRialtoParachainMessageDispatch, DbWeight, - WithRialtoMessagesInstance, WithRialtoParachainMessagesInstance, + rialto_messages::FromRialtoMessageDispatch, WithRialtoMessagesInstance, + WithRialtoParachainMessagesInstance, }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::{ - XcmBlobMessageDispatchResult, XcmRouterWeigher, - }; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_core::Get; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { @@ -347,10 +343,7 @@ mod tests { #[test] fn xcm_messages_from_rialto_are_dispatched() { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = FromRialtoMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch @@ -364,11 +357,7 @@ mod tests { #[test] fn xcm_messages_from_rialto_parachain_are_dispatched() { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = - FromRialtoParachainMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 58c6a8c673f9b..460f4aa6a6861 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -844,12 +844,10 @@ mod tests { LaneId, MessageKey, }; use bridge_runtime_common::{ - integrity::check_additional_signed, - messages_xcm_extension::{XcmBlobMessageDispatchResult, XcmRouterWeigher}, + integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchResult, }; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_core::Get; use sp_runtime::generic::Era; use xcm_executor::XcmExecutor; @@ -914,10 +912,7 @@ mod tests { #[test] fn xcm_messages_from_millau_are_dispatched() { new_test_ext().execute_with(|| { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::<()>::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 3fff141bf8484..5d4a92b50916f 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -63,7 +63,7 @@ pub type FromMillauMessageDispatch = bp_rialto_parachain::RialtoParachain, bp_millau::Millau, crate::OnRialtoParachainBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher<()>, + (), >; /// Messages proof for Millau -> RialtoParachain messages. diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 9d0c4f97c898c..ab4b7dd521dab 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -60,7 +60,7 @@ pub type FromMillauMessageDispatch = bp_rialto::Rialto, bp_millau::Millau, crate::xcm_config::OnRialtoBlobDispatcher, - bridge_runtime_common::messages_xcm_extension::XcmRouterWeigher, + (), >; /// Messages proof for Millau -> Rialto messages. diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 64a5a896f95e1..7a4966d92ddaf 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -189,18 +189,15 @@ mod tests { use super::*; use crate::{ millau_messages::{FromMillauMessageDispatch, XCM_LANE}, - DbWeight, WithMillauMessagesInstance, + WithMillauMessagesInstance, }; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::{ - XcmBlobMessageDispatchResult, XcmRouterWeigher, - }; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_core::Get; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { @@ -263,10 +260,7 @@ mod tests { #[test] fn xcm_messages_from_millau_are_dispatched() { - let mut incoming_message = prepare_inbound_bridge_message(); - - let dispatch_weight = FromMillauMessageDispatch::dispatch_weight(&mut incoming_message); - assert_eq!(dispatch_weight, XcmRouterWeigher::::get()); + let incoming_message = prepare_inbound_bridge_message(); // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 028172e7ab42f..b067523c305b9 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -40,6 +40,39 @@ use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessagePr use sp_runtime::traits::{Header, Zero}; use sp_std::prelude::*; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; +use xcm::v3::prelude::*; + +/// Prepare inbound bridge message according to given message proof parameters. +fn prepare_inbound_message( + params: &MessageProofParams, + destination: InteriorMultiLocation, +) -> Vec { + // we only care about **this** message size when message proof needs to be `Minimal` + let expected_size = match params.size { + StorageProofSize::Minimal(size) => size as usize, + _ => 0, + }; + + // if we don't need a correct message, then we may just return some random blob + if !params.is_successful_dispatch_expected { + return vec![0u8; expected_size] + } + + // else let's prepare successful message. For XCM bridge hubs, it is the message that + // will be pushed further to some XCM queue (XCMP/UMP) + let location = xcm::VersionedInteriorMultiLocation::V3(destination); + let location_encoded_size = location.encoded_size(); + + // we don't need to be super-precise with `expected_size` here + let xcm_size = expected_size.saturating_sub(location_encoded_size); + let xcm = xcm::VersionedXcm::<()>::V3(vec![Instruction::ClearOrigin; xcm_size].into()); + + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + // (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed + // to the storage) + (location, xcm).encode().encode() +} /// Prepare proof of messages for the `receive_messages_proof` call. /// @@ -51,6 +84,7 @@ use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; /// function. pub fn prepare_message_proof_from_grandpa_chain( params: MessageProofParams, + message_destination: InteriorMultiLocation, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: pallet_bridge_grandpa::Config>>, @@ -61,12 +95,9 @@ where let (state_root, storage_proof) = prepare_messages_storage_proof::( params.lane, params.message_nonces.clone(), - params.outbound_lane_data, + params.outbound_lane_data.clone(), params.size, - match params.size { - StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }, + prepare_inbound_message(¶ms, message_destination), encode_all_messages, encode_lane_data, ); @@ -82,7 +113,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - Weight::zero(), + Weight::MAX / 1000, ) } @@ -96,6 +127,7 @@ where /// `prepare_message_proof_from_grandpa_chain` function. pub fn prepare_message_proof_from_parachain( params: MessageProofParams, + message_destination: InteriorMultiLocation, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: pallet_bridge_parachains::Config, @@ -107,12 +139,9 @@ where let (state_root, storage_proof) = prepare_messages_storage_proof::( params.lane, params.message_nonces.clone(), - params.outbound_lane_data, + params.outbound_lane_data.clone(), params.size, - match params.size { - StorageProofSize::Minimal(ref size) => vec![0u8; *size as _], - _ => vec![], - }, + prepare_inbound_message(¶ms, message_destination), encode_all_messages, encode_lane_data, ); @@ -129,7 +158,7 @@ where nonces_start: *params.message_nonces.start(), nonces_end: *params.message_nonces.end(), }, - Weight::zero(), + Weight::MAX / 1000, ) } diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index a8ca86c85c3e4..d4bf2bc1bed6d 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -28,43 +28,15 @@ use bp_messages::{ }; use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; use codec::{Decode, Encode}; -use frame_support::{ - dispatch::Weight, traits::Get, weights::RuntimeDbWeight, CloneNoBound, EqNoBound, - PartialEqNoBound, -}; +use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; +use pallet_bridge_messages::WeightInfoExt as MessagesPalletWeights; use scale_info::TypeInfo; -use sp_std::marker::PhantomData; +use sp_runtime::SaturatedConversion; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; /// Plain "XCM" payload, which we transfer through bridge pub type XcmAsPlainPayload = sp_std::prelude::Vec; -// TODO: below are just rough estimations. Other things also happen there (including hashing and so -// on). Shall we do some benchmarking??? TODO: add proof_size component here -// https://github.com/paritytech/parity-bridges-common/issues/1986 - -/// Simple weigher for incoming XCM dispatch at **bridge hubs** to use with -/// `XcmBlobMessageDispatch`. -/// -/// By our design, message at bridge hub is simply pushed to some other queue. This implementation -/// is for this case only. If your runtime performs some other actions with incoming XCM messages, -/// you shall use your own implementation. -/// -/// If message is redirected to the relay chain, then `ParentAsUmp` is used and it roughly does -/// 1 db read and 1 db write (in its `send_upward_message` method). -/// -/// If message is redirected to some sibling parachain, then `XcmpQueue` is used and -/// it roughly does 2 db reads and 2 db writes (in its `SendXcm` implementation). -/// -/// The difference is not that big, so let's choose maximal. -pub struct XcmRouterWeigher(PhantomData); - -impl> Get for XcmRouterWeigher { - fn get() -> Weight { - T::get().reads_writes(2, 2) - } -} - /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] pub enum XcmBlobMessageDispatchResult { @@ -74,17 +46,13 @@ pub enum XcmBlobMessageDispatchResult { } /// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages -pub struct XcmBlobMessageDispatch< - SourceBridgeHubChain, - TargetBridgeHubChain, - DispatchBlob, - DispatchBlobWeigher, -> { +pub struct XcmBlobMessageDispatch +{ _marker: sp_std::marker::PhantomData<( SourceBridgeHubChain, TargetBridgeHubChain, DispatchBlob, - DispatchBlobWeigher, + Weights, )>, } @@ -92,20 +60,21 @@ impl< SourceBridgeHubChain: Chain, TargetBridgeHubChain: Chain, BlobDispatcher: DispatchBlob, - DispatchBlobWeigher: Get, + Weights: MessagesPalletWeights, > MessageDispatch> - for XcmBlobMessageDispatch< - SourceBridgeHubChain, - TargetBridgeHubChain, - BlobDispatcher, - DispatchBlobWeigher, - > + for XcmBlobMessageDispatch { type DispatchPayload = XcmAsPlainPayload; type DispatchLevelResult = XcmBlobMessageDispatchResult; - fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { - DispatchBlobWeigher::get() + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { + match message.data.payload { + Ok(ref payload) => { + let payload_size = payload.encoded_size().saturated_into(); + Weights::message_dispatch_weight(payload_size) + }, + Err(_) => Weight::zero(), + } } fn dispatch( @@ -122,7 +91,6 @@ impl< message.key.nonce ); return MessageDispatchResult { - // TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629 unspent_weight: Weight::zero(), dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload, } @@ -158,11 +126,7 @@ impl< XcmBlobMessageDispatchResult::NotDispatched(e) }, }; - MessageDispatchResult { - // TODO:check-parameter - setup uspent_weight? https://github.com/paritytech/polkadot/issues/6629 - unspent_weight: Weight::zero(), - dispatch_level_result, - } + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result } } } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 955dd3da2c57b..bc9c1f752574b 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -48,6 +48,11 @@ pub struct MessageProofParams { pub message_nonces: RangeInclusive, /// If `Some`, the proof needs to include this outbound lane data. pub outbound_lane_data: Option, + /// If `true`, the caller expects that the proof will contain correct messages that will + /// be successfully dispatched. This is only called from the "optional" + /// `receive_single_message_proof_with_dispatch` benchmark. If you don't need it, just + /// return `true` from the `is_message_successfully_dispatched`. + pub is_successful_dispatch_expected: bool, /// Proof size requirements. pub size: StorageProofSize, } @@ -95,32 +100,25 @@ pub trait Config: crate::Config { params: MessageDeliveryProofParams, ) -> >::MessagesDeliveryProof; - /// Returns true if message has been dispatched (either successfully or not). - /// - /// We assume that messages have near-zero dispatch weight, so most of times it - /// is hard to determine whether messages has been dispatched or not. For example, - /// XCM message can be a call that leaves entry in `frame_system::Events` vector, - /// but not all XCM messages do that and we don't want to include weight of this - /// action to the base weight of message delivery. Hence, the default `true` return - /// value. - fn is_message_dispatched(_nonce: MessageNonce) -> bool { + /// Returns true if message has been successfully dispatched or not. + fn is_message_successfully_dispatched(_nonce: MessageNonce) -> bool { true } + /// Returns true if given relayer has been rewarded for some of its actions. fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool; } benchmarks_instance_pallet! { // - // Benchmarks that are used directly by the runtime. + // Benchmarks that are used directly by the runtime calls weight formulae. // // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at target (this) chain. + // * message is dispatched (reminder: dispatch weight should be minimal); + // * message requires all heavy checks done by dispatcher. // // This is base benchmark for all other message delivery benchmarks. receive_single_message_proof { @@ -135,6 +133,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -143,15 +142,13 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with two minimal-weight messages and following conditions: // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at target (this) chain. + // * message is dispatched (reminder: dispatch weight should be minimal); + // * message requires all heavy checks done by dispatcher. // // The weight of single message delivery could be approximated as // `weight(receive_two_messages_proof) - weight(receive_single_message_proof)`. @@ -169,6 +166,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=22, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 2, dispatch_weight) @@ -177,15 +175,13 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 22, ); - assert!(T::is_message_dispatched(22)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: // * proof includes outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; - // * message requires all heavy checks done by dispatcher; - // * message dispatch fee is paid at target (this) chain. + // * message is successfully dispatched (reminder: dispatch weight should be minimal); + // * message requires all heavy checks done by dispatcher. // // The weight of outbound lane state delivery would be // `weight(receive_single_message_proof_with_outbound_lane_state) - weight(receive_single_message_proof)`. @@ -207,6 +203,7 @@ benchmarks_instance_pallet! { latest_received_nonce: 20, latest_generated_nonce: 21, }), + is_successful_dispatch_expected: false, size: StorageProofSize::Minimal(EXPECTED_DEFAULT_MESSAGE_LENGTH), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -214,14 +211,13 @@ benchmarks_instance_pallet! { let lane_state = crate::InboundLanes::::get(&T::bench_lane_id()); assert_eq!(lane_state.last_delivered_nonce(), 21); assert_eq!(lane_state.last_confirmed_nonce, 20); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * the proof has many redundand trie nodes with total size of approximately 1KB; + // * the proof has large leaf with total size of approximately 1KB; // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; + // * message is dispatched (reminder: dispatch weight should be minimal); // * message requires all heavy checks done by dispatcher. // // With single KB of messages proof, the weight of the call is increased (roughly) by @@ -238,6 +234,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::HasLargeLeaf(1024), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -246,14 +243,13 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_proof` extrinsic with single minimal-weight message and following conditions: - // * the proof has many redundand trie nodes with total size of approximately 16KB; + // * the proof has large leaf with total size of approximately 16KB; // * proof does not include outbound lane state proof; // * inbound lane already has state, so it needs to be read and decoded; - // * message is successfully dispatched; + // * message is dispatched (reminder: dispatch weight should be minimal); // * message requires all heavy checks done by dispatcher. // // Size of proof grows because it contains extra trie nodes in it. @@ -272,6 +268,7 @@ benchmarks_instance_pallet! { lane: T::bench_lane_id(), message_nonces: 21..=21, outbound_lane_data: None, + is_successful_dispatch_expected: false, size: StorageProofSize::HasLargeLeaf(16 * 1024), }); }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) @@ -280,7 +277,6 @@ benchmarks_instance_pallet! { crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), 21, ); - assert!(T::is_message_dispatched(21)); } // Benchmark `receive_messages_delivery_proof` extrinsic with following conditions: @@ -400,6 +396,47 @@ benchmarks_instance_pallet! { assert!(T::is_relayer_rewarded(&relayer1_id)); assert!(T::is_relayer_rewarded(&relayer2_id)); } + + // + // Benchmarks that the runtime developers may use for proper pallet configuration. + // + + // This benchmark is optional and may be used when runtime developer need a way to compute + // message dispatch weight. In this case, he needs to provide messages that can go the whole + // dispatch + // + // Benchmark `receive_messages_proof` extrinsic with single message and following conditions: + // + // * proof does not include outbound lane state proof; + // * inbound lane already has state, so it needs to be read and decoded; + // * message is **SUCCESSFULLY** dispatched; + // * message requires all heavy checks done by dispatcher. + receive_single_message_proof_with_dispatch { + // maybe dispatch weight relies on the message size too? + let i in EXPECTED_DEFAULT_MESSAGE_LENGTH .. EXPECTED_DEFAULT_MESSAGE_LENGTH * 16; + + let relayer_id_on_source = T::bridged_relayer_id(); + let relayer_id_on_target = account("relayer", 0, SEED); + T::endow_account(&relayer_id_on_target); + + // mark messages 1..=20 as delivered + receive_messages::(20); + + let (proof, dispatch_weight) = T::prepare_message_proof(MessageProofParams { + lane: T::bench_lane_id(), + message_nonces: 21..=21, + outbound_lane_data: None, + is_successful_dispatch_expected: true, + size: StorageProofSize::Minimal(i), + }); + }: receive_messages_proof(RawOrigin::Signed(relayer_id_on_target), relayer_id_on_source, proof, 1, dispatch_weight) + verify { + assert_eq!( + crate::InboundLanes::::get(&T::bench_lane_id()).last_delivered_nonce(), + 21, + ); + assert!(T::is_message_successfully_dispatched(21)); + } } fn send_regular_message, I: 'static>() { diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 4b2e5b48ee256..baaef317241ac 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for RialtoMessages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-03-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -58,6 +58,7 @@ pub trait WeightInfo { fn receive_delivery_proof_for_single_message() -> Weight; fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight; fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight; + fn receive_single_message_proof_with_dispatch(i: u32) -> Weight; } /// Weights for `RialtoMessages` that are generated using one of the Bridge testnets. @@ -79,19 +80,14 @@ impl WeightInfo for BridgeWeight { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 48_058 nanoseconds. - Weight::from_parts(50_422_000, 54703) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_321 nanoseconds. + Weight::from_parts(54_478_000, 57170) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -107,19 +103,14 @@ impl WeightInfo for BridgeWeight { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 59_371 nanoseconds. - Weight::from_parts(61_726_000, 54703) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_597 nanoseconds. + Weight::from_parts(69_267_000, 57170) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -135,19 +126,14 @@ impl WeightInfo for BridgeWeight { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 53_398 nanoseconds. - Weight::from_parts(54_351_000, 54703) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_079 nanoseconds. + Weight::from_parts(65_905_000, 57170) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -166,9 +152,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 50_064 nanoseconds. - Weight::from_parts(51_306_000, 54200) + // Estimated: `57170` + // Minimum execution time: 50_588 nanoseconds. + Weight::from_parts(53_544_000, 57170) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -189,9 +175,9 @@ impl WeightInfo for BridgeWeight { fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 75_403 nanoseconds. - Weight::from_parts(77_006_000, 54200) + // Estimated: `57170` + // Minimum execution time: 78_269 nanoseconds. + Weight::from_parts(81_748_000, 57170) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -217,9 +203,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `5624` - // Minimum execution time: 41_670 nanoseconds. - Weight::from_parts(42_863_000, 5624) + // Estimated: `9584` + // Minimum execution time: 45_786 nanoseconds. + Weight::from_parts(47_382_000, 9584) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -245,9 +231,9 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `5624` - // Minimum execution time: 40_928 nanoseconds. - Weight::from_parts(42_165_000, 5624) + // Estimated: `9584` + // Minimum execution time: 44_544 nanoseconds. + Weight::from_parts(45_451_000, 9584) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -273,12 +259,39 @@ impl WeightInfo for BridgeWeight { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8164` - // Minimum execution time: 44_022 nanoseconds. - Weight::from_parts(44_657_000, 8164) + // Estimated: `12124` + // Minimum execution time: 47_344 nanoseconds. + Weight::from_parts(48_311_000, 12124) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32) -> Weight { + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_385 nanoseconds. + Weight::from_parts(54_919_468, 57170) + // Standard Error: 108 + .saturating_add(Weight::from_parts(3_286, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests @@ -297,19 +310,14 @@ impl WeightInfo for () { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 48_058 nanoseconds. - Weight::from_parts(50_422_000, 54703) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_321 nanoseconds. + Weight::from_parts(54_478_000, 57170) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -325,19 +333,14 @@ impl WeightInfo for () { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 59_371 nanoseconds. - Weight::from_parts(61_726_000, 54703) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_597 nanoseconds. + Weight::from_parts(69_267_000, 57170) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -353,19 +356,14 @@ impl WeightInfo for () { /// /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) - /// - /// Storage: Balances TotalIssuance (r:1 w:1) - /// - /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: - /// MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: - // Measured: `693` - // Estimated: `54703` - // Minimum execution time: 53_398 nanoseconds. - Weight::from_parts(54_351_000, 54703) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 64_079 nanoseconds. + Weight::from_parts(65_905_000, 57170) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) /// @@ -384,9 +382,9 @@ impl WeightInfo for () { fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 50_064 nanoseconds. - Weight::from_parts(51_306_000, 54200) + // Estimated: `57170` + // Minimum execution time: 50_588 nanoseconds. + Weight::from_parts(53_544_000, 57170) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -407,9 +405,9 @@ impl WeightInfo for () { fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: // Measured: `618` - // Estimated: `54200` - // Minimum execution time: 75_403 nanoseconds. - Weight::from_parts(77_006_000, 54200) + // Estimated: `57170` + // Minimum execution time: 78_269 nanoseconds. + Weight::from_parts(81_748_000, 57170) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -435,9 +433,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_single_message() -> Weight { // Proof Size summary in bytes: // Measured: `579` - // Estimated: `5624` - // Minimum execution time: 41_670 nanoseconds. - Weight::from_parts(42_863_000, 5624) + // Estimated: `9584` + // Minimum execution time: 45_786 nanoseconds. + Weight::from_parts(47_382_000, 9584) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -463,9 +461,9 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `5624` - // Minimum execution time: 40_928 nanoseconds. - Weight::from_parts(42_165_000, 5624) + // Estimated: `9584` + // Minimum execution time: 44_544 nanoseconds. + Weight::from_parts(45_451_000, 9584) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -491,10 +489,37 @@ impl WeightInfo for () { fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { // Proof Size summary in bytes: // Measured: `596` - // Estimated: `8164` - // Minimum execution time: 44_022 nanoseconds. - Weight::from_parts(44_657_000, 8164) + // Estimated: `12124` + // Minimum execution time: 47_344 nanoseconds. + Weight::from_parts(48_311_000, 12124) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// added: 497, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// added: 2048, mode: MaxEncodedLen) + /// + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// 51655, mode: MaxEncodedLen) + /// + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32) -> Weight { + // Proof Size summary in bytes: + // Measured: `618` + // Estimated: `57170` + // Minimum execution time: 52_385 nanoseconds. + Weight::from_parts(54_919_468, 57170) + // Standard Error: 108 + .saturating_add(Weight::from_parts(3_286, 0).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 5598706b5dbf2..090c03390ba36 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -403,6 +403,21 @@ pub trait WeightInfoExt: WeightInfo { (15 * 1024); proof_size_in_bytes * byte_weight } + + // Functions that may be used by runtime developers. + + /// Returns dispatch weight of message of given size. + /// + /// This function would return correct value only if your runtime is configured to run + /// `receive_single_message_proof_with_dispatch` benchmark. See its requirements for + /// details. + fn message_dispatch_weight(message_size: u32) -> Weight { + // There may be a tiny overweight/underweight here, because we don't account how message + // size affects all steps before dispatch. But the effect should be small enough and we + // may ignore it. + Self::receive_single_message_proof_with_dispatch(message_size) + .saturating_sub(Self::receive_single_message_proof()) + } } impl WeightInfoExt for () { From 552ab02f9803dc1c85070091bb6e86013d586b71 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 24 Mar 2023 15:11:34 +0200 Subject: [PATCH 1000/1210] bump substrate+polkadot refs and fix builds (#1989) * bump refs and fix build * more fixes * Fix rialto-parachain node * Update dependencies for tools/runtime-codegen * Regenerate rialto-parachain indirect runtime * Fix register_parachain * Fix clippy * Undo clippy allow --------- Co-authored-by: Serban Iorga --- bin/millau/node/src/service.rs | 31 +- bin/millau/runtime/src/lib.rs | 12 + bin/millau/runtime/src/xcm_config.rs | 2 + bin/rialto-parachain/node/src/command.rs | 2 +- bin/rialto-parachain/node/src/service.rs | 8 +- bin/rialto-parachain/runtime/src/lib.rs | 13 + bin/rialto/node/src/chain_spec.rs | 8 +- bin/rialto/runtime/src/lib.rs | 106 +- bin/rialto/runtime/src/parachains.rs | 2 +- bin/rialto/runtime/src/xcm_config.rs | 2 + bin/runtime-common/Cargo.toml | 2 +- bin/runtime-common/src/mock.rs | 4 + modules/messages/src/mock.rs | 6 +- modules/relayers/src/mock.rs | 6 +- .../chain-bridge-hub-cumulus/src/lib.rs | 2 +- primitives/relayers/src/lib.rs | 13 +- primitives/runtime/Cargo.toml | 2 +- .../src/cli/register_parachain.rs | 4 +- relays/client-rialto-parachain/Cargo.toml | 2 +- .../src/codegen_runtime.rs | 1342 +++++++++++------ relays/client-substrate/src/client.rs | 4 +- 21 files changed, 998 insertions(+), 575 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index f8e6d34933dd5..7230accef8e5b 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -22,7 +22,6 @@ use sc_client_api::BlockBackend; use sc_consensus_aura::{CompatibilityMode, ImportQueueParams, SlotProportion, StartAuraParams}; use sc_consensus_grandpa::SharedVoterState; pub use sc_executor::NativeElseWasmExecutor; -use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; @@ -78,10 +77,6 @@ pub fn new_partial( >, ServiceError, > { - if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".into())) - } - let telemetry = config .telemetry_endpoints .clone() @@ -175,13 +170,6 @@ pub fn new_partial( }) } -fn remote_keystore(_url: &str) -> Result, &'static str> { - // FIXME: here would the concrete keystore be built, - // must return a concrete type (NOT `LocalKeystore`) that - // implements `CryptoStore` and `SyncCryptoStore` - Err("Remote Keystore not supported.") -} - /// Builds a new service for a full client. pub fn new_full(mut config: Configuration) -> Result { use sc_network_common::sync::warp::WarpSyncParams; @@ -191,22 +179,12 @@ pub fn new_full(mut config: Configuration) -> Result backend, mut task_manager, import_queue, - mut keystore_container, + keystore_container, select_chain, transaction_pool, other: (block_import, grandpa_link, beefy_voter_links, beefy_rpc_links, mut telemetry), } = new_partial(&config)?; - if let Some(url) = &config.keystore_remote { - match remote_keystore(url) { - Ok(k) => keystore_container.set_remote_keystore(k), - Err(e) => - return Err(ServiceError::Other(format!( - "Error hooking up remote keystore for {url}: {e}" - ))), - }; - } - let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change @@ -332,7 +310,7 @@ pub fn new_full(mut config: Configuration) -> Result let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), - keystore: keystore_container.sync_keystore(), + keystore: keystore_container.keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), sync_service: sync_service.clone(), @@ -375,7 +353,7 @@ pub fn new_full(mut config: Configuration) -> Result }, force_authoring, backoff_authoring_blocks, - keystore: keystore_container.sync_keystore(), + keystore: keystore_container.keystore(), sync_oracle: sync_service.clone(), justification_sync_link: sync_service.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), @@ -394,8 +372,7 @@ pub fn new_full(mut config: Configuration) -> Result // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = - if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; + let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; let justifications_protocol_name = beefy_on_demand_justifications_handler.protocol_name(); let payload_provider = sp_consensus_beefy::mmr::MmrRootProvider::new(client.clone()); diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 8ed2f0a97e478..b0c6b2875fe94 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -331,6 +331,10 @@ impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } parameter_types! { @@ -655,6 +659,14 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 384835f8bbcb3..4aaec83771b04 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -28,6 +28,7 @@ use frame_support::{ traits::{ConstU32, Everything, Nothing}, weights::Weight, }; +use frame_system::EnsureRoot; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, @@ -186,6 +187,7 @@ impl pallet_xcm::Config for Runtime { type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; } pub struct ToRialtoOrRialtoParachainSwitchExporter; diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index 2cb08ec4ea283..7393b0147329a 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -286,7 +286,7 @@ pub fn run() -> Result<()> { let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); let parachain_account = - AccountIdConversion::::into_account_truncating(&id); + AccountIdConversion::::into_account_truncating(&id); let state_version = RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 7e7fa2ed09be8..6662b2e962568 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -47,7 +47,7 @@ use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; use sp_api::ConstructRuntimeApi; -use sp_keystore::SyncCryptoStorePtr; +use sp_keystore::KeystorePtr; use sp_runtime::traits::BlakeTwo256; use substrate_prometheus_endpoint::Registry; @@ -237,7 +237,7 @@ where Arc, Arc>>, Arc>, - SyncCryptoStorePtr, + KeystorePtr, bool, ) -> Result>, sc_service::Error>, { @@ -294,7 +294,7 @@ where transaction_pool: transaction_pool.clone(), task_manager: &mut task_manager, config: parachain_config, - keystore: params.keystore_container.sync_keystore(), + keystore: params.keystore_container.keystore(), backend: backend.clone(), network: network.clone(), sync_service: sync_service.clone(), @@ -324,7 +324,7 @@ where relay_chain_interface.clone(), transaction_pool, sync_service, - params.keystore_container.sync_keystore(), + params.keystore_container.keystore(), force_authoring, )?; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 460f4aa6a6861..4e4fcffcd0051 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -304,6 +304,10 @@ impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } impl pallet_transaction_payment::Config for Runtime { @@ -492,6 +496,7 @@ impl pallet_xcm::Config for Runtime { type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; + type AdminOrigin = frame_system::EnsureRoot; } impl cumulus_pallet_xcm::Config for Runtime { @@ -637,6 +642,14 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index c51ca1197f61c..ceb82d45b3857 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use frame_support::weights::Weight; -use polkadot_primitives::v2::{AssignmentId, ValidatorId}; +use polkadot_primitives::v4::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, @@ -244,8 +244,8 @@ fn testnet_genesis( validation_upgrade_cooldown: 2u32, validation_upgrade_delay: 2, code_retention_period: 1200, - max_code_size: polkadot_primitives::v2::MAX_CODE_SIZE, - max_pov_size: polkadot_primitives::v2::MAX_POV_SIZE, + max_code_size: polkadot_primitives::v4::MAX_CODE_SIZE, + max_pov_size: polkadot_primitives::v4::MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, chain_availability_period: 4, @@ -255,7 +255,7 @@ fn testnet_genesis( max_downward_message_size: 1024 * 1024, ump_service_total_weight: Weight::from_parts( 100_000_000_000, - polkadot_primitives::v2::MAX_POV_SIZE as u64, + polkadot_primitives::v4::MAX_POV_SIZE as u64, ), max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index bdc205bec1405..1a6f0f1e540c5 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -330,6 +330,10 @@ impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } parameter_types! { @@ -579,6 +583,14 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { @@ -754,55 +766,55 @@ impl_runtime_apis! { } impl polkadot_primitives::runtime_api::ParachainHost for Runtime { - fn validators() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v2::validators::() + fn validators() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v4::validators::() } - fn validator_groups() -> (Vec>, polkadot_primitives::v2::GroupRotationInfo) { - polkadot_runtime_parachains::runtime_api_impl::v2::validator_groups::() + fn validator_groups() -> (Vec>, polkadot_primitives::v4::GroupRotationInfo) { + polkadot_runtime_parachains::runtime_api_impl::v4::validator_groups::() } - fn availability_cores() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v2::availability_cores::() + fn availability_cores() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v4::availability_cores::() } - fn persisted_validation_data(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) - -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v2::persisted_validation_data::(para_id, assumption) + fn persisted_validation_data(para_id: polkadot_primitives::v4::Id, assumption: polkadot_primitives::v4::OccupiedCoreAssumption) + -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v4::persisted_validation_data::(para_id, assumption) } fn assumed_validation_data( - para_id: polkadot_primitives::v2::Id, + para_id: polkadot_primitives::v4::Id, expected_persisted_validation_data_hash: Hash, - ) -> Option<(polkadot_primitives::v2::PersistedValidationData, polkadot_primitives::v2::ValidationCodeHash)> { - polkadot_runtime_parachains::runtime_api_impl::v2::assumed_validation_data::( + ) -> Option<(polkadot_primitives::v4::PersistedValidationData, polkadot_primitives::v4::ValidationCodeHash)> { + polkadot_runtime_parachains::runtime_api_impl::v4::assumed_validation_data::( para_id, expected_persisted_validation_data_hash, ) } fn check_validation_outputs( - para_id: polkadot_primitives::v2::Id, - outputs: polkadot_primitives::v2::CandidateCommitments, + para_id: polkadot_primitives::v4::Id, + outputs: polkadot_primitives::v4::CandidateCommitments, ) -> bool { - polkadot_runtime_parachains::runtime_api_impl::v2::check_validation_outputs::(para_id, outputs) + polkadot_runtime_parachains::runtime_api_impl::v4::check_validation_outputs::(para_id, outputs) } - fn session_index_for_child() -> polkadot_primitives::v2::SessionIndex { - polkadot_runtime_parachains::runtime_api_impl::v2::session_index_for_child::() + fn session_index_for_child() -> polkadot_primitives::v4::SessionIndex { + polkadot_runtime_parachains::runtime_api_impl::v4::session_index_for_child::() } - fn validation_code(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) - -> Option { - polkadot_runtime_parachains::runtime_api_impl::v2::validation_code::(para_id, assumption) + fn validation_code(para_id: polkadot_primitives::v4::Id, assumption: polkadot_primitives::v4::OccupiedCoreAssumption) + -> Option { + polkadot_runtime_parachains::runtime_api_impl::v4::validation_code::(para_id, assumption) } - fn candidate_pending_availability(para_id: polkadot_primitives::v2::Id) -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v2::candidate_pending_availability::(para_id) + fn candidate_pending_availability(para_id: polkadot_primitives::v4::Id) -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v4::candidate_pending_availability::(para_id) } - fn candidate_events() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v2::candidate_events::(|ev| { + fn candidate_events() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v4::candidate_events::(|ev| { match ev { RuntimeEvent::Inclusion(ev) => { Some(ev) @@ -812,46 +824,54 @@ impl_runtime_apis! { }) } - fn session_info(index: polkadot_primitives::v2::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v2::session_info::(index) + fn session_info(index: polkadot_primitives::v4::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v4::session_info::(index) } - fn dmq_contents(recipient: polkadot_primitives::v2::Id) -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v2::dmq_contents::(recipient) + fn dmq_contents(recipient: polkadot_primitives::v4::Id) -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v4::dmq_contents::(recipient) } fn inbound_hrmp_channels_contents( - recipient: polkadot_primitives::v2::Id - ) -> BTreeMap>> { - polkadot_runtime_parachains::runtime_api_impl::v2::inbound_hrmp_channels_contents::(recipient) + recipient: polkadot_primitives::v4::Id + ) -> BTreeMap>> { + polkadot_runtime_parachains::runtime_api_impl::v4::inbound_hrmp_channels_contents::(recipient) } - fn validation_code_by_hash(hash: polkadot_primitives::v2::ValidationCodeHash) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_by_hash::(hash) + fn validation_code_by_hash(hash: polkadot_primitives::v4::ValidationCodeHash) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v4::validation_code_by_hash::(hash) } - fn on_chain_votes() -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v2::on_chain_votes::() + fn on_chain_votes() -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v4::on_chain_votes::() } - fn submit_pvf_check_statement(stmt: polkadot_primitives::v2::PvfCheckStatement, signature: polkadot_primitives::v2::ValidatorSignature) { - polkadot_runtime_parachains::runtime_api_impl::v2::submit_pvf_check_statement::(stmt, signature) + fn submit_pvf_check_statement(stmt: polkadot_primitives::v4::PvfCheckStatement, signature: polkadot_primitives::v4::ValidatorSignature) { + polkadot_runtime_parachains::runtime_api_impl::v4::submit_pvf_check_statement::(stmt, signature) } - fn pvfs_require_precheck() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v2::pvfs_require_precheck::() + fn pvfs_require_precheck() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v4::pvfs_require_precheck::() } - fn validation_code_hash(para_id: polkadot_primitives::v2::Id, assumption: polkadot_primitives::v2::OccupiedCoreAssumption) - -> Option + fn validation_code_hash(para_id: polkadot_primitives::v4::Id, assumption: polkadot_primitives::v4::OccupiedCoreAssumption) + -> Option { - polkadot_runtime_parachains::runtime_api_impl::v2::validation_code_hash::(para_id, assumption) + polkadot_runtime_parachains::runtime_api_impl::v4::validation_code_hash::(para_id, assumption) + } + + fn disputes() -> Vec<(polkadot_primitives::v4::SessionIndex, polkadot_primitives::v4::CandidateHash, polkadot_primitives::v4::DisputeState)> { + polkadot_runtime_parachains::runtime_api_impl::v4::get_session_disputes::() + } + + fn session_executor_params(session_index: polkadot_primitives::v4::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v4::session_executor_params::(session_index) } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { fn authorities() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v2::relevant_authority_ids::() + polkadot_runtime_parachains::runtime_api_impl::v4::relevant_authority_ids::() } } diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 9a3346eafd870..8ceb27140f004 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -23,7 +23,7 @@ use crate::{ use frame_support::{parameter_types, traits::KeyOwnerProofSystem}; use frame_system::EnsureRoot; -use polkadot_primitives::v2::{ValidatorId, ValidatorIndex}; +use polkadot_primitives::v4::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ configuration as parachains_configuration, disputes as parachains_disputes, diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 7a4966d92ddaf..9f6488b4c4d31 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -27,6 +27,7 @@ use frame_support::{ traits::{ConstU32, Everything, Nothing}, weights::Weight, }; +use frame_system::EnsureRoot; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, @@ -182,6 +183,7 @@ impl pallet_xcm::Config for Runtime { type WeightInfo = pallet_xcm::TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; + type AdminOrigin = EnsureRoot; } #[cfg(test)] diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index dde9e70f576ae..e4a5d7ccce1b2 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -hash-db = { version = "0.15.2", default-features = false } +hash-db = { version = "0.16.0", default-features = false } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 5c2c967c060a8..ac6cf122b0f1d 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -172,6 +172,10 @@ impl pallet_balances::Config for TestRuntime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } impl pallet_transaction_payment::Config for TestRuntime { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index a31ee2b940134..807721ba86674 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -40,7 +40,7 @@ use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, ConstU32, IdentityLookup}, Perbill, }; use std::{ @@ -133,6 +133,10 @@ impl pallet_balances::Config for TestRuntime { type WeightInfo = (); type MaxReserves = (); type ReserveIdentifier = (); + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } parameter_types! { diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index c40c86f1db547..5e97e81ae3344 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -24,7 +24,7 @@ use frame_support::{parameter_types, weights::RuntimeDbWeight}; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, ConstU32, IdentityLookup}, }; pub type AccountId = u64; @@ -86,6 +86,10 @@ impl pallet_balances::Config for TestRuntime { type WeightInfo = (); type MaxReserves = (); type ReserveIdentifier = (); + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } impl pallet_bridge_relayers::Config for TestRuntime { diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 5a745fdaba470..4c9f9e20468c6 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -53,7 +53,7 @@ pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// This is a copy-paste from the cumulus repo's `parachains-common` crate. const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_SECOND, 0) .saturating_div(2) - .set_proof_size(polkadot_primitives::v2::MAX_POV_SIZE as u64); + .set_proof_size(polkadot_primitives::v4::MAX_POV_SIZE as u64); /// All cumulus bridge hubs assume that about 5 percent of the block weight is consumed by /// `on_initialize` handlers. This is used to limit the maximal weight of a single extrinsic. diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index fb35095841502..f14b841fa9ebe 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -21,7 +21,7 @@ use bp_messages::LaneId; use bp_runtime::{ChainId, StorageDoubleMapKeyProvider}; -use frame_support::{Blake2_128Concat, Identity}; +use frame_support::{traits::tokens::Preservation, Blake2_128Concat, Identity}; use scale_info::TypeInfo; use sp_runtime::{ codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}, @@ -110,7 +110,7 @@ where impl PaymentProcedure for PayRewardFromAccount where - T: frame_support::traits::fungible::Transfer, + T: frame_support::traits::fungible::Mutate, Relayer: Decode + Encode, { type Error = sp_runtime::DispatchError; @@ -120,8 +120,13 @@ where rewards_account_params: RewardsAccountParams, reward: T::Balance, ) -> Result<(), Self::Error> { - T::transfer(&Self::rewards_account(rewards_account_params), relayer, reward, false) - .map(drop) + T::transfer( + &Self::rewards_account(rewards_account_params), + relayer, + reward, + Preservation::Expendable, + ) + .map(drop) } } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 5ec7a353fdfe3..802e58e1af1ab 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -hash-db = { version = "0.15.2", default-features = false } +hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 1bc9f941ecf29..320277590bcd0 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -103,8 +103,8 @@ impl RegisterParachain { let para_id: ParaId = relay_client .storage_value(StorageKey(para_id_key.to_vec()), None) .await? - .unwrap_or(polkadot_primitives::v2::LOWEST_PUBLIC_ID) - .max(polkadot_primitives::v2::LOWEST_PUBLIC_ID); + .unwrap_or(polkadot_primitives::v4::LOWEST_PUBLIC_ID) + .max(polkadot_primitives::v4::LOWEST_PUBLIC_ID); log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 02a9c70ce5e5d..987ac532ca6d8 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -subxt = { git = "https://github.com/paritytech/subxt", branch = "master", default-features = false, features = [] } +subxt = { version = "0.27.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs index d725aafd41553..893bca1e27eff 100644 --- a/relays/client-rialto-parachain/src/codegen_runtime.rs +++ b/relays/client-rialto-parachain/src/codegen_runtime.rs @@ -22,11 +22,10 @@ #[allow(clippy::all)] pub mod api { use super::api as root_mod; - pub static PALLETS: [&str; 17usize] = [ + pub static PALLETS: [&str; 16usize] = [ "System", "Timestamp", "Sudo", - "RandomnessCollectiveFlip", "TransactionPayment", "ParachainSystem", "ParachainInfo", @@ -49,7 +48,7 @@ pub mod api { System(system::Event), #[codec(index = 2)] Sudo(sudo::Event), - #[codec(index = 4)] + #[codec(index = 3)] TransactionPayment(transaction_payment::Event), #[codec(index = 20)] ParachainSystem(parachain_system::Event), @@ -65,6 +64,8 @@ pub mod api { DmpQueue(dmp_queue::Event), #[codec(index = 54)] BridgeRelayers(bridge_relayers::Event), + #[codec(index = 55)] + BridgeMillauGrandpa(bridge_millau_grandpa::Event), #[codec(index = 56)] BridgeMillauMessages(bridge_millau_messages::Event), } @@ -134,9 +135,8 @@ pub mod api { impl TransactionApi { #[doc = "Make some on-chain remark."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(1)`"] - #[doc = "# "] pub fn remark( &self, remark: ::std::vec::Vec<::core::primitive::u8>, @@ -171,16 +171,8 @@ pub mod api { } #[doc = "Set the new runtime code."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code`"] - #[doc = "- 1 call to `can_set_code`: `O(S)` (calls `sp_io::misc::runtime_version` which is"] - #[doc = " expensive)."] - #[doc = "- 1 storage write (codec `O(C)`)."] - #[doc = "- 1 digest item."] - #[doc = "- 1 event."] - #[doc = "The weight of this function is dependent on the runtime, but generally this is very"] - #[doc = "expensive. We will treat this as a full block."] - #[doc = "# "] pub fn set_code( &self, code: ::std::vec::Vec<::core::primitive::u8>, @@ -198,13 +190,8 @@ pub mod api { } #[doc = "Set the new runtime code without doing any checks of the given `code`."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(C)` where `C` length of `code`"] - #[doc = "- 1 storage write (codec `O(C)`)."] - #[doc = "- 1 digest item."] - #[doc = "- 1 event."] - #[doc = "The weight of this function is dependent on the runtime. We will treat this as a full"] - #[doc = "block. # "] pub fn set_code_without_checks( &self, code: ::std::vec::Vec<::core::primitive::u8>, @@ -379,7 +366,9 @@ pub mod api { ::subxt::metadata::DecodeStaticType< runtime_types::frame_system::AccountInfo< ::core::primitive::u32, - runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + runtime_types::pallet_balances::types::AccountData< + ::core::primitive::u128, + >, >, >, ::subxt::storage::address::Yes, @@ -394,9 +383,10 @@ pub mod api { ::subxt::storage::address::StorageHasher::Blake2_128Concat, )], [ - 176u8, 187u8, 21u8, 220u8, 159u8, 204u8, 127u8, 14u8, 21u8, 69u8, 77u8, - 114u8, 230u8, 141u8, 107u8, 79u8, 23u8, 16u8, 174u8, 243u8, 252u8, - 42u8, 65u8, 120u8, 229u8, 38u8, 210u8, 255u8, 22u8, 40u8, 109u8, 223u8, + 248u8, 178u8, 160u8, 222u8, 45u8, 231u8, 115u8, 164u8, 98u8, 184u8, + 174u8, 206u8, 149u8, 190u8, 175u8, 34u8, 202u8, 230u8, 69u8, 218u8, + 83u8, 43u8, 170u8, 41u8, 106u8, 77u8, 233u8, 97u8, 114u8, 14u8, 155u8, + 131u8, ], ) } @@ -407,7 +397,9 @@ pub mod api { ::subxt::metadata::DecodeStaticType< runtime_types::frame_system::AccountInfo< ::core::primitive::u32, - runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + runtime_types::pallet_balances::types::AccountData< + ::core::primitive::u128, + >, >, >, (), @@ -419,9 +411,10 @@ pub mod api { "Account", Vec::new(), [ - 176u8, 187u8, 21u8, 220u8, 159u8, 204u8, 127u8, 14u8, 21u8, 69u8, 77u8, - 114u8, 230u8, 141u8, 107u8, 79u8, 23u8, 16u8, 174u8, 243u8, 252u8, - 42u8, 65u8, 120u8, 229u8, 38u8, 210u8, 255u8, 22u8, 40u8, 109u8, 223u8, + 248u8, 178u8, 160u8, 222u8, 45u8, 231u8, 115u8, 164u8, 98u8, 184u8, + 174u8, 206u8, 149u8, 190u8, 175u8, 34u8, 202u8, 230u8, 69u8, 218u8, + 83u8, 43u8, 170u8, 41u8, 106u8, 77u8, 233u8, 97u8, 114u8, 14u8, 155u8, + 131u8, ], ) } @@ -668,9 +661,9 @@ pub mod api { "Events", vec![], [ - 4u8, 71u8, 59u8, 55u8, 39u8, 106u8, 211u8, 249u8, 109u8, 197u8, 134u8, - 138u8, 5u8, 188u8, 131u8, 120u8, 65u8, 30u8, 151u8, 104u8, 238u8, 32u8, - 251u8, 122u8, 104u8, 218u8, 7u8, 84u8, 253u8, 65u8, 48u8, 185u8, + 76u8, 19u8, 44u8, 121u8, 59u8, 168u8, 101u8, 101u8, 248u8, 3u8, 172u8, + 27u8, 249u8, 200u8, 147u8, 17u8, 4u8, 102u8, 186u8, 6u8, 152u8, 62u8, + 76u8, 195u8, 45u8, 188u8, 191u8, 30u8, 134u8, 78u8, 199u8, 93u8, ], ) } @@ -990,12 +983,11 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be `Inherent`."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(1)` (Note that implementations of `OnTimestampSet` must also be `O(1)`)"] #[doc = "- 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in"] #[doc = " `on_finalize`)"] #[doc = "- 1 event handler `on_timestamp_set`. Must be `O(1)`."] - #[doc = "# "] pub fn set( &self, now: ::core::primitive::u64, @@ -1124,12 +1116,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- Limited storage reads."] - #[doc = "- One DB write (event)."] - #[doc = "- Weight of derivative `call` execution + 10,000."] - #[doc = "# "] pub fn sudo( &self, call: runtime_types::rialto_parachain_runtime::RuntimeCall, @@ -1139,10 +1127,9 @@ pub mod api { "sudo", Sudo { call: ::std::boxed::Box::new(call) }, [ - 229u8, 162u8, 204u8, 182u8, 225u8, 254u8, 3u8, 66u8, 233u8, 49u8, 60u8, - 73u8, 182u8, 192u8, 90u8, 122u8, 176u8, 63u8, 200u8, 64u8, 111u8, - 155u8, 223u8, 233u8, 51u8, 220u8, 157u8, 192u8, 74u8, 236u8, 150u8, - 222u8, + 19u8, 178u8, 172u8, 30u8, 28u8, 209u8, 160u8, 61u8, 76u8, 239u8, 71u8, + 124u8, 21u8, 34u8, 233u8, 176u8, 100u8, 90u8, 198u8, 118u8, 117u8, 2u8, + 147u8, 7u8, 109u8, 1u8, 32u8, 35u8, 99u8, 0u8, 107u8, 145u8, ], ) } @@ -1152,10 +1139,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- The weight of this call is defined by the caller."] - #[doc = "# "] pub fn sudo_unchecked_weight( &self, call: runtime_types::rialto_parachain_runtime::RuntimeCall, @@ -1166,9 +1151,10 @@ pub mod api { "sudo_unchecked_weight", SudoUncheckedWeight { call: ::std::boxed::Box::new(call), weight }, [ - 161u8, 202u8, 77u8, 33u8, 112u8, 211u8, 100u8, 184u8, 205u8, 250u8, - 70u8, 16u8, 39u8, 213u8, 108u8, 2u8, 195u8, 255u8, 15u8, 72u8, 142u8, - 180u8, 26u8, 203u8, 73u8, 81u8, 10u8, 29u8, 34u8, 101u8, 47u8, 99u8, + 145u8, 160u8, 12u8, 105u8, 228u8, 240u8, 115u8, 105u8, 220u8, 99u8, + 215u8, 228u8, 115u8, 71u8, 109u8, 28u8, 149u8, 247u8, 159u8, 216u8, + 76u8, 71u8, 68u8, 87u8, 254u8, 146u8, 185u8, 174u8, 251u8, 209u8, 72u8, + 122u8, ], ) } @@ -1177,11 +1163,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- Limited storage reads."] - #[doc = "- One DB change."] - #[doc = "# "] pub fn set_key( &self, new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -1202,12 +1185,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- Limited storage reads."] - #[doc = "- One DB write (event)."] - #[doc = "- Weight of derivative `call` execution + 10,000."] - #[doc = "# "] pub fn sudo_as( &self, who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -1218,10 +1197,10 @@ pub mod api { "sudo_as", SudoAs { who, call: ::std::boxed::Box::new(call) }, [ - 100u8, 104u8, 192u8, 203u8, 123u8, 243u8, 209u8, 131u8, 26u8, 247u8, - 84u8, 157u8, 133u8, 227u8, 210u8, 237u8, 58u8, 23u8, 139u8, 213u8, - 134u8, 19u8, 12u8, 31u8, 219u8, 212u8, 230u8, 37u8, 152u8, 199u8, - 220u8, 163u8, + 229u8, 45u8, 129u8, 96u8, 54u8, 29u8, 159u8, 77u8, 210u8, 144u8, 29u8, + 97u8, 127u8, 133u8, 122u8, 110u8, 152u8, 194u8, 211u8, 246u8, 97u8, + 197u8, 187u8, 203u8, 46u8, 12u8, 104u8, 125u8, 15u8, 226u8, 28u8, + 183u8, ], ) } @@ -1294,42 +1273,6 @@ pub mod api { } } } - pub mod randomness_collective_flip { - use super::{root_mod, runtime_types}; - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " Series of block headers from the last 81 blocks that acts as random seed material. This"] - #[doc = " is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of"] - #[doc = " the oldest hash."] - pub fn random_material( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::bounded_vec::BoundedVec< - ::subxt::utils::H256, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "RandomnessCollectiveFlip", - "RandomMaterial", - vec![], - [ - 152u8, 126u8, 73u8, 88u8, 54u8, 147u8, 6u8, 19u8, 214u8, 40u8, 159u8, - 30u8, 236u8, 61u8, 240u8, 65u8, 178u8, 94u8, 146u8, 152u8, 135u8, - 252u8, 160u8, 86u8, 123u8, 114u8, 251u8, 140u8, 98u8, 143u8, 217u8, - 242u8, - ], - ) - } - } - } - } pub mod transaction_payment { use super::{root_mod, runtime_types}; #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] @@ -1468,6 +1411,7 @@ pub mod api { )] pub struct AuthorizeUpgrade { pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, } #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, @@ -1517,21 +1461,40 @@ pub mod api { ], ) } + #[doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] + #[doc = "later."] + #[doc = ""] + #[doc = "The `check_version` parameter sets a boolean flag for whether or not the runtime's spec"] + #[doc = "version and name should be verified on upgrade. Since the authorization only has a hash,"] + #[doc = "it cannot actually perform the verification."] + #[doc = ""] + #[doc = "This call requires Root origin."] pub fn authorize_upgrade( &self, code_hash: ::subxt::utils::H256, + check_version: ::core::primitive::bool, ) -> ::subxt::tx::StaticTxPayload { ::subxt::tx::StaticTxPayload::new( "ParachainSystem", "authorize_upgrade", - AuthorizeUpgrade { code_hash }, + AuthorizeUpgrade { code_hash, check_version }, [ - 52u8, 152u8, 69u8, 207u8, 143u8, 113u8, 163u8, 11u8, 181u8, 182u8, - 124u8, 101u8, 207u8, 19u8, 59u8, 81u8, 129u8, 29u8, 79u8, 115u8, 90u8, - 83u8, 225u8, 124u8, 21u8, 108u8, 99u8, 194u8, 78u8, 83u8, 252u8, 163u8, + 208u8, 115u8, 62u8, 35u8, 70u8, 223u8, 65u8, 57u8, 216u8, 44u8, 169u8, + 249u8, 90u8, 112u8, 17u8, 208u8, 30u8, 131u8, 102u8, 131u8, 240u8, + 217u8, 230u8, 214u8, 145u8, 198u8, 55u8, 13u8, 217u8, 51u8, 178u8, + 141u8, ], ) } + #[doc = "Provide the preimage (runtime binary) `code` for an upgrade that has been authorized."] + #[doc = ""] + #[doc = "If the authorization required a version check, this call will ensure the spec name"] + #[doc = "remains unchanged and that the spec version has increased."] + #[doc = ""] + #[doc = "Note that this function will not apply the new `code`, but only attempt to schedule the"] + #[doc = "upgrade with the Relay Chain."] + #[doc = ""] + #[doc = "All origins are allowed."] pub fn enact_authorized_upgrade( &self, code: ::std::vec::Vec<::core::primitive::u8>, @@ -1696,7 +1659,7 @@ pub mod api { &self, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::polkadot_primitives::v2::PersistedValidationData< + runtime_types::polkadot_primitives::v4::PersistedValidationData< ::subxt::utils::H256, ::core::primitive::u32, >, @@ -1769,7 +1732,7 @@ pub mod api { ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< ::core::option::Option< - runtime_types::polkadot_primitives::v2::UpgradeRestriction, + runtime_types::polkadot_primitives::v4::UpgradeRestriction, >, >, ::subxt::storage::address::Yes, @@ -1844,7 +1807,7 @@ pub mod api { &self, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::polkadot_primitives::v2::AbridgedHostConfiguration, + runtime_types::polkadot_primitives::v4::AbridgedHostConfiguration, >, ::subxt::storage::address::Yes, (), @@ -2105,7 +2068,9 @@ pub mod api { pub fn authorized_upgrade( &self, ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, + ::subxt::metadata::DecodeStaticType< + runtime_types::cumulus_pallet_parachain_system::CodeUpgradeAuthorization, + >, ::subxt::storage::address::Yes, (), (), @@ -2115,10 +2080,9 @@ pub mod api { "AuthorizedUpgrade", vec![], [ - 136u8, 238u8, 241u8, 144u8, 252u8, 61u8, 101u8, 171u8, 234u8, 160u8, - 145u8, 210u8, 69u8, 29u8, 204u8, 166u8, 250u8, 101u8, 254u8, 32u8, - 96u8, 197u8, 222u8, 212u8, 50u8, 189u8, 25u8, 7u8, 48u8, 183u8, 234u8, - 95u8, + 12u8, 212u8, 71u8, 191u8, 89u8, 101u8, 195u8, 3u8, 23u8, 180u8, 233u8, + 52u8, 53u8, 133u8, 207u8, 94u8, 58u8, 43u8, 221u8, 236u8, 161u8, 41u8, + 30u8, 194u8, 125u8, 2u8, 118u8, 152u8, 197u8, 49u8, 34u8, 33u8, ], ) } @@ -2186,7 +2150,7 @@ pub mod api { #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] - pub struct Transfer { + pub struct TransferAllowDeath { pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] pub value: ::core::primitive::u128, @@ -2194,12 +2158,12 @@ pub mod api { #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] - pub struct SetBalance { + pub struct SetBalanceDeprecated { pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] pub new_free: ::core::primitive::u128, #[codec(compact)] - pub new_reserved: ::core::primitive::u128, + pub old_reserved: ::core::primitive::u128, } #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, @@ -2232,82 +2196,79 @@ pub mod api { pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, pub amount: ::core::primitive::u128, } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct UpgradeAccounts { + pub who: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct Transfer { + pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + pub value: ::core::primitive::u128, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct ForceSetBalance { + pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + pub new_free: ::core::primitive::u128, + } pub struct TransactionApi; impl TransactionApi { #[doc = "Transfer some liquid free balance to another account."] #[doc = ""] - #[doc = "`transfer` will set the `FreeBalance` of the sender and receiver."] + #[doc = "`transfer_allow_death` will set the `FreeBalance` of the sender and receiver."] #[doc = "If the sender's account is below the existential deposit as a result"] #[doc = "of the transfer, the account will be reaped."] #[doc = ""] #[doc = "The dispatch origin for this call must be `Signed` by the transactor."] - #[doc = ""] - #[doc = "# "] - #[doc = "- Dependent on arguments but not critical, given proper implementations for input config"] - #[doc = " types. See related functions below."] - #[doc = "- It contains a limited number of reads and writes internally and no complex"] - #[doc = " computation."] - #[doc = ""] - #[doc = "Related functions:"] - #[doc = ""] - #[doc = " - `ensure_can_withdraw` is always called internally but has a bounded complexity."] - #[doc = " - Transferring balances to accounts that did not exist before will cause"] - #[doc = " `T::OnNewAccount::on_new_account` to be called."] - #[doc = " - Removing enough funds from an account will trigger `T::DustRemoval::on_unbalanced`."] - #[doc = " - `transfer_keep_alive` works the same way as `transfer`, but has an additional check"] - #[doc = " that the transfer will not kill the origin account."] - #[doc = "---------------------------------"] - #[doc = "- Origin account is already in memory, so no DB operations for them."] - #[doc = "# "] - pub fn transfer( + pub fn transfer_allow_death( &self, dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, value: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { + ) -> ::subxt::tx::StaticTxPayload { ::subxt::tx::StaticTxPayload::new( "Balances", - "transfer", - Transfer { dest, value }, + "transfer_allow_death", + TransferAllowDeath { dest, value }, [ - 111u8, 222u8, 32u8, 56u8, 171u8, 77u8, 252u8, 29u8, 194u8, 155u8, - 200u8, 192u8, 198u8, 81u8, 23u8, 115u8, 236u8, 91u8, 218u8, 114u8, - 107u8, 141u8, 138u8, 100u8, 237u8, 21u8, 58u8, 172u8, 3u8, 20u8, 216u8, - 38u8, + 234u8, 130u8, 149u8, 36u8, 235u8, 112u8, 159u8, 189u8, 104u8, 148u8, + 108u8, 230u8, 25u8, 198u8, 71u8, 158u8, 112u8, 3u8, 162u8, 25u8, 145u8, + 252u8, 44u8, 63u8, 47u8, 34u8, 47u8, 158u8, 61u8, 14u8, 120u8, 255u8, ], ) } - #[doc = "Set the balances of a given account."] - #[doc = ""] - #[doc = "This will alter `FreeBalance` and `ReservedBalance` in storage. it will"] - #[doc = "also alter the total issuance of the system (`TotalIssuance`) appropriately."] - #[doc = "If the new free or reserved balance is below the existential deposit,"] - #[doc = "it will reset the account nonce (`frame_system::AccountNonce`)."] + #[doc = "Set the regular balance of a given account; it also takes a reserved balance but this"] + #[doc = "must be the same as the account's current reserved balance."] #[doc = ""] #[doc = "The dispatch origin for this call is `root`."] - pub fn set_balance( + #[doc = ""] + #[doc = "WARNING: This call is DEPRECATED! Use `force_set_balance` instead."] + pub fn set_balance_deprecated( &self, who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, new_free: ::core::primitive::u128, - new_reserved: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { + old_reserved: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { ::subxt::tx::StaticTxPayload::new( "Balances", - "set_balance", - SetBalance { who, new_free, new_reserved }, + "set_balance_deprecated", + SetBalanceDeprecated { who, new_free, old_reserved }, [ - 234u8, 215u8, 97u8, 98u8, 243u8, 199u8, 57u8, 76u8, 59u8, 161u8, 118u8, - 207u8, 34u8, 197u8, 198u8, 61u8, 231u8, 210u8, 169u8, 235u8, 150u8, - 137u8, 173u8, 49u8, 28u8, 77u8, 84u8, 149u8, 143u8, 210u8, 139u8, - 193u8, + 240u8, 107u8, 184u8, 206u8, 78u8, 106u8, 115u8, 152u8, 130u8, 56u8, + 156u8, 176u8, 105u8, 27u8, 176u8, 187u8, 49u8, 171u8, 229u8, 79u8, + 254u8, 248u8, 8u8, 162u8, 134u8, 12u8, 89u8, 100u8, 137u8, 102u8, + 132u8, 158u8, ], ) } - #[doc = "Exactly as `transfer`, except the origin must be root and the source account may be"] - #[doc = "specified."] - #[doc = "# "] - #[doc = "- Same as transfer, but additional read and write because the source account is not"] - #[doc = " assumed to be in the overlay."] - #[doc = "# "] + #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] + #[doc = "may be specified."] pub fn force_transfer( &self, source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -2326,12 +2287,12 @@ pub mod api { ], ) } - #[doc = "Same as the [`transfer`] call, but with a check that the transfer will not kill the"] - #[doc = "origin account."] + #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] + #[doc = "kill the origin account."] #[doc = ""] - #[doc = "99% of the time you want [`transfer`] instead."] + #[doc = "99% of the time you want [`transfer_allow_death`] instead."] #[doc = ""] - #[doc = "[`transfer`]: struct.Pallet.html#method.transfer"] + #[doc = "[`transfer_allow_death`]: struct.Pallet.html#method.transfer"] pub fn transfer_keep_alive( &self, dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -2363,9 +2324,7 @@ pub mod api { #[doc = "- `keep_alive`: A boolean to determine if the `transfer_all` operation should send all"] #[doc = " of the funds the account has, causing the sender account to be killed (false), or"] #[doc = " transfer everything except at least the existential deposit, which will guarantee to"] - #[doc = " keep the sender account alive (true). # "] - #[doc = "- O(1). Just like transfer, but reading the user's transferable balance first."] - #[doc = " #"] + #[doc = " keep the sender account alive (true)."] pub fn transfer_all( &self, dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -2403,6 +2362,68 @@ pub mod api { ], ) } + #[doc = "Upgrade a specified account."] + #[doc = ""] + #[doc = "- `origin`: Must be `Signed`."] + #[doc = "- `who`: The account to be upgraded."] + #[doc = ""] + #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] + #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] + #[doc = "possibililty of churn)."] + pub fn upgrade_accounts( + &self, + who: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "upgrade_accounts", + UpgradeAccounts { who }, + [ + 164u8, 61u8, 119u8, 24u8, 165u8, 46u8, 197u8, 59u8, 39u8, 198u8, 228u8, + 96u8, 228u8, 45u8, 85u8, 51u8, 37u8, 5u8, 75u8, 40u8, 241u8, 163u8, + 86u8, 228u8, 151u8, 217u8, 47u8, 105u8, 203u8, 103u8, 207u8, 4u8, + ], + ) + } + #[doc = "Alias for `transfer_allow_death`, provided only for name-wise compatibility."] + #[doc = ""] + #[doc = "WARNING: DEPRECATED! Will be released in approximately 3 months."] + pub fn transfer( + &self, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + value: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "transfer", + Transfer { dest, value }, + [ + 111u8, 222u8, 32u8, 56u8, 171u8, 77u8, 252u8, 29u8, 194u8, 155u8, + 200u8, 192u8, 198u8, 81u8, 23u8, 115u8, 236u8, 91u8, 218u8, 114u8, + 107u8, 141u8, 138u8, 100u8, 237u8, 21u8, 58u8, 172u8, 3u8, 20u8, 216u8, + 38u8, + ], + ) + } + #[doc = "Set the regular balance of a given account."] + #[doc = ""] + #[doc = "The dispatch origin for this call is `root`."] + pub fn force_set_balance( + &self, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + new_free: ::core::primitive::u128, + ) -> ::subxt::tx::StaticTxPayload { + ::subxt::tx::StaticTxPayload::new( + "Balances", + "force_set_balance", + ForceSetBalance { who, new_free }, + [ + 237u8, 4u8, 41u8, 58u8, 62u8, 179u8, 160u8, 4u8, 50u8, 71u8, 178u8, + 36u8, 130u8, 130u8, 92u8, 229u8, 16u8, 245u8, 169u8, 109u8, 165u8, + 72u8, 94u8, 70u8, 196u8, 136u8, 37u8, 94u8, 140u8, 215u8, 125u8, 125u8, + ], + ) + } } } #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] @@ -2454,7 +2475,6 @@ pub mod api { pub struct BalanceSet { pub who: ::sp_core::crypto::AccountId32, pub free: ::core::primitive::u128, - pub reserved: ::core::primitive::u128, } impl ::subxt::events::StaticEvent for BalanceSet { const PALLET: &'static str = "Balances"; @@ -2536,6 +2556,95 @@ pub mod api { const PALLET: &'static str = "Balances"; const EVENT: &'static str = "Slashed"; } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was minted into an account."] + pub struct Minted { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Minted { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Minted"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was burned from an account."] + pub struct Burned { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Burned { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Burned"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was suspended from an account (it can be restored later)."] + pub struct Suspended { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Suspended { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Suspended"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Some amount was restored into an account."] + pub struct Restored { + pub who: ::sp_core::crypto::AccountId32, + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Restored { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Restored"; + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "An account was upgraded."] + pub struct Upgraded { + pub who: ::sp_core::crypto::AccountId32, + } + impl ::subxt::events::StaticEvent for Upgraded { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Upgraded"; + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Total issuance was increased by `amount`, creating a credit to be balanced."] + pub struct Issued { + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Issued { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Issued"; + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "Total issuance was decreased by `amount`, creating a debt to be balanced."] + pub struct Rescinded { + pub amount: ::core::primitive::u128, + } + impl ::subxt::events::StaticEvent for Rescinded { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Rescinded"; + } } pub mod storage { use super::runtime_types; @@ -2611,7 +2720,7 @@ pub mod api { _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + runtime_types::pallet_balances::types::AccountData<::core::primitive::u128>, >, ::subxt::storage::address::Yes, ::subxt::storage::address::Yes, @@ -2625,9 +2734,10 @@ pub mod api { ::subxt::storage::address::StorageHasher::Blake2_128Concat, )], [ - 246u8, 154u8, 253u8, 71u8, 192u8, 192u8, 192u8, 236u8, 128u8, 80u8, - 40u8, 252u8, 201u8, 43u8, 3u8, 131u8, 19u8, 49u8, 141u8, 240u8, 172u8, - 217u8, 215u8, 109u8, 87u8, 135u8, 248u8, 57u8, 98u8, 185u8, 22u8, 4u8, + 109u8, 250u8, 18u8, 96u8, 139u8, 232u8, 4u8, 139u8, 133u8, 239u8, 30u8, + 237u8, 73u8, 209u8, 143u8, 160u8, 94u8, 248u8, 124u8, 43u8, 224u8, + 165u8, 11u8, 6u8, 176u8, 144u8, 189u8, 161u8, 174u8, 210u8, 56u8, + 225u8, ], ) } @@ -2659,7 +2769,7 @@ pub mod api { &self, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::pallet_balances::AccountData<::core::primitive::u128>, + runtime_types::pallet_balances::types::AccountData<::core::primitive::u128>, >, (), ::subxt::storage::address::Yes, @@ -2670,9 +2780,10 @@ pub mod api { "Account", Vec::new(), [ - 246u8, 154u8, 253u8, 71u8, 192u8, 192u8, 192u8, 236u8, 128u8, 80u8, - 40u8, 252u8, 201u8, 43u8, 3u8, 131u8, 19u8, 49u8, 141u8, 240u8, 172u8, - 217u8, 215u8, 109u8, 87u8, 135u8, 248u8, 57u8, 98u8, 185u8, 22u8, 4u8, + 109u8, 250u8, 18u8, 96u8, 139u8, 232u8, 4u8, 139u8, 133u8, 239u8, 30u8, + 237u8, 73u8, 209u8, 143u8, 160u8, 94u8, 248u8, 124u8, 43u8, 224u8, + 165u8, 11u8, 6u8, 176u8, 144u8, 189u8, 161u8, 174u8, 210u8, 56u8, + 225u8, ], ) } @@ -2683,8 +2794,10 @@ pub mod api { _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< - runtime_types::pallet_balances::BalanceLock<::core::primitive::u128>, + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + runtime_types::pallet_balances::types::BalanceLock< + ::core::primitive::u128, + >, >, >, ::subxt::storage::address::Yes, @@ -2711,8 +2824,10 @@ pub mod api { &self, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< - runtime_types::pallet_balances::BalanceLock<::core::primitive::u128>, + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + runtime_types::pallet_balances::types::BalanceLock< + ::core::primitive::u128, + >, >, >, (), @@ -2736,8 +2851,8 @@ pub mod api { _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::bounded_vec::BoundedVec< - runtime_types::pallet_balances::ReserveData< + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_balances::types::ReserveData< [::core::primitive::u8; 8usize], ::core::primitive::u128, >, @@ -2766,8 +2881,8 @@ pub mod api { &self, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::bounded_vec::BoundedVec< - runtime_types::pallet_balances::ReserveData< + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_balances::types::ReserveData< [::core::primitive::u8; 8usize], ::core::primitive::u128, >, @@ -2788,6 +2903,122 @@ pub mod api { ], ) } + #[doc = " Holds on account balances."] + pub fn holds( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_balances::types::IdAmount< + (), + ::core::primitive::u128, + >, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Holds", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 247u8, 81u8, 4u8, 220u8, 77u8, 205u8, 28u8, 131u8, 215u8, 74u8, 197u8, + 137u8, 113u8, 214u8, 249u8, 91u8, 81u8, 216u8, 8u8, 5u8, 233u8, 39u8, + 104u8, 250u8, 3u8, 228u8, 148u8, 78u8, 4u8, 34u8, 45u8, 143u8, + ], + ) + } + #[doc = " Holds on account balances."] + pub fn holds_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_balances::types::IdAmount< + (), + ::core::primitive::u128, + >, + >, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Holds", + Vec::new(), + [ + 247u8, 81u8, 4u8, 220u8, 77u8, 205u8, 28u8, 131u8, 215u8, 74u8, 197u8, + 137u8, 113u8, 214u8, 249u8, 91u8, 81u8, 216u8, 8u8, 5u8, 233u8, 39u8, + 104u8, 250u8, 3u8, 228u8, 148u8, 78u8, 4u8, 34u8, 45u8, 143u8, + ], + ) + } + #[doc = " Freeze locks on account balances."] + pub fn freezes( + &self, + _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_balances::types::IdAmount< + (), + ::core::primitive::u128, + >, + >, + >, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Freezes", + vec![::subxt::storage::address::StorageMapKey::new( + _0.borrow(), + ::subxt::storage::address::StorageHasher::Blake2_128Concat, + )], + [ + 211u8, 24u8, 237u8, 217u8, 47u8, 230u8, 147u8, 39u8, 112u8, 209u8, + 193u8, 47u8, 242u8, 13u8, 241u8, 0u8, 100u8, 45u8, 116u8, 130u8, 246u8, + 196u8, 50u8, 134u8, 135u8, 112u8, 206u8, 1u8, 12u8, 53u8, 106u8, 131u8, + ], + ) + } + #[doc = " Freeze locks on account balances."] + pub fn freezes_root( + &self, + ) -> ::subxt::storage::address::StaticStorageAddress< + ::subxt::metadata::DecodeStaticType< + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_balances::types::IdAmount< + (), + ::core::primitive::u128, + >, + >, + >, + (), + ::subxt::storage::address::Yes, + ::subxt::storage::address::Yes, + > { + ::subxt::storage::address::StaticStorageAddress::new( + "Balances", + "Freezes", + Vec::new(), + [ + 211u8, 24u8, 237u8, 217u8, 47u8, 230u8, 147u8, 39u8, 112u8, 209u8, + 193u8, 47u8, 242u8, 13u8, 241u8, 0u8, 100u8, 45u8, 116u8, 130u8, 246u8, + 196u8, 50u8, 134u8, 135u8, 112u8, 206u8, 1u8, 12u8, 53u8, 106u8, 131u8, + ], + ) + } } } pub mod constants { @@ -2845,6 +3076,40 @@ pub mod api { ], ) } + #[doc = " The maximum number of holds that can exist on an account at any time."] + pub fn max_holds( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "Balances", + "MaxHolds", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } + #[doc = " The maximum number of individual freeze locks that can exist on an account at any time."] + pub fn max_freezes( + &self, + ) -> ::subxt::constants::StaticConstantAddress< + ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, + > { + ::subxt::constants::StaticConstantAddress::new( + "Balances", + "MaxFreezes", + [ + 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, + 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, + 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, + 145u8, + ], + ) + } } } } @@ -3660,9 +3925,9 @@ pub mod api { message: ::std::boxed::Box::new(message), }, [ - 26u8, 89u8, 11u8, 127u8, 105u8, 218u8, 45u8, 49u8, 234u8, 4u8, 72u8, - 86u8, 134u8, 227u8, 122u8, 187u8, 183u8, 63u8, 27u8, 203u8, 123u8, - 200u8, 64u8, 192u8, 64u8, 204u8, 68u8, 98u8, 27u8, 234u8, 176u8, 93u8, + 246u8, 35u8, 227u8, 112u8, 223u8, 7u8, 44u8, 186u8, 60u8, 225u8, 153u8, + 249u8, 104u8, 51u8, 123u8, 227u8, 143u8, 65u8, 232u8, 209u8, 178u8, + 104u8, 70u8, 56u8, 230u8, 14u8, 75u8, 83u8, 250u8, 160u8, 9u8, 39u8, ], ) } @@ -3698,10 +3963,9 @@ pub mod api { fee_asset_item, }, [ - 18u8, 130u8, 117u8, 55u8, 235u8, 117u8, 250u8, 246u8, 109u8, 145u8, - 160u8, 184u8, 72u8, 76u8, 61u8, 229u8, 50u8, 94u8, 60u8, 202u8, 25u8, - 180u8, 228u8, 63u8, 171u8, 182u8, 224u8, 146u8, 196u8, 203u8, 243u8, - 70u8, + 187u8, 42u8, 2u8, 96u8, 105u8, 125u8, 74u8, 53u8, 2u8, 21u8, 31u8, + 160u8, 201u8, 197u8, 157u8, 190u8, 40u8, 145u8, 5u8, 99u8, 194u8, 41u8, + 114u8, 60u8, 165u8, 186u8, 15u8, 226u8, 85u8, 113u8, 159u8, 136u8, ], ) } @@ -3738,9 +4002,9 @@ pub mod api { fee_asset_item, }, [ - 233u8, 36u8, 82u8, 54u8, 27u8, 201u8, 7u8, 145u8, 212u8, 107u8, 150u8, - 124u8, 125u8, 135u8, 226u8, 60u8, 133u8, 157u8, 202u8, 114u8, 102u8, - 67u8, 170u8, 66u8, 133u8, 228u8, 66u8, 45u8, 55u8, 188u8, 0u8, 19u8, + 249u8, 177u8, 76u8, 204u8, 186u8, 165u8, 16u8, 186u8, 129u8, 239u8, + 65u8, 252u8, 9u8, 132u8, 32u8, 164u8, 117u8, 177u8, 40u8, 21u8, 196u8, + 246u8, 147u8, 2u8, 95u8, 110u8, 68u8, 162u8, 148u8, 9u8, 59u8, 170u8, ], ) } @@ -3765,10 +4029,9 @@ pub mod api { "execute", Execute { message: ::std::boxed::Box::new(message), max_weight }, [ - 144u8, 56u8, 199u8, 18u8, 111u8, 10u8, 128u8, 179u8, 178u8, 216u8, - 119u8, 103u8, 11u8, 218u8, 221u8, 181u8, 129u8, 24u8, 192u8, 66u8, - 219u8, 239u8, 33u8, 161u8, 3u8, 51u8, 25u8, 177u8, 169u8, 188u8, 197u8, - 33u8, + 102u8, 41u8, 146u8, 29u8, 241u8, 205u8, 95u8, 153u8, 228u8, 141u8, + 11u8, 228u8, 13u8, 44u8, 75u8, 204u8, 174u8, 35u8, 155u8, 104u8, 204u8, + 82u8, 239u8, 98u8, 249u8, 187u8, 193u8, 1u8, 122u8, 88u8, 162u8, 200u8, ], ) } @@ -3788,10 +4051,9 @@ pub mod api { "force_xcm_version", ForceXcmVersion { location: ::std::boxed::Box::new(location), xcm_version }, [ - 150u8, 120u8, 133u8, 146u8, 71u8, 43u8, 247u8, 59u8, 124u8, 234u8, - 125u8, 149u8, 216u8, 199u8, 137u8, 17u8, 87u8, 220u8, 110u8, 154u8, - 95u8, 92u8, 251u8, 180u8, 253u8, 1u8, 200u8, 98u8, 36u8, 48u8, 231u8, - 3u8, + 68u8, 48u8, 95u8, 61u8, 152u8, 95u8, 213u8, 126u8, 209u8, 176u8, 230u8, + 160u8, 164u8, 42u8, 128u8, 62u8, 175u8, 3u8, 161u8, 170u8, 20u8, 31u8, + 216u8, 122u8, 31u8, 77u8, 64u8, 182u8, 121u8, 41u8, 23u8, 80u8, ], ) } @@ -3828,10 +4090,9 @@ pub mod api { "force_subscribe_version_notify", ForceSubscribeVersionNotify { location: ::std::boxed::Box::new(location) }, [ - 44u8, 16u8, 170u8, 133u8, 130u8, 247u8, 158u8, 196u8, 23u8, 250u8, - 128u8, 106u8, 40u8, 44u8, 245u8, 45u8, 170u8, 223u8, 15u8, 12u8, 204u8, - 159u8, 92u8, 154u8, 186u8, 107u8, 13u8, 70u8, 17u8, 174u8, 192u8, - 111u8, + 236u8, 37u8, 153u8, 26u8, 174u8, 187u8, 154u8, 38u8, 179u8, 223u8, + 130u8, 32u8, 128u8, 30u8, 148u8, 229u8, 7u8, 185u8, 174u8, 9u8, 96u8, + 215u8, 189u8, 178u8, 148u8, 141u8, 249u8, 118u8, 7u8, 238u8, 1u8, 49u8, ], ) } @@ -3852,10 +4113,9 @@ pub mod api { location: ::std::boxed::Box::new(location), }, [ - 77u8, 123u8, 3u8, 212u8, 40u8, 117u8, 46u8, 241u8, 174u8, 0u8, 131u8, - 242u8, 193u8, 177u8, 104u8, 161u8, 42u8, 54u8, 252u8, 70u8, 209u8, - 47u8, 87u8, 181u8, 75u8, 177u8, 157u8, 90u8, 145u8, 110u8, 121u8, - 208u8, + 154u8, 169u8, 145u8, 211u8, 185u8, 71u8, 9u8, 63u8, 3u8, 158u8, 187u8, + 173u8, 115u8, 166u8, 100u8, 66u8, 12u8, 40u8, 198u8, 40u8, 213u8, + 104u8, 95u8, 183u8, 215u8, 53u8, 94u8, 158u8, 106u8, 56u8, 149u8, 52u8, ], ) } @@ -3896,9 +4156,9 @@ pub mod api { weight_limit, }, [ - 71u8, 241u8, 225u8, 54u8, 199u8, 145u8, 122u8, 171u8, 17u8, 54u8, 20u8, - 80u8, 102u8, 131u8, 241u8, 79u8, 5u8, 3u8, 193u8, 26u8, 22u8, 180u8, - 237u8, 226u8, 109u8, 219u8, 185u8, 161u8, 153u8, 79u8, 102u8, 93u8, + 131u8, 191u8, 89u8, 27u8, 236u8, 142u8, 130u8, 129u8, 245u8, 95u8, + 159u8, 96u8, 252u8, 80u8, 28u8, 40u8, 128u8, 55u8, 41u8, 123u8, 22u8, + 18u8, 0u8, 236u8, 77u8, 68u8, 135u8, 181u8, 40u8, 47u8, 92u8, 240u8, ], ) } @@ -3938,10 +4198,10 @@ pub mod api { weight_limit, }, [ - 157u8, 57u8, 28u8, 124u8, 235u8, 202u8, 68u8, 125u8, 203u8, 246u8, - 109u8, 4u8, 199u8, 14u8, 103u8, 38u8, 67u8, 185u8, 81u8, 67u8, 124u8, - 64u8, 197u8, 45u8, 101u8, 199u8, 73u8, 196u8, 162u8, 36u8, 100u8, - 107u8, + 234u8, 19u8, 104u8, 174u8, 98u8, 159u8, 205u8, 110u8, 240u8, 78u8, + 186u8, 138u8, 236u8, 116u8, 104u8, 215u8, 57u8, 178u8, 166u8, 208u8, + 197u8, 113u8, 101u8, 56u8, 23u8, 56u8, 84u8, 14u8, 173u8, 70u8, 211u8, + 201u8, ], ) } @@ -4477,6 +4737,17 @@ pub mod api { const PALLET: &'static str = "DmpQueue"; const EVENT: &'static str = "OverweightServiced"; } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "The maximum number of downward messages was."] + pub struct MaxMessagesExhausted { + pub message_id: [::core::primitive::u8; 32usize], + } + impl ::subxt::events::StaticEvent for MaxMessagesExhausted { + const PALLET: &'static str = "DmpQueue"; + const EVENT: &'static str = "MaxMessagesExhausted"; + } } pub mod storage { use super::runtime_types; @@ -4667,23 +4938,24 @@ pub mod api { :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] pub struct ClaimRewards { - pub lane_id: runtime_types::bp_messages::LaneId, + pub rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, } pub struct TransactionApi; impl TransactionApi { #[doc = "Claim accumulated rewards."] pub fn claim_rewards( &self, - lane_id: runtime_types::bp_messages::LaneId, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, ) -> ::subxt::tx::StaticTxPayload { ::subxt::tx::StaticTxPayload::new( "BridgeRelayers", "claim_rewards", - ClaimRewards { lane_id }, + ClaimRewards { rewards_account_params }, [ - 119u8, 55u8, 12u8, 215u8, 255u8, 17u8, 1u8, 92u8, 187u8, 154u8, 120u8, - 10u8, 51u8, 16u8, 160u8, 18u8, 194u8, 236u8, 95u8, 173u8, 64u8, 75u8, - 251u8, 68u8, 235u8, 116u8, 69u8, 240u8, 186u8, 153u8, 118u8, 17u8, + 141u8, 52u8, 193u8, 42u8, 145u8, 26u8, 147u8, 35u8, 227u8, 221u8, + 221u8, 188u8, 104u8, 186u8, 123u8, 46u8, 190u8, 236u8, 120u8, 19u8, + 230u8, 219u8, 238u8, 227u8, 75u8, 35u8, 36u8, 177u8, 227u8, 130u8, + 103u8, 128u8, ], ) } @@ -4699,7 +4971,7 @@ pub mod api { #[doc = "Reward has been paid to the relayer."] pub struct RewardPaid { pub relayer: ::sp_core::crypto::AccountId32, - pub lane_id: runtime_types::bp_messages::LaneId, + pub rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, pub reward: ::core::primitive::u128, } impl ::subxt::events::StaticEvent for RewardPaid { @@ -4715,7 +4987,7 @@ pub mod api { pub fn relayer_rewards( &self, _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - _1: impl ::std::borrow::Borrow, + _1: impl ::std::borrow::Borrow, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, ::subxt::storage::address::Yes, @@ -4736,10 +5008,10 @@ pub mod api { ), ], [ - 79u8, 50u8, 107u8, 107u8, 201u8, 181u8, 235u8, 111u8, 185u8, 125u8, - 108u8, 204u8, 163u8, 11u8, 69u8, 236u8, 90u8, 232u8, 9u8, 225u8, 210u8, - 142u8, 175u8, 166u8, 159u8, 74u8, 112u8, 249u8, 16u8, 115u8, 144u8, - 177u8, + 116u8, 81u8, 48u8, 55u8, 199u8, 26u8, 100u8, 7u8, 177u8, 230u8, 132u8, + 248u8, 221u8, 90u8, 33u8, 155u8, 198u8, 216u8, 43u8, 149u8, 92u8, + 100u8, 199u8, 183u8, 150u8, 214u8, 199u8, 222u8, 224u8, 228u8, 238u8, + 108u8, ], ) } @@ -4757,10 +5029,10 @@ pub mod api { "RelayerRewards", Vec::new(), [ - 79u8, 50u8, 107u8, 107u8, 201u8, 181u8, 235u8, 111u8, 185u8, 125u8, - 108u8, 204u8, 163u8, 11u8, 69u8, 236u8, 90u8, 232u8, 9u8, 225u8, 210u8, - 142u8, 175u8, 166u8, 159u8, 74u8, 112u8, 249u8, 16u8, 115u8, 144u8, - 177u8, + 116u8, 81u8, 48u8, 55u8, 199u8, 26u8, 100u8, 7u8, 177u8, 230u8, 132u8, + 248u8, 221u8, 90u8, 33u8, 155u8, 198u8, 216u8, 43u8, 149u8, 92u8, + 100u8, 199u8, 183u8, 150u8, 214u8, 199u8, 222u8, 224u8, 228u8, 238u8, + 108u8, ], ) } @@ -4919,6 +5191,23 @@ pub mod api { } } } + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub type Event = runtime_types::pallet_bridge_grandpa::pallet::Event; + pub mod events { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + #[doc = "Best finalized chain header has been updated to the header with given number and hash."] + pub struct UpdatedBestFinalizedHeader { + pub number: ::core::primitive::u64, + pub hash: ::bp_millau::MillauHash, + } + impl ::subxt::events::StaticEvent for UpdatedBestFinalizedHeader { + const PALLET: &'static str = "BridgeMillauGrandpa"; + const EVENT: &'static str = "UpdatedBestFinalizedHeader"; + } + } pub mod storage { use super::runtime_types; pub struct StorageApi; @@ -5243,23 +5532,6 @@ pub mod api { ], ) } - #[doc = " Max number of authorities at the bridged chain."] - pub fn max_bridged_authorities( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "BridgeMillauGrandpa", - "MaxBridgedAuthorities", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } } } } @@ -5405,9 +5677,7 @@ pub mod api { :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] #[doc = "Messages have been received from the bridged chain."] - pub struct MessagesReceived( - pub ::std::vec::Vec>, - ); + pub struct MessagesReceived (pub :: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) ; impl ::subxt::events::StaticEvent for MessagesReceived { const PALLET: &'static str = "BridgeMillauMessages"; const EVENT: &'static str = "MessagesReceived"; @@ -5584,7 +5854,7 @@ pub mod api { _0: impl ::std::borrow::Borrow, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + runtime_types::bounded_collections::bounded_vec::BoundedVec< ::core::primitive::u8, >, >, @@ -5611,7 +5881,7 @@ pub mod api { &self, ) -> ::subxt::storage::address::StaticStorageAddress< ::subxt::metadata::DecodeStaticType< - runtime_types::sp_core::bounded::bounded_vec::BoundedVec< + runtime_types::bounded_collections::bounded_vec::BoundedVec< ::core::primitive::u8, >, >, @@ -5671,9 +5941,32 @@ pub mod api { } } } - } - pub mod runtime_types { - use super::runtime_types; + } + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } pub mod bp_header_chain { use super::runtime_types; #[derive( @@ -5760,6 +6053,26 @@ pub mod api { pub messages: runtime_types::bp_messages::DeliveredMessages, } } + pub mod bp_relayers { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub enum RewardsAccountOwner { + #[codec(index = 0)] + ThisChain, + #[codec(index = 1)] + BridgedChain, + } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct RewardsAccountParams { + pub lane_id: runtime_types::bp_messages::LaneId, + pub bridged_chain_id: [::core::primitive::u8; 4usize], + pub owner: runtime_types::bp_relayers::RewardsAccountOwner, + } + } pub mod bp_runtime { use super::runtime_types; pub mod messages { @@ -5796,6 +6109,26 @@ pub mod api { Halted, } } + pub mod bridge_runtime_common { + use super::runtime_types; + pub mod messages_xcm_extension { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum XcmBlobMessageDispatchResult { + #[codec(index = 0)] + InvalidPayload, + #[codec(index = 1)] + Dispatched, + #[codec(index = 2)] + NotDispatched, + } + } + } pub mod cumulus_pallet_dmp_queue { use super::runtime_types; pub mod pallet { @@ -5870,6 +6203,9 @@ pub mod api { overweight_index: ::core::primitive::u64, weight_used: ::sp_weights::Weight, }, + #[codec(index = 6)] + #[doc = "The maximum number of downward messages was."] + MaxMessagesExhausted { message_id: [::core::primitive::u8; 32usize] }, } } #[derive( @@ -5899,7 +6235,7 @@ pub mod api { )] #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] pub enum Call { - # [codec (index = 0)] # [doc = "Set the current validation data."] # [doc = ""] # [doc = "This should be invoked exactly once per block. It will panic at the finalization"] # [doc = "phase if the call was not invoked."] # [doc = ""] # [doc = "The dispatch origin for this call must be `Inherent`"] # [doc = ""] # [doc = "As a side effect, this function upgrades the current validation function"] # [doc = "if the appropriate time has come."] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + # [codec (index = 0)] # [doc = "Set the current validation data."] # [doc = ""] # [doc = "This should be invoked exactly once per block. It will panic at the finalization"] # [doc = "phase if the call was not invoked."] # [doc = ""] # [doc = "The dispatch origin for this call must be `Inherent`"] # [doc = ""] # [doc = "As a side effect, this function upgrades the current validation function"] # [doc = "if the appropriate time has come."] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] # [doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] # [doc = "later."] # [doc = ""] # [doc = "The `check_version` parameter sets a boolean flag for whether or not the runtime's spec"] # [doc = "version and name should be verified on upgrade. Since the authorization only has a hash,"] # [doc = "it cannot actually perform the verification."] # [doc = ""] # [doc = "This call requires Root origin."] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] # [doc = "Provide the preimage (runtime binary) `code` for an upgrade that has been authorized."] # [doc = ""] # [doc = "If the authorization required a version check, this call will ensure the spec name"] # [doc = "remains unchanged and that the spec version has increased."] # [doc = ""] # [doc = "Note that this function will not apply the new `code`, but only attempt to schedule the"] # [doc = "upgrade with the Relay Chain."] # [doc = ""] # [doc = "All origins are allowed."] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, @@ -5909,20 +6245,20 @@ pub mod api { #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] pub enum Error { #[codec(index = 0)] - #[doc = "Attempt to upgrade validation function while existing upgrade pending"] + #[doc = "Attempt to upgrade validation function while existing upgrade pending."] OverlappingUpgrades, #[codec(index = 1)] - #[doc = "Polkadot currently prohibits this parachain from upgrading its validation function"] + #[doc = "Polkadot currently prohibits this parachain from upgrading its validation function."] ProhibitedByPolkadot, #[codec(index = 2)] #[doc = "The supplied validation function has compiled into a blob larger than Polkadot is"] - #[doc = "willing to run"] + #[doc = "willing to run."] TooBig, #[codec(index = 3)] - #[doc = "The inherent which supplies the validation data did not run this block"] + #[doc = "The inherent which supplies the validation data did not run this block."] ValidationDataNotAvailable, #[codec(index = 4)] - #[doc = "The inherent which supplies the host configuration did not run this block"] + #[doc = "The inherent which supplies the host configuration did not run this block."] HostConfigurationNotAvailable, #[codec(index = 5)] #[doc = "No validation function upgrade is currently scheduled."] @@ -5983,14 +6319,21 @@ pub mod api { pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), pub ingress_channels: ::std::vec::Vec<( runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_primitives::v2::AbridgedHrmpChannel, + runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, )>, pub egress_channels: ::std::vec::Vec<( runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_primitives::v2::AbridgedHrmpChannel, + runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, )>, } } + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct CodeUpgradeAuthorization { + pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, + } } pub mod cumulus_pallet_xcm { use super::runtime_types; @@ -6257,7 +6600,7 @@ pub mod api { )] pub struct ParachainInherentData { pub validation_data: - runtime_types::polkadot_primitives::v2::PersistedValidationData< + runtime_types::polkadot_primitives::v4::PersistedValidationData< ::subxt::utils::H256, ::core::primitive::u32, >, @@ -6507,9 +6850,8 @@ pub mod api { #[codec(index = 0)] #[doc = "Make some on-chain remark."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(1)`"] - #[doc = "# "] remark { remark: ::std::vec::Vec<::core::primitive::u8> }, #[codec(index = 1)] #[doc = "Set the number of pages in the WebAssembly environment's heap."] @@ -6517,27 +6859,14 @@ pub mod api { #[codec(index = 2)] #[doc = "Set the new runtime code."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code`"] - #[doc = "- 1 call to `can_set_code`: `O(S)` (calls `sp_io::misc::runtime_version` which is"] - #[doc = " expensive)."] - #[doc = "- 1 storage write (codec `O(C)`)."] - #[doc = "- 1 digest item."] - #[doc = "- 1 event."] - #[doc = "The weight of this function is dependent on the runtime, but generally this is very"] - #[doc = "expensive. We will treat this as a full block."] - #[doc = "# "] set_code { code: ::std::vec::Vec<::core::primitive::u8> }, #[codec(index = 3)] #[doc = "Set the new runtime code without doing any checks of the given `code`."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(C)` where `C` length of `code`"] - #[doc = "- 1 storage write (codec `O(C)`)."] - #[doc = "- 1 digest item."] - #[doc = "- 1 event."] - #[doc = "The weight of this function is dependent on the runtime. We will treat this as a full"] - #[doc = "block. # "] set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, #[codec(index = 4)] #[doc = "Set some items of storage."] @@ -6680,57 +7009,33 @@ pub mod api { #[codec(index = 0)] #[doc = "Transfer some liquid free balance to another account."] #[doc = ""] - #[doc = "`transfer` will set the `FreeBalance` of the sender and receiver."] + #[doc = "`transfer_allow_death` will set the `FreeBalance` of the sender and receiver."] #[doc = "If the sender's account is below the existential deposit as a result"] #[doc = "of the transfer, the account will be reaped."] #[doc = ""] #[doc = "The dispatch origin for this call must be `Signed` by the transactor."] - #[doc = ""] - #[doc = "# "] - #[doc = "- Dependent on arguments but not critical, given proper implementations for input config"] - #[doc = " types. See related functions below."] - #[doc = "- It contains a limited number of reads and writes internally and no complex"] - #[doc = " computation."] - #[doc = ""] - #[doc = "Related functions:"] - #[doc = ""] - #[doc = " - `ensure_can_withdraw` is always called internally but has a bounded complexity."] - #[doc = " - Transferring balances to accounts that did not exist before will cause"] - #[doc = " `T::OnNewAccount::on_new_account` to be called."] - #[doc = " - Removing enough funds from an account will trigger `T::DustRemoval::on_unbalanced`."] - #[doc = " - `transfer_keep_alive` works the same way as `transfer`, but has an additional check"] - #[doc = " that the transfer will not kill the origin account."] - #[doc = "---------------------------------"] - #[doc = "- Origin account is already in memory, so no DB operations for them."] - #[doc = "# "] - transfer { + transfer_allow_death { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] value: ::core::primitive::u128, }, #[codec(index = 1)] - #[doc = "Set the balances of a given account."] - #[doc = ""] - #[doc = "This will alter `FreeBalance` and `ReservedBalance` in storage. it will"] - #[doc = "also alter the total issuance of the system (`TotalIssuance`) appropriately."] - #[doc = "If the new free or reserved balance is below the existential deposit,"] - #[doc = "it will reset the account nonce (`frame_system::AccountNonce`)."] + #[doc = "Set the regular balance of a given account; it also takes a reserved balance but this"] + #[doc = "must be the same as the account's current reserved balance."] #[doc = ""] #[doc = "The dispatch origin for this call is `root`."] - set_balance { + #[doc = ""] + #[doc = "WARNING: This call is DEPRECATED! Use `force_set_balance` instead."] + set_balance_deprecated { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] new_free: ::core::primitive::u128, #[codec(compact)] - new_reserved: ::core::primitive::u128, + old_reserved: ::core::primitive::u128, }, #[codec(index = 2)] - #[doc = "Exactly as `transfer`, except the origin must be root and the source account may be"] - #[doc = "specified."] - #[doc = "# "] - #[doc = "- Same as transfer, but additional read and write because the source account is not"] - #[doc = " assumed to be in the overlay."] - #[doc = "# "] + #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] + #[doc = "may be specified."] force_transfer { source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -6738,12 +7043,12 @@ pub mod api { value: ::core::primitive::u128, }, #[codec(index = 3)] - #[doc = "Same as the [`transfer`] call, but with a check that the transfer will not kill the"] - #[doc = "origin account."] + #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] + #[doc = "kill the origin account."] #[doc = ""] - #[doc = "99% of the time you want [`transfer`] instead."] + #[doc = "99% of the time you want [`transfer_allow_death`] instead."] #[doc = ""] - #[doc = "[`transfer`]: struct.Pallet.html#method.transfer"] + #[doc = "[`transfer_allow_death`]: struct.Pallet.html#method.transfer"] transfer_keep_alive { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] @@ -6764,9 +7069,7 @@ pub mod api { #[doc = "- `keep_alive`: A boolean to determine if the `transfer_all` operation should send all"] #[doc = " of the funds the account has, causing the sender account to be killed (false), or"] #[doc = " transfer everything except at least the existential deposit, which will guarantee to"] - #[doc = " keep the sender account alive (true). # "] - #[doc = "- O(1). Just like transfer, but reading the user's transferable balance first."] - #[doc = " #"] + #[doc = " keep the sender account alive (true)."] transfer_all { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, keep_alive: ::core::primitive::bool, @@ -6779,6 +7082,34 @@ pub mod api { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, amount: ::core::primitive::u128, }, + #[codec(index = 6)] + #[doc = "Upgrade a specified account."] + #[doc = ""] + #[doc = "- `origin`: Must be `Signed`."] + #[doc = "- `who`: The account to be upgraded."] + #[doc = ""] + #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] + #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] + #[doc = "possibililty of churn)."] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 7)] + #[doc = "Alias for `transfer_allow_death`, provided only for name-wise compatibility."] + #[doc = ""] + #[doc = "WARNING: DEPRECATED! Will be released in approximately 3 months."] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 8)] + #[doc = "Set the regular balance of a given account."] + #[doc = ""] + #[doc = "The dispatch origin for this call is `root`."] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, } #[derive( :: subxt :: ext :: codec :: Decode, @@ -6789,29 +7120,35 @@ pub mod api { #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] pub enum Error { #[codec(index = 0)] - #[doc = "Vesting balance too high to send value"] + #[doc = "Vesting balance too high to send value."] VestingBalance, #[codec(index = 1)] - #[doc = "Account liquidity restrictions prevent withdrawal"] + #[doc = "Account liquidity restrictions prevent withdrawal."] LiquidityRestrictions, #[codec(index = 2)] #[doc = "Balance too low to send value."] InsufficientBalance, #[codec(index = 3)] - #[doc = "Value too low to create account due to existential deposit"] + #[doc = "Value too low to create account due to existential deposit."] ExistentialDeposit, #[codec(index = 4)] - #[doc = "Transfer/payment would kill account"] - KeepAlive, + #[doc = "Transfer/payment would kill account."] + Expendability, #[codec(index = 5)] - #[doc = "A vesting schedule already exists for this account"] + #[doc = "A vesting schedule already exists for this account."] ExistingVestingSchedule, #[codec(index = 6)] - #[doc = "Beneficiary account must pre-exist"] + #[doc = "Beneficiary account must pre-exist."] DeadAccount, #[codec(index = 7)] - #[doc = "Number of named reserves exceed MaxReserves"] + #[doc = "Number of named reserves exceed `MaxReserves`."] TooManyReserves, + #[codec(index = 8)] + #[doc = "Number of holds exceed `MaxHolds`."] + TooManyHolds, + #[codec(index = 9)] + #[doc = "Number of freezes exceed `MaxFreezes`."] + TooManyFreezes, } #[derive( :: subxt :: ext :: codec :: Decode, @@ -6846,7 +7183,6 @@ pub mod api { BalanceSet { who: ::sp_core::crypto::AccountId32, free: ::core::primitive::u128, - reserved: ::core::primitive::u128, }, #[codec(index = 4)] #[doc = "Some balance was reserved (moved from free to reserved)."] @@ -6882,42 +7218,102 @@ pub mod api { #[codec(index = 9)] #[doc = "Some amount was removed from the account (e.g. for misbehavior)."] Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + #[doc = "Some amount was minted into an account."] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + #[doc = "Some amount was burned from an account."] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + #[doc = "Some amount was suspended from an account (it can be restored later)."] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + #[doc = "Some amount was restored into an account."] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + #[doc = "An account was upgraded."] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + #[doc = "Total issuance was increased by `amount`, creating a credit to be balanced."] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + #[doc = "Total issuance was decreased by `amount`, creating a debt to be balanced."] + Rescinded { amount: ::core::primitive::u128 }, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub misc_frozen: _0, - pub fee_frozen: _0, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::Reasons, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, + pub mod types { + use super::runtime_types; + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: subxt :: ext :: codec :: CompactAs, + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } } } pub mod pallet_bridge_grandpa { @@ -7023,6 +7419,21 @@ pub mod api { #[doc = "Error generated by the `OwnedBridgeModule` trait."] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } + #[derive( + :: subxt :: ext :: codec :: Decode, + :: subxt :: ext :: codec :: Encode, + Clone, + Debug, + )] + #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + pub enum Event { + #[codec(index = 0)] + #[doc = "Best finalized chain header has been updated to the header with given number and hash."] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u64, + hash: ::bp_millau::MillauHash, + }, + } } pub mod storage_types { use super::runtime_types; @@ -7033,7 +7444,7 @@ pub mod api { Debug, )] pub struct StoredAuthoritySet { - pub authorities: runtime_types::sp_core::bounded::bounded_vec::BoundedVec<( + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( runtime_types::sp_consensus_grandpa::app::Public, ::core::primitive::u64, )>, @@ -7118,24 +7529,7 @@ pub mod api { )] #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] pub enum Event { - #[codec(index = 0)] - #[doc = "Message has been accepted and is waiting to be delivered."] - MessageAccepted { - lane_id: runtime_types::bp_messages::LaneId, - nonce: ::core::primitive::u64, - }, - #[codec(index = 1)] - #[doc = "Messages have been received from the bridged chain."] - MessagesReceived( - ::std::vec::Vec>, - ), - #[codec(index = 2)] - #[doc = "Messages in the inclusive range have been delivered to the bridged chain."] - MessagesDelivered { - lane_id: runtime_types::bp_messages::LaneId, - messages: runtime_types::bp_messages::DeliveredMessages, - }, - } + # [codec (index = 0)] # [doc = "Message has been accepted and is waiting to be delivered."] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] # [doc = "Messages have been received from the bridged chain."] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] # [doc = "Messages in the inclusive range have been delivered to the bridged chain."] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } } } pub mod pallet_bridge_relayers { @@ -7152,7 +7546,9 @@ pub mod api { pub enum Call { #[codec(index = 0)] #[doc = "Claim accumulated rewards."] - claim_rewards { lane_id: runtime_types::bp_messages::LaneId }, + claim_rewards { + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + }, } #[derive( :: subxt :: ext :: codec :: Decode, @@ -7181,7 +7577,7 @@ pub mod api { #[doc = "Reward has been paid to the relayer."] RewardPaid { relayer: ::sp_core::crypto::AccountId32, - lane_id: runtime_types::bp_messages::LaneId, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, reward: ::core::primitive::u128, }, } @@ -7204,12 +7600,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- Limited storage reads."] - #[doc = "- One DB write (event)."] - #[doc = "- Weight of derivative `call` execution + 10,000."] - #[doc = "# "] sudo { call: ::std::boxed::Box, @@ -7221,10 +7613,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- The weight of this call is defined by the caller."] - #[doc = "# "] sudo_unchecked_weight { call: ::std::boxed::Box, @@ -7236,11 +7626,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- Limited storage reads."] - #[doc = "- One DB change."] - #[doc = "# "] set_key { new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, }, @@ -7250,12 +7637,8 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be _Signed_."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- O(1)."] - #[doc = "- Limited storage reads."] - #[doc = "- One DB write (event)."] - #[doc = "- Weight of derivative `call` execution + 10,000."] - #[doc = "# "] sudo_as { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, call: @@ -7325,12 +7708,11 @@ pub mod api { #[doc = ""] #[doc = "The dispatch origin for this call must be `Inherent`."] #[doc = ""] - #[doc = "# "] + #[doc = "## Complexity"] #[doc = "- `O(1)` (Note that implementations of `OnTimestampSet` must also be `O(1)`)"] #[doc = "- 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in"] #[doc = " `on_finalize`)"] #[doc = "- 1 event handler `on_timestamp_set`. Must be `O(1)`."] - #[doc = "# "] set { #[codec(compact)] now: ::core::primitive::u64, @@ -7907,7 +8289,7 @@ pub mod api { } pub mod polkadot_primitives { use super::runtime_types; - pub mod v2 { + pub mod v4 { use super::runtime_types; #[derive( :: subxt :: ext :: codec :: Decode, @@ -7969,6 +8351,14 @@ pub mod api { #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] + pub struct BridgeRejectObsoleteHeadersAndMessages; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] + pub struct DummyBridgeRefundMillauMessages; + #[derive( + :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, + )] pub struct Runtime; #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, @@ -8007,7 +8397,7 @@ pub mod api { System(runtime_types::frame_system::pallet::Event), #[codec(index = 2)] Sudo(runtime_types::pallet_sudo::pallet::Event), - #[codec(index = 4)] + #[codec(index = 3)] TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), #[codec(index = 20)] ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), @@ -8023,6 +8413,8 @@ pub mod api { DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), #[codec(index = 54)] BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 55)] + BridgeMillauGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), #[codec(index = 56)] BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Event), } @@ -8052,32 +8444,9 @@ pub mod api { DivisionByZero, } } - pub mod sp_core { + pub mod sp_consensus_grandpa { use super::runtime_types; - pub mod bounded { - use super::runtime_types; - pub mod bounded_vec { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod ecdsa { + pub mod app { use super::runtime_types; #[derive( :: subxt :: ext :: codec :: Decode, @@ -8085,26 +8454,29 @@ pub mod api { Clone, Debug, )] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; + pub struct Public(pub runtime_types::sp_core::ed25519::Public); #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] - pub struct Public(pub [::core::primitive::u8; 32usize]); + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_core { + use super::runtime_types; + pub mod ecdsa { + use super::runtime_types; #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] - pub struct Signature(pub [::core::primitive::u8; 64usize]); + pub struct Signature(pub [::core::primitive::u8; 65usize]); } - pub mod sr25519 { + pub mod ed25519 { use super::runtime_types; #[derive( :: subxt :: ext :: codec :: Decode, @@ -8112,27 +8484,24 @@ pub mod api { Clone, Debug, )] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; + pub struct Public(pub [::core::primitive::u8; 32usize]); #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + pub struct Signature(pub [::core::primitive::u8; 64usize]); } } pub mod sp_runtime { @@ -8237,9 +8606,9 @@ pub mod api { )] pub enum TokenError { #[codec(index = 0)] - NoFunds, + FundsUnavailable, #[codec(index = 1)] - WouldDie, + OnlyProvider, #[codec(index = 2)] BelowMinimum, #[codec(index = 3)] @@ -8250,6 +8619,10 @@ pub mod api { Frozen, #[codec(index = 6)] Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, } #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, @@ -8352,7 +8725,7 @@ pub mod api { GeneralIndex(#[codec(compact)] ::core::primitive::u128), #[codec(index = 6)] GeneralKey( - runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< ::core::primitive::u8, >, ), @@ -8627,7 +9000,7 @@ pub mod api { Unit, #[codec(index = 1)] Named( - runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< ::core::primitive::u8, >, ), @@ -8840,7 +9213,7 @@ pub mod api { Any, #[codec(index = 1)] Named( - runtime_types::sp_core::bounded::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< ::core::primitive::u8, >, ), @@ -9007,7 +9380,10 @@ pub mod api { #[codec(index = 5)] GeneralIndex(#[codec(compact)] ::core::primitive::u128), #[codec(index = 6)] - GeneralKey([::core::primitive::u8; 32usize]), + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, #[codec(index = 7)] OnlyChild, #[codec(index = 8)] @@ -9580,9 +9956,17 @@ pub mod api { #[codec(index = 0)] Success, #[codec(index = 1)] - Error(::std::vec::Vec<::core::primitive::u8>), + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), #[codec(index = 2)] - TruncatedError(::std::vec::Vec<::core::primitive::u8>), + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), } #[derive( :: subxt :: ext :: codec :: Decode, @@ -9593,8 +9977,12 @@ pub mod api { pub struct PalletInfo { #[codec(compact)] pub index: ::core::primitive::u32, - pub name: ::std::vec::Vec<::core::primitive::u8>, - pub module_name: ::std::vec::Vec<::core::primitive::u8>, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, #[codec(compact)] pub major: ::core::primitive::u32, #[codec(compact)] @@ -9635,7 +10023,11 @@ pub mod api { #[codec(index = 3)] Version(::core::primitive::u32), #[codec(index = 4)] - PalletsInfo(runtime_types::xcm::v3::VecPalletInfo), + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), #[codec(index = 5)] DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), } @@ -9645,13 +10037,6 @@ pub mod api { Clone, Debug, )] - pub struct VecPalletInfo(pub ::std::vec::Vec); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] pub enum WeightLimit { #[codec(index = 0)] Unlimited, @@ -9670,18 +10055,18 @@ pub mod api { :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] pub enum VersionedMultiAssets { - #[codec(index = 0)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] V3(runtime_types::xcm::v3::multiasset::MultiAssets), } #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, )] pub enum VersionedMultiLocation { - #[codec(index = 0)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] V3(runtime_types::xcm::v3::multilocation::MultiLocation), } #[derive( @@ -9739,11 +10124,6 @@ pub mod api { pub fn sudo(&self) -> sudo::storage::StorageApi { sudo::storage::StorageApi } - pub fn randomness_collective_flip( - &self, - ) -> randomness_collective_flip::storage::StorageApi { - randomness_collective_flip::storage::StorageApi - } pub fn transaction_payment(&self) -> transaction_payment::storage::StorageApi { transaction_payment::storage::StorageApi } @@ -9818,9 +10198,9 @@ pub mod api { let runtime_metadata_hash = client.metadata().metadata_hash(&PALLETS); if runtime_metadata_hash != [ - 29u8, 217u8, 238u8, 58u8, 9u8, 201u8, 174u8, 206u8, 19u8, 133u8, 133u8, 32u8, - 139u8, 251u8, 132u8, 7u8, 135u8, 118u8, 231u8, 231u8, 9u8, 150u8, 246u8, 171u8, - 190u8, 93u8, 114u8, 63u8, 86u8, 200u8, 148u8, 126u8, + 244u8, 26u8, 245u8, 96u8, 241u8, 56u8, 22u8, 163u8, 219u8, 209u8, 103u8, 161u8, + 138u8, 242u8, 33u8, 114u8, 162u8, 107u8, 1u8, 216u8, 115u8, 116u8, 164u8, 126u8, + 81u8, 51u8, 88u8, 36u8, 180u8, 113u8, 18u8, 58u8, ] { Err(::subxt::error::MetadataError::IncompatibleMetadata) } else { diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 6a381c4e97717..27af7d7d77f74 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -739,12 +739,12 @@ impl Client { async fn jsonrpsee_execute(&self, make_jsonrpsee_future: MF) -> Result where MF: FnOnce(Arc) -> F + Send + 'static, - F: Future> + Send, + F: Future> + Send + 'static, T: Send + 'static, { let data = self.data.read().await; let client = data.client.clone(); - data.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await? + data.tokio.spawn(make_jsonrpsee_future(client)).await? } /// Returns `true` if version guard can be started. From 1c1a27a160a790a1b6c3f8c75dbd0a252c7e4284 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 24 Mar 2023 15:50:53 +0100 Subject: [PATCH 1001/1210] Try check-rustdoc pipeline (#1782) * Try check-rustdoc pipeline * another try * another try without `--all-features` * fixed cargo doc issues * exclude relay-rialto-parachain-client from cargo doc --------- Co-authored-by: Svyatoslav Nikolsky --- bin/rialto-parachain/runtime/src/lib.rs | 2 +- bin/runtime-common/src/messages_xcm_extension.rs | 12 ++++++------ primitives/chain-millau/src/lib.rs | 6 +++--- primitives/chain-rialto/src/lib.rs | 6 +++--- primitives/polkadot-core/src/lib.rs | 6 +++--- relays/lib-substrate-relay/src/messages_source.rs | 2 +- relays/lib-substrate-relay/src/messages_target.rs | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 4e4fcffcd0051..b5419e2c25e88 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -16,7 +16,7 @@ //! The Rialto parachain runtime. This can be compiled with `#[no_std]`, ready for Wasm. //! -//! Originally a copy of runtime from https://github.com/substrate-developer-hub/substrate-parachain-template. +//! Originally a copy of runtime from . #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index d4bf2bc1bed6d..3d802d12fad64 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -15,11 +15,11 @@ // along with Parity Bridges Common. If not, see . //! Module provides utilities for easier XCM handling, e.g: -//! [`XcmExecutor`] -> [`MessageSender`] -> +//! `XcmExecutor` -> `MessageSender` -> `OutboundMessageQueue` //! | -//! +//! `Relayer` //! | -//! [`XcmRouter`] <- [`MessageDispatch`] <- +//! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue` use bp_messages::{ source_chain::MessagesBridge, @@ -136,7 +136,7 @@ pub trait XcmBlobHauler { /// Runtime message sender adapter. type MessageSender: MessagesBridge; - /// Runtime message sender origin, which is used by [`MessageSender`]. + /// Runtime message sender origin, which is used by [`Self::MessageSender`]. type MessageSenderOrigin; /// Our location within the Consensus Universe. fn message_sender_origin() -> Self::MessageSenderOrigin; @@ -145,8 +145,8 @@ pub trait XcmBlobHauler { fn xcm_lane() -> LaneId; } -/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`MessageSender`] and makes sure that -/// XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed. +/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`XcmBlobHauler::MessageSender`] and +/// makes sure that XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed. pub struct XcmBlobHaulerAdapter(sp_std::marker::PhantomData); impl> HaulBlob for XcmBlobHaulerAdapter diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 81ed54362631b..b7f67ca07e288 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -86,12 +86,12 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 5; /// Reasonable number of headers in the `votes_ancestries` on Millau chain. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; /// Approximate average header size in `votes_ancestries` field of justification on Millau chain. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; /// Approximate maximal header size on Millau chain. @@ -100,7 +100,7 @@ pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; /// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also /// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT .saturating_mul(3) .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index a1c4a7267a7bd..01349f131be70 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -75,12 +75,12 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 5; /// Reasonable number of headers in the `votes_ancestries` on Rialto chain. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; /// Approximate average header size in `votes_ancestries` field of justification on Rialto chain. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; /// Approximate maximal header size on Rialto chain. @@ -89,7 +89,7 @@ pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; /// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also /// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT .saturating_mul(3) .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index eae2d49a6fdbe..3774d283fc473 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -54,7 +54,7 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256; /// Reasonable number of headers in the `votes_ancestries` on Polkadot-like chains. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. /// /// This value comes from recent (February, 2023) Kusama and Polkadot headers. There are no /// justifications with any additional headers in votes ancestry, so reasonable headers may @@ -65,7 +65,7 @@ pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; /// Approximate average header size in `votes_ancestries` field of justification on Polkadot-like /// chains. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. /// /// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but some /// non-mandatory headers has size `40kb` (they contain the BABE epoch descriptor with all @@ -75,7 +75,7 @@ pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024; /// Approximate maximal header size on Polkadot-like chains. /// -/// See [`bp_header_chain::ChainWithGrandpa`] for more details. +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. /// /// This value comes from recent (February, 2023) Kusama headers. Maximal header is a mandatory /// header. In its SCALE-encoded form it is `80348` bytes. Let's have some reserve here. diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index a151af8ee8277..de795beb7870c 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -16,7 +16,7 @@ //! Substrate client as Substrate messages source. The chain we connect to should have //! runtime that implements `HeaderApi` to allow bridging with -//! chain. +//! `` chain. use crate::{ messages_lane::{ diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 7b0d9d63fb786..68b68b1993647 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -16,7 +16,7 @@ //! Substrate client as Substrate messages target. The chain we connect to should have //! runtime that implements `HeaderApi` to allow bridging with -//! chain. +//! `` chain. use crate::{ messages_lane::{ From f6c6169abd530a9f55f220461d675b340c624a04 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 02:05:58 +0000 Subject: [PATCH 1002/1210] Bump async-trait from 0.1.67 to 0.1.68 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.67 to 0.1.68. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.67...0.1.68) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index d683c131b6e4e..80df2311bc970 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.67" +async-trait = "0.1.68" futures = "0.3.27" log = "0.4.17" relay-utils = { path = "../utils" } From 2f2f11a737c883978da5921c2992720f8934ba2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 02:03:06 +0000 Subject: [PATCH 1003/1210] Bump clap from 4.1.11 to 4.1.13 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.11 to 4.1.13. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.1.11...v4.1.13) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 063fedc5e64dd..cfe6e921f4b07 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.11", features = ["derive"] } +clap = { version = "4.1.13", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.94" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 84e804f484e25..c60bad8386a96 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.1.11", features = ["derive"] } +clap = { version = "4.1.13", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 8658dd95ec5e6..859a62f22abbb 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.11", features = ["derive"] } +clap = { version = "4.1.13", features = ["derive"] } serde_json = "1.0.94" # Bridge dependencies From 2bf615f828212ce4cc1d438a27da382781054888 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Mar 2023 11:20:32 +0300 Subject: [PATCH 1004/1210] Rust cargo doc for all features (#1995) * run rustfix rustdoc in grandpa pallet benchmarks * enable rustdoc for all features * fix rialto parachain runtime compilation --- bin/rialto-parachain/runtime/Cargo.toml | 4 +++- bin/rialto/node/Cargo.toml | 1 + modules/grandpa/src/benchmarking.rs | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index ed193b4e68157..0018c8f3905ae 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -83,10 +83,12 @@ runtime-benchmarks = [ 'sp-runtime/runtime-benchmarks', 'frame-benchmarking', 'frame-support/runtime-benchmarks', - 'frame-system-benchmarking', + 'frame-system-benchmarking/runtime-benchmarks', 'frame-system/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', 'pallet-timestamp/runtime-benchmarks', + 'pallet-xcm/runtime-benchmarks', + 'xcm-builder/runtime-benchmarks', ] std = [ "bp-messages/std", diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 859a62f22abbb..bc8841c4f8795 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -45,5 +45,6 @@ frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", bran [features] default = [] runtime-benchmarks = [ + "polkadot-service/runtime-benchmarks", "rialto-runtime/runtime-benchmarks", ] diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 5b9faea2a9965..78c7fc362a281 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -30,8 +30,8 @@ //! //! Consider the following: //! -//! / [B'] <- [C'] -//! [A] <- [B] <- [C] +//! / B <- C' +//! A <- B <- C //! //! The common ancestor of both forks is block A, so this is what GRANDPA will finalize. In order to //! verify this we will have vote ancestries of `[B, C, B', C']` and pre-commits `[C, C']`. From 4be1e84178efc1ae1ce33b1035bca07130aa2c89 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 27 Mar 2023 14:33:12 +0300 Subject: [PATCH 1005/1210] Run benchmarks for mock runtimes (#1996) * run benchmarks for pallet-bridge-grandpa mock runtime * run benchmarks for pallet-bridge-relayers mock runtime * run benchmarks for pallet-bridge-parachains mock runtime * run benchmarks for pallet-bridge-messages mock runtime * test benchmarks on mockj runtimes from CI * clippy and spelling --- modules/grandpa/src/benchmarking.rs | 2 ++ modules/grandpa/src/mock.rs | 9 ++++- modules/messages/Cargo.toml | 4 +-- modules/messages/src/benchmarking.rs | 4 ++- modules/messages/src/mock.rs | 50 +++++++++++++++++++++++--- modules/parachains/src/benchmarking.rs | 4 ++- modules/parachains/src/lib.rs | 10 +++--- modules/parachains/src/mock.rs | 39 +++++++++++++++++++- modules/relayers/src/benchmarking.rs | 2 ++ modules/relayers/src/mock.rs | 22 ++++++++++-- 10 files changed, 129 insertions(+), 17 deletions(-) diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 78c7fc362a281..aa222d6e4de6f 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -136,4 +136,6 @@ benchmarks_instance_pallet! { // check that the header#0 has been pruned assert!(!>::contains_key(genesis_header.hash())); } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index b10f5d86c3de2..2220ba3f129f5 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -131,10 +131,17 @@ impl ChainWithGrandpa for TestBridgedChain { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; } +/// Return test externalities to use in tests. +pub fn new_test_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::new(Default::default()) +} + +/// Return test within default test externalities context. pub fn run_test(test: impl FnOnce() -> T) -> T { - sp_io::TestExternalities::new(Default::default()).execute_with(test) + new_test_ext().execute_with(test) } +/// Return test header with given number. pub fn test_header(num: TestNumber) -> TestHeader { // We wrap the call to avoid explicit type annotations in our tests bp_test_utils::test_header(num) diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index afa8b92b22827..4f1e04eecc278 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -27,9 +27,9 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } bp-test-utils = { path = "../../primitives/test-utils" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] default = ["std"] diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index bc9c1f752574b..aab8855a729a8 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -37,7 +37,7 @@ use sp_std::{ops::RangeInclusive, prelude::*}; const SEED: u32 = 0; /// Pallet we're benchmarking here. -pub struct Pallet, I: 'static>(crate::Pallet); +pub struct Pallet, I: 'static = ()>(crate::Pallet); /// Benchmark-specific message proof parameters. #[derive(Debug)] @@ -437,6 +437,8 @@ benchmarks_instance_pallet! { ); assert!(T::is_message_successfully_dispatched(21)); } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } fn send_regular_message, I: 'static>() { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 807721ba86674..02940f369e25c 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -170,6 +170,44 @@ impl Config for TestRuntime { type BridgedChainId = TestBridgedChainId; } +#[cfg(feature = "runtime-benchmarks")] +impl crate::benchmarking::Config<()> for TestRuntime { + fn bench_lane_id() -> LaneId { + TEST_LANE_ID + } + + fn prepare_message_proof( + params: crate::benchmarking::MessageProofParams, + ) -> (TestMessagesProof, Weight) { + // in mock run we only care about benchmarks correctness, not the benchmark results + // => ignore size related arguments + let (messages, total_dispatch_weight) = + params.message_nonces.into_iter().map(|n| message(n, REGULAR_PAYLOAD)).fold( + (Vec::new(), Weight::zero()), + |(mut messages, total_dispatch_weight), message| { + let weight = REGULAR_PAYLOAD.declared_weight; + messages.push(message); + (messages, total_dispatch_weight.saturating_add(weight)) + }, + ); + let mut proof: TestMessagesProof = Ok(messages).into(); + proof.result.as_mut().unwrap().get_mut(0).unwrap().1.lane_state = params.outbound_lane_data; + (proof, total_dispatch_weight) + } + + fn prepare_message_delivery_proof( + params: crate::benchmarking::MessageDeliveryProofParams, + ) -> TestMessagesDeliveryProof { + // in mock run we only care about benchmarks correctness, not the benchmark results + // => ignore size related arguments + TestMessagesDeliveryProof(Ok((params.lane, params.inbound_lane_data))) + } + + fn is_relayer_rewarded(_relayer: &AccountId) -> bool { + true + } +} + impl Size for TestPayload { fn size(&self) -> u32 { 16 + self.extra.len() as u32 @@ -439,12 +477,16 @@ pub fn unrewarded_relayer( UnrewardedRelayer { relayer, messages: DeliveredMessages { begin, end } } } -/// Run pallet test. -pub fn run_test(test: impl FnOnce() -> T) -> T { +/// Return test externalities to use in tests. +pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(ENDOWED_ACCOUNT, 1_000_000)] } .assimilate_storage(&mut t) .unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(test) + sp_io::TestExternalities::new(t) +} + +/// Run pallet test. +pub fn run_test(test: impl FnOnce() -> T) -> T { + new_test_ext().execute_with(test) } diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index 83cfba0b8c6b0..59c4642cde999 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -28,7 +28,7 @@ use frame_system::RawOrigin; use sp_std::prelude::*; /// Pallet we're benchmarking here. -pub struct Pallet, I: 'static>(crate::Pallet); +pub struct Pallet, I: 'static = ()>(crate::Pallet); /// Trait that must be implemented by runtime to benchmark the parachains finality pallet. pub trait Config: crate::Config { @@ -111,4 +111,6 @@ benchmarks_instance_pallet! { assert!(crate::Pallet::::best_parachain_head(parachain).is_some()); } } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index e72e2aec8c202..8fe6c4e938391 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -689,7 +689,7 @@ pub fn initialize_for_benchmarks, I: 'static, PC: Parachain::WeightInfo; type DbWeight = ::DbWeight; - fn initialize(state_root: RelayBlockHash) { + pub(crate) fn initialize(state_root: RelayBlockHash) -> RelayBlockHash { pallet_bridge_grandpa::Pallet::::initialize( RuntimeOrigin::root(), bp_header_chain::InitializationData { @@ -738,6 +738,8 @@ mod tests { System::::set_block_number(1); System::::reset_events(); + + test_relay_header(0, state_root).hash() } fn proceed(num: RelayBlockNumber, state_root: RelayBlockHash) -> ParaHash { @@ -759,7 +761,7 @@ mod tests { hash } - fn prepare_parachain_heads_proof( + pub(crate) fn prepare_parachain_heads_proof( heads: Vec<(u32, ParaHead)>, ) -> (RelayBlockHash, ParaHeadsProof, Vec<(ParaId, ParaHash)>) { let mut parachains = Vec::with_capacity(heads.len()); @@ -795,7 +797,7 @@ mod tests { } } - fn head_data(parachain: u32, head_number: u32) -> ParaHead { + pub(crate) fn head_data(parachain: u32, head_number: u32) -> ParaHead { ParaHead( RegularParachainHeader::new( head_number as _, diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index c19ce98eba2fe..90e6d7c558e49 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -228,6 +228,36 @@ impl pallet_bridge_parachains::Config for TestRuntime { type MaxParaHeadDataSize = ConstU32; } +#[cfg(feature = "runtime-benchmarks")] +impl pallet_bridge_parachains::benchmarking::Config<()> for TestRuntime { + fn parachains() -> Vec { + vec![ + ParaId(Parachain1::PARACHAIN_ID), + ParaId(Parachain2::PARACHAIN_ID), + ParaId(Parachain3::PARACHAIN_ID), + ] + } + + fn prepare_parachain_heads_proof( + parachains: &[ParaId], + _parachain_head_size: u32, + _proof_size: bp_runtime::StorageProofSize, + ) -> ( + crate::RelayBlockNumber, + crate::RelayBlockHash, + bp_polkadot_core::parachains::ParaHeadsProof, + Vec<(ParaId, bp_polkadot_core::parachains::ParaHash)>, + ) { + // in mock run we only care about benchmarks correctness, not the benchmark results + // => ignore size related arguments + let (state_root, proof, parachains) = crate::tests::prepare_parachain_heads_proof( + parachains.iter().map(|p| (p.0, crate::tests::head_data(p.0, 1))).collect(), + ); + let relay_genesis_hash = crate::tests::initialize(state_root); + (0, relay_genesis_hash, proof, parachains) + } +} + #[derive(Debug)] pub struct TestBridgedChain; @@ -290,14 +320,21 @@ impl ChainWithGrandpa for OtherBridgedChain { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; } +/// Return test externalities to use in tests. +pub fn new_test_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::new(Default::default()) +} + +/// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { - sp_io::TestExternalities::new(Default::default()).execute_with(|| { + new_test_ext().execute_with(|| { System::set_block_number(1); System::reset_events(); test() }) } +/// Return test relay chain header with given number. pub fn test_relay_header( num: crate::RelayBlockNumber, state_root: crate::RelayBlockHash, diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index 7dcf77eb958ea..a762a5693c26e 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -54,4 +54,6 @@ benchmarks! { // payment logic, so we assume that if call has succeeded, the procedure has // also completed successfully } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 5e97e81ae3344..fe8c586eecc59 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -99,6 +99,18 @@ impl pallet_bridge_relayers::Config for TestRuntime { type WeightInfo = (); } +#[cfg(feature = "runtime-benchmarks")] +impl pallet_bridge_relayers::benchmarking::Config for TestRuntime { + fn prepare_environment(account_params: RewardsAccountParams, reward: Balance) { + use frame_support::traits::fungible::Mutate; + let rewards_account = + bp_relayers::PayRewardFromAccount::::rewards_account( + account_params, + ); + Balances::mint_into(&rewards_account, reward).unwrap(); + } +} + /// Message lane that we're using in tests. pub const TEST_REWARDS_ACCOUNT_PARAMS: RewardsAccountParams = RewardsAccountParams::new(LaneId([0, 0, 0, 0]), *b"test", RewardsAccountOwner::ThisChain); @@ -127,9 +139,13 @@ impl PaymentProcedure for TestPaymentProcedure { } } +/// Return test externalities to use in tests. +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + sp_io::TestExternalities::new(t) +} + /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(test) + new_test_ext().execute_with(test) } From f2126758d21f9c67158f065001d92a673da9aec0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Mar 2023 13:45:04 +0300 Subject: [PATCH 1006/1210] MaxRequests -> MaxFreeMandatoryHeadersPerBlock in pallet-bridge-grandpa (#1997) * MaxRequests -> MaxFreeMandatoryHeadersPerBlock in pallet-bridge-grandpa * fix comment * fix comment * fix comment --- bin/millau/runtime/src/lib.rs | 8 +- bin/rialto-parachain/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/lib.rs | 6 +- bin/runtime-common/src/integrity.rs | 6 +- bin/runtime-common/src/mock.rs | 2 +- modules/grandpa/src/lib.rs | 190 +++++++++++++++++------- modules/grandpa/src/mock.rs | 11 +- modules/parachains/src/mock.rs | 4 +- 8 files changed, 152 insertions(+), 81 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b0c6b2875fe94..deff859a81641 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -399,11 +399,7 @@ pub type RialtoGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_rialto::Rialto; - // This is a pretty unscientific cap. - // - // Note that once this is hit the pallet will essentially throttle incoming requests down to one - // call per block. - type MaxRequests = ConstU32<50>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; type HeadersToKeep = ConstU32<{ bp_rialto::DAYS }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } @@ -412,7 +408,7 @@ pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; impl pallet_bridge_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_westend::Westend; - type MaxRequests = ConstU32<50>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; type HeadersToKeep = ConstU32<{ bp_westend::DAYS }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index b5419e2c25e88..cd4e256f4203e 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -540,11 +540,7 @@ pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_millau::Millau; - /// This is a pretty unscientific cap. - /// - /// Note that once this is hit the pallet will essentially throttle incoming requests down to - /// one call per block. - type MaxRequests = ConstU32<50>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; type HeadersToKeep = ConstU32<{ bp_millau::DAYS as u32 }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 1a6f0f1e540c5..aeb0a3a7c5749 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -396,11 +396,7 @@ pub type MillauGrandpaInstance = (); impl pallet_bridge_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; type BridgedChain = bp_millau::Millau; - /// This is a pretty unscientific cap. - /// - /// Note that once this is hit the pallet will essentially throttle incoming requests down to - /// one call per block. - type MaxRequests = ConstU32<50>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; type HeadersToKeep = ConstU32<{ bp_millau::DAYS as u32 }>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 96716fe851cb2..5820dd99b91ca 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -178,9 +178,9 @@ where GI: 'static, { assert!( - R::MaxRequests::get() > 0, - "MaxRequests ({}) must be larger than zero", - R::MaxRequests::get(), + R::HeadersToKeep::get() > 0, + "HeadersToKeep ({}) must be larger than zero", + R::HeadersToKeep::get(), ); } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index ac6cf122b0f1d..c4c7c2fa8ac92 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -196,7 +196,7 @@ impl pallet_transaction_payment::Config for TestRuntime { impl pallet_bridge_grandpa::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type BridgedChain = BridgedUnderlyingChain; - type MaxRequests = ConstU32<50>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; type HeadersToKeep = ConstU32<8>; type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 2d81f3106fc9d..df51aa1eb7ed6 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -103,14 +103,17 @@ pub mod pallet { /// The chain we are bridging to here. type BridgedChain: ChainWithGrandpa; - /// The upper bound on the number of requests allowed by the pallet. + /// Maximal number of "free" mandatory header transactions per block. /// - /// A request refers to an action which writes a header to storage. - /// - /// Once this bound is reached the pallet will not allow any dispatchables to be called - /// until the request count has decreased. + /// To be able to track the bridged chain, the pallet requires all headers that are + /// changing GRANDPA authorities set at the bridged chain (we call them mandatory). + /// So it is a common good deed to submit mandatory headers to the pallet. However, if the + /// bridged chain gets compromised, its validators may generate as many mandatory headers + /// as they want. And they may fill the whole block (at this chain) for free. This constants + /// limits number of calls that we may refund in a single block. All calls above this + /// limit are accepted, but are not refunded. #[pallet::constant] - type MaxRequests: Get; + type MaxFreeMandatoryHeadersPerBlock: Get; /// Maximal number of finalized headers to keep in the storage. /// @@ -131,10 +134,13 @@ pub mod pallet { #[pallet::hooks] impl, I: 'static> Hooks> for Pallet { - fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { - >::mutate(|count| *count = count.saturating_sub(1)); + fn on_initialize(_n: BlockNumberFor) -> Weight { + FreeMandatoryHeadersRemaining::::put(T::MaxFreeMandatoryHeadersPerBlock::get()); + Weight::zero() + } - T::DbWeight::get().reads_writes(1, 1) + fn on_finalize(_n: BlockNumberFor) { + FreeMandatoryHeadersRemaining::::kill(); } } @@ -166,8 +172,6 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; - ensure!(Self::request_count() < T::MaxRequests::get(), >::TooManyRequests); - let (hash, number) = (finality_target.hash(), *finality_target.number()); log::trace!( target: LOG_TARGET, @@ -185,9 +189,16 @@ pub mod pallet { let is_authorities_change_enacted = try_enact_authority_change::(&finality_target, set_id)?; let may_refund_call_fee = is_authorities_change_enacted && + // if we have seen too many mandatory headers in this block, we don't want to refund + Self::free_mandatory_headers_remaining() > 0 && + // if arguments out of expected bounds, we don't want to refund submit_finality_proof_info_from_args::(&finality_target, &justification) .fits_limits(); - >::mutate(|count| *count += 1); + if may_refund_call_fee { + FreeMandatoryHeadersRemaining::::mutate(|count| { + *count = count.saturating_sub(1) + }); + } insert_header::(*finality_target, hash); log::info!( target: LOG_TARGET, @@ -273,16 +284,20 @@ pub mod pallet { } } - /// The current number of requests which have written to storage. + /// Number mandatory headers that we may accept in the current block for free (returning + /// `Pays::No`). /// - /// If the `RequestCount` hits `MaxRequests`, no more calls will be allowed to the pallet until - /// the request capacity is increased. + /// If the `FreeMandatoryHeadersRemaining` hits zero, all following mandatory headers in the + /// current block are accepted with fee (`Pays::Yes` is returned). /// - /// The `RequestCount` is decreased by one at the beginning of every block. This is to ensure - /// that the pallet can always make progress. + /// The `FreeMandatoryHeadersRemaining` is an ephemeral value that is set to + /// `MaxFreeMandatoryHeadersPerBlock` at each block initialization and is killed on block + /// finalization. So it never ends up in the storage trie. #[pallet::storage] - #[pallet::getter(fn request_count)] - pub(super) type RequestCount, I: 'static = ()> = StorageValue<_, u32, ValueQuery>; + #[pallet::whitelist_storage] + #[pallet::getter(fn free_mandatory_headers_remaining)] + pub(super) type FreeMandatoryHeadersRemaining, I: 'static = ()> = + StorageValue<_, u32, ValueQuery>; /// Hash of the header used to bootstrap the pallet. #[pallet::storage] @@ -392,8 +407,6 @@ pub mod pallet { InvalidJustification, /// The authority set from the underlying header chain is invalid. InvalidAuthoritySet, - /// There are too many requests for the current window to handle. - TooManyRequests, /// The header being imported is older than the best finalized header known to the pallet. OldHeader, /// The scheduled authority set change found in the header is unsupported by the pallet. @@ -662,7 +675,8 @@ mod tests { }; use codec::Encode; use frame_support::{ - assert_err, assert_noop, assert_ok, dispatch::PostDispatchInfo, + assert_err, assert_noop, assert_ok, + dispatch::{Pays, PostDispatchInfo}, storage::generator::StorageValue, }; use frame_system::{EventRecord, Phase}; @@ -705,6 +719,51 @@ mod tests { ) } + fn submit_finality_proof_with_set_id( + header: u8, + set_id: u64, + ) -> frame_support::dispatch::DispatchResultWithPostInfo { + let header = test_header(header.into()); + let justification = make_justification_for_header(JustificationGeneratorParams { + header: header.clone(), + set_id, + ..Default::default() + }); + + Pallet::::submit_finality_proof( + RuntimeOrigin::signed(1), + Box::new(header), + justification, + ) + } + + fn submit_mandatory_finality_proof( + number: u8, + set_id: u64, + ) -> frame_support::dispatch::DispatchResultWithPostInfo { + let mut header = test_header(number.into()); + // to ease tests that are using `submit_mandatory_finality_proof`, we'll be using the + // same set for all sessions + let consensus_log = + ConsensusLog::::ScheduledChange(sp_consensus_grandpa::ScheduledChange { + next_authorities: authority_list(), + delay: 0, + }); + header.digest = + Digest { logs: vec![DigestItem::Consensus(GRANDPA_ENGINE_ID, consensus_log.encode())] }; + let justification = make_justification_for_header(JustificationGeneratorParams { + header: header.clone(), + set_id, + ..Default::default() + }); + + Pallet::::submit_finality_proof( + RuntimeOrigin::signed(1), + Box::new(header), + justification, + ) + } + fn next_block() { use frame_support::traits::OnInitialize; @@ -1169,13 +1228,18 @@ mod tests { } #[test] - fn rate_limiter_disallows_imports_once_limit_is_hit_in_single_block() { + fn rate_limiter_disallows_free_imports_once_limit_is_hit_in_single_block() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1)); - assert_ok!(submit_finality_proof(2)); - assert_err!(submit_finality_proof(3), >::TooManyRequests); + let result = submit_mandatory_finality_proof(1, 1); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(2, 2); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(3, 3); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); }) } @@ -1183,7 +1247,8 @@ mod tests { fn rate_limiter_invalid_requests_do_not_count_towards_request_count() { run_test(|| { let submit_invalid_request = || { - let header = test_header(1); + let mut header = test_header(1); + header.digest = change_log(0); let mut invalid_justification = make_default_justification(&header); invalid_justification.round = 42; @@ -1196,15 +1261,19 @@ mod tests { initialize_substrate_bridge(); - for _ in 0..::MaxRequests::get() + 1 { - // Notice that the error here *isn't* `TooManyRequests` + for _ in 0..::MaxFreeMandatoryHeadersPerBlock::get() + 1 { assert_err!(submit_invalid_request(), >::InvalidJustification); } - // Can still submit `MaxRequests` requests afterwards - assert_ok!(submit_finality_proof(1)); - assert_ok!(submit_finality_proof(2)); - assert_err!(submit_finality_proof(3), >::TooManyRequests); + // Can still submit free mandatory headers afterwards + let result = submit_mandatory_finality_proof(1, 1); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(2, 2); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(3, 3); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); }) } @@ -1212,40 +1281,51 @@ mod tests { fn rate_limiter_allows_request_after_new_block_has_started() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1)); - assert_ok!(submit_finality_proof(2)); - next_block(); - assert_ok!(submit_finality_proof(3)); - }) - } + let result = submit_mandatory_finality_proof(1, 1); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); - #[test] - fn rate_limiter_disallows_imports_once_limit_is_hit_across_different_blocks() { - run_test(|| { - initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1)); - assert_ok!(submit_finality_proof(2)); + let result = submit_mandatory_finality_proof(2, 2); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(3, 3); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); next_block(); - assert_ok!(submit_finality_proof(3)); - assert_err!(submit_finality_proof(4), >::TooManyRequests); + + let result = submit_mandatory_finality_proof(4, 4); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(5, 5); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_mandatory_finality_proof(6, 6); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); }) } #[test] - fn rate_limiter_allows_max_requests_after_long_time_with_no_activity() { + fn rate_limiter_ignores_non_mandatory_headers() { run_test(|| { initialize_substrate_bridge(); - assert_ok!(submit_finality_proof(1)); - assert_ok!(submit_finality_proof(2)); - next_block(); - next_block(); + let result = submit_finality_proof(1); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); - next_block(); - assert_ok!(submit_finality_proof(5)); - assert_ok!(submit_finality_proof(7)); + let result = submit_mandatory_finality_proof(2, 1); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_finality_proof_with_set_id(3, 2); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); + + let result = submit_mandatory_finality_proof(4, 2); + assert_eq!(result.expect("call failed").pays_fee, Pays::No); + + let result = submit_finality_proof_with_set_id(5, 3); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); + + let result = submit_mandatory_finality_proof(6, 3); + assert_eq!(result.expect("call failed").pays_fee, Pays::Yes); }) } diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 2220ba3f129f5..0ebbc0bccbb7b 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -21,7 +21,7 @@ use bp_header_chain::ChainWithGrandpa; use bp_runtime::Chain; use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, ConstU64}, + traits::{ConstU32, ConstU64, Hooks}, weights::Weight, }; use sp_core::sr25519::Signature; @@ -87,7 +87,7 @@ impl frame_system::Config for TestRuntime { } parameter_types! { - pub const MaxRequests: u32 = 2; + pub const MaxFreeMandatoryHeadersPerBlock: u32 = 2; pub const HeadersToKeep: u32 = 5; pub const SessionLength: u64 = 5; pub const NumValidators: u32 = 5; @@ -96,7 +96,7 @@ parameter_types! { impl grandpa::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type BridgedChain = TestBridgedChain; - type MaxRequests = MaxRequests; + type MaxFreeMandatoryHeadersPerBlock = MaxFreeMandatoryHeadersPerBlock; type HeadersToKeep = HeadersToKeep; type WeightInfo = (); } @@ -138,7 +138,10 @@ pub fn new_test_ext() -> sp_io::TestExternalities { /// Return test within default test externalities context. pub fn run_test(test: impl FnOnce() -> T) -> T { - new_test_ext().execute_with(test) + new_test_ext().execute_with(|| { + let _ = Grandpa::on_initialize(0); + test() + }) } /// Return test header with given number. diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 90e6d7c558e49..3086adc1cc2ea 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -199,7 +199,7 @@ parameter_types! { impl pallet_bridge_grandpa::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type BridgedChain = TestBridgedChain; - type MaxRequests = ConstU32<2>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type WeightInfo = (); } @@ -207,7 +207,7 @@ impl pallet_bridge_grandpa::Config for TestRun impl pallet_bridge_grandpa::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type BridgedChain = TestBridgedChain; - type MaxRequests = ConstU32<2>; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<2>; type HeadersToKeep = HeadersToKeep; type WeightInfo = (); } From 094bf777c2a49dc9767d2c1ae0d5006513d50104 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 28 Mar 2023 15:16:03 +0300 Subject: [PATCH 1007/1210] bump BridgeHubRococo/BridgeHubWococo versions (#2000) --- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/chains/wococo.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index 166e6edbad360..c0041c53ddbf4 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,5 +27,5 @@ impl CliChain for Rococo { impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9372, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9381, transaction_version: 2 }); } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index b6eceb8614e83..73b3884c289d9 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -27,5 +27,5 @@ impl CliChain for Wococo { impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9372, transaction_version: 1 }); + Some(SimpleRuntimeVersion { spec_version: 9381, transaction_version: 2 }); } From 0930eb4612daa5c16dd37da6a26ede41ec2647a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 02:03:36 +0000 Subject: [PATCH 1008/1210] Bump tokio from 1.26.0 to 1.27.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.26.0 to 1.27.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.26.0...tokio-1.27.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index ce83817a9956a..885a8e3346019 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.17" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.1.1", features = ["derive"] } -tokio = { version = "1.26", features = ["rt-multi-thread"] } +tokio = { version = "1.27", features = ["rt-multi-thread"] } thiserror = "1.0.40" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 91bd9e20d6594..723f127c0910f 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.28" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.26", features = ["rt"] } +tokio = { version = "1.27", features = ["rt"] } thiserror = "1.0.40" # Bridge dependencies From 763612da9d6624e4179c4bcea6efa5f11dfa5355 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 02:04:49 +0000 Subject: [PATCH 1009/1210] Bump serde_json from 1.0.94 to 1.0.95 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.94 to 1.0.95. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.94...v1.0.95) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index cfe6e921f4b07..858c332068389 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.13", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.94" +serde_json = "1.0.95" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index bc8841c4f8795..c653274f4d26b 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.1.13", features = ["derive"] } -serde_json = "1.0.94" +serde_json = "1.0.95" # Bridge dependencies From 48177dd5b13f197293d8e96a7a9da354dcdf65a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 02:06:06 +0000 Subject: [PATCH 1010/1210] Bump tempfile from 3.4.0 to 3.5.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.4.0 to 3.5.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/commits) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 6984cfed00c77..1fde2102e1a61 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -69,5 +69,5 @@ xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", defau bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.3" sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -tempfile = "3.4" +tempfile = "3.5" finality-grandpa = { version = "0.16.2" } From 294b3098af1068c92cf58a86856a42679f2ba737 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 02:07:25 +0000 Subject: [PATCH 1011/1210] Bump futures from 0.3.27 to 0.3.28 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.27 to 0.3.28. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.27...0.3.28) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 1fde2102e1a61..64a1009f4bb23 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.27" +futures = "0.3.28" hex = "0.4" log = "0.4.17" num-format = "0.4" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 885a8e3346019..b089a3b6660e4 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.27" +futures = "0.3.28" jsonrpsee = { version = "0.16", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 287798431fef5..ab75533b023af 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } -futures = "0.3.27" +futures = "0.3.28" log = "0.4.17" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 17c75220f6d38..d07aa936b57c6 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,7 @@ thiserror = "1.0.40" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.27" +futures = "0.3.28" hex = "0.4" num-traits = "0.2" log = "0.4.17" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index efb6c6c85854d..8c4b8257d5aa6 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" -futures = "0.3.27" +futures = "0.3.28" hex = "0.4" log = "0.4.17" num-traits = "0.2" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 80df2311bc970..0cecf063922f9 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" async-trait = "0.1.68" -futures = "0.3.27" +futures = "0.3.28" log = "0.4.17" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 723f127c0910f..aa14e2ae2e353 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1" backoff = "0.4" isahc = "1.2" env_logger = "0.10.0" -futures = "0.3.27" +futures = "0.3.28" jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" From cf177e855bf78a221d9665da340c91e789c4cdd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 02:11:02 +0000 Subject: [PATCH 1012/1210] Bump hex-literal from 0.3.4 to 0.4.0 Bumps [hex-literal](https://github.com/RustCrypto/utils) from 0.3.4 to 0.4.0. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/hex-literal-v0.3.4...hex-literal-v0.4.0) --- updated-dependencies: - dependency-name: hex-literal dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 2f828393336f5..8401acf133f13 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -hex-literal = "0.3" +hex-literal = "0.4" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 0018c8f3905ae..7f52a06cf3f66 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -11,7 +11,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} -hex-literal = "0.3" +hex-literal = "0.4" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } # Bridge depedencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index ca2f4ad88d309..e9ec2e5edb931 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -27,7 +27,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [dev-dependencies] bp-test-utils = { path = "../test-utils" } hex = "0.4" -hex-literal = "0.3" +hex-literal = "0.4" [features] default = ["std"] diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index f54090893a678..a08964f70600a 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -23,7 +23,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [dev-dependencies] hex = "0.4" -hex-literal = "0.3" +hex-literal = "0.4" [features] default = ["std"] diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index ee91361a4e279..353ee80a43650 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -23,7 +23,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d [dev-dependencies] hex = "0.4" -hex-literal = "0.3" +hex-literal = "0.4" [features] default = ["std"] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 802e58e1af1ab..f0546733fedec 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -27,7 +27,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", trie-db = { version = "0.27.1", default-features = false } [dev-dependencies] -hex-literal = "0.3" +hex-literal = "0.4" [features] default = ["std"] diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 64a1009f4bb23..7853b9cb599ac 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -67,7 +67,7 @@ xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", defau [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } -hex-literal = "0.3" +hex-literal = "0.4" sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } tempfile = "3.5" finality-grandpa = { version = "0.16.2" } From 60ed4f852206792ae1fbcb9a5332f466dbc7465c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 06:41:21 +0000 Subject: [PATCH 1013/1210] Bump clap from 4.1.13 to 4.2.1 Bumps [clap](https://github.com/clap-rs/clap) from 4.1.13 to 4.2.1. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.1.13...v4.2.1) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 858c332068389..8f7e4ba69d862 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.13", features = ["derive"] } +clap = { version = "4.2.1", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.95" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index c60bad8386a96..afd52ed72ba2d 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.1.13", features = ["derive"] } +clap = { version = "4.2.1", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index c653274f4d26b..f105014fb51e9 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.1.13", features = ["derive"] } +clap = { version = "4.2.1", features = ["derive"] } serde_json = "1.0.95" # Bridge dependencies From 3f94ce625f80cbca691adf79da318da32d80a188 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 06:41:10 +0000 Subject: [PATCH 1014/1210] Bump scale-info from 2.4.0 to 2.5.0 Bumps [scale-info](https://github.com/paritytech/scale-info) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/paritytech/scale-info/releases) - [Changelog](https://github.com/paritytech/scale-info/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/scale-info/compare/v2.4.0...v2.5.0) --- updated-dependencies: - dependency-name: scale-info dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- relays/client-bridge-hub-kusama/Cargo.toml | 2 +- relays/client-bridge-hub-polkadot/Cargo.toml | 2 +- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 8401acf133f13..ce1484fecad94 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.4" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 7f52a06cf3f66..53f57e026199c 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -12,7 +12,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} hex-literal = "0.4" -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge depedencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 4f0f64cbc9597..2b68e72d6f8b2 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index e4a5d7ccce1b2..3db4ae9abca6e 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index b50ac723db2a6..8aff2c169b464 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 0a737ef633a85..07d2593b9145f 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 4f1e04eecc278..f733d62bf6401 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index c25956248d054..39c3ba626aa09 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 200fbbca3093b..c654c60d02bb5 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 504adfae41697..2d7dc272a6faf 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 4b4044252ca99..9039064fbf4f1 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.0.1", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 00d5a02d47c49..d1e2e0edd968c 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -13,7 +13,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", optional = true } parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index e9ec2e5edb931..5b9f87614a87f 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index a08964f70600a..32d7c65ebcbbb 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 333f7ad647a67..e47b8c5e68c70 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index a9db53a8bf01e..daae99ec71c1a 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 353ee80a43650..8ac3125848834 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.1.1", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index f0546733fedec..4d48ad61894d5 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Dependencies diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index 3485323ca6c51..96650710f677d 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index dee3147eb35a3..6126a8f2b3f1d 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 78c3533971c70..48df2e56cf088 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index 8164ae5afed21..d4578fcd4887a 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 987ac532ca6d8..4450dee37116f 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } subxt = { version = "0.27.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index b089a3b6660e4..2a79832bf9d64 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,7 +14,7 @@ jsonrpsee = { version = "0.16", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.8" -scale-info = { version = "2.1.1", features = ["derive"] } +scale-info = { version = "2.5.0", features = ["derive"] } tokio = { version = "1.27", features = ["rt-multi-thread"] } thiserror = "1.0.40" From 1cfd1b9b83d150a815f7a57448fa3a2fee833c1c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 4 Apr 2023 15:05:44 +0300 Subject: [PATCH 1015/1210] Remove unneeded error debug strings (#2017) * Remove unneeded error debug strings This reverts commit ff33e6ce127ea22c359b1b0273d6f3a5a27f484c. --- bin/runtime-common/src/messages_xcm_extension.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 3d802d12fad64..4ccdd7a4b4df5 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -42,7 +42,7 @@ pub type XcmAsPlainPayload = sp_std::prelude::Vec; pub enum XcmBlobMessageDispatchResult { InvalidPayload, Dispatched, - NotDispatched(#[codec(skip)] &'static str), + NotDispatched(#[codec(skip)] Option), } /// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages @@ -106,24 +106,12 @@ impl< XcmBlobMessageDispatchResult::Dispatched }, Err(e) => { - let e = match e { - DispatchBlobError::Unbridgable => "DispatchBlobError::Unbridgable", - DispatchBlobError::InvalidEncoding => "DispatchBlobError::InvalidEncoding", - DispatchBlobError::UnsupportedLocationVersion => - "DispatchBlobError::UnsupportedLocationVersion", - DispatchBlobError::UnsupportedXcmVersion => - "DispatchBlobError::UnsupportedXcmVersion", - DispatchBlobError::RoutingError => "DispatchBlobError::RoutingError", - DispatchBlobError::NonUniversalDestination => - "DispatchBlobError::NonUniversalDestination", - DispatchBlobError::WrongGlobal => "DispatchBlobError::WrongGlobal", - }; log::error!( target: crate::LOG_TARGET_BRIDGE_DISPATCH, "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}", e, message.key.nonce ); - XcmBlobMessageDispatchResult::NotDispatched(e) + XcmBlobMessageDispatchResult::NotDispatched(Some(e)) }, }; MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result } From 1637d8b7273e5c65f1fdf7a2e14ef65e108e4556 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 7 Apr 2023 09:55:06 +0300 Subject: [PATCH 1016/1210] fail with InsufficientDispatchWeight if dispatch_weight doesn't cover weight of all bundled messages (#2018) --- modules/grandpa/src/lib.rs | 10 +++ modules/messages/src/lib.rs | 73 +++++++++++-------- modules/parachains/src/lib.rs | 10 +++ primitives/messages/src/lib.rs | 8 +- .../src/codegen_runtime.rs | 6 +- 5 files changed, 67 insertions(+), 40 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index df51aa1eb7ed6..9d38c9723d7ac 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -160,6 +160,16 @@ pub mod pallet { /// /// If successful in verification, it will write the target header to the underlying storage /// pallet. + /// + /// The call fails if: + /// + /// - the pallet is halted; + /// + /// - the pallet knows better header than the `finality_target`; + /// + /// - verification is not optimized or invalid; + /// + /// - header contains forced authorities set change or change with non-zero delay. #[pallet::call_index(0)] #[pallet::weight(::submit_finality_proof( justification.commit.precommits.len().saturated_into(), diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 3faf00b9e75bf..f7bc7d8a109f9 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -249,6 +249,22 @@ pub mod pallet { /// The weight of the call assumes that the transaction always brings outbound lane /// state update. Because of that, the submitter (relayer) has no benefit of not including /// this data in the transaction, so reward confirmations lags should be minimal. + /// + /// The call fails if: + /// + /// - the pallet is halted; + /// + /// - the call origin is not `Signed(_)`; + /// + /// - there are too many messages in the proof; + /// + /// - the proof verification procedure returns an error - e.g. because header used to craft + /// proof is not imported by the associated finality pallet; + /// + /// - the `dispatch_weight` argument is not sufficient to dispatch all bundled messages. + /// + /// The call may succeed, but some messages may not be delivered e.g. if they are not fit + /// into the unrewarded relayers vector. #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::receive_messages_proof_weight(proof, *messages_count, *dispatch_weight))] pub fn receive_messages_proof( @@ -324,18 +340,10 @@ pub mod pallet { let mut lane_messages_received_status = ReceivedMessages::new(lane_id, Vec::with_capacity(lane_data.messages.len())); - let mut is_lane_processing_stopped_no_weight_left = false; - for mut message in lane_data.messages { debug_assert_eq!(message.key.lane_id, lane_id); total_messages += 1; - if is_lane_processing_stopped_no_weight_left { - lane_messages_received_status - .push_skipped_for_not_enough_weight(message.key.nonce); - continue - } - // ensure that relayer has declared enough weight for dispatching next message // on this lane. We can't dispatch lane messages out-of-order, so if declared // weight is not enough, let's move to next lane @@ -348,10 +356,8 @@ pub mod pallet { message_dispatch_weight, dispatch_weight_left, ); - lane_messages_received_status - .push_skipped_for_not_enough_weight(message.key.nonce); - is_lane_processing_stopped_no_weight_left = true; - continue + + fail!(Error::::InsufficientDispatchWeight); } let receival_result = lane.receive_message::( @@ -554,8 +560,9 @@ pub mod pallet { /// The relayer has declared invalid unrewarded relayers state in the /// `receive_messages_delivery_proof` call. InvalidUnrewardedRelayersState, - /// The message someone is trying to work with (i.e. increase fee) is already-delivered. - MessageIsAlreadyDelivered, + /// The cumulative dispatch weight, passed by relayer is not enough to cover dispatch + /// of all bundled messages. + InsufficientDispatchWeight, /// The message someone is trying to work with (i.e. increase fee) is not yet sent. MessageIsNotYetSent, /// The number of actually confirmed messages is going to be larger than the number of @@ -1277,13 +1284,16 @@ mod tests { run_test(|| { let mut declared_weight = REGULAR_PAYLOAD.declared_weight; *declared_weight.ref_time_mut() -= 1; - assert_ok!(Pallet::::receive_messages_proof( - RuntimeOrigin::signed(1), - TEST_RELAYER_A, - Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), - 1, - declared_weight, - )); + assert_noop!( + Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + 1, + declared_weight, + ), + Error::::InsufficientDispatchWeight + ); assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 0); }); } @@ -1541,15 +1551,18 @@ mod tests { let message2 = message(2, message_payload(0, u64::MAX / 2)); let message3 = message(3, message_payload(0, u64::MAX / 2)); - assert_ok!(Pallet::::receive_messages_proof( - RuntimeOrigin::signed(1), - TEST_RELAYER_A, - // this may cause overflow if source chain storage is invalid - Ok(vec![message1, message2, message3]).into(), - 3, - Weight::MAX, - )); - assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 2); + assert_noop!( + Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + // this may cause overflow if source chain storage is invalid + Ok(vec![message1, message2, message3]).into(), + 3, + Weight::MAX, + ), + Error::::InsufficientDispatchWeight + ); + assert_eq!(InboundLanes::::get(TEST_LANE_ID).last_delivered_nonce(), 0); }); } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 8fe6c4e938391..6c89b09513cd6 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -294,6 +294,16 @@ pub mod pallet { /// `polkadot-runtime-parachains::paras` pallet instance, deployed at the bridged chain. /// The proof is supposed to be crafted at the `relay_header_hash` that must already be /// imported by corresponding GRANDPA pallet at this chain. + /// + /// The call fails if: + /// + /// - the pallet is halted; + /// + /// - the relay chain block `at_relay_block` is not imported by the associated bridge + /// GRANDPA pallet. + /// + /// The call may succeed, but some heads may not be updated e.g. because pallet knows + /// better head or it isn't tracked by the pallet. #[pallet::call_index(0)] #[pallet::weight(WeightInfoOf::::submit_parachain_heads_weight( T::DbWeight::get(), diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 754349d634eef..8c10989d62011 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -238,8 +238,6 @@ pub struct ReceivedMessages { pub lane: LaneId, /// Result of messages which we tried to dispatch pub receive_results: Vec<(MessageNonce, ReceivalResult)>, - /// Messages which were skipped and never dispatched - pub skipped_for_not_enough_weight: Vec, } impl ReceivedMessages { @@ -247,16 +245,12 @@ impl ReceivedMessages { lane: LaneId, receive_results: Vec<(MessageNonce, ReceivalResult)>, ) -> Self { - ReceivedMessages { lane, receive_results, skipped_for_not_enough_weight: Vec::new() } + ReceivedMessages { lane, receive_results } } pub fn push(&mut self, message: MessageNonce, result: ReceivalResult) { self.receive_results.push((message, result)); } - - pub fn push_skipped_for_not_enough_weight(&mut self, message: MessageNonce) { - self.skipped_for_not_enough_weight.push(message); - } } /// Result of single message receival. diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs index 893bca1e27eff..3ea4a0ac2b5a0 100644 --- a/relays/client-rialto-parachain/src/codegen_runtime.rs +++ b/relays/client-rialto-parachain/src/codegen_runtime.rs @@ -6043,7 +6043,6 @@ pub mod api { ::core::primitive::u64, runtime_types::bp_messages::ReceivalResult<_0>, )>, - pub skipped_for_not_enough_weight: ::std::vec::Vec<::core::primitive::u64>, } #[derive( :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, @@ -7508,8 +7507,9 @@ pub mod api { #[doc = "`receive_messages_delivery_proof` call."] InvalidUnrewardedRelayersState, #[codec(index = 11)] - #[doc = "The message someone is trying to work with (i.e. increase fee) is already-delivered."] - MessageIsAlreadyDelivered, + #[doc = "The cumulative dispatch weight, passed by relayer is not enough to cover dispatch"] + #[doc = "of all bundled messages."] + InsufficientDispatchWeight, #[codec(index = 12)] #[doc = "The message someone is trying to work with (i.e. increase fee) is not yet sent."] MessageIsNotYetSent, From 172830a0c845b8d29e1eadd1cdf521402fefee7a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 7 Apr 2023 09:55:48 +0300 Subject: [PATCH 1017/1210] only refund if all bundled messages have been delivered (#2019) --- bin/runtime-common/src/messages_call_ext.rs | 17 ++++-- .../src/refund_relayer_extension.rs | 59 ++++++++++++++++++- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 588afad106da6..e8f992c638910 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -25,8 +25,11 @@ use sp_runtime::transaction_validity::TransactionValidity; /// Generic info about a messages delivery/confirmation proof. #[derive(PartialEq, RuntimeDebug)] pub struct BaseMessagesProofInfo { + /// Message lane, used by the call. pub lane_id: LaneId, + /// Nonce of the best message, included in the call. pub best_bundled_nonce: MessageNonce, + /// Nonce of the best message, stored by this chain before the call is dispatched. pub best_stored_nonce: MessageNonce, } @@ -58,19 +61,23 @@ pub struct CallHelper, I: 'static> { } impl, I: 'static> CallHelper { - /// Check if a call delivered proof/confirmation for at least some of the messages that it - /// contained. - pub fn was_partially_successful(info: &CallInfo) -> bool { + /// Returns true if: + /// + /// - call is `receive_messages_proof` and all messages have been delivered; + /// + /// - call is `receive_messages_delivery_proof` and all messages confirmations have been + /// received. + pub fn was_successful(info: &CallInfo) -> bool { match info { CallInfo::ReceiveMessagesProof(info) => { let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(info.0.lane_id); - inbound_lane_data.last_delivered_nonce() > info.0.best_stored_nonce + inbound_lane_data.last_delivered_nonce() == info.0.best_bundled_nonce }, CallInfo::ReceiveMessagesDeliveryProof(info) => { let outbound_lane_data = pallet_bridge_messages::OutboundLanes::::get(info.0.lane_id); - outbound_lane_data.latest_received_nonce > info.0.best_stored_nonce + outbound_lane_data.latest_received_nonce == info.0.best_bundled_nonce }, } } diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 7be97f19ad2ab..9b1e9a3a1a4d7 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -344,6 +344,16 @@ where finality_proof_info.block_number, ) { // we only refund relayer if all calls have updated chain state + log::trace!( + target: "runtime::bridge", + "{} from parachain {} via {:?}: failed to refund relayer {:?}, because \ + relay chain finality proof has not been accepted", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + relayer, + ); + return Ok(()) } @@ -366,15 +376,34 @@ where para_proof_info, ) { // we only refund relayer if all calls have updated chain state + log::trace!( + target: "runtime::bridge", + "{} from parachain {} via {:?}: failed to refund relayer {:?}, because \ + parachain finality proof has not been accepted", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + relayer, + ); + return Ok(()) } } - // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that + // Check if the `ReceiveMessagesProof` call delivered all the messages that // it contained. If this happens, we consider the transaction "helpful" and refund it. let msgs_call_info = call_info.messages_call_info(); - if !MessagesCallHelper::::was_partially_successful(msgs_call_info) - { + if !MessagesCallHelper::::was_successful(msgs_call_info) { + log::trace!( + target: "runtime::bridge", + "{} from parachain {} via {:?}: failed to refund relayer {:?}, because \ + some of messages have not been accepted", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + relayer, + ); + return Ok(()) } @@ -1032,6 +1061,30 @@ mod tests { }); } + #[test] + fn post_dispatch_ignores_transaction_that_has_not_delivered_all_messages() { + run_test(|| { + initialize_environment(200, 200, Default::default(), 150); + + assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); + assert_storage_noop!(run_post_dispatch( + Some(parachain_finality_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(()))); + + assert_storage_noop!(run_post_dispatch( + Some(all_finality_confirmation_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch( + Some(parachain_finality_confirmation_pre_dispatch_data()), + Ok(()) + )); + assert_storage_noop!(run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(()))); + }); + } + #[test] fn post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight() { run_test(|| { From 803208a9150b6c08fe1be826337c15338e86725e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 10 Apr 2023 10:39:24 +0300 Subject: [PATCH 1018/1210] Reintroduce msg dispatch status reporting (#2027) * Use an actual Result inside MessageDispatchResult We need this in order to distinguish between Ok and Err * Revert #1660 * Fixes + simplifications * Implement review suggestions --- bin/millau/runtime/src/xcm_config.rs | 10 +- bin/rialto-parachain/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/xcm_config.rs | 6 +- bin/runtime-common/src/integrity.rs | 6 +- .../src/messages_xcm_extension.rs | 18 +-- modules/messages/Cargo.toml | 1 + modules/messages/src/benchmarking.rs | 12 +- modules/messages/src/inbound_lane.rs | 27 +++-- modules/messages/src/lib.rs | 111 ++++++++++------- modules/messages/src/mock.rs | 24 ++-- modules/messages/src/outbound_lane.rs | 88 +++++++++++--- primitives/messages/Cargo.toml | 2 + primitives/messages/src/lib.rs | 113 +++++++++++++++--- primitives/messages/src/target_chain.rs | 10 +- primitives/runtime/src/messages.rs | 4 +- 15 files changed, 307 insertions(+), 131 deletions(-) diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 4aaec83771b04..56546f2999297 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -242,7 +242,7 @@ mod tests { target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchError; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use xcm_executor::XcmExecutor; @@ -352,8 +352,8 @@ mod tests { let dispatch_result = FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + dispatch_result.dispatch_result, + Err(XcmBlobMessageDispatchError::NotDispatched(_)), )); } @@ -366,8 +366,8 @@ mod tests { let dispatch_result = FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + dispatch_result.dispatch_result, + Err(XcmBlobMessageDispatchError::NotDispatched(_)), )); } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index cd4e256f4203e..b03f7965d7b28 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -853,7 +853,7 @@ mod tests { LaneId, MessageKey, }; use bridge_runtime_common::{ - integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchResult, + integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchError, }; use codec::Encode; use pallet_bridge_messages::OutboundLanes; @@ -928,8 +928,8 @@ mod tests { let dispatch_result = FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + dispatch_result.dispatch_result, + Err(XcmBlobMessageDispatchError::NotDispatched(_)), )); }); } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 9f6488b4c4d31..265f435645e8f 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -197,7 +197,7 @@ mod tests { target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchError; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use xcm_executor::XcmExecutor; @@ -269,8 +269,8 @@ mod tests { let dispatch_result = FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + dispatch_result.dispatch_result, + Err(XcmBlobMessageDispatchError::NotDispatched(_)), )); } } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 5820dd99b91ca..3a677ce43ceda 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -307,8 +307,10 @@ pub fn check_message_lane_weights( messages::target::maximal_incoming_message_dispatch_weight(C::max_extrinsic_weight()), ); - let max_incoming_inbound_lane_data_proof_size = - InboundLaneData::<()>::encoded_size_hint_u32(this_chain_max_unrewarded_relayers as _); + let max_incoming_inbound_lane_data_proof_size = InboundLaneData::<()>::encoded_size_hint_u32( + this_chain_max_unrewarded_relayers as _, + this_chain_max_unconfirmed_messages as _, + ); pallet_bridge_messages::ensure_able_to_receive_confirmation::>( C::max_extrinsic_size(), C::max_extrinsic_weight(), diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 4ccdd7a4b4df5..d0fdc458e958c 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -39,9 +39,8 @@ pub type XcmAsPlainPayload = sp_std::prelude::Vec; /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] -pub enum XcmBlobMessageDispatchResult { +pub enum XcmBlobMessageDispatchError { InvalidPayload, - Dispatched, NotDispatched(#[codec(skip)] Option), } @@ -65,7 +64,7 @@ impl< for XcmBlobMessageDispatch { type DispatchPayload = XcmAsPlainPayload; - type DispatchLevelResult = XcmBlobMessageDispatchResult; + type DispatchError = XcmBlobMessageDispatchError; fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload { @@ -80,7 +79,7 @@ impl< fn dispatch( _relayer_account: &AccountIdOf, message: DispatchMessage, - ) -> MessageDispatchResult { + ) -> MessageDispatchResult { let payload = match message.data.payload { Ok(payload) => payload, Err(e) => { @@ -92,7 +91,7 @@ impl< ); return MessageDispatchResult { unspent_weight: Weight::zero(), - dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload, + dispatch_result: Err(XcmBlobMessageDispatchError::InvalidPayload), } }, }; @@ -103,7 +102,7 @@ impl< "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob was ok - message_nonce: {:?}", message.key.nonce ); - XcmBlobMessageDispatchResult::Dispatched + Ok(()) }, Err(e) => { log::error!( @@ -111,10 +110,13 @@ impl< "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}", e, message.key.nonce ); - XcmBlobMessageDispatchResult::NotDispatched(Some(e)) + Err(XcmBlobMessageDispatchError::NotDispatched(Some(e))) }, }; - MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result } + MessageDispatchResult { + unspent_weight: Weight::zero(), + dispatch_result: dispatch_level_result, + } } } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index f733d62bf6401..7dbe6e15ba342 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index aab8855a729a8..f7a2769715fa5 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -301,7 +301,7 @@ benchmarks_instance_pallet! { inbound_lane_data: InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: relayer_id.clone(), - messages: DeliveredMessages::new(1), + messages: DeliveredMessages::new(1, true), }].into_iter().collect(), last_confirmed_nonce: 0, }, @@ -333,8 +333,8 @@ benchmarks_instance_pallet! { total_messages: 2, last_delivered_nonce: 2, }; - let mut delivered_messages = DeliveredMessages::new(1); - delivered_messages.note_dispatched_message(); + let mut delivered_messages = DeliveredMessages::new(1, true); + delivered_messages.note_dispatched_message(true); let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -379,11 +379,11 @@ benchmarks_instance_pallet! { relayers: vec![ UnrewardedRelayer { relayer: relayer1_id.clone(), - messages: DeliveredMessages::new(1), + messages: DeliveredMessages::new(1, true), }, UnrewardedRelayer { relayer: relayer2_id.clone(), - messages: DeliveredMessages::new(2), + messages: DeliveredMessages::new(2, true), }, ].into_iter().collect(), last_confirmed_nonce: 0, @@ -451,7 +451,7 @@ fn receive_messages, I: 'static>(nonce: MessageNonce) { inbound_lane_storage.set_data(InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: T::bridged_relayer_id(), - messages: DeliveredMessages::new(nonce), + messages: DeliveredMessages::new(nonce, true), }] .into_iter() .collect(), diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 3f64ab765b5da..21d835d31c715 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -101,6 +101,7 @@ impl, I: 'static> MaxEncodedLen for StoredInboundLaneData { fn max_encoded_len() -> usize { InboundLaneData::::encoded_size_hint( T::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize, + T::MaxUnconfirmedMessagesAtInboundLane::get() as usize, ) .unwrap_or(usize::MAX) } @@ -154,6 +155,9 @@ impl InboundLane { // overlap. match data.relayers.front_mut() { Some(entry) if entry.messages.begin < new_confirmed_nonce => { + entry.messages.dispatch_results = entry.messages.dispatch_results + [(new_confirmed_nonce + 1 - entry.messages.begin) as usize..] + .to_bitvec(); entry.messages.begin = new_confirmed_nonce + 1; }, _ => {}, @@ -170,7 +174,7 @@ impl InboundLane { relayer_at_this_chain: &AccountId, nonce: MessageNonce, message_data: DispatchMessageData, - ) -> ReceivalResult { + ) -> ReceivalResult { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { @@ -198,19 +202,20 @@ impl InboundLane { ); // now let's update inbound lane storage - let push_new = match data.relayers.back_mut() { + match data.relayers.back_mut() { Some(entry) if entry.relayer == *relayer_at_bridged_chain => { - entry.messages.note_dispatched_message(); - false + entry.messages.note_dispatched_message(dispatch_result.dispatch_result.is_ok()); + }, + _ => { + data.relayers.push_back(UnrewardedRelayer { + relayer: relayer_at_bridged_chain.clone(), + messages: DeliveredMessages::new( + nonce, + dispatch_result.dispatch_result.is_ok(), + ), + }); }, - _ => true, }; - if push_new { - data.relayers.push_back(UnrewardedRelayer { - relayer: (*relayer_at_bridged_chain).clone(), - messages: DeliveredMessages::new(nonce), - }); - } self.storage.set_data(data); ReceivalResult::Dispatched(dispatch_result) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index f7bc7d8a109f9..f425c824b6d8f 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -66,7 +66,7 @@ use bp_messages::{ use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; -use sp_runtime::traits::UniqueSaturatedFrom; +use sp_runtime::{traits::UniqueSaturatedFrom, SaturatedConversion}; use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; @@ -527,7 +527,7 @@ pub mod pallet { MessagesReceived( Vec< ReceivedMessages< - >::DispatchLevelResult, + >::DispatchError, >, >, ), @@ -807,15 +807,19 @@ impl, I: 'static> RuntimeInboundLaneStorage { /// `receive_messages_proof` call, because the actual inbound lane state is smaller than the /// maximal configured. /// - /// Maximal inbound lane state set size is configured by the - /// `MaxUnrewardedRelayerEntriesAtInboundLane` constant from the pallet configuration. The PoV - /// of the call includes the maximal size of inbound lane state. If the actual size is smaller, - /// we may subtract extra bytes from this component. + /// Maximal inbound lane state size is computed using the + /// `MaxUnrewardedRelayerEntriesAtInboundLane` and `MaxUnconfirmedMessagesAtInboundLane` + /// constants from the pallet configuration. The PoV of the call includes the maximal size + /// of the inbound lane state. If the actual size is smaller, we may subtract extra bytes + /// from this component. pub fn extra_proof_size_bytes(&self) -> u64 { let max_encoded_len = StoredInboundLaneData::::max_encoded_len(); let relayers_count = self.data().relayers.len(); + let messages_count = self.data().relayers.iter().fold(0usize, |sum, relayer| { + sum.saturating_add(relayer.messages.total_messages().saturated_into::()) + }); let actual_encoded_len = - InboundLaneData::::encoded_size_hint(relayers_count) + InboundLaneData::::encoded_size_hint(relayers_count, messages_count) .unwrap_or(usize::MAX); max_encoded_len.saturating_sub(actual_encoded_len) as _ } @@ -946,6 +950,7 @@ mod tests { }; use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; + use std::collections::VecDeque; fn get_ready_for_events() { System::::set_block_number(1); @@ -1003,7 +1008,7 @@ mod tests { last_confirmed_nonce: 1, relayers: vec![UnrewardedRelayer { relayer: 0, - messages: DeliveredMessages::new(1), + messages: DeliveredMessages::new(1, true), }] .into_iter() .collect(), @@ -1023,13 +1028,44 @@ mod tests { phase: Phase::Initialization, event: TestEvent::Messages(Event::MessagesDelivered { lane_id: TEST_LANE_ID, - messages: DeliveredMessages::new(1), + messages: DeliveredMessages::new(1, true), }), topics: vec![], }], ); } + fn unrewarded_relayer_entry(msg_count: usize) -> UnrewardedRelayer { + UnrewardedRelayer { + relayer: 42u64, + messages: DeliveredMessages { + begin: 0, + end: msg_count as MessageNonce - 1, + dispatch_results: FromIterator::from_iter(vec![true; msg_count]), + }, + } + } + + fn unrewarded_relayers_vec( + entry_count: usize, + msg_count: usize, + ) -> VecDeque> { + if entry_count > msg_count { + panic!("unrewarded_relayers_vec(): expecting msg_count to be >= entry_count"); + } + + let mut unrewarded_relayers = vec![]; + let mut available_msg_count = msg_count; + for _ in 0..entry_count - 1 { + unrewarded_relayers + .push(unrewarded_relayer_entry(std::cmp::min(1, available_msg_count))); + available_msg_count -= 1 + } + unrewarded_relayers.push(unrewarded_relayer_entry(available_msg_count)); + + unrewarded_relayers.into_iter().collect() + } + #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { @@ -1634,6 +1670,7 @@ mod tests { fn proof_size_refund_from_receive_messages_proof_works() { run_test(|| { let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; + let max_msgs = crate::mock::MaxUnconfirmedMessagesAtInboundLane::get() as usize; // if there's maximal number of unrewarded relayer entries at the inbound lane, then // `proof_size` is unchanged in post-dispatch weight @@ -1648,15 +1685,7 @@ mod tests { InboundLanes::::insert( TEST_LANE_ID, StoredInboundLaneData(InboundLaneData { - relayers: vec![ - UnrewardedRelayer { - relayer: 42, - messages: DeliveredMessages { begin: 0, end: 100 } - }; - max_entries - ] - .into_iter() - .collect(), + relayers: unrewarded_relayers_vec(max_entries, max_msgs), last_confirmed_nonce: 0, }), ); @@ -1677,15 +1706,7 @@ mod tests { InboundLanes::::insert( TEST_LANE_ID, StoredInboundLaneData(InboundLaneData { - relayers: vec![ - UnrewardedRelayer { - relayer: 42, - messages: DeliveredMessages { begin: 0, end: 100 } - }; - max_entries - 1 - ] - .into_iter() - .collect(), + relayers: unrewarded_relayers_vec(max_entries - 1, max_msgs), last_confirmed_nonce: 0, }), ); @@ -1701,7 +1722,7 @@ mod tests { .unwrap(); assert!( post_dispatch_weight.proof_size() < pre_dispatch_weight.proof_size(), - "Expected post-dispatch PoV {} to be less than pre-dispatch PoV {}", + "Expected post-dispatch PoV {} to be < than pre-dispatch PoV {}", post_dispatch_weight.proof_size(), pre_dispatch_weight.proof_size(), ); @@ -1717,8 +1738,8 @@ mod tests { // messages 1+2 are confirmed in 1 tx, message 3 in a separate tx // dispatch of message 2 has failed - let mut delivered_messages_1_and_2 = DeliveredMessages::new(1); - delivered_messages_1_and_2.note_dispatched_message(); + let mut delivered_messages_1_and_2 = DeliveredMessages::new(1, true); + delivered_messages_1_and_2.note_dispatched_message(true); let messages_1_and_2_proof = Ok(( TEST_LANE_ID, InboundLaneData { @@ -1731,7 +1752,7 @@ mod tests { .collect(), }, )); - let delivered_message_3 = DeliveredMessages::new(3); + let delivered_message_3 = DeliveredMessages::new(3, true); let messages_3_proof = Ok(( TEST_LANE_ID, InboundLaneData { @@ -2022,7 +2043,7 @@ mod tests { last_confirmed_nonce: 1, relayers: vec![UnrewardedRelayer { relayer: 0, - messages: DeliveredMessages::new(1), + messages: DeliveredMessages::new(1, true), }] .into_iter() .collect(), @@ -2082,39 +2103,39 @@ mod tests { #[test] fn inbound_storage_extra_proof_size_bytes_works() { - fn relayer_entry() -> UnrewardedRelayer { - UnrewardedRelayer { relayer: 42u64, messages: DeliveredMessages { begin: 0, end: 100 } } - } + let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; + let max_msgs = crate::mock::MaxUnconfirmedMessagesAtInboundLane::get() as usize; - fn storage(relayer_entries: usize) -> RuntimeInboundLaneStorage { + fn storage( + entry_count: usize, + msg_count: usize, + ) -> RuntimeInboundLaneStorage { RuntimeInboundLaneStorage { lane_id: Default::default(), cached_data: RefCell::new(Some(InboundLaneData { - relayers: vec![relayer_entry(); relayer_entries].into_iter().collect(), + relayers: unrewarded_relayers_vec(entry_count, msg_count), last_confirmed_nonce: 0, })), _phantom: Default::default(), } } - let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; - // when we have exactly `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers - assert_eq!(storage(max_entries).extra_proof_size_bytes(), 0); + assert_eq!(storage(max_entries, max_msgs).extra_proof_size_bytes(), 0); // when we have less than `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers assert_eq!( - storage(max_entries - 1).extra_proof_size_bytes(), - relayer_entry().encode().len() as u64 + storage(max_entries - 1, max_msgs).extra_proof_size_bytes(), + unrewarded_relayer_entry(1).encoded_size() as u64 ); assert_eq!( - storage(max_entries - 2).extra_proof_size_bytes(), - 2 * relayer_entry().encode().len() as u64 + storage(max_entries - 2, max_msgs).extra_proof_size_bytes(), + 2 * unrewarded_relayer_entry(1).encoded_size() as u64 ); // when we have more than `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers // (shall not happen in practice) - assert_eq!(storage(max_entries + 1).extra_proof_size_bytes(), 0); + assert_eq!(storage(max_entries + 1, max_msgs).extra_proof_size_bytes(), 0); } #[test] diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 02940f369e25c..be4072f9278f5 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -19,6 +19,7 @@ use crate::Config; +use bitvec::prelude::*; use bp_messages::{ calc_relayers_rewards, source_chain::{DeliveryConfirmationPayments, LaneMessageVerifier, TargetHeaderChain}, @@ -62,13 +63,13 @@ pub struct TestPayload { /// /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, /// but for test purposes we'll be making it larger than `declared_weight` sometimes. - pub dispatch_result: MessageDispatchResult, + pub dispatch_result: MessageDispatchResult, /// Extra bytes that affect payload size. pub extra: Vec, } pub type TestMessageFee = u64; pub type TestRelayer = u64; -pub type TestDispatchLevelResult = (); +pub type TestDispatchError = (); type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -412,7 +413,7 @@ pub struct TestMessageDispatch; impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; - type DispatchLevelResult = TestDispatchLevelResult; + type DispatchError = TestDispatchError; fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { @@ -424,7 +425,7 @@ impl MessageDispatch for TestMessageDispatch { fn dispatch( _relayer_account: &AccountId, message: DispatchMessage, - ) -> MessageDispatchResult { + ) -> MessageDispatchResult { match message.data.payload.as_ref() { Ok(payload) => payload.dispatch_result.clone(), Err(_) => dispatch_result(0), @@ -459,12 +460,10 @@ pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { } /// Returns message dispatch result with given unspent weight. -pub const fn dispatch_result( - unspent_weight: u64, -) -> MessageDispatchResult { +pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult { MessageDispatchResult { unspent_weight: Weight::from_parts(unspent_weight, 0), - dispatch_level_result: (), + dispatch_result: Ok(()), } } @@ -474,7 +473,14 @@ pub fn unrewarded_relayer( end: MessageNonce, relayer: TestRelayer, ) -> UnrewardedRelayer { - UnrewardedRelayer { relayer, messages: DeliveredMessages { begin, end } } + UnrewardedRelayer { + relayer, + messages: DeliveredMessages { + begin, + end, + dispatch_results: bitvec![u8, Msb0; 1; (end + 1).saturating_sub(begin) as _], + }, + } } /// Return test externalities to use in tests. diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 33a58a40400bf..5b3281b5b162f 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -18,8 +18,10 @@ use crate::Config; +use bitvec::prelude::*; use bp_messages::{ - DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, + DeliveredMessages, DispatchResultsBitVec, LaneId, MessageNonce, MessagePayload, + OutboundLaneData, UnrewardedRelayer, }; use frame_support::{ weights::{RuntimeDbWeight, Weight}, @@ -65,6 +67,9 @@ pub enum ReceivalConfirmationResult { /// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid /// bridged chain storage. NonConsecutiveUnrewardedRelayerEntries, + /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May + /// be a result of invalid bridged chain storage. + InvalidNumberOfDispatchResults, /// The chain has more messages that need to be confirmed than there is in the proof. TryingToConfirmMoreMessagesThanExpected(MessageNonce), } @@ -124,9 +129,14 @@ impl OutboundLane { ) } - if let Err(e) = ensure_unrewarded_relayers_are_correct(latest_delivered_nonce, relayers) { - return e - } + let dispatch_results = match extract_dispatch_results( + data.latest_received_nonce, + latest_delivered_nonce, + relayers, + ) { + Ok(dispatch_results) => dispatch_results, + Err(extract_error) => return extract_error, + }; let prev_latest_received_nonce = data.latest_received_nonce; data.latest_received_nonce = latest_delivered_nonce; @@ -135,6 +145,7 @@ impl OutboundLane { ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages { begin: prev_latest_received_nonce + 1, end: latest_delivered_nonce, + dispatch_results, }) } @@ -169,30 +180,34 @@ impl OutboundLane { } } -/// Verifies unrewarded relayers vec. +/// Extract new dispatch results from the unrewarded relayers vec. /// /// Returns `Err(_)` if unrewarded relayers vec contains invalid data, meaning that the bridged /// chain has invalid runtime storage. -fn ensure_unrewarded_relayers_are_correct( +fn extract_dispatch_results( + prev_latest_received_nonce: MessageNonce, latest_received_nonce: MessageNonce, relayers: &VecDeque>, -) -> Result<(), ReceivalConfirmationResult> { - let mut last_entry_end: Option = None; +) -> Result { + // the only caller of this functions checks that the + // prev_latest_received_nonce..=latest_received_nonce is valid, so we're ready to accept + // messages in this range => with_capacity call must succeed here or we'll be unable to receive + // confirmations at all + let mut received_dispatch_result = + BitVec::with_capacity((latest_received_nonce - prev_latest_received_nonce + 1) as _); + let mut expected_entry_begin = relayers.front().map(|entry| entry.messages.begin); for entry in relayers { // unrewarded relayer entry must have at least 1 unconfirmed message // (guaranteed by the `InboundLane::receive_message()`) - if entry.messages.end < entry.messages.begin { + if entry.messages.total_messages() == 0 { return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry) } // every entry must confirm range of messages that follows previous entry range // (guaranteed by the `InboundLane::receive_message()`) - if let Some(last_entry_end) = last_entry_end { - let expected_entry_begin = last_entry_end.checked_add(1); - if expected_entry_begin != Some(entry.messages.begin) { - return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries) - } + if expected_entry_begin != Some(entry.messages.begin) { + return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries) } - last_entry_end = Some(entry.messages.end); + expected_entry_begin = entry.messages.end.checked_add(1); // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { @@ -201,9 +216,30 @@ fn ensure_unrewarded_relayers_are_correct( // this is detected now return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages) } + // entry must have single dispatch result for every message + // (guaranteed by the `InboundLane::receive_message()`) + if entry.messages.dispatch_results.len() as MessageNonce != entry.messages.total_messages() + { + return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults) + } + + // now we know that the entry is valid + // => let's check if it brings new confirmations + let new_messages_begin = + sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1); + if entry.messages.end < new_messages_begin { + continue + } + + // now we know that entry brings new confirmations + // => let's extract dispatch results + received_dispatch_result.extend_from_bitslice( + &entry.messages.dispatch_results + [(new_messages_begin - entry.messages.begin) as usize..], + ); } - Ok(()) + Ok(received_dispatch_result) } #[cfg(test)] @@ -228,7 +264,11 @@ mod tests { } fn delivered_messages(nonces: RangeInclusive) -> DeliveredMessages { - DeliveredMessages { begin: *nonces.start(), end: *nonces.end() } + DeliveredMessages { + begin: *nonces.start(), + end: *nonces.end(), + dispatch_results: bitvec![u8, Msb0; 1; (nonces.end() - nonces.start() + 1) as _], + } } fn assert_3_messages_confirmation_fails( @@ -361,6 +401,20 @@ mod tests { ); } + #[test] + fn confirm_delivery_fails_if_number_of_dispatch_results_in_entry_is_invalid() { + let mut relayers: VecDeque<_> = unrewarded_relayers(1..=1) + .into_iter() + .chain(unrewarded_relayers(2..=2).into_iter()) + .chain(unrewarded_relayers(3..=3).into_iter()) + .collect(); + relayers[0].messages.dispatch_results.clear(); + assert_eq!( + assert_3_messages_confirmation_fails(3, &relayers), + ReceivalConfirmationResult::InvalidNumberOfDispatchResults, + ); + } + #[test] fn prune_messages_works() { run_test(|| { diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 32d7c65ebcbbb..bc1b92c6b88e7 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } @@ -28,6 +29,7 @@ hex-literal = "0.4" [features] default = ["std"] std = [ + "bitvec/std", "bp-runtime/std", "codec/std", "frame-support/std", diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 8c10989d62011..c877c9cdf2c47 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -20,6 +20,7 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] +use bitvec::prelude::*; use bp_runtime::{BasicOperatingMode, OperatingMode}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; @@ -156,18 +157,68 @@ impl Default for InboundLaneData { } impl InboundLaneData { + fn dispatch_results_encoded_size_hint( + relayers_entries: usize, + message_count: usize, + ) -> Option + where + RelayerId: MaxEncodedLen, + { + // The worst-case scenario for the bitvecs size is the one in which we have as many relayer + // entries as possible taking an extra 1 byte slot with just 1 bit of actual information. + // For example: + // 11111111 1------- + // 11111111 1------- + // 1------- + // 1------- + + // If there are less msgs than relayer entries, in the worst case, each dispatch result + // belongs to a different relayer slot. This means 1 byte for the len prefix and 1 byte + // for the actual data. + if relayers_entries >= message_count { + return relayers_entries.checked_add(message_count) + } + + let msgs_per_byte = 8; + // At the begining each relayer slot has 1 message, using 1 byte + let mut num_result_bytes = relayers_entries; + // Then we add batches of 8 messages to some relayer slot until there are no more messages. + // Each batch takes up 1 more byte. + num_result_bytes = + num_result_bytes.checked_add((message_count - relayers_entries) / msgs_per_byte)?; + + // The len is stored in a `Compact`. `Compact` can store a max value of + // 63 on 1 byte, 16383 on 2 bytes, etc. + let max_len_per_first_byte = 0b0011_1111; + // At the begining each relayer slot uses 1 byte for the len prefix + // (each relayer slot contains 1 message) + let mut num_len_bytes = relayers_entries; + // Then we add batches of 63 messages to as many relayer slots as possible, requiring 2 + // bytes for the `len` prefix. It's hard to believe that we'll need more than 2 bytes + // (more than 16383 messages in 1 relayer slot). + num_len_bytes = num_len_bytes.checked_add(sp_std::cmp::min( + (message_count - relayers_entries) / max_len_per_first_byte, + relayers_entries, + ))?; + + num_result_bytes.checked_add(num_len_bytes) + } + /// Returns approximate size of the struct, given a number of entries in the `relayers` set and /// size of each entry. /// /// Returns `None` if size overflows `usize` limits. - pub fn encoded_size_hint(relayers_entries: usize) -> Option + pub fn encoded_size_hint(relayers_entries: usize, message_count: usize) -> Option where RelayerId: MaxEncodedLen, { let message_nonce_size = MessageNonce::max_encoded_len(); let relayer_id_encoded_size = RelayerId::max_encoded_len(); let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; - let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; + let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?.checked_add( + Self::dispatch_results_encoded_size_hint(relayers_entries, message_count)?, + )?; + relayers_size.checked_add(message_nonce_size) } @@ -175,11 +226,11 @@ impl InboundLaneData { /// `relayers` set and the size of each entry. /// /// Returns `u32::MAX` if size overflows `u32` limits. - pub fn encoded_size_hint_u32(relayers_entries: usize) -> u32 + pub fn encoded_size_hint_u32(relayers_entries: usize, messages_count: usize) -> u32 where RelayerId: MaxEncodedLen, { - Self::encoded_size_hint(relayers_entries) + Self::encoded_size_hint(relayers_entries, messages_count) .and_then(|x| u32::try_from(x).ok()) .unwrap_or(u32::MAX) } @@ -219,6 +270,9 @@ pub struct InboundMessageDetails { pub dispatch_weight: Weight, } +/// Bit vector of message dispatch results. +pub type DispatchResultsBitVec = BitVec; + /// Unrewarded relayer entry stored in the inbound lane data. /// /// This struct represents a continuous range of messages that have been delivered by the same @@ -276,13 +330,19 @@ pub struct DeliveredMessages { pub begin: MessageNonce, /// Nonce of the last message that has been delivered (inclusive). pub end: MessageNonce, + /// Dispatch result (`false`/`true`), returned by the message dispatcher for every + /// message in the `[begin; end]` range. See `dispatch_result` field of the + /// `bp_runtime::messages::MessageDispatchResult` structure for more information. + pub dispatch_results: DispatchResultsBitVec, } impl DeliveredMessages { /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given /// dispatch result. - pub fn new(nonce: MessageNonce) -> Self { - DeliveredMessages { begin: nonce, end: nonce } + pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { + let mut dispatch_results = BitVec::with_capacity(1); + dispatch_results.push(dispatch_result); + DeliveredMessages { begin: nonce, end: nonce, dispatch_results } } /// Return total count of delivered messages. @@ -295,14 +355,25 @@ impl DeliveredMessages { } /// Note new dispatched message. - pub fn note_dispatched_message(&mut self) { + pub fn note_dispatched_message(&mut self, dispatch_result: bool) { self.end += 1; + self.dispatch_results.push(dispatch_result); } /// Returns true if delivered messages contain message with given nonce. pub fn contains_message(&self, nonce: MessageNonce) -> bool { (self.begin..=self.end).contains(&nonce) } + + /// Get dispatch result flag by message nonce. + /// + /// Dispatch result flag must be interpreted using the knowledge of dispatch mechanism + /// at the target chain. See `dispatch_result` field of the + /// `bp_runtime::messages::MessageDispatchResult` structure for more information. + pub fn message_dispatch_result(&self, nonce: MessageNonce) -> Option { + let index = nonce.checked_sub(self.begin)? as usize; + self.dispatch_results.get(index).map(|bit| *bit) + } } /// Gist of `InboundLaneData::relayers` field used by runtime APIs. @@ -414,10 +485,10 @@ mod tests { assert_eq!( total_unrewarded_messages( &vec![ - UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) }, + UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0, true) }, UnrewardedRelayer { relayer: 2, - messages: DeliveredMessages::new(MessageNonce::MAX) + messages: DeliveredMessages::new(MessageNonce::MAX, true) }, ] .into_iter() @@ -438,12 +509,21 @@ mod tests { (13u8, 128u8), ]; for (relayer_entries, messages_count) in test_cases { - let expected_size = InboundLaneData::::encoded_size_hint(relayer_entries as _); + let expected_size = + InboundLaneData::::encoded_size_hint(relayer_entries as _, messages_count as _); let actual_size = InboundLaneData { relayers: (1u8..=relayer_entries) - .map(|i| UnrewardedRelayer { - relayer: i, - messages: DeliveredMessages::new(i as _), + .map(|i| { + let mut entry = UnrewardedRelayer { + relayer: i, + messages: DeliveredMessages::new(i as _, true), + }; + entry.messages.dispatch_results = bitvec![ + u8, Msb0; + 1; + (messages_count / relayer_entries) as _ + ]; + entry }) .collect(), last_confirmed_nonce: messages_count as _, @@ -459,13 +539,16 @@ mod tests { } #[test] - fn contains_result_works() { - let delivered_messages = DeliveredMessages { begin: 100, end: 150 }; + fn message_dispatch_result_works() { + let delivered_messages = + DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![u8, Msb0; 1; 151] }; assert!(!delivered_messages.contains_message(99)); assert!(delivered_messages.contains_message(100)); assert!(delivered_messages.contains_message(150)); assert!(!delivered_messages.contains_message(151)); + + assert_eq!(delivered_messages.message_dispatch_result(125), Some(true)); } #[test] diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 8496b90214c40..da96c4e59cd95 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -90,7 +90,7 @@ pub trait MessageDispatch { type DispatchPayload: Decode; /// Fine-grained result of single message dispatch (for better diagnostic purposes) - type DispatchLevelResult: Clone + sp_std::fmt::Debug + Eq; + type DispatchError: Clone + sp_std::fmt::Debug + Eq; /// Estimate dispatch weight. /// @@ -109,7 +109,7 @@ pub trait MessageDispatch { fn dispatch( relayer_account: &AccountId, message: DispatchMessage, - ) -> MessageDispatchResult; + ) -> MessageDispatchResult; } /// Manages payments that are happening at the target chain during message delivery transaction. @@ -190,7 +190,7 @@ impl MessageDispatch { type DispatchPayload = DispatchPayload; - type DispatchLevelResult = (); + type DispatchError = (); fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX @@ -199,7 +199,7 @@ impl MessageDispatch, - ) -> MessageDispatchResult { - MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } + ) -> MessageDispatchResult { + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_result: Err(()) } } } diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index 9f7c8ab5ca4e3..efbd751816770 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -22,7 +22,7 @@ use scale_info::TypeInfo; /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] -pub struct MessageDispatchResult { +pub struct MessageDispatchResult { /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: /// @@ -31,5 +31,5 @@ pub struct MessageDispatchResult { /// 2) if message has not been dispatched at all. pub unspent_weight: Weight, /// Fine-grained result of single message dispatch (for better diagnostic purposes) - pub dispatch_level_result: DispatchLevelResult, + pub dispatch_result: Result<(), DispatchError>, } From f9d8ececf8cd15413e3463fbae041bd0ece6cbbc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 10 Apr 2023 12:49:15 +0300 Subject: [PATCH 1019/1210] Reject delivery transactions with at least one obsolete message (#2021) * reject delivery transactions with at least one obsolete message * clippy * allow empty delivery transactions with rewards confirmations BUT only when there's no room left in the unrewarded relayers vector * clippy * allow empty delivery transactions if no message slots in unrewarded relayers vector --- bin/runtime-common/src/messages_call_ext.rs | 339 ++++++++++++++++-- bin/runtime-common/src/mock.rs | 8 +- .../src/refund_relayer_extension.rs | 34 +- modules/messages/src/lib.rs | 4 + 4 files changed, 351 insertions(+), 34 deletions(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index e8f992c638910..b299d758a323e 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -17,25 +17,74 @@ use crate::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; -use bp_messages::{LaneId, MessageNonce}; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; +use bp_messages::{InboundLaneData, LaneId, MessageNonce}; +use frame_support::{ + dispatch::CallableCallFor, + traits::{Get, IsSubType}, + RuntimeDebug, +}; use pallet_bridge_messages::{Config, Pallet}; use sp_runtime::transaction_validity::TransactionValidity; +use sp_std::ops::RangeInclusive; /// Generic info about a messages delivery/confirmation proof. #[derive(PartialEq, RuntimeDebug)] pub struct BaseMessagesProofInfo { /// Message lane, used by the call. pub lane_id: LaneId, - /// Nonce of the best message, included in the call. - pub best_bundled_nonce: MessageNonce, + /// Nonces of messages, included in the call. + /// + /// For delivery transaction, it is nonces of bundled messages. For confirmation + /// transaction, it is nonces that are to be confirmed during the call. + pub bundled_range: RangeInclusive, /// Nonce of the best message, stored by this chain before the call is dispatched. + /// + /// For delivery transaction, it is the nonce of best delivered message before the call. + /// For confirmation transaction, it is the nonce of best confirmed message before the call. pub best_stored_nonce: MessageNonce, + /// For message delivery transactions, the state of unrewarded relayers vector before the + /// call is dispatched. + pub unrewarded_relayers: Option, +} + +/// Occupation state of the unrewarded relayers vector. +#[derive(PartialEq, RuntimeDebug)] +#[cfg_attr(test, derive(Default))] +pub struct UnrewardedRelayerOccupation { + /// The number of remaining unoccupied entries for new relayers. + pub free_relayer_slots: MessageNonce, + /// The number of messages that we are ready to accept. + pub free_message_slots: MessageNonce, } impl BaseMessagesProofInfo { + /// Returns true if `bundled_range` cannot be directly appended to the `best_stored_nonce` + /// or if the `bundled_range` is empty (unless we're confirming rewards when unrewarded + /// relayers vector is full). fn is_obsolete(&self) -> bool { - self.best_bundled_nonce <= self.best_stored_nonce + // transactions with zero bundled nonces are not allowed, unless they're message + // delivery transactions, which brings reward confirmations required to unblock + // the lane + if self.bundled_range.is_empty() { + let (free_relayer_slots, free_message_slots) = self + .unrewarded_relayers + .as_ref() + .map(|s| (s.free_relayer_slots, s.free_message_slots)) + .unwrap_or((MessageNonce::MAX, MessageNonce::MAX)); + let empty_transactions_allowed = + // we allow empty transactions when we can't accept delivery from new relayers + free_relayer_slots == 0 || + // or if we can't accept new messages at all + free_message_slots == 0; + if empty_transactions_allowed { + return false + } + + return true + } + + // otherwise we require bundled messages to continue stored range + *self.bundled_range.start() != self.best_stored_nonce + 1 } } @@ -72,12 +121,31 @@ impl, I: 'static> CallHelper { CallInfo::ReceiveMessagesProof(info) => { let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(info.0.lane_id); - inbound_lane_data.last_delivered_nonce() == info.0.best_bundled_nonce + if info.0.bundled_range.is_empty() { + match info.0.unrewarded_relayers { + Some(ref pre_occupation) => { + let post_occupation = + unrewarded_relayers_occupation::(&inbound_lane_data); + // we don't care about `free_relayer_slots` here - it is checked in + // `is_obsolete` and every relayer has delivered at least one message, + // so if relayer slots are released, then message slots are also + // released + return post_occupation.free_message_slots > + pre_occupation.free_message_slots + }, + None => { + // shouldn't happen in practice, given our code + return false + }, + } + } + + inbound_lane_data.last_delivered_nonce() == *info.0.bundled_range.end() }, CallInfo::ReceiveMessagesDeliveryProof(info) => { let outbound_lane_data = pallet_bridge_messages::OutboundLanes::::get(info.0.lane_id); - outbound_lane_data.latest_received_nonce == info.0.best_bundled_nonce + outbound_lane_data.latest_received_nonce == *info.0.bundled_range.end() }, } } @@ -133,8 +201,13 @@ impl< return Some(ReceiveMessagesProofInfo(BaseMessagesProofInfo { lane_id: proof.lane, - best_bundled_nonce: proof.nonces_end, + // we want all messages in this range to be new for us. Otherwise transaction will + // be considered obsolete. + bundled_range: proof.nonces_start..=proof.nonces_end, best_stored_nonce: inbound_lane_data.last_delivered_nonce(), + unrewarded_relayers: Some(unrewarded_relayers_occupation::( + &inbound_lane_data, + )), })) } @@ -152,8 +225,14 @@ impl< return Some(ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { lane_id: proof.lane, - best_bundled_nonce: relayers_state.last_delivered_nonce, + // there's a time frame between message delivery, message confirmation and reward + // confirmation. Because of that, we can't assume that our state has been confirmed + // to the bridged chain. So we are accepting any proof that brings new + // confirmations. + bundled_range: outbound_lane_data.latest_received_nonce + 1..= + relayers_state.last_delivered_nonce, best_stored_nonce: outbound_lane_data.latest_received_nonce, + unrewarded_relayers: None, })) } @@ -211,20 +290,74 @@ impl< } } +/// Returns occupation state of unrewarded relayers vector. +fn unrewarded_relayers_occupation, I: 'static>( + inbound_lane_data: &InboundLaneData, +) -> UnrewardedRelayerOccupation { + UnrewardedRelayerOccupation { + free_relayer_slots: T::MaxUnrewardedRelayerEntriesAtInboundLane::get() + .saturating_sub(inbound_lane_data.relayers.len() as MessageNonce), + free_message_slots: { + // 5 - 0 = 5 ==> 1,2,3,4,5 + // 5 - 3 = 2 ==> 4,5 + let unconfirmed_messages = inbound_lane_data + .last_delivered_nonce() + .saturating_sub(inbound_lane_data.last_confirmed_nonce); + T::MaxUnconfirmedMessagesAtInboundLane::get().saturating_sub(unconfirmed_messages) + }, + } +} + #[cfg(test)] mod tests { + use super::*; use crate::{ messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }, messages_call_ext::MessagesCallSubType, - mock::{TestRuntime, ThisChainRuntimeCall}, + mock::{ + MaxUnconfirmedMessagesAtInboundLane, MaxUnrewardedRelayerEntriesAtInboundLane, + TestRuntime, ThisChainRuntimeCall, + }, }; - use bp_messages::UnrewardedRelayersState; + use bp_messages::{DeliveredMessages, UnrewardedRelayer, UnrewardedRelayersState}; + use sp_std::ops::RangeInclusive; + + fn fill_unrewarded_relayers() { + let mut inbound_lane_state = + pallet_bridge_messages::InboundLanes::::get(LaneId([0, 0, 0, 0])); + for n in 0..MaxUnrewardedRelayerEntriesAtInboundLane::get() { + inbound_lane_state.relayers.push_back(UnrewardedRelayer { + relayer: Default::default(), + messages: DeliveredMessages { begin: n + 1, end: n + 1 }, + }); + } + pallet_bridge_messages::InboundLanes::::insert( + LaneId([0, 0, 0, 0]), + inbound_lane_state, + ); + } + + fn fill_unrewarded_messages() { + let mut inbound_lane_state = + pallet_bridge_messages::InboundLanes::::get(LaneId([0, 0, 0, 0])); + inbound_lane_state.relayers.push_back(UnrewardedRelayer { + relayer: Default::default(), + messages: DeliveredMessages { + begin: 1, + end: MaxUnconfirmedMessagesAtInboundLane::get(), + }, + }); + pallet_bridge_messages::InboundLanes::::insert( + LaneId([0, 0, 0, 0]), + inbound_lane_state, + ); + } fn deliver_message_10() { pallet_bridge_messages::InboundLanes::::insert( - bp_messages::LaneId([0, 0, 0, 0]), + LaneId([0, 0, 0, 0]), bp_messages::InboundLaneData { relayers: Default::default(), last_confirmed_nonce: 10 }, ); } @@ -236,12 +369,13 @@ mod tests { ThisChainRuntimeCall::BridgeMessages( pallet_bridge_messages::Call::::receive_messages_proof { relayer_id_at_bridged_chain: 42, - messages_count: (nonces_end - nonces_start + 1) as u32, + messages_count: nonces_end.checked_sub(nonces_start).map(|x| x + 1).unwrap_or(0) + as u32, dispatch_weight: frame_support::weights::Weight::zero(), proof: FromBridgedChainMessagesProof { bridged_header_hash: Default::default(), storage_proof: vec![], - lane: bp_messages::LaneId([0, 0, 0, 0]), + lane: LaneId([0, 0, 0, 0]), nonces_start, nonces_end, }, @@ -254,8 +388,8 @@ mod tests { #[test] fn extension_rejects_obsolete_messages() { sp_io::TestExternalities::new(Default::default()).execute_with(|| { - // when current best delivered is message#10 and we're trying to deliver message#5 => tx - // is rejected + // when current best delivered is message#10 and we're trying to deliver messages 8..=9 + // => tx is rejected deliver_message_10(); assert!(!validate_message_delivery(8, 9)); }); @@ -264,26 +398,77 @@ mod tests { #[test] fn extension_rejects_same_message() { sp_io::TestExternalities::new(Default::default()).execute_with(|| { - // when current best delivered is message#10 and we're trying to import message#10 => tx - // is rejected + // when current best delivered is message#10 and we're trying to import messages 10..=10 + // => tx is rejected deliver_message_10(); assert!(!validate_message_delivery(8, 10)); }); } #[test] - fn extension_accepts_new_message() { + fn extension_rejects_call_with_some_obsolete_messages() { sp_io::TestExternalities::new(Default::default()).execute_with(|| { - // when current best delivered is message#10 and we're trying to deliver message#15 => - // tx is accepted + // when current best delivered is message#10 and we're trying to deliver messages + // 10..=15 => tx is rejected deliver_message_10(); - assert!(validate_message_delivery(10, 15)); + assert!(!validate_message_delivery(10, 15)); + }); + } + + #[test] + fn extension_rejects_call_with_future_messages() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best delivered is message#10 and we're trying to deliver messages + // 13..=15 => tx is rejected + deliver_message_10(); + assert!(!validate_message_delivery(13, 15)); + }); + } + + #[test] + fn extension_rejects_empty_delivery_with_rewards_confirmations_if_there_are_free_relayer_and_message_slots( + ) { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + deliver_message_10(); + assert!(!validate_message_delivery(10, 9)); + }); + } + + #[test] + fn extension_accepts_empty_delivery_with_rewards_confirmations_if_there_are_no_free_relayer_slots( + ) { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + deliver_message_10(); + fill_unrewarded_relayers(); + assert!(validate_message_delivery(10, 9)); + }); + } + + #[test] + fn extension_accepts_empty_delivery_with_rewards_confirmations_if_there_are_no_free_message_slots( + ) { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + fill_unrewarded_messages(); + assert!(validate_message_delivery( + MaxUnconfirmedMessagesAtInboundLane::get(), + MaxUnconfirmedMessagesAtInboundLane::get() - 1 + )); + }); + } + + #[test] + fn extension_accepts_new_messages() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best delivered is message#10 and we're trying to deliver message 11..=15 + // => tx is accepted + deliver_message_10(); + assert!(validate_message_delivery(11, 15)); }); } fn confirm_message_10() { pallet_bridge_messages::OutboundLanes::::insert( - bp_messages::LaneId([0, 0, 0, 0]), + LaneId([0, 0, 0, 0]), bp_messages::OutboundLaneData { oldest_unpruned_nonce: 0, latest_received_nonce: 10, @@ -298,7 +483,7 @@ mod tests { proof: FromBridgedChainMessagesDeliveryProof { bridged_header_hash: Default::default(), storage_proof: Vec::new(), - lane: bp_messages::LaneId([0, 0, 0, 0]), + lane: LaneId([0, 0, 0, 0]), }, relayers_state: UnrewardedRelayersState { last_delivered_nonce, @@ -330,6 +515,15 @@ mod tests { }); } + #[test] + fn extension_rejects_empty_confirmation_even_if_there_are_no_free_unrewarded_entries() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + confirm_message_10(); + fill_unrewarded_relayers(); + assert!(!validate_message_confirmation(10)); + }); + } + #[test] fn extension_accepts_new_confirmation() { sp_io::TestExternalities::new(Default::default()).execute_with(|| { @@ -339,4 +533,101 @@ mod tests { assert!(validate_message_confirmation(15)); }); } + + fn was_message_delivery_successful( + bundled_range: RangeInclusive, + is_empty: bool, + ) -> bool { + CallHelper::::was_successful(&CallInfo::ReceiveMessagesProof( + ReceiveMessagesProofInfo(BaseMessagesProofInfo { + lane_id: LaneId([0, 0, 0, 0]), + bundled_range, + best_stored_nonce: 0, // doesn't matter for `was_successful` + unrewarded_relayers: Some(UnrewardedRelayerOccupation { + free_relayer_slots: 0, // doesn't matter for `was_successful` + free_message_slots: if is_empty { + 0 + } else { + MaxUnconfirmedMessagesAtInboundLane::get() + }, + }), + }), + )) + } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn was_successful_returns_false_for_failed_reward_confirmation_transaction() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + fill_unrewarded_messages(); + assert!(!was_message_delivery_successful(10..=9, true)); + }); + } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn was_successful_returns_true_for_successful_reward_confirmation_transaction() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + assert!(was_message_delivery_successful(10..=9, true)); + }); + } + + #[test] + fn was_successful_returns_false_for_failed_delivery() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + deliver_message_10(); + assert!(!was_message_delivery_successful(10..=12, false)); + }); + } + + #[test] + fn was_successful_returns_false_for_partially_successful_delivery() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + deliver_message_10(); + assert!(!was_message_delivery_successful(9..=12, false)); + }); + } + + #[test] + fn was_successful_returns_true_for_successful_delivery() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + deliver_message_10(); + assert!(was_message_delivery_successful(9..=10, false)); + }); + } + + fn was_message_confirmation_successful(bundled_range: RangeInclusive) -> bool { + CallHelper::::was_successful(&CallInfo::ReceiveMessagesDeliveryProof( + ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { + lane_id: LaneId([0, 0, 0, 0]), + bundled_range, + best_stored_nonce: 0, // doesn't matter for `was_successful` + unrewarded_relayers: None, + }), + )) + } + + #[test] + fn was_successful_returns_false_for_failed_confirmation() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + confirm_message_10(); + assert!(!was_message_confirmation_successful(10..=12)); + }); + } + + #[test] + fn was_successful_returns_false_for_partially_successful_confirmation() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + confirm_message_10(); + assert!(!was_message_confirmation_successful(9..=12)); + }); + } + + #[test] + fn was_successful_returns_true_for_successful_confirmation() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + confirm_message_10(); + assert!(was_message_confirmation_successful(9..=10)); + }); + } } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index c4c7c2fa8ac92..967682ccbc513 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -33,7 +33,7 @@ use crate::messages::{ }; use bp_header_chain::{ChainWithGrandpa, HeaderChain}; -use bp_messages::{target_chain::ForbidInboundMessages, LaneId}; +use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; use codec::{Decode, Encode}; @@ -126,6 +126,8 @@ parameter_types! { pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); + pub const MaxUnrewardedRelayerEntriesAtInboundLane: MessageNonce = 16; + pub const MaxUnconfirmedMessagesAtInboundLane: MessageNonce = 32; } impl frame_system::Config for TestRuntime { @@ -216,8 +218,8 @@ impl pallet_bridge_messages::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; type ActiveOutboundLanes = ActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = ConstU64<16>; - type MaxUnconfirmedMessagesAtInboundLane = ConstU64<16>; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; type MaximalOutboundPayloadSize = FromThisChainMaximalOutboundPayloadSize; type OutboundPayload = FromThisChainMessagePayload; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 9b1e9a3a1a4d7..ebfc0b3346602 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -461,6 +461,7 @@ mod tests { }, messages_call_ext::{ BaseMessagesProofInfo, ReceiveMessagesDeliveryProofInfo, ReceiveMessagesProofInfo, + UnrewardedRelayerOccupation, }, mock::*, }; @@ -567,7 +568,11 @@ mod tests { bridged_header_hash: Default::default(), storage_proof: vec![], lane: TestLaneId::get(), - nonces_start: best_message, + nonces_start: pallet_bridge_messages::InboundLanes::::get( + TEST_LANE_ID, + ) + .last_delivered_nonce() + + 1, nonces_end: best_message, }, messages_count: 1, @@ -658,8 +663,12 @@ mod tests { MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( BaseMessagesProofInfo { lane_id: TEST_LANE_ID, - best_bundled_nonce: 200, + bundled_range: 101..=200, best_stored_nonce: 100, + unrewarded_relayers: Some(UnrewardedRelayerOccupation { + free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), + free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), + }), }, )), ), @@ -683,8 +692,9 @@ mod tests { MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( BaseMessagesProofInfo { lane_id: TEST_LANE_ID, - best_bundled_nonce: 200, + bundled_range: 101..=200, best_stored_nonce: 100, + unrewarded_relayers: None, }, )), ), @@ -703,8 +713,12 @@ mod tests { MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( BaseMessagesProofInfo { lane_id: TEST_LANE_ID, - best_bundled_nonce: 200, + bundled_range: 101..=200, best_stored_nonce: 100, + unrewarded_relayers: Some(UnrewardedRelayerOccupation { + free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), + free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), + }), }, )), ), @@ -723,8 +737,9 @@ mod tests { MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( BaseMessagesProofInfo { lane_id: TEST_LANE_ID, - best_bundled_nonce: 200, + bundled_range: 101..=200, best_stored_nonce: 100, + unrewarded_relayers: None, }, )), ), @@ -737,8 +752,12 @@ mod tests { call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesProof( ReceiveMessagesProofInfo(BaseMessagesProofInfo { lane_id: TEST_LANE_ID, - best_bundled_nonce: 200, + bundled_range: 101..=200, best_stored_nonce: 100, + unrewarded_relayers: Some(UnrewardedRelayerOccupation { + free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), + free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), + }), }), )), } @@ -750,8 +769,9 @@ mod tests { call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesDeliveryProof( ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo { lane_id: TEST_LANE_ID, - best_bundled_nonce: 200, + bundled_range: 101..=200, best_stored_nonce: 100, + unrewarded_relayers: None, }), )), } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index f425c824b6d8f..bf456b1c0d2c5 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -514,6 +514,10 @@ pub mod pallet { lane_id, ); + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2020 + // we need to refund unused weight (because the inbound lane state may contain + // already confirmed messages and already rewarded relayer entries) + Ok(()) } } From 1a9ad70f85acbd91698641a3b2c0a4b94e8e10a9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 10 Apr 2023 13:43:37 +0300 Subject: [PATCH 1020/1210] Boost message delivery transaction priority (#2023) * reject delivery transactions with at least one obsolete message * clippy * boost priority of message delivery transactions: transaction with more messages has larger priority than the transaction with less messages * apply review suggestion * CallInfo::bundled_messages * validate_does_not_boost_priority_of_message_delivery_transactons_with_too_many_messages * clippy --- bin/millau/runtime/Cargo.toml | 2 +- bin/millau/runtime/src/lib.rs | 2 + .../runtime/src/rialto_parachain_messages.rs | 70 +++++ bin/runtime-common/Cargo.toml | 1 + bin/runtime-common/src/lib.rs | 1 + bin/runtime-common/src/messages_call_ext.rs | 24 +- bin/runtime-common/src/mock.rs | 2 +- bin/runtime-common/src/priority_calculator.rs | 201 +++++++++++++++ .../src/refund_relayer_extension.rs | 243 +++++++++++++----- 9 files changed, 481 insertions(+), 65 deletions(-) create mode 100644 bin/runtime-common/src/priority_calculator.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index ce1484fecad94..e1a55ea6f247e 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -69,7 +69,7 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] -bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } +bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test", "std"] } env_logger = "0.10" static_assertions = "1.1" diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index deff859a81641..4e6f1e43e8c6d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -589,11 +589,13 @@ generate_bridge_reject_obsolete_headers_and_messages! { bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); /// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. +pub type PriorityBoostPerMessage = ConstU64<921_900_294>; pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< Runtime, RefundableParachain, RefundableMessagesLane, ActualFeeRefund, + PriorityBoostPerMessage, StrBridgeRefundRialtoPara2000Lane0Msgs, >; diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index b3d33c1cefd70..bef8a281188e8 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -137,3 +137,73 @@ impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { XCM_LANE } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + PriorityBoostPerMessage, RialtoGrandpaInstance, Runtime, + WithRialtoParachainMessagesInstance, + }; + + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, + }, + }; + + #[test] + fn ensure_millau_message_lane_weights_are_correct() { + check_message_lane_weights::( + bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE, + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: RialtoGrandpaInstance, + with_bridged_chain_messages_instance: WithRialtoParachainMessagesInstance, + bridge: WithRialtoParachainMessageBridge, + this_chain: bp_millau::Millau, + bridged_chain: bp_rialto::Rialto, + ); + + assert_complete_bridge_constants::< + Runtime, + RialtoGrandpaInstance, + WithRialtoParachainMessagesInstance, + WithRialtoParachainMessageBridge, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_millau::BlockLength::get(), + block_weights: bp_millau::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::RIALTO_PARACHAIN_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME, + }, + }); + + bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< + Runtime, + WithRialtoParachainMessagesInstance, + PriorityBoostPerMessage, + >(1_000_000); + } +} diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 3db4ae9abca6e..9d616bf588e45 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -47,6 +47,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "maste [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } +bitvec = { version = "1", features = ["alloc"] } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index ed486c04abccb..e8a2d2470fa19 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -30,6 +30,7 @@ pub mod messages_benchmarking; pub mod messages_call_ext; pub mod messages_xcm_extension; pub mod parachains_benchmarking; +pub mod priority_calculator; pub mod refund_relayer_extension; mod messages_generation; diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index b299d758a323e..8d53c4844c80f 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -104,6 +104,22 @@ pub enum CallInfo { ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo), } +impl CallInfo { + /// Returns number of messages, bundled with this transaction. + pub fn bundled_messages(&self) -> MessageNonce { + let bundled_range = match *self { + Self::ReceiveMessagesProof(ref info) => &info.0.bundled_range, + Self::ReceiveMessagesDeliveryProof(ref info) => &info.0.bundled_range, + }; + + bundled_range + .end() + .checked_sub(*bundled_range.start()) + .map(|d| d.saturating_add(1)) + .unwrap_or(0) + } +} + /// Helper struct that provides methods for working with a call supported by `CallInfo`. pub struct CallHelper, I: 'static> { pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, @@ -321,6 +337,7 @@ mod tests { TestRuntime, ThisChainRuntimeCall, }, }; + use bitvec::prelude::*; use bp_messages::{DeliveredMessages, UnrewardedRelayer, UnrewardedRelayersState}; use sp_std::ops::RangeInclusive; @@ -330,7 +347,11 @@ mod tests { for n in 0..MaxUnrewardedRelayerEntriesAtInboundLane::get() { inbound_lane_state.relayers.push_back(UnrewardedRelayer { relayer: Default::default(), - messages: DeliveredMessages { begin: n + 1, end: n + 1 }, + messages: DeliveredMessages { + begin: n + 1, + end: n + 1, + dispatch_results: bitvec![u8, Msb0; 1; 1], + }, }); } pallet_bridge_messages::InboundLanes::::insert( @@ -347,6 +368,7 @@ mod tests { messages: DeliveredMessages { begin: 1, end: MaxUnconfirmedMessagesAtInboundLane::get(), + dispatch_results: bitvec![u8, Msb0; 1; MaxUnconfirmedMessagesAtInboundLane::get() as _], }, }); pallet_bridge_messages::InboundLanes::::insert( diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 967682ccbc513..036813f6fd514 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -127,7 +127,7 @@ parameter_types! { pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); pub const MaxUnrewardedRelayerEntriesAtInboundLane: MessageNonce = 16; - pub const MaxUnconfirmedMessagesAtInboundLane: MessageNonce = 32; + pub const MaxUnconfirmedMessagesAtInboundLane: MessageNonce = 1_000; } impl frame_system::Config for TestRuntime { diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs new file mode 100644 index 0000000000000..590de05fb1c66 --- /dev/null +++ b/bin/runtime-common/src/priority_calculator.rs @@ -0,0 +1,201 @@ +// Copyright 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 . + +//! Bridge transaction priority calculator. +//! +//! We want to prioritize message delivery transactions with more messages over +//! transactions with less messages. That's because we reject delivery transactions +//! if it contains already delivered message. And if some transaction delivers +//! single message with nonce `N`, then the transaction with nonces `N..=N+100` will +//! be rejected. This can lower bridge throughput down to one message per block. + +use bp_messages::MessageNonce; +use frame_support::traits::Get; +use sp_runtime::transaction_validity::TransactionPriority; + +// reexport everything from `integrity_tests` module +pub use integrity_tests::*; + +/// Compute priority boost for message delivery transaction that delivers +/// given number of messages. +pub fn compute_priority_boost( + messages: MessageNonce, +) -> TransactionPriority +where + PriorityBoostPerMessage: Get, +{ + // we don't want any boost for transaction with single message => minus one + PriorityBoostPerMessage::get().saturating_mul(messages - 1) +} + +#[cfg(not(feature = "integrity-test"))] +mod integrity_tests {} + +#[cfg(feature = "integrity-test")] +mod integrity_tests { + use super::compute_priority_boost; + + use bp_messages::MessageNonce; + use bp_runtime::PreComputedSize; + use frame_support::{ + dispatch::{DispatchClass, DispatchInfo, Dispatchable, Pays, PostDispatchInfo}, + traits::Get, + }; + use pallet_bridge_messages::WeightInfoExt; + use pallet_transaction_payment::OnChargeTransaction; + use sp_runtime::{ + traits::{UniqueSaturatedInto, Zero}, + transaction_validity::TransactionPriority, + FixedPointOperand, SaturatedConversion, Saturating, + }; + + type BalanceOf = + <::OnChargeTransaction as OnChargeTransaction< + T, + >>::Balance; + + /// Ensures that the value of `PriorityBoostPerMessage` matches the value of + /// `tip_boost_per_message`. + /// + /// We want two transactions, `TX1` with `N` messages and `TX2` with `N+1` messages, have almost + /// the same priority if we'll add `tip_boost_per_message` tip to the `TX1`. We want to be sure + /// that if we add plain `PriorityBoostPerMessage` priority to `TX1`, the priority will be close + /// to `TX2` as well. + pub fn ensure_priority_boost_is_sane( + tip_boost_per_message: BalanceOf, + ) where + Runtime: + pallet_transaction_payment::Config + pallet_bridge_messages::Config, + MessagesInstance: 'static, + PriorityBoostPerMessage: Get, + Runtime::RuntimeCall: Dispatchable, + BalanceOf: Send + Sync + FixedPointOperand, + { + let priority_boost_per_message = PriorityBoostPerMessage::get(); + let maximal_messages_in_delivery_transaction = + Runtime::MaxUnconfirmedMessagesAtInboundLane::get(); + for messages in 1..=maximal_messages_in_delivery_transaction { + let base_priority = estimate_message_delivery_transaction_priority::< + Runtime, + MessagesInstance, + >(messages, Zero::zero()); + let priority_boost = compute_priority_boost::(messages); + let priority_with_boost = base_priority + priority_boost; + + let tip = tip_boost_per_message.saturating_mul((messages - 1).unique_saturated_into()); + let priority_with_tip = + estimate_message_delivery_transaction_priority::(1, tip); + + const ERROR_MARGIN: TransactionPriority = 5; // 5% + if priority_with_boost.abs_diff(priority_with_tip).saturating_mul(100) / + priority_with_tip > + ERROR_MARGIN + { + panic!( + "The PriorityBoostPerMessage value ({}) must be fixed to: {}", + priority_boost_per_message, + compute_priority_boost_per_message::( + tip_boost_per_message + ), + ); + } + } + } + + /// Compute priority boost that we give to message delivery transaction for additional message. + #[cfg(feature = "integrity-test")] + fn compute_priority_boost_per_message( + tip_boost_per_message: BalanceOf, + ) -> TransactionPriority + where + Runtime: + pallet_transaction_payment::Config + pallet_bridge_messages::Config, + MessagesInstance: 'static, + Runtime::RuntimeCall: Dispatchable, + BalanceOf: Send + Sync + FixedPointOperand, + { + // esimate priority of transaction that delivers one message and has large tip + let maximal_messages_in_delivery_transaction = + Runtime::MaxUnconfirmedMessagesAtInboundLane::get(); + let small_with_tip_priority = + estimate_message_delivery_transaction_priority::( + 1, + tip_boost_per_message + .saturating_mul(maximal_messages_in_delivery_transaction.saturated_into()), + ); + // estimate priority of transaction that delivers maximal number of messages, but has no tip + let large_without_tip_priority = estimate_message_delivery_transaction_priority::< + Runtime, + MessagesInstance, + >(maximal_messages_in_delivery_transaction, Zero::zero()); + + small_with_tip_priority + .saturating_sub(large_without_tip_priority) + .saturating_div(maximal_messages_in_delivery_transaction - 1) + } + + /// Estimate message delivery transaction priority. + #[cfg(feature = "integrity-test")] + fn estimate_message_delivery_transaction_priority( + messages: MessageNonce, + tip: BalanceOf, + ) -> TransactionPriority + where + Runtime: + pallet_transaction_payment::Config + pallet_bridge_messages::Config, + MessagesInstance: 'static, + Runtime::RuntimeCall: Dispatchable, + BalanceOf: Send + Sync + FixedPointOperand, + { + // just an estimation of extra transaction bytes that are added to every transaction + // (including signature, signed extensions extra and etc + in our case it includes + // all call arguments extept the proof itself) + let base_tx_size = 512; + // let's say we are relaying similar small messages and for every message we add more trie + // nodes to the proof (x0.5 because we expect some nodes to be reused) + let estimated_message_size = 512; + // let's say all our messages have the same dispatch weight + let estimated_message_dispatch_weight = + Runtime::WeightInfo::message_dispatch_weight(estimated_message_size); + // messages proof argument size is (for every message) messages size + some additional + // trie nodes. Some of them are reused by different messages, so let's take 2/3 of default + // "overhead" constant + let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size() + .saturating_mul(2) + .saturating_div(3) + .saturating_add(estimated_message_size) + .saturating_mul(messages as _); + + // finally we are able to estimate transaction size and weight + let transaction_size = base_tx_size.saturating_add(messages_proof_size); + let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight( + &PreComputedSize(transaction_size as _), + messages as _, + estimated_message_dispatch_weight.saturating_mul(messages), + ); + + pallet_transaction_payment::ChargeTransactionPayment::::get_priority( + &DispatchInfo { + weight: transaction_weight, + class: DispatchClass::Normal, + pays_fee: Pays::Yes, + }, + transaction_size as _, + tip, + Zero::zero(), + ) + } +} diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index ebfc0b3346602..83eafa1a36a2d 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -46,7 +46,9 @@ use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as Uti use scale_info::TypeInfo; use sp_runtime::{ traits::{DispatchInfoOf, Get, PostDispatchInfoOf, SignedExtension, Zero}, - transaction_validity::{TransactionValidity, TransactionValidityError, ValidTransaction}, + transaction_validity::{ + TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder, + }, DispatchResult, FixedPointOperand, }; use sp_std::{marker::PhantomData, vec, vec::Vec}; @@ -58,7 +60,7 @@ type CallOf = ::RuntimeCall; /// Trait identifying a bridged parachain. A relayer might be refunded for delivering messages /// coming from this parachain. -trait RefundableParachainId { +pub trait RefundableParachainId { /// The instance of the bridge parachains pallet. type Instance; /// The parachain Id. @@ -78,7 +80,7 @@ where /// Trait identifying a bridged messages lane. A relayer might be refunded for delivering messages /// coming from this lane. -trait RefundableMessagesLaneId { +pub trait RefundableMessagesLaneId { /// The instance of the bridge messages pallet. type Instance; /// The messages lane id. @@ -201,36 +203,75 @@ impl CallInfo { RuntimeDebugNoBound, TypeInfo, )] -#[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Id))] -pub struct RefundBridgedParachainMessages( - PhantomData<(Runtime, Para, Msgs, Refund, Id)>, +#[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Priority, Id))] +pub struct RefundBridgedParachainMessages( + PhantomData<(Runtime, Para, Msgs, Refund, Priority, Id)>, ); -impl - RefundBridgedParachainMessages +impl + RefundBridgedParachainMessages where - Runtime: UtilityConfig>, - CallOf: IsSubType, Runtime>>, + Self: 'static + Send + Sync, + Runtime: UtilityConfig> + + BoundedBridgeGrandpaConfig + + ParachainsConfig + + MessagesConfig, + Para: RefundableParachainId, + Msgs: RefundableMessagesLaneId, + CallOf: Dispatchable + + IsSubType, Runtime>> + + GrandpaCallSubType + + ParachainsCallSubType + + MessagesCallSubType, { - fn expand_call<'a>(&self, call: &'a CallOf) -> Option>> { - let calls = match call.is_sub_type() { - Some(UtilityCall::::batch_all { ref calls }) => { - if calls.len() > 3 { - return None - } - - calls.iter().collect() - }, - Some(_) => return None, + fn expand_call<'a>(&self, call: &'a CallOf) -> Vec<&'a CallOf> { + match call.is_sub_type() { + Some(UtilityCall::::batch_all { ref calls }) if calls.len() <= 3 => + calls.iter().collect(), + Some(_) => vec![], None => vec![call], - }; + } + } + + fn parse_and_check_for_obsolete_call( + &self, + call: &CallOf, + ) -> Result, TransactionValidityError> { + let calls = self.expand_call(call); + let total_calls = calls.len(); + let mut calls = calls.into_iter().map(Self::check_obsolete_call).rev(); + + let msgs_call = calls.next().transpose()?.and_then(|c| c.call_info_for(Msgs::Id::get())); + let para_finality_call = calls + .next() + .transpose()? + .and_then(|c| c.submit_parachain_heads_info_for(Para::Id::get())); + let relay_finality_call = + calls.next().transpose()?.and_then(|c| c.submit_finality_proof_info()); + + Ok(match (total_calls, relay_finality_call, para_finality_call, msgs_call) { + (3, Some(relay_finality_call), Some(para_finality_call), Some(msgs_call)) => Some( + CallInfo::AllFinalityAndMsgs(relay_finality_call, para_finality_call, msgs_call), + ), + (2, None, Some(para_finality_call), Some(msgs_call)) => + Some(CallInfo::ParachainFinalityAndMsgs(para_finality_call, msgs_call)), + (1, None, None, Some(msgs_call)) => Some(CallInfo::Msgs(msgs_call)), + _ => None, + }) + } - Some(calls) + fn check_obsolete_call( + call: &CallOf, + ) -> Result<&CallOf, TransactionValidityError> { + call.check_obsolete_submit_finality_proof()?; + call.check_obsolete_submit_parachain_heads()?; + call.check_obsolete_call()?; + Ok(call) } } -impl SignedExtension - for RefundBridgedParachainMessages +impl SignedExtension + for RefundBridgedParachainMessages where Self: 'static + Send + Sync, Runtime: UtilityConfig> @@ -241,6 +282,7 @@ where Para: RefundableParachainId, Msgs: RefundableMessagesLaneId, Refund: RefundCalculator, + Priority: Get, Id: StaticStrProvider, CallOf: Dispatchable + IsSubType, Runtime>> @@ -265,46 +307,46 @@ where _info: &DispatchInfoOf, _len: usize, ) -> TransactionValidity { - if let Some(calls) = self.expand_call(call) { - for nested_call in calls { - nested_call.check_obsolete_submit_finality_proof()?; - nested_call.check_obsolete_submit_parachain_heads()?; - nested_call.check_obsolete_call()?; + // this is the only relevant line of code for the `pre_dispatch` + // + // we're not calling `validato` from `pre_dispatch` directly because of performance + // reasons, so if you're adding some code that may fail here, please check if it needs + // to be added to the `pre_dispatch` as well + let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + + // the following code just plays with transaction priority and never returns an error + let mut valid_transaction = ValidTransactionBuilder::default(); + if let Some(parsed_call) = parsed_call { + // we give delivery transactions some boost, that depends on number of messages inside + let messages_call_info = parsed_call.messages_call_info(); + if let MessagesCallInfo::ReceiveMessagesProof(_) = messages_call_info { + // compute total number of messages in transaction + let bundled_messages = messages_call_info.bundled_messages(); + + // a quick check to avoid invalid high-priority transactions + if bundled_messages <= Runtime::MaxUnconfirmedMessagesAtInboundLane::get() { + let priority_boost = crate::priority_calculator::compute_priority_boost::< + Priority, + >(bundled_messages); + valid_transaction = valid_transaction.priority(priority_boost); + } } } - Ok(ValidTransaction::default()) + valid_transaction.build() } fn pre_dispatch( self, who: &Self::AccountId, call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + _info: &DispatchInfoOf, + _len: usize, ) -> Result { - // reject batch transactions with obsolete headers - self.validate(who, call, info, len).map(drop)?; - - // Try to check if the tx matches one of types we support. - let parse_call = || { - let mut calls = self.expand_call(call)?.into_iter(); - match calls.len() { - 3 => Some(CallInfo::AllFinalityAndMsgs( - calls.next()?.submit_finality_proof_info()?, - calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, - calls.next()?.call_info_for(Msgs::Id::get())?, - )), - 2 => Some(CallInfo::ParachainFinalityAndMsgs( - calls.next()?.submit_parachain_heads_info_for(Para::Id::get())?, - calls.next()?.call_info_for(Msgs::Id::get())?, - )), - 1 => Some(CallInfo::Msgs(calls.next()?.call_info_for(Msgs::Id::get())?)), - _ => None, - } - }; + // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) + let parsed_call = self.parse_and_check_for_obsolete_call(call)?; - Ok(parse_call().map(|call_info| { + Ok(parsed_call.map(|call_info| { log::trace!( target: "runtime::bridge", "{} from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", @@ -475,14 +517,24 @@ mod tests { use pallet_bridge_messages::Call as MessagesCall; use pallet_bridge_parachains::{Call as ParachainsCall, RelayBlockHash}; use sp_runtime::{ - traits::Header as HeaderT, transaction_validity::InvalidTransaction, DispatchError, + traits::{ConstU64, Header as HeaderT}, + transaction_validity::{InvalidTransaction, ValidTransaction}, + DispatchError, }; parameter_types! { TestParachain: u32 = 1000; pub TestLaneId: LaneId = TEST_LANE_ID; - pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::ThisChain); - pub MsgDeliveryProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new(TEST_LANE_ID, TEST_BRIDGED_CHAIN_ID, RewardsAccountOwner::BridgedChain); + pub MsgProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new( + TEST_LANE_ID, + TEST_BRIDGED_CHAIN_ID, + RewardsAccountOwner::ThisChain, + ); + pub MsgDeliveryProofsRewardsAccount: RewardsAccountParams = RewardsAccountParams::new( + TEST_LANE_ID, + TEST_BRIDGED_CHAIN_ID, + RewardsAccountOwner::BridgedChain, + ); } bp_runtime::generate_static_str_provider!(TestExtension); @@ -491,6 +543,7 @@ mod tests { RefundableParachain<(), TestParachain>, RefundableMessagesLane<(), TestLaneId>, ActualFeeRefund, + ConstU64<1>, StrTestExtension, >; @@ -831,32 +884,98 @@ mod tests { ) } + #[test] + fn validate_boosts_priority_of_message_delivery_transactons() { + run_test(|| { + initialize_environment(100, 100, Default::default(), 100); + + let priority_of_100_messages_delivery = + run_validate(message_delivery_call(200)).unwrap().priority; + let priority_of_200_messages_delivery = + run_validate(message_delivery_call(300)).unwrap().priority; + assert!( + priority_of_200_messages_delivery > priority_of_100_messages_delivery, + "Invalid priorities: {} for 200 messages vs {} for 100 messages", + priority_of_200_messages_delivery, + priority_of_100_messages_delivery, + ); + + let priority_of_100_messages_confirmation = + run_validate(message_confirmation_call(200)).unwrap().priority; + let priority_of_200_messages_confirmation = + run_validate(message_confirmation_call(300)).unwrap().priority; + assert_eq!( + priority_of_100_messages_confirmation, + priority_of_200_messages_confirmation + ); + }); + } + + #[test] + fn validate_does_not_boost_priority_of_message_delivery_transactons_with_too_many_messages() { + run_test(|| { + initialize_environment(100, 100, Default::default(), 100); + + let priority_of_max_messages_delivery = run_validate(message_delivery_call( + 100 + MaxUnconfirmedMessagesAtInboundLane::get(), + )) + .unwrap() + .priority; + let priority_of_more_than_max_messages_delivery = run_validate(message_delivery_call( + 100 + MaxUnconfirmedMessagesAtInboundLane::get() + 1, + )) + .unwrap() + .priority; + + assert!( + priority_of_max_messages_delivery > priority_of_more_than_max_messages_delivery, + "Invalid priorities: {} for MAX messages vs {} for MAX+1 messages", + priority_of_max_messages_delivery, + priority_of_more_than_max_messages_delivery, + ); + }); + } + #[test] fn validate_allows_non_obsolete_transactions() { run_test(|| { initialize_environment(100, 100, Default::default(), 100); - assert_eq!(run_validate(message_delivery_call(200)), Ok(ValidTransaction::default()),); + fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { + run_validate(call).map(|mut tx| { + tx.priority = 0; + tx + }) + } + assert_eq!( - run_validate(message_confirmation_call(200)), + run_validate_ignore_priority(message_delivery_call(200)), + Ok(ValidTransaction::default()), + ); + assert_eq!( + run_validate_ignore_priority(message_confirmation_call(200)), Ok(ValidTransaction::default()), ); assert_eq!( - run_validate(parachain_finality_and_delivery_batch_call(200, 200)), + run_validate_ignore_priority(parachain_finality_and_delivery_batch_call(200, 200)), Ok(ValidTransaction::default()), ); assert_eq!( - run_validate(parachain_finality_and_confirmation_batch_call(200, 200)), + run_validate_ignore_priority(parachain_finality_and_confirmation_batch_call( + 200, 200 + )), Ok(ValidTransaction::default()), ); assert_eq!( - run_validate(all_finality_and_delivery_batch_call(200, 200, 200)), + run_validate_ignore_priority(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(ValidTransaction::default()), ); assert_eq!( - run_validate(all_finality_and_confirmation_batch_call(200, 200, 200)), + run_validate_ignore_priority(all_finality_and_confirmation_batch_call( + 200, 200, 200 + )), Ok(ValidTransaction::default()), ); }); From 597cc19ddf831485be14ed5634dcca52abad1be2 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 12 Apr 2023 09:52:55 +0300 Subject: [PATCH 1021/1210] refund extra weight in receive_messages_delivery_proof call (#2031) --- modules/messages/src/lib.rs | 120 +++++++++++++++++------- modules/messages/src/mock.rs | 10 +- modules/relayers/src/payment_adapter.rs | 7 +- primitives/messages/src/source_chain.rs | 10 +- 4 files changed, 104 insertions(+), 43 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index bf456b1c0d2c5..3404ba0b219c0 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -63,7 +63,7 @@ use bp_messages::{ MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, }; -use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, Size}; +use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; use sp_runtime::{traits::UniqueSaturatedFrom, SaturatedConversion}; @@ -423,10 +423,11 @@ pub mod pallet { pub fn receive_messages_delivery_proof( origin: OriginFor, proof: MessagesDeliveryProofOf, - relayers_state: UnrewardedRelayersState, - ) -> DispatchResult { + mut relayers_state: UnrewardedRelayersState, + ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; + let proof_size = proof.size(); let confirmation_relayer = ensure_signed(origin)?; let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof) .map_err(|err| { @@ -499,13 +500,27 @@ pub mod pallet { }); // if some new messages have been confirmed, reward relayers - T::DeliveryConfirmationPayments::pay_reward( + let actually_rewarded_relayers = T::DeliveryConfirmationPayments::pay_reward( lane_id, lane_data.relayers, &confirmation_relayer, &received_range, ); - } + + // update relayers state with actual numbers to compute actual weight below + relayers_state.unrewarded_relayer_entries = sp_std::cmp::min( + relayers_state.unrewarded_relayer_entries, + actually_rewarded_relayers, + ); + relayers_state.total_messages = sp_std::cmp::min( + relayers_state.total_messages, + received_range + .end() + .checked_sub(*received_range.start()) + .and_then(|x| x.checked_add(1)) + .unwrap_or(MessageNonce::MAX), + ); + }; log::trace!( target: LOG_TARGET, @@ -514,11 +529,15 @@ pub mod pallet { lane_id, ); - // TODO: https://github.com/paritytech/parity-bridges-common/issues/2020 - // we need to refund unused weight (because the inbound lane state may contain - // already confirmed messages and already rewarded relayer entries) + // because of lags, the inbound lane state (`lane_data`) may have entries for + // already rewarded relayers and messages (if all entries are duplicated, then + // this transaction must be filtered out by our signed extension) + let actual_weight = T::WeightInfo::receive_messages_delivery_proof_weight( + &PreComputedSize(proof_size as usize), + &relayers_state, + ); - Ok(()) + Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) } } @@ -940,8 +959,9 @@ mod tests { message, message_payload, run_test, unrewarded_relayer, AccountId, DbWeight, RuntimeEvent as TestEvent, RuntimeOrigin, TestDeliveryConfirmationPayments, TestDeliveryPayments, TestMessagesDeliveryProof, TestMessagesProof, TestRelayer, - TestRuntime, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, - TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, + TestRuntime, TestWeightInfo, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, + REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, + TEST_RELAYER_B, }; use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState}; use bp_test_utils::generate_owned_bridge_module_tests; @@ -1398,50 +1418,78 @@ mod tests { )); // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A - assert_ok!(Pallet::::receive_messages_delivery_proof( + let single_message_delivery_proof = TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)].into_iter().collect(), + ..Default::default() + }, + ))); + let single_message_delivery_proof_size = single_message_delivery_proof.size(); + let result = Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), - TestMessagesDeliveryProof(Ok(( - TEST_LANE_ID, - InboundLaneData { - relayers: vec![unrewarded_relayer(1, 1, TEST_RELAYER_A)] - .into_iter() - .collect(), - ..Default::default() - } - ))), + single_message_delivery_proof, UnrewardedRelayersState { unrewarded_relayer_entries: 1, total_messages: 1, last_delivered_nonce: 1, ..Default::default() }, - )); + ); + assert_ok!(result); + assert_eq!( + result.unwrap().actual_weight.unwrap(), + TestWeightInfo::receive_messages_delivery_proof_weight( + &PreComputedSize(single_message_delivery_proof_size as _), + &UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + ) + ); assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1)); assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1)); // this reports delivery of both message 1 and message 2 => reward is paid only to // TEST_RELAYER_B - assert_ok!(Pallet::::receive_messages_delivery_proof( + let two_messages_delivery_proof = TestMessagesDeliveryProof(Ok(( + TEST_LANE_ID, + InboundLaneData { + relayers: vec![ + unrewarded_relayer(1, 1, TEST_RELAYER_A), + unrewarded_relayer(2, 2, TEST_RELAYER_B), + ] + .into_iter() + .collect(), + ..Default::default() + }, + ))); + let two_messages_delivery_proof_size = two_messages_delivery_proof.size(); + let result = Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), - TestMessagesDeliveryProof(Ok(( - TEST_LANE_ID, - InboundLaneData { - relayers: vec![ - unrewarded_relayer(1, 1, TEST_RELAYER_A), - unrewarded_relayer(2, 2, TEST_RELAYER_B) - ] - .into_iter() - .collect(), - ..Default::default() - } - ))), + two_messages_delivery_proof, UnrewardedRelayersState { unrewarded_relayer_entries: 2, total_messages: 2, last_delivered_nonce: 2, ..Default::default() }, - )); + ); + assert_ok!(result); + // even though the pre-dispatch weight was for two messages, the actual weight is + // for single message only + assert_eq!( + result.unwrap().actual_weight.unwrap(), + TestWeightInfo::receive_messages_delivery_proof_weight( + &PreComputedSize(two_messages_delivery_proof_size as _), + &UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }, + ) + ); assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1)); assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1)); }); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index be4072f9278f5..d16fd4138fc38 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -148,9 +148,12 @@ parameter_types! { pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID, TEST_LANE_ID_2]; } +/// weights of messages pallet calls we use in tests. +pub type TestWeightInfo = (); + impl Config for TestRuntime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type WeightInfo = TestWeightInfo; type ActiveOutboundLanes = ActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -381,12 +384,15 @@ impl DeliveryConfirmationPayments for TestDeliveryConfirmationPayment messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, received_range: &RangeInclusive, - ) { + ) -> MessageNonce { let relayers_rewards = calc_relayers_rewards(messages_relayers, received_range); + let rewarded_relayers = relayers_rewards.len(); for (relayer, reward) in &relayers_rewards { let key = (b":relayer-reward:", relayer, reward).encode(); frame_support::storage::unhashed::put(&key, &true); } + + rewarded_relayers as _ } } diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index 2752044958b4f..a9536cfc0275f 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -20,7 +20,7 @@ use crate::{Config, Pallet}; use bp_messages::{ source_chain::{DeliveryConfirmationPayments, RelayersRewards}, - LaneId, + LaneId, MessageNonce, }; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use frame_support::{sp_runtime::SaturatedConversion, traits::Get}; @@ -47,9 +47,10 @@ where messages_relayers: VecDeque>, confirmation_relayer: &T::AccountId, received_range: &RangeInclusive, - ) { + ) -> MessageNonce { let relayers_rewards = bp_messages::calc_relayers_rewards::(messages_relayers, received_range); + let rewarded_relayers = relayers_rewards.len(); register_relayers_rewards::( confirmation_relayer, @@ -61,6 +62,8 @@ where ), DeliveryReward::get(), ); + + rewarded_relayers as _ } } diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 83f27843d6389..394a934171fea 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -98,12 +98,14 @@ pub trait DeliveryConfirmationPayments { /// /// The implementation may also choose to pay reward to the `confirmation_relayer`, which is /// a relayer that has submitted delivery confirmation transaction. + /// + /// Returns number of actually rewarded relayers. fn pay_reward( lane_id: LaneId, messages_relayers: VecDeque>, confirmation_relayer: &AccountId, received_range: &RangeInclusive, - ); + ) -> MessageNonce; } impl DeliveryConfirmationPayments for () { @@ -114,8 +116,9 @@ impl DeliveryConfirmationPayments for () { _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, _received_range: &RangeInclusive, - ) { + ) -> MessageNonce { // this implementation is not rewarding relayers at all + 0 } } @@ -202,6 +205,7 @@ impl DeliveryConfirmationPayments for ForbidOutboundMessag _messages_relayers: VecDeque>, _confirmation_relayer: &AccountId, _received_range: &RangeInclusive, - ) { + ) -> MessageNonce { + 0 } } From 3147fcb1229dd0e3d8044e75ca366a5d64bbc36e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 Apr 2023 10:15:30 +0300 Subject: [PATCH 1022/1210] Impl review suggestions from #2021 (#2036) * unrewarded_relayers for ReceiveMessagesProofInfo only * simplify return * removed comment * appends_to_stored_nonce --- bin/runtime-common/src/messages_call_ext.rs | 137 +++++++++--------- .../src/refund_relayer_extension.rs | 47 +++--- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 8d53c4844c80f..b208a9d02b422 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -42,9 +42,13 @@ pub struct BaseMessagesProofInfo { /// For delivery transaction, it is the nonce of best delivered message before the call. /// For confirmation transaction, it is the nonce of best confirmed message before the call. pub best_stored_nonce: MessageNonce, - /// For message delivery transactions, the state of unrewarded relayers vector before the - /// call is dispatched. - pub unrewarded_relayers: Option, +} + +impl BaseMessagesProofInfo { + /// Returns true if `bundled_range` continues the `0..=best_stored_nonce` range. + fn appends_to_stored_nonce(&self) -> bool { + *self.bundled_range.start() == self.best_stored_nonce + 1 + } } /// Occupation state of the unrewarded relayers vector. @@ -57,45 +61,52 @@ pub struct UnrewardedRelayerOccupation { pub free_message_slots: MessageNonce, } -impl BaseMessagesProofInfo { - /// Returns true if `bundled_range` cannot be directly appended to the `best_stored_nonce` - /// or if the `bundled_range` is empty (unless we're confirming rewards when unrewarded - /// relayers vector is full). +/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. +#[derive(PartialEq, RuntimeDebug)] +pub struct ReceiveMessagesProofInfo { + /// Base messages proof info + pub base: BaseMessagesProofInfo, + /// State of unrewarded relayers vector. + pub unrewarded_relayers: UnrewardedRelayerOccupation, +} + +impl ReceiveMessagesProofInfo { + /// Returns true if: + /// + /// - either inbound lane is ready to accept bundled messages; + /// + /// - or there are no bundled messages, but the inbound lane is blocked by too many unconfirmed + /// messages and/or unrewarded relayers. fn is_obsolete(&self) -> bool { // transactions with zero bundled nonces are not allowed, unless they're message // delivery transactions, which brings reward confirmations required to unblock // the lane - if self.bundled_range.is_empty() { - let (free_relayer_slots, free_message_slots) = self - .unrewarded_relayers - .as_ref() - .map(|s| (s.free_relayer_slots, s.free_message_slots)) - .unwrap_or((MessageNonce::MAX, MessageNonce::MAX)); + if self.base.bundled_range.is_empty() { let empty_transactions_allowed = // we allow empty transactions when we can't accept delivery from new relayers - free_relayer_slots == 0 || + self.unrewarded_relayers.free_relayer_slots == 0 || // or if we can't accept new messages at all - free_message_slots == 0; - if empty_transactions_allowed { - return false - } + self.unrewarded_relayers.free_message_slots == 0; - return true + return !empty_transactions_allowed } // otherwise we require bundled messages to continue stored range - *self.bundled_range.start() != self.best_stored_nonce + 1 + !self.base.appends_to_stored_nonce() } } -/// Info about a `ReceiveMessagesProof` call which tries to update a single lane. -#[derive(PartialEq, RuntimeDebug)] -pub struct ReceiveMessagesProofInfo(pub BaseMessagesProofInfo); - /// Info about a `ReceiveMessagesDeliveryProof` call which tries to update a single lane. #[derive(PartialEq, RuntimeDebug)] pub struct ReceiveMessagesDeliveryProofInfo(pub BaseMessagesProofInfo); +impl ReceiveMessagesDeliveryProofInfo { + /// Returns true if outbound lane is ready to accept confirmations of bundled messages. + fn is_obsolete(&self) -> bool { + self.0.bundled_range.is_empty() || !self.0.appends_to_stored_nonce() + } +} + /// Info about a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call /// which tries to update a single lane. #[derive(PartialEq, RuntimeDebug)] @@ -108,7 +119,7 @@ impl CallInfo { /// Returns number of messages, bundled with this transaction. pub fn bundled_messages(&self) -> MessageNonce { let bundled_range = match *self { - Self::ReceiveMessagesProof(ref info) => &info.0.bundled_range, + Self::ReceiveMessagesProof(ref info) => &info.base.bundled_range, Self::ReceiveMessagesDeliveryProof(ref info) => &info.0.bundled_range, }; @@ -136,27 +147,19 @@ impl, I: 'static> CallHelper { match info { CallInfo::ReceiveMessagesProof(info) => { let inbound_lane_data = - pallet_bridge_messages::InboundLanes::::get(info.0.lane_id); - if info.0.bundled_range.is_empty() { - match info.0.unrewarded_relayers { - Some(ref pre_occupation) => { - let post_occupation = - unrewarded_relayers_occupation::(&inbound_lane_data); - // we don't care about `free_relayer_slots` here - it is checked in - // `is_obsolete` and every relayer has delivered at least one message, - // so if relayer slots are released, then message slots are also - // released - return post_occupation.free_message_slots > - pre_occupation.free_message_slots - }, - None => { - // shouldn't happen in practice, given our code - return false - }, - } + pallet_bridge_messages::InboundLanes::::get(info.base.lane_id); + if info.base.bundled_range.is_empty() { + let post_occupation = + unrewarded_relayers_occupation::(&inbound_lane_data); + // we don't care about `free_relayer_slots` here - it is checked in + // `is_obsolete` and every relayer has delivered at least one message, + // so if relayer slots are released, then message slots are also + // released + return post_occupation.free_message_slots > + info.unrewarded_relayers.free_message_slots } - inbound_lane_data.last_delivered_nonce() == *info.0.bundled_range.end() + inbound_lane_data.last_delivered_nonce() == *info.base.bundled_range.end() }, CallInfo::ReceiveMessagesDeliveryProof(info) => { let outbound_lane_data = @@ -215,16 +218,16 @@ impl< { let inbound_lane_data = pallet_bridge_messages::InboundLanes::::get(proof.lane); - return Some(ReceiveMessagesProofInfo(BaseMessagesProofInfo { - lane_id: proof.lane, - // we want all messages in this range to be new for us. Otherwise transaction will - // be considered obsolete. - bundled_range: proof.nonces_start..=proof.nonces_end, - best_stored_nonce: inbound_lane_data.last_delivered_nonce(), - unrewarded_relayers: Some(unrewarded_relayers_occupation::( - &inbound_lane_data, - )), - })) + return Some(ReceiveMessagesProofInfo { + base: BaseMessagesProofInfo { + lane_id: proof.lane, + // we want all messages in this range to be new for us. Otherwise transaction + // will be considered obsolete. + bundled_range: proof.nonces_start..=proof.nonces_end, + best_stored_nonce: inbound_lane_data.last_delivered_nonce(), + }, + unrewarded_relayers: unrewarded_relayers_occupation::(&inbound_lane_data), + }) } None @@ -248,7 +251,6 @@ impl< bundled_range: outbound_lane_data.latest_received_nonce + 1..= relayers_state.last_delivered_nonce, best_stored_nonce: outbound_lane_data.latest_received_nonce, - unrewarded_relayers: None, })) } @@ -270,7 +272,7 @@ impl< fn call_info_for(&self, lane_id: LaneId) -> Option { self.call_info().filter(|info| { let actual_lane_id = match info { - CallInfo::ReceiveMessagesProof(info) => info.0.lane_id, + CallInfo::ReceiveMessagesProof(info) => info.base.lane_id, CallInfo::ReceiveMessagesDeliveryProof(info) => info.0.lane_id, }; actual_lane_id == lane_id @@ -279,7 +281,7 @@ impl< fn check_obsolete_call(&self) -> TransactionValidity { match self.call_info() { - Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.0.is_obsolete() => { + Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.is_obsolete() => { log::trace!( target: pallet_bridge_messages::LOG_TARGET, "Rejecting obsolete messages delivery transaction: {:?}", @@ -289,7 +291,7 @@ impl< return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() }, Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info)) - if proof_info.0.is_obsolete() => + if proof_info.is_obsolete() => { log::trace!( target: pallet_bridge_messages::LOG_TARGET, @@ -314,8 +316,6 @@ fn unrewarded_relayers_occupation, I: 'static>( free_relayer_slots: T::MaxUnrewardedRelayerEntriesAtInboundLane::get() .saturating_sub(inbound_lane_data.relayers.len() as MessageNonce), free_message_slots: { - // 5 - 0 = 5 ==> 1,2,3,4,5 - // 5 - 3 = 2 ==> 4,5 let unconfirmed_messages = inbound_lane_data .last_delivered_nonce() .saturating_sub(inbound_lane_data.last_confirmed_nonce); @@ -561,19 +561,21 @@ mod tests { is_empty: bool, ) -> bool { CallHelper::::was_successful(&CallInfo::ReceiveMessagesProof( - ReceiveMessagesProofInfo(BaseMessagesProofInfo { - lane_id: LaneId([0, 0, 0, 0]), - bundled_range, - best_stored_nonce: 0, // doesn't matter for `was_successful` - unrewarded_relayers: Some(UnrewardedRelayerOccupation { + ReceiveMessagesProofInfo { + base: BaseMessagesProofInfo { + lane_id: LaneId([0, 0, 0, 0]), + bundled_range, + best_stored_nonce: 0, // doesn't matter for `was_successful` + }, + unrewarded_relayers: UnrewardedRelayerOccupation { free_relayer_slots: 0, // doesn't matter for `was_successful` free_message_slots: if is_empty { 0 } else { MaxUnconfirmedMessagesAtInboundLane::get() }, - }), - }), + }, + }, )) } @@ -624,7 +626,6 @@ mod tests { lane_id: LaneId([0, 0, 0, 0]), bundled_range, best_stored_nonce: 0, // doesn't matter for `was_successful` - unrewarded_relayers: None, }), )) } diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 83eafa1a36a2d..1aae6a16a3c1d 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -713,17 +713,17 @@ mod tests { para_id: ParaId(TestParachain::get()), para_head_hash: [1u8; 32].into(), }, - MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( - BaseMessagesProofInfo { + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo { + base: BaseMessagesProofInfo { lane_id: TEST_LANE_ID, bundled_range: 101..=200, best_stored_nonce: 100, - unrewarded_relayers: Some(UnrewardedRelayerOccupation { - free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), - free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), - }), }, - )), + unrewarded_relayers: UnrewardedRelayerOccupation { + free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), + free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), + }, + }), ), } } @@ -747,7 +747,6 @@ mod tests { lane_id: TEST_LANE_ID, bundled_range: 101..=200, best_stored_nonce: 100, - unrewarded_relayers: None, }, )), ), @@ -763,17 +762,17 @@ mod tests { para_id: ParaId(TestParachain::get()), para_head_hash: [1u8; 32].into(), }, - MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo( - BaseMessagesProofInfo { + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo { + base: BaseMessagesProofInfo { lane_id: TEST_LANE_ID, bundled_range: 101..=200, best_stored_nonce: 100, - unrewarded_relayers: Some(UnrewardedRelayerOccupation { - free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), - free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), - }), }, - )), + unrewarded_relayers: UnrewardedRelayerOccupation { + free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), + free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), + }, + }), ), } } @@ -792,7 +791,6 @@ mod tests { lane_id: TEST_LANE_ID, bundled_range: 101..=200, best_stored_nonce: 100, - unrewarded_relayers: None, }, )), ), @@ -803,15 +801,17 @@ mod tests { PreDispatchData { relayer: relayer_account_at_this_chain(), call_info: CallInfo::Msgs(MessagesCallInfo::ReceiveMessagesProof( - ReceiveMessagesProofInfo(BaseMessagesProofInfo { - lane_id: TEST_LANE_ID, - bundled_range: 101..=200, - best_stored_nonce: 100, - unrewarded_relayers: Some(UnrewardedRelayerOccupation { + ReceiveMessagesProofInfo { + base: BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + bundled_range: 101..=200, + best_stored_nonce: 100, + }, + unrewarded_relayers: UnrewardedRelayerOccupation { free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), - }), - }), + }, + }, )), } } @@ -824,7 +824,6 @@ mod tests { lane_id: TEST_LANE_ID, bundled_range: 101..=200, best_stored_nonce: 100, - unrewarded_relayers: None, }), )), } From ea64325cdb2df2dfe49752d8d5cf4cc31019b6e3 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 13 Apr 2023 10:38:34 +0300 Subject: [PATCH 1023/1210] Define `RangeInclusiveExt` (#2037) * Define RangeInclusiveExt * Use RangeInclusiveExt * Add docs --- bin/runtime-common/src/messages_call_ext.rs | 16 -------------- .../src/refund_relayer_extension.rs | 6 +++--- modules/messages/src/lib.rs | 7 ++----- primitives/messages/src/lib.rs | 8 ++----- primitives/runtime/src/lib.rs | 21 +++++++++++++++++-- 5 files changed, 26 insertions(+), 32 deletions(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index b208a9d02b422..1ca1bab6a351e 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -115,22 +115,6 @@ pub enum CallInfo { ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo), } -impl CallInfo { - /// Returns number of messages, bundled with this transaction. - pub fn bundled_messages(&self) -> MessageNonce { - let bundled_range = match *self { - Self::ReceiveMessagesProof(ref info) => &info.base.bundled_range, - Self::ReceiveMessagesDeliveryProof(ref info) => &info.0.bundled_range, - }; - - bundled_range - .end() - .checked_sub(*bundled_range.start()) - .map(|d| d.saturating_add(1)) - .unwrap_or(0) - } -} - /// Helper struct that provides methods for working with a call supported by `CallInfo`. pub struct CallHelper, I: 'static> { pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 1aae6a16a3c1d..925fea2a74349 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -24,7 +24,7 @@ use crate::messages_call_ext::{ }; use bp_messages::LaneId; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; -use bp_runtime::StaticStrProvider; +use bp_runtime::{RangeInclusiveExt, StaticStrProvider}; use codec::{Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, @@ -319,9 +319,9 @@ where if let Some(parsed_call) = parsed_call { // we give delivery transactions some boost, that depends on number of messages inside let messages_call_info = parsed_call.messages_call_info(); - if let MessagesCallInfo::ReceiveMessagesProof(_) = messages_call_info { + if let MessagesCallInfo::ReceiveMessagesProof(info) = messages_call_info { // compute total number of messages in transaction - let bundled_messages = messages_call_info.bundled_messages(); + let bundled_messages = info.base.bundled_range.checked_len().unwrap_or(0); // a quick check to avoid invalid high-priority transactions if bundled_messages <= Runtime::MaxUnconfirmedMessagesAtInboundLane::get() { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 3404ba0b219c0..5b1b98ea7a18b 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -90,6 +90,7 @@ pub const LOG_TARGET: &str = "runtime::bridge-messages"; pub mod pallet { use super::*; use bp_messages::{ReceivalResult, ReceivedMessages}; + use bp_runtime::RangeInclusiveExt; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -514,11 +515,7 @@ pub mod pallet { ); relayers_state.total_messages = sp_std::cmp::min( relayers_state.total_messages, - received_range - .end() - .checked_sub(*received_range.start()) - .and_then(|x| x.checked_add(1)) - .unwrap_or(MessageNonce::MAX), + received_range.checked_len().unwrap_or(MessageNonce::MAX), ); }; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index c877c9cdf2c47..9481a4b9bb80c 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -21,7 +21,7 @@ #![allow(clippy::too_many_arguments)] use bitvec::prelude::*; -use bp_runtime::{BasicOperatingMode, OperatingMode}; +use bp_runtime::{BasicOperatingMode, OperatingMode, RangeInclusiveExt}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; use scale_info::TypeInfo; @@ -347,11 +347,7 @@ impl DeliveredMessages { /// Return total count of delivered messages. pub fn total_messages(&self) -> MessageNonce { - if self.end >= self.begin { - self.end - self.begin + 1 - } else { - 0 - } + (self.begin..=self.end).checked_len().unwrap_or(0) } /// Note new dispatched message. diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index d4f551ce57a0b..df77745bc02dd 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -27,7 +27,7 @@ use frame_system::RawOrigin; use scale_info::TypeInfo; use sp_core::storage::StorageKey; use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto}; -use sp_std::{convert::TryFrom, fmt::Debug, vec, vec::Vec}; +use sp_std::{convert::TryFrom, fmt::Debug, ops::RangeInclusive, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, @@ -35,7 +35,7 @@ pub use chain::{ UnderlyingChainProvider, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; -use num_traits::{CheckedSub, One}; +use num_traits::{CheckedAdd, CheckedSub, One}; pub use storage_proof::{ record_all_keys as record_all_trie_keys, Error as StorageProofError, ProofSize as StorageProofSize, RawStorageProof, StorageProofChecker, @@ -523,6 +523,23 @@ impl Debug for StrippableError { } } +/// A trait defining helper methods for `RangeInclusive` (start..=end) +pub trait RangeInclusiveExt { + /// Computes the length of the `RangeInclusive`, checking for underflow and overflow. + fn checked_len(&self) -> Option; +} + +impl RangeInclusiveExt for RangeInclusive +where + Idx: CheckedSub + CheckedAdd + One, +{ + fn checked_len(&self) -> Option { + self.end() + .checked_sub(self.start()) + .and_then(|len| len.checked_add(&Idx::one())) + } +} + #[cfg(test)] mod tests { use super::*; From e1b7ae4bb9e0ce4f3858fe914b3d9c19e943cf1b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 13 Apr 2023 15:55:02 +0300 Subject: [PATCH 1024/1210] update refs (#2041) --- bin/millau/node/src/service.rs | 17 ++++++++++++----- bin/rialto-parachain/node/src/service.rs | 24 +++++++++++++++++------- bin/rialto/node/src/command.rs | 4 ++-- modules/beefy/src/lib.rs | 2 +- primitives/messages/src/lib.rs | 4 ++-- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 7230accef8e5b..07cd29a0d6d58 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -22,6 +22,7 @@ use sc_client_api::BlockBackend; use sc_consensus_aura::{CompatibilityMode, ImportQueueParams, SlotProportion, StartAuraParams}; use sc_consensus_grandpa::SharedVoterState; pub use sc_executor::NativeElseWasmExecutor; +use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; @@ -88,11 +89,17 @@ pub fn new_partial( }) .transpose()?; - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - config.runtime_cache_size, + let heap_pages = config + .default_heap_pages + .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); + let executor = NativeElseWasmExecutor::::new_with_wasm_executor( + WasmExecutor::builder() + .with_execution_method(config.wasm_method) + .with_onchain_heap_alloc_strategy(heap_pages) + .with_offchain_heap_alloc_strategy(heap_pages) + .with_max_runtime_instances(config.max_runtime_instances) + .with_runtime_cache_size(config.runtime_cache_size) + .build(), ); let (client, backend, keystore_container, task_manager) = diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 6662b2e962568..24eb94e655d57 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -41,7 +41,10 @@ use cumulus_primitives_core::ParaId; use cumulus_relay_chain_interface::RelayChainInterface; use sc_consensus::ImportQueue; // Substrate Imports -use sc_executor::{NativeElseWasmExecutor, NativeExecutionDispatch}; +use sc_executor::{ + HeapAllocStrategy, NativeElseWasmExecutor, NativeExecutionDispatch, WasmExecutor, + DEFAULT_HEAP_ALLOC_STRATEGY, +}; use sc_network::NetworkBlock; use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; @@ -131,12 +134,19 @@ where }) .transpose()?; - let executor = sc_executor::NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - config.runtime_cache_size, - ); + let heap_pages = config + .default_heap_pages + .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); + let executor = + sc_executor::NativeElseWasmExecutor::::new_with_wasm_executor( + WasmExecutor::builder() + .with_execution_method(config.wasm_method) + .with_onchain_heap_alloc_strategy(heap_pages) + .with_offchain_heap_alloc_strategy(heap_pages) + .with_max_runtime_instances(config.max_runtime_instances) + .with_runtime_cache_size(config.runtime_cache_size) + .build(), + ); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 8286444d3ea85..0bff2e523b498 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -164,7 +164,7 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path); + polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path, None); Ok(()) }, Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => { @@ -172,7 +172,7 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path); + polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path, None); Ok(()) }, None => { diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index a3a68928bc5bc..79795dd0770ab 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -94,7 +94,7 @@ pub struct ImportedCommitmentsInfoData { next_block_number_index: u32, } -#[frame_support::pallet] +#[frame_support::pallet(dev_mode)] pub mod pallet { use super::*; use bp_runtime::{BasicOperatingMode, OwnedBridgeModule}; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 9481a4b9bb80c..7b7e9476a017d 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -245,7 +245,7 @@ impl InboundLaneData { } /// Outbound message details, returned by runtime APIs. -#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct OutboundMessageDetails { /// Nonce assigned to the message. pub nonce: MessageNonce, @@ -259,7 +259,7 @@ pub struct OutboundMessageDetails { } /// Inbound message details, returned by runtime APIs. -#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] pub struct InboundMessageDetails { /// Computed message dispatch weight. /// From d574c41782c3b89952b86ea77b4a3e4785e5bd6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 01:59:48 +0000 Subject: [PATCH 1025/1210] Bump serde_json from 1.0.95 to 1.0.96 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.95 to 1.0.96. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.95...v1.0.96) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 8f7e4ba69d862..21f48efb1eb31 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.2.1", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.95" +serde_json = "1.0.96" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index f105014fb51e9..c39f7e5b67bbf 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.2.1", features = ["derive"] } -serde_json = "1.0.95" +serde_json = "1.0.96" # Bridge dependencies From 1081fcca2de5bda03a4ab15059b58436f3ccfc77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 05:31:46 +0000 Subject: [PATCH 1026/1210] Bump clap from 4.2.1 to 4.2.2 Bumps [clap](https://github.com/clap-rs/clap) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 21f48efb1eb31..21b5cd02559d9 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.1", features = ["derive"] } +clap = { version = "4.2.2", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.96" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index afd52ed72ba2d..2315eb94a116d 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.2.1", features = ["derive"] } +clap = { version = "4.2.2", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index c39f7e5b67bbf..23c7d3315e765 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.1", features = ["derive"] } +clap = { version = "4.2.2", features = ["derive"] } serde_json = "1.0.96" # Bridge dependencies From b52c42adacd6c3a635b34567425dec310663bbf8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 17 Apr 2023 12:14:34 +0300 Subject: [PATCH 1027/1210] Revert dispatch-results (#2048) * Revert "Reintroduce msg dispatch status reporting (#2027)" This reverts commit 803208a9150b6c08fe1be826337c15338e86725e. * post-revert fix --- bin/millau/runtime/src/xcm_config.rs | 10 +- bin/rialto-parachain/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/xcm_config.rs | 6 +- bin/runtime-common/Cargo.toml | 1 - bin/runtime-common/src/integrity.rs | 6 +- bin/runtime-common/src/messages_call_ext.rs | 8 +- .../src/messages_xcm_extension.rs | 18 ++- modules/messages/Cargo.toml | 1 - modules/messages/src/benchmarking.rs | 12 +- modules/messages/src/inbound_lane.rs | 27 ++--- modules/messages/src/lib.rs | 111 +++++++---------- modules/messages/src/mock.rs | 24 ++-- modules/messages/src/outbound_lane.rs | 88 +++----------- primitives/messages/Cargo.toml | 2 - primitives/messages/src/lib.rs | 113 +++--------------- primitives/messages/src/target_chain.rs | 10 +- primitives/runtime/src/messages.rs | 4 +- 17 files changed, 132 insertions(+), 315 deletions(-) diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 56546f2999297..4aaec83771b04 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -242,7 +242,7 @@ mod tests { target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchError; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use xcm_executor::XcmExecutor; @@ -352,8 +352,8 @@ mod tests { let dispatch_result = FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_result, - Err(XcmBlobMessageDispatchError::NotDispatched(_)), + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), )); } @@ -366,8 +366,8 @@ mod tests { let dispatch_result = FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_result, - Err(XcmBlobMessageDispatchError::NotDispatched(_)), + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), )); } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index b03f7965d7b28..cd4e256f4203e 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -853,7 +853,7 @@ mod tests { LaneId, MessageKey, }; use bridge_runtime_common::{ - integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchError, + integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchResult, }; use codec::Encode; use pallet_bridge_messages::OutboundLanes; @@ -928,8 +928,8 @@ mod tests { let dispatch_result = FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_result, - Err(XcmBlobMessageDispatchError::NotDispatched(_)), + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), )); }); } diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 265f435645e8f..9f6488b4c4d31 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -197,7 +197,7 @@ mod tests { target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchError; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; use xcm_executor::XcmExecutor; @@ -269,8 +269,8 @@ mod tests { let dispatch_result = FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); assert!(matches!( - dispatch_result.dispatch_result, - Err(XcmBlobMessageDispatchError::NotDispatched(_)), + dispatch_result.dispatch_level_result, + XcmBlobMessageDispatchResult::NotDispatched(_), )); } } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 9d616bf588e45..3db4ae9abca6e 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -47,7 +47,6 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "maste [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } -bitvec = { version = "1", features = ["alloc"] } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 3a677ce43ceda..5820dd99b91ca 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -307,10 +307,8 @@ pub fn check_message_lane_weights( messages::target::maximal_incoming_message_dispatch_weight(C::max_extrinsic_weight()), ); - let max_incoming_inbound_lane_data_proof_size = InboundLaneData::<()>::encoded_size_hint_u32( - this_chain_max_unrewarded_relayers as _, - this_chain_max_unconfirmed_messages as _, - ); + let max_incoming_inbound_lane_data_proof_size = + InboundLaneData::<()>::encoded_size_hint_u32(this_chain_max_unrewarded_relayers as _); pallet_bridge_messages::ensure_able_to_receive_confirmation::>( C::max_extrinsic_size(), C::max_extrinsic_weight(), diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 1ca1bab6a351e..f3665a8d93b52 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -321,7 +321,6 @@ mod tests { TestRuntime, ThisChainRuntimeCall, }, }; - use bitvec::prelude::*; use bp_messages::{DeliveredMessages, UnrewardedRelayer, UnrewardedRelayersState}; use sp_std::ops::RangeInclusive; @@ -331,11 +330,7 @@ mod tests { for n in 0..MaxUnrewardedRelayerEntriesAtInboundLane::get() { inbound_lane_state.relayers.push_back(UnrewardedRelayer { relayer: Default::default(), - messages: DeliveredMessages { - begin: n + 1, - end: n + 1, - dispatch_results: bitvec![u8, Msb0; 1; 1], - }, + messages: DeliveredMessages { begin: n + 1, end: n + 1 }, }); } pallet_bridge_messages::InboundLanes::::insert( @@ -352,7 +347,6 @@ mod tests { messages: DeliveredMessages { begin: 1, end: MaxUnconfirmedMessagesAtInboundLane::get(), - dispatch_results: bitvec![u8, Msb0; 1; MaxUnconfirmedMessagesAtInboundLane::get() as _], }, }); pallet_bridge_messages::InboundLanes::::insert( diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index d0fdc458e958c..4ccdd7a4b4df5 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -39,8 +39,9 @@ pub type XcmAsPlainPayload = sp_std::prelude::Vec; /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] -pub enum XcmBlobMessageDispatchError { +pub enum XcmBlobMessageDispatchResult { InvalidPayload, + Dispatched, NotDispatched(#[codec(skip)] Option), } @@ -64,7 +65,7 @@ impl< for XcmBlobMessageDispatch { type DispatchPayload = XcmAsPlainPayload; - type DispatchError = XcmBlobMessageDispatchError; + type DispatchLevelResult = XcmBlobMessageDispatchResult; fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload { @@ -79,7 +80,7 @@ impl< fn dispatch( _relayer_account: &AccountIdOf, message: DispatchMessage, - ) -> MessageDispatchResult { + ) -> MessageDispatchResult { let payload = match message.data.payload { Ok(payload) => payload, Err(e) => { @@ -91,7 +92,7 @@ impl< ); return MessageDispatchResult { unspent_weight: Weight::zero(), - dispatch_result: Err(XcmBlobMessageDispatchError::InvalidPayload), + dispatch_level_result: XcmBlobMessageDispatchResult::InvalidPayload, } }, }; @@ -102,7 +103,7 @@ impl< "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob was ok - message_nonce: {:?}", message.key.nonce ); - Ok(()) + XcmBlobMessageDispatchResult::Dispatched }, Err(e) => { log::error!( @@ -110,13 +111,10 @@ impl< "[XcmBlobMessageDispatch] DispatchBlob::dispatch_blob failed, error: {:?} - message_nonce: {:?}", e, message.key.nonce ); - Err(XcmBlobMessageDispatchError::NotDispatched(Some(e))) + XcmBlobMessageDispatchResult::NotDispatched(Some(e)) }, }; - MessageDispatchResult { - unspent_weight: Weight::zero(), - dispatch_result: dispatch_level_result, - } + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result } } } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 7dbe6e15ba342..f733d62bf6401 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index f7a2769715fa5..aab8855a729a8 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -301,7 +301,7 @@ benchmarks_instance_pallet! { inbound_lane_data: InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: relayer_id.clone(), - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }].into_iter().collect(), last_confirmed_nonce: 0, }, @@ -333,8 +333,8 @@ benchmarks_instance_pallet! { total_messages: 2, last_delivered_nonce: 2, }; - let mut delivered_messages = DeliveredMessages::new(1, true); - delivered_messages.note_dispatched_message(true); + let mut delivered_messages = DeliveredMessages::new(1); + delivered_messages.note_dispatched_message(); let proof = T::prepare_message_delivery_proof(MessageDeliveryProofParams { lane: T::bench_lane_id(), inbound_lane_data: InboundLaneData { @@ -379,11 +379,11 @@ benchmarks_instance_pallet! { relayers: vec![ UnrewardedRelayer { relayer: relayer1_id.clone(), - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }, UnrewardedRelayer { relayer: relayer2_id.clone(), - messages: DeliveredMessages::new(2, true), + messages: DeliveredMessages::new(2), }, ].into_iter().collect(), last_confirmed_nonce: 0, @@ -451,7 +451,7 @@ fn receive_messages, I: 'static>(nonce: MessageNonce) { inbound_lane_storage.set_data(InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: T::bridged_relayer_id(), - messages: DeliveredMessages::new(nonce, true), + messages: DeliveredMessages::new(nonce), }] .into_iter() .collect(), diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 21d835d31c715..3f64ab765b5da 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -101,7 +101,6 @@ impl, I: 'static> MaxEncodedLen for StoredInboundLaneData { fn max_encoded_len() -> usize { InboundLaneData::::encoded_size_hint( T::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize, - T::MaxUnconfirmedMessagesAtInboundLane::get() as usize, ) .unwrap_or(usize::MAX) } @@ -155,9 +154,6 @@ impl InboundLane { // overlap. match data.relayers.front_mut() { Some(entry) if entry.messages.begin < new_confirmed_nonce => { - entry.messages.dispatch_results = entry.messages.dispatch_results - [(new_confirmed_nonce + 1 - entry.messages.begin) as usize..] - .to_bitvec(); entry.messages.begin = new_confirmed_nonce + 1; }, _ => {}, @@ -174,7 +170,7 @@ impl InboundLane { relayer_at_this_chain: &AccountId, nonce: MessageNonce, message_data: DispatchMessageData, - ) -> ReceivalResult { + ) -> ReceivalResult { let mut data = self.storage.data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { @@ -202,20 +198,19 @@ impl InboundLane { ); // now let's update inbound lane storage - match data.relayers.back_mut() { + let push_new = match data.relayers.back_mut() { Some(entry) if entry.relayer == *relayer_at_bridged_chain => { - entry.messages.note_dispatched_message(dispatch_result.dispatch_result.is_ok()); - }, - _ => { - data.relayers.push_back(UnrewardedRelayer { - relayer: relayer_at_bridged_chain.clone(), - messages: DeliveredMessages::new( - nonce, - dispatch_result.dispatch_result.is_ok(), - ), - }); + entry.messages.note_dispatched_message(); + false }, + _ => true, }; + if push_new { + data.relayers.push_back(UnrewardedRelayer { + relayer: (*relayer_at_bridged_chain).clone(), + messages: DeliveredMessages::new(nonce), + }); + } self.storage.set_data(data); ReceivalResult::Dispatched(dispatch_result) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 5b1b98ea7a18b..c94f5ffa752fa 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -66,7 +66,7 @@ use bp_messages::{ use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; -use sp_runtime::{traits::UniqueSaturatedFrom, SaturatedConversion}; +use sp_runtime::traits::UniqueSaturatedFrom; use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; mod inbound_lane; @@ -547,7 +547,7 @@ pub mod pallet { MessagesReceived( Vec< ReceivedMessages< - >::DispatchError, + >::DispatchLevelResult, >, >, ), @@ -827,19 +827,15 @@ impl, I: 'static> RuntimeInboundLaneStorage { /// `receive_messages_proof` call, because the actual inbound lane state is smaller than the /// maximal configured. /// - /// Maximal inbound lane state size is computed using the - /// `MaxUnrewardedRelayerEntriesAtInboundLane` and `MaxUnconfirmedMessagesAtInboundLane` - /// constants from the pallet configuration. The PoV of the call includes the maximal size - /// of the inbound lane state. If the actual size is smaller, we may subtract extra bytes - /// from this component. + /// Maximal inbound lane state set size is configured by the + /// `MaxUnrewardedRelayerEntriesAtInboundLane` constant from the pallet configuration. The PoV + /// of the call includes the maximal size of inbound lane state. If the actual size is smaller, + /// we may subtract extra bytes from this component. pub fn extra_proof_size_bytes(&self) -> u64 { let max_encoded_len = StoredInboundLaneData::::max_encoded_len(); let relayers_count = self.data().relayers.len(); - let messages_count = self.data().relayers.iter().fold(0usize, |sum, relayer| { - sum.saturating_add(relayer.messages.total_messages().saturated_into::()) - }); let actual_encoded_len = - InboundLaneData::::encoded_size_hint(relayers_count, messages_count) + InboundLaneData::::encoded_size_hint(relayers_count) .unwrap_or(usize::MAX); max_encoded_len.saturating_sub(actual_encoded_len) as _ } @@ -971,7 +967,6 @@ mod tests { }; use frame_system::{EventRecord, Pallet as System, Phase}; use sp_runtime::DispatchError; - use std::collections::VecDeque; fn get_ready_for_events() { System::::set_block_number(1); @@ -1029,7 +1024,7 @@ mod tests { last_confirmed_nonce: 1, relayers: vec![UnrewardedRelayer { relayer: 0, - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }] .into_iter() .collect(), @@ -1049,44 +1044,13 @@ mod tests { phase: Phase::Initialization, event: TestEvent::Messages(Event::MessagesDelivered { lane_id: TEST_LANE_ID, - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }), topics: vec![], }], ); } - fn unrewarded_relayer_entry(msg_count: usize) -> UnrewardedRelayer { - UnrewardedRelayer { - relayer: 42u64, - messages: DeliveredMessages { - begin: 0, - end: msg_count as MessageNonce - 1, - dispatch_results: FromIterator::from_iter(vec![true; msg_count]), - }, - } - } - - fn unrewarded_relayers_vec( - entry_count: usize, - msg_count: usize, - ) -> VecDeque> { - if entry_count > msg_count { - panic!("unrewarded_relayers_vec(): expecting msg_count to be >= entry_count"); - } - - let mut unrewarded_relayers = vec![]; - let mut available_msg_count = msg_count; - for _ in 0..entry_count - 1 { - unrewarded_relayers - .push(unrewarded_relayer_entry(std::cmp::min(1, available_msg_count))); - available_msg_count -= 1 - } - unrewarded_relayers.push(unrewarded_relayer_entry(available_msg_count)); - - unrewarded_relayers.into_iter().collect() - } - #[test] fn pallet_rejects_transactions_if_halted() { run_test(|| { @@ -1719,7 +1683,6 @@ mod tests { fn proof_size_refund_from_receive_messages_proof_works() { run_test(|| { let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; - let max_msgs = crate::mock::MaxUnconfirmedMessagesAtInboundLane::get() as usize; // if there's maximal number of unrewarded relayer entries at the inbound lane, then // `proof_size` is unchanged in post-dispatch weight @@ -1734,7 +1697,15 @@ mod tests { InboundLanes::::insert( TEST_LANE_ID, StoredInboundLaneData(InboundLaneData { - relayers: unrewarded_relayers_vec(max_entries, max_msgs), + relayers: vec![ + UnrewardedRelayer { + relayer: 42, + messages: DeliveredMessages { begin: 0, end: 100 } + }; + max_entries + ] + .into_iter() + .collect(), last_confirmed_nonce: 0, }), ); @@ -1755,7 +1726,15 @@ mod tests { InboundLanes::::insert( TEST_LANE_ID, StoredInboundLaneData(InboundLaneData { - relayers: unrewarded_relayers_vec(max_entries - 1, max_msgs), + relayers: vec![ + UnrewardedRelayer { + relayer: 42, + messages: DeliveredMessages { begin: 0, end: 100 } + }; + max_entries - 1 + ] + .into_iter() + .collect(), last_confirmed_nonce: 0, }), ); @@ -1771,7 +1750,7 @@ mod tests { .unwrap(); assert!( post_dispatch_weight.proof_size() < pre_dispatch_weight.proof_size(), - "Expected post-dispatch PoV {} to be < than pre-dispatch PoV {}", + "Expected post-dispatch PoV {} to be less than pre-dispatch PoV {}", post_dispatch_weight.proof_size(), pre_dispatch_weight.proof_size(), ); @@ -1787,8 +1766,8 @@ mod tests { // messages 1+2 are confirmed in 1 tx, message 3 in a separate tx // dispatch of message 2 has failed - let mut delivered_messages_1_and_2 = DeliveredMessages::new(1, true); - delivered_messages_1_and_2.note_dispatched_message(true); + let mut delivered_messages_1_and_2 = DeliveredMessages::new(1); + delivered_messages_1_and_2.note_dispatched_message(); let messages_1_and_2_proof = Ok(( TEST_LANE_ID, InboundLaneData { @@ -1801,7 +1780,7 @@ mod tests { .collect(), }, )); - let delivered_message_3 = DeliveredMessages::new(3, true); + let delivered_message_3 = DeliveredMessages::new(3); let messages_3_proof = Ok(( TEST_LANE_ID, InboundLaneData { @@ -2092,7 +2071,7 @@ mod tests { last_confirmed_nonce: 1, relayers: vec![UnrewardedRelayer { relayer: 0, - messages: DeliveredMessages::new(1, true), + messages: DeliveredMessages::new(1), }] .into_iter() .collect(), @@ -2152,39 +2131,39 @@ mod tests { #[test] fn inbound_storage_extra_proof_size_bytes_works() { - let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; - let max_msgs = crate::mock::MaxUnconfirmedMessagesAtInboundLane::get() as usize; + fn relayer_entry() -> UnrewardedRelayer { + UnrewardedRelayer { relayer: 42u64, messages: DeliveredMessages { begin: 0, end: 100 } } + } - fn storage( - entry_count: usize, - msg_count: usize, - ) -> RuntimeInboundLaneStorage { + fn storage(relayer_entries: usize) -> RuntimeInboundLaneStorage { RuntimeInboundLaneStorage { lane_id: Default::default(), cached_data: RefCell::new(Some(InboundLaneData { - relayers: unrewarded_relayers_vec(entry_count, msg_count), + relayers: vec![relayer_entry(); relayer_entries].into_iter().collect(), last_confirmed_nonce: 0, })), _phantom: Default::default(), } } + let max_entries = crate::mock::MaxUnrewardedRelayerEntriesAtInboundLane::get() as usize; + // when we have exactly `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers - assert_eq!(storage(max_entries, max_msgs).extra_proof_size_bytes(), 0); + assert_eq!(storage(max_entries).extra_proof_size_bytes(), 0); // when we have less than `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers assert_eq!( - storage(max_entries - 1, max_msgs).extra_proof_size_bytes(), - unrewarded_relayer_entry(1).encoded_size() as u64 + storage(max_entries - 1).extra_proof_size_bytes(), + relayer_entry().encode().len() as u64 ); assert_eq!( - storage(max_entries - 2, max_msgs).extra_proof_size_bytes(), - 2 * unrewarded_relayer_entry(1).encoded_size() as u64 + storage(max_entries - 2).extra_proof_size_bytes(), + 2 * relayer_entry().encode().len() as u64 ); // when we have more than `MaxUnrewardedRelayerEntriesAtInboundLane` unrewarded relayers // (shall not happen in practice) - assert_eq!(storage(max_entries + 1, max_msgs).extra_proof_size_bytes(), 0); + assert_eq!(storage(max_entries + 1).extra_proof_size_bytes(), 0); } #[test] diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index d16fd4138fc38..75f05b4820a8a 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -19,7 +19,6 @@ use crate::Config; -use bitvec::prelude::*; use bp_messages::{ calc_relayers_rewards, source_chain::{DeliveryConfirmationPayments, LaneMessageVerifier, TargetHeaderChain}, @@ -63,13 +62,13 @@ pub struct TestPayload { /// /// Note: in correct code `dispatch_result.unspent_weight` will always be <= `declared_weight`, /// but for test purposes we'll be making it larger than `declared_weight` sometimes. - pub dispatch_result: MessageDispatchResult, + pub dispatch_result: MessageDispatchResult, /// Extra bytes that affect payload size. pub extra: Vec, } pub type TestMessageFee = u64; pub type TestRelayer = u64; -pub type TestDispatchError = (); +pub type TestDispatchLevelResult = (); type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -419,7 +418,7 @@ pub struct TestMessageDispatch; impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; - type DispatchError = TestDispatchError; + type DispatchLevelResult = TestDispatchLevelResult; fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { @@ -431,7 +430,7 @@ impl MessageDispatch for TestMessageDispatch { fn dispatch( _relayer_account: &AccountId, message: DispatchMessage, - ) -> MessageDispatchResult { + ) -> MessageDispatchResult { match message.data.payload.as_ref() { Ok(payload) => payload.dispatch_result.clone(), Err(_) => dispatch_result(0), @@ -466,10 +465,12 @@ pub const fn message_payload(id: u64, declared_weight: u64) -> TestPayload { } /// Returns message dispatch result with given unspent weight. -pub const fn dispatch_result(unspent_weight: u64) -> MessageDispatchResult { +pub const fn dispatch_result( + unspent_weight: u64, +) -> MessageDispatchResult { MessageDispatchResult { unspent_weight: Weight::from_parts(unspent_weight, 0), - dispatch_result: Ok(()), + dispatch_level_result: (), } } @@ -479,14 +480,7 @@ pub fn unrewarded_relayer( end: MessageNonce, relayer: TestRelayer, ) -> UnrewardedRelayer { - UnrewardedRelayer { - relayer, - messages: DeliveredMessages { - begin, - end, - dispatch_results: bitvec![u8, Msb0; 1; (end + 1).saturating_sub(begin) as _], - }, - } + UnrewardedRelayer { relayer, messages: DeliveredMessages { begin, end } } } /// Return test externalities to use in tests. diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 5b3281b5b162f..33a58a40400bf 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -18,10 +18,8 @@ use crate::Config; -use bitvec::prelude::*; use bp_messages::{ - DeliveredMessages, DispatchResultsBitVec, LaneId, MessageNonce, MessagePayload, - OutboundLaneData, UnrewardedRelayer, + DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, }; use frame_support::{ weights::{RuntimeDbWeight, Weight}, @@ -67,9 +65,6 @@ pub enum ReceivalConfirmationResult { /// The unrewarded relayers vec contains non-consecutive entries. May be a result of invalid /// bridged chain storage. NonConsecutiveUnrewardedRelayerEntries, - /// The unrewarded relayers vec contains entry with mismatched number of dispatch results. May - /// be a result of invalid bridged chain storage. - InvalidNumberOfDispatchResults, /// The chain has more messages that need to be confirmed than there is in the proof. TryingToConfirmMoreMessagesThanExpected(MessageNonce), } @@ -129,14 +124,9 @@ impl OutboundLane { ) } - let dispatch_results = match extract_dispatch_results( - data.latest_received_nonce, - latest_delivered_nonce, - relayers, - ) { - Ok(dispatch_results) => dispatch_results, - Err(extract_error) => return extract_error, - }; + if let Err(e) = ensure_unrewarded_relayers_are_correct(latest_delivered_nonce, relayers) { + return e + } let prev_latest_received_nonce = data.latest_received_nonce; data.latest_received_nonce = latest_delivered_nonce; @@ -145,7 +135,6 @@ impl OutboundLane { ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages { begin: prev_latest_received_nonce + 1, end: latest_delivered_nonce, - dispatch_results, }) } @@ -180,34 +169,30 @@ impl OutboundLane { } } -/// Extract new dispatch results from the unrewarded relayers vec. +/// Verifies unrewarded relayers vec. /// /// Returns `Err(_)` if unrewarded relayers vec contains invalid data, meaning that the bridged /// chain has invalid runtime storage. -fn extract_dispatch_results( - prev_latest_received_nonce: MessageNonce, +fn ensure_unrewarded_relayers_are_correct( latest_received_nonce: MessageNonce, relayers: &VecDeque>, -) -> Result { - // the only caller of this functions checks that the - // prev_latest_received_nonce..=latest_received_nonce is valid, so we're ready to accept - // messages in this range => with_capacity call must succeed here or we'll be unable to receive - // confirmations at all - let mut received_dispatch_result = - BitVec::with_capacity((latest_received_nonce - prev_latest_received_nonce + 1) as _); - let mut expected_entry_begin = relayers.front().map(|entry| entry.messages.begin); +) -> Result<(), ReceivalConfirmationResult> { + let mut last_entry_end: Option = None; for entry in relayers { // unrewarded relayer entry must have at least 1 unconfirmed message // (guaranteed by the `InboundLane::receive_message()`) - if entry.messages.total_messages() == 0 { + if entry.messages.end < entry.messages.begin { return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry) } // every entry must confirm range of messages that follows previous entry range // (guaranteed by the `InboundLane::receive_message()`) - if expected_entry_begin != Some(entry.messages.begin) { - return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries) + if let Some(last_entry_end) = last_entry_end { + let expected_entry_begin = last_entry_end.checked_add(1); + if expected_entry_begin != Some(entry.messages.begin) { + return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries) + } } - expected_entry_begin = entry.messages.end.checked_add(1); + last_entry_end = Some(entry.messages.end); // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { @@ -216,30 +201,9 @@ fn extract_dispatch_results( // this is detected now return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages) } - // entry must have single dispatch result for every message - // (guaranteed by the `InboundLane::receive_message()`) - if entry.messages.dispatch_results.len() as MessageNonce != entry.messages.total_messages() - { - return Err(ReceivalConfirmationResult::InvalidNumberOfDispatchResults) - } - - // now we know that the entry is valid - // => let's check if it brings new confirmations - let new_messages_begin = - sp_std::cmp::max(entry.messages.begin, prev_latest_received_nonce + 1); - if entry.messages.end < new_messages_begin { - continue - } - - // now we know that entry brings new confirmations - // => let's extract dispatch results - received_dispatch_result.extend_from_bitslice( - &entry.messages.dispatch_results - [(new_messages_begin - entry.messages.begin) as usize..], - ); } - Ok(received_dispatch_result) + Ok(()) } #[cfg(test)] @@ -264,11 +228,7 @@ mod tests { } fn delivered_messages(nonces: RangeInclusive) -> DeliveredMessages { - DeliveredMessages { - begin: *nonces.start(), - end: *nonces.end(), - dispatch_results: bitvec![u8, Msb0; 1; (nonces.end() - nonces.start() + 1) as _], - } + DeliveredMessages { begin: *nonces.start(), end: *nonces.end() } } fn assert_3_messages_confirmation_fails( @@ -401,20 +361,6 @@ mod tests { ); } - #[test] - fn confirm_delivery_fails_if_number_of_dispatch_results_in_entry_is_invalid() { - let mut relayers: VecDeque<_> = unrewarded_relayers(1..=1) - .into_iter() - .chain(unrewarded_relayers(2..=2).into_iter()) - .chain(unrewarded_relayers(3..=3).into_iter()) - .collect(); - relayers[0].messages.dispatch_results.clear(); - assert_eq!( - assert_3_messages_confirmation_fails(3, &relayers), - ReceivalConfirmationResult::InvalidNumberOfDispatchResults, - ); - } - #[test] fn prune_messages_works() { run_test(|| { diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index bc1b92c6b88e7..32d7c65ebcbbb 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bitvec = { version = "1", default-features = false, features = ["alloc"] } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } @@ -29,7 +28,6 @@ hex-literal = "0.4" [features] default = ["std"] std = [ - "bitvec/std", "bp-runtime/std", "codec/std", "frame-support/std", diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 7b7e9476a017d..3910837a442e0 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -20,7 +20,6 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bitvec::prelude::*; use bp_runtime::{BasicOperatingMode, OperatingMode, RangeInclusiveExt}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::RuntimeDebug; @@ -157,68 +156,18 @@ impl Default for InboundLaneData { } impl InboundLaneData { - fn dispatch_results_encoded_size_hint( - relayers_entries: usize, - message_count: usize, - ) -> Option - where - RelayerId: MaxEncodedLen, - { - // The worst-case scenario for the bitvecs size is the one in which we have as many relayer - // entries as possible taking an extra 1 byte slot with just 1 bit of actual information. - // For example: - // 11111111 1------- - // 11111111 1------- - // 1------- - // 1------- - - // If there are less msgs than relayer entries, in the worst case, each dispatch result - // belongs to a different relayer slot. This means 1 byte for the len prefix and 1 byte - // for the actual data. - if relayers_entries >= message_count { - return relayers_entries.checked_add(message_count) - } - - let msgs_per_byte = 8; - // At the begining each relayer slot has 1 message, using 1 byte - let mut num_result_bytes = relayers_entries; - // Then we add batches of 8 messages to some relayer slot until there are no more messages. - // Each batch takes up 1 more byte. - num_result_bytes = - num_result_bytes.checked_add((message_count - relayers_entries) / msgs_per_byte)?; - - // The len is stored in a `Compact`. `Compact` can store a max value of - // 63 on 1 byte, 16383 on 2 bytes, etc. - let max_len_per_first_byte = 0b0011_1111; - // At the begining each relayer slot uses 1 byte for the len prefix - // (each relayer slot contains 1 message) - let mut num_len_bytes = relayers_entries; - // Then we add batches of 63 messages to as many relayer slots as possible, requiring 2 - // bytes for the `len` prefix. It's hard to believe that we'll need more than 2 bytes - // (more than 16383 messages in 1 relayer slot). - num_len_bytes = num_len_bytes.checked_add(sp_std::cmp::min( - (message_count - relayers_entries) / max_len_per_first_byte, - relayers_entries, - ))?; - - num_result_bytes.checked_add(num_len_bytes) - } - /// Returns approximate size of the struct, given a number of entries in the `relayers` set and /// size of each entry. /// /// Returns `None` if size overflows `usize` limits. - pub fn encoded_size_hint(relayers_entries: usize, message_count: usize) -> Option + pub fn encoded_size_hint(relayers_entries: usize) -> Option where RelayerId: MaxEncodedLen, { let message_nonce_size = MessageNonce::max_encoded_len(); let relayer_id_encoded_size = RelayerId::max_encoded_len(); let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; - let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?.checked_add( - Self::dispatch_results_encoded_size_hint(relayers_entries, message_count)?, - )?; - + let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; relayers_size.checked_add(message_nonce_size) } @@ -226,11 +175,11 @@ impl InboundLaneData { /// `relayers` set and the size of each entry. /// /// Returns `u32::MAX` if size overflows `u32` limits. - pub fn encoded_size_hint_u32(relayers_entries: usize, messages_count: usize) -> u32 + pub fn encoded_size_hint_u32(relayers_entries: usize) -> u32 where RelayerId: MaxEncodedLen, { - Self::encoded_size_hint(relayers_entries, messages_count) + Self::encoded_size_hint(relayers_entries) .and_then(|x| u32::try_from(x).ok()) .unwrap_or(u32::MAX) } @@ -270,9 +219,6 @@ pub struct InboundMessageDetails { pub dispatch_weight: Weight, } -/// Bit vector of message dispatch results. -pub type DispatchResultsBitVec = BitVec; - /// Unrewarded relayer entry stored in the inbound lane data. /// /// This struct represents a continuous range of messages that have been delivered by the same @@ -330,19 +276,13 @@ pub struct DeliveredMessages { pub begin: MessageNonce, /// Nonce of the last message that has been delivered (inclusive). pub end: MessageNonce, - /// Dispatch result (`false`/`true`), returned by the message dispatcher for every - /// message in the `[begin; end]` range. See `dispatch_result` field of the - /// `bp_runtime::messages::MessageDispatchResult` structure for more information. - pub dispatch_results: DispatchResultsBitVec, } impl DeliveredMessages { /// Create new `DeliveredMessages` struct that confirms delivery of single nonce with given /// dispatch result. - pub fn new(nonce: MessageNonce, dispatch_result: bool) -> Self { - let mut dispatch_results = BitVec::with_capacity(1); - dispatch_results.push(dispatch_result); - DeliveredMessages { begin: nonce, end: nonce, dispatch_results } + pub fn new(nonce: MessageNonce) -> Self { + DeliveredMessages { begin: nonce, end: nonce } } /// Return total count of delivered messages. @@ -351,25 +291,14 @@ impl DeliveredMessages { } /// Note new dispatched message. - pub fn note_dispatched_message(&mut self, dispatch_result: bool) { + pub fn note_dispatched_message(&mut self) { self.end += 1; - self.dispatch_results.push(dispatch_result); } /// Returns true if delivered messages contain message with given nonce. pub fn contains_message(&self, nonce: MessageNonce) -> bool { (self.begin..=self.end).contains(&nonce) } - - /// Get dispatch result flag by message nonce. - /// - /// Dispatch result flag must be interpreted using the knowledge of dispatch mechanism - /// at the target chain. See `dispatch_result` field of the - /// `bp_runtime::messages::MessageDispatchResult` structure for more information. - pub fn message_dispatch_result(&self, nonce: MessageNonce) -> Option { - let index = nonce.checked_sub(self.begin)? as usize; - self.dispatch_results.get(index).map(|bit| *bit) - } } /// Gist of `InboundLaneData::relayers` field used by runtime APIs. @@ -481,10 +410,10 @@ mod tests { assert_eq!( total_unrewarded_messages( &vec![ - UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0, true) }, + UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) }, UnrewardedRelayer { relayer: 2, - messages: DeliveredMessages::new(MessageNonce::MAX, true) + messages: DeliveredMessages::new(MessageNonce::MAX) }, ] .into_iter() @@ -505,21 +434,12 @@ mod tests { (13u8, 128u8), ]; for (relayer_entries, messages_count) in test_cases { - let expected_size = - InboundLaneData::::encoded_size_hint(relayer_entries as _, messages_count as _); + let expected_size = InboundLaneData::::encoded_size_hint(relayer_entries as _); let actual_size = InboundLaneData { relayers: (1u8..=relayer_entries) - .map(|i| { - let mut entry = UnrewardedRelayer { - relayer: i, - messages: DeliveredMessages::new(i as _, true), - }; - entry.messages.dispatch_results = bitvec![ - u8, Msb0; - 1; - (messages_count / relayer_entries) as _ - ]; - entry + .map(|i| UnrewardedRelayer { + relayer: i, + messages: DeliveredMessages::new(i as _), }) .collect(), last_confirmed_nonce: messages_count as _, @@ -535,16 +455,13 @@ mod tests { } #[test] - fn message_dispatch_result_works() { - let delivered_messages = - DeliveredMessages { begin: 100, end: 150, dispatch_results: bitvec![u8, Msb0; 1; 151] }; + fn contains_result_works() { + let delivered_messages = DeliveredMessages { begin: 100, end: 150 }; assert!(!delivered_messages.contains_message(99)); assert!(delivered_messages.contains_message(100)); assert!(delivered_messages.contains_message(150)); assert!(!delivered_messages.contains_message(151)); - - assert_eq!(delivered_messages.message_dispatch_result(125), Some(true)); } #[test] diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index da96c4e59cd95..8496b90214c40 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -90,7 +90,7 @@ pub trait MessageDispatch { type DispatchPayload: Decode; /// Fine-grained result of single message dispatch (for better diagnostic purposes) - type DispatchError: Clone + sp_std::fmt::Debug + Eq; + type DispatchLevelResult: Clone + sp_std::fmt::Debug + Eq; /// Estimate dispatch weight. /// @@ -109,7 +109,7 @@ pub trait MessageDispatch { fn dispatch( relayer_account: &AccountId, message: DispatchMessage, - ) -> MessageDispatchResult; + ) -> MessageDispatchResult; } /// Manages payments that are happening at the target chain during message delivery transaction. @@ -190,7 +190,7 @@ impl MessageDispatch { type DispatchPayload = DispatchPayload; - type DispatchError = (); + type DispatchLevelResult = (); fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX @@ -199,7 +199,7 @@ impl MessageDispatch, - ) -> MessageDispatchResult { - MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_result: Err(()) } + ) -> MessageDispatchResult { + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } } } diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index efbd751816770..9f7c8ab5ca4e3 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -22,7 +22,7 @@ use scale_info::TypeInfo; /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] -pub struct MessageDispatchResult { +pub struct MessageDispatchResult { /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: /// @@ -31,5 +31,5 @@ pub struct MessageDispatchResult { /// 2) if message has not been dispatched at all. pub unspent_weight: Weight, /// Fine-grained result of single message dispatch (for better diagnostic purposes) - pub dispatch_result: Result<(), DispatchError>, + pub dispatch_level_result: DispatchLevelResult, } From 9223136e6b854b17574d1a314c1ff8446b7e599f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 17 Apr 2023 15:09:31 +0300 Subject: [PATCH 1028/1210] Small simplifications (#2050) --- modules/messages/src/inbound_lane.rs | 16 +++++++--------- primitives/messages/src/lib.rs | 12 +++++------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 3f64ab765b5da..59ff566719586 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -198,19 +198,17 @@ impl InboundLane { ); // now let's update inbound lane storage - let push_new = match data.relayers.back_mut() { + match data.relayers.back_mut() { Some(entry) if entry.relayer == *relayer_at_bridged_chain => { entry.messages.note_dispatched_message(); - false }, - _ => true, + _ => { + data.relayers.push_back(UnrewardedRelayer { + relayer: relayer_at_bridged_chain.clone(), + messages: DeliveredMessages::new(nonce), + }); + }, }; - if push_new { - data.relayers.push_back(UnrewardedRelayer { - relayer: (*relayer_at_bridged_chain).clone(), - messages: DeliveredMessages::new(nonce), - }); - } self.storage.set_data(data); ReceivalResult::Dispatched(dispatch_result) diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 3910837a442e0..2828d5af00632 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -164,11 +164,9 @@ impl InboundLaneData { where RelayerId: MaxEncodedLen, { - let message_nonce_size = MessageNonce::max_encoded_len(); - let relayer_id_encoded_size = RelayerId::max_encoded_len(); - let relayers_entry_size = relayer_id_encoded_size.checked_add(2 * message_nonce_size)?; - let relayers_size = relayers_entries.checked_mul(relayers_entry_size)?; - relayers_size.checked_add(message_nonce_size) + relayers_entries + .checked_mul(UnrewardedRelayer::::max_encoded_len())? + .checked_add(MessageNonce::max_encoded_len()) } /// Returns the approximate size of the struct as u32, given a number of entries in the @@ -223,7 +221,7 @@ pub struct InboundMessageDetails { /// /// This struct represents a continuous range of messages that have been delivered by the same /// relayer and whose confirmations are still pending. -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct UnrewardedRelayer { /// Identifier of the relayer. pub relayer: RelayerId, @@ -270,7 +268,7 @@ pub enum ReceivalResult { } /// Delivered messages with their dispatch result. -#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] +#[derive(Clone, Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct DeliveredMessages { /// Nonce of the first message that has been delivered (inclusive). pub begin: MessageNonce, From 9408b027dfb272d09d5a9d0f1103ae998a1a770f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 19 Apr 2023 15:36:16 +0300 Subject: [PATCH 1029/1210] Test deployments fixes (#2057) * Fix node_impl_version error ``` error: unexpected argument '--node-impl-version' found tip: to pass '--node-impl-version' as a value, use '-- --node-impl-version' Usage: rialto-bridge-node prepare-worker For more information, try '--help'. ``` * Fix rialto-parachain not producing blocks We must have at least 2 validators for each collator --- bin/rialto/node/src/cli.rs | 10 +++++++--- bin/rialto/node/src/command.rs | 10 ++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index 98323c9d9ca65..c39efed4ce986 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -68,15 +68,15 @@ pub enum Subcommand { Inspect(node_inspect::cli::InspectCmd), /// Benchmark runtime pallets. - #[clap(subcommand)] + #[command(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. - #[clap(name = "prepare-worker", hide = true)] + #[command(name = "prepare-worker", hide = true)] PvfPrepareWorker(ValidationWorkerCommand), /// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary. - #[clap(name = "execute-worker", hide = true)] + #[command(name = "execute-worker", hide = true)] PvfExecuteWorker(ValidationWorkerCommand), } @@ -84,5 +84,9 @@ pub enum Subcommand { #[derive(Debug, Parser)] pub struct ValidationWorkerCommand { /// The path to the validation host's socket. + #[arg(long)] pub socket_path: String, + /// Calling node implementation version + #[arg(long)] + pub node_impl_version: String, } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 0bff2e523b498..a21b3a88d2c23 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -164,7 +164,10 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf::prepare_worker_entrypoint(&cmd.socket_path, None); + polkadot_node_core_pvf::prepare_worker_entrypoint( + &cmd.socket_path, + Some(&cmd.node_impl_version), + ); Ok(()) }, Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => { @@ -172,7 +175,10 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf::execute_worker_entrypoint(&cmd.socket_path, None); + polkadot_node_core_pvf::execute_worker_entrypoint( + &cmd.socket_path, + Some(&cmd.node_impl_version), + ); Ok(()) }, None => { From 2a39d4fa8c942379ef226ebf76ba3d5201b1d785 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 21 Apr 2023 09:56:22 +0300 Subject: [PATCH 1030/1210] submit lane unblock transactions from relay (#2030) * submit lane unblock transactions from relay * moved body of select_nonces_to_deliver to the separate select_race_action * extracted latest_confirmed_nonce_at_source method * return Option from select_race_action * make required_source_header_at_target async * remove extra argument from required_source_header_at_target * small fixes in tests * Revert "return Option from select_race_action" This reverts commit 9f13dbfae39a5a45564550e8c89b10a524a68729. * implement required_source_header_at_target using what-if approach * fix compilation * fmt * clippy * moved some code to the can_submit_transaction_with --- relays/client-substrate/src/chain.rs | 2 +- relays/lib-substrate-relay/src/lib.rs | 2 +- relays/messages/Cargo.toml | 1 + relays/messages/src/message_lane_loop.rs | 30 +- relays/messages/src/message_race_delivery.rs | 547 +++++++++++++------ relays/messages/src/message_race_loop.rs | 34 +- relays/messages/src/message_race_strategy.rs | 6 +- 7 files changed, 428 insertions(+), 194 deletions(-) diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 8c7dc00aa67bb..54c9ad4f3b68c 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -55,7 +55,7 @@ pub trait Chain: ChainBase + Clone { /// Block type. type SignedBlock: Member + Serialize + DeserializeOwned + BlockWithJustification; /// The aggregated `Call` type. - type Call: Clone + Codec + Debug + Send; + type Call: Clone + Codec + Debug + Send + Sync; } /// Substrate-based relay chain that supports parachains. diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 37a4d602e598d..f9bd80d50793c 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -91,7 +91,7 @@ impl TaggedAccount { } /// Batch call builder. -pub trait BatchCallBuilder: Clone + Send { +pub trait BatchCallBuilder: Clone + Send + Sync { /// Create batch call from given calls vector. fn build_batch_call(&self, _calls: Vec) -> Call; } diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 8c4b8257d5aa6..a45b272810537 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" +env_logger = "0.10" futures = "0.3.28" hex = "0.4" log = "0.4.17" diff --git a/relays/messages/src/message_lane_loop.rs b/relays/messages/src/message_lane_loop.rs index ba86f05ffd32a..b681d86d2ae8f 100644 --- a/relays/messages/src/message_lane_loop.rs +++ b/relays/messages/src/message_lane_loop.rs @@ -111,7 +111,7 @@ pub struct NoncesSubmitArtifacts { /// Batch transaction that already submit some headers and needs to be extended with /// messages/delivery proof before sending. -pub trait BatchTransaction: Debug + Send { +pub trait BatchTransaction: Debug + Send + Sync { /// Header that was required in the original call and which is bundled within this /// batch transaction. fn required_header_id(&self) -> HeaderId; @@ -622,11 +622,19 @@ pub(crate) mod tests { } impl TestClientData { - fn receive_messages(&mut self, proof: TestMessagesProof) { + fn receive_messages( + &mut self, + maybe_batch_tx: Option, + proof: TestMessagesProof, + ) { self.target_state.best_self = HeaderId(self.target_state.best_self.0 + 1, self.target_state.best_self.1 + 1); self.target_state.best_finalized_self = self.target_state.best_self; self.target_latest_received_nonce = *proof.0.end(); + if let Some(maybe_batch_tx) = maybe_batch_tx { + self.target_state.best_finalized_peer_at_best_self = + Some(maybe_batch_tx.required_header_id()); + } if let Some(target_latest_confirmed_received_nonce) = proof.1 { self.target_latest_confirmed_received_nonce = target_latest_confirmed_received_nonce; @@ -634,10 +642,18 @@ pub(crate) mod tests { self.submitted_messages_proofs.push(proof); } - fn receive_messages_delivery_proof(&mut self, proof: TestMessagesReceivingProof) { + fn receive_messages_delivery_proof( + &mut self, + maybe_batch_tx: Option, + proof: TestMessagesReceivingProof, + ) { self.source_state.best_self = HeaderId(self.source_state.best_self.0 + 1, self.source_state.best_self.1 + 1); self.source_state.best_finalized_self = self.source_state.best_self; + if let Some(maybe_batch_tx) = maybe_batch_tx { + self.source_state.best_finalized_peer_at_best_self = + Some(maybe_batch_tx.required_header_id()); + } self.submitted_messages_receiving_proofs.push(proof); self.source_latest_confirmed_received_nonce = proof; } @@ -760,13 +776,13 @@ pub(crate) mod tests { async fn submit_messages_receiving_proof( &self, - _maybe_batch_tx: Option, + maybe_batch_tx: Option, _generated_at_block: TargetHeaderIdOf, proof: TestMessagesReceivingProof, ) -> Result { let mut data = self.data.lock(); (self.tick)(&mut data); - data.receive_messages_delivery_proof(proof); + data.receive_messages_delivery_proof(maybe_batch_tx, proof); (self.post_tick)(&mut data); Ok(TestTransactionTracker(data.source_tracked_transaction_status)) } @@ -885,7 +901,7 @@ pub(crate) mod tests { async fn submit_messages_proof( &self, - _maybe_batch_tx: Option, + maybe_batch_tx: Option, _generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: TestMessagesProof, @@ -895,7 +911,7 @@ pub(crate) mod tests { if data.is_target_fails { return Err(TestError) } - data.receive_messages(proof); + data.receive_messages(maybe_batch_tx, proof); (self.post_tick)(&mut data); Ok(NoncesSubmitArtifacts { nonces, diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 7a245858b32d8..4af02ba2b568a 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -290,7 +290,185 @@ impl std::fmt::Debug for MessageDeliveryStrategy MessageDeliveryStrategy { +impl MessageDeliveryStrategy +where + P: MessageLane, + SC: MessageLaneSourceClient

, + TC: MessageLaneTargetClient

, +{ + /// Returns true if some race action can be selected (with `select_race_action`) at given + /// `best_finalized_source_header_id_at_best_target` source header at target. + async fn can_submit_transaction_with< + RS: RaceState, TargetHeaderIdOf

>, + >( + &self, + mut race_state: RS, + maybe_best_finalized_source_header_id_at_best_target: Option>, + ) -> bool { + if let Some(best_finalized_source_header_id_at_best_target) = + maybe_best_finalized_source_header_id_at_best_target + { + race_state.set_best_finalized_source_header_id_at_best_target( + best_finalized_source_header_id_at_best_target, + ); + + return self.select_race_action(race_state).await.is_some() + } + + false + } + + async fn select_race_action, TargetHeaderIdOf

>>( + &self, + race_state: RS, + ) -> Option<(RangeInclusive, MessageProofParameters)> { + let best_target_nonce = self.strategy.best_at_target()?; + let best_finalized_source_header_id_at_best_target = + race_state.best_finalized_source_header_id_at_best_target()?; + let latest_confirmed_nonce_at_source = self + .latest_confirmed_nonce_at_source(&best_finalized_source_header_id_at_best_target) + .unwrap_or(best_target_nonce); + let target_nonces = self.target_nonces.as_ref()?; + + // There's additional condition in the message delivery race: target would reject messages + // if there are too much unconfirmed messages at the inbound lane. + + // The receiving race is responsible to deliver confirmations back to the source chain. So + // if there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. + let latest_received_nonce_at_target = target_nonces.latest_nonce; + let confirmations_missing = + latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); + match confirmations_missing { + Some(confirmations_missing) + if confirmations_missing >= self.max_unconfirmed_nonces_at_target => + { + log::debug!( + target: "bridge", + "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ + at target: target.latest_received={:?}, source.latest_confirmed={:?}, max={:?}", + MessageDeliveryRace::

::source_name(), + MessageDeliveryRace::

::target_name(), + latest_received_nonce_at_target, + latest_confirmed_nonce_at_source, + self.max_unconfirmed_nonces_at_target, + ); + + return None + }, + _ => (), + } + + // Ok - we may have new nonces to deliver. But target may still reject new messages, because + // we haven't notified it that (some) messages have been confirmed. So we may want to + // include updated `source.latest_confirmed` in the proof. + // + // Important note: we're including outbound state lane proof whenever there are unconfirmed + // nonces on the target chain. Other strategy is to include it only if it's absolutely + // necessary. + let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce; + let outbound_state_proof_required = + latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; + + // The target node would also reject messages if there are too many entries in the + // "unrewarded relayers" set. If we are unable to prove new rewards to the target node, then + // we should wait for confirmations race. + let unrewarded_limit_reached = + target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries >= + self.max_unrewarded_relayer_entries_at_target || + target_nonces.nonces_data.unrewarded_relayers.total_messages >= + self.max_unconfirmed_nonces_at_target; + if unrewarded_limit_reached { + // so there are already too many unrewarded relayer entries in the set + // + // => check if we can prove enough rewards. If not, we should wait for more rewards to + // be paid + let number_of_rewards_being_proved = + latest_confirmed_nonce_at_source.saturating_sub(latest_confirmed_nonce_at_target); + let enough_rewards_being_proved = number_of_rewards_being_proved >= + target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry; + if !enough_rewards_being_proved { + return None + } + } + + // If we're here, then the confirmations race did its job && sending side now knows that + // messages have been delivered. Now let's select nonces that we want to deliver. + // + // We may deliver at most: + // + // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - + // latest_confirmed_nonce_at_target) + // + // messages in the batch. But since we're including outbound state proof in the batch, then + // it may be increased to: + // + // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - + // latest_confirmed_nonce_at_source) + let future_confirmed_nonce_at_target = if outbound_state_proof_required { + latest_confirmed_nonce_at_source + } else { + latest_confirmed_nonce_at_target + }; + let max_nonces = latest_received_nonce_at_target + .checked_sub(future_confirmed_nonce_at_target) + .and_then(|diff| self.max_unconfirmed_nonces_at_target.checked_sub(diff)) + .unwrap_or_default(); + let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); + let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; + let max_messages_size_in_single_batch = self.max_messages_size_in_single_batch; + let lane_source_client = self.lane_source_client.clone(); + let lane_target_client = self.lane_target_client.clone(); + + // select nonces from nonces, available for delivery + let selected_nonces = match self.strategy.available_source_queue_indices(race_state) { + Some(available_source_queue_indices) => { + let source_queue = self.strategy.source_queue(); + let reference = RelayMessagesBatchReference { + max_messages_in_this_batch: max_nonces, + max_messages_weight_in_single_batch, + max_messages_size_in_single_batch, + lane_source_client: lane_source_client.clone(), + lane_target_client: lane_target_client.clone(), + best_target_nonce, + nonces_queue: source_queue.clone(), + nonces_queue_range: available_source_queue_indices, + metrics: self.metrics_msg.clone(), + }; + + MessageRaceLimits::decide(reference).await + }, + None => { + // we still may need to submit delivery transaction with zero messages to + // unblock the lane. But it'll only be accepted if the lane is blocked + // (i.e. when `unrewarded_limit_reached` is `true`) + None + }, + }; + + // check if we need unblocking transaction and we may submit it + #[allow(clippy::reversed_empty_ranges)] + let selected_nonces = match selected_nonces { + Some(selected_nonces) => selected_nonces, + None if unrewarded_limit_reached && outbound_state_proof_required => 1..=0, + _ => return None, + }; + + let dispatch_weight = self.dispatch_weight_for_range(&selected_nonces); + Some(( + selected_nonces, + MessageProofParameters { outbound_state_proof_required, dispatch_weight }, + )) + } + + /// Returns lastest confirmed message at source chain, given source block. + fn latest_confirmed_nonce_at_source(&self, at: &SourceHeaderIdOf

) -> Option { + self.latest_confirmed_nonces_at_source + .iter() + .take_while(|(id, _)| id.0 <= at.0) + .last() + .map(|(_, nonce)| *nonce) + } + /// Returns total weight of all undelivered messages. fn dispatch_weight_for_range(&self, range: &RangeInclusive) -> Weight { self.strategy @@ -322,9 +500,10 @@ where self.strategy.is_empty() } - fn required_source_header_at_target, TargetHeaderIdOf

>>( + async fn required_source_header_at_target< + RS: RaceState, TargetHeaderIdOf

>, + >( &self, - current_best: &SourceHeaderIdOf

, race_state: RS, ) -> Option> { // we have already submitted something - let's wait until it is mined @@ -332,32 +511,41 @@ where return None } - let has_nonces_to_deliver = !self.strategy.is_empty(); - let header_required_for_messages_delivery = - self.strategy.required_source_header_at_target(current_best, race_state); - let header_required_for_reward_confirmations_delivery = self - .latest_confirmed_nonces_at_source - .back() - .filter(|(id, nonce)| *nonce != 0 && id.0 > current_best.0) - .map(|(id, _)| id.clone()); - match ( - has_nonces_to_deliver, - header_required_for_messages_delivery, - header_required_for_reward_confirmations_delivery, - ) { - // if we need to delver messages and proof-of-delivery-confirmations, then we need to - // select the most recent header to avoid extra roundtrips - (true, Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }), - // if we only need to deliver messages - fine, let's require some source header - // - // if we need new header for proof-of-delivery-confirmations - let's also ask for that. - // Even though it may require additional header, we'll be sure that we won't block the - // lane (sometimes we can't deliver messages without proof-of-delivery-confirmations) - (true, a, b) => a.or(b), - // we never submit delivery transaction without messages, so if `has_nonces_to_deliver` - // if `false`, we don't need any source headers at target - (false, _, _) => None, + // if we can deliver something using current race state, go on + let selected_nonces = self.select_race_action(race_state.clone()).await; + if selected_nonces.is_some() { + return None + } + + // check if we may deliver some messages if we'll relay require source header + // to target first + let maybe_source_header_for_delivery = + self.strategy.source_queue().back().map(|(id, _)| id.clone()); + if self + .can_submit_transaction_with( + race_state.clone(), + maybe_source_header_for_delivery.clone(), + ) + .await + { + return maybe_source_header_for_delivery + } + + // ok, we can't delivery anything even if we relay some source blocks first. But maybe + // the lane is blocked and we need to submit unblock transaction? + let maybe_source_header_for_reward_confirmation = + self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone()); + if self + .can_submit_transaction_with( + race_state.clone(), + maybe_source_header_for_reward_confirmation.clone(), + ) + .await + { + return maybe_source_header_for_reward_confirmation } + + None } fn best_at_source(&self) -> Option { @@ -436,128 +624,7 @@ where &self, race_state: RS, ) -> Option<(RangeInclusive, Self::ProofParameters)> { - let best_target_nonce = self.strategy.best_at_target()?; - let best_finalized_source_header_id_at_best_target = - race_state.best_finalized_source_header_id_at_best_target()?; - let latest_confirmed_nonce_at_source = self - .latest_confirmed_nonces_at_source - .iter() - .take_while(|(id, _)| id.0 <= best_finalized_source_header_id_at_best_target.0) - .last() - .map(|(_, nonce)| *nonce) - .unwrap_or(best_target_nonce); - let target_nonces = self.target_nonces.as_ref()?; - - // There's additional condition in the message delivery race: target would reject messages - // if there are too much unconfirmed messages at the inbound lane. - - // The receiving race is responsible to deliver confirmations back to the source chain. So - // if there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. - let latest_received_nonce_at_target = target_nonces.latest_nonce; - let confirmations_missing = - latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); - match confirmations_missing { - Some(confirmations_missing) - if confirmations_missing >= self.max_unconfirmed_nonces_at_target => - { - log::debug!( - target: "bridge", - "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ - at target: target.latest_received={:?}, source.latest_confirmed={:?}, max={:?}", - MessageDeliveryRace::

::source_name(), - MessageDeliveryRace::

::target_name(), - latest_received_nonce_at_target, - latest_confirmed_nonce_at_source, - self.max_unconfirmed_nonces_at_target, - ); - - return None - }, - _ => (), - } - - // Ok - we may have new nonces to deliver. But target may still reject new messages, because - // we haven't notified it that (some) messages have been confirmed. So we may want to - // include updated `source.latest_confirmed` in the proof. - // - // Important note: we're including outbound state lane proof whenever there are unconfirmed - // nonces on the target chain. Other strategy is to include it only if it's absolutely - // necessary. - let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce; - let outbound_state_proof_required = - latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; - - // The target node would also reject messages if there are too many entries in the - // "unrewarded relayers" set. If we are unable to prove new rewards to the target node, then - // we should wait for confirmations race. - let unrewarded_relayer_entries_limit_reached = - target_nonces.nonces_data.unrewarded_relayers.unrewarded_relayer_entries >= - self.max_unrewarded_relayer_entries_at_target; - if unrewarded_relayer_entries_limit_reached { - // so there are already too many unrewarded relayer entries in the set - // - // => check if we can prove enough rewards. If not, we should wait for more rewards to - // be paid - let number_of_rewards_being_proved = - latest_confirmed_nonce_at_source.saturating_sub(latest_confirmed_nonce_at_target); - let enough_rewards_being_proved = number_of_rewards_being_proved >= - target_nonces.nonces_data.unrewarded_relayers.messages_in_oldest_entry; - if !enough_rewards_being_proved { - return None - } - } - - // If we're here, then the confirmations race did its job && sending side now knows that - // messages have been delivered. Now let's select nonces that we want to deliver. - // - // We may deliver at most: - // - // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - - // latest_confirmed_nonce_at_target) - // - // messages in the batch. But since we're including outbound state proof in the batch, then - // it may be increased to: - // - // max_unconfirmed_nonces_at_target - (latest_received_nonce_at_target - - // latest_confirmed_nonce_at_source) - let future_confirmed_nonce_at_target = if outbound_state_proof_required { - latest_confirmed_nonce_at_source - } else { - latest_confirmed_nonce_at_target - }; - let max_nonces = latest_received_nonce_at_target - .checked_sub(future_confirmed_nonce_at_target) - .and_then(|diff| self.max_unconfirmed_nonces_at_target.checked_sub(diff)) - .unwrap_or_default(); - let max_nonces = std::cmp::min(max_nonces, self.max_messages_in_single_batch); - let max_messages_weight_in_single_batch = self.max_messages_weight_in_single_batch; - let max_messages_size_in_single_batch = self.max_messages_size_in_single_batch; - let lane_source_client = self.lane_source_client.clone(); - let lane_target_client = self.lane_target_client.clone(); - - let available_source_queue_indices = - self.strategy.available_source_queue_indices(race_state)?; - let source_queue = self.strategy.source_queue(); - - let reference = RelayMessagesBatchReference { - max_messages_in_this_batch: max_nonces, - max_messages_weight_in_single_batch, - max_messages_size_in_single_batch, - lane_source_client: lane_source_client.clone(), - lane_target_client: lane_target_client.clone(), - best_target_nonce, - nonces_queue: source_queue.clone(), - nonces_queue_range: available_source_queue_indices, - metrics: self.metrics_msg.clone(), - }; - - let selected_nonces = MessageRaceLimits::decide(reference).await?; - let dispatch_weight = self.dispatch_weight_for_range(&selected_nonces); - - Some(( - selected_nonces, - MessageProofParameters { outbound_state_proof_required, dispatch_weight }, - )) + self.select_race_action(race_state).await } } @@ -980,31 +1047,41 @@ mod tests { ); // nothing needs to be delivered now and we don't need any new headers assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - assert_eq!(strategy.required_source_header_at_target(&header_id(1), state.clone()), None); - - // now let's generate two more nonces [24; 25] at the soruce; - strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 19, 0)); - // - // - so now we'll need to relay source block#2 to be able to accept messages [24; 25]. - assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - assert_eq!( - strategy.required_source_header_at_target(&header_id(1), state.clone()), - Some(header_id(2)) - ); + assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); - // let's relay source block#2 + // block#2 is generated state.best_finalized_source_header_id_at_source = Some(header_id(2)); state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); state.best_target_header_id = Some(header_id(2)); state.best_finalized_target_header_id = Some(header_id(2)); + // now let's generate two more nonces [24; 25] at the source; + strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 19, 0)); + // + // we don't need to relay more headers to target, because messages [20; 23] have + // not confirmed to source yet + assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); + assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); + + // let's relay source block#3 + state.best_finalized_source_header_id_at_source = Some(header_id(3)); + state.best_finalized_source_header_id_at_best_target = Some(header_id(3)); + state.best_target_header_id = Some(header_id(3)); + state.best_finalized_target_header_id = Some(header_id(3)); + // and ask strategy again => still nothing to deliver, because parallel confirmations // race need to be pushed further assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None); - assert_eq!(strategy.required_source_header_at_target(&header_id(2), state.clone()), None); + assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); + + // let's relay source block#3 + state.best_finalized_source_header_id_at_source = Some(header_id(4)); + state.best_finalized_source_header_id_at_best_target = Some(header_id(4)); + state.best_target_header_id = Some(header_id(4)); + state.best_finalized_target_header_id = Some(header_id(4)); // let's confirm messages [20; 23] - strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 23, 0)); + strategy.source_nonces_updated(header_id(4), source_nonces(24..=25, 23, 0)); // and ask strategy again => now we have everything required to deliver remaining // [24; 25] nonces and proof of [20; 23] confirmation @@ -1012,7 +1089,7 @@ mod tests { strategy.select_nonces_to_deliver(state.clone()).await, Some(((24..=25), proof_parameters(true, 2))), ); - assert_eq!(strategy.required_source_header_at_target(&header_id(2), state), None); + assert_eq!(strategy.required_source_header_at_target(state).await, None); } #[async_std::test] @@ -1041,9 +1118,9 @@ mod tests { ); } - #[test] + #[async_std::test] #[allow(clippy::reversed_empty_ranges)] - fn no_source_headers_required_at_target_if_lanes_are_empty() { + async fn no_source_headers_required_at_target_if_lanes_are_empty() { let (state, _) = prepare_strategy(); let mut strategy = TestStrategy { max_unrewarded_relayer_entries_at_target: 4, @@ -1073,7 +1150,7 @@ mod tests { strategy.latest_confirmed_nonces_at_source, VecDeque::from([(source_header_id, 0)]) ); - assert_eq!(strategy.required_source_header_at_target(&source_header_id, state), None); + assert_eq!(strategy.required_source_header_at_target(state).await, None); } #[async_std::test] @@ -1159,4 +1236,138 @@ mod tests { )), ); } + + #[async_std::test] + #[allow(clippy::reversed_empty_ranges)] + async fn delivery_race_is_able_to_unblock_lane() { + // step 1: messages 20..=23 are delivered from source to target at target block 2 + fn at_target_block_2_deliver_messages( + strategy: &mut TestStrategy, + state: &mut TestRaceState, + occupied_relayer_slots: MessageNonce, + occupied_message_slots: MessageNonce, + ) { + let nonces_at_target = TargetClientNonces { + latest_nonce: 23, + nonces_data: DeliveryRaceTargetNoncesData { + confirmed_nonce: 19, + unrewarded_relayers: UnrewardedRelayersState { + unrewarded_relayer_entries: occupied_relayer_slots, + total_messages: occupied_message_slots, + ..Default::default() + }, + }, + }; + + state.best_target_header_id = Some(header_id(2)); + state.best_finalized_target_header_id = Some(header_id(2)); + + strategy.best_target_nonces_updated(nonces_at_target.clone(), state); + strategy.finalized_target_nonces_updated(nonces_at_target, state); + } + + // step 2: delivery of messages 20..=23 is confirmed to the source node at source block 2 + fn at_source_block_2_deliver_confirmations( + strategy: &mut TestStrategy, + state: &mut TestRaceState, + ) { + state.best_finalized_source_header_id_at_source = Some(header_id(2)); + + strategy.source_nonces_updated( + header_id(2), + SourceClientNonces { new_nonces: Default::default(), confirmed_nonce: Some(23) }, + ); + } + + // step 3: finalize source block 2 at target block 3 and select nonces to deliver + async fn at_target_block_3_select_nonces_to_deliver( + strategy: &TestStrategy, + mut state: TestRaceState, + ) -> Option<(RangeInclusive, MessageProofParameters)> { + state.best_finalized_source_header_id_at_best_target = Some(header_id(2)); + state.best_target_header_id = Some(header_id(3)); + state.best_finalized_target_header_id = Some(header_id(3)); + + strategy.select_nonces_to_deliver(state).await + } + + let max_unrewarded_relayer_entries_at_target = 4; + let max_unconfirmed_nonces_at_target = 4; + let expected_rewards_proof = Some(( + 1..=0, + MessageProofParameters { + outbound_state_proof_required: true, + dispatch_weight: Weight::zero(), + }, + )); + + // TODO: also fix + test `required_source_header_at_target` + + // when lane is NOT blocked + let (mut state, mut strategy) = prepare_strategy(); + at_target_block_2_deliver_messages( + &mut strategy, + &mut state, + max_unrewarded_relayer_entries_at_target - 1, + max_unconfirmed_nonces_at_target - 1, + ); + at_source_block_2_deliver_confirmations(&mut strategy, &mut state); + assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); + assert_eq!(at_target_block_3_select_nonces_to_deliver(&strategy, state).await, None); + + // when lane is blocked by no-relayer-slots in unrewarded relayers vector + let (mut state, mut strategy) = prepare_strategy(); + at_target_block_2_deliver_messages( + &mut strategy, + &mut state, + max_unrewarded_relayer_entries_at_target, + max_unconfirmed_nonces_at_target - 1, + ); + at_source_block_2_deliver_confirmations(&mut strategy, &mut state); + assert_eq!( + strategy.required_source_header_at_target(state.clone()).await, + Some(header_id(2)) + ); + assert_eq!( + at_target_block_3_select_nonces_to_deliver(&strategy, state).await, + expected_rewards_proof + ); + + // when lane is blocked by no-message-slots in unrewarded relayers vector + let (mut state, mut strategy) = prepare_strategy(); + at_target_block_2_deliver_messages( + &mut strategy, + &mut state, + max_unrewarded_relayer_entries_at_target - 1, + max_unconfirmed_nonces_at_target, + ); + at_source_block_2_deliver_confirmations(&mut strategy, &mut state); + assert_eq!( + strategy.required_source_header_at_target(state.clone()).await, + Some(header_id(2)) + ); + assert_eq!( + at_target_block_3_select_nonces_to_deliver(&strategy, state).await, + expected_rewards_proof + ); + + // when lane is blocked by no-message-slots and no-message-slots in unrewarded relayers + // vector + let (mut state, mut strategy) = prepare_strategy(); + at_target_block_2_deliver_messages( + &mut strategy, + &mut state, + max_unrewarded_relayer_entries_at_target - 1, + max_unconfirmed_nonces_at_target, + ); + at_source_block_2_deliver_confirmations(&mut strategy, &mut state); + assert_eq!( + strategy.required_source_header_at_target(state.clone()).await, + Some(header_id(2)) + ); + assert_eq!( + at_target_block_3_select_nonces_to_deliver(&strategy, state).await, + expected_rewards_proof + ); + } } diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 7e3f84dd5d119..be7d5b4675659 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -41,14 +41,14 @@ use std::{ /// One of races within lane. pub trait MessageRace { /// Header id of the race source. - type SourceHeaderId: Debug + Clone + PartialEq + Send; + type SourceHeaderId: Debug + Clone + PartialEq + Send + Sync; /// Header id of the race source. - type TargetHeaderId: Debug + Clone + PartialEq + Send; + type TargetHeaderId: Debug + Clone + PartialEq + Send + Sync; /// Message nonce used in the race. type MessageNonce: Debug + Clone; /// Proof that is generated and delivered in this race. - type Proof: Debug + Clone + Send; + type Proof: Debug + Clone + Send + Sync; /// Name of the race source. fn source_name() -> String; @@ -175,9 +175,8 @@ pub trait RaceStrategy: Debug { /// Should return true if nothing has to be synced. fn is_empty(&self) -> bool; /// Return id of source header that is required to be on target to continue synchronization. - fn required_source_header_at_target>( + async fn required_source_header_at_target>( &self, - current_best: &SourceHeaderId, race_state: RS, ) -> Option; /// Return the best nonce at source node. @@ -218,7 +217,11 @@ pub trait RaceStrategy: Debug { } /// State of the race. -pub trait RaceState: Send { +pub trait RaceState: Clone + Send + Sync { + /// Set best finalized source header id at the best block on the target + /// client (at the `best_finalized_source_header_id_at_best_target`). + fn set_best_finalized_source_header_id_at_best_target(&mut self, id: SourceHeaderId); + /// Best finalized source header id at the source client. fn best_finalized_source_header_id_at_source(&self) -> Option; /// Best finalized source header id at the best block on the target @@ -281,11 +284,15 @@ impl Default impl RaceState for RaceStateImpl where - SourceHeaderId: Clone + Send, - TargetHeaderId: Clone + Send, - Proof: Clone + Send, - BatchTx: Clone + Send, + SourceHeaderId: Clone + Send + Sync, + TargetHeaderId: Clone + Send + Sync, + Proof: Clone + Send + Sync, + BatchTx: Clone + Send + Sync, { + fn set_best_finalized_source_header_id_at_best_target(&mut self, id: SourceHeaderId) { + self.best_finalized_source_header_id_at_best_target = Some(id); + } + fn best_finalized_source_header_id_at_source(&self) -> Option { self.best_finalized_source_header_id_at_source.clone() } @@ -430,10 +437,9 @@ pub async fn run, TC: TargetClient

>( ).fail_if_connection_error(FailedClient::Source)?; // ask for more headers if we have nonces to deliver and required headers are missing - source_required_header = race_state - .best_finalized_source_header_id_at_best_target - .as_ref() - .and_then(|best| strategy.required_source_header_at_target(best, race_state.clone())); + source_required_header = strategy + .required_source_header_at_target(race_state.clone()) + .await; }, nonces = target_best_nonces => { target_best_nonces_required = false; diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index e6016448c95cc..718c296391c5c 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -205,16 +205,16 @@ impl< self.source_queue.is_empty() } - fn required_source_header_at_target< + async fn required_source_header_at_target< RS: RaceState< HeaderId, HeaderId, >, >( &self, - current_best: &HeaderId, - _race_state: RS, + race_state: RS, ) -> Option> { + let current_best = race_state.best_finalized_source_header_id_at_best_target()?; self.source_queue .back() .and_then(|(h, _)| if h.0 > current_best.0 { Some(h.clone()) } else { None }) From b01e671dc54d8fa330ebda93940c66b50110a536 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 21 Apr 2023 15:53:51 +0300 Subject: [PATCH 1031/1210] Another use of RangeInclusiveExt::checked_len() (#2060) --- bin/runtime-common/src/messages.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 9d2e5811380c5..6f6b19595775d 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -20,7 +20,7 @@ //! pallet is used to dispatch incoming messages. Message identified by a tuple //! of to elements - message lane id and message nonce. -pub use bp_runtime::{UnderlyingChainOf, UnderlyingChainProvider}; +pub use bp_runtime::{RangeInclusiveExt, UnderlyingChainOf, UnderlyingChainProvider}; use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_messages::{ @@ -365,6 +365,7 @@ pub mod target { nonces_start, nonces_end, } = proof; + let nonces_range = nonces_start..=nonces_end; B::BridgedHeaderChain::parse_finalized_storage_proof( bridged_header_hash, @@ -374,26 +375,17 @@ pub mod target { StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default() }; // receiving proofs where end < begin is ok (if proof includes outbound lane state) - let messages_in_the_proof = - if let Some(nonces_difference) = nonces_end.checked_sub(nonces_start) { - // let's check that the user (relayer) has passed correct `messages_count` - // (this bounds maximal capacity of messages vec below) - let messages_in_the_proof = nonces_difference.saturating_add(1); - if messages_in_the_proof != MessageNonce::from(messages_count) { - return Err(Error::MessagesCountMismatch) - } - - messages_in_the_proof - } else { - 0 - }; + let messages_in_the_proof = nonces_range.checked_len().unwrap_or(0); + if messages_in_the_proof != MessageNonce::from(messages_count) { + return Err(Error::MessagesCountMismatch) + } // Read messages first. All messages that are claimed to be in the proof must // be in the proof. So any error in `read_value`, or even missing value is fatal. // // Mind that we allow proofs with no messages if outbound lane state is proved. let mut messages = Vec::with_capacity(messages_in_the_proof as _); - for nonce in nonces_start..=nonces_end { + for nonce in nonces_range { let message_key = MessageKey { lane_id: lane, nonce }; let message_payload = parser.read_and_decode_message_payload(&message_key)?; messages.push(Message { key: message_key, payload: message_payload }); From f477a1c00912c30ac36258443dfdc957253eeb03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 02:01:16 +0000 Subject: [PATCH 1032/1210] Bump clap from 4.2.2 to 4.2.4 Bumps [clap](https://github.com/clap-rs/clap) from 4.2.2 to 4.2.4. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.2.2...v4.2.4) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 21b5cd02559d9..7eb7c79405be8 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.2", features = ["derive"] } +clap = { version = "4.2.4", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.96" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 2315eb94a116d..38521d7aa0e21 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.2.2", features = ["derive"] } +clap = { version = "4.2.4", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 23c7d3315e765..ffbb587dc1f57 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.2", features = ["derive"] } +clap = { version = "4.2.4", features = ["derive"] } serde_json = "1.0.96" # Bridge dependencies From dda9f698048edecdacc5e924dae21e9fac39792e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 24 Apr 2023 15:46:50 +0300 Subject: [PATCH 1033/1210] [relay-substrate-client] Bump jsonrpsee (#2066) --- bin/rialto/runtime/src/lib.rs | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-substrate/src/client.rs | 2 +- relays/client-substrate/src/error.rs | 12 +++++------- relays/client-substrate/src/rpc.rs | 6 +++--- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index aeb0a3a7c5749..b325332acba5c 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -495,7 +495,7 @@ construct_runtime!( Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage}, Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config}, Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, - Dmp: polkadot_runtime_parachains::dmp::{Pallet, Call, Storage}, + Dmp: polkadot_runtime_parachains::dmp::{Pallet, Storage}, Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event}, Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 2a79832bf9d64..90904ab9be11f 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -10,7 +10,7 @@ async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.28" -jsonrpsee = { version = "0.16", features = ["macros", "ws-client"] } +jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.8" diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 27af7d7d77f74..91ff7b9a214d4 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -231,7 +231,7 @@ impl Client { let client = tokio .spawn(async move { RpcClientBuilder::default() - .max_notifs_per_subscription(MAX_SUBSCRIPTION_CAPACITY) + .max_buffer_capacity_per_subscription(MAX_SUBSCRIPTION_CAPACITY) .build(&uri) .await }) diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 54247c5dc1768..40015c122bbe9 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -138,13 +138,11 @@ impl Error { impl MaybeConnectionError for Error { fn is_connection_error(&self) -> bool { match *self { - Error::RpcError(RpcError::Transport(_)) - // right now if connection to the ws server is dropped (after it is already established), - // we're getting this error - | Error::RpcError(RpcError::Internal(_)) - | Error::RpcError(RpcError::RestartNeeded(_)) - | Error::ClientNotSynced(_) => true, - Error::FailedToReadBestFinalizedHeaderHash { ref error, .. } => error.is_connection_error(), + Error::RpcError(RpcError::Transport(_)) | + Error::RpcError(RpcError::RestartNeeded(_)) | + Error::ClientNotSynced(_) => true, + Error::FailedToReadBestFinalizedHeaderHash { ref error, .. } => + error.is_connection_error(), Error::FailedToReadBestHeader { ref error, .. } => error.is_connection_error(), Error::FailedToReadHeaderByHash { ref error, .. } => error.is_connection_error(), Error::ErrorExecutingRuntimeCall { ref error, .. } => error.is_connection_error(), diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 083b1dea761a1..94726e49187ab 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -73,7 +73,7 @@ pub(crate) trait SubstrateAuthor { async fn pending_extrinsics(&self) -> RpcResult>; /// Submit and watch for extrinsic state. #[subscription(name = "submitAndWatchExtrinsic", unsubscribe = "unwatchExtrinsic", item = TransactionStatusOf)] - fn submit_and_watch_extrinsic(&self, extrinsic: Bytes); + async fn submit_and_watch_extrinsic(&self, extrinsic: Bytes); } /// RPC methods of Substrate `state` namespace, that we are using. @@ -118,7 +118,7 @@ pub trait SubstrateFinalityClient { pub(crate) trait SubstrateGrandpa { /// Subscribe to GRANDPA justifications. #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] - fn subscribe_justifications(&self); + async fn subscribe_justifications(&self); } /// RPC finality methods of Substrate `grandpa` namespace, that we are using. @@ -136,7 +136,7 @@ impl SubstrateFinalityClient for SubstrateGrandpaFinalit pub(crate) trait SubstrateBeefy { /// Subscribe to BEEFY justifications. #[subscription(name = "subscribeJustifications", unsubscribe = "unsubscribeJustifications", item = Bytes)] - fn subscribe_justifications(&self); + async fn subscribe_justifications(&self); } /// RPC finality methods of Substrate `beefy` namespace, that we are using. From abc8ed57fa43d348c3bfa093133ee39b0c51c41b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 24 Apr 2023 17:33:53 +0300 Subject: [PATCH 1034/1210] select nothing if we have already selected nonces to submit or have submitted something (#2065) --- relays/messages/src/message_race_delivery.rs | 38 ++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 4af02ba2b568a..cd691d17f7e3d 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -322,6 +322,16 @@ where &self, race_state: RS, ) -> Option<(RangeInclusive, MessageProofParameters)> { + // if we have already selected nonces that we want to submit, do nothing + if race_state.nonces_to_submit().is_some() { + return None + } + + // if we already submitted some nonces, do nothing + if race_state.nonces_submitted().is_some() { + return None + } + let best_target_nonce = self.strategy.best_at_target()?; let best_finalized_source_header_id_at_best_target = race_state.best_finalized_source_header_id_at_best_target()?; @@ -1301,8 +1311,6 @@ mod tests { }, )); - // TODO: also fix + test `required_source_header_at_target` - // when lane is NOT blocked let (mut state, mut strategy) = prepare_strategy(); at_target_block_2_deliver_messages( @@ -1369,5 +1377,31 @@ mod tests { at_target_block_3_select_nonces_to_deliver(&strategy, state).await, expected_rewards_proof ); + + // when we have already selected some nonces to deliver, we don't need to select anything + let (mut state, mut strategy) = prepare_strategy(); + at_target_block_2_deliver_messages( + &mut strategy, + &mut state, + max_unrewarded_relayer_entries_at_target - 1, + max_unconfirmed_nonces_at_target, + ); + at_source_block_2_deliver_confirmations(&mut strategy, &mut state); + state.nonces_to_submit = Some((header_id(2), 1..=0, (1..=0, None))); + assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); + assert_eq!(at_target_block_3_select_nonces_to_deliver(&strategy, state).await, None); + + // when we have already submitted some nonces, we don't need to select anything + let (mut state, mut strategy) = prepare_strategy(); + at_target_block_2_deliver_messages( + &mut strategy, + &mut state, + max_unrewarded_relayer_entries_at_target - 1, + max_unconfirmed_nonces_at_target, + ); + at_source_block_2_deliver_confirmations(&mut strategy, &mut state); + state.nonces_submitted = Some(1..=0); + assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); + assert_eq!(at_target_block_3_select_nonces_to_deliver(&strategy, state).await, None); } } From 1855dc1f1388d9f2a8d3608f007b1b5027c567c6 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 24 Apr 2023 18:11:45 +0300 Subject: [PATCH 1035/1210] fix the way latest_confirmed_nonce_at_source is "calculated" (#2067) --- relays/messages/src/message_race_delivery.rs | 37 ++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index cd691d17f7e3d..8a667fdbdb890 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -335,10 +335,10 @@ where let best_target_nonce = self.strategy.best_at_target()?; let best_finalized_source_header_id_at_best_target = race_state.best_finalized_source_header_id_at_best_target()?; + let target_nonces = self.target_nonces.as_ref()?; let latest_confirmed_nonce_at_source = self .latest_confirmed_nonce_at_source(&best_finalized_source_header_id_at_best_target) - .unwrap_or(best_target_nonce); - let target_nonces = self.target_nonces.as_ref()?; + .unwrap_or(target_nonces.nonces_data.confirmed_nonce); // There's additional condition in the message delivery race: target would reject messages // if there are too much unconfirmed messages at the inbound lane. @@ -1404,4 +1404,37 @@ mod tests { assert_eq!(strategy.required_source_header_at_target(state.clone()).await, None); assert_eq!(at_target_block_3_select_nonces_to_deliver(&strategy, state).await, None); } + + #[async_std::test] + async fn outbound_state_proof_is_not_required_when_we_have_no_new_confirmations() { + let (mut state, mut strategy) = prepare_strategy(); + + // pretend that we haven't seen any confirmations yet (or they're at the future target chain + // blocks) + strategy.latest_confirmed_nonces_at_source.clear(); + + // emulate delivery of some nonces (20..=23 are generated, but we only deliver 20..=21) + let nonces_at_target = TargetClientNonces { + latest_nonce: 21, + nonces_data: DeliveryRaceTargetNoncesData { + confirmed_nonce: 19, + unrewarded_relayers: UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 2, + ..Default::default() + }, + }, + }; + state.best_target_header_id = Some(header_id(2)); + state.best_finalized_target_header_id = Some(header_id(2)); + strategy.best_target_nonces_updated(nonces_at_target.clone(), &mut state); + strategy.finalized_target_nonces_updated(nonces_at_target, &mut state); + + // we won't include outbound lane state proof into 22..=23 delivery transaction + // because it brings no new reward confirmations + assert_eq!( + strategy.select_nonces_to_deliver(state).await, + Some(((22..=23), proof_parameters(false, 2))) + ); + } } From daf4c7d5f07bf5dbe47282fd17a51c0b6a3a9bee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 25 Apr 2023 16:24:13 +0300 Subject: [PATCH 1036/1210] Slash relayers for invalid transactions (#2025) * slash relayer balance for invalid transactions * require some gap before unstake is possible * more clippy * log priority boost * add issue ref to TODO * fix typo * is_message_delivery_call -> is_receive_messages_proof_call * moved is_receive_messages_proof_call above * only slash relayers for priority transactions * Update primitives/relayers/src/registration.rs Co-authored-by: Adrian Catangiu * Update primitives/relayers/src/registration.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/refund_relayer_extension.rs Co-authored-by: Adrian Catangiu * Update modules/relayers/src/lib.rs Co-authored-by: Adrian Catangiu * Update primitives/relayers/src/registration.rs Co-authored-by: Adrian Catangiu * benificiary -> beneficiary --------- Co-authored-by: Adrian Catangiu --- bin/millau/runtime/src/lib.rs | 9 + bin/rialto-parachain/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/lib.rs | 1 + bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages_call_ext.rs | 10 + bin/runtime-common/src/mock.rs | 24 +- .../src/refund_relayer_extension.rs | 694 +++++++++++++----- modules/relayers/src/lib.rs | 581 ++++++++++++++- modules/relayers/src/mock.rs | 45 +- modules/relayers/src/stake_adapter.rs | 186 +++++ primitives/relayers/src/lib.rs | 4 + primitives/relayers/src/registration.rs | 121 +++ 12 files changed, 1495 insertions(+), 183 deletions(-) create mode 100644 modules/relayers/src/stake_adapter.rs create mode 100644 primitives/relayers/src/registration.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4e6f1e43e8c6d..dccd75a5b0014 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -372,6 +372,7 @@ parameter_types! { /// Authorities are changing every 5 minutes. pub const Period: BlockNumber = bp_millau::SESSION_LENGTH; pub const Offset: BlockNumber = 0; + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; } impl pallet_session::Config for Runtime { @@ -392,6 +393,14 @@ impl pallet_bridge_relayers::Config for Runtime { type Reward = Balance; type PaymentProcedure = bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + ConstU64<1_000>, + ConstU64<8>, + >; type WeightInfo = (); } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index cd4e256f4203e..cd5c45ec4ba9a 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -533,6 +533,7 @@ impl pallet_bridge_relayers::Config for Runtime { type Reward = Balance; type PaymentProcedure = bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = (); type WeightInfo = (); } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index b325332acba5c..0d2c667efa533 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -389,6 +389,7 @@ impl pallet_bridge_relayers::Config for Runtime { type Reward = Balance; type PaymentProcedure = bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = (); type WeightInfo = (); } diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 3db4ae9abca6e..e7cd39da90b12 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -30,6 +30,7 @@ pallet-bridge-relayers = { path = "../../modules/relayers", default-features = f frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -62,6 +63,7 @@ std = [ "frame-system/std", "hash-db/std", "log/std", + "pallet-balances/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-parachains/std", diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index f3665a8d93b52..3f48ce583f9ce 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -115,6 +115,16 @@ pub enum CallInfo { ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo), } +impl CallInfo { + /// Returns range of messages, bundled with the call. + pub fn bundled_messages(&self) -> RangeInclusive { + match *self { + Self::ReceiveMessagesProof(ref info) => info.base.bundled_range.clone(), + Self::ReceiveMessagesDeliveryProof(ref info) => info.0.bundled_range.clone(), + } + } +} + /// Helper struct that provides methods for working with a call supported by `CallInfo`. pub struct CallHelper, I: 'static> { pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 036813f6fd514..c176719967614 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -35,6 +35,7 @@ use crate::messages::{ use bp_header_chain::{ChainWithGrandpa, HeaderChain}; use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_relayers::PayRewardFromAccount; use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; use codec::{Decode, Encode}; use frame_support::{ @@ -83,6 +84,20 @@ pub type BridgedChainHasher = BlakeTwo256; pub type BridgedChainHeader = sp_runtime::generic::Header; +/// Rewards payment procedure. +pub type TestPaymentProcedure = PayRewardFromAccount; +/// Stake that we are using in tests. +pub type TestStake = ConstU64<5_000>; +/// Stake and slash mechanism to use in tests. +pub type TestStakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + ThisChainAccountId, + ThisChainBlockNumber, + Balances, + ReserveId, + TestStake, + ConstU32<8>, +>; + /// Message lane used in tests. pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); /// Bridged chain id used in tests. @@ -128,6 +143,7 @@ parameter_types! { pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); pub const MaxUnrewardedRelayerEntriesAtInboundLane: MessageNonce = 16; pub const MaxUnconfirmedMessagesAtInboundLane: MessageNonce = 1_000; + pub const ReserveId: [u8; 8] = *b"brdgrlrs"; } impl frame_system::Config for TestRuntime { @@ -244,7 +260,8 @@ impl pallet_bridge_messages::Config for TestRuntime { impl pallet_bridge_relayers::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Reward = ThisChainBalance; - type PaymentProcedure = (); + type PaymentProcedure = TestPaymentProcedure; + type StakeAndSlash = TestStakeAndSlash; type WeightInfo = (); } @@ -400,3 +417,8 @@ impl ThisChainWithMessages for BridgedChain { } impl BridgedChainWithMessages for BridgedChain {} + +/// Run test within test externalities. +pub fn run_test(test: impl FnOnce()) { + sp_io::TestExternalities::new(Default::default()).execute_with(test) +} diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 925fea2a74349..7d65263e9fd06 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -22,7 +22,7 @@ use crate::messages_call_ext::{ CallHelper as MessagesCallHelper, CallInfo as MessagesCallInfo, MessagesCallSubType, }; -use bp_messages::LaneId; +use bp_messages::{LaneId, MessageNonce}; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::{RangeInclusiveExt, StaticStrProvider}; use codec::{Decode, Encode}; @@ -30,7 +30,7 @@ use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, traits::IsSubType, weights::Weight, - CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, + CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, }; use pallet_bridge_grandpa::{ CallSubType as GrandpaCallSubType, SubmitFinalityProofHelper, SubmitFinalityProofInfo, @@ -53,6 +53,7 @@ use sp_runtime::{ }; use sp_std::{marker::PhantomData, vec, vec::Vec}; +type AccountIdOf = ::AccountId; // without this typedef rustfmt fails with internal err type BalanceOf = <::OnChargeTransaction as OnChargeTransaction>::Balance; @@ -158,6 +159,14 @@ pub enum CallInfo { } impl CallInfo { + /// Returns true if call is a message delivery call (with optional finality calls). + fn is_receive_messages_proof_call(&self) -> bool { + match self.messages_call_info() { + MessagesCallInfo::ReceiveMessagesProof(_) => true, + MessagesCallInfo::ReceiveMessagesDeliveryProof(_) => false, + } + } + /// Returns the pre-dispatch `finality_target` sent to the `SubmitFinalityProof` call. fn submit_finality_proof_info(&self) -> Option> { match *self { @@ -185,6 +194,17 @@ impl CallInfo { } } +/// The actions on relayer account that need to be performed because of his actions. +#[derive(RuntimeDebug, PartialEq)] +enum RelayerAccountAction { + /// Do nothing with relayer account. + None, + /// Reward the relayer. + Reward(AccountId, RewardsAccountParams, Reward), + /// Slash the relayer. + Slash(AccountId, RewardsAccountParams), +} + /// Signed extension that refunds a relayer for new messages coming from a parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) @@ -205,7 +225,25 @@ impl CallInfo { )] #[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Priority, Id))] pub struct RefundBridgedParachainMessages( - PhantomData<(Runtime, Para, Msgs, Refund, Priority, Id)>, + PhantomData<( + // runtime with `frame-utility`, `pallet-bridge-grandpa`, `pallet-bridge-parachains`, + // `pallet-bridge-messages` and `pallet-bridge-relayers` pallets deployed + Runtime, + // implementation of `RefundableParachainId` trait, which specifies the instance of + // the used `pallet-bridge-parachains` pallet and the bridged parachain id + Para, + // implementation of `RefundableMessagesLaneId` trait, which specifies the instance of + // the used `pallet-bridge-messages` pallet and the lane within this pallet + Msgs, + // implementation of the `RefundCalculator` trait, that is used to compute refund that + // we give to relayer for his transaction + Refund, + // getter for per-message `TransactionPriority` boost that we give to message + // delivery transactions + Priority, + // the runtime-unique identifier of this signed extension + Id, + )>, ); impl @@ -215,9 +253,13 @@ where Runtime: UtilityConfig> + BoundedBridgeGrandpaConfig + ParachainsConfig - + MessagesConfig, + + MessagesConfig + + RelayersConfig, Para: RefundableParachainId, Msgs: RefundableMessagesLaneId, + Refund: RefundCalculator, + Priority: Get, + Id: StaticStrProvider, CallOf: Dispatchable + IsSubType, Runtime>> + GrandpaCallSubType @@ -268,118 +310,69 @@ where call.check_obsolete_call()?; Ok(call) } -} - -impl SignedExtension - for RefundBridgedParachainMessages -where - Self: 'static + Send + Sync, - Runtime: UtilityConfig> - + BoundedBridgeGrandpaConfig - + ParachainsConfig - + MessagesConfig - + RelayersConfig, - Para: RefundableParachainId, - Msgs: RefundableMessagesLaneId, - Refund: RefundCalculator, - Priority: Get, - Id: StaticStrProvider, - CallOf: Dispatchable - + IsSubType, Runtime>> - + GrandpaCallSubType - + ParachainsCallSubType - + MessagesCallSubType, -{ - const IDENTIFIER: &'static str = Id::STR; - type AccountId = Runtime::AccountId; - type Call = CallOf; - type AdditionalSigned = (); - type Pre = Option>; - - fn additional_signed(&self) -> Result<(), TransactionValidityError> { - Ok(()) - } - fn validate( - &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> TransactionValidity { - // this is the only relevant line of code for the `pre_dispatch` - // - // we're not calling `validato` from `pre_dispatch` directly because of performance - // reasons, so if you're adding some code that may fail here, please check if it needs - // to be added to the `pre_dispatch` as well - let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + /// Given post-dispatch information, analyze the outcome of relayer call and return + /// actions that need to be performed on relayer account. + fn analyze_call_result( + pre: Option>>, + info: &DispatchInfo, + post_info: &PostDispatchInfo, + len: usize, + result: &DispatchResult, + ) -> RelayerAccountAction, Runtime::Reward> { + let mut extra_weight = Weight::zero(); + let mut extra_size = 0; - // the following code just plays with transaction priority and never returns an error - let mut valid_transaction = ValidTransactionBuilder::default(); - if let Some(parsed_call) = parsed_call { - // we give delivery transactions some boost, that depends on number of messages inside - let messages_call_info = parsed_call.messages_call_info(); - if let MessagesCallInfo::ReceiveMessagesProof(info) = messages_call_info { - // compute total number of messages in transaction - let bundled_messages = info.base.bundled_range.checked_len().unwrap_or(0); - - // a quick check to avoid invalid high-priority transactions - if bundled_messages <= Runtime::MaxUnconfirmedMessagesAtInboundLane::get() { - let priority_boost = crate::priority_calculator::compute_priority_boost::< - Priority, - >(bundled_messages); - valid_transaction = valid_transaction.priority(priority_boost); - } - } - } + // We don't refund anything for transactions that we don't support. + let (relayer, call_info) = match pre { + Some(Some(pre)) => (pre.relayer, pre.call_info), + _ => return RelayerAccountAction::None, + }; - valid_transaction.build() - } + // now we know that the relayer either needs to be rewarded, or slashed + // => let's prepare the correspondent account that pays reward/receives slashed amount + let reward_account_params = RewardsAccountParams::new( + Msgs::Id::get(), + Runtime::BridgedChainId::get(), + if call_info.is_receive_messages_proof_call() { + RewardsAccountOwner::ThisChain + } else { + RewardsAccountOwner::BridgedChain + }, + ); - fn pre_dispatch( - self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) - let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + // prepare return value for the case if the call has failed or it has not caused + // expected side effects (e.g. not all messages have been accepted) + // + // we are not checking if relayer is registered here - it happens during the slash attempt + // + // there are couple of edge cases here: + // + // - when the relayer becomes registered during message dispatch: this is unlikely + relayer + // should be ready for slashing after registration; + // + // - when relayer is registered after `validate` is called and priority is not boosted: + // relayer should be ready for slashing after registration. + let may_slash_relayer = + Self::bundled_messages_for_priority_boost(Some(&call_info)).is_some(); + let slash_relayer_if_delivery_result = may_slash_relayer + .then(|| RelayerAccountAction::Slash(relayer.clone(), reward_account_params)) + .unwrap_or(RelayerAccountAction::None); - Ok(parsed_call.map(|call_info| { + // We don't refund anything if the transaction has failed. + if let Err(e) = result { log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", + "{} from parachain {} via {:?}: relayer {:?} has submitted invalid messages transaction: {:?}", Self::IDENTIFIER, Para::Id::get(), Msgs::Id::get(), - call_info, + relayer, + e, ); - PreDispatchData { relayer: who.clone(), call_info } - })) - } - - fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, - len: usize, - result: &DispatchResult, - ) -> Result<(), TransactionValidityError> { - let mut extra_weight = Weight::zero(); - let mut extra_size = 0; - - // We don't refund anything if the transaction has failed. - if result.is_err() { - return Ok(()) + return slash_relayer_if_delivery_result } - // We don't refund anything for transactions that we don't support. - let (relayer, call_info) = match pre { - Some(Some(pre)) => (pre.relayer, pre.call_info), - _ => return Ok(()), - }; - // check if relay chain state has been updated if let Some(finality_proof_info) = call_info.submit_finality_proof_info() { if !SubmitFinalityProofHelper::::was_successful( @@ -388,15 +381,13 @@ where // we only refund relayer if all calls have updated chain state log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?}: failed to refund relayer {:?}, because \ - relay chain finality proof has not been accepted", + "{} from parachain {} via {:?}: relayer {:?} has submitted invalid relay chain finality proof", Self::IDENTIFIER, Para::Id::get(), Msgs::Id::get(), relayer, ); - - return Ok(()) + return slash_relayer_if_delivery_result; } // there's a conflict between how bridge GRANDPA pallet works and a `utility.batchAll` @@ -420,33 +411,29 @@ where // we only refund relayer if all calls have updated chain state log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?}: failed to refund relayer {:?}, because \ - parachain finality proof has not been accepted", + "{} from parachain {} via {:?}: relayer {:?} has submitted invalid parachain finality proof", Self::IDENTIFIER, Para::Id::get(), Msgs::Id::get(), relayer, ); - - return Ok(()) + return slash_relayer_if_delivery_result } } - // Check if the `ReceiveMessagesProof` call delivered all the messages that + // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that // it contained. If this happens, we consider the transaction "helpful" and refund it. let msgs_call_info = call_info.messages_call_info(); if !MessagesCallHelper::::was_successful(msgs_call_info) { log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?}: failed to refund relayer {:?}, because \ - some of messages have not been accepted", + "{} from parachain {} via {:?}: relayer {:?} has submitted invalid messages call", Self::IDENTIFIER, Para::Id::get(), Msgs::Id::get(), relayer, ); - - return Ok(()) + return slash_relayer_if_delivery_result } // regarding the tip - refund that happens here (at this side of the bridge) isn't the whole @@ -465,31 +452,172 @@ where // compute the relayer refund let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); - // finally - register refund in relayers pallet - let rewards_account_owner = match msgs_call_info { - MessagesCallInfo::ReceiveMessagesProof(_) => RewardsAccountOwner::ThisChain, - MessagesCallInfo::ReceiveMessagesDeliveryProof(_) => RewardsAccountOwner::BridgedChain, + // we can finally reward relayer + RelayerAccountAction::Reward(relayer, reward_account_params, refund) + } + + /// Returns number of bundled messages `Some(_)`, if the given call info is a: + /// + /// - message delivery transaction; + /// + /// - with reasonable bundled messages that may be accepted by the messages pallet. + /// + /// This function is used to check whether the transaction priority should be + /// virtually boosted. The relayer registration (we only boost priority for registered + /// relayer transactions) must be checked outside. + fn bundled_messages_for_priority_boost(call_info: Option<&CallInfo>) -> Option { + // we only boost priority of message delivery transactions + let parsed_call = match call_info { + Some(parsed_call) if parsed_call.is_receive_messages_proof_call() => parsed_call, + _ => return None, }; - RelayersPallet::::register_relayer_reward( - RewardsAccountParams::new( - Msgs::Id::get(), - Runtime::BridgedChainId::get(), - rewards_account_owner, - ), - &relayer, - refund, - ); + + // compute total number of messages in transaction + let bundled_messages = + parsed_call.messages_call_info().bundled_messages().checked_len().unwrap_or(0); + + // a quick check to avoid invalid high-priority transactions + if bundled_messages > Runtime::MaxUnconfirmedMessagesAtInboundLane::get() { + return None + } + + Some(bundled_messages) + } +} + +impl SignedExtension + for RefundBridgedParachainMessages +where + Self: 'static + Send + Sync, + Runtime: UtilityConfig> + + BoundedBridgeGrandpaConfig + + ParachainsConfig + + MessagesConfig + + RelayersConfig, + Para: RefundableParachainId, + Msgs: RefundableMessagesLaneId, + Refund: RefundCalculator, + Priority: Get, + Id: StaticStrProvider, + CallOf: Dispatchable + + IsSubType, Runtime>> + + GrandpaCallSubType + + ParachainsCallSubType + + MessagesCallSubType, +{ + const IDENTIFIER: &'static str = Id::STR; + type AccountId = Runtime::AccountId; + type Call = CallOf; + type AdditionalSigned = (); + type Pre = Option>; + + fn additional_signed(&self) -> Result<(), TransactionValidityError> { + Ok(()) + } + + fn validate( + &self, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> TransactionValidity { + // this is the only relevant line of code for the `pre_dispatch` + // + // we're not calling `validate` from `pre_dispatch` directly because of performance + // reasons, so if you're adding some code that may fail here, please check if it needs + // to be added to the `pre_dispatch` as well + let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + + // the following code just plays with transaction priority and never returns an error + + // we only boost priority of presumably correct message delivery transactions + let bundled_messages = match Self::bundled_messages_for_priority_boost(parsed_call.as_ref()) + { + Some(bundled_messages) => bundled_messages, + None => return Ok(Default::default()), + }; + + // we only boost priority if relayer has staked required balance + if !RelayersPallet::::is_registration_active(who) { + return Ok(Default::default()) + } + + // compute priority boost + let priority_boost = + crate::priority_calculator::compute_priority_boost::(bundled_messages); + let valid_transaction = ValidTransactionBuilder::default().priority(priority_boost); log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?} has registered reward: {:?} for {:?}", + "{} from parachain {} via {:?} has boosted priority of message delivery transaction \ + of relayer {:?}: {} messages -> {} priority", Self::IDENTIFIER, Para::Id::get(), Msgs::Id::get(), - refund, - relayer, + who, + bundled_messages, + priority_boost, ); + valid_transaction.build() + } + + fn pre_dispatch( + self, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) + let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + + Ok(parsed_call.map(|call_info| { + log::trace!( + target: "runtime::bridge", + "{} from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + call_info, + ); + PreDispatchData { relayer: who.clone(), call_info } + })) + } + + fn post_dispatch( + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + let call_result = Self::analyze_call_result(pre, info, post_info, len, result); + + match call_result { + RelayerAccountAction::None => (), + RelayerAccountAction::Reward(relayer, reward_account, reward) => { + RelayersPallet::::register_relayer_reward( + reward_account, + &relayer, + reward, + ); + + log::trace!( + target: "runtime::bridge", + "{} from parachain {} via {:?} has registered reward: {:?} for {:?}", + Self::IDENTIFIER, + Para::Id::get(), + Msgs::Id::get(), + reward, + relayer, + ); + }, + RelayerAccountAction::Slash(relayer, slash_account) => + RelayersPallet::::slash_and_deregister(&relayer, slash_account), + } + Ok(()) } } @@ -509,10 +637,14 @@ mod tests { }; use bp_messages::{InboundLaneData, MessageNonce, OutboundLaneData, UnrewardedRelayersState}; use bp_parachains::{BestParaHeadHash, ParaInfo}; - use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; + use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; use bp_runtime::HeaderId; use bp_test_utils::{make_default_justification, test_keyring}; - use frame_support::{assert_storage_noop, parameter_types, weights::Weight}; + use frame_support::{ + assert_storage_noop, parameter_types, + traits::{fungible::Mutate, ReservableCurrency}, + weights::Weight, + }; use pallet_bridge_grandpa::{Call as GrandpaCall, StoredAuthoritySet}; use pallet_bridge_messages::Call as MessagesCall; use pallet_bridge_parachains::{Call as ParachainsCall, RelayBlockHash}; @@ -547,6 +679,22 @@ mod tests { StrTestExtension, >; + fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance { + let test_stake: ThisChainBalance = TestStake::get(); + ExistentialDeposit::get().saturating_add(test_stake * 100) + } + + // in tests, the following accounts are equal (because of how `into_sub_account_truncating` + // works) + + fn delivery_rewards_account() -> ThisChainAccountId { + TestPaymentProcedure::rewards_account(MsgProofsRewardsAccount::get()) + } + + fn confirmation_rewards_account() -> ThisChainAccountId { + TestPaymentProcedure::rewards_account(MsgDeliveryProofsRewardsAccount::get()) + } + fn relayer_account_at_this_chain() -> ThisChainAccountId { 0 } @@ -558,7 +706,6 @@ mod tests { fn initialize_environment( best_relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, - parachain_head_hash: ParaHash, best_message: MessageNonce, ) { let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect(); @@ -572,7 +719,7 @@ mod tests { let para_info = ParaInfo { best_head_hash: BestParaHeadHash { at_relay_block_number: parachain_head_at_relay_header_number, - head_hash: parachain_head_hash, + head_hash: [parachain_head_at_relay_header_number as u8; 32].into(), }, next_imported_hash_position: 0, }; @@ -586,6 +733,14 @@ mod tests { let out_lane_data = OutboundLaneData { latest_received_nonce: best_message, ..Default::default() }; pallet_bridge_messages::OutboundLanes::::insert(lane_id, out_lane_data); + + Balances::mint_into(&delivery_rewards_account(), ExistentialDeposit::get()).unwrap(); + Balances::mint_into(&confirmation_rewards_account(), ExistentialDeposit::get()).unwrap(); + Balances::mint_into( + &relayer_account_at_this_chain(), + initial_balance_of_relayer_account_at_this_chain(), + ) + .unwrap(); } fn submit_relay_header_call(relay_header_number: RelayBlockNumber) -> RuntimeCall { @@ -609,7 +764,10 @@ mod tests { ) -> RuntimeCall { RuntimeCall::BridgeParachains(ParachainsCall::submit_parachain_heads { at_relay_block: (parachain_head_at_relay_header_number, RelayBlockHash::default()), - parachains: vec![(ParaId(TestParachain::get()), [1u8; 32].into())], + parachains: vec![( + ParaId(TestParachain::get()), + [parachain_head_at_relay_header_number as u8; 32].into(), + )], parachain_heads_proof: ParaHeadsProof(vec![]), }) } @@ -711,7 +869,7 @@ mod tests { SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), - para_head_hash: [1u8; 32].into(), + para_head_hash: [200u8; 32].into(), }, MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo { base: BaseMessagesProofInfo { @@ -740,7 +898,7 @@ mod tests { SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), - para_head_hash: [1u8; 32].into(), + para_head_hash: [200u8; 32].into(), }, MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( BaseMessagesProofInfo { @@ -760,7 +918,7 @@ mod tests { SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), - para_head_hash: [1u8; 32].into(), + para_head_hash: [200u8; 32].into(), }, MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo { base: BaseMessagesProofInfo { @@ -784,7 +942,7 @@ mod tests { SubmitParachainHeadsInfo { at_relay_block_number: 200, para_id: ParaId(TestParachain::get()), - para_head_hash: [1u8; 32].into(), + para_head_hash: [200u8; 32].into(), }, MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( BaseMessagesProofInfo { @@ -829,8 +987,21 @@ mod tests { } } - fn run_test(test: impl FnOnce()) { - sp_io::TestExternalities::new(Default::default()).execute_with(test) + fn set_bundled_range_end( + mut pre_dispatch_data: PreDispatchData, + end: MessageNonce, + ) -> PreDispatchData { + let msg_info = match pre_dispatch_data.call_info { + CallInfo::AllFinalityAndMsgs(_, _, ref mut info) => info, + CallInfo::ParachainFinalityAndMsgs(_, ref mut info) => info, + CallInfo::Msgs(ref mut info) => info, + }; + + if let MessagesCallInfo::ReceiveMessagesProof(ref mut msg_info) = msg_info { + msg_info.base.bundled_range = *msg_info.base.bundled_range.start()..=end + } + + pre_dispatch_data } fn run_validate(call: RuntimeCall) -> TransactionValidity { @@ -838,6 +1009,13 @@ mod tests { extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } + fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { + run_validate(call).map(|mut tx| { + tx.priority = 0; + tx + }) + } + fn run_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { @@ -883,10 +1061,49 @@ mod tests { ) } + #[test] + fn validate_doesnt_boost_transaction_priority_if_relayer_is_not_registered() { + run_test(|| { + initialize_environment(100, 100, 100); + Balances::set_balance(&relayer_account_at_this_chain(), ExistentialDeposit::get()); + + // message delivery is failing + assert_eq!(run_validate(message_delivery_call(200)), Ok(Default::default()),); + assert_eq!( + run_validate(parachain_finality_and_delivery_batch_call(200, 200)), + Ok(Default::default()), + ); + assert_eq!( + run_validate(all_finality_and_delivery_batch_call(200, 200, 200)), + Ok(Default::default()), + ); + // message confirmation validation is passing + assert_eq!( + run_validate_ignore_priority(message_confirmation_call(200)), + Ok(Default::default()), + ); + assert_eq!( + run_validate_ignore_priority(parachain_finality_and_confirmation_batch_call( + 200, 200 + )), + Ok(Default::default()), + ); + assert_eq!( + run_validate_ignore_priority(all_finality_and_confirmation_batch_call( + 200, 200, 200 + )), + Ok(Default::default()), + ); + }); + } + #[test] fn validate_boosts_priority_of_message_delivery_transactons() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); + + BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000) + .unwrap(); let priority_of_100_messages_delivery = run_validate(message_delivery_call(200)).unwrap().priority; @@ -913,7 +1130,10 @@ mod tests { #[test] fn validate_does_not_boost_priority_of_message_delivery_transactons_with_too_many_messages() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); + + BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000) + .unwrap(); let priority_of_max_messages_delivery = run_validate(message_delivery_call( 100 + MaxUnconfirmedMessagesAtInboundLane::get(), @@ -938,14 +1158,7 @@ mod tests { #[test] fn validate_allows_non_obsolete_transactions() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); - - fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { - run_validate(call).map(|mut tx| { - tx.priority = 0; - tx - }) - } + initialize_environment(100, 100, 100); assert_eq!( run_validate_ignore_priority(message_delivery_call(200)), @@ -983,7 +1196,7 @@ mod tests { #[test] fn ext_rejects_batch_with_obsolete_relay_chain_header() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)), @@ -1000,7 +1213,7 @@ mod tests { #[test] fn ext_rejects_batch_with_obsolete_parachain_head() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)), @@ -1025,7 +1238,7 @@ mod tests { #[test] fn ext_rejects_batch_with_obsolete_messages() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)), @@ -1068,7 +1281,7 @@ mod tests { #[test] fn pre_dispatch_parses_batch_with_relay_chain_and_parachain_headers() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); assert_eq!( run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), @@ -1084,7 +1297,7 @@ mod tests { #[test] fn pre_dispatch_parses_batch_with_parachain_header() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); assert_eq!( run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), @@ -1100,7 +1313,7 @@ mod tests { #[test] fn pre_dispatch_fails_to_parse_batch_with_multiple_parachain_headers() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); let call = RuntimeCall::Utility(UtilityCall::batch_all { calls: vec![ @@ -1123,7 +1336,7 @@ mod tests { #[test] fn pre_dispatch_parses_message_transaction() { run_test(|| { - initialize_environment(100, 100, Default::default(), 100); + initialize_environment(100, 100, 100); assert_eq!( run_pre_dispatch(message_delivery_call(200)), @@ -1156,7 +1369,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_updated_relay_chain_state() { run_test(|| { - initialize_environment(100, 200, Default::default(), 200); + initialize_environment(100, 200, 200); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); }); @@ -1165,7 +1378,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_updated_parachain_state() { run_test(|| { - initialize_environment(200, 100, Default::default(), 200); + initialize_environment(200, 100, 200); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); assert_storage_noop!(run_post_dispatch( @@ -1178,7 +1391,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_delivered_any_messages() { run_test(|| { - initialize_environment(200, 200, Default::default(), 100); + initialize_environment(200, 200, 100); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); assert_storage_noop!(run_post_dispatch( @@ -1202,7 +1415,7 @@ mod tests { #[test] fn post_dispatch_ignores_transaction_that_has_not_delivered_all_messages() { run_test(|| { - initialize_environment(200, 200, Default::default(), 150); + initialize_environment(200, 200, 150); assert_storage_noop!(run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(()))); assert_storage_noop!(run_post_dispatch( @@ -1226,7 +1439,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_all_finality_batch_with_extra_weight() { run_test(|| { - initialize_environment(200, 200, [1u8; 32].into(), 200); + initialize_environment(200, 200, 200); let mut dispatch_info = dispatch_info(); dispatch_info.weight = Weight::from_parts( @@ -1275,7 +1488,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_all_finality_batch() { run_test(|| { - initialize_environment(200, 200, [1u8; 32].into(), 200); + initialize_environment(200, 200, 200); run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())); assert_eq!( @@ -1300,7 +1513,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_parachain_finality_batch() { run_test(|| { - initialize_environment(200, 200, [1u8; 32].into(), 200); + initialize_environment(200, 200, 200); run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(())); assert_eq!( @@ -1325,7 +1538,7 @@ mod tests { #[test] fn post_dispatch_refunds_relayer_in_message_transaction() { run_test(|| { - initialize_environment(200, 200, Default::default(), 200); + initialize_environment(200, 200, 200); run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())); assert_eq!( @@ -1346,4 +1559,149 @@ mod tests { ); }); } + + #[test] + fn post_dispatch_slashing_relayer_stake() { + run_test(|| { + initialize_environment(200, 200, 100); + + let delivery_rewards_account_balance = + Balances::free_balance(delivery_rewards_account()); + + let test_stake: ThisChainBalance = TestStake::get(); + Balances::set_balance( + &relayer_account_at_this_chain(), + ExistentialDeposit::get() + test_stake * 10, + ); + + // slashing works for message delivery calls + BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000) + .unwrap(); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + run_post_dispatch(Some(delivery_pre_dispatch_data()), Ok(())); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0); + assert_eq!( + delivery_rewards_account_balance + test_stake, + Balances::free_balance(delivery_rewards_account()) + ); + + BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000) + .unwrap(); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + run_post_dispatch(Some(parachain_finality_pre_dispatch_data()), Ok(())); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0); + assert_eq!( + delivery_rewards_account_balance + test_stake * 2, + Balances::free_balance(delivery_rewards_account()) + ); + + BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000) + .unwrap(); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + run_post_dispatch(Some(all_finality_pre_dispatch_data()), Ok(())); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), 0); + assert_eq!( + delivery_rewards_account_balance + test_stake * 3, + Balances::free_balance(delivery_rewards_account()) + ); + + // reserve doesn't work for message confirmation calls + let confirmation_rewards_account_balance = + Balances::free_balance(confirmation_rewards_account()); + + Balances::reserve(&relayer_account_at_this_chain(), test_stake).unwrap(); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + + assert_eq!( + confirmation_rewards_account_balance, + Balances::free_balance(confirmation_rewards_account()) + ); + run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + + run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(())); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + + run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(())); + assert_eq!(Balances::reserved_balance(relayer_account_at_this_chain()), test_stake); + + // check that unreserve has happened, not slashing + assert_eq!( + delivery_rewards_account_balance + test_stake * 3, + Balances::free_balance(delivery_rewards_account()) + ); + assert_eq!( + confirmation_rewards_account_balance, + Balances::free_balance(confirmation_rewards_account()) + ); + }); + } + + fn run_analyze_call_result( + pre_dispatch_data: PreDispatchData, + dispatch_result: DispatchResult, + ) -> RelayerAccountAction { + TestExtension::analyze_call_result( + Some(Some(pre_dispatch_data)), + &dispatch_info(), + &post_dispatch_info(), + 1024, + &dispatch_result, + ) + } + + #[test] + fn analyze_call_result_shall_not_slash_for_transactions_with_too_many_messages() { + run_test(|| { + initialize_environment(100, 100, 100); + + // the `analyze_call_result` should return slash if number of bundled messages is + // within reasonable limits + assert_eq!( + run_analyze_call_result(all_finality_pre_dispatch_data(), Ok(())), + RelayerAccountAction::Slash( + relayer_account_at_this_chain(), + MsgProofsRewardsAccount::get() + ), + ); + assert_eq!( + run_analyze_call_result(parachain_finality_pre_dispatch_data(), Ok(())), + RelayerAccountAction::Slash( + relayer_account_at_this_chain(), + MsgProofsRewardsAccount::get() + ), + ); + assert_eq!( + run_analyze_call_result(delivery_pre_dispatch_data(), Ok(())), + RelayerAccountAction::Slash( + relayer_account_at_this_chain(), + MsgProofsRewardsAccount::get() + ), + ); + + // the `analyze_call_result` should not return slash if number of bundled messages is + // larger than the + assert_eq!( + run_analyze_call_result( + set_bundled_range_end(all_finality_pre_dispatch_data(), 1_000_000), + Ok(()) + ), + RelayerAccountAction::None, + ); + assert_eq!( + run_analyze_call_result( + set_bundled_range_end(parachain_finality_pre_dispatch_data(), 1_000_000), + Ok(()) + ), + RelayerAccountAction::None, + ); + assert_eq!( + run_analyze_call_result( + set_bundled_range_end(delivery_pre_dispatch_data(), 1_000_000), + Ok(()) + ), + RelayerAccountAction::None, + ); + }); + } } diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index bd33b811b3043..14e44d30f89ef 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -20,20 +20,25 @@ #![cfg_attr(not(feature = "std"), no_std)] #![warn(missing_docs)] -use bp_relayers::{PaymentProcedure, RelayerRewardsKeyProvider, RewardsAccountParams}; +use bp_relayers::{ + PaymentProcedure, Registration, RelayerRewardsKeyProvider, RewardsAccountParams, StakeAndSlash, +}; use bp_runtime::StorageDoubleMapKeyProvider; -use frame_support::sp_runtime::Saturating; +use frame_support::fail; use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero}; +use sp_runtime::{traits::CheckedSub, Saturating}; use sp_std::marker::PhantomData; pub use pallet::*; pub use payment_adapter::DeliveryConfirmationPaymentsAdapter; +pub use stake_adapter::StakeAndSlashNamed; pub use weights::WeightInfo; pub mod benchmarking; mod mock; mod payment_adapter; +mod stake_adapter; pub mod weights; @@ -56,8 +61,10 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// Type of relayer reward. type Reward: AtLeast32BitUnsigned + Copy + Parameter + MaxEncodedLen; - /// Pay rewards adapter. + /// Pay rewards scheme. type PaymentProcedure: PaymentProcedure; + /// Stake and slash scheme. + type StakeAndSlash: StakeAndSlash; /// Pallet call weights. type WeightInfo: WeightInfo; } @@ -102,9 +109,194 @@ pub mod pallet { }, ) } + + /// Register relayer or update its registration. + /// + /// Registration allows relayer to get priority boost for its message delivery transactions. + #[pallet::call_index(1)] + #[pallet::weight(Weight::zero())] // TODO: https://github.com/paritytech/parity-bridges-common/issues/2033 + pub fn register(origin: OriginFor, valid_till: T::BlockNumber) -> DispatchResult { + let relayer = ensure_signed(origin)?; + + // valid till must be larger than the current block number and the lease must be larger + // than the `RequiredRegistrationLease` + let lease = valid_till.saturating_sub(frame_system::Pallet::::block_number()); + ensure!( + lease > Pallet::::required_registration_lease(), + Error::::InvalidRegistrationLease + ); + + RegisteredRelayers::::try_mutate(&relayer, |maybe_registration| -> DispatchResult { + let mut registration = maybe_registration + .unwrap_or_else(|| Registration { valid_till, stake: Zero::zero() }); + + // new `valid_till` must be larger (or equal) than the old one + ensure!( + valid_till >= registration.valid_till, + Error::::CannotReduceRegistrationLease, + ); + registration.valid_till = valid_till; + + // regarding stake, there are three options: + // - if relayer stake is larger than required stake, we may do unreserve + // - if relayer stake equals to required stake, we do nothing + // - if relayer stake is smaller than required stake, we do additional reserve + let required_stake = Pallet::::required_stake(); + if let Some(to_unreserve) = registration.stake.checked_sub(&required_stake) { + Self::do_unreserve(&relayer, to_unreserve)?; + } else if let Some(to_reserve) = required_stake.checked_sub(®istration.stake) { + T::StakeAndSlash::reserve(&relayer, to_reserve).map_err(|e| { + log::trace!( + target: LOG_TARGET, + "Failed to reserve {:?} on relayer {:?} account: {:?}", + to_reserve, + relayer, + e, + ); + + Error::::FailedToReserve + })?; + } + registration.stake = required_stake; + + Self::deposit_event(Event::::RegistrationUpdated { + relayer: relayer.clone(), + registration, + }); + + *maybe_registration = Some(registration); + + Ok(()) + }) + } + + /// `Deregister` relayer. + /// + /// After this call, message delivery transactions of the relayer won't get any priority + /// boost. + #[pallet::call_index(2)] + #[pallet::weight(Weight::zero())] // TODO: https://github.com/paritytech/parity-bridges-common/issues/2033 + pub fn deregister(origin: OriginFor) -> DispatchResult { + let relayer = ensure_signed(origin)?; + + RegisteredRelayers::::try_mutate(&relayer, |maybe_registration| -> DispatchResult { + let registration = match maybe_registration.take() { + Some(registration) => registration, + None => fail!(Error::::NotRegistered), + }; + + // we can't deregister until `valid_till + 1` + ensure!( + registration.valid_till < frame_system::Pallet::::block_number(), + Error::::RegistrationIsStillActive, + ); + + // if stake is non-zero, we should do unreserve + if !registration.stake.is_zero() { + Self::do_unreserve(&relayer, registration.stake)?; + } + + Self::deposit_event(Event::::Deregistered { relayer: relayer.clone() }); + + *maybe_registration = None; + + Ok(()) + }) + } } impl Pallet { + /// Returns true if given relayer registration is active at current block. + /// + /// This call respects both `RequiredStake` and `RequiredRegistrationLease`, meaning that + /// it'll return false if registered stake is lower than required or if remaining lease + /// is less than `RequiredRegistrationLease`. + pub fn is_registration_active(relayer: &T::AccountId) -> bool { + let registration = match Self::registered_relayer(relayer) { + Some(registration) => registration, + None => return false, + }; + + // registration is inactive if relayer stake is less than required + if registration.stake < Self::required_stake() { + return false + } + + // registration is inactive if it ends soon + let remaining_lease = registration + .valid_till + .saturating_sub(frame_system::Pallet::::block_number()); + if remaining_lease <= Self::required_registration_lease() { + return false + } + + true + } + + /// Slash and `deregister` relayer. This function slashes all staked balance. + /// + /// It may fail inside, but error is swallowed and we only log it. + pub fn slash_and_deregister( + relayer: &T::AccountId, + slash_destination: RewardsAccountParams, + ) { + let registration = match RegisteredRelayers::::take(relayer) { + Some(registration) => registration, + None => { + log::trace!( + target: crate::LOG_TARGET, + "Cannot slash unregistered relayer {:?}", + relayer, + ); + + return + }, + }; + + match T::StakeAndSlash::repatriate_reserved( + relayer, + slash_destination, + registration.stake, + ) { + Ok(failed_to_slash) if failed_to_slash.is_zero() => { + log::trace!( + target: crate::LOG_TARGET, + "Relayer account {:?} has been slashed for {:?}. Funds were deposited to {:?}", + relayer, + registration.stake, + slash_destination, + ); + }, + Ok(failed_to_slash) => { + log::trace!( + target: crate::LOG_TARGET, + "Relayer account {:?} has been partially slashed for {:?}. Funds were deposited to {:?}. \ + Failed to slash: {:?}", + relayer, + registration.stake, + slash_destination, + failed_to_slash, + ); + }, + Err(e) => { + // TODO: document this. Where? + + // it may fail if there's no beneficiary account. For us it means that this + // account must exists before we'll deploy the bridge + log::debug!( + target: crate::LOG_TARGET, + "Failed to slash relayer account {:?}: {:?}. Maybe beneficiary account doesn't exist? \ + Beneficiary: {:?}, amount: {:?}, failed to slash: {:?}", + relayer, + e, + slash_destination, + registration.stake, + registration.stake, + ); + }, + } + } + /// Register reward for given relayer. pub fn register_relayer_reward( rewards_account_params: RewardsAccountParams, @@ -132,6 +324,42 @@ pub mod pallet { }, ); } + + /// Return required registration lease. + fn required_registration_lease() -> T::BlockNumber { + >::RequiredRegistrationLease::get() + } + + /// Return required stake. + fn required_stake() -> T::Reward { + >::RequiredStake::get() + } + + /// `Unreserve` given amount on relayer account. + fn do_unreserve(relayer: &T::AccountId, amount: T::Reward) -> DispatchResult { + let failed_to_unreserve = T::StakeAndSlash::unreserve(relayer, amount); + if !failed_to_unreserve.is_zero() { + log::trace!( + target: LOG_TARGET, + "Failed to unreserve {:?}/{:?} on relayer {:?} account", + failed_to_unreserve, + amount, + relayer, + ); + + fail!(Error::::FailedToUnreserve) + } + + Ok(()) + } } #[pallet::event] @@ -146,6 +374,25 @@ pub mod pallet { /// Reward amount. reward: T::Reward, }, + /// Relayer registration has been added or updated. + RegistrationUpdated { + /// Relayer account that has been registered. + relayer: T::AccountId, + /// Relayer registration. + registration: Registration, + }, + /// Relayer has been `deregistered`. + Deregistered { + /// Relayer account that has been `deregistered`. + relayer: T::AccountId, + }, + /// Relayer has been slashed and `deregistered`. + SlashedAndDeregistered { + /// Relayer account that has been `deregistered`. + relayer: T::AccountId, + /// Registration that was removed. + registration: Registration, + }, } #[pallet::error] @@ -154,6 +401,19 @@ pub mod pallet { NoRewardForRelayer, /// Reward payment procedure has failed. FailedToPayReward, + /// The relayer has tried to register for past block or registration lease + /// is too short. + InvalidRegistrationLease, + /// New registration lease is less than the previous one. + CannotReduceRegistrationLease, + /// Failed to reserve enough funds on relayer account. + FailedToReserve, + /// Failed to `unreserve` enough funds on relayer account. + FailedToUnreserve, + /// Cannot `deregister` if not registered. + NotRegistered, + /// Failed to `deregister` relayer, because lease is still active. + RegistrationIsStillActive, } /// Map of the relayer => accumulated reward. @@ -168,6 +428,22 @@ pub mod pallet { as StorageDoubleMapKeyProvider>::Value, OptionQuery, >; + + /// Relayers that have reserved some of their balance to get free priority boost + /// for their message delivery transactions. + /// + /// Other relayers may submit transactions as well, but they will have default + /// priority and will be rejected (without significant tip) in case if registered + /// relayer is present. + #[pallet::storage] + #[pallet::getter(fn registered_relayer)] + pub type RegisteredRelayers = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Registration, + OptionQuery, + >; } #[cfg(test)] @@ -253,10 +529,10 @@ mod tests { None ); - //Check if the `RewardPaid` event was emitted. + // Check if the `RewardPaid` event was emitted. assert_eq!( - System::::events(), - vec![EventRecord { + System::::events().last(), + Some(&EventRecord { phase: Phase::Initialization, event: TestEvent::Relayers(RewardPaid { relayer: REGULAR_RELAYER, @@ -264,7 +540,7 @@ mod tests { reward: 100 }), topics: vec![], - }], + }), ); }); } @@ -306,4 +582,295 @@ mod tests { assert_eq!(Balances::balance(&1), 200); }); } + + #[test] + fn register_fails_if_valid_till_is_a_past_block() { + run_test(|| { + System::::set_block_number(100); + + assert_noop!( + Pallet::::register(RuntimeOrigin::signed(REGISTER_RELAYER), 50), + Error::::InvalidRegistrationLease, + ); + }); + } + + #[test] + fn register_fails_if_valid_till_lease_is_less_than_required() { + run_test(|| { + System::::set_block_number(100); + + assert_noop!( + Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 99 + Lease::get() + ), + Error::::InvalidRegistrationLease, + ); + }); + } + + #[test] + fn register_works() { + run_test(|| { + get_ready_for_events(); + + assert_ok!(Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 150 + )); + assert_eq!(Balances::reserved_balance(REGISTER_RELAYER), Stake::get()); + assert_eq!( + Pallet::::registered_relayer(REGISTER_RELAYER), + Some(Registration { valid_till: 150, stake: Stake::get() }), + ); + + assert_eq!( + System::::events().last(), + Some(&EventRecord { + phase: Phase::Initialization, + event: TestEvent::Relayers(Event::RegistrationUpdated { + relayer: REGISTER_RELAYER, + registration: Registration { valid_till: 150, stake: Stake::get() }, + }), + topics: vec![], + }), + ); + }); + } + + #[test] + fn register_fails_if_new_valid_till_is_lesser_than_previous() { + run_test(|| { + assert_ok!(Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 150 + )); + + assert_noop!( + Pallet::::register(RuntimeOrigin::signed(REGISTER_RELAYER), 125), + Error::::CannotReduceRegistrationLease, + ); + }); + } + + #[test] + fn register_fails_if_it_cant_unreserve_some_balance_if_required_stake_decreases() { + run_test(|| { + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 150, stake: Stake::get() + 1 }, + ); + + assert_noop!( + Pallet::::register(RuntimeOrigin::signed(REGISTER_RELAYER), 150), + Error::::FailedToUnreserve, + ); + }); + } + + #[test] + fn register_unreserves_some_balance_if_required_stake_decreases() { + run_test(|| { + get_ready_for_events(); + + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 150, stake: Stake::get() + 1 }, + ); + TestStakeAndSlash::reserve(®ISTER_RELAYER, Stake::get() + 1).unwrap(); + assert_eq!(Balances::reserved_balance(REGISTER_RELAYER), Stake::get() + 1); + let free_balance = Balances::free_balance(REGISTER_RELAYER); + + assert_ok!(Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 150 + )); + assert_eq!(Balances::reserved_balance(REGISTER_RELAYER), Stake::get()); + assert_eq!(Balances::free_balance(REGISTER_RELAYER), free_balance + 1); + assert_eq!( + Pallet::::registered_relayer(REGISTER_RELAYER), + Some(Registration { valid_till: 150, stake: Stake::get() }), + ); + + assert_eq!( + System::::events().last(), + Some(&EventRecord { + phase: Phase::Initialization, + event: TestEvent::Relayers(Event::RegistrationUpdated { + relayer: REGISTER_RELAYER, + registration: Registration { valid_till: 150, stake: Stake::get() } + }), + topics: vec![], + }), + ); + }); + } + + #[test] + fn register_fails_if_it_cant_reserve_some_balance() { + run_test(|| { + Balances::set_balance(®ISTER_RELAYER, 0); + assert_noop!( + Pallet::::register(RuntimeOrigin::signed(REGISTER_RELAYER), 150), + Error::::FailedToReserve, + ); + }); + } + + #[test] + fn register_fails_if_it_cant_reserve_some_balance_if_required_stake_increases() { + run_test(|| { + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 150, stake: Stake::get() - 1 }, + ); + Balances::set_balance(®ISTER_RELAYER, 0); + + assert_noop!( + Pallet::::register(RuntimeOrigin::signed(REGISTER_RELAYER), 150), + Error::::FailedToReserve, + ); + }); + } + + #[test] + fn register_reserves_some_balance_if_required_stake_increases() { + run_test(|| { + get_ready_for_events(); + + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 150, stake: Stake::get() - 1 }, + ); + TestStakeAndSlash::reserve(®ISTER_RELAYER, Stake::get() - 1).unwrap(); + + let free_balance = Balances::free_balance(REGISTER_RELAYER); + assert_ok!(Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 150 + )); + assert_eq!(Balances::reserved_balance(REGISTER_RELAYER), Stake::get()); + assert_eq!(Balances::free_balance(REGISTER_RELAYER), free_balance - 1); + assert_eq!( + Pallet::::registered_relayer(REGISTER_RELAYER), + Some(Registration { valid_till: 150, stake: Stake::get() }), + ); + + assert_eq!( + System::::events().last(), + Some(&EventRecord { + phase: Phase::Initialization, + event: TestEvent::Relayers(Event::RegistrationUpdated { + relayer: REGISTER_RELAYER, + registration: Registration { valid_till: 150, stake: Stake::get() } + }), + topics: vec![], + }), + ); + }); + } + + #[test] + fn deregister_fails_if_not_registered() { + run_test(|| { + assert_noop!( + Pallet::::deregister(RuntimeOrigin::signed(REGISTER_RELAYER)), + Error::::NotRegistered, + ); + }); + } + + #[test] + fn deregister_fails_if_registration_is_still_active() { + run_test(|| { + assert_ok!(Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 150 + )); + + System::::set_block_number(100); + + assert_noop!( + Pallet::::deregister(RuntimeOrigin::signed(REGISTER_RELAYER)), + Error::::RegistrationIsStillActive, + ); + }); + } + + #[test] + fn deregister_works() { + run_test(|| { + get_ready_for_events(); + + assert_ok!(Pallet::::register( + RuntimeOrigin::signed(REGISTER_RELAYER), + 150 + )); + + System::::set_block_number(151); + + let reserved_balance = Balances::reserved_balance(REGISTER_RELAYER); + let free_balance = Balances::free_balance(REGISTER_RELAYER); + assert_ok!(Pallet::::deregister(RuntimeOrigin::signed(REGISTER_RELAYER))); + assert_eq!( + Balances::reserved_balance(REGISTER_RELAYER), + reserved_balance - Stake::get() + ); + assert_eq!(Balances::free_balance(REGISTER_RELAYER), free_balance + Stake::get()); + + assert_eq!( + System::::events().last(), + Some(&EventRecord { + phase: Phase::Initialization, + event: TestEvent::Relayers(Event::Deregistered { relayer: REGISTER_RELAYER }), + topics: vec![], + }), + ); + }); + } + + #[test] + fn is_registration_active_is_false_for_unregistered_relayer() { + run_test(|| { + assert!(!Pallet::::is_registration_active(®ISTER_RELAYER)); + }); + } + + #[test] + fn is_registration_active_is_false_when_stake_is_too_low() { + run_test(|| { + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 150, stake: Stake::get() - 1 }, + ); + assert!(!Pallet::::is_registration_active(®ISTER_RELAYER)); + }); + } + + #[test] + fn is_registration_active_is_false_when_remaining_lease_is_too_low() { + run_test(|| { + System::::set_block_number(150 - Lease::get()); + + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 150, stake: Stake::get() }, + ); + assert!(!Pallet::::is_registration_active(®ISTER_RELAYER)); + }); + } + + #[test] + fn is_registration_active_is_true_when_relayer_is_properly_registeered() { + run_test(|| { + System::::set_block_number(150 - Lease::get()); + + RegisteredRelayers::::insert( + REGISTER_RELAYER, + Registration { valid_till: 151, stake: Stake::get() }, + ); + assert!(Pallet::::is_registration_active(®ISTER_RELAYER)); + }); + } } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index fe8c586eecc59..406a365f3509f 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -19,8 +19,10 @@ use crate as pallet_bridge_relayers; use bp_messages::LaneId; -use bp_relayers::{PaymentProcedure, RewardsAccountOwner, RewardsAccountParams}; -use frame_support::{parameter_types, weights::RuntimeDbWeight}; +use bp_relayers::{ + PayRewardFromAccount, PaymentProcedure, RewardsAccountOwner, RewardsAccountParams, +}; +use frame_support::{parameter_types, traits::fungible::Mutate, weights::RuntimeDbWeight}; use sp_core::H256; use sp_runtime::{ testing::Header as SubstrateHeader, @@ -29,6 +31,16 @@ use sp_runtime::{ pub type AccountId = u64; pub type Balance = u64; +pub type BlockNumber = u64; + +pub type TestStakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + ReserveId, + Stake, + Lease, +>; type Block = frame_system::mocking::MockBlock; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -47,13 +59,17 @@ frame_support::construct_runtime! { parameter_types! { pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; + pub const ExistentialDeposit: Balance = 1; + pub const ReserveId: [u8; 8] = *b"brdgrlrs"; + pub const Stake: Balance = 1_000; + pub const Lease: BlockNumber = 8; } impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; type Index = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = u64; + type BlockNumber = BlockNumber; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; @@ -81,11 +97,11 @@ impl pallet_balances::Config for TestRuntime { type Balance = Balance; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = frame_support::traits::ConstU64<1>; + type ExistentialDeposit = ExistentialDeposit; type AccountStore = frame_system::Pallet; type WeightInfo = (); - type MaxReserves = (); - type ReserveIdentifier = (); + type MaxReserves = ConstU32<1>; + type ReserveIdentifier = [u8; 8]; type HoldIdentifier = (); type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; @@ -96,6 +112,7 @@ impl pallet_bridge_relayers::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; type PaymentProcedure = TestPaymentProcedure; + type StakeAndSlash = TestStakeAndSlash; type WeightInfo = (); } @@ -121,9 +138,18 @@ pub const REGULAR_RELAYER: AccountId = 1; /// Relayer that can't receive rewards. pub const FAILING_RELAYER: AccountId = 2; +/// Relayer that is able to register. +pub const REGISTER_RELAYER: AccountId = 42; + /// Payment procedure that rejects payments to the `FAILING_RELAYER`. pub struct TestPaymentProcedure; +impl TestPaymentProcedure { + pub fn rewards_account(params: RewardsAccountParams) -> AccountId { + PayRewardFromAccount::<(), AccountId>::rewards_account(params) + } +} + impl PaymentProcedure for TestPaymentProcedure { type Error = (); @@ -147,5 +173,10 @@ pub fn new_test_ext() -> sp_io::TestExternalities { /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { - new_test_ext().execute_with(test) + new_test_ext().execute_with(|| { + Balances::mint_into(®ISTER_RELAYER, ExistentialDeposit::get() + 10 * Stake::get()) + .unwrap(); + + test() + }) } diff --git a/modules/relayers/src/stake_adapter.rs b/modules/relayers/src/stake_adapter.rs new file mode 100644 index 0000000000000..055b6a111ec72 --- /dev/null +++ b/modules/relayers/src/stake_adapter.rs @@ -0,0 +1,186 @@ +// 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 . + +//! Code that allows `NamedReservableCurrency` to be used as a `StakeAndSlash` +//! mechanism of the relayers pallet. + +use bp_relayers::{PayRewardFromAccount, RewardsAccountParams, StakeAndSlash}; +use codec::Codec; +use frame_support::traits::{tokens::BalanceStatus, NamedReservableCurrency}; +use sp_runtime::{traits::Get, DispatchError, DispatchResult}; +use sp_std::{fmt::Debug, marker::PhantomData}; + +/// `StakeAndSlash` that works with `NamedReservableCurrency` and uses named +/// reservations. +/// +/// **WARNING**: this implementation assumes that the relayers pallet is configured to +/// use the [`bp_relayers::PayRewardFromAccount`] as its relayers payment scheme. +pub struct StakeAndSlashNamed( + PhantomData<(AccountId, BlockNumber, Currency, ReserveId, Stake, Lease)>, +); + +impl + StakeAndSlash + for StakeAndSlashNamed +where + AccountId: Codec + Debug, + Currency: NamedReservableCurrency, + ReserveId: Get, + Stake: Get, + Lease: Get, +{ + type RequiredStake = Stake; + type RequiredRegistrationLease = Lease; + + fn reserve(relayer: &AccountId, amount: Currency::Balance) -> DispatchResult { + Currency::reserve_named(&ReserveId::get(), relayer, amount) + } + + fn unreserve(relayer: &AccountId, amount: Currency::Balance) -> Currency::Balance { + Currency::unreserve_named(&ReserveId::get(), relayer, amount) + } + + fn repatriate_reserved( + relayer: &AccountId, + beneficiary: RewardsAccountParams, + amount: Currency::Balance, + ) -> Result { + let beneficiary_account = + PayRewardFromAccount::<(), AccountId>::rewards_account(beneficiary); + Currency::repatriate_reserved_named( + &ReserveId::get(), + relayer, + &beneficiary_account, + amount, + BalanceStatus::Free, + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + + use frame_support::traits::fungible::Mutate; + + fn test_stake() -> Balance { + Stake::get() + } + + #[test] + fn reserve_works() { + run_test(|| { + assert!(TestStakeAndSlash::reserve(&1, test_stake()).is_err()); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::reserved_balance(1), 0); + + Balances::mint_into(&2, test_stake() - 1).unwrap(); + assert!(TestStakeAndSlash::reserve(&2, test_stake()).is_err()); + assert_eq!(Balances::free_balance(2), test_stake() - 1); + assert_eq!(Balances::reserved_balance(2), 0); + + Balances::mint_into(&3, test_stake() * 2).unwrap(); + assert_eq!(TestStakeAndSlash::reserve(&3, test_stake()), Ok(())); + assert_eq!(Balances::free_balance(3), test_stake()); + assert_eq!(Balances::reserved_balance(3), test_stake()); + }) + } + + #[test] + fn unreserve_works() { + run_test(|| { + assert_eq!(TestStakeAndSlash::unreserve(&1, test_stake()), test_stake()); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::reserved_balance(1), 0); + + Balances::mint_into(&2, test_stake() * 2).unwrap(); + TestStakeAndSlash::reserve(&2, test_stake() / 3).unwrap(); + assert_eq!( + TestStakeAndSlash::unreserve(&2, test_stake()), + test_stake() - test_stake() / 3 + ); + assert_eq!(Balances::free_balance(2), test_stake() * 2); + assert_eq!(Balances::reserved_balance(2), 0); + + Balances::mint_into(&3, test_stake() * 2).unwrap(); + TestStakeAndSlash::reserve(&3, test_stake()).unwrap(); + assert_eq!(TestStakeAndSlash::unreserve(&3, test_stake()), 0); + assert_eq!(Balances::free_balance(3), test_stake() * 2); + assert_eq!(Balances::reserved_balance(3), 0); + }) + } + + #[test] + fn repatriate_reserved_works() { + run_test(|| { + let beneficiary = TEST_REWARDS_ACCOUNT_PARAMS; + let beneficiary_account = TestPaymentProcedure::rewards_account(beneficiary); + + let mut expected_balance = ExistentialDeposit::get(); + Balances::mint_into(&beneficiary_account, expected_balance).unwrap(); + + assert_eq!( + TestStakeAndSlash::repatriate_reserved(&1, beneficiary, test_stake()), + Ok(test_stake()) + ); + assert_eq!(Balances::free_balance(1), 0); + assert_eq!(Balances::reserved_balance(1), 0); + assert_eq!(Balances::free_balance(beneficiary_account), expected_balance); + assert_eq!(Balances::reserved_balance(beneficiary_account), 0); + + expected_balance += test_stake() / 3; + Balances::mint_into(&2, test_stake() * 2).unwrap(); + TestStakeAndSlash::reserve(&2, test_stake() / 3).unwrap(); + assert_eq!( + TestStakeAndSlash::repatriate_reserved(&2, beneficiary, test_stake()), + Ok(test_stake() - test_stake() / 3) + ); + assert_eq!(Balances::free_balance(2), test_stake() * 2 - test_stake() / 3); + assert_eq!(Balances::reserved_balance(2), 0); + assert_eq!(Balances::free_balance(beneficiary_account), expected_balance); + assert_eq!(Balances::reserved_balance(beneficiary_account), 0); + + expected_balance += test_stake(); + Balances::mint_into(&3, test_stake() * 2).unwrap(); + TestStakeAndSlash::reserve(&3, test_stake()).unwrap(); + assert_eq!( + TestStakeAndSlash::repatriate_reserved(&3, beneficiary, test_stake()), + Ok(0) + ); + assert_eq!(Balances::free_balance(3), test_stake()); + assert_eq!(Balances::reserved_balance(3), 0); + assert_eq!(Balances::free_balance(beneficiary_account), expected_balance); + assert_eq!(Balances::reserved_balance(beneficiary_account), 0); + }) + } + + #[test] + fn repatriate_reserved_doesnt_work_when_beneficiary_account_is_missing() { + run_test(|| { + let beneficiary = TEST_REWARDS_ACCOUNT_PARAMS; + let beneficiary_account = TestPaymentProcedure::rewards_account(beneficiary); + + Balances::mint_into(&3, test_stake() * 2).unwrap(); + TestStakeAndSlash::reserve(&3, test_stake()).unwrap(); + assert!(TestStakeAndSlash::repatriate_reserved(&3, beneficiary, test_stake()).is_err()); + assert_eq!(Balances::free_balance(3), test_stake()); + assert_eq!(Balances::reserved_balance(3), test_stake()); + assert_eq!(Balances::free_balance(beneficiary_account), 0); + assert_eq!(Balances::reserved_balance(beneficiary_account), 0); + }); + } +} diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index f14b841fa9ebe..21f66a2ffa100 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -19,6 +19,8 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] +pub use registration::{Registration, StakeAndSlash}; + use bp_messages::LaneId; use bp_runtime::{ChainId, StorageDoubleMapKeyProvider}; use frame_support::{traits::tokens::Preservation, Blake2_128Concat, Identity}; @@ -30,6 +32,8 @@ use sp_runtime::{ }; use sp_std::{fmt::Debug, marker::PhantomData}; +mod registration; + /// The owner of the sovereign account that should pay the rewards. /// /// Each of the 2 final points connected by a bridge owns a sovereign account at each end of the diff --git a/primitives/relayers/src/registration.rs b/primitives/relayers/src/registration.rs new file mode 100644 index 0000000000000..da64bdde3793c --- /dev/null +++ b/primitives/relayers/src/registration.rs @@ -0,0 +1,121 @@ +// Copyright 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 . + +//! Bridge relayers registration and slashing scheme. +//! +//! There is an option to add a refund-relayer signed extension that will compensate +//! relayer costs of the message delivery and confirmation transactions (as well as +//! required finality proofs). This extension boosts priority of message delivery +//! transactions, based on the number of bundled messages. So transaction with more +//! messages has larger priority than the transaction with less messages. +//! See [`bridge_runtime_common::priority_calculator`] for details; +//! +//! This encourages relayers to include more messages to their delivery transactions. +//! At the same time, we are not verifying storage proofs before boosting +//! priority. Instead, we simply trust relayer, when it says that transaction delivers +//! `N` messages. +//! +//! This allows relayers to submit transactions which declare large number of bundled +//! transactions to receive priority boost for free, potentially pushing actual delivery +//! transactions from the block (or even transaction queue). Such transactions are +//! not free, but their cost is relatively small. +//! +//! To alleviate that, we only boost transactions of relayers that have some stake +//! that guarantees that their transactions are valid. Such relayers get priority +//! for free, but they risk to lose their stake. + +use crate::RewardsAccountParams; + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{Get, Zero}, + DispatchError, DispatchResult, +}; + +/// Relayer registration. +#[derive(Copy, Clone, Debug, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen)] +pub struct Registration { + /// The last block number, where this registration is considered active. + /// + /// Relayer has an option to renew his registration (this may be done before it + /// is spoiled as well). Starting from block `valid_till + 1`, relayer may `deregister` + /// himself and get his stake back. + /// + /// Please keep in mind that priority boost stops working some blocks before the + /// registration ends (see [`StakeAndSlash::RequiredRegistrationLease`]). + pub valid_till: BlockNumber, + /// Active relayer stake, which is mapped to the relayer reserved balance. + /// + /// If `stake` is less than the [`StakeAndSlash::RequiredStake`], the registration + /// is considered inactive even if `valid_till + 1` is not yet reached. + pub stake: Balance, +} + +/// Relayer stake-and-slash mechanism. +pub trait StakeAndSlash { + /// The stake that the relayer must have to have its transactions boosted. + type RequiredStake: Get; + /// Required **remaining** registration lease to be able to get transaction priority boost. + /// + /// If the difference between registration's `valid_till` and the current block number + /// is less than the `RequiredRegistrationLease`, it becomes inactive and relayer transaction + /// won't get priority boost. This period exists, because priority is calculated when + /// transaction is placed to the queue (and it is reevaluated periodically) and then some time + /// may pass before transaction will be included into the block. + type RequiredRegistrationLease: Get; + + /// Reserve the given amount at relayer account. + fn reserve(relayer: &AccountId, amount: Balance) -> DispatchResult; + /// `Unreserve` the given amount from relayer account. + /// + /// Returns amount that we have failed to `unreserve`. + fn unreserve(relayer: &AccountId, amount: Balance) -> Balance; + /// Slash up to `amount` from reserved balance of account `relayer` and send funds to given + /// `beneficiary`. + /// + /// Returns `Ok(_)` with non-zero balance if we have failed to repatriate some portion of stake. + fn repatriate_reserved( + relayer: &AccountId, + beneficiary: RewardsAccountParams, + amount: Balance, + ) -> Result; +} + +impl StakeAndSlash for () +where + Balance: Default + Zero, + BlockNumber: Default, +{ + type RequiredStake = (); + type RequiredRegistrationLease = (); + + fn reserve(_relayer: &AccountId, _amount: Balance) -> DispatchResult { + Ok(()) + } + + fn unreserve(_relayer: &AccountId, _amount: Balance) -> Balance { + Zero::zero() + } + + fn repatriate_reserved( + _relayer: &AccountId, + _beneficiary: RewardsAccountParams, + _amount: Balance, + ) -> Result { + Ok(Zero::zero()) + } +} From bc637a34e14a04a8e45569536ab87c5ea3bd40ff Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 25 Apr 2023 19:03:52 +0300 Subject: [PATCH 1037/1210] Messages relay fixes (#2073) * removed obsolete check that is superseded by the unblock checks below * if messages race transaction submit has failed, do not restart loop. Instead, wait for new best nonces from target node and retry selection. That's because submit has probably failed because other relayer has submitted same nonces * reset nonces_to_submit and nonces_submitted if at least one of selected/submitted nonces is already at target * removed extra check --- relays/messages/src/message_race_delivery.rs | 47 +++---------------- relays/messages/src/message_race_loop.rs | 23 ++++++++-- relays/messages/src/message_race_strategy.rs | 48 ++++++++++++++++---- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 8a667fdbdb890..06e02a06017b1 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -343,31 +343,6 @@ where // There's additional condition in the message delivery race: target would reject messages // if there are too much unconfirmed messages at the inbound lane. - // The receiving race is responsible to deliver confirmations back to the source chain. So - // if there's a lot of unconfirmed messages, let's wait until it'll be able to do its job. - let latest_received_nonce_at_target = target_nonces.latest_nonce; - let confirmations_missing = - latest_received_nonce_at_target.checked_sub(latest_confirmed_nonce_at_source); - match confirmations_missing { - Some(confirmations_missing) - if confirmations_missing >= self.max_unconfirmed_nonces_at_target => - { - log::debug!( - target: "bridge", - "Cannot deliver any more messages from {} to {}. Too many unconfirmed nonces \ - at target: target.latest_received={:?}, source.latest_confirmed={:?}, max={:?}", - MessageDeliveryRace::

::source_name(), - MessageDeliveryRace::

::target_name(), - latest_received_nonce_at_target, - latest_confirmed_nonce_at_source, - self.max_unconfirmed_nonces_at_target, - ); - - return None - }, - _ => (), - } - // Ok - we may have new nonces to deliver. But target may still reject new messages, because // we haven't notified it that (some) messages have been confirmed. So we may want to // include updated `source.latest_confirmed` in the proof. @@ -375,6 +350,7 @@ where // Important note: we're including outbound state lane proof whenever there are unconfirmed // nonces on the target chain. Other strategy is to include it only if it's absolutely // necessary. + let latest_received_nonce_at_target = target_nonces.latest_nonce; let latest_confirmed_nonce_at_target = target_nonces.nonces_data.confirmed_nonce; let outbound_state_proof_required = latest_confirmed_nonce_at_target < latest_confirmed_nonce_at_source; @@ -585,6 +561,11 @@ where self.strategy.source_nonces_updated(at_block, nonces) } + fn reset_best_target_nonces(&mut self) { + self.target_nonces = None; + self.strategy.reset_best_target_nonces(); + } + fn best_target_nonces_updated, TargetHeaderIdOf

>>( &mut self, nonces: TargetClientNonces, @@ -808,22 +789,6 @@ mod tests { ); } - #[async_std::test] - async fn message_delivery_strategy_selects_nothing_if_too_many_confirmations_missing() { - let (state, mut strategy) = prepare_strategy(); - - // if there are already `max_unconfirmed_nonces_at_target` messages on target, - // we need to wait until confirmations will be delivered by receiving race - strategy.latest_confirmed_nonces_at_source = vec![( - header_id(1), - strategy.target_nonces.as_ref().unwrap().latest_nonce - - strategy.max_unconfirmed_nonces_at_target, - )] - .into_iter() - .collect(); - assert_eq!(strategy.select_nonces_to_deliver(state).await, None); - } - #[async_std::test] async fn message_delivery_strategy_includes_outbound_state_proof_when_new_nonces_are_available() { diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index be7d5b4675659..3df9eef496016 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -195,6 +195,9 @@ pub trait RaceStrategy: Debug { at_block: SourceHeaderId, nonces: SourceClientNonces, ); + /// Called when we want to wait until next `best_target_nonces_updated` before selecting + /// any nonces for delivery. + fn reset_best_target_nonces(&mut self); /// Called when best nonces are updated at target node of the race. fn best_target_nonces_updated>( &mut self, @@ -542,14 +545,22 @@ pub async fn run, TC: TargetClient

>( P::target_name(), ); - race_state.reset_nonces_to_submit(); race_state.nonces_submitted = Some(artifacts.nonces); target_tx_tracker.set(artifacts.tx_tracker.wait().fuse()); }, &mut target_go_offline_future, async_std::task::sleep, || format!("Error submitting proof {}", P::target_name()), - ).fail_if_error(FailedClient::Target).map(|_| true)?; + ).fail_if_connection_error(FailedClient::Target)?; + + // in any case - we don't need to retry submitting the same nonces again until + // we read nonces from the target client + race_state.reset_nonces_to_submit(); + // if we have failed to submit transaction AND that is not the connection issue, + // then we need to read best target nonces before selecting nonces again + if !target_client_is_online { + strategy.reset_best_target_nonces(); + } }, target_transaction_status = target_tx_tracker => { match (target_transaction_status, race_state.nonces_submitted.as_ref()) { @@ -699,7 +710,13 @@ pub async fn run, TC: TargetClient

>( .fuse(), ); } else if let Some(source_required_header) = source_required_header.clone() { - log::debug!(target: "bridge", "Going to require {} header {:?} at {}", P::source_name(), source_required_header, P::target_name()); + log::debug!( + target: "bridge", + "Going to require {} header {:?} at {}", + P::source_name(), + source_required_header, + P::target_name(), + ); target_require_source_header .set(race_target.require_source_header(source_required_header).fuse()); } else if target_best_nonces_required { diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 718c296391c5c..5c8f9a162b4a2 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -254,6 +254,10 @@ impl< ) } + fn reset_best_target_nonces(&mut self) { + self.best_target_nonce = None; + } + fn best_target_nonces_updated< RS: RaceState< HeaderId, @@ -266,19 +270,37 @@ impl< ) { let nonce = nonces.latest_nonce; + // if **some** of nonces that we have selected to submit already present at the + // target chain => select new nonces let need_to_select_new_nonces = race_state .nonces_to_submit() - .map(|nonces| *nonces.end() <= nonce) + .map(|nonces| nonce >= *nonces.start()) .unwrap_or(false); if need_to_select_new_nonces { + log::trace!( + target: "bridge", + "Latest nonce at target is {}. Clearing nonces to submit: {:?}", + nonce, + race_state.nonces_to_submit(), + ); + race_state.reset_nonces_to_submit(); } + // if **some** of nonces that we have submitted already present at the + // target chain => select new nonces let need_new_nonces_to_submit = race_state .nonces_submitted() - .map(|nonces| *nonces.end() <= nonce) + .map(|nonces| nonce >= *nonces.start()) .unwrap_or(false); if need_new_nonces_to_submit { + log::trace!( + target: "bridge", + "Latest nonce at target is {}. Clearing submitted nonces: {:?}", + nonce, + race_state.nonces_submitted(), + ); + race_state.reset_nonces_submitted(); } @@ -415,10 +437,15 @@ mod tests { let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); - strategy.best_target_nonces_updated(target_nonces(7), &mut state); + // we are going to submit 5..=10, so having latest nonce 4 at target is fine + strategy.best_target_nonces_updated(target_nonces(4), &mut state); assert!(state.nonces_to_submit.is_some()); - strategy.best_target_nonces_updated(target_nonces(10), &mut state); - assert!(state.nonces_to_submit.is_none()); + // any nonce larger than 4 invalidates the `nonces_to_submit` + for nonce in 5..=11 { + state.nonces_to_submit = Some((header_id(1), 5..=10, (5..=10, None))); + strategy.best_target_nonces_updated(target_nonces(nonce), &mut state); + assert!(state.nonces_to_submit.is_none()); + } } #[test] @@ -426,10 +453,15 @@ mod tests { let mut state = TestRaceStateImpl::default(); let mut strategy = BasicStrategy::::new(); state.nonces_submitted = Some(5..=10); - strategy.best_target_nonces_updated(target_nonces(7), &mut state); + // we have submitted 5..=10, so having latest nonce 4 at target is fine + strategy.best_target_nonces_updated(target_nonces(4), &mut state); assert!(state.nonces_submitted.is_some()); - strategy.best_target_nonces_updated(target_nonces(10), &mut state); - assert!(state.nonces_submitted.is_none()); + // any nonce larger than 4 invalidates the `nonces_submitted` + for nonce in 5..=11 { + state.nonces_submitted = Some(5..=10); + strategy.best_target_nonces_updated(target_nonces(nonce), &mut state); + assert!(state.nonces_submitted.is_none()); + } } #[async_std::test] From 864baf63f47b5e8b6275344fc39a395496ae81cc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 26 Apr 2023 08:57:49 +0300 Subject: [PATCH 1038/1210] Fix max-size messages at test chains (#2064) * fix max-size messages submit for test chains * impl review suggestions --- bin/runtime-common/src/lib.rs | 14 +++ relays/bin-substrate/Cargo.toml | 7 +- relays/bin-substrate/src/chains/millau.rs | 27 +++++- relays/bin-substrate/src/chains/rialto.rs | 25 ++++- .../src/chains/rialto_parachain.rs | 25 ++++- .../bin-substrate/src/cli/encode_message.rs | 97 +++++++++++++------ 6 files changed, 162 insertions(+), 33 deletions(-) diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index e8a2d2470fa19..12b096492cd48 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -159,7 +159,21 @@ pub enum CustomNetworkId { RialtoParachain, } +impl TryFrom for CustomNetworkId { + type Error = (); + + fn try_from(chain: bp_runtime::ChainId) -> Result { + Ok(match chain { + bp_runtime::MILLAU_CHAIN_ID => Self::Millau, + bp_runtime::RIALTO_CHAIN_ID => Self::Rialto, + bp_runtime::RIALTO_PARACHAIN_CHAIN_ID => Self::RialtoParachain, + _ => return Err(()), + }) + } +} + impl CustomNetworkId { + /// Converts self to XCM' network id. pub const fn as_network_id(&self) -> NetworkId { match *self { CustomNetworkId::Millau => NetworkId::Kusama, diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 7853b9cb599ac..0a315035042a1 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -49,6 +49,9 @@ relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } +# we are not using this runtime to craft callsour transactions, but we still need it +# to prepare large XCM messages +rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies @@ -62,8 +65,8 @@ polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } - +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 44416195c6a44..9249958c286b5 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -17,11 +17,36 @@ //! Millau chain specification for CLI. use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::EncodedOrDecodedCall; +use bp_runtime::{ChainId, EncodedOrDecodedCall, RIALTO_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; +use bridge_runtime_common::CustomNetworkId; use relay_millau_client::Millau; use relay_substrate_client::SimpleRuntimeVersion; +use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for Millau { + fn encode_wire_message( + target: ChainId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result> { + let target = match target { + RIALTO_CHAIN_ID => CustomNetworkId::Rialto.as_network_id(), + RIALTO_PARACHAIN_CHAIN_ID => CustomNetworkId::RialtoParachain.as_network_id(), + _ => return Err(anyhow::format_err!("Unsupported target chain: {:?}", target)), + }; + + Ok(millau_runtime::xcm_config::ToRialtoOrRialtoParachainSwitchExporter::validate( + target, + 0, + &mut Some(Self::dummy_universal_source()?), + &mut Some(target.into()), + &mut Some(at_target_xcm), + ) + .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? + .0 + .1 + .0) + } + fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 34a448ae4cb13..fb3003b30d71f 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -17,11 +17,34 @@ //! Rialto chain specification for CLI. use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::EncodedOrDecodedCall; +use bp_runtime::{ChainId, EncodedOrDecodedCall, MILLAU_CHAIN_ID}; +use bridge_runtime_common::CustomNetworkId; use relay_rialto_client::Rialto; use relay_substrate_client::SimpleRuntimeVersion; +use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for Rialto { + fn encode_wire_message( + target: ChainId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result> { + let target = match target { + MILLAU_CHAIN_ID => CustomNetworkId::Millau.as_network_id(), + _ => return Err(anyhow::format_err!("Unsupported target chian: {:?}", target)), + }; + + Ok(rialto_runtime::millau_messages::ToMillauBlobExporter::validate( + target, + 0, + &mut Some(Self::dummy_universal_source()?), + &mut Some(target.into()), + &mut Some(at_target_xcm), + ) + .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? + .0 + .0) + } + fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 8ea2c1ffd433c..f1de10b5c5f31 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -17,11 +17,34 @@ //! Rialto parachain specification for CLI. use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::EncodedOrDecodedCall; +use bp_runtime::{ChainId, EncodedOrDecodedCall, MILLAU_CHAIN_ID}; +use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; use relay_substrate_client::SimpleRuntimeVersion; +use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for RialtoParachain { + fn encode_wire_message( + target: ChainId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result> { + let target = match target { + MILLAU_CHAIN_ID => CustomNetworkId::Millau.as_network_id(), + _ => return Err(anyhow::format_err!("Unsupported target chain: {:?}", target)), + }; + + Ok(rialto_parachain_runtime::millau_messages::ToMillauBlobExporter::validate( + target, + 0, + &mut Some(Self::dummy_universal_source()?), + &mut Some(target.into()), + &mut Some(at_target_xcm), + ) + .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? + .0 + .0) + } + fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 9abf8b2df6dda..25231a970bfcb 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -15,11 +15,13 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ExplicitOrMaximal, HexBytes}; -use bp_runtime::EncodedOrDecodedCall; +use bp_runtime::{ChainId, EncodedOrDecodedCall}; +use bridge_runtime_common::CustomNetworkId; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::Chain; use structopt::StructOpt; +use xcm::latest::prelude::*; /// All possible messages that may be delivered to generic Substrate chain. /// @@ -43,6 +45,31 @@ pub enum Message { pub type RawMessage = Vec; pub trait CliEncodeMessage: Chain { + /// Returns dummy `AccountId32` universal source given this network id. + fn dummy_universal_source() -> anyhow::Result { + use xcm::v3::prelude::*; + + let this_network = CustomNetworkId::try_from(Self::ID) + .map(|n| n.as_network_id()) + .map_err(|_| anyhow::format_err!("Unsupported chain: {:?}", Self::ID))?; + let this_location: InteriorMultiLocation = this_network.into(); + + let origin = MultiLocation { + parents: 0, + interior: X1(AccountId32 { network: Some(this_network), id: [0u8; 32] }), + }; + let universal_source = this_location + .within_global(origin) + .map_err(|e| anyhow::format_err!("Invalid location: {:?}", e))?; + + Ok(universal_source) + } + /// Returns XCM blob that is passed to the `send_message` function of the messages pallet + /// and then is sent over the wire. + fn encode_wire_message( + target: ChainId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result>; /// Encode an `execute` XCM call of the XCM pallet. fn encode_execute_xcm( message: xcm::VersionedXcm, @@ -56,41 +83,42 @@ pub trait CliEncodeMessage: Chain { } /// Encode message payload passed through CLI flags. -pub(crate) fn encode_message( +pub(crate) fn encode_message( message: &Message, ) -> anyhow::Result { Ok(match message { Message::Raw { ref data } => data.0.clone(), Message::Sized { ref size } => { - let expected_xcm_size = match *size { + let destination = CustomNetworkId::try_from(Target::ID) + .map(|n| n.as_network_id()) + .map_err(|_| anyhow::format_err!("Unsupported target chain: {:?}", Target::ID))?; + let expected_size = match *size { ExplicitOrMaximal::Explicit(size) => size, ExplicitOrMaximal::Maximal => compute_maximal_message_size( Source::max_extrinsic_size(), Target::max_extrinsic_size(), ), - }; - - // there's no way to craft XCM of the given size - we'll be using `ExpectPallet` - // instruction, which has byte vector inside - let mut current_vec_size = expected_xcm_size; - let xcm = loop { - let xcm = xcm::VersionedXcm::<()>::V3( - vec![xcm::v3::Instruction::ExpectPallet { - index: 0, - name: vec![42; current_vec_size as usize], - module_name: vec![], - crate_major: 0, - min_crate_minor: 0, - }] - .into(), - ); - if xcm.encode().len() <= expected_xcm_size as usize { - break xcm - } - - current_vec_size -= 1; - }; - xcm.encode() + } as usize; + + let at_target_xcm = vec![xcm::v3::Instruction::ClearOrigin; expected_size].into(); + let at_target_xcm_size = + Source::encode_wire_message(Target::ID, at_target_xcm)?.encoded_size(); + let at_target_xcm_overhead = at_target_xcm_size.saturating_sub(expected_size); + let at_target_xcm = vec![ + xcm::v3::Instruction::ClearOrigin; + expected_size.saturating_sub(at_target_xcm_overhead) + ] + .into(); + + xcm::VersionedXcm::<()>::V3( + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: at_target_xcm, + }] + .into(), + ) + .encode() }, }) } @@ -123,13 +151,21 @@ mod tests { use relay_millau_client::Millau; use relay_rialto_client::Rialto; + fn approximate_message_size(xcm_msg_len: usize) -> usize { + xcm_msg_len + Source::dummy_universal_source().unwrap().encoded_size() + } + #[test] fn encode_explicit_size_message_works() { let msg = encode_message::(&Message::Sized { size: ExplicitOrMaximal::Explicit(100), }) .unwrap(); - assert_eq!(msg.len(), 100); + // since it isn't the returned XCM what is sent over the wire, we can only check if + // it is close to what we need + assert!( + (1f64 - (approximate_message_size::(msg.len()) as f64) / 100_f64).abs() < 0.1 + ); // check that it decodes to valid xcm let _ = decode_xcm::<()>(msg).unwrap(); } @@ -144,7 +180,12 @@ mod tests { let msg = encode_message::(&Message::Sized { size: ExplicitOrMaximal::Maximal }) .unwrap(); - assert_eq!(msg.len(), maximal_size as usize); + // since it isn't the returned XCM what is sent over the wire, we can only check if + // it is close to what we need + assert!( + (1f64 - approximate_message_size::(msg.len()) as f64 / maximal_size as f64) + .abs() < 0.1 + ); // check that it decodes to valid xcm let _ = decode_xcm::<()>(msg).unwrap(); } From 1a1173b40b74406acc2ef4da1228e418e1597a6e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 26 Apr 2023 09:49:05 +0300 Subject: [PATCH 1039/1210] Update subxt dependencies (#2072) --- relays/client-rialto-parachain/Cargo.toml | 2 +- .../src/codegen_runtime.rs | 7715 +---------------- relays/client-rialto-parachain/src/lib.rs | 3 +- 3 files changed, 199 insertions(+), 7521 deletions(-) diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 4450dee37116f..b6d5c423336eb 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } -subxt = { version = "0.27.1", default-features = false, features = [] } +subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs index 3ea4a0ac2b5a0..1338d4938a36f 100644 --- a/relays/client-rialto-parachain/src/codegen_runtime.rs +++ b/relays/client-rialto-parachain/src/codegen_runtime.rs @@ -22,5956 +22,24 @@ #[allow(clippy::all)] pub mod api { use super::api as root_mod; - pub static PALLETS: [&str; 16usize] = [ - "System", - "Timestamp", - "Sudo", - "TransactionPayment", - "ParachainSystem", - "ParachainInfo", - "Balances", - "Aura", - "AuraExt", - "XcmpQueue", - "PolkadotXcm", - "CumulusXcm", - "DmpQueue", - "BridgeRelayers", - "BridgeMillauGrandpa", - "BridgeMillauMessages", - ]; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub enum Event { - #[codec(index = 0)] - System(system::Event), - #[codec(index = 2)] - Sudo(sudo::Event), - #[codec(index = 3)] - TransactionPayment(transaction_payment::Event), - #[codec(index = 20)] - ParachainSystem(parachain_system::Event), - #[codec(index = 30)] - Balances(balances::Event), - #[codec(index = 50)] - XcmpQueue(xcmp_queue::Event), - #[codec(index = 51)] - PolkadotXcm(polkadot_xcm::Event), - #[codec(index = 52)] - CumulusXcm(cumulus_xcm::Event), - #[codec(index = 53)] - DmpQueue(dmp_queue::Event), - #[codec(index = 54)] - BridgeRelayers(bridge_relayers::Event), - #[codec(index = 55)] - BridgeMillauGrandpa(bridge_millau_grandpa::Event), - #[codec(index = 56)] - BridgeMillauMessages(bridge_millau_messages::Event), - } - pub mod system { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Remark { - pub remark: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - pub struct SetHeapPages { - pub pages: ::core::primitive::u64, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetCode { - pub code: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetCodeWithoutChecks { - pub code: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetStorage { - pub items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct KillStorage { - pub keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct KillPrefix { - pub prefix: ::std::vec::Vec<::core::primitive::u8>, - pub subkeys: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct RemarkWithEvent { - pub remark: ::std::vec::Vec<::core::primitive::u8>, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Make some on-chain remark."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(1)`"] - pub fn remark( - &self, - remark: ::std::vec::Vec<::core::primitive::u8>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "remark", - Remark { remark }, - [ - 101u8, 80u8, 195u8, 226u8, 224u8, 247u8, 60u8, 128u8, 3u8, 101u8, 51u8, - 147u8, 96u8, 126u8, 76u8, 230u8, 194u8, 227u8, 191u8, 73u8, 160u8, - 146u8, 87u8, 147u8, 243u8, 28u8, 228u8, 116u8, 224u8, 181u8, 129u8, - 160u8, - ], - ) - } - #[doc = "Set the number of pages in the WebAssembly environment's heap."] - pub fn set_heap_pages( - &self, - pages: ::core::primitive::u64, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "set_heap_pages", - SetHeapPages { pages }, - [ - 43u8, 103u8, 128u8, 49u8, 156u8, 136u8, 11u8, 204u8, 80u8, 6u8, 244u8, - 86u8, 171u8, 44u8, 140u8, 225u8, 142u8, 198u8, 43u8, 87u8, 26u8, 45u8, - 125u8, 222u8, 165u8, 254u8, 172u8, 158u8, 39u8, 178u8, 86u8, 87u8, - ], - ) - } - #[doc = "Set the new runtime code."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code`"] - pub fn set_code( - &self, - code: ::std::vec::Vec<::core::primitive::u8>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "set_code", - SetCode { code }, - [ - 27u8, 104u8, 244u8, 205u8, 188u8, 254u8, 121u8, 13u8, 106u8, 120u8, - 244u8, 108u8, 97u8, 84u8, 100u8, 68u8, 26u8, 69u8, 93u8, 128u8, 107u8, - 4u8, 3u8, 142u8, 13u8, 134u8, 196u8, 62u8, 113u8, 181u8, 14u8, 40u8, - ], - ) - } - #[doc = "Set the new runtime code without doing any checks of the given `code`."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(C)` where `C` length of `code`"] - pub fn set_code_without_checks( - &self, - code: ::std::vec::Vec<::core::primitive::u8>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "set_code_without_checks", - SetCodeWithoutChecks { code }, - [ - 102u8, 160u8, 125u8, 235u8, 30u8, 23u8, 45u8, 239u8, 112u8, 148u8, - 159u8, 158u8, 42u8, 93u8, 206u8, 94u8, 80u8, 250u8, 66u8, 195u8, 60u8, - 40u8, 142u8, 169u8, 183u8, 80u8, 80u8, 96u8, 3u8, 231u8, 99u8, 216u8, - ], - ) - } - #[doc = "Set some items of storage."] - pub fn set_storage( - &self, - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "set_storage", - SetStorage { items }, - [ - 74u8, 43u8, 106u8, 255u8, 50u8, 151u8, 192u8, 155u8, 14u8, 90u8, 19u8, - 45u8, 165u8, 16u8, 235u8, 242u8, 21u8, 131u8, 33u8, 172u8, 119u8, 78u8, - 140u8, 10u8, 107u8, 202u8, 122u8, 235u8, 181u8, 191u8, 22u8, 116u8, - ], - ) - } - #[doc = "Kill some items from storage."] - pub fn kill_storage( - &self, - keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "kill_storage", - KillStorage { keys }, - [ - 174u8, 174u8, 13u8, 174u8, 75u8, 138u8, 128u8, 235u8, 222u8, 216u8, - 85u8, 18u8, 198u8, 1u8, 138u8, 70u8, 19u8, 108u8, 209u8, 41u8, 228u8, - 67u8, 130u8, 230u8, 160u8, 207u8, 11u8, 180u8, 139u8, 242u8, 41u8, - 15u8, - ], - ) - } - #[doc = "Kill all storage items with a key that starts with the given prefix."] - #[doc = ""] - #[doc = "**NOTE:** We rely on the Root origin to provide us the number of subkeys under"] - #[doc = "the prefix we are removing to accurately calculate the weight of this function."] - pub fn kill_prefix( - &self, - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "kill_prefix", - KillPrefix { prefix, subkeys }, - [ - 203u8, 116u8, 217u8, 42u8, 154u8, 215u8, 77u8, 217u8, 13u8, 22u8, - 193u8, 2u8, 128u8, 115u8, 179u8, 115u8, 187u8, 218u8, 129u8, 34u8, - 80u8, 4u8, 173u8, 120u8, 92u8, 35u8, 237u8, 112u8, 201u8, 207u8, 200u8, - 48u8, - ], - ) - } - #[doc = "Make some on-chain remark and emit event."] - pub fn remark_with_event( - &self, - remark: ::std::vec::Vec<::core::primitive::u8>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "System", - "remark_with_event", - RemarkWithEvent { remark }, - [ - 123u8, 225u8, 180u8, 179u8, 144u8, 74u8, 27u8, 85u8, 101u8, 75u8, - 134u8, 44u8, 181u8, 25u8, 183u8, 158u8, 14u8, 213u8, 56u8, 225u8, - 136u8, 88u8, 26u8, 114u8, 178u8, 43u8, 176u8, 43u8, 240u8, 84u8, 116u8, - 46u8, - ], - ) - } - } - } - #[doc = "Event for the System pallet."] - pub type Event = runtime_types::frame_system::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An extrinsic completed successfully."] - pub struct ExtrinsicSuccess { - pub dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - } - impl ::subxt::events::StaticEvent for ExtrinsicSuccess { - const PALLET: &'static str = "System"; - const EVENT: &'static str = "ExtrinsicSuccess"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An extrinsic failed."] - pub struct ExtrinsicFailed { - pub dispatch_error: runtime_types::sp_runtime::DispatchError, - pub dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - } - impl ::subxt::events::StaticEvent for ExtrinsicFailed { - const PALLET: &'static str = "System"; - const EVENT: &'static str = "ExtrinsicFailed"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "`:code` was updated."] - pub struct CodeUpdated; - impl ::subxt::events::StaticEvent for CodeUpdated { - const PALLET: &'static str = "System"; - const EVENT: &'static str = "CodeUpdated"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A new account was created."] - pub struct NewAccount { - pub account: ::sp_core::crypto::AccountId32, - } - impl ::subxt::events::StaticEvent for NewAccount { - const PALLET: &'static str = "System"; - const EVENT: &'static str = "NewAccount"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An account was reaped."] - pub struct KilledAccount { - pub account: ::sp_core::crypto::AccountId32, - } - impl ::subxt::events::StaticEvent for KilledAccount { - const PALLET: &'static str = "System"; - const EVENT: &'static str = "KilledAccount"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "On on-chain remark happened."] - pub struct Remarked { - pub sender: ::sp_core::crypto::AccountId32, - pub hash: ::subxt::utils::H256, - } - impl ::subxt::events::StaticEvent for Remarked { - const PALLET: &'static str = "System"; - const EVENT: &'static str = "Remarked"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " The full account information for a particular account ID."] - pub fn account( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::frame_system::AccountInfo< - ::core::primitive::u32, - runtime_types::pallet_balances::types::AccountData< - ::core::primitive::u128, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "Account", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 248u8, 178u8, 160u8, 222u8, 45u8, 231u8, 115u8, 164u8, 98u8, 184u8, - 174u8, 206u8, 149u8, 190u8, 175u8, 34u8, 202u8, 230u8, 69u8, 218u8, - 83u8, 43u8, 170u8, 41u8, 106u8, 77u8, 233u8, 97u8, 114u8, 14u8, 155u8, - 131u8, - ], - ) - } - #[doc = " The full account information for a particular account ID."] - pub fn account_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::frame_system::AccountInfo< - ::core::primitive::u32, - runtime_types::pallet_balances::types::AccountData< - ::core::primitive::u128, - >, - >, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "Account", - Vec::new(), - [ - 248u8, 178u8, 160u8, 222u8, 45u8, 231u8, 115u8, 164u8, 98u8, 184u8, - 174u8, 206u8, 149u8, 190u8, 175u8, 34u8, 202u8, 230u8, 69u8, 218u8, - 83u8, 43u8, 170u8, 41u8, 106u8, 77u8, 233u8, 97u8, 114u8, 14u8, 155u8, - 131u8, - ], - ) - } - #[doc = " Total extrinsics count for the current block."] - pub fn extrinsic_count( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "ExtrinsicCount", - vec![], - [ - 223u8, 60u8, 201u8, 120u8, 36u8, 44u8, 180u8, 210u8, 242u8, 53u8, - 222u8, 154u8, 123u8, 176u8, 249u8, 8u8, 225u8, 28u8, 232u8, 4u8, 136u8, - 41u8, 151u8, 82u8, 189u8, 149u8, 49u8, 166u8, 139u8, 9u8, 163u8, 231u8, - ], - ) - } - #[doc = " The current weight for the block."] - pub fn block_weight( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::frame_support::dispatch::PerDispatchClass< - ::sp_weights::Weight, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "BlockWeight", - vec![], - [ - 120u8, 67u8, 71u8, 163u8, 36u8, 202u8, 52u8, 106u8, 143u8, 155u8, - 144u8, 87u8, 142u8, 241u8, 232u8, 183u8, 56u8, 235u8, 27u8, 237u8, - 20u8, 202u8, 33u8, 85u8, 189u8, 0u8, 28u8, 52u8, 198u8, 40u8, 219u8, - 54u8, - ], - ) - } - #[doc = " Total length (in bytes) for all extrinsics put together, for the current block."] - pub fn all_extrinsics_len( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "AllExtrinsicsLen", - vec![], - [ - 202u8, 145u8, 209u8, 225u8, 40u8, 220u8, 174u8, 74u8, 93u8, 164u8, - 254u8, 248u8, 254u8, 192u8, 32u8, 117u8, 96u8, 149u8, 53u8, 145u8, - 219u8, 64u8, 234u8, 18u8, 217u8, 200u8, 203u8, 141u8, 145u8, 28u8, - 134u8, 60u8, - ], - ) - } - #[doc = " Map of block numbers to block hashes."] - pub fn block_hash( - &self, - _0: impl ::std::borrow::Borrow<::core::primitive::u32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "BlockHash", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Twox64Concat, - )], - [ - 50u8, 112u8, 176u8, 239u8, 175u8, 18u8, 205u8, 20u8, 241u8, 195u8, - 21u8, 228u8, 186u8, 57u8, 200u8, 25u8, 38u8, 44u8, 106u8, 20u8, 168u8, - 80u8, 76u8, 235u8, 12u8, 51u8, 137u8, 149u8, 200u8, 4u8, 220u8, 237u8, - ], - ) - } - #[doc = " Map of block numbers to block hashes."] - pub fn block_hash_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "BlockHash", - Vec::new(), - [ - 50u8, 112u8, 176u8, 239u8, 175u8, 18u8, 205u8, 20u8, 241u8, 195u8, - 21u8, 228u8, 186u8, 57u8, 200u8, 25u8, 38u8, 44u8, 106u8, 20u8, 168u8, - 80u8, 76u8, 235u8, 12u8, 51u8, 137u8, 149u8, 200u8, 4u8, 220u8, 237u8, - ], - ) - } - #[doc = " Extrinsics data for the current block (maps an extrinsic's index to its data)."] - pub fn extrinsic_data( - &self, - _0: impl ::std::borrow::Borrow<::core::primitive::u32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "ExtrinsicData", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Twox64Concat, - )], - [ - 210u8, 224u8, 211u8, 186u8, 118u8, 210u8, 185u8, 194u8, 238u8, 211u8, - 254u8, 73u8, 67u8, 184u8, 31u8, 229u8, 168u8, 125u8, 98u8, 23u8, 241u8, - 59u8, 49u8, 86u8, 126u8, 9u8, 114u8, 163u8, 160u8, 62u8, 50u8, 67u8, - ], - ) - } - #[doc = " Extrinsics data for the current block (maps an extrinsic's index to its data)."] - pub fn extrinsic_data_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "ExtrinsicData", - Vec::new(), - [ - 210u8, 224u8, 211u8, 186u8, 118u8, 210u8, 185u8, 194u8, 238u8, 211u8, - 254u8, 73u8, 67u8, 184u8, 31u8, 229u8, 168u8, 125u8, 98u8, 23u8, 241u8, - 59u8, 49u8, 86u8, 126u8, 9u8, 114u8, 163u8, 160u8, 62u8, 50u8, 67u8, - ], - ) - } - #[doc = " The current block number being processed. Set by `execute_block`."] - pub fn number( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "Number", - vec![], - [ - 228u8, 96u8, 102u8, 190u8, 252u8, 130u8, 239u8, 172u8, 126u8, 235u8, - 246u8, 139u8, 208u8, 15u8, 88u8, 245u8, 141u8, 232u8, 43u8, 204u8, - 36u8, 87u8, 211u8, 141u8, 187u8, 68u8, 236u8, 70u8, 193u8, 235u8, - 164u8, 191u8, - ], - ) - } - #[doc = " Hash of the previous block."] - pub fn parent_hash( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::subxt::utils::H256>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "ParentHash", - vec![], - [ - 232u8, 206u8, 177u8, 119u8, 38u8, 57u8, 233u8, 50u8, 225u8, 49u8, - 169u8, 176u8, 210u8, 51u8, 231u8, 176u8, 234u8, 186u8, 188u8, 112u8, - 15u8, 152u8, 195u8, 232u8, 201u8, 97u8, 208u8, 249u8, 9u8, 163u8, 69u8, - 36u8, - ], - ) - } - #[doc = " Digest of the current block, also part of the block header."] - pub fn digest( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::sp_runtime::generic::Digest>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "Digest", - vec![], - [ - 83u8, 141u8, 200u8, 132u8, 182u8, 55u8, 197u8, 122u8, 13u8, 159u8, - 31u8, 42u8, 60u8, 191u8, 89u8, 221u8, 242u8, 47u8, 199u8, 213u8, 48u8, - 216u8, 131u8, 168u8, 245u8, 82u8, 56u8, 190u8, 62u8, 69u8, 96u8, 37u8, - ], - ) - } - #[doc = " Events deposited for the current block."] - #[doc = ""] - #[doc = " NOTE: The item is unbound and should therefore never be read on chain."] - #[doc = " It could otherwise inflate the PoV size of a block."] - #[doc = ""] - #[doc = " Events have a large in-memory size. Box the events to not go out-of-memory"] - #[doc = " just in case someone still reads them from within the runtime."] - pub fn events( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec< - runtime_types::frame_system::EventRecord< - runtime_types::rialto_parachain_runtime::RuntimeEvent, - ::subxt::utils::H256, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "Events", - vec![], - [ - 76u8, 19u8, 44u8, 121u8, 59u8, 168u8, 101u8, 101u8, 248u8, 3u8, 172u8, - 27u8, 249u8, 200u8, 147u8, 17u8, 4u8, 102u8, 186u8, 6u8, 152u8, 62u8, - 76u8, 195u8, 45u8, 188u8, 191u8, 30u8, 134u8, 78u8, 199u8, 93u8, - ], - ) - } - #[doc = " The number of events in the `Events` list."] - pub fn event_count( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "EventCount", - vec![], - [ - 236u8, 93u8, 90u8, 177u8, 250u8, 211u8, 138u8, 187u8, 26u8, 208u8, - 203u8, 113u8, 221u8, 233u8, 227u8, 9u8, 249u8, 25u8, 202u8, 185u8, - 161u8, 144u8, 167u8, 104u8, 127u8, 187u8, 38u8, 18u8, 52u8, 61u8, 66u8, - 112u8, - ], - ) - } - #[doc = " Mapping between a topic (represented by T::Hash) and a vector of indexes"] - #[doc = " of events in the `>` list."] - #[doc = ""] - #[doc = " All topic vectors have deterministic storage locations depending on the topic. This"] - #[doc = " allows light-clients to leverage the changes trie storage tracking mechanism and"] - #[doc = " in case of changes fetch the list of events of interest."] - #[doc = ""] - #[doc = " The value has the type `(T::BlockNumber, EventIndex)` because if we used only just"] - #[doc = " the `EventIndex` then in case if the topic has the same contents on the next block"] - #[doc = " no notification will be triggered thus the event might be lost."] - pub fn event_topics( - &self, - _0: impl ::std::borrow::Borrow<::subxt::utils::H256>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec<(::core::primitive::u32, ::core::primitive::u32)>, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "EventTopics", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 205u8, 90u8, 142u8, 190u8, 176u8, 37u8, 94u8, 82u8, 98u8, 1u8, 129u8, - 63u8, 246u8, 101u8, 130u8, 58u8, 216u8, 16u8, 139u8, 196u8, 154u8, - 111u8, 110u8, 178u8, 24u8, 44u8, 183u8, 176u8, 232u8, 82u8, 223u8, - 38u8, - ], - ) - } - #[doc = " Mapping between a topic (represented by T::Hash) and a vector of indexes"] - #[doc = " of events in the `>` list."] - #[doc = ""] - #[doc = " All topic vectors have deterministic storage locations depending on the topic. This"] - #[doc = " allows light-clients to leverage the changes trie storage tracking mechanism and"] - #[doc = " in case of changes fetch the list of events of interest."] - #[doc = ""] - #[doc = " The value has the type `(T::BlockNumber, EventIndex)` because if we used only just"] - #[doc = " the `EventIndex` then in case if the topic has the same contents on the next block"] - #[doc = " no notification will be triggered thus the event might be lost."] - pub fn event_topics_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec<(::core::primitive::u32, ::core::primitive::u32)>, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "EventTopics", - Vec::new(), - [ - 205u8, 90u8, 142u8, 190u8, 176u8, 37u8, 94u8, 82u8, 98u8, 1u8, 129u8, - 63u8, 246u8, 101u8, 130u8, 58u8, 216u8, 16u8, 139u8, 196u8, 154u8, - 111u8, 110u8, 178u8, 24u8, 44u8, 183u8, 176u8, 232u8, 82u8, 223u8, - 38u8, - ], - ) - } - #[doc = " Stores the `spec_version` and `spec_name` of when the last runtime upgrade happened."] - pub fn last_runtime_upgrade( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::frame_system::LastRuntimeUpgradeInfo, - >, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "LastRuntimeUpgrade", - vec![], - [ - 52u8, 37u8, 117u8, 111u8, 57u8, 130u8, 196u8, 14u8, 99u8, 77u8, 91u8, - 126u8, 178u8, 249u8, 78u8, 34u8, 9u8, 194u8, 92u8, 105u8, 113u8, 81u8, - 185u8, 127u8, 245u8, 184u8, 60u8, 29u8, 234u8, 182u8, 96u8, 196u8, - ], - ) - } - #[doc = " True if we have upgraded so that `type RefCount` is `u32`. False (default) if not."] - pub fn upgraded_to_u32_ref_count( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "UpgradedToU32RefCount", - vec![], - [ - 171u8, 88u8, 244u8, 92u8, 122u8, 67u8, 27u8, 18u8, 59u8, 175u8, 175u8, - 178u8, 20u8, 150u8, 213u8, 59u8, 222u8, 141u8, 32u8, 107u8, 3u8, 114u8, - 83u8, 250u8, 180u8, 233u8, 152u8, 54u8, 187u8, 99u8, 131u8, 204u8, - ], - ) - } - #[doc = " True if we have upgraded so that AccountInfo contains three types of `RefCount`. False"] - #[doc = " (default) if not."] - pub fn upgraded_to_triple_ref_count( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "UpgradedToTripleRefCount", - vec![], - [ - 90u8, 33u8, 56u8, 86u8, 90u8, 101u8, 89u8, 133u8, 203u8, 56u8, 201u8, - 210u8, 244u8, 232u8, 150u8, 18u8, 51u8, 105u8, 14u8, 230u8, 103u8, - 155u8, 246u8, 99u8, 53u8, 207u8, 225u8, 128u8, 186u8, 76u8, 40u8, - 185u8, - ], - ) - } - #[doc = " The execution phase of the block."] - pub fn execution_phase( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "System", - "ExecutionPhase", - vec![], - [ - 230u8, 183u8, 221u8, 135u8, 226u8, 223u8, 55u8, 104u8, 138u8, 224u8, - 103u8, 156u8, 222u8, 99u8, 203u8, 199u8, 164u8, 168u8, 193u8, 133u8, - 201u8, 155u8, 63u8, 95u8, 17u8, 206u8, 165u8, 123u8, 161u8, 33u8, - 172u8, 93u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " Block & extrinsics weights: base values and limits."] - pub fn block_weights( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::frame_system::limits::BlockWeights, - >, - > { - ::subxt::constants::StaticConstantAddress::new( - "System", - "BlockWeights", - [ - 118u8, 253u8, 239u8, 217u8, 145u8, 115u8, 85u8, 86u8, 172u8, 248u8, - 139u8, 32u8, 158u8, 126u8, 172u8, 188u8, 197u8, 105u8, 145u8, 235u8, - 171u8, 50u8, 31u8, 225u8, 167u8, 187u8, 241u8, 87u8, 6u8, 17u8, 234u8, - 185u8, - ], - ) - } - #[doc = " The maximum length of a block (in bytes)."] - pub fn block_length( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::frame_system::limits::BlockLength, - >, - > { - ::subxt::constants::StaticConstantAddress::new( - "System", - "BlockLength", - [ - 116u8, 184u8, 225u8, 228u8, 207u8, 203u8, 4u8, 220u8, 234u8, 198u8, - 150u8, 108u8, 205u8, 87u8, 194u8, 131u8, 229u8, 51u8, 140u8, 4u8, 47u8, - 12u8, 200u8, 144u8, 153u8, 62u8, 51u8, 39u8, 138u8, 205u8, 203u8, - 236u8, - ], - ) - } - #[doc = " Maximum number of block number to block hash mappings to keep (oldest pruned first)."] - pub fn block_hash_count( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "System", - "BlockHashCount", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - #[doc = " The weight of runtime database operations the runtime can invoke."] - pub fn db_weight( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType, - > { - ::subxt::constants::StaticConstantAddress::new( - "System", - "DbWeight", - [ - 124u8, 162u8, 190u8, 149u8, 49u8, 177u8, 162u8, 231u8, 62u8, 167u8, - 199u8, 181u8, 43u8, 232u8, 185u8, 116u8, 195u8, 51u8, 233u8, 223u8, - 20u8, 129u8, 246u8, 13u8, 65u8, 180u8, 64u8, 9u8, 157u8, 59u8, 245u8, - 118u8, - ], - ) - } - #[doc = " Get the chain's current version."] - pub fn version( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType, - > { - ::subxt::constants::StaticConstantAddress::new( - "System", - "Version", - [ - 93u8, 98u8, 57u8, 243u8, 229u8, 8u8, 234u8, 231u8, 72u8, 230u8, 139u8, - 47u8, 63u8, 181u8, 17u8, 2u8, 220u8, 231u8, 104u8, 237u8, 185u8, 143u8, - 165u8, 253u8, 188u8, 76u8, 147u8, 12u8, 170u8, 26u8, 74u8, 200u8, - ], - ) - } - #[doc = " The designated SS58 prefix of this chain."] - #[doc = ""] - #[doc = " This replaces the \"ss58Format\" property declared in the chain spec. Reason is"] - #[doc = " that the runtime should know about the prefix in order to make use of it as"] - #[doc = " an identifier of the chain."] - pub fn ss58_prefix( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u16>, - > { - ::subxt::constants::StaticConstantAddress::new( - "System", - "SS58Prefix", - [ - 116u8, 33u8, 2u8, 170u8, 181u8, 147u8, 171u8, 169u8, 167u8, 227u8, - 41u8, 144u8, 11u8, 236u8, 82u8, 100u8, 74u8, 60u8, 184u8, 72u8, 169u8, - 90u8, 208u8, 135u8, 15u8, 117u8, 10u8, 123u8, 128u8, 193u8, 29u8, 70u8, - ], - ) - } - } - } - } - pub mod timestamp { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Set { - #[codec(compact)] - pub now: ::core::primitive::u64, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Set the current time."] - #[doc = ""] - #[doc = "This call should be invoked exactly once per block. It will panic at the finalization"] - #[doc = "phase, if this call hasn't been invoked by that time."] - #[doc = ""] - #[doc = "The timestamp should be greater than the previous one by the amount specified by"] - #[doc = "`MinimumPeriod`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be `Inherent`."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(1)` (Note that implementations of `OnTimestampSet` must also be `O(1)`)"] - #[doc = "- 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in"] - #[doc = " `on_finalize`)"] - #[doc = "- 1 event handler `on_timestamp_set`. Must be `O(1)`."] - pub fn set( - &self, - now: ::core::primitive::u64, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Timestamp", - "set", - Set { now }, - [ - 6u8, 97u8, 172u8, 236u8, 118u8, 238u8, 228u8, 114u8, 15u8, 115u8, - 102u8, 85u8, 66u8, 151u8, 16u8, 33u8, 187u8, 17u8, 166u8, 88u8, 127u8, - 214u8, 182u8, 51u8, 168u8, 88u8, 43u8, 101u8, 185u8, 8u8, 1u8, 28u8, - ], - ) - } - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " Current time for the current block."] - pub fn now( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u64>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Timestamp", - "Now", - vec![], - [ - 148u8, 53u8, 50u8, 54u8, 13u8, 161u8, 57u8, 150u8, 16u8, 83u8, 144u8, - 221u8, 59u8, 75u8, 158u8, 130u8, 39u8, 123u8, 106u8, 134u8, 202u8, - 185u8, 83u8, 85u8, 60u8, 41u8, 120u8, 96u8, 210u8, 34u8, 2u8, 250u8, - ], - ) - } - #[doc = " Did the timestamp get updated in this block?"] - pub fn did_update( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Timestamp", - "DidUpdate", - vec![], - [ - 70u8, 13u8, 92u8, 186u8, 80u8, 151u8, 167u8, 90u8, 158u8, 232u8, 175u8, - 13u8, 103u8, 135u8, 2u8, 78u8, 16u8, 6u8, 39u8, 158u8, 167u8, 85u8, - 27u8, 47u8, 122u8, 73u8, 127u8, 26u8, 35u8, 168u8, 72u8, 204u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " The minimum period between blocks. Beware that this is different to the *expected*"] - #[doc = " period that the block production apparatus provides. Your chosen consensus system will"] - #[doc = " generally work with this to determine a sensible block time. e.g. For Aura, it will be"] - #[doc = " double this period on default settings."] - pub fn minimum_period( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u64>, - > { - ::subxt::constants::StaticConstantAddress::new( - "Timestamp", - "MinimumPeriod", - [ - 128u8, 214u8, 205u8, 242u8, 181u8, 142u8, 124u8, 231u8, 190u8, 146u8, - 59u8, 226u8, 157u8, 101u8, 103u8, 117u8, 249u8, 65u8, 18u8, 191u8, - 103u8, 119u8, 53u8, 85u8, 81u8, 96u8, 220u8, 42u8, 184u8, 239u8, 42u8, - 246u8, - ], - ) - } - } - } - } - pub mod sudo { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Sudo { - pub call: ::std::boxed::Box, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SudoUncheckedWeight { - pub call: ::std::boxed::Box, - pub weight: ::sp_weights::Weight, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetKey { - pub new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SudoAs { - pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pub call: ::std::boxed::Box, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - pub fn sudo( - &self, - call: runtime_types::rialto_parachain_runtime::RuntimeCall, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Sudo", - "sudo", - Sudo { call: ::std::boxed::Box::new(call) }, - [ - 19u8, 178u8, 172u8, 30u8, 28u8, 209u8, 160u8, 61u8, 76u8, 239u8, 71u8, - 124u8, 21u8, 34u8, 233u8, 176u8, 100u8, 90u8, 198u8, 118u8, 117u8, 2u8, - 147u8, 7u8, 109u8, 1u8, 32u8, 35u8, 99u8, 0u8, 107u8, 145u8, - ], - ) - } - #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] - #[doc = "This function does not check the weight of the call, and instead allows the"] - #[doc = "Sudo user to specify the weight of the call."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - pub fn sudo_unchecked_weight( - &self, - call: runtime_types::rialto_parachain_runtime::RuntimeCall, - weight: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Sudo", - "sudo_unchecked_weight", - SudoUncheckedWeight { call: ::std::boxed::Box::new(call), weight }, - [ - 145u8, 160u8, 12u8, 105u8, 228u8, 240u8, 115u8, 105u8, 220u8, 99u8, - 215u8, 228u8, 115u8, 71u8, 109u8, 28u8, 149u8, 247u8, 159u8, 216u8, - 76u8, 71u8, 68u8, 87u8, 254u8, 146u8, 185u8, 174u8, 251u8, 209u8, 72u8, - 122u8, - ], - ) - } - #[doc = "Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo"] - #[doc = "key."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - pub fn set_key( - &self, - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Sudo", - "set_key", - SetKey { new }, - [ - 23u8, 224u8, 218u8, 169u8, 8u8, 28u8, 111u8, 199u8, 26u8, 88u8, 225u8, - 105u8, 17u8, 19u8, 87u8, 156u8, 97u8, 67u8, 89u8, 173u8, 70u8, 0u8, - 5u8, 246u8, 198u8, 135u8, 182u8, 180u8, 44u8, 9u8, 212u8, 95u8, - ], - ) - } - #[doc = "Authenticates the sudo key and dispatches a function call with `Signed` origin from"] - #[doc = "a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] - pub fn sudo_as( - &self, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: runtime_types::rialto_parachain_runtime::RuntimeCall, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Sudo", - "sudo_as", - SudoAs { who, call: ::std::boxed::Box::new(call) }, - [ - 229u8, 45u8, 129u8, 96u8, 54u8, 29u8, 159u8, 77u8, 210u8, 144u8, 29u8, - 97u8, 127u8, 133u8, 122u8, 110u8, 152u8, 194u8, 211u8, 246u8, 97u8, - 197u8, 187u8, 203u8, 46u8, 12u8, 104u8, 125u8, 15u8, 226u8, 28u8, - 183u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_sudo::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A sudo just took place. \\[result\\]"] - pub struct Sudid { - pub sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - } - impl ::subxt::events::StaticEvent for Sudid { - const PALLET: &'static str = "Sudo"; - const EVENT: &'static str = "Sudid"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "The \\[sudoer\\] just switched identity; the old key is supplied if one existed."] - pub struct KeyChanged { - pub old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, - } - impl ::subxt::events::StaticEvent for KeyChanged { - const PALLET: &'static str = "Sudo"; - const EVENT: &'static str = "KeyChanged"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A sudo just took place. \\[result\\]"] - pub struct SudoAsDone { - pub sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - } - impl ::subxt::events::StaticEvent for SudoAsDone { - const PALLET: &'static str = "Sudo"; - const EVENT: &'static str = "SudoAsDone"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " The `AccountId` of the sudo key."] - pub fn key( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::sp_core::crypto::AccountId32>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Sudo", - "Key", - vec![], - [ - 244u8, 73u8, 188u8, 136u8, 218u8, 163u8, 68u8, 179u8, 122u8, 173u8, - 34u8, 108u8, 137u8, 28u8, 182u8, 16u8, 196u8, 92u8, 138u8, 34u8, 102u8, - 80u8, 199u8, 88u8, 107u8, 207u8, 36u8, 22u8, 168u8, 167u8, 20u8, 142u8, - ], - ) - } - } - } - } - pub mod transaction_payment { - use super::{root_mod, runtime_types}; - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_transaction_payment::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,"] - #[doc = "has been paid by `who`."] - pub struct TransactionFeePaid { - pub who: ::sp_core::crypto::AccountId32, - pub actual_fee: ::core::primitive::u128, - pub tip: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for TransactionFeePaid { - const PALLET: &'static str = "TransactionPayment"; - const EVENT: &'static str = "TransactionFeePaid"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - pub fn next_fee_multiplier( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::sp_arithmetic::fixed_point::FixedU128, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "TransactionPayment", - "NextFeeMultiplier", - vec![], - [ - 210u8, 0u8, 206u8, 165u8, 183u8, 10u8, 206u8, 52u8, 14u8, 90u8, 218u8, - 197u8, 189u8, 125u8, 113u8, 216u8, 52u8, 161u8, 45u8, 24u8, 245u8, - 237u8, 121u8, 41u8, 106u8, 29u8, 45u8, 129u8, 250u8, 203u8, 206u8, - 180u8, - ], - ) - } - pub fn storage_version( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::pallet_transaction_payment::Releases, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "TransactionPayment", - "StorageVersion", - vec![], - [ - 219u8, 243u8, 82u8, 176u8, 65u8, 5u8, 132u8, 114u8, 8u8, 82u8, 176u8, - 200u8, 97u8, 150u8, 177u8, 164u8, 166u8, 11u8, 34u8, 12u8, 12u8, 198u8, - 58u8, 191u8, 186u8, 221u8, 221u8, 119u8, 181u8, 253u8, 154u8, 228u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " A fee mulitplier for `Operational` extrinsics to compute \"virtual tip\" to boost their"] - #[doc = " `priority`"] - #[doc = ""] - #[doc = " This value is multipled by the `final_fee` to obtain a \"virtual tip\" that is later"] - #[doc = " added to a tip component in regular `priority` calculations."] - #[doc = " It means that a `Normal` transaction can front-run a similarly-sized `Operational`"] - #[doc = " extrinsic (with no tip), by including a tip value greater than the virtual tip."] - #[doc = ""] - #[doc = " ```rust,ignore"] - #[doc = " // For `Normal`"] - #[doc = " let priority = priority_calc(tip);"] - #[doc = ""] - #[doc = " // For `Operational`"] - #[doc = " let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier;"] - #[doc = " let priority = priority_calc(tip + virtual_tip);"] - #[doc = " ```"] - #[doc = ""] - #[doc = " Note that since we use `final_fee` the multiplier applies also to the regular `tip`"] - #[doc = " sent with the transaction. So, not only does the transaction get a priority bump based"] - #[doc = " on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational`"] - #[doc = " transactions."] - pub fn operational_fee_multiplier( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u8>, - > { - ::subxt::constants::StaticConstantAddress::new( - "TransactionPayment", - "OperationalFeeMultiplier", - [ - 141u8, 130u8, 11u8, 35u8, 226u8, 114u8, 92u8, 179u8, 168u8, 110u8, - 28u8, 91u8, 221u8, 64u8, 4u8, 148u8, 201u8, 193u8, 185u8, 66u8, 226u8, - 114u8, 97u8, 79u8, 62u8, 212u8, 202u8, 114u8, 237u8, 228u8, 183u8, - 165u8, - ], - ) - } - } - } - } - pub mod parachain_system { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetValidationData { - pub data: - runtime_types::cumulus_primitives_parachain_inherent::ParachainInherentData, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SudoSendUpwardMessage { - pub message: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct AuthorizeUpgrade { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct EnactAuthorizedUpgrade { - pub code: ::std::vec::Vec<::core::primitive::u8>, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Set the current validation data."] - #[doc = ""] - #[doc = "This should be invoked exactly once per block. It will panic at the finalization"] - #[doc = "phase if the call was not invoked."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be `Inherent`"] - #[doc = ""] - #[doc = "As a side effect, this function upgrades the current validation function"] - #[doc = "if the appropriate time has come."] - pub fn set_validation_data( - &self, - data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "ParachainSystem", - "set_validation_data", - SetValidationData { data }, - [ - 200u8, 80u8, 163u8, 177u8, 184u8, 117u8, 61u8, 203u8, 244u8, 214u8, - 106u8, 151u8, 128u8, 131u8, 254u8, 120u8, 254u8, 76u8, 104u8, 39u8, - 215u8, 227u8, 233u8, 254u8, 26u8, 62u8, 17u8, 42u8, 19u8, 127u8, 108u8, - 242u8, - ], - ) - } - pub fn sudo_send_upward_message( - &self, - message: ::std::vec::Vec<::core::primitive::u8>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "ParachainSystem", - "sudo_send_upward_message", - SudoSendUpwardMessage { message }, - [ - 127u8, 79u8, 45u8, 183u8, 190u8, 205u8, 184u8, 169u8, 255u8, 191u8, - 86u8, 154u8, 134u8, 25u8, 249u8, 63u8, 47u8, 194u8, 108u8, 62u8, 60u8, - 170u8, 81u8, 240u8, 113u8, 48u8, 181u8, 171u8, 95u8, 63u8, 26u8, 222u8, - ], - ) - } - #[doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] - #[doc = "later."] - #[doc = ""] - #[doc = "The `check_version` parameter sets a boolean flag for whether or not the runtime's spec"] - #[doc = "version and name should be verified on upgrade. Since the authorization only has a hash,"] - #[doc = "it cannot actually perform the verification."] - #[doc = ""] - #[doc = "This call requires Root origin."] - pub fn authorize_upgrade( - &self, - code_hash: ::subxt::utils::H256, - check_version: ::core::primitive::bool, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "ParachainSystem", - "authorize_upgrade", - AuthorizeUpgrade { code_hash, check_version }, - [ - 208u8, 115u8, 62u8, 35u8, 70u8, 223u8, 65u8, 57u8, 216u8, 44u8, 169u8, - 249u8, 90u8, 112u8, 17u8, 208u8, 30u8, 131u8, 102u8, 131u8, 240u8, - 217u8, 230u8, 214u8, 145u8, 198u8, 55u8, 13u8, 217u8, 51u8, 178u8, - 141u8, - ], - ) - } - #[doc = "Provide the preimage (runtime binary) `code` for an upgrade that has been authorized."] - #[doc = ""] - #[doc = "If the authorization required a version check, this call will ensure the spec name"] - #[doc = "remains unchanged and that the spec version has increased."] - #[doc = ""] - #[doc = "Note that this function will not apply the new `code`, but only attempt to schedule the"] - #[doc = "upgrade with the Relay Chain."] - #[doc = ""] - #[doc = "All origins are allowed."] - pub fn enact_authorized_upgrade( - &self, - code: ::std::vec::Vec<::core::primitive::u8>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "ParachainSystem", - "enact_authorized_upgrade", - EnactAuthorizedUpgrade { code }, - [ - 43u8, 157u8, 1u8, 230u8, 134u8, 72u8, 230u8, 35u8, 159u8, 13u8, 201u8, - 134u8, 184u8, 94u8, 167u8, 13u8, 108u8, 157u8, 145u8, 166u8, 119u8, - 37u8, 51u8, 121u8, 252u8, 255u8, 48u8, 251u8, 126u8, 152u8, 247u8, 5u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::cumulus_pallet_parachain_system::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "The validation function has been scheduled to apply."] - pub struct ValidationFunctionStored; - impl ::subxt::events::StaticEvent for ValidationFunctionStored { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "ValidationFunctionStored"; - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "The validation function was applied as of the contained relay chain block number."] - pub struct ValidationFunctionApplied { - pub relay_chain_block_num: ::core::primitive::u32, - } - impl ::subxt::events::StaticEvent for ValidationFunctionApplied { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "ValidationFunctionApplied"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "The relay-chain aborted the upgrade process."] - pub struct ValidationFunctionDiscarded; - impl ::subxt::events::StaticEvent for ValidationFunctionDiscarded { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "ValidationFunctionDiscarded"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An upgrade has been authorized."] - pub struct UpgradeAuthorized { - pub code_hash: ::subxt::utils::H256, - } - impl ::subxt::events::StaticEvent for UpgradeAuthorized { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "UpgradeAuthorized"; - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Some downward messages have been received and will be processed."] - pub struct DownwardMessagesReceived { - pub count: ::core::primitive::u32, - } - impl ::subxt::events::StaticEvent for DownwardMessagesReceived { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "DownwardMessagesReceived"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward messages were processed using the given weight."] - pub struct DownwardMessagesProcessed { - pub weight_used: ::sp_weights::Weight, - pub dmq_head: ::subxt::utils::H256, - } - impl ::subxt::events::StaticEvent for DownwardMessagesProcessed { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "DownwardMessagesProcessed"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An upward message was sent to the relay chain."] - pub struct UpwardMessageSent { - pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - } - impl ::subxt::events::StaticEvent for UpwardMessageSent { - const PALLET: &'static str = "ParachainSystem"; - const EVENT: &'static str = "UpwardMessageSent"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " In case of a scheduled upgrade, this storage field contains the validation code to be applied."] - #[doc = ""] - #[doc = " As soon as the relay chain gives us the go-ahead signal, we will overwrite the [`:code`][well_known_keys::CODE]"] - #[doc = " which will result the next block process with the new validation code. This concludes the upgrade process."] - #[doc = ""] - #[doc = " [well_known_keys::CODE]: sp_core::storage::well_known_keys::CODE"] - pub fn pending_validation_code( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "PendingValidationCode", - vec![], - [ - 162u8, 35u8, 108u8, 76u8, 160u8, 93u8, 215u8, 84u8, 20u8, 249u8, 57u8, - 187u8, 88u8, 161u8, 15u8, 131u8, 213u8, 89u8, 140u8, 20u8, 227u8, - 204u8, 79u8, 176u8, 114u8, 119u8, 8u8, 7u8, 64u8, 15u8, 90u8, 92u8, - ], - ) - } - #[doc = " Validation code that is set by the parachain and is to be communicated to collator and"] - #[doc = " consequently the relay-chain."] - #[doc = ""] - #[doc = " This will be cleared in `on_initialize` of each new block if no other pallet already set"] - #[doc = " the value."] - pub fn new_validation_code( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "NewValidationCode", - vec![], - [ - 224u8, 174u8, 53u8, 106u8, 240u8, 49u8, 48u8, 79u8, 219u8, 74u8, 142u8, - 166u8, 92u8, 204u8, 244u8, 200u8, 43u8, 169u8, 177u8, 207u8, 190u8, - 106u8, 180u8, 65u8, 245u8, 131u8, 134u8, 4u8, 53u8, 45u8, 76u8, 3u8, - ], - ) - } - #[doc = " The [`PersistedValidationData`] set for this block."] - #[doc = " This value is expected to be set only once per block and it's never stored"] - #[doc = " in the trie."] - pub fn validation_data( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::polkadot_primitives::v4::PersistedValidationData< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "ValidationData", - vec![], - [ - 112u8, 58u8, 240u8, 81u8, 219u8, 110u8, 244u8, 186u8, 251u8, 90u8, - 195u8, 217u8, 229u8, 102u8, 233u8, 24u8, 109u8, 96u8, 219u8, 72u8, - 139u8, 93u8, 58u8, 140u8, 40u8, 110u8, 167u8, 98u8, 199u8, 12u8, 138u8, - 131u8, - ], - ) - } - #[doc = " Were the validation data set to notify the relay chain?"] - pub fn did_set_validation_code( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "DidSetValidationCode", - vec![], - [ - 89u8, 83u8, 74u8, 174u8, 234u8, 188u8, 149u8, 78u8, 140u8, 17u8, 92u8, - 165u8, 243u8, 87u8, 59u8, 97u8, 135u8, 81u8, 192u8, 86u8, 193u8, 187u8, - 113u8, 22u8, 108u8, 83u8, 242u8, 208u8, 174u8, 40u8, 49u8, 245u8, - ], - ) - } - #[doc = " The relay chain block number associated with the last parachain block."] - pub fn last_relay_chain_block_number( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "LastRelayChainBlockNumber", - vec![], - [ - 68u8, 121u8, 6u8, 159u8, 181u8, 94u8, 151u8, 215u8, 225u8, 244u8, 4u8, - 158u8, 216u8, 85u8, 55u8, 228u8, 197u8, 35u8, 200u8, 33u8, 29u8, 182u8, - 17u8, 83u8, 59u8, 63u8, 25u8, 180u8, 132u8, 23u8, 97u8, 252u8, - ], - ) - } - #[doc = " An option which indicates if the relay-chain restricts signalling a validation code upgrade."] - #[doc = " In other words, if this is `Some` and [`NewValidationCode`] is `Some` then the produced"] - #[doc = " candidate will be invalid."] - #[doc = ""] - #[doc = " This storage item is a mirror of the corresponding value for the current parachain from the"] - #[doc = " relay-chain. This value is ephemeral which means it doesn't hit the storage. This value is"] - #[doc = " set after the inherent."] - pub fn upgrade_restriction_signal( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::core::option::Option< - runtime_types::polkadot_primitives::v4::UpgradeRestriction, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "UpgradeRestrictionSignal", - vec![], - [ - 61u8, 3u8, 26u8, 6u8, 88u8, 114u8, 109u8, 63u8, 7u8, 115u8, 245u8, - 198u8, 73u8, 234u8, 28u8, 228u8, 126u8, 27u8, 151u8, 18u8, 133u8, 54u8, - 144u8, 149u8, 246u8, 43u8, 83u8, 47u8, 77u8, 238u8, 10u8, 196u8, - ], - ) - } - #[doc = " The state proof for the last relay parent block."] - #[doc = ""] - #[doc = " This field is meant to be updated each block with the validation data inherent. Therefore,"] - #[doc = " before processing of the inherent, e.g. in `on_initialize` this data may be stale."] - #[doc = ""] - #[doc = " This data is also absent from the genesis."] - pub fn relay_state_proof( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::sp_trie::storage_proof::StorageProof, - >, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "RelayStateProof", - vec![], - [ - 35u8, 124u8, 167u8, 221u8, 162u8, 145u8, 158u8, 186u8, 57u8, 154u8, - 225u8, 6u8, 176u8, 13u8, 178u8, 195u8, 209u8, 122u8, 221u8, 26u8, - 155u8, 126u8, 153u8, 246u8, 101u8, 221u8, 61u8, 145u8, 211u8, 236u8, - 48u8, 130u8, - ], - ) - } - #[doc = " The snapshot of some state related to messaging relevant to the current parachain as per"] - #[doc = " the relay parent."] - #[doc = ""] - #[doc = " This field is meant to be updated each block with the validation data inherent. Therefore,"] - #[doc = " before processing of the inherent, e.g. in `on_initialize` this data may be stale."] - #[doc = ""] - #[doc = " This data is also absent from the genesis."] pub fn relevant_messaging_state (& self ,) -> :: subxt :: storage :: address :: StaticStorageAddress :: < :: subxt :: metadata :: DecodeStaticType < runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: MessagingStateSnapshot > , :: subxt :: storage :: address :: Yes , () , () >{ - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "RelevantMessagingState", - vec![], - [ - 68u8, 241u8, 114u8, 83u8, 200u8, 99u8, 8u8, 244u8, 110u8, 134u8, 106u8, - 153u8, 17u8, 90u8, 184u8, 157u8, 100u8, 140u8, 157u8, 83u8, 25u8, - 166u8, 173u8, 31u8, 221u8, 24u8, 236u8, 85u8, 176u8, 223u8, 237u8, - 65u8, - ], - ) - } - #[doc = " The parachain host configuration that was obtained from the relay parent."] - #[doc = ""] - #[doc = " This field is meant to be updated each block with the validation data inherent. Therefore,"] - #[doc = " before processing of the inherent, e.g. in `on_initialize` this data may be stale."] - #[doc = ""] - #[doc = " This data is also absent from the genesis."] - pub fn host_configuration( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::polkadot_primitives::v4::AbridgedHostConfiguration, - >, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "HostConfiguration", - vec![], - [ - 104u8, 200u8, 30u8, 202u8, 119u8, 204u8, 233u8, 20u8, 67u8, 199u8, - 47u8, 166u8, 254u8, 152u8, 10u8, 187u8, 240u8, 255u8, 148u8, 201u8, - 134u8, 41u8, 130u8, 201u8, 112u8, 65u8, 68u8, 103u8, 56u8, 123u8, - 178u8, 113u8, - ], - ) - } - #[doc = " The last downward message queue chain head we have observed."] - #[doc = ""] - #[doc = " This value is loaded before and saved after processing inbound downward messages carried"] - #[doc = " by the system inherent."] - pub fn last_dmq_mqc_head( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::cumulus_primitives_parachain_inherent::MessageQueueChain, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "LastDmqMqcHead", - vec![], - [ - 176u8, 255u8, 246u8, 125u8, 36u8, 120u8, 24u8, 44u8, 26u8, 64u8, 236u8, - 210u8, 189u8, 237u8, 50u8, 78u8, 45u8, 139u8, 58u8, 141u8, 112u8, - 253u8, 178u8, 198u8, 87u8, 71u8, 77u8, 248u8, 21u8, 145u8, 187u8, 52u8, - ], - ) - } - #[doc = " The message queue chain heads we have observed per each channel incoming channel."] - #[doc = ""] - #[doc = " This value is loaded before and saved after processing inbound downward messages carried"] - #[doc = " by the system inherent."] - pub fn last_hrmp_mqc_heads( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::cumulus_primitives_parachain_inherent::MessageQueueChain, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "LastHrmpMqcHeads", - vec![], - [ - 55u8, 179u8, 35u8, 16u8, 173u8, 0u8, 122u8, 179u8, 236u8, 98u8, 9u8, - 112u8, 11u8, 219u8, 241u8, 89u8, 131u8, 198u8, 64u8, 139u8, 103u8, - 158u8, 77u8, 107u8, 83u8, 236u8, 255u8, 208u8, 47u8, 61u8, 219u8, - 240u8, - ], - ) - } - #[doc = " Number of downward messages processed in a block."] - #[doc = ""] - #[doc = " This will be cleared in `on_initialize` of each new block."] - pub fn processed_downward_messages( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "ProcessedDownwardMessages", - vec![], - [ - 48u8, 177u8, 84u8, 228u8, 101u8, 235u8, 181u8, 27u8, 66u8, 55u8, 50u8, - 146u8, 245u8, 223u8, 77u8, 132u8, 178u8, 80u8, 74u8, 90u8, 166u8, 81u8, - 109u8, 25u8, 91u8, 69u8, 5u8, 69u8, 123u8, 197u8, 160u8, 146u8, - ], - ) - } - #[doc = " HRMP watermark that was set in a block."] - #[doc = ""] - #[doc = " This will be cleared in `on_initialize` of each new block."] - pub fn hrmp_watermark( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "HrmpWatermark", - vec![], - [ - 189u8, 59u8, 183u8, 195u8, 69u8, 185u8, 241u8, 226u8, 62u8, 204u8, - 230u8, 77u8, 102u8, 75u8, 86u8, 157u8, 249u8, 140u8, 219u8, 72u8, 94u8, - 64u8, 176u8, 72u8, 34u8, 205u8, 114u8, 103u8, 231u8, 233u8, 206u8, - 111u8, - ], - ) - } - #[doc = " HRMP messages that were sent in a block."] - #[doc = ""] - #[doc = " This will be cleared in `on_initialize` of each new block."] - pub fn hrmp_outbound_messages( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain::primitives::Id, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "HrmpOutboundMessages", - vec![], - [ - 74u8, 86u8, 173u8, 248u8, 90u8, 230u8, 71u8, 225u8, 127u8, 164u8, - 221u8, 62u8, 146u8, 13u8, 73u8, 9u8, 98u8, 168u8, 6u8, 14u8, 97u8, - 166u8, 45u8, 70u8, 62u8, 210u8, 9u8, 32u8, 83u8, 18u8, 4u8, 201u8, - ], - ) - } - #[doc = " Upward messages that were sent in a block."] - #[doc = ""] - #[doc = " This will be cleared in `on_initialize` of each new block."] - pub fn upward_messages( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "UpwardMessages", - vec![], - [ - 129u8, 208u8, 187u8, 36u8, 48u8, 108u8, 135u8, 56u8, 204u8, 60u8, - 100u8, 158u8, 113u8, 238u8, 46u8, 92u8, 228u8, 41u8, 178u8, 177u8, - 208u8, 195u8, 148u8, 149u8, 127u8, 21u8, 93u8, 92u8, 29u8, 115u8, 10u8, - 248u8, - ], - ) - } - #[doc = " Upward messages that are still pending and not yet send to the relay chain."] - pub fn pending_upward_messages( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "PendingUpwardMessages", - vec![], - [ - 223u8, 46u8, 224u8, 227u8, 222u8, 119u8, 225u8, 244u8, 59u8, 87u8, - 127u8, 19u8, 217u8, 237u8, 103u8, 61u8, 6u8, 210u8, 107u8, 201u8, - 117u8, 25u8, 85u8, 248u8, 36u8, 231u8, 28u8, 202u8, 41u8, 140u8, 208u8, - 254u8, - ], - ) - } - #[doc = " The number of HRMP messages we observed in `on_initialize` and thus used that number for"] - #[doc = " announcing the weight of `on_initialize` and `on_finalize`."] - pub fn announced_hrmp_messages_per_candidate( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "AnnouncedHrmpMessagesPerCandidate", - vec![], - [ - 132u8, 61u8, 162u8, 129u8, 251u8, 243u8, 20u8, 144u8, 162u8, 73u8, - 237u8, 51u8, 248u8, 41u8, 127u8, 171u8, 180u8, 79u8, 137u8, 23u8, 66u8, - 134u8, 106u8, 222u8, 182u8, 154u8, 0u8, 145u8, 184u8, 156u8, 36u8, - 97u8, - ], - ) - } - #[doc = " The weight we reserve at the beginning of the block for processing XCMP messages. This"] - #[doc = " overrides the amount set in the Config trait."] - pub fn reserved_xcmp_weight_override( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::sp_weights::Weight>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "ReservedXcmpWeightOverride", - vec![], - [ - 180u8, 90u8, 34u8, 178u8, 1u8, 242u8, 211u8, 97u8, 100u8, 34u8, 39u8, - 42u8, 142u8, 249u8, 236u8, 194u8, 244u8, 164u8, 96u8, 54u8, 98u8, 46u8, - 92u8, 196u8, 185u8, 51u8, 231u8, 234u8, 249u8, 143u8, 244u8, 64u8, - ], - ) - } - #[doc = " The weight we reserve at the beginning of the block for processing DMP messages. This"] - #[doc = " overrides the amount set in the Config trait."] - pub fn reserved_dmp_weight_override( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::sp_weights::Weight>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "ReservedDmpWeightOverride", - vec![], - [ - 90u8, 122u8, 168u8, 240u8, 95u8, 195u8, 160u8, 109u8, 175u8, 170u8, - 227u8, 44u8, 139u8, 176u8, 32u8, 161u8, 57u8, 233u8, 56u8, 55u8, 123u8, - 168u8, 174u8, 96u8, 159u8, 62u8, 186u8, 186u8, 17u8, 70u8, 57u8, 246u8, - ], - ) - } - #[doc = " The next authorized upgrade, if there is one."] - pub fn authorized_upgrade( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::cumulus_pallet_parachain_system::CodeUpgradeAuthorization, - >, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "AuthorizedUpgrade", - vec![], - [ - 12u8, 212u8, 71u8, 191u8, 89u8, 101u8, 195u8, 3u8, 23u8, 180u8, 233u8, - 52u8, 53u8, 133u8, 207u8, 94u8, 58u8, 43u8, 221u8, 236u8, 161u8, 41u8, - 30u8, 194u8, 125u8, 2u8, 118u8, 152u8, 197u8, 49u8, 34u8, 33u8, - ], - ) - } - #[doc = " A custom head data that should be returned as result of `validate_block`."] - #[doc = ""] - #[doc = " See [`Pallet::set_custom_validation_head_data`] for more information."] - pub fn custom_validation_head_data( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainSystem", - "CustomValidationHeadData", - vec![], - [ - 189u8, 150u8, 234u8, 128u8, 111u8, 27u8, 173u8, 92u8, 109u8, 4u8, 98u8, - 103u8, 158u8, 19u8, 16u8, 5u8, 107u8, 135u8, 126u8, 170u8, 62u8, 64u8, - 149u8, 80u8, 33u8, 17u8, 83u8, 22u8, 176u8, 118u8, 26u8, 223u8, - ], - ) - } - } - } - } - pub mod parachain_info { - use super::{root_mod, runtime_types}; - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - pub fn parachain_id( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::polkadot_parachain::primitives::Id, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "ParachainInfo", - "ParachainId", - vec![], - [ - 151u8, 191u8, 241u8, 118u8, 192u8, 47u8, 166u8, 151u8, 217u8, 240u8, - 165u8, 232u8, 51u8, 113u8, 243u8, 1u8, 89u8, 240u8, 11u8, 1u8, 77u8, - 104u8, 12u8, 56u8, 17u8, 135u8, 214u8, 19u8, 114u8, 135u8, 66u8, 76u8, - ], - ) - } - } - } - } - pub mod balances { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct TransferAllowDeath { - pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - pub value: ::core::primitive::u128, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetBalanceDeprecated { - pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - pub new_free: ::core::primitive::u128, - #[codec(compact)] - pub old_reserved: ::core::primitive::u128, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceTransfer { - pub source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - pub value: ::core::primitive::u128, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct TransferKeepAlive { - pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - pub value: ::core::primitive::u128, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct TransferAll { - pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pub keep_alive: ::core::primitive::bool, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceUnreserve { - pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pub amount: ::core::primitive::u128, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct UpgradeAccounts { - pub who: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Transfer { - pub dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - pub value: ::core::primitive::u128, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceSetBalance { - pub who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - pub new_free: ::core::primitive::u128, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Transfer some liquid free balance to another account."] - #[doc = ""] - #[doc = "`transfer_allow_death` will set the `FreeBalance` of the sender and receiver."] - #[doc = "If the sender's account is below the existential deposit as a result"] - #[doc = "of the transfer, the account will be reaped."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be `Signed` by the transactor."] - pub fn transfer_allow_death( - &self, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - value: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "transfer_allow_death", - TransferAllowDeath { dest, value }, - [ - 234u8, 130u8, 149u8, 36u8, 235u8, 112u8, 159u8, 189u8, 104u8, 148u8, - 108u8, 230u8, 25u8, 198u8, 71u8, 158u8, 112u8, 3u8, 162u8, 25u8, 145u8, - 252u8, 44u8, 63u8, 47u8, 34u8, 47u8, 158u8, 61u8, 14u8, 120u8, 255u8, - ], - ) - } - #[doc = "Set the regular balance of a given account; it also takes a reserved balance but this"] - #[doc = "must be the same as the account's current reserved balance."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] - #[doc = ""] - #[doc = "WARNING: This call is DEPRECATED! Use `force_set_balance` instead."] - pub fn set_balance_deprecated( - &self, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - new_free: ::core::primitive::u128, - old_reserved: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "set_balance_deprecated", - SetBalanceDeprecated { who, new_free, old_reserved }, - [ - 240u8, 107u8, 184u8, 206u8, 78u8, 106u8, 115u8, 152u8, 130u8, 56u8, - 156u8, 176u8, 105u8, 27u8, 176u8, 187u8, 49u8, 171u8, 229u8, 79u8, - 254u8, 248u8, 8u8, 162u8, 134u8, 12u8, 89u8, 100u8, 137u8, 102u8, - 132u8, 158u8, - ], - ) - } - #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] - #[doc = "may be specified."] - pub fn force_transfer( - &self, - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - value: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "force_transfer", - ForceTransfer { source, dest, value }, - [ - 79u8, 174u8, 212u8, 108u8, 184u8, 33u8, 170u8, 29u8, 232u8, 254u8, - 195u8, 218u8, 221u8, 134u8, 57u8, 99u8, 6u8, 70u8, 181u8, 227u8, 56u8, - 239u8, 243u8, 158u8, 157u8, 245u8, 36u8, 162u8, 11u8, 237u8, 147u8, - 15u8, - ], - ) - } - #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] - #[doc = "kill the origin account."] - #[doc = ""] - #[doc = "99% of the time you want [`transfer_allow_death`] instead."] - #[doc = ""] - #[doc = "[`transfer_allow_death`]: struct.Pallet.html#method.transfer"] - pub fn transfer_keep_alive( - &self, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - value: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "transfer_keep_alive", - TransferKeepAlive { dest, value }, - [ - 112u8, 179u8, 75u8, 168u8, 193u8, 221u8, 9u8, 82u8, 190u8, 113u8, - 253u8, 13u8, 130u8, 134u8, 170u8, 216u8, 136u8, 111u8, 242u8, 220u8, - 202u8, 112u8, 47u8, 79u8, 73u8, 244u8, 226u8, 59u8, 240u8, 188u8, - 210u8, 208u8, - ], - ) - } - #[doc = "Transfer the entire transferable balance from the caller account."] - #[doc = ""] - #[doc = "NOTE: This function only attempts to transfer _transferable_ balances. This means that"] - #[doc = "any locked, reserved, or existential deposits (when `keep_alive` is `true`), will not be"] - #[doc = "transferred by this function. To ensure that this function results in a killed account,"] - #[doc = "you might need to prepare the account by removing any reference counters, storage"] - #[doc = "deposits, etc..."] - #[doc = ""] - #[doc = "The dispatch origin of this call must be Signed."] - #[doc = ""] - #[doc = "- `dest`: The recipient of the transfer."] - #[doc = "- `keep_alive`: A boolean to determine if the `transfer_all` operation should send all"] - #[doc = " of the funds the account has, causing the sender account to be killed (false), or"] - #[doc = " transfer everything except at least the existential deposit, which will guarantee to"] - #[doc = " keep the sender account alive (true)."] - pub fn transfer_all( - &self, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "transfer_all", - TransferAll { dest, keep_alive }, - [ - 46u8, 129u8, 29u8, 177u8, 221u8, 107u8, 245u8, 69u8, 238u8, 126u8, - 145u8, 26u8, 219u8, 208u8, 14u8, 80u8, 149u8, 1u8, 214u8, 63u8, 67u8, - 201u8, 144u8, 45u8, 129u8, 145u8, 174u8, 71u8, 238u8, 113u8, 208u8, - 34u8, - ], - ) - } - #[doc = "Unreserve some balance from a user by force."] - #[doc = ""] - #[doc = "Can only be called by ROOT."] - pub fn force_unreserve( - &self, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "force_unreserve", - ForceUnreserve { who, amount }, - [ - 160u8, 146u8, 137u8, 76u8, 157u8, 187u8, 66u8, 148u8, 207u8, 76u8, - 32u8, 254u8, 82u8, 215u8, 35u8, 161u8, 213u8, 52u8, 32u8, 98u8, 102u8, - 106u8, 234u8, 123u8, 6u8, 175u8, 184u8, 188u8, 174u8, 106u8, 176u8, - 78u8, - ], - ) - } - #[doc = "Upgrade a specified account."] - #[doc = ""] - #[doc = "- `origin`: Must be `Signed`."] - #[doc = "- `who`: The account to be upgraded."] - #[doc = ""] - #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] - #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] - #[doc = "possibililty of churn)."] - pub fn upgrade_accounts( - &self, - who: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "upgrade_accounts", - UpgradeAccounts { who }, - [ - 164u8, 61u8, 119u8, 24u8, 165u8, 46u8, 197u8, 59u8, 39u8, 198u8, 228u8, - 96u8, 228u8, 45u8, 85u8, 51u8, 37u8, 5u8, 75u8, 40u8, 241u8, 163u8, - 86u8, 228u8, 151u8, 217u8, 47u8, 105u8, 203u8, 103u8, 207u8, 4u8, - ], - ) - } - #[doc = "Alias for `transfer_allow_death`, provided only for name-wise compatibility."] - #[doc = ""] - #[doc = "WARNING: DEPRECATED! Will be released in approximately 3 months."] - pub fn transfer( - &self, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - value: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "transfer", - Transfer { dest, value }, - [ - 111u8, 222u8, 32u8, 56u8, 171u8, 77u8, 252u8, 29u8, 194u8, 155u8, - 200u8, 192u8, 198u8, 81u8, 23u8, 115u8, 236u8, 91u8, 218u8, 114u8, - 107u8, 141u8, 138u8, 100u8, 237u8, 21u8, 58u8, 172u8, 3u8, 20u8, 216u8, - 38u8, - ], - ) - } - #[doc = "Set the regular balance of a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] - pub fn force_set_balance( - &self, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - new_free: ::core::primitive::u128, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "Balances", - "force_set_balance", - ForceSetBalance { who, new_free }, - [ - 237u8, 4u8, 41u8, 58u8, 62u8, 179u8, 160u8, 4u8, 50u8, 71u8, 178u8, - 36u8, 130u8, 130u8, 92u8, 229u8, 16u8, 245u8, 169u8, 109u8, 165u8, - 72u8, 94u8, 70u8, 196u8, 136u8, 37u8, 94u8, 140u8, 215u8, 125u8, 125u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_balances::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An account was created with some free balance."] - pub struct Endowed { - pub account: ::sp_core::crypto::AccountId32, - pub free_balance: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Endowed { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Endowed"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An account was removed whose balance was non-zero but below ExistentialDeposit,"] - #[doc = "resulting in an outright loss."] - pub struct DustLost { - pub account: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for DustLost { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "DustLost"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Transfer succeeded."] - pub struct Transfer { - pub from: ::sp_core::crypto::AccountId32, - pub to: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Transfer { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Transfer"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A balance was set by root."] - pub struct BalanceSet { - pub who: ::sp_core::crypto::AccountId32, - pub free: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for BalanceSet { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "BalanceSet"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some balance was reserved (moved from free to reserved)."] - pub struct Reserved { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Reserved { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Reserved"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some balance was unreserved (moved from reserved to free)."] - pub struct Unreserved { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Unreserved { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Unreserved"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some balance was moved from the reserve of the first account to the second account."] - #[doc = "Final argument indicates the destination balance type."] - pub struct ReserveRepatriated { - pub from: ::sp_core::crypto::AccountId32, - pub to: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - pub destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - } - impl ::subxt::events::StaticEvent for ReserveRepatriated { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "ReserveRepatriated"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was deposited (e.g. for transaction fees)."] - pub struct Deposit { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Deposit { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Deposit"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was withdrawn from the account (e.g. for transaction fees)."] - pub struct Withdraw { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Withdraw { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Withdraw"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was removed from the account (e.g. for misbehavior)."] - pub struct Slashed { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Slashed { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Slashed"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was minted into an account."] - pub struct Minted { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Minted { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Minted"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was burned from an account."] - pub struct Burned { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Burned { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Burned"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was suspended from an account (it can be restored later)."] - pub struct Suspended { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Suspended { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Suspended"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some amount was restored into an account."] - pub struct Restored { - pub who: ::sp_core::crypto::AccountId32, - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Restored { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Restored"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An account was upgraded."] - pub struct Upgraded { - pub who: ::sp_core::crypto::AccountId32, - } - impl ::subxt::events::StaticEvent for Upgraded { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Upgraded"; - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Total issuance was increased by `amount`, creating a credit to be balanced."] - pub struct Issued { - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Issued { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Issued"; - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Total issuance was decreased by `amount`, creating a debt to be balanced."] - pub struct Rescinded { - pub amount: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for Rescinded { - const PALLET: &'static str = "Balances"; - const EVENT: &'static str = "Rescinded"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " The total units issued in the system."] - pub fn total_issuance( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "TotalIssuance", - vec![], - [ - 1u8, 206u8, 252u8, 237u8, 6u8, 30u8, 20u8, 232u8, 164u8, 115u8, 51u8, - 156u8, 156u8, 206u8, 241u8, 187u8, 44u8, 84u8, 25u8, 164u8, 235u8, - 20u8, 86u8, 242u8, 124u8, 23u8, 28u8, 140u8, 26u8, 73u8, 231u8, 51u8, - ], - ) - } - #[doc = " The total units of outstanding deactivated balance in the system."] - pub fn inactive_issuance( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "InactiveIssuance", - vec![], - [ - 74u8, 203u8, 111u8, 142u8, 225u8, 104u8, 173u8, 51u8, 226u8, 12u8, - 85u8, 135u8, 41u8, 206u8, 177u8, 238u8, 94u8, 246u8, 184u8, 250u8, - 140u8, 213u8, 91u8, 118u8, 163u8, 111u8, 211u8, 46u8, 204u8, 160u8, - 154u8, 21u8, - ], - ) - } - #[doc = " The Balances pallet example of storing the balance of an account."] - #[doc = ""] - #[doc = " # Example"] - #[doc = ""] - #[doc = " ```nocompile"] - #[doc = " impl pallet_balances::Config for Runtime {"] - #[doc = " type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData>"] - #[doc = " }"] - #[doc = " ```"] - #[doc = ""] - #[doc = " You can also store the balance of an account in the `System` pallet."] - #[doc = ""] - #[doc = " # Example"] - #[doc = ""] - #[doc = " ```nocompile"] - #[doc = " impl pallet_balances::Config for Runtime {"] - #[doc = " type AccountStore = System"] - #[doc = " }"] - #[doc = " ```"] - #[doc = ""] - #[doc = " But this comes with tradeoffs, storing account balances in the system pallet stores"] - #[doc = " `frame_system` data alongside the account data contrary to storing account balances in the"] - #[doc = " `Balances` pallet, which uses a `StorageMap` to store balances data only."] - #[doc = " NOTE: This is only used in the case that this pallet is used to store balances."] - pub fn account( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::pallet_balances::types::AccountData<::core::primitive::u128>, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Account", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 109u8, 250u8, 18u8, 96u8, 139u8, 232u8, 4u8, 139u8, 133u8, 239u8, 30u8, - 237u8, 73u8, 209u8, 143u8, 160u8, 94u8, 248u8, 124u8, 43u8, 224u8, - 165u8, 11u8, 6u8, 176u8, 144u8, 189u8, 161u8, 174u8, 210u8, 56u8, - 225u8, - ], - ) - } - #[doc = " The Balances pallet example of storing the balance of an account."] - #[doc = ""] - #[doc = " # Example"] - #[doc = ""] - #[doc = " ```nocompile"] - #[doc = " impl pallet_balances::Config for Runtime {"] - #[doc = " type AccountStore = StorageMapShim, frame_system::Provider, AccountId, Self::AccountData>"] - #[doc = " }"] - #[doc = " ```"] - #[doc = ""] - #[doc = " You can also store the balance of an account in the `System` pallet."] - #[doc = ""] - #[doc = " # Example"] - #[doc = ""] - #[doc = " ```nocompile"] - #[doc = " impl pallet_balances::Config for Runtime {"] - #[doc = " type AccountStore = System"] - #[doc = " }"] - #[doc = " ```"] - #[doc = ""] - #[doc = " But this comes with tradeoffs, storing account balances in the system pallet stores"] - #[doc = " `frame_system` data alongside the account data contrary to storing account balances in the"] - #[doc = " `Balances` pallet, which uses a `StorageMap` to store balances data only."] - #[doc = " NOTE: This is only used in the case that this pallet is used to store balances."] - pub fn account_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::pallet_balances::types::AccountData<::core::primitive::u128>, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Account", - Vec::new(), - [ - 109u8, 250u8, 18u8, 96u8, 139u8, 232u8, 4u8, 139u8, 133u8, 239u8, 30u8, - 237u8, 73u8, 209u8, 143u8, 160u8, 94u8, 248u8, 124u8, 43u8, 224u8, - 165u8, 11u8, 6u8, 176u8, 144u8, 189u8, 161u8, 174u8, 210u8, 56u8, - 225u8, - ], - ) - } - #[doc = " Any liquidity locks on some account balances."] - #[doc = " NOTE: Should only be accessed when setting, changing and freeing a lock."] - pub fn locks( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - runtime_types::pallet_balances::types::BalanceLock< - ::core::primitive::u128, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Locks", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 216u8, 253u8, 87u8, 73u8, 24u8, 218u8, 35u8, 0u8, 244u8, 134u8, 195u8, - 58u8, 255u8, 64u8, 153u8, 212u8, 210u8, 232u8, 4u8, 122u8, 90u8, 212u8, - 136u8, 14u8, 127u8, 232u8, 8u8, 192u8, 40u8, 233u8, 18u8, 250u8, - ], - ) - } - #[doc = " Any liquidity locks on some account balances."] - #[doc = " NOTE: Should only be accessed when setting, changing and freeing a lock."] - pub fn locks_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - runtime_types::pallet_balances::types::BalanceLock< - ::core::primitive::u128, - >, - >, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Locks", - Vec::new(), - [ - 216u8, 253u8, 87u8, 73u8, 24u8, 218u8, 35u8, 0u8, 244u8, 134u8, 195u8, - 58u8, 255u8, 64u8, 153u8, 212u8, 210u8, 232u8, 4u8, 122u8, 90u8, 212u8, - 136u8, 14u8, 127u8, 232u8, 8u8, 192u8, 40u8, 233u8, 18u8, 250u8, - ], - ) - } - #[doc = " Named reserves on some account balances."] - pub fn reserves( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_balances::types::ReserveData< - [::core::primitive::u8; 8usize], - ::core::primitive::u128, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Reserves", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 17u8, 32u8, 191u8, 46u8, 76u8, 220u8, 101u8, 100u8, 42u8, 250u8, 128u8, - 167u8, 117u8, 44u8, 85u8, 96u8, 105u8, 216u8, 16u8, 147u8, 74u8, 55u8, - 183u8, 94u8, 160u8, 177u8, 26u8, 187u8, 71u8, 197u8, 187u8, 163u8, - ], - ) - } - #[doc = " Named reserves on some account balances."] - pub fn reserves_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_balances::types::ReserveData< - [::core::primitive::u8; 8usize], - ::core::primitive::u128, - >, - >, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Reserves", - Vec::new(), - [ - 17u8, 32u8, 191u8, 46u8, 76u8, 220u8, 101u8, 100u8, 42u8, 250u8, 128u8, - 167u8, 117u8, 44u8, 85u8, 96u8, 105u8, 216u8, 16u8, 147u8, 74u8, 55u8, - 183u8, 94u8, 160u8, 177u8, 26u8, 187u8, 71u8, 197u8, 187u8, 163u8, - ], - ) - } - #[doc = " Holds on account balances."] - pub fn holds( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_balances::types::IdAmount< - (), - ::core::primitive::u128, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Holds", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 247u8, 81u8, 4u8, 220u8, 77u8, 205u8, 28u8, 131u8, 215u8, 74u8, 197u8, - 137u8, 113u8, 214u8, 249u8, 91u8, 81u8, 216u8, 8u8, 5u8, 233u8, 39u8, - 104u8, 250u8, 3u8, 228u8, 148u8, 78u8, 4u8, 34u8, 45u8, 143u8, - ], - ) - } - #[doc = " Holds on account balances."] - pub fn holds_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_balances::types::IdAmount< - (), - ::core::primitive::u128, - >, - >, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Holds", - Vec::new(), - [ - 247u8, 81u8, 4u8, 220u8, 77u8, 205u8, 28u8, 131u8, 215u8, 74u8, 197u8, - 137u8, 113u8, 214u8, 249u8, 91u8, 81u8, 216u8, 8u8, 5u8, 233u8, 39u8, - 104u8, 250u8, 3u8, 228u8, 148u8, 78u8, 4u8, 34u8, 45u8, 143u8, - ], - ) - } - #[doc = " Freeze locks on account balances."] - pub fn freezes( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_balances::types::IdAmount< - (), - ::core::primitive::u128, - >, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Freezes", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 211u8, 24u8, 237u8, 217u8, 47u8, 230u8, 147u8, 39u8, 112u8, 209u8, - 193u8, 47u8, 242u8, 13u8, 241u8, 0u8, 100u8, 45u8, 116u8, 130u8, 246u8, - 196u8, 50u8, 134u8, 135u8, 112u8, 206u8, 1u8, 12u8, 53u8, 106u8, 131u8, - ], - ) - } - #[doc = " Freeze locks on account balances."] - pub fn freezes_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_balances::types::IdAmount< - (), - ::core::primitive::u128, - >, - >, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "Balances", - "Freezes", - Vec::new(), - [ - 211u8, 24u8, 237u8, 217u8, 47u8, 230u8, 147u8, 39u8, 112u8, 209u8, - 193u8, 47u8, 242u8, 13u8, 241u8, 0u8, 100u8, 45u8, 116u8, 130u8, 246u8, - 196u8, 50u8, 134u8, 135u8, 112u8, 206u8, 1u8, 12u8, 53u8, 106u8, 131u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " The minimum amount required to keep an account open."] - pub fn existential_deposit( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, - > { - ::subxt::constants::StaticConstantAddress::new( - "Balances", - "ExistentialDeposit", - [ - 84u8, 157u8, 140u8, 4u8, 93u8, 57u8, 29u8, 133u8, 105u8, 200u8, 214u8, - 27u8, 144u8, 208u8, 218u8, 160u8, 130u8, 109u8, 101u8, 54u8, 210u8, - 136u8, 71u8, 63u8, 49u8, 237u8, 234u8, 15u8, 178u8, 98u8, 148u8, 156u8, - ], - ) - } - #[doc = " The maximum number of locks that should exist on an account."] - #[doc = " Not strictly enforced, but used for weight estimation."] - pub fn max_locks( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "Balances", - "MaxLocks", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - #[doc = " The maximum number of named reserves that can exist on an account."] - pub fn max_reserves( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "Balances", - "MaxReserves", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - #[doc = " The maximum number of holds that can exist on an account at any time."] - pub fn max_holds( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "Balances", - "MaxHolds", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - #[doc = " The maximum number of individual freeze locks that can exist on an account at any time."] - pub fn max_freezes( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "Balances", - "MaxFreezes", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - } - } - } - pub mod aura { - use super::{root_mod, runtime_types}; - } - pub mod aura_ext { - use super::{root_mod, runtime_types}; - } - pub mod xcmp_queue { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ServiceOverweight { - pub index: ::core::primitive::u64, - pub weight_limit: ::sp_weights::Weight, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SuspendXcmExecution; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ResumeXcmExecution; - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - pub struct UpdateSuspendThreshold { - pub new: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - pub struct UpdateDropThreshold { - pub new: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - pub struct UpdateResumeThreshold { - pub new: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct UpdateThresholdWeight { - pub new: ::sp_weights::Weight, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct UpdateWeightRestrictDecay { - pub new: ::sp_weights::Weight, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct UpdateXcmpMaxIndividualWeight { - pub new: ::sp_weights::Weight, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Services a single overweight XCM."] - #[doc = ""] - #[doc = "- `origin`: Must pass `ExecuteOverweightOrigin`."] - #[doc = "- `index`: The index of the overweight XCM to service"] - #[doc = "- `weight_limit`: The amount of weight that XCM execution may take."] - #[doc = ""] - #[doc = "Errors:"] - #[doc = "- `BadOverweightIndex`: XCM under `index` is not found in the `Overweight` storage map."] - #[doc = "- `BadXcm`: XCM under `index` cannot be properly decoded into a valid XCM format."] - #[doc = "- `WeightOverLimit`: XCM execution may use greater `weight_limit`."] - #[doc = ""] - #[doc = "Events:"] - #[doc = "- `OverweightServiced`: On success."] - pub fn service_overweight( - &self, - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "service_overweight", - ServiceOverweight { index, weight_limit }, - [ - 121u8, 236u8, 235u8, 23u8, 210u8, 238u8, 238u8, 122u8, 15u8, 86u8, - 34u8, 119u8, 105u8, 100u8, 214u8, 236u8, 117u8, 39u8, 254u8, 235u8, - 189u8, 15u8, 72u8, 74u8, 225u8, 134u8, 148u8, 126u8, 31u8, 203u8, - 144u8, 106u8, - ], - ) - } - #[doc = "Suspends all XCM executions for the XCMP queue, regardless of the sender's origin."] - #[doc = ""] - #[doc = "- `origin`: Must pass `ControllerOrigin`."] - pub fn suspend_xcm_execution( - &self, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "suspend_xcm_execution", - SuspendXcmExecution {}, - [ - 139u8, 76u8, 166u8, 86u8, 106u8, 144u8, 16u8, 47u8, 105u8, 185u8, 7u8, - 7u8, 63u8, 14u8, 250u8, 236u8, 99u8, 121u8, 101u8, 143u8, 28u8, 175u8, - 108u8, 197u8, 226u8, 43u8, 103u8, 92u8, 186u8, 12u8, 51u8, 153u8, - ], - ) - } - #[doc = "Resumes all XCM executions for the XCMP queue."] - #[doc = ""] - #[doc = "Note that this function doesn't change the status of the in/out bound channels."] - #[doc = ""] - #[doc = "- `origin`: Must pass `ControllerOrigin`."] - pub fn resume_xcm_execution( - &self, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "resume_xcm_execution", - ResumeXcmExecution {}, - [ - 67u8, 111u8, 47u8, 237u8, 79u8, 42u8, 90u8, 56u8, 245u8, 2u8, 20u8, - 23u8, 33u8, 121u8, 135u8, 50u8, 204u8, 147u8, 195u8, 80u8, 177u8, - 202u8, 8u8, 160u8, 164u8, 138u8, 64u8, 252u8, 178u8, 63u8, 102u8, - 245u8, - ], - ) - } - #[doc = "Overwrites the number of pages of messages which must be in the queue for the other side to be told to"] - #[doc = "suspend their sending."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.suspend_value`"] - pub fn update_suspend_threshold( - &self, - new: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "update_suspend_threshold", - UpdateSuspendThreshold { new }, - [ - 155u8, 120u8, 9u8, 228u8, 110u8, 62u8, 233u8, 36u8, 57u8, 85u8, 19u8, - 67u8, 246u8, 88u8, 81u8, 116u8, 243u8, 236u8, 174u8, 130u8, 8u8, 246u8, - 254u8, 97u8, 155u8, 207u8, 123u8, 60u8, 164u8, 14u8, 196u8, 97u8, - ], - ) - } - #[doc = "Overwrites the number of pages of messages which must be in the queue after which we drop any further"] - #[doc = "messages from the channel."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.drop_threshold`"] - pub fn update_drop_threshold( - &self, - new: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "update_drop_threshold", - UpdateDropThreshold { new }, - [ - 146u8, 177u8, 164u8, 96u8, 247u8, 182u8, 229u8, 175u8, 194u8, 101u8, - 186u8, 168u8, 94u8, 114u8, 172u8, 119u8, 35u8, 222u8, 175u8, 21u8, - 67u8, 61u8, 216u8, 144u8, 194u8, 10u8, 181u8, 62u8, 166u8, 198u8, - 138u8, 243u8, - ], - ) - } - #[doc = "Overwrites the number of pages of messages which the queue must be reduced to before it signals that"] - #[doc = "message sending may recommence after it has been suspended."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.resume_threshold`"] - pub fn update_resume_threshold( - &self, - new: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "update_resume_threshold", - UpdateResumeThreshold { new }, - [ - 231u8, 128u8, 80u8, 179u8, 61u8, 50u8, 103u8, 209u8, 103u8, 55u8, - 101u8, 113u8, 150u8, 10u8, 202u8, 7u8, 0u8, 77u8, 58u8, 4u8, 227u8, - 17u8, 225u8, 112u8, 121u8, 203u8, 184u8, 113u8, 231u8, 156u8, 174u8, - 154u8, - ], - ) - } - #[doc = "Overwrites the amount of remaining weight under which we stop processing messages."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.threshold_weight`"] - pub fn update_threshold_weight( - &self, - new: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "update_threshold_weight", - UpdateThresholdWeight { new }, - [ - 14u8, 144u8, 112u8, 207u8, 195u8, 208u8, 184u8, 164u8, 94u8, 41u8, 8u8, - 58u8, 180u8, 80u8, 239u8, 39u8, 210u8, 159u8, 114u8, 169u8, 152u8, - 176u8, 26u8, 161u8, 32u8, 43u8, 250u8, 156u8, 56u8, 21u8, 43u8, 159u8, - ], - ) - } - #[doc = "Overwrites the speed to which the available weight approaches the maximum weight."] - #[doc = "A lower number results in a faster progression. A value of 1 makes the entire weight available initially."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.weight_restrict_decay`."] - pub fn update_weight_restrict_decay( - &self, - new: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "update_weight_restrict_decay", - UpdateWeightRestrictDecay { new }, - [ - 42u8, 53u8, 83u8, 191u8, 51u8, 227u8, 210u8, 193u8, 142u8, 218u8, - 244u8, 177u8, 19u8, 87u8, 148u8, 177u8, 231u8, 197u8, 196u8, 255u8, - 41u8, 130u8, 245u8, 139u8, 107u8, 212u8, 90u8, 161u8, 82u8, 248u8, - 160u8, 223u8, - ], - ) - } - #[doc = "Overwrite the maximum amount of weight any individual message may consume."] - #[doc = "Messages above this weight go into the overweight queue and may only be serviced explicitly."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.xcmp_max_individual_weight`."] - pub fn update_xcmp_max_individual_weight( - &self, - new: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "XcmpQueue", - "update_xcmp_max_individual_weight", - UpdateXcmpMaxIndividualWeight { new }, - [ - 148u8, 185u8, 89u8, 36u8, 152u8, 220u8, 248u8, 233u8, 236u8, 82u8, - 170u8, 111u8, 225u8, 142u8, 25u8, 211u8, 72u8, 248u8, 250u8, 14u8, - 45u8, 72u8, 78u8, 95u8, 92u8, 196u8, 245u8, 104u8, 112u8, 128u8, 27u8, - 109u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::cumulus_pallet_xcmp_queue::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some XCM was executed ok."] - pub struct Success { - pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - pub weight: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for Success { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "Success"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some XCM failed."] - pub struct Fail { - pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - pub error: runtime_types::xcm::v3::traits::Error, - pub weight: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for Fail { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "Fail"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Bad XCM version used."] - pub struct BadVersion { - pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - } - impl ::subxt::events::StaticEvent for BadVersion { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "BadVersion"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Bad XCM format used."] - pub struct BadFormat { - pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - } - impl ::subxt::events::StaticEvent for BadFormat { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "BadFormat"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An HRMP message was sent to a sibling parachain."] - pub struct XcmpMessageSent { - pub message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - } - impl ::subxt::events::StaticEvent for XcmpMessageSent { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "XcmpMessageSent"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An XCM exceeded the individual message weight budget."] - pub struct OverweightEnqueued { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub sent_at: ::core::primitive::u32, - pub index: ::core::primitive::u64, - pub required: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for OverweightEnqueued { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "OverweightEnqueued"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An XCM from the overweight queue was executed with the given actual weight used."] - pub struct OverweightServiced { - pub index: ::core::primitive::u64, - pub used: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for OverweightServiced { - const PALLET: &'static str = "XcmpQueue"; - const EVENT: &'static str = "OverweightServiced"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " Status of the inbound XCMP channels."] - pub fn inbound_xcmp_status( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec< - runtime_types::cumulus_pallet_xcmp_queue::InboundChannelDetails, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "InboundXcmpStatus", - vec![], - [ - 183u8, 198u8, 237u8, 153u8, 132u8, 201u8, 87u8, 182u8, 121u8, 164u8, - 129u8, 241u8, 58u8, 192u8, 115u8, 152u8, 7u8, 33u8, 95u8, 51u8, 2u8, - 176u8, 144u8, 12u8, 125u8, 83u8, 92u8, 198u8, 211u8, 101u8, 28u8, 50u8, - ], - ) - } - #[doc = " Inbound aggregate XCMP messages. It can only be one per ParaId/block."] - pub fn inbound_xcmp_messages( - &self, - _0: impl ::std::borrow::Borrow, - _1: impl ::std::borrow::Borrow<::core::primitive::u32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "InboundXcmpMessages", - vec![ - ::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - ), - ::subxt::storage::address::StorageMapKey::new( - _1.borrow(), - ::subxt::storage::address::StorageHasher::Twox64Concat, - ), - ], - [ - 157u8, 232u8, 222u8, 97u8, 218u8, 96u8, 96u8, 90u8, 216u8, 205u8, 39u8, - 130u8, 109u8, 152u8, 127u8, 57u8, 54u8, 63u8, 104u8, 135u8, 33u8, - 175u8, 197u8, 166u8, 238u8, 22u8, 137u8, 162u8, 226u8, 199u8, 87u8, - 25u8, - ], - ) - } - #[doc = " Inbound aggregate XCMP messages. It can only be one per ParaId/block."] - pub fn inbound_xcmp_messages_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "InboundXcmpMessages", - Vec::new(), - [ - 157u8, 232u8, 222u8, 97u8, 218u8, 96u8, 96u8, 90u8, 216u8, 205u8, 39u8, - 130u8, 109u8, 152u8, 127u8, 57u8, 54u8, 63u8, 104u8, 135u8, 33u8, - 175u8, 197u8, 166u8, 238u8, 22u8, 137u8, 162u8, 226u8, 199u8, 87u8, - 25u8, - ], - ) - } - #[doc = " The non-empty XCMP channels in order of becoming non-empty, and the index of the first"] - #[doc = " and last outbound message. If the two indices are equal, then it indicates an empty"] - #[doc = " queue and there must be a non-`Ok` `OutboundStatus`. We assume queues grow no greater"] - #[doc = " than 65535 items. Queue indices for normal messages begin at one; zero is reserved in"] - #[doc = " case of the need to send a high-priority signal message this block."] - #[doc = " The bool is true if there is a signal message waiting to be sent."] - pub fn outbound_xcmp_status( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec< - runtime_types::cumulus_pallet_xcmp_queue::OutboundChannelDetails, - >, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "OutboundXcmpStatus", - vec![], - [ - 238u8, 120u8, 185u8, 141u8, 82u8, 159u8, 41u8, 68u8, 204u8, 15u8, 46u8, - 152u8, 144u8, 74u8, 250u8, 83u8, 71u8, 105u8, 54u8, 53u8, 226u8, 87u8, - 14u8, 202u8, 58u8, 160u8, 54u8, 162u8, 239u8, 248u8, 227u8, 116u8, - ], - ) - } - #[doc = " The messages outbound in a given XCMP channel."] - pub fn outbound_xcmp_messages( - &self, - _0: impl ::std::borrow::Borrow, - _1: impl ::std::borrow::Borrow<::core::primitive::u16>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "OutboundXcmpMessages", - vec![ - ::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - ), - ::subxt::storage::address::StorageMapKey::new( - _1.borrow(), - ::subxt::storage::address::StorageHasher::Twox64Concat, - ), - ], - [ - 50u8, 182u8, 237u8, 191u8, 106u8, 67u8, 54u8, 1u8, 17u8, 107u8, 70u8, - 90u8, 202u8, 8u8, 63u8, 184u8, 171u8, 111u8, 192u8, 196u8, 7u8, 31u8, - 186u8, 68u8, 31u8, 63u8, 71u8, 61u8, 83u8, 223u8, 79u8, 200u8, - ], - ) - } - #[doc = " The messages outbound in a given XCMP channel."] - pub fn outbound_xcmp_messages_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "OutboundXcmpMessages", - Vec::new(), - [ - 50u8, 182u8, 237u8, 191u8, 106u8, 67u8, 54u8, 1u8, 17u8, 107u8, 70u8, - 90u8, 202u8, 8u8, 63u8, 184u8, 171u8, 111u8, 192u8, 196u8, 7u8, 31u8, - 186u8, 68u8, 31u8, 63u8, 71u8, 61u8, 83u8, 223u8, 79u8, 200u8, - ], - ) - } - #[doc = " Any signal messages waiting to be sent."] - pub fn signal_messages( - &self, - _0: impl ::std::borrow::Borrow, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "SignalMessages", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 156u8, 242u8, 186u8, 89u8, 177u8, 195u8, 90u8, 121u8, 94u8, 106u8, - 222u8, 78u8, 19u8, 162u8, 179u8, 96u8, 38u8, 113u8, 209u8, 148u8, 29u8, - 110u8, 106u8, 167u8, 162u8, 96u8, 221u8, 20u8, 33u8, 179u8, 168u8, - 142u8, - ], - ) - } - #[doc = " Any signal messages waiting to be sent."] - pub fn signal_messages_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::std::vec::Vec<::core::primitive::u8>>, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "SignalMessages", - Vec::new(), - [ - 156u8, 242u8, 186u8, 89u8, 177u8, 195u8, 90u8, 121u8, 94u8, 106u8, - 222u8, 78u8, 19u8, 162u8, 179u8, 96u8, 38u8, 113u8, 209u8, 148u8, 29u8, - 110u8, 106u8, 167u8, 162u8, 96u8, 221u8, 20u8, 33u8, 179u8, 168u8, - 142u8, - ], - ) - } - #[doc = " The configuration which controls the dynamics of the outbound queue."] - pub fn queue_config( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::cumulus_pallet_xcmp_queue::QueueConfigData, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "QueueConfig", - vec![], - [ - 154u8, 172u8, 227u8, 208u8, 130u8, 93u8, 173u8, 129u8, 33u8, 75u8, - 180u8, 100u8, 35u8, 154u8, 40u8, 188u8, 86u8, 53u8, 74u8, 118u8, 131u8, - 159u8, 240u8, 159u8, 185u8, 45u8, 165u8, 6u8, 90u8, 125u8, 77u8, 253u8, - ], - ) - } - #[doc = " The messages that exceeded max individual message weight budget."] - #[doc = ""] - #[doc = " These message stay in this storage map until they are manually dispatched via"] - #[doc = " `service_overweight`."] - pub fn overweight( - &self, - _0: impl ::std::borrow::Borrow<::core::primitive::u64>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<( - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::std::vec::Vec<::core::primitive::u8>, - )>, - ::subxt::storage::address::Yes, - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "Overweight", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Twox64Concat, - )], - [ - 222u8, 249u8, 232u8, 110u8, 117u8, 229u8, 165u8, 164u8, 219u8, 219u8, - 149u8, 204u8, 25u8, 78u8, 204u8, 116u8, 111u8, 114u8, 120u8, 222u8, - 56u8, 77u8, 122u8, 147u8, 108u8, 15u8, 94u8, 161u8, 212u8, 50u8, 7u8, - 7u8, - ], - ) - } - #[doc = " The messages that exceeded max individual message weight budget."] - #[doc = ""] - #[doc = " These message stay in this storage map until they are manually dispatched via"] - #[doc = " `service_overweight`."] - pub fn overweight_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<( - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::std::vec::Vec<::core::primitive::u8>, - )>, - (), - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "Overweight", - Vec::new(), - [ - 222u8, 249u8, 232u8, 110u8, 117u8, 229u8, 165u8, 164u8, 219u8, 219u8, - 149u8, 204u8, 25u8, 78u8, 204u8, 116u8, 111u8, 114u8, 120u8, 222u8, - 56u8, 77u8, 122u8, 147u8, 108u8, 15u8, 94u8, 161u8, 212u8, 50u8, 7u8, - 7u8, - ], - ) - } - #[doc = "Counter for the related counted storage map"] - pub fn counter_for_overweight( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "CounterForOverweight", - vec![], - [ - 148u8, 226u8, 248u8, 107u8, 165u8, 97u8, 218u8, 160u8, 127u8, 48u8, - 185u8, 251u8, 35u8, 137u8, 119u8, 251u8, 151u8, 167u8, 189u8, 66u8, - 80u8, 74u8, 134u8, 129u8, 222u8, 180u8, 51u8, 182u8, 50u8, 110u8, 10u8, - 43u8, - ], - ) - } - #[doc = " The number of overweight messages ever recorded in `Overweight`. Also doubles as the next"] - #[doc = " available free overweight index."] - pub fn overweight_count( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u64>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "OverweightCount", - vec![], - [ - 102u8, 180u8, 196u8, 148u8, 115u8, 62u8, 46u8, 238u8, 97u8, 116u8, - 117u8, 42u8, 14u8, 5u8, 72u8, 237u8, 230u8, 46u8, 150u8, 126u8, 89u8, - 64u8, 233u8, 166u8, 180u8, 137u8, 52u8, 233u8, 252u8, 255u8, 36u8, - 20u8, - ], - ) - } - #[doc = " Whether or not the XCMP queue is suspended from executing incoming XCMs or not."] - pub fn queue_suspended( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::bool>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "XcmpQueue", - "QueueSuspended", - vec![], - [ - 23u8, 37u8, 48u8, 112u8, 222u8, 17u8, 252u8, 65u8, 160u8, 217u8, 218u8, - 30u8, 2u8, 1u8, 204u8, 0u8, 251u8, 17u8, 138u8, 197u8, 164u8, 50u8, - 122u8, 0u8, 31u8, 238u8, 147u8, 213u8, 30u8, 132u8, 184u8, 215u8, - ], - ) - } - } - } - } - pub mod polkadot_xcm { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Send { - pub dest: ::std::boxed::Box, - pub message: ::std::boxed::Box, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct TeleportAssets { - pub dest: ::std::boxed::Box, - pub beneficiary: ::std::boxed::Box, - pub assets: ::std::boxed::Box, - pub fee_asset_item: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ReserveTransferAssets { - pub dest: ::std::boxed::Box, - pub beneficiary: ::std::boxed::Box, - pub assets: ::std::boxed::Box, - pub fee_asset_item: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Execute { - pub message: ::std::boxed::Box, - pub max_weight: ::sp_weights::Weight, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceXcmVersion { - pub location: - ::std::boxed::Box, - pub xcm_version: ::core::primitive::u32, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceDefaultXcmVersion { - pub maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceSubscribeVersionNotify { - pub location: ::std::boxed::Box, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ForceUnsubscribeVersionNotify { - pub location: ::std::boxed::Box, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct LimitedReserveTransferAssets { - pub dest: ::std::boxed::Box, - pub beneficiary: ::std::boxed::Box, - pub assets: ::std::boxed::Box, - pub fee_asset_item: ::core::primitive::u32, - pub weight_limit: runtime_types::xcm::v3::WeightLimit, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct LimitedTeleportAssets { - pub dest: ::std::boxed::Box, - pub beneficiary: ::std::boxed::Box, - pub assets: ::std::boxed::Box, - pub fee_asset_item: ::core::primitive::u32, - pub weight_limit: runtime_types::xcm::v3::WeightLimit, - } - pub struct TransactionApi; - impl TransactionApi { - pub fn send( - &self, - dest: runtime_types::xcm::VersionedMultiLocation, - message: runtime_types::xcm::VersionedXcm, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "send", - Send { - dest: ::std::boxed::Box::new(dest), - message: ::std::boxed::Box::new(message), - }, - [ - 246u8, 35u8, 227u8, 112u8, 223u8, 7u8, 44u8, 186u8, 60u8, 225u8, 153u8, - 249u8, 104u8, 51u8, 123u8, 227u8, 143u8, 65u8, 232u8, 209u8, 178u8, - 104u8, 70u8, 56u8, 230u8, 14u8, 75u8, 83u8, 250u8, 160u8, 9u8, 39u8, - ], - ) - } - #[doc = "Teleport some assets from the local chain to some destination chain."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] - #[doc = "with all fees taken as needed from the asset."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] - #[doc = " `dest` side. May not be empty."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] - pub fn teleport_assets( - &self, - dest: runtime_types::xcm::VersionedMultiLocation, - beneficiary: runtime_types::xcm::VersionedMultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - fee_asset_item: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "teleport_assets", - TeleportAssets { - dest: ::std::boxed::Box::new(dest), - beneficiary: ::std::boxed::Box::new(beneficiary), - assets: ::std::boxed::Box::new(assets), - fee_asset_item, - }, - [ - 187u8, 42u8, 2u8, 96u8, 105u8, 125u8, 74u8, 53u8, 2u8, 21u8, 31u8, - 160u8, 201u8, 197u8, 157u8, 190u8, 40u8, 145u8, 5u8, 99u8, 194u8, 41u8, - 114u8, 60u8, 165u8, 186u8, 15u8, 226u8, 85u8, 113u8, 159u8, 136u8, - ], - ) - } - #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] - #[doc = "chain and forward a notification XCM."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] - #[doc = "with all fees taken as needed from the asset."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] - #[doc = " `dest` side."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] - pub fn reserve_transfer_assets( - &self, - dest: runtime_types::xcm::VersionedMultiLocation, - beneficiary: runtime_types::xcm::VersionedMultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - fee_asset_item: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "reserve_transfer_assets", - ReserveTransferAssets { - dest: ::std::boxed::Box::new(dest), - beneficiary: ::std::boxed::Box::new(beneficiary), - assets: ::std::boxed::Box::new(assets), - fee_asset_item, - }, - [ - 249u8, 177u8, 76u8, 204u8, 186u8, 165u8, 16u8, 186u8, 129u8, 239u8, - 65u8, 252u8, 9u8, 132u8, 32u8, 164u8, 117u8, 177u8, 40u8, 21u8, 196u8, - 246u8, 147u8, 2u8, 95u8, 110u8, 68u8, 162u8, 148u8, 9u8, 59u8, 170u8, - ], - ) - } - #[doc = "Execute an XCM message from a local, signed, origin."] - #[doc = ""] - #[doc = "An event is deposited indicating whether `msg` could be executed completely or only"] - #[doc = "partially."] - #[doc = ""] - #[doc = "No more than `max_weight` will be used in its attempted execution. If this is less than the"] - #[doc = "maximum amount of weight that the message could take to be executed, then no execution"] - #[doc = "attempt will be made."] - #[doc = ""] - #[doc = "NOTE: A successful return to this does *not* imply that the `msg` was executed successfully"] - #[doc = "to completion; only that *some* of it was executed."] - pub fn execute( - &self, - message: runtime_types::xcm::VersionedXcm, - max_weight: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "execute", - Execute { message: ::std::boxed::Box::new(message), max_weight }, - [ - 102u8, 41u8, 146u8, 29u8, 241u8, 205u8, 95u8, 153u8, 228u8, 141u8, - 11u8, 228u8, 13u8, 44u8, 75u8, 204u8, 174u8, 35u8, 155u8, 104u8, 204u8, - 82u8, 239u8, 98u8, 249u8, 187u8, 193u8, 1u8, 122u8, 88u8, 162u8, 200u8, - ], - ) - } - #[doc = "Extoll that a particular destination can be communicated with through a particular"] - #[doc = "version of XCM."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `location`: The destination that is being described."] - #[doc = "- `xcm_version`: The latest version of XCM that `location` supports."] - pub fn force_xcm_version( - &self, - location: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm_version: ::core::primitive::u32, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "force_xcm_version", - ForceXcmVersion { location: ::std::boxed::Box::new(location), xcm_version }, - [ - 68u8, 48u8, 95u8, 61u8, 152u8, 95u8, 213u8, 126u8, 209u8, 176u8, 230u8, - 160u8, 164u8, 42u8, 128u8, 62u8, 175u8, 3u8, 161u8, 170u8, 20u8, 31u8, - 216u8, 122u8, 31u8, 77u8, 64u8, 182u8, 121u8, 41u8, 23u8, 80u8, - ], - ) - } - #[doc = "Set a safe XCM version (the version that XCM should be encoded with if the most recent"] - #[doc = "version a destination can accept is unknown)."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `maybe_xcm_version`: The default XCM encoding version, or `None` to disable."] - pub fn force_default_xcm_version( - &self, - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "force_default_xcm_version", - ForceDefaultXcmVersion { maybe_xcm_version }, - [ - 38u8, 36u8, 59u8, 231u8, 18u8, 79u8, 76u8, 9u8, 200u8, 125u8, 214u8, - 166u8, 37u8, 99u8, 111u8, 161u8, 135u8, 2u8, 133u8, 157u8, 165u8, 18u8, - 152u8, 81u8, 209u8, 255u8, 137u8, 237u8, 28u8, 126u8, 224u8, 141u8, - ], - ) - } - #[doc = "Ask a location to notify us regarding their XCM version and any changes to it."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `location`: The location to which we should subscribe for XCM version notifications."] - pub fn force_subscribe_version_notify( - &self, - location: runtime_types::xcm::VersionedMultiLocation, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "force_subscribe_version_notify", - ForceSubscribeVersionNotify { location: ::std::boxed::Box::new(location) }, - [ - 236u8, 37u8, 153u8, 26u8, 174u8, 187u8, 154u8, 38u8, 179u8, 223u8, - 130u8, 32u8, 128u8, 30u8, 148u8, 229u8, 7u8, 185u8, 174u8, 9u8, 96u8, - 215u8, 189u8, 178u8, 148u8, 141u8, 249u8, 118u8, 7u8, 238u8, 1u8, 49u8, - ], - ) - } - #[doc = "Require that a particular destination should no longer notify us regarding any XCM"] - #[doc = "version changes."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `location`: The location to which we are currently subscribed for XCM version"] - #[doc = " notifications which we no longer desire."] - pub fn force_unsubscribe_version_notify( - &self, - location: runtime_types::xcm::VersionedMultiLocation, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "force_unsubscribe_version_notify", - ForceUnsubscribeVersionNotify { - location: ::std::boxed::Box::new(location), - }, - [ - 154u8, 169u8, 145u8, 211u8, 185u8, 71u8, 9u8, 63u8, 3u8, 158u8, 187u8, - 173u8, 115u8, 166u8, 100u8, 66u8, 12u8, 40u8, 198u8, 40u8, 213u8, - 104u8, 95u8, 183u8, 215u8, 53u8, 94u8, 158u8, 106u8, 56u8, 149u8, 52u8, - ], - ) - } - #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] - #[doc = "chain and forward a notification XCM."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] - #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] - #[doc = "at risk."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] - #[doc = " `dest` side."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] - #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] - pub fn limited_reserve_transfer_assets( - &self, - dest: runtime_types::xcm::VersionedMultiLocation, - beneficiary: runtime_types::xcm::VersionedMultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "limited_reserve_transfer_assets", - LimitedReserveTransferAssets { - dest: ::std::boxed::Box::new(dest), - beneficiary: ::std::boxed::Box::new(beneficiary), - assets: ::std::boxed::Box::new(assets), - fee_asset_item, - weight_limit, - }, - [ - 131u8, 191u8, 89u8, 27u8, 236u8, 142u8, 130u8, 129u8, 245u8, 95u8, - 159u8, 96u8, 252u8, 80u8, 28u8, 40u8, 128u8, 55u8, 41u8, 123u8, 22u8, - 18u8, 0u8, 236u8, 77u8, 68u8, 135u8, 181u8, 40u8, 47u8, 92u8, 240u8, - ], - ) - } - #[doc = "Teleport some assets from the local chain to some destination chain."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] - #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] - #[doc = "at risk."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] - #[doc = " `dest` side. May not be empty."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] - #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] - pub fn limited_teleport_assets( - &self, - dest: runtime_types::xcm::VersionedMultiLocation, - beneficiary: runtime_types::xcm::VersionedMultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "PolkadotXcm", - "limited_teleport_assets", - LimitedTeleportAssets { - dest: ::std::boxed::Box::new(dest), - beneficiary: ::std::boxed::Box::new(beneficiary), - assets: ::std::boxed::Box::new(assets), - fee_asset_item, - weight_limit, - }, - [ - 234u8, 19u8, 104u8, 174u8, 98u8, 159u8, 205u8, 110u8, 240u8, 78u8, - 186u8, 138u8, 236u8, 116u8, 104u8, 215u8, 57u8, 178u8, 166u8, 208u8, - 197u8, 113u8, 101u8, 56u8, 23u8, 56u8, 84u8, 14u8, 173u8, 70u8, 211u8, - 201u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_xcm::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Execution of an XCM message was attempted."] - #[doc = ""] - #[doc = "\\[ outcome \\]"] - pub struct Attempted(pub runtime_types::xcm::v3::traits::Outcome); - impl ::subxt::events::StaticEvent for Attempted { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "Attempted"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A XCM message was sent."] - #[doc = ""] - #[doc = "\\[ origin, destination, message \\]"] - pub struct Sent( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::v3::Xcm, - ); - impl ::subxt::events::StaticEvent for Sent { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "Sent"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Query response received which does not match a registered query. This may be because a"] - #[doc = "matching query was never registered, it may be because it is a duplicate response, or"] - #[doc = "because the query timed out."] - #[doc = ""] - #[doc = "\\[ origin location, id \\]"] - pub struct UnexpectedResponse( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u64, - ); - impl ::subxt::events::StaticEvent for UnexpectedResponse { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "UnexpectedResponse"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Query response has been received and is ready for taking with `take_response`. There is"] - #[doc = "no registered notification call."] - #[doc = ""] - #[doc = "\\[ id, response \\]"] - pub struct ResponseReady( - pub ::core::primitive::u64, - pub runtime_types::xcm::v3::Response, - ); - impl ::subxt::events::StaticEvent for ResponseReady { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "ResponseReady"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Query response has been received and query is removed. The registered notification has"] - #[doc = "been dispatched and executed successfully."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index \\]"] - pub struct Notified( - pub ::core::primitive::u64, - pub ::core::primitive::u8, - pub ::core::primitive::u8, - ); - impl ::subxt::events::StaticEvent for Notified { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "Notified"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Query response has been received and query is removed. The registered notification could"] - #[doc = "not be dispatched because the dispatch weight is greater than the maximum weight"] - #[doc = "originally budgeted by this runtime for the query result."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index, actual weight, max budgeted weight \\]"] - pub struct NotifyOverweight( - pub ::core::primitive::u64, - pub ::core::primitive::u8, - pub ::core::primitive::u8, - pub ::sp_weights::Weight, - pub ::sp_weights::Weight, - ); - impl ::subxt::events::StaticEvent for NotifyOverweight { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "NotifyOverweight"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Query response has been received and query is removed. There was a general error with"] - #[doc = "dispatching the notification call."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index \\]"] - pub struct NotifyDispatchError( - pub ::core::primitive::u64, - pub ::core::primitive::u8, - pub ::core::primitive::u8, - ); - impl ::subxt::events::StaticEvent for NotifyDispatchError { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "NotifyDispatchError"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Query response has been received and query is removed. The dispatch was unable to be"] - #[doc = "decoded into a `Call`; this might be due to dispatch function having a signature which"] - #[doc = "is not `(origin, QueryId, Response)`."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index \\]"] - pub struct NotifyDecodeFailed( - pub ::core::primitive::u64, - pub ::core::primitive::u8, - pub ::core::primitive::u8, - ); - impl ::subxt::events::StaticEvent for NotifyDecodeFailed { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "NotifyDecodeFailed"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Expected query response has been received but the origin location of the response does"] - #[doc = "not match that expected. The query remains registered for a later, valid, response to"] - #[doc = "be received and acted upon."] - #[doc = ""] - #[doc = "\\[ origin location, id, expected location \\]"] - pub struct InvalidResponder( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u64, - pub ::core::option::Option, - ); - impl ::subxt::events::StaticEvent for InvalidResponder { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "InvalidResponder"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Expected query response has been received but the expected origin location placed in"] - #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] - #[doc = ""] - #[doc = "This is unexpected (since a location placed in storage in a previously executing"] - #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] - #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] - #[doc = "needed."] - #[doc = ""] - #[doc = "\\[ origin location, id \\]"] - pub struct InvalidResponderVersion( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u64, - ); - impl ::subxt::events::StaticEvent for InvalidResponderVersion { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "InvalidResponderVersion"; - } - #[derive( - :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Received query response has been read and removed."] - #[doc = ""] - #[doc = "\\[ id \\]"] - pub struct ResponseTaken(pub ::core::primitive::u64); - impl ::subxt::events::StaticEvent for ResponseTaken { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "ResponseTaken"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some assets have been placed in an asset trap."] - #[doc = ""] - #[doc = "\\[ hash, origin, assets \\]"] - pub struct AssetsTrapped( - pub ::subxt::utils::H256, - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::VersionedMultiAssets, - ); - impl ::subxt::events::StaticEvent for AssetsTrapped { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "AssetsTrapped"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "An XCM version change notification message has been attempted to be sent."] - #[doc = ""] - #[doc = "The cost of sending it (borne by the chain) is included."] - #[doc = ""] - #[doc = "\\[ destination, result, cost \\]"] - pub struct VersionChangeNotified( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u32, - pub runtime_types::xcm::v3::multiasset::MultiAssets, - ); - impl ::subxt::events::StaticEvent for VersionChangeNotified { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "VersionChangeNotified"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "The supported version of a location has been changed. This might be through an"] - #[doc = "automatic notification or a manual intervention."] - #[doc = ""] - #[doc = "\\[ location, XCM version \\]"] - pub struct SupportedVersionChanged( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u32, - ); - impl ::subxt::events::StaticEvent for SupportedVersionChanged { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "SupportedVersionChanged"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A given location which had a version change subscription was dropped owing to an error"] - #[doc = "sending the notification to it."] - #[doc = ""] - #[doc = "\\[ location, query ID, error \\]"] - pub struct NotifyTargetSendFail( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u64, - pub runtime_types::xcm::v3::traits::Error, - ); - impl ::subxt::events::StaticEvent for NotifyTargetSendFail { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "NotifyTargetSendFail"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A given location which had a version change subscription was dropped owing to an error"] - #[doc = "migrating the location to our new XCM format."] - #[doc = ""] - #[doc = "\\[ location, query ID \\]"] - pub struct NotifyTargetMigrationFail( - pub runtime_types::xcm::VersionedMultiLocation, - pub ::core::primitive::u64, - ); - impl ::subxt::events::StaticEvent for NotifyTargetMigrationFail { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "NotifyTargetMigrationFail"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Expected query response has been received but the expected querier location placed in"] - #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] - #[doc = ""] - #[doc = "This is unexpected (since a location placed in storage in a previously executing"] - #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] - #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] - #[doc = "needed."] - #[doc = ""] - #[doc = "\\[ origin location, id \\]"] - pub struct InvalidQuerierVersion( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u64, - ); - impl ::subxt::events::StaticEvent for InvalidQuerierVersion { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "InvalidQuerierVersion"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Expected query response has been received but the querier location of the response does"] - #[doc = "not match the expected. The query remains registered for a later, valid, response to"] - #[doc = "be received and acted upon."] - #[doc = ""] - #[doc = "\\[ origin location, id, expected querier, maybe actual querier \\]"] - pub struct InvalidQuerier( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::primitive::u64, - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub ::core::option::Option, - ); - impl ::subxt::events::StaticEvent for InvalidQuerier { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "InvalidQuerier"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "A remote has requested XCM version change notification from us and we have honored it."] - #[doc = "A version information message is sent to them and its cost is included."] - #[doc = ""] - #[doc = "\\[ destination location, cost \\]"] - pub struct VersionNotifyStarted( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::v3::multiasset::MultiAssets, - ); - impl ::subxt::events::StaticEvent for VersionNotifyStarted { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "VersionNotifyStarted"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "We have requested that a remote chain sends us XCM version change notifications."] - #[doc = ""] - #[doc = "\\[ destination location, cost \\]"] - pub struct VersionNotifyRequested( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::v3::multiasset::MultiAssets, - ); - impl ::subxt::events::StaticEvent for VersionNotifyRequested { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "VersionNotifyRequested"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "We have requested that a remote chain stops sending us XCM version change notifications."] - #[doc = ""] - #[doc = "\\[ destination location, cost \\]"] - pub struct VersionNotifyUnrequested( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::v3::multiasset::MultiAssets, - ); - impl ::subxt::events::StaticEvent for VersionNotifyUnrequested { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "VersionNotifyUnrequested"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Fees were paid from a location for an operation (often for using `SendXcm`)."] - #[doc = ""] - #[doc = "\\[ paying location, fees \\]"] - pub struct FeesPaid( - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::v3::multiasset::MultiAssets, - ); - impl ::subxt::events::StaticEvent for FeesPaid { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "FeesPaid"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Some assets have been claimed from an asset trap"] - #[doc = ""] - #[doc = "\\[ hash, origin, assets \\]"] - pub struct AssetsClaimed( - pub ::subxt::utils::H256, - pub runtime_types::xcm::v3::multilocation::MultiLocation, - pub runtime_types::xcm::VersionedMultiAssets, - ); - impl ::subxt::events::StaticEvent for AssetsClaimed { - const PALLET: &'static str = "PolkadotXcm"; - const EVENT: &'static str = "AssetsClaimed"; - } - } - } - pub mod cumulus_xcm { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - pub struct TransactionApi; - impl TransactionApi {} - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::cumulus_pallet_xcm::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message is invalid XCM."] - #[doc = "\\[ id \\]"] - pub struct InvalidFormat(pub [::core::primitive::u8; 32usize]); - impl ::subxt::events::StaticEvent for InvalidFormat { - const PALLET: &'static str = "CumulusXcm"; - const EVENT: &'static str = "InvalidFormat"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message is unsupported version of XCM."] - #[doc = "\\[ id \\]"] - pub struct UnsupportedVersion(pub [::core::primitive::u8; 32usize]); - impl ::subxt::events::StaticEvent for UnsupportedVersion { - const PALLET: &'static str = "CumulusXcm"; - const EVENT: &'static str = "UnsupportedVersion"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message executed with the given outcome."] - #[doc = "\\[ id, outcome \\]"] - pub struct ExecutedDownward( - pub [::core::primitive::u8; 32usize], - pub runtime_types::xcm::v3::traits::Outcome, - ); - impl ::subxt::events::StaticEvent for ExecutedDownward { - const PALLET: &'static str = "CumulusXcm"; - const EVENT: &'static str = "ExecutedDownward"; - } - } - } - pub mod dmp_queue { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ServiceOverweight { - pub index: ::core::primitive::u64, - pub weight_limit: ::sp_weights::Weight, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Service a single overweight message."] - pub fn service_overweight( - &self, - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "DmpQueue", - "service_overweight", - ServiceOverweight { index, weight_limit }, - [ - 121u8, 236u8, 235u8, 23u8, 210u8, 238u8, 238u8, 122u8, 15u8, 86u8, - 34u8, 119u8, 105u8, 100u8, 214u8, 236u8, 117u8, 39u8, 254u8, 235u8, - 189u8, 15u8, 72u8, 74u8, 225u8, 134u8, 148u8, 126u8, 31u8, 203u8, - 144u8, 106u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::cumulus_pallet_dmp_queue::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message is invalid XCM."] - pub struct InvalidFormat { - pub message_id: [::core::primitive::u8; 32usize], - } - impl ::subxt::events::StaticEvent for InvalidFormat { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "InvalidFormat"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message is unsupported version of XCM."] - pub struct UnsupportedVersion { - pub message_id: [::core::primitive::u8; 32usize], - } - impl ::subxt::events::StaticEvent for UnsupportedVersion { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "UnsupportedVersion"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message executed with the given outcome."] - pub struct ExecutedDownward { - pub message_id: [::core::primitive::u8; 32usize], - pub outcome: runtime_types::xcm::v3::traits::Outcome, - } - impl ::subxt::events::StaticEvent for ExecutedDownward { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "ExecutedDownward"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "The weight limit for handling downward messages was reached."] - pub struct WeightExhausted { - pub message_id: [::core::primitive::u8; 32usize], - pub remaining_weight: ::sp_weights::Weight, - pub required_weight: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for WeightExhausted { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "WeightExhausted"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message is overweight and was placed in the overweight queue."] - pub struct OverweightEnqueued { - pub message_id: [::core::primitive::u8; 32usize], - pub overweight_index: ::core::primitive::u64, - pub required_weight: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for OverweightEnqueued { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "OverweightEnqueued"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Downward message from the overweight queue was executed."] - pub struct OverweightServiced { - pub overweight_index: ::core::primitive::u64, - pub weight_used: ::sp_weights::Weight, - } - impl ::subxt::events::StaticEvent for OverweightServiced { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "OverweightServiced"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "The maximum number of downward messages was."] - pub struct MaxMessagesExhausted { - pub message_id: [::core::primitive::u8; 32usize], - } - impl ::subxt::events::StaticEvent for MaxMessagesExhausted { - const PALLET: &'static str = "DmpQueue"; - const EVENT: &'static str = "MaxMessagesExhausted"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " The configuration."] - pub fn configuration( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::cumulus_pallet_dmp_queue::ConfigData, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "Configuration", - vec![], - [ - 133u8, 113u8, 115u8, 164u8, 128u8, 145u8, 234u8, 106u8, 150u8, 54u8, - 247u8, 135u8, 181u8, 197u8, 178u8, 30u8, 204u8, 46u8, 6u8, 137u8, 82u8, - 1u8, 75u8, 171u8, 7u8, 157u8, 3u8, 19u8, 92u8, 10u8, 234u8, 66u8, - ], - ) - } - #[doc = " The page index."] - pub fn page_index( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::cumulus_pallet_dmp_queue::PageIndexData, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "PageIndex", - vec![], - [ - 94u8, 132u8, 34u8, 67u8, 10u8, 22u8, 235u8, 96u8, 168u8, 26u8, 57u8, - 200u8, 130u8, 218u8, 37u8, 71u8, 28u8, 119u8, 78u8, 107u8, 209u8, - 120u8, 190u8, 2u8, 101u8, 215u8, 122u8, 187u8, 94u8, 38u8, 255u8, - 234u8, - ], - ) - } - #[doc = " The queue pages."] - pub fn pages( - &self, - _0: impl ::std::borrow::Borrow<::core::primitive::u32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec<( - ::core::primitive::u32, - ::std::vec::Vec<::core::primitive::u8>, - )>, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "Pages", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 228u8, 86u8, 33u8, 107u8, 248u8, 4u8, 223u8, 175u8, 222u8, 25u8, 204u8, - 42u8, 235u8, 21u8, 215u8, 91u8, 167u8, 14u8, 133u8, 151u8, 190u8, 57u8, - 138u8, 208u8, 79u8, 244u8, 132u8, 14u8, 48u8, 247u8, 171u8, 108u8, - ], - ) - } - #[doc = " The queue pages."] - pub fn pages_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - ::std::vec::Vec<( - ::core::primitive::u32, - ::std::vec::Vec<::core::primitive::u8>, - )>, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "Pages", - Vec::new(), - [ - 228u8, 86u8, 33u8, 107u8, 248u8, 4u8, 223u8, 175u8, 222u8, 25u8, 204u8, - 42u8, 235u8, 21u8, 215u8, 91u8, 167u8, 14u8, 133u8, 151u8, 190u8, 57u8, - 138u8, 208u8, 79u8, 244u8, 132u8, 14u8, 48u8, 247u8, 171u8, 108u8, - ], - ) - } - #[doc = " The overweight messages."] - pub fn overweight( - &self, - _0: impl ::std::borrow::Borrow<::core::primitive::u64>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<( - ::core::primitive::u32, - ::std::vec::Vec<::core::primitive::u8>, - )>, - ::subxt::storage::address::Yes, - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "Overweight", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 222u8, 85u8, 143u8, 49u8, 42u8, 248u8, 138u8, 163u8, 46u8, 199u8, - 188u8, 61u8, 137u8, 135u8, 127u8, 146u8, 210u8, 254u8, 121u8, 42u8, - 112u8, 114u8, 22u8, 228u8, 207u8, 207u8, 245u8, 175u8, 152u8, 140u8, - 225u8, 237u8, - ], - ) - } - #[doc = " The overweight messages."] - pub fn overweight_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<( - ::core::primitive::u32, - ::std::vec::Vec<::core::primitive::u8>, - )>, - (), - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "Overweight", - Vec::new(), - [ - 222u8, 85u8, 143u8, 49u8, 42u8, 248u8, 138u8, 163u8, 46u8, 199u8, - 188u8, 61u8, 137u8, 135u8, 127u8, 146u8, 210u8, 254u8, 121u8, 42u8, - 112u8, 114u8, 22u8, 228u8, 207u8, 207u8, 245u8, 175u8, 152u8, 140u8, - 225u8, 237u8, - ], - ) - } - #[doc = "Counter for the related counted storage map"] - pub fn counter_for_overweight( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "DmpQueue", - "CounterForOverweight", - vec![], - [ - 148u8, 226u8, 248u8, 107u8, 165u8, 97u8, 218u8, 160u8, 127u8, 48u8, - 185u8, 251u8, 35u8, 137u8, 119u8, 251u8, 151u8, 167u8, 189u8, 66u8, - 80u8, 74u8, 134u8, 129u8, 222u8, 180u8, 51u8, 182u8, 50u8, 110u8, 10u8, - 43u8, - ], - ) - } - } - } - } - pub mod bridge_relayers { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ClaimRewards { - pub rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Claim accumulated rewards."] - pub fn claim_rewards( - &self, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeRelayers", - "claim_rewards", - ClaimRewards { rewards_account_params }, - [ - 141u8, 52u8, 193u8, 42u8, 145u8, 26u8, 147u8, 35u8, 227u8, 221u8, - 221u8, 188u8, 104u8, 186u8, 123u8, 46u8, 190u8, 236u8, 120u8, 19u8, - 230u8, 219u8, 238u8, 227u8, 75u8, 35u8, 36u8, 177u8, 227u8, 130u8, - 103u8, 128u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_bridge_relayers::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Reward has been paid to the relayer."] - pub struct RewardPaid { - pub relayer: ::sp_core::crypto::AccountId32, - pub rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - pub reward: ::core::primitive::u128, - } - impl ::subxt::events::StaticEvent for RewardPaid { - const PALLET: &'static str = "BridgeRelayers"; - const EVENT: &'static str = "RewardPaid"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " Map of the relayer => accumulated reward."] - pub fn relayer_rewards( - &self, - _0: impl ::std::borrow::Borrow<::sp_core::crypto::AccountId32>, - _1: impl ::std::borrow::Borrow, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, - ::subxt::storage::address::Yes, - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeRelayers", - "RelayerRewards", - vec![ - ::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - ), - ::subxt::storage::address::StorageMapKey::new( - _1.borrow(), - ::subxt::storage::address::StorageHasher::Identity, - ), - ], - [ - 116u8, 81u8, 48u8, 55u8, 199u8, 26u8, 100u8, 7u8, 177u8, 230u8, 132u8, - 248u8, 221u8, 90u8, 33u8, 155u8, 198u8, 216u8, 43u8, 149u8, 92u8, - 100u8, 199u8, 183u8, 150u8, 214u8, 199u8, 222u8, 224u8, 228u8, 238u8, - 108u8, - ], - ) - } - #[doc = " Map of the relayer => accumulated reward."] - pub fn relayer_rewards_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u128>, - (), - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeRelayers", - "RelayerRewards", - Vec::new(), - [ - 116u8, 81u8, 48u8, 55u8, 199u8, 26u8, 100u8, 7u8, 177u8, 230u8, 132u8, - 248u8, 221u8, 90u8, 33u8, 155u8, 198u8, 216u8, 43u8, 149u8, 92u8, - 100u8, 199u8, 183u8, 150u8, 214u8, 199u8, 222u8, 224u8, 228u8, 238u8, - 108u8, - ], - ) - } - } - } - } - pub mod bridge_millau_grandpa { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SubmitFinalityProof { - pub finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - pub justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct Initialize { - pub init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetOwner { - pub new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetOperatingMode { - pub operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Verify a target header is finalized according to the given finality proof."] - #[doc = ""] - #[doc = "It will use the underlying storage pallet to fetch information about the current"] - #[doc = "authorities and best finalized header in order to verify that the header is finalized."] - #[doc = ""] - #[doc = "If successful in verification, it will write the target header to the underlying storage"] - #[doc = "pallet."] - pub fn submit_finality_proof( - &self, - finality_target: ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauGrandpa", - "submit_finality_proof", - SubmitFinalityProof { - finality_target: ::std::boxed::Box::new(finality_target), - justification, - }, - [ - 3u8, 161u8, 243u8, 208u8, 245u8, 135u8, 86u8, 233u8, 103u8, 140u8, - 81u8, 3u8, 119u8, 185u8, 68u8, 167u8, 208u8, 155u8, 169u8, 201u8, - 209u8, 248u8, 162u8, 45u8, 155u8, 225u8, 173u8, 62u8, 156u8, 171u8, - 19u8, 190u8, - ], - ) - } - #[doc = "Bootstrap the bridge pallet with an initial header and authority set from which to sync."] - #[doc = ""] - #[doc = "The initial configuration provided does not need to be the genesis header of the bridged"] - #[doc = "chain, it can be any arbitrary header. You can also provide the next scheduled set"] - #[doc = "change if it is already know."] - #[doc = ""] - #[doc = "This function is only allowed to be called from a trusted origin and writes to storage"] - #[doc = "with practically no checks in terms of the validity of the data. It is important that"] - #[doc = "you ensure that valid data is being passed in."] - pub fn initialize( - &self, - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauGrandpa", - "initialize", - Initialize { init_data }, - [ - 244u8, 188u8, 202u8, 145u8, 218u8, 91u8, 74u8, 80u8, 41u8, 185u8, - 239u8, 178u8, 231u8, 128u8, 198u8, 90u8, 135u8, 219u8, 200u8, 23u8, - 194u8, 47u8, 61u8, 222u8, 194u8, 84u8, 142u8, 37u8, 64u8, 37u8, 69u8, - 198u8, - ], - ) - } - #[doc = "Change `PalletOwner`."] - #[doc = ""] - #[doc = "May only be called either by root, or by `PalletOwner`."] - pub fn set_owner( - &self, - new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauGrandpa", - "set_owner", - SetOwner { new_owner }, - [ - 100u8, 221u8, 84u8, 142u8, 158u8, 5u8, 47u8, 212u8, 9u8, 35u8, 82u8, - 135u8, 108u8, 238u8, 231u8, 197u8, 77u8, 219u8, 176u8, 222u8, 88u8, - 167u8, 152u8, 34u8, 177u8, 244u8, 160u8, 195u8, 211u8, 3u8, 66u8, - 253u8, - ], - ) - } - #[doc = "Halt or resume all pallet operations."] - #[doc = ""] - #[doc = "May only be called either by root, or by `PalletOwner`."] - pub fn set_operating_mode( - &self, - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauGrandpa", - "set_operating_mode", - SetOperatingMode { operating_mode }, - [ - 128u8, 25u8, 81u8, 145u8, 111u8, 185u8, 226u8, 152u8, 18u8, 51u8, 89u8, - 236u8, 200u8, 157u8, 157u8, 186u8, 207u8, 208u8, 152u8, 168u8, 12u8, - 39u8, 249u8, 48u8, 195u8, 160u8, 54u8, 73u8, 30u8, 230u8, 25u8, 46u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_bridge_grandpa::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Best finalized chain header has been updated to the header with given number and hash."] - pub struct UpdatedBestFinalizedHeader { - pub number: ::core::primitive::u64, - pub hash: ::bp_millau::MillauHash, - } - impl ::subxt::events::StaticEvent for UpdatedBestFinalizedHeader { - const PALLET: &'static str = "BridgeMillauGrandpa"; - const EVENT: &'static str = "UpdatedBestFinalizedHeader"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " The current number of requests which have written to storage."] - #[doc = ""] - #[doc = " If the `RequestCount` hits `MaxRequests`, no more calls will be allowed to the pallet until"] - #[doc = " the request capacity is increased."] - #[doc = ""] - #[doc = " The `RequestCount` is decreased by one at the beginning of every block. This is to ensure"] - #[doc = " that the pallet can always make progress."] - pub fn request_count( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "RequestCount", - vec![], - [ - 100u8, 156u8, 98u8, 176u8, 229u8, 85u8, 81u8, 159u8, 120u8, 156u8, - 33u8, 179u8, 224u8, 237u8, 52u8, 198u8, 81u8, 81u8, 10u8, 180u8, 53u8, - 141u8, 96u8, 4u8, 39u8, 217u8, 58u8, 9u8, 57u8, 79u8, 47u8, 201u8, - ], - ) - } - #[doc = " Hash of the header used to bootstrap the pallet."] - pub fn initial_hash( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::bp_millau::MillauHash>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "InitialHash", - vec![], - [ - 167u8, 131u8, 64u8, 215u8, 102u8, 70u8, 21u8, 34u8, 254u8, 233u8, 2u8, - 49u8, 253u8, 67u8, 235u8, 10u8, 21u8, 223u8, 220u8, 198u8, 180u8, - 137u8, 88u8, 251u8, 230u8, 108u8, 9u8, 104u8, 101u8, 105u8, 38u8, - 138u8, - ], - ) - } - #[doc = " Hash of the best finalized header."] - pub fn best_finalized( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_runtime::HeaderId< - ::bp_millau::MillauHash, - ::core::primitive::u64, - >, - >, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "BestFinalized", - vec![], - [ - 61u8, 173u8, 97u8, 223u8, 180u8, 235u8, 85u8, 126u8, 217u8, 228u8, - 87u8, 174u8, 116u8, 156u8, 162u8, 252u8, 100u8, 200u8, 138u8, 14u8, - 102u8, 177u8, 66u8, 164u8, 216u8, 114u8, 18u8, 223u8, 94u8, 78u8, - 107u8, 58u8, - ], - ) - } - #[doc = " A ring buffer of imported hashes. Ordered by the insertion time."] - pub fn imported_hashes( - &self, - _0: impl ::std::borrow::Borrow<::core::primitive::u32>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::bp_millau::MillauHash>, - ::subxt::storage::address::Yes, - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "ImportedHashes", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Identity, - )], - [ - 249u8, 185u8, 202u8, 36u8, 40u8, 197u8, 111u8, 168u8, 136u8, 138u8, - 84u8, 135u8, 69u8, 34u8, 181u8, 46u8, 158u8, 16u8, 150u8, 190u8, 81u8, - 53u8, 239u8, 199u8, 83u8, 93u8, 197u8, 205u8, 129u8, 173u8, 141u8, - 43u8, - ], - ) - } - #[doc = " A ring buffer of imported hashes. Ordered by the insertion time."] - pub fn imported_hashes_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::bp_millau::MillauHash>, - (), - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "ImportedHashes", - Vec::new(), - [ - 249u8, 185u8, 202u8, 36u8, 40u8, 197u8, 111u8, 168u8, 136u8, 138u8, - 84u8, 135u8, 69u8, 34u8, 181u8, 46u8, 158u8, 16u8, 150u8, 190u8, 81u8, - 53u8, 239u8, 199u8, 83u8, 93u8, 197u8, 205u8, 129u8, 173u8, 141u8, - 43u8, - ], - ) - } - #[doc = " Current ring buffer position."] - pub fn imported_hashes_pointer( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "ImportedHashesPointer", - vec![], - [ - 159u8, 83u8, 35u8, 45u8, 27u8, 249u8, 155u8, 131u8, 181u8, 196u8, - 224u8, 26u8, 92u8, 132u8, 127u8, 237u8, 13u8, 142u8, 196u8, 147u8, - 221u8, 216u8, 11u8, 78u8, 190u8, 241u8, 201u8, 96u8, 74u8, 185u8, - 208u8, 42u8, - ], - ) - } - #[doc = " Relevant fields of imported headers."] - pub fn imported_headers( - &self, - _0: impl ::std::borrow::Borrow<::bp_millau::MillauHash>, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_header_chain::StoredHeaderData< - ::core::primitive::u64, - ::bp_millau::MillauHash, - >, - >, - ::subxt::storage::address::Yes, - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "ImportedHeaders", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Identity, - )], - [ - 109u8, 41u8, 102u8, 223u8, 133u8, 169u8, 46u8, 221u8, 235u8, 67u8, - 28u8, 192u8, 2u8, 242u8, 215u8, 166u8, 227u8, 182u8, 136u8, 217u8, - 61u8, 10u8, 246u8, 70u8, 17u8, 246u8, 223u8, 113u8, 9u8, 136u8, 181u8, - 242u8, - ], - ) - } - #[doc = " Relevant fields of imported headers."] - pub fn imported_headers_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_header_chain::StoredHeaderData< - ::core::primitive::u64, - ::bp_millau::MillauHash, - >, - >, - (), - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "ImportedHeaders", - Vec::new(), - [ - 109u8, 41u8, 102u8, 223u8, 133u8, 169u8, 46u8, 221u8, 235u8, 67u8, - 28u8, 192u8, 2u8, 242u8, 215u8, 166u8, 227u8, 182u8, 136u8, 217u8, - 61u8, 10u8, 246u8, 70u8, 17u8, 246u8, 223u8, 113u8, 9u8, 136u8, 181u8, - 242u8, - ], - ) - } - #[doc = " The current GRANDPA Authority set."] - pub fn current_authority_set( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::pallet_bridge_grandpa::storage_types::StoredAuthoritySet, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "CurrentAuthoritySet", - vec![], - [ - 249u8, 40u8, 229u8, 120u8, 141u8, 219u8, 206u8, 5u8, 54u8, 121u8, - 207u8, 77u8, 8u8, 80u8, 105u8, 107u8, 151u8, 111u8, 82u8, 119u8, 8u8, - 31u8, 104u8, 82u8, 92u8, 156u8, 37u8, 160u8, 235u8, 64u8, 62u8, 94u8, - ], - ) - } - #[doc = " Optional pallet owner."] - #[doc = ""] - #[doc = " Pallet owner has a right to halt all pallet operations and then resume it. If it is"] - #[doc = " `None`, then there are no direct ways to halt/resume pallet operations, but other"] - #[doc = " runtime methods may still be used to do that (i.e. democracy::referendum to update halt"] - #[doc = " flag directly or call the `halt_operations`)."] - pub fn pallet_owner( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::sp_core::crypto::AccountId32>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "PalletOwner", - vec![], - [ - 89u8, 42u8, 74u8, 119u8, 21u8, 164u8, 30u8, 115u8, 207u8, 126u8, 98u8, - 16u8, 162u8, 214u8, 67u8, 172u8, 178u8, 223u8, 139u8, 121u8, 174u8, - 89u8, 215u8, 75u8, 200u8, 161u8, 61u8, 195u8, 65u8, 222u8, 246u8, - 233u8, - ], - ) - } - #[doc = " The current operating mode of the pallet."] - #[doc = ""] - #[doc = " Depending on the mode either all, or no transactions will be allowed."] - pub fn pallet_operating_mode( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_runtime::BasicOperatingMode, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauGrandpa", - "PalletOperatingMode", - vec![], - [ - 218u8, 66u8, 212u8, 71u8, 38u8, 152u8, 55u8, 129u8, 125u8, 231u8, 91u8, - 216u8, 157u8, 141u8, 173u8, 146u8, 30u8, 40u8, 132u8, 107u8, 97u8, - 39u8, 36u8, 81u8, 231u8, 222u8, 113u8, 136u8, 233u8, 212u8, 225u8, - 75u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " The upper bound on the number of requests allowed by the pallet."] - #[doc = ""] - #[doc = " A request refers to an action which writes a header to storage."] - #[doc = ""] - #[doc = " Once this bound is reached the pallet will not allow any dispatchables to be called"] - #[doc = " until the request count has decreased."] - pub fn max_requests( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "BridgeMillauGrandpa", - "MaxRequests", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - #[doc = " Maximal number of finalized headers to keep in the storage."] - #[doc = ""] - #[doc = " The setting is there to prevent growing the on-chain state indefinitely. Note"] - #[doc = " the setting does not relate to block numbers - we will simply keep as much items"] - #[doc = " in the storage, so it doesn't guarantee any fixed timeframe for finality headers."] - #[doc = ""] - #[doc = " Incautious change of this constant may lead to orphan entries in the runtime storage."] - pub fn headers_to_keep( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "BridgeMillauGrandpa", - "HeadersToKeep", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - } - } - } - pub mod bridge_millau_messages { - use super::{root_mod, runtime_types}; - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] - pub mod calls { - use super::{root_mod, runtime_types}; - type DispatchError = runtime_types::sp_runtime::DispatchError; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetOwner { - pub new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct SetOperatingMode { - pub operating_mode: runtime_types::bp_messages::MessagesOperatingMode, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ReceiveMessagesProof { - pub relayer_id_at_bridged_chain: ::sp_core::crypto::AccountId32, - pub proof: ::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< - ::bp_millau::MillauHash, - >, - pub messages_count: ::core::primitive::u32, - pub dispatch_weight: ::sp_weights::Weight, - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - pub struct ReceiveMessagesDeliveryProof { pub proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , pub relayers_state : :: bp_messages :: UnrewardedRelayersState , } - pub struct TransactionApi; - impl TransactionApi { - #[doc = "Change `PalletOwner`."] - #[doc = ""] - #[doc = "May only be called either by root, or by `PalletOwner`."] - pub fn set_owner( - &self, - new_owner: ::core::option::Option<::sp_core::crypto::AccountId32>, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauMessages", - "set_owner", - SetOwner { new_owner }, - [ - 100u8, 221u8, 84u8, 142u8, 158u8, 5u8, 47u8, 212u8, 9u8, 35u8, 82u8, - 135u8, 108u8, 238u8, 231u8, 197u8, 77u8, 219u8, 176u8, 222u8, 88u8, - 167u8, 152u8, 34u8, 177u8, 244u8, 160u8, 195u8, 211u8, 3u8, 66u8, - 253u8, - ], - ) - } - #[doc = "Halt or resume all/some pallet operations."] - #[doc = ""] - #[doc = "May only be called either by root, or by `PalletOwner`."] - pub fn set_operating_mode( - &self, - operating_mode: runtime_types::bp_messages::MessagesOperatingMode, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauMessages", - "set_operating_mode", - SetOperatingMode { operating_mode }, - [ - 236u8, 230u8, 127u8, 17u8, 145u8, 186u8, 102u8, 200u8, 227u8, 208u8, - 230u8, 121u8, 102u8, 199u8, 123u8, 118u8, 199u8, 160u8, 131u8, 116u8, - 102u8, 167u8, 119u8, 144u8, 70u8, 114u8, 0u8, 223u8, 54u8, 197u8, 39u8, - 58u8, - ], - ) - } - #[doc = "Receive messages proof from bridged chain."] - #[doc = ""] - #[doc = "The weight of the call assumes that the transaction always brings outbound lane"] - #[doc = "state update. Because of that, the submitter (relayer) has no benefit of not including"] - #[doc = "this data in the transaction, so reward confirmations lags should be minimal."] - pub fn receive_messages_proof( - &self, - relayer_id_at_bridged_chain: ::sp_core::crypto::AccountId32, - proof: ::bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< - ::bp_millau::MillauHash, - >, - messages_count: ::core::primitive::u32, - dispatch_weight: ::sp_weights::Weight, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauMessages", - "receive_messages_proof", - ReceiveMessagesProof { - relayer_id_at_bridged_chain, - proof, - messages_count, - dispatch_weight, - }, - [ - 14u8, 23u8, 191u8, 242u8, 252u8, 163u8, 87u8, 149u8, 211u8, 25u8, - 112u8, 192u8, 206u8, 49u8, 135u8, 124u8, 79u8, 92u8, 204u8, 39u8, 80u8, - 139u8, 155u8, 124u8, 134u8, 1u8, 66u8, 68u8, 213u8, 85u8, 42u8, 250u8, - ], - ) - } - #[doc = "Receive messages delivery proof from bridged chain."] - pub fn receive_messages_delivery_proof( - &self, - proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash >, - relayers_state: ::bp_messages::UnrewardedRelayersState, - ) -> ::subxt::tx::StaticTxPayload { - ::subxt::tx::StaticTxPayload::new( - "BridgeMillauMessages", - "receive_messages_delivery_proof", - ReceiveMessagesDeliveryProof { proof, relayers_state }, - [ - 216u8, 113u8, 64u8, 20u8, 16u8, 64u8, 144u8, 143u8, 105u8, 30u8, 192u8, - 89u8, 74u8, 34u8, 56u8, 151u8, 20u8, 234u8, 14u8, 211u8, 64u8, 103u8, - 218u8, 164u8, 69u8, 107u8, 6u8, 119u8, 13u8, 90u8, 150u8, 24u8, - ], - ) - } - } - } - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] - pub type Event = runtime_types::pallet_bridge_messages::pallet::Event; - pub mod events { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Message has been accepted and is waiting to be delivered."] - pub struct MessageAccepted { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - impl ::subxt::events::StaticEvent for MessageAccepted { - const PALLET: &'static str = "BridgeMillauMessages"; - const EVENT: &'static str = "MessageAccepted"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Messages have been received from the bridged chain."] - pub struct MessagesReceived (pub :: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) ; - impl ::subxt::events::StaticEvent for MessagesReceived { - const PALLET: &'static str = "BridgeMillauMessages"; - const EVENT: &'static str = "MessagesReceived"; - } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] - #[doc = "Messages in the inclusive range have been delivered to the bridged chain."] - pub struct MessagesDelivered { - pub lane_id: runtime_types::bp_messages::LaneId, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - impl ::subxt::events::StaticEvent for MessagesDelivered { - const PALLET: &'static str = "BridgeMillauMessages"; - const EVENT: &'static str = "MessagesDelivered"; - } - } - pub mod storage { - use super::runtime_types; - pub struct StorageApi; - impl StorageApi { - #[doc = " Optional pallet owner."] - #[doc = ""] - #[doc = " Pallet owner has a right to halt all pallet operations and then resume it. If it is"] - #[doc = " `None`, then there are no direct ways to halt/resume pallet operations, but other"] - #[doc = " runtime methods may still be used to do that (i.e. democracy::referendum to update halt"] - #[doc = " flag directly or call the `halt_operations`)."] - pub fn pallet_owner( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType<::sp_core::crypto::AccountId32>, - ::subxt::storage::address::Yes, - (), - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "PalletOwner", - vec![], - [ - 89u8, 42u8, 74u8, 119u8, 21u8, 164u8, 30u8, 115u8, 207u8, 126u8, 98u8, - 16u8, 162u8, 214u8, 67u8, 172u8, 178u8, 223u8, 139u8, 121u8, 174u8, - 89u8, 215u8, 75u8, 200u8, 161u8, 61u8, 195u8, 65u8, 222u8, 246u8, - 233u8, - ], - ) - } - #[doc = " The current operating mode of the pallet."] - #[doc = ""] - #[doc = " Depending on the mode either all, some, or no transactions will be allowed."] - pub fn pallet_operating_mode( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_messages::MessagesOperatingMode, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - (), - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "PalletOperatingMode", - vec![], - [ - 215u8, 195u8, 85u8, 231u8, 158u8, 22u8, 160u8, 132u8, 69u8, 206u8, - 238u8, 14u8, 56u8, 100u8, 134u8, 41u8, 58u8, 120u8, 225u8, 164u8, - 173u8, 87u8, 22u8, 123u8, 102u8, 167u8, 68u8, 70u8, 184u8, 131u8, - 232u8, 65u8, - ], - ) - } - #[doc = " Map of lane id => inbound lane data."] - pub fn inbound_lanes( - &self, - _0: impl ::std::borrow::Borrow, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_messages::InboundLaneData<::sp_core::crypto::AccountId32>, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "InboundLanes", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 38u8, 58u8, 110u8, 130u8, 112u8, 76u8, 231u8, 76u8, 56u8, 241u8, 183u8, - 153u8, 112u8, 41u8, 248u8, 208u8, 217u8, 57u8, 102u8, 30u8, 107u8, - 98u8, 59u8, 78u8, 56u8, 119u8, 186u8, 183u8, 213u8, 72u8, 199u8, 90u8, - ], - ) - } - #[doc = " Map of lane id => inbound lane data."] - pub fn inbound_lanes_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_messages::InboundLaneData<::sp_core::crypto::AccountId32>, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "InboundLanes", - Vec::new(), - [ - 38u8, 58u8, 110u8, 130u8, 112u8, 76u8, 231u8, 76u8, 56u8, 241u8, 183u8, - 153u8, 112u8, 41u8, 248u8, 208u8, 217u8, 57u8, 102u8, 30u8, 107u8, - 98u8, 59u8, 78u8, 56u8, 119u8, 186u8, 183u8, 213u8, 72u8, 199u8, 90u8, - ], - ) - } - #[doc = " Map of lane id => outbound lane data."] - pub fn outbound_lanes( - &self, - _0: impl ::std::borrow::Borrow, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_messages::OutboundLaneData, - >, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "OutboundLanes", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 67u8, 155u8, 173u8, 244u8, 80u8, 38u8, 26u8, 71u8, 51u8, 150u8, 86u8, - 146u8, 132u8, 122u8, 70u8, 122u8, 172u8, 246u8, 106u8, 232u8, 149u8, - 227u8, 240u8, 146u8, 51u8, 184u8, 30u8, 182u8, 200u8, 43u8, 190u8, - 38u8, - ], - ) - } - #[doc = " Map of lane id => outbound lane data."] - pub fn outbound_lanes_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bp_messages::OutboundLaneData, - >, - (), - ::subxt::storage::address::Yes, - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "OutboundLanes", - Vec::new(), - [ - 67u8, 155u8, 173u8, 244u8, 80u8, 38u8, 26u8, 71u8, 51u8, 150u8, 86u8, - 146u8, 132u8, 122u8, 70u8, 122u8, 172u8, 246u8, 106u8, 232u8, 149u8, - 227u8, 240u8, 146u8, 51u8, 184u8, 30u8, 182u8, 200u8, 43u8, 190u8, - 38u8, - ], - ) - } - #[doc = " All queued outbound messages."] - pub fn outbound_messages( - &self, - _0: impl ::std::borrow::Borrow, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - >, - ::subxt::storage::address::Yes, - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "OutboundMessages", - vec![::subxt::storage::address::StorageMapKey::new( - _0.borrow(), - ::subxt::storage::address::StorageHasher::Blake2_128Concat, - )], - [ - 44u8, 35u8, 2u8, 25u8, 91u8, 101u8, 152u8, 23u8, 48u8, 250u8, 178u8, - 15u8, 194u8, 118u8, 146u8, 1u8, 112u8, 83u8, 243u8, 166u8, 124u8, - 153u8, 48u8, 193u8, 43u8, 31u8, 33u8, 72u8, 228u8, 113u8, 86u8, 217u8, - ], - ) - } - #[doc = " All queued outbound messages."] - pub fn outbound_messages_root( - &self, - ) -> ::subxt::storage::address::StaticStorageAddress< - ::subxt::metadata::DecodeStaticType< - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - >, - (), - (), - ::subxt::storage::address::Yes, - > { - ::subxt::storage::address::StaticStorageAddress::new( - "BridgeMillauMessages", - "OutboundMessages", - Vec::new(), - [ - 44u8, 35u8, 2u8, 25u8, 91u8, 101u8, 152u8, 23u8, 48u8, 250u8, 178u8, - 15u8, 194u8, 118u8, 146u8, 1u8, 112u8, 83u8, 243u8, 166u8, 124u8, - 153u8, 48u8, 193u8, 43u8, 31u8, 33u8, 72u8, 228u8, 113u8, 86u8, 217u8, - ], - ) - } - } - } - pub mod constants { - use super::runtime_types; - pub struct ConstantsApi; - impl ConstantsApi { - #[doc = " Gets the chain id value from the instance."] - pub fn bridged_chain_id( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<[::core::primitive::u8; 4usize]>, - > { - ::subxt::constants::StaticConstantAddress::new( - "BridgeMillauMessages", - "BridgedChainId", - [ - 101u8, 157u8, 37u8, 163u8, 190u8, 134u8, 129u8, 212u8, 240u8, 135u8, - 174u8, 76u8, 220u8, 179u8, 252u8, 69u8, 65u8, 253u8, 69u8, 214u8, 61u8, - 249u8, 4u8, 38u8, 181u8, 237u8, 25u8, 131u8, 242u8, 20u8, 17u8, 152u8, - ], - ) - } - #[doc = " Maximal encoded size of the outbound payload."] - pub fn maximal_outbound_payload_size( - &self, - ) -> ::subxt::constants::StaticConstantAddress< - ::subxt::metadata::DecodeStaticType<::core::primitive::u32>, - > { - ::subxt::constants::StaticConstantAddress::new( - "BridgeMillauMessages", - "MaximalOutboundPayloadSize", - [ - 98u8, 252u8, 116u8, 72u8, 26u8, 180u8, 225u8, 83u8, 200u8, 157u8, - 125u8, 151u8, 53u8, 76u8, 168u8, 26u8, 10u8, 9u8, 98u8, 68u8, 9u8, - 178u8, 197u8, 113u8, 31u8, 79u8, 200u8, 90u8, 203u8, 100u8, 41u8, - 145u8, - ], - ) - } - } - } - } pub mod runtime_types { use super::runtime_types; pub mod bounded_collections { use super::runtime_types; pub mod bounded_vec { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); } pub mod weak_bounded_vec { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); } } pub mod bp_header_chain { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct StoredHeaderData<_0, _1> { pub number: _0, pub state_root: _1, @@ -5979,51 +47,37 @@ pub mod api { } pub mod bp_messages { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct DeliveredMessages { pub begin: ::core::primitive::u64, pub end: ::core::primitive::u64, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct InboundLaneData<_0> { pub relayers: ::std::vec::Vec>, pub last_confirmed_nonce: ::core::primitive::u64, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MessageKey { pub lane_id: runtime_types::bp_messages::LaneId, pub nonce: ::core::primitive::u64, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum MessagesOperatingMode { #[codec(index = 0)] Basic(runtime_types::bp_runtime::BasicOperatingMode), #[codec(index = 1)] RejectingOutboundMessages, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct OutboundLaneData { pub oldest_unpruned_nonce: ::core::primitive::u64, pub latest_received_nonce: ::core::primitive::u64, pub latest_generated_nonce: ::core::primitive::u64, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum ReceivalResult<_0> { #[codec(index = 0)] Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), @@ -6034,9 +88,7 @@ pub mod api { #[codec(index = 3)] TooManyUnconfirmedMessages, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct ReceivedMessages<_0> { pub lane: runtime_types::bp_messages::LaneId, pub receive_results: ::std::vec::Vec<( @@ -6044,9 +96,7 @@ pub mod api { runtime_types::bp_messages::ReceivalResult<_0>, )>, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct UnrewardedRelayer<_0> { pub relayer: _0, pub messages: runtime_types::bp_messages::DeliveredMessages, @@ -6054,18 +104,14 @@ pub mod api { } pub mod bp_relayers { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum RewardsAccountOwner { #[codec(index = 0)] ThisChain, #[codec(index = 1)] BridgedChain, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct RewardsAccountParams { pub lane_id: runtime_types::bp_messages::LaneId, pub bridged_chain_id: [::core::primitive::u8; 4usize], @@ -6076,33 +122,22 @@ pub mod api { use super::runtime_types; pub mod messages { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MessageDispatchResult<_0> { pub unspent_weight: ::sp_weights::Weight, pub dispatch_level_result: _0, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum BasicOperatingMode { #[codec(index = 0)] Normal, #[codec(index = 1)] Halted, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum OwnedBridgeModuleError { #[codec(index = 0)] Halted, @@ -6112,12 +147,7 @@ pub mod api { use super::runtime_types; pub mod messages_xcm_extension { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum XcmBlobMessageDispatchResult { #[codec(index = 0)] InvalidPayload, @@ -6132,90 +162,58 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Service a single overweight message."] service_overweight { index: ::core::primitive::u64, weight_limit: ::sp_weights::Weight, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "The message index given is unknown."] Unknown, #[codec(index = 1)] - #[doc = "The amount of weight given is possibly not enough for executing the message."] OverLimit, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "Downward message is invalid XCM."] InvalidFormat { message_id: [::core::primitive::u8; 32usize] }, #[codec(index = 1)] - #[doc = "Downward message is unsupported version of XCM."] UnsupportedVersion { message_id: [::core::primitive::u8; 32usize] }, #[codec(index = 2)] - #[doc = "Downward message executed with the given outcome."] ExecutedDownward { message_id: [::core::primitive::u8; 32usize], outcome: runtime_types::xcm::v3::traits::Outcome, }, #[codec(index = 3)] - #[doc = "The weight limit for handling downward messages was reached."] WeightExhausted { message_id: [::core::primitive::u8; 32usize], remaining_weight: ::sp_weights::Weight, required_weight: ::sp_weights::Weight, }, #[codec(index = 4)] - #[doc = "Downward message is overweight and was placed in the overweight queue."] OverweightEnqueued { message_id: [::core::primitive::u8; 32usize], overweight_index: ::core::primitive::u64, required_weight: ::sp_weights::Weight, }, #[codec(index = 5)] - #[doc = "Downward message from the overweight queue was executed."] OverweightServiced { overweight_index: ::core::primitive::u64, weight_used: ::sp_weights::Weight, }, #[codec(index = 6)] - #[doc = "The maximum number of downward messages was."] MaxMessagesExhausted { message_id: [::core::primitive::u8; 32usize] }, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct ConfigData { pub max_individual: ::sp_weights::Weight, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct PageIndexData { pub begin_used: ::core::primitive::u32, pub end_used: ::core::primitive::u32, @@ -6226,80 +224,46 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { - # [codec (index = 0)] # [doc = "Set the current validation data."] # [doc = ""] # [doc = "This should be invoked exactly once per block. It will panic at the finalization"] # [doc = "phase if the call was not invoked."] # [doc = ""] # [doc = "The dispatch origin for this call must be `Inherent`"] # [doc = ""] # [doc = "As a side effect, this function upgrades the current validation function"] # [doc = "if the appropriate time has come."] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] # [doc = "Authorize an upgrade to a given `code_hash` for the runtime. The runtime can be supplied"] # [doc = "later."] # [doc = ""] # [doc = "The `check_version` parameter sets a boolean flag for whether or not the runtime's spec"] # [doc = "version and name should be verified on upgrade. Since the authorization only has a hash,"] # [doc = "it cannot actually perform the verification."] # [doc = ""] # [doc = "This call requires Root origin."] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] # [doc = "Provide the preimage (runtime binary) `code` for an upgrade that has been authorized."] # [doc = ""] # [doc = "If the authorization required a version check, this call will ensure the spec name"] # [doc = "remains unchanged and that the spec version has increased."] # [doc = ""] # [doc = "Note that this function will not apply the new `code`, but only attempt to schedule the"] # [doc = "upgrade with the Relay Chain."] # [doc = ""] # [doc = "All origins are allowed."] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "Attempt to upgrade validation function while existing upgrade pending."] OverlappingUpgrades, #[codec(index = 1)] - #[doc = "Polkadot currently prohibits this parachain from upgrading its validation function."] ProhibitedByPolkadot, #[codec(index = 2)] - #[doc = "The supplied validation function has compiled into a blob larger than Polkadot is"] - #[doc = "willing to run."] TooBig, #[codec(index = 3)] - #[doc = "The inherent which supplies the validation data did not run this block."] ValidationDataNotAvailable, #[codec(index = 4)] - #[doc = "The inherent which supplies the host configuration did not run this block."] HostConfigurationNotAvailable, #[codec(index = 5)] - #[doc = "No validation function upgrade is currently scheduled."] NotScheduled, #[codec(index = 6)] - #[doc = "No code upgrade has been authorized."] NothingAuthorized, #[codec(index = 7)] - #[doc = "The given code upgrade has not been authorized."] Unauthorized, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "The validation function has been scheduled to apply."] ValidationFunctionStored, #[codec(index = 1)] - #[doc = "The validation function was applied as of the contained relay chain block number."] ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, #[codec(index = 2)] - #[doc = "The relay-chain aborted the upgrade process."] ValidationFunctionDiscarded, #[codec(index = 3)] - #[doc = "An upgrade has been authorized."] UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, #[codec(index = 4)] - #[doc = "Some downward messages have been received and will be processed."] DownwardMessagesReceived { count: ::core::primitive::u32 }, #[codec(index = 5)] - #[doc = "Downward messages were processed using the given weight."] DownwardMessagesProcessed { weight_used: ::sp_weights::Weight, dmq_head: ::subxt::utils::H256, }, #[codec(index = 6)] - #[doc = "An upward message was sent to the relay chain."] UpwardMessageSent { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, }, @@ -6307,12 +271,7 @@ pub mod api { } pub mod relay_state_snapshot { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MessagingStateSnapshot { pub dmq_mqc_head: ::subxt::utils::H256, pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), @@ -6326,9 +285,7 @@ pub mod api { )>, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CodeUpgradeAuthorization { pub code_hash: ::subxt::utils::H256, pub check_version: ::core::primitive::bool, @@ -6338,41 +295,17 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call {} - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error {} - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "Downward message is invalid XCM."] - #[doc = "\\[ id \\]"] InvalidFormat([::core::primitive::u8; 32usize]), #[codec(index = 1)] - #[doc = "Downward message is unsupported version of XCM."] - #[doc = "\\[ id \\]"] UnsupportedVersion([::core::primitive::u8; 32usize]), #[codec(index = 2)] - #[doc = "Downward message executed with the given outcome."] - #[doc = "\\[ id, outcome \\]"] ExecutedDownward( [::core::primitive::u8; 32usize], runtime_types::xcm::v3::traits::Outcome, @@ -6384,148 +317,69 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Services a single overweight XCM."] - #[doc = ""] - #[doc = "- `origin`: Must pass `ExecuteOverweightOrigin`."] - #[doc = "- `index`: The index of the overweight XCM to service"] - #[doc = "- `weight_limit`: The amount of weight that XCM execution may take."] - #[doc = ""] - #[doc = "Errors:"] - #[doc = "- `BadOverweightIndex`: XCM under `index` is not found in the `Overweight` storage map."] - #[doc = "- `BadXcm`: XCM under `index` cannot be properly decoded into a valid XCM format."] - #[doc = "- `WeightOverLimit`: XCM execution may use greater `weight_limit`."] - #[doc = ""] - #[doc = "Events:"] - #[doc = "- `OverweightServiced`: On success."] service_overweight { index: ::core::primitive::u64, weight_limit: ::sp_weights::Weight, }, #[codec(index = 1)] - #[doc = "Suspends all XCM executions for the XCMP queue, regardless of the sender's origin."] - #[doc = ""] - #[doc = "- `origin`: Must pass `ControllerOrigin`."] suspend_xcm_execution, #[codec(index = 2)] - #[doc = "Resumes all XCM executions for the XCMP queue."] - #[doc = ""] - #[doc = "Note that this function doesn't change the status of the in/out bound channels."] - #[doc = ""] - #[doc = "- `origin`: Must pass `ControllerOrigin`."] resume_xcm_execution, #[codec(index = 3)] - #[doc = "Overwrites the number of pages of messages which must be in the queue for the other side to be told to"] - #[doc = "suspend their sending."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.suspend_value`"] update_suspend_threshold { new: ::core::primitive::u32 }, #[codec(index = 4)] - #[doc = "Overwrites the number of pages of messages which must be in the queue after which we drop any further"] - #[doc = "messages from the channel."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.drop_threshold`"] update_drop_threshold { new: ::core::primitive::u32 }, #[codec(index = 5)] - #[doc = "Overwrites the number of pages of messages which the queue must be reduced to before it signals that"] - #[doc = "message sending may recommence after it has been suspended."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.resume_threshold`"] update_resume_threshold { new: ::core::primitive::u32 }, #[codec(index = 6)] - #[doc = "Overwrites the amount of remaining weight under which we stop processing messages."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.threshold_weight`"] update_threshold_weight { new: ::sp_weights::Weight }, #[codec(index = 7)] - #[doc = "Overwrites the speed to which the available weight approaches the maximum weight."] - #[doc = "A lower number results in a faster progression. A value of 1 makes the entire weight available initially."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.weight_restrict_decay`."] update_weight_restrict_decay { new: ::sp_weights::Weight }, #[codec(index = 8)] - #[doc = "Overwrite the maximum amount of weight any individual message may consume."] - #[doc = "Messages above this weight go into the overweight queue and may only be serviced explicitly."] - #[doc = ""] - #[doc = "- `origin`: Must pass `Root`."] - #[doc = "- `new`: Desired value for `QueueConfigData.xcmp_max_individual_weight`."] update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "Failed to send XCM message."] FailedToSend, #[codec(index = 1)] - #[doc = "Bad XCM origin."] BadXcmOrigin, #[codec(index = 2)] - #[doc = "Bad XCM data."] BadXcm, #[codec(index = 3)] - #[doc = "Bad overweight index."] BadOverweightIndex, #[codec(index = 4)] - #[doc = "Provided weight is possibly not enough to execute the message."] WeightOverLimit, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "Some XCM was executed ok."] Success { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, weight: ::sp_weights::Weight, }, #[codec(index = 1)] - #[doc = "Some XCM failed."] Fail { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, error: runtime_types::xcm::v3::traits::Error, weight: ::sp_weights::Weight, }, #[codec(index = 2)] - #[doc = "Bad XCM version used."] BadVersion { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, }, #[codec(index = 3)] - #[doc = "Bad XCM format used."] BadFormat { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, }, #[codec(index = 4)] - #[doc = "An HRMP message was sent to a sibling parachain."] XcmpMessageSent { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, }, #[codec(index = 5)] - #[doc = "An XCM exceeded the individual message weight budget."] OverweightEnqueued { sender: runtime_types::polkadot_parachain::primitives::Id, sent_at: ::core::primitive::u32, @@ -6533,13 +387,10 @@ pub mod api { required: ::sp_weights::Weight, }, #[codec(index = 6)] - #[doc = "An XCM from the overweight queue was executed with the given actual weight used."] OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct InboundChannelDetails { pub sender: runtime_types::polkadot_parachain::primitives::Id, pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, @@ -6548,18 +399,14 @@ pub mod api { runtime_types::polkadot_parachain::primitives::XcmpMessageFormat, )>, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum InboundState { #[codec(index = 0)] Ok, #[codec(index = 1)] Suspended, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct OutboundChannelDetails { pub recipient: runtime_types::polkadot_parachain::primitives::Id, pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, @@ -6567,18 +414,14 @@ pub mod api { pub first_index: ::core::primitive::u16, pub last_index: ::core::primitive::u16, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum OutboundState { #[codec(index = 0)] Ok, #[codec(index = 1)] Suspended, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct QueueConfigData { pub suspend_threshold: ::core::primitive::u32, pub drop_threshold: ::core::primitive::u32, @@ -6590,13 +433,9 @@ pub mod api { } pub mod cumulus_primitives_parachain_inherent { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct ParachainInherentData { pub validation_data: runtime_types::polkadot_primitives::v4::PersistedValidationData< @@ -6621,9 +460,7 @@ pub mod api { } pub mod finality_grandpa { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Commit<_0, _1, _2, _3> { pub target_hash: _0, pub target_number: _1, @@ -6631,16 +468,12 @@ pub mod api { runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, >, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Precommit<_0, _1> { pub target_hash: _0, pub target_number: _1, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct SignedPrecommit<_0, _1, _2, _3> { pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, pub signature: _2, @@ -6651,12 +484,7 @@ pub mod api { use super::runtime_types; pub mod dispatch { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum DispatchClass { #[codec(index = 0)] Normal, @@ -6665,35 +493,20 @@ pub mod api { #[codec(index = 2)] Mandatory, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct DispatchInfo { pub weight: ::sp_weights::Weight, pub class: runtime_types::frame_support::dispatch::DispatchClass, pub pays_fee: runtime_types::frame_support::dispatch::Pays, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Pays { #[codec(index = 0)] Yes, #[codec(index = 1)] No, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct PerDispatchClass<_0> { pub normal: _0, pub operational: _0, @@ -6706,12 +519,7 @@ pub mod api { use super::runtime_types; pub mod misc { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum BalanceStatus { #[codec(index = 0)] Free, @@ -6728,94 +536,49 @@ pub mod api { use super::runtime_types; pub mod check_genesis { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckGenesis; } pub mod check_mortality { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckMortality(pub ::sp_runtime::generic::Era); } pub mod check_non_zero_sender { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckNonZeroSender; } pub mod check_nonce { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); } pub mod check_spec_version { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckSpecVersion; } pub mod check_tx_version { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckTxVersion; } pub mod check_weight { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct CheckWeight; } } pub mod limits { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct BlockLength { pub max: runtime_types::frame_support::dispatch::PerDispatchClass< ::core::primitive::u32, >, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct BlockWeights { pub base_block: ::sp_weights::Weight, pub max_block: ::sp_weights::Weight, @@ -6823,12 +586,7 @@ pub mod api { runtime_types::frame_system::limits::WeightsPerClass, >, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct WeightsPerClass { pub base_extrinsic: ::sp_weights::Weight, pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, @@ -6838,37 +596,17 @@ pub mod api { } pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Make some on-chain remark."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(1)`"] remark { remark: ::std::vec::Vec<::core::primitive::u8> }, #[codec(index = 1)] - #[doc = "Set the number of pages in the WebAssembly environment's heap."] set_heap_pages { pages: ::core::primitive::u64 }, #[codec(index = 2)] - #[doc = "Set the new runtime code."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code`"] set_code { code: ::std::vec::Vec<::core::primitive::u8> }, #[codec(index = 3)] - #[doc = "Set the new runtime code without doing any checks of the given `code`."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(C)` where `C` length of `code`"] set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, #[codec(index = 4)] - #[doc = "Set some items of storage."] set_storage { items: ::std::vec::Vec<( ::std::vec::Vec<::core::primitive::u8>, @@ -6876,88 +614,52 @@ pub mod api { )>, }, #[codec(index = 5)] - #[doc = "Kill some items from storage."] kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, #[codec(index = 6)] - #[doc = "Kill all storage items with a key that starts with the given prefix."] - #[doc = ""] - #[doc = "**NOTE:** We rely on the Root origin to provide us the number of subkeys under"] - #[doc = "the prefix we are removing to accurately calculate the weight of this function."] kill_prefix { prefix: ::std::vec::Vec<::core::primitive::u8>, subkeys: ::core::primitive::u32, }, #[codec(index = 7)] - #[doc = "Make some on-chain remark and emit event."] remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Error for the System pallet"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "The name of specification does not match between the current runtime"] - #[doc = "and the new runtime."] InvalidSpecName, #[codec(index = 1)] - #[doc = "The specification version is not allowed to decrease between the current runtime"] - #[doc = "and the new runtime."] SpecVersionNeedsToIncrease, #[codec(index = 2)] - #[doc = "Failed to extract the runtime version from the new runtime."] - #[doc = ""] - #[doc = "Either calling `Core_version` or decoding `RuntimeVersion` failed."] FailedToExtractRuntimeVersion, #[codec(index = 3)] - #[doc = "Suicide called when the account has non-default composite data."] NonDefaultComposite, #[codec(index = 4)] - #[doc = "There is a non-zero reference count preventing the account from being purged."] NonZeroRefCount, #[codec(index = 5)] - #[doc = "The origin filter prevent the call to be dispatched."] CallFiltered, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Event for the System pallet."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "An extrinsic completed successfully."] ExtrinsicSuccess { dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, }, #[codec(index = 1)] - #[doc = "An extrinsic failed."] ExtrinsicFailed { dispatch_error: runtime_types::sp_runtime::DispatchError, dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, }, #[codec(index = 2)] - #[doc = "`:code` was updated."] CodeUpdated, #[codec(index = 3)] - #[doc = "A new account was created."] NewAccount { account: ::sp_core::crypto::AccountId32 }, #[codec(index = 4)] - #[doc = "An account was reaped."] KilledAccount { account: ::sp_core::crypto::AccountId32 }, #[codec(index = 5)] - #[doc = "On on-chain remark happened."] Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct AccountInfo<_0, _1> { pub nonce: _0, pub consumers: _0, @@ -6965,25 +667,19 @@ pub mod api { pub sufficients: _0, pub data: _1, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct EventRecord<_0, _1> { pub phase: runtime_types::frame_system::Phase, pub event: _0, pub topics: ::std::vec::Vec<_1>, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct LastRuntimeUpgradeInfo { #[codec(compact)] pub spec_version: ::core::primitive::u32, pub spec_name: ::std::string::String, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Phase { #[codec(index = 0)] ApplyExtrinsic(::core::primitive::u32), @@ -6997,34 +693,15 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Transfer some liquid free balance to another account."] - #[doc = ""] - #[doc = "`transfer_allow_death` will set the `FreeBalance` of the sender and receiver."] - #[doc = "If the sender's account is below the existential deposit as a result"] - #[doc = "of the transfer, the account will be reaped."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be `Signed` by the transactor."] transfer_allow_death { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] value: ::core::primitive::u128, }, #[codec(index = 1)] - #[doc = "Set the regular balance of a given account; it also takes a reserved balance but this"] - #[doc = "must be the same as the account's current reserved balance."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] - #[doc = ""] - #[doc = "WARNING: This call is DEPRECATED! Use `force_set_balance` instead."] set_balance_deprecated { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] @@ -7033,8 +710,6 @@ pub mod api { old_reserved: ::core::primitive::u128, }, #[codec(index = 2)] - #[doc = "Exactly as `transfer_allow_death`, except the origin must be root and the source account"] - #[doc = "may be specified."] force_transfer { source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -7042,162 +717,93 @@ pub mod api { value: ::core::primitive::u128, }, #[codec(index = 3)] - #[doc = "Same as the [`transfer_allow_death`] call, but with a check that the transfer will not"] - #[doc = "kill the origin account."] - #[doc = ""] - #[doc = "99% of the time you want [`transfer_allow_death`] instead."] - #[doc = ""] - #[doc = "[`transfer_allow_death`]: struct.Pallet.html#method.transfer"] transfer_keep_alive { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] value: ::core::primitive::u128, }, #[codec(index = 4)] - #[doc = "Transfer the entire transferable balance from the caller account."] - #[doc = ""] - #[doc = "NOTE: This function only attempts to transfer _transferable_ balances. This means that"] - #[doc = "any locked, reserved, or existential deposits (when `keep_alive` is `true`), will not be"] - #[doc = "transferred by this function. To ensure that this function results in a killed account,"] - #[doc = "you might need to prepare the account by removing any reference counters, storage"] - #[doc = "deposits, etc..."] - #[doc = ""] - #[doc = "The dispatch origin of this call must be Signed."] - #[doc = ""] - #[doc = "- `dest`: The recipient of the transfer."] - #[doc = "- `keep_alive`: A boolean to determine if the `transfer_all` operation should send all"] - #[doc = " of the funds the account has, causing the sender account to be killed (false), or"] - #[doc = " transfer everything except at least the existential deposit, which will guarantee to"] - #[doc = " keep the sender account alive (true)."] transfer_all { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, keep_alive: ::core::primitive::bool, }, #[codec(index = 5)] - #[doc = "Unreserve some balance from a user by force."] - #[doc = ""] - #[doc = "Can only be called by ROOT."] force_unreserve { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, amount: ::core::primitive::u128, }, #[codec(index = 6)] - #[doc = "Upgrade a specified account."] - #[doc = ""] - #[doc = "- `origin`: Must be `Signed`."] - #[doc = "- `who`: The account to be upgraded."] - #[doc = ""] - #[doc = "This will waive the transaction fee if at least all but 10% of the accounts needed to"] - #[doc = "be upgraded. (We let some not have to be upgraded just in order to allow for the"] - #[doc = "possibililty of churn)."] upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, #[codec(index = 7)] - #[doc = "Alias for `transfer_allow_death`, provided only for name-wise compatibility."] - #[doc = ""] - #[doc = "WARNING: DEPRECATED! Will be released in approximately 3 months."] transfer { dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] value: ::core::primitive::u128, }, #[codec(index = 8)] - #[doc = "Set the regular balance of a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call is `root`."] force_set_balance { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, #[codec(compact)] new_free: ::core::primitive::u128, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "Vesting balance too high to send value."] VestingBalance, #[codec(index = 1)] - #[doc = "Account liquidity restrictions prevent withdrawal."] LiquidityRestrictions, #[codec(index = 2)] - #[doc = "Balance too low to send value."] InsufficientBalance, #[codec(index = 3)] - #[doc = "Value too low to create account due to existential deposit."] ExistentialDeposit, #[codec(index = 4)] - #[doc = "Transfer/payment would kill account."] Expendability, #[codec(index = 5)] - #[doc = "A vesting schedule already exists for this account."] ExistingVestingSchedule, #[codec(index = 6)] - #[doc = "Beneficiary account must pre-exist."] DeadAccount, #[codec(index = 7)] - #[doc = "Number of named reserves exceed `MaxReserves`."] TooManyReserves, #[codec(index = 8)] - #[doc = "Number of holds exceed `MaxHolds`."] TooManyHolds, #[codec(index = 9)] - #[doc = "Number of freezes exceed `MaxFreezes`."] TooManyFreezes, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "An account was created with some free balance."] Endowed { account: ::sp_core::crypto::AccountId32, free_balance: ::core::primitive::u128, }, #[codec(index = 1)] - #[doc = "An account was removed whose balance was non-zero but below ExistentialDeposit,"] - #[doc = "resulting in an outright loss."] DustLost { account: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 2)] - #[doc = "Transfer succeeded."] Transfer { from: ::sp_core::crypto::AccountId32, to: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 3)] - #[doc = "A balance was set by root."] BalanceSet { who: ::sp_core::crypto::AccountId32, free: ::core::primitive::u128, }, #[codec(index = 4)] - #[doc = "Some balance was reserved (moved from free to reserved)."] Reserved { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 5)] - #[doc = "Some balance was unreserved (moved from reserved to free)."] Unreserved { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 6)] - #[doc = "Some balance was moved from the reserve of the first account to the second account."] - #[doc = "Final argument indicates the destination balance type."] ReserveRepatriated { from: ::sp_core::crypto::AccountId32, to: ::sp_core::crypto::AccountId32, @@ -7206,95 +812,72 @@ pub mod api { runtime_types::frame_support::traits::tokens::misc::BalanceStatus, }, #[codec(index = 7)] - #[doc = "Some amount was deposited (e.g. for transaction fees)."] Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, #[codec(index = 8)] - #[doc = "Some amount was withdrawn from the account (e.g. for transaction fees)."] Withdraw { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 9)] - #[doc = "Some amount was removed from the account (e.g. for misbehavior)."] Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, #[codec(index = 10)] - #[doc = "Some amount was minted into an account."] Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, #[codec(index = 11)] - #[doc = "Some amount was burned from an account."] Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, #[codec(index = 12)] - #[doc = "Some amount was suspended from an account (it can be restored later)."] Suspended { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 13)] - #[doc = "Some amount was restored into an account."] Restored { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128, }, #[codec(index = 14)] - #[doc = "An account was upgraded."] Upgraded { who: ::sp_core::crypto::AccountId32 }, #[codec(index = 15)] - #[doc = "Total issuance was increased by `amount`, creating a credit to be balanced."] Issued { amount: ::core::primitive::u128 }, #[codec(index = 16)] - #[doc = "Total issuance was decreased by `amount`, creating a debt to be balanced."] Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, } - } - pub mod types { - use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct AccountData<_0> { pub free: _0, pub reserved: _0, pub frozen: _0, pub flags: runtime_types::pallet_balances::types::ExtraFlags, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct BalanceLock<_0> { pub id: [::core::primitive::u8; 8usize], pub amount: _0, pub reasons: runtime_types::pallet_balances::types::Reasons, } #[derive( + :: codec :: Decode, + :: codec :: Encode, :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, Clone, Debug, )] pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct IdAmount<_0, _1> { pub id: _0, pub amount: _1, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Reasons { #[codec(index = 0)] Fee, @@ -7303,12 +886,7 @@ pub mod api { #[codec(index = 2)] All, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct ReserveData<_0, _1> { pub id: _0, pub amount: _1, @@ -7319,22 +897,9 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Verify a target header is finalized according to the given finality proof."] - #[doc = ""] - #[doc = "It will use the underlying storage pallet to fetch information about the current"] - #[doc = "authorities and best finalized header in order to verify that the header is finalized."] - #[doc = ""] - #[doc = "If successful in verification, it will write the target header to the underlying storage"] - #[doc = "pallet."] submit_finality_proof { finality_target: ::std::boxed::Box< ::sp_runtime::generic::Header< @@ -7350,15 +915,6 @@ pub mod api { >, }, #[codec(index = 1)] - #[doc = "Bootstrap the bridge pallet with an initial header and authority set from which to sync."] - #[doc = ""] - #[doc = "The initial configuration provided does not need to be the genesis header of the bridged"] - #[doc = "chain, it can be any arbitrary header. You can also provide the next scheduled set"] - #[doc = "change if it is already know."] - #[doc = ""] - #[doc = "This function is only allowed to be called from a trusted origin and writes to storage"] - #[doc = "with practically no checks in terms of the validity of the data. It is important that"] - #[doc = "you ensure that valid data is being passed in."] initialize { init_data: ::bp_header_chain::InitializationData< ::sp_runtime::generic::Header< @@ -7368,66 +924,34 @@ pub mod api { >, }, #[codec(index = 2)] - #[doc = "Change `PalletOwner`."] - #[doc = ""] - #[doc = "May only be called either by root, or by `PalletOwner`."] set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, #[codec(index = 3)] - #[doc = "Halt or resume all pallet operations."] - #[doc = ""] - #[doc = "May only be called either by root, or by `PalletOwner`."] set_operating_mode { operating_mode: runtime_types::bp_runtime::BasicOperatingMode, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "The given justification is invalid for the given header."] InvalidJustification, #[codec(index = 1)] - #[doc = "The authority set from the underlying header chain is invalid."] InvalidAuthoritySet, #[codec(index = 2)] - #[doc = "There are too many requests for the current window to handle."] - TooManyRequests, - #[codec(index = 3)] - #[doc = "The header being imported is older than the best finalized header known to the pallet."] OldHeader, - #[codec(index = 4)] - #[doc = "The scheduled authority set change found in the header is unsupported by the pallet."] - #[doc = ""] - #[doc = "This is the case for non-standard (e.g forced) authority set changes."] + #[codec(index = 3)] UnsupportedScheduledChange, - #[codec(index = 5)] - #[doc = "The pallet is not yet initialized."] + #[codec(index = 4)] NotInitialized, - #[codec(index = 6)] - #[doc = "The pallet has already been initialized."] + #[codec(index = 5)] AlreadyInitialized, - #[codec(index = 7)] - #[doc = "Too many authorities in the set."] + #[codec(index = 6)] TooManyAuthoritiesInSet, - #[codec(index = 8)] - #[doc = "Error generated by the `OwnedBridgeModule` trait."] + #[codec(index = 7)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "Best finalized chain header has been updated to the header with given number and hash."] UpdatedBestFinalizedHeader { number: ::core::primitive::u64, hash: ::bp_millau::MillauHash, @@ -7436,12 +960,7 @@ pub mod api { } pub mod storage_types { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct StoredAuthoritySet { pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( runtime_types::sp_consensus_grandpa::app::Public, @@ -7455,126 +974,68 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { - # [codec (index = 0)] # [doc = "Change `PalletOwner`."] # [doc = ""] # [doc = "May only be called either by root, or by `PalletOwner`."] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] # [doc = "Halt or resume all/some pallet operations."] # [doc = ""] # [doc = "May only be called either by root, or by `PalletOwner`."] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] # [doc = "Receive messages proof from bridged chain."] # [doc = ""] # [doc = "The weight of the call assumes that the transaction always brings outbound lane"] # [doc = "state update. Because of that, the submitter (relayer) has no benefit of not including"] # [doc = "this data in the transaction, so reward confirmations lags should be minimal."] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: bp_millau :: MillauHash > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] # [doc = "Receive messages delivery proof from bridged chain."] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: bp_millau :: MillauHash > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "Pallet is not in Normal operating mode."] NotOperatingNormally, #[codec(index = 1)] - #[doc = "The outbound lane is inactive."] InactiveOutboundLane, #[codec(index = 2)] - #[doc = "The message is too large to be sent over the bridge."] MessageIsTooLarge, #[codec(index = 3)] - #[doc = "Message has been treated as invalid by chain verifier."] MessageRejectedByChainVerifier, #[codec(index = 4)] - #[doc = "Message has been treated as invalid by lane verifier."] MessageRejectedByLaneVerifier, #[codec(index = 5)] - #[doc = "Submitter has failed to pay fee for delivering and dispatching messages."] FailedToWithdrawMessageFee, #[codec(index = 6)] - #[doc = "The transaction brings too many messages."] TooManyMessagesInTheProof, #[codec(index = 7)] - #[doc = "Invalid messages has been submitted."] InvalidMessagesProof, #[codec(index = 8)] - #[doc = "Invalid messages delivery proof has been submitted."] InvalidMessagesDeliveryProof, #[codec(index = 9)] - #[doc = "The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane)."] InvalidUnrewardedRelayers, #[codec(index = 10)] - #[doc = "The relayer has declared invalid unrewarded relayers state in the"] - #[doc = "`receive_messages_delivery_proof` call."] InvalidUnrewardedRelayersState, #[codec(index = 11)] - #[doc = "The cumulative dispatch weight, passed by relayer is not enough to cover dispatch"] - #[doc = "of all bundled messages."] InsufficientDispatchWeight, #[codec(index = 12)] - #[doc = "The message someone is trying to work with (i.e. increase fee) is not yet sent."] MessageIsNotYetSent, #[codec(index = 13)] - #[doc = "The number of actually confirmed messages is going to be larger than the number of"] - #[doc = "messages in the proof. This may mean that this or bridged chain storage is corrupted."] TryingToConfirmMoreMessagesThanExpected, #[codec(index = 14)] - #[doc = "Error generated by the `OwnedBridgeModule` trait."] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { - # [codec (index = 0)] # [doc = "Message has been accepted and is waiting to be delivered."] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] # [doc = "Messages have been received from the bridged chain."] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] # [doc = "Messages in the inclusive range have been delivered to the bridged chain."] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } } } pub mod pallet_bridge_relayers { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Claim accumulated rewards."] claim_rewards { rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "No reward can be claimed by given relayer."] NoRewardForRelayer, #[codec(index = 1)] - #[doc = "Reward payment procedure has failed."] FailedToPayReward, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "Reward has been paid to the relayer."] RewardPaid { relayer: ::sp_core::crypto::AccountId32, rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, @@ -7587,97 +1048,47 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] sudo { call: ::std::boxed::Box, }, #[codec(index = 1)] - #[doc = "Authenticates the sudo key and dispatches a function call with `Root` origin."] - #[doc = "This function does not check the weight of the call, and instead allows the"] - #[doc = "Sudo user to specify the weight of the call."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] sudo_unchecked_weight { call: ::std::boxed::Box, weight: ::sp_weights::Weight, }, #[codec(index = 2)] - #[doc = "Authenticates the current sudo key and sets the given AccountId (`new`) as the new sudo"] - #[doc = "key."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] set_key { new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, }, #[codec(index = 3)] - #[doc = "Authenticates the sudo key and dispatches a function call with `Signed` origin from"] - #[doc = "a given account."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be _Signed_."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- O(1)."] sudo_as { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, call: ::std::boxed::Box, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Error for the Sudo pallet"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "Sender must be the Sudo account"] RequireSudo, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "A sudo just took place. \\[result\\]"] Sudid { sudo_result: ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, }, #[codec(index = 1)] - #[doc = "The \\[sudoer\\] just switched identity; the old key is supplied if one existed."] KeyChanged { old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, }, #[codec(index = 2)] - #[doc = "A sudo just took place. \\[result\\]"] SudoAsDone { sudo_result: ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, @@ -7689,30 +1100,9 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] - #[doc = "Set the current time."] - #[doc = ""] - #[doc = "This call should be invoked exactly once per block. It will panic at the finalization"] - #[doc = "phase, if this call hasn't been invoked by that time."] - #[doc = ""] - #[doc = "The timestamp should be greater than the previous one by the amount specified by"] - #[doc = "`MinimumPeriod`."] - #[doc = ""] - #[doc = "The dispatch origin for this call must be `Inherent`."] - #[doc = ""] - #[doc = "## Complexity"] - #[doc = "- `O(1)` (Note that implementations of `OnTimestampSet` must also be `O(1)`)"] - #[doc = "- 1 storage read and 1 storage mutation (codec `O(1)`). (because of `DidUpdate::take` in"] - #[doc = " `on_finalize`)"] - #[doc = "- 1 event handler `on_timestamp_set`. Must be `O(1)`."] set { #[codec(compact)] now: ::core::primitive::u64, @@ -7724,17 +1114,9 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,"] - #[doc = "has been paid by `who`."] TransactionFeePaid { who: ::sp_core::crypto::AccountId32, actual_fee: ::core::primitive::u128, @@ -7742,13 +1124,9 @@ pub mod api { }, } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Releases { #[codec(index = 0)] V1Ancient, @@ -7760,13 +1138,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "Contains one variant per dispatchable that can be called by an extrinsic."] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Call { #[codec(index = 0)] send { @@ -7774,21 +1146,6 @@ pub mod api { message: ::std::boxed::Box, }, #[codec(index = 1)] - #[doc = "Teleport some assets from the local chain to some destination chain."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] - #[doc = "with all fees taken as needed from the asset."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] - #[doc = " `dest` side. May not be empty."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] teleport_assets { dest: ::std::boxed::Box, beneficiary: ::std::boxed::Box, @@ -7796,22 +1153,6 @@ pub mod api { fee_asset_item: ::core::primitive::u32, }, #[codec(index = 2)] - #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] - #[doc = "chain and forward a notification XCM."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`. The weight limit for fees is not provided and thus is unlimited,"] - #[doc = "with all fees taken as needed from the asset."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] - #[doc = " `dest` side."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] reserve_transfer_assets { dest: ::std::boxed::Box, beneficiary: ::std::boxed::Box, @@ -7819,79 +1160,29 @@ pub mod api { fee_asset_item: ::core::primitive::u32, }, #[codec(index = 3)] - #[doc = "Execute an XCM message from a local, signed, origin."] - #[doc = ""] - #[doc = "An event is deposited indicating whether `msg` could be executed completely or only"] - #[doc = "partially."] - #[doc = ""] - #[doc = "No more than `max_weight` will be used in its attempted execution. If this is less than the"] - #[doc = "maximum amount of weight that the message could take to be executed, then no execution"] - #[doc = "attempt will be made."] - #[doc = ""] - #[doc = "NOTE: A successful return to this does *not* imply that the `msg` was executed successfully"] - #[doc = "to completion; only that *some* of it was executed."] execute { message: ::std::boxed::Box, max_weight: ::sp_weights::Weight, }, #[codec(index = 4)] - #[doc = "Extoll that a particular destination can be communicated with through a particular"] - #[doc = "version of XCM."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `location`: The destination that is being described."] - #[doc = "- `xcm_version`: The latest version of XCM that `location` supports."] force_xcm_version { location: ::std::boxed::Box, xcm_version: ::core::primitive::u32, }, #[codec(index = 5)] - #[doc = "Set a safe XCM version (the version that XCM should be encoded with if the most recent"] - #[doc = "version a destination can accept is unknown)."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `maybe_xcm_version`: The default XCM encoding version, or `None` to disable."] force_default_xcm_version { maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, }, #[codec(index = 6)] - #[doc = "Ask a location to notify us regarding their XCM version and any changes to it."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `location`: The location to which we should subscribe for XCM version notifications."] force_subscribe_version_notify { location: ::std::boxed::Box, }, #[codec(index = 7)] - #[doc = "Require that a particular destination should no longer notify us regarding any XCM"] - #[doc = "version changes."] - #[doc = ""] - #[doc = "- `origin`: Must be Root."] - #[doc = "- `location`: The location to which we are currently subscribed for XCM version"] - #[doc = " notifications which we no longer desire."] force_unsubscribe_version_notify { location: ::std::boxed::Box, }, #[codec(index = 8)] - #[doc = "Transfer some assets from the local chain to the sovereign account of a destination"] - #[doc = "chain and forward a notification XCM."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] - #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] - #[doc = "at risk."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. This should include the assets used to pay the fee on the"] - #[doc = " `dest` side."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] - #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] limited_reserve_transfer_assets { dest: ::std::boxed::Box, beneficiary: ::std::boxed::Box, @@ -7900,23 +1191,6 @@ pub mod api { weight_limit: runtime_types::xcm::v3::WeightLimit, }, #[codec(index = 9)] - #[doc = "Teleport some assets from the local chain to some destination chain."] - #[doc = ""] - #[doc = "Fee payment on the destination side is made from the asset in the `assets` vector of"] - #[doc = "index `fee_asset_item`, up to enough to pay for `weight_limit` of weight. If more weight"] - #[doc = "is needed than `weight_limit`, then the operation will fail and the assets send may be"] - #[doc = "at risk."] - #[doc = ""] - #[doc = "- `origin`: Must be capable of withdrawing the `assets` and executing XCM."] - #[doc = "- `dest`: Destination context for the assets. Will typically be `X2(Parent, Parachain(..))` to send"] - #[doc = " from parachain to parachain, or `X1(Parachain(..))` to send from relay to parachain."] - #[doc = "- `beneficiary`: A beneficiary location for the assets in the context of `dest`. Will generally be"] - #[doc = " an `AccountId32` value."] - #[doc = "- `assets`: The assets to be withdrawn. The first item should be the currency used to to pay the fee on the"] - #[doc = " `dest` side. May not be empty."] - #[doc = "- `fee_asset_item`: The index into `assets` of the item which should be used to pay"] - #[doc = " fees."] - #[doc = "- `weight_limit`: The remote-side weight limit, if any, for the XCM fee purchase."] limited_teleport_assets { dest: ::std::boxed::Box, beneficiary: ::std::boxed::Box, @@ -7925,128 +1199,69 @@ pub mod api { weight_limit: runtime_types::xcm::v3::WeightLimit, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/main-docs/build/events-errors/)\n\t\t\tof this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] - #[doc = "The desired destination was unreachable, generally because there is a no way of routing"] - #[doc = "to it."] Unreachable, #[codec(index = 1)] - #[doc = "There was some other issue (i.e. not to do with routing) in sending the message. Perhaps"] - #[doc = "a lack of space for buffering the message."] SendFailure, #[codec(index = 2)] - #[doc = "The message execution fails the filter."] Filtered, #[codec(index = 3)] - #[doc = "The message's weight could not be determined."] UnweighableMessage, #[codec(index = 4)] - #[doc = "The destination `MultiLocation` provided cannot be inverted."] DestinationNotInvertible, #[codec(index = 5)] - #[doc = "The assets to be sent are empty."] Empty, #[codec(index = 6)] - #[doc = "Could not re-anchor the assets to declare the fees for the destination chain."] CannotReanchor, #[codec(index = 7)] - #[doc = "Too many assets have been attempted for transfer."] TooManyAssets, #[codec(index = 8)] - #[doc = "Origin is invalid for sending."] InvalidOrigin, #[codec(index = 9)] - #[doc = "The version of the `Versioned` value used is not able to be interpreted."] BadVersion, #[codec(index = 10)] - #[doc = "The given location could not be used (e.g. because it cannot be expressed in the"] - #[doc = "desired version of XCM)."] BadLocation, #[codec(index = 11)] - #[doc = "The referenced subscription could not be found."] NoSubscription, #[codec(index = 12)] - #[doc = "The location is invalid since it already has a subscription from us."] AlreadySubscribed, #[codec(index = 13)] - #[doc = "Invalid asset for the operation."] InvalidAsset, #[codec(index = 14)] - #[doc = "The owner does not own (all) of the asset that they wish to do the operation on."] LowBalance, #[codec(index = 15)] - #[doc = "The asset owner has too many locks on the asset."] TooManyLocks, #[codec(index = 16)] - #[doc = "The given account is not an identifiable sovereign account for any location."] AccountNotSovereign, #[codec(index = 17)] - #[doc = "The operation required fees to be paid which the initiator could not meet."] FeesNotMet, #[codec(index = 18)] - #[doc = "A remote lock with the corresponding data could not be found."] LockNotFound, #[codec(index = 19)] - #[doc = "The unlock operation cannot succeed because there are still users of the lock."] InUse, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] - #[doc = "\n\t\t\tThe [event](https://docs.substrate.io/main-docs/build/events-errors/) emitted\n\t\t\tby this pallet.\n\t\t\t"] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Event { #[codec(index = 0)] - #[doc = "Execution of an XCM message was attempted."] - #[doc = ""] - #[doc = "\\[ outcome \\]"] Attempted(runtime_types::xcm::v3::traits::Outcome), #[codec(index = 1)] - #[doc = "A XCM message was sent."] - #[doc = ""] - #[doc = "\\[ origin, destination, message \\]"] Sent( runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::v3::Xcm, ), #[codec(index = 2)] - #[doc = "Query response received which does not match a registered query. This may be because a"] - #[doc = "matching query was never registered, it may be because it is a duplicate response, or"] - #[doc = "because the query timed out."] - #[doc = ""] - #[doc = "\\[ origin location, id \\]"] UnexpectedResponse( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u64, ), #[codec(index = 3)] - #[doc = "Query response has been received and is ready for taking with `take_response`. There is"] - #[doc = "no registered notification call."] - #[doc = ""] - #[doc = "\\[ id, response \\]"] ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), #[codec(index = 4)] - #[doc = "Query response has been received and query is removed. The registered notification has"] - #[doc = "been dispatched and executed successfully."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index \\]"] Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), #[codec(index = 5)] - #[doc = "Query response has been received and query is removed. The registered notification could"] - #[doc = "not be dispatched because the dispatch weight is greater than the maximum weight"] - #[doc = "originally budgeted by this runtime for the query result."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index, actual weight, max budgeted weight \\]"] NotifyOverweight( ::core::primitive::u64, ::core::primitive::u8, @@ -8055,32 +1270,18 @@ pub mod api { ::sp_weights::Weight, ), #[codec(index = 6)] - #[doc = "Query response has been received and query is removed. There was a general error with"] - #[doc = "dispatching the notification call."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index \\]"] NotifyDispatchError( ::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8, ), #[codec(index = 7)] - #[doc = "Query response has been received and query is removed. The dispatch was unable to be"] - #[doc = "decoded into a `Call`; this might be due to dispatch function having a signature which"] - #[doc = "is not `(origin, QueryId, Response)`."] - #[doc = ""] - #[doc = "\\[ id, pallet index, call index \\]"] NotifyDecodeFailed( ::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8, ), #[codec(index = 8)] - #[doc = "Expected query response has been received but the origin location of the response does"] - #[doc = "not match that expected. The query remains registered for a later, valid, response to"] - #[doc = "be received and acted upon."] - #[doc = ""] - #[doc = "\\[ origin location, id, expected location \\]"] InvalidResponder( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u64, @@ -8089,92 +1290,46 @@ pub mod api { >, ), #[codec(index = 9)] - #[doc = "Expected query response has been received but the expected origin location placed in"] - #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] - #[doc = ""] - #[doc = "This is unexpected (since a location placed in storage in a previously executing"] - #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] - #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] - #[doc = "needed."] - #[doc = ""] - #[doc = "\\[ origin location, id \\]"] InvalidResponderVersion( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u64, ), #[codec(index = 10)] - #[doc = "Received query response has been read and removed."] - #[doc = ""] - #[doc = "\\[ id \\]"] ResponseTaken(::core::primitive::u64), #[codec(index = 11)] - #[doc = "Some assets have been placed in an asset trap."] - #[doc = ""] - #[doc = "\\[ hash, origin, assets \\]"] AssetsTrapped( ::subxt::utils::H256, runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::VersionedMultiAssets, ), #[codec(index = 12)] - #[doc = "An XCM version change notification message has been attempted to be sent."] - #[doc = ""] - #[doc = "The cost of sending it (borne by the chain) is included."] - #[doc = ""] - #[doc = "\\[ destination, result, cost \\]"] VersionChangeNotified( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u32, runtime_types::xcm::v3::multiasset::MultiAssets, ), #[codec(index = 13)] - #[doc = "The supported version of a location has been changed. This might be through an"] - #[doc = "automatic notification or a manual intervention."] - #[doc = ""] - #[doc = "\\[ location, XCM version \\]"] SupportedVersionChanged( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u32, ), #[codec(index = 14)] - #[doc = "A given location which had a version change subscription was dropped owing to an error"] - #[doc = "sending the notification to it."] - #[doc = ""] - #[doc = "\\[ location, query ID, error \\]"] NotifyTargetSendFail( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u64, runtime_types::xcm::v3::traits::Error, ), #[codec(index = 15)] - #[doc = "A given location which had a version change subscription was dropped owing to an error"] - #[doc = "migrating the location to our new XCM format."] - #[doc = ""] - #[doc = "\\[ location, query ID \\]"] NotifyTargetMigrationFail( runtime_types::xcm::VersionedMultiLocation, ::core::primitive::u64, ), #[codec(index = 16)] - #[doc = "Expected query response has been received but the expected querier location placed in"] - #[doc = "storage by this runtime previously cannot be decoded. The query remains registered."] - #[doc = ""] - #[doc = "This is unexpected (since a location placed in storage in a previously executing"] - #[doc = "runtime should be readable prior to query timeout) and dangerous since the possibly"] - #[doc = "valid response will be dropped. Manual governance intervention is probably going to be"] - #[doc = "needed."] - #[doc = ""] - #[doc = "\\[ origin location, id \\]"] InvalidQuerierVersion( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u64, ), #[codec(index = 17)] - #[doc = "Expected query response has been received but the querier location of the response does"] - #[doc = "not match the expected. The query remains registered for a later, valid, response to"] - #[doc = "be received and acted upon."] - #[doc = ""] - #[doc = "\\[ origin location, id, expected querier, maybe actual querier \\]"] InvalidQuerier( runtime_types::xcm::v3::multilocation::MultiLocation, ::core::primitive::u64, @@ -8184,42 +1339,26 @@ pub mod api { >, ), #[codec(index = 18)] - #[doc = "A remote has requested XCM version change notification from us and we have honored it."] - #[doc = "A version information message is sent to them and its cost is included."] - #[doc = ""] - #[doc = "\\[ destination location, cost \\]"] VersionNotifyStarted( runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::v3::multiasset::MultiAssets, ), #[codec(index = 19)] - #[doc = "We have requested that a remote chain sends us XCM version change notifications."] - #[doc = ""] - #[doc = "\\[ destination location, cost \\]"] VersionNotifyRequested( runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::v3::multiasset::MultiAssets, ), #[codec(index = 20)] - #[doc = "We have requested that a remote chain stops sending us XCM version change notifications."] - #[doc = ""] - #[doc = "\\[ destination location, cost \\]"] VersionNotifyUnrequested( runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::v3::multiasset::MultiAssets, ), #[codec(index = 21)] - #[doc = "Fees were paid from a location for an operation (often for using `SendXcm`)."] - #[doc = ""] - #[doc = "\\[ paying location, fees \\]"] FeesPaid( runtime_types::xcm::v3::multilocation::MultiLocation, runtime_types::xcm::v3::multiasset::MultiAssets, ), #[codec(index = 22)] - #[doc = "Some assets have been claimed from an asset trap"] - #[doc = ""] - #[doc = "\\[ hash, origin, assets \\]"] AssetsClaimed( ::subxt::utils::H256, runtime_types::xcm::v3::multilocation::MultiLocation, @@ -8230,23 +1369,17 @@ pub mod api { } pub mod polkadot_core_primitives { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct InboundDownwardMessage<_0> { pub sent_at: _0, pub msg: ::std::vec::Vec<::core::primitive::u8>, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct InboundHrmpMessage<_0> { pub sent_at: _0, pub data: ::std::vec::Vec<::core::primitive::u8>, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct OutboundHrmpMessage<_0> { pub recipient: _0, pub data: ::std::vec::Vec<::core::primitive::u8>, @@ -8256,27 +1389,17 @@ pub mod api { use super::runtime_types; pub mod primitives { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); #[derive( + :: codec :: Decode, + :: codec :: Encode, :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, Clone, Debug, )] pub struct Id(pub ::core::primitive::u32); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum XcmpMessageFormat { #[codec(index = 0)] ConcatenatedVersionedXcm, @@ -8291,12 +1414,7 @@ pub mod api { use super::runtime_types; pub mod v4 { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct AbridgedHostConfiguration { pub max_code_size: ::core::primitive::u32, pub max_head_data_size: ::core::primitive::u32, @@ -8308,12 +1426,7 @@ pub mod api { pub validation_upgrade_cooldown: ::core::primitive::u32, pub validation_upgrade_delay: ::core::primitive::u32, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct AbridgedHrmpChannel { pub max_capacity: ::core::primitive::u32, pub max_total_size: ::core::primitive::u32, @@ -8322,24 +1435,14 @@ pub mod api { pub total_size: ::core::primitive::u32, pub mqc_head: ::core::option::Option<::subxt::utils::H256>, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct PersistedValidationData<_0, _1> { pub parent_head: runtime_types::polkadot_parachain::primitives::HeadData, pub relay_parent_number: _1, pub relay_parent_storage_root: _0, pub max_pov_size: _1, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum UpgradeRestriction { #[codec(index = 0)] Present, @@ -8348,21 +1451,13 @@ pub mod api { } pub mod rialto_parachain_runtime { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct DummyBridgeRefundMillauMessages; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Runtime; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum RuntimeCall { #[codec(index = 0)] System(runtime_types::frame_system::pallet::Call), @@ -8389,9 +1484,7 @@ pub mod api { #[codec(index = 56)] BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Call), } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum RuntimeEvent { #[codec(index = 0)] System(runtime_types::frame_system::pallet::Event), @@ -8424,17 +1517,15 @@ pub mod api { pub mod fixed_point { use super::runtime_types; #[derive( + :: codec :: Decode, + :: codec :: Encode, :: subxt :: ext :: codec :: CompactAs, - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, Clone, Debug, )] pub struct FixedU128(pub ::core::primitive::u128); } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum ArithmeticError { #[codec(index = 0)] Underflow, @@ -8448,19 +1539,9 @@ pub mod api { use super::runtime_types; pub mod app { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); } } @@ -8468,39 +1549,19 @@ pub mod api { use super::runtime_types; pub mod ecdsa { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Signature(pub [::core::primitive::u8; 65usize]); } pub mod ed25519 { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Signature(pub [::core::primitive::u8; 64usize]); } pub mod sr25519 { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Signature(pub [::core::primitive::u8; 64usize]); } } @@ -8510,12 +1571,7 @@ pub mod api { use super::runtime_types; pub mod digest { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum DigestItem { #[codec(index = 6)] PreRuntime( @@ -8540,21 +1596,14 @@ pub mod api { } pub mod unchecked_extrinsic { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct UncheckedExtrinsic<_0, _1, _2, _3>( pub ::std::vec::Vec<::core::primitive::u8>, #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, ); } } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum DispatchError { #[codec(index = 0)] Other, @@ -8583,16 +1632,12 @@ pub mod api { #[codec(index = 12)] Unavailable, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct ModuleError { pub index: ::core::primitive::u8, pub error: [::core::primitive::u8; 4usize], } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum MultiSignature { #[codec(index = 0)] Ed25519(runtime_types::sp_core::ed25519::Signature), @@ -8601,9 +1646,7 @@ pub mod api { #[codec(index = 2)] Ecdsa(runtime_types::sp_core::ecdsa::Signature), } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum TokenError { #[codec(index = 0)] FundsUnavailable, @@ -8624,9 +1667,7 @@ pub mod api { #[codec(index = 8)] NotExpendable, } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum TransactionalError { #[codec(index = 0)] LimitReached, @@ -8638,12 +1679,7 @@ pub mod api { use super::runtime_types; pub mod storage_proof { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct StorageProof { pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, } @@ -8651,9 +1687,7 @@ pub mod api { } pub mod sp_version { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct RuntimeVersion { pub spec_name: ::std::string::String, pub impl_name: ::std::string::String, @@ -8668,9 +1702,7 @@ pub mod api { } pub mod sp_weights { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct RuntimeDbWeight { pub read: ::core::primitive::u64, pub write: ::core::primitive::u64, @@ -8680,12 +1712,7 @@ pub mod api { use super::runtime_types; pub mod double_encoded { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct DoubleEncoded { pub encoded: ::std::vec::Vec<::core::primitive::u8>, } @@ -8694,12 +1721,7 @@ pub mod api { use super::runtime_types; pub mod junction { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Junction { #[codec(index = 0)] Parachain(#[codec(compact)] ::core::primitive::u32), @@ -8740,24 +1762,14 @@ pub mod api { } pub mod multiasset { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum AssetId { #[codec(index = 0)] Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 1)] Abstract(::std::vec::Vec<::core::primitive::u8>), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum AssetInstance { #[codec(index = 0)] Undefined, @@ -8774,67 +1786,37 @@ pub mod api { #[codec(index = 6)] Blob(::std::vec::Vec<::core::primitive::u8>), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Fungibility { #[codec(index = 0)] Fungible(#[codec(compact)] ::core::primitive::u128), #[codec(index = 1)] NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MultiAsset { pub id: runtime_types::xcm::v2::multiasset::AssetId, pub fun: runtime_types::xcm::v2::multiasset::Fungibility, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum MultiAssetFilter { #[codec(index = 0)] Definite(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 1)] Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MultiAssets( pub ::std::vec::Vec, ); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum WildFungibility { #[codec(index = 0)] Fungible, #[codec(index = 1)] NonFungible, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum WildMultiAsset { #[codec(index = 0)] All, @@ -8847,12 +1829,7 @@ pub mod api { } pub mod multilocation { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Junctions { #[codec(index = 0)] Here, @@ -8915,12 +1892,7 @@ pub mod api { runtime_types::xcm::v2::junction::Junction, ), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MultiLocation { pub parents: ::core::primitive::u8, pub interior: runtime_types::xcm::v2::multilocation::Junctions, @@ -8928,12 +1900,7 @@ pub mod api { } pub mod traits { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] Overflow, @@ -8989,12 +1956,7 @@ pub mod api { WeightNotComputable, } } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum BodyId { #[codec(index = 0)] Unit, @@ -9021,12 +1983,7 @@ pub mod api { #[codec(index = 9)] Treasury, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum BodyPart { #[codec(index = 0)] Voice, @@ -9057,12 +2014,7 @@ pub mod api { denom: ::core::primitive::u32, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Instruction { #[codec(index = 0)] WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), @@ -9202,12 +2154,7 @@ pub mod api { #[codec(index = 27)] UnsubscribeVersion, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum NetworkId { #[codec(index = 0)] Any, @@ -9222,12 +2169,7 @@ pub mod api { #[codec(index = 3)] Kusama, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum OriginKind { #[codec(index = 0)] Native, @@ -9238,12 +2180,7 @@ pub mod api { #[codec(index = 3)] Xcm, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Response { #[codec(index = 0)] Null, @@ -9259,36 +2196,21 @@ pub mod api { #[codec(index = 3)] Version(::core::primitive::u32), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum WeightLimit { #[codec(index = 0)] Unlimited, #[codec(index = 1)] Limited(#[codec(compact)] ::core::primitive::u64), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Xcm(pub ::std::vec::Vec); } pub mod v3 { use super::runtime_types; pub mod junction { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum BodyId { #[codec(index = 0)] Unit, @@ -9311,12 +2233,7 @@ pub mod api { #[codec(index = 9)] Treasury, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum BodyPart { #[codec(index = 0)] Voice, @@ -9347,12 +2264,7 @@ pub mod api { denom: ::core::primitive::u32, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Junction { #[codec(index = 0)] Parachain(#[codec(compact)] ::core::primitive::u32), @@ -9394,12 +2306,7 @@ pub mod api { #[codec(index = 9)] GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum NetworkId { #[codec(index = 0)] ByGenesis([::core::primitive::u8; 32usize]), @@ -9431,12 +2338,7 @@ pub mod api { } pub mod junctions { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Junctions { #[codec(index = 0)] Here, @@ -9502,24 +2404,14 @@ pub mod api { } pub mod multiasset { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum AssetId { #[codec(index = 0)] Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), #[codec(index = 1)] Abstract([::core::primitive::u8; 32usize]), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum AssetInstance { #[codec(index = 0)] Undefined, @@ -9534,67 +2426,37 @@ pub mod api { #[codec(index = 5)] Array32([::core::primitive::u8; 32usize]), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Fungibility { #[codec(index = 0)] Fungible(#[codec(compact)] ::core::primitive::u128), #[codec(index = 1)] NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MultiAsset { pub id: runtime_types::xcm::v3::multiasset::AssetId, pub fun: runtime_types::xcm::v3::multiasset::Fungibility, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum MultiAssetFilter { #[codec(index = 0)] Definite(runtime_types::xcm::v3::multiasset::MultiAssets), #[codec(index = 1)] Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MultiAssets( pub ::std::vec::Vec, ); - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum WildFungibility { #[codec(index = 0)] Fungible, #[codec(index = 1)] NonFungible, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum WildMultiAsset { #[codec(index = 0)] All, @@ -9616,12 +2478,7 @@ pub mod api { } pub mod multilocation { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct MultiLocation { pub parents: ::core::primitive::u8, pub interior: runtime_types::xcm::v3::junctions::Junctions, @@ -9629,12 +2486,7 @@ pub mod api { } pub mod traits { use super::runtime_types; - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Error { #[codec(index = 0)] Overflow, @@ -9717,12 +2569,7 @@ pub mod api { #[codec(index = 39)] ExceedsStackLimit, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Outcome { #[codec(index = 0)] Complete(::sp_weights::Weight), @@ -9732,12 +2579,7 @@ pub mod api { Error(runtime_types::xcm::v3::traits::Error), } } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Instruction { #[codec(index = 0)] WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), @@ -9946,12 +2788,7 @@ pub mod api { >, }, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum MaybeErrorCode { #[codec(index = 0)] Success, @@ -9968,12 +2805,7 @@ pub mod api { >, ), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct PalletInfo { #[codec(compact)] pub index: ::core::primitive::u32, @@ -9990,24 +2822,14 @@ pub mod api { #[codec(compact)] pub patch: ::core::primitive::u32, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct QueryResponseInfo { pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, #[codec(compact)] pub query_id: ::core::primitive::u64, pub max_weight: ::sp_weights::Weight, } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum Response { #[codec(index = 0)] Null, @@ -10031,47 +2853,31 @@ pub mod api { #[codec(index = 5)] DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum WeightLimit { #[codec(index = 0)] Unlimited, #[codec(index = 1)] Limited(::sp_weights::Weight), } - #[derive( - :: subxt :: ext :: codec :: Decode, - :: subxt :: ext :: codec :: Encode, - Clone, - Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub struct Xcm(pub ::std::vec::Vec); } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum VersionedMultiAssets { #[codec(index = 1)] V2(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 3)] V3(runtime_types::xcm::v3::multiasset::MultiAssets), } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum VersionedMultiLocation { #[codec(index = 1)] V2(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 3)] V3(runtime_types::xcm::v3::multilocation::MultiLocation), } - #[derive( - :: subxt :: ext :: codec :: Decode, :: subxt :: ext :: codec :: Encode, Clone, Debug, - )] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] pub enum VersionedXcm { #[codec(index = 2)] V2(runtime_types::xcm::v2::Xcm), @@ -10080,131 +2886,4 @@ pub mod api { } } } - #[doc = r" The default error type returned when there is a runtime issue,"] - #[doc = r" exposed here for ease of use."] - pub type DispatchError = runtime_types::sp_runtime::DispatchError; - pub fn constants() -> ConstantsApi { - ConstantsApi - } - pub fn storage() -> StorageApi { - StorageApi - } - pub fn tx() -> TransactionApi { - TransactionApi - } - pub struct ConstantsApi; - impl ConstantsApi { - pub fn system(&self) -> system::constants::ConstantsApi { - system::constants::ConstantsApi - } - pub fn timestamp(&self) -> timestamp::constants::ConstantsApi { - timestamp::constants::ConstantsApi - } - pub fn transaction_payment(&self) -> transaction_payment::constants::ConstantsApi { - transaction_payment::constants::ConstantsApi - } - pub fn balances(&self) -> balances::constants::ConstantsApi { - balances::constants::ConstantsApi - } - pub fn bridge_millau_grandpa(&self) -> bridge_millau_grandpa::constants::ConstantsApi { - bridge_millau_grandpa::constants::ConstantsApi - } - pub fn bridge_millau_messages(&self) -> bridge_millau_messages::constants::ConstantsApi { - bridge_millau_messages::constants::ConstantsApi - } - } - pub struct StorageApi; - impl StorageApi { - pub fn system(&self) -> system::storage::StorageApi { - system::storage::StorageApi - } - pub fn timestamp(&self) -> timestamp::storage::StorageApi { - timestamp::storage::StorageApi - } - pub fn sudo(&self) -> sudo::storage::StorageApi { - sudo::storage::StorageApi - } - pub fn transaction_payment(&self) -> transaction_payment::storage::StorageApi { - transaction_payment::storage::StorageApi - } - pub fn parachain_system(&self) -> parachain_system::storage::StorageApi { - parachain_system::storage::StorageApi - } - pub fn parachain_info(&self) -> parachain_info::storage::StorageApi { - parachain_info::storage::StorageApi - } - pub fn balances(&self) -> balances::storage::StorageApi { - balances::storage::StorageApi - } - pub fn xcmp_queue(&self) -> xcmp_queue::storage::StorageApi { - xcmp_queue::storage::StorageApi - } - pub fn dmp_queue(&self) -> dmp_queue::storage::StorageApi { - dmp_queue::storage::StorageApi - } - pub fn bridge_relayers(&self) -> bridge_relayers::storage::StorageApi { - bridge_relayers::storage::StorageApi - } - pub fn bridge_millau_grandpa(&self) -> bridge_millau_grandpa::storage::StorageApi { - bridge_millau_grandpa::storage::StorageApi - } - pub fn bridge_millau_messages(&self) -> bridge_millau_messages::storage::StorageApi { - bridge_millau_messages::storage::StorageApi - } - } - pub struct TransactionApi; - impl TransactionApi { - pub fn system(&self) -> system::calls::TransactionApi { - system::calls::TransactionApi - } - pub fn timestamp(&self) -> timestamp::calls::TransactionApi { - timestamp::calls::TransactionApi - } - pub fn sudo(&self) -> sudo::calls::TransactionApi { - sudo::calls::TransactionApi - } - pub fn parachain_system(&self) -> parachain_system::calls::TransactionApi { - parachain_system::calls::TransactionApi - } - pub fn balances(&self) -> balances::calls::TransactionApi { - balances::calls::TransactionApi - } - pub fn xcmp_queue(&self) -> xcmp_queue::calls::TransactionApi { - xcmp_queue::calls::TransactionApi - } - pub fn polkadot_xcm(&self) -> polkadot_xcm::calls::TransactionApi { - polkadot_xcm::calls::TransactionApi - } - pub fn cumulus_xcm(&self) -> cumulus_xcm::calls::TransactionApi { - cumulus_xcm::calls::TransactionApi - } - pub fn dmp_queue(&self) -> dmp_queue::calls::TransactionApi { - dmp_queue::calls::TransactionApi - } - pub fn bridge_relayers(&self) -> bridge_relayers::calls::TransactionApi { - bridge_relayers::calls::TransactionApi - } - pub fn bridge_millau_grandpa(&self) -> bridge_millau_grandpa::calls::TransactionApi { - bridge_millau_grandpa::calls::TransactionApi - } - pub fn bridge_millau_messages(&self) -> bridge_millau_messages::calls::TransactionApi { - bridge_millau_messages::calls::TransactionApi - } - } - #[doc = r" check whether the Client you are using is aligned with the statically generated codegen."] - pub fn validate_codegen>( - client: &C, - ) -> Result<(), ::subxt::error::MetadataError> { - let runtime_metadata_hash = client.metadata().metadata_hash(&PALLETS); - if runtime_metadata_hash != - [ - 244u8, 26u8, 245u8, 96u8, 241u8, 56u8, 22u8, 163u8, 219u8, 209u8, 103u8, 161u8, - 138u8, 242u8, 33u8, 114u8, 162u8, 107u8, 1u8, 216u8, 115u8, 116u8, 164u8, 126u8, - 81u8, 51u8, 88u8, 36u8, 180u8, 113u8, 18u8, 58u8, - ] { - Err(::subxt::error::MetadataError::IncompatibleMetadata) - } else { - Ok(()) - } - } } diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index ddb54fbefc06d..bb7be12979f20 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -61,8 +61,7 @@ impl Chain for RialtoParachain { impl ChainWithBalances for RialtoParachain { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - let key = codegen_runtime::api::storage().system().account(account_id); - StorageKey(key.to_bytes()) + bp_polkadot_core::AccountInfoStorageMapKeyProvider::final_key(account_id) } } From 4e5578a1aba1319aa3751ac227041f032776162a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 26 Apr 2023 12:46:11 +0300 Subject: [PATCH 1040/1210] Fixed off-by-one when confirming rewards in messages pallet (#2075) * fixed off-by-one when confirming rewards in messages pallet * Update modules/messages/src/inbound_lane.rs --- modules/messages/src/inbound_lane.rs | 34 ++++++++++++++++++++++++---- modules/messages/src/lib.rs | 29 +++++------------------- modules/messages/src/mock.rs | 22 +++++++++++++++--- 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 59ff566719586..fa6480d962fb4 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -153,7 +153,7 @@ impl InboundLane { // Note: There will be max. 1 record to update as we don't allow messages from relayers to // overlap. match data.relayers.front_mut() { - Some(entry) if entry.messages.begin < new_confirmed_nonce => { + Some(entry) if entry.messages.begin <= new_confirmed_nonce => { entry.messages.begin = new_confirmed_nonce + 1; }, _ => {}, @@ -221,12 +221,13 @@ mod tests { use crate::{ inbound_lane, mock::{ - dispatch_result, inbound_message_data, run_test, unrewarded_relayer, - TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, - TEST_RELAYER_B, TEST_RELAYER_C, + dispatch_result, inbound_message_data, inbound_unrewarded_relayers_state, run_test, + unrewarded_relayer, TestMessageDispatch, TestRuntime, REGULAR_PAYLOAD, TEST_LANE_ID, + TEST_RELAYER_A, TEST_RELAYER_B, TEST_RELAYER_C, }, RuntimeInboundLaneStorage, }; + use bp_messages::UnrewardedRelayersState; fn receive_regular_message( lane: &mut InboundLane>, @@ -545,4 +546,29 @@ mod tests { ); }); } + + #[test] + fn first_message_is_confirmed_correctly() { + run_test(|| { + let mut lane = inbound_lane::(TEST_LANE_ID); + receive_regular_message(&mut lane, 1); + receive_regular_message(&mut lane, 2); + assert_eq!( + lane.receive_state_update(OutboundLaneData { + latest_received_nonce: 1, + ..Default::default() + }), + Some(1), + ); + assert_eq!( + inbound_unrewarded_relayers_state(TEST_LANE_ID), + UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, + total_messages: 1, + last_delivered_nonce: 2, + }, + ); + }); + } } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index c94f5ffa752fa..6985b9018e701 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -949,12 +949,12 @@ fn verify_and_decode_messages_proof::reset_events(); } - fn inbound_unrewarded_relayers_state( - lane: bp_messages::LaneId, - ) -> bp_messages::UnrewardedRelayersState { - let inbound_lane_data = InboundLanes::::get(lane).0; - let last_delivered_nonce = inbound_lane_data.last_delivered_nonce(); - let relayers = inbound_lane_data.relayers; - bp_messages::UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), - last_delivered_nonce, - } - } - fn send_regular_message() { get_ready_for_events(); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 75f05b4820a8a..270222a1fd6ed 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -26,8 +26,8 @@ use bp_messages::{ DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, - DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, - OutboundLaneData, UnrewardedRelayer, + total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, + MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -142,7 +142,7 @@ impl pallet_balances::Config for TestRuntime { parameter_types! { pub const MaxMessagesToPruneAtOnce: u64 = 10; pub const MaxUnrewardedRelayerEntriesAtInboundLane: u64 = 16; - pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 32; + pub const MaxUnconfirmedMessagesAtInboundLane: u64 = 128; pub const TestBridgedChainId: bp_runtime::ChainId = *b"test"; pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID, TEST_LANE_ID_2]; } @@ -483,6 +483,22 @@ pub fn unrewarded_relayer( UnrewardedRelayer { relayer, messages: DeliveredMessages { begin, end } } } +/// Returns unrewarded relayers state at given lane. +pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> UnrewardedRelayersState { + let inbound_lane_data = crate::InboundLanes::::get(lane).0; + let last_delivered_nonce = inbound_lane_data.last_delivered_nonce(); + let relayers = inbound_lane_data.relayers; + UnrewardedRelayersState { + unrewarded_relayer_entries: relayers.len() as _, + messages_in_oldest_entry: relayers + .front() + .map(|entry| 1 + entry.messages.end - entry.messages.begin) + .unwrap_or(0), + total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), + last_delivered_nonce, + } +} + /// Return test externalities to use in tests. pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); From be915cb45e3f9f5a1921c23ba6ec5161e8cceaab Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 26 Apr 2023 14:42:53 +0300 Subject: [PATCH 1041/1210] Revert "Fix max-size messages at test chains (#2064)" (#2077) This reverts commit 864baf63f47b5e8b6275344fc39a395496ae81cc. --- bin/runtime-common/src/lib.rs | 14 --- relays/bin-substrate/Cargo.toml | 7 +- relays/bin-substrate/src/chains/millau.rs | 27 +----- relays/bin-substrate/src/chains/rialto.rs | 25 +---- .../src/chains/rialto_parachain.rs | 25 +---- .../bin-substrate/src/cli/encode_message.rs | 97 ++++++------------- 6 files changed, 33 insertions(+), 162 deletions(-) diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 12b096492cd48..e8a2d2470fa19 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -159,21 +159,7 @@ pub enum CustomNetworkId { RialtoParachain, } -impl TryFrom for CustomNetworkId { - type Error = (); - - fn try_from(chain: bp_runtime::ChainId) -> Result { - Ok(match chain { - bp_runtime::MILLAU_CHAIN_ID => Self::Millau, - bp_runtime::RIALTO_CHAIN_ID => Self::Rialto, - bp_runtime::RIALTO_PARACHAIN_CHAIN_ID => Self::RialtoParachain, - _ => return Err(()), - }) - } -} - impl CustomNetworkId { - /// Converts self to XCM' network id. pub const fn as_network_id(&self) -> NetworkId { match *self { CustomNetworkId::Millau => NetworkId::Kusama, diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 0a315035042a1..7853b9cb599ac 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -49,9 +49,6 @@ relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } -# we are not using this runtime to craft callsour transactions, but we still need it -# to prepare large XCM messages -rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies @@ -65,8 +62,8 @@ polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } + [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 9249958c286b5..44416195c6a44 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -17,36 +17,11 @@ //! Millau chain specification for CLI. use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::{ChainId, EncodedOrDecodedCall, RIALTO_CHAIN_ID, RIALTO_PARACHAIN_CHAIN_ID}; -use bridge_runtime_common::CustomNetworkId; +use bp_runtime::EncodedOrDecodedCall; use relay_millau_client::Millau; use relay_substrate_client::SimpleRuntimeVersion; -use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for Millau { - fn encode_wire_message( - target: ChainId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result> { - let target = match target { - RIALTO_CHAIN_ID => CustomNetworkId::Rialto.as_network_id(), - RIALTO_PARACHAIN_CHAIN_ID => CustomNetworkId::RialtoParachain.as_network_id(), - _ => return Err(anyhow::format_err!("Unsupported target chain: {:?}", target)), - }; - - Ok(millau_runtime::xcm_config::ToRialtoOrRialtoParachainSwitchExporter::validate( - target, - 0, - &mut Some(Self::dummy_universal_source()?), - &mut Some(target.into()), - &mut Some(at_target_xcm), - ) - .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? - .0 - .1 - .0) - } - fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index fb3003b30d71f..34a448ae4cb13 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -17,34 +17,11 @@ //! Rialto chain specification for CLI. use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::{ChainId, EncodedOrDecodedCall, MILLAU_CHAIN_ID}; -use bridge_runtime_common::CustomNetworkId; +use bp_runtime::EncodedOrDecodedCall; use relay_rialto_client::Rialto; use relay_substrate_client::SimpleRuntimeVersion; -use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for Rialto { - fn encode_wire_message( - target: ChainId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result> { - let target = match target { - MILLAU_CHAIN_ID => CustomNetworkId::Millau.as_network_id(), - _ => return Err(anyhow::format_err!("Unsupported target chian: {:?}", target)), - }; - - Ok(rialto_runtime::millau_messages::ToMillauBlobExporter::validate( - target, - 0, - &mut Some(Self::dummy_universal_source()?), - &mut Some(target.into()), - &mut Some(at_target_xcm), - ) - .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? - .0 - .0) - } - fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index f1de10b5c5f31..8ea2c1ffd433c 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -17,34 +17,11 @@ //! Rialto parachain specification for CLI. use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::{ChainId, EncodedOrDecodedCall, MILLAU_CHAIN_ID}; -use bridge_runtime_common::CustomNetworkId; +use bp_runtime::EncodedOrDecodedCall; use relay_rialto_parachain_client::RialtoParachain; use relay_substrate_client::SimpleRuntimeVersion; -use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for RialtoParachain { - fn encode_wire_message( - target: ChainId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result> { - let target = match target { - MILLAU_CHAIN_ID => CustomNetworkId::Millau.as_network_id(), - _ => return Err(anyhow::format_err!("Unsupported target chain: {:?}", target)), - }; - - Ok(rialto_parachain_runtime::millau_messages::ToMillauBlobExporter::validate( - target, - 0, - &mut Some(Self::dummy_universal_source()?), - &mut Some(target.into()), - &mut Some(at_target_xcm), - ) - .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? - .0 - .0) - } - fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 25231a970bfcb..9abf8b2df6dda 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -15,13 +15,11 @@ // along with Parity Bridges Common. If not, see . use crate::cli::{ExplicitOrMaximal, HexBytes}; -use bp_runtime::{ChainId, EncodedOrDecodedCall}; -use bridge_runtime_common::CustomNetworkId; +use bp_runtime::EncodedOrDecodedCall; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::Chain; use structopt::StructOpt; -use xcm::latest::prelude::*; /// All possible messages that may be delivered to generic Substrate chain. /// @@ -45,31 +43,6 @@ pub enum Message { pub type RawMessage = Vec; pub trait CliEncodeMessage: Chain { - /// Returns dummy `AccountId32` universal source given this network id. - fn dummy_universal_source() -> anyhow::Result { - use xcm::v3::prelude::*; - - let this_network = CustomNetworkId::try_from(Self::ID) - .map(|n| n.as_network_id()) - .map_err(|_| anyhow::format_err!("Unsupported chain: {:?}", Self::ID))?; - let this_location: InteriorMultiLocation = this_network.into(); - - let origin = MultiLocation { - parents: 0, - interior: X1(AccountId32 { network: Some(this_network), id: [0u8; 32] }), - }; - let universal_source = this_location - .within_global(origin) - .map_err(|e| anyhow::format_err!("Invalid location: {:?}", e))?; - - Ok(universal_source) - } - /// Returns XCM blob that is passed to the `send_message` function of the messages pallet - /// and then is sent over the wire. - fn encode_wire_message( - target: ChainId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result>; /// Encode an `execute` XCM call of the XCM pallet. fn encode_execute_xcm( message: xcm::VersionedXcm, @@ -83,42 +56,41 @@ pub trait CliEncodeMessage: Chain { } /// Encode message payload passed through CLI flags. -pub(crate) fn encode_message( +pub(crate) fn encode_message( message: &Message, ) -> anyhow::Result { Ok(match message { Message::Raw { ref data } => data.0.clone(), Message::Sized { ref size } => { - let destination = CustomNetworkId::try_from(Target::ID) - .map(|n| n.as_network_id()) - .map_err(|_| anyhow::format_err!("Unsupported target chain: {:?}", Target::ID))?; - let expected_size = match *size { + let expected_xcm_size = match *size { ExplicitOrMaximal::Explicit(size) => size, ExplicitOrMaximal::Maximal => compute_maximal_message_size( Source::max_extrinsic_size(), Target::max_extrinsic_size(), ), - } as usize; - - let at_target_xcm = vec![xcm::v3::Instruction::ClearOrigin; expected_size].into(); - let at_target_xcm_size = - Source::encode_wire_message(Target::ID, at_target_xcm)?.encoded_size(); - let at_target_xcm_overhead = at_target_xcm_size.saturating_sub(expected_size); - let at_target_xcm = vec![ - xcm::v3::Instruction::ClearOrigin; - expected_size.saturating_sub(at_target_xcm_overhead) - ] - .into(); - - xcm::VersionedXcm::<()>::V3( - vec![ExportMessage { - network: destination, - destination: destination.into(), - xcm: at_target_xcm, - }] - .into(), - ) - .encode() + }; + + // there's no way to craft XCM of the given size - we'll be using `ExpectPallet` + // instruction, which has byte vector inside + let mut current_vec_size = expected_xcm_size; + let xcm = loop { + let xcm = xcm::VersionedXcm::<()>::V3( + vec![xcm::v3::Instruction::ExpectPallet { + index: 0, + name: vec![42; current_vec_size as usize], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + }] + .into(), + ); + if xcm.encode().len() <= expected_xcm_size as usize { + break xcm + } + + current_vec_size -= 1; + }; + xcm.encode() }, }) } @@ -151,21 +123,13 @@ mod tests { use relay_millau_client::Millau; use relay_rialto_client::Rialto; - fn approximate_message_size(xcm_msg_len: usize) -> usize { - xcm_msg_len + Source::dummy_universal_source().unwrap().encoded_size() - } - #[test] fn encode_explicit_size_message_works() { let msg = encode_message::(&Message::Sized { size: ExplicitOrMaximal::Explicit(100), }) .unwrap(); - // since it isn't the returned XCM what is sent over the wire, we can only check if - // it is close to what we need - assert!( - (1f64 - (approximate_message_size::(msg.len()) as f64) / 100_f64).abs() < 0.1 - ); + assert_eq!(msg.len(), 100); // check that it decodes to valid xcm let _ = decode_xcm::<()>(msg).unwrap(); } @@ -180,12 +144,7 @@ mod tests { let msg = encode_message::(&Message::Sized { size: ExplicitOrMaximal::Maximal }) .unwrap(); - // since it isn't the returned XCM what is sent over the wire, we can only check if - // it is close to what we need - assert!( - (1f64 - approximate_message_size::(msg.len()) as f64 / maximal_size as f64) - .abs() < 0.1 - ); + assert_eq!(msg.len(), maximal_size as usize); // check that it decodes to valid xcm let _ = decode_xcm::<()>(msg).unwrap(); } From ac3b2b412edd8c424c44ae19eb7b76a06c8b1e8b Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 26 Apr 2023 21:36:48 +0200 Subject: [PATCH 1042/1210] Removed relayer_account: &AccountId from MessageDispatch (#2080) * SourceBridgeHubChain/TargetBridgeHubChain replaced with RelayerAccountChain * Fix * Removed `relayer_account: &AccountId` from `MessageDispatch` --- bin/millau/runtime/src/rialto_messages.rs | 2 - .../runtime/src/rialto_parachain_messages.rs | 2 - bin/millau/runtime/src/xcm_config.rs | 6 +- bin/rialto-parachain/runtime/src/lib.rs | 3 +- .../runtime/src/millau_messages.rs | 2 - bin/rialto/runtime/src/millau_messages.rs | 2 - bin/rialto/runtime/src/xcm_config.rs | 3 +- .../src/messages_xcm_extension.rs | 22 ++------ modules/grandpa/src/lib.rs | 6 +- modules/messages/src/inbound_lane.rs | 56 +++++++------------ modules/messages/src/lib.rs | 14 +---- modules/messages/src/mock.rs | 3 +- primitives/messages/src/target_chain.rs | 9 +-- 13 files changed, 39 insertions(+), 91 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 84535283d4847..573e3f5e68d0d 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -64,8 +64,6 @@ pub type ToRialtoMessagesDeliveryProof = /// Call-dispatch based message dispatch for Rialto -> Millau messages. pub type FromRialtoMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - bp_millau::Millau, - bp_rialto::Rialto, crate::xcm_config::OnMillauBlobDispatcher, (), >; diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index bef8a281188e8..041d3256f428a 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -59,8 +59,6 @@ pub type FromRialtoParachainMessagePayload = messages::target::FromBridgedChainM /// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. pub type FromRialtoParachainMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - bp_millau::Millau, - bp_rialto::Rialto, crate::xcm_config::OnMillauBlobDispatcher, (), >; diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 4aaec83771b04..cabb70f40cc9f 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -349,8 +349,7 @@ mod tests { // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = - FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, XcmBlobMessageDispatchResult::NotDispatched(_), @@ -363,8 +362,7 @@ mod tests { // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = - FromRialtoMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, XcmBlobMessageDispatchResult::NotDispatched(_), diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index cd5c45ec4ba9a..de8ca493520e8 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -926,8 +926,7 @@ mod tests { // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = - FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + let dispatch_result = FromMillauMessageDispatch::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, XcmBlobMessageDispatchResult::NotDispatched(_), diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 5d4a92b50916f..9c00e6bad348a 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -60,8 +60,6 @@ pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePay /// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. pub type FromMillauMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - bp_rialto_parachain::RialtoParachain, - bp_millau::Millau, crate::OnRialtoParachainBlobDispatcher, (), >; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index ab4b7dd521dab..7c960639f2fa6 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -57,8 +57,6 @@ pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePay /// Call-dispatch based message dispatch for Millau -> Rialto messages. pub type FromMillauMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - bp_rialto::Rialto, - bp_millau::Millau, crate::xcm_config::OnRialtoBlobDispatcher, (), >; diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 9f6488b4c4d31..52c5af635b374 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -266,8 +266,7 @@ mod tests { // we care only about handing message to the XCM dispatcher, so we don't care about its // actual dispatch - let dispatch_result = - FromMillauMessageDispatch::dispatch(&AccountId::from([0u8; 32]), incoming_message); + let dispatch_result = FromMillauMessageDispatch::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, XcmBlobMessageDispatchResult::NotDispatched(_), diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 4ccdd7a4b4df5..96fdf1d501826 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -26,7 +26,7 @@ use bp_messages::{ target_chain::{DispatchMessage, MessageDispatch}, LaneId, }; -use bp_runtime::{messages::MessageDispatchResult, AccountIdOf, Chain}; +use bp_runtime::messages::MessageDispatchResult; use codec::{Decode, Encode}; use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; use pallet_bridge_messages::WeightInfoExt as MessagesPalletWeights; @@ -46,23 +46,12 @@ pub enum XcmBlobMessageDispatchResult { } /// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages -pub struct XcmBlobMessageDispatch -{ - _marker: sp_std::marker::PhantomData<( - SourceBridgeHubChain, - TargetBridgeHubChain, - DispatchBlob, - Weights, - )>, +pub struct XcmBlobMessageDispatch { + _marker: sp_std::marker::PhantomData<(DispatchBlob, Weights)>, } -impl< - SourceBridgeHubChain: Chain, - TargetBridgeHubChain: Chain, - BlobDispatcher: DispatchBlob, - Weights: MessagesPalletWeights, - > MessageDispatch> - for XcmBlobMessageDispatch +impl MessageDispatch + for XcmBlobMessageDispatch { type DispatchPayload = XcmAsPlainPayload; type DispatchLevelResult = XcmBlobMessageDispatchResult; @@ -78,7 +67,6 @@ impl< } fn dispatch( - _relayer_account: &AccountIdOf, message: DispatchMessage, ) -> MessageDispatchResult { let payload = match message.data.payload { diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 9d38c9723d7ac..329e4c2113677 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -834,6 +834,7 @@ mod tests { run_test(|| { assert_eq!(BestFinalized::::get(), None,); assert_eq!(Pallet::::best_finalized(), None); + assert_eq!(PalletOperatingMode::::try_get(), Err(())); let init_data = init_with_origin(RuntimeOrigin::root()).unwrap(); @@ -843,7 +844,10 @@ mod tests { CurrentAuthoritySet::::get().authorities, init_data.authority_list ); - assert_eq!(PalletOperatingMode::::get(), BasicOperatingMode::Normal); + assert_eq!( + PalletOperatingMode::::try_get(), + Ok(BasicOperatingMode::Normal) + ); }) } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index fa6480d962fb4..5ec4444dbdfbe 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -164,10 +164,9 @@ impl InboundLane { } /// Receive new message. - pub fn receive_message, AccountId>( + pub fn receive_message( &mut self, relayer_at_bridged_chain: &S::Relayer, - relayer_at_this_chain: &AccountId, nonce: MessageNonce, message_data: DispatchMessageData, ) -> ReceivalResult { @@ -189,13 +188,10 @@ impl InboundLane { } // then, dispatch message - let dispatch_result = Dispatch::dispatch( - relayer_at_this_chain, - DispatchMessage { - key: MessageKey { lane_id: self.storage.id(), nonce }, - data: message_data, - }, - ); + let dispatch_result = Dispatch::dispatch(DispatchMessage { + key: MessageKey { lane_id: self.storage.id(), nonce }, + data: message_data, + }); // now let's update inbound lane storage match data.relayers.back_mut() { @@ -234,8 +230,7 @@ mod tests { nonce: MessageNonce, ) { assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, nonce, inbound_message_data(REGULAR_PAYLOAD) @@ -362,8 +357,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, 10, inbound_message_data(REGULAR_PAYLOAD) @@ -382,8 +376,7 @@ mod tests { ::MaxUnrewardedRelayerEntriesAtInboundLane::get(); for current_nonce in 1..max_nonce + 1 { assert_eq!( - lane.receive_message::( - &(TEST_RELAYER_A + current_nonce), + lane.receive_message::( &(TEST_RELAYER_A + current_nonce), current_nonce, inbound_message_data(REGULAR_PAYLOAD) @@ -393,8 +386,7 @@ mod tests { } // Fails to dispatch new message from different than latest relayer. assert_eq!( - lane.receive_message::( - &(TEST_RELAYER_A + max_nonce + 1), + lane.receive_message::( &(TEST_RELAYER_A + max_nonce + 1), max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) @@ -403,8 +395,7 @@ mod tests { ); // Fails to dispatch new messages from latest relayer. Prevents griefing attacks. assert_eq!( - lane.receive_message::( - &(TEST_RELAYER_A + max_nonce), + lane.receive_message::( &(TEST_RELAYER_A + max_nonce), max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) @@ -421,8 +412,7 @@ mod tests { let max_nonce = ::MaxUnconfirmedMessagesAtInboundLane::get(); for current_nonce in 1..=max_nonce { assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, current_nonce, inbound_message_data(REGULAR_PAYLOAD) @@ -432,8 +422,7 @@ mod tests { } // Fails to dispatch new message from different than latest relayer. assert_eq!( - lane.receive_message::( - &TEST_RELAYER_B, + lane.receive_message::( &TEST_RELAYER_B, max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) @@ -442,8 +431,7 @@ mod tests { ); // Fails to dispatch new messages from latest relayer. assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) @@ -458,8 +446,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, 1, inbound_message_data(REGULAR_PAYLOAD) @@ -467,8 +454,7 @@ mod tests { ReceivalResult::Dispatched(dispatch_result(0)) ); assert_eq!( - lane.receive_message::( - &TEST_RELAYER_B, + lane.receive_message::( &TEST_RELAYER_B, 2, inbound_message_data(REGULAR_PAYLOAD) @@ -476,8 +462,7 @@ mod tests { ReceivalResult::Dispatched(dispatch_result(0)) ); assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, 3, inbound_message_data(REGULAR_PAYLOAD) @@ -500,8 +485,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, 1, inbound_message_data(REGULAR_PAYLOAD) @@ -509,8 +493,7 @@ mod tests { ReceivalResult::Dispatched(dispatch_result(0)) ); assert_eq!( - lane.receive_message::( - &TEST_RELAYER_B, + lane.receive_message::( &TEST_RELAYER_B, 1, inbound_message_data(REGULAR_PAYLOAD) @@ -536,8 +519,7 @@ mod tests { let mut payload = REGULAR_PAYLOAD; *payload.dispatch_result.unspent_weight.ref_time_mut() = 1; assert_eq!( - lane.receive_message::( - &TEST_RELAYER_A, + lane.receive_message::( &TEST_RELAYER_A, 1, inbound_message_data(payload) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 6985b9018e701..8f4911b8d0327 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -162,10 +162,7 @@ pub mod pallet { /// Source header chain, as it is represented on target chain. type SourceHeaderChain: SourceHeaderChain; /// Message dispatch. - type MessageDispatch: MessageDispatch< - Self::AccountId, - DispatchPayload = Self::InboundPayload, - >; + type MessageDispatch: MessageDispatch; } /// Shortcut to messages proof type for Config. @@ -361,9 +358,8 @@ pub mod pallet { fail!(Error::::InsufficientDispatchWeight); } - let receival_result = lane.receive_message::( + let receival_result = lane.receive_message::( &relayer_id_at_bridged_chain, - &relayer_id_at_this_chain, message.key.nonce, message.data, ); @@ -545,11 +541,7 @@ pub mod pallet { MessageAccepted { lane_id: LaneId, nonce: MessageNonce }, /// Messages have been received from the bridged chain. MessagesReceived( - Vec< - ReceivedMessages< - >::DispatchLevelResult, - >, - >, + Vec::DispatchLevelResult>>, ), /// Messages in the inclusive range have been delivered to the bridged chain. MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages }, diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 270222a1fd6ed..3d78ab562d21c 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -416,7 +416,7 @@ impl SourceHeaderChain for TestSourceHeaderChain { #[derive(Debug)] pub struct TestMessageDispatch; -impl MessageDispatch for TestMessageDispatch { +impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; type DispatchLevelResult = TestDispatchLevelResult; @@ -428,7 +428,6 @@ impl MessageDispatch for TestMessageDispatch { } fn dispatch( - _relayer_account: &AccountId, message: DispatchMessage, ) -> MessageDispatchResult { match message.data.payload.as_ref() { diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 8496b90214c40..3c2e8cf0cb074 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -83,7 +83,7 @@ pub trait SourceHeaderChain { } /// Called when inbound message is received. -pub trait MessageDispatch { +pub trait MessageDispatch { /// Decoded message payload type. Valid message may contain invalid payload. In this case /// message is delivered, but dispatch fails. Therefore, two separate types of payload /// (opaque `MessagePayload` used in delivery and this `DispatchPayload` used in dispatch). @@ -103,11 +103,7 @@ pub trait MessageDispatch { /// /// It is up to the implementers of this trait to determine whether the message /// is invalid (i.e. improperly encoded, has too large weight, ...) or not. - /// - /// If your configuration allows paying dispatch fee at the target chain, then - /// it must be paid inside this method to the `relayer_account`. fn dispatch( - relayer_account: &AccountId, message: DispatchMessage, ) -> MessageDispatchResult; } @@ -186,7 +182,7 @@ impl SourceHeaderChain } } -impl MessageDispatch +impl MessageDispatch for ForbidInboundMessages { type DispatchPayload = DispatchPayload; @@ -197,7 +193,6 @@ impl MessageDispatch, ) -> MessageDispatchResult { MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } From 664f8fdd76c91e4ca0b93adf48ff06c088a20e3a Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 27 Apr 2023 11:58:40 +0200 Subject: [PATCH 1043/1210] Nits (#2083) --- bin/runtime-common/Cargo.toml | 2 -- primitives/relayers/src/registration.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index e7cd39da90b12..3db4ae9abca6e 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -30,7 +30,6 @@ pallet-bridge-relayers = { path = "../../modules/relayers", default-features = f frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -63,7 +62,6 @@ std = [ "frame-system/std", "hash-db/std", "log/std", - "pallet-balances/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-parachains/std", diff --git a/primitives/relayers/src/registration.rs b/primitives/relayers/src/registration.rs index da64bdde3793c..7ab20844bdf93 100644 --- a/primitives/relayers/src/registration.rs +++ b/primitives/relayers/src/registration.rs @@ -21,7 +21,7 @@ //! required finality proofs). This extension boosts priority of message delivery //! transactions, based on the number of bundled messages. So transaction with more //! messages has larger priority than the transaction with less messages. -//! See [`bridge_runtime_common::priority_calculator`] for details; +//! See `bridge_runtime_common::priority_calculator` for details; //! //! This encourages relayers to include more messages to their delivery transactions. //! At the same time, we are not verifying storage proofs before boosting From 9c26f69cfe46aa4a754e77951875b68671954801 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 27 Apr 2023 13:18:20 +0300 Subject: [PATCH 1044/1210] Benchmarks for new relayers pallet calls (#2040) * slash relayer balance for invalid transactions * require some gap before unstake is possible * more clippy * log priority boost * add issue ref to TODO * fix typo * is_message_delivery_call -> is_receive_messages_proof_call * moved is_receive_messages_proof_call above * only slash relayers for priority transactions * benchmarks for new relayers pallet calls * generated weights * regenerated weights afer master merge * actually use weights --- bin/millau/runtime/src/lib.rs | 10 ++- modules/relayers/src/benchmarking.rs | 37 +++++++++- modules/relayers/src/lib.rs | 8 +- modules/relayers/src/mock.rs | 9 ++- modules/relayers/src/weights.rs | 106 ++++++++++++++++++++++++--- 5 files changed, 147 insertions(+), 23 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dccd75a5b0014..b717fd0a56cdc 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1108,16 +1108,20 @@ impl_runtime_apis! { } impl RelayersConfig for Runtime { - fn prepare_environment( + fn prepare_rewards_account( account_params: RewardsAccountParams, reward: Balance, ) { - use frame_support::traits::fungible::Mutate; let rewards_account = bp_relayers::PayRewardFromAccount::< Balances, AccountId >::rewards_account(account_params); - Balances::mint_into(&rewards_account, reward).unwrap(); + Self::deposit_account(rewards_account, reward); + } + + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); } } diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index a762a5693c26e..635de51f8acde 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -24,6 +24,7 @@ use bp_messages::LaneId; use bp_relayers::RewardsAccountOwner; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_system::RawOrigin; +use sp_runtime::traits::One; /// Reward amount that is (hopefully) is larger than existential deposit across all chains. const REWARD_AMOUNT: u32 = u32::MAX; @@ -34,7 +35,9 @@ pub struct Pallet(crate::Pallet); /// Trait that must be implemented by runtime. pub trait Config: crate::Config { /// Prepare environment for paying given reward for serving given lane. - fn prepare_environment(account_params: RewardsAccountParams, reward: Self::Reward); + fn prepare_rewards_account(account_params: RewardsAccountParams, reward: Self::Reward); + /// Give enough balance to given account. + fn deposit_account(account: Self::AccountId, balance: Self::Reward); } benchmarks! { @@ -46,7 +49,7 @@ benchmarks! { let relayer: T::AccountId = whitelisted_caller(); let reward = T::Reward::from(REWARD_AMOUNT); - T::prepare_environment(account_params, reward); + T::prepare_rewards_account(account_params, reward); RelayerRewards::::insert(&relayer, account_params, reward); }: _(RawOrigin::Signed(relayer), account_params) verify { @@ -55,5 +58,35 @@ benchmarks! { // also completed successfully } + // Benchmark `register` call. + register { + let relayer: T::AccountId = whitelisted_caller(); + let valid_till = frame_system::Pallet::::block_number() + .saturating_add(crate::Pallet::::required_registration_lease()) + .saturating_add(One::one()) + .saturating_add(One::one()); + + T::deposit_account(relayer.clone(), crate::Pallet::::required_stake()); + }: _(RawOrigin::Signed(relayer.clone()), valid_till) + verify { + assert!(crate::Pallet::::is_registration_active(&relayer)); + } + + // Benchmark `deregister` call. + deregister { + let relayer: T::AccountId = whitelisted_caller(); + let valid_till = frame_system::Pallet::::block_number() + .saturating_add(crate::Pallet::::required_registration_lease()) + .saturating_add(One::one()) + .saturating_add(One::one()); + T::deposit_account(relayer.clone(), crate::Pallet::::required_stake()); + crate::Pallet::::register(RawOrigin::Signed(relayer.clone()).into(), valid_till).unwrap(); + + frame_system::Pallet::::set_block_number(valid_till.saturating_add(One::one())); + }: _(RawOrigin::Signed(relayer.clone())) + verify { + assert!(!crate::Pallet::::is_registration_active(&relayer)); + } + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 14e44d30f89ef..fd0e82aab8db5 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -114,7 +114,7 @@ pub mod pallet { /// /// Registration allows relayer to get priority boost for its message delivery transactions. #[pallet::call_index(1)] - #[pallet::weight(Weight::zero())] // TODO: https://github.com/paritytech/parity-bridges-common/issues/2033 + #[pallet::weight(T::WeightInfo::register())] pub fn register(origin: OriginFor, valid_till: T::BlockNumber) -> DispatchResult { let relayer = ensure_signed(origin)?; @@ -175,7 +175,7 @@ pub mod pallet { /// After this call, message delivery transactions of the relayer won't get any priority /// boost. #[pallet::call_index(2)] - #[pallet::weight(Weight::zero())] // TODO: https://github.com/paritytech/parity-bridges-common/issues/2033 + #[pallet::weight(T::WeightInfo::deregister())] pub fn deregister(origin: OriginFor) -> DispatchResult { let relayer = ensure_signed(origin)?; @@ -326,7 +326,7 @@ pub mod pallet { } /// Return required registration lease. - fn required_registration_lease() -> T::BlockNumber { + pub(crate) fn required_registration_lease() -> T::BlockNumber { T::Reward { + pub(crate) fn required_stake() -> T::Reward { ::rewards_account( account_params, ); - Balances::mint_into(&rewards_account, reward).unwrap(); + Self::deposit_account(rewards_account, reward); + } + + fn deposit_account(account: Self::AccountId, balance: Self::Reward) { + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); } } diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 1f111aaf1367d..abfdd50019fee 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-02, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-04-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -51,6 +51,8 @@ use sp_std::marker::PhantomData; /// Weight functions needed for pallet_bridge_relayers. pub trait WeightInfo { fn claim_rewards() -> Weight; + fn register() -> Weight; + fn deregister() -> Weight; } /// Weights for `pallet_bridge_relayers` that are generated using one of the Bridge testnets. @@ -63,16 +65,57 @@ impl WeightInfo for BridgeWeight { /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) /// + /// Storage: Balances TotalIssuance (r:1 w:0) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) + /// /// Storage: System Account (r:1 w:1) /// - /// Proof: System Account (max_values: None, max_size: Some(96), added: 2571, mode: + /// Proof: System Account (max_values: None, max_size: Some(104), added: 2579, mode: /// MaxEncodedLen) fn claim_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `275` - // Estimated: `5111` - // Minimum execution time: 48_639 nanoseconds. - Weight::from_parts(49_600_000, 5111) + // Measured: `294` + // Estimated: `8592` + // Minimum execution time: 75_307 nanoseconds. + Weight::from_parts(76_564_000, 8592) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539, + /// mode: MaxEncodedLen) + /// + /// Storage: Balances Reserves (r:1 w:1) + /// + /// Proof: Balances Reserves (max_values: None, max_size: Some(849), added: 3324, mode: + /// MaxEncodedLen) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `87` + // Estimated: `7843` + // Minimum execution time: 38_270 nanoseconds. + Weight::from_parts(39_191_000, 7843) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539, + /// mode: MaxEncodedLen) + /// + /// Storage: Balances Reserves (r:1 w:1) + /// + /// Proof: Balances Reserves (max_values: None, max_size: Some(849), added: 3324, mode: + /// MaxEncodedLen) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `264` + // Estimated: `7843` + // Minimum execution time: 43_028 nanoseconds. + Weight::from_parts(44_098_000, 7843) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -85,16 +128,57 @@ impl WeightInfo for () { /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, /// mode: MaxEncodedLen) /// + /// Storage: Balances TotalIssuance (r:1 w:0) + /// + /// Proof: Balances TotalIssuance (max_values: Some(1), max_size: Some(8), added: 503, mode: + /// MaxEncodedLen) + /// /// Storage: System Account (r:1 w:1) /// - /// Proof: System Account (max_values: None, max_size: Some(96), added: 2571, mode: + /// Proof: System Account (max_values: None, max_size: Some(104), added: 2579, mode: /// MaxEncodedLen) fn claim_rewards() -> Weight { // Proof Size summary in bytes: - // Measured: `275` - // Estimated: `5111` - // Minimum execution time: 48_639 nanoseconds. - Weight::from_parts(49_600_000, 5111) + // Measured: `294` + // Estimated: `8592` + // Minimum execution time: 75_307 nanoseconds. + Weight::from_parts(76_564_000, 8592) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539, + /// mode: MaxEncodedLen) + /// + /// Storage: Balances Reserves (r:1 w:1) + /// + /// Proof: Balances Reserves (max_values: None, max_size: Some(849), added: 3324, mode: + /// MaxEncodedLen) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `87` + // Estimated: `7843` + // Minimum execution time: 38_270 nanoseconds. + Weight::from_parts(39_191_000, 7843) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539, + /// mode: MaxEncodedLen) + /// + /// Storage: Balances Reserves (r:1 w:1) + /// + /// Proof: Balances Reserves (max_values: None, max_size: Some(849), added: 3324, mode: + /// MaxEncodedLen) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `264` + // Estimated: `7843` + // Minimum execution time: 43_028 nanoseconds. + Weight::from_parts(44_098_000, 7843) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } From c27797bb8b3f4379e6180e18a3f253e645262de0 Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 27 Apr 2023 19:07:31 +0800 Subject: [PATCH 1045/1210] Update comment (#2081) --- modules/messages/src/outbound_lane.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 33a58a40400bf..3d0d4de966a59 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -196,9 +196,6 @@ fn ensure_unrewarded_relayers_are_correct( // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { - // technically this will be detected in the next loop iteration as - // `InvalidNumberOfDispatchResults` but to guarantee safety of loop operations below - // this is detected now return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages) } } From 0702477c8614bd64ea83be0e8520f8c16340b29a Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 27 Apr 2023 15:04:57 +0300 Subject: [PATCH 1046/1210] Add more logs to relayer and message pallets (#2082) * add more logs * unused import * fmt --- modules/messages/src/lib.rs | 3 ++- modules/messages/src/mock.rs | 16 +++------------- modules/relayers/src/lib.rs | 2 ++ primitives/messages/src/lib.rs | 15 +++++++++++++++ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 8f4911b8d0327..045015b775125 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -329,9 +329,10 @@ pub mod pallet { if let Some(updated_latest_confirmed_nonce) = updated_latest_confirmed_nonce { log::trace!( target: LOG_TARGET, - "Received lane {:?} state update: latest_confirmed_nonce={}", + "Received lane {:?} state update: latest_confirmed_nonce={}. Unrewarded relayers: {:?}", lane_id, updated_latest_confirmed_nonce, + UnrewardedRelayersState::from(&lane.storage().data()), ); } } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 3d78ab562d21c..2e45d5b601f0b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -26,8 +26,8 @@ use bp_messages::{ DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, - total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, - MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, + DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, + OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -485,17 +485,7 @@ pub fn unrewarded_relayer( /// Returns unrewarded relayers state at given lane. pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> UnrewardedRelayersState { let inbound_lane_data = crate::InboundLanes::::get(lane).0; - let last_delivered_nonce = inbound_lane_data.last_delivered_nonce(); - let relayers = inbound_lane_data.relayers; - UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), - last_delivered_nonce, - } + UnrewardedRelayersState::from(&inbound_lane_data) } /// Return test externalities to use in tests. diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index fd0e82aab8db5..008c487836a3c 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -159,6 +159,7 @@ pub mod pallet { } registration.stake = required_stake; + log::trace!(target: LOG_TARGET, "Successfully registered relayer: {:?}", relayer); Self::deposit_event(Event::::RegistrationUpdated { relayer: relayer.clone(), registration, @@ -196,6 +197,7 @@ pub mod pallet { Self::do_unreserve(&relayer, registration.stake)?; } + log::trace!(target: LOG_TARGET, "Successfully deregistered relayer: {:?}", relayer); Self::deposit_event(Event::::Deregistered { relayer: relayer.clone() }); *maybe_registration = None; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 2828d5af00632..e485aa2f801c3 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -316,6 +316,21 @@ pub struct UnrewardedRelayersState { pub last_delivered_nonce: MessageNonce, } +impl From<&InboundLaneData> for UnrewardedRelayersState { + fn from(lane: &InboundLaneData) -> UnrewardedRelayersState { + UnrewardedRelayersState { + unrewarded_relayer_entries: lane.relayers.len() as _, + messages_in_oldest_entry: lane + .relayers + .front() + .and_then(|entry| (entry.messages.begin..=entry.messages.end).checked_len()) + .unwrap_or(0), + total_messages: total_unrewarded_messages(&lane.relayers).unwrap_or(MessageNonce::MAX), + last_delivered_nonce: lane.last_delivered_nonce(), + } + } +} + /// Outbound lane data. #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] pub struct OutboundLaneData { From 6631b4139690505b8f53a59bf29cf9d9dc7821e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 02:05:53 +0000 Subject: [PATCH 1047/1210] Bump scale-info from 2.5.0 to 2.6.0 Bumps [scale-info](https://github.com/paritytech/scale-info) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/paritytech/scale-info/releases) - [Changelog](https://github.com/paritytech/scale-info/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/scale-info/commits) --- updated-dependencies: - dependency-name: scale-info dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- relays/client-bridge-hub-kusama/Cargo.toml | 2 +- relays/client-bridge-hub-polkadot/Cargo.toml | 2 +- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index e1a55ea6f247e..4594c73fd9266 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.4" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 53f57e026199c..01c712a82eaff 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -12,7 +12,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} hex-literal = "0.4" -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge depedencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 2b68e72d6f8b2..f687905ad6349 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 3db4ae9abca6e..039e323b9b71e 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 8aff2c169b464..4270b96e208b2 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 07d2593b9145f..9b97b518fc5cd 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index f733d62bf6401..639ac9dc23ce6 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 39c3ba626aa09..d8c89b79991b8 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index c654c60d02bb5..857d47cc65a38 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 2d7dc272a6faf..1a14f230c6bcb 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 9039064fbf4f1..3316bc09d51b6 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index d1e2e0edd968c..7c5c5e11345f3 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -13,7 +13,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", optional = true } parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 5b9f87614a87f..e0349ebc9b9d4 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 32d7c65ebcbbb..32a89f6cf78f0 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index e47b8c5e68c70..426597a25086a 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index daae99ec71c1a..56c6de04d41c2 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 8ac3125848834..b84b0393adf1d 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.5.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 4d48ad61894d5..694ff4e1aa648 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Dependencies diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index 96650710f677d..f6e2c853a10de 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index 6126a8f2b3f1d..2b3ec0b6bad73 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 48df2e56cf088..5826a1321bc72 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index d4578fcd4887a..72a25b001e5bb 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index b6d5c423336eb..789e0622cfc83 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } -scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 90904ab9be11f..6d8b5ce2cb15f 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,7 +14,7 @@ jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.8" -scale-info = { version = "2.5.0", features = ["derive"] } +scale-info = { version = "2.6.0", features = ["derive"] } tokio = { version = "1.27", features = ["rt-multi-thread"] } thiserror = "1.0.40" From c67ef5aa8d6b65136f9fae1ada748bfcce05c3d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 02:04:06 +0000 Subject: [PATCH 1048/1210] Bump clap from 4.2.4 to 4.2.5 Bumps [clap](https://github.com/clap-rs/clap) from 4.2.4 to 4.2.5. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.2.4...v4.2.5) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 7eb7c79405be8..fd2096df5fa5f 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.4", features = ["derive"] } +clap = { version = "4.2.5", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.96" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 38521d7aa0e21..075e70c961ba8 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.2.4", features = ["derive"] } +clap = { version = "4.2.5", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index ffbb587dc1f57..36eaa7021a07e 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.4", features = ["derive"] } +clap = { version = "4.2.5", features = ["derive"] } serde_json = "1.0.96" # Bridge dependencies From bad6abe173dcf34e4be6ef23386cb3a7b5ceaafe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 05:43:46 +0000 Subject: [PATCH 1049/1210] Bump tokio from 1.27.0 to 1.28.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.27.0 to 1.28.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.27.0...tokio-1.28.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 6d8b5ce2cb15f..3dfeb9decbd1e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.17" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.6.0", features = ["derive"] } -tokio = { version = "1.27", features = ["rt-multi-thread"] } +tokio = { version = "1.28", features = ["rt-multi-thread"] } thiserror = "1.0.40" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index aa14e2ae2e353..78b7fd8fe97f1 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.28" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.27", features = ["rt"] } +tokio = { version = "1.28", features = ["rt"] } thiserror = "1.0.40" # Bridge dependencies From 00c78dcd1a6cfee6ff6734db520db4b0d08d3d47 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 May 2023 11:38:33 +0300 Subject: [PATCH 1050/1210] Add integrity tests to rialto parachain runtiime (#2096) * add integrity tests to rialto-parachain runtime * post cherry-pick fixes --- bin/rialto-parachain/runtime/Cargo.toml | 1 + .../runtime/src/millau_messages.rs | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 01c712a82eaff..d44f4b42af448 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -76,6 +76,7 @@ pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } +static_assertions = "1.1" [features] default = ['std'] diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 9c00e6bad348a..51db53c9c5b39 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -134,3 +134,64 @@ impl XcmBlobHauler for ToMillauXcmBlobHauler { XCM_LANE } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, + }, + }; + + #[test] + fn ensure_millau_message_lane_weights_are_correct() { + check_message_lane_weights::( + bp_millau::EXTRA_STORAGE_PROOF_SIZE, + bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: MillauGrandpaInstance, + with_bridged_chain_messages_instance: WithMillauMessagesInstance, + bridge: WithMillauMessageBridge, + this_chain: bp_rialto_parachain::RialtoParachain, + bridged_chain: bp_millau::Millau, + ); + + assert_complete_bridge_constants::< + Runtime, + MillauGrandpaInstance, + WithMillauMessagesInstance, + WithMillauMessageBridge, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_rialto_parachain::BlockLength::get(), + block_weights: bp_rialto_parachain::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::MILLAU_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: + bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, + }, + }); + } +} From ec1293bc84b829124b1099a9697d286b998fe5bc Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 May 2023 12:22:51 +0300 Subject: [PATCH 1051/1210] Add millau specific messages weights (#2097) * refactor weights a bit * post cherry-pick fixes * do not run spellcheck on new weight files * fix --- bin/millau/runtime/src/lib.rs | 57 ++---- bin/millau/runtime/src/rialto_messages.rs | 6 + .../runtime/src/rialto_parachain_messages.rs | 8 + bin/millau/runtime/src/weights/mod.rs | 21 ++ ...h_runtime_with_rialto_messages_instance.rs | 188 ++++++++++++++++++ ...with_rialto_parachain_messages_instance.rs | 188 ++++++++++++++++++ bin/rialto/runtime/src/millau_messages.rs | 2 +- modules/grandpa/src/weights.rs | 2 +- modules/messages/src/weights.rs | 2 +- modules/parachains/src/weights.rs | 2 +- modules/relayers/src/weights.rs | 2 +- 11 files changed, 438 insertions(+), 40 deletions(-) create mode 100644 bin/millau/runtime/src/weights/mod.rs create mode 100644 bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs create mode 100644 bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index b717fd0a56cdc..03fedd009347d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -30,6 +30,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod rialto_messages; pub mod rialto_parachain_messages; +pub mod weights; pub mod xcm_config; use bp_parachains::SingleParaStoredHeaderDataBuilder; @@ -442,7 +443,7 @@ pub type WithRialtoMessagesInstance = (); impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; + type WeightInfo = weights::RialtoMessagesWeightInfo; type ActiveOutboundLanes = RialtoActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -472,7 +473,7 @@ pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1 impl pallet_bridge_messages::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; + type WeightInfo = weights::RialtoParachainMessagesWeightInfo; type ActiveOutboundLanes = RialtoParachainActiveOutboundLanes; type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; @@ -598,7 +599,7 @@ generate_bridge_reject_obsolete_headers_and_messages! { bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); /// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. -pub type PriorityBoostPerMessage = ConstU64<921_900_294>; +pub type PriorityBoostPerMessage = ConstU64<699_683_285>; pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< Runtime, RefundableParachain, @@ -647,6 +648,17 @@ pub type Executive = frame_executive::Executive< AllPalletsWithSystem, >; +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [pallet_bridge_messages, MessagesBench::] + [pallet_bridge_messages, MessagesBench::] + [pallet_bridge_grandpa, BridgeRialtoGrandpa] + [pallet_bridge_parachains, ParachainsBench::] + [pallet_bridge_relayers, RelayersBench::] + ); +} + impl_runtime_apis! { impl sp_api::Core for Runtime { fn version() -> RuntimeVersion { @@ -954,7 +966,7 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{list_benchmark, Benchmarking, BenchmarkList}; + use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; @@ -962,22 +974,16 @@ impl_runtime_apis! { use pallet_bridge_relayers::benchmarking::Pallet as RelayersBench; let mut list = Vec::::new(); - - list_benchmark!(list, extra, RialtoParachainMessages, MessagesBench::); - list_benchmark!(list, extra, RialtoMessages, MessagesBench::); - list_benchmark!(list, extra, pallet_bridge_grandpa, BridgeRialtoGrandpa); - list_benchmark!(list, extra, pallet_bridge_parachains, ParachainsBench::); - list_benchmark!(list, extra, pallet_bridge_relayers, RelayersBench::); + list_benchmarks!(list, extra); let storage_info = AllPalletsWithSystem::storage_info(); - return (list, storage_info) } fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig, ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey, add_benchmark}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; let whitelist: Vec = vec![ // Block Number @@ -992,9 +998,6 @@ impl_runtime_apis! { hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), ]; - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - use bridge_runtime_common::messages_benchmarking::{ prepare_message_delivery_proof_from_grandpa_chain, prepare_message_delivery_proof_from_parachain, @@ -1125,26 +1128,10 @@ impl_runtime_apis! { } } - add_benchmark!( - params, - batches, - RialtoParachainMessages, - MessagesBench:: - ); - add_benchmark!( - params, - batches, - RialtoMessages, - MessagesBench:: - ); - add_benchmark!(params, batches, pallet_bridge_grandpa, BridgeRialtoGrandpa); - add_benchmark!( - params, - batches, - pallet_bridge_parachains, - ParachainsBench:: - ); - add_benchmark!(params, batches, pallet_bridge_relayers, RelayersBench::); + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + + add_benchmarks!(params, batches); Ok(batches) } diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 573e3f5e68d0d..0cd535351f88e 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -135,6 +135,12 @@ impl XcmBlobHauler for ToRialtoXcmBlobHauler { } } +impl pallet_bridge_messages::WeightInfoExt for crate::weights::RialtoMessagesWeightInfo { + fn expected_extra_storage_proof_size() -> u32 { + bp_rialto::EXTRA_STORAGE_PROOF_SIZE + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 041d3256f428a..7f91bd290b72b 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -136,6 +136,14 @@ impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { } } +impl pallet_bridge_messages::WeightInfoExt + for crate::weights::RialtoParachainMessagesWeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/bin/millau/runtime/src/weights/mod.rs b/bin/millau/runtime/src/weights/mod.rs new file mode 100644 index 0000000000000..801ff9b3c8f68 --- /dev/null +++ b/bin/millau/runtime/src/weights/mod.rs @@ -0,0 +1,21 @@ +// 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 . + +mod pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance; +mod pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance; + +pub use pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance::WeightInfo as RialtoMessagesWeightInfo; +pub use pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance::WeightInfo as RialtoParachainMessagesWeightInfo; diff --git a/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs b/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs new file mode 100644 index 0000000000000..b58402d275638 --- /dev/null +++ b/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs @@ -0,0 +1,188 @@ + +//! Autogenerated weights for `pallet_bridge_messages` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/millau-bridge-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_bridge_messages +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./bin/millau/runtime/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_messages`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_messages::WeightInfo for WeightInfo { + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `490` + // Estimated: `57170` + // Minimum execution time: 51_189_000 picoseconds. + Weight::from_parts(52_881_000, 0) + .saturating_add(Weight::from_parts(0, 57170)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_two_messages_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `490` + // Estimated: `57170` + // Minimum execution time: 65_083_000 picoseconds. + Weight::from_parts(66_878_000, 0) + .saturating_add(Weight::from_parts(0, 57170)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `490` + // Estimated: `57170` + // Minimum execution time: 57_919_000 picoseconds. + Weight::from_parts(58_927_000, 0) + .saturating_add(Weight::from_parts(0, 57170)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_1_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `490` + // Estimated: `57170` + // Minimum execution time: 52_202_000 picoseconds. + Weight::from_parts(53_617_000, 0) + .saturating_add(Weight::from_parts(0, 57170)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_16_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `490` + // Estimated: `57170` + // Minimum execution time: 74_726_000 picoseconds. + Weight::from_parts(76_379_000, 0) + .saturating_add(Weight::from_parts(0, 57170)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `515` + // Estimated: `9584` + // Minimum execution time: 45_156_000 picoseconds. + Weight::from_parts(46_535_000, 0) + .saturating_add(Weight::from_parts(0, 9584)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `532` + // Estimated: `9584` + // Minimum execution time: 44_104_000 picoseconds. + Weight::from_parts(45_602_000, 0) + .saturating_add(Weight::from_parts(0, 9584)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `532` + // Estimated: `12124` + // Minimum execution time: 46_880_000 picoseconds. + Weight::from_parts(48_472_000, 0) + .saturating_add(Weight::from_parts(0, 12124)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) + /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// The range of component `i` is `[128, 2048]`. + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `490` + // Estimated: `57170` + // Minimum execution time: 107_297_000 picoseconds. + Weight::from_parts(98_819_194, 0) + .saturating_add(Weight::from_parts(0, 57170)) + // Standard Error: 2_195 + .saturating_add(Weight::from_parts(448_268, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs b/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs new file mode 100644 index 0000000000000..c71cb11fdc717 --- /dev/null +++ b/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs @@ -0,0 +1,188 @@ + +//! Autogenerated weights for `pallet_bridge_messages` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/millau-bridge-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_bridge_messages +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./bin/millau/runtime/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_messages`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_messages::WeightInfo for WeightInfo { + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `428` + // Estimated: `56803` + // Minimum execution time: 49_949_000 picoseconds. + Weight::from_parts(51_439_000, 0) + .saturating_add(Weight::from_parts(0, 56803)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_two_messages_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `428` + // Estimated: `56803` + // Minimum execution time: 62_552_000 picoseconds. + Weight::from_parts(64_899_000, 0) + .saturating_add(Weight::from_parts(0, 56803)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `428` + // Estimated: `56803` + // Minimum execution time: 56_795_000 picoseconds. + Weight::from_parts(58_441_000, 0) + .saturating_add(Weight::from_parts(0, 56803)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_1_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `428` + // Estimated: `56803` + // Minimum execution time: 51_340_000 picoseconds. + Weight::from_parts(52_533_000, 0) + .saturating_add(Weight::from_parts(0, 56803)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_16_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `428` + // Estimated: `56803` + // Minimum execution time: 74_022_000 picoseconds. + Weight::from_parts(75_115_000, 0) + .saturating_add(Weight::from_parts(0, 56803)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `453` + // Estimated: `9217` + // Minimum execution time: 43_296_000 picoseconds. + Weight::from_parts(45_022_000, 0) + .saturating_add(Weight::from_parts(0, 9217)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `470` + // Estimated: `9217` + // Minimum execution time: 42_618_000 picoseconds. + Weight::from_parts(43_972_000, 0) + .saturating_add(Weight::from_parts(0, 9217)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `470` + // Estimated: `11757` + // Minimum execution time: 45_954_000 picoseconds. + Weight::from_parts(46_892_000, 0) + .saturating_add(Weight::from_parts(0, 11757)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) + /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) + /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) + /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// The range of component `i` is `[128, 2048]`. + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `428` + // Estimated: `56803` + // Minimum execution time: 107_766_000 picoseconds. + Weight::from_parts(97_865_035, 0) + .saturating_add(Weight::from_parts(0, 56803)) + // Standard Error: 2_179 + .saturating_add(Weight::from_parts(447_749, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 7c960639f2fa6..58f86148fbec0 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -149,7 +149,7 @@ mod tests { }; #[test] - fn ensure_rialto_message_lane_weights_are_correct() { + fn ensure_millau_message_lane_weights_are_correct() { check_message_lane_weights::( bp_millau::EXTRA_STORAGE_PROOF_SIZE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 089aee8b56951..4b94f7adfe73b 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -35,7 +35,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/grandpa/src/weights.rs -// --template=./.maintain/millau-weight-template.hbs +// --template=./.maintain/bridge-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index baaef317241ac..9880f1dd1ea3d 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -35,7 +35,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/messages/src/weights.rs -// --template=./.maintain/millau-weight-template.hbs +// --template=./.maintain/bridge-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 54a835cbc8738..1e81dba72fe99 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -35,7 +35,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/parachains/src/weights.rs -// --template=./.maintain/millau-weight-template.hbs +// --template=./.maintain/bridge-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index abfdd50019fee..a1f8fde1b0dd1 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -35,7 +35,7 @@ // --wasm-execution=Compiled // --heap-pages=4096 // --output=./modules/relayers/src/weights.rs -// --template=./.maintain/millau-weight-template.hbs +// --template=./.maintain/bridge-weight-template.hbs #![allow(clippy::all)] #![allow(unused_parens)] From 8d1069c87172a0479266a7d2647aa5665a6b7107 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 2 May 2023 14:55:07 +0300 Subject: [PATCH 1052/1210] Add weight of refund extension post_dispatch to the weights of messages pallet (#2089) * add weight of refund extension post_dispatch to the weights of messages pallet * fixed tests and removed TODO * verify runtime overhead weight in integrity tests * add integrity tests to rialto-parachain runtime * refactor weights a bit * refund ext is disabled for Rialto <> Millau bridge * Update bin/runtime-common/src/integrity.rs Co-authored-by: Adrian Catangiu * Update bin/runtime-common/src/integrity.rs Co-authored-by: Adrian Catangiu * Update modules/relayers/src/weights_ext.rs Co-authored-by: Adrian Catangiu --------- Co-authored-by: Adrian Catangiu --- bin/millau/runtime/src/lib.rs | 2 +- bin/millau/runtime/src/rialto_messages.rs | 10 ++ .../runtime/src/rialto_parachain_messages.rs | 10 ++ .../runtime/src/millau_messages.rs | 1 + bin/rialto/runtime/src/millau_messages.rs | 1 + bin/runtime-common/src/integrity.rs | 32 +++++- .../src/refund_relayer_extension.rs | 47 +++++--- modules/messages/src/weights_ext.rs | 43 ++++++++ modules/relayers/src/benchmarking.rs | 39 +++++++ modules/relayers/src/lib.rs | 4 +- modules/relayers/src/weights.rs | 100 +++++++++++++++--- modules/relayers/src/weights_ext.rs | 49 +++++++++ 12 files changed, 308 insertions(+), 30 deletions(-) create mode 100644 modules/relayers/src/weights_ext.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 03fedd009347d..60732339cf106 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -599,7 +599,7 @@ generate_bridge_reject_obsolete_headers_and_messages! { bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); /// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. -pub type PriorityBoostPerMessage = ConstU64<699_683_285>; +pub type PriorityBoostPerMessage = ConstU64<324_316_715>; pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< Runtime, RefundableParachain, diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 0cd535351f88e..b71eb76d90a6c 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -26,6 +26,7 @@ use bridge_runtime_common::{ messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use pallet_bridge_relayers::WeightInfoExt as _; use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; @@ -139,6 +140,14 @@ impl pallet_bridge_messages::WeightInfoExt for crate::weights::RialtoMessagesWei fn expected_extra_storage_proof_size() -> u32 { bp_rialto::EXTRA_STORAGE_PROOF_SIZE } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_proof_overhead_from_runtime() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_delivery_proof_overhead_from_runtime() + } } #[cfg(test)] @@ -161,6 +170,7 @@ mod tests { bp_rialto::EXTRA_STORAGE_PROOF_SIZE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + false, ); } diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 7f91bd290b72b..8d5216d96c939 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -28,6 +28,7 @@ use bridge_runtime_common::{ messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use pallet_bridge_relayers::WeightInfoExt as _; use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; @@ -142,6 +143,14 @@ impl pallet_bridge_messages::WeightInfoExt fn expected_extra_storage_proof_size() -> u32 { bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_proof_overhead_from_runtime() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_delivery_proof_overhead_from_runtime() + } } #[cfg(test)] @@ -167,6 +176,7 @@ mod tests { bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, ); } diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 51db53c9c5b39..3c523ebfa1245 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -154,6 +154,7 @@ mod tests { bp_millau::EXTRA_STORAGE_PROOF_SIZE, bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + false, ); } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 58f86148fbec0..a7d1d19f0d8d8 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -154,6 +154,7 @@ mod tests { bp_millau::EXTRA_STORAGE_PROOF_SIZE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + false, ); } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 5820dd99b91ca..bf3d239eefd64 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -24,8 +24,9 @@ use crate::{messages, messages::MessageBridge}; use bp_messages::{InboundLaneData, MessageNonce}; use bp_runtime::{Chain, ChainId}; use codec::Encode; -use frame_support::{storage::generator::StorageValue, traits::Get}; +use frame_support::{storage::generator::StorageValue, traits::Get, weights::Weight}; use frame_system::limits; +use pallet_bridge_messages::WeightInfoExt as _; use sp_runtime::traits::SignedExtension; /// Macro that ensures that the runtime configuration and chain primitives crate are sharing @@ -289,15 +290,25 @@ where } /// Check that the message lane weights are correct. -pub fn check_message_lane_weights( +pub fn check_message_lane_weights< + C: Chain, + T: frame_system::Config + pallet_bridge_messages::Config, +>( bridged_chain_extra_storage_proof_size: u32, this_chain_max_unrewarded_relayers: MessageNonce, this_chain_max_unconfirmed_messages: MessageNonce, + // whether `RefundBridgedParachainMessages` extension is deployed at runtime and is used for + // refunding this bridge transactions? + // + // in other words: pass true for all known production chains + runtime_includes_refund_extension: bool, ) { - type Weights = pallet_bridge_messages::weights::BridgeWeight; + type Weights = ::WeightInfo; + // check basic weight assumptions pallet_bridge_messages::ensure_weights_are_correct::>(); + // check that weights allow us to receive messages let max_incoming_message_proof_size = bridged_chain_extra_storage_proof_size .saturating_add(messages::target::maximal_incoming_message_size(C::max_extrinsic_size())); pallet_bridge_messages::ensure_able_to_receive_message::>( @@ -307,6 +318,7 @@ pub fn check_message_lane_weights( messages::target::maximal_incoming_message_dispatch_weight(C::max_extrinsic_weight()), ); + // check that weights allow us to receive delivery confirmations let max_incoming_inbound_lane_data_proof_size = InboundLaneData::<()>::encoded_size_hint_u32(this_chain_max_unrewarded_relayers as _); pallet_bridge_messages::ensure_able_to_receive_confirmation::>( @@ -316,6 +328,20 @@ pub fn check_message_lane_weights( this_chain_max_unrewarded_relayers, this_chain_max_unconfirmed_messages, ); + + // check that extra weights of delivery/confirmation transactions include the weight + // of `RefundBridgedParachainMessages` operations. This signed extension assumes the worst case + // (i.e. slashing if delivery transaction was invalid) and refunds some weight if + // assumption was wrong (i.e. if we did refund instead of slashing). This check + // ensures the extension will not refund weight when it doesn't need to (i.e. if pallet + // weights do not account weights of refund extension). + if runtime_includes_refund_extension { + assert_ne!(Weights::::receive_messages_proof_overhead_from_runtime(), Weight::zero()); + assert_ne!( + Weights::::receive_messages_delivery_proof_overhead_from_runtime(), + Weight::zero() + ); + } } /// Check that the `AdditionalSigned` type of a wrapped runtime is the same as the one of the diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 7d65263e9fd06..00ea70aa04eac 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -40,7 +40,9 @@ use pallet_bridge_parachains::{ BoundedBridgeGrandpaConfig, CallSubType as ParachainsCallSubType, Config as ParachainsConfig, RelayBlockNumber, SubmitParachainHeadsHelper, SubmitParachainHeadsInfo, }; -use pallet_bridge_relayers::{Config as RelayersConfig, Pallet as RelayersPallet}; +use pallet_bridge_relayers::{ + Config as RelayersConfig, Pallet as RelayersPallet, WeightInfoExt as _, +}; use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTransaction}; use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; @@ -445,11 +447,19 @@ where // decrease post-dispatch weight/size using extra weight/size that we know now let post_info_len = len.saturating_sub(extra_size as usize); - let mut post_info = *post_info; - post_info.actual_weight = - Some(post_info.actual_weight.unwrap_or(info.weight).saturating_sub(extra_weight)); + let mut post_info_weight = + post_info.actual_weight.unwrap_or(info.weight).saturating_sub(extra_weight); + + // let's also replace the weight of slashing relayer with the weight of rewarding relayer + if call_info.is_receive_messages_proof_call() { + post_info_weight = post_info_weight.saturating_sub( + ::WeightInfo::extra_weight_of_successful_receive_messages_proof_call(), + ); + } // compute the relayer refund + let mut post_info = *post_info; + post_info.actual_weight = Some(post_info_weight); let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); // we can finally reward relayer @@ -1052,7 +1062,20 @@ mod tests { assert_eq!(post_dispatch_result, Ok(())); } - fn expected_reward() -> ThisChainBalance { + fn expected_delivery_reward() -> ThisChainBalance { + let mut post_dispatch_info = post_dispatch_info(); + let extra_weight = ::WeightInfo::extra_weight_of_successful_receive_messages_proof_call(); + post_dispatch_info.actual_weight = + Some(dispatch_info().weight.saturating_sub(extra_weight)); + pallet_transaction_payment::Pallet::::compute_actual_fee( + 1024, + &dispatch_info(), + &post_dispatch_info, + Zero::zero(), + ) + } + + fn expected_confirmation_reward() -> ThisChainBalance { pallet_transaction_payment::Pallet::::compute_actual_fee( 1024, &dispatch_info(), @@ -1449,7 +1472,7 @@ mod tests { // without any size/weight refund: we expect regular reward let pre_dispatch_data = all_finality_pre_dispatch_data(); - let regular_reward = expected_reward(); + let regular_reward = expected_delivery_reward(); run_post_dispatch(Some(pre_dispatch_data), Ok(())); assert_eq!( RelayersPallet::::relayer_reward( @@ -1496,7 +1519,7 @@ mod tests { relayer_account_at_this_chain(), MsgProofsRewardsAccount::get() ), - Some(expected_reward()), + Some(expected_delivery_reward()), ); run_post_dispatch(Some(all_finality_confirmation_pre_dispatch_data()), Ok(())); @@ -1505,7 +1528,7 @@ mod tests { relayer_account_at_this_chain(), MsgDeliveryProofsRewardsAccount::get() ), - Some(expected_reward()), + Some(expected_confirmation_reward()), ); }); } @@ -1521,7 +1544,7 @@ mod tests { relayer_account_at_this_chain(), MsgProofsRewardsAccount::get() ), - Some(expected_reward()), + Some(expected_delivery_reward()), ); run_post_dispatch(Some(parachain_finality_confirmation_pre_dispatch_data()), Ok(())); @@ -1530,7 +1553,7 @@ mod tests { relayer_account_at_this_chain(), MsgDeliveryProofsRewardsAccount::get() ), - Some(expected_reward()), + Some(expected_confirmation_reward()), ); }); } @@ -1546,7 +1569,7 @@ mod tests { relayer_account_at_this_chain(), MsgProofsRewardsAccount::get() ), - Some(expected_reward()), + Some(expected_delivery_reward()), ); run_post_dispatch(Some(confirmation_pre_dispatch_data()), Ok(())); @@ -1555,7 +1578,7 @@ mod tests { relayer_account_at_this_chain(), MsgDeliveryProofsRewardsAccount::get() ), - Some(expected_reward()), + Some(expected_confirmation_reward()), ); }); } diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 090c03390ba36..3aefd6be7ca78 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -266,6 +266,27 @@ pub trait WeightInfoExt: WeightInfo { /// this value, we're going to charge relayer for that. fn expected_extra_storage_proof_size() -> u32; + // Our configuration assumes that the runtime has special signed extensions used to: + // + // 1) reject obsolete delivery and confirmation transactions; + // + // 2) refund transaction cost to relayer and register his rewards. + // + // The checks in (1) are trivial, so its computation weight may be ignored. And we only touch + // storage values that are read during the call. So we may ignore the weight of this check. + // + // However, during (2) we read and update storage values of other pallets + // (`pallet-bridge-relayers` and balances/assets pallet). So we need to add this weight to the + // weight of our call. Hence two following methods. + + /// Extra weight that is added to the `receive_messages_proof` call weight by signed extensions + /// that are declared at runtime level. + fn receive_messages_proof_overhead_from_runtime() -> Weight; + + /// Extra weight that is added to the `receive_messages_delivery_proof` call weight by signed + /// extensions that are declared at runtime level. + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight; + // Functions that are directly mapped to extrinsics weights. /// Weight of message delivery extrinsic. @@ -276,6 +297,8 @@ pub trait WeightInfoExt: WeightInfo { ) -> Weight { // basic components of extrinsic weight let transaction_overhead = Self::receive_messages_proof_overhead(); + let transaction_overhead_from_runtime = + Self::receive_messages_proof_overhead_from_runtime(); let outbound_state_delivery_weight = Self::receive_messages_proof_outbound_lane_state_overhead(); let messages_delivery_weight = @@ -292,6 +315,7 @@ pub trait WeightInfoExt: WeightInfo { ); transaction_overhead + .saturating_add(transaction_overhead_from_runtime) .saturating_add(outbound_state_delivery_weight) .saturating_add(messages_delivery_weight) .saturating_add(messages_dispatch_weight) @@ -305,6 +329,8 @@ pub trait WeightInfoExt: WeightInfo { ) -> Weight { // basic components of extrinsic weight let transaction_overhead = Self::receive_messages_delivery_proof_overhead(); + let transaction_overhead_from_runtime = + Self::receive_messages_delivery_proof_overhead_from_runtime(); let messages_overhead = Self::receive_messages_delivery_proof_messages_overhead(relayers_state.total_messages); let relayers_overhead = Self::receive_messages_delivery_proof_relayers_overhead( @@ -319,6 +345,7 @@ pub trait WeightInfoExt: WeightInfo { ); transaction_overhead + .saturating_add(transaction_overhead_from_runtime) .saturating_add(messages_overhead) .saturating_add(relayers_overhead) .saturating_add(proof_size_overhead) @@ -424,12 +451,28 @@ impl WeightInfoExt for () { fn expected_extra_storage_proof_size() -> u32 { EXTRA_STORAGE_PROOF_SIZE } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + Weight::zero() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + Weight::zero() + } } impl WeightInfoExt for crate::weights::BridgeWeight { fn expected_extra_storage_proof_size() -> u32 { EXTRA_STORAGE_PROOF_SIZE } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + Weight::zero() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + Weight::zero() + } } #[cfg(test)] diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index 635de51f8acde..d66a11ff06d02 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -88,5 +88,44 @@ benchmarks! { assert!(!crate::Pallet::::is_registration_active(&relayer)); } + // Benchmark `slash_and_deregister` method of the pallet. We are adding this weight to + // the weight of message delivery call if `RefundBridgedParachainMessages` signed extension + // is deployed at runtime level. + slash_and_deregister { + // prepare and register relayer account + let relayer: T::AccountId = whitelisted_caller(); + let valid_till = frame_system::Pallet::::block_number() + .saturating_add(crate::Pallet::::required_registration_lease()) + .saturating_add(One::one()) + .saturating_add(One::one()); + T::deposit_account(relayer.clone(), crate::Pallet::::required_stake()); + crate::Pallet::::register(RawOrigin::Signed(relayer.clone()).into(), valid_till).unwrap(); + + // create slash destination account + let lane = LaneId([0, 0, 0, 0]); + let slash_destination = RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain); + T::prepare_rewards_account(slash_destination.clone(), Zero::zero()); + }: { + crate::Pallet::::slash_and_deregister(&relayer, slash_destination) + } + verify { + assert!(!crate::Pallet::::is_registration_active(&relayer)); + } + + // Benchmark `register_relayer_reward` method of the pallet. We are adding this weight to + // the weight of message delivery call if `RefundBridgedParachainMessages` signed extension + // is deployed at runtime level. + register_relayer_reward { + let lane = LaneId([0, 0, 0, 0]); + let relayer: T::AccountId = whitelisted_caller(); + let account_params = + RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain); + }: { + crate::Pallet::::register_relayer_reward(account_params.clone(), &relayer, One::one()); + } + verify { + assert_eq!(RelayerRewards::::get(relayer, &account_params), Some(One::one())); + } + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::TestRuntime) } diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 008c487836a3c..54b888cf29dc9 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -33,12 +33,14 @@ pub use pallet::*; pub use payment_adapter::DeliveryConfirmationPaymentsAdapter; pub use stake_adapter::StakeAndSlashNamed; pub use weights::WeightInfo; +pub use weights_ext::WeightInfoExt; pub mod benchmarking; mod mock; mod payment_adapter; mod stake_adapter; +mod weights_ext; pub mod weights; @@ -66,7 +68,7 @@ pub mod pallet { /// Stake and slash scheme. type StakeAndSlash: StakeAndSlash; /// Pallet call weights. - type WeightInfo: WeightInfo; + type WeightInfo: WeightInfoExt; } #[pallet::pallet] diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index a1f8fde1b0dd1..1bc195a542472 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -17,7 +17,7 @@ //! Autogenerated weights for pallet_bridge_relayers //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-04-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` //! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 @@ -53,6 +53,8 @@ pub trait WeightInfo { fn claim_rewards() -> Weight; fn register() -> Weight; fn deregister() -> Weight; + fn slash_and_deregister() -> Weight; + fn register_relayer_reward() -> Weight; } /// Weights for `pallet_bridge_relayers` that are generated using one of the Bridge testnets. @@ -78,8 +80,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `294` // Estimated: `8592` - // Minimum execution time: 75_307 nanoseconds. - Weight::from_parts(76_564_000, 8592) + // Minimum execution time: 77_614 nanoseconds. + Weight::from_parts(79_987_000, 8592) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -96,8 +98,8 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `87` // Estimated: `7843` - // Minimum execution time: 38_270 nanoseconds. - Weight::from_parts(39_191_000, 7843) + // Minimum execution time: 39_590 nanoseconds. + Weight::from_parts(40_546_000, 7843) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -114,11 +116,47 @@ impl WeightInfo for BridgeWeight { // Proof Size summary in bytes: // Measured: `264` // Estimated: `7843` - // Minimum execution time: 43_028 nanoseconds. - Weight::from_parts(44_098_000, 7843) + // Minimum execution time: 43_332 nanoseconds. + Weight::from_parts(45_087_000, 7843) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539, + /// mode: MaxEncodedLen) + /// + /// Storage: Balances Reserves (r:1 w:1) + /// + /// Proof: Balances Reserves (max_values: None, max_size: Some(849), added: 3324, mode: + /// MaxEncodedLen) + /// + /// Storage: System Account (r:1 w:1) + /// + /// Proof: System Account (max_values: None, max_size: Some(104), added: 2579, mode: + /// MaxEncodedLen) + fn slash_and_deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `380` + // Estimated: `11412` + // Minimum execution time: 42_358 nanoseconds. + Weight::from_parts(43_539_000, 11412) + .saturating_add(T::DbWeight::get().reads(3_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, + /// mode: MaxEncodedLen) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `12` + // Estimated: `3530` + // Minimum execution time: 6_338 nanoseconds. + Weight::from_parts(6_526_000, 3530) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests @@ -141,8 +179,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `294` // Estimated: `8592` - // Minimum execution time: 75_307 nanoseconds. - Weight::from_parts(76_564_000, 8592) + // Minimum execution time: 77_614 nanoseconds. + Weight::from_parts(79_987_000, 8592) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -159,8 +197,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `87` // Estimated: `7843` - // Minimum execution time: 38_270 nanoseconds. - Weight::from_parts(39_191_000, 7843) + // Minimum execution time: 39_590 nanoseconds. + Weight::from_parts(40_546_000, 7843) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -177,9 +215,45 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `264` // Estimated: `7843` - // Minimum execution time: 43_028 nanoseconds. - Weight::from_parts(44_098_000, 7843) + // Minimum execution time: 43_332 nanoseconds. + Weight::from_parts(45_087_000, 7843) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(64), added: 2539, + /// mode: MaxEncodedLen) + /// + /// Storage: Balances Reserves (r:1 w:1) + /// + /// Proof: Balances Reserves (max_values: None, max_size: Some(849), added: 3324, mode: + /// MaxEncodedLen) + /// + /// Storage: System Account (r:1 w:1) + /// + /// Proof: System Account (max_values: None, max_size: Some(104), added: 2579, mode: + /// MaxEncodedLen) + fn slash_and_deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `380` + // Estimated: `11412` + // Minimum execution time: 42_358 nanoseconds. + Weight::from_parts(43_539_000, 11412) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, + /// mode: MaxEncodedLen) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `12` + // Estimated: `3530` + // Minimum execution time: 6_338 nanoseconds. + Weight::from_parts(6_526_000, 3530) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/modules/relayers/src/weights_ext.rs b/modules/relayers/src/weights_ext.rs new file mode 100644 index 0000000000000..d459b0686bd7e --- /dev/null +++ b/modules/relayers/src/weights_ext.rs @@ -0,0 +1,49 @@ +// 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 . + +//! Weight-related utilities. + +use crate::weights::WeightInfo; + +use frame_support::pallet_prelude::Weight; + +/// Extended weight info. +pub trait WeightInfoExt: WeightInfo { + /// Returns weight, that needs to be added to the pre-dispatch weight of message delivery call, + /// if `RefundBridgedParachainMessages` signed extension is deployed at runtime level. + fn receive_messages_proof_overhead_from_runtime() -> Weight { + Self::slash_and_deregister().max(Self::register_relayer_reward()) + } + + /// Returns weight, that needs to be added to the pre-dispatch weight of message delivery + /// confirmation call, if `RefundBridgedParachainMessages` signed extension is deployed at + /// runtime level. + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + Self::register_relayer_reward() + } + + /// Returns weight that we need to deduct from the message delivery call weight that has + /// completed successfully. + /// + /// Usually, the weight of `slash_and_deregister` is larger than the weight of the + /// `register_relayer_reward`. So if relayer has been rewarded, we want to deduct the difference + /// to get the actual post-dispatch weight. + fn extra_weight_of_successful_receive_messages_proof_call() -> Weight { + Self::slash_and_deregister().saturating_sub(Self::register_relayer_reward()) + } +} + +impl WeightInfoExt for T {} From a34ed4af8d70852b94720d8c506b6d69005cd9cb Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 3 May 2023 10:44:06 +0300 Subject: [PATCH 1053/1210] Fix sized messages (Follow-up on #2064) (#2103) * Use wasm execution on millau and rialto It's safer like this since here are some errors that aren't caught when using native execution * Revert "Revert "Fix max-size messages at test chains (#2064)" (#2077)" This reverts commit be915cb45e3f9f5a1921c23ba6ec5161e8cceaab. * Adjustments --- bin/runtime-common/src/lib.rs | 14 +++ relays/bin-substrate/Cargo.toml | 7 +- relays/bin-substrate/src/chains/millau.rs | 28 +++++ relays/bin-substrate/src/chains/rialto.rs | 23 ++++ .../src/chains/rialto_parachain.rs | 23 ++++ .../bin-substrate/src/cli/encode_message.rs | 102 ++++++++++++------ 6 files changed, 163 insertions(+), 34 deletions(-) diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index e8a2d2470fa19..12b096492cd48 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -159,7 +159,21 @@ pub enum CustomNetworkId { RialtoParachain, } +impl TryFrom for CustomNetworkId { + type Error = (); + + fn try_from(chain: bp_runtime::ChainId) -> Result { + Ok(match chain { + bp_runtime::MILLAU_CHAIN_ID => Self::Millau, + bp_runtime::RIALTO_CHAIN_ID => Self::Rialto, + bp_runtime::RIALTO_PARACHAIN_CHAIN_ID => Self::RialtoParachain, + _ => return Err(()), + }) + } +} + impl CustomNetworkId { + /// Converts self to XCM' network id. pub const fn as_network_id(&self) -> NetworkId { match *self { CustomNetworkId::Millau => NetworkId::Kusama, diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 7853b9cb599ac..0a315035042a1 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -49,6 +49,9 @@ relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } +# we are not using this runtime to craft callsour transactions, but we still need it +# to prepare large XCM messages +rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies @@ -62,8 +65,8 @@ polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } - +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 44416195c6a44..4cee26255d397 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -18,10 +18,38 @@ use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; +use bridge_runtime_common::CustomNetworkId; use relay_millau_client::Millau; use relay_substrate_client::SimpleRuntimeVersion; +use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for Millau { + fn encode_wire_message( + target: xcm::v3::NetworkId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result> { + anyhow::ensure!( + [ + CustomNetworkId::Rialto.as_network_id(), + CustomNetworkId::RialtoParachain.as_network_id() + ] + .contains(&target), + anyhow::format_err!("Unsupported target chain: {:?}", target) + ); + + Ok(millau_runtime::xcm_config::ToRialtoOrRialtoParachainSwitchExporter::validate( + target, + 0, + &mut Some(Self::dummy_universal_source()?), + &mut Some(target.into()), + &mut Some(at_target_xcm), + ) + .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? + .0 + .1 + .0) + } + fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs index 34a448ae4cb13..30bc7eb13ca99 100644 --- a/relays/bin-substrate/src/chains/rialto.rs +++ b/relays/bin-substrate/src/chains/rialto.rs @@ -18,10 +18,33 @@ use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; +use bridge_runtime_common::CustomNetworkId; use relay_rialto_client::Rialto; use relay_substrate_client::SimpleRuntimeVersion; +use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for Rialto { + fn encode_wire_message( + target: xcm::v3::NetworkId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result> { + anyhow::ensure!( + target == CustomNetworkId::Millau.as_network_id(), + anyhow::format_err!("Unsupported target chain: {:?}", target) + ); + + Ok(rialto_runtime::millau_messages::ToMillauBlobExporter::validate( + target, + 0, + &mut Some(Self::dummy_universal_source()?), + &mut Some(target.into()), + &mut Some(at_target_xcm), + ) + .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? + .0 + .0) + } + fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs index 8ea2c1ffd433c..872d96981d0bf 100644 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -18,10 +18,33 @@ use crate::cli::{encode_message::CliEncodeMessage, CliChain}; use bp_runtime::EncodedOrDecodedCall; +use bridge_runtime_common::CustomNetworkId; use relay_rialto_parachain_client::RialtoParachain; use relay_substrate_client::SimpleRuntimeVersion; +use xcm_executor::traits::ExportXcm; impl CliEncodeMessage for RialtoParachain { + fn encode_wire_message( + target: xcm::v3::NetworkId, + at_target_xcm: xcm::v3::Xcm<()>, + ) -> anyhow::Result> { + anyhow::ensure!( + target == CustomNetworkId::Millau.as_network_id(), + anyhow::format_err!("Unsupported target chain: {:?}", target) + ); + + Ok(rialto_parachain_runtime::millau_messages::ToMillauBlobExporter::validate( + target, + 0, + &mut Some(Self::dummy_universal_source()?), + &mut Some(target.into()), + &mut Some(at_target_xcm), + ) + .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? + .0 + .0) + } + fn encode_execute_xcm( message: xcm::VersionedXcm, ) -> anyhow::Result> { diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs index 9abf8b2df6dda..646075e832679 100644 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ b/relays/bin-substrate/src/cli/encode_message.rs @@ -16,10 +16,12 @@ use crate::cli::{ExplicitOrMaximal, HexBytes}; use bp_runtime::EncodedOrDecodedCall; +use bridge_runtime_common::CustomNetworkId; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::Chain; use structopt::StructOpt; +use xcm::latest::prelude::*; /// All possible messages that may be delivered to generic Substrate chain. /// @@ -43,6 +45,22 @@ pub enum Message { pub type RawMessage = Vec; pub trait CliEncodeMessage: Chain { + /// Returns dummy `AccountId32` universal source given this network id. + fn dummy_universal_source() -> anyhow::Result { + use xcm::v3::prelude::*; + + let this_network = CustomNetworkId::try_from(Self::ID) + .map(|n| n.as_network_id()) + .map_err(|_| anyhow::format_err!("Unsupported chain: {:?}", Self::ID))?; + Ok(X2( + GlobalConsensus(this_network), + AccountId32 { network: Some(this_network), id: [0u8; 32] }, + )) + } + + /// Returns XCM blob that is passed to the `send_message` function of the messages pallet + /// and then is sent over the wire. + fn encode_wire_message(target: NetworkId, at_target_xcm: Xcm<()>) -> anyhow::Result>; /// Encode an `execute` XCM call of the XCM pallet. fn encode_execute_xcm( message: xcm::VersionedXcm, @@ -56,41 +74,52 @@ pub trait CliEncodeMessage: Chain { } /// Encode message payload passed through CLI flags. -pub(crate) fn encode_message( +pub(crate) fn encode_message( message: &Message, ) -> anyhow::Result { Ok(match message { Message::Raw { ref data } => data.0.clone(), Message::Sized { ref size } => { - let expected_xcm_size = match *size { + let destination = CustomNetworkId::try_from(Target::ID) + .map(|n| n.as_network_id()) + .map_err(|_| anyhow::format_err!("Unsupported target chain: {:?}", Target::ID))?; + let expected_size = match *size { ExplicitOrMaximal::Explicit(size) => size, ExplicitOrMaximal::Maximal => compute_maximal_message_size( Source::max_extrinsic_size(), Target::max_extrinsic_size(), ), - }; - - // there's no way to craft XCM of the given size - we'll be using `ExpectPallet` - // instruction, which has byte vector inside - let mut current_vec_size = expected_xcm_size; - let xcm = loop { - let xcm = xcm::VersionedXcm::<()>::V3( - vec![xcm::v3::Instruction::ExpectPallet { - index: 0, - name: vec![42; current_vec_size as usize], - module_name: vec![], - crate_major: 0, - min_crate_minor: 0, - }] - .into(), - ); - if xcm.encode().len() <= expected_xcm_size as usize { - break xcm - } - - current_vec_size -= 1; - }; - xcm.encode() + } as usize; + + let at_target_xcm = vec![ExpectPallet { + index: 0, + name: vec![42; expected_size], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + }] + .into(); + let at_target_xcm_size = + Source::encode_wire_message(destination, at_target_xcm)?.encoded_size(); + let at_target_xcm_overhead = at_target_xcm_size.saturating_sub(expected_size); + let at_target_xcm = vec![ExpectPallet { + index: 0, + name: vec![42; expected_size.saturating_sub(at_target_xcm_overhead)], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + }] + .into(); + + xcm::VersionedXcm::<()>::V3( + vec![ExportMessage { + network: destination, + destination: destination.into(), + xcm: at_target_xcm, + }] + .into(), + ) + .encode() }, }) } @@ -108,11 +137,7 @@ pub(crate) fn compute_maximal_message_size( bridge_runtime_common::messages::target::maximal_incoming_message_size( maximal_target_extrinsic_size, ); - if maximal_message_size > maximal_source_extrinsic_size { - maximal_source_extrinsic_size - } else { - maximal_message_size - } + std::cmp::min(maximal_message_size, maximal_source_extrinsic_size) } #[cfg(test)] @@ -123,13 +148,21 @@ mod tests { use relay_millau_client::Millau; use relay_rialto_client::Rialto; + fn approximate_message_size(xcm_msg_len: usize) -> usize { + xcm_msg_len + Source::dummy_universal_source().unwrap().encoded_size() + } + #[test] fn encode_explicit_size_message_works() { let msg = encode_message::(&Message::Sized { size: ExplicitOrMaximal::Explicit(100), }) .unwrap(); - assert_eq!(msg.len(), 100); + // since it isn't the returned XCM what is sent over the wire, we can only check if + // it is close to what we need + assert!( + (1f64 - (approximate_message_size::(msg.len()) as f64) / 100_f64).abs() < 0.1 + ); // check that it decodes to valid xcm let _ = decode_xcm::<()>(msg).unwrap(); } @@ -144,7 +177,12 @@ mod tests { let msg = encode_message::(&Message::Sized { size: ExplicitOrMaximal::Maximal }) .unwrap(); - assert_eq!(msg.len(), maximal_size as usize); + // since it isn't the returned XCM what is sent over the wire, we can only check if + // it is close to what we need + assert!( + (1f64 - approximate_message_size::(msg.len()) as f64 / maximal_size as f64) + .abs() < 0.1 + ); // check that it decodes to valid xcm let _ = decode_xcm::<()>(msg).unwrap(); } From 9068145975e582a1dc4939eab6cdb24053374873 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 3 May 2023 14:31:47 +0300 Subject: [PATCH 1054/1210] Fix comment (#2105) --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 0a315035042a1..f71920a1d182e 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -49,7 +49,7 @@ relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } relay-wococo-client = { path = "../client-wococo" } rialto-runtime = { path = "../../bin/rialto/runtime" } -# we are not using this runtime to craft callsour transactions, but we still need it +# we are not using this runtime to craft call or transactions, but we still need it # to prepare large XCM messages rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } From 8549bceedfbe81c075c20a5693a73c7215cd2884 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 3 May 2023 16:23:10 +0300 Subject: [PATCH 1055/1210] Use generated runtimes for BHR/BHW (#2106) * Use generated runtimes for BHR/BHW * Deduplicate BHR/BHW runtimes * Add script for regenerating runtimes --- ...ub_rococo_messages_to_bridge_hub_wococo.rs | 8 +- ...ub_wococo_messages_to_bridge_hub_rococo.rs | 8 +- .../rococo_headers_to_bridge_hub_wococo.rs | 4 +- .../rococo_parachains_to_bridge_hub_wococo.rs | 4 +- .../wococo_headers_to_bridge_hub_rococo.rs | 4 +- .../wococo_parachains_to_bridge_hub_rococo.rs | 4 +- relays/bin-substrate/src/cli/init_bridge.rs | 12 +- relays/client-bridge-hub-rococo/Cargo.toml | 5 +- .../src/codegen_runtime.rs | 3348 +++++++++++++++++ relays/client-bridge-hub-rococo/src/lib.rs | 48 +- .../src/runtime_wrapper.rs | 69 - relays/client-bridge-hub-wococo/Cargo.toml | 7 +- relays/client-bridge-hub-wococo/src/lib.rs | 27 +- .../src/runtime_wrapper.rs | 115 - .../src/codegen_runtime.rs | 393 +- relays/client-rialto-parachain/src/lib.rs | 2 +- 16 files changed, 3647 insertions(+), 411 deletions(-) create mode 100644 relays/client-bridge-hub-rococo/src/codegen_runtime.rs delete mode 100644 relays/client-bridge-hub-rococo/src/runtime_wrapper.rs delete mode 100644 relays/client-bridge-hub-wococo/src/runtime_wrapper.rs diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs index 9e4b5b15fd6d4..18d9c31089c31 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs @@ -35,15 +35,15 @@ impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubRococoMessagesToBridgeHubWococoMessageLane, BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoMessages, - relay_bridge_hub_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_proof + relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoMessages, + relay_bridge_hub_wococo_client::BridgeMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubRococoMessagesToBridgeHubWococoMessageLane, BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoMessages, - relay_bridge_hub_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_delivery_proof + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoMessages, + relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_delivery_proof ); /// Description of BridgeHubRococo -> BridgeHubWococo messages bridge. diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs index fb5a81c021e19..d327926823bf3 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs @@ -35,15 +35,15 @@ impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubWococoMessagesToBridgeHubRococoMessageLane, BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoMessages, - relay_bridge_hub_rococo_client::runtime::BridgeWococoMessagesCall::receive_messages_proof + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoMessages, + relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubWococoMessagesToBridgeHubRococoMessageLane, BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoMessages, - relay_bridge_hub_wococo_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof + relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoMessages, + relay_bridge_hub_wococo_client::BridgeMessagesCall::receive_messages_delivery_proof ); /// Description of BridgeHubWococo -> BridgeHubRococo messages bridge. diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs index 2272144311c6d..b7d17d931f843 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs @@ -32,8 +32,8 @@ pub struct RococoFinalityToBridgeHubWococo; substrate_relay_helper::generate_submit_finality_proof_call_builder!( RococoFinalityToBridgeHubWococo, RococoFinalityToBridgeHubWococoCallBuilder, - relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa, - relay_bridge_hub_wococo_client::runtime::BridgeRococoGrandpaCall::submit_finality_proof + relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoGrandpa, + relay_bridge_hub_wococo_client::BridgeGrandpaCall::submit_finality_proof ); #[async_trait] diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs index 78b4ff35a7d45..b2704c092b845 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs @@ -44,8 +44,8 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoParachain( - relay_bridge_hub_wococo_client::runtime::BridgeParachainCall::submit_parachain_heads { + relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoParachain( + relay_bridge_hub_wococo_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs index 3904300958216..206c83b815314 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs @@ -32,8 +32,8 @@ pub struct WococoFinalityToBridgeHubRococo; substrate_relay_helper::generate_submit_finality_proof_call_builder!( WococoFinalityToBridgeHubRococo, WococoFinalityToBridgeHubRococoCallBuilder, - relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoGrandpa, - relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::submit_finality_proof + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoGrandpa, + relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof ); #[async_trait] diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs index bc76e377c9214..ca77857833d0b 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs @@ -44,8 +44,8 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoParachain( - bp_parachains::BridgeParachainCall::submit_parachain_heads { + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoParachain( + relay_bridge_hub_rococo_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 95cd02f6c6fcc..7b38d81227199 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -180,10 +180,8 @@ impl BridgeInitializer for RococoToBridgeHubWococoCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - relay_bridge_hub_wococo_client::runtime::Call::BridgeRococoGrandpa( - relay_bridge_hub_wococo_client::runtime::BridgeRococoGrandpaCall::initialize { - init_data, - }, + relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoGrandpa( + relay_bridge_hub_wococo_client::BridgeGrandpaCall::initialize { init_data }, ) } } @@ -194,10 +192,8 @@ impl BridgeInitializer for WococoToBridgeHubRococoCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - relay_bridge_hub_rococo_client::runtime::Call::BridgeWococoGrandpa( - relay_bridge_hub_rococo_client::runtime::BridgeWococoGrandpaCall::initialize { - init_data, - }, + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoGrandpa( + relay_bridge_hub_rococo_client::BridgeGrandpaCall::initialize { init_data }, ) } } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 5826a1321bc72..a901e029bf542 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } -relay-substrate-client = { path = "../client-substrate" } +subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies @@ -17,12 +17,15 @@ bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs new file mode 100644 index 0000000000000..6488d923d7594 --- /dev/null +++ b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs @@ -0,0 +1,3348 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url +//! wss://rococo-bridge-hub-rpc.polkadot.io:443 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod bp_header_chain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HeaderChainError { + #[codec(index = 0)] + UnknownHeader, + #[codec(index = 1)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredHeaderData<_0, _1> { + pub number: _0, + pub state_root: _1, + } + } + pub mod bp_messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DeliveredMessages { + pub begin: ::core::primitive::u64, + pub end: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundLaneData<_0> { + pub relayers: ::std::vec::Vec>, + pub last_confirmed_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LaneId(pub [::core::primitive::u8; 4usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageKey { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MessagesOperatingMode { + #[codec(index = 0)] + Basic(runtime_types::bp_runtime::BasicOperatingMode), + #[codec(index = 1)] + RejectingOutboundMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundLaneData { + pub oldest_unpruned_nonce: ::core::primitive::u64, + pub latest_received_nonce: ::core::primitive::u64, + pub latest_generated_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalResult<_0> { + #[codec(index = 0)] + Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), + #[codec(index = 1)] + InvalidNonce, + #[codec(index = 2)] + TooManyUnrewardedRelayers, + #[codec(index = 3)] + TooManyUnconfirmedMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceivedMessages<_0> { + pub lane: runtime_types::bp_messages::LaneId, + pub receive_results: ::std::vec::Vec<( + ::core::primitive::u64, + runtime_types::bp_messages::ReceivalResult<_0>, + )>, + pub skipped_for_not_enough_weight: ::std::vec::Vec<::core::primitive::u64>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnrewardedRelayer<_0> { + pub relayer: _0, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + } + pub mod bp_parachains { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BestParaHeadHash { + pub at_relay_block_number: ::core::primitive::u32, + pub head_hash: ::subxt::utils::H256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo { + pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, + pub next_imported_hash_position: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); + } + pub mod bp_relayers { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardsAccountOwner { + #[codec(index = 0)] + ThisChain, + #[codec(index = 1)] + BridgedChain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardsAccountParams { + pub lane_id: runtime_types::bp_messages::LaneId, + pub bridged_chain_id: [::core::primitive::u8; 4usize], + pub owner: runtime_types::bp_relayers::RewardsAccountOwner, + } + } + pub mod bp_runtime { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageDispatchResult<_0> { + pub unspent_weight: ::sp_weights::Weight, + pub dispatch_level_result: _0, + } + } + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateNodesInProof, + #[codec(index = 1)] + UnusedNodesInTheProof, + #[codec(index = 2)] + StorageRootMismatch, + #[codec(index = 3)] + StorageValueUnavailable, + #[codec(index = 4)] + StorageValueEmpty, + #[codec(index = 5)] + StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderId<_0, _1>(pub _1, pub _0); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OwnedBridgeModuleError { + #[codec(index = 0)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StrippableError; + } + pub mod bridge_hub_rococo_runtime { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BridgeRejectObsoleteHeadersAndMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + #[codec(index = 0)] + system( + runtime_types::frame_support::dispatch::RawOrigin< + ::sp_core::crypto::AccountId32, + >, + ), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), + #[codec(index = 3)] + Void(runtime_types::sp_core::Void), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 36)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 41)] + BridgeWococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 42)] + BridgeWococoParachain(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 46)] + BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 43)] + BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 44)] + BridgeRococoParachain(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 45)] + BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 47)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 11)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 36)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 41)] + BridgeWococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 42)] + BridgeWococoParachain(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 46)] + BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), + #[codec(index = 43)] + BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 44)] + BridgeRococoParachain(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 45)] + BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), + #[codec(index = 47)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, + } + } + pub mod bridge_runtime_common { + use super::runtime_types; + pub mod messages_xcm_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmBlobMessageDispatchResult { + #[codec(index = 0)] + InvalidPayload, + #[codec(index = 1)] + Dispatched, + #[codec(index = 2)] + NotDispatched, + } + } + pub mod refund_relayer_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundBridgedParachainMessages; + } + } + pub mod cumulus_pallet_dmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + OverLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat { message_id: [::core::primitive::u8; 32usize] }, + #[codec(index = 1)] + UnsupportedVersion { message_id: [::core::primitive::u8; 32usize] }, + #[codec(index = 2)] + ExecutedDownward { + message_id: [::core::primitive::u8; 32usize], + outcome: runtime_types::xcm::v3::traits::Outcome, + }, + #[codec(index = 3)] + WeightExhausted { + message_id: [::core::primitive::u8; 32usize], + remaining_weight: ::sp_weights::Weight, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + OverweightEnqueued { + message_id: [::core::primitive::u8; 32usize], + overweight_index: ::core::primitive::u64, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 5)] + OverweightServiced { + overweight_index: ::core::primitive::u64, + weight_used: ::sp_weights::Weight, + }, + #[codec(index = 6)] + MaxMessagesExhausted { message_id: [::core::primitive::u8; 32usize] }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ConfigData { + pub max_individual: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PageIndexData { + pub begin_used: ::core::primitive::u32, + pub end_used: ::core::primitive::u32, + pub overweight_count: ::core::primitive::u64, + } + } + pub mod cumulus_pallet_parachain_system { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OverlappingUpgrades, + #[codec(index = 1)] + ProhibitedByPolkadot, + #[codec(index = 2)] + TooBig, + #[codec(index = 3)] + ValidationDataNotAvailable, + #[codec(index = 4)] + HostConfigurationNotAvailable, + #[codec(index = 5)] + NotScheduled, + #[codec(index = 6)] + NothingAuthorized, + #[codec(index = 7)] + Unauthorized, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ValidationFunctionStored, + #[codec(index = 1)] + ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, + #[codec(index = 2)] + ValidationFunctionDiscarded, + #[codec(index = 3)] + UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + DownwardMessagesReceived { count: ::core::primitive::u32 }, + #[codec(index = 5)] + DownwardMessagesProcessed { + weight_used: ::sp_weights::Weight, + dmq_head: ::subxt::utils::H256, + }, + #[codec(index = 6)] + UpwardMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + pub mod relay_state_snapshot { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessagingStateSnapshot { + pub dmq_mqc_head: ::subxt::utils::H256, + pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), + pub ingress_channels: ::std::vec::Vec<( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, + )>, + pub egress_channels: ::std::vec::Vec<( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, + )>, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CodeUpgradeAuthorization { + pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, + } + } + pub mod cumulus_pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + UnsupportedVersion([::core::primitive::u8; 32usize]), + #[codec(index = 2)] + ExecutedDownward( + [::core::primitive::u8; 32usize], + runtime_types::xcm::v3::traits::Outcome, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Relay, + #[codec(index = 1)] + SiblingParachain(runtime_types::polkadot_parachain::primitives::Id), + } + } + } + pub mod cumulus_pallet_xcmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + #[codec(index = 1)] + suspend_xcm_execution, + #[codec(index = 2)] + resume_xcm_execution, + #[codec(index = 3)] + update_suspend_threshold { new: ::core::primitive::u32 }, + #[codec(index = 4)] + update_drop_threshold { new: ::core::primitive::u32 }, + #[codec(index = 5)] + update_resume_threshold { new: ::core::primitive::u32 }, + #[codec(index = 6)] + update_threshold_weight { new: ::sp_weights::Weight }, + #[codec(index = 7)] + update_weight_restrict_decay { new: ::sp_weights::Weight }, + #[codec(index = 8)] + update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSend, + #[codec(index = 1)] + BadXcmOrigin, + #[codec(index = 2)] + BadXcm, + #[codec(index = 3)] + BadOverweightIndex, + #[codec(index = 4)] + WeightOverLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Success { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + weight: ::sp_weights::Weight, + }, + #[codec(index = 1)] + Fail { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + error: runtime_types::xcm::v3::traits::Error, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + BadVersion { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 3)] + BadFormat { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 4)] + XcmpMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 5)] + OverweightEnqueued { + sender: runtime_types::polkadot_parachain::primitives::Id, + sent_at: ::core::primitive::u32, + index: ::core::primitive::u64, + required: ::sp_weights::Weight, + }, + #[codec(index = 6)] + OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundChannelDetails { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, + pub message_metadata: ::std::vec::Vec<( + ::core::primitive::u32, + runtime_types::polkadot_parachain::primitives::XcmpMessageFormat, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundChannelDetails { + pub recipient: runtime_types::polkadot_parachain::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, + pub signals_exist: ::core::primitive::bool, + pub first_index: ::core::primitive::u16, + pub last_index: ::core::primitive::u16, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OutboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueueConfigData { + pub suspend_threshold: ::core::primitive::u32, + pub drop_threshold: ::core::primitive::u32, + pub resume_threshold: ::core::primitive::u32, + pub threshold_weight: ::sp_weights::Weight, + pub weight_restrict_decay: ::sp_weights::Weight, + pub xcmp_max_individual_weight: ::sp_weights::Weight, + } + } + pub mod cumulus_primitives_parachain_inherent { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageQueueChain(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParachainInherentData { + pub validation_data: + runtime_types::polkadot_primitives::v4::PersistedValidationData< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, + pub downward_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundDownwardMessage< + ::core::primitive::u32, + >, + >, + pub horizontal_messages: ::subxt::utils::KeyedVec< + runtime_types::polkadot_parachain::primitives::Id, + ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundHrmpMessage< + ::core::primitive::u32, + >, + >, + >, + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commit<_0, _1, _2, _3> { + pub target_hash: _0, + pub target_number: _1, + pub precommits: ::std::vec::Vec< + runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedPrecommit<_0, _1, _2, _3> { + pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, + pub signature: _2, + pub id: _3, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + set_balance_deprecated { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + #[codec(compact)] + old_reserved: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 7)] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_bridge_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 1)] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 2)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidJustification, + #[codec(index = 1)] + InvalidAuthoritySet, + #[codec(index = 2)] + TooManyRequests, + #[codec(index = 3)] + OldHeader, + #[codec(index = 4)] + UnsupportedScheduledChange, + #[codec(index = 5)] + NotInitialized, + #[codec(index = 6)] + AlreadyInitialized, + #[codec(index = 7)] + TooManyAuthoritiesInSet, + #[codec(index = 8)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u32, + hash: ::subxt::utils::H256, + }, + } + } + pub mod storage_types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredAuthoritySet { + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + } + } + pub mod pallet_bridge_messages { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotOperatingNormally, + #[codec(index = 1)] + InactiveOutboundLane, + #[codec(index = 2)] + MessageIsTooLarge, + #[codec(index = 3)] + MessageRejectedByChainVerifier, + #[codec(index = 4)] + MessageRejectedByLaneVerifier, + #[codec(index = 5)] + FailedToWithdrawMessageFee, + #[codec(index = 6)] + TooManyMessagesInTheProof, + #[codec(index = 7)] + InvalidMessagesProof, + #[codec(index = 8)] + InvalidMessagesDeliveryProof, + #[codec(index = 9)] + InvalidUnrewardedRelayers, + #[codec(index = 10)] + InvalidUnrewardedRelayersState, + #[codec(index = 11)] + MessageIsAlreadyDelivered, + #[codec(index = 12)] + MessageIsNotYetSent, + #[codec(index = 13)] + TryingToConfirmMoreMessagesThanExpected, + #[codec(index = 14)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } + } + } + pub mod pallet_bridge_parachains { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_parachain_heads { + at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), + parachains: ::std::vec::Vec<( + ::bp_polkadot_core::parachains::ParaId, + ::subxt::utils::H256, + )>, + parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, + }, + #[codec(index = 1)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 2)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnknownRelayChainBlock, + #[codec(index = 1)] + InvalidRelayChainBlockNumber, + #[codec(index = 2)] + HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 3)] + UnknownParaHead, + #[codec(index = 4)] + StorageRootMismatch, + #[codec(index = 5)] + FailedToExtractStateRoot, + #[codec(index = 6)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 1)] + MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 2)] + IncorrectParachainHeadHash { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + actual_parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + RejectedObsoleteParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 4)] + RejectedLargeParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + parachain_head_size: ::core::primitive::u32, + }, + #[codec(index = 5)] + UpdatedParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + } + } + } + pub mod pallet_bridge_relayers { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim_rewards { + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NoRewardForRelayer, + #[codec(index = 1)] + FailedToPayReward, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RewardPaid { + relayer: ::sp_core::crypto::AccountId32, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + reward: ::core::primitive::u128, + }, + } + } + } + pub mod pallet_collator_selection { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 1)] + set_desired_candidates { max: ::core::primitive::u32 }, + #[codec(index = 2)] + set_candidacy_bond { bond: ::core::primitive::u128 }, + #[codec(index = 3)] + register_as_candidate, + #[codec(index = 4)] + leave_intent, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateInfo<_0, _1> { + pub who: _0, + pub deposit: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCandidates, + #[codec(index = 1)] + TooFewCandidates, + #[codec(index = 2)] + Unknown, + #[codec(index = 3)] + Permission, + #[codec(index = 4)] + AlreadyCandidate, + #[codec(index = 5)] + NotCandidate, + #[codec(index = 6)] + TooManyInvulnerables, + #[codec(index = 7)] + AlreadyInvulnerable, + #[codec(index = 8)] + NoAssociatedValidatorId, + #[codec(index = 9)] + ValidatorNotRegistered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewInvulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 1)] + NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, + #[codec(index = 2)] + NewCandidacyBond { bond_amount: ::core::primitive::u128 }, + #[codec(index = 3)] + CandidateAdded { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 4)] + CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, + } + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box< + runtime_types::bridge_hub_rococo_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_rococo_runtime::RuntimeCall, + >, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: _0, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::bridge_hub_rococo_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { + calls: + ::std::vec::Vec, + }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box< + runtime_types::bridge_hub_rococo_runtime::RuntimeCall, + >, + }, + #[codec(index = 2)] + batch_all { + calls: + ::std::vec::Vec, + }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box< + runtime_types::bridge_hub_rococo_runtime::OriginCaller, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_rococo_runtime::RuntimeCall, + >, + }, + #[codec(index = 4)] + force_batch { + calls: + ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box< + runtime_types::bridge_hub_rococo_runtime::RuntimeCall, + >, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: + ::std::boxed::Box, + xcm_version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted(runtime_types::xcm::v3::traits::Outcome), + #[codec(index = 1)] + Sent( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::Xcm, + ), + #[codec(index = 2)] + UnexpectedResponse( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 3)] + ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + #[codec(index = 4)] + Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + #[codec(index = 5)] + NotifyOverweight( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ::sp_weights::Weight, + ::sp_weights::Weight, + ), + #[codec(index = 6)] + NotifyDispatchError( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 7)] + NotifyDecodeFailed( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 8)] + InvalidResponder( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 9)] + InvalidResponderVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 10)] + ResponseTaken(::core::primitive::u64), + #[codec(index = 11)] + AssetsTrapped( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + #[codec(index = 12)] + VersionChangeNotified( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 13)] + SupportedVersionChanged( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + ), + #[codec(index = 14)] + NotifyTargetSendFail( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::traits::Error, + ), + #[codec(index = 15)] + NotifyTargetMigrationFail( + runtime_types::xcm::VersionedMultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 16)] + InvalidQuerierVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 17)] + InvalidQuerier( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 18)] + VersionNotifyStarted( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 19)] + VersionNotifyRequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 20)] + VersionNotifyUnrequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 21)] + FeesPaid( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 22)] + AssetsClaimed( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::xcm::v3::multilocation::MultiLocation), + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmpMessageFormat { + #[codec(index = 0)] + ConcatenatedVersionedXcm, + #[codec(index = 1)] + ConcatenatedEncodedBlob, + #[codec(index = 2)] + Signals, + } + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v4 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHostConfiguration { + pub max_code_size: ::core::primitive::u32, + pub max_head_data_size: ::core::primitive::u32, + pub max_upward_queue_count: ::core::primitive::u32, + pub max_upward_queue_size: ::core::primitive::u32, + pub max_upward_message_size: ::core::primitive::u32, + pub max_upward_message_num_per_candidate: ::core::primitive::u32, + pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, + pub validation_upgrade_cooldown: ::core::primitive::u32, + pub validation_upgrade_delay: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PersistedValidationData<_0, _1> { + pub parent_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub relay_parent_number: _1, + pub relay_parent_storage_root: _0, + pub max_pov_size: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_consensus_aura { + use super::runtime_types; + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1, _2, _3)>, + ); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_trie { + use super::runtime_types; + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StorageProof { + pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + } + } +} diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index bc2ec3aca41e6..2a0595953956a 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -16,22 +16,29 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. -use bp_bridge_hub_rococo::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; +pub mod codegen_runtime; + +use bp_bridge_hub_rococo::{BridgeHubSignedExtension, SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -/// Re-export runtime wrapper -pub mod runtime_wrapper; -pub use runtime_wrapper as runtime; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::bridge_hub_rococo_runtime::RuntimeCall; +pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; +type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; +type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Rococo chain definition #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -49,7 +56,7 @@ impl Chain for BridgeHubRococo { const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_rococo::SignedBlock; - type Call = runtime::Call; + type Call = RuntimeCall; } impl ChainWithBalances for BridgeHubRococo { @@ -58,13 +65,22 @@ impl ChainWithBalances for BridgeHubRococo { } } +impl From> for RuntimeCall { + fn from(value: MockUtilityCall) -> RuntimeCall { + match value { + MockUtilityCall::batch_all(calls) => + RuntimeCall::Utility(UtilityCall::batch_all { calls }), + } + } +} + impl ChainWithUtilityPallet for BridgeHubRococo { - type UtilityPallet = MockedRuntimeUtilityPallet; + type UtilityPallet = MockedRuntimeUtilityPallet; } impl ChainWithTransactions for BridgeHubRococo { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = runtime::UncheckedExtrinsic; + type SignedTransaction = UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -72,7 +88,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::SignedExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -86,7 +102,7 @@ impl ChainWithTransactions for BridgeHubRococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(runtime::UncheckedExtrinsic::new_signed( + Ok(UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -135,13 +151,13 @@ mod tests { use super::*; use relay_substrate_client::TransactionEra; + type SystemCall = runtime_types::frame_system::pallet::Call; + #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(relay_substrate_client::calls::SystemCall::remark( - b"Hello world!".to_vec(), - )) - .into(), + call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) + .into(), nonce: 777, tip: 888, era: TransactionEra::immortal(), diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs deleted file mode 100644 index 26e0bd9da5e29..0000000000000 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ /dev/null @@ -1,69 +0,0 @@ -// 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 . - -//! Types that are specific to the BridgeHubRococo runtime. - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_bridge_hub_rococo::SignedExtension; -pub use bp_header_chain::BridgeGrandpaCallOf; -pub use bp_parachains::BridgeParachainCall; -pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; - -/// Unchecked BridgeHubRococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; - -// The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. -pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; -// The indirect pallet call used to sync `BridgeHubWococo` messages to `BHRococo`. -pub type BridgeWococoMessagesCall = BridgeMessagesCallOf; - -/// `BridgeHubRococo` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `BridgeHubRococo` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `BridgeHubRococo` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - #[cfg(test)] - #[codec(index = 0)] - System(SystemCall), - /// Utility pallet. - #[codec(index = 40)] - Utility(UtilityCall), - - /// Wococo bridge pallet. - #[codec(index = 41)] - BridgeWococoGrandpa(BridgeWococoGrandpaCall), - /// Wococo parachain bridge pallet. - #[codec(index = 42)] - BridgeWococoParachain(BridgeParachainCall), - /// Wococo messages bridge pallet. - #[codec(index = 46)] - BridgeWococoMessages(BridgeWococoMessagesCall), -} - -impl From> for Call { - fn from(call: UtilityCall) -> Call { - Call::Utility(call) - } -} diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index 72a25b001e5bb..e5c0684ba0ab0 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } -relay-substrate-client = { path = "../client-substrate" } +subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies @@ -17,16 +17,19 @@ bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } +relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } [dev-dependencies] -bp-polkadot-core = { path = "../../primitives/polkadot-core" } sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index c9acc47dd954d..0e2b9839301ba 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_bridge_hub_wococo::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_wococo::{BridgeHubSignedExtension, SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; use bp_runtime::ChainId; use codec::Encode; @@ -29,9 +29,14 @@ use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -/// Re-export runtime wrapper -pub mod runtime_wrapper; -pub use runtime_wrapper as runtime; +pub use codegen_runtime::api::runtime_types; +use relay_bridge_hub_rococo_client::codegen_runtime; + +pub type RuntimeCall = runtime_types::bridge_hub_rococo_runtime::RuntimeCall; +pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; +type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; /// Wococo chain definition #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -49,7 +54,7 @@ impl Chain for BridgeHubWococo { const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_wococo::SignedBlock; - type Call = runtime::Call; + type Call = RuntimeCall; } impl ChainWithBalances for BridgeHubWococo { @@ -59,12 +64,12 @@ impl ChainWithBalances for BridgeHubWococo { } impl ChainWithUtilityPallet for BridgeHubWococo { - type UtilityPallet = MockedRuntimeUtilityPallet; + type UtilityPallet = MockedRuntimeUtilityPallet; } impl ChainWithTransactions for BridgeHubWococo { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = runtime::UncheckedExtrinsic; + type SignedTransaction = UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -72,7 +77,7 @@ impl ChainWithTransactions for BridgeHubWococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::SignedExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -86,7 +91,7 @@ impl ChainWithTransactions for BridgeHubWococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(runtime::UncheckedExtrinsic::new_signed( + Ok(UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -135,10 +140,12 @@ mod tests { use super::*; use relay_substrate_client::TransactionEra; + type SystemCall = runtime_types::frame_system::pallet::Call; + #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) .into(), nonce: 777, tip: 888, diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs deleted file mode 100644 index b9803955922db..0000000000000 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ /dev/null @@ -1,115 +0,0 @@ -// 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 . - -//! Types that are specific to the BridgeHubWococo runtime. - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_bridge_hub_wococo::SignedExtension; -pub use bp_header_chain::BridgeGrandpaCallOf; -pub use bp_parachains::BridgeParachainCall; -pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; - -/// Unchecked BridgeHubWococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; - -// The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. -pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; -// The indirect pallet call used to sync `BridgeHubRococo` messages to `BridgeHubWococo`. -pub type BridgeRococoMessagesCall = BridgeMessagesCallOf; - -/// `BridgeHubWococo` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `BridgeHubWococo` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `BridgeHubWococo` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - #[cfg(test)] - #[codec(index = 0)] - System(SystemCall), - /// Utility pallet. - #[codec(index = 40)] - Utility(UtilityCall), - - /// Rococo bridge pallet. - #[codec(index = 43)] - BridgeRococoGrandpa(BridgeRococoGrandpaCall), - /// Rococo parachain bridge pallet. - #[codec(index = 44)] - BridgeRococoParachain(BridgeParachainCall), - /// Rococo messages bridge pallet. - #[codec(index = 45)] - BridgeRococoMessages(BridgeRococoMessagesCall), -} - -impl From> for Call { - fn from(call: UtilityCall) -> Call { - Call::Utility(call) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_runtime::BasicOperatingMode; - use sp_consensus_grandpa::AuthorityList; - use sp_core::hexdisplay::HexDisplay; - use sp_runtime::traits::Header; - use std::str::FromStr; - - pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; - pub type RelayBlockHasher = bp_polkadot_core::Hasher; - pub type RelayBlockHeader = sp_runtime::generic::Header; - - #[test] - fn encode_decode_calls() { - let header = RelayBlockHeader::new( - 75, - bp_polkadot_core::Hash::from_str( - "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", - ) - .expect("invalid value"), - Default::default(), - ); - let init_data = bp_header_chain::InitializationData { - header: Box::new(header), - authority_list: AuthorityList::default(), - set_id: 6, - operating_mode: BasicOperatingMode::Normal, - }; - let call = BridgeRococoGrandpaCall::initialize { init_data }; - let tx = Call::BridgeRococoGrandpa(call); - - // encode call as hex string - let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); - assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); - } -} diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs index 1338d4938a36f..eb19d98d7e487 100644 --- a/relays/client-rialto-parachain/src/codegen_runtime.rs +++ b/relays/client-rialto-parachain/src/codegen_runtime.rs @@ -28,18 +28,18 @@ pub mod api { use super::runtime_types; pub mod bounded_vec { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); } pub mod weak_bounded_vec { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); } } pub mod bp_header_chain { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct StoredHeaderData<_0, _1> { pub number: _0, pub state_root: _1, @@ -47,37 +47,37 @@ pub mod api { } pub mod bp_messages { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct DeliveredMessages { pub begin: ::core::primitive::u64, pub end: ::core::primitive::u64, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct InboundLaneData<_0> { pub relayers: ::std::vec::Vec>, pub last_confirmed_nonce: ::core::primitive::u64, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MessageKey { pub lane_id: runtime_types::bp_messages::LaneId, pub nonce: ::core::primitive::u64, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum MessagesOperatingMode { #[codec(index = 0)] Basic(runtime_types::bp_runtime::BasicOperatingMode), #[codec(index = 1)] RejectingOutboundMessages, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct OutboundLaneData { pub oldest_unpruned_nonce: ::core::primitive::u64, pub latest_received_nonce: ::core::primitive::u64, pub latest_generated_nonce: ::core::primitive::u64, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum ReceivalResult<_0> { #[codec(index = 0)] Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), @@ -88,7 +88,7 @@ pub mod api { #[codec(index = 3)] TooManyUnconfirmedMessages, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ReceivedMessages<_0> { pub lane: runtime_types::bp_messages::LaneId, pub receive_results: ::std::vec::Vec<( @@ -96,7 +96,7 @@ pub mod api { runtime_types::bp_messages::ReceivalResult<_0>, )>, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct UnrewardedRelayer<_0> { pub relayer: _0, pub messages: runtime_types::bp_messages::DeliveredMessages, @@ -104,14 +104,22 @@ pub mod api { } pub mod bp_relayers { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + pub mod registration { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0, _1> { + pub valid_till: _0, + pub stake: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RewardsAccountOwner { #[codec(index = 0)] ThisChain, #[codec(index = 1)] BridgedChain, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RewardsAccountParams { pub lane_id: runtime_types::bp_messages::LaneId, pub bridged_chain_id: [::core::primitive::u8; 4usize], @@ -122,22 +130,22 @@ pub mod api { use super::runtime_types; pub mod messages { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MessageDispatchResult<_0> { pub unspent_weight: ::sp_weights::Weight, pub dispatch_level_result: _0, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum BasicOperatingMode { #[codec(index = 0)] Normal, #[codec(index = 1)] Halted, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum OwnedBridgeModuleError { #[codec(index = 0)] Halted, @@ -147,7 +155,7 @@ pub mod api { use super::runtime_types; pub mod messages_xcm_extension { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum XcmBlobMessageDispatchResult { #[codec(index = 0)] InvalidPayload, @@ -162,7 +170,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] service_overweight { @@ -170,14 +178,14 @@ pub mod api { weight_limit: ::sp_weights::Weight, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] Unknown, #[codec(index = 1)] OverLimit, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] InvalidFormat { message_id: [::core::primitive::u8; 32usize] }, @@ -209,11 +217,11 @@ pub mod api { MaxMessagesExhausted { message_id: [::core::primitive::u8; 32usize] }, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ConfigData { pub max_individual: ::sp_weights::Weight, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct PageIndexData { pub begin_used: ::core::primitive::u32, pub end_used: ::core::primitive::u32, @@ -224,10 +232,10 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] OverlappingUpgrades, @@ -246,7 +254,7 @@ pub mod api { #[codec(index = 7)] Unauthorized, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] ValidationFunctionStored, @@ -271,7 +279,7 @@ pub mod api { } pub mod relay_state_snapshot { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MessagingStateSnapshot { pub dmq_mqc_head: ::subxt::utils::H256, pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), @@ -285,7 +293,7 @@ pub mod api { )>, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CodeUpgradeAuthorization { pub code_hash: ::subxt::utils::H256, pub check_version: ::core::primitive::bool, @@ -295,11 +303,11 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] InvalidFormat([::core::primitive::u8; 32usize]), @@ -317,7 +325,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] service_overweight { @@ -341,7 +349,7 @@ pub mod api { #[codec(index = 8)] update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] FailedToSend, @@ -354,7 +362,7 @@ pub mod api { #[codec(index = 4)] WeightOverLimit, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] Success { @@ -390,7 +398,7 @@ pub mod api { OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct InboundChannelDetails { pub sender: runtime_types::polkadot_parachain::primitives::Id, pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, @@ -399,14 +407,14 @@ pub mod api { runtime_types::polkadot_parachain::primitives::XcmpMessageFormat, )>, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum InboundState { #[codec(index = 0)] Ok, #[codec(index = 1)] Suspended, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct OutboundChannelDetails { pub recipient: runtime_types::polkadot_parachain::primitives::Id, pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, @@ -414,14 +422,14 @@ pub mod api { pub first_index: ::core::primitive::u16, pub last_index: ::core::primitive::u16, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum OutboundState { #[codec(index = 0)] Ok, #[codec(index = 1)] Suspended, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct QueueConfigData { pub suspend_threshold: ::core::primitive::u32, pub drop_threshold: ::core::primitive::u32, @@ -433,9 +441,9 @@ pub mod api { } pub mod cumulus_primitives_parachain_inherent { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ParachainInherentData { pub validation_data: runtime_types::polkadot_primitives::v4::PersistedValidationData< @@ -460,7 +468,7 @@ pub mod api { } pub mod finality_grandpa { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Commit<_0, _1, _2, _3> { pub target_hash: _0, pub target_number: _1, @@ -468,12 +476,12 @@ pub mod api { runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, >, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Precommit<_0, _1> { pub target_hash: _0, pub target_number: _1, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct SignedPrecommit<_0, _1, _2, _3> { pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, pub signature: _2, @@ -484,7 +492,7 @@ pub mod api { use super::runtime_types; pub mod dispatch { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum DispatchClass { #[codec(index = 0)] Normal, @@ -493,20 +501,20 @@ pub mod api { #[codec(index = 2)] Mandatory, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct DispatchInfo { pub weight: ::sp_weights::Weight, pub class: runtime_types::frame_support::dispatch::DispatchClass, pub pays_fee: runtime_types::frame_support::dispatch::Pays, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Pays { #[codec(index = 0)] Yes, #[codec(index = 1)] No, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct PerDispatchClass<_0> { pub normal: _0, pub operational: _0, @@ -519,7 +527,9 @@ pub mod api { use super::runtime_types; pub mod misc { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] pub enum BalanceStatus { #[codec(index = 0)] Free, @@ -536,49 +546,49 @@ pub mod api { use super::runtime_types; pub mod check_genesis { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckGenesis; } pub mod check_mortality { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckMortality(pub ::sp_runtime::generic::Era); } pub mod check_non_zero_sender { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckNonZeroSender; } pub mod check_nonce { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); } pub mod check_spec_version { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckSpecVersion; } pub mod check_tx_version { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckTxVersion; } pub mod check_weight { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CheckWeight; } } pub mod limits { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BlockLength { pub max: runtime_types::frame_support::dispatch::PerDispatchClass< ::core::primitive::u32, >, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BlockWeights { pub base_block: ::sp_weights::Weight, pub max_block: ::sp_weights::Weight, @@ -586,7 +596,7 @@ pub mod api { runtime_types::frame_system::limits::WeightsPerClass, >, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct WeightsPerClass { pub base_extrinsic: ::sp_weights::Weight, pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, @@ -596,7 +606,7 @@ pub mod api { } pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] remark { remark: ::std::vec::Vec<::core::primitive::u8> }, @@ -623,7 +633,7 @@ pub mod api { #[codec(index = 7)] remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] InvalidSpecName, @@ -638,7 +648,7 @@ pub mod api { #[codec(index = 5)] CallFiltered, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] ExtrinsicSuccess { @@ -659,7 +669,7 @@ pub mod api { Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AccountInfo<_0, _1> { pub nonce: _0, pub consumers: _0, @@ -667,19 +677,19 @@ pub mod api { pub sufficients: _0, pub data: _1, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct EventRecord<_0, _1> { pub phase: runtime_types::frame_system::Phase, pub event: _0, pub topics: ::std::vec::Vec<_1>, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct LastRuntimeUpgradeInfo { #[codec(compact)] pub spec_version: ::core::primitive::u32, pub spec_name: ::std::string::String, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Phase { #[codec(index = 0)] ApplyExtrinsic(::core::primitive::u32), @@ -693,7 +703,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] transfer_allow_death { @@ -747,7 +757,7 @@ pub mod api { new_free: ::core::primitive::u128, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] VestingBalance, @@ -770,7 +780,7 @@ pub mod api { #[codec(index = 9)] TooManyFreezes, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] Endowed { @@ -851,14 +861,14 @@ pub mod api { } pub mod types { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AccountData<_0> { pub free: _0, pub reserved: _0, pub frozen: _0, pub flags: runtime_types::pallet_balances::types::ExtraFlags, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BalanceLock<_0> { pub id: [::core::primitive::u8; 8usize], pub amount: _0, @@ -870,14 +880,15 @@ pub mod api { :: subxt :: ext :: codec :: CompactAs, Clone, Debug, + PartialEq, )] pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct IdAmount<_0, _1> { pub id: _0, pub amount: _1, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Reasons { #[codec(index = 0)] Fee, @@ -886,7 +897,7 @@ pub mod api { #[codec(index = 2)] All, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ReserveData<_0, _1> { pub id: _0, pub amount: _1, @@ -897,7 +908,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] submit_finality_proof { @@ -930,7 +941,7 @@ pub mod api { operating_mode: runtime_types::bp_runtime::BasicOperatingMode, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] InvalidJustification, @@ -949,7 +960,7 @@ pub mod api { #[codec(index = 7)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] UpdatedBestFinalizedHeader { @@ -960,7 +971,7 @@ pub mod api { } pub mod storage_types { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct StoredAuthoritySet { pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( runtime_types::sp_consensus_grandpa::app::Public, @@ -974,10 +985,10 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: bp_millau :: MillauHash > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] NotOperatingNormally, @@ -1010,7 +1021,7 @@ pub mod api { #[codec(index = 14)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } } @@ -1019,21 +1030,37 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] claim_rewards { rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, }, + #[codec(index = 1)] + register { valid_till: ::core::primitive::u32 }, + #[codec(index = 2)] + deregister, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] NoRewardForRelayer, #[codec(index = 1)] FailedToPayReward, + #[codec(index = 2)] + InvalidRegistrationLease, + #[codec(index = 3)] + CannotReduceRegistrationLease, + #[codec(index = 4)] + FailedToReserve, + #[codec(index = 5)] + FailedToUnreserve, + #[codec(index = 6)] + NotRegistered, + #[codec(index = 7)] + RegistrationIsStillActive, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] RewardPaid { @@ -1041,6 +1068,24 @@ pub mod api { rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, reward: ::core::primitive::u128, }, + #[codec(index = 1)] + RegistrationUpdated { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + Deregistered { relayer: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + SlashedAndDeregistered { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, } } } @@ -1048,7 +1093,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] sudo { @@ -1072,12 +1117,12 @@ pub mod api { ::std::boxed::Box, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] RequireSudo, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] Sudid { @@ -1100,7 +1145,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] set { @@ -1114,7 +1159,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] TransactionFeePaid { @@ -1124,9 +1169,9 @@ pub mod api { }, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Releases { #[codec(index = 0)] V1Ancient, @@ -1138,7 +1183,7 @@ pub mod api { use super::runtime_types; pub mod pallet { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { #[codec(index = 0)] send { @@ -1199,7 +1244,7 @@ pub mod api { weight_limit: runtime_types::xcm::v3::WeightLimit, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] Unreachable, @@ -1242,7 +1287,7 @@ pub mod api { #[codec(index = 19)] InUse, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] Attempted(runtime_types::xcm::v3::traits::Outcome), @@ -1369,17 +1414,17 @@ pub mod api { } pub mod polkadot_core_primitives { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct InboundDownwardMessage<_0> { pub sent_at: _0, pub msg: ::std::vec::Vec<::core::primitive::u8>, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct InboundHrmpMessage<_0> { pub sent_at: _0, pub data: ::std::vec::Vec<::core::primitive::u8>, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct OutboundHrmpMessage<_0> { pub recipient: _0, pub data: ::std::vec::Vec<::core::primitive::u8>, @@ -1389,7 +1434,7 @@ pub mod api { use super::runtime_types; pub mod primitives { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); #[derive( :: codec :: Decode, @@ -1397,9 +1442,10 @@ pub mod api { :: subxt :: ext :: codec :: CompactAs, Clone, Debug, + PartialEq, )] pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum XcmpMessageFormat { #[codec(index = 0)] ConcatenatedVersionedXcm, @@ -1414,7 +1460,7 @@ pub mod api { use super::runtime_types; pub mod v4 { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AbridgedHostConfiguration { pub max_code_size: ::core::primitive::u32, pub max_head_data_size: ::core::primitive::u32, @@ -1426,7 +1472,7 @@ pub mod api { pub validation_upgrade_cooldown: ::core::primitive::u32, pub validation_upgrade_delay: ::core::primitive::u32, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AbridgedHrmpChannel { pub max_capacity: ::core::primitive::u32, pub max_total_size: ::core::primitive::u32, @@ -1435,14 +1481,14 @@ pub mod api { pub total_size: ::core::primitive::u32, pub mqc_head: ::core::option::Option<::subxt::utils::H256>, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct PersistedValidationData<_0, _1> { pub parent_head: runtime_types::polkadot_parachain::primitives::HeadData, pub relay_parent_number: _1, pub relay_parent_storage_root: _0, pub max_pov_size: _1, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum UpgradeRestriction { #[codec(index = 0)] Present, @@ -1451,13 +1497,13 @@ pub mod api { } pub mod rialto_parachain_runtime { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct DummyBridgeRefundMillauMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RuntimeCall { #[codec(index = 0)] System(runtime_types::frame_system::pallet::Call), @@ -1484,7 +1530,7 @@ pub mod api { #[codec(index = 56)] BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Call), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RuntimeEvent { #[codec(index = 0)] System(runtime_types::frame_system::pallet::Event), @@ -1522,10 +1568,11 @@ pub mod api { :: subxt :: ext :: codec :: CompactAs, Clone, Debug, + PartialEq, )] pub struct FixedU128(pub ::core::primitive::u128); } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum ArithmeticError { #[codec(index = 0)] Underflow, @@ -1539,9 +1586,9 @@ pub mod api { use super::runtime_types; pub mod app { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); } } @@ -1549,19 +1596,19 @@ pub mod api { use super::runtime_types; pub mod ecdsa { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Signature(pub [::core::primitive::u8; 65usize]); } pub mod ed25519 { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Signature(pub [::core::primitive::u8; 64usize]); } pub mod sr25519 { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Signature(pub [::core::primitive::u8; 64usize]); } } @@ -1571,7 +1618,7 @@ pub mod api { use super::runtime_types; pub mod digest { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum DigestItem { #[codec(index = 6)] PreRuntime( @@ -1596,14 +1643,14 @@ pub mod api { } pub mod unchecked_extrinsic { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct UncheckedExtrinsic<_0, _1, _2, _3>( pub ::std::vec::Vec<::core::primitive::u8>, #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, ); } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum DispatchError { #[codec(index = 0)] Other, @@ -1632,12 +1679,12 @@ pub mod api { #[codec(index = 12)] Unavailable, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ModuleError { pub index: ::core::primitive::u8, pub error: [::core::primitive::u8; 4usize], } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum MultiSignature { #[codec(index = 0)] Ed25519(runtime_types::sp_core::ed25519::Signature), @@ -1646,7 +1693,7 @@ pub mod api { #[codec(index = 2)] Ecdsa(runtime_types::sp_core::ecdsa::Signature), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum TokenError { #[codec(index = 0)] FundsUnavailable, @@ -1667,7 +1714,7 @@ pub mod api { #[codec(index = 8)] NotExpendable, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum TransactionalError { #[codec(index = 0)] LimitReached, @@ -1679,7 +1726,7 @@ pub mod api { use super::runtime_types; pub mod storage_proof { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct StorageProof { pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, } @@ -1687,7 +1734,7 @@ pub mod api { } pub mod sp_version { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RuntimeVersion { pub spec_name: ::std::string::String, pub impl_name: ::std::string::String, @@ -1702,7 +1749,7 @@ pub mod api { } pub mod sp_weights { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RuntimeDbWeight { pub read: ::core::primitive::u64, pub write: ::core::primitive::u64, @@ -1712,7 +1759,7 @@ pub mod api { use super::runtime_types; pub mod double_encoded { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct DoubleEncoded { pub encoded: ::std::vec::Vec<::core::primitive::u8>, } @@ -1721,7 +1768,7 @@ pub mod api { use super::runtime_types; pub mod junction { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Junction { #[codec(index = 0)] Parachain(#[codec(compact)] ::core::primitive::u32), @@ -1762,14 +1809,14 @@ pub mod api { } pub mod multiasset { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum AssetId { #[codec(index = 0)] Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 1)] Abstract(::std::vec::Vec<::core::primitive::u8>), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum AssetInstance { #[codec(index = 0)] Undefined, @@ -1786,37 +1833,37 @@ pub mod api { #[codec(index = 6)] Blob(::std::vec::Vec<::core::primitive::u8>), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Fungibility { #[codec(index = 0)] Fungible(#[codec(compact)] ::core::primitive::u128), #[codec(index = 1)] NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MultiAsset { pub id: runtime_types::xcm::v2::multiasset::AssetId, pub fun: runtime_types::xcm::v2::multiasset::Fungibility, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum MultiAssetFilter { #[codec(index = 0)] Definite(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 1)] Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MultiAssets( pub ::std::vec::Vec, ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum WildFungibility { #[codec(index = 0)] Fungible, #[codec(index = 1)] NonFungible, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum WildMultiAsset { #[codec(index = 0)] All, @@ -1829,7 +1876,7 @@ pub mod api { } pub mod multilocation { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Junctions { #[codec(index = 0)] Here, @@ -1892,7 +1939,7 @@ pub mod api { runtime_types::xcm::v2::junction::Junction, ), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MultiLocation { pub parents: ::core::primitive::u8, pub interior: runtime_types::xcm::v2::multilocation::Junctions, @@ -1900,7 +1947,7 @@ pub mod api { } pub mod traits { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] Overflow, @@ -1956,7 +2003,7 @@ pub mod api { WeightNotComputable, } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum BodyId { #[codec(index = 0)] Unit, @@ -1983,7 +2030,7 @@ pub mod api { #[codec(index = 9)] Treasury, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum BodyPart { #[codec(index = 0)] Voice, @@ -2014,7 +2061,7 @@ pub mod api { denom: ::core::primitive::u32, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Instruction { #[codec(index = 0)] WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), @@ -2154,7 +2201,7 @@ pub mod api { #[codec(index = 27)] UnsubscribeVersion, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum NetworkId { #[codec(index = 0)] Any, @@ -2169,7 +2216,7 @@ pub mod api { #[codec(index = 3)] Kusama, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum OriginKind { #[codec(index = 0)] Native, @@ -2180,7 +2227,7 @@ pub mod api { #[codec(index = 3)] Xcm, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Response { #[codec(index = 0)] Null, @@ -2196,21 +2243,21 @@ pub mod api { #[codec(index = 3)] Version(::core::primitive::u32), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum WeightLimit { #[codec(index = 0)] Unlimited, #[codec(index = 1)] Limited(#[codec(compact)] ::core::primitive::u64), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Xcm(pub ::std::vec::Vec); } pub mod v3 { use super::runtime_types; pub mod junction { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum BodyId { #[codec(index = 0)] Unit, @@ -2233,7 +2280,7 @@ pub mod api { #[codec(index = 9)] Treasury, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum BodyPart { #[codec(index = 0)] Voice, @@ -2264,7 +2311,7 @@ pub mod api { denom: ::core::primitive::u32, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Junction { #[codec(index = 0)] Parachain(#[codec(compact)] ::core::primitive::u32), @@ -2306,7 +2353,7 @@ pub mod api { #[codec(index = 9)] GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum NetworkId { #[codec(index = 0)] ByGenesis([::core::primitive::u8; 32usize]), @@ -2338,7 +2385,7 @@ pub mod api { } pub mod junctions { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Junctions { #[codec(index = 0)] Here, @@ -2404,14 +2451,14 @@ pub mod api { } pub mod multiasset { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum AssetId { #[codec(index = 0)] Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), #[codec(index = 1)] Abstract([::core::primitive::u8; 32usize]), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum AssetInstance { #[codec(index = 0)] Undefined, @@ -2426,37 +2473,37 @@ pub mod api { #[codec(index = 5)] Array32([::core::primitive::u8; 32usize]), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Fungibility { #[codec(index = 0)] Fungible(#[codec(compact)] ::core::primitive::u128), #[codec(index = 1)] NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MultiAsset { pub id: runtime_types::xcm::v3::multiasset::AssetId, pub fun: runtime_types::xcm::v3::multiasset::Fungibility, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum MultiAssetFilter { #[codec(index = 0)] Definite(runtime_types::xcm::v3::multiasset::MultiAssets), #[codec(index = 1)] Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MultiAssets( pub ::std::vec::Vec, ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum WildFungibility { #[codec(index = 0)] Fungible, #[codec(index = 1)] NonFungible, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum WildMultiAsset { #[codec(index = 0)] All, @@ -2478,7 +2525,7 @@ pub mod api { } pub mod multilocation { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MultiLocation { pub parents: ::core::primitive::u8, pub interior: runtime_types::xcm::v3::junctions::Junctions, @@ -2486,7 +2533,7 @@ pub mod api { } pub mod traits { use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] Overflow, @@ -2569,7 +2616,7 @@ pub mod api { #[codec(index = 39)] ExceedsStackLimit, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Outcome { #[codec(index = 0)] Complete(::sp_weights::Weight), @@ -2579,7 +2626,7 @@ pub mod api { Error(runtime_types::xcm::v3::traits::Error), } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Instruction { #[codec(index = 0)] WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), @@ -2788,7 +2835,7 @@ pub mod api { >, }, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum MaybeErrorCode { #[codec(index = 0)] Success, @@ -2805,7 +2852,7 @@ pub mod api { >, ), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct PalletInfo { #[codec(compact)] pub index: ::core::primitive::u32, @@ -2822,14 +2869,14 @@ pub mod api { #[codec(compact)] pub patch: ::core::primitive::u32, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct QueryResponseInfo { pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, #[codec(compact)] pub query_id: ::core::primitive::u64, pub max_weight: ::sp_weights::Weight, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Response { #[codec(index = 0)] Null, @@ -2853,31 +2900,31 @@ pub mod api { #[codec(index = 5)] DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum WeightLimit { #[codec(index = 0)] Unlimited, #[codec(index = 1)] Limited(::sp_weights::Weight), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Xcm(pub ::std::vec::Vec); } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedMultiAssets { #[codec(index = 1)] V2(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 3)] V3(runtime_types::xcm::v3::multiasset::MultiAssets), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedMultiLocation { #[codec(index = 1)] V2(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 3)] V3(runtime_types::xcm::v3::multilocation::MultiLocation), } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug)] + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedXcm { #[codec(index = 2)] V2(runtime_types::xcm::v2::Xcm), diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index bb7be12979f20..e8d31ee83c33b 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -56,7 +56,7 @@ impl Chain for RialtoParachain { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); type SignedBlock = bp_polkadot_core::SignedBlock; - type Call = runtime_types::rialto_parachain_runtime::RuntimeCall; + type Call = RuntimeCall; } impl ChainWithBalances for RialtoParachain { From 3f3f991e04b46147e09c33a45665f2cb359df749 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 3 May 2023 15:33:45 +0200 Subject: [PATCH 1056/1210] Add `MessagesPalletInstance` for integrity tests (#2107) --- bin/millau/runtime/src/rialto_messages.rs | 2 +- .../runtime/src/rialto_parachain_messages.rs | 2 +- .../runtime/src/millau_messages.rs | 6 +++++- bin/rialto/runtime/src/millau_messages.rs | 2 +- bin/runtime-common/src/integrity.rs | 18 +++++++++++------- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index b71eb76d90a6c..04084e0b9520c 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -166,7 +166,7 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( + check_message_lane_weights::( bp_rialto::EXTRA_STORAGE_PROOF_SIZE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 8d5216d96c939..1050f500fe8c1 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -172,7 +172,7 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( + check_message_lane_weights::( bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE, bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 3c523ebfa1245..68c9cbbec6011 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -150,7 +150,11 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( + check_message_lane_weights::< + bp_rialto_parachain::RialtoParachain, + Runtime, + WithMillauMessagesInstance, + >( bp_millau::EXTRA_STORAGE_PROOF_SIZE, bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index a7d1d19f0d8d8..a99243cc3e6a9 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -150,7 +150,7 @@ mod tests { #[test] fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( + check_message_lane_weights::( bp_millau::EXTRA_STORAGE_PROOF_SIZE, bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index bf3d239eefd64..aa698b0b95e9d 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -292,7 +292,8 @@ where /// Check that the message lane weights are correct. pub fn check_message_lane_weights< C: Chain, - T: frame_system::Config + pallet_bridge_messages::Config, + T: frame_system::Config + pallet_bridge_messages::Config, + MessagesPalletInstance: 'static, >( bridged_chain_extra_storage_proof_size: u32, this_chain_max_unrewarded_relayers: MessageNonce, @@ -303,15 +304,15 @@ pub fn check_message_lane_weights< // in other words: pass true for all known production chains runtime_includes_refund_extension: bool, ) { - type Weights = ::WeightInfo; + type Weights = >::WeightInfo; // check basic weight assumptions - pallet_bridge_messages::ensure_weights_are_correct::>(); + pallet_bridge_messages::ensure_weights_are_correct::>(); // check that weights allow us to receive messages let max_incoming_message_proof_size = bridged_chain_extra_storage_proof_size .saturating_add(messages::target::maximal_incoming_message_size(C::max_extrinsic_size())); - pallet_bridge_messages::ensure_able_to_receive_message::>( + pallet_bridge_messages::ensure_able_to_receive_message::>( C::max_extrinsic_size(), C::max_extrinsic_weight(), max_incoming_message_proof_size, @@ -321,7 +322,7 @@ pub fn check_message_lane_weights< // check that weights allow us to receive delivery confirmations let max_incoming_inbound_lane_data_proof_size = InboundLaneData::<()>::encoded_size_hint_u32(this_chain_max_unrewarded_relayers as _); - pallet_bridge_messages::ensure_able_to_receive_confirmation::>( + pallet_bridge_messages::ensure_able_to_receive_confirmation::>( C::max_extrinsic_size(), C::max_extrinsic_weight(), max_incoming_inbound_lane_data_proof_size, @@ -336,9 +337,12 @@ pub fn check_message_lane_weights< // ensures the extension will not refund weight when it doesn't need to (i.e. if pallet // weights do not account weights of refund extension). if runtime_includes_refund_extension { - assert_ne!(Weights::::receive_messages_proof_overhead_from_runtime(), Weight::zero()); assert_ne!( - Weights::::receive_messages_delivery_proof_overhead_from_runtime(), + Weights::::receive_messages_proof_overhead_from_runtime(), + Weight::zero() + ); + assert_ne!( + Weights::::receive_messages_delivery_proof_overhead_from_runtime(), Weight::zero() ); } From d508de22639209ae4fb0d8521a1d1c5530a0e1df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 02:07:20 +0000 Subject: [PATCH 1057/1210] Bump sysinfo from 0.28.4 to 0.29.0 Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.28.4 to 0.29.0. - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/commits) --- updated-dependencies: - dependency-name: sysinfo dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 78b7fd8fe97f1..65e268a07707e 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -18,7 +18,7 @@ jsonpath_lib = "0.3" log = "0.4.17" num-traits = "0.2" serde_json = "1.0" -sysinfo = "0.28" +sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.28", features = ["rt"] } thiserror = "1.0.40" From c018e0e09105920c566a658b588243b102899a1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 02:05:51 +0000 Subject: [PATCH 1058/1210] Bump clap from 4.2.5 to 4.2.7 Bumps [clap](https://github.com/clap-rs/clap) from 4.2.5 to 4.2.7. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.2.5...v4.2.7) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index fd2096df5fa5f..3b64f98fa53cc 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.5", features = ["derive"] } +clap = { version = "4.2.7", features = ["derive"] } jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.96" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 075e70c961ba8..7dc89a0111c95 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.2.5", features = ["derive"] } +clap = { version = "4.2.7", features = ["derive"] } log = '0.4.17' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 36eaa7021a07e..7f28a15426322 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.5", features = ["derive"] } +clap = { version = "4.2.7", features = ["derive"] } serde_json = "1.0.96" # Bridge dependencies From 63caabc75132ae7782c1e340cd29fbdb22863225 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 9 May 2023 08:21:02 +0300 Subject: [PATCH 1059/1210] Propagate message verification errors (#2114) * Propagate message verification errors * Replace parse_finalized_storage_proof() with storage_proof_checker() * small fixes * fix comment --- bin/runtime-common/src/messages.rs | 218 ++++++++++-------------- modules/grandpa/src/lib.rs | 10 +- modules/messages/src/lib.rs | 20 ++- modules/messages/src/mock.rs | 27 ++- modules/parachains/src/lib.rs | 207 +++++++++++----------- primitives/header-chain/src/lib.rs | 12 +- primitives/messages/Cargo.toml | 2 + primitives/messages/src/lib.rs | 39 ++++- primitives/messages/src/source_chain.rs | 30 ++-- primitives/messages/src/target_chain.rs | 16 +- 10 files changed, 277 insertions(+), 304 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 6f6b19595775d..97a460716c904 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -22,18 +22,19 @@ pub use bp_runtime::{RangeInclusiveExt, UnderlyingChainOf, UnderlyingChainProvider}; -use bp_header_chain::{HeaderChain, HeaderChainError}; +use bp_header_chain::HeaderChain; use bp_messages::{ source_chain::{LaneMessageVerifier, TargetHeaderChain}, target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, + VerificationError, }; -use bp_runtime::{Chain, RawStorageProof, Size, StorageProofChecker, StorageProofError}; +use bp_runtime::{Chain, RawStorageProof, Size, StorageProofChecker}; use codec::{Decode, Encode}; use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; use hash_db::Hasher; use scale_info::TypeInfo; -use sp_std::{convert::TryFrom, fmt::Debug, marker::PhantomData, vec::Vec}; +use sp_std::{convert::TryFrom, marker::PhantomData, vec::Vec}; /// Bidirectional message bridge. pub trait MessageBridge { @@ -74,29 +75,6 @@ pub type BalanceOf = bp_runtime::BalanceOf>; /// Type of origin that is used on the chain. pub type OriginOf = ::RuntimeOrigin; -/// Error that happens during message verification. -#[derive(Debug, PartialEq, Eq)] -pub enum Error { - /// The message proof is empty. - EmptyMessageProof, - /// Error returned by the bridged header chain. - HeaderChain(HeaderChainError), - /// Error returned while reading/decoding inbound lane data from the storage proof. - InboundLaneStorage(StorageProofError), - /// The declared message weight is incorrect. - InvalidMessageWeight, - /// Declared messages count doesn't match actual value. - MessagesCountMismatch, - /// Error returned while reading/decoding message data from the storage proof. - MessageStorage(StorageProofError), - /// The message is too large. - MessageTooLarge, - /// Error returned while reading/decoding outbound lane data from the storage proof. - OutboundLaneStorage(StorageProofError), - /// Storage proof related error. - StorageProof(StorageProofError), -} - /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { use super::*; @@ -169,14 +147,12 @@ pub mod source { + Into>>, OriginOf>>>, AccountIdOf>: PartialEq + Clone, { - type Error = &'static str; - fn verify_message( _submitter: &OriginOf>, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, _payload: &FromThisChainMessagePayload, - ) -> Result<(), Self::Error> { + ) -> Result<(), VerificationError> { // IMPORTANT: any error that is returned here is fatal for the bridge, because // this code is executed at the bridge hub and message sender actually lives // at some sibling parachain. So we are failing **after** the message has been @@ -200,16 +176,15 @@ pub mod source { impl TargetHeaderChain>> for TargetHeaderChainAdapter { - type Error = Error; type MessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof>>; - fn verify_message(payload: &FromThisChainMessagePayload) -> Result<(), Self::Error> { + fn verify_message(payload: &FromThisChainMessagePayload) -> Result<(), VerificationError> { verify_chain_message::(payload) } fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData>>), Self::Error> { + ) -> Result<(LaneId, InboundLaneData>>), VerificationError> { verify_messages_delivery_proof::(proof) } } @@ -221,7 +196,7 @@ pub mod source { /// check) that would reject message (see `FromThisChainMessageVerifier`). pub fn verify_chain_message( payload: &FromThisChainMessagePayload, - ) -> Result<(), Error> { + ) -> Result<(), VerificationError> { // IMPORTANT: any error that is returned here is fatal for the bridge, because // this code is executed at the bridge hub and message sender actually lives // at some sibling parachain. So we are failing **after** the message has been @@ -243,7 +218,7 @@ pub mod source { // transaction also contains signatures and signed extensions. Because of this, we reserve // 1/3 of the the maximal extrinsic weight for this data. if payload.len() > maximal_message_size::() as usize { - return Err(Error::MessageTooLarge) + return Err(VerificationError::MessageTooLarge) } Ok(()) @@ -255,31 +230,26 @@ pub mod source { /// parachains, please use the `verify_messages_delivery_proof_from_parachain`. pub fn verify_messages_delivery_proof( proof: FromBridgedChainMessagesDeliveryProof>>, - ) -> Result, Error> { + ) -> Result, VerificationError> { let FromBridgedChainMessagesDeliveryProof { bridged_header_hash, storage_proof, lane } = proof; - B::BridgedHeaderChain::parse_finalized_storage_proof( - bridged_header_hash, - storage_proof, - |mut storage| { - // Messages delivery proof is just proof of single storage key read => any error - // is fatal. - let storage_inbound_lane_data_key = - bp_messages::storage_keys::inbound_lane_data_key( - B::BRIDGED_MESSAGES_PALLET_NAME, - &lane, - ); - let inbound_lane_data = storage - .read_and_decode_mandatory_value(storage_inbound_lane_data_key.0.as_ref()) - .map_err(Error::InboundLaneStorage)?; - - // check that the storage proof doesn't have any untouched trie nodes - storage.ensure_no_unused_nodes().map_err(Error::StorageProof)?; - - Ok((lane, inbound_lane_data)) - }, - ) - .map_err(Error::HeaderChain)? + let mut storage = + B::BridgedHeaderChain::storage_proof_checker(bridged_header_hash, storage_proof) + .map_err(VerificationError::HeaderChain)?; + // Messages delivery proof is just proof of single storage key read => any error + // is fatal. + let storage_inbound_lane_data_key = bp_messages::storage_keys::inbound_lane_data_key( + B::BRIDGED_MESSAGES_PALLET_NAME, + &lane, + ); + let inbound_lane_data = storage + .read_and_decode_mandatory_value(storage_inbound_lane_data_key.0.as_ref()) + .map_err(VerificationError::InboundLaneStorage)?; + + // check that the storage proof doesn't have any untouched trie nodes + storage.ensure_no_unused_nodes().map_err(VerificationError::StorageProof)?; + + Ok((lane, inbound_lane_data)) } } @@ -335,13 +305,12 @@ pub mod target { pub struct SourceHeaderChainAdapter(PhantomData); impl SourceHeaderChain for SourceHeaderChainAdapter { - type Error = Error; type MessagesProof = FromBridgedChainMessagesProof>>; fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result, Self::Error> { + ) -> Result, VerificationError> { verify_messages_proof::(proof, messages_count) } } @@ -357,7 +326,7 @@ pub mod target { pub fn verify_messages_proof( proof: FromBridgedChainMessagesProof>>, messages_count: u32, - ) -> Result, Error> { + ) -> Result, VerificationError> { let FromBridgedChainMessagesProof { bridged_header_hash, storage_proof, @@ -365,57 +334,52 @@ pub mod target { nonces_start, nonces_end, } = proof; + let storage = + B::BridgedHeaderChain::storage_proof_checker(bridged_header_hash, storage_proof) + .map_err(VerificationError::HeaderChain)?; + let mut parser = StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default() }; let nonces_range = nonces_start..=nonces_end; - B::BridgedHeaderChain::parse_finalized_storage_proof( - bridged_header_hash, - storage_proof, - |storage| { - let mut parser = - StorageProofCheckerAdapter::<_, B> { storage, _dummy: Default::default() }; - - // receiving proofs where end < begin is ok (if proof includes outbound lane state) - let messages_in_the_proof = nonces_range.checked_len().unwrap_or(0); - if messages_in_the_proof != MessageNonce::from(messages_count) { - return Err(Error::MessagesCountMismatch) - } - - // Read messages first. All messages that are claimed to be in the proof must - // be in the proof. So any error in `read_value`, or even missing value is fatal. - // - // Mind that we allow proofs with no messages if outbound lane state is proved. - let mut messages = Vec::with_capacity(messages_in_the_proof as _); - for nonce in nonces_range { - let message_key = MessageKey { lane_id: lane, nonce }; - let message_payload = parser.read_and_decode_message_payload(&message_key)?; - messages.push(Message { key: message_key, payload: message_payload }); - } - - // Now let's check if proof contains outbound lane state proof. It is optional, so - // we simply ignore `read_value` errors and missing value. - let proved_lane_messages = ProvedLaneMessages { - lane_state: parser.read_and_decode_outbound_lane_data(&lane)?, - messages, - }; - - // Now we may actually check if the proof is empty or not. - if proved_lane_messages.lane_state.is_none() && - proved_lane_messages.messages.is_empty() - { - return Err(Error::EmptyMessageProof) - } - - // check that the storage proof doesn't have any untouched trie nodes - parser.storage.ensure_no_unused_nodes().map_err(Error::StorageProof)?; - - // We only support single lane messages in this generated_schema - let mut proved_messages = ProvedMessages::new(); - proved_messages.insert(lane, proved_lane_messages); - - Ok(proved_messages) - }, - ) - .map_err(Error::HeaderChain)? + // receiving proofs where end < begin is ok (if proof includes outbound lane state) + let messages_in_the_proof = nonces_range.checked_len().unwrap_or(0); + if messages_in_the_proof != MessageNonce::from(messages_count) { + return Err(VerificationError::MessagesCountMismatch) + } + + // Read messages first. All messages that are claimed to be in the proof must + // be in the proof. So any error in `read_value`, or even missing value is fatal. + // + // Mind that we allow proofs with no messages if outbound lane state is proved. + let mut messages = Vec::with_capacity(messages_in_the_proof as _); + for nonce in nonces_range { + let message_key = MessageKey { lane_id: lane, nonce }; + let message_payload = parser.read_and_decode_message_payload(&message_key)?; + messages.push(Message { key: message_key, payload: message_payload }); + } + + // Now let's check if proof contains outbound lane state proof. It is optional, so + // we simply ignore `read_value` errors and missing value. + let proved_lane_messages = ProvedLaneMessages { + lane_state: parser.read_and_decode_outbound_lane_data(&lane)?, + messages, + }; + + // Now we may actually check if the proof is empty or not. + if proved_lane_messages.lane_state.is_none() && proved_lane_messages.messages.is_empty() { + return Err(VerificationError::EmptyMessageProof) + } + + // check that the storage proof doesn't have any untouched trie nodes + parser + .storage + .ensure_no_unused_nodes() + .map_err(VerificationError::StorageProof)?; + + // We only support single lane messages in this generated_schema + let mut proved_messages = ProvedMessages::new(); + proved_messages.insert(lane, proved_lane_messages); + + Ok(proved_messages) } struct StorageProofCheckerAdapter { @@ -427,7 +391,7 @@ pub mod target { fn read_and_decode_outbound_lane_data( &mut self, lane_id: &LaneId, - ) -> Result, Error> { + ) -> Result, VerificationError> { let storage_outbound_lane_data_key = bp_messages::storage_keys::outbound_lane_data_key( B::BRIDGED_MESSAGES_PALLET_NAME, lane_id, @@ -435,13 +399,13 @@ pub mod target { self.storage .read_and_decode_opt_value(storage_outbound_lane_data_key.0.as_ref()) - .map_err(Error::OutboundLaneStorage) + .map_err(VerificationError::OutboundLaneStorage) } fn read_and_decode_message_payload( &mut self, message_key: &MessageKey, - ) -> Result { + ) -> Result { let storage_message_key = bp_messages::storage_keys::message_key( B::BRIDGED_MESSAGES_PALLET_NAME, &message_key.lane_id, @@ -449,7 +413,7 @@ pub mod target { ); self.storage .read_and_decode_mandatory_value(storage_message_key.0.as_ref()) - .map_err(Error::MessageStorage) + .map_err(VerificationError::MessageStorage) } } } @@ -470,8 +434,8 @@ mod tests { }, mock::*, }; - use bp_header_chain::StoredHeaderDataBuilder; - use bp_runtime::HeaderId; + use bp_header_chain::{HeaderChainError, StoredHeaderDataBuilder}; + use bp_runtime::{HeaderId, StorageProofError}; use codec::Encode; use sp_core::H256; use sp_runtime::traits::Header as _; @@ -559,7 +523,7 @@ mod tests { using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { target::verify_messages_proof::(proof, 5) }), - Err(Error::MessagesCountMismatch), + Err(VerificationError::MessagesCountMismatch), ); } @@ -569,7 +533,7 @@ mod tests { using_messages_proof(10, None, encode_all_messages, encode_lane_data, |proof| { target::verify_messages_proof::(proof, 15) }), - Err(Error::MessagesCountMismatch), + Err(VerificationError::MessagesCountMismatch), ); } @@ -582,7 +546,7 @@ mod tests { pallet_bridge_grandpa::ImportedHeaders::::remove(bridged_header_hash); target::verify_messages_proof::(proof, 10) }), - Err(Error::HeaderChain(HeaderChainError::UnknownHeader)), + Err(VerificationError::HeaderChain(HeaderChainError::UnknownHeader)), ); } @@ -605,7 +569,7 @@ mod tests { ); target::verify_messages_proof::(proof, 10) }), - Err(Error::HeaderChain(HeaderChainError::StorageProof( + Err(VerificationError::HeaderChain(HeaderChainError::StorageProof( StorageProofError::StorageRootMismatch ))), ); @@ -620,7 +584,7 @@ mod tests { proof.storage_proof.push(node); target::verify_messages_proof::(proof, 10) },), - Err(Error::HeaderChain(HeaderChainError::StorageProof( + Err(VerificationError::HeaderChain(HeaderChainError::StorageProof( StorageProofError::DuplicateNodesInProof ))), ); @@ -633,7 +597,7 @@ mod tests { proof.storage_proof.push(vec![42]); target::verify_messages_proof::(proof, 10) },), - Err(Error::StorageProof(StorageProofError::UnusedNodesInTheProof)), + Err(VerificationError::StorageProof(StorageProofError::UnusedNodesInTheProof)), ); } @@ -647,7 +611,7 @@ mod tests { encode_lane_data, |proof| target::verify_messages_proof::(proof, 10) ), - Err(Error::MessageStorage(StorageProofError::StorageValueEmpty)), + Err(VerificationError::MessageStorage(StorageProofError::StorageValueEmpty)), ); } @@ -667,7 +631,7 @@ mod tests { encode_lane_data, |proof| target::verify_messages_proof::(proof, 10), ), - Err(Error::MessageStorage(StorageProofError::StorageValueDecodeFailed(_))), + Err(VerificationError::MessageStorage(StorageProofError::StorageValueDecodeFailed(_))), ); } @@ -689,7 +653,9 @@ mod tests { }, |proof| target::verify_messages_proof::(proof, 10), ), - Err(Error::OutboundLaneStorage(StorageProofError::StorageValueDecodeFailed(_))), + Err(VerificationError::OutboundLaneStorage( + StorageProofError::StorageValueDecodeFailed(_) + )), ); } @@ -699,7 +665,7 @@ mod tests { using_messages_proof(0, None, encode_all_messages, encode_lane_data, |proof| { target::verify_messages_proof::(proof, 0) },), - Err(Error::EmptyMessageProof), + Err(VerificationError::EmptyMessageProof), ); } @@ -773,7 +739,7 @@ mod tests { proof.nonces_end = u64::MAX; target::verify_messages_proof::(proof, u32::MAX) },), - Err(Error::MessagesCountMismatch), + Err(VerificationError::MessagesCountMismatch), ); } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 329e4c2113677..50286512db896 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -1212,11 +1212,8 @@ mod tests { fn parse_finalized_storage_proof_rejects_proof_on_unknown_header() { run_test(|| { assert_noop!( - Pallet::::parse_finalized_storage_proof( - Default::default(), - vec![], - |_| (), - ), + Pallet::::storage_proof_checker(Default::default(), vec![],) + .map(|_| ()), bp_header_chain::HeaderChainError::UnknownHeader, ); }); @@ -1235,8 +1232,7 @@ mod tests { >::insert(hash, header.build()); assert_ok!( - Pallet::::parse_finalized_storage_proof(hash, storage_proof, |_| (),), - (), + Pallet::::storage_proof_checker(hash, storage_proof).map(|_| ()) ); }); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 045015b775125..6e27c7f2f7aeb 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -61,7 +61,7 @@ use bp_messages::{ }, total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, - OutboundMessageDetails, UnrewardedRelayersState, + OutboundMessageDetails, UnrewardedRelayersState, VerificationError, }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size}; use codec::{Decode, Encode, MaxEncodedLen}; @@ -557,9 +557,9 @@ pub mod pallet { /// The message is too large to be sent over the bridge. MessageIsTooLarge, /// Message has been treated as invalid by chain verifier. - MessageRejectedByChainVerifier, + MessageRejectedByChainVerifier(VerificationError), /// Message has been treated as invalid by lane verifier. - MessageRejectedByLaneVerifier, + MessageRejectedByLaneVerifier(VerificationError), /// Submitter has failed to pay fee for delivering and dispatching messages. FailedToWithdrawMessageFee, /// The transaction brings too many messages. @@ -732,7 +732,7 @@ fn send_message, I: 'static>( err, ); - Error::::MessageRejectedByChainVerifier + Error::::MessageRejectedByChainVerifier(err) })?; // now let's enforce any additional lane rules @@ -746,7 +746,7 @@ fn send_message, I: 'static>( err, ); - Error::::MessageRejectedByLaneVerifier + Error::::MessageRejectedByLaneVerifier(err) }, )?; @@ -918,7 +918,7 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag fn verify_and_decode_messages_proof( proof: Chain::MessagesProof, messages_count: u32, -) -> Result>, Chain::Error> { +) -> Result>, VerificationError> { // `receive_messages_proof` weight formula and `MaxUnconfirmedMessagesAtInboundLane` check // guarantees that the `message_count` is sane and Vec may be allocated. // (tx with too many messages will either be rejected from the pool, or will fail earlier) @@ -1177,7 +1177,9 @@ mod tests { TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN, ), - Error::::MessageRejectedByChainVerifier, + Error::::MessageRejectedByChainVerifier(VerificationError::Other( + mock::TEST_ERROR + )), ); }); } @@ -1190,7 +1192,9 @@ mod tests { message.reject_by_lane_verifier = true; assert_noop!( send_message::(RuntimeOrigin::signed(1), TEST_LANE_ID, message,), - Error::::MessageRejectedByLaneVerifier, + Error::::MessageRejectedByLaneVerifier(VerificationError::Other( + mock::TEST_ERROR + )), ); }); } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 2e45d5b601f0b..f0516fbc23f96 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -27,7 +27,7 @@ use bp_messages::{ ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, - OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, + OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, VerificationError, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -295,13 +295,11 @@ impl Size for TestMessagesDeliveryProof { pub struct TestTargetHeaderChain; impl TargetHeaderChain for TestTargetHeaderChain { - type Error = &'static str; - type MessagesDeliveryProof = TestMessagesDeliveryProof; - fn verify_message(payload: &TestPayload) -> Result<(), Self::Error> { + fn verify_message(payload: &TestPayload) -> Result<(), VerificationError> { if *payload == PAYLOAD_REJECTED_BY_TARGET_CHAIN { - Err(TEST_ERROR) + Err(VerificationError::Other(TEST_ERROR)) } else { Ok(()) } @@ -309,8 +307,8 @@ impl TargetHeaderChain for TestTargetHeaderChain { fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - proof.0.map_err(|_| TEST_ERROR) + ) -> Result<(LaneId, InboundLaneData), VerificationError> { + proof.0.map_err(|_| VerificationError::Other(TEST_ERROR)) } } @@ -319,18 +317,16 @@ impl TargetHeaderChain for TestTargetHeaderChain { pub struct TestLaneMessageVerifier; impl LaneMessageVerifier for TestLaneMessageVerifier { - type Error = &'static str; - fn verify_message( _submitter: &RuntimeOrigin, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, payload: &TestPayload, - ) -> Result<(), Self::Error> { + ) -> Result<(), VerificationError> { if !payload.reject_by_lane_verifier { Ok(()) } else { - Err(TEST_ERROR) + Err(VerificationError::Other(TEST_ERROR)) } } } @@ -400,15 +396,16 @@ impl DeliveryConfirmationPayments for TestDeliveryConfirmationPayment pub struct TestSourceHeaderChain; impl SourceHeaderChain for TestSourceHeaderChain { - type Error = &'static str; - type MessagesProof = TestMessagesProof; fn verify_messages_proof( proof: Self::MessagesProof, _messages_count: u32, - ) -> Result, Self::Error> { - proof.result.map(|proof| proof.into_iter().collect()).map_err(|_| TEST_ERROR) + ) -> Result, VerificationError> { + proof + .result + .map(|proof| proof.into_iter().collect()) + .map_err(|_| VerificationError::Other(TEST_ERROR)) } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 6c89b09513cd6..7670a3bacfe8d 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -91,6 +91,8 @@ pub mod pallet { BoundedStorageValue<>::MaxParaHeadDataSize, ParaStoredHeaderData>; /// Weight info of the given parachains pallet. pub type WeightInfoOf = >::WeightInfo; + type GrandpaPalletOf = + pallet_bridge_grandpa::Pallet>::BridgesGrandpaPalletInstance>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -125,14 +127,8 @@ pub mod pallet { UnknownRelayChainBlock, /// The number of stored relay block is different from what the relayer has provided. InvalidRelayChainBlockNumber, - /// Error generated by a method defined in `bp-header-chain`. - HeaderChain(HeaderChainError), - /// Given parachain head is unknown. - UnknownParaHead, - /// The storage proof doesn't contains storage root. So it is invalid for given header. - StorageRootMismatch, - /// Failed to extract state root from given parachain head. - FailedToExtractStateRoot, + /// Parachain heads storage proof is invalid. + HeaderChainStorageProof(HeaderChainError), /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } @@ -337,112 +333,113 @@ pub mod pallet { parachains.len() as _, ); - pallet_bridge_grandpa::Pallet::::parse_finalized_storage_proof( + let mut storage = GrandpaPalletOf::::storage_proof_checker( relay_block_hash, parachain_heads_proof.0, - move |mut storage| { - for (parachain, parachain_head_hash) in parachains { - let parachain_head = match Pallet::::read_parachain_head(&mut storage, parachain) { - Ok(Some(parachain_head)) => parachain_head, - Ok(None) => { - log::trace!( - target: LOG_TARGET, - "The head of parachain {:?} is None. {}", - parachain, - if ParasInfo::::contains_key(parachain) { - "Looks like it is not yet registered at the source relay chain" - } else { - "Looks like it has been deregistered from the source relay chain" - }, - ); - Self::deposit_event(Event::MissingParachainHead { parachain }); - continue; - }, - Err(e) => { - log::trace!( - target: LOG_TARGET, - "The read of head of parachain {:?} has failed: {:?}", - parachain, - e, - ); - Self::deposit_event(Event::MissingParachainHead { parachain }); - continue; + ) + .map_err(Error::::HeaderChainStorageProof)?; + + for (parachain, parachain_head_hash) in parachains { + let parachain_head = match Self::read_parachain_head(&mut storage, parachain) { + Ok(Some(parachain_head)) => parachain_head, + Ok(None) => { + log::trace!( + target: LOG_TARGET, + "The head of parachain {:?} is None. {}", + parachain, + if ParasInfo::::contains_key(parachain) { + "Looks like it is not yet registered at the source relay chain" + } else { + "Looks like it has been deregistered from the source relay chain" }, - }; + ); + Self::deposit_event(Event::MissingParachainHead { parachain }); + continue + }, + Err(e) => { + log::trace!( + target: LOG_TARGET, + "The read of head of parachain {:?} has failed: {:?}", + parachain, + e, + ); + Self::deposit_event(Event::MissingParachainHead { parachain }); + continue + }, + }; + + // if relayer has specified invalid parachain head hash, ignore the head + // (this isn't strictly necessary, but better safe than sorry) + let actual_parachain_head_hash = parachain_head.hash(); + if parachain_head_hash != actual_parachain_head_hash { + log::trace!( + target: LOG_TARGET, + "The submitter has specified invalid parachain {:?} head hash: \ + {:?} vs {:?}", + parachain, + parachain_head_hash, + actual_parachain_head_hash, + ); + Self::deposit_event(Event::IncorrectParachainHeadHash { + parachain, + parachain_head_hash, + actual_parachain_head_hash, + }); + continue + } - // if relayer has specified invalid parachain head hash, ignore the head - // (this isn't strictly necessary, but better safe than sorry) - let actual_parachain_head_hash = parachain_head.hash(); - if parachain_head_hash != actual_parachain_head_hash { + // convert from parachain head into stored parachain head data + let parachain_head_data = + match T::ParaStoredHeaderDataBuilder::try_build(parachain, ¶chain_head) { + Some(parachain_head_data) => parachain_head_data, + None => { log::trace!( - target: LOG_TARGET, - "The submitter has specified invalid parachain {:?} head hash: {:?} vs {:?}", - parachain, - parachain_head_hash, - actual_parachain_head_hash, - ); - Self::deposit_event(Event::IncorrectParachainHeadHash { - parachain, - parachain_head_hash, - actual_parachain_head_hash, - }); - continue; - } - - // convert from parachain head into stored parachain head data - let parachain_head_data = match T::ParaStoredHeaderDataBuilder::try_build( - parachain, - ¶chain_head, - ) { - Some(parachain_head_data) => parachain_head_data, - None => { - log::trace!( target: LOG_TARGET, "The head of parachain {:?} has been provided, but it is not tracked by the pallet", parachain, ); - Self::deposit_event(Event::UntrackedParachainRejected { parachain }); - continue; - }, - }; - - let update_result: Result<_, ()> = ParasInfo::::try_mutate(parachain, |stored_best_head| { - let artifacts = Pallet::::update_parachain_head( - parachain, - stored_best_head.take(), - relay_block_number, - parachain_head_data, - parachain_head_hash, - )?; - *stored_best_head = Some(artifacts.best_head); - Ok(artifacts.prune_happened) - }); - - // we're refunding weight if update has not happened and if pruning has not happened - let is_update_happened = matches!(update_result, Ok(_)); - if !is_update_happened { - actual_weight = actual_weight - .saturating_sub(WeightInfoOf::::parachain_head_storage_write_weight(T::DbWeight::get())); - } - let is_prune_happened = matches!(update_result, Ok(true)); - if !is_prune_happened { - actual_weight = actual_weight - .saturating_sub(WeightInfoOf::::parachain_head_pruning_weight(T::DbWeight::get())); - } - } + Self::deposit_event(Event::UntrackedParachainRejected { parachain }); + continue + }, + }; + + let update_result: Result<_, ()> = + ParasInfo::::try_mutate(parachain, |stored_best_head| { + let artifacts = Pallet::::update_parachain_head( + parachain, + stored_best_head.take(), + relay_block_number, + parachain_head_data, + parachain_head_hash, + )?; + *stored_best_head = Some(artifacts.best_head); + Ok(artifacts.prune_happened) + }); + + // we're refunding weight if update has not happened and if pruning has not happened + let is_update_happened = matches!(update_result, Ok(_)); + if !is_update_happened { + actual_weight = actual_weight.saturating_sub( + WeightInfoOf::::parachain_head_storage_write_weight( + T::DbWeight::get(), + ), + ); + } + let is_prune_happened = matches!(update_result, Ok(true)); + if !is_prune_happened { + actual_weight = actual_weight.saturating_sub( + WeightInfoOf::::parachain_head_pruning_weight(T::DbWeight::get()), + ); + } + } - // even though we may have accepted some parachain heads, we can't allow relayers to submit - // proof with unused trie nodes - // => treat this as an error - // - // (we can throw error here, because now all our calls are transactional) - storage.ensure_no_unused_nodes() - }, - ) - .and_then(|r| r.map_err(HeaderChainError::StorageProof)) - .map_err(|e| { - log::trace!(target: LOG_TARGET, "Parachain heads storage proof is invalid: {:?}", e); - Error::::HeaderChain(e) + // even though we may have accepted some parachain heads, we can't allow relayers to + // submit proof with unused trie nodes + // => treat this as an error + // + // (we can throw error here, because now all our calls are transactional) + storage.ensure_no_unused_nodes().map_err(|e| { + Error::::HeaderChainStorageProof(HeaderChainError::StorageProof(e)) })?; Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes }) @@ -1438,7 +1435,7 @@ pub(crate) mod tests { // try to import head#5 of parachain#1 at relay chain block #0 assert_noop!( import_parachain_1_head(0, Default::default(), parachains, proof), - Error::::HeaderChain(HeaderChainError::StorageProof( + Error::::HeaderChainStorageProof(HeaderChainError::StorageProof( StorageProofError::StorageRootMismatch )) ); diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5e2bbad242e5b..5b27845472896 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -73,18 +73,14 @@ impl StoredHeaderDataBuilder for H { pub trait HeaderChain { /// Returns state (storage) root of given finalized header. fn finalized_header_state_root(header_hash: HashOf) -> Option>; - /// Parse storage proof using finalized header. - fn parse_finalized_storage_proof( + /// Get storage proof checker using finalized header. + fn storage_proof_checker( header_hash: HashOf, storage_proof: RawStorageProof, - parse: impl FnOnce(StorageProofChecker>) -> R, - ) -> Result { + ) -> Result>, HeaderChainError> { let state_root = Self::finalized_header_state_root(header_hash) .ok_or(HeaderChainError::UnknownHeader)?; - let storage_proof_checker = bp_runtime::StorageProofChecker::new(state_root, storage_proof) - .map_err(HeaderChainError::StorageProof)?; - - Ok(parse(storage_proof_checker)) + StorageProofChecker::new(state_root, storage_proof).map_err(HeaderChainError::StorageProof) } } diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 32a89f6cf78f0..cb35b4ae65b2d 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -14,6 +14,7 @@ serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../header-chain", default-features = false } # Substrate Dependencies @@ -29,6 +30,7 @@ hex-literal = "0.4" default = ["std"] std = [ "bp-runtime/std", + "bp-header-chain/std", "codec/std", "frame-support/std", "scale-info/std", diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index e485aa2f801c3..10aee6ce97b7b 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -20,9 +20,15 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_runtime::{BasicOperatingMode, OperatingMode, RangeInclusiveExt}; +use bp_header_chain::HeaderChainError; +use bp_runtime::{ + messages::MessageDispatchResult, BasicOperatingMode, OperatingMode, RangeInclusiveExt, + StorageProofError, +}; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::RuntimeDebug; +use frame_support::{PalletError, RuntimeDebug}; +// Weight is reexported to avoid additional frame-support dependencies in related crates. +pub use frame_support::weights::Weight; use scale_info::TypeInfo; use source_chain::RelayersRewards; use sp_core::TypeId; @@ -32,10 +38,6 @@ pub mod source_chain; pub mod storage_keys; pub mod target_chain; -use bp_runtime::messages::MessageDispatchResult; -// Weight is reexported to avoid additional frame-support dependencies in related crates. -pub use frame_support::weights::Weight; - /// Messages pallet operating mode. #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] @@ -414,6 +416,31 @@ pub enum BridgeMessagesCall { }, } +/// Error that happens during message verification. +#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)] +pub enum VerificationError { + /// The message proof is empty. + EmptyMessageProof, + /// Error returned by the bridged header chain. + HeaderChain(HeaderChainError), + /// Error returned while reading/decoding inbound lane data from the storage proof. + InboundLaneStorage(StorageProofError), + /// The declared message weight is incorrect. + InvalidMessageWeight, + /// Declared messages count doesn't match actual value. + MessagesCountMismatch, + /// Error returned while reading/decoding message data from the storage proof. + MessageStorage(StorageProofError), + /// The message is too large. + MessageTooLarge, + /// Error returned while reading/decoding outbound lane data from the storage proof. + OutboundLaneStorage(StorageProofError), + /// Storage proof related error. + StorageProof(StorageProofError), + /// Custom error + Other(#[codec(skip)] &'static str), +} + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 394a934171fea..f3c50b84a09ad 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -16,7 +16,7 @@ //! Primitives of messages module, that are used on the source chain. -use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData}; +use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData, VerificationError}; use crate::UnrewardedRelayer; use bp_runtime::Size; @@ -40,9 +40,6 @@ pub type RelayersRewards = BTreeMap; /// source chain to the target chain. The `AccountId` type here means the account /// type used by the source chain. pub trait TargetHeaderChain { - /// Error type. - type Error: Debug; - /// Proof that messages have been received by target chain. type MessagesDeliveryProof: Parameter + Size; @@ -58,12 +55,12 @@ pub trait TargetHeaderChain { /// 1MB. BTC nodes aren't accepting transactions that are larger than 1MB, so relayer /// will be unable to craft valid transaction => this (and all subsequent) messages will /// never be delivered. - fn verify_message(payload: &Payload) -> Result<(), Self::Error>; + fn verify_message(payload: &Payload) -> Result<(), VerificationError>; /// Verify messages delivery proof and return lane && nonce of the latest received message. fn verify_messages_delivery_proof( proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error>; + ) -> Result<(LaneId, InboundLaneData), VerificationError>; } /// Lane message verifier. @@ -75,9 +72,6 @@ pub trait TargetHeaderChain { /// /// Any fee requirements should also be enforced here. pub trait LaneMessageVerifier { - /// Error type. - type Error: Debug + Into<&'static str>; - /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the /// lane. fn verify_message( @@ -85,7 +79,7 @@ pub trait LaneMessageVerifier { lane: &LaneId, outbound_data: &OutboundLaneData, payload: &Payload, - ) -> Result<(), Self::Error>; + ) -> Result<(), VerificationError>; } /// Manages payments that are happening at the source chain during delivery confirmation @@ -169,31 +163,27 @@ const ALL_OUTBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all outbound messages"; impl TargetHeaderChain for ForbidOutboundMessages { - type Error = &'static str; - type MessagesDeliveryProof = (); - fn verify_message(_payload: &Payload) -> Result<(), Self::Error> { - Err(ALL_OUTBOUND_MESSAGES_REJECTED) + fn verify_message(_payload: &Payload) -> Result<(), VerificationError> { + Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED)) } fn verify_messages_delivery_proof( _proof: Self::MessagesDeliveryProof, - ) -> Result<(LaneId, InboundLaneData), Self::Error> { - Err(ALL_OUTBOUND_MESSAGES_REJECTED) + ) -> Result<(LaneId, InboundLaneData), VerificationError> { + Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED)) } } impl LaneMessageVerifier for ForbidOutboundMessages { - type Error = &'static str; - fn verify_message( _submitter: &SenderOrigin, _lane: &LaneId, _outbound_data: &OutboundLaneData, _payload: &Payload, - ) -> Result<(), Self::Error> { - Err(ALL_OUTBOUND_MESSAGES_REJECTED) + ) -> Result<(), VerificationError> { + Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED)) } } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 3c2e8cf0cb074..385bc4ac373d6 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -16,7 +16,9 @@ //! Primitives of messages module, that are used on the target chain. -use crate::{LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData}; +use crate::{ + LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, VerificationError, +}; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; @@ -58,9 +60,6 @@ pub struct DispatchMessage { /// can't change. Wrong implementation may lead to invalid lane states (i.e. lane /// that's stuck) and/or processing messages without paying fees. pub trait SourceHeaderChain { - /// Error type. - type Error: Debug; - /// Proof that messages are sent from source chain. This may also include proof /// of corresponding outbound lane states. type MessagesProof: Parameter + Size; @@ -79,7 +78,7 @@ pub trait SourceHeaderChain { fn verify_messages_proof( proof: Self::MessagesProof, messages_count: u32, - ) -> Result, Self::Error>; + ) -> Result, VerificationError>; } /// Called when inbound message is received. @@ -164,21 +163,20 @@ pub struct ForbidInboundMessages( PhantomData<(MessagesProof, DispatchPayload)>, ); -/// Error message that is used in `ForbidOutboundMessages` implementation. +/// Error message that is used in `ForbidInboundMessages` implementation. const ALL_INBOUND_MESSAGES_REJECTED: &str = "This chain is configured to reject all inbound messages"; impl SourceHeaderChain for ForbidInboundMessages { - type Error = &'static str; type MessagesProof = MessagesProof; fn verify_messages_proof( _proof: Self::MessagesProof, _messages_count: u32, - ) -> Result, Self::Error> { - Err(ALL_INBOUND_MESSAGES_REJECTED) + ) -> Result, VerificationError> { + Err(VerificationError::Other(ALL_INBOUND_MESSAGES_REJECTED)) } } From 2e05ce03ba4580bd2db02c8b8cb80c339bf38e6c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 9 May 2023 11:43:15 +0300 Subject: [PATCH 1060/1210] Propagate message receival confirmation errors (#2116) * Propagate message receival confirmation errors * spellcheck --- modules/messages/src/lib.rs | 67 ++++++---------- modules/messages/src/outbound_lane.rs | 106 ++++++++++++-------------- 2 files changed, 71 insertions(+), 102 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 6e27c7f2f7aeb..02255e15082f6 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -48,7 +48,7 @@ pub use weights_ext::{ use crate::{ inbound_lane::{InboundLane, InboundLaneStorage}, - outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationResult}, + outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationError}, }; use bp_messages::{ @@ -458,36 +458,13 @@ pub mod pallet { // mark messages as delivered let mut lane = outbound_lane::(lane_id); let last_delivered_nonce = lane_data.last_delivered_nonce(); - let confirmed_messages = match lane.confirm_delivery( - relayers_state.total_messages, - last_delivered_nonce, - &lane_data.relayers, - ) { - ReceivalConfirmationResult::ConfirmedMessages(confirmed_messages) => - Some(confirmed_messages), - ReceivalConfirmationResult::NoNewConfirmations => None, - ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected( - to_confirm_messages_count, - ) => { - log::trace!( - target: LOG_TARGET, - "Messages delivery proof contains too many messages to confirm: {} vs declared {}", - to_confirm_messages_count, - relayers_state.total_messages, - ); - - fail!(Error::::TryingToConfirmMoreMessagesThanExpected); - }, - error => { - log::trace!( - target: LOG_TARGET, - "Messages delivery proof contains invalid unrewarded relayers vec: {:?}", - error, - ); - - fail!(Error::::InvalidUnrewardedRelayers); - }, - }; + let confirmed_messages = lane + .confirm_delivery( + relayers_state.total_messages, + last_delivered_nonce, + &lane_data.relayers, + ) + .map_err(Error::::ReceivalConfirmation)?; if let Some(confirmed_messages) = confirmed_messages { // emit 'delivered' event @@ -568,8 +545,6 @@ pub mod pallet { InvalidMessagesProof, /// Invalid messages delivery proof has been submitted. InvalidMessagesDeliveryProof, - /// The bridged chain has invalid `UnrewardedRelayers` in its storage (fatal for the lane). - InvalidUnrewardedRelayers, /// The relayer has declared invalid unrewarded relayers state in the /// `receive_messages_delivery_proof` call. InvalidUnrewardedRelayersState, @@ -578,9 +553,8 @@ pub mod pallet { InsufficientDispatchWeight, /// The message someone is trying to work with (i.e. increase fee) is not yet sent. MessageIsNotYetSent, - /// The number of actually confirmed messages is going to be larger than the number of - /// messages in the proof. This may mean that this or bridged chain storage is corrupted. - TryingToConfirmMoreMessagesThanExpected, + /// Error confirming messages receival. + ReceivalConfirmation(ReceivalConfirmationError), /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } @@ -941,13 +915,16 @@ fn verify_and_decode_messages_proof::TryingToConfirmMoreMessagesThanExpected, + Error::::ReceivalConfirmation( + ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected + ), ); }); } diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 3d0d4de966a59..bc4fdfab9195d 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -16,16 +16,18 @@ //! Everything about outgoing messages sending. -use crate::Config; +use crate::{Config, LOG_TARGET}; use bp_messages::{ DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, }; +use codec::{Decode, Encode}; use frame_support::{ weights::{RuntimeDbWeight, Weight}, - BoundedVec, RuntimeDebug, + BoundedVec, PalletError, RuntimeDebug, }; use num_traits::Zero; +use scale_info::TypeInfo; use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. @@ -49,13 +51,8 @@ pub trait OutboundLaneStorage { pub type StoredMessagePayload = BoundedVec>::MaximalOutboundPayloadSize>; /// Result of messages receival confirmation. -#[derive(RuntimeDebug, PartialEq, Eq)] -pub enum ReceivalConfirmationResult { - /// New messages have been confirmed by the confirmation transaction. - ConfirmedMessages(DeliveredMessages), - /// Confirmation transaction brings no new confirmation. This may be a result of relayer - /// error or several relayers running. - NoNewConfirmations, +#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)] +pub enum ReceivalConfirmationError { /// Bridged chain is trying to confirm more messages than we have generated. May be a result /// of invalid bridged chain storage. FailedToConfirmFutureMessages, @@ -66,7 +63,7 @@ pub enum ReceivalConfirmationResult { /// bridged chain storage. NonConsecutiveUnrewardedRelayerEntries, /// The chain has more messages that need to be confirmed than there is in the proof. - TryingToConfirmMoreMessagesThanExpected(MessageNonce), + TryingToConfirmMoreMessagesThanExpected, } /// Outbound messages lane. @@ -105,37 +102,39 @@ impl OutboundLane { max_allowed_messages: MessageNonce, latest_delivered_nonce: MessageNonce, relayers: &VecDeque>, - ) -> ReceivalConfirmationResult { + ) -> Result, ReceivalConfirmationError> { let mut data = self.storage.data(); - if latest_delivered_nonce <= data.latest_received_nonce { - return ReceivalConfirmationResult::NoNewConfirmations + let confirmed_messages = DeliveredMessages { + begin: data.latest_received_nonce.saturating_add(1), + end: latest_delivered_nonce, + }; + if confirmed_messages.total_messages() == 0 { + return Ok(None) } - if latest_delivered_nonce > data.latest_generated_nonce { - return ReceivalConfirmationResult::FailedToConfirmFutureMessages + if confirmed_messages.end > data.latest_generated_nonce { + return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages) } - if latest_delivered_nonce - data.latest_received_nonce > max_allowed_messages { + if confirmed_messages.total_messages() > max_allowed_messages { // that the relayer has declared correct number of messages that the proof contains (it // is checked outside of the function). But it may happen (but only if this/bridged // chain storage is corrupted, though) that the actual number of confirmed messages if // larger than declared. This would mean that 'reward loop' will take more time than the // weight formula accounts, so we can't allow that. - return ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected( - latest_delivered_nonce - data.latest_received_nonce, - ) + log::trace!( + target: LOG_TARGET, + "Messages delivery proof contains too many messages to confirm: {} vs declared {}", + confirmed_messages.total_messages(), + max_allowed_messages, + ); + return Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected) } - if let Err(e) = ensure_unrewarded_relayers_are_correct(latest_delivered_nonce, relayers) { - return e - } + ensure_unrewarded_relayers_are_correct(confirmed_messages.end, relayers)?; - let prev_latest_received_nonce = data.latest_received_nonce; - data.latest_received_nonce = latest_delivered_nonce; + data.latest_received_nonce = confirmed_messages.end; self.storage.set_data(data); - ReceivalConfirmationResult::ConfirmedMessages(DeliveredMessages { - begin: prev_latest_received_nonce + 1, - end: latest_delivered_nonce, - }) + Ok(Some(confirmed_messages)) } /// Prune at most `max_messages_to_prune` already received messages. @@ -176,27 +175,24 @@ impl OutboundLane { fn ensure_unrewarded_relayers_are_correct( latest_received_nonce: MessageNonce, relayers: &VecDeque>, -) -> Result<(), ReceivalConfirmationResult> { - let mut last_entry_end: Option = None; +) -> Result<(), ReceivalConfirmationError> { + let mut expected_entry_begin = relayers.front().map(|entry| entry.messages.begin); for entry in relayers { // unrewarded relayer entry must have at least 1 unconfirmed message // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end < entry.messages.begin { - return Err(ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry) + return Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry) } // every entry must confirm range of messages that follows previous entry range // (guaranteed by the `InboundLane::receive_message()`) - if let Some(last_entry_end) = last_entry_end { - let expected_entry_begin = last_entry_end.checked_add(1); - if expected_entry_begin != Some(entry.messages.begin) { - return Err(ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries) - } + if expected_entry_begin != Some(entry.messages.begin) { + return Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries) } - last_entry_end = Some(entry.messages.end); + expected_entry_begin = entry.messages.end.checked_add(1); // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { - return Err(ReceivalConfirmationResult::FailedToConfirmFutureMessages) + return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages) } } @@ -231,7 +227,7 @@ mod tests { fn assert_3_messages_confirmation_fails( latest_received_nonce: MessageNonce, relayers: &VecDeque>, - ) -> ReceivalConfirmationResult { + ) -> Result, ReceivalConfirmationError> { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); @@ -268,7 +264,7 @@ mod tests { assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), - ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), + Ok(Some(delivered_messages(1..=3))), ); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); @@ -286,19 +282,13 @@ mod tests { assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), - ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), - ); - assert_eq!( - lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), - ReceivalConfirmationResult::NoNewConfirmations, + Ok(Some(delivered_messages(1..=3))), ); + assert_eq!(lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), Ok(None),); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); - assert_eq!( - lane.confirm_delivery(1, 2, &unrewarded_relayers(1..=1)), - ReceivalConfirmationResult::NoNewConfirmations, - ); + assert_eq!(lane.confirm_delivery(1, 2, &unrewarded_relayers(1..=1)), Ok(None),); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 3); }); @@ -308,7 +298,7 @@ mod tests { fn confirm_delivery_rejects_nonce_larger_than_last_generated() { assert_eq!( assert_3_messages_confirmation_fails(10, &unrewarded_relayers(1..=10),), - ReceivalConfirmationResult::FailedToConfirmFutureMessages, + Err(ReceivalConfirmationError::FailedToConfirmFutureMessages), ); } @@ -323,7 +313,7 @@ mod tests { .chain(unrewarded_relayers(3..=3).into_iter()) .collect(), ), - ReceivalConfirmationResult::FailedToConfirmFutureMessages, + Err(ReceivalConfirmationError::FailedToConfirmFutureMessages), ); } @@ -339,7 +329,7 @@ mod tests { .chain(unrewarded_relayers(2..=3).into_iter()) .collect(), ), - ReceivalConfirmationResult::EmptyUnrewardedRelayerEntry, + Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry), ); } @@ -354,7 +344,7 @@ mod tests { .chain(unrewarded_relayers(2..=2).into_iter()) .collect(), ), - ReceivalConfirmationResult::NonConsecutiveUnrewardedRelayerEntries, + Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries), ); } @@ -383,7 +373,7 @@ mod tests { // after confirmation, some messages are received assert_eq!( lane.confirm_delivery(2, 2, &unrewarded_relayers(1..=2)), - ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=2)), + Ok(Some(delivered_messages(1..=2))), ); assert_eq!( lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)), @@ -396,7 +386,7 @@ mod tests { // after last message is confirmed, everything is pruned assert_eq!( lane.confirm_delivery(1, 3, &unrewarded_relayers(3..=3)), - ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(3..=3)), + Ok(Some(delivered_messages(3..=3))), ); assert_eq!( lane.prune_messages(RocksDbWeight::get(), RocksDbWeight::get().writes(101)), @@ -418,15 +408,15 @@ mod tests { lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!( lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), - ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3), + Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), ); assert_eq!( lane.confirm_delivery(2, 3, &unrewarded_relayers(1..=3)), - ReceivalConfirmationResult::TryingToConfirmMoreMessagesThanExpected(3), + Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), ); assert_eq!( lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), - ReceivalConfirmationResult::ConfirmedMessages(delivered_messages(1..=3)), + Ok(Some(delivered_messages(1..=3))), ); }); } From fc9e2e892af4f5e4072d36b608f0cde7cd47b9fb Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 9 May 2023 11:43:36 +0300 Subject: [PATCH 1061/1210] temporarily remove balance guard (#2121) --- relays/client-substrate/src/client.rs | 24 +-- relays/client-substrate/src/guard.rs | 185 +----------------- .../src/finality/guards.rs | 48 ----- .../lib-substrate-relay/src/finality/mod.rs | 1 - 4 files changed, 5 insertions(+), 253 deletions(-) delete mode 100644 relays/lib-substrate-relay/src/finality/guards.rs diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 91ff7b9a214d4..a1c8a22be19d0 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -17,7 +17,7 @@ //! Substrate node client. use crate::{ - chain::{Chain, ChainWithBalances, ChainWithTransactions}, + chain::{Chain, ChainWithTransactions}, rpc::{ SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient, SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, @@ -31,14 +31,12 @@ use async_trait::async_trait; use bp_runtime::{HeaderIdProvider, StorageDoubleMapKeyProvider, StorageMapKeyProvider}; use codec::{Decode, Encode}; use frame_support::weights::Weight; -use frame_system::AccountInfo; use futures::{SinkExt, StreamExt}; use jsonrpsee::{ core::DeserializeOwned, ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder}, }; use num_traits::{Saturating, Zero}; -use pallet_balances::AccountData; use pallet_transaction_payment::RuntimeDispatchInfo; use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT}; use sp_core::{ @@ -424,26 +422,6 @@ impl Client { }) } - /// Return native tokens balance of the account. - pub async fn free_native_balance(&self, account: C::AccountId) -> Result - where - C: ChainWithBalances, - { - self.jsonrpsee_execute(move |client| async move { - let storage_key = C::account_info_storage_key(&account); - let encoded_account_data = - SubstrateStateClient::::storage(&*client, storage_key, None) - .await? - .ok_or(Error::AccountDoesNotExist)?; - let decoded_account_data = AccountInfo::>::decode( - &mut &encoded_account_data.0[..], - ) - .map_err(Error::ResponseParseFailed)?; - Ok(decoded_account_data.data.free) - }) - .await - } - /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 1afbf0d3d17ed..a4ed47424e818 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -20,10 +20,8 @@ use crate::{error::Error, Chain, ChainWithBalances, Client}; use async_trait::async_trait; -use num_traits::CheckedSub; use sp_version::RuntimeVersion; use std::{ - collections::VecDeque, fmt::Display, time::{Duration, Instant}, }; @@ -36,11 +34,6 @@ pub trait Environment: Send + Sync + 'static { /// Return current runtime version. async fn runtime_version(&mut self) -> Result; - /// Return free native balance of the account on the chain. - async fn free_native_balance( - &mut self, - account: C::AccountId, - ) -> Result; /// Return current time. fn now(&self) -> Instant { @@ -99,80 +92,6 @@ pub fn abort_on_spec_version_change( }); } -/// Abort if, during 24 hours, free balance of given account is decreased at least by given value. -/// Other components may increase (or decrease) balance of account and it WILL affect logic of the -/// guard. -pub fn abort_when_account_balance_decreased( - mut env: impl Environment, - account_id: C::AccountId, - maximal_decrease: C::Balance, -) { - const DAY: Duration = Duration::from_secs(60 * 60 * 24); - - async_std::task::spawn(async move { - log::info!( - target: "bridge-guard", - "Starting balance guard for {}/{:?}. Maximal decrease: {:?}", - C::NAME, - account_id, - maximal_decrease, - ); - - let mut balances = VecDeque::new(); - - loop { - let current_time = env.now(); - - // remember balances that are beyound 24h border - if let Some(time_border) = current_time.checked_sub(DAY) { - while balances.front().map(|(time, _)| *time < time_border).unwrap_or(false) { - balances.pop_front(); - } - } - - // read balance of the account - let current_balance = env.free_native_balance(account_id.clone()).await; - - // remember balance and check difference - match current_balance { - Ok(current_balance) => { - // remember balance - balances.push_back((current_time, current_balance)); - - // check if difference between current and oldest balance is too large - let (oldest_time, oldest_balance) = - balances.front().expect("pushed to queue couple of lines above; qed"); - let balances_difference = oldest_balance.checked_sub(¤t_balance); - if balances_difference > Some(maximal_decrease) { - log::error!( - target: "bridge-guard", - "Balance of {} account {:?} has decreased from {:?} to {:?} in {} minutes. Aborting relay", - C::NAME, - account_id, - oldest_balance, - current_balance, - current_time.duration_since(*oldest_time).as_secs() / 60, - ); - - env.abort().await; - } - }, - Err(error) => { - log::warn!( - target: "bridge-guard", - "Failed to read {} account {:?} balance: {}. Relay may need to be stopped manually", - C::NAME, - account_id, - error, - ); - }, - }; - - env.sleep(conditions_check_delay::()).await; - } - }); -} - /// Delay between conditions check. fn conditions_check_delay() -> Duration { C::AVERAGE_BLOCK_INTERVAL * (10 + rand::random::() % 10) @@ -185,13 +104,6 @@ impl Environment for Client { async fn runtime_version(&mut self) -> Result { Client::::runtime_version(self).await } - - async fn free_native_balance( - &mut self, - account: C::AccountId, - ) -> Result { - Client::::free_native_balance(self, account).await - } } #[cfg(test)] @@ -207,7 +119,6 @@ mod tests { struct TestEnvironment { runtime_version_rx: UnboundedReceiver, - free_native_balance_rx: UnboundedReceiver, slept_tx: UnboundedSender<()>, aborted_tx: UnboundedSender<()>, } @@ -220,10 +131,6 @@ mod tests { Ok(self.runtime_version_rx.next().await.unwrap_or_default()) } - async fn free_native_balance(&mut self, _account: u32) -> Result { - Ok(self.free_native_balance_rx.next().await.unwrap_or_default()) - } - async fn sleep(&mut self, _duration: Duration) { let _ = self.slept_tx.send(()).await; } @@ -240,17 +147,11 @@ mod tests { async_std::task::block_on(async { let ( (mut runtime_version_tx, runtime_version_rx), - (_free_native_balance_tx, free_native_balance_rx), (slept_tx, mut slept_rx), (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); + ) = (unbounded(), unbounded(), unbounded()); abort_on_spec_version_change( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, + TestEnvironment { runtime_version_rx, slept_tx, aborted_tx }, 0, ); @@ -272,17 +173,11 @@ mod tests { async_std::task::block_on(async { let ( (mut runtime_version_tx, runtime_version_rx), - (_free_native_balance_tx, free_native_balance_rx), (slept_tx, mut slept_rx), (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); + ) = (unbounded(), unbounded(), unbounded()); abort_on_spec_version_change( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, + TestEnvironment { runtime_version_rx, slept_tx, aborted_tx }, 42, ); @@ -298,76 +193,4 @@ mod tests { assert!(aborted_rx.next().now_or_never().is_none()); }); } - - #[test] - fn aborts_when_balance_is_too_low() { - async_std::task::block_on(async { - let ( - (_runtime_version_tx, runtime_version_rx), - (mut free_native_balance_tx, free_native_balance_rx), - (slept_tx, mut slept_rx), - (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); - abort_when_account_balance_decreased( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, - 0, - 100, - ); - - // client responds with initial balance - free_native_balance_tx.send(1000).await.unwrap(); - - // then the guard sleeps - slept_rx.next().await; - - // and then client responds with updated balance, which is too low - free_native_balance_tx.send(899).await.unwrap(); - - // then the `abort` function is called - aborted_rx.next().await; - // and we do not reach next `sleep` function call - assert!(slept_rx.next().now_or_never().is_none()); - }); - } - - #[test] - fn does_not_aborts_when_balance_is_enough() { - async_std::task::block_on(async { - let ( - (_runtime_version_tx, runtime_version_rx), - (mut free_native_balance_tx, free_native_balance_rx), - (slept_tx, mut slept_rx), - (aborted_tx, mut aborted_rx), - ) = (unbounded(), unbounded(), unbounded(), unbounded()); - abort_when_account_balance_decreased( - TestEnvironment { - runtime_version_rx, - free_native_balance_rx, - slept_tx, - aborted_tx, - }, - 0, - 100, - ); - - // client responds with initial balance - free_native_balance_tx.send(1000).await.unwrap(); - - // then the guard sleeps - slept_rx.next().await; - - // and then client responds with updated balance, which is enough - free_native_balance_tx.send(950).await.unwrap(); - - // then the `sleep` function is called - slept_rx.next().await; - // and `abort` is not called - assert!(aborted_rx.next().now_or_never().is_none()); - }); - } } diff --git a/relays/lib-substrate-relay/src/finality/guards.rs b/relays/lib-substrate-relay/src/finality/guards.rs deleted file mode 100644 index 188a03733a382..0000000000000 --- a/relays/lib-substrate-relay/src/finality/guards.rs +++ /dev/null @@ -1,48 +0,0 @@ -// 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 . - -//! Tools for starting guards of finality relays. - -use crate::TransactionParams; - -use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, ChainWithBalances, ChainWithTransactions, -}; -use sp_core::Pair; - -/// Start finality relay guards. -pub async fn start( - target_client: &relay_substrate_client::Client, - transaction_params: &TransactionParams>, - enable_version_guard: bool, - maximal_balance_decrease_per_day: C::Balance, -) -> relay_substrate_client::Result<()> -where - AccountIdOf: From< as Pair>::Public>, -{ - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - relay_substrate_client::guard::abort_when_account_balance_decreased( - target_client.clone(), - transaction_params.signer.public().into(), - maximal_balance_decrease_per_day, - ); - Ok(()) -} diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index b0f0ee4e52cc7..37ee61b48f1bd 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -39,7 +39,6 @@ use sp_core::Pair; use std::{fmt::Debug, marker::PhantomData}; pub mod engine; -pub mod guards; pub mod initialize; pub mod source; pub mod target; From f18b07ead7dea74ba3e0538de8401450bbf1d71c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 9 May 2023 11:48:24 +0300 Subject: [PATCH 1062/1210] Remove some `expect()` statements (#2123) * Return error on save_message() Prevent unexpected failures. * Remove RefCell * Fix spellcheck * CI fixes --- modules/messages/src/benchmarking.rs | 9 +-- modules/messages/src/inbound_lane.rs | 42 +++++++------- modules/messages/src/lib.rs | 82 ++++++++++++--------------- modules/messages/src/outbound_lane.rs | 50 +++++++++------- 4 files changed, 92 insertions(+), 91 deletions(-) diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index aab8855a729a8..04f64b53b305f 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -17,8 +17,8 @@ //! Messages pallet benchmarking. use crate::{ - inbound_lane::InboundLaneStorage, inbound_lane_storage, outbound_lane, - weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, Call, OutboundLanes, + inbound_lane::InboundLaneStorage, outbound_lane, weights_ext::EXPECTED_DEFAULT_MESSAGE_LENGTH, + Call, OutboundLanes, RuntimeInboundLaneStorage, }; use bp_messages::{ @@ -443,11 +443,12 @@ benchmarks_instance_pallet! { fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(vec![]); + outbound_lane.send_message(vec![]).expect("We craft valid messages"); } fn receive_messages, I: 'static>(nonce: MessageNonce) { - let mut inbound_lane_storage = inbound_lane_storage::(T::bench_lane_id()); + let mut inbound_lane_storage = + RuntimeInboundLaneStorage::::from_lane_id(T::bench_lane_id()); inbound_lane_storage.set_data(InboundLaneData { relayers: vec![UnrewardedRelayer { relayer: T::bridged_relayer_id(), diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 5ec4444dbdfbe..2912c89cd1bee 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -40,7 +40,7 @@ pub trait InboundLaneStorage { /// Return maximal number of unconfirmed messages in inbound lane. fn max_unconfirmed_messages(&self) -> MessageNonce; /// Get lane data from the storage. - fn data(&self) -> InboundLaneData; + fn get_or_init_data(&mut self) -> InboundLaneData; /// Update lane data in the storage. fn set_data(&mut self, data: InboundLaneData); } @@ -117,9 +117,9 @@ impl InboundLane { InboundLane { storage } } - /// Returns storage reference. - pub fn storage(&self) -> &S { - &self.storage + /// Returns `mut` storage reference. + pub fn storage_mut(&mut self) -> &mut S { + &mut self.storage } /// Receive state of the corresponding outbound lane. @@ -127,7 +127,7 @@ impl InboundLane { &mut self, outbound_lane_data: OutboundLaneData, ) -> Option { - let mut data = self.storage.data(); + let mut data = self.storage.get_or_init_data(); let last_delivered_nonce = data.last_delivered_nonce(); if outbound_lane_data.latest_received_nonce > last_delivered_nonce { @@ -170,7 +170,7 @@ impl InboundLane { nonce: MessageNonce, message_data: DispatchMessageData, ) -> ReceivalResult { - let mut data = self.storage.data(); + let mut data = self.storage.get_or_init_data(); let is_correct_message = nonce == data.last_delivered_nonce() + 1; if !is_correct_message { return ReceivalResult::InvalidNonce @@ -252,7 +252,7 @@ mod tests { None, ); - assert_eq!(lane.storage.data().last_confirmed_nonce, 0); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 0); }); } @@ -270,7 +270,7 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().last_confirmed_nonce, 3); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3); assert_eq!( lane.receive_state_update(OutboundLaneData { @@ -279,7 +279,7 @@ mod tests { }), None, ); - assert_eq!(lane.storage.data().last_confirmed_nonce, 3); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3); }); } @@ -290,9 +290,9 @@ mod tests { receive_regular_message(&mut lane, 1); receive_regular_message(&mut lane, 2); receive_regular_message(&mut lane, 3); - assert_eq!(lane.storage.data().last_confirmed_nonce, 0); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 0); assert_eq!( - lane.storage.data().relayers, + lane.storage.get_or_init_data().relayers, vec![unrewarded_relayer(1, 3, TEST_RELAYER_A)] ); @@ -303,9 +303,9 @@ mod tests { }), Some(2), ); - assert_eq!(lane.storage.data().last_confirmed_nonce, 2); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 2); assert_eq!( - lane.storage.data().relayers, + lane.storage.get_or_init_data().relayers, vec![unrewarded_relayer(3, 3, TEST_RELAYER_A)] ); @@ -316,8 +316,8 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().last_confirmed_nonce, 3); - assert_eq!(lane.storage.data().relayers, vec![]); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3); + assert_eq!(lane.storage.get_or_init_data().relayers, vec![]); }); } @@ -325,7 +325,7 @@ mod tests { fn receive_status_update_works_with_batches_from_relayers() { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); - let mut seed_storage_data = lane.storage.data(); + let mut seed_storage_data = lane.storage.get_or_init_data(); // Prepare data seed_storage_data.last_confirmed_nonce = 0; seed_storage_data.relayers.push_back(unrewarded_relayer(1, 1, TEST_RELAYER_A)); @@ -341,9 +341,9 @@ mod tests { }), Some(3), ); - assert_eq!(lane.storage.data().last_confirmed_nonce, 3); + assert_eq!(lane.storage.get_or_init_data().last_confirmed_nonce, 3); assert_eq!( - lane.storage.data().relayers, + lane.storage.get_or_init_data().relayers, vec![ unrewarded_relayer(4, 4, TEST_RELAYER_B), unrewarded_relayer(5, 5, TEST_RELAYER_C) @@ -364,7 +364,7 @@ mod tests { ), ReceivalResult::InvalidNonce ); - assert_eq!(lane.storage.data().last_delivered_nonce(), 0); + assert_eq!(lane.storage.get_or_init_data().last_delivered_nonce(), 0); }); } @@ -470,7 +470,7 @@ mod tests { ReceivalResult::Dispatched(dispatch_result(0)) ); assert_eq!( - lane.storage.data().relayers, + lane.storage.get_or_init_data().relayers, vec![ unrewarded_relayer(1, 1, TEST_RELAYER_A), unrewarded_relayer(2, 2, TEST_RELAYER_B), @@ -508,7 +508,7 @@ mod tests { run_test(|| { let mut lane = inbound_lane::(TEST_LANE_ID); receive_regular_message(&mut lane, 1); - assert_eq!(lane.storage.data().last_delivered_nonce(), 1); + assert_eq!(lane.storage.get_or_init_data().last_delivered_nonce(), 1); }); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 02255e15082f6..307de89d54eca 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -67,7 +67,7 @@ use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; use sp_runtime::traits::UniqueSaturatedFrom; -use sp_std::{cell::RefCell, marker::PhantomData, prelude::*}; +use sp_std::{marker::PhantomData, prelude::*}; mod inbound_lane; mod outbound_lane; @@ -319,7 +319,7 @@ pub mod pallet { // subtract extra storage proof bytes from the actual PoV size - there may be // less unrewarded relayers than the maximal configured value - let lane_extra_proof_size_bytes = lane.storage().extra_proof_size_bytes(); + let lane_extra_proof_size_bytes = lane.storage_mut().extra_proof_size_bytes(); actual_weight = actual_weight.set_proof_size( actual_weight.proof_size().saturating_sub(lane_extra_proof_size_bytes), ); @@ -332,7 +332,7 @@ pub mod pallet { "Received lane {:?} state update: latest_confirmed_nonce={}. Unrewarded relayers: {:?}", lane_id, updated_latest_confirmed_nonce, - UnrewardedRelayersState::from(&lane.storage().data()), + UnrewardedRelayersState::from(&lane.storage_mut().get_or_init_data()), ); } } @@ -531,12 +531,12 @@ pub mod pallet { NotOperatingNormally, /// The outbound lane is inactive. InactiveOutboundLane, - /// The message is too large to be sent over the bridge. - MessageIsTooLarge, /// Message has been treated as invalid by chain verifier. MessageRejectedByChainVerifier(VerificationError), /// Message has been treated as invalid by lane verifier. MessageRejectedByLaneVerifier(VerificationError), + /// Message has been treated as invalid by the pallet logic. + MessageRejectedByPallet(VerificationError), /// Submitter has failed to pay fee for delivering and dispatching messages. FailedToWithdrawMessageFee, /// The transaction brings too many messages. @@ -727,11 +727,9 @@ fn send_message, I: 'static>( // finally, save message in outbound storage and emit event let encoded_payload = payload.encode(); let encoded_payload_len = encoded_payload.len(); - ensure!( - encoded_payload_len <= T::MaximalOutboundPayloadSize::get() as usize, - Error::::MessageIsTooLarge - ); - let nonce = lane.send_message(encoded_payload); + let nonce = lane + .send_message(encoded_payload) + .map_err(Error::::MessageRejectedByPallet)?; log::trace!( target: LOG_TARGET, @@ -761,18 +759,7 @@ fn ensure_normal_operating_mode, I: 'static>() -> Result<(), Error< fn inbound_lane, I: 'static>( lane_id: LaneId, ) -> InboundLane> { - InboundLane::new(inbound_lane_storage::(lane_id)) -} - -/// Creates new runtime inbound lane storage. -fn inbound_lane_storage, I: 'static>( - lane_id: LaneId, -) -> RuntimeInboundLaneStorage { - RuntimeInboundLaneStorage { - lane_id, - cached_data: RefCell::new(None), - _phantom: Default::default(), - } + InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id)) } /// Creates new outbound lane object, backed by runtime storage. @@ -785,10 +772,17 @@ fn outbound_lane, I: 'static>( /// Runtime inbound lane storage. struct RuntimeInboundLaneStorage, I: 'static = ()> { lane_id: LaneId, - cached_data: RefCell>>, + cached_data: Option>, _phantom: PhantomData, } +impl, I: 'static> RuntimeInboundLaneStorage { + /// Creates new runtime inbound lane storage. + fn from_lane_id(lane_id: LaneId) -> RuntimeInboundLaneStorage { + RuntimeInboundLaneStorage { lane_id, cached_data: None, _phantom: Default::default() } + } +} + impl, I: 'static> RuntimeInboundLaneStorage { /// Returns number of bytes that may be subtracted from the PoV component of /// `receive_messages_proof` call, because the actual inbound lane state is smaller than the @@ -798,9 +792,9 @@ impl, I: 'static> RuntimeInboundLaneStorage { /// `MaxUnrewardedRelayerEntriesAtInboundLane` constant from the pallet configuration. The PoV /// of the call includes the maximal size of inbound lane state. If the actual size is smaller, /// we may subtract extra bytes from this component. - pub fn extra_proof_size_bytes(&self) -> u64 { + pub fn extra_proof_size_bytes(&mut self) -> u64 { let max_encoded_len = StoredInboundLaneData::::max_encoded_len(); - let relayers_count = self.data().relayers.len(); + let relayers_count = self.get_or_init_data().relayers.len(); let actual_encoded_len = InboundLaneData::::encoded_size_hint(relayers_count) .unwrap_or(usize::MAX); @@ -823,26 +817,20 @@ impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage< T::MaxUnconfirmedMessagesAtInboundLane::get() } - fn data(&self) -> InboundLaneData { - match self.cached_data.clone().into_inner() { - Some(data) => data, + fn get_or_init_data(&mut self) -> InboundLaneData { + match self.cached_data { + Some(ref data) => data.clone(), None => { let data: InboundLaneData = InboundLanes::::get(self.lane_id).into(); - *self.cached_data.try_borrow_mut().expect( - "we're in the single-threaded environment;\ - we have no recursive borrows; qed", - ) = Some(data.clone()); + self.cached_data = Some(data.clone()); data }, } } fn set_data(&mut self, data: InboundLaneData) { - *self.cached_data.try_borrow_mut().expect( - "we're in the single-threaded environment;\ - we have no recursive borrows; qed", - ) = Some(data.clone()); + self.cached_data = Some(data.clone()); InboundLanes::::insert(self.lane_id, StoredInboundLaneData::(data)) } } @@ -872,15 +860,17 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag .map(Into::into) } - fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload) { + fn save_message( + &mut self, + nonce: MessageNonce, + message_payload: MessagePayload, + ) -> Result<(), VerificationError> { OutboundMessages::::insert( MessageKey { lane_id: self.lane_id, nonce }, - StoredMessagePayload::::try_from(message_payload).expect( - "save_message is called after all checks in send_message; \ - send_message checks message size; \ - qed", - ), + StoredMessagePayload::::try_from(message_payload) + .map_err(|_| VerificationError::MessageTooLarge)?, ); + Ok(()) } fn remove_message(&mut self, nonce: &MessageNonce) { @@ -1128,7 +1118,9 @@ mod tests { TEST_LANE_ID, message_payload.clone(), ), - Error::::MessageIsTooLarge, + Error::::MessageRejectedByPallet( + VerificationError::MessageTooLarge + ), ); // let's check that we're able to send `MAX_OUTBOUND_PAYLOAD_SIZE` messages @@ -2097,10 +2089,10 @@ mod tests { fn storage(relayer_entries: usize) -> RuntimeInboundLaneStorage { RuntimeInboundLaneStorage { lane_id: Default::default(), - cached_data: RefCell::new(Some(InboundLaneData { + cached_data: Some(InboundLaneData { relayers: vec![relayer_entry(); relayer_entries].into_iter().collect(), last_confirmed_nonce: 0, - })), + }), _phantom: Default::default(), } } diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index bc4fdfab9195d..0cf0c4ccb425c 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -20,6 +20,7 @@ use crate::{Config, LOG_TARGET}; use bp_messages::{ DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, + VerificationError, }; use codec::{Decode, Encode}; use frame_support::{ @@ -42,7 +43,11 @@ pub trait OutboundLaneStorage { #[cfg(test)] fn message(&self, nonce: &MessageNonce) -> Option; /// Save outbound message in the storage. - fn save_message(&mut self, nonce: MessageNonce, message_payload: MessagePayload); + fn save_message( + &mut self, + nonce: MessageNonce, + message_payload: MessagePayload, + ) -> Result<(), VerificationError>; /// Remove outbound message from the storage. fn remove_message(&mut self, nonce: &MessageNonce); } @@ -85,15 +90,18 @@ impl OutboundLane { /// Send message over lane. /// /// Returns new message nonce. - pub fn send_message(&mut self, message_payload: MessagePayload) -> MessageNonce { + pub fn send_message( + &mut self, + message_payload: MessagePayload, + ) -> Result { let mut data = self.storage.data(); let nonce = data.latest_generated_nonce + 1; data.latest_generated_nonce = nonce; - self.storage.save_message(nonce, message_payload); + self.storage.save_message(nonce, message_payload)?; self.storage.set_data(data); - nonce + Ok(nonce) } /// Confirm messages delivery. @@ -209,7 +217,7 @@ mod tests { }, outbound_lane, }; - use frame_support::weights::constants::RocksDbWeight; + use frame_support::{assert_ok, weights::constants::RocksDbWeight}; use sp_std::ops::RangeInclusive; fn unrewarded_relayers( @@ -230,9 +238,9 @@ mod tests { ) -> Result, ReceivalConfirmationError> { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); let result = lane.confirm_delivery(3, latest_received_nonce, relayers); @@ -247,7 +255,7 @@ mod tests { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); assert_eq!(lane.storage.data().latest_generated_nonce, 0); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1)); assert!(lane.storage.message(&1).is_some()); assert_eq!(lane.storage.data().latest_generated_nonce, 1); }); @@ -257,9 +265,9 @@ mod tests { fn confirm_delivery_works() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 2); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 3); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1)); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(2)); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(3)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( @@ -275,9 +283,9 @@ mod tests { fn confirm_delivery_rejects_nonce_lesser_than_latest_received() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( @@ -359,9 +367,9 @@ mod tests { ); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // when nothing is confirmed, nothing is pruned - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); assert!(lane.storage.message(&1).is_some()); assert!(lane.storage.message(&2).is_some()); assert!(lane.storage.message(&3).is_some()); @@ -403,9 +411,9 @@ mod tests { fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); - lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); assert_eq!( lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), From d17acab285b6828658f4425040eecf1ac17bd26c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 9 May 2023 18:16:06 +0300 Subject: [PATCH 1063/1210] Cosmetics (#2124) * Cosmetics * Address PR comment --- modules/messages/src/lib.rs | 31 +++------ primitives/messages/src/lib.rs | 69 +++++++++---------- primitives/runtime/src/lib.rs | 14 +++- .../src/messages_target.rs | 23 ++----- 4 files changed, 61 insertions(+), 76 deletions(-) diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 307de89d54eca..f04e86f3a8e32 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -59,9 +59,9 @@ use bp_messages::{ DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, - total_unrewarded_messages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, - MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, - OutboundMessageDetails, UnrewardedRelayersState, VerificationError, + DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, MessageKey, MessageNonce, + MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, + UnrewardedRelayersState, VerificationError, }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size}; use codec::{Decode, Encode, MaxEncodedLen}; @@ -437,21 +437,8 @@ pub mod pallet { Error::::InvalidMessagesDeliveryProof })?; - - // verify that the relayer has declared correct `lane_data::relayers` state - // (we only care about total number of entries and messages, because this affects call - // weight) - ensure!( - total_unrewarded_messages(&lane_data.relayers).unwrap_or(MessageNonce::MAX) == - relayers_state.total_messages && - lane_data.relayers.len() as MessageNonce == - relayers_state.unrewarded_relayer_entries, - Error::::InvalidUnrewardedRelayersState - ); - // the `last_delivered_nonce` field may also be used by the signed extension. Even - // though providing wrong value isn't critical, let's also check it here. ensure!( - lane_data.last_delivered_nonce() == relayers_state.last_delivered_nonce, + relayers_state.is_valid(&lane_data), Error::::InvalidUnrewardedRelayersState ); @@ -975,9 +962,9 @@ mod tests { ))), UnrewardedRelayersState { unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, total_messages: 1, last_delivered_nonce: 1, - ..Default::default() }, )); @@ -1341,9 +1328,9 @@ mod tests { single_message_delivery_proof, UnrewardedRelayersState { unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, total_messages: 1, last_delivered_nonce: 1, - ..Default::default() }, ); assert_ok!(result); @@ -1381,9 +1368,9 @@ mod tests { two_messages_delivery_proof, UnrewardedRelayersState { unrewarded_relayer_entries: 2, + messages_in_oldest_entry: 1, total_messages: 2, last_delivered_nonce: 2, - ..Default::default() }, ); assert_ok!(result); @@ -1746,9 +1733,9 @@ mod tests { TestMessagesDeliveryProof(messages_1_and_2_proof), UnrewardedRelayersState { unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 2, total_messages: 2, last_delivered_nonce: 2, - ..Default::default() }, )); // second tx with message 3 @@ -1757,9 +1744,9 @@ mod tests { TestMessagesDeliveryProof(messages_3_proof), UnrewardedRelayersState { unrewarded_relayer_entries: 1, + messages_in_oldest_entry: 1, total_messages: 1, last_delivered_nonce: 3, - ..Default::default() }, )); }); diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 10aee6ce97b7b..8f6c946610960 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -191,6 +191,17 @@ impl InboundLaneData { .map(|entry| entry.messages.end) .unwrap_or(self.last_confirmed_nonce) } + + /// Returns the total number of messages in the `relayers` vector, + /// saturating in case of underflow or overflow. + pub fn total_unrewarded_messages(&self) -> MessageNonce { + let relayers = &self.relayers; + match (relayers.front(), relayers.back()) { + (Some(front), Some(back)) => + (front.messages.begin..=back.messages.end).saturating_len(), + _ => 0, + } + } } /// Outbound message details, returned by runtime APIs. @@ -287,7 +298,7 @@ impl DeliveredMessages { /// Return total count of delivered messages. pub fn total_messages(&self) -> MessageNonce { - (self.begin..=self.end).checked_len().unwrap_or(0) + (self.begin..=self.end).saturating_len() } /// Note new dispatched message. @@ -318,6 +329,13 @@ pub struct UnrewardedRelayersState { pub last_delivered_nonce: MessageNonce, } +impl UnrewardedRelayersState { + // Verify that the relayers state corresponds with the `InboundLaneData`. + pub fn is_valid(&self, lane_data: &InboundLaneData) -> bool { + self == &lane_data.into() + } +} + impl From<&InboundLaneData> for UnrewardedRelayersState { fn from(lane: &InboundLaneData) -> UnrewardedRelayersState { UnrewardedRelayersState { @@ -325,9 +343,9 @@ impl From<&InboundLaneData> for UnrewardedRelayersState { messages_in_oldest_entry: lane .relayers .front() - .and_then(|entry| (entry.messages.begin..=entry.messages.end).checked_len()) + .map(|entry| entry.messages.total_messages()) .unwrap_or(0), - total_messages: total_unrewarded_messages(&lane.relayers).unwrap_or(MessageNonce::MAX), + total_messages: lane.total_unrewarded_messages(), last_delivered_nonce: lane.last_delivered_nonce(), } } @@ -357,24 +375,6 @@ impl Default for OutboundLaneData { } } -/// Returns total number of messages in the `InboundLaneData::relayers` vector. -/// -/// Returns `None` if there are more messages that `MessageNonce` may fit (i.e. `MessageNonce + 1`). -pub fn total_unrewarded_messages( - relayers: &VecDeque>, -) -> Option { - match (relayers.front(), relayers.back()) { - (Some(front), Some(back)) => { - if let Some(difference) = back.messages.end.checked_sub(front.messages.begin) { - difference.checked_add(1) - } else { - Some(0) - } - }, - _ => Some(0), - } -} - /// Calculate the number of messages that the relayers have delivered. pub fn calc_relayers_rewards( messages_relayers: VecDeque>, @@ -447,20 +447,19 @@ mod tests { #[test] fn total_unrewarded_messages_does_not_overflow() { - assert_eq!( - total_unrewarded_messages( - &vec![ - UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) }, - UnrewardedRelayer { - relayer: 2, - messages: DeliveredMessages::new(MessageNonce::MAX) - }, - ] - .into_iter() - .collect() - ), - None, - ); + let lane_data = InboundLaneData { + relayers: vec![ + UnrewardedRelayer { relayer: 1, messages: DeliveredMessages::new(0) }, + UnrewardedRelayer { + relayer: 2, + messages: DeliveredMessages::new(MessageNonce::MAX), + }, + ] + .into_iter() + .collect(), + last_confirmed_nonce: 0, + }; + assert_eq!(lane_data.total_unrewarded_messages(), MessageNonce::MAX); } #[test] diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index df77745bc02dd..742ffe32ea753 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -35,7 +35,7 @@ pub use chain::{ UnderlyingChainProvider, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; -use num_traits::{CheckedAdd, CheckedSub, One}; +use num_traits::{CheckedAdd, CheckedSub, One, SaturatingAdd, Zero}; pub use storage_proof::{ record_all_keys as record_all_trie_keys, Error as StorageProofError, ProofSize as StorageProofSize, RawStorageProof, StorageProofChecker, @@ -527,17 +527,27 @@ impl Debug for StrippableError { pub trait RangeInclusiveExt { /// Computes the length of the `RangeInclusive`, checking for underflow and overflow. fn checked_len(&self) -> Option; + /// Computes the length of the `RangeInclusive`, saturating in case of underflow or overflow. + fn saturating_len(&self) -> Idx; } impl RangeInclusiveExt for RangeInclusive where - Idx: CheckedSub + CheckedAdd + One, + Idx: CheckedSub + CheckedAdd + SaturatingAdd + One + Zero, { fn checked_len(&self) -> Option { self.end() .checked_sub(self.start()) .and_then(|len| len.checked_add(&Idx::one())) } + + fn saturating_len(&self) -> Idx { + let len = match self.end().checked_sub(self.start()) { + Some(len) => len, + None => return Idx::zero(), + }; + len.saturating_add(&Idx::one()) + } } #[cfg(test)] diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index 68b68b1993647..f47b48010ecdd 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -31,8 +31,8 @@ use crate::{ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ - storage_keys::inbound_lane_data_key, total_unrewarded_messages, InboundLaneData, LaneId, - MessageNonce, UnrewardedRelayersState, + storage_keys::inbound_lane_data_key, InboundLaneData, LaneId, MessageNonce, + UnrewardedRelayersState, }; use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use messages_relay::{ @@ -45,7 +45,7 @@ use relay_substrate_client::{ }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; -use std::{collections::VecDeque, convert::TryFrom, ops::RangeInclusive}; +use std::{convert::TryFrom, ops::RangeInclusive}; /// Message receiving proof returned by the target Substrate node. pub type SubstrateMessagesDeliveryProof = @@ -197,20 +197,9 @@ where id: TargetHeaderIdOf>, ) -> Result<(TargetHeaderIdOf>, UnrewardedRelayersState), SubstrateError> { - let inbound_lane_data = self.inbound_lane_data(id).await?; - let last_delivered_nonce = - inbound_lane_data.as_ref().map(|data| data.last_delivered_nonce()).unwrap_or(0); - let relayers = inbound_lane_data.map(|data| data.relayers).unwrap_or_else(VecDeque::new); - let unrewarded_relayers_state = bp_messages::UnrewardedRelayersState { - unrewarded_relayer_entries: relayers.len() as _, - messages_in_oldest_entry: relayers - .front() - .map(|entry| 1 + entry.messages.end - entry.messages.begin) - .unwrap_or(0), - total_messages: total_unrewarded_messages(&relayers).unwrap_or(MessageNonce::MAX), - last_delivered_nonce, - }; - Ok((id, unrewarded_relayers_state)) + let inbound_lane_data = + self.inbound_lane_data(id).await?.unwrap_or(InboundLaneData::default()); + Ok((id, (&inbound_lane_data).into())) } async fn prove_messages_receiving( From b1c1c9ba29ef058f18dc8b16c3800393654be868 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 10 May 2023 17:26:52 +0300 Subject: [PATCH 1064/1210] Small fixes (#2126) --- bin/runtime-common/src/messages.rs | 2 +- bin/runtime-common/src/messages_call_ext.rs | 2 +- modules/messages/src/inbound_lane.rs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 97a460716c904..e6c7deb98a2ca 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -216,7 +216,7 @@ pub mod source { // the message itself. The proof is always larger than the message. But unless chain state // is enormously large, it should be several dozens/hundreds of bytes. The delivery // transaction also contains signatures and signed extensions. Because of this, we reserve - // 1/3 of the the maximal extrinsic weight for this data. + // 1/3 of the the maximal extrinsic size for this data. if payload.len() > maximal_message_size::() as usize { return Err(VerificationError::MessageTooLarge) } diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 3f48ce583f9ce..8b4a50a0f30f4 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -47,7 +47,7 @@ pub struct BaseMessagesProofInfo { impl BaseMessagesProofInfo { /// Returns true if `bundled_range` continues the `0..=best_stored_nonce` range. fn appends_to_stored_nonce(&self) -> bool { - *self.bundled_range.start() == self.best_stored_nonce + 1 + Some(*self.bundled_range.start()) == self.best_stored_nonce.checked_add(1) } } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 2912c89cd1bee..b665b5516fc4d 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -171,8 +171,7 @@ impl InboundLane { message_data: DispatchMessageData, ) -> ReceivalResult { let mut data = self.storage.get_or_init_data(); - let is_correct_message = nonce == data.last_delivered_nonce() + 1; - if !is_correct_message { + if Some(nonce) != data.last_delivered_nonce().checked_add(1) { return ReceivalResult::InvalidNonce } From b57a62da2a65cb946dd9b2127ca79ec2a66e4763 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 11 May 2023 10:16:43 +0200 Subject: [PATCH 1065/1210] BHK/P alignments (#2115) * Constants * Unused import? * Cargo.lock * Unused deps * TODO: fix doc or reimport? * Try to aviod redefine para_id constant for `RefundableParachainId` * Checked and removed TODOs --- bin/millau/runtime/src/lib.rs | 3 +-- bin/rialto-parachain/runtime/src/lib.rs | 2 +- bin/runtime-common/Cargo.toml | 6 +----- .../src/refund_relayer_extension.rs | 19 +++++++++++++++---- modules/parachains/src/lib.rs | 8 ++++---- primitives/chain-bridge-hub-kusama/src/lib.rs | 2 -- .../chain-bridge-hub-polkadot/src/lib.rs | 3 --- primitives/chain-kusama/src/lib.rs | 7 +++++++ primitives/chain-polkadot/src/lib.rs | 7 +++++++ primitives/polkadot-core/src/parachains.rs | 4 ++-- primitives/runtime/src/chain.rs | 8 ++++++++ primitives/runtime/src/lib.rs | 6 +++--- relays/bin-substrate/src/chains/kusama.rs | 3 +-- relays/bin-substrate/src/chains/polkadot.rs | 3 +-- .../src/runtime_wrapper.rs | 9 +++------ .../src/runtime_wrapper.rs | 11 ++++------- relays/client-kusama/src/lib.rs | 1 - relays/client-polkadot/src/lib.rs | 1 - 18 files changed, 58 insertions(+), 45 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 60732339cf106..ad424f5cae6e7 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -501,7 +501,6 @@ impl pallet_bridge_messages::Config for Run parameter_types! { pub const RialtoParachainMessagesLane: bp_messages::LaneId = rialto_parachain_messages::XCM_LANE; - pub const RialtoParachainId: u32 = bp_rialto_parachain::RIALTO_PARACHAIN_ID; pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME; pub const MaxRialtoParaHeadDataSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; @@ -602,7 +601,7 @@ bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); pub type PriorityBoostPerMessage = ConstU64<324_316_715>; pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< Runtime, - RefundableParachain, + RefundableParachain, RefundableMessagesLane, ActualFeeRefund, PriorityBoostPerMessage, diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index de8ca493520e8..32b25b0e0bd4d 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -390,7 +390,7 @@ pub type XcmOriginToTransactDispatchOrigin = ( // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognised. RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 039e323b9b71e..08d102cc753ab 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -40,10 +40,8 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot dependencies -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } @@ -68,7 +66,6 @@ std = [ "pallet-bridge-relayers/std", "pallet-transaction-payment/std", "pallet-utility/std", - "pallet-xcm/std", "scale-info/std", "sp-api/std", "sp-core/std", @@ -78,13 +75,12 @@ std = [ "sp-trie/std", "xcm/std", "xcm-builder/std", - "xcm-executor/std", ] runtime-benchmarks = [ "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] integrity-test = [ diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 00ea70aa04eac..c54198373167f 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -24,7 +24,7 @@ use crate::messages_call_ext::{ }; use bp_messages::{LaneId, MessageNonce}; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; -use bp_runtime::{RangeInclusiveExt, StaticStrProvider}; +use bp_runtime::{Parachain, ParachainIdOf, RangeInclusiveExt, StaticStrProvider}; use codec::{Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, @@ -71,9 +71,9 @@ pub trait RefundableParachainId { } /// Default implementation of `RefundableParachainId`. -pub struct RefundableParachain(PhantomData<(Instance, Id)>); +pub struct DefaultRefundableParachainId(PhantomData<(Instance, Id)>); -impl RefundableParachainId for RefundableParachain +impl RefundableParachainId for DefaultRefundableParachainId where Id: Get, { @@ -81,6 +81,17 @@ where type Id = Id; } +/// Implementation of `RefundableParachainId` for `trait Parachain`. +pub struct RefundableParachain(PhantomData<(Instance, Para)>); + +impl RefundableParachainId for RefundableParachain +where + Para: Parachain, +{ + type Instance = Instance; + type Id = ParachainIdOf; +} + /// Trait identifying a bridged messages lane. A relayer might be refunded for delivering messages /// coming from this lane. pub trait RefundableMessagesLaneId { @@ -682,7 +693,7 @@ mod tests { bp_runtime::generate_static_str_provider!(TestExtension); type TestExtension = RefundBridgedParachainMessages< TestRuntime, - RefundableParachain<(), TestParachain>, + DefaultRefundableParachainId<(), TestParachain>, RefundableMessagesLane<(), TestLaneId>, ActualFeeRefund, ConstU64<1>, diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 7670a3bacfe8d..5a393af7cc4e5 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -394,10 +394,10 @@ pub mod pallet { Some(parachain_head_data) => parachain_head_data, None => { log::trace!( - target: LOG_TARGET, - "The head of parachain {:?} has been provided, but it is not tracked by the pallet", - parachain, - ); + target: LOG_TARGET, + "The head of parachain {:?} has been provided, but it is not tracked by the pallet", + parachain, + ); Self::deposit_event(Event::UntrackedParachainRejected { parachain }); continue }, diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs index 6ca2cd047fb7e..00b6c8301e4c2 100644 --- a/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -72,12 +72,10 @@ pub type Address = MultiAddress; pub const BRIDGE_HUB_KUSAMA_PARACHAIN_ID: u32 = 1002; /// Name of the With-BridgeHubKusama messages pallet instance that is deployed at bridged chains. -// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) pub const WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessages"; /// Name of the With-BridgeHubKusama bridge-relayers pallet instance that is deployed at bridged /// chains. -// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) pub const WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; decl_bridge_finality_runtime_apis!(bridge_hub_kusama); diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs index 646fb0a6e4186..8bd9167b618b1 100644 --- a/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -59,16 +59,13 @@ impl Parachain for BridgeHubPolkadot { } /// Identifier of BridgeHubPolkadot in the Polkadot relay chain. -// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) pub const BRIDGE_HUB_POLKADOT_PARACHAIN_ID: u32 = 1002; /// Name of the With-BridgeHubPolkadot messages pallet instance that is deployed at bridged chains. -// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) pub const WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotMessages"; /// Name of the With-BridgeHubPolkadot bridge-relayers pallet instance that is deployed at bridged /// chains. -// TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) pub const WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; decl_bridge_finality_runtime_apis!(bridge_hub_polkadot); diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 8e5aec8afda33..5cef6ae0ee64b 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -62,4 +62,11 @@ pub const PARAS_PALLET_NAME: &str = "Paras"; /// Name of the With-Kusama GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; +/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Polkadot +/// parachains. +/// +/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some +/// reserve. +pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; + decl_bridge_finality_runtime_apis!(kusama); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 92995601698d0..51d9f6f0233e3 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -62,4 +62,11 @@ pub const PARAS_PALLET_NAME: &str = "Paras"; /// Name of the With-Polkadot GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; +/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Polkadot +/// parachains. +/// +/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some +/// reserve. +pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; + decl_bridge_finality_runtime_apis!(polkadot); diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 0b410dff49f75..9cac3279c7285 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -18,8 +18,8 @@ //! //! Even though this (bridges) repository references polkadot repository, we can't //! reference polkadot crates from pallets. That's because bridges repository is -//! included in the polkadot repository and included pallets are used by polkadot -//! chains. Having pallets that are referencing polkadot, would mean that there may +//! included in the Cumulus repository and included pallets are used by Cumulus +//! parachains. Having pallets that are referencing polkadot, would mean that there may //! be two versions of polkadot crates included in the runtime. Which is bad. use bp_runtime::{RawStorageProof, Size}; diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 94b3a193c5829..c79058cea90cf 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -232,6 +232,14 @@ where const PARACHAIN_ID: u32 = <::Chain as Parachain>::PARACHAIN_ID; } +/// Adapter for `Get` to access `PARACHAIN_ID` from `trait Parachain` +pub struct ParachainIdOf(sp_std::marker::PhantomData); +impl frame_support::traits::Get for ParachainIdOf { + fn get() -> u32 { + Para::PARACHAIN_ID + } +} + /// Underlying chain type. pub type UnderlyingChainOf = ::Chain; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 742ffe32ea753..1922a2eb16040 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -31,8 +31,8 @@ use sp_std::{convert::TryFrom, fmt::Debug, ops::RangeInclusive, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, - HasherOf, HeaderOf, IndexOf, Parachain, SignatureOf, TransactionEraOf, UnderlyingChainOf, - UnderlyingChainProvider, + HasherOf, HeaderOf, IndexOf, Parachain, ParachainIdOf, SignatureOf, TransactionEraOf, + UnderlyingChainOf, UnderlyingChainProvider, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; use num_traits::{CheckedAdd, CheckedSub, One, SaturatingAdd, Zero}; @@ -95,7 +95,7 @@ pub const BRIDGE_HUB_WOCOCO_CHAIN_ID: ChainId = *b"bhwo"; pub const BRIDGE_HUB_KUSAMA_CHAIN_ID: ChainId = *b"bhks"; /// BridgeHubPolkadot chain id. -pub const BRIDGE_HUB_POLKADOT_CHAIN_ID: ChainId = *b"bhwo"; +pub const BRIDGE_HUB_POLKADOT_CHAIN_ID: ChainId = *b"bhpd"; /// Generic header Id. #[derive( diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 6d5a4764f91ec..0a30a0c07a095 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -26,7 +26,6 @@ impl CliChain for Kusama { } impl CliChain for BridgeHubKusama { - // TODO: fix me (https://github.com/paritytech/parity-bridges-common/issues/1945) const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 4242, transaction_version: 42 }); + Some(SimpleRuntimeVersion { spec_version: 9410, transaction_version: 21 }); } diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index 4fe5a48398bcd..b2585dbb3050d 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -26,7 +26,6 @@ impl CliChain for Polkadot { } impl CliChain for BridgeHubPolkadot { - // TODO: fix me (https://github.com/paritytech/parity-bridges-common/issues/1945) const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 4242, transaction_version: 42 }); + Some(SimpleRuntimeVersion { spec_version: 9410, transaction_version: 22 }); } diff --git a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs index 18bdafc0f04de..96a5b4fe033c7 100644 --- a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs @@ -54,16 +54,13 @@ pub enum Call { Utility(UtilityCall), /// Polkadot bridge pallet. - // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) - #[codec(index = 41)] + #[codec(index = 51)] BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), /// Polkadot parachain bridge pallet. - // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) - #[codec(index = 42)] + #[codec(index = 52)] BridgePolkadotParachain(BridgeParachainCall), /// Polkadot messages bridge pallet. - // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) - #[codec(index = 46)] + #[codec(index = 53)] BridgePolkadotMessages(BridgePolkadotMessagesCall), } diff --git a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs index 5afac61dbb3fc..924d3bbef07d6 100644 --- a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs @@ -53,16 +53,13 @@ pub enum Call { Utility(UtilityCall), /// Kusama bridge pallet. - // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) - #[codec(index = 43)] + #[codec(index = 51)] BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), /// Kusama parachain bridge pallet. - // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) - #[codec(index = 44)] + #[codec(index = 52)] BridgeKusamaParachain(BridgeParachainCall), /// Kusama messages bridge pallet. - // TODO: the index is wrong (https://github.com/paritytech/parity-bridges-common/issues/1945) - #[codec(index = 45)] + #[codec(index = 53)] BridgeKusamaMessages(BridgeKusamaMessagesCall), } @@ -114,6 +111,6 @@ mod tests { // encode call as hex string let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); - assert_eq!(hex_encoded_call, "0x2b01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); + assert_eq!(hex_encoded_call, "0x3301ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); } } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 99a52b4baf434..3d53fe8f9f186 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -55,6 +55,5 @@ impl ChainWithBalances for Kusama { impl RelayChain for Kusama { const PARAS_PALLET_NAME: &'static str = bp_kusama::PARAS_PALLET_NAME; - // TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeKusamaParachain"; } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 7f8615e0cd0ef..96453ab9041a8 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -55,6 +55,5 @@ impl ChainWithBalances for Polkadot { impl RelayChain for Polkadot { const PARAS_PALLET_NAME: &'static str = bp_polkadot::PARAS_PALLET_NAME; - // TODO: check me (https://github.com/paritytech/parity-bridges-common/issues/1945) const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgePolkadotParachain"; } From 6ef036107f182073f705aeac030e9ee5cf58b043 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 11 May 2023 12:32:13 +0300 Subject: [PATCH 1066/1210] Fix clippy warnings (#2127) --- relays/messages/src/message_race_delivery.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/relays/messages/src/message_race_delivery.rs b/relays/messages/src/message_race_delivery.rs index 06e02a06017b1..137deb5b74f75 100644 --- a/relays/messages/src/message_race_delivery.rs +++ b/relays/messages/src/message_race_delivery.rs @@ -813,7 +813,7 @@ mod tests { // if there are already `max_unrewarded_relayer_entries_at_target` entries at target, // we need to wait until rewards will be paid { - let mut unrewarded_relayers = + let unrewarded_relayers = &mut strategy.target_nonces.as_mut().unwrap().nonces_data.unrewarded_relayers; unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; @@ -832,9 +832,9 @@ mod tests { let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; { - let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; + let nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 1; - let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; + let unrewarded_relayers = &mut nonces_data.unrewarded_relayers; unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 4; @@ -851,9 +851,9 @@ mod tests { let prev_confirmed_nonce_at_source = strategy.latest_confirmed_nonces_at_source.back().unwrap().1; { - let mut nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; + let nonces_data = &mut strategy.target_nonces.as_mut().unwrap().nonces_data; nonces_data.confirmed_nonce = prev_confirmed_nonce_at_source - 3; - let mut unrewarded_relayers = &mut nonces_data.unrewarded_relayers; + let unrewarded_relayers = &mut nonces_data.unrewarded_relayers; unrewarded_relayers.unrewarded_relayer_entries = strategy.max_unrewarded_relayer_entries_at_target; unrewarded_relayers.messages_in_oldest_entry = 3; From 701e61031e6575cdeace610469f658dff08fcc52 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 12 May 2023 16:42:59 +0200 Subject: [PATCH 1067/1210] Support for kusama-polkadot relaying (#2128) --- relays/bin-substrate/src/cli/init_bridge.rs | 38 ++++++++++++++ .../src/cli/relay_headers_and_messages/mod.rs | 51 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 7b38d81227199..f297a8db6b44a 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -19,6 +19,10 @@ use codec::Encode; use crate::{ bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, rialto_millau::{ millau_headers_to_rialto::MillauToRialtoCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -66,6 +70,8 @@ pub enum InitBridgeName { MillauToRialtoParachain, RococoToBridgeHubWococo, WococoToBridgeHubRococo, + KusamaToBridgeHubPolkadot, + PolkadotToBridgeHubKusama, } #[async_trait] @@ -198,6 +204,34 @@ impl BridgeInitializer for WococoToBridgeHubRococoCliBridge { } } +impl BridgeInitializer for KusamaToBridgeHubPolkadotCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaGrandpa( + relay_bridge_hub_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize { + init_data, + }, + ) + } +} + +impl BridgeInitializer for PolkadotToBridgeHubKusamaCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotGrandpa( + relay_bridge_hub_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize { + init_data, + }, + ) + } +} + impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { @@ -211,6 +245,10 @@ impl InitBridge { RococoToBridgeHubWococoCliBridge::init_bridge(self), InitBridgeName::WococoToBridgeHubRococo => WococoToBridgeHubRococoCliBridge::init_bridge(self), + InitBridgeName::KusamaToBridgeHubPolkadot => + KusamaToBridgeHubPolkadotCliBridge::init_bridge(self), + InitBridgeName::PolkadotToBridgeHubKusama => + PolkadotToBridgeHubKusamaCliBridge::init_bridge(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 5384c8ff9e9fd..a47283400aab0 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -40,6 +40,10 @@ use relay_to_relay::*; use crate::{ bridges::{ + kusama_polkadot::{ + kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, + polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, + }, rialto_millau::{ millau_headers_to_rialto::MillauToRialtoCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -202,6 +206,10 @@ declare_chain_cli_schema!(Rococo, rococo); declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); declare_chain_cli_schema!(Wococo, wococo); declare_chain_cli_schema!(BridgeHubWococo, bridge_hub_wococo); +declare_chain_cli_schema!(Kusama, kusama); +declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); +declare_chain_cli_schema!(Polkadot, polkadot); +declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); // Means to override signers of different layer transactions. declare_chain_cli_schema!(MillauHeadersToRialto, millau_headers_to_rialto); declare_chain_cli_schema!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); @@ -217,10 +225,21 @@ declare_chain_cli_schema!( WococoParachainsToBridgeHubRococo, wococo_parachains_to_bridge_hub_rococo ); +declare_chain_cli_schema!(KusamaHeadersToBridgeHubPolkadot, kusama_headers_to_bridge_hub_polkadot); +declare_chain_cli_schema!( + KusamaParachainsToBridgeHubPolkadot, + kusama_parachains_to_bridge_hub_polkadot +); +declare_chain_cli_schema!(PolkadotHeadersToBridgeHubKusama, polkadot_headers_to_bridge_hub_kusama); +declare_chain_cli_schema!( + PolkadotParachainsToBridgeHubKusama, + polkadot_parachains_to_bridge_hub_kusama +); // All supported bridges. declare_relay_to_relay_bridge_schema!(Millau, Rialto); declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWococo, Wococo); +declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); /// Base portion of the bidirectional complex relay. /// @@ -463,6 +482,32 @@ impl Full2WayBridge for BridgeHubRococoBridgeHubWococoFull2WayBridge { } } +/// BridgeHubKusama <> BridgeHubPolkadot complex relay. +pub struct BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { + type Base = ParachainToParachainBridge; + type Left = relay_bridge_hub_kusama_client::BridgeHubKusama; + type Right = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + type L2R = BridgeHubKusamaToBridgeHubPolkadotCliBridge; + type R2L = BridgeHubPolkadotToBridgeHubKusamaCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { @@ -472,6 +517,8 @@ pub enum RelayHeadersAndMessages { MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), /// BridgeHubRococo <> BridgeHubWococo relay. BridgeHubRococoBridgeHubWococo(BridgeHubRococoBridgeHubWococoHeadersAndMessages), + /// BridgeHubKusama <> BridgeHubPolkadot relay. + BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), } impl RelayHeadersAndMessages { @@ -488,6 +535,10 @@ impl RelayHeadersAndMessages { BridgeHubRococoBridgeHubWococoFull2WayBridge::new(params.into_bridge().await?)? .run() .await, + RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot(params) => + BridgeHubKusamaBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? + .run() + .await, } } } From 7226737951cf86fe234ceea500895a1618d22a48 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 16 May 2023 16:46:21 +0200 Subject: [PATCH 1068/1210] Bump polkadot/substrate (#2134) * Bump polkadot/substrate * Fix millau network service * Fix polkadot_node_core_pvf_worker * Fix sc-network * Fix parachain rpc stuff * Check `integrity-test` for `bridge-runtime-common` * Backport fix from cumulus https://github.com/paritytech/cumulus/pull/2585/files#diff-5a942d80670b5ef31bb18b5acacab93ff30512d7cd21c19d7da364f76f6bb5c3 because of https://gitlab.parity.io/parity/mirrors/cumulus/-/jobs/2842938 * TODO * Bump cumulus --- bin/millau/node/Cargo.toml | 1 + bin/millau/node/src/service.rs | 23 ++++++++++---------- bin/millau/runtime/src/lib.rs | 1 + bin/millau/runtime/src/xcm_config.rs | 2 ++ bin/rialto-parachain/node/src/cli.rs | 8 +++++-- bin/rialto-parachain/node/src/command.rs | 22 +++++-------------- bin/rialto-parachain/node/src/service.rs | 8 +++++-- bin/rialto-parachain/runtime/src/lib.rs | 3 +++ bin/rialto/node/Cargo.toml | 2 +- bin/rialto/node/src/command.rs | 4 ++-- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/xcm_config.rs | 2 ++ primitives/header-chain/src/justification.rs | 21 +++++++++++++++++- 13 files changed, 61 insertions(+), 37 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3b64f98fa53cc..6710c6a217f10 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -36,6 +36,7 @@ sc-executor = { git = "https://github.com/paritytech/substrate", branch = "maste sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 07cd29a0d6d58..3f0bc2536be0a 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -178,7 +178,7 @@ pub fn new_partial( } /// Builds a new service for a full client. -pub fn new_full(mut config: Configuration) -> Result { +pub fn new_full(config: Configuration) -> Result { use sc_network_common::sync::warp::WarpSyncParams; let sc_service::PartialComponents { @@ -194,6 +194,8 @@ pub fn new_full(mut config: Configuration) -> Result let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); + let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); + // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change // anything in terms of behaviour, but makes the logs more consistent with the other // Substrate nodes. @@ -201,10 +203,9 @@ pub fn new_full(mut config: Configuration) -> Result &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), &config.chain_spec, ); - config - .network - .extra_sets - .push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + net_config.add_notification_protocol(sc_consensus_grandpa::grandpa_peers_set_config( + grandpa_protocol_name.clone(), + )); let beefy_gossip_proto_name = sc_consensus_beefy::gossip_protocol_name(genesis_hash, config.chain_spec.fork_id()); @@ -217,13 +218,10 @@ pub fn new_full(mut config: Configuration) -> Result client.clone(), config.prometheus_registry().cloned(), ); - config - .network - .extra_sets - .push(sc_consensus_beefy::communication::beefy_peers_set_config( - beefy_gossip_proto_name.clone(), - )); - config.network.request_response_protocols.push(beefy_req_resp_cfg); + net_config.add_notification_protocol( + sc_consensus_beefy::communication::beefy_peers_set_config(beefy_gossip_proto_name.clone()), + ); + net_config.add_request_response_protocol(beefy_req_resp_cfg); let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( backend.clone(), @@ -234,6 +232,7 @@ pub fn new_full(mut config: Configuration) -> Result let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, + net_config, client: client.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index ad424f5cae6e7..887d516248b22 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -367,6 +367,7 @@ impl pallet_transaction_payment::Config for Runtime { impl pallet_sudo::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; + type WeightInfo = pallet_sudo::weights::SubstrateWeight; } parameter_types! { diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index cabb70f40cc9f..d6b763b116c29 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -188,6 +188,8 @@ impl pallet_xcm::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); } pub struct ToRialtoOrRialtoParachainSwitchExporter; diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index a003c91113c00..77d5bd1ff948a 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -136,7 +136,11 @@ impl RelayChainCli { ) -> Self { let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); - let base_path = para_config.base_path.as_ref().map(|x| x.path().join("rialto-bridge-node")); - Self { base_path, chain_id, base: polkadot_cli::RunCmd::parse_from(relay_chain_args) } + let base_path = para_config.base_path.path().join("rialto-bridge-node"); + Self { + base_path: Some(base_path), + chain_id, + base: polkadot_cli::RunCmd::parse_from(relay_chain_args), + } } } diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index 7393b0147329a..dce14df801b0f 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -320,14 +320,10 @@ impl DefaultConfigurationValues for RelayChainCli { 30334 } - fn rpc_ws_listen_port() -> u16 { + fn rpc_listen_port() -> u16 { 9945 } - fn rpc_http_listen_port() -> u16 { - 9934 - } - fn prometheus_listen_port() -> u16 { 9616 } @@ -357,16 +353,8 @@ impl CliConfiguration for RelayChainCli { .or_else(|| self.base_path.clone().map(Into::into))) } - fn rpc_http(&self, default_listen_port: u16) -> Result> { - self.base.base.rpc_http(default_listen_port) - } - - fn rpc_ipc(&self) -> Result> { - self.base.base.rpc_ipc() - } - - fn rpc_ws(&self, default_listen_port: u16) -> Result> { - self.base.base.rpc_ws(default_listen_port) + fn rpc_addr(&self, default_listen_port: u16) -> Result> { + self.base.base.rpc_addr(default_listen_port) } fn prometheus_config( @@ -408,8 +396,8 @@ impl CliConfiguration for RelayChainCli { self.base.base.rpc_methods() } - fn rpc_ws_max_connections(&self) -> Result> { - self.base.base.rpc_ws_max_connections() + fn rpc_max_connections(&self) -> Result { + self.base.base.rpc_max_connections() } fn rpc_cors(&self, is_dev: bool) -> Result>> { diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 24eb94e655d57..7e516ed56825e 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -45,7 +45,7 @@ use sc_executor::{ HeapAllocStrategy, NativeElseWasmExecutor, NativeExecutionDispatch, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, }; -use sc_network::NetworkBlock; +use sc_network::{config::FullNetworkConfiguration, NetworkBlock}; use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; @@ -278,10 +278,12 @@ where let prometheus_registry = parachain_config.prometheus_registry().cloned(); let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); + let net_config = FullNetworkConfiguration::new(¶chain_config.network); let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: ¶chain_config, + net_config, client: client.clone(), transaction_pool: transaction_pool.clone(), spawn_handle: task_manager.spawn_handle(), @@ -333,7 +335,7 @@ where &task_manager, relay_chain_interface.clone(), transaction_pool, - sync_service, + sync_service.clone(), params.keystore_container.keystore(), force_authoring, )?; @@ -353,6 +355,7 @@ where collator_key: collator_key.expect("Command line arguments do not allow this. qed"), relay_chain_slot_duration, recovery_handle: Box::new(overseer_handle), + sync_service, }; start_collator(params).await?; @@ -366,6 +369,7 @@ where relay_chain_slot_duration, import_queue: import_queue_service, recovery_handle: Box::new(overseer_handle), + sync_service, }; start_full_node(params)?; diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 32b25b0e0bd4d..d44ae22e17e7d 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -322,6 +322,7 @@ impl pallet_transaction_payment::Config for Runtime { impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_sudo::weights::SubstrateWeight; } parameter_types! { @@ -497,6 +498,8 @@ impl pallet_xcm::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = frame_system::EnsureRoot; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 7f28a15426322..1a53acf044fa7 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -33,7 +33,7 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies -polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-pvf-worker = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index a21b3a88d2c23..8a7178fbd3104 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -164,7 +164,7 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf::prepare_worker_entrypoint( + polkadot_node_core_pvf_worker::prepare_worker_entrypoint( &cmd.socket_path, Some(&cmd.node_impl_version), ); @@ -175,7 +175,7 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf::execute_worker_entrypoint( + polkadot_node_core_pvf_worker::execute_worker_entrypoint( &cmd.socket_path, Some(&cmd.node_impl_version), ); diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 0d2c667efa533..8f45a2a19190d 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -365,6 +365,7 @@ impl pallet_transaction_payment::Config for Runtime { impl pallet_sudo::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; + type WeightInfo = pallet_sudo::weights::SubstrateWeight; } impl pallet_session::Config for Runtime { diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index 52c5af635b374..cee246ad67ad1 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -184,6 +184,8 @@ impl pallet_xcm::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); } #[cfg(test)] diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 06ed782763dfc..8433107fce20d 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -38,7 +38,7 @@ use sp_std::{ /// /// This particular proof is used to prove that headers on a bridged chain /// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] pub struct GrandpaJustification { /// The round (voting period) this justification is valid for. pub round: u64, @@ -49,6 +49,25 @@ pub struct GrandpaJustification { pub votes_ancestries: Vec

, } +// TODO: remove and use `RuntimeDebug` (https://github.com/paritytech/parity-bridges-common/issues/2136) +impl sp_std::fmt::Debug for GrandpaJustification
{ + fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { + #[cfg(feature = "std")] + { + fmt.debug_struct("GrandpaJustification") + .field("round", &self.round) + .field("commit", &self.commit) + .field("votes_ancestries", &self.votes_ancestries) + .finish() + } + + #[cfg(not(feature = "std"))] + { + fmt.write_str("") + } + } +} + impl GrandpaJustification { /// Returns reasonable size of justification using constants from the provided chain. /// From 803170f346d01df094341f1b6c7c24ef421c8e21 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 17 May 2023 09:43:01 +0300 Subject: [PATCH 1069/1210] fix nodes startup (#2138) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aab6007d2cd24..2f8c5ca9abb29 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ To run a Rialto node for example, you can use the following command: ```bash docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ -it paritytech/rialto-bridge-node --dev --tmp \ - --rpc-cors=all --unsafe-rpc-external --unsafe-ws-external + --rpc-cors=all --unsafe-rpc-external ``` ## Community From 4a40f97a452ea1cfe839eaf681332e558d18f704 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 18 May 2023 17:16:07 +0300 Subject: [PATCH 1070/1210] Ws-port argument has been repalced with rpc-port (#2140) * ws-port argument has been repalced with rpc-port * fixed paras pallet weight and expose unsigned validation * add bootnodes to RialtoParachain collators * another bump + increase block proposal time * revert RUST_LOG=trace for test network nodes --- bin/rialto-parachain/node/src/service.rs | 4 +- bin/rialto/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/parachains.rs | 50 +++++++++++++++++++++++- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index 7e516ed56825e..f21a2f65e795b 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -502,8 +502,8 @@ pub async fn start_node( keystore, force_authoring, slot_duration, - // We got around 500ms for proposing - block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), + // We got around 1000ms for proposing + block_proposal_slot_portion: SlotProportion::new(1f32 / 12f32), telemetry, max_block_proposal_slot_portion: None, }, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8f45a2a19190d..8d57e99b2972b 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -495,7 +495,7 @@ construct_runtime!( Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent}, Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage}, - Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config}, + Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, Dmp: polkadot_runtime_parachains::dmp::{Pallet, Storage}, Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event}, diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 8ceb27140f004..f2542cf032952 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -21,7 +21,7 @@ use crate::{ RuntimeOrigin, ShiftSessionManager, Slots, UncheckedExtrinsic, }; -use frame_support::{parameter_types, traits::KeyOwnerProofSystem}; +use frame_support::{parameter_types, traits::KeyOwnerProofSystem, weights::Weight}; use frame_system::EnsureRoot; use polkadot_primitives::v4::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; @@ -106,11 +106,57 @@ parameter_types! { impl parachains_paras::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = parachains_paras::TestWeightInfo; + type WeightInfo = ParasWeightInfo; type UnsignedPriority = ParasUnsignedPriority; type NextSessionRotation = Babe; } +/// Test weight for the `Paras` pallet. +/// +/// We can't use `parachains_paras::TestWeightInfo` anymore, because it returns `Weight::MAX` +/// where we need some real-world weights. We'll use zero weights here, though to avoid +/// adding benchmarks to Rialto runtime. +pub struct ParasWeightInfo; + +impl parachains_paras::WeightInfo for ParasWeightInfo { + fn force_set_current_code(_c: u32) -> Weight { + Weight::zero() + } + fn force_set_current_head(_s: u32) -> Weight { + Weight::zero() + } + fn force_schedule_code_upgrade(_c: u32) -> Weight { + Weight::zero() + } + fn force_note_new_head(_s: u32) -> Weight { + Weight::zero() + } + fn force_queue_action() -> Weight { + Weight::zero() + } + fn add_trusted_validation_code(_c: u32) -> Weight { + Weight::zero() + } + fn poke_unused_validation_code() -> Weight { + Weight::zero() + } + fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { + Weight::zero() + } + fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { + Weight::zero() + } + fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { + Weight::zero() + } + fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { + Weight::zero() + } + fn include_pvf_check_statement() -> Weight { + Weight::zero() + } +} + impl parachains_paras_inherent::Config for Runtime { type WeightInfo = parachains_paras_inherent::TestWeightInfo; } From d25a5c42bc82eeafff79e586543834bfe8764df6 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 18 May 2023 18:08:15 +0300 Subject: [PATCH 1071/1210] expose test utilities to be used in BH paras (#2142) Signed-off-by: acatangiu --- bin/runtime-common/src/lib.rs | 2 +- bin/runtime-common/src/messages_generation.rs | 8 +- modules/parachains/src/lib.rs | 96 ++++++++----------- modules/parachains/src/mock.rs | 7 +- primitives/test-utils/Cargo.toml | 9 +- primitives/test-utils/src/lib.rs | 41 ++++++++ 6 files changed, 98 insertions(+), 65 deletions(-) diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 12b096492cd48..546d4388471c1 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -28,12 +28,12 @@ pub mod messages; pub mod messages_api; pub mod messages_benchmarking; pub mod messages_call_ext; +pub mod messages_generation; pub mod messages_xcm_extension; pub mod parachains_benchmarking; pub mod priority_calculator; pub mod refund_relayer_extension; -mod messages_generation; mod mock; #[cfg(feature = "integrity-test")] diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs index 29a869a5c871a..8dbf3abd683cf 100644 --- a/bin/runtime-common/src/messages_generation.rs +++ b/bin/runtime-common/src/messages_generation.rs @@ -16,8 +16,6 @@ //! Helpers for generating message storage proofs, that are used by tests and by benchmarks. -#![cfg(any(feature = "runtime-benchmarks", test))] - use crate::messages::{BridgedChain, HashOf, HasherOf, MessageBridge}; use bp_messages::{ @@ -29,19 +27,19 @@ use sp_std::{ops::RangeInclusive, prelude::*}; use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; /// Simple and correct message data encode function. -pub(crate) fn encode_all_messages(_: MessageNonce, m: &MessagePayload) -> Option> { +pub fn encode_all_messages(_: MessageNonce, m: &MessagePayload) -> Option> { Some(m.encode()) } /// Simple and correct outbound lane data encode function. -pub(crate) fn encode_lane_data(d: &OutboundLaneData) -> Vec { +pub fn encode_lane_data(d: &OutboundLaneData) -> Vec { d.encode() } /// Prepare storage proof of given messages. /// /// Returns state trie root and nodes with prepared messages. -pub(crate) fn prepare_messages_storage_proof( +pub fn prepare_messages_storage_proof( lane: LaneId, message_nonces: RangeInclusive, outbound_lane_data: Option, diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 5a393af7cc4e5..c2052e3d4ebee 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -701,16 +701,17 @@ pub(crate) mod tests { use crate::mock::{ run_test, test_relay_header, BigParachainHeader, RegularParachainHasher, RegularParachainHeader, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, - PARAS_PALLET_NAME, UNTRACKED_PARACHAIN_ID, + UNTRACKED_PARACHAIN_ID, }; + use bp_test_utils::prepare_parachain_heads_proof; use codec::Encode; use bp_parachains::{ BestParaHeadHash, BridgeParachainCall, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider, }; use bp_runtime::{ - record_all_trie_keys, BasicOperatingMode, OwnedBridgeModuleError, - StorageDoubleMapKeyProvider, StorageMapKeyProvider, + BasicOperatingMode, OwnedBridgeModuleError, StorageDoubleMapKeyProvider, + StorageMapKeyProvider, }; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, @@ -725,7 +726,6 @@ pub(crate) mod tests { use frame_system::{EventRecord, Pallet as System, Phase}; use sp_core::Hasher; use sp_runtime::{traits::Header as HeaderT, DispatchError}; - use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; type BridgesGrandpaPalletInstance = pallet_bridge_grandpa::Instance1; type WeightInfo = ::WeightInfo; @@ -768,32 +768,6 @@ pub(crate) mod tests { hash } - pub(crate) fn prepare_parachain_heads_proof( - heads: Vec<(u32, ParaHead)>, - ) -> (RelayBlockHash, ParaHeadsProof, Vec<(ParaId, ParaHash)>) { - let mut parachains = Vec::with_capacity(heads.len()); - let mut root = Default::default(); - let mut mdb = MemoryDB::default(); - { - let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); - for (parachain, head) in heads { - let storage_key = - parachain_head_storage_key_at_source(PARAS_PALLET_NAME, ParaId(parachain)); - trie.insert(&storage_key.0, &head.encode()) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in tests"); - parachains.push((ParaId(parachain), head.hash())); - } - } - - // generate storage proof to be delivered to This chain - let storage_proof = record_all_trie_keys::, _>(&mdb, &root) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - - (root, ParaHeadsProof(storage_proof), parachains) - } - fn initial_best_head(parachain: u32) -> ParaInfo { ParaInfo { best_head_hash: BestParaHeadHash { @@ -875,7 +849,7 @@ pub(crate) mod tests { #[test] fn submit_parachain_heads_checks_operating_mode() { let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 0))]); run_test(|| { initialize(state_root); @@ -906,7 +880,10 @@ pub(crate) mod tests { #[test] fn imports_initial_parachain_heads() { let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 0)), (3, head_data(3, 10))]); + prepare_parachain_heads_proof::(vec![ + (1, head_data(1, 0)), + (3, head_data(3, 10)), + ]); run_test(|| { initialize(state_root); @@ -985,9 +962,9 @@ pub(crate) mod tests { #[test] fn imports_parachain_heads_is_able_to_progress() { let (state_root_5, proof_5, parachains_5) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 5))]); let (state_root_10, proof_10, parachains_10) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 and import head#5 of parachain#1 initialize(state_root_5); @@ -1083,11 +1060,12 @@ pub(crate) mod tests { #[test] fn ignores_untracked_parachain() { - let (state_root, proof, parachains) = prepare_parachain_heads_proof(vec![ - (1, head_data(1, 5)), - (UNTRACKED_PARACHAIN_ID, head_data(1, 5)), - (2, head_data(1, 5)), - ]); + let (state_root, proof, parachains) = + prepare_parachain_heads_proof::(vec![ + (1, head_data(1, 5)), + (UNTRACKED_PARACHAIN_ID, head_data(1, 5)), + (2, head_data(1, 5)), + ]); run_test(|| { // start with relay block #0 and try to import head#5 of parachain#1 and untracked // parachain @@ -1160,7 +1138,7 @@ pub(crate) mod tests { #[test] fn does_nothing_when_already_imported_this_head_at_previous_relay_header() { let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 0))]); run_test(|| { // import head#0 of parachain#1 at relay block#0 initialize(state_root); @@ -1220,9 +1198,9 @@ pub(crate) mod tests { #[test] fn does_nothing_when_already_imported_head_at_better_relay_header() { let (state_root_5, proof_5, parachains_5) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 5))]); let (state_root_10, proof_10, parachains_10) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 10))]); run_test(|| { // start with relay block #0 initialize(state_root_5); @@ -1314,7 +1292,10 @@ pub(crate) mod tests { #[test] fn does_nothing_when_parachain_head_is_too_large() { let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5)), (4, big_head_data(1, 5))]); + prepare_parachain_heads_proof::(vec![ + (1, head_data(1, 5)), + (4, big_head_data(1, 5)), + ]); run_test(|| { // start with relay block #0 and try to import head#5 of parachain#1 and big parachain initialize(state_root); @@ -1368,8 +1349,9 @@ pub(crate) mod tests { // import exactly `HeadsToKeep` headers for i in 0..heads_to_keep { - let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, i))]); + let (state_root, proof, parachains) = prepare_parachain_heads_proof::< + RegularParachainHeader, + >(vec![(1, head_data(1, i))]); if i == 0 { initialize(state_root); } else { @@ -1389,8 +1371,9 @@ pub(crate) mod tests { } // import next relay chain header and next parachain head - let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, heads_to_keep))]); + let (state_root, proof, parachains) = prepare_parachain_heads_proof::< + RegularParachainHeader, + >(vec![(1, head_data(1, heads_to_keep))]); proceed(heads_to_keep, state_root); let expected_weight = weight_of_import_parachain_1_head(&proof, true); let result = import_parachain_1_head(heads_to_keep, state_root, parachains, proof); @@ -1411,7 +1394,7 @@ pub(crate) mod tests { #[test] fn fails_on_unknown_relay_chain_block() { let (state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(state_root); @@ -1427,7 +1410,7 @@ pub(crate) mod tests { #[test] fn fails_on_invalid_storage_proof() { let (_state_root, proof, parachains) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 5))]); run_test(|| { // start with relay block #0 initialize(Default::default()); @@ -1445,11 +1428,11 @@ pub(crate) mod tests { #[test] fn is_not_rewriting_existing_head_if_failed_to_read_updated_head() { let (state_root_5, proof_5, parachains_5) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 5))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 5))]); let (state_root_10_at_20, proof_10_at_20, parachains_10_at_20) = - prepare_parachain_heads_proof(vec![(2, head_data(2, 10))]); + prepare_parachain_heads_proof::(vec![(2, head_data(2, 10))]); let (state_root_10_at_30, proof_10_at_30, parachains_10_at_30) = - prepare_parachain_heads_proof(vec![(1, head_data(1, 10))]); + prepare_parachain_heads_proof::(vec![(1, head_data(1, 10))]); run_test(|| { // we've already imported head#5 of parachain#1 at relay block#10 initialize(state_root_5); @@ -1517,7 +1500,8 @@ pub(crate) mod tests { #[test] fn ignores_parachain_head_if_it_is_missing_from_storage_proof() { - let (state_root, proof, _) = prepare_parachain_heads_proof(vec![]); + let (state_root, proof, _) = + prepare_parachain_heads_proof::(vec![]); let parachains = vec![(ParaId(2), Default::default())]; run_test(|| { initialize(state_root); @@ -1542,7 +1526,8 @@ pub(crate) mod tests { #[test] fn ignores_parachain_head_if_parachain_head_hash_is_wrong() { - let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let (state_root, proof, _) = + prepare_parachain_heads_proof::(vec![(1, head_data(1, 0))]); let parachains = vec![(ParaId(1), head_data(1, 10).hash())]; run_test(|| { initialize(state_root); @@ -1569,7 +1554,8 @@ pub(crate) mod tests { #[test] fn test_bridge_parachain_call_is_correctly_defined() { - let (state_root, proof, _) = prepare_parachain_heads_proof(vec![(1, head_data(1, 0))]); + let (state_root, proof, _) = + prepare_parachain_heads_proof::(vec![(1, head_data(1, 0))]); let parachains = vec![(ParaId(2), Default::default())]; let relay_header_id = (0, test_relay_header(0, state_root).hash()); diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 3086adc1cc2ea..0a61d91d7b2db 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -250,9 +250,10 @@ impl pallet_bridge_parachains::benchmarking::Config<()> for TestRuntime { ) { // in mock run we only care about benchmarks correctness, not the benchmark results // => ignore size related arguments - let (state_root, proof, parachains) = crate::tests::prepare_parachain_heads_proof( - parachains.iter().map(|p| (p.0, crate::tests::head_data(p.0, 1))).collect(), - ); + let (state_root, proof, parachains) = + bp_test_utils::prepare_parachain_heads_proof::( + parachains.iter().map(|p| (p.0, crate::tests::head_data(p.0, 1))).collect(), + ); let relay_genesis_hash = crate::tests::initialize(state_root); (0, relay_genesis_hash, proof, parachains) } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 5ed835857d1c2..2e2af99332eab 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -7,23 +7,30 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } +bp-parachains = { path = "../parachains", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-grandpa = { 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-runtime = { 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 } [features] default = ["std"] std = [ "bp-header-chain/std", + "bp-polkadot-core/std", "codec/std", "ed25519-dalek/std", "finality-grandpa/std", "sp-application-crypto/std", "sp-consensus-grandpa/std", + "sp-core/std", "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 6bb4adbf45092..5a7d0cca279a0 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -19,10 +19,14 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_header_chain::justification::{required_justification_precommits, GrandpaJustification}; +use bp_parachains::parachain_head_storage_key_at_source; +use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; +use bp_runtime::record_all_trie_keys; use codec::Encode; use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, AuthorityWeight, SetId}; use sp_runtime::traits::{Header as HeaderT, One, Zero}; use sp_std::prelude::*; +use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; // Re-export all our test account utilities pub use keyring::*; @@ -31,6 +35,7 @@ mod keyring; pub const TEST_GRANDPA_ROUND: u64 = 1; pub const TEST_GRANDPA_SET_ID: SetId = 1; +pub const PARAS_PALLET_NAME: &str = "Paras"; /// Configuration parameters when generating test GRANDPA justifications. #[derive(Clone)] @@ -161,6 +166,33 @@ fn generate_chain(fork_id: u32, depth: u32, ancestor: &H) -> Vec headers } +/// Make valid proof for parachain `heads` +pub fn prepare_parachain_heads_proof( + heads: Vec<(u32, ParaHead)>, +) -> (H::Hash, ParaHeadsProof, Vec<(ParaId, ParaHash)>) { + let mut parachains = Vec::with_capacity(heads.len()); + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = TrieDBMutBuilderV1::::new(&mut mdb, &mut root).build(); + for (parachain, head) in heads { + let storage_key = + parachain_head_storage_key_at_source(PARAS_PALLET_NAME, ParaId(parachain)); + trie.insert(&storage_key.0, &head.encode()) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in tests"); + parachains.push((ParaId(parachain), head.hash())); + } + } + + // generate storage proof to be delivered to This chain + let storage_proof = record_all_trie_keys::, _>(&mdb, &root) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); + + (root, ParaHeadsProof(storage_proof), parachains) +} + /// Create signed precommit with given target. pub fn signed_precommit( signer: &Account, @@ -207,6 +239,15 @@ pub fn test_header(number: H::Number) -> H { header } +/// Get a header for testing with given `state_root`. +/// +/// The correct parent hash will be used if given a non-zero header. +pub fn test_header_with_root(number: H::Number, state_root: H::Hash) -> H { + let mut header: H = test_header(number); + header.set_state_root(state_root); + header +} + /// Convenience function for generating a Header ID at a given block number. pub fn header_id(index: u8) -> (H::Hash, H::Number) { (test_header::(index.into()).hash(), index.into()) From 063d7fa2258ef3ee2f34272a6f44423a0ea2caab Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 23 May 2023 15:29:48 +0200 Subject: [PATCH 1072/1210] Updated BHR/W version + codegen (#2148) --- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/chains/wococo.rs | 2 +- .../src/codegen_runtime.rs | 163 ++++++++++++------ 3 files changed, 109 insertions(+), 58 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index c0041c53ddbf4..dc8bd64836a62 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,5 +27,5 @@ impl CliChain for Rococo { impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9381, transaction_version: 2 }); + Some(SimpleRuntimeVersion { spec_version: 9420, transaction_version: 3 }); } diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs index 73b3884c289d9..c9e3943d80865 100644 --- a/relays/bin-substrate/src/chains/wococo.rs +++ b/relays/bin-substrate/src/chains/wococo.rs @@ -27,5 +27,5 @@ impl CliChain for Wococo { impl CliChain for BridgeHubWococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9381, transaction_version: 2 }); + Some(SimpleRuntimeVersion { spec_version: 9420, transaction_version: 3 }); } diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs index 6488d923d7594..2ad17d8eb7c9f 100644 --- a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs @@ -103,13 +103,35 @@ pub mod api { ::core::primitive::u64, runtime_types::bp_messages::ReceivalResult<_0>, )>, - pub skipped_for_not_enough_weight: ::std::vec::Vec<::core::primitive::u64>, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct UnrewardedRelayer<_0> { pub relayer: _0, pub messages: runtime_types::bp_messages::DeliveredMessages, } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VerificationError { + #[codec(index = 0)] + EmptyMessageProof, + #[codec(index = 1)] + HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 2)] + InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 3)] + InvalidMessageWeight, + #[codec(index = 4)] + MessagesCountMismatch, + #[codec(index = 5)] + MessageStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 6)] + MessageTooLarge, + #[codec(index = 7)] + OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 8)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 9)] + Other, + } } pub mod bp_parachains { use super::runtime_types; @@ -128,6 +150,14 @@ pub mod api { } pub mod bp_relayers { use super::runtime_types; + pub mod registration { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0, _1> { + pub valid_till: _0, + pub stake: _1, + } + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RewardsAccountOwner { #[codec(index = 0)] @@ -427,17 +457,11 @@ pub mod api { pub mod relay_state_snapshot { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { - pub dmq_mqc_head: ::subxt::utils::H256, - pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), - pub ingress_channels: ::std::vec::Vec<( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, - )>, - pub egress_channels: ::std::vec::Vec<( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, - )>, + pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_size : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispachQueueSize , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain :: primitives :: Id , runtime_types :: polkadot_primitives :: v4 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain :: primitives :: Id , runtime_types :: polkadot_primitives :: v4 :: AbridgedHrmpChannel ,) > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RelayDispachQueueSize { + pub remaining_count: ::core::primitive::u32, + pub remaining_size: ::core::primitive::u32, } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -1011,6 +1035,17 @@ pub mod api { Issued { amount: ::core::primitive::u128 }, #[codec(index = 16)] Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, } } pub mod types { @@ -1102,18 +1137,16 @@ pub mod api { #[codec(index = 1)] InvalidAuthoritySet, #[codec(index = 2)] - TooManyRequests, - #[codec(index = 3)] OldHeader, - #[codec(index = 4)] + #[codec(index = 3)] UnsupportedScheduledChange, - #[codec(index = 5)] + #[codec(index = 4)] NotInitialized, - #[codec(index = 6)] + #[codec(index = 5)] AlreadyInitialized, - #[codec(index = 7)] + #[codec(index = 6)] TooManyAuthoritiesInSet, - #[codec(index = 8)] + #[codec(index = 7)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -1139,44 +1172,28 @@ pub mod api { } pub mod pallet_bridge_messages { use super::runtime_types; - pub mod pallet { + pub mod outbound_lane { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { + pub enum ReceivalConfirmationError { #[codec(index = 0)] - NotOperatingNormally, + FailedToConfirmFutureMessages, #[codec(index = 1)] - InactiveOutboundLane, + EmptyUnrewardedRelayerEntry, #[codec(index = 2)] - MessageIsTooLarge, + NonConsecutiveUnrewardedRelayerEntries, #[codec(index = 3)] - MessageRejectedByChainVerifier, - #[codec(index = 4)] - MessageRejectedByLaneVerifier, - #[codec(index = 5)] - FailedToWithdrawMessageFee, - #[codec(index = 6)] - TooManyMessagesInTheProof, - #[codec(index = 7)] - InvalidMessagesProof, - #[codec(index = 8)] - InvalidMessagesDeliveryProof, - #[codec(index = 9)] - InvalidUnrewardedRelayers, - #[codec(index = 10)] - InvalidUnrewardedRelayersState, - #[codec(index = 11)] - MessageIsAlreadyDelivered, - #[codec(index = 12)] - MessageIsNotYetSent, - #[codec(index = 13)] TryingToConfirmMoreMessagesThanExpected, - #[codec(index = 14)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 3)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } @@ -1211,14 +1228,8 @@ pub mod api { #[codec(index = 1)] InvalidRelayChainBlockNumber, #[codec(index = 2)] - HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), #[codec(index = 3)] - UnknownParaHead, - #[codec(index = 4)] - StorageRootMismatch, - #[codec(index = 5)] - FailedToExtractStateRoot, - #[codec(index = 6)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -1262,6 +1273,10 @@ pub mod api { claim_rewards { rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, }, + #[codec(index = 1)] + register { valid_till: ::core::primitive::u32 }, + #[codec(index = 2)] + deregister, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { @@ -1269,6 +1284,18 @@ pub mod api { NoRewardForRelayer, #[codec(index = 1)] FailedToPayReward, + #[codec(index = 2)] + InvalidRegistrationLease, + #[codec(index = 3)] + CannotReduceRegistrationLease, + #[codec(index = 4)] + FailedToReserve, + #[codec(index = 5)] + FailedToUnreserve, + #[codec(index = 6)] + NotRegistered, + #[codec(index = 7)] + RegistrationIsStillActive, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { @@ -1278,6 +1305,24 @@ pub mod api { rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, reward: ::core::primitive::u128, }, + #[codec(index = 1)] + RegistrationUpdated { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + Deregistered { relayer: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + SlashedAndDeregistered { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, } } } @@ -1679,6 +1724,8 @@ pub mod api { fee_asset_item: ::core::primitive::u32, weight_limit: runtime_types::xcm::v3::WeightLimit, }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { @@ -2090,6 +2137,8 @@ pub mod api { Corruption, #[codec(index = 12)] Unavailable, + #[codec(index = 13)] + RootNotAllowed, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ModuleError { @@ -2125,6 +2174,8 @@ pub mod api { CannotCreateHold, #[codec(index = 8)] NotExpendable, + #[codec(index = 9)] + Blocked, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum TransactionalError { From 0898ac9bf7900b63b703fffec70706e161112e67 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 1 Jun 2023 15:07:35 +0300 Subject: [PATCH 1073/1210] backport cumulus changes to polkadot-staging (#2167) * backport cumulus changes * bump substrate & polkadot and make it build * fix runtimes * bump substrate, polkadot & cumulus * fix build: remove ump leftovers * fix tests: disable runtime version check in tests * fix build: use sp_version::runtime_version macro Signed-off-by: acatangiu --- bin/millau/runtime/build.rs | 1 + bin/millau/runtime/src/lib.rs | 7 +-- bin/rialto-parachain/runtime/build.rs | 1 + bin/rialto-parachain/runtime/src/lib.rs | 2 +- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/node/src/chain_spec.rs | 5 -- bin/rialto/node/src/command.rs | 4 +- bin/rialto/runtime/Cargo.toml | 3 + bin/rialto/runtime/build.rs | 1 + bin/rialto/runtime/src/lib.rs | 8 +-- bin/rialto/runtime/src/parachains.rs | 74 +++++++++++++++++++++---- bin/runtime-common/Cargo.toml | 4 +- bin/runtime-common/src/mock.rs | 2 +- modules/beefy/src/lib.rs | 8 +-- modules/grandpa/Cargo.toml | 4 +- modules/grandpa/src/lib.rs | 10 +--- modules/messages/Cargo.toml | 4 +- modules/messages/src/lib.rs | 14 +---- modules/messages/src/mock.rs | 2 +- modules/parachains/Cargo.toml | 4 +- modules/parachains/src/lib.rs | 14 +---- modules/relayers/Cargo.toml | 4 +- modules/relayers/src/mock.rs | 2 +- 23 files changed, 99 insertions(+), 81 deletions(-) diff --git a/bin/millau/runtime/build.rs b/bin/millau/runtime/build.rs index cc865704327dd..25e220e46fc3b 100644 --- a/bin/millau/runtime/build.rs +++ b/bin/millau/runtime/build.rs @@ -21,5 +21,6 @@ fn main() { .with_current_project() .import_memory() .export_heap_base() + .disable_runtime_version_section_check() .build() } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 887d516248b22..92dabc9407ce7 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -146,6 +146,7 @@ impl_opaque_keys! { } /// This runtime version. +#[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("millau-runtime"), impl_name: create_runtime_str!("millau-runtime"), @@ -254,17 +255,15 @@ impl pallet_grandpa::Config for Runtime { mod mmr { use super::Runtime; pub use pallet_mmr::primitives::*; - use sp_runtime::traits::Keccak256; pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; - pub type Hash = ::Output; pub type Hashing = ::Hashing; + pub type Hash = ::Output; } impl pallet_mmr::Config for Runtime { const INDEXING_PREFIX: &'static [u8] = b"mmr"; type Hashing = Keccak256; - type Hash = mmr::Hash; type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; type WeightInfo = (); type LeafData = pallet_beefy_mmr::Pallet; @@ -332,7 +331,7 @@ impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; diff --git a/bin/rialto-parachain/runtime/build.rs b/bin/rialto-parachain/runtime/build.rs index 65095bd1b7e9e..692e270bbbae3 100644 --- a/bin/rialto-parachain/runtime/build.rs +++ b/bin/rialto-parachain/runtime/build.rs @@ -21,5 +21,6 @@ fn main() { .with_current_project() .export_heap_base() .import_memory() + .disable_runtime_version_section_check() .build() } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index d44ae22e17e7d..498cdf8a58fde 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -304,7 +304,7 @@ impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 1a53acf044fa7..7f28a15426322 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -33,7 +33,7 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot Dependencies -polkadot-node-core-pvf-worker = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index ceb82d45b3857..c5364019a0e4c 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use frame_support::weights::Weight; use polkadot_primitives::v4::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, @@ -253,10 +252,6 @@ fn testnet_genesis( max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, max_downward_message_size: 1024 * 1024, - ump_service_total_weight: Weight::from_parts( - 100_000_000_000, - polkadot_primitives::v4::MAX_POV_SIZE as u64, - ), max_upward_message_size: 50 * 1024, max_upward_message_num_per_candidate: 5, hrmp_sender_deposit: 0, diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 8a7178fbd3104..a21b3a88d2c23 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -164,7 +164,7 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf_worker::prepare_worker_entrypoint( + polkadot_node_core_pvf::prepare_worker_entrypoint( &cmd.socket_path, Some(&cmd.node_impl_version), ); @@ -175,7 +175,7 @@ pub fn run() -> sc_cli::Result<()> { builder.with_colors(false); let _ = builder.init(); - polkadot_node_core_pvf_worker::execute_worker_entrypoint( + polkadot_node_core_pvf::execute_worker_entrypoint( &cmd.socket_path, Some(&cmd.node_impl_version), ); diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index f687905ad6349..12254010b35dc 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -38,6 +38,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["historical"]} pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } @@ -101,6 +102,7 @@ std = [ "pallet-bridge-messages/std", "pallet-bridge-relayers/std", "pallet-grandpa/std", + "pallet-message-queue/std", "pallet-mmr/std", "pallet-xcm/std", "pallet-session/std", @@ -136,6 +138,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/rialto/runtime/build.rs b/bin/rialto/runtime/build.rs index cc865704327dd..25e220e46fc3b 100644 --- a/bin/rialto/runtime/build.rs +++ b/bin/rialto/runtime/build.rs @@ -21,5 +21,6 @@ fn main() { .with_current_project() .import_memory() .export_heap_base() + .disable_runtime_version_section_check() .build() } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8d57e99b2972b..9240314c54430 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -132,6 +132,7 @@ impl_opaque_keys! { } /// This runtime version. +#[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("rialto-runtime"), impl_name: create_runtime_str!("rialto-runtime"), @@ -262,7 +263,6 @@ impl pallet_grandpa::Config for Runtime { impl pallet_mmr::Config for Runtime { const INDEXING_PREFIX: &'static [u8] = b"mmr"; type Hashing = Keccak256; - type Hash = ::Output; type LeafData = pallet_beefy_mmr::Pallet; type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; type WeightInfo = (); @@ -330,7 +330,7 @@ impl pallet_balances::Config for Runtime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; @@ -498,12 +498,12 @@ construct_runtime!( Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, Dmp: polkadot_runtime_parachains::dmp::{Pallet, Storage}, - Ump: polkadot_runtime_parachains::ump::{Pallet, Call, Storage, Event}, Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, ParaSessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, ParasDisputes: polkadot_runtime_parachains::disputes::{Pallet, Call, Storage, Event}, ParasSlashing: polkadot_runtime_parachains::disputes::slashing::{Pallet, Call, Storage, ValidateUnsigned}, + MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event}, // Parachain Onboarding Pallets Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event}, @@ -558,8 +558,8 @@ mod mmr { pub use pallet_mmr::primitives::*; pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; - pub type Hash = ::Hash; pub type Hashing = ::Hashing; + pub type Hash = ::Output; } impl_runtime_apis! { diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index f2542cf032952..587cb4d93404c 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -17,24 +17,30 @@ //! Parachains support in Rialto runtime. use crate::{ - AccountId, Babe, Balance, Balances, BlockNumber, Registrar, Runtime, RuntimeCall, RuntimeEvent, - RuntimeOrigin, ShiftSessionManager, Slots, UncheckedExtrinsic, + xcm_config, AccountId, Babe, Balance, Balances, BlockNumber, Registrar, Runtime, RuntimeCall, + RuntimeEvent, RuntimeOrigin, ShiftSessionManager, Slots, UncheckedExtrinsic, }; -use frame_support::{parameter_types, traits::KeyOwnerProofSystem, weights::Weight}; +use frame_support::{ + parameter_types, + traits::{KeyOwnerProofSystem, ProcessMessage, ProcessMessageError}, + weights::{Weight, WeightMeter}, +}; use frame_system::EnsureRoot; use polkadot_primitives::v4::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ configuration as parachains_configuration, disputes as parachains_disputes, - disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, - inclusion as parachains_inclusion, initializer as parachains_initializer, - origin as parachains_origin, paras as parachains_paras, + disputes::slashing as parachains_slashing, + dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, + inclusion::{AggregateMessageOrigin, UmpQueueId}, + initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras, paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler, - session_info as parachains_session_info, shared as parachains_shared, ump as parachains_ump, + session_info as parachains_session_info, shared as parachains_shared, }; use sp_core::crypto::KeyTypeId; use sp_runtime::transaction_validity::TransactionPriority; +use xcm::latest::Junction; impl frame_system::offchain::SendTransactionTypes for Runtime where @@ -70,6 +76,8 @@ impl parachains_inclusion::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RewardValidators = RewardValidators; type DisputesHandler = (); + type MessageQueue = crate::MessageQueue; + type WeightInfo = (); } impl parachains_initializer::Config for Runtime { @@ -108,6 +116,7 @@ impl parachains_paras::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = ParasWeightInfo; type UnsignedPriority = ParasUnsignedPriority; + type QueueFootprinter = crate::Inclusion; type NextSessionRotation = Babe; } @@ -169,12 +178,53 @@ impl parachains_session_info::Config for Runtime { impl parachains_shared::Config for Runtime {} -impl parachains_ump::Config for Runtime { +parameter_types! { + /// Amount of weight that can be spent per block to service messages. + /// + /// # WARNING + /// + /// This is not a good value for para-chains since the `Scheduler` + /// already uses up to 80 percent block weight. + pub MessageQueueServiceWeight: Weight = crate::Perbill::from_percent(20) * bp_rialto::BlockWeights::get().max_block; + pub const MessageQueueHeapSize: u32 = 32 * 1024; + pub const MessageQueueMaxStale: u32 = 96; +} + +/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet. +pub struct MessageProcessor; +impl ProcessMessage for MessageProcessor { + type Origin = AggregateMessageOrigin; + + fn process_message( + message: &[u8], + origin: Self::Origin, + meter: &mut WeightMeter, + id: &mut [u8; 32], + ) -> Result { + let para = match origin { + AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para, + }; + xcm_builder::ProcessXcmMessage::< + Junction, + xcm_executor::XcmExecutor, + RuntimeCall, + >::process_message(message, Junction::Parachain(para.into()), meter, id) + } +} + +impl pallet_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type UmpSink = (); - type FirstMessageFactorPercent = frame_support::traits::ConstU64<100>; - type ExecuteOverweightOrigin = EnsureRoot; - type WeightInfo = parachains_ump::TestWeightInfo; + type Size = u32; + type HeapSize = MessageQueueHeapSize; + type MaxStale = MessageQueueMaxStale; + type ServiceWeight = MessageQueueServiceWeight; + #[cfg(not(feature = "runtime-benchmarks"))] + type MessageProcessor = MessageProcessor; + #[cfg(feature = "runtime-benchmarks")] + type MessageProcessor = + pallet_message_queue::mock_helpers::NoopMessageProcessor; + type QueueChangeHandler = crate::Inclusion; + type WeightInfo = (); } // required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 08d102cc753ab..8fe89de962ef1 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,8 +9,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } -log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +log = { version = "0.4.18", default-features = false } +scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index c176719967614..4542ad39b6241 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -190,7 +190,7 @@ impl pallet_balances::Config for TestRuntime { type MaxLocks = ConstU32<50>; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index 79795dd0770ab..f22d8e488a2b2 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -328,6 +328,7 @@ pub mod pallet { StorageValue<_, BasicOperatingMode, ValueQuery>; #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] pub struct GenesisConfig, I: 'static = ()> { /// Optional module owner account. pub owner: Option, @@ -335,13 +336,6 @@ pub mod pallet { pub init_data: Option>, } - #[cfg(feature = "std")] - impl, I: 'static> Default for GenesisConfig { - fn default() -> Self { - Self { owner: None, init_data: None } - } - } - #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 9b97b518fc5cd..3414349937076 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -10,8 +10,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +log = { version = "0.4.18", default-features = false } +scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 50286512db896..10b60878302e8 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -44,7 +44,7 @@ use bp_header_chain::{ }; use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; -use frame_support::{dispatch::PostDispatchInfo, ensure}; +use frame_support::{dispatch::PostDispatchInfo, ensure, DefaultNoBound}; use sp_consensus_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, @@ -370,6 +370,7 @@ pub mod pallet { StorageValue<_, BasicOperatingMode, ValueQuery>; #[pallet::genesis_config] + #[derive(DefaultNoBound)] pub struct GenesisConfig, I: 'static = ()> { /// Optional module owner account. pub owner: Option, @@ -377,13 +378,6 @@ pub mod pallet { pub init_data: Option>>, } - #[cfg(feature = "std")] - impl, I: 'static> Default for GenesisConfig { - fn default() -> Self { - Self { owner: None, init_data: None } - } - } - #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 639ac9dc23ce6..34120e6908a30 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -8,9 +8,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.17", default-features = false } +log = { version = "0.4.18", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index f04e86f3a8e32..51e6857d7778c 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -65,7 +65,7 @@ use bp_messages::{ }; use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size}; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get}; +use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get, DefaultNoBound}; use sp_runtime::traits::UniqueSaturatedFrom; use sp_std::{marker::PhantomData, prelude::*}; @@ -586,6 +586,7 @@ pub mod pallet { StorageMap<_, Blake2_128Concat, MessageKey, StoredMessagePayload>; #[pallet::genesis_config] + #[derive(DefaultNoBound)] pub struct GenesisConfig, I: 'static = ()> { /// Initial pallet operating mode. pub operating_mode: MessagesOperatingMode, @@ -595,17 +596,6 @@ pub mod pallet { pub phantom: sp_std::marker::PhantomData, } - #[cfg(feature = "std")] - impl, I: 'static> Default for GenesisConfig { - fn default() -> Self { - Self { - operating_mode: Default::default(), - owner: Default::default(), - phantom: Default::default(), - } - } - } - #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index f0516fbc23f96..8716c5bc3ac7f 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -133,7 +133,7 @@ impl pallet_balances::Config for TestRuntime { type WeightInfo = (); type MaxReserves = (); type ReserveIdentifier = (); - type HoldIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index d8c89b79991b8..5ee30f594c7b9 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -7,8 +7,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +log = { version = "0.4.18", default-features = false } +scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index c2052e3d4ebee..b17b52163d857 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -30,7 +30,7 @@ use bp_header_chain::{HeaderChain, HeaderChainError}; use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo, ParaStoredHeaderData}; use bp_polkadot_core::parachains::{ParaHash, ParaHead, ParaHeadsProof, ParaId}; use bp_runtime::{Chain, HashOf, HeaderId, HeaderIdOf, Parachain, StorageProofError}; -use frame_support::dispatch::PostDispatchInfo; +use frame_support::{dispatch::PostDispatchInfo, DefaultNoBound}; use sp_std::{marker::PhantomData, vec::Vec}; #[cfg(feature = "runtime-benchmarks")] @@ -611,6 +611,7 @@ pub mod pallet { } #[pallet::genesis_config] + #[derive(DefaultNoBound)] pub struct GenesisConfig, I: 'static = ()> { /// Initial pallet operating mode. pub operating_mode: BasicOperatingMode, @@ -620,17 +621,6 @@ pub mod pallet { pub phantom: sp_std::marker::PhantomData, } - #[cfg(feature = "std")] - impl, I: 'static> Default for GenesisConfig { - fn default() -> Self { - Self { - operating_mode: Default::default(), - owner: Default::default(), - phantom: Default::default(), - } - } - } - #[pallet::genesis_build] impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 857d47cc65a38..9fbc0996ba785 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -8,8 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.17", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +log = { version = "0.4.18", default-features = false } +scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 69d8418a02414..d8c5bd9096720 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -102,7 +102,7 @@ impl pallet_balances::Config for TestRuntime { type WeightInfo = (); type MaxReserves = ConstU32<1>; type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); type MaxHolds = ConstU32<0>; type MaxFreezes = ConstU32<0>; From dcefee5a114fd2b4c1c752f1b65dd0acd684beec Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 14 Jun 2023 16:41:36 +0300 Subject: [PATCH 1074/1210] minor doc fix (#2207) --- primitives/chain-bridge-hub-cumulus/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 4c9f9e20468c6..b174cd700ed45 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -124,9 +124,13 @@ pub type Address = MultiAddress; // `ensure_able_to_receive_confirmation` test. /// Maximal number of unrewarded relayer entries at inbound lane for Cumulus-based parachains. +/// Note: this value is security-relevant, decreasing it should not be done without careful +/// analysis (like the one above). pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane for Cumulus-based parachains. +/// Note: this value is security-relevant, decreasing it should not be done without careful +/// analysis (like the one above). pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// Extra signed extension data that is used by all bridge hubs. From ee7d3f8d2eb7291944b99e3630bb606d8d220d8f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 3 Jul 2023 18:02:35 +0300 Subject: [PATCH 1075/1210] Ensure that the origin is signed for submit_parachain_heads and submit_finality_proof calls (#2239) * ensure that the origin is signed for submit_parachain_heads and submit_finality_proof calls * clippy * clippy --- modules/grandpa/src/lib.rs | 22 +++++++++++++++++++++- modules/parachains/src/lib.rs | 26 ++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 10b60878302e8..f9c3ab68a06f2 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -176,11 +176,12 @@ pub mod pallet { justification.votes_ancestries.len().saturated_into(), ))] pub fn submit_finality_proof( - _origin: OriginFor, + origin: OriginFor, finality_target: Box>, justification: GrandpaJustification>, ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; + ensure_signed(origin)?; let (hash, number) = (finality_target.hash(), *finality_target.number()); log::trace!( @@ -1414,4 +1415,23 @@ mod tests { fn maybe_headers_to_keep_returns_correct_value() { assert_eq!(MaybeHeadersToKeep::::get(), Some(mock::HeadersToKeep::get())); } + + #[test] + fn submit_finality_proof_requires_signed_origin() { + run_test(|| { + initialize_substrate_bridge(); + + let header = test_header(1); + let justification = make_default_justification(&header); + + assert_noop!( + Pallet::::submit_finality_proof( + RuntimeOrigin::root(), + Box::new(header), + justification, + ), + DispatchError::BadOrigin, + ); + }) + } } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index b17b52163d857..52b436b820712 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -307,12 +307,13 @@ pub mod pallet { parachains.len() as _, ))] pub fn submit_parachain_heads( - _origin: OriginFor, + origin: OriginFor, at_relay_block: (RelayBlockNumber, RelayBlockHash), parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; + ensure_signed(origin)?; // we'll need relay chain header to verify that parachains heads are always increasing. let (relay_block_number, relay_block_hash) = at_relay_block; @@ -417,7 +418,7 @@ pub mod pallet { }); // we're refunding weight if update has not happened and if pruning has not happened - let is_update_happened = matches!(update_result, Ok(_)); + let is_update_happened = update_result.is_ok(); if !is_update_happened { actual_weight = actual_weight.saturating_sub( WeightInfoOf::::parachain_head_storage_write_weight( @@ -1579,4 +1580,25 @@ pub(crate) mod tests { Some(mock::TOTAL_PARACHAINS * mock::HeadsToKeep::get()), ); } + + #[test] + fn submit_finality_proof_requires_signed_origin() { + run_test(|| { + let (state_root, proof, parachains) = + prepare_parachain_heads_proof::(vec![(1, head_data(1, 0))]); + + initialize(state_root); + + // `submit_parachain_heads()` should fail when the pallet is halted. + assert_noop!( + Pallet::::submit_parachain_heads( + RuntimeOrigin::root(), + (0, test_relay_header(0, state_root).hash()), + parachains, + proof, + ), + DispatchError::BadOrigin + ); + }) + } } From 7f4daf27790da288be8656c5ee6b9e90b703c4f5 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 4 Jul 2023 15:53:44 +0200 Subject: [PATCH 1076/1210] Nits for subtree (#2241) * Updated version according to Cumulus * Renaming * Cargo.lock --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 4 ++-- docs/polkadot-kusama-bridge-overview.md | 10 +++++----- docs/polkadot-kusama-bridge.html | 6 +++--- modules/beefy/Cargo.toml | 4 ++-- modules/grandpa/Cargo.toml | 4 ++-- modules/messages/Cargo.toml | 4 ++-- modules/messages/README.md | 2 +- modules/parachains/Cargo.toml | 4 ++-- modules/relayers/Cargo.toml | 4 ++-- modules/shift-session-manager/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- relays/client-bridge-hub-kusama/Cargo.toml | 2 +- relays/client-bridge-hub-polkadot/Cargo.toml | 2 +- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- 27 files changed, 39 insertions(+), 39 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 4594c73fd9266..c92698edae29d 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.4" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index d44f4b42af448..41ca0bff9bf46 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -12,7 +12,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} hex-literal = "0.4" -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge depedencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 12254010b35dc..2320665cf9a32 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 8fe89de962ef1..98b3bc992501f 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,8 +9,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } -log = { version = "0.4.18", default-features = false } -scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +log = { version = "0.4.19", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/docs/polkadot-kusama-bridge-overview.md b/docs/polkadot-kusama-bridge-overview.md index 9f407b6ba00a3..e59e0058530a5 100644 --- a/docs/polkadot-kusama-bridge-overview.md +++ b/docs/polkadot-kusama-bridge-overview.md @@ -24,8 +24,8 @@ You won't be able to directly use bridge hub transactions to send XCM messages o to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will just queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. -Our first planned bridge will connect the Polkadot' Statemint and Kusama' Statemine. Bridge between those two -parachains would allow Statemint accounts to hold wrapped KSM tokens and Statemine accounts to hold wrapped DOT +Our first planned bridge will connect the Polkadot' AssetHub and Kusama' AssetHub. Bridge between those two +parachains would allow AssetHubPolkadot accounts to hold wrapped KSM tokens and AssetHubKusama accounts to hold wrapped DOT tokens. For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, @@ -93,13 +93,13 @@ Obviously, there should be someone who is paying relayer rewards. We want bridge can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides of the bridge to cover relayer rewards. -Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Statemine (Kusama Parachain) will -have an account at the Polkadot Bridge Hub. The Statemint (Polkadot Parachain) will have an account at the Kusama +Bridged Parachains will have sovereign accounts at bridge hubs. For example, the AssetHubKusama (Kusama Parachain) will +have an account at the Polkadot Bridge Hub. The AssetHubPolkadot (Polkadot Parachain) will have an account at the Kusama Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the `pallet_bridge_relayers::claim_rewards`. Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. -Statemine will only reward relayers that are delivering messages from Statemine. The Statemine sovereign account +AssetHubKusama will only reward relayers that are delivering messages from AssetHubKusama. The AssetHubKusama sovereign account is not used to cover rewards of bridging with some other Polkadot Parachain. ### Multiple Relayers and Rewards diff --git a/docs/polkadot-kusama-bridge.html b/docs/polkadot-kusama-bridge.html index dcbae0e7b1769..272412226f67c 100644 --- a/docs/polkadot-kusama-bridge.html +++ b/docs/polkadot-kusama-bridge.html @@ -16,7 +16,7 @@

Polkadot <> Kusama Bridge

In our architecture, the lane that is used to relay messages over the bridge is determined by - the XCM source and destinations. So e.g. bridge between Statemint and Statemine (and opposite direction) + the XCM source and destinations. So e.g. bridge between AssetHubPolkadot and AssetHubKusama (and opposite direction) will use the lane 00000000, bridge between some other Polkadot Parachain and some other Kusama Parachain will use the lane 00000001 and so on.

@@ -50,7 +50,7 @@

Polkadot <> Kusama Bridge

end polkadot_bh<===>|Message is relayed to the Bridged Chain using lane 00000000|kusama_bh - + linkStyle 2 stroke:red linkStyle 7 stroke:red linkStyle 8 stroke:red @@ -64,4 +64,4 @@

Polkadot <> Kusama Bridge

mermaid.initialize({ startOnLoad: true }); - \ No newline at end of file + diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 4270b96e208b2..421f11ddc8979 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -7,8 +7,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.14", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +log = { version = "0.4.19", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 3414349937076..c9a79eb8682d8 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -10,8 +10,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -log = { version = "0.4.18", default-features = false } -scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +log = { version = "0.4.19", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 34120e6908a30..da69f66d53868 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -8,9 +8,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.18", default-features = false } +log = { version = "0.4.19", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/messages/README.md b/modules/messages/README.md index b717db6ad6285..3b84656025fff 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -33,7 +33,7 @@ is the runtime developer who defines what message lane and message mean for this In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane as a channel of communication between two parachains of different relay chains. For example, lane -`[0, 0, 0, 0]` is used for Statemint <> Statemine communications. Other lanes may be used to bridge +`[0, 0, 0, 0]` is used for AssetHubPolkadot <> AssetHubKusama communications. Other lanes may be used to bridge another parachains. ## Message Workflow diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 5ee30f594c7b9..f7e2184a261d2 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -7,8 +7,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.18", default-features = false } -scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +log = { version = "0.4.19", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 9fbc0996ba785..ef41d70a242f2 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -8,8 +8,8 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.18", default-features = false } -scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +log = { version = "0.4.19", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 1a14f230c6bcb..83fd1a098d7f1 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 3316bc09d51b6..7ddaa6e1eb246 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.6.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 7c5c5e11345f3..d4b59c2aa9e83 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -13,7 +13,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", optional = true } parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index e0349ebc9b9d4..9718318f603d8 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index cb35b4ae65b2d..e5d5f70895bcc 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.6.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge dependencies diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 426597a25086a..90cff6be3911d 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 56c6de04d41c2..b7ba480347387 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index b84b0393adf1d..fd2c9e19f9841 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.6.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 694ff4e1aa648..456cfea9edb22 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Substrate Dependencies diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index f6e2c853a10de..a7bb7dcc4eea4 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index 2b3ec0b6bad73..dd0b083135d33 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index a901e029bf542..55a412693375a 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index e5c0684ba0ab0..eeeb8b33d623e 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 789e0622cfc83..5766954e7ad35 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } -scale-info = { version = "2.6.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } subxt = { version = "0.28.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 3dfeb9decbd1e..4dd7975280409 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,7 +14,7 @@ jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = "0.4.17" num-traits = "0.2" rand = "0.8" -scale-info = { version = "2.6.0", features = ["derive"] } +scale-info = { version = "2.9.0", features = ["derive"] } tokio = { version = "1.28", features = ["rt-multi-thread"] } thiserror = "1.0.40" From 5734033f967e2302b2c69643c62d386d3c65d732 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 4 Jul 2023 16:06:07 +0200 Subject: [PATCH 1077/1210] Update docs (#2242) --- docs/polkadot-kusama-bridge-overview.md | 12 ++++++------ docs/polkadot-kusama-bridge.html | 26 ++++++++++++------------- modules/messages/README.md | 4 ++-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/polkadot-kusama-bridge-overview.md b/docs/polkadot-kusama-bridge-overview.md index e59e0058530a5..b469720f65b2b 100644 --- a/docs/polkadot-kusama-bridge-overview.md +++ b/docs/polkadot-kusama-bridge-overview.md @@ -24,9 +24,9 @@ You won't be able to directly use bridge hub transactions to send XCM messages o to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will just queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. -Our first planned bridge will connect the Polkadot' AssetHub and Kusama' AssetHub. Bridge between those two -parachains would allow AssetHubPolkadot accounts to hold wrapped KSM tokens and AssetHubKusama accounts to hold wrapped DOT -tokens. +Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two +parachains would allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama +accounts to hold wrapped DOT tokens. For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, when other parachains will join the bridge, they will be using other lanes for their messages. @@ -93,13 +93,13 @@ Obviously, there should be someone who is paying relayer rewards. We want bridge can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides of the bridge to cover relayer rewards. -Bridged Parachains will have sovereign accounts at bridge hubs. For example, the AssetHubKusama (Kusama Parachain) will -have an account at the Polkadot Bridge Hub. The AssetHubPolkadot (Polkadot Parachain) will have an account at the Kusama +Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will +have an account at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the `pallet_bridge_relayers::claim_rewards`. Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. -AssetHubKusama will only reward relayers that are delivering messages from AssetHubKusama. The AssetHubKusama sovereign account +Kusama Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign account is not used to cover rewards of bridging with some other Polkadot Parachain. ### Multiple Relayers and Rewards diff --git a/docs/polkadot-kusama-bridge.html b/docs/polkadot-kusama-bridge.html index 272412226f67c..bf248adb57167 100644 --- a/docs/polkadot-kusama-bridge.html +++ b/docs/polkadot-kusama-bridge.html @@ -16,7 +16,7 @@

Polkadot <> Kusama Bridge

In our architecture, the lane that is used to relay messages over the bridge is determined by - the XCM source and destinations. So e.g. bridge between AssetHubPolkadot and AssetHubKusama (and opposite direction) + the XCM source and destinations. So e.g. bridge between Asset Hubs Polkadot and Kusama (and opposite direction) will use the lane 00000000, bridge between some other Polkadot Parachain and some other Kusama Parachain will use the lane 00000001 and so on.

@@ -24,33 +24,33 @@

Polkadot <> Kusama Bridge

flowchart LR subgraph Polkadot Consensus polkadot(((Polkadot))) - statemint(((Statemint))) + asset_hub_polkadot(((Polkadot Asset Hub))) polkadot_bh(((Polkadot Bridge Hub))) - polkadot---statemint + polkadot---asset_hub_polkadot polkadot---polkadot_bh - statemint-->|Send Message Using HRMP|polkadot_bh + asset_hub_polkadot-->|Send Message Using HRMP|polkadot_bh - polkadot_bh-->|Send Message Using HRMP|statemint - statemint-->|Dispatch the Message|statemint + polkadot_bh-->|Send Message Using HRMP|asset_hub_polkadot + asset_hub_polkadot-->|Dispatch the Message|asset_hub_polkadot end subgraph Kusama Consensus kusama_bh(((Kusama Bridge Hub))) - statemine(((Statemine))) + asset_hub_kusama(((Kusama Asset Hub))) kusama(((Kusama))) - kusama---statemine + kusama---asset_hub_kusama kusama---kusama_bh - kusama_bh-->|Send Message Using HRMP|statemine - statemine-->|Dispatch the Message|statemine + kusama_bh-->|Send Message Using HRMP|asset_hub_kusama + asset_hub_kusama-->|Dispatch the Message|asset_hub_kusama - statemine-->|Send Message Using HRMP|kusama_bh + asset_hub_kusama-->|Send Message Using HRMP|kusama_bh end polkadot_bh<===>|Message is relayed to the Bridged Chain using lane 00000000|kusama_bh - + linkStyle 2 stroke:red linkStyle 7 stroke:red linkStyle 8 stroke:red @@ -64,4 +64,4 @@

Polkadot <> Kusama Bridge

mermaid.initialize({ startOnLoad: true }); - + \ No newline at end of file diff --git a/modules/messages/README.md b/modules/messages/README.md index 3b84656025fff..b5250d0dca0b2 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -33,8 +33,8 @@ is the runtime developer who defines what message lane and message mean for this In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane as a channel of communication between two parachains of different relay chains. For example, lane -`[0, 0, 0, 0]` is used for AssetHubPolkadot <> AssetHubKusama communications. Other lanes may be used to bridge -another parachains. +`[0, 0, 0, 0]` is used for Polkadot <> Kusama Asset Hub communications. Other lanes may be used to +bridge other parachains. ## Message Workflow From 68e03e7a63939264aef476bc7c2486794bb712d5 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 4 Jul 2023 17:04:44 +0200 Subject: [PATCH 1078/1210] Fix deps from Cumulus (#2244) * Fix deps * Fix deps --- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 4 ++-- primitives/runtime/Cargo.toml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 9718318f603d8..bb372085292cf 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index e5d5f70895bcc..ecb0bdc4079d1 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge dependencies @@ -34,7 +34,7 @@ std = [ "codec/std", "frame-support/std", "scale-info/std", - "serde", + "serde/std", "sp-core/std", "sp-std/std" ] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 456cfea9edb22..4a4bc932bce01 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -12,7 +12,7 @@ hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Substrate Dependencies @@ -38,7 +38,7 @@ std = [ "hash-db/std", "num-traits/std", "scale-info/std", - "serde", + "serde/std", "sp-core/std", "sp-io/std", "sp-runtime/std", From d1fb1b5199d36afda512423efbc1e5fa1fc900a5 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 7 Jul 2023 13:26:55 +0300 Subject: [PATCH 1079/1210] Deduplicate Grandpa consensus log reading logic (#2245) (#2246) --- modules/grandpa/src/lib.rs | 52 ++++--------------- primitives/header-chain/src/lib.rs | 17 +++++- .../src/finality/engine.rs | 7 ++- 3 files changed, 29 insertions(+), 47 deletions(-) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index f9c3ab68a06f2..b789aedef2c8f 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -39,13 +39,12 @@ pub use storage_types::StoredAuthoritySet; use bp_header_chain::{ - justification::GrandpaJustification, ChainWithGrandpa, HeaderChain, InitializationData, - StoredHeaderData, StoredHeaderDataBuilder, + justification::GrandpaJustification, ChainWithGrandpa, GrandpaConsensusLogReader, HeaderChain, + InitializationData, StoredHeaderData, StoredHeaderDataBuilder, }; use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; use frame_support::{dispatch::PostDispatchInfo, ensure, DefaultNoBound}; -use sp_consensus_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, SaturatedConversion, @@ -443,11 +442,17 @@ pub mod pallet { // We don't support forced changes - at that point governance intervention is required. ensure!( - super::find_forced_change(header).is_none(), + GrandpaConsensusLogReader::>::find_forced_change( + header.digest() + ) + .is_none(), >::UnsupportedScheduledChange ); - if let Some(change) = super::find_scheduled_change(header) { + if let Some(change) = + GrandpaConsensusLogReader::>::find_scheduled_change( + header.digest(), + ) { // GRANDPA only includes a `delay` for forced changes, so this isn't valid. ensure!(change.delay == Zero::zero(), >::UnsupportedScheduledChange); @@ -616,42 +621,6 @@ impl, I: 'static> HeaderChain> for GrandpaChainH } } -pub(crate) fn find_scheduled_change( - header: &H, -) -> Option> { - use sp_runtime::generic::OpaqueDigestItemId; - - let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); - - let filter_log = |log: ConsensusLog| match log { - ConsensusLog::ScheduledChange(change) => Some(change), - _ => None, - }; - - // find the first consensus digest with the right ID which converts to - // the right kind of consensus log. - header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) -} - -/// Checks the given header for a consensus digest signaling a **forced** scheduled change and -/// extracts it. -pub(crate) fn find_forced_change( - header: &H, -) -> Option<(H::Number, sp_consensus_grandpa::ScheduledChange)> { - use sp_runtime::generic::OpaqueDigestItemId; - - let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); - - let filter_log = |log: ConsensusLog| match log { - ConsensusLog::ForcedChange(delay, change) => Some((delay, change)), - _ => None, - }; - - // find the first consensus digest with the right ID which converts to - // the right kind of consensus log. - header.digest().convert_first(|l| l.try_to(id).and_then(filter_log)) -} - /// (Re)initialize bridge with given header for using it in `pallet-bridge-messages` benchmarks. #[cfg(feature = "runtime-benchmarks")] pub fn initialize_for_benchmarks, I: 'static>(header: BridgedHeader) { @@ -685,6 +654,7 @@ mod tests { storage::generator::StorageValue, }; use frame_system::{EventRecord, Phase}; + use sp_consensus_grandpa::{ConsensusLog, GRANDPA_ENGINE_ID}; use sp_core::Get; use sp_runtime::{Digest, DigestItem, DispatchError}; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5b27845472896..6b9373cf18798 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -139,7 +139,7 @@ pub trait ConsensusLogReader { pub struct GrandpaConsensusLogReader(sp_std::marker::PhantomData); impl GrandpaConsensusLogReader { - pub fn find_authorities_change( + pub fn find_scheduled_change( digest: &Digest, ) -> Option> { // find the first consensus digest with the right ID which converts to @@ -151,11 +151,24 @@ impl GrandpaConsensusLogReader { _ => None, }) } + + pub fn find_forced_change( + digest: &Digest, + ) -> Option<(Number, sp_consensus_grandpa::ScheduledChange)> { + // find the first consensus digest with the right ID which converts to + // the right kind of consensus log. + digest + .convert_first(|log| log.consensus_try_to(&GRANDPA_ENGINE_ID)) + .and_then(|log| match log { + ConsensusLog::ForcedChange(delay, change) => Some((delay, change)), + _ => None, + }) + } } impl ConsensusLogReader for GrandpaConsensusLogReader { fn schedules_authorities_change(digest: &Digest) -> bool { - GrandpaConsensusLogReader::::find_authorities_change(digest).is_some() + GrandpaConsensusLogReader::::find_scheduled_change(digest).is_some() } } diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index f2ddd32db8600..0c22ec040f912 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -237,10 +237,9 @@ impl Engine for Grandpa { // If initial header changes the GRANDPA authorities set, then we need previous authorities // to verify justification. let mut authorities_for_verification = initial_authorities_set.clone(); - let scheduled_change = - GrandpaConsensusLogReader::>::find_authorities_change( - initial_header.digest(), - ); + let scheduled_change = GrandpaConsensusLogReader::>::find_scheduled_change( + initial_header.digest(), + ); assert!( scheduled_change.as_ref().map(|c| c.delay.is_zero()).unwrap_or(true), "GRANDPA authorities change at {} scheduled to happen in {:?} blocks. We expect\ From 02efaf2e14883634292e9bfca1170f234d32c724 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 7 Jul 2023 16:33:21 +0300 Subject: [PATCH 1080/1210] Define generate_grandpa_key_ownership_proof() (#2247) (#2248) --- relays/client-substrate/Cargo.toml | 1 + relays/client-substrate/src/client.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 4dd7975280409..359f049d9dbd0 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -39,6 +39,7 @@ pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "ma sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index a1c8a22be19d0..8a0875a89763e 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -52,6 +52,8 @@ use sp_version::RuntimeVersion; use std::future::Future; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; +const SUB_API_GRANDPA_GENERATE_KEY_OWNERSHIP_PROOF: &str = + "GrandpaApi_generate_key_ownership_proof"; const SUB_API_TXPOOL_VALIDATE_TRANSACTION: &str = "TaggedTransactionQueue_validate_transaction"; const SUB_API_TX_PAYMENT_QUERY_INFO: &str = "TransactionPaymentApi_query_info"; const MAX_SUBSCRIPTION_CAPACITY: usize = 4096; @@ -713,6 +715,23 @@ impl Client { Ok(Subscription(Mutex::new(receiver))) } + // TODO: remove warning after implementing + // https://github.com/paritytech/parity-bridges-common/issues/39 + #[allow(dead_code)] + async fn generate_grandpa_key_ownership_proof( + &self, + at: HashOf, + set_id: sp_consensus_grandpa::SetId, + authority_id: sp_consensus_grandpa::AuthorityId, + ) -> Result> { + self.typed_state_call( + SUB_API_GRANDPA_GENERATE_KEY_OWNERSHIP_PROOF.into(), + (set_id, authority_id), + Some(at), + ) + .await + } + /// Execute jsonrpsee future in tokio context. async fn jsonrpsee_execute(&self, make_jsonrpsee_future: MF) -> Result where From cc0bf6bf48df755c90bf62bf7f076416611e75a9 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 10 Jul 2023 15:31:48 +0300 Subject: [PATCH 1081/1210] Implement RuntimeDebug for GrandpaJustification (#2254) --- primitives/header-chain/src/justification.rs | 23 ++------------------ 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index 8433107fce20d..a8f5148253129 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -24,7 +24,7 @@ use crate::ChainWithGrandpa; use bp_runtime::{BlockNumberOf, Chain, HashOf}; use codec::{Decode, Encode, MaxEncodedLen}; use finality_grandpa::voter_set::VoterSet; -use frame_support::RuntimeDebug; +use frame_support::{RuntimeDebug, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::{traits::Header as HeaderT, SaturatedConversion}; @@ -38,7 +38,7 @@ use sp_std::{ /// /// This particular proof is used to prove that headers on a bridged chain /// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] +#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeDebugNoBound)] pub struct GrandpaJustification { /// The round (voting period) this justification is valid for. pub round: u64, @@ -49,25 +49,6 @@ pub struct GrandpaJustification { pub votes_ancestries: Vec
, } -// TODO: remove and use `RuntimeDebug` (https://github.com/paritytech/parity-bridges-common/issues/2136) -impl sp_std::fmt::Debug for GrandpaJustification
{ - fn fmt(&self, fmt: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result { - #[cfg(feature = "std")] - { - fmt.debug_struct("GrandpaJustification") - .field("round", &self.round) - .field("commit", &self.commit) - .field("votes_ancestries", &self.votes_ancestries) - .finish() - } - - #[cfg(not(feature = "std"))] - { - fmt.write_str("") - } - } -} - impl GrandpaJustification { /// Returns reasonable size of justification using constants from the provided chain. /// From ebb8257d5ca4dbaed6a3e2bcd6dff1d041447013 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 13 Jul 2023 16:24:03 +0300 Subject: [PATCH 1082/1210] GRANDPA: optimize votes_ancestries when needed (#2262) (#2264) * GRANDPA: optimize votes_ancestries when needed * Address review comments --- primitives/header-chain/src/justification.rs | 225 +++++++++++------- .../tests/implementation_match.rs | 28 +-- .../header-chain/tests/justification.rs | 99 +++++++- .../src/finality/engine.rs | 10 +- .../src/finality/target.rs | 4 +- .../src/on_demand/headers.rs | 4 +- 6 files changed, 255 insertions(+), 115 deletions(-) diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index a8f5148253129..b83c697d60875 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -21,7 +21,7 @@ use crate::ChainWithGrandpa; -use bp_runtime::{BlockNumberOf, Chain, HashOf}; +use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId}; use codec::{Decode, Encode, MaxEncodedLen}; use finality_grandpa::voter_set::VoterSet; use frame_support::{RuntimeDebug, RuntimeDebugNoBound}; @@ -84,6 +84,10 @@ impl GrandpaJustification { 8u32.saturating_add(max_expected_signed_commit_size) .saturating_add(max_expected_votes_ancestries_size) } + + pub fn commit_target_id(&self) -> HeaderId { + HeaderId(self.commit.target_number, self.commit.target_hash) + } } impl crate::FinalityProof for GrandpaJustification { @@ -109,12 +113,12 @@ pub enum Error { InvalidAuthoritySignature, /// The justification contains precommit for header that is not a descendant of the commit /// header. - PrecommitIsNotCommitDescendant, + UnrelatedAncestryVote, /// The cumulative weight of all votes in the justification is not enough to justify commit /// header finalization. TooLowCumulativeWeight, /// The justification contains extra (unused) headers in its `votes_ancestries` field. - ExtraHeadersInVotesAncestries, + RedundantVotesAncestries, } /// Given GRANDPA authorities set size, return number of valid authorities votes that the @@ -139,20 +143,25 @@ pub fn verify_and_optimize_justification( finalized_target: (Header::Hash, Header::Number), authorities_set_id: SetId, authorities_set: &VoterSet, - justification: GrandpaJustification
, -) -> Result, Error> + justification: &mut GrandpaJustification
, +) -> Result<(), Error> where Header::Number: finality_grandpa::BlockNumberOps, { - let mut optimizer = OptimizationCallbacks(Vec::new()); + let mut optimizer = OptimizationCallbacks { + extra_precommits: vec![], + redundant_votes_ancestries: Default::default(), + }; verify_justification_with_callbacks( finalized_target, authorities_set_id, authorities_set, - &justification, + justification, &mut optimizer, )?; - Ok(optimizer.optimize(justification)) + optimizer.optimize(justification); + + Ok(()) } /// Verify that justification, that is generated by given authority set, finalizes given header. @@ -175,19 +184,28 @@ where } /// Verification callbacks. -trait VerificationCallbacks { +trait VerificationCallbacks { /// Called when we see a precommit from unknown authority. fn on_unkown_authority(&mut self, precommit_idx: usize) -> Result<(), Error>; /// Called when we see a precommit with duplicate vote from known authority. fn on_duplicate_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; + /// Called when we see a precommit with an invalid signature. + fn on_invalid_authority_signature(&mut self, precommit_idx: usize) -> Result<(), Error>; /// Called when we see a precommit after we've collected enough votes from authorities. fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; + /// Called when we see a precommit that is not a descendant of the commit target. + fn on_unrelated_ancestry_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; + /// Called when there are redundant headers in the votes ancestries. + fn on_redundant_votes_ancestries( + &mut self, + redundant_votes_ancestries: BTreeSet, + ) -> Result<(), Error>; } /// Verification callbacks that reject all unknown, duplicate or redundant votes. struct StrictVerificationCallbacks; -impl VerificationCallbacks for StrictVerificationCallbacks { +impl VerificationCallbacks
for StrictVerificationCallbacks { fn on_unkown_authority(&mut self, _precommit_idx: usize) -> Result<(), Error> { Err(Error::UnknownAuthorityVote) } @@ -196,45 +214,82 @@ impl VerificationCallbacks for StrictVerificationCallbacks { Err(Error::DuplicateAuthorityVote) } + fn on_invalid_authority_signature(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Err(Error::InvalidAuthoritySignature) + } + fn on_redundant_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { Err(Error::RedundantVotesInJustification) } + + fn on_unrelated_ancestry_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { + Err(Error::UnrelatedAncestryVote) + } + + fn on_redundant_votes_ancestries( + &mut self, + _redundant_votes_ancestries: BTreeSet, + ) -> Result<(), Error> { + Err(Error::RedundantVotesAncestries) + } } /// Verification callbacks for justification optimization. -struct OptimizationCallbacks(Vec); - -impl OptimizationCallbacks { - fn optimize( - self, - mut justification: GrandpaJustification
, - ) -> GrandpaJustification
{ - for invalid_precommit_idx in self.0.into_iter().rev() { +struct OptimizationCallbacks { + extra_precommits: Vec, + redundant_votes_ancestries: BTreeSet, +} + +impl OptimizationCallbacks
{ + fn optimize(self, justification: &mut GrandpaJustification
) { + for invalid_precommit_idx in self.extra_precommits.into_iter().rev() { justification.commit.precommits.remove(invalid_precommit_idx); } - justification + if !self.redundant_votes_ancestries.is_empty() { + justification + .votes_ancestries + .retain(|header| !self.redundant_votes_ancestries.contains(&header.hash())) + } } } -impl VerificationCallbacks for OptimizationCallbacks { +impl VerificationCallbacks
for OptimizationCallbacks
{ fn on_unkown_authority(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.0.push(precommit_idx); + self.extra_precommits.push(precommit_idx); Ok(()) } fn on_duplicate_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.0.push(precommit_idx); + self.extra_precommits.push(precommit_idx); + Ok(()) + } + + fn on_invalid_authority_signature(&mut self, precommit_idx: usize) -> Result<(), Error> { + self.extra_precommits.push(precommit_idx); Ok(()) } fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.0.push(precommit_idx); + self.extra_precommits.push(precommit_idx); + Ok(()) + } + + fn on_unrelated_ancestry_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { + self.extra_precommits.push(precommit_idx); + Ok(()) + } + + fn on_redundant_votes_ancestries( + &mut self, + redundant_votes_ancestries: BTreeSet, + ) -> Result<(), Error> { + self.redundant_votes_ancestries = redundant_votes_ancestries; Ok(()) } } /// Verify that justification, that is generated by given authority set, finalizes given header. -fn verify_justification_with_callbacks( +fn verify_justification_with_callbacks>( finalized_target: (Header::Hash, Header::Number), authorities_set_id: SetId, authorities_set: &VoterSet, @@ -249,8 +304,8 @@ where return Err(Error::InvalidJustificationTarget) } - let threshold = authorities_set.threshold().0.into(); - let mut chain = AncestryChain::new(&justification.votes_ancestries); + let threshold = authorities_set.threshold().get(); + let mut chain = AncestryChain::new(justification); let mut signature_buffer = Vec::new(); let mut votes = BTreeSet::new(); let mut cumulative_weight = 0u64; @@ -277,34 +332,20 @@ where // there's a lot of code in `validate_commit` and `import_precommit` functions inside // `finality-grandpa` crate (mostly related to reporting equivocations). But the only thing // that we care about is that only first vote from the authority is accepted - if !votes.insert(signed.id.clone()) { + if votes.contains(&signed.id) { callbacks.on_duplicate_authority_vote(precommit_idx)?; continue } - // everything below this line can't just `continue`, because state is already altered - - // precommits aren't allowed for block lower than the target - if signed.precommit.target_number < justification.commit.target_number { - return Err(Error::PrecommitIsNotCommitDescendant) - } - // all precommits must be descendants of target block - chain = chain - .ensure_descendant(&justification.commit.target_hash, &signed.precommit.target_hash)?; - // since we know now that the precommit target is the descendant of the justification - // target, we may increase 'weight' of the justification target - // - // there's a lot of code in the `VoteGraph::insert` method inside `finality-grandpa` crate, - // but in the end it is only used to find GHOST, which we don't care about. The only thing - // that we care about is that the justification target has enough weight - cumulative_weight = cumulative_weight.checked_add(authority_info.weight().0.into()).expect( - "sum of weights of ALL authorities is expected not to overflow - this is guaranteed by\ - existence of VoterSet;\ - the order of loop conditions guarantees that we can account vote from same authority\ - multiple times;\ - thus we'll never overflow the u64::MAX;\ - qed", - ); + // all precommits must be descendants of the target block + let route = + match chain.ancestry(&signed.precommit.target_hash, &signed.precommit.target_number) { + Some(route) => route, + None => { + callbacks.on_unrelated_ancestry_vote(precommit_idx)?; + continue + }, + }; // verify authority signature if !sp_consensus_grandpa::check_message_signature_with_buffer( @@ -315,76 +356,98 @@ where authorities_set_id, &mut signature_buffer, ) { - return Err(Error::InvalidAuthoritySignature) + callbacks.on_invalid_authority_signature(precommit_idx)?; + continue } + + // now we can count the vote since we know that it is valid + votes.insert(signed.id.clone()); + chain.mark_route_as_visited(route); + cumulative_weight = cumulative_weight.saturating_add(authority_info.weight().get()); } - // check that there are no extra headers in the justification - if !chain.unvisited.is_empty() { - return Err(Error::ExtraHeadersInVotesAncestries) + // check that the cumulative weight of validators that voted for the justification target (or + // one of its descendents) is larger than the required threshold. + if cumulative_weight < threshold { + return Err(Error::TooLowCumulativeWeight) } - // check that the cumulative weight of validators voted for the justification target (or one - // of its descendents) is larger than required threshold. - if cumulative_weight >= threshold { - Ok(()) - } else { - Err(Error::TooLowCumulativeWeight) + // check that there are no extra headers in the justification + if !chain.is_fully_visited() { + callbacks.on_redundant_votes_ancestries(chain.unvisited)?; } + + Ok(()) } /// Votes ancestries with useful methods. #[derive(RuntimeDebug)] pub struct AncestryChain { + /// We expect all forks in the ancestry chain to be descendants of base. + base: HeaderId, /// Header hash => parent header hash mapping. pub parents: BTreeMap, - /// Hashes of headers that were not visited by `is_ancestor` method. + /// Hashes of headers that were not visited by `ancestry()`. pub unvisited: BTreeSet, } impl AncestryChain
{ /// Create new ancestry chain. - pub fn new(ancestry: &[Header]) -> AncestryChain
{ + pub fn new(justification: &GrandpaJustification
) -> AncestryChain
{ let mut parents = BTreeMap::new(); let mut unvisited = BTreeSet::new(); - for ancestor in ancestry { + for ancestor in &justification.votes_ancestries { let hash = ancestor.hash(); let parent_hash = *ancestor.parent_hash(); parents.insert(hash, parent_hash); unvisited.insert(hash); } - AncestryChain { parents, unvisited } + AncestryChain { base: justification.commit_target_id(), parents, unvisited } } - /// Returns `Ok(_)` if `precommit_target` is a descendant of the `commit_target` block and - /// `Err(_)` otherwise. - pub fn ensure_descendant( - mut self, - commit_target: &Header::Hash, - precommit_target: &Header::Hash, - ) -> Result { - let mut current_hash = *precommit_target; + /// Returns a route if the precommit target block is a descendant of the `base` block. + pub fn ancestry( + &self, + precommit_target_hash: &Header::Hash, + precommit_target_number: &Header::Number, + ) -> Option> { + if precommit_target_number < &self.base.number() { + return None + } + + let mut route = vec![]; + let mut current_hash = *precommit_target_hash; loop { - if current_hash == *commit_target { + if current_hash == self.base.hash() { break } - let is_visited_before = !self.unvisited.remove(¤t_hash); current_hash = match self.parents.get(¤t_hash) { Some(parent_hash) => { + let is_visited_before = self.unvisited.get(¤t_hash).is_none(); if is_visited_before { - // `Some(parent_hash)` means that the `current_hash` is in the `parents` - // container `is_visited_before` means that it has been visited before in - // some of previous calls => since we assume that previous call has finished - // with `true`, this also will be finished with `true` - return Ok(self) + // If the current header has been visited in a previous call, it is a + // descendent of `base` (we assume that the previous call was successful). + return Some(route) } + route.push(current_hash); *parent_hash }, - None => return Err(Error::PrecommitIsNotCommitDescendant), + None => return None, }; } - Ok(self) + + Some(route) + } + + fn mark_route_as_visited(&mut self, route: Vec) { + for hash in route { + self.unvisited.remove(&hash); + } + } + + fn is_fully_visited(&self) -> bool { + self.unvisited.is_empty() } } diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index c70683b173d1f..46652dede56ad 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -38,8 +38,8 @@ type TestNumber = ::Number; struct AncestryChain(bp_header_chain::justification::AncestryChain); impl AncestryChain { - fn new(ancestry: &[TestHeader]) -> Self { - Self(bp_header_chain::justification::AncestryChain::new(ancestry)) + fn new(justification: &GrandpaJustification) -> Self { + Self(bp_header_chain::justification::AncestryChain::new(justification)) } } @@ -55,9 +55,9 @@ impl finality_grandpa::Chain for AncestryChain { if current_hash == base { break } - match self.0.parents.get(¤t_hash).cloned() { + match self.0.parents.get(¤t_hash) { Some(parent_hash) => { - current_hash = parent_hash; + current_hash = *parent_hash; route.push(current_hash); }, _ => return Err(finality_grandpa::Error::NotDescendent), @@ -124,7 +124,7 @@ fn same_result_when_precommit_target_has_lower_number_than_commit_target() { &full_voter_set(), &justification, ), - Err(Error::PrecommitIsNotCommitDescendant), + Err(Error::UnrelatedAncestryVote), ); // original implementation returns `Ok(validation_result)` @@ -132,7 +132,7 @@ fn same_result_when_precommit_target_has_lower_number_than_commit_target() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -157,7 +157,7 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { &full_voter_set(), &justification, ), - Err(Error::PrecommitIsNotCommitDescendant), + Err(Error::UnrelatedAncestryVote), ); // original implementation returns `Ok(validation_result)` @@ -165,7 +165,7 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -198,7 +198,7 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -236,7 +236,7 @@ fn different_result_when_justification_contains_duplicate_vote() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -277,7 +277,7 @@ fn different_results_when_authority_equivocates_once_in_a_round() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -330,7 +330,7 @@ fn different_results_when_authority_equivocates_twice_in_a_round() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -369,7 +369,7 @@ fn different_results_when_there_are_more_than_enough_votes() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); @@ -410,7 +410,7 @@ fn different_results_when_there_is_a_vote_of_unknown_authority() { let result = finality_grandpa::validate_commit( &justification.commit, &full_voter_set(), - &AncestryChain::new(&justification.votes_ancestries), + &AncestryChain::new(&justification), ) .unwrap(); diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification.rs index 3cd63b935d00e..26ed67fa65f61 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification.rs @@ -21,6 +21,8 @@ use bp_header_chain::justification::{ Error, }; use bp_test_utils::*; +use finality_grandpa::SignedPrecommit; +use sp_consensus_grandpa::AuthoritySignature; type TestHeader = sp_runtime::testing::Header; @@ -133,7 +135,7 @@ fn justification_with_invalid_commit_rejected() { &voter_set(), &justification, ), - Err(Error::ExtraHeadersInVotesAncestries), + Err(Error::TooLowCumulativeWeight), ); } @@ -166,7 +168,7 @@ fn justification_with_invalid_precommit_ancestry() { &voter_set(), &justification, ), - Err(Error::ExtraHeadersInVotesAncestries), + Err(Error::RedundantVotesAncestries), ); } @@ -197,14 +199,14 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { #[test] fn optimizer_does_noting_with_minimal_justification() { - let justification = make_default_justification::(&test_header(1)); + let mut justification = make_default_justification::(&test_header(1)); let num_precommits_before = justification.commit.precommits.len(); - let justification = verify_and_optimize_justification::( + verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - justification, + &mut justification, ) .unwrap(); let num_precommits_after = justification.commit.precommits.len(); @@ -223,11 +225,11 @@ fn unknown_authority_votes_are_removed_by_optimizer() { )); let num_precommits_before = justification.commit.precommits.len(); - let justification = verify_and_optimize_justification::( + verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - justification, + &mut justification, ) .unwrap(); let num_precommits_after = justification.commit.precommits.len(); @@ -244,11 +246,42 @@ fn duplicate_authority_votes_are_removed_by_optimizer() { .push(justification.commit.precommits.first().cloned().unwrap()); let num_precommits_before = justification.commit.precommits.len(); - let justification = verify_and_optimize_justification::( + verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - justification, + &mut justification, + ) + .unwrap(); + let num_precommits_after = justification.commit.precommits.len(); + + assert_eq!(num_precommits_before - 1, num_precommits_after); +} + +#[test] +fn invalid_authority_signatures_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(1)); + + let target = header_id::(1); + let invalid_raw_signature: Vec = ALICE.sign(b"").to_bytes().into(); + justification.commit.precommits.insert( + 0, + SignedPrecommit { + precommit: finality_grandpa::Precommit { + target_hash: target.0, + target_number: target.1, + }, + signature: AuthoritySignature::try_from(invalid_raw_signature).unwrap(), + id: ALICE.into(), + }, + ); + + let num_precommits_before = justification.commit.precommits.len(); + verify_and_optimize_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &mut justification, ) .unwrap(); let num_precommits_after = justification.commit.precommits.len(); @@ -267,14 +300,58 @@ fn redundant_authority_votes_are_removed_by_optimizer() { )); let num_precommits_before = justification.commit.precommits.len(); - let justification = verify_and_optimize_justification::( + verify_and_optimize_justification::( header_id::(1), TEST_GRANDPA_SET_ID, &voter_set(), - justification, + &mut justification, ) .unwrap(); let num_precommits_after = justification.commit.precommits.len(); assert_eq!(num_precommits_before - 1, num_precommits_after); } + +#[test] +fn unrelated_ancestry_votes_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(2)); + justification.commit.precommits.insert( + 0, + signed_precommit::( + &ALICE, + header_id::(1), + justification.round, + TEST_GRANDPA_SET_ID, + ), + ); + + let num_precommits_before = justification.commit.precommits.len(); + verify_and_optimize_justification::( + header_id::(2), + TEST_GRANDPA_SET_ID, + &voter_set(), + &mut justification, + ) + .unwrap(); + let num_precommits_after = justification.commit.precommits.len(); + + assert_eq!(num_precommits_before - 1, num_precommits_after); +} + +#[test] +fn redundant_votes_ancestries_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(1)); + justification.votes_ancestries.push(test_header(100)); + + let num_votes_ancestries_before = justification.votes_ancestries.len(); + verify_and_optimize_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &mut justification, + ) + .unwrap(); + let num_votes_ancestries_after = justification.votes_ancestries.len(); + + assert_eq!(num_votes_ancestries_before - 1, num_votes_ancestries_after); +} diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 0c22ec040f912..3f7e3eecbaa98 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -91,8 +91,8 @@ pub trait Engine: Send { async fn optimize_proof( target_client: &Client, header: &C::Header, - proof: Self::FinalityProof, - ) -> Result; + proof: &mut Self::FinalityProof, + ) -> Result<(), SubstrateError>; /// Prepare initialization data for the finality bridge pallet. async fn prepare_initialization_data( @@ -149,8 +149,8 @@ impl Engine for Grandpa { async fn optimize_proof( target_client: &Client, header: &C::Header, - proof: Self::FinalityProof, - ) -> Result { + proof: &mut Self::FinalityProof, + ) -> Result<(), SubstrateError> { let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key( C::WITH_CHAIN_GRANDPA_PALLET_NAME, ); @@ -275,7 +275,7 @@ impl Engine for Grandpa { (initial_header_hash, initial_header_number), initial_authorities_set_id, &authorities_for_verification, - justification.clone(), + &mut justification.clone(), ) .is_ok(); diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 81a22520fa951..2d9d4b856e025 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -109,10 +109,10 @@ where async fn submit_finality_proof( &self, header: SyncHeader>, - proof: SubstrateFinalityProof

, + mut proof: SubstrateFinalityProof

, ) -> Result { // runtime module at target chain may require optimized finality proof - let proof = P::FinalityEngine::optimize_proof(&self.client, &header, proof).await?; + P::FinalityEngine::optimize_proof(&self.client, &header, &mut proof).await?; // now we may submit optimized finality proof let transaction_params = self.transaction_params.clone(); diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index aded79a857af2..1dfc544703c88 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -135,11 +135,11 @@ impl OnDemandRelay Result<(HeaderIdOf, Vec>), SubstrateError> { // first find proper header (either `required_header`) or its descendant let finality_source = SubstrateFinalitySource::

::new(self.source_client.clone(), None); - let (header, proof) = finality_source.prove_block_finality(required_header).await?; + let (header, mut proof) = finality_source.prove_block_finality(required_header).await?; let header_id = header.id(); // optimize justification before including it into the call - let proof = P::FinalityEngine::optimize_proof(&self.target_client, &header, proof).await?; + P::FinalityEngine::optimize_proof(&self.target_client, &header, &mut proof).await?; log::debug!( target: "bridge", From 8b10f171e21324f3d76adfb2073e781746e82eb4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 19 Jul 2023 18:18:05 +0300 Subject: [PATCH 1083/1210] Update dependecies (#2277) (#2281) * cargo update -p parachain-info * flush * it compiles * clippy * temporary add more logging to cargo deny * Revert "temporary add more logging to cargo deny" This reverts commit 20daa88bca6d9a01dbe933579b1d57ae5c3a7bd8. * list installed Rust binaries before running cargo deny * changed prev commit * once again * try cargo update? * post-update fixes (nothing important) --- bin/millau/node/Cargo.toml | 5 +- bin/millau/node/src/chain_spec.rs | 14 +- bin/millau/node/src/command.rs | 9 +- bin/millau/node/src/service.rs | 48 ++++-- bin/millau/runtime/src/lib.rs | 32 ++-- bin/millau/runtime/src/xcm_config.rs | 5 +- bin/rialto-parachain/node/src/chain_spec.rs | 12 +- bin/rialto-parachain/node/src/cli.rs | 39 +---- bin/rialto-parachain/node/src/command.rs | 99 +++--------- bin/rialto-parachain/node/src/service.rs | 5 +- bin/rialto-parachain/runtime/src/lib.rs | 32 ++-- bin/rialto/node/src/chain_spec.rs | 20 +-- bin/rialto/node/src/command.rs | 10 +- bin/rialto/runtime/src/lib.rs | 153 ++++++++++-------- bin/rialto/runtime/src/parachains.rs | 4 +- bin/rialto/runtime/src/xcm_config.rs | 5 +- bin/runtime-common/src/integrity.rs | 10 +- bin/runtime-common/src/mock.rs | 22 +-- modules/beefy/src/lib.rs | 4 +- modules/beefy/src/mock.rs | 19 +-- modules/grandpa/src/call_ext.rs | 4 +- modules/grandpa/src/lib.rs | 2 +- modules/grandpa/src/mock.rs | 25 ++- modules/messages/src/lib.rs | 6 +- modules/messages/src/mock.rs | 18 +-- modules/parachains/src/lib.rs | 2 +- modules/parachains/src/mock.rs | 27 ++-- modules/relayers/src/lib.rs | 16 +- modules/relayers/src/mock.rs | 17 +- modules/shift-session-manager/src/lib.rs | 21 +-- primitives/beefy/Cargo.toml | 4 +- primitives/beefy/src/lib.rs | 4 +- .../chain-bridge-hub-cumulus/src/lib.rs | 14 +- primitives/chain-bridge-hub-kusama/src/lib.rs | 2 +- .../chain-bridge-hub-polkadot/src/lib.rs | 2 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 2 +- primitives/chain-bridge-hub-wococo/src/lib.rs | 2 +- primitives/chain-kusama/src/lib.rs | 2 +- primitives/chain-millau/Cargo.toml | 8 +- primitives/chain-millau/src/lib.rs | 12 +- primitives/chain-millau/src/millau_hash.rs | 2 - primitives/chain-polkadot/src/lib.rs | 2 +- primitives/chain-rialto-parachain/src/lib.rs | 6 +- primitives/chain-rialto/src/lib.rs | 6 +- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-westend/src/lib.rs | 4 +- primitives/chain-wococo/src/lib.rs | 2 +- primitives/header-chain/src/justification.rs | 17 +- primitives/header-chain/src/lib.rs | 6 +- .../tests/implementation_match.rs | 4 +- primitives/messages/src/lib.rs | 16 +- primitives/polkadot-core/src/lib.rs | 7 +- primitives/runtime/src/chain.rs | 10 +- primitives/runtime/src/lib.rs | 18 ++- primitives/runtime/src/messages.rs | 4 +- .../src/cli/register_parachain.rs | 4 +- relays/bin-substrate/src/cli/send_message.rs | 2 +- relays/client-millau/src/lib.rs | 4 +- relays/client-rialto/src/lib.rs | 4 +- relays/client-substrate/src/chain.rs | 4 +- relays/client-substrate/src/client.rs | 6 +- relays/client-substrate/src/lib.rs | 2 +- relays/client-substrate/src/rpc.rs | 2 +- relays/client-substrate/src/test_chain.rs | 4 +- .../src/transaction_tracker.rs | 4 +- .../src/finality/initialize.rs | 4 +- .../src/messages_metrics.rs | 4 +- .../src/on_demand/parachains.rs | 4 +- relays/messages/src/message_race_strategy.rs | 4 +- 69 files changed, 409 insertions(+), 486 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 6710c6a217f10..a0a0e4ffbd1e0 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,8 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.7", features = ["derive"] } +clap = { version = "4.3.12", features = ["derive"] } +futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.96" @@ -37,10 +38,12 @@ sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 8669ca92cc801..425f5685ae267 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -16,8 +16,9 @@ use millau_runtime::{ AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, - BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GenesisConfig, GrandpaConfig, - SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, + BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GrandpaConfig, + RuntimeGenesisConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, + WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_beefy::crypto::AuthorityId as BeefyId; @@ -41,7 +42,7 @@ const RIALTO_MESSAGES_PALLET_OWNER: &str = "Rialto.MessagesOwner"; const RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER: &str = "RialtoParachain.MessagesOwner"; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; /// The chain specification option. This is expected to come in from the CLI and /// is little more than one of a number of alternatives which can easily be converted @@ -193,17 +194,18 @@ fn testnet_genesis( root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, -) -> GenesisConfig { - GenesisConfig { +) -> RuntimeGenesisConfig { + RuntimeGenesisConfig { system: SystemConfig { code: WASM_BINARY.expect("Millau development WASM not available").to_vec(), + ..Default::default() }, balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, aura: AuraConfig { authorities: Vec::new() }, beefy: BeefyConfig::default(), - grandpa: GrandpaConfig { authorities: Vec::new() }, + grandpa: GrandpaConfig { authorities: Vec::new(), ..Default::default() }, sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { keys: initial_authorities diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs index b8dff87f8f244..745b393786e1d 100644 --- a/bin/millau/node/src/command.rs +++ b/bin/millau/node/src/command.rs @@ -21,7 +21,7 @@ use crate::{ }; use frame_benchmarking_cli::BenchmarkCmd; use millau_runtime::{Block, RuntimeApi}; -use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; +use sc_cli::SubstrateCli; use sc_service::PartialComponents; impl SubstrateCli for Cli { @@ -53,10 +53,6 @@ impl SubstrateCli for Cli { "millau-bridge-node".into() } - fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - &millau_runtime::VERSION - } - fn load_spec(&self, id: &str) -> Result, String> { Ok(Box::new( match id { @@ -83,8 +79,7 @@ pub fn run() -> sc_cli::Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - runner - .sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 3f0bc2536be0a..954b46fe0ceda 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -18,13 +18,14 @@ use jsonrpsee::RpcModule; use millau_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::BlockBackend; +use sc_client_api::{Backend, BlockBackend}; use sc_consensus_aura::{CompatibilityMode, ImportQueueParams, SlotProportion, StartAuraParams}; use sc_consensus_grandpa::SharedVoterState; pub use sc_executor::NativeElseWasmExecutor; use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; use sc_telemetry::{Telemetry, TelemetryWorker}; +use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use std::{sync::Arc, time::Duration}; @@ -127,6 +128,7 @@ pub fn new_partial( let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( client.clone(), + 512, &client, select_chain.clone(), telemetry.as_ref().map(|x| x.handle()), @@ -223,6 +225,7 @@ pub fn new_full(config: Configuration) -> Result { ); net_config.add_request_response_protocol(beefy_req_resp_cfg); + let role = config.role.clone(); let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -242,15 +245,28 @@ pub fn new_full(config: Configuration) -> Result { })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), + use futures::FutureExt; + + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-work", + sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { + runtime_api_provider: client.clone(), + keystore: Some(keystore_container.keystore()), + offchain_db: backend.offchain_storage(), + transaction_pool: Some(OffchainTransactionPoolFactory::new( + transaction_pool.clone(), + )), + network_provider: network.clone(), + is_validator: role.is_authority(), + enable_http_requests: false, + custom_extensions: move |_| vec![], + }) + .run(client.clone(), task_manager.spawn_handle()) + .boxed(), ); } - let role = config.role.clone(); let force_authoring = config.force_authoring; let backoff_authoring_blocks: Option<()> = None; let name = config.network.node_name.clone(); @@ -277,7 +293,7 @@ pub fn new_full(config: Configuration) -> Result { let shared_voter_state = shared_voter_state.clone(); let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( - backend, + backend.clone(), Some(shared_authority_set.clone()), ); @@ -308,7 +324,16 @@ pub fn new_full(config: Configuration) -> Result { .into_rpc(), ) .map_err(map_err)?; - io.merge(Mmr::new(client.clone()).into_rpc()).map_err(map_err)?; + io.merge( + Mmr::new( + client.clone(), + backend + .offchain_storage() + .ok_or("Backend doesn't provide the required offchain storage")?, + ) + .into_rpc(), + ) + .map_err(map_err)?; Ok(io) }) }; @@ -332,7 +357,7 @@ pub fn new_full(config: Configuration) -> Result { let proposer_factory = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), - transaction_pool, + transaction_pool.clone(), prometheus_registry.as_ref(), telemetry.as_ref().map(|x| x.handle()), ); @@ -411,7 +436,7 @@ pub fn new_full(config: Configuration) -> Result { let grandpa_config = sc_consensus_grandpa::Config { // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), - justification_period: 512, + justification_generation_period: 512, name: Some(name), observer_enabled: false, keystore, @@ -436,6 +461,7 @@ pub fn new_full(config: Configuration) -> Result { prometheus_registry, shared_voter_state, telemetry: telemetry.as_ref().map(|x| x.handle()), + offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), }; // the GRANDPA voter task is considered infallible, i.e. diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 92dabc9407ce7..daaa9815a8afc 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -65,7 +65,8 @@ pub use frame_support::{ dispatch::DispatchClass, parameter_types, traits::{ - ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, + ConstBool, ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, Imbalance, + KeyOwnerProofSystem, }, weights::{ constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, @@ -111,8 +112,8 @@ pub type AccountIndex = u32; /// Balance of an account. pub type Balance = bp_millau::Balance; -/// Index of a transaction in the chain. -pub type Index = bp_millau::Index; +/// Nonce of a transaction in the chain. +pub type Nonce = bp_millau::Nonce; /// A hash of some data used by the chain. pub type Hash = bp_millau::Hash; @@ -184,15 +185,13 @@ impl frame_system::Config for Runtime { /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = IdentityLookup; /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The index type for blocks. - type BlockNumber = BlockNumber; + type Nonce = Nonce; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = Hashing; /// The header type. - type Header = generic::Header; + type Block = Block; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. @@ -229,6 +228,7 @@ impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type MaxAuthorities = ConstU32<10>; type DisabledValidators = (); + type AllowMultipleBlocksPerSlot = ConstBool; } impl pallet_beefy::Config for Runtime { @@ -239,6 +239,7 @@ impl pallet_beefy::Config for Runtime { type WeightInfo = (); type KeyOwnerProof = sp_core::Void; type EquivocationReportSystem = (); + type MaxNominators = ConstU32<256>; } impl pallet_grandpa::Config for Runtime { @@ -249,6 +250,7 @@ impl pallet_grandpa::Config for Runtime { type MaxSetIdSessionEntries = ConstU64<0>; type KeyOwnerProof = sp_core::Void; type EquivocationReportSystem = (); + type MaxNominators = ConstU32<256>; } /// MMR helper types. @@ -542,12 +544,8 @@ impl pallet_utility::Config for Runtime { } construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = opaque::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + pub enum Runtime { + System: frame_system::{Pallet, Call, Config, Storage, Event}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, Utility: pallet_utility, @@ -560,7 +558,7 @@ construct_runtime!( // Consensus support. Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, // BEEFY Bridges support. @@ -582,7 +580,7 @@ construct_runtime!( BridgeRialtoParachainMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config}, // Pallet for sending XCM. - XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, } ); @@ -708,8 +706,8 @@ impl_runtime_apis! { } } - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Index { + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { System::account_nonce(account) } } diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index d6b763b116c29..623c8219016fe 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -110,6 +110,7 @@ pub type Barrier = ( pub type OnMillauBlobDispatcher = xcm_builder::BridgeBlobDispatcher< crate::xcm_config::XcmRouter, crate::xcm_config::UniversalLocation, + (), >; /// XCM weigher type. @@ -141,6 +142,7 @@ impl xcm_executor::Config for XcmConfig { type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; + type Aliasers = Nothing; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -247,11 +249,12 @@ mod tests { use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; + use sp_runtime::BuildStorage; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( - frame_system::GenesisConfig::default().build_storage::().unwrap(), + frame_system::GenesisConfig::::default().build_storage().unwrap(), ) } diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs index bfce4f717c679..b42c9a6a8f5ee 100644 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ b/bin/rialto-parachain/node/src/chain_spec.rs @@ -35,7 +35,7 @@ const MILLAU_MESSAGES_PALLET_OWNER: &str = "Millau.MessagesOwner"; /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = - sc_service::GenericChainSpec; + sc_service::GenericChainSpec; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { @@ -176,18 +176,22 @@ fn testnet_genesis( initial_authorities: Vec, endowed_accounts: Vec, id: ParaId, -) -> rialto_parachain_runtime::GenesisConfig { - rialto_parachain_runtime::GenesisConfig { +) -> rialto_parachain_runtime::RuntimeGenesisConfig { + rialto_parachain_runtime::RuntimeGenesisConfig { system: rialto_parachain_runtime::SystemConfig { code: rialto_parachain_runtime::WASM_BINARY .expect("WASM binary was not build, please build it!") .to_vec(), + ..Default::default() }, balances: rialto_parachain_runtime::BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), }, sudo: rialto_parachain_runtime::SudoConfig { key: Some(root_key) }, - parachain_info: rialto_parachain_runtime::ParachainInfoConfig { parachain_id: id }, + parachain_info: rialto_parachain_runtime::ParachainInfoConfig { + parachain_id: id, + ..Default::default() + }, aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, aura_ext: Default::default(), bridge_millau_messages: BridgeMillauMessagesConfig { diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs index 77d5bd1ff948a..c8c457752d600 100644 --- a/bin/rialto-parachain/node/src/cli.rs +++ b/bin/rialto-parachain/node/src/cli.rs @@ -18,6 +18,7 @@ use crate::chain_spec; use clap::Parser; +use cumulus_client_cli::{ExportGenesisStateCommand, ExportGenesisWasmCommand}; use std::path::PathBuf; /// Sub-commands supported by the collator. @@ -57,44 +58,6 @@ pub enum Subcommand { Benchmark(frame_benchmarking_cli::BenchmarkCmd), } -/// Command for exporting the genesis state of the parachain -#[derive(Debug, Parser)] -pub struct ExportGenesisStateCommand { - /// Output file name or stdout if unspecified. - #[clap(action)] - pub output: Option, - - /// Id of the parachain this state is for. - /// - /// Default: 100 - #[clap(long, conflicts_with = "chain")] - pub parachain_id: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis state should be exported. - #[clap(long, conflicts_with = "parachain-id")] - pub chain: Option, -} - -/// Command for exporting the genesis wasm file. -#[derive(Debug, Parser)] -pub struct ExportGenesisWasmCommand { - /// Output file name or stdout if unspecified. - #[clap(action)] - pub output: Option, - - /// Write output in binary. Default is to write in hex. - #[clap(short, long)] - pub raw: bool, - - /// The name of the chain for that the genesis wasm file should be exported. - #[clap(long)] - pub chain: Option, -} - #[derive(Debug, Parser)] #[clap( propagate_version = true, diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs index dce14df801b0f..50c1857f1c9c8 100644 --- a/bin/rialto-parachain/node/src/command.rs +++ b/bin/rialto-parachain/node/src/command.rs @@ -17,22 +17,18 @@ use crate::{ chain_spec, cli::{Cli, RelayChainCli, Subcommand}, - service::{new_partial, ParachainRuntimeExecutor}, + service::new_partial, }; -use codec::Encode; -use cumulus_client_cli::generate_genesis_block; use cumulus_primitives_core::ParaId; use frame_benchmarking_cli::BenchmarkCmd; use log::info; use rialto_parachain_runtime::{Block, RuntimeApi}; use sc_cli::{ ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, - NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, + NetworkParams, Result, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; -use sp_core::hexdisplay::HexDisplay; -use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; -use std::{io::Write, net::SocketAddr}; +use std::net::SocketAddr; fn load_spec( id: &str, @@ -79,10 +75,6 @@ impl SubstrateCli for Cli { fn load_spec(&self, id: &str) -> std::result::Result, String> { load_spec(id, self.parachain_id.unwrap_or(2000).into()) } - - fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - &rialto_parachain_runtime::VERSION - } } impl SubstrateCli for RelayChainCli { @@ -117,19 +109,6 @@ impl SubstrateCli for RelayChainCli { fn load_spec(&self, id: &str) -> std::result::Result, String> { polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id) } - - fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion { - polkadot_cli::Cli::native_runtime_version(chain_spec) - } -} - -fn extract_genesis_wasm(chain_spec: &dyn sc_service::ChainSpec) -> Result> { - let mut storage = chain_spec.build_storage()?; - - storage - .top - .remove(sp_core::storage::well_known_keys::CODE) - .ok_or_else(|| "Could not find wasm file in genesis state!".into()) } macro_rules! construct_async_run { @@ -207,59 +186,30 @@ pub fn run() -> Result<()> { None ))) }, - Some(Subcommand::ExportGenesisState(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let spec = load_spec( - ¶ms.chain.clone().unwrap_or_default(), - params.parachain_id.expect("Missing ParaId").into(), - )?; - let state_version = Cli::native_runtime_version(&spec).state_version(); - let block: Block = generate_genesis_block(&*spec, state_version)?; - let raw_header = block.header().encode(); - let output_buf = if params.raw { - raw_header - } else { - format!("0x{:?}", HexDisplay::from(&block.header().encode())).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } + Some(Subcommand::ExportGenesisState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| { + let partials = new_partial::( + &config, + crate::service::parachain_build_import_queue, + )?; - Ok(()) + cmd.run(&*config.chain_spec, &*partials.client) + }) }, - Some(Subcommand::ExportGenesisWasm(params)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_profiling(sc_tracing::TracingReceiver::Log, ""); - let _ = builder.init(); - - let raw_wasm_blob = - extract_genesis_wasm(&*cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?; - let output_buf = if params.raw { - raw_wasm_blob - } else { - format!("0x{:?}", HexDisplay::from(&raw_wasm_blob)).into_bytes() - }; - - if let Some(output) = ¶ms.output { - std::fs::write(output, output_buf)?; - } else { - std::io::stdout().write_all(&output_buf)?; - } - - Ok(()) + Some(Subcommand::ExportGenesisWasm(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; + cmd.run(&*spec) + }) }, Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -285,15 +235,6 @@ pub fn run() -> Result<()> { let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); - let parachain_account = - AccountIdConversion::::into_account_truncating(&id); - - let state_version = - RelayChainCli::native_runtime_version(&config.chain_spec).state_version(); - let block: Block = generate_genesis_block(&*config.chain_spec, state_version) - .map_err(|e| format!("{e:?}"))?; - let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); - let polkadot_config = SubstrateCli::create_configuration( &polkadot_cli, &polkadot_cli, @@ -302,8 +243,6 @@ pub fn run() -> Result<()> { .map_err(|err| format!("Relay chain argument error: {err}"))?; info!("Parachain id: {:?}", id); - info!("Parachain Account: {}", parachain_account); - info!("Parachain genesis state: {}", genesis_state); info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); crate::service::start_node(config, polkadot_config, collator_options, id) diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index f21a2f65e795b..e244f6018f641 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -33,7 +33,7 @@ use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, Slo use cumulus_client_consensus_common::{ ParachainBlockImport as TParachainBlockImport, ParachainConsensus, }; -use cumulus_client_network::BlockAnnounceValidator; +use cumulus_client_network::RequireSecondedInBlockAnnounce; use cumulus_client_service::{ prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, }; @@ -271,7 +271,8 @@ where let client = params.client.clone(); let backend = params.backend.clone(); - let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id); + let block_announce_validator = + RequireSecondedInBlockAnnounce::new(relay_chain_interface.clone(), id); let force_authoring = parachain_config.force_authoring; let validator = parachain_config.role.is_authority(); diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 498cdf8a58fde..18c915819d5fb 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -50,7 +50,7 @@ pub use frame_support::{ construct_runtime, dispatch::DispatchClass, match_types, parameter_types, - traits::{ConstU32, Everything, IsInVec, Nothing, Randomness}, + traits::{ConstBool, ConstU32, Everything, IsInVec, Nothing, Randomness}, weights::{ constants::{ BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, @@ -70,7 +70,7 @@ pub use sp_runtime::{MultiAddress, Perbill, Permill}; pub use bp_rialto_parachain::{ AccountId, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher as Hashing, Header, - Index, Signature, MAXIMUM_BLOCK_WEIGHT, + Nonce, Signature, MAXIMUM_BLOCK_WEIGHT, }; pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; @@ -231,15 +231,13 @@ impl frame_system::Config for Runtime { /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The index type for blocks. - type BlockNumber = BlockNumber; + type Nonce = Nonce; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = Hashing; /// The header type. - type Header = generic::Header; + type Block = Block; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. @@ -431,7 +429,7 @@ pub type Barrier = TakeWeightCredit; /// Dispatches received XCM messages from other chain. pub type OnRialtoParachainBlobDispatcher = - xcm_builder::BridgeBlobDispatcher; + xcm_builder::BridgeBlobDispatcher; /// XCM weigher type. pub type XcmWeigher = FixedWeightBounds; @@ -461,6 +459,7 @@ impl Config for XcmConfig { type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; + type Aliasers = Nothing; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -529,6 +528,7 @@ impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); type MaxAuthorities = MaxAuthorities; + type AllowMultipleBlocksPerSlot = ConstBool; } impl pallet_bridge_relayers::Config for Runtime { @@ -592,23 +592,19 @@ impl pallet_bridge_messages::Config for Runtime { // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = generic::Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Storage, Config, Event}, + pub enum Runtime { + System: frame_system::{Pallet, Call, Storage, Config, Event}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 20, - ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21, + ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 30, Aura: pallet_aura::{Pallet, Config}, - AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, + AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 50, @@ -719,8 +715,8 @@ impl_runtime_apis! { } } - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Index { + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { System::account_nonce(account) } } @@ -866,7 +862,7 @@ mod tests { fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( - frame_system::GenesisConfig::default().build_storage::().unwrap(), + frame_system::GenesisConfig::::default().build_storage().unwrap(), ) } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index c5364019a0e4c..d32dc55296943 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,11 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use polkadot_primitives::v4::{AssignmentId, ValidatorId}; +use polkadot_primitives::v5::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, - ConfigurationConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, - SudoConfig, SystemConfig, WASM_BINARY, + ConfigurationConfig, GrandpaConfig, RuntimeGenesisConfig, SessionConfig, SessionKeys, + Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -41,7 +41,7 @@ const MILLAU_MESSAGES_PALLET_OWNER: &str = "Millau.MessagesOwner"; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = - sc_service::GenericChainSpec; + sc_service::GenericChainSpec; /// The chain specification option. This is expected to come in from the CLI and /// is little more than one of a number of alternatives which can easily be converted @@ -200,10 +200,11 @@ fn testnet_genesis( root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, -) -> GenesisConfig { - GenesisConfig { +) -> RuntimeGenesisConfig { + RuntimeGenesisConfig { system: SystemConfig { code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(), + ..Default::default() }, balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), @@ -211,9 +212,10 @@ fn testnet_genesis( babe: BabeConfig { authorities: Vec::new(), epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), + ..Default::default() }, beefy: BeefyConfig::default(), - grandpa: GrandpaConfig { authorities: Vec::new() }, + grandpa: GrandpaConfig { authorities: Vec::new(), ..Default::default() }, sudo: SudoConfig { key: Some(root_key) }, session: SessionConfig { keys: initial_authorities @@ -243,8 +245,8 @@ fn testnet_genesis( validation_upgrade_cooldown: 2u32, validation_upgrade_delay: 2, code_retention_period: 1200, - max_code_size: polkadot_primitives::v4::MAX_CODE_SIZE, - max_pov_size: polkadot_primitives::v4::MAX_POV_SIZE, + max_code_size: polkadot_primitives::v5::MAX_CODE_SIZE, + max_pov_size: polkadot_primitives::v5::MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, chain_availability_period: 4, diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index a21b3a88d2c23..156d365c20243 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -17,7 +17,7 @@ use crate::cli::{Cli, Subcommand}; use frame_benchmarking_cli::BenchmarkCmd; use rialto_runtime::{Block, RuntimeApi}; -use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; +use sc_cli::SubstrateCli; impl SubstrateCli for Cli { fn impl_name() -> String { @@ -48,10 +48,6 @@ impl SubstrateCli for Cli { "rialto-bridge-node".into() } - fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - &rialto_runtime::VERSION - } - fn load_spec(&self, id: &str) -> Result, String> { Ok(Box::new( match id { @@ -92,7 +88,7 @@ pub fn run() -> sc_cli::Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| cmd.run::(config)) } else { println!( "Benchmarking wasn't enabled when building the node. \ @@ -200,7 +196,7 @@ pub fn run() -> sc_cli::Result<()> { let program_path = None; let overseer_enable_anyways = false; - polkadot_service::new_full::( + polkadot_service::new_full( config, is_collator, grandpa_pause, diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 9240314c54430..1d93d24951e91 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -94,8 +94,8 @@ pub type AccountIndex = u32; /// Balance of an account. pub type Balance = bp_rialto::Balance; -/// Index of a transaction in the chain. -pub type Index = bp_rialto::Index; +/// Nonce of a transaction in the chain. +pub type Nonce = bp_rialto::Nonce; /// A hash of some data used by the chain. pub type Hash = bp_rialto::Hash; @@ -170,15 +170,13 @@ impl frame_system::Config for Runtime { /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The index type for blocks. - type BlockNumber = BlockNumber; + type Nonce = Nonce; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = Hashing; /// The header type. - type Header = generic::Header; + type Block = Block; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. @@ -238,6 +236,8 @@ impl pallet_babe::Config for Runtime { // equivocation related configuration - we don't expect any equivocations in our testnets type KeyOwnerProof = sp_core::Void; type EquivocationReportSystem = (); + + type MaxNominators = ConstU32<256>; } impl pallet_beefy::Config for Runtime { @@ -248,6 +248,7 @@ impl pallet_beefy::Config for Runtime { type WeightInfo = (); type KeyOwnerProof = sp_core::Void; type EquivocationReportSystem = (); + type MaxNominators = ConstU32<256>; } impl pallet_grandpa::Config for Runtime { @@ -258,6 +259,7 @@ impl pallet_grandpa::Config for Runtime { type MaxSetIdSessionEntries = ConstU64<0>; type KeyOwnerProof = sp_core::Void; type EquivocationReportSystem = (); + type MaxNominators = ConstU32<256>; } impl pallet_mmr::Config for Runtime { @@ -454,25 +456,21 @@ impl pallet_bridge_beefy::Config for Runtime { } construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = opaque::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + pub enum Runtime { + System: frame_system::{Pallet, Call, Config, Storage, Event}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, // Must be before session. - Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned}, + Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned}, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, // Consensus support. - AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, + AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, // BEEFY Bridges support. @@ -495,10 +493,10 @@ construct_runtime!( Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent}, Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage}, - Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, + Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, Dmp: polkadot_runtime_parachains::dmp::{Pallet, Storage}, - Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, + Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, ParaSessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, ParasDisputes: polkadot_runtime_parachains::disputes::{Pallet, Call, Storage, Event}, @@ -511,7 +509,7 @@ construct_runtime!( ParasSudoWrapper: polkadot_runtime_common::paras_sudo_wrapper::{Pallet, Call}, // Pallet for sending XCM. - XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, } ); @@ -612,8 +610,8 @@ impl_runtime_apis! { } } - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Index { + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { System::account_nonce(account) } } @@ -764,55 +762,55 @@ impl_runtime_apis! { } impl polkadot_primitives::runtime_api::ParachainHost for Runtime { - fn validators() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v4::validators::() + fn validators() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v5::validators::() } - fn validator_groups() -> (Vec>, polkadot_primitives::v4::GroupRotationInfo) { - polkadot_runtime_parachains::runtime_api_impl::v4::validator_groups::() + fn validator_groups() -> (Vec>, polkadot_primitives::v5::GroupRotationInfo) { + polkadot_runtime_parachains::runtime_api_impl::v5::validator_groups::() } - fn availability_cores() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v4::availability_cores::() + fn availability_cores() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v5::availability_cores::() } - fn persisted_validation_data(para_id: polkadot_primitives::v4::Id, assumption: polkadot_primitives::v4::OccupiedCoreAssumption) - -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v4::persisted_validation_data::(para_id, assumption) + fn persisted_validation_data(para_id: polkadot_primitives::v5::Id, assumption: polkadot_primitives::v5::OccupiedCoreAssumption) + -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v5::persisted_validation_data::(para_id, assumption) } fn assumed_validation_data( - para_id: polkadot_primitives::v4::Id, + para_id: polkadot_primitives::v5::Id, expected_persisted_validation_data_hash: Hash, - ) -> Option<(polkadot_primitives::v4::PersistedValidationData, polkadot_primitives::v4::ValidationCodeHash)> { - polkadot_runtime_parachains::runtime_api_impl::v4::assumed_validation_data::( + ) -> Option<(polkadot_primitives::v5::PersistedValidationData, polkadot_primitives::v5::ValidationCodeHash)> { + polkadot_runtime_parachains::runtime_api_impl::v5::assumed_validation_data::( para_id, expected_persisted_validation_data_hash, ) } fn check_validation_outputs( - para_id: polkadot_primitives::v4::Id, - outputs: polkadot_primitives::v4::CandidateCommitments, + para_id: polkadot_primitives::v5::Id, + outputs: polkadot_primitives::v5::CandidateCommitments, ) -> bool { - polkadot_runtime_parachains::runtime_api_impl::v4::check_validation_outputs::(para_id, outputs) + polkadot_runtime_parachains::runtime_api_impl::v5::check_validation_outputs::(para_id, outputs) } - fn session_index_for_child() -> polkadot_primitives::v4::SessionIndex { - polkadot_runtime_parachains::runtime_api_impl::v4::session_index_for_child::() + fn session_index_for_child() -> polkadot_primitives::v5::SessionIndex { + polkadot_runtime_parachains::runtime_api_impl::v5::session_index_for_child::() } - fn validation_code(para_id: polkadot_primitives::v4::Id, assumption: polkadot_primitives::v4::OccupiedCoreAssumption) - -> Option { - polkadot_runtime_parachains::runtime_api_impl::v4::validation_code::(para_id, assumption) + fn validation_code(para_id: polkadot_primitives::v5::Id, assumption: polkadot_primitives::v5::OccupiedCoreAssumption) + -> Option { + polkadot_runtime_parachains::runtime_api_impl::v5::validation_code::(para_id, assumption) } - fn candidate_pending_availability(para_id: polkadot_primitives::v4::Id) -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v4::candidate_pending_availability::(para_id) + fn candidate_pending_availability(para_id: polkadot_primitives::v5::Id) -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v5::candidate_pending_availability::(para_id) } - fn candidate_events() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v4::candidate_events::(|ev| { + fn candidate_events() -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v5::candidate_events::(|ev| { match ev { RuntimeEvent::Inclusion(ev) => { Some(ev) @@ -822,54 +820,75 @@ impl_runtime_apis! { }) } - fn session_info(index: polkadot_primitives::v4::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v4::session_info::(index) + fn session_info(index: polkadot_primitives::v5::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v5::session_info::(index) } - fn dmq_contents(recipient: polkadot_primitives::v4::Id) -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v4::dmq_contents::(recipient) + fn dmq_contents(recipient: polkadot_primitives::v5::Id) -> Vec> { + polkadot_runtime_parachains::runtime_api_impl::v5::dmq_contents::(recipient) } fn inbound_hrmp_channels_contents( - recipient: polkadot_primitives::v4::Id - ) -> BTreeMap>> { - polkadot_runtime_parachains::runtime_api_impl::v4::inbound_hrmp_channels_contents::(recipient) + recipient: polkadot_primitives::v5::Id + ) -> BTreeMap>> { + polkadot_runtime_parachains::runtime_api_impl::v5::inbound_hrmp_channels_contents::(recipient) } - fn validation_code_by_hash(hash: polkadot_primitives::v4::ValidationCodeHash) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v4::validation_code_by_hash::(hash) + fn validation_code_by_hash(hash: polkadot_primitives::v5::ValidationCodeHash) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v5::validation_code_by_hash::(hash) } - fn on_chain_votes() -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v4::on_chain_votes::() + fn on_chain_votes() -> Option> { + polkadot_runtime_parachains::runtime_api_impl::v5::on_chain_votes::() } - fn submit_pvf_check_statement(stmt: polkadot_primitives::v4::PvfCheckStatement, signature: polkadot_primitives::v4::ValidatorSignature) { - polkadot_runtime_parachains::runtime_api_impl::v4::submit_pvf_check_statement::(stmt, signature) + fn submit_pvf_check_statement(stmt: polkadot_primitives::v5::PvfCheckStatement, signature: polkadot_primitives::v5::ValidatorSignature) { + polkadot_runtime_parachains::runtime_api_impl::v5::submit_pvf_check_statement::(stmt, signature) } - fn pvfs_require_precheck() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v4::pvfs_require_precheck::() + fn pvfs_require_precheck() -> Vec { + polkadot_runtime_parachains::runtime_api_impl::v5::pvfs_require_precheck::() } - fn validation_code_hash(para_id: polkadot_primitives::v4::Id, assumption: polkadot_primitives::v4::OccupiedCoreAssumption) - -> Option + fn validation_code_hash(para_id: polkadot_primitives::v5::Id, assumption: polkadot_primitives::v5::OccupiedCoreAssumption) + -> Option { - polkadot_runtime_parachains::runtime_api_impl::v4::validation_code_hash::(para_id, assumption) + polkadot_runtime_parachains::runtime_api_impl::v5::validation_code_hash::(para_id, assumption) + } + + fn disputes() -> Vec<(polkadot_primitives::v5::SessionIndex, polkadot_primitives::v5::CandidateHash, polkadot_primitives::v5::DisputeState)> { + polkadot_runtime_parachains::runtime_api_impl::v5::get_session_disputes::() + } + + fn session_executor_params(session_index: polkadot_primitives::v5::SessionIndex) -> Option { + polkadot_runtime_parachains::runtime_api_impl::v5::session_executor_params::(session_index) } - fn disputes() -> Vec<(polkadot_primitives::v4::SessionIndex, polkadot_primitives::v4::CandidateHash, polkadot_primitives::v4::DisputeState)> { - polkadot_runtime_parachains::runtime_api_impl::v4::get_session_disputes::() + fn unapplied_slashes( + ) -> Vec<(polkadot_primitives::v5::SessionIndex, polkadot_primitives::v5::CandidateHash, polkadot_primitives::v5::slashing::PendingSlashes)> { + polkadot_runtime_parachains::runtime_api_impl::v5::unapplied_slashes::() } - fn session_executor_params(session_index: polkadot_primitives::v4::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v4::session_executor_params::(session_index) + fn key_ownership_proof( + _validator_id: polkadot_primitives::v5::ValidatorId, + ) -> Option { + unimplemented!("Not used at Rialto") + } + + fn submit_report_dispute_lost( + dispute_proof: polkadot_primitives::v5::slashing::DisputeProof, + key_ownership_proof: polkadot_primitives::v5::slashing::OpaqueKeyOwnershipProof, + ) -> Option<()> { + polkadot_runtime_parachains::runtime_api_impl::v5::submit_unsigned_slashing_report::( + dispute_proof, + key_ownership_proof, + ) } } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { fn authorities() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v4::relevant_authority_ids::() + polkadot_runtime_parachains::runtime_api_impl::v5::relevant_authority_ids::() } } diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 587cb4d93404c..63d7dc6d1456a 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -27,7 +27,7 @@ use frame_support::{ weights::{Weight, WeightMeter}, }; use frame_system::EnsureRoot; -use polkadot_primitives::v4::{ValidatorId, ValidatorIndex}; +use polkadot_primitives::v5::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ configuration as parachains_configuration, disputes as parachains_disputes, @@ -68,6 +68,7 @@ impl parachains_dmp::Config for Runtime {} impl parachains_hrmp::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; + type ChannelManager = EnsureRoot; type Currency = Balances; type WeightInfo = parachains_hrmp::TestWeightInfo; } @@ -225,6 +226,7 @@ impl pallet_message_queue::Config for Runtime { pallet_message_queue::mock_helpers::NoopMessageProcessor; type QueueChangeHandler = crate::Inclusion; type WeightInfo = (); + type QueuePausedQuery = (); } // required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs index cee246ad67ad1..caac064f81534 100644 --- a/bin/rialto/runtime/src/xcm_config.rs +++ b/bin/rialto/runtime/src/xcm_config.rs @@ -106,6 +106,7 @@ pub type Barrier = ( pub type OnRialtoBlobDispatcher = xcm_builder::BridgeBlobDispatcher< crate::xcm_config::XcmRouter, crate::xcm_config::UniversalLocation, + (), >; /// Incoming XCM weigher type. @@ -137,6 +138,7 @@ impl xcm_executor::Config for XcmConfig { type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; type SafeCallFilter = Everything; + type Aliasers = Nothing; } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -202,11 +204,12 @@ mod tests { use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; + use sp_runtime::BuildStorage; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { sp_io::TestExternalities::new( - frame_system::GenesisConfig::default().build_storage::().unwrap(), + frame_system::GenesisConfig::::default().build_storage().unwrap(), ) } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index aa698b0b95e9d..a0af3b981f307 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -30,7 +30,7 @@ use pallet_bridge_messages::WeightInfoExt as _; use sp_runtime::traits::SignedExtension; /// Macro that ensures that the runtime configuration and chain primitives crate are sharing -/// the same types (index, block number, hash, hasher, account id and header). +/// the same types (nonce, block number, hash, hasher, account id and header). #[macro_export] macro_rules! assert_chain_types( ( runtime: $r:path, this_chain: $this:path ) => { @@ -38,15 +38,15 @@ macro_rules! assert_chain_types( // if one of asserts fail, then either bridge isn't configured properly (or alternatively - non-standard // configuration is used), or something has broke existing configuration (meaning that all bridged chains // and relays will stop functioning) - use frame_system::Config as SystemConfig; + use frame_system::{Config as SystemConfig, pallet_prelude::{BlockNumberFor, HeaderFor}}; use static_assertions::assert_type_eq_all; - assert_type_eq_all!(<$r as SystemConfig>::Index, bp_runtime::IndexOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::BlockNumber, bp_runtime::BlockNumberOf<$this>); + assert_type_eq_all!(<$r as SystemConfig>::Nonce, bp_runtime::NonceOf<$this>); + assert_type_eq_all!(BlockNumberFor<$r>, bp_runtime::BlockNumberOf<$this>); assert_type_eq_all!(<$r as SystemConfig>::Hash, bp_runtime::HashOf<$this>); assert_type_eq_all!(<$r as SystemConfig>::Hashing, bp_runtime::HasherOf<$this>); assert_type_eq_all!(<$r as SystemConfig>::AccountId, bp_runtime::AccountIdOf<$this>); - assert_type_eq_all!(<$r as SystemConfig>::Header, bp_runtime::HeaderOf<$this>); + assert_type_eq_all!(HeaderFor<$r>, bp_runtime::HeaderOf<$this>); } } ); diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 4542ad39b6241..6b5edabc886b8 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -66,9 +66,7 @@ pub type ThisChainCallOrigin = RuntimeOrigin; /// Header of `ThisChain`. pub type ThisChainHeader = sp_runtime::generic::Header; /// Block of `ThisChain`. -pub type ThisChainBlock = frame_system::mocking::MockBlock; -/// Unchecked extrinsic of `ThisChain`. -pub type ThisChainUncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +pub type ThisChainBlock = frame_system::mocking::MockBlockU32; /// Account identifier at the `BridgedChain`. pub type BridgedChainAccountId = u128; @@ -108,12 +106,9 @@ pub const BRIDGED_CHAIN_MAX_EXTRINSIC_WEIGHT: usize = 2048; pub const BRIDGED_CHAIN_MAX_EXTRINSIC_SIZE: u32 = 1024; frame_support::construct_runtime! { - pub enum TestRuntime where - Block = ThisChainBlock, - NodeBlock = ThisChainBlock, - UncheckedExtrinsic = ThisChainUncheckedExtrinsic, + pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, Utility: pallet_utility, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, @@ -148,14 +143,13 @@ parameter_types! { impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = ThisChainBlockNumber; type Hash = ThisChainHash; type Hashing = ThisChainHasher; type AccountId = ThisChainAccountId; type Lookup = IdentityLookup; - type Header = ThisChainHeader; + type Block = ThisChainBlock; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU32<250>; type Version = (); @@ -324,7 +318,7 @@ impl Chain for ThisUnderlyingChain { type Header = ThisChainHeader; type AccountId = ThisChainAccountId; type Balance = ThisChainBalance; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::MultiSignature; fn max_extrinsic_size() -> u32 { @@ -364,7 +358,7 @@ impl Chain for BridgedUnderlyingChain { type Header = BridgedChainHeader; type AccountId = BridgedChainAccountId; type Balance = BridgedChainBalance; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::MultiSignature; fn max_extrinsic_size() -> u32 { @@ -390,7 +384,7 @@ impl Chain for BridgedUnderlyingParachain { type Header = BridgedChainHeader; type AccountId = BridgedChainAccountId; type Balance = BridgedChainBalance; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::MultiSignature; fn max_extrinsic_size() -> u32 { diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index f22d8e488a2b2..4bbe48ca0c6aa 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -130,7 +130,7 @@ pub mod pallet { #[pallet::hooks] impl, I: 'static> Hooks> for Pallet { - fn on_initialize(_n: T::BlockNumber) -> frame_support::weights::Weight { + fn on_initialize(_n: BlockNumberFor) -> frame_support::weights::Weight { >::mutate(|count| *count = count.saturating_sub(1)); Weight::from_parts(0, 0) @@ -337,7 +337,7 @@ pub mod pallet { } #[pallet::genesis_build] - impl, I: 'static> GenesisBuild for GenesisConfig { + impl, I: 'static> BuildGenesisConfig for GenesisConfig { fn build(&self) { if let Some(ref owner) = self.owner { >::put(owner); diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 1ffccc5dfbc5c..3eeabab4be29f 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -57,16 +57,12 @@ pub type TestBridgedRawMmrLeaf = sp_consensus_beefy::mmr::MmrLeaf< >; pub type TestBridgedMmrNode = MmrDataOrHash; -type TestBlock = frame_system::mocking::MockBlock; -type TestUncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; construct_runtime! { - pub enum TestRuntime where - Block = TestBlock, - NodeBlock = TestBlock, - UncheckedExtrinsic = TestUncheckedExtrinsic, + pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, Beefy: beefy::{Pallet}, } } @@ -79,14 +75,13 @@ parameter_types! { impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = u64; + type Block = Block; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = TestAccountId; type Lookup = IdentityLookup; - type Header = Header; type RuntimeEvent = (); type BlockHashCount = ConstU64<250>; type Version = (); @@ -117,11 +112,11 @@ impl Chain for TestBridgedChain { type BlockNumber = TestBridgedBlockNumber; type Hash = H256; type Hasher = BlakeTwo256; - type Header = ::Header; + type Header = sp_runtime::testing::Header; type AccountId = TestAccountId; type Balance = u64; - type Index = u64; + type Nonce = u64; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index b57aebb1ac1e7..c83e88b7b5621 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -179,7 +179,9 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( /// Returns maximal expected size of `submit_finality_proof` call arguments. fn max_expected_call_size, I: 'static>(required_precommits: u32) -> u32 { let max_expected_justification_size = - GrandpaJustification::max_reasonable_size::(required_precommits); + GrandpaJustification::>::max_reasonable_size::( + required_precommits, + ); // call arguments are header and justification T::BridgedChain::MAX_HEADER_SIZE.saturating_add(max_expected_justification_size) diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index b789aedef2c8f..eb49849ac881f 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -379,7 +379,7 @@ pub mod pallet { } #[pallet::genesis_build] - impl, I: 'static> GenesisBuild for GenesisConfig { + impl, I: 'static> BuildGenesisConfig for GenesisConfig { fn build(&self) { if let Some(ref owner) = self.owner { >::put(owner); diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 0ebbc0bccbb7b..bd305dfef9dc0 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -26,29 +26,25 @@ use frame_support::{ }; use sp_core::sr25519::Signature; use sp_runtime::{ - testing::{Header, H256}, + testing::H256, traits::{BlakeTwo256, IdentityLookup}, Perbill, }; pub type AccountId = u64; -pub type TestHeader = crate::BridgedHeader; -pub type TestNumber = crate::BridgedBlockNumber; +pub type TestHeader = sp_runtime::testing::Header; +pub type TestNumber = u64; type Block = frame_system::mocking::MockBlock; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; pub const MAX_BRIDGED_AUTHORITIES: u32 = 5; use crate as grandpa; construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, + pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, Grandpa: grandpa::{Pallet, Call, Event}, } } @@ -61,14 +57,13 @@ parameter_types! { impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; - type Header = Header; + type Block = Block; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<250>; type Version = (); @@ -105,14 +100,14 @@ impl grandpa::Config for TestRuntime { pub struct TestBridgedChain; impl Chain for TestBridgedChain { - type BlockNumber = ::BlockNumber; + type BlockNumber = TestNumber; type Hash = ::Hash; type Hasher = ::Hashing; - type Header = ::Header; + type Header = TestHeader; type AccountId = AccountId; type Balance = u64; - type Index = u64; + type Nonce = u64; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 51e6857d7778c..3bfd5bc7e98f7 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -188,9 +188,9 @@ pub mod pallet { #[pallet::hooks] impl, I: 'static> Hooks> for Pallet where - u32: TryFrom<::BlockNumber>, + u32: TryFrom>, { - fn on_idle(_block: T::BlockNumber, remaining_weight: Weight) -> Weight { + fn on_idle(_block: BlockNumberFor, remaining_weight: Weight) -> Weight { // we'll need at least to read outbound lane state, kill a message and update lane state let db_weight = T::DbWeight::get(); if !remaining_weight.all_gte(db_weight.reads_writes(1, 2)) { @@ -597,7 +597,7 @@ pub mod pallet { } #[pallet::genesis_build] - impl, I: 'static> GenesisBuild for GenesisConfig { + impl, I: 'static> BuildGenesisConfig for GenesisConfig { fn build(&self) { PalletOperatingMode::::put(self.operating_mode); if let Some(ref owner) = self.owner { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 8716c5bc3ac7f..62bc76c5e010b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -39,9 +39,8 @@ use frame_support::{ use scale_info::TypeInfo; use sp_core::H256; use sp_runtime::{ - testing::Header as SubstrateHeader, traits::{BlakeTwo256, ConstU32, IdentityLookup}, - Perbill, + BuildStorage, Perbill, }; use std::{ collections::{BTreeMap, VecDeque}, @@ -71,17 +70,13 @@ pub type TestRelayer = u64; pub type TestDispatchLevelResult = (); type Block = frame_system::mocking::MockBlock; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; use crate as pallet_bridge_messages; frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, + pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Call, Event}, Messages: pallet_bridge_messages::{Pallet, Call, Event}, } @@ -98,14 +93,13 @@ pub type DbWeight = RocksDbWeight; impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; - type Header = SubstrateHeader; + type Block = Block; type RuntimeEvent = RuntimeEvent; type BlockHashCount = ConstU64<250>; type Version = (); @@ -487,7 +481,7 @@ pub fn inbound_unrewarded_relayers_state(lane: bp_messages::LaneId) -> Unrewarde /// Return test externalities to use in tests. pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(ENDOWED_ACCOUNT, 1_000_000)] } .assimilate_storage(&mut t) .unwrap(); diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 52b436b820712..4f78a45d4b77b 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -623,7 +623,7 @@ pub mod pallet { } #[pallet::genesis_build] - impl, I: 'static> GenesisBuild for GenesisConfig { + impl, I: 'static> BuildGenesisConfig for GenesisConfig { fn build(&self) { PalletOperatingMode::::put(self.operating_mode); if let Some(ref owner) = self.owner { diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 0a61d91d7b2db..a7030f0ae0310 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -19,7 +19,7 @@ use bp_polkadot_core::parachains::ParaId; use bp_runtime::{Chain, Parachain}; use frame_support::{construct_runtime, parameter_types, traits::ConstU32, weights::Weight}; use sp_runtime::{ - testing::{Header, H256}, + testing::H256, traits::{BlakeTwo256, Header as HeaderT, IdentityLookup}, MultiSignature, Perbill, }; @@ -33,7 +33,6 @@ pub type RelayBlockHeader = sp_runtime::generic::Header; type Block = frame_system::mocking::MockBlock; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; pub const PARAS_PALLET_NAME: &str = "Paras"; pub const UNTRACKED_PARACHAIN_ID: u32 = 10; @@ -55,7 +54,7 @@ impl Chain for Parachain1 { type Header = RegularParachainHeader; type AccountId = u64; type Balance = u64; - type Index = u64; + type Nonce = u64; type Signature = MultiSignature; fn max_extrinsic_size() -> u32 { @@ -79,7 +78,7 @@ impl Chain for Parachain2 { type Header = RegularParachainHeader; type AccountId = u64; type Balance = u64; - type Index = u64; + type Nonce = u64; type Signature = MultiSignature; fn max_extrinsic_size() -> u32 { @@ -103,7 +102,7 @@ impl Chain for Parachain3 { type Header = RegularParachainHeader; type AccountId = u64; type Balance = u64; - type Index = u64; + type Nonce = u64; type Signature = MultiSignature; fn max_extrinsic_size() -> u32 { @@ -128,7 +127,7 @@ impl Chain for BigParachain { type Header = BigParachainHeader; type AccountId = u64; type Balance = u64; - type Index = u64; + type Nonce = u64; type Signature = MultiSignature; fn max_extrinsic_size() -> u32 { @@ -144,12 +143,9 @@ impl Parachain for BigParachain { } construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, + pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, Grandpa1: pallet_bridge_grandpa::::{Pallet, Event}, Grandpa2: pallet_bridge_grandpa::::{Pallet, Event}, Parachains: pallet_bridge_parachains::{Call, Pallet, Event}, @@ -165,14 +161,13 @@ parameter_types! { impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = TestNumber; + type Block = Block; type Hash = H256; type Hashing = RegularParachainHasher; type AccountId = AccountId; type Lookup = IdentityLookup; - type Header = Header; type RuntimeEvent = RuntimeEvent; type BlockHashCount = BlockHashCount; type Version = (); @@ -270,7 +265,7 @@ impl Chain for TestBridgedChain { type AccountId = AccountId; type Balance = u32; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::testing::TestSignature; fn max_extrinsic_size() -> u32 { @@ -301,7 +296,7 @@ impl Chain for OtherBridgedChain { type AccountId = AccountId; type Balance = u32; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::testing::TestSignature; fn max_extrinsic_size() -> u32 { diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index 54b888cf29dc9..a71c218443b3d 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -66,7 +66,7 @@ pub mod pallet { /// Pay rewards scheme. type PaymentProcedure: PaymentProcedure; /// Stake and slash scheme. - type StakeAndSlash: StakeAndSlash; + type StakeAndSlash: StakeAndSlash, Self::Reward>; /// Pallet call weights. type WeightInfo: WeightInfoExt; } @@ -117,7 +117,7 @@ pub mod pallet { /// Registration allows relayer to get priority boost for its message delivery transactions. #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::register())] - pub fn register(origin: OriginFor, valid_till: T::BlockNumber) -> DispatchResult { + pub fn register(origin: OriginFor, valid_till: BlockNumberFor) -> DispatchResult { let relayer = ensure_signed(origin)?; // valid till must be larger than the current block number and the lease must be larger @@ -330,10 +330,10 @@ pub mod pallet { } /// Return required registration lease. - pub(crate) fn required_registration_lease() -> T::BlockNumber { + pub(crate) fn required_registration_lease() -> BlockNumberFor { , T::Reward, >>::RequiredRegistrationLease::get() } @@ -342,7 +342,7 @@ pub mod pallet { pub(crate) fn required_stake() -> T::Reward { , T::Reward, >>::RequiredStake::get() } @@ -383,7 +383,7 @@ pub mod pallet { /// Relayer account that has been registered. relayer: T::AccountId, /// Relayer registration. - registration: Registration, + registration: Registration, T::Reward>, }, /// Relayer has been `deregistered`. Deregistered { @@ -395,7 +395,7 @@ pub mod pallet { /// Relayer account that has been `deregistered`. relayer: T::AccountId, /// Registration that was removed. - registration: Registration, + registration: Registration, T::Reward>, }, } @@ -445,7 +445,7 @@ pub mod pallet { _, Blake2_128Concat, T::AccountId, - Registration, + Registration, T::Reward>, OptionQuery, >; } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index d8c5bd9096720..b3fcb24cdd20d 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -25,8 +25,8 @@ use bp_relayers::{ use frame_support::{parameter_types, traits::fungible::Mutate, weights::RuntimeDbWeight}; use sp_core::H256; use sp_runtime::{ - testing::Header as SubstrateHeader, traits::{BlakeTwo256, ConstU32, IdentityLookup}, + BuildStorage, }; pub type AccountId = u64; @@ -43,15 +43,11 @@ pub type TestStakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< >; type Block = frame_system::mocking::MockBlock; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, + pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event}, Balances: pallet_balances::{Pallet, Event}, Relayers: pallet_bridge_relayers::{Pallet, Call, Event}, } @@ -67,14 +63,13 @@ parameter_types! { impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = BlockNumber; + type Block = Block; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; - type Header = SubstrateHeader; type RuntimeEvent = RuntimeEvent; type BlockHashCount = frame_support::traits::ConstU64<250>; type Version = (); @@ -170,7 +165,7 @@ impl PaymentProcedure for TestPaymentProcedure { /// Return test externalities to use in tests. pub fn new_test_ext() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); sp_io::TestExternalities::new(t) } diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 1c38a52b0c21e..17bbb0a479f18 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -124,11 +124,10 @@ mod tests { parameter_types, sp_io::TestExternalities, sp_runtime::{ - testing::{Header, UintAuthorityId}, + testing::UintAuthorityId, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, - Perbill, RuntimeAppPublic, + BuildStorage, Perbill, RuntimeAppPublic, }, - traits::GenesisBuild, weights::Weight, BasicExternalities, }; @@ -137,15 +136,10 @@ mod tests { type AccountId = u64; type Block = frame_system::mocking::MockBlock; - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; frame_support::construct_runtime! { - pub enum TestRuntime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, + pub enum TestRuntime { + System: frame_system::{Pallet, Call, Config, Storage, Event}, Session: pallet_session::{Pallet}, } } @@ -158,14 +152,13 @@ mod tests { impl frame_system::Config for TestRuntime { type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type Nonce = u64; type RuntimeCall = RuntimeCall; - type BlockNumber = u64; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; - type Header = Header; + type Block = Block; type RuntimeEvent = (); type BlockHashCount = frame_support::traits::ConstU64<250>; type Version = (); @@ -220,7 +213,7 @@ mod tests { } fn new_test_ext() -> TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); let keys = vec![ (1, 1, UintAuthorityId(1)), diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 7ddaa6e1eb246..70e0f0f2f4817 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } -serde = { version = "1.0", optional = true } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge Dependencies @@ -34,7 +34,7 @@ std = [ "pallet-beefy-mmr/std", "pallet-mmr/std", "scale-info/std", - "serde", + "serde/std", "sp-consensus-beefy/std", "sp-runtime/std", "sp-std/std" diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index de260d45eca68..1daf5a3620796 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -37,6 +37,7 @@ use bp_runtime::{BasicOperatingMode, BlockNumberOf, Chain, HashOf}; use codec::{Decode, Encode}; use frame_support::Parameter; use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; use sp_runtime::{ traits::{Convert, MaybeSerializeDeserialize}, RuntimeAppPublic, RuntimeDebug, @@ -127,8 +128,7 @@ pub type BeefyMmrLeafOf = sp_consensus_beefy::mmr::MmrLeaf< /// /// Provides the initial context that the bridge needs in order to know /// where to start the sync process from. -#[derive(Encode, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[derive(Encode, Decode, RuntimeDebug, PartialEq, Clone, TypeInfo, Serialize, Deserialize)] pub struct InitializationData { /// Pallet operating mode. pub operating_mode: BasicOperatingMode, diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index b174cd700ed45..525b2e62ceab0 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -18,7 +18,7 @@ pub use bp_polkadot_core::{ AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, - Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, + Hashing, Header, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, }; @@ -53,7 +53,7 @@ pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// This is a copy-paste from the cumulus repo's `parachains-common` crate. const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_SECOND, 0) .saturating_div(2) - .set_proof_size(polkadot_primitives::v4::MAX_POV_SIZE as u64); + .set_proof_size(polkadot_primitives::v5::MAX_POV_SIZE as u64); /// All cumulus bridge hubs assume that about 5 percent of the block weight is consumed by /// `on_initialize` handlers. This is used to limit the maximal weight of a single extrinsic. @@ -140,7 +140,7 @@ pub type SignedExtra = ( CheckTxVersion, CheckGenesis, CheckEra, - CheckNonce, + CheckNonce, CheckWeight, ChargeTransactionPayment, BridgeRejectObsoleteHeadersAndMessages, @@ -159,12 +159,12 @@ pub trait BridgeHubSignedExtension { transaction_version: u32, era: bp_runtime::TransactionEra, genesis_hash: Hash, - nonce: Index, + nonce: Nonce, tip: Balance, ) -> Self; /// Return transaction nonce. - fn nonce(&self) -> Index; + fn nonce(&self) -> Nonce; /// Return transaction tip. fn tip(&self) -> Balance; @@ -177,7 +177,7 @@ impl BridgeHubSignedExtension for SignedExtension { transaction_version: u32, era: bp_runtime::TransactionEra, genesis_hash: Hash, - nonce: Index, + nonce: Nonce, tip: Balance, ) -> Self { GenericSignedExtension::new( @@ -209,7 +209,7 @@ impl BridgeHubSignedExtension for SignedExtension { } /// Return transaction nonce. - fn nonce(&self) -> Index { + fn nonce(&self) -> Nonce { self.payload.5 .0 } diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs index 00b6c8301e4c2..7405f561fb2ea 100644 --- a/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -43,7 +43,7 @@ impl Chain for BridgeHubKusama { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs index 8bd9167b618b1..e1fc0d7bc47d9 100644 --- a/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -39,7 +39,7 @@ impl Chain for BridgeHubPolkadot { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 936e4d1beb7f8..50206c8e6b383 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -43,7 +43,7 @@ impl Chain for BridgeHubRococo { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 00704995c5ebf..7d14460c73709 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -39,7 +39,7 @@ impl Chain for BridgeHubWococo { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 5cef6ae0ee64b..229905a3d4ac5 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -35,7 +35,7 @@ impl Chain for Kusama { type AccountId = ::AccountId; type Balance = ::Balance; - type Index = ::Index; + type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index d4b59c2aa9e83..d12e76a8d04e6 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -11,10 +11,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" fixed-hash = { version = "0.8.0", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } -impl-serde = { version = "0.4.0", optional = true } +impl-serde = { version = "0.4.0", default-features = false } parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge Dependencies @@ -46,10 +46,10 @@ std = [ "frame-system/std", "hash256-std-hasher/std", "impl-codec/std", - "impl-serde", + "impl-serde/std", "parity-util-mem/std", "scale-info/std", - "serde", + "serde/std", "sp-api/std", "sp-core/std", "sp-io/std", diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index b7f67ca07e288..a752b5f7114ae 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -33,6 +33,7 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ traits::{IdentifyAccount, Verify}, @@ -41,8 +42,6 @@ use sp_runtime::{ use sp_std::prelude::*; use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; use sp_runtime::traits::Keccak256; pub use millau_hash::MillauHash; @@ -145,8 +144,8 @@ pub type AccountSigner = MultiSigner; /// Balance of an account. pub type Balance = u64; -/// Index of a transaction in the chain. -pub type Index = u32; +/// Nonce of a transaction in the chain. +pub type Nonce = u32; /// Weight-to-Fee type used by Millau. pub type WeightToFee = IdentityFee; @@ -163,7 +162,7 @@ impl Chain for Millau { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { @@ -197,8 +196,7 @@ impl ChainWithBeefy for Millau { } /// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. -#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug, TypeInfo, Serialize, Deserialize)] pub struct BlakeTwoAndKeccak256; impl sp_core::Hasher for BlakeTwoAndKeccak256 { diff --git a/primitives/chain-millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs index 11968b2f28267..8851c319dd451 100644 --- a/primitives/chain-millau/src/millau_hash.rs +++ b/primitives/chain-millau/src/millau_hash.rs @@ -27,9 +27,7 @@ fixed_hash::construct_fixed_hash! { pub struct MillauHash(64); } -#[cfg(feature = "std")] impl_serde::impl_fixed_hash_serde!(MillauHash, 64); - impl_codec::impl_fixed_hash_codec!(MillauHash, 64); impl CheckEqual for MillauHash { diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 51d9f6f0233e3..628634bb46f01 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -35,7 +35,7 @@ impl Chain for Polkadot { type AccountId = ::AccountId; type Balance = ::Balance; - type Index = ::Index; + type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index 67b1a135f34a9..cc58edba788a6 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -96,8 +96,8 @@ pub type Balance = u128; /// An instant or duration in time. pub type Moment = u64; -/// Index of a transaction in the parachain. -pub type Index = u32; +/// Nonce of a transaction in the parachain. +pub type Nonce = u32; /// Weight-to-Fee type used by Rialto parachain. pub type WeightToFee = IdentityFee; @@ -114,7 +114,7 @@ impl Chain for RialtoParachain { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 01349f131be70..d5be78516a21a 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -149,8 +149,8 @@ pub type Balance = u128; /// An instant or duration in time. pub type Moment = u64; -/// Index of a transaction in the chain. -pub type Index = u32; +/// Nonce of a transaction in the chain. +pub type Nonce = u32; /// Weight-to-Fee type used by Rialto. pub type WeightToFee = IdentityFee; @@ -167,7 +167,7 @@ impl Chain for Rialto { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 0cb0b1d41e6dc..a825c8b39787c 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -35,7 +35,7 @@ impl Chain for Rococo { type AccountId = ::AccountId; type Balance = ::Balance; - type Index = ::Index; + type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 74e8895aff906..071f3a15a42c3 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -35,7 +35,7 @@ impl Chain for Westend { type AccountId = ::AccountId; type Balance = ::Balance; - type Index = ::Index; + type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { @@ -70,7 +70,7 @@ impl Chain for Westmint { type AccountId = AccountId; type Balance = Balance; - type Index = Nonce; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 2df019496ab14..fb63613427d03 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -38,7 +38,7 @@ impl Chain for Wococo { type AccountId = ::AccountId; type Balance = ::Balance; - type Index = ::Index; + type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs index b83c697d60875..714546a42ef2d 100644 --- a/primitives/header-chain/src/justification.rs +++ b/primitives/header-chain/src/justification.rs @@ -56,7 +56,7 @@ impl GrandpaJustification { /// any precise calculations - that's just an estimation. pub fn max_reasonable_size(required_precommits: u32) -> u32 where - C: Chain

+ ChainWithGrandpa, + C: Chain + ChainWithGrandpa, { // we don't need precise results here - just estimations, so some details // are removed from computations (e.g. bytes required to encode vector length) @@ -144,10 +144,7 @@ pub fn verify_and_optimize_justification( authorities_set_id: SetId, authorities_set: &VoterSet, justification: &mut GrandpaJustification
, -) -> Result<(), Error> -where - Header::Number: finality_grandpa::BlockNumberOps, -{ +) -> Result<(), Error> { let mut optimizer = OptimizationCallbacks { extra_precommits: vec![], redundant_votes_ancestries: Default::default(), @@ -170,10 +167,7 @@ pub fn verify_justification( authorities_set_id: SetId, authorities_set: &VoterSet, justification: &GrandpaJustification
, -) -> Result<(), Error> -where - Header::Number: finality_grandpa::BlockNumberOps, -{ +) -> Result<(), Error> { verify_justification_with_callbacks( finalized_target, authorities_set_id, @@ -295,10 +289,7 @@ fn verify_justification_with_callbacks, justification: &GrandpaJustification
, callbacks: &mut C, -) -> Result<(), Error> -where - Header::Number: finality_grandpa::BlockNumberOps, -{ +) -> Result<(), Error> { // ensure that it is justification for the expected header if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { return Err(Error::InvalidJustificationTarget) diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 6b9373cf18798..5268e7d5c5faf 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -27,7 +27,6 @@ use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; use frame_support::PalletError; use scale_info::TypeInfo; -#[cfg(feature = "std")] use serde::{Deserialize, Serialize}; use sp_consensus_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; @@ -110,8 +109,9 @@ impl AuthoritySet { /// Data required for initializing the GRANDPA bridge pallet. /// /// The bridge needs to know where to start its sync from, and this provides that initial context. -#[derive(Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive( + Default, Encode, Decode, RuntimeDebug, PartialEq, Eq, Clone, TypeInfo, Serialize, Deserialize, +)] pub struct InitializationData { /// The header from which we should start syncing. pub header: Box, diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index 46652dede56ad..d5e42e214976b 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -104,8 +104,8 @@ pub fn make_default_justification(header: &TestHeader) -> GrandpaJustification::Out; -/// Account Index (a.k.a. nonce). -pub type Index = u32; - /// Hashing type. pub type Hashing = BlakeTwo256; @@ -205,7 +202,7 @@ pub type AccountId = ::AccountId; /// Address of account on Polkadot-like chains. pub type AccountAddress = MultiAddress; -/// Index of a transaction on the Polkadot-like chains. +/// Nonce of a transaction on the Polkadot-like chains. pub type Nonce = u32; /// Block type of Polkadot-like chains. @@ -236,7 +233,7 @@ impl Chain for PolkadotLike { type AccountId = AccountId; type Balance = Balance; - type Index = Index; + type Nonce = Nonce; type Signature = Signature; fn max_extrinsic_size() -> u32 { diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index c79058cea90cf..8c47662a7c13c 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -170,8 +170,8 @@ pub trait Chain: Send + Sync + 'static { + Zero + TryFrom + MaxEncodedLen; - /// Index of a transaction used by the chain. - type Index: Parameter + /// Nonce of a transaction used by the chain. + type Nonce: Parameter + Member + MaybeSerialize + Debug @@ -206,7 +206,7 @@ where type Header = ::Header; type AccountId = ::AccountId; type Balance = ::Balance; - type Index = ::Index; + type Nonce = ::Nonce; type Signature = ::Signature; fn max_extrinsic_size() -> u32 { @@ -261,8 +261,8 @@ pub type AccountIdOf = ::AccountId; /// Balance type used by the chain. pub type BalanceOf = ::Balance; -/// Transaction index type used by the chain. -pub type IndexOf = ::Index; +/// Transaction nonce type used by the chain. +pub type NonceOf = ::Nonce; /// Signature type used by the chain. pub type SignatureOf = ::Signature; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 1922a2eb16040..0bfbd1c2ee91b 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -25,13 +25,14 @@ use frame_support::{ }; use frame_system::RawOrigin; use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; use sp_core::storage::StorageKey; use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto}; use sp_std::{convert::TryFrom, fmt::Debug, ops::RangeInclusive, vec, vec::Vec}; pub use chain::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, - HasherOf, HeaderOf, IndexOf, Parachain, ParachainIdOf, SignatureOf, TransactionEraOf, + HasherOf, HeaderOf, NonceOf, Parachain, ParachainIdOf, SignatureOf, TransactionEraOf, UnderlyingChainOf, UnderlyingChainProvider, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; @@ -373,8 +374,19 @@ pub trait OperatingMode: Send + Copy + Debug + FullCodec { } /// Basic operating modes for a bridges module (Normal/Halted). -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[derive( + Encode, + Decode, + Clone, + Copy, + PartialEq, + Eq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Serialize, + Deserialize, +)] pub enum BasicOperatingMode { /// Normal mode, when all operations are allowed. Normal, diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index 9f7c8ab5ca4e3..d308582957839 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -26,8 +26,8 @@ pub struct MessageDispatchResult { /// Unspent dispatch weight. This weight that will be deducted from total delivery transaction /// weight, thus reducing the transaction cost. This shall not be zero in (at least) two cases: /// - /// 1) if message has been dispatched successfully, but post-dispatch weight is less than - /// the weight, declared by the message sender; + /// 1) if message has been dispatched successfully, but post-dispatch weight is less than the + /// weight, declared by the message sender; /// 2) if message has not been dispatched at all. pub unspent_weight: Weight, /// Fine-grained result of single message dispatch (for better diagnostic purposes) diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 320277590bcd0..539366c8dbaf5 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -103,8 +103,8 @@ impl RegisterParachain { let para_id: ParaId = relay_client .storage_value(StorageKey(para_id_key.to_vec()), None) .await? - .unwrap_or(polkadot_primitives::v4::LOWEST_PUBLIC_ID) - .max(polkadot_primitives::v4::LOWEST_PUBLIC_ID); + .unwrap_or(polkadot_primitives::v5::LOWEST_PUBLIC_ID) + .max(polkadot_primitives::v5::LOWEST_PUBLIC_ID); log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 8f76e501f6968..918643faadb69 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -61,7 +61,7 @@ pub struct SendMessage { #[async_trait] trait MessageSender: MessagesCliBridge where - Self::Source: ChainBase + ChainWithTransactions + CliChain + CliEncodeMessage, + Self::Source: ChainBase + ChainWithTransactions + CliChain + CliEncodeMessage, ::Balance: Display + From + Into, ::Call: Sync, ::SignedTransaction: Sync, diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index ce42d004bb807..d6ce47d847dd3 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -21,7 +21,7 @@ use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, IndexOf, SignParam, + ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, NonceOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -139,7 +139,7 @@ impl ChainWithTransactions for Millau { Some( UnsignedTransaction::new( tx.function.into(), - Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), ) .tip(Compact::>::decode(&mut &extra.7.encode()[..]).ok()?.into()), ) diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index f8f696068fe90..97b6c7ee802bf 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -21,7 +21,7 @@ use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, IndexOf, RelayChain, SignParam, UnderlyingChainProvider, + Error as SubstrateError, NonceOf, RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; @@ -139,7 +139,7 @@ impl ChainWithTransactions for Rialto { Some( UnsignedTransaction::new( tx.function.into(), - Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), + Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), ) .tip(Compact::>::decode(&mut &extra.7.encode()[..]).ok()?.into()), ) diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 54c9ad4f3b68c..f733a10d06b24 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -166,7 +166,7 @@ pub struct UnsignedTransaction { /// Runtime call of this transaction. pub call: EncodedOrDecodedCall, /// Transaction nonce. - pub nonce: C::Index, + pub nonce: C::Nonce, /// Tip included into transaction. pub tip: C::Balance, /// Transaction era used by the chain. @@ -175,7 +175,7 @@ pub struct UnsignedTransaction { impl UnsignedTransaction { /// Create new unsigned transaction with given call, nonce, era and zero tip. - pub fn new(call: EncodedOrDecodedCall, nonce: C::Index) -> Self { + pub fn new(call: EncodedOrDecodedCall, nonce: C::Nonce) -> Self { Self { call, nonce, era: TransactionEra::Immortal, tip: Zero::zero() } } diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 8a0875a89763e..a4001a19aa051 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -427,7 +427,7 @@ impl Client { /// Get the nonce of the given Substrate account. /// /// Note: It's the caller's responsibility to make sure `account` is a valid SS58 address. - pub async fn next_account_index(&self, account: C::AccountId) -> Result { + pub async fn next_account_index(&self, account: C::AccountId) -> Result { self.jsonrpsee_execute(move |client| async move { Ok(SubstrateFrameSystemClient::::account_next_index(&*client, account).await?) }) @@ -474,7 +474,7 @@ impl Client { pub async fn submit_signed_extrinsic( &self, signer: &AccountKeyPairOf, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Nonce) -> Result> + Send + 'static, ) -> Result @@ -515,7 +515,7 @@ impl Client { pub async fn submit_and_watch_signed_extrinsic( &self, signer: &AccountKeyPairOf, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Nonce) -> Result> + Send + 'static, ) -> Result> diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index c8d8b6f8129f9..84c2ad10cf8f6 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -50,7 +50,7 @@ pub use crate::{ }; pub use bp_runtime::{ AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain as ChainBase, HashOf, HeaderIdOf, - HeaderOf, IndexOf, Parachain as ParachainBase, SignatureOf, TransactionEra, TransactionEraOf, + HeaderOf, NonceOf, Parachain as ParachainBase, SignatureOf, TransactionEra, TransactionEraOf, UnderlyingChainProvider, }; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 94726e49187ab..35ab08c0f4151 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -154,7 +154,7 @@ impl SubstrateFinalityClient for SubstrateBeefyFinalityClient { pub(crate) trait SubstrateFrameSystem { /// Return index of next account transaction. #[method(name = "accountNextIndex")] - async fn account_next_index(&self, account_id: C::AccountId) -> RpcResult; + async fn account_next_index(&self, account_id: C::AccountId) -> RpcResult; } /// RPC methods of Substrate `pallet_transaction_payment` frame pallet, that we are using. diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 64c7590ee5250..923092b1bcb7b 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -38,7 +38,7 @@ impl bp_runtime::Chain for TestChain { type AccountId = u32; type Balance = u32; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::testing::TestSignature; fn max_extrinsic_size() -> u32 { @@ -80,7 +80,7 @@ impl bp_runtime::Chain for TestParachainBase { type AccountId = u32; type Balance = u32; - type Index = u32; + type Nonce = u32; type Signature = sp_runtime::testing::TestSignature; fn max_extrinsic_size() -> u32 { diff --git a/relays/client-substrate/src/transaction_tracker.rs b/relays/client-substrate/src/transaction_tracker.rs index 211f7faab0e19..00375768c45c2 100644 --- a/relays/client-substrate/src/transaction_tracker.rs +++ b/relays/client-substrate/src/transaction_tracker.rs @@ -54,8 +54,8 @@ impl Environment for Client { /// 2) assume that the transaction is lost and resubmit another transaction instantly; /// /// 3) wait for some time (if transaction is mortal - then until block where it dies; if it is -/// immortal - then for some time that we assume is long enough to mine it) and assume that -/// it is lost. +/// immortal - then for some time that we assume is long enough to mine it) and assume that it is +/// lost. /// /// This struct implements third option as it seems to be the most optimal. pub struct TransactionTracker { diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index 87052cf7aa47a..1b990f5dbda3e 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -46,7 +46,7 @@ pub async fn initialize< dry_run: bool, ) where F: FnOnce( - TargetChain::Index, + TargetChain::Nonce, E::InitializationData, ) -> Result, SubstrateError> + Send @@ -112,7 +112,7 @@ async fn do_initialize< > where F: FnOnce( - TargetChain::Index, + TargetChain::Nonce, E::InitializationData, ) -> Result, SubstrateError> + Send diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 33d855a026318..50972dfc49cb6 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -27,7 +27,7 @@ use pallet_balances::AccountData; use relay_substrate_client::{ metrics::{FloatStorageValue, FloatStorageValueMetric}, AccountIdOf, BalanceOf, Chain, ChainWithBalances, ChainWithMessages, Client, - Error as SubstrateError, IndexOf, + Error as SubstrateError, NonceOf, }; use relay_utils::metrics::{MetricsParams, StandaloneMetric}; use sp_core::storage::StorageData; @@ -133,7 +133,7 @@ where ) -> Result, SubstrateError> { maybe_raw_value .map(|raw_value| { - AccountInfo::, AccountData>>::decode(&mut &raw_value.0[..]) + AccountInfo::, AccountData>>::decode(&mut &raw_value.0[..]) .map_err(SubstrateError::ResponseParseFailed) .map(|account_data| { convert_to_token_balance(account_data.data.free.into(), self.token_decimals) diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/relays/lib-substrate-relay/src/on_demand/parachains.rs index 4c205770d4acb..f67c002bba7f9 100644 --- a/relays/lib-substrate-relay/src/on_demand/parachains.rs +++ b/relays/lib-substrate-relay/src/on_demand/parachains.rs @@ -318,8 +318,8 @@ async fn background_task( // // 7) on-demand parachains relay sets `ParachainsSource::maximal_header_number` to the // `PH'.number()`. - // 8) parachains finality relay sees that the parachain head has been - // updated and relays `PH'` to the target chain. + // 8) parachains finality relay sees that the parachain head has been updated and relays + // `PH'` to the target chain. // select headers to relay let relay_data = read_relay_data( diff --git a/relays/messages/src/message_race_strategy.rs b/relays/messages/src/message_race_strategy.rs index 5c8f9a162b4a2..93d178e55b04f 100644 --- a/relays/messages/src/message_race_strategy.rs +++ b/relays/messages/src/message_race_strategy.rs @@ -14,8 +14,8 @@ //! Basic delivery strategy. The strategy selects nonces if: //! //! 1) there are more nonces on the source side than on the target side; -//! 2) new nonces may be proved to target node (i.e. they have appeared at the -//! block, which is known to the target node). +//! 2) new nonces may be proved to target node (i.e. they have appeared at the block, which is known +//! to the target node). use crate::message_race_loop::{ NoncesRange, RaceState, RaceStrategy, SourceClientNonces, TargetClientNonces, From ecc6c4ebc9f7eecfd97af12e2af0dccaf217cc9e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 20 Jul 2023 14:23:36 +0300 Subject: [PATCH 1084/1210] More backports from Cumulus subtree to polkadot-staging (#2283) * more backports from Cumulus subtree * spelling * fmt * trigger CI * Revert "trigger CI" This reverts commit b009d732aa26d006a7f2b48878ee864c338c49d5. * Revert "Revert "trigger CI"" This reverts commit 715606a75948124962b14dbb260cf3aed01bc665. * Revert "Revert "Revert "trigger CI""" This reverts commit dc0d2233da86fd12a77216008e59bd38fcbb2fac. --- bin/millau/node/src/chain_spec.rs | 4 ++-- bin/millau/runtime/src/lib.rs | 7 ++++--- modules/grandpa/Cargo.toml | 4 ++-- primitives/chain-westend/src/lib.rs | 20 +++++++++---------- primitives/header-chain/Cargo.toml | 6 +++--- primitives/parachains/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/runtime/src/lib.rs | 4 ++-- .../westend_parachains_to_millau.rs | 12 +++++------ relays/bin-substrate/src/chains/westend.rs | 4 ++-- .../bin-substrate/src/cli/relay_parachains.rs | 6 +++--- relays/client-westend/src/lib.rs | 14 ++++++------- 12 files changed, 43 insertions(+), 42 deletions(-) diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index 425f5685ae267..f985d4d9783ec 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -164,8 +164,8 @@ fn endowed_accounts() -> Vec { get_account_id_from_seed::(WESTEND_GRANDPA_PALLET_OWNER), get_account_id_from_seed::("Westend.HeadersRelay1"), get_account_id_from_seed::("Westend.HeadersRelay2"), - get_account_id_from_seed::("Westend.WestmintHeaders1"), - get_account_id_from_seed::("Westend.WestmintHeaders2"), + get_account_id_from_seed::("Westend.AssetHubWestendHeaders1"), + get_account_id_from_seed::("Westend.AssetHubWestendHeaders2"), // Accounts, used by Rialto<>Millau bridge get_account_id_from_seed::(RIALTO_MESSAGES_PALLET_OWNER), get_account_id_from_seed::("Rialto.HeadersAndMessagesRelay"), diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index daaa9815a8afc..dfd6fc322e505 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -531,7 +531,8 @@ impl pallet_bridge_parachains::Config for Runtime type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; - type ParaStoredHeaderDataBuilder = SingleParaStoredHeaderDataBuilder; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; type HeadsToKeep = ConstU32<1024>; type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; } @@ -889,12 +890,12 @@ impl_runtime_apis! { } } - impl bp_westend::WestmintFinalityApi for Runtime { + impl bp_westend::AssetHubWestendFinalityApi for Runtime { fn best_finalized() -> Option> { pallet_bridge_parachains::Pallet::< Runtime, WithWestendParachainsInstance, - >::best_parachain_head_id::().unwrap_or(None) + >::best_parachain_head_id::().unwrap_or(None) } } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index c9a79eb8682d8..d04c60729790e 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -22,8 +22,8 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-grandpa = { 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-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } 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 } diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 071f3a15a42c3..cdda46ba7b2b9 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -56,13 +56,13 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } -/// Westmint parachain definition +/// `AssetHubWestend` parachain definition #[derive(Debug, Clone, Copy)] -pub struct Westmint; +pub struct AssetHubWestend; -// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend -// primitives here. -impl Chain for Westmint { +// AssetHubWestend seems to use the same configuration as all Polkadot-like chains, so we'll use +// Westend primitives here. +impl Chain for AssetHubWestend { type BlockNumber = BlockNumber; type Hash = Hash; type Hasher = Hasher; @@ -82,8 +82,8 @@ impl Chain for Westmint { } } -impl Parachain for Westmint { - const PARACHAIN_ID: u32 = WESTMINT_PARACHAIN_ID; +impl Parachain for AssetHubWestend { + const PARACHAIN_ID: u32 = ASSET_HUB_WESTEND_PARACHAIN_ID; } /// Name of the parachains pallet at the Westend runtime. @@ -100,9 +100,9 @@ pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -/// Identifier of Westmint parachain at the Westend relay chain. -pub const WESTMINT_PARACHAIN_ID: u32 = 1000; +/// Identifier of `AssetHubWestend` parachain at the Westend relay chain. +pub const ASSET_HUB_WESTEND_PARACHAIN_ID: u32 = 1000; decl_bridge_finality_runtime_apis!(westend); -decl_bridge_finality_runtime_apis!(westmint); +decl_bridge_finality_runtime_apis!(AssetHubWestend); diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index bb372085292cf..962d262d571b3 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -19,9 +19,9 @@ bp-runtime = { path = "../runtime", 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-consensus-grandpa = { 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-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [dev-dependencies] diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 90cff6be3911d..6cd138c62249a 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -3,7 +3,7 @@ name = "bp-parachains" description = "Primitives of parachains module." version = "0.1.0" authors = ["Parity Technologies "] -edition = "2018" +edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 4a4bc932bce01..dea3c979b8628 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -20,7 +20,7 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } 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 } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 0bfbd1c2ee91b..150e015cb4f12 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -77,8 +77,8 @@ pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; /// Westend chain id. pub const WESTEND_CHAIN_ID: ChainId = *b"wend"; -/// Westend chain id. -pub const WESTMINT_CHAIN_ID: ChainId = *b"wmnt"; +/// `AssetHubWestmint` chain id. +pub const ASSET_HUB_WESTEND_CHAIN_ID: ChainId = *b"ahwe"; /// Rococo chain id. pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs index 0556ecab368eb..78164eb17e449 100644 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs @@ -18,7 +18,7 @@ use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; use relay_millau_client::Millau; -use relay_westend_client::{Westend, Westmint}; +use relay_westend_client::{AssetHubWestend, Westend}; use substrate_relay_helper::parachains::{ DirectSubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, }; @@ -28,7 +28,7 @@ use substrate_relay_helper::parachains::{ pub struct WestendParachainsToMillau; impl SubstrateParachainsPipeline for WestendParachainsToMillau { - type SourceParachain = Westmint; + type SourceParachain = AssetHubWestend; type SourceRelayChain = Westend; type TargetChain = Millau; @@ -44,16 +44,16 @@ pub type WestendParachainsToMillauSubmitParachainHeadsCallBuilder = >; //// `WestendParachain` to `Millau` bridge definition. -pub struct WestmintToMillauCliBridge {} +pub struct AssetHubWestendToMillauCliBridge {} -impl ParachainToRelayHeadersCliBridge for WestmintToMillauCliBridge { +impl ParachainToRelayHeadersCliBridge for AssetHubWestendToMillauCliBridge { type SourceRelay = Westend; type ParachainFinality = WestendParachainsToMillau; type RelayFinality = crate::bridges::westend_millau::westend_headers_to_millau::WestendFinalityToMillau; } -impl CliBridgeBase for WestmintToMillauCliBridge { - type Source = Westmint; +impl CliBridgeBase for AssetHubWestendToMillauCliBridge { + type Source = AssetHubWestend; type Target = Millau; } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 9cf639e987486..af404878ceb06 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -18,12 +18,12 @@ use crate::cli::CliChain; use relay_substrate_client::SimpleRuntimeVersion; -use relay_westend_client::{Westend, Westmint}; +use relay_westend_client::{AssetHubWestend, Westend}; impl CliChain for Westend { const RUNTIME_VERSION: Option = None; } -impl CliChain for Westmint { +impl CliChain for AssetHubWestend { const RUNTIME_VERSION: Option = None; } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 8c2aa1cc8c1f6..67daf01c8f4b2 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -24,7 +24,7 @@ use crate::bridges::{ rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, }, - westend_millau::westend_parachains_to_millau::WestmintToMillauCliBridge, + westend_millau::westend_parachains_to_millau::AssetHubWestendToMillauCliBridge, }; use async_std::sync::Mutex; use async_trait::async_trait; @@ -115,7 +115,7 @@ where } impl ParachainsRelayer for RialtoParachainToMillauCliBridge {} -impl ParachainsRelayer for WestmintToMillauCliBridge {} +impl ParachainsRelayer for AssetHubWestendToMillauCliBridge {} impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} @@ -128,7 +128,7 @@ impl RelayParachains { RelayParachainsBridge::RialtoToMillau => RialtoParachainToMillauCliBridge::relay_parachains(self), RelayParachainsBridge::WestendToMillau => - WestmintToMillauCliBridge::relay_parachains(self), + AssetHubWestendToMillauCliBridge::relay_parachains(self), RelayParachainsBridge::RococoToBridgeHubWococo => BridgeHubRococoToBridgeHubWococoCliBridge::relay_parachains(self), RelayParachainsBridge::WococoToBridgeHubRococo => diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 6013bfad128a5..1251276fcfdbd 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -58,21 +58,21 @@ impl ChainWithBalances for Westend { } } -/// Westmint parachain definition +/// `AssetHubWestend` parachain definition #[derive(Debug, Clone, Copy)] -pub struct Westmint; +pub struct AssetHubWestend; -impl UnderlyingChainProvider for Westmint { - type Chain = bp_westend::Westmint; +impl UnderlyingChainProvider for AssetHubWestend { + type Chain = bp_westend::AssetHubWestend; } // Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend // primitives here. -impl Chain for Westmint { - const ID: ChainId = bp_runtime::WESTMINT_CHAIN_ID; +impl Chain for AssetHubWestend { + const ID: ChainId = bp_runtime::ASSET_HUB_WESTEND_CHAIN_ID; const NAME: &'static str = "Westmint"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_westend::BEST_FINALIZED_WESTMINT_HEADER_METHOD; + bp_westend::BEST_FINALIZED_ASSETHUBWESTEND_HEADER_METHOD; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); type SignedBlock = bp_westend::SignedBlock; From f1783a91f5f1341792d3d6d443a8e975b3714f38 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 24 Jul 2023 16:26:23 +0300 Subject: [PATCH 1085/1210] GRANDPA justifications: equivocation detection primitives (#2295) (#2297) * GRANDPA justifications: equivocation detection primitives - made the justification verification logic more customizable - added support for parsing multiple justifications and extracting equivocations - split the logic into multiple files - split the errors into multiple enums --- primitives/header-chain/src/justification.rs | 444 ------------------ .../header-chain/src/justification/mod.rs | 127 +++++ .../verification/equivocation.rs | 179 +++++++ .../src/justification/verification/mod.rs | 279 +++++++++++ .../justification/verification/optimizer.rs | 132 ++++++ .../src/justification/verification/strict.rs | 106 +++++ .../tests/implementation_match.rs | 27 +- .../tests/justification/equivocation.rs | 124 +++++ .../optimizer.rs} | 178 +------ .../tests/justification/strict.rs | 196 ++++++++ primitives/header-chain/tests/tests.rs | 7 + 11 files changed, 1163 insertions(+), 636 deletions(-) delete mode 100644 primitives/header-chain/src/justification.rs create mode 100644 primitives/header-chain/src/justification/mod.rs create mode 100644 primitives/header-chain/src/justification/verification/equivocation.rs create mode 100644 primitives/header-chain/src/justification/verification/mod.rs create mode 100644 primitives/header-chain/src/justification/verification/optimizer.rs create mode 100644 primitives/header-chain/src/justification/verification/strict.rs create mode 100644 primitives/header-chain/tests/justification/equivocation.rs rename primitives/header-chain/tests/{justification.rs => justification/optimizer.rs} (55%) create mode 100644 primitives/header-chain/tests/justification/strict.rs create mode 100644 primitives/header-chain/tests/tests.rs diff --git a/primitives/header-chain/src/justification.rs b/primitives/header-chain/src/justification.rs deleted file mode 100644 index 714546a42ef2d..0000000000000 --- a/primitives/header-chain/src/justification.rs +++ /dev/null @@ -1,444 +0,0 @@ -// 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 . - -//! Pallet for checking GRANDPA Finality Proofs. -//! -//! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin -//! will ever be moved to the sp_consensus_grandpa, we should reuse that implementation. - -use crate::ChainWithGrandpa; - -use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId}; -use codec::{Decode, Encode, MaxEncodedLen}; -use finality_grandpa::voter_set::VoterSet; -use frame_support::{RuntimeDebug, RuntimeDebugNoBound}; -use scale_info::TypeInfo; -use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, SetId}; -use sp_runtime::{traits::Header as HeaderT, SaturatedConversion}; -use sp_std::{ - collections::{btree_map::BTreeMap, btree_set::BTreeSet}, - prelude::*, -}; - -/// A GRANDPA Justification is a proof that a given header was finalized -/// at a certain height and with a certain set of authorities. -/// -/// This particular proof is used to prove that headers on a bridged chain -/// (so not our chain) have been finalized correctly. -#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeDebugNoBound)] -pub struct GrandpaJustification { - /// The round (voting period) this justification is valid for. - pub round: u64, - /// The set of votes for the chain which is to be finalized. - pub commit: - finality_grandpa::Commit, - /// A proof that the chain of blocks in the commit are related to each other. - pub votes_ancestries: Vec
, -} - -impl GrandpaJustification { - /// Returns reasonable size of justification using constants from the provided chain. - /// - /// An imprecise analogue of `MaxEncodedLen` implementation. We don't use it for - /// any precise calculations - that's just an estimation. - pub fn max_reasonable_size(required_precommits: u32) -> u32 - where - C: Chain + ChainWithGrandpa, - { - // we don't need precise results here - just estimations, so some details - // are removed from computations (e.g. bytes required to encode vector length) - - // structures in `finality_grandpa` crate are not implementing `MaxEncodedLength`, so - // here's our estimation for the `finality_grandpa::Commit` struct size - // - // precommit is: hash + number - // signed precommit is: precommit + signature (64b) + authority id - // commit is: hash + number + vec of signed precommits - let signed_precommit_size: u32 = BlockNumberOf::::max_encoded_len() - .saturating_add(HashOf::::max_encoded_len().saturated_into()) - .saturating_add(64) - .saturating_add(AuthorityId::max_encoded_len().saturated_into()) - .saturated_into(); - let max_expected_signed_commit_size = signed_precommit_size - .saturating_mul(required_precommits) - .saturating_add(BlockNumberOf::::max_encoded_len().saturated_into()) - .saturating_add(HashOf::::max_encoded_len().saturated_into()); - - // justification is a signed GRANDPA commit, `votes_ancestries` vector and round number - let max_expected_votes_ancestries_size = C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY - .saturating_mul(C::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); - - 8u32.saturating_add(max_expected_signed_commit_size) - .saturating_add(max_expected_votes_ancestries_size) - } - - pub fn commit_target_id(&self) -> HeaderId { - HeaderId(self.commit.target_number, self.commit.target_hash) - } -} - -impl crate::FinalityProof for GrandpaJustification { - fn target_header_number(&self) -> H::Number { - self.commit.target_number - } -} - -/// Justification verification error. -#[derive(Eq, RuntimeDebug, PartialEq)] -pub enum Error { - /// Failed to decode justification. - JustificationDecode, - /// Justification is finalizing unexpected header. - InvalidJustificationTarget, - /// Justification contains redundant votes. - RedundantVotesInJustification, - /// Justification contains unknown authority precommit. - UnknownAuthorityVote, - /// Justification contains duplicate authority precommit. - DuplicateAuthorityVote, - /// The authority has provided an invalid signature. - InvalidAuthoritySignature, - /// The justification contains precommit for header that is not a descendant of the commit - /// header. - UnrelatedAncestryVote, - /// The cumulative weight of all votes in the justification is not enough to justify commit - /// header finalization. - TooLowCumulativeWeight, - /// The justification contains extra (unused) headers in its `votes_ancestries` field. - RedundantVotesAncestries, -} - -/// Given GRANDPA authorities set size, return number of valid authorities votes that the -/// justification must have to be valid. -/// -/// This function assumes that all authorities have the same vote weight. -pub fn required_justification_precommits(authorities_set_length: u32) -> u32 { - authorities_set_length - authorities_set_length.saturating_sub(1) / 3 -} - -/// Decode justification target. -pub fn decode_justification_target( - raw_justification: &[u8], -) -> Result<(Header::Hash, Header::Number), Error> { - GrandpaJustification::
::decode(&mut &*raw_justification) - .map(|justification| (justification.commit.target_hash, justification.commit.target_number)) - .map_err(|_| Error::JustificationDecode) -} - -/// Verify and optimize given justification by removing unknown and duplicate votes. -pub fn verify_and_optimize_justification( - finalized_target: (Header::Hash, Header::Number), - authorities_set_id: SetId, - authorities_set: &VoterSet, - justification: &mut GrandpaJustification
, -) -> Result<(), Error> { - let mut optimizer = OptimizationCallbacks { - extra_precommits: vec![], - redundant_votes_ancestries: Default::default(), - }; - verify_justification_with_callbacks( - finalized_target, - authorities_set_id, - authorities_set, - justification, - &mut optimizer, - )?; - optimizer.optimize(justification); - - Ok(()) -} - -/// Verify that justification, that is generated by given authority set, finalizes given header. -pub fn verify_justification( - finalized_target: (Header::Hash, Header::Number), - authorities_set_id: SetId, - authorities_set: &VoterSet, - justification: &GrandpaJustification
, -) -> Result<(), Error> { - verify_justification_with_callbacks( - finalized_target, - authorities_set_id, - authorities_set, - justification, - &mut StrictVerificationCallbacks, - ) -} - -/// Verification callbacks. -trait VerificationCallbacks { - /// Called when we see a precommit from unknown authority. - fn on_unkown_authority(&mut self, precommit_idx: usize) -> Result<(), Error>; - /// Called when we see a precommit with duplicate vote from known authority. - fn on_duplicate_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; - /// Called when we see a precommit with an invalid signature. - fn on_invalid_authority_signature(&mut self, precommit_idx: usize) -> Result<(), Error>; - /// Called when we see a precommit after we've collected enough votes from authorities. - fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; - /// Called when we see a precommit that is not a descendant of the commit target. - fn on_unrelated_ancestry_vote(&mut self, precommit_idx: usize) -> Result<(), Error>; - /// Called when there are redundant headers in the votes ancestries. - fn on_redundant_votes_ancestries( - &mut self, - redundant_votes_ancestries: BTreeSet, - ) -> Result<(), Error>; -} - -/// Verification callbacks that reject all unknown, duplicate or redundant votes. -struct StrictVerificationCallbacks; - -impl VerificationCallbacks
for StrictVerificationCallbacks { - fn on_unkown_authority(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Err(Error::UnknownAuthorityVote) - } - - fn on_duplicate_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Err(Error::DuplicateAuthorityVote) - } - - fn on_invalid_authority_signature(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Err(Error::InvalidAuthoritySignature) - } - - fn on_redundant_authority_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Err(Error::RedundantVotesInJustification) - } - - fn on_unrelated_ancestry_vote(&mut self, _precommit_idx: usize) -> Result<(), Error> { - Err(Error::UnrelatedAncestryVote) - } - - fn on_redundant_votes_ancestries( - &mut self, - _redundant_votes_ancestries: BTreeSet, - ) -> Result<(), Error> { - Err(Error::RedundantVotesAncestries) - } -} - -/// Verification callbacks for justification optimization. -struct OptimizationCallbacks { - extra_precommits: Vec, - redundant_votes_ancestries: BTreeSet, -} - -impl OptimizationCallbacks
{ - fn optimize(self, justification: &mut GrandpaJustification
) { - for invalid_precommit_idx in self.extra_precommits.into_iter().rev() { - justification.commit.precommits.remove(invalid_precommit_idx); - } - if !self.redundant_votes_ancestries.is_empty() { - justification - .votes_ancestries - .retain(|header| !self.redundant_votes_ancestries.contains(&header.hash())) - } - } -} - -impl VerificationCallbacks
for OptimizationCallbacks
{ - fn on_unkown_authority(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.extra_precommits.push(precommit_idx); - Ok(()) - } - - fn on_duplicate_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.extra_precommits.push(precommit_idx); - Ok(()) - } - - fn on_invalid_authority_signature(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.extra_precommits.push(precommit_idx); - Ok(()) - } - - fn on_redundant_authority_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.extra_precommits.push(precommit_idx); - Ok(()) - } - - fn on_unrelated_ancestry_vote(&mut self, precommit_idx: usize) -> Result<(), Error> { - self.extra_precommits.push(precommit_idx); - Ok(()) - } - - fn on_redundant_votes_ancestries( - &mut self, - redundant_votes_ancestries: BTreeSet, - ) -> Result<(), Error> { - self.redundant_votes_ancestries = redundant_votes_ancestries; - Ok(()) - } -} - -/// Verify that justification, that is generated by given authority set, finalizes given header. -fn verify_justification_with_callbacks>( - finalized_target: (Header::Hash, Header::Number), - authorities_set_id: SetId, - authorities_set: &VoterSet, - justification: &GrandpaJustification
, - callbacks: &mut C, -) -> Result<(), Error> { - // ensure that it is justification for the expected header - if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { - return Err(Error::InvalidJustificationTarget) - } - - let threshold = authorities_set.threshold().get(); - let mut chain = AncestryChain::new(justification); - let mut signature_buffer = Vec::new(); - let mut votes = BTreeSet::new(); - let mut cumulative_weight = 0u64; - - for (precommit_idx, signed) in justification.commit.precommits.iter().enumerate() { - // if we have collected enough precommits, we probabably want to fail/remove extra - // precommits - if cumulative_weight >= threshold { - callbacks.on_redundant_authority_vote(precommit_idx)?; - continue - } - - // authority must be in the set - let authority_info = match authorities_set.get(&signed.id) { - Some(authority_info) => authority_info, - None => { - callbacks.on_unkown_authority(precommit_idx)?; - continue - }, - }; - - // check if authority has already voted in the same round. - // - // there's a lot of code in `validate_commit` and `import_precommit` functions inside - // `finality-grandpa` crate (mostly related to reporting equivocations). But the only thing - // that we care about is that only first vote from the authority is accepted - if votes.contains(&signed.id) { - callbacks.on_duplicate_authority_vote(precommit_idx)?; - continue - } - - // all precommits must be descendants of the target block - let route = - match chain.ancestry(&signed.precommit.target_hash, &signed.precommit.target_number) { - Some(route) => route, - None => { - callbacks.on_unrelated_ancestry_vote(precommit_idx)?; - continue - }, - }; - - // verify authority signature - if !sp_consensus_grandpa::check_message_signature_with_buffer( - &finality_grandpa::Message::Precommit(signed.precommit.clone()), - &signed.id, - &signed.signature, - justification.round, - authorities_set_id, - &mut signature_buffer, - ) { - callbacks.on_invalid_authority_signature(precommit_idx)?; - continue - } - - // now we can count the vote since we know that it is valid - votes.insert(signed.id.clone()); - chain.mark_route_as_visited(route); - cumulative_weight = cumulative_weight.saturating_add(authority_info.weight().get()); - } - - // check that the cumulative weight of validators that voted for the justification target (or - // one of its descendents) is larger than the required threshold. - if cumulative_weight < threshold { - return Err(Error::TooLowCumulativeWeight) - } - - // check that there are no extra headers in the justification - if !chain.is_fully_visited() { - callbacks.on_redundant_votes_ancestries(chain.unvisited)?; - } - - Ok(()) -} - -/// Votes ancestries with useful methods. -#[derive(RuntimeDebug)] -pub struct AncestryChain { - /// We expect all forks in the ancestry chain to be descendants of base. - base: HeaderId, - /// Header hash => parent header hash mapping. - pub parents: BTreeMap, - /// Hashes of headers that were not visited by `ancestry()`. - pub unvisited: BTreeSet, -} - -impl AncestryChain
{ - /// Create new ancestry chain. - pub fn new(justification: &GrandpaJustification
) -> AncestryChain
{ - let mut parents = BTreeMap::new(); - let mut unvisited = BTreeSet::new(); - for ancestor in &justification.votes_ancestries { - let hash = ancestor.hash(); - let parent_hash = *ancestor.parent_hash(); - parents.insert(hash, parent_hash); - unvisited.insert(hash); - } - AncestryChain { base: justification.commit_target_id(), parents, unvisited } - } - - /// Returns a route if the precommit target block is a descendant of the `base` block. - pub fn ancestry( - &self, - precommit_target_hash: &Header::Hash, - precommit_target_number: &Header::Number, - ) -> Option> { - if precommit_target_number < &self.base.number() { - return None - } - - let mut route = vec![]; - let mut current_hash = *precommit_target_hash; - loop { - if current_hash == self.base.hash() { - break - } - - current_hash = match self.parents.get(¤t_hash) { - Some(parent_hash) => { - let is_visited_before = self.unvisited.get(¤t_hash).is_none(); - if is_visited_before { - // If the current header has been visited in a previous call, it is a - // descendent of `base` (we assume that the previous call was successful). - return Some(route) - } - route.push(current_hash); - - *parent_hash - }, - None => return None, - }; - } - - Some(route) - } - - fn mark_route_as_visited(&mut self, route: Vec) { - for hash in route { - self.unvisited.remove(&hash); - } - } - - fn is_fully_visited(&self) -> bool { - self.unvisited.is_empty() - } -} diff --git a/primitives/header-chain/src/justification/mod.rs b/primitives/header-chain/src/justification/mod.rs new file mode 100644 index 0000000000000..17be6cfd79611 --- /dev/null +++ b/primitives/header-chain/src/justification/mod.rs @@ -0,0 +1,127 @@ +// Copyright 2019-2023 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 . + +//! Logic for checking GRANDPA Finality Proofs. +//! +//! Adapted copy of substrate/client/finality-grandpa/src/justification.rs. If origin +//! will ever be moved to the sp_consensus_grandpa, we should reuse that implementation. + +mod verification; + +use crate::ChainWithGrandpa; +pub use verification::{ + equivocation::{EquivocationsCollector, Error as EquivocationsCollectorError}, + optimizer::verify_and_optimize_justification, + strict::verify_justification, + AncestryChain, Error as JustificationVerificationError, PrecommitError, +}; + +use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId}; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{RuntimeDebug, RuntimeDebugNoBound}; +use scale_info::TypeInfo; +use sp_consensus_grandpa::{AuthorityId, AuthoritySignature}; +use sp_runtime::{traits::Header as HeaderT, SaturatedConversion}; +use sp_std::prelude::*; + +/// A GRANDPA Justification is a proof that a given header was finalized +/// at a certain height and with a certain set of authorities. +/// +/// This particular proof is used to prove that headers on a bridged chain +/// (so not our chain) have been finalized correctly. +#[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo, RuntimeDebugNoBound)] +pub struct GrandpaJustification { + /// The round (voting period) this justification is valid for. + pub round: u64, + /// The set of votes for the chain which is to be finalized. + pub commit: + finality_grandpa::Commit, + /// A proof that the chain of blocks in the commit are related to each other. + pub votes_ancestries: Vec
, +} + +impl GrandpaJustification { + /// Returns reasonable size of justification using constants from the provided chain. + /// + /// An imprecise analogue of `MaxEncodedLen` implementation. We don't use it for + /// any precise calculations - that's just an estimation. + pub fn max_reasonable_size(required_precommits: u32) -> u32 + where + C: Chain + ChainWithGrandpa, + { + // we don't need precise results here - just estimations, so some details + // are removed from computations (e.g. bytes required to encode vector length) + + // structures in `finality_grandpa` crate are not implementing `MaxEncodedLength`, so + // here's our estimation for the `finality_grandpa::Commit` struct size + // + // precommit is: hash + number + // signed precommit is: precommit + signature (64b) + authority id + // commit is: hash + number + vec of signed precommits + let signed_precommit_size: u32 = BlockNumberOf::::max_encoded_len() + .saturating_add(HashOf::::max_encoded_len().saturated_into()) + .saturating_add(64) + .saturating_add(AuthorityId::max_encoded_len().saturated_into()) + .saturated_into(); + let max_expected_signed_commit_size = signed_precommit_size + .saturating_mul(required_precommits) + .saturating_add(BlockNumberOf::::max_encoded_len().saturated_into()) + .saturating_add(HashOf::::max_encoded_len().saturated_into()); + + let max_expected_votes_ancestries_size = C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + .saturating_mul(C::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); + + // justification is round number (u64=8b), a signed GRANDPA commit and the + // `votes_ancestries` vector + 8u32.saturating_add(max_expected_signed_commit_size) + .saturating_add(max_expected_votes_ancestries_size) + } + + /// Return identifier of header that this justification claims to finalize. + pub fn commit_target_id(&self) -> HeaderId { + HeaderId(self.commit.target_number, self.commit.target_hash) + } +} + +impl crate::FinalityProof for GrandpaJustification { + fn target_header_number(&self) -> H::Number { + self.commit.target_number + } +} + +/// Justification verification error. +#[derive(Eq, RuntimeDebug, PartialEq)] +pub enum Error { + /// Failed to decode justification. + JustificationDecode, +} + +/// Given GRANDPA authorities set size, return number of valid authorities votes that the +/// justification must have to be valid. +/// +/// This function assumes that all authorities have the same vote weight. +pub fn required_justification_precommits(authorities_set_length: u32) -> u32 { + authorities_set_length - authorities_set_length.saturating_sub(1) / 3 +} + +/// Decode justification target. +pub fn decode_justification_target( + raw_justification: &[u8], +) -> Result<(Header::Hash, Header::Number), Error> { + GrandpaJustification::
::decode(&mut &*raw_justification) + .map(|justification| (justification.commit.target_hash, justification.commit.target_number)) + .map_err(|_| Error::JustificationDecode) +} diff --git a/primitives/header-chain/src/justification/verification/equivocation.rs b/primitives/header-chain/src/justification/verification/equivocation.rs new file mode 100644 index 0000000000000..0ade3736c2274 --- /dev/null +++ b/primitives/header-chain/src/justification/verification/equivocation.rs @@ -0,0 +1,179 @@ +// Copyright 2019-2023 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 . + +//! Logic for extracting equivocations from multiple GRANDPA Finality Proofs. + +use crate::justification::{ + verification::{ + Error as JustificationVerificationError, JustificationVerifier, PrecommitError, + SignedPrecommit, + }, + GrandpaJustification, +}; + +use crate::justification::verification::IterationFlow; +use finality_grandpa::voter_set::VoterSet; +use frame_support::RuntimeDebug; +use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, EquivocationProof, Precommit, SetId}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + prelude::*, +}; + +/// Justification verification error. +#[derive(Eq, RuntimeDebug, PartialEq)] +pub enum Error { + /// Justification is targeting unexpected round. + InvalidRound, + /// Justification verification error. + JustificationVerification(JustificationVerificationError), +} + +enum AuthorityVotes { + SingleVote(SignedPrecommit
), + Equivocation( + finality_grandpa::Equivocation, AuthoritySignature>, + ), +} + +/// Structure that can extract equivocations from multiple GRANDPA justifications. +pub struct EquivocationsCollector<'a, Header: HeaderT> { + round: u64, + authorities_set_id: SetId, + authorities_set: &'a VoterSet, + + votes: BTreeMap>, +} + +impl<'a, Header: HeaderT> EquivocationsCollector<'a, Header> { + /// Create a new instance of `EquivocationsCollector`. + pub fn new( + authorities_set_id: SetId, + authorities_set: &'a VoterSet, + base_justification: &GrandpaJustification
, + ) -> Result { + let mut checker = Self { + round: base_justification.round, + authorities_set_id, + authorities_set, + votes: BTreeMap::new(), + }; + + checker.parse_justification(base_justification)?; + Ok(checker) + } + + /// Parse an additional justification for equivocations. + pub fn parse_justification( + &mut self, + justification: &GrandpaJustification
, + ) -> Result<(), Error> { + // The justification should target the same round as the base justification. + if self.round != justification.round { + return Err(Error::InvalidRound) + } + + self.verify_justification( + (justification.commit.target_hash, justification.commit.target_number), + self.authorities_set_id, + self.authorities_set, + justification, + ) + .map_err(Error::JustificationVerification) + } + + /// Extract the equivocation proofs that have been collected. + pub fn into_equivocation_proofs(self) -> Vec> { + let mut equivocations = vec![]; + for (_authority, vote) in self.votes { + if let AuthorityVotes::Equivocation(equivocation) = vote { + equivocations.push(EquivocationProof::new( + self.authorities_set_id, + sp_consensus_grandpa::Equivocation::Precommit(equivocation), + )); + } + } + + equivocations + } +} + +impl<'a, Header: HeaderT> JustificationVerifier
for EquivocationsCollector<'a, Header> { + fn process_redundant_vote( + &mut self, + _precommit_idx: usize, + ) -> Result { + Ok(IterationFlow::Run) + } + + fn process_known_authority_vote( + &mut self, + _precommit_idx: usize, + _signed: &SignedPrecommit
, + ) -> Result { + Ok(IterationFlow::Run) + } + + fn process_unknown_authority_vote( + &mut self, + _precommit_idx: usize, + ) -> Result<(), PrecommitError> { + Ok(()) + } + + fn process_unrelated_ancestry_vote( + &mut self, + _precommit_idx: usize, + ) -> Result { + Ok(IterationFlow::Run) + } + + fn process_invalid_signature_vote( + &mut self, + _precommit_idx: usize, + ) -> Result<(), PrecommitError> { + Ok(()) + } + + fn process_valid_vote(&mut self, signed: &SignedPrecommit
) { + match self.votes.get_mut(&signed.id) { + Some(vote) => match vote { + AuthorityVotes::SingleVote(first_vote) => { + if first_vote.precommit != signed.precommit { + *vote = AuthorityVotes::Equivocation(finality_grandpa::Equivocation { + round_number: self.round, + identity: signed.id.clone(), + first: (first_vote.precommit.clone(), first_vote.signature.clone()), + second: (signed.precommit.clone(), signed.signature.clone()), + }); + } + }, + AuthorityVotes::Equivocation(_) => {}, + }, + None => { + self.votes.insert(signed.id.clone(), AuthorityVotes::SingleVote(signed.clone())); + }, + } + } + + fn process_redundant_votes_ancestries( + &mut self, + _redundant_votes_ancestries: BTreeSet, + ) -> Result<(), JustificationVerificationError> { + Ok(()) + } +} diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/primitives/header-chain/src/justification/verification/mod.rs new file mode 100644 index 0000000000000..7cec1f14e966e --- /dev/null +++ b/primitives/header-chain/src/justification/verification/mod.rs @@ -0,0 +1,279 @@ +// Copyright 2019-2023 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 . + +//! Logic for checking GRANDPA Finality Proofs. + +pub mod equivocation; +pub mod optimizer; +pub mod strict; + +use crate::justification::GrandpaJustification; + +use bp_runtime::HeaderId; +use finality_grandpa::voter_set::VoterSet; +use frame_support::RuntimeDebug; +use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, SetId}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::{ + collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + prelude::*, +}; + +type SignedPrecommit
= finality_grandpa::SignedPrecommit< +
::Hash, +
::Number, + AuthoritySignature, + AuthorityId, +>; + +/// Votes ancestries with useful methods. +#[derive(RuntimeDebug)] +pub struct AncestryChain { + /// We expect all forks in the ancestry chain to be descendants of base. + base: HeaderId, + /// Header hash => parent header hash mapping. + pub parents: BTreeMap, + /// Hashes of headers that were not visited by `ancestry()`. + pub unvisited: BTreeSet, +} + +impl AncestryChain
{ + /// Create new ancestry chain. + pub fn new(justification: &GrandpaJustification
) -> AncestryChain
{ + let mut parents = BTreeMap::new(); + let mut unvisited = BTreeSet::new(); + for ancestor in &justification.votes_ancestries { + let hash = ancestor.hash(); + let parent_hash = *ancestor.parent_hash(); + parents.insert(hash, parent_hash); + unvisited.insert(hash); + } + AncestryChain { base: justification.commit_target_id(), parents, unvisited } + } + + /// Returns a route if the precommit target block is a descendant of the `base` block. + pub fn ancestry( + &self, + precommit_target_hash: &Header::Hash, + precommit_target_number: &Header::Number, + ) -> Option> { + if precommit_target_number < &self.base.number() { + return None + } + + let mut route = vec![]; + let mut current_hash = *precommit_target_hash; + loop { + if current_hash == self.base.hash() { + break + } + + current_hash = match self.parents.get(¤t_hash) { + Some(parent_hash) => { + let is_visited_before = self.unvisited.get(¤t_hash).is_none(); + if is_visited_before { + // If the current header has been visited in a previous call, it is a + // descendent of `base` (we assume that the previous call was successful). + return Some(route) + } + route.push(current_hash); + + *parent_hash + }, + None => return None, + }; + } + + Some(route) + } + + fn mark_route_as_visited(&mut self, route: Vec) { + for hash in route { + self.unvisited.remove(&hash); + } + } + + fn is_fully_visited(&self) -> bool { + self.unvisited.is_empty() + } +} + +/// Justification verification error. +#[derive(Eq, RuntimeDebug, PartialEq)] +pub enum Error { + /// Justification is finalizing unexpected header. + InvalidJustificationTarget, + /// Error validating a precommit + Precommit(PrecommitError), + /// The cumulative weight of all votes in the justification is not enough to justify commit + /// header finalization. + TooLowCumulativeWeight, + /// The justification contains extra (unused) headers in its `votes_ancestries` field. + RedundantVotesAncestries, +} + +/// Justification verification error. +#[derive(Eq, RuntimeDebug, PartialEq)] +pub enum PrecommitError { + /// Justification contains redundant votes. + RedundantAuthorityVote, + /// Justification contains unknown authority precommit. + UnknownAuthorityVote, + /// Justification contains duplicate authority precommit. + DuplicateAuthorityVote, + /// The authority has provided an invalid signature. + InvalidAuthoritySignature, + /// The justification contains precommit for header that is not a descendant of the commit + /// header. + UnrelatedAncestryVote, +} + +enum IterationFlow { + Run, + Skip, +} + +/// Verification callbacks. +trait JustificationVerifier { + fn process_redundant_vote( + &mut self, + precommit_idx: usize, + ) -> Result; + + fn process_known_authority_vote( + &mut self, + precommit_idx: usize, + signed: &SignedPrecommit
, + ) -> Result; + + fn process_unknown_authority_vote( + &mut self, + precommit_idx: usize, + ) -> Result<(), PrecommitError>; + + fn process_unrelated_ancestry_vote( + &mut self, + precommit_idx: usize, + ) -> Result; + + fn process_invalid_signature_vote( + &mut self, + precommit_idx: usize, + ) -> Result<(), PrecommitError>; + + fn process_valid_vote(&mut self, signed: &SignedPrecommit
); + + /// Called when there are redundant headers in the votes ancestries. + fn process_redundant_votes_ancestries( + &mut self, + redundant_votes_ancestries: BTreeSet, + ) -> Result<(), Error>; + + fn verify_justification( + &mut self, + finalized_target: (Header::Hash, Header::Number), + authorities_set_id: SetId, + authorities_set: &VoterSet, + justification: &GrandpaJustification
, + ) -> Result<(), Error> { + // ensure that it is justification for the expected header + if (justification.commit.target_hash, justification.commit.target_number) != + finalized_target + { + return Err(Error::InvalidJustificationTarget) + } + + let threshold = authorities_set.threshold().get(); + let mut chain = AncestryChain::new(justification); + let mut signature_buffer = Vec::new(); + let mut cumulative_weight = 0u64; + + for (precommit_idx, signed) in justification.commit.precommits.iter().enumerate() { + if cumulative_weight >= threshold { + let action = + self.process_redundant_vote(precommit_idx).map_err(Error::Precommit)?; + if matches!(action, IterationFlow::Skip) { + continue + } + } + + // authority must be in the set + let authority_info = match authorities_set.get(&signed.id) { + Some(authority_info) => { + // The implementer may want to do extra checks here. + // For example to see if the authority has already voted in the same round. + let action = self + .process_known_authority_vote(precommit_idx, signed) + .map_err(Error::Precommit)?; + if matches!(action, IterationFlow::Skip) { + continue + } + + authority_info + }, + None => { + self.process_unknown_authority_vote(precommit_idx).map_err(Error::Precommit)?; + continue + }, + }; + + // all precommits must be descendants of the target block + let maybe_route = + chain.ancestry(&signed.precommit.target_hash, &signed.precommit.target_number); + if maybe_route.is_none() { + let action = self + .process_unrelated_ancestry_vote(precommit_idx) + .map_err(Error::Precommit)?; + if matches!(action, IterationFlow::Skip) { + continue + } + } + + // verify authority signature + if !sp_consensus_grandpa::check_message_signature_with_buffer( + &finality_grandpa::Message::Precommit(signed.precommit.clone()), + &signed.id, + &signed.signature, + justification.round, + authorities_set_id, + &mut signature_buffer, + ) { + self.process_invalid_signature_vote(precommit_idx).map_err(Error::Precommit)?; + continue + } + + // now we can count the vote since we know that it is valid + self.process_valid_vote(signed); + if let Some(route) = maybe_route { + chain.mark_route_as_visited(route); + cumulative_weight = cumulative_weight.saturating_add(authority_info.weight().get()); + } + } + + // check that the cumulative weight of validators that voted for the justification target + // (or one of its descendents) is larger than the required threshold. + if cumulative_weight < threshold { + return Err(Error::TooLowCumulativeWeight) + } + + // check that there are no extra headers in the justification + if !chain.is_fully_visited() { + self.process_redundant_votes_ancestries(chain.unvisited)?; + } + + Ok(()) + } +} diff --git a/primitives/header-chain/src/justification/verification/optimizer.rs b/primitives/header-chain/src/justification/verification/optimizer.rs new file mode 100644 index 0000000000000..4cc6778ff511e --- /dev/null +++ b/primitives/header-chain/src/justification/verification/optimizer.rs @@ -0,0 +1,132 @@ +// Copyright 2019-2023 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 . + +//! Logic for optimizing GRANDPA Finality Proofs. + +use crate::justification::{ + verification::{Error, JustificationVerifier, PrecommitError}, + GrandpaJustification, +}; + +use crate::justification::verification::{IterationFlow, SignedPrecommit}; +use finality_grandpa::voter_set::VoterSet; +use sp_consensus_grandpa::{AuthorityId, SetId}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::{collections::btree_set::BTreeSet, prelude::*}; + +// Verification callbacks for justification optimization. +struct JustificationOptimizer { + votes: BTreeSet, + + extra_precommits: Vec, + redundant_votes_ancestries: BTreeSet, +} + +impl JustificationOptimizer
{ + fn optimize(self, justification: &mut GrandpaJustification
) { + for invalid_precommit_idx in self.extra_precommits.into_iter().rev() { + justification.commit.precommits.remove(invalid_precommit_idx); + } + if !self.redundant_votes_ancestries.is_empty() { + justification + .votes_ancestries + .retain(|header| !self.redundant_votes_ancestries.contains(&header.hash())) + } + } +} + +impl JustificationVerifier
for JustificationOptimizer
{ + fn process_redundant_vote( + &mut self, + precommit_idx: usize, + ) -> Result { + self.extra_precommits.push(precommit_idx); + Ok(IterationFlow::Skip) + } + + fn process_known_authority_vote( + &mut self, + precommit_idx: usize, + signed: &SignedPrecommit
, + ) -> Result { + // Skip duplicate votes + if self.votes.contains(&signed.id) { + self.extra_precommits.push(precommit_idx); + return Ok(IterationFlow::Skip) + } + + Ok(IterationFlow::Run) + } + + fn process_unknown_authority_vote( + &mut self, + precommit_idx: usize, + ) -> Result<(), PrecommitError> { + self.extra_precommits.push(precommit_idx); + Ok(()) + } + + fn process_unrelated_ancestry_vote( + &mut self, + precommit_idx: usize, + ) -> Result { + self.extra_precommits.push(precommit_idx); + Ok(IterationFlow::Skip) + } + + fn process_invalid_signature_vote( + &mut self, + precommit_idx: usize, + ) -> Result<(), PrecommitError> { + self.extra_precommits.push(precommit_idx); + Ok(()) + } + + fn process_valid_vote(&mut self, signed: &SignedPrecommit
) { + self.votes.insert(signed.id.clone()); + } + + fn process_redundant_votes_ancestries( + &mut self, + redundant_votes_ancestries: BTreeSet, + ) -> Result<(), Error> { + self.redundant_votes_ancestries = redundant_votes_ancestries; + Ok(()) + } +} + +/// Verify and optimize given justification by removing unknown and duplicate votes. +pub fn verify_and_optimize_justification( + finalized_target: (Header::Hash, Header::Number), + authorities_set_id: SetId, + authorities_set: &VoterSet, + justification: &mut GrandpaJustification
, +) -> Result<(), Error> { + let mut optimizer = JustificationOptimizer { + votes: BTreeSet::new(), + extra_precommits: vec![], + redundant_votes_ancestries: Default::default(), + }; + optimizer.verify_justification( + finalized_target, + authorities_set_id, + authorities_set, + justification, + )?; + optimizer.optimize(justification); + + Ok(()) +} diff --git a/primitives/header-chain/src/justification/verification/strict.rs b/primitives/header-chain/src/justification/verification/strict.rs new file mode 100644 index 0000000000000..da936c2358277 --- /dev/null +++ b/primitives/header-chain/src/justification/verification/strict.rs @@ -0,0 +1,106 @@ +// Copyright 2019-2023 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 . + +//! Logic for checking if GRANDPA Finality Proofs are valid and optimal. + +use crate::justification::{ + verification::{Error, JustificationVerifier, PrecommitError}, + GrandpaJustification, +}; + +use crate::justification::verification::{IterationFlow, SignedPrecommit}; +use finality_grandpa::voter_set::VoterSet; +use sp_consensus_grandpa::{AuthorityId, SetId}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::collections::btree_set::BTreeSet; + +/// Verification callbacks that reject all unknown, duplicate or redundant votes. +struct StrictJustificationVerifier { + votes: BTreeSet, +} + +impl JustificationVerifier
for StrictJustificationVerifier { + fn process_redundant_vote( + &mut self, + _precommit_idx: usize, + ) -> Result { + Err(PrecommitError::RedundantAuthorityVote) + } + + fn process_known_authority_vote( + &mut self, + _precommit_idx: usize, + signed: &SignedPrecommit
, + ) -> Result { + if self.votes.contains(&signed.id) { + // There's a lot of code in `validate_commit` and `import_precommit` functions + // inside `finality-grandpa` crate (mostly related to reporting equivocations). + // But the only thing that we care about is that only first vote from the + // authority is accepted + return Err(PrecommitError::DuplicateAuthorityVote) + } + + Ok(IterationFlow::Run) + } + + fn process_unknown_authority_vote( + &mut self, + _precommit_idx: usize, + ) -> Result<(), PrecommitError> { + Err(PrecommitError::UnknownAuthorityVote) + } + + fn process_unrelated_ancestry_vote( + &mut self, + _precommit_idx: usize, + ) -> Result { + Err(PrecommitError::UnrelatedAncestryVote) + } + + fn process_invalid_signature_vote( + &mut self, + _precommit_idx: usize, + ) -> Result<(), PrecommitError> { + Err(PrecommitError::InvalidAuthoritySignature) + } + + fn process_valid_vote(&mut self, signed: &SignedPrecommit
) { + self.votes.insert(signed.id.clone()); + } + + fn process_redundant_votes_ancestries( + &mut self, + _redundant_votes_ancestries: BTreeSet, + ) -> Result<(), Error> { + Err(Error::RedundantVotesAncestries) + } +} + +/// Verify that justification, that is generated by given authority set, finalizes given header. +pub fn verify_justification( + finalized_target: (Header::Hash, Header::Number), + authorities_set_id: SetId, + authorities_set: &VoterSet, + justification: &GrandpaJustification
, +) -> Result<(), Error> { + let mut verifier = StrictJustificationVerifier { votes: BTreeSet::new() }; + verifier.verify_justification( + finalized_target, + authorities_set_id, + authorities_set, + justification, + ) +} diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index d5e42e214976b..c4cd7f5f5b26e 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -21,7 +21,9 @@ //! Some of tests in this module may partially duplicate tests from `justification.rs`, //! but their purpose is different. -use bp_header_chain::justification::{verify_justification, Error, GrandpaJustification}; +use bp_header_chain::justification::{ + verify_justification, GrandpaJustification, JustificationVerificationError, PrecommitError, +}; use bp_test_utils::{ header_id, make_justification_for_header, signed_precommit, test_header, Account, JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE, TEST_GRANDPA_SET_ID, @@ -85,13 +87,6 @@ fn minimal_accounts_set() -> Vec<(Account, AuthorityWeight)> { vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1), (DAVE, 1)] } -/// Get a minimal subset of GRANDPA authorities that have enough cumulative vote weight to justify a -/// header finality. -pub fn minimal_voter_set() -> VoterSet { - VoterSet::new(minimal_accounts_set().iter().map(|(id, w)| (AuthorityId::from(*id), *w))) - .unwrap() -} - /// Make a valid GRANDPA justification with sensible defaults. pub fn make_default_justification(header: &TestHeader) -> GrandpaJustification { make_justification_for_header(JustificationGeneratorParams { @@ -124,7 +119,7 @@ fn same_result_when_precommit_target_has_lower_number_than_commit_target() { &full_voter_set(), &justification, ), - Err(Error::UnrelatedAncestryVote), + Err(JustificationVerificationError::Precommit(PrecommitError::UnrelatedAncestryVote)), ); // original implementation returns `Ok(validation_result)` @@ -157,7 +152,7 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { &full_voter_set(), &justification, ), - Err(Error::UnrelatedAncestryVote), + Err(JustificationVerificationError::Precommit(PrecommitError::UnrelatedAncestryVote)), ); // original implementation returns `Ok(validation_result)` @@ -191,7 +186,7 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta &full_voter_set(), &justification, ), - Err(Error::TooLowCumulativeWeight), + Err(JustificationVerificationError::TooLowCumulativeWeight), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == false`. @@ -229,7 +224,7 @@ fn different_result_when_justification_contains_duplicate_vote() { &full_voter_set(), &justification, ), - Err(Error::DuplicateAuthorityVote), + Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -270,7 +265,7 @@ fn different_results_when_authority_equivocates_once_in_a_round() { &full_voter_set(), &justification, ), - Err(Error::DuplicateAuthorityVote), + Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -323,7 +318,7 @@ fn different_results_when_authority_equivocates_twice_in_a_round() { &full_voter_set(), &justification, ), - Err(Error::DuplicateAuthorityVote), + Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -362,7 +357,7 @@ fn different_results_when_there_are_more_than_enough_votes() { &full_voter_set(), &justification, ), - Err(Error::RedundantVotesInJustification), + Err(JustificationVerificationError::Precommit(PrecommitError::RedundantAuthorityVote)), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. @@ -403,7 +398,7 @@ fn different_results_when_there_is_a_vote_of_unknown_authority() { &full_voter_set(), &justification, ), - Err(Error::UnknownAuthorityVote), + Err(JustificationVerificationError::Precommit(PrecommitError::UnknownAuthorityVote)), ); // original implementation returns `Ok(validation_result)` // with `validation_result.is_valid() == true`. diff --git a/primitives/header-chain/tests/justification/equivocation.rs b/primitives/header-chain/tests/justification/equivocation.rs new file mode 100644 index 0000000000000..072d5668edeb4 --- /dev/null +++ b/primitives/header-chain/tests/justification/equivocation.rs @@ -0,0 +1,124 @@ +// Copyright 2020-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 . + +//! Tests for Grandpa equivocations collector code. + +use bp_header_chain::justification::EquivocationsCollector; +use bp_test_utils::*; +use finality_grandpa::Precommit; +use sp_consensus_grandpa::EquivocationProof; + +type TestHeader = sp_runtime::testing::Header; + +#[test] +fn duplicate_votes_are_not_considered_equivocations() { + let voter_set = voter_set(); + let base_justification = make_default_justification::(&test_header(1)); + + let mut collector = + EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap(); + collector.parse_justification(&base_justification.clone()).unwrap(); + + assert_eq!(collector.into_equivocation_proofs().len(), 0); +} + +#[test] +fn equivocations_are_detected_in_base_justification_redundant_votes() { + let voter_set = voter_set(); + let mut base_justification = make_default_justification::(&test_header(1)); + + let first_vote = base_justification.commit.precommits[0].clone(); + let equivocation = signed_precommit::( + &ALICE, + header_id::(1), + base_justification.round, + TEST_GRANDPA_SET_ID, + ); + base_justification.commit.precommits.push(equivocation.clone()); + + let collector = + EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap(); + + assert_eq!( + collector.into_equivocation_proofs(), + vec![EquivocationProof::new( + 1, + sp_consensus_grandpa::Equivocation::Precommit(finality_grandpa::Equivocation { + round_number: 1, + identity: ALICE.into(), + first: ( + Precommit { + target_hash: first_vote.precommit.target_hash, + target_number: first_vote.precommit.target_number + }, + first_vote.signature + ), + second: ( + Precommit { + target_hash: equivocation.precommit.target_hash, + target_number: equivocation.precommit.target_number + }, + equivocation.signature + ) + }) + )] + ); +} + +#[test] +fn equivocations_are_detected_in_extra_justification_redundant_votes() { + let voter_set = voter_set(); + let base_justification = make_default_justification::(&test_header(1)); + let first_vote = base_justification.commit.precommits[0].clone(); + + let mut extra_justification = base_justification.clone(); + let equivocation = signed_precommit::( + &ALICE, + header_id::(1), + base_justification.round, + TEST_GRANDPA_SET_ID, + ); + extra_justification.commit.precommits.push(equivocation.clone()); + + let mut collector = + EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap(); + collector.parse_justification(&extra_justification).unwrap(); + + assert_eq!( + collector.into_equivocation_proofs(), + vec![EquivocationProof::new( + 1, + sp_consensus_grandpa::Equivocation::Precommit(finality_grandpa::Equivocation { + round_number: 1, + identity: ALICE.into(), + first: ( + Precommit { + target_hash: first_vote.precommit.target_hash, + target_number: first_vote.precommit.target_number + }, + first_vote.signature + ), + second: ( + Precommit { + target_hash: equivocation.precommit.target_hash, + target_number: equivocation.precommit.target_number + }, + equivocation.signature + ) + }) + )] + ); +} diff --git a/primitives/header-chain/tests/justification.rs b/primitives/header-chain/tests/justification/optimizer.rs similarity index 55% rename from primitives/header-chain/tests/justification.rs rename to primitives/header-chain/tests/justification/optimizer.rs index 26ed67fa65f61..8d1ba5ac6facb 100644 --- a/primitives/header-chain/tests/justification.rs +++ b/primitives/header-chain/tests/justification/optimizer.rs @@ -14,189 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Tests for Grandpa Justification code. +//! Tests for Grandpa Justification optimizer code. -use bp_header_chain::justification::{ - required_justification_precommits, verify_and_optimize_justification, verify_justification, - Error, -}; +use bp_header_chain::justification::verify_and_optimize_justification; use bp_test_utils::*; use finality_grandpa::SignedPrecommit; use sp_consensus_grandpa::AuthoritySignature; type TestHeader = sp_runtime::testing::Header; -#[test] -fn valid_justification_accepted() { - let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)]; - let params = JustificationGeneratorParams { - header: test_header(1), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: authorities.clone(), - ancestors: 7, - forks: 3, - }; - - let justification = make_justification_for_header::(params.clone()); - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), - &justification, - ), - Ok(()), - ); - - assert_eq!(justification.commit.precommits.len(), authorities.len()); - assert_eq!(justification.votes_ancestries.len(), params.ancestors as usize); -} - -#[test] -fn valid_justification_accepted_with_single_fork() { - let params = JustificationGeneratorParams { - header: test_header(1), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)], - ancestors: 5, - forks: 1, - }; - - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), - &make_justification_for_header::(params) - ), - Ok(()), - ); -} - -#[test] -fn valid_justification_accepted_with_arbitrary_number_of_authorities() { - use finality_grandpa::voter_set::VoterSet; - use sp_consensus_grandpa::AuthorityId; - - let n = 15; - let required_signatures = required_justification_precommits(n as _); - let authorities = accounts(n).iter().map(|k| (*k, 1)).collect::>(); - - let params = JustificationGeneratorParams { - header: test_header(1), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: authorities.clone().into_iter().take(required_signatures as _).collect(), - ancestors: n.into(), - forks: required_signatures, - }; - - let authorities = authorities - .iter() - .map(|(id, w)| (AuthorityId::from(*id), *w)) - .collect::>(); - let voter_set = VoterSet::new(authorities).unwrap(); - - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set, - &make_justification_for_header::(params) - ), - Ok(()), - ); -} - -#[test] -fn justification_with_invalid_target_rejected() { - assert_eq!( - verify_justification::( - header_id::(2), - TEST_GRANDPA_SET_ID, - &voter_set(), - &make_default_justification::(&test_header(1)), - ), - Err(Error::InvalidJustificationTarget), - ); -} - -#[test] -fn justification_with_invalid_commit_rejected() { - let mut justification = make_default_justification::(&test_header(1)); - justification.commit.precommits.clear(); - - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), - &justification, - ), - Err(Error::TooLowCumulativeWeight), - ); -} - -#[test] -fn justification_with_invalid_authority_signature_rejected() { - let mut justification = make_default_justification::(&test_header(1)); - justification.commit.precommits[0].signature = - sp_core::crypto::UncheckedFrom::unchecked_from([1u8; 64]); - - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), - &justification, - ), - Err(Error::InvalidAuthoritySignature), - ); -} - -#[test] -fn justification_with_invalid_precommit_ancestry() { - let mut justification = make_default_justification::(&test_header(1)); - justification.votes_ancestries.push(test_header(10)); - - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), - &justification, - ), - Err(Error::RedundantVotesAncestries), - ); -} - -#[test] -fn justification_is_invalid_if_we_dont_meet_threshold() { - // Need at least three authorities to sign off or else the voter set threshold can't be reached - let authorities = vec![(ALICE, 1), (BOB, 1)]; - - let params = JustificationGeneratorParams { - header: test_header(1), - round: TEST_GRANDPA_ROUND, - set_id: TEST_GRANDPA_SET_ID, - authorities: authorities.clone(), - ancestors: 2 * authorities.len() as u32, - forks: 2, - }; - - assert_eq!( - verify_justification::( - header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), - &make_justification_for_header::(params) - ), - Err(Error::TooLowCumulativeWeight), - ); -} - #[test] fn optimizer_does_noting_with_minimal_justification() { let mut justification = make_default_justification::(&test_header(1)); diff --git a/primitives/header-chain/tests/justification/strict.rs b/primitives/header-chain/tests/justification/strict.rs new file mode 100644 index 0000000000000..bf8fa5c9f4579 --- /dev/null +++ b/primitives/header-chain/tests/justification/strict.rs @@ -0,0 +1,196 @@ +// Copyright 2020-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 . + +//! Tests for Grandpa strict justification verifier code. + +use bp_header_chain::justification::{ + required_justification_precommits, verify_justification, JustificationVerificationError, + PrecommitError, +}; +use bp_test_utils::*; + +type TestHeader = sp_runtime::testing::Header; + +#[test] +fn valid_justification_accepted() { + let authorities = vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)]; + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: authorities.clone(), + ancestors: 7, + forks: 3, + }; + + let justification = make_justification_for_header::(params.clone()); + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &justification, + ), + Ok(()), + ); + + assert_eq!(justification.commit.precommits.len(), authorities.len()); + assert_eq!(justification.votes_ancestries.len(), params.ancestors as usize); +} + +#[test] +fn valid_justification_accepted_with_single_fork() { + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: vec![(ALICE, 1), (BOB, 1), (CHARLIE, 1)], + ancestors: 5, + forks: 1, + }; + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &make_justification_for_header::(params) + ), + Ok(()), + ); +} + +#[test] +fn valid_justification_accepted_with_arbitrary_number_of_authorities() { + use finality_grandpa::voter_set::VoterSet; + use sp_consensus_grandpa::AuthorityId; + + let n = 15; + let required_signatures = required_justification_precommits(n as _); + let authorities = accounts(n).iter().map(|k| (*k, 1)).collect::>(); + + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: authorities.clone().into_iter().take(required_signatures as _).collect(), + ancestors: n.into(), + forks: required_signatures, + }; + + let authorities = authorities + .iter() + .map(|(id, w)| (AuthorityId::from(*id), *w)) + .collect::>(); + let voter_set = VoterSet::new(authorities).unwrap(); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set, + &make_justification_for_header::(params) + ), + Ok(()), + ); +} + +#[test] +fn justification_with_invalid_target_rejected() { + assert_eq!( + verify_justification::( + header_id::(2), + TEST_GRANDPA_SET_ID, + &voter_set(), + &make_default_justification::(&test_header(1)), + ), + Err(JustificationVerificationError::InvalidJustificationTarget), + ); +} + +#[test] +fn justification_with_invalid_commit_rejected() { + let mut justification = make_default_justification::(&test_header(1)); + justification.commit.precommits.clear(); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &justification, + ), + Err(JustificationVerificationError::TooLowCumulativeWeight), + ); +} + +#[test] +fn justification_with_invalid_authority_signature_rejected() { + let mut justification = make_default_justification::(&test_header(1)); + justification.commit.precommits[0].signature = + sp_core::crypto::UncheckedFrom::unchecked_from([1u8; 64]); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &justification, + ), + Err(JustificationVerificationError::Precommit(PrecommitError::InvalidAuthoritySignature)), + ); +} + +#[test] +fn justification_with_invalid_precommit_ancestry() { + let mut justification = make_default_justification::(&test_header(1)); + justification.votes_ancestries.push(test_header(10)); + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &justification, + ), + Err(JustificationVerificationError::RedundantVotesAncestries), + ); +} + +#[test] +fn justification_is_invalid_if_we_dont_meet_threshold() { + // Need at least three authorities to sign off or else the voter set threshold can't be reached + let authorities = vec![(ALICE, 1), (BOB, 1)]; + + let params = JustificationGeneratorParams { + header: test_header(1), + round: TEST_GRANDPA_ROUND, + set_id: TEST_GRANDPA_SET_ID, + authorities: authorities.clone(), + ancestors: 2 * authorities.len() as u32, + forks: 2, + }; + + assert_eq!( + verify_justification::( + header_id::(1), + TEST_GRANDPA_SET_ID, + &voter_set(), + &make_justification_for_header::(params) + ), + Err(JustificationVerificationError::TooLowCumulativeWeight), + ); +} diff --git a/primitives/header-chain/tests/tests.rs b/primitives/header-chain/tests/tests.rs new file mode 100644 index 0000000000000..7c525a9303adc --- /dev/null +++ b/primitives/header-chain/tests/tests.rs @@ -0,0 +1,7 @@ +mod justification { + mod equivocation; + mod optimizer; + mod strict; +} + +mod implementation_match; From 81df7daf30543ac19beefdf248192791056982c0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 27 Jul 2023 15:50:17 +0300 Subject: [PATCH 1086/1210] GRANDPA module: store accepted justifications (#2298) (#2301) Store accepted justifications in events. --- bin/millau/runtime/Cargo.toml | 1 + bin/millau/runtime/src/lib.rs | 10 +++++++ bin/rialto-parachain/runtime/Cargo.toml | 1 + bin/rialto-parachain/runtime/src/lib.rs | 5 ++++ bin/rialto/runtime/Cargo.toml | 1 + bin/rialto/runtime/src/lib.rs | 5 ++++ modules/grandpa/src/lib.rs | 28 +++++++++++++++---- modules/parachains/src/lib.rs | 24 ++++++++++------ primitives/chain-kusama/src/lib.rs | 2 +- primitives/chain-millau/src/lib.rs | 4 +-- primitives/chain-polkadot/src/lib.rs | 2 +- primitives/chain-rialto/src/lib.rs | 4 +-- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-westend/src/lib.rs | 3 +- primitives/chain-wococo/src/lib.rs | 2 +- primitives/header-chain/src/lib.rs | 16 ++++++++++- primitives/runtime/src/chain.rs | 23 +++++++++++++-- relays/client-kusama/src/lib.rs | 11 ++++++-- relays/client-millau/src/lib.rs | 12 ++++++-- relays/client-polkadot/src/lib.rs | 13 +++++++-- relays/client-rialto/src/lib.rs | 12 ++++++-- relays/client-rococo/src/lib.rs | 10 ++++++- relays/client-substrate/src/chain.rs | 22 +++++---------- relays/client-westend/src/lib.rs | 10 ++++++- relays/client-wococo/src/lib.rs | 10 ++++++- .../src/finality/engine.rs | 21 +++++++++----- .../src/finality/source.rs | 2 +- 27 files changed, 193 insertions(+), 63 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index c92698edae29d..f4ad89159e068 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -13,6 +13,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Bridge dependencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-parachains = { path = "../../../primitives/parachains", default-features = false } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dfd6fc322e505..f0e23cc8d77f6 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -882,12 +882,22 @@ impl_runtime_apis! { fn best_finalized() -> Option> { BridgeRialtoGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeRialtoGrandpa::accepted_finality_proofs() + } } impl bp_westend::WestendFinalityApi for Runtime { fn best_finalized() -> Option> { BridgeWestendGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeWestendGrandpa::accepted_finality_proofs() + } } impl bp_westend::AssetHubWestendFinalityApi for Runtime { diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 41ca0bff9bf46..1b87205e9e9c4 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -16,6 +16,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Bridge depedencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 18c915819d5fb..db3113ce4489c 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -746,6 +746,11 @@ impl_runtime_apis! { fn best_finalized() -> Option> { BridgeMillauGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeMillauGrandpa::accepted_finality_proofs() + } } impl bp_millau::ToMillauOutboundLaneApi for Runtime { diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 2320665cf9a32..7f1b18bf99cb2 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -12,6 +12,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Bridge dependencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 1d93d24951e91..b4e64072afc0e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -694,6 +694,11 @@ impl_runtime_apis! { fn best_finalized() -> Option> { BridgeMillauGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeMillauGrandpa::accepted_finality_proofs() + } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index eb49849ac881f..fd9361948b653 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -49,7 +49,7 @@ use sp_runtime::{ traits::{Header as HeaderT, Zero}, SaturatedConversion, }; -use sp_std::{boxed::Box, convert::TryInto}; +use sp_std::{boxed::Box, convert::TryInto, prelude::*}; mod call_ext; #[cfg(test)] @@ -237,7 +237,7 @@ pub mod pallet { let actual_weight = pre_dispatch_weight .set_proof_size(pre_dispatch_weight.proof_size().saturating_sub(unused_proof_size)); - Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash }); + Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash, justification }); Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } @@ -402,6 +402,8 @@ pub mod pallet { UpdatedBestFinalizedHeader { number: BridgedBlockNumber, hash: BridgedBlockHash, + /// Justification. + justification: GrandpaJustification>, }, } @@ -603,10 +605,22 @@ pub mod pallet { } } -impl, I: 'static> Pallet { - /// Get the best finalized block number. - pub fn best_finalized_number() -> Option> { - BestFinalized::::get().map(|id| id.number()) +impl, I: 'static> Pallet +where + ::RuntimeEvent: TryInto>, +{ + /// Get the GRANDPA justifications accepted in the current block. + pub fn accepted_finality_proofs() -> Vec>> { + frame_system::Pallet::::read_events_no_consensus() + .filter_map(|event| { + if let Event::::UpdatedBestFinalizedHeader { justification, .. } = + event.event.try_into().ok()? + { + return Some(justification) + } + None + }) + .collect() } } @@ -913,10 +927,12 @@ mod tests { event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { number: *header.number(), hash: header.hash(), + justification: justification.clone(), }), topics: vec![], }], ); + assert_eq!(Pallet::::accepted_finality_proofs(), vec![justification]); }) } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 4f78a45d4b77b..3380b63aa5cfb 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -691,12 +691,13 @@ pub(crate) mod tests { use super::*; use crate::mock::{ run_test, test_relay_header, BigParachainHeader, RegularParachainHasher, - RegularParachainHeader, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, - UNTRACKED_PARACHAIN_ID, + RegularParachainHeader, RelayBlockHeader, RuntimeEvent as TestEvent, RuntimeOrigin, + TestRuntime, UNTRACKED_PARACHAIN_ID, }; use bp_test_utils::prepare_parachain_heads_proof; use codec::Encode; + use bp_header_chain::justification::GrandpaJustification; use bp_parachains::{ BestParaHeadHash, BridgeParachainCall, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider, }; @@ -740,7 +741,10 @@ pub(crate) mod tests { test_relay_header(0, state_root).hash() } - fn proceed(num: RelayBlockNumber, state_root: RelayBlockHash) -> ParaHash { + fn proceed( + num: RelayBlockNumber, + state_root: RelayBlockHash, + ) -> (ParaHash, GrandpaJustification) { pallet_bridge_grandpa::Pallet::::on_initialize( 0, ); @@ -752,11 +756,11 @@ pub(crate) mod tests { pallet_bridge_grandpa::Pallet::::submit_finality_proof( RuntimeOrigin::signed(1), Box::new(header), - justification, + justification.clone(), ) ); - hash + (hash, justification) } fn initial_best_head(parachain: u32) -> ParaInfo { @@ -993,7 +997,7 @@ pub(crate) mod tests { ); // import head#10 of parachain#1 at relay block #1 - let relay_1_hash = proceed(1, state_root_10); + let (relay_1_hash, justification) = proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( ParasInfo::::get(ParaId(1)), @@ -1032,6 +1036,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification } ), topics: vec![], @@ -1149,7 +1154,7 @@ pub(crate) mod tests { // try to import head#0 of parachain#1 at relay block#1 // => call succeeds, but nothing is changed - let relay_1_hash = proceed(1, state_root); + let (relay_1_hash, justification) = proceed(1, state_root); assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); assert_eq!( @@ -1169,6 +1174,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification } ), topics: vec![], @@ -1197,7 +1203,7 @@ pub(crate) mod tests { initialize(state_root_5); // head#10 of parachain#1 at relay block#1 - let relay_1_hash = proceed(1, state_root_10); + let (relay_1_hash, justification) = proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( ParasInfo::::get(ParaId(1)), @@ -1218,6 +1224,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification: justification.clone() } ), topics: vec![], @@ -1255,6 +1262,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification } ), topics: vec![], diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 229905a3d4ac5..80be182abfb70 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -69,4 +69,4 @@ pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -decl_bridge_finality_runtime_apis!(kusama); +decl_bridge_finality_runtime_apis!(kusama, grandpa); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index a752b5f7114ae..7acaa2c4018ec 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -25,7 +25,7 @@ use bp_header_chain::ChainWithGrandpa; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{decl_bridge_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, @@ -244,4 +244,4 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the transaction payment pallet at the Millau runtime. pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; -decl_bridge_runtime_apis!(millau); +decl_bridge_runtime_apis!(millau, grandpa); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 628634bb46f01..fb87c36442389 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -69,4 +69,4 @@ pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -decl_bridge_finality_runtime_apis!(polkadot); +decl_bridge_finality_runtime_apis!(polkadot, grandpa); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index d5be78516a21a..1104e17bb03a3 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -22,7 +22,7 @@ use bp_header_chain::ChainWithGrandpa; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{decl_bridge_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, @@ -211,4 +211,4 @@ pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; /// Name of the parachains pallet in the Rialto runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; -decl_bridge_runtime_apis!(rialto); +decl_bridge_runtime_apis!(rialto, grandpa); diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a825c8b39787c..a5aa46edde0e2 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -73,4 +73,4 @@ pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -decl_bridge_finality_runtime_apis!(rococo); +decl_bridge_finality_runtime_apis!(rococo, grandpa); diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index cdda46ba7b2b9..c1cab3198fbb5 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -19,6 +19,7 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; +use frame_support::sp_std::prelude::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; @@ -103,6 +104,6 @@ pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; /// Identifier of `AssetHubWestend` parachain at the Westend relay chain. pub const ASSET_HUB_WESTEND_PARACHAIN_ID: u32 = 1000; -decl_bridge_finality_runtime_apis!(westend); +decl_bridge_finality_runtime_apis!(westend, grandpa); decl_bridge_finality_runtime_apis!(AssetHubWestend); diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index fb63613427d03..8009fde023a22 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -62,4 +62,4 @@ impl ChainWithGrandpa for Wococo { /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; -decl_bridge_finality_runtime_apis!(wococo); +decl_bridge_finality_runtime_apis!(wococo, grandpa); diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5268e7d5c5faf..1f5102203ca2f 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -21,7 +21,7 @@ use bp_runtime::{ BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker, - StorageProofError, + StorageProofError, UnderlyingChainProvider, }; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; @@ -234,3 +234,17 @@ pub trait ChainWithGrandpa: Chain { /// refund amount and doing calls which exceed the limit, may be costly to submitter. const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; } + +/// A trait that provides the type of the underlying `ChainWithGrandpa`. +pub trait UnderlyingChainWithGrandpaProvider: UnderlyingChainProvider { + /// Underlying `ChainWithGrandpa` type. + type ChainWithGrandpa: ChainWithGrandpa; +} + +impl UnderlyingChainWithGrandpaProvider for T +where + T: UnderlyingChainProvider, + T::Chain: ChainWithGrandpa, +{ + type ChainWithGrandpa = T::Chain; +} diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 8c47662a7c13c..a5fb8a28809d8 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -279,10 +279,11 @@ pub type TransactionEraOf = crate::TransactionEra, HashOf /// - `FinalityApi` /// - constants that are stringified names of runtime API methods: /// - `BEST_FINALIZED__HEADER_METHOD` +/// - `_ACCEPTED__FINALITY_PROOFS_METHOD` /// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). #[macro_export] macro_rules! decl_bridge_finality_runtime_apis { - ($chain: ident) => { + ($chain: ident $(, $consensus: ident => $justification_type: ty)?) => { bp_runtime::paste::item! { mod [<$chain _finality_api>] { use super::*; @@ -291,6 +292,13 @@ macro_rules! decl_bridge_finality_runtime_apis { pub const []: &str = stringify!([<$chain:camel FinalityApi_best_finalized>]); + $( + /// Name of the `FinalityApi::accepted__finality_proofs` + /// runtime method. + pub const [<$chain:upper _ACCEPTED_ $consensus:upper _FINALITY_PROOFS_METHOD>]: &str = + stringify!([<$chain:camel FinalityApi_accepted_ $consensus:lower _finality_proofs>]); + )? + sp_api::decl_runtime_apis! { /// API for querying information about the finalized chain headers. /// @@ -299,6 +307,12 @@ macro_rules! decl_bridge_finality_runtime_apis { pub trait [<$chain:camel FinalityApi>] { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> Option>; + + $( + /// Returns the justifications accepted in the current block. + fn []( + ) -> Vec<$justification_type>; + )? } } } @@ -306,6 +320,9 @@ macro_rules! decl_bridge_finality_runtime_apis { pub use [<$chain _finality_api>]::*; } }; + ($chain: ident, grandpa) => { + decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::justification::GrandpaJustification
); + }; } /// Convenience macro that declares bridge messages runtime apis and related constants for a chain. @@ -376,8 +393,8 @@ macro_rules! decl_bridge_messages_runtime_apis { /// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). #[macro_export] macro_rules! decl_bridge_runtime_apis { - ($chain: ident) => { - bp_runtime::decl_bridge_finality_runtime_apis!($chain); + ($chain: ident $(, $consensus: ident)?) => { + bp_runtime::decl_bridge_finality_runtime_apis!($chain $(, $consensus)?); bp_runtime::decl_bridge_messages_runtime_apis!($chain); }; } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 3d53fe8f9f186..0f4172248f382 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,9 +16,11 @@ //! Types used to connect to the Kusama chain. -use bp_kusama::AccountInfoStorageMapKeyProvider; +use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD}; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -47,6 +49,11 @@ impl Chain for Kusama { type Call = (); } +impl ChainWithGrandpa for Kusama { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + KUSAMA_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index d6ce47d847dd3..1e899c7fdac3d 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -17,12 +17,13 @@ //! Types used to connect to the Millau-Substrate chain. use bp_messages::MessageNonce; +use bp_millau::MILLAU_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, NonceOf, SignParam, - UnderlyingChainProvider, UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + FullRuntimeUtilityPallet, NonceOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -65,6 +66,11 @@ impl Chain for Millau { type Call = millau_runtime::RuntimeCall; } +impl ChainWithGrandpa for Millau { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + MILLAU_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Millau { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 96453ab9041a8..f65f06c7de4e1 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,9 +16,13 @@ //! Types used to connect to the Polkadot chain. -use bp_polkadot::AccountInfoStorageMapKeyProvider; +use bp_polkadot::{ + AccountInfoStorageMapKeyProvider, POLKADOT_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD, +}; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -47,6 +51,11 @@ impl Chain for Polkadot { type Call = (); } +impl ChainWithGrandpa for Polkadot { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + POLKADOT_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 97b6c7ee802bf..00c98876e477c 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -17,12 +17,13 @@ //! Types used to connect to the Rialto-Substrate chain. use bp_messages::MessageNonce; +use bp_rialto::RIALTO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, NonceOf, RelayChain, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + ChainWithTransactions, Error as SubstrateError, NonceOf, RelayChain, SignParam, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -50,6 +51,11 @@ impl Chain for Rialto { type Call = rialto_runtime::RuntimeCall; } +impl ChainWithGrandpa for Rialto { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + RIALTO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl RelayChain for Rialto { const PARAS_PALLET_NAME: &'static str = bp_rialto::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index ede1bf1ded4e5..5254b877ea82a 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,8 +16,11 @@ //! Types used to connect to the Rococo-Substrate chain. +use bp_rococo::ROCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -46,6 +49,11 @@ impl Chain for Rococo { type Call = (); } +impl ChainWithGrandpa for Rococo { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + ROCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index f733a10d06b24..0d178da3db898 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,6 +16,7 @@ use crate::calls::UtilityCall; +use bp_header_chain::UnderlyingChainWithGrandpaProvider; use bp_messages::MessageNonce; use bp_runtime::{ Chain as ChainBase, ChainId, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, @@ -77,22 +78,13 @@ pub trait RelayChain: Chain { /// /// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement /// this trait. -pub trait ChainWithGrandpa: Chain { - /// Name of the bridge GRANDPA pallet (used in `construct_runtime` macro call) that is deployed - /// at some other chain to bridge with this `ChainWithGrandpa`. +pub trait ChainWithGrandpa: Chain + UnderlyingChainWithGrandpaProvider { + /// Name of the runtime API method that is returning the GRANDPA justifications accepted + /// by the `submit_finality_proofs` extrinsic in the queried block. /// - /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using - /// the same name. - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str; -} - -impl ChainWithGrandpa for T -where - T: Chain + UnderlyingChainProvider, - T::Chain: bp_header_chain::ChainWithGrandpa, -{ - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = - ::WITH_CHAIN_GRANDPA_PALLET_NAME; + /// Keep in mind that this method is normally provided by the other chain, which is + /// bridged with this chain. + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str; } /// Substrate-based parachain from minimal relay-client point of view. diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 1251276fcfdbd..67f1f61c547b8 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -17,7 +17,10 @@ //! Types used to connect to the Westend chain. use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use bp_westend::WESTEND_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -46,6 +49,11 @@ impl Chain for Westend { type Call = (); } +impl ChainWithGrandpa for Westend { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + WESTEND_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl RelayChain for Westend { const PARAS_PALLET_NAME: &'static str = bp_westend::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 2f0d6b22f9291..acb41be50e6d5 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -17,7 +17,10 @@ //! Types used to connect to the Wococo-Substrate chain. use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use bp_wococo::WOCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -46,6 +49,11 @@ impl Chain for Wococo { type Call = (); } +impl ChainWithGrandpa for Wococo { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + WOCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 3f7e3eecbaa98..0092db969925c 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -20,7 +20,8 @@ use crate::error::Error; use async_trait::async_trait; use bp_header_chain::{ justification::{verify_and_optimize_justification, GrandpaJustification}, - ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader, + ChainWithGrandpa as ChainWithGrandpaBase, ConsensusLogReader, FinalityProof, + GrandpaConsensusLogReader, }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode}; use codec::{Decode, Encode}; @@ -83,8 +84,10 @@ pub trait Engine: Send { } /// A method to subscribe to encoded finality proofs, given source client. - async fn finality_proofs(client: &Client) -> Result, SubstrateError> { - client.subscribe_finality_justifications::().await + async fn source_finality_proofs( + source_client: &Client, + ) -> Result, SubstrateError> { + source_client.subscribe_finality_justifications::().await } /// Optimize finality proof before sending it to the target node. @@ -139,11 +142,15 @@ impl Engine for Grandpa { type OperatingMode = BasicOperatingMode; fn is_initialized_key() -> StorageKey { - bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + bp_header_chain::storage_keys::best_finalized_key( + C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, + ) } fn pallet_operating_mode_key() -> StorageKey { - bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + bp_header_chain::storage_keys::pallet_operating_mode_key( + C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, + ) } async fn optimize_proof( @@ -152,7 +159,7 @@ impl Engine for Grandpa { proof: &mut Self::FinalityProof, ) -> Result<(), SubstrateError> { let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key( - C::WITH_CHAIN_GRANDPA_PALLET_NAME, + C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, ); let (authority_set, authority_set_id): ( sp_consensus_grandpa::AuthorityList, @@ -199,7 +206,7 @@ impl Engine for Grandpa { // But now there are problems with this approach - `CurrentSetId` may return invalid value. // So here we're waiting for the next justification, read the authorities set and then try // to figure out the set id with bruteforce. - let justifications = Self::finality_proofs(&source_client) + let justifications = Self::source_finality_proofs(&source_client) .await .map_err(|err| Error::Subscribe(C::NAME, err))?; // Read next justification - the header that it finalizes will be used as initial header. diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index c8f11d99461ba..6227263902ae6 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -234,7 +234,7 @@ impl SourceClient Result { Ok(unfold( - P::FinalityEngine::finality_proofs(&self.client).await?, + P::FinalityEngine::source_finality_proofs(&self.client).await?, move |subscription| async move { loop { let log_error = |err| { From 08ae6a70eafd565192514a5699425173d4aacef1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 4 Aug 2023 16:14:36 +0300 Subject: [PATCH 1087/1210] remove message sender origin (#2322) --- bin/millau/runtime/src/rialto_messages.rs | 7 -- .../runtime/src/rialto_parachain_messages.rs | 7 -- .../runtime/src/millau_messages.rs | 6 -- bin/rialto/runtime/src/millau_messages.rs | 7 -- bin/runtime-common/src/messages.rs | 10 +-- .../src/messages_xcm_extension.rs | 13 +-- modules/messages/src/lib.rs | 87 +++++-------------- modules/messages/src/mock.rs | 3 +- primitives/messages/src/source_chain.rs | 22 ++--- 9 files changed, 34 insertions(+), 128 deletions(-) diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 04084e0b9520c..a9a80fdf7d715 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -27,7 +27,6 @@ use bridge_runtime_common::{ }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; use pallet_bridge_relayers::WeightInfoExt as _; -use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto. @@ -124,12 +123,6 @@ pub struct ToRialtoXcmBlobHauler; impl XcmBlobHauler for ToRialtoXcmBlobHauler { type MessageSender = pallet_bridge_messages::Pallet; - type MessageSenderOrigin = RuntimeOrigin; - - fn message_sender_origin() -> RuntimeOrigin { - pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) - .into() - } fn xcm_lane() -> LaneId { XCM_LANE diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 1050f500fe8c1..a8540b705d754 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -29,7 +29,6 @@ use bridge_runtime_common::{ }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; use pallet_bridge_relayers::WeightInfoExt as _; -use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto parachain. @@ -125,12 +124,6 @@ pub struct ToRialtoParachainXcmBlobHauler; impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { type MessageSender = pallet_bridge_messages::Pallet; - type MessageSenderOrigin = RuntimeOrigin; - - fn message_sender_origin() -> RuntimeOrigin { - pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) - .into() - } fn xcm_lane() -> LaneId { XCM_LANE diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 68c9cbbec6011..666b1f0a8412e 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -29,7 +29,6 @@ use bridge_runtime_common::{ messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; -use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Millau. @@ -124,11 +123,6 @@ pub struct ToMillauXcmBlobHauler; impl XcmBlobHauler for ToMillauXcmBlobHauler { type MessageSender = pallet_bridge_messages::Pallet; - type MessageSenderOrigin = RuntimeOrigin; - - fn message_sender_origin() -> RuntimeOrigin { - pallet_xcm::Origin::from(MultiLocation::new(1, crate::UniversalLocation::get())).into() - } fn xcm_lane() -> LaneId { XCM_LANE diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index a99243cc3e6a9..357a5d7f02f09 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -26,7 +26,6 @@ use bridge_runtime_common::{ messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; -use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Lane that is used for XCM messages exchange. @@ -123,12 +122,6 @@ pub struct ToMillauXcmBlobHauler; impl XcmBlobHauler for ToMillauXcmBlobHauler { type MessageSender = pallet_bridge_messages::Pallet; - type MessageSenderOrigin = RuntimeOrigin; - - fn message_sender_origin() -> RuntimeOrigin { - pallet_xcm::Origin::from(MultiLocation::new(1, crate::xcm_config::UniversalLocation::get())) - .into() - } fn xcm_lane() -> LaneId { XCM_LANE diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index e6c7deb98a2ca..316c4d3cad927 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -72,8 +72,6 @@ pub type HasherOf = bp_runtime::HasherOf>; pub type AccountIdOf = bp_runtime::AccountIdOf>; /// Type of balances that is used on the chain. pub type BalanceOf = bp_runtime::BalanceOf>; -/// Type of origin that is used on the chain. -pub type OriginOf = ::RuntimeOrigin; /// Sub-module that is declaring types required for processing This -> Bridged chain messages. pub mod source { @@ -138,17 +136,11 @@ pub mod source { #[derive(RuntimeDebug)] pub struct FromThisChainMessageVerifier(PhantomData); - impl LaneMessageVerifier>, FromThisChainMessagePayload> - for FromThisChainMessageVerifier + impl LaneMessageVerifier for FromThisChainMessageVerifier where B: MessageBridge, - // matches requirements from the `frame_system::Config::Origin` - OriginOf>: Clone - + Into>>, OriginOf>>>, - AccountIdOf>: PartialEq + Clone, { fn verify_message( - _submitter: &OriginOf>, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, _payload: &FromThisChainMessagePayload, diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 96fdf1d501826..0317d745c15cf 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -110,12 +110,7 @@ impl MessageDispat /// one side, where on the other it can be dispatched by [`XcmBlobMessageDispatch`]. pub trait XcmBlobHauler { /// Runtime message sender adapter. - type MessageSender: MessagesBridge; - - /// Runtime message sender origin, which is used by [`Self::MessageSender`]. - type MessageSenderOrigin; - /// Our location within the Consensus Universe. - fn message_sender_origin() -> Self::MessageSenderOrigin; + type MessageSender: MessagesBridge; /// Return message lane (as "point-to-point link") used to deliver XCM messages. fn xcm_lane() -> LaneId; @@ -124,12 +119,10 @@ pub trait XcmBlobHauler { /// XCM bridge adapter which connects [`XcmBlobHauler`] with [`XcmBlobHauler::MessageSender`] and /// makes sure that XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed. pub struct XcmBlobHaulerAdapter(sp_std::marker::PhantomData); -impl> HaulBlob - for XcmBlobHaulerAdapter -{ +impl HaulBlob for XcmBlobHaulerAdapter { fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { let lane = H::xcm_lane(); - H::MessageSender::send_message(H::message_sender_origin(), lane, blob) + H::MessageSender::send_message(lane, blob) .map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256)) .map(|result| { log::info!( diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 3bfd5bc7e98f7..91ab3c965b93c 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -153,7 +153,7 @@ pub mod pallet { /// Target header chain. type TargetHeaderChain: TargetHeaderChain; /// Message payload verifier. - type LaneMessageVerifier: LaneMessageVerifier; + type LaneMessageVerifier: LaneMessageVerifier; /// Delivery confirmation payments. type DeliveryConfirmationPayments: DeliveryConfirmationPayments; @@ -643,8 +643,7 @@ pub mod pallet { } } -impl bp_messages::source_chain::MessagesBridge - for Pallet +impl bp_messages::source_chain::MessagesBridge for Pallet where T: Config, I: 'static, @@ -652,17 +651,15 @@ where type Error = sp_runtime::DispatchErrorWithPostInfo; fn send_message( - sender: T::RuntimeOrigin, lane: LaneId, message: T::OutboundPayload, ) -> Result { - crate::send_message::(sender, lane, message) + crate::send_message::(lane, message) } } /// Function that actually sends message. fn send_message, I: 'static>( - submitter: T::RuntimeOrigin, lane_id: LaneId, payload: T::OutboundPayload, ) -> sp_std::result::Result< @@ -688,18 +685,16 @@ fn send_message, I: 'static>( // now let's enforce any additional lane rules let mut lane = outbound_lane::(lane_id); - T::LaneMessageVerifier::verify_message(&submitter, &lane_id, &lane.data(), &payload).map_err( - |err| { - log::trace!( - target: LOG_TARGET, - "Message to lane {:?} is rejected by lane verifier: {:?}", - lane_id, - err, - ); + T::LaneMessageVerifier::verify_message(&lane_id, &lane.data(), &payload).map_err(|err| { + log::trace!( + target: LOG_TARGET, + "Message to lane {:?} is rejected by lane verifier: {:?}", + lane_id, + err, + ); - Error::::MessageRejectedByLaneVerifier(err) - }, - )?; + Error::::MessageRejectedByLaneVerifier(err) + })?; // finally, save message in outbound storage and emit event let encoded_payload = payload.encode(); @@ -915,7 +910,7 @@ mod tests { let message_nonce = outbound_lane::(TEST_LANE_ID).data().latest_generated_nonce + 1; - send_message::(RuntimeOrigin::signed(1), TEST_LANE_ID, REGULAR_PAYLOAD) + send_message::(TEST_LANE_ID, REGULAR_PAYLOAD) .expect("send_message has failed"); // check event with assigned nonce @@ -982,11 +977,7 @@ mod tests { )); assert_noop!( - send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - ), + send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,), Error::::NotOperatingNormally, ); @@ -1036,11 +1027,7 @@ mod tests { ); assert_noop!( - send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - ), + send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,), Error::::NotOperatingNormally, ); @@ -1090,11 +1077,7 @@ mod tests { .extra .extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]); assert_noop!( - send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - message_payload.clone(), - ), + send_message::(TEST_LANE_ID, message_payload.clone(),), Error::::MessageRejectedByPallet( VerificationError::MessageTooLarge ), @@ -1105,11 +1088,7 @@ mod tests { message_payload.extra.pop(); } assert_eq!(message_payload.encoded_size() as u32, MAX_OUTBOUND_PAYLOAD_SIZE); - assert_ok!(send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - message_payload, - ),); + assert_ok!(send_message::(TEST_LANE_ID, message_payload,),); }) } @@ -1118,11 +1097,7 @@ mod tests { run_test(|| { // messages with this payload are rejected by target chain verifier assert_noop!( - send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - PAYLOAD_REJECTED_BY_TARGET_CHAIN, - ), + send_message::(TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN,), Error::::MessageRejectedByChainVerifier(VerificationError::Other( mock::TEST_ERROR )), @@ -1137,7 +1112,7 @@ mod tests { let mut message = REGULAR_PAYLOAD; message.reject_by_lane_verifier = true; assert_noop!( - send_message::(RuntimeOrigin::signed(1), TEST_LANE_ID, message,), + send_message::(TEST_LANE_ID, message,), Error::::MessageRejectedByLaneVerifier(VerificationError::Other( mock::TEST_ERROR )), @@ -1293,16 +1268,8 @@ mod tests { #[test] fn receive_messages_delivery_proof_rewards_relayers() { run_test(|| { - assert_ok!(send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - )); - assert_ok!(send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID, - REGULAR_PAYLOAD, - )); + assert_ok!(send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,)); + assert_ok!(send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,)); // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A let single_message_delivery_proof = TestMessagesDeliveryProof(Ok(( @@ -1899,11 +1866,7 @@ mod tests { send_regular_message(); receive_messages_delivery_proof(); // send + receive confirmation for lane 2 - assert_ok!(send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID_2, - REGULAR_PAYLOAD, - )); + assert_ok!(send_message::(TEST_LANE_ID_2, REGULAR_PAYLOAD,)); assert_ok!(Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( @@ -1979,11 +1942,7 @@ mod tests { fn outbound_message_from_unconfigured_lane_is_rejected() { run_test(|| { assert_noop!( - send_message::( - RuntimeOrigin::signed(1), - TEST_LANE_ID_3, - REGULAR_PAYLOAD, - ), + send_message::(TEST_LANE_ID_3, REGULAR_PAYLOAD,), Error::::InactiveOutboundLane, ); }); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 62bc76c5e010b..83752523efb9b 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -310,9 +310,8 @@ impl TargetHeaderChain for TestTargetHeaderChain { #[derive(Debug, Default)] pub struct TestLaneMessageVerifier; -impl LaneMessageVerifier for TestLaneMessageVerifier { +impl LaneMessageVerifier for TestLaneMessageVerifier { fn verify_message( - _submitter: &RuntimeOrigin, _lane: &LaneId, _lane_outbound_data: &OutboundLaneData, payload: &TestPayload, diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index f3c50b84a09ad..09f6396ad7421 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -71,11 +71,10 @@ pub trait TargetHeaderChain { /// Lane3 until some block, ...), then it may be built using this verifier. /// /// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { +pub trait LaneMessageVerifier { /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the /// lane. fn verify_message( - submitter: &SenderOrigin, lane: &LaneId, outbound_data: &OutboundLaneData, payload: &Payload, @@ -124,32 +123,24 @@ pub struct SendMessageArtifacts { } /// Messages bridge API to be used from other pallets. -pub trait MessagesBridge { +pub trait MessagesBridge { /// Error type. type Error: Debug; /// Send message over the bridge. /// /// Returns unique message nonce or error if send has failed. - fn send_message( - sender: SenderOrigin, - lane: LaneId, - message: Payload, - ) -> Result; + fn send_message(lane: LaneId, message: Payload) -> Result; } /// Bridge that does nothing when message is being sent. #[derive(Eq, RuntimeDebug, PartialEq)] pub struct NoopMessagesBridge; -impl MessagesBridge for NoopMessagesBridge { +impl MessagesBridge for NoopMessagesBridge { type Error = &'static str; - fn send_message( - _sender: SenderOrigin, - _lane: LaneId, - _message: Payload, - ) -> Result { + fn send_message(_lane: LaneId, _message: Payload) -> Result { Ok(SendMessageArtifacts { nonce: 0 }) } } @@ -176,9 +167,8 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier for ForbidOutboundMessages { +impl LaneMessageVerifier for ForbidOutboundMessages { fn verify_message( - _submitter: &SenderOrigin, _lane: &LaneId, _outbound_data: &OutboundLaneData, _payload: &Payload, From 4df9742086fd30d2dad28fc9cc06e4408ac01c5e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 8 Aug 2023 15:27:07 +0300 Subject: [PATCH 1088/1210] Grandpa: Store the authority set changes (#2336) (#2337) * Grandpa: Store the authority set changes --- bin/millau/runtime/src/lib.rs | 12 ++-- bin/rialto-parachain/runtime/src/lib.rs | 6 +- bin/rialto/runtime/src/lib.rs | 6 +- modules/grandpa/src/lib.rs | 75 ++++++++++++++++++------- modules/grandpa/src/storage_types.rs | 4 +- modules/parachains/src/lib.rs | 22 ++++++-- primitives/chain-millau/Cargo.toml | 5 +- primitives/header-chain/src/lib.rs | 9 +++ primitives/runtime/src/chain.rs | 8 +-- relays/client-kusama/src/lib.rs | 6 +- relays/client-millau/src/lib.rs | 6 +- relays/client-polkadot/src/lib.rs | 8 +-- relays/client-rialto/src/lib.rs | 6 +- relays/client-rococo/src/lib.rs | 6 +- relays/client-substrate/src/chain.rs | 6 +- relays/client-westend/src/lib.rs | 6 +- relays/client-wococo/src/lib.rs | 6 +- 17 files changed, 128 insertions(+), 69 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index f0e23cc8d77f6..75f82c5343981 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -883,9 +883,9 @@ impl_runtime_apis! { BridgeRialtoGrandpa::best_finalized() } - fn accepted_grandpa_finality_proofs( - ) -> Vec> { - BridgeRialtoGrandpa::accepted_finality_proofs() + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgeRialtoGrandpa::synced_headers_grandpa_info() } } @@ -894,9 +894,9 @@ impl_runtime_apis! { BridgeWestendGrandpa::best_finalized() } - fn accepted_grandpa_finality_proofs( - ) -> Vec> { - BridgeWestendGrandpa::accepted_finality_proofs() + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgeWestendGrandpa::synced_headers_grandpa_info() } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index db3113ce4489c..eb15806b4e39e 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -747,9 +747,9 @@ impl_runtime_apis! { BridgeMillauGrandpa::best_finalized() } - fn accepted_grandpa_finality_proofs( - ) -> Vec> { - BridgeMillauGrandpa::accepted_finality_proofs() + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgeMillauGrandpa::synced_headers_grandpa_info() } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index b4e64072afc0e..8af330b328b6a 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -695,9 +695,9 @@ impl_runtime_apis! { BridgeMillauGrandpa::best_finalized() } - fn accepted_grandpa_finality_proofs( - ) -> Vec> { - BridgeMillauGrandpa::accepted_finality_proofs() + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgeMillauGrandpa::synced_headers_grandpa_info() } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index fd9361948b653..259a6c0f36b79 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -39,8 +39,8 @@ pub use storage_types::StoredAuthoritySet; use bp_header_chain::{ - justification::GrandpaJustification, ChainWithGrandpa, GrandpaConsensusLogReader, HeaderChain, - InitializationData, StoredHeaderData, StoredHeaderDataBuilder, + justification::GrandpaJustification, AuthoritySet, ChainWithGrandpa, GrandpaConsensusLogReader, + HeaderChain, HeaderGrandpaInfo, InitializationData, StoredHeaderData, StoredHeaderDataBuilder, }; use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; use finality_grandpa::voter_set::VoterSet; @@ -194,11 +194,12 @@ pub mod pallet { let authority_set = >::get(); let unused_proof_size = authority_set.unused_proof_size(); let set_id = authority_set.set_id; - verify_justification::(&justification, hash, number, authority_set.into())?; + let authority_set: AuthoritySet = authority_set.into(); + verify_justification::(&justification, hash, number, authority_set)?; - let is_authorities_change_enacted = + let maybe_new_authority_set = try_enact_authority_change::(&finality_target, set_id)?; - let may_refund_call_fee = is_authorities_change_enacted && + let may_refund_call_fee = maybe_new_authority_set.is_some() && // if we have seen too many mandatory headers in this block, we don't want to refund Self::free_mandatory_headers_remaining() > 0 && // if arguments out of expected bounds, we don't want to refund @@ -237,7 +238,14 @@ pub mod pallet { let actual_weight = pre_dispatch_weight .set_proof_size(pre_dispatch_weight.proof_size().saturating_sub(unused_proof_size)); - Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash, justification }); + Self::deposit_event(Event::UpdatedBestFinalizedHeader { + number, + hash, + grandpa_info: HeaderGrandpaInfo { + justification, + authority_set: maybe_new_authority_set, + }, + }); Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } @@ -402,8 +410,8 @@ pub mod pallet { UpdatedBestFinalizedHeader { number: BridgedBlockNumber, hash: BridgedBlockHash, - /// Justification. - justification: GrandpaJustification>, + /// The Grandpa info associated to the new best finalized header. + grandpa_info: HeaderGrandpaInfo>, }, } @@ -439,9 +447,7 @@ pub mod pallet { pub(crate) fn try_enact_authority_change, I: 'static>( header: &BridgedHeader, current_set_id: sp_consensus_grandpa::SetId, - ) -> Result { - let mut change_enacted = false; - + ) -> Result, DispatchError> { // We don't support forced changes - at that point governance intervention is required. ensure!( GrandpaConsensusLogReader::>::find_forced_change( @@ -470,7 +476,6 @@ pub mod pallet { // Since our header schedules a change and we know the delay is 0, it must also enact // the change. >::put(&next_authorities); - change_enacted = true; log::info!( target: LOG_TARGET, @@ -479,9 +484,11 @@ pub mod pallet { current_set_id + 1, next_authorities, ); + + return Ok(Some(next_authorities.into())) }; - Ok(change_enacted) + Ok(None) } /// Verify a GRANDPA justification (finality proof) for a given header. @@ -610,13 +617,13 @@ where ::RuntimeEvent: TryInto>, { /// Get the GRANDPA justifications accepted in the current block. - pub fn accepted_finality_proofs() -> Vec>> { + pub fn synced_headers_grandpa_info() -> Vec>> { frame_system::Pallet::::read_events_no_consensus() .filter_map(|event| { - if let Event::::UpdatedBestFinalizedHeader { justification, .. } = + if let Event::::UpdatedBestFinalizedHeader { grandpa_info, .. } = event.event.try_into().ok()? { - return Some(justification) + return Some(grandpa_info) } None }) @@ -927,12 +934,18 @@ mod tests { event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { number: *header.number(), hash: header.hash(), - justification: justification.clone(), + grandpa_info: HeaderGrandpaInfo { + justification: justification.clone(), + authority_set: None, + }, }), topics: vec![], }], ); - assert_eq!(Pallet::::accepted_finality_proofs(), vec![justification]); + assert_eq!( + Pallet::::synced_headers_grandpa_info(), + vec![HeaderGrandpaInfo { justification, authority_set: None }] + ); }) } @@ -1038,7 +1051,7 @@ mod tests { let result = Pallet::::submit_finality_proof( RuntimeOrigin::signed(1), Box::new(header.clone()), - justification, + justification.clone(), ); assert_ok!(result); assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::No); @@ -1053,6 +1066,30 @@ mod tests { StoredAuthoritySet::::try_new(next_authorities, next_set_id) .unwrap(), ); + + // Here + assert_eq!( + System::events(), + vec![EventRecord { + phase: Phase::Initialization, + event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { + number: *header.number(), + hash: header.hash(), + grandpa_info: HeaderGrandpaInfo { + justification: justification.clone(), + authority_set: Some(>::get().into()), + }, + }), + topics: vec![], + }], + ); + assert_eq!( + Pallet::::synced_headers_grandpa_info(), + vec![HeaderGrandpaInfo { + justification, + authority_set: Some(>::get().into()), + }] + ); }) } diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index 704482863350b..59fcb5d3f077f 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -20,7 +20,7 @@ use crate::{Config, Error}; use bp_header_chain::{AuthoritySet, ChainWithGrandpa}; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{traits::Get, BoundedVec, RuntimeDebugNoBound}; +use frame_support::{traits::Get, BoundedVec, CloneNoBound, RuntimeDebugNoBound}; use scale_info::TypeInfo; use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; use sp_std::marker::PhantomData; @@ -39,7 +39,7 @@ impl, I: 'static> Get for StoredAuthorityListLimit { } /// A bounded GRANDPA Authority List and ID. -#[derive(Clone, Decode, Encode, Eq, TypeInfo, MaxEncodedLen, RuntimeDebugNoBound)] +#[derive(CloneNoBound, Decode, Encode, Eq, TypeInfo, MaxEncodedLen, RuntimeDebugNoBound)] #[scale_info(skip_type_params(T, I))] pub struct StoredAuthoritySet, I: 'static> { /// List of GRANDPA authorities for the current round. diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 3380b63aa5cfb..24bc3535e619e 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -697,7 +697,7 @@ pub(crate) mod tests { use bp_test_utils::prepare_parachain_heads_proof; use codec::Encode; - use bp_header_chain::justification::GrandpaJustification; + use bp_header_chain::{justification::GrandpaJustification, HeaderGrandpaInfo}; use bp_parachains::{ BestParaHeadHash, BridgeParachainCall, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider, }; @@ -1036,7 +1036,10 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - justification + grandpa_info: HeaderGrandpaInfo { + justification, + authority_set: None, + }, } ), topics: vec![], @@ -1174,7 +1177,10 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - justification + grandpa_info: HeaderGrandpaInfo { + justification, + authority_set: None, + } } ), topics: vec![], @@ -1224,7 +1230,10 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - justification: justification.clone() + grandpa_info: HeaderGrandpaInfo { + justification: justification.clone(), + authority_set: None, + } } ), topics: vec![], @@ -1262,7 +1271,10 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - justification + grandpa_info: HeaderGrandpaInfo { + justification, + authority_set: None, + } } ), topics: vec![], diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index d12e76a8d04e6..4d7f1580c2371 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -8,7 +8,10 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -fixed-hash = { version = "0.8.0", default-features = false } +# TODO: Consume `fixed-hash` from crates.io when the following fix is published: +# https://github.com/paritytech/parity-common/commit/d3a9327124a66e52ca1114bb8640c02c18c134b8 +# Expected in a version > 0.8.0 +fixed-hash = { git = "https://github.com/paritytech/parity-common", branch = "master", default-features = false } hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", default-features = false } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 1f5102203ca2f..720dafdd93b09 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -172,6 +172,15 @@ impl ConsensusLogReader for GrandpaConsensusLogReader { } } +/// The Grandpa-related info associated to a header. +#[derive(Encode, Decode, Debug, PartialEq, Clone, TypeInfo)] +pub struct HeaderGrandpaInfo { + /// The header justification + pub justification: justification::GrandpaJustification
, + /// The authority set introduced by the header. + pub authority_set: Option, +} + /// A minimized version of `pallet-bridge-grandpa::Call` that can be used without a runtime. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] #[allow(non_camel_case_types)] diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index a5fb8a28809d8..a1b7e8d54b4f6 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -295,8 +295,8 @@ macro_rules! decl_bridge_finality_runtime_apis { $( /// Name of the `FinalityApi::accepted__finality_proofs` /// runtime method. - pub const [<$chain:upper _ACCEPTED_ $consensus:upper _FINALITY_PROOFS_METHOD>]: &str = - stringify!([<$chain:camel FinalityApi_accepted_ $consensus:lower _finality_proofs>]); + pub const [<$chain:upper _SYNCED_HEADERS_ $consensus:upper _INFO_METHOD>]: &str = + stringify!([<$chain:camel FinalityApi_synced_headers_ $consensus:lower _info>]); )? sp_api::decl_runtime_apis! { @@ -310,7 +310,7 @@ macro_rules! decl_bridge_finality_runtime_apis { $( /// Returns the justifications accepted in the current block. - fn []( + fn []( ) -> Vec<$justification_type>; )? } @@ -321,7 +321,7 @@ macro_rules! decl_bridge_finality_runtime_apis { } }; ($chain: ident, grandpa) => { - decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::justification::GrandpaJustification
); + decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::HeaderGrandpaInfo
); }; } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 0f4172248f382..477ea1b108f2d 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the Kusama chain. -use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD}; +use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; use bp_runtime::ChainId; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, @@ -50,8 +50,8 @@ impl Chain for Kusama { } impl ChainWithGrandpa for Kusama { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - KUSAMA_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl ChainWithBalances for Kusama { diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 1e899c7fdac3d..90def2d3bd5b6 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Millau-Substrate chain. use bp_messages::MessageNonce; -use bp_millau::MILLAU_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use bp_millau::MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ @@ -67,8 +67,8 @@ impl Chain for Millau { } impl ChainWithGrandpa for Millau { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - MILLAU_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl ChainWithBalances for Millau { diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index f65f06c7de4e1..a906944c8f498 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,9 +16,7 @@ //! Types used to connect to the Polkadot chain. -use bp_polkadot::{ - AccountInfoStorageMapKeyProvider, POLKADOT_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD, -}; +use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; use bp_runtime::ChainId; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, @@ -52,8 +50,8 @@ impl Chain for Polkadot { } impl ChainWithGrandpa for Polkadot { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - POLKADOT_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl ChainWithBalances for Polkadot { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 00c98876e477c..c12d27bc1d916 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Rialto-Substrate chain. use bp_messages::MessageNonce; -use bp_rialto::RIALTO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use bp_rialto::RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ @@ -52,8 +52,8 @@ impl Chain for Rialto { } impl ChainWithGrandpa for Rialto { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - RIALTO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl RelayChain for Rialto { diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5254b877ea82a..c4221e0dd004b 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the Rococo-Substrate chain. -use bp_rococo::ROCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use bp_runtime::ChainId; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, @@ -50,8 +50,8 @@ impl Chain for Rococo { } impl ChainWithGrandpa for Rococo { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - ROCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl ChainWithBalances for Rococo { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 0d178da3db898..fe0ec3ebb0a36 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -79,12 +79,12 @@ pub trait RelayChain: Chain { /// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement /// this trait. pub trait ChainWithGrandpa: Chain + UnderlyingChainWithGrandpaProvider { - /// Name of the runtime API method that is returning the GRANDPA justifications accepted - /// by the `submit_finality_proofs` extrinsic in the queried block. + /// Name of the runtime API method that is returning the GRANDPA info associated with the + /// headers accepted by the `submit_finality_proofs` extrinsic in the queried block. /// /// Keep in mind that this method is normally provided by the other chain, which is /// bridged with this chain. - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str; } /// Substrate-based parachain from minimal relay-client point of view. diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 67f1f61c547b8..e76bf65b82d89 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Westend chain. use bp_runtime::ChainId; -use bp_westend::WESTEND_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; @@ -50,8 +50,8 @@ impl Chain for Westend { } impl ChainWithGrandpa for Westend { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - WESTEND_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl RelayChain for Westend { diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index acb41be50e6d5..e4d23a27dcd39 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -17,7 +17,7 @@ //! Types used to connect to the Wococo-Substrate chain. use bp_runtime::ChainId; -use bp_wococo::WOCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use bp_wococo::WOCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; @@ -50,8 +50,8 @@ impl Chain for Wococo { } impl ChainWithGrandpa for Wococo { - const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = - WOCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + WOCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; } impl ChainWithBalances for Wococo { From 4db5f1252d92a542c3eb0f7e774a54ba3c121cc6 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 10 Aug 2023 10:44:34 +0200 Subject: [PATCH 1089/1210] Backport fix (for wasm `std` env) (#2339) * Backport fix (for wasm `std` env) * Cargo.lock * Polkadot/Westend * Cargo.lock --- primitives/chain-bridge-hub-kusama/src/lib.rs | 2 +- primitives/chain-bridge-hub-polkadot/src/lib.rs | 2 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 2 +- primitives/chain-bridge-hub-wococo/src/lib.rs | 2 +- primitives/chain-kusama/Cargo.toml | 2 ++ primitives/chain-kusama/src/lib.rs | 1 + primitives/chain-polkadot/Cargo.toml | 2 ++ primitives/chain-polkadot/src/lib.rs | 1 + primitives/chain-rococo/Cargo.toml | 2 ++ primitives/chain-rococo/src/lib.rs | 1 + primitives/chain-westend/Cargo.toml | 2 ++ primitives/chain-westend/src/lib.rs | 1 + primitives/chain-wococo/Cargo.toml | 2 ++ primitives/chain-wococo/src/lib.rs | 1 + 14 files changed, 19 insertions(+), 4 deletions(-) diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs index 7405f561fb2ea..03f295e07f1ef 100644 --- a/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{ sp_runtime::{MultiAddress, MultiSigner}, RuntimeDebug, }; -use sp_std::prelude::*; +use sp_std::prelude::Vec; /// BridgeHubKusama parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs index e1fc0d7bc47d9..ceacfe67ff2cb 100644 --- a/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; use frame_support::{dispatch::DispatchClass, RuntimeDebug}; -use sp_std::prelude::*; +use sp_std::prelude::Vec; /// BridgeHubPolkadot parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 50206c8e6b383..f8d46ff32bde8 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{ sp_runtime::{MultiAddress, MultiSigner}, RuntimeDebug, }; -use sp_std::prelude::*; +use sp_std::prelude::Vec; /// BridgeHubRococo parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 7d14460c73709..abbb0cc20ea4b 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; use frame_support::{dispatch::DispatchClass, RuntimeDebug}; -use sp_std::prelude::*; +use sp_std::prelude::Vec; /// BridgeHubWococo parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 7f48ded1a37e6..65b0729aa17e8 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -18,6 +18,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -27,4 +28,5 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-std/std", ] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 80be182abfb70..b758484aefeb4 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -23,6 +23,7 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::weights::Weight; +use sp_std::prelude::Vec; /// Kusama Chain pub struct Kusama; diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index def26bdda1c88..1522f1dadb71f 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -18,6 +18,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -27,4 +28,5 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-std/std", ] diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index fb87c36442389..eb62c1729adfd 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -23,6 +23,7 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::weights::Weight; +use sp_std::prelude::Vec; /// Polkadot Chain pub struct Polkadot; diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 4e21bd38b7acb..26e035b439a62 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -17,6 +17,7 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] @@ -27,4 +28,5 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-std/std", ] diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a5aa46edde0e2..140069d756959 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -23,6 +23,7 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::{parameter_types, weights::Weight}; +use sp_std::prelude::Vec; /// Rococo Chain pub struct Rococo; diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 13a2e597f9d86..a080b8d352748 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -18,6 +18,7 @@ bp-runtime = { path = "../runtime", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -27,4 +28,5 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-std/std", ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index c1cab3198fbb5..5840f6a652890 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -24,6 +24,7 @@ use frame_support::sp_std::prelude::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; use frame_support::weights::Weight; +use sp_std::prelude::Vec; /// Westend Chain pub struct Westend; diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 25fd7b9fd947a..3bde102d8f2c8 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -19,6 +19,7 @@ bp-rococo = { path = "../chain-rococo", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] default = ["std"] @@ -29,4 +30,5 @@ std = [ "bp-rococo/std", "frame-support/std", "sp-api/std", + "sp-std/std", ] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 8009fde023a22..8247b63238ce4 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -26,6 +26,7 @@ pub use bp_rococo::{ use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::weights::Weight; +use sp_std::prelude::Vec; /// Wococo Chain pub struct Wococo; From 2d6b9190814e4a16a19d948f4c84d8f641094bb6 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 11 Aug 2023 12:35:54 +0300 Subject: [PATCH 1090/1210] Add basic equivocation detection pipeline schema (#2338) (#2341) * Move finality Engine to finality_base folder * Define SubstrateFinalityPipeline Extract basic parts of SubstrateFinalitySyncPipeline into SubstrateFinalityPipeline * Add equivocation detection pipeline * Fix comment --- .../kusama_headers_to_bridge_hub_polkadot.rs | 9 +- .../polkadot_headers_to_bridge_hub_kusama.rs | 9 +- .../rialto_millau/millau_headers_to_rialto.rs | 11 ++- .../rialto_millau/rialto_headers_to_millau.rs | 11 ++- .../millau_headers_to_rialto_parachain.rs | 10 ++- .../rococo_headers_to_bridge_hub_wococo.rs | 9 +- .../wococo_headers_to_bridge_hub_rococo.rs | 9 +- .../westend_headers_to_millau.rs | 11 ++- relays/bin-substrate/src/cli/init_bridge.rs | 2 +- relays/client-kusama/Cargo.toml | 1 + relays/client-kusama/src/lib.rs | 3 + relays/client-millau/Cargo.toml | 1 + relays/client-millau/src/lib.rs | 3 + relays/client-polkadot/Cargo.toml | 1 + relays/client-polkadot/src/lib.rs | 3 + relays/client-rialto/Cargo.toml | 1 + relays/client-rialto/src/lib.rs | 3 + relays/client-rococo/Cargo.toml | 1 + relays/client-rococo/src/lib.rs | 3 + relays/client-substrate/src/chain.rs | 3 + relays/client-westend/Cargo.toml | 1 + relays/client-westend/src/lib.rs | 3 + relays/client-wococo/Cargo.toml | 1 + relays/client-wococo/src/lib.rs | 3 + relays/lib-substrate-relay/Cargo.toml | 1 + .../src/equivocation/mod.rs | 83 +++++++++++++++++++ .../src/finality/initialize.rs | 2 +- .../lib-substrate-relay/src/finality/mod.rs | 22 ++--- .../src/finality/source.rs | 13 +-- .../src/finality/target.rs | 3 +- .../src/{finality => finality_base}/engine.rs | 6 ++ .../src/finality_base/mod.rs | 35 ++++++++ relays/lib-substrate-relay/src/lib.rs | 2 + .../src/on_demand/headers.rs | 2 +- 34 files changed, 234 insertions(+), 47 deletions(-) create mode 100644 relays/lib-substrate-relay/src/equivocation/mod.rs rename relays/lib-substrate-relay/src/{finality => finality_base}/engine.rs (97%) create mode 100644 relays/lib-substrate-relay/src/finality_base/mod.rs diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs index 1cfaf922692f6..271aa5c6777fc 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -21,7 +21,8 @@ use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, }; @@ -37,11 +38,15 @@ substrate_relay_helper::generate_submit_finality_proof_call_builder!( ); #[async_trait] -impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { +impl SubstrateFinalityPipeline for KusamaFinalityToBridgeHubPolkadot { type SourceChain = relay_kusama_client::Kusama; type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { type SubmitFinalityProofCallBuilder = KusamaFinalityToBridgeHubPolkadotCallBuilder; async fn start_relay_guards( diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs index 6827c24768cb8..44d7ee94e3d21 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -21,7 +21,8 @@ use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, }; @@ -37,11 +38,15 @@ substrate_relay_helper::generate_submit_finality_proof_call_builder!( ); #[async_trait] -impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { +impl SubstrateFinalityPipeline for PolkadotFinalityToBridgeHubKusama { type SourceChain = relay_polkadot_client::Polkadot; type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama; type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { type SubmitFinalityProofCallBuilder = PolkadotFinalityToBridgeHubKusamaCallBuilder; async fn start_relay_guards( diff --git a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs index f805b29c6a943..490ded1f67cb9 100644 --- a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs @@ -17,20 +17,23 @@ //! Millau-to-Rialto headers sync entrypoint. use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, - SubstrateFinalitySyncPipeline, +use substrate_relay_helper::{ + finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; /// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] pub struct MillauFinalityToRialto; -impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { +impl SubstrateFinalityPipeline for MillauFinalityToRialto { type SourceChain = relay_millau_client::Millau; type TargetChain = relay_rialto_client::Rialto; type FinalityEngine = GrandpaFinalityEngine; +} + +impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< Self, rialto_runtime::Runtime, diff --git a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs index 7c979f5279567..c6ac05011f301 100644 --- a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs @@ -17,20 +17,23 @@ //! Rialto-to-Millau headers sync entrypoint. use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, - SubstrateFinalitySyncPipeline, +use substrate_relay_helper::{ + finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; /// Description of Millau -> Rialto finalized headers bridge. #[derive(Clone, Debug)] pub struct RialtoFinalityToMillau; -impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { +impl SubstrateFinalityPipeline for RialtoFinalityToMillau { type SourceChain = relay_rialto_client::Rialto; type TargetChain = relay_millau_client::Millau; type FinalityEngine = GrandpaFinalityEngine; +} + +impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< Self, millau_runtime::Runtime, diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs index d1c090c0797e0..79d3bde22fa75 100644 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs @@ -35,8 +35,9 @@ //! Millau-to-RialtoParachain headers sync entrypoint. use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline, +use substrate_relay_helper::{ + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; substrate_relay_helper::generate_submit_finality_proof_call_builder!( @@ -50,11 +51,14 @@ substrate_relay_helper::generate_submit_finality_proof_call_builder!( #[derive(Clone, Debug)] pub struct MillauFinalityToRialtoParachain; -impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { +impl SubstrateFinalityPipeline for MillauFinalityToRialtoParachain { type SourceChain = relay_millau_client::Millau; type TargetChain = relay_rialto_parachain_client::RialtoParachain; type FinalityEngine = GrandpaFinalityEngine; +} + +impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { type SubmitFinalityProofCallBuilder = MillauFinalityToRialtoParachainCallBuilder; } diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs index b7d17d931f843..906340633ab4c 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs @@ -21,7 +21,8 @@ use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, }; @@ -37,11 +38,15 @@ substrate_relay_helper::generate_submit_finality_proof_call_builder!( ); #[async_trait] -impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { +impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWococo { type SourceChain = relay_rococo_client::Rococo; type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { type SubmitFinalityProofCallBuilder = RococoFinalityToBridgeHubWococoCallBuilder; async fn start_relay_guards( diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs index 206c83b815314..418225d9bacab 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs @@ -21,7 +21,8 @@ use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ - finality::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalitySyncPipeline}, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, }; @@ -37,11 +38,15 @@ substrate_relay_helper::generate_submit_finality_proof_call_builder!( ); #[async_trait] -impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { +impl SubstrateFinalityPipeline for WococoFinalityToBridgeHubRococo { type SourceChain = relay_wococo_client::Wococo; type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { type SubmitFinalityProofCallBuilder = WococoFinalityToBridgeHubRococoCallBuilder; async fn start_relay_guards( diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs index 2a253756c2b98..eadbc3057045a 100644 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs @@ -17,20 +17,23 @@ //! Westend-to-Millau headers sync entrypoint. use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::finality::{ - engine::Grandpa as GrandpaFinalityEngine, DirectSubmitGrandpaFinalityProofCallBuilder, - SubstrateFinalitySyncPipeline, +use substrate_relay_helper::{ + finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; /// Description of Westend -> Millau finalized headers bridge. #[derive(Clone, Debug)] pub struct WestendFinalityToMillau; -impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { +impl SubstrateFinalityPipeline for WestendFinalityToMillau { type SourceChain = relay_westend_client::Westend; type TargetChain = relay_millau_client::Millau; type FinalityEngine = GrandpaFinalityEngine; +} + +impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< Self, millau_runtime::Runtime, diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index f297a8db6b44a..110d5e94f8b39 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -41,7 +41,7 @@ use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; -use substrate_relay_helper::finality::engine::{Engine, Grandpa as GrandpaFinalityEngine}; +use substrate_relay_helper::finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}; /// Initialize bridge pallet. #[derive(StructOpt)] diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 302f530eb4e96..767aefa5f2789 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -17,3 +17,4 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 477ea1b108f2d..2ea7fa39d0f07 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; use sp_core::storage::StorageKey; +use sp_session::MembershipProof; use std::time::Duration; /// Kusama header id. @@ -52,6 +53,8 @@ impl Chain for Kusama { impl ChainWithGrandpa for Kusama { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl ChainWithBalances for Kusama { diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index fe5482e5b6721..1cb759c5e3118 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -24,3 +24,4 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index 90def2d3bd5b6..b3101c980c557 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -27,6 +27,7 @@ use relay_substrate_client::{ }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use sp_session::MembershipProof; use std::time::Duration; /// Millau header id. @@ -69,6 +70,8 @@ impl Chain for Millau { impl ChainWithGrandpa for Millau { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl ChainWithBalances for Millau { diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 0d3a30949cbbb..7da3499a16bda 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -17,3 +17,4 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index a906944c8f498..6e39f985c6301 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; use sp_core::storage::StorageKey; +use sp_session::MembershipProof; use std::time::Duration; /// Polkadot header id. @@ -52,6 +53,8 @@ impl Chain for Polkadot { impl ChainWithGrandpa for Polkadot { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl ChainWithBalances for Polkadot { diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index c1ae0dfabe7ec..9b3a987387965 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -24,3 +24,4 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index c12d27bc1d916..cc5371612c346 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -27,6 +27,7 @@ use relay_substrate_client::{ }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use sp_session::MembershipProof; use std::time::Duration; /// Rialto header id. @@ -54,6 +55,8 @@ impl Chain for Rialto { impl ChainWithGrandpa for Rialto { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl RelayChain for Rialto { diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 2a5b556dce22c..c569ab4f27efd 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -17,3 +17,4 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index c4221e0dd004b..bf2cdd772271b 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; use sp_core::storage::StorageKey; +use sp_session::MembershipProof; use std::time::Duration; /// Rococo header id. @@ -52,6 +53,8 @@ impl Chain for Rococo { impl ChainWithGrandpa for Rococo { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl ChainWithBalances for Rococo { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index fe0ec3ebb0a36..fb99fc7af16f7 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -85,6 +85,9 @@ pub trait ChainWithGrandpa: Chain + UnderlyingChainWithGrandpaProvider { /// Keep in mind that this method is normally provided by the other chain, which is /// bridged with this chain. const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str; + + /// The type of the key owner proof used by the grandpa engine. + type KeyOwnerProof; } /// Substrate-based parachain from minimal relay-client point of view. diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 351013bd86446..9bc7d7adc099b 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -17,3 +17,4 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index e76bf65b82d89..674f4c71e82f8 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; use sp_core::storage::StorageKey; +use sp_session::MembershipProof; use std::time::Duration; /// Westend header id. @@ -52,6 +53,8 @@ impl Chain for Westend { impl ChainWithGrandpa for Westend { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl RelayChain for Westend { diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index 78a5afe17cabc..e545111c2f636 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -16,3 +16,4 @@ bp-wococo = { path = "../../primitives/chain-wococo" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index e4d23a27dcd39..f447fa6542e58 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, }; use sp_core::storage::StorageKey; +use sp_session::MembershipProof; use std::time::Duration; /// Wococo header id. @@ -52,6 +53,8 @@ impl Chain for Wococo { impl ChainWithGrandpa for Wococo { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = WOCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; } impl ChainWithBalances for Wococo { diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index d07aa936b57c6..869b6e00122ef 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -43,6 +43,7 @@ bp-messages = { path = "../../primitives/messages" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/lib-substrate-relay/src/equivocation/mod.rs b/relays/lib-substrate-relay/src/equivocation/mod.rs new file mode 100644 index 0000000000000..31668490f90c1 --- /dev/null +++ b/relays/lib-substrate-relay/src/equivocation/mod.rs @@ -0,0 +1,83 @@ +// Copyright 2019-2023 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 . + +//! Types and functions intended to ease adding of new Substrate -> Substrate +//! equivocation detection pipelines. + +use crate::finality_base::SubstrateFinalityPipeline; +use std::marker::PhantomData; + +use crate::finality_base::engine::Engine; +use async_trait::async_trait; +use bp_runtime::{BlockNumberOf, HashOf}; +use pallet_grandpa::{Call as GrandpaCall, Config as GrandpaConfig}; +use relay_substrate_client::CallOf; +use sp_runtime::traits::{Block, Header}; + +/// Substrate -> Substrate equivocation detection pipeline. +#[async_trait] +pub trait SubstrateEquivocationDetectionPipeline: SubstrateFinalityPipeline { + /// How the `report_equivocation` call is built ? + type ReportEquivocationCallBuilder: ReportEquivocationCallBuilder; +} + +type EquivocationProofOf

= <

::FinalityEngine as Engine< +

::SourceChain, +>>::EquivocationProof; +type KeyOwnerProofOf

= <

::FinalityEngine as Engine< +

::SourceChain, +>>::KeyOwnerProof; + +/// Different ways of building `report_equivocation` calls. +pub trait ReportEquivocationCallBuilder { + /// Build a `report_equivocation` call to be executed on the source chain. + fn build_report_equivocation_call( + equivocation_proof: EquivocationProofOf

, + key_owner_proof: KeyOwnerProofOf

, + ) -> CallOf; +} + +/// Building the `report_equivocation` call when having direct access to the target chain runtime. +pub struct DirectReportGrandpaEquivocationCallBuilder { + _phantom: PhantomData<(P, R)>, +} + +impl ReportEquivocationCallBuilder

for DirectReportGrandpaEquivocationCallBuilder +where + P: SubstrateEquivocationDetectionPipeline, + P::FinalityEngine: Engine< + P::SourceChain, + EquivocationProof = sp_consensus_grandpa::EquivocationProof< + HashOf, + BlockNumberOf, + >, + >, + R: frame_system::Config> + + GrandpaConfig>, + ::Header: Header>, + CallOf: From>, +{ + fn build_report_equivocation_call( + equivocation_proof: EquivocationProofOf

, + key_owner_proof: KeyOwnerProofOf

, + ) -> CallOf { + GrandpaCall::::report_equivocation { + equivocation_proof: Box::new(equivocation_proof), + key_owner_proof, + } + .into() + } +} diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/relays/lib-substrate-relay/src/finality/initialize.rs index 1b990f5dbda3e..5dde46c39dd67 100644 --- a/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/relays/lib-substrate-relay/src/finality/initialize.rs @@ -21,7 +21,7 @@ //! and authorities set from source to target chain. The finality sync starts //! with this header. -use crate::{error::Error, finality::engine::Engine}; +use crate::{error::Error, finality_base::engine::Engine}; use sp_core::Pair; use bp_runtime::HeaderIdOf; diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index 37ee61b48f1bd..bae49efe72e01 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -19,26 +19,25 @@ use crate::{ finality::{ - engine::Engine, source::{SubstrateFinalityProof, SubstrateFinalitySource}, target::SubstrateFinalityTarget, }, TransactionParams, }; +use crate::finality_base::{engine::Engine, SubstrateFinalityPipeline}; use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; use finality_relay::FinalitySyncPipeline; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, - ChainWithTransactions, Client, HashOf, HeaderOf, SyncHeader, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, + HashOf, HeaderOf, SyncHeader, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; use std::{fmt::Debug, marker::PhantomData}; -pub mod engine; pub mod initialize; pub mod source; pub mod target; @@ -51,14 +50,7 @@ pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; /// Substrate -> Substrate finality proofs synchronization pipeline. #[async_trait] -pub trait SubstrateFinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { - /// Headers of this chain are submitted to the `TargetChain`. - type SourceChain: Chain; - /// Headers of the `SourceChain` are submitted to this chain. - type TargetChain: ChainWithTransactions; - - /// Finality engine. - type FinalityEngine: Engine; +pub trait SubstrateFinalitySyncPipeline: SubstrateFinalityPipeline { /// How submit finality proof call is built? type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder; @@ -144,16 +136,16 @@ macro_rules! generate_submit_finality_proof_call_builder { fn build_submit_finality_proof_call( header: relay_substrate_client::SyncHeader< relay_substrate_client::HeaderOf< - <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::SourceChain + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain > >, proof: bp_header_chain::justification::GrandpaJustification< relay_substrate_client::HeaderOf< - <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::SourceChain + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain > >, ) -> relay_substrate_client::CallOf< - <$pipeline as $crate::finality::SubstrateFinalitySyncPipeline>::TargetChain + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::TargetChain > { bp_runtime::paste::item! { $bridge_grandpa($submit_finality_proof { diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index 6227263902ae6..208299f9cb2bf 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -16,8 +16,12 @@ //! Default generic implementation of finality source for basic Substrate client. -use crate::finality::{engine::Engine, FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}; +use crate::{ + finality::{FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}, + finality_base::engine::Engine, +}; +use crate::finality_base::SubstrateFinalityPipeline; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::FinalityProof; @@ -42,10 +46,9 @@ pub type SubstrateFinalityProofsStream

= Pin> + Send>>; /// Substrate finality proof. Specific to the used `FinalityEngine`. -pub type SubstrateFinalityProof

= - <

::FinalityEngine as Engine< -

::SourceChain, - >>::FinalityProof; +pub type SubstrateFinalityProof

= <

::FinalityEngine as Engine< +

::SourceChain, +>>::FinalityProof; /// Substrate node as finality source. pub struct SubstrateFinalitySource { diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 2d9d4b856e025..3d1fa780eaefb 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -18,9 +18,10 @@ use crate::{ finality::{ - engine::Engine, source::SubstrateFinalityProof, FinalitySyncPipelineAdapter, + source::SubstrateFinalityProof, FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }, + finality_base::engine::Engine, TransactionParams, }; diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs similarity index 97% rename from relays/lib-substrate-relay/src/finality/engine.rs rename to relays/lib-substrate-relay/src/finality_base/engine.rs index 0092db969925c..dc84ebaa4d5c6 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -47,6 +47,10 @@ pub trait Engine: Send { type FinalityClient: SubstrateFinalityClient; /// Type of finality proofs, used by consensus engine. type FinalityProof: FinalityProof> + Decode + Encode; + /// The type of the equivocation proof used by the consensus engine. + type EquivocationProof; + /// The type of the key owner proof used by the consensus engine. + type KeyOwnerProof; /// Type of bridge pallet initialization data. type InitializationData: std::fmt::Debug + Send + Sync + 'static; /// Type of bridge pallet operating mode. @@ -138,6 +142,8 @@ impl Engine for Grandpa { type ConsensusLogReader = GrandpaConsensusLogReader<::Number>; type FinalityClient = SubstrateGrandpaFinalityClient; type FinalityProof = GrandpaJustification>; + type EquivocationProof = sp_consensus_grandpa::EquivocationProof, BlockNumberOf>; + type KeyOwnerProof = C::KeyOwnerProof; type InitializationData = bp_header_chain::InitializationData; type OperatingMode = BasicOperatingMode; diff --git a/relays/lib-substrate-relay/src/finality_base/mod.rs b/relays/lib-substrate-relay/src/finality_base/mod.rs new file mode 100644 index 0000000000000..e48f82480325a --- /dev/null +++ b/relays/lib-substrate-relay/src/finality_base/mod.rs @@ -0,0 +1,35 @@ +// Copyright 2019-2023 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 . + +//! Types and functions intended to ease adding of new Substrate -> Substrate +//! finality pipelines. + +pub mod engine; + +use async_trait::async_trait; +use relay_substrate_client::{Chain, ChainWithTransactions}; +use std::fmt::Debug; + +/// Substrate -> Substrate finality related pipeline. +#[async_trait] +pub trait SubstrateFinalityPipeline: 'static + Clone + Debug + Send + Sync { + /// Headers of this chain are submitted to the `TargetChain`. + type SourceChain: Chain; + /// Headers of the `SourceChain` are submitted to this chain. + type TargetChain: ChainWithTransactions; + /// Finality engine. + type FinalityEngine: engine::Engine; +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index f9bd80d50793c..50a89e90e2dcd 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -22,8 +22,10 @@ use relay_substrate_client::{Chain, ChainWithUtilityPallet, UtilityPallet}; use std::marker::PhantomData; +pub mod equivocation; pub mod error; pub mod finality; +pub mod finality_base; pub mod messages_lane; pub mod messages_metrics; pub mod messages_source; diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 1dfc544703c88..5014851a5b2f3 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -38,11 +38,11 @@ use relay_utils::{ use crate::{ finality::{ - engine::Engine, source::{RequiredHeaderNumberRef, SubstrateFinalitySource}, target::SubstrateFinalityTarget, SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT, }, + finality_base::engine::Engine, on_demand::OnDemandRelay, TransactionParams, }; From 61dd6d47b92811ac7e1943aafc748a5294de92f5 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 16 Aug 2023 08:20:09 +0300 Subject: [PATCH 1091/1210] Add equivocation detector crate and implement clients (#2348) (#2353) * Split FinalitySyncPipeline and SourceClient * Move some logic to finality_base * Add empty equivocation detection clients * Add equivocation reporting logic to the source client * Use convenience trait for SubstrateFinalitySyncPipeline * Define JustificationVerificationContext for GRANDPA * Equivocation source client: finality_verification_context() * Equivocation source client: synced_headers_finality_info() * reuse HeaderFinalityInfo * Define EquivocationsFinder * Fix spellcheck * Address review comments * Avoid equivocations lookup errors --- bin/millau/runtime/src/lib.rs | 4 +- bin/rialto-parachain/runtime/src/lib.rs | 2 +- bin/rialto/runtime/src/lib.rs | 2 +- modules/grandpa/src/lib.rs | 48 ++--- modules/parachains/src/lib.rs | 26 +-- .../header-chain/src/justification/mod.rs | 5 +- .../verification/equivocation.rs | 110 ++++++----- .../src/justification/verification/mod.rs | 31 +++- .../justification/verification/optimizer.rs | 17 +- .../src/justification/verification/strict.rs | 17 +- primitives/header-chain/src/lib.rs | 71 ++++++-- .../tests/implementation_match.rs | 34 ++-- .../tests/justification/equivocation.rs | 16 +- .../tests/justification/optimizer.rs | 21 +-- .../tests/justification/strict.rs | 28 +-- primitives/runtime/src/chain.rs | 2 +- primitives/test-utils/src/keyring.rs | 8 +- relays/bin-substrate/src/cli/relay_headers.rs | 7 +- relays/client-substrate/src/chain.rs | 9 +- relays/client-substrate/src/client.rs | 15 +- relays/equivocation/Cargo.toml | 13 ++ relays/equivocation/src/lib.rs | 70 +++++++ relays/finality/src/base.rs | 51 ++++++ relays/finality/src/finality_loop.rs | 17 +- relays/finality/src/finality_loop_tests.rs | 28 +-- relays/finality/src/lib.rs | 17 +- relays/lib-substrate-relay/Cargo.toml | 1 + .../src/equivocation/mod.rs | 78 +++++++- .../src/equivocation/source.rs | 101 ++++++++++ .../src/equivocation/target.rs | 86 +++++++++ .../lib-substrate-relay/src/finality/mod.rs | 49 +++-- .../src/finality/source.rs | 74 ++------ .../src/finality/target.rs | 14 +- .../src/finality_base/engine.rs | 172 ++++++++++++++---- .../src/finality_base/mod.rs | 60 +++++- 35 files changed, 930 insertions(+), 374 deletions(-) create mode 100644 relays/equivocation/Cargo.toml create mode 100644 relays/equivocation/src/lib.rs create mode 100644 relays/finality/src/base.rs create mode 100644 relays/lib-substrate-relay/src/equivocation/source.rs create mode 100644 relays/lib-substrate-relay/src/equivocation/target.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 75f82c5343981..a1526bc2e1810 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -884,7 +884,7 @@ impl_runtime_apis! { } fn synced_headers_grandpa_info( - ) -> Vec> { + ) -> Vec> { BridgeRialtoGrandpa::synced_headers_grandpa_info() } } @@ -895,7 +895,7 @@ impl_runtime_apis! { } fn synced_headers_grandpa_info( - ) -> Vec> { + ) -> Vec> { BridgeWestendGrandpa::synced_headers_grandpa_info() } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index eb15806b4e39e..cae840de96744 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -748,7 +748,7 @@ impl_runtime_apis! { } fn synced_headers_grandpa_info( - ) -> Vec> { + ) -> Vec> { BridgeMillauGrandpa::synced_headers_grandpa_info() } } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 8af330b328b6a..dbfa0cf7eb614 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -696,7 +696,7 @@ impl_runtime_apis! { } fn synced_headers_grandpa_info( - ) -> Vec> { + ) -> Vec> { BridgeMillauGrandpa::synced_headers_grandpa_info() } } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 259a6c0f36b79..425712ad9a20e 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -40,10 +40,10 @@ pub use storage_types::StoredAuthoritySet; use bp_header_chain::{ justification::GrandpaJustification, AuthoritySet, ChainWithGrandpa, GrandpaConsensusLogReader, - HeaderChain, HeaderGrandpaInfo, InitializationData, StoredHeaderData, StoredHeaderDataBuilder, + HeaderChain, InitializationData, StoredHeaderData, StoredHeaderDataBuilder, + StoredHeaderGrandpaInfo, }; use bp_runtime::{BlockNumberOf, HashOf, HasherOf, HeaderId, HeaderOf, OwnedBridgeModule}; -use finality_grandpa::voter_set::VoterSet; use frame_support::{dispatch::PostDispatchInfo, ensure, DefaultNoBound}; use sp_runtime::{ traits::{Header as HeaderT, Zero}, @@ -241,9 +241,9 @@ pub mod pallet { Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash, - grandpa_info: HeaderGrandpaInfo { - justification, - authority_set: maybe_new_authority_set, + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification, + new_verification_context: maybe_new_authority_set, }, }); @@ -411,7 +411,7 @@ pub mod pallet { number: BridgedBlockNumber, hash: BridgedBlockHash, /// The Grandpa info associated to the new best finalized header. - grandpa_info: HeaderGrandpaInfo>, + grandpa_info: StoredHeaderGrandpaInfo>, }, } @@ -505,14 +505,9 @@ pub mod pallet { ) -> Result<(), sp_runtime::DispatchError> { use bp_header_chain::justification::verify_justification; - let voter_set = - VoterSet::new(authority_set.authorities).ok_or(>::InvalidAuthoritySet)?; - let set_id = authority_set.set_id; - Ok(verify_justification::>( (hash, number), - set_id, - &voter_set, + &authority_set.try_into().map_err(|_| >::InvalidAuthoritySet)?, justification, ) .map_err(|e| { @@ -617,7 +612,7 @@ where ::RuntimeEvent: TryInto>, { /// Get the GRANDPA justifications accepted in the current block. - pub fn synced_headers_grandpa_info() -> Vec>> { + pub fn synced_headers_grandpa_info() -> Vec>> { frame_system::Pallet::::read_events_no_consensus() .filter_map(|event| { if let Event::::UpdatedBestFinalizedHeader { grandpa_info, .. } = @@ -934,9 +929,9 @@ mod tests { event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { number: *header.number(), hash: header.hash(), - grandpa_info: HeaderGrandpaInfo { - justification: justification.clone(), - authority_set: None, + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification.clone(), + new_verification_context: None, }, }), topics: vec![], @@ -944,7 +939,10 @@ mod tests { ); assert_eq!( Pallet::::synced_headers_grandpa_info(), - vec![HeaderGrandpaInfo { justification, authority_set: None }] + vec![StoredHeaderGrandpaInfo { + finality_proof: justification, + new_verification_context: None + }] ); }) } @@ -1075,9 +1073,11 @@ mod tests { event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { number: *header.number(), hash: header.hash(), - grandpa_info: HeaderGrandpaInfo { - justification: justification.clone(), - authority_set: Some(>::get().into()), + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification.clone(), + new_verification_context: Some( + >::get().into() + ), }, }), topics: vec![], @@ -1085,9 +1085,11 @@ mod tests { ); assert_eq!( Pallet::::synced_headers_grandpa_info(), - vec![HeaderGrandpaInfo { - justification, - authority_set: Some(>::get().into()), + vec![StoredHeaderGrandpaInfo { + finality_proof: justification, + new_verification_context: Some( + >::get().into() + ), }] ); }) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 24bc3535e619e..be46fae3c9253 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -697,7 +697,7 @@ pub(crate) mod tests { use bp_test_utils::prepare_parachain_heads_proof; use codec::Encode; - use bp_header_chain::{justification::GrandpaJustification, HeaderGrandpaInfo}; + use bp_header_chain::{justification::GrandpaJustification, StoredHeaderGrandpaInfo}; use bp_parachains::{ BestParaHeadHash, BridgeParachainCall, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider, }; @@ -1036,9 +1036,9 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - grandpa_info: HeaderGrandpaInfo { - justification, - authority_set: None, + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification, + new_verification_context: None, }, } ), @@ -1177,9 +1177,9 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - grandpa_info: HeaderGrandpaInfo { - justification, - authority_set: None, + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification, + new_verification_context: None, } } ), @@ -1230,9 +1230,9 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - grandpa_info: HeaderGrandpaInfo { - justification: justification.clone(), - authority_set: None, + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification.clone(), + new_verification_context: None, } } ), @@ -1271,9 +1271,9 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, - grandpa_info: HeaderGrandpaInfo { - justification, - authority_set: None, + grandpa_info: StoredHeaderGrandpaInfo { + finality_proof: justification, + new_verification_context: None, } } ), diff --git a/primitives/header-chain/src/justification/mod.rs b/primitives/header-chain/src/justification/mod.rs index 17be6cfd79611..5fa5d7d607c8a 100644 --- a/primitives/header-chain/src/justification/mod.rs +++ b/primitives/header-chain/src/justification/mod.rs @@ -23,10 +23,11 @@ mod verification; use crate::ChainWithGrandpa; pub use verification::{ - equivocation::{EquivocationsCollector, Error as EquivocationsCollectorError}, + equivocation::{EquivocationsCollector, GrandpaEquivocationsFinder}, optimizer::verify_and_optimize_justification, strict::verify_justification, - AncestryChain, Error as JustificationVerificationError, PrecommitError, + AncestryChain, Error as JustificationVerificationError, JustificationVerificationContext, + PrecommitError, }; use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId}; diff --git a/primitives/header-chain/src/justification/verification/equivocation.rs b/primitives/header-chain/src/justification/verification/equivocation.rs index 0ade3736c2274..2484fc4d6b2bf 100644 --- a/primitives/header-chain/src/justification/verification/equivocation.rs +++ b/primitives/header-chain/src/justification/verification/equivocation.rs @@ -16,33 +16,26 @@ //! Logic for extracting equivocations from multiple GRANDPA Finality Proofs. -use crate::justification::{ - verification::{ - Error as JustificationVerificationError, JustificationVerifier, PrecommitError, - SignedPrecommit, +use crate::{ + justification::{ + verification::{ + Error as JustificationVerificationError, IterationFlow, + JustificationVerificationContext, JustificationVerifier, PrecommitError, + SignedPrecommit, + }, + GrandpaJustification, }, - GrandpaJustification, + ChainWithGrandpa, FindEquivocations, }; -use crate::justification::verification::IterationFlow; -use finality_grandpa::voter_set::VoterSet; -use frame_support::RuntimeDebug; -use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, EquivocationProof, Precommit, SetId}; +use bp_runtime::{BlockNumberOf, HashOf, HeaderOf}; +use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, EquivocationProof, Precommit}; use sp_runtime::traits::Header as HeaderT; use sp_std::{ collections::{btree_map::BTreeMap, btree_set::BTreeSet}, prelude::*, }; -/// Justification verification error. -#[derive(Eq, RuntimeDebug, PartialEq)] -pub enum Error { - /// Justification is targeting unexpected round. - InvalidRound, - /// Justification verification error. - JustificationVerification(JustificationVerificationError), -} - enum AuthorityVotes { SingleVote(SignedPrecommit

), Equivocation( @@ -53,8 +46,7 @@ enum AuthorityVotes { /// Structure that can extract equivocations from multiple GRANDPA justifications. pub struct EquivocationsCollector<'a, Header: HeaderT> { round: u64, - authorities_set_id: SetId, - authorities_set: &'a VoterSet, + context: &'a JustificationVerificationContext, votes: BTreeMap>, } @@ -62,38 +54,34 @@ pub struct EquivocationsCollector<'a, Header: HeaderT> { impl<'a, Header: HeaderT> EquivocationsCollector<'a, Header> { /// Create a new instance of `EquivocationsCollector`. pub fn new( - authorities_set_id: SetId, - authorities_set: &'a VoterSet, + context: &'a JustificationVerificationContext, base_justification: &GrandpaJustification
, - ) -> Result { - let mut checker = Self { - round: base_justification.round, - authorities_set_id, - authorities_set, - votes: BTreeMap::new(), - }; - - checker.parse_justification(base_justification)?; + ) -> Result { + let mut checker = Self { round: base_justification.round, context, votes: BTreeMap::new() }; + + checker.verify_justification( + (base_justification.commit.target_hash, base_justification.commit.target_number), + checker.context, + base_justification, + )?; + Ok(checker) } - /// Parse an additional justification for equivocations. - pub fn parse_justification( - &mut self, - justification: &GrandpaJustification
, - ) -> Result<(), Error> { - // The justification should target the same round as the base justification. - if self.round != justification.round { - return Err(Error::InvalidRound) + /// Parse additional justifications for equivocations. + pub fn parse_justifications(&mut self, justifications: &[GrandpaJustification
]) { + let round = self.round; + for justification in + justifications.iter().filter(|justification| round == justification.round) + { + // We ignore the Errors received here since we don't care if the proofs are valid. + // We only care about collecting equivocations. + let _ = self.verify_justification( + (justification.commit.target_hash, justification.commit.target_number), + self.context, + justification, + ); } - - self.verify_justification( - (justification.commit.target_hash, justification.commit.target_number), - self.authorities_set_id, - self.authorities_set, - justification, - ) - .map_err(Error::JustificationVerification) } /// Extract the equivocation proofs that have been collected. @@ -102,7 +90,7 @@ impl<'a, Header: HeaderT> EquivocationsCollector<'a, Header> { for (_authority, vote) in self.votes { if let AuthorityVotes::Equivocation(equivocation) = vote { equivocations.push(EquivocationProof::new( - self.authorities_set_id, + self.context.authority_set_id, sp_consensus_grandpa::Equivocation::Precommit(equivocation), )); } @@ -177,3 +165,29 @@ impl<'a, Header: HeaderT> JustificationVerifier
for EquivocationsCollect Ok(()) } } + +/// Helper struct for finding equivocations in GRANDPA proofs. +pub struct GrandpaEquivocationsFinder(sp_std::marker::PhantomData); + +impl + FindEquivocations< + GrandpaJustification>, + JustificationVerificationContext, + EquivocationProof, BlockNumberOf>, + > for GrandpaEquivocationsFinder +{ + type Error = JustificationVerificationError; + + fn find_equivocations( + verification_context: &JustificationVerificationContext, + synced_proof: &GrandpaJustification>, + source_proofs: &[GrandpaJustification>], + ) -> Result, BlockNumberOf>>, Self::Error> { + let mut equivocations_collector = + EquivocationsCollector::new(verification_context, synced_proof)?; + + equivocations_collector.parse_justifications(source_proofs); + + Ok(equivocations_collector.into_equivocation_proofs()) + } +} diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/primitives/header-chain/src/justification/verification/mod.rs index 7cec1f14e966e..7af5292256cb8 100644 --- a/primitives/header-chain/src/justification/verification/mod.rs +++ b/primitives/header-chain/src/justification/verification/mod.rs @@ -20,7 +20,7 @@ pub mod equivocation; pub mod optimizer; pub mod strict; -use crate::justification::GrandpaJustification; +use crate::{justification::GrandpaJustification, AuthoritySet}; use bp_runtime::HeaderId; use finality_grandpa::voter_set::VoterSet; @@ -114,6 +114,8 @@ impl AncestryChain
{ /// Justification verification error. #[derive(Eq, RuntimeDebug, PartialEq)] pub enum Error { + /// Could not convert `AuthorityList` to `VoterSet`. + InvalidAuthorityList, /// Justification is finalizing unexpected header. InvalidJustificationTarget, /// Error validating a precommit @@ -141,6 +143,24 @@ pub enum PrecommitError { UnrelatedAncestryVote, } +/// The context needed for validating GRANDPA finality proofs. +pub struct JustificationVerificationContext { + /// The authority set used to verify the justification. + pub voter_set: VoterSet, + /// The ID of the authority set used to verify the justification. + pub authority_set_id: SetId, +} + +impl TryFrom for JustificationVerificationContext { + type Error = Error; + + fn try_from(authority_set: AuthoritySet) -> Result { + let voter_set = + VoterSet::new(authority_set.authorities).ok_or(Error::InvalidAuthorityList)?; + Ok(JustificationVerificationContext { voter_set, authority_set_id: authority_set.set_id }) + } +} + enum IterationFlow { Run, Skip, @@ -185,8 +205,7 @@ trait JustificationVerifier { fn verify_justification( &mut self, finalized_target: (Header::Hash, Header::Number), - authorities_set_id: SetId, - authorities_set: &VoterSet, + context: &JustificationVerificationContext, justification: &GrandpaJustification
, ) -> Result<(), Error> { // ensure that it is justification for the expected header @@ -196,7 +215,7 @@ trait JustificationVerifier { return Err(Error::InvalidJustificationTarget) } - let threshold = authorities_set.threshold().get(); + let threshold = context.voter_set.threshold().get(); let mut chain = AncestryChain::new(justification); let mut signature_buffer = Vec::new(); let mut cumulative_weight = 0u64; @@ -211,7 +230,7 @@ trait JustificationVerifier { } // authority must be in the set - let authority_info = match authorities_set.get(&signed.id) { + let authority_info = match context.voter_set.get(&signed.id) { Some(authority_info) => { // The implementer may want to do extra checks here. // For example to see if the authority has already voted in the same round. @@ -248,7 +267,7 @@ trait JustificationVerifier { &signed.id, &signed.signature, justification.round, - authorities_set_id, + context.authority_set_id, &mut signature_buffer, ) { self.process_invalid_signature_vote(precommit_idx).map_err(Error::Precommit)?; diff --git a/primitives/header-chain/src/justification/verification/optimizer.rs b/primitives/header-chain/src/justification/verification/optimizer.rs index 4cc6778ff511e..99ccdd50616b0 100644 --- a/primitives/header-chain/src/justification/verification/optimizer.rs +++ b/primitives/header-chain/src/justification/verification/optimizer.rs @@ -21,9 +21,10 @@ use crate::justification::{ GrandpaJustification, }; -use crate::justification::verification::{IterationFlow, SignedPrecommit}; -use finality_grandpa::voter_set::VoterSet; -use sp_consensus_grandpa::{AuthorityId, SetId}; +use crate::justification::verification::{ + IterationFlow, JustificationVerificationContext, SignedPrecommit, +}; +use sp_consensus_grandpa::AuthorityId; use sp_runtime::traits::Header as HeaderT; use sp_std::{collections::btree_set::BTreeSet, prelude::*}; @@ -111,8 +112,7 @@ impl JustificationVerifier
for JustificationOptimizer( finalized_target: (Header::Hash, Header::Number), - authorities_set_id: SetId, - authorities_set: &VoterSet, + context: &JustificationVerificationContext, justification: &mut GrandpaJustification
, ) -> Result<(), Error> { let mut optimizer = JustificationOptimizer { @@ -120,12 +120,7 @@ pub fn verify_and_optimize_justification( extra_precommits: vec![], redundant_votes_ancestries: Default::default(), }; - optimizer.verify_justification( - finalized_target, - authorities_set_id, - authorities_set, - justification, - )?; + optimizer.verify_justification(finalized_target, context, justification)?; optimizer.optimize(justification); Ok(()) diff --git a/primitives/header-chain/src/justification/verification/strict.rs b/primitives/header-chain/src/justification/verification/strict.rs index da936c2358277..a9d5f4c1f7362 100644 --- a/primitives/header-chain/src/justification/verification/strict.rs +++ b/primitives/header-chain/src/justification/verification/strict.rs @@ -21,9 +21,10 @@ use crate::justification::{ GrandpaJustification, }; -use crate::justification::verification::{IterationFlow, SignedPrecommit}; -use finality_grandpa::voter_set::VoterSet; -use sp_consensus_grandpa::{AuthorityId, SetId}; +use crate::justification::verification::{ + IterationFlow, JustificationVerificationContext, SignedPrecommit, +}; +use sp_consensus_grandpa::AuthorityId; use sp_runtime::traits::Header as HeaderT; use sp_std::collections::btree_set::BTreeSet; @@ -92,15 +93,9 @@ impl JustificationVerifier
for StrictJustificationVerif /// Verify that justification, that is generated by given authority set, finalizes given header. pub fn verify_justification( finalized_target: (Header::Hash, Header::Number), - authorities_set_id: SetId, - authorities_set: &VoterSet, + context: &JustificationVerificationContext, justification: &GrandpaJustification
, ) -> Result<(), Error> { let mut verifier = StrictJustificationVerifier { votes: BTreeSet::new() }; - verifier.verify_justification( - finalized_target, - authorities_set_id, - authorities_set, - justification, - ) + verifier.verify_justification(finalized_target, context, justification) } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 720dafdd93b09..ea6c58f4c0979 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -19,6 +19,9 @@ #![cfg_attr(not(feature = "std"), no_std)] +use crate::justification::{ + GrandpaJustification, JustificationVerificationContext, JustificationVerificationError, +}; use bp_runtime::{ BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker, StorageProofError, UnderlyingChainProvider, @@ -30,7 +33,7 @@ use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_consensus_grandpa::{AuthorityList, ConsensusLog, SetId, GRANDPA_ENGINE_ID}; use sp_runtime::{traits::Header as HeaderT, Digest, RuntimeDebug}; -use sp_std::boxed::Box; +use sp_std::{boxed::Box, vec::Vec}; pub mod justification; pub mod storage_keys; @@ -172,13 +175,48 @@ impl ConsensusLogReader for GrandpaConsensusLogReader { } } -/// The Grandpa-related info associated to a header. +/// The finality-related info associated to a header. #[derive(Encode, Decode, Debug, PartialEq, Clone, TypeInfo)] -pub struct HeaderGrandpaInfo { - /// The header justification - pub justification: justification::GrandpaJustification
, - /// The authority set introduced by the header. - pub authority_set: Option, +pub struct HeaderFinalityInfo { + /// The header finality proof. + pub finality_proof: FinalityProof, + /// The new verification context introduced by the header. + pub new_verification_context: Option, +} + +/// Grandpa-related info associated to a header. This info can be saved to events. +pub type StoredHeaderGrandpaInfo
= + HeaderFinalityInfo, AuthoritySet>; + +/// Processed Grandpa-related info associated to a header. +pub type HeaderGrandpaInfo
= + HeaderFinalityInfo, JustificationVerificationContext>; + +impl TryFrom> for HeaderGrandpaInfo
{ + type Error = JustificationVerificationError; + + fn try_from(grandpa_info: StoredHeaderGrandpaInfo
) -> Result { + Ok(Self { + finality_proof: grandpa_info.finality_proof, + new_verification_context: match grandpa_info.new_verification_context { + Some(authority_set) => Some(authority_set.try_into()?), + None => None, + }, + }) + } +} + +/// Helper trait for finding equivocations in finality proofs. +pub trait FindEquivocations { + /// The type returned when encountering an error while looking for equivocations. + type Error; + + /// Find equivocations. + fn find_equivocations( + verification_context: &FinalityVerificationContext, + synced_proof: &FinalityProof, + source_proofs: &[FinalityProof], + ) -> Result, Self::Error>; } /// A minimized version of `pallet-bridge-grandpa::Call` that can be used without a runtime. @@ -244,16 +282,17 @@ pub trait ChainWithGrandpa: Chain { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; } -/// A trait that provides the type of the underlying `ChainWithGrandpa`. -pub trait UnderlyingChainWithGrandpaProvider: UnderlyingChainProvider { - /// Underlying `ChainWithGrandpa` type. - type ChainWithGrandpa: ChainWithGrandpa; -} - -impl UnderlyingChainWithGrandpaProvider for T +impl ChainWithGrandpa for T where - T: UnderlyingChainProvider, + T: Chain + UnderlyingChainProvider, T::Chain: ChainWithGrandpa, { - type ChainWithGrandpa = T::Chain; + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + ::WITH_CHAIN_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = ::MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + ::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = ::MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = + ::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index c4cd7f5f5b26e..db96961832d4b 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -22,14 +22,15 @@ //! but their purpose is different. use bp_header_chain::justification::{ - verify_justification, GrandpaJustification, JustificationVerificationError, PrecommitError, + verify_justification, GrandpaJustification, JustificationVerificationContext, + JustificationVerificationError, PrecommitError, }; use bp_test_utils::{ header_id, make_justification_for_header, signed_precommit, test_header, Account, JustificationGeneratorParams, ALICE, BOB, CHARLIE, DAVE, EVE, FERDIE, TEST_GRANDPA_SET_ID, }; use finality_grandpa::voter_set::VoterSet; -use sp_consensus_grandpa::{AuthorityId, AuthorityWeight}; +use sp_consensus_grandpa::{AuthorityId, AuthorityWeight, SetId}; use sp_runtime::traits::Header as HeaderT; type TestHeader = sp_runtime::testing::Header; @@ -81,6 +82,11 @@ fn full_voter_set() -> VoterSet { VoterSet::new(full_accounts_set().iter().map(|(id, w)| (AuthorityId::from(*id), *w))).unwrap() } +pub fn full_verification_context(set_id: SetId) -> JustificationVerificationContext { + let voter_set = full_voter_set(); + JustificationVerificationContext { voter_set, authority_set_id: set_id } +} + /// Get a minimal set of accounts. fn minimal_accounts_set() -> Vec<(Account, AuthorityWeight)> { // there are 5 accounts in the full set => we need 2/3 + 1 accounts, which results in 4 accounts @@ -115,8 +121,7 @@ fn same_result_when_precommit_target_has_lower_number_than_commit_target() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::UnrelatedAncestryVote)), @@ -148,8 +153,7 @@ fn same_result_when_precommit_target_is_not_descendant_of_commit_target() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::UnrelatedAncestryVote)), @@ -182,8 +186,7 @@ fn same_result_when_there_are_not_enough_cumulative_weight_to_finalize_commit_ta assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::TooLowCumulativeWeight), @@ -220,8 +223,7 @@ fn different_result_when_justification_contains_duplicate_vote() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)), @@ -261,8 +263,7 @@ fn different_results_when_authority_equivocates_once_in_a_round() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)), @@ -314,8 +315,7 @@ fn different_results_when_authority_equivocates_twice_in_a_round() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::DuplicateAuthorityVote)), @@ -353,8 +353,7 @@ fn different_results_when_there_are_more_than_enough_votes() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::RedundantAuthorityVote)), @@ -394,8 +393,7 @@ fn different_results_when_there_is_a_vote_of_unknown_authority() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &full_voter_set(), + &full_verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::UnknownAuthorityVote)), diff --git a/primitives/header-chain/tests/justification/equivocation.rs b/primitives/header-chain/tests/justification/equivocation.rs index 072d5668edeb4..f3c133481fb89 100644 --- a/primitives/header-chain/tests/justification/equivocation.rs +++ b/primitives/header-chain/tests/justification/equivocation.rs @@ -25,19 +25,18 @@ type TestHeader = sp_runtime::testing::Header; #[test] fn duplicate_votes_are_not_considered_equivocations() { - let voter_set = voter_set(); + let verification_context = verification_context(TEST_GRANDPA_SET_ID); let base_justification = make_default_justification::(&test_header(1)); let mut collector = - EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap(); - collector.parse_justification(&base_justification.clone()).unwrap(); + EquivocationsCollector::new(&verification_context, &base_justification).unwrap(); + collector.parse_justifications(&[base_justification.clone()]); assert_eq!(collector.into_equivocation_proofs().len(), 0); } #[test] fn equivocations_are_detected_in_base_justification_redundant_votes() { - let voter_set = voter_set(); let mut base_justification = make_default_justification::(&test_header(1)); let first_vote = base_justification.commit.precommits[0].clone(); @@ -49,8 +48,9 @@ fn equivocations_are_detected_in_base_justification_redundant_votes() { ); base_justification.commit.precommits.push(equivocation.clone()); + let verification_context = verification_context(TEST_GRANDPA_SET_ID); let collector = - EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap(); + EquivocationsCollector::new(&verification_context, &base_justification).unwrap(); assert_eq!( collector.into_equivocation_proofs(), @@ -80,7 +80,6 @@ fn equivocations_are_detected_in_base_justification_redundant_votes() { #[test] fn equivocations_are_detected_in_extra_justification_redundant_votes() { - let voter_set = voter_set(); let base_justification = make_default_justification::(&test_header(1)); let first_vote = base_justification.commit.precommits[0].clone(); @@ -93,9 +92,10 @@ fn equivocations_are_detected_in_extra_justification_redundant_votes() { ); extra_justification.commit.precommits.push(equivocation.clone()); + let verification_context = verification_context(TEST_GRANDPA_SET_ID); let mut collector = - EquivocationsCollector::new(TEST_GRANDPA_SET_ID, &voter_set, &base_justification).unwrap(); - collector.parse_justification(&extra_justification).unwrap(); + EquivocationsCollector::new(&verification_context, &base_justification).unwrap(); + collector.parse_justifications(&[extra_justification]); assert_eq!( collector.into_equivocation_proofs(), diff --git a/primitives/header-chain/tests/justification/optimizer.rs b/primitives/header-chain/tests/justification/optimizer.rs index 8d1ba5ac6facb..bdc90a3b07cf6 100644 --- a/primitives/header-chain/tests/justification/optimizer.rs +++ b/primitives/header-chain/tests/justification/optimizer.rs @@ -30,8 +30,7 @@ fn optimizer_does_noting_with_minimal_justification() { let num_precommits_before = justification.commit.precommits.len(); verify_and_optimize_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); @@ -53,8 +52,7 @@ fn unknown_authority_votes_are_removed_by_optimizer() { let num_precommits_before = justification.commit.precommits.len(); verify_and_optimize_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); @@ -74,8 +72,7 @@ fn duplicate_authority_votes_are_removed_by_optimizer() { let num_precommits_before = justification.commit.precommits.len(); verify_and_optimize_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); @@ -105,8 +102,7 @@ fn invalid_authority_signatures_are_removed_by_optimizer() { let num_precommits_before = justification.commit.precommits.len(); verify_and_optimize_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); @@ -128,8 +124,7 @@ fn redundant_authority_votes_are_removed_by_optimizer() { let num_precommits_before = justification.commit.precommits.len(); verify_and_optimize_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); @@ -154,8 +149,7 @@ fn unrelated_ancestry_votes_are_removed_by_optimizer() { let num_precommits_before = justification.commit.precommits.len(); verify_and_optimize_justification::( header_id::(2), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); @@ -172,8 +166,7 @@ fn redundant_votes_ancestries_are_removed_by_optimizer() { let num_votes_ancestries_before = justification.votes_ancestries.len(); verify_and_optimize_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &mut justification, ) .unwrap(); diff --git a/primitives/header-chain/tests/justification/strict.rs b/primitives/header-chain/tests/justification/strict.rs index bf8fa5c9f4579..9568f7f7cf9a3 100644 --- a/primitives/header-chain/tests/justification/strict.rs +++ b/primitives/header-chain/tests/justification/strict.rs @@ -17,8 +17,8 @@ //! Tests for Grandpa strict justification verifier code. use bp_header_chain::justification::{ - required_justification_precommits, verify_justification, JustificationVerificationError, - PrecommitError, + required_justification_precommits, verify_justification, JustificationVerificationContext, + JustificationVerificationError, PrecommitError, }; use bp_test_utils::*; @@ -40,8 +40,7 @@ fn valid_justification_accepted() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &justification, ), Ok(()), @@ -65,8 +64,7 @@ fn valid_justification_accepted_with_single_fork() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &make_justification_for_header::(params) ), Ok(()), @@ -100,8 +98,7 @@ fn valid_justification_accepted_with_arbitrary_number_of_authorities() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set, + &JustificationVerificationContext { voter_set, authority_set_id: TEST_GRANDPA_SET_ID }, &make_justification_for_header::(params) ), Ok(()), @@ -113,8 +110,7 @@ fn justification_with_invalid_target_rejected() { assert_eq!( verify_justification::( header_id::(2), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &make_default_justification::(&test_header(1)), ), Err(JustificationVerificationError::InvalidJustificationTarget), @@ -129,8 +125,7 @@ fn justification_with_invalid_commit_rejected() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::TooLowCumulativeWeight), @@ -146,8 +141,7 @@ fn justification_with_invalid_authority_signature_rejected() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::Precommit(PrecommitError::InvalidAuthoritySignature)), @@ -162,8 +156,7 @@ fn justification_with_invalid_precommit_ancestry() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &justification, ), Err(JustificationVerificationError::RedundantVotesAncestries), @@ -187,8 +180,7 @@ fn justification_is_invalid_if_we_dont_meet_threshold() { assert_eq!( verify_justification::( header_id::(1), - TEST_GRANDPA_SET_ID, - &voter_set(), + &verification_context(TEST_GRANDPA_SET_ID), &make_justification_for_header::(params) ), Err(JustificationVerificationError::TooLowCumulativeWeight), diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index a1b7e8d54b4f6..43fdaf8da1b7f 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -321,7 +321,7 @@ macro_rules! decl_bridge_finality_runtime_apis { } }; ($chain: ident, grandpa) => { - decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::HeaderGrandpaInfo
); + decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::StoredHeaderGrandpaInfo
); }; } diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index b1782109668ae..a4e818a3b8880 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -16,10 +16,11 @@ //! Utilities for working with test accounts. +use bp_header_chain::{justification::JustificationVerificationContext, AuthoritySet}; use codec::Encode; use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; use finality_grandpa::voter_set::VoterSet; -use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight}; +use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; @@ -78,6 +79,11 @@ pub fn voter_set() -> VoterSet { VoterSet::new(authority_list()).unwrap() } +/// Get a valid justification verification context for a GRANDPA round. +pub fn verification_context(set_id: SetId) -> JustificationVerificationContext { + AuthoritySet { authorities: authority_list(), set_id }.try_into().unwrap() +} + /// Convenience function to get a list of Grandpa authorities. pub fn authority_list() -> AuthorityList { test_keyring().iter().map(|(id, w)| (AuthorityId::from(*id), *w)).collect() diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index fbe360d3cd780..fd84782c07ce0 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -15,8 +15,6 @@ // along with Parity Bridges Common. If not, see . use async_trait::async_trait; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf}; -use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -76,10 +74,7 @@ pub enum RelayHeadersBridge { } #[async_trait] -trait HeadersRelayer: RelayToRelayHeadersCliBridge -where - AccountIdOf: From< as Pair>::Public>, -{ +trait HeadersRelayer: RelayToRelayHeadersCliBridge { /// Relay headers. async fn relay_headers(data: RelayHeaders) -> anyhow::Result<()> { let source_client = data.source.into_client::().await?; diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index fb99fc7af16f7..ec51b8dd1f2aa 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,16 +16,17 @@ use crate::calls::UtilityCall; -use bp_header_chain::UnderlyingChainWithGrandpaProvider; +use bp_header_chain::ChainWithGrandpa as ChainWithGrandpaBase; use bp_messages::MessageNonce; use bp_runtime::{ Chain as ChainBase, ChainId, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra, TransactionEraOf, UnderlyingChainProvider, }; -use codec::{Codec, Encode}; +use codec::{Codec, Decode, Encode}; use jsonrpsee::core::{DeserializeOwned, Serialize}; use num_traits::Zero; use sc_transaction_pool_api::TransactionStatus; +use scale_info::TypeInfo; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{ generic::SignedBlock, @@ -78,7 +79,7 @@ pub trait RelayChain: Chain { /// /// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement /// this trait. -pub trait ChainWithGrandpa: Chain + UnderlyingChainWithGrandpaProvider { +pub trait ChainWithGrandpa: Chain + ChainWithGrandpaBase { /// Name of the runtime API method that is returning the GRANDPA info associated with the /// headers accepted by the `submit_finality_proofs` extrinsic in the queried block. /// @@ -87,7 +88,7 @@ pub trait ChainWithGrandpa: Chain + UnderlyingChainWithGrandpaProvider { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str; /// The type of the key owner proof used by the grandpa engine. - type KeyOwnerProof; + type KeyOwnerProof: Decode + TypeInfo + Send; } /// Substrate-based parachain from minimal relay-client point of view. diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index a4001a19aa051..688303fb73796 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -22,8 +22,8 @@ use crate::{ SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient, SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, }, - transaction_stall_timeout, AccountKeyPairOf, ConnectionParams, Error, HashOf, HeaderIdOf, - Result, SignParam, TransactionTracker, UnsignedTransaction, + transaction_stall_timeout, AccountKeyPairOf, ChainWithGrandpa, ConnectionParams, Error, HashOf, + HeaderIdOf, Result, SignParam, TransactionTracker, UnsignedTransaction, }; use async_std::sync::{Arc, Mutex, RwLock}; @@ -715,15 +715,16 @@ impl Client { Ok(Subscription(Mutex::new(receiver))) } - // TODO: remove warning after implementing - // https://github.com/paritytech/parity-bridges-common/issues/39 - #[allow(dead_code)] - async fn generate_grandpa_key_ownership_proof( + /// Generates a proof of key ownership for the given authority in the given set. + pub async fn generate_grandpa_key_ownership_proof( &self, at: HashOf, set_id: sp_consensus_grandpa::SetId, authority_id: sp_consensus_grandpa::AuthorityId, - ) -> Result> { + ) -> Result> + where + C: ChainWithGrandpa, + { self.typed_state_call( SUB_API_GRANDPA_GENERATE_KEY_OWNERSHIP_PROOF.into(), (set_id, authority_id), diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml new file mode 100644 index 0000000000000..93a1470c6a978 --- /dev/null +++ b/relays/equivocation/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "equivocation-detector" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +description = "Equivocation detector" + +[dependencies] +async-trait = "0.1" +bp-header-chain = { path = "../../primitives/header-chain" } +finality-relay = { path = "../finality" } +relay-utils = { path = "../utils" } diff --git a/relays/equivocation/src/lib.rs b/relays/equivocation/src/lib.rs new file mode 100644 index 0000000000000..9019c3cf69f6c --- /dev/null +++ b/relays/equivocation/src/lib.rs @@ -0,0 +1,70 @@ +// Copyright 2019-2023 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 . + +use async_trait::async_trait; +use bp_header_chain::{FindEquivocations, HeaderFinalityInfo}; +use finality_relay::{FinalityPipeline, SourceClientBase}; +use relay_utils::{relay_loop::Client as RelayClient, TransactionTracker}; + +pub trait EquivocationDetectionPipeline: FinalityPipeline { + /// Block number of the target chain. + type TargetNumber: relay_utils::BlockNumberBase; + /// The context needed for validating finality proofs. + type FinalityVerificationContext; + /// The type of the equivocation proof. + type EquivocationProof; + /// The equivocations finder. + type EquivocationsFinder: FindEquivocations< + Self::FinalityProof, + Self::FinalityVerificationContext, + Self::EquivocationProof, + >; +} + +/// Source client used in equivocation detection loop. +#[async_trait] +pub trait SourceClient: SourceClientBase

{ + /// Transaction tracker to track submitted transactions. + type TransactionTracker: TransactionTracker; + + /// Report equivocation. + async fn report_equivocation( + &self, + at: P::Hash, + equivocation: P::EquivocationProof, + ) -> Result; +} + +/// Target client used in equivocation detection loop. +#[async_trait] +pub trait TargetClient: RelayClient { + /// Get the data stored by the target at the specified block for validating source finality + /// proofs. + async fn finality_verification_context( + &self, + at: P::TargetNumber, + ) -> Result; + + /// Get the finality info associated to the source headers synced with the target chain at the + /// specified block. + async fn synced_headers_finality_info( + &self, + at: P::TargetNumber, + ) -> Result< + Vec>, + Self::Error, + >; +} diff --git a/relays/finality/src/base.rs b/relays/finality/src/base.rs new file mode 100644 index 0000000000000..bf9acbdf98210 --- /dev/null +++ b/relays/finality/src/base.rs @@ -0,0 +1,51 @@ +// Copyright 2019-2023 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 . + +use async_trait::async_trait; +use bp_header_chain::FinalityProof; +use futures::Stream; +use relay_utils::relay_loop::Client as RelayClient; +use std::fmt::Debug; + +/// Base finality pipeline. +pub trait FinalityPipeline: 'static + Clone + Debug + Send + Sync { + /// Name of the finality proofs source. + const SOURCE_NAME: &'static str; + /// Name of the finality proofs target. + const TARGET_NAME: &'static str; + + /// Synced headers are identified by this hash. + type Hash: Eq + Clone + Copy + Send + Sync + Debug; + /// Synced headers are identified by this number. + type Number: relay_utils::BlockNumberBase; + /// Finality proof type. + type FinalityProof: FinalityProof; +} + +/// Source client used in finality related loops. +#[async_trait] +pub trait SourceClientBase: RelayClient { + /// Stream of new finality proofs. The stream is allowed to miss proofs for some + /// headers, even if those headers are mandatory. + type FinalityProofsStream: Stream + Send + Unpin; + + /// Subscribe to new finality proofs. + async fn finality_proofs(&self) -> Result; +} + +/// Target client used in finality related loops. +#[async_trait] +pub trait TargetClientBase: RelayClient {} diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 1ee1a8d9db6bb..7c8217c209fd0 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -20,11 +20,13 @@ //! assume that the persistent proof either exists, or will eventually become available. use crate::{ - sync_loop_metrics::SyncLoopMetrics, FinalityProof, FinalitySyncPipeline, SourceHeader, + sync_loop_metrics::SyncLoopMetrics, FinalityPipeline, FinalitySyncPipeline, SourceClientBase, + SourceHeader, }; use async_trait::async_trait; use backoff::backoff::Backoff; +use bp_header_chain::FinalityProof; use futures::{select, Future, FutureExt, Stream, StreamExt}; use num_traits::{One, Saturating}; use relay_utils::{ @@ -66,11 +68,7 @@ pub struct FinalitySyncParams { /// Source client used in finality synchronization loop. #[async_trait] -pub trait SourceClient: RelayClient { - /// Stream of new finality proofs. The stream is allowed to miss proofs for some - /// headers, even if those headers are mandatory. - type FinalityProofsStream: Stream + Send; - +pub trait SourceClient: SourceClientBase

{ /// Get best finalized block number. async fn best_finalized_block_number(&self) -> Result; @@ -79,9 +77,6 @@ pub trait SourceClient: RelayClient { &self, number: P::Number, ) -> Result<(P::Header, Option), Self::Error>; - - /// Subscribe to new finality proofs. - async fn finality_proofs(&self) -> Result; } /// Target client used in finality synchronization loop. @@ -143,10 +138,10 @@ pub async fn run( pub(crate) type UnjustifiedHeaders = Vec; /// Finality proofs container. Ordered by target header number. pub(crate) type FinalityProofs

= - Vec<(

::Number,

::FinalityProof)>; + Vec<(

::Number,

::FinalityProof)>; /// Reference to finality proofs container. pub(crate) type FinalityProofsRef<'a, P> = - &'a [(

::Number,

::FinalityProof)]; + &'a [(

::Number,

::FinalityProof)]; /// Error that may happen inside finality synchronization loop. #[derive(Debug)] diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs index 1853c095f703f..774a5c0c67307 100644 --- a/relays/finality/src/finality_loop_tests.rs +++ b/relays/finality/src/finality_loop_tests.rs @@ -26,11 +26,11 @@ use crate::{ SourceClient, TargetClient, }, sync_loop_metrics::SyncLoopMetrics, - FinalityProof, FinalitySyncPipeline, SourceHeader, + FinalityPipeline, FinalitySyncPipeline, SourceClientBase, SourceHeader, }; use async_trait::async_trait; -use bp_header_chain::GrandpaConsensusLogReader; +use bp_header_chain::{FinalityProof, GrandpaConsensusLogReader}; use futures::{FutureExt, Stream, StreamExt}; use parking_lot::Mutex; use relay_utils::{ @@ -80,15 +80,18 @@ impl MaybeConnectionError for TestError { #[derive(Debug, Clone)] struct TestFinalitySyncPipeline; -impl FinalitySyncPipeline for TestFinalitySyncPipeline { +impl FinalityPipeline for TestFinalitySyncPipeline { const SOURCE_NAME: &'static str = "TestSource"; const TARGET_NAME: &'static str = "TestTarget"; type Hash = TestHash; type Number = TestNumber; + type FinalityProof = TestFinalityProof; +} + +impl FinalitySyncPipeline for TestFinalitySyncPipeline { type ConsensusLogReader = GrandpaConsensusLogReader; type Header = TestSourceHeader; - type FinalityProof = TestFinalityProof; } #[derive(Debug, Clone, PartialEq, Eq)] @@ -146,9 +149,18 @@ impl RelayClient for TestSourceClient { } #[async_trait] -impl SourceClient for TestSourceClient { +impl SourceClientBase for TestSourceClient { type FinalityProofsStream = Pin + 'static + Send>>; + async fn finality_proofs(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut data); + Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) + } +} + +#[async_trait] +impl SourceClient for TestSourceClient { async fn best_finalized_block_number(&self) -> Result { let mut data = self.data.lock(); (self.on_method_call)(&mut data); @@ -163,12 +175,6 @@ impl SourceClient for TestSourceClient { (self.on_method_call)(&mut data); data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) } - - async fn finality_proofs(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(&mut data); - Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) - } } #[derive(Clone)] diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index dca47c6a572cf..599cf2f9f9de3 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -20,34 +20,25 @@ //! to submit all source headers to the target node. pub use crate::{ + base::{FinalityPipeline, SourceClientBase}, finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}, sync_loop_metrics::SyncLoopMetrics, }; -use bp_header_chain::{ConsensusLogReader, FinalityProof}; +use bp_header_chain::ConsensusLogReader; use std::fmt::Debug; +mod base; mod finality_loop; mod finality_loop_tests; mod sync_loop_metrics; /// Finality proofs synchronization pipeline. -pub trait FinalitySyncPipeline: 'static + Clone + Debug + Send + Sync { - /// Name of the finality proofs source. - const SOURCE_NAME: &'static str; - /// Name of the finality proofs target. - const TARGET_NAME: &'static str; - - /// Headers we're syncing are identified by this hash. - type Hash: Eq + Clone + Copy + Send + Sync + Debug; - /// Headers we're syncing are identified by this number. - type Number: relay_utils::BlockNumberBase; +pub trait FinalitySyncPipeline: FinalityPipeline { /// A reader that can extract the consensus log from the header digest and interpret it. type ConsensusLogReader: ConsensusLogReader; /// Type of header that we're syncing. type Header: SourceHeader; - /// Finality proof type. - type FinalityProof: FinalityProof; } /// Header that we're receiving from source node. diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 869b6e00122ef..72e97dbe69ac6 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -24,6 +24,7 @@ bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-relayers = { path = "../../primitives/relayers" } bridge-runtime-common = { path = "../../bin/runtime-common" } +equivocation-detector = { path = "../equivocation" } finality-grandpa = { version = "0.16.2" } finality-relay = { path = "../finality" } parachains-relay = { path = "../parachains" } diff --git a/relays/lib-substrate-relay/src/equivocation/mod.rs b/relays/lib-substrate-relay/src/equivocation/mod.rs index 31668490f90c1..40750088bfb43 100644 --- a/relays/lib-substrate-relay/src/equivocation/mod.rs +++ b/relays/lib-substrate-relay/src/equivocation/mod.rs @@ -17,30 +17,96 @@ //! Types and functions intended to ease adding of new Substrate -> Substrate //! equivocation detection pipelines. -use crate::finality_base::SubstrateFinalityPipeline; -use std::marker::PhantomData; +mod source; +mod target; + +use crate::finality_base::{engine::Engine, SubstrateFinalityPipeline, SubstrateFinalityProof}; -use crate::finality_base::engine::Engine; use async_trait::async_trait; -use bp_runtime::{BlockNumberOf, HashOf}; +use bp_runtime::{AccountIdOf, BlockNumberOf, HashOf}; +use equivocation_detector::EquivocationDetectionPipeline; +use finality_relay::FinalityPipeline; use pallet_grandpa::{Call as GrandpaCall, Config as GrandpaConfig}; -use relay_substrate_client::CallOf; +use relay_substrate_client::{AccountKeyPairOf, CallOf, Chain, ChainWithTransactions}; +use sp_core::Pair; use sp_runtime::traits::{Block, Header}; +use std::marker::PhantomData; + +/// Convenience trait that adds bounds to `SubstrateEquivocationDetectionPipeline`. +pub trait BaseSubstrateEquivocationDetectionPipeline: + SubstrateFinalityPipeline +{ + /// Bounded `SubstrateFinalityPipeline::SourceChain`. + type BoundedSourceChain: ChainWithTransactions; + + /// Bounded `AccountIdOf`. + type BoundedSourceChainAccountId: From< as Pair>::Public> + + Send; +} + +impl BaseSubstrateEquivocationDetectionPipeline for T +where + T: SubstrateFinalityPipeline, + T::SourceChain: ChainWithTransactions, + AccountIdOf: From< as Pair>::Public>, +{ + type BoundedSourceChain = T::SourceChain; + type BoundedSourceChainAccountId = AccountIdOf; +} /// Substrate -> Substrate equivocation detection pipeline. #[async_trait] -pub trait SubstrateEquivocationDetectionPipeline: SubstrateFinalityPipeline { +pub trait SubstrateEquivocationDetectionPipeline: + BaseSubstrateEquivocationDetectionPipeline +{ /// How the `report_equivocation` call is built ? type ReportEquivocationCallBuilder: ReportEquivocationCallBuilder; } +type FinalityProoffOf

= <

::FinalityEngine as Engine< +

::SourceChain, +>>::FinalityProof; +type FinalityVerificationContextfOf

= + <

::FinalityEngine as Engine< +

::SourceChain, + >>::FinalityVerificationContext; type EquivocationProofOf

= <

::FinalityEngine as Engine<

::SourceChain, >>::EquivocationProof; +type EquivocationsFinderOf

= <

::FinalityEngine as Engine< +

::SourceChain, +>>::EquivocationsFinder; type KeyOwnerProofOf

= <

::FinalityEngine as Engine<

::SourceChain, >>::KeyOwnerProof; +/// Adapter that allows a `SubstrateEquivocationDetectionPipeline` to act as an +/// `EquivocationDetectionPipeline`. +#[derive(Clone, Debug)] +pub struct EquivocationDetectionPipelineAdapter { + _phantom: PhantomData

, +} + +impl FinalityPipeline + for EquivocationDetectionPipelineAdapter

+{ + const SOURCE_NAME: &'static str = P::SourceChain::NAME; + const TARGET_NAME: &'static str = P::TargetChain::NAME; + + type Hash = HashOf; + type Number = BlockNumberOf; + type FinalityProof = SubstrateFinalityProof

; +} + +impl EquivocationDetectionPipeline + for EquivocationDetectionPipelineAdapter

+{ + type TargetNumber = BlockNumberOf; + type FinalityVerificationContext = FinalityVerificationContextfOf

; + type EquivocationProof = EquivocationProofOf

; + type EquivocationsFinder = EquivocationsFinderOf

; +} + /// Different ways of building `report_equivocation` calls. pub trait ReportEquivocationCallBuilder { /// Build a `report_equivocation` call to be executed on the source chain. diff --git a/relays/lib-substrate-relay/src/equivocation/source.rs b/relays/lib-substrate-relay/src/equivocation/source.rs new file mode 100644 index 0000000000000..543c057ee9ae5 --- /dev/null +++ b/relays/lib-substrate-relay/src/equivocation/source.rs @@ -0,0 +1,101 @@ +// Copyright 2019-2023 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 . + +//! Default generic implementation of equivocation source for basic Substrate client. + +use crate::{ + equivocation::{ + EquivocationDetectionPipelineAdapter, EquivocationProofOf, ReportEquivocationCallBuilder, + SubstrateEquivocationDetectionPipeline, + }, + finality_base::{engine::Engine, finality_proofs, SubstrateFinalityProofsStream}, + TransactionParams, +}; + +use async_trait::async_trait; +use bp_runtime::{HashOf, TransactionEra}; +use equivocation_detector::SourceClient; +use finality_relay::SourceClientBase; +use relay_substrate_client::{ + AccountKeyPairOf, Client, Error, TransactionTracker, UnsignedTransaction, +}; +use relay_utils::relay_loop::Client as RelayClient; + +/// Substrate node as equivocation source. +pub struct SubstrateEquivocationSource { + client: Client, + transaction_params: TransactionParams>, +} + +impl SubstrateEquivocationSource

{} + +impl Clone for SubstrateEquivocationSource

{ + fn clone(&self) -> Self { + Self { client: self.client.clone(), transaction_params: self.transaction_params.clone() } + } +} + +#[async_trait] +impl RelayClient for SubstrateEquivocationSource

{ + type Error = Error; + + async fn reconnect(&mut self) -> Result<(), Error> { + self.client.reconnect().await + } +} + +#[async_trait] +impl + SourceClientBase> for SubstrateEquivocationSource

+{ + type FinalityProofsStream = SubstrateFinalityProofsStream

; + + async fn finality_proofs(&self) -> Result { + finality_proofs::

(&self.client).await + } +} + +#[async_trait] +impl + SourceClient> for SubstrateEquivocationSource

+{ + type TransactionTracker = TransactionTracker>; + + async fn report_equivocation( + &self, + at: HashOf, + equivocation: EquivocationProofOf

, + ) -> Result { + let key_owner_proof = + P::FinalityEngine::generate_source_key_ownership_proof(&self.client, at, &equivocation) + .await?; + + let mortality = self.transaction_params.mortality; + let call = P::ReportEquivocationCallBuilder::build_report_equivocation_call( + equivocation, + key_owner_proof, + ); + self.client + .submit_and_watch_signed_extrinsic( + &self.transaction_params.signer, + move |best_block_id, transaction_nonce| { + Ok(UnsignedTransaction::new(call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, mortality))) + }, + ) + .await + } +} diff --git a/relays/lib-substrate-relay/src/equivocation/target.rs b/relays/lib-substrate-relay/src/equivocation/target.rs new file mode 100644 index 0000000000000..36343a6eddb8e --- /dev/null +++ b/relays/lib-substrate-relay/src/equivocation/target.rs @@ -0,0 +1,86 @@ +// Copyright 2019-2023 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 . + +//! Default generic implementation of equivocation source for basic Substrate client. + +use crate::{ + equivocation::{EquivocationDetectionPipelineAdapter, SubstrateEquivocationDetectionPipeline}, + finality_base::engine::Engine, +}; + +use crate::equivocation::{FinalityProoffOf, FinalityVerificationContextfOf}; +use async_trait::async_trait; +use bp_header_chain::HeaderFinalityInfo; +use bp_runtime::BlockNumberOf; +use equivocation_detector::TargetClient; +use relay_substrate_client::{Client, Error}; +use relay_utils::relay_loop::Client as RelayClient; +use sp_runtime::traits::Header; +use std::marker::PhantomData; + +/// Substrate node as equivocation source. +pub struct SubstrateEquivocationTarget { + client: Client, + + _phantom: PhantomData

, +} + +impl SubstrateEquivocationTarget

{} + +impl Clone for SubstrateEquivocationTarget

{ + fn clone(&self) -> Self { + Self { client: self.client.clone(), _phantom: Default::default() } + } +} + +#[async_trait] +impl RelayClient for SubstrateEquivocationTarget

{ + type Error = Error; + + async fn reconnect(&mut self) -> Result<(), Error> { + self.client.reconnect().await + } +} + +#[async_trait] +impl + TargetClient> for SubstrateEquivocationTarget

+{ + async fn finality_verification_context( + &self, + at: BlockNumberOf, + ) -> Result, Self::Error> { + P::FinalityEngine::finality_verification_context( + &self.client, + self.client.header_by_number(at).await?.hash(), + ) + .await + } + + async fn synced_headers_finality_info( + &self, + at: BlockNumberOf, + ) -> Result< + Vec, FinalityVerificationContextfOf

>>, + Self::Error, + > { + P::FinalityEngine::synced_headers_finality_info( + &self.client, + self.client.header_by_number(at).await?.hash(), + ) + .await + } +} diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index bae49efe72e01..98aec1d52b908 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -18,21 +18,18 @@ //! finality proofs synchronization pipelines. use crate::{ - finality::{ - source::{SubstrateFinalityProof, SubstrateFinalitySource}, - target::SubstrateFinalityTarget, - }, + finality::{source::SubstrateFinalitySource, target::SubstrateFinalityTarget}, + finality_base::{engine::Engine, SubstrateFinalityPipeline, SubstrateFinalityProof}, TransactionParams, }; -use crate::finality_base::{engine::Engine, SubstrateFinalityPipeline}; use async_trait::async_trait; use bp_header_chain::justification::GrandpaJustification; -use finality_relay::FinalitySyncPipeline; +use finality_relay::{FinalityPipeline, FinalitySyncPipeline}; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ - transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, Client, - HashOf, HeaderOf, SyncHeader, + transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, BlockNumberOf, CallOf, Chain, + ChainWithTransactions, Client, HashOf, HeaderOf, SyncHeader, }; use relay_utils::metrics::MetricsParams; use sp_core::Pair; @@ -48,9 +45,31 @@ pub mod target; /// Substrate+GRANDPA based chains (good to know). pub(crate) const RECENT_FINALITY_PROOFS_LIMIT: usize = 4096; +/// Convenience trait that adds bounds to `SubstrateFinalitySyncPipeline`. +pub trait BaseSubstrateFinalitySyncPipeline: + SubstrateFinalityPipeline +{ + /// Bounded `SubstrateFinalityPipeline::TargetChain`. + type BoundedTargetChain: ChainWithTransactions; + + /// Bounded `AccountIdOf`. + type BoundedTargetChainAccountId: From< as Pair>::Public> + + Send; +} + +impl BaseSubstrateFinalitySyncPipeline for T +where + T: SubstrateFinalityPipeline, + T::TargetChain: ChainWithTransactions, + AccountIdOf: From< as Pair>::Public>, +{ + type BoundedTargetChain = T::TargetChain; + type BoundedTargetChainAccountId = AccountIdOf; +} + /// Substrate -> Substrate finality proofs synchronization pipeline. #[async_trait] -pub trait SubstrateFinalitySyncPipeline: SubstrateFinalityPipeline { +pub trait SubstrateFinalitySyncPipeline: BaseSubstrateFinalitySyncPipeline { /// How submit finality proof call is built? type SubmitFinalityProofCallBuilder: SubmitFinalityProofCallBuilder; @@ -70,15 +89,18 @@ pub struct FinalitySyncPipelineAdapter { _phantom: PhantomData

, } -impl FinalitySyncPipeline for FinalitySyncPipelineAdapter

{ +impl FinalityPipeline for FinalitySyncPipelineAdapter

{ const SOURCE_NAME: &'static str = P::SourceChain::NAME; const TARGET_NAME: &'static str = P::TargetChain::NAME; type Hash = HashOf; type Number = BlockNumberOf; + type FinalityProof = SubstrateFinalityProof

; +} + +impl FinalitySyncPipeline for FinalitySyncPipelineAdapter

{ type ConsensusLogReader = >::ConsensusLogReader; type Header = SyncHeader>; - type FinalityProof = SubstrateFinalityProof

; } /// Different ways of building `submit_finality_proof` calls. @@ -165,10 +187,7 @@ pub async fn run( only_mandatory_headers: bool, transaction_params: TransactionParams>, metrics_params: MetricsParams, -) -> anyhow::Result<()> -where - AccountIdOf: From< as Pair>::Public>, -{ +) -> anyhow::Result<()> { log::info!( target: "bridge", "Starting {} -> {} finality proof relay", diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index 208299f9cb2bf..41c6c53daf4d6 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -18,38 +18,27 @@ use crate::{ finality::{FinalitySyncPipelineAdapter, SubstrateFinalitySyncPipeline}, - finality_base::engine::Engine, + finality_base::{ + engine::Engine, finality_proofs, SubstrateFinalityProof, SubstrateFinalityProofsStream, + }, }; -use crate::finality_base::SubstrateFinalityPipeline; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::FinalityProof; use codec::Decode; -use finality_relay::SourceClient; +use finality_relay::{SourceClient, SourceClientBase}; use futures::{ select, - stream::{try_unfold, unfold, Stream, StreamExt, TryStreamExt}, + stream::{try_unfold, Stream, StreamExt, TryStreamExt}, }; use num_traits::One; -use relay_substrate_client::{ - BlockNumberOf, BlockWithJustification, Chain, Client, Error, HeaderOf, -}; +use relay_substrate_client::{BlockNumberOf, BlockWithJustification, Client, Error, HeaderOf}; use relay_utils::{relay_loop::Client as RelayClient, UniqueSaturatedInto}; -use std::pin::Pin; /// Shared updatable reference to the maximal header number that we want to sync from the source. pub type RequiredHeaderNumberRef = Arc::BlockNumber>>; -/// Substrate finality proofs stream. -pub type SubstrateFinalityProofsStream

= - Pin> + Send>>; - -/// Substrate finality proof. Specific to the used `FinalityEngine`. -pub type SubstrateFinalityProof

= <

::FinalityEngine as Engine< -

::SourceChain, ->>::FinalityProof; - /// Substrate node as finality source. pub struct SubstrateFinalitySource { client: Client, @@ -204,11 +193,20 @@ impl RelayClient for SubstrateFinalitySource

SourceClient> +impl SourceClientBase> for SubstrateFinalitySource

{ type FinalityProofsStream = SubstrateFinalityProofsStream

; + async fn finality_proofs(&self) -> Result { + finality_proofs::

(&self.client).await + } +} + +#[async_trait] +impl SourceClient> + for SubstrateFinalitySource

+{ async fn best_finalized_block_number(&self) -> Result, Error> { let mut finalized_header_number = self.on_chain_best_finalized_block_number().await?; // never return block number larger than requested. This way we'll never sync headers @@ -234,46 +232,6 @@ impl SourceClient { header_and_finality_proof::

(&self.client, number).await } - - async fn finality_proofs(&self) -> Result { - Ok(unfold( - P::FinalityEngine::source_finality_proofs(&self.client).await?, - move |subscription| async move { - loop { - let log_error = |err| { - log::error!( - target: "bridge", - "Failed to read justification target from the {} justifications stream: {:?}", - P::SourceChain::NAME, - err, - ); - }; - - let next_justification = subscription - .next() - .await - .map_err(|err| log_error(err.to_string())) - .ok()??; - - let decoded_justification = - >::FinalityProof::decode( - &mut &next_justification[..], - ); - - let justification = match decoded_justification { - Ok(j) => j, - Err(err) => { - log_error(format!("decode failed with error {err:?}")); - continue - }, - }; - - return Some((justification, subscription)) - } - }, - ) - .boxed()) - } } async fn header_and_finality_proof( diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 3d1fa780eaefb..1be668392dd36 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -18,21 +18,19 @@ use crate::{ finality::{ - source::SubstrateFinalityProof, FinalitySyncPipelineAdapter, - SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, + FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }, - finality_base::engine::Engine, + finality_base::{engine::Engine, SubstrateFinalityProof}, TransactionParams, }; use async_trait::async_trait; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Client, Error, HeaderIdOf, HeaderOf, SyncHeader, TransactionEra, + AccountKeyPairOf, Client, Error, HeaderIdOf, HeaderOf, SyncHeader, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; -use sp_core::Pair; /// Substrate client as Substrate finality target. pub struct SubstrateFinalityTarget { @@ -86,8 +84,6 @@ impl RelayClient for SubstrateFinalityTarget

TargetClient> for SubstrateFinalityTarget

-where - AccountIdOf: From< as Pair>::Public>, { type TransactionTracker = TransactionTracker>; @@ -116,7 +112,7 @@ where P::FinalityEngine::optimize_proof(&self.client, &header, &mut proof).await?; // now we may submit optimized finality proof - let transaction_params = self.transaction_params.clone(); + let mortality = self.transaction_params.mortality; let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); self.client @@ -124,7 +120,7 @@ where &self.transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(call.into(), transaction_nonce) - .era(TransactionEra::new(best_block_id, transaction_params.mortality))) + .era(TransactionEra::new(best_block_id, mortality))) }, ) .await diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs index dc84ebaa4d5c6..49614638f89e6 100644 --- a/relays/lib-substrate-relay/src/finality_base/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -19,13 +19,15 @@ use crate::error::Error; use async_trait::async_trait; use bp_header_chain::{ - justification::{verify_and_optimize_justification, GrandpaJustification}, - ChainWithGrandpa as ChainWithGrandpaBase, ConsensusLogReader, FinalityProof, - GrandpaConsensusLogReader, + justification::{ + verify_and_optimize_justification, GrandpaEquivocationsFinder, GrandpaJustification, + JustificationVerificationContext, + }, + AuthoritySet, ConsensusLogReader, FinalityProof, FindEquivocations, GrandpaConsensusLogReader, + HeaderFinalityInfo, HeaderGrandpaInfo, StoredHeaderGrandpaInfo, }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode}; use codec::{Decode, Encode}; -use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; use relay_substrate_client::{ BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, HeaderOf, @@ -33,7 +35,7 @@ use relay_substrate_client::{ }; use sp_consensus_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID}; use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::{traits::Header, ConsensusEngineId}; +use sp_runtime::{scale_info::TypeInfo, traits::Header, ConsensusEngineId}; use std::marker::PhantomData; /// Finality engine, used by the Substrate chain. @@ -47,10 +49,18 @@ pub trait Engine: Send { type FinalityClient: SubstrateFinalityClient; /// Type of finality proofs, used by consensus engine. type FinalityProof: FinalityProof> + Decode + Encode; + /// The context needed for verifying finality proofs. + type FinalityVerificationContext; /// The type of the equivocation proof used by the consensus engine. - type EquivocationProof; + type EquivocationProof: Send + Sync; + /// The equivocations finder. + type EquivocationsFinder: FindEquivocations< + Self::FinalityProof, + Self::FinalityVerificationContext, + Self::EquivocationProof, + >; /// The type of the key owner proof used by the consensus engine. - type KeyOwnerProof; + type KeyOwnerProof: Send; /// Type of bridge pallet initialization data. type InitializationData: std::fmt::Debug + Send + Sync + 'static; /// Type of bridge pallet operating mode. @@ -105,6 +115,29 @@ pub trait Engine: Send { async fn prepare_initialization_data( client: Client, ) -> Result, BlockNumberOf>>; + + /// Get the context needed for validating a finality proof. + async fn finality_verification_context( + target_client: &Client, + at: HashOf, + ) -> Result; + + /// Returns the finality info associated to the source headers synced with the target + /// at the provided block. + async fn synced_headers_finality_info( + target_client: &Client, + at: TargetChain::Hash, + ) -> Result< + Vec>, + SubstrateError, + >; + + /// Generate key ownership proof for the provided equivocation. + async fn generate_source_key_ownership_proof( + source_client: &Client, + at: C::Hash, + equivocation: &Self::EquivocationProof, + ) -> Result; } /// GRANDPA finality engine. @@ -142,21 +175,19 @@ impl Engine for Grandpa { type ConsensusLogReader = GrandpaConsensusLogReader<::Number>; type FinalityClient = SubstrateGrandpaFinalityClient; type FinalityProof = GrandpaJustification>; + type FinalityVerificationContext = JustificationVerificationContext; type EquivocationProof = sp_consensus_grandpa::EquivocationProof, BlockNumberOf>; + type EquivocationsFinder = GrandpaEquivocationsFinder; type KeyOwnerProof = C::KeyOwnerProof; type InitializationData = bp_header_chain::InitializationData; type OperatingMode = BasicOperatingMode; fn is_initialized_key() -> StorageKey { - bp_header_chain::storage_keys::best_finalized_key( - C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, - ) + bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } fn pallet_operating_mode_key() -> StorageKey { - bp_header_chain::storage_keys::pallet_operating_mode_key( - C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, - ) + bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } async fn optimize_proof( @@ -164,31 +195,18 @@ impl Engine for Grandpa { header: &C::Header, proof: &mut Self::FinalityProof, ) -> Result<(), SubstrateError> { - let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key( - C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, - ); - let (authority_set, authority_set_id): ( - sp_consensus_grandpa::AuthorityList, - sp_consensus_grandpa::SetId, - ) = target_client - .storage_value(current_authority_set_key, None) - .await? - .map(Ok) - .unwrap_or(Err(SubstrateError::Custom(format!( - "{} `CurrentAuthoritySet` is missing from the {} storage", - C::NAME, - TargetChain::NAME, - ))))?; - let authority_set = - finality_grandpa::voter_set::VoterSet::new(authority_set).expect("TODO"); + let verification_context = Grandpa::::finality_verification_context( + target_client, + target_client.best_header().await?.hash(), + ) + .await?; // we're risking with race here - we have decided to submit justification some time ago and // actual authorities set (which we have read now) may have changed, so this // `optimize_justification` may fail. But if target chain is configured properly, it'll fail // anyway, after we submit transaction and failing earlier is better. So - it is fine verify_and_optimize_justification( (header.hash(), *header.number()), - authority_set_id, - &authority_set, + &verification_context, proof, ) .map_err(|e| { @@ -275,8 +293,6 @@ impl Engine for Grandpa { // Now let's try to guess authorities set id by verifying justification. let mut initial_authorities_set_id = 0; let mut min_possible_block_number = C::BlockNumber::zero(); - let authorities_for_verification = VoterSet::new(authorities_for_verification.clone()) - .ok_or(Error::ReadInvalidAuthorities(C::NAME, authorities_for_verification))?; loop { log::trace!( target: "bridge", "Trying {} GRANDPA authorities set id: {}", @@ -286,8 +302,14 @@ impl Engine for Grandpa { let is_valid_set_id = verify_and_optimize_justification( (initial_header_hash, initial_header_number), - initial_authorities_set_id, - &authorities_for_verification, + &AuthoritySet { + authorities: authorities_for_verification.clone(), + set_id: initial_authorities_set_id, + } + .try_into() + .map_err(|_| { + Error::ReadInvalidAuthorities(C::NAME, authorities_for_verification.clone()) + })?, &mut justification.clone(), ) .is_ok(); @@ -317,4 +339,82 @@ impl Engine for Grandpa { operating_mode: BasicOperatingMode::Normal, }) } + + async fn finality_verification_context( + target_client: &Client, + at: HashOf, + ) -> Result { + let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key( + C::WITH_CHAIN_GRANDPA_PALLET_NAME, + ); + let authority_set: AuthoritySet = target_client + .storage_value(current_authority_set_key, Some(at)) + .await? + .map(Ok) + .unwrap_or(Err(SubstrateError::Custom(format!( + "{} `CurrentAuthoritySet` is missing from the {} storage", + C::NAME, + TargetChain::NAME, + ))))?; + + authority_set.try_into().map_err(|e| { + SubstrateError::Custom(format!( + "{} `CurrentAuthoritySet` from the {} storage is invalid: {e:?}", + C::NAME, + TargetChain::NAME, + )) + }) + } + + async fn synced_headers_finality_info( + target_client: &Client, + at: TargetChain::Hash, + ) -> Result>>, SubstrateError> { + let stored_headers_grandpa_info: Vec>> = target_client + .typed_state_call(C::SYNCED_HEADERS_GRANDPA_INFO_METHOD.to_string(), (), Some(at)) + .await?; + + let mut headers_grandpa_info = vec![]; + for stored_header_grandpa_info in stored_headers_grandpa_info { + headers_grandpa_info.push(stored_header_grandpa_info.try_into().map_err(|e| { + SubstrateError::Custom(format!( + "{} `AuthoritySet` synced to {} is invalid: {e:?} ", + C::NAME, + TargetChain::NAME, + )) + })?); + } + + Ok(headers_grandpa_info) + } + + async fn generate_source_key_ownership_proof( + source_client: &Client, + at: C::Hash, + equivocation: &Self::EquivocationProof, + ) -> Result { + let set_id = equivocation.set_id(); + let offender = equivocation.offender(); + + let opaque_key_owner_proof = source_client + .generate_grandpa_key_ownership_proof(at, set_id, offender.clone()) + .await? + .ok_or(SubstrateError::Custom(format!( + "Couldn't get GRANDPA key ownership proof from {} at block: {at} \ + for offender: {:?}, set_id: {set_id} ", + C::NAME, + offender.clone(), + )))?; + + let key_owner_proof = + opaque_key_owner_proof.decode().ok_or(SubstrateError::Custom(format!( + "Couldn't decode GRANDPA `OpaqueKeyOwnnershipProof` from {} at block: {at} + to `{:?}` for offender: {:?}, set_id: {set_id}, at block: {at}", + C::NAME, + ::type_info().path, + offender.clone(), + )))?; + + Ok(key_owner_proof) + } } diff --git a/relays/lib-substrate-relay/src/finality_base/mod.rs b/relays/lib-substrate-relay/src/finality_base/mod.rs index e48f82480325a..bcd3f008d67c9 100644 --- a/relays/lib-substrate-relay/src/finality_base/mod.rs +++ b/relays/lib-substrate-relay/src/finality_base/mod.rs @@ -19,9 +19,12 @@ pub mod engine; +use crate::finality_base::engine::Engine; use async_trait::async_trait; -use relay_substrate_client::{Chain, ChainWithTransactions}; -use std::fmt::Debug; +use codec::Decode; +use futures::{stream::unfold, Stream, StreamExt}; +use relay_substrate_client::{Chain, Client, Error}; +use std::{fmt::Debug, pin::Pin}; /// Substrate -> Substrate finality related pipeline. #[async_trait] @@ -29,7 +32,56 @@ pub trait SubstrateFinalityPipeline: 'static + Clone + Debug + Send + Sync { /// Headers of this chain are submitted to the `TargetChain`. type SourceChain: Chain; /// Headers of the `SourceChain` are submitted to this chain. - type TargetChain: ChainWithTransactions; + type TargetChain: Chain; /// Finality engine. - type FinalityEngine: engine::Engine; + type FinalityEngine: Engine; +} + +/// Substrate finality proof. Specific to the used `FinalityEngine`. +pub type SubstrateFinalityProof

= <

::FinalityEngine as Engine< +

::SourceChain, +>>::FinalityProof; + +/// Substrate finality proofs stream. +pub type SubstrateFinalityProofsStream

= + Pin> + Send>>; + +/// Subscribe to new finality proofs. +pub async fn finality_proofs( + client: &Client, +) -> Result, Error> { + Ok(unfold( + P::FinalityEngine::source_finality_proofs(client).await?, + move |subscription| async move { + loop { + let log_error = |err| { + log::error!( + target: "bridge", + "Failed to read justification target from the {} justifications stream: {:?}", + P::SourceChain::NAME, + err, + ); + }; + + let next_justification = + subscription.next().await.map_err(|err| log_error(err.to_string())).ok()??; + + let decoded_justification = + >::FinalityProof::decode( + &mut &next_justification[..], + ); + + let justification = match decoded_justification { + Ok(j) => j, + Err(err) => { + log_error(format!("decode failed with error {err:?}")); + continue + }, + }; + + return Some((justification, subscription)) + } + }, + ) + .boxed()) } From 331a2186265fbee554df37bd70b52e3ac186435f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 16 Aug 2023 12:42:51 +0300 Subject: [PATCH 1092/1210] Finality loop refactoring (#2357) --- relays/finality/Cargo.toml | 2 +- relays/finality/src/finality_loop.rs | 1072 ++++++++--------- relays/finality/src/finality_loop_tests.rs | 604 ---------- relays/finality/src/finality_proofs.rs | 227 ++++ relays/finality/src/headers.rs | 237 ++++ relays/finality/src/lib.rs | 40 +- relays/finality/src/mock.rs | 209 ++++ .../src/finality/source.rs | 2 +- relays/utils/src/relay_loop.rs | 12 +- 9 files changed, 1226 insertions(+), 1179 deletions(-) delete mode 100644 relays/finality/src/finality_loop_tests.rs create mode 100644 relays/finality/src/finality_proofs.rs create mode 100644 relays/finality/src/headers.rs create mode 100644 relays/finality/src/mock.rs diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index ab75533b023af..7fcd08ef6f5f8 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -12,7 +12,7 @@ async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.28" -log = "0.4.17" +log = "0.4.20" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index 7c8217c209fd0..b1f1f018c0edf 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -19,23 +19,23 @@ //! is the mandatory headers, which we always submit to the target node. For such headers, we //! assume that the persistent proof either exists, or will eventually become available. +use crate::{sync_loop_metrics::SyncLoopMetrics, Error, FinalitySyncPipeline, SourceHeader}; + use crate::{ - sync_loop_metrics::SyncLoopMetrics, FinalityPipeline, FinalitySyncPipeline, SourceClientBase, - SourceHeader, + base::SourceClientBase, + finality_proofs::{FinalityProofsBuf, FinalityProofsStream}, + headers::{JustifiedHeader, JustifiedHeaderSelector}, }; - use async_trait::async_trait; -use backoff::backoff::Backoff; -use bp_header_chain::FinalityProof; -use futures::{select, Future, FutureExt, Stream, StreamExt}; -use num_traits::{One, Saturating}; +use backoff::{backoff::Backoff, ExponentialBackoff}; +use futures::{future::Fuse, select, Future, FutureExt}; +use num_traits::Saturating; use relay_utils::{ metrics::MetricsParams, relay_loop::Client as RelayClient, retry_backoff, FailedClient, HeaderId, MaybeConnectionError, TrackedTransactionStatus, TransactionTracker, }; use std::{ fmt::Debug, - pin::Pin, time::{Duration, Instant}, }; @@ -104,653 +104,593 @@ pub fn metrics_prefix() -> String { format!("{}_to_{}_Sync", P::SOURCE_NAME, P::TARGET_NAME) } -/// Run finality proofs synchronization loop. -pub async fn run( - source_client: impl SourceClient

, - target_client: impl TargetClient

, - sync_params: FinalitySyncParams, - metrics_params: MetricsParams, - exit_signal: impl Future + 'static + Send, -) -> Result<(), relay_utils::Error> { - let exit_signal = exit_signal.shared(); - relay_utils::relay_loop(source_client, target_client) - .with_metrics(metrics_params) - .loop_metric(SyncLoopMetrics::new( - Some(&metrics_prefix::

()), - "source", - "source_at_target", - )?)? - .expose() - .await? - .run(metrics_prefix::

(), move |source_client, target_client, metrics| { - run_until_connection_lost( - source_client, - target_client, - sync_params.clone(), - metrics, - exit_signal.clone(), - ) - }) - .await +pub struct SyncInfo { + pub best_number_at_source: P::Number, + pub best_number_at_target: P::Number, + pub is_using_same_fork: bool, } -/// Unjustified headers container. Ordered by header number. -pub(crate) type UnjustifiedHeaders = Vec; -/// Finality proofs container. Ordered by target header number. -pub(crate) type FinalityProofs

= - Vec<(

::Number,

::FinalityProof)>; -/// Reference to finality proofs container. -pub(crate) type FinalityProofsRef<'a, P> = - &'a [(

::Number,

::FinalityProof)]; - -/// Error that may happen inside finality synchronization loop. -#[derive(Debug)] -pub(crate) enum Error { - /// Source client request has failed with given error. - Source(SourceError), - /// Target client request has failed with given error. - Target(TargetError), - /// Finality proof for mandatory header is missing from the source node. - MissingMandatoryFinalityProof(P::Number), -} +impl SyncInfo

{ + /// Checks if both clients are on the same fork. + async fn is_on_same_fork>( + source_client: &SC, + id_at_target: &HeaderId, + ) -> Result { + let header_at_source = source_client.header_and_finality_proof(id_at_target.0).await?.0; + let header_hash_at_source = header_at_source.hash(); + Ok(if id_at_target.1 == header_hash_at_source { + true + } else { + log::error!( + target: "bridge", + "Source node ({}) and pallet at target node ({}) have different headers at the same height {:?}: \ + at-source {:?} vs at-target {:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + id_at_target.0, + header_hash_at_source, + id_at_target.1, + ); + + false + }) + } -impl Error -where - P: FinalitySyncPipeline, - SourceError: MaybeConnectionError, - TargetError: MaybeConnectionError, -{ - fn fail_if_connection_error(&self) -> Result<(), FailedClient> { - match *self { - Error::Source(ref error) if error.is_connection_error() => Err(FailedClient::Source), - Error::Target(ref error) if error.is_connection_error() => Err(FailedClient::Target), - _ => Ok(()), + async fn new, TC: TargetClient

>( + source_client: &SC, + target_client: &TC, + ) -> Result> { + let best_number_at_source = + source_client.best_finalized_block_number().await.map_err(Error::Source)?; + let best_id_at_target = + target_client.best_finalized_source_block_id().await.map_err(Error::Target)?; + let best_number_at_target = best_id_at_target.0; + + let is_using_same_fork = Self::is_on_same_fork(source_client, &best_id_at_target) + .await + .map_err(Error::Source)?; + + Ok(Self { best_number_at_source, best_number_at_target, is_using_same_fork }) + } + + fn update_metrics(&self, metrics_sync: &Option) { + if let Some(metrics_sync) = metrics_sync { + metrics_sync.update_best_block_at_source(self.best_number_at_source); + metrics_sync.update_best_block_at_target(self.best_number_at_target); + metrics_sync.update_using_same_fork(self.is_using_same_fork); } } + + pub fn num_headers(&self) -> P::Number { + self.best_number_at_source.saturating_sub(self.best_number_at_target) + } } /// Information about transaction that we have submitted. #[derive(Debug, Clone)] -pub(crate) struct Transaction { +pub struct Transaction { /// Submitted transaction tracker. - pub tracker: Tracker, + tracker: Tracker, /// The number of the header we have submitted. - pub submitted_header_number: Number, + header_number: Number, } impl Transaction { pub async fn submit< - C: TargetClient, P: FinalitySyncPipeline, + TC: TargetClient, >( - target_client: &C, + target_client: &TC, header: P::Header, justification: P::FinalityProof, - ) -> Result { - let submitted_header_number = header.number(); + ) -> Result { + let header_number = header.number(); log::debug!( target: "bridge", "Going to submit finality proof of {} header #{:?} to {}", P::SOURCE_NAME, - submitted_header_number, + header_number, P::TARGET_NAME, ); let tracker = target_client.submit_finality_proof(header, justification).await?; - Ok(Transaction { tracker, submitted_header_number }) + Ok(Transaction { tracker, header_number }) } - pub async fn track, P: FinalitySyncPipeline>( + async fn track< + P: FinalitySyncPipeline, + SC: SourceClient

, + TC: TargetClient

, + >( self, - target_client: &C, - ) -> Result<(), String> { + target_client: TC, + ) -> Result<(), Error> { match self.tracker.wait().await { TrackedTransactionStatus::Finalized(_) => { // The transaction has been finalized, but it may have been finalized in the // "failed" state. So let's check if the block number was actually updated. - // If it wasn't then we are stalled. - // - // Please also note that we're returning an error if we fail to read required data - // from the target client - that's the best we can do here to avoid actual stall. target_client .best_finalized_source_block_id() .await - .map_err(|e| format!("failed to read best block from target node: {e:?}")) + .map_err(Error::Target) .and_then(|best_id_at_target| { - if self.submitted_header_number > best_id_at_target.0 { - return Err(format!( - "best block at target after tx is {:?} and we've submitted {:?}", - best_id_at_target.0, self.submitted_header_number, - )) + if self.header_number > best_id_at_target.0 { + return Err(Error::ProofSubmissionTxFailed { + submitted_number: self.header_number, + best_number_at_target: best_id_at_target.0, + }) } Ok(()) }) }, - TrackedTransactionStatus::Lost => Err("transaction failed".to_string()), + TrackedTransactionStatus::Lost => Err(Error::ProofSubmissionTxLost), } } } -/// Finality proofs stream that may be restarted. -pub(crate) struct RestartableFinalityProofsStream { - /// Flag that the stream needs to be restarted. - pub(crate) needs_restart: bool, - /// The stream itself. - stream: Pin>, -} +/// Finality synchronization loop state. +struct FinalityLoop, TC: TargetClient

> { + source_client: SC, + target_client: TC, -impl RestartableFinalityProofsStream { - pub async fn create_raw_stream< - C: SourceClient, - P: FinalitySyncPipeline, - >( - source_client: &C, - ) -> Result { - source_client.finality_proofs().await.map_err(|error| { - log::error!( - target: "bridge", - "Failed to subscribe to {} justifications: {:?}. Going to reconnect", - P::SOURCE_NAME, - error, - ); + sync_params: FinalitySyncParams, + metrics_sync: Option, - FailedClient::Source - }) + progress: (Instant, Option), + retry_backoff: ExponentialBackoff, + finality_proofs_stream: FinalityProofsStream, + finality_proofs_buf: FinalityProofsBuf

, + best_submitted_number: Option, +} + +impl, TC: TargetClient

> FinalityLoop { + pub fn new( + source_client: SC, + target_client: TC, + sync_params: FinalitySyncParams, + metrics_sync: Option, + ) -> Self { + Self { + source_client, + target_client, + sync_params, + metrics_sync, + progress: (Instant::now(), None), + retry_backoff: retry_backoff(), + finality_proofs_stream: FinalityProofsStream::new(), + finality_proofs_buf: FinalityProofsBuf::new(vec![]), + best_submitted_number: None, + } } - pub async fn restart_if_scheduled< - C: SourceClient, - P: FinalitySyncPipeline, - >( - &mut self, - source_client: &C, - ) -> Result<(), FailedClient> { - if self.needs_restart { - log::warn!(target: "bridge", "{} finality proofs stream is being restarted", P::SOURCE_NAME); + fn update_progress(&mut self, info: &SyncInfo

) { + let (prev_time, prev_best_number_at_target) = self.progress; + let now = Instant::now(); + + let needs_update = now - prev_time > Duration::from_secs(10) || + prev_best_number_at_target + .map(|prev_best_number_at_target| { + info.best_number_at_target.saturating_sub(prev_best_number_at_target) > + 10.into() + }) + .unwrap_or(true); - self.needs_restart = false; - self.stream = Box::pin(Self::create_raw_stream(source_client).await?); + if !needs_update { + return } - Ok(()) + + log::info!( + target: "bridge", + "Synced {:?} of {:?} headers", + info.best_number_at_target, + info.best_number_at_source, + ); + + self.progress = (now, Some(info.best_number_at_target)) } - pub fn next(&mut self) -> Option { - match self.stream.next().now_or_never() { - Some(Some(finality_proof)) => Some(finality_proof), - Some(None) => { - self.needs_restart = true; - None - }, - None => None, + pub async fn select_header_to_submit( + &mut self, + info: &SyncInfo

, + ) -> Result>, Error> { + // to see that the loop is progressing + log::trace!( + target: "bridge", + "Considering range of headers ({}; {}]", + info.best_number_at_target, + info.best_number_at_source + ); + + // read missing headers + let selector = JustifiedHeaderSelector::new::(&self.source_client, info).await?; + // if we see that the header schedules GRANDPA change, we need to submit it + if self.sync_params.only_mandatory_headers { + return Ok(selector.select_mandatory()) } - } -} -impl From for RestartableFinalityProofsStream { - fn from(stream: S) -> Self { - RestartableFinalityProofsStream { needs_restart: false, stream: Box::pin(stream) } + // all headers that are missing from the target client are non-mandatory + // => even if we have already selected some header and its persistent finality proof, + // we may try to select better header by reading non-persistent proofs from the stream + self.finality_proofs_buf.fill(&mut self.finality_proofs_stream); + let maybe_justified_header = selector.select(&self.finality_proofs_buf); + + // remove obsolete 'recent' finality proofs + keep its size under certain limit + let oldest_finality_proof_to_keep = maybe_justified_header + .as_ref() + .map(|justified_header| justified_header.number()) + .unwrap_or(info.best_number_at_target); + self.finality_proofs_buf + .prune(oldest_finality_proof_to_keep, self.sync_params.recent_finality_proofs_limit); + + Ok(maybe_justified_header) } -} -/// Finality synchronization loop state. -pub(crate) struct FinalityLoopState<'a, P: FinalitySyncPipeline, FinalityProofsStream> { - /// Synchronization loop progress. - pub(crate) progress: &'a mut (Instant, Option), - /// Finality proofs stream. - pub(crate) finality_proofs_stream: - &'a mut RestartableFinalityProofsStream, - /// Recent finality proofs that we have read from the stream. - pub(crate) recent_finality_proofs: &'a mut FinalityProofs

, - /// Number of the last header, submitted to the target node. - pub(crate) submitted_header_number: Option, -} + pub async fn run_iteration( + &mut self, + ) -> Result< + Option>, + Error, + > { + // read best source headers ids from source and target nodes + let info = SyncInfo::new(&self.source_client, &self.target_client).await?; + info.update_metrics(&self.metrics_sync); + self.update_progress(&info); + + // if we have already submitted header, then we just need to wait for it + // if we're waiting too much, then we believe our transaction has been lost and restart sync + if Some(info.best_number_at_target) < self.best_submitted_number { + return Ok(None) + } -/// Run finality relay loop until connection to one of nodes is lost. -pub(crate) async fn run_until_connection_lost( - source_client: impl SourceClient

, - target_client: impl TargetClient

, - sync_params: FinalitySyncParams, - metrics_sync: Option, - exit_signal: impl Future, -) -> Result<(), FailedClient> { - let last_transaction_tracker = futures::future::Fuse::terminated(); - let exit_signal = exit_signal.fuse(); - futures::pin_mut!(last_transaction_tracker, exit_signal); - - let mut finality_proofs_stream = - RestartableFinalityProofsStream::create_raw_stream(&source_client).await?.into(); - let mut recent_finality_proofs = Vec::new(); - - let mut progress = (Instant::now(), None); - let mut retry_backoff = retry_backoff(); - let mut last_submitted_header_number = None; - - loop { - // run loop iteration - let iteration_result = run_loop_iteration( - &source_client, - &target_client, - FinalityLoopState { - progress: &mut progress, - finality_proofs_stream: &mut finality_proofs_stream, - recent_finality_proofs: &mut recent_finality_proofs, - submitted_header_number: last_submitted_header_number, - }, - &sync_params, - &metrics_sync, - ) - .await; - - // deal with errors - let next_tick = match iteration_result { - Ok(Some(updated_transaction)) => { - last_submitted_header_number = Some(updated_transaction.submitted_header_number); - last_transaction_tracker.set(updated_transaction.track(&target_client).fuse()); - retry_backoff.reset(); - sync_params.tick - }, - Ok(None) => { - retry_backoff.reset(); - sync_params.tick - }, - Err(error) => { - log::error!(target: "bridge", "Finality sync loop iteration has failed with error: {:?}", error); - error.fail_if_connection_error()?; - retry_backoff.next_backoff().unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) + // submit new header if we have something new + match self.select_header_to_submit(&info).await? { + Some(header) => { + let transaction = + Transaction::submit(&self.target_client, header.header, header.proof) + .await + .map_err(Error::Target)?; + self.best_submitted_number = Some(transaction.header_number); + Ok(Some(transaction)) }, - }; - finality_proofs_stream.restart_if_scheduled(&source_client).await?; - - // wait till exit signal, or new source block - select! { - transaction_result = last_transaction_tracker => { - transaction_result.map_err(|e| { - log::error!( - target: "bridge", - "Finality synchronization from {} to {} has stalled with error: {}. Going to restart", - P::SOURCE_NAME, - P::TARGET_NAME, - e, - ); - - // Restart the loop if we're stalled. - FailedClient::Both - })? - }, - _ = async_std::task::sleep(next_tick).fuse() => {}, - _ = exit_signal => return Ok(()), + None => Ok(None), } } -} -pub(crate) async fn run_loop_iteration( - source_client: &SC, - target_client: &TC, - state: FinalityLoopState<'_, P, SC::FinalityProofsStream>, - sync_params: &FinalitySyncParams, - metrics_sync: &Option, -) -> Result>, Error> -where - P: FinalitySyncPipeline, - SC: SourceClient

, - TC: TargetClient

, -{ - // read best source headers ids from source and target nodes - let best_number_at_source = - source_client.best_finalized_block_number().await.map_err(Error::Source)?; - let best_id_at_target = - target_client.best_finalized_source_block_id().await.map_err(Error::Target)?; - let best_number_at_target = best_id_at_target.0; - - let different_hash_at_source = ensure_same_fork::(&best_id_at_target, source_client) - .await - .map_err(Error::Source)?; - let using_same_fork = different_hash_at_source.is_none(); - if let Some(ref different_hash_at_source) = different_hash_at_source { - log::error!( - target: "bridge", - "Source node ({}) and pallet at target node ({}) have different headers at the same height {:?}: \ - at-source {:?} vs at-target {:?}", - P::SOURCE_NAME, - P::TARGET_NAME, - best_number_at_target, - different_hash_at_source, - best_id_at_target.1, - ); - } + async fn ensure_finality_proofs_stream(&mut self) -> Result<(), FailedClient> { + if let Err(e) = self.finality_proofs_stream.ensure_stream(&self.source_client).await { + if e.is_connection_error() { + return Err(FailedClient::Source) + } + } - if let Some(ref metrics_sync) = *metrics_sync { - metrics_sync.update_best_block_at_source(best_number_at_source); - metrics_sync.update_best_block_at_target(best_number_at_target); - metrics_sync.update_using_same_fork(using_same_fork); + Ok(()) } - *state.progress = - print_sync_progress::

(*state.progress, best_number_at_source, best_number_at_target); - - // if we have already submitted header, then we just need to wait for it - // if we're waiting too much, then we believe our transaction has been lost and restart sync - if let Some(submitted_header_number) = state.submitted_header_number { - if best_number_at_target >= submitted_header_number { - // transaction has been mined && we can continue - } else { - return Ok(None) + + /// Run finality relay loop until connection to one of nodes is lost. + async fn run_until_connection_lost( + &mut self, + exit_signal: impl Future, + ) -> Result<(), FailedClient> { + self.ensure_finality_proofs_stream().await?; + let proof_submission_tx_tracker = Fuse::terminated(); + let exit_signal = exit_signal.fuse(); + futures::pin_mut!(exit_signal, proof_submission_tx_tracker); + + loop { + // run loop iteration + let next_tick = match self.run_iteration().await { + Ok(Some(tx)) => { + proof_submission_tx_tracker + .set(tx.track::(self.target_client.clone()).fuse()); + self.retry_backoff.reset(); + self.sync_params.tick + }, + Ok(None) => { + self.retry_backoff.reset(); + self.sync_params.tick + }, + Err(error) => { + log::error!(target: "bridge", "Finality sync loop iteration has failed with error: {:?}", error); + error.fail_if_connection_error()?; + self.retry_backoff + .next_backoff() + .unwrap_or(relay_utils::relay_loop::RECONNECT_DELAY) + }, + }; + self.ensure_finality_proofs_stream().await?; + + // wait till exit signal, or new source block + select! { + proof_submission_result = proof_submission_tx_tracker => { + if let Err(e) = proof_submission_result { + log::error!( + target: "bridge", + "Finality sync proof submission tx to {} has failed with error: {:?}.", + P::TARGET_NAME, + e, + ); + self.best_submitted_number = None; + e.fail_if_connection_error()?; + } + }, + _ = async_std::task::sleep(next_tick).fuse() => {}, + _ = exit_signal => return Ok(()), + } } } - // submit new header if we have something new - match select_header_to_submit( - source_client, - target_client, - state.finality_proofs_stream, - state.recent_finality_proofs, - best_number_at_source, - best_number_at_target, - sync_params, - ) - .await? - { - Some((header, justification)) => { - let transaction = Transaction::submit(target_client, header, justification) - .await - .map_err(Error::Target)?; - Ok(Some(transaction)) - }, - None => Ok(None), + pub async fn run( + source_client: SC, + target_client: TC, + sync_params: FinalitySyncParams, + metrics_sync: Option, + exit_signal: impl Future, + ) -> Result<(), FailedClient> { + let mut finality_loop = Self::new(source_client, target_client, sync_params, metrics_sync); + finality_loop.run_until_connection_lost(exit_signal).await } } -pub(crate) async fn select_header_to_submit( - source_client: &SC, - target_client: &TC, - finality_proofs_stream: &mut RestartableFinalityProofsStream, - recent_finality_proofs: &mut FinalityProofs

, - best_number_at_source: P::Number, - best_number_at_target: P::Number, - sync_params: &FinalitySyncParams, -) -> Result, Error> -where - P: FinalitySyncPipeline, - SC: SourceClient

, - TC: TargetClient

, -{ - // to see that the loop is progressing - log::trace!( - target: "bridge", - "Considering range of headers ({:?}; {:?}]", - best_number_at_target, - best_number_at_source, - ); - - // read missing headers. if we see that the header schedules GRANDPA change, we need to - // submit this header - let selected_finality_proof = read_missing_headers::( - source_client, - target_client, - best_number_at_source, - best_number_at_target, - ) - .await?; - let (mut unjustified_headers, mut selected_finality_proof) = match selected_finality_proof { - SelectedFinalityProof::Mandatory(header, finality_proof) => - return Ok(Some((header, finality_proof))), - _ if sync_params.only_mandatory_headers => { - // we are not reading finality proofs from the stream, so eventually it'll break - // but we don't care about transient proofs at all, so it is acceptable - return Ok(None) - }, - SelectedFinalityProof::Regular(unjustified_headers, header, finality_proof) => - (unjustified_headers, Some((header, finality_proof))), - SelectedFinalityProof::None(unjustified_headers) => (unjustified_headers, None), - }; - - // all headers that are missing from the target client are non-mandatory - // => even if we have already selected some header and its persistent finality proof, - // we may try to select better header by reading non-persistent proofs from the stream - read_finality_proofs_from_stream::(finality_proofs_stream, recent_finality_proofs); - selected_finality_proof = select_better_recent_finality_proof::

( - recent_finality_proofs, - &mut unjustified_headers, - selected_finality_proof, - ); - - // remove obsolete 'recent' finality proofs + keep its size under certain limit - let oldest_finality_proof_to_keep = selected_finality_proof - .as_ref() - .map(|(header, _)| header.number()) - .unwrap_or(best_number_at_target); - prune_recent_finality_proofs::

( - oldest_finality_proof_to_keep, - recent_finality_proofs, - sync_params.recent_finality_proofs_limit, - ); - - Ok(selected_finality_proof) -} - -/// Ensures that both clients are on the same fork. -/// -/// Returns `Some(_)` with header has at the source client if headers are different. -async fn ensure_same_fork>( - best_id_at_target: &HeaderId, - source_client: &SC, -) -> Result, SC::Error> { - let header_at_source = source_client.header_and_finality_proof(best_id_at_target.0).await?.0; - let header_hash_at_source = header_at_source.hash(); - Ok(if best_id_at_target.1 == header_hash_at_source { - None - } else { - Some(header_hash_at_source) - }) -} - -/// Finality proof that has been selected by the `read_missing_headers` function. -pub(crate) enum SelectedFinalityProof { - /// Mandatory header and its proof has been selected. We shall submit proof for this header. - Mandatory(Header, FinalityProof), - /// Regular header and its proof has been selected. We may submit this proof, or proof for - /// some better header. - Regular(UnjustifiedHeaders

, Header, FinalityProof), - /// We haven't found any missing header with persistent proof at the target client. - None(UnjustifiedHeaders
), +/// Run finality proofs synchronization loop. +pub async fn run( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + sync_params: FinalitySyncParams, + metrics_params: MetricsParams, + exit_signal: impl Future + 'static + Send, +) -> Result<(), relay_utils::Error> { + let exit_signal = exit_signal.shared(); + relay_utils::relay_loop(source_client, target_client) + .with_metrics(metrics_params) + .loop_metric(SyncLoopMetrics::new( + Some(&metrics_prefix::

()), + "source", + "source_at_target", + )?)? + .expose() + .await? + .run(metrics_prefix::

(), move |source_client, target_client, metrics| { + FinalityLoop::run( + source_client, + target_client, + sync_params.clone(), + metrics, + exit_signal.clone(), + ) + }) + .await } -/// Read missing headers and their persistent finality proofs from the target client. -/// -/// If we have found some header with known proof, it is returned. -/// Otherwise, `SelectedFinalityProof::None` is returned. -/// -/// Unless we have found mandatory header, all missing headers are collected and returned. -pub(crate) async fn read_missing_headers< - P: FinalitySyncPipeline, - SC: SourceClient

, - TC: TargetClient

, ->( - source_client: &SC, - _target_client: &TC, - best_number_at_source: P::Number, - best_number_at_target: P::Number, -) -> Result, Error> { - let mut unjustified_headers = Vec::new(); - let mut selected_finality_proof = None; - let mut header_number = best_number_at_target + One::one(); - while header_number <= best_number_at_source { - let (header, finality_proof) = source_client - .header_and_finality_proof(header_number) - .await - .map_err(Error::Source)?; - let is_mandatory = header.is_mandatory(); - - match (is_mandatory, finality_proof) { - (true, Some(finality_proof)) => { - log::trace!(target: "bridge", "Header {:?} is mandatory", header_number); - return Ok(SelectedFinalityProof::Mandatory(header, finality_proof)) +#[cfg(test)] +mod tests { + use super::*; + + use crate::mock::*; + use futures::{FutureExt, StreamExt}; + use parking_lot::Mutex; + use relay_utils::{FailedClient, HeaderId, TrackedTransactionStatus}; + use std::{collections::HashMap, sync::Arc}; + + fn prepare_test_clients( + exit_sender: futures::channel::mpsc::UnboundedSender<()>, + state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, + source_headers: HashMap)>, + ) -> (TestSourceClient, TestTargetClient) { + let internal_state_function: Arc = + Arc::new(move |data| { + if state_function(data) { + exit_sender.unbounded_send(()).unwrap(); + } + }); + let clients_data = Arc::new(Mutex::new(ClientsData { + source_best_block_number: 10, + source_headers, + source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], + + target_best_block_id: HeaderId(5, 5), + target_headers: vec![], + target_transaction_tracker: TestTransactionTracker( + TrackedTransactionStatus::Finalized(Default::default()), + ), + })); + ( + TestSourceClient { + on_method_call: internal_state_function.clone(), + data: clients_data.clone(), }, - (true, None) => return Err(Error::MissingMandatoryFinalityProof(header.number())), - (false, Some(finality_proof)) => { - log::trace!(target: "bridge", "Header {:?} has persistent finality proof", header_number); - unjustified_headers.clear(); - selected_finality_proof = Some((header, finality_proof)); - }, - (false, None) => { - unjustified_headers.push(header); - }, - } - - header_number = header_number + One::one(); + TestTargetClient { on_method_call: internal_state_function, data: clients_data }, + ) } - log::trace!( - target: "bridge", - "Read {} {} headers. Selected finality proof for header: {:?}", - best_number_at_source.saturating_sub(best_number_at_target), - P::SOURCE_NAME, - selected_finality_proof.as_ref().map(|(header, _)| header), - ); - - Ok(match selected_finality_proof { - Some((header, proof)) => SelectedFinalityProof::Regular(unjustified_headers, header, proof), - None => SelectedFinalityProof::None(unjustified_headers), - }) -} - -/// Read finality proofs from the stream. -pub(crate) fn read_finality_proofs_from_stream< - P: FinalitySyncPipeline, - FPS: Stream, ->( - finality_proofs_stream: &mut RestartableFinalityProofsStream, - recent_finality_proofs: &mut FinalityProofs

, -) { - let mut proofs_count = 0; - let mut first_header_number = None; - let mut last_header_number = None; - while let Some(finality_proof) = finality_proofs_stream.next() { - let target_header_number = finality_proof.target_header_number(); - if first_header_number.is_none() { - first_header_number = Some(target_header_number); + fn test_sync_params() -> FinalitySyncParams { + FinalitySyncParams { + tick: Duration::from_secs(0), + recent_finality_proofs_limit: 1024, + stall_timeout: Duration::from_secs(1), + only_mandatory_headers: false, } - last_header_number = Some(target_header_number); - proofs_count += 1; + } - recent_finality_proofs.push((target_header_number, finality_proof)); + fn run_sync_loop( + state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, + ) -> (ClientsData, Result<(), FailedClient>) { + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + let (source_client, target_client) = prepare_test_clients( + exit_sender, + state_function, + vec![ + (5, (TestSourceHeader(false, 5, 5), None)), + (6, (TestSourceHeader(false, 6, 6), None)), + (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), + (8, (TestSourceHeader(true, 8, 8), Some(TestFinalityProof(8)))), + (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), + (10, (TestSourceHeader(false, 10, 10), None)), + ] + .into_iter() + .collect(), + ); + let sync_params = test_sync_params(); + + let clients_data = source_client.data.clone(); + let result = async_std::task::block_on(FinalityLoop::run( + source_client, + target_client, + sync_params, + None, + exit_receiver.into_future().map(|(_, _)| ()), + )); + + let clients_data = clients_data.lock().clone(); + (clients_data, result) } - if proofs_count != 0 { - log::trace!( - target: "bridge", - "Read {} finality proofs from {} finality stream for headers in range [{:?}; {:?}]", - proofs_count, - P::SOURCE_NAME, - first_header_number, - last_header_number, + #[test] + fn finality_sync_loop_works() { + let (client_data, result) = run_sync_loop(|data| { + // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, + // because header#8 has persistent finality proof && it is mandatory => it is submitted + // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, + // because there are no more persistent finality proofs + // + // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 + // from the stream + if data.target_best_block_id.0 == 9 { + data.source_best_block_number = 14; + data.source_headers.insert(11, (TestSourceHeader(false, 11, 11), None)); + data.source_headers + .insert(12, (TestSourceHeader(false, 12, 12), Some(TestFinalityProof(12)))); + data.source_headers.insert(13, (TestSourceHeader(false, 13, 13), None)); + data.source_headers + .insert(14, (TestSourceHeader(false, 14, 14), Some(TestFinalityProof(14)))); + } + // once this ^^^ is done, we generate more blocks && read persistent proof for block 16 + if data.target_best_block_id.0 == 14 { + data.source_best_block_number = 17; + data.source_headers.insert(15, (TestSourceHeader(false, 15, 15), None)); + data.source_headers + .insert(16, (TestSourceHeader(false, 16, 16), Some(TestFinalityProof(16)))); + data.source_headers.insert(17, (TestSourceHeader(false, 17, 17), None)); + } + + data.target_best_block_id.0 == 16 + }); + + assert_eq!(result, Ok(())); + assert_eq!( + client_data.target_headers, + vec![ + // before adding 11..14: finality proof for mandatory header#8 + (TestSourceHeader(true, 8, 8), TestFinalityProof(8)), + // before adding 11..14: persistent finality proof for non-mandatory header#9 + (TestSourceHeader(false, 9, 9), TestFinalityProof(9)), + // after adding 11..14: ephemeral finality proof for non-mandatory header#14 + (TestSourceHeader(false, 14, 14), TestFinalityProof(14)), + // after adding 15..17: persistent finality proof for non-mandatory header#16 + (TestSourceHeader(false, 16, 16), TestFinalityProof(16)), + ], ); } -} -/// Try to select better header and its proof, given finality proofs that we -/// have recently read from the stream. -pub(crate) fn select_better_recent_finality_proof( - recent_finality_proofs: FinalityProofsRef

, - unjustified_headers: &mut UnjustifiedHeaders, - selected_finality_proof: Option<(P::Header, P::FinalityProof)>, -) -> Option<(P::Header, P::FinalityProof)> { - if unjustified_headers.is_empty() || recent_finality_proofs.is_empty() { - log::trace!( - target: "bridge", - "Can not improve selected {} finality proof {:?}. No unjustified headers and recent proofs", - P::SOURCE_NAME, - selected_finality_proof.as_ref().map(|(h, _)| h.number()), + fn run_only_mandatory_headers_mode_test( + only_mandatory_headers: bool, + has_mandatory_headers: bool, + ) -> Option> { + let (exit_sender, _) = futures::channel::mpsc::unbounded(); + let (source_client, target_client) = prepare_test_clients( + exit_sender, + |_| false, + vec![ + (6, (TestSourceHeader(false, 6, 6), Some(TestFinalityProof(6)))), + (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), + (8, (TestSourceHeader(has_mandatory_headers, 8, 8), Some(TestFinalityProof(8)))), + (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), + (10, (TestSourceHeader(false, 10, 10), Some(TestFinalityProof(10)))), + ] + .into_iter() + .collect(), ); - return selected_finality_proof + async_std::task::block_on(async { + let mut finality_loop = FinalityLoop::new( + source_client, + target_client, + FinalitySyncParams { + tick: Duration::from_secs(0), + recent_finality_proofs_limit: 0, + stall_timeout: Duration::from_secs(0), + only_mandatory_headers, + }, + None, + ); + let info = SyncInfo { + best_number_at_source: 10, + best_number_at_target: 5, + is_using_same_fork: true, + }; + finality_loop.select_header_to_submit(&info).await.unwrap() + }) } - const NOT_EMPTY_PROOF: &str = "we have checked that the vec is not empty; qed"; - - // we need proofs for headers in range unjustified_range_begin..=unjustified_range_end - let unjustified_range_begin = unjustified_headers.first().expect(NOT_EMPTY_PROOF).number(); - let unjustified_range_end = unjustified_headers.last().expect(NOT_EMPTY_PROOF).number(); - - // we have proofs for headers in range buffered_range_begin..=buffered_range_end - let buffered_range_begin = recent_finality_proofs.first().expect(NOT_EMPTY_PROOF).0; - let buffered_range_end = recent_finality_proofs.last().expect(NOT_EMPTY_PROOF).0; - - // we have two ranges => find intersection - let intersection_begin = std::cmp::max(unjustified_range_begin, buffered_range_begin); - let intersection_end = std::cmp::min(unjustified_range_end, buffered_range_end); - let intersection = intersection_begin..=intersection_end; - - // find last proof from intersection - let selected_finality_proof_index = recent_finality_proofs - .binary_search_by_key(intersection.end(), |(number, _)| *number) - .unwrap_or_else(|index| index.saturating_sub(1)); - let (selected_header_number, finality_proof) = - &recent_finality_proofs[selected_finality_proof_index]; - let has_selected_finality_proof = intersection.contains(selected_header_number); - log::trace!( - target: "bridge", - "Trying to improve selected {} finality proof {:?}. Headers range: [{:?}; {:?}]. Proofs range: [{:?}; {:?}].\ - Trying to improve to: {:?}. Result: {}", - P::SOURCE_NAME, - selected_finality_proof.as_ref().map(|(h, _)| h.number()), - unjustified_range_begin, - unjustified_range_end, - buffered_range_begin, - buffered_range_end, - selected_header_number, - if has_selected_finality_proof { "improved" } else { "not improved" }, - ); - if !has_selected_finality_proof { - return selected_finality_proof + #[test] + fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_headers_are_required( + ) { + assert_eq!(run_only_mandatory_headers_mode_test(true, false), None); + assert_eq!( + run_only_mandatory_headers_mode_test(false, false), + Some(JustifiedHeader { + header: TestSourceHeader(false, 10, 10), + proof: TestFinalityProof(10) + }), + ); } - // now remove all obsolete headers and extract selected header - let selected_header_position = unjustified_headers - .binary_search_by_key(selected_header_number, |header| header.number()) - .expect("unjustified_headers contain all headers from intersection; qed"); - let selected_header = unjustified_headers.swap_remove(selected_header_position); - Some((selected_header, finality_proof.clone())) -} + #[test] + fn select_header_to_submit_selects_mandatory_headers_when_only_mandatory_headers_are_required() + { + assert_eq!( + run_only_mandatory_headers_mode_test(true, true), + Some(JustifiedHeader { + header: TestSourceHeader(true, 8, 8), + proof: TestFinalityProof(8) + }), + ); + assert_eq!( + run_only_mandatory_headers_mode_test(false, true), + Some(JustifiedHeader { + header: TestSourceHeader(true, 8, 8), + proof: TestFinalityProof(8) + }), + ); + } -pub(crate) fn prune_recent_finality_proofs( - justified_header_number: P::Number, - recent_finality_proofs: &mut FinalityProofs

, - recent_finality_proofs_limit: usize, -) { - let justified_header_idx = recent_finality_proofs - .binary_search_by_key(&justified_header_number, |(header_number, _)| *header_number) - .map(|idx| idx + 1) - .unwrap_or_else(|idx| idx); - let proofs_limit_idx = - recent_finality_proofs.len().saturating_sub(recent_finality_proofs_limit); - - *recent_finality_proofs = - recent_finality_proofs.split_off(std::cmp::max(justified_header_idx, proofs_limit_idx)); -} + #[test] + fn different_forks_at_source_and_at_target_are_detected() { + let (exit_sender, _exit_receiver) = futures::channel::mpsc::unbounded(); + let (source_client, target_client) = prepare_test_clients( + exit_sender, + |_| false, + vec![ + (5, (TestSourceHeader(false, 5, 42), None)), + (6, (TestSourceHeader(false, 6, 6), None)), + (7, (TestSourceHeader(false, 7, 7), None)), + (8, (TestSourceHeader(false, 8, 8), None)), + (9, (TestSourceHeader(false, 9, 9), None)), + (10, (TestSourceHeader(false, 10, 10), None)), + ] + .into_iter() + .collect(), + ); -fn print_sync_progress( - progress_context: (Instant, Option), - best_number_at_source: P::Number, - best_number_at_target: P::Number, -) -> (Instant, Option) { - let (prev_time, prev_best_number_at_target) = progress_context; - let now = Instant::now(); - - let need_update = now - prev_time > Duration::from_secs(10) || - prev_best_number_at_target - .map(|prev_best_number_at_target| { - best_number_at_target.saturating_sub(prev_best_number_at_target) > 10.into() - }) - .unwrap_or(true); - - if !need_update { - return (prev_time, prev_best_number_at_target) - } + let metrics_sync = SyncLoopMetrics::new(None, "source", "target").unwrap(); + async_std::task::block_on(async { + let mut finality_loop = FinalityLoop::new( + source_client, + target_client, + test_sync_params(), + Some(metrics_sync.clone()), + ); + finality_loop.run_iteration().await.unwrap() + }); - log::info!( - target: "bridge", - "Synced {:?} of {:?} headers", - best_number_at_target, - best_number_at_source, - ); - (now, Some(best_number_at_target)) + assert!(!metrics_sync.is_using_same_fork()); + } } diff --git a/relays/finality/src/finality_loop_tests.rs b/relays/finality/src/finality_loop_tests.rs deleted file mode 100644 index 774a5c0c67307..0000000000000 --- a/relays/finality/src/finality_loop_tests.rs +++ /dev/null @@ -1,604 +0,0 @@ -// 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 . - -//! Tests for finality synchronization loop. - -#![cfg(test)] - -use crate::{ - finality_loop::{ - prune_recent_finality_proofs, read_finality_proofs_from_stream, run_loop_iteration, - run_until_connection_lost, select_better_recent_finality_proof, select_header_to_submit, - FinalityLoopState, FinalityProofs, FinalitySyncParams, RestartableFinalityProofsStream, - SourceClient, TargetClient, - }, - sync_loop_metrics::SyncLoopMetrics, - FinalityPipeline, FinalitySyncPipeline, SourceClientBase, SourceHeader, -}; - -use async_trait::async_trait; -use bp_header_chain::{FinalityProof, GrandpaConsensusLogReader}; -use futures::{FutureExt, Stream, StreamExt}; -use parking_lot::Mutex; -use relay_utils::{ - relay_loop::Client as RelayClient, FailedClient, HeaderId, MaybeConnectionError, - TrackedTransactionStatus, TransactionTracker, -}; -use std::{ - collections::HashMap, - pin::Pin, - sync::Arc, - time::{Duration, Instant}, -}; - -type IsMandatory = bool; -type TestNumber = u64; -type TestHash = u64; - -#[derive(Clone, Debug)] -struct TestTransactionTracker(TrackedTransactionStatus>); - -impl Default for TestTransactionTracker { - fn default() -> TestTransactionTracker { - TestTransactionTracker(TrackedTransactionStatus::Finalized(Default::default())) - } -} - -#[async_trait] -impl TransactionTracker for TestTransactionTracker { - type HeaderId = HeaderId; - - async fn wait(self) -> TrackedTransactionStatus> { - self.0 - } -} - -#[derive(Debug, Clone)] -enum TestError { - NonConnection, -} - -impl MaybeConnectionError for TestError { - fn is_connection_error(&self) -> bool { - false - } -} - -#[derive(Debug, Clone)] -struct TestFinalitySyncPipeline; - -impl FinalityPipeline for TestFinalitySyncPipeline { - const SOURCE_NAME: &'static str = "TestSource"; - const TARGET_NAME: &'static str = "TestTarget"; - - type Hash = TestHash; - type Number = TestNumber; - type FinalityProof = TestFinalityProof; -} - -impl FinalitySyncPipeline for TestFinalitySyncPipeline { - type ConsensusLogReader = GrandpaConsensusLogReader; - type Header = TestSourceHeader; -} - -#[derive(Debug, Clone, PartialEq, Eq)] -struct TestSourceHeader(IsMandatory, TestNumber, TestHash); - -impl SourceHeader> - for TestSourceHeader -{ - fn hash(&self) -> TestHash { - self.2 - } - - fn number(&self) -> TestNumber { - self.1 - } - - fn is_mandatory(&self) -> bool { - self.0 - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -struct TestFinalityProof(TestNumber); - -impl FinalityProof for TestFinalityProof { - fn target_header_number(&self) -> TestNumber { - self.0 - } -} - -#[derive(Debug, Clone, Default)] -struct ClientsData { - source_best_block_number: TestNumber, - source_headers: HashMap)>, - source_proofs: Vec, - - target_best_block_id: HeaderId, - target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, - target_transaction_tracker: TestTransactionTracker, -} - -#[derive(Clone)] -struct TestSourceClient { - on_method_call: Arc, - data: Arc>, -} - -#[async_trait] -impl RelayClient for TestSourceClient { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - unreachable!() - } -} - -#[async_trait] -impl SourceClientBase for TestSourceClient { - type FinalityProofsStream = Pin + 'static + Send>>; - - async fn finality_proofs(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(&mut data); - Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) - } -} - -#[async_trait] -impl SourceClient for TestSourceClient { - async fn best_finalized_block_number(&self) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(&mut data); - Ok(data.source_best_block_number) - } - - async fn header_and_finality_proof( - &self, - number: TestNumber, - ) -> Result<(TestSourceHeader, Option), TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(&mut data); - data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) - } -} - -#[derive(Clone)] -struct TestTargetClient { - on_method_call: Arc, - data: Arc>, -} - -#[async_trait] -impl RelayClient for TestTargetClient { - type Error = TestError; - - async fn reconnect(&mut self) -> Result<(), TestError> { - unreachable!() - } -} - -#[async_trait] -impl TargetClient for TestTargetClient { - type TransactionTracker = TestTransactionTracker; - - async fn best_finalized_source_block_id( - &self, - ) -> Result, TestError> { - let mut data = self.data.lock(); - (self.on_method_call)(&mut data); - Ok(data.target_best_block_id) - } - - async fn submit_finality_proof( - &self, - header: TestSourceHeader, - proof: TestFinalityProof, - ) -> Result { - let mut data = self.data.lock(); - (self.on_method_call)(&mut data); - data.target_best_block_id = HeaderId(header.number(), header.hash()); - data.target_headers.push((header, proof)); - (self.on_method_call)(&mut data); - Ok(data.target_transaction_tracker.clone()) - } -} - -fn prepare_test_clients( - exit_sender: futures::channel::mpsc::UnboundedSender<()>, - state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, - source_headers: HashMap)>, -) -> (TestSourceClient, TestTargetClient) { - let internal_state_function: Arc = - Arc::new(move |data| { - if state_function(data) { - exit_sender.unbounded_send(()).unwrap(); - } - }); - let clients_data = Arc::new(Mutex::new(ClientsData { - source_best_block_number: 10, - source_headers, - source_proofs: vec![TestFinalityProof(12), TestFinalityProof(14)], - - target_best_block_id: HeaderId(5, 5), - target_headers: vec![], - target_transaction_tracker: TestTransactionTracker(TrackedTransactionStatus::Finalized( - Default::default(), - )), - })); - ( - TestSourceClient { - on_method_call: internal_state_function.clone(), - data: clients_data.clone(), - }, - TestTargetClient { on_method_call: internal_state_function, data: clients_data }, - ) -} - -fn test_sync_params() -> FinalitySyncParams { - FinalitySyncParams { - tick: Duration::from_secs(0), - recent_finality_proofs_limit: 1024, - stall_timeout: Duration::from_secs(1), - only_mandatory_headers: false, - } -} - -fn run_sync_loop( - state_function: impl Fn(&mut ClientsData) -> bool + Send + Sync + 'static, -) -> (ClientsData, Result<(), FailedClient>) { - let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); - let (source_client, target_client) = prepare_test_clients( - exit_sender, - state_function, - vec![ - (5, (TestSourceHeader(false, 5, 5), None)), - (6, (TestSourceHeader(false, 6, 6), None)), - (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(true, 8, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10, 10), None)), - ] - .into_iter() - .collect(), - ); - let sync_params = test_sync_params(); - - let clients_data = source_client.data.clone(); - let result = async_std::task::block_on(run_until_connection_lost( - source_client, - target_client, - sync_params, - None, - exit_receiver.into_future().map(|(_, _)| ()), - )); - - let clients_data = clients_data.lock().clone(); - (clients_data, result) -} - -#[test] -fn finality_sync_loop_works() { - let (client_data, result) = run_sync_loop(|data| { - // header#7 has persistent finality proof, but it isn't mandatory => it isn't submitted, - // because header#8 has persistent finality proof && it is mandatory => it is submitted - // header#9 has persistent finality proof, but it isn't mandatory => it is submitted, - // because there are no more persistent finality proofs - // - // once this ^^^ is done, we generate more blocks && read proof for blocks 12 and 14 from - // the stream - if data.target_best_block_id.0 == 9 { - data.source_best_block_number = 14; - data.source_headers.insert(11, (TestSourceHeader(false, 11, 11), None)); - data.source_headers - .insert(12, (TestSourceHeader(false, 12, 12), Some(TestFinalityProof(12)))); - data.source_headers.insert(13, (TestSourceHeader(false, 13, 13), None)); - data.source_headers - .insert(14, (TestSourceHeader(false, 14, 14), Some(TestFinalityProof(14)))); - } - // once this ^^^ is done, we generate more blocks && read persistent proof for block 16 - if data.target_best_block_id.0 == 14 { - data.source_best_block_number = 17; - data.source_headers.insert(15, (TestSourceHeader(false, 15, 15), None)); - data.source_headers - .insert(16, (TestSourceHeader(false, 16, 16), Some(TestFinalityProof(16)))); - data.source_headers.insert(17, (TestSourceHeader(false, 17, 17), None)); - } - - data.target_best_block_id.0 == 16 - }); - - assert_eq!(result, Ok(())); - assert_eq!( - client_data.target_headers, - vec![ - // before adding 11..14: finality proof for mandatory header#8 - (TestSourceHeader(true, 8, 8), TestFinalityProof(8)), - // before adding 11..14: persistent finality proof for non-mandatory header#9 - (TestSourceHeader(false, 9, 9), TestFinalityProof(9)), - // after adding 11..14: ephemeral finality proof for non-mandatory header#14 - (TestSourceHeader(false, 14, 14), TestFinalityProof(14)), - // after adding 15..17: persistent finality proof for non-mandatory header#16 - (TestSourceHeader(false, 16, 16), TestFinalityProof(16)), - ], - ); -} - -fn run_only_mandatory_headers_mode_test( - only_mandatory_headers: bool, - has_mandatory_headers: bool, -) -> Option<(TestSourceHeader, TestFinalityProof)> { - let (exit_sender, _) = futures::channel::mpsc::unbounded(); - let (source_client, target_client) = prepare_test_clients( - exit_sender, - |_| false, - vec![ - (6, (TestSourceHeader(false, 6, 6), Some(TestFinalityProof(6)))), - (7, (TestSourceHeader(false, 7, 7), Some(TestFinalityProof(7)))), - (8, (TestSourceHeader(has_mandatory_headers, 8, 8), Some(TestFinalityProof(8)))), - (9, (TestSourceHeader(false, 9, 9), Some(TestFinalityProof(9)))), - (10, (TestSourceHeader(false, 10, 10), Some(TestFinalityProof(10)))), - ] - .into_iter() - .collect(), - ); - async_std::task::block_on(select_header_to_submit( - &source_client, - &target_client, - &mut RestartableFinalityProofsStream::from(futures::stream::empty().boxed()), - &mut vec![], - 10, - 5, - &FinalitySyncParams { - tick: Duration::from_secs(0), - recent_finality_proofs_limit: 0, - stall_timeout: Duration::from_secs(0), - only_mandatory_headers, - }, - )) - .unwrap() -} - -#[test] -fn select_header_to_submit_skips_non_mandatory_headers_when_only_mandatory_headers_are_required() { - assert_eq!(run_only_mandatory_headers_mode_test(true, false), None); - assert_eq!( - run_only_mandatory_headers_mode_test(false, false), - Some((TestSourceHeader(false, 10, 10), TestFinalityProof(10))), - ); -} - -#[test] -fn select_header_to_submit_selects_mandatory_headers_when_only_mandatory_headers_are_required() { - assert_eq!( - run_only_mandatory_headers_mode_test(true, true), - Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), - ); - assert_eq!( - run_only_mandatory_headers_mode_test(false, true), - Some((TestSourceHeader(true, 8, 8), TestFinalityProof(8))), - ); -} - -#[test] -fn select_better_recent_finality_proof_works() { - // if there are no unjustified headers, nothing is changed - assert_eq!( - select_better_recent_finality_proof::( - &[(5, TestFinalityProof(5))], - &mut vec![], - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - - // if there are no recent finality proofs, nothing is changed - assert_eq!( - select_better_recent_finality_proof::( - &[], - &mut vec![TestSourceHeader(false, 5, 5)], - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - - // if there's no intersection between recent finality proofs and unjustified headers, nothing is - // changed - let mut unjustified_headers = - vec![TestSourceHeader(false, 9, 9), TestSourceHeader(false, 10, 10)]; - assert_eq!( - select_better_recent_finality_proof::( - &[(1, TestFinalityProof(1)), (4, TestFinalityProof(4))], - &mut unjustified_headers, - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - - // if there's intersection between recent finality proofs and unjustified headers, but there are - // no proofs in this intersection, nothing is changed - let mut unjustified_headers = vec![ - TestSourceHeader(false, 8, 8), - TestSourceHeader(false, 9, 9), - TestSourceHeader(false, 10, 10), - ]; - assert_eq!( - select_better_recent_finality_proof::( - &[(7, TestFinalityProof(7)), (11, TestFinalityProof(11))], - &mut unjustified_headers, - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ); - assert_eq!( - unjustified_headers, - vec![ - TestSourceHeader(false, 8, 8), - TestSourceHeader(false, 9, 9), - TestSourceHeader(false, 10, 10) - ] - ); - - // if there's intersection between recent finality proofs and unjustified headers and there's - // a proof in this intersection: - // - this better (last from intersection) proof is selected; - // - 'obsolete' unjustified headers are pruned. - let mut unjustified_headers = vec![ - TestSourceHeader(false, 8, 8), - TestSourceHeader(false, 9, 9), - TestSourceHeader(false, 10, 10), - ]; - assert_eq!( - select_better_recent_finality_proof::( - &[(7, TestFinalityProof(7)), (9, TestFinalityProof(9))], - &mut unjustified_headers, - Some((TestSourceHeader(false, 2, 2), TestFinalityProof(2))), - ), - Some((TestSourceHeader(false, 9, 9), TestFinalityProof(9))), - ); -} - -#[test] -fn read_finality_proofs_from_stream_works() { - // when stream is currently empty, nothing is changed - let mut recent_finality_proofs = vec![(1, TestFinalityProof(1))]; - let mut stream = futures::stream::pending().into(); - read_finality_proofs_from_stream::( - &mut stream, - &mut recent_finality_proofs, - ); - assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1))]); - assert!(!stream.needs_restart); - - // when stream has entry with target, it is added to the recent proofs container - let mut stream = futures::stream::iter(vec![TestFinalityProof(4)]) - .chain(futures::stream::pending()) - .into(); - read_finality_proofs_from_stream::( - &mut stream, - &mut recent_finality_proofs, - ); - assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))]); - assert!(!stream.needs_restart); - - // when stream has ended, we'll need to restart it - let mut stream = futures::stream::empty().into(); - read_finality_proofs_from_stream::( - &mut stream, - &mut recent_finality_proofs, - ); - assert_eq!(recent_finality_proofs, vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))]); - assert!(stream.needs_restart); -} - -#[test] -fn prune_recent_finality_proofs_works() { - let original_recent_finality_proofs: FinalityProofs = vec![ - (10, TestFinalityProof(10)), - (13, TestFinalityProof(13)), - (15, TestFinalityProof(15)), - (17, TestFinalityProof(17)), - (19, TestFinalityProof(19)), - ] - .into_iter() - .collect(); - - // when there's proof for justified header in the vec - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(10, &mut recent_finality_proofs, 1024); - assert_eq!(&original_recent_finality_proofs[1..], recent_finality_proofs,); - - // when there are no proof for justified header in the vec - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(11, &mut recent_finality_proofs, 1024); - assert_eq!(&original_recent_finality_proofs[1..], recent_finality_proofs,); - - // when there are too many entries after initial prune && they also need to be pruned - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(10, &mut recent_finality_proofs, 2); - assert_eq!(&original_recent_finality_proofs[3..], recent_finality_proofs,); - - // when last entry is pruned - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(19, &mut recent_finality_proofs, 2); - assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); - - // when post-last entry is pruned - let mut recent_finality_proofs = original_recent_finality_proofs.clone(); - prune_recent_finality_proofs::(20, &mut recent_finality_proofs, 2); - assert_eq!(&original_recent_finality_proofs[5..], recent_finality_proofs,); -} - -#[test] -fn different_forks_at_source_and_at_target_are_detected() { - let (exit_sender, _exit_receiver) = futures::channel::mpsc::unbounded(); - let (source_client, target_client) = prepare_test_clients( - exit_sender, - |_| false, - vec![ - (5, (TestSourceHeader(false, 5, 42), None)), - (6, (TestSourceHeader(false, 6, 6), None)), - (7, (TestSourceHeader(false, 7, 7), None)), - (8, (TestSourceHeader(false, 8, 8), None)), - (9, (TestSourceHeader(false, 9, 9), None)), - (10, (TestSourceHeader(false, 10, 10), None)), - ] - .into_iter() - .collect(), - ); - - let mut progress = (Instant::now(), None); - let mut finality_proofs_stream = futures::stream::iter(vec![]).boxed().into(); - let mut recent_finality_proofs = Vec::new(); - let metrics_sync = SyncLoopMetrics::new(None, "source", "target").unwrap(); - async_std::task::block_on(run_loop_iteration::( - &source_client, - &target_client, - FinalityLoopState { - progress: &mut progress, - finality_proofs_stream: &mut finality_proofs_stream, - recent_finality_proofs: &mut recent_finality_proofs, - submitted_header_number: None, - }, - &test_sync_params(), - &Some(metrics_sync.clone()), - )) - .unwrap(); - - assert!(!metrics_sync.is_using_same_fork()); -} - -#[test] -fn stalls_when_transaction_tracker_returns_error() { - let (_, result) = run_sync_loop(|data| { - data.target_transaction_tracker = TestTransactionTracker(TrackedTransactionStatus::Lost); - data.target_best_block_id = HeaderId(5, 5); - data.target_best_block_id.0 == 16 - }); - - assert_eq!(result, Err(FailedClient::Both)); -} - -#[test] -fn stalls_when_transaction_tracker_returns_finalized_but_transaction_fails() { - let (_, result) = run_sync_loop(|data| { - data.target_best_block_id = HeaderId(5, 5); - data.target_best_block_id.0 == 16 - }); - - assert_eq!(result, Err(FailedClient::Both)); -} diff --git a/relays/finality/src/finality_proofs.rs b/relays/finality/src/finality_proofs.rs new file mode 100644 index 0000000000000..d457c0693bf3e --- /dev/null +++ b/relays/finality/src/finality_proofs.rs @@ -0,0 +1,227 @@ +// Copyright 2019-2023 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 . + +use crate::{base::SourceClientBase, FinalityPipeline}; + +use bp_header_chain::FinalityProof; +use futures::{FutureExt, Stream, StreamExt}; +use std::pin::Pin; + +/// Finality proofs container. Ordered by target header number. +pub type FinalityProofs

= + Vec<(

::Number,

::FinalityProof)>; + +/// Source finality proofs stream that may be restarted. +pub struct FinalityProofsStream> { + /// The underlying stream. + stream: Option>>, +} + +impl> FinalityProofsStream { + pub fn new() -> Self { + Self { stream: None } + } + + fn next(&mut self) -> Option<::Item> { + let stream = match &mut self.stream { + Some(stream) => stream, + None => return None, + }; + + match stream.next().now_or_never() { + Some(Some(finality_proof)) => Some(finality_proof), + Some(None) => { + self.stream = None; + None + }, + None => None, + } + } + + pub async fn ensure_stream(&mut self, source_client: &SC) -> Result<(), SC::Error> { + if self.stream.is_none() { + log::warn!(target: "bridge", "{} finality proofs stream is being started / restarted", + P::SOURCE_NAME); + + let stream = source_client.finality_proofs().await.map_err(|error| { + log::error!( + target: "bridge", + "Failed to subscribe to {} justifications: {:?}", + P::SOURCE_NAME, + error, + ); + + error + })?; + self.stream = Some(Box::pin(stream)); + } + + Ok(()) + } +} + +/// Source finality proofs buffer. +pub struct FinalityProofsBuf { + /// Proofs buffer. + buf: FinalityProofs

, +} + +impl FinalityProofsBuf

{ + pub fn new(buf: FinalityProofs

) -> Self { + Self { buf } + } + + pub fn buf(&self) -> &FinalityProofs

{ + &self.buf + } + + pub fn fill>(&mut self, stream: &mut FinalityProofsStream) { + let mut proofs_count = 0; + let mut first_header_number = None; + let mut last_header_number = None; + while let Some(finality_proof) = stream.next() { + let target_header_number = finality_proof.target_header_number(); + first_header_number.get_or_insert(target_header_number); + last_header_number = Some(target_header_number); + proofs_count += 1; + + self.buf.push((target_header_number, finality_proof)); + } + + if proofs_count != 0 { + log::trace!( + target: "bridge", + "Read {} finality proofs from {} finality stream for headers in range [{:?}; {:?}]", + proofs_count, + P::SOURCE_NAME, + first_header_number, + last_header_number, + ); + } + } + + pub fn prune(&mut self, until_hdr_num: P::Number, buf_limit: usize) { + let kept_hdr_idx = self + .buf + .binary_search_by_key(&until_hdr_num, |(hdr_num, _)| *hdr_num) + .map(|idx| idx + 1) + .unwrap_or_else(|idx| idx); + let buf_limit_idx = self.buf.len().saturating_sub(buf_limit); + + self.buf = self.buf.split_off(std::cmp::max(kept_hdr_idx, buf_limit_idx)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + + impl> FinalityProofsStream { + fn from_stream(stream: SC::FinalityProofsStream) -> Self { + Self { stream: Some(Box::pin(stream)) } + } + } + + #[test] + fn finality_proofs_buf_fill_works() { + // when stream is currently empty, nothing is changed + let mut finality_proofs_buf = + FinalityProofsBuf:: { buf: vec![(1, TestFinalityProof(1))] }; + let mut stream = + FinalityProofsStream::::from_stream( + Box::pin(futures::stream::pending()), + ); + finality_proofs_buf.fill(&mut stream); + assert_eq!(finality_proofs_buf.buf, vec![(1, TestFinalityProof(1))]); + assert!(stream.stream.is_some()); + + // when stream has entry with target, it is added to the recent proofs container + let mut stream = + FinalityProofsStream::::from_stream( + Box::pin( + futures::stream::iter(vec![TestFinalityProof(4)]) + .chain(futures::stream::pending()), + ), + ); + finality_proofs_buf.fill(&mut stream); + assert_eq!( + finality_proofs_buf.buf, + vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] + ); + assert!(stream.stream.is_some()); + + // when stream has ended, we'll need to restart it + let mut stream = + FinalityProofsStream::::from_stream( + Box::pin(futures::stream::empty()), + ); + finality_proofs_buf.fill(&mut stream); + assert_eq!( + finality_proofs_buf.buf, + vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] + ); + assert!(stream.stream.is_none()); + } + + #[test] + fn finality_proofs_buf_prune_works() { + let original_finality_proofs_buf: FinalityProofs = vec![ + (10, TestFinalityProof(10)), + (13, TestFinalityProof(13)), + (15, TestFinalityProof(15)), + (17, TestFinalityProof(17)), + (19, TestFinalityProof(19)), + ] + .into_iter() + .collect(); + + // when there's proof for justified header in the vec + let mut finality_proofs_buf = FinalityProofsBuf:: { + buf: original_finality_proofs_buf.clone(), + }; + finality_proofs_buf.prune(10, 1024); + assert_eq!(&original_finality_proofs_buf[1..], finality_proofs_buf.buf,); + + // when there are no proof for justified header in the vec + let mut finality_proofs_buf = FinalityProofsBuf:: { + buf: original_finality_proofs_buf.clone(), + }; + finality_proofs_buf.prune(11, 1024); + assert_eq!(&original_finality_proofs_buf[1..], finality_proofs_buf.buf,); + + // when there are too many entries after initial prune && they also need to be pruned + let mut finality_proofs_buf = FinalityProofsBuf:: { + buf: original_finality_proofs_buf.clone(), + }; + finality_proofs_buf.prune(10, 2); + assert_eq!(&original_finality_proofs_buf[3..], finality_proofs_buf.buf,); + + // when last entry is pruned + let mut finality_proofs_buf = FinalityProofsBuf:: { + buf: original_finality_proofs_buf.clone(), + }; + finality_proofs_buf.prune(19, 2); + assert_eq!(&original_finality_proofs_buf[5..], finality_proofs_buf.buf,); + + // when post-last entry is pruned + let mut finality_proofs_buf = FinalityProofsBuf:: { + buf: original_finality_proofs_buf.clone(), + }; + finality_proofs_buf.prune(20, 2); + assert_eq!(&original_finality_proofs_buf[5..], finality_proofs_buf.buf,); + } +} diff --git a/relays/finality/src/headers.rs b/relays/finality/src/headers.rs new file mode 100644 index 0000000000000..bdb05c9d9b72f --- /dev/null +++ b/relays/finality/src/headers.rs @@ -0,0 +1,237 @@ +// 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 . + +use crate::{ + finality_loop::SyncInfo, finality_proofs::FinalityProofsBuf, Error, FinalitySyncPipeline, + SourceClient, SourceHeader, TargetClient, +}; + +use std::cmp::Ordering; + +/// Unjustified headers container. Ordered by header number. +pub type UnjustifiedHeaders = Vec; + +#[derive(Debug)] +#[cfg_attr(test, derive(Clone, PartialEq))] +pub struct JustifiedHeader { + pub header: P::Header, + pub proof: P::FinalityProof, +} + +impl JustifiedHeader

{ + pub fn number(&self) -> P::Number { + self.header.number() + } +} + +/// Finality proof that has been selected by the `read_missing_headers` function. +pub enum JustifiedHeaderSelector { + /// Mandatory header and its proof has been selected. We shall submit proof for this header. + Mandatory(JustifiedHeader

), + /// Regular header and its proof has been selected. We may submit this proof, or proof for + /// some better header. + Regular(UnjustifiedHeaders, JustifiedHeader

), + /// We haven't found any missing header with persistent proof at the target client. + None(UnjustifiedHeaders), +} + +impl JustifiedHeaderSelector

{ + pub(crate) async fn new, TC: TargetClient

>( + source_client: &SC, + info: &SyncInfo

, + ) -> Result> { + let mut unjustified_headers = Vec::new(); + let mut maybe_justified_header = None; + + let mut header_number = info.best_number_at_target + 1.into(); + while header_number <= info.best_number_at_source { + let (header, maybe_proof) = source_client + .header_and_finality_proof(header_number) + .await + .map_err(Error::Source)?; + + match (header.is_mandatory(), maybe_proof) { + (true, Some(proof)) => { + log::trace!(target: "bridge", "Header {:?} is mandatory", header_number); + return Ok(Self::Mandatory(JustifiedHeader { header, proof })) + }, + (true, None) => return Err(Error::MissingMandatoryFinalityProof(header.number())), + (false, Some(proof)) => { + log::trace!(target: "bridge", "Header {:?} has persistent finality proof", header_number); + unjustified_headers.clear(); + maybe_justified_header = Some(JustifiedHeader { header, proof }); + }, + (false, None) => { + unjustified_headers.push(header); + }, + } + + header_number = header_number + 1.into(); + } + + log::trace!( + target: "bridge", + "Read {} {} headers. Selected finality proof for header: {:?}", + info.num_headers(), + P::SOURCE_NAME, + maybe_justified_header.as_ref().map(|justified_header| &justified_header.header), + ); + + Ok(match maybe_justified_header { + Some(justified_header) => Self::Regular(unjustified_headers, justified_header), + None => Self::None(unjustified_headers), + }) + } + + pub fn select_mandatory(self) -> Option> { + match self { + JustifiedHeaderSelector::Mandatory(header) => Some(header), + _ => None, + } + } + + pub fn select(self, buf: &FinalityProofsBuf

) -> Option> { + let (unjustified_headers, maybe_justified_header) = match self { + JustifiedHeaderSelector::Mandatory(justified_header) => return Some(justified_header), + JustifiedHeaderSelector::Regular(unjustified_headers, justified_header) => + (unjustified_headers, Some(justified_header)), + JustifiedHeaderSelector::None(unjustified_headers) => (unjustified_headers, None), + }; + + let mut finality_proofs_iter = buf.buf().iter().rev(); + let mut maybe_finality_proof = finality_proofs_iter.next(); + + let mut unjustified_headers_iter = unjustified_headers.iter().rev(); + let mut maybe_unjustified_header = unjustified_headers_iter.next(); + + while let (Some(finality_proof), Some(unjustified_header)) = + (maybe_finality_proof, maybe_unjustified_header) + { + match finality_proof.0.cmp(&unjustified_header.number()) { + Ordering::Equal => { + log::trace!( + target: "bridge", + "Managed to improve selected {} finality proof {:?} to {:?}.", + P::SOURCE_NAME, + maybe_justified_header.as_ref().map(|justified_header| justified_header.number()), + finality_proof.0 + ); + return Some(JustifiedHeader { + header: unjustified_header.clone(), + proof: finality_proof.1.clone(), + }) + }, + Ordering::Less => maybe_unjustified_header = unjustified_headers_iter.next(), + Ordering::Greater => { + maybe_finality_proof = finality_proofs_iter.next(); + }, + } + } + + log::trace!( + target: "bridge", + "Could not improve selected {} finality proof {:?}.", + P::SOURCE_NAME, + maybe_justified_header.as_ref().map(|justified_header| justified_header.number()) + ); + maybe_justified_header + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + + #[test] + fn select_better_recent_finality_proof_works() { + // if there are no unjustified headers, nothing is changed + let finality_proofs_buf = + FinalityProofsBuf::::new(vec![(5, TestFinalityProof(5))]); + let justified_header = + JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; + let selector = JustifiedHeaderSelector::Regular(vec![], justified_header.clone()); + assert_eq!(selector.select(&finality_proofs_buf), Some(justified_header)); + + // if there are no buffered finality proofs, nothing is changed + let finality_proofs_buf = FinalityProofsBuf::::new(vec![]); + let justified_header = + JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; + let selector = JustifiedHeaderSelector::Regular( + vec![TestSourceHeader(false, 5, 5)], + justified_header.clone(), + ); + assert_eq!(selector.select(&finality_proofs_buf), Some(justified_header)); + + // if there's no intersection between recent finality proofs and unjustified headers, + // nothing is changed + let finality_proofs_buf = FinalityProofsBuf::::new(vec![ + (1, TestFinalityProof(1)), + (4, TestFinalityProof(4)), + ]); + let justified_header = + JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; + let selector = JustifiedHeaderSelector::Regular( + vec![TestSourceHeader(false, 9, 9), TestSourceHeader(false, 10, 10)], + justified_header.clone(), + ); + assert_eq!(selector.select(&finality_proofs_buf), Some(justified_header)); + + // if there's intersection between recent finality proofs and unjustified headers, but there + // are no proofs in this intersection, nothing is changed + let finality_proofs_buf = FinalityProofsBuf::::new(vec![ + (7, TestFinalityProof(7)), + (11, TestFinalityProof(11)), + ]); + let justified_header = + JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; + let selector = JustifiedHeaderSelector::Regular( + vec![ + TestSourceHeader(false, 8, 8), + TestSourceHeader(false, 9, 9), + TestSourceHeader(false, 10, 10), + ], + justified_header.clone(), + ); + assert_eq!(selector.select(&finality_proofs_buf), Some(justified_header)); + + // if there's intersection between recent finality proofs and unjustified headers and + // there's a proof in this intersection: + // - this better (last from intersection) proof is selected; + // - 'obsolete' unjustified headers are pruned. + let finality_proofs_buf = FinalityProofsBuf::::new(vec![ + (7, TestFinalityProof(7)), + (9, TestFinalityProof(9)), + ]); + let justified_header = + JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; + let selector = JustifiedHeaderSelector::Regular( + vec![ + TestSourceHeader(false, 8, 8), + TestSourceHeader(false, 9, 9), + TestSourceHeader(false, 10, 10), + ], + justified_header, + ); + assert_eq!( + selector.select(&finality_proofs_buf), + Some(JustifiedHeader { + header: TestSourceHeader(false, 9, 9), + proof: TestFinalityProof(9) + }) + ); + } +} diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index 599cf2f9f9de3..51cd9a0935535 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -26,11 +26,14 @@ pub use crate::{ }; use bp_header_chain::ConsensusLogReader; +use relay_utils::{FailedClient, MaybeConnectionError}; use std::fmt::Debug; mod base; mod finality_loop; -mod finality_loop_tests; +mod finality_proofs; +mod headers; +mod mock; mod sync_loop_metrics; /// Finality proofs synchronization pipeline. @@ -50,3 +53,38 @@ pub trait SourceHeader: Clone + Debug + PartialEq + Send + /// Returns true if this header needs to be submitted to target node. fn is_mandatory(&self) -> bool; } + +/// Error that may happen inside finality synchronization loop. +#[derive(Debug)] +enum Error { + /// Source client request has failed with given error. + Source(SourceError), + /// Target client request has failed with given error. + Target(TargetError), + /// Finality proof for mandatory header is missing from the source node. + MissingMandatoryFinalityProof(P::Number), + /// `submit_finality_proof` transaction failed + ProofSubmissionTxFailed { + #[allow(dead_code)] + submitted_number: P::Number, + #[allow(dead_code)] + best_number_at_target: P::Number, + }, + /// `submit_finality_proof` transaction lost + ProofSubmissionTxLost, +} + +impl Error +where + P: FinalitySyncPipeline, + SourceError: MaybeConnectionError, + TargetError: MaybeConnectionError, +{ + fn fail_if_connection_error(&self) -> Result<(), FailedClient> { + match *self { + Error::Source(ref error) if error.is_connection_error() => Err(FailedClient::Source), + Error::Target(ref error) if error.is_connection_error() => Err(FailedClient::Target), + _ => Ok(()), + } + } +} diff --git a/relays/finality/src/mock.rs b/relays/finality/src/mock.rs new file mode 100644 index 0000000000000..181504ce26070 --- /dev/null +++ b/relays/finality/src/mock.rs @@ -0,0 +1,209 @@ +// 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 . + +//! Tests for finality synchronization loop. + +#![cfg(test)] + +use crate::{ + base::SourceClientBase, + finality_loop::{SourceClient, TargetClient}, + FinalityPipeline, FinalitySyncPipeline, SourceHeader, +}; + +use async_trait::async_trait; +use bp_header_chain::{FinalityProof, GrandpaConsensusLogReader}; +use futures::{Stream, StreamExt}; +use parking_lot::Mutex; +use relay_utils::{ + relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError, TrackedTransactionStatus, + TransactionTracker, +}; +use std::{collections::HashMap, pin::Pin, sync::Arc}; + +type IsMandatory = bool; +pub type TestNumber = u64; +type TestHash = u64; + +#[derive(Clone, Debug)] +pub struct TestTransactionTracker(pub TrackedTransactionStatus>); + +impl Default for TestTransactionTracker { + fn default() -> TestTransactionTracker { + TestTransactionTracker(TrackedTransactionStatus::Finalized(Default::default())) + } +} + +#[async_trait] +impl TransactionTracker for TestTransactionTracker { + type HeaderId = HeaderId; + + async fn wait(self) -> TrackedTransactionStatus> { + self.0 + } +} + +#[derive(Debug, Clone)] +pub enum TestError { + NonConnection, +} + +impl MaybeConnectionError for TestError { + fn is_connection_error(&self) -> bool { + false + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct TestFinalitySyncPipeline; + +impl FinalityPipeline for TestFinalitySyncPipeline { + const SOURCE_NAME: &'static str = "TestSource"; + const TARGET_NAME: &'static str = "TestTarget"; + + type Hash = TestHash; + type Number = TestNumber; + type FinalityProof = TestFinalityProof; +} + +impl FinalitySyncPipeline for TestFinalitySyncPipeline { + type ConsensusLogReader = GrandpaConsensusLogReader; + type Header = TestSourceHeader; +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TestSourceHeader(pub IsMandatory, pub TestNumber, pub TestHash); + +impl SourceHeader> + for TestSourceHeader +{ + fn hash(&self) -> TestHash { + self.2 + } + + fn number(&self) -> TestNumber { + self.1 + } + + fn is_mandatory(&self) -> bool { + self.0 + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TestFinalityProof(pub TestNumber); + +impl FinalityProof for TestFinalityProof { + fn target_header_number(&self) -> TestNumber { + self.0 + } +} + +#[derive(Debug, Clone, Default)] +pub struct ClientsData { + pub source_best_block_number: TestNumber, + pub source_headers: HashMap)>, + pub source_proofs: Vec, + + pub target_best_block_id: HeaderId, + pub target_headers: Vec<(TestSourceHeader, TestFinalityProof)>, + pub target_transaction_tracker: TestTransactionTracker, +} + +#[derive(Clone)] +pub struct TestSourceClient { + pub on_method_call: Arc, + pub data: Arc>, +} + +#[async_trait] +impl RelayClient for TestSourceClient { + type Error = TestError; + + async fn reconnect(&mut self) -> Result<(), TestError> { + unreachable!() + } +} + +#[async_trait] +impl SourceClientBase for TestSourceClient { + type FinalityProofsStream = Pin + 'static + Send>>; + + async fn finality_proofs(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut data); + Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) + } +} + +#[async_trait] +impl SourceClient for TestSourceClient { + async fn best_finalized_block_number(&self) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut data); + Ok(data.source_best_block_number) + } + + async fn header_and_finality_proof( + &self, + number: TestNumber, + ) -> Result<(TestSourceHeader, Option), TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(&mut data); + data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) + } +} + +#[derive(Clone)] +pub struct TestTargetClient { + pub on_method_call: Arc, + pub data: Arc>, +} + +#[async_trait] +impl RelayClient for TestTargetClient { + type Error = TestError; + + async fn reconnect(&mut self) -> Result<(), TestError> { + unreachable!() + } +} + +#[async_trait] +impl TargetClient for TestTargetClient { + type TransactionTracker = TestTransactionTracker; + + async fn best_finalized_source_block_id( + &self, + ) -> Result, TestError> { + let mut data = self.data.lock(); + (self.on_method_call)(&mut data); + Ok(data.target_best_block_id) + } + + async fn submit_finality_proof( + &self, + header: TestSourceHeader, + proof: TestFinalityProof, + ) -> Result { + let mut data = self.data.lock(); + (self.on_method_call)(&mut data); + data.target_best_block_id = HeaderId(header.number(), header.hash()); + data.target_headers.push((header, proof)); + (self.on_method_call)(&mut data); + Ok(data.target_transaction_tracker.clone()) + } +} diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index 41c6c53daf4d6..c94af6108957a 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -125,7 +125,7 @@ impl SubstrateFinalitySource

{ Error, > { let client = self.client.clone(); - let best_finalized_block_number = self.client.best_finalized_header_number().await?; + let best_finalized_block_number = client.best_finalized_header_number().await?; Ok(try_unfold((client, block_number), move |(client, current_block_number)| async move { // if we've passed the `best_finalized_block_number`, we no longer need persistent // justifications diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index 11e14744a075c..dad7293de6d28 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -130,19 +130,19 @@ impl Loop { match result { Ok(()) => break, - Err(failed_client) => + Err(failed_client) => { + log::debug!(target: "bridge", "Restarting relay loop"); + reconnect_failed_client( failed_client, self.reconnect_delay, &mut self.source_client, &mut self.target_client, ) - .await, + .await + }, } - - log::debug!(target: "bridge", "Restarting relay loop"); } - Ok(()) }; @@ -194,7 +194,7 @@ impl LoopMetrics { Err(err) => { log::trace!( target: "bridge-metrics", - "Failed to create tokio runtime. Prometheus meterics are not available: {:?}", + "Failed to create tokio runtime. Prometheus metrics are not available: {:?}", err, ); return From 3c35680a523bca6ee91e0bb1b8bb2c6c05ce6e21 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 16 Aug 2023 16:49:11 +0300 Subject: [PATCH 1093/1210] Dynamic fees for bridges-v1 (#2294) * impl backpressure in the XcmBlobHaulerAdapter * LocalXcmQueueManager + more adapters * OnMessageDelviered callback * forbid mesage delivery transactions when the channel between target bridge hub and target asset hub is suspended * pallet-xcm-bridge-hub-router * removed commented code * improvements and tests for palle-xcm-bridge-router * use LocalXcmChannel in XcmBlobMessageDispatch * new tests for logic changes in messages pallet * tests for LocalXcmQueueSuspender * tests for LocalXcmQueueMessageProcessor * tests for new logic in the XcmBlobHaulerAdapter * fix other tests in the bridge-runtime-common * extension_reject_call_when_dispatcher_is_inactive * benchmarks for pallet-xcm-bridge-hub-router * get rid of redundant storage value * add new pallet to verify-pallets-build.sh * fixing spellcheck, clippy and rustdoc * trigger CI * Revert "trigger CI" This reverts commit 48f1ba032334e3c6d8470436483736988aa060ac. * change log target for xcm bridge router pallet * Update modules/xcm-bridge-hub-router/src/lib.rs Co-authored-by: Branislav Kontur * use saturated_len where possible * fmt * (Suggestion) Ability to externalize configuration for `ExporterFor` (#2313) * Ability to externalize configuration for `ExporterFor` (Replaced `BridgedNetworkId/SiblingBridgeHubLocation` with `Bridges: ExporterFor`) * Fix millau * Compile fix * Return back `BridgedNetworkId` but as optional filter * Replaced `BaseFee` with fees from inner `Bridges: ExporterFor` * typo * Clippy * Rename LocalXcmChannel to XcmChannelStatusProvider (#2319) * Rename LocalXcmChannel to XcmChannelStatusProvider * fmt * added/fixed some docs * Dynamic fees v1: report congestion status to sending chain (#2318) * report congestion status: changes at the sending chain * OnMessagesDelivered is back * report congestion status: changes at the bridge hub * moer logging * fix? benchmarks * spelling * tests for XcmBlobHaulerAdapter and LocalXcmQueueManager * tests for messages pallet * fix typo * rustdoc * Update modules/messages/src/lib.rs * apply review suggestions * ".git/.scripts/commands/fmt/fmt.sh" * Added `XcmBridgeHubRouterCall::report_bridge_status` encodings for AHK/P (#2350) * Added `XcmBridgeHubRouterCall::report_bridge_status` encodings for AHK/P * Spellcheck * Added const for `XcmBridgeHubRouterTransactCallMaxWeight` * Cargo.lock * Introduced base delivery fee constants * Congestion messages as Optional to turn on/off `supports_congestion_detection` * Spellcheck * Ability to externalize dest for benchmarks * Ability to externalize dest for benchmarks --------- Co-authored-by: Branislav Kontur Co-authored-by: command-bot <> --- bin/millau/runtime/Cargo.toml | 5 + bin/millau/runtime/src/lib.rs | 43 +- bin/millau/runtime/src/rialto_messages.rs | 19 +- .../runtime/src/rialto_parachain_messages.rs | 20 +- bin/millau/runtime/src/xcm_config.rs | 40 +- bin/rialto-parachain/runtime/src/lib.rs | 1 + .../runtime/src/millau_messages.rs | 19 +- bin/rialto/runtime/src/lib.rs | 1 + bin/rialto/runtime/src/millau_messages.rs | 19 +- bin/runtime-common/Cargo.toml | 2 + bin/runtime-common/src/messages_call_ext.rs | 29 +- .../src/messages_xcm_extension.rs | 397 ++++++++++++- bin/runtime-common/src/mock.rs | 40 +- .../src/refund_relayer_extension.rs | 3 +- modules/messages/src/lib.rs | 81 ++- modules/messages/src/mock.rs | 37 +- modules/xcm-bridge-hub-router/Cargo.toml | 59 ++ .../xcm-bridge-hub-router/src/benchmarking.rs | 96 +++ modules/xcm-bridge-hub-router/src/lib.rs | 557 ++++++++++++++++++ modules/xcm-bridge-hub-router/src/mock.rs | 148 +++++ modules/xcm-bridge-hub-router/src/weights.rs | 208 +++++++ primitives/chain-asset-hub-kusama/Cargo.toml | 26 + primitives/chain-asset-hub-kusama/src/lib.rs | 49 ++ .../chain-asset-hub-polkadot/Cargo.toml | 26 + .../chain-asset-hub-polkadot/src/lib.rs | 49 ++ primitives/messages/src/lib.rs | 8 + primitives/messages/src/source_chain.rs | 17 +- primitives/messages/src/target_chain.rs | 13 + primitives/xcm-bridge-hub-router/Cargo.toml | 24 + primitives/xcm-bridge-hub-router/src/lib.rs | 66 +++ 30 files changed, 2031 insertions(+), 71 deletions(-) create mode 100644 modules/xcm-bridge-hub-router/Cargo.toml create mode 100644 modules/xcm-bridge-hub-router/src/benchmarking.rs create mode 100644 modules/xcm-bridge-hub-router/src/lib.rs create mode 100644 modules/xcm-bridge-hub-router/src/mock.rs create mode 100644 modules/xcm-bridge-hub-router/src/weights.rs create mode 100644 primitives/chain-asset-hub-kusama/Cargo.toml create mode 100644 primitives/chain-asset-hub-kusama/src/lib.rs create mode 100644 primitives/chain-asset-hub-polkadot/Cargo.toml create mode 100644 primitives/chain-asset-hub-polkadot/src/lib.rs create mode 100644 primitives/xcm-bridge-hub-router/Cargo.toml create mode 100644 primitives/xcm-bridge-hub-router/src/lib.rs diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index f4ad89159e068..ccff85b99eb60 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -23,12 +23,14 @@ bp-rialto = { path = "../../../primitives/chain-rialto", default-features = fals bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-westend = { path = "../../../primitives/chain-westend", default-features = false } +bp-xcm-bridge-hub-router = { path = "../../../primitives/xcm-bridge-hub-router", default-features = false } bridge-runtime-common = { path = "../../runtime-common", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false } pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } +pallet-xcm-bridge-hub-router = { path = "../../../modules/xcm-bridge-hub-router", default-features = false } # Substrate Dependencies @@ -90,6 +92,7 @@ std = [ "bp-rialto-parachain/std", "bp-runtime/std", "bp-westend/std", + "bp-xcm-bridge-hub-router/std", "bridge-runtime-common/std", "codec/std", "frame-executive/std", @@ -114,6 +117,7 @@ std = [ "pallet-transaction-payment/std", "pallet-utility/std", "pallet-xcm/std", + "pallet-xcm-bridge-hub-router/std", "scale-info/std", "sp-api/std", "sp-block-builder/std", @@ -140,6 +144,7 @@ runtime-benchmarks = [ "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "pallet-xcm-bridge-hub-router/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index a1526bc2e1810..2067dfccb562f 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -55,6 +55,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; +use xcm_builder::NetworkExportTable; // to be able to use Millau runtime in `bridge-runtime-common` tests pub use bridge_runtime_common; @@ -65,8 +66,8 @@ pub use frame_support::{ dispatch::DispatchClass, parameter_types, traits::{ - ConstBool, ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, Imbalance, - KeyOwnerProofSystem, + ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, + Imbalance, KeyOwnerProofSystem, }, weights::{ constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, @@ -464,6 +465,7 @@ impl pallet_bridge_messages::Config for Runtime { WithRialtoMessagesInstance, frame_support::traits::ConstU64<100_000>, >; + type OnMessagesDelivered = (); type SourceHeaderChain = crate::rialto_messages::RialtoAsSourceHeaderChain; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; @@ -495,6 +497,7 @@ impl pallet_bridge_messages::Config for Run WithRialtoParachainMessagesInstance, frame_support::traits::ConstU64<100_000>, >; + type OnMessagesDelivered = (); type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsSourceHeaderChain; type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; @@ -544,6 +547,27 @@ impl pallet_utility::Config for Runtime { type WeightInfo = (); } +// this config is totally incorrect - the pallet is not actually used at this runtime. We need +// it only to be able to run benchmarks and make required traits (and default weights for tests). +parameter_types! { + pub BridgeTable: Vec<(xcm::prelude::NetworkId, xcm::prelude::MultiLocation, Option)> + = vec![(xcm_config::RialtoNetwork::get(), xcm_config::TokenLocation::get(), Some((xcm_config::TokenAssetId::get(), 1_000_000_000_u128).into()))]; +} +impl pallet_xcm_bridge_hub_router::Config for Runtime { + type WeightInfo = (); + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::RialtoNetwork; + type Bridges = NetworkExportTable; + + type BridgeHubOrigin = frame_system::EnsureRoot; + type ToBridgeHubSender = xcm_config::XcmRouter; + type WithBridgeHubChannel = xcm_config::EmulatedSiblingXcmpChannel; + + type ByteFee = ConstU128<1_000>; + type FeeAsset = xcm_config::TokenAssetId; +} + construct_runtime!( pub enum Runtime { System: frame_system::{Pallet, Call, Config, Storage, Event}, @@ -582,6 +606,9 @@ construct_runtime!( // Pallet for sending XCM. XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, + + // Pallets that are not actually used here (yet?), but we need to run benchmarks on it. + XcmBridgeHubRouter: pallet_xcm_bridge_hub_router::{Pallet, Storage} = 200, } ); @@ -654,6 +681,7 @@ mod benches { [pallet_bridge_grandpa, BridgeRialtoGrandpa] [pallet_bridge_parachains, ParachainsBench::] [pallet_bridge_relayers, RelayersBench::] + [pallet_xcm_bridge_hub_router, XcmBridgeHubRouterBench::] ); } @@ -980,6 +1008,7 @@ impl_runtime_apis! { use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; use pallet_bridge_parachains::benchmarking::Pallet as ParachainsBench; use pallet_bridge_relayers::benchmarking::Pallet as RelayersBench; + use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -1026,6 +1055,10 @@ impl_runtime_apis! { Pallet as RelayersBench, Config as RelayersConfig, }; + use pallet_xcm_bridge_hub_router::benchmarking::{ + Pallet as XcmBridgeHubRouterBench, + Config as XcmBridgeHubRouterConfig, + }; use rialto_messages::WithRialtoMessageBridge; use rialto_parachain_messages::WithRialtoParachainMessageBridge; @@ -1136,6 +1169,12 @@ impl_runtime_apis! { } } + impl XcmBridgeHubRouterConfig<()> for Runtime { + fn make_congested() { + xcm_config::EmulatedSiblingXcmpChannel::make_congested() + } + } + let mut batches = Vec::::new(); let params = (&config, &whitelist); diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index a9a80fdf7d715..884f994feaaf1 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -23,10 +23,11 @@ use bridge_runtime_common::{ messages::{ self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, }, - messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; use pallet_bridge_relayers::WeightInfoExt as _; +use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto. @@ -42,6 +43,11 @@ parameter_types! { /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; + /// Lane used by the with-Rialto bridge. + pub RialtoSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); + + /// Dummy message used in configuration. + pub DummyXcmMessage: Xcm<()> = Xcm::new(); } /// Message payload for Millau -> Rialto messages. @@ -66,6 +72,7 @@ pub type FromRialtoMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< crate::xcm_config::OnMillauBlobDispatcher, (), + (), >; /// Maximal outbound payload size of Millau -> Rialto messages. @@ -122,11 +129,13 @@ pub type ToRialtoBlobExporter = HaulBlobExporter< pub struct ToRialtoXcmBlobHauler; impl XcmBlobHauler for ToRialtoXcmBlobHauler { - type MessageSender = pallet_bridge_messages::Pallet; + type Runtime = Runtime; + type MessagesInstance = WithRialtoMessagesInstance; + type SenderAndLane = RialtoSenderAndLane; - fn xcm_lane() -> LaneId { - XCM_LANE - } + type ToSourceChainSender = crate::xcm_config::XcmRouter; + type CongestedMessage = DummyXcmMessage; + type UncongestedMessage = DummyXcmMessage; } impl pallet_bridge_messages::WeightInfoExt for crate::weights::RialtoMessagesWeightInfo { diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index a8540b705d754..2eff0835c39ef 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -25,10 +25,11 @@ use bridge_runtime_common::{ messages::{ self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, }, - messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; use pallet_bridge_relayers::WeightInfoExt as _; +use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Rialto parachain. @@ -44,6 +45,11 @@ parameter_types! { /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; + /// Lane used by the with-RialtoParachain bridge. + pub RialtoParachainSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); + + /// Dummy message used in configuration. + pub DummyXcmMessage: Xcm<()> = Xcm::new(); } /// Message payload for Millau -> RialtoParachain messages. @@ -61,6 +67,7 @@ pub type FromRialtoParachainMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< crate::xcm_config::OnMillauBlobDispatcher, (), + (), >; /// Maximal outbound payload size of Millau -> RialtoParachain messages. @@ -122,12 +129,13 @@ pub type ToRialtoParachainBlobExporter = HaulBlobExporter< pub struct ToRialtoParachainXcmBlobHauler; impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { - type MessageSender = - pallet_bridge_messages::Pallet; + type Runtime = Runtime; + type MessagesInstance = WithRialtoParachainMessagesInstance; + type SenderAndLane = RialtoParachainSenderAndLane; - fn xcm_lane() -> LaneId { - XCM_LANE - } + type ToSourceChainSender = crate::xcm_config::XcmRouter; + type CongestedMessage = DummyXcmMessage; + type UncongestedMessage = DummyXcmMessage; } impl pallet_bridge_messages::WeightInfoExt diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs index 623c8219016fe..45236360ddcc1 100644 --- a/bin/millau/runtime/src/xcm_config.rs +++ b/bin/millau/runtime/src/xcm_config.rs @@ -42,6 +42,8 @@ parameter_types! { /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to /// the context". pub const TokenLocation: MultiLocation = Here.into_location(); + /// Token asset identifier. + pub TokenAssetId: AssetId = TokenLocation::get().into(); /// The Millau network ID. pub const ThisNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); /// The Rialto network ID. @@ -98,7 +100,7 @@ parameter_types! { } /// The XCM router. We are not sending messages to sibling/parent/child chains here. -pub type XcmRouter = (); +pub type XcmRouter = EmulatedSiblingXcmpChannel; /// The barriers one of which must be passed for an XCM message to be executed. pub type Barrier = ( @@ -235,6 +237,38 @@ impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { } } +/// Emulating XCMP channel with sibling chain. We don't have required infra here, at Millau, +/// so we have to provide at least something to be able to run benchmarks. +pub struct EmulatedSiblingXcmpChannel; + +impl SendXcm for EmulatedSiblingXcmpChannel { + type Ticket = (); + + fn validate( + _destination: &mut Option, + _message: &mut Option>, + ) -> SendResult { + Ok(((), Default::default())) + } + + fn deliver(_ticket: Self::Ticket) -> Result { + Ok(XcmHash::default()) + } +} + +impl EmulatedSiblingXcmpChannel { + /// Start emulating congested channel. + pub fn make_congested() { + frame_support::storage::unhashed::put(b"EmulatedSiblingXcmpChannel.Congested", &true); + } +} + +impl bp_xcm_bridge_hub_router::XcmChannelStatusProvider for EmulatedSiblingXcmpChannel { + fn is_congested() -> bool { + frame_support::storage::unhashed::get_or_default(b"EmulatedSiblingXcmpChannel.Congested") + } +} + #[cfg(test)] mod tests { use super::*; @@ -357,7 +391,7 @@ mod tests { let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + XcmBlobMessageDispatchResult::Dispatched, )); } @@ -370,7 +404,7 @@ mod tests { let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); assert!(matches!( dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), + XcmBlobMessageDispatchResult::Dispatched, )); } } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index cae840de96744..9bfe241394418 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -584,6 +584,7 @@ impl pallet_bridge_messages::Config for Runtime { WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, >; + type OnMessagesDelivered = (); type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index 666b1f0a8412e..fea7fc70c863f 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -26,9 +26,10 @@ use bridge_runtime_common::{ messages::{ self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, }, - messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Default lane that is used to send messages to Millau. @@ -44,6 +45,11 @@ parameter_types! { /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; + /// Lane used by the with-Millau bridge. + pub MullauSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); + + /// Dummy message used in configuration. + pub DummyXcmMessage: Xcm<()> = Xcm::new(); } /// Message payload for RialtoParachain -> Millau messages. @@ -61,6 +67,7 @@ pub type FromMillauMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< crate::OnRialtoParachainBlobDispatcher, (), + (), >; /// Messages proof for Millau -> RialtoParachain messages. @@ -122,11 +129,13 @@ pub type ToMillauBlobExporter = pub struct ToMillauXcmBlobHauler; impl XcmBlobHauler for ToMillauXcmBlobHauler { - type MessageSender = pallet_bridge_messages::Pallet; + type Runtime = Runtime; + type MessagesInstance = WithMillauMessagesInstance; + type SenderAndLane = MullauSenderAndLane; - fn xcm_lane() -> LaneId { - XCM_LANE - } + type ToSourceChainSender = crate::XcmRouter; + type CongestedMessage = DummyXcmMessage; + type UncongestedMessage = DummyXcmMessage; } #[cfg(test)] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index dbfa0cf7eb614..95c1f60b601c1 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -442,6 +442,7 @@ impl pallet_bridge_messages::Config for Runtime { WithMillauMessagesInstance, frame_support::traits::ConstU128<100_000>, >; + type OnMessagesDelivered = (); type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 357a5d7f02f09..4efef0bf1e56e 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -23,9 +23,10 @@ use bridge_runtime_common::{ messages::{ self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, }, - messages_xcm_extension::{XcmBlobHauler, XcmBlobHaulerAdapter}, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; /// Lane that is used for XCM messages exchange. @@ -41,6 +42,11 @@ parameter_types! { /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge /// (it is prepended with `UniversalOrigin` instruction). pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; + /// Lane used by the with-Millau bridge. + pub MullauSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); + + /// Dummy message used in configuration. + pub DummyXcmMessage: Xcm<()> = Xcm::new(); } /// Message payload for Rialto -> Millau messages. @@ -58,6 +64,7 @@ pub type FromMillauMessageDispatch = bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< crate::xcm_config::OnRialtoBlobDispatcher, (), + (), >; /// Messages proof for Millau -> Rialto messages. @@ -121,11 +128,13 @@ pub type ToMillauBlobExporter = HaulBlobExporter< pub struct ToMillauXcmBlobHauler; impl XcmBlobHauler for ToMillauXcmBlobHauler { - type MessageSender = pallet_bridge_messages::Pallet; + type Runtime = Runtime; + type MessagesInstance = WithMillauMessagesInstance; + type SenderAndLane = MullauSenderAndLane; - fn xcm_lane() -> LaneId { - XCM_LANE - } + type ToSourceChainSender = crate::xcm_config::XcmRouter; + type CongestedMessage = DummyXcmMessage; + type UncongestedMessage = DummyXcmMessage; } #[cfg(test)] diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 98b3bc992501f..9ca6a4c5df98c 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -21,6 +21,7 @@ bp-parachains = { path = "../../primitives/parachains", default-features = false bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } pallet-bridge-parachains = { path = "../../modules/parachains", default-features = false } @@ -55,6 +56,7 @@ std = [ "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", + "bp-xcm-bridge-hub-router/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 8b4a50a0f30f4..0a1d7243620c9 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -17,7 +17,7 @@ use crate::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; -use bp_messages::{InboundLaneData, LaneId, MessageNonce}; +use bp_messages::{target_chain::MessageDispatch, InboundLaneData, LaneId, MessageNonce}; use frame_support::{ dispatch::CallableCallFor, traits::{Get, IsSubType}, @@ -77,7 +77,12 @@ impl ReceiveMessagesProofInfo { /// /// - or there are no bundled messages, but the inbound lane is blocked by too many unconfirmed /// messages and/or unrewarded relayers. - fn is_obsolete(&self) -> bool { + fn is_obsolete(&self, is_dispatcher_active: bool) -> bool { + // if dispatcher is inactive, we don't accept any delivery transactions + if !is_dispatcher_active { + return true + } + // transactions with zero bundled nonces are not allowed, unless they're message // delivery transactions, which brings reward confirmations required to unblock // the lane @@ -275,7 +280,9 @@ impl< fn check_obsolete_call(&self) -> TransactionValidity { match self.call_info() { - Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.is_obsolete() => { + Some(CallInfo::ReceiveMessagesProof(proof_info)) + if proof_info.is_obsolete(T::MessageDispatch::is_active()) => + { log::trace!( target: pallet_bridge_messages::LOG_TARGET, "Rejecting obsolete messages delivery transaction: {:?}", @@ -327,8 +334,8 @@ mod tests { }, messages_call_ext::MessagesCallSubType, mock::{ - MaxUnconfirmedMessagesAtInboundLane, MaxUnrewardedRelayerEntriesAtInboundLane, - TestRuntime, ThisChainRuntimeCall, + DummyMessageDispatch, MaxUnconfirmedMessagesAtInboundLane, + MaxUnrewardedRelayerEntriesAtInboundLane, TestRuntime, ThisChainRuntimeCall, }, }; use bp_messages::{DeliveredMessages, UnrewardedRelayer, UnrewardedRelayersState}; @@ -435,6 +442,18 @@ mod tests { }); } + #[test] + fn extension_reject_call_when_dispatcher_is_inactive() { + sp_io::TestExternalities::new(Default::default()).execute_with(|| { + // when current best delivered is message#10 and we're trying to deliver message 11..=15 + // => tx is accepted, but we have inactive dispatcher, so... + deliver_message_10(); + + DummyMessageDispatch::deactivate(); + assert!(!validate_message_delivery(11, 15)); + }); + } + #[test] fn extension_rejects_empty_delivery_with_rewards_confirmations_if_there_are_free_relayer_and_message_slots( ) { diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 0317d745c15cf..44e554ecb24f8 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -22,16 +22,22 @@ //! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue` use bp_messages::{ - source_chain::MessagesBridge, + source_chain::{MessagesBridge, OnMessagesDelivered}, target_chain::{DispatchMessage, MessageDispatch}, - LaneId, + LaneId, MessageNonce, }; use bp_runtime::messages::MessageDispatchResult; +use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; use codec::{Decode, Encode}; -use frame_support::{dispatch::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; -use pallet_bridge_messages::WeightInfoExt as MessagesPalletWeights; +use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound}; +use pallet_bridge_messages::{ + Config as MessagesConfig, OutboundLanesCongestedSignals, Pallet as MessagesPallet, + WeightInfoExt as MessagesPalletWeights, +}; use scale_info::TypeInfo; use sp_runtime::SaturatedConversion; +use sp_std::{fmt::Debug, marker::PhantomData}; +use xcm::prelude::*; use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; /// Plain "XCM" payload, which we transfer through bridge @@ -46,16 +52,25 @@ pub enum XcmBlobMessageDispatchResult { } /// [`XcmBlobMessageDispatch`] is responsible for dispatching received messages -pub struct XcmBlobMessageDispatch { - _marker: sp_std::marker::PhantomData<(DispatchBlob, Weights)>, +/// +/// It needs to be used at the target bridge hub. +pub struct XcmBlobMessageDispatch { + _marker: sp_std::marker::PhantomData<(DispatchBlob, Weights, Channel)>, } -impl MessageDispatch - for XcmBlobMessageDispatch +impl< + BlobDispatcher: DispatchBlob, + Weights: MessagesPalletWeights, + Channel: XcmChannelStatusProvider, + > MessageDispatch for XcmBlobMessageDispatch { type DispatchPayload = XcmAsPlainPayload; type DispatchLevelResult = XcmBlobMessageDispatchResult; + fn is_active() -> bool { + !Channel::is_congested() + } + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload { Ok(ref payload) => { @@ -106,40 +121,374 @@ impl MessageDispat } } +/// A pair of sending chain location and message lane, used by this chain to send messages +/// over the bridge. +pub struct SenderAndLane { + /// Sending chain relative location. + pub location: MultiLocation, + /// Message lane, used by the sending chain. + pub lane: LaneId, +} + +impl SenderAndLane { + /// Create new object using provided location and lane. + pub fn new(location: MultiLocation, lane: LaneId) -> Self { + SenderAndLane { location, lane } + } +} + /// [`XcmBlobHauler`] is responsible for sending messages to the bridge "point-to-point link" from /// one side, where on the other it can be dispatched by [`XcmBlobMessageDispatch`]. pub trait XcmBlobHauler { - /// Runtime message sender adapter. - type MessageSender: MessagesBridge; + /// Runtime that has messages pallet deployed. + type Runtime: MessagesConfig; + /// Instance of the messages pallet that is used to send messages. + type MessagesInstance: 'static; + /// Returns lane used by this hauler. + type SenderAndLane: Get; + + /// Actual XCM message sender (`HRMP` or `UMP`) to the source chain + /// location (`Self::SenderAndLane::get().location`). + type ToSourceChainSender: SendXcm; + /// An XCM message that is sent to the sending chain when the bridge queue becomes congested. + type CongestedMessage: Get>>; + /// An XCM message that is sent to the sending chain when the bridge queue becomes not + /// congested. + type UncongestedMessage: Get>>; - /// Return message lane (as "point-to-point link") used to deliver XCM messages. - fn xcm_lane() -> LaneId; + /// Returns `true` if we want to handle congestion. + fn supports_congestion_detection() -> bool { + Self::CongestedMessage::get().is_some() || Self::UncongestedMessage::get().is_some() + } } -/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`XcmBlobHauler::MessageSender`] and -/// makes sure that XCM blob is sent to the [`pallet_bridge_messages`] queue to be relayed. +/// XCM bridge adapter which connects [`XcmBlobHauler`] with [`pallet_bridge_messages`] and +/// makes sure that XCM blob is sent to the outbound lane to be relayed. +/// +/// It needs to be used at the source bridge hub. pub struct XcmBlobHaulerAdapter(sp_std::marker::PhantomData); -impl HaulBlob for XcmBlobHaulerAdapter { + +impl HaulBlob for XcmBlobHaulerAdapter +where + H::Runtime: MessagesConfig, +{ fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { - let lane = H::xcm_lane(); - H::MessageSender::send_message(lane, blob) - .map(|artifacts| (lane, artifacts.nonce).using_encoded(sp_io::hashing::blake2_256)) - .map(|result| { + let sender_and_lane = H::SenderAndLane::get(); + MessagesPallet::::send_message(sender_and_lane.lane, blob) + .map(|artifacts| { log::info!( target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - ok: {:?} on lane: {:?}", - result, - lane - ) + "haul_blob result - ok: {:?} on lane: {:?}. Enqueued messages: {}", + artifacts.nonce, + sender_and_lane.lane, + artifacts.enqueued_messages, + ); + + // notify XCM queue manager about updated lane state + LocalXcmQueueManager::::on_bridge_message_enqueued( + &sender_and_lane, + artifacts.enqueued_messages, + ); }) .map_err(|error| { log::error!( target: crate::LOG_TARGET_BRIDGE_DISPATCH, "haul_blob result - error: {:?} on lane: {:?}", error, - lane + sender_and_lane.lane, ); HaulBlobError::Transport("MessageSenderError") }) } } + +impl OnMessagesDelivered for XcmBlobHaulerAdapter { + fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) { + let sender_and_lane = H::SenderAndLane::get(); + if sender_and_lane.lane != lane { + return + } + + // notify XCM queue manager about updated lane state + LocalXcmQueueManager::::on_bridge_messages_delivered( + &sender_and_lane, + enqueued_messages, + ); + } +} + +/// Manager of local XCM queues (and indirectly - underlying transport channels) that +/// controls the queue state. +/// +/// It needs to be used at the source bridge hub. +pub struct LocalXcmQueueManager(PhantomData); + +/// Maximal number of messages in the outbound bridge queue. Once we reach this limit, we +/// send a "congestion" XCM message to the sending chain. +const OUTBOUND_LANE_CONGESTED_THRESHOLD: MessageNonce = 8_192; + +/// After we have sent "congestion" XCM message to the sending chain, we wait until number +/// of messages in the outbound bridge queue drops to this count, before sending `uncongestion` +/// XCM message. +const OUTBOUND_LANE_UNCONGESTED_THRESHOLD: MessageNonce = 1_024; + +impl LocalXcmQueueManager { + /// Must be called whenever we push a message to the bridge lane. + pub fn on_bridge_message_enqueued( + sender_and_lane: &SenderAndLane, + enqueued_messages: MessageNonce, + ) { + // skip if we dont want to handle congestion + if !H::supports_congestion_detection() { + return + } + + // if we have already sent the congestion signal, we don't want to do anything + if Self::is_congested_signal_sent(sender_and_lane.lane) { + return + } + + // if the bridge queue is not congested, we don't want to do anything + let is_congested = enqueued_messages > OUTBOUND_LANE_CONGESTED_THRESHOLD; + if !is_congested { + return + } + + log::info!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "Sending 'congested' XCM message to {:?} to avoid overloading lane {:?}: there are\ + {} messages queued at the bridge queue", + sender_and_lane.location, + sender_and_lane.lane, + enqueued_messages, + ); + + if let Err(e) = Self::send_congested_signal(sender_and_lane) { + log::info!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "Failed to send the 'congested' XCM message to {:?}: {:?}", + sender_and_lane.location, + e, + ); + } + } + + /// Must be called whenever we receive a message delivery confirmation. + pub fn on_bridge_messages_delivered( + sender_and_lane: &SenderAndLane, + enqueued_messages: MessageNonce, + ) { + // skip if we dont want to handle congestion + if !H::supports_congestion_detection() { + return + } + + // if we have not sent the congestion signal before, we don't want to do anything + if !Self::is_congested_signal_sent(sender_and_lane.lane) { + return + } + + // if the bridge queue is still congested, we don't want to do anything + let is_congested = enqueued_messages > OUTBOUND_LANE_UNCONGESTED_THRESHOLD; + if is_congested { + return + } + + log::info!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "Sending 'uncongested' XCM message to {:?}. Lane {:?}: there are\ + {} messages queued at the bridge queue", + sender_and_lane.location, + sender_and_lane.lane, + enqueued_messages, + ); + + if let Err(e) = Self::send_uncongested_signal(sender_and_lane) { + log::info!( + target: crate::LOG_TARGET_BRIDGE_DISPATCH, + "Failed to send the 'uncongested' XCM message to {:?}: {:?}", + sender_and_lane.location, + e, + ); + } + } + + /// Returns true if we have sent "congested" signal to the `sending_chain_location`. + fn is_congested_signal_sent(lane: LaneId) -> bool { + OutboundLanesCongestedSignals::::get(lane) + } + + /// Send congested signal to the `sending_chain_location`. + fn send_congested_signal(sender_and_lane: &SenderAndLane) -> Result<(), SendError> { + if let Some(msg) = H::CongestedMessage::get() { + send_xcm::(sender_and_lane.location, msg)?; + OutboundLanesCongestedSignals::::insert( + sender_and_lane.lane, + true, + ); + } + Ok(()) + } + + /// Send `uncongested` signal to the `sending_chain_location`. + fn send_uncongested_signal(sender_and_lane: &SenderAndLane) -> Result<(), SendError> { + if let Some(msg) = H::UncongestedMessage::get() { + send_xcm::(sender_and_lane.location, msg)?; + OutboundLanesCongestedSignals::::remove( + sender_and_lane.lane, + ); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + + use bp_messages::OutboundLaneData; + use frame_support::parameter_types; + use pallet_bridge_messages::OutboundLanes; + + parameter_types! { + pub TestSenderAndLane: SenderAndLane = SenderAndLane { + location: MultiLocation::new(1, X1(Parachain(1000))), + lane: TEST_LANE_ID, + }; + pub DummyXcmMessage: Xcm<()> = Xcm::new(); + } + + struct DummySendXcm; + + impl DummySendXcm { + fn messages_sent() -> u32 { + frame_support::storage::unhashed::get(b"DummySendXcm").unwrap_or(0) + } + } + + impl SendXcm for DummySendXcm { + type Ticket = (); + + fn validate( + _destination: &mut Option, + _message: &mut Option>, + ) -> SendResult { + Ok(((), Default::default())) + } + + fn deliver(_ticket: Self::Ticket) -> Result { + let messages_sent: u32 = Self::messages_sent(); + frame_support::storage::unhashed::put(b"DummySendXcm", &(messages_sent + 1)); + Ok(XcmHash::default()) + } + } + + struct TestBlobHauler; + + impl XcmBlobHauler for TestBlobHauler { + type Runtime = TestRuntime; + type MessagesInstance = (); + type SenderAndLane = TestSenderAndLane; + + type ToSourceChainSender = DummySendXcm; + type CongestedMessage = DummyXcmMessage; + type UncongestedMessage = DummyXcmMessage; + } + + type TestBlobHaulerAdapter = XcmBlobHaulerAdapter; + + fn fill_up_lane_to_congestion() { + OutboundLanes::::insert( + TEST_LANE_ID, + OutboundLaneData { + oldest_unpruned_nonce: 0, + latest_received_nonce: 0, + latest_generated_nonce: OUTBOUND_LANE_CONGESTED_THRESHOLD, + }, + ); + } + + #[test] + fn congested_signal_is_not_sent_twice() { + run_test(|| { + fill_up_lane_to_congestion(); + + // next sent message leads to congested signal + TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 1); + + // next sent message => we don't sent another congested signal + TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 1); + }); + } + + #[test] + fn congested_signal_is_not_sent_when_outbound_lane_is_not_congested() { + run_test(|| { + TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 0); + }); + } + + #[test] + fn congested_signal_is_sent_when_outbound_lane_is_congested() { + run_test(|| { + fill_up_lane_to_congestion(); + + // next sent message leads to congested signal + TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 1); + assert!(LocalXcmQueueManager::::is_congested_signal_sent(TEST_LANE_ID)); + }); + } + + #[test] + fn uncongested_signal_is_not_sent_when_messages_are_delivered_at_other_lane() { + run_test(|| { + LocalXcmQueueManager::::send_congested_signal(&TestSenderAndLane::get()).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 1); + + // when we receive a delivery report for other lane, we don't send an uncongested signal + TestBlobHaulerAdapter::on_messages_delivered(LaneId([42, 42, 42, 42]), 0); + assert_eq!(DummySendXcm::messages_sent(), 1); + }); + } + + #[test] + fn uncongested_signal_is_not_sent_when_we_havent_send_congested_signal_before() { + run_test(|| { + TestBlobHaulerAdapter::on_messages_delivered(TEST_LANE_ID, 0); + assert_eq!(DummySendXcm::messages_sent(), 0); + }); + } + + #[test] + fn uncongested_signal_is_not_sent_if_outbound_lane_is_still_congested() { + run_test(|| { + LocalXcmQueueManager::::send_congested_signal(&TestSenderAndLane::get()).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 1); + + TestBlobHaulerAdapter::on_messages_delivered( + TEST_LANE_ID, + OUTBOUND_LANE_UNCONGESTED_THRESHOLD + 1, + ); + assert_eq!(DummySendXcm::messages_sent(), 1); + }); + } + + #[test] + fn uncongested_signal_is_sent_if_outbound_lane_is_uncongested() { + run_test(|| { + LocalXcmQueueManager::::send_congested_signal(&TestSenderAndLane::get()).unwrap(); + assert_eq!(DummySendXcm::messages_sent(), 1); + + TestBlobHaulerAdapter::on_messages_delivered( + TEST_LANE_ID, + OUTBOUND_LANE_UNCONGESTED_THRESHOLD, + ); + assert_eq!(DummySendXcm::messages_sent(), 2); + }); + } +} diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 6b5edabc886b8..9c41d17fa9957 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -33,10 +33,15 @@ use crate::messages::{ }; use bp_header_chain::{ChainWithGrandpa, HeaderChain}; -use bp_messages::{target_chain::ForbidInboundMessages, LaneId, MessageNonce}; +use bp_messages::{ + target_chain::{DispatchMessage, MessageDispatch}, + LaneId, MessageNonce, +}; use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_relayers::PayRewardFromAccount; -use bp_runtime::{Chain, ChainId, Parachain, UnderlyingChainProvider}; +use bp_runtime::{ + messages::MessageDispatchResult, Chain, ChainId, Parachain, UnderlyingChainProvider, +}; use codec::{Decode, Encode}; use frame_support::{ parameter_types, @@ -245,9 +250,10 @@ impl pallet_bridge_messages::Config for TestRuntime { (), ConstU64<100_000>, >; + type OnMessagesDelivered = (); type SourceHeaderChain = SourceHeaderChainAdapter; - type MessageDispatch = ForbidInboundMessages<(), FromBridgedChainMessagePayload>; + type MessageDispatch = DummyMessageDispatch; type BridgedChainId = BridgedChainId; } @@ -259,6 +265,34 @@ impl pallet_bridge_relayers::Config for TestRuntime { type WeightInfo = (); } +/// Dummy message dispatcher. +pub struct DummyMessageDispatch; + +impl DummyMessageDispatch { + pub fn deactivate() { + frame_support::storage::unhashed::put(&b"inactive"[..], &false); + } +} + +impl MessageDispatch for DummyMessageDispatch { + type DispatchPayload = Vec; + type DispatchLevelResult = (); + + fn is_active() -> bool { + frame_support::storage::unhashed::take::(&b"inactive"[..]) != Some(false) + } + + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + Weight::zero() + } + + fn dispatch( + _: DispatchMessage, + ) -> MessageDispatchResult { + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } + } +} + /// Bridge that is deployed on `ThisChain` and allows sending/receiving messages to/from /// `BridgedChain`. #[derive(Debug, PartialEq, Eq)] diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index c54198373167f..f611686420c29 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -494,8 +494,7 @@ where }; // compute total number of messages in transaction - let bundled_messages = - parsed_call.messages_call_info().bundled_messages().checked_len().unwrap_or(0); + let bundled_messages = parsed_call.messages_call_info().bundled_messages().saturating_len(); // a quick check to avoid invalid high-priority transactions if bundled_messages > Runtime::MaxUnconfirmedMessagesAtInboundLane::get() { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 91ab3c965b93c..67c6fb23cf167 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -53,7 +53,8 @@ use crate::{ use bp_messages::{ source_chain::{ - DeliveryConfirmationPayments, LaneMessageVerifier, SendMessageArtifacts, TargetHeaderChain, + DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, + SendMessageArtifacts, TargetHeaderChain, }, target_chain::{ DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, @@ -63,7 +64,9 @@ use bp_messages::{ MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, VerificationError, }; -use bp_runtime::{BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, Size}; +use bp_runtime::{ + BasicOperatingMode, ChainId, OwnedBridgeModule, PreComputedSize, RangeInclusiveExt, Size, +}; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get, DefaultNoBound}; use sp_runtime::traits::UniqueSaturatedFrom; @@ -156,6 +159,8 @@ pub mod pallet { type LaneMessageVerifier: LaneMessageVerifier; /// Delivery confirmation payments. type DeliveryConfirmationPayments: DeliveryConfirmationPayments; + /// Delivery confirmation callback. + type OnMessagesDelivered: OnMessagesDelivered; // Types that are used by inbound_lane (on target chain). @@ -281,6 +286,9 @@ pub mod pallet { Error::::TooManyMessagesInTheProof ); + // if message dispatcher is currently inactive, we won't accept any messages + ensure!(T::MessageDispatch::is_active(), Error::::MessageDispatchInactive); + // why do we need to know the weight of this (`receive_messages_proof`) call? Because // we may want to return some funds for not-dispatching (or partially dispatching) some // messages to the call origin (relayer). And this is done by returning actual weight @@ -487,6 +495,12 @@ pub mod pallet { lane_id, ); + // notify others about messages delivery + T::OnMessagesDelivered::on_messages_delivered( + lane_id, + lane.data().queued_messages().saturating_len(), + ); + // because of lags, the inbound lane state (`lane_data`) may have entries for // already rewarded relayers and messages (if all entries are duplicated, then // this transaction must be filtered out by our signed extension) @@ -518,6 +532,8 @@ pub mod pallet { NotOperatingNormally, /// The outbound lane is inactive. InactiveOutboundLane, + /// The inbound message dispatcher is inactive. + MessageDispatchInactive, /// Message has been treated as invalid by chain verifier. MessageRejectedByChainVerifier(VerificationError), /// Message has been treated as invalid by lane verifier. @@ -580,6 +596,25 @@ pub mod pallet { MaxValues = MaybeOutboundLanesCount, >; + /// Map of lane id => is congested signal sent. It is managed by the + /// `bridge_runtime_common::LocalXcmQueueManager`. + /// + /// **bridges-v1**: this map is a temporary hack and will be dropped in the `v2`. We can emulate + /// a storage map using `sp_io::unhashed` storage functions, but then benchmarks are not + /// accounting its `proof_size`, so it is missing from the final weights. So we need to make it + /// a map inside some pallet. We could use a simply value instead of map here, because + /// in `v1` we'll only have a single lane. But in the case of adding another lane before `v2`, + /// it'll be easier to deal with the isolated storage map instead. + #[pallet::storage] + pub type OutboundLanesCongestedSignals, I: 'static = ()> = StorageMap< + Hasher = Blake2_128Concat, + Key = LaneId, + Value = bool, + QueryKind = ValueQuery, + OnEmpty = GetDefault, + MaxValues = MaybeOutboundLanesCount, + >; + /// All queued outbound messages. #[pallet::storage] pub type OutboundMessages, I: 'static = ()> = @@ -627,6 +662,11 @@ pub mod pallet { } } + /// Return outbound lane data. + pub fn outbound_lane_data(lane: LaneId) -> OutboundLaneData { + OutboundLanes::::get(lane) + } + /// Return inbound lane data. pub fn inbound_lane_data(lane: LaneId) -> InboundLaneData { InboundLanes::::get(lane).0 @@ -703,6 +743,9 @@ fn send_message, I: 'static>( .send_message(encoded_payload) .map_err(Error::::MessageRejectedByPallet)?; + // return number of messages in the queue to let sender know about its state + let enqueued_messages = lane.data().queued_messages().saturating_len(); + log::trace!( target: LOG_TARGET, "Accepted message {} to lane {:?}. Message size: {:?}", @@ -713,7 +756,7 @@ fn send_message, I: 'static>( Pallet::::deposit_event(Event::MessageAccepted { lane_id, nonce }); - Ok(SendMessageArtifacts { nonce }) + Ok(SendMessageArtifacts { nonce, enqueued_messages }) } /// Ensure that the pallet is in normal operational mode. @@ -881,8 +924,9 @@ mod tests { mock::{ inbound_unrewarded_relayers_state, message, message_payload, run_test, unrewarded_relayer, AccountId, DbWeight, RuntimeEvent as TestEvent, RuntimeOrigin, - TestDeliveryConfirmationPayments, TestDeliveryPayments, TestMessagesDeliveryProof, - TestMessagesProof, TestRelayer, TestRuntime, TestWeightInfo, MAX_OUTBOUND_PAYLOAD_SIZE, + TestDeliveryConfirmationPayments, TestDeliveryPayments, TestMessageDispatch, + TestMessagesDeliveryProof, TestMessagesProof, TestOnMessagesDelivered, TestRelayer, + TestRuntime, TestWeightInfo, MAX_OUTBOUND_PAYLOAD_SIZE, PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, }, @@ -908,10 +952,12 @@ mod tests { fn send_regular_message() { get_ready_for_events(); - let message_nonce = - outbound_lane::(TEST_LANE_ID).data().latest_generated_nonce + 1; - send_message::(TEST_LANE_ID, REGULAR_PAYLOAD) + let outbound_lane = outbound_lane::(TEST_LANE_ID); + let message_nonce = outbound_lane.data().latest_generated_nonce + 1; + let prev_enqueud_messages = outbound_lane.data().queued_messages().saturating_len(); + let artifacts = send_message::(TEST_LANE_ID, REGULAR_PAYLOAD) .expect("send_message has failed"); + assert_eq!(artifacts.enqueued_messages, prev_enqueud_messages + 1); // check event with assigned nonce assert_eq!( @@ -1201,6 +1247,23 @@ mod tests { }); } + #[test] + fn receive_messages_fails_if_dispatcher_is_inactive() { + run_test(|| { + TestMessageDispatch::deactivate(); + assert_noop!( + Pallet::::receive_messages_proof( + RuntimeOrigin::signed(1), + TEST_RELAYER_A, + Ok(vec![message(1, REGULAR_PAYLOAD)]).into(), + 1, + REGULAR_PAYLOAD.declared_weight, + ), + Error::::MessageDispatchInactive, + ); + }); + } + #[test] fn receive_messages_proof_does_not_accept_message_if_dispatch_weight_is_not_enough() { run_test(|| { @@ -1304,6 +1367,7 @@ mod tests { ); assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1)); assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1)); + assert_eq!(TestOnMessagesDelivered::call_arguments(), Some((TEST_LANE_ID, 1))); // this reports delivery of both message 1 and message 2 => reward is paid only to // TEST_RELAYER_B @@ -1346,6 +1410,7 @@ mod tests { ); assert!(!TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_A, 1)); assert!(TestDeliveryConfirmationPayments::is_reward_paid(TEST_RELAYER_B, 1)); + assert_eq!(TestOnMessagesDelivered::call_arguments(), Some((TEST_LANE_ID, 0))); }); } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 83752523efb9b..67f7b78a487aa 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -21,7 +21,9 @@ use crate::Config; use bp_messages::{ calc_relayers_rewards, - source_chain::{DeliveryConfirmationPayments, LaneMessageVerifier, TargetHeaderChain}, + source_chain::{ + DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, TargetHeaderChain, + }, target_chain::{ DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, @@ -161,6 +163,7 @@ impl Config for TestRuntime { type TargetHeaderChain = TestTargetHeaderChain; type LaneMessageVerifier = TestLaneMessageVerifier; type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments; + type OnMessagesDelivered = TestOnMessagesDelivered; type SourceHeaderChain = TestSourceHeaderChain; type MessageDispatch = TestMessageDispatch; @@ -402,14 +405,26 @@ impl SourceHeaderChain for TestSourceHeaderChain { } } -/// Source header chain that is used in tests. +/// Test message dispatcher. #[derive(Debug)] pub struct TestMessageDispatch; +impl TestMessageDispatch { + pub fn deactivate() { + frame_support::storage::unhashed::put(b"TestMessageDispatch.IsCongested", &true) + } +} + impl MessageDispatch for TestMessageDispatch { type DispatchPayload = TestPayload; type DispatchLevelResult = TestDispatchLevelResult; + fn is_active() -> bool { + !frame_support::storage::unhashed::get_or_default::( + b"TestMessageDispatch.IsCongested", + ) + } + fn dispatch_weight(message: &mut DispatchMessage) -> Weight { match message.data.payload.as_ref() { Ok(payload) => payload.declared_weight, @@ -427,6 +442,24 @@ impl MessageDispatch for TestMessageDispatch { } } +/// Test callback, called during message delivery confirmation transaction. +pub struct TestOnMessagesDelivered; + +impl TestOnMessagesDelivered { + pub fn call_arguments() -> Option<(LaneId, MessageNonce)> { + frame_support::storage::unhashed::get(b"TestOnMessagesDelivered.OnMessagesDelivered") + } +} + +impl OnMessagesDelivered for TestOnMessagesDelivered { + fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) { + frame_support::storage::unhashed::put( + b"TestOnMessagesDelivered.OnMessagesDelivered", + &(lane, enqueued_messages), + ); + } +} + /// Return test lane message with given nonce and payload. pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message { Message { key: MessageKey { lane_id: TEST_LANE_ID, nonce }, payload: payload.encode() } diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml new file mode 100644 index 0000000000000..3d13e7cc3d7f2 --- /dev/null +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -0,0 +1,59 @@ +[package] +name = "pallet-xcm-bridge-hub-router" +description = "Bridge hub interface for sibling/parent chains with dynamic fees support." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +log = { version = "0.4.19", default-features = false } +scale-info = { version = "2.8.0", default-features = false, features = ["bit-vec", "derive", "serde"] } + +# Bridge dependencies + +bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } + +# Substrate Dependencies + +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +# Polkadot Dependencies + +xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } + +[dev-dependencies] +sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } + +[features] +default = ["std"] +std = [ + "bp-xcm-bridge-hub-router/std", + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "xcm/std", + "xcm-builder/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", +] diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/modules/xcm-bridge-hub-router/src/benchmarking.rs new file mode 100644 index 0000000000000..b32b983daf72c --- /dev/null +++ b/modules/xcm-bridge-hub-router/src/benchmarking.rs @@ -0,0 +1,96 @@ +// 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 . + +//! XCM bridge hub router pallet benchmarks. + +#![cfg(feature = "runtime-benchmarks")] + +use crate::{Bridge, Call}; + +use bp_xcm_bridge_hub_router::{BridgeState, MINIMAL_DELIVERY_FEE_FACTOR}; +use frame_benchmarking::benchmarks_instance_pallet; +use frame_support::{ + dispatch::UnfilteredDispatchable, + traits::{EnsureOrigin, Get, Hooks}, +}; +use sp_runtime::traits::Zero; +use xcm::prelude::*; + +/// Pallet we're benchmarking here. +pub struct Pallet, I: 'static = ()>(crate::Pallet); + +/// Trait that must be implemented by runtime to be able to benchmark pallet properly. +pub trait Config: crate::Config { + /// Fill up queue so it becomes congested. + fn make_congested(); + + /// Returns destination which is valid for this router instance. + /// (Needs to pass `T::Bridges`) + /// Make sure that `SendXcm` will pass. + fn ensure_bridged_target_destination() -> MultiLocation { + MultiLocation::new( + Self::UniversalLocation::get().len() as u8, + X1(GlobalConsensus(Self::BridgedNetworkId::get().unwrap())), + ) + } +} + +benchmarks_instance_pallet! { + on_initialize_when_non_congested { + Bridge::::put(BridgeState { + is_congested: false, + delivery_fee_factor: MINIMAL_DELIVERY_FEE_FACTOR + MINIMAL_DELIVERY_FEE_FACTOR, + }); + }: { + crate::Pallet::::on_initialize(Zero::zero()) + } + + on_initialize_when_congested { + Bridge::::put(BridgeState { + is_congested: false, + delivery_fee_factor: MINIMAL_DELIVERY_FEE_FACTOR + MINIMAL_DELIVERY_FEE_FACTOR, + }); + T::make_congested(); + }: { + crate::Pallet::::on_initialize(Zero::zero()) + } + + report_bridge_status { + Bridge::::put(BridgeState::default()); + + let origin: T::RuntimeOrigin = T::BridgeHubOrigin::try_successful_origin().expect("expected valid BridgeHubOrigin"); + let bridge_id = Default::default(); + let is_congested = true; + + let call = Call::::report_bridge_status { bridge_id, is_congested }; + }: { call.dispatch_bypass_filter(origin)? } + verify { + assert!(Bridge::::get().is_congested); + } + + send_message { + // make local queue congested, because it means additional db write + T::make_congested(); + + let dest = T::ensure_bridged_target_destination(); + let xcm = sp_std::vec![].into(); + }: { + send_xcm::>(dest, xcm).expect("message is sent") + } + verify { + assert!(Bridge::::get().delivery_fee_factor > MINIMAL_DELIVERY_FEE_FACTOR); + } +} diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs new file mode 100644 index 0000000000000..87e050b45c736 --- /dev/null +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -0,0 +1,557 @@ +// 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 . + +//! Pallet that may be used instead of `SovereignPaidRemoteExporter` in the XCM router +//! configuration. The main thing that the pallet offers is the dynamic message fee, +//! that is computed based on the bridge queues state. It starts exponentially increasing +//! if the queue between this chain and the sibling/child bridge hub is congested. +//! +//! All other bridge hub queues offer some backpressure mechanisms. So if at least one +//! of all queues is congested, it will eventually lead to the growth of the queue at +//! this chain. +//! +//! **A note on terminology**: when we mention the bridge hub here, we mean the chain that +//! has the messages pallet deployed (`pallet-bridge-grandpa`, `pallet-bridge-messages`, +//! `pallet-xcm-bridge-hub`, ...). It may be the system bridge hub parachain or any other +//! chain. + +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_xcm_bridge_hub_router::{ + BridgeState, XcmChannelStatusProvider, MINIMAL_DELIVERY_FEE_FACTOR, +}; +use codec::Encode; +use frame_support::traits::Get; +use sp_core::H256; +use sp_runtime::{FixedPointNumber, FixedU128, Saturating}; +use xcm::prelude::*; +use xcm_builder::{ExporterFor, SovereignPaidRemoteExporter}; + +pub use pallet::*; +pub use weights::WeightInfo; + +pub mod benchmarking; +pub mod weights; + +mod mock; + +/// The factor that is used to increase current message fee factor when bridge experiencing +/// some lags. +const EXPONENTIAL_FEE_BASE: FixedU128 = FixedU128::from_rational(105, 100); // 1.05 +/// The factor that is used to increase current message fee factor for every sent kilobyte. +const MESSAGE_SIZE_FEE_BASE: FixedU128 = FixedU128::from_rational(1, 1000); // 0.001 + +/// Maximal size of the XCM message that may be sent over bridge. +/// +/// This should be less than the maximal size, allowed by the messages pallet, because +/// the message itself is wrapped in other structs and is double encoded. +pub const HARD_MESSAGE_SIZE_LIMIT: u32 = 32 * 1024; + +/// The target that will be used when publishing logs related to this pallet. +/// +/// This doesn't match the pattern used by other bridge pallets (`runtime::bridge-*`). But this +/// pallet has significant differences with those pallets. The main one is that is intended to +/// be deployed at sending chains. Other bridge pallets are likely to be deployed at the separate +/// bridge hub parachain. +pub const LOG_TARGET: &str = "xcm::bridge-hub-router"; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// Benchmarks results from runtime we're plugged into. + type WeightInfo: WeightInfo; + + /// Universal location of this runtime. + type UniversalLocation: Get; + /// The bridged network that this config is for if specified. + /// Also used for filtering `Bridges` by `BridgedNetworkId`. + /// If not specified, allows all networks pass through. + type BridgedNetworkId: Get>; + /// Configuration for supported **bridged networks/locations** with **bridge location** and + /// **possible fee**. Allows to externalize better control over allowed **bridged + /// networks/locations**. + type Bridges: ExporterFor; + + /// Origin of the sibling bridge hub that is allowed to report bridge status. + type BridgeHubOrigin: EnsureOrigin; + /// Actual message sender (`HRMP` or `DMP`) to the sibling bridge hub location. + type ToBridgeHubSender: SendXcm; + /// Underlying channel with the sibling bridge hub. It must match the channel, used + /// by the `Self::ToBridgeHubSender`. + type WithBridgeHubChannel: XcmChannelStatusProvider; + + /// Additional fee that is paid for every byte of the outbound message. + type ByteFee: Get; + /// Asset that is used to paid bridge fee. + type FeeAsset: Get; + } + + #[pallet::pallet] + pub struct Pallet(PhantomData<(T, I)>); + + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet { + fn on_initialize(_n: BlockNumberFor) -> Weight { + // TODO: make sure that `WithBridgeHubChannel::is_congested` returns true if either + // of XCM channels (outbound/inbound) is suspended. Because if outbound is suspended + // that is definitely congestion. If inbound is suspended, then we are not able to + // receive the "report_bridge_status" signal (that maybe sent by the bridge hub). + + // if the channel with sibling/child bridge hub is suspended, we don't change + // anything + if T::WithBridgeHubChannel::is_congested() { + return T::WeightInfo::on_initialize_when_congested() + } + + // if bridge has reported congestion, we don't change anything + let mut bridge = Self::bridge(); + if bridge.is_congested { + return T::WeightInfo::on_initialize_when_congested() + } + + // if fee factor is already minimal, we don't change anything + if bridge.delivery_fee_factor == MINIMAL_DELIVERY_FEE_FACTOR { + return T::WeightInfo::on_initialize_when_congested() + } + + let previous_factor = bridge.delivery_fee_factor; + bridge.delivery_fee_factor = + MINIMAL_DELIVERY_FEE_FACTOR.max(bridge.delivery_fee_factor / EXPONENTIAL_FEE_BASE); + log::info!( + target: LOG_TARGET, + "Bridge queue is uncongested. Decreased fee factor from {} to {}", + previous_factor, + bridge.delivery_fee_factor, + ); + + Bridge::::put(bridge); + T::WeightInfo::on_initialize_when_non_congested() + } + } + + #[pallet::call] + impl, I: 'static> Pallet { + /// Notification about congested bridge queue. + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::report_bridge_status())] + pub fn report_bridge_status( + origin: OriginFor, + // this argument is not currently used, but to ease future migration, we'll keep it + // here + bridge_id: H256, + is_congested: bool, + ) -> DispatchResult { + let _ = T::BridgeHubOrigin::ensure_origin(origin)?; + + log::info!( + target: LOG_TARGET, + "Received bridge status from {:?}: congested = {}", + bridge_id, + is_congested, + ); + + Bridge::::mutate(|bridge| { + bridge.is_congested = is_congested; + }); + Ok(()) + } + } + + /// Bridge that we are using. + /// + /// **bridges-v1** assumptions: all outbound messages through this router are using single lane + /// and to single remote consensus. If there is some other remote consensus that uses the same + /// bridge hub, the separate pallet instance shall be used, In `v2` we'll have all required + /// primitives (lane-id aka bridge-id, derived from XCM locations) to support multiple bridges + /// by the same pallet instance. + #[pallet::storage] + #[pallet::getter(fn bridge)] + pub type Bridge, I: 'static = ()> = StorageValue<_, BridgeState, ValueQuery>; + + impl, I: 'static> Pallet { + /// Called when new message is sent (queued to local outbound XCM queue) over the bridge. + pub(crate) fn on_message_sent_to_bridge(message_size: u32) { + let _ = Bridge::::try_mutate(|bridge| { + let is_channel_with_bridge_hub_congested = T::WithBridgeHubChannel::is_congested(); + let is_bridge_congested = bridge.is_congested; + + // if outbound queue is not congested AND bridge has not reported congestion, do + // nothing + if !is_channel_with_bridge_hub_congested && !is_bridge_congested { + return Err(()) + } + + // ok - we need to increase the fee factor, let's do that + let message_size_factor = FixedU128::from_u32(message_size.saturating_div(1024)) + .saturating_mul(MESSAGE_SIZE_FEE_BASE); + let total_factor = EXPONENTIAL_FEE_BASE.saturating_add(message_size_factor); + let previous_factor = bridge.delivery_fee_factor; + bridge.delivery_fee_factor = + bridge.delivery_fee_factor.saturating_mul(total_factor); + + log::info!( + target: LOG_TARGET, + "Bridge channel is congested. Increased fee factor from {} to {}", + previous_factor, + bridge.delivery_fee_factor, + ); + + Ok(()) + }); + } + } +} + +/// We'll be using `SovereignPaidRemoteExporter` to send remote messages over the sibling/child +/// bridge hub. +type ViaBridgeHubExporter = SovereignPaidRemoteExporter< + Pallet, + >::ToBridgeHubSender, + >::UniversalLocation, +>; + +// This pallet acts as the `ExporterFor` for the `SovereignPaidRemoteExporter` to compute +// message fee using fee factor. +impl, I: 'static> ExporterFor for Pallet { + fn exporter_for( + network: &NetworkId, + remote_location: &InteriorMultiLocation, + message: &Xcm<()>, + ) -> Option<(MultiLocation, Option)> { + // ensure that the message is sent to the expected bridged network (if specified). + if let Some(bridged_network) = T::BridgedNetworkId::get() { + if *network != bridged_network { + log::trace!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} does not support bridging to network {:?}!", + bridged_network, + network, + ); + return None + } + } + + // ensure that the message is sent to the expected bridged network and location. + let Some((bridge_hub_location, maybe_payment)) = + T::Bridges::exporter_for(network, remote_location, message) + else { + log::trace!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} does not support bridging to network {:?} and remote_location {:?}!", + T::BridgedNetworkId::get(), + network, + remote_location, + ); + return None + }; + + // take `base_fee` from `T::Brides`, but it has to be the same `T::FeeAsset` + let base_fee = match maybe_payment { + Some(payment) => match payment { + MultiAsset { fun: Fungible(amount), id } if id.eq(&T::FeeAsset::get()) => amount, + invalid_asset => { + log::error!( + target: LOG_TARGET, + "Router with bridged_network_id {:?} is configured for `T::FeeAsset` {:?} which is not \ + compatible with {:?} for bridge_hub_location: {:?} for bridging to {:?}/{:?}!", + T::BridgedNetworkId::get(), + T::FeeAsset::get(), + invalid_asset, + bridge_hub_location, + network, + remote_location, + ); + return None + }, + }, + None => 0, + }; + + // compute fee amount. Keep in mind that this is only the bridge fee. The fee for sending + // message from this chain to child/sibling bridge hub is determined by the + // `Config::ToBridgeHubSender` + let message_size = message.encoded_size(); + let message_fee = (message_size as u128).saturating_mul(T::ByteFee::get()); + let fee_sum = base_fee.saturating_add(message_fee); + let fee_factor = Self::bridge().delivery_fee_factor; + let fee = fee_factor.saturating_mul_int(fee_sum); + + let fee = if fee > 0 { Some((T::FeeAsset::get(), fee).into()) } else { None }; + + log::info!( + target: LOG_TARGET, + "Going to send message to {:?} ({} bytes) over bridge. Computed bridge fee {:?} using fee factor {}", + (network, remote_location), + message_size, + fee, + fee_factor + ); + + Some((bridge_hub_location, fee)) + } +} + +// This pallet acts as the `SendXcm` to the sibling/child bridge hub instead of regular +// XCMP/DMP transport. This allows injecting dynamic message fees into XCM programs that +// are going to the bridged network. +impl, I: 'static> SendXcm for Pallet { + type Ticket = (u32, ::Ticket); + + fn validate( + dest: &mut Option, + xcm: &mut Option>, + ) -> SendResult { + // we won't have an access to `dest` and `xcm` in the `delvier` method, so precompute + // everything required here + let message_size = xcm + .as_ref() + .map(|xcm| xcm.encoded_size() as _) + .ok_or(SendError::MissingArgument)?; + + // bridge doesn't support oversized/overweight messages now. So it is better to drop such + // messages here than at the bridge hub. Let's check the message size. + if message_size > HARD_MESSAGE_SIZE_LIMIT { + return Err(SendError::ExceedsMaxMessageSize) + } + + // just use exporter to validate destination and insert instructions to pay message fee + // at the sibling/child bridge hub + // + // the cost will include both cost of: (1) to-sibling bridg hub delivery (returned by + // the `Config::ToBridgeHubSender`) and (2) to-bridged bridge hub delivery (returned by + // `Self::exporter_for`) + ViaBridgeHubExporter::::validate(dest, xcm) + .map(|(ticket, cost)| ((message_size, ticket), cost)) + } + + fn deliver(ticket: Self::Ticket) -> Result { + // use router to enqueue message to the sibling/child bridge hub. This also should handle + // payment for passing through this queue. + let (message_size, ticket) = ticket; + let xcm_hash = ViaBridgeHubExporter::::deliver(ticket)?; + + // increase delivery fee factor if required + Self::on_message_sent_to_bridge(message_size); + + Ok(xcm_hash) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use mock::*; + + use frame_support::traits::Hooks; + use sp_runtime::traits::One; + + fn congested_bridge(delivery_fee_factor: FixedU128) -> BridgeState { + BridgeState { is_congested: true, delivery_fee_factor } + } + + fn uncongested_bridge(delivery_fee_factor: FixedU128) -> BridgeState { + BridgeState { is_congested: false, delivery_fee_factor } + } + + #[test] + fn initial_fee_factor_is_one() { + run_test(|| { + assert_eq!( + Bridge::::get(), + uncongested_bridge(MINIMAL_DELIVERY_FEE_FACTOR), + ); + }) + } + + #[test] + fn fee_factor_is_not_decreased_from_on_initialize_when_xcm_channel_is_congested() { + run_test(|| { + Bridge::::put(uncongested_bridge(FixedU128::from_rational(125, 100))); + TestWithBridgeHubChannel::make_congested(); + + // it should not decrease, because xcm channel is congested + let old_bridge = XcmBridgeHubRouter::bridge(); + XcmBridgeHubRouter::on_initialize(One::one()); + assert_eq!(XcmBridgeHubRouter::bridge(), old_bridge); + }) + } + + #[test] + fn fee_factor_is_not_decreased_from_on_initialize_when_bridge_has_reported_congestion() { + run_test(|| { + Bridge::::put(congested_bridge(FixedU128::from_rational(125, 100))); + + // it should not decrease, because bridge congested + let old_bridge = XcmBridgeHubRouter::bridge(); + XcmBridgeHubRouter::on_initialize(One::one()); + assert_eq!(XcmBridgeHubRouter::bridge(), old_bridge); + }) + } + + #[test] + fn fee_factor_is_decreased_from_on_initialize_when_xcm_channel_is_uncongested() { + run_test(|| { + Bridge::::put(uncongested_bridge(FixedU128::from_rational(125, 100))); + + // it shold eventually decreased to one + while XcmBridgeHubRouter::bridge().delivery_fee_factor > MINIMAL_DELIVERY_FEE_FACTOR { + XcmBridgeHubRouter::on_initialize(One::one()); + } + + // verify that it doesn't decreases anymore + XcmBridgeHubRouter::on_initialize(One::one()); + assert_eq!( + XcmBridgeHubRouter::bridge(), + uncongested_bridge(MINIMAL_DELIVERY_FEE_FACTOR) + ); + }) + } + + #[test] + fn not_applicable_if_destination_is_within_other_network() { + run_test(|| { + assert_eq!( + send_xcm::( + MultiLocation::new(2, X2(GlobalConsensus(Rococo), Parachain(1000))), + vec![].into(), + ), + Err(SendError::NotApplicable), + ); + }); + } + + #[test] + fn exceeds_max_message_size_if_size_is_above_hard_limit() { + run_test(|| { + assert_eq!( + send_xcm::( + MultiLocation::new(2, X2(GlobalConsensus(Rococo), Parachain(1000))), + vec![ClearOrigin; HARD_MESSAGE_SIZE_LIMIT as usize].into(), + ), + Err(SendError::ExceedsMaxMessageSize), + ); + }); + } + + #[test] + fn returns_proper_delivery_price() { + run_test(|| { + let dest = MultiLocation::new(2, X1(GlobalConsensus(BridgedNetworkId::get()))); + let xcm: Xcm<()> = vec![ClearOrigin].into(); + let msg_size = xcm.encoded_size(); + + // initially the base fee is used: `BASE_FEE + BYTE_FEE * msg_size + HRMP_FEE` + let expected_fee = BASE_FEE + BYTE_FEE * (msg_size as u128) + HRMP_FEE; + assert_eq!( + XcmBridgeHubRouter::validate(&mut Some(dest), &mut Some(xcm.clone())) + .unwrap() + .1 + .get(0), + Some(&(BridgeFeeAsset::get(), expected_fee).into()), + ); + + // but when factor is larger than one, it increases the fee, so it becomes: + // `(BASE_FEE + BYTE_FEE * msg_size) * F + HRMP_FEE` + let factor = FixedU128::from_rational(125, 100); + Bridge::::put(uncongested_bridge(factor)); + let expected_fee = + (FixedU128::saturating_from_integer(BASE_FEE + BYTE_FEE * (msg_size as u128)) * + factor) + .into_inner() / FixedU128::DIV + + HRMP_FEE; + assert_eq!( + XcmBridgeHubRouter::validate(&mut Some(dest), &mut Some(xcm)).unwrap().1.get(0), + Some(&(BridgeFeeAsset::get(), expected_fee).into()), + ); + }); + } + + #[test] + fn sent_message_doesnt_increase_factor_if_xcm_channel_is_uncongested() { + run_test(|| { + let old_bridge = XcmBridgeHubRouter::bridge(); + assert_eq!( + send_xcm::( + MultiLocation::new( + 2, + X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) + ), + vec![ClearOrigin].into(), + ) + .map(drop), + Ok(()), + ); + + assert!(TestToBridgeHubSender::is_message_sent()); + assert_eq!(old_bridge, XcmBridgeHubRouter::bridge()); + }); + } + + #[test] + fn sent_message_increases_factor_if_xcm_channel_is_congested() { + run_test(|| { + TestWithBridgeHubChannel::make_congested(); + + let old_bridge = XcmBridgeHubRouter::bridge(); + assert_eq!( + send_xcm::( + MultiLocation::new( + 2, + X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) + ), + vec![ClearOrigin].into(), + ) + .map(drop), + Ok(()), + ); + + assert!(TestToBridgeHubSender::is_message_sent()); + assert!( + old_bridge.delivery_fee_factor < XcmBridgeHubRouter::bridge().delivery_fee_factor + ); + }); + } + + #[test] + fn sent_message_increases_factor_if_bridge_has_reported_congestion() { + run_test(|| { + Bridge::::put(congested_bridge(MINIMAL_DELIVERY_FEE_FACTOR)); + + let old_bridge = XcmBridgeHubRouter::bridge(); + assert_eq!( + send_xcm::( + MultiLocation::new( + 2, + X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) + ), + vec![ClearOrigin].into(), + ) + .map(drop), + Ok(()), + ); + + assert!(TestToBridgeHubSender::is_message_sent()); + assert!( + old_bridge.delivery_fee_factor < XcmBridgeHubRouter::bridge().delivery_fee_factor + ); + }); + } +} diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs new file mode 100644 index 0000000000000..5ad7be4890a17 --- /dev/null +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -0,0 +1,148 @@ +// 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 . + +#![cfg(test)] + +use crate as pallet_xcm_bridge_hub_router; + +use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; +use frame_support::{construct_runtime, parameter_types}; +use frame_system::EnsureRoot; +use sp_core::H256; +use sp_runtime::{ + traits::{BlakeTwo256, ConstU128, IdentityLookup}, + BuildStorage, +}; +use xcm::prelude::*; +use xcm_builder::NetworkExportTable; + +pub type AccountId = u64; +type Block = frame_system::mocking::MockBlock; + +/// HRMP fee. +pub const HRMP_FEE: u128 = 500; +/// Base bridge fee. +pub const BASE_FEE: u128 = 1_000_000; +/// Byte bridge fee. +pub const BYTE_FEE: u128 = 1_000; + +construct_runtime! { + pub enum TestRuntime + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + XcmBridgeHubRouter: pallet_xcm_bridge_hub_router::{Pallet, Storage}, + } +} + +parameter_types! { + pub ThisNetworkId: NetworkId = Polkadot; + pub BridgedNetworkId: NetworkId = Kusama; + pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(ThisNetworkId::get()), Parachain(1000)); + pub SiblingBridgeHubLocation: MultiLocation = ParentThen(X1(Parachain(1002))).into(); + pub BridgeFeeAsset: AssetId = MultiLocation::parent().into(); + pub BridgeTable: Vec<(NetworkId, MultiLocation, Option)> + = vec![(BridgedNetworkId::get(), SiblingBridgeHubLocation::get(), Some((BridgeFeeAsset::get(), BASE_FEE).into()))]; +} + +impl frame_system::Config for TestRuntime { + type RuntimeOrigin = RuntimeOrigin; + type Nonce = u64; + type RuntimeCall = RuntimeCall; + type Block = Block; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = frame_support::traits::ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type BaseCallFilter = frame_support::traits::Everything; + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_xcm_bridge_hub_router::Config<()> for TestRuntime { + type WeightInfo = (); + + type UniversalLocation = UniversalLocation; + type BridgedNetworkId = BridgedNetworkId; + type Bridges = NetworkExportTable; + + type BridgeHubOrigin = EnsureRoot; + type ToBridgeHubSender = TestToBridgeHubSender; + type WithBridgeHubChannel = TestWithBridgeHubChannel; + + type ByteFee = ConstU128; + type FeeAsset = BridgeFeeAsset; +} + +pub struct TestToBridgeHubSender; + +impl TestToBridgeHubSender { + pub fn is_message_sent() -> bool { + frame_support::storage::unhashed::get_or_default(b"TestToBridgeHubSender.Sent") + } +} + +impl SendXcm for TestToBridgeHubSender { + type Ticket = (); + + fn validate( + _destination: &mut Option, + _message: &mut Option>, + ) -> SendResult { + Ok(((), (BridgeFeeAsset::get(), HRMP_FEE).into())) + } + + fn deliver(_ticket: Self::Ticket) -> Result { + frame_support::storage::unhashed::put(b"TestToBridgeHubSender.Sent", &true); + Ok([0u8; 32]) + } +} + +pub struct TestWithBridgeHubChannel; + +impl TestWithBridgeHubChannel { + pub fn make_congested() { + frame_support::storage::unhashed::put(b"TestWithBridgeHubChannel.Congested", &true); + } +} + +impl XcmChannelStatusProvider for TestWithBridgeHubChannel { + fn is_congested() -> bool { + frame_support::storage::unhashed::get_or_default(b"TestWithBridgeHubChannel.Congested") + } +} + +/// Return test externalities to use in tests. +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + sp_io::TestExternalities::new(t) +} + +/// Run pallet test. +pub fn run_test(test: impl FnOnce() -> T) -> T { + new_test_ext().execute_with(|| test()) +} diff --git a/modules/xcm-bridge-hub-router/src/weights.rs b/modules/xcm-bridge-hub-router/src/weights.rs new file mode 100644 index 0000000000000..04909f3b2e838 --- /dev/null +++ b/modules/xcm-bridge-hub-router/src/weights.rs @@ -0,0 +1,208 @@ +// 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 . + +//! Autogenerated weights for pallet_xcm_bridge_hub_router +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-03, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` +//! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/millau-bridge-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm_bridge_hub_router +// --extrinsic=* +// --execution=wasm +// --wasm-execution=Compiled +// --heap-pages=4096 +// --output=./modules/xcm-bridge-hub-router/src/weights.rs +// --template=./.maintain/bridge-weight-template.hbs + +#![allow(clippy::all)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{ + traits::Get, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_xcm_bridge_hub_router. +pub trait WeightInfo { + fn on_initialize_when_non_congested() -> Weight; + fn on_initialize_when_congested() -> Weight; + fn report_bridge_status() -> Weight; + fn send_message() -> Weight; +} + +/// Weights for `pallet_xcm_bridge_hub_router` that are generated using one of the Bridge testnets. +/// +/// Those weights are test only and must never be used in production. +pub struct BridgeWeight(PhantomData); +impl WeightInfo for BridgeWeight { + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + /// + /// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` + /// (r:1 w:0) + /// + /// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1 + /// w:0) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `53` + // Estimated: `3518` + // Minimum execution time: 11_934 nanoseconds. + Weight::from_parts(12_201_000, 3518) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + /// + /// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` + /// (r:1 w:0) + /// + /// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1 + /// w:0) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `94` + // Estimated: `3559` + // Minimum execution time: 9_010 nanoseconds. + Weight::from_parts(9_594_000, 3559) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `53` + // Estimated: `1502` + // Minimum execution time: 10_427 nanoseconds. + Weight::from_parts(10_682_000, 1502) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + /// + /// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` + /// (r:1 w:0) + /// + /// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1 + /// w:0) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `52` + // Estimated: `3517` + // Minimum execution time: 19_709 nanoseconds. + Weight::from_parts(20_110_000, 3517) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + /// + /// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` + /// (r:1 w:0) + /// + /// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1 + /// w:0) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `53` + // Estimated: `3518` + // Minimum execution time: 11_934 nanoseconds. + Weight::from_parts(12_201_000, 3518) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + /// + /// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` + /// (r:1 w:0) + /// + /// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1 + /// w:0) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `94` + // Estimated: `3559` + // Minimum execution time: 9_010 nanoseconds. + Weight::from_parts(9_594_000, 3559) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `53` + // Estimated: `1502` + // Minimum execution time: 10_427 nanoseconds. + Weight::from_parts(10_682_000, 1502) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `XcmBridgeHubRouter::Bridge` (r:1 w:1) + /// + /// Proof: `XcmBridgeHubRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: + /// 512, mode: `MaxEncodedLen`) + /// + /// Storage: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` + /// (r:1 w:0) + /// + /// Proof: UNKNOWN KEY `0x456d756c617465645369626c696e6758636d704368616e6e656c2e436f6e6765` (r:1 + /// w:0) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `52` + // Estimated: `3517` + // Minimum execution time: 19_709 nanoseconds. + Weight::from_parts(20_110_000, 3517) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} diff --git a/primitives/chain-asset-hub-kusama/Cargo.toml b/primitives/chain-asset-hub-kusama/Cargo.toml new file mode 100644 index 0000000000000..6d5a4207ee668 --- /dev/null +++ b/primitives/chain-asset-hub-kusama/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "bp-asset-hub-kusama" +description = "Primitives of AssetHubKusama parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } + +# Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +# Bridge Dependencies +bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-xcm-bridge-hub-router/std", + "frame-support/std", + "codec/std", + "scale-info/std", +] diff --git a/primitives/chain-asset-hub-kusama/src/lib.rs b/primitives/chain-asset-hub-kusama/src/lib.rs new file mode 100644 index 0000000000000..b3b25ba6eddd7 --- /dev/null +++ b/primitives/chain-asset-hub-kusama/src/lib.rs @@ -0,0 +1,49 @@ +// Copyright 2022 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 . + +//! Module with configuration which reflects AssetHubKusama runtime setup. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; + +/// `AssetHubKusama` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `AssetHubKusama` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `AssetHubKusama` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// `ToPolkadotXcmRouter` bridge pallet. + #[codec(index = 43)] + ToPolkadotXcmRouter(XcmBridgeHubRouterCall), +} + +frame_support::parameter_types! { + /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. + pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); + + /// Base delivery fee to `BridgeHubKusama`. + /// (initially was calculated `170733333` + `10%` by test `BridgeHubKusama::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) + pub const BridgeHubKusamaBaseFeeInDots: u128 = 187806666; +} diff --git a/primitives/chain-asset-hub-polkadot/Cargo.toml b/primitives/chain-asset-hub-polkadot/Cargo.toml new file mode 100644 index 0000000000000..4ab562c6b34ce --- /dev/null +++ b/primitives/chain-asset-hub-polkadot/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "bp-asset-hub-polkadot" +description = "Primitives of AssetHubPolkadot parachain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } + +# Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +# Bridge Dependencies +bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-xcm-bridge-hub-router/std", + "frame-support/std", + "codec/std", + "scale-info/std", +] diff --git a/primitives/chain-asset-hub-polkadot/src/lib.rs b/primitives/chain-asset-hub-polkadot/src/lib.rs new file mode 100644 index 0000000000000..7363e5af02a2c --- /dev/null +++ b/primitives/chain-asset-hub-polkadot/src/lib.rs @@ -0,0 +1,49 @@ +// Copyright 2022 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 . + +//! Module with configuration which reflects AssetHubPolkadot runtime setup. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; + +/// `AssetHubPolkadot` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `AssetHubPolkadot` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `AssetHubPolkadot` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// `ToKusamaXcmRouter` bridge pallet. + #[codec(index = 43)] + ToKusamaXcmRouter(XcmBridgeHubRouterCall), +} + +frame_support::parameter_types! { + /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. + pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); + + /// Base delivery fee to `BridgeHubPolkadot`. + /// (initially was calculated `51220000` + `10%` by test `BridgeHubPolkadot::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) + pub const BridgeHubPolkadotBaseFeeInDots: u128 = 56342000; +} diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index cb3a14572d72b..84c41de3b361f 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -387,6 +387,14 @@ impl Default for OutboundLaneData { } } +impl OutboundLaneData { + /// Return nonces of all currently queued messages (i.e. messages that we believe + /// are not delivered yet). + pub fn queued_messages(&self) -> RangeInclusive { + (self.latest_received_nonce + 1)..=self.latest_generated_nonce + } +} + /// Calculate the number of messages that the relayers have delivered. pub fn calc_relayers_rewards( messages_relayers: VecDeque>, diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 09f6396ad7421..3cc78522baf1e 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -115,11 +115,26 @@ impl DeliveryConfirmationPayments for () { } } +/// Callback that is called at the source chain (bridge hub) when we get delivery confirmation +/// for new messages. +pub trait OnMessagesDelivered { + /// New messages delivery has been confirmed. + /// + /// The only argument of the function is the number of yet undelivered messages + fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce); +} + +impl OnMessagesDelivered for () { + fn on_messages_delivered(_lane: LaneId, _enqueued_messages: MessageNonce) {} +} + /// Send message artifacts. #[derive(Eq, RuntimeDebug, PartialEq)] pub struct SendMessageArtifacts { /// Nonce of the message. pub nonce: MessageNonce, + /// Number of enqueued messages at the lane, after the message is sent. + pub enqueued_messages: MessageNonce, } /// Messages bridge API to be used from other pallets. @@ -141,7 +156,7 @@ impl MessagesBridge for NoopMessagesBridge { type Error = &'static str; fn send_message(_lane: LaneId, _message: Payload) -> Result { - Ok(SendMessageArtifacts { nonce: 0 }) + Ok(SendMessageArtifacts { nonce: 0, enqueued_messages: 0 }) } } diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 385bc4ac373d6..60f5c1b3c1c5b 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -91,6 +91,15 @@ pub trait MessageDispatch { /// Fine-grained result of single message dispatch (for better diagnostic purposes) type DispatchLevelResult: Clone + sp_std::fmt::Debug + Eq; + /// Returns `true` if dispatcher is ready to accept additional messages. The `false` should + /// be treated as a hint by both dispatcher and its consumers - i.e. dispatcher shall not + /// simply drop messages if it returns `false`. The consumer may still call the `dispatch` + /// if dispatcher has returned `false`. + /// + /// We check it in the messages delivery transaction prologue. So if it becomes `false` + /// after some portion of messages is already dispatched, it doesn't fail the whole transaction. + fn is_active() -> bool; + /// Estimate dispatch weight. /// /// This function must return correct upper bound of dispatch weight. The return value @@ -186,6 +195,10 @@ impl MessageDispatch type DispatchPayload = DispatchPayload; type DispatchLevelResult = (); + fn is_active() -> bool { + false + } + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { Weight::MAX } diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml new file mode 100644 index 0000000000000..ca17f52d169b4 --- /dev/null +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "bp-xcm-bridge-hub-router" +description = "Primitives of the xcm-bridge-hub fee pallet." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } + +# Substrate Dependencies +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "scale-info/std", + "sp-runtime/std", + "sp-core/std", +] diff --git a/primitives/xcm-bridge-hub-router/src/lib.rs b/primitives/xcm-bridge-hub-router/src/lib.rs new file mode 100644 index 0000000000000..0dd329f9e4a0e --- /dev/null +++ b/primitives/xcm-bridge-hub-router/src/lib.rs @@ -0,0 +1,66 @@ +// 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 . + +//! Primitives of the `xcm-bridge-hub-router` pallet. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_core::H256; +use sp_runtime::{FixedU128, RuntimeDebug}; + +/// Minimal delivery fee factor. +pub const MINIMAL_DELIVERY_FEE_FACTOR: FixedU128 = FixedU128::from_u32(1); + +/// XCM channel status provider that may report whether it is congested or not. +/// +/// By channel we mean the physical channel that is used to deliver messages of one +/// of the bridge queues. +pub trait XcmChannelStatusProvider { + /// Returns true if the channel is currently congested. + fn is_congested() -> bool; +} + +impl XcmChannelStatusProvider for () { + fn is_congested() -> bool { + false + } +} + +/// Current status of the bridge. +#[derive(Clone, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen, RuntimeDebug)] +pub struct BridgeState { + /// Current delivery fee factor. + pub delivery_fee_factor: FixedU128, + /// Bridge congestion flag. + pub is_congested: bool, +} + +impl Default for BridgeState { + fn default() -> BridgeState { + BridgeState { delivery_fee_factor: MINIMAL_DELIVERY_FEE_FACTOR, is_congested: false } + } +} + +/// A minimized version of `pallet-xcm-bridge-hub-router::Call` that can be used without a runtime. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +#[allow(non_camel_case_types)] +pub enum XcmBridgeHubRouterCall { + /// `pallet-xcm-bridge-hub-router::Call::report_bridge_status` + #[codec(index = 0)] + report_bridge_status { bridge_id: H256, is_congested: bool }, +} From 2a6c4eaa9d03a0d564b5271489236e2bfba68070 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 17 Aug 2023 10:34:08 +0300 Subject: [PATCH 1094/1210] #2351 to polkadot-staging (#2359) --- relays/client-substrate/src/client.rs | 58 ++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 688303fb73796..8328e1ce8bec1 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -138,6 +138,15 @@ struct ClientData { client: Arc, } +/// Already encoded value. +struct PreEncoded(Vec); + +impl Encode for PreEncoded { + fn encode(&self) -> Vec { + self.0.clone() + } +} + #[async_trait] impl relay_utils::relay_loop::Client for Client { type Error = Error; @@ -438,6 +447,16 @@ impl Client { /// /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_unsigned_extrinsic(&self, transaction: Bytes) -> Result { + // one last check that the transaction is valid. Most of checks happen in the relay loop and + // it is the "final" check before submission. + let best_header_hash = self.best_header().await?.hash(); + self.validate_transaction(best_header_hash, PreEncoded(transaction.0.clone())) + .await + .map_err(|e| { + log::error!(target: "bridge", "Pre-submit {} transaction validation failed: {:?}", C::NAME, e); + e + })??; + self.jsonrpsee_execute(move |client| async move { let tx_hash = SubstrateAuthorClient::::submit_extrinsic(&*client, transaction) .await @@ -494,9 +513,19 @@ impl Client { // will be dropped from the pool. let best_header_id = best_header.parent_id().unwrap_or_else(|| best_header.id()); + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; + let signed_extrinsic = C::sign_transaction(signing_data, extrinsic)?.encode(); + + // one last check that the transaction is valid. Most of checks happen in the relay loop and + // it is the "final" check before submission. + self.validate_transaction(best_header_id.1, PreEncoded(signed_extrinsic.clone())) + .await + .map_err(|e| { + log::error!(target: "bridge", "Pre-submit {} transaction validation failed: {:?}", C::NAME, e); + e + })??; + self.jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let signed_extrinsic = C::sign_transaction(signing_data, extrinsic)?.encode(); let tx_hash = SubstrateAuthorClient::::submit_extrinsic(&*client, Bytes(signed_extrinsic)) .await @@ -529,16 +558,27 @@ impl Client { let transaction_nonce = self.next_account_index(signer.public().into()).await?; let best_header = self.best_header().await?; let best_header_id = best_header.id(); + + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; + let stall_timeout = transaction_stall_timeout( + extrinsic.era.mortality_period(), + C::AVERAGE_BLOCK_INTERVAL, + STALL_TIMEOUT, + ); + let signed_extrinsic = C::sign_transaction(signing_data, extrinsic)?.encode(); + + // one last check that the transaction is valid. Most of checks happen in the relay loop and + // it is the "final" check before submission. + self.validate_transaction(best_header_id.1, PreEncoded(signed_extrinsic.clone())) + .await + .map_err(|e| { + log::error!(target: "bridge", "Pre-submit {} transaction validation failed: {:?}", C::NAME, e); + e + })??; + let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); let (tracker, subscription) = self .jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; - let stall_timeout = transaction_stall_timeout( - extrinsic.era.mortality_period(), - C::AVERAGE_BLOCK_INTERVAL, - STALL_TIMEOUT, - ); - let signed_extrinsic = C::sign_transaction(signing_data, extrinsic)?.encode(); let tx_hash = C::Hasher::hash(&signed_extrinsic); let subscription = SubstrateAuthorClient::::submit_and_watch_extrinsic( &*client, From 89eb627ca599837f8c60b62fa3cbe2b80b849c8e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 23 Aug 2023 12:51:24 +0300 Subject: [PATCH 1095/1210] Manually update deps in polkadot staging (#2371) * Bump clap from 4.3.19 to 4.3.21 Bumps [clap](https://github.com/clap-rs/clap) from 4.3.19 to 4.3.21. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.3.19...v4.3.21) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump tokio from 1.29.1 to 1.31.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.29.1 to 1.31.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.29.1...tokio-1.31.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump sysinfo from 0.29.7 to 0.29.8 Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.29.7 to 0.29.8. - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/commits) --- updated-dependencies: - dependency-name: sysinfo dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump async-trait from 0.1.72 to 0.1.73 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.72 to 0.1.73. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.72...0.1.73) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump log from 0.4.19 to 0.4.20 Bumps [log](https://github.com/rust-lang/log) from 0.4.19 to 0.4.20. - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.19...0.4.20) --- updated-dependencies: - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump anyhow from 1.0.72 to 1.0.75 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.72 to 1.0.75. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.72...1.0.75) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump tempfile from 3.7.1 to 3.8.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.7.1 to 3.8.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.7.1...v3.8.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump clap from 4.3.21 to 4.3.23 Bumps [clap](https://github.com/clap-rs/clap) from 4.3.21 to 4.3.23. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.3.21...v4.3.23) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump tokio from 1.31.0 to 1.32.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.31.0 to 1.32.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.31.0...tokio-1.32.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Bump serde_json from 1.0.104 to 1.0.105 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.104 to 1.0.105. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.104...v1.0.105) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump thiserror from 1.0.44 to 1.0.47 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.44 to 1.0.47. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.44...1.0.47) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Bump rustls-webpki from 0.101.1 to 0.101.4 Bumps [rustls-webpki](https://github.com/rustls/webpki) from 0.101.1 to 0.101.4. - [Release notes](https://github.com/rustls/webpki/releases) - [Commits](https://github.com/rustls/webpki/compare/v/0.101.1...v/0.101.4) --- updated-dependencies: - dependency-name: rustls-webpki dependency-type: indirect ... Signed-off-by: dependabot[bot] * Bump rustls-webpki from 0.100.1 to 0.100.2 in /tools/runtime-codegen Bumps [rustls-webpki](https://github.com/rustls/webpki) from 0.100.1 to 0.100.2. - [Release notes](https://github.com/rustls/webpki/releases) - [Commits](https://github.com/rustls/webpki/compare/v/0.100.1...v/0.100.2) --- updated-dependencies: - dependency-name: rustls-webpki dependency-type: indirect ... Signed-off-by: dependabot[bot] * fix clippy (#2335) * fix clippy * fix clippy issues --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- bin/millau/node/Cargo.toml | 4 ++-- bin/rialto-parachain/node/Cargo.toml | 4 ++-- bin/rialto/node/Cargo.toml | 4 ++-- bin/runtime-common/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 4 ++-- .../src/bridges/rialto_millau/millau_headers_to_rialto.rs | 2 +- .../src/bridges/rialto_millau/rialto_headers_to_millau.rs | 2 +- .../millau_headers_to_rialto_parachain.rs | 2 +- .../rialto_parachains_to_millau.rs | 2 +- .../bridges/westend_millau/westend_headers_to_millau.rs | 2 +- .../westend_millau/westend_parachains_to_millau.rs | 2 +- .../src/cli/relay_headers_and_messages/mod.rs | 4 ++-- relays/client-substrate/Cargo.toml | 6 +++--- relays/lib-substrate-relay/Cargo.toml | 4 ++-- relays/lib-substrate-relay/src/messages_metrics.rs | 2 +- relays/messages/Cargo.toml | 2 +- relays/messages/src/message_race_loop.rs | 8 ++------ relays/parachains/Cargo.toml | 4 ++-- relays/utils/Cargo.toml | 6 +++--- 25 files changed, 37 insertions(+), 41 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index a0a0e4ffbd1e0..d551694422ace 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,10 +9,10 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.23", features = ["derive"] } futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.96" +serde_json = "1.0.105" # Bridge dependencies diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 7dc89a0111c95..537098bbd6e61 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,8 +17,8 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.2.7", features = ["derive"] } -log = '0.4.17' +clap = { version = "4.3.23", features = ["derive"] } +log = '0.4.20' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 7f28a15426322..aa3824e4d51de 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -9,8 +9,8 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.2.7", features = ["derive"] } -serde_json = "1.0.96" +clap = { version = "4.3.23", features = ["derive"] } +serde_json = "1.0.105" # Bridge dependencies diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 9ca6a4c5df98c..5fb75f3887f11 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 421f11ddc8979..202d30b170579 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index d04c60729790e..0bd62beeaad48 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index da69f66d53868..8db52acefc0b4 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index f7e2184a261d2..3e8d00511d533 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index ef41d70a242f2..93b0917970608 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 3d13e7cc3d7f2..8a6bcef060480 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.20", default-features = false } scale-info = { version = "2.8.0", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index f71920a1d182e..6e95895983098 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -12,7 +12,7 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.28" hex = "0.4" -log = "0.4.17" +log = "0.4.20" num-format = "0.4" num-traits = "0.2" rbtag = "0.3" @@ -72,5 +72,5 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "maste bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.4" sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } -tempfile = "3.5" +tempfile = "3.8" finality-grandpa = { version = "0.16.2" } diff --git a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs index 490ded1f67cb9..2e2452eb31b8c 100644 --- a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs @@ -41,7 +41,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { >; } -//// `Millau` to `Rialto` bridge definition. +/// `Millau` to `Rialto` bridge definition. pub struct MillauToRialtoCliBridge {} impl CliBridgeBase for MillauToRialtoCliBridge { diff --git a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs index c6ac05011f301..c855aa66c2983 100644 --- a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs @@ -41,7 +41,7 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { >; } -//// `Rialto` to `Millau` bridge definition. +/// `Rialto` to `Millau` bridge definition. pub struct RialtoToMillauCliBridge {} impl CliBridgeBase for RialtoToMillauCliBridge { diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs index 79d3bde22fa75..fd7559843022d 100644 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs @@ -62,7 +62,7 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { type SubmitFinalityProofCallBuilder = MillauFinalityToRialtoParachainCallBuilder; } -//// `Millau` to `RialtoParachain` bridge definition. +/// `Millau` to `RialtoParachain` bridge definition. pub struct MillauToRialtoParachainCliBridge {} impl CliBridgeBase for MillauToRialtoParachainCliBridge { diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs index 04f2b5aa7c745..6b2a1332144dc 100644 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs @@ -44,7 +44,7 @@ pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder = millau_runtime::WithRialtoParachainsInstance, >; -//// `RialtoParachain` to `Millau` bridge definition. +/// `RialtoParachain` to `Millau` bridge definition. pub struct RialtoParachainToMillauCliBridge {} impl CliBridgeBase for RialtoParachainToMillauCliBridge { diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs index eadbc3057045a..afbbd064d1fe0 100644 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs +++ b/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs @@ -41,7 +41,7 @@ impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { >; } -//// `Westend` to `Millau` bridge definition. +/// `Westend` to `Millau` bridge definition. pub struct WestendToMillauCliBridge {} impl CliBridgeBase for WestendToMillauCliBridge { diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs index 78164eb17e449..a3d5ba08df503 100644 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs @@ -43,7 +43,7 @@ pub type WestendParachainsToMillauSubmitParachainHeadsCallBuilder = millau_runtime::WithWestendParachainsInstance, >; -//// `WestendParachain` to `Millau` bridge definition. +/// `WestendParachain` to `Millau` bridge definition. pub struct AssetHubWestendToMillauCliBridge {} impl ParachainToRelayHeadersCliBridge for AssetHubWestendToMillauCliBridge { diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index a47283400aab0..21b352aff6ef6 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -355,14 +355,14 @@ where let common = self.mut_base().mut_common(); substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Right>( common.left.client.clone(), - &mut common.metrics_params, + &common.metrics_params, &common.left.accounts, &lanes, ) .await?; substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Left>( common.right.client.clone(), - &mut common.metrics_params, + &common.metrics_params, &common.right.accounts, &lanes, ) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 359f049d9dbd0..e0c1a5461f971 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -11,12 +11,12 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.28" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } -log = "0.4.17" +log = "0.4.20" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.9.0", features = ["derive"] } -tokio = { version = "1.28", features = ["rt-multi-thread"] } -thiserror = "1.0.40" +tokio = { version = "1.32", features = ["rt-multi-thread"] } +thiserror = "1.0.47" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 72e97dbe69ac6..8fe86bfb06a08 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,14 +7,14 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.40" +thiserror = "1.0.47" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.28" hex = "0.4" num-traits = "0.2" -log = "0.4.17" +log = "0.4.20" # Bridge dependencies diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/relays/lib-substrate-relay/src/messages_metrics.rs index 50972dfc49cb6..27bf6186c3ba0 100644 --- a/relays/lib-substrate-relay/src/messages_metrics.rs +++ b/relays/lib-substrate-relay/src/messages_metrics.rs @@ -37,7 +37,7 @@ use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; /// Add relay accounts balance metrics. pub async fn add_relay_balances_metrics( client: Client, - metrics: &mut MetricsParams, + metrics: &MetricsParams, relay_accounts: &Vec>>, lanes: &[LaneId], ) -> anyhow::Result<()> diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index a45b272810537..4d84f220a3a6d 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -11,7 +11,7 @@ async-trait = "0.1" env_logger = "0.10" futures = "0.3.28" hex = "0.4" -log = "0.4.17" +log = "0.4.20" num-traits = "0.2" parking_lot = "0.12.1" diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index 3df9eef496016..f28be78842fc1 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -664,7 +664,7 @@ pub async fn run, TC: TargetClient

>( }) .fuse(), ); - } else if source_nonces_required && best_at_source.is_some() { + } else if let (true, Some(best_at_source)) = (source_nonces_required, best_at_source) { log::debug!(target: "bridge", "Asking {} about message nonces", P::source_name()); let at_block = race_state .best_finalized_source_header_id_at_source @@ -674,11 +674,7 @@ pub async fn run, TC: TargetClient

>( best_finalized_source_header_id_at_source is Some; qed", ) .clone(); - source_nonces.set( - race_source - .nonces(at_block, best_at_source.expect("guaranteed by if condition; qed")) - .fuse(), - ); + source_nonces.set(race_source.nonces(at_block, best_at_source).fuse()); } else { source_client_is_online = true; } diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 0cecf063922f9..75fec34b425f2 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,9 +7,9 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.68" +async-trait = "0.1.73" futures = "0.3.28" -log = "0.4.17" +log = "0.4.20" relay-utils = { path = "../utils" } # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 65e268a07707e..5aa1a4e6bb224 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -15,13 +15,13 @@ isahc = "1.2" env_logger = "0.10.0" futures = "0.3.28" jsonpath_lib = "0.3" -log = "0.4.17" +log = "0.4.20" num-traits = "0.2" serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.28", features = ["rt"] } -thiserror = "1.0.40" +tokio = { version = "1.32", features = ["rt"] } +thiserror = "1.0.47" # Bridge dependencies From cd32c1423d05351746230e15a1e934daf3f2b61d Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 23 Aug 2023 19:31:17 +0300 Subject: [PATCH 1096/1210] Backport: Implement basic equivocations detection loop (#2375) * Implement basic equivocations detection loop (#2367) * FinalityProofsBuf adjustments - store a Vec - transform prune `buf_limit` to Option * FinalityProof: add target_header_hash() * Target client: implement best_synced_header_hash() * Implement first version of the equivocations detection loop * Address code review comments * Leftover * polkadot-staging adjustments --- .../header-chain/src/justification/mod.rs | 6 +- primitives/header-chain/src/lib.rs | 7 +- relays/equivocation/Cargo.toml | 5 + relays/equivocation/src/equivocation_loop.rs | 336 ++++++++++++++++++ relays/equivocation/src/lib.rs | 29 +- relays/equivocation/src/reporter.rs | 83 +++++ relays/finality/src/base.rs | 2 +- relays/finality/src/finality_loop.rs | 6 +- relays/finality/src/finality_proofs.rs | 67 ++-- relays/finality/src/headers.rs | 21 +- relays/finality/src/lib.rs | 1 + relays/finality/src/mock.rs | 6 +- .../src/equivocation/target.rs | 28 +- .../src/finality/target.rs | 8 +- .../src/finality_base/engine.rs | 10 +- .../src/finality_base/mod.rs | 20 ++ .../src/messages_source.rs | 7 +- relays/utils/src/lib.rs | 9 +- 18 files changed, 572 insertions(+), 79 deletions(-) create mode 100644 relays/equivocation/src/equivocation_loop.rs create mode 100644 relays/equivocation/src/reporter.rs diff --git a/primitives/header-chain/src/justification/mod.rs b/primitives/header-chain/src/justification/mod.rs index 5fa5d7d607c8a..fbb8af80b2cdd 100644 --- a/primitives/header-chain/src/justification/mod.rs +++ b/primitives/header-chain/src/justification/mod.rs @@ -97,7 +97,11 @@ impl GrandpaJustification { } } -impl crate::FinalityProof for GrandpaJustification { +impl crate::FinalityProof for GrandpaJustification { + fn target_header_hash(&self) -> H::Hash { + self.commit.target_hash + } + fn target_header_number(&self) -> H::Number { self.commit.target_number } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index ea6c58f4c0979..b1eda8dc3f73c 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -127,7 +127,10 @@ pub struct InitializationData { } /// Abstract finality proof that is justifying block finality. -pub trait FinalityProof: Clone + Send + Sync + Debug { +pub trait FinalityProof: Clone + Send + Sync + Debug { + /// Return hash of header that this proof is generated for. + fn target_header_hash(&self) -> Hash; + /// Return number of header that this proof is generated for. fn target_header_number(&self) -> Number; } @@ -209,7 +212,7 @@ impl TryFrom> for HeaderGrandpa /// Helper trait for finding equivocations in finality proofs. pub trait FindEquivocations { /// The type returned when encountering an error while looking for equivocations. - type Error; + type Error: Debug; /// Find equivocations. fn find_equivocations( diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 93a1470c6a978..637fa4feaf686 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -7,7 +7,12 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Equivocation detector" [dependencies] +async-std = "1.6.5" async-trait = "0.1" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +futures = "0.3.28" +log = "0.4.20" +num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/equivocation/src/equivocation_loop.rs b/relays/equivocation/src/equivocation_loop.rs new file mode 100644 index 0000000000000..5b935786353cf --- /dev/null +++ b/relays/equivocation/src/equivocation_loop.rs @@ -0,0 +1,336 @@ +// Copyright 2019-2023 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 . + +use crate::{ + reporter::EquivocationsReporter, EquivocationDetectionPipeline, HeaderFinalityInfo, + SourceClient, TargetClient, +}; + +use bp_header_chain::{FinalityProof, FindEquivocations}; +use finality_relay::{FinalityProofsBuf, FinalityProofsStream}; +use futures::{select, FutureExt}; +use num_traits::Saturating; +use relay_utils::{ + relay_loop::{reconnect_failed_client, RECONNECT_DELAY}, + FailedClient, MaybeConnectionError, +}; +use std::{future::Future, time::Duration}; + +/// The context needed for finding equivocations inside finality proofs and reporting them. +struct EquivocationReportingContext { + synced_header_hash: P::Hash, + synced_verification_context: P::FinalityVerificationContext, +} + +impl EquivocationReportingContext

{ + /// Try to get the `EquivocationReportingContext` used by the target chain + /// at the provided block. + async fn try_read_from_target>( + target_client: &TC, + at: P::TargetNumber, + ) -> Result, TC::Error> { + let maybe_best_synced_header_hash = target_client.best_synced_header_hash(at).await?; + Ok(match maybe_best_synced_header_hash { + Some(best_synced_header_hash) => Some(EquivocationReportingContext { + synced_header_hash: best_synced_header_hash, + synced_verification_context: target_client + .finality_verification_context(at) + .await?, + }), + None => None, + }) + } + + /// Update with the new context introduced by the `HeaderFinalityInfo

` if any. + fn update(&mut self, info: HeaderFinalityInfo

) { + if let Some(new_verification_context) = info.new_verification_context { + self.synced_header_hash = info.finality_proof.target_header_hash(); + self.synced_verification_context = new_verification_context; + } + } +} + +/// Equivocations detection loop state. +struct EquivocationDetectionLoop< + P: EquivocationDetectionPipeline, + SC: SourceClient

, + TC: TargetClient

, +> { + source_client: SC, + target_client: TC, + + from_block_num: Option, + until_block_num: Option, + + reporter: EquivocationsReporter, + + finality_proofs_stream: FinalityProofsStream, + finality_proofs_buf: FinalityProofsBuf

, +} + +impl, TC: TargetClient

> + EquivocationDetectionLoop +{ + async fn handle_source_error(&mut self, e: SC::Error) { + if e.is_connection_error() { + reconnect_failed_client( + FailedClient::Source, + RECONNECT_DELAY, + &mut self.source_client, + &mut self.target_client, + ) + .await; + } else { + async_std::task::sleep(RECONNECT_DELAY).await; + } + } + + async fn handle_target_error(&mut self, e: TC::Error) { + if e.is_connection_error() { + reconnect_failed_client( + FailedClient::Target, + RECONNECT_DELAY, + &mut self.source_client, + &mut self.target_client, + ) + .await; + } else { + async_std::task::sleep(RECONNECT_DELAY).await; + } + } + + async fn ensure_finality_proofs_stream(&mut self) { + match self.finality_proofs_stream.ensure_stream(&self.source_client).await { + Ok(_) => {}, + Err(e) => { + log::error!( + target: "bridge", + "Could not connect to the {} `FinalityProofsStream`: {e:?}", + P::SOURCE_NAME, + ); + + // Reconnect to the source client if needed + self.handle_source_error(e).await + }, + } + } + + async fn best_finalized_target_block_number(&mut self) -> Option { + match self.target_client.best_finalized_header_number().await { + Ok(block_num) => Some(block_num), + Err(e) => { + log::error!( + target: "bridge", + "Could not read best finalized header number from {}: {e:?}", + P::TARGET_NAME, + ); + + // Reconnect target client and move on + self.handle_target_error(e).await; + + None + }, + } + } + + async fn build_equivocation_reporting_context( + &mut self, + block_num: P::TargetNumber, + ) -> Option> { + match EquivocationReportingContext::try_read_from_target( + &self.target_client, + block_num.saturating_sub(1.into()), + ) + .await + { + Ok(Some(context)) => Some(context), + Ok(None) => None, + Err(e) => { + log::error!( + target: "bridge", + "Could not read {} `EquivocationReportingContext` from {} at block {block_num}: {e:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + ); + + // Reconnect target client if needed and move on. + self.handle_target_error(e).await; + None + }, + } + } + + /// Try to get the finality info associated to the source headers synced with the target chain + /// at the specified block. + async fn synced_source_headers_at_target( + &mut self, + at: P::TargetNumber, + ) -> Vec> { + match self.target_client.synced_headers_finality_info(at).await { + Ok(synced_headers) => synced_headers, + Err(e) => { + log::error!( + target: "bridge", + "Could not get {} headers synced to {} at block {at:?}", + P::SOURCE_NAME, + P::TARGET_NAME + ); + + // Reconnect in case of a connection error. + self.handle_target_error(e).await; + // And move on to the next block. + vec![] + }, + } + } + + async fn report_equivocation(&mut self, at: P::Hash, equivocation: P::EquivocationProof) { + match self.reporter.submit_report(&self.source_client, at, equivocation.clone()).await { + Ok(_) => {}, + Err(e) => { + log::error!( + target: "bridge", + "Could not submit equivocation report to {} for {equivocation:?}: {e:?}", + P::SOURCE_NAME, + ); + + // Reconnect source client and move on + self.handle_source_error(e).await; + }, + } + } + + async fn check_block( + &mut self, + block_num: P::TargetNumber, + context: &mut EquivocationReportingContext

, + ) { + let synced_headers = self.synced_source_headers_at_target(block_num).await; + + for synced_header in synced_headers { + self.finality_proofs_buf.fill(&mut self.finality_proofs_stream); + + let equivocations = match P::EquivocationsFinder::find_equivocations( + &context.synced_verification_context, + &synced_header.finality_proof, + self.finality_proofs_buf.buf().as_slice(), + ) { + Ok(equivocations) => equivocations, + Err(e) => { + log::error!( + target: "bridge", + "Could not search for equivocations in the finality proof \ + for source header {:?} synced at target block {block_num:?}: {e:?}", + synced_header.finality_proof.target_header_hash() + ); + continue + }, + }; + for equivocation in equivocations { + self.report_equivocation(context.synced_header_hash, equivocation).await; + } + + self.finality_proofs_buf + .prune(synced_header.finality_proof.target_header_number(), None); + context.update(synced_header); + } + } + + async fn do_run(&mut self, tick: Duration, exit_signal: impl Future) { + let exit_signal = exit_signal.fuse(); + futures::pin_mut!(exit_signal); + + loop { + // Make sure that we are connected to the source finality proofs stream. + self.ensure_finality_proofs_stream().await; + // Check the status of the pending equivocation reports + self.reporter.process_pending_reports().await; + + // Update blocks range. + if let Some(block_number) = self.best_finalized_target_block_number().await { + self.from_block_num.get_or_insert(block_number); + self.until_block_num = Some(block_number); + } + let (from, until) = match (self.from_block_num, self.until_block_num) { + (Some(from), Some(until)) => (from, until), + _ => continue, + }; + + // Check the available blocks + let mut current_block_number = from; + while current_block_number <= until { + let mut context = + match self.build_equivocation_reporting_context(current_block_number).await { + Some(context) => context, + None => continue, + }; + self.check_block(current_block_number, &mut context).await; + current_block_number = current_block_number.saturating_add(1.into()); + } + self.until_block_num = Some(current_block_number); + + select! { + _ = async_std::task::sleep(tick).fuse() => {}, + _ = exit_signal => return, + } + } + } + + pub async fn run( + source_client: SC, + target_client: TC, + tick: Duration, + exit_signal: impl Future, + ) -> Result<(), FailedClient> { + let mut equivocation_detection_loop = Self { + source_client, + target_client, + from_block_num: None, + until_block_num: None, + reporter: EquivocationsReporter::::new(), + finality_proofs_stream: FinalityProofsStream::new(), + finality_proofs_buf: FinalityProofsBuf::new(vec![]), + }; + + equivocation_detection_loop.do_run(tick, exit_signal).await; + Ok(()) + } +} + +/// Spawn the equivocations detection loop. +/// TODO: remove `#[allow(dead_code)]` +#[allow(dead_code)] +pub async fn run( + source_client: impl SourceClient

, + target_client: impl TargetClient

, + tick: Duration, + exit_signal: impl Future + 'static + Send, +) -> Result<(), relay_utils::Error> { + let exit_signal = exit_signal.shared(); + relay_utils::relay_loop(source_client, target_client) + .run( + format!("{}_to_{}_EquivocationDetection", P::SOURCE_NAME, P::TARGET_NAME), + move |source_client, target_client, _metrics| { + EquivocationDetectionLoop::run( + source_client, + target_client, + tick, + exit_signal.clone(), + ) + }, + ) + .await +} diff --git a/relays/equivocation/src/lib.rs b/relays/equivocation/src/lib.rs index 9019c3cf69f6c..bbae97502f579 100644 --- a/relays/equivocation/src/lib.rs +++ b/relays/equivocation/src/lib.rs @@ -14,18 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +mod equivocation_loop; +mod reporter; + use async_trait::async_trait; -use bp_header_chain::{FindEquivocations, HeaderFinalityInfo}; +use bp_header_chain::FindEquivocations; use finality_relay::{FinalityPipeline, SourceClientBase}; use relay_utils::{relay_loop::Client as RelayClient, TransactionTracker}; +use std::fmt::Debug; pub trait EquivocationDetectionPipeline: FinalityPipeline { /// Block number of the target chain. type TargetNumber: relay_utils::BlockNumberBase; /// The context needed for validating finality proofs. - type FinalityVerificationContext; + type FinalityVerificationContext: Send; /// The type of the equivocation proof. - type EquivocationProof; + type EquivocationProof: Clone + Debug + Send + Sync; /// The equivocations finder. type EquivocationsFinder: FindEquivocations< Self::FinalityProof, @@ -34,6 +38,11 @@ pub trait EquivocationDetectionPipeline: FinalityPipeline { >; } +type HeaderFinalityInfo

= bp_header_chain::HeaderFinalityInfo< +

::FinalityProof, +

::FinalityVerificationContext, +>; + /// Source client used in equivocation detection loop. #[async_trait] pub trait SourceClient: SourceClientBase

{ @@ -51,6 +60,15 @@ pub trait SourceClient: SourceClientBase

{ /// Target client used in equivocation detection loop. #[async_trait] pub trait TargetClient: RelayClient { + /// Get the best finalized header number. + async fn best_finalized_header_number(&self) -> Result; + + /// Get the hash of the best source header known by the target at the provided block number. + async fn best_synced_header_hash( + &self, + at: P::TargetNumber, + ) -> Result, Self::Error>; + /// Get the data stored by the target at the specified block for validating source finality /// proofs. async fn finality_verification_context( @@ -63,8 +81,5 @@ pub trait TargetClient: RelayClient { async fn synced_headers_finality_info( &self, at: P::TargetNumber, - ) -> Result< - Vec>, - Self::Error, - >; + ) -> Result>, Self::Error>; } diff --git a/relays/equivocation/src/reporter.rs b/relays/equivocation/src/reporter.rs new file mode 100644 index 0000000000000..27b4d71beb01b --- /dev/null +++ b/relays/equivocation/src/reporter.rs @@ -0,0 +1,83 @@ +// Copyright 2019-2023 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 . + +//! Helper struct used for submitting finality reports and tracking their status. + +use crate::{EquivocationDetectionPipeline, SourceClient}; + +use futures::FutureExt; +use relay_utils::{TrackedTransactionFuture, TrackedTransactionStatus, TransactionTracker}; +use std::{ + future::poll_fn, + task::{Context, Poll}, +}; + +pub struct EquivocationsReporter> { + pending_reports: Vec>, +} + +impl> EquivocationsReporter { + pub fn new() -> Self { + Self { pending_reports: vec![] } + } + + /// Submit a `report_equivocation()` transaction to the source chain. + /// + /// We store the transaction tracker for future monitoring. + pub async fn submit_report( + &mut self, + source_client: &SC, + at: P::Hash, + equivocation: P::EquivocationProof, + ) -> Result<(), SC::Error> { + let pending_report = source_client.report_equivocation(at, equivocation).await?; + self.pending_reports.push(pending_report.wait()); + + Ok(()) + } + + fn do_process_pending_reports(&mut self, cx: &mut Context<'_>) -> Poll<()> { + self.pending_reports.retain_mut(|pending_report| { + match pending_report.poll_unpin(cx) { + Poll::Ready(tx_status) => { + match tx_status { + TrackedTransactionStatus::Lost => { + log::error!(target: "bridge", "Equivocation report tx was lost"); + }, + TrackedTransactionStatus::Finalized(id) => { + log::error!(target: "bridge", "Equivocation report tx was finalized in source block {id:?}"); + }, + } + + // The future was processed. Drop it. + false + }, + Poll::Pending => { + // The future is still pending. Retain it. + true + }, + } + }); + + Poll::Ready(()) + } + + /// Iterate through all the pending `report_equivocation()` transactions + /// and log the ones that finished. + pub async fn process_pending_reports(&mut self) { + poll_fn(|cx| self.do_process_pending_reports(cx)).await + } +} diff --git a/relays/finality/src/base.rs b/relays/finality/src/base.rs index bf9acbdf98210..4253468eaace1 100644 --- a/relays/finality/src/base.rs +++ b/relays/finality/src/base.rs @@ -32,7 +32,7 @@ pub trait FinalityPipeline: 'static + Clone + Debug + Send + Sync { /// Synced headers are identified by this number. type Number: relay_utils::BlockNumberBase; /// Finality proof type. - type FinalityProof: FinalityProof; + type FinalityProof: FinalityProof; } /// Source client used in finality related loops. diff --git a/relays/finality/src/finality_loop.rs b/relays/finality/src/finality_loop.rs index b1f1f018c0edf..e31d8a708122d 100644 --- a/relays/finality/src/finality_loop.rs +++ b/relays/finality/src/finality_loop.rs @@ -319,8 +319,10 @@ impl, TC: TargetClient

> Finality .as_ref() .map(|justified_header| justified_header.number()) .unwrap_or(info.best_number_at_target); - self.finality_proofs_buf - .prune(oldest_finality_proof_to_keep, self.sync_params.recent_finality_proofs_limit); + self.finality_proofs_buf.prune( + oldest_finality_proof_to_keep, + Some(self.sync_params.recent_finality_proofs_limit), + ); Ok(maybe_justified_header) } diff --git a/relays/finality/src/finality_proofs.rs b/relays/finality/src/finality_proofs.rs index d457c0693bf3e..cd6d12938ce42 100644 --- a/relays/finality/src/finality_proofs.rs +++ b/relays/finality/src/finality_proofs.rs @@ -20,11 +20,8 @@ use bp_header_chain::FinalityProof; use futures::{FutureExt, Stream, StreamExt}; use std::pin::Pin; -/// Finality proofs container. Ordered by target header number. -pub type FinalityProofs

= - Vec<(

::Number,

::FinalityProof)>; - /// Source finality proofs stream that may be restarted. +#[derive(Default)] pub struct FinalityProofsStream> { /// The underlying stream. stream: Option>>, @@ -75,16 +72,16 @@ impl> FinalityProofsStream { /// Source finality proofs buffer. pub struct FinalityProofsBuf { - /// Proofs buffer. - buf: FinalityProofs

, + /// Proofs buffer. Ordered by target header number. + buf: Vec, } impl FinalityProofsBuf

{ - pub fn new(buf: FinalityProofs

) -> Self { + pub fn new(buf: Vec) -> Self { Self { buf } } - pub fn buf(&self) -> &FinalityProofs

{ + pub fn buf(&self) -> &Vec { &self.buf } @@ -98,7 +95,7 @@ impl FinalityProofsBuf

{ last_header_number = Some(target_header_number); proofs_count += 1; - self.buf.push((target_header_number, finality_proof)); + self.buf.push(finality_proof); } if proofs_count != 0 { @@ -113,15 +110,19 @@ impl FinalityProofsBuf

{ } } - pub fn prune(&mut self, until_hdr_num: P::Number, buf_limit: usize) { - let kept_hdr_idx = self + /// Prune all finality proofs that target header numbers older than `first_to_keep`. + pub fn prune(&mut self, first_to_keep: P::Number, maybe_buf_limit: Option) { + let first_to_keep_idx = self .buf - .binary_search_by_key(&until_hdr_num, |(hdr_num, _)| *hdr_num) + .binary_search_by_key(&first_to_keep, |hdr| hdr.target_header_number()) .map(|idx| idx + 1) .unwrap_or_else(|idx| idx); - let buf_limit_idx = self.buf.len().saturating_sub(buf_limit); + let buf_limit_idx = match maybe_buf_limit { + Some(buf_limit) => self.buf.len().saturating_sub(buf_limit), + None => 0, + }; - self.buf = self.buf.split_off(std::cmp::max(kept_hdr_idx, buf_limit_idx)); + self.buf = self.buf.split_off(std::cmp::max(first_to_keep_idx, buf_limit_idx)); } } @@ -140,13 +141,13 @@ mod tests { fn finality_proofs_buf_fill_works() { // when stream is currently empty, nothing is changed let mut finality_proofs_buf = - FinalityProofsBuf:: { buf: vec![(1, TestFinalityProof(1))] }; + FinalityProofsBuf:: { buf: vec![TestFinalityProof(1)] }; let mut stream = FinalityProofsStream::::from_stream( Box::pin(futures::stream::pending()), ); finality_proofs_buf.fill(&mut stream); - assert_eq!(finality_proofs_buf.buf, vec![(1, TestFinalityProof(1))]); + assert_eq!(finality_proofs_buf.buf, vec![TestFinalityProof(1)]); assert!(stream.stream.is_some()); // when stream has entry with target, it is added to the recent proofs container @@ -158,10 +159,7 @@ mod tests { ), ); finality_proofs_buf.fill(&mut stream); - assert_eq!( - finality_proofs_buf.buf, - vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] - ); + assert_eq!(finality_proofs_buf.buf, vec![TestFinalityProof(1), TestFinalityProof(4)]); assert!(stream.stream.is_some()); // when stream has ended, we'll need to restart it @@ -170,21 +168,20 @@ mod tests { Box::pin(futures::stream::empty()), ); finality_proofs_buf.fill(&mut stream); - assert_eq!( - finality_proofs_buf.buf, - vec![(1, TestFinalityProof(1)), (4, TestFinalityProof(4))] - ); + assert_eq!(finality_proofs_buf.buf, vec![TestFinalityProof(1), TestFinalityProof(4)]); assert!(stream.stream.is_none()); } #[test] fn finality_proofs_buf_prune_works() { - let original_finality_proofs_buf: FinalityProofs = vec![ - (10, TestFinalityProof(10)), - (13, TestFinalityProof(13)), - (15, TestFinalityProof(15)), - (17, TestFinalityProof(17)), - (19, TestFinalityProof(19)), + let original_finality_proofs_buf: Vec< + ::FinalityProof, + > = vec![ + TestFinalityProof(10), + TestFinalityProof(13), + TestFinalityProof(15), + TestFinalityProof(17), + TestFinalityProof(19), ] .into_iter() .collect(); @@ -193,35 +190,35 @@ mod tests { let mut finality_proofs_buf = FinalityProofsBuf:: { buf: original_finality_proofs_buf.clone(), }; - finality_proofs_buf.prune(10, 1024); + finality_proofs_buf.prune(10, None); assert_eq!(&original_finality_proofs_buf[1..], finality_proofs_buf.buf,); // when there are no proof for justified header in the vec let mut finality_proofs_buf = FinalityProofsBuf:: { buf: original_finality_proofs_buf.clone(), }; - finality_proofs_buf.prune(11, 1024); + finality_proofs_buf.prune(11, None); assert_eq!(&original_finality_proofs_buf[1..], finality_proofs_buf.buf,); // when there are too many entries after initial prune && they also need to be pruned let mut finality_proofs_buf = FinalityProofsBuf:: { buf: original_finality_proofs_buf.clone(), }; - finality_proofs_buf.prune(10, 2); + finality_proofs_buf.prune(10, Some(2)); assert_eq!(&original_finality_proofs_buf[3..], finality_proofs_buf.buf,); // when last entry is pruned let mut finality_proofs_buf = FinalityProofsBuf:: { buf: original_finality_proofs_buf.clone(), }; - finality_proofs_buf.prune(19, 2); + finality_proofs_buf.prune(19, Some(2)); assert_eq!(&original_finality_proofs_buf[5..], finality_proofs_buf.buf,); // when post-last entry is pruned let mut finality_proofs_buf = FinalityProofsBuf:: { buf: original_finality_proofs_buf.clone(), }; - finality_proofs_buf.prune(20, 2); + finality_proofs_buf.prune(20, Some(2)); assert_eq!(&original_finality_proofs_buf[5..], finality_proofs_buf.buf,); } } diff --git a/relays/finality/src/headers.rs b/relays/finality/src/headers.rs index bdb05c9d9b72f..91f7cd0378ecd 100644 --- a/relays/finality/src/headers.rs +++ b/relays/finality/src/headers.rs @@ -19,6 +19,7 @@ use crate::{ SourceClient, SourceHeader, TargetClient, }; +use bp_header_chain::FinalityProof; use std::cmp::Ordering; /// Unjustified headers container. Ordered by header number. @@ -120,18 +121,18 @@ impl JustifiedHeaderSelector

{ while let (Some(finality_proof), Some(unjustified_header)) = (maybe_finality_proof, maybe_unjustified_header) { - match finality_proof.0.cmp(&unjustified_header.number()) { + match finality_proof.target_header_number().cmp(&unjustified_header.number()) { Ordering::Equal => { log::trace!( target: "bridge", "Managed to improve selected {} finality proof {:?} to {:?}.", P::SOURCE_NAME, maybe_justified_header.as_ref().map(|justified_header| justified_header.number()), - finality_proof.0 + finality_proof.target_header_number() ); return Some(JustifiedHeader { header: unjustified_header.clone(), - proof: finality_proof.1.clone(), + proof: finality_proof.clone(), }) }, Ordering::Less => maybe_unjustified_header = unjustified_headers_iter.next(), @@ -160,7 +161,7 @@ mod tests { fn select_better_recent_finality_proof_works() { // if there are no unjustified headers, nothing is changed let finality_proofs_buf = - FinalityProofsBuf::::new(vec![(5, TestFinalityProof(5))]); + FinalityProofsBuf::::new(vec![TestFinalityProof(5)]); let justified_header = JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; let selector = JustifiedHeaderSelector::Regular(vec![], justified_header.clone()); @@ -179,8 +180,8 @@ mod tests { // if there's no intersection between recent finality proofs and unjustified headers, // nothing is changed let finality_proofs_buf = FinalityProofsBuf::::new(vec![ - (1, TestFinalityProof(1)), - (4, TestFinalityProof(4)), + TestFinalityProof(1), + TestFinalityProof(4), ]); let justified_header = JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; @@ -193,8 +194,8 @@ mod tests { // if there's intersection between recent finality proofs and unjustified headers, but there // are no proofs in this intersection, nothing is changed let finality_proofs_buf = FinalityProofsBuf::::new(vec![ - (7, TestFinalityProof(7)), - (11, TestFinalityProof(11)), + TestFinalityProof(7), + TestFinalityProof(11), ]); let justified_header = JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; @@ -213,8 +214,8 @@ mod tests { // - this better (last from intersection) proof is selected; // - 'obsolete' unjustified headers are pruned. let finality_proofs_buf = FinalityProofsBuf::::new(vec![ - (7, TestFinalityProof(7)), - (9, TestFinalityProof(9)), + TestFinalityProof(7), + TestFinalityProof(9), ]); let justified_header = JustifiedHeader { header: TestSourceHeader(false, 2, 2), proof: TestFinalityProof(2) }; diff --git a/relays/finality/src/lib.rs b/relays/finality/src/lib.rs index 51cd9a0935535..3579e68e1ef9c 100644 --- a/relays/finality/src/lib.rs +++ b/relays/finality/src/lib.rs @@ -22,6 +22,7 @@ pub use crate::{ base::{FinalityPipeline, SourceClientBase}, finality_loop::{metrics_prefix, run, FinalitySyncParams, SourceClient, TargetClient}, + finality_proofs::{FinalityProofsBuf, FinalityProofsStream}, sync_loop_metrics::SyncLoopMetrics, }; diff --git a/relays/finality/src/mock.rs b/relays/finality/src/mock.rs index 181504ce26070..e3ec4e4d0d47a 100644 --- a/relays/finality/src/mock.rs +++ b/relays/finality/src/mock.rs @@ -106,7 +106,11 @@ impl SourceHeader> #[derive(Debug, Clone, PartialEq, Eq)] pub struct TestFinalityProof(pub TestNumber); -impl FinalityProof for TestFinalityProof { +impl FinalityProof for TestFinalityProof { + fn target_header_hash(&self) -> TestHash { + Default::default() + } + fn target_header_number(&self) -> TestNumber { self.0 } diff --git a/relays/lib-substrate-relay/src/equivocation/target.rs b/relays/lib-substrate-relay/src/equivocation/target.rs index 36343a6eddb8e..f7e63dd943af5 100644 --- a/relays/lib-substrate-relay/src/equivocation/target.rs +++ b/relays/lib-substrate-relay/src/equivocation/target.rs @@ -17,14 +17,16 @@ //! Default generic implementation of equivocation source for basic Substrate client. use crate::{ - equivocation::{EquivocationDetectionPipelineAdapter, SubstrateEquivocationDetectionPipeline}, - finality_base::engine::Engine, + equivocation::{ + EquivocationDetectionPipelineAdapter, FinalityProoffOf, FinalityVerificationContextfOf, + SubstrateEquivocationDetectionPipeline, + }, + finality_base::{best_synced_header_id, engine::Engine}, }; -use crate::equivocation::{FinalityProoffOf, FinalityVerificationContextfOf}; use async_trait::async_trait; use bp_header_chain::HeaderFinalityInfo; -use bp_runtime::BlockNumberOf; +use bp_runtime::{BlockNumberOf, HashOf}; use equivocation_detector::TargetClient; use relay_substrate_client::{Client, Error}; use relay_utils::relay_loop::Client as RelayClient; @@ -59,6 +61,24 @@ impl RelayClient for SubstrateEquivoc impl TargetClient> for SubstrateEquivocationTarget

{ + async fn best_finalized_header_number( + &self, + ) -> Result, Self::Error> { + self.client.best_finalized_header_number().await + } + + async fn best_synced_header_hash( + &self, + at: BlockNumberOf, + ) -> Result>, Self::Error> { + Ok(best_synced_header_id::( + &self.client, + self.client.header_by_number(at).await?.hash(), + ) + .await? + .map(|id| id.hash())) + } + async fn finality_verification_context( &self, at: BlockNumberOf, diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 1be668392dd36..930f0360311c3 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -20,7 +20,7 @@ use crate::{ finality::{ FinalitySyncPipelineAdapter, SubmitFinalityProofCallBuilder, SubstrateFinalitySyncPipeline, }, - finality_base::{engine::Engine, SubstrateFinalityProof}, + finality_base::{best_synced_header_id, engine::Engine, SubstrateFinalityProof}, TransactionParams, }; @@ -31,6 +31,7 @@ use relay_substrate_client::{ TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; +use sp_runtime::traits::Header; /// Substrate client as Substrate finality target. pub struct SubstrateFinalityTarget { @@ -94,12 +95,11 @@ impl TargetClient( + Ok(best_synced_header_id::( &self.client, - None, + self.client.best_header().await?.hash(), ) .await? - .best_finalized_peer_at_best_self .ok_or(Error::BridgePalletIsNotInitialized)?) } diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs index 49614638f89e6..afb2229fc4cf3 100644 --- a/relays/lib-substrate-relay/src/finality_base/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -36,7 +36,7 @@ use relay_substrate_client::{ use sp_consensus_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID}; use sp_core::{storage::StorageKey, Bytes}; use sp_runtime::{scale_info::TypeInfo, traits::Header, ConsensusEngineId}; -use std::marker::PhantomData; +use std::{fmt::Debug, marker::PhantomData}; /// Finality engine, used by the Substrate chain. #[async_trait] @@ -48,11 +48,11 @@ pub trait Engine: Send { /// Type of Finality RPC client used by this engine. type FinalityClient: SubstrateFinalityClient; /// Type of finality proofs, used by consensus engine. - type FinalityProof: FinalityProof> + Decode + Encode; + type FinalityProof: FinalityProof, BlockNumberOf> + Decode + Encode; /// The context needed for verifying finality proofs. - type FinalityVerificationContext; + type FinalityVerificationContext: Send; /// The type of the equivocation proof used by the consensus engine. - type EquivocationProof: Send + Sync; + type EquivocationProof: Clone + Debug + Send + Sync; /// The equivocations finder. type EquivocationsFinder: FindEquivocations< Self::FinalityProof, @@ -62,7 +62,7 @@ pub trait Engine: Send { /// The type of the key owner proof used by the consensus engine. type KeyOwnerProof: Send; /// Type of bridge pallet initialization data. - type InitializationData: std::fmt::Debug + Send + Sync + 'static; + type InitializationData: Debug + Send + Sync + 'static; /// Type of bridge pallet operating mode. type OperatingMode: OperatingMode + 'static; diff --git a/relays/lib-substrate-relay/src/finality_base/mod.rs b/relays/lib-substrate-relay/src/finality_base/mod.rs index bcd3f008d67c9..825960b1b3ef2 100644 --- a/relays/lib-substrate-relay/src/finality_base/mod.rs +++ b/relays/lib-substrate-relay/src/finality_base/mod.rs @@ -20,7 +20,9 @@ pub mod engine; use crate::finality_base::engine::Engine; + use async_trait::async_trait; +use bp_runtime::{HashOf, HeaderIdOf}; use codec::Decode; use futures::{stream::unfold, Stream, StreamExt}; use relay_substrate_client::{Chain, Client, Error}; @@ -85,3 +87,21 @@ pub async fn finality_proofs( ) .boxed()) } + +/// Get the id of the best `SourceChain` header known to the `TargetChain` at the provided +/// target block using the exposed runtime API method. +/// +/// The runtime API method should be `FinalityApi::best_finalized()`. +pub async fn best_synced_header_id( + target_client: &Client, + at: HashOf, +) -> Result>, Error> +where + SourceChain: Chain, + TargetChain: Chain, +{ + // now let's read id of best finalized peer header at our best finalized block + target_client + .typed_state_call(SourceChain::BEST_FINALIZED_HEADER_ID_METHOD.into(), (), Some(at)) + .await +} diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index de795beb7870c..4c49d76bdf357 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -19,6 +19,7 @@ //! `` chain. use crate::{ + finality_base::best_synced_header_id, messages_lane::{ BatchProofTransaction, MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, @@ -428,11 +429,7 @@ where // now let's read id of best finalized peer header at our best finalized block let peer_on_self_best_finalized_id = - best_finalized_peer_header_at_self::( - self_client, - self_best_id.hash(), - ) - .await?; + best_synced_header_id::(self_client, self_best_id.hash()).await?; // read actual header, matching the `peer_on_self_best_finalized_id` from the peer chain let actual_peer_on_self_best_finalized_id = diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index 428ee33494ca4..f23357bfed709 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -20,10 +20,11 @@ pub use bp_runtime::HeaderId; pub use error::Error; pub use relay_loop::{relay_loop, relay_metrics}; pub use sp_runtime::traits::{UniqueSaturatedFrom, UniqueSaturatedInto}; +use std::fmt::Debug; use async_trait::async_trait; use backoff::{backoff::Backoff, ExponentialBackoff}; -use futures::future::FutureExt; +use futures::future::{BoxFuture, FutureExt}; use std::time::Duration; use thiserror::Error; @@ -134,12 +135,16 @@ pub enum TrackedTransactionStatus { #[async_trait] pub trait TransactionTracker: Send { /// Header id, used by the chain. - type HeaderId: Clone + Send; + type HeaderId: Clone + Debug + Send; /// Wait until transaction is either finalized or invalidated/lost. async fn wait(self) -> TrackedTransactionStatus; } +/// Future associated with `TransactionTracker`, monitoring the transaction status. +pub type TrackedTransactionFuture = + BoxFuture<'static, TrackedTransactionStatus<::HeaderId>>; + /// Stringified error that may be either connection-related or not. #[derive(Error, Debug)] pub enum StringifiedMaybeConnectionError { From 5993e63ebd412b1b7f938f75e580643c9dc56588 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 31 Aug 2023 08:50:19 +0300 Subject: [PATCH 1097/1210] Start the equivocation detection loop from the complex relayer (#2507) (#2512) * Impl SubstrateEquivocationDetectionPipeline for Millau * Impl SubstrateEquivocationDetectionPipeline for Rialto * Make BridgeHubSignedExtension more generic * Define generate_report_equivocation_call_builder!() macro * Impl SubstrateEquivocationDetectionPipeline for Rococo * Impl SubstrateEquivocationDetectionPipeline for Wococo * Impl SubstrateEquivocationDetectionPipeline for Kusama * Impl SubstrateEquivocationDetectionPipeline for Polkadot * Complex relayer simplification - remove `signer` and `transactions_mortality` and add `tx_params` - change the order of some fields * Add equivocation detection CLI traits * Complex relayer: start equivocation detectin loop * Update runtimes regeneration script * Equivocation loop: Fix infinite loop * Revert "Complex relayer: start equivocation detectin loop" This reverts commit b518ef85679d73654f9f0e2add38cd3839552057. * Add subcommand for starting the equivocation detection loop * Fixes * Initialize empty metrics for the equivocations detector loop --- bin/rialto-parachain/runtime/Cargo.toml | 1 + bin/rialto-parachain/runtime/src/lib.rs | 56 +- bin/runtime-common/src/integrity.rs | 13 - .../chain-bridge-hub-cumulus/src/lib.rs | 91 +- primitives/chain-kusama/src/lib.rs | 3 + primitives/chain-polkadot/src/lib.rs | 5 +- primitives/chain-rococo/src/lib.rs | 3 + primitives/chain-wococo/src/lib.rs | 3 + primitives/polkadot-core/src/lib.rs | 103 +- primitives/runtime/src/extensions.rs | 12 +- .../kusama_headers_to_bridge_hub_polkadot.rs | 25 +- .../polkadot_headers_to_bridge_hub_kusama.rs | 25 +- .../rialto_millau/millau_headers_to_rialto.rs | 17 +- .../rialto_millau/rialto_headers_to_millau.rs | 17 +- .../millau_headers_to_rialto_parachain.rs | 17 +- .../rococo_headers_to_bridge_hub_wococo.rs | 25 +- .../wococo_headers_to_bridge_hub_rococo.rs | 25 +- relays/bin-substrate/src/cli/bridge.rs | 29 +- .../src/cli/detect_equivocations.rs | 113 + relays/bin-substrate/src/cli/mod.rs | 9 +- .../src/cli/relay_headers_and_messages/mod.rs | 20 +- .../parachain_to_parachain.rs | 40 +- .../relay_to_parachain.rs | 24 +- .../relay_to_relay.rs | 20 +- relays/client-bridge-hub-kusama/src/lib.rs | 4 +- relays/client-bridge-hub-polkadot/Cargo.toml | 1 + relays/client-bridge-hub-polkadot/src/lib.rs | 4 +- relays/client-bridge-hub-rococo/src/lib.rs | 4 +- relays/client-bridge-hub-wococo/src/lib.rs | 4 +- relays/client-kusama/Cargo.toml | 12 +- relays/client-kusama/src/codegen_runtime.rs | 8338 ++++++++++++++++ relays/client-kusama/src/lib.rs | 72 +- relays/client-millau/src/lib.rs | 5 +- relays/client-polkadot/Cargo.toml | 12 +- relays/client-polkadot/src/codegen_runtime.rs | 8399 +++++++++++++++++ relays/client-polkadot/src/lib.rs | 72 +- relays/client-rialto-parachain/src/lib.rs | 3 +- relays/client-rialto/src/lib.rs | 5 +- relays/client-rococo/Cargo.toml | 12 +- relays/client-rococo/src/codegen_runtime.rs | 7441 +++++++++++++++ relays/client-rococo/src/lib.rs | 72 +- relays/client-wococo/Cargo.toml | 9 +- relays/client-wococo/src/lib.rs | 71 +- relays/equivocation/src/equivocation_loop.rs | 12 +- relays/equivocation/src/lib.rs | 2 + .../src/equivocation/mod.rs | 68 +- .../src/equivocation/source.rs | 10 +- .../src/equivocation/target.rs | 7 +- 48 files changed, 25091 insertions(+), 244 deletions(-) create mode 100644 relays/bin-substrate/src/cli/detect_equivocations.rs create mode 100644 relays/client-kusama/src/codegen_runtime.rs create mode 100644 relays/client-polkadot/src/codegen_runtime.rs create mode 100644 relays/client-rococo/src/codegen_runtime.rs diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 1b87205e9e9c4..f2893633e7fa5 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -19,6 +19,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } +bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } bp-runtime = { path = "../../../primitives/runtime", default-features = false } bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 9bfe241394418..00e14ed85ed72 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -858,12 +858,10 @@ mod tests { target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, LaneId, MessageKey, }; - use bridge_runtime_common::{ - integrity::check_additional_signed, messages_xcm_extension::XcmBlobMessageDispatchResult, - }; + use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; use codec::Encode; use pallet_bridge_messages::OutboundLanes; - use sp_runtime::generic::Era; + use sp_runtime::{generic::Era, traits::Zero}; use xcm_executor::XcmExecutor; fn new_test_ext() -> sp_io::TestExternalities { @@ -941,24 +939,36 @@ mod tests { #[test] fn ensure_signed_extension_definition_is_correct() { - let payload: SignedExtra = ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(Era::Immortal), - frame_system::CheckNonce::from(10), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(10), - BridgeRejectObsoleteHeadersAndMessages, - DummyBridgeRefundMillauMessages, - ); - let indirect_payload = bp_rialto_parachain::SignedExtension::new( - ((), (), (), (), Era::Immortal, 10.into(), (), 10.into(), (), ()), - None, - ); - assert_eq!(payload.encode(), indirect_payload.encode()); - - check_additional_signed::(); + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + + sp_io::TestExternalities::default().execute_with(|| { + frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages, + DummyBridgeRefundMillauMessages, + ); + let indirect_payload = bp_rialto_parachain::SignedExtension::from_params( + VERSION.spec_version, + VERSION.transaction_version, + bp_runtime::TransactionEra::Immortal, + System::block_hash(BlockNumber::zero()), + 10, + 10, + (((), ()), ((), ())), + ); + assert_eq!(payload.encode(), indirect_payload.encode()); + assert_eq!( + payload.additional_signed().unwrap().encode(), + indirect_payload.additional_signed().unwrap().encode() + ) + }); } } diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index a0af3b981f307..765f812c70e0f 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -27,7 +27,6 @@ use codec::Encode; use frame_support::{storage::generator::StorageValue, traits::Get, weights::Weight}; use frame_system::limits; use pallet_bridge_messages::WeightInfoExt as _; -use sp_runtime::traits::SignedExtension; /// Macro that ensures that the runtime configuration and chain primitives crate are sharing /// the same types (nonce, block number, hash, hasher, account id and header). @@ -347,15 +346,3 @@ pub fn check_message_lane_weights< ); } } - -/// Check that the `AdditionalSigned` type of a wrapped runtime is the same as the one of the -/// corresponding actual runtime. -/// -/// This method doesn't perform any `assert`. If the condition is not true it will generate a -/// compile-time error. -pub fn check_additional_signed() -where - SignedExt: SignedExtension, - IndirectSignedExt: SignedExtension, -{ -} diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 525b2e62ceab0..feaac9e882daf 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -23,10 +23,9 @@ pub use bp_polkadot_core::{ }; use bp_messages::*; +use bp_polkadot_core::SuffixedCommonSignedExtension; use bp_runtime::extensions::{ - BridgeRejectObsoleteHeadersAndMessages, ChargeTransactionPayment, CheckEra, CheckGenesis, - CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, CheckWeight, - GenericSignedExtension, RefundBridgedParachainMessagesSchema, + BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, }; use frame_support::{ dispatch::DispatchClass, @@ -133,88 +132,8 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// analysis (like the one above). pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; -/// Extra signed extension data that is used by all bridge hubs. -pub type SignedExtra = ( - CheckNonZeroSender, - CheckSpecVersion, - CheckTxVersion, - CheckGenesis, - CheckEra, - CheckNonce, - CheckWeight, - ChargeTransactionPayment, +/// Signed extension that is used by all bridge hubs. +pub type SignedExtension = SuffixedCommonSignedExtension<( BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, -); - -/// Signed extension that is used by all bridge hubs. -pub type SignedExtension = GenericSignedExtension; - -/// Helper trait to define some extra methods on bridge hubs signed extension (and -/// overcome Rust limitations). -pub trait BridgeHubSignedExtension { - /// Create signed extension from its components. - fn from_params( - spec_version: u32, - transaction_version: u32, - era: bp_runtime::TransactionEra, - genesis_hash: Hash, - nonce: Nonce, - tip: Balance, - ) -> Self; - - /// Return transaction nonce. - fn nonce(&self) -> Nonce; - - /// Return transaction tip. - fn tip(&self) -> Balance; -} - -impl BridgeHubSignedExtension for SignedExtension { - /// Create signed extension from its components. - fn from_params( - spec_version: u32, - transaction_version: u32, - era: bp_runtime::TransactionEra, - genesis_hash: Hash, - nonce: Nonce, - tip: Balance, - ) -> Self { - GenericSignedExtension::new( - ( - (), // non-zero sender - (), // spec version - (), // tx version - (), // genesis - era.frame_era(), // era - nonce.into(), // nonce (compact encoding) - (), // Check weight - tip.into(), // transaction payment / tip (compact encoding) - (), // bridge reject obsolete headers and msgs - (), // bridge reward to relayer for message passing - ), - Some(( - (), - spec_version, - transaction_version, - genesis_hash, - era.signed_payload(genesis_hash), - (), - (), - (), - (), - (), - )), - ) - } - - /// Return transaction nonce. - fn nonce(&self) -> Nonce { - self.payload.5 .0 - } - - /// Return transaction tip. - fn tip(&self) -> Balance { - self.payload.7 .0 - } -} +)>; diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index b758484aefeb4..3f001638bb40d 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -57,6 +57,9 @@ impl ChainWithGrandpa for Kusama { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } +// The SignedExtension used by Kusama. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; + /// Name of the parachains pallet in the Kusama runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index eb62c1729adfd..49c88cd357b20 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -21,7 +21,7 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_finality_runtime_apis, extensions::PrevalidateAttests, Chain}; use frame_support::weights::Weight; use sp_std::prelude::Vec; @@ -57,6 +57,9 @@ impl ChainWithGrandpa for Polkadot { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } +/// The SignedExtension used by Polkadot. +pub type SignedExtension = SuffixedCommonSignedExtension; + /// Name of the parachains pallet in the Polkadot runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 140069d756959..0ab0fa4ec4767 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -61,6 +61,9 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } +// The SignedExtension used by Rococo. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; + /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 8247b63238ce4..1a3e8ded629e8 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -60,6 +60,9 @@ impl ChainWithGrandpa for Wococo { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } +// The SignedExtension used by Wococo. +pub use bp_rococo::CommonSignedExtension as SignedExtension; + /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index ffd48d8a38922..945b56cdc62eb 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -17,7 +17,15 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::MessageNonce; -use bp_runtime::{Chain, EncodedOrDecodedCall, StorageMapKeyProvider}; +use bp_runtime::{ + self, + extensions::{ + ChargeTransactionPayment, CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, + CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, + SignedExtensionSchema, + }, + Chain, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, +}; use frame_support::{ dispatch::DispatchClass, parameter_types, @@ -272,6 +280,99 @@ impl AccountInfoStorageMapKeyProvider { } } +/// Extra signed extension data that is used by most chains. +pub type CommonSignedExtra = ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ChargeTransactionPayment, +); + +/// Extra signed extension data that starts with `CommonSignedExtra`. +pub type SuffixedCommonSignedExtension = + GenericSignedExtension<(CommonSignedExtra, Suffix)>; + +/// Helper trait to define some extra methods on `SuffixedCommonSignedExtension`. +pub trait SuffixedCommonSignedExtensionExt { + /// Create signed extension from its components. + fn from_params( + spec_version: u32, + transaction_version: u32, + era: TransactionEra, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + extra: (Suffix::Payload, Suffix::AdditionalSigned), + ) -> Self; + + /// Return transaction nonce. + fn nonce(&self) -> Nonce; + + /// Return transaction tip. + fn tip(&self) -> Balance; +} + +impl SuffixedCommonSignedExtensionExt for SuffixedCommonSignedExtension +where + Suffix: SignedExtensionSchema, +{ + fn from_params( + spec_version: u32, + transaction_version: u32, + era: TransactionEra, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + extra: (Suffix::Payload, Suffix::AdditionalSigned), + ) -> Self { + GenericSignedExtension::new( + ( + ( + (), // non-zero sender + (), // spec version + (), // tx version + (), // genesis + era.frame_era(), // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + tip.into(), // transaction payment / tip (compact encoding) + ), + extra.0, + ), + Some(( + ( + (), + spec_version, + transaction_version, + genesis_hash, + era.signed_payload(genesis_hash), + (), + (), + (), + ), + extra.1, + )), + ) + } + + fn nonce(&self) -> Nonce { + let common_payload = self.payload.0; + common_payload.5 .0 + } + + fn tip(&self) -> Balance { + let common_payload = self.payload.0; + common_payload.7 .0 + } +} + +/// Signed extension that is used by most chains. +pub type CommonSignedExtension = SuffixedCommonSignedExtension<()>; + #[cfg(test)] mod tests { use super::*; diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index 96ee9d1e6ec91..9fa8fb5222adb 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -35,7 +35,12 @@ pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTy type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo; } -// An implementation of `SignedExtensionSchema` using generic params. +impl SignedExtensionSchema for () { + type Payload = (); + type AdditionalSigned = (); +} + +/// An implementation of `SignedExtensionSchema` using generic params. #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] pub struct GenericSignedExtensionSchema(PhantomData<(P, S)>); @@ -72,6 +77,9 @@ pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; /// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. pub type ChargeTransactionPayment = GenericSignedExtensionSchema, ()>; +/// The `SignedExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. +pub type PrevalidateAttests = GenericSignedExtensionSchema<(), ()>; + /// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; @@ -99,7 +107,7 @@ pub struct GenericSignedExtension { // It may be set to `None` if extensions are decoded. We are never reconstructing transactions // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to // read fields of the `payload`. And when resigning transaction, we're reconstructing - // `SignedExtensions` from the scratch. + // `SignedExtensions` from scratch. additional_signed: Option, } diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs index 271aa5c6777fc..a5419a725e2e1 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -16,11 +16,14 @@ //! Kusama-to-BridgeHubPolkadot headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, @@ -32,11 +35,18 @@ pub struct KusamaFinalityToBridgeHubPolkadot; substrate_relay_helper::generate_submit_finality_proof_call_builder!( KusamaFinalityToBridgeHubPolkadot, - KusamaFinalityToBridgeHubPolkadotCallBuilder, + SubmitFinalityProofCallBuilder, relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaGrandpa, relay_bridge_hub_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof ); +substrate_relay_helper::generate_report_equivocation_call_builder!( + KusamaFinalityToBridgeHubPolkadot, + ReportEquivocationCallBuilder, + relay_kusama_client::RuntimeCall::Grandpa, + relay_kusama_client::GrandpaCall::report_equivocation +); + #[async_trait] impl SubstrateFinalityPipeline for KusamaFinalityToBridgeHubPolkadot { type SourceChain = relay_kusama_client::Kusama; @@ -47,7 +57,7 @@ impl SubstrateFinalityPipeline for KusamaFinalityToBridgeHubPolkadot { #[async_trait] impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { - type SubmitFinalityProofCallBuilder = KusamaFinalityToBridgeHubPolkadotCallBuilder; + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; async fn start_relay_guards( target_client: &Client, @@ -64,6 +74,11 @@ impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { } } +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for KusamaFinalityToBridgeHubPolkadot { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + /// `Kusama` to BridgeHub `Polkadot` bridge definition. pub struct KusamaToBridgeHubPolkadotCliBridge {} @@ -75,3 +90,7 @@ impl CliBridgeBase for KusamaToBridgeHubPolkadotCliBridge { impl RelayToRelayHeadersCliBridge for KusamaToBridgeHubPolkadotCliBridge { type Finality = KusamaFinalityToBridgeHubPolkadot; } + +impl RelayToRelayEquivocationDetectionCliBridge for KusamaToBridgeHubPolkadotCliBridge { + type Equivocation = KusamaFinalityToBridgeHubPolkadot; +} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs index 44d7ee94e3d21..5899b8c25f6e0 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -16,11 +16,14 @@ //! Polkadot-to-KusamaBridgeHub headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, @@ -32,11 +35,18 @@ pub struct PolkadotFinalityToBridgeHubKusama; substrate_relay_helper::generate_submit_finality_proof_call_builder!( PolkadotFinalityToBridgeHubKusama, - PolkadotFinalityToBridgeHubKusamaCallBuilder, + SubmitFinalityProofCallBuilder, relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotGrandpa, relay_bridge_hub_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof ); +substrate_relay_helper::generate_report_equivocation_call_builder!( + PolkadotFinalityToBridgeHubKusama, + ReportEquivocationCallBuilder, + relay_polkadot_client::RuntimeCall::Grandpa, + relay_polkadot_client::GrandpaCall::report_equivocation +); + #[async_trait] impl SubstrateFinalityPipeline for PolkadotFinalityToBridgeHubKusama { type SourceChain = relay_polkadot_client::Polkadot; @@ -47,7 +57,7 @@ impl SubstrateFinalityPipeline for PolkadotFinalityToBridgeHubKusama { #[async_trait] impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { - type SubmitFinalityProofCallBuilder = PolkadotFinalityToBridgeHubKusamaCallBuilder; + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; async fn start_relay_guards( target_client: &Client, @@ -64,6 +74,11 @@ impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { } } +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for PolkadotFinalityToBridgeHubKusama { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + /// `Polkadot` to BridgeHub `Kusama` bridge definition. pub struct PolkadotToBridgeHubKusamaCliBridge {} @@ -75,3 +90,7 @@ impl CliBridgeBase for PolkadotToBridgeHubKusamaCliBridge { impl RelayToRelayHeadersCliBridge for PolkadotToBridgeHubKusamaCliBridge { type Finality = PolkadotFinalityToBridgeHubKusama; } + +impl RelayToRelayEquivocationDetectionCliBridge for PolkadotToBridgeHubKusamaCliBridge { + type Equivocation = PolkadotFinalityToBridgeHubKusama; +} diff --git a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs index 2e2452eb31b8c..7fd5513a27295 100644 --- a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs @@ -16,8 +16,14 @@ //! Millau-to-Rialto headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; use substrate_relay_helper::{ + equivocation::{ + DirectReportGrandpaEquivocationCallBuilder, SubstrateEquivocationDetectionPipeline, + }, finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; @@ -41,6 +47,11 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { >; } +impl SubstrateEquivocationDetectionPipeline for MillauFinalityToRialto { + type ReportEquivocationCallBuilder = + DirectReportGrandpaEquivocationCallBuilder; +} + /// `Millau` to `Rialto` bridge definition. pub struct MillauToRialtoCliBridge {} @@ -53,6 +64,10 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { type Finality = MillauFinalityToRialto; } +impl RelayToRelayEquivocationDetectionCliBridge for MillauToRialtoCliBridge { + type Equivocation = MillauFinalityToRialto; +} + impl MessagesCliBridge for MillauToRialtoCliBridge { type MessagesLane = crate::bridges::rialto_millau::millau_messages_to_rialto::MillauMessagesToRialto; diff --git a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs index c855aa66c2983..d9b98d77784e7 100644 --- a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs +++ b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs @@ -16,8 +16,14 @@ //! Rialto-to-Millau headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; use substrate_relay_helper::{ + equivocation::{ + DirectReportGrandpaEquivocationCallBuilder, SubstrateEquivocationDetectionPipeline, + }, finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; @@ -41,6 +47,11 @@ impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { >; } +impl SubstrateEquivocationDetectionPipeline for RialtoFinalityToMillau { + type ReportEquivocationCallBuilder = + DirectReportGrandpaEquivocationCallBuilder; +} + /// `Rialto` to `Millau` bridge definition. pub struct RialtoToMillauCliBridge {} @@ -53,6 +64,10 @@ impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { type Finality = RialtoFinalityToMillau; } +impl RelayToRelayEquivocationDetectionCliBridge for RialtoToMillauCliBridge { + type Equivocation = RialtoFinalityToMillau; +} + impl MessagesCliBridge for RialtoToMillauCliBridge { type MessagesLane = crate::bridges::rialto_millau::rialto_messages_to_millau::RialtoMessagesToMillau; diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs index fd7559843022d..051057e217665 100644 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs +++ b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs @@ -34,8 +34,14 @@ //! Millau-to-RialtoParachain headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; use substrate_relay_helper::{ + equivocation::{ + DirectReportGrandpaEquivocationCallBuilder, SubstrateEquivocationDetectionPipeline, + }, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; @@ -62,6 +68,11 @@ impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { type SubmitFinalityProofCallBuilder = MillauFinalityToRialtoParachainCallBuilder; } +impl SubstrateEquivocationDetectionPipeline for MillauFinalityToRialtoParachain { + type ReportEquivocationCallBuilder = + DirectReportGrandpaEquivocationCallBuilder; +} + /// `Millau` to `RialtoParachain` bridge definition. pub struct MillauToRialtoParachainCliBridge {} @@ -74,6 +85,10 @@ impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { type Finality = MillauFinalityToRialtoParachain; } +impl RelayToRelayEquivocationDetectionCliBridge for MillauToRialtoParachainCliBridge { + type Equivocation = MillauFinalityToRialtoParachain; +} + impl MessagesCliBridge for MillauToRialtoParachainCliBridge { type MessagesLane = crate::bridges::rialto_parachain_millau::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs index 906340633ab4c..d89ba35849c69 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs @@ -16,11 +16,14 @@ //! Rococo-to-Wococo bridge hubs headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, @@ -32,11 +35,18 @@ pub struct RococoFinalityToBridgeHubWococo; substrate_relay_helper::generate_submit_finality_proof_call_builder!( RococoFinalityToBridgeHubWococo, - RococoFinalityToBridgeHubWococoCallBuilder, + SubmitFinalityProofCallBuilder, relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoGrandpa, relay_bridge_hub_wococo_client::BridgeGrandpaCall::submit_finality_proof ); +substrate_relay_helper::generate_report_equivocation_call_builder!( + RococoFinalityToBridgeHubWococo, + ReportEquivocationCallBuilder, + relay_rococo_client::RuntimeCall::Grandpa, + relay_rococo_client::GrandpaCall::report_equivocation +); + #[async_trait] impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWococo { type SourceChain = relay_rococo_client::Rococo; @@ -47,7 +57,7 @@ impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWococo { #[async_trait] impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { - type SubmitFinalityProofCallBuilder = RococoFinalityToBridgeHubWococoCallBuilder; + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; async fn start_relay_guards( target_client: &Client, @@ -64,6 +74,11 @@ impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { } } +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for RococoFinalityToBridgeHubWococo { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + /// `Rococo` to BridgeHub `Wococo` bridge definition. pub struct RococoToBridgeHubWococoCliBridge {} @@ -75,3 +90,7 @@ impl CliBridgeBase for RococoToBridgeHubWococoCliBridge { impl RelayToRelayHeadersCliBridge for RococoToBridgeHubWococoCliBridge { type Finality = RococoFinalityToBridgeHubWococo; } + +impl RelayToRelayEquivocationDetectionCliBridge for RococoToBridgeHubWococoCliBridge { + type Equivocation = RococoFinalityToBridgeHubWococo; +} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs index 418225d9bacab..44d91f06e3e78 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs @@ -16,11 +16,14 @@ //! Wococo-to-Rococo bridge hubs headers sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; use async_trait::async_trait; use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, TransactionParams, @@ -32,11 +35,18 @@ pub struct WococoFinalityToBridgeHubRococo; substrate_relay_helper::generate_submit_finality_proof_call_builder!( WococoFinalityToBridgeHubRococo, - WococoFinalityToBridgeHubRococoCallBuilder, + SubmitFinalityProofCallBuilder, relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoGrandpa, relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof ); +substrate_relay_helper::generate_report_equivocation_call_builder!( + WococoFinalityToBridgeHubRococo, + ReportEquivocationCallBuilder, + relay_wococo_client::RuntimeCall::Grandpa, + relay_wococo_client::GrandpaCall::report_equivocation +); + #[async_trait] impl SubstrateFinalityPipeline for WococoFinalityToBridgeHubRococo { type SourceChain = relay_wococo_client::Wococo; @@ -47,7 +57,7 @@ impl SubstrateFinalityPipeline for WococoFinalityToBridgeHubRococo { #[async_trait] impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { - type SubmitFinalityProofCallBuilder = WococoFinalityToBridgeHubRococoCallBuilder; + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; async fn start_relay_guards( target_client: &Client, @@ -64,6 +74,11 @@ impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { } } +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for WococoFinalityToBridgeHubRococo { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + /// `Wococo` to BridgeHub `Rococo` bridge definition. pub struct WococoToBridgeHubRococoCliBridge {} @@ -75,3 +90,7 @@ impl CliBridgeBase for WococoToBridgeHubRococoCliBridge { impl RelayToRelayHeadersCliBridge for WococoToBridgeHubRococoCliBridge { type Finality = WococoFinalityToBridgeHubRococo; } + +impl RelayToRelayEquivocationDetectionCliBridge for WococoToBridgeHubRococoCliBridge { + type Equivocation = WococoFinalityToBridgeHubRococo; +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 62c71183a4801..6cbbdd0ebe50c 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -19,8 +19,8 @@ use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumbe use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, messages_lane::SubstrateMessageLane, - parachains::SubstrateParachainsPipeline, + equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, + messages_lane::SubstrateMessageLane, parachains::SubstrateParachainsPipeline, }; #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] @@ -56,6 +56,31 @@ pub trait RelayToRelayHeadersCliBridge: CliBridgeBase { >; } +/// Convenience trait that adds bounds to `CliBridgeBase`. +pub trait RelayToRelayEquivocationDetectionCliBridgeBase: CliBridgeBase { + type BoundedSource: ChainWithTransactions; +} + +impl RelayToRelayEquivocationDetectionCliBridgeBase for T +where + T: CliBridgeBase, + T::Source: ChainWithTransactions, +{ + type BoundedSource = T::Source; +} + +/// Bridge representation that can be used from the CLI for detecting equivocations +/// in the headers synchronized from a relay chain to a relay chain. +pub trait RelayToRelayEquivocationDetectionCliBridge: + RelayToRelayEquivocationDetectionCliBridgeBase +{ + /// Equivocation detection pipeline. + type Equivocation: SubstrateEquivocationDetectionPipeline< + SourceChain = Self::Source, + TargetChain = Self::Target, + >; +} + /// Bridge representation that can be used from the CLI for relaying headers /// from a parachain to a relay chain. pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs new file mode 100644 index 0000000000000..142a3f8e69a88 --- /dev/null +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -0,0 +1,113 @@ +// Copyright 2019-2023 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 . + +use crate::{ + bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, + rialto_millau::{ + millau_headers_to_rialto::MillauToRialtoCliBridge, + rialto_headers_to_millau::RialtoToMillauCliBridge, + }, + rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rococo_wococo::{ + rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, + wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, + }, + }, + cli::{bridge::*, chain_schema::*, PrometheusParams}, +}; + +use async_trait::async_trait; +use relay_substrate_client::ChainWithTransactions; +use structopt::StructOpt; +use strum::{EnumString, EnumVariantNames, VariantNames}; +use substrate_relay_helper::equivocation; + +/// Start equivocation detection loop. +#[derive(StructOpt)] +pub struct DetectEquivocations { + #[structopt(possible_values = DetectEquivocationsBridge::VARIANTS, case_insensitive = true)] + bridge: DetectEquivocationsBridge, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +#[derive(Debug, EnumString, EnumVariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Equivocations detection bridge. +pub enum DetectEquivocationsBridge { + MillauToRialto, + RialtoToMillau, + MillauToRialtoParachain, + RococoToBridgeHubWococo, + WococoToBridgeHubRococo, + KusamaToBridgeHubPolkadot, + PolkadotToBridgeHubKusama, +} + +#[async_trait] +trait EquivocationsDetector: RelayToRelayEquivocationDetectionCliBridge +where + Self::Source: ChainWithTransactions, +{ + async fn start(data: DetectEquivocations) -> anyhow::Result<()> { + equivocation::run::( + data.source.into_client::().await?, + data.target.into_client::().await?, + data.source_sign.transaction_params::()?, + data.prometheus_params.into_metrics_params()?, + ) + .await + } +} + +impl EquivocationsDetector for MillauToRialtoCliBridge {} +impl EquivocationsDetector for RialtoToMillauCliBridge {} +impl EquivocationsDetector for MillauToRialtoParachainCliBridge {} +impl EquivocationsDetector for RococoToBridgeHubWococoCliBridge {} +impl EquivocationsDetector for WococoToBridgeHubRococoCliBridge {} +impl EquivocationsDetector for KusamaToBridgeHubPolkadotCliBridge {} +impl EquivocationsDetector for PolkadotToBridgeHubKusamaCliBridge {} + +impl DetectEquivocations { + /// Run the command. + pub async fn run(self) -> anyhow::Result<()> { + match self.bridge { + DetectEquivocationsBridge::MillauToRialto => MillauToRialtoCliBridge::start(self), + DetectEquivocationsBridge::RialtoToMillau => RialtoToMillauCliBridge::start(self), + DetectEquivocationsBridge::MillauToRialtoParachain => + MillauToRialtoParachainCliBridge::start(self), + DetectEquivocationsBridge::RococoToBridgeHubWococo => + RococoToBridgeHubWococoCliBridge::start(self), + DetectEquivocationsBridge::WococoToBridgeHubRococo => + WococoToBridgeHubRococoCliBridge::start(self), + DetectEquivocationsBridge::KusamaToBridgeHubPolkadot => + KusamaToBridgeHubPolkadotCliBridge::start(self), + DetectEquivocationsBridge::PolkadotToBridgeHubKusama => + PolkadotToBridgeHubKusamaCliBridge::start(self), + } + .await + } +} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index a5b90744067a0..890fd9efb34ed 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -35,6 +35,7 @@ pub(crate) mod encode_message; pub(crate) mod send_message; mod chain_schema; +mod detect_equivocations; mod init_bridge; mod register_parachain; mod relay_headers; @@ -86,8 +87,13 @@ pub enum Command { ResubmitTransactions(resubmit_transactions::ResubmitTransactions), /// Register parachain. RegisterParachain(register_parachain::RegisterParachain), - /// + /// Relay parachain heads. RelayParachains(relay_parachains::RelayParachains), + /// Detect and report equivocations. + /// + /// Parses the source chain headers that were synchronized with the target chain looking for + /// equivocations. If any equivocation is found, it is reported to the source chain. + DetectEquivocations(detect_equivocations::DetectEquivocations), } impl Command { @@ -119,6 +125,7 @@ impl Command { Self::ResubmitTransactions(arg) => arg.run().await?, Self::RegisterParachain(arg) => arg.run().await?, Self::RelayParachains(arg) => arg.run().await?, + Self::DetectEquivocations(arg) => arg.run().await?, } Ok(()) } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 21b352aff6ef6..cd2d39cdec28b 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -131,10 +131,8 @@ impl { /// Chain client. pub client: Client, - /// Transactions signer. - pub sign: AccountKeyPairOf, - /// Transactions mortality. - pub transactions_mortality: Option, + /// Params used for sending transactions to the chain. + pub tx_params: TransactionParams>, /// Accounts, which balances are exposed as metrics by the relay process. pub accounts: Vec>>, } @@ -181,15 +179,9 @@ where ) -> MessagesRelayParams { MessagesRelayParams { source_client: self.source.client.clone(), - source_transaction_params: TransactionParams { - signer: self.source.sign.clone(), - mortality: self.source.transactions_mortality, - }, + source_transaction_params: self.source.tx_params.clone(), target_client: self.target.client.clone(), - target_transaction_params: TransactionParams { - signer: self.target.sign.clone(), - mortality: self.target.transactions_mortality, - }, + target_transaction_params: self.target.tx_params.clone(), source_to_target_headers_relay: Some(source_to_target_headers_relay), target_to_source_headers_relay: Some(target_to_source_headers_relay), lane_id, @@ -328,11 +320,11 @@ where { let common = self.mut_base().mut_common(); common.left.accounts.push(TaggedAccount::Messages { - id: common.left.sign.public().into(), + id: common.left.tx_params.signer.public().into(), bridged_chain: Self::Right::NAME.to_string(), }); common.right.accounts.push(TaggedAccount::Messages { - id: common.right.sign.public().into(), + id: common.right.tx_params.signer.public().into(), bridged_chain: Self::Left::NAME.to_string(), }); } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index b4c858e566b2e..24d6f00861d00 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -58,13 +58,13 @@ pub struct ParachainToParachainBridge< /// Override for right_relay->left headers signer. pub right_headers_to_left_transaction_params: TransactionParams::Target>>, - /// Override for left_relay->right headers signer. - pub left_headers_to_right_transaction_params: - TransactionParams::Target>>, - /// Override for right->left parachains signer. pub right_parachains_to_left_transaction_params: TransactionParams::Target>>, + + /// Override for left_relay->right headers signer. + pub left_headers_to_right_transaction_params: + TransactionParams::Target>>, /// Override for left->right parachains signer. pub left_parachains_to_right_transaction_params: TransactionParams::Target>>, @@ -83,35 +83,33 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { #[structopt(flatten)] left: [<$left_parachain ConnectionParams>], - #[structopt(flatten)] - left_relay: [<$left_chain ConnectionParams>], - // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_parachain SigningParams>], - + // override for right_relay->left-parachain headers signer #[structopt(flatten)] - right: [<$right_parachain ConnectionParams>], + right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_parachain SigningParams>], + // override for right->left parachains signer #[structopt(flatten)] - right_relay: [<$right_chain ConnectionParams>], + right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_parachain SigningParams>], - // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] - right_sign: [<$right_parachain SigningParams>], + left_relay: [<$left_chain ConnectionParams>], - // override for right_relay->left-parachain headers signer #[structopt(flatten)] - right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_parachain SigningParams>], + right: [<$right_parachain ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the right chain + #[structopt(flatten)] + right_sign: [<$right_parachain SigningParams>], // override for left_relay->right-parachain headers signer #[structopt(flatten)] left_relay_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], - - // override for right->left parachains signer - #[structopt(flatten)] - right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_parachain SigningParams>], // override for left->right parachains signer #[structopt(flatten)] left_parachains_to_right_sign_override: [<$left_chain ParachainsTo $right_parachain SigningParams>], + + #[structopt(flatten)] + right_relay: [<$right_chain ConnectionParams>], } impl [<$left_parachain $right_parachain HeadersAndMessages>] { @@ -134,14 +132,12 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { self.shared, BridgeEndCommonParams { client: self.left.into_client::().await?, - sign: self.left_sign.to_keypair::()?, - transactions_mortality: self.left_sign.transactions_mortality()?, + tx_params: self.left_sign.transaction_params::()?, accounts: vec![], }, BridgeEndCommonParams { client: self.right.into_client::().await?, - sign: self.right_sign.to_keypair::()?, - transactions_mortality: self.right_sign.transactions_mortality()?, + tx_params: self.right_sign.transaction_params::()?, accounts: vec![], }, )?, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index d632cce08e9c7..ef47e44dc1837 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -61,6 +61,7 @@ pub struct RelayToParachainBridge< /// Override for right->left parachains signer. pub right_parachains_to_left_transaction_params: TransactionParams::Target>>, + /// Override for left->right headers signer. pub left_headers_to_right_transaction_params: TransactionParams::Target>>, @@ -79,30 +80,27 @@ macro_rules! declare_relay_to_parachain_bridge_schema { #[structopt(flatten)] left: [<$left_chain ConnectionParams>], - // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_chain SigningParams>], - + // override for right_relay->left headers signer #[structopt(flatten)] - right: [<$right_parachain ConnectionParams>], + right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], + // override for right->left parachains signer #[structopt(flatten)] - right_relay: [<$right_chain ConnectionParams>], + right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>], + #[structopt(flatten)] + right: [<$right_parachain ConnectionParams>], // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$right_parachain SigningParams>], - - // override for right_relay->left headers signer - #[structopt(flatten)] - right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], // override for left->right headers signer #[structopt(flatten)] left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], - // override for right->left parachains signer #[structopt(flatten)] - right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>], + right_relay: [<$right_chain ConnectionParams>], } impl [<$left_chain $right_parachain HeadersAndMessages>] { @@ -122,14 +120,12 @@ macro_rules! declare_relay_to_parachain_bridge_schema { self.shared, BridgeEndCommonParams { client: self.left.into_client::().await?, - sign: self.left_sign.to_keypair::()?, - transactions_mortality: self.left_sign.transactions_mortality()?, + tx_params: self.left_sign.transaction_params::()?, accounts: vec![], }, BridgeEndCommonParams { client: self.right.into_client::().await?, - sign: self.right_sign.to_keypair::()?, - transactions_mortality: self.right_sign.transactions_mortality()?, + tx_params: self.right_sign.transaction_params::()?, accounts: vec![], }, )?, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index fce80492fc071..a313628933ba6 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -56,22 +56,24 @@ macro_rules! declare_relay_to_relay_bridge_schema { pub struct [<$left_chain $right_chain HeadersAndMessages>] { #[structopt(flatten)] shared: HeadersAndMessagesSharedParams, - // default signer, which is always used to sign messages relay transactions on the left chain + #[structopt(flatten)] left: [<$left_chain ConnectionParams>], + // default signer, which is always used to sign messages relay transactions on the left chain + #[structopt(flatten)] + left_sign: [<$left_chain SigningParams>], // override for right->left headers signer #[structopt(flatten)] right_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], - #[structopt(flatten)] - left_sign: [<$left_chain SigningParams>], - // default signer, which is always used to sign messages relay transactions on the right chain + #[structopt(flatten)] right: [<$right_chain ConnectionParams>], + #[structopt(flatten)] + // default signer, which is always used to sign messages relay transactions on the right chain + right_sign: [<$right_chain SigningParams>], // override for left->right headers signer #[structopt(flatten)] left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_chain SigningParams>], - #[structopt(flatten)] - right_sign: [<$right_chain SigningParams>], } impl [<$left_chain $right_chain HeadersAndMessages>] { @@ -88,14 +90,12 @@ macro_rules! declare_relay_to_relay_bridge_schema { self.shared, BridgeEndCommonParams { client: self.left.into_client::().await?, - sign: self.left_sign.to_keypair::()?, - transactions_mortality: self.left_sign.transactions_mortality()?, + tx_params: self.left_sign.transaction_params::()?, accounts: vec![], }, BridgeEndCommonParams { client: self.right.into_client::().await?, - sign: self.right_sign.to_keypair::()?, - transactions_mortality: self.right_sign.transactions_mortality()?, + tx_params: self.right_sign.transaction_params::()?, accounts: vec![], }, )?, diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index 6549a32ca7956..f54f32f9bfeb2 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -16,8 +16,9 @@ //! Types used to connect to the BridgeHub-Kusama-Substrate parachain. -use bp_bridge_hub_kusama::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_kusama::AVERAGE_BLOCK_INTERVAL; use bp_messages::MessageNonce; +use bp_polkadot::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ @@ -79,6 +80,7 @@ impl ChainWithTransactions for BridgeHubKusama { param.genesis_hash, unsigned.nonce, unsigned.tip, + (((), ()), ((), ())), ), )?; diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index dd0b083135d33..a0214d53d82f1 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -17,6 +17,7 @@ bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } +bp-polkadot-core= { path = "../../primitives/polkadot-core" } bp-kusama = { path = "../../primitives/chain-kusama" } bp-runtime = { path = "../../primitives/runtime" } diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index 6428b055dd5a2..299bc4d736aec 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -16,8 +16,9 @@ //! Types used to connect to the BridgeHub-Polkadot-Substrate parachain. -use bp_bridge_hub_polkadot::{BridgeHubSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_polkadot::AVERAGE_BLOCK_INTERVAL; use bp_messages::MessageNonce; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ @@ -79,6 +80,7 @@ impl ChainWithTransactions for BridgeHubPolkadot { param.genesis_hash, unsigned.nonce, unsigned.tip, + (((), ()), ((), ())), ), )?; diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 2a0595953956a..7e3a441f561e1 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -18,8 +18,9 @@ pub mod codegen_runtime; -use bp_bridge_hub_rococo::{BridgeHubSignedExtension, SignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_rococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ @@ -95,6 +96,7 @@ impl ChainWithTransactions for BridgeHubRococo { param.genesis_hash, unsigned.nonce, unsigned.tip, + (((), ()), ((), ())), ), )?; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 0e2b9839301ba..b144093d3669c 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,8 +16,9 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_bridge_hub_wococo::{BridgeHubSignedExtension, SignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_wococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_messages::MessageNonce; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ @@ -84,6 +85,7 @@ impl ChainWithTransactions for BridgeHubWococo { param.genesis_hash, unsigned.nonce, unsigned.tip, + (((), ()), ((), ())), ), )?; diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 767aefa5f2789..d1b5c706f4d11 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -6,15 +6,23 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +subxt = { version = "0.31.0", default-features = false, features = ["native"] } # Bridge dependencies bp-kusama = { path = "../../primitives/chain-kusama" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + # Substrate Dependencies +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-kusama/src/codegen_runtime.rs b/relays/client-kusama/src/codegen_runtime.rs new file mode 100644 index 0000000000000..3c37d61f4cf19 --- /dev/null +++ b/relays/client-kusama/src/codegen_runtime.rs @@ -0,0 +1,8338 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://kusama-rpc.polkadot.io:443 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_btree_map { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedBTreeMap<_0, _1>(pub ::subxt::utils::KeyedVec<_0, _1>); + } + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Equivocation<_0, _1, _2> { + pub round_number: ::core::primitive::u64, + pub identity: _0, + pub first: (_1, _2), + pub second: (_1, _2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Prevote<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PostDispatchInfo { + pub actual_weight: ::core::option::Option<::sp_weights::Weight>, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProcessMessageError { + #[codec(index = 0)] + BadFormat, + #[codec(index = 1)] + Corrupt, + #[codec(index = 2)] + Unsupported, + #[codec(index = 3)] + Overweight(::sp_weights::Weight), + #[codec(index = 4)] + Yield, + } + } + pub mod misc { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WrapperOpaque<_0>( + #[codec(compact)] pub ::core::primitive::u32, + pub _0, + ); + } + pub mod preimages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Bounded<_0> { + #[codec(index = 0)] + Legacy { + hash: ::subxt::utils::H256, + }, + #[codec(index = 1)] + Inline( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Lookup { + hash: ::subxt::utils::H256, + len: ::core::primitive::u32, + }, + __Ignore(::core::marker::PhantomData<_0>), + } + } + pub mod schedule { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchTime<_0> { + #[codec(index = 0)] + At(_0), + #[codec(index = 1)] + After(_0), + } + } + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletId(pub [::core::primitive::u8; 8usize]); + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod kusama_runtime { + use super::runtime_types; + pub mod governance { + use super::runtime_types; + pub mod origins { + use super::runtime_types; + pub mod pallet_custom_origins { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Origin { + #[codec(index = 0)] + StakingAdmin, + #[codec(index = 1)] + Treasurer, + #[codec(index = 2)] + FellowshipAdmin, + #[codec(index = 3)] + GeneralAdmin, + #[codec(index = 4)] + AuctionAdmin, + #[codec(index = 5)] + LeaseAdmin, + #[codec(index = 6)] + ReferendumCanceller, + #[codec(index = 7)] + ReferendumKiller, + #[codec(index = 8)] + SmallTipper, + #[codec(index = 9)] + BigTipper, + #[codec(index = 10)] + SmallSpender, + #[codec(index = 11)] + MediumSpender, + #[codec(index = 12)] + BigSpender, + #[codec(index = 13)] + WhitelistedCaller, + #[codec(index = 14)] + FellowshipInitiates, + #[codec(index = 15)] + Fellows, + #[codec(index = 16)] + FellowshipExperts, + #[codec(index = 17)] + FellowshipMasters, + #[codec(index = 18)] + Fellowship1Dan, + #[codec(index = 19)] + Fellowship2Dan, + #[codec(index = 20)] + Fellowship3Dan, + #[codec(index = 21)] + Fellowship4Dan, + #[codec(index = 22)] + Fellowship5Dan, + #[codec(index = 23)] + Fellowship6Dan, + #[codec(index = 24)] + Fellowship7Dan, + #[codec(index = 25)] + Fellowship8Dan, + #[codec(index = 26)] + Fellowship9Dan, + } + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct NposCompactSolution24 { + pub votes1: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes2: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + ( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ), + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes3: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 2usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes4: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 3usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes5: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 4usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes6: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 5usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes7: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 6usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes8: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 7usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes9: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 8usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes10: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 9usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes11: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 10usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes12: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 11usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes13: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 12usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes14: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 13usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes15: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 14usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes16: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 15usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes17: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 16usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes18: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 17usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes19: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 18usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes20: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 19usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes21: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 20usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes22: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 21usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes23: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 22usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes24: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 23usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + # [codec (index = 0)] system (runtime_types :: frame_support :: dispatch :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 43)] Origins (runtime_types :: kusama_runtime :: governance :: origins :: pallet_custom_origins :: Origin ,) , # [codec (index = 50)] ParachainsOrigin (runtime_types :: polkadot_runtime_parachains :: origin :: pallet :: Origin ,) , # [codec (index = 99)] XcmPallet (runtime_types :: pallet_xcm :: pallet :: Origin ,) , # [codec (index = 4)] Void (runtime_types :: sp_core :: Void ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProxyType { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + NonTransfer, + #[codec(index = 2)] + Governance, + #[codec(index = 3)] + Staking, + #[codec(index = 4)] + IdentityJudgement, + #[codec(index = 5)] + CancelProxy, + #[codec(index = 6)] + Auction, + #[codec(index = 7)] + Society, + #[codec(index = 8)] + NominationPools, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + Babe(runtime_types::pallet_babe::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 3)] + Indices(runtime_types::pallet_indices::pallet::Call), + #[codec(index = 4)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 6)] + Staking(runtime_types::pallet_staking::pallet::pallet::Call), + #[codec(index = 8)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 10)] + Grandpa(runtime_types::pallet_grandpa::pallet::Call), + #[codec(index = 11)] + ImOnline(runtime_types::pallet_im_online::pallet::Call), + #[codec(index = 18)] + Treasury(runtime_types::pallet_treasury::pallet::Call), + #[codec(index = 20)] + ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Call), + #[codec(index = 21)] + Referenda(runtime_types::pallet_referenda::pallet::Call), + #[codec(index = 22)] + FellowshipCollective(runtime_types::pallet_ranked_collective::pallet::Call), + #[codec(index = 23)] + FellowshipReferenda(runtime_types::pallet_referenda::pallet::Call), + #[codec(index = 44)] + Whitelist(runtime_types::pallet_whitelist::pallet::Call), + #[codec(index = 19)] + Claims(runtime_types::polkadot_runtime_common::claims::pallet::Call), + #[codec(index = 24)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 25)] + Identity(runtime_types::pallet_identity::pallet::Call), + #[codec(index = 26)] + Society(runtime_types::pallet_society::pallet::Call), + #[codec(index = 27)] + Recovery(runtime_types::pallet_recovery::pallet::Call), + #[codec(index = 28)] + Vesting(runtime_types::pallet_vesting::pallet::Call), + #[codec(index = 29)] + Scheduler(runtime_types::pallet_scheduler::pallet::Call), + #[codec(index = 30)] + Proxy(runtime_types::pallet_proxy::pallet::Call), + #[codec(index = 31)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 32)] + Preimage(runtime_types::pallet_preimage::pallet::Call), + #[codec(index = 35)] + Bounties(runtime_types::pallet_bounties::pallet::Call), + #[codec(index = 40)] + ChildBounties(runtime_types::pallet_child_bounties::pallet::Call), + #[codec(index = 37)] + ElectionProviderMultiPhase( + runtime_types::pallet_election_provider_multi_phase::pallet::Call, + ), + #[codec(index = 38)] + Nis(runtime_types::pallet_nis::pallet::Call), + #[codec(index = 45)] + NisCounterpartBalances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 39)] + VoterList(runtime_types::pallet_bags_list::pallet::Call), + #[codec(index = 41)] + NominationPools(runtime_types::pallet_nomination_pools::pallet::Call), + #[codec(index = 42)] + FastUnstake(runtime_types::pallet_fast_unstake::pallet::Call), + #[codec(index = 51)] + Configuration( + runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, + ), + #[codec(index = 52)] + ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), + #[codec(index = 53)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), + #[codec(index = 54)] + ParaInherent( + runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, + ), + #[codec(index = 56)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), + #[codec(index = 57)] + Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), + #[codec(index = 60)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), + #[codec(index = 62)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), + #[codec(index = 63)] + ParasSlashing( + runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, + ), + #[codec(index = 70)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), + #[codec(index = 71)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), + #[codec(index = 72)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), + #[codec(index = 73)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 100)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 3)] + Indices(runtime_types::pallet_indices::pallet::Event), + #[codec(index = 4)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 33)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 6)] + Staking(runtime_types::pallet_staking::pallet::pallet::Event), + #[codec(index = 7)] + Offences(runtime_types::pallet_offences::pallet::Event), + #[codec(index = 8)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 10)] + Grandpa(runtime_types::pallet_grandpa::pallet::Event), + #[codec(index = 11)] + ImOnline(runtime_types::pallet_im_online::pallet::Event), + #[codec(index = 18)] + Treasury(runtime_types::pallet_treasury::pallet::Event), + #[codec(index = 20)] + ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Event), + #[codec(index = 21)] + Referenda(runtime_types::pallet_referenda::pallet::Event), + #[codec(index = 22)] + FellowshipCollective(runtime_types::pallet_ranked_collective::pallet::Event), + #[codec(index = 23)] + FellowshipReferenda(runtime_types::pallet_referenda::pallet::Event), + #[codec(index = 44)] + Whitelist(runtime_types::pallet_whitelist::pallet::Event), + #[codec(index = 19)] + Claims(runtime_types::polkadot_runtime_common::claims::pallet::Event), + #[codec(index = 24)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 25)] + Identity(runtime_types::pallet_identity::pallet::Event), + #[codec(index = 26)] + Society(runtime_types::pallet_society::pallet::Event), + #[codec(index = 27)] + Recovery(runtime_types::pallet_recovery::pallet::Event), + #[codec(index = 28)] + Vesting(runtime_types::pallet_vesting::pallet::Event), + #[codec(index = 29)] + Scheduler(runtime_types::pallet_scheduler::pallet::Event), + #[codec(index = 30)] + Proxy(runtime_types::pallet_proxy::pallet::Event), + #[codec(index = 31)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 32)] + Preimage(runtime_types::pallet_preimage::pallet::Event), + #[codec(index = 35)] + Bounties(runtime_types::pallet_bounties::pallet::Event), + #[codec(index = 40)] + ChildBounties(runtime_types::pallet_child_bounties::pallet::Event), + #[codec(index = 37)] + ElectionProviderMultiPhase( + runtime_types::pallet_election_provider_multi_phase::pallet::Event, + ), + #[codec(index = 38)] + Nis(runtime_types::pallet_nis::pallet::Event), + #[codec(index = 45)] + NisCounterpartBalances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 39)] + VoterList(runtime_types::pallet_bags_list::pallet::Event), + #[codec(index = 41)] + NominationPools(runtime_types::pallet_nomination_pools::pallet::Event), + #[codec(index = 42)] + FastUnstake(runtime_types::pallet_fast_unstake::pallet::Event), + #[codec(index = 53)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), + #[codec(index = 56)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), + #[codec(index = 60)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), + #[codec(index = 62)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), + #[codec(index = 70)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), + #[codec(index = 71)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), + #[codec(index = 72)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), + #[codec(index = 73)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 100)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeHoldReason { + #[codec(index = 38)] + Nis(runtime_types::pallet_nis::pallet::HoldReason), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, + pub babe: runtime_types::sp_consensus_babe::app::Public, + pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, + pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, + pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, + } + } + pub mod pallet_babe { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + plan_config_change { + config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEquivocationProof, + #[codec(index = 1)] + InvalidKeyOwnershipProof, + #[codec(index = 2)] + DuplicateOffenceReport, + #[codec(index = 3)] + InvalidConfiguration, + } + } + } + pub mod pallet_bags_list { + use super::runtime_types; + pub mod list { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bag { + pub head: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub tail: ::core::option::Option<::sp_core::crypto::AccountId32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ListError { + #[codec(index = 0)] + Duplicate, + #[codec(index = 1)] + NotHeavier, + #[codec(index = 2)] + NotInSameBag, + #[codec(index = 3)] + NodeNotFound, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Node { + pub id: ::sp_core::crypto::AccountId32, + pub prev: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub next: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub bag_upper: ::core::primitive::u64, + pub score: ::core::primitive::u64, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + rebag { + dislocated: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + put_in_front_of { + lighter: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + List(runtime_types::pallet_bags_list::list::ListError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Rebagged { + who: ::sp_core::crypto::AccountId32, + from: ::core::primitive::u64, + to: ::core::primitive::u64, + }, + #[codec(index = 1)] + ScoreUpdated { + who: ::sp_core::crypto::AccountId32, + new_score: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + set_balance_deprecated { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + #[codec(compact)] + old_reserved: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 7)] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_bounties { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose_bounty { + #[codec(compact)] + value: ::core::primitive::u128, + description: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + approve_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 2)] + propose_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 3)] + unassign_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 4)] + accept_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 5)] + award_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + claim_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 7)] + close_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 8)] + extend_bounty_expiry { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + remark: ::std::vec::Vec<::core::primitive::u8>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InsufficientProposersBalance, + #[codec(index = 1)] + InvalidIndex, + #[codec(index = 2)] + ReasonTooBig, + #[codec(index = 3)] + UnexpectedStatus, + #[codec(index = 4)] + RequireCurator, + #[codec(index = 5)] + InvalidValue, + #[codec(index = 6)] + InvalidFee, + #[codec(index = 7)] + PendingPayout, + #[codec(index = 8)] + Premature, + #[codec(index = 9)] + HasActiveChildBounty, + #[codec(index = 10)] + TooManyQueued, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BountyProposed { index: ::core::primitive::u32 }, + #[codec(index = 1)] + BountyRejected { index: ::core::primitive::u32, bond: ::core::primitive::u128 }, + #[codec(index = 2)] + BountyBecameActive { index: ::core::primitive::u32 }, + #[codec(index = 3)] + BountyAwarded { + index: ::core::primitive::u32, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 4)] + BountyClaimed { + index: ::core::primitive::u32, + payout: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 5)] + BountyCanceled { index: ::core::primitive::u32 }, + #[codec(index = 6)] + BountyExtended { index: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bounty<_0, _1, _2> { + pub proposer: _0, + pub value: _1, + pub fee: _1, + pub curator_deposit: _1, + pub bond: _1, + pub status: runtime_types::pallet_bounties::BountyStatus<_0, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BountyStatus<_0, _1> { + #[codec(index = 0)] + Proposed, + #[codec(index = 1)] + Approved, + #[codec(index = 2)] + Funded, + #[codec(index = 3)] + CuratorProposed { curator: _0 }, + #[codec(index = 4)] + Active { curator: _0, update_due: _1 }, + #[codec(index = 5)] + PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, + } + } + pub mod pallet_child_bounties { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + value: ::core::primitive::u128, + description: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + propose_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 2)] + accept_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 3)] + unassign_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 4)] + award_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + claim_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 6)] + close_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParentBountyNotActive, + #[codec(index = 1)] + InsufficientBountyBalance, + #[codec(index = 2)] + TooManyChildBounties, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Added { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, + #[codec(index = 1)] + Awarded { + index: ::core::primitive::u32, + child_index: ::core::primitive::u32, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 2)] + Claimed { + index: ::core::primitive::u32, + child_index: ::core::primitive::u32, + payout: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Canceled { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChildBounty<_0, _1, _2> { + pub parent_bounty: _2, + pub value: _1, + pub fee: _1, + pub curator_deposit: _1, + pub status: runtime_types::pallet_child_bounties::ChildBountyStatus<_0, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ChildBountyStatus<_0, _1> { + #[codec(index = 0)] + Added, + #[codec(index = 1)] + CuratorProposed { curator: _0 }, + #[codec(index = 2)] + Active { curator: _0 }, + #[codec(index = 3)] + PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, + } + } + pub mod pallet_conviction_voting { + use super::runtime_types; + pub mod conviction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Conviction { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Locked1x, + #[codec(index = 2)] + Locked2x, + #[codec(index = 3)] + Locked3x, + #[codec(index = 4)] + Locked4x, + #[codec(index = 5)] + Locked5x, + #[codec(index = 6)] + Locked6x, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vote { + #[codec(compact)] + poll_index: ::core::primitive::u32, + vote: runtime_types::pallet_conviction_voting::vote::AccountVote< + ::core::primitive::u128, + >, + }, + #[codec(index = 1)] + delegate { + class: ::core::primitive::u16, + to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, + balance: ::core::primitive::u128, + }, + #[codec(index = 2)] + undelegate { class: ::core::primitive::u16 }, + #[codec(index = 3)] + unlock { + class: ::core::primitive::u16, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + remove_vote { + class: ::core::option::Option<::core::primitive::u16>, + index: ::core::primitive::u32, + }, + #[codec(index = 5)] + remove_other_vote { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + class: ::core::primitive::u16, + index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotOngoing, + #[codec(index = 1)] + NotVoter, + #[codec(index = 2)] + NoPermission, + #[codec(index = 3)] + NoPermissionYet, + #[codec(index = 4)] + AlreadyDelegating, + #[codec(index = 5)] + AlreadyVoting, + #[codec(index = 6)] + InsufficientFunds, + #[codec(index = 7)] + NotDelegating, + #[codec(index = 8)] + Nonsense, + #[codec(index = 9)] + MaxVotesReached, + #[codec(index = 10)] + ClassNeeded, + #[codec(index = 11)] + BadClass, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Delegated(::sp_core::crypto::AccountId32, ::sp_core::crypto::AccountId32), + #[codec(index = 1)] + Undelegated(::sp_core::crypto::AccountId32), + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Delegations<_0> { + pub votes: _0, + pub capital: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Tally<_0> { + pub ayes: _0, + pub nays: _0, + pub support: _0, + } + } + pub mod vote { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AccountVote<_0> { + #[codec(index = 0)] + Standard { + vote: runtime_types::pallet_conviction_voting::vote::Vote, + balance: _0, + }, + #[codec(index = 1)] + Split { aye: _0, nay: _0 }, + #[codec(index = 2)] + SplitAbstain { aye: _0, nay: _0, abstain: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Casting<_0, _1, _2> { + pub votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _1, + runtime_types::pallet_conviction_voting::vote::AccountVote<_0>, + )>, + pub delegations: + runtime_types::pallet_conviction_voting::types::Delegations<_0>, + pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_1, _0>, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Delegating<_0, _1, _2> { + pub balance: _0, + pub target: _1, + pub conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, + pub delegations: + runtime_types::pallet_conviction_voting::types::Delegations<_0>, + pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_2, _0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PriorLock<_0, _1>(pub _0, pub _1); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Vote(pub ::core::primitive::u8); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Voting<_0, _1, _2, _3> { + #[codec(index = 0)] + Casting(runtime_types::pallet_conviction_voting::vote::Casting<_0, _2, _2>), + #[codec(index = 1)] + Delegating( + runtime_types::pallet_conviction_voting::vote::Delegating<_0, _1, _2>, + ), + __Ignore(::core::marker::PhantomData<_3>), + } + } + } + pub mod pallet_election_provider_multi_phase { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] submit_unsigned { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: kusama_runtime :: NposCompactSolution24 > > , witness : runtime_types :: pallet_election_provider_multi_phase :: SolutionOrSnapshotSize , } , # [codec (index = 1)] set_minimum_untrusted_score { maybe_next_score : :: core :: option :: Option < runtime_types :: sp_npos_elections :: ElectionScore > , } , # [codec (index = 2)] set_emergency_election_result { supports : :: std :: vec :: Vec < (:: sp_core :: crypto :: AccountId32 , runtime_types :: sp_npos_elections :: Support < :: sp_core :: crypto :: AccountId32 > ,) > , } , # [codec (index = 3)] submit { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: kusama_runtime :: NposCompactSolution24 > > , } , # [codec (index = 4)] governance_fallback { maybe_max_voters : :: core :: option :: Option < :: core :: primitive :: u32 > , maybe_max_targets : :: core :: option :: Option < :: core :: primitive :: u32 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PreDispatchEarlySubmission, + #[codec(index = 1)] + PreDispatchWrongWinnerCount, + #[codec(index = 2)] + PreDispatchWeakSubmission, + #[codec(index = 3)] + SignedQueueFull, + #[codec(index = 4)] + SignedCannotPayDeposit, + #[codec(index = 5)] + SignedInvalidWitness, + #[codec(index = 6)] + SignedTooMuchWeight, + #[codec(index = 7)] + OcwCallWrongEra, + #[codec(index = 8)] + MissingSnapshotMetadata, + #[codec(index = 9)] + InvalidSubmissionIndex, + #[codec(index = 10)] + CallNotAllowed, + #[codec(index = 11)] + FallbackFailed, + #[codec(index = 12)] + BoundNotMet, + #[codec(index = 13)] + TooManyWinners, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + SolutionStored { + compute: + runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + origin: ::core::option::Option<::sp_core::crypto::AccountId32>, + prev_ejected: ::core::primitive::bool, + }, + #[codec(index = 1)] + ElectionFinalized { + compute: + runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + score: runtime_types::sp_npos_elections::ElectionScore, + }, + #[codec(index = 2)] + ElectionFailed, + #[codec(index = 3)] + Rewarded { + account: ::sp_core::crypto::AccountId32, + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + Slashed { + account: ::sp_core::crypto::AccountId32, + value: ::core::primitive::u128, + }, + #[codec(index = 5)] + PhaseTransitioned { + from: runtime_types::pallet_election_provider_multi_phase::Phase< + ::core::primitive::u32, + >, + to: runtime_types::pallet_election_provider_multi_phase::Phase< + ::core::primitive::u32, + >, + round: ::core::primitive::u32, + }, + } + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedSubmission<_0, _1, _2> { + pub who: _0, + pub deposit: _1, + pub raw_solution: + runtime_types::pallet_election_provider_multi_phase::RawSolution<_2>, + pub call_fee: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ElectionCompute { + #[codec(index = 0)] + OnChain, + #[codec(index = 1)] + Signed, + #[codec(index = 2)] + Unsigned, + #[codec(index = 3)] + Fallback, + #[codec(index = 4)] + Emergency, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase<_0> { + #[codec(index = 0)] + Off, + #[codec(index = 1)] + Signed, + #[codec(index = 2)] + Unsigned((::core::primitive::bool, _0)), + #[codec(index = 3)] + Emergency, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RawSolution<_0> { + pub solution: _0, + pub score: runtime_types::sp_npos_elections::ElectionScore, + pub round: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReadySolution { + pub supports: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::sp_core::crypto::AccountId32, + runtime_types::sp_npos_elections::Support<::sp_core::crypto::AccountId32>, + )>, + pub score: runtime_types::sp_npos_elections::ElectionScore, + pub compute: runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RoundSnapshot<_0, _1> { + pub voters: ::std::vec::Vec<_1>, + pub targets: ::std::vec::Vec<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SolutionOrSnapshotSize { + #[codec(compact)] + pub voters: ::core::primitive::u32, + #[codec(compact)] + pub targets: ::core::primitive::u32, + } + } + pub mod pallet_fast_unstake { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register_fast_unstake, + #[codec(index = 1)] + deregister, + #[codec(index = 2)] + control { eras_to_check: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotController, + #[codec(index = 1)] + AlreadyQueued, + #[codec(index = 2)] + NotFullyBonded, + #[codec(index = 3)] + NotQueued, + #[codec(index = 4)] + AlreadyHead, + #[codec(index = 5)] + CallNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Unstaked { + stash: ::sp_core::crypto::AccountId32, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + Slashed { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + InternalError, + #[codec(index = 3)] + BatchChecked { eras: ::std::vec::Vec<::core::primitive::u32> }, + #[codec(index = 4)] + BatchFinished { size: ::core::primitive::u32 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnstakeRequest { + pub stashes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + )>, + pub checked: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >, + } + } + } + pub mod pallet_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + note_stalled { + delay: ::core::primitive::u32, + best_finalized_block_number: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PauseFailed, + #[codec(index = 1)] + ResumeFailed, + #[codec(index = 2)] + ChangePending, + #[codec(index = 3)] + TooSoon, + #[codec(index = 4)] + InvalidKeyOwnershipProof, + #[codec(index = 5)] + InvalidEquivocationProof, + #[codec(index = 6)] + DuplicateOffenceReport, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewAuthorities { + authority_set: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + }, + #[codec(index = 1)] + Paused, + #[codec(index = 2)] + Resumed, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredPendingChange<_0> { + pub scheduled_at: _0, + pub delay: _0, + pub next_authorities: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub forced: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StoredState<_0> { + #[codec(index = 0)] + Live, + #[codec(index = 1)] + PendingPause { scheduled_at: _0, delay: _0 }, + #[codec(index = 2)] + Paused, + #[codec(index = 3)] + PendingResume { scheduled_at: _0, delay: _0 }, + } + } + pub mod pallet_identity { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_registrar { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + set_identity { + info: + ::std::boxed::Box, + }, + #[codec(index = 2)] + set_subs { + subs: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_identity::types::Data, + )>, + }, + #[codec(index = 3)] + clear_identity, + #[codec(index = 4)] + request_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + #[codec(compact)] + max_fee: ::core::primitive::u128, + }, + #[codec(index = 5)] + cancel_request { reg_index: ::core::primitive::u32 }, + #[codec(index = 6)] + set_fee { + #[codec(compact)] + index: ::core::primitive::u32, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 7)] + set_account_id { + #[codec(compact)] + index: ::core::primitive::u32, + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 8)] + set_fields { + #[codec(compact)] + index: ::core::primitive::u32, + fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + }, + #[codec(index = 9)] + provide_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + judgement: runtime_types::pallet_identity::types::Judgement< + ::core::primitive::u128, + >, + identity: ::subxt::utils::H256, + }, + #[codec(index = 10)] + kill_identity { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 11)] + add_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 12)] + rename_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 13)] + remove_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 14)] + quit_sub, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManySubAccounts, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotNamed, + #[codec(index = 3)] + EmptyIndex, + #[codec(index = 4)] + FeeChanged, + #[codec(index = 5)] + NoIdentity, + #[codec(index = 6)] + StickyJudgement, + #[codec(index = 7)] + JudgementGiven, + #[codec(index = 8)] + InvalidJudgement, + #[codec(index = 9)] + InvalidIndex, + #[codec(index = 10)] + InvalidTarget, + #[codec(index = 11)] + TooManyFields, + #[codec(index = 12)] + TooManyRegistrars, + #[codec(index = 13)] + AlreadyClaimed, + #[codec(index = 14)] + NotSub, + #[codec(index = 15)] + NotOwned, + #[codec(index = 16)] + JudgementForDifferentIdentity, + #[codec(index = 17)] + JudgementPaymentFailed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IdentitySet { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + IdentityCleared { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 2)] + IdentityKilled { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 3)] + JudgementRequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 4)] + JudgementUnrequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 5)] + JudgementGiven { + target: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + RegistrarAdded { registrar_index: ::core::primitive::u32 }, + #[codec(index = 7)] + SubIdentityAdded { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 8)] + SubIdentityRemoved { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 9)] + SubIdentityRevoked { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct BitFlags<_0>( + pub ::core::primitive::u64, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Data { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Raw0([::core::primitive::u8; 0usize]), + #[codec(index = 2)] + Raw1([::core::primitive::u8; 1usize]), + #[codec(index = 3)] + Raw2([::core::primitive::u8; 2usize]), + #[codec(index = 4)] + Raw3([::core::primitive::u8; 3usize]), + #[codec(index = 5)] + Raw4([::core::primitive::u8; 4usize]), + #[codec(index = 6)] + Raw5([::core::primitive::u8; 5usize]), + #[codec(index = 7)] + Raw6([::core::primitive::u8; 6usize]), + #[codec(index = 8)] + Raw7([::core::primitive::u8; 7usize]), + #[codec(index = 9)] + Raw8([::core::primitive::u8; 8usize]), + #[codec(index = 10)] + Raw9([::core::primitive::u8; 9usize]), + #[codec(index = 11)] + Raw10([::core::primitive::u8; 10usize]), + #[codec(index = 12)] + Raw11([::core::primitive::u8; 11usize]), + #[codec(index = 13)] + Raw12([::core::primitive::u8; 12usize]), + #[codec(index = 14)] + Raw13([::core::primitive::u8; 13usize]), + #[codec(index = 15)] + Raw14([::core::primitive::u8; 14usize]), + #[codec(index = 16)] + Raw15([::core::primitive::u8; 15usize]), + #[codec(index = 17)] + Raw16([::core::primitive::u8; 16usize]), + #[codec(index = 18)] + Raw17([::core::primitive::u8; 17usize]), + #[codec(index = 19)] + Raw18([::core::primitive::u8; 18usize]), + #[codec(index = 20)] + Raw19([::core::primitive::u8; 19usize]), + #[codec(index = 21)] + Raw20([::core::primitive::u8; 20usize]), + #[codec(index = 22)] + Raw21([::core::primitive::u8; 21usize]), + #[codec(index = 23)] + Raw22([::core::primitive::u8; 22usize]), + #[codec(index = 24)] + Raw23([::core::primitive::u8; 23usize]), + #[codec(index = 25)] + Raw24([::core::primitive::u8; 24usize]), + #[codec(index = 26)] + Raw25([::core::primitive::u8; 25usize]), + #[codec(index = 27)] + Raw26([::core::primitive::u8; 26usize]), + #[codec(index = 28)] + Raw27([::core::primitive::u8; 27usize]), + #[codec(index = 29)] + Raw28([::core::primitive::u8; 28usize]), + #[codec(index = 30)] + Raw29([::core::primitive::u8; 29usize]), + #[codec(index = 31)] + Raw30([::core::primitive::u8; 30usize]), + #[codec(index = 32)] + Raw31([::core::primitive::u8; 31usize]), + #[codec(index = 33)] + Raw32([::core::primitive::u8; 32usize]), + #[codec(index = 34)] + BlakeTwo256([::core::primitive::u8; 32usize]), + #[codec(index = 35)] + Sha256([::core::primitive::u8; 32usize]), + #[codec(index = 36)] + Keccak256([::core::primitive::u8; 32usize]), + #[codec(index = 37)] + ShaThree256([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum IdentityField { + #[codec(index = 1)] + Display, + #[codec(index = 2)] + Legal, + #[codec(index = 4)] + Web, + #[codec(index = 8)] + Riot, + #[codec(index = 16)] + Email, + #[codec(index = 32)] + PgpFingerprint, + #[codec(index = 64)] + Image, + #[codec(index = 128)] + Twitter, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdentityInfo { + pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::pallet_identity::types::Data, + runtime_types::pallet_identity::types::Data, + )>, + pub display: runtime_types::pallet_identity::types::Data, + pub legal: runtime_types::pallet_identity::types::Data, + pub web: runtime_types::pallet_identity::types::Data, + pub riot: runtime_types::pallet_identity::types::Data, + pub email: runtime_types::pallet_identity::types::Data, + pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, + pub image: runtime_types::pallet_identity::types::Data, + pub twitter: runtime_types::pallet_identity::types::Data, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Judgement<_0> { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + FeePaid(_0), + #[codec(index = 2)] + Reasonable, + #[codec(index = 3)] + KnownGood, + #[codec(index = 4)] + OutOfDate, + #[codec(index = 5)] + LowQuality, + #[codec(index = 6)] + Erroneous, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RegistrarInfo<_0, _1> { + pub account: _1, + pub fee: _0, + pub fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0> { + pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::core::primitive::u32, + runtime_types::pallet_identity::types::Judgement<_0>, + )>, + pub deposit: _0, + pub info: runtime_types::pallet_identity::types::IdentityInfo, + } + } + } + pub mod pallet_im_online { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + heartbeat { + heartbeat: + runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, + signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidKey, + #[codec(index = 1)] + DuplicatedHeartbeat, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + HeartbeatReceived { + authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + }, + #[codec(index = 1)] + AllGood, + #[codec(index = 2)] + SomeOffline { + offline: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_staking::Exposure< + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + >, + )>, + }, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedOpaqueNetworkState { + pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + pub external_addresses: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Heartbeat<_0> { + pub block_number: _0, + pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, + pub session_index: _0, + pub authority_index: _0, + pub validators_len: _0, + } + } + pub mod pallet_indices { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { index: ::core::primitive::u32 }, + #[codec(index = 1)] + transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + }, + #[codec(index = 2)] + free { index: ::core::primitive::u32 }, + #[codec(index = 3)] + force_transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + freeze: ::core::primitive::bool, + }, + #[codec(index = 4)] + freeze { index: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAssigned, + #[codec(index = 1)] + NotOwner, + #[codec(index = 2)] + InUse, + #[codec(index = 3)] + NotTransfer, + #[codec(index = 4)] + Permanent, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IndexAssigned { + who: ::sp_core::crypto::AccountId32, + index: ::core::primitive::u32, + }, + #[codec(index = 1)] + IndexFreed { index: ::core::primitive::u32 }, + #[codec(index = 2)] + IndexFrozen { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + }, + } + } + } + pub mod pallet_message_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotReapable, + #[codec(index = 1)] + NoPage, + #[codec(index = 2)] + NoMessage, + #[codec(index = 3)] + AlreadyProcessed, + #[codec(index = 4)] + Queued, + #[codec(index = 5)] + InsufficientWeight, + #[codec(index = 6)] + TemporarilyUnprocessable, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BookState<_0> { + pub begin: ::core::primitive::u32, + pub end: ::core::primitive::u32, + pub count: ::core::primitive::u32, + pub ready_neighbours: + ::core::option::Option>, + pub message_count: ::core::primitive::u64, + pub size: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Neighbours<_0> { + pub prev: _0, + pub next: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Page<_0> { + pub remaining: _0, + pub remaining_size: _0, + pub first_index: _0, + pub first: _0, + pub last: _0, + pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: _0, + } + } + pub mod pallet_nis { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bid<_0, _1> { + pub amount: _0, + pub who: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + place_bid { + #[codec(compact)] + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 1)] + retract_bid { + #[codec(compact)] + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 2)] + fund_deficit, + #[codec(index = 3)] + thaw_private { + #[codec(compact)] + index: ::core::primitive::u32, + maybe_proportion: ::core::option::Option< + runtime_types::sp_arithmetic::per_things::Perquintill, + >, + }, + #[codec(index = 4)] + thaw_communal { + #[codec(compact)] + index: ::core::primitive::u32, + }, + #[codec(index = 5)] + communify { + #[codec(compact)] + index: ::core::primitive::u32, + }, + #[codec(index = 6)] + privatize { + #[codec(compact)] + index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DurationTooSmall, + #[codec(index = 1)] + DurationTooBig, + #[codec(index = 2)] + AmountTooSmall, + #[codec(index = 3)] + BidTooLow, + #[codec(index = 4)] + UnknownReceipt, + #[codec(index = 5)] + NotOwner, + #[codec(index = 6)] + NotExpired, + #[codec(index = 7)] + UnknownBid, + #[codec(index = 8)] + PortionTooBig, + #[codec(index = 9)] + Unfunded, + #[codec(index = 10)] + AlreadyFunded, + #[codec(index = 11)] + Throttled, + #[codec(index = 12)] + MakesDust, + #[codec(index = 13)] + AlreadyCommunal, + #[codec(index = 14)] + AlreadyPrivate, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BidPlaced { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 1)] + BidRetracted { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 2)] + BidDropped { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 3)] + Issued { + index: ::core::primitive::u32, + expiry: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + proportion: runtime_types::sp_arithmetic::per_things::Perquintill, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + Thawed { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + proportion: runtime_types::sp_arithmetic::per_things::Perquintill, + amount: ::core::primitive::u128, + dropped: ::core::primitive::bool, + }, + #[codec(index = 5)] + Funded { deficit: ::core::primitive::u128 }, + #[codec(index = 6)] + Transferred { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HoldReason { + #[codec(index = 0)] + NftReceipt, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceiptRecord<_0, _1, _2> { + pub proportion: runtime_types::sp_arithmetic::per_things::Perquintill, + pub owner: ::core::option::Option<(_0, _2)>, + pub expiry: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SummaryRecord<_0, _1> { + pub proportion_owed: runtime_types::sp_arithmetic::per_things::Perquintill, + pub index: _0, + pub thawed: runtime_types::sp_arithmetic::per_things::Perquintill, + pub last_period: _0, + pub receipts_on_hold: _1, + } + } + } + pub mod pallet_nomination_pools { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + join { + #[codec(compact)] + amount: ::core::primitive::u128, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 1)] + bond_extra { + extra: runtime_types::pallet_nomination_pools::BondExtra< + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + claim_payout, + #[codec(index = 3)] + unbond { + member_account: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + unbonding_points: ::core::primitive::u128, + }, + #[codec(index = 4)] + pool_withdraw_unbonded { + pool_id: ::core::primitive::u32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 5)] + withdraw_unbonded { + member_account: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 6)] + create { + #[codec(compact)] + amount: ::core::primitive::u128, + root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 7)] + create_with_pool_id { + #[codec(compact)] + amount: ::core::primitive::u128, + root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 8)] + nominate { + pool_id: ::core::primitive::u32, + validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 9)] + set_state { + pool_id: ::core::primitive::u32, + state: runtime_types::pallet_nomination_pools::PoolState, + }, + #[codec(index = 10)] + set_metadata { + pool_id: ::core::primitive::u32, + metadata: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 11)] + set_configs { + min_join_bond: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u128, + >, + min_create_bond: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u128, + >, + max_pools: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + max_members: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + max_members_per_pool: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + global_max_commission: runtime_types::pallet_nomination_pools::ConfigOp< + runtime_types::sp_arithmetic::per_things::Perbill, + >, + }, + #[codec(index = 12)] + update_roles { + pool_id: ::core::primitive::u32, + new_root: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + new_nominator: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + new_bouncer: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 13)] + chill { pool_id: ::core::primitive::u32 }, + #[codec(index = 14)] + bond_extra_other { + member: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + extra: runtime_types::pallet_nomination_pools::BondExtra< + ::core::primitive::u128, + >, + }, + #[codec(index = 15)] + set_claim_permission { + permission: runtime_types::pallet_nomination_pools::ClaimPermission, + }, + #[codec(index = 16)] + claim_payout_other { other: ::sp_core::crypto::AccountId32 }, + #[codec(index = 17)] + set_commission { + pool_id: ::core::primitive::u32, + new_commission: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + }, + #[codec(index = 18)] + set_commission_max { + pool_id: ::core::primitive::u32, + max_commission: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 19)] + set_commission_change_rate { + pool_id: ::core::primitive::u32, + change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + }, + #[codec(index = 20)] + claim_commission { pool_id: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DefensiveError { + #[codec(index = 0)] + NotEnoughSpaceInUnbondPool, + #[codec(index = 1)] + PoolNotFound, + #[codec(index = 2)] + RewardPoolNotFound, + #[codec(index = 3)] + SubPoolsNotFound, + #[codec(index = 4)] + BondedStashKilledPrematurely, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PoolNotFound, + #[codec(index = 1)] + PoolMemberNotFound, + #[codec(index = 2)] + RewardPoolNotFound, + #[codec(index = 3)] + SubPoolsNotFound, + #[codec(index = 4)] + AccountBelongsToOtherPool, + #[codec(index = 5)] + FullyUnbonding, + #[codec(index = 6)] + MaxUnbondingLimit, + #[codec(index = 7)] + CannotWithdrawAny, + #[codec(index = 8)] + MinimumBondNotMet, + #[codec(index = 9)] + OverflowRisk, + #[codec(index = 10)] + NotDestroying, + #[codec(index = 11)] + NotNominator, + #[codec(index = 12)] + NotKickerOrDestroying, + #[codec(index = 13)] + NotOpen, + #[codec(index = 14)] + MaxPools, + #[codec(index = 15)] + MaxPoolMembers, + #[codec(index = 16)] + CanNotChangeState, + #[codec(index = 17)] + DoesNotHavePermission, + #[codec(index = 18)] + MetadataExceedsMaxLen, + #[codec(index = 19)] + Defensive(runtime_types::pallet_nomination_pools::pallet::DefensiveError), + #[codec(index = 20)] + PartialUnbondNotAllowedPermissionlessly, + #[codec(index = 21)] + MaxCommissionRestricted, + #[codec(index = 22)] + CommissionExceedsMaximum, + #[codec(index = 23)] + CommissionChangeThrottled, + #[codec(index = 24)] + CommissionChangeRateNotAllowed, + #[codec(index = 25)] + NoPendingCommission, + #[codec(index = 26)] + NoCommissionCurrentSet, + #[codec(index = 27)] + PoolIdInUse, + #[codec(index = 28)] + InvalidPoolId, + #[codec(index = 29)] + BondExtraRestricted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { + depositor: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 1)] + Bonded { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + bonded: ::core::primitive::u128, + joined: ::core::primitive::bool, + }, + #[codec(index = 2)] + PaidOut { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + payout: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unbonded { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + points: ::core::primitive::u128, + era: ::core::primitive::u32, + }, + #[codec(index = 4)] + Withdrawn { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + points: ::core::primitive::u128, + }, + #[codec(index = 5)] + Destroyed { pool_id: ::core::primitive::u32 }, + #[codec(index = 6)] + StateChanged { + pool_id: ::core::primitive::u32, + new_state: runtime_types::pallet_nomination_pools::PoolState, + }, + #[codec(index = 7)] + MemberRemoved { + pool_id: ::core::primitive::u32, + member: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + RolesUpdated { + root: ::core::option::Option<::sp_core::crypto::AccountId32>, + bouncer: ::core::option::Option<::sp_core::crypto::AccountId32>, + nominator: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 9)] + PoolSlashed { + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + }, + #[codec(index = 10)] + UnbondingPoolSlashed { + pool_id: ::core::primitive::u32, + era: ::core::primitive::u32, + balance: ::core::primitive::u128, + }, + #[codec(index = 11)] + PoolCommissionUpdated { + pool_id: ::core::primitive::u32, + current: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + }, + #[codec(index = 12)] + PoolMaxCommissionUpdated { + pool_id: ::core::primitive::u32, + max_commission: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 13)] + PoolCommissionChangeRateUpdated { + pool_id: ::core::primitive::u32, + change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + }, + #[codec(index = 14)] + PoolCommissionClaimed { + pool_id: ::core::primitive::u32, + commission: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BondExtra<_0> { + #[codec(index = 0)] + FreeBalance(_0), + #[codec(index = 1)] + Rewards, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BondedPoolInner { + pub commission: runtime_types::pallet_nomination_pools::Commission, + pub member_counter: ::core::primitive::u32, + pub points: ::core::primitive::u128, + pub roles: runtime_types::pallet_nomination_pools::PoolRoles< + ::sp_core::crypto::AccountId32, + >, + pub state: runtime_types::pallet_nomination_pools::PoolState, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ClaimPermission { + #[codec(index = 0)] + Permissioned, + #[codec(index = 1)] + PermissionlessCompound, + #[codec(index = 2)] + PermissionlessWithdraw, + #[codec(index = 3)] + PermissionlessAll, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commission { + pub current: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + pub max: ::core::option::Option, + pub change_rate: ::core::option::Option< + runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + >, + pub throttle_from: ::core::option::Option<::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommissionChangeRate<_0> { + pub max_increase: runtime_types::sp_arithmetic::per_things::Perbill, + pub min_delay: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConfigOp<_0> { + #[codec(index = 0)] + Noop, + #[codec(index = 1)] + Set(_0), + #[codec(index = 2)] + Remove, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PoolMember { + pub pool_id: ::core::primitive::u32, + pub points: ::core::primitive::u128, + pub last_recorded_reward_counter: + runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub unbonding_eras: + runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< + ::core::primitive::u32, + ::core::primitive::u128, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PoolRoles<_0> { + pub depositor: _0, + pub root: ::core::option::Option<_0>, + pub nominator: ::core::option::Option<_0>, + pub bouncer: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PoolState { + #[codec(index = 0)] + Open, + #[codec(index = 1)] + Blocked, + #[codec(index = 2)] + Destroying, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardPool { + pub last_recorded_reward_counter: + runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub last_recorded_total_payouts: ::core::primitive::u128, + pub total_rewards_claimed: ::core::primitive::u128, + pub total_commission_pending: ::core::primitive::u128, + pub total_commission_claimed: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SubPools { + pub no_era: runtime_types::pallet_nomination_pools::UnbondPool, + pub with_era: + runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< + ::core::primitive::u32, + runtime_types::pallet_nomination_pools::UnbondPool, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnbondPool { + pub points: ::core::primitive::u128, + pub balance: ::core::primitive::u128, + } + } + pub mod pallet_offences { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Offence { + kind: [::core::primitive::u8; 16usize], + timeslot: ::std::vec::Vec<::core::primitive::u8>, + }, + } + } + } + pub mod pallet_preimage { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + unnote_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + request_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 3)] + unrequest_preimage { hash: ::subxt::utils::H256 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooBig, + #[codec(index = 1)] + AlreadyNoted, + #[codec(index = 2)] + NotAuthorized, + #[codec(index = 3)] + NotNoted, + #[codec(index = 4)] + Requested, + #[codec(index = 5)] + NotRequested, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Noted { hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + Requested { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + Cleared { hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RequestStatus<_0, _1> { + #[codec(index = 0)] + Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, + #[codec(index = 1)] + Requested { + deposit: ::core::option::Option<(_0, _1)>, + count: ::core::primitive::u32, + len: ::core::option::Option<::core::primitive::u32>, + }, + } + } + pub mod pallet_proxy { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + proxy { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + add_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::kusama_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 2)] + remove_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::kusama_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 3)] + remove_proxies, + #[codec(index = 4)] + create_pure { + proxy_type: runtime_types::kusama_runtime::ProxyType, + delay: ::core::primitive::u32, + index: ::core::primitive::u16, + }, + #[codec(index = 5)] + kill_pure { + spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::kusama_runtime::ProxyType, + index: ::core::primitive::u16, + #[codec(compact)] + height: ::core::primitive::u32, + #[codec(compact)] + ext_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + announce { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 7)] + remove_announcement { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 8)] + reject_announcement { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 9)] + proxy_announced { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooMany, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotProxy, + #[codec(index = 3)] + Unproxyable, + #[codec(index = 4)] + Duplicate, + #[codec(index = 5)] + NoPermission, + #[codec(index = 6)] + Unannounced, + #[codec(index = 7)] + NoSelfProxy, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ProxyExecuted { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + PureCreated { + pure: ::sp_core::crypto::AccountId32, + who: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::kusama_runtime::ProxyType, + disambiguation_index: ::core::primitive::u16, + }, + #[codec(index = 2)] + Announced { + real: ::sp_core::crypto::AccountId32, + proxy: ::sp_core::crypto::AccountId32, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + ProxyAdded { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::kusama_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 4)] + ProxyRemoved { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::kusama_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Announcement<_0, _1, _2> { + pub real: _0, + pub call_hash: _1, + pub height: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ProxyDefinition<_0, _1, _2> { + pub delegate: _0, + pub proxy_type: _1, + pub delay: _2, + } + } + pub mod pallet_ranked_collective { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + promote_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + demote_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + remove_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + min_rank: ::core::primitive::u16, + }, + #[codec(index = 4)] + vote { poll: ::core::primitive::u32, aye: ::core::primitive::bool }, + #[codec(index = 5)] + cleanup_poll { poll_index: ::core::primitive::u32, max: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AlreadyMember, + #[codec(index = 1)] + NotMember, + #[codec(index = 2)] + NotPolling, + #[codec(index = 3)] + Ongoing, + #[codec(index = 4)] + NoneRemaining, + #[codec(index = 5)] + Corruption, + #[codec(index = 6)] + RankTooLow, + #[codec(index = 7)] + InvalidWitness, + #[codec(index = 8)] + NoPermission, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + MemberAdded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + RankChanged { + who: ::sp_core::crypto::AccountId32, + rank: ::core::primitive::u16, + }, + #[codec(index = 2)] + MemberRemoved { + who: ::sp_core::crypto::AccountId32, + rank: ::core::primitive::u16, + }, + #[codec(index = 3)] + Voted { + who: ::sp_core::crypto::AccountId32, + poll: ::core::primitive::u32, + vote: runtime_types::pallet_ranked_collective::VoteRecord, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + } + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct MemberRecord { + pub rank: ::core::primitive::u16, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Tally { + pub bare_ayes: ::core::primitive::u32, + pub ayes: ::core::primitive::u32, + pub nays: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VoteRecord { + #[codec(index = 0)] + Aye(::core::primitive::u32), + #[codec(index = 1)] + Nay(::core::primitive::u32), + } + } + pub mod pallet_recovery { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_recovered { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + set_recovered { + lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + create_recovery { + friends: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + threshold: ::core::primitive::u16, + delay_period: ::core::primitive::u32, + }, + #[codec(index = 3)] + initiate_recovery { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + vouch_recovery { + lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + claim_recovery { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + close_recovery { + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 7)] + remove_recovery, + #[codec(index = 8)] + cancel_recovered { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAllowed, + #[codec(index = 1)] + ZeroThreshold, + #[codec(index = 2)] + NotEnoughFriends, + #[codec(index = 3)] + MaxFriends, + #[codec(index = 4)] + NotSorted, + #[codec(index = 5)] + NotRecoverable, + #[codec(index = 6)] + AlreadyRecoverable, + #[codec(index = 7)] + AlreadyStarted, + #[codec(index = 8)] + NotStarted, + #[codec(index = 9)] + NotFriend, + #[codec(index = 10)] + DelayPeriod, + #[codec(index = 11)] + AlreadyVouched, + #[codec(index = 12)] + Threshold, + #[codec(index = 13)] + StillActive, + #[codec(index = 14)] + AlreadyProxy, + #[codec(index = 15)] + BadState, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RecoveryCreated { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + RecoveryInitiated { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 2)] + RecoveryVouched { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + sender: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + RecoveryClosed { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 4)] + AccountRecovered { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 5)] + RecoveryRemoved { lost_account: ::sp_core::crypto::AccountId32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ActiveRecovery<_0, _1, _2> { + pub created: _0, + pub deposit: _1, + pub friends: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RecoveryConfig<_0, _1, _2> { + pub delay_period: _0, + pub deposit: _1, + pub friends: _2, + pub threshold: ::core::primitive::u16, + } + } + pub mod pallet_referenda { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit { + proposal_origin: + ::std::boxed::Box, + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::kusama_runtime::RuntimeCall, + >, + enactment_moment: + runtime_types::frame_support::traits::schedule::DispatchTime< + ::core::primitive::u32, + >, + }, + #[codec(index = 1)] + place_decision_deposit { index: ::core::primitive::u32 }, + #[codec(index = 2)] + refund_decision_deposit { index: ::core::primitive::u32 }, + #[codec(index = 3)] + cancel { index: ::core::primitive::u32 }, + #[codec(index = 4)] + kill { index: ::core::primitive::u32 }, + #[codec(index = 5)] + nudge_referendum { index: ::core::primitive::u32 }, + #[codec(index = 6)] + one_fewer_deciding { track: ::core::primitive::u16 }, + #[codec(index = 7)] + refund_submission_deposit { index: ::core::primitive::u32 }, + #[codec(index = 8)] + set_metadata { + index: ::core::primitive::u32, + maybe_hash: ::core::option::Option<::subxt::utils::H256>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotOngoing, + #[codec(index = 1)] + HasDeposit, + #[codec(index = 2)] + BadTrack, + #[codec(index = 3)] + Full, + #[codec(index = 4)] + QueueEmpty, + #[codec(index = 5)] + BadReferendum, + #[codec(index = 6)] + NothingToDo, + #[codec(index = 7)] + NoTrack, + #[codec(index = 8)] + Unfinished, + #[codec(index = 9)] + NoPermission, + #[codec(index = 10)] + NoDeposit, + #[codec(index = 11)] + BadStatus, + #[codec(index = 12)] + PreimageNotExist, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Submitted { + index: ::core::primitive::u32, + track: ::core::primitive::u16, + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::kusama_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + DecisionDepositPlaced { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + DecisionDepositRefunded { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + DepositSlashed { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + DecisionStarted { + index: ::core::primitive::u32, + track: ::core::primitive::u16, + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::kusama_runtime::RuntimeCall, + >, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + #[codec(index = 5)] + ConfirmStarted { index: ::core::primitive::u32 }, + #[codec(index = 6)] + ConfirmAborted { index: ::core::primitive::u32 }, + #[codec(index = 7)] + Confirmed { + index: ::core::primitive::u32, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + #[codec(index = 8)] + Approved { index: ::core::primitive::u32 }, + #[codec(index = 9)] + Rejected { + index: ::core::primitive::u32, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + #[codec(index = 10)] + TimedOut { + index: ::core::primitive::u32, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + #[codec(index = 11)] + Cancelled { + index: ::core::primitive::u32, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + #[codec(index = 12)] + Killed { + index: ::core::primitive::u32, + tally: runtime_types::pallet_ranked_collective::Tally, + }, + #[codec(index = 13)] + SubmissionDepositRefunded { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + MetadataSet { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, + #[codec(index = 15)] + MetadataCleared { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Curve { + #[codec(index = 0)] + LinearDecreasing { + length: runtime_types::sp_arithmetic::per_things::Perbill, + floor: runtime_types::sp_arithmetic::per_things::Perbill, + ceil: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 1)] + SteppedDecreasing { + begin: runtime_types::sp_arithmetic::per_things::Perbill, + end: runtime_types::sp_arithmetic::per_things::Perbill, + step: runtime_types::sp_arithmetic::per_things::Perbill, + period: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 2)] + Reciprocal { + factor: runtime_types::sp_arithmetic::fixed_point::FixedI64, + x_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, + y_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DecidingStatus<_0> { + pub since: _0, + pub confirming: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Deposit<_0, _1> { + pub who: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReferendumInfo<_0, _1, _2, _3, _4, _5, _6, _7> { + #[codec(index = 0)] + Ongoing( + runtime_types::pallet_referenda::types::ReferendumStatus< + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + >, + ), + #[codec(index = 1)] + Approved( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 2)] + Rejected( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 3)] + Cancelled( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 4)] + TimedOut( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 5)] + Killed(_2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReferendumStatus<_0, _1, _2, _3, _4, _5, _6, _7> { + pub track: _0, + pub origin: _1, + pub proposal: _3, + pub enactment: runtime_types::frame_support::traits::schedule::DispatchTime<_2>, + pub submitted: _2, + pub submission_deposit: runtime_types::pallet_referenda::types::Deposit<_6, _4>, + pub decision_deposit: ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + pub deciding: ::core::option::Option< + runtime_types::pallet_referenda::types::DecidingStatus<_2>, + >, + pub tally: _5, + pub in_queue: ::core::primitive::bool, + pub alarm: ::core::option::Option<(_2, _7)>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct TrackInfo<_0, _1> { + pub name: ::std::string::String, + pub max_deciding: _1, + pub decision_deposit: _0, + pub prepare_period: _1, + pub decision_period: _1, + pub confirm_period: _1, + pub min_enactment_period: _1, + pub min_approval: runtime_types::pallet_referenda::types::Curve, + pub min_support: runtime_types::pallet_referenda::types::Curve, + } + } + } + pub mod pallet_scheduler { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + schedule { + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + schedule_named { + id: [::core::primitive::u8; 32usize], + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 3)] + cancel_named { id: [::core::primitive::u8; 32usize] }, + #[codec(index = 4)] + schedule_after { + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 5)] + schedule_named_after { + id: [::core::primitive::u8; 32usize], + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSchedule, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + TargetBlockNumberInPast, + #[codec(index = 3)] + RescheduleNoChange, + #[codec(index = 4)] + Named, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 1)] + Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + Dispatched { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + CallUnavailable { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 4)] + PeriodicFailed { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 5)] + PermanentlyOverweight { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Scheduled<_0, _1, _2, _3, _4> { + pub maybe_id: ::core::option::Option<_0>, + pub priority: ::core::primitive::u8, + pub call: _1, + pub maybe_periodic: ::core::option::Option<(_2, _2)>, + pub origin: _3, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::kusama_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_society { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + bid { value: ::core::primitive::u128 }, + #[codec(index = 1)] + unbid { pos: ::core::primitive::u32 }, + #[codec(index = 2)] + vouch { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + value: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + #[codec(index = 3)] + unvouch { pos: ::core::primitive::u32 }, + #[codec(index = 4)] + vote { + candidate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + approve: ::core::primitive::bool, + }, + #[codec(index = 5)] + defender_vote { approve: ::core::primitive::bool }, + #[codec(index = 6)] + payout, + #[codec(index = 7)] + found { + founder: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + max_members: ::core::primitive::u32, + rules: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 8)] + unfound, + #[codec(index = 9)] + judge_suspended_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + forgive: ::core::primitive::bool, + }, + #[codec(index = 10)] + judge_suspended_candidate { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + judgement: runtime_types::pallet_society::Judgement, + }, + #[codec(index = 11)] + set_max_members { max: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + BadPosition, + #[codec(index = 1)] + NotMember, + #[codec(index = 2)] + AlreadyMember, + #[codec(index = 3)] + Suspended, + #[codec(index = 4)] + NotSuspended, + #[codec(index = 5)] + NoPayout, + #[codec(index = 6)] + AlreadyFounded, + #[codec(index = 7)] + InsufficientPot, + #[codec(index = 8)] + AlreadyVouching, + #[codec(index = 9)] + NotVouching, + #[codec(index = 10)] + Head, + #[codec(index = 11)] + Founder, + #[codec(index = 12)] + AlreadyBid, + #[codec(index = 13)] + AlreadyCandidate, + #[codec(index = 14)] + NotCandidate, + #[codec(index = 15)] + MaxMembers, + #[codec(index = 16)] + NotFounder, + #[codec(index = 17)] + NotHead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Founded { founder: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + Bid { + candidate_id: ::sp_core::crypto::AccountId32, + offer: ::core::primitive::u128, + }, + #[codec(index = 2)] + Vouch { + candidate_id: ::sp_core::crypto::AccountId32, + offer: ::core::primitive::u128, + vouching: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + AutoUnbid { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + Unbid { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Unvouch { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + Inducted { + primary: ::sp_core::crypto::AccountId32, + candidates: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 7)] + SuspendedMemberJudgement { + who: ::sp_core::crypto::AccountId32, + judged: ::core::primitive::bool, + }, + #[codec(index = 8)] + CandidateSuspended { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 9)] + MemberSuspended { member: ::sp_core::crypto::AccountId32 }, + #[codec(index = 10)] + Challenged { member: ::sp_core::crypto::AccountId32 }, + #[codec(index = 11)] + Vote { + candidate: ::sp_core::crypto::AccountId32, + voter: ::sp_core::crypto::AccountId32, + vote: ::core::primitive::bool, + }, + #[codec(index = 12)] + DefenderVote { + voter: ::sp_core::crypto::AccountId32, + vote: ::core::primitive::bool, + }, + #[codec(index = 13)] + NewMaxMembers { max: ::core::primitive::u32 }, + #[codec(index = 14)] + Unfounded { founder: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Deposit { value: ::core::primitive::u128 }, + #[codec(index = 16)] + SkepticsChosen { skeptics: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bid<_0, _1> { + pub who: _0, + pub kind: runtime_types::pallet_society::BidKind<_0, _1>, + pub value: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BidKind<_0, _1> { + #[codec(index = 0)] + Deposit(_1), + #[codec(index = 1)] + Vouch(_0, _1), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Judgement { + #[codec(index = 0)] + Rebid, + #[codec(index = 1)] + Reject, + #[codec(index = 2)] + Approve, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Vote { + #[codec(index = 0)] + Skeptic, + #[codec(index = 1)] + Reject, + #[codec(index = 2)] + Approve, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VouchingStatus { + #[codec(index = 0)] + Vouching, + #[codec(index = 1)] + Banned, + } + } + pub mod pallet_staking { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + bond { + #[codec(compact)] + value: ::core::primitive::u128, + payee: runtime_types::pallet_staking::RewardDestination< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 1)] + bond_extra { + #[codec(compact)] + max_additional: ::core::primitive::u128, + }, + #[codec(index = 2)] + unbond { + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + withdraw_unbonded { num_slashing_spans: ::core::primitive::u32 }, + #[codec(index = 4)] + validate { prefs: runtime_types::pallet_staking::ValidatorPrefs }, + #[codec(index = 5)] + nominate { + targets: ::std::vec::Vec< + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + >, + }, + #[codec(index = 6)] + chill, + #[codec(index = 7)] + set_payee { + payee: runtime_types::pallet_staking::RewardDestination< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 8)] + set_controller, + #[codec(index = 9)] + set_validator_count { + #[codec(compact)] + new: ::core::primitive::u32, + }, + #[codec(index = 10)] + increase_validator_count { + #[codec(compact)] + additional: ::core::primitive::u32, + }, + #[codec(index = 11)] + scale_validator_count { + factor: runtime_types::sp_arithmetic::per_things::Percent, + }, + #[codec(index = 12)] + force_no_eras, + #[codec(index = 13)] + force_new_era, + #[codec(index = 14)] + set_invulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 15)] + force_unstake { + stash: ::sp_core::crypto::AccountId32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 16)] + force_new_era_always, + #[codec(index = 17)] + cancel_deferred_slash { + era: ::core::primitive::u32, + slash_indices: ::std::vec::Vec<::core::primitive::u32>, + }, + #[codec(index = 18)] + payout_stakers { + validator_stash: ::sp_core::crypto::AccountId32, + era: ::core::primitive::u32, + }, + #[codec(index = 19)] + rebond { + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 20)] + reap_stash { + stash: ::sp_core::crypto::AccountId32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 21)] + kick { + who: ::std::vec::Vec< + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + >, + }, + #[codec(index = 22)] + set_staking_configs { + min_nominator_bond: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u128, + >, + min_validator_bond: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u128, + >, + max_nominator_count: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u32, + >, + max_validator_count: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u32, + >, + chill_threshold: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + runtime_types::sp_arithmetic::per_things::Percent, + >, + min_commission: runtime_types::pallet_staking::pallet::pallet::ConfigOp< + runtime_types::sp_arithmetic::per_things::Perbill, + >, + }, + #[codec(index = 23)] + chill_other { controller: ::sp_core::crypto::AccountId32 }, + #[codec(index = 24)] + force_apply_min_commission { + validator_stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 25)] + set_min_commission { + new: runtime_types::sp_arithmetic::per_things::Perbill, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConfigOp<_0> { + #[codec(index = 0)] + Noop, + #[codec(index = 1)] + Set(_0), + #[codec(index = 2)] + Remove, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotController, + #[codec(index = 1)] + NotStash, + #[codec(index = 2)] + AlreadyBonded, + #[codec(index = 3)] + AlreadyPaired, + #[codec(index = 4)] + EmptyTargets, + #[codec(index = 5)] + DuplicateIndex, + #[codec(index = 6)] + InvalidSlashIndex, + #[codec(index = 7)] + InsufficientBond, + #[codec(index = 8)] + NoMoreChunks, + #[codec(index = 9)] + NoUnlockChunk, + #[codec(index = 10)] + FundedTarget, + #[codec(index = 11)] + InvalidEraToReward, + #[codec(index = 12)] + InvalidNumberOfNominations, + #[codec(index = 13)] + NotSortedAndUnique, + #[codec(index = 14)] + AlreadyClaimed, + #[codec(index = 15)] + IncorrectHistoryDepth, + #[codec(index = 16)] + IncorrectSlashingSpans, + #[codec(index = 17)] + BadState, + #[codec(index = 18)] + TooManyTargets, + #[codec(index = 19)] + BadTarget, + #[codec(index = 20)] + CannotChillOther, + #[codec(index = 21)] + TooManyNominators, + #[codec(index = 22)] + TooManyValidators, + #[codec(index = 23)] + CommissionTooLow, + #[codec(index = 24)] + BoundNotMet, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + EraPaid { + era_index: ::core::primitive::u32, + validator_payout: ::core::primitive::u128, + remainder: ::core::primitive::u128, + }, + #[codec(index = 1)] + Rewarded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Slashed { + staker: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + SlashReported { + validator: ::sp_core::crypto::AccountId32, + fraction: runtime_types::sp_arithmetic::per_things::Perbill, + slash_era: ::core::primitive::u32, + }, + #[codec(index = 4)] + OldSlashingReportDiscarded { session_index: ::core::primitive::u32 }, + #[codec(index = 5)] + StakersElected, + #[codec(index = 6)] + Bonded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 7)] + Unbonded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 8)] + Withdrawn { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Kicked { + nominator: ::sp_core::crypto::AccountId32, + stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 10)] + StakingElectionFailed, + #[codec(index = 11)] + Chilled { stash: ::sp_core::crypto::AccountId32 }, + #[codec(index = 12)] + PayoutStarted { + era_index: ::core::primitive::u32, + validator_stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 13)] + ValidatorPrefsSet { + stash: ::sp_core::crypto::AccountId32, + prefs: runtime_types::pallet_staking::ValidatorPrefs, + }, + #[codec(index = 14)] + ForceEra { mode: runtime_types::pallet_staking::Forcing }, + } + } + } + pub mod slashing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SlashingSpans { + pub span_index: ::core::primitive::u32, + pub last_start: ::core::primitive::u32, + pub last_nonzero_slash: ::core::primitive::u32, + pub prior: ::std::vec::Vec<::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SpanRecord<_0> { + pub slashed: _0, + pub paid_out: _0, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ActiveEraInfo { + pub index: ::core::primitive::u32, + pub start: ::core::option::Option<::core::primitive::u64>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EraRewardPoints<_0> { + pub total: ::core::primitive::u32, + pub individual: ::subxt::utils::KeyedVec<_0, ::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Exposure<_0, _1> { + #[codec(compact)] + pub total: _1, + #[codec(compact)] + pub own: _1, + pub others: + ::std::vec::Vec>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Forcing { + #[codec(index = 0)] + NotForcing, + #[codec(index = 1)] + ForceNew, + #[codec(index = 2)] + ForceNone, + #[codec(index = 3)] + ForceAlways, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndividualExposure<_0, _1> { + pub who: _0, + #[codec(compact)] + pub value: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Nominations { + pub targets: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::sp_core::crypto::AccountId32, + >, + pub submitted_in: ::core::primitive::u32, + pub suppressed: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardDestination<_0> { + #[codec(index = 0)] + Staked, + #[codec(index = 1)] + Stash, + #[codec(index = 2)] + Controller, + #[codec(index = 3)] + Account(_0), + #[codec(index = 4)] + None, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StakingLedger { + pub stash: ::sp_core::crypto::AccountId32, + #[codec(compact)] + pub total: ::core::primitive::u128, + #[codec(compact)] + pub active: ::core::primitive::u128, + pub unlocking: runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_staking::UnlockChunk<::core::primitive::u128>, + >, + pub claimed_rewards: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnappliedSlash<_0, _1> { + pub validator: _0, + pub own: _1, + pub others: ::std::vec::Vec<(_0, _1)>, + pub reporters: ::std::vec::Vec<_0>, + pub payout: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnlockChunk<_0> { + #[codec(compact)] + pub value: _0, + #[codec(compact)] + pub era: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidatorPrefs { + #[codec(compact)] + pub commission: runtime_types::sp_arithmetic::per_things::Perbill, + pub blocked: ::core::primitive::bool, + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_treasury { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose_spend { + #[codec(compact)] + value: ::core::primitive::u128, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + reject_proposal { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + #[codec(index = 2)] + approve_proposal { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + #[codec(index = 3)] + spend { + #[codec(compact)] + amount: ::core::primitive::u128, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + remove_approval { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InsufficientProposersBalance, + #[codec(index = 1)] + InvalidIndex, + #[codec(index = 2)] + TooManyApprovals, + #[codec(index = 3)] + InsufficientPermission, + #[codec(index = 4)] + ProposalNotApproved, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { proposal_index: ::core::primitive::u32 }, + #[codec(index = 1)] + Spending { budget_remaining: ::core::primitive::u128 }, + #[codec(index = 2)] + Awarded { + proposal_index: ::core::primitive::u32, + award: ::core::primitive::u128, + account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Rejected { + proposal_index: ::core::primitive::u32, + slashed: ::core::primitive::u128, + }, + #[codec(index = 4)] + Burnt { burnt_funds: ::core::primitive::u128 }, + #[codec(index = 5)] + Rollover { rollover_balance: ::core::primitive::u128 }, + #[codec(index = 6)] + Deposit { value: ::core::primitive::u128 }, + #[codec(index = 7)] + SpendApproved { + proposal_index: ::core::primitive::u32, + amount: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + UpdatedInactive { + reactivated: ::core::primitive::u128, + deactivated: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Proposal<_0, _1> { + pub proposer: _0, + pub value: _1, + pub beneficiary: _0, + pub bond: _1, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { calls: ::std::vec::Vec }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box, + }, + #[codec(index = 2)] + batch_all { calls: ::std::vec::Vec }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box, + call: ::std::boxed::Box, + }, + #[codec(index = 4)] + force_batch { + calls: ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_vesting { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vest, + #[codec(index = 1)] + vest_other { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + vested_transfer { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 3)] + force_vested_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 4)] + merge_schedules { + schedule1_index: ::core::primitive::u32, + schedule2_index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotVesting, + #[codec(index = 1)] + AtMaxVestingSchedules, + #[codec(index = 2)] + AmountLow, + #[codec(index = 3)] + ScheduleIndexOutOfBounds, + #[codec(index = 4)] + InvalidScheduleParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + VestingUpdated { + account: ::sp_core::crypto::AccountId32, + unvested: ::core::primitive::u128, + }, + #[codec(index = 1)] + VestingCompleted { account: ::sp_core::crypto::AccountId32 }, + } + } + pub mod vesting_info { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VestingInfo<_0, _1> { + pub locked: _0, + pub per_block: _0, + pub starting_block: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V0, + #[codec(index = 1)] + V1, + } + } + pub mod pallet_whitelist { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + whitelist_call { call_hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + remove_whitelisted_call { call_hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + dispatch_whitelisted_call { + call_hash: ::subxt::utils::H256, + call_encoded_len: ::core::primitive::u32, + call_weight_witness: ::sp_weights::Weight, + }, + #[codec(index = 3)] + dispatch_whitelisted_call_with_preimage { + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnavailablePreImage, + #[codec(index = 1)] + UndecodableCall, + #[codec(index = 2)] + InvalidCallWeightWitness, + #[codec(index = 3)] + CallIsNotWhitelisted, + #[codec(index = 4)] + CallAlreadyWhitelisted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CallWhitelisted { call_hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + WhitelistedCallRemoved { call_hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + WhitelistedCallDispatched { + call_hash: ::subxt::utils::H256, + result: ::core::result::Result< + runtime_types::frame_support::dispatch::PostDispatchInfo, + runtime_types::sp_runtime::DispatchErrorWithPostInfo< + runtime_types::frame_support::dispatch::PostDispatchInfo, + >, + >, + }, + } + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: + ::std::boxed::Box, + xcm_version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted(runtime_types::xcm::v3::traits::Outcome), + #[codec(index = 1)] + Sent( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::Xcm, + ), + #[codec(index = 2)] + UnexpectedResponse( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 3)] + ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + #[codec(index = 4)] + Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + #[codec(index = 5)] + NotifyOverweight( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ::sp_weights::Weight, + ::sp_weights::Weight, + ), + #[codec(index = 6)] + NotifyDispatchError( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 7)] + NotifyDecodeFailed( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 8)] + InvalidResponder( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 9)] + InvalidResponderVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 10)] + ResponseTaken(::core::primitive::u64), + #[codec(index = 11)] + AssetsTrapped( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + #[codec(index = 12)] + VersionChangeNotified( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 13)] + SupportedVersionChanged( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + ), + #[codec(index = 14)] + NotifyTargetSendFail( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::traits::Error, + ), + #[codec(index = 15)] + NotifyTargetMigrationFail( + runtime_types::xcm::VersionedMultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 16)] + InvalidQuerierVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 17)] + InvalidQuerier( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 18)] + VersionNotifyStarted( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 19)] + VersionNotifyRequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 20)] + VersionNotifyUnrequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 21)] + FeesPaid( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 22)] + AssetsClaimed( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateHash(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelId { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub recipient: runtime_types::polkadot_parachain::primitives::Id, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCodeHash(pub ::subxt::utils::H256); + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v4 { + use super::runtime_types; + pub mod assignment_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod collator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + pub mod executor_params { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ExecutorParam { + #[codec(index = 1)] + MaxMemoryPages(::core::primitive::u32), + #[codec(index = 2)] + StackLogicalMax(::core::primitive::u32), + #[codec(index = 3)] + StackNativeMax(::core::primitive::u32), + #[codec(index = 4)] + PrecheckingMaxMemory(::core::primitive::u64), + #[codec(index = 5)] + PvfPrepTimeout( + runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 6)] + PvfExecTimeout( + runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 7)] + WasmExtBulkMemory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutorParams( + pub ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, + >, + ); + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedSigned<_0, _1> { + pub payload: _0, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + pub signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, + } + } + pub mod validator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfield( + pub ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BackedCandidate<_0> { + pub candidate: + runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, + pub validity_votes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::ValidityAttestation, + >, + pub validator_indices: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateCommitments<_0> { + pub upward_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::std::vec::Vec<::core::primitive::u8>, + >, + pub horizontal_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain::primitives::Id, + >, + >, + pub new_validation_code: ::core::option::Option< + runtime_types::polkadot_parachain::primitives::ValidationCode, + >, + pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, + pub processed_downward_messages: _0, + pub hrmp_watermark: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateDescriptor<_0> { + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub relay_parent: _0, + pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, + pub persisted_validation_data_hash: _0, + pub pov_hash: _0, + pub erasure_root: _0, + pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, + pub para_head: _0, + pub validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments_hash: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommittedCandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< + ::core::primitive::u32, + >, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct CoreIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum CoreOccupied { + #[codec(index = 0)] + Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), + #[codec(index = 1)] + Parachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeState<_0> { + pub validators_for: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub validators_against: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub start: _0, + pub concluded_at: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeStatement { + #[codec(index = 0)] + Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), + #[codec(index = 1)] + Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeStatementSet { + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub session: ::core::primitive::u32, + pub statements: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::DisputeStatement, + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Signature, + )>, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct GroupIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndexedVec<_0, _1>( + pub ::std::vec::Vec<_1>, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData<_0> { + pub bitfields: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + >, + >, + pub backed_candidates: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::BackedCandidate< + ::subxt::utils::H256, + >, + >, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + pub parent_header: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaim( + pub runtime_types::polkadot_parachain::primitives::Id, + pub runtime_types::polkadot_primitives::v4::collator_app::Public, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadEntry { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, + pub retries: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckStatement { + pub accept: ::core::primitive::bool, + pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + pub session_index: ::core::primitive::u32, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfExecTimeoutKind { + #[codec(index = 0)] + Backing, + #[codec(index = 1)] + Approval, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfPrepTimeoutKind { + #[codec(index = 0)] + Precheck, + #[codec(index = 1)] + Lenient, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ScrapedOnChainVotes<_0> { + pub session: ::core::primitive::u32, + pub backing_validators_per_candidate: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, + ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::ValidityAttestation, + )>, + )>, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionInfo { + pub active_validator_indices: + ::std::vec::Vec, + pub random_seed: [::core::primitive::u8; 32usize], + pub dispute_period: ::core::primitive::u32, + pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub discovery_keys: + ::std::vec::Vec, + pub assignment_keys: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::assignment_app::Public, + >, + pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::GroupIndex, + ::std::vec::Vec, + >, + pub n_cores: ::core::primitive::u32, + pub zeroth_delay_tranche_width: ::core::primitive::u32, + pub relay_vrf_modulo_samples: ::core::primitive::u32, + pub n_delay_tranches: ::core::primitive::u32, + pub no_show_slots: ::core::primitive::u32, + pub needed_approvals: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + #[codec(index = 1)] + BackingSeconded(::subxt::utils::H256), + #[codec(index = 2)] + BackingValid(::subxt::utils::H256), + #[codec(index = 3)] + ApprovalChecking, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ValidatorIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidityAttestation { + #[codec(index = 1)] + Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + #[codec(index = 2)] + Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + } + } + pub mod vstaging { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + } + pub mod polkadot_runtime_common { + use super::runtime_types; + pub mod auctions { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + new_auction { + #[codec(compact)] + duration: ::core::primitive::u32, + #[codec(compact)] + lease_period_index: ::core::primitive::u32, + }, + #[codec(index = 1)] + bid { + #[codec(compact)] + para: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + auction_index: ::core::primitive::u32, + #[codec(compact)] + first_slot: ::core::primitive::u32, + #[codec(compact)] + last_slot: ::core::primitive::u32, + #[codec(compact)] + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + cancel_auction, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AuctionInProgress, + #[codec(index = 1)] + LeasePeriodInPast, + #[codec(index = 2)] + ParaNotRegistered, + #[codec(index = 3)] + NotCurrentAuction, + #[codec(index = 4)] + NotAuction, + #[codec(index = 5)] + AuctionEnded, + #[codec(index = 6)] + AlreadyLeasedOut, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + AuctionStarted { + auction_index: ::core::primitive::u32, + lease_period: ::core::primitive::u32, + ending: ::core::primitive::u32, + }, + #[codec(index = 1)] + AuctionClosed { auction_index: ::core::primitive::u32 }, + #[codec(index = 2)] + Reserved { + bidder: ::sp_core::crypto::AccountId32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unreserved { + bidder: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + ReserveConfiscated { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + BidAccepted { + bidder: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + first_slot: ::core::primitive::u32, + last_slot: ::core::primitive::u32, + }, + #[codec(index = 6)] + WinningOffset { + auction_index: ::core::primitive::u32, + block_number: ::core::primitive::u32, + }, + } + } + } + pub mod claims { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { + dest: ::sp_core::crypto::AccountId32, + ethereum_signature: + runtime_types::polkadot_runtime_common::claims::EcdsaSignature, + }, + #[codec(index = 1)] + mint_claim { + who: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + value: ::core::primitive::u128, + vesting_schedule: ::core::option::Option<( + ::core::primitive::u128, + ::core::primitive::u128, + ::core::primitive::u32, + )>, + statement: ::core::option::Option< + runtime_types::polkadot_runtime_common::claims::StatementKind, + >, + }, + #[codec(index = 2)] + claim_attest { + dest: ::sp_core::crypto::AccountId32, + ethereum_signature: + runtime_types::polkadot_runtime_common::claims::EcdsaSignature, + statement: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 3)] + attest { statement: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + move_claim { + old: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + new: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + maybe_preclaim: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEthereumSignature, + #[codec(index = 1)] + SignerHasNoClaim, + #[codec(index = 2)] + SenderHasNoClaim, + #[codec(index = 3)] + PotUnderflow, + #[codec(index = 4)] + InvalidStatement, + #[codec(index = 5)] + VestedBalanceExists, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Claimed { + who: ::sp_core::crypto::AccountId32, + ethereum_address: + runtime_types::polkadot_runtime_common::claims::EthereumAddress, + amount: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EcdsaSignature(pub [::core::primitive::u8; 65usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EthereumAddress(pub [::core::primitive::u8; 20usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StatementKind { + #[codec(index = 0)] + Regular, + #[codec(index = 1)] + Saft, + } + } + pub mod crowdloan { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + create { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 1)] + contribute { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + value: ::core::primitive::u128, + signature: + ::core::option::Option, + }, + #[codec(index = 2)] + withdraw { + who: ::sp_core::crypto::AccountId32, + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 3)] + refund { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + dissolve { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + edit { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 6)] + add_memo { + index: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 7)] + poke { index: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + contribute_all { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + signature: + ::core::option::Option, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FirstPeriodInPast, + #[codec(index = 1)] + FirstPeriodTooFarInFuture, + #[codec(index = 2)] + LastPeriodBeforeFirstPeriod, + #[codec(index = 3)] + LastPeriodTooFarInFuture, + #[codec(index = 4)] + CannotEndInPast, + #[codec(index = 5)] + EndTooFarInFuture, + #[codec(index = 6)] + Overflow, + #[codec(index = 7)] + ContributionTooSmall, + #[codec(index = 8)] + InvalidParaId, + #[codec(index = 9)] + CapExceeded, + #[codec(index = 10)] + ContributionPeriodOver, + #[codec(index = 11)] + InvalidOrigin, + #[codec(index = 12)] + NotParachain, + #[codec(index = 13)] + LeaseActive, + #[codec(index = 14)] + BidOrLeaseActive, + #[codec(index = 15)] + FundNotEnded, + #[codec(index = 16)] + NoContributions, + #[codec(index = 17)] + NotReadyToDissolve, + #[codec(index = 18)] + InvalidSignature, + #[codec(index = 19)] + MemoTooLarge, + #[codec(index = 20)] + AlreadyInNewRaise, + #[codec(index = 21)] + VrfDelayInProgress, + #[codec(index = 22)] + NoLeasePeriod, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 1)] + Contributed { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Withdrew { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + PartiallyRefunded { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 6)] + HandleBidResult { + para_id: runtime_types::polkadot_parachain::primitives::Id, + result: ::core::result::Result< + (), + runtime_types::sp_runtime::DispatchError, + >, + }, + #[codec(index = 7)] + Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + MemoUpdated { + who: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 9)] + AddedToNewRaise { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FundInfo<_0, _1, _2, _3> { + pub depositor: _0, + pub verifier: ::core::option::Option, + pub deposit: _1, + pub raised: _1, + pub end: _2, + pub cap: _1, + pub last_contribution: + runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, + pub first_period: _2, + pub last_period: _2, + pub fund_index: _2, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum LastContribution<_0> { + #[codec(index = 0)] + Never, + #[codec(index = 1)] + PreEnding(_0), + #[codec(index = 2)] + Ending(_0), + } + } + pub mod paras_registrar { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register { + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_register { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 2)] + deregister { id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 3)] + swap { + id: runtime_types::polkadot_parachain::primitives::Id, + other: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + reserve, + #[codec(index = 6)] + add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 7)] + schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 8)] + set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + AlreadyRegistered, + #[codec(index = 2)] + NotOwner, + #[codec(index = 3)] + CodeTooLarge, + #[codec(index = 4)] + HeadDataTooLarge, + #[codec(index = 5)] + NotParachain, + #[codec(index = 6)] + NotParathread, + #[codec(index = 7)] + CannotDeregister, + #[codec(index = 8)] + CannotDowngrade, + #[codec(index = 9)] + CannotUpgrade, + #[codec(index = 10)] + ParaLocked, + #[codec(index = 11)] + NotReserved, + #[codec(index = 12)] + EmptyCode, + #[codec(index = 13)] + CannotSwap, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Registered { + para_id: runtime_types::polkadot_parachain::primitives::Id, + manager: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 1)] + Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + Reserved { + para_id: runtime_types::polkadot_parachain::primitives::Id, + who: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Swapped { + para_id: runtime_types::polkadot_parachain::primitives::Id, + other_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo<_0, _1> { + pub manager: _0, + pub deposit: _1, + pub locked: ::core::primitive::bool, + } + } + pub mod slots { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_lease { + para: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + }, + #[codec(index = 1)] + clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaNotOnboarding, + #[codec(index = 1)] + LeaseError, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewLeasePeriod { lease_period: ::core::primitive::u32 }, + #[codec(index = 1)] + Leased { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + } + } + } + } + pub mod polkadot_runtime_parachains { + use super::runtime_types; + pub mod configuration { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidNewValue, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HostConfiguration<_0> { + pub max_code_size: _0, + pub max_head_data_size: _0, + pub max_upward_queue_count: _0, + pub max_upward_queue_size: _0, + pub max_upward_message_size: _0, + pub max_upward_message_num_per_candidate: _0, + pub hrmp_max_message_num_per_candidate: _0, + pub validation_upgrade_cooldown: _0, + pub validation_upgrade_delay: _0, + pub async_backing_params: + runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, + pub max_pov_size: _0, + pub max_downward_message_size: _0, + pub hrmp_max_parachain_outbound_channels: _0, + pub hrmp_max_parathread_outbound_channels: _0, + pub hrmp_sender_deposit: ::core::primitive::u128, + pub hrmp_recipient_deposit: ::core::primitive::u128, + pub hrmp_channel_max_capacity: _0, + pub hrmp_channel_max_total_size: _0, + pub hrmp_max_parachain_inbound_channels: _0, + pub hrmp_max_parathread_inbound_channels: _0, + pub hrmp_channel_max_message_size: _0, + pub executor_params: + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, + pub code_retention_period: _0, + pub parathread_cores: _0, + pub parathread_retries: _0, + pub group_rotation_frequency: _0, + pub chain_availability_period: _0, + pub thread_availability_period: _0, + pub scheduling_lookahead: _0, + pub max_validators_per_core: ::core::option::Option<_0>, + pub max_validators: ::core::option::Option<_0>, + pub dispute_period: _0, + pub dispute_post_conclusion_acceptance_period: _0, + pub no_show_slots: _0, + pub n_delay_tranches: _0, + pub zeroth_delay_tranche_width: _0, + pub needed_approvals: _0, + pub relay_vrf_modulo_samples: _0, + pub pvf_checking_enabled: ::core::primitive::bool, + pub pvf_voting_ttl: _0, + pub minimum_validation_upgrade_delay: _0, + } + } + pub mod disputes { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_unfreeze, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateDisputeStatementSets, + #[codec(index = 1)] + AncientDisputeStatement, + #[codec(index = 2)] + ValidatorIndexOutOfBounds, + #[codec(index = 3)] + InvalidSignature, + #[codec(index = 4)] + DuplicateStatement, + #[codec(index = 5)] + SingleSidedDispute, + #[codec(index = 6)] + MaliciousBacker, + #[codec(index = 7)] + MissingBackingVotes, + #[codec(index = 8)] + UnconfirmedDispute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + DisputeInitiated( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, + ), + #[codec(index = 1)] + DisputeConcluded( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, + ), + #[codec(index = 2)] + Revert(::core::primitive::u32), + } + } + pub mod slashing { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Call { + # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Error { + #[codec(index = 0)] + InvalidKeyOwnershipProof, + #[codec(index = 1)] + InvalidSessionIndex, + #[codec(index = 2)] + InvalidCandidateHash, + #[codec(index = 3)] + InvalidValidatorIndex, + #[codec(index = 4)] + ValidatorIndexIdMismatch, + #[codec(index = 5)] + DuplicateSlashingReport, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputesTimeSlot { + pub session_index: ::core::primitive::u32, + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SlashingOffenceKind { + #[codec(index = 0)] + ForInvalid, + #[codec(index = 1)] + AgainstValid, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeLocation { + #[codec(index = 0)] + Local, + #[codec(index = 1)] + Remote, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeResult { + #[codec(index = 0)] + Valid, + #[codec(index = 1)] + Invalid, + } + } + pub mod hrmp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + hrmp_init_open_channel { + recipient: runtime_types::polkadot_parachain::primitives::Id, + proposed_max_capacity: ::core::primitive::u32, + proposed_max_message_size: ::core::primitive::u32, + }, + #[codec(index = 1)] + hrmp_accept_open_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 2)] + hrmp_close_channel { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + }, + #[codec(index = 3)] + force_clean_hrmp { + para: runtime_types::polkadot_parachain::primitives::Id, + inbound: ::core::primitive::u32, + outbound: ::core::primitive::u32, + }, + #[codec(index = 4)] + force_process_hrmp_open { channels: ::core::primitive::u32 }, + #[codec(index = 5)] + force_process_hrmp_close { channels: ::core::primitive::u32 }, + #[codec(index = 6)] + hrmp_cancel_open_request { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + open_requests: ::core::primitive::u32, + }, + #[codec(index = 7)] + force_open_hrmp_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + recipient: runtime_types::polkadot_parachain::primitives::Id, + max_capacity: ::core::primitive::u32, + max_message_size: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OpenHrmpChannelToSelf, + #[codec(index = 1)] + OpenHrmpChannelInvalidRecipient, + #[codec(index = 2)] + OpenHrmpChannelZeroCapacity, + #[codec(index = 3)] + OpenHrmpChannelCapacityExceedsLimit, + #[codec(index = 4)] + OpenHrmpChannelZeroMessageSize, + #[codec(index = 5)] + OpenHrmpChannelMessageSizeExceedsLimit, + #[codec(index = 6)] + OpenHrmpChannelAlreadyExists, + #[codec(index = 7)] + OpenHrmpChannelAlreadyRequested, + #[codec(index = 8)] + OpenHrmpChannelLimitExceeded, + #[codec(index = 9)] + AcceptHrmpChannelDoesntExist, + #[codec(index = 10)] + AcceptHrmpChannelAlreadyConfirmed, + #[codec(index = 11)] + AcceptHrmpChannelLimitExceeded, + #[codec(index = 12)] + CloseHrmpChannelUnauthorized, + #[codec(index = 13)] + CloseHrmpChannelDoesntExist, + #[codec(index = 14)] + CloseHrmpChannelAlreadyUnderway, + #[codec(index = 15)] + CancelHrmpOpenChannelUnauthorized, + #[codec(index = 16)] + OpenHrmpChannelDoesntExist, + #[codec(index = 17)] + OpenHrmpChannelAlreadyConfirmed, + #[codec(index = 18)] + WrongWitness, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + OpenChannelRequested( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + #[codec(index = 1)] + OpenChannelCanceled( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 2)] + OpenChannelAccepted( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 3)] + ChannelClosed( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 4)] + HrmpChannelForceOpened( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + pub sender_deposit: ::core::primitive::u128, + pub recipient_deposit: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpOpenChannelRequest { + pub confirmed: ::core::primitive::bool, + pub _age: ::core::primitive::u32, + pub sender_deposit: ::core::primitive::u128, + pub max_message_size: ::core::primitive::u32, + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + } + } + pub mod inclusion { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnsortedOrDuplicateValidatorIndices, + #[codec(index = 1)] + UnsortedOrDuplicateDisputeStatementSet, + #[codec(index = 2)] + UnsortedOrDuplicateBackedCandidates, + #[codec(index = 3)] + UnexpectedRelayParent, + #[codec(index = 4)] + WrongBitfieldSize, + #[codec(index = 5)] + BitfieldAllZeros, + #[codec(index = 6)] + BitfieldDuplicateOrUnordered, + #[codec(index = 7)] + ValidatorIndexOutOfBounds, + #[codec(index = 8)] + InvalidBitfieldSignature, + #[codec(index = 9)] + UnscheduledCandidate, + #[codec(index = 10)] + CandidateScheduledBeforeParaFree, + #[codec(index = 11)] + WrongCollator, + #[codec(index = 12)] + ScheduledOutOfOrder, + #[codec(index = 13)] + HeadDataTooLarge, + #[codec(index = 14)] + PrematureCodeUpgrade, + #[codec(index = 15)] + NewCodeTooLarge, + #[codec(index = 16)] + CandidateNotInParentContext, + #[codec(index = 17)] + InvalidGroupIndex, + #[codec(index = 18)] + InsufficientBacking, + #[codec(index = 19)] + InvalidBacking, + #[codec(index = 20)] + NotCollatorSigned, + #[codec(index = 21)] + ValidationDataHashMismatch, + #[codec(index = 22)] + IncorrectDownwardMessageHandling, + #[codec(index = 23)] + InvalidUpwardMessages, + #[codec(index = 24)] + HrmpWatermarkMishandling, + #[codec(index = 25)] + InvalidOutboundHrmp, + #[codec(index = 26)] + InvalidValidationCodeHash, + #[codec(index = 27)] + ParaHeadMismatch, + #[codec(index = 28)] + BitfieldReferencesFreedCore, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CandidateBacked( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 1)] + CandidateIncluded( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 2)] + CandidateTimedOut( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + ), + #[codec(index = 3)] + UpwardMessagesReceived { + from: runtime_types::polkadot_parachain::primitives::Id, + count: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfieldRecord<_0> { + pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + pub submitted_at: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidatePendingAvailability<_0, _1> { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub availability_votes: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub backers: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub relay_parent_number: _1, + pub backed_in_number: _1, + pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UmpQueueId { + #[codec(index = 0)] + Para(runtime_types::polkadot_parachain::primitives::Id), + } + } + pub mod initializer { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_approve { up_to: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BufferedSessionChange { + pub validators: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub queued: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub session_index: ::core::primitive::u32, + } + } + pub mod origin { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Parachain(runtime_types::polkadot_parachain::primitives::Id), + } + } + } + pub mod paras { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_set_current_code { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 2)] + force_schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + relay_parent_number: ::core::primitive::u32, + }, + #[codec(index = 3)] + force_note_new_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 4)] + force_queue_action { + para: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + add_trusted_validation_code { + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 6)] + poke_unused_validation_code { + validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + }, + #[codec(index = 7)] + include_pvf_check_statement { + stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, + signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + CannotOnboard, + #[codec(index = 2)] + CannotOffboard, + #[codec(index = 3)] + CannotUpgrade, + #[codec(index = 4)] + CannotDowngrade, + #[codec(index = 5)] + PvfCheckStatementStale, + #[codec(index = 6)] + PvfCheckStatementFuture, + #[codec(index = 7)] + PvfCheckValidatorIndexOutOfBounds, + #[codec(index = 8)] + PvfCheckInvalidSignature, + #[codec(index = 9)] + PvfCheckDoubleVote, + #[codec(index = 10)] + PvfCheckSubjectInvalid, + #[codec(index = 11)] + CannotUpgradeCode, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 2)] + CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 3)] + NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 4)] + ActionQueued( + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ), + #[codec(index = 5)] + PvfCheckStarted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 6)] + PvfCheckAccepted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 7)] + PvfCheckRejected( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaGenesisArgs { + pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + pub para_kind: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ParaLifecycle { + #[codec(index = 0)] + Onboarding, + #[codec(index = 1)] + Parathread, + #[codec(index = 2)] + Parachain, + #[codec(index = 3)] + UpgradingParathread, + #[codec(index = 4)] + DowngradingParachain, + #[codec(index = 5)] + OffboardingParathread, + #[codec(index = 6)] + OffboardingParachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaPastCodeMeta<_0> { + pub upgrade_times: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, + >, + pub last_pruned: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckActiveVoteState<_0> { + pub votes_accept: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub votes_reject: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub age: _0, + pub created_at: _0, + pub causes: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfCheckCause<_0> { + #[codec(index = 0)] + Onboarding(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + Upgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + relay_parent_number: _0, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReplacementTimes<_0> { + pub expected_at: _0, + pub activated_at: _0, + } + } + pub mod paras_inherent { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + enter { + data: runtime_types::polkadot_primitives::v4::InherentData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyInclusionInherents, + #[codec(index = 1)] + InvalidParentHeader, + #[codec(index = 2)] + CandidateConcludedInvalid, + #[codec(index = 3)] + InherentOverweight, + #[codec(index = 4)] + DisputeStatementsUnsortedOrDuplicates, + #[codec(index = 5)] + DisputeInvalid, + } + } + } + pub mod scheduler { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssignmentKind { + #[codec(index = 0)] + Parachain, + #[codec(index = 1)] + Parathread( + runtime_types::polkadot_primitives::v4::collator_app::Public, + ::core::primitive::u32, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CoreAssignment { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, + pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaimQueue { + pub queue: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, + >, + pub next_core_offset: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueuedParathread { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, + pub core_offset: ::core::primitive::u32, + } + } + pub mod shared { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FixedI64(pub ::core::primitive::i64); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + pub mod per_things { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct PerU16(pub ::core::primitive::u16); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Perbill(pub ::core::primitive::u32); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Percent(pub ::core::primitive::u8); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Permill(pub ::core::primitive::u32); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Perquintill(pub ::core::primitive::u64); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_authority_discovery { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + pub mod sp_consensus_babe { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod digests { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NextConfigDescriptor { + #[codec(index = 1)] + V1 { + c: (::core::primitive::u64, ::core::primitive::u64), + allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PreDigest { + #[codec(index = 1)] + Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), + #[codec(index = 2)] + SecondaryPlain( + runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, + ), + #[codec(index = 3)] + SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PrimaryPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryPlainPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryVRFPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AllowedSlots { + #[codec(index = 0)] + PrimarySlots, + #[codec(index = 1)] + PrimaryAndSecondaryPlainSlots, + #[codec(index = 2)] + PrimaryAndSecondaryVRFSlots, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BabeEpochConfiguration { + pub c: (::core::primitive::u64, ::core::primitive::u64), + pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Equivocation<_0, _1> { + #[codec(index = 0)] + Prevote( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Prevote<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + #[codec(index = 1)] + Precommit( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Precommit<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EquivocationProof<_0, _1> { + pub offender: _1, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub first_header: _0, + pub second_header: _0, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 33usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod offchain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueNetworkState { + pub peer_id: runtime_types::sp_core::OpaquePeerId, + pub external_addresses: + ::std::vec::Vec, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod vrf { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VrfSignature { + pub output: [::core::primitive::u8; 32usize], + pub proof: [::core::primitive::u8; 64usize], + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_npos_elections { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ElectionScore { + pub minimal_stake: ::core::primitive::u128, + pub sum_stake: ::core::primitive::u128, + pub sum_stake_squared: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Support<_0> { + pub total: ::core::primitive::u128, + pub voters: ::std::vec::Vec<(_0, ::core::primitive::u128)>, + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, + ); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchErrorWithPostInfo<_0> { + pub post_info: _0, + pub error: runtime_types::sp_runtime::DispatchError, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSigner { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Public), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Public), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Public), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_staking { + use super::runtime_types; + pub mod offence { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OffenceDetails<_0, _1> { + pub offender: _1, + pub reporters: ::std::vec::Vec<_0>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + } + } +} diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 2ea7fa39d0f07..2108f67dc9d81 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,21 +16,36 @@ //! Types used to connect to the Kusama chain. +pub mod codegen_runtime; + use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; +use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, + RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::storage::StorageKey; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use sp_session::MembershipProof; use std::time::Duration; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::kusama_runtime::RuntimeCall; + +pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; + /// Kusama header id. pub type HeaderId = relay_utils::HeaderId; /// Kusama header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; +/// The address format for describing accounts. +pub type Address = MultiAddress; + /// Kusama chain definition #[derive(Debug, Clone, Copy)] pub struct Kusama; @@ -47,7 +62,7 @@ impl Chain for Kusama { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); type SignedBlock = bp_kusama::SignedBlock; - type Call = (); + type Call = RuntimeCall; } impl ChainWithGrandpa for Kusama { @@ -67,3 +82,54 @@ impl RelayChain for Kusama { const PARAS_PALLET_NAME: &'static str = bp_kusama::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeKusamaParachain"; } + +impl ChainWithTransactions for Kusama { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = + bp_polkadot_core::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_kusama::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ((), ()), + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(Self::SignedTransaction::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index b3101c980c557..ffd4a3f1cb8ed 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -25,9 +25,8 @@ use relay_substrate_client::{ ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, NonceOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::{storage::StorageKey, Pair}; +use sp_core::{storage::StorageKey, Pair, Void}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use sp_session::MembershipProof; use std::time::Duration; /// Millau header id. @@ -71,7 +70,7 @@ impl ChainWithGrandpa for Millau { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - type KeyOwnerProof = MembershipProof; + type KeyOwnerProof = Void; } impl ChainWithBalances for Millau { diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 7da3499a16bda..3c5db4fa55b06 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -6,15 +6,23 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +subxt = { version = "0.31.0", default-features = false, features = ["native"] } # Bridge dependencies bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + # Substrate Dependencies +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-polkadot/src/codegen_runtime.rs b/relays/client-polkadot/src/codegen_runtime.rs new file mode 100644 index 0000000000000..aa4b37cec502a --- /dev/null +++ b/relays/client-polkadot/src/codegen_runtime.rs @@ -0,0 +1,8399 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://rpc.polkadot.io:443 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_btree_map { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedBTreeMap<_0, _1>(pub ::subxt::utils::KeyedVec<_0, _1>); + } + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Equivocation<_0, _1, _2> { + pub round_number: ::core::primitive::u64, + pub identity: _0, + pub first: (_1, _2), + pub second: (_1, _2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Prevote<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PostDispatchInfo { + pub actual_weight: ::core::option::Option<::sp_weights::Weight>, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProcessMessageError { + #[codec(index = 0)] + BadFormat, + #[codec(index = 1)] + Corrupt, + #[codec(index = 2)] + Unsupported, + #[codec(index = 3)] + Overweight(::sp_weights::Weight), + #[codec(index = 4)] + Yield, + } + } + pub mod misc { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WrapperOpaque<_0>( + #[codec(compact)] pub ::core::primitive::u32, + pub _0, + ); + } + pub mod preimages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Bounded<_0> { + #[codec(index = 0)] + Legacy { + hash: ::subxt::utils::H256, + }, + #[codec(index = 1)] + Inline( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Lookup { + hash: ::subxt::utils::H256, + len: ::core::primitive::u32, + }, + __Ignore(::core::marker::PhantomData<_0>), + } + } + pub mod schedule { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchTime<_0> { + #[codec(index = 0)] + At(_0), + #[codec(index = 1)] + After(_0), + } + } + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletId(pub [::core::primitive::u8; 8usize]); + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_babe { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + plan_config_change { + config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEquivocationProof, + #[codec(index = 1)] + InvalidKeyOwnershipProof, + #[codec(index = 2)] + DuplicateOffenceReport, + #[codec(index = 3)] + InvalidConfiguration, + } + } + } + pub mod pallet_bags_list { + use super::runtime_types; + pub mod list { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bag { + pub head: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub tail: ::core::option::Option<::sp_core::crypto::AccountId32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ListError { + #[codec(index = 0)] + Duplicate, + #[codec(index = 1)] + NotHeavier, + #[codec(index = 2)] + NotInSameBag, + #[codec(index = 3)] + NodeNotFound, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Node { + pub id: ::sp_core::crypto::AccountId32, + pub prev: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub next: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub bag_upper: ::core::primitive::u64, + pub score: ::core::primitive::u64, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + rebag { + dislocated: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + put_in_front_of { + lighter: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + List(runtime_types::pallet_bags_list::list::ListError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Rebagged { + who: ::sp_core::crypto::AccountId32, + from: ::core::primitive::u64, + to: ::core::primitive::u64, + }, + #[codec(index = 1)] + ScoreUpdated { + who: ::sp_core::crypto::AccountId32, + new_score: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + set_balance_deprecated { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + #[codec(compact)] + old_reserved: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 7)] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_bounties { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose_bounty { + #[codec(compact)] + value: ::core::primitive::u128, + description: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + approve_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 2)] + propose_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 3)] + unassign_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 4)] + accept_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 5)] + award_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + claim_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 7)] + close_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 8)] + extend_bounty_expiry { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + remark: ::std::vec::Vec<::core::primitive::u8>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InsufficientProposersBalance, + #[codec(index = 1)] + InvalidIndex, + #[codec(index = 2)] + ReasonTooBig, + #[codec(index = 3)] + UnexpectedStatus, + #[codec(index = 4)] + RequireCurator, + #[codec(index = 5)] + InvalidValue, + #[codec(index = 6)] + InvalidFee, + #[codec(index = 7)] + PendingPayout, + #[codec(index = 8)] + Premature, + #[codec(index = 9)] + HasActiveChildBounty, + #[codec(index = 10)] + TooManyQueued, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BountyProposed { index: ::core::primitive::u32 }, + #[codec(index = 1)] + BountyRejected { index: ::core::primitive::u32, bond: ::core::primitive::u128 }, + #[codec(index = 2)] + BountyBecameActive { index: ::core::primitive::u32 }, + #[codec(index = 3)] + BountyAwarded { + index: ::core::primitive::u32, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 4)] + BountyClaimed { + index: ::core::primitive::u32, + payout: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 5)] + BountyCanceled { index: ::core::primitive::u32 }, + #[codec(index = 6)] + BountyExtended { index: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bounty<_0, _1, _2> { + pub proposer: _0, + pub value: _1, + pub fee: _1, + pub curator_deposit: _1, + pub bond: _1, + pub status: runtime_types::pallet_bounties::BountyStatus<_0, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BountyStatus<_0, _1> { + #[codec(index = 0)] + Proposed, + #[codec(index = 1)] + Approved, + #[codec(index = 2)] + Funded, + #[codec(index = 3)] + CuratorProposed { curator: _0 }, + #[codec(index = 4)] + Active { curator: _0, update_due: _1 }, + #[codec(index = 5)] + PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, + } + } + pub mod pallet_child_bounties { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + value: ::core::primitive::u128, + description: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + propose_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 2)] + accept_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 3)] + unassign_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 4)] + award_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + claim_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 6)] + close_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParentBountyNotActive, + #[codec(index = 1)] + InsufficientBountyBalance, + #[codec(index = 2)] + TooManyChildBounties, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Added { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, + #[codec(index = 1)] + Awarded { + index: ::core::primitive::u32, + child_index: ::core::primitive::u32, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 2)] + Claimed { + index: ::core::primitive::u32, + child_index: ::core::primitive::u32, + payout: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Canceled { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChildBounty<_0, _1, _2> { + pub parent_bounty: _2, + pub value: _1, + pub fee: _1, + pub curator_deposit: _1, + pub status: runtime_types::pallet_child_bounties::ChildBountyStatus<_0, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ChildBountyStatus<_0, _1> { + #[codec(index = 0)] + Added, + #[codec(index = 1)] + CuratorProposed { curator: _0 }, + #[codec(index = 2)] + Active { curator: _0 }, + #[codec(index = 3)] + PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, + } + } + pub mod pallet_collective { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_members { + new_members: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + prime: ::core::option::Option<::sp_core::crypto::AccountId32>, + old_count: ::core::primitive::u32, + }, + #[codec(index = 1)] + execute { + proposal: ::std::boxed::Box, + #[codec(compact)] + length_bound: ::core::primitive::u32, + }, + #[codec(index = 2)] + propose { + #[codec(compact)] + threshold: ::core::primitive::u32, + proposal: ::std::boxed::Box, + #[codec(compact)] + length_bound: ::core::primitive::u32, + }, + #[codec(index = 3)] + vote { + proposal: ::subxt::utils::H256, + #[codec(compact)] + index: ::core::primitive::u32, + approve: ::core::primitive::bool, + }, + #[codec(index = 5)] + disapprove_proposal { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 6)] + close { + proposal_hash: ::subxt::utils::H256, + #[codec(compact)] + index: ::core::primitive::u32, + proposal_weight_bound: ::sp_weights::Weight, + #[codec(compact)] + length_bound: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotMember, + #[codec(index = 1)] + DuplicateProposal, + #[codec(index = 2)] + ProposalMissing, + #[codec(index = 3)] + WrongIndex, + #[codec(index = 4)] + DuplicateVote, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooEarly, + #[codec(index = 7)] + TooManyProposals, + #[codec(index = 8)] + WrongProposalWeight, + #[codec(index = 9)] + WrongProposalLength, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { + account: ::sp_core::crypto::AccountId32, + proposal_index: ::core::primitive::u32, + proposal_hash: ::subxt::utils::H256, + threshold: ::core::primitive::u32, + }, + #[codec(index = 1)] + Voted { + account: ::sp_core::crypto::AccountId32, + proposal_hash: ::subxt::utils::H256, + voted: ::core::primitive::bool, + yes: ::core::primitive::u32, + no: ::core::primitive::u32, + }, + #[codec(index = 2)] + Approved { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 3)] + Disapproved { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + Executed { + proposal_hash: ::subxt::utils::H256, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 5)] + MemberExecuted { + proposal_hash: ::subxt::utils::H256, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 6)] + Closed { + proposal_hash: ::subxt::utils::H256, + yes: ::core::primitive::u32, + no: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Members(::core::primitive::u32, ::core::primitive::u32), + #[codec(index = 1)] + Member(_0), + #[codec(index = 2)] + _Phantom, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Votes<_0, _1> { + pub index: _1, + pub threshold: _1, + pub ayes: ::std::vec::Vec<_0>, + pub nays: ::std::vec::Vec<_0>, + pub end: _1, + } + } + pub mod pallet_conviction_voting { + use super::runtime_types; + pub mod conviction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Conviction { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Locked1x, + #[codec(index = 2)] + Locked2x, + #[codec(index = 3)] + Locked3x, + #[codec(index = 4)] + Locked4x, + #[codec(index = 5)] + Locked5x, + #[codec(index = 6)] + Locked6x, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vote { + #[codec(compact)] + poll_index: ::core::primitive::u32, + vote: runtime_types::pallet_conviction_voting::vote::AccountVote< + ::core::primitive::u128, + >, + }, + #[codec(index = 1)] + delegate { + class: ::core::primitive::u16, + to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, + balance: ::core::primitive::u128, + }, + #[codec(index = 2)] + undelegate { class: ::core::primitive::u16 }, + #[codec(index = 3)] + unlock { + class: ::core::primitive::u16, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + remove_vote { + class: ::core::option::Option<::core::primitive::u16>, + index: ::core::primitive::u32, + }, + #[codec(index = 5)] + remove_other_vote { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + class: ::core::primitive::u16, + index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotOngoing, + #[codec(index = 1)] + NotVoter, + #[codec(index = 2)] + NoPermission, + #[codec(index = 3)] + NoPermissionYet, + #[codec(index = 4)] + AlreadyDelegating, + #[codec(index = 5)] + AlreadyVoting, + #[codec(index = 6)] + InsufficientFunds, + #[codec(index = 7)] + NotDelegating, + #[codec(index = 8)] + Nonsense, + #[codec(index = 9)] + MaxVotesReached, + #[codec(index = 10)] + ClassNeeded, + #[codec(index = 11)] + BadClass, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Delegated(::sp_core::crypto::AccountId32, ::sp_core::crypto::AccountId32), + #[codec(index = 1)] + Undelegated(::sp_core::crypto::AccountId32), + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Delegations<_0> { + pub votes: _0, + pub capital: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Tally<_0> { + pub ayes: _0, + pub nays: _0, + pub support: _0, + } + } + pub mod vote { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AccountVote<_0> { + #[codec(index = 0)] + Standard { + vote: runtime_types::pallet_conviction_voting::vote::Vote, + balance: _0, + }, + #[codec(index = 1)] + Split { aye: _0, nay: _0 }, + #[codec(index = 2)] + SplitAbstain { aye: _0, nay: _0, abstain: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Casting<_0, _1, _2> { + pub votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _1, + runtime_types::pallet_conviction_voting::vote::AccountVote<_0>, + )>, + pub delegations: + runtime_types::pallet_conviction_voting::types::Delegations<_0>, + pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_1, _0>, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Delegating<_0, _1, _2> { + pub balance: _0, + pub target: _1, + pub conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, + pub delegations: + runtime_types::pallet_conviction_voting::types::Delegations<_0>, + pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_2, _0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PriorLock<_0, _1>(pub _0, pub _1); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Vote(pub ::core::primitive::u8); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Voting<_0, _1, _2, _3> { + #[codec(index = 0)] + Casting(runtime_types::pallet_conviction_voting::vote::Casting<_0, _2, _2>), + #[codec(index = 1)] + Delegating( + runtime_types::pallet_conviction_voting::vote::Delegating<_0, _1, _2>, + ), + __Ignore(::core::marker::PhantomData<_3>), + } + } + } + pub mod pallet_democracy { + use super::runtime_types; + pub mod conviction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Conviction { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Locked1x, + #[codec(index = 2)] + Locked2x, + #[codec(index = 3)] + Locked3x, + #[codec(index = 4)] + Locked4x, + #[codec(index = 5)] + Locked5x, + #[codec(index = 6)] + Locked6x, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + second { + #[codec(compact)] + proposal: ::core::primitive::u32, + }, + #[codec(index = 2)] + vote { + #[codec(compact)] + ref_index: ::core::primitive::u32, + vote: runtime_types::pallet_democracy::vote::AccountVote< + ::core::primitive::u128, + >, + }, + #[codec(index = 3)] + emergency_cancel { ref_index: ::core::primitive::u32 }, + #[codec(index = 4)] + external_propose { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 5)] + external_propose_majority { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 6)] + external_propose_default { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 7)] + fast_track { + proposal_hash: ::subxt::utils::H256, + voting_period: ::core::primitive::u32, + delay: ::core::primitive::u32, + }, + #[codec(index = 8)] + veto_external { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 9)] + cancel_referendum { + #[codec(compact)] + ref_index: ::core::primitive::u32, + }, + #[codec(index = 10)] + delegate { + to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + conviction: runtime_types::pallet_democracy::conviction::Conviction, + balance: ::core::primitive::u128, + }, + #[codec(index = 11)] + undelegate, + #[codec(index = 12)] + clear_public_proposals, + #[codec(index = 13)] + unlock { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 14)] + remove_vote { index: ::core::primitive::u32 }, + #[codec(index = 15)] + remove_other_vote { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + }, + #[codec(index = 16)] + blacklist { + proposal_hash: ::subxt::utils::H256, + maybe_ref_index: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 17)] + cancel_proposal { + #[codec(compact)] + prop_index: ::core::primitive::u32, + }, + #[codec(index = 18)] + set_metadata { + owner: runtime_types::pallet_democracy::types::MetadataOwner, + maybe_hash: ::core::option::Option<::subxt::utils::H256>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ValueLow, + #[codec(index = 1)] + ProposalMissing, + #[codec(index = 2)] + AlreadyCanceled, + #[codec(index = 3)] + DuplicateProposal, + #[codec(index = 4)] + ProposalBlacklisted, + #[codec(index = 5)] + NotSimpleMajority, + #[codec(index = 6)] + InvalidHash, + #[codec(index = 7)] + NoProposal, + #[codec(index = 8)] + AlreadyVetoed, + #[codec(index = 9)] + ReferendumInvalid, + #[codec(index = 10)] + NoneWaiting, + #[codec(index = 11)] + NotVoter, + #[codec(index = 12)] + NoPermission, + #[codec(index = 13)] + AlreadyDelegating, + #[codec(index = 14)] + InsufficientFunds, + #[codec(index = 15)] + NotDelegating, + #[codec(index = 16)] + VotesExist, + #[codec(index = 17)] + InstantNotAllowed, + #[codec(index = 18)] + Nonsense, + #[codec(index = 19)] + WrongUpperBound, + #[codec(index = 20)] + MaxVotesReached, + #[codec(index = 21)] + TooMany, + #[codec(index = 22)] + VotingPeriodLow, + #[codec(index = 23)] + PreimageNotExist, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { + proposal_index: ::core::primitive::u32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 1)] + Tabled { + proposal_index: ::core::primitive::u32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 2)] + ExternalTabled, + #[codec(index = 3)] + Started { + ref_index: ::core::primitive::u32, + threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, + }, + #[codec(index = 4)] + Passed { ref_index: ::core::primitive::u32 }, + #[codec(index = 5)] + NotPassed { ref_index: ::core::primitive::u32 }, + #[codec(index = 6)] + Cancelled { ref_index: ::core::primitive::u32 }, + #[codec(index = 7)] + Delegated { + who: ::sp_core::crypto::AccountId32, + target: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + Undelegated { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 9)] + Vetoed { + who: ::sp_core::crypto::AccountId32, + proposal_hash: ::subxt::utils::H256, + until: ::core::primitive::u32, + }, + #[codec(index = 10)] + Blacklisted { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 11)] + Voted { + voter: ::sp_core::crypto::AccountId32, + ref_index: ::core::primitive::u32, + vote: runtime_types::pallet_democracy::vote::AccountVote< + ::core::primitive::u128, + >, + }, + #[codec(index = 12)] + Seconded { + seconder: ::sp_core::crypto::AccountId32, + prop_index: ::core::primitive::u32, + }, + #[codec(index = 13)] + ProposalCanceled { prop_index: ::core::primitive::u32 }, + #[codec(index = 14)] + MetadataSet { + owner: runtime_types::pallet_democracy::types::MetadataOwner, + hash: ::subxt::utils::H256, + }, + #[codec(index = 15)] + MetadataCleared { + owner: runtime_types::pallet_democracy::types::MetadataOwner, + hash: ::subxt::utils::H256, + }, + #[codec(index = 16)] + MetadataTransferred { + prev_owner: runtime_types::pallet_democracy::types::MetadataOwner, + owner: runtime_types::pallet_democracy::types::MetadataOwner, + hash: ::subxt::utils::H256, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Delegations<_0> { + pub votes: _0, + pub capital: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MetadataOwner { + #[codec(index = 0)] + External, + #[codec(index = 1)] + Proposal(::core::primitive::u32), + #[codec(index = 2)] + Referendum(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReferendumInfo<_0, _1, _2> { + #[codec(index = 0)] + Ongoing(runtime_types::pallet_democracy::types::ReferendumStatus<_0, _1, _2>), + #[codec(index = 1)] + Finished { approved: ::core::primitive::bool, end: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReferendumStatus<_0, _1, _2> { + pub end: _0, + pub proposal: _1, + pub threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, + pub delay: _0, + pub tally: runtime_types::pallet_democracy::types::Tally<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Tally<_0> { + pub ayes: _0, + pub nays: _0, + pub turnout: _0, + } + } + pub mod vote { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AccountVote<_0> { + #[codec(index = 0)] + Standard { vote: runtime_types::pallet_democracy::vote::Vote, balance: _0 }, + #[codec(index = 1)] + Split { aye: _0, nay: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PriorLock<_0, _1>(pub _0, pub _1); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Vote(pub ::core::primitive::u8); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Voting<_0, _1, _2> { + #[codec(index = 0)] + Direct { + votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _2, + runtime_types::pallet_democracy::vote::AccountVote<_0>, + )>, + delegations: runtime_types::pallet_democracy::types::Delegations<_0>, + prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, + }, + #[codec(index = 1)] + Delegating { + balance: _0, + target: _1, + conviction: runtime_types::pallet_democracy::conviction::Conviction, + delegations: runtime_types::pallet_democracy::types::Delegations<_0>, + prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, + }, + } + } + pub mod vote_threshold { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VoteThreshold { + #[codec(index = 0)] + SuperMajorityApprove, + #[codec(index = 1)] + SuperMajorityAgainst, + #[codec(index = 2)] + SimpleMajority, + } + } + } + pub mod pallet_election_provider_multi_phase { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] submit_unsigned { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: polkadot_runtime :: NposCompactSolution16 > > , witness : runtime_types :: pallet_election_provider_multi_phase :: SolutionOrSnapshotSize , } , # [codec (index = 1)] set_minimum_untrusted_score { maybe_next_score : :: core :: option :: Option < runtime_types :: sp_npos_elections :: ElectionScore > , } , # [codec (index = 2)] set_emergency_election_result { supports : :: std :: vec :: Vec < (:: sp_core :: crypto :: AccountId32 , runtime_types :: sp_npos_elections :: Support < :: sp_core :: crypto :: AccountId32 > ,) > , } , # [codec (index = 3)] submit { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: polkadot_runtime :: NposCompactSolution16 > > , } , # [codec (index = 4)] governance_fallback { maybe_max_voters : :: core :: option :: Option < :: core :: primitive :: u32 > , maybe_max_targets : :: core :: option :: Option < :: core :: primitive :: u32 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PreDispatchEarlySubmission, + #[codec(index = 1)] + PreDispatchWrongWinnerCount, + #[codec(index = 2)] + PreDispatchWeakSubmission, + #[codec(index = 3)] + SignedQueueFull, + #[codec(index = 4)] + SignedCannotPayDeposit, + #[codec(index = 5)] + SignedInvalidWitness, + #[codec(index = 6)] + SignedTooMuchWeight, + #[codec(index = 7)] + OcwCallWrongEra, + #[codec(index = 8)] + MissingSnapshotMetadata, + #[codec(index = 9)] + InvalidSubmissionIndex, + #[codec(index = 10)] + CallNotAllowed, + #[codec(index = 11)] + FallbackFailed, + #[codec(index = 12)] + BoundNotMet, + #[codec(index = 13)] + TooManyWinners, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + SolutionStored { + compute: + runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + origin: ::core::option::Option<::sp_core::crypto::AccountId32>, + prev_ejected: ::core::primitive::bool, + }, + #[codec(index = 1)] + ElectionFinalized { + compute: + runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + score: runtime_types::sp_npos_elections::ElectionScore, + }, + #[codec(index = 2)] + ElectionFailed, + #[codec(index = 3)] + Rewarded { + account: ::sp_core::crypto::AccountId32, + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + Slashed { + account: ::sp_core::crypto::AccountId32, + value: ::core::primitive::u128, + }, + #[codec(index = 5)] + PhaseTransitioned { + from: runtime_types::pallet_election_provider_multi_phase::Phase< + ::core::primitive::u32, + >, + to: runtime_types::pallet_election_provider_multi_phase::Phase< + ::core::primitive::u32, + >, + round: ::core::primitive::u32, + }, + } + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedSubmission<_0, _1, _2> { + pub who: _0, + pub deposit: _1, + pub raw_solution: + runtime_types::pallet_election_provider_multi_phase::RawSolution<_2>, + pub call_fee: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ElectionCompute { + #[codec(index = 0)] + OnChain, + #[codec(index = 1)] + Signed, + #[codec(index = 2)] + Unsigned, + #[codec(index = 3)] + Fallback, + #[codec(index = 4)] + Emergency, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase<_0> { + #[codec(index = 0)] + Off, + #[codec(index = 1)] + Signed, + #[codec(index = 2)] + Unsigned((::core::primitive::bool, _0)), + #[codec(index = 3)] + Emergency, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RawSolution<_0> { + pub solution: _0, + pub score: runtime_types::sp_npos_elections::ElectionScore, + pub round: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReadySolution { + pub supports: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::sp_core::crypto::AccountId32, + runtime_types::sp_npos_elections::Support<::sp_core::crypto::AccountId32>, + )>, + pub score: runtime_types::sp_npos_elections::ElectionScore, + pub compute: runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RoundSnapshot<_0, _1> { + pub voters: ::std::vec::Vec<_1>, + pub targets: ::std::vec::Vec<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SolutionOrSnapshotSize { + #[codec(compact)] + pub voters: ::core::primitive::u32, + #[codec(compact)] + pub targets: ::core::primitive::u32, + } + } + pub mod pallet_elections_phragmen { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vote { + votes: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + remove_voter, + #[codec(index = 2)] + submit_candidacy { + #[codec(compact)] + candidate_count: ::core::primitive::u32, + }, + #[codec(index = 3)] + renounce_candidacy { + renouncing: runtime_types::pallet_elections_phragmen::Renouncing, + }, + #[codec(index = 4)] + remove_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + slash_bond: ::core::primitive::bool, + rerun_election: ::core::primitive::bool, + }, + #[codec(index = 5)] + clean_defunct_voters { + num_voters: ::core::primitive::u32, + num_defunct: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnableToVote, + #[codec(index = 1)] + NoVotes, + #[codec(index = 2)] + TooManyVotes, + #[codec(index = 3)] + MaximumVotesExceeded, + #[codec(index = 4)] + LowBalance, + #[codec(index = 5)] + UnableToPayBond, + #[codec(index = 6)] + MustBeVoter, + #[codec(index = 7)] + DuplicatedCandidate, + #[codec(index = 8)] + TooManyCandidates, + #[codec(index = 9)] + MemberSubmit, + #[codec(index = 10)] + RunnerUpSubmit, + #[codec(index = 11)] + InsufficientCandidateFunds, + #[codec(index = 12)] + NotMember, + #[codec(index = 13)] + InvalidWitnessData, + #[codec(index = 14)] + InvalidVoteCount, + #[codec(index = 15)] + InvalidRenouncing, + #[codec(index = 16)] + InvalidReplacement, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewTerm { + new_members: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + )>, + }, + #[codec(index = 1)] + EmptyTerm, + #[codec(index = 2)] + ElectionError, + #[codec(index = 3)] + MemberKicked { member: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + Renounced { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + CandidateSlashed { + candidate: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + SeatHolderSlashed { + seat_holder: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Renouncing { + #[codec(index = 0)] + Member, + #[codec(index = 1)] + RunnerUp, + #[codec(index = 2)] + Candidate(#[codec(compact)] ::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SeatHolder<_0, _1> { + pub who: _0, + pub stake: _1, + pub deposit: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Voter<_0, _1> { + pub votes: ::std::vec::Vec<_0>, + pub stake: _1, + pub deposit: _1, + } + } + pub mod pallet_fast_unstake { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register_fast_unstake, + #[codec(index = 1)] + deregister, + #[codec(index = 2)] + control { eras_to_check: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotController, + #[codec(index = 1)] + AlreadyQueued, + #[codec(index = 2)] + NotFullyBonded, + #[codec(index = 3)] + NotQueued, + #[codec(index = 4)] + AlreadyHead, + #[codec(index = 5)] + CallNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Unstaked { + stash: ::sp_core::crypto::AccountId32, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + Slashed { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + InternalError, + #[codec(index = 3)] + BatchChecked { eras: ::std::vec::Vec<::core::primitive::u32> }, + #[codec(index = 4)] + BatchFinished { size: ::core::primitive::u32 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnstakeRequest { + pub stashes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + )>, + pub checked: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >, + } + } + } + pub mod pallet_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + note_stalled { + delay: ::core::primitive::u32, + best_finalized_block_number: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PauseFailed, + #[codec(index = 1)] + ResumeFailed, + #[codec(index = 2)] + ChangePending, + #[codec(index = 3)] + TooSoon, + #[codec(index = 4)] + InvalidKeyOwnershipProof, + #[codec(index = 5)] + InvalidEquivocationProof, + #[codec(index = 6)] + DuplicateOffenceReport, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewAuthorities { + authority_set: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + }, + #[codec(index = 1)] + Paused, + #[codec(index = 2)] + Resumed, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredPendingChange<_0> { + pub scheduled_at: _0, + pub delay: _0, + pub next_authorities: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub forced: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StoredState<_0> { + #[codec(index = 0)] + Live, + #[codec(index = 1)] + PendingPause { scheduled_at: _0, delay: _0 }, + #[codec(index = 2)] + Paused, + #[codec(index = 3)] + PendingResume { scheduled_at: _0, delay: _0 }, + } + } + pub mod pallet_identity { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_registrar { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + set_identity { + info: + ::std::boxed::Box, + }, + #[codec(index = 2)] + set_subs { + subs: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_identity::types::Data, + )>, + }, + #[codec(index = 3)] + clear_identity, + #[codec(index = 4)] + request_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + #[codec(compact)] + max_fee: ::core::primitive::u128, + }, + #[codec(index = 5)] + cancel_request { reg_index: ::core::primitive::u32 }, + #[codec(index = 6)] + set_fee { + #[codec(compact)] + index: ::core::primitive::u32, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 7)] + set_account_id { + #[codec(compact)] + index: ::core::primitive::u32, + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 8)] + set_fields { + #[codec(compact)] + index: ::core::primitive::u32, + fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + }, + #[codec(index = 9)] + provide_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + judgement: runtime_types::pallet_identity::types::Judgement< + ::core::primitive::u128, + >, + identity: ::subxt::utils::H256, + }, + #[codec(index = 10)] + kill_identity { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 11)] + add_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 12)] + rename_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 13)] + remove_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 14)] + quit_sub, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManySubAccounts, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotNamed, + #[codec(index = 3)] + EmptyIndex, + #[codec(index = 4)] + FeeChanged, + #[codec(index = 5)] + NoIdentity, + #[codec(index = 6)] + StickyJudgement, + #[codec(index = 7)] + JudgementGiven, + #[codec(index = 8)] + InvalidJudgement, + #[codec(index = 9)] + InvalidIndex, + #[codec(index = 10)] + InvalidTarget, + #[codec(index = 11)] + TooManyFields, + #[codec(index = 12)] + TooManyRegistrars, + #[codec(index = 13)] + AlreadyClaimed, + #[codec(index = 14)] + NotSub, + #[codec(index = 15)] + NotOwned, + #[codec(index = 16)] + JudgementForDifferentIdentity, + #[codec(index = 17)] + JudgementPaymentFailed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IdentitySet { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + IdentityCleared { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 2)] + IdentityKilled { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 3)] + JudgementRequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 4)] + JudgementUnrequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 5)] + JudgementGiven { + target: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + RegistrarAdded { registrar_index: ::core::primitive::u32 }, + #[codec(index = 7)] + SubIdentityAdded { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 8)] + SubIdentityRemoved { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 9)] + SubIdentityRevoked { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct BitFlags<_0>( + pub ::core::primitive::u64, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Data { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Raw0([::core::primitive::u8; 0usize]), + #[codec(index = 2)] + Raw1([::core::primitive::u8; 1usize]), + #[codec(index = 3)] + Raw2([::core::primitive::u8; 2usize]), + #[codec(index = 4)] + Raw3([::core::primitive::u8; 3usize]), + #[codec(index = 5)] + Raw4([::core::primitive::u8; 4usize]), + #[codec(index = 6)] + Raw5([::core::primitive::u8; 5usize]), + #[codec(index = 7)] + Raw6([::core::primitive::u8; 6usize]), + #[codec(index = 8)] + Raw7([::core::primitive::u8; 7usize]), + #[codec(index = 9)] + Raw8([::core::primitive::u8; 8usize]), + #[codec(index = 10)] + Raw9([::core::primitive::u8; 9usize]), + #[codec(index = 11)] + Raw10([::core::primitive::u8; 10usize]), + #[codec(index = 12)] + Raw11([::core::primitive::u8; 11usize]), + #[codec(index = 13)] + Raw12([::core::primitive::u8; 12usize]), + #[codec(index = 14)] + Raw13([::core::primitive::u8; 13usize]), + #[codec(index = 15)] + Raw14([::core::primitive::u8; 14usize]), + #[codec(index = 16)] + Raw15([::core::primitive::u8; 15usize]), + #[codec(index = 17)] + Raw16([::core::primitive::u8; 16usize]), + #[codec(index = 18)] + Raw17([::core::primitive::u8; 17usize]), + #[codec(index = 19)] + Raw18([::core::primitive::u8; 18usize]), + #[codec(index = 20)] + Raw19([::core::primitive::u8; 19usize]), + #[codec(index = 21)] + Raw20([::core::primitive::u8; 20usize]), + #[codec(index = 22)] + Raw21([::core::primitive::u8; 21usize]), + #[codec(index = 23)] + Raw22([::core::primitive::u8; 22usize]), + #[codec(index = 24)] + Raw23([::core::primitive::u8; 23usize]), + #[codec(index = 25)] + Raw24([::core::primitive::u8; 24usize]), + #[codec(index = 26)] + Raw25([::core::primitive::u8; 25usize]), + #[codec(index = 27)] + Raw26([::core::primitive::u8; 26usize]), + #[codec(index = 28)] + Raw27([::core::primitive::u8; 27usize]), + #[codec(index = 29)] + Raw28([::core::primitive::u8; 28usize]), + #[codec(index = 30)] + Raw29([::core::primitive::u8; 29usize]), + #[codec(index = 31)] + Raw30([::core::primitive::u8; 30usize]), + #[codec(index = 32)] + Raw31([::core::primitive::u8; 31usize]), + #[codec(index = 33)] + Raw32([::core::primitive::u8; 32usize]), + #[codec(index = 34)] + BlakeTwo256([::core::primitive::u8; 32usize]), + #[codec(index = 35)] + Sha256([::core::primitive::u8; 32usize]), + #[codec(index = 36)] + Keccak256([::core::primitive::u8; 32usize]), + #[codec(index = 37)] + ShaThree256([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum IdentityField { + #[codec(index = 1)] + Display, + #[codec(index = 2)] + Legal, + #[codec(index = 4)] + Web, + #[codec(index = 8)] + Riot, + #[codec(index = 16)] + Email, + #[codec(index = 32)] + PgpFingerprint, + #[codec(index = 64)] + Image, + #[codec(index = 128)] + Twitter, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdentityInfo { + pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::pallet_identity::types::Data, + runtime_types::pallet_identity::types::Data, + )>, + pub display: runtime_types::pallet_identity::types::Data, + pub legal: runtime_types::pallet_identity::types::Data, + pub web: runtime_types::pallet_identity::types::Data, + pub riot: runtime_types::pallet_identity::types::Data, + pub email: runtime_types::pallet_identity::types::Data, + pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, + pub image: runtime_types::pallet_identity::types::Data, + pub twitter: runtime_types::pallet_identity::types::Data, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Judgement<_0> { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + FeePaid(_0), + #[codec(index = 2)] + Reasonable, + #[codec(index = 3)] + KnownGood, + #[codec(index = 4)] + OutOfDate, + #[codec(index = 5)] + LowQuality, + #[codec(index = 6)] + Erroneous, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RegistrarInfo<_0, _1> { + pub account: _1, + pub fee: _0, + pub fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0> { + pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::core::primitive::u32, + runtime_types::pallet_identity::types::Judgement<_0>, + )>, + pub deposit: _0, + pub info: runtime_types::pallet_identity::types::IdentityInfo, + } + } + } + pub mod pallet_im_online { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + heartbeat { + heartbeat: + runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, + signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidKey, + #[codec(index = 1)] + DuplicatedHeartbeat, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + HeartbeatReceived { + authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + }, + #[codec(index = 1)] + AllGood, + #[codec(index = 2)] + SomeOffline { + offline: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_staking::Exposure< + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + >, + )>, + }, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedOpaqueNetworkState { + pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + pub external_addresses: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Heartbeat<_0> { + pub block_number: _0, + pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, + pub session_index: _0, + pub authority_index: _0, + pub validators_len: _0, + } + } + pub mod pallet_indices { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { index: ::core::primitive::u32 }, + #[codec(index = 1)] + transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + }, + #[codec(index = 2)] + free { index: ::core::primitive::u32 }, + #[codec(index = 3)] + force_transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + freeze: ::core::primitive::bool, + }, + #[codec(index = 4)] + freeze { index: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAssigned, + #[codec(index = 1)] + NotOwner, + #[codec(index = 2)] + InUse, + #[codec(index = 3)] + NotTransfer, + #[codec(index = 4)] + Permanent, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IndexAssigned { + who: ::sp_core::crypto::AccountId32, + index: ::core::primitive::u32, + }, + #[codec(index = 1)] + IndexFreed { index: ::core::primitive::u32 }, + #[codec(index = 2)] + IndexFrozen { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + }, + } + } + } + pub mod pallet_membership { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + remove_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + swap_member { + remove: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + add: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + reset_members { members: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 4)] + change_key { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + set_prime { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + clear_prime, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AlreadyMember, + #[codec(index = 1)] + NotMember, + #[codec(index = 2)] + TooManyMembers, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + MemberAdded, + #[codec(index = 1)] + MemberRemoved, + #[codec(index = 2)] + MembersSwapped, + #[codec(index = 3)] + MembersReset, + #[codec(index = 4)] + KeyChanged, + #[codec(index = 5)] + Dummy, + } + } + } + pub mod pallet_message_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotReapable, + #[codec(index = 1)] + NoPage, + #[codec(index = 2)] + NoMessage, + #[codec(index = 3)] + AlreadyProcessed, + #[codec(index = 4)] + Queued, + #[codec(index = 5)] + InsufficientWeight, + #[codec(index = 6)] + TemporarilyUnprocessable, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BookState<_0> { + pub begin: ::core::primitive::u32, + pub end: ::core::primitive::u32, + pub count: ::core::primitive::u32, + pub ready_neighbours: + ::core::option::Option>, + pub message_count: ::core::primitive::u64, + pub size: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Neighbours<_0> { + pub prev: _0, + pub next: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Page<_0> { + pub remaining: _0, + pub remaining_size: _0, + pub first_index: _0, + pub first: _0, + pub last: _0, + pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: _0, + } + } + pub mod pallet_nomination_pools { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + join { + #[codec(compact)] + amount: ::core::primitive::u128, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 1)] + bond_extra { + extra: runtime_types::pallet_nomination_pools::BondExtra< + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + claim_payout, + #[codec(index = 3)] + unbond { + member_account: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + unbonding_points: ::core::primitive::u128, + }, + #[codec(index = 4)] + pool_withdraw_unbonded { + pool_id: ::core::primitive::u32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 5)] + withdraw_unbonded { + member_account: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 6)] + create { + #[codec(compact)] + amount: ::core::primitive::u128, + root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 7)] + create_with_pool_id { + #[codec(compact)] + amount: ::core::primitive::u128, + root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 8)] + nominate { + pool_id: ::core::primitive::u32, + validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 9)] + set_state { + pool_id: ::core::primitive::u32, + state: runtime_types::pallet_nomination_pools::PoolState, + }, + #[codec(index = 10)] + set_metadata { + pool_id: ::core::primitive::u32, + metadata: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 11)] + set_configs { + min_join_bond: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u128, + >, + min_create_bond: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u128, + >, + max_pools: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + max_members: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + max_members_per_pool: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + global_max_commission: runtime_types::pallet_nomination_pools::ConfigOp< + runtime_types::sp_arithmetic::per_things::Perbill, + >, + }, + #[codec(index = 12)] + update_roles { + pool_id: ::core::primitive::u32, + new_root: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + new_nominator: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + new_bouncer: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 13)] + chill { pool_id: ::core::primitive::u32 }, + #[codec(index = 14)] + bond_extra_other { + member: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + extra: runtime_types::pallet_nomination_pools::BondExtra< + ::core::primitive::u128, + >, + }, + #[codec(index = 15)] + set_claim_permission { + permission: runtime_types::pallet_nomination_pools::ClaimPermission, + }, + #[codec(index = 16)] + claim_payout_other { other: ::sp_core::crypto::AccountId32 }, + #[codec(index = 17)] + set_commission { + pool_id: ::core::primitive::u32, + new_commission: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + }, + #[codec(index = 18)] + set_commission_max { + pool_id: ::core::primitive::u32, + max_commission: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 19)] + set_commission_change_rate { + pool_id: ::core::primitive::u32, + change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + }, + #[codec(index = 20)] + claim_commission { pool_id: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DefensiveError { + #[codec(index = 0)] + NotEnoughSpaceInUnbondPool, + #[codec(index = 1)] + PoolNotFound, + #[codec(index = 2)] + RewardPoolNotFound, + #[codec(index = 3)] + SubPoolsNotFound, + #[codec(index = 4)] + BondedStashKilledPrematurely, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PoolNotFound, + #[codec(index = 1)] + PoolMemberNotFound, + #[codec(index = 2)] + RewardPoolNotFound, + #[codec(index = 3)] + SubPoolsNotFound, + #[codec(index = 4)] + AccountBelongsToOtherPool, + #[codec(index = 5)] + FullyUnbonding, + #[codec(index = 6)] + MaxUnbondingLimit, + #[codec(index = 7)] + CannotWithdrawAny, + #[codec(index = 8)] + MinimumBondNotMet, + #[codec(index = 9)] + OverflowRisk, + #[codec(index = 10)] + NotDestroying, + #[codec(index = 11)] + NotNominator, + #[codec(index = 12)] + NotKickerOrDestroying, + #[codec(index = 13)] + NotOpen, + #[codec(index = 14)] + MaxPools, + #[codec(index = 15)] + MaxPoolMembers, + #[codec(index = 16)] + CanNotChangeState, + #[codec(index = 17)] + DoesNotHavePermission, + #[codec(index = 18)] + MetadataExceedsMaxLen, + #[codec(index = 19)] + Defensive(runtime_types::pallet_nomination_pools::pallet::DefensiveError), + #[codec(index = 20)] + PartialUnbondNotAllowedPermissionlessly, + #[codec(index = 21)] + MaxCommissionRestricted, + #[codec(index = 22)] + CommissionExceedsMaximum, + #[codec(index = 23)] + CommissionChangeThrottled, + #[codec(index = 24)] + CommissionChangeRateNotAllowed, + #[codec(index = 25)] + NoPendingCommission, + #[codec(index = 26)] + NoCommissionCurrentSet, + #[codec(index = 27)] + PoolIdInUse, + #[codec(index = 28)] + InvalidPoolId, + #[codec(index = 29)] + BondExtraRestricted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { + depositor: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 1)] + Bonded { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + bonded: ::core::primitive::u128, + joined: ::core::primitive::bool, + }, + #[codec(index = 2)] + PaidOut { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + payout: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unbonded { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + points: ::core::primitive::u128, + era: ::core::primitive::u32, + }, + #[codec(index = 4)] + Withdrawn { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + points: ::core::primitive::u128, + }, + #[codec(index = 5)] + Destroyed { pool_id: ::core::primitive::u32 }, + #[codec(index = 6)] + StateChanged { + pool_id: ::core::primitive::u32, + new_state: runtime_types::pallet_nomination_pools::PoolState, + }, + #[codec(index = 7)] + MemberRemoved { + pool_id: ::core::primitive::u32, + member: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + RolesUpdated { + root: ::core::option::Option<::sp_core::crypto::AccountId32>, + bouncer: ::core::option::Option<::sp_core::crypto::AccountId32>, + nominator: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 9)] + PoolSlashed { + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + }, + #[codec(index = 10)] + UnbondingPoolSlashed { + pool_id: ::core::primitive::u32, + era: ::core::primitive::u32, + balance: ::core::primitive::u128, + }, + #[codec(index = 11)] + PoolCommissionUpdated { + pool_id: ::core::primitive::u32, + current: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + }, + #[codec(index = 12)] + PoolMaxCommissionUpdated { + pool_id: ::core::primitive::u32, + max_commission: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 13)] + PoolCommissionChangeRateUpdated { + pool_id: ::core::primitive::u32, + change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + }, + #[codec(index = 14)] + PoolCommissionClaimed { + pool_id: ::core::primitive::u32, + commission: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BondExtra<_0> { + #[codec(index = 0)] + FreeBalance(_0), + #[codec(index = 1)] + Rewards, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BondedPoolInner { + pub commission: runtime_types::pallet_nomination_pools::Commission, + pub member_counter: ::core::primitive::u32, + pub points: ::core::primitive::u128, + pub roles: runtime_types::pallet_nomination_pools::PoolRoles< + ::sp_core::crypto::AccountId32, + >, + pub state: runtime_types::pallet_nomination_pools::PoolState, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ClaimPermission { + #[codec(index = 0)] + Permissioned, + #[codec(index = 1)] + PermissionlessCompound, + #[codec(index = 2)] + PermissionlessWithdraw, + #[codec(index = 3)] + PermissionlessAll, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commission { + pub current: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + pub max: ::core::option::Option, + pub change_rate: ::core::option::Option< + runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + >, + pub throttle_from: ::core::option::Option<::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommissionChangeRate<_0> { + pub max_increase: runtime_types::sp_arithmetic::per_things::Perbill, + pub min_delay: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConfigOp<_0> { + #[codec(index = 0)] + Noop, + #[codec(index = 1)] + Set(_0), + #[codec(index = 2)] + Remove, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PoolMember { + pub pool_id: ::core::primitive::u32, + pub points: ::core::primitive::u128, + pub last_recorded_reward_counter: + runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub unbonding_eras: + runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< + ::core::primitive::u32, + ::core::primitive::u128, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PoolRoles<_0> { + pub depositor: _0, + pub root: ::core::option::Option<_0>, + pub nominator: ::core::option::Option<_0>, + pub bouncer: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PoolState { + #[codec(index = 0)] + Open, + #[codec(index = 1)] + Blocked, + #[codec(index = 2)] + Destroying, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardPool { + pub last_recorded_reward_counter: + runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub last_recorded_total_payouts: ::core::primitive::u128, + pub total_rewards_claimed: ::core::primitive::u128, + pub total_commission_pending: ::core::primitive::u128, + pub total_commission_claimed: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SubPools { + pub no_era: runtime_types::pallet_nomination_pools::UnbondPool, + pub with_era: + runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< + ::core::primitive::u32, + runtime_types::pallet_nomination_pools::UnbondPool, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnbondPool { + pub points: ::core::primitive::u128, + pub balance: ::core::primitive::u128, + } + } + pub mod pallet_offences { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Offence { + kind: [::core::primitive::u8; 16usize], + timeslot: ::std::vec::Vec<::core::primitive::u8>, + }, + } + } + } + pub mod pallet_preimage { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + unnote_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + request_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 3)] + unrequest_preimage { hash: ::subxt::utils::H256 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooBig, + #[codec(index = 1)] + AlreadyNoted, + #[codec(index = 2)] + NotAuthorized, + #[codec(index = 3)] + NotNoted, + #[codec(index = 4)] + Requested, + #[codec(index = 5)] + NotRequested, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Noted { hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + Requested { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + Cleared { hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RequestStatus<_0, _1> { + #[codec(index = 0)] + Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, + #[codec(index = 1)] + Requested { + deposit: ::core::option::Option<(_0, _1)>, + count: ::core::primitive::u32, + len: ::core::option::Option<::core::primitive::u32>, + }, + } + } + pub mod pallet_proxy { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + proxy { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + add_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::polkadot_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 2)] + remove_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::polkadot_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 3)] + remove_proxies, + #[codec(index = 4)] + create_pure { + proxy_type: runtime_types::polkadot_runtime::ProxyType, + delay: ::core::primitive::u32, + index: ::core::primitive::u16, + }, + #[codec(index = 5)] + kill_pure { + spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::polkadot_runtime::ProxyType, + index: ::core::primitive::u16, + #[codec(compact)] + height: ::core::primitive::u32, + #[codec(compact)] + ext_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + announce { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 7)] + remove_announcement { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 8)] + reject_announcement { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 9)] + proxy_announced { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooMany, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotProxy, + #[codec(index = 3)] + Unproxyable, + #[codec(index = 4)] + Duplicate, + #[codec(index = 5)] + NoPermission, + #[codec(index = 6)] + Unannounced, + #[codec(index = 7)] + NoSelfProxy, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ProxyExecuted { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + PureCreated { + pure: ::sp_core::crypto::AccountId32, + who: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::polkadot_runtime::ProxyType, + disambiguation_index: ::core::primitive::u16, + }, + #[codec(index = 2)] + Announced { + real: ::sp_core::crypto::AccountId32, + proxy: ::sp_core::crypto::AccountId32, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + ProxyAdded { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::polkadot_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 4)] + ProxyRemoved { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::polkadot_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Announcement<_0, _1, _2> { + pub real: _0, + pub call_hash: _1, + pub height: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ProxyDefinition<_0, _1, _2> { + pub delegate: _0, + pub proxy_type: _1, + pub delay: _2, + } + } + pub mod pallet_referenda { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit { + proposal_origin: + ::std::boxed::Box, + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + enactment_moment: + runtime_types::frame_support::traits::schedule::DispatchTime< + ::core::primitive::u32, + >, + }, + #[codec(index = 1)] + place_decision_deposit { index: ::core::primitive::u32 }, + #[codec(index = 2)] + refund_decision_deposit { index: ::core::primitive::u32 }, + #[codec(index = 3)] + cancel { index: ::core::primitive::u32 }, + #[codec(index = 4)] + kill { index: ::core::primitive::u32 }, + #[codec(index = 5)] + nudge_referendum { index: ::core::primitive::u32 }, + #[codec(index = 6)] + one_fewer_deciding { track: ::core::primitive::u16 }, + #[codec(index = 7)] + refund_submission_deposit { index: ::core::primitive::u32 }, + #[codec(index = 8)] + set_metadata { + index: ::core::primitive::u32, + maybe_hash: ::core::option::Option<::subxt::utils::H256>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotOngoing, + #[codec(index = 1)] + HasDeposit, + #[codec(index = 2)] + BadTrack, + #[codec(index = 3)] + Full, + #[codec(index = 4)] + QueueEmpty, + #[codec(index = 5)] + BadReferendum, + #[codec(index = 6)] + NothingToDo, + #[codec(index = 7)] + NoTrack, + #[codec(index = 8)] + Unfinished, + #[codec(index = 9)] + NoPermission, + #[codec(index = 10)] + NoDeposit, + #[codec(index = 11)] + BadStatus, + #[codec(index = 12)] + PreimageNotExist, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Submitted { + index: ::core::primitive::u32, + track: ::core::primitive::u16, + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + DecisionDepositPlaced { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + DecisionDepositRefunded { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + DepositSlashed { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + DecisionStarted { + index: ::core::primitive::u32, + track: ::core::primitive::u16, + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::polkadot_runtime::RuntimeCall, + >, + tally: runtime_types::pallet_conviction_voting::types::Tally< + ::core::primitive::u128, + >, + }, + #[codec(index = 5)] + ConfirmStarted { index: ::core::primitive::u32 }, + #[codec(index = 6)] + ConfirmAborted { index: ::core::primitive::u32 }, + #[codec(index = 7)] + Confirmed { + index: ::core::primitive::u32, + tally: runtime_types::pallet_conviction_voting::types::Tally< + ::core::primitive::u128, + >, + }, + #[codec(index = 8)] + Approved { index: ::core::primitive::u32 }, + #[codec(index = 9)] + Rejected { + index: ::core::primitive::u32, + tally: runtime_types::pallet_conviction_voting::types::Tally< + ::core::primitive::u128, + >, + }, + #[codec(index = 10)] + TimedOut { + index: ::core::primitive::u32, + tally: runtime_types::pallet_conviction_voting::types::Tally< + ::core::primitive::u128, + >, + }, + #[codec(index = 11)] + Cancelled { + index: ::core::primitive::u32, + tally: runtime_types::pallet_conviction_voting::types::Tally< + ::core::primitive::u128, + >, + }, + #[codec(index = 12)] + Killed { + index: ::core::primitive::u32, + tally: runtime_types::pallet_conviction_voting::types::Tally< + ::core::primitive::u128, + >, + }, + #[codec(index = 13)] + SubmissionDepositRefunded { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + MetadataSet { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, + #[codec(index = 15)] + MetadataCleared { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Curve { + #[codec(index = 0)] + LinearDecreasing { + length: runtime_types::sp_arithmetic::per_things::Perbill, + floor: runtime_types::sp_arithmetic::per_things::Perbill, + ceil: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 1)] + SteppedDecreasing { + begin: runtime_types::sp_arithmetic::per_things::Perbill, + end: runtime_types::sp_arithmetic::per_things::Perbill, + step: runtime_types::sp_arithmetic::per_things::Perbill, + period: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 2)] + Reciprocal { + factor: runtime_types::sp_arithmetic::fixed_point::FixedI64, + x_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, + y_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DecidingStatus<_0> { + pub since: _0, + pub confirming: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Deposit<_0, _1> { + pub who: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReferendumInfo<_0, _1, _2, _3, _4, _5, _6, _7> { + #[codec(index = 0)] + Ongoing( + runtime_types::pallet_referenda::types::ReferendumStatus< + _0, + _1, + _2, + _3, + _4, + _5, + _6, + _7, + >, + ), + #[codec(index = 1)] + Approved( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 2)] + Rejected( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 3)] + Cancelled( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 4)] + TimedOut( + _2, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + ), + #[codec(index = 5)] + Killed(_2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReferendumStatus<_0, _1, _2, _3, _4, _5, _6, _7> { + pub track: _0, + pub origin: _1, + pub proposal: _3, + pub enactment: runtime_types::frame_support::traits::schedule::DispatchTime<_2>, + pub submitted: _2, + pub submission_deposit: runtime_types::pallet_referenda::types::Deposit<_6, _4>, + pub decision_deposit: ::core::option::Option< + runtime_types::pallet_referenda::types::Deposit<_6, _4>, + >, + pub deciding: ::core::option::Option< + runtime_types::pallet_referenda::types::DecidingStatus<_2>, + >, + pub tally: _5, + pub in_queue: ::core::primitive::bool, + pub alarm: ::core::option::Option<(_2, _7)>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct TrackInfo<_0, _1> { + pub name: ::std::string::String, + pub max_deciding: _1, + pub decision_deposit: _0, + pub prepare_period: _1, + pub decision_period: _1, + pub confirm_period: _1, + pub min_enactment_period: _1, + pub min_approval: runtime_types::pallet_referenda::types::Curve, + pub min_support: runtime_types::pallet_referenda::types::Curve, + } + } + } + pub mod pallet_scheduler { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + schedule { + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + schedule_named { + id: [::core::primitive::u8; 32usize], + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 3)] + cancel_named { id: [::core::primitive::u8; 32usize] }, + #[codec(index = 4)] + schedule_after { + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 5)] + schedule_named_after { + id: [::core::primitive::u8; 32usize], + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSchedule, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + TargetBlockNumberInPast, + #[codec(index = 3)] + RescheduleNoChange, + #[codec(index = 4)] + Named, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 1)] + Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + Dispatched { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + CallUnavailable { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 4)] + PeriodicFailed { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 5)] + PermanentlyOverweight { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Scheduled<_0, _1, _2, _3, _4> { + pub maybe_id: ::core::option::Option<_0>, + pub priority: ::core::primitive::u8, + pub call: _1, + pub maybe_periodic: ::core::option::Option<(_2, _2)>, + pub origin: _3, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::polkadot_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_staking { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + bond { + #[codec(compact)] + value: ::core::primitive::u128, + payee: runtime_types::pallet_staking::RewardDestination< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 1)] + bond_extra { + #[codec(compact)] + max_additional: ::core::primitive::u128, + }, + #[codec(index = 2)] + unbond { + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + withdraw_unbonded { num_slashing_spans: ::core::primitive::u32 }, + #[codec(index = 4)] + validate { prefs: runtime_types::pallet_staking::ValidatorPrefs }, + #[codec(index = 5)] + nominate { + targets: ::std::vec::Vec< + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + >, + }, + #[codec(index = 6)] + chill, + #[codec(index = 7)] + set_payee { + payee: runtime_types::pallet_staking::RewardDestination< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 8)] + set_controller, + #[codec(index = 9)] + set_validator_count { + #[codec(compact)] + new: ::core::primitive::u32, + }, + #[codec(index = 10)] + increase_validator_count { + #[codec(compact)] + additional: ::core::primitive::u32, + }, + #[codec(index = 11)] + scale_validator_count { + factor: runtime_types::sp_arithmetic::per_things::Percent, + }, + #[codec(index = 12)] + force_no_eras, + #[codec(index = 13)] + force_new_era, + #[codec(index = 14)] + set_invulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 15)] + force_unstake { + stash: ::sp_core::crypto::AccountId32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 16)] + force_new_era_always, + #[codec(index = 17)] + cancel_deferred_slash { + era: ::core::primitive::u32, + slash_indices: ::std::vec::Vec<::core::primitive::u32>, + }, + #[codec(index = 18)] + payout_stakers { + validator_stash: ::sp_core::crypto::AccountId32, + era: ::core::primitive::u32, + }, + #[codec(index = 19)] + rebond { + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 20)] + reap_stash { + stash: ::sp_core::crypto::AccountId32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 21)] + kick { + who: ::std::vec::Vec< + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + >, + }, + #[codec(index = 22)] + set_staking_configs { + min_nominator_bond: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u128, + >, + min_validator_bond: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u128, + >, + max_nominator_count: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u32, + >, + max_validator_count: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u32, + >, + chill_threshold: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + runtime_types::sp_arithmetic::per_things::Percent, + >, + min_commission: runtime_types::pallet_staking::pallet::pallet::ConfigOp< + runtime_types::sp_arithmetic::per_things::Perbill, + >, + }, + #[codec(index = 23)] + chill_other { controller: ::sp_core::crypto::AccountId32 }, + #[codec(index = 24)] + force_apply_min_commission { + validator_stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 25)] + set_min_commission { + new: runtime_types::sp_arithmetic::per_things::Perbill, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConfigOp<_0> { + #[codec(index = 0)] + Noop, + #[codec(index = 1)] + Set(_0), + #[codec(index = 2)] + Remove, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotController, + #[codec(index = 1)] + NotStash, + #[codec(index = 2)] + AlreadyBonded, + #[codec(index = 3)] + AlreadyPaired, + #[codec(index = 4)] + EmptyTargets, + #[codec(index = 5)] + DuplicateIndex, + #[codec(index = 6)] + InvalidSlashIndex, + #[codec(index = 7)] + InsufficientBond, + #[codec(index = 8)] + NoMoreChunks, + #[codec(index = 9)] + NoUnlockChunk, + #[codec(index = 10)] + FundedTarget, + #[codec(index = 11)] + InvalidEraToReward, + #[codec(index = 12)] + InvalidNumberOfNominations, + #[codec(index = 13)] + NotSortedAndUnique, + #[codec(index = 14)] + AlreadyClaimed, + #[codec(index = 15)] + IncorrectHistoryDepth, + #[codec(index = 16)] + IncorrectSlashingSpans, + #[codec(index = 17)] + BadState, + #[codec(index = 18)] + TooManyTargets, + #[codec(index = 19)] + BadTarget, + #[codec(index = 20)] + CannotChillOther, + #[codec(index = 21)] + TooManyNominators, + #[codec(index = 22)] + TooManyValidators, + #[codec(index = 23)] + CommissionTooLow, + #[codec(index = 24)] + BoundNotMet, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + EraPaid { + era_index: ::core::primitive::u32, + validator_payout: ::core::primitive::u128, + remainder: ::core::primitive::u128, + }, + #[codec(index = 1)] + Rewarded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Slashed { + staker: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + SlashReported { + validator: ::sp_core::crypto::AccountId32, + fraction: runtime_types::sp_arithmetic::per_things::Perbill, + slash_era: ::core::primitive::u32, + }, + #[codec(index = 4)] + OldSlashingReportDiscarded { session_index: ::core::primitive::u32 }, + #[codec(index = 5)] + StakersElected, + #[codec(index = 6)] + Bonded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 7)] + Unbonded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 8)] + Withdrawn { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Kicked { + nominator: ::sp_core::crypto::AccountId32, + stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 10)] + StakingElectionFailed, + #[codec(index = 11)] + Chilled { stash: ::sp_core::crypto::AccountId32 }, + #[codec(index = 12)] + PayoutStarted { + era_index: ::core::primitive::u32, + validator_stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 13)] + ValidatorPrefsSet { + stash: ::sp_core::crypto::AccountId32, + prefs: runtime_types::pallet_staking::ValidatorPrefs, + }, + #[codec(index = 14)] + ForceEra { mode: runtime_types::pallet_staking::Forcing }, + } + } + } + pub mod slashing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SlashingSpans { + pub span_index: ::core::primitive::u32, + pub last_start: ::core::primitive::u32, + pub last_nonzero_slash: ::core::primitive::u32, + pub prior: ::std::vec::Vec<::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SpanRecord<_0> { + pub slashed: _0, + pub paid_out: _0, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ActiveEraInfo { + pub index: ::core::primitive::u32, + pub start: ::core::option::Option<::core::primitive::u64>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EraRewardPoints<_0> { + pub total: ::core::primitive::u32, + pub individual: ::subxt::utils::KeyedVec<_0, ::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Exposure<_0, _1> { + #[codec(compact)] + pub total: _1, + #[codec(compact)] + pub own: _1, + pub others: + ::std::vec::Vec>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Forcing { + #[codec(index = 0)] + NotForcing, + #[codec(index = 1)] + ForceNew, + #[codec(index = 2)] + ForceNone, + #[codec(index = 3)] + ForceAlways, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndividualExposure<_0, _1> { + pub who: _0, + #[codec(compact)] + pub value: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Nominations { + pub targets: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::sp_core::crypto::AccountId32, + >, + pub submitted_in: ::core::primitive::u32, + pub suppressed: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardDestination<_0> { + #[codec(index = 0)] + Staked, + #[codec(index = 1)] + Stash, + #[codec(index = 2)] + Controller, + #[codec(index = 3)] + Account(_0), + #[codec(index = 4)] + None, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StakingLedger { + pub stash: ::sp_core::crypto::AccountId32, + #[codec(compact)] + pub total: ::core::primitive::u128, + #[codec(compact)] + pub active: ::core::primitive::u128, + pub unlocking: runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_staking::UnlockChunk<::core::primitive::u128>, + >, + pub claimed_rewards: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnappliedSlash<_0, _1> { + pub validator: _0, + pub own: _1, + pub others: ::std::vec::Vec<(_0, _1)>, + pub reporters: ::std::vec::Vec<_0>, + pub payout: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnlockChunk<_0> { + #[codec(compact)] + pub value: _0, + #[codec(compact)] + pub era: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidatorPrefs { + #[codec(compact)] + pub commission: runtime_types::sp_arithmetic::per_things::Perbill, + pub blocked: ::core::primitive::bool, + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_tips { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_awesome { + reason: ::std::vec::Vec<::core::primitive::u8>, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + retract_tip { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + tip_new { + reason: ::std::vec::Vec<::core::primitive::u8>, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + tip_value: ::core::primitive::u128, + }, + #[codec(index = 3)] + tip { + hash: ::subxt::utils::H256, + #[codec(compact)] + tip_value: ::core::primitive::u128, + }, + #[codec(index = 4)] + close_tip { hash: ::subxt::utils::H256 }, + #[codec(index = 5)] + slash_tip { hash: ::subxt::utils::H256 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ReasonTooBig, + #[codec(index = 1)] + AlreadyKnown, + #[codec(index = 2)] + UnknownTip, + #[codec(index = 3)] + NotFinder, + #[codec(index = 4)] + StillOpen, + #[codec(index = 5)] + Premature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewTip { tip_hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + TipClosing { tip_hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + TipClosed { + tip_hash: ::subxt::utils::H256, + who: ::sp_core::crypto::AccountId32, + payout: ::core::primitive::u128, + }, + #[codec(index = 3)] + TipRetracted { tip_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + TipSlashed { + tip_hash: ::subxt::utils::H256, + finder: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpenTip<_0, _1, _2, _3> { + pub reason: _3, + pub who: _0, + pub finder: _0, + pub deposit: _1, + pub closes: ::core::option::Option<_2>, + pub tips: ::std::vec::Vec<(_0, _1)>, + pub finders_fee: ::core::primitive::bool, + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_treasury { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose_spend { + #[codec(compact)] + value: ::core::primitive::u128, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + reject_proposal { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + #[codec(index = 2)] + approve_proposal { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + #[codec(index = 3)] + spend { + #[codec(compact)] + amount: ::core::primitive::u128, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + remove_approval { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InsufficientProposersBalance, + #[codec(index = 1)] + InvalidIndex, + #[codec(index = 2)] + TooManyApprovals, + #[codec(index = 3)] + InsufficientPermission, + #[codec(index = 4)] + ProposalNotApproved, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { proposal_index: ::core::primitive::u32 }, + #[codec(index = 1)] + Spending { budget_remaining: ::core::primitive::u128 }, + #[codec(index = 2)] + Awarded { + proposal_index: ::core::primitive::u32, + award: ::core::primitive::u128, + account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Rejected { + proposal_index: ::core::primitive::u32, + slashed: ::core::primitive::u128, + }, + #[codec(index = 4)] + Burnt { burnt_funds: ::core::primitive::u128 }, + #[codec(index = 5)] + Rollover { rollover_balance: ::core::primitive::u128 }, + #[codec(index = 6)] + Deposit { value: ::core::primitive::u128 }, + #[codec(index = 7)] + SpendApproved { + proposal_index: ::core::primitive::u32, + amount: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + UpdatedInactive { + reactivated: ::core::primitive::u128, + deactivated: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Proposal<_0, _1> { + pub proposer: _0, + pub value: _1, + pub beneficiary: _0, + pub bond: _1, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { calls: ::std::vec::Vec }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box, + }, + #[codec(index = 2)] + batch_all { + calls: ::std::vec::Vec, + }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box, + call: ::std::boxed::Box, + }, + #[codec(index = 4)] + force_batch { + calls: ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_vesting { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vest, + #[codec(index = 1)] + vest_other { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + vested_transfer { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 3)] + force_vested_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 4)] + merge_schedules { + schedule1_index: ::core::primitive::u32, + schedule2_index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotVesting, + #[codec(index = 1)] + AtMaxVestingSchedules, + #[codec(index = 2)] + AmountLow, + #[codec(index = 3)] + ScheduleIndexOutOfBounds, + #[codec(index = 4)] + InvalidScheduleParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + VestingUpdated { + account: ::sp_core::crypto::AccountId32, + unvested: ::core::primitive::u128, + }, + #[codec(index = 1)] + VestingCompleted { account: ::sp_core::crypto::AccountId32 }, + } + } + pub mod vesting_info { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VestingInfo<_0, _1> { + pub locked: _0, + pub per_block: _0, + pub starting_block: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V0, + #[codec(index = 1)] + V1, + } + } + pub mod pallet_whitelist { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + whitelist_call { call_hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + remove_whitelisted_call { call_hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + dispatch_whitelisted_call { + call_hash: ::subxt::utils::H256, + call_encoded_len: ::core::primitive::u32, + call_weight_witness: ::sp_weights::Weight, + }, + #[codec(index = 3)] + dispatch_whitelisted_call_with_preimage { + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnavailablePreImage, + #[codec(index = 1)] + UndecodableCall, + #[codec(index = 2)] + InvalidCallWeightWitness, + #[codec(index = 3)] + CallIsNotWhitelisted, + #[codec(index = 4)] + CallAlreadyWhitelisted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CallWhitelisted { call_hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + WhitelistedCallRemoved { call_hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + WhitelistedCallDispatched { + call_hash: ::subxt::utils::H256, + result: ::core::result::Result< + runtime_types::frame_support::dispatch::PostDispatchInfo, + runtime_types::sp_runtime::DispatchErrorWithPostInfo< + runtime_types::frame_support::dispatch::PostDispatchInfo, + >, + >, + }, + } + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: + ::std::boxed::Box, + xcm_version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted(runtime_types::xcm::v3::traits::Outcome), + #[codec(index = 1)] + Sent( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::Xcm, + ), + #[codec(index = 2)] + UnexpectedResponse( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 3)] + ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + #[codec(index = 4)] + Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + #[codec(index = 5)] + NotifyOverweight( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ::sp_weights::Weight, + ::sp_weights::Weight, + ), + #[codec(index = 6)] + NotifyDispatchError( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 7)] + NotifyDecodeFailed( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 8)] + InvalidResponder( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 9)] + InvalidResponderVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 10)] + ResponseTaken(::core::primitive::u64), + #[codec(index = 11)] + AssetsTrapped( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + #[codec(index = 12)] + VersionChangeNotified( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 13)] + SupportedVersionChanged( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + ), + #[codec(index = 14)] + NotifyTargetSendFail( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::traits::Error, + ), + #[codec(index = 15)] + NotifyTargetMigrationFail( + runtime_types::xcm::VersionedMultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 16)] + InvalidQuerierVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 17)] + InvalidQuerier( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 18)] + VersionNotifyStarted( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 19)] + VersionNotifyRequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 20)] + VersionNotifyUnrequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 21)] + FeesPaid( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 22)] + AssetsClaimed( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateHash(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelId { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub recipient: runtime_types::polkadot_parachain::primitives::Id, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCodeHash(pub ::subxt::utils::H256); + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v4 { + use super::runtime_types; + pub mod assignment_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod collator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + pub mod executor_params { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ExecutorParam { + #[codec(index = 1)] + MaxMemoryPages(::core::primitive::u32), + #[codec(index = 2)] + StackLogicalMax(::core::primitive::u32), + #[codec(index = 3)] + StackNativeMax(::core::primitive::u32), + #[codec(index = 4)] + PrecheckingMaxMemory(::core::primitive::u64), + #[codec(index = 5)] + PvfPrepTimeout( + runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 6)] + PvfExecTimeout( + runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 7)] + WasmExtBulkMemory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutorParams( + pub ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, + >, + ); + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedSigned<_0, _1> { + pub payload: _0, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + pub signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, + } + } + pub mod validator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfield( + pub ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BackedCandidate<_0> { + pub candidate: + runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, + pub validity_votes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::ValidityAttestation, + >, + pub validator_indices: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateCommitments<_0> { + pub upward_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::std::vec::Vec<::core::primitive::u8>, + >, + pub horizontal_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain::primitives::Id, + >, + >, + pub new_validation_code: ::core::option::Option< + runtime_types::polkadot_parachain::primitives::ValidationCode, + >, + pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, + pub processed_downward_messages: _0, + pub hrmp_watermark: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateDescriptor<_0> { + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub relay_parent: _0, + pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, + pub persisted_validation_data_hash: _0, + pub pov_hash: _0, + pub erasure_root: _0, + pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, + pub para_head: _0, + pub validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments_hash: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommittedCandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< + ::core::primitive::u32, + >, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct CoreIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum CoreOccupied { + #[codec(index = 0)] + Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), + #[codec(index = 1)] + Parachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeState<_0> { + pub validators_for: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub validators_against: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub start: _0, + pub concluded_at: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeStatement { + #[codec(index = 0)] + Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), + #[codec(index = 1)] + Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeStatementSet { + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub session: ::core::primitive::u32, + pub statements: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::DisputeStatement, + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Signature, + )>, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct GroupIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndexedVec<_0, _1>( + pub ::std::vec::Vec<_1>, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData<_0> { + pub bitfields: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + >, + >, + pub backed_candidates: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::BackedCandidate< + ::subxt::utils::H256, + >, + >, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + pub parent_header: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaim( + pub runtime_types::polkadot_parachain::primitives::Id, + pub runtime_types::polkadot_primitives::v4::collator_app::Public, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadEntry { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, + pub retries: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckStatement { + pub accept: ::core::primitive::bool, + pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + pub session_index: ::core::primitive::u32, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfExecTimeoutKind { + #[codec(index = 0)] + Backing, + #[codec(index = 1)] + Approval, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfPrepTimeoutKind { + #[codec(index = 0)] + Precheck, + #[codec(index = 1)] + Lenient, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ScrapedOnChainVotes<_0> { + pub session: ::core::primitive::u32, + pub backing_validators_per_candidate: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, + ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::ValidityAttestation, + )>, + )>, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionInfo { + pub active_validator_indices: + ::std::vec::Vec, + pub random_seed: [::core::primitive::u8; 32usize], + pub dispute_period: ::core::primitive::u32, + pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub discovery_keys: + ::std::vec::Vec, + pub assignment_keys: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::assignment_app::Public, + >, + pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::GroupIndex, + ::std::vec::Vec, + >, + pub n_cores: ::core::primitive::u32, + pub zeroth_delay_tranche_width: ::core::primitive::u32, + pub relay_vrf_modulo_samples: ::core::primitive::u32, + pub n_delay_tranches: ::core::primitive::u32, + pub no_show_slots: ::core::primitive::u32, + pub needed_approvals: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + #[codec(index = 1)] + BackingSeconded(::subxt::utils::H256), + #[codec(index = 2)] + BackingValid(::subxt::utils::H256), + #[codec(index = 3)] + ApprovalChecking, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ValidatorIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidityAttestation { + #[codec(index = 1)] + Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + #[codec(index = 2)] + Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + } + } + pub mod vstaging { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + } + pub mod polkadot_runtime { + use super::runtime_types; + pub mod governance { + use super::runtime_types; + pub mod origins { + use super::runtime_types; + pub mod pallet_custom_origins { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Origin { + #[codec(index = 0)] + StakingAdmin, + #[codec(index = 1)] + Treasurer, + #[codec(index = 2)] + FellowshipAdmin, + #[codec(index = 3)] + GeneralAdmin, + #[codec(index = 4)] + AuctionAdmin, + #[codec(index = 5)] + LeaseAdmin, + #[codec(index = 6)] + ReferendumCanceller, + #[codec(index = 7)] + ReferendumKiller, + #[codec(index = 8)] + SmallTipper, + #[codec(index = 9)] + BigTipper, + #[codec(index = 10)] + SmallSpender, + #[codec(index = 11)] + MediumSpender, + #[codec(index = 12)] + BigSpender, + #[codec(index = 13)] + WhitelistedCaller, + } + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct NposCompactSolution16 { + pub votes1: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes2: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + ( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ), + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes3: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 2usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes4: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 3usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes5: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 4usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes6: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 5usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes7: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 6usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes8: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 7usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes9: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 8usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes10: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 9usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes11: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 10usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes12: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 11usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes13: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 12usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes14: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 13usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes15: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 14usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes16: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 15usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + # [codec (index = 0)] system (runtime_types :: frame_support :: dispatch :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 15)] Council (runtime_types :: pallet_collective :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 16)] TechnicalCommittee (runtime_types :: pallet_collective :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 22)] Origins (runtime_types :: polkadot_runtime :: governance :: origins :: pallet_custom_origins :: Origin ,) , # [codec (index = 50)] ParachainsOrigin (runtime_types :: polkadot_runtime_parachains :: origin :: pallet :: Origin ,) , # [codec (index = 99)] XcmPallet (runtime_types :: pallet_xcm :: pallet :: Origin ,) , # [codec (index = 6)] Void (runtime_types :: sp_core :: Void ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProxyType { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + NonTransfer, + #[codec(index = 2)] + Governance, + #[codec(index = 3)] + Staking, + #[codec(index = 5)] + IdentityJudgement, + #[codec(index = 6)] + CancelProxy, + #[codec(index = 7)] + Auction, + #[codec(index = 8)] + NominationPools, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + Scheduler(runtime_types::pallet_scheduler::pallet::Call), + #[codec(index = 10)] + Preimage(runtime_types::pallet_preimage::pallet::Call), + #[codec(index = 2)] + Babe(runtime_types::pallet_babe::pallet::Call), + #[codec(index = 3)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 4)] + Indices(runtime_types::pallet_indices::pallet::Call), + #[codec(index = 5)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 7)] + Staking(runtime_types::pallet_staking::pallet::pallet::Call), + #[codec(index = 9)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 11)] + Grandpa(runtime_types::pallet_grandpa::pallet::Call), + #[codec(index = 12)] + ImOnline(runtime_types::pallet_im_online::pallet::Call), + #[codec(index = 14)] + Democracy(runtime_types::pallet_democracy::pallet::Call), + #[codec(index = 15)] + Council(runtime_types::pallet_collective::pallet::Call), + #[codec(index = 16)] + TechnicalCommittee(runtime_types::pallet_collective::pallet::Call), + #[codec(index = 17)] + PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Call), + #[codec(index = 18)] + TechnicalMembership(runtime_types::pallet_membership::pallet::Call), + #[codec(index = 19)] + Treasury(runtime_types::pallet_treasury::pallet::Call), + #[codec(index = 20)] + ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Call), + #[codec(index = 21)] + Referenda(runtime_types::pallet_referenda::pallet::Call), + #[codec(index = 23)] + Whitelist(runtime_types::pallet_whitelist::pallet::Call), + #[codec(index = 24)] + Claims(runtime_types::polkadot_runtime_common::claims::pallet::Call), + #[codec(index = 25)] + Vesting(runtime_types::pallet_vesting::pallet::Call), + #[codec(index = 26)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 28)] + Identity(runtime_types::pallet_identity::pallet::Call), + #[codec(index = 29)] + Proxy(runtime_types::pallet_proxy::pallet::Call), + #[codec(index = 30)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 34)] + Bounties(runtime_types::pallet_bounties::pallet::Call), + #[codec(index = 38)] + ChildBounties(runtime_types::pallet_child_bounties::pallet::Call), + #[codec(index = 35)] + Tips(runtime_types::pallet_tips::pallet::Call), + #[codec(index = 36)] + ElectionProviderMultiPhase( + runtime_types::pallet_election_provider_multi_phase::pallet::Call, + ), + #[codec(index = 37)] + VoterList(runtime_types::pallet_bags_list::pallet::Call), + #[codec(index = 39)] + NominationPools(runtime_types::pallet_nomination_pools::pallet::Call), + #[codec(index = 40)] + FastUnstake(runtime_types::pallet_fast_unstake::pallet::Call), + #[codec(index = 51)] + Configuration( + runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, + ), + #[codec(index = 52)] + ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), + #[codec(index = 53)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), + #[codec(index = 54)] + ParaInherent( + runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, + ), + #[codec(index = 56)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), + #[codec(index = 57)] + Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), + #[codec(index = 60)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), + #[codec(index = 62)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), + #[codec(index = 63)] + ParasSlashing( + runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, + ), + #[codec(index = 70)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), + #[codec(index = 71)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), + #[codec(index = 72)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), + #[codec(index = 73)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 100)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 1)] + Scheduler(runtime_types::pallet_scheduler::pallet::Event), + #[codec(index = 10)] + Preimage(runtime_types::pallet_preimage::pallet::Event), + #[codec(index = 4)] + Indices(runtime_types::pallet_indices::pallet::Event), + #[codec(index = 5)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 32)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 7)] + Staking(runtime_types::pallet_staking::pallet::pallet::Event), + #[codec(index = 8)] + Offences(runtime_types::pallet_offences::pallet::Event), + #[codec(index = 9)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 11)] + Grandpa(runtime_types::pallet_grandpa::pallet::Event), + #[codec(index = 12)] + ImOnline(runtime_types::pallet_im_online::pallet::Event), + #[codec(index = 14)] + Democracy(runtime_types::pallet_democracy::pallet::Event), + #[codec(index = 15)] + Council(runtime_types::pallet_collective::pallet::Event), + #[codec(index = 16)] + TechnicalCommittee(runtime_types::pallet_collective::pallet::Event), + #[codec(index = 17)] + PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Event), + #[codec(index = 18)] + TechnicalMembership(runtime_types::pallet_membership::pallet::Event), + #[codec(index = 19)] + Treasury(runtime_types::pallet_treasury::pallet::Event), + #[codec(index = 20)] + ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Event), + #[codec(index = 21)] + Referenda(runtime_types::pallet_referenda::pallet::Event), + #[codec(index = 23)] + Whitelist(runtime_types::pallet_whitelist::pallet::Event), + #[codec(index = 24)] + Claims(runtime_types::polkadot_runtime_common::claims::pallet::Event), + #[codec(index = 25)] + Vesting(runtime_types::pallet_vesting::pallet::Event), + #[codec(index = 26)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 28)] + Identity(runtime_types::pallet_identity::pallet::Event), + #[codec(index = 29)] + Proxy(runtime_types::pallet_proxy::pallet::Event), + #[codec(index = 30)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 34)] + Bounties(runtime_types::pallet_bounties::pallet::Event), + #[codec(index = 38)] + ChildBounties(runtime_types::pallet_child_bounties::pallet::Event), + #[codec(index = 35)] + Tips(runtime_types::pallet_tips::pallet::Event), + #[codec(index = 36)] + ElectionProviderMultiPhase( + runtime_types::pallet_election_provider_multi_phase::pallet::Event, + ), + #[codec(index = 37)] + VoterList(runtime_types::pallet_bags_list::pallet::Event), + #[codec(index = 39)] + NominationPools(runtime_types::pallet_nomination_pools::pallet::Event), + #[codec(index = 40)] + FastUnstake(runtime_types::pallet_fast_unstake::pallet::Event), + #[codec(index = 53)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), + #[codec(index = 56)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), + #[codec(index = 60)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), + #[codec(index = 62)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), + #[codec(index = 70)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), + #[codec(index = 71)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), + #[codec(index = 72)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), + #[codec(index = 73)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 100)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, + pub babe: runtime_types::sp_consensus_babe::app::Public, + pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, + pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, + pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, + } + } + pub mod polkadot_runtime_common { + use super::runtime_types; + pub mod auctions { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + new_auction { + #[codec(compact)] + duration: ::core::primitive::u32, + #[codec(compact)] + lease_period_index: ::core::primitive::u32, + }, + #[codec(index = 1)] + bid { + #[codec(compact)] + para: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + auction_index: ::core::primitive::u32, + #[codec(compact)] + first_slot: ::core::primitive::u32, + #[codec(compact)] + last_slot: ::core::primitive::u32, + #[codec(compact)] + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + cancel_auction, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AuctionInProgress, + #[codec(index = 1)] + LeasePeriodInPast, + #[codec(index = 2)] + ParaNotRegistered, + #[codec(index = 3)] + NotCurrentAuction, + #[codec(index = 4)] + NotAuction, + #[codec(index = 5)] + AuctionEnded, + #[codec(index = 6)] + AlreadyLeasedOut, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + AuctionStarted { + auction_index: ::core::primitive::u32, + lease_period: ::core::primitive::u32, + ending: ::core::primitive::u32, + }, + #[codec(index = 1)] + AuctionClosed { auction_index: ::core::primitive::u32 }, + #[codec(index = 2)] + Reserved { + bidder: ::sp_core::crypto::AccountId32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unreserved { + bidder: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + ReserveConfiscated { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + BidAccepted { + bidder: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + first_slot: ::core::primitive::u32, + last_slot: ::core::primitive::u32, + }, + #[codec(index = 6)] + WinningOffset { + auction_index: ::core::primitive::u32, + block_number: ::core::primitive::u32, + }, + } + } + } + pub mod claims { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { + dest: ::sp_core::crypto::AccountId32, + ethereum_signature: + runtime_types::polkadot_runtime_common::claims::EcdsaSignature, + }, + #[codec(index = 1)] + mint_claim { + who: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + value: ::core::primitive::u128, + vesting_schedule: ::core::option::Option<( + ::core::primitive::u128, + ::core::primitive::u128, + ::core::primitive::u32, + )>, + statement: ::core::option::Option< + runtime_types::polkadot_runtime_common::claims::StatementKind, + >, + }, + #[codec(index = 2)] + claim_attest { + dest: ::sp_core::crypto::AccountId32, + ethereum_signature: + runtime_types::polkadot_runtime_common::claims::EcdsaSignature, + statement: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 3)] + attest { statement: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + move_claim { + old: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + new: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + maybe_preclaim: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEthereumSignature, + #[codec(index = 1)] + SignerHasNoClaim, + #[codec(index = 2)] + SenderHasNoClaim, + #[codec(index = 3)] + PotUnderflow, + #[codec(index = 4)] + InvalidStatement, + #[codec(index = 5)] + VestedBalanceExists, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Claimed { + who: ::sp_core::crypto::AccountId32, + ethereum_address: + runtime_types::polkadot_runtime_common::claims::EthereumAddress, + amount: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EcdsaSignature(pub [::core::primitive::u8; 65usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EthereumAddress(pub [::core::primitive::u8; 20usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PrevalidateAttests; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StatementKind { + #[codec(index = 0)] + Regular, + #[codec(index = 1)] + Saft, + } + } + pub mod crowdloan { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + create { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 1)] + contribute { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + value: ::core::primitive::u128, + signature: + ::core::option::Option, + }, + #[codec(index = 2)] + withdraw { + who: ::sp_core::crypto::AccountId32, + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 3)] + refund { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + dissolve { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + edit { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 6)] + add_memo { + index: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 7)] + poke { index: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + contribute_all { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + signature: + ::core::option::Option, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FirstPeriodInPast, + #[codec(index = 1)] + FirstPeriodTooFarInFuture, + #[codec(index = 2)] + LastPeriodBeforeFirstPeriod, + #[codec(index = 3)] + LastPeriodTooFarInFuture, + #[codec(index = 4)] + CannotEndInPast, + #[codec(index = 5)] + EndTooFarInFuture, + #[codec(index = 6)] + Overflow, + #[codec(index = 7)] + ContributionTooSmall, + #[codec(index = 8)] + InvalidParaId, + #[codec(index = 9)] + CapExceeded, + #[codec(index = 10)] + ContributionPeriodOver, + #[codec(index = 11)] + InvalidOrigin, + #[codec(index = 12)] + NotParachain, + #[codec(index = 13)] + LeaseActive, + #[codec(index = 14)] + BidOrLeaseActive, + #[codec(index = 15)] + FundNotEnded, + #[codec(index = 16)] + NoContributions, + #[codec(index = 17)] + NotReadyToDissolve, + #[codec(index = 18)] + InvalidSignature, + #[codec(index = 19)] + MemoTooLarge, + #[codec(index = 20)] + AlreadyInNewRaise, + #[codec(index = 21)] + VrfDelayInProgress, + #[codec(index = 22)] + NoLeasePeriod, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 1)] + Contributed { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Withdrew { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + PartiallyRefunded { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 6)] + HandleBidResult { + para_id: runtime_types::polkadot_parachain::primitives::Id, + result: ::core::result::Result< + (), + runtime_types::sp_runtime::DispatchError, + >, + }, + #[codec(index = 7)] + Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + MemoUpdated { + who: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 9)] + AddedToNewRaise { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FundInfo<_0, _1, _2, _3> { + pub depositor: _0, + pub verifier: ::core::option::Option, + pub deposit: _1, + pub raised: _1, + pub end: _2, + pub cap: _1, + pub last_contribution: + runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, + pub first_period: _2, + pub last_period: _2, + pub fund_index: _2, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum LastContribution<_0> { + #[codec(index = 0)] + Never, + #[codec(index = 1)] + PreEnding(_0), + #[codec(index = 2)] + Ending(_0), + } + } + pub mod paras_registrar { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register { + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_register { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 2)] + deregister { id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 3)] + swap { + id: runtime_types::polkadot_parachain::primitives::Id, + other: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + reserve, + #[codec(index = 6)] + add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 7)] + schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 8)] + set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + AlreadyRegistered, + #[codec(index = 2)] + NotOwner, + #[codec(index = 3)] + CodeTooLarge, + #[codec(index = 4)] + HeadDataTooLarge, + #[codec(index = 5)] + NotParachain, + #[codec(index = 6)] + NotParathread, + #[codec(index = 7)] + CannotDeregister, + #[codec(index = 8)] + CannotDowngrade, + #[codec(index = 9)] + CannotUpgrade, + #[codec(index = 10)] + ParaLocked, + #[codec(index = 11)] + NotReserved, + #[codec(index = 12)] + EmptyCode, + #[codec(index = 13)] + CannotSwap, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Registered { + para_id: runtime_types::polkadot_parachain::primitives::Id, + manager: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 1)] + Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + Reserved { + para_id: runtime_types::polkadot_parachain::primitives::Id, + who: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Swapped { + para_id: runtime_types::polkadot_parachain::primitives::Id, + other_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo<_0, _1> { + pub manager: _0, + pub deposit: _1, + pub locked: ::core::primitive::bool, + } + } + pub mod slots { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_lease { + para: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + }, + #[codec(index = 1)] + clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaNotOnboarding, + #[codec(index = 1)] + LeaseError, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewLeasePeriod { lease_period: ::core::primitive::u32 }, + #[codec(index = 1)] + Leased { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + } + } + } + } + pub mod polkadot_runtime_parachains { + use super::runtime_types; + pub mod configuration { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidNewValue, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HostConfiguration<_0> { + pub max_code_size: _0, + pub max_head_data_size: _0, + pub max_upward_queue_count: _0, + pub max_upward_queue_size: _0, + pub max_upward_message_size: _0, + pub max_upward_message_num_per_candidate: _0, + pub hrmp_max_message_num_per_candidate: _0, + pub validation_upgrade_cooldown: _0, + pub validation_upgrade_delay: _0, + pub async_backing_params: + runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, + pub max_pov_size: _0, + pub max_downward_message_size: _0, + pub hrmp_max_parachain_outbound_channels: _0, + pub hrmp_max_parathread_outbound_channels: _0, + pub hrmp_sender_deposit: ::core::primitive::u128, + pub hrmp_recipient_deposit: ::core::primitive::u128, + pub hrmp_channel_max_capacity: _0, + pub hrmp_channel_max_total_size: _0, + pub hrmp_max_parachain_inbound_channels: _0, + pub hrmp_max_parathread_inbound_channels: _0, + pub hrmp_channel_max_message_size: _0, + pub executor_params: + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, + pub code_retention_period: _0, + pub parathread_cores: _0, + pub parathread_retries: _0, + pub group_rotation_frequency: _0, + pub chain_availability_period: _0, + pub thread_availability_period: _0, + pub scheduling_lookahead: _0, + pub max_validators_per_core: ::core::option::Option<_0>, + pub max_validators: ::core::option::Option<_0>, + pub dispute_period: _0, + pub dispute_post_conclusion_acceptance_period: _0, + pub no_show_slots: _0, + pub n_delay_tranches: _0, + pub zeroth_delay_tranche_width: _0, + pub needed_approvals: _0, + pub relay_vrf_modulo_samples: _0, + pub pvf_checking_enabled: ::core::primitive::bool, + pub pvf_voting_ttl: _0, + pub minimum_validation_upgrade_delay: _0, + } + } + pub mod disputes { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_unfreeze, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateDisputeStatementSets, + #[codec(index = 1)] + AncientDisputeStatement, + #[codec(index = 2)] + ValidatorIndexOutOfBounds, + #[codec(index = 3)] + InvalidSignature, + #[codec(index = 4)] + DuplicateStatement, + #[codec(index = 5)] + SingleSidedDispute, + #[codec(index = 6)] + MaliciousBacker, + #[codec(index = 7)] + MissingBackingVotes, + #[codec(index = 8)] + UnconfirmedDispute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + DisputeInitiated( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, + ), + #[codec(index = 1)] + DisputeConcluded( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, + ), + #[codec(index = 2)] + Revert(::core::primitive::u32), + } + } + pub mod slashing { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Call { + # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Error { + #[codec(index = 0)] + InvalidKeyOwnershipProof, + #[codec(index = 1)] + InvalidSessionIndex, + #[codec(index = 2)] + InvalidCandidateHash, + #[codec(index = 3)] + InvalidValidatorIndex, + #[codec(index = 4)] + ValidatorIndexIdMismatch, + #[codec(index = 5)] + DuplicateSlashingReport, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputesTimeSlot { + pub session_index: ::core::primitive::u32, + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SlashingOffenceKind { + #[codec(index = 0)] + ForInvalid, + #[codec(index = 1)] + AgainstValid, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeLocation { + #[codec(index = 0)] + Local, + #[codec(index = 1)] + Remote, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeResult { + #[codec(index = 0)] + Valid, + #[codec(index = 1)] + Invalid, + } + } + pub mod hrmp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + hrmp_init_open_channel { + recipient: runtime_types::polkadot_parachain::primitives::Id, + proposed_max_capacity: ::core::primitive::u32, + proposed_max_message_size: ::core::primitive::u32, + }, + #[codec(index = 1)] + hrmp_accept_open_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 2)] + hrmp_close_channel { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + }, + #[codec(index = 3)] + force_clean_hrmp { + para: runtime_types::polkadot_parachain::primitives::Id, + inbound: ::core::primitive::u32, + outbound: ::core::primitive::u32, + }, + #[codec(index = 4)] + force_process_hrmp_open { channels: ::core::primitive::u32 }, + #[codec(index = 5)] + force_process_hrmp_close { channels: ::core::primitive::u32 }, + #[codec(index = 6)] + hrmp_cancel_open_request { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + open_requests: ::core::primitive::u32, + }, + #[codec(index = 7)] + force_open_hrmp_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + recipient: runtime_types::polkadot_parachain::primitives::Id, + max_capacity: ::core::primitive::u32, + max_message_size: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OpenHrmpChannelToSelf, + #[codec(index = 1)] + OpenHrmpChannelInvalidRecipient, + #[codec(index = 2)] + OpenHrmpChannelZeroCapacity, + #[codec(index = 3)] + OpenHrmpChannelCapacityExceedsLimit, + #[codec(index = 4)] + OpenHrmpChannelZeroMessageSize, + #[codec(index = 5)] + OpenHrmpChannelMessageSizeExceedsLimit, + #[codec(index = 6)] + OpenHrmpChannelAlreadyExists, + #[codec(index = 7)] + OpenHrmpChannelAlreadyRequested, + #[codec(index = 8)] + OpenHrmpChannelLimitExceeded, + #[codec(index = 9)] + AcceptHrmpChannelDoesntExist, + #[codec(index = 10)] + AcceptHrmpChannelAlreadyConfirmed, + #[codec(index = 11)] + AcceptHrmpChannelLimitExceeded, + #[codec(index = 12)] + CloseHrmpChannelUnauthorized, + #[codec(index = 13)] + CloseHrmpChannelDoesntExist, + #[codec(index = 14)] + CloseHrmpChannelAlreadyUnderway, + #[codec(index = 15)] + CancelHrmpOpenChannelUnauthorized, + #[codec(index = 16)] + OpenHrmpChannelDoesntExist, + #[codec(index = 17)] + OpenHrmpChannelAlreadyConfirmed, + #[codec(index = 18)] + WrongWitness, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + OpenChannelRequested( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + #[codec(index = 1)] + OpenChannelCanceled( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 2)] + OpenChannelAccepted( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 3)] + ChannelClosed( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 4)] + HrmpChannelForceOpened( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + pub sender_deposit: ::core::primitive::u128, + pub recipient_deposit: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpOpenChannelRequest { + pub confirmed: ::core::primitive::bool, + pub _age: ::core::primitive::u32, + pub sender_deposit: ::core::primitive::u128, + pub max_message_size: ::core::primitive::u32, + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + } + } + pub mod inclusion { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnsortedOrDuplicateValidatorIndices, + #[codec(index = 1)] + UnsortedOrDuplicateDisputeStatementSet, + #[codec(index = 2)] + UnsortedOrDuplicateBackedCandidates, + #[codec(index = 3)] + UnexpectedRelayParent, + #[codec(index = 4)] + WrongBitfieldSize, + #[codec(index = 5)] + BitfieldAllZeros, + #[codec(index = 6)] + BitfieldDuplicateOrUnordered, + #[codec(index = 7)] + ValidatorIndexOutOfBounds, + #[codec(index = 8)] + InvalidBitfieldSignature, + #[codec(index = 9)] + UnscheduledCandidate, + #[codec(index = 10)] + CandidateScheduledBeforeParaFree, + #[codec(index = 11)] + WrongCollator, + #[codec(index = 12)] + ScheduledOutOfOrder, + #[codec(index = 13)] + HeadDataTooLarge, + #[codec(index = 14)] + PrematureCodeUpgrade, + #[codec(index = 15)] + NewCodeTooLarge, + #[codec(index = 16)] + CandidateNotInParentContext, + #[codec(index = 17)] + InvalidGroupIndex, + #[codec(index = 18)] + InsufficientBacking, + #[codec(index = 19)] + InvalidBacking, + #[codec(index = 20)] + NotCollatorSigned, + #[codec(index = 21)] + ValidationDataHashMismatch, + #[codec(index = 22)] + IncorrectDownwardMessageHandling, + #[codec(index = 23)] + InvalidUpwardMessages, + #[codec(index = 24)] + HrmpWatermarkMishandling, + #[codec(index = 25)] + InvalidOutboundHrmp, + #[codec(index = 26)] + InvalidValidationCodeHash, + #[codec(index = 27)] + ParaHeadMismatch, + #[codec(index = 28)] + BitfieldReferencesFreedCore, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CandidateBacked( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 1)] + CandidateIncluded( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 2)] + CandidateTimedOut( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + ), + #[codec(index = 3)] + UpwardMessagesReceived { + from: runtime_types::polkadot_parachain::primitives::Id, + count: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfieldRecord<_0> { + pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + pub submitted_at: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidatePendingAvailability<_0, _1> { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub availability_votes: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub backers: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub relay_parent_number: _1, + pub backed_in_number: _1, + pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UmpQueueId { + #[codec(index = 0)] + Para(runtime_types::polkadot_parachain::primitives::Id), + } + } + pub mod initializer { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_approve { up_to: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BufferedSessionChange { + pub validators: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub queued: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub session_index: ::core::primitive::u32, + } + } + pub mod origin { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Parachain(runtime_types::polkadot_parachain::primitives::Id), + } + } + } + pub mod paras { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_set_current_code { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 2)] + force_schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + relay_parent_number: ::core::primitive::u32, + }, + #[codec(index = 3)] + force_note_new_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 4)] + force_queue_action { + para: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + add_trusted_validation_code { + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 6)] + poke_unused_validation_code { + validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + }, + #[codec(index = 7)] + include_pvf_check_statement { + stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, + signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + CannotOnboard, + #[codec(index = 2)] + CannotOffboard, + #[codec(index = 3)] + CannotUpgrade, + #[codec(index = 4)] + CannotDowngrade, + #[codec(index = 5)] + PvfCheckStatementStale, + #[codec(index = 6)] + PvfCheckStatementFuture, + #[codec(index = 7)] + PvfCheckValidatorIndexOutOfBounds, + #[codec(index = 8)] + PvfCheckInvalidSignature, + #[codec(index = 9)] + PvfCheckDoubleVote, + #[codec(index = 10)] + PvfCheckSubjectInvalid, + #[codec(index = 11)] + CannotUpgradeCode, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 2)] + CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 3)] + NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 4)] + ActionQueued( + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ), + #[codec(index = 5)] + PvfCheckStarted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 6)] + PvfCheckAccepted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 7)] + PvfCheckRejected( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaGenesisArgs { + pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + pub para_kind: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ParaLifecycle { + #[codec(index = 0)] + Onboarding, + #[codec(index = 1)] + Parathread, + #[codec(index = 2)] + Parachain, + #[codec(index = 3)] + UpgradingParathread, + #[codec(index = 4)] + DowngradingParachain, + #[codec(index = 5)] + OffboardingParathread, + #[codec(index = 6)] + OffboardingParachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaPastCodeMeta<_0> { + pub upgrade_times: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, + >, + pub last_pruned: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckActiveVoteState<_0> { + pub votes_accept: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub votes_reject: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub age: _0, + pub created_at: _0, + pub causes: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfCheckCause<_0> { + #[codec(index = 0)] + Onboarding(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + Upgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + relay_parent_number: _0, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReplacementTimes<_0> { + pub expected_at: _0, + pub activated_at: _0, + } + } + pub mod paras_inherent { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + enter { + data: runtime_types::polkadot_primitives::v4::InherentData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyInclusionInherents, + #[codec(index = 1)] + InvalidParentHeader, + #[codec(index = 2)] + CandidateConcludedInvalid, + #[codec(index = 3)] + InherentOverweight, + #[codec(index = 4)] + DisputeStatementsUnsortedOrDuplicates, + #[codec(index = 5)] + DisputeInvalid, + } + } + } + pub mod scheduler { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssignmentKind { + #[codec(index = 0)] + Parachain, + #[codec(index = 1)] + Parathread( + runtime_types::polkadot_primitives::v4::collator_app::Public, + ::core::primitive::u32, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CoreAssignment { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, + pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaimQueue { + pub queue: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, + >, + pub next_core_offset: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueuedParathread { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, + pub core_offset: ::core::primitive::u32, + } + } + pub mod shared { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FixedI64(pub ::core::primitive::i64); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + pub mod per_things { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct PerU16(pub ::core::primitive::u16); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Perbill(pub ::core::primitive::u32); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Percent(pub ::core::primitive::u8); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Permill(pub ::core::primitive::u32); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_authority_discovery { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + pub mod sp_consensus_babe { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod digests { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NextConfigDescriptor { + #[codec(index = 1)] + V1 { + c: (::core::primitive::u64, ::core::primitive::u64), + allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PreDigest { + #[codec(index = 1)] + Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), + #[codec(index = 2)] + SecondaryPlain( + runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, + ), + #[codec(index = 3)] + SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PrimaryPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryPlainPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryVRFPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AllowedSlots { + #[codec(index = 0)] + PrimarySlots, + #[codec(index = 1)] + PrimaryAndSecondaryPlainSlots, + #[codec(index = 2)] + PrimaryAndSecondaryVRFSlots, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BabeEpochConfiguration { + pub c: (::core::primitive::u64, ::core::primitive::u64), + pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Equivocation<_0, _1> { + #[codec(index = 0)] + Prevote( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Prevote<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + #[codec(index = 1)] + Precommit( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Precommit<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EquivocationProof<_0, _1> { + pub offender: _1, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub first_header: _0, + pub second_header: _0, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 33usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod offchain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueNetworkState { + pub peer_id: runtime_types::sp_core::OpaquePeerId, + pub external_addresses: + ::std::vec::Vec, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod vrf { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VrfSignature { + pub output: [::core::primitive::u8; 32usize], + pub proof: [::core::primitive::u8; 64usize], + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_npos_elections { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ElectionScore { + pub minimal_stake: ::core::primitive::u128, + pub sum_stake: ::core::primitive::u128, + pub sum_stake_squared: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Support<_0> { + pub total: ::core::primitive::u128, + pub voters: ::std::vec::Vec<(_0, ::core::primitive::u128)>, + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, + ); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchErrorWithPostInfo<_0> { + pub post_info: _0, + pub error: runtime_types::sp_runtime::DispatchError, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSigner { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Public), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Public), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Public), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_staking { + use super::runtime_types; + pub mod offence { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OffenceDetails<_0, _1> { + pub offender: _1, + pub reporters: ::std::vec::Vec<_0>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + } + } +} diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 6e39f985c6301..4181b6dcff773 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,21 +16,36 @@ //! Types used to connect to the Polkadot chain. +mod codegen_runtime; + use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; +use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, + RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::storage::StorageKey; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use sp_session::MembershipProof; use std::time::Duration; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::polkadot_runtime::RuntimeCall; + +pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; + /// Polkadot header id. pub type HeaderId = relay_utils::HeaderId; /// Polkadot header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; +/// The address format for describing accounts. +pub type Address = MultiAddress; + /// Polkadot chain definition #[derive(Debug, Clone, Copy)] pub struct Polkadot; @@ -47,7 +62,7 @@ impl Chain for Polkadot { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); type SignedBlock = bp_polkadot::SignedBlock; - type Call = (); + type Call = RuntimeCall; } impl ChainWithGrandpa for Polkadot { @@ -67,3 +82,54 @@ impl RelayChain for Polkadot { const PARAS_PALLET_NAME: &'static str = bp_polkadot::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgePolkadotParachain"; } + +impl ChainWithTransactions for Polkadot { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = + bp_polkadot_core::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_polkadot::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ((), ()), + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(Self::SignedTransaction::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs index e8d31ee83c33b..b6617b90f137e 100644 --- a/relays/client-rialto-parachain/src/lib.rs +++ b/relays/client-rialto-parachain/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_cumulus::BridgeHubSignedExtension; use bp_messages::MessageNonce; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ @@ -98,6 +98,7 @@ impl ChainWithTransactions for RialtoParachain { param.genesis_hash, unsigned.nonce, unsigned.tip, + (((), ()), ((), ())), ), )?; diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index cc5371612c346..94d8c24d95105 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -25,9 +25,8 @@ use relay_substrate_client::{ ChainWithTransactions, Error as SubstrateError, NonceOf, RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::{storage::StorageKey, Pair}; +use sp_core::{storage::StorageKey, Pair, Void}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use sp_session::MembershipProof; use std::time::Duration; /// Rialto header id. @@ -56,7 +55,7 @@ impl ChainWithGrandpa for Rialto { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - type KeyOwnerProof = MembershipProof; + type KeyOwnerProof = Void; } impl RelayChain for Rialto { diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index c569ab4f27efd..fac1e74a7c8b6 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -6,15 +6,23 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +subxt = { version = "0.31.0", default-features = false, features = ["native"] } # Bridge dependencies +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + # Substrate Dependencies +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-rococo/src/codegen_runtime.rs b/relays/client-rococo/src/codegen_runtime.rs new file mode 100644 index 0000000000000..959812b11ba02 --- /dev/null +++ b/relays/client-rococo/src/codegen_runtime.rs @@ -0,0 +1,7441 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://rococo-rpc.polkadot.io:443 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Equivocation<_0, _1, _2> { + pub round_number: ::core::primitive::u64, + pub identity: _0, + pub first: (_1, _2), + pub second: (_1, _2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Prevote<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProcessMessageError { + #[codec(index = 0)] + BadFormat, + #[codec(index = 1)] + Corrupt, + #[codec(index = 2)] + Unsupported, + #[codec(index = 3)] + Overweight(::sp_weights::Weight), + #[codec(index = 4)] + Yield, + } + } + pub mod misc { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WrapperOpaque<_0>( + #[codec(compact)] pub ::core::primitive::u32, + pub _0, + ); + } + pub mod preimages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Bounded<_0> { + #[codec(index = 0)] + Legacy { + hash: ::subxt::utils::H256, + }, + #[codec(index = 1)] + Inline( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Lookup { + hash: ::subxt::utils::H256, + len: ::core::primitive::u32, + }, + __Ignore(::core::marker::PhantomData<_0>), + } + } + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletId(pub [::core::primitive::u8; 8usize]); + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_babe { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + plan_config_change { + config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEquivocationProof, + #[codec(index = 1)] + InvalidKeyOwnershipProof, + #[codec(index = 2)] + DuplicateOffenceReport, + #[codec(index = 3)] + InvalidConfiguration, + } + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + set_balance_deprecated { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + #[codec(compact)] + old_reserved: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 7)] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_beefy { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_beefy::EquivocationProof< + ::core::primitive::u32, + runtime_types::sp_consensus_beefy::crypto::Public, + runtime_types::sp_consensus_beefy::crypto::Signature, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_beefy::EquivocationProof< + ::core::primitive::u32, + runtime_types::sp_consensus_beefy::crypto::Public, + runtime_types::sp_consensus_beefy::crypto::Signature, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidKeyOwnershipProof, + #[codec(index = 1)] + InvalidEquivocationProof, + #[codec(index = 2)] + DuplicateOffenceReport, + } + } + } + pub mod pallet_bounties { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose_bounty { + #[codec(compact)] + value: ::core::primitive::u128, + description: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + approve_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 2)] + propose_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 3)] + unassign_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 4)] + accept_curator { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 5)] + award_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + claim_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 7)] + close_bounty { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + }, + #[codec(index = 8)] + extend_bounty_expiry { + #[codec(compact)] + bounty_id: ::core::primitive::u32, + remark: ::std::vec::Vec<::core::primitive::u8>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InsufficientProposersBalance, + #[codec(index = 1)] + InvalidIndex, + #[codec(index = 2)] + ReasonTooBig, + #[codec(index = 3)] + UnexpectedStatus, + #[codec(index = 4)] + RequireCurator, + #[codec(index = 5)] + InvalidValue, + #[codec(index = 6)] + InvalidFee, + #[codec(index = 7)] + PendingPayout, + #[codec(index = 8)] + Premature, + #[codec(index = 9)] + HasActiveChildBounty, + #[codec(index = 10)] + TooManyQueued, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BountyProposed { index: ::core::primitive::u32 }, + #[codec(index = 1)] + BountyRejected { index: ::core::primitive::u32, bond: ::core::primitive::u128 }, + #[codec(index = 2)] + BountyBecameActive { index: ::core::primitive::u32 }, + #[codec(index = 3)] + BountyAwarded { + index: ::core::primitive::u32, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 4)] + BountyClaimed { + index: ::core::primitive::u32, + payout: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 5)] + BountyCanceled { index: ::core::primitive::u32 }, + #[codec(index = 6)] + BountyExtended { index: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bounty<_0, _1, _2> { + pub proposer: _0, + pub value: _1, + pub fee: _1, + pub curator_deposit: _1, + pub bond: _1, + pub status: runtime_types::pallet_bounties::BountyStatus<_0, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BountyStatus<_0, _1> { + #[codec(index = 0)] + Proposed, + #[codec(index = 1)] + Approved, + #[codec(index = 2)] + Funded, + #[codec(index = 3)] + CuratorProposed { curator: _0 }, + #[codec(index = 4)] + Active { curator: _0, update_due: _1 }, + #[codec(index = 5)] + PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, + } + } + pub mod pallet_child_bounties { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + value: ::core::primitive::u128, + description: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + propose_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 2)] + accept_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 3)] + unassign_curator { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 4)] + award_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + claim_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + #[codec(index = 6)] + close_child_bounty { + #[codec(compact)] + parent_bounty_id: ::core::primitive::u32, + #[codec(compact)] + child_bounty_id: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParentBountyNotActive, + #[codec(index = 1)] + InsufficientBountyBalance, + #[codec(index = 2)] + TooManyChildBounties, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Added { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, + #[codec(index = 1)] + Awarded { + index: ::core::primitive::u32, + child_index: ::core::primitive::u32, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 2)] + Claimed { + index: ::core::primitive::u32, + child_index: ::core::primitive::u32, + payout: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Canceled { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChildBounty<_0, _1, _2> { + pub parent_bounty: _2, + pub value: _1, + pub fee: _1, + pub curator_deposit: _1, + pub status: runtime_types::pallet_child_bounties::ChildBountyStatus<_0, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ChildBountyStatus<_0, _1> { + #[codec(index = 0)] + Added, + #[codec(index = 1)] + CuratorProposed { curator: _0 }, + #[codec(index = 2)] + Active { curator: _0 }, + #[codec(index = 3)] + PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, + } + } + pub mod pallet_collective { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_members { + new_members: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + prime: ::core::option::Option<::sp_core::crypto::AccountId32>, + old_count: ::core::primitive::u32, + }, + #[codec(index = 1)] + execute { + proposal: ::std::boxed::Box, + #[codec(compact)] + length_bound: ::core::primitive::u32, + }, + #[codec(index = 2)] + propose { + #[codec(compact)] + threshold: ::core::primitive::u32, + proposal: ::std::boxed::Box, + #[codec(compact)] + length_bound: ::core::primitive::u32, + }, + #[codec(index = 3)] + vote { + proposal: ::subxt::utils::H256, + #[codec(compact)] + index: ::core::primitive::u32, + approve: ::core::primitive::bool, + }, + #[codec(index = 5)] + disapprove_proposal { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 6)] + close { + proposal_hash: ::subxt::utils::H256, + #[codec(compact)] + index: ::core::primitive::u32, + proposal_weight_bound: ::sp_weights::Weight, + #[codec(compact)] + length_bound: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotMember, + #[codec(index = 1)] + DuplicateProposal, + #[codec(index = 2)] + ProposalMissing, + #[codec(index = 3)] + WrongIndex, + #[codec(index = 4)] + DuplicateVote, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooEarly, + #[codec(index = 7)] + TooManyProposals, + #[codec(index = 8)] + WrongProposalWeight, + #[codec(index = 9)] + WrongProposalLength, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { + account: ::sp_core::crypto::AccountId32, + proposal_index: ::core::primitive::u32, + proposal_hash: ::subxt::utils::H256, + threshold: ::core::primitive::u32, + }, + #[codec(index = 1)] + Voted { + account: ::sp_core::crypto::AccountId32, + proposal_hash: ::subxt::utils::H256, + voted: ::core::primitive::bool, + yes: ::core::primitive::u32, + no: ::core::primitive::u32, + }, + #[codec(index = 2)] + Approved { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 3)] + Disapproved { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + Executed { + proposal_hash: ::subxt::utils::H256, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 5)] + MemberExecuted { + proposal_hash: ::subxt::utils::H256, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 6)] + Closed { + proposal_hash: ::subxt::utils::H256, + yes: ::core::primitive::u32, + no: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Members(::core::primitive::u32, ::core::primitive::u32), + #[codec(index = 1)] + Member(_0), + #[codec(index = 2)] + _Phantom, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Votes<_0, _1> { + pub index: _1, + pub threshold: _1, + pub ayes: ::std::vec::Vec<_0>, + pub nays: ::std::vec::Vec<_0>, + pub end: _1, + } + } + pub mod pallet_democracy { + use super::runtime_types; + pub mod conviction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Conviction { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Locked1x, + #[codec(index = 2)] + Locked2x, + #[codec(index = 3)] + Locked3x, + #[codec(index = 4)] + Locked4x, + #[codec(index = 5)] + Locked5x, + #[codec(index = 6)] + Locked6x, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::rococo_runtime::RuntimeCall, + >, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + second { + #[codec(compact)] + proposal: ::core::primitive::u32, + }, + #[codec(index = 2)] + vote { + #[codec(compact)] + ref_index: ::core::primitive::u32, + vote: runtime_types::pallet_democracy::vote::AccountVote< + ::core::primitive::u128, + >, + }, + #[codec(index = 3)] + emergency_cancel { ref_index: ::core::primitive::u32 }, + #[codec(index = 4)] + external_propose { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::rococo_runtime::RuntimeCall, + >, + }, + #[codec(index = 5)] + external_propose_majority { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::rococo_runtime::RuntimeCall, + >, + }, + #[codec(index = 6)] + external_propose_default { + proposal: runtime_types::frame_support::traits::preimages::Bounded< + runtime_types::rococo_runtime::RuntimeCall, + >, + }, + #[codec(index = 7)] + fast_track { + proposal_hash: ::subxt::utils::H256, + voting_period: ::core::primitive::u32, + delay: ::core::primitive::u32, + }, + #[codec(index = 8)] + veto_external { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 9)] + cancel_referendum { + #[codec(compact)] + ref_index: ::core::primitive::u32, + }, + #[codec(index = 10)] + delegate { + to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + conviction: runtime_types::pallet_democracy::conviction::Conviction, + balance: ::core::primitive::u128, + }, + #[codec(index = 11)] + undelegate, + #[codec(index = 12)] + clear_public_proposals, + #[codec(index = 13)] + unlock { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 14)] + remove_vote { index: ::core::primitive::u32 }, + #[codec(index = 15)] + remove_other_vote { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + }, + #[codec(index = 16)] + blacklist { + proposal_hash: ::subxt::utils::H256, + maybe_ref_index: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 17)] + cancel_proposal { + #[codec(compact)] + prop_index: ::core::primitive::u32, + }, + #[codec(index = 18)] + set_metadata { + owner: runtime_types::pallet_democracy::types::MetadataOwner, + maybe_hash: ::core::option::Option<::subxt::utils::H256>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ValueLow, + #[codec(index = 1)] + ProposalMissing, + #[codec(index = 2)] + AlreadyCanceled, + #[codec(index = 3)] + DuplicateProposal, + #[codec(index = 4)] + ProposalBlacklisted, + #[codec(index = 5)] + NotSimpleMajority, + #[codec(index = 6)] + InvalidHash, + #[codec(index = 7)] + NoProposal, + #[codec(index = 8)] + AlreadyVetoed, + #[codec(index = 9)] + ReferendumInvalid, + #[codec(index = 10)] + NoneWaiting, + #[codec(index = 11)] + NotVoter, + #[codec(index = 12)] + NoPermission, + #[codec(index = 13)] + AlreadyDelegating, + #[codec(index = 14)] + InsufficientFunds, + #[codec(index = 15)] + NotDelegating, + #[codec(index = 16)] + VotesExist, + #[codec(index = 17)] + InstantNotAllowed, + #[codec(index = 18)] + Nonsense, + #[codec(index = 19)] + WrongUpperBound, + #[codec(index = 20)] + MaxVotesReached, + #[codec(index = 21)] + TooMany, + #[codec(index = 22)] + VotingPeriodLow, + #[codec(index = 23)] + PreimageNotExist, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { + proposal_index: ::core::primitive::u32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 1)] + Tabled { + proposal_index: ::core::primitive::u32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 2)] + ExternalTabled, + #[codec(index = 3)] + Started { + ref_index: ::core::primitive::u32, + threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, + }, + #[codec(index = 4)] + Passed { ref_index: ::core::primitive::u32 }, + #[codec(index = 5)] + NotPassed { ref_index: ::core::primitive::u32 }, + #[codec(index = 6)] + Cancelled { ref_index: ::core::primitive::u32 }, + #[codec(index = 7)] + Delegated { + who: ::sp_core::crypto::AccountId32, + target: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + Undelegated { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 9)] + Vetoed { + who: ::sp_core::crypto::AccountId32, + proposal_hash: ::subxt::utils::H256, + until: ::core::primitive::u32, + }, + #[codec(index = 10)] + Blacklisted { proposal_hash: ::subxt::utils::H256 }, + #[codec(index = 11)] + Voted { + voter: ::sp_core::crypto::AccountId32, + ref_index: ::core::primitive::u32, + vote: runtime_types::pallet_democracy::vote::AccountVote< + ::core::primitive::u128, + >, + }, + #[codec(index = 12)] + Seconded { + seconder: ::sp_core::crypto::AccountId32, + prop_index: ::core::primitive::u32, + }, + #[codec(index = 13)] + ProposalCanceled { prop_index: ::core::primitive::u32 }, + #[codec(index = 14)] + MetadataSet { + owner: runtime_types::pallet_democracy::types::MetadataOwner, + hash: ::subxt::utils::H256, + }, + #[codec(index = 15)] + MetadataCleared { + owner: runtime_types::pallet_democracy::types::MetadataOwner, + hash: ::subxt::utils::H256, + }, + #[codec(index = 16)] + MetadataTransferred { + prev_owner: runtime_types::pallet_democracy::types::MetadataOwner, + owner: runtime_types::pallet_democracy::types::MetadataOwner, + hash: ::subxt::utils::H256, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Delegations<_0> { + pub votes: _0, + pub capital: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MetadataOwner { + #[codec(index = 0)] + External, + #[codec(index = 1)] + Proposal(::core::primitive::u32), + #[codec(index = 2)] + Referendum(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReferendumInfo<_0, _1, _2> { + #[codec(index = 0)] + Ongoing(runtime_types::pallet_democracy::types::ReferendumStatus<_0, _1, _2>), + #[codec(index = 1)] + Finished { approved: ::core::primitive::bool, end: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReferendumStatus<_0, _1, _2> { + pub end: _0, + pub proposal: _1, + pub threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, + pub delay: _0, + pub tally: runtime_types::pallet_democracy::types::Tally<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Tally<_0> { + pub ayes: _0, + pub nays: _0, + pub turnout: _0, + } + } + pub mod vote { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AccountVote<_0> { + #[codec(index = 0)] + Standard { vote: runtime_types::pallet_democracy::vote::Vote, balance: _0 }, + #[codec(index = 1)] + Split { aye: _0, nay: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PriorLock<_0, _1>(pub _0, pub _1); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Vote(pub ::core::primitive::u8); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Voting<_0, _1, _2> { + #[codec(index = 0)] + Direct { + votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _2, + runtime_types::pallet_democracy::vote::AccountVote<_0>, + )>, + delegations: runtime_types::pallet_democracy::types::Delegations<_0>, + prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, + }, + #[codec(index = 1)] + Delegating { + balance: _0, + target: _1, + conviction: runtime_types::pallet_democracy::conviction::Conviction, + delegations: runtime_types::pallet_democracy::types::Delegations<_0>, + prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, + }, + } + } + pub mod vote_threshold { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VoteThreshold { + #[codec(index = 0)] + SuperMajorityApprove, + #[codec(index = 1)] + SuperMajorityAgainst, + #[codec(index = 2)] + SimpleMajority, + } + } + } + pub mod pallet_elections_phragmen { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vote { + votes: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + remove_voter, + #[codec(index = 2)] + submit_candidacy { + #[codec(compact)] + candidate_count: ::core::primitive::u32, + }, + #[codec(index = 3)] + renounce_candidacy { + renouncing: runtime_types::pallet_elections_phragmen::Renouncing, + }, + #[codec(index = 4)] + remove_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + slash_bond: ::core::primitive::bool, + rerun_election: ::core::primitive::bool, + }, + #[codec(index = 5)] + clean_defunct_voters { + num_voters: ::core::primitive::u32, + num_defunct: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnableToVote, + #[codec(index = 1)] + NoVotes, + #[codec(index = 2)] + TooManyVotes, + #[codec(index = 3)] + MaximumVotesExceeded, + #[codec(index = 4)] + LowBalance, + #[codec(index = 5)] + UnableToPayBond, + #[codec(index = 6)] + MustBeVoter, + #[codec(index = 7)] + DuplicatedCandidate, + #[codec(index = 8)] + TooManyCandidates, + #[codec(index = 9)] + MemberSubmit, + #[codec(index = 10)] + RunnerUpSubmit, + #[codec(index = 11)] + InsufficientCandidateFunds, + #[codec(index = 12)] + NotMember, + #[codec(index = 13)] + InvalidWitnessData, + #[codec(index = 14)] + InvalidVoteCount, + #[codec(index = 15)] + InvalidRenouncing, + #[codec(index = 16)] + InvalidReplacement, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewTerm { + new_members: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + )>, + }, + #[codec(index = 1)] + EmptyTerm, + #[codec(index = 2)] + ElectionError, + #[codec(index = 3)] + MemberKicked { member: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + Renounced { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + CandidateSlashed { + candidate: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + SeatHolderSlashed { + seat_holder: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Renouncing { + #[codec(index = 0)] + Member, + #[codec(index = 1)] + RunnerUp, + #[codec(index = 2)] + Candidate(#[codec(compact)] ::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SeatHolder<_0, _1> { + pub who: _0, + pub stake: _1, + pub deposit: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Voter<_0, _1> { + pub votes: ::std::vec::Vec<_0>, + pub stake: _1, + pub deposit: _1, + } + } + pub mod pallet_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + note_stalled { + delay: ::core::primitive::u32, + best_finalized_block_number: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PauseFailed, + #[codec(index = 1)] + ResumeFailed, + #[codec(index = 2)] + ChangePending, + #[codec(index = 3)] + TooSoon, + #[codec(index = 4)] + InvalidKeyOwnershipProof, + #[codec(index = 5)] + InvalidEquivocationProof, + #[codec(index = 6)] + DuplicateOffenceReport, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewAuthorities { + authority_set: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + }, + #[codec(index = 1)] + Paused, + #[codec(index = 2)] + Resumed, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredPendingChange<_0> { + pub scheduled_at: _0, + pub delay: _0, + pub next_authorities: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub forced: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StoredState<_0> { + #[codec(index = 0)] + Live, + #[codec(index = 1)] + PendingPause { scheduled_at: _0, delay: _0 }, + #[codec(index = 2)] + Paused, + #[codec(index = 3)] + PendingResume { scheduled_at: _0, delay: _0 }, + } + } + pub mod pallet_identity { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_registrar { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + set_identity { + info: + ::std::boxed::Box, + }, + #[codec(index = 2)] + set_subs { + subs: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_identity::types::Data, + )>, + }, + #[codec(index = 3)] + clear_identity, + #[codec(index = 4)] + request_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + #[codec(compact)] + max_fee: ::core::primitive::u128, + }, + #[codec(index = 5)] + cancel_request { reg_index: ::core::primitive::u32 }, + #[codec(index = 6)] + set_fee { + #[codec(compact)] + index: ::core::primitive::u32, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 7)] + set_account_id { + #[codec(compact)] + index: ::core::primitive::u32, + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 8)] + set_fields { + #[codec(compact)] + index: ::core::primitive::u32, + fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + }, + #[codec(index = 9)] + provide_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + judgement: runtime_types::pallet_identity::types::Judgement< + ::core::primitive::u128, + >, + identity: ::subxt::utils::H256, + }, + #[codec(index = 10)] + kill_identity { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 11)] + add_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 12)] + rename_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 13)] + remove_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 14)] + quit_sub, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManySubAccounts, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotNamed, + #[codec(index = 3)] + EmptyIndex, + #[codec(index = 4)] + FeeChanged, + #[codec(index = 5)] + NoIdentity, + #[codec(index = 6)] + StickyJudgement, + #[codec(index = 7)] + JudgementGiven, + #[codec(index = 8)] + InvalidJudgement, + #[codec(index = 9)] + InvalidIndex, + #[codec(index = 10)] + InvalidTarget, + #[codec(index = 11)] + TooManyFields, + #[codec(index = 12)] + TooManyRegistrars, + #[codec(index = 13)] + AlreadyClaimed, + #[codec(index = 14)] + NotSub, + #[codec(index = 15)] + NotOwned, + #[codec(index = 16)] + JudgementForDifferentIdentity, + #[codec(index = 17)] + JudgementPaymentFailed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IdentitySet { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + IdentityCleared { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 2)] + IdentityKilled { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 3)] + JudgementRequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 4)] + JudgementUnrequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 5)] + JudgementGiven { + target: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + RegistrarAdded { registrar_index: ::core::primitive::u32 }, + #[codec(index = 7)] + SubIdentityAdded { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 8)] + SubIdentityRemoved { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 9)] + SubIdentityRevoked { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct BitFlags<_0>( + pub ::core::primitive::u64, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Data { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Raw0([::core::primitive::u8; 0usize]), + #[codec(index = 2)] + Raw1([::core::primitive::u8; 1usize]), + #[codec(index = 3)] + Raw2([::core::primitive::u8; 2usize]), + #[codec(index = 4)] + Raw3([::core::primitive::u8; 3usize]), + #[codec(index = 5)] + Raw4([::core::primitive::u8; 4usize]), + #[codec(index = 6)] + Raw5([::core::primitive::u8; 5usize]), + #[codec(index = 7)] + Raw6([::core::primitive::u8; 6usize]), + #[codec(index = 8)] + Raw7([::core::primitive::u8; 7usize]), + #[codec(index = 9)] + Raw8([::core::primitive::u8; 8usize]), + #[codec(index = 10)] + Raw9([::core::primitive::u8; 9usize]), + #[codec(index = 11)] + Raw10([::core::primitive::u8; 10usize]), + #[codec(index = 12)] + Raw11([::core::primitive::u8; 11usize]), + #[codec(index = 13)] + Raw12([::core::primitive::u8; 12usize]), + #[codec(index = 14)] + Raw13([::core::primitive::u8; 13usize]), + #[codec(index = 15)] + Raw14([::core::primitive::u8; 14usize]), + #[codec(index = 16)] + Raw15([::core::primitive::u8; 15usize]), + #[codec(index = 17)] + Raw16([::core::primitive::u8; 16usize]), + #[codec(index = 18)] + Raw17([::core::primitive::u8; 17usize]), + #[codec(index = 19)] + Raw18([::core::primitive::u8; 18usize]), + #[codec(index = 20)] + Raw19([::core::primitive::u8; 19usize]), + #[codec(index = 21)] + Raw20([::core::primitive::u8; 20usize]), + #[codec(index = 22)] + Raw21([::core::primitive::u8; 21usize]), + #[codec(index = 23)] + Raw22([::core::primitive::u8; 22usize]), + #[codec(index = 24)] + Raw23([::core::primitive::u8; 23usize]), + #[codec(index = 25)] + Raw24([::core::primitive::u8; 24usize]), + #[codec(index = 26)] + Raw25([::core::primitive::u8; 25usize]), + #[codec(index = 27)] + Raw26([::core::primitive::u8; 26usize]), + #[codec(index = 28)] + Raw27([::core::primitive::u8; 27usize]), + #[codec(index = 29)] + Raw28([::core::primitive::u8; 28usize]), + #[codec(index = 30)] + Raw29([::core::primitive::u8; 29usize]), + #[codec(index = 31)] + Raw30([::core::primitive::u8; 30usize]), + #[codec(index = 32)] + Raw31([::core::primitive::u8; 31usize]), + #[codec(index = 33)] + Raw32([::core::primitive::u8; 32usize]), + #[codec(index = 34)] + BlakeTwo256([::core::primitive::u8; 32usize]), + #[codec(index = 35)] + Sha256([::core::primitive::u8; 32usize]), + #[codec(index = 36)] + Keccak256([::core::primitive::u8; 32usize]), + #[codec(index = 37)] + ShaThree256([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum IdentityField { + #[codec(index = 1)] + Display, + #[codec(index = 2)] + Legal, + #[codec(index = 4)] + Web, + #[codec(index = 8)] + Riot, + #[codec(index = 16)] + Email, + #[codec(index = 32)] + PgpFingerprint, + #[codec(index = 64)] + Image, + #[codec(index = 128)] + Twitter, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdentityInfo { + pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::pallet_identity::types::Data, + runtime_types::pallet_identity::types::Data, + )>, + pub display: runtime_types::pallet_identity::types::Data, + pub legal: runtime_types::pallet_identity::types::Data, + pub web: runtime_types::pallet_identity::types::Data, + pub riot: runtime_types::pallet_identity::types::Data, + pub email: runtime_types::pallet_identity::types::Data, + pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, + pub image: runtime_types::pallet_identity::types::Data, + pub twitter: runtime_types::pallet_identity::types::Data, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Judgement<_0> { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + FeePaid(_0), + #[codec(index = 2)] + Reasonable, + #[codec(index = 3)] + KnownGood, + #[codec(index = 4)] + OutOfDate, + #[codec(index = 5)] + LowQuality, + #[codec(index = 6)] + Erroneous, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RegistrarInfo<_0, _1> { + pub account: _1, + pub fee: _0, + pub fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0> { + pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::core::primitive::u32, + runtime_types::pallet_identity::types::Judgement<_0>, + )>, + pub deposit: _0, + pub info: runtime_types::pallet_identity::types::IdentityInfo, + } + } + } + pub mod pallet_im_online { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + heartbeat { + heartbeat: + runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, + signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidKey, + #[codec(index = 1)] + DuplicatedHeartbeat, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + HeartbeatReceived { + authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + }, + #[codec(index = 1)] + AllGood, + #[codec(index = 2)] + SomeOffline { offline: ::std::vec::Vec<(::sp_core::crypto::AccountId32, ())> }, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedOpaqueNetworkState { + pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + pub external_addresses: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Heartbeat<_0> { + pub block_number: _0, + pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, + pub session_index: _0, + pub authority_index: _0, + pub validators_len: _0, + } + } + pub mod pallet_indices { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { index: ::core::primitive::u32 }, + #[codec(index = 1)] + transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + }, + #[codec(index = 2)] + free { index: ::core::primitive::u32 }, + #[codec(index = 3)] + force_transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + freeze: ::core::primitive::bool, + }, + #[codec(index = 4)] + freeze { index: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAssigned, + #[codec(index = 1)] + NotOwner, + #[codec(index = 2)] + InUse, + #[codec(index = 3)] + NotTransfer, + #[codec(index = 4)] + Permanent, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IndexAssigned { + who: ::sp_core::crypto::AccountId32, + index: ::core::primitive::u32, + }, + #[codec(index = 1)] + IndexFreed { index: ::core::primitive::u32 }, + #[codec(index = 2)] + IndexFrozen { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + }, + } + } + } + pub mod pallet_membership { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + remove_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + swap_member { + remove: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + add: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + reset_members { members: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 4)] + change_key { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + set_prime { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + clear_prime, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AlreadyMember, + #[codec(index = 1)] + NotMember, + #[codec(index = 2)] + TooManyMembers, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + MemberAdded, + #[codec(index = 1)] + MemberRemoved, + #[codec(index = 2)] + MembersSwapped, + #[codec(index = 3)] + MembersReset, + #[codec(index = 4)] + KeyChanged, + #[codec(index = 5)] + Dummy, + } + } + } + pub mod pallet_message_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotReapable, + #[codec(index = 1)] + NoPage, + #[codec(index = 2)] + NoMessage, + #[codec(index = 3)] + AlreadyProcessed, + #[codec(index = 4)] + Queued, + #[codec(index = 5)] + InsufficientWeight, + #[codec(index = 6)] + TemporarilyUnprocessable, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BookState<_0> { + pub begin: ::core::primitive::u32, + pub end: ::core::primitive::u32, + pub count: ::core::primitive::u32, + pub ready_neighbours: + ::core::option::Option>, + pub message_count: ::core::primitive::u64, + pub size: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Neighbours<_0> { + pub prev: _0, + pub next: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Page<_0> { + pub remaining: _0, + pub remaining_size: _0, + pub first_index: _0, + pub first: _0, + pub last: _0, + pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: _0, + } + } + pub mod pallet_nis { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bid<_0, _1> { + pub amount: _0, + pub who: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + place_bid { + #[codec(compact)] + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 1)] + retract_bid { + #[codec(compact)] + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 2)] + fund_deficit, + #[codec(index = 3)] + thaw_private { + #[codec(compact)] + index: ::core::primitive::u32, + maybe_proportion: ::core::option::Option< + runtime_types::sp_arithmetic::per_things::Perquintill, + >, + }, + #[codec(index = 4)] + thaw_communal { + #[codec(compact)] + index: ::core::primitive::u32, + }, + #[codec(index = 5)] + communify { + #[codec(compact)] + index: ::core::primitive::u32, + }, + #[codec(index = 6)] + privatize { + #[codec(compact)] + index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DurationTooSmall, + #[codec(index = 1)] + DurationTooBig, + #[codec(index = 2)] + AmountTooSmall, + #[codec(index = 3)] + BidTooLow, + #[codec(index = 4)] + UnknownReceipt, + #[codec(index = 5)] + NotOwner, + #[codec(index = 6)] + NotExpired, + #[codec(index = 7)] + UnknownBid, + #[codec(index = 8)] + PortionTooBig, + #[codec(index = 9)] + Unfunded, + #[codec(index = 10)] + AlreadyFunded, + #[codec(index = 11)] + Throttled, + #[codec(index = 12)] + MakesDust, + #[codec(index = 13)] + AlreadyCommunal, + #[codec(index = 14)] + AlreadyPrivate, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BidPlaced { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 1)] + BidRetracted { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 2)] + BidDropped { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + duration: ::core::primitive::u32, + }, + #[codec(index = 3)] + Issued { + index: ::core::primitive::u32, + expiry: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + proportion: runtime_types::sp_arithmetic::per_things::Perquintill, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + Thawed { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + proportion: runtime_types::sp_arithmetic::per_things::Perquintill, + amount: ::core::primitive::u128, + dropped: ::core::primitive::bool, + }, + #[codec(index = 5)] + Funded { deficit: ::core::primitive::u128 }, + #[codec(index = 6)] + Transferred { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HoldReason { + #[codec(index = 0)] + NftReceipt, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceiptRecord<_0, _1, _2> { + pub proportion: runtime_types::sp_arithmetic::per_things::Perquintill, + pub owner: ::core::option::Option<(_0, _2)>, + pub expiry: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SummaryRecord<_0, _1> { + pub proportion_owed: runtime_types::sp_arithmetic::per_things::Perquintill, + pub index: _0, + pub thawed: runtime_types::sp_arithmetic::per_things::Perquintill, + pub last_period: _0, + pub receipts_on_hold: _1, + } + } + } + pub mod pallet_offences { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Offence { + kind: [::core::primitive::u8; 16usize], + timeslot: ::std::vec::Vec<::core::primitive::u8>, + }, + } + } + } + pub mod pallet_preimage { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + unnote_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + request_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 3)] + unrequest_preimage { hash: ::subxt::utils::H256 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooBig, + #[codec(index = 1)] + AlreadyNoted, + #[codec(index = 2)] + NotAuthorized, + #[codec(index = 3)] + NotNoted, + #[codec(index = 4)] + Requested, + #[codec(index = 5)] + NotRequested, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Noted { hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + Requested { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + Cleared { hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RequestStatus<_0, _1> { + #[codec(index = 0)] + Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, + #[codec(index = 1)] + Requested { + deposit: ::core::option::Option<(_0, _1)>, + count: ::core::primitive::u32, + len: ::core::option::Option<::core::primitive::u32>, + }, + } + } + pub mod pallet_proxy { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + proxy { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + add_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::rococo_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 2)] + remove_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::rococo_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 3)] + remove_proxies, + #[codec(index = 4)] + create_pure { + proxy_type: runtime_types::rococo_runtime::ProxyType, + delay: ::core::primitive::u32, + index: ::core::primitive::u16, + }, + #[codec(index = 5)] + kill_pure { + spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::rococo_runtime::ProxyType, + index: ::core::primitive::u16, + #[codec(compact)] + height: ::core::primitive::u32, + #[codec(compact)] + ext_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + announce { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 7)] + remove_announcement { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 8)] + reject_announcement { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 9)] + proxy_announced { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooMany, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotProxy, + #[codec(index = 3)] + Unproxyable, + #[codec(index = 4)] + Duplicate, + #[codec(index = 5)] + NoPermission, + #[codec(index = 6)] + Unannounced, + #[codec(index = 7)] + NoSelfProxy, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ProxyExecuted { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + PureCreated { + pure: ::sp_core::crypto::AccountId32, + who: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::rococo_runtime::ProxyType, + disambiguation_index: ::core::primitive::u16, + }, + #[codec(index = 2)] + Announced { + real: ::sp_core::crypto::AccountId32, + proxy: ::sp_core::crypto::AccountId32, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + ProxyAdded { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::rococo_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 4)] + ProxyRemoved { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::rococo_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Announcement<_0, _1, _2> { + pub real: _0, + pub call_hash: _1, + pub height: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ProxyDefinition<_0, _1, _2> { + pub delegate: _0, + pub proxy_type: _1, + pub delay: _2, + } + } + pub mod pallet_recovery { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_recovered { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + set_recovered { + lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + create_recovery { + friends: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + threshold: ::core::primitive::u16, + delay_period: ::core::primitive::u32, + }, + #[codec(index = 3)] + initiate_recovery { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + vouch_recovery { + lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + claim_recovery { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + close_recovery { + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 7)] + remove_recovery, + #[codec(index = 8)] + cancel_recovered { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAllowed, + #[codec(index = 1)] + ZeroThreshold, + #[codec(index = 2)] + NotEnoughFriends, + #[codec(index = 3)] + MaxFriends, + #[codec(index = 4)] + NotSorted, + #[codec(index = 5)] + NotRecoverable, + #[codec(index = 6)] + AlreadyRecoverable, + #[codec(index = 7)] + AlreadyStarted, + #[codec(index = 8)] + NotStarted, + #[codec(index = 9)] + NotFriend, + #[codec(index = 10)] + DelayPeriod, + #[codec(index = 11)] + AlreadyVouched, + #[codec(index = 12)] + Threshold, + #[codec(index = 13)] + StillActive, + #[codec(index = 14)] + AlreadyProxy, + #[codec(index = 15)] + BadState, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RecoveryCreated { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + RecoveryInitiated { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 2)] + RecoveryVouched { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + sender: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + RecoveryClosed { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 4)] + AccountRecovered { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 5)] + RecoveryRemoved { lost_account: ::sp_core::crypto::AccountId32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ActiveRecovery<_0, _1, _2> { + pub created: _0, + pub deposit: _1, + pub friends: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RecoveryConfig<_0, _1, _2> { + pub delay_period: _0, + pub deposit: _1, + pub friends: _2, + pub threshold: ::core::primitive::u16, + } + } + pub mod pallet_scheduler { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + schedule { + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + schedule_named { + id: [::core::primitive::u8; 32usize], + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 3)] + cancel_named { id: [::core::primitive::u8; 32usize] }, + #[codec(index = 4)] + schedule_after { + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 5)] + schedule_named_after { + id: [::core::primitive::u8; 32usize], + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSchedule, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + TargetBlockNumberInPast, + #[codec(index = 3)] + RescheduleNoChange, + #[codec(index = 4)] + Named, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 1)] + Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + Dispatched { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + CallUnavailable { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 4)] + PeriodicFailed { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 5)] + PermanentlyOverweight { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Scheduled<_0, _1, _2, _3, _4> { + pub maybe_id: ::core::option::Option<_0>, + pub priority: ::core::primitive::u8, + pub call: _1, + pub maybe_periodic: ::core::option::Option<(_2, _2)>, + pub origin: _3, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::rococo_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_society { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + bid { value: ::core::primitive::u128 }, + #[codec(index = 1)] + unbid { pos: ::core::primitive::u32 }, + #[codec(index = 2)] + vouch { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + value: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + #[codec(index = 3)] + unvouch { pos: ::core::primitive::u32 }, + #[codec(index = 4)] + vote { + candidate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + approve: ::core::primitive::bool, + }, + #[codec(index = 5)] + defender_vote { approve: ::core::primitive::bool }, + #[codec(index = 6)] + payout, + #[codec(index = 7)] + found { + founder: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + max_members: ::core::primitive::u32, + rules: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 8)] + unfound, + #[codec(index = 9)] + judge_suspended_member { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + forgive: ::core::primitive::bool, + }, + #[codec(index = 10)] + judge_suspended_candidate { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + judgement: runtime_types::pallet_society::Judgement, + }, + #[codec(index = 11)] + set_max_members { max: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + BadPosition, + #[codec(index = 1)] + NotMember, + #[codec(index = 2)] + AlreadyMember, + #[codec(index = 3)] + Suspended, + #[codec(index = 4)] + NotSuspended, + #[codec(index = 5)] + NoPayout, + #[codec(index = 6)] + AlreadyFounded, + #[codec(index = 7)] + InsufficientPot, + #[codec(index = 8)] + AlreadyVouching, + #[codec(index = 9)] + NotVouching, + #[codec(index = 10)] + Head, + #[codec(index = 11)] + Founder, + #[codec(index = 12)] + AlreadyBid, + #[codec(index = 13)] + AlreadyCandidate, + #[codec(index = 14)] + NotCandidate, + #[codec(index = 15)] + MaxMembers, + #[codec(index = 16)] + NotFounder, + #[codec(index = 17)] + NotHead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Founded { founder: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + Bid { + candidate_id: ::sp_core::crypto::AccountId32, + offer: ::core::primitive::u128, + }, + #[codec(index = 2)] + Vouch { + candidate_id: ::sp_core::crypto::AccountId32, + offer: ::core::primitive::u128, + vouching: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + AutoUnbid { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + Unbid { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Unvouch { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + Inducted { + primary: ::sp_core::crypto::AccountId32, + candidates: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 7)] + SuspendedMemberJudgement { + who: ::sp_core::crypto::AccountId32, + judged: ::core::primitive::bool, + }, + #[codec(index = 8)] + CandidateSuspended { candidate: ::sp_core::crypto::AccountId32 }, + #[codec(index = 9)] + MemberSuspended { member: ::sp_core::crypto::AccountId32 }, + #[codec(index = 10)] + Challenged { member: ::sp_core::crypto::AccountId32 }, + #[codec(index = 11)] + Vote { + candidate: ::sp_core::crypto::AccountId32, + voter: ::sp_core::crypto::AccountId32, + vote: ::core::primitive::bool, + }, + #[codec(index = 12)] + DefenderVote { + voter: ::sp_core::crypto::AccountId32, + vote: ::core::primitive::bool, + }, + #[codec(index = 13)] + NewMaxMembers { max: ::core::primitive::u32 }, + #[codec(index = 14)] + Unfounded { founder: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Deposit { value: ::core::primitive::u128 }, + #[codec(index = 16)] + SkepticsChosen { skeptics: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bid<_0, _1> { + pub who: _0, + pub kind: runtime_types::pallet_society::BidKind<_0, _1>, + pub value: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BidKind<_0, _1> { + #[codec(index = 0)] + Deposit(_1), + #[codec(index = 1)] + Vouch(_0, _1), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Judgement { + #[codec(index = 0)] + Rebid, + #[codec(index = 1)] + Reject, + #[codec(index = 2)] + Approve, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Vote { + #[codec(index = 0)] + Skeptic, + #[codec(index = 1)] + Reject, + #[codec(index = 2)] + Approve, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VouchingStatus { + #[codec(index = 0)] + Vouching, + #[codec(index = 1)] + Banned, + } + } + pub mod pallet_state_trie_migration { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + control_auto_migration { + maybe_config: ::core::option::Option< + runtime_types::pallet_state_trie_migration::pallet::MigrationLimits, + >, + }, + #[codec(index = 1)] + continue_migrate { + limits: runtime_types::pallet_state_trie_migration::pallet::MigrationLimits, + real_size_upper: ::core::primitive::u32, + witness_task: + runtime_types::pallet_state_trie_migration::pallet::MigrationTask, + }, + #[codec(index = 2)] + migrate_custom_top { + keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + witness_size: ::core::primitive::u32, + }, + #[codec(index = 3)] + migrate_custom_child { + root: ::std::vec::Vec<::core::primitive::u8>, + child_keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + total_size: ::core::primitive::u32, + }, + #[codec(index = 4)] + set_signed_max_limits { + limits: runtime_types::pallet_state_trie_migration::pallet::MigrationLimits, + }, + #[codec(index = 5)] + force_set_progress { + progress_top: runtime_types::pallet_state_trie_migration::pallet::Progress, + progress_child: + runtime_types::pallet_state_trie_migration::pallet::Progress, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MaxSignedLimits, + #[codec(index = 1)] + KeyTooLong, + #[codec(index = 2)] + NotEnoughFunds, + #[codec(index = 3)] + BadWitness, + #[codec(index = 4)] + SignedMigrationNotAllowed, + #[codec(index = 5)] + BadChildRoot, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Migrated { + top: ::core::primitive::u32, + child: ::core::primitive::u32, + compute: + runtime_types::pallet_state_trie_migration::pallet::MigrationCompute, + }, + #[codec(index = 1)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 2)] + AutoMigrationFinished, + #[codec(index = 3)] + Halted { error: runtime_types::pallet_state_trie_migration::pallet::Error }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MigrationCompute { + #[codec(index = 0)] + Signed, + #[codec(index = 1)] + Auto, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MigrationLimits { + pub size: ::core::primitive::u32, + pub item: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MigrationTask { + pub progress_top: runtime_types::pallet_state_trie_migration::pallet::Progress, + pub progress_child: + runtime_types::pallet_state_trie_migration::pallet::Progress, + pub size: ::core::primitive::u32, + pub top_items: ::core::primitive::u32, + pub child_items: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Progress { + #[codec(index = 0)] + ToStart, + #[codec(index = 1)] + LastKey( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Complete, + } + } + } + pub mod pallet_sudo { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + sudo { call: ::std::boxed::Box }, + #[codec(index = 1)] + sudo_unchecked_weight { + call: ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + set_key { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + sudo_as { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + RequireSudo, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Sudid { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + KeyChanged { + old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 2)] + SudoAsDone { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_tips { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_awesome { + reason: ::std::vec::Vec<::core::primitive::u8>, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + retract_tip { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + tip_new { + reason: ::std::vec::Vec<::core::primitive::u8>, + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + tip_value: ::core::primitive::u128, + }, + #[codec(index = 3)] + tip { + hash: ::subxt::utils::H256, + #[codec(compact)] + tip_value: ::core::primitive::u128, + }, + #[codec(index = 4)] + close_tip { hash: ::subxt::utils::H256 }, + #[codec(index = 5)] + slash_tip { hash: ::subxt::utils::H256 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ReasonTooBig, + #[codec(index = 1)] + AlreadyKnown, + #[codec(index = 2)] + UnknownTip, + #[codec(index = 3)] + NotFinder, + #[codec(index = 4)] + StillOpen, + #[codec(index = 5)] + Premature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewTip { tip_hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + TipClosing { tip_hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + TipClosed { + tip_hash: ::subxt::utils::H256, + who: ::sp_core::crypto::AccountId32, + payout: ::core::primitive::u128, + }, + #[codec(index = 3)] + TipRetracted { tip_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + TipSlashed { + tip_hash: ::subxt::utils::H256, + finder: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpenTip<_0, _1, _2, _3> { + pub reason: _3, + pub who: _0, + pub finder: _0, + pub deposit: _1, + pub closes: ::core::option::Option<_2>, + pub tips: ::std::vec::Vec<(_0, _1)>, + pub finders_fee: ::core::primitive::bool, + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_treasury { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + propose_spend { + #[codec(compact)] + value: ::core::primitive::u128, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + reject_proposal { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + #[codec(index = 2)] + approve_proposal { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + #[codec(index = 3)] + spend { + #[codec(compact)] + amount: ::core::primitive::u128, + beneficiary: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + remove_approval { + #[codec(compact)] + proposal_id: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InsufficientProposersBalance, + #[codec(index = 1)] + InvalidIndex, + #[codec(index = 2)] + TooManyApprovals, + #[codec(index = 3)] + InsufficientPermission, + #[codec(index = 4)] + ProposalNotApproved, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Proposed { proposal_index: ::core::primitive::u32 }, + #[codec(index = 1)] + Spending { budget_remaining: ::core::primitive::u128 }, + #[codec(index = 2)] + Awarded { + proposal_index: ::core::primitive::u32, + award: ::core::primitive::u128, + account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Rejected { + proposal_index: ::core::primitive::u32, + slashed: ::core::primitive::u128, + }, + #[codec(index = 4)] + Burnt { burnt_funds: ::core::primitive::u128 }, + #[codec(index = 5)] + Rollover { rollover_balance: ::core::primitive::u128 }, + #[codec(index = 6)] + Deposit { value: ::core::primitive::u128 }, + #[codec(index = 7)] + SpendApproved { + proposal_index: ::core::primitive::u32, + amount: ::core::primitive::u128, + beneficiary: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + UpdatedInactive { + reactivated: ::core::primitive::u128, + deactivated: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Proposal<_0, _1> { + pub proposer: _0, + pub value: _1, + pub beneficiary: _0, + pub bond: _1, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { calls: ::std::vec::Vec }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box, + }, + #[codec(index = 2)] + batch_all { calls: ::std::vec::Vec }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box, + call: ::std::boxed::Box, + }, + #[codec(index = 4)] + force_batch { + calls: ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_vesting { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vest, + #[codec(index = 1)] + vest_other { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + vested_transfer { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 3)] + force_vested_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 4)] + merge_schedules { + schedule1_index: ::core::primitive::u32, + schedule2_index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotVesting, + #[codec(index = 1)] + AtMaxVestingSchedules, + #[codec(index = 2)] + AmountLow, + #[codec(index = 3)] + ScheduleIndexOutOfBounds, + #[codec(index = 4)] + InvalidScheduleParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + VestingUpdated { + account: ::sp_core::crypto::AccountId32, + unvested: ::core::primitive::u128, + }, + #[codec(index = 1)] + VestingCompleted { account: ::sp_core::crypto::AccountId32 }, + } + } + pub mod vesting_info { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VestingInfo<_0, _1> { + pub locked: _0, + pub per_block: _0, + pub starting_block: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V0, + #[codec(index = 1)] + V1, + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: + ::std::boxed::Box, + xcm_version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted(runtime_types::xcm::v3::traits::Outcome), + #[codec(index = 1)] + Sent( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::Xcm, + ), + #[codec(index = 2)] + UnexpectedResponse( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 3)] + ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + #[codec(index = 4)] + Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + #[codec(index = 5)] + NotifyOverweight( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ::sp_weights::Weight, + ::sp_weights::Weight, + ), + #[codec(index = 6)] + NotifyDispatchError( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 7)] + NotifyDecodeFailed( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 8)] + InvalidResponder( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 9)] + InvalidResponderVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 10)] + ResponseTaken(::core::primitive::u64), + #[codec(index = 11)] + AssetsTrapped( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + #[codec(index = 12)] + VersionChangeNotified( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 13)] + SupportedVersionChanged( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + ), + #[codec(index = 14)] + NotifyTargetSendFail( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::traits::Error, + ), + #[codec(index = 15)] + NotifyTargetMigrationFail( + runtime_types::xcm::VersionedMultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 16)] + InvalidQuerierVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 17)] + InvalidQuerier( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 18)] + VersionNotifyStarted( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 19)] + VersionNotifyRequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 20)] + VersionNotifyUnrequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 21)] + FeesPaid( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 22)] + AssetsClaimed( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateHash(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelId { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub recipient: runtime_types::polkadot_parachain::primitives::Id, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCodeHash(pub ::subxt::utils::H256); + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v4 { + use super::runtime_types; + pub mod assignment_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod collator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + pub mod executor_params { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ExecutorParam { + #[codec(index = 1)] + MaxMemoryPages(::core::primitive::u32), + #[codec(index = 2)] + StackLogicalMax(::core::primitive::u32), + #[codec(index = 3)] + StackNativeMax(::core::primitive::u32), + #[codec(index = 4)] + PrecheckingMaxMemory(::core::primitive::u64), + #[codec(index = 5)] + PvfPrepTimeout( + runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 6)] + PvfExecTimeout( + runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 7)] + WasmExtBulkMemory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutorParams( + pub ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, + >, + ); + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedSigned<_0, _1> { + pub payload: _0, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + pub signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, + } + } + pub mod validator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfield( + pub ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BackedCandidate<_0> { + pub candidate: + runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, + pub validity_votes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::ValidityAttestation, + >, + pub validator_indices: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateCommitments<_0> { + pub upward_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::std::vec::Vec<::core::primitive::u8>, + >, + pub horizontal_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain::primitives::Id, + >, + >, + pub new_validation_code: ::core::option::Option< + runtime_types::polkadot_parachain::primitives::ValidationCode, + >, + pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, + pub processed_downward_messages: _0, + pub hrmp_watermark: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateDescriptor<_0> { + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub relay_parent: _0, + pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, + pub persisted_validation_data_hash: _0, + pub pov_hash: _0, + pub erasure_root: _0, + pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, + pub para_head: _0, + pub validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments_hash: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommittedCandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< + ::core::primitive::u32, + >, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct CoreIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum CoreOccupied { + #[codec(index = 0)] + Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), + #[codec(index = 1)] + Parachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeState<_0> { + pub validators_for: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub validators_against: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub start: _0, + pub concluded_at: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeStatement { + #[codec(index = 0)] + Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), + #[codec(index = 1)] + Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeStatementSet { + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub session: ::core::primitive::u32, + pub statements: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::DisputeStatement, + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Signature, + )>, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct GroupIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndexedVec<_0, _1>( + pub ::std::vec::Vec<_1>, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData<_0> { + pub bitfields: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + >, + >, + pub backed_candidates: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::BackedCandidate< + ::subxt::utils::H256, + >, + >, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + pub parent_header: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaim( + pub runtime_types::polkadot_parachain::primitives::Id, + pub runtime_types::polkadot_primitives::v4::collator_app::Public, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadEntry { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, + pub retries: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckStatement { + pub accept: ::core::primitive::bool, + pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + pub session_index: ::core::primitive::u32, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfExecTimeoutKind { + #[codec(index = 0)] + Backing, + #[codec(index = 1)] + Approval, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfPrepTimeoutKind { + #[codec(index = 0)] + Precheck, + #[codec(index = 1)] + Lenient, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ScrapedOnChainVotes<_0> { + pub session: ::core::primitive::u32, + pub backing_validators_per_candidate: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, + ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::ValidityAttestation, + )>, + )>, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionInfo { + pub active_validator_indices: + ::std::vec::Vec, + pub random_seed: [::core::primitive::u8; 32usize], + pub dispute_period: ::core::primitive::u32, + pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub discovery_keys: + ::std::vec::Vec, + pub assignment_keys: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::assignment_app::Public, + >, + pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::GroupIndex, + ::std::vec::Vec, + >, + pub n_cores: ::core::primitive::u32, + pub zeroth_delay_tranche_width: ::core::primitive::u32, + pub relay_vrf_modulo_samples: ::core::primitive::u32, + pub n_delay_tranches: ::core::primitive::u32, + pub no_show_slots: ::core::primitive::u32, + pub needed_approvals: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + #[codec(index = 1)] + BackingSeconded(::subxt::utils::H256), + #[codec(index = 2)] + BackingValid(::subxt::utils::H256), + #[codec(index = 3)] + ApprovalChecking, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ValidatorIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidityAttestation { + #[codec(index = 1)] + Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + #[codec(index = 2)] + Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + } + } + pub mod vstaging { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + } + pub mod polkadot_runtime_common { + use super::runtime_types; + pub mod assigned_slots { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] assign_perm_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , # [codec (index = 1)] assign_temp_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , lease_period_start : runtime_types :: polkadot_runtime_common :: assigned_slots :: SlotLeasePeriodStart , } , # [codec (index = 2)] unassign_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaDoesntExist, + #[codec(index = 1)] + NotParathread, + #[codec(index = 2)] + CannotUpgrade, + #[codec(index = 3)] + CannotDowngrade, + #[codec(index = 4)] + SlotAlreadyAssigned, + #[codec(index = 5)] + SlotNotAssigned, + #[codec(index = 6)] + OngoingLeaseExists, + #[codec(index = 7)] + MaxPermanentSlotsExceeded, + #[codec(index = 8)] + MaxTemporarySlotsExceeded, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + PermanentSlotAssigned(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + TemporarySlotAssigned(runtime_types::polkadot_parachain::primitives::Id), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParachainTemporarySlot<_0, _1> { + pub manager: _0, + pub period_begin: _1, + pub period_count: _1, + pub last_lease: ::core::option::Option<_1>, + pub lease_count: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SlotLeasePeriodStart { + #[codec(index = 0)] + Current, + #[codec(index = 1)] + Next, + } + } + pub mod auctions { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + new_auction { + #[codec(compact)] + duration: ::core::primitive::u32, + #[codec(compact)] + lease_period_index: ::core::primitive::u32, + }, + #[codec(index = 1)] + bid { + #[codec(compact)] + para: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + auction_index: ::core::primitive::u32, + #[codec(compact)] + first_slot: ::core::primitive::u32, + #[codec(compact)] + last_slot: ::core::primitive::u32, + #[codec(compact)] + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + cancel_auction, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AuctionInProgress, + #[codec(index = 1)] + LeasePeriodInPast, + #[codec(index = 2)] + ParaNotRegistered, + #[codec(index = 3)] + NotCurrentAuction, + #[codec(index = 4)] + NotAuction, + #[codec(index = 5)] + AuctionEnded, + #[codec(index = 6)] + AlreadyLeasedOut, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + AuctionStarted { + auction_index: ::core::primitive::u32, + lease_period: ::core::primitive::u32, + ending: ::core::primitive::u32, + }, + #[codec(index = 1)] + AuctionClosed { auction_index: ::core::primitive::u32 }, + #[codec(index = 2)] + Reserved { + bidder: ::sp_core::crypto::AccountId32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unreserved { + bidder: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + ReserveConfiscated { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + BidAccepted { + bidder: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + first_slot: ::core::primitive::u32, + last_slot: ::core::primitive::u32, + }, + #[codec(index = 6)] + WinningOffset { + auction_index: ::core::primitive::u32, + block_number: ::core::primitive::u32, + }, + } + } + } + pub mod claims { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { + dest: ::sp_core::crypto::AccountId32, + ethereum_signature: + runtime_types::polkadot_runtime_common::claims::EcdsaSignature, + }, + #[codec(index = 1)] + mint_claim { + who: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + value: ::core::primitive::u128, + vesting_schedule: ::core::option::Option<( + ::core::primitive::u128, + ::core::primitive::u128, + ::core::primitive::u32, + )>, + statement: ::core::option::Option< + runtime_types::polkadot_runtime_common::claims::StatementKind, + >, + }, + #[codec(index = 2)] + claim_attest { + dest: ::sp_core::crypto::AccountId32, + ethereum_signature: + runtime_types::polkadot_runtime_common::claims::EcdsaSignature, + statement: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 3)] + attest { statement: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + move_claim { + old: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + new: runtime_types::polkadot_runtime_common::claims::EthereumAddress, + maybe_preclaim: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEthereumSignature, + #[codec(index = 1)] + SignerHasNoClaim, + #[codec(index = 2)] + SenderHasNoClaim, + #[codec(index = 3)] + PotUnderflow, + #[codec(index = 4)] + InvalidStatement, + #[codec(index = 5)] + VestedBalanceExists, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Claimed { + who: ::sp_core::crypto::AccountId32, + ethereum_address: + runtime_types::polkadot_runtime_common::claims::EthereumAddress, + amount: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EcdsaSignature(pub [::core::primitive::u8; 65usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EthereumAddress(pub [::core::primitive::u8; 20usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StatementKind { + #[codec(index = 0)] + Regular, + #[codec(index = 1)] + Saft, + } + } + pub mod crowdloan { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + create { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 1)] + contribute { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + value: ::core::primitive::u128, + signature: + ::core::option::Option, + }, + #[codec(index = 2)] + withdraw { + who: ::sp_core::crypto::AccountId32, + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 3)] + refund { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + dissolve { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + edit { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 6)] + add_memo { + index: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 7)] + poke { index: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + contribute_all { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + signature: + ::core::option::Option, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FirstPeriodInPast, + #[codec(index = 1)] + FirstPeriodTooFarInFuture, + #[codec(index = 2)] + LastPeriodBeforeFirstPeriod, + #[codec(index = 3)] + LastPeriodTooFarInFuture, + #[codec(index = 4)] + CannotEndInPast, + #[codec(index = 5)] + EndTooFarInFuture, + #[codec(index = 6)] + Overflow, + #[codec(index = 7)] + ContributionTooSmall, + #[codec(index = 8)] + InvalidParaId, + #[codec(index = 9)] + CapExceeded, + #[codec(index = 10)] + ContributionPeriodOver, + #[codec(index = 11)] + InvalidOrigin, + #[codec(index = 12)] + NotParachain, + #[codec(index = 13)] + LeaseActive, + #[codec(index = 14)] + BidOrLeaseActive, + #[codec(index = 15)] + FundNotEnded, + #[codec(index = 16)] + NoContributions, + #[codec(index = 17)] + NotReadyToDissolve, + #[codec(index = 18)] + InvalidSignature, + #[codec(index = 19)] + MemoTooLarge, + #[codec(index = 20)] + AlreadyInNewRaise, + #[codec(index = 21)] + VrfDelayInProgress, + #[codec(index = 22)] + NoLeasePeriod, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 1)] + Contributed { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Withdrew { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + PartiallyRefunded { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 6)] + HandleBidResult { + para_id: runtime_types::polkadot_parachain::primitives::Id, + result: ::core::result::Result< + (), + runtime_types::sp_runtime::DispatchError, + >, + }, + #[codec(index = 7)] + Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + MemoUpdated { + who: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 9)] + AddedToNewRaise { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FundInfo<_0, _1, _2, _3> { + pub depositor: _0, + pub verifier: ::core::option::Option, + pub deposit: _1, + pub raised: _1, + pub end: _2, + pub cap: _1, + pub last_contribution: + runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, + pub first_period: _2, + pub last_period: _2, + pub fund_index: _2, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum LastContribution<_0> { + #[codec(index = 0)] + Never, + #[codec(index = 1)] + PreEnding(_0), + #[codec(index = 2)] + Ending(_0), + } + } + pub mod paras_registrar { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register { + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_register { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 2)] + deregister { id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 3)] + swap { + id: runtime_types::polkadot_parachain::primitives::Id, + other: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + reserve, + #[codec(index = 6)] + add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 7)] + schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 8)] + set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + AlreadyRegistered, + #[codec(index = 2)] + NotOwner, + #[codec(index = 3)] + CodeTooLarge, + #[codec(index = 4)] + HeadDataTooLarge, + #[codec(index = 5)] + NotParachain, + #[codec(index = 6)] + NotParathread, + #[codec(index = 7)] + CannotDeregister, + #[codec(index = 8)] + CannotDowngrade, + #[codec(index = 9)] + CannotUpgrade, + #[codec(index = 10)] + ParaLocked, + #[codec(index = 11)] + NotReserved, + #[codec(index = 12)] + EmptyCode, + #[codec(index = 13)] + CannotSwap, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Registered { + para_id: runtime_types::polkadot_parachain::primitives::Id, + manager: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 1)] + Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + Reserved { + para_id: runtime_types::polkadot_parachain::primitives::Id, + who: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Swapped { + para_id: runtime_types::polkadot_parachain::primitives::Id, + other_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo<_0, _1> { + pub manager: _0, + pub deposit: _1, + pub locked: ::core::primitive::bool, + } + } + pub mod paras_sudo_wrapper { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + sudo_schedule_para_initialize { + id: runtime_types::polkadot_parachain::primitives::Id, + genesis: + runtime_types::polkadot_runtime_parachains::paras::ParaGenesisArgs, + }, + #[codec(index = 1)] + sudo_schedule_para_cleanup { + id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 2)] + sudo_schedule_parathread_upgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 3)] + sudo_schedule_parachain_downgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + sudo_queue_downward_xcm { + id: runtime_types::polkadot_parachain::primitives::Id, + xcm: ::std::boxed::Box, + }, + #[codec(index = 5)] + sudo_establish_hrmp_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + recipient: runtime_types::polkadot_parachain::primitives::Id, + max_capacity: ::core::primitive::u32, + max_message_size: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaDoesntExist, + #[codec(index = 1)] + ParaAlreadyExists, + #[codec(index = 2)] + ExceedsMaxMessageSize, + #[codec(index = 3)] + CouldntCleanup, + #[codec(index = 4)] + NotParathread, + #[codec(index = 5)] + NotParachain, + #[codec(index = 6)] + CannotUpgrade, + #[codec(index = 7)] + CannotDowngrade, + } + } + } + pub mod slots { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_lease { + para: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + }, + #[codec(index = 1)] + clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaNotOnboarding, + #[codec(index = 1)] + LeaseError, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewLeasePeriod { lease_period: ::core::primitive::u32 }, + #[codec(index = 1)] + Leased { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + } + } + } + } + pub mod polkadot_runtime_parachains { + use super::runtime_types; + pub mod configuration { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidNewValue, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HostConfiguration<_0> { + pub max_code_size: _0, + pub max_head_data_size: _0, + pub max_upward_queue_count: _0, + pub max_upward_queue_size: _0, + pub max_upward_message_size: _0, + pub max_upward_message_num_per_candidate: _0, + pub hrmp_max_message_num_per_candidate: _0, + pub validation_upgrade_cooldown: _0, + pub validation_upgrade_delay: _0, + pub async_backing_params: + runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, + pub max_pov_size: _0, + pub max_downward_message_size: _0, + pub hrmp_max_parachain_outbound_channels: _0, + pub hrmp_max_parathread_outbound_channels: _0, + pub hrmp_sender_deposit: ::core::primitive::u128, + pub hrmp_recipient_deposit: ::core::primitive::u128, + pub hrmp_channel_max_capacity: _0, + pub hrmp_channel_max_total_size: _0, + pub hrmp_max_parachain_inbound_channels: _0, + pub hrmp_max_parathread_inbound_channels: _0, + pub hrmp_channel_max_message_size: _0, + pub executor_params: + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, + pub code_retention_period: _0, + pub parathread_cores: _0, + pub parathread_retries: _0, + pub group_rotation_frequency: _0, + pub chain_availability_period: _0, + pub thread_availability_period: _0, + pub scheduling_lookahead: _0, + pub max_validators_per_core: ::core::option::Option<_0>, + pub max_validators: ::core::option::Option<_0>, + pub dispute_period: _0, + pub dispute_post_conclusion_acceptance_period: _0, + pub no_show_slots: _0, + pub n_delay_tranches: _0, + pub zeroth_delay_tranche_width: _0, + pub needed_approvals: _0, + pub relay_vrf_modulo_samples: _0, + pub pvf_checking_enabled: ::core::primitive::bool, + pub pvf_voting_ttl: _0, + pub minimum_validation_upgrade_delay: _0, + } + } + pub mod disputes { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_unfreeze, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateDisputeStatementSets, + #[codec(index = 1)] + AncientDisputeStatement, + #[codec(index = 2)] + ValidatorIndexOutOfBounds, + #[codec(index = 3)] + InvalidSignature, + #[codec(index = 4)] + DuplicateStatement, + #[codec(index = 5)] + SingleSidedDispute, + #[codec(index = 6)] + MaliciousBacker, + #[codec(index = 7)] + MissingBackingVotes, + #[codec(index = 8)] + UnconfirmedDispute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + DisputeInitiated( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, + ), + #[codec(index = 1)] + DisputeConcluded( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, + ), + #[codec(index = 2)] + Revert(::core::primitive::u32), + } + } + pub mod slashing { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Call { + # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Error { + #[codec(index = 0)] + InvalidKeyOwnershipProof, + #[codec(index = 1)] + InvalidSessionIndex, + #[codec(index = 2)] + InvalidCandidateHash, + #[codec(index = 3)] + InvalidValidatorIndex, + #[codec(index = 4)] + ValidatorIndexIdMismatch, + #[codec(index = 5)] + DuplicateSlashingReport, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputesTimeSlot { + pub session_index: ::core::primitive::u32, + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SlashingOffenceKind { + #[codec(index = 0)] + ForInvalid, + #[codec(index = 1)] + AgainstValid, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeLocation { + #[codec(index = 0)] + Local, + #[codec(index = 1)] + Remote, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeResult { + #[codec(index = 0)] + Valid, + #[codec(index = 1)] + Invalid, + } + } + pub mod hrmp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + hrmp_init_open_channel { + recipient: runtime_types::polkadot_parachain::primitives::Id, + proposed_max_capacity: ::core::primitive::u32, + proposed_max_message_size: ::core::primitive::u32, + }, + #[codec(index = 1)] + hrmp_accept_open_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 2)] + hrmp_close_channel { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + }, + #[codec(index = 3)] + force_clean_hrmp { + para: runtime_types::polkadot_parachain::primitives::Id, + inbound: ::core::primitive::u32, + outbound: ::core::primitive::u32, + }, + #[codec(index = 4)] + force_process_hrmp_open { channels: ::core::primitive::u32 }, + #[codec(index = 5)] + force_process_hrmp_close { channels: ::core::primitive::u32 }, + #[codec(index = 6)] + hrmp_cancel_open_request { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + open_requests: ::core::primitive::u32, + }, + #[codec(index = 7)] + force_open_hrmp_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + recipient: runtime_types::polkadot_parachain::primitives::Id, + max_capacity: ::core::primitive::u32, + max_message_size: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OpenHrmpChannelToSelf, + #[codec(index = 1)] + OpenHrmpChannelInvalidRecipient, + #[codec(index = 2)] + OpenHrmpChannelZeroCapacity, + #[codec(index = 3)] + OpenHrmpChannelCapacityExceedsLimit, + #[codec(index = 4)] + OpenHrmpChannelZeroMessageSize, + #[codec(index = 5)] + OpenHrmpChannelMessageSizeExceedsLimit, + #[codec(index = 6)] + OpenHrmpChannelAlreadyExists, + #[codec(index = 7)] + OpenHrmpChannelAlreadyRequested, + #[codec(index = 8)] + OpenHrmpChannelLimitExceeded, + #[codec(index = 9)] + AcceptHrmpChannelDoesntExist, + #[codec(index = 10)] + AcceptHrmpChannelAlreadyConfirmed, + #[codec(index = 11)] + AcceptHrmpChannelLimitExceeded, + #[codec(index = 12)] + CloseHrmpChannelUnauthorized, + #[codec(index = 13)] + CloseHrmpChannelDoesntExist, + #[codec(index = 14)] + CloseHrmpChannelAlreadyUnderway, + #[codec(index = 15)] + CancelHrmpOpenChannelUnauthorized, + #[codec(index = 16)] + OpenHrmpChannelDoesntExist, + #[codec(index = 17)] + OpenHrmpChannelAlreadyConfirmed, + #[codec(index = 18)] + WrongWitness, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + OpenChannelRequested( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + #[codec(index = 1)] + OpenChannelCanceled( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 2)] + OpenChannelAccepted( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 3)] + ChannelClosed( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 4)] + HrmpChannelForceOpened( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + pub sender_deposit: ::core::primitive::u128, + pub recipient_deposit: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpOpenChannelRequest { + pub confirmed: ::core::primitive::bool, + pub _age: ::core::primitive::u32, + pub sender_deposit: ::core::primitive::u128, + pub max_message_size: ::core::primitive::u32, + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + } + } + pub mod inclusion { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnsortedOrDuplicateValidatorIndices, + #[codec(index = 1)] + UnsortedOrDuplicateDisputeStatementSet, + #[codec(index = 2)] + UnsortedOrDuplicateBackedCandidates, + #[codec(index = 3)] + UnexpectedRelayParent, + #[codec(index = 4)] + WrongBitfieldSize, + #[codec(index = 5)] + BitfieldAllZeros, + #[codec(index = 6)] + BitfieldDuplicateOrUnordered, + #[codec(index = 7)] + ValidatorIndexOutOfBounds, + #[codec(index = 8)] + InvalidBitfieldSignature, + #[codec(index = 9)] + UnscheduledCandidate, + #[codec(index = 10)] + CandidateScheduledBeforeParaFree, + #[codec(index = 11)] + WrongCollator, + #[codec(index = 12)] + ScheduledOutOfOrder, + #[codec(index = 13)] + HeadDataTooLarge, + #[codec(index = 14)] + PrematureCodeUpgrade, + #[codec(index = 15)] + NewCodeTooLarge, + #[codec(index = 16)] + CandidateNotInParentContext, + #[codec(index = 17)] + InvalidGroupIndex, + #[codec(index = 18)] + InsufficientBacking, + #[codec(index = 19)] + InvalidBacking, + #[codec(index = 20)] + NotCollatorSigned, + #[codec(index = 21)] + ValidationDataHashMismatch, + #[codec(index = 22)] + IncorrectDownwardMessageHandling, + #[codec(index = 23)] + InvalidUpwardMessages, + #[codec(index = 24)] + HrmpWatermarkMishandling, + #[codec(index = 25)] + InvalidOutboundHrmp, + #[codec(index = 26)] + InvalidValidationCodeHash, + #[codec(index = 27)] + ParaHeadMismatch, + #[codec(index = 28)] + BitfieldReferencesFreedCore, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CandidateBacked( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 1)] + CandidateIncluded( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 2)] + CandidateTimedOut( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + ), + #[codec(index = 3)] + UpwardMessagesReceived { + from: runtime_types::polkadot_parachain::primitives::Id, + count: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfieldRecord<_0> { + pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + pub submitted_at: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidatePendingAvailability<_0, _1> { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub availability_votes: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub backers: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub relay_parent_number: _1, + pub backed_in_number: _1, + pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UmpQueueId { + #[codec(index = 0)] + Para(runtime_types::polkadot_parachain::primitives::Id), + } + } + pub mod initializer { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_approve { up_to: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BufferedSessionChange { + pub validators: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub queued: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub session_index: ::core::primitive::u32, + } + } + pub mod origin { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Parachain(runtime_types::polkadot_parachain::primitives::Id), + } + } + } + pub mod paras { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_set_current_code { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 2)] + force_schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + relay_parent_number: ::core::primitive::u32, + }, + #[codec(index = 3)] + force_note_new_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 4)] + force_queue_action { + para: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + add_trusted_validation_code { + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 6)] + poke_unused_validation_code { + validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + }, + #[codec(index = 7)] + include_pvf_check_statement { + stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, + signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + CannotOnboard, + #[codec(index = 2)] + CannotOffboard, + #[codec(index = 3)] + CannotUpgrade, + #[codec(index = 4)] + CannotDowngrade, + #[codec(index = 5)] + PvfCheckStatementStale, + #[codec(index = 6)] + PvfCheckStatementFuture, + #[codec(index = 7)] + PvfCheckValidatorIndexOutOfBounds, + #[codec(index = 8)] + PvfCheckInvalidSignature, + #[codec(index = 9)] + PvfCheckDoubleVote, + #[codec(index = 10)] + PvfCheckSubjectInvalid, + #[codec(index = 11)] + CannotUpgradeCode, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 2)] + CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 3)] + NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 4)] + ActionQueued( + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ), + #[codec(index = 5)] + PvfCheckStarted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 6)] + PvfCheckAccepted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 7)] + PvfCheckRejected( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaGenesisArgs { + pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + pub para_kind: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ParaLifecycle { + #[codec(index = 0)] + Onboarding, + #[codec(index = 1)] + Parathread, + #[codec(index = 2)] + Parachain, + #[codec(index = 3)] + UpgradingParathread, + #[codec(index = 4)] + DowngradingParachain, + #[codec(index = 5)] + OffboardingParathread, + #[codec(index = 6)] + OffboardingParachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaPastCodeMeta<_0> { + pub upgrade_times: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, + >, + pub last_pruned: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckActiveVoteState<_0> { + pub votes_accept: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub votes_reject: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub age: _0, + pub created_at: _0, + pub causes: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfCheckCause<_0> { + #[codec(index = 0)] + Onboarding(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + Upgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + relay_parent_number: _0, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReplacementTimes<_0> { + pub expected_at: _0, + pub activated_at: _0, + } + } + pub mod paras_inherent { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + enter { + data: runtime_types::polkadot_primitives::v4::InherentData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyInclusionInherents, + #[codec(index = 1)] + InvalidParentHeader, + #[codec(index = 2)] + CandidateConcludedInvalid, + #[codec(index = 3)] + InherentOverweight, + #[codec(index = 4)] + DisputeStatementsUnsortedOrDuplicates, + #[codec(index = 5)] + DisputeInvalid, + } + } + } + pub mod scheduler { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssignmentKind { + #[codec(index = 0)] + Parachain, + #[codec(index = 1)] + Parathread( + runtime_types::polkadot_primitives::v4::collator_app::Public, + ::core::primitive::u32, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CoreAssignment { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, + pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaimQueue { + pub queue: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, + >, + pub next_core_offset: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueuedParathread { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, + pub core_offset: ::core::primitive::u32, + } + } + pub mod shared { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + } + } + } + pub mod rococo_runtime { + use super::runtime_types; + pub mod validator_manager { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register_validators { + validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 1)] + deregister_validators { + validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ValidatorsRegistered(::std::vec::Vec<::sp_core::crypto::AccountId32>), + #[codec(index = 1)] + ValidatorsDeregistered(::std::vec::Vec<::sp_core::crypto::AccountId32>), + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + #[codec(index = 0)] + system( + runtime_types::frame_support::dispatch::RawOrigin< + ::sp_core::crypto::AccountId32, + >, + ), + #[codec(index = 14)] + Council( + runtime_types::pallet_collective::RawOrigin<::sp_core::crypto::AccountId32>, + ), + #[codec(index = 15)] + TechnicalCommittee( + runtime_types::pallet_collective::RawOrigin<::sp_core::crypto::AccountId32>, + ), + #[codec(index = 50)] + ParachainsOrigin( + runtime_types::polkadot_runtime_parachains::origin::pallet::Origin, + ), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Origin), + #[codec(index = 5)] + Void(runtime_types::sp_core::Void), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProxyType { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + NonTransfer, + #[codec(index = 2)] + Governance, + #[codec(index = 3)] + IdentityJudgement, + #[codec(index = 4)] + CancelProxy, + #[codec(index = 5)] + Auction, + #[codec(index = 6)] + Society, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + Babe(runtime_types::pallet_babe::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 3)] + Indices(runtime_types::pallet_indices::pallet::Call), + #[codec(index = 4)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 8)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 10)] + Grandpa(runtime_types::pallet_grandpa::pallet::Call), + #[codec(index = 11)] + ImOnline(runtime_types::pallet_im_online::pallet::Call), + #[codec(index = 13)] + Democracy(runtime_types::pallet_democracy::pallet::Call), + #[codec(index = 14)] + Council(runtime_types::pallet_collective::pallet::Call), + #[codec(index = 15)] + TechnicalCommittee(runtime_types::pallet_collective::pallet::Call), + #[codec(index = 16)] + PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Call), + #[codec(index = 17)] + TechnicalMembership(runtime_types::pallet_membership::pallet::Call), + #[codec(index = 18)] + Treasury(runtime_types::pallet_treasury::pallet::Call), + #[codec(index = 19)] + Claims(runtime_types::polkadot_runtime_common::claims::pallet::Call), + #[codec(index = 24)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 25)] + Identity(runtime_types::pallet_identity::pallet::Call), + #[codec(index = 26)] + Society(runtime_types::pallet_society::pallet::Call), + #[codec(index = 27)] + Recovery(runtime_types::pallet_recovery::pallet::Call), + #[codec(index = 28)] + Vesting(runtime_types::pallet_vesting::pallet::Call), + #[codec(index = 29)] + Scheduler(runtime_types::pallet_scheduler::pallet::Call), + #[codec(index = 30)] + Proxy(runtime_types::pallet_proxy::pallet::Call), + #[codec(index = 31)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 32)] + Preimage(runtime_types::pallet_preimage::pallet::Call), + #[codec(index = 35)] + Bounties(runtime_types::pallet_bounties::pallet::Call), + #[codec(index = 40)] + ChildBounties(runtime_types::pallet_child_bounties::pallet::Call), + #[codec(index = 36)] + Tips(runtime_types::pallet_tips::pallet::Call), + #[codec(index = 38)] + Nis(runtime_types::pallet_nis::pallet::Call), + #[codec(index = 45)] + NisCounterpartBalances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 51)] + Configuration( + runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, + ), + #[codec(index = 52)] + ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), + #[codec(index = 53)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), + #[codec(index = 54)] + ParaInherent( + runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, + ), + #[codec(index = 56)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), + #[codec(index = 57)] + Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), + #[codec(index = 60)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), + #[codec(index = 62)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), + #[codec(index = 63)] + ParasSlashing( + runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, + ), + #[codec(index = 64)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Call), + #[codec(index = 70)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), + #[codec(index = 71)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), + #[codec(index = 72)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), + #[codec(index = 73)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 240)] + Beefy(runtime_types::pallet_beefy::pallet::Call), + #[codec(index = 250)] + ParasSudoWrapper( + runtime_types::polkadot_runtime_common::paras_sudo_wrapper::pallet::Call, + ), + #[codec(index = 251)] + AssignedSlots(runtime_types::polkadot_runtime_common::assigned_slots::pallet::Call), + #[codec(index = 252)] + ValidatorManager(runtime_types::rococo_runtime::validator_manager::pallet::Call), + #[codec(index = 254)] + StateTrieMigration(runtime_types::pallet_state_trie_migration::pallet::Call), + #[codec(index = 255)] + Sudo(runtime_types::pallet_sudo::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 3)] + Indices(runtime_types::pallet_indices::pallet::Event), + #[codec(index = 4)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 33)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 7)] + Offences(runtime_types::pallet_offences::pallet::Event), + #[codec(index = 8)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 10)] + Grandpa(runtime_types::pallet_grandpa::pallet::Event), + #[codec(index = 11)] + ImOnline(runtime_types::pallet_im_online::pallet::Event), + #[codec(index = 13)] + Democracy(runtime_types::pallet_democracy::pallet::Event), + #[codec(index = 14)] + Council(runtime_types::pallet_collective::pallet::Event), + #[codec(index = 15)] + TechnicalCommittee(runtime_types::pallet_collective::pallet::Event), + #[codec(index = 16)] + PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Event), + #[codec(index = 17)] + TechnicalMembership(runtime_types::pallet_membership::pallet::Event), + #[codec(index = 18)] + Treasury(runtime_types::pallet_treasury::pallet::Event), + #[codec(index = 19)] + Claims(runtime_types::polkadot_runtime_common::claims::pallet::Event), + #[codec(index = 24)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 25)] + Identity(runtime_types::pallet_identity::pallet::Event), + #[codec(index = 26)] + Society(runtime_types::pallet_society::pallet::Event), + #[codec(index = 27)] + Recovery(runtime_types::pallet_recovery::pallet::Event), + #[codec(index = 28)] + Vesting(runtime_types::pallet_vesting::pallet::Event), + #[codec(index = 29)] + Scheduler(runtime_types::pallet_scheduler::pallet::Event), + #[codec(index = 30)] + Proxy(runtime_types::pallet_proxy::pallet::Event), + #[codec(index = 31)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 32)] + Preimage(runtime_types::pallet_preimage::pallet::Event), + #[codec(index = 35)] + Bounties(runtime_types::pallet_bounties::pallet::Event), + #[codec(index = 40)] + ChildBounties(runtime_types::pallet_child_bounties::pallet::Event), + #[codec(index = 36)] + Tips(runtime_types::pallet_tips::pallet::Event), + #[codec(index = 38)] + Nis(runtime_types::pallet_nis::pallet::Event), + #[codec(index = 45)] + NisCounterpartBalances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 53)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), + #[codec(index = 56)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), + #[codec(index = 60)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), + #[codec(index = 62)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), + #[codec(index = 64)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Event), + #[codec(index = 70)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), + #[codec(index = 71)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), + #[codec(index = 72)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), + #[codec(index = 73)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 251)] + AssignedSlots( + runtime_types::polkadot_runtime_common::assigned_slots::pallet::Event, + ), + #[codec(index = 252)] + ValidatorManager(runtime_types::rococo_runtime::validator_manager::pallet::Event), + #[codec(index = 254)] + StateTrieMigration(runtime_types::pallet_state_trie_migration::pallet::Event), + #[codec(index = 255)] + Sudo(runtime_types::pallet_sudo::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeHoldReason { + #[codec(index = 38)] + Nis(runtime_types::pallet_nis::pallet::HoldReason), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, + pub babe: runtime_types::sp_consensus_babe::app::Public, + pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, + pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, + pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, + pub beefy: runtime_types::sp_consensus_beefy::crypto::Public, + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + pub mod per_things { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Percent(pub ::core::primitive::u8); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Permill(pub ::core::primitive::u32); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Perquintill(pub ::core::primitive::u64); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_authority_discovery { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + pub mod sp_consensus_babe { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod digests { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NextConfigDescriptor { + #[codec(index = 1)] + V1 { + c: (::core::primitive::u64, ::core::primitive::u64), + allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PreDigest { + #[codec(index = 1)] + Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), + #[codec(index = 2)] + SecondaryPlain( + runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, + ), + #[codec(index = 3)] + SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PrimaryPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryPlainPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryVRFPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AllowedSlots { + #[codec(index = 0)] + PrimarySlots, + #[codec(index = 1)] + PrimaryAndSecondaryPlainSlots, + #[codec(index = 2)] + PrimaryAndSecondaryVRFSlots, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BabeEpochConfiguration { + pub c: (::core::primitive::u64, ::core::primitive::u64), + pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + } + } + pub mod sp_consensus_beefy { + use super::runtime_types; + pub mod commitment { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commitment<_0> { + pub payload: runtime_types::sp_consensus_beefy::payload::Payload, + pub block_number: _0, + pub validator_set_id: ::core::primitive::u64, + } + } + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ecdsa::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ecdsa::Signature); + } + pub mod mmr { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BeefyAuthoritySet<_0> { + pub id: ::core::primitive::u64, + pub len: ::core::primitive::u32, + pub root: _0, + } + } + pub mod payload { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Payload( + pub ::std::vec::Vec<( + [::core::primitive::u8; 2usize], + ::std::vec::Vec<::core::primitive::u8>, + )>, + ); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EquivocationProof<_0, _1, _2> { + pub first: runtime_types::sp_consensus_beefy::VoteMessage<_0, _1, _2>, + pub second: runtime_types::sp_consensus_beefy::VoteMessage<_0, _1, _2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VoteMessage<_0, _1, _2> { + pub commitment: runtime_types::sp_consensus_beefy::commitment::Commitment<_0>, + pub id: _1, + pub signature: _2, + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Equivocation<_0, _1> { + #[codec(index = 0)] + Prevote( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Prevote<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + #[codec(index = 1)] + Precommit( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Precommit<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EquivocationProof<_0, _1> { + pub offender: _1, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub first_header: _0, + pub second_header: _0, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 33usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod offchain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueNetworkState { + pub peer_id: runtime_types::sp_core::OpaquePeerId, + pub external_addresses: + ::std::vec::Vec, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod vrf { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VrfSignature { + pub output: [::core::primitive::u8; 32usize], + pub proof: [::core::primitive::u8; 64usize], + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1, _2, _3)>, + ); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSigner { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Public), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Public), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Public), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_staking { + use super::runtime_types; + pub mod offence { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OffenceDetails<_0, _1> { + pub offender: _1, + pub reporters: ::std::vec::Vec<_0>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + } + } +} diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index bf2cdd772271b..03b5ff5db62de 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,21 +16,36 @@ //! Types used to connect to the Rococo-Substrate chain. +pub mod codegen_runtime; + +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use bp_runtime::ChainId; +use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, + RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::storage::StorageKey; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use sp_session::MembershipProof; use std::time::Duration; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::rococo_runtime::RuntimeCall; + +pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; + /// Rococo header id. pub type HeaderId = relay_utils::HeaderId; /// Rococo header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; +/// The address format for describing accounts. +pub type Address = MultiAddress; + /// Rococo chain definition #[derive(Debug, Clone, Copy)] pub struct Rococo; @@ -47,7 +62,7 @@ impl Chain for Rococo { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); type SignedBlock = bp_rococo::SignedBlock; - type Call = (); + type Call = RuntimeCall; } impl ChainWithGrandpa for Rococo { @@ -67,3 +82,54 @@ impl RelayChain for Rococo { const PARAS_PALLET_NAME: &'static str = bp_rococo::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeRococoParachain"; } + +impl ChainWithTransactions for Rococo { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = + bp_polkadot_core::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_rococo::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ((), ()), + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(Self::SignedTransaction::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index e545111c2f636..f1db1f6173840 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -6,14 +6,19 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } # Bridge dependencies +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } bp-wococo = { path = "../../primitives/chain-wococo" } +relay-rococo-client = { path = "../client-rococo" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index f447fa6542e58..fa0d60faba6ec 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -16,21 +16,35 @@ //! Types used to connect to the Wococo-Substrate chain. +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use bp_wococo::WOCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; +use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, + RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::storage::StorageKey; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use sp_session::MembershipProof; use std::time::Duration; +pub use codegen_runtime::api::runtime_types; +use relay_rococo_client::codegen_runtime; + +pub type RuntimeCall = runtime_types::rococo_runtime::RuntimeCall; + +pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; + /// Wococo header id. pub type HeaderId = relay_utils::HeaderId; /// Wococo header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; +/// The address format for describing accounts. +pub type Address = MultiAddress; + /// Wococo chain definition #[derive(Debug, Clone, Copy)] pub struct Wococo; @@ -47,7 +61,7 @@ impl Chain for Wococo { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); type SignedBlock = bp_wococo::SignedBlock; - type Call = (); + type Call = RuntimeCall; } impl ChainWithGrandpa for Wococo { @@ -67,3 +81,54 @@ impl RelayChain for Wococo { const PARAS_PALLET_NAME: &'static str = bp_wococo::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWococoParachain"; } + +impl ChainWithTransactions for Wococo { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = + bp_polkadot_core::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_wococo::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ((), ()), + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(Self::SignedTransaction::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} diff --git a/relays/equivocation/src/equivocation_loop.rs b/relays/equivocation/src/equivocation_loop.rs index 5b935786353cf..61ffa92c8dc46 100644 --- a/relays/equivocation/src/equivocation_loop.rs +++ b/relays/equivocation/src/equivocation_loop.rs @@ -24,6 +24,7 @@ use finality_relay::{FinalityProofsBuf, FinalityProofsStream}; use futures::{select, FutureExt}; use num_traits::Saturating; use relay_utils::{ + metrics::MetricsParams, relay_loop::{reconnect_failed_client, RECONNECT_DELAY}, FailedClient, MaybeConnectionError, }; @@ -275,7 +276,10 @@ impl, TC: TargetClient

> let mut context = match self.build_equivocation_reporting_context(current_block_number).await { Some(context) => context, - None => continue, + None => { + current_block_number = current_block_number.saturating_add(1.into()); + continue + }, }; self.check_block(current_block_number, &mut context).await; current_block_number = current_block_number.saturating_add(1.into()); @@ -311,16 +315,18 @@ impl, TC: TargetClient

> } /// Spawn the equivocations detection loop. -/// TODO: remove `#[allow(dead_code)]` -#[allow(dead_code)] pub async fn run( source_client: impl SourceClient

, target_client: impl TargetClient

, tick: Duration, + metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, ) -> Result<(), relay_utils::Error> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) + .with_metrics(metrics_params) + .expose() + .await? .run( format!("{}_to_{}_EquivocationDetection", P::SOURCE_NAME, P::TARGET_NAME), move |source_client, target_client, _metrics| { diff --git a/relays/equivocation/src/lib.rs b/relays/equivocation/src/lib.rs index bbae97502f579..6f9337483fdab 100644 --- a/relays/equivocation/src/lib.rs +++ b/relays/equivocation/src/lib.rs @@ -23,6 +23,8 @@ use finality_relay::{FinalityPipeline, SourceClientBase}; use relay_utils::{relay_loop::Client as RelayClient, TransactionTracker}; use std::fmt::Debug; +pub use equivocation_loop::run; + pub trait EquivocationDetectionPipeline: FinalityPipeline { /// Block number of the target chain. type TargetNumber: relay_utils::BlockNumberBase; diff --git a/relays/lib-substrate-relay/src/equivocation/mod.rs b/relays/lib-substrate-relay/src/equivocation/mod.rs index 40750088bfb43..ee0928c2af137 100644 --- a/relays/lib-substrate-relay/src/equivocation/mod.rs +++ b/relays/lib-substrate-relay/src/equivocation/mod.rs @@ -20,14 +20,19 @@ mod source; mod target; -use crate::finality_base::{engine::Engine, SubstrateFinalityPipeline, SubstrateFinalityProof}; +use crate::{ + equivocation::{source::SubstrateEquivocationSource, target::SubstrateEquivocationTarget}, + finality_base::{engine::Engine, SubstrateFinalityPipeline, SubstrateFinalityProof}, + TransactionParams, +}; use async_trait::async_trait; use bp_runtime::{AccountIdOf, BlockNumberOf, HashOf}; use equivocation_detector::EquivocationDetectionPipeline; use finality_relay::FinalityPipeline; use pallet_grandpa::{Call as GrandpaCall, Config as GrandpaConfig}; -use relay_substrate_client::{AccountKeyPairOf, CallOf, Chain, ChainWithTransactions}; +use relay_substrate_client::{AccountKeyPairOf, CallOf, Chain, ChainWithTransactions, Client}; +use relay_utils::metrics::MetricsParams; use sp_core::Pair; use sp_runtime::traits::{Block, Header}; use std::marker::PhantomData; @@ -70,13 +75,15 @@ type FinalityVerificationContextfOf

= <

::FinalityEngine as Engine<

::SourceChain, >>::FinalityVerificationContext; -type EquivocationProofOf

= <

::FinalityEngine as Engine< +/// The type of the equivocation proof used by the `SubstrateEquivocationDetectionPipeline` +pub type EquivocationProofOf

= <

::FinalityEngine as Engine<

::SourceChain, >>::EquivocationProof; type EquivocationsFinderOf

= <

::FinalityEngine as Engine<

::SourceChain, >>::EquivocationsFinder; -type KeyOwnerProofOf

= <

::FinalityEngine as Engine< +/// The type of the key owner proof used by the `SubstrateEquivocationDetectionPipeline` +pub type KeyOwnerProofOf

= <

::FinalityEngine as Engine<

::SourceChain, >>::KeyOwnerProof; @@ -147,3 +154,56 @@ where .into() } } + +/// Macro that generates `ReportEquivocationCallBuilder` implementation for the case where +/// we only have access to the mocked version of the source chain runtime. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_report_equivocation_call_builder { + ($pipeline:ident, $mocked_builder:ident, $grandpa:path, $report_equivocation:path) => { + pub struct $mocked_builder; + + impl $crate::equivocation::ReportEquivocationCallBuilder<$pipeline> + for $mocked_builder + { + fn build_report_equivocation_call( + equivocation_proof: $crate::equivocation::EquivocationProofOf<$pipeline>, + key_owner_proof: $crate::equivocation::KeyOwnerProofOf<$pipeline>, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain + > { + bp_runtime::paste::item! { + $grandpa($report_equivocation { + equivocation_proof: Box::new(equivocation_proof), + key_owner_proof: key_owner_proof + }) + } + } + } + }; +} + +/// Run Substrate-to-Substrate equivocations detection loop. +pub async fn run( + source_client: Client, + target_client: Client, + source_transaction_params: TransactionParams>, + metrics_params: MetricsParams, +) -> anyhow::Result<()> { + log::info!( + target: "bridge", + "Starting {} -> {} equivocations detection loop", + P::SourceChain::NAME, + P::TargetChain::NAME, + ); + + equivocation_detector::run( + SubstrateEquivocationSource::

::new(source_client, source_transaction_params), + SubstrateEquivocationTarget::

::new(target_client), + P::TargetChain::AVERAGE_BLOCK_INTERVAL, + metrics_params, + futures::future::pending(), + ) + .await + .map_err(|e| anyhow::format_err!("{}", e)) +} diff --git a/relays/lib-substrate-relay/src/equivocation/source.rs b/relays/lib-substrate-relay/src/equivocation/source.rs index 543c057ee9ae5..a0c7dcf5cbc32 100644 --- a/relays/lib-substrate-relay/src/equivocation/source.rs +++ b/relays/lib-substrate-relay/src/equivocation/source.rs @@ -40,7 +40,15 @@ pub struct SubstrateEquivocationSource>, } -impl SubstrateEquivocationSource

{} +impl SubstrateEquivocationSource

{ + /// Create new instance of `SubstrateEquivocationSource`. + pub fn new( + client: Client, + transaction_params: TransactionParams>, + ) -> Self { + Self { client, transaction_params } + } +} impl Clone for SubstrateEquivocationSource

{ fn clone(&self) -> Self { diff --git a/relays/lib-substrate-relay/src/equivocation/target.rs b/relays/lib-substrate-relay/src/equivocation/target.rs index f7e63dd943af5..6eee2ab91d45b 100644 --- a/relays/lib-substrate-relay/src/equivocation/target.rs +++ b/relays/lib-substrate-relay/src/equivocation/target.rs @@ -40,7 +40,12 @@ pub struct SubstrateEquivocationTarget, } -impl SubstrateEquivocationTarget

{} +impl SubstrateEquivocationTarget

{ + /// Create new instance of `SubstrateEquivocationTarget`. + pub fn new(client: Client) -> Self { + Self { client, _phantom: Default::default() } + } +} impl Clone for SubstrateEquivocationTarget

{ fn clone(&self) -> Self { From 15af379ec8a3011df60e6bab9e0eb11f4534f6f5 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 1 Sep 2023 09:33:52 +0300 Subject: [PATCH 1098/1210] Backport `polkadot-sdk` changes to `polkadot-staging` (#2518) * Asynchronous backing PR (#2300) * Update substrate & polkadot * min changes to make async backing compile * (async backing) parachain-system: track limitations for unincluded blocks (#2438) * unincluded segment draft * read para head from storage proof * read_para_head -> read_included_para_head * Provide pub interface * add errors * fix unincluded segment update * BlockTracker -> Ancestor * add a dmp limit * Read para head depending on the storage switch * doc comments * storage items docs * add a sanity check on block initialize * Check watermark * append to the segment on block finalize * Move segment update into set_validation_data * Resolve para head todo * option watermark * fix comment * Drop dmq check * fix weight * doc-comments on inherent invariant * Remove TODO * add todo * primitives tests * pallet tests * doc comments * refactor unincluded segment length into a ConsensusHook (#2501) * refactor unincluded segment length into a ConsensusHook * add docs * refactor bandwidth_out calculation Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * test for limits from impl * fmt * make tests compile * update comment * uncomment test * fix collator test by adding parent to state proof * patch HRMP watermark rules for unincluded segment * get consensus-common tests to pass, using unincluded segment * fix unincluded segment tests * get all tests passing * fmt * rustdoc CI * aura-ext: limit the number of authored blocks per slot (#2551) * aura_ext consensus hook * reverse dependency * include weight into hook * fix tests * remove stray println Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> * fix test warning * fix doc link --------- Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> Co-authored-by: Chris Sosnin * parachain-system: ignore go ahead signal once upgrade is processed (#2594) * handle goahead signal for unincluded segment * doc comment * add test * parachain-system: drop processed messages from inherent data (#2590) * implement `drop_processed_messages` * drop messages based on relay parent number * adjust tests * drop changes to mqc * fix comment * drop test * drop more dead code * clippy * aura-ext: check slot in consensus hook and remove all `CheckInherents` logic (#2658) * aura-ext: check slot in consensus hook * convert relay chain slot * Make relay chain slot duration generic * use fixed velocity hook for pallets with aura * purge timestamp inherent * fix warning * adjust runtime tests * fix slots in tests * Make `xcm-emulator` test pass for new consensus hook (#2722) * add pallets on_initialize * tests pass * add AuraExt on_init * ".git/.scripts/commands/fmt/fmt.sh" --------- Co-authored-by: command-bot <> --------- Co-authored-by: Ignacio Palacios * update polkadot git refs * CollationGenerationConfig closure is now optional (#2772) * CollationGenerationConfig closure is now optional * fix test * propagate network-protocol-staging feature (#2899) * Feature Flagging Consensus Hook Type Parameter (#2911) * First pass * fmt * Added as default feature in tomls * Changed to direct dependency feature * Dealing with clippy error * Update pallets/parachain-system/src/lib.rs Co-authored-by: asynchronous rob --------- Co-authored-by: asynchronous rob * fmt * bump deps and remove warning * parachain-system: update RelevantMessagingState according to the unincluded segment (#2948) * mostly address 2471 with a bug introduced * adjust relevant messaging state after computing total * fmt * max -> min * fix test implementation of xcmp source * add test * fix test message sending logic * fix + test * add more to unincluded segment test * fmt --------- Co-authored-by: Chris Sosnin * Integrate new Aura / Parachain Consensus Logic in Parachain-Template / Polkadot-Parachain (#2864) * add a comment * refactor client/service utilities * deprecate start_collator * update parachain-template * update test-service in the same way * update polkadot-parachain crate * fmt * wire up new SubmitCollation message * some runtime utilities for implementing unincluded segment runtime APIs * allow parachains to configure their level of sybil-resistance when starting the network * make aura-ext compile * update to specify sybil resistance levels * fmt * specify relay chain slot duration in milliseconds * update Aura to explicitly produce Send futures also, make relay_chain_slot_duration a Duration * add authoring duration to basic collator and document params * integrate new basic collator into parachain-template * remove assert_send used for testing * basic-aura: only author when parent included * update polkadot-parachain-bin * fmt * some fixes * fixes * add a RelayNumberMonotonicallyIncreases * add a utility function for initializing subsystems * some logging for timestamp adjustment * fmt * some fixes for lookahead collator * add a log * update `find_potential_parents` to account for sessions * bound the loop * restore & deprecate old start_collator and start_full_node functions. * remove unnecessary await calls * fix warning * clippy * more clippy * remove unneeded logic * ci * update comment Co-authored-by: Marcin S. * (async backing) restore `CheckInherents` for backwards-compatibility (#2977) * bring back timestamp * Restore CheckInherents * revert to empty CheckInherents * make CheckInherents optional * attempt * properly end system blocks * add some more comments * ignore failing system parachain tests * update refs after main feature branch merge * comment out the offending tests because CI runs ignored tests * fix warnings * fmt * revert to polkadot master * cargo update -p polkadot-primitives -p sp-io --------- Co-authored-by: asynchronous rob Co-authored-by: Ignacio Palacios Co-authored-by: Bradley Olson <34992650+BradleyOlson64@users.noreply.github.com> Co-authored-by: Marcin S. Co-authored-by: eskimor Co-authored-by: Andronik (cherry picked from commit 6ef1117685a56e98ead266a7d752355c10986704) * Companion: restructure macro related exports (#3015) * restructure macro related exports * restructure macro related exports * wip * wip * update cargo lock * refactor RuntimeDebug on unincluded segment * fmt * Companion: restructure `benchmarking` macro related exports (#3039) * wip * wip * restructure benchmarking macro related exports * add cargo lock --------- Co-authored-by: parity-processbot <> (cherry picked from commit 8349c8d18af15c091b2f2a9f23f07a22ff2309cc) * Add missing workspace members (#3056) * Add dependencies Signed-off-by: Oliver Tale-Yazdi * Add missing workspace members Signed-off-by: Oliver Tale-Yazdi * Fix more Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi (cherry picked from commit 44499cf262e2e76dfbee432423d2b54a09c12415) * Add CI for monorepo (#1145) * Add CI for monorepo * fix frame tests * Format features Signed-off-by: Oliver Tale-Yazdi * add note for skipping tests and disable test-linux-stable-all * Fix tests and compile issues (#1152) * Fix feature dependant import Signed-off-by: Oliver Tale-Yazdi * Bump test timeout Signed-off-by: Oliver Tale-Yazdi * Remove feature gate Signed-off-by: Oliver Tale-Yazdi * Add resolver 2 Signed-off-by: Oliver Tale-Yazdi * Remove old lockfile Signed-off-by: Oliver Tale-Yazdi * Format features Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi * Fix check-dependency-rules Signed-off-by: Oliver Tale-Yazdi * rm test-runtime Signed-off-by: Oliver Tale-Yazdi * Actually fix script Signed-off-by: Oliver Tale-Yazdi * enable cargo-check-each-crate-macos * Run check-each-crate on 6 machines (#1163) --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi (cherry picked from commit e49493442a9377be9344c06a4990e17423783d41) * Fix features (#1194) * Manually fix conflicting ? Signed-off-by: Oliver Tale-Yazdi * Remove duplicates Signed-off-by: Oliver Tale-Yazdi * Autofix feature propagation zepter lint propagate-feature --feature try-runtime --left-side-feature-missing=ignore --workspace --fix --feature-enables-dep="try-runtime:frame-try-runtime" zepter lint propagate-feature --feature runtime-benchmarks --left-side-feature-missing=ignore --workspace --fix --feature-enables-dep="runtime-benchmarks:frame-benchmarking" zepter lint propagate-feature --feature std --left-side-feature-missing=ignore --workspace --fix zepter f f Signed-off-by: Oliver Tale-Yazdi * Bump zepter Signed-off-by: Oliver Tale-Yazdi * Add some duplicates Signed-off-by: Oliver Tale-Yazdi * Revert "Add some duplicates" This reverts commit c6ce627273881c478f5b34f23d3a67db632dbebf. * Remove default enabled features Signed-off-by: Oliver Tale-Yazdi * Bump Zepter Signed-off-by: Oliver Tale-Yazdi * Bump in correct location :facepalm: Signed-off-by: Oliver Tale-Yazdi * DNM: Add some mistakes Signed-off-by: Oliver Tale-Yazdi * DNM: Add some mistakes Signed-off-by: Oliver Tale-Yazdi * Revert "DNM: Add some mistakes" This reverts commit d469b3f0ba2aaed5f35f6ff5995f99e682da5800. * Revert "DNM: Add some mistakes" This reverts commit d892a73a35cac01e3721bdba74574b88bd04f83c. --------- Signed-off-by: Oliver Tale-Yazdi (cherry picked from commit 0400ed90757d125f7769f49044632dac6b654cc4) * Fix build profiles (#1229) * Fix build profiles Closes https://github.com/paritytech/polkadot-sdk/issues/1155 Signed-off-by: Oliver Tale-Yazdi * Manually set version to 1.0.0 Signed-off-by: Oliver Tale-Yazdi * Use workspace repo Signed-off-by: Oliver Tale-Yazdi * 'Authors and Edition from workspace Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi (cherry picked from commit dcda0e50f544c47634f4d994d41692e13a222294) * Set test crates to nopublish (#1240) * Set test crates to nopublish * Don't publish more crates * Set even more crates to nopublish --------- Co-authored-by: Oliver Tale-Yazdi (cherry picked from commit 1c7ef1f23283bf4878410d4bc2d9c643fa34a279) * Add missing licenses and tune the scanning workflow (#1288) * Add missing Cumulus licenses * Typo * Add missing Substrate licenses * Single job checking the sub-repos in steps * Remove dates * Remove dates * Add missing (C) * Update FRAME UI tests Signed-off-by: Oliver Tale-Yazdi * Update more UI tests Signed-off-by: Oliver Tale-Yazdi --------- Signed-off-by: Oliver Tale-Yazdi Co-authored-by: Oliver Tale-Yazdi (cherry picked from commit bfb241d7f3e29152b9fe0ab3a0364ee0c89ec65c) * Restructure `dispatch` macro related exports (#1162) * restructure dispatch macro related exports * moved Dispatchable to lib.rs * fix .gitignore final newline * ".git/.scripts/commands/fmt/fmt.sh" * fix rustdocs * wip --------- Co-authored-by: Liam Aharon Co-authored-by: command-bot <> Co-authored-by: ordian (cherry picked from commit bdbe98297032e21a553bf191c530690b1d591405) * Fixes * Fix clippy --------- Co-authored-by: Chris Sosnin <48099298+slumber@users.noreply.github.com> Co-authored-by: Juan Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Co-authored-by: Lulu Co-authored-by: Przemek Rzad --- bin/runtime-common/Cargo.toml | 24 +++++++++++-------- bin/runtime-common/src/integrity.rs | 2 +- bin/runtime-common/src/lib.rs | 4 ++-- bin/runtime-common/src/messages.rs | 5 ++-- bin/runtime-common/src/messages_api.rs | 2 +- .../src/messages_benchmarking.rs | 2 +- bin/runtime-common/src/messages_call_ext.rs | 5 ++-- bin/runtime-common/src/messages_generation.rs | 2 +- .../src/messages_xcm_extension.rs | 4 ++-- bin/runtime-common/src/mock.rs | 2 +- .../src/parachains_benchmarking.rs | 2 +- bin/runtime-common/src/priority_calculator.rs | 6 ++--- .../src/refund_relayer_extension.rs | 10 ++++---- modules/grandpa/Cargo.toml | 12 ++++++---- modules/grandpa/src/benchmarking.rs | 2 +- modules/grandpa/src/call_ext.rs | 6 ++--- modules/grandpa/src/lib.rs | 2 +- modules/grandpa/src/mock.rs | 2 +- modules/grandpa/src/storage_types.rs | 2 +- modules/grandpa/src/weights.rs | 2 +- modules/messages/Cargo.toml | 14 +++++++---- modules/messages/src/benchmarking.rs | 2 +- modules/messages/src/inbound_lane.rs | 5 ++-- modules/messages/src/lib.rs | 2 +- modules/messages/src/mock.rs | 2 +- modules/messages/src/outbound_lane.rs | 5 ++-- modules/messages/src/weights.rs | 2 +- modules/messages/src/weights_ext.rs | 2 +- modules/parachains/Cargo.toml | 14 +++++++---- modules/parachains/src/benchmarking.rs | 2 +- modules/parachains/src/call_ext.rs | 9 ++++--- modules/parachains/src/lib.rs | 2 +- modules/parachains/src/mock.rs | 2 +- modules/parachains/src/weights.rs | 2 +- modules/parachains/src/weights_ext.rs | 2 +- modules/relayers/Cargo.toml | 15 +++++++++--- modules/relayers/src/benchmarking.rs | 2 +- modules/relayers/src/lib.rs | 2 +- modules/relayers/src/mock.rs | 2 +- modules/relayers/src/payment_adapter.rs | 2 +- modules/relayers/src/stake_adapter.rs | 2 +- modules/relayers/src/weights.rs | 2 +- modules/relayers/src/weights_ext.rs | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 16 ++++++++----- .../xcm-bridge-hub-router/src/benchmarking.rs | 7 ++---- modules/xcm-bridge-hub-router/src/lib.rs | 2 +- modules/xcm-bridge-hub-router/src/mock.rs | 4 ++-- modules/xcm-bridge-hub-router/src/weights.rs | 2 +- primitives/chain-asset-hub-kusama/Cargo.toml | 8 +++---- primitives/chain-asset-hub-kusama/src/lib.rs | 2 +- .../chain-asset-hub-polkadot/Cargo.toml | 10 ++++---- .../chain-asset-hub-polkadot/src/lib.rs | 2 +- .../chain-bridge-hub-cumulus/Cargo.toml | 14 +++++------ .../chain-bridge-hub-cumulus/src/lib.rs | 2 +- primitives/chain-bridge-hub-kusama/Cargo.toml | 8 ++++--- primitives/chain-bridge-hub-kusama/src/lib.rs | 4 ++-- .../chain-bridge-hub-polkadot/Cargo.toml | 10 ++++---- .../chain-bridge-hub-polkadot/src/lib.rs | 5 ++-- primitives/chain-bridge-hub-rococo/Cargo.toml | 8 ++++--- primitives/chain-bridge-hub-rococo/src/lib.rs | 10 +++----- primitives/chain-bridge-hub-wococo/Cargo.toml | 10 ++++---- primitives/chain-bridge-hub-wococo/src/lib.rs | 5 ++-- primitives/chain-kusama/Cargo.toml | 6 ++--- primitives/chain-kusama/src/lib.rs | 2 +- primitives/chain-polkadot/Cargo.toml | 6 ++--- primitives/chain-polkadot/src/lib.rs | 2 +- primitives/chain-rococo/Cargo.toml | 6 ++--- primitives/chain-rococo/src/lib.rs | 2 +- primitives/chain-wococo/Cargo.toml | 8 +++---- primitives/chain-wococo/src/lib.rs | 2 +- primitives/header-chain/Cargo.toml | 10 ++++---- .../header-chain/src/justification/mod.rs | 6 ++--- .../verification/equivocation.rs | 2 +- .../src/justification/verification/mod.rs | 5 ++-- .../justification/verification/optimizer.rs | 2 +- .../src/justification/verification/strict.rs | 2 +- primitives/header-chain/src/lib.rs | 2 +- primitives/header-chain/src/storage_keys.rs | 2 +- .../tests/implementation_match.rs | 2 +- .../tests/justification/equivocation.rs | 2 +- .../tests/justification/optimizer.rs | 2 +- .../tests/justification/strict.rs | 2 +- primitives/header-chain/tests/tests.rs | 16 +++++++++++++ primitives/messages/Cargo.toml | 10 ++++---- primitives/messages/src/lib.rs | 6 ++--- primitives/messages/src/source_chain.rs | 5 ++-- primitives/messages/src/storage_keys.rs | 2 +- primitives/messages/src/target_chain.rs | 5 ++-- primitives/parachains/Cargo.toml | 6 ++--- primitives/parachains/src/lib.rs | 6 ++--- primitives/polkadot-core/Cargo.toml | 8 +++---- primitives/polkadot-core/src/lib.rs | 6 ++--- primitives/polkadot-core/src/parachains.rs | 4 ++-- primitives/relayers/Cargo.toml | 6 ++--- primitives/relayers/src/lib.rs | 2 +- primitives/relayers/src/registration.rs | 2 +- primitives/runtime/Cargo.toml | 10 ++++---- primitives/runtime/src/chain.rs | 2 +- primitives/runtime/src/extensions.rs | 2 +- primitives/runtime/src/lib.rs | 10 ++++---- primitives/runtime/src/messages.rs | 5 ++-- primitives/runtime/src/storage_proof.rs | 2 +- primitives/runtime/src/storage_types.rs | 5 ++-- primitives/test-utils/Cargo.toml | 10 +++++--- primitives/test-utils/src/keyring.rs | 2 +- primitives/test-utils/src/lib.rs | 2 +- primitives/xcm-bridge-hub-router/Cargo.toml | 13 ++++------ primitives/xcm-bridge-hub-router/src/lib.rs | 2 +- 108 files changed, 305 insertions(+), 240 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 5fb75f3887f11..91460e28b6194 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "bridge-runtime-common" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -repository = "https://github.com/paritytech/parity-bridges-common/" +authors.workspace = true +edition.workspace = true +repository.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -41,20 +41,21 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot dependencies -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-messages/std", "bp-parachains/std", "bp-polkadot-core/std", + "bp-relayers/std", "bp-runtime/std", "bp-xcm-bridge-hub-router/std", "codec/std", @@ -75,16 +76,19 @@ std = [ "sp-runtime/std", "sp-std/std", "sp-trie/std", - "xcm/std", "xcm-builder/std", + "xcm/std", ] runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] -integrity-test = [ - "static_assertions", -] +integrity-test = [ "static_assertions" ] diff --git a/bin/runtime-common/src/integrity.rs b/bin/runtime-common/src/integrity.rs index 765f812c70e0f..d3827a14dd6cc 100644 --- a/bin/runtime-common/src/integrity.rs +++ b/bin/runtime-common/src/integrity.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 546d4388471c1..ae6f40b142145 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -103,7 +103,7 @@ where #[macro_export] macro_rules! generate_bridge_reject_obsolete_headers_and_messages { ($call:ty, $account_id:ty, $($filter_call:ty),*) => { - #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, frame_support::RuntimeDebug, scale_info::TypeInfo)] + #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, sp_runtime::RuntimeDebug, scale_info::TypeInfo)] pub struct BridgeRejectObsoleteHeadersAndMessages; impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index 316c4d3cad927..ac66adae6614b 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -31,9 +31,10 @@ use bp_messages::{ }; use bp_runtime::{Chain, RawStorageProof, Size, StorageProofChecker}; use codec::{Decode, Encode}; -use frame_support::{traits::Get, weights::Weight, RuntimeDebug}; +use frame_support::{traits::Get, weights::Weight}; use hash_db::Hasher; use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; use sp_std::{convert::TryFrom, marker::PhantomData, vec::Vec}; /// Bidirectional message bridge. diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index 199e062fe9826..ccf1c754041ed 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index b067523c305b9..60f4bb17858c6 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 0a1d7243620c9..07a99d2c0a16c 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -21,10 +21,9 @@ use bp_messages::{target_chain::MessageDispatch, InboundLaneData, LaneId, Messag use frame_support::{ dispatch::CallableCallFor, traits::{Get, IsSubType}, - RuntimeDebug, }; use pallet_bridge_messages::{Config, Pallet}; -use sp_runtime::transaction_validity::TransactionValidity; +use sp_runtime::{transaction_validity::TransactionValidity, RuntimeDebug}; use sp_std::ops::RangeInclusive; /// Generic info about a messages delivery/confirmation proof. diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs index 8dbf3abd683cf..3c550a9bd0fd5 100644 --- a/bin/runtime-common/src/messages_generation.rs +++ b/bin/runtime-common/src/messages_generation.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 44e554ecb24f8..77c23db3b2ba2 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -29,7 +29,7 @@ use bp_messages::{ use bp_runtime::messages::MessageDispatchResult; use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; use codec::{Decode, Encode}; -use frame_support::{dispatch::Weight, traits::Get, CloneNoBound, EqNoBound, PartialEqNoBound}; +use frame_support::{traits::Get, weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; use pallet_bridge_messages::{ Config as MessagesConfig, OutboundLanesCongestedSignals, Pallet as MessagesPallet, WeightInfoExt as MessagesPalletWeights, diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 9c41d17fa9957..45ef790d74482 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index aad53673c3ad3..63dc78385e46e 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs index 590de05fb1c66..3d53f9da8c20e 100644 --- a/bin/runtime-common/src/priority_calculator.rs +++ b/bin/runtime-common/src/priority_calculator.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -51,13 +51,13 @@ mod integrity_tests { use bp_messages::MessageNonce; use bp_runtime::PreComputedSize; use frame_support::{ - dispatch::{DispatchClass, DispatchInfo, Dispatchable, Pays, PostDispatchInfo}, + dispatch::{DispatchClass, DispatchInfo, Pays, PostDispatchInfo}, traits::Get, }; use pallet_bridge_messages::WeightInfoExt; use pallet_transaction_payment::OnChargeTransaction; use sp_runtime::{ - traits::{UniqueSaturatedInto, Zero}, + traits::{Dispatchable, UniqueSaturatedInto, Zero}, transaction_validity::TransactionPriority, FixedPointOperand, SaturatedConversion, Saturating, }; diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index f611686420c29..f0c2cbf44509b 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -27,10 +27,10 @@ use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::{Parachain, ParachainIdOf, RangeInclusiveExt, StaticStrProvider}; use codec::{Decode, Encode}; use frame_support::{ - dispatch::{CallableCallFor, DispatchInfo, Dispatchable, PostDispatchInfo}, + dispatch::{CallableCallFor, DispatchInfo, PostDispatchInfo}, traits::IsSubType, weights::Weight, - CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, + CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; use pallet_bridge_grandpa::{ CallSubType as GrandpaCallSubType, SubmitFinalityProofHelper, SubmitFinalityProofInfo, @@ -47,11 +47,11 @@ use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTra use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Get, PostDispatchInfoOf, SignedExtension, Zero}, + traits::{DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, SignedExtension, Zero}, transaction_validity::{ TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder, }, - DispatchResult, FixedPointOperand, + DispatchResult, FixedPointOperand, RuntimeDebug, }; use sp_std::{marker::PhantomData, vec, vec::Vec}; diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 0bd62beeaad48..44a1974290168 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "pallet-bridge-grandpa" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -36,16 +36,16 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-runtime/std", "bp-test-utils/std", "codec/std", "finality-grandpa/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "frame-benchmarking/std", "log/std", "scale-info/std", "sp-consensus-grandpa/std", @@ -56,8 +56,12 @@ std = [ runtime-benchmarks = [ "bp-test-utils", "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index aa222d6e4de6f..182b2f56eb1c5 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index c83e88b7b5621..e0648d5dd0f1d 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -18,11 +18,11 @@ use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Erro use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa}; use bp_runtime::BlockNumberOf; use codec::Encode; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight, RuntimeDebug}; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight}; use sp_runtime::{ traits::{Header, Zero}, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, - SaturatedConversion, + RuntimeDebug, SaturatedConversion, }; /// Info about a `SubmitParachainHeads` call which tries to update a single parachain. diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 425712ad9a20e..22df604bf1895 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index bd305dfef9dc0..f88a0a3e6a6ee 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/grandpa/src/storage_types.rs b/modules/grandpa/src/storage_types.rs index 59fcb5d3f077f..6d1a7882dd499 100644 --- a/modules/grandpa/src/storage_types.rs +++ b/modules/grandpa/src/storage_types.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 4b94f7adfe73b..89ed70d13ac33 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 8db52acefc0b4..9131a1063056b 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -2,8 +2,8 @@ name = "pallet-bridge-messages" description = "Module that allows bridged chains to exchange messages using lane concept." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -32,14 +32,14 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "m sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-messages/std", "bp-runtime/std", "codec/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "frame-benchmarking/std", "log/std", "num-traits/std", "scale-info/std", @@ -49,8 +49,14 @@ std = [ ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-balances/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 04f64b53b305f..8c4e6fbf00ca4 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index b665b5516fc4d..966ec939e70e2 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -24,8 +24,9 @@ use bp_messages::{ ReceivalResult, UnrewardedRelayer, }; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; -use frame_support::{traits::Get, RuntimeDebug}; +use frame_support::traits::Get; use scale_info::{Type, TypeInfo}; +use sp_runtime::RuntimeDebug; use sp_std::prelude::PartialEq; /// Inbound lane storage. diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 67c6fb23cf167..b87c64d160752 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 67f7b78a487aa..aebb7eafa7871 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 0cf0c4ccb425c..f92e9ccfd95c6 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -25,10 +25,11 @@ use bp_messages::{ use codec::{Decode, Encode}; use frame_support::{ weights::{RuntimeDbWeight, Weight}, - BoundedVec, PalletError, RuntimeDebug, + BoundedVec, PalletError, }; use num_traits::Zero; use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 9880f1dd1ea3d..5b6863984ec78 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 3aefd6be7ca78..1be24a738a495 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 3e8d00511d533..6db3802157973 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "pallet-bridge-parachains" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -34,16 +34,16 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-parachains/std", "bp-polkadot-core/std", "bp-runtime/std", "codec/std", + "frame-benchmarking/std", "frame-support/std", "frame-system/std", - "frame-benchmarking/std", "log/std", "pallet-bridge-grandpa/std", "scale-info/std", @@ -53,8 +53,14 @@ std = [ ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-bridge-grandpa/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/modules/parachains/src/benchmarking.rs b/modules/parachains/src/benchmarking.rs index 59c4642cde999..27e06a12a1d93 100644 --- a/modules/parachains/src/benchmarking.rs +++ b/modules/parachains/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/parachains/src/call_ext.rs b/modules/parachains/src/call_ext.rs index ee3770146c260..99640dadc61f4 100644 --- a/modules/parachains/src/call_ext.rs +++ b/modules/parachains/src/call_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -17,8 +17,11 @@ use crate::{Config, Pallet, RelayBlockNumber}; use bp_parachains::BestParaHeadHash; use bp_polkadot_core::parachains::{ParaHash, ParaId}; -use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug}; -use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}; +use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; +use sp_runtime::{ + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + RuntimeDebug, +}; /// Info about a `SubmitParachainHeads` call which tries to update a single parachain. #[derive(PartialEq, RuntimeDebug)] diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index be46fae3c9253..b2ef0bf52bd3d 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index a7030f0ae0310..14afe38417105 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 1e81dba72fe99..9182ec466117b 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs index eecdfe903593e..13bc9ad2bbce0 100644 --- a/modules/parachains/src/weights_ext.rs +++ b/modules/parachains/src/weights_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 93b0917970608..2c6a1a2f2b2a5 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -2,8 +2,8 @@ name = "pallet-bridge-relayers" description = "Module used to store relayer rewards and coordinate relayers set." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -35,7 +35,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-messages/std", "bp-relayers/std", @@ -45,6 +45,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-bridge-messages/std", "scale-info/std", "sp-arithmetic/std", "sp-runtime/std", @@ -52,8 +53,16 @@ std = [ ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-bridge-messages/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index d66a11ff06d02..2d74ab38f9dbd 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index a71c218443b3d..b9b98ca7e253f 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index b3fcb24cdd20d..4713ec91658af 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/src/payment_adapter.rs b/modules/relayers/src/payment_adapter.rs index a9536cfc0275f..b2d9c676bddc4 100644 --- a/modules/relayers/src/payment_adapter.rs +++ b/modules/relayers/src/payment_adapter.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/src/stake_adapter.rs b/modules/relayers/src/stake_adapter.rs index 055b6a111ec72..88af9b1877bfe 100644 --- a/modules/relayers/src/stake_adapter.rs +++ b/modules/relayers/src/stake_adapter.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 1bc195a542472..2e064a3936df3 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/relayers/src/weights_ext.rs b/modules/relayers/src/weights_ext.rs index d459b0686bd7e..9cd25c47c3782 100644 --- a/modules/relayers/src/weights_ext.rs +++ b/modules/relayers/src/weights_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 8a6bcef060480..d2c8d06fdeaeb 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -2,8 +2,8 @@ name = "pallet-xcm-bridge-hub-router" description = "Bridge hub interface for sibling/parent chains with dynamic fees support." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -26,15 +26,15 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d # Polkadot Dependencies -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } [dev-dependencies] sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-xcm-bridge-hub-router/std", "codec/std", @@ -46,14 +46,18 @@ std = [ "sp-core/std", "sp-runtime/std", "sp-std/std", - "xcm/std", "xcm-builder/std", + "xcm/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "sp-runtime/try-runtime", ] diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/modules/xcm-bridge-hub-router/src/benchmarking.rs index b32b983daf72c..4bbe414f66355 100644 --- a/modules/xcm-bridge-hub-router/src/benchmarking.rs +++ b/modules/xcm-bridge-hub-router/src/benchmarking.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -22,10 +22,7 @@ use crate::{Bridge, Call}; use bp_xcm_bridge_hub_router::{BridgeState, MINIMAL_DELIVERY_FEE_FACTOR}; use frame_benchmarking::benchmarks_instance_pallet; -use frame_support::{ - dispatch::UnfilteredDispatchable, - traits::{EnsureOrigin, Get, Hooks}, -}; +use frame_support::traits::{EnsureOrigin, Get, Hooks, UnfilteredDispatchable}; use sp_runtime::traits::Zero; use xcm::prelude::*; diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs index 87e050b45c736..5cf94fc83fd9d 100644 --- a/modules/xcm-bridge-hub-router/src/lib.rs +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 5ad7be4890a17..58df21a6d9016 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -144,5 +144,5 @@ pub fn new_test_ext() -> sp_io::TestExternalities { /// Run pallet test. pub fn run_test(test: impl FnOnce() -> T) -> T { - new_test_ext().execute_with(|| test()) + new_test_ext().execute_with(test) } diff --git a/modules/xcm-bridge-hub-router/src/weights.rs b/modules/xcm-bridge-hub-router/src/weights.rs index 04909f3b2e838..62936e997f3cd 100644 --- a/modules/xcm-bridge-hub-router/src/weights.rs +++ b/modules/xcm-bridge-hub-router/src/weights.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-asset-hub-kusama/Cargo.toml b/primitives/chain-asset-hub-kusama/Cargo.toml index 6d5a4207ee668..c87b8eee8868b 100644 --- a/primitives/chain-asset-hub-kusama/Cargo.toml +++ b/primitives/chain-asset-hub-kusama/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-asset-hub-kusama" description = "Primitives of AssetHubKusama parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -17,10 +17,10 @@ frame-support = { git = "https://github.com/paritytech/substrate", branch = "mas bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-xcm-bridge-hub-router/std", - "frame-support/std", "codec/std", + "frame-support/std", "scale-info/std", ] diff --git a/primitives/chain-asset-hub-kusama/src/lib.rs b/primitives/chain-asset-hub-kusama/src/lib.rs index b3b25ba6eddd7..94016c1da0cb1 100644 --- a/primitives/chain-asset-hub-kusama/src/lib.rs +++ b/primitives/chain-asset-hub-kusama/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-asset-hub-polkadot/Cargo.toml b/primitives/chain-asset-hub-polkadot/Cargo.toml index 4ab562c6b34ce..eef4ae760aac4 100644 --- a/primitives/chain-asset-hub-polkadot/Cargo.toml +++ b/primitives/chain-asset-hub-polkadot/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-asset-hub-polkadot" description = "Primitives of AssetHubPolkadot parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -12,15 +12,17 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Bridge Dependencies bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-xcm-bridge-hub-router/std", - "frame-support/std", "codec/std", + "frame-support/std", "scale-info/std", + "sp-runtime/std", ] diff --git a/primitives/chain-asset-hub-polkadot/src/lib.rs b/primitives/chain-asset-hub-polkadot/src/lib.rs index 7363e5af02a2c..486fba60e1f88 100644 --- a/primitives/chain-asset-hub-polkadot/src/lib.rs +++ b/primitives/chain-asset-hub-polkadot/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index 2bbe3d029a37a..1880333d34632 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-bridge-hub-cumulus" description = "Primitives of BridgeHubRococo parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -21,17 +21,17 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } # Polkadot Dependencies -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ - "bp-polkadot-core/std", "bp-messages/std", + "bp-polkadot-core/std", "bp-runtime/std", - "frame-system/std", "frame-support/std", + "frame-system/std", + "polkadot-primitives/std", "sp-api/std", "sp-std/std", - "polkadot-primitives/std", ] diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index feaac9e882daf..c1dbc6db36f64 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml index 6d4334eaa57f0..1ad196d9ff643 100644 --- a/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-bridge-hub-kusama" description = "Primitives of BridgeHubRococo parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -17,15 +17,17 @@ bp-messages = { path = "../../primitives/messages", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs index 03f295e07f1ef..3a919648df47f 100644 --- a/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -27,8 +27,8 @@ use bp_runtime::{ use frame_support::{ dispatch::DispatchClass, sp_runtime::{MultiAddress, MultiSigner}, - RuntimeDebug, }; +use sp_runtime::RuntimeDebug; use sp_std::prelude::Vec; /// BridgeHubKusama parachain. diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml index 2a0ab3213c85b..2ddb30225fa4f 100644 --- a/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-bridge-hub-polkadot" description = "Primitives of BridgeHubWococo parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -18,15 +18,17 @@ bp-messages = { path = "../../primitives/messages", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-bridge-hub-cumulus/std", - "bp-runtime/std", "bp-messages/std", + "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs index ceacfe67ff2cb..bf8d8e07c3a61 100644 --- a/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -24,7 +24,8 @@ use bp_messages::*; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; -use frame_support::{dispatch::DispatchClass, RuntimeDebug}; +use frame_support::dispatch::DispatchClass; +use sp_runtime::RuntimeDebug; use sp_std::prelude::Vec; /// BridgeHubPolkadot parachain. diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index 85c4225ab55c3..714d9aa48e196 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-bridge-hub-rococo" description = "Primitives of BridgeHubRococo parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -17,15 +17,17 @@ bp-messages = { path = "../../primitives/messages", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index f8d46ff32bde8..b726c62ac42b3 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -24,13 +24,9 @@ use bp_messages::*; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; -use frame_support::{ - dispatch::DispatchClass, - sp_runtime::{MultiAddress, MultiSigner}, - RuntimeDebug, -}; +use frame_support::dispatch::DispatchClass; +use sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug}; use sp_std::prelude::Vec; - /// BridgeHubRococo parachain. #[derive(RuntimeDebug)] pub struct BridgeHubRococo; diff --git a/primitives/chain-bridge-hub-wococo/Cargo.toml b/primitives/chain-bridge-hub-wococo/Cargo.toml index 24ecdb7adbca1..fb480b4a440f6 100644 --- a/primitives/chain-bridge-hub-wococo/Cargo.toml +++ b/primitives/chain-bridge-hub-wococo/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-bridge-hub-wococo" description = "Primitives of BridgeHubWococo parachain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -18,15 +18,17 @@ bp-messages = { path = "../../primitives/messages", default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-bridge-hub-cumulus/std", - "bp-runtime/std", "bp-messages/std", + "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index abbb0cc20ea4b..5e4758645d9ea 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -24,7 +24,8 @@ use bp_messages::*; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, }; -use frame_support::{dispatch::DispatchClass, RuntimeDebug}; +use frame_support::dispatch::DispatchClass; +use sp_runtime::RuntimeDebug; use sp_std::prelude::Vec; /// BridgeHubWococo parachain. diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 65b0729aa17e8..e4d59c9d159d4 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-kusama" description = "Primitives of Kusama runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 3f001638bb40d..8c3fbd9c203e5 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 1522f1dadb71f..d67a4f10fd10e 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-polkadot" description = "Primitives of Polkadot runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 49c88cd357b20..d1d6f74543121 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 26e035b439a62..97958e714f505 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-rococo" description = "Primitives of Rococo runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -21,7 +21,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 0ab0fa4ec4767..1589d14ea5143 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index 3bde102d8f2c8..c7e8a3af0a06c 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-wococo" description = "Primitives of Wococo runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -22,12 +22,12 @@ sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-polkadot-core/std", - "bp-runtime/std", "bp-rococo/std", + "bp-runtime/std", "frame-support/std", "sp-api/std", "sp-std/std", diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 1a3e8ded629e8..5b5bde8269044 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 962d262d571b3..3281225883f81 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-header-chain" description = "A common interface for describing what a bridge pallet should be able to do." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -30,16 +30,16 @@ hex = "0.4" hex-literal = "0.4" [features] -default = ["std"] +default = [ "std" ] std = [ "bp-runtime/std", "codec/std", "finality-grandpa/std", - "serde/std", "frame-support/std", "scale-info/std", - "sp-core/std", + "serde/std", "sp-consensus-grandpa/std", + "sp-core/std", "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/header-chain/src/justification/mod.rs b/primitives/header-chain/src/justification/mod.rs index fbb8af80b2cdd..72a5f68918d97 100644 --- a/primitives/header-chain/src/justification/mod.rs +++ b/primitives/header-chain/src/justification/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -32,10 +32,10 @@ pub use verification::{ use bp_runtime::{BlockNumberOf, Chain, HashOf, HeaderId}; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{RuntimeDebug, RuntimeDebugNoBound}; +use frame_support::RuntimeDebugNoBound; use scale_info::TypeInfo; use sp_consensus_grandpa::{AuthorityId, AuthoritySignature}; -use sp_runtime::{traits::Header as HeaderT, SaturatedConversion}; +use sp_runtime::{traits::Header as HeaderT, RuntimeDebug, SaturatedConversion}; use sp_std::prelude::*; /// A GRANDPA Justification is a proof that a given header was finalized diff --git a/primitives/header-chain/src/justification/verification/equivocation.rs b/primitives/header-chain/src/justification/verification/equivocation.rs index 2484fc4d6b2bf..e2d7a8e804c20 100644 --- a/primitives/header-chain/src/justification/verification/equivocation.rs +++ b/primitives/header-chain/src/justification/verification/equivocation.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/primitives/header-chain/src/justification/verification/mod.rs index 7af5292256cb8..bb8aaadf327ec 100644 --- a/primitives/header-chain/src/justification/verification/mod.rs +++ b/primitives/header-chain/src/justification/verification/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -24,9 +24,8 @@ use crate::{justification::GrandpaJustification, AuthoritySet}; use bp_runtime::HeaderId; use finality_grandpa::voter_set::VoterSet; -use frame_support::RuntimeDebug; use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, SetId}; -use sp_runtime::traits::Header as HeaderT; +use sp_runtime::{traits::Header as HeaderT, RuntimeDebug}; use sp_std::{ collections::{btree_map::BTreeMap, btree_set::BTreeSet}, prelude::*, diff --git a/primitives/header-chain/src/justification/verification/optimizer.rs b/primitives/header-chain/src/justification/verification/optimizer.rs index 99ccdd50616b0..6552b359170a8 100644 --- a/primitives/header-chain/src/justification/verification/optimizer.rs +++ b/primitives/header-chain/src/justification/verification/optimizer.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/src/justification/verification/strict.rs b/primitives/header-chain/src/justification/verification/strict.rs index a9d5f4c1f7362..f899c6c8efc06 100644 --- a/primitives/header-chain/src/justification/verification/strict.rs +++ b/primitives/header-chain/src/justification/verification/strict.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index b1eda8dc3f73c..d2c7ec0759e88 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/src/storage_keys.rs b/primitives/header-chain/src/storage_keys.rs index c4dbe53bd9a7f..55d095afbf2ae 100644 --- a/primitives/header-chain/src/storage_keys.rs +++ b/primitives/header-chain/src/storage_keys.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index db96961832d4b..f664a419621f6 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/tests/justification/equivocation.rs b/primitives/header-chain/tests/justification/equivocation.rs index f3c133481fb89..0bc084cc1a970 100644 --- a/primitives/header-chain/tests/justification/equivocation.rs +++ b/primitives/header-chain/tests/justification/equivocation.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/tests/justification/optimizer.rs b/primitives/header-chain/tests/justification/optimizer.rs index bdc90a3b07cf6..21bcd7e86b51e 100644 --- a/primitives/header-chain/tests/justification/optimizer.rs +++ b/primitives/header-chain/tests/justification/optimizer.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/tests/justification/strict.rs b/primitives/header-chain/tests/justification/strict.rs index 9568f7f7cf9a3..188c9f5baba26 100644 --- a/primitives/header-chain/tests/justification/strict.rs +++ b/primitives/header-chain/tests/justification/strict.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/header-chain/tests/tests.rs b/primitives/header-chain/tests/tests.rs index 7c525a9303adc..269fde09bb71c 100644 --- a/primitives/header-chain/tests/tests.rs +++ b/primitives/header-chain/tests/tests.rs @@ -1,3 +1,19 @@ +// Copyright (C) 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 . + mod justification { mod equivocation; mod optimizer; diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index ecb0bdc4079d1..83530438361c8 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-messages" description = "Primitives of messages module." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -27,14 +27,14 @@ hex = "0.4" hex-literal = "0.4" [features] -default = ["std"] +default = [ "std" ] std = [ - "bp-runtime/std", "bp-header-chain/std", + "bp-runtime/std", "codec/std", "frame-support/std", "scale-info/std", "serde/std", "sp-core/std", - "sp-std/std" + "sp-std/std", ] diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 84c41de3b361f..e48914f759186 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -26,13 +26,13 @@ use bp_runtime::{ StorageProofError, }; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{PalletError, RuntimeDebug}; +use frame_support::PalletError; // Weight is reexported to avoid additional frame-support dependencies in related crates. pub use frame_support::weights::Weight; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use source_chain::RelayersRewards; -use sp_core::TypeId; +use sp_core::{RuntimeDebug, TypeId}; use sp_std::{collections::vec_deque::VecDeque, ops::RangeInclusive, prelude::*}; pub mod source_chain; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 3cc78522baf1e..73092c3cce0a5 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -20,7 +20,8 @@ use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData, Verificatio use crate::UnrewardedRelayer; use bp_runtime::Size; -use frame_support::{Parameter, RuntimeDebug}; +use frame_support::Parameter; +use sp_core::RuntimeDebug; use sp_std::{ collections::{btree_map::BTreeMap, vec_deque::VecDeque}, fmt::Debug, diff --git a/primitives/messages/src/storage_keys.rs b/primitives/messages/src/storage_keys.rs index 4edf9828cfde0..8eedf8fcc7ac9 100644 --- a/primitives/messages/src/storage_keys.rs +++ b/primitives/messages/src/storage_keys.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/messages/src/target_chain.rs b/primitives/messages/src/target_chain.rs index 60f5c1b3c1c5b..388ce16ccdc06 100644 --- a/primitives/messages/src/target_chain.rs +++ b/primitives/messages/src/target_chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -22,8 +22,9 @@ use crate::{ use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode, Error as CodecError}; -use frame_support::{weights::Weight, Parameter, RuntimeDebug}; +use frame_support::{weights::Weight, Parameter}; use scale_info::TypeInfo; +use sp_core::RuntimeDebug; use sp_std::{collections::btree_map::BTreeMap, fmt::Debug, marker::PhantomData, prelude::*}; /// Proved messages from the source chain. diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 6cd138c62249a..40d62ff41389f 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-parachains" description = "Primitives of parachains module." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -25,7 +25,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index e619fc7b641af..262b9c6f97752 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -29,10 +29,10 @@ use bp_runtime::{ StorageMapKeyProvider, }; use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{Blake2_128Concat, RuntimeDebug, Twox64Concat}; +use frame_support::{Blake2_128Concat, Twox64Concat}; use scale_info::TypeInfo; use sp_core::storage::StorageKey; -use sp_runtime::traits::Header as HeaderT; +use sp_runtime::{traits::Header as HeaderT, RuntimeDebug}; use sp_std::{marker::PhantomData, prelude::*}; /// Best known parachain head hash. diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index b7ba480347387..694b78d1a0799 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-polkadot-core" description = "Primitives of Polkadot-like runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -29,13 +29,13 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d hex = "0.4" [features] -default = ["std"] +default = [ "std" ] std = [ "bp-messages/std", "bp-runtime/std", + "codec/std", "frame-support/std", "frame-system/std", - "codec/std", "parity-util-mem", "scale-info/std", "serde", diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 945b56cdc62eb..af39b5ab9baba 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -33,14 +33,14 @@ use frame_support::{ constants::{BlockExecutionWeight, WEIGHT_REF_TIME_PER_SECOND}, Weight, }, - Blake2_128Concat, RuntimeDebug, + Blake2_128Concat, }; use frame_system::limits; use sp_core::{storage::StorageKey, Hasher as HasherT}; use sp_runtime::{ generic, traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiAddress, MultiSignature, OpaqueExtrinsic, + MultiAddress, MultiSignature, OpaqueExtrinsic, RuntimeDebug, }; use sp_std::prelude::Vec; diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 9cac3279c7285..3cf8eca0c6b6d 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -24,9 +24,9 @@ use bp_runtime::{RawStorageProof, Size}; use codec::{CompactAs, Decode, Encode, MaxEncodedLen}; -use frame_support::RuntimeDebug; use scale_info::TypeInfo; use sp_core::Hasher; +use sp_runtime::RuntimeDebug; use sp_std::vec::Vec; #[cfg(feature = "std")] diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index fd2c9e19f9841..6be26ec96b043 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-relayers" description = "Primitives of relayers module." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -26,7 +26,7 @@ hex = "0.4" hex-literal = "0.4" [features] -default = ["std"] +default = [ "std" ] std = [ "bp-messages/std", "bp-runtime/std", diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index 21f66a2ffa100..c529eea536d73 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/relayers/src/registration.rs b/primitives/relayers/src/registration.rs index 7ab20844bdf93..bc2d0d127aefe 100644 --- a/primitives/relayers/src/registration.rs +++ b/primitives/relayers/src/registration.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index dea3c979b8628..2e38019b53ab4 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -2,14 +2,15 @@ name = "bp-runtime" description = "Primitives that may be used at (bridges) runtime level." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" +log = { version = "0.4.19", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } @@ -30,20 +31,21 @@ trie-db = { version = "0.27.1", default-features = false } hex-literal = "0.4" [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", "frame-system/std", "hash-db/std", + "log/std", "num-traits/std", "scale-info/std", "serde/std", "sp-core/std", "sp-io/std", "sp-runtime/std", - "sp-std/std", "sp-state-machine/std", + "sp-std/std", "sp-trie/std", "trie-db/std", ] diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 43fdaf8da1b7f..5caaebd42babc 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index 9fa8fb5222adb..44eeaad93c916 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 150e015cb4f12..e5f1afb4161d6 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -20,14 +20,16 @@ use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; use frame_support::{ - log, pallet_prelude::DispatchResult, weights::Weight, PalletError, RuntimeDebug, StorageHasher, - StorageValue, + pallet_prelude::DispatchResult, weights::Weight, PalletError, StorageHasher, StorageValue, }; use frame_system::RawOrigin; use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_core::storage::StorageKey; -use sp_runtime::traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto}; +use sp_runtime::{ + traits::{BadOrigin, Header as HeaderT, UniqueSaturatedInto}, + RuntimeDebug, +}; use sp_std::{convert::TryFrom, fmt::Debug, ops::RangeInclusive, vec, vec::Vec}; pub use chain::{ diff --git a/primitives/runtime/src/messages.rs b/primitives/runtime/src/messages.rs index d308582957839..0f219e984f728 100644 --- a/primitives/runtime/src/messages.rs +++ b/primitives/runtime/src/messages.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -17,8 +17,9 @@ //! Primitives that may be used by different message delivery and dispatch mechanisms. use codec::{Decode, Encode}; -use frame_support::{weights::Weight, RuntimeDebug}; +use frame_support::weights::Weight; use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; /// Message dispatch result. #[derive(Encode, Decode, RuntimeDebug, Clone, PartialEq, Eq, TypeInfo)] diff --git a/primitives/runtime/src/storage_proof.rs b/primitives/runtime/src/storage_proof.rs index 09641376666af..1b706aa66c16f 100644 --- a/primitives/runtime/src/storage_proof.rs +++ b/primitives/runtime/src/storage_proof.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/runtime/src/storage_types.rs b/primitives/runtime/src/storage_types.rs index b37f779d00b32..91c5451805a98 100644 --- a/primitives/runtime/src/storage_types.rs +++ b/primitives/runtime/src/storage_types.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -18,8 +18,9 @@ //! during conversion. use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{traits::Get, RuntimeDebug}; +use frame_support::traits::Get; use scale_info::{Type, TypeInfo}; +use sp_runtime::RuntimeDebug; use sp_std::{marker::PhantomData, ops::Deref}; /// Error that is returned when the value size exceeds maximal configured size. diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 2e2af99332eab..8b9029749411a 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "bp-test-utils" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } @@ -21,10 +22,12 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", d sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", + "bp-parachains/std", "bp-polkadot-core/std", + "bp-runtime/std", "codec/std", "ed25519-dalek/std", "finality-grandpa/std", @@ -33,4 +36,5 @@ std = [ "sp-core/std", "sp-runtime/std", "sp-std/std", + "sp-trie/std", ] diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index a4e818a3b8880..b99132de3ec36 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 5a7d0cca279a0..4d3b84759938b 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index ca17f52d169b4..18cf3791a4953 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-xcm-bridge-hub-router" description = "Primitives of the xcm-bridge-hub fee pallet." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -15,10 +15,5 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } [features] -default = ["std"] -std = [ - "codec/std", - "scale-info/std", - "sp-runtime/std", - "sp-core/std", -] +default = [ "std" ] +std = [ "codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std" ] diff --git a/primitives/xcm-bridge-hub-router/src/lib.rs b/primitives/xcm-bridge-hub-router/src/lib.rs index 0dd329f9e4a0e..dbedb7a52c7fe 100644 --- a/primitives/xcm-bridge-hub-router/src/lib.rs +++ b/primitives/xcm-bridge-hub-router/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 From a2e4ba42792ddf8570505116227e10d8f9821df7 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 1 Sep 2023 11:32:41 +0200 Subject: [PATCH 1099/1210] Fix benchmark with new XCM::V3 `MAX_INSTRUCTIONS_TO_DECODE` (#2514) * Fix benchmark with new XCM::V3 MAX_INSTRUCTIONS_TO_DECODE * Small refactor * `ClearOrigin` replaced by ExpectPallet * Doc * Spellcheck * Fixes and pr reviews --- bin/millau/runtime/src/lib.rs | 5 +- .../src/messages_benchmarking.rs | 87 ++++++++++++++----- modules/messages/src/weights_ext.rs | 4 +- 3 files changed, 71 insertions(+), 25 deletions(-) diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 2067dfccb562f..66d78fc3c810e 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -1036,6 +1036,7 @@ impl_runtime_apis! { ]; use bridge_runtime_common::messages_benchmarking::{ + generate_xcm_builder_bridge_message_sample, prepare_message_delivery_proof_from_grandpa_chain, prepare_message_delivery_proof_from_parachain, prepare_message_proof_from_grandpa_chain, @@ -1070,7 +1071,7 @@ impl_runtime_apis! { Runtime, WithRialtoParachainsInstance, WithRialtoParachainMessageBridge, - >(params, xcm::v3::Junctions::Here) + >(params, generate_xcm_builder_bridge_message_sample(xcm::v3::Junctions::Here)) } fn prepare_message_delivery_proof( @@ -1101,7 +1102,7 @@ impl_runtime_apis! { Runtime, RialtoGrandpaInstance, WithRialtoMessageBridge, - >(params, xcm::v3::Junctions::Here) + >(params, generate_xcm_builder_bridge_message_sample(xcm::v3::Junctions::Here)) } fn prepare_message_delivery_proof( diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index 60f4bb17858c6..d80a88f1068c8 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -29,7 +29,7 @@ use crate::{ }, }; -use bp_messages::storage_keys; +use bp_messages::{storage_keys, MessagePayload}; use bp_polkadot_core::parachains::ParaHash; use bp_runtime::{ record_all_trie_keys, Chain, Parachain, RawStorageProof, StorageProofSize, UnderlyingChainOf, @@ -45,8 +45,8 @@ use xcm::v3::prelude::*; /// Prepare inbound bridge message according to given message proof parameters. fn prepare_inbound_message( params: &MessageProofParams, - destination: InteriorMultiLocation, -) -> Vec { + successful_dispatch_message_generator: impl Fn(usize) -> MessagePayload, +) -> MessagePayload { // we only care about **this** message size when message proof needs to be `Minimal` let expected_size = match params.size { StorageProofSize::Minimal(size) => size as usize, @@ -58,20 +58,15 @@ fn prepare_inbound_message( return vec![0u8; expected_size] } - // else let's prepare successful message. For XCM bridge hubs, it is the message that - // will be pushed further to some XCM queue (XCMP/UMP) - let location = xcm::VersionedInteriorMultiLocation::V3(destination); - let location_encoded_size = location.encoded_size(); - - // we don't need to be super-precise with `expected_size` here - let xcm_size = expected_size.saturating_sub(location_encoded_size); - let xcm = xcm::VersionedXcm::<()>::V3(vec![Instruction::ClearOrigin; xcm_size].into()); - - // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor - // or public fields, so just tuple - // (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed - // to the storage) - (location, xcm).encode().encode() + // else let's prepare successful message. + let msg = successful_dispatch_message_generator(expected_size); + assert!( + msg.len() >= expected_size, + "msg.len(): {} does not match expected_size: {}", + expected_size, + msg.len() + ); + msg } /// Prepare proof of messages for the `receive_messages_proof` call. @@ -84,7 +79,7 @@ fn prepare_inbound_message( /// function. pub fn prepare_message_proof_from_grandpa_chain( params: MessageProofParams, - message_destination: InteriorMultiLocation, + message_generator: impl Fn(usize) -> MessagePayload, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: pallet_bridge_grandpa::Config>>, @@ -97,7 +92,7 @@ where params.message_nonces.clone(), params.outbound_lane_data.clone(), params.size, - prepare_inbound_message(¶ms, message_destination), + prepare_inbound_message(¶ms, message_generator), encode_all_messages, encode_lane_data, ); @@ -127,7 +122,7 @@ where /// `prepare_message_proof_from_grandpa_chain` function. pub fn prepare_message_proof_from_parachain( params: MessageProofParams, - message_destination: InteriorMultiLocation, + message_generator: impl Fn(usize) -> MessagePayload, ) -> (FromBridgedChainMessagesProof>>, Weight) where R: pallet_bridge_parachains::Config, @@ -141,7 +136,7 @@ where params.message_nonces.clone(), params.outbound_lane_data.clone(), params.size, - prepare_inbound_message(¶ms, message_destination), + prepare_inbound_message(¶ms, message_generator), encode_all_messages, encode_lane_data, ); @@ -291,3 +286,53 @@ where pallet_bridge_parachains::initialize_for_benchmarks::(bridged_header); (bridged_block_number, bridged_header_hash) } + +/// Returns callback which generates `BridgeMessage` from Polkadot XCM builder based on +/// `expected_message_size` for benchmark. +pub fn generate_xcm_builder_bridge_message_sample( + destination: InteriorMultiLocation, +) -> impl Fn(usize) -> MessagePayload { + move |expected_message_size| -> MessagePayload { + // For XCM bridge hubs, it is the message that + // will be pushed further to some XCM queue (XCMP/UMP) + let location = xcm::VersionedInteriorMultiLocation::V3(destination); + let location_encoded_size = location.encoded_size(); + + // we don't need to be super-precise with `expected_size` here + let xcm_size = expected_message_size.saturating_sub(location_encoded_size); + let xcm_data_size = xcm_size.saturating_sub( + // minus empty instruction size + xcm::v3::Instruction::<()>::ExpectPallet { + index: 0, + name: vec![], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + } + .encoded_size(), + ); + + log::trace!( + target: "runtime::bridge-benchmarks", + "generate_xcm_builder_bridge_message_sample with expected_message_size: {}, location_encoded_size: {}, xcm_size: {}, xcm_data_size: {}", + expected_message_size, location_encoded_size, xcm_size, xcm_data_size, + ); + + let xcm = xcm::VersionedXcm::<()>::V3( + vec![xcm::v3::Instruction::<()>::ExpectPallet { + index: 0, + name: vec![42; xcm_data_size], + module_name: vec![], + crate_major: 0, + min_crate_minor: 0, + }] + .into(), + ); + + // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor + // or public fields, so just tuple + // (double encoding, because `.encode()` is called on original Xcm BLOB when it is pushed + // to the storage) + (location, xcm).encode().encode() + } +} diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index 1be24a738a495..aeb3a581a69ee 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -29,8 +29,8 @@ pub const EXPECTED_DEFAULT_MESSAGE_LENGTH: u32 = 128; /// calls we're checking here would fit 1KB. const SIGNED_EXTENSIONS_SIZE: u32 = 1024; -/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at -/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie. +/// Number of extra bytes (excluding size of storage value itself) of storage proof. +/// This mostly depends on number of entries (and their density) in the storage trie. /// Some reserve is reserved to account future chain growth. pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; From d1c9fb53f87c1f09aa4a9ee51ebc4039fe082df4 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 4 Sep 2023 10:14:39 +0300 Subject: [PATCH 1100/1210] `polkadot-staging` branch: Use polkadot-sdk dependencies (#2524) * Use polkadot-sdk dependencies * Fix ring-proof ref * Fix Beefy * Fix imports * Simple runtimes fixes * Fix substrate-relay * Add ParaAssignmentProvider for Rialto * Rialto chain_spec fix * Fix Rialto build * Fix Rialto pvf workers * Allow rialto-parachain deprecated features warnings --- bin/millau/node/Cargo.toml | 66 +++++++-------- bin/millau/node/src/chain_spec.rs | 2 +- bin/millau/node/src/service.rs | 2 +- bin/millau/runtime/Cargo.toml | 70 ++++++++-------- bin/millau/runtime/src/lib.rs | 15 ++-- bin/millau/runtime/src/rialto_messages.rs | 3 +- .../runtime/src/rialto_parachain_messages.rs | 3 +- bin/rialto-parachain/node/Cargo.toml | 82 +++++++++---------- bin/rialto-parachain/node/src/lib.rs | 1 + bin/rialto-parachain/node/src/main.rs | 1 + bin/rialto-parachain/node/src/service.rs | 27 ++---- bin/rialto-parachain/runtime/Cargo.toml | 78 +++++++++--------- bin/rialto-parachain/runtime/src/lib.rs | 5 +- .../runtime/src/millau_messages.rs | 3 +- bin/rialto/node/Cargo.toml | 49 ++++++----- bin/rialto/node/src/chain_spec.rs | 6 +- bin/rialto/node/src/cli.rs | 8 -- bin/rialto/node/src/command.rs | 65 ++++----------- bin/rialto/node/src/workers/execute-worker.rs | 23 ++++++ bin/rialto/node/src/workers/prepare-worker.rs | 23 ++++++ bin/rialto/runtime/Cargo.toml | 80 +++++++++--------- bin/rialto/runtime/src/lib.rs | 11 +-- bin/rialto/runtime/src/millau_messages.rs | 3 +- bin/rialto/runtime/src/parachains.rs | 16 +++- bin/runtime-common/Cargo.toml | 26 +++--- modules/beefy/Cargo.toml | 18 ++-- modules/beefy/src/lib.rs | 12 ++- modules/beefy/src/mock.rs | 4 +- modules/beefy/src/mock_chain.rs | 2 +- modules/beefy/src/utils.rs | 2 +- modules/grandpa/Cargo.toml | 18 ++-- modules/messages/Cargo.toml | 16 ++-- modules/parachains/Cargo.toml | 16 ++-- modules/relayers/Cargo.toml | 20 ++--- modules/shift-session-manager/Cargo.toml | 16 ++-- modules/shift-session-manager/src/lib.rs | 4 +- modules/xcm-bridge-hub-router/Cargo.toml | 20 ++--- primitives/beefy/Cargo.toml | 14 ++-- primitives/beefy/src/lib.rs | 4 +- primitives/chain-asset-hub-kusama/Cargo.toml | 2 +- .../chain-asset-hub-polkadot/Cargo.toml | 4 +- .../chain-bridge-hub-cumulus/Cargo.toml | 10 +-- primitives/chain-bridge-hub-kusama/Cargo.toml | 8 +- .../chain-bridge-hub-polkadot/Cargo.toml | 8 +- primitives/chain-bridge-hub-rococo/Cargo.toml | 8 +- primitives/chain-bridge-hub-wococo/Cargo.toml | 8 +- primitives/chain-kusama/Cargo.toml | 6 +- primitives/chain-millau/Cargo.toml | 16 ++-- primitives/chain-millau/src/lib.rs | 3 +- primitives/chain-polkadot/Cargo.toml | 6 +- primitives/chain-rialto-parachain/Cargo.toml | 12 +-- primitives/chain-rialto-parachain/src/lib.rs | 3 +- primitives/chain-rialto/Cargo.toml | 12 +-- primitives/chain-rialto/src/lib.rs | 3 +- primitives/chain-rococo/Cargo.toml | 6 +- primitives/chain-westend/Cargo.toml | 6 +- primitives/chain-westend/src/lib.rs | 3 +- primitives/chain-wococo/Cargo.toml | 6 +- primitives/header-chain/Cargo.toml | 10 +-- primitives/messages/Cargo.toml | 6 +- primitives/parachains/Cargo.toml | 8 +- primitives/polkadot-core/Cargo.toml | 10 +-- primitives/relayers/Cargo.toml | 6 +- primitives/runtime/Cargo.toml | 16 ++-- primitives/test-utils/Cargo.toml | 12 +-- primitives/xcm-bridge-hub-router/Cargo.toml | 4 +- relays/bin-substrate/Cargo.toml | 20 ++--- .../src/cli/register_parachain.rs | 2 +- relays/client-bridge-hub-kusama/Cargo.toml | 4 +- relays/client-bridge-hub-polkadot/Cargo.toml | 6 +- relays/client-bridge-hub-rococo/Cargo.toml | 6 +- relays/client-bridge-hub-wococo/Cargo.toml | 8 +- relays/client-kusama/Cargo.toml | 10 +-- relays/client-millau/Cargo.toml | 12 +-- relays/client-polkadot/Cargo.toml | 10 +-- relays/client-rialto-parachain/Cargo.toml | 6 +- relays/client-rialto/Cargo.toml | 12 +-- relays/client-rococo/Cargo.toml | 10 +-- relays/client-substrate/Cargo.toml | 34 ++++---- relays/client-substrate/src/chain.rs | 2 +- relays/client-westend/Cargo.toml | 4 +- relays/client-wococo/Cargo.toml | 6 +- relays/equivocation/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 16 ++-- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 4 +- 87 files changed, 622 insertions(+), 592 deletions(-) create mode 100644 bin/rialto/node/src/workers/execute-worker.rs create mode 100644 bin/rialto/node/src/workers/prepare-worker.rs diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index d551694422ace..0903aab9e606c 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -20,41 +20,41 @@ millau-runtime = { path = "../runtime" } # Substrate Dependencies -sc-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-beefy-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } -node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } -mmr-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master"} -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-consensus-beefy-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +node-inspect = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +mmr-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master"} +sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-network = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-network-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [] diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs index f985d4d9783ec..01883bb4ef083 100644 --- a/bin/millau/node/src/chain_spec.rs +++ b/bin/millau/node/src/chain_spec.rs @@ -21,7 +21,7 @@ use millau_runtime::{ WASM_BINARY, }; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_consensus_beefy::crypto::AuthorityId as BeefyId; +use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 954b46fe0ceda..1e31ecdd14d59 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -62,7 +62,7 @@ pub fn new_partial( FullClient, FullBackend, FullSelectChain, - sc_consensus::DefaultImportQueue, + sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( sc_consensus_grandpa::GrandpaBlockImport< diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index ccff85b99eb60..57586fb961f7a 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -34,42 +34,42 @@ pallet-xcm-bridge-hub-router = { path = "../../../modules/xcm-bridge-hub-router" # Substrate Dependencies -sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["historical"]} -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-aura = { 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-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["historical"]} +pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Polkadot Dependencies -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test", "std"] } @@ -77,7 +77,7 @@ env_logger = "0.10" static_assertions = "1.1" [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = ["std"] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 66d78fc3c810e..4fd9a098fc044 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -43,7 +43,7 @@ use pallet_grandpa::{ use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_consensus_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; +use sp_consensus_beefy::{ecdsa_crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use sp_core::OpaqueMetadata; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -73,7 +73,7 @@ pub use frame_support::{ constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, }, - RuntimeDebug, StorageValue, + StorageValue, }; pub use frame_system::Call as SystemCall; @@ -797,7 +797,7 @@ impl_runtime_apis! { } } - impl sp_consensus_beefy::BeefyApi for Runtime { + impl sp_consensus_beefy::BeefyApi for Runtime { fn beefy_genesis() -> Option { Beefy::genesis_block() } @@ -809,15 +809,15 @@ impl_runtime_apis! { fn submit_report_equivocation_unsigned_extrinsic( _equivocation_proof: sp_consensus_beefy::EquivocationProof< NumberFor, - sp_consensus_beefy::crypto::AuthorityId, - sp_consensus_beefy::crypto::Signature + sp_consensus_beefy::ecdsa_crypto::AuthorityId, + sp_consensus_beefy::ecdsa_crypto::Signature >, _key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( _set_id: sp_consensus_beefy::ValidatorSetId, - _authority_id: sp_consensus_beefy::crypto::AuthorityId, + _authority_id: sp_consensus_beefy::ecdsa_crypto::AuthorityId, ) -> Option { None } } @@ -1020,7 +1020,8 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig, ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch}; + use frame_support::traits::TrackedStorageKey; let whitelist: Vec = vec![ // Block Number diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs index 884f994feaaf1..8b778600f9723 100644 --- a/bin/millau/runtime/src/rialto_messages.rs +++ b/bin/millau/runtime/src/rialto_messages.rs @@ -25,8 +25,9 @@ use bridge_runtime_common::{ }, messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; -use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use frame_support::{parameter_types, weights::Weight}; use pallet_bridge_relayers::WeightInfoExt as _; +use sp_runtime::RuntimeDebug; use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs index 2eff0835c39ef..1c4807f0cd332 100644 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ b/bin/millau/runtime/src/rialto_parachain_messages.rs @@ -27,8 +27,9 @@ use bridge_runtime_common::{ }, messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; -use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use frame_support::{parameter_types, weights::Weight}; use pallet_bridge_relayers::WeightInfoExt as _; +use sp_runtime::RuntimeDebug; use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 537098bbd6e61..ced2d809c1456 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [[bin]] name = 'rialto-parachain-collator' @@ -29,53 +29,53 @@ jsonrpsee = { version = "0.16.2", features = ["server"] } rialto-parachain-runtime = { path = '../runtime' } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } ## Substrate Client Dependencies -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-network-sync = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "master"} -sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" } +sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-network = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-network-sync = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master"} +sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-tracing = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } ## Substrate Primitive Dependencies -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } # Cumulus dependencies -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "master" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "master" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-client-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-client-network = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-client-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } # Polkadot dependencies -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/bin/rialto-parachain/node/src/lib.rs b/bin/rialto-parachain/node/src/lib.rs index 3ec291596b719..5dd2a8af861b1 100644 --- a/bin/rialto-parachain/node/src/lib.rs +++ b/bin/rialto-parachain/node/src/lib.rs @@ -15,4 +15,5 @@ // along with Parity Bridges Common. If not, see . pub mod chain_spec; +#[allow(deprecated)] pub mod service; diff --git a/bin/rialto-parachain/node/src/main.rs b/bin/rialto-parachain/node/src/main.rs index 2b4e0b438d1a9..ca93efa067cc9 100644 --- a/bin/rialto-parachain/node/src/main.rs +++ b/bin/rialto-parachain/node/src/main.rs @@ -20,6 +20,7 @@ mod chain_spec; #[macro_use] +#[allow(deprecated)] mod service; mod cli; mod command; diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index e244f6018f641..c43241d4945f3 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -95,7 +95,7 @@ pub fn new_partial( ParachainClient, ParachainBackend, (), - sc_consensus::DefaultImportQueue>, + sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool>, (ParachainBlockImport, Option, Option), >, @@ -106,10 +106,8 @@ where RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys - + sp_api::ApiExt< - Block, - StateBackend = sc_client_api::StateBackendFor, - > + sp_offchain::OffchainWorkerApi + + sp_api::ApiExt + + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder, sc_client_api::StateBackendFor: sp_api::StateBackend, BIQ: FnOnce( @@ -118,10 +116,7 @@ where &Configuration, Option, &TaskManager, - ) -> Result< - sc_consensus::DefaultImportQueue>, - sc_service::Error, - >, + ) -> Result, sc_service::Error>, { let telemetry = config .telemetry_endpoints @@ -213,10 +208,8 @@ where RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + sp_api::Metadata + sp_session::SessionKeys - + sp_api::ApiExt< - Block, - StateBackend = sc_client_api::StateBackendFor, - > + sp_offchain::OffchainWorkerApi + + sp_api::ApiExt + + sp_offchain::OffchainWorkerApi + sp_block_builder::BlockBuilder + cumulus_primitives_core::CollectCollationInfo, sc_client_api::StateBackendFor: sp_api::StateBackend, @@ -234,10 +227,7 @@ where &Configuration, Option, &TaskManager, - ) -> Result< - sc_consensus::DefaultImportQueue>, - sc_service::Error, - >, + ) -> Result, sc_service::Error>, BIC: FnOnce( Arc>, ParachainBlockImport, @@ -389,8 +379,7 @@ pub fn parachain_build_import_queue( config: &Configuration, telemetry: Option, task_manager: &TaskManager, -) -> Result>, sc_service::Error> -{ +) -> Result, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; cumulus_client_consensus_aura::import_queue::< diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index f2893633e7fa5..8f987e27f362c 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} @@ -30,51 +30,51 @@ pallet-bridge-relayers = { path = "../../../modules/relayers", default-features # Substrate Dependencies ## Substrate Primitive Dependencies -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-block-builder = { 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-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } ## Substrate FRAME Dependencies -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } ## Substrate Pallet Dependencies -pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Cumulus Dependencies -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "master", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +parachain-info = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Polkadot Dependencies -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } @@ -127,7 +127,7 @@ std = [ "pallet-transaction-payment-rpc-runtime-api/std", "pallet-xcm/std", "parachain-info/std", - "polkadot-parachain/std", + "polkadot-parachain-primitives/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-parachain-system/std", "cumulus-pallet-xcmp-queue/std", diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 00e14ed85ed72..e64932d1a443f 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -80,7 +80,7 @@ pub use pallet_xcm::Call as XcmCall; // Polkadot & XCM imports use bridge_runtime_common::CustomNetworkId; use pallet_xcm::XcmPassthrough; -use polkadot_parachain::primitives::Sibling; +use polkadot_parachain_primitives::primitives::Sibling; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, @@ -791,7 +791,8 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark}; + use frame_support::traits::TrackedStorageKey; use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs index fea7fc70c863f..b75a3d520b78a 100644 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ b/bin/rialto-parachain/runtime/src/millau_messages.rs @@ -28,7 +28,8 @@ use bridge_runtime_common::{ }, messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; -use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use frame_support::{parameter_types, weights::Weight}; +use sp_runtime::RuntimeDebug; use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index aa3824e4d51de..e7b91b82182a1 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -1,3 +1,11 @@ +[[bin]] +name = "rialto-bridge-node-execute-worker" +path = "src/workers/execute-worker.rs" + +[[bin]] +name = "rialto-bridge-node-prepare-worker" +path = "src/workers/prepare-worker.rs" + [package] name = "rialto-bridge-node" description = "Substrate node compatible with Rialto runtime" @@ -18,29 +26,32 @@ rialto-runtime = { path = "../runtime" } # Substrate Dependencies -sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -node-inspect = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master"} -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +node-inspect = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master"} +sc-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } # Polkadot Dependencies -polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } +polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-node-core-pvf-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-node-core-pvf-execute-worker = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-node-core-pvf-prepare-worker = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } [build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [] diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index d32dc55296943..505dc5a760b67 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -23,7 +23,7 @@ use rialto_runtime::{ use serde_json::json; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; -use sp_consensus_beefy::crypto::AuthorityId as BeefyId; +use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; @@ -249,8 +249,6 @@ fn testnet_genesis( max_pov_size: polkadot_primitives::v5::MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, - chain_availability_period: 4, - thread_availability_period: 4, max_upward_queue_count: 8, max_upward_queue_size: 1024 * 1024, max_downward_message_size: 1024 * 1024, @@ -261,10 +259,8 @@ fn testnet_genesis( hrmp_channel_max_capacity: 8, hrmp_channel_max_total_size: 8 * 1024, hrmp_max_parachain_inbound_channels: 4, - hrmp_max_parathread_inbound_channels: 4, hrmp_channel_max_message_size: 1024 * 1024, hrmp_max_parachain_outbound_channels: 4, - hrmp_max_parathread_outbound_channels: 4, hrmp_max_message_num_per_candidate: 5, dispute_period: 6, no_show_slots: 2, diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs index c39efed4ce986..521f2268bdc5e 100644 --- a/bin/rialto/node/src/cli.rs +++ b/bin/rialto/node/src/cli.rs @@ -70,14 +70,6 @@ pub enum Subcommand { /// Benchmark runtime pallets. #[command(subcommand)] Benchmark(frame_benchmarking_cli::BenchmarkCmd), - - /// FOR INTERNAL USE: analog of the "prepare-worker" command of the polkadot binary. - #[command(name = "prepare-worker", hide = true)] - PvfPrepareWorker(ValidationWorkerCommand), - - /// FOR INTERNAL USE: analog of the "execute-worker" command of the polkadot binary. - #[command(name = "execute-worker", hide = true)] - PvfExecuteWorker(ValidationWorkerCommand), } /// Validation worker command. diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs index 156d365c20243..397f8a3e24e9b 100644 --- a/bin/rialto/node/src/command.rs +++ b/bin/rialto/node/src/command.rs @@ -155,60 +155,29 @@ pub fn run() -> sc_cli::Result<()> { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run::(config)) }, - Some(Subcommand::PvfPrepareWorker(cmd)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_colors(false); - let _ = builder.init(); - - polkadot_node_core_pvf::prepare_worker_entrypoint( - &cmd.socket_path, - Some(&cmd.node_impl_version), - ); - Ok(()) - }, - Some(crate::cli::Subcommand::PvfExecuteWorker(cmd)) => { - let mut builder = sc_cli::LoggerBuilder::new(""); - builder.with_colors(false); - let _ = builder.init(); - - polkadot_node_core_pvf::execute_worker_entrypoint( - &cmd.socket_path, - Some(&cmd.node_impl_version), - ); - Ok(()) - }, None => { let runner = cli.create_runner(&cli.run)?; - // some parameters that are used by polkadot nodes, but that are not used by our binary - // let jaeger_agent = None; - // let grandpa_pause = None; - // let no_beefy = true; - // let telemetry_worker_handler = None; - // let is_collator = crate::service::IsCollator::No; - let overseer_gen = polkadot_service::overseer::RealOverseerGen; runner.run_node_until_exit(|config| async move { - let is_collator = polkadot_service::IsCollator::No; - let grandpa_pause = None; - let enable_beefy = true; - let jaeger_agent = None; - let telemetry_worker_handle = None; - let program_path = None; - let overseer_enable_anyways = false; - polkadot_service::new_full( config, - is_collator, - grandpa_pause, - enable_beefy, - jaeger_agent, - telemetry_worker_handle, - program_path, - overseer_enable_anyways, - overseer_gen, - None, - None, - None, + polkadot_service::NewFullParams { + is_parachain_node: polkadot_service::IsParachainNode::No, + grandpa_pause: None, + enable_beefy: true, + jaeger_agent: None, + telemetry_worker_handle: None, + node_version: None, + workers_path: None, + workers_names: Some(( + "rialto-bridge-node-prepare-worker".to_string(), + "rialto-bridge-node-execute-worker".to_string(), + )), + overseer_gen: polkadot_service::overseer::RealOverseerGen, + overseer_message_channel_capacity_override: None, + malus_finality_delay: None, + hwbench: None, + }, ) .map(|full| full.task_manager) .map_err(service_error) diff --git a/bin/rialto/node/src/workers/execute-worker.rs b/bin/rialto/node/src/workers/execute-worker.rs new file mode 100644 index 0000000000000..72cab799d753e --- /dev/null +++ b/bin/rialto/node/src/workers/execute-worker.rs @@ -0,0 +1,23 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Execute worker. + +polkadot_node_core_pvf_common::decl_worker_main!( + "execute-worker", + polkadot_node_core_pvf_execute_worker::worker_entrypoint, + env!("SUBSTRATE_CLI_IMPL_VERSION") +); diff --git a/bin/rialto/node/src/workers/prepare-worker.rs b/bin/rialto/node/src/workers/prepare-worker.rs new file mode 100644 index 0000000000000..695f66cc7b7d3 --- /dev/null +++ b/bin/rialto/node/src/workers/prepare-worker.rs @@ -0,0 +1,23 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +//! Prepare worker. + +polkadot_node_core_pvf_common::decl_worker_main!( + "prepare-worker", + polkadot_node_core_pvf_prepare_worker::worker_entrypoint, + env!("SUBSTRATE_CLI_IMPL_VERSION") +); diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 7f1b18bf99cb2..d8b402d310979 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -27,47 +27,47 @@ pallet-shift-session-manager = { path = "../../../modules/shift-session-manager" # Substrate Dependencies -sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["historical"]} -pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-babe = { 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-inherents = { 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-offchain = { 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-session = { 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-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["historical"]} +pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Polkadot (parachain) Dependencies -pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } @@ -75,7 +75,7 @@ env_logger = "0.10" static_assertions = "1.1" [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "master" } +substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = ["std"] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 95c1f60b601c1..d149421864f6f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -39,7 +39,7 @@ use pallet_grandpa::{ use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_consensus_beefy::{crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; +use sp_consensus_beefy::{ecdsa_crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; use sp_core::OpaqueMetadata; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, @@ -502,6 +502,7 @@ construct_runtime!( ParaSessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, ParasDisputes: polkadot_runtime_parachains::disputes::{Pallet, Call, Storage, Event}, ParasSlashing: polkadot_runtime_parachains::disputes::slashing::{Pallet, Call, Storage, ValidateUnsigned}, + ParaAssignmentProvider: polkadot_runtime_parachains::assigner_parachains::{Pallet}, MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event}, // Parachain Onboarding Pallets @@ -617,7 +618,7 @@ impl_runtime_apis! { } } - impl sp_consensus_beefy::BeefyApi for Runtime { + impl sp_consensus_beefy::BeefyApi for Runtime { fn beefy_genesis() -> Option { Beefy::genesis_block() } @@ -629,15 +630,15 @@ impl_runtime_apis! { fn submit_report_equivocation_unsigned_extrinsic( _equivocation_proof: sp_consensus_beefy::EquivocationProof< NumberFor, - sp_consensus_beefy::crypto::AuthorityId, - sp_consensus_beefy::crypto::Signature + sp_consensus_beefy::ecdsa_crypto::AuthorityId, + sp_consensus_beefy::ecdsa_crypto::Signature >, _key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( _set_id: sp_consensus_beefy::ValidatorSetId, - _authority_id: sp_consensus_beefy::crypto::AuthorityId, + _authority_id: sp_consensus_beefy::ecdsa_crypto::AuthorityId, ) -> Option { None } } diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs index 4efef0bf1e56e..03e4c494cf2a4 100644 --- a/bin/rialto/runtime/src/millau_messages.rs +++ b/bin/rialto/runtime/src/millau_messages.rs @@ -25,7 +25,8 @@ use bridge_runtime_common::{ }, messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, }; -use frame_support::{parameter_types, weights::Weight, RuntimeDebug}; +use frame_support::{parameter_types, weights::Weight}; +use sp_runtime::RuntimeDebug; use xcm::latest::prelude::*; use xcm_builder::HaulBlobExporter; diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index 63d7dc6d1456a..aba204af7cf65 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -17,8 +17,9 @@ //! Parachains support in Rialto runtime. use crate::{ - xcm_config, AccountId, Babe, Balance, Balances, BlockNumber, Registrar, Runtime, RuntimeCall, - RuntimeEvent, RuntimeOrigin, ShiftSessionManager, Slots, UncheckedExtrinsic, + xcm_config, AccountId, Babe, Balance, Balances, BlockNumber, ParaAssignmentProvider, Registrar, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ShiftSessionManager, Slots, + UncheckedExtrinsic, }; use frame_support::{ @@ -135,6 +136,11 @@ impl parachains_paras::WeightInfo for ParasWeightInfo { fn force_set_current_head(_s: u32) -> Weight { Weight::zero() } + + fn force_set_most_recent_context() -> Weight { + Weight::zero() + } + fn force_schedule_code_upgrade(_c: u32) -> Weight { Weight::zero() } @@ -171,7 +177,11 @@ impl parachains_paras_inherent::Config for Runtime { type WeightInfo = parachains_paras_inherent::TestWeightInfo; } -impl parachains_scheduler::Config for Runtime {} +impl polkadot_runtime_parachains::assigner_parachains::Config for Runtime {} + +impl parachains_scheduler::Config for Runtime { + type AssignmentProvider = ParaAssignmentProvider; +} impl parachains_session_info::Config for Runtime { type ValidatorSet = ShiftSessionManager; diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 91460e28b6194..602f6ac95f823 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -29,24 +29,24 @@ pallet-bridge-relayers = { path = "../../modules/relayers", default-features = f # Substrate dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-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 } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Polkadot dependencies -xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } -xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "master" } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "master" } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [ "std" ] diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 202d30b170579..10923e2e1e737 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -18,19 +18,19 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] -sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.3.2" } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } rand = "0.8" -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } bp-test-utils = { path = "../../primitives/test-utils" } [features] diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index 4bbe48ca0c6aa..8637e9f190c18 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -441,7 +441,11 @@ mod tests { InitializationData { operating_mode: BasicOperatingMode::Normal, best_block_number: 0, - authority_set: BeefyAuthoritySet { id: 0, len: 1, root: [0u8; 32].into() } + authority_set: BeefyAuthoritySet { + id: 0, + len: 1, + keyset_commitment: [0u8; 32].into() + } } ), Error::::AlreadyInitialized, @@ -458,7 +462,11 @@ mod tests { InitializationData { operating_mode: BasicOperatingMode::Normal, best_block_number: 0, - authority_set: BeefyAuthoritySet { id: 0, len: 0, root: [0u8; 32].into() } + authority_set: BeefyAuthoritySet { + id: 0, + len: 0, + keyset_commitment: [0u8; 32].into() + } } ), Error::::InvalidInitialAuthoritySet, diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 3eeabab4be29f..3985d25c32f07 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -32,7 +32,7 @@ use sp_runtime::{ Perbill, }; -pub use sp_consensus_beefy::crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; +pub use sp_consensus_beefy::ecdsa_crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; use sp_core::crypto::Wraps; use sp_runtime::traits::Keccak256; @@ -194,7 +194,7 @@ pub fn validator_ids(index: u32, count: u32) -> Vec { pub fn authority_set_info(id: u64, validators: &Vec) -> TestBridgedAuthoritySetInfo { let merkle_root = get_authorities_mmr_root::(validators.iter()); - TestBridgedAuthoritySetInfo { id, len: validators.len() as u32, root: merkle_root } + TestBridgedAuthoritySetInfo { id, len: validators.len() as u32, keyset_commitment: merkle_root } } /// Sign BEEFY commitment. diff --git a/modules/beefy/src/mock_chain.rs b/modules/beefy/src/mock_chain.rs index c736aed074247..c4fa74915bfeb 100644 --- a/modules/beefy/src/mock_chain.rs +++ b/modules/beefy/src/mock_chain.rs @@ -194,7 +194,7 @@ impl HeaderBuilder { beefy_next_authority_set: BeefyNextAuthoritySet { id: next_validator_set_id, len: next_validators.len() as u32, - root: next_validators_mmr_root, + keyset_commitment: next_validators_mmr_root, }, leaf_extra: (), }; diff --git a/modules/beefy/src/utils.rs b/modules/beefy/src/utils.rs index 45e14ecbfe0b6..ce7a116308d16 100644 --- a/modules/beefy/src/utils.rs +++ b/modules/beefy/src/utils.rs @@ -42,7 +42,7 @@ fn verify_authority_set, I: 'static>( // Ensure that the authority set that signed the commitment is the expected one. let root = get_authorities_mmr_root::(authority_set.validators().iter()); - ensure!(root == authority_set_info.root, Error::::InvalidValidatorSetRoot); + ensure!(root == authority_set_info.keyset_commitment, Error::::InvalidValidatorSetRoot); Ok(()) } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 44a1974290168..455968716c62e 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -20,20 +20,20 @@ bp-header-chain = { path = "../../primitives/header-chain", default-features = f # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } -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 } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["serde"] } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["serde"] } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Optional Benchmarking Dependencies bp-test-utils = { path = "../../primitives/test-utils", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [ "std" ] diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 9131a1063056b..582b9dd8c150c 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -19,17 +19,17 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [ "std" ] diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 6db3802157973..8be580ad1a7bc 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -20,18 +20,18 @@ pallet-bridge-grandpa = { path = "../grandpa", default-features = false } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-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 } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bp-header-chain = { path = "../../primitives/header-chain" } bp-test-utils = { path = "../../primitives/test-utils" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [ "std" ] diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 2c6a1a2f2b2a5..6cbfd6ee3cb30 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -20,19 +20,19 @@ pallet-bridge-messages = { path = "../messages", default-features = false } # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-arithmetic = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bp-runtime = { path = "../../primitives/runtime" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [ "std" ] diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 83fd1a098d7f1..a30b88890adc8 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -12,15 +12,17 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-staking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-staking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = ["std"] diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs index 17bbb0a479f18..49690842418ce 100644 --- a/modules/shift-session-manager/src/lib.rs +++ b/modules/shift-session-manager/src/lib.rs @@ -122,16 +122,16 @@ mod tests { use super::*; use frame_support::{ parameter_types, - sp_io::TestExternalities, sp_runtime::{ testing::UintAuthorityId, traits::{BlakeTwo256, ConvertInto, IdentityLookup}, BuildStorage, Perbill, RuntimeAppPublic, }, weights::Weight, - BasicExternalities, }; use sp_core::H256; + use sp_io::TestExternalities; + use sp_state_machine::BasicExternalities; type AccountId = u64; diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index d2c8d06fdeaeb..49a796516c067 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -17,21 +17,21 @@ bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", de # Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Polkadot Dependencies -xcm = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } -xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [ "std" ] diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 70e0f0f2f4817..2d89bfaacae25 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -17,13 +17,13 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -binary-merkle-tree = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -pallet-mmr = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +binary-merkle-tree = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/beefy/src/lib.rs b/primitives/beefy/src/lib.rs index 1daf5a3620796..0441781e79a66 100644 --- a/primitives/beefy/src/lib.rs +++ b/primitives/beefy/src/lib.rs @@ -26,7 +26,9 @@ pub use pallet_mmr::{ verify_leaves_proof as verify_mmr_leaves_proof, }; pub use sp_consensus_beefy::{ - crypto::{AuthorityId as EcdsaValidatorId, AuthoritySignature as EcdsaValidatorSignature}, + ecdsa_crypto::{ + AuthorityId as EcdsaValidatorId, AuthoritySignature as EcdsaValidatorSignature, + }, known_payloads::MMR_ROOT_ID as MMR_ROOT_PAYLOAD_ID, mmr::{BeefyAuthoritySet, MmrLeafVersion}, BeefyAuthorityId, Commitment, Payload as BeefyPayload, SignedCommitment, ValidatorSet, diff --git a/primitives/chain-asset-hub-kusama/Cargo.toml b/primitives/chain-asset-hub-kusama/Cargo.toml index c87b8eee8868b..c40561347bfc0 100644 --- a/primitives/chain-asset-hub-kusama/Cargo.toml +++ b/primitives/chain-asset-hub-kusama/Cargo.toml @@ -11,7 +11,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Bridge Dependencies bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } diff --git a/primitives/chain-asset-hub-polkadot/Cargo.toml b/primitives/chain-asset-hub-polkadot/Cargo.toml index eef4ae760aac4..e23ed5c5e2468 100644 --- a/primitives/chain-asset-hub-polkadot/Cargo.toml +++ b/primitives/chain-asset-hub-polkadot/Cargo.toml @@ -11,8 +11,8 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } # Substrate Dependencies -frame-support = { 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/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Bridge Dependencies bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index 1880333d34632..5d1fcf0fe1b0e 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -15,13 +15,13 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies -frame-system = { 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-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Polkadot Dependencies -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false , branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "master" } [features] default = [ "std" ] diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml index 1ad196d9ff643..d9fc32524c083 100644 --- a/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -15,10 +15,10 @@ bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml index 2ddb30225fa4f..5e3516136c823 100644 --- a/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -16,10 +16,10 @@ bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index 714d9aa48e196..9dfedc850c8f3 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -15,10 +15,10 @@ bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-bridge-hub-wococo/Cargo.toml b/primitives/chain-bridge-hub-wococo/Cargo.toml index fb480b4a440f6..28536dce1f7ca 100644 --- a/primitives/chain-bridge-hub-wococo/Cargo.toml +++ b/primitives/chain-bridge-hub-wococo/Cargo.toml @@ -16,10 +16,10 @@ bp-messages = { path = "../../primitives/messages", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index e4d59c9d159d4..4e27792f71792 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 4d7f1580c2371..220e8d657e705 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -28,14 +28,14 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-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 } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index 7acaa2c4018ec..ae14f7f362953 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -29,7 +29,6 @@ use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Ch use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, - RuntimeDebug, }; use frame_system::limits; use scale_info::TypeInfo; @@ -37,7 +36,7 @@ use serde::{Deserialize, Serialize}; use sp_core::{storage::StateVersion, Hasher as HasherT}; use sp_runtime::{ traits::{IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, RuntimeDebug, }; use sp_std::prelude::*; use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index d67a4f10fd10e..592498743c8e9 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index 3335c6bcc4109..0963aa0776e92 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -17,12 +17,12 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index cc58edba788a6..c30372b5a0788 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -25,13 +25,12 @@ use bp_runtime::{decl_bridge_runtime_apis, Chain, Parachain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, - RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, RuntimeDebug, }; use sp_std::vec::Vec; diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index 0a70e0504c97a..a588320af9396 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -16,12 +16,12 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 1104e17bb03a3..34d7c8f747668 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -26,13 +26,12 @@ use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Ch use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, - RuntimeDebug, }; use frame_system::limits; use sp_core::Hasher as HasherT; use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, + MultiSignature, MultiSigner, Perbill, RuntimeDebug, }; use sp_std::prelude::*; diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 97958e714f505..49a98747acbf6 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { 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-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index a080b8d352748..c6712857dd691 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 5840f6a652890..11182e9aefe97 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -19,12 +19,11 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; -use frame_support::sp_std::prelude::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; use frame_support::weights::Weight; -use sp_std::prelude::Vec; +use sp_std::prelude::*; /// Westend Chain pub struct Westend; diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml index c7e8a3af0a06c..ffe14b3bc914f 100644 --- a/primitives/chain-wococo/Cargo.toml +++ b/primitives/chain-wococo/Cargo.toml @@ -17,9 +17,9 @@ bp-rococo = { path = "../chain-rococo", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 3281225883f81..66b290917f304 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -18,11 +18,11 @@ bp-runtime = { path = "../runtime", 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, features = ["serde"] } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, features = ["serde"] } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["serde"] } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["serde"] } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["serde"] } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] bp-test-utils = { path = "../test-utils" } diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 83530438361c8..8cad58f44a8e7 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -18,9 +18,9 @@ bp-header-chain = { path = "../header-chain", 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] hex = "0.4" diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 40d62ff41389f..adabcf29fd650 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -19,10 +19,10 @@ bp-runtime = { path = "../runtime", 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 694b78d1a0799..194ef3535b8da 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -19,11 +19,11 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] hex = "0.4" diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 6be26ec96b043..54b86deb34fc8 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -17,9 +17,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Dependencies -frame-support = { 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-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [dev-dependencies] hex = "0.4" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 2e38019b53ab4..a5583c6b98884 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -17,14 +17,14 @@ serde = { version = "1.0", default-features = false, features = ["alloc", "deriv # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -frame-system = { 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, features = ["serde"] } -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 } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["serde"] } +sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } trie-db = { version = "0.27.1", default-features = false } [dev-dependencies] diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 8b9029749411a..ac603d3450dd8 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -14,12 +14,12 @@ bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } finality-grandpa = { version = "0.16.2", default-features = false } -sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } -sp-consensus-grandpa = { 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-runtime = { 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 } +sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index 18cf3791a4953..63c66a945edbb 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -11,8 +11,8 @@ codec = { package = "parity-scale-codec", version = "3.1.5", default-features = scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies -sp-runtime = { 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-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 6e95895983098..28a2b1a35de02 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -56,21 +56,21 @@ substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } # Polkadot Dependencies -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "master" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.4" -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } tempfile = "3.8" finality-grandpa = { version = "0.16.2" } diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index 539366c8dbaf5..a72feecdae827 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -19,7 +19,7 @@ use crate::cli::{chain_schema::*, Balance}; use codec::Encode; use frame_support::Twox64Concat; use num_traits::Zero; -use polkadot_parachain::primitives::{ +use polkadot_parachain_primitives::primitives::{ HeadData as ParaHeadData, Id as ParaId, ValidationCode as ParaValidationCode, }; use polkadot_runtime_common::{ diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index a7bb7dcc4eea4..c52e708f656d5 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -24,5 +24,5 @@ bridge-runtime-common = { path = "../../bin/runtime-common" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index a0214d53d82f1..bf6d65b304d80 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -25,9 +25,9 @@ bridge-runtime-common = { path = "../../bin/runtime-common" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] bp-polkadot-core = { path = "../../primitives/polkadot-core" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 55a412693375a..1f3a70aaa5d5d 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -26,6 +26,6 @@ relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index eeeb8b33d623e..a511b9071eb73 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -27,9 +27,9 @@ relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index d1b5c706f4d11..dd1154bea953f 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -21,8 +21,8 @@ relay-utils = { path = "../utils" } # Substrate Dependencies -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml index 1cb759c5e3118..ccfeced1c2704 100644 --- a/relays/client-millau/Cargo.toml +++ b/relays/client-millau/Cargo.toml @@ -19,9 +19,9 @@ millau-runtime = { path = "../../bin/millau/runtime" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 3c5db4fa55b06..67bf87c4d5cc8 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -21,8 +21,8 @@ relay-utils = { path = "../utils" } # Substrate Dependencies -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 5766954e7ad35..bb8bb5604547c 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -25,6 +25,6 @@ relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml index 9b3a987387965..7a1b378c9ac9c 100644 --- a/relays/client-rialto/Cargo.toml +++ b/relays/client-rialto/Cargo.toml @@ -19,9 +19,9 @@ rialto-runtime = { path = "../../bin/rialto/runtime" } # Substrate Dependencies -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index fac1e74a7c8b6..22ceae5e76b25 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -21,8 +21,8 @@ relay-utils = { path = "../utils" } # Substrate Dependencies -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index e0c1a5461f971..188c411c6914e 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -30,26 +30,26 @@ relay-utils = { path = "../utils" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } # Polkadot Dependencies -xcm = { git = "https://github.com/paritytech/polkadot", branch = "master", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [] diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index ec51b8dd1f2aa..09742f1058e69 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -196,7 +196,7 @@ pub type AccountKeyPairOf = ::AccountKeyPair; /// Substrate-based chain transactions signing scheme. pub trait ChainWithTransactions: Chain { /// Type of key pairs used to sign transactions. - type AccountKeyPair: Pair; + type AccountKeyPair: Pair + Clone + Send + Sync; /// Signed transaction. type SignedTransaction: Clone + Debug + Codec + Send + 'static; diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 9bc7d7adc099b..520cb232b0f6e 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -16,5 +16,5 @@ bp-westend = { path = "../../primitives/chain-westend" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml index f1db1f6173840..ab9e08aeef5f4 100644 --- a/relays/client-wococo/Cargo.toml +++ b/relays/client-wococo/Cargo.toml @@ -19,6 +19,6 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } # Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 637fa4feaf686..4df0f0d11709e 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } futures = "0.3.28" log = "0.4.20" num-traits = "0.2" diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 8fe86bfb06a08..fc5dd4f8caed9 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -41,20 +41,20 @@ bp-messages = { path = "../../primitives/messages" } # Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } relay-rialto-client = { path = "../client-rialto" } relay-rococo-client = { path = "../client-rococo" } relay-wococo-client = { path = "../client-wococo" } diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 4d84f220a3a6d..9df36b2f0320c 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -21,4 +21,4 @@ bp-messages = { path = "../../primitives/messages" } finality-relay = { path = "../finality" } relay-utils = { path = "../utils" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-arithmetic = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 75fec34b425f2..a97aabcaa167a 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -20,4 +20,4 @@ relay-substrate-client = { path = "../client-substrate" } [dev-dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 5aa1a4e6bb224..633d069169499 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -29,5 +29,5 @@ bp-runtime = { path = "../../primitives/runtime" } # Substrate dependencies -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } From 0ab3a978a2c7b83f4fff2a41274dc0609376087e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 4 Sep 2023 12:40:46 +0300 Subject: [PATCH 1101/1210] Markdown linter (#1309) (#2526) * Add markdown linting - add linter default rules - adapt rules to current code - fix the code for linting to pass - add CI check fix #1243 * Fix markdown for Substrate * Fix tooling install * Fix workflow * Add documentation * Remove trailing spaces * Update .github/.markdownlint.yaml Co-authored-by: Oliver Tale-Yazdi * Fix mangled markdown/lists * Fix captalization issues on known words (cherry picked from commit a30092ab42c74c8a4d4c6ce8ac2b0e860749bb46) Co-authored-by: Chevdor --- CODE_OF_CONDUCT.md | 4 +- README.md | 118 ++++----- SECURITY.md | 12 +- docs/high-level-overview.md | 209 ++++++++------- docs/polkadot-kusama-bridge-overview.md | 111 ++++---- modules/messages/README.md | 339 +++++++++++------------- modules/parachains/README.md | 2 +- 7 files changed, 385 insertions(+), 410 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 70541fb72fa25..23411da2e048c 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -34,9 +34,9 @@ of preference. We see that blockchains are naturally community platforms with u ultimate decision makers. We assert that good software will maximise user agency by facilitate user-expression on the network. As such: -- This project will strive to give users as much choice as is both reasonable and possible over what +* This project will strive to give users as much choice as is both reasonable and possible over what protocol they adhere to; but -- use of the project's technical forums, commenting systems, pull requests and issue trackers as a +* use of the project's technical forums, commenting systems, pull requests and issue trackers as a means to express individual protocol preferences is forbidden. ## Our Responsibilities diff --git a/README.md b/README.md index 2f8c5ca9abb29..da46fe67d924a 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,10 @@ This is a collection of components for building bridges. -These components include Substrate pallets for syncing headers, passing arbitrary messages, as well -as libraries for building relayers to provide cross-chain communication capabilities. +These components include Substrate pallets for syncing headers, passing arbitrary messages, as well as libraries for +building relayers to provide cross-chain communication capabilities. -Three bridge nodes are also available. The nodes can be used to run test networks which bridge other -Substrate chains. +Three bridge nodes are also available. The nodes can be used to run test networks which bridge other Substrate chains. 🚧 The bridges are currently under construction - a hardhat is recommended beyond this point 🚧 @@ -21,8 +20,8 @@ Substrate chains. ## Installation -To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web -Assembly (WASM) runtime for the node. You can configure the WASM support as so: +To get up and running you need both stable and nightly Rust. Rust nightly is used to build the Web Assembly (WASM) +runtime for the node. You can configure the WASM support as so: ```bash rustup install nightly @@ -38,8 +37,8 @@ cargo build --all cargo test --all ``` -Also you can build the repo with -[Parity CI Docker image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): +Also you can build the repo with [Parity CI Docker +image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): ```bash docker pull paritytech/bridges-ci:production @@ -57,16 +56,14 @@ docker run --rm -it -w /shellhere/parity-bridges-common \ If you want to reproduce other steps of CI process you can use the following [guide](https://github.com/paritytech/scripts#reproduce-ci-locally). -If you need more information about setting up your development environment [Substrate's -Installation page](https://docs.substrate.io/main-docs/install/) is a good -resource. +If you need more information about setting up your development environment [Substrate's Installation +page](https://docs.substrate.io/main-docs/install/) is a good resource. ## High-Level Architecture -This repo has support for bridging foreign chains together using a combination of Substrate pallets -and external processes called relayers. A bridge chain is one that is able to follow the consensus -of a foreign chain independently. For example, consider the case below where we want to bridge two -Substrate based chains. +This repo has support for bridging foreign chains together using a combination of Substrate pallets and external +processes called relayers. A bridge chain is one that is able to follow the consensus of a foreign chain independently. +For example, consider the case below where we want to bridge two Substrate based chains. ``` +---------------+ +---------------+ @@ -82,19 +79,19 @@ Substrate based chains. +---------------+ ``` -The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by -using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact -directly they need an external service, called a relayer, to communicate. The relayer will subscribe -to new Rialto headers via RPC and submit them to the Millau chain for verification. +The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by using a runtime +module designed to track GRANDPA finality. Since two blockchains can't interact directly they need an external service, +called a relayer, to communicate. The relayer will subscribe to new Rialto headers via RPC and submit them to the Millau +chain for verification. -Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth -description of the bridge interaction. +Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth description of the +bridge interaction. ## Project Layout -Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual -"blockchain", the `modules` which are used to build the blockchain's logic (a.k.a the runtime) and -the `relays` which are used to pass messages between chains. +Here's an overview of how the project is laid out. The main bits are the `bin`, which is the actual "blockchain", the +`modules` which are used to build the blockchain's logic (a.k.a the runtime) and the `relays` which are used to pass +messages between chains. ``` ├── bin // Node and Runtime for the various Substrate chains @@ -117,16 +114,16 @@ the `relays` which are used to pass messages between chains. ## Running the Bridge -To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes -on each side of the bridge (source and target chain). +To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes on each side of the +bridge (source and target chain). There are 2 ways to run the bridge, described below: -- building & running from source: with this option, you'll be able to run the bridge between two standalone -chains that are running GRANDPA finality gadget to achieve finality; +- building & running from source: with this option, you'll be able to run the bridge between two standalone chains that +are running GRANDPA finality gadget to achieve finality; -- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, -complex relays and more. +- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, complex relays +and more. ### Using the Source @@ -141,16 +138,15 @@ cargo build -p substrate-relay ### Running a Dev network -We will launch a dev network to demonstrate how to relay a message between two Substrate based -chains (named Rialto and Millau). +We will launch a dev network to demonstrate how to relay a message between two Substrate based chains (named Rialto and +Millau). -To do this we will need two nodes, two relayers which will relay headers, and two relayers which -will relay messages. +To do this we will need two nodes, two relayers which will relay headers, and two relayers which will relay messages. #### Running from local scripts -To run a simple dev network you can use the scripts located in the -[`deployments/local-scripts` folder](./deployments/local-scripts). +To run a simple dev network you can use the scripts located in the [`deployments/local-scripts` +folder](./deployments/local-scripts). First, we must run the two Substrate nodes. @@ -167,8 +163,8 @@ After the nodes are up we can run the header relayers. ./deployments/local-scripts/relay-rialto-to-millau.sh ``` -At this point you should see the relayer submitting headers from the Millau Substrate chain to the -Rialto Substrate chain. +At this point you should see the relayer submitting headers from the Millau Substrate chain to the Rialto Substrate +chain. ``` # Header Relayer Logs @@ -192,20 +188,23 @@ You will also see the message lane relayers listening for new messages. [Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces [...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race [...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces -[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } +[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { + latest_nonce: 0, nonces_data: () } [...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces -[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { latest_nonce: 0, nonces_data: () } +[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { + latest_nonce: 0, nonces_data: () } [...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) } [...] [date] DEBUG bridge Asking Millau node about its state -[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) } +[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: + HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) } ``` To send a message see the ["How to send a message" section](#how-to-send-a-message). ### How to send a message -In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM -`Trap(43)` message. +In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM `Trap(43)` +message. ```bash # In `parity-bridges-common` folder @@ -222,20 +221,20 @@ TRACE bridge Sent transaction to Millau node: 0x5e68... And at the Rialto node logs you'll something like this: ``` -... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: 48559)/Weight(ref_time: 1215065371, proof_size: 54703). -``` +... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: + 48559)/Weight(ref_time: 1215065371, proof_size: 54703). +``` -It means that the message has been delivered and dispatched. Message may be dispatched with an -error, though - the goal of our test bridge is to ensure that messages are successfully delivered -and all involved components are working. +It means that the message has been delivered and dispatched. Message may be dispatched with an error, though - the goal +of our test bridge is to ensure that messages are successfully delivered and all involved components are working. ## Full Network Docker Compose Setup -For a more sophisticated deployment which includes bidirectional header sync, message passing, -monitoring dashboards, etc. see the [Deployments README](./deployments/README.md). +For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards, +etc. see the [Deployments README](./deployments/README.md). -You should note that you can find images for all the bridge components published on -[Docker Hub](https://hub.docker.com/u/paritytech). +You should note that you can find images for all the bridge components published on [Docker +Hub](https://hub.docker.com/u/paritytech). To run a Rialto node for example, you can use the following command: @@ -247,13 +246,12 @@ docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ ## Community -Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat -server like, for example, Discord. Most discussions around Polkadot and Substrate happen -in various Element "rooms" (channels). So, joining Element might be a good idea, anyway. +Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat server like, for +example, Discord. Most discussions around Polkadot and Substrate happen in various Element "rooms" (channels). So, +joining Element might be a good idea, anyway. -If you are interested in information exchange and development of Polkadot related bridges please -feel free to join the [Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) -Element channel. +If you are interested in information exchange and development of Polkadot related bridges please feel free to join the +[Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) Element channel. -The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element -channel is most suited for discussions regarding Substrate itself. +The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element channel is most suited +for discussions regarding Substrate itself. diff --git a/SECURITY.md b/SECURITY.md index 65f2f3bff05dd..9f215c8876547 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,11 +4,15 @@ Thanks for helping make the Parity ecosystem more secure. Security is one of our ## Reporting a vulnerability -If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it in the public forum as it can cause more damage, rather than giving real help to the ecosystem. +If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it +in the public forum as it can cause more damage, rather than giving real help to the ecosystem. Security vulnerabilities should be reported by the [contact form](https://security-submission.parity.io/). -If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information about our Bug Bounty Program. - -**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for information. +If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. +Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) to find out the information +about our Bug Bounty Program. +**Warning**: This is an unified SECURITY.md file for Paritytech GitHub Organization. The presence of this file does not +mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for +information. diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 449224124afd7..42efc8100bd08 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -1,83 +1,85 @@ # High-Level Bridge Documentation -This document gives a brief, abstract description of main components that may be found in this repository. -If you want to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please -refer to the [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md). +This document gives a brief, abstract description of main components that may be found in this repository. If you want +to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please refer to the [Polkadot <> +Kusama Bridge](./polkadot-kusama-bridge-overview.md). ## Purpose -This repo contains all components required to build a trustless connection between standalone Substrate chains, -that are using GRANDPA finality, their parachains or any combination of those. On top of this connection, we -offer a messaging pallet that provides means to organize messages exchange. +This repo contains all components required to build a trustless connection between standalone Substrate chains, that are +using GRANDPA finality, their parachains or any combination of those. On top of this connection, we offer a messaging +pallet that provides means to organize messages exchange. -On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM messaging](./polkadot-kusama-bridge-overview.md), -[encoded calls messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on. +On top of that layered infrastructure, anyone may build their own bridge applications - e.g. [XCM +messaging](./polkadot-kusama-bridge-overview.md), [encoded calls +messaging](https://github.com/paritytech/parity-bridges-common/releases/tag/encoded-calls-messaging) and so on. ## Terminology -Even though we support (and require) two-way bridging, the documentation will generally talk about -a one-sided interaction. That's to say, we will only talk about syncing finality proofs and messages -from a _source_ chain to a _target_ chain. This is because the two-sided interaction is really just the -one-sided interaction with the source and target chains switched. +Even though we support (and require) two-way bridging, the documentation will generally talk about a one-sided +interaction. That's to say, we will only talk about syncing finality proofs and messages from a _source_ chain to a +_target_ chain. This is because the two-sided interaction is really just the one-sided interaction with the source and +target chains switched. The bridge has both on-chain (pallets) and offchain (relayers) components. ## On-chain components -On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require -deployment at the target chain, while messages pallet needs to be deployed at both, source -and target chains. +On-chain bridge components are pallets that are deployed at the chain runtime. Finality pallets require deployment at +the target chain, while messages pallet needs to be deployed at both, source and target chains. ### Bridge GRANDPA Finality Pallet -A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth" -about the source chain headers which have been finalized. This is useful for higher level applications. +A GRANDPA light client of the source chain built into the target chain's runtime. It provides a "source of truth" about +the source chain headers which have been finalized. This is useful for higher level applications. -The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), -generated by the current authorities set. The GRANDPA protocol itself requires current authorities set to -generate explicit justification for the header that enacts next authorities set. Such headers and their finality -proofs are called mandatory in the pallet and relayer pays no fee for such headers submission. +The pallet tracks current GRANDPA authorities set and only accepts finality proofs (GRANDPA justifications), generated +by the current authorities set. The GRANDPA protocol itself requires current authorities set to generate explicit +justification for the header that enacts next authorities set. Such headers and their finality proofs are called +mandatory in the pallet and relayer pays no fee for such headers submission. -The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers -he wants to submit (with the exception of mandatory headers). +The pallet does not require all headers to be imported or provided. The relayer itself chooses which headers he wants to +submit (with the exception of mandatory headers). More: [pallet level documentation and code](../modules/grandpa/). ### Bridge Parachains Finality Pallet -Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their -finality proofs. Instead, they rely on their relay chain finality. The parachain header is considered final, -when it is accepted by the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) -at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay -chain GRANDPA gadget. +Parachains are not supposed to have their own finality, so we can't use bridge GRANDPA pallet to verify their finality +proofs. Instead, they rely on their relay chain finality. The parachain header is considered final, when it is accepted +by the [`paras` +pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) +at its relay chain. Obviously, the relay chain block, where it is accepted, must also be finalized by the relay chain +GRANDPA gadget. That said, the bridge parachains pallet accepts storage proof of one or several parachain heads, inserted to the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) -map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras). +map of the [`paras` +pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras). To verify this storage proof, the pallet uses relay chain header, imported earlier by the bridge GRANDPA pallet. -The pallet may track multiple parachains at once and those parachains may use different primitives. So the -parachain header decoding never happens at the pallet level. For maintaining the headers order, the pallet -uses relay chain header number. +The pallet may track multiple parachains at once and those parachains may use different primitives. So the parachain +header decoding never happens at the pallet level. For maintaining the headers order, the pallet uses relay chain header +number. More: [pallet level documentation and code](../modules/parachains/). ### Bridge Messages Pallet -The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the -target chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the -same order they are sent. The pallet supports many lanes. +The pallet is responsible for queuing messages at the source chain and receiving the messages proofs at the target +chain. The messages are sent to the particular _lane_, where they are guaranteed to be received in the same order they +are sent. The pallet supports many lanes. -The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of -messages that have been received. Inbound lane end stores the number of messages that have been received and -also a map that maps messages to relayers that have delivered those messages to the target chain. +The lane has two ends. Outbound lane end is storing number of messages that have been sent and the number of messages +that have been received. Inbound lane end stores the number of messages that have been received and also a map that maps +messages to relayers that have delivered those messages to the target chain. The pallet has three main entrypoints: - the `send_message` may be used by the other runtime pallets to send the messages; -- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the -dispatch code; -- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding -relayers that have delivered the message. +- the `receive_messages_proof` is responsible for parsing the messages proof and handing messages over to the dispatch +code; +- the `receive_messages_delivery_proof` is responsible for parsing the messages delivery proof and rewarding relayers +that have delivered the message. Many things are abstracted by the pallet: - the message itself may mean anything, the pallet doesn't care about its content; @@ -85,97 +87,98 @@ Many things are abstracted by the pallet: - the messages proof and messages delivery proof are verified outside of the pallet; - the relayers incentivization scheme is defined outside of the pallet. -Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular -storage proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages -pallet, in this case, depends on one of the finality pallets. The messages are XCM messages and we are using -XCM executor to dispatch them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) -document. +Outside of the messaging pallet, we have a set of adapters, where messages and delivery proofs are regular storage +proofs. The proofs are generated at the bridged chain and require bridged chain finality. So messages pallet, in this +case, depends on one of the finality pallets. The messages are XCM messages and we are using XCM executor to dispatch +them on receival. You may find more info in [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md) document. More: [pallet level documentation and code](../modules/messages/). ### Bridge Relayers Pallet -The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When -the rewards are registered and the reward amount is configured outside of the pallet. +The pallet is quite simple. It just registers relayer rewards and has an entrypoint to collect them. When the rewards +are registered and the reward amount is configured outside of the pallet. More: [pallet level documentation and code](../modules/relayers/). ## Offchain Components -Offchain bridge components are separate processes, called relayers. Relayers are connected both to the -source chain and target chain nodes. Relayers are reading state of the source chain, compare it to the -state of the target chain and, if state at target chain needs to be updated, submits target chain -transaction. +Offchain bridge components are separate processes, called relayers. Relayers are connected both to the source chain and +target chain nodes. Relayers are reading state of the source chain, compare it to the state of the target chain and, if +state at target chain needs to be updated, submits target chain transaction. ### GRANDPA Finality Relay -The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to -the Bridge GRANDPA Finality Pallet, deployed at the target chain. For that, the relay subscribes to -the source chain GRANDPA justifications stream and submits every new justification it sees to the -target chain GRANDPA light client. In addition, relay is searching for mandatory headers and -submits their justifications - without that the pallet will be unable to move forward. +The task of relay is to submit source chain GRANDPA justifications and their corresponding headers to the Bridge GRANDPA +Finality Pallet, deployed at the target chain. For that, the relay subscribes to the source chain GRANDPA justifications +stream and submits every new justification it sees to the target chain GRANDPA light client. In addition, relay is +searching for mandatory headers and submits their justifications - without that the pallet will be unable to move +forward. -More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and code](../relays/finality/). +More: [GRANDPA Finality Relay Sequence Diagram](./grandpa-finality-relay.html), [pallet level documentation and +code](../relays/finality/). ### Parachains Finality Relay -The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the -tracked parachain nodes. The relay looks at the [`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) -map of the [`paras` pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) -in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at -the target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** -until header `B` or one of its ancestors appears at the target chain. Once it is available, the storage -proof of the map entry is generated and is submitted to the target chain. +The relay connects to the source _relay_ chain and the target chain nodes. It doesn't need to connect to the tracked +parachain nodes. The relay looks at the +[`Heads`](https://github.com/paritytech/polkadot/blob/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras/mod.rs#L642) +map of the [`paras` +pallet](https://github.com/paritytech/polkadot/tree/1a034bd6de0e76721d19aed02a538bcef0787260/runtime/parachains/src/paras) +in source chain, and compares the value with the best parachain head, stored in the bridge parachains pallet at the +target chain. If new parachain head appears at the relay chain block `B`, the relay process **waits** until header `B` +or one of its ancestors appears at the target chain. Once it is available, the storage proof of the map entry is +generated and is submitted to the target chain. -As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains -finality relay requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or -any of its children's finality at source won't be relayed at target, and target chain -won't be able to verify generated storage proof. +As its on-chain component (which requires bridge GRANDPA pallet to be deployed nearby), the parachains finality relay +requires GRANDPA finality relay to be running in parallel. Without it, the header `B` or any of its children's finality +at source won't be relayed at target, and target chain won't be able to verify generated storage proof. More: [Parachains Finality Relay Sequence Diagram](./parachains-finality-relay.html), [code](../relays/parachains/). ### Messages Relay -Messages relay is actually two relays that are running in a single process: messages delivery relay and -delivery confirmation relay. Even though they are more complex and have many caveats, the overall algorithm -is the same as in other relays. +Messages relay is actually two relays that are running in a single process: messages delivery relay and delivery +confirmation relay. Even though they are more complex and have many caveats, the overall algorithm is the same as in +other relays. -Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new -messages are queued there. Once they appear at the source block `B`, the relay start waiting for the block -`B` or its descendant appear at the target chain. Then the messages storage proof is generated and submitted -to the bridge messages pallet at the target chain. In addition, the transaction may include the storage proof -of the outbound lane state - that proves that relayer rewards have been paid and this data (map of relay -accounts to the delivered messages) may be pruned from the inbound lane state at the target chain. +Message delivery relay connects to the source chain and looks at the outbound lane end, waiting until new messages are +queued there. Once they appear at the source block `B`, the relay start waiting for the block `B` or its descendant +appear at the target chain. Then the messages storage proof is generated and submitted to the bridge messages pallet at +the target chain. In addition, the transaction may include the storage proof of the outbound lane state - that proves +that relayer rewards have been paid and this data (map of relay accounts to the delivered messages) may be pruned from +the inbound lane state at the target chain. -Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new -messages are delivered to the target chain, the corresponding _source chain account_ is inserted to the -map in the inbound lane data. Relay detects that, say, at the target chain block `B` and waits until that -block or its descendant appears at the source chain. Once that happens, the relay crafts a storage proof of -that data and sends it to the messages pallet, deployed at the source chain. +Delivery confirmation relay connects to the target chain and starts watching the inbound lane end. When new messages are +delivered to the target chain, the corresponding _source chain account_ is inserted to the map in the inbound lane data. +Relay detects that, say, at the target chain block `B` and waits until that block or its descendant appears at the +source chain. Once that happens, the relay crafts a storage proof of that data and sends it to the messages pallet, +deployed at the source chain. -As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages -relay submits transactions to both source and target chains, it requires both _source-to-target_ and -_target-to-source_ finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, -depending on the type of connected chain. +As you can see, the messages relay also requires finality relay to be operating in parallel. Since messages relay +submits transactions to both source and target chains, it requires both _source-to-target_ and _target-to-source_ +finality relays. They can be GRANDPA finality relays or GRANDPA+parachains finality relays, depending on the type of +connected chain. -More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and code](../relays/messages/). +More: [Messages Relay Sequence Diagram](./messages-relay.html), [pallet level documentation and +code](../relays/messages/). ### Complex Relay -Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory -GRANDPA header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it -sees, will have to pay a (quite large) cost. And if no messages are sent through the bridge, that is just -waste of money. +Every relay transaction has its cost. The only transaction, that is "free" to relayer is when the mandatory GRANDPA +header is submitted. The relay that feeds the bridge with every relay chain and/or parachain head it sees, will have to +pay a (quite large) cost. And if no messages are sent through the bridge, that is just waste of money. -We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions -that are required for the messages/confirmations delivery. This mode starts two message relays (in both -directions). All required finality relays are also started in a special _on-demand_ mode. In this mode they -do not submit any headers without special request. As always, the only exception is when GRANDPA finality -relay sees the mandatory header - it is submitted without such request. +We have a special relay mode, called _complex relay_, where relay mostly sleeps and only submits transactions that are +required for the messages/confirmations delivery. This mode starts two message relays (in both directions). All required +finality relays are also started in a special _on-demand_ mode. In this mode they do not submit any headers without +special request. As always, the only exception is when GRANDPA finality relay sees the mandatory header - it is +submitted without such request. -The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations -to be delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and -then message relay may perform its job. If on-demand relay is a parachain finality relay, it also runs its -own on-demand GRANDPA relay, which is used to relay required relay chain headers. +The message relays are watching their lanes and when, at some block `B`, they see new messages/confirmations to be +delivered, they are asking on-demand relays to relay this block `B`. On-demand relays does that and then message relay +may perform its job. If on-demand relay is a parachain finality relay, it also runs its own on-demand GRANDPA relay, +which is used to relay required relay chain headers. -More: [Complex Relay Sequence Diagram](./complex-relay.html), [code](../relays/bin-substrate/src/cli/relay_headers_and_messages/). +More: [Complex Relay Sequence Diagram](./complex-relay.html), +[code](../relays/bin-substrate/src/cli/relay_headers_and_messages/). diff --git a/docs/polkadot-kusama-bridge-overview.md b/docs/polkadot-kusama-bridge-overview.md index b469720f65b2b..08036f0b0722b 100644 --- a/docs/polkadot-kusama-bridge-overview.md +++ b/docs/polkadot-kusama-bridge-overview.md @@ -1,35 +1,35 @@ # Polkadot <> Kusama Bridge Overview -This document describes how we use all components, described in the [High-Level Bridge Documentation](./high-level-overview.md), -to build the XCM bridge between Kusama and Polkadot. In this case, our components merely work as a XCM transport -(like XCMP/UMP/HRMP), between chains that are not a part of the same consensus system. +This document describes how we use all components, described in the [High-Level Bridge +Documentation](./high-level-overview.md), to build the XCM bridge between Kusama and Polkadot. In this case, our +components merely work as a XCM transport (like XCMP/UMP/HRMP), between chains that are not a part of the same consensus +system. The overall architecture may be seen in [this diagram](./polkadot-kusama-bridge.html). ## Bridge Hubs -All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains. -That's why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama -Bridge Hub under Kusama consensus. +All operations at relay chain are expensive. Ideally all non-mandatory transactions must happen on parachains. That's +why we are planning to have two parachains - Polkadot Bridge Hub under Polkadot consensus and Kusama Bridge Hub under +Kusama consensus. -The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to -use our bridge hubs too and have their pallets there. +The Bridge Hub will have all required bridge pallets in its runtime. We hope that later, other teams will be able to use +our bridge hubs too and have their pallets there. -The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub. -The runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs. +The Bridge Hub will use the base token of the ecosystem - KSM at Kusama Bridge Hub and DOT at Polkadot Bridge Hub. The +runtime will have minimal set of non-bridge pallets, so there's not much you can do directly on bridge hubs. ## Connecting Parachains -You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need -to use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will -just queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. +You won't be able to directly use bridge hub transactions to send XCM messages over the bridge. Instead, you'll need to +use other parachains transactions, which will use HRMP to deliver messages to the Bridge Hub. The Bridge Hub will just +queue these messages in its outbound lane, which is dedicated to deliver messages between two parachains. -Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two -parachains would allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama -accounts to hold wrapped DOT tokens. +Our first planned bridge will connect the Polkadot and Kusama Asset Hubs. A bridge between those two parachains would +allow Asset Hub Polkadot accounts to hold wrapped KSM tokens and Asset Hub Kusama accounts to hold wrapped DOT tokens. -For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, -when other parachains will join the bridge, they will be using other lanes for their messages. +For that bridge (pair of parachains under different consensus systems) we'll be using the lane 00000000. Later, when +other parachains will join the bridge, they will be using other lanes for their messages. ## Running Relayers @@ -38,9 +38,9 @@ justifications to the bridge hubs at the other side. It'll also relay finalized Hub heads. This will only happen when messages will be queued at hubs. So most of time relayer will be idle. There's no any active relayer sets, or something like that. Anyone may start its own relayer and relay queued messages. -We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost. -Apart from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have -a mechanism for rewarding relayers. +We are not against that and, as always, appreciate any community efforts. Of course, running relayer has the cost. Apart +from paying for the CPU and network, the relayer pays for transactions at both sides of the bridge. We have a mechanism +for rewarding relayers. ### Compensating the Cost of Message Delivery Transactions @@ -56,51 +56,49 @@ is the relayer, which is following our rules: - we compensate the cost of message delivery transactions that have actually delivered the messages. So if your transaction has claimed to deliver messages `[42, 43, 44]`, but, because of some reasons, has actually delivered - messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then - the relayer pays the full cost of the transaction; + messages `[42, 43]`, the transaction will be free for relayer. If it has not delivered any messages, then the relayer + pays the full cost of the transaction; - we compensate the cost of message delivery and all required finality calls, if they are part of the same [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326) - transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used - to prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they - are not linked together, the relayer pays the full transaction cost. + transaction. Of course, the calls inside the batch must be linked - e.g. the submitted parachain head must be used to + prove messages. Relay header must be used to prove parachain head finality. If one of calls fails, or if they are not + linked together, the relayer pays the full transaction cost. Please keep in mind that the fee of "zero-cost" transactions is still withdrawn from the relayer account. But the -compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer -may later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call. +compensation is registered in the `pallet_bridge_relayers::RelayerRewards` map at the target bridge hub. The relayer may +later claim all its rewards later, using the `pallet_bridge_relayers::claim_rewards` call. *A side note*: why we don't simply set the cost of useful transactions to zero? That's because the bridge has its cost. If we won't take any fees, it would mean that the sender is not obliged to pay for its messages. And Bridge Hub -collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later, -in the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section. +collators (and, maybe, "treasury") are not receiving any payment for including transactions. More about this later, in +the [Who is Rewarding Relayers](#who-is-rewarding-relayers) section. ### Message Delivery Confirmation Rewards In addition to the "zero-cost" message delivery transactions, the relayer is also rewarded for: -- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge - Hub.; +- delivering every message. The reward is registered during delivery confirmation transaction at the Source Bridge Hub.; -- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms - delivery of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It - receives some fee for confirming messages, delivered by other relayers. +- submitting delivery confirmation transaction. The relayer may submit delivery confirmation that e.g. confirms delivery + of four messages, of which the only one (or zero) messages is actually delivered by this relayer. It receives some fee + for confirming messages, delivered by other relayers. Both rewards may be claimed using the `pallet_bridge_relayers::claim_rewards` call at the Source Bridge Hub. ### Who is Rewarding Relayers Obviously, there should be someone who is paying relayer rewards. We want bridge transactions to have a cost, so we -can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides -of the bridge to cover relayer rewards. +can't use fees for rewards. Instead, the parachains using the bridge, use sovereign accounts on both sides of the bridge +to cover relayer rewards. -Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will -have an account at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama -Bridge Hub. The sovereign accounts are used as a source of funds when the relayer is calling the -`pallet_bridge_relayers::claim_rewards`. +Bridged Parachains will have sovereign accounts at bridge hubs. For example, the Kusama Asset Hub will have an account +at the Polkadot Bridge Hub. The Polkadot Asset Hub will have an account at the Kusama Bridge Hub. The sovereign accounts +are used as a source of funds when the relayer is calling the `pallet_bridge_relayers::claim_rewards`. -Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. -Kusama Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign account -is not used to cover rewards of bridging with some other Polkadot Parachain. +Since messages lane is only used by the pair of parachains, there's no collision between different bridges. E.g. Kusama +Asset Hub will only reward relayers that are delivering messages from Kusama Asset Hub. The Kusama Asset Hub sovereign +account is not used to cover rewards of bridging with some other Polkadot Parachain. ### Multiple Relayers and Rewards @@ -108,25 +106,24 @@ Our goal is to incentivize running honest relayers. But we have no relayers sets message delivery transaction, hoping that the cost of this transaction will be compensated. So what if some message is currently queued and two relayers are submitting two identical message delivery transactions at once? Without any special means, the cost of first included transaction will be compensated and the cost of the other one won't. A honest, -but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which -may be used by other useful transactions. +but unlucky relayer will lose some money. In addition, we'll waste some portion of block size and weight, which may be +used by other useful transactions. -To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages! {}](../bin/runtime-common/src/lib.rs) -and [RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are -preventing bridge transactions with obsolete data from including into the block. We are rejecting following -transactions: +To solve the problem, we have two signed extensions ([generate_bridge_reject_obsolete_headers_and_messages! +{}](../bin/runtime-common/src/lib.rs) and +[RefundRelayerForMessagesFromParachain](../bin/runtime-common/src/refund_relayer_extension.rs)), that are preventing +bridge transactions with obsolete data from including into the block. We are rejecting following transactions: - transactions, that are submitting the GRANDPA justification for the best finalized header, or one of its ancestors; - transactions, that are submitting the proof of the current best parachain head, or one of its ancestors; -- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered, - the transaction is not rejected; +- transactions, that are delivering already delivered messages. If at least one of messages is not yet delivered, the + transaction is not rejected; -- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new, - the transaction is not rejected; +- transactions, that are confirming delivery of already confirmed messages. If at least one of confirmations is new, the + transaction is not rejected; - [`frame_utility::batch_all`](https://github.com/paritytech/substrate/blob/891d6a5c870ab88521183facafc811a203bb6541/frame/utility/src/lib.rs#L326) - transactions, that have both finality and message delivery calls. All restrictions from the - [Compensating the Cost of Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions) - are applied. + transactions, that have both finality and message delivery calls. All restrictions from the [Compensating the Cost of + Message Delivery Transactions](#compensating-the-cost-of-message-delivery-transactions) are applied. diff --git a/modules/messages/README.md b/modules/messages/README.md index b5250d0dca0b2..457d5f5facfa7 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -1,8 +1,7 @@ # Bridge Messages Pallet -The messages pallet is used to deliver messages from source chain to target chain. Message is -(almost) opaque to the module and the final goal is to hand message to the message dispatch -mechanism. +The messages pallet is used to deliver messages from source chain to target chain. Message is (almost) opaque to the +module and the final goal is to hand message to the message dispatch mechanism. ## Contents @@ -14,229 +13,203 @@ mechanism. ## Overview -Message lane is an unidirectional channel, where messages are sent from source chain to the target -chain. At the same time, a single instance of messages module supports both outbound lanes and -inbound lanes. So the chain where the module is deployed (this chain), may act as a source chain for -outbound messages (heading to a bridged chain) and as a target chain for inbound messages (coming -from a bridged chain). +Message lane is an unidirectional channel, where messages are sent from source chain to the target chain. At the same +time, a single instance of messages module supports both outbound lanes and inbound lanes. So the chain where the module +is deployed (this chain), may act as a source chain for outbound messages (heading to a bridged chain) and as a target +chain for inbound messages (coming from a bridged chain). -Messages module supports multiple message lanes. Every message lane is identified with a 4-byte -identifier. Messages sent through the lane are assigned unique (for this lane) increasing integer -value that is known as nonce ("number that can only be used once"). Messages that are sent over the -same lane are guaranteed to be delivered to the target chain in the same order they're sent from -the source chain. In other words, message with nonce `N` will be delivered right before delivering a -message with nonce `N+1`. +Messages module supports multiple message lanes. Every message lane is identified with a 4-byte identifier. Messages +sent through the lane are assigned unique (for this lane) increasing integer value that is known as nonce ("number that +can only be used once"). Messages that are sent over the same lane are guaranteed to be delivered to the target chain in +the same order they're sent from the source chain. In other words, message with nonce `N` will be delivered right before +delivering a message with nonce `N+1`. -Single message lane may be seen as a transport channel for single application (onchain, offchain or -mixed). At the same time the module itself never dictates any lane or message rules. In the end, it -is the runtime developer who defines what message lane and message mean for this runtime. +Single message lane may be seen as a transport channel for single application (onchain, offchain or mixed). At the same +time the module itself never dictates any lane or message rules. In the end, it is the runtime developer who defines +what message lane and message mean for this runtime. -In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane -as a channel of communication between two parachains of different relay chains. For example, lane -`[0, 0, 0, 0]` is used for Polkadot <> Kusama Asset Hub communications. Other lanes may be used to -bridge other parachains. +In our [Kusama<>Polkadot bridge](../../docs/polkadot-kusama-bridge-overview.md) we are using lane as a channel of +communication between two parachains of different relay chains. For example, lane `[0, 0, 0, 0]` is used for Polkadot <> +Kusama Asset Hub communications. Other lanes may be used to bridge other parachains. ## Message Workflow -The pallet is not intended to be used by end users and provides no public calls to send the message. -Instead, it provides runtime-internal method that allows other pallets (or other runtime code) to queue -outbound messages. - -The message "appears" when some runtime code calls the `send_message()` method of the pallet. -The submitter specifies the lane that they're willing to use and the message itself. If some fee must -be paid for sending the message, it must be paid outside of the pallet. If a message passes all checks -(that include, for example, message size check, disabled lane check, ...), the nonce is assigned and -the message is stored in the module storage. The message is in an "undelivered" state now. - -We assume that there are external, offchain actors, called relayers, that are submitting module -related transactions to both target and source chains. The pallet itself has no assumptions about -relayers incentivization scheme, but it has some callbacks for paying rewards. See -[Integrating Messages Module into runtime](#Integrating-Messages-Module-into-runtime) -for details. - -Eventually, some relayer would notice this message in the "undelivered" state and it would decide to -deliver this message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery -transaction) for the messages module instance, deployed at the target chain. Relayer provides -its account id at the source chain, the proof of message (or several messages), the number of -messages in the transaction and their cumulative dispatch weight. Once a transaction is mined, the -message is considered "delivered". - -Once a message is delivered, the relayer may want to confirm delivery back to the source chain. -There are two reasons why it would want to do that. The first is that we intentionally limit number -of "delivered", but not yet "confirmed" messages at inbound lanes -(see [What about other Constants in the Messages Module Configuration Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). -So at some point, the target chain may stop accepting new messages until relayers confirm some of -these. The second is that if the relayer wants to be rewarded for delivery, it must prove the fact -that it has actually delivered the message. And this proof may only be generated after the delivery -transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` transaction (aka -confirmation transaction) for the messages module instance, deployed at the source chain. Once -this transaction is mined, the message is considered "confirmed". - -The "confirmed" state is the final state of the message. But there's one last thing related to the -message - the fact that it is now "confirmed" and reward has been paid to the relayer (or at least -callback for this has been called), must be confirmed to the target chain. Otherwise, we may reach -the limit of "unconfirmed" messages at the target chain and it will stop accepting new messages. So -relayer sometimes includes a nonce of the latest "confirmed" message in the next +The pallet is not intended to be used by end users and provides no public calls to send the message. Instead, it +provides runtime-internal method that allows other pallets (or other runtime code) to queue outbound messages. + +The message "appears" when some runtime code calls the `send_message()` method of the pallet. The submitter specifies +the lane that they're willing to use and the message itself. If some fee must be paid for sending the message, it must +be paid outside of the pallet. If a message passes all checks (that include, for example, message size check, disabled +lane check, ...), the nonce is assigned and the message is stored in the module storage. The message is in an +"undelivered" state now. + +We assume that there are external, offchain actors, called relayers, that are submitting module related transactions to +both target and source chains. The pallet itself has no assumptions about relayers incentivization scheme, but it has +some callbacks for paying rewards. See [Integrating Messages Module into +runtime](#Integrating-Messages-Module-into-runtime) for details. + +Eventually, some relayer would notice this message in the "undelivered" state and it would decide to deliver this +message. Relayer then crafts `receive_messages_proof()` transaction (aka delivery transaction) for the messages module +instance, deployed at the target chain. Relayer provides its account id at the source chain, the proof of message (or +several messages), the number of messages in the transaction and their cumulative dispatch weight. Once a transaction is +mined, the message is considered "delivered". + +Once a message is delivered, the relayer may want to confirm delivery back to the source chain. There are two reasons +why it would want to do that. The first is that we intentionally limit number of "delivered", but not yet "confirmed" +messages at inbound lanes (see [What about other Constants in the Messages Module Configuration +Trait](#What-about-other-Constants-in-the-Messages-Module-Configuration-Trait) for explanation). So at some point, the +target chain may stop accepting new messages until relayers confirm some of these. The second is that if the relayer +wants to be rewarded for delivery, it must prove the fact that it has actually delivered the message. And this proof may +only be generated after the delivery transaction is mined. So relayer crafts the `receive_messages_delivery_proof()` +transaction (aka confirmation transaction) for the messages module instance, deployed at the source chain. Once this +transaction is mined, the message is considered "confirmed". + +The "confirmed" state is the final state of the message. But there's one last thing related to the message - the fact +that it is now "confirmed" and reward has been paid to the relayer (or at least callback for this has been called), must +be confirmed to the target chain. Otherwise, we may reach the limit of "unconfirmed" messages at the target chain and it +will stop accepting new messages. So relayer sometimes includes a nonce of the latest "confirmed" message in the next `receive_messages_proof()` transaction, proving that some messages have been confirmed. ## Integrating Messages Module into Runtime -As it has been said above, the messages module supports both outbound and inbound message lanes. -So if we will integrate a module in some runtime, it may act as the source chain runtime for -outbound messages and as the target chain runtime for inbound messages. In this section, we'll -sometimes refer to the chain we're currently integrating with, as "this chain" and the other -chain as "bridged chain". - -Messages module doesn't simply accept transactions that are claiming that the bridged chain has -some updated data for us. Instead of this, the module assumes that the bridged chain is able to -prove that updated data in some way. The proof is abstracted from the module and may be of any kind. -In our Substrate-to-Substrate bridge we're using runtime storage proofs. Other bridges may use -transaction proofs, Substrate header digests or anything else that may be proved. - -**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module -configuration. But if you're interested in well-probed and relatively easy integration of two -Substrate-based chains, you may want to look at the -[bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of -helpers for integration, which may be directly used from within your runtime. Then if you'll decide -to change something in this scheme, get back here for detailed information. +As it has been said above, the messages module supports both outbound and inbound message lanes. So if we will integrate +a module in some runtime, it may act as the source chain runtime for outbound messages and as the target chain runtime +for inbound messages. In this section, we'll sometimes refer to the chain we're currently integrating with, as "this +chain" and the other chain as "bridged chain". + +Messages module doesn't simply accept transactions that are claiming that the bridged chain has some updated data for +us. Instead of this, the module assumes that the bridged chain is able to prove that updated data in some way. The proof +is abstracted from the module and may be of any kind. In our Substrate-to-Substrate bridge we're using runtime storage +proofs. Other bridges may use transaction proofs, Substrate header digests or anything else that may be proved. + +**IMPORTANT NOTE**: everything below in this chapter describes details of the messages module configuration. But if +you're interested in well-probed and relatively easy integration of two Substrate-based chains, you may want to look at +the [bridge-runtime-common](../../bin/runtime-common/) crate. This crate is providing a lot of helpers for integration, +which may be directly used from within your runtime. Then if you'll decide to change something in this scheme, get back +here for detailed information. ### General Information -The messages module supports instances. Every module instance is supposed to bridge this chain -and some bridged chain. To bridge with another chain, using another instance is suggested (this -isn't forced anywhere in the code, though). Keep in mind, that the pallet may be used to build -virtual channels between multiple chains, as we do in our [Polkadot <> Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). -There, the pallet actually bridges only two parachains - Kusama Bridge Hub and Polkadot -Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages to their -Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper +The messages module supports instances. Every module instance is supposed to bridge this chain and some bridged chain. +To bridge with another chain, using another instance is suggested (this isn't forced anywhere in the code, though). Keep +in mind, that the pallet may be used to build virtual channels between multiple chains, as we do in our [Polkadot <> +Kusama bridge](../../docs/polkadot-kusama-bridge-overview.md). There, the pallet actually bridges only two parachains - +Kusama Bridge Hub and Polkadot Bridge Hub. However, other Kusama and Polkadot parachains are able to send (XCM) messages +to their Bridge Hubs. The messages will be delivered to the other side of the bridge and routed to the proper destination parachain within the bridged chain consensus. -Message submitters may track message progress by inspecting module events. When Message is accepted, -the `MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that -has been assigned to the message. When a message is delivered to the target chain, the `MessagesDelivered` -event is emitted from the `receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains -the message lane identifier and inclusive range of delivered message nonces. +Message submitters may track message progress by inspecting module events. When Message is accepted, the +`MessageAccepted` event is emitted. The event contains both message lane identifier and nonce that has been assigned to +the message. When a message is delivered to the target chain, the `MessagesDelivered` event is emitted from the +`receive_messages_delivery_proof()` transaction. The `MessagesDelivered` contains the message lane identifier and +inclusive range of delivered message nonces. -The pallet provides no means to get the result of message dispatch at the target chain. If that is -required, it must be done outside of the pallet. For example, XCM messages, when dispatched, have -special instructions to send some data back to the sender. Other dispatchers may use similar -mechanism for that. +The pallet provides no means to get the result of message dispatch at the target chain. If that is required, it must be +done outside of the pallet. For example, XCM messages, when dispatched, have special instructions to send some data back +to the sender. Other dispatchers may use similar mechanism for that. ### How to plug-in Messages Module to Send Messages to the Bridged Chain? -The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with -outbound messages. The `pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the -bridged chain as the target for our outbound messages. It must be able to check that the bridged -chain may accept our message - like that the message has size below maximal possible transaction -size of the chain and so on. And when the relayer sends us a confirmation transaction, this -implementation must be able to parse and verify the proof of messages delivery. Normally, you would -reuse the same (configurable) type on all chains that are sending messages to the same bridged -chain. - -The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound -messages. The simplest callback may just accept all messages. But in this case you'll need to answer -many questions first. Who will pay for the delivery and confirmation transaction? Are we sure that -someone will ever deliver this message to the bridged chain? Are we sure that we don't bloat our -runtime storage by accepting this message? What if the message is improperly encoded or has some -fields set to invalid values? Answering all those (and similar) questions would lead to correct -implementation. +The `pallet_bridge_messages::Config` trait has 3 main associated types that are used to work with outbound messages. The +`pallet_bridge_messages::Config::TargetHeaderChain` defines how we see the bridged chain as the target for our outbound +messages. It must be able to check that the bridged chain may accept our message - like that the message has size below +maximal possible transaction size of the chain and so on. And when the relayer sends us a confirmation transaction, this +implementation must be able to parse and verify the proof of messages delivery. Normally, you would reuse the same +(configurable) type on all chains that are sending messages to the same bridged chain. + +The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The +simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will +pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the +bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is +improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to +correct implementation. There's another thing to consider when implementing type for use in -`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes -identically, or they'll have different sets of verification rules? For example, you may reserve -lane#1 for messages coming from some 'wrapped-token' pallet - then you may verify in your -implementation that the origin is associated with this pallet. Lane#2 may be reserved for 'system' -messages and you may charge zero fee for such messages. You may have some rate limiting for messages -sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is +`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll +have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some +'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet. +Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate +limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation. -The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation -transaction is received, we call the `pay_reward()` method, passing the range of delivered messages. -You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its -[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible -implementation. It allows you to pay fixed reward for relaying the message and some of its portion -for confirming delivery. +The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation transaction is +received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the +[`pallet-bridge-relayers`](../relayers/) pallet and its +[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible implementation. It +allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery. ### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? You should be looking at the `bp_messages::source_chain::ForbidOutboundMessages` structure -[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements -all required traits and will simply reject all transactions, related to outbound messages. +[`bp_messages::source_chain`](../../primitives/messages/src/source_chain.rs). It implements all required traits and will +simply reject all transactions, related to outbound messages. ### How to plug-in Messages Module to Receive Messages from the Bridged Chain? -The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with -inbound messages. The `pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the -bridged chain as the source of our inbound messages. When relayer sends us a delivery transaction, -this implementation must be able to parse and verify the proof of messages wrapped in this -transaction. Normally, you would reuse the same (configurable) type on all chains that are sending -messages to the same bridged chain. +The `pallet_bridge_messages::Config` trait has 2 main associated types that are used to work with inbound messages. The +`pallet_bridge_messages::Config::SourceHeaderChain` defines how we see the bridged chain as the source of our inbound +messages. When relayer sends us a delivery transaction, this implementation must be able to parse and verify the proof +of messages wrapped in this transaction. Normally, you would reuse the same (configurable) type on all chains that are +sending messages to the same bridged chain. -The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered -messages. Apart from actually dispatching the message, the implementation must return the correct -dispatch weight of the message before dispatch is called. +The `pallet_bridge_messages::Config::MessageDispatch` defines a way on how to dispatch delivered messages. Apart from +actually dispatching the message, the implementation must return the correct dispatch weight of the message before +dispatch is called. ### I have a Messages Module in my Runtime, but I Want to Reject all Inbound Messages. What shall I do? -You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from -the [`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It -implements all required traits and will simply reject all transactions, related to inbound messages. +You should be looking at the `bp_messages::target_chain::ForbidInboundMessages` structure from the +[`bp_messages::target_chain`](../../primitives/messages/src/target_chain.rs) module. It implements all required traits +and will simply reject all transactions, related to inbound messages. ### What about other Constants in the Messages Module Configuration Trait? Two settings that are used to check messages in the `send_message()` function. The -`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that -may be used to send messages. All messages sent using other lanes are rejected. All messages that have -size above `pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected. - -To be able to reward the relayer for delivering messages, we store a map of message nonces range => -identifier of the relayer that has delivered this range at the target chain runtime storage. If a -relayer delivers multiple consequent ranges, they're merged into single entry. So there may be more -than one entry for the same relayer. Eventually, this whole map must be delivered back to the source -chain to confirm delivery and pay rewards. So to make sure we are able to craft this confirmation -transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure that -the weight of processing this map is below a certain limit. Both size and processing weight mostly -depend on the number of entries. The number of entries is limited with the -`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight -also depends on the total number of messages that are being confirmed, because every confirmed -message needs to be read. So there's another -`pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. - -When choosing values for these parameters, you must also keep in mind that if proof in your scheme -is based on finality of headers (and it is the most obvious option for Substrate-based chains with -finality notion), then choosing too small values for these parameters may cause significant delays -in message delivery. That's because there are too many actors involved in this scheme: 1) authorities -that are finalizing headers of the target chain need to finalize header with non-empty map; 2) the -headers relayer then needs to submit this header and its finality proof to the source chain; 3) the -messages relayer must then send confirmation transaction (storage proof of this map) to the source -chain; 4) when the confirmation transaction will be mined at some header, source chain authorities -must finalize this header; 5) the headers relay then needs to submit this header and its finality -proof to the target chain; 6) only now the messages relayer may submit new messages from the source -to target chain and prune the entry from the map. - -Delivery transaction requires the relayer to provide both number of entries and total number of -messages in the map. This means that the module never charges an extra cost for delivering a map - -the relayer would need to pay exactly for the number of entries+messages it has delivered. So the -best guess for values of these parameters would be the pair that would occupy `N` percent of the -maximal transaction size and weight of the source chain. The `N` should be large enough to process -large maps, at the same time keeping reserve for future source chain upgrades. +`pallet_bridge_messages::Config::ActiveOutboundLanes` is an array of all message lanes, that may be used to send +messages. All messages sent using other lanes are rejected. All messages that have size above +`pallet_bridge_messages::Config::MaximalOutboundPayloadSize` will also be rejected. + +To be able to reward the relayer for delivering messages, we store a map of message nonces range => identifier of the +relayer that has delivered this range at the target chain runtime storage. If a relayer delivers multiple consequent +ranges, they're merged into single entry. So there may be more than one entry for the same relayer. Eventually, this +whole map must be delivered back to the source chain to confirm delivery and pay rewards. So to make sure we are able to +craft this confirmation transaction, we need to: (1) keep the size of this map below a certain limit and (2) make sure +that the weight of processing this map is below a certain limit. Both size and processing weight mostly depend on the +number of entries. The number of entries is limited with the +`pallet_bridge_messages::ConfigMaxUnrewardedRelayerEntriesAtInboundLane` parameter. Processing weight also depends on +the total number of messages that are being confirmed, because every confirmed message needs to be read. So there's +another `pallet_bridge_messages::Config::MaxUnconfirmedMessagesAtInboundLane` parameter for that. + +When choosing values for these parameters, you must also keep in mind that if proof in your scheme is based on finality +of headers (and it is the most obvious option for Substrate-based chains with finality notion), then choosing too small +values for these parameters may cause significant delays in message delivery. That's because there are too many actors +involved in this scheme: 1) authorities that are finalizing headers of the target chain need to finalize header with +non-empty map; 2) the headers relayer then needs to submit this header and its finality proof to the source chain; 3) +the messages relayer must then send confirmation transaction (storage proof of this map) to the source chain; 4) when +the confirmation transaction will be mined at some header, source chain authorities must finalize this header; 5) the +headers relay then needs to submit this header and its finality proof to the target chain; 6) only now the messages +relayer may submit new messages from the source to target chain and prune the entry from the map. + +Delivery transaction requires the relayer to provide both number of entries and total number of messages in the map. +This means that the module never charges an extra cost for delivering a map - the relayer would need to pay exactly for +the number of entries+messages it has delivered. So the best guess for values of these parameters would be the pair that +would occupy `N` percent of the maximal transaction size and weight of the source chain. The `N` should be large enough +to process large maps, at the same time keeping reserve for future source chain upgrades. ## Non-Essential Functionality -There may be a special account in every runtime where the messages module is deployed. This -account, named 'module owner', is like a module-level sudo account - he's able to halt and -resume all module operations without requiring runtime upgrade. Calls that are related to this -account are: +There may be a special account in every runtime where the messages module is deployed. This account, named 'module +owner', is like a module-level sudo account - he's able to halt and resume all module operations without requiring +runtime upgrade. Calls that are related to this account are: - `fn set_owner()`: current module owner may call it to transfer "ownership" to another account; -- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all - module operations. After this call, all message-related transactions will be rejected until - further `resume_operations` call'. This call may be used when something extraordinary happens with - the bridge; -- `fn resume_operations()`: module owner may call this function to resume bridge operations. The - module will resume its regular operations after this call. +- `fn halt_operations()`: the module owner (or sudo account) may call this function to stop all module operations. After + this call, all message-related transactions will be rejected until further `resume_operations` call'. This call may be + used when something extraordinary happens with the bridge; +- `fn resume_operations()`: module owner may call this function to resume bridge operations. The module will resume its + regular operations after this call. If pallet owner is not defined, the governance may be used to make those calls. ## Messages Relay -We have an offchain actor, who is watching for new messages and submits them to the bridged chain. -It is the messages relay - you may look at the [crate level documentation and the code](../../relays/messages/). +We have an offchain actor, who is watching for new messages and submits them to the bridged chain. It is the messages +relay - you may look at the [crate level documentation and the code](../../relays/messages/). diff --git a/modules/parachains/README.md b/modules/parachains/README.md index 5982c65ad3166..d3f52c791ab58 100644 --- a/modules/parachains/README.md +++ b/modules/parachains/README.md @@ -19,7 +19,7 @@ validators. Validators validate the block and register the new parachain head in [`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645) of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet, deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet, -even though the names are similar. +even though the names are similar. And what the bridge parachains pallet does, is simply verifying storage proofs of parachain heads within that `Heads` map. It does that using relay chain header, that has been previously imported by the From 48ff28395c19797d17656508aff59954a37d05f0 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 4 Sep 2023 19:54:55 +0300 Subject: [PATCH 1102/1210] bridges subtree fixes (#2528) --- primitives/polkadot-core/src/parachains.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 3cf8eca0c6b6d..223956171f864 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -37,7 +37,8 @@ use parity_util_mem::MallocSizeOf; /// Parachain id. /// -/// This is an equivalent of the `polkadot_parachain::Id`, which is a compact-encoded `u32`. +/// This is an equivalent of the `polkadot_parachain_primitives::Id`, which is a compact-encoded +/// `u32`. #[derive( Clone, CompactAs, @@ -64,7 +65,7 @@ impl From for ParaId { /// Parachain head. /// -/// This is an equivalent of the `polkadot_parachain::HeadData`. +/// This is an equivalent of the `polkadot_parachain_primitives::HeadData`. /// /// The parachain head means (at least in Cumulus) a SCALE-encoded parachain header. #[derive( From 8ecb1772aa8bf317aba5f0ca799f13fcb8db05cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:03:10 +0000 Subject: [PATCH 1103/1210] Bump subxt from 0.28.0 to 0.31.0 Bumps [subxt](https://github.com/paritytech/subxt) from 0.28.0 to 0.31.0. - [Release notes](https://github.com/paritytech/subxt/releases) - [Changelog](https://github.com/paritytech/subxt/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/subxt/compare/v0.28.0...v0.31.0) --- updated-dependencies: - dependency-name: subxt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 1f3a70aaa5d5d..58d5ca7c18af4 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.28.0", default-features = false, features = [] } +subxt = { version = "0.31.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index a511b9071eb73..51b445e46d2aa 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.28.0", default-features = false, features = [] } +subxt = { version = "0.31.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index bb8bb5604547c..5d3a912bd9e5b 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.28.0", default-features = false, features = [] } +subxt = { version = "0.31.0", default-features = false, features = [] } # Bridge dependencies From 6de22e0208f1a45c9406d71d052205663ff390f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:04:38 +0000 Subject: [PATCH 1104/1210] Bump strum from 0.24.1 to 0.25.0 Bumps [strum](https://github.com/Peternator7/strum) from 0.24.1 to 0.25.0. - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 28a2b1a35de02..c9d12a7029678 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -19,7 +19,7 @@ rbtag = "0.3" structopt = "0.3" signal-hook = "0.3.15" signal-hook-async-std = "0.2.2" -strum = { version = "0.24.1", features = ["derive"] } +strum = { version = "0.25.0", features = ["derive"] } # Bridge dependencies bp-header-chain = { path = "../../primitives/header-chain" } From 04311cafe4d6ebb16abbe674ad174e4a345c45cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:25:10 +0000 Subject: [PATCH 1105/1210] Bump thiserror from 1.0.47 to 1.0.48 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.47 to 1.0.48. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.47...1.0.48) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 188c411c6914e..23dd31b80fe6c 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -16,7 +16,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.9.0", features = ["derive"] } tokio = { version = "1.32", features = ["rt-multi-thread"] } -thiserror = "1.0.47" +thiserror = "1.0.48" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index fc5dd4f8caed9..ab01ad63dcf17 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.47" +thiserror = "1.0.48" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 633d069169499..2a66eb25dfb9f 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.32", features = ["rt"] } -thiserror = "1.0.47" +thiserror = "1.0.48" # Bridge dependencies From bfb87bf098d98f3913b92fea3e24442ccfcb0e53 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Fri, 8 Sep 2023 12:50:12 +0200 Subject: [PATCH 1106/1210] Backport for polkadot-sdk#1446 (#2546) * Backport for polkadot-sdk#1446 * Cargo.toml --- primitives/test-utils/Cargo.toml | 2 +- primitives/test-utils/src/keyring.rs | 24 +++++------------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index ac603d3450dd8..a57a2d82088e3 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -12,7 +12,7 @@ bp-parachains = { path = "../parachains", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -ed25519-dalek = { version = "1.0", default-features = false, features = ["u64_backend"] } +ed25519-dalek = { version = "2.0", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index b99132de3ec36..eabf9c784eb81 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -18,7 +18,7 @@ use bp_header_chain::{justification::JustificationVerificationContext, AuthoritySet}; use codec::Encode; -use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signature}; +use ed25519_dalek::{Signature, SigningKey, VerifyingKey}; use finality_grandpa::voter_set::VoterSet; use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; use sp_runtime::RuntimeDebug; @@ -37,29 +37,15 @@ pub const FERDIE: Account = Account(5); pub struct Account(pub u16); impl Account { - pub fn public(&self) -> PublicKey { - (&self.secret()).into() + pub fn public(&self) -> VerifyingKey { + self.pair().verifying_key() } - pub fn secret(&self) -> SecretKey { + pub fn pair(&self) -> SigningKey { let data = self.0.encode(); let mut bytes = [0_u8; 32]; bytes[0..data.len()].copy_from_slice(&data); - SecretKey::from_bytes(&bytes) - .expect("A static array of the correct length is a known good.") - } - - pub fn pair(&self) -> Keypair { - let mut pair: [u8; 64] = [0; 64]; - - let secret = self.secret(); - pair[..32].copy_from_slice(&secret.to_bytes()); - - let public = self.public(); - pair[32..].copy_from_slice(&public.to_bytes()); - - Keypair::from_bytes(&pair) - .expect("We expect the SecretKey to be good, so this must also be good.") + SigningKey::from_bytes(&bytes) } pub fn sign(&self, msg: &[u8]) -> Signature { From 03b93614079706d84ef0e22dddbd205912ca1f2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 01:57:31 +0000 Subject: [PATCH 1107/1210] Bump serde_json from 1.0.105 to 1.0.106 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.105 to 1.0.106. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.105...v1.0.106) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 0903aab9e606c..13565cc10e974 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -12,7 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" clap = { version = "4.3.23", features = ["derive"] } futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.105" +serde_json = "1.0.106" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index e7b91b82182a1..627de19d67305 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -18,7 +18,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.3.23", features = ["derive"] } -serde_json = "1.0.105" +serde_json = "1.0.106" # Bridge dependencies From 23699de14a111cadf2d4daaafc77ef8d7a622906 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 12 Sep 2023 16:38:26 +0300 Subject: [PATCH 1108/1210] Equivocation detection loop: Reorganize block checking logic as state machine (#2555) (#2557) * Split `reconnect_failed_client()` logic * Reorganize block checking logic as state machine This way we'll be able to save the state in case of a failure --- relays/equivocation/src/block_checker.rs | 252 +++++++++++++++++++ relays/equivocation/src/equivocation_loop.rs | 198 ++------------- relays/equivocation/src/lib.rs | 50 +++- relays/utils/src/relay_loop.rs | 57 ++--- 4 files changed, 340 insertions(+), 217 deletions(-) create mode 100644 relays/equivocation/src/block_checker.rs diff --git a/relays/equivocation/src/block_checker.rs b/relays/equivocation/src/block_checker.rs new file mode 100644 index 0000000000000..358d61fcf8e56 --- /dev/null +++ b/relays/equivocation/src/block_checker.rs @@ -0,0 +1,252 @@ +// Copyright (C) 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 . + +use crate::{ + handle_client_error, reporter::EquivocationsReporter, EquivocationDetectionPipeline, + EquivocationReportingContext, HeaderFinalityInfo, SourceClient, TargetClient, +}; + +use bp_header_chain::{FinalityProof, FindEquivocations as FindEquivocationsT}; +use finality_relay::FinalityProofsBuf; +use futures::future::{BoxFuture, FutureExt}; +use num_traits::Saturating; + +/// First step in the block checking state machine. +/// +/// Getting the finality info associated to the source headers synced with the target chain +/// at the specified block. +pub struct ReadSyncedHeaders { + pub target_block_num: P::TargetNumber, +} + +impl ReadSyncedHeaders

{ + pub async fn next>( + self, + target_client: &mut TC, + ) -> Result, Self> { + match target_client.synced_headers_finality_info(self.target_block_num).await { + Ok(synced_headers) => + Ok(ReadContext { target_block_num: self.target_block_num, synced_headers }), + Err(e) => { + log::error!( + target: "bridge", + "Could not get {} headers synced to {} at block {}: {e:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + self.target_block_num + ); + + // Reconnect target client in case of a connection error. + handle_client_error(target_client, e).await; + + Err(self) + }, + } + } +} + +/// Second step in the block checking state machine. +/// +/// Reading the equivocation reporting context from the target chain. +pub struct ReadContext { + target_block_num: P::TargetNumber, + synced_headers: Vec>, +} + +impl ReadContext

{ + pub async fn next>( + self, + target_client: &mut TC, + ) -> Result>, Self> { + match EquivocationReportingContext::try_read_from_target::( + target_client, + self.target_block_num.saturating_sub(1.into()), + ) + .await + { + Ok(Some(context)) => Ok(Some(FindEquivocations { + target_block_num: self.target_block_num, + synced_headers: self.synced_headers, + context, + })), + Ok(None) => Ok(None), + Err(e) => { + log::error!( + target: "bridge", + "Could not read {} `EquivocationReportingContext` from {} at block {}: {e:?}", + P::SOURCE_NAME, + P::TARGET_NAME, + self.target_block_num.saturating_sub(1.into()), + ); + + // Reconnect target client in case of a connection error. + handle_client_error(target_client, e).await; + + Err(self) + }, + } + } +} + +/// Third step in the block checking state machine. +/// +/// Searching for equivocations in the source headers synced with the target chain. +pub struct FindEquivocations { + target_block_num: P::TargetNumber, + synced_headers: Vec>, + context: EquivocationReportingContext

, +} + +impl FindEquivocations

{ + pub fn next( + mut self, + finality_proofs_buf: &mut FinalityProofsBuf

, + ) -> Vec> { + let mut result = vec![]; + for synced_header in self.synced_headers { + match P::EquivocationsFinder::find_equivocations( + &self.context.synced_verification_context, + &synced_header.finality_proof, + finality_proofs_buf.buf().as_slice(), + ) { + Ok(equivocations) => result.push(ReportEquivocations { + source_block_hash: self.context.synced_header_hash, + equivocations, + }), + Err(e) => { + log::error!( + target: "bridge", + "Could not search for equivocations in the finality proof \ + for source header {:?} synced at target block {}: {e:?}", + synced_header.finality_proof.target_header_hash(), + self.target_block_num + ); + }, + }; + + finality_proofs_buf.prune(synced_header.finality_proof.target_header_number(), None); + self.context.update(synced_header); + } + + result + } +} + +/// Fourth step in the block checking state machine. +/// +/// Reporting the detected equivocations (if any). +pub struct ReportEquivocations { + source_block_hash: P::Hash, + equivocations: Vec, +} + +impl ReportEquivocations

{ + pub async fn next>( + mut self, + source_client: &mut SC, + reporter: &mut EquivocationsReporter, + ) -> Result<(), Self> { + let mut unprocessed_equivocations = vec![]; + for equivocation in self.equivocations { + match reporter + .submit_report(source_client, self.source_block_hash, equivocation.clone()) + .await + { + Ok(_) => {}, + Err(e) => { + log::error!( + target: "bridge", + "Could not submit equivocation report to {} for {equivocation:?}: {e:?}", + P::SOURCE_NAME, + ); + + // Mark the equivocation as unprocessed + unprocessed_equivocations.push(equivocation); + // Reconnect source client in case of a connection error. + handle_client_error(source_client, e).await; + }, + } + } + + self.equivocations = unprocessed_equivocations; + if !self.equivocations.is_empty() { + return Err(self) + } + + Ok(()) + } +} + +/// Block checking state machine. +pub enum BlockChecker { + ReadSyncedHeaders(ReadSyncedHeaders

), + ReadContext(ReadContext

), + ReportEquivocations(Vec>), +} + +impl BlockChecker

{ + pub fn new(target_block_num: P::TargetNumber) -> Self { + Self::ReadSyncedHeaders(ReadSyncedHeaders { target_block_num }) + } + + pub fn run<'a, SC: SourceClient

, TC: TargetClient

>( + self, + source_client: &'a mut SC, + target_client: &'a mut TC, + finality_proofs_buf: &'a mut FinalityProofsBuf

, + reporter: &'a mut EquivocationsReporter, + ) -> BoxFuture<'a, Result<(), Self>> { + async move { + match self { + Self::ReadSyncedHeaders(state) => { + let read_context = + state.next(target_client).await.map_err(Self::ReadSyncedHeaders)?; + Self::ReadContext(read_context) + .run(source_client, target_client, finality_proofs_buf, reporter) + .await + }, + Self::ReadContext(state) => { + let maybe_find_equivocations = + state.next(target_client).await.map_err(Self::ReadContext)?; + let find_equivocations = match maybe_find_equivocations { + Some(find_equivocations) => find_equivocations, + None => return Ok(()), + }; + Self::ReportEquivocations(find_equivocations.next(finality_proofs_buf)) + .run(source_client, target_client, finality_proofs_buf, reporter) + .await + }, + Self::ReportEquivocations(state) => { + let mut failures = vec![]; + for report_equivocations in state { + if let Err(failure) = + report_equivocations.next(source_client, reporter).await + { + failures.push(failure); + } + } + + if !failures.is_empty() { + return Err(Self::ReportEquivocations(failures)) + } + + Ok(()) + }, + } + } + .boxed() + } +} diff --git a/relays/equivocation/src/equivocation_loop.rs b/relays/equivocation/src/equivocation_loop.rs index 61ffa92c8dc46..da3f72b94660d 100644 --- a/relays/equivocation/src/equivocation_loop.rs +++ b/relays/equivocation/src/equivocation_loop.rs @@ -15,55 +15,17 @@ // along with Parity Bridges Common. If not, see . use crate::{ - reporter::EquivocationsReporter, EquivocationDetectionPipeline, HeaderFinalityInfo, + handle_client_error, reporter::EquivocationsReporter, EquivocationDetectionPipeline, SourceClient, TargetClient, }; -use bp_header_chain::{FinalityProof, FindEquivocations}; +use crate::block_checker::BlockChecker; use finality_relay::{FinalityProofsBuf, FinalityProofsStream}; use futures::{select, FutureExt}; use num_traits::Saturating; -use relay_utils::{ - metrics::MetricsParams, - relay_loop::{reconnect_failed_client, RECONNECT_DELAY}, - FailedClient, MaybeConnectionError, -}; +use relay_utils::{metrics::MetricsParams, FailedClient}; use std::{future::Future, time::Duration}; -/// The context needed for finding equivocations inside finality proofs and reporting them. -struct EquivocationReportingContext { - synced_header_hash: P::Hash, - synced_verification_context: P::FinalityVerificationContext, -} - -impl EquivocationReportingContext

{ - /// Try to get the `EquivocationReportingContext` used by the target chain - /// at the provided block. - async fn try_read_from_target>( - target_client: &TC, - at: P::TargetNumber, - ) -> Result, TC::Error> { - let maybe_best_synced_header_hash = target_client.best_synced_header_hash(at).await?; - Ok(match maybe_best_synced_header_hash { - Some(best_synced_header_hash) => Some(EquivocationReportingContext { - synced_header_hash: best_synced_header_hash, - synced_verification_context: target_client - .finality_verification_context(at) - .await?, - }), - None => None, - }) - } - - /// Update with the new context introduced by the `HeaderFinalityInfo

` if any. - fn update(&mut self, info: HeaderFinalityInfo

) { - if let Some(new_verification_context) = info.new_verification_context { - self.synced_header_hash = info.finality_proof.target_header_hash(); - self.synced_verification_context = new_verification_context; - } - } -} - /// Equivocations detection loop state. struct EquivocationDetectionLoop< P: EquivocationDetectionPipeline, @@ -85,34 +47,6 @@ struct EquivocationDetectionLoop< impl, TC: TargetClient

> EquivocationDetectionLoop { - async fn handle_source_error(&mut self, e: SC::Error) { - if e.is_connection_error() { - reconnect_failed_client( - FailedClient::Source, - RECONNECT_DELAY, - &mut self.source_client, - &mut self.target_client, - ) - .await; - } else { - async_std::task::sleep(RECONNECT_DELAY).await; - } - } - - async fn handle_target_error(&mut self, e: TC::Error) { - if e.is_connection_error() { - reconnect_failed_client( - FailedClient::Target, - RECONNECT_DELAY, - &mut self.source_client, - &mut self.target_client, - ) - .await; - } else { - async_std::task::sleep(RECONNECT_DELAY).await; - } - } - async fn ensure_finality_proofs_stream(&mut self) { match self.finality_proofs_stream.ensure_stream(&self.source_client).await { Ok(_) => {}, @@ -124,7 +58,7 @@ impl, TC: TargetClient

> ); // Reconnect to the source client if needed - self.handle_source_error(e).await + handle_client_error(&mut self.source_client, e).await; }, } } @@ -140,116 +74,13 @@ impl, TC: TargetClient

> ); // Reconnect target client and move on - self.handle_target_error(e).await; - - None - }, - } - } - - async fn build_equivocation_reporting_context( - &mut self, - block_num: P::TargetNumber, - ) -> Option> { - match EquivocationReportingContext::try_read_from_target( - &self.target_client, - block_num.saturating_sub(1.into()), - ) - .await - { - Ok(Some(context)) => Some(context), - Ok(None) => None, - Err(e) => { - log::error!( - target: "bridge", - "Could not read {} `EquivocationReportingContext` from {} at block {block_num}: {e:?}", - P::SOURCE_NAME, - P::TARGET_NAME, - ); + handle_client_error(&mut self.target_client, e).await; - // Reconnect target client if needed and move on. - self.handle_target_error(e).await; None }, } } - /// Try to get the finality info associated to the source headers synced with the target chain - /// at the specified block. - async fn synced_source_headers_at_target( - &mut self, - at: P::TargetNumber, - ) -> Vec> { - match self.target_client.synced_headers_finality_info(at).await { - Ok(synced_headers) => synced_headers, - Err(e) => { - log::error!( - target: "bridge", - "Could not get {} headers synced to {} at block {at:?}", - P::SOURCE_NAME, - P::TARGET_NAME - ); - - // Reconnect in case of a connection error. - self.handle_target_error(e).await; - // And move on to the next block. - vec![] - }, - } - } - - async fn report_equivocation(&mut self, at: P::Hash, equivocation: P::EquivocationProof) { - match self.reporter.submit_report(&self.source_client, at, equivocation.clone()).await { - Ok(_) => {}, - Err(e) => { - log::error!( - target: "bridge", - "Could not submit equivocation report to {} for {equivocation:?}: {e:?}", - P::SOURCE_NAME, - ); - - // Reconnect source client and move on - self.handle_source_error(e).await; - }, - } - } - - async fn check_block( - &mut self, - block_num: P::TargetNumber, - context: &mut EquivocationReportingContext

, - ) { - let synced_headers = self.synced_source_headers_at_target(block_num).await; - - for synced_header in synced_headers { - self.finality_proofs_buf.fill(&mut self.finality_proofs_stream); - - let equivocations = match P::EquivocationsFinder::find_equivocations( - &context.synced_verification_context, - &synced_header.finality_proof, - self.finality_proofs_buf.buf().as_slice(), - ) { - Ok(equivocations) => equivocations, - Err(e) => { - log::error!( - target: "bridge", - "Could not search for equivocations in the finality proof \ - for source header {:?} synced at target block {block_num:?}: {e:?}", - synced_header.finality_proof.target_header_hash() - ); - continue - }, - }; - for equivocation in equivocations { - self.report_equivocation(context.synced_header_hash, equivocation).await; - } - - self.finality_proofs_buf - .prune(synced_header.finality_proof.target_header_number(), None); - context.update(synced_header); - } - } - async fn do_run(&mut self, tick: Duration, exit_signal: impl Future) { let exit_signal = exit_signal.fuse(); futures::pin_mut!(exit_signal); @@ -273,15 +104,16 @@ impl, TC: TargetClient

> // Check the available blocks let mut current_block_number = from; while current_block_number <= until { - let mut context = - match self.build_equivocation_reporting_context(current_block_number).await { - Some(context) => context, - None => { - current_block_number = current_block_number.saturating_add(1.into()); - continue - }, - }; - self.check_block(current_block_number, &mut context).await; + self.finality_proofs_buf.fill(&mut self.finality_proofs_stream); + let block_checker = BlockChecker::new(current_block_number); + let _ = block_checker + .run( + &mut self.source_client, + &mut self.target_client, + &mut self.finality_proofs_buf, + &mut self.reporter, + ) + .await; current_block_number = current_block_number.saturating_add(1.into()); } self.until_block_num = Some(current_block_number); diff --git a/relays/equivocation/src/lib.rs b/relays/equivocation/src/lib.rs index 6f9337483fdab..bb1f40c13e6d4 100644 --- a/relays/equivocation/src/lib.rs +++ b/relays/equivocation/src/lib.rs @@ -14,13 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +mod block_checker; mod equivocation_loop; mod reporter; use async_trait::async_trait; -use bp_header_chain::FindEquivocations; +use bp_header_chain::{FinalityProof, FindEquivocations}; use finality_relay::{FinalityPipeline, SourceClientBase}; -use relay_utils::{relay_loop::Client as RelayClient, TransactionTracker}; +use relay_utils::{ + relay_loop::{Client as RelayClient, RECONNECT_DELAY}, + MaybeConnectionError, TransactionTracker, +}; use std::fmt::Debug; pub use equivocation_loop::run; @@ -85,3 +89,45 @@ pub trait TargetClient: RelayClient { at: P::TargetNumber, ) -> Result>, Self::Error>; } + +/// The context needed for finding equivocations inside finality proofs and reporting them. +struct EquivocationReportingContext { + pub synced_header_hash: P::Hash, + pub synced_verification_context: P::FinalityVerificationContext, +} + +impl EquivocationReportingContext

{ + /// Try to get the `EquivocationReportingContext` used by the target chain + /// at the provided block. + pub async fn try_read_from_target>( + target_client: &TC, + at: P::TargetNumber, + ) -> Result, TC::Error> { + let maybe_best_synced_header_hash = target_client.best_synced_header_hash(at).await?; + Ok(match maybe_best_synced_header_hash { + Some(best_synced_header_hash) => Some(EquivocationReportingContext { + synced_header_hash: best_synced_header_hash, + synced_verification_context: target_client + .finality_verification_context(at) + .await?, + }), + None => None, + }) + } + + /// Update with the new context introduced by the `HeaderFinalityInfo

` if any. + pub fn update(&mut self, info: HeaderFinalityInfo

) { + if let Some(new_verification_context) = info.new_verification_context { + self.synced_header_hash = info.finality_proof.target_header_hash(); + self.synced_verification_context = new_verification_context; + } + } +} + +async fn handle_client_error(client: &mut C, e: C::Error) { + if e.is_connection_error() { + client.reconnect_until_success(RECONNECT_DELAY).await; + } else { + async_std::task::sleep(RECONNECT_DELAY).await; + } +} diff --git a/relays/utils/src/relay_loop.rs b/relays/utils/src/relay_loop.rs index dad7293de6d28..7105190a45831 100644 --- a/relays/utils/src/relay_loop.rs +++ b/relays/utils/src/relay_loop.rs @@ -35,6 +35,25 @@ pub trait Client: 'static + Clone + Send + Sync { /// Try to reconnect to source node. async fn reconnect(&mut self) -> Result<(), Self::Error>; + + /// Try to reconnect to the source node in an infinite loop until it succeeds. + async fn reconnect_until_success(&mut self, delay: Duration) { + loop { + match self.reconnect().await { + Ok(()) => break, + Err(error) => { + log::warn!( + target: "bridge", + "Failed to reconnect to client. Going to retry in {}s: {:?}", + delay.as_secs(), + error, + ); + + async_std::task::sleep(delay).await; + }, + } + } + } } #[async_trait] @@ -226,44 +245,18 @@ impl LoopMetrics { } } -/// Deal with the client who has returned connection error. +/// Deal with the clients that have returned connection error. pub async fn reconnect_failed_client( failed_client: FailedClient, reconnect_delay: Duration, source_client: &mut impl Client, target_client: &mut impl Client, ) { - loop { - async_std::task::sleep(reconnect_delay).await; - if failed_client == FailedClient::Both || failed_client == FailedClient::Source { - match source_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to source client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue - }, - } - } - if failed_client == FailedClient::Both || failed_client == FailedClient::Target { - match target_client.reconnect().await { - Ok(()) => (), - Err(error) => { - log::warn!( - target: "bridge", - "Failed to reconnect to target client. Going to retry in {}s: {:?}", - reconnect_delay.as_secs(), - error, - ); - continue - }, - } - } + if failed_client == FailedClient::Source || failed_client == FailedClient::Both { + source_client.reconnect_until_success(reconnect_delay).await; + } - break + if failed_client == FailedClient::Target || failed_client == FailedClient::Both { + target_client.reconnect_until_success(reconnect_delay).await; } } From 3c4d892b5956377eebb717618e2241a6fc038cb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 16:20:18 +0000 Subject: [PATCH 1109/1210] Bump trie-db from 0.27.1 to 0.28.0 Bumps [trie-db](https://github.com/paritytech/trie) from 0.27.1 to 0.28.0. - [Commits](https://github.com/paritytech/trie/compare/trie-db-v0.27.1...trie-db-v0.28.0) --- updated-dependencies: - dependency-name: trie-db dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/runtime/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index a5583c6b98884..6872ffd98486b 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -trie-db = { version = "0.27.1", default-features = false } +trie-db = { version = "0.28.0", default-features = false } [dev-dependencies] hex-literal = "0.4" From ff4e277d6ddfdd345f4e3adb3d18eb98e7a514e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 07:14:47 +0000 Subject: [PATCH 1110/1210] Bump serde_json from 1.0.106 to 1.0.107 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.106 to 1.0.107. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.106...v1.0.107) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 13565cc10e974..e6e7d4d57ccbb 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -12,7 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" clap = { version = "4.3.23", features = ["derive"] } futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.106" +serde_json = "1.0.107" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 627de19d67305..8b02d601cacd0 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -18,7 +18,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.3.23", features = ["derive"] } -serde_json = "1.0.106" +serde_json = "1.0.107" # Bridge dependencies From d464292c22f57ffa18e082538e9af52f824be878 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 07:48:46 +0000 Subject: [PATCH 1111/1210] Bump clap from 4.4.2 to 4.4.3 Bumps [clap](https://github.com/clap-rs/clap) from 4.4.2 to 4.4.3. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.2...v4.4.3) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index e6e7d4d57ccbb..c8c6cd3f75bdf 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.3.23", features = ["derive"] } +clap = { version = "4.4.3", features = ["derive"] } futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.107" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index ced2d809c1456..d2bc660cbc361 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.3.23", features = ["derive"] } +clap = { version = "4.4.3", features = ["derive"] } log = '0.4.20' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 8b02d601cacd0..a8ad170d49d41 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.3.23", features = ["derive"] } +clap = { version = "4.4.3", features = ["derive"] } serde_json = "1.0.107" # Bridge dependencies From 861fbe4d004697833cc7aaa5ee31c0dfcacd7b6c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 18 Sep 2023 11:51:54 +0300 Subject: [PATCH 1112/1210] Add unit tests for the equivocation detection loop (#2571) * Add unit tests for the equivocation detection loop * clippy * use std::future::pending() --- .../src/justification/verification/mod.rs | 1 + relays/equivocation/Cargo.toml | 2 +- relays/equivocation/src/block_checker.rs | 229 +++++++++++++- relays/equivocation/src/equivocation_loop.rs | 144 ++++++++- relays/equivocation/src/lib.rs | 16 +- relays/equivocation/src/mock.rs | 285 ++++++++++++++++++ relays/equivocation/src/reporter.rs | 52 +++- relays/finality/src/finality_proofs.rs | 10 +- .../src/finality_base/engine.rs | 2 +- relays/utils/src/lib.rs | 4 +- 10 files changed, 716 insertions(+), 29 deletions(-) create mode 100644 relays/equivocation/src/mock.rs diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/primitives/header-chain/src/justification/verification/mod.rs index bb8aaadf327ec..a66fc1e0d91d1 100644 --- a/primitives/header-chain/src/justification/verification/mod.rs +++ b/primitives/header-chain/src/justification/verification/mod.rs @@ -143,6 +143,7 @@ pub enum PrecommitError { } /// The context needed for validating GRANDPA finality proofs. +#[derive(RuntimeDebug)] pub struct JustificationVerificationContext { /// The authority set used to verify the justification. pub voter_set: VoterSet, diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 4df0f0d11709e..ff94e73709114 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Equivocation detector" [dependencies] -async-std = "1.6.5" +async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } diff --git a/relays/equivocation/src/block_checker.rs b/relays/equivocation/src/block_checker.rs index 358d61fcf8e56..c8131e5b9796f 100644 --- a/relays/equivocation/src/block_checker.rs +++ b/relays/equivocation/src/block_checker.rs @@ -28,6 +28,7 @@ use num_traits::Saturating; /// /// Getting the finality info associated to the source headers synced with the target chain /// at the specified block. +#[cfg_attr(test, derive(Debug, PartialEq))] pub struct ReadSyncedHeaders { pub target_block_num: P::TargetNumber, } @@ -61,6 +62,7 @@ impl ReadSyncedHeaders

{ /// Second step in the block checking state machine. /// /// Reading the equivocation reporting context from the target chain. +#[cfg_attr(test, derive(Debug))] pub struct ReadContext { target_block_num: P::TargetNumber, synced_headers: Vec>, @@ -104,6 +106,7 @@ impl ReadContext

{ /// Third step in the block checking state machine. /// /// Searching for equivocations in the source headers synced with the target chain. +#[cfg_attr(test, derive(Debug))] pub struct FindEquivocations { target_block_num: P::TargetNumber, synced_headers: Vec>, @@ -122,10 +125,13 @@ impl FindEquivocations

{ &synced_header.finality_proof, finality_proofs_buf.buf().as_slice(), ) { - Ok(equivocations) => result.push(ReportEquivocations { - source_block_hash: self.context.synced_header_hash, - equivocations, - }), + Ok(equivocations) => + if !equivocations.is_empty() { + result.push(ReportEquivocations { + source_block_hash: self.context.synced_header_hash, + equivocations, + }) + }, Err(e) => { log::error!( target: "bridge", @@ -148,6 +154,7 @@ impl FindEquivocations

{ /// Fourth step in the block checking state machine. /// /// Reporting the detected equivocations (if any). +#[cfg_attr(test, derive(Debug))] pub struct ReportEquivocations { source_block_hash: P::Hash, equivocations: Vec, @@ -157,7 +164,7 @@ impl ReportEquivocations

{ pub async fn next>( mut self, source_client: &mut SC, - reporter: &mut EquivocationsReporter, + reporter: &mut EquivocationsReporter<'_, P, SC>, ) -> Result<(), Self> { let mut unprocessed_equivocations = vec![]; for equivocation in self.equivocations { @@ -191,6 +198,7 @@ impl ReportEquivocations

{ } /// Block checking state machine. +#[cfg_attr(test, derive(Debug))] pub enum BlockChecker { ReadSyncedHeaders(ReadSyncedHeaders

), ReadContext(ReadContext

), @@ -250,3 +258,214 @@ impl BlockChecker

{ .boxed() } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use std::collections::HashMap; + + impl PartialEq for ReadContext { + fn eq(&self, other: &Self) -> bool { + self.target_block_num == other.target_block_num && + self.synced_headers == other.synced_headers + } + } + + impl PartialEq for FindEquivocations { + fn eq(&self, other: &Self) -> bool { + self.target_block_num == other.target_block_num && + self.synced_headers == other.synced_headers && + self.context == other.context + } + } + + impl PartialEq for ReportEquivocations { + fn eq(&self, other: &Self) -> bool { + self.source_block_hash == other.source_block_hash && + self.equivocations == other.equivocations + } + } + + impl PartialEq for BlockChecker { + fn eq(&self, _other: &Self) -> bool { + matches!(self, _other) + } + } + + #[async_std::test] + async fn block_checker_works() { + let mut source_client = TestSourceClient { ..Default::default() }; + let mut target_client = TestTargetClient { + best_synced_header_hash: HashMap::from([(9, Ok(Some(5)))]), + finality_verification_context: HashMap::from([( + 9, + Ok(TestFinalityVerificationContext { check_equivocations: true }), + )]), + synced_headers_finality_info: HashMap::from([( + 10, + Ok(vec![ + new_header_finality_info(6, None), + new_header_finality_info(7, Some(false)), + new_header_finality_info(8, None), + new_header_finality_info(9, Some(true)), + new_header_finality_info(10, None), + new_header_finality_info(11, None), + new_header_finality_info(12, None), + ]), + )]), + ..Default::default() + }; + let mut reporter = + EquivocationsReporter::::new(); + + let block_checker = BlockChecker::new(10); + assert!(block_checker + .run( + &mut source_client, + &mut target_client, + &mut FinalityProofsBuf::new(vec![ + TestFinalityProof(6, vec!["6-1"]), + TestFinalityProof(7, vec![]), + TestFinalityProof(8, vec!["8-1"]), + TestFinalityProof(9, vec!["9-1"]), + TestFinalityProof(10, vec![]), + TestFinalityProof(11, vec!["11-1", "11-2"]), + TestFinalityProof(12, vec!["12-1"]) + ]), + &mut reporter + ) + .await + .is_ok()); + assert_eq!( + *source_client.reported_equivocations.lock().unwrap(), + HashMap::from([(5, vec!["6-1"]), (9, vec!["11-1", "11-2", "12-1"])]) + ); + } + + #[async_std::test] + async fn block_checker_works_with_empty_context() { + let mut target_client = TestTargetClient { + best_synced_header_hash: HashMap::from([(9, Ok(None))]), + finality_verification_context: HashMap::from([( + 9, + Ok(TestFinalityVerificationContext { check_equivocations: true }), + )]), + synced_headers_finality_info: HashMap::from([( + 10, + Ok(vec![new_header_finality_info(6, None)]), + )]), + ..Default::default() + }; + let mut source_client = TestSourceClient { ..Default::default() }; + let mut reporter = + EquivocationsReporter::::new(); + + let block_checker = BlockChecker::new(10); + assert!(block_checker + .run( + &mut source_client, + &mut target_client, + &mut FinalityProofsBuf::new(vec![TestFinalityProof(6, vec!["6-1"])]), + &mut reporter + ) + .await + .is_ok()); + assert_eq!(*source_client.reported_equivocations.lock().unwrap(), HashMap::default()); + } + + #[async_std::test] + async fn read_synced_headers_handles_errors() { + let mut target_client = TestTargetClient { + synced_headers_finality_info: HashMap::from([ + (10, Err(TestClientError::NonConnection)), + (11, Err(TestClientError::Connection)), + ]), + ..Default::default() + }; + let mut source_client = TestSourceClient { ..Default::default() }; + let mut reporter = + EquivocationsReporter::::new(); + + // NonConnection error + let block_checker = BlockChecker::new(10); + assert_eq!( + block_checker + .run( + &mut source_client, + &mut target_client, + &mut FinalityProofsBuf::new(vec![]), + &mut reporter + ) + .await, + Err(BlockChecker::ReadSyncedHeaders(ReadSyncedHeaders { target_block_num: 10 })) + ); + assert_eq!(target_client.num_reconnects, 0); + + // Connection error + let block_checker = BlockChecker::new(11); + assert_eq!( + block_checker + .run( + &mut source_client, + &mut target_client, + &mut FinalityProofsBuf::new(vec![]), + &mut reporter + ) + .await, + Err(BlockChecker::ReadSyncedHeaders(ReadSyncedHeaders { target_block_num: 11 })) + ); + assert_eq!(target_client.num_reconnects, 1); + } + + #[async_std::test] + async fn read_context_handles_errors() { + let mut target_client = TestTargetClient { + synced_headers_finality_info: HashMap::from([(10, Ok(vec![])), (11, Ok(vec![]))]), + best_synced_header_hash: HashMap::from([ + (9, Err(TestClientError::NonConnection)), + (10, Err(TestClientError::Connection)), + ]), + ..Default::default() + }; + let mut source_client = TestSourceClient { ..Default::default() }; + let mut reporter = + EquivocationsReporter::::new(); + + // NonConnection error + let block_checker = BlockChecker::new(10); + assert_eq!( + block_checker + .run( + &mut source_client, + &mut target_client, + &mut FinalityProofsBuf::new(vec![]), + &mut reporter + ) + .await, + Err(BlockChecker::ReadContext(ReadContext { + target_block_num: 10, + synced_headers: vec![] + })) + ); + assert_eq!(target_client.num_reconnects, 0); + + // Connection error + let block_checker = BlockChecker::new(11); + assert_eq!( + block_checker + .run( + &mut source_client, + &mut target_client, + &mut FinalityProofsBuf::new(vec![]), + &mut reporter + ) + .await, + Err(BlockChecker::ReadContext(ReadContext { + target_block_num: 11, + synced_headers: vec![] + })) + ); + assert_eq!(target_client.num_reconnects, 1); + } +} diff --git a/relays/equivocation/src/equivocation_loop.rs b/relays/equivocation/src/equivocation_loop.rs index da3f72b94660d..dfc4af0d4f62b 100644 --- a/relays/equivocation/src/equivocation_loop.rs +++ b/relays/equivocation/src/equivocation_loop.rs @@ -21,7 +21,7 @@ use crate::{ use crate::block_checker::BlockChecker; use finality_relay::{FinalityProofsBuf, FinalityProofsStream}; -use futures::{select, FutureExt}; +use futures::{select_biased, FutureExt}; use num_traits::Saturating; use relay_utils::{metrics::MetricsParams, FailedClient}; use std::{future::Future, time::Duration}; @@ -38,7 +38,7 @@ struct EquivocationDetectionLoop< from_block_num: Option, until_block_num: Option, - reporter: EquivocationsReporter, + reporter: EquivocationsReporter<'static, P, SC>, finality_proofs_stream: FinalityProofsStream, finality_proofs_buf: FinalityProofsBuf

, @@ -116,11 +116,11 @@ impl, TC: TargetClient

> .await; current_block_number = current_block_number.saturating_add(1.into()); } - self.until_block_num = Some(current_block_number); + self.from_block_num = Some(current_block_number); - select! { - _ = async_std::task::sleep(tick).fuse() => {}, + select_biased! { _ = exit_signal => return, + _ = async_std::task::sleep(tick).fuse() => {}, } } } @@ -172,3 +172,137 @@ pub async fn run( ) .await } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use futures::{channel::mpsc::UnboundedSender, StreamExt}; + use std::{ + collections::{HashMap, VecDeque}, + sync::{Arc, Mutex}, + }; + + fn best_finalized_header_number( + best_finalized_headers: &Mutex>>, + exit_sender: &UnboundedSender<()>, + ) -> Result { + let mut best_finalized_headers = best_finalized_headers.lock().unwrap(); + let result = best_finalized_headers.pop_front().unwrap(); + if best_finalized_headers.is_empty() { + exit_sender.unbounded_send(()).unwrap(); + } + result + } + + #[async_std::test] + async fn multiple_blocks_are_checked_correctly() { + let best_finalized_headers = Arc::new(Mutex::new(VecDeque::from([Ok(10), Ok(12), Ok(13)]))); + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + + let source_client = TestSourceClient { + finality_proofs: Arc::new(Mutex::new(vec![ + TestFinalityProof(2, vec!["2-1"]), + TestFinalityProof(3, vec!["3-1", "3-2"]), + TestFinalityProof(4, vec!["4-1"]), + TestFinalityProof(5, vec!["5-1"]), + TestFinalityProof(6, vec!["6-1", "6-2"]), + TestFinalityProof(7, vec!["7-1", "7-2"]), + ])), + ..Default::default() + }; + let reported_equivocations = source_client.reported_equivocations.clone(); + let target_client = TestTargetClient { + best_finalized_header_number: Arc::new(move || { + best_finalized_header_number(&best_finalized_headers, &exit_sender) + }), + best_synced_header_hash: HashMap::from([ + (9, Ok(Some(1))), + (10, Ok(Some(3))), + (11, Ok(Some(5))), + (12, Ok(Some(6))), + ]), + finality_verification_context: HashMap::from([ + (9, Ok(TestFinalityVerificationContext { check_equivocations: true })), + (10, Ok(TestFinalityVerificationContext { check_equivocations: true })), + (11, Ok(TestFinalityVerificationContext { check_equivocations: false })), + (12, Ok(TestFinalityVerificationContext { check_equivocations: true })), + ]), + synced_headers_finality_info: HashMap::from([ + ( + 10, + Ok(vec![new_header_finality_info(2, None), new_header_finality_info(3, None)]), + ), + ( + 11, + Ok(vec![ + new_header_finality_info(4, None), + new_header_finality_info(5, Some(false)), + ]), + ), + (12, Ok(vec![new_header_finality_info(6, None)])), + (13, Ok(vec![new_header_finality_info(7, None)])), + ]), + ..Default::default() + }; + + assert!(run::( + source_client, + target_client, + Duration::from_secs(0), + MetricsParams { address: None, registry: Default::default() }, + exit_receiver.into_future().map(|(_, _)| ()), + ) + .await + .is_ok()); + assert_eq!( + *reported_equivocations.lock().unwrap(), + HashMap::from([ + (1, vec!["2-1", "3-1", "3-2"]), + (3, vec!["4-1", "5-1"]), + (6, vec!["7-1", "7-2"]) + ]) + ); + } + + #[async_std::test] + async fn blocks_following_error_are_checked_correctly() { + let best_finalized_headers = Mutex::new(VecDeque::from([Ok(10), Ok(11)])); + let (exit_sender, exit_receiver) = futures::channel::mpsc::unbounded(); + + let source_client = TestSourceClient { + finality_proofs: Arc::new(Mutex::new(vec![ + TestFinalityProof(2, vec!["2-1"]), + TestFinalityProof(3, vec!["3-1"]), + ])), + ..Default::default() + }; + let reported_equivocations = source_client.reported_equivocations.clone(); + let target_client = TestTargetClient { + best_finalized_header_number: Arc::new(move || { + best_finalized_header_number(&best_finalized_headers, &exit_sender) + }), + best_synced_header_hash: HashMap::from([(9, Ok(Some(1))), (10, Ok(Some(2)))]), + finality_verification_context: HashMap::from([ + (9, Ok(TestFinalityVerificationContext { check_equivocations: true })), + (10, Ok(TestFinalityVerificationContext { check_equivocations: true })), + ]), + synced_headers_finality_info: HashMap::from([ + (10, Err(TestClientError::NonConnection)), + (11, Ok(vec![new_header_finality_info(3, None)])), + ]), + ..Default::default() + }; + + assert!(run::( + source_client, + target_client, + Duration::from_secs(0), + MetricsParams { address: None, registry: Default::default() }, + exit_receiver.into_future().map(|(_, _)| ()), + ) + .await + .is_ok()); + assert_eq!(*reported_equivocations.lock().unwrap(), HashMap::from([(2, vec!["3-1"]),])); + } +} diff --git a/relays/equivocation/src/lib.rs b/relays/equivocation/src/lib.rs index bb1f40c13e6d4..56a71ef3bc63c 100644 --- a/relays/equivocation/src/lib.rs +++ b/relays/equivocation/src/lib.rs @@ -16,24 +16,27 @@ mod block_checker; mod equivocation_loop; +mod mock; mod reporter; use async_trait::async_trait; use bp_header_chain::{FinalityProof, FindEquivocations}; use finality_relay::{FinalityPipeline, SourceClientBase}; -use relay_utils::{ - relay_loop::{Client as RelayClient, RECONNECT_DELAY}, - MaybeConnectionError, TransactionTracker, -}; -use std::fmt::Debug; +use relay_utils::{relay_loop::Client as RelayClient, MaybeConnectionError, TransactionTracker}; +use std::{fmt::Debug, time::Duration}; pub use equivocation_loop::run; +#[cfg(not(test))] +const RECONNECT_DELAY: Duration = relay_utils::relay_loop::RECONNECT_DELAY; +#[cfg(test)] +const RECONNECT_DELAY: Duration = mock::TEST_RECONNECT_DELAY; + pub trait EquivocationDetectionPipeline: FinalityPipeline { /// Block number of the target chain. type TargetNumber: relay_utils::BlockNumberBase; /// The context needed for validating finality proofs. - type FinalityVerificationContext: Send; + type FinalityVerificationContext: Debug + Send; /// The type of the equivocation proof. type EquivocationProof: Clone + Debug + Send + Sync; /// The equivocations finder. @@ -91,6 +94,7 @@ pub trait TargetClient: RelayClient { } /// The context needed for finding equivocations inside finality proofs and reporting them. +#[derive(Debug, PartialEq)] struct EquivocationReportingContext { pub synced_header_hash: P::Hash, pub synced_verification_context: P::FinalityVerificationContext, diff --git a/relays/equivocation/src/mock.rs b/relays/equivocation/src/mock.rs new file mode 100644 index 0000000000000..ced5c6f358065 --- /dev/null +++ b/relays/equivocation/src/mock.rs @@ -0,0 +1,285 @@ +// Copyright (C) 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 . + +#![cfg(test)] + +use crate::{EquivocationDetectionPipeline, HeaderFinalityInfo, SourceClient, TargetClient}; +use async_trait::async_trait; +use bp_header_chain::{FinalityProof, FindEquivocations}; +use finality_relay::{FinalityPipeline, SourceClientBase}; +use futures::{Stream, StreamExt}; +use relay_utils::{ + relay_loop::Client as RelayClient, HeaderId, MaybeConnectionError, TrackedTransactionStatus, + TransactionTracker, +}; +use std::{ + collections::HashMap, + pin::Pin, + sync::{Arc, Mutex}, + time::Duration, +}; + +pub type TestSourceHashAndNumber = u64; +pub type TestTargetNumber = u64; +pub type TestEquivocationProof = &'static str; + +pub const TEST_RECONNECT_DELAY: Duration = Duration::from_secs(0); + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TestFinalityProof(pub TestSourceHashAndNumber, pub Vec); + +impl FinalityProof for TestFinalityProof { + fn target_header_hash(&self) -> TestSourceHashAndNumber { + self.0 + } + + fn target_header_number(&self) -> TestSourceHashAndNumber { + self.0 + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct TestEquivocationDetectionPipeline; + +impl FinalityPipeline for TestEquivocationDetectionPipeline { + const SOURCE_NAME: &'static str = "TestSource"; + const TARGET_NAME: &'static str = "TestTarget"; + + type Hash = TestSourceHashAndNumber; + type Number = TestSourceHashAndNumber; + type FinalityProof = TestFinalityProof; +} + +#[derive(Clone, Debug, PartialEq)] +pub struct TestFinalityVerificationContext { + pub check_equivocations: bool, +} + +pub struct TestEquivocationsFinder; + +impl FindEquivocations + for TestEquivocationsFinder +{ + type Error = (); + + fn find_equivocations( + verification_context: &TestFinalityVerificationContext, + synced_proof: &TestFinalityProof, + source_proofs: &[TestFinalityProof], + ) -> Result, Self::Error> { + if verification_context.check_equivocations { + // Get the equivocations from the source proofs, in order to make sure + // that they are correctly provided. + if let Some(proof) = source_proofs.iter().find(|proof| proof.0 == synced_proof.0) { + return Ok(proof.1.clone()) + } + } + + Ok(vec![]) + } +} + +impl EquivocationDetectionPipeline for TestEquivocationDetectionPipeline { + type TargetNumber = TestTargetNumber; + type FinalityVerificationContext = TestFinalityVerificationContext; + type EquivocationProof = TestEquivocationProof; + type EquivocationsFinder = TestEquivocationsFinder; +} + +#[derive(Debug, Clone)] +pub enum TestClientError { + Connection, + NonConnection, +} + +impl MaybeConnectionError for TestClientError { + fn is_connection_error(&self) -> bool { + match self { + TestClientError::Connection => true, + TestClientError::NonConnection => false, + } + } +} + +#[derive(Clone)] +pub struct TestSourceClient { + pub num_reconnects: u32, + pub finality_proofs: Arc>>, + pub reported_equivocations: + Arc>>>, +} + +impl Default for TestSourceClient { + fn default() -> Self { + Self { + num_reconnects: 0, + finality_proofs: Arc::new(Mutex::new(vec![])), + reported_equivocations: Arc::new(Mutex::new(Default::default())), + } + } +} + +#[async_trait] +impl RelayClient for TestSourceClient { + type Error = TestClientError; + + async fn reconnect(&mut self) -> Result<(), Self::Error> { + self.num_reconnects += 1; + + Ok(()) + } +} + +#[async_trait] +impl SourceClientBase for TestSourceClient { + type FinalityProofsStream = Pin + 'static + Send>>; + + async fn finality_proofs(&self) -> Result { + let finality_proofs = std::mem::take(&mut *self.finality_proofs.lock().unwrap()); + Ok(futures::stream::iter(finality_proofs).boxed()) + } +} + +#[derive(Clone, Debug)] +pub struct TestTransactionTracker( + pub TrackedTransactionStatus>, +); + +impl Default for TestTransactionTracker { + fn default() -> TestTransactionTracker { + TestTransactionTracker(TrackedTransactionStatus::Finalized(Default::default())) + } +} + +#[async_trait] +impl TransactionTracker for TestTransactionTracker { + type HeaderId = HeaderId; + + async fn wait( + self, + ) -> TrackedTransactionStatus> { + self.0 + } +} + +#[async_trait] +impl SourceClient for TestSourceClient { + type TransactionTracker = TestTransactionTracker; + + async fn report_equivocation( + &self, + at: TestSourceHashAndNumber, + equivocation: TestEquivocationProof, + ) -> Result { + self.reported_equivocations + .lock() + .unwrap() + .entry(at) + .or_default() + .push(equivocation); + + Ok(TestTransactionTracker::default()) + } +} + +#[derive(Clone)] +pub struct TestTargetClient { + pub num_reconnects: u32, + pub best_finalized_header_number: + Arc Result + Send + Sync>, + pub best_synced_header_hash: + HashMap, TestClientError>>, + pub finality_verification_context: + HashMap>, + pub synced_headers_finality_info: HashMap< + TestTargetNumber, + Result>, TestClientError>, + >, +} + +impl Default for TestTargetClient { + fn default() -> Self { + Self { + num_reconnects: 0, + best_finalized_header_number: Arc::new(|| Ok(0)), + best_synced_header_hash: Default::default(), + finality_verification_context: Default::default(), + synced_headers_finality_info: Default::default(), + } + } +} + +#[async_trait] +impl RelayClient for TestTargetClient { + type Error = TestClientError; + + async fn reconnect(&mut self) -> Result<(), Self::Error> { + self.num_reconnects += 1; + + Ok(()) + } +} + +#[async_trait] +impl TargetClient for TestTargetClient { + async fn best_finalized_header_number(&self) -> Result { + (self.best_finalized_header_number)() + } + + async fn best_synced_header_hash( + &self, + at: TestTargetNumber, + ) -> Result, Self::Error> { + self.best_synced_header_hash + .get(&at) + .unwrap_or(&Err(TestClientError::NonConnection)) + .clone() + } + + async fn finality_verification_context( + &self, + at: TestTargetNumber, + ) -> Result { + self.finality_verification_context + .get(&at) + .unwrap_or(&Err(TestClientError::NonConnection)) + .clone() + } + + async fn synced_headers_finality_info( + &self, + at: TestTargetNumber, + ) -> Result>, Self::Error> { + self.synced_headers_finality_info + .get(&at) + .unwrap_or(&Err(TestClientError::NonConnection)) + .clone() + } +} + +pub fn new_header_finality_info( + source_hdr: TestSourceHashAndNumber, + check_following_equivocations: Option, +) -> HeaderFinalityInfo { + HeaderFinalityInfo:: { + finality_proof: TestFinalityProof(source_hdr, vec![]), + new_verification_context: check_following_equivocations.map( + |check_following_equivocations| TestFinalityVerificationContext { + check_equivocations: check_following_equivocations, + }, + ), + } +} diff --git a/relays/equivocation/src/reporter.rs b/relays/equivocation/src/reporter.rs index 27b4d71beb01b..9c4642383d164 100644 --- a/relays/equivocation/src/reporter.rs +++ b/relays/equivocation/src/reporter.rs @@ -25,11 +25,11 @@ use std::{ task::{Context, Poll}, }; -pub struct EquivocationsReporter> { - pending_reports: Vec>, +pub struct EquivocationsReporter<'a, P: EquivocationDetectionPipeline, SC: SourceClient

> { + pending_reports: Vec>, } -impl> EquivocationsReporter { +impl<'a, P: EquivocationDetectionPipeline, SC: SourceClient

> EquivocationsReporter<'a, P, SC> { pub fn new() -> Self { Self { pending_reports: vec![] } } @@ -81,3 +81,49 @@ impl> EquivocationsReporte poll_fn(|cx| self.do_process_pending_reports(cx)).await } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use relay_utils::HeaderId; + use std::sync::Mutex; + + #[async_std::test] + async fn process_pending_reports_works() { + let polled_reports = Mutex::new(vec![]); + let finished_reports = Mutex::new(vec![]); + + let mut reporter = + EquivocationsReporter:: { + pending_reports: vec![ + Box::pin(async { + polled_reports.lock().unwrap().push(1); + finished_reports.lock().unwrap().push(1); + TrackedTransactionStatus::Finalized(HeaderId(1, 1)) + }), + Box::pin(async { + polled_reports.lock().unwrap().push(2); + finished_reports.lock().unwrap().push(2); + TrackedTransactionStatus::Finalized(HeaderId(2, 2)) + }), + Box::pin(async { + polled_reports.lock().unwrap().push(3); + std::future::pending::<()>().await; + finished_reports.lock().unwrap().push(3); + TrackedTransactionStatus::Finalized(HeaderId(3, 3)) + }), + Box::pin(async { + polled_reports.lock().unwrap().push(4); + finished_reports.lock().unwrap().push(4); + TrackedTransactionStatus::Finalized(HeaderId(4, 4)) + }), + ], + }; + + reporter.process_pending_reports().await; + assert_eq!(*polled_reports.lock().unwrap(), vec![1, 2, 3, 4]); + assert_eq!(*finished_reports.lock().unwrap(), vec![1, 2, 4]); + assert_eq!(reporter.pending_reports.len(), 1); + } +} diff --git a/relays/finality/src/finality_proofs.rs b/relays/finality/src/finality_proofs.rs index cd6d12938ce42..e78cf8d62790d 100644 --- a/relays/finality/src/finality_proofs.rs +++ b/relays/finality/src/finality_proofs.rs @@ -32,6 +32,10 @@ impl> FinalityProofsStream { Self { stream: None } } + pub fn from_stream(stream: SC::FinalityProofsStream) -> Self { + Self { stream: Some(Box::pin(stream)) } + } + fn next(&mut self) -> Option<::Item> { let stream = match &mut self.stream { Some(stream) => stream, @@ -131,12 +135,6 @@ mod tests { use super::*; use crate::mock::*; - impl> FinalityProofsStream { - fn from_stream(stream: SC::FinalityProofsStream) -> Self { - Self { stream: Some(Box::pin(stream)) } - } - } - #[test] fn finality_proofs_buf_fill_works() { // when stream is currently empty, nothing is changed diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs index afb2229fc4cf3..fb4515beeaaca 100644 --- a/relays/lib-substrate-relay/src/finality_base/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -50,7 +50,7 @@ pub trait Engine: Send { /// Type of finality proofs, used by consensus engine. type FinalityProof: FinalityProof, BlockNumberOf> + Decode + Encode; /// The context needed for verifying finality proofs. - type FinalityVerificationContext: Send; + type FinalityVerificationContext: Debug + Send; /// The type of the equivocation proof used by the consensus engine. type EquivocationProof: Clone + Debug + Send + Sync; /// The equivocations finder. diff --git a/relays/utils/src/lib.rs b/relays/utils/src/lib.rs index f23357bfed709..2776620be3594 100644 --- a/relays/utils/src/lib.rs +++ b/relays/utils/src/lib.rs @@ -142,8 +142,8 @@ pub trait TransactionTracker: Send { } /// Future associated with `TransactionTracker`, monitoring the transaction status. -pub type TrackedTransactionFuture = - BoxFuture<'static, TrackedTransactionStatus<::HeaderId>>; +pub type TrackedTransactionFuture<'a, T> = + BoxFuture<'a, TrackedTransactionStatus<::HeaderId>>; /// Stringified error that may be either connection-related or not. #[derive(Error, Debug)] From ef3ef4563bfcfe1a2a28ef320b819afd2c540220 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 19 Sep 2023 15:02:41 +0300 Subject: [PATCH 1113/1210] Merge bulletin chain changes into polkadot staging (#2574) * polkadot-staging for v1.0.0 * Add polkadot bulletin chain primitives (#2542) * add polkadot bulletin chain primitives * also impl ChainWithMessages * clippy * instead of requiring sp_std::vec::Vec import when using runtime API generation macro, let's use full type path directly in macro (#2551) * Polkadot Bulletin Chain client (#2552) * relay-polkadot-bulletin-client * generate Polkadot Bulletin Chain Runtime * Add relays that will be used in Polkadot Bulletin <> Polkadot.BH bridge (#2556) * added Polkadot.BH <> Polkadot Bulletin chain relays * uncommented ED stuff * complex PolkadotBulletin <> Polkadot.BH relay * removed TODO * spelling * prepare refund extension infra to add refund extension for messages from standalone chain (#2558) * prepare refund extension infra to add refund extension for messages from standalone chain * spelling * apply adapter to fix compilation * clippy * added POLKADOT_BULLETIN_CHAIN_ID constant * RefundBridgedGrandpaMessages to refund transaction costs for messages coming to/from bridged standalone/relay chain (#2566) * RefundBridgedGrandpaMessages to refund transaction costs for messages coming to/from bridged standalone/relay chain * clippy * fix compilation * fix codec dependency (#2567) * Support message relay limits override (#2570) * support message relay limits overrides for bridges * spelling * export EXTRA_STORAGE_PROOF_SIZE for Polkadot Bulletin (#2572) --- bin/millau/runtime/src/lib.rs | 20 +- .../src/refund_relayer_extension.rs | 905 +++++++--- primitives/chain-bridge-hub-kusama/src/lib.rs | 1 - .../chain-bridge-hub-polkadot/src/lib.rs | 1 - primitives/chain-bridge-hub-rococo/src/lib.rs | 2 +- primitives/chain-bridge-hub-wococo/src/lib.rs | 1 - primitives/chain-kusama/src/lib.rs | 1 - primitives/chain-millau/src/lib.rs | 4 +- primitives/chain-polkadot-bulletin/Cargo.toml | 41 + primitives/chain-polkadot-bulletin/src/lib.rs | 215 +++ primitives/chain-polkadot/src/lib.rs | 1 - primitives/chain-rialto-parachain/src/lib.rs | 5 +- primitives/chain-rialto/src/lib.rs | 5 +- primitives/chain-rococo/src/lib.rs | 1 - primitives/chain-wococo/src/lib.rs | 1 - primitives/runtime/src/chain.rs | 16 +- primitives/runtime/src/lib.rs | 3 + relays/bin-substrate/Cargo.toml | 2 + relays/bin-substrate/src/bridges/mod.rs | 1 + ..._polkadot_messages_to_polkadot_bulletin.rs | 65 + .../src/bridges/polkadot_bulletin/mod.rs | 23 + ...bulletin_headers_to_bridge_hub_polkadot.rs | 101 ++ ...ulletin_messages_to_bridge_hub_polkadot.rs | 65 + .../polkadot_headers_to_polkadot_bulletin.rs | 96 ++ ...olkadot_parachains_to_polkadot_bulletin.rs | 92 + relays/bin-substrate/src/chains/mod.rs | 1 + .../src/chains/polkadot_bulletin.rs | 26 + relays/bin-substrate/src/cli/bridge.rs | 15 +- relays/bin-substrate/src/cli/init_bridge.rs | 41 + relays/bin-substrate/src/cli/relay_headers.rs | 12 + .../src/cli/relay_headers_and_messages/mod.rs | 55 +- .../bin-substrate/src/cli/relay_messages.rs | 11 + .../bin-substrate/src/cli/relay_parachains.rs | 5 + relays/bin-substrate/src/cli/send_message.rs | 14 +- relays/client-bridge-hub-polkadot/Cargo.toml | 3 +- .../src/runtime_wrapper.rs | 22 +- relays/client-polkadot-bulletin/Cargo.toml | 30 + .../src/codegen_runtime.rs | 1480 +++++++++++++++++ relays/client-polkadot-bulletin/src/lib.rs | 158 ++ relays/client-substrate/src/guard.rs | 8 +- .../lib-substrate-relay/src/messages_lane.rs | 37 +- 41 files changed, 3288 insertions(+), 298 deletions(-) create mode 100644 primitives/chain-polkadot-bulletin/Cargo.toml create mode 100644 primitives/chain-polkadot-bulletin/src/lib.rs create mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs create mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs create mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs create mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs create mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs create mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs create mode 100644 relays/bin-substrate/src/chains/polkadot_bulletin.rs create mode 100644 relays/client-polkadot-bulletin/Cargo.toml create mode 100644 relays/client-polkadot-bulletin/src/codegen_runtime.rs create mode 100644 relays/client-polkadot-bulletin/src/lib.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 4fd9a098fc044..9abe5ce69c096 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -88,8 +88,8 @@ pub use pallet_xcm::Call as XcmCall; use bridge_runtime_common::{ generate_bridge_reject_obsolete_headers_and_messages, refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane, - RefundableParachain, + ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, + RefundableMessagesLane, RefundableParachain, }, }; #[cfg(any(feature = "std", test))] @@ -625,13 +625,15 @@ generate_bridge_reject_obsolete_headers_and_messages! { bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); /// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. pub type PriorityBoostPerMessage = ConstU64<324_316_715>; -pub type BridgeRefundRialtoParachainMessages = RefundBridgedParachainMessages< - Runtime, - RefundableParachain, - RefundableMessagesLane, - ActualFeeRefund, - PriorityBoostPerMessage, - StrBridgeRefundRialtoPara2000Lane0Msgs, +pub type BridgeRefundRialtoParachainMessages = RefundSignedExtensionAdapter< + RefundBridgedParachainMessages< + Runtime, + RefundableParachain, + RefundableMessagesLane, + ActualFeeRefund, + PriorityBoostPerMessage, + StrBridgeRefundRialtoPara2000Lane0Msgs, + >, >; /// The address format for describing accounts. diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index f0c2cbf44509b..55a4d17036e22 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -24,8 +24,8 @@ use crate::messages_call_ext::{ }; use bp_messages::{LaneId, MessageNonce}; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; -use bp_runtime::{Parachain, ParachainIdOf, RangeInclusiveExt, StaticStrProvider}; -use codec::{Decode, Encode}; +use bp_runtime::{Chain, Parachain, ParachainIdOf, RangeInclusiveExt, StaticStrProvider}; +use codec::{Codec, Decode, Encode}; use frame_support::{ dispatch::{CallableCallFor, DispatchInfo, PostDispatchInfo}, traits::IsSubType, @@ -33,7 +33,8 @@ use frame_support::{ CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound, }; use pallet_bridge_grandpa::{ - CallSubType as GrandpaCallSubType, SubmitFinalityProofHelper, SubmitFinalityProofInfo, + CallSubType as GrandpaCallSubType, Config as GrandpaConfig, SubmitFinalityProofHelper, + SubmitFinalityProofInfo, }; use pallet_bridge_messages::Config as MessagesConfig; use pallet_bridge_parachains::{ @@ -96,7 +97,7 @@ where /// coming from this lane. pub trait RefundableMessagesLaneId { /// The instance of the bridge messages pallet. - type Instance; + type Instance: 'static; /// The messages lane id. type Id: Get; } @@ -106,6 +107,7 @@ pub struct RefundableMessagesLane(PhantomData<(Instance, Id)>); impl RefundableMessagesLaneId for RefundableMessagesLane where + Instance: 'static, Id: Get, { type Instance = Instance; @@ -165,7 +167,11 @@ pub enum CallInfo { SubmitParachainHeadsInfo, MessagesCallInfo, ), + /// Relay chain finality + message delivery/confirmation calls. + RelayFinalityAndMsgs(SubmitFinalityProofInfo, MessagesCallInfo), /// Parachain finality + message delivery/confirmation calls. + /// + /// This variant is used only when bridging with parachain. ParachainFinalityAndMsgs(SubmitParachainHeadsInfo, MessagesCallInfo), /// Standalone message delivery/confirmation call. Msgs(MessagesCallInfo), @@ -184,6 +190,7 @@ impl CallInfo { fn submit_finality_proof_info(&self) -> Option> { match *self { Self::AllFinalityAndMsgs(info, _, _) => Some(info), + Self::RelayFinalityAndMsgs(info, _) => Some(info), _ => None, } } @@ -201,6 +208,7 @@ impl CallInfo { fn messages_call_info(&self) -> &MessagesCallInfo { match self { Self::AllFinalityAndMsgs(_, _, info) => info, + Self::RelayFinalityAndMsgs(_, info) => info, Self::ParachainFinalityAndMsgs(_, info) => info, Self::Msgs(info) => info, } @@ -209,7 +217,7 @@ impl CallInfo { /// The actions on relayer account that need to be performed because of his actions. #[derive(RuntimeDebug, PartialEq)] -enum RelayerAccountAction { +pub enum RelayerAccountAction { /// Do nothing with relayer account. None, /// Reward the relayer. @@ -218,121 +226,60 @@ enum RelayerAccountAction { Slash(AccountId, RewardsAccountParams), } -/// Signed extension that refunds a relayer for new messages coming from a parachain. -/// -/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) -/// with message delivery transaction. Batch may deliver either both relay chain header and -/// parachain head, or just parachain head. Corresponding headers must be used in messages -/// proof verification. -/// -/// Extension does not refund transaction tip due to security reasons. -#[derive( - DefaultNoBound, - CloneNoBound, - Decode, - Encode, - EqNoBound, - PartialEqNoBound, - RuntimeDebugNoBound, - TypeInfo, -)] -#[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Priority, Id))] -pub struct RefundBridgedParachainMessages( - PhantomData<( - // runtime with `frame-utility`, `pallet-bridge-grandpa`, `pallet-bridge-parachains`, - // `pallet-bridge-messages` and `pallet-bridge-relayers` pallets deployed - Runtime, - // implementation of `RefundableParachainId` trait, which specifies the instance of - // the used `pallet-bridge-parachains` pallet and the bridged parachain id - Para, - // implementation of `RefundableMessagesLaneId` trait, which specifies the instance of - // the used `pallet-bridge-messages` pallet and the lane within this pallet - Msgs, - // implementation of the `RefundCalculator` trait, that is used to compute refund that - // we give to relayer for his transaction - Refund, - // getter for per-message `TransactionPriority` boost that we give to message - // delivery transactions - Priority, - // the runtime-unique identifier of this signed extension - Id, - )>, -); - -impl - RefundBridgedParachainMessages +/// Everything common among our refund signed extensions. +pub trait RefundSignedExtension: + 'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo where - Self: 'static + Send + Sync, - Runtime: UtilityConfig> - + BoundedBridgeGrandpaConfig - + ParachainsConfig - + MessagesConfig - + RelayersConfig, - Para: RefundableParachainId, - Msgs: RefundableMessagesLaneId, - Refund: RefundCalculator, - Priority: Get, - Id: StaticStrProvider, - CallOf: Dispatchable - + IsSubType, Runtime>> - + GrandpaCallSubType - + ParachainsCallSubType - + MessagesCallSubType, + >::BridgedChain: + Chain, { - fn expand_call<'a>(&self, call: &'a CallOf) -> Vec<&'a CallOf> { - match call.is_sub_type() { - Some(UtilityCall::::batch_all { ref calls }) if calls.len() <= 3 => - calls.iter().collect(), - Some(_) => vec![], - None => vec![call], - } - } - + /// This chain runtime. + type Runtime: UtilityConfig> + + GrandpaConfig + + MessagesConfig<::Instance> + + RelayersConfig; + /// Grandpa pallet reference. + type GrandpaInstance: 'static; + /// Messages pallet and lane reference. + type Msgs: RefundableMessagesLaneId; + /// Refund amount calculator. + type Refund: RefundCalculator::Reward>; + /// Priority boost calculator. + type Priority: Get; + /// Signed extension unique identifier. + type Id: StaticStrProvider; + + /// Unpack batch runtime call. + fn expand_call(call: &CallOf) -> Vec<&CallOf>; + + /// Given runtime call, check if it has supported format. Additionally, check if any of + /// (optionally batched) calls are obsolete and we shall reject the transaction. fn parse_and_check_for_obsolete_call( - &self, - call: &CallOf, - ) -> Result, TransactionValidityError> { - let calls = self.expand_call(call); - let total_calls = calls.len(); - let mut calls = calls.into_iter().map(Self::check_obsolete_call).rev(); - - let msgs_call = calls.next().transpose()?.and_then(|c| c.call_info_for(Msgs::Id::get())); - let para_finality_call = calls - .next() - .transpose()? - .and_then(|c| c.submit_parachain_heads_info_for(Para::Id::get())); - let relay_finality_call = - calls.next().transpose()?.and_then(|c| c.submit_finality_proof_info()); + call: &CallOf, + ) -> Result, TransactionValidityError>; - Ok(match (total_calls, relay_finality_call, para_finality_call, msgs_call) { - (3, Some(relay_finality_call), Some(para_finality_call), Some(msgs_call)) => Some( - CallInfo::AllFinalityAndMsgs(relay_finality_call, para_finality_call, msgs_call), - ), - (2, None, Some(para_finality_call), Some(msgs_call)) => - Some(CallInfo::ParachainFinalityAndMsgs(para_finality_call, msgs_call)), - (1, None, None, Some(msgs_call)) => Some(CallInfo::Msgs(msgs_call)), - _ => None, - }) - } + /// Check if parsed call is already obsolete. + fn check_obsolete_parsed_call( + call: &CallOf, + ) -> Result<&CallOf, TransactionValidityError>; - fn check_obsolete_call( - call: &CallOf, - ) -> Result<&CallOf, TransactionValidityError> { - call.check_obsolete_submit_finality_proof()?; - call.check_obsolete_submit_parachain_heads()?; - call.check_obsolete_call()?; - Ok(call) - } + /// Called from post-dispatch and shall perform additional checks (apart from relay + /// chain finality and messages transaction finality) of given call result. + fn additional_call_result_check( + relayer: &AccountIdOf, + call_info: &CallInfo, + ) -> bool; /// Given post-dispatch information, analyze the outcome of relayer call and return /// actions that need to be performed on relayer account. fn analyze_call_result( - pre: Option>>, + pre: Option>>>, info: &DispatchInfo, post_info: &PostDispatchInfo, len: usize, result: &DispatchResult, - ) -> RelayerAccountAction, Runtime::Reward> { + ) -> RelayerAccountAction, ::Reward> + { let mut extra_weight = Weight::zero(); let mut extra_size = 0; @@ -344,15 +291,18 @@ where // now we know that the relayer either needs to be rewarded, or slashed // => let's prepare the correspondent account that pays reward/receives slashed amount - let reward_account_params = RewardsAccountParams::new( - Msgs::Id::get(), - Runtime::BridgedChainId::get(), - if call_info.is_receive_messages_proof_call() { - RewardsAccountOwner::ThisChain - } else { - RewardsAccountOwner::BridgedChain - }, - ); + let reward_account_params = + RewardsAccountParams::new( + ::Id::get(), + ::Instance, + >>::BridgedChainId::get(), + if call_info.is_receive_messages_proof_call() { + RewardsAccountOwner::ThisChain + } else { + RewardsAccountOwner::BridgedChain + }, + ); // prepare return value for the case if the call has failed or it has not caused // expected side effects (e.g. not all messages have been accepted) @@ -376,10 +326,9 @@ where if let Err(e) = result { log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?}: relayer {:?} has submitted invalid messages transaction: {:?}", - Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), + "{} via {:?}: relayer {:?} has submitted invalid messages transaction: {:?}", + Self::Id::STR, + ::Id::get(), relayer, e, ); @@ -388,19 +337,18 @@ where // check if relay chain state has been updated if let Some(finality_proof_info) = call_info.submit_finality_proof_info() { - if !SubmitFinalityProofHelper::::was_successful( + if !SubmitFinalityProofHelper::::was_successful( finality_proof_info.block_number, ) { // we only refund relayer if all calls have updated chain state log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?}: relayer {:?} has submitted invalid relay chain finality proof", - Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), + "{} via {:?}: relayer {:?} has submitted invalid relay chain finality proof", + Self::Id::STR, + ::Id::get(), relayer, ); - return slash_relayer_if_delivery_result; + return slash_relayer_if_delivery_result } // there's a conflict between how bridge GRANDPA pallet works and a `utility.batchAll` @@ -416,39 +364,25 @@ where extra_size = finality_proof_info.extra_size; } - // check if parachain state has been updated - if let Some(para_proof_info) = call_info.submit_parachain_heads_info() { - if !SubmitParachainHeadsHelper::::was_successful( - para_proof_info, - ) { - // we only refund relayer if all calls have updated chain state - log::trace!( - target: "runtime::bridge", - "{} from parachain {} via {:?}: relayer {:?} has submitted invalid parachain finality proof", - Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), - relayer, - ); - return slash_relayer_if_delivery_result - } - } - // Check if the `ReceiveMessagesProof` call delivered at least some of the messages that // it contained. If this happens, we consider the transaction "helpful" and refund it. let msgs_call_info = call_info.messages_call_info(); - if !MessagesCallHelper::::was_successful(msgs_call_info) { + if !MessagesCallHelper::::Instance>::was_successful(msgs_call_info) { log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?}: relayer {:?} has submitted invalid messages call", - Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), + "{} via {:?}: relayer {:?} has submitted invalid messages call", + Self::Id::STR, + ::Id::get(), relayer, ); return slash_relayer_if_delivery_result } + // do additional check + if !Self::additional_call_result_check(&relayer, &call_info) { + return slash_relayer_if_delivery_result + } + // regarding the tip - refund that happens here (at this side of the bridge) isn't the whole // relayer compensation. He'll receive some amount at the other side of the bridge. It shall // (in theory) cover the tip there. Otherwise, if we'll be compensating tip here, some @@ -464,14 +398,14 @@ where // let's also replace the weight of slashing relayer with the weight of rewarding relayer if call_info.is_receive_messages_proof_call() { post_info_weight = post_info_weight.saturating_sub( - ::WeightInfo::extra_weight_of_successful_receive_messages_proof_call(), + ::WeightInfo::extra_weight_of_successful_receive_messages_proof_call(), ); } // compute the relayer refund let mut post_info = *post_info; post_info.actual_weight = Some(post_info_weight); - let refund = Refund::compute_refund(info, &post_info, post_info_len, tip); + let refund = Self::Refund::compute_refund(info, &post_info, post_info_len, tip); // we can finally reward relayer RelayerAccountAction::Reward(relayer, reward_account_params, refund) @@ -497,7 +431,11 @@ where let bundled_messages = parsed_call.messages_call_info().bundled_messages().saturating_len(); // a quick check to avoid invalid high-priority transactions - if bundled_messages > Runtime::MaxUnconfirmedMessagesAtInboundLane::get() { + let max_unconfirmed_messages_in_confirmation_tx = ::Instance, + >>::MaxUnconfirmedMessagesAtInboundLane::get( + ); + if bundled_messages > max_unconfirmed_messages_in_confirmation_tx { return None } @@ -505,31 +443,37 @@ where } } -impl SignedExtension - for RefundBridgedParachainMessages +/// Adapter that allow implementing `sp_runtime::traits::SignedExtension` for any +/// `RefundSignedExtension`. +#[derive( + DefaultNoBound, + CloneNoBound, + Decode, + Encode, + EqNoBound, + PartialEqNoBound, + RuntimeDebugNoBound, + TypeInfo, +)] +pub struct RefundSignedExtensionAdapter(T) where - Self: 'static + Send + Sync, - Runtime: UtilityConfig> - + BoundedBridgeGrandpaConfig - + ParachainsConfig - + MessagesConfig - + RelayersConfig, - Para: RefundableParachainId, - Msgs: RefundableMessagesLaneId, - Refund: RefundCalculator, - Priority: Get, - Id: StaticStrProvider, - CallOf: Dispatchable - + IsSubType, Runtime>> - + GrandpaCallSubType - + ParachainsCallSubType - + MessagesCallSubType, + >::BridgedChain: + Chain; + +impl SignedExtension for RefundSignedExtensionAdapter +where + >::BridgedChain: + Chain, + CallOf: Dispatchable + + IsSubType, T::Runtime>> + + GrandpaCallSubType + + MessagesCallSubType::Instance>, { - const IDENTIFIER: &'static str = Id::STR; - type AccountId = Runtime::AccountId; - type Call = CallOf; + const IDENTIFIER: &'static str = T::Id::STR; + type AccountId = AccountIdOf; + type Call = CallOf; type AdditionalSigned = (); - type Pre = Option>; + type Pre = Option>>; fn additional_signed(&self) -> Result<(), TransactionValidityError> { Ok(()) @@ -547,34 +491,32 @@ where // we're not calling `validate` from `pre_dispatch` directly because of performance // reasons, so if you're adding some code that may fail here, please check if it needs // to be added to the `pre_dispatch` as well - let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + let parsed_call = T::parse_and_check_for_obsolete_call(call)?; // the following code just plays with transaction priority and never returns an error // we only boost priority of presumably correct message delivery transactions - let bundled_messages = match Self::bundled_messages_for_priority_boost(parsed_call.as_ref()) - { + let bundled_messages = match T::bundled_messages_for_priority_boost(parsed_call.as_ref()) { Some(bundled_messages) => bundled_messages, None => return Ok(Default::default()), }; // we only boost priority if relayer has staked required balance - if !RelayersPallet::::is_registration_active(who) { + if !RelayersPallet::::is_registration_active(who) { return Ok(Default::default()) } // compute priority boost let priority_boost = - crate::priority_calculator::compute_priority_boost::(bundled_messages); + crate::priority_calculator::compute_priority_boost::(bundled_messages); let valid_transaction = ValidTransactionBuilder::default().priority(priority_boost); log::trace!( target: "runtime::bridge", - "{} from parachain {} via {:?} has boosted priority of message delivery transaction \ + "{} via {:?} has boosted priority of message delivery transaction \ of relayer {:?}: {} messages -> {} priority", Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), + ::Id::get(), who, bundled_messages, priority_boost, @@ -591,54 +533,294 @@ where _len: usize, ) -> Result { // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) - let parsed_call = self.parse_and_check_for_obsolete_call(call)?; + let parsed_call = T::parse_and_check_for_obsolete_call(call)?; + + Ok(parsed_call.map(|call_info| { + log::trace!( + target: "runtime::bridge", + "{} via {:?} parsed bridge transaction in pre-dispatch: {:?}", + Self::IDENTIFIER, + ::Id::get(), + call_info, + ); + PreDispatchData { relayer: who.clone(), call_info } + })) + } + + fn post_dispatch( + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, + len: usize, + result: &DispatchResult, + ) -> Result<(), TransactionValidityError> { + let call_result = T::analyze_call_result(pre, info, post_info, len, result); + + match call_result { + RelayerAccountAction::None => (), + RelayerAccountAction::Reward(relayer, reward_account, reward) => { + RelayersPallet::::register_relayer_reward( + reward_account, + &relayer, + reward, + ); + + log::trace!( + target: "runtime::bridge", + "{} via {:?} has registered reward: {:?} for {:?}", + Self::IDENTIFIER, + ::Id::get(), + reward, + relayer, + ); + }, + RelayerAccountAction::Slash(relayer, slash_account) => + RelayersPallet::::slash_and_deregister(&relayer, slash_account), + } + + Ok(()) + } +} + +/// Signed extension that refunds a relayer for new messages coming from a parachain. +/// +/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) +/// with message delivery transaction. Batch may deliver either both relay chain header and +/// parachain head, or just parachain head. Corresponding headers must be used in messages +/// proof verification. +/// +/// Extension does not refund transaction tip due to security reasons. +#[derive( + DefaultNoBound, + CloneNoBound, + Decode, + Encode, + EqNoBound, + PartialEqNoBound, + RuntimeDebugNoBound, + TypeInfo, +)] +#[scale_info(skip_type_params(Runtime, Para, Msgs, Refund, Priority, Id))] +pub struct RefundBridgedParachainMessages( + PhantomData<( + // runtime with `frame-utility`, `pallet-bridge-grandpa`, `pallet-bridge-parachains`, + // `pallet-bridge-messages` and `pallet-bridge-relayers` pallets deployed + Runtime, + // implementation of `RefundableParachainId` trait, which specifies the instance of + // the used `pallet-bridge-parachains` pallet and the bridged parachain id + Para, + // implementation of `RefundableMessagesLaneId` trait, which specifies the instance of + // the used `pallet-bridge-messages` pallet and the lane within this pallet + Msgs, + // implementation of the `RefundCalculator` trait, that is used to compute refund that + // we give to relayer for his transaction + Refund, + // getter for per-message `TransactionPriority` boost that we give to message + // delivery transactions + Priority, + // the runtime-unique identifier of this signed extension + Id, + )>, +); + +impl RefundSignedExtension + for RefundBridgedParachainMessages +where + Self: 'static + Send + Sync, + Runtime: UtilityConfig> + + BoundedBridgeGrandpaConfig + + ParachainsConfig + + MessagesConfig + + RelayersConfig, + Para: RefundableParachainId, + Msgs: RefundableMessagesLaneId, + Refund: RefundCalculator, + Priority: Get, + Id: StaticStrProvider, + CallOf: Dispatchable + + IsSubType, Runtime>> + + GrandpaCallSubType + + ParachainsCallSubType + + MessagesCallSubType, +{ + type Runtime = Runtime; + type GrandpaInstance = Runtime::BridgesGrandpaPalletInstance; + type Msgs = Msgs; + type Refund = Refund; + type Priority = Priority; + type Id = Id; + + fn expand_call(call: &CallOf) -> Vec<&CallOf> { + match call.is_sub_type() { + Some(UtilityCall::::batch_all { ref calls }) if calls.len() <= 3 => + calls.iter().collect(), + Some(_) => vec![], + None => vec![call], + } + } + + fn parse_and_check_for_obsolete_call( + call: &CallOf, + ) -> Result, TransactionValidityError> { + let calls = Self::expand_call(call); + let total_calls = calls.len(); + let mut calls = calls.into_iter().map(Self::check_obsolete_parsed_call).rev(); + + let msgs_call = calls.next().transpose()?.and_then(|c| c.call_info_for(Msgs::Id::get())); + let para_finality_call = calls + .next() + .transpose()? + .and_then(|c| c.submit_parachain_heads_info_for(Para::Id::get())); + let relay_finality_call = + calls.next().transpose()?.and_then(|c| c.submit_finality_proof_info()); + + Ok(match (total_calls, relay_finality_call, para_finality_call, msgs_call) { + (3, Some(relay_finality_call), Some(para_finality_call), Some(msgs_call)) => Some( + CallInfo::AllFinalityAndMsgs(relay_finality_call, para_finality_call, msgs_call), + ), + (2, None, Some(para_finality_call), Some(msgs_call)) => + Some(CallInfo::ParachainFinalityAndMsgs(para_finality_call, msgs_call)), + (1, None, None, Some(msgs_call)) => Some(CallInfo::Msgs(msgs_call)), + _ => None, + }) + } + + fn check_obsolete_parsed_call( + call: &CallOf, + ) -> Result<&CallOf, TransactionValidityError> { + call.check_obsolete_submit_finality_proof()?; + call.check_obsolete_submit_parachain_heads()?; + call.check_obsolete_call()?; + Ok(call) + } + + fn additional_call_result_check(relayer: &Runtime::AccountId, call_info: &CallInfo) -> bool { + // check if parachain state has been updated + if let Some(para_proof_info) = call_info.submit_parachain_heads_info() { + if !SubmitParachainHeadsHelper::::was_successful( + para_proof_info, + ) { + // we only refund relayer if all calls have updated chain state + log::trace!( + target: "runtime::bridge", + "{} from parachain {} via {:?}: relayer {:?} has submitted invalid parachain finality proof", + Id::STR, + Para::Id::get(), + Msgs::Id::get(), + relayer, + ); + return false + } + } + + true + } +} + +/// Signed extension that refunds a relayer for new messages coming from a standalone (GRANDPA) +/// chain. +/// +/// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) +/// with message delivery transaction. Batch may deliver either both relay chain header and +/// parachain head, or just parachain head. Corresponding headers must be used in messages +/// proof verification. +/// +/// Extension does not refund transaction tip due to security reasons. +#[derive( + DefaultNoBound, + CloneNoBound, + Decode, + Encode, + EqNoBound, + PartialEqNoBound, + RuntimeDebugNoBound, + TypeInfo, +)] +#[scale_info(skip_type_params(Runtime, GrandpaInstance, Msgs, Refund, Priority, Id))] +pub struct RefundBridgedGrandpaMessages( + PhantomData<( + // runtime with `frame-utility`, `pallet-bridge-grandpa`, + // `pallet-bridge-messages` and `pallet-bridge-relayers` pallets deployed + Runtime, + // bridge GRANDPA pallet instance, used to track bridged chain state + GrandpaInstance, + // implementation of `RefundableMessagesLaneId` trait, which specifies the instance of + // the used `pallet-bridge-messages` pallet and the lane within this pallet + Msgs, + // implementation of the `RefundCalculator` trait, that is used to compute refund that + // we give to relayer for his transaction + Refund, + // getter for per-message `TransactionPriority` boost that we give to message + // delivery transactions + Priority, + // the runtime-unique identifier of this signed extension + Id, + )>, +); + +impl RefundSignedExtension + for RefundBridgedGrandpaMessages +where + Self: 'static + Send + Sync, + Runtime: UtilityConfig> + + BoundedBridgeGrandpaConfig + + MessagesConfig + + RelayersConfig, + GrandpaInstance: 'static, + Msgs: RefundableMessagesLaneId, + Refund: RefundCalculator, + Priority: Get, + Id: StaticStrProvider, + CallOf: Dispatchable + + IsSubType, Runtime>> + + GrandpaCallSubType + + MessagesCallSubType, +{ + type Runtime = Runtime; + type GrandpaInstance = GrandpaInstance; + type Msgs = Msgs; + type Refund = Refund; + type Priority = Priority; + type Id = Id; - Ok(parsed_call.map(|call_info| { - log::trace!( - target: "runtime::bridge", - "{} from parachain {} via {:?} parsed bridge transaction in pre-dispatch: {:?}", - Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), - call_info, - ); - PreDispatchData { relayer: who.clone(), call_info } - })) + fn expand_call(call: &CallOf) -> Vec<&CallOf> { + match call.is_sub_type() { + Some(UtilityCall::::batch_all { ref calls }) if calls.len() <= 2 => + calls.iter().collect(), + Some(_) => vec![], + None => vec![call], + } } - fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, - len: usize, - result: &DispatchResult, - ) -> Result<(), TransactionValidityError> { - let call_result = Self::analyze_call_result(pre, info, post_info, len, result); + fn parse_and_check_for_obsolete_call( + call: &CallOf, + ) -> Result, TransactionValidityError> { + let calls = Self::expand_call(call); + let total_calls = calls.len(); + let mut calls = calls.into_iter().map(Self::check_obsolete_parsed_call).rev(); - match call_result { - RelayerAccountAction::None => (), - RelayerAccountAction::Reward(relayer, reward_account, reward) => { - RelayersPallet::::register_relayer_reward( - reward_account, - &relayer, - reward, - ); + let msgs_call = calls.next().transpose()?.and_then(|c| c.call_info_for(Msgs::Id::get())); + let relay_finality_call = + calls.next().transpose()?.and_then(|c| c.submit_finality_proof_info()); - log::trace!( - target: "runtime::bridge", - "{} from parachain {} via {:?} has registered reward: {:?} for {:?}", - Self::IDENTIFIER, - Para::Id::get(), - Msgs::Id::get(), - reward, - relayer, - ); - }, - RelayerAccountAction::Slash(relayer, slash_account) => - RelayersPallet::::slash_and_deregister(&relayer, slash_account), - } + Ok(match (total_calls, relay_finality_call, msgs_call) { + (2, Some(relay_finality_call), Some(msgs_call)) => + Some(CallInfo::RelayFinalityAndMsgs(relay_finality_call, msgs_call)), + (1, None, Some(msgs_call)) => Some(CallInfo::Msgs(msgs_call)), + _ => None, + }) + } - Ok(()) + fn check_obsolete_parsed_call( + call: &CallOf, + ) -> Result<&CallOf, TransactionValidityError> { + call.check_obsolete_submit_finality_proof()?; + call.check_obsolete_call()?; + Ok(call) + } + + fn additional_call_result_check(_relayer: &Runtime::AccountId, _call_info: &CallInfo) -> bool { + true } } @@ -690,7 +872,17 @@ mod tests { } bp_runtime::generate_static_str_provider!(TestExtension); - type TestExtension = RefundBridgedParachainMessages< + + type TestGrandpaExtensionProvider = RefundBridgedGrandpaMessages< + TestRuntime, + (), + RefundableMessagesLane<(), TestLaneId>, + ActualFeeRefund, + ConstU64<1>, + StrTestExtension, + >; + type TestGrandpaExtension = RefundSignedExtensionAdapter; + type TestExtensionProvider = RefundBridgedParachainMessages< TestRuntime, DefaultRefundableParachainId<(), TestParachain>, RefundableMessagesLane<(), TestLaneId>, @@ -698,6 +890,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; + type TestExtension = RefundSignedExtensionAdapter; fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance { let test_stake: ThisChainBalance = TestStake::get(); @@ -849,6 +1042,30 @@ mod tests { }) } + fn relay_finality_and_delivery_batch_call( + relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call(relay_header_number), + message_delivery_call(best_message), + ], + }) + } + + fn relay_finality_and_confirmation_batch_call( + relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call(relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_and_delivery_batch_call( relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, @@ -931,6 +1148,50 @@ mod tests { } } + fn relay_finality_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::RelayFinalityAndMsgs( + SubmitFinalityProofInfo { + block_number: 200, + extra_weight: Weight::zero(), + extra_size: 0, + }, + MessagesCallInfo::ReceiveMessagesProof(ReceiveMessagesProofInfo { + base: BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + bundled_range: 101..=200, + best_stored_nonce: 100, + }, + unrewarded_relayers: UnrewardedRelayerOccupation { + free_relayer_slots: MaxUnrewardedRelayerEntriesAtInboundLane::get(), + free_message_slots: MaxUnconfirmedMessagesAtInboundLane::get(), + }, + }), + ), + } + } + + fn relay_finality_confirmation_pre_dispatch_data() -> PreDispatchData { + PreDispatchData { + relayer: relayer_account_at_this_chain(), + call_info: CallInfo::RelayFinalityAndMsgs( + SubmitFinalityProofInfo { + block_number: 200, + extra_weight: Weight::zero(), + extra_size: 0, + }, + MessagesCallInfo::ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo( + BaseMessagesProofInfo { + lane_id: TEST_LANE_ID, + bundled_range: 101..=200, + best_stored_nonce: 100, + }, + )), + ), + } + } + fn parachain_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), @@ -1013,6 +1274,7 @@ mod tests { ) -> PreDispatchData { let msg_info = match pre_dispatch_data.call_info { CallInfo::AllFinalityAndMsgs(_, _, ref mut info) => info, + CallInfo::RelayFinalityAndMsgs(_, ref mut info) => info, CallInfo::ParachainFinalityAndMsgs(_, ref mut info) => info, CallInfo::Msgs(ref mut info) => info, }; @@ -1025,7 +1287,14 @@ mod tests { } fn run_validate(call: RuntimeCall) -> TransactionValidity { - let extension: TestExtension = RefundBridgedParachainMessages(PhantomData); + let extension: TestExtension = + RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + } + + fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity { + let extension: TestGrandpaExtension = + RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } @@ -1039,7 +1308,16 @@ mod tests { fn run_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { - let extension: TestExtension = RefundBridgedParachainMessages(PhantomData); + let extension: TestExtension = + RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + } + + fn run_grandpa_pre_dispatch( + call: RuntimeCall, + ) -> Result>, TransactionValidityError> { + let extension: TestGrandpaExtension = + RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } @@ -1674,7 +1952,7 @@ mod tests { pre_dispatch_data: PreDispatchData, dispatch_result: DispatchResult, ) -> RelayerAccountAction { - TestExtension::analyze_call_result( + TestExtensionProvider::analyze_call_result( Some(Some(pre_dispatch_data)), &dispatch_info(), &post_dispatch_info(), @@ -1737,4 +2015,175 @@ mod tests { ); }); } + + #[test] + fn grandpa_ext_only_parses_valid_batches() { + run_test(|| { + initialize_environment(100, 100, 100); + + // relay + parachain + message delivery calls batch is ignored + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &all_finality_and_delivery_batch_call(200, 200, 200) + ), + Ok(None), + ); + + // relay + parachain + message confirmation calls batch is ignored + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &all_finality_and_confirmation_batch_call(200, 200, 200) + ), + Ok(None), + ); + + // parachain + message delivery call batch is ignored + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + ¶chain_finality_and_delivery_batch_call(200, 200) + ), + Ok(None), + ); + + // parachain + message confirmation call batch is ignored + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + ¶chain_finality_and_confirmation_batch_call(200, 200) + ), + Ok(None), + ); + + // relay + message delivery call batch is accepted + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &relay_finality_and_delivery_batch_call(200, 200) + ), + Ok(Some(relay_finality_pre_dispatch_data().call_info)), + ); + + // relay + message confirmation call batch is accepted + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &relay_finality_and_confirmation_batch_call(200, 200) + ), + Ok(Some(relay_finality_confirmation_pre_dispatch_data().call_info)), + ); + + // message delivery call batch is accepted + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &message_delivery_call(200) + ), + Ok(Some(delivery_pre_dispatch_data().call_info)), + ); + + // message confirmation call batch is accepted + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &message_confirmation_call(200) + ), + Ok(Some(confirmation_pre_dispatch_data().call_info)), + ); + }); + } + + #[test] + fn grandpa_ext_rejects_batch_with_obsolete_relay_chain_header() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_grandpa_validate(relay_finality_and_delivery_batch_call(100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + }); + } + + #[test] + fn grandpa_ext_rejects_calls_with_obsolete_messages() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + assert_eq!( + run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_grandpa_pre_dispatch(message_delivery_call(100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + assert_eq!( + run_grandpa_pre_dispatch(message_confirmation_call(100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + + assert_eq!( + run_grandpa_validate(message_delivery_call(100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + assert_eq!( + run_grandpa_validate(message_confirmation_call(100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); + }); + } + + #[test] + fn grandpa_ext_accepts_calls_with_new_messages() { + run_test(|| { + initialize_environment(100, 100, 100); + + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 200)), + Ok(Some(relay_finality_pre_dispatch_data()),) + ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 200)), + Ok(Some(relay_finality_confirmation_pre_dispatch_data())), + ); + + assert_eq!( + run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 200)), + Ok(Default::default()), + ); + assert_eq!( + run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 200)), + Ok(Default::default()), + ); + + assert_eq!( + run_grandpa_pre_dispatch(message_delivery_call(200)), + Ok(Some(delivery_pre_dispatch_data())), + ); + assert_eq!( + run_grandpa_pre_dispatch(message_confirmation_call(200)), + Ok(Some(confirmation_pre_dispatch_data())), + ); + + assert_eq!(run_grandpa_validate(message_delivery_call(200)), Ok(Default::default()),); + assert_eq!( + run_grandpa_validate(message_confirmation_call(200)), + Ok(Default::default()), + ); + }); + } } diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs index 3a919648df47f..66e0dad05895c 100644 --- a/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -29,7 +29,6 @@ use frame_support::{ sp_runtime::{MultiAddress, MultiSigner}, }; use sp_runtime::RuntimeDebug; -use sp_std::prelude::Vec; /// BridgeHubKusama parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs index bf8d8e07c3a61..c3661c1adcada 100644 --- a/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -26,7 +26,6 @@ use bp_runtime::{ }; use frame_support::dispatch::DispatchClass; use sp_runtime::RuntimeDebug; -use sp_std::prelude::Vec; /// BridgeHubPolkadot parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index b726c62ac42b3..a50bda23ac8d3 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -26,7 +26,7 @@ use bp_runtime::{ }; use frame_support::dispatch::DispatchClass; use sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug}; -use sp_std::prelude::Vec; + /// BridgeHubRococo parachain. #[derive(RuntimeDebug)] pub struct BridgeHubRococo; diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 5e4758645d9ea..ce4600f5ff35d 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -26,7 +26,6 @@ use bp_runtime::{ }; use frame_support::dispatch::DispatchClass; use sp_runtime::RuntimeDebug; -use sp_std::prelude::Vec; /// BridgeHubWococo parachain. #[derive(RuntimeDebug)] diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 8c3fbd9c203e5..d5748aa132cea 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -23,7 +23,6 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::weights::Weight; -use sp_std::prelude::Vec; /// Kusama Chain pub struct Kusama; diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index ae14f7f362953..0c31287166661 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -22,9 +22,7 @@ mod millau_hash; use bp_beefy::ChainWithBeefy; use bp_header_chain::ChainWithGrandpa; -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; +use bp_messages::MessageNonce; use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml new file mode 100644 index 0000000000000..4ad1bb497c67e --- /dev/null +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "bp-polkadot-bulletin" +description = "Primitives of Polkadot Bulletin chain runtime." +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } + +# Bridge Dependencies + +bp-header-chain = { path = "../header-chain", default-features = false } +bp-messages = { path = "../messages", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-runtime = { path = "../runtime", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +[features] +default = ["std"] +std = [ + "bp-header-chain/std", + "bp-messages/std", + "bp-polkadot-core/std", + "bp-runtime/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/primitives/chain-polkadot-bulletin/src/lib.rs new file mode 100644 index 0000000000000..fcc6e90eb1b29 --- /dev/null +++ b/primitives/chain-polkadot-bulletin/src/lib.rs @@ -0,0 +1,215 @@ +// Copyright (C) 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 . + +//! Polkadot Bulletin Chain primitives. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +use bp_header_chain::ChainWithGrandpa; +use bp_messages::MessageNonce; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, + extensions::{ + CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, + CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema, + }, + Chain, TransactionEra, +}; +use codec::{Decode, Encode}; +use frame_support::{ + dispatch::DispatchClass, + parameter_types, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, +}; +use frame_system::limits; +use scale_info::TypeInfo; +use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidityError, Perbill}; + +// This chain reuses most of Polkadot primitives. +pub use bp_polkadot_core::{ + AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature, + SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE_IN_JUSTIFICATION, + EXTRA_STORAGE_PROOF_SIZE, MAX_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, +}; + +/// Maximal number of GRANDPA authorities at Polkadot Bulletin chain. +pub const MAX_AUTHORITIES_COUNT: u32 = 100; + +/// Name of the With-Polkadot Bulletin chain GRANDPA pallet instance that is deployed at bridged +/// chains. +pub const WITH_POLKADOT_BULLETIN_GRANDPA_PALLET_NAME: &str = "BridgePolkadotBulletinGrandpa"; +/// Name of the With-Polkadot Bulletin chain messages pallet instance that is deployed at bridged +/// chains. +pub const WITH_POLKADOT_BULLETIN_MESSAGES_PALLET_NAME: &str = "BridgePolkadotBulletinMessages"; + +// There are fewer system operations on this chain (e.g. staking, governance, etc.). Use a higher +// percentage of the block for data storage. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(90); + +// Re following constants - we are using the same values at Cumulus parachains. They are limited +// by the maximal transaction weight/size. Since block limits at Bulletin Chain are larger than +// at the Cumulus Bridgeg Hubs, we could reuse the same values. + +/// Maximal number of unrewarded relayer entries at inbound lane for Cumulus-based parachains. +pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; + +/// Maximal number of unconfirmed messages at inbound lane for Cumulus-based parachains. +pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; + +/// This signed extension is used to ensure that the chain transactions are signed by proper +pub type ValidateSigned = GenericSignedExtensionSchema<(), ()>; + +/// Signed extension schema, used by Polkadot Bulletin. +pub type SignedExtensionSchema = GenericSignedExtension<( + ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ), + ValidateSigned, +)>; + +/// Signed extension, used by Polkadot Bulletin. +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub struct SignedExtension(SignedExtensionSchema); + +impl sp_runtime::traits::SignedExtension for SignedExtension { + const IDENTIFIER: &'static str = "Not needed."; + type AccountId = (); + type Call = (); + type AdditionalSigned = + ::AdditionalSigned; + type Pre = (); + + fn additional_signed(&self) -> Result { + self.0.additional_signed() + } + + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } +} + +impl SignedExtension { + /// Create signed extension from its components. + pub fn from_params( + spec_version: u32, + transaction_version: u32, + era: TransactionEra, + genesis_hash: Hash, + nonce: Nonce, + ) -> Self { + Self(GenericSignedExtension::new( + ( + ( + (), // non-zero sender + (), // spec version + (), // tx version + (), // genesis + era.frame_era(), // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + ), + (), + ), + Some(( + ( + (), + spec_version, + transaction_version, + genesis_hash, + era.signed_payload(genesis_hash), + (), + (), + ), + (), + )), + )) + } + + /// Return transaction nonce. + pub fn nonce(&self) -> Nonce { + let common_payload = self.0.payload.0; + common_payload.5 .0 + } +} + +parameter_types! { + /// We allow for 2 seconds of compute with a 6 second average block time. + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::with_sensible_defaults( + Weight::from_parts(2u64 * WEIGHT_REF_TIME_PER_SECOND, u64::MAX), + NORMAL_DISPATCH_RATIO, + ); + // Note: Max transaction size is 8 MB. Set max block size to 10 MB to facilitate data storage. + // This is double the "normal" Relay Chain block length limit. + /// Maximal block length at Polkadot Bulletin chain. + pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio( + 10 * 1024 * 1024, + NORMAL_DISPATCH_RATIO, + ); +} + +/// Polkadot Bulletin Chain declaration. +pub struct PolkadotBulletin; + +impl Chain for PolkadotBulletin { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + // The Bulletin Chain is a permissioned blockchain without any balances. Our `Chain` trait + // requires balance type, which is then used by various bridge infrastructure code. However + // this code is optional and we are not planning to use it in our bridge. + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +impl ChainWithGrandpa for PolkadotBulletin { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_POLKADOT_BULLETIN_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} + +decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa); +decl_bridge_messages_runtime_apis!(polkadot_bulletin); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index d1d6f74543121..61c8ca927d807 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -23,7 +23,6 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, extensions::PrevalidateAttests, Chain}; use frame_support::weights::Weight; -use sp_std::prelude::Vec; /// Polkadot Chain pub struct Polkadot; diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs index c30372b5a0788..18655503edddf 100644 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ b/primitives/chain-rialto-parachain/src/lib.rs @@ -18,9 +18,7 @@ // RuntimeApi generated functions #![allow(clippy::too_many_arguments)] -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; +use bp_messages::MessageNonce; use bp_runtime::{decl_bridge_runtime_apis, Chain, Parachain}; use frame_support::{ dispatch::DispatchClass, @@ -32,7 +30,6 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, MultiSignature, MultiSigner, Perbill, RuntimeDebug, }; -use sp_std::vec::Vec; /// Identifier of RialtoParachain in the Rialto relay chain. /// diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index 34d7c8f747668..9d5215c10292a 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -19,9 +19,7 @@ #![allow(clippy::too_many_arguments)] use bp_header_chain::ChainWithGrandpa; -use bp_messages::{ - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, -}; +use bp_messages::MessageNonce; use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, @@ -33,7 +31,6 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentifyAccount, Verify}, MultiSignature, MultiSigner, Perbill, RuntimeDebug, }; -use sp_std::prelude::*; /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 1589d14ea5143..5436ad846468c 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -23,7 +23,6 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::{parameter_types, weights::Weight}; -use sp_std::prelude::Vec; /// Rococo Chain pub struct Rococo; diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index 5b5bde8269044..b1df65630beff 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -26,7 +26,6 @@ pub use bp_rococo::{ use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; use frame_support::weights::Weight; -use sp_std::prelude::Vec; /// Wococo Chain pub struct Wococo; diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 5caaebd42babc..e1809e145248f 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -311,7 +311,7 @@ macro_rules! decl_bridge_finality_runtime_apis { $( /// Returns the justifications accepted in the current block. fn []( - ) -> Vec<$justification_type>; + ) -> sp_std::vec::Vec<$justification_type>; )? } } @@ -360,10 +360,10 @@ macro_rules! decl_bridge_messages_runtime_apis { /// If some (or all) messages are missing from the storage, they'll also will /// be missing from the resulting vector. The vector is ordered by the nonce. fn message_details( - lane: LaneId, - begin: MessageNonce, - end: MessageNonce, - ) -> Vec; + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> sp_std::vec::Vec; } /// Inbound message lane API for messages sent by this chain. @@ -376,9 +376,9 @@ macro_rules! decl_bridge_messages_runtime_apis { pub trait [] { /// Return details of given inbound messages. fn message_details( - lane: LaneId, - messages: Vec<(MessagePayload, OutboundMessageDetails)>, - ) -> Vec; + lane: bp_messages::LaneId, + messages: sp_std::vec::Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> sp_std::vec::Vec; } } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index e5f1afb4161d6..16cd603fe3449 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -73,6 +73,9 @@ pub const MILLAU_CHAIN_ID: ChainId = *b"mlau"; /// Polkadot chain id. pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; +/// Polkadot Bulletin chain id. +pub const POLKADOT_BULLETIN_CHAIN_ID: ChainId = *b"pdbc"; + /// Kusama chain id. pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index c9d12a7029678..795d91326a157 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -26,6 +26,7 @@ bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-millau = { path = "../../primitives/chain-millau" } +bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rialto = { path = "../../primitives/chain-rialto" } bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } @@ -43,6 +44,7 @@ relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } relay-kusama-client = { path = "../client-kusama" } relay-polkadot-client = { path = "../client-polkadot" } +relay-polkadot-bulletin-client = { path = "../client-polkadot-bulletin" } relay-rococo-client = { path = "../client-rococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs index 62e69cc0e5fbd..53fe5e0c192d8 100644 --- a/relays/bin-substrate/src/bridges/mod.rs +++ b/relays/bin-substrate/src/bridges/mod.rs @@ -17,6 +17,7 @@ //! Declaration of all bridges that the relay is able to serve. pub mod kusama_polkadot; +pub mod polkadot_bulletin; pub mod rialto_millau; pub mod rialto_parachain_millau; pub mod rococo_wococo; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs new file mode 100644 index 0000000000000..614b42de4ed89 --- /dev/null +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs @@ -0,0 +1,65 @@ +// Copyright 2022 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 . + +//! BridgeHubPolkadot-to-PolkadotBulletin messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +use relay_polkadot_bulletin_client::PolkadotBulletin; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +/// BridgeHubPolkadot-to-PolkadotBulletin messages bridge. +pub struct BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge { + type Source = BridgeHubPolkadot; + type Target = PolkadotBulletin; +} + +impl MessagesCliBridge for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge { + type MessagesLane = BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane, + BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesProofCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotBridgeHubMessages, + relay_polkadot_bulletin_client::BridgePolkadotBridgeHubMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane, + BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinMessages, + relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinMessagesCall::receive_messages_delivery_proof +); + +/// BridgeHubPolkadot-to-PolkadotBulletin messages lane. +#[derive(Clone, Debug)] +pub struct BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane; + +impl SubstrateMessageLane for BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane { + type SourceChain = BridgeHubPolkadot; + type TargetChain = PolkadotBulletin; + + type ReceiveMessagesProofCallBuilder = + BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = (); +} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs new file mode 100644 index 0000000000000..d7c740f601abc --- /dev/null +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs @@ -0,0 +1,23 @@ +// 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 . + +//! Declaration of all bridges between Polkadot Bulletin Chain and Polkadot Bridge Hub. + +pub mod bridge_hub_polkadot_messages_to_polkadot_bulletin; +pub mod polkadot_bulletin_headers_to_bridge_hub_polkadot; +pub mod polkadot_bulletin_messages_to_bridge_hub_polkadot; +pub mod polkadot_headers_to_polkadot_bulletin; +pub mod polkadot_parachains_to_polkadot_bulletin; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs new file mode 100644 index 0000000000000..33f59feda3bae --- /dev/null +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs @@ -0,0 +1,101 @@ +// Copyright 2022 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 . + +//! PolkadotBulletin-to-BridgeHubPolkadot headers sync entrypoint. + +use crate::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, + TransactionParams, +}; + +/// Description of `PolkadotBulletin` -> `PolkadotBridgeHub` finalized headers bridge. +#[derive(Clone, Debug)] +pub struct PolkadotBulletinFinalityToBridgeHubPolkadot; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + PolkadotBulletinFinalityToBridgeHubPolkadot, + SubmitFinalityProofCallBuilder, + relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinGrandpa, + relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinGrandpaCall::submit_finality_proof +); + +substrate_relay_helper::generate_report_equivocation_call_builder!( + PolkadotBulletinFinalityToBridgeHubPolkadot, + ReportEquivocationCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::Grandpa, + relay_polkadot_bulletin_client::GrandpaCall::report_equivocation +); + +#[async_trait] +impl SubstrateFinalityPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { + type SourceChain = relay_polkadot_bulletin_client::PolkadotBulletin; + type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + + type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } +} + +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + +/// `PolkadotBulletin` to BridgeHub `Polkadot` bridge definition. +pub struct PolkadotBulletinToBridgeHubPolkadotCliBridge {} + +impl CliBridgeBase for PolkadotBulletinToBridgeHubPolkadotCliBridge { + type Source = relay_polkadot_bulletin_client::PolkadotBulletin; + type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +} + +impl RelayToRelayHeadersCliBridge for PolkadotBulletinToBridgeHubPolkadotCliBridge { + type Finality = PolkadotBulletinFinalityToBridgeHubPolkadot; +} + +impl RelayToRelayEquivocationDetectionCliBridge for PolkadotBulletinToBridgeHubPolkadotCliBridge { + type Equivocation = PolkadotBulletinFinalityToBridgeHubPolkadot; +} + +impl MessagesCliBridge for PolkadotBulletinToBridgeHubPolkadotCliBridge { + type MessagesLane = crate::bridges::polkadot_bulletin::polkadot_bulletin_messages_to_bridge_hub_polkadot::PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane; +} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs new file mode 100644 index 0000000000000..ddfbcea495f90 --- /dev/null +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs @@ -0,0 +1,65 @@ +// Copyright 2022 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 . + +//! PolkadotBulletin-to-BridgeHubPolkadot messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; +use relay_polkadot_bulletin_client::PolkadotBulletin; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +/// PolkadotBulletin-to-BridgeHubPolkadot messages bridge. +pub struct PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} + +impl CliBridgeBase for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge { + type Source = PolkadotBulletin; + type Target = BridgeHubPolkadot; +} + +impl MessagesCliBridge for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge { + type MessagesLane = PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane, + PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinMessages, + relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane, + PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotBridgeHubMessages, + relay_polkadot_bulletin_client::BridgePolkadotBridgeHubMessagesCall::receive_messages_delivery_proof +); + +/// PolkadotBulletin-to-BridgeHubPolkadot messages lane. +#[derive(Clone, Debug)] +pub struct PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane; + +impl SubstrateMessageLane for PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane { + type SourceChain = PolkadotBulletin; + type TargetChain = BridgeHubPolkadot; + + type ReceiveMessagesProofCallBuilder = + PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; +} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs new file mode 100644 index 0000000000000..7770fd1559444 --- /dev/null +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs @@ -0,0 +1,96 @@ +// Copyright 2022 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 . + +//! Polkadot-to-PolkadotBulletin headers sync entrypoint. + +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, + TransactionParams, +}; + +/// Description of Polkadot -> `PolkadotBulletin` finalized headers bridge. +#[derive(Clone, Debug)] +pub struct PolkadotFinalityToPolkadotBulletin; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + PolkadotFinalityToPolkadotBulletin, + SubmitFinalityProofCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotGrandpa, + relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall::submit_finality_proof +); + +substrate_relay_helper::generate_report_equivocation_call_builder!( + PolkadotFinalityToPolkadotBulletin, + ReportEquivocationCallBuilder, + relay_polkadot_client::RuntimeCall::Grandpa, + relay_polkadot_client::GrandpaCall::report_equivocation +); + +#[async_trait] +impl SubstrateFinalityPipeline for PolkadotFinalityToPolkadotBulletin { + type SourceChain = relay_polkadot_client::Polkadot; + type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; + + type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for PolkadotFinalityToPolkadotBulletin { + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } +} + +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for PolkadotFinalityToPolkadotBulletin { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + +/// `Polkadot` to BridgeHub `PolkadotBulletin` bridge definition. +pub struct PolkadotToPolkadotBulletinCliBridge {} + +impl CliBridgeBase for PolkadotToPolkadotBulletinCliBridge { + type Source = relay_polkadot_client::Polkadot; + type Target = relay_polkadot_bulletin_client::PolkadotBulletin; +} + +impl RelayToRelayHeadersCliBridge for PolkadotToPolkadotBulletinCliBridge { + type Finality = PolkadotFinalityToPolkadotBulletin; +} + +impl RelayToRelayEquivocationDetectionCliBridge for PolkadotToPolkadotBulletinCliBridge { + type Equivocation = PolkadotFinalityToPolkadotBulletin; +} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs new file mode 100644 index 0000000000000..674c84adb39c6 --- /dev/null +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs @@ -0,0 +1,92 @@ +// 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 . + +//! Polkadot-to-PolkadotBulletin parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; + +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use bp_runtime::Chain; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::{ + messages_lane::MessagesRelayLimits, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, +}; + +/// Polkadot-to-PolkadotBulletin parachain sync description. +#[derive(Clone, Debug)] +pub struct PolkadotToPolkadotBulletin; + +impl SubstrateParachainsPipeline for PolkadotToPolkadotBulletin { + type SourceParachain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + type SourceRelayChain = relay_polkadot_client::Polkadot; + type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; + + type SubmitParachainHeadsCallBuilder = PolkadotToPolkadotBulletinCallBuilder; +} + +pub struct PolkadotToPolkadotBulletinCallBuilder; +impl SubmitParachainHeadsCallBuilder + for PolkadotToPolkadotBulletinCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotParachains( + relay_polkadot_bulletin_client::BridgePolkadotParachainsCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + }, + ) + } +} + +/// Polkadot-to-PolkadotBulletin parachain sync description for the CLI. +pub struct PolkadotToPolkadotBulletinCliBridge {} + +impl ParachainToRelayHeadersCliBridge for PolkadotToPolkadotBulletinCliBridge { + type SourceRelay = relay_polkadot_client::Polkadot; + type ParachainFinality = PolkadotToPolkadotBulletin; + type RelayFinality = + crate::bridges::polkadot_bulletin::polkadot_headers_to_polkadot_bulletin::PolkadotFinalityToPolkadotBulletin; +} + +impl CliBridgeBase for PolkadotToPolkadotBulletinCliBridge { + type Source = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + type Target = relay_polkadot_bulletin_client::PolkadotBulletin; +} + +impl MessagesCliBridge for PolkadotToPolkadotBulletinCliBridge { + type MessagesLane = + crate::bridges::polkadot_bulletin::bridge_hub_polkadot_messages_to_polkadot_bulletin::BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane; + + fn maybe_messages_limits() -> Option { + // Polkadot Bulletin chain is missing the `TransactionPayment` runtime API (as well as the + // transaction payment pallet itself), so we can't estimate limits using runtime calls. + // Let's do it here. + // + // Folloiung constants are just safe **underestimations**. Normally, we are able to deliver + // and dispatch thousands of messages in the same transaction. + Some(MessagesRelayLimits { + max_messages_in_single_batch: 128, + max_messages_weight_in_single_batch: + bp_polkadot_bulletin::PolkadotBulletin::max_extrinsic_weight() / 20, + }) + } +} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index b1a91ed1e85cb..c9a55e9e900f0 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -19,6 +19,7 @@ mod kusama; mod millau; mod polkadot; +mod polkadot_bulletin; mod rialto; mod rialto_parachain; mod rococo; diff --git a/relays/bin-substrate/src/chains/polkadot_bulletin.rs b/relays/bin-substrate/src/chains/polkadot_bulletin.rs new file mode 100644 index 0000000000000..ee7edbd9f4231 --- /dev/null +++ b/relays/bin-substrate/src/chains/polkadot_bulletin.rs @@ -0,0 +1,26 @@ +// Copyright 2022 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 . + +//! Polkadot + Polkadot parachains specification for CLI. + +use crate::cli::CliChain; +use relay_polkadot_bulletin_client::PolkadotBulletin; +use relay_substrate_client::SimpleRuntimeVersion; + +impl CliChain for PolkadotBulletin { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 }); +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 6cbbdd0ebe50c..59015f07f247b 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -19,8 +19,10 @@ use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumbe use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; use strum::{EnumString, EnumVariantNames}; use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, - messages_lane::SubstrateMessageLane, parachains::SubstrateParachainsPipeline, + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + messages_lane::{MessagesRelayLimits, SubstrateMessageLane}, + parachains::SubstrateParachainsPipeline, }; #[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] @@ -35,6 +37,8 @@ pub enum FullBridge { BridgeHubWococoToBridgeHubRococo, BridgeHubKusamaToBridgeHubPolkadot, BridgeHubPolkadotToBridgeHubKusama, + PolkadotBulletinToBridgeHubPolkadot, + BridgeHubPolkadotToPolkadotBulletin, } /// Minimal bridge representation that can be used from the CLI. @@ -109,4 +113,11 @@ where pub trait MessagesCliBridge: CliBridgeBase { /// The Source -> Destination messages synchronization pipeline. type MessagesLane: SubstrateMessageLane; + + /// Optional messages delivery transaction limits that the messages relay is going + /// to use. If it returns `None`, limits are estimated using `TransactionPayment` API + /// at the target chain. + fn maybe_messages_limits() -> Option { + None + } } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 110d5e94f8b39..af938102e40d1 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -23,6 +23,10 @@ use crate::{ kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, }, + polkadot_bulletin::{ + polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, + polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, + }, rialto_millau::{ millau_headers_to_rialto::MillauToRialtoCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -72,6 +76,8 @@ pub enum InitBridgeName { WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, + PolkadotToPolkadotBulletin, + PolkadotBulletinToBridgeHubPolkadot, } #[async_trait] @@ -232,6 +238,37 @@ impl BridgeInitializer for PolkadotToBridgeHubKusamaCliBridge { } } +impl BridgeInitializer for PolkadotToPolkadotBulletinCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + type RuntimeCall = relay_polkadot_bulletin_client::RuntimeCall; + type BridgePolkadotGrandpaCall = relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall; + type SudoCall = relay_polkadot_bulletin_client::SudoCall; + + let initialize_call = + RuntimeCall::BridgePolkadotGrandpa(BridgePolkadotGrandpaCall::initialize { init_data }); + + RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(initialize_call) }) + } +} + +impl BridgeInitializer for PolkadotBulletinToBridgeHubPolkadotCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinGrandpa( + relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinGrandpaCall::initialize { + init_data, + }, + ) + } +} + impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { @@ -249,6 +286,10 @@ impl InitBridge { KusamaToBridgeHubPolkadotCliBridge::init_bridge(self), InitBridgeName::PolkadotToBridgeHubKusama => PolkadotToBridgeHubKusamaCliBridge::init_bridge(self), + InitBridgeName::PolkadotToPolkadotBulletin => + PolkadotToPolkadotBulletinCliBridge::init_bridge(self), + InitBridgeName::PolkadotBulletinToBridgeHubPolkadot => + PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index fd84782c07ce0..800e8587d8b25 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -23,6 +23,10 @@ use crate::bridges::{ kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, }, + polkadot_bulletin::{ + polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, + polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, + }, rialto_millau::{ millau_headers_to_rialto::MillauToRialtoCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -71,6 +75,8 @@ pub enum RelayHeadersBridge { WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, + PolkadotToPolkadotBulletin, + PolkadotBulletinToBridgeHubPolkadot, } #[async_trait] @@ -116,6 +122,8 @@ impl HeadersRelayer for RococoToBridgeHubWococoCliBridge {} impl HeadersRelayer for WococoToBridgeHubRococoCliBridge {} impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} +impl HeadersRelayer for PolkadotToPolkadotBulletinCliBridge {} +impl HeadersRelayer for PolkadotBulletinToBridgeHubPolkadotCliBridge {} impl RelayHeaders { /// Run the command. @@ -134,6 +142,10 @@ impl RelayHeaders { KusamaToBridgeHubPolkadotCliBridge::relay_headers(self), RelayHeadersBridge::PolkadotToBridgeHubKusama => PolkadotToBridgeHubKusamaCliBridge::relay_headers(self), + RelayHeadersBridge::PolkadotToPolkadotBulletin => + PolkadotToPolkadotBulletinCliBridge::relay_headers(self), + RelayHeadersBridge::PolkadotBulletinToBridgeHubPolkadot => + PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index cd2d39cdec28b..86f6ef9e3472c 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -44,6 +44,10 @@ use crate::{ kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, }, + polkadot_bulletin::{ + polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, + polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, + }, rialto_millau::{ millau_headers_to_rialto::MillauToRialtoCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -77,7 +81,9 @@ use relay_substrate_client::{ use relay_utils::metrics::MetricsParams; use sp_core::Pair; use substrate_relay_helper::{ - messages_lane::MessagesRelayParams, on_demand::OnDemandRelay, TaggedAccount, TransactionParams, + messages_lane::{MessagesRelayLimits, MessagesRelayParams}, + on_demand::OnDemandRelay, + TaggedAccount, TransactionParams, }; /// Parameters that have the same names across all bridges. @@ -176,6 +182,7 @@ where source_to_target_headers_relay: Arc>, target_to_source_headers_relay: Arc>, lane_id: LaneId, + maybe_limits: Option, ) -> MessagesRelayParams { MessagesRelayParams { source_client: self.source.client.clone(), @@ -185,6 +192,7 @@ where source_to_target_headers_relay: Some(source_to_target_headers_relay), target_to_source_headers_relay: Some(target_to_source_headers_relay), lane_id, + limits: maybe_limits, metrics_params: self.metrics_params.clone().disable(), } } @@ -202,6 +210,7 @@ declare_chain_cli_schema!(Kusama, kusama); declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); declare_chain_cli_schema!(Polkadot, polkadot); declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); +declare_chain_cli_schema!(PolkadotBulletin, polkadot_bulletin); // Means to override signers of different layer transactions. declare_chain_cli_schema!(MillauHeadersToRialto, millau_headers_to_rialto); declare_chain_cli_schema!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); @@ -227,11 +236,21 @@ declare_chain_cli_schema!( PolkadotParachainsToBridgeHubKusama, polkadot_parachains_to_bridge_hub_kusama ); +declare_chain_cli_schema!( + PolkadotBulletinHeadersToBridgeHubPolkadot, + polkadot_bulletin_headers_to_bridge_hub_polkadot +); +declare_chain_cli_schema!(PolkadotHeadersToPolkadotBulletin, polkadot_headers_to_polkadot_bulletin); +declare_chain_cli_schema!( + PolkadotParachainsToPolkadotBulletin, + polkadot_parachains_to_polkadot_bulletin +); // All supported bridges. declare_relay_to_relay_bridge_schema!(Millau, Rialto); declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWococo, Wococo); declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); +declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); /// Base portion of the bidirectional complex relay. /// @@ -370,6 +389,7 @@ where left_to_right_on_demand_headers.clone(), right_to_left_on_demand_headers.clone(), lane, + Self::L2R::maybe_messages_limits(), )) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); @@ -381,6 +401,7 @@ where right_to_left_on_demand_headers.clone(), left_to_right_on_demand_headers.clone(), lane, + Self::R2L::maybe_messages_limits(), )) .map_err(|e| anyhow::format_err!("{}", e)) .boxed(); @@ -500,6 +521,32 @@ impl Full2WayBridge for BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { } } +/// `PolkadotBulletin` <> `BridgeHubPolkadot` complex relay. +pub struct PolkadotBulletinBridgeHubPolkadotFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for PolkadotBulletinBridgeHubPolkadotFull2WayBridge { + type Base = RelayToParachainBridge; + type Left = relay_polkadot_bulletin_client::PolkadotBulletin; + type Right = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; + type L2R = PolkadotBulletinToBridgeHubPolkadotCliBridge; + type R2L = PolkadotToPolkadotBulletinCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { @@ -511,6 +558,8 @@ pub enum RelayHeadersAndMessages { BridgeHubRococoBridgeHubWococo(BridgeHubRococoBridgeHubWococoHeadersAndMessages), /// BridgeHubKusama <> BridgeHubPolkadot relay. BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), + /// `PolkadotBulletin` <> `BridgeHubPolkadot` relay. + PolkadotBulletinBridgeHubPolkadot(PolkadotBulletinBridgeHubPolkadotHeadersAndMessages), } impl RelayHeadersAndMessages { @@ -531,6 +580,10 @@ impl RelayHeadersAndMessages { BridgeHubKusamaBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? .run() .await, + RelayHeadersAndMessages::PolkadotBulletinBridgeHubPolkadot(params) => + PolkadotBulletinBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? + .run() + .await, } } } diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 1624524e4a5b1..b5ba275af6fa0 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -24,6 +24,10 @@ use crate::bridges::{ bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge, bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge, }, + polkadot_bulletin::{ + bridge_hub_polkadot_messages_to_polkadot_bulletin::BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge, + polkadot_bulletin_messages_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge, + }, rialto_millau::{ millau_headers_to_rialto::MillauToRialtoCliBridge, rialto_headers_to_millau::RialtoToMillauCliBridge, @@ -93,6 +97,7 @@ where source_to_target_headers_relay: None, target_to_source_headers_relay: None, lane_id: data.lane.into(), + limits: Self::maybe_messages_limits(), metrics_params: data.prometheus_params.into_metrics_params()?, }) .await @@ -108,6 +113,8 @@ impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} impl MessagesRelayer for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} +impl MessagesRelayer for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} +impl MessagesRelayer for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} impl RelayMessages { /// Run the command. @@ -127,6 +134,10 @@ impl RelayMessages { BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubPolkadotToBridgeHubKusama => BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self), + FullBridge::PolkadotBulletinToBridgeHubPolkadot => + PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubPolkadotToPolkadotBulletin => + BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 67daf01c8f4b2..3dc9daad1aab4 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -19,6 +19,7 @@ use crate::bridges::{ kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, }, + polkadot_bulletin::polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, rialto_parachain_millau::rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, rococo_wococo::{ rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, @@ -71,6 +72,7 @@ pub enum RelayParachainsBridge { WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, + PolkadotToPolkadotBulletin, } #[async_trait] @@ -120,6 +122,7 @@ impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} impl ParachainsRelayer for BridgeHubPolkadotToBridgeHubKusamaCliBridge {} +impl ParachainsRelayer for PolkadotToPolkadotBulletinCliBridge {} impl RelayParachains { /// Run the command. @@ -137,6 +140,8 @@ impl RelayParachains { BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self), RelayParachainsBridge::PolkadotToBridgeHubKusama => BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self), + RelayParachainsBridge::PolkadotToPolkadotBulletin => + PolkadotToPolkadotBulletinCliBridge::relay_parachains(self), } .await } diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs index 918643faadb69..02ef58b371948 100644 --- a/relays/bin-substrate/src/cli/send_message.rs +++ b/relays/bin-substrate/src/cli/send_message.rs @@ -109,18 +109,8 @@ impl SendMessage { MillauToRialtoParachainCliBridge::send_message(self), FullBridge::RialtoParachainToMillau => RialtoParachainToMillauCliBridge::send_message(self), - FullBridge::BridgeHubRococoToBridgeHubWococo => unimplemented!( - "Sending message from BridgeHubRococo to BridgeHubWococo is not supported" - ), - FullBridge::BridgeHubWococoToBridgeHubRococo => unimplemented!( - "Sending message from BridgeHubWococo to BridgeHubRococo is not supported" - ), - FullBridge::BridgeHubKusamaToBridgeHubPolkadot => unimplemented!( - "Sending message from BridgeHubKusama to BridgeHubPolkadot is not supported" - ), - FullBridge::BridgeHubPolkadotToBridgeHubKusama => unimplemented!( - "Sending message from BridgeHubPolkadot to BridgeHubKusama is not supported" - ), + // all our (soon to retire_ testnets are above, so if is fine to use `_` + _ => unimplemented!("Sending message from in {:?} is not supported", self.bridge,), } .await } diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index bf6d65b304d80..f071778446d84 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -17,7 +17,8 @@ bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-core= { path = "../../primitives/polkadot-core" } +bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-kusama = { path = "../../primitives/chain-kusama" } bp-runtime = { path = "../../primitives/runtime" } diff --git a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs index 924d3bbef07d6..ded177996df94 100644 --- a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs @@ -29,11 +29,18 @@ pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubPolkadot extrinsic. pub type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; -// The indirect pallet call used to sync `Kusama` GRANDPA finality to `BHPolkadot`. +/// The indirect pallet call used to sync `Kusama` GRANDPA finality to `BHPolkadot`. pub type BridgeKusamaGrandpaCall = BridgeGrandpaCallOf; -// The indirect pallet call used to sync `BridgeHubKusama` messages to `BridgeHubPolkadot`. +/// The indirect pallet call used to sync `BridgeHubKusama` messages to `BridgeHubPolkadot`. pub type BridgeKusamaMessagesCall = BridgeMessagesCallOf; +/// The indirect pallet call used to sync `PolkadotBulletin` GRANDPA finality to `BHPolkadot`. +pub type BridgePolkadotBulletinGrandpaCall = + BridgeGrandpaCallOf; +/// The indirect pallet call used to sync `PolkadotBulletin` messages to `BridgeHubPolkadot`. +pub type BridgePolkadotBulletinMessagesCall = + BridgeMessagesCallOf; + /// `BridgeHubPolkadot` Runtime `Call` enum. /// /// The enum represents a subset of possible `Call`s we can send to `BridgeHubPolkadot` chain. @@ -52,15 +59,22 @@ pub enum Call { #[codec(index = 40)] Utility(UtilityCall), - /// Kusama bridge pallet. + /// Kusama grandpa bridge pallet. #[codec(index = 51)] BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), - /// Kusama parachain bridge pallet. + /// Kusama parachains bridge pallet. #[codec(index = 52)] BridgeKusamaParachain(BridgeParachainCall), /// Kusama messages bridge pallet. #[codec(index = 53)] BridgeKusamaMessages(BridgeKusamaMessagesCall), + + /// Polkadot Bulletin grandpa bridge pallet. + #[codec(index = 55)] + BridgePolkadotBulletinGrandpa(BridgePolkadotBulletinGrandpaCall), + /// Polkadot Bulletin messages bridge pallet. + #[codec(index = 56)] + BridgePolkadotBulletinMessages(BridgePolkadotBulletinMessagesCall), } impl From> for Call { diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml new file mode 100644 index 0000000000000..bcff9d2f21220 --- /dev/null +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "relay-polkadot-bulletin-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +subxt = { version = "0.31.0", default-features = false, features = ["native"] } + +# Bridge dependencies + +bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } +bp-runtime = { path = "../../primitives/runtime" } +bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + +# Substrate Dependencies + +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-polkadot-bulletin/src/codegen_runtime.rs b/relays/client-polkadot-bulletin/src/codegen_runtime.rs new file mode 100644 index 0000000000000..37af5b0b98e0b --- /dev/null +++ b/relays/client-polkadot-bulletin/src/codegen_runtime.rs @@ -0,0 +1,1480 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url ws://127.0.0.1:9944 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod bp_header_chain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AuthoritySet { + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HeaderChainError { + #[codec(index = 0)] + UnknownHeader, + #[codec(index = 1)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderFinalityInfo<_0, _1> { + pub finality_proof: _0, + pub new_verification_context: ::core::option::Option<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredHeaderData<_0, _1> { + pub number: _0, + pub state_root: _1, + } + } + pub mod bp_messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DeliveredMessages { + pub begin: ::core::primitive::u64, + pub end: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundLaneData<_0> { + pub relayers: ::std::vec::Vec>, + pub last_confirmed_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LaneId(pub [::core::primitive::u8; 4usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageKey { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MessagesOperatingMode { + #[codec(index = 0)] + Basic(runtime_types::bp_runtime::BasicOperatingMode), + #[codec(index = 1)] + RejectingOutboundMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundLaneData { + pub oldest_unpruned_nonce: ::core::primitive::u64, + pub latest_received_nonce: ::core::primitive::u64, + pub latest_generated_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalResult<_0> { + #[codec(index = 0)] + Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), + #[codec(index = 1)] + InvalidNonce, + #[codec(index = 2)] + TooManyUnrewardedRelayers, + #[codec(index = 3)] + TooManyUnconfirmedMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceivedMessages<_0> { + pub lane: runtime_types::bp_messages::LaneId, + pub receive_results: ::std::vec::Vec<( + ::core::primitive::u64, + runtime_types::bp_messages::ReceivalResult<_0>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnrewardedRelayer<_0> { + pub relayer: _0, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VerificationError { + #[codec(index = 0)] + EmptyMessageProof, + #[codec(index = 1)] + HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 2)] + InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 3)] + InvalidMessageWeight, + #[codec(index = 4)] + MessagesCountMismatch, + #[codec(index = 5)] + MessageStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 6)] + MessageTooLarge, + #[codec(index = 7)] + OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 8)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 9)] + Other, + } + } + pub mod bp_parachains { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BestParaHeadHash { + pub at_relay_block_number: ::core::primitive::u32, + pub head_hash: ::subxt::utils::H256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo { + pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, + pub next_imported_hash_position: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); + } + pub mod bp_runtime { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageDispatchResult<_0> { + pub unspent_weight: ::sp_weights::Weight, + pub dispatch_level_result: _0, + } + } + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateNodesInProof, + #[codec(index = 1)] + UnusedNodesInTheProof, + #[codec(index = 2)] + StorageRootMismatch, + #[codec(index = 3)] + StorageValueUnavailable, + #[codec(index = 4)] + StorageValueEmpty, + #[codec(index = 5)] + StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderId<_0, _1>(pub _1, pub _0); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OwnedBridgeModuleError { + #[codec(index = 0)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StrippableError; + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commit<_0, _1, _2, _3> { + pub target_hash: _0, + pub target_number: _1, + pub precommits: ::std::vec::Vec< + runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Equivocation<_0, _1, _2> { + pub round_number: ::core::primitive::u64, + pub identity: _0, + pub first: (_1, _2), + pub second: (_1, _2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Prevote<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedPrecommit<_0, _1, _2, _3> { + pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, + pub signature: _2, + pub id: _3, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + } + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_babe { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + plan_config_change { + config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEquivocationProof, + #[codec(index = 1)] + InvalidKeyOwnershipProof, + #[codec(index = 2)] + DuplicateOffenceReport, + #[codec(index = 3)] + InvalidConfiguration, + } + } + } + pub mod pallet_bridge_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 1)] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 2)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidJustification, + #[codec(index = 1)] + InvalidAuthoritySet, + #[codec(index = 2)] + OldHeader, + #[codec(index = 3)] + UnsupportedScheduledChange, + #[codec(index = 4)] + NotInitialized, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooManyAuthoritiesInSet, + #[codec(index = 7)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u32, + hash: ::subxt::utils::H256, + grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< + ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + runtime_types::bp_header_chain::AuthoritySet, + >, + }, + } + } + pub mod storage_types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredAuthoritySet { + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + } + } + pub mod pallet_bridge_messages { + use super::runtime_types; + pub mod outbound_lane { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalConfirmationError { + #[codec(index = 0)] + FailedToConfirmFutureMessages, + #[codec(index = 1)] + EmptyUnrewardedRelayerEntry, + #[codec(index = 2)] + NonConsecutiveUnrewardedRelayerEntries, + #[codec(index = 3)] + TryingToConfirmMoreMessagesThanExpected, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 1)] + set_operating_mode { + operating_mode: runtime_types::bp_messages::MessagesOperatingMode, + }, + #[codec(index = 2)] + receive_messages_proof { + relayer_id_at_bridged_chain: ::sp_core::crypto::AccountId32, + proof: bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< + ::subxt::utils::H256, + >, + messages_count: ::core::primitive::u32, + dispatch_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + receive_messages_delivery_proof { + proof: bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< + ::subxt::utils::H256, + >, + relayers_state: ::bp_messages::UnrewardedRelayersState, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + MessageAccepted { + lane_id: runtime_types::bp_messages::LaneId, + nonce: ::core::primitive::u64, + }, + #[codec(index = 1)] + MessagesReceived( + ::std::vec::Vec>, + ), + #[codec(index = 2)] + MessagesDelivered { + lane_id: runtime_types::bp_messages::LaneId, + messages: runtime_types::bp_messages::DeliveredMessages, + }, + } + } + } + pub mod pallet_bridge_parachains { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_parachain_heads { + at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), + parachains: ::std::vec::Vec<( + ::bp_polkadot_core::parachains::ParaId, + ::subxt::utils::H256, + )>, + parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, + }, + #[codec(index = 1)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 2)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnknownRelayChainBlock, + #[codec(index = 1)] + InvalidRelayChainBlockNumber, + #[codec(index = 2)] + HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 3)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 1)] + MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 2)] + IncorrectParachainHeadHash { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + actual_parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + RejectedObsoleteParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 4)] + RejectedLargeParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + parachain_head_size: ::core::primitive::u32, + }, + #[codec(index = 5)] + UpdatedParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + } + } + } + pub mod pallet_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + note_stalled { + delay: ::core::primitive::u32, + best_finalized_block_number: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PauseFailed, + #[codec(index = 1)] + ResumeFailed, + #[codec(index = 2)] + ChangePending, + #[codec(index = 3)] + TooSoon, + #[codec(index = 4)] + InvalidKeyOwnershipProof, + #[codec(index = 5)] + InvalidEquivocationProof, + #[codec(index = 6)] + DuplicateOffenceReport, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewAuthorities { + authority_set: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + }, + #[codec(index = 1)] + Paused, + #[codec(index = 2)] + Resumed, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredPendingChange<_0> { + pub scheduled_at: _0, + pub delay: _0, + pub next_authorities: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub forced: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StoredState<_0> { + #[codec(index = 0)] + Live, + #[codec(index = 1)] + PendingPause { scheduled_at: _0, delay: _0 }, + #[codec(index = 2)] + Paused, + #[codec(index = 3)] + PendingResume { scheduled_at: _0, delay: _0 }, + } + } + pub mod pallet_im_online { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + heartbeat { + heartbeat: + runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, + signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidKey, + #[codec(index = 1)] + DuplicatedHeartbeat, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + HeartbeatReceived { + authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + }, + #[codec(index = 1)] + AllGood, + #[codec(index = 2)] + SomeOffline { + offline: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + ::sp_core::crypto::AccountId32, + )>, + }, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Heartbeat<_0> { + pub block_number: _0, + pub session_index: _0, + pub authority_index: _0, + pub validators_len: _0, + } + } + pub mod pallet_offences { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Offence { + kind: [::core::primitive::u8; 16usize], + timeslot: ::std::vec::Vec<::core::primitive::u8>, + }, + } + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::polkadot_bulletin_chain_runtime::opaque::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_sudo { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + sudo { + call: ::std::boxed::Box< + runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + sudo_unchecked_weight { + call: ::std::boxed::Box< + runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall, + >, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + set_key { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + sudo_as { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: ::std::boxed::Box< + runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + RequireSudo, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Sudid { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + KeyChanged { + old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 2)] + SudoAsDone { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_storage { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + store { data: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + renew { block: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + check_proof { + proof: runtime_types::sp_transaction_storage_proof::TransactionStorageProof, + }, + #[codec(index = 3)] + authorize_account { + who: ::sp_core::crypto::AccountId32, + transactions: ::core::primitive::u32, + bytes: ::core::primitive::u64, + }, + #[codec(index = 4)] + authorize_preimage { + hash: [::core::primitive::u8; 32usize], + max_size: ::core::primitive::u64, + }, + #[codec(index = 5)] + remove_expired_account_authorization { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + remove_expired_preimage_authorization { hash: [::core::primitive::u8; 32usize] }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + BadContext, + #[codec(index = 1)] + BadDataSize, + #[codec(index = 2)] + TooManyTransactions, + #[codec(index = 3)] + RenewedNotFound, + #[codec(index = 4)] + UnexpectedProof, + #[codec(index = 5)] + InvalidProof, + #[codec(index = 6)] + MissingStateData, + #[codec(index = 7)] + DoubleCheck, + #[codec(index = 8)] + AuthorizationNotFound, + #[codec(index = 9)] + AuthorizationNotExpired, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Stored { index: ::core::primitive::u32 }, + #[codec(index = 1)] + Renewed { index: ::core::primitive::u32 }, + #[codec(index = 2)] + ProofChecked, + #[codec(index = 3)] + AccountAuthorized { + who: ::sp_core::crypto::AccountId32, + transactions: ::core::primitive::u32, + bytes: ::core::primitive::u64, + }, + #[codec(index = 4)] + PreimageAuthorized { + hash: [::core::primitive::u8; 32usize], + max_size: ::core::primitive::u64, + }, + #[codec(index = 5)] + ExpiredAccountAuthorizationRemoved { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + ExpiredPreimageAuthorizationRemoved { hash: [::core::primitive::u8; 32usize] }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Authorization<_0> { + pub extent: runtime_types::pallet_transaction_storage::AuthorizationExtent, + pub expiration: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AuthorizationExtent { + pub transactions: ::core::primitive::u32, + pub bytes: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AuthorizationScope<_0> { + #[codec(index = 0)] + Account(_0), + #[codec(index = 1)] + Preimage([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct TransactionInfo { + pub chunk_root: ::subxt::utils::H256, + pub content_hash: ::subxt::utils::H256, + pub size: ::core::primitive::u32, + pub block_chunks: ::core::primitive::u32, + } + } + pub mod pallet_validator_set { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_validator { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + remove_validator { who: ::sp_core::crypto::AccountId32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Duplicate, + #[codec(index = 1)] + NotAValidator, + #[codec(index = 2)] + TooManyValidators, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ValidatorAdded(::sp_core::crypto::AccountId32), + #[codec(index = 1)] + ValidatorRemoved(::sp_core::crypto::AccountId32), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Validator<_0> { + pub min_set_keys_block: _0, + } + } + pub mod polkadot_bulletin_chain_runtime { + use super::runtime_types; + pub mod opaque { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub babe: runtime_types::sp_consensus_babe::app::Public, + pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, + pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + Babe(runtime_types::pallet_babe::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 6)] + ValidatorSet(runtime_types::pallet_validator_set::pallet::Call), + #[codec(index = 7)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 8)] + ImOnline(runtime_types::pallet_im_online::pallet::Call), + #[codec(index = 9)] + Grandpa(runtime_types::pallet_grandpa::pallet::Call), + #[codec(index = 10)] + Sudo(runtime_types::pallet_sudo::pallet::Call), + #[codec(index = 11)] + TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Call), + #[codec(index = 12)] + BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 13)] + BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 14)] + BridgePolkadotBridgeHubMessages( + runtime_types::pallet_bridge_messages::pallet::Call, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 4)] + Offences(runtime_types::pallet_offences::pallet::Event), + #[codec(index = 6)] + ValidatorSet(runtime_types::pallet_validator_set::pallet::Event), + #[codec(index = 7)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 8)] + ImOnline(runtime_types::pallet_im_online::pallet::Event), + #[codec(index = 9)] + Grandpa(runtime_types::pallet_grandpa::pallet::Event), + #[codec(index = 10)] + Sudo(runtime_types::pallet_sudo::pallet::Event), + #[codec(index = 11)] + TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Event), + #[codec(index = 12)] + BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 13)] + BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 14)] + BridgePolkadotBridgeHubMessages( + runtime_types::pallet_bridge_messages::pallet::Event, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidateSigned; + } + pub mod sp_arithmetic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_consensus_babe { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod digests { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NextConfigDescriptor { + #[codec(index = 1)] + V1 { + c: (::core::primitive::u64, ::core::primitive::u64), + allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PreDigest { + #[codec(index = 1)] + Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), + #[codec(index = 2)] + SecondaryPlain( + runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, + ), + #[codec(index = 3)] + SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PrimaryPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryPlainPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryVRFPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AllowedSlots { + #[codec(index = 0)] + PrimarySlots, + #[codec(index = 1)] + PrimaryAndSecondaryPlainSlots, + #[codec(index = 2)] + PrimaryAndSecondaryVRFSlots, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BabeEpochConfiguration { + pub c: (::core::primitive::u64, ::core::primitive::u64), + pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Equivocation<_0, _1> { + #[codec(index = 0)] + Prevote( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Prevote<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + #[codec(index = 1)] + Precommit( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Precommit<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EquivocationProof<_0, _1> { + pub offender: _1, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub first_header: _0, + pub second_header: _0, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + pub mod vrf { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VrfSignature { + pub output: [::core::primitive::u8; 32usize], + pub proof: [::core::primitive::u8; 64usize], + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, + ); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_staking { + use super::runtime_types; + pub mod offence { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OffenceDetails<_0, _1> { + pub offender: _1, + pub reporters: ::std::vec::Vec<_0>, + } + } + } + pub mod sp_transaction_storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct TransactionStorageProof { + pub chunk: ::std::vec::Vec<::core::primitive::u8>, + pub proof: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + } +} diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs new file mode 100644 index 0000000000000..09fb7863a8b1c --- /dev/null +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -0,0 +1,158 @@ +// 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 . + +//! Types used to connect to the Polkadot Bulletin chain. + +mod codegen_runtime; + +use bp_messages::MessageNonce; +use bp_polkadot_bulletin::POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; +use bp_runtime::ChainId; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, + Error as SubstrateError, SignParam, UnderlyingChainProvider, UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; +use sp_session::MembershipProof; +use std::time::Duration; + +pub use codegen_runtime::api::runtime_types; + +/// Call of the Polkadot Bulletin Chain runtime. +pub type RuntimeCall = runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall; +/// Call of the `Sudo` pallet. +pub type SudoCall = runtime_types::pallet_sudo::pallet::Call; +/// Call of the GRANDPA pallet. +pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; +/// Call of the with-PolkadotBridgeHub bridge GRANDPA pallet. +pub type BridgePolkadotGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +/// Call of the with-PolkadotBridgeHub bridge parachains pallet. +pub type BridgePolkadotParachainsCall = runtime_types::pallet_bridge_parachains::pallet::Call; +/// Call of the with-PolkadotBridgeHub bridge messages pallet. +pub type BridgePolkadotBridgeHubMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; + +/// Polkadot header id. +pub type HeaderId = + relay_utils::HeaderId; + +/// Polkadot header type used in headers sync. +pub type SyncHeader = relay_substrate_client::SyncHeader; + +/// The address format for describing accounts. +pub type Address = MultiAddress; + +/// Polkadot chain definition +#[derive(Debug, Clone, Copy)] +pub struct PolkadotBulletin; + +impl UnderlyingChainProvider for PolkadotBulletin { + type Chain = bp_polkadot_bulletin::PolkadotBulletin; +} + +impl Chain for PolkadotBulletin { + const ID: ChainId = *b"pbch"; + + const NAME: &'static str = "PolkadotBulletin"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_polkadot_bulletin::BEST_FINALIZED_POLKADOT_BULLETIN_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type SignedBlock = bp_polkadot_bulletin::SignedBlock; + type Call = RuntimeCall; +} + +impl ChainWithGrandpa for PolkadotBulletin { + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = MembershipProof; +} + +impl ChainWithMessages for PolkadotBulletin { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_polkadot_bulletin::WITH_POLKADOT_BULLETIN_MESSAGES_PALLET_NAME; + // this is not critical (some metrics will be missing from the storage), but probably it needs + // to be changed when we'll polish the bridge configuration + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot_bulletin::TO_POLKADOT_BULLETIN_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_polkadot_bulletin::FROM_POLKADOT_BULLETIN_MESSAGE_DETAILS_METHOD; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot_bulletin::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_polkadot_bulletin::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + +impl ChainWithBalances for PolkadotBulletin { + fn account_info_storage_key(_account_id: &Self::AccountId) -> StorageKey { + // no balances at this chain + StorageKey(vec![]) + } +} + +impl ChainWithTransactions for PolkadotBulletin { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = + bp_polkadot_bulletin::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_polkadot_bulletin::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(Self::SignedTransaction::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce())) + } +} diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index a4ed47424e818..545396b30b859 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -17,7 +17,7 @@ //! Pallet provides a set of guard functions that are running in background threads //! and are aborting process if some condition fails. -use crate::{error::Error, Chain, ChainWithBalances, Client}; +use crate::{error::Error, Chain, Client}; use async_trait::async_trait; use sp_version::RuntimeVersion; @@ -28,7 +28,7 @@ use std::{ /// Guards environment. #[async_trait] -pub trait Environment: Send + Sync + 'static { +pub trait Environment: Send + Sync + 'static { /// Error type. type Error: Display + Send + Sync + 'static; @@ -52,7 +52,7 @@ pub trait Environment: Send + Sync + 'static { } /// Abort when runtime spec version is different from specified. -pub fn abort_on_spec_version_change( +pub fn abort_on_spec_version_change( mut env: impl Environment, expected_spec_version: u32, ) { @@ -98,7 +98,7 @@ fn conditions_check_delay() -> Duration { } #[async_trait] -impl Environment for Client { +impl Environment for Client { type Error = Error; async fn runtime_version(&mut self) -> Result { diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index b86a2629b0751..413f3d2c51ef5 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -105,10 +105,21 @@ pub struct MessagesRelayParams { Option>>, /// Identifier of lane that needs to be served. pub lane_id: LaneId, + /// Messages relay limits. If not provided, the relay tries to determine it automatically, + /// using `TransactionPayment` pallet runtime API. + pub limits: Option, /// Metrics parameters. pub metrics_params: MetricsParams, } +/// Delivery transaction limits. +pub struct MessagesRelayLimits { + /// Maximal number of messages in the delivery transaction. + pub max_messages_in_single_batch: MessageNonce, + /// Maximal cumulative weight of messages in the delivery transaction. + pub max_messages_weight_in_single_batch: Weight, +} + /// Batch transaction that brings headers + and messages delivery/receiving confirmations to the /// source node. #[derive(Clone)] @@ -178,15 +189,18 @@ where let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3; // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using // weights from Rialto and then simply dividing it by x2. + let limits = match params.limits { + Some(limits) => limits, + None => + select_delivery_transaction_limits_rpc::

( + ¶ms, + P::TargetChain::max_extrinsic_weight(), + P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + ) + .await?, + }; let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - select_delivery_transaction_limits_rpc::

( - ¶ms, - P::TargetChain::max_extrinsic_weight(), - P::SourceChain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - ) - .await?; - let (max_messages_in_single_batch, max_messages_weight_in_single_batch) = - (max_messages_in_single_batch / 2, max_messages_weight_in_single_batch / 2); + (limits.max_messages_in_single_batch / 2, limits.max_messages_weight_in_single_batch / 2); let source_client = params.source_client; let target_client = params.target_client; @@ -457,7 +471,7 @@ async fn select_delivery_transaction_limits_rpc( params: &MessagesRelayParams

, max_extrinsic_weight: Weight, max_unconfirmed_messages_at_inbound_lane: MessageNonce, -) -> anyhow::Result<(MessageNonce, Weight)> +) -> anyhow::Result where AccountIdOf: From< as Pair>::Public>, { @@ -515,7 +529,10 @@ where "Relay shall be able to deliver messages with dispatch weight = max_extrinsic_weight / 2", ); - Ok((max_number_of_messages, weight_for_messages_dispatch)) + Ok(MessagesRelayLimits { + max_messages_in_single_batch: max_number_of_messages, + max_messages_weight_in_single_batch: weight_for_messages_dispatch, + }) } /// Returns dummy message delivery transaction with zero messages and `1kb` proof. From bfd5985e57bbf152c2acaae05374ec11d932bce7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 12:05:16 +0000 Subject: [PATCH 1114/1210] Bump clap from 4.4.3 to 4.4.4 Bumps [clap](https://github.com/clap-rs/clap) from 4.4.3 to 4.4.4. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.3...v4.4.4) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index c8c6cd3f75bdf..3c7ce1cea8093 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.3", features = ["derive"] } +clap = { version = "4.4.4", features = ["derive"] } futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.107" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index d2bc660cbc361..479d4dac9098f 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.4.3", features = ["derive"] } +clap = { version = "4.4.4", features = ["derive"] } log = '0.4.20' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index a8ad170d49d41..0cf695374a29d 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.3", features = ["derive"] } +clap = { version = "4.4.4", features = ["derive"] } serde_json = "1.0.107" # Bridge dependencies From 9f536e648b0164e7a1f9a8b920608563ccdb8335 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 28 Sep 2023 13:57:54 +0300 Subject: [PATCH 1115/1210] fiox overflow when computing priority boost (#2587) --- bin/runtime-common/src/priority_calculator.rs | 2 +- .../src/refund_relayer_extension.rs | 39 ++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs index 3d53f9da8c20e..fd10344812517 100644 --- a/bin/runtime-common/src/priority_calculator.rs +++ b/bin/runtime-common/src/priority_calculator.rs @@ -38,7 +38,7 @@ where PriorityBoostPerMessage: Get, { // we don't want any boost for transaction with single message => minus one - PriorityBoostPerMessage::get().saturating_mul(messages - 1) + PriorityBoostPerMessage::get().saturating_mul(messages.saturating_sub(1)) } #[cfg(not(feature = "integrity-test"))] diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 55a4d17036e22..876c069dc0f77 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -837,7 +837,10 @@ mod tests { }, mock::*, }; - use bp_messages::{InboundLaneData, MessageNonce, OutboundLaneData, UnrewardedRelayersState}; + use bp_messages::{ + DeliveredMessages, InboundLaneData, MessageNonce, OutboundLaneData, UnrewardedRelayer, + UnrewardedRelayersState, + }; use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; use bp_runtime::HeaderId; @@ -2186,4 +2189,38 @@ mod tests { ); }); } + + #[test] + fn does_not_panic_on_boosting_priority_of_empty_message_delivery_transaction() { + run_test(|| { + let best_delivered_message = MaxUnconfirmedMessagesAtInboundLane::get(); + initialize_environment(100, 100, best_delivered_message); + + // register relayer so it gets priority boost + BridgeRelayers::register(RuntimeOrigin::signed(relayer_account_at_this_chain()), 1000) + .unwrap(); + + // allow empty message delivery transactions + let lane_id = TestLaneId::get(); + let in_lane_data = InboundLaneData { + last_confirmed_nonce: 0, + relayers: vec![UnrewardedRelayer { + relayer: relayer_account_at_bridged_chain(), + messages: DeliveredMessages { begin: 1, end: best_delivered_message }, + }] + .into(), + }; + pallet_bridge_messages::InboundLanes::::insert(lane_id, in_lane_data); + + // now check that the priority of empty tx is the same as priority of 1-message tx + let priority_of_zero_messages_delivery = + run_validate(message_delivery_call(best_delivered_message)).unwrap().priority; + let priority_of_one_messages_delivery = + run_validate(message_delivery_call(best_delivered_message + 1)) + .unwrap() + .priority; + + assert_eq!(priority_of_zero_messages_delivery, priority_of_one_messages_delivery); + }); + } } From 22505d32fdfdcb2b9d7d20caa0400ee86d6b9f72 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 28 Sep 2023 14:36:10 +0300 Subject: [PATCH 1116/1210] Backport changes from polkadot-sdk (#2588) * backport https://github.com/paritytech/polkadot-sdk/pull/1543 * another backport --- primitives/chain-bridge-hub-cumulus/src/lib.rs | 2 +- primitives/test-utils/Cargo.toml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index c1dbc6db36f64..cd281324ee55f 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -52,7 +52,7 @@ pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); /// This is a copy-paste from the cumulus repo's `parachains-common` crate. const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_SECOND, 0) .saturating_div(2) - .set_proof_size(polkadot_primitives::v5::MAX_POV_SIZE as u64); + .set_proof_size(polkadot_primitives::MAX_POV_SIZE as u64); /// All cumulus bridge hubs assume that about 5 percent of the block weight is consumed by /// `on_initialize` handlers. This is used to limit the maximal weight of a single extrinsic. diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index a57a2d82088e3..5de05b3aa5903 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" -publish = false [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } From a432ae2d242d7c4e376c77ca7f6bd5def8bd263e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 28 Sep 2023 14:57:35 +0300 Subject: [PATCH 1117/1210] https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/3833103 (#2589) --- primitives/chain-polkadot-bulletin/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index 4ad1bb497c67e..1cabe968da01b 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-messages/std", From 548309a54ec428197181f3234dbdbb3f3a086f2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 01:38:26 +0000 Subject: [PATCH 1118/1210] Bump thiserror from 1.0.48 to 1.0.49 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.48 to 1.0.49. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.48...1.0.49) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 23dd31b80fe6c..3bced8e1db315 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -16,7 +16,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.9.0", features = ["derive"] } tokio = { version = "1.32", features = ["rt-multi-thread"] } -thiserror = "1.0.48" +thiserror = "1.0.49" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index ab01ad63dcf17..22e957895a0c0 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.48" +thiserror = "1.0.49" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 2a66eb25dfb9f..2fbdb3afe4765 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.32", features = ["rt"] } -thiserror = "1.0.48" +thiserror = "1.0.49" # Bridge dependencies From fbcf4ce3b75e191636260e6fc50b872ae1dac563 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 01:40:06 +0000 Subject: [PATCH 1119/1210] Bump clap from 4.4.4 to 4.4.6 Bumps [clap](https://github.com/clap-rs/clap) from 4.4.4 to 4.4.6. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.4...v4.4.6) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 3c7ce1cea8093..9d4b9e0f70476 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.4", features = ["derive"] } +clap = { version = "4.4.6", features = ["derive"] } futures = "0.3.28" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.107" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index 479d4dac9098f..e57ed60e5a296 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] [dependencies] -clap = { version = "4.4.4", features = ["derive"] } +clap = { version = "4.4.6", features = ["derive"] } log = '0.4.20' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 0cf695374a29d..8fcf395dfb0bd 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.4", features = ["derive"] } +clap = { version = "4.4.6", features = ["derive"] } serde_json = "1.0.107" # Bridge dependencies From 2cb21ca643f21f98d5ab45dba7a964309f9e7872 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 01:41:41 +0000 Subject: [PATCH 1120/1210] Bump subxt from 0.31.0 to 0.32.0 Bumps [subxt](https://github.com/paritytech/subxt) from 0.31.0 to 0.32.0. - [Release notes](https://github.com/paritytech/subxt/releases) - [Changelog](https://github.com/paritytech/subxt/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/subxt/commits) --- updated-dependencies: - dependency-name: subxt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-kusama/Cargo.toml | 2 +- relays/client-polkadot-bulletin/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 58d5ca7c18af4..daec725e8be0d 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = [] } +subxt = { version = "0.32.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index 51b445e46d2aa..d70ed4c85f560 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = [] } +subxt = { version = "0.32.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index dd1154bea953f..0e6e5c664efdb 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.0", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml index bcff9d2f21220..04176ed9496c3 100644 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.0", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 67bf87c4d5cc8..57fca81297952 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.0", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 5d3a912bd9e5b..19a8de53a91a9 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = [] } +subxt = { version = "0.32.0", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 22ceae5e76b25..ee96f6bb6fa07 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.31.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.0", default-features = false, features = ["native"] } # Bridge dependencies From 16bf09bf26810a3a2820a36a4953329a2cbafcc8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 5 Oct 2023 12:31:38 +0300 Subject: [PATCH 1121/1210] Reject transactions if bridge pallets are halted (#2600) * reject transactions if bridge pallets are halted * fixed CI (#2598) --- bin/runtime-common/src/messages_call_ext.rs | 13 ++- .../src/refund_relayer_extension.rs | 107 +++++++++++++++++- modules/beefy/src/lib.rs | 6 +- modules/grandpa/src/call_ext.rs | 21 +++- modules/parachains/src/call_ext.rs | 19 +++- 5 files changed, 152 insertions(+), 14 deletions(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 07a99d2c0a16c..435584d61f549 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -18,6 +18,7 @@ use crate::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use bp_messages::{target_chain::MessageDispatch, InboundLaneData, LaneId, MessageNonce}; +use bp_runtime::OwnedBridgeModule; use frame_support::{ dispatch::CallableCallFor, traits::{Get, IsSubType}, @@ -278,7 +279,17 @@ impl< } fn check_obsolete_call(&self) -> TransactionValidity { + let is_pallet_halted = Pallet::::ensure_not_halted().is_err(); match self.call_info() { + Some(proof_info) if is_pallet_halted => { + log::trace!( + target: pallet_bridge_messages::LOG_TARGET, + "Rejecting messages transaction on halted pallet: {:?}", + proof_info + ); + + return sp_runtime::transaction_validity::InvalidTransaction::Call.into() + }, Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.is_obsolete(T::MessageDispatch::is_active()) => { @@ -291,7 +302,7 @@ impl< return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() }, Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info)) - if proof_info.is_obsolete() => + if is_pallet_halted || proof_info.is_obsolete() => { log::trace!( target: pallet_bridge_messages::LOG_TARGET, diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 876c069dc0f77..6d8b211480858 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -838,21 +838,23 @@ mod tests { mock::*, }; use bp_messages::{ - DeliveredMessages, InboundLaneData, MessageNonce, OutboundLaneData, UnrewardedRelayer, - UnrewardedRelayersState, + DeliveredMessages, InboundLaneData, MessageNonce, MessagesOperatingMode, OutboundLaneData, + UnrewardedRelayer, UnrewardedRelayersState, }; use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; - use bp_runtime::HeaderId; + use bp_runtime::{BasicOperatingMode, HeaderId}; use bp_test_utils::{make_default_justification, test_keyring}; use frame_support::{ assert_storage_noop, parameter_types, traits::{fungible::Mutate, ReservableCurrency}, weights::Weight, }; - use pallet_bridge_grandpa::{Call as GrandpaCall, StoredAuthoritySet}; - use pallet_bridge_messages::Call as MessagesCall; - use pallet_bridge_parachains::{Call as ParachainsCall, RelayBlockHash}; + use pallet_bridge_grandpa::{Call as GrandpaCall, Pallet as GrandpaPallet, StoredAuthoritySet}; + use pallet_bridge_messages::{Call as MessagesCall, Pallet as MessagesPallet}; + use pallet_bridge_parachains::{ + Call as ParachainsCall, Pallet as ParachainsPallet, RelayBlockHash, + }; use sp_runtime::{ traits::{ConstU64, Header as HeaderT}, transaction_validity::{InvalidTransaction, ValidTransaction}, @@ -1592,6 +1594,99 @@ mod tests { }); } + #[test] + fn ext_rejects_batch_with_grandpa_finality_proof_when_grandpa_pallet_is_halted() { + run_test(|| { + initialize_environment(100, 100, 100); + + GrandpaPallet::::set_operating_mode( + RuntimeOrigin::root(), + BasicOperatingMode::Halted, + ) + .unwrap(); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + }); + } + + #[test] + fn ext_rejects_batch_with_parachain_finality_proof_when_parachains_pallet_is_halted() { + run_test(|| { + initialize_environment(100, 100, 100); + + ParachainsPallet::::set_operating_mode( + RuntimeOrigin::root(), + BasicOperatingMode::Halted, + ) + .unwrap(); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + assert_eq!( + run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + }); + } + + #[test] + fn ext_rejects_transaction_when_messages_pallet_is_halted() { + run_test(|| { + initialize_environment(100, 100, 100); + + MessagesPallet::::set_operating_mode( + RuntimeOrigin::root(), + MessagesOperatingMode::Basic(BasicOperatingMode::Halted), + ) + .unwrap(); + + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + + assert_eq!( + run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + assert_eq!( + run_pre_dispatch(parachain_finality_and_confirmation_batch_call(200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + + assert_eq!( + run_pre_dispatch(message_delivery_call(200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + assert_eq!( + run_pre_dispatch(message_confirmation_call(200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); + }); + } + #[test] fn pre_dispatch_parses_batch_with_relay_chain_and_parachain_headers() { run_test(|| { diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index 8637e9f190c18..686115a7b0ed5 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -601,7 +601,7 @@ mod tests { .is_some()); assert_eq!( ImportedBlockNumbers::::get(index), - Some(index + 1).map(Into::into) + Some(Into::into(index + 1)), ); } @@ -619,7 +619,7 @@ mod tests { .is_some()); assert_eq!( ImportedBlockNumbers::::get(0), - Some(commitments_to_keep + 1).map(Into::into) + Some(Into::into(commitments_to_keep + 1)), ); // the side effect of the import is that the commitment#1 is pruned assert!(ImportedCommitments::::get(1).is_none()); @@ -638,7 +638,7 @@ mod tests { .is_some()); assert_eq!( ImportedBlockNumbers::::get(1), - Some(commitments_to_keep + 2).map(Into::into) + Some(Into::into(commitments_to_keep + 2)), ); // the side effect of the import is that the commitment#2 is pruned assert!(ImportedCommitments::::get(1).is_none()); diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index e0648d5dd0f1d..f238064f92bca 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -16,7 +16,7 @@ use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet}; use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa}; -use bp_runtime::BlockNumberOf; +use bp_runtime::{BlockNumberOf, OwnedBridgeModule}; use codec::Encode; use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight}; use sp_runtime::{ @@ -126,6 +126,10 @@ pub trait CallSubType, I: 'static>: _ => return Ok(ValidTransaction::default()), }; + if Pallet::::ensure_not_halted().is_err() { + return InvalidTransaction::Call.into() + } + match SubmitFinalityProofHelper::::check_obsolete(finality_target.block_number) { Ok(_) => Ok(ValidTransaction::default()), Err(Error::::OldHeader) => InvalidTransaction::Stale.into(), @@ -192,10 +196,10 @@ mod tests { use crate::{ call_ext::CallSubType, mock::{run_test, test_header, RuntimeCall, TestBridgedChain, TestNumber, TestRuntime}, - BestFinalized, Config, WeightInfo, + BestFinalized, Config, PalletOperatingMode, WeightInfo, }; use bp_header_chain::ChainWithGrandpa; - use bp_runtime::HeaderId; + use bp_runtime::{BasicOperatingMode, HeaderId}; use bp_test_utils::{ make_default_justification, make_justification_for_header, JustificationGeneratorParams, }; @@ -238,6 +242,17 @@ mod tests { }); } + #[test] + fn extension_rejects_new_header_if_pallet_is_halted() { + run_test(|| { + // when pallet is halted => tx is rejected + sync_to_header_10(); + PalletOperatingMode::::put(BasicOperatingMode::Halted); + + assert!(!validate_block_submit(15)); + }); + } + #[test] fn extension_accepts_new_header() { run_test(|| { diff --git a/modules/parachains/src/call_ext.rs b/modules/parachains/src/call_ext.rs index 99640dadc61f4..198ff11be4951 100644 --- a/modules/parachains/src/call_ext.rs +++ b/modules/parachains/src/call_ext.rs @@ -17,6 +17,7 @@ use crate::{Config, Pallet, RelayBlockNumber}; use bp_parachains::BestParaHeadHash; use bp_polkadot_core::parachains::{ParaHash, ParaId}; +use bp_runtime::OwnedBridgeModule; use frame_support::{dispatch::CallableCallFor, traits::IsSubType}; use sp_runtime::{ transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, @@ -141,6 +142,10 @@ pub trait CallSubType, I: 'static>: None => return Ok(ValidTransaction::default()), }; + if Pallet::::ensure_not_halted().is_err() { + return InvalidTransaction::Call.into() + } + if SubmitParachainHeadsHelper::::is_obsolete(&update) { return InvalidTransaction::Stale.into() } @@ -160,10 +165,11 @@ where mod tests { use crate::{ mock::{run_test, RuntimeCall, TestRuntime}, - CallSubType, ParaInfo, ParasInfo, RelayBlockNumber, + CallSubType, PalletOperatingMode, ParaInfo, ParasInfo, RelayBlockNumber, }; use bp_parachains::BestParaHeadHash; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; + use bp_runtime::BasicOperatingMode; fn validate_submit_parachain_heads( num: RelayBlockNumber, @@ -221,6 +227,17 @@ mod tests { }); } + #[test] + fn extension_rejects_header_if_pallet_is_halted() { + run_test(|| { + // when pallet is halted => tx is rejected + sync_to_relay_header_10(); + PalletOperatingMode::::put(BasicOperatingMode::Halted); + + assert!(!validate_submit_parachain_heads(15, vec![(ParaId(1), [2u8; 32].into())])); + }); + } + #[test] fn extension_accepts_new_header() { run_test(|| { From 4aa2886bc89d894576e0a4762e522881e422623d Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 5 Oct 2023 13:00:26 +0300 Subject: [PATCH 1122/1210] actualize check_obsolete_call comment (#2601) --- bin/runtime-common/src/messages_call_ext.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 435584d61f549..3ee6b65707760 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -188,8 +188,22 @@ pub trait MessagesCallSubType, I: 'static>: /// or a `ReceiveMessagesDeliveryProof` call, if the call is for the provided lane. fn call_info_for(&self, lane_id: LaneId) -> Option; - /// Check that a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call is trying - /// to deliver/confirm at least some messages that are better than the ones we know of. + /// Ensures that a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call: + /// + /// - does not deliver already delivered messages. We require all messages in the + /// `ReceiveMessagesProof` call to be undelivered; + /// + /// - does not submit empty `ReceiveMessagesProof` call with zero messages, unless the lane + /// needs to be unblocked by providing relayer rewards proof; + /// + /// - brings no new delivery confirmations in a `ReceiveMessagesDeliveryProof` call. We require + /// at least one new delivery confirmation in the unrewarded relayers set; + /// + /// - does not violate some basic (easy verifiable) messages pallet rules obsolete (like + /// submitting a call when a pallet is halted or delivering messages when a dispatcher is + /// inactive). + /// + /// If one of above rules is violated, the transaction is treated as invalid. fn check_obsolete_call(&self) -> TransactionValidity; } From 48bf2231496f1805591f527947004f101c321e03 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 6 Oct 2023 11:00:01 +0300 Subject: [PATCH 1123/1210] apply late suggestions for #2600 (#2603) --- bin/runtime-common/src/messages_call_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 3ee6b65707760..5303fcb7ba030 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -316,7 +316,7 @@ impl< return sp_runtime::transaction_validity::InvalidTransaction::Stale.into() }, Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info)) - if is_pallet_halted || proof_info.is_obsolete() => + if proof_info.is_obsolete() => { log::trace!( target: pallet_bridge_messages::LOG_TARGET, From 5541e9aa589b9d8b9b83f04f12b48493ee95ca6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 02:00:34 +0000 Subject: [PATCH 1124/1210] Bump subxt from 0.32.0 to 0.32.1 Bumps [subxt](https://github.com/paritytech/subxt) from 0.32.0 to 0.32.1. - [Release notes](https://github.com/paritytech/subxt/releases) - [Changelog](https://github.com/paritytech/subxt/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/subxt/commits) --- updated-dependencies: - dependency-name: subxt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-kusama/Cargo.toml | 2 +- relays/client-polkadot-bulletin/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index daec725e8be0d..d4bd0e151ae39 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = [] } +subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index d70ed4c85f560..e8c8a015fa980 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = [] } +subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 0e6e5c664efdb..be03225b7b4c0 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml index 04176ed9496c3..6694f3c761f72 100644 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 57fca81297952..224227c63b7e8 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 19a8de53a91a9..93bad81cd75ff 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = [] } +subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index ee96f6bb6fa07..5cccefa50e063 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.0", default-features = false, features = ["native"] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies From d08fd724fd0a29ae3389d10bf89eab2abcbeb404 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 06:49:05 +0000 Subject: [PATCH 1125/1210] Bump tokio from 1.32.0 to 1.33.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.32.0 to 1.33.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.32.0...tokio-1.33.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 3bced8e1db315..7fdd18f226e78 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.20" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.9.0", features = ["derive"] } -tokio = { version = "1.32", features = ["rt-multi-thread"] } +tokio = { version = "1.33", features = ["rt-multi-thread"] } thiserror = "1.0.49" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 2fbdb3afe4765..ccdb822205115 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.32", features = ["rt"] } +tokio = { version = "1.33", features = ["rt"] } thiserror = "1.0.49" # Bridge dependencies From fc3a4973504f7e05c853b4bf9c4fc8c1765cfcf3 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 12 Oct 2023 10:08:35 +0300 Subject: [PATCH 1126/1210] Millau, Rialto: accept equivocation reports (#2614) (#2617) --- bin/millau/runtime/Cargo.toml | 4 +++ bin/millau/runtime/src/lib.rs | 43 ++++++++++++++++++++++++++++++--- bin/rialto/runtime/Cargo.toml | 4 +++ bin/rialto/runtime/src/lib.rs | 37 +++++++++++++++++++++++++--- relays/client-millau/src/lib.rs | 5 ++-- relays/client-rialto/src/lib.rs | 5 ++-- 6 files changed, 88 insertions(+), 10 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 57586fb961f7a..861a40120dbc3 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -41,11 +41,13 @@ frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = " frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-offences = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["historical"]} pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } @@ -100,6 +102,7 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "pallet-aura/std", + "pallet-authorship/std", "pallet-balances/std", "pallet-beefy/std", "pallet-beefy-mmr/std", @@ -109,6 +112,7 @@ std = [ "pallet-bridge-relayers/std", "pallet-grandpa/std", "pallet-mmr/std", + "pallet-offences/std", "pallet-session/std", "pallet-shift-session-manager/std", "pallet-sudo/std", diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 9abe5ce69c096..cf2b887d1ab44 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -49,7 +49,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, KeyTypeId, Perquintill, }; use sp_std::prelude::*; #[cfg(feature = "std")] @@ -249,8 +249,9 @@ impl pallet_grandpa::Config for Runtime { type WeightInfo = (); type MaxAuthorities = ConstU32<10>; type MaxSetIdSessionEntries = ConstU64<0>; - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); + type KeyOwnerProof = >::Proof; + type EquivocationReportSystem = + pallet_grandpa::EquivocationReportSystem; type MaxNominators = ConstU32<256>; } @@ -377,6 +378,7 @@ parameter_types! { pub const Period: BlockNumber = bp_millau::SESSION_LENGTH; pub const Offset: BlockNumber = 0; pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + pub ReportLongevity: u64 = Period::get() * 10; } impl pallet_session::Config for Runtime { @@ -392,6 +394,37 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } +impl frame_system::offchain::SendTransactionTypes for Runtime +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = RuntimeCall; +} + +impl pallet_authorship::Config for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (); +} + +pub struct FullIdentificationOf; +impl sp_runtime::traits::Convert> for FullIdentificationOf { + fn convert(_: AccountId) -> Option<()> { + Some(()) + } +} + +impl pallet_session::historical::Config for Runtime { + type FullIdentification = (); + type FullIdentificationOf = FullIdentificationOf; +} + +impl pallet_offences::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type IdentificationTuple = pallet_session::historical::IdentificationTuple; + type OnOffenceHandler = (); +} + impl pallet_bridge_relayers::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Reward = Balance; @@ -582,6 +615,10 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, // Consensus support. + Authorship: pallet_authorship::{Pallet, Storage}, + Offences: pallet_offences::{Pallet, Storage, Event}, + Historical: pallet_session::historical::{Pallet}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, ShiftSessionManager: pallet_shift_session_manager::{Pallet}, diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index d8b402d310979..7bd89803cafac 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -34,6 +34,7 @@ frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = " frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } @@ -41,6 +42,7 @@ pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +pallet-offences = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["historical"]} pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } @@ -94,6 +96,7 @@ std = [ "frame-system-rpc-runtime-api/std", "frame-system/std", "pallet-authority-discovery/std", + "pallet-authorship/std", "pallet-babe/std", "pallet-balances/std", "pallet-beefy/std", @@ -105,6 +108,7 @@ std = [ "pallet-grandpa/std", "pallet-message-queue/std", "pallet-mmr/std", + "pallet-offences/std", "pallet-xcm/std", "pallet-session/std", "pallet-shift-session-manager/std", diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index d149421864f6f..c00e32e9f317e 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -45,7 +45,7 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, Perquintill, + ApplyExtrinsicResult, FixedPointNumber, KeyTypeId, Perquintill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; #[cfg(feature = "std")] @@ -219,6 +219,7 @@ pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = parameter_types! { pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64; pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK; + pub ReportLongevity: u64 = EpochDuration::get() * 10; } impl pallet_babe::Config for Runtime { @@ -257,8 +258,9 @@ impl pallet_grandpa::Config for Runtime { type WeightInfo = (); type MaxAuthorities = ConstU32<10>; type MaxSetIdSessionEntries = ConstU64<0>; - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); + type KeyOwnerProof = >::Proof; + type EquivocationReportSystem = + pallet_grandpa::EquivocationReportSystem; type MaxNominators = ConstU32<256>; } @@ -383,6 +385,29 @@ impl pallet_session::Config for Runtime { type WeightInfo = (); } +impl pallet_authorship::Config for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (); +} + +pub struct FullIdentificationOf; +impl sp_runtime::traits::Convert> for FullIdentificationOf { + fn convert(_: AccountId) -> Option<()> { + Some(()) + } +} + +impl pallet_session::historical::Config for Runtime { + type FullIdentification = (); + type FullIdentificationOf = FullIdentificationOf; +} + +impl pallet_offences::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type IdentificationTuple = pallet_session::historical::IdentificationTuple; + type OnOffenceHandler = (); +} + impl pallet_authority_discovery::Config for Runtime { type MaxAuthorities = ConstU32<10>; } @@ -469,6 +494,12 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, // Consensus support. + // Authorship must be before session in order to note author in the correct session and era + // for im-online. + Authorship: pallet_authorship::{Pallet, Storage}, + Offences: pallet_offences::{Pallet, Storage, Event}, + Historical: pallet_session::historical::{Pallet}, + AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, Session: pallet_session::{Pallet, Call, Storage, Event, Config}, Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index ffd4a3f1cb8ed..b3101c980c557 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -25,8 +25,9 @@ use relay_substrate_client::{ ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, NonceOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::{storage::StorageKey, Pair, Void}; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use sp_session::MembershipProof; use std::time::Duration; /// Millau header id. @@ -70,7 +71,7 @@ impl ChainWithGrandpa for Millau { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - type KeyOwnerProof = Void; + type KeyOwnerProof = MembershipProof; } impl ChainWithBalances for Millau { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 94d8c24d95105..cc5371612c346 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -25,8 +25,9 @@ use relay_substrate_client::{ ChainWithTransactions, Error as SubstrateError, NonceOf, RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::{storage::StorageKey, Pair, Void}; +use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use sp_session::MembershipProof; use std::time::Duration; /// Rialto header id. @@ -55,7 +56,7 @@ impl ChainWithGrandpa for Rialto { const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - type KeyOwnerProof = Void; + type KeyOwnerProof = MembershipProof; } impl RelayChain for Rialto { From f700ef51da694853220f71f6589a79c75eaac32e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 01:30:04 +0000 Subject: [PATCH 1127/1210] Bump async-trait from 0.1.73 to 0.1.74 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.73 to 0.1.74. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.73...0.1.74) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/parachains/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index a97aabcaa167a..fcd962f1038a1 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" -async-trait = "0.1.73" +async-trait = "0.1.74" futures = "0.3.28" log = "0.4.20" relay-utils = { path = "../utils" } From 17fa5fda6d92c2285fa7aa790e9524928ba8638c Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 17 Oct 2023 17:49:22 +0300 Subject: [PATCH 1128/1210] add missing crate descriptions (#2629) --- bin/runtime-common/Cargo.toml | 1 + modules/beefy/Cargo.toml | 1 + modules/grandpa/Cargo.toml | 1 + modules/parachains/Cargo.toml | 1 + primitives/test-utils/Cargo.toml | 1 + 5 files changed, 5 insertions(+) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 602f6ac95f823..ee3dd4be05c6c 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "bridge-runtime-common" version = "0.1.0" +description = "Common types and functions that may be used by substrate-based runtimes of all bridged chains" authors.workspace = true edition.workspace = true repository.workspace = true diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 10923e2e1e737..0f5bd0a546dc8 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "pallet-bridge-beefy" version = "0.1.0" +description = "Module implementing BEEFY on-chain light client used for bridging consensus of substrate-based chains." authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 455968716c62e..34bd76fd103e5 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "pallet-bridge-grandpa" version = "0.1.0" +description = "Module implementing GRANDPA on-chain light client used for bridging consensus of substrate-based chains." authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 8be580ad1a7bc..7a77d7653135d 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "pallet-bridge-parachains" version = "0.1.0" +description = "Module that allows bridged relay chains to exchange information on their parachains' heads." authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 5de05b3aa5903..778d4e165e86b 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "bp-test-utils" version = "0.1.0" +description = "Utilities for testing substrate-based runtime bridge code" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" From 85234df016223e126c349457812a2fbbeccc1994 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 19 Oct 2023 08:16:40 +0300 Subject: [PATCH 1129/1210] Grandpa justifications: Avoid duplicate vote ancestries (#2634) (#2635) * Grandpa justifications: Avoid duplicate vote ancestries --- .../verification/equivocation.rs | 7 +++ .../src/justification/verification/mod.rs | 59 +++++++++++++++---- .../justification/verification/optimizer.rs | 15 +++++ .../src/justification/verification/strict.rs | 9 ++- .../tests/implementation_match.rs | 4 +- .../tests/justification/optimizer.rs | 20 +++++++ .../tests/justification/strict.rs | 16 ++++- 7 files changed, 114 insertions(+), 16 deletions(-) diff --git a/primitives/header-chain/src/justification/verification/equivocation.rs b/primitives/header-chain/src/justification/verification/equivocation.rs index e2d7a8e804c20..fbad301281994 100644 --- a/primitives/header-chain/src/justification/verification/equivocation.rs +++ b/primitives/header-chain/src/justification/verification/equivocation.rs @@ -101,6 +101,13 @@ impl<'a, Header: HeaderT> EquivocationsCollector<'a, Header> { } impl<'a, Header: HeaderT> JustificationVerifier

for EquivocationsCollector<'a, Header> { + fn process_duplicate_votes_ancestries( + &mut self, + _duplicate_votes_ancestries: Vec, + ) -> Result<(), JustificationVerificationError> { + Ok(()) + } + fn process_redundant_vote( &mut self, _precommit_idx: usize, diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/primitives/header-chain/src/justification/verification/mod.rs index a66fc1e0d91d1..c71149bf9c28e 100644 --- a/primitives/header-chain/src/justification/verification/mod.rs +++ b/primitives/header-chain/src/justification/verification/mod.rs @@ -27,7 +27,13 @@ use finality_grandpa::voter_set::VoterSet; use sp_consensus_grandpa::{AuthorityId, AuthoritySignature, SetId}; use sp_runtime::{traits::Header as HeaderT, RuntimeDebug}; use sp_std::{ - collections::{btree_map::BTreeMap, btree_set::BTreeSet}, + collections::{ + btree_map::{ + BTreeMap, + Entry::{Occupied, Vacant}, + }, + btree_set::BTreeSet, + }, prelude::*, }; @@ -44,23 +50,40 @@ pub struct AncestryChain { /// We expect all forks in the ancestry chain to be descendants of base. base: HeaderId, /// Header hash => parent header hash mapping. - pub parents: BTreeMap, + parents: BTreeMap, /// Hashes of headers that were not visited by `ancestry()`. - pub unvisited: BTreeSet, + unvisited: BTreeSet, } impl AncestryChain
{ - /// Create new ancestry chain. - pub fn new(justification: &GrandpaJustification
) -> AncestryChain
{ + /// Creates a new instance of `AncestryChain` starting from a `GrandpaJustification`. + /// + /// Returns the `AncestryChain` and a `Vec` containing the `votes_ancestries` entries + /// that were ignored when creating it, because they are duplicates. + pub fn new( + justification: &GrandpaJustification
, + ) -> (AncestryChain
, Vec) { let mut parents = BTreeMap::new(); let mut unvisited = BTreeSet::new(); - for ancestor in &justification.votes_ancestries { + let mut ignored_idxs = Vec::new(); + for (idx, ancestor) in justification.votes_ancestries.iter().enumerate() { let hash = ancestor.hash(); - let parent_hash = *ancestor.parent_hash(); - parents.insert(hash, parent_hash); - unvisited.insert(hash); + match parents.entry(hash) { + Occupied(_) => { + ignored_idxs.push(idx); + }, + Vacant(entry) => { + entry.insert(*ancestor.parent_hash()); + unvisited.insert(hash); + }, + } } - AncestryChain { base: justification.commit_target_id(), parents, unvisited } + (AncestryChain { base: justification.commit_target_id(), parents, unvisited }, ignored_idxs) + } + + /// Returns the hash of a block's parent if the block is present in the ancestry. + pub fn parent_hash_of(&self, hash: &Header::Hash) -> Option<&Header::Hash> { + self.parents.get(hash) } /// Returns a route if the precommit target block is a descendant of the `base` block. @@ -80,7 +103,7 @@ impl AncestryChain
{ break } - current_hash = match self.parents.get(¤t_hash) { + current_hash = match self.parent_hash_of(¤t_hash) { Some(parent_hash) => { let is_visited_before = self.unvisited.get(¤t_hash).is_none(); if is_visited_before { @@ -117,6 +140,8 @@ pub enum Error { InvalidAuthorityList, /// Justification is finalizing unexpected header. InvalidJustificationTarget, + /// The justification contains duplicate headers in its `votes_ancestries` field. + DuplicateVotesAncestries, /// Error validating a precommit Precommit(PrecommitError), /// The cumulative weight of all votes in the justification is not enough to justify commit @@ -168,6 +193,12 @@ enum IterationFlow { /// Verification callbacks. trait JustificationVerifier { + /// Called when there are duplicate headers in the votes ancestries. + fn process_duplicate_votes_ancestries( + &mut self, + duplicate_votes_ancestries: Vec, + ) -> Result<(), Error>; + fn process_redundant_vote( &mut self, precommit_idx: usize, @@ -216,10 +247,14 @@ trait JustificationVerifier { } let threshold = context.voter_set.threshold().get(); - let mut chain = AncestryChain::new(justification); + let (mut chain, ignored_idxs) = AncestryChain::new(justification); let mut signature_buffer = Vec::new(); let mut cumulative_weight = 0u64; + if !ignored_idxs.is_empty() { + self.process_duplicate_votes_ancestries(ignored_idxs)?; + } + for (precommit_idx, signed) in justification.commit.precommits.iter().enumerate() { if cumulative_weight >= threshold { let action = diff --git a/primitives/header-chain/src/justification/verification/optimizer.rs b/primitives/header-chain/src/justification/verification/optimizer.rs index 6552b359170a8..3f1e6ab670ca6 100644 --- a/primitives/header-chain/src/justification/verification/optimizer.rs +++ b/primitives/header-chain/src/justification/verification/optimizer.rs @@ -33,6 +33,7 @@ struct JustificationOptimizer { votes: BTreeSet, extra_precommits: Vec, + duplicate_votes_ancestries_idxs: Vec, redundant_votes_ancestries: BTreeSet, } @@ -41,6 +42,11 @@ impl JustificationOptimizer
{ for invalid_precommit_idx in self.extra_precommits.into_iter().rev() { justification.commit.precommits.remove(invalid_precommit_idx); } + if !self.duplicate_votes_ancestries_idxs.is_empty() { + for idx in self.duplicate_votes_ancestries_idxs.iter().rev() { + justification.votes_ancestries.swap_remove(*idx); + } + } if !self.redundant_votes_ancestries.is_empty() { justification .votes_ancestries @@ -50,6 +56,14 @@ impl JustificationOptimizer
{ } impl JustificationVerifier
for JustificationOptimizer
{ + fn process_duplicate_votes_ancestries( + &mut self, + duplicate_votes_ancestries: Vec, + ) -> Result<(), Error> { + self.duplicate_votes_ancestries_idxs = duplicate_votes_ancestries.to_vec(); + Ok(()) + } + fn process_redundant_vote( &mut self, precommit_idx: usize, @@ -118,6 +132,7 @@ pub fn verify_and_optimize_justification( let mut optimizer = JustificationOptimizer { votes: BTreeSet::new(), extra_precommits: vec![], + duplicate_votes_ancestries_idxs: vec![], redundant_votes_ancestries: Default::default(), }; optimizer.verify_justification(finalized_target, context, justification)?; diff --git a/primitives/header-chain/src/justification/verification/strict.rs b/primitives/header-chain/src/justification/verification/strict.rs index f899c6c8efc06..858cf517a431e 100644 --- a/primitives/header-chain/src/justification/verification/strict.rs +++ b/primitives/header-chain/src/justification/verification/strict.rs @@ -26,7 +26,7 @@ use crate::justification::verification::{ }; use sp_consensus_grandpa::AuthorityId; use sp_runtime::traits::Header as HeaderT; -use sp_std::collections::btree_set::BTreeSet; +use sp_std::{collections::btree_set::BTreeSet, vec::Vec}; /// Verification callbacks that reject all unknown, duplicate or redundant votes. struct StrictJustificationVerifier { @@ -34,6 +34,13 @@ struct StrictJustificationVerifier { } impl JustificationVerifier
for StrictJustificationVerifier { + fn process_duplicate_votes_ancestries( + &mut self, + _duplicate_votes_ancestries: Vec, + ) -> Result<(), Error> { + Err(Error::DuplicateVotesAncestries) + } + fn process_redundant_vote( &mut self, _precommit_idx: usize, diff --git a/primitives/header-chain/tests/implementation_match.rs b/primitives/header-chain/tests/implementation_match.rs index f664a419621f6..1f61f91ff4bbf 100644 --- a/primitives/header-chain/tests/implementation_match.rs +++ b/primitives/header-chain/tests/implementation_match.rs @@ -42,7 +42,7 @@ struct AncestryChain(bp_header_chain::justification::AncestryChain); impl AncestryChain { fn new(justification: &GrandpaJustification) -> Self { - Self(bp_header_chain::justification::AncestryChain::new(justification)) + Self(bp_header_chain::justification::AncestryChain::new(justification).0) } } @@ -58,7 +58,7 @@ impl finality_grandpa::Chain for AncestryChain { if current_hash == base { break } - match self.0.parents.get(¤t_hash) { + match self.0.parent_hash_of(¤t_hash) { Some(parent_hash) => { current_hash = *parent_hash; route.push(current_hash); diff --git a/primitives/header-chain/tests/justification/optimizer.rs b/primitives/header-chain/tests/justification/optimizer.rs index 21bcd7e86b51e..8d7e2d6502568 100644 --- a/primitives/header-chain/tests/justification/optimizer.rs +++ b/primitives/header-chain/tests/justification/optimizer.rs @@ -158,6 +158,26 @@ fn unrelated_ancestry_votes_are_removed_by_optimizer() { assert_eq!(num_precommits_before - 1, num_precommits_after); } +#[test] +fn duplicate_votes_ancestries_are_removed_by_optimizer() { + let mut justification = make_default_justification::(&test_header(1)); + let optimized_votes_ancestries = justification.votes_ancestries.clone(); + justification.votes_ancestries = justification + .votes_ancestries + .into_iter() + .flat_map(|item| std::iter::repeat(item).take(3)) + .collect(); + + verify_and_optimize_justification::( + header_id::(1), + &verification_context(TEST_GRANDPA_SET_ID), + &mut justification, + ) + .unwrap(); + + assert_eq!(justification.votes_ancestries, optimized_votes_ancestries); +} + #[test] fn redundant_votes_ancestries_are_removed_by_optimizer() { let mut justification = make_default_justification::(&test_header(1)); diff --git a/primitives/header-chain/tests/justification/strict.rs b/primitives/header-chain/tests/justification/strict.rs index 188c9f5baba26..639a669572b21 100644 --- a/primitives/header-chain/tests/justification/strict.rs +++ b/primitives/header-chain/tests/justification/strict.rs @@ -149,7 +149,21 @@ fn justification_with_invalid_authority_signature_rejected() { } #[test] -fn justification_with_invalid_precommit_ancestry() { +fn justification_with_duplicate_votes_ancestry() { + let mut justification = make_default_justification::(&test_header(1)); + justification.votes_ancestries.push(justification.votes_ancestries[0].clone()); + + assert_eq!( + verify_justification::( + header_id::(1), + &verification_context(TEST_GRANDPA_SET_ID), + &justification, + ), + Err(JustificationVerificationError::DuplicateVotesAncestries), + ); +} +#[test] +fn justification_with_redundant_votes_ancestry() { let mut justification = make_default_justification::(&test_header(1)); justification.votes_ancestries.push(test_header(10)); From ce560d66b5545a37c5653c3a2e219268da54f49e Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 19 Oct 2023 10:04:26 +0200 Subject: [PATCH 1130/1210] Backport from `polkadot-sdk` with actual master (#2633) * Backport from `polkadot-sdk` * lingua stuff * Fixes * Fix * Features? * Fix - v5 -> v6 * zepter format features * try zepter with CI * Fix imports * Fix * Fix * Fix * Revert zepther pipeline --- bin/millau/node/Cargo.toml | 4 +- bin/millau/node/src/service.rs | 3 +- bin/millau/runtime/Cargo.toml | 15 +- bin/millau/runtime/src/lib.rs | 13 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto-parachain/node/src/service.rs | 1 + bin/rialto-parachain/runtime/Cargo.toml | 60 +++---- bin/rialto/node/Cargo.toml | 2 +- bin/rialto/node/src/chain_spec.rs | 6 +- bin/rialto/runtime/Cargo.toml | 13 +- bin/rialto/runtime/src/lib.rs | 147 +++++++++++------- bin/rialto/runtime/src/parachains.rs | 7 +- modules/beefy/Cargo.toml | 7 +- modules/parachains/README.md | 10 +- modules/shift-session-manager/Cargo.toml | 7 +- .../xcm-bridge-hub-router/src/benchmarking.rs | 8 +- modules/xcm-bridge-hub-router/src/mock.rs | 13 +- primitives/beefy/Cargo.toml | 4 +- primitives/chain-asset-hub-rococo/Cargo.toml | 26 ++++ primitives/chain-asset-hub-rococo/src/lib.rs | 52 +++++++ primitives/chain-asset-hub-wococo/Cargo.toml | 26 ++++ primitives/chain-asset-hub-wococo/src/lib.rs | 52 +++++++ primitives/chain-bridge-hub-rococo/src/lib.rs | 3 + primitives/chain-bridge-hub-wococo/src/lib.rs | 3 + primitives/chain-millau/Cargo.toml | 2 +- primitives/chain-rialto-parachain/Cargo.toml | 2 +- primitives/chain-rialto/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 2 +- .../src/cli/register_parachain.rs | 4 +- 29 files changed, 353 insertions(+), 143 deletions(-) create mode 100644 primitives/chain-asset-hub-rococo/Cargo.toml create mode 100644 primitives/chain-asset-hub-rococo/src/lib.rs create mode 100644 primitives/chain-asset-hub-wococo/Cargo.toml create mode 100644 primitives/chain-asset-hub-wococo/src/lib.rs diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 9d4b9e0f70476..88175ba6993bd 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -58,6 +58,4 @@ frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", b [features] default = [] -runtime-benchmarks = [ - "millau-runtime/runtime-benchmarks", -] +runtime-benchmarks = [ "millau-runtime/runtime-benchmarks" ] diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs index 1e31ecdd14d59..cb57dd118cc71 100644 --- a/bin/millau/node/src/service.rs +++ b/bin/millau/node/src/service.rs @@ -181,7 +181,7 @@ pub fn new_partial( /// Builds a new service for a full client. pub fn new_full(config: Configuration) -> Result { - use sc_network_common::sync::warp::WarpSyncParams; + use sc_service::WarpSyncParams; let sc_service::PartialComponents { client, @@ -242,6 +242,7 @@ pub fn new_full(config: Configuration) -> Result { import_queue, block_announce_validator_builder: None, warp_sync_params: Some(WarpSyncParams::WithProvider(warp_sync)), + block_relay: None, })?; if config.offchain_worker.enabled { diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 861a40120dbc3..302a04d024420 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -82,16 +82,15 @@ static_assertions = "1.1" substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ - "sp-consensus-beefy/std", "bp-messages/std", "bp-millau/std", "bp-parachains/std", "bp-polkadot-core/std", "bp-relayers/std", - "bp-rialto/std", "bp-rialto-parachain/std", + "bp-rialto/std", "bp-runtime/std", "bp-westend/std", "bp-xcm-bridge-hub-router/std", @@ -104,8 +103,8 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", - "pallet-beefy/std", "pallet-beefy-mmr/std", + "pallet-beefy/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-parachains/std", @@ -120,12 +119,13 @@ std = [ "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", "pallet-utility/std", - "pallet-xcm/std", "pallet-xcm-bridge-hub-router/std", + "pallet-xcm/std", "scale-info/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", + "sp-consensus-beefy/std", "sp-core/std", "sp-inherents/std", "sp-io/std", @@ -135,20 +135,21 @@ std = [ "sp-std/std", "sp-transaction-pool/std", "sp-version/std", - "xcm/std", "xcm-builder/std", "xcm-executor/std", + "xcm/std", ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", "pallet-xcm-bridge-hub-router/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index cf2b887d1ab44..27f00c801bc4d 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -55,7 +55,7 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use xcm_builder::NetworkExportTable; +use xcm_builder::{NetworkExportTable, NetworkExportTableItem}; // to be able to use Millau runtime in `bridge-runtime-common` tests pub use bridge_runtime_common; @@ -583,8 +583,15 @@ impl pallet_utility::Config for Runtime { // this config is totally incorrect - the pallet is not actually used at this runtime. We need // it only to be able to run benchmarks and make required traits (and default weights for tests). parameter_types! { - pub BridgeTable: Vec<(xcm::prelude::NetworkId, xcm::prelude::MultiLocation, Option)> - = vec![(xcm_config::RialtoNetwork::get(), xcm_config::TokenLocation::get(), Some((xcm_config::TokenAssetId::get(), 1_000_000_000_u128).into()))]; + pub BridgeTable: Vec + = vec![ + NetworkExportTableItem::new( + xcm_config::RialtoNetwork::get(), + None, + xcm_config::TokenLocation::get(), + Some((xcm_config::TokenAssetId::get(), 1_000_000_000_u128).into()) + ) + ]; } impl pallet_xcm_bridge_hub_router::Config for Runtime { type WeightInfo = (); diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index e57ed60e5a296..d83ed44c32176 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -14,7 +14,7 @@ name = 'rialto-parachain-collator' [features] default = [] -runtime-benchmarks = ['rialto-parachain-runtime/runtime-benchmarks'] +runtime-benchmarks = [ 'rialto-parachain-runtime/runtime-benchmarks' ] [dependencies] clap = { version = "4.4.6", features = ["derive"] } diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs index c43241d4945f3..86c5a7615901c 100644 --- a/bin/rialto-parachain/node/src/service.rs +++ b/bin/rialto-parachain/node/src/service.rs @@ -283,6 +283,7 @@ where Box::new(block_announce_validator) })), warp_sync_params: None, + block_relay: None, })?; let rpc_client = client.clone(); diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 8f987e27f362c..bc4f8fb4d5c70 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -81,62 +81,66 @@ bridge-runtime-common = { path = "../../runtime-common", features = ["integrity- static_assertions = "1.1" [features] -default = ['std'] +default = [ 'std' ] runtime-benchmarks = [ - 'sp-runtime/runtime-benchmarks', + 'bridge-runtime-common/runtime-benchmarks', 'frame-benchmarking', 'frame-support/runtime-benchmarks', 'frame-system-benchmarking/runtime-benchmarks', 'frame-system/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', + 'pallet-bridge-grandpa/runtime-benchmarks', + 'pallet-bridge-messages/runtime-benchmarks', + 'pallet-bridge-relayers/runtime-benchmarks', 'pallet-timestamp/runtime-benchmarks', 'pallet-xcm/runtime-benchmarks', + 'sp-runtime/runtime-benchmarks', 'xcm-builder/runtime-benchmarks', ] std = [ "bp-messages/std", "bp-millau/std", "bp-relayers/std", - "bp-runtime/std", "bp-rialto-parachain/std", + "bp-runtime/std", "bridge-runtime-common/std", "codec/std", - "scale-info/std", - "sp-api/std", - "sp-std/std", - "sp-io/std", - "sp-core/std", - "sp-runtime/std", - "sp-version/std", - "sp-offchain/std", - "sp-session/std", - "sp-block-builder/std", - "sp-transaction-pool/std", - "sp-inherents/std", - "frame-support/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", "frame-executive/std", - "frame-system/std", + "frame-support/std", "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-aura/std", "pallet-balances/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", "pallet-bridge-relayers/std", - "pallet-timestamp/std", "pallet-sudo/std", - "pallet-transaction-payment/std", + "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain-primitives/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-pallet-xcm/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "xcm/std", + "scale-info/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", "xcm-builder/std", "xcm-executor/std", - "pallet-aura/std", - "sp-consensus-aura/std", + "xcm/std", ] diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 8fcf395dfb0bd..06352a1377951 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -47,7 +47,7 @@ polkadot-node-core-pvf-execute-worker = { git = "https://github.com/paritytech/p polkadot-node-core-pvf-prepare-worker = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = [ "full-node", "polkadot-native" ] } +polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = [ "full-node" ] } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs index 505dc5a760b67..6d1180d12a985 100644 --- a/bin/rialto/node/src/chain_spec.rs +++ b/bin/rialto/node/src/chain_spec.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use polkadot_primitives::v5::{AssignmentId, ValidatorId}; +use polkadot_primitives::v6::{AssignmentId, ValidatorId}; use rialto_runtime::{ AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, ConfigurationConfig, GrandpaConfig, RuntimeGenesisConfig, SessionConfig, SessionKeys, @@ -245,8 +245,8 @@ fn testnet_genesis( validation_upgrade_cooldown: 2u32, validation_upgrade_delay: 2, code_retention_period: 1200, - max_code_size: polkadot_primitives::v5::MAX_CODE_SIZE, - max_pov_size: polkadot_primitives::v5::MAX_POV_SIZE, + max_code_size: polkadot_primitives::v6::MAX_CODE_SIZE, + max_pov_size: polkadot_primitives::v6::MAX_POV_SIZE, max_head_data_size: 32 * 1024, group_rotation_frequency: 20, max_upward_queue_count: 8, diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 7bd89803cafac..2bdadfd0cde70 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -80,9 +80,8 @@ static_assertions = "1.1" substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ - "sp-consensus-beefy/std", "bp-messages/std", "bp-millau/std", "bp-relayers/std", @@ -99,8 +98,8 @@ std = [ "pallet-authorship/std", "pallet-babe/std", "pallet-balances/std", - "pallet-beefy/std", "pallet-beefy-mmr/std", + "pallet-beefy/std", "pallet-bridge-beefy/std", "pallet-bridge-grandpa/std", "pallet-bridge-messages/std", @@ -109,13 +108,13 @@ std = [ "pallet-message-queue/std", "pallet-mmr/std", "pallet-offences/std", - "pallet-xcm/std", "pallet-session/std", "pallet-shift-session-manager/std", "pallet-sudo/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "pallet-xcm/std", "polkadot-primitives/std", "polkadot-runtime-common/std", "polkadot-runtime-parachains/std", @@ -124,6 +123,7 @@ std = [ "sp-authority-discovery/std", "sp-block-builder/std", "sp-consensus-babe/std", + "sp-consensus-beefy/std", "sp-core/std", "sp-inherents/std", "sp-io/std", @@ -133,18 +133,21 @@ std = [ "sp-std/std", "sp-transaction-pool/std", "sp-version/std", - "xcm/std", "xcm-builder/std", "xcm-executor/std", + "xcm/std", ] runtime-benchmarks = [ "bridge-runtime-common/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index c00e32e9f317e..684b3e5bf466f 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -37,6 +37,10 @@ use pallet_grandpa::{ fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, }; use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; +use polkadot_primitives::Id as ParaId; +use polkadot_runtime_parachains::runtime_api_impl::{ + v7 as parachains_runtime_api_impl, vstaging as parachains_staging_runtime_api_impl, +}; use sp_api::impl_runtime_apis; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_beefy::{ecdsa_crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; @@ -522,7 +526,7 @@ construct_runtime!( ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin}, Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config}, Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage}, - Inclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, + ParaInclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent}, Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage}, Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, @@ -799,58 +803,59 @@ impl_runtime_apis! { } } + #[api_version(8)] impl polkadot_primitives::runtime_api::ParachainHost for Runtime { - fn validators() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v5::validators::() + fn validators() -> Vec { + parachains_runtime_api_impl::validators::() } - fn validator_groups() -> (Vec>, polkadot_primitives::v5::GroupRotationInfo) { - polkadot_runtime_parachains::runtime_api_impl::v5::validator_groups::() + fn validator_groups() -> (Vec>, polkadot_primitives::GroupRotationInfo) { + parachains_runtime_api_impl::validator_groups::() } - fn availability_cores() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v5::availability_cores::() + fn availability_cores() -> Vec> { + parachains_runtime_api_impl::availability_cores::() } - fn persisted_validation_data(para_id: polkadot_primitives::v5::Id, assumption: polkadot_primitives::v5::OccupiedCoreAssumption) - -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v5::persisted_validation_data::(para_id, assumption) + fn persisted_validation_data(para_id: ParaId, assumption: polkadot_primitives::OccupiedCoreAssumption) + -> Option> { + parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption) } fn assumed_validation_data( - para_id: polkadot_primitives::v5::Id, + para_id: ParaId, expected_persisted_validation_data_hash: Hash, - ) -> Option<(polkadot_primitives::v5::PersistedValidationData, polkadot_primitives::v5::ValidationCodeHash)> { - polkadot_runtime_parachains::runtime_api_impl::v5::assumed_validation_data::( + ) -> Option<(polkadot_primitives::PersistedValidationData, polkadot_primitives::ValidationCodeHash)> { + parachains_runtime_api_impl::assumed_validation_data::( para_id, expected_persisted_validation_data_hash, ) } fn check_validation_outputs( - para_id: polkadot_primitives::v5::Id, - outputs: polkadot_primitives::v5::CandidateCommitments, + para_id: ParaId, + outputs: polkadot_primitives::CandidateCommitments, ) -> bool { - polkadot_runtime_parachains::runtime_api_impl::v5::check_validation_outputs::(para_id, outputs) + parachains_runtime_api_impl::check_validation_outputs::(para_id, outputs) } - fn session_index_for_child() -> polkadot_primitives::v5::SessionIndex { - polkadot_runtime_parachains::runtime_api_impl::v5::session_index_for_child::() + fn session_index_for_child() -> polkadot_primitives::SessionIndex { + parachains_runtime_api_impl::session_index_for_child::() } - fn validation_code(para_id: polkadot_primitives::v5::Id, assumption: polkadot_primitives::v5::OccupiedCoreAssumption) - -> Option { - polkadot_runtime_parachains::runtime_api_impl::v5::validation_code::(para_id, assumption) + fn validation_code(para_id: ParaId, assumption: polkadot_primitives::OccupiedCoreAssumption) + -> Option { + parachains_runtime_api_impl::validation_code::(para_id, assumption) } - fn candidate_pending_availability(para_id: polkadot_primitives::v5::Id) -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v5::candidate_pending_availability::(para_id) + fn candidate_pending_availability(para_id: ParaId) -> Option> { + parachains_runtime_api_impl::candidate_pending_availability::(para_id) } - fn candidate_events() -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v5::candidate_events::(|ev| { + fn candidate_events() -> Vec> { + parachains_runtime_api_impl::candidate_events::(|ev| { match ev { - RuntimeEvent::Inclusion(ev) => { + RuntimeEvent::ParaInclusion(ev) => { Some(ev) } _ => None, @@ -858,75 +863,99 @@ impl_runtime_apis! { }) } - fn session_info(index: polkadot_primitives::v5::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v5::session_info::(index) + fn session_info(index: polkadot_primitives::SessionIndex) -> Option { + parachains_runtime_api_impl::session_info::(index) } - fn dmq_contents(recipient: polkadot_primitives::v5::Id) -> Vec> { - polkadot_runtime_parachains::runtime_api_impl::v5::dmq_contents::(recipient) + fn session_executor_params(session_index: polkadot_primitives::SessionIndex) -> Option { + parachains_runtime_api_impl::session_executor_params::(session_index) } - fn inbound_hrmp_channels_contents( - recipient: polkadot_primitives::v5::Id - ) -> BTreeMap>> { - polkadot_runtime_parachains::runtime_api_impl::v5::inbound_hrmp_channels_contents::(recipient) + fn dmq_contents(recipient: ParaId) -> Vec> { + parachains_runtime_api_impl::dmq_contents::(recipient) } - fn validation_code_by_hash(hash: polkadot_primitives::v5::ValidationCodeHash) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v5::validation_code_by_hash::(hash) + fn inbound_hrmp_channels_contents( + recipient: ParaId + ) -> BTreeMap>> { + parachains_runtime_api_impl::inbound_hrmp_channels_contents::(recipient) } - fn on_chain_votes() -> Option> { - polkadot_runtime_parachains::runtime_api_impl::v5::on_chain_votes::() + fn validation_code_by_hash(hash: polkadot_primitives::ValidationCodeHash) -> Option { + parachains_runtime_api_impl::validation_code_by_hash::(hash) } - fn submit_pvf_check_statement(stmt: polkadot_primitives::v5::PvfCheckStatement, signature: polkadot_primitives::v5::ValidatorSignature) { - polkadot_runtime_parachains::runtime_api_impl::v5::submit_pvf_check_statement::(stmt, signature) + fn on_chain_votes() -> Option> { + parachains_runtime_api_impl::on_chain_votes::() } - fn pvfs_require_precheck() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v5::pvfs_require_precheck::() + fn submit_pvf_check_statement( + stmt: polkadot_primitives::PvfCheckStatement, + signature: polkadot_primitives::ValidatorSignature + ) { + parachains_runtime_api_impl::submit_pvf_check_statement::(stmt, signature) } - fn validation_code_hash(para_id: polkadot_primitives::v5::Id, assumption: polkadot_primitives::v5::OccupiedCoreAssumption) - -> Option - { - polkadot_runtime_parachains::runtime_api_impl::v5::validation_code_hash::(para_id, assumption) + fn pvfs_require_precheck() -> Vec { + parachains_runtime_api_impl::pvfs_require_precheck::() } - fn disputes() -> Vec<(polkadot_primitives::v5::SessionIndex, polkadot_primitives::v5::CandidateHash, polkadot_primitives::v5::DisputeState)> { - polkadot_runtime_parachains::runtime_api_impl::v5::get_session_disputes::() + fn validation_code_hash(para_id: ParaId, assumption: polkadot_primitives::OccupiedCoreAssumption) + -> Option + { + parachains_runtime_api_impl::validation_code_hash::(para_id, assumption) } - fn session_executor_params(session_index: polkadot_primitives::v5::SessionIndex) -> Option { - polkadot_runtime_parachains::runtime_api_impl::v5::session_executor_params::(session_index) + fn disputes() -> Vec<(polkadot_primitives::SessionIndex, polkadot_primitives::CandidateHash, polkadot_primitives::DisputeState)> { + parachains_runtime_api_impl::get_session_disputes::() } fn unapplied_slashes( - ) -> Vec<(polkadot_primitives::v5::SessionIndex, polkadot_primitives::v5::CandidateHash, polkadot_primitives::v5::slashing::PendingSlashes)> { - polkadot_runtime_parachains::runtime_api_impl::v5::unapplied_slashes::() + ) -> Vec<(polkadot_primitives::SessionIndex, polkadot_primitives::CandidateHash, polkadot_primitives::slashing::PendingSlashes)> { + parachains_runtime_api_impl::unapplied_slashes::() } fn key_ownership_proof( - _validator_id: polkadot_primitives::v5::ValidatorId, - ) -> Option { - unimplemented!("Not used at Rialto") + validator_id: polkadot_primitives::ValidatorId, + ) -> Option { + use codec::Encode; + + Historical::prove((polkadot_primitives::PARACHAIN_KEY_TYPE_ID, validator_id)) + .map(|p| p.encode()) + .map(polkadot_primitives::slashing::OpaqueKeyOwnershipProof::new) } fn submit_report_dispute_lost( - dispute_proof: polkadot_primitives::v5::slashing::DisputeProof, - key_ownership_proof: polkadot_primitives::v5::slashing::OpaqueKeyOwnershipProof, + dispute_proof: polkadot_primitives::slashing::DisputeProof, + key_ownership_proof: polkadot_primitives::slashing::OpaqueKeyOwnershipProof, ) -> Option<()> { - polkadot_runtime_parachains::runtime_api_impl::v5::submit_unsigned_slashing_report::( + parachains_runtime_api_impl::submit_unsigned_slashing_report::( dispute_proof, key_ownership_proof, ) } + + fn minimum_backing_votes() -> u32 { + parachains_runtime_api_impl::minimum_backing_votes::() + } + + fn para_backing_state(para_id: ParaId) -> Option { + parachains_runtime_api_impl::backing_state::(para_id) + } + + fn async_backing_params() -> polkadot_primitives::AsyncBackingParams { + parachains_runtime_api_impl::async_backing_params::() + } + + fn disabled_validators() -> Vec { + parachains_staging_runtime_api_impl::disabled_validators::() + } + } impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { fn authorities() -> Vec { - polkadot_runtime_parachains::runtime_api_impl::v5::relevant_authority_ids::() + parachains_runtime_api_impl::relevant_authority_ids::() } } diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs index aba204af7cf65..972edbf35286e 100644 --- a/bin/rialto/runtime/src/parachains.rs +++ b/bin/rialto/runtime/src/parachains.rs @@ -28,7 +28,7 @@ use frame_support::{ weights::{Weight, WeightMeter}, }; use frame_system::EnsureRoot; -use polkadot_primitives::v5::{ValidatorId, ValidatorIndex}; +use polkadot_primitives::v6::{ValidatorId, ValidatorIndex}; use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; use polkadot_runtime_parachains::{ configuration as parachains_configuration, disputes as parachains_disputes, @@ -118,8 +118,9 @@ impl parachains_paras::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = ParasWeightInfo; type UnsignedPriority = ParasUnsignedPriority; - type QueueFootprinter = crate::Inclusion; + type QueueFootprinter = crate::ParaInclusion; type NextSessionRotation = Babe; + type OnNewHead = Registrar; } /// Test weight for the `Paras` pallet. @@ -234,7 +235,7 @@ impl pallet_message_queue::Config for Runtime { #[cfg(feature = "runtime-benchmarks")] type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor; - type QueueChangeHandler = crate::Inclusion; + type QueueChangeHandler = crate::ParaInclusion; type WeightInfo = (); type QueuePausedQuery = (); } diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 0f5bd0a546dc8..37f9bf96d57f6 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -35,7 +35,7 @@ sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" bp-test-utils = { path = "../../primitives/test-utils" } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-beefy/std", "bp-runtime/std", @@ -49,7 +49,4 @@ std = [ "sp-runtime/std", "sp-std/std", ] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", -] +try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] diff --git a/modules/parachains/README.md b/modules/parachains/README.md index d3f52c791ab58..9ca6080383443 100644 --- a/modules/parachains/README.md +++ b/modules/parachains/README.md @@ -9,15 +9,15 @@ to verify storage proofs, generated at the bridged relay chain. ## A Brief Introduction into Parachains Finality -You can find detailed information on parachains finality in the [Polkadot](https://github.com/paritytech/polkadot) -and [Cumulus](https://github.com/paritytech/cumulus) repositories. This section gives a brief overview of how -the parachain finality works and how to build a light client for a parachain. +You can find detailed information on parachains finality in the +[Polkadot-SDK](https://github.com/paritytech/polkadot-sdk) repository. This section gives a brief overview of how the +parachain finality works and how to build a light client for a parachain. The main thing there is that the parachain generates blocks on its own, but it can't achieve finality without help of its relay chain. Instead, the parachain collators create a block and hand it over to the relay chain validators. Validators validate the block and register the new parachain head in the -[`Heads` map](https://github.com/paritytech/polkadot/blob/88013730166ba90745ae7c9eb3e0c1be1513c7cc/runtime/parachains/src/paras/mod.rs#L645) -of the [`paras`](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) pallet, +[`Heads` map](https://github.com/paritytech/polkadot-sdk/blob/bc5005217a8c2e7c95b9011c96d7e619879b1200/polkadot/runtime/parachains/src/paras/mod.rs#L683-L686) +of the [`paras`](https://github.com/paritytech/polkadot-sdk/tree/master/polkadot/runtime/parachains/src/paras) pallet, deployed at the relay chain. Keep in mind that this pallet, deployed at a relay chain, is **NOT** a bridge pallet, even though the names are similar. diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index a30b88890adc8..14f6bdc10c8e5 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -25,7 +25,7 @@ sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk", branch sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = ["std"] +default = [ "std" ] std = [ "codec/std", "frame-support/std", @@ -35,7 +35,4 @@ std = [ "sp-staking/std", "sp-std/std", ] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", -] +try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/modules/xcm-bridge-hub-router/src/benchmarking.rs index 4bbe414f66355..c4d1e3971e747 100644 --- a/modules/xcm-bridge-hub-router/src/benchmarking.rs +++ b/modules/xcm-bridge-hub-router/src/benchmarking.rs @@ -60,6 +60,8 @@ benchmarks_instance_pallet! { is_congested: false, delivery_fee_factor: MINIMAL_DELIVERY_FEE_FACTOR + MINIMAL_DELIVERY_FEE_FACTOR, }); + + let _ = T::ensure_bridged_target_destination(); T::make_congested(); }: { crate::Pallet::::on_initialize(Zero::zero()) @@ -79,11 +81,11 @@ benchmarks_instance_pallet! { } send_message { - // make local queue congested, because it means additional db write - T::make_congested(); - let dest = T::ensure_bridged_target_destination(); let xcm = sp_std::vec![].into(); + + // make local queue congested, because it means additional db write + T::make_congested(); }: { send_xcm::>(dest, xcm).expect("message is sent") } diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 58df21a6d9016..2152b4eb28f33 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -27,7 +27,7 @@ use sp_runtime::{ BuildStorage, }; use xcm::prelude::*; -use xcm_builder::NetworkExportTable; +use xcm_builder::{NetworkExportTable, NetworkExportTableItem}; pub type AccountId = u64; type Block = frame_system::mocking::MockBlock; @@ -53,8 +53,15 @@ parameter_types! { pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(ThisNetworkId::get()), Parachain(1000)); pub SiblingBridgeHubLocation: MultiLocation = ParentThen(X1(Parachain(1002))).into(); pub BridgeFeeAsset: AssetId = MultiLocation::parent().into(); - pub BridgeTable: Vec<(NetworkId, MultiLocation, Option)> - = vec![(BridgedNetworkId::get(), SiblingBridgeHubLocation::get(), Some((BridgeFeeAsset::get(), BASE_FEE).into()))]; + pub BridgeTable: Vec + = vec![ + NetworkExportTableItem::new( + BridgedNetworkId::get(), + None, + SiblingBridgeHubLocation::get(), + Some((BridgeFeeAsset::get(), BASE_FEE).into()) + ) + ]; } impl frame_system::Config for TestRuntime { diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 2d89bfaacae25..6c6e66afedf0b 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-runtime/std", "codec/std", @@ -37,5 +37,5 @@ std = [ "serde/std", "sp-consensus-beefy/std", "sp-runtime/std", - "sp-std/std" + "sp-std/std", ] diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/primitives/chain-asset-hub-rococo/Cargo.toml new file mode 100644 index 0000000000000..d5e4328893dbf --- /dev/null +++ b/primitives/chain-asset-hub-rococo/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "bp-asset-hub-rococo" +description = "Primitives of AssetHubRococo parachain runtime." +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } + +# Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +# Bridge Dependencies +bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } + +[features] +default = [ "std" ] +std = [ + "bp-xcm-bridge-hub-router/std", + "codec/std", + "frame-support/std", + "scale-info/std", +] diff --git a/primitives/chain-asset-hub-rococo/src/lib.rs b/primitives/chain-asset-hub-rococo/src/lib.rs new file mode 100644 index 0000000000000..f1ea1e9c88c9a --- /dev/null +++ b/primitives/chain-asset-hub-rococo/src/lib.rs @@ -0,0 +1,52 @@ +// Copyright (C) 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 . + +//! Module with configuration which reflects AssetHubRococo runtime setup. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; + +/// `AssetHubRococo` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `AssetHubRococo` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `AssetHubRococo` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// `ToWococoXcmRouter` bridge pallet. + #[codec(index = 43)] + ToWococoXcmRouter(XcmBridgeHubRouterCall), +} + +frame_support::parameter_types! { + /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. + pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); + + /// Base delivery fee to `BridgeHubRococo`. + /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) + pub const BridgeHubRococoBaseFeeInRocs: u128 = 1214739988; +} + +/// Identifier of AssetHubRococo in the Rococo relay chain. +pub const ASSET_HUB_ROCOCO_PARACHAIN_ID: u32 = 1000; diff --git a/primitives/chain-asset-hub-wococo/Cargo.toml b/primitives/chain-asset-hub-wococo/Cargo.toml new file mode 100644 index 0000000000000..5120bd2b43140 --- /dev/null +++ b/primitives/chain-asset-hub-wococo/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "bp-asset-hub-wococo" +description = "Primitives of AssetHubWococo parachain runtime." +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } + +# Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +# Bridge Dependencies +bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } + +[features] +default = [ "std" ] +std = [ + "bp-xcm-bridge-hub-router/std", + "codec/std", + "frame-support/std", + "scale-info/std", +] diff --git a/primitives/chain-asset-hub-wococo/src/lib.rs b/primitives/chain-asset-hub-wococo/src/lib.rs new file mode 100644 index 0000000000000..5ce66054d64aa --- /dev/null +++ b/primitives/chain-asset-hub-wococo/src/lib.rs @@ -0,0 +1,52 @@ +// Copyright (C) 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 . + +//! Module with configuration which reflects AssetHubWococo runtime setup. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; + +/// `AssetHubWococo` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `AssetHubWococo` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `AssetHubWococo` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// `ToRococoXcmRouter` bridge pallet. + #[codec(index = 44)] + ToRococoXcmRouter(XcmBridgeHubRouterCall), +} + +frame_support::parameter_types! { + /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. + pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); + + /// Base delivery fee to `BridgeHubWococo`. + /// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) + pub const BridgeHubWococoBaseFeeInWocs: u128 = 1214739988; +} + +/// Identifier of AssetHubWococo in the Wococo relay chain. +pub const ASSET_HUB_WOCOCO_PARACHAIN_ID: u32 = 1000; diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index a50bda23ac8d3..6da5cd3818fe4 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -74,5 +74,8 @@ pub const WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessa /// chains. pub const WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; +/// Pallet index of `BridgeWococoMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_WOCOCO_MESSAGES_PALLET_INDEX: u8 = 46; + decl_bridge_finality_runtime_apis!(bridge_hub_rococo); decl_bridge_messages_runtime_apis!(bridge_hub_rococo); diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index ce4600f5ff35d..0c7717368042a 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -68,5 +68,8 @@ pub const WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessa /// chains. pub const WITH_BRIDGE_HUB_WOCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; +/// Pallet index of `BridgeRococoMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45; + decl_bridge_finality_runtime_apis!(bridge_hub_wococo); decl_bridge_messages_runtime_apis!(bridge_hub_wococo); diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 220e8d657e705..4efdf667ac8b0 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -38,7 +38,7 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-beefy/std", "bp-header-chain/std", diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml index 0963aa0776e92..0122c508e2b92 100644 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ b/primitives/chain-rialto-parachain/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml index a588320af9396..083abbd545840 100644 --- a/primitives/chain-rialto/Cargo.toml +++ b/primitives/chain-rialto/Cargo.toml @@ -24,7 +24,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-messages/std", diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index c6712857dd691..abc04224dcac9 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = ["std"] +default = [ "std" ] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs index a72feecdae827..90464335166e8 100644 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ b/relays/bin-substrate/src/cli/register_parachain.rs @@ -103,8 +103,8 @@ impl RegisterParachain { let para_id: ParaId = relay_client .storage_value(StorageKey(para_id_key.to_vec()), None) .await? - .unwrap_or(polkadot_primitives::v5::LOWEST_PUBLIC_ID) - .max(polkadot_primitives::v5::LOWEST_PUBLIC_ID); + .unwrap_or(polkadot_primitives::v6::LOWEST_PUBLIC_ID) + .max(polkadot_primitives::v6::LOWEST_PUBLIC_ID); log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id From b9f07286d936151fd736c6342c7a334f5ecf0049 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 01:28:52 +0000 Subject: [PATCH 1131/1210] Bump thiserror from 1.0.49 to 1.0.50 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.49 to 1.0.50. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.49...1.0.50) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 7fdd18f226e78..2fd3fff09f998 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -16,7 +16,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.9.0", features = ["derive"] } tokio = { version = "1.33", features = ["rt-multi-thread"] } -thiserror = "1.0.49" +thiserror = "1.0.50" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 22e957895a0c0..2d5f58af224eb 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.49" +thiserror = "1.0.50" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ccdb822205115..a66ba99600959 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.33", features = ["rt"] } -thiserror = "1.0.49" +thiserror = "1.0.50" # Bridge dependencies From 482a5d78b4805151f02abab5458aab0d575300bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 01:29:33 +0000 Subject: [PATCH 1132/1210] Bump scale-info from 2.9.0 to 2.10.0 Bumps [scale-info](https://github.com/paritytech/scale-info) from 2.9.0 to 2.10.0. - [Release notes](https://github.com/paritytech/scale-info/releases) - [Changelog](https://github.com/paritytech/scale-info/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/scale-info/compare/v2.9.0...v2.10.0) --- updated-dependencies: - dependency-name: scale-info dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/millau/runtime/Cargo.toml | 2 +- bin/rialto-parachain/runtime/Cargo.toml | 2 +- bin/rialto/runtime/Cargo.toml | 2 +- bin/runtime-common/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/shift-session-manager/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/chain-asset-hub-kusama/Cargo.toml | 2 +- primitives/chain-asset-hub-polkadot/Cargo.toml | 2 +- primitives/chain-millau/Cargo.toml | 2 +- primitives/chain-polkadot-bulletin/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/xcm-bridge-hub-router/Cargo.toml | 2 +- relays/client-bridge-hub-kusama/Cargo.toml | 2 +- relays/client-bridge-hub-polkadot/Cargo.toml | 2 +- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-wococo/Cargo.toml | 2 +- relays/client-kusama/Cargo.toml | 2 +- relays/client-polkadot-bulletin/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rialto-parachain/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index 302a04d024420..7e963d6b74d0b 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] hex-literal = "0.4" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index bc4f8fb4d5c70..0715e7a2927ae 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -12,7 +12,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", b [dependencies] codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} hex-literal = "0.4" -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge depedencies diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 2bdadfd0cde70..5ef7d53bed4a1 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index ee3dd4be05c6c..e94d886006e89 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 37f9bf96d57f6..97fb6c7237e48 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 34bd76fd103e5..6569fe9c400b7 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -12,7 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 582b9dd8c150c..e24cab3e587bb 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 7a77d7653135d..b9d5c0e6d33e9 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 6cbfd6ee3cb30..6e00ee99cebb7 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml index 14f6bdc10c8e5..e70dd6ace16e4 100644 --- a/modules/shift-session-manager/Cargo.toml +++ b/modules/shift-session-manager/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 49a796516c067..314c7526fc4e1 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.8.0", default-features = false, features = ["bit-vec", "derive", "serde"] } +scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 6c6e66afedf0b..1a2870997379c 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge Dependencies diff --git a/primitives/chain-asset-hub-kusama/Cargo.toml b/primitives/chain-asset-hub-kusama/Cargo.toml index c40561347bfc0..5c8ccf3d0fca3 100644 --- a/primitives/chain-asset-hub-kusama/Cargo.toml +++ b/primitives/chain-asset-hub-kusama/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/chain-asset-hub-polkadot/Cargo.toml b/primitives/chain-asset-hub-polkadot/Cargo.toml index e23ed5c5e2468..9c302f72d162f 100644 --- a/primitives/chain-asset-hub-polkadot/Cargo.toml +++ b/primitives/chain-asset-hub-polkadot/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml index 4efdf667ac8b0..5ea9d36f9f7b1 100644 --- a/primitives/chain-millau/Cargo.toml +++ b/primitives/chain-millau/Cargo.toml @@ -16,7 +16,7 @@ hash256-std-hasher = { version = "0.15.2", default-features = false } impl-codec = { version = "0.6", default-features = false } impl-serde = { version = "0.4.0", default-features = false } parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge Dependencies diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index 1cabe968da01b..597145d683c2e 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 66b290917f304..03c998989937e 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 8cad58f44a8e7..c608fcf33c24f 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Bridge dependencies diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index adabcf29fd650..95ce8d50f70c1 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 194ef3535b8da..513b46098c621 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 54b86deb34fc8..db381836e98ac 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 6872ffd98486b..dc5793e3aa0d2 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -12,7 +12,7 @@ hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" log = { version = "0.4.19", default-features = false } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } # Substrate Dependencies diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index 63c66a945edbb..9454a3efd1c73 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.9.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index c52e708f656d5..2eb175a2a8b0b 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index f071778446d84..3976652215a49 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } relay-substrate-client = { path = "../client-substrate" } # Bridge dependencies diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index d4bd0e151ae39..f6fe83e1c556c 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index e8c8a015fa980..b60e8c0e87216 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index be03225b7b4c0..fee0db14a511b 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml index 6694f3c761f72..29118d41364c2 100644 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 224227c63b7e8..58a7b058f0ec9 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml index 93bad81cd75ff..fc91e27ee0f82 100644 --- a/relays/client-rialto-parachain/Cargo.toml +++ b/relays/client-rialto-parachain/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5" } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 5cccefa50e063..b6d603d436482 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 2fd3fff09f998..5e8fde7a23b09 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,7 +14,7 @@ jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = "0.4.20" num-traits = "0.2" rand = "0.8" -scale-info = { version = "2.9.0", features = ["derive"] } +scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.33", features = ["rt-multi-thread"] } thiserror = "1.0.50" From bd4b2079ba92f7e59c8f06cee55c05df89bd7ec4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 27 Oct 2023 16:45:53 +0300 Subject: [PATCH 1133/1210] Port #2648 to polkadot-staging (#2651) * Deposit event when relayer reward is registered (#2648) * RewardRegistered event * test it * fix compilation --- modules/relayers/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/modules/relayers/src/lib.rs b/modules/relayers/src/lib.rs index b9b98ca7e253f..ce66c9df48e01 100644 --- a/modules/relayers/src/lib.rs +++ b/modules/relayers/src/lib.rs @@ -325,6 +325,12 @@ pub mod pallet { rewards_account_params, new_reward, ); + + Self::deposit_event(Event::::RewardRegistered { + relayer: relayer.clone(), + rewards_account_params, + reward, + }); }, ); } @@ -369,6 +375,15 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { + /// Relayer reward has been registered and may be claimed later. + RewardRegistered { + /// Relayer account that can claim reward. + relayer: T::AccountId, + /// Relayer can claim reward from this account. + rewards_account_params: RewardsAccountParams, + /// Reward amount. + reward: T::Reward, + }, /// Reward has been paid to the relayer. RewardPaid { /// Relayer account that has been rewarded. @@ -455,7 +470,7 @@ mod tests { use super::*; use mock::{RuntimeEvent as TestEvent, *}; - use crate::Event::RewardPaid; + use crate::Event::{RewardPaid, RewardRegistered}; use bp_messages::LaneId; use bp_relayers::RewardsAccountOwner; use frame_support::{ @@ -470,6 +485,33 @@ mod tests { System::::reset_events(); } + #[test] + fn register_relayer_reward_emit_event() { + run_test(|| { + get_ready_for_events(); + + Pallet::::register_relayer_reward( + TEST_REWARDS_ACCOUNT_PARAMS, + ®ULAR_RELAYER, + 100, + ); + + // Check if the `RewardRegistered` event was emitted. + assert_eq!( + System::::events().last(), + Some(&EventRecord { + phase: Phase::Initialization, + event: TestEvent::Relayers(RewardRegistered { + relayer: REGULAR_RELAYER, + rewards_account_params: TEST_REWARDS_ACCOUNT_PARAMS, + reward: 100 + }), + topics: vec![], + }), + ); + }); + } + #[test] fn root_cant_claim_anything() { run_test(|| { From b7aaa1c7b4e98f63b56cc0c0fa286933f8f14f5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 02:36:55 +0000 Subject: [PATCH 1134/1210] Bump futures from 0.3.28 to 0.3.29 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.28 to 0.3.29. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.28...0.3.29) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/equivocation/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 88175ba6993bd..d661a255e3eff 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -10,7 +10,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.4.6", features = ["derive"] } -futures = "0.3.28" +futures = "0.3.29" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.107" diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 795d91326a157..3e822a9bb6ca8 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.28" +futures = "0.3.29" hex = "0.4" log = "0.4.20" num-format = "0.4" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 5e8fde7a23b09..c107ae6fa45f4 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.28" +futures = "0.3.29" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = "0.4.20" num-traits = "0.2" diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index ff94e73709114..d14177bacec8c 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -12,7 +12,7 @@ async-trait = "0.1" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -futures = "0.3.28" +futures = "0.3.29" log = "0.4.20" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 7fcd08ef6f5f8..725ac5386b1b4 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -11,7 +11,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } -futures = "0.3.28" +futures = "0.3.29" log = "0.4.20" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 2d5f58af224eb..6fe3c02cbca82 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,7 @@ thiserror = "1.0.50" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.28" +futures = "0.3.29" hex = "0.4" num-traits = "0.2" log = "0.4.20" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 9df36b2f0320c..ccaed009a5ab4 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" env_logger = "0.10" -futures = "0.3.28" +futures = "0.3.29" hex = "0.4" log = "0.4.20" num-traits = "0.2" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index fcd962f1038a1..89aab19b4b556 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] async-std = "1.6.5" async-trait = "0.1.74" -futures = "0.3.28" +futures = "0.3.29" log = "0.4.20" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index a66ba99600959..e39cf8cdacbf7 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -13,7 +13,7 @@ async-trait = "0.1" backoff = "0.4" isahc = "1.2" env_logger = "0.10.0" -futures = "0.3.28" +futures = "0.3.29" jsonpath_lib = "0.3" log = "0.4.20" num-traits = "0.2" From 40d690e7986fd9e30ab249d81c878ed754332df9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 06:14:26 +0000 Subject: [PATCH 1135/1210] Bump clap from 4.4.6 to 4.4.7 Bumps [clap](https://github.com/clap-rs/clap) from 4.4.6 to 4.4.7. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.6...v4.4.7) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index d661a255e3eff..add3527df3e1f 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.6", features = ["derive"] } +clap = { version = "4.4.7", features = ["derive"] } futures = "0.3.29" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.107" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index d83ed44c32176..c3646df4cf55d 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = [ 'rialto-parachain-runtime/runtime-benchmarks' ] [dependencies] -clap = { version = "4.4.6", features = ["derive"] } +clap = { version = "4.4.7", features = ["derive"] } log = '0.4.20' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 06352a1377951..882ce89e8e0ce 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.6", features = ["derive"] } +clap = { version = "4.4.7", features = ["derive"] } serde_json = "1.0.107" # Bridge dependencies From d62648b9ad6702ffd0856d608ecaae13006f0c5d Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 31 Oct 2023 09:28:51 +0100 Subject: [PATCH 1136/1210] Add Rococo<>Westend bridge support/relay (#2647) * Added Rococo<>Westend primitives * Latest fashion * WIP * Temporary hack for AssetHubWestend to Millau * typo * tool/runtime-codegen tweaks * Rococo<>Westend relay part * zepter * Unify `Parachain` vs `Parachains` --- bin/millau/runtime/src/lib.rs | 52 +- modules/beefy/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/src/lib.rs | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/chain-asset-hub-rococo/Cargo.toml | 2 +- primitives/chain-asset-hub-rococo/src/lib.rs | 7 +- primitives/chain-asset-hub-westend/Cargo.toml | 26 + primitives/chain-asset-hub-westend/src/lib.rs | 52 + primitives/chain-asset-hub-wococo/Cargo.toml | 2 +- primitives/chain-asset-hub-wococo/src/lib.rs | 4 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 5 +- .../chain-bridge-hub-westend/Cargo.toml | 34 + .../chain-bridge-hub-westend/src/lib.rs | 75 + primitives/chain-bridge-hub-wococo/src/lib.rs | 2 +- primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-westend/src/lib.rs | 50 +- primitives/runtime/src/lib.rs | 3 + relays/bin-substrate/Cargo.toml | 1 + relays/bin-substrate/src/bridges/mod.rs | 1 + ...b_rococo_messages_to_bridge_hub_westend.rs | 64 + ...b_westend_messages_to_bridge_hub_rococo.rs | 64 + .../src/bridges/rococo_westend/mod.rs | 24 + .../rococo_headers_to_bridge_hub_westend.rs | 96 + ...rococo_parachains_to_bridge_hub_westend.rs | 75 + .../westend_headers_to_bridge_hub_rococo.rs | 96 + ...westend_parachains_to_bridge_hub_rococo.rs | 75 + .../rococo_parachains_to_bridge_hub_wococo.rs | 2 +- .../wococo_parachains_to_bridge_hub_rococo.rs | 2 +- .../westend_parachains_to_millau.rs | 37 +- relays/bin-substrate/src/chains/millau.rs | 8 + relays/bin-substrate/src/chains/westend.rs | 8 +- relays/bin-substrate/src/cli/bridge.rs | 2 + relays/bin-substrate/src/cli/init_bridge.rs | 36 + .../src/cli/relay_headers_and_messages/mod.rs | 49 + .../bin-substrate/src/cli/relay_messages.rs | 10 + .../bin-substrate/src/cli/relay_parachains.rs | 12 + .../src/codegen_runtime.rs | 32 +- relays/client-bridge-hub-westend/Cargo.toml | 34 + relays/client-bridge-hub-westend/src/lib.rs | 162 + .../src/runtime_wrapper.rs | 116 + relays/client-bridge-hub-wococo/Cargo.toml | 1 - relays/client-rococo/src/lib.rs | 2 +- relays/client-westend/Cargo.toml | 12 +- relays/client-westend/src/codegen_runtime.rs | 6945 +++++++++++++++++ relays/client-westend/src/lib.rs | 86 +- relays/client-wococo/src/lib.rs | 2 +- 46 files changed, 8277 insertions(+), 99 deletions(-) create mode 100644 primitives/chain-asset-hub-westend/Cargo.toml create mode 100644 primitives/chain-asset-hub-westend/src/lib.rs create mode 100644 primitives/chain-bridge-hub-westend/Cargo.toml create mode 100644 primitives/chain-bridge-hub-westend/src/lib.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/mod.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs create mode 100644 relays/client-bridge-hub-westend/Cargo.toml create mode 100644 relays/client-bridge-hub-westend/src/lib.rs create mode 100644 relays/client-bridge-hub-westend/src/runtime_wrapper.rs create mode 100644 relays/client-westend/src/codegen_runtime.rs diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index 27f00c801bc4d..a349551a873c0 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -568,7 +568,7 @@ impl pallet_bridge_parachains::Config for Runtime type BridgesGrandpaPalletInstance = WestendGrandpaInstance; type ParasPalletName = WestendParasPalletName; type ParaStoredHeaderDataBuilder = - SingleParaStoredHeaderDataBuilder; + SingleParaStoredHeaderDataBuilder; type HeadsToKeep = ConstU32<1024>; type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; } @@ -974,12 +974,12 @@ impl_runtime_apis! { } } - impl bp_westend::AssetHubWestendFinalityApi for Runtime { + impl bp_bridged_chain::AssetHubWestendFinalityApi for Runtime { fn best_finalized() -> Option> { pallet_bridge_parachains::Pallet::< Runtime, WithWestendParachainsInstance, - >::best_parachain_head_id::().unwrap_or(None) + >::best_parachain_head_id::().unwrap_or(None) } } @@ -1252,3 +1252,49 @@ mod tests { assert!(core::mem::size_of::() <= MAX_CALL_SIZE); } } + +/// TODO: Note: I know this does not belong here, but I don't want to add it to the +/// `chain-asset-hub-westend` or `chain-westend`, because we wont use it for production and I don't +/// want to bring this to the bridges subtree now. Anyway, we plan to retire millau/rialto, so this +/// hack will disappear with that. +pub mod bp_bridged_chain { + use bp_messages::Weight; + pub use bp_polkadot_core::{ + AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, + Hasher, Hashing, Header, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, + EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, + }; + use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; + + /// `AssetHubWestend` parachain definition + #[derive(Debug, Clone, Copy)] + pub struct AssetHubWestend; + + // AssetHubWestend seems to use the same configuration as all Polkadot-like chains, so we'll use + // Westend primitives here. + impl Chain for AssetHubWestend { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + bp_westend::Westend::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_westend::Westend::max_extrinsic_weight() + } + } + + impl Parachain for AssetHubWestend { + const PARACHAIN_ID: u32 = 1000; + } + + decl_bridge_finality_runtime_apis!(AssetHubWestend); +} diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 97fb6c7237e48..5d699019e63ec 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs index 5cf94fc83fd9d..cf51ef82412fb 100644 --- a/modules/xcm-bridge-hub-router/src/lib.rs +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -335,7 +335,7 @@ impl, I: 'static> SendXcm for Pallet { // just use exporter to validate destination and insert instructions to pay message fee // at the sibling/child bridge hub // - // the cost will include both cost of: (1) to-sibling bridg hub delivery (returned by + // the cost will include both cost of: (1) to-sibling bridge hub delivery (returned by // the `Config::ToBridgeHubSender`) and (2) to-bridged bridge hub delivery (returned by // `Self::exporter_for`) ViaBridgeHubExporter::::validate(dest, xcm) diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 1a2870997379c..09ff1fdb1fbcf 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/primitives/chain-asset-hub-rococo/Cargo.toml index d5e4328893dbf..de9cd8b0d8060 100644 --- a/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/primitives/chain-asset-hub-rococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/chain-asset-hub-rococo/src/lib.rs b/primitives/chain-asset-hub-rococo/src/lib.rs index f1ea1e9c88c9a..1a08ade2f4f2f 100644 --- a/primitives/chain-asset-hub-rococo/src/lib.rs +++ b/primitives/chain-asset-hub-rococo/src/lib.rs @@ -37,6 +37,9 @@ pub enum Call { /// `ToWococoXcmRouter` bridge pallet. #[codec(index = 43)] ToWococoXcmRouter(XcmBridgeHubRouterCall), + /// `ToWestendXcmRouter` bridge pallet. + #[codec(index = 45)] + ToWestendXcmRouter(XcmBridgeHubRouterCall), } frame_support::parameter_types! { @@ -44,8 +47,8 @@ frame_support::parameter_types! { pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); /// Base delivery fee to `BridgeHubRococo`. - /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) - pub const BridgeHubRococoBaseFeeInRocs: u128 = 1214739988; + /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const BridgeHubRococoBaseFeeInRocs: u128 = 1624803349; } /// Identifier of AssetHubRococo in the Rococo relay chain. diff --git a/primitives/chain-asset-hub-westend/Cargo.toml b/primitives/chain-asset-hub-westend/Cargo.toml new file mode 100644 index 0000000000000..5ed968763550c --- /dev/null +++ b/primitives/chain-asset-hub-westend/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "bp-asset-hub-westend" +description = "Primitives of AssetHubWestend parachain runtime." +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } + +# Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +# Bridge Dependencies +bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } + +[features] +default = [ "std" ] +std = [ + "bp-xcm-bridge-hub-router/std", + "codec/std", + "frame-support/std", + "scale-info/std", +] diff --git a/primitives/chain-asset-hub-westend/src/lib.rs b/primitives/chain-asset-hub-westend/src/lib.rs new file mode 100644 index 0000000000000..c943dc320b76a --- /dev/null +++ b/primitives/chain-asset-hub-westend/src/lib.rs @@ -0,0 +1,52 @@ +// Copyright (C) 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 . + +//! Module with configuration which reflects AssetHubWestend runtime setup. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; + +/// `AssetHubWestend` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `AssetHubWestend` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `AssetHubWestend` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + /// `ToRococoXcmRouter` bridge pallet. + #[codec(index = 34)] + ToRococoXcmRouter(XcmBridgeHubRouterCall), +} + +frame_support::parameter_types! { + /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. + pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); + + /// Base delivery fee to `BridgeHubWestend`. + /// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const BridgeHubWestendBaseFeeInWocs: u128 = 1624803349; +} + +/// Identifier of AssetHubWestend in the Westend relay chain. +pub const ASSET_HUB_WESTEND_PARACHAIN_ID: u32 = 1000; diff --git a/primitives/chain-asset-hub-wococo/Cargo.toml b/primitives/chain-asset-hub-wococo/Cargo.toml index 5120bd2b43140..d56205c3a1257 100644 --- a/primitives/chain-asset-hub-wococo/Cargo.toml +++ b/primitives/chain-asset-hub-wococo/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/chain-asset-hub-wococo/src/lib.rs b/primitives/chain-asset-hub-wococo/src/lib.rs index 5ce66054d64aa..809e56934e96e 100644 --- a/primitives/chain-asset-hub-wococo/src/lib.rs +++ b/primitives/chain-asset-hub-wococo/src/lib.rs @@ -44,8 +44,8 @@ frame_support::parameter_types! { pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); /// Base delivery fee to `BridgeHubWococo`. - /// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) - pub const BridgeHubWococoBaseFeeInWocs: u128 = 1214739988; + /// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const BridgeHubWococoBaseFeeInWocs: u128 = 1624803349; } /// Identifier of AssetHubWococo in the Wococo relay chain. diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 6da5cd3818fe4..039d681951cd1 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -75,7 +75,10 @@ pub const WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessa pub const WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; /// Pallet index of `BridgeWococoMessages: pallet_bridge_messages::`. -pub const WITH_BRIDGE_WOCOCO_MESSAGES_PALLET_INDEX: u8 = 46; +pub const WITH_BRIDGE_ROCOCO_TO_WOCOCO_MESSAGES_PALLET_INDEX: u8 = 46; + +/// Pallet index of `BridgeWestendMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 51; decl_bridge_finality_runtime_apis!(bridge_hub_rococo); decl_bridge_messages_runtime_apis!(bridge_hub_rococo); diff --git a/primitives/chain-bridge-hub-westend/Cargo.toml b/primitives/chain-bridge-hub-westend/Cargo.toml new file mode 100644 index 0000000000000..f425e7dbdbeb8 --- /dev/null +++ b/primitives/chain-bridge-hub-westend/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "bp-bridge-hub-westend" +description = "Primitives of BridgeHubWestend parachain runtime." +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Bridge Dependencies + +bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } + +# Substrate Based Dependencies + +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +[features] +default = [ "std" ] +std = [ + "bp-bridge-hub-cumulus/std", + "bp-messages/std", + "bp-runtime/std", + "frame-support/std", + "sp-api/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/primitives/chain-bridge-hub-westend/src/lib.rs b/primitives/chain-bridge-hub-westend/src/lib.rs new file mode 100644 index 0000000000000..a52e328b68753 --- /dev/null +++ b/primitives/chain-bridge-hub-westend/src/lib.rs @@ -0,0 +1,75 @@ +// Copyright (C) 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 . + +//! Module with configuration which reflects BridgeHubWestend runtime setup +//! (AccountId, Headers, Hashes...) + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use bp_bridge_hub_cumulus::*; +use bp_messages::*; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, +}; +use frame_support::dispatch::DispatchClass; +use sp_runtime::RuntimeDebug; + +/// BridgeHubWestend parachain. +#[derive(RuntimeDebug)] +pub struct BridgeHubWestend; + +impl Chain for BridgeHubWestend { + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; + + type AccountId = AccountId; + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; + + fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) + } + + fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) + } +} + +impl Parachain for BridgeHubWestend { + const PARACHAIN_ID: u32 = BRIDGE_HUB_WESTEND_PARACHAIN_ID; +} + +/// Identifier of BridgeHubWestend in the Westend relay chain. +pub const BRIDGE_HUB_WESTEND_PARACHAIN_ID: u32 = 1002; + +/// Name of the With-BridgeHubWestend messages pallet instance that is deployed at bridged chains. +pub const WITH_BRIDGE_HUB_WESTEND_MESSAGES_PALLET_NAME: &str = "BridgeWestendMessages"; + +/// Name of the With-BridgeHubWestend bridge-relayers pallet instance that is deployed at bridged +/// chains. +pub const WITH_BRIDGE_HUB_WESTEND_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; + +/// Pallet index of `BridgeRococoMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 44; + +decl_bridge_finality_runtime_apis!(bridge_hub_westend); +decl_bridge_messages_runtime_apis!(bridge_hub_westend); diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 0c7717368042a..750a8f7ecb9dd 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -69,7 +69,7 @@ pub const WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessa pub const WITH_BRIDGE_HUB_WOCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; /// Pallet index of `BridgeRococoMessages: pallet_bridge_messages::`. -pub const WITH_BRIDGE_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45; +pub const WITH_BRIDGE_WOCOCO_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45; decl_bridge_finality_runtime_apis!(bridge_hub_wococo); decl_bridge_messages_runtime_apis!(bridge_hub_wococo); diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 49a98747acbf6..29ac59dd3ed20 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false } # Substrate Based Dependencies +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] default = [ "std" ] diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 11182e9aefe97..45c13d600601f 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// Copyright (C) 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 @@ -21,9 +21,8 @@ pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; -use frame_support::weights::Weight; -use sp_std::prelude::*; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use frame_support::{parameter_types, weights::Weight}; /// Westend Chain pub struct Westend; @@ -57,53 +56,24 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; } -/// `AssetHubWestend` parachain definition -#[derive(Debug, Clone, Copy)] -pub struct AssetHubWestend; - -// AssetHubWestend seems to use the same configuration as all Polkadot-like chains, so we'll use -// Westend primitives here. -impl Chain for AssetHubWestend { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - Westend::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - Westend::max_extrinsic_weight() - } +parameter_types! { + pub const SS58Prefix: u8 = 42; } -impl Parachain for AssetHubWestend { - const PARACHAIN_ID: u32 = ASSET_HUB_WESTEND_PARACHAIN_ID; -} +// The SignedExtension used by Westend. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; -/// Name of the parachains pallet at the Westend runtime. +/// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; /// Name of the With-Westend GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa"; -/// Name of the With-Westend parachains bridge pallet instance that is deployed at bridged chains. -pub const WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeWestendParachains"; -/// Maximal SCALE-encoded size of parachains headers that are stored at Westend `Paras` pallet. +/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Westend +/// parachains. /// /// It includes the block number and state root, so it shall be near 40 bytes, but let's have some /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -/// Identifier of `AssetHubWestend` parachain at the Westend relay chain. -pub const ASSET_HUB_WESTEND_PARACHAIN_ID: u32 = 1000; - decl_bridge_finality_runtime_apis!(westend, grandpa); - -decl_bridge_finality_runtime_apis!(AssetHubWestend); diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 16cd603fe3449..e5277d8db6a84 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -97,6 +97,9 @@ pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro"; /// BridgeHubWococo chain id. pub const BRIDGE_HUB_WOCOCO_CHAIN_ID: ChainId = *b"bhwo"; +/// BridgeHubWestend chain id. +pub const BRIDGE_HUB_WESTEND_CHAIN_ID: ChainId = *b"bhwd"; + /// BridgeHubKusama chain id. pub const BRIDGE_HUB_KUSAMA_CHAIN_ID: ChainId = *b"bhks"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 3e822a9bb6ca8..b4e69816e59c4 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -41,6 +41,7 @@ relay-rialto-parachain-client = { path = "../client-rialto-parachain" } relay-bridge-hub-kusama-client = { path = "../client-bridge-hub-kusama" } relay-bridge-hub-polkadot-client = { path = "../client-bridge-hub-polkadot" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } +relay-bridge-hub-westend-client = { path = "../client-bridge-hub-westend" } relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } relay-kusama-client = { path = "../client-kusama" } relay-polkadot-client = { path = "../client-polkadot" } diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs index 53fe5e0c192d8..5a6bf72d0c523 100644 --- a/relays/bin-substrate/src/bridges/mod.rs +++ b/relays/bin-substrate/src/bridges/mod.rs @@ -20,5 +20,6 @@ pub mod kusama_polkadot; pub mod polkadot_bulletin; pub mod rialto_millau; pub mod rialto_parachain_millau; +pub mod rococo_westend; pub mod rococo_wococo; pub mod westend_millau; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs new file mode 100644 index 0000000000000..353fa7df32a4e --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs @@ -0,0 +1,64 @@ +// Copyright 2022 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 . + +//! BridgeHubRococo-to-BridgeHubWestend messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_bridge_hub_rococo_client::BridgeHubRococo; +use relay_bridge_hub_westend_client::BridgeHubWestend; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +pub struct BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubRococoToBridgeHubWestendMessagesCliBridge { + type Source = BridgeHubRococo; + type Target = BridgeHubWestend; +} + +impl MessagesCliBridge for BridgeHubRococoToBridgeHubWestendMessagesCliBridge { + type MessagesLane = BridgeHubRococoMessagesToBridgeHubWestendMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + BridgeHubRococoMessagesToBridgeHubWestendMessageLane, + BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_westend_client::runtime::Call::BridgeRococoMessages, + relay_bridge_hub_westend_client::runtime::BridgeRococoMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + BridgeHubRococoMessagesToBridgeHubWestendMessageLane, + BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendMessages, + relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_delivery_proof +); + +/// Description of BridgeHubRococo -> BridgeHubWestendWestend messages bridge. +#[derive(Clone, Debug)] +pub struct BridgeHubRococoMessagesToBridgeHubWestendMessageLane; + +impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWestendMessageLane { + type SourceChain = BridgeHubRococo; + type TargetChain = BridgeHubWestend; + + type ReceiveMessagesProofCallBuilder = + BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; +} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..ceea252db4216 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs @@ -0,0 +1,64 @@ +// Copyright 2022 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 . + +//! BridgeHubWestend-to-BridgeHubRococo messages sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_bridge_hub_rococo_client::BridgeHubRococo; +use relay_bridge_hub_westend_client::BridgeHubWestend; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +pub struct BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubWestendToBridgeHubRococoMessagesCliBridge { + type Source = BridgeHubWestend; + type Target = BridgeHubRococo; +} + +impl MessagesCliBridge for BridgeHubWestendToBridgeHubRococoMessagesCliBridge { + type MessagesLane = BridgeHubWestendMessagesToBridgeHubRococoMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + BridgeHubWestendMessagesToBridgeHubRococoMessageLane, + BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendMessages, + relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + BridgeHubWestendMessagesToBridgeHubRococoMessageLane, + BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_westend_client::runtime::Call::BridgeRococoMessages, + relay_bridge_hub_westend_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof +); + +/// Description of BridgeHubWestend -> BridgeHubRococo messages bridge. +#[derive(Clone, Debug)] +pub struct BridgeHubWestendMessagesToBridgeHubRococoMessageLane; + +impl SubstrateMessageLane for BridgeHubWestendMessagesToBridgeHubRococoMessageLane { + type SourceChain = BridgeHubWestend; + type TargetChain = BridgeHubRococo; + + type ReceiveMessagesProofCallBuilder = + BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; +} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/mod.rs b/relays/bin-substrate/src/bridges/rococo_westend/mod.rs new file mode 100644 index 0000000000000..965d3e0561f99 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/mod.rs @@ -0,0 +1,24 @@ +// 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 . + +//! Declaration of all bridges between Rococo Bridge Hub and Westend Bridge Hub. + +pub mod bridge_hub_rococo_messages_to_bridge_hub_westend; +pub mod bridge_hub_westend_messages_to_bridge_hub_rococo; +pub mod rococo_headers_to_bridge_hub_westend; +pub mod rococo_parachains_to_bridge_hub_westend; +pub mod westend_headers_to_bridge_hub_rococo; +pub mod westend_parachains_to_bridge_hub_rococo; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs new file mode 100644 index 0000000000000..75f6ff6f25c20 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs @@ -0,0 +1,96 @@ +// Copyright 2022 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 . + +//! Rococo-to-Westend bridge hubs headers sync entrypoint. + +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, + TransactionParams, +}; + +/// Description of Rococo -> Westend finalized headers bridge. +#[derive(Clone, Debug)] +pub struct RococoFinalityToBridgeHubWestend; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + RococoFinalityToBridgeHubWestend, + SubmitFinalityProofCallBuilder, + relay_bridge_hub_westend_client::runtime::Call::BridgeRococoGrandpa, + relay_bridge_hub_westend_client::runtime::BridgeRococoGrandpaCall::submit_finality_proof +); + +substrate_relay_helper::generate_report_equivocation_call_builder!( + RococoFinalityToBridgeHubWestend, + ReportEquivocationCallBuilder, + relay_rococo_client::RuntimeCall::Grandpa, + relay_rococo_client::GrandpaCall::report_equivocation +); + +#[async_trait] +impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWestend { + type SourceChain = relay_rococo_client::Rococo; + type TargetChain = relay_bridge_hub_westend_client::BridgeHubWestend; + + type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWestend { + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } +} + +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for RococoFinalityToBridgeHubWestend { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + +/// `Rococo` to BridgeHub `Westend` bridge definition. +pub struct RococoToBridgeHubWestendCliBridge {} + +impl CliBridgeBase for RococoToBridgeHubWestendCliBridge { + type Source = relay_rococo_client::Rococo; + type Target = relay_bridge_hub_westend_client::BridgeHubWestend; +} + +impl RelayToRelayHeadersCliBridge for RococoToBridgeHubWestendCliBridge { + type Finality = RococoFinalityToBridgeHubWestend; +} + +impl RelayToRelayEquivocationDetectionCliBridge for RococoToBridgeHubWestendCliBridge { + type Equivocation = RococoFinalityToBridgeHubWestend; +} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs new file mode 100644 index 0000000000000..edd600acc4d5b --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs @@ -0,0 +1,75 @@ +// 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 . + +//! Westend-to-Rococo parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::parachains::{ + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// BridgeHub-to-BridgeHub parachain sync description. +#[derive(Clone, Debug)] +pub struct BridgeHubRococoToBridgeHubWestend; + +impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWestend { + type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo; + type SourceRelayChain = relay_rococo_client::Rococo; + type TargetChain = relay_bridge_hub_westend_client::BridgeHubWestend; + + type SubmitParachainHeadsCallBuilder = BridgeHubRococoToBridgeHubWestendCallBuilder; +} + +pub struct BridgeHubRococoToBridgeHubWestendCallBuilder; +impl SubmitParachainHeadsCallBuilder + for BridgeHubRococoToBridgeHubWestendCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_bridge_hub_westend_client::runtime::Call::BridgeRococoParachains( + relay_bridge_hub_westend_client::runtime::BridgeParachainCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + }, + ) + } +} + +/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. +pub struct BridgeHubRococoToBridgeHubWestendCliBridge {} + +impl ParachainToRelayHeadersCliBridge for BridgeHubRococoToBridgeHubWestendCliBridge { + type SourceRelay = relay_rococo_client::Rococo; + type ParachainFinality = BridgeHubRococoToBridgeHubWestend; + type RelayFinality = + crate::bridges::rococo_westend::rococo_headers_to_bridge_hub_westend::RococoFinalityToBridgeHubWestend; +} + +impl CliBridgeBase for BridgeHubRococoToBridgeHubWestendCliBridge { + type Source = relay_bridge_hub_rococo_client::BridgeHubRococo; + type Target = relay_bridge_hub_westend_client::BridgeHubWestend; +} + +impl MessagesCliBridge for BridgeHubRococoToBridgeHubWestendCliBridge { + type MessagesLane = + crate::bridges::rococo_westend::bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoMessagesToBridgeHubWestendMessageLane; +} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..1532e06b95386 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs @@ -0,0 +1,96 @@ +// Copyright 2022 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 . + +//! Westend-to-Rococo bridge hubs headers sync entrypoint. + +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + +use async_trait::async_trait; +use relay_substrate_client::{AccountKeyPairOf, Client}; +use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, + TransactionParams, +}; + +/// Description of Westend -> Rococo finalized headers bridge. +#[derive(Clone, Debug)] +pub struct WestendFinalityToBridgeHubRococo; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + WestendFinalityToBridgeHubRococo, + SubmitFinalityProofCallBuilder, + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendGrandpa, + relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof +); + +substrate_relay_helper::generate_report_equivocation_call_builder!( + WestendFinalityToBridgeHubRococo, + ReportEquivocationCallBuilder, + relay_westend_client::RuntimeCall::Grandpa, + relay_westend_client::GrandpaCall::report_equivocation +); + +#[async_trait] +impl SubstrateFinalityPipeline for WestendFinalityToBridgeHubRococo { + type SourceChain = relay_westend_client::Westend; + type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; + + type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for WestendFinalityToBridgeHubRococo { + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; + + async fn start_relay_guards( + target_client: &Client, + _transaction_params: &TransactionParams>, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } +} + +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for WestendFinalityToBridgeHubRococo { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + +/// `Westend` to BridgeHub `Rococo` bridge definition. +pub struct WestendToBridgeHubRococoCliBridge {} + +impl CliBridgeBase for WestendToBridgeHubRococoCliBridge { + type Source = relay_westend_client::Westend; + type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; +} + +impl RelayToRelayHeadersCliBridge for WestendToBridgeHubRococoCliBridge { + type Finality = WestendFinalityToBridgeHubRococo; +} + +impl RelayToRelayEquivocationDetectionCliBridge for WestendToBridgeHubRococoCliBridge { + type Equivocation = WestendFinalityToBridgeHubRococo; +} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..dac915dc3ba9e --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs @@ -0,0 +1,75 @@ +// 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 . + +//! Rococo-to-Westend parachains sync entrypoint. + +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::parachains::{ + SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +}; + +/// BridgeHub-to-BridgeHub parachain sync description. +#[derive(Clone, Debug)] +pub struct BridgeHubWestendToBridgeHubRococo; + +impl SubstrateParachainsPipeline for BridgeHubWestendToBridgeHubRococo { + type SourceParachain = relay_bridge_hub_westend_client::BridgeHubWestend; + type SourceRelayChain = relay_westend_client::Westend; + type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; + + type SubmitParachainHeadsCallBuilder = BridgeHubWestendToBridgeHubRococoCallBuilder; +} + +pub struct BridgeHubWestendToBridgeHubRococoCallBuilder; +impl SubmitParachainHeadsCallBuilder + for BridgeHubWestendToBridgeHubRococoCallBuilder +{ + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendParachains( + relay_bridge_hub_rococo_client::BridgeParachainCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + }, + ) + } +} + +/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. +pub struct BridgeHubWestendToBridgeHubRococoCliBridge {} + +impl ParachainToRelayHeadersCliBridge for BridgeHubWestendToBridgeHubRococoCliBridge { + type SourceRelay = relay_westend_client::Westend; + type ParachainFinality = BridgeHubWestendToBridgeHubRococo; + type RelayFinality = + crate::bridges::rococo_westend::westend_headers_to_bridge_hub_rococo::WestendFinalityToBridgeHubRococo; +} + +impl CliBridgeBase for BridgeHubWestendToBridgeHubRococoCliBridge { + type Source = relay_bridge_hub_westend_client::BridgeHubWestend; + type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; +} + +impl MessagesCliBridge for BridgeHubWestendToBridgeHubRococoCliBridge { + type MessagesLane = + crate::bridges::rococo_westend::bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendMessagesToBridgeHubRococoMessageLane; +} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs index b2704c092b845..b7296e0a38fb4 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs @@ -44,7 +44,7 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoParachain( + relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoParachains( relay_bridge_hub_wococo_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs index ca77857833d0b..165f4af11c8fe 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs @@ -44,7 +44,7 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoParachain( + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoParachains( relay_bridge_hub_rococo_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs index a3d5ba08df503..96023dc430a28 100644 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs +++ b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs @@ -18,7 +18,7 @@ use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; use relay_millau_client::Millau; -use relay_westend_client::{AssetHubWestend, Westend}; +use relay_westend_client::Westend; use substrate_relay_helper::parachains::{ DirectSubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, }; @@ -28,7 +28,7 @@ use substrate_relay_helper::parachains::{ pub struct WestendParachainsToMillau; impl SubstrateParachainsPipeline for WestendParachainsToMillau { - type SourceParachain = AssetHubWestend; + type SourceParachain = relay_asset_hub_westend_client::AssetHubWestend; type SourceRelayChain = Westend; type TargetChain = Millau; @@ -54,6 +54,37 @@ impl ParachainToRelayHeadersCliBridge for AssetHubWestendToMillauCliBridge { } impl CliBridgeBase for AssetHubWestendToMillauCliBridge { - type Source = AssetHubWestend; + type Source = relay_asset_hub_westend_client::AssetHubWestend; type Target = Millau; } + +/// TODO: Note: I know this does not belong here, but I don't want to add it to the +/// `chain-asset-hub-westend` or `chain-westend`, because we wont use it for production and I don't +/// want to bring this to the bridges subtree now. Anyway, we plan to retire millau/rialto, so this +/// hack will disappear with that. +pub mod relay_asset_hub_westend_client { + use bp_runtime::{ChainId, UnderlyingChainProvider}; + use relay_substrate_client::Chain; + use std::time::Duration; + + /// `AssetHubWestend` parachain definition + #[derive(Debug, Clone, Copy)] + pub struct AssetHubWestend; + + impl UnderlyingChainProvider for AssetHubWestend { + type Chain = millau_runtime::bp_bridged_chain::AssetHubWestend; + } + + // Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use + // Westend primitives here. + impl Chain for AssetHubWestend { + const ID: ChainId = bp_runtime::ASSET_HUB_WESTEND_CHAIN_ID; + const NAME: &'static str = "Westmint"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + millau_runtime::bp_bridged_chain::BEST_FINALIZED_ASSETHUBWESTEND_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + + type SignedBlock = bp_polkadot_core::SignedBlock; + type Call = (); + } +} diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs index 4cee26255d397..f60d60386e9ba 100644 --- a/relays/bin-substrate/src/chains/millau.rs +++ b/relays/bin-substrate/src/chains/millau.rs @@ -65,3 +65,11 @@ impl CliChain for Millau { const RUNTIME_VERSION: Option = Some(SimpleRuntimeVersion::from_runtime_version(&millau_runtime::VERSION)); } + +/// TODO: Note: I know this does not belong here, but I don't want to add it to the +/// `chain-asset-hub-westend` or `chain-westend`, because we wont use it for production and I don't +/// want to bring this to the bridges subtree now. Anyway, we plan to retire millau/rialto, so this +/// hack will disappear with that. +impl CliChain for crate::bridges::westend_millau::westend_parachains_to_millau::relay_asset_hub_westend_client::AssetHubWestend { + const RUNTIME_VERSION: Option = None; +} diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index af404878ceb06..5376fc210e520 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -17,13 +17,15 @@ //! Westend chain specification for CLI. use crate::cli::CliChain; +use relay_bridge_hub_westend_client::BridgeHubWestend; use relay_substrate_client::SimpleRuntimeVersion; -use relay_westend_client::{AssetHubWestend, Westend}; +use relay_westend_client::Westend; impl CliChain for Westend { const RUNTIME_VERSION: Option = None; } -impl CliChain for AssetHubWestend { - const RUNTIME_VERSION: Option = None; +impl CliChain for BridgeHubWestend { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 10000, transaction_version: 3 }); } diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 59015f07f247b..0c1483b348b1a 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -35,6 +35,8 @@ pub enum FullBridge { RialtoParachainToMillau, BridgeHubRococoToBridgeHubWococo, BridgeHubWococoToBridgeHubRococo, + BridgeHubRococoToBridgeHubWestend, + BridgeHubWestendToBridgeHubRococo, BridgeHubKusamaToBridgeHubPolkadot, BridgeHubPolkadotToBridgeHubKusama, PolkadotBulletinToBridgeHubPolkadot, diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index af938102e40d1..415897aeba94c 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -32,6 +32,10 @@ use crate::{ rialto_headers_to_millau::RialtoToMillauCliBridge, }, rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, + rococo_westend::{ + rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, + westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, + }, rococo_wococo::{ rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, @@ -78,6 +82,8 @@ pub enum InitBridgeName { PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, PolkadotBulletinToBridgeHubPolkadot, + RococoToBridgeHubWestend, + WestendToBridgeHubRococo, } #[async_trait] @@ -210,6 +216,32 @@ impl BridgeInitializer for WococoToBridgeHubRococoCliBridge { } } +impl BridgeInitializer for RococoToBridgeHubWestendCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_westend_client::runtime::Call::BridgeRococoGrandpa( + relay_bridge_hub_westend_client::runtime::BridgeRococoGrandpaCall::initialize { + init_data, + }, + ) + } +} + +impl BridgeInitializer for WestendToBridgeHubRococoCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendGrandpa( + relay_bridge_hub_rococo_client::BridgeGrandpaCall::initialize { init_data }, + ) + } +} + impl BridgeInitializer for KusamaToBridgeHubPolkadotCliBridge { type Engine = GrandpaFinalityEngine; @@ -290,6 +322,10 @@ impl InitBridge { PolkadotToPolkadotBulletinCliBridge::init_bridge(self), InitBridgeName::PolkadotBulletinToBridgeHubPolkadot => PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self), + InitBridgeName::RococoToBridgeHubWestend => + RococoToBridgeHubWestendCliBridge::init_bridge(self), + InitBridgeName::WestendToBridgeHubRococo => + WestendToBridgeHubRococoCliBridge::init_bridge(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 86f6ef9e3472c..5a8c084889d75 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -56,6 +56,10 @@ use crate::{ millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, }, + rococo_westend::{ + rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, + westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, + }, rococo_wococo::{ rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, @@ -206,6 +210,8 @@ declare_chain_cli_schema!(Rococo, rococo); declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); declare_chain_cli_schema!(Wococo, wococo); declare_chain_cli_schema!(BridgeHubWococo, bridge_hub_wococo); +declare_chain_cli_schema!(Westend, westend); +declare_chain_cli_schema!(BridgeHubWestend, bridge_hub_westend); declare_chain_cli_schema!(Kusama, kusama); declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); declare_chain_cli_schema!(Polkadot, polkadot); @@ -226,6 +232,16 @@ declare_chain_cli_schema!( WococoParachainsToBridgeHubRococo, wococo_parachains_to_bridge_hub_rococo ); +declare_chain_cli_schema!(RococoHeadersToBridgeHubWestend, rococo_headers_to_bridge_hub_westend); +declare_chain_cli_schema!( + RococoParachainsToBridgeHubWestend, + rococo_parachains_to_bridge_hub_westend +); +declare_chain_cli_schema!(WestendHeadersToBridgeHubRococo, westend_headers_to_bridge_hub_rococo); +declare_chain_cli_schema!( + WestendParachainsToBridgeHubRococo, + westend_parachains_to_bridge_hub_rococo +); declare_chain_cli_schema!(KusamaHeadersToBridgeHubPolkadot, kusama_headers_to_bridge_hub_polkadot); declare_chain_cli_schema!( KusamaParachainsToBridgeHubPolkadot, @@ -249,6 +265,7 @@ declare_chain_cli_schema!( declare_relay_to_relay_bridge_schema!(Millau, Rialto); declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWococo, Wococo); +declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWestend, Westend); declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); @@ -495,6 +512,32 @@ impl Full2WayBridge for BridgeHubRococoBridgeHubWococoFull2WayBridge { } } +/// BridgeHubRococo <> BridgeHubWestend complex relay. +pub struct BridgeHubRococoBridgeHubWestendFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for BridgeHubRococoBridgeHubWestendFull2WayBridge { + type Base = ParachainToParachainBridge; + type Left = relay_bridge_hub_rococo_client::BridgeHubRococo; + type Right = relay_bridge_hub_westend_client::BridgeHubWestend; + type L2R = BridgeHubRococoToBridgeHubWestendCliBridge; + type R2L = BridgeHubWestendToBridgeHubRococoCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + /// BridgeHubKusama <> BridgeHubPolkadot complex relay. pub struct BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { base: ::Base, @@ -560,6 +603,8 @@ pub enum RelayHeadersAndMessages { BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), /// `PolkadotBulletin` <> `BridgeHubPolkadot` relay. PolkadotBulletinBridgeHubPolkadot(PolkadotBulletinBridgeHubPolkadotHeadersAndMessages), + /// BridgeHubRococo <> BridgeHubWestend relay. + BridgeHubRococoBridgeHubWestend(BridgeHubRococoBridgeHubWestendHeadersAndMessages), } impl RelayHeadersAndMessages { @@ -576,6 +621,10 @@ impl RelayHeadersAndMessages { BridgeHubRococoBridgeHubWococoFull2WayBridge::new(params.into_bridge().await?)? .run() .await, + RelayHeadersAndMessages::BridgeHubRococoBridgeHubWestend(params) => + BridgeHubRococoBridgeHubWestendFull2WayBridge::new(params.into_bridge().await?)? + .run() + .await, RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot(params) => BridgeHubKusamaBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? .run() diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index b5ba275af6fa0..9880edcda2ca1 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -36,6 +36,10 @@ use crate::bridges::{ millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, }, + rococo_westend::{ + bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendMessagesCliBridge, + bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, + }, rococo_wococo::{ bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge, bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge, @@ -111,6 +115,8 @@ impl MessagesRelayer for MillauToRialtoParachainCliBridge {} impl MessagesRelayer for RialtoParachainToMillauCliBridge {} impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} +impl MessagesRelayer for BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} +impl MessagesRelayer for BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} impl MessagesRelayer for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} impl MessagesRelayer for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} @@ -130,6 +136,10 @@ impl RelayMessages { BridgeHubRococoToBridgeHubWococoMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubWococoToBridgeHubRococo => BridgeHubWococoToBridgeHubRococoMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubRococoToBridgeHubWestend => + BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubWestendToBridgeHubRococo => + BridgeHubWestendToBridgeHubRococoMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubKusamaToBridgeHubPolkadot => BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubPolkadotToBridgeHubKusama => diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 3dc9daad1aab4..03d3860f3b224 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -21,6 +21,10 @@ use crate::bridges::{ }, polkadot_bulletin::polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, rialto_parachain_millau::rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, + rococo_westend::{ + rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, + westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, + }, rococo_wococo::{ rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, @@ -73,6 +77,8 @@ pub enum RelayParachainsBridge { KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, + RococoToBridgeHubWestend, + WestendToBridgeHubRococo, } #[async_trait] @@ -120,6 +126,8 @@ impl ParachainsRelayer for RialtoParachainToMillauCliBridge {} impl ParachainsRelayer for AssetHubWestendToMillauCliBridge {} impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} +impl ParachainsRelayer for BridgeHubRococoToBridgeHubWestendCliBridge {} +impl ParachainsRelayer for BridgeHubWestendToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} impl ParachainsRelayer for BridgeHubPolkadotToBridgeHubKusamaCliBridge {} impl ParachainsRelayer for PolkadotToPolkadotBulletinCliBridge {} @@ -136,6 +144,10 @@ impl RelayParachains { BridgeHubRococoToBridgeHubWococoCliBridge::relay_parachains(self), RelayParachainsBridge::WococoToBridgeHubRococo => BridgeHubWococoToBridgeHubRococoCliBridge::relay_parachains(self), + RelayParachainsBridge::RococoToBridgeHubWestend => + BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self), + RelayParachainsBridge::WestendToBridgeHubRococo => + BridgeHubWestendToBridgeHubRococoCliBridge::relay_parachains(self), RelayParachainsBridge::KusamaToBridgeHubPolkadot => BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self), RelayParachainsBridge::PolkadotToBridgeHubKusama => diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs index 2ad17d8eb7c9f..cf125b8cf5966 100644 --- a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs @@ -264,16 +264,22 @@ pub mod api { Multisig(runtime_types::pallet_multisig::pallet::Call), #[codec(index = 41)] BridgeWococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 42)] - BridgeWococoParachain(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 46)] - BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), #[codec(index = 43)] BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 48)] + BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 42)] + BridgeWococoParachains(runtime_types::pallet_bridge_parachains::pallet::Call), #[codec(index = 44)] - BridgeRococoParachain(runtime_types::pallet_bridge_parachains::pallet::Call), + BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 49)] + BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 46)] + BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), #[codec(index = 45)] BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 51)] + BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Call), #[codec(index = 47)] BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), } @@ -305,16 +311,22 @@ pub mod api { Multisig(runtime_types::pallet_multisig::pallet::Event), #[codec(index = 41)] BridgeWococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 42)] - BridgeWococoParachain(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 46)] - BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), #[codec(index = 43)] BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 48)] + BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 42)] + BridgeWococoParachains(runtime_types::pallet_bridge_parachains::pallet::Event), #[codec(index = 44)] - BridgeRococoParachain(runtime_types::pallet_bridge_parachains::pallet::Event), + BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 49)] + BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 46)] + BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), #[codec(index = 45)] BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), + #[codec(index = 51)] + BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Event), #[codec(index = 47)] BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), } diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml new file mode 100644 index 0000000000000..a147aaee43917 --- /dev/null +++ b/relays/client-bridge-hub-westend/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "relay-bridge-hub-westend-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +subxt = { version = "0.32.1", default-features = false, features = [] } + +# Bridge dependencies + +bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } +bp-bridge-hub-westend = { path = "../../primitives/chain-bridge-hub-westend" } +bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } +bp-parachains = { path = "../../primitives/parachains" } +bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-rococo = { path = "../../primitives/chain-rococo" } +bp-runtime = { path = "../../primitives/runtime" } + +bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-substrate-client = { path = "../client-substrate" } + +# Substrate Dependencies + +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } + +[dev-dependencies] +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs new file mode 100644 index 0000000000000..addbbe0414786 --- /dev/null +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -0,0 +1,162 @@ +// Copyright 2022 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 . + +//! Types used to connect to the BridgeHub-Westend-Substrate parachain. + +use bp_bridge_hub_westend::AVERAGE_BLOCK_INTERVAL; +use bp_messages::MessageNonce; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_runtime::ChainId; +use codec::Encode; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, + UnsignedTransaction, +}; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; +use std::time::Duration; + +/// Re-export runtime wrapper +pub mod runtime_wrapper; +pub use runtime_wrapper as runtime; + +/// Westend chain definition +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BridgeHubWestend; + +impl UnderlyingChainProvider for BridgeHubWestend { + type Chain = bp_bridge_hub_westend::BridgeHubWestend; +} + +impl Chain for BridgeHubWestend { + const ID: ChainId = bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID; + const NAME: &'static str = "BridgeHubWestend"; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + bp_bridge_hub_westend::BEST_FINALIZED_BRIDGE_HUB_WESTEND_HEADER_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; + + type SignedBlock = bp_bridge_hub_westend::SignedBlock; + type Call = runtime::Call; +} + +impl ChainWithBalances for BridgeHubWestend { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + bp_bridge_hub_westend::AccountInfoStorageMapKeyProvider::final_key(account_id) + } +} + +impl ChainWithUtilityPallet for BridgeHubWestend { + type UtilityPallet = MockedRuntimeUtilityPallet; +} + +impl ChainWithTransactions for BridgeHubWestend { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = runtime::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + runtime::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + (((), ()), ((), ())), + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(runtime::UncheckedExtrinsic::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| { + *address == bp_bridge_hub_westend::Address::Id(signer.public().into()) + }) + .unwrap_or(false) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } +} + +impl ChainWithMessages for BridgeHubWestend { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_westend::WITH_BRIDGE_HUB_WESTEND_MESSAGES_PALLET_NAME; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = + Some(bp_bridge_hub_westend::WITH_BRIDGE_HUB_WESTEND_RELAYERS_PALLET_NAME); + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_westend::TO_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + bp_bridge_hub_westend::FROM_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_westend::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + +#[cfg(test)] +mod tests { + use super::*; + use relay_substrate_client::TransactionEra; + + #[test] + fn parse_transaction_works() { + let unsigned = UnsignedTransaction { + call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + .into(), + nonce: 777, + tip: 888, + era: TransactionEra::immortal(), + }; + let signed_transaction = BridgeHubWestend::sign_transaction( + SignParam { + spec_version: 42, + transaction_version: 50000, + genesis_hash: [42u8; 32].into(), + signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), + }, + unsigned.clone(), + ) + .unwrap(); + let parsed_transaction = BridgeHubWestend::parse_transaction(signed_transaction).unwrap(); + assert_eq!(parsed_transaction, unsigned); + } +} diff --git a/relays/client-bridge-hub-westend/src/runtime_wrapper.rs b/relays/client-bridge-hub-westend/src/runtime_wrapper.rs new file mode 100644 index 0000000000000..b4ff36cde7a30 --- /dev/null +++ b/relays/client-bridge-hub-westend/src/runtime_wrapper.rs @@ -0,0 +1,116 @@ +// 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 . + +//! Types that are specific to the BridgeHubWestend runtime. +// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945) + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub use bp_bridge_hub_westend::SignedExtension; +pub use bp_header_chain::BridgeGrandpaCallOf; +pub use bp_parachains::BridgeParachainCall; +pub use bridge_runtime_common::messages::BridgeMessagesCallOf; +pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; + +/// Unchecked BridgeHubWestend extrinsic. +pub type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic; + +/// The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWestend`. +pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; +/// The indirect pallet call used to sync `BridgeHubRococo` messages to `BridgeHubWestend`. +pub type BridgeRococoMessagesCall = BridgeMessagesCallOf; + +/// `BridgeHubWestend` Runtime `Call` enum. +/// +/// The enum represents a subset of possible `Call`s we can send to `BridgeHubWestend` chain. +/// Ideally this code would be auto-generated from metadata, because we want to +/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. +/// +/// All entries here (like pretty much in the entire file) must be kept in sync with +/// `BridgeHubWestend` `construct_runtime`, so that we maintain SCALE-compatibility. +#[allow(clippy::large_enum_variant)] +#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] +pub enum Call { + #[cfg(test)] + #[codec(index = 0)] + System(SystemCall), + /// Utility pallet. + #[codec(index = 40)] + Utility(UtilityCall), + + /// Rococo grandpa bridge pallet. + #[codec(index = 42)] + BridgeRococoGrandpa(BridgeRococoGrandpaCall), + /// Rococo parachains bridge pallet. + #[codec(index = 43)] + BridgeRococoParachains(BridgeParachainCall), + /// Rococo messages bridge pallet. + #[codec(index = 44)] + BridgeRococoMessages(BridgeRococoMessagesCall), +} + +impl From> for Call { + fn from(call: UtilityCall) -> Call { + Call::Utility(call) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bp_runtime::BasicOperatingMode; + use sp_consensus_grandpa::AuthorityList; + use sp_core::hexdisplay::HexDisplay; + use sp_runtime::traits::Header; + use std::str::FromStr; + + pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; + pub type RelayBlockHasher = bp_polkadot_core::Hasher; + pub type RelayBlockHeader = sp_runtime::generic::Header; + + #[test] + fn encode_decode_calls() { + let header = RelayBlockHeader::new( + 75, + bp_polkadot_core::Hash::from_str( + "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", + ) + .expect("invalid value"), + bp_polkadot_core::Hash::from_str( + "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", + ) + .expect("invalid value"), + Default::default(), + ); + let init_data = bp_header_chain::InitializationData { + header: Box::new(header), + authority_list: AuthorityList::default(), + set_id: 6, + operating_mode: BasicOperatingMode::Normal, + }; + let call = BridgeRococoGrandpaCall::initialize { init_data }; + let tx = Call::BridgeRococoGrandpa(call); + + // encode call as hex string + let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); + assert_eq!(hex_encoded_call, "0x2a01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); + } +} diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml index b60e8c0e87216..d90af65d3a0bb 100644 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ b/relays/client-bridge-hub-wococo/Cargo.toml @@ -18,7 +18,6 @@ bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 03b5ff5db62de..42e022d1be336 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -80,7 +80,7 @@ impl ChainWithBalances for Rococo { impl RelayChain for Rococo { const PARAS_PALLET_NAME: &'static str = bp_rococo::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeRococoParachain"; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeRococoParachains"; } impl ChainWithTransactions for Rococo { diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 520cb232b0f6e..0c6083f8f8c83 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -6,15 +6,23 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } +codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } bp-westend = { path = "../../primitives/chain-westend" } +relay-substrate-client = { path = "../client-substrate" } +relay-utils = { path = "../utils" } + # Substrate Dependencies +sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-westend/src/codegen_runtime.rs b/relays/client-westend/src/codegen_runtime.rs new file mode 100644 index 0000000000000..9422622e48c50 --- /dev/null +++ b/relays/client-westend/src/codegen_runtime.rs @@ -0,0 +1,6945 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://westend-rpc.polkadot.io:443 + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +pub mod api { + use super::api as root_mod; + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_btree_map { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedBTreeMap<_0, _1>(pub ::subxt::utils::KeyedVec<_0, _1>); + } + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Equivocation<_0, _1, _2> { + pub round_number: ::core::primitive::u64, + pub identity: _0, + pub first: (_1, _2), + pub second: (_1, _2), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Prevote<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProcessMessageError { + #[codec(index = 0)] + BadFormat, + #[codec(index = 1)] + Corrupt, + #[codec(index = 2)] + Unsupported, + #[codec(index = 3)] + Overweight(::sp_weights::Weight), + #[codec(index = 4)] + Yield, + } + } + pub mod misc { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WrapperOpaque<_0>( + #[codec(compact)] pub ::core::primitive::u32, + pub _0, + ); + } + pub mod preimages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Bounded<_0> { + #[codec(index = 0)] + Legacy { + hash: ::subxt::utils::H256, + }, + #[codec(index = 1)] + Inline( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Lookup { + hash: ::subxt::utils::H256, + len: ::core::primitive::u32, + }, + __Ignore(::core::marker::PhantomData<_0>), + } + } + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletId(pub [::core::primitive::u8; 8usize]); + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: _0, + pub providers: _0, + pub sufficients: _0, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_babe { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + runtime_types::sp_consensus_slots::EquivocationProof< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + runtime_types::sp_consensus_babe::app::Public, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + plan_config_change { + config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidEquivocationProof, + #[codec(index = 1)] + InvalidKeyOwnershipProof, + #[codec(index = 2)] + DuplicateOffenceReport, + #[codec(index = 3)] + InvalidConfiguration, + } + } + } + pub mod pallet_bags_list { + use super::runtime_types; + pub mod list { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Bag { + pub head: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub tail: ::core::option::Option<::sp_core::crypto::AccountId32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ListError { + #[codec(index = 0)] + Duplicate, + #[codec(index = 1)] + NotHeavier, + #[codec(index = 2)] + NotInSameBag, + #[codec(index = 3)] + NodeNotFound, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Node { + pub id: ::sp_core::crypto::AccountId32, + pub prev: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub next: ::core::option::Option<::sp_core::crypto::AccountId32>, + pub bag_upper: ::core::primitive::u64, + pub score: ::core::primitive::u64, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + rebag { + dislocated: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + put_in_front_of { + lighter: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + List(runtime_types::pallet_bags_list::list::ListError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Rebagged { + who: ::sp_core::crypto::AccountId32, + from: ::core::primitive::u64, + to: ::core::primitive::u64, + }, + #[codec(index = 1)] + ScoreUpdated { + who: ::sp_core::crypto::AccountId32, + new_score: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 1)] + set_balance_deprecated { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + #[codec(compact)] + old_reserved: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 7)] + transfer { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_election_provider_multi_phase { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] submit_unsigned { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: westend_runtime :: NposCompactSolution16 > > , witness : runtime_types :: pallet_election_provider_multi_phase :: SolutionOrSnapshotSize , } , # [codec (index = 1)] set_minimum_untrusted_score { maybe_next_score : :: core :: option :: Option < runtime_types :: sp_npos_elections :: ElectionScore > , } , # [codec (index = 2)] set_emergency_election_result { supports : :: std :: vec :: Vec < (:: sp_core :: crypto :: AccountId32 , runtime_types :: sp_npos_elections :: Support < :: sp_core :: crypto :: AccountId32 > ,) > , } , # [codec (index = 3)] submit { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: westend_runtime :: NposCompactSolution16 > > , } , # [codec (index = 4)] governance_fallback { maybe_max_voters : :: core :: option :: Option < :: core :: primitive :: u32 > , maybe_max_targets : :: core :: option :: Option < :: core :: primitive :: u32 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PreDispatchEarlySubmission, + #[codec(index = 1)] + PreDispatchWrongWinnerCount, + #[codec(index = 2)] + PreDispatchWeakSubmission, + #[codec(index = 3)] + SignedQueueFull, + #[codec(index = 4)] + SignedCannotPayDeposit, + #[codec(index = 5)] + SignedInvalidWitness, + #[codec(index = 6)] + SignedTooMuchWeight, + #[codec(index = 7)] + OcwCallWrongEra, + #[codec(index = 8)] + MissingSnapshotMetadata, + #[codec(index = 9)] + InvalidSubmissionIndex, + #[codec(index = 10)] + CallNotAllowed, + #[codec(index = 11)] + FallbackFailed, + #[codec(index = 12)] + BoundNotMet, + #[codec(index = 13)] + TooManyWinners, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + SolutionStored { + compute: + runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + origin: ::core::option::Option<::sp_core::crypto::AccountId32>, + prev_ejected: ::core::primitive::bool, + }, + #[codec(index = 1)] + ElectionFinalized { + compute: + runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + score: runtime_types::sp_npos_elections::ElectionScore, + }, + #[codec(index = 2)] + ElectionFailed, + #[codec(index = 3)] + Rewarded { + account: ::sp_core::crypto::AccountId32, + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + Slashed { + account: ::sp_core::crypto::AccountId32, + value: ::core::primitive::u128, + }, + #[codec(index = 5)] + PhaseTransitioned { + from: runtime_types::pallet_election_provider_multi_phase::Phase< + ::core::primitive::u32, + >, + to: runtime_types::pallet_election_provider_multi_phase::Phase< + ::core::primitive::u32, + >, + round: ::core::primitive::u32, + }, + } + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedSubmission<_0, _1, _2> { + pub who: _0, + pub deposit: _1, + pub raw_solution: + runtime_types::pallet_election_provider_multi_phase::RawSolution<_2>, + pub call_fee: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ElectionCompute { + #[codec(index = 0)] + OnChain, + #[codec(index = 1)] + Signed, + #[codec(index = 2)] + Unsigned, + #[codec(index = 3)] + Fallback, + #[codec(index = 4)] + Emergency, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase<_0> { + #[codec(index = 0)] + Off, + #[codec(index = 1)] + Signed, + #[codec(index = 2)] + Unsigned((::core::primitive::bool, _0)), + #[codec(index = 3)] + Emergency, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RawSolution<_0> { + pub solution: _0, + pub score: runtime_types::sp_npos_elections::ElectionScore, + pub round: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReadySolution { + pub supports: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::sp_core::crypto::AccountId32, + runtime_types::sp_npos_elections::Support<::sp_core::crypto::AccountId32>, + )>, + pub score: runtime_types::sp_npos_elections::ElectionScore, + pub compute: runtime_types::pallet_election_provider_multi_phase::ElectionCompute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RoundSnapshot<_0, _1> { + pub voters: ::std::vec::Vec<_1>, + pub targets: ::std::vec::Vec<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SolutionOrSnapshotSize { + #[codec(compact)] + pub voters: ::core::primitive::u32, + #[codec(compact)] + pub targets: ::core::primitive::u32, + } + } + pub mod pallet_fast_unstake { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register_fast_unstake, + #[codec(index = 1)] + deregister, + #[codec(index = 2)] + control { eras_to_check: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotController, + #[codec(index = 1)] + AlreadyQueued, + #[codec(index = 2)] + NotFullyBonded, + #[codec(index = 3)] + NotQueued, + #[codec(index = 4)] + AlreadyHead, + #[codec(index = 5)] + CallNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Unstaked { + stash: ::sp_core::crypto::AccountId32, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + Slashed { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + InternalError, + #[codec(index = 3)] + BatchChecked { eras: ::std::vec::Vec<::core::primitive::u32> }, + #[codec(index = 4)] + BatchFinished { size: ::core::primitive::u32 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnstakeRequest { + pub stashes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + )>, + pub checked: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >, + } + } + } + pub mod pallet_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + report_equivocation { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 1)] + report_equivocation_unsigned { + equivocation_proof: ::std::boxed::Box< + ::sp_consensus_grandpa::EquivocationProof< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + >, + key_owner_proof: ::sp_session::MembershipProof, + }, + #[codec(index = 2)] + note_stalled { + delay: ::core::primitive::u32, + best_finalized_block_number: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PauseFailed, + #[codec(index = 1)] + ResumeFailed, + #[codec(index = 2)] + ChangePending, + #[codec(index = 3)] + TooSoon, + #[codec(index = 4)] + InvalidKeyOwnershipProof, + #[codec(index = 5)] + InvalidEquivocationProof, + #[codec(index = 6)] + DuplicateOffenceReport, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewAuthorities { + authority_set: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + }, + #[codec(index = 1)] + Paused, + #[codec(index = 2)] + Resumed, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredPendingChange<_0> { + pub scheduled_at: _0, + pub delay: _0, + pub next_authorities: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub forced: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum StoredState<_0> { + #[codec(index = 0)] + Live, + #[codec(index = 1)] + PendingPause { scheduled_at: _0, delay: _0 }, + #[codec(index = 2)] + Paused, + #[codec(index = 3)] + PendingResume { scheduled_at: _0, delay: _0 }, + } + } + pub mod pallet_identity { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + add_registrar { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 1)] + set_identity { + info: + ::std::boxed::Box, + }, + #[codec(index = 2)] + set_subs { + subs: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_identity::types::Data, + )>, + }, + #[codec(index = 3)] + clear_identity, + #[codec(index = 4)] + request_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + #[codec(compact)] + max_fee: ::core::primitive::u128, + }, + #[codec(index = 5)] + cancel_request { reg_index: ::core::primitive::u32 }, + #[codec(index = 6)] + set_fee { + #[codec(compact)] + index: ::core::primitive::u32, + #[codec(compact)] + fee: ::core::primitive::u128, + }, + #[codec(index = 7)] + set_account_id { + #[codec(compact)] + index: ::core::primitive::u32, + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 8)] + set_fields { + #[codec(compact)] + index: ::core::primitive::u32, + fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + }, + #[codec(index = 9)] + provide_judgement { + #[codec(compact)] + reg_index: ::core::primitive::u32, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + judgement: runtime_types::pallet_identity::types::Judgement< + ::core::primitive::u128, + >, + identity: ::subxt::utils::H256, + }, + #[codec(index = 10)] + kill_identity { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 11)] + add_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 12)] + rename_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + data: runtime_types::pallet_identity::types::Data, + }, + #[codec(index = 13)] + remove_sub { + sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 14)] + quit_sub, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManySubAccounts, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotNamed, + #[codec(index = 3)] + EmptyIndex, + #[codec(index = 4)] + FeeChanged, + #[codec(index = 5)] + NoIdentity, + #[codec(index = 6)] + StickyJudgement, + #[codec(index = 7)] + JudgementGiven, + #[codec(index = 8)] + InvalidJudgement, + #[codec(index = 9)] + InvalidIndex, + #[codec(index = 10)] + InvalidTarget, + #[codec(index = 11)] + TooManyFields, + #[codec(index = 12)] + TooManyRegistrars, + #[codec(index = 13)] + AlreadyClaimed, + #[codec(index = 14)] + NotSub, + #[codec(index = 15)] + NotOwned, + #[codec(index = 16)] + JudgementForDifferentIdentity, + #[codec(index = 17)] + JudgementPaymentFailed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IdentitySet { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + IdentityCleared { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 2)] + IdentityKilled { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 3)] + JudgementRequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 4)] + JudgementUnrequested { + who: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 5)] + JudgementGiven { + target: ::sp_core::crypto::AccountId32, + registrar_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + RegistrarAdded { registrar_index: ::core::primitive::u32 }, + #[codec(index = 7)] + SubIdentityAdded { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 8)] + SubIdentityRemoved { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 9)] + SubIdentityRevoked { + sub: ::sp_core::crypto::AccountId32, + main: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct BitFlags<_0>( + pub ::core::primitive::u64, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Data { + #[codec(index = 0)] + None, + #[codec(index = 1)] + Raw0([::core::primitive::u8; 0usize]), + #[codec(index = 2)] + Raw1([::core::primitive::u8; 1usize]), + #[codec(index = 3)] + Raw2([::core::primitive::u8; 2usize]), + #[codec(index = 4)] + Raw3([::core::primitive::u8; 3usize]), + #[codec(index = 5)] + Raw4([::core::primitive::u8; 4usize]), + #[codec(index = 6)] + Raw5([::core::primitive::u8; 5usize]), + #[codec(index = 7)] + Raw6([::core::primitive::u8; 6usize]), + #[codec(index = 8)] + Raw7([::core::primitive::u8; 7usize]), + #[codec(index = 9)] + Raw8([::core::primitive::u8; 8usize]), + #[codec(index = 10)] + Raw9([::core::primitive::u8; 9usize]), + #[codec(index = 11)] + Raw10([::core::primitive::u8; 10usize]), + #[codec(index = 12)] + Raw11([::core::primitive::u8; 11usize]), + #[codec(index = 13)] + Raw12([::core::primitive::u8; 12usize]), + #[codec(index = 14)] + Raw13([::core::primitive::u8; 13usize]), + #[codec(index = 15)] + Raw14([::core::primitive::u8; 14usize]), + #[codec(index = 16)] + Raw15([::core::primitive::u8; 15usize]), + #[codec(index = 17)] + Raw16([::core::primitive::u8; 16usize]), + #[codec(index = 18)] + Raw17([::core::primitive::u8; 17usize]), + #[codec(index = 19)] + Raw18([::core::primitive::u8; 18usize]), + #[codec(index = 20)] + Raw19([::core::primitive::u8; 19usize]), + #[codec(index = 21)] + Raw20([::core::primitive::u8; 20usize]), + #[codec(index = 22)] + Raw21([::core::primitive::u8; 21usize]), + #[codec(index = 23)] + Raw22([::core::primitive::u8; 22usize]), + #[codec(index = 24)] + Raw23([::core::primitive::u8; 23usize]), + #[codec(index = 25)] + Raw24([::core::primitive::u8; 24usize]), + #[codec(index = 26)] + Raw25([::core::primitive::u8; 25usize]), + #[codec(index = 27)] + Raw26([::core::primitive::u8; 26usize]), + #[codec(index = 28)] + Raw27([::core::primitive::u8; 27usize]), + #[codec(index = 29)] + Raw28([::core::primitive::u8; 28usize]), + #[codec(index = 30)] + Raw29([::core::primitive::u8; 29usize]), + #[codec(index = 31)] + Raw30([::core::primitive::u8; 30usize]), + #[codec(index = 32)] + Raw31([::core::primitive::u8; 31usize]), + #[codec(index = 33)] + Raw32([::core::primitive::u8; 32usize]), + #[codec(index = 34)] + BlakeTwo256([::core::primitive::u8; 32usize]), + #[codec(index = 35)] + Sha256([::core::primitive::u8; 32usize]), + #[codec(index = 36)] + Keccak256([::core::primitive::u8; 32usize]), + #[codec(index = 37)] + ShaThree256([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum IdentityField { + #[codec(index = 1)] + Display, + #[codec(index = 2)] + Legal, + #[codec(index = 4)] + Web, + #[codec(index = 8)] + Riot, + #[codec(index = 16)] + Email, + #[codec(index = 32)] + PgpFingerprint, + #[codec(index = 64)] + Image, + #[codec(index = 128)] + Twitter, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdentityInfo { + pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::pallet_identity::types::Data, + runtime_types::pallet_identity::types::Data, + )>, + pub display: runtime_types::pallet_identity::types::Data, + pub legal: runtime_types::pallet_identity::types::Data, + pub web: runtime_types::pallet_identity::types::Data, + pub riot: runtime_types::pallet_identity::types::Data, + pub email: runtime_types::pallet_identity::types::Data, + pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, + pub image: runtime_types::pallet_identity::types::Data, + pub twitter: runtime_types::pallet_identity::types::Data, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Judgement<_0> { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + FeePaid(_0), + #[codec(index = 2)] + Reasonable, + #[codec(index = 3)] + KnownGood, + #[codec(index = 4)] + OutOfDate, + #[codec(index = 5)] + LowQuality, + #[codec(index = 6)] + Erroneous, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RegistrarInfo<_0, _1> { + pub account: _1, + pub fee: _0, + pub fields: runtime_types::pallet_identity::types::BitFlags< + runtime_types::pallet_identity::types::IdentityField, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0> { + pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + ::core::primitive::u32, + runtime_types::pallet_identity::types::Judgement<_0>, + )>, + pub deposit: _0, + pub info: runtime_types::pallet_identity::types::IdentityInfo, + } + } + } + pub mod pallet_im_online { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + heartbeat { + heartbeat: + runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, + signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidKey, + #[codec(index = 1)] + DuplicatedHeartbeat, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + HeartbeatReceived { + authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + }, + #[codec(index = 1)] + AllGood, + #[codec(index = 2)] + SomeOffline { + offline: ::std::vec::Vec<( + ::sp_core::crypto::AccountId32, + runtime_types::pallet_staking::Exposure< + ::sp_core::crypto::AccountId32, + ::core::primitive::u128, + >, + )>, + }, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedOpaqueNetworkState { + pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + pub external_addresses: + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Heartbeat<_0> { + pub block_number: _0, + pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, + pub session_index: _0, + pub authority_index: _0, + pub validators_len: _0, + } + } + pub mod pallet_indices { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim { index: ::core::primitive::u32 }, + #[codec(index = 1)] + transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + }, + #[codec(index = 2)] + free { index: ::core::primitive::u32 }, + #[codec(index = 3)] + force_transfer { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + index: ::core::primitive::u32, + freeze: ::core::primitive::bool, + }, + #[codec(index = 4)] + freeze { index: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAssigned, + #[codec(index = 1)] + NotOwner, + #[codec(index = 2)] + InUse, + #[codec(index = 3)] + NotTransfer, + #[codec(index = 4)] + Permanent, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + IndexAssigned { + who: ::sp_core::crypto::AccountId32, + index: ::core::primitive::u32, + }, + #[codec(index = 1)] + IndexFreed { index: ::core::primitive::u32 }, + #[codec(index = 2)] + IndexFrozen { + index: ::core::primitive::u32, + who: ::sp_core::crypto::AccountId32, + }, + } + } + } + pub mod pallet_message_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotReapable, + #[codec(index = 1)] + NoPage, + #[codec(index = 2)] + NoMessage, + #[codec(index = 3)] + AlreadyProcessed, + #[codec(index = 4)] + Queued, + #[codec(index = 5)] + InsufficientWeight, + #[codec(index = 6)] + TemporarilyUnprocessable, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BookState<_0> { + pub begin: ::core::primitive::u32, + pub end: ::core::primitive::u32, + pub count: ::core::primitive::u32, + pub ready_neighbours: + ::core::option::Option>, + pub message_count: ::core::primitive::u64, + pub size: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Neighbours<_0> { + pub prev: _0, + pub next: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Page<_0> { + pub remaining: _0, + pub remaining_size: _0, + pub first_index: _0, + pub first: _0, + pub last: _0, + pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: _0, + } + } + pub mod pallet_nomination_pools { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + join { + #[codec(compact)] + amount: ::core::primitive::u128, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 1)] + bond_extra { + extra: runtime_types::pallet_nomination_pools::BondExtra< + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + claim_payout, + #[codec(index = 3)] + unbond { + member_account: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + unbonding_points: ::core::primitive::u128, + }, + #[codec(index = 4)] + pool_withdraw_unbonded { + pool_id: ::core::primitive::u32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 5)] + withdraw_unbonded { + member_account: + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 6)] + create { + #[codec(compact)] + amount: ::core::primitive::u128, + root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 7)] + create_with_pool_id { + #[codec(compact)] + amount: ::core::primitive::u128, + root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 8)] + nominate { + pool_id: ::core::primitive::u32, + validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 9)] + set_state { + pool_id: ::core::primitive::u32, + state: runtime_types::pallet_nomination_pools::PoolState, + }, + #[codec(index = 10)] + set_metadata { + pool_id: ::core::primitive::u32, + metadata: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 11)] + set_configs { + min_join_bond: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u128, + >, + min_create_bond: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u128, + >, + max_pools: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + max_members: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + max_members_per_pool: runtime_types::pallet_nomination_pools::ConfigOp< + ::core::primitive::u32, + >, + global_max_commission: runtime_types::pallet_nomination_pools::ConfigOp< + runtime_types::sp_arithmetic::per_things::Perbill, + >, + }, + #[codec(index = 12)] + update_roles { + pool_id: ::core::primitive::u32, + new_root: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + new_nominator: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + new_bouncer: runtime_types::pallet_nomination_pools::ConfigOp< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 13)] + chill { pool_id: ::core::primitive::u32 }, + #[codec(index = 14)] + bond_extra_other { + member: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + extra: runtime_types::pallet_nomination_pools::BondExtra< + ::core::primitive::u128, + >, + }, + #[codec(index = 15)] + set_claim_permission { + permission: runtime_types::pallet_nomination_pools::ClaimPermission, + }, + #[codec(index = 16)] + claim_payout_other { other: ::sp_core::crypto::AccountId32 }, + #[codec(index = 17)] + set_commission { + pool_id: ::core::primitive::u32, + new_commission: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + }, + #[codec(index = 18)] + set_commission_max { + pool_id: ::core::primitive::u32, + max_commission: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 19)] + set_commission_change_rate { + pool_id: ::core::primitive::u32, + change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + }, + #[codec(index = 20)] + claim_commission { pool_id: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DefensiveError { + #[codec(index = 0)] + NotEnoughSpaceInUnbondPool, + #[codec(index = 1)] + PoolNotFound, + #[codec(index = 2)] + RewardPoolNotFound, + #[codec(index = 3)] + SubPoolsNotFound, + #[codec(index = 4)] + BondedStashKilledPrematurely, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + PoolNotFound, + #[codec(index = 1)] + PoolMemberNotFound, + #[codec(index = 2)] + RewardPoolNotFound, + #[codec(index = 3)] + SubPoolsNotFound, + #[codec(index = 4)] + AccountBelongsToOtherPool, + #[codec(index = 5)] + FullyUnbonding, + #[codec(index = 6)] + MaxUnbondingLimit, + #[codec(index = 7)] + CannotWithdrawAny, + #[codec(index = 8)] + MinimumBondNotMet, + #[codec(index = 9)] + OverflowRisk, + #[codec(index = 10)] + NotDestroying, + #[codec(index = 11)] + NotNominator, + #[codec(index = 12)] + NotKickerOrDestroying, + #[codec(index = 13)] + NotOpen, + #[codec(index = 14)] + MaxPools, + #[codec(index = 15)] + MaxPoolMembers, + #[codec(index = 16)] + CanNotChangeState, + #[codec(index = 17)] + DoesNotHavePermission, + #[codec(index = 18)] + MetadataExceedsMaxLen, + #[codec(index = 19)] + Defensive(runtime_types::pallet_nomination_pools::pallet::DefensiveError), + #[codec(index = 20)] + PartialUnbondNotAllowedPermissionlessly, + #[codec(index = 21)] + MaxCommissionRestricted, + #[codec(index = 22)] + CommissionExceedsMaximum, + #[codec(index = 23)] + CommissionChangeThrottled, + #[codec(index = 24)] + CommissionChangeRateNotAllowed, + #[codec(index = 25)] + NoPendingCommission, + #[codec(index = 26)] + NoCommissionCurrentSet, + #[codec(index = 27)] + PoolIdInUse, + #[codec(index = 28)] + InvalidPoolId, + #[codec(index = 29)] + BondExtraRestricted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { + depositor: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + }, + #[codec(index = 1)] + Bonded { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + bonded: ::core::primitive::u128, + joined: ::core::primitive::bool, + }, + #[codec(index = 2)] + PaidOut { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + payout: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unbonded { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + points: ::core::primitive::u128, + era: ::core::primitive::u32, + }, + #[codec(index = 4)] + Withdrawn { + member: ::sp_core::crypto::AccountId32, + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + points: ::core::primitive::u128, + }, + #[codec(index = 5)] + Destroyed { pool_id: ::core::primitive::u32 }, + #[codec(index = 6)] + StateChanged { + pool_id: ::core::primitive::u32, + new_state: runtime_types::pallet_nomination_pools::PoolState, + }, + #[codec(index = 7)] + MemberRemoved { + pool_id: ::core::primitive::u32, + member: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 8)] + RolesUpdated { + root: ::core::option::Option<::sp_core::crypto::AccountId32>, + bouncer: ::core::option::Option<::sp_core::crypto::AccountId32>, + nominator: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 9)] + PoolSlashed { + pool_id: ::core::primitive::u32, + balance: ::core::primitive::u128, + }, + #[codec(index = 10)] + UnbondingPoolSlashed { + pool_id: ::core::primitive::u32, + era: ::core::primitive::u32, + balance: ::core::primitive::u128, + }, + #[codec(index = 11)] + PoolCommissionUpdated { + pool_id: ::core::primitive::u32, + current: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + }, + #[codec(index = 12)] + PoolMaxCommissionUpdated { + pool_id: ::core::primitive::u32, + max_commission: runtime_types::sp_arithmetic::per_things::Perbill, + }, + #[codec(index = 13)] + PoolCommissionChangeRateUpdated { + pool_id: ::core::primitive::u32, + change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + }, + #[codec(index = 14)] + PoolCommissionClaimed { + pool_id: ::core::primitive::u32, + commission: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BondExtra<_0> { + #[codec(index = 0)] + FreeBalance(_0), + #[codec(index = 1)] + Rewards, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BondedPoolInner { + pub commission: runtime_types::pallet_nomination_pools::Commission, + pub member_counter: ::core::primitive::u32, + pub points: ::core::primitive::u128, + pub roles: runtime_types::pallet_nomination_pools::PoolRoles< + ::sp_core::crypto::AccountId32, + >, + pub state: runtime_types::pallet_nomination_pools::PoolState, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ClaimPermission { + #[codec(index = 0)] + Permissioned, + #[codec(index = 1)] + PermissionlessCompound, + #[codec(index = 2)] + PermissionlessWithdraw, + #[codec(index = 3)] + PermissionlessAll, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commission { + pub current: ::core::option::Option<( + runtime_types::sp_arithmetic::per_things::Perbill, + ::sp_core::crypto::AccountId32, + )>, + pub max: ::core::option::Option, + pub change_rate: ::core::option::Option< + runtime_types::pallet_nomination_pools::CommissionChangeRate< + ::core::primitive::u32, + >, + >, + pub throttle_from: ::core::option::Option<::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommissionChangeRate<_0> { + pub max_increase: runtime_types::sp_arithmetic::per_things::Perbill, + pub min_delay: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConfigOp<_0> { + #[codec(index = 0)] + Noop, + #[codec(index = 1)] + Set(_0), + #[codec(index = 2)] + Remove, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PoolMember { + pub pool_id: ::core::primitive::u32, + pub points: ::core::primitive::u128, + pub last_recorded_reward_counter: + runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub unbonding_eras: + runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< + ::core::primitive::u32, + ::core::primitive::u128, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PoolRoles<_0> { + pub depositor: _0, + pub root: ::core::option::Option<_0>, + pub nominator: ::core::option::Option<_0>, + pub bouncer: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PoolState { + #[codec(index = 0)] + Open, + #[codec(index = 1)] + Blocked, + #[codec(index = 2)] + Destroying, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardPool { + pub last_recorded_reward_counter: + runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub last_recorded_total_payouts: ::core::primitive::u128, + pub total_rewards_claimed: ::core::primitive::u128, + pub total_commission_pending: ::core::primitive::u128, + pub total_commission_claimed: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SubPools { + pub no_era: runtime_types::pallet_nomination_pools::UnbondPool, + pub with_era: + runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< + ::core::primitive::u32, + runtime_types::pallet_nomination_pools::UnbondPool, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnbondPool { + pub points: ::core::primitive::u128, + pub balance: ::core::primitive::u128, + } + } + pub mod pallet_offences { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Offence { + kind: [::core::primitive::u8; 16usize], + timeslot: ::std::vec::Vec<::core::primitive::u8>, + }, + } + } + } + pub mod pallet_preimage { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + unnote_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + request_preimage { hash: ::subxt::utils::H256 }, + #[codec(index = 3)] + unrequest_preimage { hash: ::subxt::utils::H256 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooBig, + #[codec(index = 1)] + AlreadyNoted, + #[codec(index = 2)] + NotAuthorized, + #[codec(index = 3)] + NotNoted, + #[codec(index = 4)] + Requested, + #[codec(index = 5)] + NotRequested, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Noted { hash: ::subxt::utils::H256 }, + #[codec(index = 1)] + Requested { hash: ::subxt::utils::H256 }, + #[codec(index = 2)] + Cleared { hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RequestStatus<_0, _1> { + #[codec(index = 0)] + Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, + #[codec(index = 1)] + Requested { + deposit: ::core::option::Option<(_0, _1)>, + count: ::core::primitive::u32, + len: ::core::option::Option<::core::primitive::u32>, + }, + } + } + pub mod pallet_proxy { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + proxy { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + add_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::westend_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 2)] + remove_proxy { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::westend_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 3)] + remove_proxies, + #[codec(index = 4)] + create_pure { + proxy_type: runtime_types::westend_runtime::ProxyType, + delay: ::core::primitive::u32, + index: ::core::primitive::u16, + }, + #[codec(index = 5)] + kill_pure { + spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + proxy_type: runtime_types::westend_runtime::ProxyType, + index: ::core::primitive::u16, + #[codec(compact)] + height: ::core::primitive::u32, + #[codec(compact)] + ext_index: ::core::primitive::u32, + }, + #[codec(index = 6)] + announce { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 7)] + remove_announcement { + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 8)] + reject_announcement { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 9)] + proxy_announced { + delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + force_proxy_type: + ::core::option::Option, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooMany, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + NotProxy, + #[codec(index = 3)] + Unproxyable, + #[codec(index = 4)] + Duplicate, + #[codec(index = 5)] + NoPermission, + #[codec(index = 6)] + Unannounced, + #[codec(index = 7)] + NoSelfProxy, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ProxyExecuted { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + PureCreated { + pure: ::sp_core::crypto::AccountId32, + who: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::westend_runtime::ProxyType, + disambiguation_index: ::core::primitive::u16, + }, + #[codec(index = 2)] + Announced { + real: ::sp_core::crypto::AccountId32, + proxy: ::sp_core::crypto::AccountId32, + call_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + ProxyAdded { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::westend_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + #[codec(index = 4)] + ProxyRemoved { + delegator: ::sp_core::crypto::AccountId32, + delegatee: ::sp_core::crypto::AccountId32, + proxy_type: runtime_types::westend_runtime::ProxyType, + delay: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Announcement<_0, _1, _2> { + pub real: _0, + pub call_hash: _1, + pub height: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ProxyDefinition<_0, _1, _2> { + pub delegate: _0, + pub proxy_type: _1, + pub delay: _2, + } + } + pub mod pallet_recovery { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_recovered { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + set_recovered { + lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + create_recovery { + friends: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + threshold: ::core::primitive::u16, + delay_period: ::core::primitive::u32, + }, + #[codec(index = 3)] + initiate_recovery { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 4)] + vouch_recovery { + lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 5)] + claim_recovery { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 6)] + close_recovery { + rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 7)] + remove_recovery, + #[codec(index = 8)] + cancel_recovered { + account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotAllowed, + #[codec(index = 1)] + ZeroThreshold, + #[codec(index = 2)] + NotEnoughFriends, + #[codec(index = 3)] + MaxFriends, + #[codec(index = 4)] + NotSorted, + #[codec(index = 5)] + NotRecoverable, + #[codec(index = 6)] + AlreadyRecoverable, + #[codec(index = 7)] + AlreadyStarted, + #[codec(index = 8)] + NotStarted, + #[codec(index = 9)] + NotFriend, + #[codec(index = 10)] + DelayPeriod, + #[codec(index = 11)] + AlreadyVouched, + #[codec(index = 12)] + Threshold, + #[codec(index = 13)] + StillActive, + #[codec(index = 14)] + AlreadyProxy, + #[codec(index = 15)] + BadState, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RecoveryCreated { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 1)] + RecoveryInitiated { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 2)] + RecoveryVouched { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + sender: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + RecoveryClosed { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 4)] + AccountRecovered { + lost_account: ::sp_core::crypto::AccountId32, + rescuer_account: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 5)] + RecoveryRemoved { lost_account: ::sp_core::crypto::AccountId32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ActiveRecovery<_0, _1, _2> { + pub created: _0, + pub deposit: _1, + pub friends: _2, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RecoveryConfig<_0, _1, _2> { + pub delay_period: _0, + pub deposit: _1, + pub friends: _2, + pub threshold: ::core::primitive::u16, + } + } + pub mod pallet_scheduler { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + schedule { + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 1)] + cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + schedule_named { + id: [::core::primitive::u8; 32usize], + when: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 3)] + cancel_named { id: [::core::primitive::u8; 32usize] }, + #[codec(index = 4)] + schedule_after { + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + #[codec(index = 5)] + schedule_named_after { + id: [::core::primitive::u8; 32usize], + after: ::core::primitive::u32, + maybe_periodic: ::core::option::Option<( + ::core::primitive::u32, + ::core::primitive::u32, + )>, + priority: ::core::primitive::u8, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSchedule, + #[codec(index = 1)] + NotFound, + #[codec(index = 2)] + TargetBlockNumberInPast, + #[codec(index = 3)] + RescheduleNoChange, + #[codec(index = 4)] + Named, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 1)] + Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, + #[codec(index = 2)] + Dispatched { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + CallUnavailable { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 4)] + PeriodicFailed { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + #[codec(index = 5)] + PermanentlyOverweight { + task: (::core::primitive::u32, ::core::primitive::u32), + id: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Scheduled<_0, _1, _2, _3, _4> { + pub maybe_id: ::core::option::Option<_0>, + pub priority: ::core::primitive::u8, + pub call: _1, + pub maybe_periodic: ::core::option::Option<(_2, _2)>, + pub origin: _3, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::westend_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_staking { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + bond { + #[codec(compact)] + value: ::core::primitive::u128, + payee: runtime_types::pallet_staking::RewardDestination< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 1)] + bond_extra { + #[codec(compact)] + max_additional: ::core::primitive::u128, + }, + #[codec(index = 2)] + unbond { + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + withdraw_unbonded { num_slashing_spans: ::core::primitive::u32 }, + #[codec(index = 4)] + validate { prefs: runtime_types::pallet_staking::ValidatorPrefs }, + #[codec(index = 5)] + nominate { + targets: ::std::vec::Vec< + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + >, + }, + #[codec(index = 6)] + chill, + #[codec(index = 7)] + set_payee { + payee: runtime_types::pallet_staking::RewardDestination< + ::sp_core::crypto::AccountId32, + >, + }, + #[codec(index = 8)] + set_controller, + #[codec(index = 9)] + set_validator_count { + #[codec(compact)] + new: ::core::primitive::u32, + }, + #[codec(index = 10)] + increase_validator_count { + #[codec(compact)] + additional: ::core::primitive::u32, + }, + #[codec(index = 11)] + scale_validator_count { + factor: runtime_types::sp_arithmetic::per_things::Percent, + }, + #[codec(index = 12)] + force_no_eras, + #[codec(index = 13)] + force_new_era, + #[codec(index = 14)] + set_invulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 15)] + force_unstake { + stash: ::sp_core::crypto::AccountId32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 16)] + force_new_era_always, + #[codec(index = 17)] + cancel_deferred_slash { + era: ::core::primitive::u32, + slash_indices: ::std::vec::Vec<::core::primitive::u32>, + }, + #[codec(index = 18)] + payout_stakers { + validator_stash: ::sp_core::crypto::AccountId32, + era: ::core::primitive::u32, + }, + #[codec(index = 19)] + rebond { + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 20)] + reap_stash { + stash: ::sp_core::crypto::AccountId32, + num_slashing_spans: ::core::primitive::u32, + }, + #[codec(index = 21)] + kick { + who: ::std::vec::Vec< + ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + >, + }, + #[codec(index = 22)] + set_staking_configs { + min_nominator_bond: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u128, + >, + min_validator_bond: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u128, + >, + max_nominator_count: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u32, + >, + max_validator_count: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + ::core::primitive::u32, + >, + chill_threshold: + runtime_types::pallet_staking::pallet::pallet::ConfigOp< + runtime_types::sp_arithmetic::per_things::Percent, + >, + min_commission: runtime_types::pallet_staking::pallet::pallet::ConfigOp< + runtime_types::sp_arithmetic::per_things::Perbill, + >, + }, + #[codec(index = 23)] + chill_other { controller: ::sp_core::crypto::AccountId32 }, + #[codec(index = 24)] + force_apply_min_commission { + validator_stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 25)] + set_min_commission { + new: runtime_types::sp_arithmetic::per_things::Perbill, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConfigOp<_0> { + #[codec(index = 0)] + Noop, + #[codec(index = 1)] + Set(_0), + #[codec(index = 2)] + Remove, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotController, + #[codec(index = 1)] + NotStash, + #[codec(index = 2)] + AlreadyBonded, + #[codec(index = 3)] + AlreadyPaired, + #[codec(index = 4)] + EmptyTargets, + #[codec(index = 5)] + DuplicateIndex, + #[codec(index = 6)] + InvalidSlashIndex, + #[codec(index = 7)] + InsufficientBond, + #[codec(index = 8)] + NoMoreChunks, + #[codec(index = 9)] + NoUnlockChunk, + #[codec(index = 10)] + FundedTarget, + #[codec(index = 11)] + InvalidEraToReward, + #[codec(index = 12)] + InvalidNumberOfNominations, + #[codec(index = 13)] + NotSortedAndUnique, + #[codec(index = 14)] + AlreadyClaimed, + #[codec(index = 15)] + IncorrectHistoryDepth, + #[codec(index = 16)] + IncorrectSlashingSpans, + #[codec(index = 17)] + BadState, + #[codec(index = 18)] + TooManyTargets, + #[codec(index = 19)] + BadTarget, + #[codec(index = 20)] + CannotChillOther, + #[codec(index = 21)] + TooManyNominators, + #[codec(index = 22)] + TooManyValidators, + #[codec(index = 23)] + CommissionTooLow, + #[codec(index = 24)] + BoundNotMet, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + EraPaid { + era_index: ::core::primitive::u32, + validator_payout: ::core::primitive::u128, + remainder: ::core::primitive::u128, + }, + #[codec(index = 1)] + Rewarded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Slashed { + staker: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + SlashReported { + validator: ::sp_core::crypto::AccountId32, + fraction: runtime_types::sp_arithmetic::per_things::Perbill, + slash_era: ::core::primitive::u32, + }, + #[codec(index = 4)] + OldSlashingReportDiscarded { session_index: ::core::primitive::u32 }, + #[codec(index = 5)] + StakersElected, + #[codec(index = 6)] + Bonded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 7)] + Unbonded { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 8)] + Withdrawn { + stash: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Kicked { + nominator: ::sp_core::crypto::AccountId32, + stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 10)] + StakingElectionFailed, + #[codec(index = 11)] + Chilled { stash: ::sp_core::crypto::AccountId32 }, + #[codec(index = 12)] + PayoutStarted { + era_index: ::core::primitive::u32, + validator_stash: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 13)] + ValidatorPrefsSet { + stash: ::sp_core::crypto::AccountId32, + prefs: runtime_types::pallet_staking::ValidatorPrefs, + }, + #[codec(index = 14)] + ForceEra { mode: runtime_types::pallet_staking::Forcing }, + } + } + } + pub mod slashing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SlashingSpans { + pub span_index: ::core::primitive::u32, + pub last_start: ::core::primitive::u32, + pub last_nonzero_slash: ::core::primitive::u32, + pub prior: ::std::vec::Vec<::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SpanRecord<_0> { + pub slashed: _0, + pub paid_out: _0, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ActiveEraInfo { + pub index: ::core::primitive::u32, + pub start: ::core::option::Option<::core::primitive::u64>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EraRewardPoints<_0> { + pub total: ::core::primitive::u32, + pub individual: ::subxt::utils::KeyedVec<_0, ::core::primitive::u32>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Exposure<_0, _1> { + #[codec(compact)] + pub total: _1, + #[codec(compact)] + pub own: _1, + pub others: + ::std::vec::Vec>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Forcing { + #[codec(index = 0)] + NotForcing, + #[codec(index = 1)] + ForceNew, + #[codec(index = 2)] + ForceNone, + #[codec(index = 3)] + ForceAlways, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndividualExposure<_0, _1> { + pub who: _0, + #[codec(compact)] + pub value: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Nominations { + pub targets: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::sp_core::crypto::AccountId32, + >, + pub submitted_in: ::core::primitive::u32, + pub suppressed: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardDestination<_0> { + #[codec(index = 0)] + Staked, + #[codec(index = 1)] + Stash, + #[codec(index = 2)] + Controller, + #[codec(index = 3)] + Account(_0), + #[codec(index = 4)] + None, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StakingLedger { + pub stash: ::sp_core::crypto::AccountId32, + #[codec(compact)] + pub total: ::core::primitive::u128, + #[codec(compact)] + pub active: ::core::primitive::u128, + pub unlocking: runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::pallet_staking::UnlockChunk<::core::primitive::u128>, + >, + pub claimed_rewards: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnappliedSlash<_0, _1> { + pub validator: _0, + pub own: _1, + pub others: ::std::vec::Vec<(_0, _1)>, + pub reporters: ::std::vec::Vec<_0>, + pub payout: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnlockChunk<_0> { + #[codec(compact)] + pub value: _0, + #[codec(compact)] + pub era: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidatorPrefs { + #[codec(compact)] + pub commission: runtime_types::sp_arithmetic::per_things::Perbill, + pub blocked: ::core::primitive::bool, + } + } + pub mod pallet_sudo { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + sudo { call: ::std::boxed::Box }, + #[codec(index = 1)] + sudo_unchecked_weight { + call: ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + set_key { + new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 3)] + sudo_as { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + call: ::std::boxed::Box, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + RequireSudo, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Sudid { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 1)] + KeyChanged { + old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 2)] + SudoAsDone { + sudo_result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { calls: ::std::vec::Vec }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box, + }, + #[codec(index = 2)] + batch_all { + calls: ::std::vec::Vec, + }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box, + call: ::std::boxed::Box, + }, + #[codec(index = 4)] + force_batch { + calls: ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_vesting { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + vest, + #[codec(index = 1)] + vest_other { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + }, + #[codec(index = 2)] + vested_transfer { + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 3)] + force_vested_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< + ::core::primitive::u128, + ::core::primitive::u32, + >, + }, + #[codec(index = 4)] + merge_schedules { + schedule1_index: ::core::primitive::u32, + schedule2_index: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotVesting, + #[codec(index = 1)] + AtMaxVestingSchedules, + #[codec(index = 2)] + AmountLow, + #[codec(index = 3)] + ScheduleIndexOutOfBounds, + #[codec(index = 4)] + InvalidScheduleParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + VestingUpdated { + account: ::sp_core::crypto::AccountId32, + unvested: ::core::primitive::u128, + }, + #[codec(index = 1)] + VestingCompleted { account: ::sp_core::crypto::AccountId32 }, + } + } + pub mod vesting_info { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VestingInfo<_0, _1> { + pub locked: _0, + pub per_block: _0, + pub starting_block: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V0, + #[codec(index = 1)] + V1, + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: + ::std::boxed::Box, + xcm_version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted(runtime_types::xcm::v3::traits::Outcome), + #[codec(index = 1)] + Sent( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::Xcm, + ), + #[codec(index = 2)] + UnexpectedResponse( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 3)] + ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + #[codec(index = 4)] + Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + #[codec(index = 5)] + NotifyOverweight( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ::sp_weights::Weight, + ::sp_weights::Weight, + ), + #[codec(index = 6)] + NotifyDispatchError( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 7)] + NotifyDecodeFailed( + ::core::primitive::u64, + ::core::primitive::u8, + ::core::primitive::u8, + ), + #[codec(index = 8)] + InvalidResponder( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 9)] + InvalidResponderVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 10)] + ResponseTaken(::core::primitive::u64), + #[codec(index = 11)] + AssetsTrapped( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + #[codec(index = 12)] + VersionChangeNotified( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 13)] + SupportedVersionChanged( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u32, + ), + #[codec(index = 14)] + NotifyTargetSendFail( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::traits::Error, + ), + #[codec(index = 15)] + NotifyTargetMigrationFail( + runtime_types::xcm::VersionedMultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 16)] + InvalidQuerierVersion( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + ), + #[codec(index = 17)] + InvalidQuerier( + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::primitive::u64, + runtime_types::xcm::v3::multilocation::MultiLocation, + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 18)] + VersionNotifyStarted( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 19)] + VersionNotifyRequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 20)] + VersionNotifyUnrequested( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 21)] + FeesPaid( + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::v3::multiasset::MultiAssets, + ), + #[codec(index = 22)] + AssetsClaimed( + ::subxt::utils::H256, + runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::xcm::VersionedMultiAssets, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateHash(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelId { + pub sender: runtime_types::polkadot_parachain::primitives::Id, + pub recipient: runtime_types::polkadot_parachain::primitives::Id, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCodeHash(pub ::subxt::utils::H256); + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v4 { + use super::runtime_types; + pub mod assignment_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod collator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + pub mod executor_params { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ExecutorParam { + #[codec(index = 1)] + MaxMemoryPages(::core::primitive::u32), + #[codec(index = 2)] + StackLogicalMax(::core::primitive::u32), + #[codec(index = 3)] + StackNativeMax(::core::primitive::u32), + #[codec(index = 4)] + PrecheckingMaxMemory(::core::primitive::u64), + #[codec(index = 5)] + PvfPrepTimeout( + runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 6)] + PvfExecTimeout( + runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, + ::core::primitive::u64, + ), + #[codec(index = 7)] + WasmExtBulkMemory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutorParams( + pub ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, + >, + ); + } + pub mod signed { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedSigned<_0, _1> { + pub payload: _0, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + pub signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, + } + } + pub mod validator_app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfield( + pub ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BackedCandidate<_0> { + pub candidate: + runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, + pub validity_votes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::ValidityAttestation, + >, + pub validator_indices: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateCommitments<_0> { + pub upward_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::std::vec::Vec<::core::primitive::u8>, + >, + pub horizontal_messages: + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain::primitives::Id, + >, + >, + pub new_validation_code: ::core::option::Option< + runtime_types::polkadot_parachain::primitives::ValidationCode, + >, + pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, + pub processed_downward_messages: _0, + pub hrmp_watermark: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateDescriptor<_0> { + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub relay_parent: _0, + pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, + pub persisted_validation_data_hash: _0, + pub pov_hash: _0, + pub erasure_root: _0, + pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, + pub para_head: _0, + pub validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments_hash: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommittedCandidateReceipt<_0> { + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< + ::core::primitive::u32, + >, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct CoreIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum CoreOccupied { + #[codec(index = 0)] + Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), + #[codec(index = 1)] + Parachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeState<_0> { + pub validators_for: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub validators_against: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub start: _0, + pub concluded_at: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeStatement { + #[codec(index = 0)] + Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), + #[codec(index = 1)] + Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeStatementSet { + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub session: ::core::primitive::u32, + pub statements: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::DisputeStatement, + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Signature, + )>, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct GroupIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IndexedVec<_0, _1>( + pub ::std::vec::Vec<_1>, + #[codec(skip)] pub ::core::marker::PhantomData<_0>, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData<_0> { + pub bitfields: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + >, + >, + pub backed_candidates: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::BackedCandidate< + ::subxt::utils::H256, + >, + >, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + pub parent_header: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaim( + pub runtime_types::polkadot_parachain::primitives::Id, + pub runtime_types::polkadot_primitives::v4::collator_app::Public, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadEntry { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, + pub retries: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckStatement { + pub accept: ::core::primitive::bool, + pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + pub session_index: ::core::primitive::u32, + pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfExecTimeoutKind { + #[codec(index = 0)] + Backing, + #[codec(index = 1)] + Approval, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfPrepTimeoutKind { + #[codec(index = 0)] + Precheck, + #[codec(index = 1)] + Lenient, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ScrapedOnChainVotes<_0> { + pub session: ::core::primitive::u32, + pub backing_validators_per_candidate: ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, + ::std::vec::Vec<( + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::ValidityAttestation, + )>, + )>, + pub disputes: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::DisputeStatementSet, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionInfo { + pub active_validator_indices: + ::std::vec::Vec, + pub random_seed: [::core::primitive::u8; 32usize], + pub dispute_period: ::core::primitive::u32, + pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::ValidatorIndex, + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub discovery_keys: + ::std::vec::Vec, + pub assignment_keys: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::assignment_app::Public, + >, + pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< + runtime_types::polkadot_primitives::v4::GroupIndex, + ::std::vec::Vec, + >, + pub n_cores: ::core::primitive::u32, + pub zeroth_delay_tranche_width: ::core::primitive::u32, + pub relay_vrf_modulo_samples: ::core::primitive::u32, + pub n_delay_tranches: ::core::primitive::u32, + pub no_show_slots: ::core::primitive::u32, + pub needed_approvals: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidDisputeStatementKind { + #[codec(index = 0)] + Explicit, + #[codec(index = 1)] + BackingSeconded(::subxt::utils::H256), + #[codec(index = 2)] + BackingValid(::subxt::utils::H256), + #[codec(index = 3)] + ApprovalChecking, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ValidatorIndex(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ValidityAttestation { + #[codec(index = 1)] + Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + #[codec(index = 2)] + Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), + } + } + pub mod vstaging { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + } + pub mod polkadot_runtime_common { + use super::runtime_types; + pub mod assigned_slots { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] assign_perm_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , # [codec (index = 1)] assign_temp_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , lease_period_start : runtime_types :: polkadot_runtime_common :: assigned_slots :: SlotLeasePeriodStart , } , # [codec (index = 2)] unassign_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaDoesntExist, + #[codec(index = 1)] + NotParathread, + #[codec(index = 2)] + CannotUpgrade, + #[codec(index = 3)] + CannotDowngrade, + #[codec(index = 4)] + SlotAlreadyAssigned, + #[codec(index = 5)] + SlotNotAssigned, + #[codec(index = 6)] + OngoingLeaseExists, + #[codec(index = 7)] + MaxPermanentSlotsExceeded, + #[codec(index = 8)] + MaxTemporarySlotsExceeded, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + PermanentSlotAssigned(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + TemporarySlotAssigned(runtime_types::polkadot_parachain::primitives::Id), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParachainTemporarySlot<_0, _1> { + pub manager: _0, + pub period_begin: _1, + pub period_count: _1, + pub last_lease: ::core::option::Option<_1>, + pub lease_count: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SlotLeasePeriodStart { + #[codec(index = 0)] + Current, + #[codec(index = 1)] + Next, + } + } + pub mod auctions { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + new_auction { + #[codec(compact)] + duration: ::core::primitive::u32, + #[codec(compact)] + lease_period_index: ::core::primitive::u32, + }, + #[codec(index = 1)] + bid { + #[codec(compact)] + para: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + auction_index: ::core::primitive::u32, + #[codec(compact)] + first_slot: ::core::primitive::u32, + #[codec(compact)] + last_slot: ::core::primitive::u32, + #[codec(compact)] + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + cancel_auction, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + AuctionInProgress, + #[codec(index = 1)] + LeasePeriodInPast, + #[codec(index = 2)] + ParaNotRegistered, + #[codec(index = 3)] + NotCurrentAuction, + #[codec(index = 4)] + NotAuction, + #[codec(index = 5)] + AuctionEnded, + #[codec(index = 6)] + AlreadyLeasedOut, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + AuctionStarted { + auction_index: ::core::primitive::u32, + lease_period: ::core::primitive::u32, + ending: ::core::primitive::u32, + }, + #[codec(index = 1)] + AuctionClosed { auction_index: ::core::primitive::u32 }, + #[codec(index = 2)] + Reserved { + bidder: ::sp_core::crypto::AccountId32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + Unreserved { + bidder: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 4)] + ReserveConfiscated { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + BidAccepted { + bidder: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + first_slot: ::core::primitive::u32, + last_slot: ::core::primitive::u32, + }, + #[codec(index = 6)] + WinningOffset { + auction_index: ::core::primitive::u32, + block_number: ::core::primitive::u32, + }, + } + } + } + pub mod crowdloan { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + create { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 1)] + contribute { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + value: ::core::primitive::u128, + signature: + ::core::option::Option, + }, + #[codec(index = 2)] + withdraw { + who: ::sp_core::crypto::AccountId32, + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 3)] + refund { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + dissolve { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + edit { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + #[codec(compact)] + cap: ::core::primitive::u128, + #[codec(compact)] + first_period: ::core::primitive::u32, + #[codec(compact)] + last_period: ::core::primitive::u32, + #[codec(compact)] + end: ::core::primitive::u32, + verifier: + ::core::option::Option, + }, + #[codec(index = 6)] + add_memo { + index: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 7)] + poke { index: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + contribute_all { + #[codec(compact)] + index: runtime_types::polkadot_parachain::primitives::Id, + signature: + ::core::option::Option, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FirstPeriodInPast, + #[codec(index = 1)] + FirstPeriodTooFarInFuture, + #[codec(index = 2)] + LastPeriodBeforeFirstPeriod, + #[codec(index = 3)] + LastPeriodTooFarInFuture, + #[codec(index = 4)] + CannotEndInPast, + #[codec(index = 5)] + EndTooFarInFuture, + #[codec(index = 6)] + Overflow, + #[codec(index = 7)] + ContributionTooSmall, + #[codec(index = 8)] + InvalidParaId, + #[codec(index = 9)] + CapExceeded, + #[codec(index = 10)] + ContributionPeriodOver, + #[codec(index = 11)] + InvalidOrigin, + #[codec(index = 12)] + NotParachain, + #[codec(index = 13)] + LeaseActive, + #[codec(index = 14)] + BidOrLeaseActive, + #[codec(index = 15)] + FundNotEnded, + #[codec(index = 16)] + NoContributions, + #[codec(index = 17)] + NotReadyToDissolve, + #[codec(index = 18)] + InvalidSignature, + #[codec(index = 19)] + MemoTooLarge, + #[codec(index = 20)] + AlreadyInNewRaise, + #[codec(index = 21)] + VrfDelayInProgress, + #[codec(index = 22)] + NoLeasePeriod, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 1)] + Contributed { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Withdrew { + who: ::sp_core::crypto::AccountId32, + fund_index: runtime_types::polkadot_parachain::primitives::Id, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + PartiallyRefunded { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 6)] + HandleBidResult { + para_id: runtime_types::polkadot_parachain::primitives::Id, + result: ::core::result::Result< + (), + runtime_types::sp_runtime::DispatchError, + >, + }, + #[codec(index = 7)] + Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 8)] + MemoUpdated { + who: ::sp_core::crypto::AccountId32, + para_id: runtime_types::polkadot_parachain::primitives::Id, + memo: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 9)] + AddedToNewRaise { + para_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FundInfo<_0, _1, _2, _3> { + pub depositor: _0, + pub verifier: ::core::option::Option, + pub deposit: _1, + pub raised: _1, + pub end: _2, + pub cap: _1, + pub last_contribution: + runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, + pub first_period: _2, + pub last_period: _2, + pub fund_index: _2, + #[codec(skip)] + pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum LastContribution<_0> { + #[codec(index = 0)] + Never, + #[codec(index = 1)] + PreEnding(_0), + #[codec(index = 2)] + Ending(_0), + } + } + pub mod paras_registrar { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + register { + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_register { + who: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + id: runtime_types::polkadot_parachain::primitives::Id, + genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 2)] + deregister { id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 3)] + swap { + id: runtime_types::polkadot_parachain::primitives::Id, + other: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 5)] + reserve, + #[codec(index = 6)] + add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 7)] + schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 8)] + set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + AlreadyRegistered, + #[codec(index = 2)] + NotOwner, + #[codec(index = 3)] + CodeTooLarge, + #[codec(index = 4)] + HeadDataTooLarge, + #[codec(index = 5)] + NotParachain, + #[codec(index = 6)] + NotParathread, + #[codec(index = 7)] + CannotDeregister, + #[codec(index = 8)] + CannotDowngrade, + #[codec(index = 9)] + CannotUpgrade, + #[codec(index = 10)] + ParaLocked, + #[codec(index = 11)] + NotReserved, + #[codec(index = 12)] + EmptyCode, + #[codec(index = 13)] + CannotSwap, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Registered { + para_id: runtime_types::polkadot_parachain::primitives::Id, + manager: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 1)] + Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + Reserved { + para_id: runtime_types::polkadot_parachain::primitives::Id, + who: ::sp_core::crypto::AccountId32, + }, + #[codec(index = 3)] + Swapped { + para_id: runtime_types::polkadot_parachain::primitives::Id, + other_id: runtime_types::polkadot_parachain::primitives::Id, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo<_0, _1> { + pub manager: _0, + pub deposit: _1, + pub locked: ::core::primitive::bool, + } + } + pub mod paras_sudo_wrapper { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + sudo_schedule_para_initialize { + id: runtime_types::polkadot_parachain::primitives::Id, + genesis: + runtime_types::polkadot_runtime_parachains::paras::ParaGenesisArgs, + }, + #[codec(index = 1)] + sudo_schedule_para_cleanup { + id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 2)] + sudo_schedule_parathread_upgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 3)] + sudo_schedule_parachain_downgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 4)] + sudo_queue_downward_xcm { + id: runtime_types::polkadot_parachain::primitives::Id, + xcm: ::std::boxed::Box, + }, + #[codec(index = 5)] + sudo_establish_hrmp_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + recipient: runtime_types::polkadot_parachain::primitives::Id, + max_capacity: ::core::primitive::u32, + max_message_size: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaDoesntExist, + #[codec(index = 1)] + ParaAlreadyExists, + #[codec(index = 2)] + ExceedsMaxMessageSize, + #[codec(index = 3)] + CouldntCleanup, + #[codec(index = 4)] + NotParathread, + #[codec(index = 5)] + NotParachain, + #[codec(index = 6)] + CannotUpgrade, + #[codec(index = 7)] + CannotDowngrade, + } + } + } + pub mod slots { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_lease { + para: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + }, + #[codec(index = 1)] + clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, + #[codec(index = 2)] + trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + ParaNotOnboarding, + #[codec(index = 1)] + LeaseError, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewLeasePeriod { lease_period: ::core::primitive::u32 }, + #[codec(index = 1)] + Leased { + para_id: runtime_types::polkadot_parachain::primitives::Id, + leaser: ::sp_core::crypto::AccountId32, + period_begin: ::core::primitive::u32, + period_count: ::core::primitive::u32, + extra_reserved: ::core::primitive::u128, + total_amount: ::core::primitive::u128, + }, + } + } + } + } + pub mod polkadot_runtime_parachains { + use super::runtime_types; + pub mod configuration { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidNewValue, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HostConfiguration<_0> { + pub max_code_size: _0, + pub max_head_data_size: _0, + pub max_upward_queue_count: _0, + pub max_upward_queue_size: _0, + pub max_upward_message_size: _0, + pub max_upward_message_num_per_candidate: _0, + pub hrmp_max_message_num_per_candidate: _0, + pub validation_upgrade_cooldown: _0, + pub validation_upgrade_delay: _0, + pub async_backing_params: + runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, + pub max_pov_size: _0, + pub max_downward_message_size: _0, + pub hrmp_max_parachain_outbound_channels: _0, + pub hrmp_max_parathread_outbound_channels: _0, + pub hrmp_sender_deposit: ::core::primitive::u128, + pub hrmp_recipient_deposit: ::core::primitive::u128, + pub hrmp_channel_max_capacity: _0, + pub hrmp_channel_max_total_size: _0, + pub hrmp_max_parachain_inbound_channels: _0, + pub hrmp_max_parathread_inbound_channels: _0, + pub hrmp_channel_max_message_size: _0, + pub executor_params: + runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, + pub code_retention_period: _0, + pub parathread_cores: _0, + pub parathread_retries: _0, + pub group_rotation_frequency: _0, + pub chain_availability_period: _0, + pub thread_availability_period: _0, + pub scheduling_lookahead: _0, + pub max_validators_per_core: ::core::option::Option<_0>, + pub max_validators: ::core::option::Option<_0>, + pub dispute_period: _0, + pub dispute_post_conclusion_acceptance_period: _0, + pub no_show_slots: _0, + pub n_delay_tranches: _0, + pub zeroth_delay_tranche_width: _0, + pub needed_approvals: _0, + pub relay_vrf_modulo_samples: _0, + pub pvf_checking_enabled: ::core::primitive::bool, + pub pvf_voting_ttl: _0, + pub minimum_validation_upgrade_delay: _0, + } + } + pub mod disputes { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_unfreeze, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateDisputeStatementSets, + #[codec(index = 1)] + AncientDisputeStatement, + #[codec(index = 2)] + ValidatorIndexOutOfBounds, + #[codec(index = 3)] + InvalidSignature, + #[codec(index = 4)] + DuplicateStatement, + #[codec(index = 5)] + SingleSidedDispute, + #[codec(index = 6)] + MaliciousBacker, + #[codec(index = 7)] + MissingBackingVotes, + #[codec(index = 8)] + UnconfirmedDispute, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + DisputeInitiated( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, + ), + #[codec(index = 1)] + DisputeConcluded( + runtime_types::polkadot_core_primitives::CandidateHash, + runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, + ), + #[codec(index = 2)] + Revert(::core::primitive::u32), + } + } + pub mod slashing { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Call { + # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum Error { + #[codec(index = 0)] + InvalidKeyOwnershipProof, + #[codec(index = 1)] + InvalidSessionIndex, + #[codec(index = 2)] + InvalidCandidateHash, + #[codec(index = 3)] + InvalidValidatorIndex, + #[codec(index = 4)] + ValidatorIndexIdMismatch, + #[codec(index = 5)] + DuplicateSlashingReport, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DisputesTimeSlot { + pub session_index: ::core::primitive::u32, + pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SlashingOffenceKind { + #[codec(index = 0)] + ForInvalid, + #[codec(index = 1)] + AgainstValid, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeLocation { + #[codec(index = 0)] + Local, + #[codec(index = 1)] + Remote, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DisputeResult { + #[codec(index = 0)] + Valid, + #[codec(index = 1)] + Invalid, + } + } + pub mod hrmp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + hrmp_init_open_channel { + recipient: runtime_types::polkadot_parachain::primitives::Id, + proposed_max_capacity: ::core::primitive::u32, + proposed_max_message_size: ::core::primitive::u32, + }, + #[codec(index = 1)] + hrmp_accept_open_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 2)] + hrmp_close_channel { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + }, + #[codec(index = 3)] + force_clean_hrmp { + para: runtime_types::polkadot_parachain::primitives::Id, + inbound: ::core::primitive::u32, + outbound: ::core::primitive::u32, + }, + #[codec(index = 4)] + force_process_hrmp_open { channels: ::core::primitive::u32 }, + #[codec(index = 5)] + force_process_hrmp_close { channels: ::core::primitive::u32 }, + #[codec(index = 6)] + hrmp_cancel_open_request { + channel_id: + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + open_requests: ::core::primitive::u32, + }, + #[codec(index = 7)] + force_open_hrmp_channel { + sender: runtime_types::polkadot_parachain::primitives::Id, + recipient: runtime_types::polkadot_parachain::primitives::Id, + max_capacity: ::core::primitive::u32, + max_message_size: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OpenHrmpChannelToSelf, + #[codec(index = 1)] + OpenHrmpChannelInvalidRecipient, + #[codec(index = 2)] + OpenHrmpChannelZeroCapacity, + #[codec(index = 3)] + OpenHrmpChannelCapacityExceedsLimit, + #[codec(index = 4)] + OpenHrmpChannelZeroMessageSize, + #[codec(index = 5)] + OpenHrmpChannelMessageSizeExceedsLimit, + #[codec(index = 6)] + OpenHrmpChannelAlreadyExists, + #[codec(index = 7)] + OpenHrmpChannelAlreadyRequested, + #[codec(index = 8)] + OpenHrmpChannelLimitExceeded, + #[codec(index = 9)] + AcceptHrmpChannelDoesntExist, + #[codec(index = 10)] + AcceptHrmpChannelAlreadyConfirmed, + #[codec(index = 11)] + AcceptHrmpChannelLimitExceeded, + #[codec(index = 12)] + CloseHrmpChannelUnauthorized, + #[codec(index = 13)] + CloseHrmpChannelDoesntExist, + #[codec(index = 14)] + CloseHrmpChannelAlreadyUnderway, + #[codec(index = 15)] + CancelHrmpOpenChannelUnauthorized, + #[codec(index = 16)] + OpenHrmpChannelDoesntExist, + #[codec(index = 17)] + OpenHrmpChannelAlreadyConfirmed, + #[codec(index = 18)] + WrongWitness, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + OpenChannelRequested( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + #[codec(index = 1)] + OpenChannelCanceled( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 2)] + OpenChannelAccepted( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 3)] + ChannelClosed( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::HrmpChannelId, + ), + #[codec(index = 4)] + HrmpChannelForceOpened( + runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ::core::primitive::u32, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + pub sender_deposit: ::core::primitive::u128, + pub recipient_deposit: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpOpenChannelRequest { + pub confirmed: ::core::primitive::bool, + pub _age: ::core::primitive::u32, + pub sender_deposit: ::core::primitive::u128, + pub max_message_size: ::core::primitive::u32, + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + } + } + pub mod inclusion { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnsortedOrDuplicateValidatorIndices, + #[codec(index = 1)] + UnsortedOrDuplicateDisputeStatementSet, + #[codec(index = 2)] + UnsortedOrDuplicateBackedCandidates, + #[codec(index = 3)] + UnexpectedRelayParent, + #[codec(index = 4)] + WrongBitfieldSize, + #[codec(index = 5)] + BitfieldAllZeros, + #[codec(index = 6)] + BitfieldDuplicateOrUnordered, + #[codec(index = 7)] + ValidatorIndexOutOfBounds, + #[codec(index = 8)] + InvalidBitfieldSignature, + #[codec(index = 9)] + UnscheduledCandidate, + #[codec(index = 10)] + CandidateScheduledBeforeParaFree, + #[codec(index = 11)] + WrongCollator, + #[codec(index = 12)] + ScheduledOutOfOrder, + #[codec(index = 13)] + HeadDataTooLarge, + #[codec(index = 14)] + PrematureCodeUpgrade, + #[codec(index = 15)] + NewCodeTooLarge, + #[codec(index = 16)] + CandidateNotInParentContext, + #[codec(index = 17)] + InvalidGroupIndex, + #[codec(index = 18)] + InsufficientBacking, + #[codec(index = 19)] + InvalidBacking, + #[codec(index = 20)] + NotCollatorSigned, + #[codec(index = 21)] + ValidationDataHashMismatch, + #[codec(index = 22)] + IncorrectDownwardMessageHandling, + #[codec(index = 23)] + InvalidUpwardMessages, + #[codec(index = 24)] + HrmpWatermarkMishandling, + #[codec(index = 25)] + InvalidOutboundHrmp, + #[codec(index = 26)] + InvalidValidationCodeHash, + #[codec(index = 27)] + ParaHeadMismatch, + #[codec(index = 28)] + BitfieldReferencesFreedCore, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CandidateBacked( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 1)] + CandidateIncluded( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + runtime_types::polkadot_primitives::v4::GroupIndex, + ), + #[codec(index = 2)] + CandidateTimedOut( + runtime_types::polkadot_primitives::v4::CandidateReceipt< + ::subxt::utils::H256, + >, + runtime_types::polkadot_parachain::primitives::HeadData, + runtime_types::polkadot_primitives::v4::CoreIndex, + ), + #[codec(index = 3)] + UpwardMessagesReceived { + from: runtime_types::polkadot_parachain::primitives::Id, + count: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AvailabilityBitfieldRecord<_0> { + pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, + pub submitted_at: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidatePendingAvailability<_0, _1> { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub hash: runtime_types::polkadot_core_primitives::CandidateHash, + pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, + pub availability_votes: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub backers: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub relay_parent_number: _1, + pub backed_in_number: _1, + pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UmpQueueId { + #[codec(index = 0)] + Para(runtime_types::polkadot_parachain::primitives::Id), + } + } + pub mod initializer { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_approve { up_to: ::core::primitive::u32 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BufferedSessionChange { + pub validators: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub queued: ::std::vec::Vec< + runtime_types::polkadot_primitives::v4::validator_app::Public, + >, + pub session_index: ::core::primitive::u32, + } + } + pub mod origin { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Parachain(runtime_types::polkadot_parachain::primitives::Id), + } + } + } + pub mod paras { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + force_set_current_code { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 1)] + force_set_current_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 2)] + force_schedule_code_upgrade { + para: runtime_types::polkadot_parachain::primitives::Id, + new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, + relay_parent_number: ::core::primitive::u32, + }, + #[codec(index = 3)] + force_note_new_head { + para: runtime_types::polkadot_parachain::primitives::Id, + new_head: runtime_types::polkadot_parachain::primitives::HeadData, + }, + #[codec(index = 4)] + force_queue_action { + para: runtime_types::polkadot_parachain::primitives::Id, + }, + #[codec(index = 5)] + add_trusted_validation_code { + validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + }, + #[codec(index = 6)] + poke_unused_validation_code { + validation_code_hash: + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + }, + #[codec(index = 7)] + include_pvf_check_statement { + stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, + signature: + runtime_types::polkadot_primitives::v4::validator_app::Signature, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotRegistered, + #[codec(index = 1)] + CannotOnboard, + #[codec(index = 2)] + CannotOffboard, + #[codec(index = 3)] + CannotUpgrade, + #[codec(index = 4)] + CannotDowngrade, + #[codec(index = 5)] + PvfCheckStatementStale, + #[codec(index = 6)] + PvfCheckStatementFuture, + #[codec(index = 7)] + PvfCheckValidatorIndexOutOfBounds, + #[codec(index = 8)] + PvfCheckInvalidSignature, + #[codec(index = 9)] + PvfCheckDoubleVote, + #[codec(index = 10)] + PvfCheckSubjectInvalid, + #[codec(index = 11)] + CannotUpgradeCode, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 2)] + CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 3)] + NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 4)] + ActionQueued( + runtime_types::polkadot_parachain::primitives::Id, + ::core::primitive::u32, + ), + #[codec(index = 5)] + PvfCheckStarted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 6)] + PvfCheckAccepted( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + #[codec(index = 7)] + PvfCheckRejected( + runtime_types::polkadot_parachain::primitives::ValidationCodeHash, + runtime_types::polkadot_parachain::primitives::Id, + ), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaGenesisArgs { + pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub validation_code: + runtime_types::polkadot_parachain::primitives::ValidationCode, + pub para_kind: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ParaLifecycle { + #[codec(index = 0)] + Onboarding, + #[codec(index = 1)] + Parathread, + #[codec(index = 2)] + Parachain, + #[codec(index = 3)] + UpgradingParathread, + #[codec(index = 4)] + DowngradingParachain, + #[codec(index = 5)] + OffboardingParathread, + #[codec(index = 6)] + OffboardingParachain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaPastCodeMeta<_0> { + pub upgrade_times: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, + >, + pub last_pruned: ::core::option::Option<_0>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PvfCheckActiveVoteState<_0> { + pub votes_accept: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub votes_reject: ::subxt::utils::bits::DecodedBits< + ::core::primitive::u8, + ::subxt::utils::bits::Lsb0, + >, + pub age: _0, + pub created_at: _0, + pub causes: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PvfCheckCause<_0> { + #[codec(index = 0)] + Onboarding(runtime_types::polkadot_parachain::primitives::Id), + #[codec(index = 1)] + Upgrade { + id: runtime_types::polkadot_parachain::primitives::Id, + relay_parent_number: _0, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReplacementTimes<_0> { + pub expected_at: _0, + pub activated_at: _0, + } + } + pub mod paras_inherent { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + enter { + data: runtime_types::polkadot_primitives::v4::InherentData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyInclusionInherents, + #[codec(index = 1)] + InvalidParentHeader, + #[codec(index = 2)] + CandidateConcludedInvalid, + #[codec(index = 3)] + InherentOverweight, + #[codec(index = 4)] + DisputeStatementsUnsortedOrDuplicates, + #[codec(index = 5)] + DisputeInvalid, + } + } + } + pub mod scheduler { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssignmentKind { + #[codec(index = 0)] + Parachain, + #[codec(index = 1)] + Parathread( + runtime_types::polkadot_primitives::v4::collator_app::Public, + ::core::primitive::u32, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CoreAssignment { + pub core: runtime_types::polkadot_primitives::v4::CoreIndex, + pub para_id: runtime_types::polkadot_parachain::primitives::Id, + pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, + pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParathreadClaimQueue { + pub queue: ::std::vec::Vec< + runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, + >, + pub next_core_offset: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueuedParathread { + pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, + pub core_offset: ::core::primitive::u32, + } + } + pub mod shared { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + pub mod per_things { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct PerU16(pub ::core::primitive::u16); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Perbill(pub ::core::primitive::u32); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Percent(pub ::core::primitive::u8); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_authority_discovery { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + pub mod sp_consensus_babe { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + pub mod digests { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NextConfigDescriptor { + #[codec(index = 1)] + V1 { + c: (::core::primitive::u64, ::core::primitive::u64), + allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum PreDigest { + #[codec(index = 1)] + Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), + #[codec(index = 2)] + SecondaryPlain( + runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, + ), + #[codec(index = 3)] + SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PrimaryPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryPlainPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SecondaryVRFPreDigest { + pub authority_index: ::core::primitive::u32, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AllowedSlots { + #[codec(index = 0)] + PrimarySlots, + #[codec(index = 1)] + PrimaryAndSecondaryPlainSlots, + #[codec(index = 2)] + PrimaryAndSecondaryVRFSlots, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BabeEpochConfiguration { + pub c: (::core::primitive::u64, ::core::primitive::u64), + pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Equivocation<_0, _1> { + #[codec(index = 0)] + Prevote( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Prevote<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + #[codec(index = 1)] + Precommit( + runtime_types::finality_grandpa::Equivocation< + runtime_types::sp_consensus_grandpa::app::Public, + runtime_types::finality_grandpa::Precommit<_0, _1>, + runtime_types::sp_consensus_grandpa::app::Signature, + >, + ), + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EquivocationProof<_0, _1> { + pub offender: _1, + pub slot: runtime_types::sp_consensus_slots::Slot, + pub first_header: _0, + pub second_header: _0, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 33usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod offchain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueNetworkState { + pub peer_id: runtime_types::sp_core::OpaquePeerId, + pub external_addresses: + ::std::vec::Vec, + } + } + pub mod sr25519 { + use super::runtime_types; + pub mod vrf { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct VrfSignature { + pub output: [::core::primitive::u8; 32usize], + pub proof: [::core::primitive::u8; 64usize], + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_npos_elections { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ElectionScore { + pub minimal_stake: ::core::primitive::u128, + pub sum_stake: ::core::primitive::u128, + pub sum_stake_squared: ::core::primitive::u128, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Support<_0> { + pub total: ::core::primitive::u128, + pub voters: ::std::vec::Vec<(_0, ::core::primitive::u128)>, + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + pub mod unchecked_extrinsic { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UncheckedExtrinsic<_0, _1, _2, _3>( + pub ::std::vec::Vec<::core::primitive::u8>, + #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1, _2, _3)>, + ); + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSigner { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Public), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Public), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Public), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_staking { + use super::runtime_types; + pub mod offence { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OffenceDetails<_0, _1> { + pub offender: _1, + pub reporters: ::std::vec::Vec<_0>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod westend_runtime { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct NposCompactSolution16 { + pub votes1: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes2: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + ( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ), + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes3: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 2usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes4: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 3usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes5: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 4usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes6: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 5usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes7: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 6usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes8: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 7usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes9: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 8usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes10: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 9usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes11: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 10usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes12: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 11usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes13: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 12usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes14: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 13usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes15: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 14usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + pub votes16: ::std::vec::Vec<( + ::subxt::ext::codec::Compact<::core::primitive::u32>, + [( + ::subxt::ext::codec::Compact<::core::primitive::u16>, + ::subxt::ext::codec::Compact< + runtime_types::sp_arithmetic::per_things::PerU16, + >, + ); 15usize], + ::subxt::ext::codec::Compact<::core::primitive::u16>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + #[codec(index = 0)] + system( + runtime_types::frame_support::dispatch::RawOrigin< + ::sp_core::crypto::AccountId32, + >, + ), + #[codec(index = 41)] + ParachainsOrigin( + runtime_types::polkadot_runtime_parachains::origin::pallet::Origin, + ), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Origin), + #[codec(index = 3)] + Void(runtime_types::sp_core::Void), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProxyType { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + NonTransfer, + #[codec(index = 2)] + Staking, + #[codec(index = 3)] + SudoBalances, + #[codec(index = 4)] + IdentityJudgement, + #[codec(index = 5)] + CancelProxy, + #[codec(index = 6)] + Auction, + #[codec(index = 7)] + NominationPools, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + Babe(runtime_types::pallet_babe::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 3)] + Indices(runtime_types::pallet_indices::pallet::Call), + #[codec(index = 4)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 6)] + Staking(runtime_types::pallet_staking::pallet::pallet::Call), + #[codec(index = 8)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 10)] + Grandpa(runtime_types::pallet_grandpa::pallet::Call), + #[codec(index = 11)] + ImOnline(runtime_types::pallet_im_online::pallet::Call), + #[codec(index = 16)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 17)] + Identity(runtime_types::pallet_identity::pallet::Call), + #[codec(index = 18)] + Recovery(runtime_types::pallet_recovery::pallet::Call), + #[codec(index = 19)] + Vesting(runtime_types::pallet_vesting::pallet::Call), + #[codec(index = 20)] + Scheduler(runtime_types::pallet_scheduler::pallet::Call), + #[codec(index = 28)] + Preimage(runtime_types::pallet_preimage::pallet::Call), + #[codec(index = 21)] + Sudo(runtime_types::pallet_sudo::pallet::Call), + #[codec(index = 22)] + Proxy(runtime_types::pallet_proxy::pallet::Call), + #[codec(index = 23)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 24)] + ElectionProviderMultiPhase( + runtime_types::pallet_election_provider_multi_phase::pallet::Call, + ), + #[codec(index = 25)] + VoterList(runtime_types::pallet_bags_list::pallet::Call), + #[codec(index = 29)] + NominationPools(runtime_types::pallet_nomination_pools::pallet::Call), + #[codec(index = 30)] + FastUnstake(runtime_types::pallet_fast_unstake::pallet::Call), + #[codec(index = 42)] + Configuration( + runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, + ), + #[codec(index = 43)] + ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), + #[codec(index = 44)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), + #[codec(index = 45)] + ParaInherent( + runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, + ), + #[codec(index = 47)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), + #[codec(index = 48)] + Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), + #[codec(index = 51)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), + #[codec(index = 53)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), + #[codec(index = 54)] + ParasSlashing( + runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, + ), + #[codec(index = 60)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), + #[codec(index = 61)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), + #[codec(index = 62)] + ParasSudoWrapper( + runtime_types::polkadot_runtime_common::paras_sudo_wrapper::pallet::Call, + ), + #[codec(index = 63)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), + #[codec(index = 64)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), + #[codec(index = 65)] + AssignedSlots(runtime_types::polkadot_runtime_common::assigned_slots::pallet::Call), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 100)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 3)] + Indices(runtime_types::pallet_indices::pallet::Event), + #[codec(index = 4)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 26)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 6)] + Staking(runtime_types::pallet_staking::pallet::pallet::Event), + #[codec(index = 7)] + Offences(runtime_types::pallet_offences::pallet::Event), + #[codec(index = 8)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 10)] + Grandpa(runtime_types::pallet_grandpa::pallet::Event), + #[codec(index = 11)] + ImOnline(runtime_types::pallet_im_online::pallet::Event), + #[codec(index = 16)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 17)] + Identity(runtime_types::pallet_identity::pallet::Event), + #[codec(index = 18)] + Recovery(runtime_types::pallet_recovery::pallet::Event), + #[codec(index = 19)] + Vesting(runtime_types::pallet_vesting::pallet::Event), + #[codec(index = 20)] + Scheduler(runtime_types::pallet_scheduler::pallet::Event), + #[codec(index = 28)] + Preimage(runtime_types::pallet_preimage::pallet::Event), + #[codec(index = 21)] + Sudo(runtime_types::pallet_sudo::pallet::Event), + #[codec(index = 22)] + Proxy(runtime_types::pallet_proxy::pallet::Event), + #[codec(index = 23)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 24)] + ElectionProviderMultiPhase( + runtime_types::pallet_election_provider_multi_phase::pallet::Event, + ), + #[codec(index = 25)] + VoterList(runtime_types::pallet_bags_list::pallet::Event), + #[codec(index = 29)] + NominationPools(runtime_types::pallet_nomination_pools::pallet::Event), + #[codec(index = 30)] + FastUnstake(runtime_types::pallet_fast_unstake::pallet::Event), + #[codec(index = 44)] + ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), + #[codec(index = 47)] + Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), + #[codec(index = 51)] + Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), + #[codec(index = 53)] + ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), + #[codec(index = 60)] + Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), + #[codec(index = 61)] + Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), + #[codec(index = 63)] + Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), + #[codec(index = 64)] + Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), + #[codec(index = 65)] + AssignedSlots( + runtime_types::polkadot_runtime_common::assigned_slots::pallet::Event, + ), + #[codec(index = 99)] + XcmPallet(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 100)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, + pub babe: runtime_types::sp_consensus_babe::app::Public, + pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, + pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, + pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, + pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + } + } +} diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 674f4c71e82f8..2f987b688a906 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -16,21 +16,36 @@ //! Types used to connect to the Westend chain. +pub mod codegen_runtime; + +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_runtime::ChainId; use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; +use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, + RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; -use sp_core::storage::StorageKey; +use sp_core::{storage::StorageKey, Pair}; +use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; use sp_session::MembershipProof; use std::time::Duration; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::westend_runtime::RuntimeCall; + +pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; + /// Westend header id. pub type HeaderId = relay_utils::HeaderId; /// Westend header type used in headers sync. pub type SyncHeader = relay_substrate_client::SyncHeader; +/// The address format for describing accounts. +pub type Address = MultiAddress; + /// Westend chain definition #[derive(Debug, Clone, Copy)] pub struct Westend; @@ -47,7 +62,7 @@ impl Chain for Westend { const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); type SignedBlock = bp_westend::SignedBlock; - type Call = (); + type Call = RuntimeCall; } impl ChainWithGrandpa for Westend { @@ -59,8 +74,7 @@ impl ChainWithGrandpa for Westend { impl RelayChain for Westend { const PARAS_PALLET_NAME: &'static str = bp_westend::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = - bp_westend::WITH_WESTEND_BRIDGE_PARAS_PALLET_NAME; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWestendParachains"; } impl ChainWithBalances for Westend { @@ -69,23 +83,53 @@ impl ChainWithBalances for Westend { } } -/// `AssetHubWestend` parachain definition -#[derive(Debug, Clone, Copy)] -pub struct AssetHubWestend; +impl ChainWithTransactions for Westend { + type AccountKeyPair = sp_core::sr25519::Pair; + type SignedTransaction = + bp_polkadot_core::UncheckedExtrinsic; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + let raw_payload = SignedPayload::new( + unsigned.call, + bp_westend::SignedExtension::from_params( + param.spec_version, + param.transaction_version, + unsigned.era, + param.genesis_hash, + unsigned.nonce, + unsigned.tip, + ((), ()), + ), + )?; + + let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); + let signer: sp_runtime::MultiSigner = param.signer.public().into(); + let (call, extra, _) = raw_payload.deconstruct(); + + Ok(Self::SignedTransaction::new_signed( + call, + signer.into_account().into(), + signature.into(), + extra, + )) + } -impl UnderlyingChainProvider for AssetHubWestend { - type Chain = bp_westend::AssetHubWestend; -} + fn is_signed(tx: &Self::SignedTransaction) -> bool { + tx.signature.is_some() + } -// Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use Westend -// primitives here. -impl Chain for AssetHubWestend { - const ID: ChainId = bp_runtime::ASSET_HUB_WESTEND_CHAIN_ID; - const NAME: &'static str = "Westmint"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_westend::BEST_FINALIZED_ASSETHUBWESTEND_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + tx.signature + .as_ref() + .map(|(address, _, _)| *address == Address::Id(signer.public().into())) + .unwrap_or(false) + } - type SignedBlock = bp_westend::SignedBlock; - type Call = (); + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + let extra = &tx.signature.as_ref()?.2; + Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + } } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index fa0d60faba6ec..ddf38a5c19d53 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -79,7 +79,7 @@ impl ChainWithBalances for Wococo { impl RelayChain for Wococo { const PARAS_PALLET_NAME: &'static str = bp_wococo::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWococoParachain"; + const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWococoParachains"; } impl ChainWithTransactions for Wococo { From a35de56fd4577825ed4e5cc67596aa2372dd9c22 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 1 Nov 2023 22:44:51 +0100 Subject: [PATCH 1137/1210] Adjusted constant because for measuring we used mistakenly rococo constants (#2664) * Adjusted constant because for measuring we used mistakenly rococo constants * typo --- primitives/chain-asset-hub-westend/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-asset-hub-westend/src/lib.rs b/primitives/chain-asset-hub-westend/src/lib.rs index c943dc320b76a..2d317e4aee468 100644 --- a/primitives/chain-asset-hub-westend/src/lib.rs +++ b/primitives/chain-asset-hub-westend/src/lib.rs @@ -45,7 +45,7 @@ frame_support::parameter_types! { /// Base delivery fee to `BridgeHubWestend`. /// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubWestendBaseFeeInWocs: u128 = 1624803349; + pub const BridgeHubWestendBaseFeeInWnds: u128 = 487441010000; } /// Identifier of AssetHubWestend in the Westend relay chain. From f81a6a2049558646e1279ffc9ecb85c4ec52b129 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 2 Nov 2023 07:05:04 +0100 Subject: [PATCH 1138/1210] Nit from `polkadot-sdk` (#2665) --- primitives/chain-polkadot-bulletin/Cargo.toml | 5 +++-- primitives/chain-westend/Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index 597145d683c2e..8b389b9f80ee2 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-polkadot-bulletin" description = "Primitives of Polkadot Bulletin chain runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] @@ -35,6 +35,7 @@ std = [ "codec/std", "frame-support/std", "frame-system/std", + "scale-info/std", "sp-api/std", "sp-runtime/std", "sp-std/std", diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index abc04224dcac9..f83ad61ed8be4 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -2,8 +2,8 @@ name = "bp-westend" description = "Primitives of Westend runtime." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] From e7fc56b06c0a6c4dadab4ba1220f3be64106dc10 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 2 Nov 2023 08:09:17 +0100 Subject: [PATCH 1139/1210] BHR/BHWE spec_version according to the `polkadot-sdk` (#2668) --- relays/bin-substrate/src/chains/rococo.rs | 2 +- relays/bin-substrate/src/chains/westend.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index dc8bd64836a62..fa376f0967471 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -27,5 +27,5 @@ impl CliChain for Rococo { impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9420, transaction_version: 3 }); + Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index 5376fc210e520..be26a36627ad8 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -27,5 +27,5 @@ impl CliChain for Westend { impl CliChain for BridgeHubWestend { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 10000, transaction_version: 3 }); + Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); } From d21e399b4781a50e82cd573854385f98ce60a956 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 2 Nov 2023 13:15:30 +0300 Subject: [PATCH 1140/1210] removed unused PARACHAINS_FINALITY_PALLET_NAME constant (#2670) --- relays/client-kusama/src/lib.rs | 1 - relays/client-polkadot/src/lib.rs | 1 - relays/client-rialto/src/lib.rs | 2 -- relays/client-rococo/src/lib.rs | 1 - relays/client-substrate/src/chain.rs | 6 ------ relays/client-westend/src/lib.rs | 1 - relays/client-wococo/src/lib.rs | 1 - 7 files changed, 13 deletions(-) diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 2108f67dc9d81..7fa88959a3c5b 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -80,7 +80,6 @@ impl ChainWithBalances for Kusama { impl RelayChain for Kusama { const PARAS_PALLET_NAME: &'static str = bp_kusama::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeKusamaParachain"; } impl ChainWithTransactions for Kusama { diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 4181b6dcff773..d0f7a7cb686d9 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -80,7 +80,6 @@ impl ChainWithBalances for Polkadot { impl RelayChain for Polkadot { const PARAS_PALLET_NAME: &'static str = bp_polkadot::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgePolkadotParachain"; } impl ChainWithTransactions for Polkadot { diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index cc5371612c346..2aa5bd638cc87 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -61,8 +61,6 @@ impl ChainWithGrandpa for Rialto { impl RelayChain for Rialto { const PARAS_PALLET_NAME: &'static str = bp_rialto::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = - bp_rialto::WITH_RIALTO_BRIDGE_PARAS_PALLET_NAME; } impl ChainWithMessages for Rialto { diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 42e022d1be336..5ac11f1ef7230 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -80,7 +80,6 @@ impl ChainWithBalances for Rococo { impl RelayChain for Rococo { const PARAS_PALLET_NAME: &'static str = bp_rococo::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeRococoParachains"; } impl ChainWithTransactions for Rococo { diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 09742f1058e69..42d1c358c0a34 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -66,12 +66,6 @@ pub trait Chain: ChainBase + Clone { pub trait RelayChain: Chain { /// Name of the `runtime_parachains::paras` pallet in the runtime of this chain. const PARAS_PALLET_NAME: &'static str; - /// Name of the bridge parachains pallet (used in `construct_runtime` macro call) that is - /// deployed at the **bridged** chain. - /// - /// We assume that all chains that are bridging with this `RelayChain` are using - /// the same name. - const PARACHAINS_FINALITY_PALLET_NAME: &'static str; } /// Substrate-based chain that is using direct GRANDPA finality from minimal relay-client point of diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 2f987b688a906..8cacffba99134 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -74,7 +74,6 @@ impl ChainWithGrandpa for Westend { impl RelayChain for Westend { const PARAS_PALLET_NAME: &'static str = bp_westend::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWestendParachains"; } impl ChainWithBalances for Westend { diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index ddf38a5c19d53..bb4e1c0130452 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -79,7 +79,6 @@ impl ChainWithBalances for Wococo { impl RelayChain for Wococo { const PARAS_PALLET_NAME: &'static str = bp_wococo::PARAS_PALLET_NAME; - const PARACHAINS_FINALITY_PALLET_NAME: &'static str = "BridgeWococoParachains"; } impl ChainWithTransactions for Wococo { From cc60f8d83f1dee2deb70f8d31478058e6bee44f7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 3 Nov 2023 11:25:12 +0300 Subject: [PATCH 1141/1210] backport https://github.com/paritytech/polkadot-sdk/pull/2139 (#2673) --- .../src/messages_benchmarking.rs | 54 ++++++------------- bin/runtime-common/src/messages_generation.rs | 37 ++++++++++++- primitives/chain-asset-hub-rococo/src/lib.rs | 4 -- primitives/chain-asset-hub-westend/src/lib.rs | 4 -- primitives/chain-asset-hub-wococo/src/lib.rs | 4 -- primitives/chain-bridge-hub-rococo/src/lib.rs | 15 ++++++ .../chain-bridge-hub-westend/src/lib.rs | 15 ++++++ primitives/chain-bridge-hub-wococo/src/lib.rs | 15 ++++++ 8 files changed, 95 insertions(+), 53 deletions(-) diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index d80a88f1068c8..e7e7891461b21 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -22,24 +22,22 @@ use crate::{ messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, - AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, ThisChain, + AccountIdOf, BridgedChain, HashOf, MessageBridge, ThisChain, }, messages_generation::{ - encode_all_messages, encode_lane_data, grow_trie_leaf_value, prepare_messages_storage_proof, + encode_all_messages, encode_lane_data, prepare_message_delivery_storage_proof, + prepare_messages_storage_proof, }, }; -use bp_messages::{storage_keys, MessagePayload}; +use bp_messages::MessagePayload; use bp_polkadot_core::parachains::ParaHash; -use bp_runtime::{ - record_all_trie_keys, Chain, Parachain, RawStorageProof, StorageProofSize, UnderlyingChainOf, -}; +use bp_runtime::{Chain, Parachain, StorageProofSize, UnderlyingChainOf}; use codec::Encode; use frame_support::weights::Weight; use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; use sp_runtime::traits::{Header, Zero}; use sp_std::prelude::*; -use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut}; use xcm::v3::prelude::*; /// Prepare inbound bridge message according to given message proof parameters. @@ -172,7 +170,11 @@ where { // prepare storage proof let lane = params.lane; - let (state_root, storage_proof) = prepare_message_delivery_proof::(params); + let (state_root, storage_proof) = prepare_message_delivery_storage_proof::( + params.lane, + params.inbound_lane_data, + params.size, + ); // update runtime storage let (_, bridged_header_hash) = insert_header_to_grandpa_pallet::(state_root); @@ -200,7 +202,11 @@ where { // prepare storage proof let lane = params.lane; - let (state_root, storage_proof) = prepare_message_delivery_proof::(params); + let (state_root, storage_proof) = prepare_message_delivery_storage_proof::( + params.lane, + params.inbound_lane_data, + params.size, + ); // update runtime storage let (_, bridged_header_hash) = @@ -213,36 +219,6 @@ where } } -/// Prepare in-memory message delivery proof, without inserting anything to the runtime storage. -fn prepare_message_delivery_proof( - params: MessageDeliveryProofParams>>, -) -> (HashOf>, RawStorageProof) -where - B: MessageBridge, -{ - // prepare Bridged chain storage with inbound lane state - let storage_key = - storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, ¶ms.lane).0; - let mut root = Default::default(); - let mut mdb = MemoryDB::default(); - { - let mut trie = - TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); - let inbound_lane_data = - grow_trie_leaf_value(params.inbound_lane_data.encode(), params.size); - trie.insert(&storage_key, &inbound_lane_data) - .map_err(|_| "TrieMut::insert has failed") - .expect("TrieMut::insert should not fail in benchmarks"); - } - - // generate storage proof to be delivered to This chain - let storage_proof = record_all_trie_keys::>>, _>(&mdb, &root) - .map_err(|_| "record_all_trie_keys has failed") - .expect("record_all_trie_keys should not fail in benchmarks"); - - (root, storage_proof) -} - /// Insert header to the bridge GRANDPA pallet. pub(crate) fn insert_header_to_grandpa_pallet( state_root: bp_runtime::HashOf, diff --git a/bin/runtime-common/src/messages_generation.rs b/bin/runtime-common/src/messages_generation.rs index 3c550a9bd0fd5..c37aaa5d4d537 100644 --- a/bin/runtime-common/src/messages_generation.rs +++ b/bin/runtime-common/src/messages_generation.rs @@ -16,10 +16,11 @@ //! Helpers for generating message storage proofs, that are used by tests and by benchmarks. -use crate::messages::{BridgedChain, HashOf, HasherOf, MessageBridge}; +use crate::messages::{AccountIdOf, BridgedChain, HashOf, HasherOf, MessageBridge, ThisChain}; use bp_messages::{ - storage_keys, LaneId, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, + storage_keys, InboundLaneData, LaneId, MessageKey, MessageNonce, MessagePayload, + OutboundLaneData, }; use bp_runtime::{record_all_trie_keys, RawStorageProof, StorageProofSize}; use codec::Encode; @@ -104,6 +105,38 @@ where (root, storage_proof) } +/// Prepare storage proof of given messages delivery. +/// +/// Returns state trie root and nodes with prepared messages. +pub fn prepare_message_delivery_storage_proof( + lane: LaneId, + inbound_lane_data: InboundLaneData>>, + size: StorageProofSize, +) -> (HashOf>, RawStorageProof) +where + B: MessageBridge, +{ + // prepare Bridged chain storage with inbound lane state + let storage_key = storage_keys::inbound_lane_data_key(B::BRIDGED_MESSAGES_PALLET_NAME, &lane).0; + let mut root = Default::default(); + let mut mdb = MemoryDB::default(); + { + let mut trie = + TrieDBMutBuilderV1::>>::new(&mut mdb, &mut root).build(); + let inbound_lane_data = grow_trie_leaf_value(inbound_lane_data.encode(), size); + trie.insert(&storage_key, &inbound_lane_data) + .map_err(|_| "TrieMut::insert has failed") + .expect("TrieMut::insert should not fail in benchmarks"); + } + + // generate storage proof to be delivered to This chain + let storage_proof = record_all_trie_keys::>>, _>(&mdb, &root) + .map_err(|_| "record_all_trie_keys has failed") + .expect("record_all_trie_keys should not fail in benchmarks"); + + (root, storage_proof) +} + /// Add extra data to the trie leaf value so that it'll be of given size. pub fn grow_trie_leaf_value(mut value: Vec, size: StorageProofSize) -> Vec { match size { diff --git a/primitives/chain-asset-hub-rococo/src/lib.rs b/primitives/chain-asset-hub-rococo/src/lib.rs index 1a08ade2f4f2f..6216b24d75c90 100644 --- a/primitives/chain-asset-hub-rococo/src/lib.rs +++ b/primitives/chain-asset-hub-rococo/src/lib.rs @@ -45,10 +45,6 @@ pub enum Call { frame_support::parameter_types! { /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); - - /// Base delivery fee to `BridgeHubRococo`. - /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubRococoBaseFeeInRocs: u128 = 1624803349; } /// Identifier of AssetHubRococo in the Rococo relay chain. diff --git a/primitives/chain-asset-hub-westend/src/lib.rs b/primitives/chain-asset-hub-westend/src/lib.rs index 2d317e4aee468..9de1c88098942 100644 --- a/primitives/chain-asset-hub-westend/src/lib.rs +++ b/primitives/chain-asset-hub-westend/src/lib.rs @@ -42,10 +42,6 @@ pub enum Call { frame_support::parameter_types! { /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); - - /// Base delivery fee to `BridgeHubWestend`. - /// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubWestendBaseFeeInWnds: u128 = 487441010000; } /// Identifier of AssetHubWestend in the Westend relay chain. diff --git a/primitives/chain-asset-hub-wococo/src/lib.rs b/primitives/chain-asset-hub-wococo/src/lib.rs index 809e56934e96e..c04eb04cce70b 100644 --- a/primitives/chain-asset-hub-wococo/src/lib.rs +++ b/primitives/chain-asset-hub-wococo/src/lib.rs @@ -42,10 +42,6 @@ pub enum Call { frame_support::parameter_types! { /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); - - /// Base delivery fee to `BridgeHubWococo`. - /// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubWococoBaseFeeInWocs: u128 = 1624803349; } /// Identifier of AssetHubWococo in the Wococo relay chain. diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 039d681951cd1..e72e711de9270 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -82,3 +82,18 @@ pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 51; decl_bridge_finality_runtime_apis!(bridge_hub_rococo); decl_bridge_messages_runtime_apis!(bridge_hub_rococo); + +frame_support::parameter_types! { + /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Rococo + /// BridgeHub. + /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const BridgeHubRococoBaseXcmFeeInRocs: u128 = 1628875538; + + /// Transaction fee that is paid at the Rococo BridgeHub for delivering single inbound message. + /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) + pub const BridgeHubRococoBaseDeliveryFeeInRocs: u128 = 6417262881; + + /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. + /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 6159996668; +} diff --git a/primitives/chain-bridge-hub-westend/src/lib.rs b/primitives/chain-bridge-hub-westend/src/lib.rs index a52e328b68753..0124e05bf8871 100644 --- a/primitives/chain-bridge-hub-westend/src/lib.rs +++ b/primitives/chain-bridge-hub-westend/src/lib.rs @@ -73,3 +73,18 @@ pub const WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 44; decl_bridge_finality_runtime_apis!(bridge_hub_westend); decl_bridge_messages_runtime_apis!(bridge_hub_westend); + +frame_support::parameter_types! { + /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Westend + /// BridgeHub. + /// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const BridgeHubWestendBaseXcmFeeInWnds: u128 = 488662666666; + + /// Transaction fee that is paid at the Westend BridgeHub for delivering single inbound message. + /// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) + pub const BridgeHubWestendBaseDeliveryFeeInWnds: u128 = 1925196628010; + + /// Transaction fee that is paid at the Westend BridgeHub for delivering single outbound message confirmation. + /// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) + pub const BridgeHubWestendBaseConfirmationFeeInWnds: u128 = 1848016628010; +} diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs index 750a8f7ecb9dd..c8bd397cec561 100644 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ b/primitives/chain-bridge-hub-wococo/src/lib.rs @@ -73,3 +73,18 @@ pub const WITH_BRIDGE_WOCOCO_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45; decl_bridge_finality_runtime_apis!(bridge_hub_wococo); decl_bridge_messages_runtime_apis!(bridge_hub_wococo); + +frame_support::parameter_types! { + /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Wococo + /// BridgeHub. + /// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const BridgeHubWococoBaseXcmFeeInWocs: u128 = 1624803349; + + /// Transaction fee that is paid at the Wococo BridgeHub for delivering single inbound message. + /// (initially was calculated by test `BridgeHubWococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) + pub const BridgeHubWococoBaseDeliveryFeeInWocs: u128 = 6417262881; + + /// Transaction fee that is paid at the Wococo BridgeHub for delivering single outbound message confirmation. + /// (initially was calculated by test `BridgeHubWococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) + pub const BridgeHubWococoBaseConfirmationFeeInWocs: u128 = 6159996668; +} From 6b298510ae7decf5fed715737a737752e56d525a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 02:37:14 +0000 Subject: [PATCH 1142/1210] Bump serde_json from 1.0.107 to 1.0.108 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.107 to 1.0.108. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.107...v1.0.108) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index add3527df3e1f..801d5f9cf9f68 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -12,7 +12,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" clap = { version = "4.4.7", features = ["derive"] } futures = "0.3.29" jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.107" +serde_json = "1.0.108" # Bridge dependencies diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index 882ce89e8e0ce..e0a7e8ad26827 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -18,7 +18,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] clap = { version = "4.4.7", features = ["derive"] } -serde_json = "1.0.107" +serde_json = "1.0.108" # Bridge dependencies From aa5f653af6e85311cf2ecc552b9635ff8c4504bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 02:36:58 +0000 Subject: [PATCH 1143/1210] Bump tokio from 1.33.0 to 1.34.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.33.0 to 1.34.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.33.0...tokio-1.34.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index c107ae6fa45f4..f4944ac972d4d 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.20" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } -tokio = { version = "1.33", features = ["rt-multi-thread"] } +tokio = { version = "1.34", features = ["rt-multi-thread"] } thiserror = "1.0.50" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index e39cf8cdacbf7..763c125d54d12 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.33", features = ["rt"] } +tokio = { version = "1.34", features = ["rt"] } thiserror = "1.0.50" # Bridge dependencies From a4f754de903c29213807bc9c730e9a663997fe05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 02:36:17 +0000 Subject: [PATCH 1144/1210] Bump env_logger from 0.10.0 to 0.10.1 Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.10.0 to 0.10.1. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.10.0...v0.10.1) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 763c125d54d12..a41beb9e52f85 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -12,7 +12,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" isahc = "1.2" -env_logger = "0.10.0" +env_logger = "0.10.1" futures = "0.3.29" jsonpath_lib = "0.3" log = "0.4.20" From 5eb25c626d844e6d8c5157f8abbb16a1b0a9b2a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 02:35:39 +0000 Subject: [PATCH 1145/1210] Bump clap from 4.4.7 to 4.4.8 Bumps [clap](https://github.com/clap-rs/clap) from 4.4.7 to 4.4.8. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](https://github.com/clap-rs/clap/compare/v4.4.7...v4.4.8) --- updated-dependencies: - dependency-name: clap dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/millau/node/Cargo.toml | 2 +- bin/rialto-parachain/node/Cargo.toml | 2 +- bin/rialto/node/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml index 801d5f9cf9f68..426cb9e863ee1 100644 --- a/bin/millau/node/Cargo.toml +++ b/bin/millau/node/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.7", features = ["derive"] } +clap = { version = "4.4.8", features = ["derive"] } futures = "0.3.29" jsonrpsee = { version = "0.16.2", features = ["server"] } serde_json = "1.0.108" diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml index c3646df4cf55d..053ee24577377 100644 --- a/bin/rialto-parachain/node/Cargo.toml +++ b/bin/rialto-parachain/node/Cargo.toml @@ -17,7 +17,7 @@ default = [] runtime-benchmarks = [ 'rialto-parachain-runtime/runtime-benchmarks' ] [dependencies] -clap = { version = "4.4.7", features = ["derive"] } +clap = { version = "4.4.8", features = ["derive"] } log = '0.4.20' codec = { package = 'parity-scale-codec', version = '3.1.5' } serde = { version = '1.0', features = ['derive'] } diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml index e0a7e8ad26827..b2d54e5160983 100644 --- a/bin/rialto/node/Cargo.toml +++ b/bin/rialto/node/Cargo.toml @@ -17,7 +17,7 @@ repository = "https://github.com/paritytech/parity-bridges-common/" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -clap = { version = "4.4.7", features = ["derive"] } +clap = { version = "4.4.8", features = ["derive"] } serde_json = "1.0.108" # Bridge dependencies From 2ad3fa91bba5079768957c4c8675524372540f14 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 13 Nov 2023 09:45:45 +0100 Subject: [PATCH 1146/1210] typo (#2690) --- primitives/chain-bridge-hub-cumulus/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index 5d1fcf0fe1b0e..5b86305a9b90c 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bp-bridge-hub-cumulus" -description = "Primitives of BridgeHubRococo parachain runtime." +description = "Primitives for BridgeHub parachain runtimes." version = "0.1.0" authors.workspace = true edition.workspace = true From c36d4d7a46ae7a5757cd9e19e6751eb8008b7ea3 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 14 Nov 2023 09:28:10 +0200 Subject: [PATCH 1147/1210] Start version guards for the ED loop (#2678) --- .../kusama_headers_to_bridge_hub_polkadot.rs | 16 ---------------- .../polkadot_headers_to_bridge_hub_kusama.rs | 16 ---------------- ...ot_bulletin_headers_to_bridge_hub_polkadot.rs | 16 ---------------- .../polkadot_headers_to_polkadot_bulletin.rs | 16 ---------------- .../rococo_headers_to_bridge_hub_westend.rs | 16 ---------------- .../westend_headers_to_bridge_hub_rococo.rs | 16 ---------------- .../rococo_headers_to_bridge_hub_wococo.rs | 16 ---------------- .../wococo_headers_to_bridge_hub_rococo.rs | 16 ---------------- .../src/cli/detect_equivocations.rs | 11 +++++++++-- relays/bin-substrate/src/cli/relay_headers.rs | 8 ++------ .../parachain_to_parachain.rs | 2 -- .../relay_to_parachain.rs | 2 -- .../relay_headers_and_messages/relay_to_relay.rs | 2 -- .../lib-substrate-relay/src/equivocation/mod.rs | 14 ++++++++++++++ relays/lib-substrate-relay/src/finality/mod.rs | 11 ++++++++--- 15 files changed, 33 insertions(+), 145 deletions(-) diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs index a5419a725e2e1..2dc9c131305ad 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Kusama -> PolkadotBridgeHub finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for KusamaFinalityToBridgeHubPolkadot { #[async_trait] impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs index 5899b8c25f6e0..589bf2546e8c1 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Polkadot -> KusamaBridgeHub finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for PolkadotFinalityToBridgeHubKusama { #[async_trait] impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs index 33f59feda3bae..dbf89ddeec398 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs @@ -22,12 +22,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of `PolkadotBulletin` -> `PolkadotBridgeHub` finalized headers bridge. @@ -59,20 +57,6 @@ impl SubstrateFinalityPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { #[async_trait] impl SubstrateFinalitySyncPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs index 7770fd1559444..897c2ac884f91 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Polkadot -> `PolkadotBulletin` finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for PolkadotFinalityToPolkadotBulletin { #[async_trait] impl SubstrateFinalitySyncPipeline for PolkadotFinalityToPolkadotBulletin { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs index 75f6ff6f25c20..24d0b6603157a 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Rococo -> Westend finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWestend { #[async_trait] impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWestend { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs index 1532e06b95386..451089b2ce009 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Westend -> Rococo finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for WestendFinalityToBridgeHubRococo { #[async_trait] impl SubstrateFinalitySyncPipeline for WestendFinalityToBridgeHubRococo { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs index d89ba35849c69..b9b9a89ba0f52 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Rococo -> Wococo finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWococo { #[async_trait] impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs index 44d91f06e3e78..c000a2764e26e 100644 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs @@ -21,12 +21,10 @@ use crate::cli::bridge::{ }; use async_trait::async_trait; -use relay_substrate_client::{AccountKeyPairOf, Client}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, - TransactionParams, }; /// Description of Wococo -> Rococo finalized headers bridge. @@ -58,20 +56,6 @@ impl SubstrateFinalityPipeline for WococoFinalityToBridgeHubRococo { #[async_trait] impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; - - async fn start_relay_guards( - target_client: &Client, - _transaction_params: &TransactionParams>, - enable_version_guard: bool, - ) -> relay_substrate_client::Result<()> { - if enable_version_guard { - relay_substrate_client::guard::abort_on_spec_version_change( - target_client.clone(), - target_client.simple_runtime_version().await?.spec_version, - ); - } - Ok(()) - } } #[async_trait] diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs index 142a3f8e69a88..bc456e025499e 100644 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -37,7 +37,7 @@ use async_trait::async_trait; use relay_substrate_client::ChainWithTransactions; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; -use substrate_relay_helper::equivocation; +use substrate_relay_helper::{equivocation, equivocation::SubstrateEquivocationDetectionPipeline}; /// Start equivocation detection loop. #[derive(StructOpt)] @@ -73,8 +73,15 @@ where Self::Source: ChainWithTransactions, { async fn start(data: DetectEquivocations) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + Self::Equivocation::start_relay_guards( + &source_client, + source_client.can_start_version_guard(), + ) + .await?; + equivocation::run::( - data.source.into_client::().await?, + source_client, data.target.into_client::().await?, data.source_sign.transaction_params::()?, data.prometheus_params.into_metrics_params()?, diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 800e8587d8b25..d3a7fa09367df 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -96,12 +96,8 @@ trait HeadersRelayer: RelayToRelayHeadersCliBridge { signer: target_sign, mortality: target_transactions_mortality, }; - Self::Finality::start_relay_guards( - &target_client, - &target_transactions_params, - target_client.can_start_version_guard(), - ) - .await?; + Self::Finality::start_relay_guards(&target_client, target_client.can_start_version_guard()) + .await?; substrate_relay_helper::finality::run::( source_client, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 24d6f00861d00..1610f648bdcdd 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -218,13 +218,11 @@ where ::RelayFinality::start_relay_guards( &self.common.right.client, - &self.left_headers_to_right_transaction_params, self.common.right.client.can_start_version_guard(), ) .await?; ::RelayFinality::start_relay_guards( &self.common.left.client, - &self.right_headers_to_left_transaction_params, self.common.left.client.can_start_version_guard(), ) .await?; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index ef47e44dc1837..98b313cc0960d 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -200,13 +200,11 @@ where ::Finality::start_relay_guards( &self.common.right.client, - &self.left_headers_to_right_transaction_params, self.common.right.client.can_start_version_guard(), ) .await?; ::RelayFinality::start_relay_guards( &self.common.left.client, - &self.right_headers_to_left_transaction_params, self.common.left.client.can_start_version_guard(), ) .await?; diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index a313628933ba6..a75263540a55f 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -156,13 +156,11 @@ where ::Finality::start_relay_guards( &self.common.right.client, - &self.left_to_right_transaction_params, self.common.right.client.can_start_version_guard(), ) .await?; ::Finality::start_relay_guards( &self.common.left.client, - &self.right_to_left_transaction_params, self.common.left.client.can_start_version_guard(), ) .await?; diff --git a/relays/lib-substrate-relay/src/equivocation/mod.rs b/relays/lib-substrate-relay/src/equivocation/mod.rs index ee0928c2af137..f6d58cbaa4ab4 100644 --- a/relays/lib-substrate-relay/src/equivocation/mod.rs +++ b/relays/lib-substrate-relay/src/equivocation/mod.rs @@ -66,6 +66,20 @@ pub trait SubstrateEquivocationDetectionPipeline: { /// How the `report_equivocation` call is built ? type ReportEquivocationCallBuilder: ReportEquivocationCallBuilder; + + /// Add relay guards if required. + async fn start_relay_guards( + source_client: &Client, + enable_version_guard: bool, + ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + source_client.clone(), + source_client.simple_runtime_version().await?.spec_version, + ); + } + Ok(()) + } } type FinalityProoffOf

= <

::FinalityEngine as Engine< diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index 98aec1d52b908..b8cf27ea78fde 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -75,10 +75,15 @@ pub trait SubstrateFinalitySyncPipeline: BaseSubstrateFinalitySyncPipeline { /// Add relay guards if required. async fn start_relay_guards( - _target_client: &Client, - _transaction_params: &TransactionParams>, - _enable_version_guard: bool, + target_client: &Client, + enable_version_guard: bool, ) -> relay_substrate_client::Result<()> { + if enable_version_guard { + relay_substrate_client::guard::abort_on_spec_version_change( + target_client.clone(), + target_client.simple_runtime_version().await?.spec_version, + ); + } Ok(()) } } From 111a18c82366fcf069cc05eab817b54ffd4a114b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 14 Nov 2023 11:50:26 +0300 Subject: [PATCH 1148/1210] Drop Rialto <> Millau bridges (#2663) (#2694) * drop Rialto <> Millau bridges * clippy --- README.md | 175 +- bin/millau/node/Cargo.toml | 61 - bin/millau/node/build.rs | 23 - bin/millau/node/src/chain_spec.rs | 237 -- bin/millau/node/src/cli.rs | 73 - bin/millau/node/src/command.rs | 154 - bin/millau/node/src/lib.rs | 32 - bin/millau/node/src/main.rs | 30 - bin/millau/node/src/service.rs | 479 --- bin/millau/runtime/Cargo.toml | 155 - bin/millau/runtime/build.rs | 26 - bin/millau/runtime/src/lib.rs | 1300 -------- bin/millau/runtime/src/rialto_messages.rs | 216 -- .../runtime/src/rialto_parachain_messages.rs | 227 -- bin/millau/runtime/src/weights/mod.rs | 21 - ...h_runtime_with_rialto_messages_instance.rs | 188 -- ...with_rialto_parachain_messages_instance.rs | 188 -- bin/millau/runtime/src/xcm_config.rs | 410 --- bin/rialto-parachain/node/Cargo.toml | 81 - bin/rialto-parachain/node/build.rs | 22 - bin/rialto-parachain/node/src/chain_spec.rs | 202 -- bin/rialto-parachain/node/src/cli.rs | 109 - bin/rialto-parachain/node/src/command.rs | 372 --- bin/rialto-parachain/node/src/lib.rs | 19 - bin/rialto-parachain/node/src/main.rs | 30 - bin/rialto-parachain/node/src/service.rs | 505 --- bin/rialto-parachain/runtime/Cargo.toml | 146 - bin/rialto-parachain/runtime/build.rs | 26 - bin/rialto-parachain/runtime/src/lib.rs | 975 ------ .../runtime/src/millau_messages.rs | 206 -- bin/rialto/node/Cargo.toml | 61 - bin/rialto/node/build.rs | 23 - bin/rialto/node/src/chain_spec.rs | 282 -- bin/rialto/node/src/cli.rs | 84 - bin/rialto/node/src/command.rs | 193 -- bin/rialto/node/src/main.rs | 28 - bin/rialto/node/src/workers/execute-worker.rs | 23 - bin/rialto/node/src/workers/prepare-worker.rs | 23 - bin/rialto/runtime/Cargo.toml | 153 - bin/rialto/runtime/build.rs | 26 - bin/rialto/runtime/src/lib.rs | 1074 ------ bin/rialto/runtime/src/millau_messages.rs | 200 -- bin/rialto/runtime/src/parachains.rs | 274 -- bin/rialto/runtime/src/xcm_config.rs | 280 -- bin/runtime-common/src/lib.rs | 41 +- bin/runtime-common/src/mock.rs | 7 +- bin/runtime-common/src/priority_calculator.rs | 1 + docs/high-level-overview.md | 2 +- modules/grandpa/src/weights.rs | 62 +- modules/messages/src/weights.rs | 226 +- modules/parachains/src/weights.rs | 122 +- modules/parachains/src/weights_ext.rs | 2 +- modules/relayers/src/weights.rs | 2 +- modules/shift-session-manager/Cargo.toml | 38 - modules/shift-session-manager/README.md | 10 - modules/shift-session-manager/src/lib.rs | 259 -- modules/xcm-bridge-hub-router/src/weights.rs | 2 +- primitives/chain-millau/Cargo.toml | 62 - primitives/chain-millau/src/lib.rs | 244 -- primitives/chain-millau/src/millau_hash.rs | 56 - primitives/chain-rialto-parachain/Cargo.toml | 39 - primitives/chain-rialto-parachain/src/lib.rs | 148 - primitives/chain-rialto/Cargo.toml | 38 - primitives/chain-rialto/src/lib.rs | 210 -- primitives/runtime/src/chain.rs | 6 +- primitives/runtime/src/lib.rs | 29 - relays/bin-substrate/Cargo.toml | 19 - relays/bin-substrate/src/bridges/mod.rs | 3 - .../rialto_millau/millau_headers_to_rialto.rs | 74 - .../millau_messages_to_rialto.rs | 47 - .../src/bridges/rialto_millau/mod.rs | 22 - .../rialto_millau/rialto_headers_to_millau.rs | 74 - .../rialto_messages_to_millau.rs | 47 - .../millau_headers_to_rialto_parachain.rs | 95 - .../millau_messages_to_rialto_parachain.rs | 51 - .../bridges/rialto_parachain_millau/mod.rs | 22 - .../rialto_parachain_messages_to_millau.rs | 51 - .../rialto_parachains_to_millau.rs | 65 - .../src/bridges/westend_millau/mod.rs | 20 - .../westend_headers_to_millau.rs | 54 - .../westend_parachains_to_millau.rs | 90 - relays/bin-substrate/src/chains/millau.rs | 75 - relays/bin-substrate/src/chains/mod.rs | 87 - relays/bin-substrate/src/chains/rialto.rs | 62 - .../src/chains/rialto_parachain.rs | 65 - relays/bin-substrate/src/cli/bridge.rs | 4 - relays/bin-substrate/src/cli/chain_schema.rs | 44 +- .../src/cli/detect_equivocations.rs | 15 - .../bin-substrate/src/cli/encode_message.rs | 189 -- relays/bin-substrate/src/cli/init_bridge.rs | 81 - relays/bin-substrate/src/cli/mod.rs | 47 +- .../src/cli/register_parachain.rs | 324 -- relays/bin-substrate/src/cli/relay_headers.rs | 19 - .../src/cli/relay_headers_and_messages/mod.rs | 361 +- .../parachain_to_parachain.rs | 64 +- .../relay_to_parachain.rs | 53 +- .../relay_to_relay.rs | 38 +- .../bin-substrate/src/cli/relay_messages.rs | 18 - .../bin-substrate/src/cli/relay_parachains.rs | 10 - .../src/cli/resubmit_transactions.rs | 560 ---- relays/bin-substrate/src/cli/send_message.rs | 177 - relays/client-millau/Cargo.toml | 27 - relays/client-millau/src/lib.rs | 197 -- relays/client-rialto-parachain/Cargo.toml | 30 - .../src/codegen_runtime.rs | 2936 ----------------- relays/client-rialto-parachain/src/lib.rs | 138 - relays/client-rialto/Cargo.toml | 27 - relays/client-rialto/src/lib.rs | 191 -- relays/finality/README.md | 14 +- relays/lib-substrate-relay/Cargo.toml | 7 +- relays/lib-substrate-relay/src/lib.rs | 23 +- .../lib-substrate-relay/src/messages_lane.rs | 2 - .../src/messages_source.rs | 35 +- relays/parachains/README.md | 14 +- 114 files changed, 363 insertions(+), 17323 deletions(-) delete mode 100644 bin/millau/node/Cargo.toml delete mode 100644 bin/millau/node/build.rs delete mode 100644 bin/millau/node/src/chain_spec.rs delete mode 100644 bin/millau/node/src/cli.rs delete mode 100644 bin/millau/node/src/command.rs delete mode 100644 bin/millau/node/src/lib.rs delete mode 100644 bin/millau/node/src/main.rs delete mode 100644 bin/millau/node/src/service.rs delete mode 100644 bin/millau/runtime/Cargo.toml delete mode 100644 bin/millau/runtime/build.rs delete mode 100644 bin/millau/runtime/src/lib.rs delete mode 100644 bin/millau/runtime/src/rialto_messages.rs delete mode 100644 bin/millau/runtime/src/rialto_parachain_messages.rs delete mode 100644 bin/millau/runtime/src/weights/mod.rs delete mode 100644 bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs delete mode 100644 bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs delete mode 100644 bin/millau/runtime/src/xcm_config.rs delete mode 100644 bin/rialto-parachain/node/Cargo.toml delete mode 100644 bin/rialto-parachain/node/build.rs delete mode 100644 bin/rialto-parachain/node/src/chain_spec.rs delete mode 100644 bin/rialto-parachain/node/src/cli.rs delete mode 100644 bin/rialto-parachain/node/src/command.rs delete mode 100644 bin/rialto-parachain/node/src/lib.rs delete mode 100644 bin/rialto-parachain/node/src/main.rs delete mode 100644 bin/rialto-parachain/node/src/service.rs delete mode 100644 bin/rialto-parachain/runtime/Cargo.toml delete mode 100644 bin/rialto-parachain/runtime/build.rs delete mode 100644 bin/rialto-parachain/runtime/src/lib.rs delete mode 100644 bin/rialto-parachain/runtime/src/millau_messages.rs delete mode 100644 bin/rialto/node/Cargo.toml delete mode 100644 bin/rialto/node/build.rs delete mode 100644 bin/rialto/node/src/chain_spec.rs delete mode 100644 bin/rialto/node/src/cli.rs delete mode 100644 bin/rialto/node/src/command.rs delete mode 100644 bin/rialto/node/src/main.rs delete mode 100644 bin/rialto/node/src/workers/execute-worker.rs delete mode 100644 bin/rialto/node/src/workers/prepare-worker.rs delete mode 100644 bin/rialto/runtime/Cargo.toml delete mode 100644 bin/rialto/runtime/build.rs delete mode 100644 bin/rialto/runtime/src/lib.rs delete mode 100644 bin/rialto/runtime/src/millau_messages.rs delete mode 100644 bin/rialto/runtime/src/parachains.rs delete mode 100644 bin/rialto/runtime/src/xcm_config.rs delete mode 100644 modules/shift-session-manager/Cargo.toml delete mode 100644 modules/shift-session-manager/README.md delete mode 100644 modules/shift-session-manager/src/lib.rs delete mode 100644 primitives/chain-millau/Cargo.toml delete mode 100644 primitives/chain-millau/src/lib.rs delete mode 100644 primitives/chain-millau/src/millau_hash.rs delete mode 100644 primitives/chain-rialto-parachain/Cargo.toml delete mode 100644 primitives/chain-rialto-parachain/src/lib.rs delete mode 100644 primitives/chain-rialto/Cargo.toml delete mode 100644 primitives/chain-rialto/src/lib.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_millau/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs delete mode 100644 relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs delete mode 100644 relays/bin-substrate/src/bridges/westend_millau/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs delete mode 100644 relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs delete mode 100644 relays/bin-substrate/src/chains/millau.rs delete mode 100644 relays/bin-substrate/src/chains/rialto.rs delete mode 100644 relays/bin-substrate/src/chains/rialto_parachain.rs delete mode 100644 relays/bin-substrate/src/cli/encode_message.rs delete mode 100644 relays/bin-substrate/src/cli/register_parachain.rs delete mode 100644 relays/bin-substrate/src/cli/resubmit_transactions.rs delete mode 100644 relays/bin-substrate/src/cli/send_message.rs delete mode 100644 relays/client-millau/Cargo.toml delete mode 100644 relays/client-millau/src/lib.rs delete mode 100644 relays/client-rialto-parachain/Cargo.toml delete mode 100644 relays/client-rialto-parachain/src/codegen_runtime.rs delete mode 100644 relays/client-rialto-parachain/src/lib.rs delete mode 100644 relays/client-rialto/Cargo.toml delete mode 100644 relays/client-rialto/src/lib.rs diff --git a/README.md b/README.md index da46fe67d924a..f8191f432adfa 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ For example, consider the case below where we want to bridge two Substrate based ``` +---------------+ +---------------+ | | | | -| Rialto | | Millau | +| Rococo | | Westend | | | | | +-------+-------+ +-------+-------+ ^ ^ @@ -79,9 +79,9 @@ For example, consider the case below where we want to bridge two Substrate based +---------------+ ``` -The Millau chain must be able to accept Rialto headers and verify their integrity. It does this by using a runtime +The Rococo chain must be able to accept Westend headers and verify their integrity. It does this by using a runtime module designed to track GRANDPA finality. Since two blockchains can't interact directly they need an external service, -called a relayer, to communicate. The relayer will subscribe to new Rialto headers via RPC and submit them to the Millau +called a relayer, to communicate. The relayer will subscribe to new Rococo headers via RPC and submit them to the Westend chain for verification. Take a look at [Bridge High Level Documentation](./docs/high-level-overview.md) for more in-depth description of the @@ -94,164 +94,23 @@ Here's an overview of how the project is laid out. The main bits are the `bin`, messages between chains. ``` -├── bin // Node and Runtime for the various Substrate chains -│ └── ... -├── deployments // Useful tools for deploying test networks +├── modules // Substrate Runtime Modules (a.k.a Pallets) +│ ├── beefy // On-Chain BEEFY Light Client (in progress) +│ ├── grandpa // On-Chain GRANDPA Light Client +│ ├── messages // Cross Chain Message Passing +│ ├── parachains // On-Chain Parachains Light Client +│ ├── relayers // Relayer Rewards Registry +│ ├── xcm-bridge-hub // Multiple Dynamic Bridges Support +│ ├── xcm-bridge-hub-router // XCM Router that may be used to Connect to XCM Bridge Hub +├── primitives // Code shared between modules, runtimes, and relays │ └── ... -├── modules // Substrate Runtime Modules (a.k.a Pallets) -│ ├── beefy // On-Chain BEEFY Light Client (in progress) -│ ├── grandpa // On-Chain GRANDPA Light Client -│ ├── messages // Cross Chain Message Passing -│ ├── parachains // On-Chain Parachains Light Client -│ ├── relayers // Relayer rewards registry +├── relays // Application for sending finality proofs and messages between chains │ └── ... -├── primitives // Code shared between modules, runtimes, and relays -│ └── ... -├── relays // Application for sending finality proofs and messages between chains -│ └── ... -└── scripts // Useful development and maintenance scripts +└── scripts // Useful development and maintenance scripts ``` ## Running the Bridge -To run the Bridge you need to be able to connect the bridge relay node to the RPC interface of nodes on each side of the -bridge (source and target chain). - -There are 2 ways to run the bridge, described below: - -- building & running from source: with this option, you'll be able to run the bridge between two standalone chains that -are running GRANDPA finality gadget to achieve finality; - -- running a Docker Compose setup: this is a recommended option, where you'll see bridges with parachains, complex relays -and more. - -### Using the Source - -First you'll need to build the bridge nodes and relay. This can be done as follows: - -```bash -# In `parity-bridges-common` folder -cargo build -p rialto-bridge-node -cargo build -p millau-bridge-node -cargo build -p substrate-relay -``` - -### Running a Dev network - -We will launch a dev network to demonstrate how to relay a message between two Substrate based chains (named Rialto and -Millau). - -To do this we will need two nodes, two relayers which will relay headers, and two relayers which will relay messages. - -#### Running from local scripts - -To run a simple dev network you can use the scripts located in the [`deployments/local-scripts` -folder](./deployments/local-scripts). - -First, we must run the two Substrate nodes. - -```bash -# In `parity-bridges-common` folder -./deployments/local-scripts/run-rialto-node.sh -./deployments/local-scripts/run-millau-node.sh -``` - -After the nodes are up we can run the header relayers. - -```bash -./deployments/local-scripts/relay-millau-to-rialto.sh -./deployments/local-scripts/relay-rialto-to-millau.sh -``` - -At this point you should see the relayer submitting headers from the Millau Substrate chain to the Rialto Substrate -chain. - -``` -# Header Relayer Logs -[Millau_to_Rialto_Sync] [date] DEBUG bridge Going to submit finality proof of Millau header #147 to Rialto -[...] [date] INFO bridge Synced 147 of 147 headers -[...] [date] DEBUG bridge Going to submit finality proof of Millau header #148 to Rialto -[...] [date] INFO bridge Synced 148 of 149 headers -``` - -Finally, we can run the message relayers. - -```bash -./deployments/local-scripts/relay-messages-millau-to-rialto.sh -./deployments/local-scripts/relay-messages-rialto-to-millau.sh -``` - -You will also see the message lane relayers listening for new messages. - -``` -# Message Relayer Logs -[Millau_to_Rialto_MessageLane_00000000] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about best message nonces -[...] [date] INFO bridge Synced Some(2) of Some(3) nonces in Millau::MessagesDelivery -> Rialto::MessagesDelivery race -[...] [date] DEBUG bridge Asking Millau::MessagesDelivery about message nonces -[...] [date] DEBUG bridge Received best nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { - latest_nonce: 0, nonces_data: () } -[...] [date] DEBUG bridge Asking Millau::ReceivingConfirmationsDelivery about finalized message nonces -[...] [date] DEBUG bridge Received finalized nonces from Millau::ReceivingConfirmationsDelivery: TargetClientNonces { - latest_nonce: 0, nonces_data: () } -[...] [date] DEBUG bridge Received nonces from Millau::MessagesDelivery: SourceClientNonces { new_nonces: {}, confirmed_nonce: Some(0) } -[...] [date] DEBUG bridge Asking Millau node about its state -[...] [date] DEBUG bridge Received state from Millau node: ClientState { best_self: HeaderId(1593, 0xacac***), best_finalized_self: - HeaderId(1590, 0x0be81d...), best_finalized_peer_at_best_self: HeaderId(0, 0xdcdd89...) } -``` - -To send a message see the ["How to send a message" section](#how-to-send-a-message). - -### How to send a message - -In this section we'll show you how to quickly send a bridge message. The message is just an encoded XCM `Trap(43)` -message. - -```bash -# In `parity-bridges-common` folder -./scripts/send-message-from-millau-rialto.sh -``` - -After sending a message you will see the following logs showing a message was successfully sent: - -``` -INFO bridge Sending message to Rialto. Size: 11. -TRACE bridge Sent transaction to Millau node: 0x5e68... -``` - -And at the Rialto node logs you'll something like this: - -``` -... runtime::bridge-messages: Received messages: total=1, valid=1. Weight used: Weight(ref_time: 1215065371, proof_size: - 48559)/Weight(ref_time: 1215065371, proof_size: 54703). -``` - -It means that the message has been delivered and dispatched. Message may be dispatched with an error, though - the goal -of our test bridge is to ensure that messages are successfully delivered and all involved components are working. - -## Full Network Docker Compose Setup - -For a more sophisticated deployment which includes bidirectional header sync, message passing, monitoring dashboards, -etc. see the [Deployments README](./deployments/README.md). - -You should note that you can find images for all the bridge components published on [Docker -Hub](https://hub.docker.com/u/paritytech). - -To run a Rialto node for example, you can use the following command: - -```bash -docker run -p 30333:30333 -p 9933:9933 -p 9944:9944 \ - -it paritytech/rialto-bridge-node --dev --tmp \ - --rpc-cors=all --unsafe-rpc-external -``` - -## Community - -Main hangout for the community is [Element](https://element.io/) (formerly Riot). Element is a chat server like, for -example, Discord. Most discussions around Polkadot and Substrate happen in various Element "rooms" (channels). So, -joining Element might be a good idea, anyway. - -If you are interested in information exchange and development of Polkadot related bridges please feel free to join the -[Polkadot Bridges](https://app.element.io/#/room/#bridges:web3.foundation) Element channel. - -The [Substrate Technical](https://app.element.io/#/room/#substrate-technical:matrix.org) Element channel is most suited -for discussions regarding Substrate itself. +Apart from live Rococo <> Westend bridge, you may spin up local networks and test see how it works locally. More +details may be found in +[this document](https://github.com/paritytech/polkadot-sdk/tree/master//cumulus/parachains/runtimes/bridge-hubs/README.md). diff --git a/bin/millau/node/Cargo.toml b/bin/millau/node/Cargo.toml deleted file mode 100644 index 426cb9e863ee1..0000000000000 --- a/bin/millau/node/Cargo.toml +++ /dev/null @@ -1,61 +0,0 @@ -[package] -name = "millau-bridge-node" -description = "Substrate node compatible with Millau runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -build = "build.rs" -repository = "https://github.com/paritytech/parity-bridges-common/" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -clap = { version = "4.4.8", features = ["derive"] } -futures = "0.3.29" -jsonrpsee = { version = "0.16.2", features = ["server"] } -serde_json = "1.0.108" - -# Bridge dependencies - -millau-runtime = { path = "../runtime" } - -# Substrate Dependencies - -sc-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-consensus-beefy-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -node-inspect = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -mmr-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master"} -sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-consensus-grandpa-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-keystore = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-network = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-network-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[features] -default = [] -runtime-benchmarks = [ "millau-runtime/runtime-benchmarks" ] diff --git a/bin/millau/node/build.rs b/bin/millau/node/build.rs deleted file mode 100644 index d9b50049e2628..0000000000000 --- a/bin/millau/node/build.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 . - -use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; - -fn main() { - generate_cargo_keys(); - - rerun_if_git_head_changed(); -} diff --git a/bin/millau/node/src/chain_spec.rs b/bin/millau/node/src/chain_spec.rs deleted file mode 100644 index 01883bb4ef083..0000000000000 --- a/bin/millau/node/src/chain_spec.rs +++ /dev/null @@ -1,237 +0,0 @@ -// 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 . - -use millau_runtime::{ - AccountId, AuraConfig, BalancesConfig, BeefyConfig, BridgeRialtoMessagesConfig, - BridgeRialtoParachainMessagesConfig, BridgeWestendGrandpaConfig, GrandpaConfig, - RuntimeGenesisConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, - WASM_BINARY, -}; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; -use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{sr25519, Pair, Public}; -use sp_runtime::traits::{IdentifyAccount, Verify}; - -/// "Names" of the authorities accounts at local testnet. -const LOCAL_AUTHORITIES_ACCOUNTS: [&str; 5] = ["Alice", "Bob", "Charlie", "Dave", "Eve"]; -/// "Names" of the authorities accounts at development testnet. -const DEV_AUTHORITIES_ACCOUNTS: [&str; 1] = [LOCAL_AUTHORITIES_ACCOUNTS[0]]; -/// "Names" of all possible authorities accounts. -const ALL_AUTHORITIES_ACCOUNTS: [&str; 5] = LOCAL_AUTHORITIES_ACCOUNTS; -/// "Name" of the `sudo` account. -const SUDO_ACCOUNT: &str = "Sudo"; -/// "Name" of the account, which owns the with-Westend GRANDPA pallet. -const WESTEND_GRANDPA_PALLET_OWNER: &str = "Westend.GrandpaOwner"; -/// "Name" of the account, which owns the with-Rialto messages pallet. -const RIALTO_MESSAGES_PALLET_OWNER: &str = "Rialto.MessagesOwner"; -/// "Name" of the account, which owns the with-RialtoParachain messages pallet. -const RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER: &str = "RialtoParachain.MessagesOwner"; - -/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = sc_service::GenericChainSpec; - -/// The chain specification option. This is expected to come in from the CLI and -/// is little more than one of a number of alternatives which can easily be converted -/// from a string (`--chain=...`) into a `ChainSpec`. -#[derive(Clone, Debug)] -pub enum Alternative { - /// Whatever the current runtime is, with just Alice as an auth. - Development, - /// Whatever the current runtime is, with simple Alice/Bob/Charlie/Dave/Eve auths. - LocalTestnet, -} - -/// Helper function to generate a crypto pair from seed -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{seed}"), None) - .expect("static values are valid; qed") - .public() -} - -type AccountPublic = ::Signer; - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId -where - AccountPublic: From<::Public>, -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// Helper function to generate an authority key for Aura -pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, BeefyId, GrandpaId) { - ( - get_account_id_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - ) -} - -impl Alternative { - /// Get an actual chain config from one of the alternatives. - pub(crate) fn load(self) -> ChainSpec { - let properties = Some( - serde_json::json!({ - "tokenDecimals": 9, - "tokenSymbol": "MLAU" - }) - .as_object() - .expect("Map given; qed") - .clone(), - ); - match self { - Alternative::Development => ChainSpec::from_genesis( - "Millau Development", - "millau_dev", - sc_service::ChainType::Development, - || { - testnet_genesis( - DEV_AUTHORITIES_ACCOUNTS - .into_iter() - .map(get_authority_keys_from_seed) - .collect(), - get_account_id_from_seed::(SUDO_ACCOUNT), - endowed_accounts(), - true, - ) - }, - vec![], - None, - None, - None, - properties, - None, - ), - Alternative::LocalTestnet => ChainSpec::from_genesis( - "Millau Local", - "millau_local", - sc_service::ChainType::Local, - || { - testnet_genesis( - LOCAL_AUTHORITIES_ACCOUNTS - .into_iter() - .map(get_authority_keys_from_seed) - .collect(), - get_account_id_from_seed::(SUDO_ACCOUNT), - endowed_accounts(), - true, - ) - }, - vec![], - None, - None, - None, - properties, - None, - ), - } - } -} - -/// We're using the same set of endowed accounts on all Millau chains (dev/local) to make -/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, -/// accounts used by relayers in our test deployments, accounts used for demonstration -/// purposes), are all available on these chains. -fn endowed_accounts() -> Vec { - let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { - [ - get_account_id_from_seed::(x), - get_account_id_from_seed::(&format!("{x}//stash")), - ] - }); - vec![ - // Sudo account - get_account_id_from_seed::(SUDO_ACCOUNT), - // Regular (unused) accounts - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Ferdie//stash"), - // Accounts, used by Westend<>Millau bridge - get_account_id_from_seed::(WESTEND_GRANDPA_PALLET_OWNER), - get_account_id_from_seed::("Westend.HeadersRelay1"), - get_account_id_from_seed::("Westend.HeadersRelay2"), - get_account_id_from_seed::("Westend.AssetHubWestendHeaders1"), - get_account_id_from_seed::("Westend.AssetHubWestendHeaders2"), - // Accounts, used by Rialto<>Millau bridge - get_account_id_from_seed::(RIALTO_MESSAGES_PALLET_OWNER), - get_account_id_from_seed::("Rialto.HeadersAndMessagesRelay"), - get_account_id_from_seed::("Rialto.OutboundMessagesRelay.Lane00000001"), - get_account_id_from_seed::("Rialto.InboundMessagesRelay.Lane00000001"), - get_account_id_from_seed::("Rialto.MessagesSender"), - // Accounts, used by RialtoParachain<>Millau bridge - get_account_id_from_seed::(RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER), - get_account_id_from_seed::("RialtoParachain.HeadersAndMessagesRelay1"), - get_account_id_from_seed::("RialtoParachain.HeadersAndMessagesRelay2"), - get_account_id_from_seed::("RialtoParachain.RialtoHeadersRelay1"), - get_account_id_from_seed::("RialtoParachain.RialtoHeadersRelay2"), - get_account_id_from_seed::("RialtoParachain.MessagesSender"), - ] - .into_iter() - .chain(all_authorities) - .collect() -} - -fn session_keys(aura: AuraId, beefy: BeefyId, grandpa: GrandpaId) -> SessionKeys { - SessionKeys { aura, beefy, grandpa } -} - -fn testnet_genesis( - initial_authorities: Vec<(AccountId, AuraId, BeefyId, GrandpaId)>, - root_key: AccountId, - endowed_accounts: Vec, - _enable_println: bool, -) -> RuntimeGenesisConfig { - RuntimeGenesisConfig { - system: SystemConfig { - code: WASM_BINARY.expect("Millau development WASM not available").to_vec(), - ..Default::default() - }, - balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), - }, - aura: AuraConfig { authorities: Vec::new() }, - beefy: BeefyConfig::default(), - grandpa: GrandpaConfig { authorities: Vec::new(), ..Default::default() }, - sudo: SudoConfig { key: Some(root_key) }, - session: SessionConfig { - keys: initial_authorities - .iter() - .map(|x| { - (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone(), x.3.clone())) - }) - .collect::>(), - }, - bridge_westend_grandpa: BridgeWestendGrandpaConfig { - // for our deployments to avoid multiple same-nonces transactions: - // //Alice is already used to initialize Rialto<->Millau bridge - // => let's use //Westend.GrandpaOwner to initialize Westend->Millau bridge - owner: Some(get_account_id_from_seed::(WESTEND_GRANDPA_PALLET_OWNER)), - ..Default::default() - }, - bridge_rialto_messages: BridgeRialtoMessagesConfig { - owner: Some(get_account_id_from_seed::(RIALTO_MESSAGES_PALLET_OWNER)), - ..Default::default() - }, - bridge_rialto_parachain_messages: BridgeRialtoParachainMessagesConfig { - owner: Some(get_account_id_from_seed::( - RIALTO_PARACHAIN_MESSAGES_PALLET_OWNER, - )), - ..Default::default() - }, - xcm_pallet: Default::default(), - } -} diff --git a/bin/millau/node/src/cli.rs b/bin/millau/node/src/cli.rs deleted file mode 100644 index 12499b5718d6d..0000000000000 --- a/bin/millau/node/src/cli.rs +++ /dev/null @@ -1,73 +0,0 @@ -// 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 . - -use clap::Parser; -use sc_cli::RunCmd; - -#[derive(Debug, Parser)] -pub struct Cli { - #[structopt(subcommand)] - pub subcommand: Option, - - #[structopt(flatten)] - pub run: RunCmd, -} - -/// Possible subcommands of the main binary. -#[derive(Debug, Parser)] -#[allow(clippy::large_enum_variant)] -pub enum Subcommand { - /// Key management CLI utilities - #[clap(subcommand)] - Key(sc_cli::KeySubcommand), - - /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. - Verify(sc_cli::VerifyCmd), - - /// Generate a seed that provides a vanity address. - Vanity(sc_cli::VanityCmd), - - /// Sign a message, with a given (secret) key. - Sign(sc_cli::SignCmd), - - /// Build a chain specification. - BuildSpec(sc_cli::BuildSpecCmd), - - /// Validate blocks. - CheckBlock(sc_cli::CheckBlockCmd), - - /// Export blocks. - ExportBlocks(sc_cli::ExportBlocksCmd), - - /// Export the state of a given block into a chain spec. - ExportState(sc_cli::ExportStateCmd), - - /// Import blocks. - ImportBlocks(sc_cli::ImportBlocksCmd), - - /// Remove the whole chain. - PurgeChain(sc_cli::PurgeChainCmd), - - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), - - /// Inspect blocks or extrinsics. - Inspect(node_inspect::cli::InspectCmd), - - /// Benchmark runtime pallets. - #[clap(subcommand)] - Benchmark(frame_benchmarking_cli::BenchmarkCmd), -} diff --git a/bin/millau/node/src/command.rs b/bin/millau/node/src/command.rs deleted file mode 100644 index 745b393786e1d..0000000000000 --- a/bin/millau/node/src/command.rs +++ /dev/null @@ -1,154 +0,0 @@ -// 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 . - -use crate::{ - cli::{Cli, Subcommand}, - service, - service::new_partial, -}; -use frame_benchmarking_cli::BenchmarkCmd; -use millau_runtime::{Block, RuntimeApi}; -use sc_cli::SubstrateCli; -use sc_service::PartialComponents; - -impl SubstrateCli for Cli { - fn impl_name() -> String { - "Millau Bridge Node".into() - } - - fn impl_version() -> String { - env!("CARGO_PKG_VERSION").into() - } - - fn description() -> String { - "Millau Bridge Node".into() - } - - fn author() -> String { - "Parity Technologies".into() - } - - fn support_url() -> String { - "https://github.com/paritytech/parity-bridges-common/".into() - } - - fn copyright_start_year() -> i32 { - 2019 - } - - fn executable_name() -> String { - "millau-bridge-node".into() - } - - fn load_spec(&self, id: &str) -> Result, String> { - Ok(Box::new( - match id { - "" | "dev" => crate::chain_spec::Alternative::Development, - "local" => crate::chain_spec::Alternative::LocalTestnet, - _ => return Err(format!("Unsupported chain specification: {id}")), - } - .load(), - )) - } -} - -/// Parse and run command line arguments -pub fn run() -> sc_cli::Result<()> { - let cli = Cli::from_args(); - // make sure to set correct crypto version. - sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom( - millau_runtime::SS58Prefix::get() as u16, - )); - - match &cli.subcommand { - Some(Subcommand::Benchmark(cmd)) => { - let runner = cli.create_runner(cmd)?; - match cmd { - BenchmarkCmd::Pallet(cmd) => - if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) - } else { - println!( - "Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - ); - Ok(()) - }, - _ => Err("Unsupported benchmarking subcommand".into()), - } - }, - Some(Subcommand::Key(cmd)) => cmd.run(&cli), - Some(Subcommand::Sign(cmd)) => cmd.run(), - Some(Subcommand::Verify(cmd)) => cmd.run(), - Some(Subcommand::Vanity(cmd)) => cmd.run(), - Some(Subcommand::BuildSpec(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, - Some(Subcommand::CheckBlock(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - new_partial(&config)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::ExportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = new_partial(&config)?; - Ok((cmd.run(client, config.database), task_manager)) - }) - }, - Some(Subcommand::ExportState(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = new_partial(&config)?; - Ok((cmd.run(client, config.chain_spec), task_manager)) - }) - }, - Some(Subcommand::ImportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - new_partial(&config)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::PurgeChain(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.database)) - }, - Some(Subcommand::Revert(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, .. } = new_partial(&config)?; - Ok((cmd.run(client, backend, None), task_manager)) - }) - }, - Some(Subcommand::Inspect(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner - .sync_run(|config| cmd.run::(config)) - }, - None => { - let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| async move { - service::new_full(config).map_err(sc_cli::Error::Service) - }) - }, - } -} diff --git a/bin/millau/node/src/lib.rs b/bin/millau/node/src/lib.rs deleted file mode 100644 index 382d1c2d7fb1c..0000000000000 --- a/bin/millau/node/src/lib.rs +++ /dev/null @@ -1,32 +0,0 @@ -// 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 . - -//! Substrate Node Template CLI library. -#![warn(missing_docs)] - -mod chain_spec; -#[macro_use] -mod service; -mod cli; -mod command; - -/// Node run result. -pub type Result = sc_cli::Result<()>; - -/// Run node. -pub fn run() -> Result { - command::run() -} diff --git a/bin/millau/node/src/main.rs b/bin/millau/node/src/main.rs deleted file mode 100644 index cf6dd9f733a16..0000000000000 --- a/bin/millau/node/src/main.rs +++ /dev/null @@ -1,30 +0,0 @@ -// 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 . - -//! Millau bridge node. - -#![warn(missing_docs)] - -mod chain_spec; -#[macro_use] -mod service; -mod cli; -mod command; - -/// Run the Millau Node -fn main() -> sc_cli::Result<()> { - command::run() -} diff --git a/bin/millau/node/src/service.rs b/bin/millau/node/src/service.rs deleted file mode 100644 index cb57dd118cc71..0000000000000 --- a/bin/millau/node/src/service.rs +++ /dev/null @@ -1,479 +0,0 @@ -// 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 . - -//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. - -use jsonrpsee::RpcModule; -use millau_runtime::{self, opaque::Block, RuntimeApi}; -use sc_client_api::{Backend, BlockBackend}; -use sc_consensus_aura::{CompatibilityMode, ImportQueueParams, SlotProportion, StartAuraParams}; -use sc_consensus_grandpa::SharedVoterState; -pub use sc_executor::NativeElseWasmExecutor; -use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; -use sc_service::{error::Error as ServiceError, Configuration, TaskManager}; -use sc_telemetry::{Telemetry, TelemetryWorker}; -use sc_transaction_pool_api::OffchainTransactionPoolFactory; -use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; -use std::{sync::Arc, time::Duration}; - -// Our native executor instance. -pub struct ExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { - /// Only enable the benchmarking host functions when we actually want to benchmark. - #[cfg(feature = "runtime-benchmarks")] - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - /// Otherwise we only use the default Substrate host functions. - #[cfg(not(feature = "runtime-benchmarks"))] - type ExtendHostFunctions = (); - - fn dispatch(method: &str, data: &[u8]) -> Option> { - millau_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - millau_runtime::native_version() - } -} - -type FullClient = - sc_service::TFullClient>; -type FullBackend = sc_service::TFullBackend; -type FullSelectChain = sc_consensus::LongestChain; - -#[allow(clippy::type_complexity)] -pub fn new_partial( - config: &Configuration, -) -> Result< - sc_service::PartialComponents< - FullClient, - FullBackend, - FullSelectChain, - sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, - ( - sc_consensus_grandpa::GrandpaBlockImport< - FullBackend, - Block, - FullClient, - FullSelectChain, - >, - sc_consensus_grandpa::LinkHalf, - sc_consensus_beefy::BeefyVoterLinks, - sc_consensus_beefy::BeefyRPCLinks, - Option, - ), - >, - ServiceError, -> { - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let heap_pages = config - .default_heap_pages - .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); - let executor = NativeElseWasmExecutor::::new_with_wasm_executor( - WasmExecutor::builder() - .with_execution_method(config.wasm_method) - .with_onchain_heap_alloc_strategy(heap_pages) - .with_offchain_heap_alloc_strategy(heap_pages) - .with_max_runtime_instances(config.max_runtime_instances) - .with_runtime_cache_size(config.runtime_cache_size) - .build(), - ); - - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - let client = Arc::new(client); - - let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", None, worker.run()); - telemetry - }); - - let select_chain = sc_consensus::LongestChain::new(backend.clone()); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( - client.clone(), - 512, - &client, - select_chain.clone(), - telemetry.as_ref().map(|x| x.handle()), - )?; - - let (beefy_block_import, beefy_voter_links, beefy_rpc_links) = - sc_consensus_beefy::beefy_block_import_and_links( - grandpa_block_import.clone(), - backend.clone(), - client.clone(), - config.prometheus_registry().cloned(), - ); - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: beefy_block_import, - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: CompatibilityMode::None, - })?; - - Ok(sc_service::PartialComponents { - client, - backend, - task_manager, - import_queue, - keystore_container, - select_chain, - transaction_pool, - other: (grandpa_block_import, grandpa_link, beefy_voter_links, beefy_rpc_links, telemetry), - }) -} - -/// Builds a new service for a full client. -pub fn new_full(config: Configuration) -> Result { - use sc_service::WarpSyncParams; - - let sc_service::PartialComponents { - client, - backend, - mut task_manager, - import_queue, - keystore_container, - select_chain, - transaction_pool, - other: (block_import, grandpa_link, beefy_voter_links, beefy_rpc_links, mut telemetry), - } = new_partial(&config)?; - - let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); - - let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network); - - // Note: GrandPa is pushed before the Polkadot-specific protocols. This doesn't change - // anything in terms of behaviour, but makes the logs more consistent with the other - // Substrate nodes. - let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( - &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), - &config.chain_spec, - ); - net_config.add_notification_protocol(sc_consensus_grandpa::grandpa_peers_set_config( - grandpa_protocol_name.clone(), - )); - - let beefy_gossip_proto_name = - sc_consensus_beefy::gossip_protocol_name(genesis_hash, config.chain_spec.fork_id()); - // `beefy_on_demand_justifications_handler` is given to `beefy-gadget` task to be run, - // while `beefy_req_resp_cfg` is added to `config.network.request_response_protocols`. - let (beefy_on_demand_justifications_handler, beefy_req_resp_cfg) = - sc_consensus_beefy::communication::request_response::BeefyJustifsRequestHandler::new( - genesis_hash, - config.chain_spec.fork_id(), - client.clone(), - config.prometheus_registry().cloned(), - ); - net_config.add_notification_protocol( - sc_consensus_beefy::communication::beefy_peers_set_config(beefy_gossip_proto_name.clone()), - ); - net_config.add_request_response_protocol(beefy_req_resp_cfg); - - let role = config.role.clone(); - let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( - backend.clone(), - grandpa_link.shared_authority_set().clone(), - Vec::default(), - )); - - let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: &config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue, - block_announce_validator_builder: None, - warp_sync_params: Some(WarpSyncParams::WithProvider(warp_sync)), - block_relay: None, - })?; - - if config.offchain_worker.enabled { - use futures::FutureExt; - - task_manager.spawn_handle().spawn( - "offchain-workers-runner", - "offchain-work", - sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { - runtime_api_provider: client.clone(), - keystore: Some(keystore_container.keystore()), - offchain_db: backend.offchain_storage(), - transaction_pool: Some(OffchainTransactionPoolFactory::new( - transaction_pool.clone(), - )), - network_provider: network.clone(), - is_validator: role.is_authority(), - enable_http_requests: false, - custom_extensions: move |_| vec![], - }) - .run(client.clone(), task_manager.spawn_handle()) - .boxed(), - ); - } - - let force_authoring = config.force_authoring; - let backoff_authoring_blocks: Option<()> = None; - let name = config.network.node_name.clone(); - let enable_grandpa = !config.disable_grandpa; - let prometheus_registry = config.prometheus_registry().cloned(); - let shared_voter_state = SharedVoterState::empty(); - - let rpc_extensions_builder = { - use sc_consensus_grandpa::FinalityProofProvider as GrandpaFinalityProofProvider; - - use mmr_rpc::{Mmr, MmrApiServer}; - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use sc_consensus_beefy_rpc::{Beefy, BeefyApiServer}; - use sc_consensus_grandpa_rpc::{Grandpa, GrandpaApiServer}; - use sc_rpc::DenyUnsafe; - use substrate_frame_rpc_system::{System, SystemApiServer}; - - let backend = backend.clone(); - let client = client.clone(); - let pool = transaction_pool.clone(); - - let justification_stream = grandpa_link.justification_stream(); - let shared_authority_set = grandpa_link.shared_authority_set().clone(); - let shared_voter_state = shared_voter_state.clone(); - - let finality_proof_provider = GrandpaFinalityProofProvider::new_for_service( - backend.clone(), - Some(shared_authority_set.clone()), - ); - - Box::new(move |_, subscription_executor: sc_rpc::SubscriptionTaskExecutor| { - let mut io = RpcModule::new(()); - let map_err = |e| sc_service::Error::Other(format!("{e}")); - io.merge(System::new(client.clone(), pool.clone(), DenyUnsafe::No).into_rpc()) - .map_err(map_err)?; - io.merge(TransactionPayment::new(client.clone()).into_rpc()).map_err(map_err)?; - io.merge( - Grandpa::new( - subscription_executor.clone(), - shared_authority_set.clone(), - shared_voter_state.clone(), - justification_stream.clone(), - finality_proof_provider.clone(), - ) - .into_rpc(), - ) - .map_err(map_err)?; - io.merge( - Beefy::::new( - beefy_rpc_links.from_voter_justif_stream.clone(), - beefy_rpc_links.from_voter_best_beefy_stream.clone(), - subscription_executor, - ) - .map_err(|e| sc_service::Error::Other(format!("{e}")))? - .into_rpc(), - ) - .map_err(map_err)?; - io.merge( - Mmr::new( - client.clone(), - backend - .offchain_storage() - .ok_or("Backend doesn't provide the required offchain storage")?, - ) - .into_rpc(), - ) - .map_err(map_err)?; - Ok(io) - }) - }; - - let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { - network: network.clone(), - client: client.clone(), - keystore: keystore_container.keystore(), - task_manager: &mut task_manager, - transaction_pool: transaction_pool.clone(), - sync_service: sync_service.clone(), - rpc_builder: rpc_extensions_builder, - backend: backend.clone(), - system_rpc_tx, - config, - tx_handler_controller, - telemetry: telemetry.as_mut(), - })?; - - if role.is_authority() { - let proposer_factory = sc_basic_authorship::ProposerFactory::new( - task_manager.spawn_handle(), - client.clone(), - transaction_pool.clone(), - prometheus_registry.as_ref(), - telemetry.as_ref().map(|x| x.handle()), - ); - - let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - - let aura = sc_consensus_aura::start_aura::( - StartAuraParams { - slot_duration, - client: client.clone(), - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.keystore(), - sync_oracle: sync_service.clone(), - justification_sync_link: sync_service.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: CompatibilityMode::None, - }, - )?; - - // the AURA authoring task is considered essential, i.e. if it - // fails we take down the service with it. - task_manager - .spawn_essential_handle() - .spawn_blocking("aura", Some("block-authoring"), aura); - } - - // if the node isn't actively participating in consensus then it doesn't - // need a keystore, regardless of which protocol we use below. - let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; - - let justifications_protocol_name = beefy_on_demand_justifications_handler.protocol_name(); - let payload_provider = sp_consensus_beefy::mmr::MmrRootProvider::new(client.clone()); - let beefy_params = sc_consensus_beefy::BeefyParams { - client: client.clone(), - backend, - payload_provider, - runtime: client, - key_store: keystore.clone(), - network_params: sc_consensus_beefy::BeefyNetworkParams { - network: network.clone(), - sync: sync_service.clone(), - gossip_protocol_name: beefy_gossip_proto_name, - justifications_protocol_name, - _phantom: core::marker::PhantomData::, - }, - min_block_delta: 2, - prometheus_registry: prometheus_registry.clone(), - links: beefy_voter_links, - on_demand_justifications_handler: beefy_on_demand_justifications_handler, - }; - - // Start the BEEFY bridge gadget. - task_manager.spawn_essential_handle().spawn_blocking( - "beefy-gadget", - None, - sc_consensus_beefy::start_beefy_gadget::<_, _, _, _, _, _, _>(beefy_params), - ); - - let grandpa_config = sc_consensus_grandpa::Config { - // FIXME #1578 make this available through chainspec - gossip_duration: Duration::from_millis(333), - justification_generation_period: 512, - name: Some(name), - observer_enabled: false, - keystore, - local_role: role, - telemetry: telemetry.as_ref().map(|x| x.handle()), - protocol_name: grandpa_protocol_name, - }; - - if enable_grandpa { - // start the full GRANDPA voter - // NOTE: non-authorities could run the GRANDPA observer protocol, but at - // this point the full voter should provide better guarantees of block - // and vote data availability than the observer. The observer has not - // been tested extensively yet and having most nodes in a network run it - // could lead to finality stalls. - let grandpa_config = sc_consensus_grandpa::GrandpaParams { - config: grandpa_config, - link: grandpa_link, - network, - sync: sync_service, - voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), - prometheus_registry, - shared_voter_state, - telemetry: telemetry.as_ref().map(|x| x.handle()), - offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool), - }; - - // the GRANDPA voter task is considered infallible, i.e. - // if it fails we take down the service with it. - task_manager.spawn_essential_handle().spawn_blocking( - "grandpa-voter", - None, - sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, - ); - } - - network_starter.start_network(); - Ok(task_manager) -} diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml deleted file mode 100644 index 7e963d6b74d0b..0000000000000 --- a/bin/millau/runtime/Cargo.toml +++ /dev/null @@ -1,155 +0,0 @@ -[package] -name = "millau-runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -repository = "https://github.com/paritytech/parity-bridges-common/" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -hex-literal = "0.4" -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Bridge dependencies - -bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } -bp-messages = { path = "../../../primitives/messages", default-features = false } -bp-millau = { path = "../../../primitives/chain-millau", default-features = false } -bp-parachains = { path = "../../../primitives/parachains", default-features = false } -bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } -bp-relayers = { path = "../../../primitives/relayers", default-features = false } -bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } -bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } -bp-runtime = { path = "../../../primitives/runtime", default-features = false } -bp-westend = { path = "../../../primitives/chain-westend", default-features = false } -bp-xcm-bridge-hub-router = { path = "../../../primitives/xcm-bridge-hub-router", default-features = false } -bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } -pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } -pallet-bridge-parachains = { path = "../../../modules/parachains", default-features = false } -pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } -pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } -pallet-xcm-bridge-hub-router = { path = "../../../modules/xcm-bridge-hub-router", default-features = false } - -# Substrate Dependencies - -sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-offences = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["historical"]} -pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-utility = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Polkadot Dependencies -pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[dev-dependencies] -bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test", "std"] } -env_logger = "0.10" -static_assertions = "1.1" - -[build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[features] -default = [ "std" ] -std = [ - "bp-messages/std", - "bp-millau/std", - "bp-parachains/std", - "bp-polkadot-core/std", - "bp-relayers/std", - "bp-rialto-parachain/std", - "bp-rialto/std", - "bp-runtime/std", - "bp-westend/std", - "bp-xcm-bridge-hub-router/std", - "bridge-runtime-common/std", - "codec/std", - "frame-executive/std", - "frame-support/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "pallet-aura/std", - "pallet-authorship/std", - "pallet-balances/std", - "pallet-beefy-mmr/std", - "pallet-beefy/std", - "pallet-bridge-grandpa/std", - "pallet-bridge-messages/std", - "pallet-bridge-parachains/std", - "pallet-bridge-relayers/std", - "pallet-grandpa/std", - "pallet-mmr/std", - "pallet-offences/std", - "pallet-session/std", - "pallet-shift-session-manager/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-utility/std", - "pallet-xcm-bridge-hub-router/std", - "pallet-xcm/std", - "scale-info/std", - "sp-api/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-consensus-beefy/std", - "sp-core/std", - "sp-inherents/std", - "sp-io/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-transaction-pool/std", - "sp-version/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] -runtime-benchmarks = [ - "bridge-runtime-common/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-bridge-grandpa/runtime-benchmarks", - "pallet-bridge-messages/runtime-benchmarks", - "pallet-bridge-parachains/runtime-benchmarks", - "pallet-bridge-relayers/runtime-benchmarks", - "pallet-xcm-bridge-hub-router/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", -] diff --git a/bin/millau/runtime/build.rs b/bin/millau/runtime/build.rs deleted file mode 100644 index 25e220e46fc3b..0000000000000 --- a/bin/millau/runtime/build.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 . - -use substrate_wasm_builder::WasmBuilder; - -fn main() { - WasmBuilder::new() - .with_current_project() - .import_memory() - .export_heap_base() - .disable_runtime_version_section_check() - .build() -} diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs deleted file mode 100644 index a349551a873c0..0000000000000 --- a/bin/millau/runtime/src/lib.rs +++ /dev/null @@ -1,1300 +0,0 @@ -// 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 . - -//! The Millau runtime. This can be compiled with `#[no_std]`, ready for Wasm. - -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] -// Runtime-generated enums -#![allow(clippy::large_enum_variant)] -// From construct_runtime macro -#![allow(clippy::from_over_into)] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -pub mod rialto_messages; -pub mod rialto_parachain_messages; -pub mod weights; -pub mod xcm_config; - -use bp_parachains::SingleParaStoredHeaderDataBuilder; -#[cfg(feature = "runtime-benchmarks")] -use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; -use bp_runtime::HeaderId; -use pallet_grandpa::{ - fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, -}; -use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; -use sp_api::impl_runtime_apis; -use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_consensus_beefy::{ecdsa_crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; -use sp_core::OpaqueMetadata; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys}, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, KeyTypeId, Perquintill, -}; -use sp_std::prelude::*; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; -use xcm_builder::{NetworkExportTable, NetworkExportTableItem}; - -// to be able to use Millau runtime in `bridge-runtime-common` tests -pub use bridge_runtime_common; - -// A few exports that help ease life for downstream crates. -pub use frame_support::{ - construct_runtime, - dispatch::DispatchClass, - parameter_types, - traits::{ - ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, - Imbalance, KeyOwnerProofSystem, - }, - weights::{ - constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, RuntimeDbWeight, - Weight, - }, - StorageValue, -}; - -pub use frame_system::Call as SystemCall; -pub use pallet_balances::Call as BalancesCall; -pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; -pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_bridge_parachains::Call as BridgeParachainsCall; -pub use pallet_sudo::Call as SudoCall; -pub use pallet_timestamp::Call as TimestampCall; -pub use pallet_xcm::Call as XcmCall; - -use bridge_runtime_common::{ - generate_bridge_reject_obsolete_headers_and_messages, - refund_relayer_extension::{ - ActualFeeRefund, RefundBridgedParachainMessages, RefundSignedExtensionAdapter, - RefundableMessagesLane, RefundableParachain, - }, -}; -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use sp_runtime::{Perbill, Permill}; - -/// An index to a block. -pub type BlockNumber = bp_millau::BlockNumber; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = bp_millau::Signature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = bp_millau::AccountId; - -/// The type for looking up accounts. We don't expect more than 4 billion of them, but you -/// never know... -pub type AccountIndex = u32; - -/// Balance of an account. -pub type Balance = bp_millau::Balance; - -/// Nonce of a transaction in the chain. -pub type Nonce = bp_millau::Nonce; - -/// A hash of some data used by the chain. -pub type Hash = bp_millau::Hash; - -/// Hashing algorithm used by the chain. -pub type Hashing = bp_millau::Hasher; - -/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know -/// the specifics of the runtime. They can then be made to be agnostic over specific formats -/// of data like extrinsics, allowing for them to continue syncing the network through upgrades -/// to even the core data structures. -pub mod opaque { - use super::*; - - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; - - /// Opaque block header type. - pub type Header = generic::Header; - /// Opaque block type. - pub type Block = generic::Block; - /// Opaque block identifier type. - pub type BlockId = generic::BlockId; -} - -impl_opaque_keys! { - pub struct SessionKeys { - pub aura: Aura, - pub beefy: Beefy, - pub grandpa: Grandpa, - } -} - -/// This runtime version. -#[sp_version::runtime_version] -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("millau-runtime"), - impl_name: create_runtime_str!("millau-runtime"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, - state_version: 0, -}; - -/// The version information used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } -} - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const Version: RuntimeVersion = VERSION; - pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 60_000_000, // ~0.06 ms = ~60 µs - write: 200_000_000, // ~0.2 ms = 200 µs - }; - pub const SS58Prefix: u8 = 60; -} - -impl frame_system::Config for Runtime { - /// The basic call filter to use in dispatchable. - type BaseCallFilter = frame_support::traits::Everything; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = IdentityLookup; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = Hashing; - /// The header type. - type Block = Block; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Version of the runtime. - type Version = Version; - /// Provides information about the pallet setup in the runtime. - type PalletInfo = PalletInfo; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block and extrinsics weights: base values and limits. - type BlockWeights = bp_millau::BlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = bp_millau::BlockLength; - /// The weight of database operations that the runtime can invoke. - type DbWeight = DbWeight; - /// The designated SS58 prefix of this chain. - type SS58Prefix = SS58Prefix; - /// The set code logic, just the default since we're not a parachain. - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type MaxAuthorities = ConstU32<10>; - type DisabledValidators = (); - type AllowMultipleBlocksPerSlot = ConstBool; -} - -impl pallet_beefy::Config for Runtime { - type BeefyId = BeefyId; - type MaxAuthorities = ConstU32<10>; - type MaxSetIdSessionEntries = ConstU64<0>; - type OnNewValidatorSet = MmrLeaf; - type WeightInfo = (); - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); - type MaxNominators = ConstU32<256>; -} - -impl pallet_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); - type MaxAuthorities = ConstU32<10>; - type MaxSetIdSessionEntries = ConstU64<0>; - type KeyOwnerProof = >::Proof; - type EquivocationReportSystem = - pallet_grandpa::EquivocationReportSystem; - type MaxNominators = ConstU32<256>; -} - -/// MMR helper types. -mod mmr { - use super::Runtime; - pub use pallet_mmr::primitives::*; - - pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; - pub type Hashing = ::Hashing; - pub type Hash = ::Output; -} - -impl pallet_mmr::Config for Runtime { - const INDEXING_PREFIX: &'static [u8] = b"mmr"; - type Hashing = Keccak256; - type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; - type WeightInfo = (); - type LeafData = pallet_beefy_mmr::Pallet; -} - -parameter_types! { - /// Version of the produced MMR leaf. - /// - /// The version consists of two parts; - /// - `major` (3 bits) - /// - `minor` (5 bits) - /// - /// `major` should be updated only if decoding the previous MMR Leaf format from the payload - /// is not possible (i.e. backward incompatible change). - /// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE - /// encoding does not prevent old leafs from being decoded. - /// - /// Hence we expect `major` to be changed really rarely (think never). - /// See [`MmrLeafVersion`] type documentation for more details. - pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0); -} - -pub struct BeefyDummyDataProvider; - -impl sp_consensus_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { - fn extra_data() {} -} - -impl pallet_beefy_mmr::Config for Runtime { - type LeafVersion = LeafVersion; - type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; - type LeafExtra = (); - type BeefyDataProvider = BeefyDummyDataProvider; -} - -parameter_types! { - pub const MinimumPeriod: u64 = bp_millau::SLOT_DURATION / 2; -} - -impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the UNIX epoch. - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: bp_millau::Balance = 500; -} - -impl pallet_balances::Config for Runtime { - /// The type for recording an account's balance. - type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); - // For weight estimation, we assume that the most locks on an individual account will be 50. - // This number may need to be adjusted in the future if this assumption no longer holds true. - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; -} - -parameter_types! { - pub const TransactionBaseFee: Balance = 0; - pub const TransactionByteFee: Balance = 1; - // values for following parameters are copied from polkadot repo, but it is fine - // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains - pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); - pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); - pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); - pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); -} - -impl pallet_transaction_payment::Config for Runtime { - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = bp_millau::WeightToFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< - Runtime, - TargetBlockFullness, - AdjustmentVariable, - MinimumMultiplier, - MaximumMultiplier, - >; - type RuntimeEvent = RuntimeEvent; -} - -impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type WeightInfo = pallet_sudo::weights::SubstrateWeight; -} - -parameter_types! { - /// Authorities are changing every 5 minutes. - pub const Period: BlockNumber = bp_millau::SESSION_LENGTH; - pub const Offset: BlockNumber = 0; - pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; - pub ReportLongevity: u64 = Period::get() * 10; -} - -impl pallet_session::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ValidatorId = ::AccountId; - type ValidatorIdOf = (); - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = pallet_shift_session_manager::Pallet; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); -} - -impl frame_system::offchain::SendTransactionTypes for Runtime -where - RuntimeCall: From, -{ - type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; -} - -impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (); -} - -pub struct FullIdentificationOf; -impl sp_runtime::traits::Convert> for FullIdentificationOf { - fn convert(_: AccountId) -> Option<()> { - Some(()) - } -} - -impl pallet_session::historical::Config for Runtime { - type FullIdentification = (); - type FullIdentificationOf = FullIdentificationOf; -} - -impl pallet_offences::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type IdentificationTuple = pallet_session::historical::IdentificationTuple; - type OnOffenceHandler = (); -} - -impl pallet_bridge_relayers::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Reward = Balance; - type PaymentProcedure = - bp_relayers::PayRewardFromAccount, AccountId>; - type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< - AccountId, - BlockNumber, - Balances, - RelayerStakeReserveId, - ConstU64<1_000>, - ConstU64<8>, - >; - type WeightInfo = (); -} - -pub type RialtoGrandpaInstance = (); -impl pallet_bridge_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BridgedChain = bp_rialto::Rialto; - type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; - type HeadersToKeep = ConstU32<{ bp_rialto::DAYS }>; - type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; -} - -pub type WestendGrandpaInstance = pallet_bridge_grandpa::Instance1; -impl pallet_bridge_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BridgedChain = bp_westend::Westend; - type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; - type HeadersToKeep = ConstU32<{ bp_westend::DAYS }>; - type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; -} - -impl pallet_shift_session_manager::Config for Runtime {} - -parameter_types! { - pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; - pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - pub const RootAccountForPayments: Option = None; - pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; - pub const RialtoParachainChainId: bp_runtime::ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; - pub RialtoActiveOutboundLanes: &'static [bp_messages::LaneId] = &[rialto_messages::XCM_LANE]; - pub RialtoParachainActiveOutboundLanes: &'static [bp_messages::LaneId] = &[rialto_parachain_messages::XCM_LANE]; -} - -/// Instance of the messages pallet used to relay messages to/from Rialto chain. -pub type WithRialtoMessagesInstance = (); - -impl pallet_bridge_messages::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::RialtoMessagesWeightInfo; - type ActiveOutboundLanes = RialtoActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; - type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - - type MaximalOutboundPayloadSize = crate::rialto_messages::ToRialtoMaximalOutboundPayloadSize; - type OutboundPayload = crate::rialto_messages::ToRialtoMessagePayload; - - type InboundPayload = crate::rialto_messages::FromRialtoMessagePayload; - type InboundRelayer = bp_rialto::AccountId; - type DeliveryPayments = (); - - type TargetHeaderChain = crate::rialto_messages::RialtoAsTargetHeaderChain; - type LaneMessageVerifier = crate::rialto_messages::ToRialtoMessageVerifier; - type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - WithRialtoMessagesInstance, - frame_support::traits::ConstU64<100_000>, - >; - type OnMessagesDelivered = (); - - type SourceHeaderChain = crate::rialto_messages::RialtoAsSourceHeaderChain; - type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; - type BridgedChainId = RialtoChainId; -} - -/// Instance of the messages pallet used to relay messages to/from RialtoParachain chain. -pub type WithRialtoParachainMessagesInstance = pallet_bridge_messages::Instance1; - -impl pallet_bridge_messages::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::RialtoParachainMessagesWeightInfo; - type ActiveOutboundLanes = RialtoParachainActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; - type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - - type MaximalOutboundPayloadSize = - crate::rialto_parachain_messages::ToRialtoParachainMaximalOutboundPayloadSize; - type OutboundPayload = crate::rialto_parachain_messages::ToRialtoParachainMessagePayload; - - type InboundPayload = crate::rialto_parachain_messages::FromRialtoParachainMessagePayload; - type InboundRelayer = bp_rialto_parachain::AccountId; - type DeliveryPayments = (); - - type TargetHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsTargetHeaderChain; - type LaneMessageVerifier = crate::rialto_parachain_messages::ToRialtoParachainMessageVerifier; - type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - WithRialtoParachainMessagesInstance, - frame_support::traits::ConstU64<100_000>, - >; - type OnMessagesDelivered = (); - - type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsSourceHeaderChain; - type MessageDispatch = crate::rialto_parachain_messages::FromRialtoParachainMessageDispatch; - type BridgedChainId = RialtoParachainChainId; -} - -parameter_types! { - pub const RialtoParachainMessagesLane: bp_messages::LaneId = rialto_parachain_messages::XCM_LANE; - pub const RialtoParasPalletName: &'static str = bp_rialto::PARAS_PALLET_NAME; - pub const WestendParasPalletName: &'static str = bp_westend::PARAS_PALLET_NAME; - pub const MaxRialtoParaHeadDataSize: u32 = bp_rialto::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; - pub const MaxWestendParaHeadDataSize: u32 = bp_westend::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; -} - -/// Instance of the with-Rialto parachains pallet. -pub type WithRialtoParachainsInstance = (); - -impl pallet_bridge_parachains::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; - type BridgesGrandpaPalletInstance = RialtoGrandpaInstance; - type ParasPalletName = RialtoParasPalletName; - type ParaStoredHeaderDataBuilder = - SingleParaStoredHeaderDataBuilder; - type HeadsToKeep = ConstU32<1024>; - type MaxParaHeadDataSize = MaxRialtoParaHeadDataSize; -} - -/// Instance of the with-Westend parachains pallet. -pub type WithWestendParachainsInstance = pallet_bridge_parachains::Instance1; - -impl pallet_bridge_parachains::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_bridge_parachains::weights::BridgeWeight; - type BridgesGrandpaPalletInstance = WestendGrandpaInstance; - type ParasPalletName = WestendParasPalletName; - type ParaStoredHeaderDataBuilder = - SingleParaStoredHeaderDataBuilder; - type HeadsToKeep = ConstU32<1024>; - type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; -} - -impl pallet_utility::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type PalletsOrigin = OriginCaller; - type WeightInfo = (); -} - -// this config is totally incorrect - the pallet is not actually used at this runtime. We need -// it only to be able to run benchmarks and make required traits (and default weights for tests). -parameter_types! { - pub BridgeTable: Vec - = vec![ - NetworkExportTableItem::new( - xcm_config::RialtoNetwork::get(), - None, - xcm_config::TokenLocation::get(), - Some((xcm_config::TokenAssetId::get(), 1_000_000_000_u128).into()) - ) - ]; -} -impl pallet_xcm_bridge_hub_router::Config for Runtime { - type WeightInfo = (); - - type UniversalLocation = xcm_config::UniversalLocation; - type BridgedNetworkId = xcm_config::RialtoNetwork; - type Bridges = NetworkExportTable; - - type BridgeHubOrigin = frame_system::EnsureRoot; - type ToBridgeHubSender = xcm_config::XcmRouter; - type WithBridgeHubChannel = xcm_config::EmulatedSiblingXcmpChannel; - - type ByteFee = ConstU128<1_000>; - type FeeAsset = xcm_config::TokenAssetId; -} - -construct_runtime!( - pub enum Runtime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - Utility: pallet_utility, - - // Must be before session. - Aura: pallet_aura::{Pallet, Config}, - - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, - - // Consensus support. - Authorship: pallet_authorship::{Pallet, Storage}, - Offences: pallet_offences::{Pallet, Storage, Event}, - Historical: pallet_session::historical::{Pallet}, - - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, - ShiftSessionManager: pallet_shift_session_manager::{Pallet}, - - // BEEFY Bridges support. - Beefy: pallet_beefy::{Pallet, Storage, Config}, - Mmr: pallet_mmr::{Pallet, Storage}, - MmrLeaf: pallet_beefy_mmr::{Pallet, Storage}, - - // Rialto bridge modules. - BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, - BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - - // Westend bridge modules. - BridgeWestendGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Config, Storage, Event}, - BridgeWestendParachains: pallet_bridge_parachains::::{Pallet, Call, Storage, Event}, - - // RialtoParachain bridge modules. - BridgeRialtoParachains: pallet_bridge_parachains::{Pallet, Call, Storage, Event}, - BridgeRialtoParachainMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config}, - - // Pallet for sending XCM. - XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, - - // Pallets that are not actually used here (yet?), but we need to run benchmarks on it. - XcmBridgeHubRouter: pallet_xcm_bridge_hub_router::{Pallet, Storage} = 200, - } -); - -generate_bridge_reject_obsolete_headers_and_messages! { - RuntimeCall, AccountId, - // Grandpa - BridgeRialtoGrandpa, BridgeWestendGrandpa, - // Parachains - BridgeRialtoParachains, - //Messages - BridgeRialtoMessages, BridgeRialtoParachainMessages -} - -bp_runtime::generate_static_str_provider!(BridgeRefundRialtoPara2000Lane0Msgs); -/// Signed extension that refunds relayers that are delivering messages from the Rialto parachain. -pub type PriorityBoostPerMessage = ConstU64<324_316_715>; -pub type BridgeRefundRialtoParachainMessages = RefundSignedExtensionAdapter< - RefundBridgedParachainMessages< - Runtime, - RefundableParachain, - RefundableMessagesLane, - ActualFeeRefund, - PriorityBoostPerMessage, - StrBridgeRefundRialtoPara2000Lane0Msgs, - >, ->; - -/// The address format for describing accounts. -pub type Address = AccountId; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - BridgeRejectObsoleteHeadersAndMessages, - BridgeRefundRialtoParachainMessages, -); -/// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; -/// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; -/// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; - -#[cfg(feature = "runtime-benchmarks")] -mod benches { - frame_benchmarking::define_benchmarks!( - [pallet_bridge_messages, MessagesBench::] - [pallet_bridge_messages, MessagesBench::] - [pallet_bridge_grandpa, BridgeRialtoGrandpa] - [pallet_bridge_parachains, ParachainsBench::] - [pallet_bridge_relayers, RelayersBench::] - [pallet_xcm_bridge_hub_router, XcmBridgeHubRouterBench::] - ); -} - -impl_runtime_apis! { - impl sp_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block); - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl sp_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Runtime::metadata().into()) - } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } - } - - impl sp_block_builder::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { - Executive::apply_extrinsic(extrinsic) - } - - fn finalize_block() -> ::Header { - Executive::finalize_block() - } - - fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents( - block: Block, - data: sp_inherents::InherentData, - ) -> sp_inherents::CheckInherentsResult { - data.check_extrinsics(&block) - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Nonce { - System::account_nonce(account) - } - } - - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction( - source: TransactionSource, - tx: ::Extrinsic, - block_hash: ::Hash, - ) -> TransactionValidity { - Executive::validate_transaction(source, tx, block_hash) - } - } - - impl sp_offchain::OffchainWorkerApi for Runtime { - fn offchain_worker(header: &::Header) { - Executive::offchain_worker(header) - } - } - - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) - } - - fn authorities() -> Vec { - Aura::authorities().to_vec() - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< - Block, - Balance, - > for Runtime { - fn query_info(uxt: ::Extrinsic, len: u32) -> RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { - TransactionPayment::query_fee_details(uxt, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - SessionKeys::generate(seed) - } - - fn decode_session_keys( - encoded: Vec, - ) -> Option, sp_core::crypto::KeyTypeId)>> { - SessionKeys::decode_into_raw_public_keys(&encoded) - } - } - - impl sp_consensus_beefy::BeefyApi for Runtime { - fn beefy_genesis() -> Option { - Beefy::genesis_block() - } - - fn validator_set() -> Option> { - Beefy::validator_set() - } - - fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: sp_consensus_beefy::EquivocationProof< - NumberFor, - sp_consensus_beefy::ecdsa_crypto::AuthorityId, - sp_consensus_beefy::ecdsa_crypto::Signature - >, - _key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof, - ) -> Option<()> { None } - - fn generate_key_ownership_proof( - _set_id: sp_consensus_beefy::ValidatorSetId, - _authority_id: sp_consensus_beefy::ecdsa_crypto::AuthorityId, - ) -> Option { None } - } - - impl pallet_mmr::primitives::MmrApi< - Block, - mmr::Hash, - BlockNumber, - > for Runtime { - fn mmr_root() -> Result { - Ok(Mmr::mmr_root()) - } - - fn mmr_leaf_count() -> Result { - Ok(Mmr::mmr_leaves()) - } - - fn generate_proof( - block_numbers: Vec, - best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { - Mmr::generate_proof(block_numbers, best_known_block_number).map( - |(leaves, proof)| { - ( - leaves - .into_iter() - .map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)) - .collect(), - proof, - ) - }, - ) - } - - fn verify_proof(leaves: Vec, proof: mmr::Proof) - -> Result<(), mmr::Error> - { - let leaves = leaves.into_iter().map(|leaf| - leaf.into_opaque_leaf() - .try_decode() - .ok_or(mmr::Error::Verify)).collect::, mmr::Error>>()?; - Mmr::verify_leaves(leaves, proof) - } - - fn verify_proof_stateless( - root: mmr::Hash, - leaves: Vec, - proof: mmr::Proof - ) -> Result<(), mmr::Error> { - let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); - pallet_mmr::verify_leaves_proof::(root, nodes, proof) - } - } - - impl fg_primitives::GrandpaApi for Runtime { - fn current_set_id() -> fg_primitives::SetId { - Grandpa::current_set_id() - } - - fn grandpa_authorities() -> GrandpaAuthorityList { - Grandpa::grandpa_authorities() - } - - fn submit_report_equivocation_unsigned_extrinsic( - equivocation_proof: fg_primitives::EquivocationProof< - ::Hash, - NumberFor, - >, - key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, - ) -> Option<()> { - let key_owner_proof = key_owner_proof.decode()?; - - Grandpa::submit_unsigned_equivocation_report( - equivocation_proof, - key_owner_proof, - ) - } - - fn generate_key_ownership_proof( - _set_id: fg_primitives::SetId, - _authority_id: GrandpaId, - ) -> Option { - // NOTE: this is the only implementation possible since we've - // defined our key owner proof type as a bottom type (i.e. a type - // with no values). - None - } - } - - impl bp_rialto::RialtoFinalityApi for Runtime { - fn best_finalized() -> Option> { - BridgeRialtoGrandpa::best_finalized() - } - - fn synced_headers_grandpa_info( - ) -> Vec> { - BridgeRialtoGrandpa::synced_headers_grandpa_info() - } - } - - impl bp_westend::WestendFinalityApi for Runtime { - fn best_finalized() -> Option> { - BridgeWestendGrandpa::best_finalized() - } - - fn synced_headers_grandpa_info( - ) -> Vec> { - BridgeWestendGrandpa::synced_headers_grandpa_info() - } - } - - impl bp_bridged_chain::AssetHubWestendFinalityApi for Runtime { - fn best_finalized() -> Option> { - pallet_bridge_parachains::Pallet::< - Runtime, - WithWestendParachainsInstance, - >::best_parachain_head_id::().unwrap_or(None) - } - } - - impl bp_rialto_parachain::RialtoParachainFinalityApi for Runtime { - fn best_finalized() -> Option> { - pallet_bridge_parachains::Pallet::< - Runtime, - WithRialtoParachainsInstance, - >::best_parachain_head_id::().unwrap_or(None) - } - } - - impl bp_rialto::ToRialtoOutboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - begin: bp_messages::MessageNonce, - end: bp_messages::MessageNonce, - ) -> Vec { - bridge_runtime_common::messages_api::outbound_message_details::< - Runtime, - WithRialtoMessagesInstance, - >(lane, begin, end) - } - } - - impl bp_rialto::FromRialtoInboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, - ) -> Vec { - bridge_runtime_common::messages_api::inbound_message_details::< - Runtime, - WithRialtoMessagesInstance, - >(lane, messages) - } - } - - impl bp_rialto_parachain::ToRialtoParachainOutboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - begin: bp_messages::MessageNonce, - end: bp_messages::MessageNonce, - ) -> Vec { - bridge_runtime_common::messages_api::outbound_message_details::< - Runtime, - WithRialtoParachainMessagesInstance, - >(lane, begin, end) - } - } - - impl bp_rialto_parachain::FromRialtoParachainInboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, - ) -> Vec { - bridge_runtime_common::messages_api::inbound_message_details::< - Runtime, - WithRialtoParachainMessagesInstance, - >(lane, messages) - } - } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn benchmark_metadata(extra: bool) -> ( - Vec, - Vec, - ) { - use frame_benchmarking::{Benchmarking, BenchmarkList}; - use frame_support::traits::StorageInfoTrait; - - use pallet_bridge_messages::benchmarking::Pallet as MessagesBench; - use pallet_bridge_parachains::benchmarking::Pallet as ParachainsBench; - use pallet_bridge_relayers::benchmarking::Pallet as RelayersBench; - use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; - - let mut list = Vec::::new(); - list_benchmarks!(list, extra); - - let storage_info = AllPalletsWithSystem::storage_info(); - return (list, storage_info) - } - - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig, - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch}; - use frame_support::traits::TrackedStorageKey; - - let whitelist: Vec = vec![ - // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), - // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), - // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), - // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), - // Caller 0 Account - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da946c154ffd9992e395af90b5b13cc6f295c77033fce8a9045824a6690bbf99c6db269502f0a8d1d2a008542d5690a0749").to_vec().into(), - ]; - - use bridge_runtime_common::messages_benchmarking::{ - generate_xcm_builder_bridge_message_sample, - prepare_message_delivery_proof_from_grandpa_chain, - prepare_message_delivery_proof_from_parachain, - prepare_message_proof_from_grandpa_chain, - prepare_message_proof_from_parachain, - }; - use pallet_bridge_messages::benchmarking::{ - Pallet as MessagesBench, - Config as MessagesConfig, - MessageDeliveryProofParams, - MessageProofParams, - }; - use pallet_bridge_parachains::benchmarking::{ - Pallet as ParachainsBench, - Config as ParachainsConfig, - }; - use pallet_bridge_relayers::benchmarking::{ - Pallet as RelayersBench, - Config as RelayersConfig, - }; - use pallet_xcm_bridge_hub_router::benchmarking::{ - Pallet as XcmBridgeHubRouterBench, - Config as XcmBridgeHubRouterConfig, - }; - use rialto_messages::WithRialtoMessageBridge; - use rialto_parachain_messages::WithRialtoParachainMessageBridge; - - impl MessagesConfig for Runtime { - fn prepare_message_proof( - params: MessageProofParams, - ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { - prepare_message_proof_from_parachain::< - Runtime, - WithRialtoParachainsInstance, - WithRialtoParachainMessageBridge, - >(params, generate_xcm_builder_bridge_message_sample(xcm::v3::Junctions::Here)) - } - - fn prepare_message_delivery_proof( - params: MessageDeliveryProofParams, - ) -> rialto_messages::ToRialtoMessagesDeliveryProof { - prepare_message_delivery_proof_from_parachain::< - Runtime, - WithRialtoParachainsInstance, - WithRialtoParachainMessageBridge, - >(params) - } - - fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - let lane = >::bench_lane_id(); - let bridged_chain_id = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; - pallet_bridge_relayers::Pallet::::relayer_reward( - relayer, - RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) - ).is_some() - } - } - - impl MessagesConfig for Runtime { - fn prepare_message_proof( - params: MessageProofParams, - ) -> (rialto_messages::FromRialtoMessagesProof, Weight) { - prepare_message_proof_from_grandpa_chain::< - Runtime, - RialtoGrandpaInstance, - WithRialtoMessageBridge, - >(params, generate_xcm_builder_bridge_message_sample(xcm::v3::Junctions::Here)) - } - - fn prepare_message_delivery_proof( - params: MessageDeliveryProofParams, - ) -> rialto_messages::ToRialtoMessagesDeliveryProof { - prepare_message_delivery_proof_from_grandpa_chain::< - Runtime, - RialtoGrandpaInstance, - WithRialtoMessageBridge, - >(params) - } - - fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { - let lane = >::bench_lane_id(); - let bridged_chain_id = bp_runtime::RIALTO_CHAIN_ID; - pallet_bridge_relayers::Pallet::::relayer_reward( - relayer, - RewardsAccountParams::new(lane, bridged_chain_id, RewardsAccountOwner::BridgedChain) - ).is_some() - } - } - - impl ParachainsConfig for Runtime { - fn parachains() -> Vec { - use bp_runtime::Parachain; - vec![bp_polkadot_core::parachains::ParaId(bp_rialto_parachain::RialtoParachain::PARACHAIN_ID)] - } - - fn prepare_parachain_heads_proof( - parachains: &[bp_polkadot_core::parachains::ParaId], - parachain_head_size: u32, - proof_size: bp_runtime::StorageProofSize, - ) -> ( - pallet_bridge_parachains::RelayBlockNumber, - pallet_bridge_parachains::RelayBlockHash, - bp_polkadot_core::parachains::ParaHeadsProof, - Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, - ) { - bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof::< - Runtime, - WithRialtoParachainsInstance, - >( - parachains, - parachain_head_size, - proof_size, - ) - } - } - - impl RelayersConfig for Runtime { - fn prepare_rewards_account( - account_params: RewardsAccountParams, - reward: Balance, - ) { - let rewards_account = bp_relayers::PayRewardFromAccount::< - Balances, - AccountId - >::rewards_account(account_params); - Self::deposit_account(rewards_account, reward); - } - - fn deposit_account(account: AccountId, balance: Balance) { - use frame_support::traits::fungible::Mutate; - Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); - } - } - - impl XcmBridgeHubRouterConfig<()> for Runtime { - fn make_congested() { - xcm_config::EmulatedSiblingXcmpChannel::make_congested() - } - } - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - - add_benchmarks!(params, batches); - - Ok(batches) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn call_size() { - const BRIDGES_PALLETS_MAX_CALL_SIZE: usize = 200; - assert!( - core::mem::size_of::>() <= - BRIDGES_PALLETS_MAX_CALL_SIZE - ); - assert!( - core::mem::size_of::>() <= - BRIDGES_PALLETS_MAX_CALL_SIZE - ); - const MAX_CALL_SIZE: usize = 230; // value from polkadot-runtime tests - assert!(core::mem::size_of::() <= MAX_CALL_SIZE); - } -} - -/// TODO: Note: I know this does not belong here, but I don't want to add it to the -/// `chain-asset-hub-westend` or `chain-westend`, because we wont use it for production and I don't -/// want to bring this to the bridges subtree now. Anyway, we plan to retire millau/rialto, so this -/// hack will disappear with that. -pub mod bp_bridged_chain { - use bp_messages::Weight; - pub use bp_polkadot_core::{ - AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, - Hasher, Hashing, Header, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, - EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, - }; - use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; - - /// `AssetHubWestend` parachain definition - #[derive(Debug, Clone, Copy)] - pub struct AssetHubWestend; - - // AssetHubWestend seems to use the same configuration as all Polkadot-like chains, so we'll use - // Westend primitives here. - impl Chain for AssetHubWestend { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - bp_westend::Westend::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_westend::Westend::max_extrinsic_weight() - } - } - - impl Parachain for AssetHubWestend { - const PARACHAIN_ID: u32 = 1000; - } - - decl_bridge_finality_runtime_apis!(AssetHubWestend); -} diff --git a/bin/millau/runtime/src/rialto_messages.rs b/bin/millau/runtime/src/rialto_messages.rs deleted file mode 100644 index 8b778600f9723..0000000000000 --- a/bin/millau/runtime/src/rialto_messages.rs +++ /dev/null @@ -1,216 +0,0 @@ -// 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 . - -//! Everything required to serve Millau <-> Rialto messages. - -use crate::{RialtoGrandpaInstance, Runtime, RuntimeOrigin, WithRialtoMessagesInstance}; - -use bp_messages::LaneId; -use bridge_runtime_common::{ - messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, - }, - messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, -}; -use frame_support::{parameter_types, weights::Weight}; -use pallet_bridge_relayers::WeightInfoExt as _; -use sp_runtime::RuntimeDebug; -use xcm::latest::prelude::*; -use xcm_builder::HaulBlobExporter; - -/// Default lane that is used to send messages to Rialto. -pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); - -parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; - /// Lane used by the with-Rialto bridge. - pub RialtoSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); - - /// Dummy message used in configuration. - pub DummyXcmMessage: Xcm<()> = Xcm::new(); -} - -/// Message payload for Millau -> Rialto messages. -pub type ToRialtoMessagePayload = messages::source::FromThisChainMessagePayload; - -/// Message verifier for Millau -> Rialto messages. -pub type ToRialtoMessageVerifier = - messages::source::FromThisChainMessageVerifier; - -/// Message payload for Rialto -> Millau messages. -pub type FromRialtoMessagePayload = messages::target::FromBridgedChainMessagePayload; - -/// Messages proof for Rialto -> Millau messages. -pub type FromRialtoMessagesProof = messages::target::FromBridgedChainMessagesProof; - -/// Messages delivery proof for Millau -> Rialto messages. -pub type ToRialtoMessagesDeliveryProof = - messages::source::FromBridgedChainMessagesDeliveryProof; - -/// Call-dispatch based message dispatch for Rialto -> Millau messages. -pub type FromRialtoMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::xcm_config::OnMillauBlobDispatcher, - (), - (), - >; - -/// Maximal outbound payload size of Millau -> Rialto messages. -pub type ToRialtoMaximalOutboundPayloadSize = - messages::source::FromThisChainMaximalOutboundPayloadSize; - -/// Millau <-> Rialto message bridge. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct WithRialtoMessageBridge; - -impl MessageBridge for WithRialtoMessageBridge { - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; - - type ThisChain = Millau; - type BridgedChain = Rialto; - type BridgedHeaderChain = - pallet_bridge_grandpa::GrandpaChainHeaders; -} - -/// Millau chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct Millau; - -impl messages::UnderlyingChainProvider for Millau { - type Chain = bp_millau::Millau; -} - -impl messages::ThisChainWithMessages for Millau { - type RuntimeOrigin = RuntimeOrigin; -} - -/// Rialto chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct Rialto; -/// Rialto as source header chain. -pub type RialtoAsSourceHeaderChain = SourceHeaderChainAdapter; -/// Rialto as target header chain. -pub type RialtoAsTargetHeaderChain = TargetHeaderChainAdapter; - -impl messages::UnderlyingChainProvider for Rialto { - type Chain = bp_rialto::Rialto; -} - -impl messages::BridgedChainWithMessages for Rialto {} - -/// Export XCM messages to be relayed to Rialto. -pub type ToRialtoBlobExporter = HaulBlobExporter< - XcmBlobHaulerAdapter, - crate::xcm_config::RialtoNetwork, - (), ->; - -/// To-Rialto XCM hauler. -pub struct ToRialtoXcmBlobHauler; - -impl XcmBlobHauler for ToRialtoXcmBlobHauler { - type Runtime = Runtime; - type MessagesInstance = WithRialtoMessagesInstance; - type SenderAndLane = RialtoSenderAndLane; - - type ToSourceChainSender = crate::xcm_config::XcmRouter; - type CongestedMessage = DummyXcmMessage; - type UncongestedMessage = DummyXcmMessage; -} - -impl pallet_bridge_messages::WeightInfoExt for crate::weights::RialtoMessagesWeightInfo { - fn expected_extra_storage_proof_size() -> u32 { - bp_rialto::EXTRA_STORAGE_PROOF_SIZE - } - - fn receive_messages_proof_overhead_from_runtime() -> Weight { - pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_proof_overhead_from_runtime() - } - - fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { - pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_delivery_proof_overhead_from_runtime() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{Runtime, WithRialtoMessagesInstance}; - - use bridge_runtime_common::{ - assert_complete_bridge_types, - integrity::{ - assert_complete_bridge_constants, check_message_lane_weights, - AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, - AssertCompleteBridgeConstants, - }, - }; - - #[test] - fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( - bp_rialto::EXTRA_STORAGE_PROOF_SIZE, - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - false, - ); - } - - #[test] - fn ensure_bridge_integrity() { - assert_complete_bridge_types!( - runtime: Runtime, - with_bridged_chain_grandpa_instance: RialtoGrandpaInstance, - with_bridged_chain_messages_instance: WithRialtoMessagesInstance, - bridge: WithRialtoMessageBridge, - this_chain: bp_millau::Millau, - bridged_chain: bp_rialto::Rialto, - ); - - assert_complete_bridge_constants::< - Runtime, - RialtoGrandpaInstance, - WithRialtoMessagesInstance, - WithRialtoMessageBridge, - >(AssertCompleteBridgeConstants { - this_chain_constants: AssertChainConstants { - block_length: bp_millau::BlockLength::get(), - block_weights: bp_millau::BlockWeights::get(), - }, - messages_pallet_constants: AssertBridgeMessagesPalletConstants { - max_unrewarded_relayers_in_bridged_confirmation_tx: - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - max_unconfirmed_messages_in_bridged_confirmation_tx: - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - bridged_chain_id: bp_runtime::RIALTO_CHAIN_ID, - }, - pallet_names: AssertBridgePalletNames { - with_this_chain_messages_pallet_name: bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, - with_bridged_chain_grandpa_pallet_name: bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME, - with_bridged_chain_messages_pallet_name: - bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, - }, - }); - } -} diff --git a/bin/millau/runtime/src/rialto_parachain_messages.rs b/bin/millau/runtime/src/rialto_parachain_messages.rs deleted file mode 100644 index 1c4807f0cd332..0000000000000 --- a/bin/millau/runtime/src/rialto_parachain_messages.rs +++ /dev/null @@ -1,227 +0,0 @@ -// 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 . - -//! Everything required to serve Millau <-> RialtoParachain messages. - -use crate::{ - Runtime, RuntimeOrigin, WithRialtoParachainMessagesInstance, WithRialtoParachainsInstance, -}; - -use bp_messages::LaneId; -use bridge_runtime_common::{ - messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, - }, - messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, -}; -use frame_support::{parameter_types, weights::Weight}; -use pallet_bridge_relayers::WeightInfoExt as _; -use sp_runtime::RuntimeDebug; -use xcm::latest::prelude::*; -use xcm_builder::HaulBlobExporter; - -/// Default lane that is used to send messages to Rialto parachain. -pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); - -parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; - /// Lane used by the with-RialtoParachain bridge. - pub RialtoParachainSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); - - /// Dummy message used in configuration. - pub DummyXcmMessage: Xcm<()> = Xcm::new(); -} - -/// Message payload for Millau -> RialtoParachain messages. -pub type ToRialtoParachainMessagePayload = messages::source::FromThisChainMessagePayload; - -/// Message verifier for Millau -> RialtoParachain messages. -pub type ToRialtoParachainMessageVerifier = - messages::source::FromThisChainMessageVerifier; - -/// Message payload for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessagePayload = messages::target::FromBridgedChainMessagePayload; - -/// Call-dispatch based message dispatch for RialtoParachain -> Millau messages. -pub type FromRialtoParachainMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::xcm_config::OnMillauBlobDispatcher, - (), - (), - >; - -/// Maximal outbound payload size of Millau -> RialtoParachain messages. -pub type ToRialtoParachainMaximalOutboundPayloadSize = - messages::source::FromThisChainMaximalOutboundPayloadSize; - -/// Millau <-> RialtoParachain message bridge. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct WithRialtoParachainMessageBridge; - -impl MessageBridge for WithRialtoParachainMessageBridge { - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; - - type ThisChain = Millau; - type BridgedChain = RialtoParachain; - type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< - Runtime, - WithRialtoParachainsInstance, - bp_rialto_parachain::RialtoParachain, - >; -} - -/// Millau chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct Millau; - -impl messages::UnderlyingChainProvider for Millau { - type Chain = bp_millau::Millau; -} - -impl messages::ThisChainWithMessages for Millau { - type RuntimeOrigin = RuntimeOrigin; -} - -/// RialtoParachain chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct RialtoParachain; -/// RialtoParachain as source header chain. -pub type RialtoParachainAsSourceHeaderChain = - SourceHeaderChainAdapter; -/// RialtoParachain as target header chain. -pub type RialtoParachainAsTargetHeaderChain = - TargetHeaderChainAdapter; - -impl messages::UnderlyingChainProvider for RialtoParachain { - type Chain = bp_rialto_parachain::RialtoParachain; -} - -impl messages::BridgedChainWithMessages for RialtoParachain {} - -/// Export XCM messages to be relayed to Rialto. -pub type ToRialtoParachainBlobExporter = HaulBlobExporter< - XcmBlobHaulerAdapter, - crate::xcm_config::RialtoParachainNetwork, - (), ->; - -/// To-RialtoParachain XCM hauler. -pub struct ToRialtoParachainXcmBlobHauler; - -impl XcmBlobHauler for ToRialtoParachainXcmBlobHauler { - type Runtime = Runtime; - type MessagesInstance = WithRialtoParachainMessagesInstance; - type SenderAndLane = RialtoParachainSenderAndLane; - - type ToSourceChainSender = crate::xcm_config::XcmRouter; - type CongestedMessage = DummyXcmMessage; - type UncongestedMessage = DummyXcmMessage; -} - -impl pallet_bridge_messages::WeightInfoExt - for crate::weights::RialtoParachainMessagesWeightInfo -{ - fn expected_extra_storage_proof_size() -> u32 { - bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE - } - - fn receive_messages_proof_overhead_from_runtime() -> Weight { - pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_proof_overhead_from_runtime() - } - - fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { - pallet_bridge_relayers::weights::BridgeWeight::::receive_messages_delivery_proof_overhead_from_runtime() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - PriorityBoostPerMessage, RialtoGrandpaInstance, Runtime, - WithRialtoParachainMessagesInstance, - }; - - use bridge_runtime_common::{ - assert_complete_bridge_types, - integrity::{ - assert_complete_bridge_constants, check_message_lane_weights, - AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, - AssertCompleteBridgeConstants, - }, - }; - - #[test] - fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( - bp_rialto_parachain::EXTRA_STORAGE_PROOF_SIZE, - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - true, - ); - } - - #[test] - fn ensure_bridge_integrity() { - assert_complete_bridge_types!( - runtime: Runtime, - with_bridged_chain_grandpa_instance: RialtoGrandpaInstance, - with_bridged_chain_messages_instance: WithRialtoParachainMessagesInstance, - bridge: WithRialtoParachainMessageBridge, - this_chain: bp_millau::Millau, - bridged_chain: bp_rialto::Rialto, - ); - - assert_complete_bridge_constants::< - Runtime, - RialtoGrandpaInstance, - WithRialtoParachainMessagesInstance, - WithRialtoParachainMessageBridge, - >(AssertCompleteBridgeConstants { - this_chain_constants: AssertChainConstants { - block_length: bp_millau::BlockLength::get(), - block_weights: bp_millau::BlockWeights::get(), - }, - messages_pallet_constants: AssertBridgeMessagesPalletConstants { - max_unrewarded_relayers_in_bridged_confirmation_tx: - bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - max_unconfirmed_messages_in_bridged_confirmation_tx: - bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - bridged_chain_id: bp_runtime::RIALTO_PARACHAIN_CHAIN_ID, - }, - pallet_names: AssertBridgePalletNames { - with_this_chain_messages_pallet_name: bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, - with_bridged_chain_grandpa_pallet_name: bp_rialto::WITH_RIALTO_GRANDPA_PALLET_NAME, - with_bridged_chain_messages_pallet_name: - bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME, - }, - }); - - bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< - Runtime, - WithRialtoParachainMessagesInstance, - PriorityBoostPerMessage, - >(1_000_000); - } -} diff --git a/bin/millau/runtime/src/weights/mod.rs b/bin/millau/runtime/src/weights/mod.rs deleted file mode 100644 index 801ff9b3c8f68..0000000000000 --- a/bin/millau/runtime/src/weights/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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 . - -mod pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance; -mod pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance; - -pub use pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance::WeightInfo as RialtoMessagesWeightInfo; -pub use pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance::WeightInfo as RialtoParachainMessagesWeightInfo; diff --git a/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs b/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs deleted file mode 100644 index b58402d275638..0000000000000 --- a/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_messages_instance.rs +++ /dev/null @@ -1,188 +0,0 @@ - -//! Autogenerated weights for `pallet_bridge_messages` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// target/release/millau-bridge-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_messages -// --extrinsic=* -// --execution=wasm -// --wasm-execution=Compiled -// --heap-pages=4096 -// --output=./bin/millau/runtime/src/weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_bridge_messages`. -pub struct WeightInfo(PhantomData); -impl pallet_bridge_messages::WeightInfo for WeightInfo { - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `490` - // Estimated: `57170` - // Minimum execution time: 51_189_000 picoseconds. - Weight::from_parts(52_881_000, 0) - .saturating_add(Weight::from_parts(0, 57170)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_two_messages_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `490` - // Estimated: `57170` - // Minimum execution time: 65_083_000 picoseconds. - Weight::from_parts(66_878_000, 0) - .saturating_add(Weight::from_parts(0, 57170)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - // Proof Size summary in bytes: - // Measured: `490` - // Estimated: `57170` - // Minimum execution time: 57_919_000 picoseconds. - Weight::from_parts(58_927_000, 0) - .saturating_add(Weight::from_parts(0, 57170)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof_1_kb() -> Weight { - // Proof Size summary in bytes: - // Measured: `490` - // Estimated: `57170` - // Minimum execution time: 52_202_000 picoseconds. - Weight::from_parts(53_617_000, 0) - .saturating_add(Weight::from_parts(0, 57170)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof_16_kb() -> Weight { - // Proof Size summary in bytes: - // Measured: `490` - // Estimated: `57170` - // Minimum execution time: 74_726_000 picoseconds. - Weight::from_parts(76_379_000, 0) - .saturating_add(Weight::from_parts(0, 57170)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) - /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - fn receive_delivery_proof_for_single_message() -> Weight { - // Proof Size summary in bytes: - // Measured: `515` - // Estimated: `9584` - // Minimum execution time: 45_156_000 picoseconds. - Weight::from_parts(46_535_000, 0) - .saturating_add(Weight::from_parts(0, 9584)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) - /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - // Proof Size summary in bytes: - // Measured: `532` - // Estimated: `9584` - // Minimum execution time: 44_104_000 picoseconds. - Weight::from_parts(45_602_000, 0) - .saturating_add(Weight::from_parts(0, 9584)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) - /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - // Proof Size summary in bytes: - // Measured: `532` - // Estimated: `12124` - // Minimum execution time: 46_880_000 picoseconds. - Weight::from_parts(48_472_000, 0) - .saturating_add(Weight::from_parts(0, 12124)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), added: 2048, mode: MaxEncodedLen) - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - /// The range of component `i` is `[128, 2048]`. - /// The range of component `i` is `[128, 2048]`. - fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `490` - // Estimated: `57170` - // Minimum execution time: 107_297_000 picoseconds. - Weight::from_parts(98_819_194, 0) - .saturating_add(Weight::from_parts(0, 57170)) - // Standard Error: 2_195 - .saturating_add(Weight::from_parts(448_268, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs b/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs deleted file mode 100644 index c71cb11fdc717..0000000000000 --- a/bin/millau/runtime/src/weights/pallet_bridge_messages_messages_bench_runtime_with_rialto_parachain_messages_instance.rs +++ /dev/null @@ -1,188 +0,0 @@ - -//! Autogenerated weights for `pallet_bridge_messages` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-01, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `covid`, CPU: `11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// target/release/millau-bridge-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_bridge_messages -// --extrinsic=* -// --execution=wasm -// --wasm-execution=Compiled -// --heap-pages=4096 -// --output=./bin/millau/runtime/src/weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_bridge_messages`. -pub struct WeightInfo(PhantomData); -impl pallet_bridge_messages::WeightInfo for WeightInfo { - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `428` - // Estimated: `56803` - // Minimum execution time: 49_949_000 picoseconds. - Weight::from_parts(51_439_000, 0) - .saturating_add(Weight::from_parts(0, 56803)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_two_messages_proof() -> Weight { - // Proof Size summary in bytes: - // Measured: `428` - // Estimated: `56803` - // Minimum execution time: 62_552_000 picoseconds. - Weight::from_parts(64_899_000, 0) - .saturating_add(Weight::from_parts(0, 56803)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof_with_outbound_lane_state() -> Weight { - // Proof Size summary in bytes: - // Measured: `428` - // Estimated: `56803` - // Minimum execution time: 56_795_000 picoseconds. - Weight::from_parts(58_441_000, 0) - .saturating_add(Weight::from_parts(0, 56803)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof_1_kb() -> Weight { - // Proof Size summary in bytes: - // Measured: `428` - // Estimated: `56803` - // Minimum execution time: 51_340_000 picoseconds. - Weight::from_parts(52_533_000, 0) - .saturating_add(Weight::from_parts(0, 56803)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - fn receive_single_message_proof_16_kb() -> Weight { - // Proof Size summary in bytes: - // Measured: `428` - // Estimated: `56803` - // Minimum execution time: 74_022_000 picoseconds. - Weight::from_parts(75_115_000, 0) - .saturating_add(Weight::from_parts(0, 56803)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages OutboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) - /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - fn receive_delivery_proof_for_single_message() -> Weight { - // Proof Size summary in bytes: - // Measured: `453` - // Estimated: `9217` - // Minimum execution time: 43_296_000 picoseconds. - Weight::from_parts(45_022_000, 0) - .saturating_add(Weight::from_parts(0, 9217)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages OutboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) - /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { - // Proof Size summary in bytes: - // Measured: `470` - // Estimated: `9217` - // Minimum execution time: 42_618_000 picoseconds. - Weight::from_parts(43_972_000, 0) - .saturating_add(Weight::from_parts(0, 9217)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages OutboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) - /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) - /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(65), added: 2540, mode: MaxEncodedLen) - fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { - // Proof Size summary in bytes: - // Measured: `470` - // Estimated: `11757` - // Minimum execution time: 45_954_000 picoseconds. - Weight::from_parts(46_892_000, 0) - .saturating_add(Weight::from_parts(0, 11757)) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: BridgeRialtoParachainMessages PalletOperatingMode (r:1 w:0) - /// Proof: BridgeRialtoParachainMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:1 w:0) - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: Some(196), added: 1681, mode: MaxEncodedLen) - /// Storage: BridgeRialtoParachainMessages InboundLanes (r:1 w:1) - /// Proof: BridgeRialtoParachainMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) - /// The range of component `i` is `[128, 2048]`. - /// The range of component `i` is `[128, 2048]`. - fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `428` - // Estimated: `56803` - // Minimum execution time: 107_766_000 picoseconds. - Weight::from_parts(97_865_035, 0) - .saturating_add(Weight::from_parts(0, 56803)) - // Standard Error: 2_179 - .saturating_add(Weight::from_parts(447_749, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/bin/millau/runtime/src/xcm_config.rs b/bin/millau/runtime/src/xcm_config.rs deleted file mode 100644 index 45236360ddcc1..0000000000000 --- a/bin/millau/runtime/src/xcm_config.rs +++ /dev/null @@ -1,410 +0,0 @@ -// 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 . - -//! XCM configurations for the Millau runtime. - -use super::{ - rialto_messages::ToRialtoBlobExporter, - rialto_parachain_messages::ToRialtoParachainBlobExporter, AccountId, AllPalletsWithSystem, - Balances, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, -}; -use bp_millau::WeightToFee; -use bridge_runtime_common::CustomNetworkId; -use frame_support::{ - parameter_types, - traits::{ConstU32, Everything, Nothing}, - weights::Weight, -}; -use frame_system::EnsureRoot; -use xcm::latest::prelude::*; -use xcm_builder::{ - AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, -}; -use xcm_executor::traits::ExportXcm; - -parameter_types! { - /// The location of the `MLAU` token, from the context of this chain. Since this token is native to this - /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to - /// the context". - pub const TokenLocation: MultiLocation = Here.into_location(); - /// Token asset identifier. - pub TokenAssetId: AssetId = TokenLocation::get().into(); - /// The Millau network ID. - pub const ThisNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); - /// The Rialto network ID. - pub const RialtoNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); - /// The RialtoParachain network ID. - pub const RialtoParachainNetwork: NetworkId = CustomNetworkId::RialtoParachain.as_network_id(); - - /// Our XCM location ancestry - i.e. our location within the Consensus Universe. - /// - /// Since Kusama is a top-level relay-chain with its own consensus, it's just our network ID. - pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); - /// The check account, which holds any native assets that have been teleported out and not back in (yet). - pub CheckAccount: (AccountId, MintLocation) = (XcmPallet::check_account(), MintLocation::Local); -} - -/// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to -/// determine the sovereign account controlled by a location. -pub type SovereignAccountOf = ( - // We can directly alias an `AccountId32` into a local account. - AccountId32Aliases, -); - -/// Our asset transactor. This is what allows us to interest with the runtime facilities from the -/// point of view of XCM-only concepts like `MultiLocation` and `MultiAsset`. -/// -/// Ours is only aware of the Balances pallet, which is mapped to `TokenLocation`. -pub type LocalAssetTransactor = XcmCurrencyAdapter< - // Use this currency: - Balances, - // Use this currency when it is a fungible asset matching the given location or name: - IsConcrete, - // We can convert the MultiLocations with our converter above: - SovereignAccountOf, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We track our teleports in/out to keep total issuance correct. - CheckAccount, ->; - -/// The means that we convert the XCM message origin location into a local dispatch origin. -type LocalOriginConverter = ( - // A `Signed` origin of the sovereign account that the original location controls. - SovereignSignedViaLocation, - // The AccountId32 location type can be expressed natively as a `Signed` origin. - SignedAccountId32AsNative, -); - -parameter_types! { - /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const BaseXcmWeight: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); - /// Maximum number of instructions in a single XCM fragment. A sanity check against weight - /// calculations getting too crazy. - pub const MaxInstructions: u32 = 100; -} - -/// The XCM router. We are not sending messages to sibling/parent/child chains here. -pub type XcmRouter = EmulatedSiblingXcmpChannel; - -/// The barriers one of which must be passed for an XCM message to be executed. -pub type Barrier = ( - // Weight that is paid for may be consumed. - TakeWeightCredit, -); - -/// Dispatches received XCM messages from other chain. -pub type OnMillauBlobDispatcher = xcm_builder::BridgeBlobDispatcher< - crate::xcm_config::XcmRouter, - crate::xcm_config::UniversalLocation, - (), ->; - -/// XCM weigher type. -pub type XcmWeigher = xcm_builder::FixedWeightBounds; - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = (); - type AssetTransactor = LocalAssetTransactor; - type OriginConverter = LocalOriginConverter; - type IsReserve = (); - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = XcmWeigher; - // The weight trader piggybacks on the existing transaction-fee conversion logic. - type Trader = UsingComponents; - type ResponseHandler = XcmPallet; - type AssetTrap = XcmPallet; - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = XcmPallet; - type SubscriptionService = XcmPallet; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = ConstU32<64>; - type FeeManager = (); - type MessageExporter = ToRialtoOrRialtoParachainSwitchExporter; - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = Nothing; -} - -/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior -/// location of this chain. -pub type LocalOriginToLocation = ( - // Usual Signed origin to be used in XCM as a corresponding AccountId32 - SignedToAccountId32, -); - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = None; -} - -impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - // We don't allow any messages to be sent via the transaction yet. This is basically safe to - // enable, (safe the possibility of someone spamming the parachain if they're willing to pay - // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will - // make `DescendOrigin` a bit more useful. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmRouter = (); - // Anyone can execute XCM messages locally. - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = xcm_executor::XcmExecutor; - // Anyone is able to use teleportation regardless of who they are and what they want to - // teleport. - type XcmTeleportFilter = Everything; - // Anyone is able to use reserve transfers regardless of who they are and what they want to - // transfer. - type XcmReserveTransferFilter = Everything; - type Weigher = XcmWeigher; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = SovereignAccountOf; - type MaxLockers = frame_support::traits::ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); -} - -pub struct ToRialtoOrRialtoParachainSwitchExporter; - -impl ExportXcm for ToRialtoOrRialtoParachainSwitchExporter { - type Ticket = (NetworkId, (sp_std::prelude::Vec, XcmHash)); - - fn validate( - network: NetworkId, - channel: u32, - universal_source: &mut Option, - destination: &mut Option, - message: &mut Option>, - ) -> SendResult { - if network == RialtoNetwork::get() { - ToRialtoBlobExporter::validate(network, channel, universal_source, destination, message) - .map(|result| ((RialtoNetwork::get(), result.0), result.1)) - } else if network == RialtoParachainNetwork::get() { - ToRialtoParachainBlobExporter::validate( - network, - channel, - universal_source, - destination, - message, - ) - .map(|result| ((RialtoParachainNetwork::get(), result.0), result.1)) - } else { - Err(SendError::Unroutable) - } - } - - fn deliver(ticket: Self::Ticket) -> Result { - let (network, ticket) = ticket; - if network == RialtoNetwork::get() { - ToRialtoBlobExporter::deliver(ticket) - } else if network == RialtoParachainNetwork::get() { - ToRialtoParachainBlobExporter::deliver(ticket) - } else { - Err(SendError::Unroutable) - } - } -} - -/// Emulating XCMP channel with sibling chain. We don't have required infra here, at Millau, -/// so we have to provide at least something to be able to run benchmarks. -pub struct EmulatedSiblingXcmpChannel; - -impl SendXcm for EmulatedSiblingXcmpChannel { - type Ticket = (); - - fn validate( - _destination: &mut Option, - _message: &mut Option>, - ) -> SendResult { - Ok(((), Default::default())) - } - - fn deliver(_ticket: Self::Ticket) -> Result { - Ok(XcmHash::default()) - } -} - -impl EmulatedSiblingXcmpChannel { - /// Start emulating congested channel. - pub fn make_congested() { - frame_support::storage::unhashed::put(b"EmulatedSiblingXcmpChannel.Congested", &true); - } -} - -impl bp_xcm_bridge_hub_router::XcmChannelStatusProvider for EmulatedSiblingXcmpChannel { - fn is_congested() -> bool { - frame_support::storage::unhashed::get_or_default(b"EmulatedSiblingXcmpChannel.Congested") - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - rialto_messages::FromRialtoMessageDispatch, WithRialtoMessagesInstance, - WithRialtoParachainMessagesInstance, - }; - use bp_messages::{ - target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - LaneId, MessageKey, - }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; - use codec::Encode; - use pallet_bridge_messages::OutboundLanes; - use sp_runtime::BuildStorage; - use xcm_executor::XcmExecutor; - - fn new_test_ext() -> sp_io::TestExternalities { - sp_io::TestExternalities::new( - frame_system::GenesisConfig::::default().build_storage().unwrap(), - ) - } - - fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm { - vec![ExportMessage { - network: destination, - destination: destination.into(), - xcm: vec![Instruction::Trap(42)].into(), - }] - .into() - } - - #[test] - fn xcm_messages_to_rialto_are_sent_using_bridge_exporter() { - new_test_ext().execute_with(|| { - // ensure that the there are no messages queued - assert_eq!( - OutboundLanes::::get( - crate::rialto_messages::XCM_LANE - ) - .latest_generated_nonce, - 0, - ); - - // export message instruction "sends" message to Rialto - XcmExecutor::::execute_xcm_in_credit( - Here, - prepare_outbound_xcm_message(RialtoNetwork::get()), - Default::default(), - Weight::MAX, - Weight::MAX, - ) - .ensure_complete() - .expect("runtime configuration must be correct"); - - // ensure that the message has been queued - assert_eq!( - OutboundLanes::::get( - crate::rialto_messages::XCM_LANE - ) - .latest_generated_nonce, - 1, - ); - }) - } - - #[test] - fn xcm_messages_to_rialto_parachain_are_sent_using_bridge_exporter() { - new_test_ext().execute_with(|| { - // ensure that the there are no messages queued - assert_eq!( - OutboundLanes::::get( - crate::rialto_parachain_messages::XCM_LANE - ) - .latest_generated_nonce, - 0, - ); - - // export message instruction "sends" message to Rialto - XcmExecutor::::execute_xcm_in_credit( - Here, - prepare_outbound_xcm_message(RialtoParachainNetwork::get()), - Default::default(), - Weight::MAX, - Weight::MAX, - ) - .ensure_complete() - .expect("runtime configuration must be correct"); - - // ensure that the message has been queued - assert_eq!( - OutboundLanes::::get( - crate::rialto_parachain_messages::XCM_LANE - ) - .latest_generated_nonce, - 1, - ); - }) - } - - fn prepare_inbound_bridge_message() -> DispatchMessage> { - let xcm = xcm::VersionedXcm::::V3(vec![Instruction::Trap(42)].into()); - let location = - xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); - // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor - // or public fields, so just tuple - let bridge_message = (location, xcm).encode(); - DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok(bridge_message) }, - } - } - - #[test] - fn xcm_messages_from_rialto_are_dispatched() { - let incoming_message = prepare_inbound_bridge_message(); - - // we care only about handing message to the XCM dispatcher, so we don't care about its - // actual dispatch - let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); - assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::Dispatched, - )); - } - - #[test] - fn xcm_messages_from_rialto_parachain_are_dispatched() { - let incoming_message = prepare_inbound_bridge_message(); - - // we care only about handing message to the XCM dispatcher, so we don't care about its - // actual dispatch - let dispatch_result = FromRialtoMessageDispatch::dispatch(incoming_message); - assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::Dispatched, - )); - } -} diff --git a/bin/rialto-parachain/node/Cargo.toml b/bin/rialto-parachain/node/Cargo.toml deleted file mode 100644 index 053ee24577377..0000000000000 --- a/bin/rialto-parachain/node/Cargo.toml +++ /dev/null @@ -1,81 +0,0 @@ -[package] -name = "rialto-parachain-collator" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -repository = "https://github.com/paritytech/parity-bridges-common/" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[[bin]] -name = 'rialto-parachain-collator' - -[features] -default = [] -runtime-benchmarks = [ 'rialto-parachain-runtime/runtime-benchmarks' ] - -[dependencies] -clap = { version = "4.4.8", features = ["derive"] } -log = '0.4.20' -codec = { package = 'parity-scale-codec', version = '3.1.5' } -serde = { version = '1.0', features = ['derive'] } - -# RPC related Dependencies -jsonrpsee = { version = "0.16.2", features = ["server"] } - -# Local Dependencies -rialto-parachain-runtime = { path = '../runtime' } - -# Substrate Dependencies -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -substrate-frame-rpc-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -## Substrate Client Dependencies -sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-chain-spec = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-client-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-consensus = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-network = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-network-sync = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-rpc = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-rpc-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master"} -sc-telemetry = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-tracing = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -## Substrate Primitive Dependencies -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-keystore = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -# Cumulus dependencies -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-client-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-client-network = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-client-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -# Polkadot dependencies -polkadot-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/bin/rialto-parachain/node/build.rs b/bin/rialto-parachain/node/build.rs deleted file mode 100644 index 8ba8a31e9a79f..0000000000000 --- a/bin/rialto-parachain/node/build.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 . - -use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; - -fn main() { - generate_cargo_keys(); - rerun_if_git_head_changed(); -} diff --git a/bin/rialto-parachain/node/src/chain_spec.rs b/bin/rialto-parachain/node/src/chain_spec.rs deleted file mode 100644 index b42c9a6a8f5ee..0000000000000 --- a/bin/rialto-parachain/node/src/chain_spec.rs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2020-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 . - -use cumulus_primitives_core::ParaId; -use rialto_parachain_runtime::{AccountId, AuraId, BridgeMillauMessagesConfig, Signature}; -use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; -use sc_service::ChainType; -use serde::{Deserialize, Serialize}; -use sp_core::{sr25519, Pair, Public}; -use sp_runtime::traits::{IdentifyAccount, Verify}; - -/// "Names" of the authorities accounts at local testnet. -const LOCAL_AUTHORITIES_ACCOUNTS: [&str; 2] = ["Alice", "Bob"]; -/// "Names" of the authorities accounts at development testnet. -const DEV_AUTHORITIES_ACCOUNTS: [&str; 2] = LOCAL_AUTHORITIES_ACCOUNTS; -/// "Names" of all possible authorities accounts. -const ALL_AUTHORITIES_ACCOUNTS: [&str; 2] = LOCAL_AUTHORITIES_ACCOUNTS; -/// "Name" of the `sudo` account. -const SUDO_ACCOUNT: &str = "Sudo"; -/// "Name" of the account, which owns the with-Millau messages pallet. -const MILLAU_MESSAGES_PALLET_OWNER: &str = "Millau.MessagesOwner"; - -/// Specialized `ChainSpec` for the normal parachain runtime. -pub type ChainSpec = - sc_service::GenericChainSpec; - -/// Helper function to generate a crypto pair from seed -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{seed}"), None) - .expect("static values are valid; qed") - .public() -} - -/// The extensions for the [`ChainSpec`]. -#[derive( - Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, -)] -#[serde(deny_unknown_fields)] -pub struct Extensions { - /// The relay chain of the Parachain. - pub relay_chain: String, - /// The id of the Parachain. - pub para_id: u32, -} - -impl Extensions { - /// Try to get the extension from the given `ChainSpec`. - pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> { - sc_chain_spec::get_extension(chain_spec.extensions()) - } -} - -type AccountPublic = ::Signer; - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId -where - AccountPublic: From<::Public>, -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// We're using the same set of endowed accounts on all RialtoParachain chains (dev/local) to make -/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, -/// accounts used by relayers in our test deployments, accounts used for demonstration -/// purposes), are all available on these chains. -fn endowed_accounts() -> Vec { - let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { - [ - get_account_id_from_seed::(x), - get_account_id_from_seed::(&format!("{x}//stash")), - ] - }); - vec![ - // Sudo account - get_account_id_from_seed::(SUDO_ACCOUNT), - // Regular (unused) accounts - get_account_id_from_seed::("Charlie"), - get_account_id_from_seed::("Dave"), - get_account_id_from_seed::("Eve"), - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Charlie//stash"), - get_account_id_from_seed::("Dave//stash"), - get_account_id_from_seed::("Eve//stash"), - get_account_id_from_seed::("Ferdie//stash"), - // Accounts, used by RialtoParachain<>Millau bridge - get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER), - get_account_id_from_seed::("Millau.HeadersAndMessagesRelay1"), - get_account_id_from_seed::("Millau.HeadersAndMessagesRelay2"), - get_account_id_from_seed::("Millau.MessagesSender"), - ] - .into_iter() - .chain(all_authorities) - .collect() -} - -pub fn development_config(id: ParaId) -> ChainSpec { - // Give your base currency a unit name and decimal places - let mut properties = sc_chain_spec::Properties::new(); - properties.insert("tokenSymbol".into(), "UNIT".into()); - properties.insert("tokenDecimals".into(), 12.into()); - - ChainSpec::from_genesis( - // Name - "Development", - // ID - "dev", - ChainType::Local, - move || { - testnet_genesis( - get_account_id_from_seed::(SUDO_ACCOUNT), - DEV_AUTHORITIES_ACCOUNTS.into_iter().map(get_from_seed::).collect(), - endowed_accounts(), - id, - ) - }, - vec![], - None, - None, - None, - None, - Extensions { - relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: id.into(), - }, - ) -} - -pub fn local_testnet_config(id: ParaId) -> ChainSpec { - // Give your base currency a unit name and decimal places - let mut properties = sc_chain_spec::Properties::new(); - properties.insert("tokenSymbol".into(), "UNIT".into()); - properties.insert("tokenDecimals".into(), 12.into()); - - ChainSpec::from_genesis( - // Name - "Local Testnet", - // ID - "local_testnet", - ChainType::Local, - move || { - testnet_genesis( - get_account_id_from_seed::(SUDO_ACCOUNT), - LOCAL_AUTHORITIES_ACCOUNTS.into_iter().map(get_from_seed::).collect(), - endowed_accounts(), - id, - ) - }, - Vec::new(), - None, - None, - None, - None, - Extensions { - relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: id.into(), - }, - ) -} - -fn testnet_genesis( - root_key: AccountId, - initial_authorities: Vec, - endowed_accounts: Vec, - id: ParaId, -) -> rialto_parachain_runtime::RuntimeGenesisConfig { - rialto_parachain_runtime::RuntimeGenesisConfig { - system: rialto_parachain_runtime::SystemConfig { - code: rialto_parachain_runtime::WASM_BINARY - .expect("WASM binary was not build, please build it!") - .to_vec(), - ..Default::default() - }, - balances: rialto_parachain_runtime::BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), - }, - sudo: rialto_parachain_runtime::SudoConfig { key: Some(root_key) }, - parachain_info: rialto_parachain_runtime::ParachainInfoConfig { - parachain_id: id, - ..Default::default() - }, - aura: rialto_parachain_runtime::AuraConfig { authorities: initial_authorities }, - aura_ext: Default::default(), - bridge_millau_messages: BridgeMillauMessagesConfig { - owner: Some(get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER)), - ..Default::default() - }, - } -} diff --git a/bin/rialto-parachain/node/src/cli.rs b/bin/rialto-parachain/node/src/cli.rs deleted file mode 100644 index c8c457752d600..0000000000000 --- a/bin/rialto-parachain/node/src/cli.rs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2020-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 . - -#![allow(clippy::large_enum_variant)] - -use crate::chain_spec; -use clap::Parser; -use cumulus_client_cli::{ExportGenesisStateCommand, ExportGenesisWasmCommand}; -use std::path::PathBuf; - -/// Sub-commands supported by the collator. -#[derive(Debug, Parser)] -pub enum Subcommand { - /// Export the genesis state of the parachain. - #[clap(name = "export-genesis-state")] - ExportGenesisState(ExportGenesisStateCommand), - - /// Export the genesis wasm of the parachain. - #[clap(name = "export-genesis-wasm")] - ExportGenesisWasm(ExportGenesisWasmCommand), - - /// Build a chain specification. - BuildSpec(sc_cli::BuildSpecCmd), - - /// Validate blocks. - CheckBlock(sc_cli::CheckBlockCmd), - - /// Export blocks. - ExportBlocks(sc_cli::ExportBlocksCmd), - - /// Export the state of a given block into a chain spec. - ExportState(sc_cli::ExportStateCmd), - - /// Import blocks. - ImportBlocks(sc_cli::ImportBlocksCmd), - - /// Remove the whole chain. - PurgeChain(cumulus_client_cli::PurgeChainCmd), - - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), - - /// The custom benchmark subcommand benchmarking runtime pallets. - #[clap(subcommand)] - Benchmark(frame_benchmarking_cli::BenchmarkCmd), -} - -#[derive(Debug, Parser)] -#[clap( - propagate_version = true, - args_conflicts_with_subcommands = true, - subcommand_negates_reqs = true -)] -pub struct Cli { - #[clap(subcommand)] - pub subcommand: Option, - - #[clap(long)] - pub parachain_id: Option, - - #[clap(flatten)] - pub run: cumulus_client_cli::RunCmd, - - /// Relaychain arguments - #[clap(raw = true)] - pub relaychain_args: Vec, -} - -#[derive(Debug)] -pub struct RelayChainCli { - /// The actual relay chain CLI object. - pub base: polkadot_cli::RunCmd, - - /// Optional chain id that should be passed to the relay chain. - pub chain_id: Option, - - /// The base path that should be used by the relay chain. - pub base_path: Option, -} - -impl RelayChainCli { - /// Parse the relay chain CLI parameters using the para chain `Configuration`. - pub fn new<'a>( - para_config: &sc_service::Configuration, - relay_chain_args: impl Iterator, - ) -> Self { - let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec); - let chain_id = extension.map(|e| e.relay_chain.clone()); - let base_path = para_config.base_path.path().join("rialto-bridge-node"); - Self { - base_path: Some(base_path), - chain_id, - base: polkadot_cli::RunCmd::parse_from(relay_chain_args), - } - } -} diff --git a/bin/rialto-parachain/node/src/command.rs b/bin/rialto-parachain/node/src/command.rs deleted file mode 100644 index 50c1857f1c9c8..0000000000000 --- a/bin/rialto-parachain/node/src/command.rs +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2020-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 . - -use crate::{ - chain_spec, - cli::{Cli, RelayChainCli, Subcommand}, - service::new_partial, -}; -use cumulus_primitives_core::ParaId; -use frame_benchmarking_cli::BenchmarkCmd; -use log::info; -use rialto_parachain_runtime::{Block, RuntimeApi}; -use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, - NetworkParams, Result, SharedParams, SubstrateCli, -}; -use sc_service::config::{BasePath, PrometheusConfig}; -use std::net::SocketAddr; - -fn load_spec( - id: &str, - para_id: ParaId, -) -> std::result::Result, String> { - Ok(match id { - "dev" => Box::new(chain_spec::development_config(para_id)), - "" | "local" => Box::new(chain_spec::local_testnet_config(para_id)), - path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), - }) -} - -impl SubstrateCli for Cli { - fn impl_name() -> String { - "Parachain Collator Template".into() - } - - fn impl_version() -> String { - env!("SUBSTRATE_CLI_IMPL_VERSION").into() - } - - fn description() -> String { - format!( - "Parachain Collator Template\n\nThe command-line arguments provided first will be \ - passed to the parachain node, while the arguments provided after -- will be passed \ - to the relaychain node.\n\n\ - {} [parachain-args] -- [relaychain-args]", - Self::executable_name() - ) - } - - fn author() -> String { - env!("CARGO_PKG_AUTHORS").into() - } - - fn support_url() -> String { - "https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into() - } - - fn copyright_start_year() -> i32 { - 2017 - } - - fn load_spec(&self, id: &str) -> std::result::Result, String> { - load_spec(id, self.parachain_id.unwrap_or(2000).into()) - } -} - -impl SubstrateCli for RelayChainCli { - fn impl_name() -> String { - "Parachain Collator Template".into() - } - - fn impl_version() -> String { - env!("SUBSTRATE_CLI_IMPL_VERSION").into() - } - - fn description() -> String { - "Parachain Collator Template\n\nThe command-line arguments provided first will be \ - passed to the parachain node, while the arguments provided after -- will be passed \ - to the relaychain node.\n\n\ - parachain-collator [parachain-args] -- [relaychain-args]" - .into() - } - - fn author() -> String { - env!("CARGO_PKG_AUTHORS").into() - } - - fn support_url() -> String { - "https://github.com/substrate-developer-hub/substrate-parachain-template/issues/new".into() - } - - fn copyright_start_year() -> i32 { - 2017 - } - - fn load_spec(&self, id: &str) -> std::result::Result, String> { - polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id) - } -} - -macro_rules! construct_async_run { - (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ - let runner = $cli.create_runner($cmd)?; - runner.async_run(|$config| { - let $components = new_partial::< - RuntimeApi, - _ - >( - &$config, - crate::service::parachain_build_import_queue, - )?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) - }} -} - -/// Parse command line arguments into service configuration. -pub fn run() -> Result<()> { - let cli = Cli::from_args(); - sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom( - rialto_parachain_runtime::SS58Prefix::get() as u16, - )); - - match &cli.subcommand { - Some(Subcommand::BuildSpec(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, - Some(Subcommand::CheckBlock(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.import_queue)) - }) - }, - Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, config.database) - )) - }, - Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, config.chain_spec) - )) - }, - Some(Subcommand::ImportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| { - Ok(cmd.run(components.client, components.import_queue)) - }) - }, - Some(Subcommand::PurgeChain(cmd)) => { - let runner = cli.create_runner(cmd)?; - - runner.sync_run(|config| { - let polkadot_cli = RelayChainCli::new( - &config, - [RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()), - ); - - let polkadot_config = SubstrateCli::create_configuration( - &polkadot_cli, - &polkadot_cli, - config.tokio_handle.clone(), - ) - .map_err(|err| format!("Relay chain argument error: {err}"))?; - - cmd.run(config, polkadot_config) - }) - }, - Some(Subcommand::Revert(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run( - components.client, - components.backend, - None - ))) - }, - Some(Subcommand::ExportGenesisState(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| { - let partials = new_partial::( - &config, - crate::service::parachain_build_import_queue, - )?; - - cmd.run(&*config.chain_spec, &*partials.client) - }) - }, - Some(Subcommand::ExportGenesisWasm(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|_config| { - let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; - cmd.run(&*spec) - }) - }, - Some(Subcommand::Benchmark(cmd)) => { - let runner = cli.create_runner(cmd)?; - match cmd { - BenchmarkCmd::Pallet(cmd) => - if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) - } else { - println!( - "Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - ); - Ok(()) - }, - _ => Err("Unsupported benchmarking subcommand".into()), - } - }, - None => { - let runner = cli.create_runner(&cli.run.normalize())?; - let collator_options = cli.run.collator_options(); - - runner.run_node_until_exit(|config| async move { - let para_id = - chain_spec::Extensions::try_get(&*config.chain_spec).map(|e| e.para_id); - - let polkadot_cli = RelayChainCli::new( - &config, - [RelayChainCli::executable_name()].iter().chain(cli.relaychain_args.iter()), - ); - - let id = ParaId::from(cli.parachain_id.or(para_id).expect("Missing ParaId")); - - let polkadot_config = SubstrateCli::create_configuration( - &polkadot_cli, - &polkadot_cli, - config.tokio_handle.clone(), - ) - .map_err(|err| format!("Relay chain argument error: {err}"))?; - - info!("Parachain id: {:?}", id); - info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); - - crate::service::start_node(config, polkadot_config, collator_options, id) - .await - .map(|r| r.0) - .map_err(Into::into) - }) - }, - } -} - -impl DefaultConfigurationValues for RelayChainCli { - fn p2p_listen_port() -> u16 { - 30334 - } - - fn rpc_listen_port() -> u16 { - 9945 - } - - fn prometheus_listen_port() -> u16 { - 9616 - } -} - -impl CliConfiguration for RelayChainCli { - fn shared_params(&self) -> &SharedParams { - self.base.base.shared_params() - } - - fn import_params(&self) -> Option<&ImportParams> { - self.base.base.import_params() - } - - fn network_params(&self) -> Option<&NetworkParams> { - self.base.base.network_params() - } - - fn keystore_params(&self) -> Option<&KeystoreParams> { - self.base.base.keystore_params() - } - - fn base_path(&self) -> Result> { - Ok(self - .shared_params() - .base_path()? - .or_else(|| self.base_path.clone().map(Into::into))) - } - - fn rpc_addr(&self, default_listen_port: u16) -> Result> { - self.base.base.rpc_addr(default_listen_port) - } - - fn prometheus_config( - &self, - default_listen_port: u16, - chain_spec: &Box, - ) -> Result> { - self.base.base.prometheus_config(default_listen_port, chain_spec) - } - - fn init( - &self, - _support_url: &String, - _impl_version: &String, - _logger_hook: F, - _config: &sc_service::Configuration, - ) -> Result<()> - where - F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), - { - unreachable!("PolkadotCli is never initialized; qed"); - } - - fn chain_id(&self, is_dev: bool) -> Result { - let chain_id = self.base.base.chain_id(is_dev)?; - - Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) - } - - fn role(&self, is_dev: bool) -> Result { - self.base.base.role(is_dev) - } - - fn transaction_pool(&self, is_dev: bool) -> Result { - self.base.base.transaction_pool(is_dev) - } - - fn rpc_methods(&self) -> Result { - self.base.base.rpc_methods() - } - - fn rpc_max_connections(&self) -> Result { - self.base.base.rpc_max_connections() - } - - fn rpc_cors(&self, is_dev: bool) -> Result>> { - self.base.base.rpc_cors(is_dev) - } - - fn default_heap_pages(&self) -> Result> { - self.base.base.default_heap_pages() - } - - fn force_authoring(&self) -> Result { - self.base.base.force_authoring() - } - - fn disable_grandpa(&self) -> Result { - self.base.base.disable_grandpa() - } - - fn max_runtime_instances(&self) -> Result> { - self.base.base.max_runtime_instances() - } - - fn announce_block(&self) -> Result { - self.base.base.announce_block() - } - - fn telemetry_endpoints( - &self, - chain_spec: &Box, - ) -> Result> { - self.base.base.telemetry_endpoints(chain_spec) - } -} diff --git a/bin/rialto-parachain/node/src/lib.rs b/bin/rialto-parachain/node/src/lib.rs deleted file mode 100644 index 5dd2a8af861b1..0000000000000 --- a/bin/rialto-parachain/node/src/lib.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2020-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 . - -pub mod chain_spec; -#[allow(deprecated)] -pub mod service; diff --git a/bin/rialto-parachain/node/src/main.rs b/bin/rialto-parachain/node/src/main.rs deleted file mode 100644 index ca93efa067cc9..0000000000000 --- a/bin/rialto-parachain/node/src/main.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020-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 . - -//! Substrate Parachain Node Template CLI - -#![warn(missing_docs)] - -mod chain_spec; -#[macro_use] -#[allow(deprecated)] -mod service; -mod cli; -mod command; - -fn main() -> sc_cli::Result<()> { - command::run() -} diff --git a/bin/rialto-parachain/node/src/service.rs b/bin/rialto-parachain/node/src/service.rs deleted file mode 100644 index 86c5a7615901c..0000000000000 --- a/bin/rialto-parachain/node/src/service.rs +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2020-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 . - -//! Rialto parachain node service. -//! -//! The code is mostly copy of `polkadot-parachains/src/service.rs` file from Cumulus -//! repository with some parts removed. We have added two RPC extensions to the original -//! service: `pallet_transaction_payment_rpc::TransactionPaymentApi` and -//! `substrate_frame_rpc_system::SystemApi`. - -// std -use std::{sync::Arc, time::Duration}; - -// Local Runtime Types -use rialto_parachain_runtime::RuntimeApi; - -// Cumulus Imports -use cumulus_client_cli::CollatorOptions; -use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::{ - ParachainBlockImport as TParachainBlockImport, ParachainConsensus, -}; -use cumulus_client_network::RequireSecondedInBlockAnnounce; -use cumulus_client_service::{ - prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, -}; -use cumulus_primitives_core::ParaId; -use cumulus_relay_chain_interface::RelayChainInterface; -use sc_consensus::ImportQueue; -// Substrate Imports -use sc_executor::{ - HeapAllocStrategy, NativeElseWasmExecutor, NativeExecutionDispatch, WasmExecutor, - DEFAULT_HEAP_ALLOC_STRATEGY, -}; -use sc_network::{config::FullNetworkConfiguration, NetworkBlock}; -use sc_network_sync::SyncingService; -use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; -use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; -use sp_api::ConstructRuntimeApi; -use sp_keystore::KeystorePtr; -use sp_runtime::traits::BlakeTwo256; -use substrate_prometheus_endpoint::Registry; - -// Runtime type overrides -type BlockNumber = u32; -type Header = sp_runtime::generic::Header; -pub type Block = sp_runtime::generic::Block; - -type ParachainClient = - TFullClient>; -type ParachainBackend = TFullBackend; -type ParachainBlockImport = - TParachainBlockImport>, ParachainBackend>; - -pub type ParachainRuntimeExecutor = ExecutorDispatch; - -// Our native executor instance. -pub struct ExecutorDispatch; - -impl NativeExecutionDispatch for ExecutorDispatch { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - rialto_parachain_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - rialto_parachain_runtime::native_version() - } -} - -/// Starts a `ServiceBuilder` for a full service. -/// -/// Use this macro if you don't actually need the full service, but just the builder in order to -/// be able to perform chain operations. -#[allow(clippy::type_complexity)] -pub fn new_partial( - config: &Configuration, - build_import_queue: BIQ, -) -> Result< - PartialComponents< - ParachainClient, - ParachainBackend, - (), - sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool>, - (ParachainBlockImport, Option, Option), - >, - sc_service::Error, -> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder, - sc_client_api::StateBackendFor: sp_api::StateBackend, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, -{ - let telemetry = config - .telemetry_endpoints - .clone() - .filter(|x| !x.is_empty()) - .map(|endpoints| -> Result<_, sc_telemetry::Error> { - let worker = TelemetryWorker::new(16)?; - let telemetry = worker.handle().new_telemetry(endpoints); - Ok((worker, telemetry)) - }) - .transpose()?; - - let heap_pages = config - .default_heap_pages - .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); - let executor = - sc_executor::NativeElseWasmExecutor::::new_with_wasm_executor( - WasmExecutor::builder() - .with_execution_method(config.wasm_method) - .with_onchain_heap_alloc_strategy(heap_pages) - .with_offchain_heap_alloc_strategy(heap_pages) - .with_max_runtime_instances(config.max_runtime_instances) - .with_runtime_cache_size(config.runtime_cache_size) - .build(), - ); - - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; - let client = Arc::new(client); - - let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); - - let telemetry = telemetry.map(|(worker, telemetry)| { - task_manager.spawn_handle().spawn("telemetry", None, worker.run()); - telemetry - }); - - let transaction_pool = sc_transaction_pool::BasicPool::new_full( - config.transaction_pool.clone(), - config.role.is_authority().into(), - config.prometheus_registry(), - task_manager.spawn_essential_handle(), - client.clone(), - ); - - let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); - - let import_queue = build_import_queue( - client.clone(), - block_import.clone(), - config, - telemetry.as_ref().map(|telemetry| telemetry.handle()), - &task_manager, - )?; - - let params = PartialComponents { - backend, - client, - import_queue, - keystore_container, - task_manager, - transaction_pool, - select_chain: (), - other: (block_import, telemetry, telemetry_worker_handle), - }; - - Ok(params) -} - -/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. -/// -/// This is the actual implementation that is abstract over the executor and the runtime api. -#[sc_tracing::logging::prefix_logs_with("Parachain")] -async fn start_node_impl( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - id: ParaId, - rpc_ext_builder: RB, - build_import_queue: BIQ, - build_consensus: BIC, -) -> sc_service::error::Result<(TaskManager, Arc>)> -where - RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, - RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sp_api::Metadata - + sp_session::SessionKeys - + sp_api::ApiExt - + sp_offchain::OffchainWorkerApi - + sp_block_builder::BlockBuilder - + cumulus_primitives_core::CollectCollationInfo, - sc_client_api::StateBackendFor: sp_api::StateBackend, - RB: Fn( - sc_rpc_api::DenyUnsafe, - Arc>, - Arc>>, - ) -> Result, sc_service::Error> - + Send - + Clone - + 'static, - BIQ: FnOnce( - Arc>, - ParachainBlockImport, - &Configuration, - Option, - &TaskManager, - ) -> Result, sc_service::Error>, - BIC: FnOnce( - Arc>, - ParachainBlockImport, - Option<&Registry>, - Option, - &TaskManager, - Arc, - Arc>>, - Arc>, - KeystorePtr, - bool, - ) -> Result>, sc_service::Error>, -{ - let parachain_config = prepare_node_config(parachain_config); - - let params = new_partial::(¶chain_config, build_import_queue)?; - let (block_import, mut telemetry, telemetry_worker_handle) = params.other; - - let mut task_manager = params.task_manager; - let (relay_chain_interface, collator_key) = - cumulus_client_service::build_relay_chain_interface( - polkadot_config, - ¶chain_config, - telemetry_worker_handle, - &mut task_manager, - collator_options, - None, - ) - .await - .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; - - let client = params.client.clone(); - let backend = params.backend.clone(); - let block_announce_validator = - RequireSecondedInBlockAnnounce::new(relay_chain_interface.clone(), id); - - let force_authoring = parachain_config.force_authoring; - let validator = parachain_config.role.is_authority(); - let prometheus_registry = parachain_config.prometheus_registry().cloned(); - let transaction_pool = params.transaction_pool.clone(); - let import_queue_service = params.import_queue.service(); - let net_config = FullNetworkConfiguration::new(¶chain_config.network); - - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = - sc_service::build_network(sc_service::BuildNetworkParams { - config: ¶chain_config, - net_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - spawn_handle: task_manager.spawn_handle(), - import_queue: params.import_queue, - block_announce_validator_builder: Some(Box::new(|_| { - Box::new(block_announce_validator) - })), - warp_sync_params: None, - block_relay: None, - })?; - - let rpc_client = client.clone(); - let rpc_transaction_pool = transaction_pool.clone(); - let rpc_extensions_builder = Box::new(move |deny_unsafe, _| { - rpc_ext_builder(deny_unsafe, rpc_client.clone(), rpc_transaction_pool.clone()) - }); - - sc_service::spawn_tasks(sc_service::SpawnTasksParams { - rpc_builder: rpc_extensions_builder.clone(), - client: client.clone(), - transaction_pool: transaction_pool.clone(), - task_manager: &mut task_manager, - config: parachain_config, - keystore: params.keystore_container.keystore(), - backend: backend.clone(), - network: network.clone(), - sync_service: sync_service.clone(), - system_rpc_tx, - tx_handler_controller, - telemetry: telemetry.as_mut(), - })?; - - let announce_block = { - let sync_service = sync_service.clone(); - Arc::new(move |hash, data| sync_service.announce_block(hash, data)) - }; - - let relay_chain_slot_duration = Duration::from_secs(6); - - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; - - if validator { - let parachain_consensus = build_consensus( - client.clone(), - block_import, - prometheus_registry.as_ref(), - telemetry.as_ref().map(|t| t.handle()), - &task_manager, - relay_chain_interface.clone(), - transaction_pool, - sync_service.clone(), - params.keystore_container.keystore(), - force_authoring, - )?; - - let spawner = task_manager.spawn_handle(); - - let params = StartCollatorParams { - para_id: id, - block_status: client.clone(), - announce_block, - client: client.clone(), - task_manager: &mut task_manager, - relay_chain_interface, - spawner, - parachain_consensus, - import_queue: import_queue_service, - collator_key: collator_key.expect("Command line arguments do not allow this. qed"), - relay_chain_slot_duration, - recovery_handle: Box::new(overseer_handle), - sync_service, - }; - - start_collator(params).await?; - } else { - let params = StartFullNodeParams { - client: client.clone(), - announce_block, - task_manager: &mut task_manager, - para_id: id, - relay_chain_interface, - relay_chain_slot_duration, - import_queue: import_queue_service, - recovery_handle: Box::new(overseer_handle), - sync_service, - }; - - start_full_node(params)?; - } - - start_network.start_network(); - - Ok((task_manager, client)) -} - -/// Build the import queue for the the parachain runtime. -#[allow(clippy::type_complexity)] -pub fn parachain_build_import_queue( - client: Arc>, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry: Option, - task_manager: &TaskManager, -) -> Result, sc_service::Error> { - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, - }) - .map_err(Into::into) -} - -/// Start a normal parachain node. -pub async fn start_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - id: ParaId, -) -> sc_service::error::Result<(TaskManager, Arc>)> { - start_node_impl::( - parachain_config, - polkadot_config, - collator_options, - id, - |_deny_unsafe, client, pool| { - use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; - use sc_rpc::DenyUnsafe; - use substrate_frame_rpc_system::{System, SystemApiServer}; - - let mut io = jsonrpsee::RpcModule::new(()); - let map_err = |e| sc_service::Error::Other(format!("{e}")); - io.merge(System::new(client.clone(), pool, DenyUnsafe::No).into_rpc()) - .map_err(map_err)?; - io.merge(TransactionPayment::new(client).into_rpc()).map_err(map_err)?; - Ok(io) - }, - parachain_build_import_queue, - |client, - block_import, - prometheus_registry, - telemetry, - task_manager, - relay_chain_interface, - transaction_pool, - sync_oracle, - keystore, - force_authoring| { - let client2 = client.clone(); - let block_import2 = block_import; - let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - - let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( - task_manager.spawn_handle(), - client, - transaction_pool, - prometheus_registry, - telemetry.clone(), - ); - - Ok(AuraConsensus::build::( - BuildAuraConsensusParams { - proposer_factory, - create_inherent_data_providers: move |_, (relay_parent, validation_data)| { - let relay_chain_interface = relay_chain_interface.clone(); - async move { - let parachain_inherent = - cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( - relay_parent, - &relay_chain_interface, - &validation_data, - id, - ).await; - let time = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *time, - slot_duration, - ); - - let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) - })?; - Ok((slot, time, parachain_inherent)) - } - }, - block_import: block_import2, - para_client: client2, - backoff_authoring_blocks: Option::<()>::None, - sync_oracle, - keystore, - force_authoring, - slot_duration, - // We got around 1000ms for proposing - block_proposal_slot_portion: SlotProportion::new(1f32 / 12f32), - telemetry, - max_block_proposal_slot_portion: None, - }, - )) - }, - ) - .await -} diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml deleted file mode 100644 index 0715e7a2927ae..0000000000000 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ /dev/null @@ -1,146 +0,0 @@ -[package] -name = "rialto-parachain-runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -repository = "https://github.com/paritytech/parity-bridges-common/" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[dependencies] -codec = { package = 'parity-scale-codec', version = '3.1.5', default-features = false, features = ['derive']} -hex-literal = "0.4" -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Bridge depedencies - -bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } -bp-messages = { path = "../../../primitives/messages", default-features = false } -bp-millau = { path = "../../../primitives/chain-millau", default-features = false } -bp-polkadot-core = { path = "../../../primitives/polkadot-core", default-features = false } -bp-relayers = { path = "../../../primitives/relayers", default-features = false } -bp-runtime = { path = "../../../primitives/runtime", default-features = false } -bp-rialto-parachain = { path = "../../../primitives/chain-rialto-parachain", default-features = false } -bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } -pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } -pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } - -# Substrate Dependencies -## Substrate Primitive Dependencies -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-consensus-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -## Substrate FRAME Dependencies -frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -## Substrate Pallet Dependencies -pallet-aura = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Cumulus Dependencies -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -parachain-info = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Polkadot Dependencies -polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[dev-dependencies] -bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } -static_assertions = "1.1" - -[features] -default = [ 'std' ] -runtime-benchmarks = [ - 'bridge-runtime-common/runtime-benchmarks', - 'frame-benchmarking', - 'frame-support/runtime-benchmarks', - 'frame-system-benchmarking/runtime-benchmarks', - 'frame-system/runtime-benchmarks', - 'pallet-balances/runtime-benchmarks', - 'pallet-bridge-grandpa/runtime-benchmarks', - 'pallet-bridge-messages/runtime-benchmarks', - 'pallet-bridge-relayers/runtime-benchmarks', - 'pallet-timestamp/runtime-benchmarks', - 'pallet-xcm/runtime-benchmarks', - 'sp-runtime/runtime-benchmarks', - 'xcm-builder/runtime-benchmarks', -] -std = [ - "bp-messages/std", - "bp-millau/std", - "bp-relayers/std", - "bp-rialto-parachain/std", - "bp-runtime/std", - "bridge-runtime-common/std", - "codec/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-xcm/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-primitives-core/std", - "cumulus-primitives-timestamp/std", - "frame-executive/std", - "frame-support/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "pallet-aura/std", - "pallet-balances/std", - "pallet-bridge-grandpa/std", - "pallet-bridge-messages/std", - "pallet-bridge-relayers/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-xcm/std", - "parachain-info/std", - "polkadot-parachain-primitives/std", - "scale-info/std", - "sp-api/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-inherents/std", - "sp-io/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-transaction-pool/std", - "sp-version/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] diff --git a/bin/rialto-parachain/runtime/build.rs b/bin/rialto-parachain/runtime/build.rs deleted file mode 100644 index 692e270bbbae3..0000000000000 --- a/bin/rialto-parachain/runtime/build.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 . - -use substrate_wasm_builder::WasmBuilder; - -fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .disable_runtime_version_section_check() - .build() -} diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs deleted file mode 100644 index e64932d1a443f..0000000000000 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ /dev/null @@ -1,975 +0,0 @@ -// 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 . - -//! The Rialto parachain runtime. This can be compiled with `#[no_std]`, ready for Wasm. -//! -//! Originally a copy of runtime from . - -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -use bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages; -use codec::{Decode, Encode}; -use cumulus_pallet_parachain_system::AnyRelayNumber; -use scale_info::TypeInfo; -use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT, DispatchInfoOf, SignedExtension}, - transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError}, - ApplyExtrinsicResult, -}; - -use sp_std::prelude::*; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; - -// A few exports that help ease life for downstream crates. -use bp_runtime::HeaderId; -pub use frame_support::{ - construct_runtime, - dispatch::DispatchClass, - match_types, parameter_types, - traits::{ConstBool, ConstU32, Everything, IsInVec, Nothing, Randomness}, - weights::{ - constants::{ - BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, - }, - IdentityFee, Weight, - }, - StorageValue, -}; -pub use frame_system::{Call as SystemCall, EnsureRoot}; -pub use pallet_balances::Call as BalancesCall; -pub use pallet_sudo::Call as SudoCall; -pub use pallet_timestamp::Call as TimestampCall; -pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use sp_runtime::{MultiAddress, Perbill, Permill}; - -pub use bp_rialto_parachain::{ - AccountId, Balance, BlockLength, BlockNumber, BlockWeights, Hash, Hasher as Hashing, Header, - Nonce, Signature, MAXIMUM_BLOCK_WEIGHT, -}; - -pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; -pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_xcm::Call as XcmCall; - -// Polkadot & XCM imports -use bridge_runtime_common::CustomNetworkId; -use pallet_xcm::XcmPassthrough; -use polkadot_parachain_primitives::primitives::Sibling; -use xcm::latest::prelude::*; -use xcm_builder::{ - AccountId32Aliases, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, - NativeAsset, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, -}; -use xcm_executor::{Config, XcmExecutor}; - -pub mod millau_messages; - -// generate signed extension that rejects obsolete bridge transactions -generate_bridge_reject_obsolete_headers_and_messages! { - RuntimeCall, AccountId, - // Grandpa - BridgeMillauGrandpa, - // Messages - BridgeMillauMessages -} - -/// Dummy signed extension that does nothing. -/// -/// We're using it to have the same set of signed extensions on all parachains with bridge pallets -/// deployed (bridge hubs and rialto parachain). -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct DummyBridgeRefundMillauMessages; - -impl SignedExtension for DummyBridgeRefundMillauMessages { - const IDENTIFIER: &'static str = "DummyBridgeRefundMillauMessages"; - type AccountId = AccountId; - type Call = RuntimeCall; - type AdditionalSigned = (); - type Pre = (); - - fn additional_signed(&self) -> Result { - Ok(()) - } - - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } -} - -/// The address format for describing accounts. -pub type Address = MultiAddress; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - BridgeRejectObsoleteHeadersAndMessages, - DummyBridgeRefundMillauMessages, -); -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; -/// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; -/// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; - -impl_opaque_keys! { - pub struct SessionKeys { - pub aura: Aura, - } -} - -/// This runtime version. -#[sp_version::runtime_version] -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("template-parachain"), - impl_name: create_runtime_str!("template-parachain"), - authoring_version: 1, - spec_version: 1, - impl_version: 0, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, - state_version: 0, -}; - -/// This determines the average expected block time that we are targeting. -/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. -/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked -/// up by `pallet_aura` to implement `fn slot_duration()`. -/// -/// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 12000; - -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES; - -// Time is measured by number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - -// Unit = the base number of indivisible units for balances -pub const UNIT: Balance = 1_000_000_000_000; -pub const MILLIUNIT: Balance = 1_000_000_000; -pub const MICROUNIT: Balance = 1_000_000; - -// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. -pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); - -/// The version information used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } -} - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const Version: RuntimeVersion = VERSION; - pub const SS58Prefix: u8 = 48; -} - -// Configure FRAME pallets to include in runtime. - -impl frame_system::Config for Runtime { - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = Hashing; - /// The header type. - type Block = Block; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The weight of database operations that the runtime can invoke. - type DbWeight = (); - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block & extrinsics weights: base values and limits. - type BlockWeights = BlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = BlockLength; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; -} - -impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the Unix epoch. - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: u128 = MILLIUNIT; - pub const TransferFee: u128 = MILLIUNIT; - pub const CreationFee: u128 = MILLIUNIT; - pub const TransactionByteFee: u128 = MICROUNIT; - pub const OperationalFeeMultiplier: u8 = 5; -} - -impl pallet_balances::Config for Runtime { - /// The type for recording an account's balance. - type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; -} - -impl pallet_transaction_payment::Config for Runtime { - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = OperationalFeeMultiplier; - type WeightToFee = IdentityFee; - type LengthToFee = IdentityFee; - type FeeMultiplierUpdate = (); - type RuntimeEvent = RuntimeEvent; -} - -impl pallet_sudo::Config for Runtime { - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_sudo::weights::SubstrateWeight; -} - -parameter_types! { - pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); -} - -impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; - type OutboundXcmpMessageSource = XcmpQueue; - type DmpMessageHandler = DmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; - type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = AnyRelayNumber; -} - -impl parachain_info::Config for Runtime {} - -impl cumulus_pallet_aura_ext::Config for Runtime {} - -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const RelayNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); - pub RelayOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); - pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); - /// The Millau network ID. - pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); - /// The RialtoParachain network ID. - pub const ThisNetwork: NetworkId = CustomNetworkId::RialtoParachain.as_network_id(); -} - -/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used -/// when determining ownership of accounts for asset transacting and when attempting to use XCM -/// `Transact` in order to determine the dispatch Origin. -pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the default `AccountId`. - ParentIsPreset, - // Sibling parachain origins convert to AccountId via the `ParaId::into`. - SiblingParachainConvertsVia, - // Straight up local `AccountId32` origins just alias directly to `AccountId`. - AccountId32Aliases, -); - -/// Means for transacting assets on this chain. -pub type LocalAssetTransactor = CurrencyAdapter< - // Use this currency: - Balances, - // Use this currency when it is a fungible asset matching the given location or name: - IsConcrete, - // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: - LocationToAccountId, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We don't track any teleports. - (), ->; - -/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, -/// ready for dispatching a transaction with XCM `Transact`. There is an `OriginKind` which can -/// biases the kind of local `Origin` it will become. -pub type XcmOriginToTransactDispatchOrigin = ( - // Sovereign account converter; this attempts to derive an `AccountId` from the origin location - // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for - // foreign chains who want to have a local sovereign account on this chain which they control. - SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when - // recognised. - RelayChainAsNative, - // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when - // recognised. - SiblingParachainAsNative, - // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a - // transaction from the Root origin. - ParentAsSuperuser, - // Native signed account converter; this just converts an `AccountId32` origin into a normal - // `Origin::Signed` origin of the same 32-byte value. - SignedAccountId32AsNative, - // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. - XcmPassthrough, -); - -// TODO: until https://github.com/paritytech/parity-bridges-common/issues/1417 is fixed (in either way), -// the following constant must match the similar constant in the Millau runtime. - -parameter_types! { - /// The amount of weight an XCM operation takes. We don't care much about those values as we're on testnet. - pub const UnitWeightCost: Weight = Weight::from_parts(1_000_000, 1024); - // One UNIT buys 1 second of weight. - pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), UNIT); - pub const MaxInstructions: u32 = 100; - pub const MaxAuthorities: u32 = 100_000; - pub MaxAssetsIntoHolding: u32 = 64; -} - -match_types! { - pub type ParentOrParentsUnitPlurality: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) } - }; -} - -pub type Barrier = TakeWeightCredit; - -/// Dispatches received XCM messages from other chain. -pub type OnRialtoParachainBlobDispatcher = - xcm_builder::BridgeBlobDispatcher; - -/// XCM weigher type. -pub type XcmWeigher = FixedWeightBounds; - -pub struct XcmConfig; -impl Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = (); - type AssetTransactor = LocalAssetTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = NativeAsset; - type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of UNIT - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = XcmWeigher; - type Trader = UsingComponents, RelayLocation, AccountId, Balances, ()>; - type ResponseHandler = PolkadotXcm; - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = (); - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); - type FeeManager = (); - type MessageExporter = millau_messages::ToMillauBlobExporter; - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = Nothing; -} - -/// No local origins on this chain are allowed to dispatch XCM sends/executions. -pub type LocalOriginToLocation = SignedToAccountId32; - -/// The XCM router. We are not sending messages to sibling/parent/child chains here. -pub type XcmRouter = (); - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = None; -} - -impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; - type Weigher = XcmWeigher; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = (); - type MaxLockers = frame_support::traits::ConstU32<8>; - type UniversalLocation = UniversalLocation; - type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type AdminOrigin = frame_system::EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); -} - -impl cumulus_pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; -} - -impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; - type ControllerOrigin = EnsureRoot; - type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); - type PriceForSiblingDelivery = (); -} - -impl cumulus_pallet_dmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = frame_system::EnsureRoot; -} - -impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = MaxAuthorities; - type AllowMultipleBlocksPerSlot = ConstBool; -} - -impl pallet_bridge_relayers::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Reward = Balance; - type PaymentProcedure = - bp_relayers::PayRewardFromAccount, AccountId>; - type StakeAndSlash = (); - type WeightInfo = (); -} - -pub type MillauGrandpaInstance = (); -impl pallet_bridge_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BridgedChain = bp_millau::Millau; - type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; - type HeadersToKeep = ConstU32<{ bp_millau::DAYS as u32 }>; - type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; -} - -parameter_types! { - pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; - pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - pub const RootAccountForPayments: Option = None; - pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; - pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[millau_messages::XCM_LANE]; -} - -/// Instance of the messages pallet used to relay messages to/from Millau chain. -pub type WithMillauMessagesInstance = (); - -impl pallet_bridge_messages::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type ActiveOutboundLanes = ActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; - type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - - type MaximalOutboundPayloadSize = crate::millau_messages::ToMillauMaximalOutboundPayloadSize; - type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; - - type InboundPayload = crate::millau_messages::FromMillauMessagePayload; - type InboundRelayer = bp_millau::AccountId; - type DeliveryPayments = (); - - type TargetHeaderChain = crate::millau_messages::MillauAsTargetHeaderChain; - type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - WithMillauMessagesInstance, - frame_support::traits::ConstU128<100_000>, - >; - type OnMessagesDelivered = (); - - type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; - type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; - type BridgedChainId = BridgedChainId; -} - -// Create the runtime by composing the FRAME pallets that were previously configured. -construct_runtime!( - pub enum Runtime { - System: frame_system::{Pallet, Call, Storage, Config, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, - - ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Storage, Inherent, Event} = 20, - ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21, - - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 30, - - Aura: pallet_aura::{Pallet, Config}, - AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, - - // XCM helpers. - XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 50, - PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin} = 51, - CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 52, - DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 53, - - // Millau bridge modules. - BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, - BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - } -); - -impl_runtime_apis! { - impl sp_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block) - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl sp_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Runtime::metadata().into()) - } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } - } - - impl sp_block_builder::BlockBuilder for Runtime { - fn apply_extrinsic( - extrinsic: ::Extrinsic, - ) -> ApplyExtrinsicResult { - Executive::apply_extrinsic(extrinsic) - } - - fn finalize_block() -> ::Header { - Executive::finalize_block() - } - - fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents( - block: Block, - data: sp_inherents::InherentData, - ) -> sp_inherents::CheckInherentsResult { - data.check_extrinsics(&block) - } - } - - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction( - source: TransactionSource, - tx: ::Extrinsic, - block_hash: ::Hash, - ) -> TransactionValidity { - Executive::validate_transaction(source, tx, block_hash) - } - } - - impl sp_offchain::OffchainWorkerApi for Runtime { - fn offchain_worker(header: &::Header) { - Executive::offchain_worker(header) - } - } - - impl sp_session::SessionKeys for Runtime { - fn decode_session_keys( - encoded: Vec, - ) -> Option, KeyTypeId)>> { - SessionKeys::decode_into_raw_public_keys(&encoded) - } - - fn generate_session_keys(seed: Option>) -> Vec { - SessionKeys::generate(seed) - } - } - - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) - } - - fn authorities() -> Vec { - Aura::authorities().to_vec() - } - } - - impl cumulus_primitives_core::CollectCollationInfo for Runtime { - fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { - ParachainSystem::collect_collation_info(header) - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Nonce { - System::account_nonce(account) - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { - fn query_info( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - fn query_fee_details( - uxt: ::Extrinsic, - len: u32, - ) -> pallet_transaction_payment::FeeDetails { - TransactionPayment::query_fee_details(uxt, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - impl bp_millau::MillauFinalityApi for Runtime { - fn best_finalized() -> Option> { - BridgeMillauGrandpa::best_finalized() - } - - fn synced_headers_grandpa_info( - ) -> Vec> { - BridgeMillauGrandpa::synced_headers_grandpa_info() - } - } - - impl bp_millau::ToMillauOutboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - begin: bp_messages::MessageNonce, - end: bp_messages::MessageNonce, - ) -> Vec { - bridge_runtime_common::messages_api::outbound_message_details::< - Runtime, - WithMillauMessagesInstance, - >(lane, begin, end) - } - } - - impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, - ) -> Vec { - bridge_runtime_common::messages_api::inbound_message_details::< - Runtime, - WithMillauMessagesInstance, - >(lane, messages) - } - } - - #[cfg(feature = "runtime-benchmarks")] - impl frame_benchmarking::Benchmark for Runtime { - fn benchmark_metadata(_extra: bool) -> ( - Vec, - Vec, - ) { - todo!("TODO: fix or remove") - } - - fn dispatch_benchmark( - config: frame_benchmarking::BenchmarkConfig - ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark}; - use frame_support::traits::TrackedStorageKey; - - use frame_system_benchmarking::Pallet as SystemBench; - impl frame_system_benchmarking::Config for Runtime {} - - let whitelist: Vec = vec![ - // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), - // Total Issuance - hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), - // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), - // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), - // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), - ]; - - let mut batches = Vec::::new(); - let params = (&config, &whitelist); - - add_benchmark!(params, batches, frame_system, SystemBench::); - add_benchmark!(params, batches, pallet_balances, Balances); - add_benchmark!(params, batches, pallet_timestamp, Timestamp); - - Ok(batches) - } - } -} - -struct CheckInherents; - -impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { - fn check_inherents( - block: &Block, - relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, - ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = relay_state_proof - .read_slot() - .expect("Could not read the relay chain slot from the proof"); - - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); - - inherent_data.check_extrinsics(block) - } -} - -cumulus_pallet_parachain_system::register_validate_block!( - Runtime = Runtime, - BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, - CheckInherents = CheckInherents, -); - -#[cfg(test)] -mod tests { - use super::*; - use crate::millau_messages::{FromMillauMessageDispatch, XCM_LANE}; - use bp_messages::{ - target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - LaneId, MessageKey, - }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; - use codec::Encode; - use pallet_bridge_messages::OutboundLanes; - use sp_runtime::{generic::Era, traits::Zero}; - use xcm_executor::XcmExecutor; - - fn new_test_ext() -> sp_io::TestExternalities { - sp_io::TestExternalities::new( - frame_system::GenesisConfig::::default().build_storage().unwrap(), - ) - } - - fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm { - vec![ExportMessage { - network: destination, - destination: destination.into(), - xcm: vec![Instruction::Trap(42)].into(), - }] - .into() - } - - #[test] - fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { - new_test_ext().execute_with(|| { - // ensure that the there are no messages queued - assert_eq!( - OutboundLanes::::get(XCM_LANE) - .latest_generated_nonce, - 0, - ); - - // export message instruction "sends" message to Rialto - XcmExecutor::::execute_xcm_in_credit( - Here, - prepare_outbound_xcm_message(MillauNetwork::get()), - Default::default(), - Weight::MAX, - Weight::MAX, - ) - .ensure_complete() - .expect("runtime configuration must be correct"); - - // ensure that the message has been queued - assert_eq!( - OutboundLanes::::get(XCM_LANE) - .latest_generated_nonce, - 1, - ); - }) - } - - fn prepare_inbound_bridge_message() -> DispatchMessage> { - let xcm = xcm::VersionedXcm::::V3(vec![Instruction::Trap(42)].into()); - let location = - xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); - // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor - // or public fields, so just tuple - let bridge_message = (location, xcm).encode(); - DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok(bridge_message) }, - } - } - - #[test] - fn xcm_messages_from_millau_are_dispatched() { - new_test_ext().execute_with(|| { - let incoming_message = prepare_inbound_bridge_message(); - - // we care only about handing message to the XCM dispatcher, so we don't care about its - // actual dispatch - let dispatch_result = FromMillauMessageDispatch::dispatch(incoming_message); - assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), - )); - }); - } - - #[test] - fn ensure_signed_extension_definition_is_correct() { - use bp_polkadot_core::SuffixedCommonSignedExtensionExt; - - sp_io::TestExternalities::default().execute_with(|| { - frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); - let payload: SignedExtra = ( - frame_system::CheckNonZeroSender::new(), - frame_system::CheckSpecVersion::new(), - frame_system::CheckTxVersion::new(), - frame_system::CheckGenesis::new(), - frame_system::CheckEra::from(Era::Immortal), - frame_system::CheckNonce::from(10), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(10), - BridgeRejectObsoleteHeadersAndMessages, - DummyBridgeRefundMillauMessages, - ); - let indirect_payload = bp_rialto_parachain::SignedExtension::from_params( - VERSION.spec_version, - VERSION.transaction_version, - bp_runtime::TransactionEra::Immortal, - System::block_hash(BlockNumber::zero()), - 10, - 10, - (((), ()), ((), ())), - ); - assert_eq!(payload.encode(), indirect_payload.encode()); - assert_eq!( - payload.additional_signed().unwrap().encode(), - indirect_payload.additional_signed().unwrap().encode() - ) - }); - } -} diff --git a/bin/rialto-parachain/runtime/src/millau_messages.rs b/bin/rialto-parachain/runtime/src/millau_messages.rs deleted file mode 100644 index b75a3d520b78a..0000000000000 --- a/bin/rialto-parachain/runtime/src/millau_messages.rs +++ /dev/null @@ -1,206 +0,0 @@ -// 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 . - -//! Everything required to serve Millau <-> RialtoParachain messages. - -// TODO: this is almost exact copy of `millau_messages.rs` from Rialto runtime. -// Should be extracted to a separate crate and reused here. - -use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance}; - -use bp_messages::LaneId; -use bridge_runtime_common::{ - messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, - }, - messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, -}; -use frame_support::{parameter_types, weights::Weight}; -use sp_runtime::RuntimeDebug; -use xcm::latest::prelude::*; -use xcm_builder::HaulBlobExporter; - -/// Default lane that is used to send messages to Millau. -pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::UnitWeightCost::get().saturating_mul(2); - -parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; - /// Lane used by the with-Millau bridge. - pub MullauSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); - - /// Dummy message used in configuration. - pub DummyXcmMessage: Xcm<()> = Xcm::new(); -} - -/// Message payload for RialtoParachain -> Millau messages. -pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; - -/// Message verifier for RialtoParachain -> Millau messages. -pub type ToMillauMessageVerifier = - messages::source::FromThisChainMessageVerifier; - -/// Message payload for Millau -> RialtoParachain messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; - -/// Call-dispatch based message dispatch for Millau -> RialtoParachain messages. -pub type FromMillauMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::OnRialtoParachainBlobDispatcher, - (), - (), - >; - -/// Messages proof for Millau -> RialtoParachain messages. -pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; - -/// Messages delivery proof for RialtoParachain -> Millau messages. -pub type ToMillauMessagesDeliveryProof = - messages::source::FromBridgedChainMessagesDeliveryProof; - -/// Maximal outbound payload size of Rialto -> Millau messages. -pub type ToMillauMaximalOutboundPayloadSize = - messages::source::FromThisChainMaximalOutboundPayloadSize; - -/// Millau <-> RialtoParachain message bridge. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct WithMillauMessageBridge; - -impl MessageBridge for WithMillauMessageBridge { - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = - bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; - - type ThisChain = RialtoParachain; - type BridgedChain = Millau; - type BridgedHeaderChain = - pallet_bridge_grandpa::GrandpaChainHeaders; -} - -/// RialtoParachain chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct RialtoParachain; - -impl messages::UnderlyingChainProvider for RialtoParachain { - type Chain = bp_rialto_parachain::RialtoParachain; -} - -impl messages::ThisChainWithMessages for RialtoParachain { - type RuntimeOrigin = RuntimeOrigin; -} - -/// Millau chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct Millau; -/// Millau as source header chain. -pub type MillauAsSourceHeaderChain = SourceHeaderChainAdapter; -/// Millau as target header chain. -pub type MillauAsTargetHeaderChain = TargetHeaderChainAdapter; - -impl messages::UnderlyingChainProvider for Millau { - type Chain = bp_millau::Millau; -} - -impl messages::BridgedChainWithMessages for Millau {} - -/// Export XCM messages to be relayed to Millau. -pub type ToMillauBlobExporter = - HaulBlobExporter, crate::MillauNetwork, ()>; - -/// To-Millau XCM hauler. -pub struct ToMillauXcmBlobHauler; - -impl XcmBlobHauler for ToMillauXcmBlobHauler { - type Runtime = Runtime; - type MessagesInstance = WithMillauMessagesInstance; - type SenderAndLane = MullauSenderAndLane; - - type ToSourceChainSender = crate::XcmRouter; - type CongestedMessage = DummyXcmMessage; - type UncongestedMessage = DummyXcmMessage; -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; - use bridge_runtime_common::{ - assert_complete_bridge_types, - integrity::{ - assert_complete_bridge_constants, check_message_lane_weights, - AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, - AssertCompleteBridgeConstants, - }, - }; - - #[test] - fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::< - bp_rialto_parachain::RialtoParachain, - Runtime, - WithMillauMessagesInstance, - >( - bp_millau::EXTRA_STORAGE_PROOF_SIZE, - bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - false, - ); - } - - #[test] - fn ensure_bridge_integrity() { - assert_complete_bridge_types!( - runtime: Runtime, - with_bridged_chain_grandpa_instance: MillauGrandpaInstance, - with_bridged_chain_messages_instance: WithMillauMessagesInstance, - bridge: WithMillauMessageBridge, - this_chain: bp_rialto_parachain::RialtoParachain, - bridged_chain: bp_millau::Millau, - ); - - assert_complete_bridge_constants::< - Runtime, - MillauGrandpaInstance, - WithMillauMessagesInstance, - WithMillauMessageBridge, - >(AssertCompleteBridgeConstants { - this_chain_constants: AssertChainConstants { - block_length: bp_rialto_parachain::BlockLength::get(), - block_weights: bp_rialto_parachain::BlockWeights::get(), - }, - messages_pallet_constants: AssertBridgeMessagesPalletConstants { - max_unrewarded_relayers_in_bridged_confirmation_tx: - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - max_unconfirmed_messages_in_bridged_confirmation_tx: - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - bridged_chain_id: bp_runtime::MILLAU_CHAIN_ID, - }, - pallet_names: AssertBridgePalletNames { - with_this_chain_messages_pallet_name: - bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME, - with_bridged_chain_grandpa_pallet_name: bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME, - with_bridged_chain_messages_pallet_name: - bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, - }, - }); - } -} diff --git a/bin/rialto/node/Cargo.toml b/bin/rialto/node/Cargo.toml deleted file mode 100644 index b2d54e5160983..0000000000000 --- a/bin/rialto/node/Cargo.toml +++ /dev/null @@ -1,61 +0,0 @@ -[[bin]] -name = "rialto-bridge-node-execute-worker" -path = "src/workers/execute-worker.rs" - -[[bin]] -name = "rialto-bridge-node-prepare-worker" -path = "src/workers/prepare-worker.rs" - -[package] -name = "rialto-bridge-node" -description = "Substrate node compatible with Rialto runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -build = "build.rs" -repository = "https://github.com/paritytech/parity-bridges-common/" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -clap = { version = "4.4.8", features = ["derive"] } -serde_json = "1.0.108" - -# Bridge dependencies - -rialto-runtime = { path = "../runtime" } - -# Substrate Dependencies - -sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -node-inspect = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master"} -sc-executor = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sc-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -# Polkadot Dependencies -polkadot-node-core-pvf = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-node-core-pvf-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-node-core-pvf-execute-worker = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-node-core-pvf-prepare-worker = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-service = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = [ "full-node" ] } - -[build-dependencies] -substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[features] -default = [] -runtime-benchmarks = [ - "polkadot-service/runtime-benchmarks", - "rialto-runtime/runtime-benchmarks", -] diff --git a/bin/rialto/node/build.rs b/bin/rialto/node/build.rs deleted file mode 100644 index d9b50049e2628..0000000000000 --- a/bin/rialto/node/build.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 . - -use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; - -fn main() { - generate_cargo_keys(); - - rerun_if_git_head_changed(); -} diff --git a/bin/rialto/node/src/chain_spec.rs b/bin/rialto/node/src/chain_spec.rs deleted file mode 100644 index 6d1180d12a985..0000000000000 --- a/bin/rialto/node/src/chain_spec.rs +++ /dev/null @@ -1,282 +0,0 @@ -// 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 . - -use polkadot_primitives::v6::{AssignmentId, ValidatorId}; -use rialto_runtime::{ - AccountId, BabeConfig, BalancesConfig, BeefyConfig, BridgeMillauMessagesConfig, - ConfigurationConfig, GrandpaConfig, RuntimeGenesisConfig, SessionConfig, SessionKeys, - Signature, SudoConfig, SystemConfig, WASM_BINARY, -}; -use serde_json::json; -use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_consensus_babe::AuthorityId as BabeId; -use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId; -use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{sr25519, Pair, Public}; -use sp_runtime::traits::{IdentifyAccount, Verify}; - -/// "Names" of the authorities accounts at local testnet. -const LOCAL_AUTHORITIES_ACCOUNTS: [&str; 5] = ["Alice", "Bob", "Charlie", "Dave", "Eve"]; -/// "Names" of the authorities accounts at development testnet. -const DEV_AUTHORITIES_ACCOUNTS: [&str; 1] = [LOCAL_AUTHORITIES_ACCOUNTS[0]]; -/// "Names" of all possible authorities accounts. -const ALL_AUTHORITIES_ACCOUNTS: [&str; 5] = LOCAL_AUTHORITIES_ACCOUNTS; -/// "Name" of the `sudo` account. -const SUDO_ACCOUNT: &str = "Sudo"; -/// "Name" of the account, which owns the with-Millau messages pallet. -const MILLAU_MESSAGES_PALLET_OWNER: &str = "Millau.MessagesOwner"; - -/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. -pub type ChainSpec = - sc_service::GenericChainSpec; - -/// The chain specification option. This is expected to come in from the CLI and -/// is little more than one of a number of alternatives which can easily be converted -/// from a string (`--chain=...`) into a `ChainSpec`. -#[derive(Clone, Debug)] -pub enum Alternative { - /// Whatever the current runtime is, with just Alice as an auth. - Development, - /// Whatever the current runtime is, with simple Alice/Bob/Charlie/Dave/Eve auths. - LocalTestnet, -} - -/// Helper function to generate a crypto pair from seed -pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{seed}"), None) - .expect("static values are valid; qed") - .public() -} - -type AccountPublic = ::Signer; - -/// Helper function to generate an account ID from seed -pub fn get_account_id_from_seed(seed: &str) -> AccountId -where - AccountPublic: From<::Public>, -{ - AccountPublic::from(get_from_seed::(seed)).into_account() -} - -/// Helper function to generate authority keys. -pub fn get_authority_keys_from_seed( - s: &str, -) -> (AccountId, BabeId, BeefyId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) { - ( - get_account_id_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - get_from_seed::(s), - ) -} - -impl Alternative { - /// Get an actual chain config from one of the alternatives. - pub(crate) fn load(self) -> ChainSpec { - let properties = Some( - json!({ - "tokenDecimals": 9, - "tokenSymbol": "RLT" - }) - .as_object() - .expect("Map given; qed") - .clone(), - ); - match self { - Alternative::Development => ChainSpec::from_genesis( - "Rialto Development", - "rialto_dev", - sc_service::ChainType::Development, - || { - testnet_genesis( - DEV_AUTHORITIES_ACCOUNTS - .into_iter() - .map(get_authority_keys_from_seed) - .collect(), - get_account_id_from_seed::(SUDO_ACCOUNT), - endowed_accounts(), - true, - ) - }, - vec![], - None, - None, - None, - properties, - Default::default(), - ), - Alternative::LocalTestnet => ChainSpec::from_genesis( - "Rialto Local", - "rialto_local", - sc_service::ChainType::Local, - || { - testnet_genesis( - LOCAL_AUTHORITIES_ACCOUNTS - .into_iter() - .map(get_authority_keys_from_seed) - .collect(), - get_account_id_from_seed::(SUDO_ACCOUNT), - endowed_accounts(), - true, - ) - }, - vec![], - None, - None, - None, - properties, - Default::default(), - ), - } - } -} - -/// We're using the same set of endowed accounts on all Millau chains (dev/local) to make -/// sure that all accounts, required for bridge to be functional (e.g. relayers fund account, -/// accounts used by relayers in our test deployments, accounts used for demonstration -/// purposes), are all available on these chains. -fn endowed_accounts() -> Vec { - let all_authorities = ALL_AUTHORITIES_ACCOUNTS.iter().flat_map(|x| { - [ - get_account_id_from_seed::(x), - get_account_id_from_seed::(&format!("{x}//stash")), - ] - }); - vec![ - // Sudo account - get_account_id_from_seed::(SUDO_ACCOUNT), - // Regular (unused) accounts - get_account_id_from_seed::("Ferdie"), - get_account_id_from_seed::("Ferdie//stash"), - // Accounts, used by Rialto<>Millau bridge - get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER), - get_account_id_from_seed::("Millau.HeadersAndMessagesRelay"), - get_account_id_from_seed::("Millau.OutboundMessagesRelay.Lane00000001"), - get_account_id_from_seed::("Millau.InboundMessagesRelay.Lane00000001"), - get_account_id_from_seed::("Millau.MessagesSender"), - ] - .into_iter() - .chain(all_authorities) - .collect() -} - -fn session_keys( - babe: BabeId, - beefy: BeefyId, - grandpa: GrandpaId, - para_validator: ValidatorId, - para_assignment: AssignmentId, - authority_discovery: AuthorityDiscoveryId, -) -> SessionKeys { - SessionKeys { babe, beefy, grandpa, para_validator, para_assignment, authority_discovery } -} - -fn testnet_genesis( - initial_authorities: Vec<( - AccountId, - BabeId, - BeefyId, - GrandpaId, - ValidatorId, - AssignmentId, - AuthorityDiscoveryId, - )>, - root_key: AccountId, - endowed_accounts: Vec, - _enable_println: bool, -) -> RuntimeGenesisConfig { - RuntimeGenesisConfig { - system: SystemConfig { - code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(), - ..Default::default() - }, - balances: BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), - }, - babe: BabeConfig { - authorities: Vec::new(), - epoch_config: Some(rialto_runtime::BABE_GENESIS_EPOCH_CONFIG), - ..Default::default() - }, - beefy: BeefyConfig::default(), - grandpa: GrandpaConfig { authorities: Vec::new(), ..Default::default() }, - sudo: SudoConfig { key: Some(root_key) }, - session: SessionConfig { - keys: initial_authorities - .iter() - .map(|x| { - ( - x.0.clone(), - x.0.clone(), - session_keys( - x.1.clone(), - x.2.clone(), - x.3.clone(), - x.4.clone(), - x.5.clone(), - x.6.clone(), - ), - ) - }) - .collect::>(), - }, - authority_discovery: Default::default(), - hrmp: Default::default(), - // this configuration is exact copy of configuration from Polkadot repo - // (see /node/service/src/chain_spec.rs:default_parachains_host_configuration) - configuration: ConfigurationConfig { - config: polkadot_runtime_parachains::configuration::HostConfiguration { - validation_upgrade_cooldown: 2u32, - validation_upgrade_delay: 2, - code_retention_period: 1200, - max_code_size: polkadot_primitives::v6::MAX_CODE_SIZE, - max_pov_size: polkadot_primitives::v6::MAX_POV_SIZE, - max_head_data_size: 32 * 1024, - group_rotation_frequency: 20, - max_upward_queue_count: 8, - max_upward_queue_size: 1024 * 1024, - max_downward_message_size: 1024 * 1024, - max_upward_message_size: 50 * 1024, - max_upward_message_num_per_candidate: 5, - hrmp_sender_deposit: 0, - hrmp_recipient_deposit: 0, - hrmp_channel_max_capacity: 8, - hrmp_channel_max_total_size: 8 * 1024, - hrmp_max_parachain_inbound_channels: 4, - hrmp_channel_max_message_size: 1024 * 1024, - hrmp_max_parachain_outbound_channels: 4, - hrmp_max_message_num_per_candidate: 5, - dispute_period: 6, - no_show_slots: 2, - n_delay_tranches: 25, - needed_approvals: 2, - relay_vrf_modulo_samples: 2, - zeroth_delay_tranche_width: 0, - minimum_validation_upgrade_delay: 5, - ..Default::default() - }, - }, - paras: Default::default(), - bridge_millau_messages: BridgeMillauMessagesConfig { - owner: Some(get_account_id_from_seed::(MILLAU_MESSAGES_PALLET_OWNER)), - ..Default::default() - }, - xcm_pallet: Default::default(), - } -} diff --git a/bin/rialto/node/src/cli.rs b/bin/rialto/node/src/cli.rs deleted file mode 100644 index 521f2268bdc5e..0000000000000 --- a/bin/rialto/node/src/cli.rs +++ /dev/null @@ -1,84 +0,0 @@ -// 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 . - -use clap::Parser; -use sc_cli::RunCmd; - -#[derive(Debug, Parser)] -pub struct Cli { - #[structopt(subcommand)] - pub subcommand: Option, - - #[structopt(flatten)] - pub run: RunCmd, -} - -/// Possible subcommands of the main binary. -#[derive(Debug, Parser)] -#[allow(clippy::large_enum_variant)] -pub enum Subcommand { - /// Key management CLI utilities - #[clap(subcommand)] - Key(sc_cli::KeySubcommand), - - /// Verify a signature for a message, provided on `STDIN`, with a given (public or secret) key. - Verify(sc_cli::VerifyCmd), - - /// Generate a seed that provides a vanity address. - Vanity(sc_cli::VanityCmd), - - /// Sign a message, with a given (secret) key. - Sign(sc_cli::SignCmd), - - /// Build a chain specification. - BuildSpec(sc_cli::BuildSpecCmd), - - /// Validate blocks. - CheckBlock(sc_cli::CheckBlockCmd), - - /// Export blocks. - ExportBlocks(sc_cli::ExportBlocksCmd), - - /// Export the state of a given block into a chain spec. - ExportState(sc_cli::ExportStateCmd), - - /// Import blocks. - ImportBlocks(sc_cli::ImportBlocksCmd), - - /// Remove the whole chain. - PurgeChain(sc_cli::PurgeChainCmd), - - /// Revert the chain to a previous state. - Revert(sc_cli::RevertCmd), - - /// Inspect blocks or extrinsics. - Inspect(node_inspect::cli::InspectCmd), - - /// Benchmark runtime pallets. - #[command(subcommand)] - Benchmark(frame_benchmarking_cli::BenchmarkCmd), -} - -/// Validation worker command. -#[derive(Debug, Parser)] -pub struct ValidationWorkerCommand { - /// The path to the validation host's socket. - #[arg(long)] - pub socket_path: String, - /// Calling node implementation version - #[arg(long)] - pub node_impl_version: String, -} diff --git a/bin/rialto/node/src/command.rs b/bin/rialto/node/src/command.rs deleted file mode 100644 index 397f8a3e24e9b..0000000000000 --- a/bin/rialto/node/src/command.rs +++ /dev/null @@ -1,193 +0,0 @@ -// 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 . - -use crate::cli::{Cli, Subcommand}; -use frame_benchmarking_cli::BenchmarkCmd; -use rialto_runtime::{Block, RuntimeApi}; -use sc_cli::SubstrateCli; - -impl SubstrateCli for Cli { - fn impl_name() -> String { - "Rialto Bridge Node".into() - } - - fn impl_version() -> String { - env!("CARGO_PKG_VERSION").into() - } - - fn description() -> String { - "Rialto Bridge Node".into() - } - - fn author() -> String { - "Parity Technologies".into() - } - - fn support_url() -> String { - "https://github.com/paritytech/parity-bridges-common/".into() - } - - fn copyright_start_year() -> i32 { - 2019 - } - - fn executable_name() -> String { - "rialto-bridge-node".into() - } - - fn load_spec(&self, id: &str) -> Result, String> { - Ok(Box::new( - match id { - "" | "dev" => crate::chain_spec::Alternative::Development, - "local" => crate::chain_spec::Alternative::LocalTestnet, - _ => return Err(format!("Unsupported chain specification: {id}")), - } - .load(), - )) - } -} - -// Rialto native executor instance. -pub struct ExecutorDispatch; - -impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { - type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; - - fn dispatch(method: &str, data: &[u8]) -> Option> { - rialto_runtime::api::dispatch(method, data) - } - - fn native_version() -> sc_executor::NativeVersion { - rialto_runtime::native_version() - } -} - -/// Parse and run command line arguments -pub fn run() -> sc_cli::Result<()> { - let cli = Cli::from_args(); - sp_core::crypto::set_default_ss58_version(sp_core::crypto::Ss58AddressFormat::custom( - rialto_runtime::SS58Prefix::get() as u16, - )); - - match &cli.subcommand { - Some(Subcommand::Benchmark(cmd)) => { - let runner = cli.create_runner(cmd)?; - match cmd { - BenchmarkCmd::Pallet(cmd) => - if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) - } else { - println!( - "Benchmarking wasn't enabled when building the node. \ - You can enable it with `--features runtime-benchmarks`." - ); - Ok(()) - }, - _ => Err("Unsupported benchmarking subcommand".into()), - } - }, - Some(Subcommand::Key(cmd)) => cmd.run(&cli), - Some(Subcommand::Sign(cmd)) => cmd.run(), - Some(Subcommand::Verify(cmd)) => cmd.run(), - Some(Subcommand::Vanity(cmd)) => cmd.run(), - Some(Subcommand::BuildSpec(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, - Some(Subcommand::CheckBlock(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|mut config| { - let (client, _, import_queue, task_manager) = - polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::ExportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|mut config| { - let (client, _, _, task_manager) = - polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; - Ok((cmd.run(client, config.database), task_manager)) - }) - }, - Some(Subcommand::ExportState(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|mut config| { - let (client, _, _, task_manager) = - polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; - Ok((cmd.run(client, config.chain_spec), task_manager)) - }) - }, - Some(Subcommand::ImportBlocks(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|mut config| { - let (client, _, import_queue, task_manager) = - polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; - Ok((cmd.run(client, import_queue), task_manager)) - }) - }, - Some(Subcommand::PurgeChain(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run(config.database)) - }, - Some(Subcommand::Revert(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.async_run(|mut config| { - let (client, backend, _, task_manager) = - polkadot_service::new_chain_ops(&mut config, None).map_err(service_error)?; - Ok((cmd.run(client, backend, None), task_manager)) - }) - }, - Some(Subcommand::Inspect(cmd)) => { - let runner = cli.create_runner(cmd)?; - runner.sync_run(|config| cmd.run::(config)) - }, - None => { - let runner = cli.create_runner(&cli.run)?; - - runner.run_node_until_exit(|config| async move { - polkadot_service::new_full( - config, - polkadot_service::NewFullParams { - is_parachain_node: polkadot_service::IsParachainNode::No, - grandpa_pause: None, - enable_beefy: true, - jaeger_agent: None, - telemetry_worker_handle: None, - node_version: None, - workers_path: None, - workers_names: Some(( - "rialto-bridge-node-prepare-worker".to_string(), - "rialto-bridge-node-execute-worker".to_string(), - )), - overseer_gen: polkadot_service::overseer::RealOverseerGen, - overseer_message_channel_capacity_override: None, - malus_finality_delay: None, - hwbench: None, - }, - ) - .map(|full| full.task_manager) - .map_err(service_error) - }) - }, - } -} - -// We don't want to change 'service.rs' too much to ease future updates => it'll keep using -// its own error enum like original polkadot service does. -fn service_error(err: polkadot_service::Error) -> sc_cli::Error { - sc_cli::Error::Application(Box::new(err)) -} diff --git a/bin/rialto/node/src/main.rs b/bin/rialto/node/src/main.rs deleted file mode 100644 index 6dea84a309b26..0000000000000 --- a/bin/rialto/node/src/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -// 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 . - -//! Rialto bridge node. - -#![warn(missing_docs)] - -mod chain_spec; -mod cli; -mod command; - -/// Run the Rialto Node -fn main() -> sc_cli::Result<()> { - command::run() -} diff --git a/bin/rialto/node/src/workers/execute-worker.rs b/bin/rialto/node/src/workers/execute-worker.rs deleted file mode 100644 index 72cab799d753e..0000000000000 --- a/bin/rialto/node/src/workers/execute-worker.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Execute worker. - -polkadot_node_core_pvf_common::decl_worker_main!( - "execute-worker", - polkadot_node_core_pvf_execute_worker::worker_entrypoint, - env!("SUBSTRATE_CLI_IMPL_VERSION") -); diff --git a/bin/rialto/node/src/workers/prepare-worker.rs b/bin/rialto/node/src/workers/prepare-worker.rs deleted file mode 100644 index 695f66cc7b7d3..0000000000000 --- a/bin/rialto/node/src/workers/prepare-worker.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot 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. - -// Polkadot 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 Polkadot. If not, see . - -//! Prepare worker. - -polkadot_node_core_pvf_common::decl_worker_main!( - "prepare-worker", - polkadot_node_core_pvf_prepare_worker::worker_entrypoint, - env!("SUBSTRATE_CLI_IMPL_VERSION") -); diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml deleted file mode 100644 index 5ef7d53bed4a1..0000000000000 --- a/bin/rialto/runtime/Cargo.toml +++ /dev/null @@ -1,153 +0,0 @@ -[package] -name = "rialto-runtime" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -repository = "https://github.com/paritytech/parity-bridges-common/" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Bridge dependencies - -bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } -bp-messages = { path = "../../../primitives/messages", default-features = false } -bp-millau = { path = "../../../primitives/chain-millau", default-features = false } -bp-relayers = { path = "../../../primitives/relayers", default-features = false } -bp-rialto = { path = "../../../primitives/chain-rialto", default-features = false } -bp-runtime = { path = "../../../primitives/runtime", default-features = false } -bridge-runtime-common = { path = "../../runtime-common", default-features = false } -pallet-bridge-beefy = { path = "../../../modules/beefy", default-features = false } -pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } -pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } -pallet-bridge-relayers = { path = "../../../modules/relayers", default-features = false } -pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } - -# Substrate Dependencies - -sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } -frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } -frame-executive = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-message-queue = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-offences = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, features = ["historical"]} -pallet-sudo = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-timestamp = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-authority-discovery = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-block-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-consensus-babe = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-inherents = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-offchain = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-transaction-pool = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Polkadot (parachain) Dependencies -pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[dev-dependencies] -bridge-runtime-common = { path = "../../runtime-common", features = ["integrity-test"] } -env_logger = "0.10" -static_assertions = "1.1" - -[build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[features] -default = [ "std" ] -std = [ - "bp-messages/std", - "bp-millau/std", - "bp-relayers/std", - "bp-rialto/std", - "bp-runtime/std", - "bridge-runtime-common/std", - "codec/std", - "frame-benchmarking/std", - "frame-executive/std", - "frame-support/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "pallet-authority-discovery/std", - "pallet-authorship/std", - "pallet-babe/std", - "pallet-balances/std", - "pallet-beefy-mmr/std", - "pallet-beefy/std", - "pallet-bridge-beefy/std", - "pallet-bridge-grandpa/std", - "pallet-bridge-messages/std", - "pallet-bridge-relayers/std", - "pallet-grandpa/std", - "pallet-message-queue/std", - "pallet-mmr/std", - "pallet-offences/std", - "pallet-session/std", - "pallet-shift-session-manager/std", - "pallet-sudo/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-xcm/std", - "polkadot-primitives/std", - "polkadot-runtime-common/std", - "polkadot-runtime-parachains/std", - "scale-info/std", - "sp-api/std", - "sp-authority-discovery/std", - "sp-block-builder/std", - "sp-consensus-babe/std", - "sp-consensus-beefy/std", - "sp-core/std", - "sp-inherents/std", - "sp-io/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-transaction-pool/std", - "sp-version/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] -runtime-benchmarks = [ - "bridge-runtime-common/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-bridge-grandpa/runtime-benchmarks", - "pallet-bridge-messages/runtime-benchmarks", - "pallet-bridge-relayers/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "polkadot-runtime-common/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", -] diff --git a/bin/rialto/runtime/build.rs b/bin/rialto/runtime/build.rs deleted file mode 100644 index 25e220e46fc3b..0000000000000 --- a/bin/rialto/runtime/build.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 . - -use substrate_wasm_builder::WasmBuilder; - -fn main() { - WasmBuilder::new() - .with_current_project() - .import_memory() - .export_heap_base() - .disable_runtime_version_section_check() - .build() -} diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs deleted file mode 100644 index 684b3e5bf466f..0000000000000 --- a/bin/rialto/runtime/src/lib.rs +++ /dev/null @@ -1,1074 +0,0 @@ -// 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 . - -//! The Rialto runtime. This can be compiled with `#[no_std]`, ready for Wasm. - -#![cfg_attr(not(feature = "std"), no_std)] -// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] -// Runtime-generated enums -#![allow(clippy::large_enum_variant)] -// From construct_runtime macro -#![allow(clippy::from_over_into)] - -// Make the WASM binary available. -#[cfg(feature = "std")] -include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); - -pub mod millau_messages; -pub mod parachains; -pub mod xcm_config; - -use bp_runtime::HeaderId; -use pallet_grandpa::{ - fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, -}; -use pallet_transaction_payment::{FeeDetails, Multiplier, RuntimeDispatchInfo}; -use polkadot_primitives::Id as ParaId; -use polkadot_runtime_parachains::runtime_api_impl::{ - v7 as parachains_runtime_api_impl, vstaging as parachains_staging_runtime_api_impl, -}; -use sp_api::impl_runtime_apis; -use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; -use sp_consensus_beefy::{ecdsa_crypto::AuthorityId as BeefyId, mmr::MmrLeafVersion, ValidatorSet}; -use sp_core::OpaqueMetadata; -use sp_runtime::{ - create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys}, - transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, FixedPointNumber, KeyTypeId, Perquintill, -}; -use sp_std::{collections::btree_map::BTreeMap, prelude::*}; -#[cfg(feature = "std")] -use sp_version::NativeVersion; -use sp_version::RuntimeVersion; - -// A few exports that help ease life for downstream crates. -pub use frame_support::{ - construct_runtime, - dispatch::DispatchClass, - parameter_types, - traits::{ - ConstU32, ConstU64, ConstU8, Currency, ExistenceRequirement, Imbalance, KeyOwnerProofSystem, - }, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, RuntimeDbWeight, Weight}, - StorageValue, -}; - -pub use frame_system::Call as SystemCall; -pub use pallet_balances::Call as BalancesCall; -pub use pallet_bridge_beefy::Call as BridgeBeefyCall; -pub use pallet_bridge_grandpa::Call as BridgeGrandpaCall; -pub use pallet_bridge_messages::Call as MessagesCall; -pub use pallet_sudo::Call as SudoCall; -pub use pallet_timestamp::Call as TimestampCall; -pub use pallet_xcm::Call as XcmCall; - -#[cfg(any(feature = "std", test))] -pub use sp_runtime::BuildStorage; -pub use sp_runtime::{Perbill, Permill}; - -/// An index to a block. -pub type BlockNumber = bp_rialto::BlockNumber; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = bp_rialto::Signature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = bp_rialto::AccountId; - -/// The type for looking up accounts. We don't expect more than 4 billion of them, but you -/// never know... -pub type AccountIndex = u32; - -/// Balance of an account. -pub type Balance = bp_rialto::Balance; - -/// Nonce of a transaction in the chain. -pub type Nonce = bp_rialto::Nonce; - -/// A hash of some data used by the chain. -pub type Hash = bp_rialto::Hash; - -/// Hashing algorithm used by the chain. -pub type Hashing = bp_rialto::Hasher; - -/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know -/// the specifics of the runtime. They can then be made to be agnostic over specific formats -/// of data like extrinsics, allowing for them to continue syncing the network through upgrades -/// to even the core data structures. -pub mod opaque { - use super::*; - - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; - - /// Opaque block header type. - pub type Header = generic::Header; - /// Opaque block type. - pub type Block = generic::Block; - /// Opaque block identifier type. - pub type BlockId = generic::BlockId; -} - -impl_opaque_keys! { - pub struct SessionKeys { - pub babe: Babe, - pub grandpa: Grandpa, - pub beefy: Beefy, - pub para_validator: Initializer, - pub para_assignment: SessionInfo, - pub authority_discovery: AuthorityDiscovery, - } -} - -/// This runtime version. -#[sp_version::runtime_version] -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("rialto-runtime"), - impl_name: create_runtime_str!("rialto-runtime"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, - state_version: 1, -}; - -/// The version information used to identify this runtime when compiled natively. -#[cfg(feature = "std")] -pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } -} - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; - pub const Version: RuntimeVersion = VERSION; - pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 60_000_000, // ~0.06 ms = ~60 µs - write: 200_000_000, // ~0.2 ms = 200 µs - }; - pub const SS58Prefix: u8 = 48; -} - -impl frame_system::Config for Runtime { - /// The basic call filter to use in dispatchable. - type BaseCallFilter = frame_support::traits::Everything; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Nonce = Nonce; - /// The type for hashing blocks and tries. - type Hash = Hash; - /// The hashing algorithm used. - type Hashing = Hashing; - /// The header type. - type Block = Block; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Version of the runtime. - type Version = Version; - /// Provides information about the pallet setup in the runtime. - type PalletInfo = PalletInfo; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block and extrinsics weights: base values and limits. - type BlockWeights = bp_rialto::BlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = bp_rialto::BlockLength; - /// The weight of database operations that the runtime can invoke. - type DbWeight = DbWeight; - /// The designated SS58 prefix of this chain. - type SS58Prefix = SS58Prefix; - /// The set code logic, just the default since we're not a parachain. - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -/// The BABE epoch configuration at genesis. -pub const BABE_GENESIS_EPOCH_CONFIG: sp_consensus_babe::BabeEpochConfiguration = - sp_consensus_babe::BabeEpochConfiguration { - c: bp_rialto::time_units::PRIMARY_PROBABILITY, - allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryVRFSlots, - }; - -parameter_types! { - pub const EpochDuration: u64 = bp_rialto::EPOCH_DURATION_IN_SLOTS as u64; - pub const ExpectedBlockTime: bp_rialto::Moment = bp_rialto::time_units::MILLISECS_PER_BLOCK; - pub ReportLongevity: u64 = EpochDuration::get() * 10; -} - -impl pallet_babe::Config for Runtime { - type EpochDuration = EpochDuration; - type ExpectedBlockTime = ExpectedBlockTime; - // session module is the trigger - type EpochChangeTrigger = pallet_babe::ExternalTrigger; - - type DisabledValidators = (); - - type WeightInfo = (); - - type MaxAuthorities = ConstU32<10>; - - // equivocation related configuration - we don't expect any equivocations in our testnets - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); - - type MaxNominators = ConstU32<256>; -} - -impl pallet_beefy::Config for Runtime { - type BeefyId = BeefyId; - type MaxAuthorities = ConstU32<10>; - type MaxSetIdSessionEntries = ConstU64<0>; - type OnNewValidatorSet = MmrLeaf; - type WeightInfo = (); - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); - type MaxNominators = ConstU32<256>; -} - -impl pallet_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); - type MaxAuthorities = ConstU32<10>; - type MaxSetIdSessionEntries = ConstU64<0>; - type KeyOwnerProof = >::Proof; - type EquivocationReportSystem = - pallet_grandpa::EquivocationReportSystem; - type MaxNominators = ConstU32<256>; -} - -impl pallet_mmr::Config for Runtime { - const INDEXING_PREFIX: &'static [u8] = b"mmr"; - type Hashing = Keccak256; - type LeafData = pallet_beefy_mmr::Pallet; - type OnNewRoot = pallet_beefy_mmr::DepositBeefyDigest; - type WeightInfo = (); -} - -parameter_types! { - /// Version of the produced MMR leaf. - /// - /// The version consists of two parts; - /// - `major` (3 bits) - /// - `minor` (5 bits) - /// - /// `major` should be updated only if decoding the previous MMR Leaf format from the payload - /// is not possible (i.e. backward incompatible change). - /// `minor` should be updated if fields are added to the previous MMR Leaf, which given SCALE - /// encoding does not prevent old leafs from being decoded. - /// - /// Hence we expect `major` to be changed really rarely (think never). - /// See [`MmrLeafVersion`] type documentation for more details. - pub LeafVersion: MmrLeafVersion = MmrLeafVersion::new(0, 0); -} - -pub struct BeefyDummyDataProvider; - -impl sp_consensus_beefy::mmr::BeefyDataProvider<()> for BeefyDummyDataProvider { - fn extra_data() {} -} - -impl pallet_beefy_mmr::Config for Runtime { - type LeafVersion = LeafVersion; - type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum; - type LeafExtra = (); - type BeefyDataProvider = BeefyDummyDataProvider; -} - -parameter_types! { - pub const MinimumPeriod: u64 = bp_rialto::SLOT_DURATION / 2; -} - -impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the UNIX epoch. - type Moment = bp_rialto::Moment; - type OnTimestampSet = Babe; - type MinimumPeriod = MinimumPeriod; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); -} - -parameter_types! { - pub const ExistentialDeposit: bp_rialto::Balance = 500; -} - -impl pallet_balances::Config for Runtime { - /// The type for recording an account's balance. - type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); - // For weight estimation, we assume that the most locks on an individual account will be 50. - // This number may need to be adjusted in the future if this assumption no longer holds true. - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; -} - -parameter_types! { - pub const TransactionBaseFee: Balance = 0; - pub const TransactionByteFee: Balance = 1; - // values for following parameters are copied from polkadot repo, but it is fine - // not to sync them - we're not going to make Rialto a full copy of one of Polkadot-like chains - pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); - pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); - pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); - pub MaximumMultiplier: Multiplier = sp_runtime::traits::Bounded::max_value(); -} - -impl pallet_transaction_payment::Config for Runtime { - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = bp_rialto::WeightToFee; - type LengthToFee = bp_rialto::WeightToFee; - type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment< - Runtime, - TargetBlockFullness, - AdjustmentVariable, - MinimumMultiplier, - MaximumMultiplier, - >; - type RuntimeEvent = RuntimeEvent; -} - -impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; - type WeightInfo = pallet_sudo::weights::SubstrateWeight; -} - -impl pallet_session::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ValidatorId = ::AccountId; - type ValidatorIdOf = (); - type ShouldEndSession = Babe; - type NextSessionRotation = Babe; - type SessionManager = pallet_shift_session_manager::Pallet; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; - // TODO: update me (https://github.com/paritytech/parity-bridges-common/issues/78) - type WeightInfo = (); -} - -impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (); -} - -pub struct FullIdentificationOf; -impl sp_runtime::traits::Convert> for FullIdentificationOf { - fn convert(_: AccountId) -> Option<()> { - Some(()) - } -} - -impl pallet_session::historical::Config for Runtime { - type FullIdentification = (); - type FullIdentificationOf = FullIdentificationOf; -} - -impl pallet_offences::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type IdentificationTuple = pallet_session::historical::IdentificationTuple; - type OnOffenceHandler = (); -} - -impl pallet_authority_discovery::Config for Runtime { - type MaxAuthorities = ConstU32<10>; -} - -impl pallet_bridge_relayers::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Reward = Balance; - type PaymentProcedure = - bp_relayers::PayRewardFromAccount, AccountId>; - type StakeAndSlash = (); - type WeightInfo = (); -} - -pub type MillauGrandpaInstance = (); -impl pallet_bridge_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BridgedChain = bp_millau::Millau; - type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; - type HeadersToKeep = ConstU32<{ bp_millau::DAYS as u32 }>; - type WeightInfo = pallet_bridge_grandpa::weights::BridgeWeight; -} - -impl pallet_shift_session_manager::Config for Runtime {} - -parameter_types! { - pub const MaxMessagesToPruneAtOnce: bp_messages::MessageNonce = 8; - pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; - pub const RootAccountForPayments: Option = None; - pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::MILLAU_CHAIN_ID; - pub ActiveOutboundLanes: &'static [bp_messages::LaneId] = &[millau_messages::XCM_LANE]; -} - -/// Instance of the messages pallet used to relay messages to/from Millau chain. -pub type WithMillauMessagesInstance = (); - -impl pallet_bridge_messages::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_bridge_messages::weights::BridgeWeight; - type ActiveOutboundLanes = ActiveOutboundLanes; - type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; - type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; - - type MaximalOutboundPayloadSize = crate::millau_messages::ToMillauMaximalOutboundPayloadSize; - type OutboundPayload = crate::millau_messages::ToMillauMessagePayload; - - type InboundPayload = crate::millau_messages::FromMillauMessagePayload; - type InboundRelayer = bp_millau::AccountId; - type DeliveryPayments = (); - - type TargetHeaderChain = crate::millau_messages::MillauAsTargetHeaderChain; - type LaneMessageVerifier = crate::millau_messages::ToMillauMessageVerifier; - type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< - Runtime, - WithMillauMessagesInstance, - frame_support::traits::ConstU128<100_000>, - >; - type OnMessagesDelivered = (); - - type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain; - type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch; - type BridgedChainId = BridgedChainId; -} - -pub type MillauBeefyInstance = (); -impl pallet_bridge_beefy::Config for Runtime { - type MaxRequests = frame_support::traits::ConstU32<16>; - type CommitmentsToKeep = frame_support::traits::ConstU32<8>; - type BridgedChain = bp_millau::Millau; -} - -construct_runtime!( - pub enum Runtime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - - // Must be before session. - Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned}, - - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, - - // Consensus support. - // Authorship must be before session in order to note author in the correct session and era - // for im-online. - Authorship: pallet_authorship::{Pallet, Storage}, - Offences: pallet_offences::{Pallet, Storage, Event}, - Historical: pallet_session::historical::{Pallet}, - - AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config}, - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event}, - ShiftSessionManager: pallet_shift_session_manager::{Pallet}, - - // BEEFY Bridges support. - Beefy: pallet_beefy::{Pallet, Storage, Config}, - Mmr: pallet_mmr::{Pallet, Storage}, - MmrLeaf: pallet_beefy_mmr::{Pallet, Storage}, - - // Millau bridge modules. - BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event}, - BridgeMillauGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage, Event}, - BridgeMillauMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event, Config}, - - // Millau bridge modules (BEEFY based). - BridgeMillauBeefy: pallet_bridge_beefy::{Pallet, Call, Storage}, - - // Parachain modules. - ParachainsOrigin: polkadot_runtime_parachains::origin::{Pallet, Origin}, - Configuration: polkadot_runtime_parachains::configuration::{Pallet, Call, Storage, Config}, - Shared: polkadot_runtime_parachains::shared::{Pallet, Call, Storage}, - ParaInclusion: polkadot_runtime_parachains::inclusion::{Pallet, Call, Storage, Event}, - ParasInherent: polkadot_runtime_parachains::paras_inherent::{Pallet, Call, Storage, Inherent}, - Scheduler: polkadot_runtime_parachains::scheduler::{Pallet, Storage}, - Paras: polkadot_runtime_parachains::paras::{Pallet, Call, Storage, Event, Config, ValidateUnsigned}, - Initializer: polkadot_runtime_parachains::initializer::{Pallet, Call, Storage}, - Dmp: polkadot_runtime_parachains::dmp::{Pallet, Storage}, - Hrmp: polkadot_runtime_parachains::hrmp::{Pallet, Call, Storage, Event, Config}, - SessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, - ParaSessionInfo: polkadot_runtime_parachains::session_info::{Pallet, Storage}, - ParasDisputes: polkadot_runtime_parachains::disputes::{Pallet, Call, Storage, Event}, - ParasSlashing: polkadot_runtime_parachains::disputes::slashing::{Pallet, Call, Storage, ValidateUnsigned}, - ParaAssignmentProvider: polkadot_runtime_parachains::assigner_parachains::{Pallet}, - MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event}, - - // Parachain Onboarding Pallets - Registrar: polkadot_runtime_common::paras_registrar::{Pallet, Call, Storage, Event}, - Slots: polkadot_runtime_common::slots::{Pallet, Call, Storage, Event}, - ParasSudoWrapper: polkadot_runtime_common::paras_sudo_wrapper::{Pallet, Call}, - - // Pallet for sending XCM. - XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, - } -); - -/// The address format for describing accounts. -pub type Address = sp_runtime::MultiAddress; -/// Block header type as expected by this runtime. -pub type Header = generic::Header; -/// Block type as expected by this runtime. -pub type Block = generic::Block; -/// A Block signed with a Justification -pub type SignedBlock = generic::SignedBlock; -/// BlockId type as expected by this runtime. -pub type BlockId = generic::BlockId; -/// The SignedExtension to the basic transaction logic. -pub type SignedExtra = ( - frame_system::CheckNonZeroSender, - frame_system::CheckSpecVersion, - frame_system::CheckTxVersion, - frame_system::CheckGenesis, - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, -); -/// The payload being signed in transactions. -pub type SignedPayload = generic::SignedPayload; -/// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; -/// Extrinsic type that has already been checked. -pub type CheckedExtrinsic = generic::CheckedExtrinsic; -/// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; - -/// MMR helper types. -mod mmr { - use super::Runtime; - pub use pallet_mmr::primitives::*; - - pub type Leaf = <::LeafData as LeafDataProvider>::LeafData; - pub type Hashing = ::Hashing; - pub type Hash = ::Output; -} - -impl_runtime_apis! { - impl sp_api::Core for Runtime { - fn version() -> RuntimeVersion { - VERSION - } - - fn execute_block(block: Block) { - Executive::execute_block(block); - } - - fn initialize_block(header: &::Header) { - Executive::initialize_block(header) - } - } - - impl sp_api::Metadata for Runtime { - fn metadata() -> OpaqueMetadata { - OpaqueMetadata::new(Runtime::metadata().into()) - } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } - } - - impl sp_block_builder::BlockBuilder for Runtime { - fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { - Executive::apply_extrinsic(extrinsic) - } - - fn finalize_block() -> ::Header { - Executive::finalize_block() - } - - fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { - data.create_extrinsics() - } - - fn check_inherents( - block: Block, - data: sp_inherents::InherentData, - ) -> sp_inherents::CheckInherentsResult { - data.check_extrinsics(&block) - } - } - - impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { - fn account_nonce(account: AccountId) -> Nonce { - System::account_nonce(account) - } - } - - impl sp_consensus_beefy::BeefyApi for Runtime { - fn beefy_genesis() -> Option { - Beefy::genesis_block() - } - - fn validator_set() -> Option> { - Beefy::validator_set() - } - - fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: sp_consensus_beefy::EquivocationProof< - NumberFor, - sp_consensus_beefy::ecdsa_crypto::AuthorityId, - sp_consensus_beefy::ecdsa_crypto::Signature - >, - _key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof, - ) -> Option<()> { None } - - fn generate_key_ownership_proof( - _set_id: sp_consensus_beefy::ValidatorSetId, - _authority_id: sp_consensus_beefy::ecdsa_crypto::AuthorityId, - ) -> Option { None } - } - - impl pallet_mmr::primitives::MmrApi< - Block, - mmr::Hash, - BlockNumber, - > for Runtime { - fn mmr_root() -> Result { - Ok(Mmr::mmr_root()) - } - - fn mmr_leaf_count() -> Result { - Ok(Mmr::mmr_leaves()) - } - - fn generate_proof( - block_numbers: Vec, - best_known_block_number: Option, - ) -> Result<(Vec, mmr::Proof), mmr::Error> { - Mmr::generate_proof(block_numbers, best_known_block_number).map( - |(leaves, proof)| { - ( - leaves - .into_iter() - .map(|leaf| mmr::EncodableOpaqueLeaf::from_leaf(&leaf)) - .collect(), - proof, - ) - }, - ) - } - - fn verify_proof(leaves: Vec, proof: mmr::Proof) - -> Result<(), mmr::Error> - { - let leaves = leaves.into_iter().map(|leaf| - leaf.into_opaque_leaf() - .try_decode() - .ok_or(mmr::Error::Verify)).collect::, mmr::Error>>()?; - Mmr::verify_leaves(leaves, proof) - } - - fn verify_proof_stateless( - root: mmr::Hash, - leaves: Vec, - proof: mmr::Proof - ) -> Result<(), mmr::Error> { - let nodes = leaves.into_iter().map(|leaf|mmr::DataOrHash::Data(leaf.into_opaque_leaf())).collect(); - pallet_mmr::verify_leaves_proof::(root, nodes, proof) - } - } - - impl bp_millau::MillauFinalityApi for Runtime { - fn best_finalized() -> Option> { - BridgeMillauGrandpa::best_finalized() - } - - fn synced_headers_grandpa_info( - ) -> Vec> { - BridgeMillauGrandpa::synced_headers_grandpa_info() - } - } - - impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { - fn validate_transaction( - source: TransactionSource, - tx: ::Extrinsic, - block_hash: ::Hash, - ) -> TransactionValidity { - Executive::validate_transaction(source, tx, block_hash) - } - } - - impl sp_offchain::OffchainWorkerApi for Runtime { - fn offchain_worker(header: &::Header) { - Executive::offchain_worker(header) - } - } - - impl sp_consensus_babe::BabeApi for Runtime { - fn configuration() -> sp_consensus_babe::BabeConfiguration { - // The choice of `c` parameter (where `1 - c` represents the - // probability of a slot being empty), is done in accordance to the - // slot duration and expected target block time, for safely - // resisting network delays of maximum two seconds. - // - sp_consensus_babe::BabeConfiguration { - slot_duration: Babe::slot_duration(), - epoch_length: EpochDuration::get(), - c: BABE_GENESIS_EPOCH_CONFIG.c, - authorities: Babe::authorities().to_vec(), - randomness: Babe::randomness(), - allowed_slots: BABE_GENESIS_EPOCH_CONFIG.allowed_slots, - } - } - - fn current_epoch_start() -> sp_consensus_babe::Slot { - Babe::current_epoch_start() - } - - fn current_epoch() -> sp_consensus_babe::Epoch { - Babe::current_epoch() - } - - fn next_epoch() -> sp_consensus_babe::Epoch { - Babe::next_epoch() - } - - fn generate_key_ownership_proof( - _slot: sp_consensus_babe::Slot, - _authority_id: sp_consensus_babe::AuthorityId, - ) -> Option { - None - } - - fn submit_report_equivocation_unsigned_extrinsic( - equivocation_proof: sp_consensus_babe::EquivocationProof<::Header>, - key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof, - ) -> Option<()> { - let key_owner_proof = key_owner_proof.decode()?; - - Babe::submit_unsigned_equivocation_report( - equivocation_proof, - key_owner_proof, - ) - } - } - - #[api_version(8)] - impl polkadot_primitives::runtime_api::ParachainHost for Runtime { - fn validators() -> Vec { - parachains_runtime_api_impl::validators::() - } - - fn validator_groups() -> (Vec>, polkadot_primitives::GroupRotationInfo) { - parachains_runtime_api_impl::validator_groups::() - } - - fn availability_cores() -> Vec> { - parachains_runtime_api_impl::availability_cores::() - } - - fn persisted_validation_data(para_id: ParaId, assumption: polkadot_primitives::OccupiedCoreAssumption) - -> Option> { - parachains_runtime_api_impl::persisted_validation_data::(para_id, assumption) - } - - fn assumed_validation_data( - para_id: ParaId, - expected_persisted_validation_data_hash: Hash, - ) -> Option<(polkadot_primitives::PersistedValidationData, polkadot_primitives::ValidationCodeHash)> { - parachains_runtime_api_impl::assumed_validation_data::( - para_id, - expected_persisted_validation_data_hash, - ) - } - - fn check_validation_outputs( - para_id: ParaId, - outputs: polkadot_primitives::CandidateCommitments, - ) -> bool { - parachains_runtime_api_impl::check_validation_outputs::(para_id, outputs) - } - - fn session_index_for_child() -> polkadot_primitives::SessionIndex { - parachains_runtime_api_impl::session_index_for_child::() - } - - fn validation_code(para_id: ParaId, assumption: polkadot_primitives::OccupiedCoreAssumption) - -> Option { - parachains_runtime_api_impl::validation_code::(para_id, assumption) - } - - fn candidate_pending_availability(para_id: ParaId) -> Option> { - parachains_runtime_api_impl::candidate_pending_availability::(para_id) - } - - fn candidate_events() -> Vec> { - parachains_runtime_api_impl::candidate_events::(|ev| { - match ev { - RuntimeEvent::ParaInclusion(ev) => { - Some(ev) - } - _ => None, - } - }) - } - - fn session_info(index: polkadot_primitives::SessionIndex) -> Option { - parachains_runtime_api_impl::session_info::(index) - } - - fn session_executor_params(session_index: polkadot_primitives::SessionIndex) -> Option { - parachains_runtime_api_impl::session_executor_params::(session_index) - } - - fn dmq_contents(recipient: ParaId) -> Vec> { - parachains_runtime_api_impl::dmq_contents::(recipient) - } - - fn inbound_hrmp_channels_contents( - recipient: ParaId - ) -> BTreeMap>> { - parachains_runtime_api_impl::inbound_hrmp_channels_contents::(recipient) - } - - fn validation_code_by_hash(hash: polkadot_primitives::ValidationCodeHash) -> Option { - parachains_runtime_api_impl::validation_code_by_hash::(hash) - } - - fn on_chain_votes() -> Option> { - parachains_runtime_api_impl::on_chain_votes::() - } - - fn submit_pvf_check_statement( - stmt: polkadot_primitives::PvfCheckStatement, - signature: polkadot_primitives::ValidatorSignature - ) { - parachains_runtime_api_impl::submit_pvf_check_statement::(stmt, signature) - } - - fn pvfs_require_precheck() -> Vec { - parachains_runtime_api_impl::pvfs_require_precheck::() - } - - fn validation_code_hash(para_id: ParaId, assumption: polkadot_primitives::OccupiedCoreAssumption) - -> Option - { - parachains_runtime_api_impl::validation_code_hash::(para_id, assumption) - } - - fn disputes() -> Vec<(polkadot_primitives::SessionIndex, polkadot_primitives::CandidateHash, polkadot_primitives::DisputeState)> { - parachains_runtime_api_impl::get_session_disputes::() - } - - fn unapplied_slashes( - ) -> Vec<(polkadot_primitives::SessionIndex, polkadot_primitives::CandidateHash, polkadot_primitives::slashing::PendingSlashes)> { - parachains_runtime_api_impl::unapplied_slashes::() - } - - fn key_ownership_proof( - validator_id: polkadot_primitives::ValidatorId, - ) -> Option { - use codec::Encode; - - Historical::prove((polkadot_primitives::PARACHAIN_KEY_TYPE_ID, validator_id)) - .map(|p| p.encode()) - .map(polkadot_primitives::slashing::OpaqueKeyOwnershipProof::new) - } - - fn submit_report_dispute_lost( - dispute_proof: polkadot_primitives::slashing::DisputeProof, - key_ownership_proof: polkadot_primitives::slashing::OpaqueKeyOwnershipProof, - ) -> Option<()> { - parachains_runtime_api_impl::submit_unsigned_slashing_report::( - dispute_proof, - key_ownership_proof, - ) - } - - fn minimum_backing_votes() -> u32 { - parachains_runtime_api_impl::minimum_backing_votes::() - } - - fn para_backing_state(para_id: ParaId) -> Option { - parachains_runtime_api_impl::backing_state::(para_id) - } - - fn async_backing_params() -> polkadot_primitives::AsyncBackingParams { - parachains_runtime_api_impl::async_backing_params::() - } - - fn disabled_validators() -> Vec { - parachains_staging_runtime_api_impl::disabled_validators::() - } - - } - - impl sp_authority_discovery::AuthorityDiscoveryApi for Runtime { - fn authorities() -> Vec { - parachains_runtime_api_impl::relevant_authority_ids::() - } - } - - impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi< - Block, - Balance, - > for Runtime { - fn query_info(uxt: ::Extrinsic, len: u32) -> RuntimeDispatchInfo { - TransactionPayment::query_info(uxt, len) - } - fn query_fee_details(uxt: ::Extrinsic, len: u32) -> FeeDetails { - TransactionPayment::query_fee_details(uxt, len) - } - fn query_weight_to_fee(weight: Weight) -> Balance { - TransactionPayment::weight_to_fee(weight) - } - fn query_length_to_fee(length: u32) -> Balance { - TransactionPayment::length_to_fee(length) - } - } - - impl sp_session::SessionKeys for Runtime { - fn generate_session_keys(seed: Option>) -> Vec { - SessionKeys::generate(seed) - } - - fn decode_session_keys( - encoded: Vec, - ) -> Option, sp_core::crypto::KeyTypeId)>> { - SessionKeys::decode_into_raw_public_keys(&encoded) - } - } - - impl fg_primitives::GrandpaApi for Runtime { - fn current_set_id() -> fg_primitives::SetId { - Grandpa::current_set_id() - } - - fn grandpa_authorities() -> GrandpaAuthorityList { - Grandpa::grandpa_authorities() - } - - fn submit_report_equivocation_unsigned_extrinsic( - equivocation_proof: fg_primitives::EquivocationProof< - ::Hash, - NumberFor, - >, - key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, - ) -> Option<()> { - let key_owner_proof = key_owner_proof.decode()?; - - Grandpa::submit_unsigned_equivocation_report( - equivocation_proof, - key_owner_proof, - ) - } - - fn generate_key_ownership_proof( - _set_id: fg_primitives::SetId, - _authority_id: GrandpaId, - ) -> Option { - // NOTE: this is the only implementation possible since we've - // defined our key owner proof type as a bottom type (i.e. a type - // with no values). - None - } - } - - impl bp_millau::ToMillauOutboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - begin: bp_messages::MessageNonce, - end: bp_messages::MessageNonce, - ) -> Vec { - bridge_runtime_common::messages_api::outbound_message_details::< - Runtime, - WithMillauMessagesInstance, - >(lane, begin, end) - } - } - - impl bp_millau::FromMillauInboundLaneApi for Runtime { - fn message_details( - lane: bp_messages::LaneId, - messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, - ) -> Vec { - bridge_runtime_common::messages_api::inbound_message_details::< - Runtime, - WithMillauMessagesInstance, - >(lane, messages) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn call_size() { - const BRIDGES_PALLETS_MAX_CALL_SIZE: usize = 200; - assert!( - core::mem::size_of::>() <= - BRIDGES_PALLETS_MAX_CALL_SIZE - ); - assert!( - core::mem::size_of::>() <= - BRIDGES_PALLETS_MAX_CALL_SIZE - ); - // Largest inner Call is `pallet_session::Call` with a size of 224 bytes. This size is a - // result of large `SessionKeys` struct. - // Total size of Rialto runtime Call is 232. - const MAX_CALL_SIZE: usize = 232; - assert!(core::mem::size_of::() <= MAX_CALL_SIZE); - } -} diff --git a/bin/rialto/runtime/src/millau_messages.rs b/bin/rialto/runtime/src/millau_messages.rs deleted file mode 100644 index 03e4c494cf2a4..0000000000000 --- a/bin/rialto/runtime/src/millau_messages.rs +++ /dev/null @@ -1,200 +0,0 @@ -// 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 . - -//! Everything required to serve Millau <-> Rialto messages. - -use crate::{MillauGrandpaInstance, Runtime, RuntimeOrigin, WithMillauMessagesInstance}; - -use bp_messages::LaneId; -use bridge_runtime_common::{ - messages::{ - self, source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, MessageBridge, - }, - messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, -}; -use frame_support::{parameter_types, weights::Weight}; -use sp_runtime::RuntimeDebug; -use xcm::latest::prelude::*; -use xcm_builder::HaulBlobExporter; - -/// Lane that is used for XCM messages exchange. -pub const XCM_LANE: LaneId = LaneId([0, 0, 0, 0]); -/// Weight of 2 XCM instructions is for simple `Trap(42)` program, coming through bridge -/// (it is prepended with `UniversalOrigin` instruction). It is used just for simplest manual -/// tests, confirming that we don't break encoding somewhere between. -pub const BASE_XCM_WEIGHT_TWICE: Weight = crate::xcm_config::BaseXcmWeight::get().saturating_mul(2); - -parameter_types! { - /// Weight credit for our test messages. - /// - /// 2 XCM instructions is for simple `Trap(42)` program, coming through bridge - /// (it is prepended with `UniversalOrigin` instruction). - pub const WeightCredit: Weight = BASE_XCM_WEIGHT_TWICE; - /// Lane used by the with-Millau bridge. - pub MullauSenderAndLane: SenderAndLane = SenderAndLane::new(Here.into(), XCM_LANE); - - /// Dummy message used in configuration. - pub DummyXcmMessage: Xcm<()> = Xcm::new(); -} - -/// Message payload for Rialto -> Millau messages. -pub type ToMillauMessagePayload = messages::source::FromThisChainMessagePayload; - -/// Message verifier for Rialto -> Millau messages. -pub type ToMillauMessageVerifier = - messages::source::FromThisChainMessageVerifier; - -/// Message payload for Millau -> Rialto messages. -pub type FromMillauMessagePayload = messages::target::FromBridgedChainMessagePayload; - -/// Call-dispatch based message dispatch for Millau -> Rialto messages. -pub type FromMillauMessageDispatch = - bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatch< - crate::xcm_config::OnRialtoBlobDispatcher, - (), - (), - >; - -/// Messages proof for Millau -> Rialto messages. -pub type FromMillauMessagesProof = messages::target::FromBridgedChainMessagesProof; - -/// Messages delivery proof for Rialto -> Millau messages. -pub type ToMillauMessagesDeliveryProof = - messages::source::FromBridgedChainMessagesDeliveryProof; - -/// Maximal outbound payload size of Rialto -> Millau messages. -pub type ToMillauMaximalOutboundPayloadSize = - messages::source::FromThisChainMaximalOutboundPayloadSize; - -/// Millau <-> Rialto message bridge. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct WithMillauMessageBridge; - -impl MessageBridge for WithMillauMessageBridge { - const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; - - type ThisChain = Rialto; - type BridgedChain = Millau; - type BridgedHeaderChain = - pallet_bridge_grandpa::GrandpaChainHeaders; -} - -/// Rialto chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct Rialto; - -impl messages::UnderlyingChainProvider for Rialto { - type Chain = bp_rialto::Rialto; -} - -impl messages::ThisChainWithMessages for Rialto { - type RuntimeOrigin = RuntimeOrigin; -} - -/// Millau chain from message lane point of view. -#[derive(RuntimeDebug, Clone, Copy)] -pub struct Millau; -/// Millau as source header chain. -pub type MillauAsSourceHeaderChain = SourceHeaderChainAdapter; -/// Millau as target header chain. -pub type MillauAsTargetHeaderChain = TargetHeaderChainAdapter; - -impl messages::UnderlyingChainProvider for Millau { - type Chain = bp_millau::Millau; -} - -impl messages::BridgedChainWithMessages for Millau {} - -/// Export XCM messages to be relayed to Millau. -pub type ToMillauBlobExporter = HaulBlobExporter< - XcmBlobHaulerAdapter, - crate::xcm_config::MillauNetwork, - (), ->; - -/// To-Millau XCM hauler. -pub struct ToMillauXcmBlobHauler; - -impl XcmBlobHauler for ToMillauXcmBlobHauler { - type Runtime = Runtime; - type MessagesInstance = WithMillauMessagesInstance; - type SenderAndLane = MullauSenderAndLane; - - type ToSourceChainSender = crate::xcm_config::XcmRouter; - type CongestedMessage = DummyXcmMessage; - type UncongestedMessage = DummyXcmMessage; -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{MillauGrandpaInstance, Runtime, WithMillauMessagesInstance}; - use bridge_runtime_common::{ - assert_complete_bridge_types, - integrity::{ - assert_complete_bridge_constants, check_message_lane_weights, - AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, - AssertCompleteBridgeConstants, - }, - }; - - #[test] - fn ensure_millau_message_lane_weights_are_correct() { - check_message_lane_weights::( - bp_millau::EXTRA_STORAGE_PROOF_SIZE, - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - false, - ); - } - - #[test] - fn ensure_bridge_integrity() { - assert_complete_bridge_types!( - runtime: Runtime, - with_bridged_chain_grandpa_instance: MillauGrandpaInstance, - with_bridged_chain_messages_instance: WithMillauMessagesInstance, - bridge: WithMillauMessageBridge, - this_chain: bp_rialto::Rialto, - bridged_chain: bp_millau::Millau, - ); - - assert_complete_bridge_constants::< - Runtime, - MillauGrandpaInstance, - WithMillauMessagesInstance, - WithMillauMessageBridge, - >(AssertCompleteBridgeConstants { - this_chain_constants: AssertChainConstants { - block_length: bp_rialto::BlockLength::get(), - block_weights: bp_rialto::BlockWeights::get(), - }, - messages_pallet_constants: AssertBridgeMessagesPalletConstants { - max_unrewarded_relayers_in_bridged_confirmation_tx: - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, - max_unconfirmed_messages_in_bridged_confirmation_tx: - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, - bridged_chain_id: bp_runtime::MILLAU_CHAIN_ID, - }, - pallet_names: AssertBridgePalletNames { - with_this_chain_messages_pallet_name: bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME, - with_bridged_chain_grandpa_pallet_name: bp_millau::WITH_MILLAU_GRANDPA_PALLET_NAME, - with_bridged_chain_messages_pallet_name: - bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME, - }, - }); - } -} diff --git a/bin/rialto/runtime/src/parachains.rs b/bin/rialto/runtime/src/parachains.rs deleted file mode 100644 index 972edbf35286e..0000000000000 --- a/bin/rialto/runtime/src/parachains.rs +++ /dev/null @@ -1,274 +0,0 @@ -// 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 . - -//! Parachains support in Rialto runtime. - -use crate::{ - xcm_config, AccountId, Babe, Balance, Balances, BlockNumber, ParaAssignmentProvider, Registrar, - Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ShiftSessionManager, Slots, - UncheckedExtrinsic, -}; - -use frame_support::{ - parameter_types, - traits::{KeyOwnerProofSystem, ProcessMessage, ProcessMessageError}, - weights::{Weight, WeightMeter}, -}; -use frame_system::EnsureRoot; -use polkadot_primitives::v6::{ValidatorId, ValidatorIndex}; -use polkadot_runtime_common::{paras_registrar, paras_sudo_wrapper, slots}; -use polkadot_runtime_parachains::{ - configuration as parachains_configuration, disputes as parachains_disputes, - disputes::slashing as parachains_slashing, - dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, - inclusion::{AggregateMessageOrigin, UmpQueueId}, - initializer as parachains_initializer, origin as parachains_origin, paras as parachains_paras, - paras_inherent as parachains_paras_inherent, scheduler as parachains_scheduler, - session_info as parachains_session_info, shared as parachains_shared, -}; -use sp_core::crypto::KeyTypeId; -use sp_runtime::transaction_validity::TransactionPriority; -use xcm::latest::Junction; - -impl frame_system::offchain::SendTransactionTypes for Runtime -where - RuntimeCall: From, -{ - type Extrinsic = UncheckedExtrinsic; - type OverarchingCall = RuntimeCall; -} - -/// Special `RewardValidators` that does nothing ;) -pub struct RewardValidators; -impl polkadot_runtime_parachains::inclusion::RewardValidators for RewardValidators { - fn reward_backing(_: impl IntoIterator) {} - fn reward_bitfields(_: impl IntoIterator) {} -} - -// all required parachain modules from `polkadot-runtime-parachains` crate - -impl parachains_configuration::Config for Runtime { - type WeightInfo = parachains_configuration::TestWeightInfo; -} - -impl parachains_dmp::Config for Runtime {} - -impl parachains_hrmp::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type ChannelManager = EnsureRoot; - type Currency = Balances; - type WeightInfo = parachains_hrmp::TestWeightInfo; -} - -impl parachains_inclusion::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RewardValidators = RewardValidators; - type DisputesHandler = (); - type MessageQueue = crate::MessageQueue; - type WeightInfo = (); -} - -impl parachains_initializer::Config for Runtime { - type Randomness = pallet_babe::RandomnessFromOneEpochAgo; - type ForceOrigin = EnsureRoot; - type WeightInfo = (); -} - -impl parachains_disputes::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RewardValidators = (); - type SlashingHandler = (); - type WeightInfo = parachains_disputes::TestWeightInfo; -} - -impl parachains_slashing::Config for Runtime { - type KeyOwnerProofSystem = (); - type KeyOwnerProof = - >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; - type HandleReports = (); - type WeightInfo = parachains_slashing::TestWeightInfo; - type BenchmarkingConfig = parachains_slashing::BenchConfig<200>; -} - -impl parachains_origin::Config for Runtime {} - -parameter_types! { - pub const ParasUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); -} - -impl parachains_paras::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = ParasWeightInfo; - type UnsignedPriority = ParasUnsignedPriority; - type QueueFootprinter = crate::ParaInclusion; - type NextSessionRotation = Babe; - type OnNewHead = Registrar; -} - -/// Test weight for the `Paras` pallet. -/// -/// We can't use `parachains_paras::TestWeightInfo` anymore, because it returns `Weight::MAX` -/// where we need some real-world weights. We'll use zero weights here, though to avoid -/// adding benchmarks to Rialto runtime. -pub struct ParasWeightInfo; - -impl parachains_paras::WeightInfo for ParasWeightInfo { - fn force_set_current_code(_c: u32) -> Weight { - Weight::zero() - } - fn force_set_current_head(_s: u32) -> Weight { - Weight::zero() - } - - fn force_set_most_recent_context() -> Weight { - Weight::zero() - } - - fn force_schedule_code_upgrade(_c: u32) -> Weight { - Weight::zero() - } - fn force_note_new_head(_s: u32) -> Weight { - Weight::zero() - } - fn force_queue_action() -> Weight { - Weight::zero() - } - fn add_trusted_validation_code(_c: u32) -> Weight { - Weight::zero() - } - fn poke_unused_validation_code() -> Weight { - Weight::zero() - } - fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { - Weight::zero() - } - fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { - Weight::zero() - } - fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { - Weight::zero() - } - fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { - Weight::zero() - } - fn include_pvf_check_statement() -> Weight { - Weight::zero() - } -} - -impl parachains_paras_inherent::Config for Runtime { - type WeightInfo = parachains_paras_inherent::TestWeightInfo; -} - -impl polkadot_runtime_parachains::assigner_parachains::Config for Runtime {} - -impl parachains_scheduler::Config for Runtime { - type AssignmentProvider = ParaAssignmentProvider; -} - -impl parachains_session_info::Config for Runtime { - type ValidatorSet = ShiftSessionManager; -} - -impl parachains_shared::Config for Runtime {} - -parameter_types! { - /// Amount of weight that can be spent per block to service messages. - /// - /// # WARNING - /// - /// This is not a good value for para-chains since the `Scheduler` - /// already uses up to 80 percent block weight. - pub MessageQueueServiceWeight: Weight = crate::Perbill::from_percent(20) * bp_rialto::BlockWeights::get().max_block; - pub const MessageQueueHeapSize: u32 = 32 * 1024; - pub const MessageQueueMaxStale: u32 = 96; -} - -/// Message processor to handle any messages that were enqueued into the `MessageQueue` pallet. -pub struct MessageProcessor; -impl ProcessMessage for MessageProcessor { - type Origin = AggregateMessageOrigin; - - fn process_message( - message: &[u8], - origin: Self::Origin, - meter: &mut WeightMeter, - id: &mut [u8; 32], - ) -> Result { - let para = match origin { - AggregateMessageOrigin::Ump(UmpQueueId::Para(para)) => para, - }; - xcm_builder::ProcessXcmMessage::< - Junction, - xcm_executor::XcmExecutor, - RuntimeCall, - >::process_message(message, Junction::Parachain(para.into()), meter, id) - } -} - -impl pallet_message_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Size = u32; - type HeapSize = MessageQueueHeapSize; - type MaxStale = MessageQueueMaxStale; - type ServiceWeight = MessageQueueServiceWeight; - #[cfg(not(feature = "runtime-benchmarks"))] - type MessageProcessor = MessageProcessor; - #[cfg(feature = "runtime-benchmarks")] - type MessageProcessor = - pallet_message_queue::mock_helpers::NoopMessageProcessor; - type QueueChangeHandler = crate::ParaInclusion; - type WeightInfo = (); - type QueuePausedQuery = (); -} - -// required onboarding pallets. We're not going to use auctions or crowdloans, so they're missing - -parameter_types! { - pub const ParaDeposit: Balance = 0; - pub const DataDepositPerByte: Balance = 0; -} - -impl paras_registrar::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type Currency = Balances; - type OnSwap = Slots; - type ParaDeposit = ParaDeposit; - type DataDepositPerByte = DataDepositPerByte; - type WeightInfo = paras_registrar::TestWeightInfo; -} - -parameter_types! { - pub const LeasePeriod: BlockNumber = 10 * bp_rialto::MINUTES; -} - -impl slots::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type Registrar = Registrar; - type LeasePeriod = LeasePeriod; - type WeightInfo = slots::TestWeightInfo; - type LeaseOffset = (); - type ForceOrigin = EnsureRoot; -} - -impl paras_sudo_wrapper::Config for Runtime {} diff --git a/bin/rialto/runtime/src/xcm_config.rs b/bin/rialto/runtime/src/xcm_config.rs deleted file mode 100644 index caac064f81534..0000000000000 --- a/bin/rialto/runtime/src/xcm_config.rs +++ /dev/null @@ -1,280 +0,0 @@ -// 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 . - -//! XCM configurations for the Rialto runtime. - -use super::{ - millau_messages::ToMillauBlobExporter, AccountId, AllPalletsWithSystem, Balances, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmPallet, -}; -use bp_rialto::WeightToFee; -use bridge_runtime_common::CustomNetworkId; -use frame_support::{ - parameter_types, - traits::{ConstU32, Everything, Nothing}, - weights::Weight, -}; -use frame_system::EnsureRoot; -use xcm::latest::prelude::*; -use xcm_builder::{ - AccountId32Aliases, CurrencyAdapter as XcmCurrencyAdapter, IsConcrete, MintLocation, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, -}; - -parameter_types! { - /// The location of the `MLAU` token, from the context of this chain. Since this token is native to this - /// chain, we make it synonymous with it and thus it is the `Here` location, which means "equivalent to - /// the context". - pub const TokenLocation: MultiLocation = Here.into_location(); - /// The Rialto network ID. - pub const ThisNetwork: NetworkId = CustomNetworkId::Rialto.as_network_id(); - /// The Millau network ID. - pub const MillauNetwork: NetworkId = CustomNetworkId::Millau.as_network_id(); - - /// Our XCM location ancestry - i.e. our location within the Consensus Universe. - /// - /// Since Polkadot is a top-level relay-chain with its own consensus, it's just our network ID. - pub UniversalLocation: InteriorMultiLocation = ThisNetwork::get().into(); - /// The check account, which holds any native assets that have been teleported out and not back in (yet). - pub CheckAccount: (AccountId, MintLocation) = (XcmPallet::check_account(), MintLocation::Local); -} - -/// The canonical means of converting a `MultiLocation` into an `AccountId`, used when we want to -/// determine the sovereign account controlled by a location. -pub type SovereignAccountOf = ( - // We can directly alias an `AccountId32` into a local account. - AccountId32Aliases, -); - -/// Our asset transactor. This is what allows us to interest with the runtime facilities from the -/// point of view of XCM-only concepts like `MultiLocation` and `MultiAsset`. -/// -/// Ours is only aware of the Balances pallet, which is mapped to `TokenLocation`. -pub type LocalAssetTransactor = XcmCurrencyAdapter< - // Use this currency: - Balances, - // Use this currency when it is a fungible asset matching the given location or name: - IsConcrete, - // We can convert the MultiLocations with our converter above: - SovereignAccountOf, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We track our teleports in/out to keep total issuance correct. - CheckAccount, ->; - -/// The means that we convert the XCM message origin location into a local dispatch origin. -type LocalOriginConverter = ( - // A `Signed` origin of the sovereign account that the original location controls. - SovereignSignedViaLocation, - // The AccountId32 location type can be expressed natively as a `Signed` origin. - SignedAccountId32AsNative, -); - -parameter_types! { - /// The amount of weight an XCM operation takes. This is a safe overestimate. - pub const BaseXcmWeight: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); - /// Maximum number of instructions in a single XCM fragment. A sanity check against weight - /// calculations getting too crazy. - pub const MaxInstructions: u32 = 100; -} - -/// The XCM router. We are not sending messages to sibling/parent/child chains here. -pub type XcmRouter = (); - -/// The barriers one of which must be passed for an XCM message to be executed. -pub type Barrier = ( - // Weight that is paid for may be consumed. - TakeWeightCredit, -); - -/// Dispatches received XCM messages from other chain. -pub type OnRialtoBlobDispatcher = xcm_builder::BridgeBlobDispatcher< - crate::xcm_config::XcmRouter, - crate::xcm_config::UniversalLocation, - (), ->; - -/// Incoming XCM weigher type. -pub type XcmWeigher = xcm_builder::FixedWeightBounds; - -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = (); - type AssetTransactor = LocalAssetTransactor; - type OriginConverter = LocalOriginConverter; - type IsReserve = (); - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = XcmWeigher; - // The weight trader piggybacks on the existing transaction-fee conversion logic. - type Trader = UsingComponents; - type ResponseHandler = XcmPallet; - type AssetTrap = XcmPallet; - type AssetLocker = (); - type AssetExchanger = (); - type AssetClaims = XcmPallet; - type SubscriptionService = XcmPallet; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = ConstU32<64>; - type FeeManager = (); - type MessageExporter = ToMillauBlobExporter; - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type Aliasers = Nothing; -} - -/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior -/// location of this chain. -pub type LocalOriginToLocation = ( - // Usual Signed origin to be used in XCM as a corresponding AccountId32 - SignedToAccountId32, -); - -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = None; -} - -impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - // We don't allow any messages to be sent via the transaction yet. This is basically safe to - // enable, (safe the possibility of someone spamming the parachain if they're willing to pay - // the DOT to send from the Relay-chain). But it's useless until we bring in XCM v3 which will - // make `DescendOrigin` a bit more useful. - type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmRouter = XcmRouter; - // Anyone can execute XCM messages locally. - type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = xcm_executor::XcmExecutor; - // Anyone is able to use teleportation regardless of who they are and what they want to - // teleport. - type XcmTeleportFilter = Everything; - // Anyone is able to use reserve transfers regardless of who they are and what they want to - // transfer. - type XcmReserveTransferFilter = Everything; - type Weigher = XcmWeigher; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = SovereignAccountOf; - type MaxLockers = frame_support::traits::ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - millau_messages::{FromMillauMessageDispatch, XCM_LANE}, - WithMillauMessagesInstance, - }; - use bp_messages::{ - target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - LaneId, MessageKey, - }; - use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; - use codec::Encode; - use pallet_bridge_messages::OutboundLanes; - use sp_runtime::BuildStorage; - use xcm_executor::XcmExecutor; - - fn new_test_ext() -> sp_io::TestExternalities { - sp_io::TestExternalities::new( - frame_system::GenesisConfig::::default().build_storage().unwrap(), - ) - } - - fn prepare_outbound_xcm_message(destination: NetworkId) -> Xcm { - vec![ExportMessage { - network: destination, - destination: destination.into(), - xcm: vec![Instruction::Trap(42)].into(), - }] - .into() - } - - #[test] - fn xcm_messages_to_millau_are_sent_using_bridge_exporter() { - new_test_ext().execute_with(|| { - // ensure that the there are no messages queued - assert_eq!( - OutboundLanes::::get(XCM_LANE) - .latest_generated_nonce, - 0, - ); - - // export message instruction "sends" message to Rialto - XcmExecutor::::execute_xcm_in_credit( - Here, - prepare_outbound_xcm_message(MillauNetwork::get()), - Default::default(), - Weight::MAX, - Weight::MAX, - ) - .ensure_complete() - .expect("runtime configuration must be correct"); - - // ensure that the message has been queued - assert_eq!( - OutboundLanes::::get(XCM_LANE) - .latest_generated_nonce, - 1, - ); - }) - } - - fn prepare_inbound_bridge_message() -> DispatchMessage> { - let xcm = xcm::VersionedXcm::::V3(vec![Instruction::Trap(42)].into()); - let location = - xcm::VersionedInteriorMultiLocation::V3(X1(GlobalConsensus(ThisNetwork::get()))); - // this is the `BridgeMessage` from polkadot xcm builder, but it has no constructor - // or public fields, so just tuple - let bridge_message = (location, xcm).encode(); - DispatchMessage { - key: MessageKey { lane_id: LaneId([0, 0, 0, 0]), nonce: 1 }, - data: DispatchMessageData { payload: Ok(bridge_message) }, - } - } - - #[test] - fn xcm_messages_from_millau_are_dispatched() { - let incoming_message = prepare_inbound_bridge_message(); - - // we care only about handing message to the XCM dispatcher, so we don't care about its - // actual dispatch - let dispatch_result = FromMillauMessageDispatch::dispatch(incoming_message); - assert!(matches!( - dispatch_result.dispatch_level_result, - XcmBlobMessageDispatchResult::NotDispatched(_), - )); - } -} diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index ae6f40b142145..d3b3b21061d05 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -22,7 +22,6 @@ use crate::messages_call_ext::MessagesCallSubType; use pallet_bridge_grandpa::CallSubType as GrandpaCallSubType; use pallet_bridge_parachains::CallSubType as ParachainsCallSubtype; use sp_runtime::transaction_validity::TransactionValidity; -use xcm::v3::NetworkId; pub mod messages; pub mod messages_api; @@ -92,8 +91,8 @@ where /// ```nocompile /// generate_bridge_reject_obsolete_headers_and_messages!{ /// Call, AccountId -/// BridgeRialtoGrandpa, BridgeWestendGrandpa, -/// BridgeRialtoParachains +/// BridgeRococoGrandpa, BridgeRococoMessages, +/// BridgeRococoParachains /// } /// ``` /// @@ -147,42 +146,6 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { }; } -/// A mapping over `NetworkId`. -/// Since `NetworkId` doesn't include `Millau`, `Rialto` and `RialtoParachain`, we create some -/// synthetic associations between these chains and `NetworkId` chains. -pub enum CustomNetworkId { - /// The Millau network ID, associated with Kusama. - Millau, - /// The Rialto network ID, associated with Polkadot. - Rialto, - /// The RialtoParachain network ID, associated with Westend. - RialtoParachain, -} - -impl TryFrom for CustomNetworkId { - type Error = (); - - fn try_from(chain: bp_runtime::ChainId) -> Result { - Ok(match chain { - bp_runtime::MILLAU_CHAIN_ID => Self::Millau, - bp_runtime::RIALTO_CHAIN_ID => Self::Rialto, - bp_runtime::RIALTO_PARACHAIN_CHAIN_ID => Self::RialtoParachain, - _ => return Err(()), - }) - } -} - -impl CustomNetworkId { - /// Converts self to XCM' network id. - pub const fn as_network_id(&self) -> NetworkId { - match *self { - CustomNetworkId::Millau => NetworkId::Kusama, - CustomNetworkId::Rialto => NetworkId::Polkadot, - CustomNetworkId::RialtoParachain => NetworkId::Westend, - } - } -} - #[cfg(test)] mod tests { use crate::BridgeRuntimeFilterCall; diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 45ef790d74482..943a98284a5e7 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -14,12 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! A mock runtime for testing different stuff in the crate. We've been using Millau -//! runtime for that before, but it has two drawbacks: -//! -//! - circular dependencies between this crate and Millau runtime; -//! -//! - we can't use (e.g. as git subtree or by copying) this crate in repo without Millau. +//! A mock runtime for testing different stuff in the crate. #![cfg(test)] diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs index fd10344812517..a597fb9e2f492 100644 --- a/bin/runtime-common/src/priority_calculator.rs +++ b/bin/runtime-common/src/priority_calculator.rs @@ -27,6 +27,7 @@ use frame_support::traits::Get; use sp_runtime::transaction_validity::TransactionPriority; // reexport everything from `integrity_tests` module +#[allow(unused_imports)] pub use integrity_tests::*; /// Compute priority boost for message delivery transaction that delivers diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md index 42efc8100bd08..d6d6fb3f0996d 100644 --- a/docs/high-level-overview.md +++ b/docs/high-level-overview.md @@ -1,7 +1,7 @@ # High-Level Bridge Documentation This document gives a brief, abstract description of main components that may be found in this repository. If you want -to see how we're using them to build Rococo <> Wococo (Kusama <> Polkadot) bridge, please refer to the [Polkadot <> +to see how we're using them to build Rococo <> Westend (Kusama <> Polkadot) bridge, please refer to the [Polkadot <> Kusama Bridge](./polkadot-kusama-bridge-overview.md). ## Purpose diff --git a/modules/grandpa/src/weights.rs b/modules/grandpa/src/weights.rs index 89ed70d13ac33..a75e7b5a8e4ad 100644 --- a/modules/grandpa/src/weights.rs +++ b/modules/grandpa/src/weights.rs @@ -23,7 +23,7 @@ //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/millau-bridge-node +// target/release/unknown-bridge-node // benchmark // pallet // --chain=dev @@ -58,39 +58,39 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { - /// Storage: BridgeRialtoGrandpa PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownGrandpa PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa RequestCount (r:1 w:1) + /// Storage: BridgeUnknownGrandpa RequestCount (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa RequestCount (max_values: Some(1), max_size: Some(4), added: 499, - /// mode: MaxEncodedLen) + /// Proof: BridgeUnknownGrandpa RequestCount (max_values: Some(1), max_size: Some(4), added: + /// 499, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa BestFinalized (r:1 w:1) + /// Storage: BridgeUnknownGrandpa BestFinalized (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: + /// Proof: BridgeUnknownGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: /// 531, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa CurrentAuthoritySet (r:1 w:0) + /// Storage: BridgeUnknownGrandpa CurrentAuthoritySet (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(209), + /// Proof: BridgeUnknownGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(209), /// added: 704, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHashesPointer (r:1 w:1) + /// Storage: BridgeUnknownGrandpa ImportedHashesPointer (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), + /// Proof: BridgeUnknownGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), /// added: 499, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1) + /// Storage: BridgeUnknownGrandpa ImportedHashes (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36), + /// Proof: BridgeUnknownGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36), /// added: 2016, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:0 w:2) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 4]`. @@ -113,39 +113,39 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { - /// Storage: BridgeRialtoGrandpa PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownGrandpa PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa RequestCount (r:1 w:1) + /// Storage: BridgeUnknownGrandpa RequestCount (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa RequestCount (max_values: Some(1), max_size: Some(4), added: 499, - /// mode: MaxEncodedLen) + /// Proof: BridgeUnknownGrandpa RequestCount (max_values: Some(1), max_size: Some(4), added: + /// 499, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa BestFinalized (r:1 w:1) + /// Storage: BridgeUnknownGrandpa BestFinalized (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: + /// Proof: BridgeUnknownGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: /// 531, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa CurrentAuthoritySet (r:1 w:0) + /// Storage: BridgeUnknownGrandpa CurrentAuthoritySet (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(209), + /// Proof: BridgeUnknownGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(209), /// added: 704, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHashesPointer (r:1 w:1) + /// Storage: BridgeUnknownGrandpa ImportedHashesPointer (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), + /// Proof: BridgeUnknownGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), /// added: 499, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHashes (r:1 w:1) + /// Storage: BridgeUnknownGrandpa ImportedHashes (r:1 w:1) /// - /// Proof: BridgeRialtoGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36), + /// Proof: BridgeUnknownGrandpa ImportedHashes (max_values: Some(14400), max_size: Some(36), /// added: 2016, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:0 w:2) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:0 w:2) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 4]`. diff --git a/modules/messages/src/weights.rs b/modules/messages/src/weights.rs index 5b6863984ec78..5bf7d56756079 100644 --- a/modules/messages/src/weights.rs +++ b/modules/messages/src/weights.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Autogenerated weights for RialtoMessages +//! Autogenerated weights for pallet_bridge_messages //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev //! DATE: 2023-03-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` @@ -23,13 +23,13 @@ //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/millau-bridge-node +// target/release/unknown-bridge-node // benchmark // pallet // --chain=dev // --steps=50 // --repeat=20 -// --pallet=RialtoMessages +// --pallet=pallet_bridge_messages // --extrinsic=* // --execution=wasm // --wasm-execution=Compiled @@ -48,7 +48,7 @@ use frame_support::{ }; use sp_std::marker::PhantomData; -/// Weight functions needed for RialtoMessages. +/// Weight functions needed for pallet_bridge_messages. pub trait WeightInfo { fn receive_single_message_proof() -> Weight; fn receive_two_messages_proof() -> Weight; @@ -61,24 +61,24 @@ pub trait WeightInfo { fn receive_single_message_proof_with_dispatch(i: u32) -> Weight; } -/// Weights for `RialtoMessages` that are generated using one of the Bridge testnets. +/// Weights for `pallet_bridge_messages` that are generated using one of the Bridge testnets. /// /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: @@ -89,19 +89,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: @@ -112,19 +112,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: @@ -135,19 +135,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: @@ -158,19 +158,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: @@ -181,19 +181,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// Proof: BridgeUnknownMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) @@ -209,19 +209,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// Proof: BridgeUnknownMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) @@ -237,19 +237,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// Proof: BridgeUnknownMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) @@ -265,19 +265,19 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) /// /// The range of component `i` is `[128, 2048]`. @@ -296,19 +296,19 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof() -> Weight { // Proof Size summary in bytes: @@ -319,19 +319,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_two_messages_proof() -> Weight { // Proof Size summary in bytes: @@ -342,19 +342,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_with_outbound_lane_state() -> Weight { // Proof Size summary in bytes: @@ -365,19 +365,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_1_kb() -> Weight { // Proof Size summary in bytes: @@ -388,19 +388,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) fn receive_single_message_proof_16_kb() -> Weight { // Proof Size summary in bytes: @@ -411,19 +411,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// Proof: BridgeUnknownMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) @@ -439,19 +439,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// Proof: BridgeUnknownMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) @@ -467,19 +467,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages OutboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages OutboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: + /// Proof: BridgeUnknownMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: /// 539, mode: MaxEncodedLen) /// /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) @@ -495,19 +495,19 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: BridgeRialtoMessages PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownMessages PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), + /// Proof: BridgeUnknownMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), /// added: 497, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoMessages InboundLanes (r:1 w:1) + /// Storage: BridgeUnknownMessages InboundLanes (r:1 w:1) /// - /// Proof: BridgeRialtoMessages InboundLanes (max_values: None, max_size: Some(49180), added: + /// Proof: BridgeUnknownMessages InboundLanes (max_values: None, max_size: Some(49180), added: /// 51655, mode: MaxEncodedLen) /// /// The range of component `i` is `[128, 2048]`. diff --git a/modules/parachains/src/weights.rs b/modules/parachains/src/weights.rs index 9182ec466117b..abddc87689470 100644 --- a/modules/parachains/src/weights.rs +++ b/modules/parachains/src/weights.rs @@ -23,7 +23,7 @@ //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/millau-bridge-node +// target/release/unknown-bridge-node // benchmark // pallet // --chain=dev @@ -60,29 +60,29 @@ pub trait WeightInfo { /// Those weights are test only and must never be used in production. pub struct BridgeWeight(PhantomData); impl WeightInfo for BridgeWeight { - /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: /// 555, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size: /// Some(64), added: 1549, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size: /// Some(196), added: 1681, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. @@ -97,29 +97,29 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: /// 555, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size: /// Some(64), added: 1549, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size: /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { // Proof Size summary in bytes: @@ -130,29 +130,29 @@ impl WeightInfo for BridgeWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: /// 555, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size: /// Some(64), added: 1549, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size: /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { // Proof Size summary in bytes: @@ -167,29 +167,29 @@ impl WeightInfo for BridgeWeight { // For backwards compatibility and tests impl WeightInfo for () { - /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: /// 555, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size: /// Some(64), added: 1549, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size: /// Some(196), added: 1681, mode: MaxEncodedLen) /// /// The range of component `p` is `[1, 2]`. @@ -204,29 +204,29 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: /// 555, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size: /// Some(64), added: 1549, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size: /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_1kb_proof() -> Weight { // Proof Size summary in bytes: @@ -237,29 +237,29 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: BridgeRialtoParachains PalletOperatingMode (r:1 w:0) + /// Storage: BridgeUnknownParachains PalletOperatingMode (r:1 w:0) /// - /// Proof: BridgeRialtoParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), + /// Proof: BridgeUnknownParachains PalletOperatingMode (max_values: Some(1), max_size: Some(1), /// added: 496, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoGrandpa ImportedHeaders (r:1 w:0) + /// Storage: BridgeUnknownGrandpa ImportedHeaders (r:1 w:0) /// - /// Proof: BridgeRialtoGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), + /// Proof: BridgeUnknownGrandpa ImportedHeaders (max_values: Some(14400), max_size: Some(68), /// added: 2048, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ParasInfo (r:1 w:1) + /// Storage: BridgeUnknownParachains ParasInfo (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: + /// Proof: BridgeUnknownParachains ParasInfo (max_values: Some(1), max_size: Some(60), added: /// 555, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHashes (r:1 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHashes (r:1 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHashes (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHashes (max_values: Some(1024), max_size: /// Some(64), added: 1549, mode: MaxEncodedLen) /// - /// Storage: BridgeRialtoParachains ImportedParaHeads (r:0 w:1) + /// Storage: BridgeUnknownParachains ImportedParaHeads (r:0 w:1) /// - /// Proof: BridgeRialtoParachains ImportedParaHeads (max_values: Some(1024), max_size: + /// Proof: BridgeUnknownParachains ImportedParaHeads (max_values: Some(1024), max_size: /// Some(196), added: 1681, mode: MaxEncodedLen) fn submit_parachain_heads_with_16kb_proof() -> Weight { // Proof Size summary in bytes: diff --git a/modules/parachains/src/weights_ext.rs b/modules/parachains/src/weights_ext.rs index 13bc9ad2bbce0..393086a85690f 100644 --- a/modules/parachains/src/weights_ext.rs +++ b/modules/parachains/src/weights_ext.rs @@ -31,7 +31,7 @@ use frame_support::weights::{RuntimeDbWeight, Weight}; pub const DEFAULT_PARACHAIN_HEAD_SIZE: u32 = 384; /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at -/// the Rialto chain. +/// some generic chain. pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; /// Extended weight info. diff --git a/modules/relayers/src/weights.rs b/modules/relayers/src/weights.rs index 2e064a3936df3..c2c065b0c0a27 100644 --- a/modules/relayers/src/weights.rs +++ b/modules/relayers/src/weights.rs @@ -23,7 +23,7 @@ //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/millau-bridge-node +// target/release/rip-bridge-node // benchmark // pallet // --chain=dev diff --git a/modules/shift-session-manager/Cargo.toml b/modules/shift-session-manager/Cargo.toml deleted file mode 100644 index e70dd6ace16e4..0000000000000 --- a/modules/shift-session-manager/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "pallet-shift-session-manager" -description = "A Substrate Runtime module that selects 2/3 of initial validators for every session" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -pallet-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-staking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[dev-dependencies] -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-state-machine = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[features] -default = [ "std" ] -std = [ - "codec/std", - "frame-support/std", - "frame-system/std", - "pallet-session/std", - "scale-info/std", - "sp-staking/std", - "sp-std/std", -] -try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] diff --git a/modules/shift-session-manager/README.md b/modules/shift-session-manager/README.md deleted file mode 100644 index 8dfbfd416e3cc..0000000000000 --- a/modules/shift-session-manager/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Shift Session Manager Pallet - -**THIS PALLET IS NOT INTENDED TO BE USED IN PRODUCTION** - -The pallet does not provide any calls or runtime storage entries. It only provides implementation of the -`pallet_session::SessionManager`. This implementation, starting from session `3` selects two thirds of initial -validators and changes the set on every session. We are using it at our testnets ([Rialto](../../bin/rialto/) and -[Millau](../../bin/millau/)) to be sure that the set changes every session. On well-known production chains -(like Kusama and Polkadot) the alternative is the set of [nPoS](https://research.web3.foundation/en/latest/polkadot/NPoS/index.html) -pallets, which selects validators, based on their nominations. diff --git a/modules/shift-session-manager/src/lib.rs b/modules/shift-session-manager/src/lib.rs deleted file mode 100644 index 49690842418ce..0000000000000 --- a/modules/shift-session-manager/src/lib.rs +++ /dev/null @@ -1,259 +0,0 @@ -// 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 . - -//! Substrate session manager that selects 2/3 validators from initial set, -//! starting from session 2. - -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::traits::{ValidatorSet, ValidatorSetWithIdentification}; -use sp_std::prelude::*; - -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::config] - #[pallet::disable_frame_system_supertrait_check] - pub trait Config: pallet_session::Config {} - - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::call] - impl Pallet {} - - /// Validators of first two sessions. - #[pallet::storage] - pub(super) type InitialValidators = StorageValue<_, Vec>; -} - -impl ValidatorSet for Pallet { - type ValidatorId = T::ValidatorId; - type ValidatorIdOf = T::ValidatorIdOf; - - fn session_index() -> sp_staking::SessionIndex { - pallet_session::Pallet::::current_index() - } - - fn validators() -> Vec { - pallet_session::Pallet::::validators() - } -} - -impl ValidatorSetWithIdentification for Pallet { - type Identification = (); - type IdentificationOf = (); -} - -impl pallet_session::SessionManager for Pallet { - fn end_session(_: sp_staking::SessionIndex) {} - fn start_session(_: sp_staking::SessionIndex) {} - fn new_session(session_index: sp_staking::SessionIndex) -> Option> { - // we don't want to add even more fields to genesis config => just return None - if session_index == 0 || session_index == 1 { - return None - } - - // the idea that on first call (i.e. when session 1 ends) we're reading current - // set of validators from session module (they are initial validators) and save - // in our 'local storage'. - // then for every session we select (deterministically) 2/3 of these initial - // validators to serve validators of new session - let available_validators = InitialValidators::::get().unwrap_or_else(|| { - let validators = >::validators(); - InitialValidators::::put(validators.clone()); - validators - }); - - Some(Self::select_validators(session_index, &available_validators)) - } -} - -impl Pallet { - /// Select validators for session. - fn select_validators( - session_index: sp_staking::SessionIndex, - available_validators: &[T::ValidatorId], - ) -> Vec { - let available_validators_count = available_validators.len(); - let count = sp_std::cmp::max(1, 2 * available_validators_count / 3); - let offset = session_index as usize % available_validators_count; - let end = offset + count; - let session_validators = match end.overflowing_sub(available_validators_count) { - (wrapped_end, false) if wrapped_end != 0 => available_validators[offset..] - .iter() - .chain(available_validators[..wrapped_end].iter()) - .cloned() - .collect(), - _ => available_validators[offset..end].to_vec(), - }; - - session_validators - } -} - -#[cfg(test)] -mod tests { - // From construct_runtime macro - #![allow(clippy::from_over_into)] - - use super::*; - use frame_support::{ - parameter_types, - sp_runtime::{ - testing::UintAuthorityId, - traits::{BlakeTwo256, ConvertInto, IdentityLookup}, - BuildStorage, Perbill, RuntimeAppPublic, - }, - weights::Weight, - }; - use sp_core::H256; - use sp_io::TestExternalities; - use sp_state_machine::BasicExternalities; - - type AccountId = u64; - - type Block = frame_system::mocking::MockBlock; - - frame_support::construct_runtime! { - pub enum TestRuntime { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Session: pallet_session::{Pallet}, - } - } - - parameter_types! { - pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Block = Block; - type RuntimeEvent = (); - type BlockHashCount = frame_support::traits::ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - - parameter_types! { - pub const Period: u64 = 1; - pub const Offset: u64 = 0; - } - - impl pallet_session::Config for TestRuntime { - type RuntimeEvent = (); - type ValidatorId = ::AccountId; - type ValidatorIdOf = ConvertInto; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = (); - type SessionHandler = TestSessionHandler; - type Keys = UintAuthorityId; - type WeightInfo = (); - } - - impl Config for TestRuntime {} - - pub struct TestSessionHandler; - impl pallet_session::SessionHandler for TestSessionHandler { - const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID]; - - fn on_genesis_session(_validators: &[(AccountId, Ks)]) { - } - - fn on_new_session( - _: bool, - _: &[(AccountId, Ks)], - _: &[(AccountId, Ks)], - ) { - } - - fn on_disabled(_: u32) {} - } - - fn new_test_ext() -> TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - let keys = vec![ - (1, 1, UintAuthorityId(1)), - (2, 2, UintAuthorityId(2)), - (3, 3, UintAuthorityId(3)), - (4, 4, UintAuthorityId(4)), - (5, 5, UintAuthorityId(5)), - ]; - - BasicExternalities::execute_with_storage(&mut t, || { - for (ref k, ..) in &keys { - frame_system::Pallet::::inc_providers(k); - } - }); - - pallet_session::GenesisConfig:: { keys } - .assimilate_storage(&mut t) - .unwrap(); - TestExternalities::new(t) - } - - #[test] - fn shift_session_manager_works() { - new_test_ext().execute_with(|| { - let all_accs = vec![1, 2, 3, 4, 5]; - - // at least 1 validator is selected - assert_eq!(Pallet::::select_validators(0, &[1]), vec![1],); - - // at session#0, shift is also 0 - assert_eq!(Pallet::::select_validators(0, &all_accs), vec![1, 2, 3],); - - // at session#1, shift is also 1 - assert_eq!(Pallet::::select_validators(1, &all_accs), vec![2, 3, 4],); - - // at session#3, we're wrapping - assert_eq!(Pallet::::select_validators(3, &all_accs), vec![4, 5, 1],); - - // at session#5, we're starting from the beginning again - assert_eq!(Pallet::::select_validators(5, &all_accs), vec![1, 2, 3],); - }); - } -} diff --git a/modules/xcm-bridge-hub-router/src/weights.rs b/modules/xcm-bridge-hub-router/src/weights.rs index 62936e997f3cd..b0c8fc6252cd5 100644 --- a/modules/xcm-bridge-hub-router/src/weights.rs +++ b/modules/xcm-bridge-hub-router/src/weights.rs @@ -23,7 +23,7 @@ //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// target/release/millau-bridge-node +// target/release/rip-bridge-node // benchmark // pallet // --chain=dev diff --git a/primitives/chain-millau/Cargo.toml b/primitives/chain-millau/Cargo.toml deleted file mode 100644 index 5ea9d36f9f7b1..0000000000000 --- a/primitives/chain-millau/Cargo.toml +++ /dev/null @@ -1,62 +0,0 @@ -[package] -name = "bp-millau" -description = "Primitives of Millau runtime." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# TODO: Consume `fixed-hash` from crates.io when the following fix is published: -# https://github.com/paritytech/parity-common/commit/d3a9327124a66e52ca1114bb8640c02c18c134b8 -# Expected in a version > 0.8.0 -fixed-hash = { git = "https://github.com/paritytech/parity-common", branch = "master", default-features = false } -hash256-std-hasher = { version = "0.15.2", default-features = false } -impl-codec = { version = "0.6", default-features = false } -impl-serde = { version = "0.4.0", default-features = false } -parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } - -# Bridge Dependencies - -bp-beefy = { path = "../beefy", default-features = false } -bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } - -# Substrate Based Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-beefy/std", - "bp-header-chain/std", - "bp-messages/std", - "bp-runtime/std", - "fixed-hash/std", - "frame-support/std", - "frame-system/std", - "hash256-std-hasher/std", - "impl-codec/std", - "impl-serde/std", - "parity-util-mem/std", - "scale-info/std", - "serde/std", - "sp-api/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "sp-trie/std", -] diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs deleted file mode 100644 index 0c31287166661..0000000000000 --- a/primitives/chain-millau/src/lib.rs +++ /dev/null @@ -1,244 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] - -mod millau_hash; - -use bp_beefy::ChainWithBeefy; -use bp_header_chain::ChainWithGrandpa; -use bp_messages::MessageNonce; -use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; -use frame_support::{ - dispatch::DispatchClass, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, -}; -use frame_system::limits; -use scale_info::TypeInfo; -use serde::{Deserialize, Serialize}; -use sp_core::{storage::StateVersion, Hasher as HasherT}; -use sp_runtime::{ - traits::{IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, RuntimeDebug, -}; -use sp_std::prelude::*; -use sp_trie::{LayoutV0, LayoutV1, TrieConfiguration}; - -use sp_runtime::traits::Keccak256; - -pub use millau_hash::MillauHash; - -/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at -/// Millau chain. This mostly depends on number of entries (and their density) in the storage trie. -/// Some reserve is reserved to account future chain growth. -pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; - -/// Number of bytes, included in the signed Millau transaction apart from the encoded call itself. -/// -/// Can be computed by subtracting encoded call size from raw transaction size. -pub const TX_EXTRA_BYTES: u32 = 103; - -/// Maximum weight of single Millau block. -/// -/// This represents 0.5 seconds of compute assuming a target block time of six seconds. -/// -/// Max PoV size is set to max value, since it isn't important for relay/standalone chains. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), u64::MAX); - -/// Represents the portion of a block that will be used by Normal extrinsics. -pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); - -/// Maximal number of unrewarded relayer entries in Millau confirmation transaction. -pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 128; - -/// Maximal number of unconfirmed messages in Millau confirmation transaction. -pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 128; - -/// The target length of a session (how often authorities change) on Millau measured in of number of -/// blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = 5 * time_units::MINUTES; - -/// Maximal number of GRANDPA authorities at Millau. -pub const MAX_AUTHORITIES_COUNT: u32 = 5; - -/// Reasonable number of headers in the `votes_ancestries` on Millau chain. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; - -/// Approximate average header size in `votes_ancestries` field of justification on Millau chain. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; - -/// Approximate maximal header size on Millau chain. -/// -/// We expect maximal header to have digest item with the new authorities set for every consensus -/// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also -/// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT - .saturating_mul(3) - .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); - -/// Re-export `time_units` to make usage easier. -pub use time_units::*; - -/// Human readable time units defined in terms of number of blocks. -pub mod time_units { - use super::BlockNumber; - - pub const MILLISECS_PER_BLOCK: u64 = 6000; - pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - - pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); - pub const HOURS: BlockNumber = MINUTES * 60; - pub const DAYS: BlockNumber = HOURS * 24; -} - -/// Block number type used in Millau. -pub type BlockNumber = u64; - -/// Hash type used in Millau. -pub type Hash = ::Out; - -/// Type of object that can produce hashes on Millau. -pub type Hasher = BlakeTwoAndKeccak256; - -/// The header type used by Millau. -pub type Header = sp_runtime::generic::Header; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// Public key of the chain account that may be used to verify signatures. -pub type AccountSigner = MultiSigner; - -/// Balance of an account. -pub type Balance = u64; - -/// Nonce of a transaction in the chain. -pub type Nonce = u32; - -/// Weight-to-Fee type used by Millau. -pub type WeightToFee = IdentityFee; - -/// Millau chain. -#[derive(RuntimeDebug)] -pub struct Millau; - -impl Chain for Millau { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) - } - - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) - } -} - -impl ChainWithGrandpa for Millau { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_MILLAU_GRANDPA_PALLET_NAME; - const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; -} - -impl ChainWithBeefy for Millau { - type CommitmentHasher = Keccak256; - type MmrHashing = Keccak256; - type MmrHash = ::Output; - type BeefyMmrLeafExtra = (); - type AuthorityId = bp_beefy::EcdsaValidatorId; - type AuthorityIdToMerkleLeaf = bp_beefy::BeefyEcdsaToEthereum; -} - -/// Millau Hasher (Blake2-256 ++ Keccak-256) implementation. -#[derive(PartialEq, Eq, Clone, Copy, RuntimeDebug, TypeInfo, Serialize, Deserialize)] -pub struct BlakeTwoAndKeccak256; - -impl sp_core::Hasher for BlakeTwoAndKeccak256 { - type Out = MillauHash; - type StdHasher = hash256_std_hasher::Hash256StdHasher; - const LENGTH: usize = 64; - - fn hash(s: &[u8]) -> Self::Out { - let mut combined_hash = MillauHash::default(); - combined_hash.as_mut()[..32].copy_from_slice(&sp_io::hashing::blake2_256(s)); - combined_hash.as_mut()[32..].copy_from_slice(&sp_io::hashing::keccak_256(s)); - combined_hash - } -} - -impl sp_runtime::traits::Hash for BlakeTwoAndKeccak256 { - type Output = MillauHash; - - fn trie_root(input: Vec<(Vec, Vec)>, state_version: StateVersion) -> Self::Output { - match state_version { - StateVersion::V0 => LayoutV0::::trie_root(input), - StateVersion::V1 => LayoutV1::::trie_root(input), - } - } - - fn ordered_trie_root(input: Vec>, state_version: StateVersion) -> Self::Output { - match state_version { - StateVersion::V0 => LayoutV0::::ordered_trie_root(input), - StateVersion::V1 => LayoutV1::::ordered_trie_root(input), - } - } -} - -frame_support::parameter_types! { - pub BlockLength: limits::BlockLength = - limits::BlockLength::max_with_normal_ratio(2 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub BlockWeights: limits::BlockWeights = - limits::BlockWeights::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); -} - -/// Name of the With-Millau GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_MILLAU_GRANDPA_PALLET_NAME: &str = "BridgeMillauGrandpa"; -/// Name of the With-Millau messages pallet instance that is deployed at bridged chains. -pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; -/// Name of the transaction payment pallet at the Millau runtime. -pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; - -decl_bridge_runtime_apis!(millau, grandpa); diff --git a/primitives/chain-millau/src/millau_hash.rs b/primitives/chain-millau/src/millau_hash.rs deleted file mode 100644 index 8851c319dd451..0000000000000 --- a/primitives/chain-millau/src/millau_hash.rs +++ /dev/null @@ -1,56 +0,0 @@ -// 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 . - -use parity_util_mem::MallocSizeOf; -use scale_info::TypeInfo; -use sp_runtime::traits::CheckEqual; - -// `sp_core::H512` can't be used, because it doesn't implement `CheckEqual`, which is required -// by `frame_system::Config::Hash`. - -fixed_hash::construct_fixed_hash! { - /// Hash type used in Millau chain. - #[derive(MallocSizeOf, TypeInfo)] - pub struct MillauHash(64); -} - -impl_serde::impl_fixed_hash_serde!(MillauHash, 64); -impl_codec::impl_fixed_hash_codec!(MillauHash, 64); - -impl CheckEqual for MillauHash { - #[cfg(feature = "std")] - fn check_equal(&self, other: &Self) { - use sp_core::hexdisplay::HexDisplay; - if self != other { - println!( - "Hash: given={}, expected={}", - HexDisplay::from(self.as_fixed_bytes()), - HexDisplay::from(other.as_fixed_bytes()), - ); - } - } - - #[cfg(not(feature = "std"))] - fn check_equal(&self, other: &Self) { - use frame_support::Printable; - - if self != other { - "Hash not equal".print(); - self.as_bytes().print(); - other.as_bytes().print(); - } - } -} diff --git a/primitives/chain-rialto-parachain/Cargo.toml b/primitives/chain-rialto-parachain/Cargo.toml deleted file mode 100644 index 0122c508e2b92..0000000000000 --- a/primitives/chain-rialto-parachain/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "bp-rialto-parachain" -description = "Primitives of Rialto parachain runtime." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# Bridge Dependencies - -bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } - -# Substrate Based Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-bridge-hub-cumulus/std", - "bp-messages/std", - "bp-runtime/std", - "frame-support/std", - "frame-system/std", - "sp-api/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/primitives/chain-rialto-parachain/src/lib.rs b/primitives/chain-rialto-parachain/src/lib.rs deleted file mode 100644 index 18655503edddf..0000000000000 --- a/primitives/chain-rialto-parachain/src/lib.rs +++ /dev/null @@ -1,148 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] - -use bp_messages::MessageNonce; -use bp_runtime::{decl_bridge_runtime_apis, Chain, Parachain}; -use frame_support::{ - dispatch::DispatchClass, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, -}; -use frame_system::limits; -use sp_core::Hasher as HasherT; -use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, RuntimeDebug, -}; - -/// Identifier of RialtoParachain in the Rialto relay chain. -/// -/// This identifier is not something that is declared either by Rialto or RialtoParachain. This -/// is an identifier of registration. So in theory it may be changed. But since bridge is going -/// to be deployed after parachain registration AND since parachain de-registration is highly -/// likely impossible, it is fine to declare this constant here. -pub const RIALTO_PARACHAIN_ID: u32 = 2000; - -/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at -/// RialtoParachain chain. This mostly depends on number of entries (and their density) in the -/// storage trie. Some reserve is reserved to account future chain growth. -pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; - -/// Can be computed by subtracting encoded call size from raw transaction size. -pub const TX_EXTRA_BYTES: u32 = 104; - -/// Maximal weight of single RialtoParachain block. -/// -/// This represents two seconds of compute assuming a target block time of six seconds. -/// -/// Max PoV size is set to `5Mb` as all Cumulus-based parachains do. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), 5 * 1024 * 1024); - -/// Represents the portion of a block that will be used by Normal extrinsics. -pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); - -/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction. -pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; - -/// Maximal number of unconfirmed messages in Rialto confirmation transaction. -pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; - -/// Block number type used in Rialto. -pub type BlockNumber = u32; - -/// Hash type used in Rialto. -pub type Hash = ::Out; - -/// The type of object that can produce hashes on Rialto. -pub type Hasher = BlakeTwo256; - -/// The header type used by Rialto. -pub type Header = sp_runtime::generic::Header; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// Public key of the chain account that may be used to verify signatures. -pub type AccountSigner = MultiSigner; - -/// Balance of an account. -pub type Balance = u128; - -/// An instant or duration in time. -pub type Moment = u64; - -/// Nonce of a transaction in the parachain. -pub type Nonce = u32; - -/// Weight-to-Fee type used by Rialto parachain. -pub type WeightToFee = IdentityFee; - -/// Rialto parachain. -#[derive(RuntimeDebug)] -pub struct RialtoParachain; - -impl Chain for RialtoParachain { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) - } - - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) - } -} - -impl Parachain for RialtoParachain { - const PARACHAIN_ID: u32 = RIALTO_PARACHAIN_ID; -} - -// Technically this is incorrect, because rialto-parachain isn't a bridge hub, but we're -// trying to keep it close to the bridge hubs code (at least in this aspect). -pub use bp_bridge_hub_cumulus::SignedExtension; - -frame_support::parameter_types! { - pub BlockLength: limits::BlockLength = - limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub BlockWeights: limits::BlockWeights = - limits::BlockWeights::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); -} - -/// Name of the With-Rialto-Parachain messages pallet instance that is deployed at bridged chains. -pub const WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME: &str = "BridgeRialtoParachainMessages"; -/// Name of the transaction payment pallet at the Rialto parachain runtime. -pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; - -decl_bridge_runtime_apis!(rialto_parachain); diff --git a/primitives/chain-rialto/Cargo.toml b/primitives/chain-rialto/Cargo.toml deleted file mode 100644 index 083abbd545840..0000000000000 --- a/primitives/chain-rialto/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "bp-rialto" -description = "Primitives of Rialto runtime." -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# Bridge Dependencies - -bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } - -# Substrate Based Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-header-chain/std", - "bp-messages/std", - "bp-runtime/std", - "frame-support/std", - "frame-system/std", - "sp-api/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs deleted file mode 100644 index 9d5215c10292a..0000000000000 --- a/primitives/chain-rialto/src/lib.rs +++ /dev/null @@ -1,210 +0,0 @@ -// 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] - -use bp_header_chain::ChainWithGrandpa; -use bp_messages::MessageNonce; -use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; -use frame_support::{ - dispatch::DispatchClass, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, -}; -use frame_system::limits; -use sp_core::Hasher as HasherT; -use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiSignature, MultiSigner, Perbill, RuntimeDebug, -}; - -/// Number of extra bytes (excluding size of storage value itself) of storage proof, built at -/// Rialto chain. This mostly depends on number of entries (and their density) in the storage trie. -/// Some reserve is reserved to account future chain growth. -pub const EXTRA_STORAGE_PROOF_SIZE: u32 = 1024; - -/// Number of bytes, included in the signed Rialto transaction apart from the encoded call itself. -/// -/// Can be computed by subtracting encoded call size from raw transaction size. -pub const TX_EXTRA_BYTES: u32 = 104; - -/// Maximal weight of single Rialto block. -/// -/// This represents two seconds of compute assuming a target block time of six seconds. -/// -/// Max PoV size is set to max value, since it isn't important for relay/standalone chains. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX); - -/// Represents the portion of a block that will be used by Normal extrinsics. -pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); - -/// Maximal number of unrewarded relayer entries in Rialto confirmation transaction. -pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; - -/// Maximal number of unconfirmed messages in Rialto confirmation transaction. -pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 1024; - -/// The target length of a session (how often authorities change) on Rialto measured in of number of -/// blocks. -/// -/// Note that since this is a target sessions may change before/after this time depending on network -/// conditions. -pub const SESSION_LENGTH: BlockNumber = 4; - -/// Maximal number of GRANDPA authorities at Rialto. -pub const MAX_AUTHORITIES_COUNT: u32 = 5; - -/// Reasonable number of headers in the `votes_ancestries` on Rialto chain. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; - -/// Approximate average header size in `votes_ancestries` field of justification on Rialto chain. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 256; - -/// Approximate maximal header size on Rialto chain. -/// -/// We expect maximal header to have digest item with the new authorities set for every consensus -/// engine (GRANDPA, Babe, BEEFY, ...) - so we multiply it by 3. And also -/// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION` bytes for other stuff. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -pub const MAX_HEADER_SIZE: u32 = MAX_AUTHORITIES_COUNT - .saturating_mul(3) - .saturating_add(AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); - -/// Maximal size of encoded `bp_parachains::ParaStoredHeaderData` structure among all Rialto -/// parachains. -/// -/// It includes the block number and state root, so it shall be near 40 bytes, but let's have some -/// reserve. -pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; - -/// Re-export `time_units` to make usage easier. -pub use time_units::*; - -/// Human readable time units defined in terms of number of blocks. -pub mod time_units { - use super::{BlockNumber, SESSION_LENGTH}; - - pub const MILLISECS_PER_BLOCK: u64 = 6000; - pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - - pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); - pub const HOURS: BlockNumber = MINUTES * 60; - pub const DAYS: BlockNumber = HOURS * 24; - - pub const EPOCH_DURATION_IN_SLOTS: BlockNumber = SESSION_LENGTH; - - // 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks. - pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); -} - -/// Block number type used in Rialto. -pub type BlockNumber = u32; - -/// Hash type used in Rialto. -pub type Hash = ::Out; - -/// The type of object that can produce hashes on Rialto. -pub type Hasher = BlakeTwo256; - -/// The header type used by Rialto. -pub type Header = sp_runtime::generic::Header; - -/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. -pub type Signature = MultiSignature; - -/// Some way of identifying an account on the chain. We intentionally make it equivalent -/// to the public key of our transaction signing scheme. -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -/// Public key of the chain account that may be used to verify signatures. -pub type AccountSigner = MultiSigner; - -/// Balance of an account. -pub type Balance = u128; - -/// An instant or duration in time. -pub type Moment = u64; - -/// Nonce of a transaction in the chain. -pub type Nonce = u32; - -/// Weight-to-Fee type used by Rialto. -pub type WeightToFee = IdentityFee; - -/// Rialto chain. -#[derive(RuntimeDebug)] -pub struct Rialto; - -impl Chain for Rialto { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) - } - - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) - } -} - -impl ChainWithGrandpa for Rialto { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_RIALTO_GRANDPA_PALLET_NAME; - const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; -} - -frame_support::parameter_types! { - pub BlockLength: limits::BlockLength = - limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub BlockWeights: limits::BlockWeights = - limits::BlockWeights::with_sensible_defaults(MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO); -} - -/// Name of the With-Rialto GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_RIALTO_GRANDPA_PALLET_NAME: &str = "BridgeRialtoGrandpa"; -/// Name of the With-Rialto messages pallet instance that is deployed at bridged chains. -pub const WITH_RIALTO_MESSAGES_PALLET_NAME: &str = "BridgeRialtoMessages"; -/// Name of the With-Rialto parachains bridge pallet instance that is deployed at bridged chains. -pub const WITH_RIALTO_BRIDGE_PARAS_PALLET_NAME: &str = "BridgeRialtoParachains"; - -/// Name of the parachain registrar pallet in the Rialto runtime. -pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; - -/// Name of the parachains pallet in the Rialto runtime. -pub const PARAS_PALLET_NAME: &str = "Paras"; - -decl_bridge_runtime_apis!(rialto, grandpa); diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index e1809e145248f..b78023efb1b86 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -280,7 +280,7 @@ pub type TransactionEraOf = crate::TransactionEra, HashOf /// - constants that are stringified names of runtime API methods: /// - `BEST_FINALIZED__HEADER_METHOD` /// - `_ACCEPTED__FINALITY_PROOFS_METHOD` -/// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). +/// The name of the chain has to be specified in snake case (e.g. `bridge_hub_polkadot`). #[macro_export] macro_rules! decl_bridge_finality_runtime_apis { ($chain: ident $(, $consensus: ident => $justification_type: ty)?) => { @@ -332,7 +332,7 @@ macro_rules! decl_bridge_finality_runtime_apis { /// - `FromInboundLaneApi` /// - constants that are stringified names of runtime API methods: /// - `FROM__MESSAGE_DETAILS_METHOD`, -/// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). +/// The name of the chain has to be specified in snake case (e.g. `bridge_hub_polkadot`). #[macro_export] macro_rules! decl_bridge_messages_runtime_apis { ($chain: ident) => { @@ -390,7 +390,7 @@ macro_rules! decl_bridge_messages_runtime_apis { /// Convenience macro that declares bridge finality runtime apis, bridge messages runtime apis /// and related constants for a chain. -/// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). +/// The name of the chain has to be specified in snake case (e.g. `bridge_hub_polkadot`). #[macro_export] macro_rules! decl_bridge_runtime_apis { ($chain: ident $(, $consensus: ident)?) => { diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index e5277d8db6a84..0b6f90fd934ff 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -61,15 +61,6 @@ pub use sp_runtime::paste; /// Use this when something must be shared among all instances. pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0]; -/// Rialto chain id. -pub const RIALTO_CHAIN_ID: ChainId = *b"rlto"; - -/// RialtoParachain chain id. -pub const RIALTO_PARACHAIN_CHAIN_ID: ChainId = *b"rlpa"; - -/// Millau chain id. -pub const MILLAU_CHAIN_ID: ChainId = *b"mlau"; - /// Polkadot chain id. pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; @@ -277,18 +268,6 @@ pub fn storage_map_final_key( 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); - buffer.push(b':'); - buffer.extend_from_slice(parameter_name.as_bytes()); - buffer.push(b':'); - StorageKey(sp_io::hashing::twox_128(&buffer).to_vec()) -} - /// This is how a storage key of storage value is computed. /// /// Copied from `frame_support::storage::storage_prefix`. @@ -574,14 +553,6 @@ where mod tests { use super::*; - #[test] - fn storage_parameter_key_works() { - assert_eq!( - storage_parameter_key("MillauToRialtoConversionRate"), - StorageKey(hex_literal::hex!("58942375551bb0af1682f72786b59d04").to_vec()), - ); - } - #[test] fn storage_value_key_works() { assert_eq!( diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index b4e69816e59c4..b1ebcbbdcee9b 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -25,19 +25,12 @@ strum = { version = "0.25.0", features = ["derive"] } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-millau = { path = "../../primitives/chain-millau" } bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rialto = { path = "../../primitives/chain-rialto" } -bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } -millau-runtime = { path = "../../bin/millau/runtime" } pallet-bridge-parachains = { path = "../../modules/parachains" } parachains-relay = { path = "../parachains" } -relay-millau-client = { path = "../client-millau" } -relay-rialto-client = { path = "../client-rialto" } -relay-rialto-parachain-client = { path = "../client-rialto-parachain" } relay-bridge-hub-kusama-client = { path = "../client-bridge-hub-kusama" } relay-bridge-hub-polkadot-client = { path = "../client-bridge-hub-polkadot" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } @@ -51,10 +44,6 @@ relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } relay-wococo-client = { path = "../client-wococo" } -rialto-runtime = { path = "../../bin/rialto/runtime" } -# we are not using this runtime to craft call or transactions, but we still need it -# to prepare large XCM messages -rialto-parachain-runtime = { path = "../../bin/rialto-parachain/runtime" } substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies @@ -63,14 +52,6 @@ frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = " sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -# Polkadot Dependencies -polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - [dev-dependencies] bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.4" diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs index 5a6bf72d0c523..5a40b80cb9321 100644 --- a/relays/bin-substrate/src/bridges/mod.rs +++ b/relays/bin-substrate/src/bridges/mod.rs @@ -18,8 +18,5 @@ pub mod kusama_polkadot; pub mod polkadot_bulletin; -pub mod rialto_millau; -pub mod rialto_parachain_millau; pub mod rococo_westend; pub mod rococo_wococo; -pub mod westend_millau; diff --git a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs deleted file mode 100644 index 7fd5513a27295..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_millau/millau_headers_to_rialto.rs +++ /dev/null @@ -1,74 +0,0 @@ -// 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 . - -//! Millau-to-Rialto headers sync entrypoint. - -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; -use substrate_relay_helper::{ - equivocation::{ - DirectReportGrandpaEquivocationCallBuilder, SubstrateEquivocationDetectionPipeline, - }, - finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Millau -> Rialto finalized headers bridge. -#[derive(Clone, Debug)] -pub struct MillauFinalityToRialto; - -impl SubstrateFinalityPipeline for MillauFinalityToRialto { - type SourceChain = relay_millau_client::Millau; - type TargetChain = relay_rialto_client::Rialto; - - type FinalityEngine = GrandpaFinalityEngine; -} - -impl SubstrateFinalitySyncPipeline for MillauFinalityToRialto { - type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< - Self, - rialto_runtime::Runtime, - rialto_runtime::MillauGrandpaInstance, - >; -} - -impl SubstrateEquivocationDetectionPipeline for MillauFinalityToRialto { - type ReportEquivocationCallBuilder = - DirectReportGrandpaEquivocationCallBuilder; -} - -/// `Millau` to `Rialto` bridge definition. -pub struct MillauToRialtoCliBridge {} - -impl CliBridgeBase for MillauToRialtoCliBridge { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_client::Rialto; -} - -impl RelayToRelayHeadersCliBridge for MillauToRialtoCliBridge { - type Finality = MillauFinalityToRialto; -} - -impl RelayToRelayEquivocationDetectionCliBridge for MillauToRialtoCliBridge { - type Equivocation = MillauFinalityToRialto; -} - -impl MessagesCliBridge for MillauToRialtoCliBridge { - type MessagesLane = - crate::bridges::rialto_millau::millau_messages_to_rialto::MillauMessagesToRialto; -} diff --git a/relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs b/relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs deleted file mode 100644 index e6a2ef1a85660..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_millau/millau_messages_to_rialto.rs +++ /dev/null @@ -1,47 +0,0 @@ -// 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 . - -//! Millau-to-Rialto messages sync entrypoint. - -use relay_millau_client::Millau; -use relay_rialto_client::Rialto; -use substrate_relay_helper::messages_lane::{ - DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, - SubstrateMessageLane, -}; - -/// Description of Millau -> Rialto messages bridge. -#[derive(Clone, Debug)] -pub struct MillauMessagesToRialto; - -impl SubstrateMessageLane for MillauMessagesToRialto { - type SourceChain = Millau; - type TargetChain = Rialto; - - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< - Self, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, - >; - type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< - Self, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, - >; - - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = (); -} diff --git a/relays/bin-substrate/src/bridges/rialto_millau/mod.rs b/relays/bin-substrate/src/bridges/rialto_millau/mod.rs deleted file mode 100644 index 2353b58ce616e..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_millau/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Rialto and Millau. - -pub mod millau_headers_to_rialto; -pub mod millau_messages_to_rialto; -pub mod rialto_headers_to_millau; -pub mod rialto_messages_to_millau; diff --git a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs deleted file mode 100644 index d9b98d77784e7..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_millau/rialto_headers_to_millau.rs +++ /dev/null @@ -1,74 +0,0 @@ -// 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 . - -//! Rialto-to-Millau headers sync entrypoint. - -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; -use substrate_relay_helper::{ - equivocation::{ - DirectReportGrandpaEquivocationCallBuilder, SubstrateEquivocationDetectionPipeline, - }, - finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Millau -> Rialto finalized headers bridge. -#[derive(Clone, Debug)] -pub struct RialtoFinalityToMillau; - -impl SubstrateFinalityPipeline for RialtoFinalityToMillau { - type SourceChain = relay_rialto_client::Rialto; - type TargetChain = relay_millau_client::Millau; - - type FinalityEngine = GrandpaFinalityEngine; -} - -impl SubstrateFinalitySyncPipeline for RialtoFinalityToMillau { - type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< - Self, - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >; -} - -impl SubstrateEquivocationDetectionPipeline for RialtoFinalityToMillau { - type ReportEquivocationCallBuilder = - DirectReportGrandpaEquivocationCallBuilder; -} - -/// `Rialto` to `Millau` bridge definition. -pub struct RialtoToMillauCliBridge {} - -impl CliBridgeBase for RialtoToMillauCliBridge { - type Source = relay_rialto_client::Rialto; - type Target = relay_millau_client::Millau; -} - -impl RelayToRelayHeadersCliBridge for RialtoToMillauCliBridge { - type Finality = RialtoFinalityToMillau; -} - -impl RelayToRelayEquivocationDetectionCliBridge for RialtoToMillauCliBridge { - type Equivocation = RialtoFinalityToMillau; -} - -impl MessagesCliBridge for RialtoToMillauCliBridge { - type MessagesLane = - crate::bridges::rialto_millau::rialto_messages_to_millau::RialtoMessagesToMillau; -} diff --git a/relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs deleted file mode 100644 index b45239fb9a91e..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_millau/rialto_messages_to_millau.rs +++ /dev/null @@ -1,47 +0,0 @@ -// 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 . - -//! Rialto-to-Millau messages sync entrypoint. - -use relay_millau_client::Millau; -use relay_rialto_client::Rialto; -use substrate_relay_helper::messages_lane::{ - DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, - SubstrateMessageLane, -}; - -/// Description of Rialto -> Millau messages bridge. -#[derive(Clone, Debug)] -pub struct RialtoMessagesToMillau; - -impl SubstrateMessageLane for RialtoMessagesToMillau { - type SourceChain = Rialto; - type TargetChain = Millau; - - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< - Self, - millau_runtime::Runtime, - millau_runtime::WithRialtoMessagesInstance, - >; - type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< - Self, - rialto_runtime::Runtime, - rialto_runtime::WithMillauMessagesInstance, - >; - - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = (); -} diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs deleted file mode 100644 index 051057e217665..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_headers_to_rialto_parachain.rs +++ /dev/null @@ -1,95 +0,0 @@ -// 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 . - -//! Millau-to-RialtoParachain headers sync entrypoint. - -// 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 . - -//! Millau-to-RialtoParachain headers sync entrypoint. - -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; -use substrate_relay_helper::{ - equivocation::{ - DirectReportGrandpaEquivocationCallBuilder, SubstrateEquivocationDetectionPipeline, - }, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - MillauFinalityToRialtoParachain, - MillauFinalityToRialtoParachainCallBuilder, - relay_rialto_parachain_client::RuntimeCall::BridgeMillauGrandpa, - relay_rialto_parachain_client::BridgeGrandpaCall::submit_finality_proof -); - -/// Description of Millau -> Rialto finalized headers bridge. -#[derive(Clone, Debug)] -pub struct MillauFinalityToRialtoParachain; - -impl SubstrateFinalityPipeline for MillauFinalityToRialtoParachain { - type SourceChain = relay_millau_client::Millau; - type TargetChain = relay_rialto_parachain_client::RialtoParachain; - - type FinalityEngine = GrandpaFinalityEngine; -} - -impl SubstrateFinalitySyncPipeline for MillauFinalityToRialtoParachain { - type SubmitFinalityProofCallBuilder = MillauFinalityToRialtoParachainCallBuilder; -} - -impl SubstrateEquivocationDetectionPipeline for MillauFinalityToRialtoParachain { - type ReportEquivocationCallBuilder = - DirectReportGrandpaEquivocationCallBuilder; -} - -/// `Millau` to `RialtoParachain` bridge definition. -pub struct MillauToRialtoParachainCliBridge {} - -impl CliBridgeBase for MillauToRialtoParachainCliBridge { - type Source = relay_millau_client::Millau; - type Target = relay_rialto_parachain_client::RialtoParachain; -} - -impl RelayToRelayHeadersCliBridge for MillauToRialtoParachainCliBridge { - type Finality = MillauFinalityToRialtoParachain; -} - -impl RelayToRelayEquivocationDetectionCliBridge for MillauToRialtoParachainCliBridge { - type Equivocation = MillauFinalityToRialtoParachain; -} - -impl MessagesCliBridge for MillauToRialtoParachainCliBridge { - type MessagesLane = - crate::bridges::rialto_parachain_millau::millau_messages_to_rialto_parachain::MillauMessagesToRialtoParachain; -} diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs deleted file mode 100644 index 8fedd22a40abe..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/millau_messages_to_rialto_parachain.rs +++ /dev/null @@ -1,51 +0,0 @@ -// 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 . - -//! Millau-to-RialtoParachain messages sync entrypoint. - -use relay_millau_client::Millau; -use relay_rialto_parachain_client::RialtoParachain; -use substrate_relay_helper::{ - messages_lane::{DirectReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane}, - UtilityPalletBatchCallBuilder, -}; - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - MillauMessagesToRialtoParachain, - MillauMessagesToRialtoParachainReceiveMessagesProofCallBuilder, - relay_rialto_parachain_client::RuntimeCall::BridgeMillauMessages, - relay_rialto_parachain_client::BridgeMessagesCall::receive_messages_proof -); - -/// Description of Millau -> RialtoParachain messages bridge. -#[derive(Clone, Debug)] -pub struct MillauMessagesToRialtoParachain; - -impl SubstrateMessageLane for MillauMessagesToRialtoParachain { - type SourceChain = Millau; - type TargetChain = RialtoParachain; - - type ReceiveMessagesProofCallBuilder = - MillauMessagesToRialtoParachainReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = DirectReceiveMessagesDeliveryProofCallBuilder< - Self, - millau_runtime::Runtime, - millau_runtime::WithRialtoParachainMessagesInstance, - >; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = (); -} diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs deleted file mode 100644 index f0613d1511eb3..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Rialto Parachain and Millau. - -pub mod millau_headers_to_rialto_parachain; -pub mod millau_messages_to_rialto_parachain; -pub mod rialto_parachain_messages_to_millau; -pub mod rialto_parachains_to_millau; diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs deleted file mode 100644 index e19953eac554d..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachain_messages_to_millau.rs +++ /dev/null @@ -1,51 +0,0 @@ -// 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 . - -//! RialtoParachain-to-Millau messages sync entrypoint. - -use relay_millau_client::Millau; -use relay_rialto_parachain_client::RialtoParachain; -use substrate_relay_helper::{ - messages_lane::{DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane}, - UtilityPalletBatchCallBuilder, -}; - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - RialtoParachainMessagesToMillau, - RialtoParachainMessagesToMillauReceiveMessagesDeliveryProofCallBuilder, - relay_rialto_parachain_client::RuntimeCall::BridgeMillauMessages, - relay_rialto_parachain_client::BridgeMessagesCall::receive_messages_delivery_proof -); - -/// Description of RialtoParachain -> Millau messages bridge. -#[derive(Clone, Debug)] -pub struct RialtoParachainMessagesToMillau; - -impl SubstrateMessageLane for RialtoParachainMessagesToMillau { - type SourceChain = RialtoParachain; - type TargetChain = Millau; - - type ReceiveMessagesProofCallBuilder = DirectReceiveMessagesProofCallBuilder< - Self, - millau_runtime::Runtime, - millau_runtime::WithRialtoParachainMessagesInstance, - >; - type ReceiveMessagesDeliveryProofCallBuilder = - RialtoParachainMessagesToMillauReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs deleted file mode 100644 index 6b2a1332144dc..0000000000000 --- a/relays/bin-substrate/src/bridges/rialto_parachain_millau/rialto_parachains_to_millau.rs +++ /dev/null @@ -1,65 +0,0 @@ -// 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 . - -//! Rialto-to-Millau parachains sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; -use relay_millau_client::Millau; -use relay_rialto_client::Rialto; -use relay_rialto_parachain_client::RialtoParachain; -use substrate_relay_helper::parachains::{ - DirectSubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, -}; - -/// Rialto-to-Millau parachains sync description. -#[derive(Clone, Debug)] -pub struct RialtoParachainsToMillau; - -impl SubstrateParachainsPipeline for RialtoParachainsToMillau { - type SourceParachain = RialtoParachain; - type SourceRelayChain = Rialto; - type TargetChain = Millau; - - type SubmitParachainHeadsCallBuilder = RialtoParachainsToMillauSubmitParachainHeadsCallBuilder; -} - -/// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. -pub type RialtoParachainsToMillauSubmitParachainHeadsCallBuilder = - DirectSubmitParachainHeadsCallBuilder< - RialtoParachainsToMillau, - millau_runtime::Runtime, - millau_runtime::WithRialtoParachainsInstance, - >; - -/// `RialtoParachain` to `Millau` bridge definition. -pub struct RialtoParachainToMillauCliBridge {} - -impl CliBridgeBase for RialtoParachainToMillauCliBridge { - type Source = RialtoParachain; - type Target = Millau; -} - -impl ParachainToRelayHeadersCliBridge for RialtoParachainToMillauCliBridge { - type SourceRelay = Rialto; - type ParachainFinality = RialtoParachainsToMillau; - type RelayFinality = - crate::bridges::rialto_millau::rialto_headers_to_millau::RialtoFinalityToMillau; -} - -impl MessagesCliBridge for RialtoParachainToMillauCliBridge { - type MessagesLane = - crate::bridges::rialto_parachain_millau::rialto_parachain_messages_to_millau::RialtoParachainMessagesToMillau; -} diff --git a/relays/bin-substrate/src/bridges/westend_millau/mod.rs b/relays/bin-substrate/src/bridges/westend_millau/mod.rs deleted file mode 100644 index 10bc19241ce12..0000000000000 --- a/relays/bin-substrate/src/bridges/westend_millau/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Westend and Millau. - -pub mod westend_headers_to_millau; -pub mod westend_parachains_to_millau; diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs deleted file mode 100644 index afbbd064d1fe0..0000000000000 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_headers_to_millau.rs +++ /dev/null @@ -1,54 +0,0 @@ -// 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 . - -//! Westend-to-Millau headers sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, RelayToRelayHeadersCliBridge}; -use substrate_relay_helper::{ - finality::{DirectSubmitGrandpaFinalityProofCallBuilder, SubstrateFinalitySyncPipeline}, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Westend -> Millau finalized headers bridge. -#[derive(Clone, Debug)] -pub struct WestendFinalityToMillau; - -impl SubstrateFinalityPipeline for WestendFinalityToMillau { - type SourceChain = relay_westend_client::Westend; - type TargetChain = relay_millau_client::Millau; - - type FinalityEngine = GrandpaFinalityEngine; -} - -impl SubstrateFinalitySyncPipeline for WestendFinalityToMillau { - type SubmitFinalityProofCallBuilder = DirectSubmitGrandpaFinalityProofCallBuilder< - Self, - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >; -} - -/// `Westend` to `Millau` bridge definition. -pub struct WestendToMillauCliBridge {} - -impl CliBridgeBase for WestendToMillauCliBridge { - type Source = relay_westend_client::Westend; - type Target = relay_millau_client::Millau; -} - -impl RelayToRelayHeadersCliBridge for WestendToMillauCliBridge { - type Finality = WestendFinalityToMillau; -} diff --git a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs b/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs deleted file mode 100644 index 96023dc430a28..0000000000000 --- a/relays/bin-substrate/src/bridges/westend_millau/westend_parachains_to_millau.rs +++ /dev/null @@ -1,90 +0,0 @@ -// 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 . - -//! Westend-to-Millau parachains sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}; -use relay_millau_client::Millau; -use relay_westend_client::Westend; -use substrate_relay_helper::parachains::{ - DirectSubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, -}; - -/// Westend-to-Millau parachains sync description. -#[derive(Clone, Debug)] -pub struct WestendParachainsToMillau; - -impl SubstrateParachainsPipeline for WestendParachainsToMillau { - type SourceParachain = relay_asset_hub_westend_client::AssetHubWestend; - type SourceRelayChain = Westend; - type TargetChain = Millau; - - type SubmitParachainHeadsCallBuilder = WestendParachainsToMillauSubmitParachainHeadsCallBuilder; -} - -/// `submit_parachain_heads` call builder for Rialto-to-Millau parachains sync pipeline. -pub type WestendParachainsToMillauSubmitParachainHeadsCallBuilder = - DirectSubmitParachainHeadsCallBuilder< - WestendParachainsToMillau, - millau_runtime::Runtime, - millau_runtime::WithWestendParachainsInstance, - >; - -/// `WestendParachain` to `Millau` bridge definition. -pub struct AssetHubWestendToMillauCliBridge {} - -impl ParachainToRelayHeadersCliBridge for AssetHubWestendToMillauCliBridge { - type SourceRelay = Westend; - type ParachainFinality = WestendParachainsToMillau; - type RelayFinality = - crate::bridges::westend_millau::westend_headers_to_millau::WestendFinalityToMillau; -} - -impl CliBridgeBase for AssetHubWestendToMillauCliBridge { - type Source = relay_asset_hub_westend_client::AssetHubWestend; - type Target = Millau; -} - -/// TODO: Note: I know this does not belong here, but I don't want to add it to the -/// `chain-asset-hub-westend` or `chain-westend`, because we wont use it for production and I don't -/// want to bring this to the bridges subtree now. Anyway, we plan to retire millau/rialto, so this -/// hack will disappear with that. -pub mod relay_asset_hub_westend_client { - use bp_runtime::{ChainId, UnderlyingChainProvider}; - use relay_substrate_client::Chain; - use std::time::Duration; - - /// `AssetHubWestend` parachain definition - #[derive(Debug, Clone, Copy)] - pub struct AssetHubWestend; - - impl UnderlyingChainProvider for AssetHubWestend { - type Chain = millau_runtime::bp_bridged_chain::AssetHubWestend; - } - - // Westmint seems to use the same configuration as all Polkadot-like chains, so we'll use - // Westend primitives here. - impl Chain for AssetHubWestend { - const ID: ChainId = bp_runtime::ASSET_HUB_WESTEND_CHAIN_ID; - const NAME: &'static str = "Westmint"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - millau_runtime::bp_bridged_chain::BEST_FINALIZED_ASSETHUBWESTEND_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_polkadot_core::SignedBlock; - type Call = (); - } -} diff --git a/relays/bin-substrate/src/chains/millau.rs b/relays/bin-substrate/src/chains/millau.rs deleted file mode 100644 index f60d60386e9ba..0000000000000 --- a/relays/bin-substrate/src/chains/millau.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Millau chain specification for CLI. - -use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::EncodedOrDecodedCall; -use bridge_runtime_common::CustomNetworkId; -use relay_millau_client::Millau; -use relay_substrate_client::SimpleRuntimeVersion; -use xcm_executor::traits::ExportXcm; - -impl CliEncodeMessage for Millau { - fn encode_wire_message( - target: xcm::v3::NetworkId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result> { - anyhow::ensure!( - [ - CustomNetworkId::Rialto.as_network_id(), - CustomNetworkId::RialtoParachain.as_network_id() - ] - .contains(&target), - anyhow::format_err!("Unsupported target chain: {:?}", target) - ); - - Ok(millau_runtime::xcm_config::ToRialtoOrRialtoParachainSwitchExporter::validate( - target, - 0, - &mut Some(Self::dummy_universal_source()?), - &mut Some(target.into()), - &mut Some(at_target_xcm), - ) - .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? - .0 - .1 - .0) - } - - fn encode_execute_xcm( - message: xcm::VersionedXcm, - ) -> anyhow::Result> { - Ok(millau_runtime::RuntimeCall::XcmPallet(millau_runtime::XcmCall::execute { - message: Box::new(message), - max_weight: Self::estimate_execute_xcm_weight(), - }) - .into()) - } -} - -impl CliChain for Millau { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion::from_runtime_version(&millau_runtime::VERSION)); -} - -/// TODO: Note: I know this does not belong here, but I don't want to add it to the -/// `chain-asset-hub-westend` or `chain-westend`, because we wont use it for production and I don't -/// want to bring this to the bridges subtree now. Anyway, we plan to retire millau/rialto, so this -/// hack will disappear with that. -impl CliChain for crate::bridges::westend_millau::westend_parachains_to_millau::relay_asset_hub_westend_client::AssetHubWestend { - const RUNTIME_VERSION: Option = None; -} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index c9a55e9e900f0..442236997c8ba 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -17,95 +17,8 @@ //! Chain-specific relayer configuration. mod kusama; -mod millau; mod polkadot; mod polkadot_bulletin; -mod rialto; -mod rialto_parachain; mod rococo; mod westend; mod wococo; - -#[cfg(test)] -mod tests { - use crate::cli::encode_message; - use bp_messages::source_chain::TargetHeaderChain; - use bp_runtime::Chain as _; - use codec::Encode; - use relay_millau_client::Millau; - use relay_rialto_client::Rialto; - use relay_substrate_client::{ChainWithTransactions, SignParam, UnsignedTransaction}; - - #[test] - fn maximal_rialto_to_millau_message_size_is_computed_correctly() { - use rialto_runtime::millau_messages::MillauAsTargetHeaderChain; - - let maximal_message_size = encode_message::compute_maximal_message_size( - bp_rialto::Rialto::max_extrinsic_size(), - bp_millau::Millau::max_extrinsic_size(), - ); - - let message = vec![42; maximal_message_size as _]; - assert_eq!(MillauAsTargetHeaderChain::verify_message(&message), Ok(())); - - let message = vec![42; (maximal_message_size + 1) as _]; - assert!(MillauAsTargetHeaderChain::verify_message(&message).is_err()); - } - - #[test] - fn maximal_size_remark_to_rialto_is_generated_correctly() { - assert!( - bridge_runtime_common::messages::target::maximal_incoming_message_size( - bp_rialto::Rialto::max_extrinsic_size() - ) > bp_millau::Millau::max_extrinsic_size(), - "We can't actually send maximal messages to Rialto from Millau, because Millau extrinsics can't be that large", - ) - } - #[test] - fn rialto_tx_extra_bytes_constant_is_correct() { - let rialto_call = rialto_runtime::RuntimeCall::System(rialto_runtime::SystemCall::remark { - remark: vec![], - }); - let rialto_tx = Rialto::sign_transaction( - SignParam { - spec_version: 1, - transaction_version: 1, - genesis_hash: Default::default(), - signer: sp_keyring::AccountKeyring::Alice.pair(), - }, - UnsignedTransaction::new(rialto_call.clone().into(), 0), - ) - .unwrap(); - let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); - assert!( - bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, - "Hardcoded number of extra bytes in Rialto transaction {} is lower than actual value: {}", - bp_rialto::TX_EXTRA_BYTES, - extra_bytes_in_transaction, - ); - } - - #[test] - fn millau_tx_extra_bytes_constant_is_correct() { - let millau_call = millau_runtime::RuntimeCall::System(millau_runtime::SystemCall::remark { - remark: vec![], - }); - let millau_tx = Millau::sign_transaction( - SignParam { - spec_version: 0, - transaction_version: 0, - genesis_hash: Default::default(), - signer: sp_keyring::AccountKeyring::Alice.pair(), - }, - UnsignedTransaction::new(millau_call.clone().into(), 0), - ) - .unwrap(); - let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); - assert!( - bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, - "Hardcoded number of extra bytes in Millau transaction {} is lower than actual value: {}", - bp_millau::TX_EXTRA_BYTES, - extra_bytes_in_transaction, - ); - } -} diff --git a/relays/bin-substrate/src/chains/rialto.rs b/relays/bin-substrate/src/chains/rialto.rs deleted file mode 100644 index 30bc7eb13ca99..0000000000000 --- a/relays/bin-substrate/src/chains/rialto.rs +++ /dev/null @@ -1,62 +0,0 @@ -// 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 . - -//! Rialto chain specification for CLI. - -use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::EncodedOrDecodedCall; -use bridge_runtime_common::CustomNetworkId; -use relay_rialto_client::Rialto; -use relay_substrate_client::SimpleRuntimeVersion; -use xcm_executor::traits::ExportXcm; - -impl CliEncodeMessage for Rialto { - fn encode_wire_message( - target: xcm::v3::NetworkId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result> { - anyhow::ensure!( - target == CustomNetworkId::Millau.as_network_id(), - anyhow::format_err!("Unsupported target chain: {:?}", target) - ); - - Ok(rialto_runtime::millau_messages::ToMillauBlobExporter::validate( - target, - 0, - &mut Some(Self::dummy_universal_source()?), - &mut Some(target.into()), - &mut Some(at_target_xcm), - ) - .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? - .0 - .0) - } - - fn encode_execute_xcm( - message: xcm::VersionedXcm, - ) -> anyhow::Result> { - Ok(rialto_runtime::RuntimeCall::XcmPallet(rialto_runtime::XcmCall::execute { - message: Box::new(message), - max_weight: Self::estimate_execute_xcm_weight(), - }) - .into()) - } -} - -impl CliChain for Rialto { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion::from_runtime_version(&rialto_runtime::VERSION)); -} diff --git a/relays/bin-substrate/src/chains/rialto_parachain.rs b/relays/bin-substrate/src/chains/rialto_parachain.rs deleted file mode 100644 index 872d96981d0bf..0000000000000 --- a/relays/bin-substrate/src/chains/rialto_parachain.rs +++ /dev/null @@ -1,65 +0,0 @@ -// 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 . - -//! Rialto parachain specification for CLI. - -use crate::cli::{encode_message::CliEncodeMessage, CliChain}; -use bp_runtime::EncodedOrDecodedCall; -use bridge_runtime_common::CustomNetworkId; -use relay_rialto_parachain_client::RialtoParachain; -use relay_substrate_client::SimpleRuntimeVersion; -use xcm_executor::traits::ExportXcm; - -impl CliEncodeMessage for RialtoParachain { - fn encode_wire_message( - target: xcm::v3::NetworkId, - at_target_xcm: xcm::v3::Xcm<()>, - ) -> anyhow::Result> { - anyhow::ensure!( - target == CustomNetworkId::Millau.as_network_id(), - anyhow::format_err!("Unsupported target chain: {:?}", target) - ); - - Ok(rialto_parachain_runtime::millau_messages::ToMillauBlobExporter::validate( - target, - 0, - &mut Some(Self::dummy_universal_source()?), - &mut Some(target.into()), - &mut Some(at_target_xcm), - ) - .map_err(|e| anyhow::format_err!("Failed to prepare outbound message: {:?}", e))? - .0 - .0) - } - - fn encode_execute_xcm( - message: xcm::VersionedXcm, - ) -> anyhow::Result> { - type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; - type XcmCall = relay_rialto_parachain_client::runtime_types::pallet_xcm::pallet::Call; - - let xcm_call = XcmCall::execute { - message: Box::new(unsafe { std::mem::transmute(message) }), - max_weight: Self::estimate_execute_xcm_weight(), - }; - - Ok(RuntimeCall::PolkadotXcm(xcm_call).into()) - } -} - -impl CliChain for RialtoParachain { - const RUNTIME_VERSION: Option = None; -} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 0c1483b348b1a..cc6dc8e43574e 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -29,10 +29,6 @@ use substrate_relay_helper::{ #[strum(serialize_all = "kebab_case")] /// Supported full bridges (headers + messages). pub enum FullBridge { - MillauToRialto, - RialtoToMillau, - MillauToRialtoParachain, - RialtoParachainToMillau, BridgeHubRococoToBridgeHubWococo, BridgeHubWococoToBridgeHubRococo, BridgeHubRococoToBridgeHubWestend, diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index bbc95d7dcdbd1..5c2161acdbd70 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -129,29 +129,6 @@ macro_rules! declare_chain_connection_params_cli_schema { }; } -/// Helper trait to override transaction parameters differently. -pub trait TransactionParamsProvider { - /// Returns `true` if transaction parameters are defined by this provider. - fn is_defined(&self) -> bool; - /// Returns transaction parameters. - fn transaction_params( - &self, - ) -> anyhow::Result>>; - - /// Returns transaction parameters, defined by `self` provider or, if they're not defined, - /// defined by `other` provider. - fn transaction_params_or( - &self, - other: &T, - ) -> anyhow::Result>> { - if self.is_defined() { - self.transaction_params::() - } else { - other.transaction_params::() - } - } -} - /// Create chain-specific set of signing parameters. #[macro_export] macro_rules! declare_chain_signing_params_cli_schema { @@ -239,15 +216,12 @@ macro_rules! declare_chain_signing_params_cli_schema { suri_password.as_deref() ).map_err(|e| anyhow::format_err!("{:?}", e)) } - } - - #[allow(dead_code)] - impl TransactionParamsProvider for [<$chain SigningParams>] { - fn is_defined(&self) -> bool { - self.[<$chain_prefix _signer>].is_some() || self.[<$chain_prefix _signer_file>].is_some() - } - fn transaction_params(&self) -> anyhow::Result>> { + /// Return transaction parameters. + #[allow(dead_code)] + pub fn transaction_params( + &self, + ) -> anyhow::Result>> { Ok(TransactionParams { mortality: self.transactions_mortality()?, signer: self.to_keypair::()?, @@ -310,7 +284,7 @@ mod tests { target_transactions_mortality: None, } - .to_keypair::() + .to_keypair::() .map(|p| p.public()) .map_err(drop), Ok(alice.public()), @@ -327,7 +301,7 @@ mod tests { target_transactions_mortality: None, } - .to_keypair::() + .to_keypair::() .map(|p| p.public()) .map_err(drop), Ok(bob.public()), @@ -344,7 +318,7 @@ mod tests { target_transactions_mortality: None, } - .to_keypair::() + .to_keypair::() .map(|p| p.public()) .map_err(drop), Ok(bob_with_alice_password.public()), @@ -361,7 +335,7 @@ mod tests { target_transactions_mortality: None, } - .to_keypair::() + .to_keypair::() .map(|p| p.public()) .map_err(drop), Ok(alice.public()), diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs index bc456e025499e..704839db0e66f 100644 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -20,11 +20,6 @@ use crate::{ kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, }, - rialto_millau::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - }, - rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rococo_wococo::{ rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, @@ -58,9 +53,6 @@ pub struct DetectEquivocations { #[strum(serialize_all = "kebab_case")] /// Equivocations detection bridge. pub enum DetectEquivocationsBridge { - MillauToRialto, - RialtoToMillau, - MillauToRialtoParachain, RococoToBridgeHubWococo, WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, @@ -90,9 +82,6 @@ where } } -impl EquivocationsDetector for MillauToRialtoCliBridge {} -impl EquivocationsDetector for RialtoToMillauCliBridge {} -impl EquivocationsDetector for MillauToRialtoParachainCliBridge {} impl EquivocationsDetector for RococoToBridgeHubWococoCliBridge {} impl EquivocationsDetector for WococoToBridgeHubRococoCliBridge {} impl EquivocationsDetector for KusamaToBridgeHubPolkadotCliBridge {} @@ -102,10 +91,6 @@ impl DetectEquivocations { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - DetectEquivocationsBridge::MillauToRialto => MillauToRialtoCliBridge::start(self), - DetectEquivocationsBridge::RialtoToMillau => RialtoToMillauCliBridge::start(self), - DetectEquivocationsBridge::MillauToRialtoParachain => - MillauToRialtoParachainCliBridge::start(self), DetectEquivocationsBridge::RococoToBridgeHubWococo => RococoToBridgeHubWococoCliBridge::start(self), DetectEquivocationsBridge::WococoToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/encode_message.rs b/relays/bin-substrate/src/cli/encode_message.rs deleted file mode 100644 index 646075e832679..0000000000000 --- a/relays/bin-substrate/src/cli/encode_message.rs +++ /dev/null @@ -1,189 +0,0 @@ -// 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 . - -use crate::cli::{ExplicitOrMaximal, HexBytes}; -use bp_runtime::EncodedOrDecodedCall; -use bridge_runtime_common::CustomNetworkId; -use codec::Encode; -use frame_support::weights::Weight; -use relay_substrate_client::Chain; -use structopt::StructOpt; -use xcm::latest::prelude::*; - -/// All possible messages that may be delivered to generic Substrate chain. -/// -/// Note this enum may be used in the context of both Source (as part of `encode-call`) -/// and Target chain (as part of `encode-message/send-message`). -#[derive(StructOpt, Debug, PartialEq, Eq)] -pub enum Message { - /// Raw bytes for the message. - Raw { - /// Raw message bytes. - data: HexBytes, - }, - /// Message with given size. - Sized { - /// Sized of the message. - size: ExplicitOrMaximal, - }, -} - -/// Raw, SCALE-encoded message payload used in expected deployment. -pub type RawMessage = Vec; - -pub trait CliEncodeMessage: Chain { - /// Returns dummy `AccountId32` universal source given this network id. - fn dummy_universal_source() -> anyhow::Result { - use xcm::v3::prelude::*; - - let this_network = CustomNetworkId::try_from(Self::ID) - .map(|n| n.as_network_id()) - .map_err(|_| anyhow::format_err!("Unsupported chain: {:?}", Self::ID))?; - Ok(X2( - GlobalConsensus(this_network), - AccountId32 { network: Some(this_network), id: [0u8; 32] }, - )) - } - - /// Returns XCM blob that is passed to the `send_message` function of the messages pallet - /// and then is sent over the wire. - fn encode_wire_message(target: NetworkId, at_target_xcm: Xcm<()>) -> anyhow::Result>; - /// Encode an `execute` XCM call of the XCM pallet. - fn encode_execute_xcm( - message: xcm::VersionedXcm, - ) -> anyhow::Result>; - - /// Estimate value of `max_weight` argument for the `execute` XCM call of the XCM pallet. - fn estimate_execute_xcm_weight() -> Weight { - // we are only executing XCM on our testnets and 1/100 of max extrinsic weight is ok - Self::max_extrinsic_weight() / 100 - } -} - -/// Encode message payload passed through CLI flags. -pub(crate) fn encode_message( - message: &Message, -) -> anyhow::Result { - Ok(match message { - Message::Raw { ref data } => data.0.clone(), - Message::Sized { ref size } => { - let destination = CustomNetworkId::try_from(Target::ID) - .map(|n| n.as_network_id()) - .map_err(|_| anyhow::format_err!("Unsupported target chain: {:?}", Target::ID))?; - let expected_size = match *size { - ExplicitOrMaximal::Explicit(size) => size, - ExplicitOrMaximal::Maximal => compute_maximal_message_size( - Source::max_extrinsic_size(), - Target::max_extrinsic_size(), - ), - } as usize; - - let at_target_xcm = vec![ExpectPallet { - index: 0, - name: vec![42; expected_size], - module_name: vec![], - crate_major: 0, - min_crate_minor: 0, - }] - .into(); - let at_target_xcm_size = - Source::encode_wire_message(destination, at_target_xcm)?.encoded_size(); - let at_target_xcm_overhead = at_target_xcm_size.saturating_sub(expected_size); - let at_target_xcm = vec![ExpectPallet { - index: 0, - name: vec![42; expected_size.saturating_sub(at_target_xcm_overhead)], - module_name: vec![], - crate_major: 0, - min_crate_minor: 0, - }] - .into(); - - xcm::VersionedXcm::<()>::V3( - vec![ExportMessage { - network: destination, - destination: destination.into(), - xcm: at_target_xcm, - }] - .into(), - ) - .encode() - }, - }) -} - -/// Compute maximal message size, given max extrinsic size at source and target chains. -pub(crate) fn compute_maximal_message_size( - maximal_source_extrinsic_size: u32, - maximal_target_extrinsic_size: u32, -) -> u32 { - // assume that both signed extensions and other arguments fit 1KB - let service_tx_bytes_on_source_chain = 1024; - let maximal_source_extrinsic_size = - maximal_source_extrinsic_size - service_tx_bytes_on_source_chain; - let maximal_message_size = - bridge_runtime_common::messages::target::maximal_incoming_message_size( - maximal_target_extrinsic_size, - ); - std::cmp::min(maximal_message_size, maximal_source_extrinsic_size) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cli::send_message::decode_xcm; - use bp_runtime::Chain; - use relay_millau_client::Millau; - use relay_rialto_client::Rialto; - - fn approximate_message_size(xcm_msg_len: usize) -> usize { - xcm_msg_len + Source::dummy_universal_source().unwrap().encoded_size() - } - - #[test] - fn encode_explicit_size_message_works() { - let msg = encode_message::(&Message::Sized { - size: ExplicitOrMaximal::Explicit(100), - }) - .unwrap(); - // since it isn't the returned XCM what is sent over the wire, we can only check if - // it is close to what we need - assert!( - (1f64 - (approximate_message_size::(msg.len()) as f64) / 100_f64).abs() < 0.1 - ); - // check that it decodes to valid xcm - let _ = decode_xcm::<()>(msg).unwrap(); - } - - #[test] - fn encode_maximal_size_message_works() { - let maximal_size = compute_maximal_message_size( - Rialto::max_extrinsic_size(), - Millau::max_extrinsic_size(), - ); - - let msg = - encode_message::(&Message::Sized { size: ExplicitOrMaximal::Maximal }) - .unwrap(); - // since it isn't the returned XCM what is sent over the wire, we can only check if - // it is close to what we need - assert!( - (1f64 - approximate_message_size::(msg.len()) as f64 / maximal_size as f64) - .abs() < 0.1 - ); - // check that it decodes to valid xcm - let _ = decode_xcm::<()>(msg).unwrap(); - } -} diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 415897aeba94c..21d95b4bfa0ea 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -27,11 +27,6 @@ use crate::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, - rialto_millau::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - }, - rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rococo_westend::{ rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, @@ -40,7 +35,6 @@ use crate::{ rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, }, - westend_millau::westend_headers_to_millau::WestendToMillauCliBridge, }, cli::{bridge::CliBridgeBase, chain_schema::*}, }; @@ -72,10 +66,6 @@ pub struct InitBridge { #[strum(serialize_all = "kebab_case")] /// Bridge to initialize. pub enum InitBridgeName { - MillauToRialto, - RialtoToMillau, - WestendToMillau, - MillauToRialtoParachain, RococoToBridgeHubWococo, WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, @@ -126,72 +116,6 @@ where } } -impl BridgeInitializer for MillauToRialtoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - rialto_runtime::SudoCall::sudo { - call: Box::new(rialto_runtime::BridgeGrandpaCall::initialize { init_data }.into()), - } - .into() - } -} - -impl BridgeInitializer for MillauToRialtoParachainCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - type RuntimeCall = relay_rialto_parachain_client::RuntimeCall; - type BridgeGrandpaCall = relay_rialto_parachain_client::BridgeGrandpaCall; - type SudoCall = relay_rialto_parachain_client::SudoCall; - - let initialize_call = - RuntimeCall::BridgeMillauGrandpa(BridgeGrandpaCall::initialize { init_data }); - - RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(initialize_call) }) - } -} - -impl BridgeInitializer for RialtoToMillauCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - let initialize_call = millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::RialtoGrandpaInstance, - >::initialize { - init_data, - }; - millau_runtime::SudoCall::sudo { call: Box::new(initialize_call.into()) }.into() - } -} - -impl BridgeInitializer for WestendToMillauCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - // at Westend -> Millau initialization we're not using sudo, because otherwise - // our deployments may fail, because we need to initialize both Rialto -> Millau - // and Westend -> Millau bridge. => since there's single possible sudo account, - // one of transaction may fail with duplicate nonce error - millau_runtime::BridgeGrandpaCall::< - millau_runtime::Runtime, - millau_runtime::WestendGrandpaInstance, - >::initialize { - init_data, - } - .into() - } -} - impl BridgeInitializer for RococoToBridgeHubWococoCliBridge { type Engine = GrandpaFinalityEngine; @@ -305,11 +229,6 @@ impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - InitBridgeName::MillauToRialto => MillauToRialtoCliBridge::init_bridge(self), - InitBridgeName::RialtoToMillau => RialtoToMillauCliBridge::init_bridge(self), - InitBridgeName::WestendToMillau => WestendToMillauCliBridge::init_bridge(self), - InitBridgeName::MillauToRialtoParachain => - MillauToRialtoParachainCliBridge::init_bridge(self), InitBridgeName::RococoToBridgeHubWococo => RococoToBridgeHubWococoCliBridge::init_bridge(self), InitBridgeName::WococoToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 890fd9efb34ed..580463ef9f9ed 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -16,8 +16,6 @@ //! Deal with CLI args of substrate-to-substrate relay. -use std::convert::TryInto; - use async_std::prelude::*; use codec::{Decode, Encode}; use futures::{select, FutureExt}; @@ -31,18 +29,14 @@ use bp_messages::LaneId; use relay_substrate_client::SimpleRuntimeVersion; pub(crate) mod bridge; -pub(crate) mod encode_message; -pub(crate) mod send_message; mod chain_schema; mod detect_equivocations; mod init_bridge; -mod register_parachain; mod relay_headers; mod relay_headers_and_messages; mod relay_messages; mod relay_parachains; -mod resubmit_transactions; /// The target that will be used when publishing logs related to this pallet. pub const LOG_TARGET: &str = "bridge"; @@ -77,16 +71,6 @@ pub enum Command { /// /// Sends initialization transaction to bootstrap the bridge with current finalized block data. InitBridge(init_bridge::InitBridge), - /// Send custom message over the bridge. - /// - /// Allows interacting with the bridge by sending messages over `Messages` component. - /// The message is being sent to the source chain, delivered to the target chain and dispatched - /// there. - SendMessage(send_message::SendMessage), - /// Resubmit transactions with increased tip if they are stalled. - ResubmitTransactions(resubmit_transactions::ResubmitTransactions), - /// Register parachain. - RegisterParachain(register_parachain::RegisterParachain), /// Relay parachain heads. RelayParachains(relay_parachains::RelayParachains), /// Detect and report equivocations. @@ -121,9 +105,6 @@ impl Command { Self::RelayMessages(arg) => arg.run().await?, Self::RelayHeadersAndMessages(arg) => arg.run().await?, Self::InitBridge(arg) => arg.run().await?, - Self::SendMessage(arg) => arg.run().await?, - Self::ResubmitTransactions(arg) => arg.run().await?, - Self::RegisterParachain(arg) => arg.run().await?, Self::RelayParachains(arg) => arg.run().await?, Self::DetectEquivocations(arg) => arg.run().await?, } @@ -169,33 +150,7 @@ arg_enum! { } } -/// Generic balance type. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Balance(pub u128); - -impl std::fmt::Display for Balance { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - use num_format::{Locale, ToFormattedString}; - write!(fmt, "{}", self.0.to_formatted_string(&Locale::en)) - } -} - -impl std::str::FromStr for Balance { - type Err = ::Err; - - fn from_str(s: &str) -> Result { - Ok(Self(s.parse()?)) - } -} - -impl Balance { - /// Cast balance to `u64` type, panicking if it's too large. - pub fn cast(&self) -> u64 { - self.0.try_into().expect("Balance is too high for this chain.") - } -} - -// Bridge-supported network definition. +/// Bridge-supported network definition. /// /// Used to abstract away CLI commands. pub trait CliChain: relay_substrate_client::Chain { diff --git a/relays/bin-substrate/src/cli/register_parachain.rs b/relays/bin-substrate/src/cli/register_parachain.rs deleted file mode 100644 index 90464335166e8..0000000000000 --- a/relays/bin-substrate/src/cli/register_parachain.rs +++ /dev/null @@ -1,324 +0,0 @@ -// 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 . - -use crate::cli::{chain_schema::*, Balance}; - -use codec::Encode; -use frame_support::Twox64Concat; -use num_traits::Zero; -use polkadot_parachain_primitives::primitives::{ - HeadData as ParaHeadData, Id as ParaId, ValidationCode as ParaValidationCode, -}; -use polkadot_runtime_common::{ - paras_registrar::Call as ParaRegistrarCall, slots::Call as ParaSlotsCall, -}; -use polkadot_runtime_parachains::paras::ParaLifecycle; -use relay_substrate_client::{AccountIdOf, CallOf, Chain, Client, UnsignedTransaction}; -use relay_utils::{TrackedTransactionStatus, TransactionTracker}; -use rialto_runtime::SudoCall; -use sp_core::{ - storage::{well_known_keys::CODE, StorageKey}, - Pair, -}; -use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; - -/// Name of the `NextFreeParaId` value in the `polkadot_runtime_common::paras_registrar` pallet. -const NEXT_FREE_PARA_ID_STORAGE_NAME: &str = "NextFreeParaId"; -/// Name of the `ParaLifecycles` map in the `polkadot_runtime_parachains::paras` pallet. -const PARAS_LIFECYCLES_STORAGE_NAME: &str = "ParaLifecycles"; - -/// Register parachain. -#[derive(StructOpt, Debug, PartialEq, Eq)] -pub struct RegisterParachain { - /// A parachain to register. - #[structopt(possible_values = Parachain::VARIANTS, case_insensitive = true)] - parachain: Parachain, - /// Parachain deposit. - #[structopt(long, default_value = "0")] - deposit: Balance, - /// Lease begin. - #[structopt(long, default_value = "0")] - lease_begin: u32, - /// Lease end. - #[structopt(long, default_value = "256")] - lease_end: u32, - #[structopt(flatten)] - relay_connection: RelaychainConnectionParams, - #[structopt(flatten)] - relay_sign: RelaychainSigningParams, - #[structopt(flatten)] - para_connection: ParachainConnectionParams, -} - -/// Parachain to register. -#[derive(Debug, EnumString, EnumVariantNames, PartialEq, Eq)] -#[strum(serialize_all = "kebab_case")] -pub enum Parachain { - RialtoParachain, -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - Parachain::RialtoParachain => { - type Relaychain = relay_rialto_client::Rialto; - type Parachain = relay_rialto_parachain_client::RialtoParachain; - - use bp_rialto::{PARAS_PALLET_NAME, PARAS_REGISTRAR_PALLET_NAME}; - - $generic - }, - } - }; -} - -impl RegisterParachain { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.parachain, { - let relay_client = self.relay_connection.into_client::().await?; - let relay_sign = self.relay_sign.to_keypair::()?; - let para_client = self.para_connection.into_client::().await?; - - // hopefully we're the only actor that is registering parachain right now - // => read next parachain id - let para_id_key = bp_runtime::storage_value_final_key( - PARAS_REGISTRAR_PALLET_NAME.as_bytes(), - NEXT_FREE_PARA_ID_STORAGE_NAME.as_bytes(), - ); - let para_id: ParaId = relay_client - .storage_value(StorageKey(para_id_key.to_vec()), None) - .await? - .unwrap_or(polkadot_primitives::v6::LOWEST_PUBLIC_ID) - .max(polkadot_primitives::v6::LOWEST_PUBLIC_ID); - log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); - - // step 1: reserve a parachain id - let relay_sudo_account: AccountIdOf = relay_sign.public().into(); - let reserve_parachain_id_call: CallOf = - ParaRegistrarCall::reserve {}.into(); - let reserve_result = relay_client - .submit_and_watch_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - reserve_parachain_id_call.into(), - transaction_nonce, - )) - }) - .await? - .wait() - .await; - if reserve_result == TrackedTransactionStatus::Lost { - return Err(anyhow::format_err!( - "Failed to finalize `reserve-parachain-id` transaction" - )) - } - log::info!(target: "bridge", "Reserved parachain id: {:?}", para_id); - - // step 2: register parathread - let para_genesis_header = para_client.header_by_number(Zero::zero()).await?; - let para_code = para_client - .raw_storage_value(StorageKey(CODE.to_vec()), Some(para_genesis_header.hash())) - .await? - .ok_or_else(|| { - anyhow::format_err!("Cannot fetch validation code of {}", Parachain::NAME) - })? - .0; - log::info!( - target: "bridge", - "Going to register parachain {:?}: genesis len = {} code len = {}", - para_id, - para_genesis_header.encode().len(), - para_code.len(), - ); - let register_parathread_call: CallOf = ParaRegistrarCall::register { - id: para_id, - genesis_head: ParaHeadData(para_genesis_header.encode()), - validation_code: ParaValidationCode(para_code), - } - .into(); - let register_result = relay_client - .submit_and_watch_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { - Ok(UnsignedTransaction::new(register_parathread_call.into(), transaction_nonce)) - }) - .await? - .wait() - .await; - if register_result == TrackedTransactionStatus::Lost { - return Err(anyhow::format_err!( - "Failed to finalize `register-parathread` transaction" - )) - } - log::info!(target: "bridge", "Registered parachain: {:?}. Waiting for onboarding", para_id); - - // wait until parathread is onboarded - let para_state_key = bp_runtime::storage_map_final_key::( - PARAS_PALLET_NAME, - PARAS_LIFECYCLES_STORAGE_NAME, - ¶_id.encode(), - ); - wait_para_state( - &relay_client, - ¶_state_key.0, - &[ParaLifecycle::Onboarding, ParaLifecycle::Parathread], - ParaLifecycle::Parathread, - ) - .await?; - - // step 3: force parachain leases - let lease_begin = self.lease_begin; - let lease_end = self.lease_end; - let para_deposit = self.deposit.cast().into(); - log::info!( - target: "bridge", - "Going to force leases of parachain {:?}: [{}; {}]", - para_id, - lease_begin, - lease_end, - ); - let force_lease_call: CallOf = SudoCall::sudo { - call: Box::new( - ParaSlotsCall::force_lease { - para: para_id, - leaser: relay_sudo_account.clone(), - amount: para_deposit, - period_begin: lease_begin, - period_count: lease_end.saturating_sub(lease_begin).saturating_add(1), - } - .into(), - ), - } - .into(); - relay_client - .submit_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { - Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce)) - }) - .await?; - log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); - - // wait until parachain is onboarded - wait_para_state( - &relay_client, - ¶_state_key.0, - &[ - ParaLifecycle::Onboarding, - ParaLifecycle::UpgradingParathread, - ParaLifecycle::Parathread, - ], - ParaLifecycle::Parachain, - ) - .await?; - - Ok(()) - }) - } -} - -/// Wait until parachain state is changed. -async fn wait_para_state( - relay_client: &Client, - para_state_key: &[u8], - from_states: &[ParaLifecycle], - to_state: ParaLifecycle, -) -> anyhow::Result<()> { - loop { - let para_state: ParaLifecycle = relay_client - .storage_value(StorageKey(para_state_key.to_vec()), None) - .await? - .ok_or_else(|| { - anyhow::format_err!( - "Cannot fetch next free parachain lifecycle from the runtime storage of {}", - Relaychain::NAME, - ) - })?; - if para_state == to_state { - log::info!(target: "bridge", "Parachain state is now: {:?}", to_state); - return Ok(()) - } - if !from_states.contains(¶_state) { - return Err(anyhow::format_err!("Invalid parachain lifecycle: {:?}", para_state)) - } - - log::info!(target: "bridge", "Parachain state: {:?}. Waiting for {:?}", para_state, to_state); - async_std::task::sleep(Relaychain::AVERAGE_BLOCK_INTERVAL).await; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn register_rialto_parachain() { - let register_parachain = RegisterParachain::from_iter(vec![ - "register-parachain", - "rialto-parachain", - "--parachain-host", - "127.0.0.1", - "--parachain-port", - "11949", - "--relaychain-host", - "127.0.0.1", - "--relaychain-port", - "9944", - "--relaychain-signer", - "//Alice", - "--deposit", - "42", - "--lease-begin", - "100", - "--lease-end", - "200", - ]); - - assert_eq!( - register_parachain, - RegisterParachain { - parachain: Parachain::RialtoParachain, - deposit: Balance(42), - lease_begin: 100, - lease_end: 200, - relay_connection: RelaychainConnectionParams { - relaychain_host: "127.0.0.1".into(), - relaychain_port: 9944, - relaychain_secure: false, - relaychain_runtime_version: RelaychainRuntimeVersionParams { - relaychain_version_mode: RuntimeVersionType::Bundle, - relaychain_spec_version: None, - relaychain_transaction_version: None, - } - }, - relay_sign: RelaychainSigningParams { - relaychain_signer: Some("//Alice".into()), - relaychain_signer_password: None, - relaychain_signer_file: None, - relaychain_signer_password_file: None, - relaychain_transactions_mortality: None, - }, - para_connection: ParachainConnectionParams { - parachain_host: "127.0.0.1".into(), - parachain_port: 11949, - parachain_secure: false, - parachain_runtime_version: ParachainRuntimeVersionParams { - parachain_version_mode: RuntimeVersionType::Bundle, - parachain_spec_version: None, - parachain_transaction_version: None, - } - }, - } - ); - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index d3a7fa09367df..95d93387a0728 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -27,16 +27,10 @@ use crate::bridges::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, - rialto_millau::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - }, - rialto_parachain_millau::millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, rococo_wococo::{ rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, }, - westend_millau::westend_headers_to_millau::WestendToMillauCliBridge, }; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; @@ -67,10 +61,6 @@ pub struct RelayHeaders { #[strum(serialize_all = "kebab_case")] /// Headers relay bridge. pub enum RelayHeadersBridge { - MillauToRialto, - RialtoToMillau, - WestendToMillau, - MillauToRialtoParachain, RococoToBridgeHubWococo, WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, @@ -110,10 +100,6 @@ trait HeadersRelayer: RelayToRelayHeadersCliBridge { } } -impl HeadersRelayer for MillauToRialtoCliBridge {} -impl HeadersRelayer for RialtoToMillauCliBridge {} -impl HeadersRelayer for WestendToMillauCliBridge {} -impl HeadersRelayer for MillauToRialtoParachainCliBridge {} impl HeadersRelayer for RococoToBridgeHubWococoCliBridge {} impl HeadersRelayer for WococoToBridgeHubRococoCliBridge {} impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} @@ -125,11 +111,6 @@ impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - RelayHeadersBridge::MillauToRialto => MillauToRialtoCliBridge::relay_headers(self), - RelayHeadersBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_headers(self), - RelayHeadersBridge::WestendToMillau => WestendToMillauCliBridge::relay_headers(self), - RelayHeadersBridge::MillauToRialtoParachain => - MillauToRialtoParachainCliBridge::relay_headers(self), RelayHeadersBridge::RococoToBridgeHubWococo => RococoToBridgeHubWococoCliBridge::relay_headers(self), RelayHeadersBridge::WococoToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 5a8c084889d75..7075e742e02d8 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -36,7 +36,6 @@ use structopt::StructOpt; use futures::{FutureExt, TryFutureExt}; use relay_to_parachain::*; -use relay_to_relay::*; use crate::{ bridges::{ @@ -48,14 +47,6 @@ use crate::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, - rialto_millau::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - }, - rialto_parachain_millau::{ - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, - }, rococo_westend::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, @@ -203,9 +194,6 @@ where } // All supported chains. -declare_chain_cli_schema!(Millau, millau); -declare_chain_cli_schema!(Rialto, rialto); -declare_chain_cli_schema!(RialtoParachain, rialto_parachain); declare_chain_cli_schema!(Rococo, rococo); declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); declare_chain_cli_schema!(Wococo, wococo); @@ -217,53 +205,7 @@ declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); declare_chain_cli_schema!(Polkadot, polkadot); declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); declare_chain_cli_schema!(PolkadotBulletin, polkadot_bulletin); -// Means to override signers of different layer transactions. -declare_chain_cli_schema!(MillauHeadersToRialto, millau_headers_to_rialto); -declare_chain_cli_schema!(MillauHeadersToRialtoParachain, millau_headers_to_rialto_parachain); -declare_chain_cli_schema!(RialtoHeadersToMillau, rialto_headers_to_millau); -declare_chain_cli_schema!(RialtoParachainsToMillau, rialto_parachains_to_millau); -declare_chain_cli_schema!(RococoHeadersToBridgeHubWococo, rococo_headers_to_bridge_hub_wococo); -declare_chain_cli_schema!( - RococoParachainsToBridgeHubWococo, - rococo_parachains_to_bridge_hub_wococo -); -declare_chain_cli_schema!(WococoHeadersToBridgeHubRococo, wococo_headers_to_bridge_hub_rococo); -declare_chain_cli_schema!( - WococoParachainsToBridgeHubRococo, - wococo_parachains_to_bridge_hub_rococo -); -declare_chain_cli_schema!(RococoHeadersToBridgeHubWestend, rococo_headers_to_bridge_hub_westend); -declare_chain_cli_schema!( - RococoParachainsToBridgeHubWestend, - rococo_parachains_to_bridge_hub_westend -); -declare_chain_cli_schema!(WestendHeadersToBridgeHubRococo, westend_headers_to_bridge_hub_rococo); -declare_chain_cli_schema!( - WestendParachainsToBridgeHubRococo, - westend_parachains_to_bridge_hub_rococo -); -declare_chain_cli_schema!(KusamaHeadersToBridgeHubPolkadot, kusama_headers_to_bridge_hub_polkadot); -declare_chain_cli_schema!( - KusamaParachainsToBridgeHubPolkadot, - kusama_parachains_to_bridge_hub_polkadot -); -declare_chain_cli_schema!(PolkadotHeadersToBridgeHubKusama, polkadot_headers_to_bridge_hub_kusama); -declare_chain_cli_schema!( - PolkadotParachainsToBridgeHubKusama, - polkadot_parachains_to_bridge_hub_kusama -); -declare_chain_cli_schema!( - PolkadotBulletinHeadersToBridgeHubPolkadot, - polkadot_bulletin_headers_to_bridge_hub_polkadot -); -declare_chain_cli_schema!(PolkadotHeadersToPolkadotBulletin, polkadot_headers_to_polkadot_bulletin); -declare_chain_cli_schema!( - PolkadotParachainsToPolkadotBulletin, - polkadot_parachains_to_polkadot_bulletin -); // All supported bridges. -declare_relay_to_relay_bridge_schema!(Millau, Rialto); -declare_relay_to_parachain_bridge_schema!(Millau, RialtoParachain, Rialto); declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWococo, Wococo); declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWestend, Westend); declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); @@ -434,58 +376,6 @@ where } } -/// Millau <> Rialto complex relay. -pub struct MillauRialtoFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for MillauRialtoFull2WayBridge { - type Base = RelayToRelayBridge; - type Left = relay_millau_client::Millau; - type Right = relay_rialto_client::Rialto; - type L2R = MillauToRialtoCliBridge; - type R2L = RialtoToMillauCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - -/// Millau <> RialtoParachain complex relay. -pub struct MillauRialtoParachainFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for MillauRialtoParachainFull2WayBridge { - type Base = RelayToParachainBridge; - type Left = relay_millau_client::Millau; - type Right = relay_rialto_parachain_client::RialtoParachain; - type L2R = MillauToRialtoParachainCliBridge; - type R2L = RialtoParachainToMillauCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - /// BridgeHubRococo <> BridgeHubWococo complex relay. pub struct BridgeHubRococoBridgeHubWococoFull2WayBridge { base: ::Base, @@ -593,10 +483,6 @@ impl Full2WayBridge for PolkadotBulletinBridgeHubPolkadotFull2WayBridge { /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { - /// Millau <> Rialto relay. - MillauRialto(MillauRialtoHeadersAndMessages), - /// Millau <> RialtoParachain relay. - MillauRialtoParachain(MillauRialtoParachainHeadersAndMessages), /// BridgeHubRococo <> BridgeHubWococo relay. BridgeHubRococoBridgeHubWococo(BridgeHubRococoBridgeHubWococoHeadersAndMessages), /// BridgeHubKusama <> BridgeHubPolkadot relay. @@ -611,12 +497,6 @@ impl RelayHeadersAndMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self { - RelayHeadersAndMessages::MillauRialto(params) => - MillauRialtoFull2WayBridge::new(params.into_bridge().await?)?.run().await, - RelayHeadersAndMessages::MillauRialtoParachain(params) => - MillauRialtoParachainFull2WayBridge::new(params.into_bridge().await?)? - .run() - .await, RelayHeadersAndMessages::BridgeHubRococoBridgeHubWococo(params) => BridgeHubRococoBridgeHubWococoFull2WayBridge::new(params.into_bridge().await?)? .run() @@ -642,130 +522,34 @@ mod tests { use super::*; #[test] - fn should_parse_relay_to_relay_options() { - // when - let res = RelayHeadersAndMessages::from_iter(vec![ - "relay-headers-and-messages", - "millau-rialto", - "--millau-host", - "millau-node-alice", - "--millau-port", - "9944", - "--millau-signer", - "//Charlie", - "--millau-transactions-mortality", - "64", - "--rialto-host", - "rialto-node-alice", - "--rialto-port", - "9944", - "--rialto-signer", - "//Charlie", - "--rialto-transactions-mortality", - "64", - "--lane", - "00000000", - "--lane", - "73776170", - "--prometheus-host", - "0.0.0.0", - ]); - - // then - assert_eq!( - res, - RelayHeadersAndMessages::MillauRialto(MillauRialtoHeadersAndMessages { - shared: HeadersAndMessagesSharedParams { - lane: vec![ - HexLaneId([0x00, 0x00, 0x00, 0x00]), - HexLaneId([0x73, 0x77, 0x61, 0x70]) - ], - only_mandatory_headers: false, - prometheus_params: PrometheusParams { - no_prometheus: false, - prometheus_host: "0.0.0.0".into(), - prometheus_port: 9616, - }, - }, - left: MillauConnectionParams { - millau_host: "millau-node-alice".into(), - millau_port: 9944, - millau_secure: false, - millau_runtime_version: MillauRuntimeVersionParams { - millau_version_mode: RuntimeVersionType::Bundle, - millau_spec_version: None, - millau_transaction_version: None, - }, - }, - left_sign: MillauSigningParams { - millau_signer: Some("//Charlie".into()), - millau_signer_password: None, - millau_signer_file: None, - millau_signer_password_file: None, - millau_transactions_mortality: Some(64), - }, - left_headers_to_right_sign_override: MillauHeadersToRialtoSigningParams { - millau_headers_to_rialto_signer: None, - millau_headers_to_rialto_signer_password: None, - millau_headers_to_rialto_signer_file: None, - millau_headers_to_rialto_signer_password_file: None, - millau_headers_to_rialto_transactions_mortality: None, - }, - right: RialtoConnectionParams { - rialto_host: "rialto-node-alice".into(), - rialto_port: 9944, - rialto_secure: false, - rialto_runtime_version: RialtoRuntimeVersionParams { - rialto_version_mode: RuntimeVersionType::Bundle, - rialto_spec_version: None, - rialto_transaction_version: None, - }, - }, - right_sign: RialtoSigningParams { - rialto_signer: Some("//Charlie".into()), - rialto_signer_password: None, - rialto_signer_file: None, - rialto_signer_password_file: None, - rialto_transactions_mortality: Some(64), - }, - right_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { - rialto_headers_to_millau_signer: None, - rialto_headers_to_millau_signer_password: None, - rialto_headers_to_millau_signer_file: None, - rialto_headers_to_millau_signer_password_file: None, - rialto_headers_to_millau_transactions_mortality: None, - }, - }), - ); - } - - #[test] - fn should_parse_relay_to_parachain_options() { + fn should_parse_parachain_to_parachain_options() { // when let res = RelayHeadersAndMessages::from_iter(vec![ "relay-headers-and-messages", - "millau-rialto-parachain", - "--millau-host", - "millau-node-alice", - "--millau-port", + "bridge-hub-kusama-bridge-hub-polkadot", + "--bridge-hub-kusama-host", + "bridge-hub-kusama-node-collator1", + "--bridge-hub-kusama-port", "9944", - "--millau-signer", + "--bridge-hub-kusama-signer", "//Iden", - "--rialto-headers-to-millau-signer", - "//Ken", - "--millau-transactions-mortality", + "--bridge-hub-kusama-transactions-mortality", "64", - "--rialto-parachain-host", - "rialto-parachain-collator-charlie", - "--rialto-parachain-port", + "--kusama-host", + "kusama-alice", + "--kusama-port", + "9944", + "--bridge-hub-polkadot-host", + "bridge-hub-polkadot-collator1", + "--bridge-hub-polkadot-port", "9944", - "--rialto-parachain-signer", + "--bridge-hub-polkadot-signer", "//George", - "--rialto-parachain-transactions-mortality", + "--bridge-hub-polkadot-transactions-mortality", "64", - "--rialto-host", - "rialto-node-alice", - "--rialto-port", + "--polkadot-host", + "polkadot-alice", + "--polkadot-port", "9944", "--lane", "00000000", @@ -776,8 +560,8 @@ mod tests { // then assert_eq!( res, - RelayHeadersAndMessages::MillauRialtoParachain( - MillauRialtoParachainHeadersAndMessages { + RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot( + BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages { shared: HeadersAndMessagesSharedParams { lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], only_mandatory_headers: false, @@ -787,70 +571,59 @@ mod tests { prometheus_port: 9616, }, }, - left: MillauConnectionParams { - millau_host: "millau-node-alice".into(), - millau_port: 9944, - millau_secure: false, - millau_runtime_version: MillauRuntimeVersionParams { - millau_version_mode: RuntimeVersionType::Bundle, - millau_spec_version: None, - millau_transaction_version: None, + left_relay: KusamaConnectionParams { + kusama_host: "kusama-alice".into(), + kusama_port: 9944, + kusama_secure: false, + kusama_runtime_version: KusamaRuntimeVersionParams { + kusama_version_mode: RuntimeVersionType::Bundle, + kusama_spec_version: None, + kusama_transaction_version: None, }, }, - left_sign: MillauSigningParams { - millau_signer: Some("//Iden".into()), - millau_signer_password: None, - millau_signer_file: None, - millau_signer_password_file: None, - millau_transactions_mortality: Some(64), - }, - left_headers_to_right_sign_override: - MillauHeadersToRialtoParachainSigningParams { - millau_headers_to_rialto_parachain_signer: None, - millau_headers_to_rialto_parachain_signer_password: None, - millau_headers_to_rialto_parachain_signer_file: None, - millau_headers_to_rialto_parachain_signer_password_file: None, - millau_headers_to_rialto_parachain_transactions_mortality: None, - }, - right: RialtoParachainConnectionParams { - rialto_parachain_host: "rialto-parachain-collator-charlie".into(), - rialto_parachain_port: 9944, - rialto_parachain_secure: false, - rialto_parachain_runtime_version: RialtoParachainRuntimeVersionParams { - rialto_parachain_version_mode: RuntimeVersionType::Bundle, - rialto_parachain_spec_version: None, - rialto_parachain_transaction_version: None, + left: BridgeHubKusamaConnectionParams { + bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(), + bridge_hub_kusama_port: 9944, + bridge_hub_kusama_secure: false, + bridge_hub_kusama_runtime_version: BridgeHubKusamaRuntimeVersionParams { + bridge_hub_kusama_version_mode: RuntimeVersionType::Bundle, + bridge_hub_kusama_spec_version: None, + bridge_hub_kusama_transaction_version: None, }, }, - right_sign: RialtoParachainSigningParams { - rialto_parachain_signer: Some("//George".into()), - rialto_parachain_signer_password: None, - rialto_parachain_signer_file: None, - rialto_parachain_signer_password_file: None, - rialto_parachain_transactions_mortality: Some(64), + left_sign: BridgeHubKusamaSigningParams { + bridge_hub_kusama_signer: Some("//Iden".into()), + bridge_hub_kusama_signer_password: None, + bridge_hub_kusama_signer_file: None, + bridge_hub_kusama_signer_password_file: None, + bridge_hub_kusama_transactions_mortality: Some(64), }, - right_relay_headers_to_left_sign_override: RialtoHeadersToMillauSigningParams { - rialto_headers_to_millau_signer: Some("//Ken".into()), - rialto_headers_to_millau_signer_password: None, - rialto_headers_to_millau_signer_file: None, - rialto_headers_to_millau_signer_password_file: None, - rialto_headers_to_millau_transactions_mortality: None, + right: BridgeHubPolkadotConnectionParams { + bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(), + bridge_hub_polkadot_port: 9944, + bridge_hub_polkadot_secure: false, + bridge_hub_polkadot_runtime_version: + BridgeHubPolkadotRuntimeVersionParams { + bridge_hub_polkadot_version_mode: RuntimeVersionType::Bundle, + bridge_hub_polkadot_spec_version: None, + bridge_hub_polkadot_transaction_version: None, + }, }, - right_parachains_to_left_sign_override: RialtoParachainsToMillauSigningParams { - rialto_parachains_to_millau_signer: None, - rialto_parachains_to_millau_signer_password: None, - rialto_parachains_to_millau_signer_file: None, - rialto_parachains_to_millau_signer_password_file: None, - rialto_parachains_to_millau_transactions_mortality: None, + right_sign: BridgeHubPolkadotSigningParams { + bridge_hub_polkadot_signer: Some("//George".into()), + bridge_hub_polkadot_signer_password: None, + bridge_hub_polkadot_signer_file: None, + bridge_hub_polkadot_signer_password_file: None, + bridge_hub_polkadot_transactions_mortality: Some(64), }, - right_relay: RialtoConnectionParams { - rialto_host: "rialto-node-alice".into(), - rialto_port: 9944, - rialto_secure: false, - rialto_runtime_version: RialtoRuntimeVersionParams { - rialto_version_mode: RuntimeVersionType::Bundle, - rialto_spec_version: None, - rialto_transaction_version: None, + right_relay: PolkadotConnectionParams { + polkadot_host: "polkadot-alice".into(), + polkadot_port: 9944, + polkadot_secure: false, + polkadot_runtime_version: PolkadotRuntimeVersionParams { + polkadot_version_mode: RuntimeVersionType::Bundle, + polkadot_spec_version: None, + polkadot_transaction_version: None, }, }, } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 1610f648bdcdd..32ba6b3ddadce 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -33,7 +33,6 @@ use substrate_relay_helper::{ on_demand::{ headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, }, - TaggedAccount, TransactionParams, }; /// A base relay between two parachain from different consensus systems. @@ -54,20 +53,6 @@ pub struct ParachainToParachainBridge< pub left_relay: Client<::SourceRelay>, /// Client of the right relay chain. pub right_relay: Client<::SourceRelay>, - - /// Override for right_relay->left headers signer. - pub right_headers_to_left_transaction_params: - TransactionParams::Target>>, - /// Override for right->left parachains signer. - pub right_parachains_to_left_transaction_params: - TransactionParams::Target>>, - - /// Override for left_relay->right headers signer. - pub left_headers_to_right_transaction_params: - TransactionParams::Target>>, - /// Override for left->right parachains signer. - pub left_parachains_to_right_transaction_params: - TransactionParams::Target>>, } macro_rules! declare_parachain_to_parachain_bridge_schema { @@ -86,12 +71,6 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_parachain SigningParams>], - // override for right_relay->left-parachain headers signer - #[structopt(flatten)] - right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_parachain SigningParams>], - // override for right->left parachains signer - #[structopt(flatten)] - right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_parachain SigningParams>], #[structopt(flatten)] left_relay: [<$left_chain ConnectionParams>], @@ -101,12 +80,6 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$right_parachain SigningParams>], - // override for left_relay->right-parachain headers signer - #[structopt(flatten)] - left_relay_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], - // override for left->right parachains signer - #[structopt(flatten)] - left_parachains_to_right_sign_override: [<$left_chain ParachainsTo $right_parachain SigningParams>], #[structopt(flatten)] right_relay: [<$right_chain ConnectionParams>], @@ -143,18 +116,6 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { )?, left_relay: self.left_relay.into_client::().await?, right_relay: self.right_relay.into_client::().await?, - right_headers_to_left_transaction_params: self - .right_relay_headers_to_left_sign_override - .transaction_params_or::(&self.left_sign)?, - left_headers_to_right_transaction_params: self - .left_relay_headers_to_right_sign_override - .transaction_params_or::(&self.right_sign)?, - right_parachains_to_left_transaction_params: self - .right_parachains_to_left_sign_override - .transaction_params_or::(&self.left_sign)?, - left_parachains_to_right_transaction_params: self - .left_parachains_to_right_sign_override - .transaction_params_or::(&self.right_sign)?, }) } } @@ -199,23 +160,6 @@ where Arc>, Arc>, )> { - self.common.left.accounts.push(TaggedAccount::Headers { - id: self.right_headers_to_left_transaction_params.signer.public().into(), - bridged_chain: RightRelay::NAME.to_string(), - }); - self.common.left.accounts.push(TaggedAccount::Parachains { - id: self.right_parachains_to_left_transaction_params.signer.public().into(), - bridged_chain: RightRelay::NAME.to_string(), - }); - self.common.right.accounts.push(TaggedAccount::Headers { - id: self.left_headers_to_right_transaction_params.signer.public().into(), - bridged_chain: Left::NAME.to_string(), - }); - self.common.right.accounts.push(TaggedAccount::Parachains { - id: self.left_parachains_to_right_transaction_params.signer.public().into(), - bridged_chain: LeftRelay::NAME.to_string(), - }); - ::RelayFinality::start_relay_guards( &self.common.right.client, self.common.right.client.can_start_version_guard(), @@ -231,7 +175,7 @@ where OnDemandHeadersRelay::<::RelayFinality>::new( self.left_relay.clone(), self.common.right.client.clone(), - self.left_headers_to_right_transaction_params.clone(), + self.common.right.tx_params.clone(), self.common.shared.only_mandatory_headers, Some(self.common.metrics_params.clone()), ); @@ -239,7 +183,7 @@ where OnDemandHeadersRelay::<::RelayFinality>::new( self.right_relay.clone(), self.common.left.client.clone(), - self.right_headers_to_left_transaction_params.clone(), + self.common.left.tx_params.clone(), self.common.shared.only_mandatory_headers, Some(self.common.metrics_params.clone()), ); @@ -249,7 +193,7 @@ where >::new( self.left_relay.clone(), self.common.right.client.clone(), - self.left_parachains_to_right_transaction_params.clone(), + self.common.right.tx_params.clone(), Arc::new(left_relay_to_right_on_demand_headers), ); let right_to_left_on_demand_parachains = OnDemandParachainsRelay::< @@ -257,7 +201,7 @@ where >::new( self.right_relay.clone(), self.common.left.client.clone(), - self.right_parachains_to_left_transaction_params.clone(), + self.common.left.tx_params.clone(), Arc::new(right_relay_to_left_on_demand_headers), ); diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs index 98b313cc0960d..fd885b6ea6c6c 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -36,7 +36,6 @@ use substrate_relay_helper::{ on_demand::{ headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, }, - TaggedAccount, TransactionParams, }; /// A base relay between standalone (relay) chain and a parachain from another consensus system. @@ -54,17 +53,6 @@ pub struct RelayToParachainBridge< Full2WayBridgeCommonParams<::Target, ::Target>, /// Client of the right relay chain. pub right_relay: Client<::SourceRelay>, - - /// Override for right_relay->left headers signer. - pub right_headers_to_left_transaction_params: - TransactionParams::Target>>, - /// Override for right->left parachains signer. - pub right_parachains_to_left_transaction_params: - TransactionParams::Target>>, - - /// Override for left->right headers signer. - pub left_headers_to_right_transaction_params: - TransactionParams::Target>>, } macro_rules! declare_relay_to_parachain_bridge_schema { @@ -83,21 +71,12 @@ macro_rules! declare_relay_to_parachain_bridge_schema { // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_chain SigningParams>], - // override for right_relay->left headers signer - #[structopt(flatten)] - right_relay_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], - // override for right->left parachains signer - #[structopt(flatten)] - right_parachains_to_left_sign_override: [<$right_chain ParachainsTo $left_chain SigningParams>], #[structopt(flatten)] right: [<$right_parachain ConnectionParams>], // default signer, which is always used to sign messages relay transactions on the right chain #[structopt(flatten)] right_sign: [<$right_parachain SigningParams>], - // override for left->right headers signer - #[structopt(flatten)] - left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_parachain SigningParams>], #[structopt(flatten)] right_relay: [<$right_chain ConnectionParams>], @@ -130,19 +109,6 @@ macro_rules! declare_relay_to_parachain_bridge_schema { }, )?, right_relay: self.right_relay.into_client::().await?, - right_headers_to_left_transaction_params: self - .right_relay_headers_to_left_sign_override - .transaction_params_or::( - &self.left_sign, - )?, - right_parachains_to_left_transaction_params: self - .right_parachains_to_left_sign_override - .transaction_params_or::( - &self.left_sign, - )?, - left_headers_to_right_transaction_params: self - .left_headers_to_right_sign_override - .transaction_params_or::(&self.right_sign)?, }) } } @@ -185,19 +151,6 @@ where Arc>, Arc>, )> { - self.common.left.accounts.push(TaggedAccount::Headers { - id: self.right_headers_to_left_transaction_params.signer.public().into(), - bridged_chain: RightRelay::NAME.to_string(), - }); - self.common.left.accounts.push(TaggedAccount::Parachains { - id: self.right_parachains_to_left_transaction_params.signer.public().into(), - bridged_chain: RightRelay::NAME.to_string(), - }); - self.common.right.accounts.push(TaggedAccount::Headers { - id: self.left_headers_to_right_transaction_params.signer.public().into(), - bridged_chain: Left::NAME.to_string(), - }); - ::Finality::start_relay_guards( &self.common.right.client, self.common.right.client.can_start_version_guard(), @@ -213,7 +166,7 @@ where OnDemandHeadersRelay::<::Finality>::new( self.common.left.client.clone(), self.common.right.client.clone(), - self.left_headers_to_right_transaction_params.clone(), + self.common.right.tx_params.clone(), self.common.shared.only_mandatory_headers, None, ); @@ -221,7 +174,7 @@ where OnDemandHeadersRelay::<::RelayFinality>::new( self.right_relay.clone(), self.common.left.client.clone(), - self.right_headers_to_left_transaction_params.clone(), + self.common.left.tx_params.clone(), self.common.shared.only_mandatory_headers, Some(self.common.metrics_params.clone()), ); @@ -230,7 +183,7 @@ where >::new( self.right_relay.clone(), self.common.left.client.clone(), - self.right_parachains_to_left_transaction_params.clone(), + self.common.left.tx_params.clone(), Arc::new(right_relay_to_left_on_demand_headers), ); diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs index a75263540a55f..11425035de287 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +// we don't have any relay/standalone <> relay/standalone chain bridges, but we may need it in a +// future +#![allow(unused_macros)] + use async_trait::async_trait; use std::sync::Arc; @@ -27,7 +31,6 @@ use sp_core::Pair; use substrate_relay_helper::{ finality::SubstrateFinalitySyncPipeline, on_demand::{headers::OnDemandHeadersRelay, OnDemandRelay}, - TaggedAccount, TransactionParams, }; /// A base relay between two standalone (relay) chains. @@ -40,12 +43,6 @@ pub struct RelayToRelayBridge< /// Parameters that are shared by all bridge types. pub common: Full2WayBridgeCommonParams<::Target, ::Target>, - /// Override for right->left headers signer. - pub right_to_left_transaction_params: - TransactionParams::Target>>, - /// Override for left->right headers signer. - pub left_to_right_transaction_params: - TransactionParams::Target>>, } macro_rules! declare_relay_to_relay_bridge_schema { @@ -62,18 +59,12 @@ macro_rules! declare_relay_to_relay_bridge_schema { // default signer, which is always used to sign messages relay transactions on the left chain #[structopt(flatten)] left_sign: [<$left_chain SigningParams>], - // override for right->left headers signer - #[structopt(flatten)] - right_headers_to_left_sign_override: [<$right_chain HeadersTo $left_chain SigningParams>], #[structopt(flatten)] right: [<$right_chain ConnectionParams>], #[structopt(flatten)] // default signer, which is always used to sign messages relay transactions on the right chain right_sign: [<$right_chain SigningParams>], - // override for left->right headers signer - #[structopt(flatten)] - left_headers_to_right_sign_override: [<$left_chain HeadersTo $right_chain SigningParams>], } impl [<$left_chain $right_chain HeadersAndMessages>] { @@ -99,12 +90,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { accounts: vec![], }, )?, - right_to_left_transaction_params: self - .right_headers_to_left_sign_override - .transaction_params_or::(&self.left_sign)?, - left_to_right_transaction_params: self - .left_headers_to_right_sign_override - .transaction_params_or::(&self.right_sign)?, + right_to_left_transaction_params: self.left_sign.transaction_params::(), + left_to_right_transaction_params: self.right_sign.transaction_params::(), }) } } @@ -145,15 +132,6 @@ where Arc>, Arc>, )> { - self.common.right.accounts.push(TaggedAccount::Headers { - id: self.left_to_right_transaction_params.signer.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }); - self.common.left.accounts.push(TaggedAccount::Headers { - id: self.right_to_left_transaction_params.signer.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }); - ::Finality::start_relay_guards( &self.common.right.client, self.common.right.client.can_start_version_guard(), @@ -169,7 +147,7 @@ where OnDemandHeadersRelay::<::Finality>::new( self.common.left.client.clone(), self.common.right.client.clone(), - self.left_to_right_transaction_params.clone(), + self.common.right.tx_params.clone(), self.common.shared.only_mandatory_headers, None, ); @@ -177,7 +155,7 @@ where OnDemandHeadersRelay::<::Finality>::new( self.common.right.client.clone(), self.common.left.client.clone(), - self.right_to_left_transaction_params.clone(), + self.common.left.tx_params.clone(), self.common.shared.only_mandatory_headers, None, ); diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 9880edcda2ca1..7d01f8bcd7df4 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -28,14 +28,6 @@ use crate::bridges::{ bridge_hub_polkadot_messages_to_polkadot_bulletin::BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge, polkadot_bulletin_messages_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge, }, - rialto_millau::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - }, - rialto_parachain_millau::{ - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, - }, rococo_westend::{ bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendMessagesCliBridge, bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, @@ -109,10 +101,6 @@ where } } -impl MessagesRelayer for MillauToRialtoCliBridge {} -impl MessagesRelayer for RialtoToMillauCliBridge {} -impl MessagesRelayer for MillauToRialtoParachainCliBridge {} -impl MessagesRelayer for RialtoParachainToMillauCliBridge {} impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} @@ -126,12 +114,6 @@ impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - FullBridge::MillauToRialto => MillauToRialtoCliBridge::relay_messages(self), - FullBridge::RialtoToMillau => RialtoToMillauCliBridge::relay_messages(self), - FullBridge::MillauToRialtoParachain => - MillauToRialtoParachainCliBridge::relay_messages(self), - FullBridge::RialtoParachainToMillau => - RialtoParachainToMillauCliBridge::relay_messages(self), FullBridge::BridgeHubRococoToBridgeHubWococo => BridgeHubRococoToBridgeHubWococoMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubWococoToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 03d3860f3b224..668632320efa8 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -20,7 +20,6 @@ use crate::bridges::{ polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, }, polkadot_bulletin::polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - rialto_parachain_millau::rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, rococo_westend::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, @@ -29,7 +28,6 @@ use crate::bridges::{ rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, }, - westend_millau::westend_parachains_to_millau::AssetHubWestendToMillauCliBridge, }; use async_std::sync::Mutex; use async_trait::async_trait; @@ -70,8 +68,6 @@ pub struct RelayParachains { #[derive(Debug, EnumString, EnumVariantNames)] #[strum(serialize_all = "kebab_case")] pub enum RelayParachainsBridge { - RialtoToMillau, - WestendToMillau, RococoToBridgeHubWococo, WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, @@ -122,8 +118,6 @@ where } } -impl ParachainsRelayer for RialtoParachainToMillauCliBridge {} -impl ParachainsRelayer for AssetHubWestendToMillauCliBridge {} impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubRococoToBridgeHubWestendCliBridge {} @@ -136,10 +130,6 @@ impl RelayParachains { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - RelayParachainsBridge::RialtoToMillau => - RialtoParachainToMillauCliBridge::relay_parachains(self), - RelayParachainsBridge::WestendToMillau => - AssetHubWestendToMillauCliBridge::relay_parachains(self), RelayParachainsBridge::RococoToBridgeHubWococo => BridgeHubRococoToBridgeHubWococoCliBridge::relay_parachains(self), RelayParachainsBridge::WococoToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/resubmit_transactions.rs b/relays/bin-substrate/src/cli/resubmit_transactions.rs deleted file mode 100644 index c5b20e939c1fa..0000000000000 --- a/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ /dev/null @@ -1,560 +0,0 @@ -// 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 . - -use crate::cli::{chain_schema::*, Balance}; - -use bp_runtime::HeaderIdProvider; -use codec::{Decode, Encode}; -use num_traits::{One, Zero}; -use relay_substrate_client::{ - AccountKeyPairOf, BlockWithJustification, Chain, ChainWithTransactions, Client, - Error as SubstrateError, HeaderIdOf, HeaderOf, SignParam, -}; -use relay_utils::FailedClient; -use sp_core::Bytes; -use sp_runtime::{ - traits::{Hash, Header as HeaderT}, - transaction_validity::TransactionPriority, -}; -use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; -use substrate_relay_helper::TransactionParams; - -/// Start resubmit transactions process. -#[derive(StructOpt)] -pub struct ResubmitTransactions { - /// A bridge instance to relay headers for. - #[structopt(possible_values = RelayChain::VARIANTS, case_insensitive = true)] - chain: RelayChain, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - /// Number of blocks we see before considering queued transaction as stalled. - #[structopt(long, default_value = "5")] - stalled_blocks: u32, - /// Tip limit. We'll never submit transaction with larger tip. - #[structopt(long)] - tip_limit: Balance, - /// Tip increase step. We'll be checking updated transaction priority by increasing its tip by - /// this step. - #[structopt(long)] - tip_step: Balance, - /// Priority selection strategy. - #[structopt(subcommand)] - strategy: PrioritySelectionStrategy, -} - -/// Chain, which transactions we're going to track && resubmit. -#[derive(Debug, EnumString, EnumVariantNames)] -#[strum(serialize_all = "kebab_case")] -pub enum RelayChain { - Millau, -} - -/// Strategy to use for priority selection. -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] -pub enum PrioritySelectionStrategy { - /// Strategy selects tip that changes transaction priority to be better than priority of - /// the first transaction of previous block. - /// - /// It only makes sense to use this strategy for Millau transactions. Millau has transactions - /// that are close to block limits, so if there are any other queued transactions, 'large' - /// transaction won't fit the block && will be postponed. To avoid this, we change its priority - /// to some large value, making it best transaction => it'll be 'mined' first. - MakeItBestTransaction, - /// Strategy selects tip that changes transaction priority to be better than priority of - /// selected queued transaction. - /// - /// When we first see stalled transaction, we make it better than worst 1/4 of queued - /// transactions. If it is still stalled, we'll make it better than 1/3 of queued transactions, - /// ... - MakeItBetterThanQueuedTransaction, -} - -macro_rules! select_bridge { - ($bridge: expr, $generic: tt) => { - match $bridge { - RelayChain::Millau => { - type Target = relay_millau_client::Millau; - - $generic - }, - } - }; -} - -impl ResubmitTransactions { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - select_bridge!(self.chain, { - let relay_loop_name = format!("ResubmitTransactions{}", Target::NAME); - let client = self.target.into_client::().await?; - let transaction_params = TransactionParams { - signer: self.target_sign.to_keypair::()?, - mortality: self.target_sign.target_transactions_mortality, - }; - - relay_utils::relay_loop((), client) - .run(relay_loop_name, move |_, client, _| { - run_until_connection_lost( - client, - transaction_params.clone(), - Context { - strategy: self.strategy, - best_header: HeaderOf::::new( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - transaction: None, - resubmitted: 0, - stalled_for: Zero::zero(), - stalled_for_limit: self.stalled_blocks as _, - tip_step: self.tip_step.cast() as _, - tip_limit: self.tip_limit.cast() as _, - }, - ) - }) - .await - .map_err(Into::into) - }) - } -} - -impl PrioritySelectionStrategy { - /// Select target priority. - async fn select_target_priority( - &self, - client: &Client, - context: &Context, - ) -> Result, SubstrateError> { - match *self { - PrioritySelectionStrategy::MakeItBestTransaction => - read_previous_block_best_priority(client, context).await, - PrioritySelectionStrategy::MakeItBetterThanQueuedTransaction => - select_priority_from_queue(client, context).await, - } - } -} - -#[derive(Debug)] -struct Context { - /// Priority selection strategy. - strategy: PrioritySelectionStrategy, - /// Best known block header. - best_header: C::Header, - /// Hash of the (potentially) stalled transaction. - transaction: Option, - /// How many times we have resubmitted this `transaction`? - resubmitted: u32, - /// This transaction is in pool for `stalled_for` wakeup intervals. - stalled_for: C::BlockNumber, - /// When `stalled_for` reaching this limit, transaction is considered stalled. - stalled_for_limit: C::BlockNumber, - /// Tip step interval. - tip_step: C::Balance, - /// Maximal tip. - tip_limit: C::Balance, -} - -impl Context { - /// Return true if transaction has stalled. - fn is_stalled(&self) -> bool { - self.stalled_for >= self.stalled_for_limit - } - - /// Notice resubmitted transaction. - fn notice_resubmitted_transaction(mut self, transaction: C::Hash) -> Self { - self.transaction = Some(transaction); - self.stalled_for = Zero::zero(); - self.resubmitted += 1; - self - } - - /// Notice transaction from the transaction pool. - fn notice_transaction(mut self, transaction: C::Hash) -> Self { - if self.transaction == Some(transaction) { - self.stalled_for += One::one(); - } else { - self.transaction = Some(transaction); - self.stalled_for = One::one(); - self.resubmitted = 0; - } - self - } -} - -/// Run resubmit transactions loop. -async fn run_until_connection_lost( - client: Client, - transaction_params: TransactionParams>, - mut context: Context, -) -> Result<(), FailedClient> { - loop { - async_std::task::sleep(C::AVERAGE_BLOCK_INTERVAL).await; - - let result = run_loop_iteration(client.clone(), transaction_params.clone(), context).await; - context = match result { - Ok(context) => context, - Err(error) => { - log::error!( - target: "bridge", - "Resubmit {} transactions loop has failed with error: {:?}", - C::NAME, - error, - ); - return Err(FailedClient::Target) - }, - }; - } -} - -/// Run single loop iteration. -async fn run_loop_iteration( - client: Client, - transaction_params: TransactionParams>, - mut context: Context, -) -> Result, SubstrateError> { - // correct best header is required for all other actions - context.best_header = client.best_header().await?; - - // check if there's queued transaction, signed by given author - let original_transaction = - match lookup_signer_transaction(&client, &transaction_params.signer).await? { - Some(original_transaction) => original_transaction, - None => { - log::trace!(target: "bridge", "No {} transactions from required signer in the txpool", C::NAME); - return Ok(context) - }, - }; - let original_transaction_hash = C::Hasher::hash(&original_transaction.encode()); - let context = context.notice_transaction(original_transaction_hash); - - // if transaction hasn't been mined for `stalled_blocks`, we'll need to resubmit it - if !context.is_stalled() { - log::trace!( - target: "bridge", - "{} transaction {:?} is not yet stalled ({:?}/{:?})", - C::NAME, - context.transaction, - context.stalled_for, - context.stalled_for_limit, - ); - return Ok(context) - } - - // select priority for updated transaction - let target_priority = match context.strategy.select_target_priority(&client, &context).await? { - Some(target_priority) => target_priority, - None => { - log::trace!(target: "bridge", "Failed to select target priority"); - return Ok(context) - }, - }; - - // update transaction tip - let (is_updated, updated_transaction) = update_transaction_tip( - &client, - &transaction_params, - context.best_header.id(), - original_transaction, - context.tip_step, - context.tip_limit, - target_priority, - ) - .await?; - - if !is_updated { - log::trace!(target: "bridge", "{} transaction tip can not be updated. Reached limit?", C::NAME); - return Ok(context) - } - - let updated_transaction = updated_transaction.encode(); - let updated_transaction_hash = C::Hasher::hash(&updated_transaction); - client.submit_unsigned_extrinsic(Bytes(updated_transaction)).await?; - - log::info!( - target: "bridge", - "Replaced {} transaction {} with {} in txpool", - C::NAME, - original_transaction_hash, - updated_transaction_hash, - ); - - Ok(context.notice_resubmitted_transaction(updated_transaction_hash)) -} - -/// Search transaction pool for transaction, signed by given key pair. -async fn lookup_signer_transaction( - client: &Client, - key_pair: &AccountKeyPairOf, -) -> Result, SubstrateError> { - let pending_transactions = client.pending_extrinsics().await?; - for pending_transaction in pending_transactions { - let pending_transaction = C::SignedTransaction::decode(&mut &pending_transaction.0[..]) - .map_err(SubstrateError::ResponseParseFailed)?; - if !C::is_signed_by(key_pair, &pending_transaction) { - continue - } - - return Ok(Some(pending_transaction)) - } - - Ok(None) -} - -/// Read priority of best signed transaction of previous block. -async fn read_previous_block_best_priority( - client: &Client, - context: &Context, -) -> Result, SubstrateError> { - let best_block = client.get_block(Some(context.best_header.hash())).await?; - let best_transaction = best_block - .extrinsics() - .iter() - .filter_map(|xt| C::SignedTransaction::decode(&mut &xt[..]).ok()) - .find(|xt| C::is_signed(xt)); - match best_transaction { - Some(best_transaction) => Ok(Some( - client - .validate_transaction(*context.best_header.parent_hash(), best_transaction) - .await?? - .priority, - )), - None => Ok(None), - } -} - -/// Select priority of some queued transaction. -async fn select_priority_from_queue( - client: &Client, - context: &Context, -) -> Result, SubstrateError> { - // select transaction from the queue - let queued_transactions = client.pending_extrinsics().await?; - let selected_transaction = match select_transaction_from_queue(queued_transactions, context) { - Some(selected_transaction) => selected_transaction, - None => return Ok(None), - }; - - let selected_transaction = C::SignedTransaction::decode(&mut &selected_transaction[..]) - .map_err(SubstrateError::ResponseParseFailed)?; - let target_priority = client - .validate_transaction(context.best_header.hash(), selected_transaction) - .await?? - .priority; - Ok(Some(target_priority)) -} - -/// Select transaction with target priority from the vec of queued transactions. -fn select_transaction_from_queue( - mut queued_transactions: Vec, - context: &Context, -) -> Option { - if queued_transactions.is_empty() { - return None - } - - // the more times we resubmit transaction (`context.resubmitted`), the closer we move - // to the front of the transaction queue - let total_transactions = queued_transactions.len(); - let resubmitted_factor = context.resubmitted; - let divisor = - 1usize.saturating_add(1usize.checked_shl(resubmitted_factor).unwrap_or(usize::MAX)); - let transactions_to_skip = total_transactions / divisor; - - Some( - queued_transactions - .swap_remove(std::cmp::min(total_transactions - 1, transactions_to_skip)), - ) -} - -/// Try to find appropriate tip for transaction so that its priority is larger than given. -async fn update_transaction_tip( - client: &Client, - transaction_params: &TransactionParams>, - at_block: HeaderIdOf, - tx: C::SignedTransaction, - tip_step: C::Balance, - tip_limit: C::Balance, - target_priority: TransactionPriority, -) -> Result<(bool, C::SignedTransaction), SubstrateError> { - let stx = format!("{tx:?}"); - let mut current_priority = client.validate_transaction(at_block.1, tx.clone()).await??.priority; - let mut unsigned_tx = C::parse_transaction(tx).ok_or_else(|| { - SubstrateError::Custom(format!("Failed to parse {} transaction {stx}", C::NAME,)) - })?; - let old_tip = unsigned_tx.tip; - - let runtime_version = client.simple_runtime_version().await?; - while current_priority < target_priority { - let next_tip = unsigned_tx.tip + tip_step; - if next_tip > tip_limit { - break - } - - log::trace!( - target: "bridge", - "{} transaction priority with tip={:?}: {}. Target priority: {}", - C::NAME, - unsigned_tx.tip, - current_priority, - target_priority, - ); - - unsigned_tx.tip = next_tip; - current_priority = client - .validate_transaction( - at_block.1, - C::sign_transaction( - SignParam { - spec_version: runtime_version.spec_version, - transaction_version: runtime_version.transaction_version, - genesis_hash: *client.genesis_hash(), - signer: transaction_params.signer.clone(), - }, - unsigned_tx.clone(), - )?, - ) - .await?? - .priority; - } - - log::debug!( - target: "bridge", - "{} transaction tip has changed from {:?} to {:?}", - C::NAME, - old_tip, - unsigned_tx.tip, - ); - - Ok(( - old_tip != unsigned_tx.tip, - C::sign_transaction( - SignParam { - spec_version: runtime_version.spec_version, - transaction_version: runtime_version.transaction_version, - genesis_hash: *client.genesis_hash(), - signer: transaction_params.signer.clone(), - }, - unsigned_tx.era(relay_substrate_client::TransactionEra::new( - at_block, - transaction_params.mortality, - )), - )?, - )) -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_rialto::Hash; - use relay_rialto_client::Rialto; - - fn context() -> Context { - Context { - strategy: PrioritySelectionStrategy::MakeItBestTransaction, - best_header: HeaderOf::::new( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - transaction: None, - resubmitted: 0, - stalled_for: Zero::zero(), - stalled_for_limit: 3, - tip_step: 100, - tip_limit: 1000, - } - } - - #[test] - fn context_works() { - let mut context = context(); - - // when transaction is noticed 2/3 times, it isn't stalled - context = context.notice_transaction(Default::default()); - assert!(!context.is_stalled()); - assert_eq!(context.stalled_for, 1); - assert_eq!(context.resubmitted, 0); - context = context.notice_transaction(Default::default()); - assert!(!context.is_stalled()); - assert_eq!(context.stalled_for, 2); - assert_eq!(context.resubmitted, 0); - - // when transaction is noticed for 3rd time in a row, it is considered stalled - context = context.notice_transaction(Default::default()); - assert!(context.is_stalled()); - assert_eq!(context.stalled_for, 3); - assert_eq!(context.resubmitted, 0); - - // and after we resubmit it, we forget previous transaction - context = context.notice_resubmitted_transaction(Hash::from([1; 32])); - assert_eq!(context.transaction, Some(Hash::from([1; 32]))); - assert_eq!(context.resubmitted, 1); - assert_eq!(context.stalled_for, 0); - } - - #[test] - fn select_transaction_from_queue_works_with_empty_queue() { - assert_eq!(select_transaction_from_queue(vec![], &context()), None); - } - - #[test] - fn select_transaction_from_queue_works() { - let mut context = context(); - let queued_transactions = vec![ - Bytes(vec![1]), - Bytes(vec![2]), - Bytes(vec![3]), - Bytes(vec![4]), - Bytes(vec![5]), - Bytes(vec![6]), - ]; - - // when we resubmit tx for the first time, 1/2 of queue is skipped - assert_eq!( - select_transaction_from_queue(queued_transactions.clone(), &context), - Some(Bytes(vec![4])), - ); - - // when we resubmit tx for the second time, 1/3 of queue is skipped - context = context.notice_resubmitted_transaction(Hash::from([1; 32])); - assert_eq!( - select_transaction_from_queue(queued_transactions.clone(), &context), - Some(Bytes(vec![3])), - ); - - // when we resubmit tx for the third time, 1/5 of queue is skipped - context = context.notice_resubmitted_transaction(Hash::from([2; 32])); - assert_eq!( - select_transaction_from_queue(queued_transactions.clone(), &context), - Some(Bytes(vec![2])), - ); - - // when we resubmit tx for the second time, 1/9 of queue is skipped - context = context.notice_resubmitted_transaction(Hash::from([3; 32])); - assert_eq!( - select_transaction_from_queue(queued_transactions, &context), - Some(Bytes(vec![1])), - ); - } -} diff --git a/relays/bin-substrate/src/cli/send_message.rs b/relays/bin-substrate/src/cli/send_message.rs deleted file mode 100644 index 02ef58b371948..0000000000000 --- a/relays/bin-substrate/src/cli/send_message.rs +++ /dev/null @@ -1,177 +0,0 @@ -// 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 . - -use crate::{ - bridges::{ - rialto_millau::{ - millau_headers_to_rialto::MillauToRialtoCliBridge, - rialto_headers_to_millau::RialtoToMillauCliBridge, - }, - rialto_parachain_millau::{ - millau_headers_to_rialto_parachain::MillauToRialtoParachainCliBridge, - rialto_parachains_to_millau::RialtoParachainToMillauCliBridge, - }, - }, - cli::{ - bridge::{FullBridge, MessagesCliBridge}, - chain_schema::*, - encode_message::{self, CliEncodeMessage, RawMessage}, - CliChain, - }, -}; -use async_trait::async_trait; -use codec::{Decode, Encode}; -use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, UnsignedTransaction, -}; -use sp_core::Pair; -use sp_runtime::AccountId32; -use std::fmt::Display; -use structopt::StructOpt; -use strum::VariantNames; - -/// Send bridge message. -#[derive(StructOpt)] -pub struct SendMessage { - /// A bridge instance to encode call for. - #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] - bridge: FullBridge, - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - /// Message type. - #[structopt(subcommand)] - message: crate::cli::encode_message::Message, -} - -#[async_trait] -trait MessageSender: MessagesCliBridge -where - Self::Source: ChainBase + ChainWithTransactions + CliChain + CliEncodeMessage, - ::Balance: Display + From + Into, - ::Call: Sync, - ::SignedTransaction: Sync, - AccountIdOf: From< as Pair>::Public>, - AccountId32: From< as Pair>::Public>, -{ - async fn send_message(data: SendMessage) -> anyhow::Result<()> { - let payload = encode_message::encode_message::(&data.message)?; - - let source_client = data.source.into_client::().await?; - let source_sign = data.source_sign.to_keypair::()?; - - let payload_len = payload.encoded_size(); - let send_message_call = Self::Source::encode_execute_xcm(decode_xcm(payload)?)?; - - source_client - .submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| { - let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); - log::info!( - target: "bridge", - "Sending message to {}. Size: {}", - Self::Target::NAME, - payload_len, - ); - Ok(unsigned) - }) - .await?; - - Ok(()) - } -} - -impl MessageSender for MillauToRialtoCliBridge {} -impl MessageSender for RialtoToMillauCliBridge {} -impl MessageSender for MillauToRialtoParachainCliBridge {} -impl MessageSender for RialtoParachainToMillauCliBridge {} - -impl SendMessage { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - FullBridge::MillauToRialto => MillauToRialtoCliBridge::send_message(self), - FullBridge::RialtoToMillau => RialtoToMillauCliBridge::send_message(self), - FullBridge::MillauToRialtoParachain => - MillauToRialtoParachainCliBridge::send_message(self), - FullBridge::RialtoParachainToMillau => - RialtoParachainToMillauCliBridge::send_message(self), - // all our (soon to retire_ testnets are above, so if is fine to use `_` - _ => unimplemented!("Sending message from in {:?} is not supported", self.bridge,), - } - .await - } -} - -/// Decode SCALE encoded raw XCM message. -pub(crate) fn decode_xcm(message: RawMessage) -> anyhow::Result> { - Decode::decode(&mut &message[..]) - .map_err(|e| anyhow::format_err!("Failed to decode XCM program: {:?}", e)) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cli::{ExplicitOrMaximal, HexBytes}; - - #[test] - fn send_raw_rialto_to_millau() { - // given - let send_message = SendMessage::from_iter(vec![ - "send-message", - "rialto-to-millau", - "--source-port", - "1234", - "--source-signer", - "//Alice", - "raw", - "dead", - ]); - - // then - assert_eq!(send_message.bridge, FullBridge::RialtoToMillau); - assert_eq!(send_message.source.source_port, 1234); - assert_eq!(send_message.source_sign.source_signer, Some("//Alice".into())); - assert_eq!( - send_message.message, - crate::cli::encode_message::Message::Raw { data: HexBytes(vec![0xDE, 0xAD]) } - ); - } - - #[test] - fn send_sized_rialto_to_millau() { - // given - let send_message = SendMessage::from_iter(vec![ - "send-message", - "rialto-to-millau", - "--source-port", - "1234", - "--source-signer", - "//Alice", - "sized", - "max", - ]); - - // then - assert_eq!(send_message.bridge, FullBridge::RialtoToMillau); - assert_eq!(send_message.source.source_port, 1234); - assert_eq!(send_message.source_sign.source_signer, Some("//Alice".into())); - assert_eq!( - send_message.message, - crate::cli::encode_message::Message::Sized { size: ExplicitOrMaximal::Maximal } - ); - } -} diff --git a/relays/client-millau/Cargo.toml b/relays/client-millau/Cargo.toml deleted file mode 100644 index ccfeced1c2704..0000000000000 --- a/relays/client-millau/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "relay-millau-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Supported Chains - -bp-messages = { path = "../../primitives/messages" } -bp-millau = { path = "../../primitives/chain-millau" } -bp-runtime = { path = "../../primitives/runtime" } -millau-runtime = { path = "../../bin/millau/runtime" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs deleted file mode 100644 index b3101c980c557..0000000000000 --- a/relays/client-millau/src/lib.rs +++ /dev/null @@ -1,197 +0,0 @@ -// 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 . - -//! Types used to connect to the Millau-Substrate chain. - -use bp_messages::MessageNonce; -use bp_millau::MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use bp_runtime::ChainId; -use codec::{Compact, Decode, Encode}; -use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - FullRuntimeUtilityPallet, NonceOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use sp_session::MembershipProof; -use std::time::Duration; - -/// Millau header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Millau chain definition. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Millau; - -impl UnderlyingChainProvider for Millau { - type Chain = bp_millau::Millau; -} - -impl ChainWithMessages for Millau { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_millau::WITH_MILLAU_MESSAGES_PALLET_NAME; - // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): change the name - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some("BridgeRelayers"); - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_millau::TO_MILLAU_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_millau::FROM_MILLAU_MESSAGE_DETAILS_METHOD; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_millau::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_millau::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -} - -impl Chain for Millau { - const ID: ChainId = bp_runtime::MILLAU_CHAIN_ID; - const NAME: &'static str = "Millau"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_millau::BEST_FINALIZED_MILLAU_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - - type SignedBlock = millau_runtime::SignedBlock; - type Call = millau_runtime::RuntimeCall; -} - -impl ChainWithGrandpa for Millau { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - MILLAU_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl ChainWithBalances for Millau { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - use frame_support::storage::generator::StorageMap; - StorageKey(frame_system::Account::::storage_map_final_key( - account_id, - )) - } -} - -impl ChainWithTransactions for Millau { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = millau_runtime::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::from_raw( - unsigned.call.clone(), - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(unsigned.era.frame_era()), - frame_system::CheckNonce::::from(unsigned.nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), - millau_runtime::BridgeRejectObsoleteHeadersAndMessages, - millau_runtime::BridgeRefundRialtoParachainMessages::default(), - ), - ( - (), - param.spec_version, - param.transaction_version, - param.genesis_hash, - unsigned.era.signed_payload(param.genesis_hash), - (), - (), - (), - (), - () - ), - ); - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(millau_runtime::UncheckedExtrinsic::new_signed( - call.into_decoded()?, - signer.into_account(), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == millau_runtime::Address::from(*signer.public().as_array_ref()) - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some( - UnsignedTransaction::new( - tx.function.into(), - Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), - ) - .tip(Compact::>::decode(&mut &extra.7.encode()[..]).ok()?.into()), - ) - } -} - -impl ChainWithUtilityPallet for Millau { - type UtilityPallet = FullRuntimeUtilityPallet; -} - -/// Millau signing params. -pub type SigningParams = sp_core::sr25519::Pair; - -/// Millau header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: millau_runtime::RuntimeCall::System(millau_runtime::SystemCall::remark { - remark: b"Hello world!".to_vec(), - }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = Millau::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 64].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = Millau::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/client-rialto-parachain/Cargo.toml b/relays/client-rialto-parachain/Cargo.toml deleted file mode 100644 index fc91e27ee0f82..0000000000000 --- a/relays/client-rialto-parachain/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "relay-rialto-parachain-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5" } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = [] } - -# Bridge dependencies - -bp-bridge-hub-cumulus = { path = "../../primitives/chain-bridge-hub-cumulus" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-millau = { path = "../../primitives/chain-millau" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } -bp-runtime = { path = "../../primitives/runtime" } - -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-substrate-client = { path = "../client-substrate" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-rialto-parachain/src/codegen_runtime.rs b/relays/client-rialto-parachain/src/codegen_runtime.rs deleted file mode 100644 index eb19d98d7e487..0000000000000 --- a/relays/client-rialto-parachain/src/codegen_runtime.rs +++ /dev/null @@ -1,2936 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url http://localhost:20433 - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -pub mod api { - use super::api as root_mod; - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod bp_header_chain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredHeaderData<_0, _1> { - pub number: _0, - pub state_root: _1, - } - } - pub mod bp_messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DeliveredMessages { - pub begin: ::core::primitive::u64, - pub end: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundLaneData<_0> { - pub relayers: ::std::vec::Vec>, - pub last_confirmed_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageKey { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MessagesOperatingMode { - #[codec(index = 0)] - Basic(runtime_types::bp_runtime::BasicOperatingMode), - #[codec(index = 1)] - RejectingOutboundMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundLaneData { - pub oldest_unpruned_nonce: ::core::primitive::u64, - pub latest_received_nonce: ::core::primitive::u64, - pub latest_generated_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalResult<_0> { - #[codec(index = 0)] - Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), - #[codec(index = 1)] - InvalidNonce, - #[codec(index = 2)] - TooManyUnrewardedRelayers, - #[codec(index = 3)] - TooManyUnconfirmedMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceivedMessages<_0> { - pub lane: runtime_types::bp_messages::LaneId, - pub receive_results: ::std::vec::Vec<( - ::core::primitive::u64, - runtime_types::bp_messages::ReceivalResult<_0>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnrewardedRelayer<_0> { - pub relayer: _0, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - } - pub mod bp_relayers { - use super::runtime_types; - pub mod registration { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0, _1> { - pub valid_till: _0, - pub stake: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardsAccountOwner { - #[codec(index = 0)] - ThisChain, - #[codec(index = 1)] - BridgedChain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardsAccountParams { - pub lane_id: runtime_types::bp_messages::LaneId, - pub bridged_chain_id: [::core::primitive::u8; 4usize], - pub owner: runtime_types::bp_relayers::RewardsAccountOwner, - } - } - pub mod bp_runtime { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageDispatchResult<_0> { - pub unspent_weight: ::sp_weights::Weight, - pub dispatch_level_result: _0, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OwnedBridgeModuleError { - #[codec(index = 0)] - Halted, - } - } - pub mod bridge_runtime_common { - use super::runtime_types; - pub mod messages_xcm_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmBlobMessageDispatchResult { - #[codec(index = 0)] - InvalidPayload, - #[codec(index = 1)] - Dispatched, - #[codec(index = 2)] - NotDispatched, - } - } - } - pub mod cumulus_pallet_dmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - OverLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat { message_id: [::core::primitive::u8; 32usize] }, - #[codec(index = 1)] - UnsupportedVersion { message_id: [::core::primitive::u8; 32usize] }, - #[codec(index = 2)] - ExecutedDownward { - message_id: [::core::primitive::u8; 32usize], - outcome: runtime_types::xcm::v3::traits::Outcome, - }, - #[codec(index = 3)] - WeightExhausted { - message_id: [::core::primitive::u8; 32usize], - remaining_weight: ::sp_weights::Weight, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - OverweightEnqueued { - message_id: [::core::primitive::u8; 32usize], - overweight_index: ::core::primitive::u64, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 5)] - OverweightServiced { - overweight_index: ::core::primitive::u64, - weight_used: ::sp_weights::Weight, - }, - #[codec(index = 6)] - MaxMessagesExhausted { message_id: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ConfigData { - pub max_individual: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PageIndexData { - pub begin_used: ::core::primitive::u32, - pub end_used: ::core::primitive::u32, - pub overweight_count: ::core::primitive::u64, - } - } - pub mod cumulus_pallet_parachain_system { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OverlappingUpgrades, - #[codec(index = 1)] - ProhibitedByPolkadot, - #[codec(index = 2)] - TooBig, - #[codec(index = 3)] - ValidationDataNotAvailable, - #[codec(index = 4)] - HostConfigurationNotAvailable, - #[codec(index = 5)] - NotScheduled, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidationFunctionStored, - #[codec(index = 1)] - ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, - #[codec(index = 2)] - ValidationFunctionDiscarded, - #[codec(index = 3)] - UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - DownwardMessagesReceived { count: ::core::primitive::u32 }, - #[codec(index = 5)] - DownwardMessagesProcessed { - weight_used: ::sp_weights::Weight, - dmq_head: ::subxt::utils::H256, - }, - #[codec(index = 6)] - UpwardMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - pub mod relay_state_snapshot { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { - pub dmq_mqc_head: ::subxt::utils::H256, - pub relay_dispatch_queue_size: (::core::primitive::u32, ::core::primitive::u32), - pub ingress_channels: ::std::vec::Vec<( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, - )>, - pub egress_channels: ::std::vec::Vec<( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_primitives::v4::AbridgedHrmpChannel, - )>, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CodeUpgradeAuthorization { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } - } - pub mod cumulus_pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - UnsupportedVersion([::core::primitive::u8; 32usize]), - #[codec(index = 2)] - ExecutedDownward( - [::core::primitive::u8; 32usize], - runtime_types::xcm::v3::traits::Outcome, - ), - } - } - } - pub mod cumulus_pallet_xcmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - #[codec(index = 1)] - suspend_xcm_execution, - #[codec(index = 2)] - resume_xcm_execution, - #[codec(index = 3)] - update_suspend_threshold { new: ::core::primitive::u32 }, - #[codec(index = 4)] - update_drop_threshold { new: ::core::primitive::u32 }, - #[codec(index = 5)] - update_resume_threshold { new: ::core::primitive::u32 }, - #[codec(index = 6)] - update_threshold_weight { new: ::sp_weights::Weight }, - #[codec(index = 7)] - update_weight_restrict_decay { new: ::sp_weights::Weight }, - #[codec(index = 8)] - update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSend, - #[codec(index = 1)] - BadXcmOrigin, - #[codec(index = 2)] - BadXcm, - #[codec(index = 3)] - BadOverweightIndex, - #[codec(index = 4)] - WeightOverLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Success { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - weight: ::sp_weights::Weight, - }, - #[codec(index = 1)] - Fail { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - error: runtime_types::xcm::v3::traits::Error, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - BadVersion { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 3)] - BadFormat { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 4)] - XcmpMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 5)] - OverweightEnqueued { - sender: runtime_types::polkadot_parachain::primitives::Id, - sent_at: ::core::primitive::u32, - index: ::core::primitive::u64, - required: ::sp_weights::Weight, - }, - #[codec(index = 6)] - OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundChannelDetails { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, - pub message_metadata: ::std::vec::Vec<( - ::core::primitive::u32, - runtime_types::polkadot_parachain::primitives::XcmpMessageFormat, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundChannelDetails { - pub recipient: runtime_types::polkadot_parachain::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, - pub signals_exist: ::core::primitive::bool, - pub first_index: ::core::primitive::u16, - pub last_index: ::core::primitive::u16, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OutboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueueConfigData { - pub suspend_threshold: ::core::primitive::u32, - pub drop_threshold: ::core::primitive::u32, - pub resume_threshold: ::core::primitive::u32, - pub threshold_weight: ::sp_weights::Weight, - pub weight_restrict_decay: ::sp_weights::Weight, - pub xcmp_max_individual_weight: ::sp_weights::Weight, - } - } - pub mod cumulus_primitives_parachain_inherent { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainInherentData { - pub validation_data: - runtime_types::polkadot_primitives::v4::PersistedValidationData< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, - pub downward_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundDownwardMessage< - ::core::primitive::u32, - >, - >, - pub horizontal_messages: ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain::primitives::Id, - ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundHrmpMessage< - ::core::primitive::u32, - >, - >, - >, - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commit<_0, _1, _2, _3> { - pub target_hash: _0, - pub target_number: _1, - pub precommits: ::std::vec::Vec< - runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedPrecommit<_0, _1, _2, _3> { - pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, - pub signature: _2, - pub id: _3, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - } - pub mod traits { - use super::runtime_types; - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - set_balance_deprecated { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - #[codec(compact)] - old_reserved: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 7)] - transfer { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bridge_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u64, - ::bp_millau::BlakeTwoAndKeccak256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u64, - hash: ::bp_millau::MillauHash, - }, - } - } - pub mod storage_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - } - } - pub mod pallet_bridge_messages { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: bp_millau :: MillauHash > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: bp_millau :: MillauHash > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotOperatingNormally, - #[codec(index = 1)] - InactiveOutboundLane, - #[codec(index = 2)] - MessageIsTooLarge, - #[codec(index = 3)] - MessageRejectedByChainVerifier, - #[codec(index = 4)] - MessageRejectedByLaneVerifier, - #[codec(index = 5)] - FailedToWithdrawMessageFee, - #[codec(index = 6)] - TooManyMessagesInTheProof, - #[codec(index = 7)] - InvalidMessagesProof, - #[codec(index = 8)] - InvalidMessagesDeliveryProof, - #[codec(index = 9)] - InvalidUnrewardedRelayers, - #[codec(index = 10)] - InvalidUnrewardedRelayersState, - #[codec(index = 11)] - InsufficientDispatchWeight, - #[codec(index = 12)] - MessageIsNotYetSent, - #[codec(index = 13)] - TryingToConfirmMoreMessagesThanExpected, - #[codec(index = 14)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - } - } - pub mod pallet_bridge_relayers { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim_rewards { - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - }, - #[codec(index = 1)] - register { valid_till: ::core::primitive::u32 }, - #[codec(index = 2)] - deregister, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NoRewardForRelayer, - #[codec(index = 1)] - FailedToPayReward, - #[codec(index = 2)] - InvalidRegistrationLease, - #[codec(index = 3)] - CannotReduceRegistrationLease, - #[codec(index = 4)] - FailedToReserve, - #[codec(index = 5)] - FailedToUnreserve, - #[codec(index = 6)] - NotRegistered, - #[codec(index = 7)] - RegistrationIsStillActive, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RewardPaid { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 1)] - RegistrationUpdated { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - #[codec(index = 2)] - Deregistered { relayer: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - SlashedAndDeregistered { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - } - } - } - pub mod pallet_sudo { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - sudo { - call: - ::std::boxed::Box, - }, - #[codec(index = 1)] - sudo_unchecked_weight { - call: - ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - set_key { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - sudo_as { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: - ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - RequireSudo, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Sudid { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - KeyChanged { - old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 2)] - SudoAsDone { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - xcm_version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted(runtime_types::xcm::v3::traits::Outcome), - #[codec(index = 1)] - Sent( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::Xcm, - ), - #[codec(index = 2)] - UnexpectedResponse( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 3)] - ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), - #[codec(index = 4)] - Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), - #[codec(index = 5)] - NotifyOverweight( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ::sp_weights::Weight, - ::sp_weights::Weight, - ), - #[codec(index = 6)] - NotifyDispatchError( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 7)] - NotifyDecodeFailed( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 8)] - InvalidResponder( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 9)] - InvalidResponderVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 10)] - ResponseTaken(::core::primitive::u64), - #[codec(index = 11)] - AssetsTrapped( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - #[codec(index = 12)] - VersionChangeNotified( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 13)] - SupportedVersionChanged( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - ), - #[codec(index = 14)] - NotifyTargetSendFail( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::traits::Error, - ), - #[codec(index = 15)] - NotifyTargetMigrationFail( - runtime_types::xcm::VersionedMultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 16)] - InvalidQuerierVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 17)] - InvalidQuerier( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 18)] - VersionNotifyStarted( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 19)] - VersionNotifyRequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 20)] - VersionNotifyUnrequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 21)] - FeesPaid( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 22)] - AssetsClaimed( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmpMessageFormat { - #[codec(index = 0)] - ConcatenatedVersionedXcm, - #[codec(index = 1)] - ConcatenatedEncodedBlob, - #[codec(index = 2)] - Signals, - } - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v4 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHostConfiguration { - pub max_code_size: ::core::primitive::u32, - pub max_head_data_size: ::core::primitive::u32, - pub max_upward_queue_count: ::core::primitive::u32, - pub max_upward_queue_size: ::core::primitive::u32, - pub max_upward_message_size: ::core::primitive::u32, - pub max_upward_message_num_per_candidate: ::core::primitive::u32, - pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, - pub validation_upgrade_cooldown: ::core::primitive::u32, - pub validation_upgrade_delay: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PersistedValidationData<_0, _1> { - pub parent_head: runtime_types::polkadot_parachain::primitives::HeadData, - pub relay_parent_number: _1, - pub relay_parent_storage_root: _0, - pub max_pov_size: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - } - } - pub mod rialto_parachain_runtime { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DummyBridgeRefundMillauMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 2)] - Sudo(runtime_types::pallet_sudo::pallet::Call), - #[codec(index = 20)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), - #[codec(index = 30)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 50)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), - #[codec(index = 51)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 52)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Call), - #[codec(index = 53)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), - #[codec(index = 54)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), - #[codec(index = 55)] - BridgeMillauGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 56)] - BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 2)] - Sudo(runtime_types::pallet_sudo::pallet::Event), - #[codec(index = 3)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 20)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), - #[codec(index = 30)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 50)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), - #[codec(index = 51)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 52)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), - #[codec(index = 53)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), - #[codec(index = 54)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), - #[codec(index = 55)] - BridgeMillauGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 56)] - BridgeMillauMessages(runtime_types::pallet_bridge_messages::pallet::Event), - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - } - pub mod sp_core { - use super::runtime_types; - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, - ); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_trie { - use super::runtime_types; - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StorageProof { - pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - } - } -} diff --git a/relays/client-rialto-parachain/src/lib.rs b/relays/client-rialto-parachain/src/lib.rs deleted file mode 100644 index b6617b90f137e..0000000000000 --- a/relays/client-rialto-parachain/src/lib.rs +++ /dev/null @@ -1,138 +0,0 @@ -// 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 . - -//! Types used to connect to the Rialto-Substrate chain. - -pub mod codegen_runtime; - -use bp_messages::MessageNonce; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, Error as SubstrateError, - SignParam, UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::rialto_parachain_runtime::RuntimeCall; -pub type SudoCall = runtime_types::pallet_sudo::pallet::Call; -pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Rialto parachain definition -#[derive(Debug, Clone, Copy)] -pub struct RialtoParachain; - -impl UnderlyingChainProvider for RialtoParachain { - type Chain = bp_rialto_parachain::RialtoParachain; -} - -impl Chain for RialtoParachain { - const ID: ChainId = bp_runtime::RIALTO_PARACHAIN_CHAIN_ID; - const NAME: &'static str = "RialtoParachain"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_rialto_parachain::BEST_FINALIZED_RIALTO_PARACHAIN_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - - type SignedBlock = bp_polkadot_core::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithBalances for RialtoParachain { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_polkadot_core::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl ChainWithMessages for RialtoParachain { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_rialto_parachain::WITH_RIALTO_PARACHAIN_MESSAGES_PALLET_NAME; - // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): change the name - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some("BridgeRelayers"); - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto_parachain::TO_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto_parachain::FROM_RIALTO_PARACHAIN_MESSAGE_DETAILS_METHOD; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_rialto_parachain::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_rialto_parachain::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -} - -impl ChainWithTransactions for RialtoParachain { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_rialto_parachain::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - (((), ()), ((), ())), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } -} - -/// RialtoParachain signing params. -pub type SigningParams = sp_core::sr25519::Pair; - -/// RialtoParachain header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; diff --git a/relays/client-rialto/Cargo.toml b/relays/client-rialto/Cargo.toml deleted file mode 100644 index 7a1b378c9ac9c..0000000000000 --- a/relays/client-rialto/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "relay-rialto-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Bridge dependencies - -bp-messages = { path = "../../primitives/messages" } -bp-rialto = { path = "../../primitives/chain-rialto" } -bp-runtime = { path = "../../primitives/runtime" } -rialto-runtime = { path = "../../bin/rialto/runtime" } - -# Substrate Dependencies - -frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs deleted file mode 100644 index 2aa5bd638cc87..0000000000000 --- a/relays/client-rialto/src/lib.rs +++ /dev/null @@ -1,191 +0,0 @@ -// 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 . - -//! Types used to connect to the Rialto-Substrate chain. - -use bp_messages::MessageNonce; -use bp_rialto::RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use bp_runtime::ChainId; -use codec::{Compact, Decode, Encode}; -use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, Error as SubstrateError, NonceOf, RelayChain, SignParam, - UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use sp_session::MembershipProof; -use std::time::Duration; - -/// Rialto header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Rialto chain definition -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Rialto; - -impl UnderlyingChainProvider for Rialto { - type Chain = bp_rialto::Rialto; -} - -impl Chain for Rialto { - const ID: ChainId = bp_runtime::RIALTO_CHAIN_ID; - const NAME: &'static str = "Rialto"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_rialto::BEST_FINALIZED_RIALTO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5); - - type SignedBlock = rialto_runtime::SignedBlock; - type Call = rialto_runtime::RuntimeCall; -} - -impl ChainWithGrandpa for Rialto { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - RIALTO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl RelayChain for Rialto { - const PARAS_PALLET_NAME: &'static str = bp_rialto::PARAS_PALLET_NAME; -} - -impl ChainWithMessages for Rialto { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_rialto::WITH_RIALTO_MESSAGES_PALLET_NAME; - // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): change the name - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some("BridgeRelayers"); - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto::TO_RIALTO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_rialto::FROM_RIALTO_MESSAGE_DETAILS_METHOD; - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_rialto::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_rialto::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -} - -impl ChainWithBalances for Rialto { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - use frame_support::storage::generator::StorageMap; - StorageKey(frame_system::Account::::storage_map_final_key( - account_id, - )) - } -} - -impl ChainWithTransactions for Rialto { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = rialto_runtime::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::from_raw( - unsigned.call.clone(), - ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(unsigned.era.frame_era()), - frame_system::CheckNonce::::from(unsigned.nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(unsigned.tip), - ), - ( - (), - param.spec_version, - param.transaction_version, - param.genesis_hash, - unsigned.era.signed_payload(param.genesis_hash), - (), - (), - (), - ), - ); - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(rialto_runtime::UncheckedExtrinsic::new_signed( - call.into_decoded()?, - signer.into_account().into(), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == rialto_runtime::Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some( - UnsignedTransaction::new( - tx.function.into(), - Compact::>::decode(&mut &extra.5.encode()[..]).ok()?.into(), - ) - .tip(Compact::>::decode(&mut &extra.7.encode()[..]).ok()?.into()), - ) - } -} - -/// Rialto signing params. -pub type SigningParams = sp_core::sr25519::Pair; - -/// Rialto header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: rialto_runtime::RuntimeCall::System(rialto_runtime::SystemCall::remark { - remark: b"Hello world!".to_vec(), - }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = Rialto::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = Rialto::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/finality/README.md b/relays/finality/README.md index 444056e756303..0a8d6a4c8b128 100644 --- a/relays/finality/README.md +++ b/relays/finality/README.md @@ -38,21 +38,21 @@ with mandatory headers are fee-free, the cost of running such relay is zero (in ## Finality Relay Metrics Finality relay provides several metrics. Metrics names depend on names of source and target chains. The list below -shows metrics names for Rialto (source chain) to Millau (target chain) finality relay. For other chains, simply -change chain names. So the metrics are: +shows metrics names for Rococo (source chain) to BridgeHubWestend (target chain) finality relay. For other +chains, simply change chain names. So the metrics are: -- `Rialto_to_Millau_Sync_best_source_block_number` - returns best finalized source chain (Rialto) block number, known +- `Rococo_to_BridgeHubWestend_Sync_best_source_block_number` - returns best finalized source chain (Rococo) block number, known to the relay. If relay is running in [on-demand mode](../bin-substrate/src/cli/relay_headers_and_messages/), the number may not match (it may be far behind) the actual best finalized number; -- `Rialto_to_Millau_Sync_best_source_at_target_block_number` - returns best finalized source chain (Rialto) block +- `Rococo_to_BridgeHubWestend_Sync_best_source_at_target_block_number` - returns best finalized source chain (Rococo) block number that is known to the bridge GRANDPA pallet at the target chain. -- `Rialto_to_Millau_Sync_is_source_and_source_at_target_using_different_forks` - if this metrics is set to `1`, then +- `Rococo_to_BridgeHubWestend_Sync_is_source_and_source_at_target_using_different_forks` - if this metrics is set to `1`, then the best source chain header, known to the target chain doesn't match the same-number-header at the source chain. It means that the GRANDPA validators set has crafted the duplicate justification and it has been submitted to the target chain. Normally (if majority of validators are honest and if you're running finality relay without large breaks) this shall not happen and the metric will have `0` value. -If relay operates properly, you should see that the `Rialto_to_Millau_Sync_best_source_at_target_block_number` -tries to reach the `Rialto_to_Millau_Sync_best_source_block_number`. And the latter one always increases. +If relay operates properly, you should see that the `Rococo_to_BridgeHubWestend_Sync_best_source_at_target_block_number` +tries to reach the `Rococo_to_BridgeHubWestend_Sync_best_source_block_number`. And the latter one always increases. diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 6fe3c02cbca82..8a490a9d2756d 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -50,12 +50,9 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", bra sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] -bp-rialto = { path = "../../primitives/chain-rialto" } -bp-rialto-parachain = { path = "../../primitives/chain-rialto-parachain" } bp-rococo = { path = "../../primitives/chain-rococo" } bp-wococo = { path = "../../primitives/chain-wococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -relay-rialto-client = { path = "../client-rialto" } relay-rococo-client = { path = "../client-rococo" } -relay-wococo-client = { path = "../client-wococo" } -rialto-runtime = { path = "../../bin/rialto/runtime" } +relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } +relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 50a89e90e2dcd..6e62038665133 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -45,21 +45,8 @@ pub struct TransactionParams { /// Tagged relay account, which balance may be exposed as metrics by the relay. #[derive(Clone, Debug)] pub enum TaggedAccount { - /// Account, used to sign headers relay transactions from given bridged chain. - Headers { - /// Account id. - id: AccountId, - /// Name of the bridged chain, which headers are relayed. - bridged_chain: String, - }, - /// Account, used to sign parachains relay transactions from given bridged relay chain. - Parachains { - /// Account id. - id: AccountId, - /// Name of the bridged relay chain with parachain heads. - bridged_chain: String, - }, - /// Account, used to sign message relay transactions from given bridged chain. + /// Account, used to sign message (also headers and parachains) relay transactions from given + /// bridged chain. Messages { /// Account id. id: AccountId, @@ -72,8 +59,6 @@ impl TaggedAccount { /// Returns reference to the account id. pub fn id(&self) -> &AccountId { match *self { - TaggedAccount::Headers { ref id, .. } => id, - TaggedAccount::Parachains { ref id, .. } => id, TaggedAccount::Messages { ref id, .. } => id, } } @@ -81,10 +66,6 @@ impl TaggedAccount { /// Returns stringified account tag. pub fn tag(&self) -> String { match *self { - TaggedAccount::Headers { ref bridged_chain, .. } => format!("{bridged_chain}Headers"), - TaggedAccount::Parachains { ref bridged_chain, .. } => { - format!("{bridged_chain}Parachains") - }, TaggedAccount::Messages { ref bridged_chain, .. } => { format!("{bridged_chain}Messages") }, diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 413f3d2c51ef5..41f04c8f986ee 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -187,8 +187,6 @@ where { // 2/3 is reserved for proofs and tx overhead let max_messages_size_in_single_batch = P::TargetChain::max_extrinsic_size() / 3; - // we don't know exact weights of the Polkadot runtime. So to guess weights we'll be using - // weights from Rialto and then simply dividing it by x2. let limits = match params.limits { Some(limits) => limits, None => diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 4c49d76bdf357..ed7a2d5924fb7 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -555,9 +555,8 @@ fn split_msgs_to_refine( mod tests { use super::*; use bp_runtime::Chain as ChainBase; - use relay_rialto_client::Rialto; - use relay_rococo_client::Rococo; - use relay_wococo_client::Wococo; + use relay_bridge_hub_rococo_client::BridgeHubRococo; + use relay_bridge_hub_wococo_client::BridgeHubWococo; fn message_details_from_rpc( nonces: RangeInclusive, @@ -574,16 +573,20 @@ mod tests { #[test] fn validate_out_msgs_details_succeeds_if_no_messages_are_missing() { - assert!( - validate_out_msgs_details::(&message_details_from_rpc(1..=3), 1..=3,).is_ok() - ); + assert!(validate_out_msgs_details::( + &message_details_from_rpc(1..=3), + 1..=3, + ) + .is_ok()); } #[test] fn validate_out_msgs_details_succeeds_if_head_messages_are_missing() { - assert!( - validate_out_msgs_details::(&message_details_from_rpc(2..=3), 1..=3,).is_ok() + assert!(validate_out_msgs_details::( + &message_details_from_rpc(2..=3), + 1..=3, ) + .is_ok()) } #[test] @@ -591,7 +594,7 @@ mod tests { let mut message_details_from_rpc = message_details_from_rpc(1..=3); message_details_from_rpc.remove(1); assert!(matches!( - validate_out_msgs_details::(&message_details_from_rpc, 1..=3,), + validate_out_msgs_details::(&message_details_from_rpc, 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -599,7 +602,7 @@ mod tests { #[test] fn validate_out_msgs_details_map_fails_if_tail_messages_are_missing() { assert!(matches!( - validate_out_msgs_details::(&message_details_from_rpc(1..=2), 1..=3,), + validate_out_msgs_details::(&message_details_from_rpc(1..=2), 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -607,7 +610,7 @@ mod tests { #[test] fn validate_out_msgs_details_fails_if_all_messages_are_missing() { assert!(matches!( - validate_out_msgs_details::(&[], 1..=3), + validate_out_msgs_details::(&[], 1..=3), Err(SubstrateError::Custom(_)) )); } @@ -615,7 +618,7 @@ mod tests { #[test] fn validate_out_msgs_details_fails_if_more_messages_than_nonces() { assert!(matches!( - validate_out_msgs_details::(&message_details_from_rpc(1..=5), 2..=5,), + validate_out_msgs_details::(&message_details_from_rpc(1..=5), 2..=5,), Err(SubstrateError::Custom(_)) )); } @@ -641,8 +644,10 @@ mod tests { msgs_to_refine.push((payload, out_msg_details)); } - let maybe_batches = - split_msgs_to_refine::(LaneId([0, 0, 0, 0]), msgs_to_refine); + let maybe_batches = split_msgs_to_refine::( + Default::default(), + msgs_to_refine, + ); match expected_batches { Ok(expected_batches) => { let batches = maybe_batches.unwrap(); @@ -664,7 +669,7 @@ mod tests { #[test] fn test_split_msgs_to_refine() { - let max_extrinsic_size = Rococo::max_extrinsic_size() as usize; + let max_extrinsic_size = BridgeHubRococo::max_extrinsic_size() as usize; // Check that an error is returned when one of the messages is too big. check_split_msgs_to_refine(vec![max_extrinsic_size], Err(())); diff --git a/relays/parachains/README.md b/relays/parachains/README.md index fc5ad03fb340d..bacd28594d807 100644 --- a/relays/parachains/README.md +++ b/relays/parachains/README.md @@ -35,15 +35,15 @@ transaction. Every parachain in Polkadot is identified by the 32-bit number. All metrics, exposed by the parachains finality relay have the `parachain` label, which is set to the parachain id. And the metrics are prefixed with the prefix, that depends on the name of the source relay and target chains. The list below shows metrics names for -Rialto (source relay chain) to Millau (target chain) parachains finality relay. For other chains, simply +Rococo (source relay chain) to BridgeHubWestend (target chain) parachains finality relay. For other chains, simply change chain names. So the metrics are: -- `Rialto_to_Millau_Parachains_best_parachain_block_number_at_source` - returns best known parachain block - number, registered in the `paras` pallet at the source relay chain (Rialto in our example); +- `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_source` - returns best known parachain block + number, registered in the `paras` pallet at the source relay chain (Rococo in our example); -- `Rialto_to_Millau_Parachains_best_parachain_block_number_at_target` - returns best known parachain block - number, registered in the bridge parachains pallet at the target chain (Millau in our example). +- `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_target` - returns best known parachain block + number, registered in the bridge parachains pallet at the target chain (BridgeHubWestend in our example). -If relay operates properly, you should see that the `Rialto_to_Millau_Parachains_best_parachain_block_number_at_target` -tries to reach the `Rialto_to_Millau_Parachains_best_parachain_block_number_at_source`. And the latter one +If relay operates properly, you should see that the `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_target` +tries to reach the `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_source`. And the latter one always increases. From c689afd7fd20610645d9453a14954613b916389f Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 14 Nov 2023 11:32:38 +0100 Subject: [PATCH 1149/1210] Remove Woococo related stuff (#2692) * Remove Woococo related stuff * More removes * Compilation * Added equvocation for Ro/We * We need chain-westend primitives --- primitives/chain-asset-hub-rococo/src/lib.rs | 3 - primitives/chain-asset-hub-wococo/Cargo.toml | 26 --- primitives/chain-asset-hub-wococo/src/lib.rs | 48 ----- primitives/chain-bridge-hub-kusama/Cargo.toml | 2 +- .../chain-bridge-hub-polkadot/Cargo.toml | 2 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 3 - primitives/chain-bridge-hub-wococo/Cargo.toml | 34 ---- primitives/chain-bridge-hub-wococo/src/lib.rs | 90 ---------- primitives/chain-wococo/Cargo.toml | 34 ---- primitives/chain-wococo/src/lib.rs | 68 ------- primitives/runtime/src/extensions.rs | 2 +- primitives/runtime/src/lib.rs | 6 - relays/bin-substrate/Cargo.toml | 2 - relays/bin-substrate/src/bridges/mod.rs | 1 - ...ub_rococo_messages_to_bridge_hub_wococo.rs | 64 ------- ...ub_wococo_messages_to_bridge_hub_rococo.rs | 64 ------- .../src/bridges/rococo_wococo/mod.rs | 24 --- .../rococo_headers_to_bridge_hub_wococo.rs | 80 --------- .../rococo_parachains_to_bridge_hub_wococo.rs | 75 -------- .../wococo_headers_to_bridge_hub_rococo.rs | 80 --------- .../wococo_parachains_to_bridge_hub_rococo.rs | 75 -------- relays/bin-substrate/src/chains/mod.rs | 1 - relays/bin-substrate/src/chains/wococo.rs | 31 ---- relays/bin-substrate/src/cli/bridge.rs | 2 - .../src/cli/detect_equivocations.rs | 22 +-- relays/bin-substrate/src/cli/init_bridge.rs | 34 ---- relays/bin-substrate/src/cli/relay_headers.rs | 12 -- .../src/cli/relay_headers_and_messages/mod.rs | 69 ++++--- .../bin-substrate/src/cli/relay_messages.rs | 10 -- .../bin-substrate/src/cli/relay_parachains.rs | 12 -- relays/client-bridge-hub-rococo/Cargo.toml | 2 - relays/client-bridge-hub-wococo/Cargo.toml | 34 ---- relays/client-bridge-hub-wococo/src/lib.rs | 169 ------------------ relays/client-wococo/Cargo.toml | 24 --- relays/client-wococo/src/lib.rs | 133 -------------- relays/lib-substrate-relay/Cargo.toml | 5 +- .../src/messages_source.rs | 4 +- 37 files changed, 48 insertions(+), 1299 deletions(-) delete mode 100644 primitives/chain-asset-hub-wococo/Cargo.toml delete mode 100644 primitives/chain-asset-hub-wococo/src/lib.rs delete mode 100644 primitives/chain-bridge-hub-wococo/Cargo.toml delete mode 100644 primitives/chain-bridge-hub-wococo/src/lib.rs delete mode 100644 primitives/chain-wococo/Cargo.toml delete mode 100644 primitives/chain-wococo/src/lib.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/chains/wococo.rs delete mode 100644 relays/client-bridge-hub-wococo/Cargo.toml delete mode 100644 relays/client-bridge-hub-wococo/src/lib.rs delete mode 100644 relays/client-wococo/Cargo.toml delete mode 100644 relays/client-wococo/src/lib.rs diff --git a/primitives/chain-asset-hub-rococo/src/lib.rs b/primitives/chain-asset-hub-rococo/src/lib.rs index 6216b24d75c90..de2e9ae856d1f 100644 --- a/primitives/chain-asset-hub-rococo/src/lib.rs +++ b/primitives/chain-asset-hub-rococo/src/lib.rs @@ -34,9 +34,6 @@ pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; #[allow(clippy::large_enum_variant)] #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub enum Call { - /// `ToWococoXcmRouter` bridge pallet. - #[codec(index = 43)] - ToWococoXcmRouter(XcmBridgeHubRouterCall), /// `ToWestendXcmRouter` bridge pallet. #[codec(index = 45)] ToWestendXcmRouter(XcmBridgeHubRouterCall), diff --git a/primitives/chain-asset-hub-wococo/Cargo.toml b/primitives/chain-asset-hub-wococo/Cargo.toml deleted file mode 100644 index d56205c3a1257..0000000000000 --- a/primitives/chain-asset-hub-wococo/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "bp-asset-hub-wococo" -description = "Primitives of AssetHubWococo parachain runtime." -version = "0.1.0" -authors.workspace = true -edition.workspace = true -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-xcm-bridge-hub-router/std", - "codec/std", - "frame-support/std", - "scale-info/std", -] diff --git a/primitives/chain-asset-hub-wococo/src/lib.rs b/primitives/chain-asset-hub-wococo/src/lib.rs deleted file mode 100644 index c04eb04cce70b..0000000000000 --- a/primitives/chain-asset-hub-wococo/src/lib.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 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 . - -//! Module with configuration which reflects AssetHubWococo runtime setup. - -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; - -/// `AssetHubWococo` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `AssetHubWococo` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `AssetHubWococo` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// `ToRococoXcmRouter` bridge pallet. - #[codec(index = 44)] - ToRococoXcmRouter(XcmBridgeHubRouterCall), -} - -frame_support::parameter_types! { - /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. - pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); -} - -/// Identifier of AssetHubWococo in the Wococo relay chain. -pub const ASSET_HUB_WOCOCO_PARACHAIN_ID: u32 = 1000; diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml index d9fc32524c083..2d6b5ba424e00 100644 --- a/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bp-bridge-hub-kusama" -description = "Primitives of BridgeHubRococo parachain runtime." +description = "Primitives of BridgeHubKusama parachain runtime." version = "0.1.0" authors.workspace = true edition.workspace = true diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml index 5e3516136c823..a4a116f0ce9fa 100644 --- a/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bp-bridge-hub-polkadot" -description = "Primitives of BridgeHubWococo parachain runtime." +description = "Primitives of BridgeHubPolkadot parachain runtime." version = "0.1.0" authors.workspace = true edition.workspace = true diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index e72e711de9270..59d293edf1c24 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -74,9 +74,6 @@ pub const WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME: &str = "BridgeRococoMessa /// chains. pub const WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; -/// Pallet index of `BridgeWococoMessages: pallet_bridge_messages::`. -pub const WITH_BRIDGE_ROCOCO_TO_WOCOCO_MESSAGES_PALLET_INDEX: u8 = 46; - /// Pallet index of `BridgeWestendMessages: pallet_bridge_messages::`. pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 51; diff --git a/primitives/chain-bridge-hub-wococo/Cargo.toml b/primitives/chain-bridge-hub-wococo/Cargo.toml deleted file mode 100644 index 28536dce1f7ca..0000000000000 --- a/primitives/chain-bridge-hub-wococo/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "bp-bridge-hub-wococo" -description = "Primitives of BridgeHubWococo parachain runtime." -version = "0.1.0" -authors.workspace = true -edition.workspace = true -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# Bridge Dependencies - -bp-bridge-hub-cumulus = { path = "../chain-bridge-hub-cumulus", default-features = false } -bp-runtime = { path = "../../primitives/runtime", default-features = false } -bp-messages = { path = "../../primitives/messages", default-features = false } - -# Substrate Based Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-bridge-hub-cumulus/std", - "bp-messages/std", - "bp-runtime/std", - "frame-support/std", - "sp-api/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/primitives/chain-bridge-hub-wococo/src/lib.rs b/primitives/chain-bridge-hub-wococo/src/lib.rs deleted file mode 100644 index c8bd397cec561..0000000000000 --- a/primitives/chain-bridge-hub-wococo/src/lib.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 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 . - -//! Module with configuration which reflects BridgeHubWococo runtime setup -//! (AccountId, Headers, Hashes...) - -#![cfg_attr(not(feature = "std"), no_std)] - -pub use bp_bridge_hub_cumulus::*; -use bp_messages::*; -use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, -}; -use frame_support::dispatch::DispatchClass; -use sp_runtime::RuntimeDebug; - -/// BridgeHubWococo parachain. -#[derive(RuntimeDebug)] -pub struct BridgeHubWococo; - -impl Chain for BridgeHubWococo { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) - } - - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) - } -} - -impl Parachain for BridgeHubWococo { - const PARACHAIN_ID: u32 = BRIDGE_HUB_WOCOCO_PARACHAIN_ID; -} - -/// Identifier of BridgeHubWococo in the Wococo relay chain. -pub const BRIDGE_HUB_WOCOCO_PARACHAIN_ID: u32 = 1014; - -/// Name of the With-BridgeHubWococo messages pallet instance that is deployed at bridged chains. -pub const WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME: &str = "BridgeWococoMessages"; - -/// Name of the With-BridgeHubWococo bridge-relayers pallet instance that is deployed at bridged -/// chains. -pub const WITH_BRIDGE_HUB_WOCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; - -/// Pallet index of `BridgeRococoMessages: pallet_bridge_messages::`. -pub const WITH_BRIDGE_WOCOCO_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45; - -decl_bridge_finality_runtime_apis!(bridge_hub_wococo); -decl_bridge_messages_runtime_apis!(bridge_hub_wococo); - -frame_support::parameter_types! { - /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Wococo - /// BridgeHub. - /// (initially was calculated by test `BridgeHubWococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubWococoBaseXcmFeeInWocs: u128 = 1624803349; - - /// Transaction fee that is paid at the Wococo BridgeHub for delivering single inbound message. - /// (initially was calculated by test `BridgeHubWococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) - pub const BridgeHubWococoBaseDeliveryFeeInWocs: u128 = 6417262881; - - /// Transaction fee that is paid at the Wococo BridgeHub for delivering single outbound message confirmation. - /// (initially was calculated by test `BridgeHubWococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubWococoBaseConfirmationFeeInWocs: u128 = 6159996668; -} diff --git a/primitives/chain-wococo/Cargo.toml b/primitives/chain-wococo/Cargo.toml deleted file mode 100644 index ffe14b3bc914f..0000000000000 --- a/primitives/chain-wococo/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "bp-wococo" -description = "Primitives of Wococo runtime." -version = "0.1.0" -authors.workspace = true -edition.workspace = true -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] - -# Bridge Dependencies - -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } -bp-rococo = { path = "../chain-rococo", default-features = false } - -# Substrate Based Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-header-chain/std", - "bp-polkadot-core/std", - "bp-rococo/std", - "bp-runtime/std", - "frame-support/std", - "sp-api/std", - "sp-std/std", -] diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs deleted file mode 100644 index b1df65630beff..0000000000000 --- a/primitives/chain-wococo/src/lib.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 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 . - -#![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] - -pub use bp_polkadot_core::*; -pub use bp_rococo::{ - SS58Prefix, MAX_AUTHORITIES_COUNT, MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE, PARAS_PALLET_NAME, -}; - -use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; -use frame_support::weights::Weight; - -/// Wococo Chain -pub struct Wococo; - -impl Chain for Wococo { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hasher; - type Header = ::Header; - - type AccountId = ::AccountId; - type Balance = ::Balance; - type Nonce = ::Nonce; - type Signature = ::Signature; - - fn max_extrinsic_size() -> u32 { - PolkadotLike::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - PolkadotLike::max_extrinsic_weight() - } -} - -impl ChainWithGrandpa for Wococo { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_WOCOCO_GRANDPA_PALLET_NAME; - const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; -} - -// The SignedExtension used by Wococo. -pub use bp_rococo::CommonSignedExtension as SignedExtension; - -/// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. -pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; - -decl_bridge_finality_runtime_apis!(wococo, grandpa); diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index 44eeaad93c916..8a618721b23a6 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -88,7 +88,7 @@ pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<( /// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), /// ())` is the same. So runtime can contains any kind of tuple: /// `(BridgeRefundBridgeHubRococoMessages)` -/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWococoMessages)` +/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)` /// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 0b6f90fd934ff..0513cfa2a6c75 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -79,15 +79,9 @@ pub const ASSET_HUB_WESTEND_CHAIN_ID: ChainId = *b"ahwe"; /// Rococo chain id. pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; -/// Wococo chain id. -pub const WOCOCO_CHAIN_ID: ChainId = *b"woco"; - /// BridgeHubRococo chain id. pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro"; -/// BridgeHubWococo chain id. -pub const BRIDGE_HUB_WOCOCO_CHAIN_ID: ChainId = *b"bhwo"; - /// BridgeHubWestend chain id. pub const BRIDGE_HUB_WESTEND_CHAIN_ID: ChainId = *b"bhwd"; diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index b1ebcbbdcee9b..df2fc2ad169e1 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -35,7 +35,6 @@ relay-bridge-hub-kusama-client = { path = "../client-bridge-hub-kusama" } relay-bridge-hub-polkadot-client = { path = "../client-bridge-hub-polkadot" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } relay-bridge-hub-westend-client = { path = "../client-bridge-hub-westend" } -relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } relay-kusama-client = { path = "../client-kusama" } relay-polkadot-client = { path = "../client-polkadot" } relay-polkadot-bulletin-client = { path = "../client-polkadot-bulletin" } @@ -43,7 +42,6 @@ relay-rococo-client = { path = "../client-rococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } relay-westend-client = { path = "../client-westend" } -relay-wococo-client = { path = "../client-wococo" } substrate-relay-helper = { path = "../lib-substrate-relay" } # Substrate Dependencies diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs index 5a40b80cb9321..8dad329cf73be 100644 --- a/relays/bin-substrate/src/bridges/mod.rs +++ b/relays/bin-substrate/src/bridges/mod.rs @@ -19,4 +19,3 @@ pub mod kusama_polkadot; pub mod polkadot_bulletin; pub mod rococo_westend; -pub mod rococo_wococo; diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs deleted file mode 100644 index 18d9c31089c31..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_rococo_messages_to_bridge_hub_wococo.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubRococo-to-BridgeHubWococo messages sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; -use relay_bridge_hub_rococo_client::BridgeHubRococo; -use relay_bridge_hub_wococo_client::BridgeHubWococo; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; - -pub struct BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { - type Source = BridgeHubRococo; - type Target = BridgeHubWococo; -} - -impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoMessagesCliBridge { - type MessagesLane = BridgeHubRococoMessagesToBridgeHubWococoMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubRococoMessagesToBridgeHubWococoMessageLane, - BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoMessages, - relay_bridge_hub_wococo_client::BridgeMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubRococoMessagesToBridgeHubWococoMessageLane, - BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoMessages, - relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_delivery_proof -); - -/// Description of BridgeHubRococo -> BridgeHubWococo messages bridge. -#[derive(Clone, Debug)] -pub struct BridgeHubRococoMessagesToBridgeHubWococoMessageLane; - -impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWococoMessageLane { - type SourceChain = BridgeHubRococo; - type TargetChain = BridgeHubWococo; - - type ReceiveMessagesProofCallBuilder = - BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubRococoMessagesToBridgeHubWococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs deleted file mode 100644 index d327926823bf3..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/bridge_hub_wococo_messages_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubWococo-to-BridgeHubRococo messages sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; -use relay_bridge_hub_rococo_client::BridgeHubRococo; -use relay_bridge_hub_wococo_client::BridgeHubWococo; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; - -pub struct BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { - type Source = BridgeHubWococo; - type Target = BridgeHubRococo; -} - -impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoMessagesCliBridge { - type MessagesLane = BridgeHubWococoMessagesToBridgeHubRococoMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubWococoMessagesToBridgeHubRococoMessageLane, - BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoMessages, - relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubWococoMessagesToBridgeHubRococoMessageLane, - BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoMessages, - relay_bridge_hub_wococo_client::BridgeMessagesCall::receive_messages_delivery_proof -); - -/// Description of BridgeHubWococo -> BridgeHubRococo messages bridge. -#[derive(Clone, Debug)] -pub struct BridgeHubWococoMessagesToBridgeHubRococoMessageLane; - -impl SubstrateMessageLane for BridgeHubWococoMessagesToBridgeHubRococoMessageLane { - type SourceChain = BridgeHubWococo; - type TargetChain = BridgeHubRococo; - - type ReceiveMessagesProofCallBuilder = - BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubWococoMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs b/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs deleted file mode 100644 index 64330a92252cd..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Rococo Bridge Hub and Wococo Bridge Hub. - -pub mod bridge_hub_rococo_messages_to_bridge_hub_wococo; -pub mod bridge_hub_wococo_messages_to_bridge_hub_rococo; -pub mod rococo_headers_to_bridge_hub_wococo; -pub mod rococo_parachains_to_bridge_hub_wococo; -pub mod wococo_headers_to_bridge_hub_rococo; -pub mod wococo_parachains_to_bridge_hub_rococo; diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs deleted file mode 100644 index b9b9a89ba0f52..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_headers_to_bridge_hub_wococo.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Rococo-to-Wococo bridge hubs headers sync entrypoint. - -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Rococo -> Wococo finalized headers bridge. -#[derive(Clone, Debug)] -pub struct RococoFinalityToBridgeHubWococo; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - RococoFinalityToBridgeHubWococo, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoGrandpa, - relay_bridge_hub_wococo_client::BridgeGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - RococoFinalityToBridgeHubWococo, - ReportEquivocationCallBuilder, - relay_rococo_client::RuntimeCall::Grandpa, - relay_rococo_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWococo { - type SourceChain = relay_rococo_client::Rococo; - type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWococo { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for RococoFinalityToBridgeHubWococo { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Rococo` to BridgeHub `Wococo` bridge definition. -pub struct RococoToBridgeHubWococoCliBridge {} - -impl CliBridgeBase for RococoToBridgeHubWococoCliBridge { - type Source = relay_rococo_client::Rococo; - type Target = relay_bridge_hub_wococo_client::BridgeHubWococo; -} - -impl RelayToRelayHeadersCliBridge for RococoToBridgeHubWococoCliBridge { - type Finality = RococoFinalityToBridgeHubWococo; -} - -impl RelayToRelayEquivocationDetectionCliBridge for RococoToBridgeHubWococoCliBridge { - type Equivocation = RococoFinalityToBridgeHubWococo; -} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs deleted file mode 100644 index b7296e0a38fb4..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/rococo_parachains_to_bridge_hub_wococo.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Wococo-to-Rococo parachains sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, -}; - -/// BridgeHub-to-BridgeHub parachain sync description. -#[derive(Clone, Debug)] -pub struct BridgeHubRococoToBridgeHubWococo; - -impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWococo { - type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo; - type SourceRelayChain = relay_rococo_client::Rococo; - type TargetChain = relay_bridge_hub_wococo_client::BridgeHubWococo; - - type SubmitParachainHeadsCallBuilder = BridgeHubRococoToBridgeHubWococoCallBuilder; -} - -pub struct BridgeHubRococoToBridgeHubWococoCallBuilder; -impl SubmitParachainHeadsCallBuilder - for BridgeHubRococoToBridgeHubWococoCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoParachains( - relay_bridge_hub_wococo_client::BridgeParachainCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. -pub struct BridgeHubRococoToBridgeHubWococoCliBridge {} - -impl ParachainToRelayHeadersCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge { - type SourceRelay = relay_rococo_client::Rococo; - type ParachainFinality = BridgeHubRococoToBridgeHubWococo; - type RelayFinality = - crate::bridges::rococo_wococo::rococo_headers_to_bridge_hub_wococo::RococoFinalityToBridgeHubWococo; -} - -impl CliBridgeBase for BridgeHubRococoToBridgeHubWococoCliBridge { - type Source = relay_bridge_hub_rococo_client::BridgeHubRococo; - type Target = relay_bridge_hub_wococo_client::BridgeHubWococo; -} - -impl MessagesCliBridge for BridgeHubRococoToBridgeHubWococoCliBridge { - type MessagesLane = - crate::bridges::rococo_wococo::bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoMessagesToBridgeHubWococoMessageLane; -} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs deleted file mode 100644 index c000a2764e26e..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_headers_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Wococo-to-Rococo bridge hubs headers sync entrypoint. - -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Wococo -> Rococo finalized headers bridge. -#[derive(Clone, Debug)] -pub struct WococoFinalityToBridgeHubRococo; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - WococoFinalityToBridgeHubRococo, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoGrandpa, - relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - WococoFinalityToBridgeHubRococo, - ReportEquivocationCallBuilder, - relay_wococo_client::RuntimeCall::Grandpa, - relay_wococo_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for WococoFinalityToBridgeHubRococo { - type SourceChain = relay_wococo_client::Wococo; - type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for WococoFinalityToBridgeHubRococo { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for WococoFinalityToBridgeHubRococo { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Wococo` to BridgeHub `Rococo` bridge definition. -pub struct WococoToBridgeHubRococoCliBridge {} - -impl CliBridgeBase for WococoToBridgeHubRococoCliBridge { - type Source = relay_wococo_client::Wococo; - type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; -} - -impl RelayToRelayHeadersCliBridge for WococoToBridgeHubRococoCliBridge { - type Finality = WococoFinalityToBridgeHubRococo; -} - -impl RelayToRelayEquivocationDetectionCliBridge for WococoToBridgeHubRococoCliBridge { - type Equivocation = WococoFinalityToBridgeHubRococo; -} diff --git a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs deleted file mode 100644 index 165f4af11c8fe..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_wococo/wococo_parachains_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Rococo-to-Wococo parachains sync entrypoint. - -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, -}; - -/// BridgeHub-to-BridgeHub parachain sync description. -#[derive(Clone, Debug)] -pub struct BridgeHubWococoToBridgeHubRococo; - -impl SubstrateParachainsPipeline for BridgeHubWococoToBridgeHubRococo { - type SourceParachain = relay_bridge_hub_wococo_client::BridgeHubWococo; - type SourceRelayChain = relay_wococo_client::Wococo; - type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; - - type SubmitParachainHeadsCallBuilder = BridgeHubWococoToBridgeHubRococoCallBuilder; -} - -pub struct BridgeHubWococoToBridgeHubRococoCallBuilder; -impl SubmitParachainHeadsCallBuilder - for BridgeHubWococoToBridgeHubRococoCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoParachains( - relay_bridge_hub_rococo_client::BridgeParachainCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. -pub struct BridgeHubWococoToBridgeHubRococoCliBridge {} - -impl ParachainToRelayHeadersCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge { - type SourceRelay = relay_wococo_client::Wococo; - type ParachainFinality = BridgeHubWococoToBridgeHubRococo; - type RelayFinality = - crate::bridges::rococo_wococo::wococo_headers_to_bridge_hub_rococo::WococoFinalityToBridgeHubRococo; -} - -impl CliBridgeBase for BridgeHubWococoToBridgeHubRococoCliBridge { - type Source = relay_bridge_hub_wococo_client::BridgeHubWococo; - type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; -} - -impl MessagesCliBridge for BridgeHubWococoToBridgeHubRococoCliBridge { - type MessagesLane = - crate::bridges::rococo_wococo::bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoMessagesToBridgeHubRococoMessageLane; -} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs index 442236997c8ba..ab15a9e679cd5 100644 --- a/relays/bin-substrate/src/chains/mod.rs +++ b/relays/bin-substrate/src/chains/mod.rs @@ -21,4 +21,3 @@ mod polkadot; mod polkadot_bulletin; mod rococo; mod westend; -mod wococo; diff --git a/relays/bin-substrate/src/chains/wococo.rs b/relays/bin-substrate/src/chains/wococo.rs deleted file mode 100644 index c9e3943d80865..0000000000000 --- a/relays/bin-substrate/src/chains/wococo.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2022 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 . - -//! Wococo + Wococo parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_wococo_client::BridgeHubWococo; -use relay_substrate_client::SimpleRuntimeVersion; -use relay_wococo_client::Wococo; - -impl CliChain for Wococo { - const RUNTIME_VERSION: Option = None; -} - -impl CliChain for BridgeHubWococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9420, transaction_version: 3 }); -} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index cc6dc8e43574e..2903a290c5b62 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -29,8 +29,6 @@ use substrate_relay_helper::{ #[strum(serialize_all = "kebab_case")] /// Supported full bridges (headers + messages). pub enum FullBridge { - BridgeHubRococoToBridgeHubWococo, - BridgeHubWococoToBridgeHubRococo, BridgeHubRococoToBridgeHubWestend, BridgeHubWestendToBridgeHubRococo, BridgeHubKusamaToBridgeHubPolkadot, diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs index 704839db0e66f..970089453bd5a 100644 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -20,9 +20,9 @@ use crate::{ kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, }, - rococo_wococo::{ - rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, - wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, + rococo_westend::{ + rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, + westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, }, }, cli::{bridge::*, chain_schema::*, PrometheusParams}, @@ -53,10 +53,10 @@ pub struct DetectEquivocations { #[strum(serialize_all = "kebab_case")] /// Equivocations detection bridge. pub enum DetectEquivocationsBridge { - RococoToBridgeHubWococo, - WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, + RococoToBridgeHubWestend, + WestendToBridgeHubRococo, } #[async_trait] @@ -82,23 +82,23 @@ where } } -impl EquivocationsDetector for RococoToBridgeHubWococoCliBridge {} -impl EquivocationsDetector for WococoToBridgeHubRococoCliBridge {} impl EquivocationsDetector for KusamaToBridgeHubPolkadotCliBridge {} impl EquivocationsDetector for PolkadotToBridgeHubKusamaCliBridge {} +impl EquivocationsDetector for RococoToBridgeHubWestendCliBridge {} +impl EquivocationsDetector for WestendToBridgeHubRococoCliBridge {} impl DetectEquivocations { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - DetectEquivocationsBridge::RococoToBridgeHubWococo => - RococoToBridgeHubWococoCliBridge::start(self), - DetectEquivocationsBridge::WococoToBridgeHubRococo => - WococoToBridgeHubRococoCliBridge::start(self), DetectEquivocationsBridge::KusamaToBridgeHubPolkadot => KusamaToBridgeHubPolkadotCliBridge::start(self), DetectEquivocationsBridge::PolkadotToBridgeHubKusama => PolkadotToBridgeHubKusamaCliBridge::start(self), + DetectEquivocationsBridge::RococoToBridgeHubWestend => + RococoToBridgeHubWestendCliBridge::start(self), + DetectEquivocationsBridge::WestendToBridgeHubRococo => + WestendToBridgeHubRococoCliBridge::start(self), } .await } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 21d95b4bfa0ea..30875e70cbb35 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -31,10 +31,6 @@ use crate::{ rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, }, - rococo_wococo::{ - rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, - wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, - }, }, cli::{bridge::CliBridgeBase, chain_schema::*}, }; @@ -66,8 +62,6 @@ pub struct InitBridge { #[strum(serialize_all = "kebab_case")] /// Bridge to initialize. pub enum InitBridgeName { - RococoToBridgeHubWococo, - WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, @@ -116,30 +110,6 @@ where } } -impl BridgeInitializer for RococoToBridgeHubWococoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_wococo_client::RuntimeCall::BridgeRococoGrandpa( - relay_bridge_hub_wococo_client::BridgeGrandpaCall::initialize { init_data }, - ) - } -} - -impl BridgeInitializer for WococoToBridgeHubRococoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWococoGrandpa( - relay_bridge_hub_rococo_client::BridgeGrandpaCall::initialize { init_data }, - ) - } -} - impl BridgeInitializer for RococoToBridgeHubWestendCliBridge { type Engine = GrandpaFinalityEngine; @@ -229,10 +199,6 @@ impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - InitBridgeName::RococoToBridgeHubWococo => - RococoToBridgeHubWococoCliBridge::init_bridge(self), - InitBridgeName::WococoToBridgeHubRococo => - WococoToBridgeHubRococoCliBridge::init_bridge(self), InitBridgeName::KusamaToBridgeHubPolkadot => KusamaToBridgeHubPolkadotCliBridge::init_bridge(self), InitBridgeName::PolkadotToBridgeHubKusama => diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 95d93387a0728..032fe64ef9070 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -27,10 +27,6 @@ use crate::bridges::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, - rococo_wococo::{ - rococo_headers_to_bridge_hub_wococo::RococoToBridgeHubWococoCliBridge, - wococo_headers_to_bridge_hub_rococo::WococoToBridgeHubRococoCliBridge, - }, }; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; @@ -61,8 +57,6 @@ pub struct RelayHeaders { #[strum(serialize_all = "kebab_case")] /// Headers relay bridge. pub enum RelayHeadersBridge { - RococoToBridgeHubWococo, - WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, @@ -100,8 +94,6 @@ trait HeadersRelayer: RelayToRelayHeadersCliBridge { } } -impl HeadersRelayer for RococoToBridgeHubWococoCliBridge {} -impl HeadersRelayer for WococoToBridgeHubRococoCliBridge {} impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} impl HeadersRelayer for PolkadotToPolkadotBulletinCliBridge {} @@ -111,10 +103,6 @@ impl RelayHeaders { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - RelayHeadersBridge::RococoToBridgeHubWococo => - RococoToBridgeHubWococoCliBridge::relay_headers(self), - RelayHeadersBridge::WococoToBridgeHubRococo => - WococoToBridgeHubRococoCliBridge::relay_headers(self), RelayHeadersBridge::KusamaToBridgeHubPolkadot => KusamaToBridgeHubPolkadotCliBridge::relay_headers(self), RelayHeadersBridge::PolkadotToBridgeHubKusama => diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 7075e742e02d8..87d1c38fab10d 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -51,10 +51,6 @@ use crate::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, }, - rococo_wococo::{ - rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, - wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, - }, }, cli::{ bridge::{ @@ -196,8 +192,6 @@ where // All supported chains. declare_chain_cli_schema!(Rococo, rococo); declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); -declare_chain_cli_schema!(Wococo, wococo); -declare_chain_cli_schema!(BridgeHubWococo, bridge_hub_wococo); declare_chain_cli_schema!(Westend, westend); declare_chain_cli_schema!(BridgeHubWestend, bridge_hub_westend); declare_chain_cli_schema!(Kusama, kusama); @@ -205,8 +199,37 @@ declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); declare_chain_cli_schema!(Polkadot, polkadot); declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); declare_chain_cli_schema!(PolkadotBulletin, polkadot_bulletin); +// Means to override signers of different layer transactions. +declare_chain_cli_schema!(RococoHeadersToBridgeHubWestend, rococo_headers_to_bridge_hub_westend); +declare_chain_cli_schema!( + RococoParachainsToBridgeHubWestend, + rococo_parachains_to_bridge_hub_westend +); +declare_chain_cli_schema!(WestendHeadersToBridgeHubRococo, westend_headers_to_bridge_hub_rococo); +declare_chain_cli_schema!( + WestendParachainsToBridgeHubRococo, + westend_parachains_to_bridge_hub_rococo +); +declare_chain_cli_schema!(KusamaHeadersToBridgeHubPolkadot, kusama_headers_to_bridge_hub_polkadot); +declare_chain_cli_schema!( + KusamaParachainsToBridgeHubPolkadot, + kusama_parachains_to_bridge_hub_polkadot +); +declare_chain_cli_schema!(PolkadotHeadersToBridgeHubKusama, polkadot_headers_to_bridge_hub_kusama); +declare_chain_cli_schema!( + PolkadotParachainsToBridgeHubKusama, + polkadot_parachains_to_bridge_hub_kusama +); +declare_chain_cli_schema!( + PolkadotBulletinHeadersToBridgeHubPolkadot, + polkadot_bulletin_headers_to_bridge_hub_polkadot +); +declare_chain_cli_schema!(PolkadotHeadersToPolkadotBulletin, polkadot_headers_to_polkadot_bulletin); +declare_chain_cli_schema!( + PolkadotParachainsToPolkadotBulletin, + polkadot_parachains_to_polkadot_bulletin +); // All supported bridges. -declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWococo, Wococo); declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWestend, Westend); declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); @@ -376,32 +399,6 @@ where } } -/// BridgeHubRococo <> BridgeHubWococo complex relay. -pub struct BridgeHubRococoBridgeHubWococoFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for BridgeHubRococoBridgeHubWococoFull2WayBridge { - type Base = ParachainToParachainBridge; - type Left = relay_bridge_hub_rococo_client::BridgeHubRococo; - type Right = relay_bridge_hub_wococo_client::BridgeHubWococo; - type L2R = BridgeHubRococoToBridgeHubWococoCliBridge; - type R2L = BridgeHubWococoToBridgeHubRococoCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - /// BridgeHubRococo <> BridgeHubWestend complex relay. pub struct BridgeHubRococoBridgeHubWestendFull2WayBridge { base: ::Base, @@ -483,8 +480,6 @@ impl Full2WayBridge for PolkadotBulletinBridgeHubPolkadotFull2WayBridge { /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { - /// BridgeHubRococo <> BridgeHubWococo relay. - BridgeHubRococoBridgeHubWococo(BridgeHubRococoBridgeHubWococoHeadersAndMessages), /// BridgeHubKusama <> BridgeHubPolkadot relay. BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), /// `PolkadotBulletin` <> `BridgeHubPolkadot` relay. @@ -497,10 +492,6 @@ impl RelayHeadersAndMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self { - RelayHeadersAndMessages::BridgeHubRococoBridgeHubWococo(params) => - BridgeHubRococoBridgeHubWococoFull2WayBridge::new(params.into_bridge().await?)? - .run() - .await, RelayHeadersAndMessages::BridgeHubRococoBridgeHubWestend(params) => BridgeHubRococoBridgeHubWestendFull2WayBridge::new(params.into_bridge().await?)? .run() diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 7d01f8bcd7df4..477e9feff050a 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -32,10 +32,6 @@ use crate::bridges::{ bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendMessagesCliBridge, bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, }, - rococo_wococo::{ - bridge_hub_rococo_messages_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoMessagesCliBridge, - bridge_hub_wococo_messages_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoMessagesCliBridge, - }, }; use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions}; use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; @@ -101,8 +97,6 @@ where } } -impl MessagesRelayer for BridgeHubRococoToBridgeHubWococoMessagesCliBridge {} -impl MessagesRelayer for BridgeHubWococoToBridgeHubRococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} impl MessagesRelayer for BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} @@ -114,10 +108,6 @@ impl RelayMessages { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - FullBridge::BridgeHubRococoToBridgeHubWococo => - BridgeHubRococoToBridgeHubWococoMessagesCliBridge::relay_messages(self), - FullBridge::BridgeHubWococoToBridgeHubRococo => - BridgeHubWococoToBridgeHubRococoMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubRococoToBridgeHubWestend => BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubWestendToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 668632320efa8..3038d1dfdb91d 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -24,10 +24,6 @@ use crate::bridges::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, }, - rococo_wococo::{ - rococo_parachains_to_bridge_hub_wococo::BridgeHubRococoToBridgeHubWococoCliBridge, - wococo_parachains_to_bridge_hub_rococo::BridgeHubWococoToBridgeHubRococoCliBridge, - }, }; use async_std::sync::Mutex; use async_trait::async_trait; @@ -68,8 +64,6 @@ pub struct RelayParachains { #[derive(Debug, EnumString, EnumVariantNames)] #[strum(serialize_all = "kebab_case")] pub enum RelayParachainsBridge { - RococoToBridgeHubWococo, - WococoToBridgeHubRococo, KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, @@ -118,8 +112,6 @@ where } } -impl ParachainsRelayer for BridgeHubRococoToBridgeHubWococoCliBridge {} -impl ParachainsRelayer for BridgeHubWococoToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubRococoToBridgeHubWestendCliBridge {} impl ParachainsRelayer for BridgeHubWestendToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} @@ -130,10 +122,6 @@ impl RelayParachains { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { - RelayParachainsBridge::RococoToBridgeHubWococo => - BridgeHubRococoToBridgeHubWococoCliBridge::relay_parachains(self), - RelayParachainsBridge::WococoToBridgeHubRococo => - BridgeHubWococoToBridgeHubRococoCliBridge::relay_parachains(self), RelayParachainsBridge::RococoToBridgeHubWestend => BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self), RelayParachainsBridge::WestendToBridgeHubRococo => diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index f6fe83e1c556c..894965ababc77 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -13,13 +13,11 @@ subxt = { version = "0.32.1", default-features = false, features = [] } # Bridge dependencies bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } -bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } -bp-wococo = { path = "../../primitives/chain-wococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/client-bridge-hub-wococo/Cargo.toml b/relays/client-bridge-hub-wococo/Cargo.toml deleted file mode 100644 index d90af65d3a0bb..0000000000000 --- a/relays/client-bridge-hub-wococo/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "relay-bridge-hub-wococo-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = [] } - -# Bridge dependencies - -bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } -bp-bridge-hub-wococo = { path = "../../primitives/chain-bridge-hub-wococo" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } - -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } -relay-substrate-client = { path = "../client-substrate" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[dev-dependencies] -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs deleted file mode 100644 index b144093d3669c..0000000000000 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2022 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 . - -//! Types used to connect to the BridgeHub-Wococo-Substrate parachain. - -use bp_bridge_hub_wococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_messages::MessageNonce; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, - UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; -use relay_bridge_hub_rococo_client::codegen_runtime; - -pub type RuntimeCall = runtime_types::bridge_hub_rococo_runtime::RuntimeCall; -pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; -pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; - -/// Wococo chain definition -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct BridgeHubWococo; - -impl UnderlyingChainProvider for BridgeHubWococo { - type Chain = bp_bridge_hub_wococo::BridgeHubWococo; -} - -impl Chain for BridgeHubWococo { - const ID: ChainId = bp_runtime::BRIDGE_HUB_WOCOCO_CHAIN_ID; - const NAME: &'static str = "BridgeHubWococo"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_bridge_hub_wococo::BEST_FINALIZED_BRIDGE_HUB_WOCOCO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = bp_bridge_hub_wococo::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithBalances for BridgeHubWococo { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_bridge_hub_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl ChainWithUtilityPallet for BridgeHubWococo { - type UtilityPallet = MockedRuntimeUtilityPallet; -} - -impl ChainWithTransactions for BridgeHubWococo { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - (((), ()), ((), ())), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(UncheckedExtrinsic::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_bridge_hub_wococo::Address::Id(signer.public().into()) - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } -} - -impl ChainWithMessages for BridgeHubWococo { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_bridge_hub_wococo::WITH_BRIDGE_HUB_WOCOCO_MESSAGES_PALLET_NAME; - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = - Some(bp_bridge_hub_wococo::WITH_BRIDGE_HUB_WOCOCO_RELAYERS_PALLET_NAME); - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_wococo::TO_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_wococo::FROM_BRIDGE_HUB_WOCOCO_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_wococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_wococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -} - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - type SystemCall = runtime_types::frame_system::pallet::Call; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = BridgeHubWococo::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = BridgeHubWococo::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/client-wococo/Cargo.toml b/relays/client-wococo/Cargo.toml deleted file mode 100644 index ab9e08aeef5f4..0000000000000 --- a/relays/client-wococo/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "relay-wococo-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } - -# Bridge dependencies - -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } -bp-wococo = { path = "../../primitives/chain-wococo" } - -relay-rococo-client = { path = "../client-rococo" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs deleted file mode 100644 index bb4e1c0130452..0000000000000 --- a/relays/client-wococo/src/lib.rs +++ /dev/null @@ -1,133 +0,0 @@ -// 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 . - -//! Types used to connect to the Wococo-Substrate chain. - -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; -use bp_wococo::WOCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use sp_session::MembershipProof; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; -use relay_rococo_client::codegen_runtime; - -pub type RuntimeCall = runtime_types::rococo_runtime::RuntimeCall; - -pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; - -/// Wococo header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Wococo header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Wococo chain definition -#[derive(Debug, Clone, Copy)] -pub struct Wococo; - -impl UnderlyingChainProvider for Wococo { - type Chain = bp_wococo::Wococo; -} - -impl Chain for Wococo { - const ID: ChainId = bp_runtime::WOCOCO_CHAIN_ID; - const NAME: &'static str = "Wococo"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_wococo::BEST_FINALIZED_WOCOCO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_wococo::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithGrandpa for Wococo { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - WOCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl ChainWithBalances for Wococo { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl RelayChain for Wococo { - const PARAS_PALLET_NAME: &'static str = bp_wococo::PARAS_PALLET_NAME; -} - -impl ChainWithTransactions for Wococo { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_wococo::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - ((), ()), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } -} diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 8a490a9d2756d..f4df31766fedb 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -51,8 +51,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas [dev-dependencies] bp-rococo = { path = "../../primitives/chain-rococo" } -bp-wococo = { path = "../../primitives/chain-wococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -relay-rococo-client = { path = "../client-rococo" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } -relay-bridge-hub-wococo-client = { path = "../client-bridge-hub-wococo" } +relay-bridge-hub-westend-client = { path = "../client-bridge-hub-westend" } +relay-rococo-client = { path = "../client-rococo" } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index ed7a2d5924fb7..f128546bad3fb 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -556,7 +556,7 @@ mod tests { use super::*; use bp_runtime::Chain as ChainBase; use relay_bridge_hub_rococo_client::BridgeHubRococo; - use relay_bridge_hub_wococo_client::BridgeHubWococo; + use relay_bridge_hub_westend_client::BridgeHubWestend; fn message_details_from_rpc( nonces: RangeInclusive, @@ -644,7 +644,7 @@ mod tests { msgs_to_refine.push((payload, out_msg_details)); } - let maybe_batches = split_msgs_to_refine::( + let maybe_batches = split_msgs_to_refine::( Default::default(), msgs_to_refine, ); From 1047d361ce2a3dbc559fe0618b1a69a9b17070ab Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 14 Nov 2023 12:42:06 +0100 Subject: [PATCH 1150/1210] Porting changes from polkadot-sdk to polkadot-staging - before update subtree with removed wococo stuff (#2696) * Porting changes from `polkadot-sdk` to `polkadot-staging` * Bump polkadot-sdk to #ae1bdcfb91a26c5f65c5ca534aa8a04523ca2277 * Cargo.lock * DefaultConfig * DefaultConfig for `frame_system::Config` * Revert back --- bin/runtime-common/src/mock.rs | 38 +++------------- modules/beefy/src/mock.rs | 34 ++------------- modules/grandpa/src/mock.rs | 40 +---------------- modules/messages/Cargo.toml | 2 - modules/messages/src/mock.rs | 53 +++-------------------- modules/parachains/src/mock.rs | 41 +++--------------- modules/relayers/Cargo.toml | 1 - modules/relayers/src/mock.rs | 43 +++--------------- modules/xcm-bridge-hub-router/src/mock.rs | 31 ++----------- primitives/relayers/Cargo.toml | 2 + primitives/relayers/src/lib.rs | 2 +- 11 files changed, 35 insertions(+), 252 deletions(-) diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 943a98284a5e7..ffabf7f6e2f84 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -39,13 +39,13 @@ use bp_runtime::{ }; use codec::{Decode, Encode}; use frame_support::{ - parameter_types, + derive_impl, parameter_types, weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight}, }; use pallet_transaction_payment::Multiplier; use sp_runtime::{ testing::H256, - traits::{BlakeTwo256, ConstU32, ConstU64, ConstU8, IdentityLookup}, + traits::{BlakeTwo256, ConstU32, ConstU64, ConstU8}, FixedPointNumber, Perquintill, }; @@ -141,30 +141,14 @@ parameter_types! { pub const ReserveId: [u8; 8] = *b"brdgrlrs"; } +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; type Hash = ThisChainHash; type Hashing = ThisChainHasher; type AccountId = ThisChainAccountId; - type Lookup = IdentityLookup; type Block = ThisChainBlock; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU32<250>; - type Version = (); - type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = DbWeight; - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type BlockHashCount = ConstU32<250>; } impl pallet_utility::Config for TestRuntime { @@ -174,20 +158,10 @@ impl pallet_utility::Config for TestRuntime { type WeightInfo = (); } +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for TestRuntime { - type Balance = ThisChainBalance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; + type AccountStore = System; } impl pallet_transaction_payment::Config for TestRuntime { diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 3985d25c32f07..0b0084609cc55 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -24,12 +24,11 @@ use crate::{ use bp_beefy::{BeefyValidatorSignatureOf, ChainWithBeefy, Commitment, MmrDataOrHash}; use bp_runtime::{BasicOperatingMode, Chain}; use codec::Encode; -use frame_support::{construct_runtime, parameter_types, traits::ConstU64, weights::Weight}; +use frame_support::{construct_runtime, derive_impl, weights::Weight}; use sp_core::{sr25519::Signature, Pair}; use sp_runtime::{ testing::{Header, H256}, - traits::{BlakeTwo256, Hash, IdentityLookup}, - Perbill, + traits::{BlakeTwo256, Hash}, }; pub use sp_consensus_beefy::ecdsa_crypto::{AuthorityId as BeefyId, Pair as BeefyPair}; @@ -67,36 +66,9 @@ construct_runtime! { } } -parameter_types! { - pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; type Block = Block; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = TestAccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = (); - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type DbWeight = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; } impl beefy::Config for TestRuntime { diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index f88a0a3e6a6ee..7efa84971fe7f 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -20,16 +20,9 @@ use bp_header_chain::ChainWithGrandpa; use bp_runtime::Chain; use frame_support::{ - construct_runtime, parameter_types, - traits::{ConstU32, ConstU64, Hooks}, - weights::Weight, + construct_runtime, derive_impl, parameter_types, traits::Hooks, weights::Weight, }; use sp_core::sr25519::Signature; -use sp_runtime::{ - testing::H256, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, -}; pub type AccountId = u64; pub type TestHeader = sp_runtime::testing::Header; @@ -49,43 +42,14 @@ construct_runtime! { } } -parameter_types! { - pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type DbWeight = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; } parameter_types! { pub const MaxFreeMandatoryHeadersPerBlock: u32 = 2; pub const HeadersToKeep: u32 = 5; - pub const SessionLength: u64 = 5; - pub const NumValidators: u32 = 5; } impl grandpa::Config for TestRuntime { diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index e24cab3e587bb..05cc60b374bf3 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -22,7 +22,6 @@ bp-runtime = { path = "../../primitives/runtime", default-features = false } frame-benchmarking = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false, optional = true } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } @@ -43,7 +42,6 @@ std = [ "log/std", "num-traits/std", "scale-info/std", - "sp-core/std", "sp-runtime/std", "sp-std/std", ] diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index aebb7eafa7871..648acad772d7a 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -34,16 +34,11 @@ use bp_messages::{ use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; use frame_support::{ - parameter_types, - traits::ConstU64, + derive_impl, parameter_types, weights::{constants::RocksDbWeight, Weight}, }; use scale_info::TypeInfo; -use sp_core::H256; -use sp_runtime::{ - traits::{BlakeTwo256, ConstU32, IdentityLookup}, - BuildStorage, Perbill, -}; +use sp_runtime::BuildStorage; use std::{ collections::{BTreeMap, VecDeque}, ops::RangeInclusive, @@ -84,55 +79,19 @@ frame_support::construct_runtime! { } } -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - pub type DbWeight = RocksDbWeight; +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); type DbWeight = DbWeight; - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; } +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for TestRuntime { - type MaxLocks = (); - type Balance = Balance; - type DustRemoval = (); - type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ConstU64<1>; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type MaxReserves = (); - type ReserveIdentifier = (); - type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; + type ReserveIdentifier = [u8; 8]; + type AccountStore = System; } parameter_types! { diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 14afe38417105..d95e76f310862 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -17,17 +17,18 @@ use bp_header_chain::ChainWithGrandpa; use bp_polkadot_core::parachains::ParaId; use bp_runtime::{Chain, Parachain}; -use frame_support::{construct_runtime, parameter_types, traits::ConstU32, weights::Weight}; +use frame_support::{ + construct_runtime, derive_impl, parameter_types, traits::ConstU32, weights::Weight, +}; use sp_runtime::{ testing::H256, - traits::{BlakeTwo256, Header as HeaderT, IdentityLookup}, - MultiSignature, Perbill, + traits::{BlakeTwo256, Header as HeaderT}, + MultiSignature, }; use crate as pallet_bridge_parachains; pub type AccountId = u64; -pub type TestNumber = u64; pub type RelayBlockHeader = sp_runtime::generic::Header; @@ -152,42 +153,12 @@ construct_runtime! { } } -parameter_types! { - pub const BlockHashCount: TestNumber = 250; - pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 0); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); -} - +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; type Block = Block; - type Hash = H256; - type Hashing = RegularParachainHasher; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type DbWeight = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; } parameter_types! { - pub const SessionLength: u64 = 5; - pub const NumValidators: u32 = 5; pub const HeadersToKeep: u32 = 5; } diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 6e00ee99cebb7..e998177694aa3 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -30,7 +30,6 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" [dev-dependencies] bp-runtime = { path = "../../primitives/runtime" } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 4713ec91658af..667b10e5c125e 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -22,12 +22,10 @@ use bp_messages::LaneId; use bp_relayers::{ PayRewardFromAccount, PaymentProcedure, RewardsAccountOwner, RewardsAccountParams, }; -use frame_support::{parameter_types, traits::fungible::Mutate, weights::RuntimeDbWeight}; -use sp_core::H256; -use sp_runtime::{ - traits::{BlakeTwo256, ConstU32, IdentityLookup}, - BuildStorage, +use frame_support::{ + derive_impl, parameter_types, traits::fungible::Mutate, weights::RuntimeDbWeight, }; +use sp_runtime::BuildStorage; pub type AccountId = u64; pub type Balance = u64; @@ -61,46 +59,17 @@ parameter_types! { pub const Lease: BlockNumber = 8; } +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; type Block = Block; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = frame_support::traits::ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); type DbWeight = DbWeight; - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; } +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] impl pallet_balances::Config for TestRuntime { - type MaxLocks = (); - type Balance = Balance; - type DustRemoval = (); - type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type WeightInfo = (); - type MaxReserves = ConstU32<1>; type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = RuntimeHoldReason; - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; + type AccountStore = System; } impl pallet_bridge_relayers::Config for TestRuntime { diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 2152b4eb28f33..2d173ebc0457a 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -19,13 +19,9 @@ use crate as pallet_xcm_bridge_hub_router; use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; -use frame_support::{construct_runtime, parameter_types}; +use frame_support::{construct_runtime, derive_impl, parameter_types}; use frame_system::EnsureRoot; -use sp_core::H256; -use sp_runtime::{ - traits::{BlakeTwo256, ConstU128, IdentityLookup}, - BuildStorage, -}; +use sp_runtime::{traits::ConstU128, BuildStorage}; use xcm::prelude::*; use xcm_builder::{NetworkExportTable, NetworkExportTableItem}; @@ -64,30 +60,9 @@ parameter_types! { ]; } +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for TestRuntime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; type Block = Block; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = frame_support::traits::ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type BaseCallFilter = frame_support::traits::Everything; - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_xcm_bridge_hub_router::Config<()> for TestRuntime { diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index db381836e98ac..927e3e905baaa 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -30,7 +30,9 @@ default = [ "std" ] std = [ "bp-messages/std", "bp-runtime/std", + "codec/std", "frame-support/std", + "scale-info/std", "sp-runtime/std", "sp-std/std", ] diff --git a/primitives/relayers/src/lib.rs b/primitives/relayers/src/lib.rs index c529eea536d73..c808c437b54cb 100644 --- a/primitives/relayers/src/lib.rs +++ b/primitives/relayers/src/lib.rs @@ -115,7 +115,7 @@ where impl PaymentProcedure for PayRewardFromAccount where T: frame_support::traits::fungible::Mutate, - Relayer: Decode + Encode, + Relayer: Decode + Encode + Eq, { type Error = sp_runtime::DispatchError; From 04bef396a614b0fa7719cde102dac932fb190e72 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 15 Nov 2023 11:35:00 +0300 Subject: [PATCH 1151/1210] removed bp-asset-hub-kusama and bp-asset-hub-polkadot (#2703) --- primitives/chain-asset-hub-kusama/Cargo.toml | 26 ---------- primitives/chain-asset-hub-kusama/src/lib.rs | 49 ------------------- .../chain-asset-hub-polkadot/Cargo.toml | 28 ----------- .../chain-asset-hub-polkadot/src/lib.rs | 49 ------------------- 4 files changed, 152 deletions(-) delete mode 100644 primitives/chain-asset-hub-kusama/Cargo.toml delete mode 100644 primitives/chain-asset-hub-kusama/src/lib.rs delete mode 100644 primitives/chain-asset-hub-polkadot/Cargo.toml delete mode 100644 primitives/chain-asset-hub-polkadot/src/lib.rs diff --git a/primitives/chain-asset-hub-kusama/Cargo.toml b/primitives/chain-asset-hub-kusama/Cargo.toml deleted file mode 100644 index 5c8ccf3d0fca3..0000000000000 --- a/primitives/chain-asset-hub-kusama/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "bp-asset-hub-kusama" -description = "Primitives of AssetHubKusama parachain runtime." -version = "0.1.0" -authors.workspace = true -edition.workspace = true -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-xcm-bridge-hub-router/std", - "codec/std", - "frame-support/std", - "scale-info/std", -] diff --git a/primitives/chain-asset-hub-kusama/src/lib.rs b/primitives/chain-asset-hub-kusama/src/lib.rs deleted file mode 100644 index 94016c1da0cb1..0000000000000 --- a/primitives/chain-asset-hub-kusama/src/lib.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 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 . - -//! Module with configuration which reflects AssetHubKusama runtime setup. - -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; - -/// `AssetHubKusama` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `AssetHubKusama` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `AssetHubKusama` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// `ToPolkadotXcmRouter` bridge pallet. - #[codec(index = 43)] - ToPolkadotXcmRouter(XcmBridgeHubRouterCall), -} - -frame_support::parameter_types! { - /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. - pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); - - /// Base delivery fee to `BridgeHubKusama`. - /// (initially was calculated `170733333` + `10%` by test `BridgeHubKusama::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) - pub const BridgeHubKusamaBaseFeeInDots: u128 = 187806666; -} diff --git a/primitives/chain-asset-hub-polkadot/Cargo.toml b/primitives/chain-asset-hub-polkadot/Cargo.toml deleted file mode 100644 index 9c302f72d162f..0000000000000 --- a/primitives/chain-asset-hub-polkadot/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "bp-asset-hub-polkadot" -description = "Primitives of AssetHubPolkadot parachain runtime." -version = "0.1.0" -authors.workspace = true -edition.workspace = true -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } - -# Substrate Dependencies -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } - -# Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } - -[features] -default = [ "std" ] -std = [ - "bp-xcm-bridge-hub-router/std", - "codec/std", - "frame-support/std", - "scale-info/std", - "sp-runtime/std", -] diff --git a/primitives/chain-asset-hub-polkadot/src/lib.rs b/primitives/chain-asset-hub-polkadot/src/lib.rs deleted file mode 100644 index 486fba60e1f88..0000000000000 --- a/primitives/chain-asset-hub-polkadot/src/lib.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 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 . - -//! Module with configuration which reflects AssetHubPolkadot runtime setup. - -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_xcm_bridge_hub_router::XcmBridgeHubRouterCall; - -/// `AssetHubPolkadot` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `AssetHubPolkadot` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `AssetHubPolkadot` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - /// `ToKusamaXcmRouter` bridge pallet. - #[codec(index = 43)] - ToKusamaXcmRouter(XcmBridgeHubRouterCall), -} - -frame_support::parameter_types! { - /// Some sane weight to execute `xcm::Transact(pallet-xcm-bridge-hub-router::Call::report_bridge_status)`. - pub const XcmBridgeHubRouterTransactCallMaxWeight: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(200_000_000, 6144); - - /// Base delivery fee to `BridgeHubPolkadot`. - /// (initially was calculated `51220000` + `10%` by test `BridgeHubPolkadot::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) - pub const BridgeHubPolkadotBaseFeeInDots: u128 = 56342000; -} From 66f10666454b1721ec5e5e803ddd3c558eb10b89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:23:31 +0000 Subject: [PATCH 1152/1210] Bump ed25519-dalek from 2.0.0 to 2.1.0 Bumps [ed25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek) from 2.0.0 to 2.1.0. - [Release notes](https://github.com/dalek-cryptography/curve25519-dalek/releases) - [Changelog](https://github.com/dalek-cryptography/curve25519-dalek/blob/2.1.0/CHANGELOG.md) - [Commits](https://github.com/dalek-cryptography/curve25519-dalek/compare/2.0.0...2.1.0) --- updated-dependencies: - dependency-name: ed25519-dalek dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- primitives/test-utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 778d4e165e86b..e8c542aefc532 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -12,7 +12,7 @@ bp-parachains = { path = "../parachains", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -ed25519-dalek = { version = "2.0", default-features = false } +ed25519-dalek = { version = "2.1", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } From 98e6cfaaf15c9dcf48f1964729343898f8825881 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Mon, 4 Dec 2023 17:00:04 +0100 Subject: [PATCH 1153/1210] Backport from `polkadot-sdk` + bump (#2725) * Backport from `polkadot-sdk` * Bump `polkadot-sdk` * revert * Cargo.lock --- README.md | 2 +- bin/runtime-common/Cargo.toml | 4 ++-- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- primitives/chain-asset-hub-rococo/Cargo.toml | 2 +- primitives/chain-asset-hub-westend/Cargo.toml | 2 +- primitives/chain-bridge-hub-cumulus/Cargo.toml | 2 +- primitives/chain-bridge-hub-kusama/Cargo.toml | 2 +- primitives/chain-bridge-hub-polkadot/Cargo.toml | 2 +- primitives/chain-bridge-hub-rococo/Cargo.toml | 2 +- primitives/chain-bridge-hub-westend/Cargo.toml | 2 +- primitives/chain-kusama/Cargo.toml | 2 +- primitives/chain-polkadot-bulletin/Cargo.toml | 2 +- primitives/chain-polkadot/Cargo.toml | 2 +- primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 4 ++-- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 4 ++-- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 6 +++--- primitives/xcm-bridge-hub-router/Cargo.toml | 6 +++--- 27 files changed, 34 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index f8191f432adfa..a2ce213d2541c 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ messages between chains. │ ├── parachains // On-Chain Parachains Light Client │ ├── relayers // Relayer Rewards Registry │ ├── xcm-bridge-hub // Multiple Dynamic Bridges Support -│ ├── xcm-bridge-hub-router // XCM Router that may be used to Connect to XCM Bridge Hub +│ ├── xcm-bridge-hub-router // XCM Router that may be used to Connect to XCM Bridge Hub ├── primitives // Code shared between modules, runtimes, and relays │ └── ... ├── relays // Application for sending finality proofs and messages between chains diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index e94d886006e89..44799c1b5332c 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -50,7 +50,7 @@ bp-test-utils = { path = "../../primitives/test-utils" } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-messages/std", @@ -92,4 +92,4 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", ] -integrity-test = [ "static_assertions" ] +integrity-test = ["static_assertions"] diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 6569fe9c400b7..4d8a5c074461a 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -37,7 +37,7 @@ sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-runtime/std", diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 05cc60b374bf3..0c8c0f7b82421 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -31,7 +31,7 @@ pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-messages/std", "bp-runtime/std", diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index b9d5c0e6d33e9..f8160e3c6c892 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -35,7 +35,7 @@ sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-parachains/std", diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index e998177694aa3..cbaedd4c73ee5 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -34,7 +34,7 @@ sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-messages/std", "bp-relayers/std", diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 314c7526fc4e1..e3a559cdc00a0 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -34,7 +34,7 @@ sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-xcm-bridge-hub-router/std", "codec/std", diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/primitives/chain-asset-hub-rococo/Cargo.toml index de9cd8b0d8060..5d86c7ebc6e68 100644 --- a/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/primitives/chain-asset-hub-rococo/Cargo.toml @@ -17,7 +17,7 @@ frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = " bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-xcm-bridge-hub-router/std", "codec/std", diff --git a/primitives/chain-asset-hub-westend/Cargo.toml b/primitives/chain-asset-hub-westend/Cargo.toml index 5ed968763550c..59629309e6f93 100644 --- a/primitives/chain-asset-hub-westend/Cargo.toml +++ b/primitives/chain-asset-hub-westend/Cargo.toml @@ -17,7 +17,7 @@ frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = " bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-xcm-bridge-hub-router/std", "codec/std", diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index 5b86305a9b90c..f0c2b5c2a1420 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -24,7 +24,7 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false , branch = "master" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-messages/std", "bp-polkadot-core/std", diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml index 2d6b5ba424e00..1ed02b9b2d528 100644 --- a/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -21,7 +21,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml index a4a116f0ce9fa..eebc4dfffd13e 100644 --- a/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -22,7 +22,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index 9dfedc850c8f3..a3f2b9c28c935 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -21,7 +21,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", diff --git a/primitives/chain-bridge-hub-westend/Cargo.toml b/primitives/chain-bridge-hub-westend/Cargo.toml index f425e7dbdbeb8..eea808ea2b568 100644 --- a/primitives/chain-bridge-hub-westend/Cargo.toml +++ b/primitives/chain-bridge-hub-westend/Cargo.toml @@ -22,7 +22,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-bridge-hub-cumulus/std", "bp-messages/std", diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index 4e27792f71792..b08489aea82da 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index 8b389b9f80ee2..b610b268d9a4d 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -26,7 +26,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-messages/std", diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 592498743c8e9..7ea28bd24b08f 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 29ac59dd3ed20..5e6e9bb73d266 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index f83ad61ed8be4..b28e250554e42 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -21,7 +21,7 @@ sp-api = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 03c998989937e..51d9b2f30f591 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -30,7 +30,7 @@ hex = "0.4" hex-literal = "0.4" [features] -default = [ "std" ] +default = ["std"] std = [ "bp-runtime/std", "codec/std", diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index c608fcf33c24f..10369e8c92253 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } @@ -27,7 +27,7 @@ hex = "0.4" hex-literal = "0.4" [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-runtime/std", diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 95ce8d50f70c1..569fa535a2817 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -25,7 +25,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-polkadot-core/std", diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 513b46098c621..e9542f6f5b345 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -29,7 +29,7 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" hex = "0.4" [features] -default = [ "std" ] +default = ["std"] std = [ "bp-messages/std", "bp-runtime/std", diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 927e3e905baaa..060e36a5f0027 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies @@ -26,7 +26,7 @@ hex = "0.4" hex-literal = "0.4" [features] -default = [ "std" ] +default = ["std"] std = [ "bp-messages/std", "bp-runtime/std", diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index dc5793e3aa0d2..b52d20d691600 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -31,7 +31,7 @@ trie-db = { version = "0.28.0", default-features = false } hex-literal = "0.4" [features] -default = [ "std" ] +default = ["std"] std = [ "codec/std", "frame-support/std", diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index e8c542aefc532..7432841760638 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -7,9 +7,9 @@ edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -bp-header-chain = { path = "../header-chain", default-features = false } +bp-header-chain = { path = "../header-chain", default-features = false } bp-parachains = { path = "../parachains", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } +bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } ed25519-dalek = { version = "2.1", default-features = false } @@ -22,7 +22,7 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" sp-trie = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-header-chain/std", "bp-parachains/std", diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index 9454a3efd1c73..6cf260ce5e9b5 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies @@ -15,5 +15,5 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] -std = [ "codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std" ] +default = ["std"] +std = ["codec/std", "scale-info/std", "sp-core/std", "sp-runtime/std"] From 698ced607e126f77b3241b09233f2e2584f9dcac Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 5 Dec 2023 18:00:34 +0300 Subject: [PATCH 1154/1210] separate constants for average and worst case relay headers (#2728) * separate constants for average and worst case relay headers * fix compilation --- bin/runtime-common/src/mock.rs | 1 + modules/grandpa/src/mock.rs | 1 + modules/parachains/src/mock.rs | 2 ++ primitives/chain-kusama/src/lib.rs | 1 + primitives/chain-polkadot-bulletin/src/lib.rs | 2 ++ primitives/chain-polkadot/src/lib.rs | 1 + primitives/chain-rococo/src/lib.rs | 1 + primitives/chain-westend/src/lib.rs | 1 + primitives/header-chain/src/lib.rs | 17 ++++++++++++++++- primitives/polkadot-core/src/lib.rs | 13 +++++++++++-- 10 files changed, 37 insertions(+), 3 deletions(-) diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index ffabf7f6e2f84..2d34dc272c728 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -378,6 +378,7 @@ impl ChainWithGrandpa for BridgedUnderlyingChain { const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; const MAX_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; } impl Chain for BridgedUnderlyingParachain { diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 7efa84971fe7f..ad61e7498bd14 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -88,6 +88,7 @@ impl ChainWithGrandpa for TestBridgedChain { const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; const MAX_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; } /// Return test externalities to use in tests. diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index d95e76f310862..8e7a0d7e40028 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -254,6 +254,7 @@ impl ChainWithGrandpa for TestBridgedChain { const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; const MAX_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; } #[derive(Debug)] @@ -285,6 +286,7 @@ impl ChainWithGrandpa for OtherBridgedChain { const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; const MAX_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; } /// Return test externalities to use in tests. diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index d5748aa132cea..7f11daadf1af7 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -54,6 +54,7 @@ impl ChainWithGrandpa for Kusama { REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; } // The SignedExtension used by Kusama. diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/primitives/chain-polkadot-bulletin/src/lib.rs index fcc6e90eb1b29..49461ab8fbfa3 100644 --- a/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/primitives/chain-polkadot-bulletin/src/lib.rs @@ -44,6 +44,7 @@ pub use bp_polkadot_core::{ AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature, SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE_IN_JUSTIFICATION, EXTRA_STORAGE_PROOF_SIZE, MAX_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, + WORST_HEADER_SIZE_IN_JUSTIFICATION, }; /// Maximal number of GRANDPA authorities at Polkadot Bulletin chain. @@ -209,6 +210,7 @@ impl ChainWithGrandpa for PolkadotBulletin { REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; } decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 61c8ca927d807..3f9e2bbc078d2 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -54,6 +54,7 @@ impl ChainWithGrandpa for Polkadot { REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; } /// The SignedExtension used by Polkadot. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 5436ad846468c..4c2d5f41f5f93 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -54,6 +54,7 @@ impl ChainWithGrandpa for Rococo { REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; } parameter_types! { diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 45c13d600601f..fdf1abe6e07b9 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -54,6 +54,7 @@ impl ChainWithGrandpa for Westend { REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; } parameter_types! { diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index d2c7ec0759e88..4e004b28b1946 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -280,9 +280,22 @@ pub trait ChainWithGrandpa: Chain { /// headers that aren't changing the set. /// /// This isn't a strict limit. The relay may submit justifications with larger headers in its + /// ancestry and the pallet will accept the call. The limit is only used to compute fee, paid + /// by the user at the sending chain. It covers most of cases, but if the actual header, + /// submitted with the messages transaction will be larger than the + /// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION`, the difference (`WORST_HEADER_SIZE_IN_JUSTIFICATION` + /// - `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION`) must be covered by the sending chain. + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; + + /// Worst-case size of the chain header from justification ancestry. We don't expect to see + /// there headers that change GRANDPA authorities set (GRANDPA will probably be able to finalize + /// at least one additional header per session on non test chains), so this is the worst-case + /// size of headers that aren't changing the set. + /// + /// This isn't a strict limit. The relay may submit justifications with larger headers in its /// ancestry and the pallet will accept the call. The limit is only used to compute maximal /// refund amount and doing calls which exceed the limit, may be costly to submitter. - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32; } impl ChainWithGrandpa for T @@ -298,4 +311,6 @@ where const MAX_HEADER_SIZE: u32 = ::MAX_HEADER_SIZE; const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = ::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = + ::WORST_HEADER_SIZE_IN_JUSTIFICATION; } diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index af39b5ab9baba..9ebff80ce4d54 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -70,7 +70,16 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256; /// reserve here. pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; -/// Approximate average header size in `votes_ancestries` field of justification on Polkadot-like +/// Average header size in `votes_ancestries` field of justification on Polkadot-like +/// chains. +/// +/// See [`bp-header-chain::ChainWithGrandpa`] for more details. +/// +/// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but let's +/// have some reserve and make it 1024. +pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 1024; + +/// Worst-case header size in `votes_ancestries` field of justification on Polkadot-like /// chains. /// /// See [`bp-header-chain::ChainWithGrandpa`] for more details. @@ -79,7 +88,7 @@ pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; /// non-mandatory headers has size `40kb` (they contain the BABE epoch descriptor with all /// authorities - just like our mandatory header). Since we assume `2` headers in justification /// votes ancestry, let's set average header to `40kb / 2`. -pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024; +pub const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024; /// Approximate maximal header size on Polkadot-like chains. /// From ece0535e64ec95048d98cb1f3fc3c171bb62b3a8 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 6 Dec 2023 15:16:02 +0300 Subject: [PATCH 1155/1210] Select header that will be fully refunded in on-demand batch finality relay (#2729) * select header that will be fully refunded for submission in on-demand **batch** finality relay * added the only possible test * spelling * nl * updated comment --- bin/runtime-common/src/mock.rs | 5 +- modules/grandpa/src/call_ext.rs | 29 ++--- modules/grandpa/src/mock.rs | 5 +- modules/parachains/src/mock.rs | 10 +- primitives/chain-kusama/src/lib.rs | 5 +- primitives/chain-polkadot-bulletin/src/lib.rs | 10 +- primitives/chain-polkadot/src/lib.rs | 5 +- primitives/chain-rococo/src/lib.rs | 5 +- primitives/chain-westend/src/lib.rs | 5 +- .../header-chain/src/justification/mod.rs | 4 +- primitives/header-chain/src/lib.rs | 106 +++++++++++++----- primitives/polkadot-core/src/lib.rs | 25 ++--- relays/bin-substrate/Cargo.toml | 1 + .../src/finality_base/engine.rs | 46 +++++++- .../src/on_demand/headers.rs | 76 +++++++++---- 15 files changed, 222 insertions(+), 115 deletions(-) diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 2d34dc272c728..bd47d37fc07d0 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -376,9 +376,8 @@ impl ChainWithGrandpa for BridgedUnderlyingChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; - const MAX_HEADER_SIZE: u32 = 256; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const MAX_MANDATORY_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE: u32 = 64; } impl Chain for BridgedUnderlyingParachain { diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index f238064f92bca..c1585020be13c 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -15,7 +15,10 @@ // along with Parity Bridges Common. If not, see . use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet}; -use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa}; +use bp_header_chain::{ + justification::GrandpaJustification, max_expected_submit_finality_proof_arguments_size, + ChainWithGrandpa, GrandpaConsensusLogReader, +}; use bp_runtime::{BlockNumberOf, OwnedBridgeModule}; use codec::Encode; use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight}; @@ -169,28 +172,28 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( Weight::zero() }; + // check if the `finality_target` is a mandatory header. If so, we are ready to refund larger + // size + let is_mandatory_finality_target = + GrandpaConsensusLogReader::>::find_scheduled_change( + finality_target.digest(), + ) + .is_some(); + // we can estimate extra call size easily, without any additional significant overhead let actual_call_size: u32 = finality_target .encoded_size() .saturating_add(justification.encoded_size()) .saturated_into(); - let max_expected_call_size = max_expected_call_size::(required_precommits); + let max_expected_call_size = max_expected_submit_finality_proof_arguments_size::( + is_mandatory_finality_target, + required_precommits, + ); let extra_size = actual_call_size.saturating_sub(max_expected_call_size); SubmitFinalityProofInfo { block_number, extra_weight, extra_size } } -/// Returns maximal expected size of `submit_finality_proof` call arguments. -fn max_expected_call_size, I: 'static>(required_precommits: u32) -> u32 { - let max_expected_justification_size = - GrandpaJustification::>::max_reasonable_size::( - required_precommits, - ); - - // call arguments are header and justification - T::BridgedChain::MAX_HEADER_SIZE.saturating_add(max_expected_justification_size) -} - #[cfg(test)] mod tests { use crate::{ diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index ad61e7498bd14..a54f56c4a6249 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -86,9 +86,8 @@ impl ChainWithGrandpa for TestBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; - const MAX_HEADER_SIZE: u32 = 256; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const MAX_MANDATORY_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE: u32 = 64; } /// Return test externalities to use in tests. diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 8e7a0d7e40028..1c7851364d1c0 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -252,9 +252,8 @@ impl ChainWithGrandpa for TestBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; - const MAX_HEADER_SIZE: u32 = 256; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const MAX_MANDATORY_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE: u32 = 64; } #[derive(Debug)] @@ -284,9 +283,8 @@ impl ChainWithGrandpa for OtherBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; - const MAX_HEADER_SIZE: u32 = 256; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 64; + const MAX_MANDATORY_HEADER_SIZE: u32 = 256; + const AVERAGE_HEADER_SIZE: u32 = 64; } /// Return test externalities to use in tests. diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 7f11daadf1af7..5f089fbc589f6 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -52,9 +52,8 @@ impl ChainWithGrandpa for Kusama { const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } // The SignedExtension used by Kusama. diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/primitives/chain-polkadot-bulletin/src/lib.rs index 49461ab8fbfa3..fe82c9644b673 100644 --- a/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/primitives/chain-polkadot-bulletin/src/lib.rs @@ -42,9 +42,8 @@ use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidi // This chain reuses most of Polkadot primitives. pub use bp_polkadot_core::{ AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature, - SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE_IN_JUSTIFICATION, - EXTRA_STORAGE_PROOF_SIZE, MAX_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, - WORST_HEADER_SIZE_IN_JUSTIFICATION, + SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE, EXTRA_STORAGE_PROOF_SIZE, + MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, }; /// Maximal number of GRANDPA authorities at Polkadot Bulletin chain. @@ -208,9 +207,8 @@ impl ChainWithGrandpa for PolkadotBulletin { const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 3f9e2bbc078d2..9a5b8970accb2 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -52,9 +52,8 @@ impl ChainWithGrandpa for Polkadot { const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } /// The SignedExtension used by Polkadot. diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 4c2d5f41f5f93..7f3e762715f32 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -52,9 +52,8 @@ impl ChainWithGrandpa for Rococo { const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } parameter_types! { diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index fdf1abe6e07b9..7fa5e140d5707 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -52,9 +52,8 @@ impl ChainWithGrandpa for Westend { const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = WORST_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } parameter_types! { diff --git a/primitives/header-chain/src/justification/mod.rs b/primitives/header-chain/src/justification/mod.rs index 72a5f68918d97..b32d8bdb5f1d8 100644 --- a/primitives/header-chain/src/justification/mod.rs +++ b/primitives/header-chain/src/justification/mod.rs @@ -82,8 +82,8 @@ impl GrandpaJustification { .saturating_add(BlockNumberOf::::max_encoded_len().saturated_into()) .saturating_add(HashOf::::max_encoded_len().saturated_into()); - let max_expected_votes_ancestries_size = C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY - .saturating_mul(C::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION); + let max_expected_votes_ancestries_size = + C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE); // justification is round number (u64=8b), a signed GRANDPA commit and the // `votes_ancestries` vector diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 4e004b28b1946..1459b1c1994bc 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -266,36 +266,28 @@ pub trait ChainWithGrandpa: Chain { /// to submitter. const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32; - /// Maximal size of the chain header. The header may be the header that enacts new GRANDPA - /// authorities set (so it has large digest inside). + /// Maximal size of the mandatory chain header. Mandatory header is the header that enacts new + /// GRANDPA authorities set (so it has large digest inside). /// /// This isn't a strict limit. The relay may submit larger headers and the pallet will accept /// the call. The limit is only used to compute maximal refund amount and doing calls which /// exceed the limit, may be costly to submitter. - const MAX_HEADER_SIZE: u32; + const MAX_MANDATORY_HEADER_SIZE: u32; - /// Average size of the chain header from justification ancestry. We don't expect to see there - /// headers that change GRANDPA authorities set (GRANDPA will probably be able to finalize at - /// least one additional header per session on non test chains), so this is average size of - /// headers that aren't changing the set. + /// Average size of the chain header. We don't expect to see there headers that change GRANDPA + /// authorities set (GRANDPA will probably be able to finalize at least one additional header + /// per session on non test chains), so this is average size of headers that aren't changing the + /// set. /// - /// This isn't a strict limit. The relay may submit justifications with larger headers in its - /// ancestry and the pallet will accept the call. The limit is only used to compute fee, paid - /// by the user at the sending chain. It covers most of cases, but if the actual header, - /// submitted with the messages transaction will be larger than the - /// `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION`, the difference (`WORST_HEADER_SIZE_IN_JUSTIFICATION` - /// - `AVERAGE_HEADER_SIZE_IN_JUSTIFICATION`) must be covered by the sending chain. - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; - - /// Worst-case size of the chain header from justification ancestry. We don't expect to see - /// there headers that change GRANDPA authorities set (GRANDPA will probably be able to finalize - /// at least one additional header per session on non test chains), so this is the worst-case - /// size of headers that aren't changing the set. + /// This isn't a strict limit. The relay may submit justifications with larger headers and the + /// pallet will accept the call. However, if the total size of all `submit_finality_proof` + /// arguments exceeds the maximal size, computed using this average size, relayer will only get + /// partial refund. /// - /// This isn't a strict limit. The relay may submit justifications with larger headers in its - /// ancestry and the pallet will accept the call. The limit is only used to compute maximal - /// refund amount and doing calls which exceed the limit, may be costly to submitter. - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32; + /// We expect some headers on production chains that are above this size. But they are rare and + /// if rellayer cares about its profitability, we expect it'll select other headers for + /// submission. + const AVERAGE_HEADER_SIZE: u32; } impl ChainWithGrandpa for T @@ -308,9 +300,67 @@ where const MAX_AUTHORITIES_COUNT: u32 = ::MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = ::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = ::MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = - ::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; - const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = - ::WORST_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = + ::MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = ::AVERAGE_HEADER_SIZE; +} + +/// Returns maximal expected size of `submit_finality_proof` call arguments. +pub fn max_expected_submit_finality_proof_arguments_size( + is_mandatory_finality_target: bool, + precommits: u32, +) -> u32 { + let max_expected_justification_size = + GrandpaJustification::>::max_reasonable_size::(precommits); + + // call arguments are header and justification + let max_expected_finality_target_size = if is_mandatory_finality_target { + C::MAX_MANDATORY_HEADER_SIZE + } else { + C::AVERAGE_HEADER_SIZE + }; + max_expected_finality_target_size.saturating_add(max_expected_justification_size) +} + +#[cfg(test)] +mod tests { + use super::*; + use frame_support::weights::Weight; + use sp_runtime::{testing::H256, traits::BlakeTwo256, MultiSignature}; + + struct TestChain; + + impl Chain for TestChain { + type BlockNumber = u32; + type Hash = H256; + type Hasher = BlakeTwo256; + type Header = sp_runtime::generic::Header; + type AccountId = u64; + type Balance = u64; + type Nonce = u64; + type Signature = MultiSignature; + + fn max_extrinsic_size() -> u32 { + 0 + } + fn max_extrinsic_weight() -> Weight { + Weight::zero() + } + } + + impl ChainWithGrandpa for TestChain { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "Test"; + const MAX_AUTHORITIES_COUNT: u32 = 128; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; + const MAX_MANDATORY_HEADER_SIZE: u32 = 100_000; + const AVERAGE_HEADER_SIZE: u32 = 1_024; + } + + #[test] + fn max_expected_submit_finality_proof_arguments_size_respects_mandatory_argument() { + assert!( + max_expected_submit_finality_proof_arguments_size::(true, 100) > + max_expected_submit_finality_proof_arguments_size::(false, 100), + ); + } } diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 9ebff80ce4d54..586cbf8cb9b47 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -64,7 +64,7 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256; /// /// See [`bp-header-chain::ChainWithGrandpa`] for more details. /// -/// This value comes from recent (February, 2023) Kusama and Polkadot headers. There are no +/// This value comes from recent (December, 2023) Kusama and Polkadot headers. There are no /// justifications with any additional headers in votes ancestry, so reasonable headers may /// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some /// reserve here. @@ -75,28 +75,17 @@ pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; /// /// See [`bp-header-chain::ChainWithGrandpa`] for more details. /// -/// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but let's -/// have some reserve and make it 1024. -pub const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = 1024; - -/// Worst-case header size in `votes_ancestries` field of justification on Polkadot-like -/// chains. -/// -/// See [`bp-header-chain::ChainWithGrandpa`] for more details. -/// -/// This value comes from recent (February, 2023) Kusama headers. Average is `336` there, but some -/// non-mandatory headers has size `40kb` (they contain the BABE epoch descriptor with all -/// authorities - just like our mandatory header). Since we assume `2` headers in justification -/// votes ancestry, let's set average header to `40kb / 2`. -pub const WORST_HEADER_SIZE_IN_JUSTIFICATION: u32 = 20 * 1024; +/// This value comes from recent (December, 2023) Kusama headers. Most of headers are `327` bytes +/// there, but let's have some reserve and make it 1024. +pub const AVERAGE_HEADER_SIZE: u32 = 1024; /// Approximate maximal header size on Polkadot-like chains. /// /// See [`bp-header-chain::ChainWithGrandpa`] for more details. /// -/// This value comes from recent (February, 2023) Kusama headers. Maximal header is a mandatory -/// header. In its SCALE-encoded form it is `80348` bytes. Let's have some reserve here. -pub const MAX_HEADER_SIZE: u32 = 90_000; +/// This value comes from recent (December, 2023) Kusama headers. Maximal header is a mandatory +/// header. In its SCALE-encoded form it is `113407` bytes. Let's have some reserve here. +pub const MAX_MANDATORY_HEADER_SIZE: u32 = 120 * 1024; /// Number of extra bytes (excluding size of storage value itself) of storage proof, built at /// Polkadot-like chain. This mostly depends on number of entries in the storage trie. diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index df2fc2ad169e1..a850f15ed4673 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } +env_logger = "0.10" futures = "0.3.29" hex = "0.4" log = "0.4.20" diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs index fb4515beeaaca..831c1e7ad5b50 100644 --- a/relays/lib-substrate-relay/src/finality_base/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -23,8 +23,9 @@ use bp_header_chain::{ verify_and_optimize_justification, GrandpaEquivocationsFinder, GrandpaJustification, JustificationVerificationContext, }, - AuthoritySet, ConsensusLogReader, FinalityProof, FindEquivocations, GrandpaConsensusLogReader, - HeaderFinalityInfo, HeaderGrandpaInfo, StoredHeaderGrandpaInfo, + max_expected_submit_finality_proof_arguments_size, AuthoritySet, ConsensusLogReader, + FinalityProof, FindEquivocations, GrandpaConsensusLogReader, HeaderFinalityInfo, + HeaderGrandpaInfo, StoredHeaderGrandpaInfo, }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode}; use codec::{Decode, Encode}; @@ -35,9 +36,22 @@ use relay_substrate_client::{ }; use sp_consensus_grandpa::{AuthorityList as GrandpaAuthoritiesSet, GRANDPA_ENGINE_ID}; use sp_core::{storage::StorageKey, Bytes}; -use sp_runtime::{scale_info::TypeInfo, traits::Header, ConsensusEngineId}; +use sp_runtime::{scale_info::TypeInfo, traits::Header, ConsensusEngineId, SaturatedConversion}; use std::{fmt::Debug, marker::PhantomData}; +/// Result of checking maximal expected call size. +pub enum MaxExpectedCallSizeCheck { + /// Size is ok and call will be refunded. + Ok, + /// The call size exceeds the maximal expected and relayer will only get partial refund. + Exceeds { + /// Actual call size. + call_size: u32, + /// Maximal expected call size. + max_call_size: u32, + }, +} + /// Finality engine, used by the Substrate chain. #[async_trait] pub trait Engine: Send { @@ -111,6 +125,14 @@ pub trait Engine: Send { proof: &mut Self::FinalityProof, ) -> Result<(), SubstrateError>; + /// Checks whether the given `header` and its finality `proof` fit the maximal expected + /// call size limit. If result is `MaxExpectedCallSizeCheck::Exceeds { .. }`, this + /// submission won't be fully refunded and relayer will spend its own funds on that. + fn check_max_expected_call_size( + header: &C::Header, + proof: &Self::FinalityProof, + ) -> MaxExpectedCallSizeCheck; + /// Prepare initialization data for the finality bridge pallet. async fn prepare_initialization_data( client: Client, @@ -219,6 +241,24 @@ impl Engine for Grandpa { }) } + fn check_max_expected_call_size( + header: &C::Header, + proof: &Self::FinalityProof, + ) -> MaxExpectedCallSizeCheck { + let is_mandatory = Self::ConsensusLogReader::schedules_authorities_change(header.digest()); + let call_size: u32 = + header.encoded_size().saturating_add(proof.encoded_size()).saturated_into(); + let max_call_size = max_expected_submit_finality_proof_arguments_size::( + is_mandatory, + proof.commit.precommits.len().saturated_into(), + ); + if call_size > max_call_size { + MaxExpectedCallSizeCheck::Exceeds { call_size, max_call_size } + } else { + MaxExpectedCallSizeCheck::Ok + } + } + /// Prepare initialization data for the GRANDPA verifier pallet. async fn prepare_initialization_data( source_client: Client, diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 5014851a5b2f3..0090dee3a03c8 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -16,14 +16,16 @@ //! On-demand Substrate -> Substrate header finality relay. -use crate::finality::SubmitFinalityProofCallBuilder; +use crate::{ + finality::SubmitFinalityProofCallBuilder, finality_base::engine::MaxExpectedCallSizeCheck, +}; use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use bp_header_chain::ConsensusLogReader; use bp_runtime::HeaderIdProvider; use futures::{select, FutureExt}; -use num_traits::{One, Zero}; +use num_traits::{One, Saturating, Zero}; use sp_runtime::traits::Header; use finality_relay::{FinalitySyncParams, TargetClient as FinalityTargetClient}; @@ -133,29 +135,61 @@ impl OnDemandRelay, ) -> Result<(HeaderIdOf, Vec>), SubstrateError> { - // first find proper header (either `required_header`) or its descendant - let finality_source = SubstrateFinalitySource::

::new(self.source_client.clone(), None); - let (header, mut proof) = finality_source.prove_block_finality(required_header).await?; - let header_id = header.id(); + const MAX_ITERATIONS: u32 = 4; + let mut iterations = 0; + let mut current_required_header = required_header; + loop { + // first find proper header (either `current_required_header`) or its descendant + let finality_source = + SubstrateFinalitySource::

::new(self.source_client.clone(), None); + let (header, mut proof) = + finality_source.prove_block_finality(current_required_header).await?; + let header_id = header.id(); + + // optimize justification before including it into the call + P::FinalityEngine::optimize_proof(&self.target_client, &header, &mut proof).await?; + + // now we have the header and its proof, but we want to minimize our losses, so let's + // check if we'll get the full refund for submitting this header + let check_result = P::FinalityEngine::check_max_expected_call_size(&header, &proof); + if let MaxExpectedCallSizeCheck::Exceeds { call_size, max_call_size } = check_result { + iterations += 1; + current_required_header = header_id.number().saturating_add(One::one()); + if iterations < MAX_ITERATIONS { + log::debug!( + target: "bridge", + "[{}] Requested to prove {} head {:?}. Selected to prove {} head {:?}. But it is too large: {} vs {}. \ + Going to select next header", + self.relay_task_name, + P::SourceChain::NAME, + required_header, + P::SourceChain::NAME, + header_id, + call_size, + max_call_size, + ); - // optimize justification before including it into the call - P::FinalityEngine::optimize_proof(&self.target_client, &header, &mut proof).await?; + continue; + } + } - log::debug!( - target: "bridge", - "[{}] Requested to prove {} head {:?}. Selected to prove {} head {:?}", - self.relay_task_name, - P::SourceChain::NAME, - required_header, - P::SourceChain::NAME, - header_id, - ); + log::debug!( + target: "bridge", + "[{}] Requested to prove {} head {:?}. Selected to prove {} head {:?} (after {} iterations)", + self.relay_task_name, + P::SourceChain::NAME, + required_header, + P::SourceChain::NAME, + header_id, + iterations, + ); - // and then craft the submit-proof call - let call = - P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + // and then craft the submit-proof call + let call = + P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); - Ok((header_id, vec![call])) + return Ok((header_id, vec![call])); + } } } From 95e9b041e95c9cfb6c9c196ef55e4ec0a687d889 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 6 Dec 2023 14:59:52 +0100 Subject: [PATCH 1156/1210] Improved `ExportXcm::validate` implementation for BridgeHubs - step 1 (#2727) * Improved `ExportXcm::validate` implementation for BridgeHubs * spellcheck * Fix try-runtime * Fix try-runtime --- bin/runtime-common/Cargo.toml | 2 + .../src/messages_xcm_extension.rs | 109 +++--- modules/xcm-bridge-hub/Cargo.toml | 74 ++++ modules/xcm-bridge-hub/src/exporter.rs | 208 +++++++++++ modules/xcm-bridge-hub/src/lib.rs | 96 +++++ modules/xcm-bridge-hub/src/mock.rs | 328 ++++++++++++++++++ primitives/xcm-bridge-hub/Cargo.toml | 16 + primitives/xcm-bridge-hub/src/lib.rs | 24 ++ 8 files changed, 794 insertions(+), 63 deletions(-) create mode 100644 modules/xcm-bridge-hub/Cargo.toml create mode 100644 modules/xcm-bridge-hub/src/exporter.rs create mode 100644 modules/xcm-bridge-hub/src/lib.rs create mode 100644 modules/xcm-bridge-hub/src/mock.rs create mode 100644 primitives/xcm-bridge-hub/Cargo.toml create mode 100644 primitives/xcm-bridge-hub/src/lib.rs diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 44799c1b5332c..1b81919434143 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -22,6 +22,7 @@ bp-parachains = { path = "../../primitives/parachains", default-features = false bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-relayers = { path = "../../primitives/relayers", default-features = false } bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false } bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } pallet-bridge-grandpa = { path = "../../modules/grandpa", default-features = false } pallet-bridge-messages = { path = "../../modules/messages", default-features = false } @@ -58,6 +59,7 @@ std = [ "bp-polkadot-core/std", "bp-relayers/std", "bp-runtime/std", + "bp-xcm-bridge-hub/std", "bp-xcm-bridge-hub-router/std", "codec/std", "frame-support/std", diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 77c23db3b2ba2..0159ede648136 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -22,26 +22,23 @@ //! `XcmRouter` <- `MessageDispatch` <- `InboundMessageQueue` use bp_messages::{ - source_chain::{MessagesBridge, OnMessagesDelivered}, + source_chain::OnMessagesDelivered, target_chain::{DispatchMessage, MessageDispatch}, LaneId, MessageNonce, }; use bp_runtime::messages::MessageDispatchResult; +pub use bp_xcm_bridge_hub::XcmAsPlainPayload; use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; use codec::{Decode, Encode}; use frame_support::{traits::Get, weights::Weight, CloneNoBound, EqNoBound, PartialEqNoBound}; use pallet_bridge_messages::{ - Config as MessagesConfig, OutboundLanesCongestedSignals, Pallet as MessagesPallet, - WeightInfoExt as MessagesPalletWeights, + Config as MessagesConfig, OutboundLanesCongestedSignals, WeightInfoExt as MessagesPalletWeights, }; use scale_info::TypeInfo; use sp_runtime::SaturatedConversion; use sp_std::{fmt::Debug, marker::PhantomData}; use xcm::prelude::*; -use xcm_builder::{DispatchBlob, DispatchBlobError, HaulBlob, HaulBlobError}; - -/// Plain "XCM" payload, which we transfer through bridge -pub type XcmAsPlainPayload = sp_std::prelude::Vec; +use xcm_builder::{DispatchBlob, DispatchBlobError}; /// Message dispatch result type for single message #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] @@ -123,6 +120,7 @@ impl< /// A pair of sending chain location and message lane, used by this chain to send messages /// over the bridge. +#[cfg_attr(feature = "std", derive(Debug, Eq, PartialEq))] pub struct SenderAndLane { /// Sending chain relative location. pub location: MultiLocation, @@ -144,8 +142,6 @@ pub trait XcmBlobHauler { type Runtime: MessagesConfig; /// Instance of the messages pallet that is used to send messages. type MessagesInstance: 'static; - /// Returns lane used by this hauler. - type SenderAndLane: Get; /// Actual XCM message sender (`HRMP` or `UMP`) to the source chain /// location (`Self::SenderAndLane::get().location`). @@ -166,54 +162,25 @@ pub trait XcmBlobHauler { /// makes sure that XCM blob is sent to the outbound lane to be relayed. /// /// It needs to be used at the source bridge hub. -pub struct XcmBlobHaulerAdapter(sp_std::marker::PhantomData); +pub struct XcmBlobHaulerAdapter( + sp_std::marker::PhantomData<(XcmBlobHauler, Lanes)>, +); -impl HaulBlob for XcmBlobHaulerAdapter -where - H::Runtime: MessagesConfig, +impl< + H: XcmBlobHauler, + Lanes: Get>, + > OnMessagesDelivered for XcmBlobHaulerAdapter { - fn haul_blob(blob: sp_std::prelude::Vec) -> Result<(), HaulBlobError> { - let sender_and_lane = H::SenderAndLane::get(); - MessagesPallet::::send_message(sender_and_lane.lane, blob) - .map(|artifacts| { - log::info!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - ok: {:?} on lane: {:?}. Enqueued messages: {}", - artifacts.nonce, - sender_and_lane.lane, - artifacts.enqueued_messages, - ); - - // notify XCM queue manager about updated lane state - LocalXcmQueueManager::::on_bridge_message_enqueued( - &sender_and_lane, - artifacts.enqueued_messages, - ); - }) - .map_err(|error| { - log::error!( - target: crate::LOG_TARGET_BRIDGE_DISPATCH, - "haul_blob result - error: {:?} on lane: {:?}", - error, - sender_and_lane.lane, - ); - HaulBlobError::Transport("MessageSenderError") - }) - } -} - -impl OnMessagesDelivered for XcmBlobHaulerAdapter { fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) { - let sender_and_lane = H::SenderAndLane::get(); - if sender_and_lane.lane != lane { - return + if let Some(sender_and_lane) = + Lanes::get().iter().find(|link| link.0.lane == lane).map(|link| &link.0) + { + // notify XCM queue manager about updated lane state + LocalXcmQueueManager::::on_bridge_messages_delivered( + sender_and_lane, + enqueued_messages, + ); } - - // notify XCM queue manager about updated lane state - LocalXcmQueueManager::::on_bridge_messages_delivered( - &sender_and_lane, - enqueued_messages, - ); } } @@ -356,6 +323,9 @@ mod tests { location: MultiLocation::new(1, X1(Parachain(1000))), lane: TEST_LANE_ID, }; + pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![ + (TestSenderAndLane::get(), (NetworkId::ByGenesis([0; 32]), InteriorMultiLocation::Here)) + ]; pub DummyXcmMessage: Xcm<()> = Xcm::new(); } @@ -389,37 +359,44 @@ mod tests { impl XcmBlobHauler for TestBlobHauler { type Runtime = TestRuntime; type MessagesInstance = (); - type SenderAndLane = TestSenderAndLane; type ToSourceChainSender = DummySendXcm; type CongestedMessage = DummyXcmMessage; type UncongestedMessage = DummyXcmMessage; } - type TestBlobHaulerAdapter = XcmBlobHaulerAdapter; + type TestBlobHaulerAdapter = XcmBlobHaulerAdapter; - fn fill_up_lane_to_congestion() { + fn fill_up_lane_to_congestion() -> MessageNonce { + let latest_generated_nonce = OUTBOUND_LANE_CONGESTED_THRESHOLD; OutboundLanes::::insert( TEST_LANE_ID, OutboundLaneData { oldest_unpruned_nonce: 0, latest_received_nonce: 0, - latest_generated_nonce: OUTBOUND_LANE_CONGESTED_THRESHOLD, + latest_generated_nonce, }, ); + latest_generated_nonce } #[test] fn congested_signal_is_not_sent_twice() { run_test(|| { - fill_up_lane_to_congestion(); + let enqueued = fill_up_lane_to_congestion(); // next sent message leads to congested signal - TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + LocalXcmQueueManager::::on_bridge_message_enqueued( + &TestSenderAndLane::get(), + enqueued + 1, + ); assert_eq!(DummySendXcm::messages_sent(), 1); // next sent message => we don't sent another congested signal - TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + LocalXcmQueueManager::::on_bridge_message_enqueued( + &TestSenderAndLane::get(), + enqueued, + ); assert_eq!(DummySendXcm::messages_sent(), 1); }); } @@ -427,7 +404,10 @@ mod tests { #[test] fn congested_signal_is_not_sent_when_outbound_lane_is_not_congested() { run_test(|| { - TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + LocalXcmQueueManager::::on_bridge_message_enqueued( + &TestSenderAndLane::get(), + 1, + ); assert_eq!(DummySendXcm::messages_sent(), 0); }); } @@ -435,10 +415,13 @@ mod tests { #[test] fn congested_signal_is_sent_when_outbound_lane_is_congested() { run_test(|| { - fill_up_lane_to_congestion(); + let enqueued = fill_up_lane_to_congestion(); // next sent message leads to congested signal - TestBlobHaulerAdapter::haul_blob(vec![42]).unwrap(); + LocalXcmQueueManager::::on_bridge_message_enqueued( + &TestSenderAndLane::get(), + enqueued + 1, + ); assert_eq!(DummySendXcm::messages_sent(), 1); assert!(LocalXcmQueueManager::::is_congested_signal_sent(TEST_LANE_ID)); }); diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml new file mode 100644 index 0000000000000..151b19a527185 --- /dev/null +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -0,0 +1,74 @@ +[package] +name = "pallet-xcm-bridge-hub" +description = "Module that adds dynamic bridges/lanes support to XCM infrastucture at the bridge hub." +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +log = { version = "0.4.20", default-features = false } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } + +# Bridge Dependencies +bp-messages = { path = "../../primitives/messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } +bp-xcm-bridge-hub = { path = "../../primitives/xcm-bridge-hub", default-features = false } +pallet-bridge-messages = { path = "../messages", default-features = false } +bridge-runtime-common = { path = "../../bin/runtime-common", default-features = false } + +# Substrate Dependencies +frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +frame-system = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +# Polkadot Dependencies +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +[dev-dependencies] +bp-header-chain = { path = "../../primitives/header-chain" } +pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } + +[features] +default = ["std"] +std = [ + "bp-messages/std", + "bp-runtime/std", + "bp-xcm-bridge-hub/std", + "bridge-runtime-common/std", + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "pallet-bridge-messages/std", + "scale-info/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", +] +runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-bridge-messages/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/modules/xcm-bridge-hub/src/exporter.rs b/modules/xcm-bridge-hub/src/exporter.rs new file mode 100644 index 0000000000000..445551d693430 --- /dev/null +++ b/modules/xcm-bridge-hub/src/exporter.rs @@ -0,0 +1,208 @@ +// 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 . + +//! The code that allows to use the pallet (`pallet-xcm-bridge-hub`) as XCM message +//! exporter at the sending bridge hub. Internally, it just enqueues outbound blob +//! in the messages pallet queue. +//! +//! This code is executed at the source bridge hub. + +use crate::{Config, Pallet, LOG_TARGET}; + +use bp_messages::source_chain::MessagesBridge; +use bp_xcm_bridge_hub::XcmAsPlainPayload; +use bridge_runtime_common::messages_xcm_extension::{LocalXcmQueueManager, SenderAndLane}; +use pallet_bridge_messages::{Config as BridgeMessagesConfig, Pallet as BridgeMessagesPallet}; +use xcm::prelude::*; +use xcm_builder::{HaulBlob, HaulBlobError, HaulBlobExporter}; +use xcm_executor::traits::ExportXcm; + +/// An easy way to access `HaulBlobExporter`. +pub type PalletAsHaulBlobExporter = HaulBlobExporter< + DummyHaulBlob, + >::BridgedNetworkId, + >::MessageExportPrice, +>; +/// An easy way to access associated messages pallet. +type MessagesPallet = BridgeMessagesPallet>::BridgeMessagesPalletInstance>; + +impl, I: 'static> ExportXcm for Pallet +where + T: BridgeMessagesConfig< + >::BridgeMessagesPalletInstance, + OutboundPayload = XcmAsPlainPayload, + >, +{ + type Ticket = (SenderAndLane, XcmAsPlainPayload, XcmHash); + + fn validate( + network: NetworkId, + channel: u32, + universal_source: &mut Option, + destination: &mut Option, + message: &mut Option>, + ) -> Result<(Self::Ticket, MultiAssets), SendError> { + // Find supported lane_id. + let sender_and_lane = Self::lane_for( + universal_source.as_ref().ok_or(SendError::MissingArgument)?, + (&network, destination.as_ref().ok_or(SendError::MissingArgument)?), + ) + .ok_or(SendError::NotApplicable)?; + + // check if we are able to route the message. We use existing `HaulBlobExporter` for that. + // It will make all required changes and will encode message properly, so that the + // `DispatchBlob` at the bridged bridge hub will be able to decode it + let ((blob, id), price) = PalletAsHaulBlobExporter::::validate( + network, + channel, + universal_source, + destination, + message, + )?; + + Ok(((sender_and_lane, blob, id), price)) + } + + fn deliver( + (sender_and_lane, blob, id): (SenderAndLane, XcmAsPlainPayload, XcmHash), + ) -> Result { + let lane_id = sender_and_lane.lane; + let send_result = MessagesPallet::::send_message(lane_id, blob); + + match send_result { + Ok(artifacts) => { + log::info!( + target: LOG_TARGET, + "XCM message {:?} has been enqueued at bridge {:?} with nonce {}", + id, + lane_id, + artifacts.nonce, + ); + + // notify XCM queue manager about updated lane state + LocalXcmQueueManager::::on_bridge_message_enqueued( + &sender_and_lane, + artifacts.enqueued_messages, + ); + }, + Err(error) => { + log::debug!( + target: LOG_TARGET, + "XCM message {:?} has been dropped because of bridge error {:?} on bridge {:?}", + id, + error, + lane_id, + ); + return Err(SendError::Transport("BridgeSendError")) + }, + } + + Ok(id) + } +} + +/// Dummy implementation of the `HaulBlob` trait that is never called. +/// +/// We are using `HaulBlobExporter`, which requires `HaulBlob` implementation. It assumes that +/// there's a single channel between two bridge hubs - `HaulBlob` only accepts the blob and nothing +/// else. But bridge messages pallet may have a dedicated channel (lane) for every pair of bridged +/// chains. So we are using our own `ExportXcm` implementation, but to utilize `HaulBlobExporter` we +/// still need this `DummyHaulBlob`. +pub struct DummyHaulBlob; + +impl HaulBlob for DummyHaulBlob { + fn haul_blob(_blob: XcmAsPlainPayload) -> Result<(), HaulBlobError> { + Err(HaulBlobError::Transport("DummyHaulBlob")) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::*; + use frame_support::assert_ok; + use xcm_executor::traits::export_xcm; + + fn universal_source() -> InteriorMultiLocation { + X2(GlobalConsensus(RelayNetwork::get()), Parachain(SIBLING_ASSET_HUB_ID)) + } + + fn universal_destination() -> InteriorMultiLocation { + BridgedDestination::get() + } + + #[test] + fn export_works() { + run_test(|| { + assert_ok!(export_xcm::( + BridgedRelayNetwork::get(), + 0, + universal_source(), + universal_destination(), + vec![Instruction::ClearOrigin].into(), + )); + }) + } + + #[test] + fn export_fails_if_argument_is_missing() { + run_test(|| { + assert_eq!( + XcmOverBridge::validate( + BridgedRelayNetwork::get(), + 0, + &mut None, + &mut Some(universal_destination()), + &mut Some(Vec::new().into()), + ), + Err(SendError::MissingArgument), + ); + + assert_eq!( + XcmOverBridge::validate( + BridgedRelayNetwork::get(), + 0, + &mut Some(universal_source()), + &mut None, + &mut Some(Vec::new().into()), + ), + Err(SendError::MissingArgument), + ); + }) + } + + #[test] + fn exporter_computes_correct_lane_id() { + run_test(|| { + let expected_lane_id = TEST_LANE_ID; + + assert_eq!( + XcmOverBridge::validate( + BridgedRelayNetwork::get(), + 0, + &mut Some(universal_source()), + &mut Some(universal_destination()), + &mut Some(Vec::new().into()), + ) + .unwrap() + .0 + .0 + .lane, + expected_lane_id, + ); + }) + } +} diff --git a/modules/xcm-bridge-hub/src/lib.rs b/modules/xcm-bridge-hub/src/lib.rs new file mode 100644 index 0000000000000..14439a4d8ffe8 --- /dev/null +++ b/modules/xcm-bridge-hub/src/lib.rs @@ -0,0 +1,96 @@ +// 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 . + +//! Module that adds XCM support to bridge pallets. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +use bridge_runtime_common::messages_xcm_extension::XcmBlobHauler; +use pallet_bridge_messages::Config as BridgeMessagesConfig; +use xcm::prelude::*; + +pub use exporter::PalletAsHaulBlobExporter; +pub use pallet::*; + +mod exporter; +mod mock; + +/// The target that will be used when publishing logs related to this pallet. +pub const LOG_TARGET: &str = "runtime::bridge-xcm"; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use bridge_runtime_common::messages_xcm_extension::SenderAndLane; + use frame_support::pallet_prelude::*; + + #[pallet::config] + #[pallet::disable_frame_system_supertrait_check] + pub trait Config: + BridgeMessagesConfig + { + /// Runtime's universal location. + type UniversalLocation: Get; + // TODO: https://github.com/paritytech/parity-bridges-common/issues/1666 remove `ChainId` and + // replace it with the `NetworkId` - then we'll be able to use + // `T as pallet_bridge_messages::Config::BridgedChain::NetworkId` + /// Bridged network id. + #[pallet::constant] + type BridgedNetworkId: Get; + /// Associated messages pallet instance that bridges us with the + /// `BridgedNetworkId` consensus. + type BridgeMessagesPalletInstance: 'static; + + /// Price of single message export to the bridged consensus (`Self::BridgedNetworkId`). + type MessageExportPrice: Get; + + /// Get point-to-point links with bridged consensus (`Self::BridgedNetworkId`). + /// (this will be replaced with dynamic on-chain bridges - `Bridges V2`) + type Lanes: Get>; + /// Support for point-to-point links + /// (this will be replaced with dynamic on-chain bridges - `Bridges V2`) + type LanesSupport: XcmBlobHauler; + } + + #[pallet::pallet] + pub struct Pallet(PhantomData<(T, I)>); + + impl, I: 'static> Pallet { + /// Returns dedicated/configured lane identifier. + pub(crate) fn lane_for( + source: &InteriorMultiLocation, + dest: (&NetworkId, &InteriorMultiLocation), + ) -> Option { + let source = source.relative_to(&T::UniversalLocation::get()); + + // Check that we have configured a point-to-point lane for 'source' and `dest`. + T::Lanes::get() + .into_iter() + .find_map(|(lane_source, (lane_dest_network, lane_dest))| { + if lane_source.location == source && + &lane_dest_network == dest.0 && + &T::BridgedNetworkId::get() == dest.0 && + &lane_dest == dest.1 + { + Some(lane_source) + } else { + None + } + }) + } + } +} diff --git a/modules/xcm-bridge-hub/src/mock.rs b/modules/xcm-bridge-hub/src/mock.rs new file mode 100644 index 0000000000000..7766aac1fb73f --- /dev/null +++ b/modules/xcm-bridge-hub/src/mock.rs @@ -0,0 +1,328 @@ +// 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 . + +#![cfg(test)] + +use crate as pallet_xcm_bridge_hub; + +use bp_messages::{ + source_chain::LaneMessageVerifier, + target_chain::{DispatchMessage, MessageDispatch}, + LaneId, OutboundLaneData, VerificationError, +}; +use bp_runtime::{messages::MessageDispatchResult, Chain, UnderlyingChainProvider}; +use bridge_runtime_common::{ + messages::{ + source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, + BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages, + }, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler}, +}; +use codec::Encode; +use frame_support::{derive_impl, parameter_types, traits::ConstU32, weights::RuntimeDbWeight}; +use sp_core::H256; +use sp_runtime::{ + testing::Header as SubstrateHeader, + traits::{BlakeTwo256, IdentityLookup}, + AccountId32, BuildStorage, +}; +use xcm::prelude::*; + +pub type AccountId = AccountId32; +pub type Balance = u64; + +type Block = frame_system::mocking::MockBlock; + +pub const SIBLING_ASSET_HUB_ID: u32 = 2001; +pub const THIS_BRIDGE_HUB_ID: u32 = 2002; +pub const BRIDGED_ASSET_HUB_ID: u32 = 1001; +pub const TEST_LANE_ID: LaneId = LaneId([0, 0, 0, 1]); + +frame_support::construct_runtime! { + pub enum TestRuntime { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Event}, + Messages: pallet_bridge_messages::{Pallet, Call, Event}, + XcmOverBridge: pallet_xcm_bridge_hub::{Pallet}, + } +} + +parameter_types! { + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { read: 1, write: 2 }; + pub const ExistentialDeposit: Balance = 1; +} + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +impl frame_system::Config for TestRuntime { + type AccountId = AccountId; + type AccountData = pallet_balances::AccountData; + type Block = Block; + type Lookup = IdentityLookup; +} + +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +impl pallet_balances::Config for TestRuntime { + type AccountStore = System; +} + +/// Lane message verifier that is used in tests. +#[derive(Debug, Default)] +pub struct TestLaneMessageVerifier; + +impl LaneMessageVerifier> for TestLaneMessageVerifier { + fn verify_message( + _lane: &LaneId, + _lane_outbound_data: &OutboundLaneData, + _payload: &Vec, + ) -> Result<(), VerificationError> { + Ok(()) + } +} + +parameter_types! { + pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID]; +} + +impl pallet_bridge_messages::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = TestMessagesWeights; + + type BridgedChainId = (); + type ActiveOutboundLanes = ActiveOutboundLanes; + type MaxUnrewardedRelayerEntriesAtInboundLane = (); + type MaxUnconfirmedMessagesAtInboundLane = (); + type MaximalOutboundPayloadSize = ConstU32<2048>; + type OutboundPayload = Vec; + type InboundPayload = Vec; + type InboundRelayer = (); + type DeliveryPayments = (); + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = TestLaneMessageVerifier; + type DeliveryConfirmationPayments = (); + type OnMessagesDelivered = (); + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = TestMessageDispatch; +} + +pub struct TestMessagesWeights; + +impl pallet_bridge_messages::WeightInfo for TestMessagesWeights { + fn receive_single_message_proof() -> Weight { + Weight::zero() + } + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + Weight::zero() + } + fn receive_delivery_proof_for_single_message() -> Weight { + Weight::zero() + } + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + Weight::zero() + } + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + Weight::zero() + } + + fn receive_two_messages_proof() -> Weight { + Weight::zero() + } + + fn receive_single_message_proof_1_kb() -> Weight { + Weight::zero() + } + + fn receive_single_message_proof_16_kb() -> Weight { + Weight::zero() + } + + fn receive_single_message_proof_with_dispatch(_: u32) -> Weight { + Weight::from_parts(1, 0) + } +} + +impl pallet_bridge_messages::WeightInfoExt for TestMessagesWeights { + fn expected_extra_storage_proof_size() -> u32 { + 0 + } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + Weight::zero() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + Weight::zero() + } +} + +parameter_types! { + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub const BridgedRelayNetwork: NetworkId = NetworkId::Polkadot; + pub const NonBridgedRelayNetwork: NetworkId = NetworkId::Rococo; + pub const BridgeReserve: Balance = 100_000; + pub UniversalLocation: InteriorMultiLocation = X2( + GlobalConsensus(RelayNetwork::get()), + Parachain(THIS_BRIDGE_HUB_ID), + ); + pub const Penalty: Balance = 1_000; +} + +impl pallet_xcm_bridge_hub::Config for TestRuntime { + type UniversalLocation = UniversalLocation; + type BridgedNetworkId = BridgedRelayNetwork; + type BridgeMessagesPalletInstance = (); + + type MessageExportPrice = (); + type Lanes = TestLanes; + type LanesSupport = TestXcmBlobHauler; +} + +parameter_types! { + pub TestSenderAndLane: SenderAndLane = SenderAndLane { + location: MultiLocation::new(1, X1(Parachain(SIBLING_ASSET_HUB_ID))), + lane: TEST_LANE_ID, + }; + pub const BridgedDestination: InteriorMultiLocation = X1( + Parachain(BRIDGED_ASSET_HUB_ID) + ); + pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![ + (TestSenderAndLane::get(), (BridgedRelayNetwork::get(), BridgedDestination::get())) + ]; +} + +pub struct TestXcmBlobHauler; +impl XcmBlobHauler for TestXcmBlobHauler { + type Runtime = TestRuntime; + type MessagesInstance = (); + type ToSourceChainSender = (); + type CongestedMessage = (); + type UncongestedMessage = (); +} + +pub struct ThisChain; + +impl Chain for ThisChain { + type BlockNumber = u64; + type Hash = H256; + type Hasher = BlakeTwo256; + type Header = SubstrateHeader; + type AccountId = AccountId; + type Balance = Balance; + type Nonce = u64; + type Signature = sp_runtime::MultiSignature; + + fn max_extrinsic_size() -> u32 { + u32::MAX + } + + fn max_extrinsic_weight() -> Weight { + Weight::MAX + } +} + +pub struct BridgedChain; +pub type BridgedHeaderHash = H256; +pub type BridgedChainHeader = SubstrateHeader; + +impl Chain for BridgedChain { + type BlockNumber = u64; + type Hash = BridgedHeaderHash; + type Hasher = BlakeTwo256; + type Header = BridgedChainHeader; + type AccountId = AccountId; + type Balance = Balance; + type Nonce = u64; + type Signature = sp_runtime::MultiSignature; + + fn max_extrinsic_size() -> u32 { + 4096 + } + + fn max_extrinsic_weight() -> Weight { + Weight::MAX + } +} + +/// Test message dispatcher. +pub struct TestMessageDispatch; + +impl TestMessageDispatch { + pub fn deactivate(lane: LaneId) { + frame_support::storage::unhashed::put(&(b"inactive", lane).encode()[..], &false); + } +} + +impl MessageDispatch for TestMessageDispatch { + type DispatchPayload = Vec; + type DispatchLevelResult = (); + + fn is_active() -> bool { + frame_support::storage::unhashed::take::(&(b"inactive").encode()[..]) != Some(false) + } + + fn dispatch_weight(_message: &mut DispatchMessage) -> Weight { + Weight::zero() + } + + fn dispatch( + _: DispatchMessage, + ) -> MessageDispatchResult { + MessageDispatchResult { unspent_weight: Weight::zero(), dispatch_level_result: () } + } +} + +pub struct WrappedThisChain; +impl UnderlyingChainProvider for WrappedThisChain { + type Chain = ThisChain; +} +impl ThisChainWithMessages for WrappedThisChain { + type RuntimeOrigin = RuntimeOrigin; +} + +pub struct WrappedBridgedChain; +impl UnderlyingChainProvider for WrappedBridgedChain { + type Chain = BridgedChain; +} +impl BridgedChainWithMessages for WrappedBridgedChain {} + +pub struct BridgedHeaderChain; +impl bp_header_chain::HeaderChain for BridgedHeaderChain { + fn finalized_header_state_root( + _hash: HashOf, + ) -> Option> { + unreachable!() + } +} + +/// Bridge that is deployed on `ThisChain` and allows sending/receiving messages to/from +/// `BridgedChain`. +#[derive(Debug, PartialEq, Eq)] +pub struct OnThisChainBridge; + +impl MessageBridge for OnThisChainBridge { + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = ""; + + type ThisChain = WrappedThisChain; + type BridgedChain = WrappedBridgedChain; + type BridgedHeaderChain = BridgedHeaderChain; +} + +/// Run pallet test. +pub fn run_test(test: impl FnOnce() -> T) -> T { + sp_io::TestExternalities::new( + frame_system::GenesisConfig::::default().build_storage().unwrap(), + ) + .execute_with(test) +} diff --git a/primitives/xcm-bridge-hub/Cargo.toml b/primitives/xcm-bridge-hub/Cargo.toml new file mode 100644 index 0000000000000..761fbef46e22c --- /dev/null +++ b/primitives/xcm-bridge-hub/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "bp-xcm-bridge-hub" +description = "Primitives of the xcm-bridge-hub pallet." +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + +[dependencies] + +# Substrate Dependencies +sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } + +[features] +default = ["std"] +std = ["sp-std/std"] diff --git a/primitives/xcm-bridge-hub/src/lib.rs b/primitives/xcm-bridge-hub/src/lib.rs new file mode 100644 index 0000000000000..9745011c902d2 --- /dev/null +++ b/primitives/xcm-bridge-hub/src/lib.rs @@ -0,0 +1,24 @@ +// 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 . + +//! Primitives of the xcm-bridge-hub pallet. + +#![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] + +/// Encoded XCM blob. We expect the bridge messages pallet to use this blob type for both inbound +/// and outbound payloads. +pub type XcmAsPlainPayload = sp_std::vec::Vec; From 2ac41b8114ba389397b0a30087609ef98e2f5572 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 02:28:14 +0000 Subject: [PATCH 1157/1210] Bump tokio from 1.34.0 to 1.35.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.34.0 to 1.35.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.34.0...tokio-1.35.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index f4944ac972d4d..9f710ec3c9fa4 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -15,7 +15,7 @@ log = "0.4.20" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } -tokio = { version = "1.34", features = ["rt-multi-thread"] } +tokio = { version = "1.35", features = ["rt-multi-thread"] } thiserror = "1.0.50" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index a41beb9e52f85..6f1546e09f268 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -20,7 +20,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.34", features = ["rt"] } +tokio = { version = "1.35", features = ["rt"] } thiserror = "1.0.50" # Bridge dependencies From 27c5afe21da53f6a8e6a3e19595ddacd0298915c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 14 Dec 2023 17:03:35 +0300 Subject: [PATCH 1158/1210] Added Rococo BH <> Rococo Bulletin bridge (#2724) * added Rococo BH <> Rococo Bulletin bridge * init-bridge support * allow customising finality-related runtime APIs * revert me * use Rococo/BridgeHubRococo pretending to be a Polkadot/BridgeHubPolkadot in Rococo <> RococoBulletin bridge * Revert "revert me" This reverts commit 90c598d9d50a25e7182c97eee7818bf8d4bc404c. * Revert "allow customising finality-related runtime APIs" This reverts commit b39c32c34acddfd0b919042122e0e667470bd0a4. * fmt * WITH_BRIDGE_ROCOCO_TO_BULLETIN_MESSAGES_PALLET_INDEX * regenerate bulletin chain runtime (pallet indices have changed) * fx WITH_BRIDGE_ROCOCO_TO_BULLETIN_MESSAGES_PALLET_INDEX constant because of latest changes * also change indices in runtime * fmt * clippy --- modules/beefy/src/mock.rs | 2 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 2 + primitives/runtime/src/chain.rs | 12 +- relays/bin-substrate/Cargo.toml | 4 + relays/bin-substrate/src/bridges/mod.rs | 1 + ..._polkadot_messages_to_polkadot_bulletin.rs | 4 +- ...ulletin_messages_to_bridge_hub_polkadot.rs | 4 +- ..._hub_rococo_messages_to_rococo_bulletin.rs | 65 + .../src/bridges/rococo_bulletin/mod.rs | 259 +++ ...o_bulletin_headers_to_bridge_hub_rococo.rs | 86 + ..._bulletin_messages_to_bridge_hub_rococo.rs | 65 + .../rococo_headers_to_rococo_bulletin.rs | 81 + .../rococo_parachains_to_rococo_bulletin.rs | 91 ++ relays/bin-substrate/src/cli/bridge.rs | 2 + relays/bin-substrate/src/cli/init_bridge.rs | 39 + relays/bin-substrate/src/cli/relay_headers.rs | 12 + .../src/cli/relay_headers_and_messages/mod.rs | 45 + .../bin-substrate/src/cli/relay_messages.rs | 10 + .../bin-substrate/src/cli/relay_parachains.rs | 5 + .../src/codegen_runtime.rs | 1445 ++++++++++++----- relays/client-bridge-hub-rococo/src/lib.rs | 2 + .../src/codegen_runtime.rs | 316 +++- relays/client-polkadot-bulletin/src/lib.rs | 2 +- relays/client-substrate/src/chain.rs | 18 + 24 files changed, 2077 insertions(+), 495 deletions(-) create mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs create mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index 0b0084609cc55..f89fd1e63480c 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -163,7 +163,7 @@ pub fn validator_ids(index: u32, count: u32) -> Vec { validator_pairs(index, count).into_iter().map(|pair| pair.public()).collect() } -pub fn authority_set_info(id: u64, validators: &Vec) -> TestBridgedAuthoritySetInfo { +pub fn authority_set_info(id: u64, validators: &[BeefyId]) -> TestBridgedAuthoritySetInfo { let merkle_root = get_authorities_mmr_root::(validators.iter()); TestBridgedAuthoritySetInfo { id, len: validators.len() as u32, keyset_commitment: merkle_root } diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 59d293edf1c24..1fe44597c3d40 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -76,6 +76,8 @@ pub const WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; /// Pallet index of `BridgeWestendMessages: pallet_bridge_messages::`. pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 51; +/// Pallet index of `BridgePolkadotBulletinMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_ROCOCO_TO_BULLETIN_MESSAGES_PALLET_INDEX: u8 = 61; decl_bridge_finality_runtime_apis!(bridge_hub_rococo); decl_bridge_messages_runtime_apis!(bridge_hub_rococo); diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index b78023efb1b86..469c839ba151f 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use crate::HeaderIdProvider; -use codec::{Decode, Encode, MaxEncodedLen}; +use codec::{Codec, Decode, Encode, MaxEncodedLen}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ @@ -39,7 +39,7 @@ pub enum EncodedOrDecodedCall { Decoded(ChainCall), } -impl EncodedOrDecodedCall { +impl EncodedOrDecodedCall { /// Returns decoded call. pub fn to_decoded(&self) -> Result { match self { @@ -57,6 +57,14 @@ impl EncodedOrDecodedCall { Self::Decoded(decoded_call) => Ok(decoded_call), } } + + /// Converts self to encoded call. + pub fn into_encoded(self) -> Vec { + match self { + Self::Encoded(encoded_call) => encoded_call, + Self::Decoded(decoded_call) => decoded_call.encode(), + } + } } impl From for EncodedOrDecodedCall { diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index a850f15ed4673..6b9114e3d7e53 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -23,11 +23,15 @@ signal-hook-async-std = "0.2.2" strum = { version = "0.25.0", features = ["derive"] } # Bridge dependencies +bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } +bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } +bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } +bp-rococo = { path = "../../primitives/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } pallet-bridge-parachains = { path = "../../modules/parachains" } diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs index 8dad329cf73be..cfe59c87567da 100644 --- a/relays/bin-substrate/src/bridges/mod.rs +++ b/relays/bin-substrate/src/bridges/mod.rs @@ -18,4 +18,5 @@ pub mod kusama_polkadot; pub mod polkadot_bulletin; +pub mod rococo_bulletin; pub mod rococo_westend; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs index 614b42de4ed89..ba80d96a93cc2 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs @@ -36,8 +36,8 @@ impl MessagesCliBridge for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane, BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotBridgeHubMessages, - relay_polkadot_bulletin_client::BridgePolkadotBridgeHubMessagesCall::receive_messages_proof + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, + relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs index ddfbcea495f90..1db77b6ed47b0 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs @@ -43,8 +43,8 @@ substrate_relay_helper::generate_receive_message_proof_call_builder!( substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane, PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotBridgeHubMessages, - relay_polkadot_bulletin_client::BridgePolkadotBridgeHubMessagesCall::receive_messages_delivery_proof + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, + relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_delivery_proof ); /// PolkadotBulletin-to-BridgeHubPolkadot messages lane. diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs new file mode 100644 index 0000000000000..a2de83831c9bf --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs @@ -0,0 +1,65 @@ +// Copyright 2022 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 . + +//! BridgeHubRococo-to-RococoBulletin messages sync entrypoint. + +use super::BridgeHubRococoAsBridgeHubPolkadot; +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +/// BridgeHubRococo-to-RococoBulletin messages bridge. +pub struct BridgeHubRococoToRococoBulletinMessagesCliBridge {} + +impl CliBridgeBase for BridgeHubRococoToRococoBulletinMessagesCliBridge { + type Source = BridgeHubRococoAsBridgeHubPolkadot; + type Target = RococoBulletin; +} + +impl MessagesCliBridge for BridgeHubRococoToRococoBulletinMessagesCliBridge { + type MessagesLane = BridgeHubRococoMessagesToRococoBulletinMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + BridgeHubRococoMessagesToRococoBulletinMessageLane, + BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesProofCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, + relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + BridgeHubRococoMessagesToRococoBulletinMessageLane, + BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinMessages, + relay_bridge_hub_rococo_client::BridgeBulletinMessagesCall::receive_messages_delivery_proof +); + +/// BridgeHubRococo-to-RococoBulletin messages lane. +#[derive(Clone, Debug)] +pub struct BridgeHubRococoMessagesToRococoBulletinMessageLane; + +impl SubstrateMessageLane for BridgeHubRococoMessagesToRococoBulletinMessageLane { + type SourceChain = BridgeHubRococoAsBridgeHubPolkadot; + type TargetChain = RococoBulletin; + + type ReceiveMessagesProofCallBuilder = + BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; + type TargetBatchCallBuilder = (); +} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs new file mode 100644 index 0000000000000..7760913f61c83 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs @@ -0,0 +1,259 @@ +// 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 . + +//! Declaration of all bridges between Rococo Bulletin Chain and Rococo Bridge Hub. + +use crate::cli::CliChain; + +use bp_messages::MessageNonce; +use bp_runtime::{ + AccountIdOf, BalanceOf, BlockNumberOf, ChainId, HashOf, HasherOf, HeaderOf, NonceOf, + SignatureOf, +}; +use frame_support::pallet_prelude::Weight; +use relay_substrate_client::{ + Error as SubstrateError, SignParam, SimpleRuntimeVersion, UnsignedTransaction, +}; +use sp_core::storage::StorageKey; +use std::time::Duration; + +pub mod bridge_hub_rococo_messages_to_rococo_bulletin; +pub mod rococo_bulletin_headers_to_bridge_hub_rococo; +pub mod rococo_bulletin_messages_to_bridge_hub_rococo; +pub mod rococo_headers_to_rococo_bulletin; +pub mod rococo_parachains_to_rococo_bulletin; + +/// Base `Chain` implementation of Rococo, pretending to be Polkadot. +pub struct RococoBaseAsPolkadot; + +impl bp_runtime::Chain for RococoBaseAsPolkadot { + type BlockNumber = BlockNumberOf; + type Hash = HashOf; + type Hasher = HasherOf; + type Header = HeaderOf; + + type AccountId = AccountIdOf; + type Balance = BalanceOf; + type Nonce = NonceOf; + type Signature = SignatureOf; + + fn max_extrinsic_size() -> u32 { + bp_rococo::Rococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_rococo::Rococo::max_extrinsic_weight() + } +} + +impl bp_header_chain::ChainWithGrandpa for RococoBaseAsPolkadot { + const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = + bp_polkadot::Polkadot::WITH_CHAIN_GRANDPA_PALLET_NAME; + const MAX_AUTHORITIES_COUNT: u32 = bp_rococo::Rococo::MAX_AUTHORITIES_COUNT; + const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = + bp_rococo::Rococo::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const MAX_HEADER_SIZE: u32 = bp_rococo::Rococo::MAX_HEADER_SIZE; + const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = + bp_rococo::Rococo::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; +} + +/// Relay `Chain` implementation of Rococo, pretending to be Polkadot. +#[derive(Debug, Clone, Copy)] +pub struct RococoAsPolkadot; + +impl bp_runtime::UnderlyingChainProvider for RococoAsPolkadot { + type Chain = RococoBaseAsPolkadot; +} + +impl relay_substrate_client::Chain for RococoAsPolkadot { + const ID: ChainId = relay_rococo_client::Rococo::ID; + const NAME: &'static str = relay_rococo_client::Rococo::NAME; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + relay_polkadot_client::Polkadot::BEST_FINALIZED_HEADER_ID_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = relay_rococo_client::Rococo::AVERAGE_BLOCK_INTERVAL; + + type SignedBlock = ::SignedBlock; + type Call = ::Call; +} + +impl relay_substrate_client::ChainWithGrandpa for RococoAsPolkadot { + const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = + relay_polkadot_client::Polkadot::SYNCED_HEADERS_GRANDPA_INFO_METHOD; + + type KeyOwnerProof = + ::KeyOwnerProof; +} + +impl relay_substrate_client::ChainWithBalances for RococoAsPolkadot { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + relay_rococo_client::Rococo::account_info_storage_key(account_id) + } +} + +impl relay_substrate_client::RelayChain for RococoAsPolkadot { + const PARAS_PALLET_NAME: &'static str = relay_rococo_client::Rococo::PARAS_PALLET_NAME; +} + +impl relay_substrate_client::ChainWithTransactions for RococoAsPolkadot { + type AccountKeyPair = ::AccountKeyPair; + type SignedTransaction = ::SignedTransaction; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + relay_rococo_client::Rococo::sign_transaction( + SignParam { + spec_version: param.spec_version, + transaction_version: param.transaction_version, + genesis_hash: param.genesis_hash, + signer: param.signer, + }, + unsigned.switch_chain(), + ) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + relay_rococo_client::Rococo::is_signed(tx) + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + relay_rococo_client::Rococo::is_signed_by(signer, tx) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + relay_rococo_client::Rococo::parse_transaction(tx).map(|tx| tx.switch_chain()) + } +} + +impl CliChain for RococoAsPolkadot { + const RUNTIME_VERSION: Option = None; +} + +/// Base `Chain` implementation of Rococo Bridge Hub, pretending to be a Polkadot Bridge Hub. +pub struct BaseBridgeHubRococoAsBridgeHubPolkadot; + +impl bp_runtime::Chain for BaseBridgeHubRococoAsBridgeHubPolkadot { + type BlockNumber = BlockNumberOf; + type Hash = HashOf; + type Hasher = HasherOf; + type Header = HeaderOf; + + type AccountId = AccountIdOf; + type Balance = BalanceOf; + type Nonce = NonceOf; + type Signature = SignatureOf; + + fn max_extrinsic_size() -> u32 { + bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_size() + } + + fn max_extrinsic_weight() -> Weight { + bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_weight() + } +} + +impl bp_runtime::Parachain for BaseBridgeHubRococoAsBridgeHubPolkadot { + const PARACHAIN_ID: u32 = bp_bridge_hub_rococo::BridgeHubRococo::PARACHAIN_ID; +} + +/// Relay `Chain` implementation of Rococo Bridge Hub, pretending to be a Polkadot Bridge Hub. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct BridgeHubRococoAsBridgeHubPolkadot; + +impl bp_runtime::UnderlyingChainProvider for BridgeHubRococoAsBridgeHubPolkadot { + type Chain = BaseBridgeHubRococoAsBridgeHubPolkadot; +} + +impl relay_substrate_client::Chain for BridgeHubRococoAsBridgeHubPolkadot { + const ID: ChainId = relay_bridge_hub_rococo_client::BridgeHubRococo::ID; + const NAME: &'static str = relay_bridge_hub_rococo_client::BridgeHubRococo::NAME; + const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = + relay_bridge_hub_polkadot_client::BridgeHubPolkadot::BEST_FINALIZED_HEADER_ID_METHOD; + const AVERAGE_BLOCK_INTERVAL: Duration = + relay_bridge_hub_rococo_client::BridgeHubRococo::AVERAGE_BLOCK_INTERVAL; + + type SignedBlock = ::SignedBlock; + type Call = + ::Call; +} + +impl relay_substrate_client::ChainWithBalances for BridgeHubRococoAsBridgeHubPolkadot { + fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { + relay_bridge_hub_rococo_client::BridgeHubRococo::account_info_storage_key(account_id) + } +} + +impl relay_substrate_client::ChainWithUtilityPallet for BridgeHubRococoAsBridgeHubPolkadot { + type UtilityPallet = relay_substrate_client::MockedRuntimeUtilityPallet< + relay_bridge_hub_rococo_client::RuntimeCall, + >; +} + +impl relay_substrate_client::ChainWithTransactions for BridgeHubRococoAsBridgeHubPolkadot { + type AccountKeyPair = ::AccountKeyPair; + type SignedTransaction = ::SignedTransaction; + + fn sign_transaction( + param: SignParam, + unsigned: UnsignedTransaction, + ) -> Result { + relay_bridge_hub_rococo_client::BridgeHubRococo::sign_transaction( + SignParam { + spec_version: param.spec_version, + transaction_version: param.transaction_version, + genesis_hash: param.genesis_hash, + signer: param.signer, + }, + unsigned.switch_chain(), + ) + } + + fn is_signed(tx: &Self::SignedTransaction) -> bool { + relay_bridge_hub_rococo_client::BridgeHubRococo::is_signed(tx) + } + + fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { + relay_bridge_hub_rococo_client::BridgeHubRococo::is_signed_by(signer, tx) + } + + fn parse_transaction(tx: Self::SignedTransaction) -> Option> { + relay_bridge_hub_rococo_client::BridgeHubRococo::parse_transaction(tx) + .map(|tx| tx.switch_chain()) + } +} + +impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPolkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_MESSAGES_PALLET_NAME; + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = + relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_RELAYERS_PALLET_NAME; + + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + relay_bridge_hub_polkadot_client::BridgeHubPolkadot::TO_CHAIN_MESSAGE_DETAILS_METHOD; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = + relay_bridge_hub_polkadot_client::BridgeHubPolkadot::FROM_CHAIN_MESSAGE_DETAILS_METHOD; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + +impl CliChain for BridgeHubRococoAsBridgeHubPolkadot { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); +} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..e897cd85967df --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs @@ -0,0 +1,86 @@ +// Copyright 2022 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 . + +//! RococoBulletin-to-BridgeHubRococo headers sync entrypoint. + +use super::BridgeHubRococoAsBridgeHubPolkadot; +use crate::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; + +use async_trait::async_trait; +use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, +}; + +/// Description of `RococoBulletin` -> `RococoBridgeHub` finalized headers bridge. +#[derive(Clone, Debug)] +pub struct RococoBulletinFinalityToBridgeHubRococo; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + RococoBulletinFinalityToBridgeHubRococo, + SubmitFinalityProofCallBuilder, + relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinGrandpa, + relay_bridge_hub_rococo_client::BridgeBulletinGrandpaCall::submit_finality_proof +); + +substrate_relay_helper::generate_report_equivocation_call_builder!( + RococoBulletinFinalityToBridgeHubRococo, + ReportEquivocationCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::Grandpa, + relay_polkadot_bulletin_client::GrandpaCall::report_equivocation +); + +#[async_trait] +impl SubstrateFinalityPipeline for RococoBulletinFinalityToBridgeHubRococo { + type SourceChain = relay_polkadot_bulletin_client::PolkadotBulletin; + type TargetChain = BridgeHubRococoAsBridgeHubPolkadot; + + type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for RococoBulletinFinalityToBridgeHubRococo { + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; +} + +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for RococoBulletinFinalityToBridgeHubRococo { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + +/// `RococoBulletin` to BridgeHub `Rococo` bridge definition. +pub struct RococoBulletinToBridgeHubRococoCliBridge {} + +impl CliBridgeBase for RococoBulletinToBridgeHubRococoCliBridge { + type Source = relay_polkadot_bulletin_client::PolkadotBulletin; + type Target = BridgeHubRococoAsBridgeHubPolkadot; +} + +impl RelayToRelayHeadersCliBridge for RococoBulletinToBridgeHubRococoCliBridge { + type Finality = RococoBulletinFinalityToBridgeHubRococo; +} + +impl RelayToRelayEquivocationDetectionCliBridge for RococoBulletinToBridgeHubRococoCliBridge { + type Equivocation = RococoBulletinFinalityToBridgeHubRococo; +} + +impl MessagesCliBridge for RococoBulletinToBridgeHubRococoCliBridge { + type MessagesLane = crate::bridges::rococo_bulletin::rococo_bulletin_messages_to_bridge_hub_rococo::RococoBulletinMessagesToBridgeHubRococoMessageLane; +} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs new file mode 100644 index 0000000000000..856be9cf6f2a8 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs @@ -0,0 +1,65 @@ +// Copyright 2022 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 . + +//! RococoBulletin-to-BridgeHubRococo messages sync entrypoint. + +use super::BridgeHubRococoAsBridgeHubPolkadot; +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; +use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; +use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; + +/// RococoBulletin-to-BridgeHubRococo messages bridge. +pub struct RococoBulletinToBridgeHubRococoMessagesCliBridge {} + +impl CliBridgeBase for RococoBulletinToBridgeHubRococoMessagesCliBridge { + type Source = RococoBulletin; + type Target = BridgeHubRococoAsBridgeHubPolkadot; +} + +impl MessagesCliBridge for RococoBulletinToBridgeHubRococoMessagesCliBridge { + type MessagesLane = RococoBulletinMessagesToBridgeHubRococoMessageLane; +} + +substrate_relay_helper::generate_receive_message_proof_call_builder!( + RococoBulletinMessagesToBridgeHubRococoMessageLane, + RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, + relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinMessages, + relay_bridge_hub_rococo_client::BridgeBulletinMessagesCall::receive_messages_proof +); + +substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( + RococoBulletinMessagesToBridgeHubRococoMessageLane, + RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, + relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_delivery_proof +); + +/// RococoBulletin-to-BridgeHubRococo messages lane. +#[derive(Clone, Debug)] +pub struct RococoBulletinMessagesToBridgeHubRococoMessageLane; + +impl SubstrateMessageLane for RococoBulletinMessagesToBridgeHubRococoMessageLane { + type SourceChain = RococoBulletin; + type TargetChain = BridgeHubRococoAsBridgeHubPolkadot; + + type ReceiveMessagesProofCallBuilder = + RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; + type ReceiveMessagesDeliveryProofCallBuilder = + RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; + + type SourceBatchCallBuilder = (); + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; +} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs new file mode 100644 index 0000000000000..8a4b44eec27b9 --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs @@ -0,0 +1,81 @@ +// Copyright 2022 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 . + +//! Rococo-to-RococoBulletin headers sync entrypoint. + +use super::RococoAsPolkadot; +use crate::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + +use async_trait::async_trait; +use substrate_relay_helper::{ + equivocation::SubstrateEquivocationDetectionPipeline, + finality::SubstrateFinalitySyncPipeline, + finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, +}; + +/// Description of Rococo -> `RococoBulletin` finalized headers bridge. +#[derive(Clone, Debug)] +pub struct RococoFinalityToRococoBulletin; + +substrate_relay_helper::generate_submit_finality_proof_call_builder!( + RococoFinalityToRococoBulletin, + SubmitFinalityProofCallBuilder, + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotGrandpa, + relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall::submit_finality_proof +); + +substrate_relay_helper::generate_report_equivocation_call_builder!( + RococoFinalityToRococoBulletin, + ReportEquivocationCallBuilder, + relay_rococo_client::RuntimeCall::Grandpa, + relay_rococo_client::GrandpaCall::report_equivocation +); + +#[async_trait] +impl SubstrateFinalityPipeline for RococoFinalityToRococoBulletin { + type SourceChain = RococoAsPolkadot; + type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; + + type FinalityEngine = GrandpaFinalityEngine; +} + +#[async_trait] +impl SubstrateFinalitySyncPipeline for RococoFinalityToRococoBulletin { + type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; +} + +#[async_trait] +impl SubstrateEquivocationDetectionPipeline for RococoFinalityToRococoBulletin { + type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; +} + +/// `Rococo` to BridgeHub `RococoBulletin` bridge definition. +pub struct RococoToRococoBulletinCliBridge {} + +impl CliBridgeBase for RococoToRococoBulletinCliBridge { + type Source = RococoAsPolkadot; + type Target = relay_polkadot_bulletin_client::PolkadotBulletin; +} + +impl RelayToRelayHeadersCliBridge for RococoToRococoBulletinCliBridge { + type Finality = RococoFinalityToRococoBulletin; +} + +impl RelayToRelayEquivocationDetectionCliBridge for RococoToRococoBulletinCliBridge { + type Equivocation = RococoFinalityToRococoBulletin; +} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs new file mode 100644 index 0000000000000..ee44bad523b4f --- /dev/null +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs @@ -0,0 +1,91 @@ +// 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 . + +//! Rococo-to-RococoBulletin parachains sync entrypoint. + +use super::{BridgeHubRococoAsBridgeHubPolkadot, RococoAsPolkadot}; +use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; + +use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; +use bp_runtime::Chain; +use relay_substrate_client::{CallOf, HeaderIdOf}; +use substrate_relay_helper::{ + messages_lane::MessagesRelayLimits, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, +}; + +/// Rococo-to-RococoBulletin parachain sync description. +#[derive(Clone, Debug)] +pub struct RococoToRococoBulletin; + +impl SubstrateParachainsPipeline for RococoToRococoBulletin { + type SourceParachain = BridgeHubRococoAsBridgeHubPolkadot; + type SourceRelayChain = RococoAsPolkadot; + type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; + + type SubmitParachainHeadsCallBuilder = RococoToRococoBulletinCallBuilder; +} + +pub struct RococoToRococoBulletinCallBuilder; +impl SubmitParachainHeadsCallBuilder for RococoToRococoBulletinCallBuilder { + fn build_submit_parachain_heads_call( + at_relay_block: HeaderIdOf, + parachains: Vec<(ParaId, ParaHash)>, + parachain_heads_proof: ParaHeadsProof, + ) -> CallOf { + relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotParachains( + relay_polkadot_bulletin_client::BridgePolkadotParachainsCall::submit_parachain_heads { + at_relay_block: (at_relay_block.0, at_relay_block.1), + parachains, + parachain_heads_proof, + }, + ) + } +} + +/// Rococo-to-RococoBulletin parachain sync description for the CLI. +pub struct RococoToRococoBulletinCliBridge {} + +impl ParachainToRelayHeadersCliBridge for RococoToRococoBulletinCliBridge { + type SourceRelay = RococoAsPolkadot; + type ParachainFinality = RococoToRococoBulletin; + type RelayFinality = + crate::bridges::rococo_bulletin::rococo_headers_to_rococo_bulletin::RococoFinalityToRococoBulletin; +} + +impl CliBridgeBase for RococoToRococoBulletinCliBridge { + type Source = BridgeHubRococoAsBridgeHubPolkadot; + type Target = relay_polkadot_bulletin_client::PolkadotBulletin; +} + +impl MessagesCliBridge for RococoToRococoBulletinCliBridge { + type MessagesLane = + crate::bridges::rococo_bulletin::bridge_hub_rococo_messages_to_rococo_bulletin::BridgeHubRococoMessagesToRococoBulletinMessageLane; + + fn maybe_messages_limits() -> Option { + // Rococo Bulletin chain is missing the `TransactionPayment` runtime API (as well as the + // transaction payment pallet itself), so we can't estimate limits using runtime calls. + // Let's do it here. + // + // Folloiung constants are just safe **underestimations**. Normally, we are able to deliver + // and dispatch thousands of messages in the same transaction. + Some(MessagesRelayLimits { + max_messages_in_single_batch: 128, + max_messages_weight_in_single_batch: + bp_polkadot_bulletin::PolkadotBulletin::max_extrinsic_weight() / 20, + }) + } +} diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 2903a290c5b62..6073d9e3155bb 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -35,6 +35,8 @@ pub enum FullBridge { BridgeHubPolkadotToBridgeHubKusama, PolkadotBulletinToBridgeHubPolkadot, BridgeHubPolkadotToPolkadotBulletin, + RococoBulletinToBridgeHubRococo, + BridgeHubRococoToRococoBulletin, } /// Minimal bridge representation that can be used from the CLI. diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 30875e70cbb35..8be74e5f9b535 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -27,6 +27,10 @@ use crate::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, + rococo_bulletin::{ + rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, + rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, + }, rococo_westend::{ rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, @@ -66,6 +70,8 @@ pub enum InitBridgeName { PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, PolkadotBulletinToBridgeHubPolkadot, + RococoToRococoBulletin, + RococoBulletinToBridgeHubRococo, RococoToBridgeHubWestend, WestendToBridgeHubRococo, } @@ -195,6 +201,35 @@ impl BridgeInitializer for PolkadotBulletinToBridgeHubPolkadotCliBridge { } } +impl BridgeInitializer for RococoToRococoBulletinCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + type RuntimeCall = relay_polkadot_bulletin_client::RuntimeCall; + type BridgePolkadotGrandpaCall = relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall; + type SudoCall = relay_polkadot_bulletin_client::SudoCall; + + let initialize_call = + RuntimeCall::BridgePolkadotGrandpa(BridgePolkadotGrandpaCall::initialize { init_data }); + + RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(initialize_call) }) + } +} + +impl BridgeInitializer for RococoBulletinToBridgeHubRococoCliBridge { + type Engine = GrandpaFinalityEngine; + + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call { + relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinGrandpa( + relay_bridge_hub_rococo_client::BridgeBulletinGrandpaCall::initialize { init_data }, + ) + } +} + impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { @@ -207,6 +242,10 @@ impl InitBridge { PolkadotToPolkadotBulletinCliBridge::init_bridge(self), InitBridgeName::PolkadotBulletinToBridgeHubPolkadot => PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self), + InitBridgeName::RococoToRococoBulletin => + RococoToRococoBulletinCliBridge::init_bridge(self), + InitBridgeName::RococoBulletinToBridgeHubRococo => + RococoBulletinToBridgeHubRococoCliBridge::init_bridge(self), InitBridgeName::RococoToBridgeHubWestend => RococoToBridgeHubWestendCliBridge::init_bridge(self), InitBridgeName::WestendToBridgeHubRococo => diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 032fe64ef9070..5e43c98770072 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -27,6 +27,10 @@ use crate::bridges::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, + rococo_bulletin::{ + rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, + rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, + }, }; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; @@ -61,6 +65,8 @@ pub enum RelayHeadersBridge { PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, PolkadotBulletinToBridgeHubPolkadot, + RococoToRococoBulletin, + RococoBulletinToBridgeHubRococo, } #[async_trait] @@ -98,6 +104,8 @@ impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} impl HeadersRelayer for PolkadotToPolkadotBulletinCliBridge {} impl HeadersRelayer for PolkadotBulletinToBridgeHubPolkadotCliBridge {} +impl HeadersRelayer for RococoToRococoBulletinCliBridge {} +impl HeadersRelayer for RococoBulletinToBridgeHubRococoCliBridge {} impl RelayHeaders { /// Run the command. @@ -111,6 +119,10 @@ impl RelayHeaders { PolkadotToPolkadotBulletinCliBridge::relay_headers(self), RelayHeadersBridge::PolkadotBulletinToBridgeHubPolkadot => PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self), + RelayHeadersBridge::RococoToRococoBulletin => + RococoToRococoBulletinCliBridge::relay_headers(self), + RelayHeadersBridge::RococoBulletinToBridgeHubRococo => + RococoBulletinToBridgeHubRococoCliBridge::relay_headers(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs index 87d1c38fab10d..c445bdddcc936 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs @@ -47,6 +47,11 @@ use crate::{ polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, + rococo_bulletin::{ + rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, + rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, + BridgeHubRococoAsBridgeHubPolkadot, + }, rococo_westend::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, @@ -199,6 +204,7 @@ declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); declare_chain_cli_schema!(Polkadot, polkadot); declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); declare_chain_cli_schema!(PolkadotBulletin, polkadot_bulletin); +declare_chain_cli_schema!(RococoBulletin, rococo_bulletin); // Means to override signers of different layer transactions. declare_chain_cli_schema!(RococoHeadersToBridgeHubWestend, rococo_headers_to_bridge_hub_westend); declare_chain_cli_schema!( @@ -224,15 +230,22 @@ declare_chain_cli_schema!( PolkadotBulletinHeadersToBridgeHubPolkadot, polkadot_bulletin_headers_to_bridge_hub_polkadot ); +declare_chain_cli_schema!( + RococoBulletinHeadersToBridgeHubRococo, + rococo_bulletin_headers_to_bridge_hub_rococo +); declare_chain_cli_schema!(PolkadotHeadersToPolkadotBulletin, polkadot_headers_to_polkadot_bulletin); +declare_chain_cli_schema!(RococoHeadersToRococoBulletin, rococo_headers_to_rococo_bulletin); declare_chain_cli_schema!( PolkadotParachainsToPolkadotBulletin, polkadot_parachains_to_polkadot_bulletin ); +declare_chain_cli_schema!(RococoParachainsToRococoBulletin, rococo_parachains_to_rococo_bulletin); // All supported bridges. declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWestend, Westend); declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); +declare_relay_to_parachain_bridge_schema!(RococoBulletin, BridgeHubRococo, Rococo); /// Base portion of the bidirectional complex relay. /// @@ -477,6 +490,32 @@ impl Full2WayBridge for PolkadotBulletinBridgeHubPolkadotFull2WayBridge { } } +/// `RococoBulletin` <> `BridgeHubRococo` complex relay. +pub struct RococoBulletinBridgeHubRococoFull2WayBridge { + base: ::Base, +} + +#[async_trait] +impl Full2WayBridge for RococoBulletinBridgeHubRococoFull2WayBridge { + type Base = RelayToParachainBridge; + type Left = relay_polkadot_bulletin_client::PolkadotBulletin; + type Right = BridgeHubRococoAsBridgeHubPolkadot; + type L2R = RococoBulletinToBridgeHubRococoCliBridge; + type R2L = RococoToRococoBulletinCliBridge; + + fn new(base: Self::Base) -> anyhow::Result { + Ok(Self { base }) + } + + fn base(&self) -> &Self::Base { + &self.base + } + + fn mut_base(&mut self) -> &mut Self::Base { + &mut self.base + } +} + /// Complex headers+messages relay. #[derive(Debug, PartialEq, StructOpt)] pub enum RelayHeadersAndMessages { @@ -484,6 +523,8 @@ pub enum RelayHeadersAndMessages { BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), /// `PolkadotBulletin` <> `BridgeHubPolkadot` relay. PolkadotBulletinBridgeHubPolkadot(PolkadotBulletinBridgeHubPolkadotHeadersAndMessages), + /// `RococoBulletin` <> `BridgeHubRococo` relay. + RococoBulletinBridgeHubRococo(RococoBulletinBridgeHubRococoHeadersAndMessages), /// BridgeHubRococo <> BridgeHubWestend relay. BridgeHubRococoBridgeHubWestend(BridgeHubRococoBridgeHubWestendHeadersAndMessages), } @@ -504,6 +545,10 @@ impl RelayHeadersAndMessages { PolkadotBulletinBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? .run() .await, + RelayHeadersAndMessages::RococoBulletinBridgeHubRococo(params) => + RococoBulletinBridgeHubRococoFull2WayBridge::new(params.into_bridge().await?)? + .run() + .await, } } } diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index 477e9feff050a..b20725b53c743 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -28,6 +28,10 @@ use crate::bridges::{ bridge_hub_polkadot_messages_to_polkadot_bulletin::BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge, polkadot_bulletin_messages_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge, }, + rococo_bulletin::{ + bridge_hub_rococo_messages_to_rococo_bulletin::BridgeHubRococoToRococoBulletinMessagesCliBridge, + rococo_bulletin_messages_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoMessagesCliBridge, + }, rococo_westend::{ bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendMessagesCliBridge, bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, @@ -103,6 +107,8 @@ impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} impl MessagesRelayer for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} impl MessagesRelayer for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} impl MessagesRelayer for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} +impl MessagesRelayer for RococoBulletinToBridgeHubRococoMessagesCliBridge {} +impl MessagesRelayer for BridgeHubRococoToRococoBulletinMessagesCliBridge {} impl RelayMessages { /// Run the command. @@ -120,6 +126,10 @@ impl RelayMessages { PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), FullBridge::BridgeHubPolkadotToPolkadotBulletin => BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self), + FullBridge::RococoBulletinToBridgeHubRococo => + RococoBulletinToBridgeHubRococoMessagesCliBridge::relay_messages(self), + FullBridge::BridgeHubRococoToRococoBulletin => + BridgeHubRococoToRococoBulletinMessagesCliBridge::relay_messages(self), } .await } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 3038d1dfdb91d..1456dddf11e23 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -20,6 +20,7 @@ use crate::bridges::{ polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, }, polkadot_bulletin::polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, + rococo_bulletin::rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, rococo_westend::{ rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, @@ -67,6 +68,7 @@ pub enum RelayParachainsBridge { KusamaToBridgeHubPolkadot, PolkadotToBridgeHubKusama, PolkadotToPolkadotBulletin, + RococoToRococoBulletin, RococoToBridgeHubWestend, WestendToBridgeHubRococo, } @@ -117,6 +119,7 @@ impl ParachainsRelayer for BridgeHubWestendToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} impl ParachainsRelayer for BridgeHubPolkadotToBridgeHubKusamaCliBridge {} impl ParachainsRelayer for PolkadotToPolkadotBulletinCliBridge {} +impl ParachainsRelayer for RococoToRococoBulletinCliBridge {} impl RelayParachains { /// Run the command. @@ -132,6 +135,8 @@ impl RelayParachains { BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self), RelayParachainsBridge::PolkadotToPolkadotBulletin => PolkadotToPolkadotBulletinCliBridge::relay_parachains(self), + RelayParachainsBridge::RococoToRococoBulletin => + RococoToRococoBulletinCliBridge::relay_parachains(self), } .await } diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs index cf125b8cf5966..2afdeb2489363 100644 --- a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs @@ -16,17 +16,27 @@ //! Autogenerated runtime API //! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url -//! wss://rococo-bridge-hub-rpc.polkadot.io:443 +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-wasm-file +//! /home/svyatonik/dev/polkadot-sdk/target/debug/wbuild/bridge-hub-rococo-runtime/ +//! bridge_hub_rococo_runtime.wasm #[allow(dead_code, unused_imports, non_camel_case_types)] #[allow(clippy::all)] +#[allow(rustdoc::broken_intra_doc_links)] pub mod api { - use super::api as root_mod; + #[allow(unused_imports)] + mod root_mod { + pub use super::*; + } pub mod runtime_types { use super::runtime_types; pub mod bounded_collections { use super::runtime_types; + pub mod bounded_btree_set { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedBTreeSet<_0>(pub ::std::vec::Vec<_0>); + } pub mod bounded_vec { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -41,6 +51,14 @@ pub mod api { pub mod bp_header_chain { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AuthoritySet { + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum HeaderChainError { #[codec(index = 0)] UnknownHeader, @@ -48,6 +66,11 @@ pub mod api { StorageProof(runtime_types::bp_runtime::storage_proof::Error), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderFinalityInfo<_0, _1> { + pub finality_proof: _0, + pub new_verification_context: ::core::option::Option<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct StoredHeaderData<_0, _1> { pub number: _0, pub state_root: _1, @@ -256,32 +279,63 @@ pub mod api { XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), #[codec(index = 31)] PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), #[codec(index = 40)] Utility(runtime_types::pallet_utility::pallet::Call), #[codec(index = 36)] Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 41)] - BridgeWococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 43)] - BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), #[codec(index = 48)] BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 42)] - BridgeWococoParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 44)] - BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 60)] + BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call2), #[codec(index = 49)] BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 46)] - BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), - #[codec(index = 45)] - BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), #[codec(index = 51)] BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 61)] + BridgePolkadotBulletinMessages( + runtime_types::pallet_bridge_messages::pallet::Call2, + ), #[codec(index = 47)] BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + #[codec(index = 250)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeError { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Error), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Error), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Error), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Error), + #[codec(index = 36)] + Multisig(runtime_types::pallet_multisig::pallet::Error), + #[codec(index = 48)] + BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), + #[codec(index = 52)] + BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error2), + #[codec(index = 49)] + BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Error), + #[codec(index = 51)] + BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Error), + #[codec(index = 53)] + BridgePolkadotBulletinMessages( + runtime_types::pallet_bridge_messages::pallet::Error2, + ), + #[codec(index = 47)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), + #[codec(index = 250)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Error), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RuntimeEvent { @@ -303,34 +357,30 @@ pub mod api { PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), #[codec(index = 32)] CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), #[codec(index = 40)] Utility(runtime_types::pallet_utility::pallet::Event), #[codec(index = 36)] Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 41)] - BridgeWococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 43)] - BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), #[codec(index = 48)] BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 42)] - BridgeWococoParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 44)] - BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 52)] + BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event2), #[codec(index = 49)] BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 46)] - BridgeWococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), - #[codec(index = 45)] - BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), #[codec(index = 51)] BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Event), + #[codec(index = 53)] + BridgePolkadotBulletinMessages( + runtime_types::pallet_bridge_messages::pallet::Event2, + ), #[codec(index = 47)] BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 250)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Event), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeHoldReason {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct SessionKeys { pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, } @@ -352,69 +402,11 @@ pub mod api { pub mod refund_relayer_extension { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundBridgedParachainMessages; - } - } - pub mod cumulus_pallet_dmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - } + pub struct RefundBridgedGrandpaMessages; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - OverLimit, - } + pub struct RefundBridgedParachainMessages; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat { message_id: [::core::primitive::u8; 32usize] }, - #[codec(index = 1)] - UnsupportedVersion { message_id: [::core::primitive::u8; 32usize] }, - #[codec(index = 2)] - ExecutedDownward { - message_id: [::core::primitive::u8; 32usize], - outcome: runtime_types::xcm::v3::traits::Outcome, - }, - #[codec(index = 3)] - WeightExhausted { - message_id: [::core::primitive::u8; 32usize], - remaining_weight: ::sp_weights::Weight, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - OverweightEnqueued { - message_id: [::core::primitive::u8; 32usize], - overweight_index: ::core::primitive::u64, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 5)] - OverweightServiced { - overweight_index: ::core::primitive::u64, - weight_used: ::sp_weights::Weight, - }, - #[codec(index = 6)] - MaxMessagesExhausted { message_id: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ConfigData { - pub max_individual: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PageIndexData { - pub begin_used: ::core::primitive::u32, - pub end_used: ::core::primitive::u32, - pub overweight_count: ::core::primitive::u64, + pub struct RefundSignedExtensionAdapter<_0>(pub _0); } } pub mod cumulus_pallet_parachain_system { @@ -469,13 +461,27 @@ pub mod api { pub mod relay_state_snapshot { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_size : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispachQueueSize , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain :: primitives :: Id , runtime_types :: polkadot_primitives :: v4 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain :: primitives :: Id , runtime_types :: polkadot_primitives :: v4 :: AbridgedHrmpChannel ,) > , } + pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RelayDispachQueueSize { + pub struct RelayDispatchQueueRemainingCapacity { pub remaining_count: ::core::primitive::u32, pub remaining_size: ::core::primitive::u32, } } + pub mod unincluded_segment { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelUpdate { + pub msg_count: ::core::primitive::u32, + pub total_bytes: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CodeUpgradeAuthorization { pub code_hash: ::subxt::utils::H256, @@ -487,8 +493,6 @@ pub mod api { pub mod pallet { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] InvalidFormat([::core::primitive::u8; 32usize]), @@ -505,7 +509,7 @@ pub mod api { #[codec(index = 0)] Relay, #[codec(index = 1)] - SiblingParachain(runtime_types::polkadot_parachain::primitives::Id), + SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), } } } @@ -515,11 +519,6 @@ pub mod api { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, #[codec(index = 1)] suspend_xcm_execution, #[codec(index = 2)] @@ -530,81 +529,25 @@ pub mod api { update_drop_threshold { new: ::core::primitive::u32 }, #[codec(index = 5)] update_resume_threshold { new: ::core::primitive::u32 }, - #[codec(index = 6)] - update_threshold_weight { new: ::sp_weights::Weight }, - #[codec(index = 7)] - update_weight_restrict_decay { new: ::sp_weights::Weight }, - #[codec(index = 8)] - update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] - FailedToSend, + BadQueueConfig, #[codec(index = 1)] - BadXcmOrigin, + AlreadySuspended, #[codec(index = 2)] - BadXcm, - #[codec(index = 3)] - BadOverweightIndex, - #[codec(index = 4)] - WeightOverLimit, + AlreadyResumed, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] - Success { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - weight: ::sp_weights::Weight, - }, - #[codec(index = 1)] - Fail { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - error: runtime_types::xcm::v3::traits::Error, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - BadVersion { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 3)] - BadFormat { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 4)] - XcmpMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 5)] - OverweightEnqueued { - sender: runtime_types::polkadot_parachain::primitives::Id, - sent_at: ::core::primitive::u32, - index: ::core::primitive::u64, - required: ::sp_weights::Weight, - }, - #[codec(index = 6)] - OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, + XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundChannelDetails { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, - pub message_metadata: ::std::vec::Vec<( - ::core::primitive::u32, - runtime_types::polkadot_parachain::primitives::XcmpMessageFormat, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct OutboundChannelDetails { - pub recipient: runtime_types::polkadot_parachain::primitives::Id, + pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, pub signals_exist: ::core::primitive::bool, pub first_index: ::core::primitive::u16, @@ -627,6 +570,18 @@ pub mod api { pub xcmp_max_individual_weight: ::sp_weights::Weight, } } + pub mod cumulus_primitives_core { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + Parent, + #[codec(index = 2)] + Sibling(runtime_types::polkadot_parachain_primitives::primitives::Id), + } + } pub mod cumulus_primitives_parachain_inherent { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -634,7 +589,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ParachainInherentData { pub validation_data: - runtime_types::polkadot_primitives::v4::PersistedValidationData< + runtime_types::polkadot_primitives::v6::PersistedValidationData< ::subxt::utils::H256, ::core::primitive::u32, >, @@ -645,7 +600,7 @@ pub mod api { >, >, pub horizontal_messages: ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain::primitives::Id, + runtime_types::polkadot_parachain_primitives::primitives::Id, ::std::vec::Vec< runtime_types::polkadot_core_primitives::InboundHrmpMessage< ::core::primitive::u32, @@ -720,6 +675,22 @@ pub mod api { } pub mod traits { use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProcessMessageError { + #[codec(index = 0)] + BadFormat, + #[codec(index = 1)] + Corrupt, + #[codec(index = 2)] + Unsupported, + #[codec(index = 3)] + Overweight(::sp_weights::Weight), + #[codec(index = 4)] + Yield, + } + } pub mod tokens { use super::runtime_types; pub mod misc { @@ -869,9 +840,9 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AccountInfo<_0, _1> { pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, + pub consumers: ::core::primitive::u32, + pub providers: ::core::primitive::u32, + pub sufficients: ::core::primitive::u32, pub data: _1, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -908,14 +879,6 @@ pub mod api { #[codec(compact)] value: ::core::primitive::u128, }, - #[codec(index = 1)] - set_balance_deprecated { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - #[codec(compact)] - old_reserved: ::core::primitive::u128, - }, #[codec(index = 2)] force_transfer { source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -941,12 +904,6 @@ pub mod api { }, #[codec(index = 6)] upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 7)] - transfer { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, #[codec(index = 8)] force_set_balance { who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, @@ -1143,6 +1100,39 @@ pub mod api { }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call2 { + #[codec(index = 0)] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 1)] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 2)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] InvalidJustification, @@ -1162,11 +1152,56 @@ pub mod api { BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error2 { + #[codec(index = 0)] + InvalidJustification, + #[codec(index = 1)] + InvalidAuthoritySet, + #[codec(index = 2)] + OldHeader, + #[codec(index = 3)] + UnsupportedScheduledChange, + #[codec(index = 4)] + NotInitialized, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooManyAuthoritiesInSet, + #[codec(index = 7)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] UpdatedBestFinalizedHeader { number: ::core::primitive::u32, hash: ::subxt::utils::H256, + grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< + ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + runtime_types::bp_header_chain::AuthoritySet, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event2 { + #[codec(index = 0)] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u32, + hash: ::subxt::utils::H256, + grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< + ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + runtime_types::bp_header_chain::AuthoritySet, + >, }, } } @@ -1180,6 +1215,14 @@ pub mod api { )>, pub set_id: ::core::primitive::u64, } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredAuthoritySet2 { + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } } } pub mod pallet_bridge_messages { @@ -1204,11 +1247,20 @@ pub mod api { pub enum Call { # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call2 { + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 3)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error2 { + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event2 { + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } } } pub mod pallet_bridge_parachains { @@ -1312,12 +1364,18 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] - RewardPaid { + RewardRegistered { relayer: ::sp_core::crypto::AccountId32, rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, reward: ::core::primitive::u128, }, #[codec(index = 1)] + RewardPaid { + relayer: ::sp_core::crypto::AccountId32, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + reward: ::core::primitive::u128, + }, + #[codec(index = 2)] RegistrationUpdated { relayer: ::sp_core::crypto::AccountId32, registration: runtime_types::bp_relayers::registration::Registration< @@ -1325,9 +1383,9 @@ pub mod api { ::core::primitive::u128, >, }, - #[codec(index = 2)] - Deregistered { relayer: ::sp_core::crypto::AccountId32 }, #[codec(index = 3)] + Deregistered { relayer: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] SlashedAndDeregistered { relayer: ::sp_core::crypto::AccountId32, registration: runtime_types::bp_relayers::registration::Registration< @@ -1354,6 +1412,17 @@ pub mod api { register_as_candidate, #[codec(index = 4)] leave_intent, + #[codec(index = 5)] + add_invulnerable { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 7)] + update_bond { new_deposit: ::core::primitive::u128 }, + #[codec(index = 8)] + take_candidate_slot { + deposit: ::core::primitive::u128, + target: ::sp_core::crypto::AccountId32, + }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct CandidateInfo<_0, _1> { @@ -1365,23 +1434,37 @@ pub mod api { #[codec(index = 0)] TooManyCandidates, #[codec(index = 1)] - TooFewCandidates, + TooFewEligibleCollators, #[codec(index = 2)] - Unknown, + AlreadyCandidate, #[codec(index = 3)] - Permission, + NotCandidate, #[codec(index = 4)] - AlreadyCandidate, + TooManyInvulnerables, #[codec(index = 5)] - NotCandidate, + AlreadyInvulnerable, #[codec(index = 6)] - TooManyInvulnerables, + NotInvulnerable, #[codec(index = 7)] - AlreadyInvulnerable, - #[codec(index = 8)] NoAssociatedValidatorId, - #[codec(index = 9)] + #[codec(index = 8)] ValidatorNotRegistered, + #[codec(index = 9)] + InsertToCandidateListFailed, + #[codec(index = 10)] + RemoveFromCandidateListFailed, + #[codec(index = 11)] + DepositTooLow, + #[codec(index = 12)] + UpdateCandidateListFailed, + #[codec(index = 13)] + InsufficientBond, + #[codec(index = 14)] + TargetIsNotCandidate, + #[codec(index = 15)] + IdenticalDeposit, + #[codec(index = 16)] + InvalidUnreserve, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { @@ -1390,18 +1473,131 @@ pub mod api { invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, }, #[codec(index = 1)] - NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, + InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, #[codec(index = 2)] - NewCandidacyBond { bond_amount: ::core::primitive::u128 }, + InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, #[codec(index = 3)] - CandidateAdded { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, + NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, #[codec(index = 4)] + NewCandidacyBond { bond_amount: ::core::primitive::u128 }, + #[codec(index = 5)] + CandidateAdded { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 6)] + CandidateBondUpdated { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 7)] CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 8)] + CandidateReplaced { + old: ::sp_core::crypto::AccountId32, + new: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 9)] + InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, + } + } + } + pub mod pallet_message_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + reap_page { + message_origin: + runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + page_index: ::core::primitive::u32, + }, + #[codec(index = 1)] + execute_overweight { + message_origin: + runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + page: ::core::primitive::u32, + index: ::core::primitive::u32, + weight_limit: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotReapable, + #[codec(index = 1)] + NoPage, + #[codec(index = 2)] + NoMessage, + #[codec(index = 3)] + AlreadyProcessed, + #[codec(index = 4)] + Queued, + #[codec(index = 5)] + InsufficientWeight, + #[codec(index = 6)] + TemporarilyUnprocessable, + #[codec(index = 7)] + QueuePaused, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ProcessingFailed { + id: [::core::primitive::u8; 32usize], + origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + error: runtime_types::frame_support::traits::messages::ProcessMessageError, + }, + #[codec(index = 1)] + Processed { + id: [::core::primitive::u8; 32usize], + origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + weight_used: ::sp_weights::Weight, + success: ::core::primitive::bool, + }, + #[codec(index = 2)] + OverweightEnqueued { + id: [::core::primitive::u8; 32usize], + origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + page_index: ::core::primitive::u32, + message_index: ::core::primitive::u32, + }, + #[codec(index = 3)] + PageReaped { + origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + index: ::core::primitive::u32, + }, } } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BookState<_0> { + pub begin: ::core::primitive::u32, + pub end: ::core::primitive::u32, + pub count: ::core::primitive::u32, + pub ready_neighbours: + ::core::option::Option>, + pub message_count: ::core::primitive::u64, + pub size: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Neighbours<_0> { + pub prev: _0, + pub next: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Page<_0> { + pub remaining: _0, + pub remaining_size: _0, + pub first_index: _0, + pub first: _0, + pub last: _0, + pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + } } pub mod pallet_multisig { use super::runtime_types; @@ -1524,7 +1720,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Timepoint<_0> { pub height: _0, - pub index: _0, + pub index: ::core::primitive::u32, } } pub mod pallet_session { @@ -1699,14 +1895,15 @@ pub mod api { }, #[codec(index = 3)] execute { - message: ::std::boxed::Box, + message: ::std::boxed::Box, max_weight: ::sp_weights::Weight, }, #[codec(index = 4)] force_xcm_version { - location: - ::std::boxed::Box, - xcm_version: ::core::primitive::u32, + location: ::std::boxed::Box< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + version: ::core::primitive::u32, }, #[codec(index = 5)] force_default_xcm_version { @@ -1768,7 +1965,7 @@ pub mod api { #[codec(index = 12)] AlreadySubscribed, #[codec(index = 13)] - InvalidAsset, + CannotCheckOutTeleport, #[codec(index = 14)] LowBalance, #[codec(index = 15)] @@ -1781,136 +1978,201 @@ pub mod api { LockNotFound, #[codec(index = 19)] InUse, + #[codec(index = 20)] + InvalidAssetNotConcrete, + #[codec(index = 21)] + InvalidAssetUnknownReserve, + #[codec(index = 22)] + InvalidAssetUnsupportedReserve, + #[codec(index = 23)] + TooManyReserves, + #[codec(index = 24)] + LocalExecutionIncomplete, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] - Attempted(runtime_types::xcm::v3::traits::Outcome), + Attempted { outcome: runtime_types::xcm::v3::traits::Outcome }, #[codec(index = 1)] - Sent( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::Xcm, - ), + Sent { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + message: runtime_types::xcm::v3::Xcm, + message_id: [::core::primitive::u8; 32usize], + }, #[codec(index = 2)] - UnexpectedResponse( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), + UnexpectedResponse { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, #[codec(index = 3)] - ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), + ResponseReady { + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + }, #[codec(index = 4)] - Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), + Notified { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, #[codec(index = 5)] - NotifyOverweight( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ::sp_weights::Weight, - ::sp_weights::Weight, - ), + NotifyOverweight { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + actual_weight: ::sp_weights::Weight, + max_budgeted_weight: ::sp_weights::Weight, + }, #[codec(index = 6)] - NotifyDispatchError( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), + NotifyDispatchError { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, #[codec(index = 7)] - NotifyDecodeFailed( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), + NotifyDecodeFailed { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, #[codec(index = 8)] - InvalidResponder( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, + InvalidResponder { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + expected_location: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, >, - ), + }, #[codec(index = 9)] - InvalidResponderVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), + InvalidResponderVersion { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, #[codec(index = 10)] - ResponseTaken(::core::primitive::u64), + ResponseTaken { query_id: ::core::primitive::u64 }, #[codec(index = 11)] - AssetsTrapped( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), + AssetsTrapped { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + }, #[codec(index = 12)] - VersionChangeNotified( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), + VersionChangeNotified { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + result: ::core::primitive::u32, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, #[codec(index = 13)] - SupportedVersionChanged( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - ), + SupportedVersionChanged { + location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + version: ::core::primitive::u32, + }, #[codec(index = 14)] - NotifyTargetSendFail( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::traits::Error, - ), + NotifyTargetSendFail { + location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + error: runtime_types::xcm::v3::traits::Error, + }, #[codec(index = 15)] - NotifyTargetMigrationFail( - runtime_types::xcm::VersionedMultiLocation, - ::core::primitive::u64, - ), + NotifyTargetMigrationFail { + location: runtime_types::xcm::VersionedMultiLocation, + query_id: ::core::primitive::u64, + }, #[codec(index = 16)] - InvalidQuerierVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), + InvalidQuerierVersion { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, #[codec(index = 17)] - InvalidQuerier( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, + InvalidQuerier { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + expected_querier: + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + maybe_actual_querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, >, - ), + }, #[codec(index = 18)] - VersionNotifyStarted( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), + VersionNotifyStarted { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, #[codec(index = 19)] - VersionNotifyRequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), + VersionNotifyRequested { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, #[codec(index = 20)] - VersionNotifyUnrequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), + VersionNotifyUnrequested { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, #[codec(index = 21)] - FeesPaid( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), + FeesPaid { + paying: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + fees: runtime_types::xcm::v3::multiasset::MultiAssets, + }, #[codec(index = 22)] - AssetsClaimed( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), + AssetsClaimed { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Origin { #[codec(index = 0)] - Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), + Xcm(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, #[codec(index = 1)] - Response(runtime_types::xcm::v3::multilocation::MultiLocation), + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, } } } @@ -1932,7 +2194,7 @@ pub mod api { pub data: ::std::vec::Vec<::core::primitive::u8>, } } - pub mod polkadot_parachain { + pub mod polkadot_parachain_primitives { use super::runtime_types; pub mod primitives { use super::runtime_types; @@ -1947,21 +2209,20 @@ pub mod api { PartialEq, )] pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmpMessageFormat { - #[codec(index = 0)] - ConcatenatedVersionedXcm, - #[codec(index = 1)] - ConcatenatedEncodedBlob, - #[codec(index = 2)] - Signals, - } } } pub mod polkadot_primitives { use super::runtime_types; - pub mod v4 { + pub mod v6 { use super::runtime_types; + pub mod async_backing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AbridgedHostConfiguration { pub max_code_size: ::core::primitive::u32, @@ -1973,6 +2234,8 @@ pub mod api { pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, pub validation_upgrade_cooldown: ::core::primitive::u32, pub validation_upgrade_delay: ::core::primitive::u32, + pub async_backing_params: + runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AbridgedHrmpChannel { @@ -1985,10 +2248,18 @@ pub mod api { } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct PersistedValidationData<_0, _1> { - pub parent_head: runtime_types::polkadot_parachain::primitives::HeadData, + pub parent_head: + runtime_types::polkadot_parachain_primitives::primitives::HeadData, pub relay_parent_number: _1, pub relay_parent_storage_root: _0, - pub max_pov_size: _1, + pub max_pov_size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum UpgradeRestriction { @@ -2112,14 +2383,6 @@ pub mod api { RuntimeEnvironmentUpdated, } } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1, _2, _3)>, - ); - } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum DispatchError { @@ -2230,6 +2493,20 @@ pub mod api { pub write: ::core::primitive::u64, } } + pub mod staging_xcm { + use super::runtime_types; + pub mod v3 { + use super::runtime_types; + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + } + } pub mod xcm { use super::runtime_types; pub mod double_encoded { @@ -2238,6 +2515,10 @@ pub mod api { pub struct DoubleEncoded { pub encoded: ::std::vec::Vec<::core::primitive::u8>, } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded2 { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } } pub mod v2 { use super::runtime_types; @@ -2677,59 +2958,201 @@ pub mod api { UnsubscribeVersion, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { + pub enum Instruction2 { #[codec(index = 0)] - Null, + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; pub mod junction { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -2929,7 +3352,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum AssetId { #[codec(index = 0)] - Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), + Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), #[codec(index = 1)] Abstract([::core::primitive::u8; 32usize]), } @@ -2998,14 +3421,6 @@ pub mod api { }, } } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } pub mod traits { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -3116,18 +3531,18 @@ pub mod api { response: runtime_types::xcm::v3::Response, max_weight: ::sp_weights::Weight, querier: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::staging_xcm::v3::multilocation::MultiLocation, >, }, #[codec(index = 4)] TransferAsset { assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 5)] TransferReserveAsset { assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, xcm: runtime_types::xcm::v3::Xcm, }, #[codec(index = 6)] @@ -3168,12 +3583,12 @@ pub mod api { #[codec(index = 13)] DepositAsset { assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 14)] DepositReserveAsset { assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, xcm: runtime_types::xcm::v3::Xcm, }, #[codec(index = 15)] @@ -3185,13 +3600,13 @@ pub mod api { #[codec(index = 16)] InitiateReserveWithdraw { assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v3::multilocation::MultiLocation, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, xcm: runtime_types::xcm::v3::Xcm, }, #[codec(index = 17)] InitiateTeleport { assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, xcm: runtime_types::xcm::v3::Xcm, }, #[codec(index = 18)] @@ -3215,7 +3630,7 @@ pub mod api { #[codec(index = 24)] ClaimAsset { assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::xcm::v3::multilocation::MultiLocation, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 25)] Trap(#[codec(compact)] ::core::primitive::u64), @@ -3234,7 +3649,7 @@ pub mod api { #[codec(index = 30)] ExpectOrigin( ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::staging_xcm::v3::multilocation::MultiLocation, >, ), #[codec(index = 31)] @@ -3277,22 +3692,22 @@ pub mod api { #[codec(index = 39)] LockAsset { asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 40)] UnlockAsset { asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::xcm::v3::multilocation::MultiLocation, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 41)] NoteUnlockable { asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::xcm::v3::multilocation::MultiLocation, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 42)] RequestUnlock { asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::xcm::v3::multilocation::MultiLocation, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, }, #[codec(index = 43)] SetFeesMode { jit_withdraw: ::core::primitive::bool }, @@ -3301,12 +3716,221 @@ pub mod api { #[codec(index = 45)] ClearTopic, #[codec(index = 46)] - AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), #[codec(index = 47)] UnpaidExecution { weight_limit: runtime_types::xcm::v3::WeightLimit, check_origin: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, >, }, } @@ -3346,7 +3970,7 @@ pub mod api { } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct QueryResponseInfo { - pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, + pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, #[codec(compact)] pub query_id: ::core::primitive::u64, pub max_weight: ::sp_weights::Weight, @@ -3384,6 +4008,13 @@ pub mod api { } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedMultiAssets { @@ -3397,7 +4028,14 @@ pub mod api { #[codec(index = 1)] V2(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 3)] - V3(runtime_types::xcm::v3::multilocation::MultiLocation), + V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedXcm { @@ -3406,6 +4044,13 @@ pub mod api { #[codec(index = 3)] V3(runtime_types::xcm::v3::Xcm), } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm2 { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm2), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm2), + } } } } diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 7e3a441f561e1..b92e0009f5b80 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -36,7 +36,9 @@ pub use codegen_runtime::api::runtime_types; pub type RuntimeCall = runtime_types::bridge_hub_rococo_runtime::RuntimeCall; pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgeBulletinMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call2; pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call2; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; diff --git a/relays/client-polkadot-bulletin/src/codegen_runtime.rs b/relays/client-polkadot-bulletin/src/codegen_runtime.rs index 37af5b0b98e0b..601a2dd973cd6 100644 --- a/relays/client-polkadot-bulletin/src/codegen_runtime.rs +++ b/relays/client-polkadot-bulletin/src/codegen_runtime.rs @@ -16,12 +16,16 @@ //! Autogenerated runtime API //! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url ws://127.0.0.1:9944 +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url ws://127.0.0.1:10000 #[allow(dead_code, unused_imports, non_camel_case_types)] #[allow(clippy::all)] +#[allow(rustdoc::broken_intra_doc_links)] pub mod api { - use super::api as root_mod; + #[allow(unused_imports)] + mod root_mod { + pub use super::*; + } pub mod runtime_types { use super::runtime_types; pub mod bounded_collections { @@ -78,6 +82,10 @@ pub mod api { pub last_confirmed_nonce: ::core::primitive::u64, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundMessageDetails { + pub dispatch_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct LaneId(pub [::core::primitive::u8; 4usize]); #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct MessageKey { @@ -98,6 +106,12 @@ pub mod api { pub latest_generated_nonce: ::core::primitive::u64, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundMessageDetails { + pub nonce: ::core::primitive::u64, + pub dispatch_weight: ::sp_weights::Weight, + pub size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum ReceivalResult<_0> { #[codec(index = 0)] Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), @@ -205,6 +219,21 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct StrippableError; } + pub mod bridge_runtime_common { + use super::runtime_types; + pub mod messages_xcm_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmBlobMessageDispatchResult { + #[codec(index = 0)] + InvalidPayload, + #[codec(index = 1)] + Dispatched, + #[codec(index = 2)] + NotDispatched, + } + } + } pub mod finality_grandpa { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -405,9 +434,9 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct AccountInfo<_0, _1> { pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, + pub consumers: ::core::primitive::u32, + pub providers: ::core::primitive::u32, + pub sufficients: ::core::primitive::u32, pub data: _1, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -588,49 +617,13 @@ pub mod api { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call { - #[codec(index = 0)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 1)] - set_operating_mode { - operating_mode: runtime_types::bp_messages::MessagesOperatingMode, - }, - #[codec(index = 2)] - receive_messages_proof { - relayer_id_at_bridged_chain: ::sp_core::crypto::AccountId32, - proof: bridge_runtime_common::messages::target::FromBridgedChainMessagesProof< - ::subxt::utils::H256, - >, - messages_count: ::core::primitive::u32, - dispatch_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - receive_messages_delivery_proof { - proof: bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof< - ::subxt::utils::H256, - >, - relayers_state: ::bp_messages::UnrewardedRelayersState, - }, - } + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { - #[codec(index = 0)] - MessageAccepted { - lane_id: runtime_types::bp_messages::LaneId, - nonce: ::core::primitive::u64, - }, - #[codec(index = 1)] - MessagesReceived( - ::std::vec::Vec>, - ), - #[codec(index = 2)] - MessagesDelivered { - lane_id: runtime_types::bp_messages::LaneId, - messages: runtime_types::bp_messages::DeliveredMessages, - }, - } + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } } } pub mod pallet_bridge_parachains { @@ -834,9 +827,9 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Heartbeat<_0> { pub block_number: _0, - pub session_index: _0, - pub authority_index: _0, - pub validators_len: _0, + pub session_index: ::core::primitive::u32, + pub authority_index: ::core::primitive::u32, + pub validators_len: ::core::primitive::u32, } } pub mod pallet_offences { @@ -853,6 +846,30 @@ pub mod api { } } } + pub mod pallet_relayer_set { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Duplicate, + #[codec(index = 1)] + NotARelayer, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RelayerAdded(::sp_core::crypto::AccountId32), + #[codec(index = 1)] + RelayerRemoved(::sp_core::crypto::AccountId32), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Relayer<_0> { + pub min_bridge_tx_block: _0, + } + } pub mod pallet_session { use super::runtime_types; pub mod pallet { @@ -1064,13 +1081,6 @@ pub mod api { pub mod pallet { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_validator { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - remove_validator { who: ::sp_core::crypto::AccountId32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { #[codec(index = 0)] Duplicate, @@ -1104,6 +1114,8 @@ pub mod api { } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BridgeRejectObsoleteHeadersAndMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Runtime; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RuntimeCall { @@ -1113,53 +1125,76 @@ pub mod api { Babe(runtime_types::pallet_babe::pallet::Call), #[codec(index = 2)] Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 6)] - ValidatorSet(runtime_types::pallet_validator_set::pallet::Call), - #[codec(index = 7)] + #[codec(index = 14)] Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 8)] + #[codec(index = 15)] ImOnline(runtime_types::pallet_im_online::pallet::Call), - #[codec(index = 9)] + #[codec(index = 16)] Grandpa(runtime_types::pallet_grandpa::pallet::Call), - #[codec(index = 10)] - Sudo(runtime_types::pallet_sudo::pallet::Call), - #[codec(index = 11)] + #[codec(index = 40)] TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Call), - #[codec(index = 12)] + #[codec(index = 51)] BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 13)] + #[codec(index = 52)] BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 53)] + BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 255)] + Sudo(runtime_types::pallet_sudo::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeError { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Error), + #[codec(index = 1)] + Babe(runtime_types::pallet_babe::pallet::Error), + #[codec(index = 13)] + ValidatorSet(runtime_types::pallet_validator_set::pallet::Error), #[codec(index = 14)] - BridgePolkadotBridgeHubMessages( - runtime_types::pallet_bridge_messages::pallet::Call, - ), + Session(runtime_types::pallet_session::pallet::Error), + #[codec(index = 15)] + ImOnline(runtime_types::pallet_im_online::pallet::Error), + #[codec(index = 16)] + Grandpa(runtime_types::pallet_grandpa::pallet::Error), + #[codec(index = 40)] + TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Error), + #[codec(index = 50)] + RelayerSet(runtime_types::pallet_relayer_set::pallet::Error), + #[codec(index = 51)] + BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), + #[codec(index = 52)] + BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Error), + #[codec(index = 53)] + BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Error), + #[codec(index = 255)] + Sudo(runtime_types::pallet_sudo::pallet::Error), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum RuntimeEvent { #[codec(index = 0)] System(runtime_types::frame_system::pallet::Event), - #[codec(index = 4)] + #[codec(index = 11)] Offences(runtime_types::pallet_offences::pallet::Event), - #[codec(index = 6)] + #[codec(index = 13)] ValidatorSet(runtime_types::pallet_validator_set::pallet::Event), - #[codec(index = 7)] + #[codec(index = 14)] Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 8)] + #[codec(index = 15)] ImOnline(runtime_types::pallet_im_online::pallet::Event), - #[codec(index = 9)] + #[codec(index = 16)] Grandpa(runtime_types::pallet_grandpa::pallet::Event), - #[codec(index = 10)] - Sudo(runtime_types::pallet_sudo::pallet::Event), - #[codec(index = 11)] + #[codec(index = 40)] TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Event), - #[codec(index = 12)] + #[codec(index = 50)] + RelayerSet(runtime_types::pallet_relayer_set::pallet::Event), + #[codec(index = 51)] BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 13)] + #[codec(index = 52)] BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 14)] - BridgePolkadotBridgeHubMessages( - runtime_types::pallet_bridge_messages::pallet::Event, - ), + #[codec(index = 53)] + BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Event), + #[codec(index = 255)] + Sudo(runtime_types::pallet_sudo::pallet::Event), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct ValidateSigned; @@ -1232,10 +1267,36 @@ pub mod api { PrimaryAndSecondaryVRFSlots, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BabeConfiguration { + pub slot_duration: ::core::primitive::u64, + pub epoch_length: ::core::primitive::u64, + pub c: (::core::primitive::u64, ::core::primitive::u64), + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_babe::app::Public, + ::core::primitive::u64, + )>, + pub randomness: [::core::primitive::u8; 32usize], + pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BabeEpochConfiguration { pub c: (::core::primitive::u64, ::core::primitive::u64), pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Epoch { + pub epoch_index: ::core::primitive::u64, + pub start_slot: runtime_types::sp_consensus_slots::Slot, + pub duration: ::core::primitive::u64, + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_babe::app::Public, + ::core::primitive::u64, + )>, + pub randomness: [::core::primitive::u8; 32usize], + pub config: runtime_types::sp_consensus_babe::BabeEpochConfiguration, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueKeyOwnershipProof(pub ::std::vec::Vec<::core::primitive::u8>); } pub mod sp_consensus_grandpa { use super::runtime_types; @@ -1265,6 +1326,8 @@ pub mod api { >, ), } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueKeyOwnershipProof(pub ::std::vec::Vec<::core::primitive::u8>); } pub mod sp_consensus_slots { use super::runtime_types; @@ -1319,11 +1382,37 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct Signature(pub [::core::primitive::u8; 64usize]); } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMetadata(pub ::std::vec::Vec<::core::primitive::u8>); + } + pub mod sp_inherents { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckInherentsResult { + pub okay: ::core::primitive::bool, + pub fatal_error: ::core::primitive::bool, + pub errors: runtime_types::sp_inherents::InherentData, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData { + pub data: ::subxt::utils::KeyedVec< + [::core::primitive::u8; 8usize], + ::std::vec::Vec<::core::primitive::u8>, + >, + } } pub mod sp_runtime { use super::runtime_types; pub mod generic { use super::runtime_types; + pub mod block { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Block<_0, _1> { + pub header: _0, + pub extrinsics: ::std::vec::Vec<_1>, + } + } pub mod digest { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -1349,13 +1438,66 @@ pub mod api { RuntimeEnvironmentUpdated, } } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, - ); + } + pub mod transaction_validity { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidTransaction { + #[codec(index = 0)] + Call, + #[codec(index = 1)] + Payment, + #[codec(index = 2)] + Future, + #[codec(index = 3)] + Stale, + #[codec(index = 4)] + BadProof, + #[codec(index = 5)] + AncientBirthBlock, + #[codec(index = 6)] + ExhaustsResources, + #[codec(index = 7)] + Custom(::core::primitive::u8), + #[codec(index = 8)] + BadMandatory, + #[codec(index = 9)] + MandatoryValidation, + #[codec(index = 10)] + BadSigner, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionSource { + #[codec(index = 0)] + InBlock, + #[codec(index = 1)] + Local, + #[codec(index = 2)] + External, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionValidityError { + #[codec(index = 0)] + Invalid(runtime_types::sp_runtime::transaction_validity::InvalidTransaction), + #[codec(index = 1)] + Unknown(runtime_types::sp_runtime::transaction_validity::UnknownTransaction), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UnknownTransaction { + #[codec(index = 0)] + CannotLookup, + #[codec(index = 1)] + NoUnsignedValidator, + #[codec(index = 2)] + Custom(::core::primitive::u8), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidTransaction { + pub priority: ::core::primitive::u64, + pub requires: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub provides: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub longevity: ::core::primitive::u64, + pub propagate: ::core::primitive::bool, } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs index 09fb7863a8b1c..56dd7b487f55f 100644 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -44,7 +44,7 @@ pub type BridgePolkadotGrandpaCall = runtime_types::pallet_bridge_grandpa::palle /// Call of the with-PolkadotBridgeHub bridge parachains pallet. pub type BridgePolkadotParachainsCall = runtime_types::pallet_bridge_parachains::pallet::Call; /// Call of the with-PolkadotBridgeHub bridge messages pallet. -pub type BridgePolkadotBridgeHubMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgePolkadotMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; /// Polkadot header id. pub type HeaderId = diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 42d1c358c0a34..ced25fe8ddb26 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -169,6 +169,24 @@ impl UnsignedTransaction { Self { call, nonce, era: TransactionEra::Immortal, tip: Zero::zero() } } + /// Convert to the transaction of the other compatible chain. + pub fn switch_chain(self) -> UnsignedTransaction + where + Other: Chain< + Nonce = C::Nonce, + Balance = C::Balance, + BlockNumber = C::BlockNumber, + Hash = C::Hash, + >, + { + UnsignedTransaction { + call: EncodedOrDecodedCall::Encoded(self.call.into_encoded()), + nonce: self.nonce, + tip: self.tip, + era: self.era, + } + } + /// Set transaction tip. #[must_use] pub fn tip(mut self, tip: C::Balance) -> Self { From 88a0575dba6236fb535debd2a1e3d1ff65ed2803 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 15 Dec 2023 10:11:41 +0300 Subject: [PATCH 1159/1210] remove no longer valid check from the ensure_weights_are_correct (#2740) * remove no longer valid check from the ensure_weights_are_correct * fix compilation --- modules/messages/src/weights_ext.rs | 3 ++- relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/messages/src/weights_ext.rs b/modules/messages/src/weights_ext.rs index aeb3a581a69ee..c12e04f692bf8 100644 --- a/modules/messages/src/weights_ext.rs +++ b/modules/messages/src/weights_ext.rs @@ -60,7 +60,8 @@ pub fn ensure_weights_are_correct() { // W::receive_messages_delivery_proof_messages_overhead(1).ref_time() may be zero because: // there's no code that iterates over confirmed messages in confirmation transaction assert_eq!(W::receive_messages_delivery_proof_messages_overhead(1).proof_size(), 0); - assert_ne!(W::receive_messages_delivery_proof_relayers_overhead(1).ref_time(), 0); + // W::receive_messages_delivery_proof_relayers_overhead(1).ref_time() may be zero because: + // runtime **can** choose not to pay any rewards to relayers // W::receive_messages_delivery_proof_relayers_overhead(1).proof_size() is an exception // it may or may not cause additional db reads, so proof size may vary assert_ne!(W::storage_proof_size_overhead(1).ref_time(), 0); diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs index 7760913f61c83..7e37b62b68594 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs @@ -65,9 +65,8 @@ impl bp_header_chain::ChainWithGrandpa for RococoBaseAsPolkadot { const MAX_AUTHORITIES_COUNT: u32 = bp_rococo::Rococo::MAX_AUTHORITIES_COUNT; const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = bp_rococo::Rococo::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_HEADER_SIZE: u32 = bp_rococo::Rococo::MAX_HEADER_SIZE; - const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32 = - bp_rococo::Rococo::AVERAGE_HEADER_SIZE_IN_JUSTIFICATION; + const MAX_MANDATORY_HEADER_SIZE: u32 = bp_rococo::Rococo::MAX_MANDATORY_HEADER_SIZE; + const AVERAGE_HEADER_SIZE: u32 = bp_rococo::Rococo::AVERAGE_HEADER_SIZE; } /// Relay `Chain` implementation of Rococo, pretending to be Polkadot. From 42d10c184f5b50e31a2fd4fcf68e76dab5a08482 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 02:13:10 +0000 Subject: [PATCH 1160/1210] Bump thiserror from 1.0.50 to 1.0.51 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.50 to 1.0.51. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.50...1.0.51) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 9f710ec3c9fa4..fff118bd28a43 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -16,7 +16,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.35", features = ["rt-multi-thread"] } -thiserror = "1.0.50" +thiserror = "1.0.51" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index f4df31766fedb..5d73119aeb90b 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] anyhow = "1.0" -thiserror = "1.0.50" +thiserror = "1.0.51" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 6f1546e09f268..049368f72bbc4 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.35", features = ["rt"] } -thiserror = "1.0.50" +thiserror = "1.0.51" # Bridge dependencies From 89b031c1e58b2fe94cdafbe89adefd0e808b9692 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Wed, 20 Dec 2023 13:00:03 +0100 Subject: [PATCH 1161/1210] Pokladot sdk backport to staging (#2746) * Bump to `polkadot-sdk` master `ebe2aad6f0ae576a0e176f38a084fe7579f936dd` * align with others * Backport xcm version stuff from `polkadot-sdk` * Backport Slava's commit from `polkadot-sdk` * Workspace clippy as `polkadot-sdk` does * Make submodules use workspace lints * Add Bridges clippy addons to workspace lints * Looks like we dont need extra clippy addons anymore? --- bin/runtime-common/Cargo.toml | 5 +- .../src/messages_xcm_extension.rs | 22 +++++ modules/beefy/Cargo.toml | 3 + modules/grandpa/Cargo.toml | 3 + modules/messages/Cargo.toml | 3 + modules/parachains/Cargo.toml | 3 + modules/relayers/Cargo.toml | 3 + modules/xcm-bridge-hub-router/Cargo.toml | 3 + .../xcm-bridge-hub-router/src/benchmarking.rs | 12 +-- modules/xcm-bridge-hub-router/src/lib.rs | 96 +++++++++++-------- modules/xcm-bridge-hub-router/src/mock.rs | 20 +++- modules/xcm-bridge-hub/Cargo.toml | 3 + modules/xcm-bridge-hub/src/exporter.rs | 3 +- modules/xcm-bridge-hub/src/lib.rs | 28 +++++- modules/xcm-bridge-hub/src/mock.rs | 8 +- primitives/beefy/Cargo.toml | 3 + primitives/chain-asset-hub-rococo/Cargo.toml | 3 + primitives/chain-asset-hub-westend/Cargo.toml | 3 + .../chain-bridge-hub-cumulus/Cargo.toml | 3 + primitives/chain-bridge-hub-kusama/Cargo.toml | 3 + .../chain-bridge-hub-polkadot/Cargo.toml | 3 + primitives/chain-bridge-hub-rococo/Cargo.toml | 3 + primitives/chain-bridge-hub-rococo/src/lib.rs | 6 +- .../chain-bridge-hub-westend/Cargo.toml | 3 + .../chain-bridge-hub-westend/src/lib.rs | 6 +- primitives/chain-kusama/Cargo.toml | 3 + primitives/chain-polkadot-bulletin/Cargo.toml | 3 + primitives/chain-polkadot/Cargo.toml | 3 + primitives/chain-rococo/Cargo.toml | 3 + primitives/chain-westend/Cargo.toml | 3 + primitives/header-chain/Cargo.toml | 3 + primitives/messages/Cargo.toml | 3 + primitives/parachains/Cargo.toml | 3 + primitives/polkadot-core/Cargo.toml | 3 + primitives/relayers/Cargo.toml | 3 + primitives/runtime/Cargo.toml | 3 + primitives/test-utils/Cargo.toml | 3 + primitives/xcm-bridge-hub-router/Cargo.toml | 3 + primitives/xcm-bridge-hub/Cargo.toml | 3 + relays/bin-substrate/Cargo.toml | 3 + relays/client-bridge-hub-kusama/Cargo.toml | 3 + relays/client-bridge-hub-polkadot/Cargo.toml | 3 + relays/client-bridge-hub-rococo/Cargo.toml | 3 + relays/client-bridge-hub-westend/Cargo.toml | 3 + relays/client-kusama/Cargo.toml | 3 + relays/client-polkadot-bulletin/Cargo.toml | 3 + relays/client-polkadot/Cargo.toml | 3 + relays/client-rococo/Cargo.toml | 3 + relays/client-substrate/Cargo.toml | 3 + relays/client-westend/Cargo.toml | 3 + relays/equivocation/Cargo.toml | 3 + relays/finality/Cargo.toml | 3 + relays/lib-substrate-relay/Cargo.toml | 3 + relays/messages/Cargo.toml | 3 + relays/parachains/Cargo.toml | 5 +- relays/utils/Cargo.toml | 3 + 56 files changed, 288 insertions(+), 58 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 1b81919434143..b642f738d6e80 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -7,6 +7,9 @@ edition.workspace = true repository.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } @@ -59,8 +62,8 @@ std = [ "bp-polkadot-core/std", "bp-relayers/std", "bp-runtime/std", - "bp-xcm-bridge-hub/std", "bp-xcm-bridge-hub-router/std", + "bp-xcm-bridge-hub/std", "codec/std", "frame-support/std", "frame-system/std", diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 0159ede648136..53c0579c4cd04 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -309,6 +309,28 @@ impl LocalXcmQueueManager { } } +/// Adapter for the implementation of `GetVersion`, which attempts to find the minimal +/// configured XCM version between the destination `dest` and the bridge hub location provided as +/// `Get`. +pub struct XcmVersionOfDestAndRemoteBridge( + sp_std::marker::PhantomData<(Version, RemoteBridge)>, +); +impl> GetVersion + for XcmVersionOfDestAndRemoteBridge +{ + fn get_version_for(dest: &MultiLocation) -> Option { + let dest_version = Version::get_version_for(dest); + let bridge_hub_version = Version::get_version_for(&RemoteBridge::get()); + + match (dest_version, bridge_hub_version) { + (Some(dv), Some(bhv)) => Some(sp_std::cmp::min(dv, bhv)), + (Some(dv), None) => Some(dv), + (None, Some(bhv)) => Some(bhv), + (None, None) => None, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 5d699019e63ec..9e9a23c2fff7b 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -6,6 +6,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 4d8a5c074461a..e7e8c5c6fe747 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 0c8c0f7b82421..01dd3dbcbde76 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index f8160e3c6c892..239f5262c8bb2 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index cbaedd4c73ee5..73cc343a193e8 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index e3a559cdc00a0..6d3e1c5ab454e 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/modules/xcm-bridge-hub-router/src/benchmarking.rs index c4d1e3971e747..922e4bf94ba8a 100644 --- a/modules/xcm-bridge-hub-router/src/benchmarking.rs +++ b/modules/xcm-bridge-hub-router/src/benchmarking.rs @@ -21,7 +21,7 @@ use crate::{Bridge, Call}; use bp_xcm_bridge_hub_router::{BridgeState, MINIMAL_DELIVERY_FEE_FACTOR}; -use frame_benchmarking::benchmarks_instance_pallet; +use frame_benchmarking::{benchmarks_instance_pallet, BenchmarkError}; use frame_support::traits::{EnsureOrigin, Get, Hooks, UnfilteredDispatchable}; use sp_runtime::traits::Zero; use xcm::prelude::*; @@ -37,11 +37,11 @@ pub trait Config: crate::Config { /// Returns destination which is valid for this router instance. /// (Needs to pass `T::Bridges`) /// Make sure that `SendXcm` will pass. - fn ensure_bridged_target_destination() -> MultiLocation { - MultiLocation::new( + fn ensure_bridged_target_destination() -> Result { + Ok(MultiLocation::new( Self::UniversalLocation::get().len() as u8, X1(GlobalConsensus(Self::BridgedNetworkId::get().unwrap())), - ) + )) } } @@ -61,7 +61,7 @@ benchmarks_instance_pallet! { delivery_fee_factor: MINIMAL_DELIVERY_FEE_FACTOR + MINIMAL_DELIVERY_FEE_FACTOR, }); - let _ = T::ensure_bridged_target_destination(); + let _ = T::ensure_bridged_target_destination()?; T::make_congested(); }: { crate::Pallet::::on_initialize(Zero::zero()) @@ -81,7 +81,7 @@ benchmarks_instance_pallet! { } send_message { - let dest = T::ensure_bridged_target_destination(); + let dest = T::ensure_bridged_target_destination()?; let xcm = sp_std::vec![].into(); // make local queue congested, because it means additional db write diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs index cf51ef82412fb..229628aedcb8a 100644 --- a/modules/xcm-bridge-hub-router/src/lib.rs +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -89,6 +89,8 @@ pub mod pallet { /// **possible fee**. Allows to externalize better control over allowed **bridged /// networks/locations**. type Bridges: ExporterFor; + /// Checks the XCM version for the destination. + type DestinationVersion: GetVersion; /// Origin of the sibling bridge hub that is allowed to report bridge status. type BridgeHubOrigin: EnsureOrigin; @@ -319,12 +321,13 @@ impl, I: 'static> SendXcm for Pallet { dest: &mut Option, xcm: &mut Option>, ) -> SendResult { - // we won't have an access to `dest` and `xcm` in the `delvier` method, so precompute + // `dest` and `xcm` are required here + let dest_ref = dest.as_ref().ok_or(SendError::MissingArgument)?; + let xcm_ref = xcm.as_ref().ok_or(SendError::MissingArgument)?; + + // we won't have an access to `dest` and `xcm` in the `deliver` method, so precompute // everything required here - let message_size = xcm - .as_ref() - .map(|xcm| xcm.encoded_size() as _) - .ok_or(SendError::MissingArgument)?; + let message_size = xcm_ref.encoded_size() as _; // bridge doesn't support oversized/overweight messages now. So it is better to drop such // messages here than at the bridge hub. Let's check the message size. @@ -332,6 +335,18 @@ impl, I: 'static> SendXcm for Pallet { return Err(SendError::ExceedsMaxMessageSize) } + // We need to ensure that the known `dest`'s XCM version can comprehend the current `xcm` + // program. This may seem like an additional, unnecessary check, but it is not. A similar + // check is probably performed by the `ViaBridgeHubExporter`, which attempts to send a + // versioned message to the sibling bridge hub. However, the local bridge hub may have a + // higher XCM version than the remote `dest`. Once again, it is better to discard such + // messages here than at the bridge hub (e.g., to avoid losing funds). + let destination_version = T::DestinationVersion::get_version_for(dest_ref) + .ok_or(SendError::DestinationUnsupported)?; + let _ = VersionedXcm::from(xcm_ref.clone()) + .into_version(destination_version) + .map_err(|()| SendError::DestinationUnsupported)?; + // just use exporter to validate destination and insert instructions to pay message fee // at the sibling/child bridge hub // @@ -358,6 +373,7 @@ impl, I: 'static> SendXcm for Pallet { #[cfg(test)] mod tests { use super::*; + use frame_support::assert_ok; use mock::*; use frame_support::traits::Hooks; @@ -451,6 +467,19 @@ mod tests { }); } + #[test] + fn destination_unsupported_if_wrap_version_fails() { + run_test(|| { + assert_eq!( + send_xcm::( + UnknownXcmVersionLocation::get(), + vec![ClearOrigin].into(), + ), + Err(SendError::DestinationUnsupported), + ); + }); + } + #[test] fn returns_proper_delivery_price() { run_test(|| { @@ -488,17 +517,14 @@ mod tests { fn sent_message_doesnt_increase_factor_if_xcm_channel_is_uncongested() { run_test(|| { let old_bridge = XcmBridgeHubRouter::bridge(); - assert_eq!( - send_xcm::( - MultiLocation::new( - 2, - X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) - ), - vec![ClearOrigin].into(), - ) - .map(drop), - Ok(()), - ); + assert_ok!(send_xcm::( + MultiLocation::new( + 2, + X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) + ), + vec![ClearOrigin].into(), + ) + .map(drop)); assert!(TestToBridgeHubSender::is_message_sent()); assert_eq!(old_bridge, XcmBridgeHubRouter::bridge()); @@ -511,17 +537,14 @@ mod tests { TestWithBridgeHubChannel::make_congested(); let old_bridge = XcmBridgeHubRouter::bridge(); - assert_eq!( - send_xcm::( - MultiLocation::new( - 2, - X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) - ), - vec![ClearOrigin].into(), - ) - .map(drop), - Ok(()), - ); + assert_ok!(send_xcm::( + MultiLocation::new( + 2, + X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) + ), + vec![ClearOrigin].into(), + ) + .map(drop)); assert!(TestToBridgeHubSender::is_message_sent()); assert!( @@ -536,17 +559,14 @@ mod tests { Bridge::::put(congested_bridge(MINIMAL_DELIVERY_FEE_FACTOR)); let old_bridge = XcmBridgeHubRouter::bridge(); - assert_eq!( - send_xcm::( - MultiLocation::new( - 2, - X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) - ), - vec![ClearOrigin].into(), - ) - .map(drop), - Ok(()), - ); + assert_ok!(send_xcm::( + MultiLocation::new( + 2, + X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) + ), + vec![ClearOrigin].into(), + ) + .map(drop)); assert!(TestToBridgeHubSender::is_message_sent()); assert!( diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 2d173ebc0457a..9079f4b9c4c64 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -19,7 +19,10 @@ use crate as pallet_xcm_bridge_hub_router; use bp_xcm_bridge_hub_router::XcmChannelStatusProvider; -use frame_support::{construct_runtime, derive_impl, parameter_types}; +use frame_support::{ + construct_runtime, derive_impl, parameter_types, + traits::{Contains, Equals}, +}; use frame_system::EnsureRoot; use sp_runtime::{traits::ConstU128, BuildStorage}; use xcm::prelude::*; @@ -58,6 +61,7 @@ parameter_types! { Some((BridgeFeeAsset::get(), BASE_FEE).into()) ) ]; + pub UnknownXcmVersionLocation: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(9999))); } #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] @@ -71,6 +75,8 @@ impl pallet_xcm_bridge_hub_router::Config<()> for TestRuntime { type UniversalLocation = UniversalLocation; type BridgedNetworkId = BridgedNetworkId; type Bridges = NetworkExportTable; + type DestinationVersion = + LatestOrNoneForLocationVersionChecker>; type BridgeHubOrigin = EnsureRoot; type ToBridgeHubSender = TestToBridgeHubSender; @@ -80,6 +86,18 @@ impl pallet_xcm_bridge_hub_router::Config<()> for TestRuntime { type FeeAsset = BridgeFeeAsset; } +pub struct LatestOrNoneForLocationVersionChecker(sp_std::marker::PhantomData); +impl> GetVersion + for LatestOrNoneForLocationVersionChecker +{ + fn get_version_for(dest: &MultiLocation) -> Option { + if Location::contains(dest) { + return None + } + Some(XCM_VERSION) + } +} + pub struct TestToBridgeHubSender; impl TestToBridgeHubSender { diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 151b19a527185..4dac474413afc 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { version = "0.4.20", default-features = false } diff --git a/modules/xcm-bridge-hub/src/exporter.rs b/modules/xcm-bridge-hub/src/exporter.rs index 445551d693430..5318b222c5452 100644 --- a/modules/xcm-bridge-hub/src/exporter.rs +++ b/modules/xcm-bridge-hub/src/exporter.rs @@ -33,7 +33,8 @@ use xcm_executor::traits::ExportXcm; /// An easy way to access `HaulBlobExporter`. pub type PalletAsHaulBlobExporter = HaulBlobExporter< DummyHaulBlob, - >::BridgedNetworkId, + >::BridgedNetwork, + >::DestinationVersion, >::MessageExportPrice, >; /// An easy way to access associated messages pallet. diff --git a/modules/xcm-bridge-hub/src/lib.rs b/modules/xcm-bridge-hub/src/lib.rs index 14439a4d8ffe8..44f6903b018b8 100644 --- a/modules/xcm-bridge-hub/src/lib.rs +++ b/modules/xcm-bridge-hub/src/lib.rs @@ -37,6 +37,7 @@ pub mod pallet { use super::*; use bridge_runtime_common::messages_xcm_extension::SenderAndLane; use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::BlockNumberFor; #[pallet::config] #[pallet::disable_frame_system_supertrait_check] @@ -48,15 +49,17 @@ pub mod pallet { // TODO: https://github.com/paritytech/parity-bridges-common/issues/1666 remove `ChainId` and // replace it with the `NetworkId` - then we'll be able to use // `T as pallet_bridge_messages::Config::BridgedChain::NetworkId` - /// Bridged network id. + /// Bridged network as relative location of bridged `GlobalConsensus`. #[pallet::constant] - type BridgedNetworkId: Get; + type BridgedNetwork: Get; /// Associated messages pallet instance that bridges us with the /// `BridgedNetworkId` consensus. type BridgeMessagesPalletInstance: 'static; /// Price of single message export to the bridged consensus (`Self::BridgedNetworkId`). type MessageExportPrice: Get; + /// Checks the XCM version for the destination. + type DestinationVersion: GetVersion; /// Get point-to-point links with bridged consensus (`Self::BridgedNetworkId`). /// (this will be replaced with dynamic on-chain bridges - `Bridges V2`) @@ -69,6 +72,17 @@ pub mod pallet { #[pallet::pallet] pub struct Pallet(PhantomData<(T, I)>); + #[pallet::hooks] + impl, I: 'static> Hooks> for Pallet { + fn integrity_test() { + assert!( + Self::bridged_network_id().is_some(), + "Configured `T::BridgedNetwork`: {:?} does not contain `GlobalConsensus` junction with `NetworkId`", + T::BridgedNetwork::get() + ) + } + } + impl, I: 'static> Pallet { /// Returns dedicated/configured lane identifier. pub(crate) fn lane_for( @@ -83,7 +97,7 @@ pub mod pallet { .find_map(|(lane_source, (lane_dest_network, lane_dest))| { if lane_source.location == source && &lane_dest_network == dest.0 && - &T::BridgedNetworkId::get() == dest.0 && + Self::bridged_network_id().as_ref() == Some(dest.0) && &lane_dest == dest.1 { Some(lane_source) @@ -92,5 +106,13 @@ pub mod pallet { } }) } + + /// Returns some `NetworkId` if contains `GlobalConsensus` junction. + fn bridged_network_id() -> Option { + match T::BridgedNetwork::get().take_first_interior() { + Some(GlobalConsensus(network)) => Some(network), + _ => None, + } + } } } diff --git a/modules/xcm-bridge-hub/src/mock.rs b/modules/xcm-bridge-hub/src/mock.rs index 7766aac1fb73f..8edd4b1f7aa9b 100644 --- a/modules/xcm-bridge-hub/src/mock.rs +++ b/modules/xcm-bridge-hub/src/mock.rs @@ -170,6 +170,10 @@ impl pallet_bridge_messages::WeightInfoExt for TestMessagesWeights { parameter_types! { pub const RelayNetwork: NetworkId = NetworkId::Kusama; pub const BridgedRelayNetwork: NetworkId = NetworkId::Polkadot; + pub const BridgedRelayNetworkLocation: MultiLocation = MultiLocation { + parents: 1, + interior: X1(GlobalConsensus(BridgedRelayNetwork::get())) + }; pub const NonBridgedRelayNetwork: NetworkId = NetworkId::Rococo; pub const BridgeReserve: Balance = 100_000; pub UniversalLocation: InteriorMultiLocation = X2( @@ -181,10 +185,12 @@ parameter_types! { impl pallet_xcm_bridge_hub::Config for TestRuntime { type UniversalLocation = UniversalLocation; - type BridgedNetworkId = BridgedRelayNetwork; + type BridgedNetwork = BridgedRelayNetworkLocation; type BridgeMessagesPalletInstance = (); type MessageExportPrice = (); + type DestinationVersion = AlwaysLatest; + type Lanes = TestLanes; type LanesSupport = TestXcmBlobHauler; } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 09ff1fdb1fbcf..74e8f0492d8a3 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -6,6 +6,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/primitives/chain-asset-hub-rococo/Cargo.toml index 5d86c7ebc6e68..c4da8ee0eafcd 100644 --- a/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/primitives/chain-asset-hub-rococo/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/primitives/chain-asset-hub-westend/Cargo.toml b/primitives/chain-asset-hub-westend/Cargo.toml index 59629309e6f93..a148cf31ca778 100644 --- a/primitives/chain-asset-hub-westend/Cargo.toml +++ b/primitives/chain-asset-hub-westend/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index f0c2b5c2a1420..08f561b4f5cbf 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml index 1ed02b9b2d528..4e1b3a6334c8e 100644 --- a/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml index eebc4dfffd13e..2f53cca46a8af 100644 --- a/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index a3f2b9c28c935..e4bbc1a08987e 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 1fe44597c3d40..f79b8a8afb321 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -86,13 +86,13 @@ frame_support::parameter_types! { /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Rococo /// BridgeHub. /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubRococoBaseXcmFeeInRocs: u128 = 1628875538; + pub const BridgeHubRococoBaseXcmFeeInRocs: u128 = 1_640_102_205; /// Transaction fee that is paid at the Rococo BridgeHub for delivering single inbound message. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) - pub const BridgeHubRococoBaseDeliveryFeeInRocs: u128 = 6417262881; + pub const BridgeHubRococoBaseDeliveryFeeInRocs: u128 = 5_651_581_649; /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 6159996668; + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 4_045_736_577; } diff --git a/primitives/chain-bridge-hub-westend/Cargo.toml b/primitives/chain-bridge-hub-westend/Cargo.toml index eea808ea2b568..333e49883f8bc 100644 --- a/primitives/chain-bridge-hub-westend/Cargo.toml +++ b/primitives/chain-bridge-hub-westend/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-bridge-hub-westend/src/lib.rs b/primitives/chain-bridge-hub-westend/src/lib.rs index 0124e05bf8871..f4524f719f9fd 100644 --- a/primitives/chain-bridge-hub-westend/src/lib.rs +++ b/primitives/chain-bridge-hub-westend/src/lib.rs @@ -78,13 +78,13 @@ frame_support::parameter_types! { /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Westend /// BridgeHub. /// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubWestendBaseXcmFeeInWnds: u128 = 488662666666; + pub const BridgeHubWestendBaseXcmFeeInWnds: u128 = 492_077_333_333; /// Transaction fee that is paid at the Westend BridgeHub for delivering single inbound message. /// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) - pub const BridgeHubWestendBaseDeliveryFeeInWnds: u128 = 1925196628010; + pub const BridgeHubWestendBaseDeliveryFeeInWnds: u128 = 1_695_489_961_344; /// Transaction fee that is paid at the Westend BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubWestendBaseConfirmationFeeInWnds: u128 = 1848016628010; + pub const BridgeHubWestendBaseConfirmationFeeInWnds: u128 = 1_618_309_961_344; } diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index b08489aea82da..ed057098813ab 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index b610b268d9a4d..3fe83b8cae7f6 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 7ea28bd24b08f..5180c34d932f6 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 5e6e9bb73d266..7d78b3ff51324 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index b28e250554e42..23cfc8de9d744 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 51d9b2f30f591..415b165101d9b 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 10369e8c92253..02388a30e74a9 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 569fa535a2817..524b95e3b6fe6 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index e9542f6f5b345..7b8b92b62fc7d 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 060e36a5f0027..5eedf738a4178 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index b52d20d691600..0874926895827 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } hash-db = { version = "0.16.0", default-features = false } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 7432841760638..3c24e1fed0f98 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] bp-header-chain = { path = "../header-chain", default-features = false } bp-parachains = { path = "../parachains", default-features = false } diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index 6cf260ce5e9b5..8000e48992cf6 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } diff --git a/primitives/xcm-bridge-hub/Cargo.toml b/primitives/xcm-bridge-hub/Cargo.toml index 761fbef46e22c..b2dc09bdf8c8a 100644 --- a/primitives/xcm-bridge-hub/Cargo.toml +++ b/primitives/xcm-bridge-hub/Cargo.toml @@ -6,6 +6,9 @@ authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] # Substrate Dependencies diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 6b9114e3d7e53..933e16c22afd2 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] anyhow = "1.0" async-std = "1.9.0" diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index 2eb175a2a8b0b..19a8e25a7027a 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index 3976652215a49..7cac7f4973be0 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 894965ababc77..04b0d0d38e51c 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml index a147aaee43917..4eae91963a2ae 100644 --- a/relays/client-bridge-hub-westend/Cargo.toml +++ b/relays/client-bridge-hub-westend/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index fee0db14a511b..3fa32aa4844a5 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml index 29118d41364c2..b0eafc963389a 100644 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 58a7b058f0ec9..52c836e14566a 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index b6d603d436482..bcc4c7ab147cf 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index fff118bd28a43..ec949c24bca47 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 0c6083f8f8c83..1933a1f4130c6 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index d14177bacec8c..7773d1e1f570a 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -6,6 +6,9 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Equivocation detector" +[lints] +workspace = true + [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 725ac5386b1b4..15f00aab4ab19 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -6,6 +6,9 @@ edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" +[lints] +workspace = true + [dependencies] async-std = "1.6.5" async-trait = "0.1" diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 5d73119aeb90b..cde5ba819f500 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] anyhow = "1.0" thiserror = "1.0.51" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index ccaed009a5ab4..9ba220d45d6b8 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 89aab19b4b556..18753759ae0ed 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -5,9 +5,12 @@ authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] async-std = "1.6.5" -async-trait = "0.1.74" +async-trait = "0.1" futures = "0.3.29" log = "0.4.20" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 049368f72bbc4..311d0d87b84d6 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -5,6 +5,9 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +[lints] +workspace = true + [dependencies] ansi_term = "0.12" anyhow = "1.0" From 927bea56fa9779bb9d3e9e7db979da8955f2cb63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Dec 2023 02:25:34 +0000 Subject: [PATCH 1162/1210] Bump futures from 0.3.29 to 0.3.30 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.29 to 0.3.30. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.29...0.3.30) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/equivocation/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 933e16c22afd2..c20a84c769cef 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -14,7 +14,7 @@ async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } env_logger = "0.10" -futures = "0.3.29" +futures = "0.3.30" hex = "0.4" log = "0.4.20" num-format = "0.4" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index ec949c24bca47..b4d08af876f8d 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -12,7 +12,7 @@ workspace = true async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.29" +futures = "0.3.30" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = "0.4.20" num-traits = "0.2" diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 7773d1e1f570a..2cc41dd60ec23 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -futures = "0.3.29" +futures = "0.3.30" log = "0.4.20" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 15f00aab4ab19..1f2173630e08b 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -14,7 +14,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } -futures = "0.3.29" +futures = "0.3.30" log = "0.4.20" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index cde5ba819f500..4270cbc027b17 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -14,7 +14,7 @@ thiserror = "1.0.51" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -futures = "0.3.29" +futures = "0.3.30" hex = "0.4" num-traits = "0.2" log = "0.4.20" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 9ba220d45d6b8..6f4a2596f122b 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -12,7 +12,7 @@ workspace = true async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" env_logger = "0.10" -futures = "0.3.29" +futures = "0.3.30" hex = "0.4" log = "0.4.20" num-traits = "0.2" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 18753759ae0ed..12d5d8e928134 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-std = "1.6.5" async-trait = "0.1" -futures = "0.3.29" +futures = "0.3.30" log = "0.4.20" relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 311d0d87b84d6..8c2992531bee2 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -16,7 +16,7 @@ async-trait = "0.1" backoff = "0.4" isahc = "1.2" env_logger = "0.10.1" -futures = "0.3.29" +futures = "0.3.30" jsonpath_lib = "0.3" log = "0.4.20" num-traits = "0.2" From e2039e31512cff9ee14976b475df0a483e7c9020 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 02:58:04 +0000 Subject: [PATCH 1163/1210] Bump thiserror from 1.0.51 to 1.0.53 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.51 to 1.0.53. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.51...1.0.53) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index b4d08af876f8d..c53f520cd0732 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -19,7 +19,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.35", features = ["rt-multi-thread"] } -thiserror = "1.0.51" +thiserror = "1.0.53" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 4270cbc027b17..08f21947d1203 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = "1.0.51" +thiserror = "1.0.53" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 8c2992531bee2..ff1613296563c 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -24,7 +24,7 @@ serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.35", features = ["rt"] } -thiserror = "1.0.51" +thiserror = "1.0.53" # Bridge dependencies From 1258267643c97cb09fd484bde7432655a105cc95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 02:55:44 +0000 Subject: [PATCH 1164/1210] Bump tempfile from 3.8.1 to 3.9.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.8.1 to 3.9.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.8.1...v3.9.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index c20a84c769cef..88c22fa8f232f 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -62,5 +62,5 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.4" sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -tempfile = "3.8" +tempfile = "3.9" finality-grandpa = { version = "0.16.2" } From c85b035763966d8c054c3bf6c5406f7db1359a66 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Wed, 3 Jan 2024 12:13:32 +0300 Subject: [PATCH 1165/1210] get rid of LaneMessageVerifier (#2168) (#2764) --- bin/runtime-common/src/messages.rs | 41 ++----------------------- bin/runtime-common/src/mock.rs | 3 +- modules/messages/README.md | 26 ++++------------ modules/messages/src/lib.rs | 34 ++------------------ modules/messages/src/mock.rs | 28 ++--------------- primitives/messages/src/source_chain.rs | 32 ++----------------- 6 files changed, 15 insertions(+), 149 deletions(-) diff --git a/bin/runtime-common/src/messages.rs b/bin/runtime-common/src/messages.rs index ac66adae6614b..4aca53f3b9836 100644 --- a/bin/runtime-common/src/messages.rs +++ b/bin/runtime-common/src/messages.rs @@ -24,7 +24,7 @@ pub use bp_runtime::{RangeInclusiveExt, UnderlyingChainOf, UnderlyingChainProvid use bp_header_chain::HeaderChain; use bp_messages::{ - source_chain::{LaneMessageVerifier, TargetHeaderChain}, + source_chain::TargetHeaderChain, target_chain::{ProvedLaneMessages, ProvedMessages, SourceHeaderChain}, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, OutboundLaneData, VerificationError, @@ -120,42 +120,6 @@ pub mod source { pub type ParsedMessagesDeliveryProofFromBridgedChain = (LaneId, InboundLaneData>>); - /// Message verifier that is doing all basic checks. - /// - /// This verifier assumes following: - /// - /// - all message lanes are equivalent, so all checks are the same; - /// - /// Following checks are made: - /// - /// - message is rejected if its lane is currently blocked; - /// - message is rejected if there are too many pending (undelivered) messages at the outbound - /// lane; - /// - check that the sender has rights to dispatch the call on target chain using provided - /// dispatch origin; - /// - check that the sender has paid enough funds for both message delivery and dispatch. - #[derive(RuntimeDebug)] - pub struct FromThisChainMessageVerifier(PhantomData); - - impl LaneMessageVerifier for FromThisChainMessageVerifier - where - B: MessageBridge, - { - fn verify_message( - _lane: &LaneId, - _lane_outbound_data: &OutboundLaneData, - _payload: &FromThisChainMessagePayload, - ) -> Result<(), VerificationError> { - // IMPORTANT: any error that is returned here is fatal for the bridge, because - // this code is executed at the bridge hub and message sender actually lives - // at some sibling parachain. So we are failing **after** the message has been - // sent and we can't report it back to sender (unless error report mechanism is - // embedded into message and its dispatcher). - - Ok(()) - } - } - /// Return maximal message size of This -> Bridged chain message. pub fn maximal_message_size() -> u32 { super::target::maximal_incoming_message_size( @@ -185,8 +149,7 @@ pub mod source { /// Do basic Bridged-chain specific verification of This -> Bridged chain message. /// /// Ok result from this function means that the delivery transaction with this message - /// may be 'mined' by the target chain. But the lane may have its own checks (e.g. fee - /// check) that would reject message (see `FromThisChainMessageVerifier`). + /// may be 'mined' by the target chain. pub fn verify_chain_message( payload: &FromThisChainMessagePayload, ) -> Result<(), VerificationError> { diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index bd47d37fc07d0..b783ce987ced3 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -21,7 +21,7 @@ use crate::messages::{ source::{ FromThisChainMaximalOutboundPayloadSize, FromThisChainMessagePayload, - FromThisChainMessageVerifier, TargetHeaderChainAdapter, + TargetHeaderChainAdapter, }, target::{FromBridgedChainMessagePayload, SourceHeaderChainAdapter}, BridgedChainWithMessages, HashOf, MessageBridge, ThisChainWithMessages, @@ -213,7 +213,6 @@ impl pallet_bridge_messages::Config for TestRuntime { type DeliveryPayments = (); type TargetHeaderChain = TargetHeaderChainAdapter; - type LaneMessageVerifier = FromThisChainMessageVerifier; type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< TestRuntime, (), diff --git a/modules/messages/README.md b/modules/messages/README.md index 457d5f5facfa7..fe62305748cd1 100644 --- a/modules/messages/README.md +++ b/modules/messages/README.md @@ -116,26 +116,12 @@ maximal possible transaction size of the chain and so on. And when the relayer s implementation must be able to parse and verify the proof of messages delivery. Normally, you would reuse the same (configurable) type on all chains that are sending messages to the same bridged chain. -The `pallet_bridge_messages::Config::LaneMessageVerifier` defines a single callback to verify outbound messages. The -simplest callback may just accept all messages. But in this case you'll need to answer many questions first. Who will -pay for the delivery and confirmation transaction? Are we sure that someone will ever deliver this message to the -bridged chain? Are we sure that we don't bloat our runtime storage by accepting this message? What if the message is -improperly encoded or has some fields set to invalid values? Answering all those (and similar) questions would lead to -correct implementation. - -There's another thing to consider when implementing type for use in -`pallet_bridge_messages::Config::LaneMessageVerifier`. It is whether we treat all message lanes identically, or they'll -have different sets of verification rules? For example, you may reserve lane#1 for messages coming from some -'wrapped-token' pallet - then you may verify in your implementation that the origin is associated with this pallet. -Lane#2 may be reserved for 'system' messages and you may charge zero fee for such messages. You may have some rate -limiting for messages sent over the lane#3. Or you may just verify the same rules set for all outbound messages - it is -all up to the `pallet_bridge_messages::Config::LaneMessageVerifier` implementation. - -The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation transaction is -received, we call the `pay_reward()` method, passing the range of delivered messages. You may use the -[`pallet-bridge-relayers`](../relayers/) pallet and its -[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible implementation. It -allows you to pay fixed reward for relaying the message and some of its portion for confirming delivery. +The last type is the `pallet_bridge_messages::Config::DeliveryConfirmationPayments`. When confirmation +transaction is received, we call the `pay_reward()` method, passing the range of delivered messages. +You may use the [`pallet-bridge-relayers`](../relayers/) pallet and its +[`DeliveryConfirmationPaymentsAdapter`](../relayers/src/payment_adapter.rs) adapter as a possible +implementation. It allows you to pay fixed reward for relaying the message and some of its portion +for confirming delivery. ### I have a Messages Module in my Runtime, but I Want to Reject all Outbound Messages. What shall I do? diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index b87c64d160752..eeae95b482c86 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -53,8 +53,7 @@ use crate::{ use bp_messages::{ source_chain::{ - DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, - SendMessageArtifacts, TargetHeaderChain, + DeliveryConfirmationPayments, OnMessagesDelivered, SendMessageArtifacts, TargetHeaderChain, }, target_chain::{ DeliveryPayments, DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, @@ -155,8 +154,6 @@ pub mod pallet { /// Target header chain. type TargetHeaderChain: TargetHeaderChain; - /// Message payload verifier. - type LaneMessageVerifier: LaneMessageVerifier; /// Delivery confirmation payments. type DeliveryConfirmationPayments: DeliveryConfirmationPayments; /// Delivery confirmation callback. @@ -723,20 +720,8 @@ fn send_message, I: 'static>( Error::::MessageRejectedByChainVerifier(err) })?; - // now let's enforce any additional lane rules - let mut lane = outbound_lane::(lane_id); - T::LaneMessageVerifier::verify_message(&lane_id, &lane.data(), &payload).map_err(|err| { - log::trace!( - target: LOG_TARGET, - "Message to lane {:?} is rejected by lane verifier: {:?}", - lane_id, - err, - ); - - Error::::MessageRejectedByLaneVerifier(err) - })?; - // finally, save message in outbound storage and emit event + let mut lane = outbound_lane::(lane_id); let encoded_payload = payload.encode(); let encoded_payload_len = encoded_payload.len(); let nonce = lane @@ -1151,21 +1136,6 @@ mod tests { }); } - #[test] - fn lane_verifier_rejects_invalid_message_in_send_message() { - run_test(|| { - // messages with zero fee are rejected by lane verifier - let mut message = REGULAR_PAYLOAD; - message.reject_by_lane_verifier = true; - assert_noop!( - send_message::(TEST_LANE_ID, message,), - Error::::MessageRejectedByLaneVerifier(VerificationError::Other( - mock::TEST_ERROR - )), - ); - }); - } - #[test] fn receive_messages_proof_works() { run_test(|| { diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 648acad772d7a..303e641ea2d3c 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -21,15 +21,13 @@ use crate::Config; use bp_messages::{ calc_relayers_rewards, - source_chain::{ - DeliveryConfirmationPayments, LaneMessageVerifier, OnMessagesDelivered, TargetHeaderChain, - }, + source_chain::{DeliveryConfirmationPayments, OnMessagesDelivered, TargetHeaderChain}, target_chain::{ DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, - OutboundLaneData, UnrewardedRelayer, UnrewardedRelayersState, VerificationError, + UnrewardedRelayer, UnrewardedRelayersState, VerificationError, }; use bp_runtime::{messages::MessageDispatchResult, Size}; use codec::{Decode, Encode}; @@ -50,8 +48,6 @@ pub type Balance = u64; pub struct TestPayload { /// Field that may be used to identify messages. pub id: u64, - /// Reject this message by lane verifier? - pub reject_by_lane_verifier: bool, /// Dispatch weight that is declared by the message sender. pub declared_weight: Weight, /// Message dispatch result. @@ -120,7 +116,6 @@ impl Config for TestRuntime { type DeliveryPayments = TestDeliveryPayments; type TargetHeaderChain = TestTargetHeaderChain; - type LaneMessageVerifier = TestLaneMessageVerifier; type DeliveryConfirmationPayments = TestDeliveryConfirmationPayments; type OnMessagesDelivered = TestOnMessagesDelivered; @@ -268,24 +263,6 @@ impl TargetHeaderChain for TestTargetHeaderChain { } } -/// Lane message verifier that is used in tests. -#[derive(Debug, Default)] -pub struct TestLaneMessageVerifier; - -impl LaneMessageVerifier for TestLaneMessageVerifier { - fn verify_message( - _lane: &LaneId, - _lane_outbound_data: &OutboundLaneData, - payload: &TestPayload, - ) -> Result<(), VerificationError> { - if !payload.reject_by_lane_verifier { - Ok(()) - } else { - Err(VerificationError::Other(TEST_ERROR)) - } - } -} - /// Reward payments at the target chain during delivery transaction. #[derive(Debug, Default)] pub struct TestDeliveryPayments; @@ -438,7 +415,6 @@ pub fn inbound_message_data(payload: TestPayload) -> DispatchMessageData TestPayload { TestPayload { id, - reject_by_lane_verifier: false, declared_weight: Weight::from_parts(declared_weight, 0), dispatch_result: dispatch_result(0), extra: Vec::new(), diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 73092c3cce0a5..56bcf0bb4bc0d 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -16,7 +16,7 @@ //! Primitives of messages module, that are used on the source chain. -use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData, VerificationError}; +use crate::{InboundLaneData, LaneId, MessageNonce, VerificationError}; use crate::UnrewardedRelayer; use bp_runtime::Size; @@ -64,24 +64,6 @@ pub trait TargetHeaderChain { ) -> Result<(LaneId, InboundLaneData), VerificationError>; } -/// Lane message verifier. -/// -/// Runtime developer may implement any additional validation logic over message-lane mechanism. -/// E.g. if lanes should have some security (e.g. you can only accept Lane1 messages from -/// Submitter1, Lane2 messages for those who has submitted first message to this lane, disable -/// Lane3 until some block, ...), then it may be built using this verifier. -/// -/// Any fee requirements should also be enforced here. -pub trait LaneMessageVerifier { - /// Verify message payload and return Ok(()) if message is valid and allowed to be sent over the - /// lane. - fn verify_message( - lane: &LaneId, - outbound_data: &OutboundLaneData, - payload: &Payload, - ) -> Result<(), VerificationError>; -} - /// Manages payments that are happening at the source chain during delivery confirmation /// transaction. pub trait DeliveryConfirmationPayments { @@ -161,7 +143,7 @@ impl MessagesBridge for NoopMessagesBridge { } } -/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and +/// Structure that may be used in place of `TargetHeaderChain` and /// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden. pub struct ForbidOutboundMessages; @@ -183,16 +165,6 @@ impl TargetHeaderChain for ForbidOutboun } } -impl LaneMessageVerifier for ForbidOutboundMessages { - fn verify_message( - _lane: &LaneId, - _outbound_data: &OutboundLaneData, - _payload: &Payload, - ) -> Result<(), VerificationError> { - Err(VerificationError::Other(ALL_OUTBOUND_MESSAGES_REJECTED)) - } -} - impl DeliveryConfirmationPayments for ForbidOutboundMessages { type Error = &'static str; From 053a147d20f6b6beb92596827f5e864eb9f4ba28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 02:40:07 +0000 Subject: [PATCH 1166/1210] Bump thiserror from 1.0.53 to 1.0.55 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.53 to 1.0.55. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.53...1.0.55) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index c53f520cd0732..2ed14860dbf76 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -19,7 +19,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.35", features = ["rt-multi-thread"] } -thiserror = "1.0.53" +thiserror = "1.0.55" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 08f21947d1203..28b9886b14169 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = "1.0.53" +thiserror = "1.0.55" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ff1613296563c..297d7f47736d7 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -24,7 +24,7 @@ serde_json = "1.0" sysinfo = "0.29" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.35", features = ["rt"] } -thiserror = "1.0.53" +thiserror = "1.0.55" # Bridge dependencies From d038662eaafffa86ce229a43888ecbedec968f15 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 8 Jan 2024 14:21:42 +0100 Subject: [PATCH 1167/1210] [polkadot-staging] Bump sysinfo from 0.29.11 to 0.30.5 (#2790) * Bump sysinfo from 0.29.11 to 0.30.5 Bumps [sysinfo](https://github.com/GuillaumeGomez/sysinfo) from 0.29.11 to 0.30.5. - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/commits) --- updated-dependencies: - dependency-name: sysinfo dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Fix build --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- relays/utils/Cargo.toml | 2 +- relays/utils/src/metrics/global.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 297d7f47736d7..5e653d3b5862a 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -21,7 +21,7 @@ jsonpath_lib = "0.3" log = "0.4.20" num-traits = "0.2" serde_json = "1.0" -sysinfo = "0.29" +sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.35", features = ["rt"] } thiserror = "1.0.55" diff --git a/relays/utils/src/metrics/global.rs b/relays/utils/src/metrics/global.rs index f7d3e25c96479..9b22fb86ef0cb 100644 --- a/relays/utils/src/metrics/global.rs +++ b/relays/utils/src/metrics/global.rs @@ -24,7 +24,7 @@ use crate::metrics::{ use async_std::sync::{Arc, Mutex}; use async_trait::async_trait; use std::time::Duration; -use sysinfo::{ProcessExt, RefreshKind, System, SystemExt}; +use sysinfo::{RefreshKind, System}; /// Global metrics update interval. const UPDATE_INTERVAL: Duration = Duration::from_secs(10); @@ -73,7 +73,7 @@ impl StandaloneMetric for GlobalMetrics { async fn update(&self) { // update system-wide metrics let mut system = self.system.lock().await; - let load = system.load_average(); + let load = sysinfo::System::load_average(); self.system_average_load.with_label_values(&["1min"]).set(load.one); self.system_average_load.with_label_values(&["5min"]).set(load.five); self.system_average_load.with_label_values(&["15min"]).set(load.fifteen); From 7c76a4a985e0723e630fc071438c646b33462fc9 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 11 Jan 2024 12:39:23 +0300 Subject: [PATCH 1168/1210] Port safe commits from master to polkadot-staging (#2761) * introduce bp_messages::ChainWithMessages (#2171) * Move Chain::ID from relay-level Chain to primitives-level Chain (#2181) * move Chain::ID from relay-level Chain to primitives-level Chain * removed chain IDs from bp-runtime * add missing file header * Some code grooming (#2276) * some code grooming: enable warn(missing_docs) for all piblic crates + added missing documentation + removed obsolete clippy/deny workarounds * removed strange allow + added comment related to other allow * removed incorrect_clone_impl_on_copy_type which is unknown to CI clippy --- bin/runtime-common/src/lib.rs | 1 + bin/runtime-common/src/messages_call_ext.rs | 7 ++- .../src/messages_xcm_extension.rs | 5 +- bin/runtime-common/src/mock.rs | 6 +++ .../src/parachains_benchmarking.rs | 2 +- .../src/refund_relayer_extension.rs | 6 +-- modules/beefy/src/lib.rs | 1 + modules/beefy/src/mock.rs | 4 +- modules/grandpa/src/lib.rs | 5 +- modules/grandpa/src/mock.rs | 6 ++- modules/messages/src/lib.rs | 18 +++++-- modules/parachains/src/call_ext.rs | 2 +- modules/parachains/src/lib.rs | 34 +++++++++++-- modules/parachains/src/mock.rs | 14 +++++- .../chain-bridge-hub-cumulus/src/lib.rs | 5 ++ primitives/chain-bridge-hub-kusama/src/lib.rs | 14 +++++- .../chain-bridge-hub-polkadot/src/lib.rs | 15 +++++- primitives/chain-bridge-hub-rococo/src/lib.rs | 15 +++++- .../chain-bridge-hub-westend/src/lib.rs | 14 +++++- primitives/chain-kusama/src/lib.rs | 29 ++++++----- primitives/chain-polkadot-bulletin/src/lib.rs | 16 ++++++- primitives/chain-polkadot/src/lib.rs | 31 +++++++----- primitives/chain-rococo/src/lib.rs | 35 +++++++------- primitives/chain-westend/src/lib.rs | 35 +++++++------- primitives/header-chain/src/lib.rs | 14 +++++- primitives/messages/src/lib.rs | 47 ++++++++++++++++-- primitives/parachains/src/lib.rs | 4 ++ primitives/polkadot-core/src/lib.rs | 48 +++++++++---------- primitives/polkadot-core/src/parachains.rs | 13 +++-- primitives/runtime/src/chain.rs | 8 +++- primitives/runtime/src/extensions.rs | 2 + primitives/runtime/src/lib.rs | 43 ++++------------- primitives/test-utils/src/keyring.rs | 10 +++- primitives/test-utils/src/lib.rs | 6 ++- .../src/bridges/rococo_bulletin/mod.rs | 23 +++++---- relays/client-bridge-hub-kusama/Cargo.toml | 2 - relays/client-bridge-hub-kusama/src/lib.rs | 10 ---- relays/client-bridge-hub-polkadot/Cargo.toml | 1 - relays/client-bridge-hub-polkadot/src/lib.rs | 10 ---- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-rococo/src/lib.rs | 10 ---- relays/client-bridge-hub-westend/Cargo.toml | 5 +- relays/client-bridge-hub-westend/src/lib.rs | 10 ---- relays/client-kusama/src/lib.rs | 2 - relays/client-polkadot-bulletin/src/lib.rs | 11 ----- relays/client-polkadot/src/lib.rs | 2 - relays/client-rococo/Cargo.toml | 1 - relays/client-rococo/src/lib.rs | 2 - relays/client-substrate/src/chain.rs | 24 ++-------- relays/client-substrate/src/test_chain.rs | 6 ++- relays/client-westend/src/lib.rs | 2 - .../lib-substrate-relay/src/messages_lane.rs | 2 +- .../src/messages_source.rs | 4 +- .../src/messages_target.rs | 8 ++-- .../src/parachains/source.rs | 2 +- relays/parachains/src/parachains_loop.rs | 3 +- 56 files changed, 389 insertions(+), 268 deletions(-) diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index d3b3b21061d05..2722f6f1c6d14 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -16,6 +16,7 @@ //! Common types/functions that may be used by runtimes of all bridged chains. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use crate::messages_call_ext::MessagesCallSubType; diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bin/runtime-common/src/messages_call_ext.rs index 5303fcb7ba030..fb07f7b6dd691 100644 --- a/bin/runtime-common/src/messages_call_ext.rs +++ b/bin/runtime-common/src/messages_call_ext.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Signed extension for the `pallet-bridge-messages` that is able to reject obsolete +//! (and some other invalid) transactions. + use crate::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; @@ -116,7 +119,9 @@ impl ReceiveMessagesDeliveryProofInfo { /// which tries to update a single lane. #[derive(PartialEq, RuntimeDebug)] pub enum CallInfo { + /// Messages delivery call info. ReceiveMessagesProof(ReceiveMessagesProofInfo), + /// Messages delivery confirmation call info. ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo), } @@ -132,7 +137,7 @@ impl CallInfo { /// Helper struct that provides methods for working with a call supported by `CallInfo`. pub struct CallHelper, I: 'static> { - pub _phantom_data: sp_std::marker::PhantomData<(T, I)>, + _phantom_data: sp_std::marker::PhantomData<(T, I)>, } impl, I: 'static> CallHelper { diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 53c0579c4cd04..4892297a3dfdf 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -40,11 +40,14 @@ use sp_std::{fmt::Debug, marker::PhantomData}; use xcm::prelude::*; use xcm_builder::{DispatchBlob, DispatchBlobError}; -/// Message dispatch result type for single message +/// Message dispatch result type for single message. #[derive(CloneNoBound, EqNoBound, PartialEqNoBound, Encode, Decode, Debug, TypeInfo)] pub enum XcmBlobMessageDispatchResult { + /// We've been unable to decode message payload. InvalidPayload, + /// Message has been dispatched. Dispatched, + /// Message has **NOT** been dispatched because of given error. NotDispatched(#[codec(skip)] Option), } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index b783ce987ced3..8877a4fd95ce3 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -314,6 +314,8 @@ impl From pub struct ThisUnderlyingChain; impl Chain for ThisUnderlyingChain { + const ID: ChainId = *b"tuch"; + type BlockNumber = ThisChainBlockNumber; type Hash = ThisChainHash; type Hasher = ThisChainHasher; @@ -354,6 +356,8 @@ pub struct BridgedUnderlyingParachain; pub struct BridgedChainCall; impl Chain for BridgedUnderlyingChain { + const ID: ChainId = *b"buch"; + type BlockNumber = BridgedChainBlockNumber; type Hash = BridgedChainHash; type Hasher = BridgedChainHasher; @@ -380,6 +384,8 @@ impl ChainWithGrandpa for BridgedUnderlyingChain { } impl Chain for BridgedUnderlyingParachain { + const ID: ChainId = *b"bupc"; + type BlockNumber = BridgedChainBlockNumber; type Hash = BridgedChainHash; type Hasher = BridgedChainHasher; diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bin/runtime-common/src/parachains_benchmarking.rs index 63dc78385e46e..b3050b9ac0f3c 100644 --- a/bin/runtime-common/src/parachains_benchmarking.rs +++ b/bin/runtime-common/src/parachains_benchmarking.rs @@ -84,5 +84,5 @@ where let (relay_block_number, relay_block_hash) = insert_header_to_grandpa_pallet::(state_root); - (relay_block_number, relay_block_hash, ParaHeadsProof(proof), parachain_heads) + (relay_block_number, relay_block_hash, ParaHeadsProof { storage_proof: proof }, parachain_heads) } diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 6d8b211480858..27b7ff1a5519b 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -116,7 +116,7 @@ where /// Refund calculator. pub trait RefundCalculator { - // The underlying integer type in which the refund is calculated. + /// The underlying integer type in which the refund is calculated. type Balance; /// Compute refund for given transaction. @@ -986,7 +986,7 @@ mod tests { ParaId(TestParachain::get()), [parachain_head_at_relay_header_number as u8; 32].into(), )], - parachain_heads_proof: ParaHeadsProof(vec![]), + parachain_heads_proof: ParaHeadsProof { storage_proof: vec![] }, }) } @@ -1732,7 +1732,7 @@ mod tests { (ParaId(TestParachain::get()), [1u8; 32].into()), (ParaId(TestParachain::get() + 1), [1u8; 32].into()), ], - parachain_heads_proof: ParaHeadsProof(vec![]), + parachain_heads_proof: ParaHeadsProof { storage_proof: vec![] }, }), message_delivery_call(200), ], diff --git a/modules/beefy/src/lib.rs b/modules/beefy/src/lib.rs index 686115a7b0ed5..27c83921021bb 100644 --- a/modules/beefy/src/lib.rs +++ b/modules/beefy/src/lib.rs @@ -29,6 +29,7 @@ //! Given the header hash, other pallets are able to verify header-based proofs //! (e.g. storage proofs, transaction inclusion proofs, etc.). +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use bp_beefy::{ChainWithBeefy, InitializationData}; diff --git a/modules/beefy/src/mock.rs b/modules/beefy/src/mock.rs index f89fd1e63480c..c99566b6b06d1 100644 --- a/modules/beefy/src/mock.rs +++ b/modules/beefy/src/mock.rs @@ -22,7 +22,7 @@ use crate::{ }; use bp_beefy::{BeefyValidatorSignatureOf, ChainWithBeefy, Commitment, MmrDataOrHash}; -use bp_runtime::{BasicOperatingMode, Chain}; +use bp_runtime::{BasicOperatingMode, Chain, ChainId}; use codec::Encode; use frame_support::{construct_runtime, derive_impl, weights::Weight}; use sp_core::{sr25519::Signature, Pair}; @@ -81,6 +81,8 @@ impl beefy::Config for TestRuntime { pub struct TestBridgedChain; impl Chain for TestBridgedChain { + const ID: ChainId = *b"tbch"; + type BlockNumber = TestBridgedBlockNumber; type Hash = H256; type Hasher = BlakeTwo256; diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index 22df604bf1895..f58db2481ada1 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -32,9 +32,8 @@ //! Shall the fork occur on the bridged chain governance intervention will be required to //! re-initialize the bridge and track the right fork. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// Runtime-generated enums -#![allow(clippy::large_enum_variant)] pub use storage_types::StoredAuthoritySet; @@ -408,7 +407,9 @@ pub mod pallet { pub enum Event, I: 'static = ()> { /// Best finalized chain header has been updated to the header with given number and hash. UpdatedBestFinalizedHeader { + /// Number of the new best finalized header. number: BridgedBlockNumber, + /// Hash of the new best finalized header. hash: BridgedBlockHash, /// The Grandpa info associated to the new best finalized header. grandpa_info: StoredHeaderGrandpaInfo>, diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index a54f56c4a6249..e41e89341b312 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -18,7 +18,7 @@ #![allow(clippy::from_over_into)] use bp_header_chain::ChainWithGrandpa; -use bp_runtime::Chain; +use bp_runtime::{Chain, ChainId}; use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::Hooks, weights::Weight, }; @@ -64,7 +64,9 @@ impl grandpa::Config for TestRuntime { pub struct TestBridgedChain; impl Chain for TestBridgedChain { - type BlockNumber = TestNumber; + const ID: ChainId = *b"tbch"; + + type BlockNumber = frame_system::pallet_prelude::BlockNumberFor; type Hash = ::Hash; type Hasher = ::Hashing; type Header = TestHeader; diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index eeae95b482c86..401ec185485b7 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -33,9 +33,8 @@ //! If this test fails with your weights, then either weights are computed incorrectly, //! or some benchmarks assumptions are broken for your runtime. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// Generated by `decl_event!` -#![allow(clippy::unused_unit)] pub use inbound_lane::StoredInboundLaneData; pub use outbound_lane::StoredMessagePayload; @@ -514,13 +513,24 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { /// Message has been accepted and is waiting to be delivered. - MessageAccepted { lane_id: LaneId, nonce: MessageNonce }, + MessageAccepted { + /// Lane, which has accepted the message. + lane_id: LaneId, + /// Nonce of accepted message. + nonce: MessageNonce, + }, /// Messages have been received from the bridged chain. MessagesReceived( + /// Result of received messages dispatch. Vec::DispatchLevelResult>>, ), /// Messages in the inclusive range have been delivered to the bridged chain. - MessagesDelivered { lane_id: LaneId, messages: DeliveredMessages }, + MessagesDelivered { + /// Lane for which the delivery has been confirmed. + lane_id: LaneId, + /// Delivered messages. + messages: DeliveredMessages, + }, } #[pallet::error] diff --git a/modules/parachains/src/call_ext.rs b/modules/parachains/src/call_ext.rs index 198ff11be4951..da91a40a23223 100644 --- a/modules/parachains/src/call_ext.rs +++ b/modules/parachains/src/call_ext.rs @@ -178,7 +178,7 @@ mod tests { RuntimeCall::Parachains(crate::Call::::submit_parachain_heads { at_relay_block: (num, Default::default()), parachains, - parachain_heads_proof: ParaHeadsProof(Vec::new()), + parachain_heads_proof: ParaHeadsProof { storage_proof: Vec::new() }, }) .check_obsolete_submit_parachain_heads() .is_ok() diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index b2ef0bf52bd3d..9adeacb0eb882 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -21,6 +21,7 @@ //! accepts storage proof of some parachain `Heads` entries from bridged relay chain. //! It requires corresponding relay headers to be already synced. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] pub use weights::WeightInfo; @@ -98,27 +99,49 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { /// The caller has provided head of parachain that the pallet is not configured to track. - UntrackedParachainRejected { parachain: ParaId }, + UntrackedParachainRejected { + /// Identifier of the parachain that is not tracked by the pallet. + parachain: ParaId, + }, /// The caller has declared that he has provided given parachain head, but it is missing /// from the storage proof. - MissingParachainHead { parachain: ParaId }, + MissingParachainHead { + /// Identifier of the parachain with missing head. + parachain: ParaId, + }, /// The caller has provided parachain head hash that is not matching the hash read from the /// storage proof. IncorrectParachainHeadHash { + /// Identifier of the parachain with incorrect head hast. parachain: ParaId, + /// Specified parachain head hash. parachain_head_hash: ParaHash, + /// Actual parachain head hash. actual_parachain_head_hash: ParaHash, }, /// The caller has provided obsolete parachain head, which is already known to the pallet. - RejectedObsoleteParachainHead { parachain: ParaId, parachain_head_hash: ParaHash }, + RejectedObsoleteParachainHead { + /// Identifier of the parachain with obsolete head. + parachain: ParaId, + /// Obsolete parachain head hash. + parachain_head_hash: ParaHash, + }, /// The caller has provided parachain head that exceeds the maximal configured head size. RejectedLargeParachainHead { + /// Identifier of the parachain with rejected head. parachain: ParaId, + /// Parachain head hash. parachain_head_hash: ParaHash, + /// Parachain head size. parachain_head_size: u32, }, /// Parachain head has been updated. - UpdatedParachainHead { parachain: ParaId, parachain_head_hash: ParaHash }, + UpdatedParachainHead { + /// Identifier of the parachain that has been updated. + parachain: ParaId, + /// Parachain head hash. + parachain_head_hash: ParaHash, + }, } #[pallet::error] @@ -137,6 +160,7 @@ pub mod pallet { pub trait BoundedBridgeGrandpaConfig: pallet_bridge_grandpa::Config { + /// Type of the bridged relay chain. type BridgedRelayChain: Chain< BlockNumber = RelayBlockNumber, Hash = RelayBlockHash, @@ -336,7 +360,7 @@ pub mod pallet { let mut storage = GrandpaPalletOf::::storage_proof_checker( relay_block_hash, - parachain_heads_proof.0, + parachain_heads_proof.storage_proof, ) .map_err(Error::::HeaderChainStorageProof)?; diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 1c7851364d1c0..143f11d986371 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -16,7 +16,7 @@ use bp_header_chain::ChainWithGrandpa; use bp_polkadot_core::parachains::ParaId; -use bp_runtime::{Chain, Parachain}; +use bp_runtime::{Chain, ChainId, Parachain}; use frame_support::{ construct_runtime, derive_impl, parameter_types, traits::ConstU32, weights::Weight, }; @@ -49,6 +49,8 @@ pub type BigParachainHeader = sp_runtime::generic::Header; pub struct Parachain1; impl Chain for Parachain1 { + const ID: ChainId = *b"pch1"; + type BlockNumber = u64; type Hash = H256; type Hasher = RegularParachainHasher; @@ -73,6 +75,8 @@ impl Parachain for Parachain1 { pub struct Parachain2; impl Chain for Parachain2 { + const ID: ChainId = *b"pch2"; + type BlockNumber = u64; type Hash = H256; type Hasher = RegularParachainHasher; @@ -97,6 +101,8 @@ impl Parachain for Parachain2 { pub struct Parachain3; impl Chain for Parachain3 { + const ID: ChainId = *b"pch3"; + type BlockNumber = u64; type Hash = H256; type Hasher = RegularParachainHasher; @@ -122,6 +128,8 @@ impl Parachain for Parachain3 { pub struct BigParachain; impl Chain for BigParachain { + const ID: ChainId = *b"bpch"; + type BlockNumber = u128; type Hash = H256; type Hasher = RegularParachainHasher; @@ -229,6 +237,8 @@ impl pallet_bridge_parachains::benchmarking::Config<()> for TestRuntime { pub struct TestBridgedChain; impl Chain for TestBridgedChain { + const ID: ChainId = *b"tbch"; + type BlockNumber = crate::RelayBlockNumber; type Hash = crate::RelayBlockHash; type Hasher = crate::RelayBlockHasher; @@ -260,6 +270,8 @@ impl ChainWithGrandpa for TestBridgedChain { pub struct OtherBridgedChain; impl Chain for OtherBridgedChain { + const ID: ChainId = *b"obch"; + type BlockNumber = u64; type Hash = crate::RelayBlockHash; type Hasher = crate::RelayBlockHasher; diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index cd281324ee55f..285f00204810b 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Primitives of all Cumulus-based bridge hubs. + +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] pub use bp_polkadot_core::{ @@ -61,6 +64,7 @@ const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TI pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); parameter_types! { + /// Size limit of the Cumulus-based bridge hub blocks. pub BlockLength: limits::BlockLength = limits::BlockLength::max_with_normal_ratio( 5 * 1024 * 1024, NORMAL_DISPATCH_RATIO, @@ -73,6 +77,7 @@ parameter_types! { pub const ExtrinsicBaseWeight: Weight = Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS, 0) .saturating_mul(125_000); + /// Weight limit of the Cumulus-based bridge hub blocks. pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() .base_block(BlockExecutionWeight::get()) .for_class(DispatchClass::all(), |weights| { diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/primitives/chain-bridge-hub-kusama/src/lib.rs index 66e0dad05895c..576e3dbee80d0 100644 --- a/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -17,12 +17,13 @@ //! Module with configuration which reflects BridgeHubKusama runtime setup (AccountId, Headers, //! Hashes...) +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] pub use bp_bridge_hub_cumulus::*; use bp_messages::*; use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain, }; use frame_support::{ dispatch::DispatchClass, @@ -35,6 +36,8 @@ use sp_runtime::RuntimeDebug; pub struct BridgeHubKusama; impl Chain for BridgeHubKusama { + const ID: ChainId = *b"bhks"; + type BlockNumber = BlockNumber; type Hash = Hash; type Hasher = Hasher; @@ -61,6 +64,15 @@ impl Parachain for BridgeHubKusama { const PARACHAIN_ID: u32 = BRIDGE_HUB_KUSAMA_PARACHAIN_ID; } +impl ChainWithMessages for BridgeHubKusama { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + /// Public key of the chain account that may be used to verify signatures. pub type AccountSigner = MultiSigner; diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/primitives/chain-bridge-hub-polkadot/src/lib.rs index c3661c1adcada..6db389c92994d 100644 --- a/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -17,12 +17,13 @@ //! Module with configuration which reflects BridgeHubPolkadot runtime setup //! (AccountId, Headers, Hashes...) +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] pub use bp_bridge_hub_cumulus::*; use bp_messages::*; use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain, }; use frame_support::dispatch::DispatchClass; use sp_runtime::RuntimeDebug; @@ -32,6 +33,8 @@ use sp_runtime::RuntimeDebug; pub struct BridgeHubPolkadot; impl Chain for BridgeHubPolkadot { + const ID: ChainId = *b"bhpd"; + type BlockNumber = BlockNumber; type Hash = Hash; type Hasher = Hasher; @@ -58,6 +61,16 @@ impl Parachain for BridgeHubPolkadot { const PARACHAIN_ID: u32 = BRIDGE_HUB_POLKADOT_PARACHAIN_ID; } +impl ChainWithMessages for BridgeHubPolkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + /// Identifier of BridgeHubPolkadot in the Polkadot relay chain. pub const BRIDGE_HUB_POLKADOT_PARACHAIN_ID: u32 = 1002; diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index f79b8a8afb321..7b109f30fe0b9 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -17,12 +17,13 @@ //! Module with configuration which reflects BridgeHubRococo runtime setup (AccountId, Headers, //! Hashes...) +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] pub use bp_bridge_hub_cumulus::*; use bp_messages::*; use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain, }; use frame_support::dispatch::DispatchClass; use sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug}; @@ -32,6 +33,8 @@ use sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug}; pub struct BridgeHubRococo; impl Chain for BridgeHubRococo { + const ID: ChainId = *b"bhro"; + type BlockNumber = BlockNumber; type Hash = Hash; type Hasher = Hasher; @@ -58,6 +61,16 @@ impl Parachain for BridgeHubRococo { const PARACHAIN_ID: u32 = BRIDGE_HUB_ROCOCO_PARACHAIN_ID; } +impl ChainWithMessages for BridgeHubRococo { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + /// Public key of the chain account that may be used to verify signatures. pub type AccountSigner = MultiSigner; diff --git a/primitives/chain-bridge-hub-westend/src/lib.rs b/primitives/chain-bridge-hub-westend/src/lib.rs index f4524f719f9fd..83d4d6e33a759 100644 --- a/primitives/chain-bridge-hub-westend/src/lib.rs +++ b/primitives/chain-bridge-hub-westend/src/lib.rs @@ -22,7 +22,7 @@ pub use bp_bridge_hub_cumulus::*; use bp_messages::*; use bp_runtime::{ - decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, Parachain, + decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain, }; use frame_support::dispatch::DispatchClass; use sp_runtime::RuntimeDebug; @@ -32,6 +32,8 @@ use sp_runtime::RuntimeDebug; pub struct BridgeHubWestend; impl Chain for BridgeHubWestend { + const ID: ChainId = *b"bhwd"; + type BlockNumber = BlockNumber; type Hash = Hash; type Hasher = Hasher; @@ -58,6 +60,16 @@ impl Parachain for BridgeHubWestend { const PARACHAIN_ID: u32 = BRIDGE_HUB_WESTEND_PARACHAIN_ID; } +impl ChainWithMessages for BridgeHubWestend { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + WITH_BRIDGE_HUB_WESTEND_MESSAGES_PALLET_NAME; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + /// Identifier of BridgeHubWestend in the Westend relay chain. pub const BRIDGE_HUB_WESTEND_PARACHAIN_ID: u32 = 1002; diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 5f089fbc589f6..e3b4d0520f61c 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -14,36 +14,39 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Primitives of the Kusama chain. + +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, ChainId}; use frame_support::weights::Weight; /// Kusama Chain pub struct Kusama; impl Chain for Kusama { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hasher; - type Header = ::Header; + const ID: ChainId = *b"ksma"; + + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; - type AccountId = ::AccountId; - type Balance = ::Balance; - type Nonce = ::Nonce; - type Signature = ::Signature; + type AccountId = AccountId; + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; fn max_extrinsic_size() -> u32 { - PolkadotLike::max_extrinsic_size() + max_extrinsic_size() } fn max_extrinsic_weight() -> Weight { - PolkadotLike::max_extrinsic_weight() + max_extrinsic_weight() } } diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/primitives/chain-polkadot-bulletin/src/lib.rs index fe82c9644b673..f2eebf9312470 100644 --- a/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/primitives/chain-polkadot-bulletin/src/lib.rs @@ -20,14 +20,14 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_header_chain::ChainWithGrandpa; -use bp_messages::MessageNonce; +use bp_messages::{ChainWithMessages, MessageNonce}; use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, extensions::{ CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema, }, - Chain, TransactionEra, + Chain, ChainId, TransactionEra, }; use codec::{Decode, Encode}; use frame_support::{ @@ -177,6 +177,8 @@ parameter_types! { pub struct PolkadotBulletin; impl Chain for PolkadotBulletin { + const ID: ChainId = *b"pdbc"; + type BlockNumber = BlockNumber; type Hash = Hash; type Hasher = Hasher; @@ -211,5 +213,15 @@ impl ChainWithGrandpa for PolkadotBulletin { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } +impl ChainWithMessages for PolkadotBulletin { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + WITH_POLKADOT_BULLETIN_MESSAGES_PALLET_NAME; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + decl_bridge_finality_runtime_apis!(polkadot_bulletin, grandpa); decl_bridge_messages_runtime_apis!(polkadot_bulletin); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 9a5b8970accb2..fc5e10308a8e3 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -14,36 +14,41 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Primitives of the Polkadot chain. + +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, extensions::PrevalidateAttests, Chain}; +use bp_runtime::{ + decl_bridge_finality_runtime_apis, extensions::PrevalidateAttests, Chain, ChainId, +}; use frame_support::weights::Weight; /// Polkadot Chain pub struct Polkadot; impl Chain for Polkadot { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hasher; - type Header = ::Header; + const ID: ChainId = *b"pdot"; + + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; - type AccountId = ::AccountId; - type Balance = ::Balance; - type Nonce = ::Nonce; - type Signature = ::Signature; + type AccountId = AccountId; + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; fn max_extrinsic_size() -> u32 { - PolkadotLike::max_extrinsic_size() + max_extrinsic_size() } fn max_extrinsic_weight() -> Weight { - PolkadotLike::max_extrinsic_weight() + max_extrinsic_weight() } } diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 7f3e762715f32..f1b256f0f090f 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -14,36 +14,39 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Primitives of the Rococo chain. + +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; -use frame_support::{parameter_types, weights::Weight}; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, ChainId}; +use frame_support::weights::Weight; /// Rococo Chain pub struct Rococo; impl Chain for Rococo { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hasher; - type Header = ::Header; + const ID: ChainId = *b"roco"; + + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; - type AccountId = ::AccountId; - type Balance = ::Balance; - type Nonce = ::Nonce; - type Signature = ::Signature; + type AccountId = AccountId; + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; fn max_extrinsic_size() -> u32 { - PolkadotLike::max_extrinsic_size() + max_extrinsic_size() } fn max_extrinsic_weight() -> Weight { - PolkadotLike::max_extrinsic_weight() + max_extrinsic_weight() } } @@ -56,10 +59,6 @@ impl ChainWithGrandpa for Rococo { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -parameter_types! { - pub const SS58Prefix: u8 = 42; -} - // The SignedExtension used by Rococo. pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index 7fa5e140d5707..f03fd2160a700 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -14,36 +14,39 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Primitives of the Westend chain. + +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; use bp_header_chain::ChainWithGrandpa; -use bp_runtime::{decl_bridge_finality_runtime_apis, Chain}; -use frame_support::{parameter_types, weights::Weight}; +use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, ChainId}; +use frame_support::weights::Weight; /// Westend Chain pub struct Westend; impl Chain for Westend { - type BlockNumber = ::BlockNumber; - type Hash = ::Hash; - type Hasher = ::Hasher; - type Header = ::Header; + const ID: ChainId = *b"wend"; + + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hasher = Hasher; + type Header = Header; - type AccountId = ::AccountId; - type Balance = ::Balance; - type Nonce = ::Nonce; - type Signature = ::Signature; + type AccountId = AccountId; + type Balance = Balance; + type Nonce = Nonce; + type Signature = Signature; fn max_extrinsic_size() -> u32 { - PolkadotLike::max_extrinsic_size() + max_extrinsic_size() } fn max_extrinsic_weight() -> Weight { - PolkadotLike::max_extrinsic_weight() + max_extrinsic_weight() } } @@ -56,10 +59,6 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -parameter_types! { - pub const SS58Prefix: u8 = 42; -} - // The SignedExtension used by Westend. pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 1459b1c1994bc..f5485aca1ee8b 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -17,6 +17,7 @@ //! Defines traits which represent a common interface for Substrate pallets which want to //! incorporate bridge functionality. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use crate::justification::{ @@ -145,6 +146,7 @@ pub trait ConsensusLogReader { pub struct GrandpaConsensusLogReader(sp_std::marker::PhantomData); impl GrandpaConsensusLogReader { + /// Find and return scheduled (regular) change digest item. pub fn find_scheduled_change( digest: &Digest, ) -> Option> { @@ -158,6 +160,8 @@ impl GrandpaConsensusLogReader { }) } + /// Find and return forced change digest item. Or light client can't do anything + /// with forced changes, so we can't accept header with the forced change digest. pub fn find_forced_change( digest: &Digest, ) -> Option<(Number, sp_consensus_grandpa::ScheduledChange)> { @@ -229,12 +233,17 @@ pub enum BridgeGrandpaCall { /// `pallet-bridge-grandpa::Call::submit_finality_proof` #[codec(index = 0)] submit_finality_proof { + /// The header that we are going to finalize. finality_target: Box

, + /// Finality justification for the `finality_target`. justification: justification::GrandpaJustification
, }, /// `pallet-bridge-grandpa::Call::initialize` #[codec(index = 1)] - initialize { init_data: InitializationData
}, + initialize { + /// All data, required to initialize the pallet. + init_data: InitializationData
, + }, } /// The `BridgeGrandpaCall` used by a chain. @@ -325,12 +334,15 @@ pub fn max_expected_submit_finality_proof_arguments_size( #[cfg(test)] mod tests { use super::*; + use bp_runtime::ChainId; use frame_support::weights::Weight; use sp_runtime::{testing::H256, traits::BlakeTwo256, MultiSignature}; struct TestChain; impl Chain for TestChain { + const ID: ChainId = *b"test"; + type BlockNumber = u32; type Hash = H256; type Hasher = BlakeTwo256; diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index e48914f759186..51b3f25f71518 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -16,14 +16,13 @@ //! Primitives of messages module. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -// RuntimeApi generated functions -#![allow(clippy::too_many_arguments)] use bp_header_chain::HeaderChainError; use bp_runtime::{ - messages::MessageDispatchResult, BasicOperatingMode, OperatingMode, RangeInclusiveExt, - StorageProofError, + messages::MessageDispatchResult, BasicOperatingMode, Chain, OperatingMode, RangeInclusiveExt, + StorageProofError, UnderlyingChainOf, UnderlyingChainProvider, }; use codec::{Decode, Encode, MaxEncodedLen}; use frame_support::PalletError; @@ -39,6 +38,36 @@ pub mod source_chain; pub mod storage_keys; pub mod target_chain; +/// Substrate-based chain with messaging support. +pub trait ChainWithMessages: Chain { + /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is + /// deployed at some other chain to bridge with this `ChainWithMessages`. + /// + /// We assume that all chains that are bridging with this `ChainWithMessages` are using + /// the same name. + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str; + + /// Maximal number of unrewarded relayers in a single confirmation transaction at this + /// `ChainWithMessages`. + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce; + /// Maximal number of unconfirmed messages in a single confirmation transaction at this + /// `ChainWithMessages`. + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; +} + +impl ChainWithMessages for T +where + T: Chain + UnderlyingChainProvider, + UnderlyingChainOf: ChainWithMessages, +{ + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + UnderlyingChainOf::::WITH_CHAIN_MESSAGES_PALLET_NAME; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + UnderlyingChainOf::::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + UnderlyingChainOf::::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + /// Messages pallet operating mode. #[derive( Encode, @@ -264,6 +293,7 @@ pub struct ReceivedMessages { } impl ReceivedMessages { + /// Creates new `ReceivedMessages` structure from given results. pub fn new( lane: LaneId, receive_results: Vec<(MessageNonce, ReceivalResult)>, @@ -271,6 +301,7 @@ impl ReceivedMessages { ReceivedMessages { lane, receive_results } } + /// Push `result` of the `message` delivery onto `receive_results` vector. pub fn push(&mut self, message: MessageNonce, result: ReceivalResult) { self.receive_results.push((message, result)); } @@ -342,7 +373,7 @@ pub struct UnrewardedRelayersState { } impl UnrewardedRelayersState { - // Verify that the relayers state corresponds with the `InboundLaneData`. + /// Verify that the relayers state corresponds with the `InboundLaneData`. pub fn is_valid(&self, lane_data: &InboundLaneData) -> bool { self == &lane_data.into() } @@ -423,15 +454,21 @@ pub enum BridgeMessagesCall { /// `pallet-bridge-messages::Call::receive_messages_proof` #[codec(index = 2)] receive_messages_proof { + /// Account id of relayer at the **bridged** chain. relayer_id_at_bridged_chain: AccountId, + /// Messages proof. proof: MessagesProof, + /// A number of messages in the proof. messages_count: u32, + /// Total dispatch weight of messages in the proof. dispatch_weight: Weight, }, /// `pallet-bridge-messages::Call::receive_messages_delivery_proof` #[codec(index = 3)] receive_messages_delivery_proof { + /// Messages delivery proof. proof: MessagesDeliveryProof, + /// "Digest" of unrewarded relayers state at the bridged chain. relayers_state: UnrewardedRelayersState, }, } diff --git a/primitives/parachains/src/lib.rs b/primitives/parachains/src/lib.rs index 262b9c6f97752..692bbd99ecef3 100644 --- a/primitives/parachains/src/lib.rs +++ b/primitives/parachains/src/lib.rs @@ -16,6 +16,7 @@ //! Primitives of parachains module. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] pub use bp_header_chain::StoredHeaderData; @@ -173,8 +174,11 @@ pub enum BridgeParachainCall { /// `pallet-bridge-parachains::Call::submit_parachain_heads` #[codec(index = 0)] submit_parachain_heads { + /// Relay chain block, for which we have submitted the `parachain_heads_proof`. at_relay_block: (RelayBlockNumber, RelayBlockHash), + /// Parachain identifiers and their head hashes. parachains: Vec<(ParaId, ParaHash)>, + /// Parachain heads proof. parachain_heads_proof: ParaHeadsProof, }, } diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index 586cbf8cb9b47..df2836495bbe1 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Primitives of the Polkadot-like chains. + +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::MessageNonce; @@ -24,7 +27,7 @@ use bp_runtime::{ CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, SignedExtensionSchema, }, - Chain, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, + EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, }; use frame_support::{ dispatch::DispatchClass, @@ -40,7 +43,7 @@ use sp_core::{storage::StorageKey, Hasher as HasherT}; use sp_runtime::{ generic, traits::{BlakeTwo256, IdentifyAccount, Verify}, - MultiAddress, MultiSignature, OpaqueExtrinsic, RuntimeDebug, + MultiAddress, MultiSignature, OpaqueExtrinsic, }; use sp_std::prelude::Vec; @@ -173,11 +176,16 @@ pub use time_units::*; pub mod time_units { use super::BlockNumber; + /// Milliseconds between Polkadot-like chain blocks. pub const MILLISECS_PER_BLOCK: u64 = 6000; + /// Slot duration in Polkadot-like chain consensus algorithms. pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + /// A minute, expressed in Polkadot-like chain blocks. pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); + /// A hour, expressed in Polkadot-like chain blocks. pub const HOURS: BlockNumber = MINUTES * 60; + /// A day, expressed in Polkadot-like chain blocks. pub const DAYS: BlockNumber = HOURS * 24; } @@ -227,31 +235,17 @@ pub type UncheckedExtrinsic = /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; -/// Polkadot-like chain. -#[derive(RuntimeDebug)] -pub struct PolkadotLike; - -impl Chain for PolkadotLike { - type BlockNumber = BlockNumber; - type Hash = Hash; - type Hasher = Hasher; - type Header = Header; - - type AccountId = AccountId; - type Balance = Balance; - type Nonce = Nonce; - type Signature = Signature; - - fn max_extrinsic_size() -> u32 { - *BlockLength::get().max.get(DispatchClass::Normal) - } +/// Returns maximal extrinsic size on all Polkadot-like chains. +pub fn max_extrinsic_size() -> u32 { + *BlockLength::get().max.get(DispatchClass::Normal) +} - fn max_extrinsic_weight() -> Weight { - BlockWeights::get() - .get(DispatchClass::Normal) - .max_extrinsic - .unwrap_or(Weight::MAX) - } +/// Returns maximal extrinsic weight on all Polkadot-like chains. +pub fn max_extrinsic_weight() -> Weight { + BlockWeights::get() + .get(DispatchClass::Normal) + .max_extrinsic + .unwrap_or(Weight::MAX) } /// Provides a storage key for account data. @@ -271,8 +265,10 @@ impl StorageMapKeyProvider for AccountInfoStorageMapKeyProvider { } impl AccountInfoStorageMapKeyProvider { + /// Name of the system pallet. const PALLET_NAME: &'static str = "System"; + /// Return storage key for given account data. pub fn final_key(id: &AccountId) -> StorageKey { ::final_key(Self::PALLET_NAME, id) } diff --git a/primitives/polkadot-core/src/parachains.rs b/primitives/polkadot-core/src/parachains.rs index 223956171f864..433cd2845abd9 100644 --- a/primitives/polkadot-core/src/parachains.rs +++ b/primitives/polkadot-core/src/parachains.rs @@ -89,11 +89,18 @@ pub type ParaHasher = crate::Hasher; /// Raw storage proof of parachain heads, stored in polkadot-like chain runtime. #[derive(Clone, Decode, Encode, Eq, PartialEq, RuntimeDebug, TypeInfo)] -pub struct ParaHeadsProof(pub RawStorageProof); +pub struct ParaHeadsProof { + /// Unverified storage proof of finalized parachain heads. + pub storage_proof: RawStorageProof, +} impl Size for ParaHeadsProof { fn size(&self) -> u32 { - u32::try_from(self.0.iter().fold(0usize, |sum, node| sum.saturating_add(node.len()))) - .unwrap_or(u32::MAX) + u32::try_from( + self.storage_proof + .iter() + .fold(0usize, |sum, node| sum.saturating_add(node.len())), + ) + .unwrap_or(u32::MAX) } } diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 469c839ba151f..7ca956e267013 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::HeaderIdProvider; +use crate::{ChainId, HeaderIdProvider}; + use codec::{Codec, Decode, Encode, MaxEncodedLen}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; @@ -99,6 +100,9 @@ impl Encode for EncodedOrDecodedCall { /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { + /// Chain id. + const ID: ChainId; + /// 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: @@ -208,6 +212,8 @@ impl Chain for T where T: Send + Sync + 'static + UnderlyingChainProvider, { + const ID: ChainId = ::ID; + type BlockNumber = ::BlockNumber; type Hash = ::Hash; type Hasher = ::Hasher; diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index 8a618721b23a6..d896bc92efffc 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -102,6 +102,7 @@ impl SignedExtensionSchema for Tuple { /// and signed payloads in the client code. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] pub struct GenericSignedExtension { + /// A payload that is included in the transaction. pub payload: S::Payload, #[codec(skip)] // It may be set to `None` if extensions are decoded. We are never reconstructing transactions @@ -112,6 +113,7 @@ pub struct GenericSignedExtension { } impl GenericSignedExtension { + /// Create new `GenericSignedExtension` object. pub fn new(payload: S::Payload, additional_signed: Option) -> Self { Self { payload, additional_signed } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 0513cfa2a6c75..e3bdc53c51549 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -16,6 +16,7 @@ //! Primitives that may be used at (bridges) runtime level. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use codec::{Decode, Encode, FullCodec, MaxEncodedLen}; @@ -61,36 +62,6 @@ pub use sp_runtime::paste; /// Use this when something must be shared among all instances. pub const NO_INSTANCE_ID: ChainId = [0, 0, 0, 0]; -/// Polkadot chain id. -pub const POLKADOT_CHAIN_ID: ChainId = *b"pdot"; - -/// Polkadot Bulletin chain id. -pub const POLKADOT_BULLETIN_CHAIN_ID: ChainId = *b"pdbc"; - -/// Kusama chain id. -pub const KUSAMA_CHAIN_ID: ChainId = *b"ksma"; - -/// Westend chain id. -pub const WESTEND_CHAIN_ID: ChainId = *b"wend"; - -/// `AssetHubWestmint` chain id. -pub const ASSET_HUB_WESTEND_CHAIN_ID: ChainId = *b"ahwe"; - -/// Rococo chain id. -pub const ROCOCO_CHAIN_ID: ChainId = *b"roco"; - -/// BridgeHubRococo chain id. -pub const BRIDGE_HUB_ROCOCO_CHAIN_ID: ChainId = *b"bhro"; - -/// BridgeHubWestend chain id. -pub const BRIDGE_HUB_WESTEND_CHAIN_ID: ChainId = *b"bhwd"; - -/// BridgeHubKusama chain id. -pub const BRIDGE_HUB_KUSAMA_CHAIN_ID: ChainId = *b"bhks"; - -/// BridgeHubPolkadot chain id. -pub const BRIDGE_HUB_POLKADOT_CHAIN_ID: ChainId = *b"bhpd"; - /// Generic header Id. #[derive( RuntimeDebug, @@ -126,10 +97,10 @@ pub type HeaderIdOf = HeaderId, BlockNumberOf>; /// Generic header id provider. pub trait HeaderIdProvider { - // Get the header id. + /// Get the header id. fn id(&self) -> HeaderId; - // Get the header id for the parent block. + /// Get the header id for the parent block. fn parent_id(&self) -> Option>; } @@ -350,7 +321,7 @@ pub enum OwnedBridgeModuleError { /// Operating mode for a bridge module. pub trait OperatingMode: Send + Copy + Debug + FullCodec { - // Returns true if the bridge module is halted. + /// Returns true if the bridge module is halted. fn is_halted(&self) -> bool; } @@ -392,8 +363,11 @@ pub trait OwnedBridgeModule { /// The target that will be used when publishing logs related to this module. const LOG_TARGET: &'static str; + /// A storage entry that holds the module `Owner` account. type OwnerStorage: StorageValue>; + /// Operating mode type of the pallet. type OperatingMode: OperatingMode; + /// A storage value that holds the pallet operating mode. type OperatingModeStorage: StorageValue; /// Check if the module is halted. @@ -469,9 +443,11 @@ impl WeightExtraOps for Weight { /// Trait that provides a static `str`. pub trait StaticStrProvider { + /// Static string. const STR: &'static str; } +/// A macro that generates `StaticStrProvider` with the string set to its stringified argument. #[macro_export] macro_rules! generate_static_str_provider { ($str:expr) => { @@ -485,6 +461,7 @@ macro_rules! generate_static_str_provider { }; } +/// Error message that is only dispayable in `std` environment. #[derive(Encode, Decode, Clone, Eq, PartialEq, PalletError, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct StrippableError { diff --git a/primitives/test-utils/src/keyring.rs b/primitives/test-utils/src/keyring.rs index eabf9c784eb81..22691183acf7a 100644 --- a/primitives/test-utils/src/keyring.rs +++ b/primitives/test-utils/src/keyring.rs @@ -24,12 +24,17 @@ use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId}; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; -/// Set of test accounts with friendly names. +/// Set of test accounts with friendly names: Alice. pub const ALICE: Account = Account(0); +/// Set of test accounts with friendly names: Bob. pub const BOB: Account = Account(1); +/// Set of test accounts with friendly names: Charlie. pub const CHARLIE: Account = Account(2); +/// Set of test accounts with friendly names: Dave. pub const DAVE: Account = Account(3); +/// Set of test accounts with friendly names: Eve. pub const EVE: Account = Account(4); +/// Set of test accounts with friendly names: Ferdie. pub const FERDIE: Account = Account(5); /// A test account which can be used to sign messages. @@ -37,10 +42,12 @@ pub const FERDIE: Account = Account(5); pub struct Account(pub u16); impl Account { + /// Returns public key of this account. pub fn public(&self) -> VerifyingKey { self.pair().verifying_key() } + /// Returns key pair, used to sign data on behalf of this account. pub fn pair(&self) -> SigningKey { let data = self.0.encode(); let mut bytes = [0_u8; 32]; @@ -48,6 +55,7 @@ impl Account { SigningKey::from_bytes(&bytes) } + /// Generate a signature of given message. pub fn sign(&self, msg: &[u8]) -> Signature { use ed25519_dalek::Signer; self.pair().sign(msg) diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 4d3b84759938b..f23ddd1a10d36 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -16,6 +16,7 @@ //! Utilities for testing runtime code. +#![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] use bp_header_chain::justification::{required_justification_precommits, GrandpaJustification}; @@ -33,8 +34,11 @@ pub use keyring::*; mod keyring; +/// GRANDPA round number used across tests. pub const TEST_GRANDPA_ROUND: u64 = 1; +/// GRANDPA validators set id used across tests. pub const TEST_GRANDPA_SET_ID: SetId = 1; +/// Name of the `Paras` pallet used across tests. pub const PARAS_PALLET_NAME: &str = "Paras"; /// Configuration parameters when generating test GRANDPA justifications. @@ -190,7 +194,7 @@ pub fn prepare_parachain_heads_proof( .map_err(|_| "record_all_trie_keys has failed") .expect("record_all_trie_keys should not fail in benchmarks"); - (root, ParaHeadsProof(storage_proof), parachains) + (root, ParaHeadsProof { storage_proof }, parachains) } /// Create signed precommit with given target. diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs index 7e37b62b68594..196978c16e8c9 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs @@ -40,6 +40,8 @@ pub mod rococo_parachains_to_rococo_bulletin; pub struct RococoBaseAsPolkadot; impl bp_runtime::Chain for RococoBaseAsPolkadot { + const ID: ChainId = relay_rococo_client::Rococo::ID; + type BlockNumber = BlockNumberOf; type Hash = HashOf; type Hasher = HasherOf; @@ -78,7 +80,6 @@ impl bp_runtime::UnderlyingChainProvider for RococoAsPolkadot { } impl relay_substrate_client::Chain for RococoAsPolkadot { - const ID: ChainId = relay_rococo_client::Rococo::ID; const NAME: &'static str = relay_rococo_client::Rococo::NAME; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = relay_polkadot_client::Polkadot::BEST_FINALIZED_HEADER_ID_METHOD; @@ -146,6 +147,8 @@ impl CliChain for RococoAsPolkadot { pub struct BaseBridgeHubRococoAsBridgeHubPolkadot; impl bp_runtime::Chain for BaseBridgeHubRococoAsBridgeHubPolkadot { + const ID: ChainId = relay_bridge_hub_rococo_client::BridgeHubRococo::ID; + type BlockNumber = BlockNumberOf; type Hash = HashOf; type Hasher = HasherOf; @@ -169,6 +172,16 @@ impl bp_runtime::Parachain for BaseBridgeHubRococoAsBridgeHubPolkadot { const PARACHAIN_ID: u32 = bp_bridge_hub_rococo::BridgeHubRococo::PARACHAIN_ID; } +impl bp_messages::ChainWithMessages for BaseBridgeHubRococoAsBridgeHubPolkadot { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = + relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_MESSAGES_PALLET_NAME; + + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = + relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = + relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; +} + /// Relay `Chain` implementation of Rococo Bridge Hub, pretending to be a Polkadot Bridge Hub. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct BridgeHubRococoAsBridgeHubPolkadot; @@ -178,7 +191,6 @@ impl bp_runtime::UnderlyingChainProvider for BridgeHubRococoAsBridgeHubPolkadot } impl relay_substrate_client::Chain for BridgeHubRococoAsBridgeHubPolkadot { - const ID: ChainId = relay_bridge_hub_rococo_client::BridgeHubRococo::ID; const NAME: &'static str = relay_bridge_hub_rococo_client::BridgeHubRococo::NAME; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = relay_bridge_hub_polkadot_client::BridgeHubPolkadot::BEST_FINALIZED_HEADER_ID_METHOD; @@ -236,8 +248,6 @@ impl relay_substrate_client::ChainWithTransactions for BridgeHubRococoAsBridgeHu } impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPolkadot { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_MESSAGES_PALLET_NAME; const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_RELAYERS_PALLET_NAME; @@ -245,11 +255,6 @@ impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPol relay_bridge_hub_polkadot_client::BridgeHubPolkadot::TO_CHAIN_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = relay_bridge_hub_polkadot_client::BridgeHubPolkadot::FROM_CHAIN_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; } impl CliChain for BridgeHubRococoAsBridgeHubPolkadot { diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index 19a8e25a7027a..ea94dac7de4b3 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -18,9 +18,7 @@ relay-substrate-client = { path = "../client-substrate" } bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-runtime = { path = "../../primitives/runtime" } bp-polkadot = { path = "../../primitives/chain-polkadot" } bridge-runtime-common = { path = "../../bin/runtime-common" } diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index f54f32f9bfeb2..d4bb057de1c23 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -17,9 +17,7 @@ //! Types used to connect to the BridgeHub-Kusama-Substrate parachain. use bp_bridge_hub_kusama::AVERAGE_BLOCK_INTERVAL; -use bp_messages::MessageNonce; use bp_polkadot::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, @@ -43,7 +41,6 @@ impl UnderlyingChainProvider for BridgeHubKusama { } impl Chain for BridgeHubKusama { - const ID: ChainId = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID; const NAME: &'static str = "BridgeHubKusama"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_kusama::BEST_FINALIZED_BRIDGE_HUB_KUSAMA_HEADER_METHOD; @@ -116,8 +113,6 @@ impl ChainWithTransactions for BridgeHubKusama { } impl ChainWithMessages for BridgeHubKusama { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME; const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some(bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME); @@ -125,11 +120,6 @@ impl ChainWithMessages for BridgeHubKusama { bp_bridge_hub_kusama::TO_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; } #[cfg(test)] diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index 7cac7f4973be0..2fd950efabe57 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -18,7 +18,6 @@ relay-substrate-client = { path = "../client-substrate" } bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index 299bc4d736aec..00006da303008 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -17,9 +17,7 @@ //! Types used to connect to the BridgeHub-Polkadot-Substrate parachain. use bp_bridge_hub_polkadot::AVERAGE_BLOCK_INTERVAL; -use bp_messages::MessageNonce; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, @@ -43,7 +41,6 @@ impl UnderlyingChainProvider for BridgeHubPolkadot { } impl Chain for BridgeHubPolkadot { - const ID: ChainId = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID; const NAME: &'static str = "BridgeHubPolkadot"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_polkadot::BEST_FINALIZED_BRIDGE_HUB_POLKADOT_HEADER_METHOD; @@ -116,8 +113,6 @@ impl ChainWithTransactions for BridgeHubPolkadot { } impl ChainWithMessages for BridgeHubPolkadot { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some(bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME); @@ -125,11 +120,6 @@ impl ChainWithMessages for BridgeHubPolkadot { bp_bridge_hub_polkadot::TO_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; } #[cfg(test)] diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index 04b0d0d38e51c..ea59240fd9274 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = [] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index b92e0009f5b80..80a6316a454bf 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -19,9 +19,7 @@ pub mod codegen_runtime; use bp_bridge_hub_rococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_messages::MessageNonce; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -52,7 +50,6 @@ impl UnderlyingChainProvider for BridgeHubRococo { } impl Chain for BridgeHubRococo { - const ID: ChainId = bp_runtime::BRIDGE_HUB_ROCOCO_CHAIN_ID; const NAME: &'static str = "BridgeHubRococo"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD; @@ -134,8 +131,6 @@ impl ChainWithTransactions for BridgeHubRococo { } impl ChainWithMessages for BridgeHubRococo { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_MESSAGES_PALLET_NAME; const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some(bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME); @@ -143,11 +138,6 @@ impl ChainWithMessages for BridgeHubRococo { bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; } #[cfg(test)] diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml index 4eae91963a2ae..ecc23ec81d9de 100644 --- a/relays/client-bridge-hub-westend/Cargo.toml +++ b/relays/client-bridge-hub-westend/Cargo.toml @@ -11,18 +11,16 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = [] } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } bp-bridge-hub-westend = { path = "../../primitives/chain-bridge-hub-westend" } bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } @@ -34,4 +32,5 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] +bp-runtime = { path = "../../primitives/runtime" } sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs index addbbe0414786..825082e10a11a 100644 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -17,9 +17,7 @@ //! Types used to connect to the BridgeHub-Westend-Substrate parachain. use bp_bridge_hub_westend::AVERAGE_BLOCK_INTERVAL; -use bp_messages::MessageNonce; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, @@ -43,7 +41,6 @@ impl UnderlyingChainProvider for BridgeHubWestend { } impl Chain for BridgeHubWestend { - const ID: ChainId = bp_runtime::BRIDGE_HUB_WESTEND_CHAIN_ID; const NAME: &'static str = "BridgeHubWestend"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_bridge_hub_westend::BEST_FINALIZED_BRIDGE_HUB_WESTEND_HEADER_METHOD; @@ -116,8 +113,6 @@ impl ChainWithTransactions for BridgeHubWestend { } impl ChainWithMessages for BridgeHubWestend { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_bridge_hub_westend::WITH_BRIDGE_HUB_WESTEND_MESSAGES_PALLET_NAME; const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = Some(bp_bridge_hub_westend::WITH_BRIDGE_HUB_WESTEND_RELAYERS_PALLET_NAME); @@ -125,11 +120,6 @@ impl ChainWithMessages for BridgeHubWestend { bp_bridge_hub_westend::TO_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_westend::FROM_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_westend::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_bridge_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; } #[cfg(test)] diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 7fa88959a3c5b..42350ccc52f74 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -20,7 +20,6 @@ pub mod codegen_runtime; use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, @@ -55,7 +54,6 @@ impl UnderlyingChainProvider for Kusama { } impl Chain for Kusama { - const ID: ChainId = bp_runtime::KUSAMA_CHAIN_ID; const NAME: &'static str = "Kusama"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs index 56dd7b487f55f..647df2ada32ec 100644 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -18,9 +18,7 @@ mod codegen_runtime; -use bp_messages::MessageNonce; use bp_polkadot_bulletin::POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, @@ -65,8 +63,6 @@ impl UnderlyingChainProvider for PolkadotBulletin { } impl Chain for PolkadotBulletin { - const ID: ChainId = *b"pbch"; - const NAME: &'static str = "PolkadotBulletin"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_polkadot_bulletin::BEST_FINALIZED_POLKADOT_BULLETIN_HEADER_METHOD; @@ -84,8 +80,6 @@ impl ChainWithGrandpa for PolkadotBulletin { } impl ChainWithMessages for PolkadotBulletin { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - bp_polkadot_bulletin::WITH_POLKADOT_BULLETIN_MESSAGES_PALLET_NAME; // this is not critical (some metrics will be missing from the storage), but probably it needs // to be changed when we'll polish the bridge configuration const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; @@ -94,11 +88,6 @@ impl ChainWithMessages for PolkadotBulletin { bp_polkadot_bulletin::TO_POLKADOT_BULLETIN_MESSAGE_DETAILS_METHOD; const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_polkadot_bulletin::FROM_POLKADOT_BULLETIN_MESSAGE_DETAILS_METHOD; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - bp_polkadot_bulletin::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - bp_polkadot_bulletin::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; } impl ChainWithBalances for PolkadotBulletin { diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index d0f7a7cb686d9..8e2a2c81748b7 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -20,7 +20,6 @@ mod codegen_runtime; use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, @@ -55,7 +54,6 @@ impl UnderlyingChainProvider for Polkadot { } impl Chain for Polkadot { - const ID: ChainId = bp_runtime::POLKADOT_CHAIN_ID; const NAME: &'static str = "Polkadot"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index bcc4c7ab147cf..ba546396fac78 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -17,7 +17,6 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5ac11f1ef7230..c96e421fa28d5 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -20,7 +20,6 @@ pub mod codegen_runtime; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use bp_runtime::ChainId; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, @@ -55,7 +54,6 @@ impl UnderlyingChainProvider for Rococo { } impl Chain for Rococo { - const ID: ChainId = bp_runtime::ROCOCO_CHAIN_ID; const NAME: &'static str = "Rococo"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index ced25fe8ddb26..9de7308c5bdd3 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -17,10 +17,10 @@ use crate::calls::UtilityCall; use bp_header_chain::ChainWithGrandpa as ChainWithGrandpaBase; -use bp_messages::MessageNonce; +use bp_messages::ChainWithMessages as ChainWithMessagesBase; use bp_runtime::{ - Chain as ChainBase, ChainId, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, - TransactionEra, TransactionEraOf, UnderlyingChainProvider, + Chain as ChainBase, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, TransactionEra, + TransactionEraOf, UnderlyingChainProvider, }; use codec::{Codec, Decode, Encode}; use jsonrpsee::core::{DeserializeOwned, Serialize}; @@ -37,8 +37,6 @@ use std::{fmt::Debug, time::Duration}; /// Substrate-based chain from minimal relay-client point of view. pub trait Chain: ChainBase + Clone { - /// Chain id. - const ID: ChainId; /// Chain name. const NAME: &'static str; /// Name of the runtime API method that is returning best known finalized header number @@ -91,14 +89,7 @@ pub trait Parachain: Chain + ParachainBase {} impl Parachain for T where T: UnderlyingChainProvider + Chain + ParachainBase {} /// Substrate-based chain with messaging support from minimal relay-client point of view. -pub trait ChainWithMessages: Chain { - /// Name of the bridge messages pallet (used in `construct_runtime` macro call) that is deployed - /// at some other chain to bridge with this `ChainWithMessages`. - /// - /// We assume that all chains that are bridging with this `ChainWithMessages` are using - /// the same name. - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str; - +pub trait ChainWithMessages: Chain + ChainWithMessagesBase { // TODO (https://github.com/paritytech/parity-bridges-common/issues/1692): check all the names // after the issue is fixed - all names must be changed @@ -116,13 +107,6 @@ pub trait ChainWithMessages: Chain { /// Name of the `FromInboundLaneApi::message_details` runtime API method. /// The method is provided by the runtime that is bridged with this `ChainWithMessages`. const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str; - - /// Maximal number of unrewarded relayers in a single confirmation transaction at this - /// `ChainWithMessages`. - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce; - /// Maximal number of unconfirmed messages in a single confirmation transaction at this - /// `ChainWithMessages`. - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce; } /// Call type used by the chain. diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 923092b1bcb7b..214f8d87a1f9f 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -31,6 +31,8 @@ use std::time::Duration; pub struct TestChain; impl bp_runtime::Chain for TestChain { + const ID: ChainId = *b"test"; + type BlockNumber = u32; type Hash = sp_core::H256; type Hasher = sp_runtime::traits::BlakeTwo256; @@ -51,7 +53,6 @@ impl bp_runtime::Chain for TestChain { } impl Chain for TestChain { - const ID: ChainId = *b"test"; const NAME: &'static str = "Test"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestMethod"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); @@ -73,6 +74,8 @@ impl ChainWithBalances for TestChain { pub struct TestParachainBase; impl bp_runtime::Chain for TestParachainBase { + const ID: ChainId = *b"tstp"; + type BlockNumber = u32; type Hash = sp_core::H256; type Hasher = sp_runtime::traits::BlakeTwo256; @@ -105,7 +108,6 @@ impl bp_runtime::UnderlyingChainProvider for TestParachain { } impl Chain for TestParachain { - const ID: ChainId = *b"test"; const NAME: &'static str = "TestParachain"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = "TestParachainMethod"; const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(0); diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 8cacffba99134..789599bbb1d29 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -19,7 +19,6 @@ pub mod codegen_runtime; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_runtime::ChainId; use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ @@ -55,7 +54,6 @@ impl UnderlyingChainProvider for Westend { } impl Chain for Westend { - const ID: ChainId = bp_runtime::WESTEND_CHAIN_ID; const NAME: &'static str = "Westend"; const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/relays/lib-substrate-relay/src/messages_lane.rs index 41f04c8f986ee..abeab8c1402d6 100644 --- a/relays/lib-substrate-relay/src/messages_lane.rs +++ b/relays/lib-substrate-relay/src/messages_lane.rs @@ -24,7 +24,7 @@ use crate::{ }; use async_std::sync::Arc; -use bp_messages::{LaneId, MessageNonce}; +use bp_messages::{ChainWithMessages as _, LaneId, MessageNonce}; use bp_runtime::{ AccountIdOf, Chain as _, EncodedOrDecodedCall, HeaderIdOf, TransactionEra, WeightExtraOps, }; diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index f128546bad3fb..26e10f8868cea 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -32,8 +32,8 @@ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ storage_keys::{operating_mode_key, outbound_lane_data_key}, - InboundMessageDetails, LaneId, MessageNonce, MessagePayload, MessagesOperatingMode, - OutboundLaneData, OutboundMessageDetails, + ChainWithMessages as _, InboundMessageDetails, LaneId, MessageNonce, MessagePayload, + MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider}; use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/relays/lib-substrate-relay/src/messages_target.rs index f47b48010ecdd..9396e785530d2 100644 --- a/relays/lib-substrate-relay/src/messages_target.rs +++ b/relays/lib-substrate-relay/src/messages_target.rs @@ -31,8 +31,8 @@ use crate::{ use async_std::sync::Arc; use async_trait::async_trait; use bp_messages::{ - storage_keys::inbound_lane_data_key, InboundLaneData, LaneId, MessageNonce, - UnrewardedRelayersState, + storage_keys::inbound_lane_data_key, ChainWithMessages as _, InboundLaneData, LaneId, + MessageNonce, UnrewardedRelayersState, }; use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use messages_relay::{ @@ -40,8 +40,8 @@ use messages_relay::{ message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, ChainWithMessages, Client, - Error as SubstrateError, HashOf, TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Client, Error as SubstrateError, HashOf, + TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index 146c5840cd51f..ba59171c8e01a 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -164,6 +164,6 @@ where })?; let parachain_head_hash = parachain_head.hash(); - Ok((ParaHeadsProof(parachain_heads_proof), parachain_head_hash)) + Ok((ParaHeadsProof { storage_proof: parachain_heads_proof }, parachain_head_hash)) } } diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 9b9038fd9761a..390b02b859459 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -648,7 +648,8 @@ mod tests { _at_block: HeaderIdOf, ) -> Result<(ParaHeadsProof, ParaHash), TestError> { let head = *self.data.lock().await.source_head.clone()?.as_available().unwrap(); - let proof = (ParaHeadsProof(vec![head.hash().encode()]), head.hash()); + let storage_proof = vec![head.hash().encode()]; + let proof = (ParaHeadsProof { storage_proof }, head.hash()); self.data.lock().await.source_proof.clone().map(|_| proof) } } From 09bf33c2e4c892f9155b61dbb49891de70ec24ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 02:45:32 +0000 Subject: [PATCH 1169/1210] Bump thiserror from 1.0.55 to 1.0.56 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.55 to 1.0.56. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.55...1.0.56) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 2ed14860dbf76..e2d641abcbaff 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -19,7 +19,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.35", features = ["rt-multi-thread"] } -thiserror = "1.0.55" +thiserror = "1.0.56" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 28b9886b14169..732ee768393cd 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = "1.0.55" +thiserror = "1.0.56" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 5e653d3b5862a..3a321e99158c6 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -24,7 +24,7 @@ serde_json = "1.0" sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.35", features = ["rt"] } -thiserror = "1.0.55" +thiserror = "1.0.56" # Bridge dependencies From 092b809b8dd6deb3f4cd933efd6b09c394c8cad8 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Thu, 18 Jan 2024 10:20:18 +0100 Subject: [PATCH 1170/1210] [`polkadot-staging`] Separate `send_message()` validations (#2795) * Fix xcm-bridge-hub build * Move send_message definition to MessagesBridge impl * Make send_message infallible * Split `MessagesBridge` into 2 phases Split `MessagesBridge` into 2 phases: - message validation - message sending --- modules/messages/src/benchmarking.rs | 4 +- modules/messages/src/lib.rs | 185 +++++++++++++----------- modules/messages/src/mock.rs | 8 +- modules/messages/src/outbound_lane.rs | 58 ++++---- modules/xcm-bridge-hub/src/exporter.rs | 71 +++++---- modules/xcm-bridge-hub/src/mock.rs | 22 +-- primitives/messages/src/source_chain.rs | 26 ++-- primitives/runtime/src/lib.rs | 2 +- 8 files changed, 180 insertions(+), 196 deletions(-) diff --git a/modules/messages/src/benchmarking.rs b/modules/messages/src/benchmarking.rs index 8c4e6fbf00ca4..4f13c4409672b 100644 --- a/modules/messages/src/benchmarking.rs +++ b/modules/messages/src/benchmarking.rs @@ -31,7 +31,7 @@ use codec::Decode; use frame_benchmarking::{account, benchmarks_instance_pallet}; use frame_support::weights::Weight; use frame_system::RawOrigin; -use sp_runtime::traits::TrailingZeroInput; +use sp_runtime::{traits::TrailingZeroInput, BoundedVec}; use sp_std::{ops::RangeInclusive, prelude::*}; const SEED: u32 = 0; @@ -443,7 +443,7 @@ benchmarks_instance_pallet! { fn send_regular_message, I: 'static>() { let mut outbound_lane = outbound_lane::(T::bench_lane_id()); - outbound_lane.send_message(vec![]).expect("We craft valid messages"); + outbound_lane.send_message(BoundedVec::try_from(vec![]).expect("We craft valid messages")); } fn receive_messages, I: 'static>(nonce: MessageNonce) { diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index 401ec185485b7..a86cb326cf040 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -534,6 +534,7 @@ pub mod pallet { } #[pallet::error] + #[derive(PartialEq, Eq)] pub enum Error { /// Pallet is not in Normal operating mode. NotOperatingNormally, @@ -543,8 +544,6 @@ pub mod pallet { MessageDispatchInactive, /// Message has been treated as invalid by chain verifier. MessageRejectedByChainVerifier(VerificationError), - /// Message has been treated as invalid by lane verifier. - MessageRejectedByLaneVerifier(VerificationError), /// Message has been treated as invalid by the pallet logic. MessageRejectedByPallet(VerificationError), /// Submitter has failed to pay fee for delivering and dispatching messages. @@ -690,68 +689,72 @@ pub mod pallet { } } +/// Structure, containing a validated message payload and all the info required +/// to send it on the bridge. +#[derive(Debug, PartialEq, Eq)] +pub struct SendMessageArgs, I: 'static> { + lane_id: LaneId, + payload: StoredMessagePayload, +} + impl bp_messages::source_chain::MessagesBridge for Pallet where T: Config, I: 'static, { - type Error = sp_runtime::DispatchErrorWithPostInfo; + type Error = Error; + type SendMessageArgs = SendMessageArgs; - fn send_message( + fn validate_message( lane: LaneId, - message: T::OutboundPayload, - ) -> Result { - crate::send_message::(lane, message) + message: &T::OutboundPayload, + ) -> Result, Self::Error> { + ensure_normal_operating_mode::()?; + + // let's check if outbound lane is active + ensure!(T::ActiveOutboundLanes::get().contains(&lane), Error::::InactiveOutboundLane); + + // let's first check if message can be delivered to target chain + T::TargetHeaderChain::verify_message(message).map_err(|err| { + log::trace!( + target: LOG_TARGET, + "Message to lane {:?} is rejected by target chain: {:?}", + lane, + err, + ); + + Error::::MessageRejectedByChainVerifier(err) + })?; + + Ok(SendMessageArgs { + lane_id: lane, + payload: StoredMessagePayload::::try_from(message.encode()).map_err(|_| { + Error::::MessageRejectedByPallet(VerificationError::MessageTooLarge) + })?, + }) } -} -/// Function that actually sends message. -fn send_message, I: 'static>( - lane_id: LaneId, - payload: T::OutboundPayload, -) -> sp_std::result::Result< - SendMessageArtifacts, - sp_runtime::DispatchErrorWithPostInfo, -> { - ensure_normal_operating_mode::()?; - - // let's check if outbound lane is active - ensure!(T::ActiveOutboundLanes::get().contains(&lane_id), Error::::InactiveOutboundLane,); - - // let's first check if message can be delivered to target chain - T::TargetHeaderChain::verify_message(&payload).map_err(|err| { + fn send_message(args: SendMessageArgs) -> SendMessageArtifacts { + // save message in outbound storage and emit event + let mut lane = outbound_lane::(args.lane_id); + let message_len = args.payload.len(); + let nonce = lane.send_message(args.payload); + + // return number of messages in the queue to let sender know about its state + let enqueued_messages = lane.data().queued_messages().saturating_len(); + log::trace!( target: LOG_TARGET, - "Message to lane {:?} is rejected by target chain: {:?}", - lane_id, - err, + "Accepted message {} to lane {:?}. Message size: {:?}", + nonce, + args.lane_id, + message_len, ); - Error::::MessageRejectedByChainVerifier(err) - })?; - - // finally, save message in outbound storage and emit event - let mut lane = outbound_lane::(lane_id); - let encoded_payload = payload.encode(); - let encoded_payload_len = encoded_payload.len(); - let nonce = lane - .send_message(encoded_payload) - .map_err(Error::::MessageRejectedByPallet)?; - - // return number of messages in the queue to let sender know about its state - let enqueued_messages = lane.data().queued_messages().saturating_len(); - - log::trace!( - target: LOG_TARGET, - "Accepted message {} to lane {:?}. Message size: {:?}", - nonce, - lane_id, - encoded_payload_len, - ); - - Pallet::::deposit_event(Event::MessageAccepted { lane_id, nonce }); + Pallet::::deposit_event(Event::MessageAccepted { lane_id: args.lane_id, nonce }); - Ok(SendMessageArtifacts { nonce, enqueued_messages }) + SendMessageArtifacts { nonce, enqueued_messages } + } } /// Ensure that the pallet is in normal operational mode. @@ -852,6 +855,8 @@ struct RuntimeOutboundLaneStorage { } impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage { + type StoredMessagePayload = StoredMessagePayload; + fn id(&self) -> LaneId { self.lane_id } @@ -865,22 +870,15 @@ impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorag } #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option { + fn message(&self, nonce: &MessageNonce) -> Option { OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce }) - .map(Into::into) } - fn save_message( - &mut self, - nonce: MessageNonce, - message_payload: MessagePayload, - ) -> Result<(), VerificationError> { + fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload) { OutboundMessages::::insert( MessageKey { lane_id: self.lane_id, nonce }, - StoredMessagePayload::::try_from(message_payload) - .map_err(|_| VerificationError::MessageTooLarge)?, + message_payload, ); - Ok(()) } fn remove_message(&mut self, nonce: &MessageNonce) { @@ -927,7 +925,10 @@ mod tests { }, outbound_lane::ReceivalConfirmationError, }; - use bp_messages::{BridgeMessagesCall, UnrewardedRelayer, UnrewardedRelayersState}; + use bp_messages::{ + source_chain::MessagesBridge, BridgeMessagesCall, UnrewardedRelayer, + UnrewardedRelayersState, + }; use bp_test_utils::generate_owned_bridge_module_tests; use frame_support::{ assert_noop, assert_ok, @@ -944,14 +945,15 @@ mod tests { System::::reset_events(); } - fn send_regular_message() { + fn send_regular_message(lane_id: LaneId) { get_ready_for_events(); - let outbound_lane = outbound_lane::(TEST_LANE_ID); + let outbound_lane = outbound_lane::(lane_id); let message_nonce = outbound_lane.data().latest_generated_nonce + 1; let prev_enqueud_messages = outbound_lane.data().queued_messages().saturating_len(); - let artifacts = send_message::(TEST_LANE_ID, REGULAR_PAYLOAD) - .expect("send_message has failed"); + let valid_message = Pallet::::validate_message(lane_id, ®ULAR_PAYLOAD) + .expect("validate_message has failed"); + let artifacts = Pallet::::send_message(valid_message); assert_eq!(artifacts.enqueued_messages, prev_enqueud_messages + 1); // check event with assigned nonce @@ -960,7 +962,7 @@ mod tests { vec![EventRecord { phase: Phase::Initialization, event: TestEvent::Messages(Event::MessageAccepted { - lane_id: TEST_LANE_ID, + lane_id, nonce: message_nonce }), topics: vec![], @@ -1011,14 +1013,14 @@ mod tests { fn pallet_rejects_transactions_if_halted() { run_test(|| { // send message first to be able to check that delivery_proof fails later - send_regular_message(); + send_regular_message(TEST_LANE_ID); PalletOperatingMode::::put(MessagesOperatingMode::Basic( BasicOperatingMode::Halted, )); assert_noop!( - send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,), + Pallet::::validate_message(TEST_LANE_ID, ®ULAR_PAYLOAD), Error::::NotOperatingNormally, ); @@ -1061,14 +1063,14 @@ mod tests { fn pallet_rejects_new_messages_in_rejecting_outbound_messages_operating_mode() { run_test(|| { // send message first to be able to check that delivery_proof fails later - send_regular_message(); + send_regular_message(TEST_LANE_ID); PalletOperatingMode::::put( MessagesOperatingMode::RejectingOutboundMessages, ); assert_noop!( - send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,), + Pallet::::validate_message(TEST_LANE_ID, ®ULAR_PAYLOAD), Error::::NotOperatingNormally, ); @@ -1104,7 +1106,7 @@ mod tests { #[test] fn send_message_works() { run_test(|| { - send_regular_message(); + send_regular_message(TEST_LANE_ID); }); } @@ -1118,7 +1120,7 @@ mod tests { .extra .extend_from_slice(&[0u8; MAX_OUTBOUND_PAYLOAD_SIZE as usize]); assert_noop!( - send_message::(TEST_LANE_ID, message_payload.clone(),), + Pallet::::validate_message(TEST_LANE_ID, &message_payload.clone(),), Error::::MessageRejectedByPallet( VerificationError::MessageTooLarge ), @@ -1129,7 +1131,11 @@ mod tests { message_payload.extra.pop(); } assert_eq!(message_payload.encoded_size() as u32, MAX_OUTBOUND_PAYLOAD_SIZE); - assert_ok!(send_message::(TEST_LANE_ID, message_payload,),); + + let valid_message = + Pallet::::validate_message(TEST_LANE_ID, &message_payload) + .expect("validate_message has failed"); + Pallet::::send_message(valid_message); }) } @@ -1138,7 +1144,10 @@ mod tests { run_test(|| { // messages with this payload are rejected by target chain verifier assert_noop!( - send_message::(TEST_LANE_ID, PAYLOAD_REJECTED_BY_TARGET_CHAIN,), + Pallet::::validate_message( + TEST_LANE_ID, + &PAYLOAD_REJECTED_BY_TARGET_CHAIN, + ), Error::::MessageRejectedByChainVerifier(VerificationError::Other( mock::TEST_ERROR )), @@ -1298,7 +1307,7 @@ mod tests { #[test] fn receive_messages_delivery_proof_works() { run_test(|| { - send_regular_message(); + send_regular_message(TEST_LANE_ID); receive_messages_delivery_proof(); assert_eq!( @@ -1311,8 +1320,8 @@ mod tests { #[test] fn receive_messages_delivery_proof_rewards_relayers() { run_test(|| { - assert_ok!(send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,)); - assert_ok!(send_message::(TEST_LANE_ID, REGULAR_PAYLOAD,)); + send_regular_message(TEST_LANE_ID); + send_regular_message(TEST_LANE_ID); // this reports delivery of message 1 => reward is paid to TEST_RELAYER_A let single_message_delivery_proof = TestMessagesDeliveryProof(Ok(( @@ -1698,9 +1707,9 @@ mod tests { #[test] fn messages_delivered_callbacks_are_called() { run_test(|| { - send_regular_message(); - send_regular_message(); - send_regular_message(); + send_regular_message(TEST_LANE_ID); + send_regular_message(TEST_LANE_ID); + send_regular_message(TEST_LANE_ID); // messages 1+2 are confirmed in 1 tx, message 3 in a separate tx // dispatch of message 2 has failed @@ -1759,7 +1768,7 @@ mod tests { ) { run_test(|| { // send message first to be able to check that delivery_proof fails later - send_regular_message(); + send_regular_message(TEST_LANE_ID); // 1) InboundLaneData declares that the `last_confirmed_nonce` is 1; // 2) InboundLaneData has no entries => `InboundLaneData::last_delivered_nonce()` @@ -1826,10 +1835,10 @@ mod tests { #[test] fn on_idle_callback_respects_remaining_weight() { run_test(|| { - send_regular_message(); - send_regular_message(); - send_regular_message(); - send_regular_message(); + send_regular_message(TEST_LANE_ID); + send_regular_message(TEST_LANE_ID); + send_regular_message(TEST_LANE_ID); + send_regular_message(TEST_LANE_ID); assert_ok!(Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), @@ -1908,10 +1917,10 @@ mod tests { fn on_idle_callback_is_rotating_lanes_to_prune() { run_test(|| { // send + receive confirmation for lane 1 - send_regular_message(); + send_regular_message(TEST_LANE_ID); receive_messages_delivery_proof(); // send + receive confirmation for lane 2 - assert_ok!(send_message::(TEST_LANE_ID_2, REGULAR_PAYLOAD,)); + send_regular_message(TEST_LANE_ID_2); assert_ok!(Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), TestMessagesDeliveryProof(Ok(( @@ -1987,7 +1996,7 @@ mod tests { fn outbound_message_from_unconfigured_lane_is_rejected() { run_test(|| { assert_noop!( - send_message::(TEST_LANE_ID_3, REGULAR_PAYLOAD,), + Pallet::::validate_message(TEST_LANE_ID_3, ®ULAR_PAYLOAD,), Error::::InactiveOutboundLane, ); }); diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index 303e641ea2d3c..af92120539854 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -17,7 +17,7 @@ // From construct_runtime macro #![allow(clippy::from_over_into)] -use crate::Config; +use crate::{Config, StoredMessagePayload}; use bp_messages::{ calc_relayers_rewards, @@ -26,7 +26,7 @@ use bp_messages::{ DeliveryPayments, DispatchMessage, DispatchMessageData, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain, }, - DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, MessagePayload, + DeliveredMessages, InboundLaneData, LaneId, Message, MessageKey, MessageNonce, UnrewardedRelayer, UnrewardedRelayersState, VerificationError, }; use bp_runtime::{messages::MessageDispatchResult, Size}; @@ -402,8 +402,8 @@ pub fn message(nonce: MessageNonce, payload: TestPayload) -> Message { } /// Return valid outbound message data, constructed from given payload. -pub fn outbound_message_data(payload: TestPayload) -> MessagePayload { - payload.encode() +pub fn outbound_message_data(payload: TestPayload) -> StoredMessagePayload { + StoredMessagePayload::::try_from(payload.encode()).expect("payload too large") } /// Return valid inbound (dispatch) message data, constructed from given payload. diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index f92e9ccfd95c6..431c2cfb7eef3 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -18,10 +18,7 @@ use crate::{Config, LOG_TARGET}; -use bp_messages::{ - DeliveredMessages, LaneId, MessageNonce, MessagePayload, OutboundLaneData, UnrewardedRelayer, - VerificationError, -}; +use bp_messages::{DeliveredMessages, LaneId, MessageNonce, OutboundLaneData, UnrewardedRelayer}; use codec::{Decode, Encode}; use frame_support::{ weights::{RuntimeDbWeight, Weight}, @@ -34,6 +31,8 @@ use sp_std::collections::vec_deque::VecDeque; /// Outbound lane storage. pub trait OutboundLaneStorage { + type StoredMessagePayload; + /// Lane id. fn id(&self) -> LaneId; /// Get lane data from the storage. @@ -42,13 +41,9 @@ pub trait OutboundLaneStorage { fn set_data(&mut self, data: OutboundLaneData); /// Returns saved outbound message payload. #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option; + fn message(&self, nonce: &MessageNonce) -> Option; /// Save outbound message in the storage. - fn save_message( - &mut self, - nonce: MessageNonce, - message_payload: MessagePayload, - ) -> Result<(), VerificationError>; + fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload); /// Remove outbound message from the storage. fn remove_message(&mut self, nonce: &MessageNonce); } @@ -91,18 +86,15 @@ impl OutboundLane { /// Send message over lane. /// /// Returns new message nonce. - pub fn send_message( - &mut self, - message_payload: MessagePayload, - ) -> Result { + pub fn send_message(&mut self, message_payload: S::StoredMessagePayload) -> MessageNonce { let mut data = self.storage.data(); let nonce = data.latest_generated_nonce + 1; data.latest_generated_nonce = nonce; - self.storage.save_message(nonce, message_payload)?; + self.storage.save_message(nonce, message_payload); self.storage.set_data(data); - Ok(nonce) + nonce } /// Confirm messages delivery. @@ -218,7 +210,7 @@ mod tests { }, outbound_lane, }; - use frame_support::{assert_ok, weights::constants::RocksDbWeight}; + use frame_support::weights::constants::RocksDbWeight; use sp_std::ops::RangeInclusive; fn unrewarded_relayers( @@ -239,9 +231,9 @@ mod tests { ) -> Result, ReceivalConfirmationError> { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); let result = lane.confirm_delivery(3, latest_received_nonce, relayers); @@ -256,7 +248,7 @@ mod tests { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); assert_eq!(lane.storage.data().latest_generated_nonce, 0); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1)); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1); assert!(lane.storage.message(&1).is_some()); assert_eq!(lane.storage.data().latest_generated_nonce, 1); }); @@ -266,9 +258,9 @@ mod tests { fn confirm_delivery_works() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(1)); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(2)); - assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), Ok(3)); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 1); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 2); + assert_eq!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD)), 3); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( @@ -284,9 +276,9 @@ mod tests { fn confirm_delivery_rejects_nonce_lesser_than_latest_received() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!(lane.storage.data().latest_generated_nonce, 3); assert_eq!(lane.storage.data().latest_received_nonce, 0); assert_eq!( @@ -368,9 +360,9 @@ mod tests { ); assert_eq!(lane.storage.data().oldest_unpruned_nonce, 1); // when nothing is confirmed, nothing is pruned - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert!(lane.storage.message(&1).is_some()); assert!(lane.storage.message(&2).is_some()); assert!(lane.storage.message(&3).is_some()); @@ -412,9 +404,9 @@ mod tests { fn confirm_delivery_detects_when_more_than_expected_messages_are_confirmed() { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); - assert_ok!(lane.send_message(outbound_message_data(REGULAR_PAYLOAD))); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); + lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!( lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), diff --git a/modules/xcm-bridge-hub/src/exporter.rs b/modules/xcm-bridge-hub/src/exporter.rs index 5318b222c5452..4e899dfa01139 100644 --- a/modules/xcm-bridge-hub/src/exporter.rs +++ b/modules/xcm-bridge-hub/src/exporter.rs @@ -42,12 +42,13 @@ type MessagesPallet = BridgeMessagesPallet>::BridgeMess impl, I: 'static> ExportXcm for Pallet where - T: BridgeMessagesConfig< - >::BridgeMessagesPalletInstance, - OutboundPayload = XcmAsPlainPayload, - >, + T: BridgeMessagesConfig, { - type Ticket = (SenderAndLane, XcmAsPlainPayload, XcmHash); + type Ticket = ( + SenderAndLane, + as MessagesBridge>::SendMessageArgs, + XcmHash, + ); fn validate( network: NetworkId, @@ -74,42 +75,38 @@ where message, )?; - Ok(((sender_and_lane, blob, id), price)) - } - - fn deliver( - (sender_and_lane, blob, id): (SenderAndLane, XcmAsPlainPayload, XcmHash), - ) -> Result { - let lane_id = sender_and_lane.lane; - let send_result = MessagesPallet::::send_message(lane_id, blob); - - match send_result { - Ok(artifacts) => { - log::info!( - target: LOG_TARGET, - "XCM message {:?} has been enqueued at bridge {:?} with nonce {}", - id, - lane_id, - artifacts.nonce, - ); - - // notify XCM queue manager about updated lane state - LocalXcmQueueManager::::on_bridge_message_enqueued( - &sender_and_lane, - artifacts.enqueued_messages, - ); - }, - Err(error) => { + let bridge_message = MessagesPallet::::validate_message(sender_and_lane.lane, &blob) + .map_err(|e| { log::debug!( target: LOG_TARGET, - "XCM message {:?} has been dropped because of bridge error {:?} on bridge {:?}", + "XCM message {:?} cannot be exported because of bridge error {:?} on bridge {:?}", id, - error, - lane_id, + e, + sender_and_lane.lane, ); - return Err(SendError::Transport("BridgeSendError")) - }, - } + SendError::Transport("BridgeValidateError") + })?; + + Ok(((sender_and_lane, bridge_message, id), price)) + } + + fn deliver((sender_and_lane, bridge_message, id): Self::Ticket) -> Result { + let lane_id = sender_and_lane.lane; + let artifacts = MessagesPallet::::send_message(bridge_message); + + log::info!( + target: LOG_TARGET, + "XCM message {:?} has been enqueued at bridge {:?} with nonce {}", + id, + lane_id, + artifacts.nonce, + ); + + // notify XCM queue manager about updated lane state + LocalXcmQueueManager::::on_bridge_message_enqueued( + &sender_and_lane, + artifacts.enqueued_messages, + ); Ok(id) } diff --git a/modules/xcm-bridge-hub/src/mock.rs b/modules/xcm-bridge-hub/src/mock.rs index 8edd4b1f7aa9b..97fc7741e4058 100644 --- a/modules/xcm-bridge-hub/src/mock.rs +++ b/modules/xcm-bridge-hub/src/mock.rs @@ -19,11 +19,10 @@ use crate as pallet_xcm_bridge_hub; use bp_messages::{ - source_chain::LaneMessageVerifier, target_chain::{DispatchMessage, MessageDispatch}, - LaneId, OutboundLaneData, VerificationError, + LaneId, }; -use bp_runtime::{messages::MessageDispatchResult, Chain, UnderlyingChainProvider}; +use bp_runtime::{messages::MessageDispatchResult, Chain, ChainId, UnderlyingChainProvider}; use bridge_runtime_common::{ messages::{ source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter, @@ -78,20 +77,6 @@ impl pallet_balances::Config for TestRuntime { type AccountStore = System; } -/// Lane message verifier that is used in tests. -#[derive(Debug, Default)] -pub struct TestLaneMessageVerifier; - -impl LaneMessageVerifier> for TestLaneMessageVerifier { - fn verify_message( - _lane: &LaneId, - _lane_outbound_data: &OutboundLaneData, - _payload: &Vec, - ) -> Result<(), VerificationError> { - Ok(()) - } -} - parameter_types! { pub const ActiveOutboundLanes: &'static [LaneId] = &[TEST_LANE_ID]; } @@ -110,7 +95,6 @@ impl pallet_bridge_messages::Config for TestRuntime { type InboundRelayer = (); type DeliveryPayments = (); type TargetHeaderChain = TargetHeaderChainAdapter; - type LaneMessageVerifier = TestLaneMessageVerifier; type DeliveryConfirmationPayments = (); type OnMessagesDelivered = (); type SourceHeaderChain = SourceHeaderChainAdapter; @@ -220,6 +204,7 @@ impl XcmBlobHauler for TestXcmBlobHauler { pub struct ThisChain; impl Chain for ThisChain { + const ID: ChainId = *b"tuch"; type BlockNumber = u64; type Hash = H256; type Hasher = BlakeTwo256; @@ -243,6 +228,7 @@ pub type BridgedHeaderHash = H256; pub type BridgedChainHeader = SubstrateHeader; impl Chain for BridgedChain { + const ID: ChainId = *b"tuch"; type BlockNumber = u64; type Hash = BridgedHeaderHash; type Hasher = BlakeTwo256; diff --git a/primitives/messages/src/source_chain.rs b/primitives/messages/src/source_chain.rs index 56bcf0bb4bc0d..f4aefd9735583 100644 --- a/primitives/messages/src/source_chain.rs +++ b/primitives/messages/src/source_chain.rs @@ -125,22 +125,22 @@ pub trait MessagesBridge { /// Error type. type Error: Debug; - /// Send message over the bridge. + /// Intermediary structure returned by `validate_message()`. /// - /// Returns unique message nonce or error if send has failed. - fn send_message(lane: LaneId, message: Payload) -> Result; -} - -/// Bridge that does nothing when message is being sent. -#[derive(Eq, RuntimeDebug, PartialEq)] -pub struct NoopMessagesBridge; + /// It can than be passed to `send_message()` in order to actually send the message + /// on the bridge. + type SendMessageArgs; -impl MessagesBridge for NoopMessagesBridge { - type Error = &'static str; + /// Check if the message can be sent over the bridge. + fn validate_message( + lane: LaneId, + message: &Payload, + ) -> Result; - fn send_message(_lane: LaneId, _message: Payload) -> Result { - Ok(SendMessageArtifacts { nonce: 0, enqueued_messages: 0 }) - } + /// Send message over the bridge. + /// + /// Returns unique message nonce or error if send has failed. + fn send_message(message: Self::SendMessageArgs) -> SendMessageArtifacts; } /// Structure that may be used in place of `TargetHeaderChain` and diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index e3bdc53c51549..850318923dc76 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -313,7 +313,7 @@ pub trait StorageDoubleMapKeyProvider { } /// Error generated by the `OwnedBridgeModule` trait. -#[derive(Encode, Decode, TypeInfo, PalletError)] +#[derive(Encode, Decode, PartialEq, Eq, TypeInfo, PalletError)] pub enum OwnedBridgeModuleError { /// All pallet operations are halted. Halted, From e42a55f0df8b6826fc0d9f590b27098411289a10 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 19 Jan 2024 10:09:45 +0100 Subject: [PATCH 1171/1210] [polkadot-staging] Backport polkadot-sdk changes + update refs (#2798) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix clippy lints behind feature gates and add new CI step all features (#2569) Many clippy lints usually enforced by `-Dcomplexity` and `-Dcorrectness` are not caught by CI as they are gated by `features`, like `runtime-benchmarks`, while the clippy CI job runs with only the default features for all targets. This PR also adds a CI step to run clippy with `--all-features` to ensure the code quality is maintained behind feature gates from now on. To improve local development, clippy lints are downgraded to warnings, but they still will result in an error at CI due to the `-Dwarnings` rustflag. --------- Co-authored-by: Liam Aharon * Cleanup bridges tests: with-grandpa-chain case (#2763) related to https://github.com/paritytech/parity-bridges-common/issues/2739 Co-authored-by: Branislav Kontur * Adds Snowbridge to Rococo runtime (#2522) # Description Adds Snowbridge to the Rococo bridge hub runtime. Includes config changes required in Rococo asset hub. --------- Co-authored-by: Alistair Singh Co-authored-by: ron Co-authored-by: Vincent Geddes Co-authored-by: claravanstaden * Bump the known_good_semver group with 4 updates (#2845) Bumps the known_good_semver group with 4 updates: [serde](https://github.com/serde-rs/serde), [serde_json](https://github.com/serde-rs/json), [clap](https://github.com/clap-rs/clap) and [serde_yaml](https://github.com/dtolnay/serde-yaml). Updates `serde` from 1.0.193 to 1.0.194
Release notes

Sourced from serde's releases.

v1.0.194

  • Update proc-macro2 to fix caching issue when using a rustc-wrapper such as sccache
Commits
  • d2d977a Release 1.0.194
  • a9a6ee9 Pull in proc-macro2 sccache fix
  • 28c5d21 Merge pull request #2669 from dtolnay/optionifletelse
  • 3d6a789 Remove option_if_let_else clippy suppression
  • a0e6869 Work around doc_link_with_quotes pedantic clippy lint
  • See full diff in compare view

Updates `serde_json` from 1.0.108 to 1.0.110
Release notes

Sourced from serde_json's releases.

v1.0.109

  • Documentation improvements
Commits
  • df5cf21 Release 1.0.110
  • c35856a Pull in proc-macro2 sccache fix
  • f88bf1f Release 1.0.109
  • bb62c73 Merge pull request #1097 from serde-rs/doccfg
  • df36d10 Restore doc cfg on re-exports
  • c367091 Merge pull request #1095 from dtolnay/hashtest
  • b328ee7 Eliminate hash closure in favor of calling hash_one directly
  • b9bcbad Use BuildHasher::hash_one
  • 7ff6c9e Use random hasher state for number hashing test
  • fe031cd Delete trace_macros! functionality from test
  • Additional commits viewable in compare view

Updates `clap` from 4.4.11 to 4.4.12
Release notes

Sourced from clap's releases.

v4.4.12

[4.4.12] - 2023-12-28

Performance

  • Only ask TypedValueParser for possible values if needed
Changelog

Sourced from clap's changelog.

[4.4.12] - 2023-12-28

Performance

  • Only ask TypedValueParser for possible values if needed
Commits
  • 6d601e6 chore: Release
  • 048e7f0 docs: Update changelog
  • 53f5b82 Merge pull request #5267 from vermiculus/sa/avoid-pv-expansion-in-help
  • 05cd057 perf: Avoid retrieving possible_values unless used
  • 2920808 test: Update snapshots
  • 28763eb chore: Release
  • ace7bb5 docs(complete): Update changelog
  • 76beca4 docs(complete): Polish API reference for dynamic
  • 3630e58 Merge pull request #5273 from epage/docsrs
  • 3724b9e docs: Include more content on docs.rs
  • See full diff in compare view

Updates `serde_yaml` from 0.9.29 to 0.9.30
Release notes

Sourced from serde_yaml's releases.

0.9.30

  • Update proc-macro2 to fix caching issue when using a rustc-wrapper such as sccache
Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix clippy warnings (#2861) Fix some issues reported by clippy * Bump the known_good_semver group with 4 updates (#2865) Bumps the known_good_semver group with 4 updates: [serde](https://github.com/serde-rs/serde), [serde_json](https://github.com/serde-rs/json), [clap](https://github.com/clap-rs/clap) and [syn](https://github.com/dtolnay/syn). Updates `serde` from 1.0.194 to 1.0.195
Release notes

Sourced from serde's releases.

v1.0.195

  • Prevent remote definitions of tuple struct or tuple variant from triggering dead_code warning (#2671)
Commits
  • 03eec42 Release 1.0.195
  • 196f311 Merge pull request #2671 from dtolnay/deadremote
  • 38d9e0b Revert "Add FIXME to fix dead_code warning when using serde(remote)"
  • 6502b31 Fix new dead_code warning in tuple struct and tuple variant remote defs
  • 6f1a8c3 Add FIXME to fix dead_code warning when using serde(remote)
  • d883c94 Work around dead_code warning in tests
  • 961fa59 Merge pull request #2670 from serde-rs/exhaustive
  • 8bc71de Fill in omitted patterns for GenericArguments match
  • 7c65a9d Pick up changes to non_exhaustive_omitted_patterns lint
  • See full diff in compare view

Updates `serde_json` from 1.0.110 to 1.0.111
Release notes

Sourced from serde_json's releases.

v1.0.111

  • Improve floating point parsing performance on loongarch64 (#1100, thanks @​heiher)
Commits

Updates `clap` from 4.4.12 to 4.4.13
Release notes

Sourced from clap's releases.

v4.4.13

[4.4.13] - 2024-01-04

Documentation

  • Fix link to structopt migration guide
Changelog

Sourced from clap's changelog.

[4.4.13] - 2024-01-04

Documentation

  • Fix link to structopt migration guide
Commits
  • 2ab48b2 chore: Release
  • 7a06a8c docs: Update changelog
  • cca190e docs: Correct link to StructOpt migration guide
  • 5c31f45 Merge pull request #5281 from Manishearth/safety-docs
  • ddae7e6 Correct safety docs
  • 48d28aa chore: Release
  • 748ce18 docs: Update changelog
  • adbe6ec Merge pull request #5278 from henry-hsieh/fix-nosort
  • 2b48858 fix: Skip nosort option below bash 4.4
  • 777b744 Merge pull request #5277 from clap-rs/renovate/actions-setup-python-5.x
  • Additional commits viewable in compare view

Updates `syn` from 2.0.47 to 2.0.48
Release notes

Sourced from syn's releases.

2.0.48

  • Improve error message on unexpected token after else (#1578)
Commits
  • 5e16fc2 Release 2.0.48
  • dc40084 Merge pull request #1578 from dtolnay/elseblock
  • 82fcefc Fix error message on unexpected token after 'else'
  • e8a5c68 Merge pull request #1576 from dtolnay/exhaustive
  • 97b1df6 Pick up changes to non_exhaustive_omitted_patterns lint
  • See full diff in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Snowbridge Rococo deployment updates (#2792) - Includes the introduction of the `fast-runtime` feature, which cleans up our features - Updates beacon client fork versions config to Sepolia's versions - Cleanup of AgentIdOf --------- Co-authored-by: Ron Co-authored-by: claravanstaden * Update Snowbridge versions and prep for publishing (#2894) - updates snowbridge crates to `0.9.0` - updates Cargo.toml files in preparation for publishing to crates.io - adds Kusama and Polkadot Snowbridge runtime config crates - moves runtime tests from the Snowbridge subtree into the bridge hub tests dir --------- Co-authored-by: claravanstaden Co-authored-by: Ron * Run bridges zombienet tests on CI (#2439) Brridges zombienet tests are non-standard - zombienet currently missing multiple relay chains support (see e.g. https://github.com/paritytech/zombienet/pull/796), so we need to go live with two relay networks, their parachains + custom test runner (which e.g. doesn't shutdown net when its tests are finished and instead waits for both networks tests to complete). So we are stuck with native zombienet provider => this PR is an attempt to gather everything in a single docker container and run tests there ~Draft, because it is far from finishing - what I want now is to see how it works on CI~ * XCMv4 (#1230) # Note for reviewer Most changes are just syntax changes necessary for the new version. Most important files should be the ones under the `xcm` folder. # Description Added XCMv4. ## Removed `Multi` prefix The following types have been renamed: - MultiLocation -> Location - MultiAsset -> Asset - MultiAssets -> Assets - InteriorMultiLocation -> InteriorLocation - MultiAssetFilter -> AssetFilter - VersionedMultiAsset -> VersionedAsset - WildMultiAsset -> WildAsset - VersionedMultiLocation -> VersionedLocation In order to fix a name conflict, the `Assets` in `xcm-executor` were renamed to `HoldingAssets`, as they represent assets in holding. ## Removed `Abstract` asset id It was not being used anywhere and this simplifies the code. Now assets are just constructed as follows: ```rust let asset: Asset = (AssetId(Location::new(1, Here)), 100u128).into(); ``` No need for specifying `Concrete` anymore. ## Outcome is now a named fields struct Instead of ```rust pub enum Outcome { Complete(Weight), Incomplete(Weight, Error), Error(Error), } ``` we now have ```rust pub enum Outcome { Complete { used: Weight }, Incomplete { used: Weight, error: Error }, Error { error: Error }, } ``` ## Added Reanchorable trait Now both locations and assets implement this trait, making it easier to reanchor both. ## New syntax for building locations and junctions Now junctions are built using the following methods: ```rust let location = Location { parents: 1, interior: [Parachain(1000), PalletInstance(50), GeneralIndex(1984)].into() }; ``` or ```rust let location = Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]); ``` And they are matched like so: ```rust match location.unpack() { (1, [Parachain(id)]) => ... (0, Here) => ..., (1, [_]) => ..., } ``` This syntax is mandatory in v4, and has been also implemented for v2 and v3 for easier migration. This was needed to make all sizes smaller. # TODO - [x] Scaffold v4 - [x] Port github.com/paritytech/polkadot/pull/7236 - [x] Remove `Multi` prefix - [x] Remove `Abstract` asset id --------- Co-authored-by: command-bot <> Co-authored-by: Keith Yeung * Fix typos (#2983) * Update polkadot-sdk refs * Update deprecated struct * Remove snowbridge folder * Westend/Rococo Asset Hub: pay xcm fees with sufficient assets (#2978) Set up the `TakeFirstAssetTrader` trader for Westend and Rococo Asset Hubs to cover XCM fees with sufficient assets. This PR reintroduces previously [removed](https://github.com/paritytech/polkadot-sdk/pull/1845) trader setups, as it was decided to keep both traders, `TakeFirstAssetTrader` and `SwapFirstAssetTrader`, during the transition period. --------- Co-authored-by: Svyatoslav Nikolsky --------- Signed-off-by: dependabot[bot] Co-authored-by: Dónal Murray Co-authored-by: Liam Aharon Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Branislav Kontur Co-authored-by: Clara van Staden Co-authored-by: Alistair Singh Co-authored-by: ron Co-authored-by: Vincent Geddes Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tsvetomir Dimitrov Co-authored-by: Francisco Aguirre Co-authored-by: Keith Yeung Co-authored-by: cristiantroy <154241727+cristiantroy@users.noreply.github.com> Co-authored-by: Muharem --- .../src/messages_benchmarking.rs | 12 +++---- .../src/messages_xcm_extension.rs | 22 ++++++------- modules/parachains/src/lib.rs | 2 +- modules/relayers/src/benchmarking.rs | 4 +-- .../xcm-bridge-hub-router/src/benchmarking.rs | 6 ++-- modules/xcm-bridge-hub-router/src/lib.rs | 33 +++++++------------ modules/xcm-bridge-hub-router/src/mock.rs | 18 +++++----- modules/xcm-bridge-hub/src/exporter.rs | 12 +++---- modules/xcm-bridge-hub/src/lib.rs | 14 ++++---- modules/xcm-bridge-hub/src/mock.rs | 17 ++++------ primitives/runtime/src/chain.rs | 2 +- relays/client-substrate/src/calls.rs | 4 +-- 12 files changed, 67 insertions(+), 79 deletions(-) diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bin/runtime-common/src/messages_benchmarking.rs index e7e7891461b21..0c7a9ad1a83d6 100644 --- a/bin/runtime-common/src/messages_benchmarking.rs +++ b/bin/runtime-common/src/messages_benchmarking.rs @@ -38,7 +38,7 @@ use frame_support::weights::Weight; use pallet_bridge_messages::benchmarking::{MessageDeliveryProofParams, MessageProofParams}; use sp_runtime::traits::{Header, Zero}; use sp_std::prelude::*; -use xcm::v3::prelude::*; +use xcm::latest::prelude::*; /// Prepare inbound bridge message according to given message proof parameters. fn prepare_inbound_message( @@ -266,19 +266,19 @@ where /// Returns callback which generates `BridgeMessage` from Polkadot XCM builder based on /// `expected_message_size` for benchmark. pub fn generate_xcm_builder_bridge_message_sample( - destination: InteriorMultiLocation, + destination: InteriorLocation, ) -> impl Fn(usize) -> MessagePayload { move |expected_message_size| -> MessagePayload { // For XCM bridge hubs, it is the message that // will be pushed further to some XCM queue (XCMP/UMP) - let location = xcm::VersionedInteriorMultiLocation::V3(destination); + let location = xcm::VersionedInteriorLocation::V4(destination.clone()); let location_encoded_size = location.encoded_size(); // we don't need to be super-precise with `expected_size` here let xcm_size = expected_message_size.saturating_sub(location_encoded_size); let xcm_data_size = xcm_size.saturating_sub( // minus empty instruction size - xcm::v3::Instruction::<()>::ExpectPallet { + Instruction::<()>::ExpectPallet { index: 0, name: vec![], module_name: vec![], @@ -294,8 +294,8 @@ pub fn generate_xcm_builder_bridge_message_sample( expected_message_size, location_encoded_size, xcm_size, xcm_data_size, ); - let xcm = xcm::VersionedXcm::<()>::V3( - vec![xcm::v3::Instruction::<()>::ExpectPallet { + let xcm = xcm::VersionedXcm::<()>::V4( + vec![Instruction::<()>::ExpectPallet { index: 0, name: vec![42; xcm_data_size], module_name: vec![], diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index 4892297a3dfdf..e3da6155f08a1 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -126,14 +126,14 @@ impl< #[cfg_attr(feature = "std", derive(Debug, Eq, PartialEq))] pub struct SenderAndLane { /// Sending chain relative location. - pub location: MultiLocation, + pub location: Location, /// Message lane, used by the sending chain. pub lane: LaneId, } impl SenderAndLane { /// Create new object using provided location and lane. - pub fn new(location: MultiLocation, lane: LaneId) -> Self { + pub fn new(location: Location, lane: LaneId) -> Self { SenderAndLane { location, lane } } } @@ -171,7 +171,7 @@ pub struct XcmBlobHaulerAdapter( impl< H: XcmBlobHauler, - Lanes: Get>, + Lanes: Get>, > OnMessagesDelivered for XcmBlobHaulerAdapter { fn on_messages_delivered(lane: LaneId, enqueued_messages: MessageNonce) { @@ -291,7 +291,7 @@ impl LocalXcmQueueManager { /// Send congested signal to the `sending_chain_location`. fn send_congested_signal(sender_and_lane: &SenderAndLane) -> Result<(), SendError> { if let Some(msg) = H::CongestedMessage::get() { - send_xcm::(sender_and_lane.location, msg)?; + send_xcm::(sender_and_lane.location.clone(), msg)?; OutboundLanesCongestedSignals::::insert( sender_and_lane.lane, true, @@ -303,7 +303,7 @@ impl LocalXcmQueueManager { /// Send `uncongested` signal to the `sending_chain_location`. fn send_uncongested_signal(sender_and_lane: &SenderAndLane) -> Result<(), SendError> { if let Some(msg) = H::UncongestedMessage::get() { - send_xcm::(sender_and_lane.location, msg)?; + send_xcm::(sender_and_lane.location.clone(), msg)?; OutboundLanesCongestedSignals::::remove( sender_and_lane.lane, ); @@ -318,10 +318,10 @@ impl LocalXcmQueueManager { pub struct XcmVersionOfDestAndRemoteBridge( sp_std::marker::PhantomData<(Version, RemoteBridge)>, ); -impl> GetVersion +impl> GetVersion for XcmVersionOfDestAndRemoteBridge { - fn get_version_for(dest: &MultiLocation) -> Option { + fn get_version_for(dest: &Location) -> Option { let dest_version = Version::get_version_for(dest); let bridge_hub_version = Version::get_version_for(&RemoteBridge::get()); @@ -345,11 +345,11 @@ mod tests { parameter_types! { pub TestSenderAndLane: SenderAndLane = SenderAndLane { - location: MultiLocation::new(1, X1(Parachain(1000))), + location: Location::new(1, [Parachain(1000)]), lane: TEST_LANE_ID, }; - pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![ - (TestSenderAndLane::get(), (NetworkId::ByGenesis([0; 32]), InteriorMultiLocation::Here)) + pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorLocation))> = sp_std::vec![ + (TestSenderAndLane::get(), (NetworkId::ByGenesis([0; 32]), InteriorLocation::Here)) ]; pub DummyXcmMessage: Xcm<()> = Xcm::new(); } @@ -366,7 +366,7 @@ mod tests { type Ticket = (); fn validate( - _destination: &mut Option, + _destination: &mut Option, _message: &mut Option>, ) -> SendResult { Ok(((), Default::default())) diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 9adeacb0eb882..87c57e84622aa 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -1494,7 +1494,7 @@ pub(crate) mod tests { ); // then if someone is pretending to provide updated head#10 of parachain#1 at relay - // block#30, and actualy provides it + // block#30, and actually provides it // // => we'll update value proceed(30, state_root_10_at_30); diff --git a/modules/relayers/src/benchmarking.rs b/modules/relayers/src/benchmarking.rs index 2d74ab38f9dbd..00c3814a4c38d 100644 --- a/modules/relayers/src/benchmarking.rs +++ b/modules/relayers/src/benchmarking.rs @@ -104,7 +104,7 @@ benchmarks! { // create slash destination account let lane = LaneId([0, 0, 0, 0]); let slash_destination = RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain); - T::prepare_rewards_account(slash_destination.clone(), Zero::zero()); + T::prepare_rewards_account(slash_destination, Zero::zero()); }: { crate::Pallet::::slash_and_deregister(&relayer, slash_destination) } @@ -121,7 +121,7 @@ benchmarks! { let account_params = RewardsAccountParams::new(lane, *b"test", RewardsAccountOwner::ThisChain); }: { - crate::Pallet::::register_relayer_reward(account_params.clone(), &relayer, One::one()); + crate::Pallet::::register_relayer_reward(account_params, &relayer, One::one()); } verify { assert_eq!(RelayerRewards::::get(relayer, &account_params), Some(One::one())); diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/modules/xcm-bridge-hub-router/src/benchmarking.rs index 922e4bf94ba8a..c4f9f534c1a47 100644 --- a/modules/xcm-bridge-hub-router/src/benchmarking.rs +++ b/modules/xcm-bridge-hub-router/src/benchmarking.rs @@ -37,10 +37,10 @@ pub trait Config: crate::Config { /// Returns destination which is valid for this router instance. /// (Needs to pass `T::Bridges`) /// Make sure that `SendXcm` will pass. - fn ensure_bridged_target_destination() -> Result { - Ok(MultiLocation::new( + fn ensure_bridged_target_destination() -> Result { + Ok(Location::new( Self::UniversalLocation::get().len() as u8, - X1(GlobalConsensus(Self::BridgedNetworkId::get().unwrap())), + [GlobalConsensus(Self::BridgedNetworkId::get().unwrap())], )) } } diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs index 229628aedcb8a..f219be78f9e1b 100644 --- a/modules/xcm-bridge-hub-router/src/lib.rs +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -80,7 +80,7 @@ pub mod pallet { type WeightInfo: WeightInfo; /// Universal location of this runtime. - type UniversalLocation: Get; + type UniversalLocation: Get; /// The bridged network that this config is for if specified. /// Also used for filtering `Bridges` by `BridgedNetworkId`. /// If not specified, allows all networks pass through. @@ -235,9 +235,9 @@ type ViaBridgeHubExporter = SovereignPaidRemoteExporter< impl, I: 'static> ExporterFor for Pallet { fn exporter_for( network: &NetworkId, - remote_location: &InteriorMultiLocation, + remote_location: &InteriorLocation, message: &Xcm<()>, - ) -> Option<(MultiLocation, Option)> { + ) -> Option<(Location, Option)> { // ensure that the message is sent to the expected bridged network (if specified). if let Some(bridged_network) = T::BridgedNetworkId::get() { if *network != bridged_network { @@ -268,7 +268,7 @@ impl, I: 'static> ExporterFor for Pallet { // take `base_fee` from `T::Brides`, but it has to be the same `T::FeeAsset` let base_fee = match maybe_payment { Some(payment) => match payment { - MultiAsset { fun: Fungible(amount), id } if id.eq(&T::FeeAsset::get()) => amount, + Asset { fun: Fungible(amount), id } if id.eq(&T::FeeAsset::get()) => amount, invalid_asset => { log::error!( target: LOG_TARGET, @@ -318,7 +318,7 @@ impl, I: 'static> SendXcm for Pallet { type Ticket = (u32, ::Ticket); fn validate( - dest: &mut Option, + dest: &mut Option, xcm: &mut Option>, ) -> SendResult { // `dest` and `xcm` are required here @@ -446,7 +446,7 @@ mod tests { run_test(|| { assert_eq!( send_xcm::( - MultiLocation::new(2, X2(GlobalConsensus(Rococo), Parachain(1000))), + Location::new(2, [GlobalConsensus(Rococo), Parachain(1000)]), vec![].into(), ), Err(SendError::NotApplicable), @@ -459,7 +459,7 @@ mod tests { run_test(|| { assert_eq!( send_xcm::( - MultiLocation::new(2, X2(GlobalConsensus(Rococo), Parachain(1000))), + Location::new(2, [GlobalConsensus(Rococo), Parachain(1000)]), vec![ClearOrigin; HARD_MESSAGE_SIZE_LIMIT as usize].into(), ), Err(SendError::ExceedsMaxMessageSize), @@ -483,14 +483,14 @@ mod tests { #[test] fn returns_proper_delivery_price() { run_test(|| { - let dest = MultiLocation::new(2, X1(GlobalConsensus(BridgedNetworkId::get()))); + let dest = Location::new(2, [GlobalConsensus(BridgedNetworkId::get())]); let xcm: Xcm<()> = vec![ClearOrigin].into(); let msg_size = xcm.encoded_size(); // initially the base fee is used: `BASE_FEE + BYTE_FEE * msg_size + HRMP_FEE` let expected_fee = BASE_FEE + BYTE_FEE * (msg_size as u128) + HRMP_FEE; assert_eq!( - XcmBridgeHubRouter::validate(&mut Some(dest), &mut Some(xcm.clone())) + XcmBridgeHubRouter::validate(&mut Some(dest.clone()), &mut Some(xcm.clone())) .unwrap() .1 .get(0), @@ -518,10 +518,7 @@ mod tests { run_test(|| { let old_bridge = XcmBridgeHubRouter::bridge(); assert_ok!(send_xcm::( - MultiLocation::new( - 2, - X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) - ), + Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)]), vec![ClearOrigin].into(), ) .map(drop)); @@ -538,10 +535,7 @@ mod tests { let old_bridge = XcmBridgeHubRouter::bridge(); assert_ok!(send_xcm::( - MultiLocation::new( - 2, - X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) - ), + Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)]), vec![ClearOrigin].into(), ) .map(drop)); @@ -560,10 +554,7 @@ mod tests { let old_bridge = XcmBridgeHubRouter::bridge(); assert_ok!(send_xcm::( - MultiLocation::new( - 2, - X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)) - ), + Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(1000)]), vec![ClearOrigin].into(), ) .map(drop)); diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 9079f4b9c4c64..6dbfba5f6fdc1 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -49,9 +49,9 @@ construct_runtime! { parameter_types! { pub ThisNetworkId: NetworkId = Polkadot; pub BridgedNetworkId: NetworkId = Kusama; - pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(ThisNetworkId::get()), Parachain(1000)); - pub SiblingBridgeHubLocation: MultiLocation = ParentThen(X1(Parachain(1002))).into(); - pub BridgeFeeAsset: AssetId = MultiLocation::parent().into(); + pub UniversalLocation: InteriorLocation = [GlobalConsensus(ThisNetworkId::get()), Parachain(1000)].into(); + pub SiblingBridgeHubLocation: Location = ParentThen([Parachain(1002)].into()).into(); + pub BridgeFeeAsset: AssetId = Location::parent().into(); pub BridgeTable: Vec = vec![ NetworkExportTableItem::new( @@ -61,7 +61,7 @@ parameter_types! { Some((BridgeFeeAsset::get(), BASE_FEE).into()) ) ]; - pub UnknownXcmVersionLocation: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(BridgedNetworkId::get()), Parachain(9999))); + pub UnknownXcmVersionLocation: Location = Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(9999)]); } #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] @@ -87,11 +87,11 @@ impl pallet_xcm_bridge_hub_router::Config<()> for TestRuntime { } pub struct LatestOrNoneForLocationVersionChecker(sp_std::marker::PhantomData); -impl> GetVersion - for LatestOrNoneForLocationVersionChecker +impl> GetVersion + for LatestOrNoneForLocationVersionChecker { - fn get_version_for(dest: &MultiLocation) -> Option { - if Location::contains(dest) { + fn get_version_for(dest: &Location) -> Option { + if LocationValue::contains(dest) { return None } Some(XCM_VERSION) @@ -110,7 +110,7 @@ impl SendXcm for TestToBridgeHubSender { type Ticket = (); fn validate( - _destination: &mut Option, + _destination: &mut Option, _message: &mut Option>, ) -> SendResult { Ok(((), (BridgeFeeAsset::get(), HRMP_FEE).into())) diff --git a/modules/xcm-bridge-hub/src/exporter.rs b/modules/xcm-bridge-hub/src/exporter.rs index 4e899dfa01139..94ec8b5f106fd 100644 --- a/modules/xcm-bridge-hub/src/exporter.rs +++ b/modules/xcm-bridge-hub/src/exporter.rs @@ -53,10 +53,10 @@ where fn validate( network: NetworkId, channel: u32, - universal_source: &mut Option, - destination: &mut Option, + universal_source: &mut Option, + destination: &mut Option, message: &mut Option>, - ) -> Result<(Self::Ticket, MultiAssets), SendError> { + ) -> Result<(Self::Ticket, Assets), SendError> { // Find supported lane_id. let sender_and_lane = Self::lane_for( universal_source.as_ref().ok_or(SendError::MissingArgument)?, @@ -134,11 +134,11 @@ mod tests { use frame_support::assert_ok; use xcm_executor::traits::export_xcm; - fn universal_source() -> InteriorMultiLocation { - X2(GlobalConsensus(RelayNetwork::get()), Parachain(SIBLING_ASSET_HUB_ID)) + fn universal_source() -> InteriorLocation { + [GlobalConsensus(RelayNetwork::get()), Parachain(SIBLING_ASSET_HUB_ID)].into() } - fn universal_destination() -> InteriorMultiLocation { + fn universal_destination() -> InteriorLocation { BridgedDestination::get() } diff --git a/modules/xcm-bridge-hub/src/lib.rs b/modules/xcm-bridge-hub/src/lib.rs index 44f6903b018b8..60b988497fc59 100644 --- a/modules/xcm-bridge-hub/src/lib.rs +++ b/modules/xcm-bridge-hub/src/lib.rs @@ -45,25 +45,25 @@ pub mod pallet { BridgeMessagesConfig { /// Runtime's universal location. - type UniversalLocation: Get; + type UniversalLocation: Get; // TODO: https://github.com/paritytech/parity-bridges-common/issues/1666 remove `ChainId` and // replace it with the `NetworkId` - then we'll be able to use // `T as pallet_bridge_messages::Config::BridgedChain::NetworkId` /// Bridged network as relative location of bridged `GlobalConsensus`. #[pallet::constant] - type BridgedNetwork: Get; + type BridgedNetwork: Get; /// Associated messages pallet instance that bridges us with the /// `BridgedNetworkId` consensus. type BridgeMessagesPalletInstance: 'static; /// Price of single message export to the bridged consensus (`Self::BridgedNetworkId`). - type MessageExportPrice: Get; + type MessageExportPrice: Get; /// Checks the XCM version for the destination. type DestinationVersion: GetVersion; /// Get point-to-point links with bridged consensus (`Self::BridgedNetworkId`). /// (this will be replaced with dynamic on-chain bridges - `Bridges V2`) - type Lanes: Get>; + type Lanes: Get>; /// Support for point-to-point links /// (this will be replaced with dynamic on-chain bridges - `Bridges V2`) type LanesSupport: XcmBlobHauler; @@ -86,10 +86,10 @@ pub mod pallet { impl, I: 'static> Pallet { /// Returns dedicated/configured lane identifier. pub(crate) fn lane_for( - source: &InteriorMultiLocation, - dest: (&NetworkId, &InteriorMultiLocation), + source: &InteriorLocation, + dest: (&NetworkId, &InteriorLocation), ) -> Option { - let source = source.relative_to(&T::UniversalLocation::get()); + let source = source.clone().relative_to(&T::UniversalLocation::get()); // Check that we have configured a point-to-point lane for 'source' and `dest`. T::Lanes::get() diff --git a/modules/xcm-bridge-hub/src/mock.rs b/modules/xcm-bridge-hub/src/mock.rs index 97fc7741e4058..e40e1f9fb6515 100644 --- a/modules/xcm-bridge-hub/src/mock.rs +++ b/modules/xcm-bridge-hub/src/mock.rs @@ -154,16 +154,13 @@ impl pallet_bridge_messages::WeightInfoExt for TestMessagesWeights { parameter_types! { pub const RelayNetwork: NetworkId = NetworkId::Kusama; pub const BridgedRelayNetwork: NetworkId = NetworkId::Polkadot; - pub const BridgedRelayNetworkLocation: MultiLocation = MultiLocation { - parents: 1, - interior: X1(GlobalConsensus(BridgedRelayNetwork::get())) - }; + pub BridgedRelayNetworkLocation: Location = (Parent, GlobalConsensus(BridgedRelayNetwork::get())).into(); pub const NonBridgedRelayNetwork: NetworkId = NetworkId::Rococo; pub const BridgeReserve: Balance = 100_000; - pub UniversalLocation: InteriorMultiLocation = X2( + pub UniversalLocation: InteriorLocation = [ GlobalConsensus(RelayNetwork::get()), Parachain(THIS_BRIDGE_HUB_ID), - ); + ].into(); pub const Penalty: Balance = 1_000; } @@ -181,13 +178,13 @@ impl pallet_xcm_bridge_hub::Config for TestRuntime { parameter_types! { pub TestSenderAndLane: SenderAndLane = SenderAndLane { - location: MultiLocation::new(1, X1(Parachain(SIBLING_ASSET_HUB_ID))), + location: Location::new(1, [Parachain(SIBLING_ASSET_HUB_ID)]), lane: TEST_LANE_ID, }; - pub const BridgedDestination: InteriorMultiLocation = X1( + pub BridgedDestination: InteriorLocation = [ Parachain(BRIDGED_ASSET_HUB_ID) - ); - pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorMultiLocation))> = sp_std::vec![ + ].into(); + pub TestLanes: sp_std::vec::Vec<(SenderAndLane, (NetworkId, InteriorLocation))> = sp_std::vec![ (TestSenderAndLane::get(), (BridgedRelayNetwork::get(), BridgedDestination::get())) ]; } diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 7ca956e267013..9ba21a1cddf13 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -203,7 +203,7 @@ pub trait Chain: Send + Sync + 'static { } /// A trait that provides the type of the underlying chain. -pub trait UnderlyingChainProvider { +pub trait UnderlyingChainProvider: Send + Sync + 'static { /// Underlying chain type. type Chain: Chain; } diff --git a/relays/client-substrate/src/calls.rs b/relays/client-substrate/src/calls.rs index 4e0ae9d99d2e6..71b9ec84aca30 100644 --- a/relays/client-substrate/src/calls.rs +++ b/relays/client-substrate/src/calls.rs @@ -20,7 +20,7 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; use sp_std::{boxed::Box, vec::Vec}; -use xcm::{VersionedMultiLocation, VersionedXcm}; +use xcm::{VersionedLocation, VersionedXcm}; /// A minimized version of `frame-system::Call` that can be used without a runtime. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] @@ -55,5 +55,5 @@ pub enum SudoCall { pub enum XcmCall { /// `pallet-xcm::Call::send` #[codec(index = 0)] - send(Box, Box>), + send(Box, Box>), } From 29d1151b4549a6efdcd1f327d04048aa4d849868 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 02:57:13 +0000 Subject: [PATCH 1172/1210] Bump env_logger from 0.10.1 to 0.11.0 Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.10.1 to 0.11.0. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.10.1...v0.11.0) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 88c22fa8f232f..61ef1dbfb0d8a 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -13,7 +13,7 @@ anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } -env_logger = "0.10" +env_logger = "0.11" futures = "0.3.30" hex = "0.4" log = "0.4.20" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 6f4a2596f122b..c03699b01eab9 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1" -env_logger = "0.10" +env_logger = "0.11" futures = "0.3.30" hex = "0.4" log = "0.4.20" diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 3a321e99158c6..0672be6335fea 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -15,7 +15,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" isahc = "1.2" -env_logger = "0.10.1" +env_logger = "0.11.0" futures = "0.3.30" jsonpath_lib = "0.3" log = "0.4.20" From 3c4d88ce05f5173d59057d3ce8a1b08024649bad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 02:10:59 +0000 Subject: [PATCH 1173/1210] Bump env_logger from 0.11.0 to 0.11.1 Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 0672be6335fea..d32423568254a 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -15,7 +15,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" isahc = "1.2" -env_logger = "0.11.0" +env_logger = "0.11.1" futures = "0.3.30" jsonpath_lib = "0.3" log = "0.4.20" From ed2cda2beaa36be4c1b51cdb0d5273e9ade896f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 02:10:16 +0000 Subject: [PATCH 1174/1210] Bump strum from 0.25.0 to 0.26.1 Bumps [strum](https://github.com/Peternator7/strum) from 0.25.0 to 0.26.1. - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 61ef1dbfb0d8a..b284cda17884b 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -23,7 +23,7 @@ rbtag = "0.3" structopt = "0.3" signal-hook = "0.3.15" signal-hook-async-std = "0.2.2" -strum = { version = "0.25.0", features = ["derive"] } +strum = { version = "0.26.1", features = ["derive"] } # Bridge dependencies bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } From 8fa72789004a16606f59ecae8a695d53a39f66e7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 29 Jan 2024 09:28:32 +0300 Subject: [PATCH 1175/1210] fix clippy --- relays/bin-substrate/src/cli/bridge.rs | 4 ++-- relays/bin-substrate/src/cli/chain_schema.rs | 4 ++-- relays/bin-substrate/src/cli/detect_equivocations.rs | 4 ++-- relays/bin-substrate/src/cli/init_bridge.rs | 4 ++-- relays/bin-substrate/src/cli/mod.rs | 4 ++-- relays/bin-substrate/src/cli/relay_headers.rs | 4 ++-- relays/bin-substrate/src/cli/relay_parachains.rs | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/bin-substrate/src/cli/bridge.rs index 6073d9e3155bb..9457dfa5c0680 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/bin-substrate/src/cli/bridge.rs @@ -17,7 +17,7 @@ use crate::cli::CliChain; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; -use strum::{EnumString, EnumVariantNames}; +use strum::{EnumString, VariantNames}; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, @@ -25,7 +25,7 @@ use substrate_relay_helper::{ parachains::SubstrateParachainsPipeline, }; -#[derive(Debug, PartialEq, Eq, EnumString, EnumVariantNames)] +#[derive(Debug, PartialEq, Eq, EnumString, VariantNames)] #[strum(serialize_all = "kebab_case")] /// Supported full bridges (headers + messages). pub enum FullBridge { diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 5c2161acdbd70..7c647dfbfd1df 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -17,14 +17,14 @@ use relay_substrate_client::{AccountKeyPairOf, ChainWithTransactions}; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames}; +use strum::{EnumString, VariantNames}; use crate::cli::CliChain; pub use relay_substrate_client::{ChainRuntimeVersion, SimpleRuntimeVersion}; use substrate_relay_helper::TransactionParams; #[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] pub enum RuntimeVersionType { /// Auto query version from chain Auto, diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs index 970089453bd5a..a8f1ed35f3afb 100644 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -31,7 +31,7 @@ use crate::{ use async_trait::async_trait; use relay_substrate_client::ChainWithTransactions; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; +use strum::{EnumString, VariantNames}; use substrate_relay_helper::{equivocation, equivocation::SubstrateEquivocationDetectionPipeline}; /// Start equivocation detection loop. @@ -49,7 +49,7 @@ pub struct DetectEquivocations { prometheus_params: PrometheusParams, } -#[derive(Debug, EnumString, EnumVariantNames)] +#[derive(Debug, EnumString, VariantNames)] #[strum(serialize_all = "kebab_case")] /// Equivocations detection bridge. pub enum DetectEquivocationsBridge { diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 8be74e5f9b535..027dd4c482f87 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -42,7 +42,7 @@ use bp_runtime::Chain as ChainBase; use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; use sp_core::Pair; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; +use strum::{EnumString, VariantNames}; use substrate_relay_helper::finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}; /// Initialize bridge pallet. @@ -62,7 +62,7 @@ pub struct InitBridge { dry_run: bool, } -#[derive(Debug, EnumString, EnumVariantNames)] +#[derive(Debug, EnumString, VariantNames)] #[strum(serialize_all = "kebab_case")] /// Bridge to initialize. pub enum InitBridgeName { diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 580463ef9f9ed..6d799023cdbc0 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -23,7 +23,7 @@ use rbtag::BuildInfo; use signal_hook::consts::*; use signal_hook_async_std::Signals; use structopt::{clap::arg_enum, StructOpt}; -use strum::{EnumString, EnumVariantNames}; +use strum::{EnumString, VariantNames}; use bp_messages::LaneId; use relay_substrate_client::SimpleRuntimeVersion; @@ -288,7 +288,7 @@ where } #[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, EnumVariantNames)] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] pub enum RuntimeVersionType { /// Auto query version from chain Auto, diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index 5e43c98770072..a3b5c4c9f82dd 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -16,7 +16,7 @@ use async_trait::async_trait; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; +use strum::{EnumString, VariantNames}; use crate::bridges::{ kusama_polkadot::{ @@ -57,7 +57,7 @@ pub struct RelayHeaders { prometheus_params: PrometheusParams, } -#[derive(Debug, EnumString, EnumVariantNames)] +#[derive(Debug, EnumString, VariantNames)] #[strum(serialize_all = "kebab_case")] /// Headers relay bridge. pub enum RelayHeadersBridge { diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index 1456dddf11e23..dc1c5ad362f42 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -33,7 +33,7 @@ use relay_substrate_client::Parachain; use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; use std::sync::Arc; use structopt::StructOpt; -use strum::{EnumString, EnumVariantNames, VariantNames}; +use strum::{EnumString, VariantNames}; use substrate_relay_helper::{ parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, TransactionParams, @@ -62,7 +62,7 @@ pub struct RelayParachains { } /// Parachain heads relay bridge. -#[derive(Debug, EnumString, EnumVariantNames)] +#[derive(Debug, EnumString, VariantNames)] #[strum(serialize_all = "kebab_case")] pub enum RelayParachainsBridge { KusamaToBridgeHubPolkadot, From aceb38886117956be85b5ed838a9176b85efd2d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 03:07:22 +0000 Subject: [PATCH 1176/1210] Bump tokio from 1.35.1 to 1.36.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.35.1 to 1.36.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.35.1...tokio-1.36.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index e2d641abcbaff..02187c5353ae1 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -18,7 +18,7 @@ log = "0.4.20" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } -tokio = { version = "1.35", features = ["rt-multi-thread"] } +tokio = { version = "1.36", features = ["rt-multi-thread"] } thiserror = "1.0.56" # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index d32423568254a..f68a3d2a3b213 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -23,7 +23,7 @@ num-traits = "0.2" serde_json = "1.0" sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.35", features = ["rt"] } +tokio = { version = "1.36", features = ["rt"] } thiserror = "1.0.56" # Bridge dependencies From 949360301cf5b27b8e2d5da716a5fd19debd90ee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Feb 2024 11:33:28 +0300 Subject: [PATCH 1177/1210] Add submit_finality_proof_ex call to the GRANDPA pallet (#2821) * depreacte submit_finality_proof and introduce submit_finality_proof_ex instead * propagate changes to the rest of runtime crates * tests for new call * suppress deprecation warning * revert changes to benchmarks to avoid unnecessary compilation issues when integrating to other repos --- .../src/refund_relayer_extension.rs | 268 +++++++++++++++++- modules/grandpa/README.md | 10 +- modules/grandpa/src/benchmarking.rs | 5 +- modules/grandpa/src/call_ext.rs | 115 +++++++- modules/grandpa/src/lib.rs | 218 +++++++++----- modules/parachains/src/lib.rs | 4 +- primitives/header-chain/src/lib.rs | 10 + 7 files changed, 533 insertions(+), 97 deletions(-) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 27b7ff1a5519b..bfcb82ad166c3 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -195,6 +195,19 @@ impl CallInfo { } } + /// Returns mutable reference to pre-dispatch `finality_target` sent to the + /// `SubmitFinalityProof` call. + #[cfg(test)] + fn submit_finality_proof_info_mut( + &mut self, + ) -> Option<&mut SubmitFinalityProofInfo> { + match *self { + Self::AllFinalityAndMsgs(ref mut info, _, _) => Some(info), + Self::RelayFinalityAndMsgs(ref mut info, _) => Some(info), + _ => None, + } + } + /// Returns the pre-dispatch `SubmitParachainHeadsInfo`. fn submit_parachain_heads_info(&self) -> Option<&SubmitParachainHeadsInfo> { match self { @@ -844,7 +857,7 @@ mod tests { use bp_parachains::{BestParaHeadHash, ParaInfo}; use bp_polkadot_core::parachains::{ParaHeadsProof, ParaId}; use bp_runtime::{BasicOperatingMode, HeaderId}; - use bp_test_utils::{make_default_justification, test_keyring}; + use bp_test_utils::{make_default_justification, test_keyring, TEST_GRANDPA_SET_ID}; use frame_support::{ assert_storage_noop, parameter_types, traits::{fungible::Mutate, ReservableCurrency}, @@ -929,7 +942,7 @@ mod tests { let authorities = test_keyring().into_iter().map(|(a, w)| (a.into(), w)).collect(); let best_relay_header = HeaderId(best_relay_header_number, RelayBlockHash::default()); pallet_bridge_grandpa::CurrentAuthoritySet::::put( - StoredAuthoritySet::try_new(authorities, 0).unwrap(), + StoredAuthoritySet::try_new(authorities, TEST_GRANDPA_SET_ID).unwrap(), ); pallet_bridge_grandpa::BestFinalized::::put(best_relay_header); @@ -977,6 +990,23 @@ mod tests { }) } + fn submit_relay_header_call_ex(relay_header_number: RelayBlockNumber) -> RuntimeCall { + let relay_header = BridgedChainHeader::new( + relay_header_number, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ); + let relay_justification = make_default_justification(&relay_header); + + RuntimeCall::BridgeGrandpa(GrandpaCall::submit_finality_proof_ex { + finality_target: Box::new(relay_header), + justification: relay_justification, + current_set_id: TEST_GRANDPA_SET_ID, + }) + } + fn submit_parachain_head_call( parachain_head_at_relay_header_number: RelayBlockNumber, ) -> RuntimeCall { @@ -1059,6 +1089,18 @@ mod tests { }) } + fn relay_finality_and_delivery_batch_call_ex( + relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call_ex(relay_header_number), + message_delivery_call(best_message), + ], + }) + } + fn relay_finality_and_confirmation_batch_call( relay_header_number: RelayBlockNumber, best_message: MessageNonce, @@ -1071,6 +1113,18 @@ mod tests { }) } + fn relay_finality_and_confirmation_batch_call_ex( + relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call_ex(relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_and_delivery_batch_call( relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, @@ -1085,6 +1139,20 @@ mod tests { }) } + fn all_finality_and_delivery_batch_call_ex( + relay_header_number: RelayBlockNumber, + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call_ex(relay_header_number), + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_delivery_call(best_message), + ], + }) + } + fn all_finality_and_confirmation_batch_call( relay_header_number: RelayBlockNumber, parachain_head_at_relay_header_number: RelayBlockNumber, @@ -1099,12 +1167,27 @@ mod tests { }) } + fn all_finality_and_confirmation_batch_call_ex( + relay_header_number: RelayBlockNumber, + parachain_head_at_relay_header_number: RelayBlockNumber, + best_message: MessageNonce, + ) -> RuntimeCall { + RuntimeCall::Utility(UtilityCall::batch_all { + calls: vec![ + submit_relay_header_call_ex(relay_header_number), + submit_parachain_head_call(parachain_head_at_relay_header_number), + message_confirmation_call(best_message), + ], + }) + } + fn all_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), call_info: CallInfo::AllFinalityAndMsgs( SubmitFinalityProofInfo { block_number: 200, + current_set_id: None, extra_weight: Weight::zero(), extra_size: 0, }, @@ -1128,12 +1211,20 @@ mod tests { } } + fn all_finality_pre_dispatch_data_ex() -> PreDispatchData { + let mut data = all_finality_pre_dispatch_data(); + data.call_info.submit_finality_proof_info_mut().unwrap().current_set_id = + Some(TEST_GRANDPA_SET_ID); + data + } + fn all_finality_confirmation_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), call_info: CallInfo::AllFinalityAndMsgs( SubmitFinalityProofInfo { block_number: 200, + current_set_id: None, extra_weight: Weight::zero(), extra_size: 0, }, @@ -1153,12 +1244,20 @@ mod tests { } } + fn all_finality_confirmation_pre_dispatch_data_ex() -> PreDispatchData { + let mut data = all_finality_confirmation_pre_dispatch_data(); + data.call_info.submit_finality_proof_info_mut().unwrap().current_set_id = + Some(TEST_GRANDPA_SET_ID); + data + } + fn relay_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), call_info: CallInfo::RelayFinalityAndMsgs( SubmitFinalityProofInfo { block_number: 200, + current_set_id: None, extra_weight: Weight::zero(), extra_size: 0, }, @@ -1177,12 +1276,20 @@ mod tests { } } + fn relay_finality_pre_dispatch_data_ex() -> PreDispatchData { + let mut data = relay_finality_pre_dispatch_data(); + data.call_info.submit_finality_proof_info_mut().unwrap().current_set_id = + Some(TEST_GRANDPA_SET_ID); + data + } + fn relay_finality_confirmation_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), call_info: CallInfo::RelayFinalityAndMsgs( SubmitFinalityProofInfo { block_number: 200, + current_set_id: None, extra_weight: Weight::zero(), extra_size: 0, }, @@ -1197,6 +1304,13 @@ mod tests { } } + fn relay_finality_confirmation_pre_dispatch_data_ex() -> PreDispatchData { + let mut data = relay_finality_confirmation_pre_dispatch_data(); + data.call_info.submit_finality_proof_info_mut().unwrap().current_set_id = + Some(TEST_GRANDPA_SET_ID); + data + } + fn parachain_finality_pre_dispatch_data() -> PreDispatchData { PreDispatchData { relayer: relayer_account_at_this_chain(), @@ -1393,6 +1507,10 @@ mod tests { run_validate(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(Default::default()), ); + assert_eq!( + run_validate(all_finality_and_delivery_batch_call_ex(200, 200, 200)), + Ok(Default::default()), + ); // message confirmation validation is passing assert_eq!( run_validate_ignore_priority(message_confirmation_call(200)), @@ -1410,6 +1528,12 @@ mod tests { )), Ok(Default::default()), ); + assert_eq!( + run_validate_ignore_priority(all_finality_and_confirmation_batch_call_ex( + 200, 200, 200 + )), + Ok(Default::default()), + ); }); } @@ -1500,12 +1624,24 @@ mod tests { run_validate_ignore_priority(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(ValidTransaction::default()), ); + assert_eq!( + run_validate_ignore_priority(all_finality_and_delivery_batch_call_ex( + 200, 200, 200 + )), + Ok(ValidTransaction::default()), + ); assert_eq!( run_validate_ignore_priority(all_finality_and_confirmation_batch_call( 200, 200, 200 )), Ok(ValidTransaction::default()), ); + assert_eq!( + run_validate_ignore_priority(all_finality_and_confirmation_batch_call_ex( + 200, 200, 200 + )), + Ok(ValidTransaction::default()), + ); }); } @@ -1518,11 +1654,19 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(100, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(100, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_validate(all_finality_and_delivery_batch_call(100, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(all_finality_and_delivery_batch_call_ex(100, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } @@ -1535,10 +1679,18 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(101, 100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(101, 100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_validate(all_finality_and_delivery_batch_call(101, 100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(all_finality_and_delivery_batch_call_ex(101, 100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_pre_dispatch(parachain_finality_and_delivery_batch_call(100, 200)), @@ -1560,19 +1712,35 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_validate(all_finality_and_delivery_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(all_finality_and_delivery_batch_call_ex(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_validate(all_finality_and_confirmation_batch_call(200, 200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_validate(all_finality_and_confirmation_batch_call_ex(200, 200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 100)), @@ -1609,10 +1777,18 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); assert_eq!( run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); }); } @@ -1631,10 +1807,18 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); assert_eq!( run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); assert_eq!( run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), @@ -1662,10 +1846,18 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); assert_eq!( run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Call)), + ); assert_eq!( run_pre_dispatch(parachain_finality_and_delivery_batch_call(200, 200)), @@ -1696,10 +1888,18 @@ mod tests { run_pre_dispatch(all_finality_and_delivery_batch_call(200, 200, 200)), Ok(Some(all_finality_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(all_finality_and_delivery_batch_call_ex(200, 200, 200)), + Ok(Some(all_finality_pre_dispatch_data_ex())), + ); assert_eq!( run_pre_dispatch(all_finality_and_confirmation_batch_call(200, 200, 200)), Ok(Some(all_finality_confirmation_pre_dispatch_data())), ); + assert_eq!( + run_pre_dispatch(all_finality_and_confirmation_batch_call_ex(200, 200, 200)), + Ok(Some(all_finality_confirmation_pre_dispatch_data_ex())), + ); }); } @@ -2126,6 +2326,12 @@ mod tests { ), Ok(None), ); + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &all_finality_and_delivery_batch_call_ex(200, 200, 200) + ), + Ok(None), + ); // relay + parachain + message confirmation calls batch is ignored assert_eq!( @@ -2134,6 +2340,12 @@ mod tests { ), Ok(None), ); + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &all_finality_and_confirmation_batch_call_ex(200, 200, 200) + ), + Ok(None), + ); // parachain + message delivery call batch is ignored assert_eq!( @@ -2158,6 +2370,12 @@ mod tests { ), Ok(Some(relay_finality_pre_dispatch_data().call_info)), ); + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &relay_finality_and_delivery_batch_call_ex(200, 200) + ), + Ok(Some(relay_finality_pre_dispatch_data_ex().call_info)), + ); // relay + message confirmation call batch is accepted assert_eq!( @@ -2166,6 +2384,12 @@ mod tests { ), Ok(Some(relay_finality_confirmation_pre_dispatch_data().call_info)), ); + assert_eq!( + TestGrandpaExtensionProvider::parse_and_check_for_obsolete_call( + &relay_finality_and_confirmation_batch_call_ex(200, 200) + ), + Ok(Some(relay_finality_confirmation_pre_dispatch_data_ex().call_info)), + ); // message delivery call batch is accepted assert_eq!( @@ -2194,11 +2418,19 @@ mod tests { run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_grandpa_validate(relay_finality_and_delivery_batch_call(100, 200)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(100, 200)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); }); } @@ -2211,19 +2443,35 @@ mod tests { run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call_ex(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 100)), Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), ); + assert_eq!( + run_grandpa_validate(relay_finality_and_confirmation_batch_call_ex(200, 100)), + Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)), + ); assert_eq!( run_grandpa_pre_dispatch(message_delivery_call(100)), @@ -2254,19 +2502,35 @@ mod tests { run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call(200, 200)), Ok(Some(relay_finality_pre_dispatch_data()),) ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_delivery_batch_call_ex(200, 200)), + Ok(Some(relay_finality_pre_dispatch_data_ex()),) + ); assert_eq!( run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call(200, 200)), Ok(Some(relay_finality_confirmation_pre_dispatch_data())), ); + assert_eq!( + run_grandpa_pre_dispatch(relay_finality_and_confirmation_batch_call_ex(200, 200)), + Ok(Some(relay_finality_confirmation_pre_dispatch_data_ex())), + ); assert_eq!( run_grandpa_validate(relay_finality_and_delivery_batch_call(200, 200)), Ok(Default::default()), ); + assert_eq!( + run_grandpa_validate(relay_finality_and_delivery_batch_call_ex(200, 200)), + Ok(Default::default()), + ); assert_eq!( run_grandpa_validate(relay_finality_and_confirmation_batch_call(200, 200)), Ok(Default::default()), ); + assert_eq!( + run_grandpa_validate(relay_finality_and_confirmation_batch_call_ex(200, 200)), + Ok(Default::default()), + ); assert_eq!( run_grandpa_pre_dispatch(message_delivery_call(200)), diff --git a/modules/grandpa/README.md b/modules/grandpa/README.md index 27b4d2389c408..43ee5c316d1b7 100644 --- a/modules/grandpa/README.md +++ b/modules/grandpa/README.md @@ -38,11 +38,11 @@ There are two main things in GRANDPA that help building light clients: ## Pallet Operations -The main entrypoint of the pallet is the `submit_finality_proof` call. It has two arguments - the finalized -headers and associated GRANDPA justification. The call simply verifies the justification using current -validators set and checks if header is better than the previous best header. If both checks are passed, the -header (only its useful fields) is inserted into the runtime storage and may be used by other pallets to verify -storage proofs. +The main entrypoint of the pallet is the `submit_finality_proof_ex` call. It has three arguments - the finalized +headers, associated GRANDPA justification and ID of the authority set that has generated this justification. The +call simply verifies the justification using current validators set and checks if header is better than the +previous best header. If both checks are passed, the header (only its useful fields) is inserted into the runtime +storage and may be used by other pallets to verify storage proofs. The submitter pays regular fee for submitting all headers, except for the mandatory header. Since it is required for the pallet operations, submitting such header is free. So if you're ok with session-length diff --git a/modules/grandpa/src/benchmarking.rs b/modules/grandpa/src/benchmarking.rs index 182b2f56eb1c5..11033373ce478 100644 --- a/modules/grandpa/src/benchmarking.rs +++ b/modules/grandpa/src/benchmarking.rs @@ -16,8 +16,9 @@ //! Benchmarks for the GRANDPA Pallet. //! -//! The main dispatchable for the GRANDPA pallet is `submit_finality_proof`, so these benchmarks are -//! based around that. There are to main factors which affect finality proof verification: +//! The main dispatchable for the GRANDPA pallet is `submit_finality_proof_ex`. Our benchmarks +//! are based around `submit_finality_proof`, though - from weight PoV they are the same calls. +//! There are to main factors which affect finality proof verification: //! //! 1. The number of `votes-ancestries` in the justification //! 2. The number of `pre-commits` in the justification diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index c1585020be13c..e3c778b480baa 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -14,7 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, Error, Pallet}; +use crate::{ + weights::WeightInfo, BridgedBlockNumber, BridgedHeader, Config, CurrentAuthoritySet, Error, + Pallet, +}; use bp_header_chain::{ justification::GrandpaJustification, max_expected_submit_finality_proof_arguments_size, ChainWithGrandpa, GrandpaConsensusLogReader, @@ -22,6 +25,7 @@ use bp_header_chain::{ use bp_runtime::{BlockNumberOf, OwnedBridgeModule}; use codec::Encode; use frame_support::{dispatch::CallableCallFor, traits::IsSubType, weights::Weight}; +use sp_consensus_grandpa::SetId; use sp_runtime::{ traits::{Header, Zero}, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, @@ -33,6 +37,9 @@ use sp_runtime::{ pub struct SubmitFinalityProofInfo { /// Number of the finality target. pub block_number: N, + /// An identifier of the validators set that has signed the submitted justification. + /// It might be `None` if deprecated version of the `submit_finality_proof` is used. + pub current_set_id: Option, /// Extra weight that we assume is included in the call. /// /// We have some assumptions about headers and justifications of the bridged chain. @@ -61,9 +68,11 @@ pub struct SubmitFinalityProofHelper, I: 'static> { impl, I: 'static> SubmitFinalityProofHelper { /// Check that the GRANDPA head provided by the `SubmitFinalityProof` is better than the best - /// one we know. + /// one we know. Additionally, checks if `current_set_id` matches the current authority set + /// id, if specified. pub fn check_obsolete( finality_target: BlockNumberOf, + current_set_id: Option, ) -> Result<(), Error> { let best_finalized = crate::BestFinalized::::get().ok_or_else(|| { log::trace!( @@ -85,6 +94,20 @@ impl, I: 'static> SubmitFinalityProofHelper { return Err(Error::::OldHeader) } + if let Some(current_set_id) = current_set_id { + let actual_set_id = >::get().set_id; + if current_set_id != actual_set_id { + log::trace!( + target: crate::LOG_TARGET, + "Cannot finalize header signed by unknown authority set: bundled {:?}, best {:?}", + current_set_id, + actual_set_id, + ); + + return Err(Error::::InvalidAuthoritySetId) + } + } + Ok(()) } @@ -111,6 +134,18 @@ pub trait CallSubType, I: 'static>: return Some(submit_finality_proof_info_from_args::( finality_target, justification, + None, + )) + } else if let Some(crate::Call::::submit_finality_proof_ex { + finality_target, + justification, + current_set_id, + }) = self.is_sub_type() + { + return Some(submit_finality_proof_info_from_args::( + finality_target, + justification, + Some(*current_set_id), )) } @@ -133,7 +168,10 @@ pub trait CallSubType, I: 'static>: return InvalidTransaction::Call.into() } - match SubmitFinalityProofHelper::::check_obsolete(finality_target.block_number) { + match SubmitFinalityProofHelper::::check_obsolete( + finality_target.block_number, + finality_target.current_set_id, + ) { Ok(_) => Ok(ValidTransaction::default()), Err(Error::::OldHeader) => InvalidTransaction::Stale.into(), Err(_) => InvalidTransaction::Call.into(), @@ -150,6 +188,7 @@ impl, I: 'static> CallSubType for T::RuntimeCall where pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( finality_target: &BridgedHeader, justification: &GrandpaJustification>, + current_set_id: Option, ) -> SubmitFinalityProofInfo> { let block_number = *finality_target.number(); @@ -191,7 +230,7 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( ); let extra_size = actual_call_size.saturating_sub(max_expected_call_size); - SubmitFinalityProofInfo { block_number, extra_weight, extra_size } + SubmitFinalityProofInfo { block_number, current_set_id, extra_weight, extra_size } } #[cfg(test)] @@ -199,20 +238,24 @@ mod tests { use crate::{ call_ext::CallSubType, mock::{run_test, test_header, RuntimeCall, TestBridgedChain, TestNumber, TestRuntime}, - BestFinalized, Config, PalletOperatingMode, WeightInfo, + BestFinalized, Config, CurrentAuthoritySet, PalletOperatingMode, StoredAuthoritySet, + SubmitFinalityProofInfo, WeightInfo, }; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{BasicOperatingMode, HeaderId}; use bp_test_utils::{ make_default_justification, make_justification_for_header, JustificationGeneratorParams, + TEST_GRANDPA_SET_ID, }; use frame_support::weights::Weight; use sp_runtime::{testing::DigestItem, traits::Header as _, SaturatedConversion}; fn validate_block_submit(num: TestNumber) -> bool { - let bridge_grandpa_call = crate::Call::::submit_finality_proof { + let bridge_grandpa_call = crate::Call::::submit_finality_proof_ex { finality_target: Box::new(test_header(num)), justification: make_default_justification(&test_header(num)), + // not initialized => zero + current_set_id: 0, }; RuntimeCall::check_obsolete_submit_finality_proof(&RuntimeCall::Grandpa( bridge_grandpa_call, @@ -256,6 +299,18 @@ mod tests { }); } + #[test] + fn extension_rejects_new_header_if_set_id_is_invalid() { + run_test(|| { + // when set id is different from the passed one => tx is rejected + sync_to_header_10(); + let next_set = StoredAuthoritySet::::try_new(vec![], 0x42).unwrap(); + CurrentAuthoritySet::::put(next_set); + + assert!(!validate_block_submit(15)); + }); + } + #[test] fn extension_accepts_new_header() { run_test(|| { @@ -266,6 +321,42 @@ mod tests { }); } + #[test] + fn submit_finality_proof_info_is_parsed() { + // when `submit_finality_proof` is used, `current_set_id` is set to `None` + let deprecated_call = + RuntimeCall::Grandpa(crate::Call::::submit_finality_proof { + finality_target: Box::new(test_header(42)), + justification: make_default_justification(&test_header(42)), + }); + assert_eq!( + deprecated_call.submit_finality_proof_info(), + Some(SubmitFinalityProofInfo { + block_number: 42, + current_set_id: None, + extra_weight: Weight::zero(), + extra_size: 0, + }) + ); + + // when `submit_finality_proof_ex` is used, `current_set_id` is set to `Some` + let deprecated_call = + RuntimeCall::Grandpa(crate::Call::::submit_finality_proof_ex { + finality_target: Box::new(test_header(42)), + justification: make_default_justification(&test_header(42)), + current_set_id: 777, + }); + assert_eq!( + deprecated_call.submit_finality_proof_info(), + Some(SubmitFinalityProofInfo { + block_number: 42, + current_set_id: Some(777), + extra_weight: Weight::zero(), + extra_size: 0, + }) + ); + } + #[test] fn extension_returns_correct_extra_size_if_call_arguments_are_too_large() { // when call arguments are below our limit => no refund @@ -275,9 +366,10 @@ mod tests { ..Default::default() }; let small_justification = make_justification_for_header(justification_params); - let small_call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + let small_call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof_ex { finality_target: Box::new(small_finality_target), justification: small_justification, + current_set_id: TEST_GRANDPA_SET_ID, }); assert_eq!(small_call.submit_finality_proof_info().unwrap().extra_size, 0); @@ -291,9 +383,10 @@ mod tests { ..Default::default() }; let large_justification = make_justification_for_header(justification_params); - let large_call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + let large_call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof_ex { finality_target: Box::new(large_finality_target), justification: large_justification, + current_set_id: TEST_GRANDPA_SET_ID, }); assert_ne!(large_call.submit_finality_proof_info().unwrap().extra_size, 0); } @@ -309,9 +402,10 @@ mod tests { // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY` headers => no refund let justification = make_justification_for_header(justification_params.clone()); - let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof_ex { finality_target: Box::new(finality_target.clone()), justification, + current_set_id: TEST_GRANDPA_SET_ID, }); assert_eq!(call.submit_finality_proof_info().unwrap().extra_weight, Weight::zero()); @@ -322,9 +416,10 @@ mod tests { justification.commit.precommits.len().saturated_into(), justification.votes_ancestries.len().saturated_into(), ); - let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof { + let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof_ex { finality_target: Box::new(finality_target), justification, + current_set_id: TEST_GRANDPA_SET_ID, }); assert_eq!(call.submit_finality_proof_info().unwrap().extra_weight, call_weight); } diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index f58db2481ada1..ce2c47da954fa 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -151,7 +151,86 @@ pub mod pallet { #[pallet::call] impl, I: 'static> Pallet { - /// Verify a target header is finalized according to the given finality proof. + /// This call is deprecated and will be removed around May 2024. Use the + /// `submit_finality_proof_ex` instead. Semantically, this call is an equivalent of the + /// `submit_finality_proof_ex` call without current authority set id check. + #[pallet::call_index(0)] + #[pallet::weight(::submit_finality_proof( + justification.commit.precommits.len().saturated_into(), + justification.votes_ancestries.len().saturated_into(), + ))] + #[allow(deprecated)] + #[deprecated( + note = "`submit_finality_proof` will be removed in May 2024. Use `submit_finality_proof_ex` instead." + )] + pub fn submit_finality_proof( + origin: OriginFor, + finality_target: Box>, + justification: GrandpaJustification>, + ) -> DispatchResultWithPostInfo { + Self::submit_finality_proof_ex( + origin, + finality_target, + justification, + // the `submit_finality_proof_ex` also reads this value, but it is done from the + // cache, so we don't treat it as an additional db access + >::get().set_id, + ) + } + + /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. + /// + /// The initial configuration provided does not need to be the genesis header of the bridged + /// chain, it can be any arbitrary header. You can also provide the next scheduled set + /// change if it is already know. + /// + /// This function is only allowed to be called from a trusted origin and writes to storage + /// with practically no checks in terms of the validity of the data. It is important that + /// you ensure that valid data is being passed in. + #[pallet::call_index(1)] + #[pallet::weight((T::DbWeight::get().reads_writes(2, 5), DispatchClass::Operational))] + pub fn initialize( + origin: OriginFor, + init_data: super::InitializationData>, + ) -> DispatchResultWithPostInfo { + Self::ensure_owner_or_root(origin)?; + + let init_allowed = !>::exists(); + ensure!(init_allowed, >::AlreadyInitialized); + initialize_bridge::(init_data.clone())?; + + log::info!( + target: LOG_TARGET, + "Pallet has been initialized with the following parameters: {:?}", + init_data + ); + + Ok(().into()) + } + + /// Change `PalletOwner`. + /// + /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(2)] + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { + >::set_owner(origin, new_owner) + } + + /// Halt or resume all pallet operations. + /// + /// May only be called either by root, or by `PalletOwner`. + #[pallet::call_index(3)] + #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] + pub fn set_operating_mode( + origin: OriginFor, + operating_mode: BasicOperatingMode, + ) -> DispatchResult { + >::set_operating_mode(origin, operating_mode) + } + + /// Verify a target header is finalized according to the given finality proof. The proof + /// is assumed to be signed by GRANDPA authorities set with `current_set_id` id. /// /// It will use the underlying storage pallet to fetch information about the current /// authorities and best finalized header in order to verify that the header is finalized. @@ -165,18 +244,22 @@ pub mod pallet { /// /// - the pallet knows better header than the `finality_target`; /// + /// - the id of best GRANDPA authority set, known to the pallet is not equal to the + /// `current_set_id`; + /// /// - verification is not optimized or invalid; /// /// - header contains forced authorities set change or change with non-zero delay. - #[pallet::call_index(0)] + #[pallet::call_index(4)] #[pallet::weight(::submit_finality_proof( justification.commit.precommits.len().saturated_into(), justification.votes_ancestries.len().saturated_into(), ))] - pub fn submit_finality_proof( + pub fn submit_finality_proof_ex( origin: OriginFor, finality_target: Box>, justification: GrandpaJustification>, + current_set_id: sp_consensus_grandpa::SetId, ) -> DispatchResultWithPostInfo { Self::ensure_not_halted().map_err(Error::::BridgeModule)?; ensure_signed(origin)?; @@ -188,7 +271,9 @@ pub mod pallet { finality_target ); - SubmitFinalityProofHelper::::check_obsolete(number)?; + // it checks whether the `number` is better than the current best block number + // and whether the `current_set_id` matches the best known set id + SubmitFinalityProofHelper::::check_obsolete(number, Some(current_set_id))?; let authority_set = >::get(); let unused_proof_size = authority_set.unused_proof_size(); @@ -202,7 +287,7 @@ pub mod pallet { // if we have seen too many mandatory headers in this block, we don't want to refund Self::free_mandatory_headers_remaining() > 0 && // if arguments out of expected bounds, we don't want to refund - submit_finality_proof_info_from_args::(&finality_target, &justification) + submit_finality_proof_info_from_args::(&finality_target, &justification, Some(current_set_id)) .fits_limits(); if may_refund_call_fee { FreeMandatoryHeadersRemaining::::mutate(|count| { @@ -248,57 +333,6 @@ pub mod pallet { Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } - - /// Bootstrap the bridge pallet with an initial header and authority set from which to sync. - /// - /// The initial configuration provided does not need to be the genesis header of the bridged - /// chain, it can be any arbitrary header. You can also provide the next scheduled set - /// change if it is already know. - /// - /// This function is only allowed to be called from a trusted origin and writes to storage - /// with practically no checks in terms of the validity of the data. It is important that - /// you ensure that valid data is being passed in. - #[pallet::call_index(1)] - #[pallet::weight((T::DbWeight::get().reads_writes(2, 5), DispatchClass::Operational))] - pub fn initialize( - origin: OriginFor, - init_data: super::InitializationData>, - ) -> DispatchResultWithPostInfo { - Self::ensure_owner_or_root(origin)?; - - let init_allowed = !>::exists(); - ensure!(init_allowed, >::AlreadyInitialized); - initialize_bridge::(init_data.clone())?; - - log::info!( - target: LOG_TARGET, - "Pallet has been initialized with the following parameters: {:?}", - init_data - ); - - Ok(().into()) - } - - /// Change `PalletOwner`. - /// - /// May only be called either by root, or by `PalletOwner`. - #[pallet::call_index(2)] - #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_owner(origin: OriginFor, new_owner: Option) -> DispatchResult { - >::set_owner(origin, new_owner) - } - - /// Halt or resume all pallet operations. - /// - /// May only be called either by root, or by `PalletOwner`. - #[pallet::call_index(3)] - #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operating_mode( - origin: OriginFor, - operating_mode: BasicOperatingMode, - ) -> DispatchResult { - >::set_operating_mode(origin, operating_mode) - } } /// Number mandatory headers that we may accept in the current block for free (returning @@ -436,6 +470,9 @@ pub mod pallet { TooManyAuthoritiesInSet, /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), + /// The `current_set_id` argument of the `submit_finality_proof_ex` doesn't match + /// the id of the current set, known to the pallet. + InvalidAuthoritySetId, } /// Check the given header for a GRANDPA scheduled authority set change. If a change @@ -663,6 +700,7 @@ mod tests { use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, make_justification_for_header, JustificationGeneratorParams, ALICE, BOB, + TEST_GRANDPA_SET_ID, }; use codec::Encode; use frame_support::{ @@ -693,7 +731,7 @@ mod tests { let init_data = InitializationData { header: Box::new(genesis), authority_list: authority_list(), - set_id: 1, + set_id: TEST_GRANDPA_SET_ID, operating_mode: BasicOperatingMode::Normal, }; @@ -704,10 +742,11 @@ mod tests { let header = test_header(header.into()); let justification = make_default_justification(&header); - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification, + TEST_GRANDPA_SET_ID, ) } @@ -722,10 +761,11 @@ mod tests { ..Default::default() }); - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification, + set_id, ) } @@ -749,10 +789,11 @@ mod tests { ..Default::default() }); - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification, + set_id, ) } @@ -955,17 +996,30 @@ mod tests { let header = test_header(1); - let params = - JustificationGeneratorParams:: { set_id: 2, ..Default::default() }; + let next_set_id = 2; + let params = JustificationGeneratorParams:: { + set_id: next_set_id, + ..Default::default() + }; let justification = make_justification_for_header(params); assert_err!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( + RuntimeOrigin::signed(1), + Box::new(header.clone()), + justification.clone(), + TEST_GRANDPA_SET_ID, + ), + >::InvalidJustification + ); + assert_err!( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification, + next_set_id, ), - >::InvalidJustification + >::InvalidAuthoritySetId ); }) } @@ -980,10 +1034,11 @@ mod tests { justification.round = 42; assert_err!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification, + TEST_GRANDPA_SET_ID, ), >::InvalidJustification ); @@ -1009,10 +1064,11 @@ mod tests { let justification = make_default_justification(&header); assert_err!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification, + TEST_GRANDPA_SET_ID, ), >::InvalidAuthoritySet ); @@ -1047,10 +1103,11 @@ mod tests { let justification = make_default_justification(&header); // Let's import our test header - let result = Pallet::::submit_finality_proof( + let result = Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header.clone()), justification.clone(), + TEST_GRANDPA_SET_ID, ); assert_ok!(result); assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::No); @@ -1109,10 +1166,11 @@ mod tests { // without large digest item ^^^ the relayer would have paid zero transaction fee // (`Pays::No`) - let result = Pallet::::submit_finality_proof( + let result = Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header.clone()), justification, + TEST_GRANDPA_SET_ID, ); assert_ok!(result); assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes); @@ -1140,10 +1198,11 @@ mod tests { // without many headers in votes ancestries ^^^ the relayer would have paid zero // transaction fee (`Pays::No`) - let result = Pallet::::submit_finality_proof( + let result = Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header.clone()), justification, + TEST_GRANDPA_SET_ID, ); assert_ok!(result); assert_eq!(result.unwrap().pays_fee, frame_support::dispatch::Pays::Yes); @@ -1169,10 +1228,11 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), - justification + justification, + TEST_GRANDPA_SET_ID, ), >::UnsupportedScheduledChange ); @@ -1194,10 +1254,11 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), - justification + justification, + TEST_GRANDPA_SET_ID, ), >::UnsupportedScheduledChange ); @@ -1219,10 +1280,11 @@ mod tests { // Should not be allowed to import this header assert_err!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), - justification + justification, + TEST_GRANDPA_SET_ID, ), >::TooManyAuthoritiesInSet ); @@ -1283,10 +1345,11 @@ mod tests { let mut invalid_justification = make_default_justification(&header); invalid_justification.round = 42; - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), invalid_justification, + TEST_GRANDPA_SET_ID, ) }; @@ -1451,10 +1514,11 @@ mod tests { let justification = make_default_justification(&header); assert_noop!( - Pallet::::submit_finality_proof( + Pallet::::submit_finality_proof_ex( RuntimeOrigin::root(), Box::new(header), justification, + TEST_GRANDPA_SET_ID, ), DispatchError::BadOrigin, ); diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 87c57e84622aa..1363a637604d1 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -731,6 +731,7 @@ pub(crate) mod tests { }; use bp_test_utils::{ authority_list, generate_owned_bridge_module_tests, make_default_justification, + TEST_GRANDPA_SET_ID, }; use frame_support::{ assert_noop, assert_ok, @@ -777,10 +778,11 @@ pub(crate) mod tests { let hash = header.hash(); let justification = make_default_justification(&header); assert_ok!( - pallet_bridge_grandpa::Pallet::::submit_finality_proof( + pallet_bridge_grandpa::Pallet::::submit_finality_proof_ex( RuntimeOrigin::signed(1), Box::new(header), justification.clone(), + TEST_GRANDPA_SET_ID, ) ); diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index f5485aca1ee8b..84a6a881a835b 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -244,6 +244,16 @@ pub enum BridgeGrandpaCall { /// All data, required to initialize the pallet. init_data: InitializationData
, }, + /// `pallet-bridge-grandpa::Call::submit_finality_proof_ex` + #[codec(index = 4)] + submit_finality_proof_ex { + /// The header that we are going to finalize. + finality_target: Box
, + /// Finality justification for the `finality_target`. + justification: justification::GrandpaJustification
, + /// An identifier of the validators set, that have signed the justification. + current_set_id: SetId, + }, } /// The `BridgeGrandpaCall` used by a chain. From 8e0c6d70d5bef3d2ebd1d33608e17320c453bed1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 6 Feb 2024 11:36:09 +0300 Subject: [PATCH 1178/1210] Pass finality proof verification context to the call builder (#2823) * pass verification context to the build_submit_finality_proof_call * current_set_id -> context --- relays/lib-substrate-relay/src/finality/mod.rs | 16 +++++++++++----- .../lib-substrate-relay/src/finality/target.rs | 10 ++++++---- .../src/finality_base/engine.rs | 14 +++++++++----- .../lib-substrate-relay/src/on_demand/headers.rs | 14 ++++++++++---- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index b8cf27ea78fde..ea7c4e0362b85 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -24,7 +24,7 @@ use crate::{ }; use async_trait::async_trait; -use bp_header_chain::justification::GrandpaJustification; +use bp_header_chain::justification::{GrandpaJustification, JustificationVerificationContext}; use finality_relay::{FinalityPipeline, FinalitySyncPipeline}; use pallet_bridge_grandpa::{Call as BridgeGrandpaCall, Config as BridgeGrandpaConfig}; use relay_substrate_client::{ @@ -110,11 +110,12 @@ impl FinalitySyncPipeline for FinalitySyncPipe /// Different ways of building `submit_finality_proof` calls. pub trait SubmitFinalityProofCallBuilder { - /// Given source chain header and its finality proofs, build call of `submit_finality_proof` - /// function of bridge GRANDPA module at the target chain. + /// Given source chain header, its finality proof and the current authority set id, build call + /// of `submit_finality_proof` function of bridge GRANDPA module at the target chain. fn build_submit_finality_proof_call( header: SyncHeader>, proof: SubstrateFinalityProof

, + context: <

::FinalityEngine as Engine>::FinalityVerificationContext, ) -> CallOf; } @@ -132,12 +133,16 @@ where I: 'static, R::BridgedChain: bp_runtime::Chain

>, CallOf: From>, - P::FinalityEngine: - Engine>>, + P::FinalityEngine: Engine< + P::SourceChain, + FinalityProof = GrandpaJustification>, + FinalityVerificationContext = JustificationVerificationContext, + >, { fn build_submit_finality_proof_call( header: SyncHeader>, proof: GrandpaJustification>, + _context: JustificationVerificationContext, ) -> CallOf { BridgeGrandpaCall::::submit_finality_proof { finality_target: Box::new(header.into_inner()), @@ -171,6 +176,7 @@ macro_rules! generate_submit_finality_proof_call_builder { <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain > >, + _context: bp_header_chain::justification::JustificationVerificationContext, ) -> relay_substrate_client::CallOf< <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::TargetChain > { diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/relays/lib-substrate-relay/src/finality/target.rs index 930f0360311c3..18464d523f4f6 100644 --- a/relays/lib-substrate-relay/src/finality/target.rs +++ b/relays/lib-substrate-relay/src/finality/target.rs @@ -108,13 +108,15 @@ impl TargetClient>, mut proof: SubstrateFinalityProof

, ) -> Result { - // runtime module at target chain may require optimized finality proof - P::FinalityEngine::optimize_proof(&self.client, &header, &mut proof).await?; + // verify and runtime module at target chain may require optimized finality proof + let context = + P::FinalityEngine::verify_and_optimize_proof(&self.client, &header, &mut proof).await?; // now we may submit optimized finality proof let mortality = self.transaction_params.mortality; - let call = - P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); + let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call( + header, proof, context, + ); self.client .submit_and_watch_signed_extrinsic( &self.transaction_params.signer, diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/relays/lib-substrate-relay/src/finality_base/engine.rs index 831c1e7ad5b50..e517b0fd9b9ab 100644 --- a/relays/lib-substrate-relay/src/finality_base/engine.rs +++ b/relays/lib-substrate-relay/src/finality_base/engine.rs @@ -118,12 +118,15 @@ pub trait Engine: Send { source_client.subscribe_finality_justifications::().await } - /// Optimize finality proof before sending it to the target node. - async fn optimize_proof( + /// Verify and optimize finality proof before sending it to the target node. + /// + /// Apart from optimization, we expect this method to perform all required checks + /// that the `header` and `proof` are valid at the current state of the target chain. + async fn verify_and_optimize_proof( target_client: &Client, header: &C::Header, proof: &mut Self::FinalityProof, - ) -> Result<(), SubstrateError>; + ) -> Result; /// Checks whether the given `header` and its finality `proof` fit the maximal expected /// call size limit. If result is `MaxExpectedCallSizeCheck::Exceeds { .. }`, this @@ -212,11 +215,11 @@ impl Engine for Grandpa { bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) } - async fn optimize_proof( + async fn verify_and_optimize_proof( target_client: &Client, header: &C::Header, proof: &mut Self::FinalityProof, - ) -> Result<(), SubstrateError> { + ) -> Result { let verification_context = Grandpa::::finality_verification_context( target_client, target_client.best_header().await?.hash(), @@ -231,6 +234,7 @@ impl Engine for Grandpa { &verification_context, proof, ) + .map(|_| verification_context) .map_err(|e| { SubstrateError::Custom(format!( "Failed to optimize {} GRANDPA jutification for header {:?}: {:?}", diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 0090dee3a03c8..8b58552d292c4 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -146,8 +146,13 @@ impl OnDemandRelay OnDemandRelay Date: Tue, 6 Feb 2024 13:17:28 +0300 Subject: [PATCH 1179/1210] Backport latest PRs from polkadot sdk (#2824) * backport https://github.com/paritytech/polkadot-sdk/pull/3034 * backport https://github.com/paritytech/polkadot-sdk/pull/3072 * backport https://github.com/paritytech/polkadot-sdk/pull/3175 * backport https://github.com/paritytech/polkadot-sdk/pull/2949 * Cargo.lock * fix invalid copypaste --- bin/runtime-common/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- modules/xcm-bridge-hub/Cargo.toml | 2 +- primitives/chain-asset-hub-rococo/Cargo.toml | 2 +- primitives/chain-asset-hub-westend/Cargo.toml | 2 +- .../chain-bridge-hub-cumulus/Cargo.toml | 2 +- .../chain-bridge-hub-cumulus/src/lib.rs | 26 +++++++++++++++++++ primitives/chain-bridge-hub-kusama/Cargo.toml | 2 +- .../chain-bridge-hub-polkadot/Cargo.toml | 2 +- primitives/chain-bridge-hub-rococo/Cargo.toml | 2 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 6 ++--- .../chain-bridge-hub-westend/Cargo.toml | 2 +- .../chain-bridge-hub-westend/src/lib.rs | 4 +-- primitives/chain-kusama/Cargo.toml | 2 +- primitives/chain-polkadot-bulletin/Cargo.toml | 2 +- primitives/chain-polkadot/Cargo.toml | 2 +- primitives/chain-rococo/Cargo.toml | 2 +- primitives/chain-westend/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/test-utils/Cargo.toml | 2 +- primitives/xcm-bridge-hub-router/Cargo.toml | 2 +- primitives/xcm-bridge-hub/Cargo.toml | 2 +- 31 files changed, 59 insertions(+), 33 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index b642f738d6e80..88bd3422d0e76 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bridge-runtime-common" -version = "0.1.0" +version = "0.7.0" description = "Common types and functions that may be used by substrate-based runtimes of all bridged chains" authors.workspace = true edition.workspace = true diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index e7e8c5c6fe747..b1480c7024635 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-bridge-grandpa" -version = "0.1.0" +version = "0.7.0" description = "Module implementing GRANDPA on-chain light client used for bridging consensus of substrate-based chains." authors.workspace = true edition.workspace = true diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 01dd3dbcbde76..9d7a1e3b9d397 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-bridge-messages" description = "Module that allows bridged chains to exchange messages using lane concept." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 239f5262c8bb2..d44b434bff7fa 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-bridge-parachains" -version = "0.1.0" +version = "0.7.0" description = "Module that allows bridged relay chains to exchange information on their parachains' heads." authors.workspace = true edition.workspace = true diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 73cc343a193e8..b0c32f4c7df65 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-bridge-relayers" description = "Module used to store relayer rewards and coordinate relayers set." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 6d3e1c5ab454e..56e9ae8f08ca5 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-xcm-bridge-hub-router" description = "Bridge hub interface for sibling/parent chains with dynamic fees support." -version = "0.1.0" +version = "0.5.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 4dac474413afc..86644f8e4c961 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-xcm-bridge-hub" description = "Module that adds dynamic bridges/lanes support to XCM infrastucture at the bridge hub." -version = "0.1.0" +version = "0.2.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/primitives/chain-asset-hub-rococo/Cargo.toml index c4da8ee0eafcd..ad0eb39f9e3ae 100644 --- a/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/primitives/chain-asset-hub-rococo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-asset-hub-rococo" description = "Primitives of AssetHubRococo parachain runtime." -version = "0.1.0" +version = "0.4.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-asset-hub-westend/Cargo.toml b/primitives/chain-asset-hub-westend/Cargo.toml index a148cf31ca778..15b17f4d02d4d 100644 --- a/primitives/chain-asset-hub-westend/Cargo.toml +++ b/primitives/chain-asset-hub-westend/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-asset-hub-westend" description = "Primitives of AssetHubWestend parachain runtime." -version = "0.1.0" +version = "0.3.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index 08f561b4f5cbf..82c87d8bc13e3 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-bridge-hub-cumulus" description = "Primitives for BridgeHub parachain runtimes." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index 285f00204810b..c49aa4b856397 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -57,6 +57,12 @@ const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(constants::WEIGHT_REF_TI .saturating_div(2) .set_proof_size(polkadot_primitives::MAX_POV_SIZE as u64); +/// We allow for 2 seconds of compute with a 6 second average block. +const MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING: Weight = Weight::from_parts( + constants::WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), + polkadot_primitives::MAX_POV_SIZE as u64, +); + /// All cumulus bridge hubs assume that about 5 percent of the block weight is consumed by /// `on_initialize` handlers. This is used to limit the maximal weight of a single extrinsic. /// @@ -96,6 +102,26 @@ parameter_types! { }) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); + + /// Weight limit of the Cumulus-based bridge hub blocks when async backing is enabled. + pub BlockWeightsForAsyncBacking: limits::BlockWeights = limits::BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING); + // Operational transactions have an extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT_FOR_ASYNC_BACKING, + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); } /// Public key of the chain account that may be used to verify signatures. diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/primitives/chain-bridge-hub-kusama/Cargo.toml index 4e1b3a6334c8e..2075fe2543c67 100644 --- a/primitives/chain-bridge-hub-kusama/Cargo.toml +++ b/primitives/chain-bridge-hub-kusama/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-bridge-hub-kusama" description = "Primitives of BridgeHubKusama parachain runtime." -version = "0.1.0" +version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/primitives/chain-bridge-hub-polkadot/Cargo.toml index 2f53cca46a8af..edef6e612372f 100644 --- a/primitives/chain-bridge-hub-polkadot/Cargo.toml +++ b/primitives/chain-bridge-hub-polkadot/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-bridge-hub-polkadot" description = "Primitives of BridgeHubPolkadot parachain runtime." -version = "0.1.0" +version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/primitives/chain-bridge-hub-rococo/Cargo.toml index e4bbc1a08987e..0370fa1c6bb2c 100644 --- a/primitives/chain-bridge-hub-rococo/Cargo.toml +++ b/primitives/chain-bridge-hub-rococo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-bridge-hub-rococo" description = "Primitives of BridgeHubRococo parachain runtime." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 7b109f30fe0b9..c4e697fbe9526 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -50,7 +50,7 @@ impl Chain for BridgeHubRococo { } fn max_extrinsic_weight() -> Weight { - BlockWeights::get() + BlockWeightsForAsyncBacking::get() .get(DispatchClass::Normal) .max_extrinsic .unwrap_or(Weight::MAX) @@ -99,7 +99,7 @@ frame_support::parameter_types! { /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Rococo /// BridgeHub. /// (initially was calculated by test `BridgeHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubRococoBaseXcmFeeInRocs: u128 = 1_640_102_205; + pub const BridgeHubRococoBaseXcmFeeInRocs: u128 = 59_034_266; /// Transaction fee that is paid at the Rococo BridgeHub for delivering single inbound message. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) @@ -107,5 +107,5 @@ frame_support::parameter_types! { /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 4_045_736_577; + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_829_647; } diff --git a/primitives/chain-bridge-hub-westend/Cargo.toml b/primitives/chain-bridge-hub-westend/Cargo.toml index 333e49883f8bc..ea452d89dba54 100644 --- a/primitives/chain-bridge-hub-westend/Cargo.toml +++ b/primitives/chain-bridge-hub-westend/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-bridge-hub-westend" description = "Primitives of BridgeHubWestend parachain runtime." -version = "0.1.0" +version = "0.3.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-bridge-hub-westend/src/lib.rs b/primitives/chain-bridge-hub-westend/src/lib.rs index 83d4d6e33a759..4af895cc6d328 100644 --- a/primitives/chain-bridge-hub-westend/src/lib.rs +++ b/primitives/chain-bridge-hub-westend/src/lib.rs @@ -49,7 +49,7 @@ impl Chain for BridgeHubWestend { } fn max_extrinsic_weight() -> Weight { - BlockWeights::get() + BlockWeightsForAsyncBacking::get() .get(DispatchClass::Normal) .max_extrinsic .unwrap_or(Weight::MAX) @@ -90,7 +90,7 @@ frame_support::parameter_types! { /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Westend /// BridgeHub. /// (initially was calculated by test `BridgeHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) - pub const BridgeHubWestendBaseXcmFeeInWnds: u128 = 492_077_333_333; + pub const BridgeHubWestendBaseXcmFeeInWnds: u128 = 17_756_830_000; /// Transaction fee that is paid at the Westend BridgeHub for delivering single inbound message. /// (initially was calculated by test `BridgeHubWestend::can_calculate_fee_for_complex_message_delivery_transaction` + `33%`) diff --git a/primitives/chain-kusama/Cargo.toml b/primitives/chain-kusama/Cargo.toml index ed057098813ab..465acf121d408 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/primitives/chain-kusama/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-kusama" description = "Primitives of Kusama runtime." -version = "0.1.0" +version = "0.5.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index 3fe83b8cae7f6..86f05624d016d 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-polkadot-bulletin" description = "Primitives of Polkadot Bulletin chain runtime." -version = "0.1.0" +version = "0.4.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-polkadot/Cargo.toml b/primitives/chain-polkadot/Cargo.toml index 5180c34d932f6..20080a7901b69 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/primitives/chain-polkadot/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-polkadot" description = "Primitives of Polkadot runtime." -version = "0.1.0" +version = "0.5.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-rococo/Cargo.toml b/primitives/chain-rococo/Cargo.toml index 7d78b3ff51324..459ee6f9f0517 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/primitives/chain-rococo/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-rococo" description = "Primitives of Rococo runtime." -version = "0.1.0" +version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/chain-westend/Cargo.toml b/primitives/chain-westend/Cargo.toml index 23cfc8de9d744..4710da7bb335d 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/primitives/chain-westend/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-westend" description = "Primitives of Westend runtime." -version = "0.1.0" +version = "0.3.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 415b165101d9b..e42959164e4ca 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-header-chain" description = "A common interface for describing what a bridge pallet should be able to do." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 02388a30e74a9..1092be13d899e 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-messages" description = "Primitives of messages module." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 524b95e3b6fe6..e62ae6a8d423c 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-parachains" description = "Primitives of parachains module." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 7b8b92b62fc7d..5ef9920d7f196 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-polkadot-core" description = "Primitives of Polkadot-like runtime." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 5eedf738a4178..19aed6b038bcd 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-relayers" description = "Primitives of relayers module." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 0874926895827..211737e4efc7f 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-runtime" description = "Primitives that may be used at (bridges) runtime level." -version = "0.1.0" +version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 3c24e1fed0f98..1b3ac9ee697cb 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bp-test-utils" -version = "0.1.0" +version = "0.7.0" description = "Utilities for testing substrate-based runtime bridge code" authors.workspace = true edition.workspace = true diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index 8000e48992cf6..a9f584e2a0316 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-xcm-bridge-hub-router" description = "Primitives of the xcm-bridge-hub fee pallet." -version = "0.1.0" +version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" diff --git a/primitives/xcm-bridge-hub/Cargo.toml b/primitives/xcm-bridge-hub/Cargo.toml index b2dc09bdf8c8a..1a5bb742eed47 100644 --- a/primitives/xcm-bridge-hub/Cargo.toml +++ b/primitives/xcm-bridge-hub/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bp-xcm-bridge-hub" description = "Primitives of the xcm-bridge-hub pallet." -version = "0.1.0" +version = "0.2.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" From 77a5db721b9d587af9de2edf8ff0fc37502bf1df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 03:00:12 +0000 Subject: [PATCH 1180/1210] Bump tempfile from 3.9.0 to 3.10.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.9.0 to 3.10.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.9.0...v3.10.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index b284cda17884b..f87c24fa77d55 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -62,5 +62,5 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas bp-test-utils = { path = "../../primitives/test-utils" } hex-literal = "0.4" sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -tempfile = "3.9" +tempfile = "3.10" finality-grandpa = { version = "0.16.2" } From 0d99ac17a5dd0c0ead995541f612472929a82d45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 03:00:39 +0000 Subject: [PATCH 1181/1210] Bump thiserror from 1.0.56 to 1.0.57 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.56 to 1.0.57. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.56...1.0.57) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 02187c5353ae1..e72b5d6cb8cc2 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -19,7 +19,7 @@ num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.36", features = ["rt-multi-thread"] } -thiserror = "1.0.56" +thiserror = "1.0.57" # Bridge dependencies diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 732ee768393cd..fe74168d7bf28 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = "1.0.56" +thiserror = "1.0.57" async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index f68a3d2a3b213..ce106d3a51dd7 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -24,7 +24,7 @@ serde_json = "1.0" sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.36", features = ["rt"] } -thiserror = "1.0.56" +thiserror = "1.0.57" # Bridge dependencies From fd037fd75eadfe4d13dd2808055eba49748d1c98 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 16 Feb 2024 11:07:03 +0300 Subject: [PATCH 1182/1210] Fix relay submitting extra parachain headers during reorg (#2839) * fix on-demand parachain relay behavior during target chain reorgs * fix compilation --- .../src/parachains/source.rs | 7 ++- relays/parachains/src/parachains_loop.rs | 45 ++++++++++++++++--- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index ba59171c8e01a..32d70cf425f0b 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -120,10 +120,15 @@ where // `max_header_id` is not set. There is no limit. AvailableHeader::Available(on_chain_para_head_id) }, - AvailableHeader::Available(max_head_id) => { + AvailableHeader::Available(max_head_id) if on_chain_para_head_id >= max_head_id => { // We report at most `max_header_id`. AvailableHeader::Available(std::cmp::min(on_chain_para_head_id, max_head_id)) }, + AvailableHeader::Available(_) => { + // the `max_head_id` is not yet available at the source chain => wait and avoid + // syncing extra headers + AvailableHeader::Unavailable + }, } } diff --git a/relays/parachains/src/parachains_loop.rs b/relays/parachains/src/parachains_loop.rs index 390b02b859459..41ebbf5aadede 100644 --- a/relays/parachains/src/parachains_loop.rs +++ b/relays/parachains/src/parachains_loop.rs @@ -256,7 +256,12 @@ where let head_at_source = read_head_at_source(&source_client, metrics.as_ref(), &best_finalized_relay_block) .await?; - let is_update_required = is_update_required::

(head_at_source, head_at_target); + let is_update_required = is_update_required::

( + head_at_source, + head_at_target, + best_finalized_relay_block, + best_target_block, + ); if is_update_required { let (head_proof, head_hash) = source_client @@ -274,10 +279,12 @@ where })?; log::info!( target: "bridge", - "Submitting {} parachain ParaId({}) head update transaction to {}", + "Submitting {} parachain ParaId({}) head update transaction to {}. Para hash at source relay {:?}: {:?}", P::SourceRelayChain::NAME, P::SourceParachain::PARACHAIN_ID, P::TargetChain::NAME, + best_finalized_relay_block, + head_hash, ); let transaction_tracker = target_client @@ -304,6 +311,8 @@ where fn is_update_required( head_at_source: AvailableHeader>, head_at_target: Option>, + best_finalized_relay_block_at_source: HeaderIdOf, + best_target_block: HeaderIdOf, ) -> bool where P::SourceRelayChain: Chain, @@ -311,14 +320,16 @@ where log::trace!( target: "bridge", "Checking if {} parachain ParaId({}) needs update at {}:\n\t\ - At {}: {:?}\n\t\ - At {}: {:?}", + At {} ({:?}): {:?}\n\t\ + At {} ({:?}): {:?}", P::SourceRelayChain::NAME, P::SourceParachain::PARACHAIN_ID, P::TargetChain::NAME, P::SourceRelayChain::NAME, + best_finalized_relay_block_at_source, head_at_source, P::TargetChain::NAME, + best_target_block, head_at_target, ); @@ -908,16 +919,28 @@ mod tests { #[test] fn parachain_is_not_updated_if_it_is_unavailable() { - assert!(!is_update_required::(AvailableHeader::Unavailable, None)); assert!(!is_update_required::( AvailableHeader::Unavailable, - Some(HeaderId(10, PARA_10_HASH)) + None, + Default::default(), + Default::default(), + )); + assert!(!is_update_required::( + AvailableHeader::Unavailable, + Some(HeaderId(10, PARA_10_HASH)), + Default::default(), + Default::default(), )); } #[test] fn parachain_is_not_updated_if_it_is_unknown_to_both_clients() { - assert!(!is_update_required::(AvailableHeader::Missing, None),); + assert!(!is_update_required::( + AvailableHeader::Missing, + None, + Default::default(), + Default::default(), + ),); } #[test] @@ -925,6 +948,8 @@ mod tests { assert!(!is_update_required::( AvailableHeader::Available(HeaderId(10, Default::default())), Some(HeaderId(20, Default::default())), + Default::default(), + Default::default(), ),); } @@ -933,6 +958,8 @@ mod tests { assert!(is_update_required::( AvailableHeader::Missing, Some(HeaderId(20, Default::default())), + Default::default(), + Default::default(), ),); } @@ -941,6 +968,8 @@ mod tests { assert!(is_update_required::( AvailableHeader::Available(HeaderId(30, Default::default())), None, + Default::default(), + Default::default(), ),); } @@ -949,6 +978,8 @@ mod tests { assert!(is_update_required::( AvailableHeader::Available(HeaderId(40, Default::default())), Some(HeaderId(30, Default::default())), + Default::default(), + Default::default(), ),); } } From 6c9d453d4e5a523ef50e44728ee786e196d60901 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 02:45:47 +0000 Subject: [PATCH 1183/1210] Bump env_logger from 0.11.1 to 0.11.2 Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.1 to 0.11.2. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.1...v0.11.2) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ce106d3a51dd7..774586f3fc193 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -15,7 +15,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" isahc = "1.2" -env_logger = "0.11.1" +env_logger = "0.11.2" futures = "0.3.30" jsonpath_lib = "0.3" log = "0.4.20" From de934c718afe5e9ec30f03bd930be297b39060ee Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 27 Feb 2024 18:53:26 +0300 Subject: [PATCH 1184/1210] Running relayer: documentation (#2829) * running relayer documentation * fix review comments * also update tag * typo * Apply suggestions from code review --------- Co-authored-by: Adrian Catangiu --- docs/bridge-relayers-claim-rewards.png | Bin 0 -> 35621 bytes docs/bridge-relayers-deregister.png | Bin 0 -> 10115 bytes docs/bridge-relayers-register.png | Bin 0 -> 51026 bytes docs/running-relayer.md | 344 +++++++++++++++++++++++++ 4 files changed, 344 insertions(+) create mode 100644 docs/bridge-relayers-claim-rewards.png create mode 100644 docs/bridge-relayers-deregister.png create mode 100644 docs/bridge-relayers-register.png create mode 100644 docs/running-relayer.md diff --git a/docs/bridge-relayers-claim-rewards.png b/docs/bridge-relayers-claim-rewards.png new file mode 100644 index 0000000000000000000000000000000000000000..d56b8dd871e8445e7cab49517123b0092ce09137 GIT binary patch literal 35621 zcmb@tbzD^6+CB`TAd-U8ogzp|mjcqEfP}=*4MR7KG>Ej)r4l0D-JK)S-QC^HZ*jio zd5-7(=lSQ|A4F%|Ywxw!y5qX9``RII6{WBqkvu{|Lc)@fmQY4QLd`@%LdJcF3clgr z_1*%1-FFa^QGEyw&xc0A;4`t~8x2PlsEMPCzP&M$sSVWH_=SU^y|J;4gBjFu52aBA zoWyFbs^KVZZ>;ZV4z;0DHMcefUm_v>&K~roV&|h8^#5J{yM&69o%1CX2e$zGO96H+ zPqo{xNJvyjG7_&$Dn zWI4CLRG2cFT;{s@nwPNQIH@Ga+%MlSB!4BtS&ToVq<|lj9!N*`PAWuVyA2K2r^up;6KN zbwIpjWkdctr7KuPSytk&Lozv9`LFY7I2XTs!F&9lBkFN>#+Sb?5d4|XuY}Ou=P1Ej!?v~{($RhaYuOjiAtk>{@}>Ux8fY)T<-Y&k4W+iPDOu@ zxX}7DG$bx3hoNXn+q}f0o)S-@w!z~fsAkFTkV+JbqkVoFJcdtNqSW4r8ef zrNHK9;mPLuHVxJMCJ)Qs&jArZMn-mYbk;d>Zu}Y{oNG)yGDZ(z&CBDBwT0$5!l5V7ogznVFf!s*AXP-K9F3l$B}4zWO{4 zc0o8=2tia=3{6e-a>0dKRg{EJs_|r5<3b^b%dxui#n3cnijVnPm4~^In@^0XuD)Zs z9@brl;It==7yVEqGYgBwgHFn|LfFmLTKH0(rPF80)+uOXzv#`7=sOjaqlD4Ms4dq2 ztbx67%|f&?Ma0_o+1F|Bp-{H+^73SUhrodW#YY$z7duc`Z>q2dstzMFb13BYFm8Bc zMCS>7qSRE>MFXn&MIL81_V)H>R#t6BoE#pfRzegwZ{ECd_3$WlJupyKRz^Bs zqC`kLIBkd%w{>aG4cy4LU)mTj{iCoYj&7F7f#`9Q{AOS-Vx;CTIQMuZR|N6C^G0oE#xQ4^p0KKpKQ3IC5lctfafU02pXwVxp|2 zC8wc5Bp1g@&%@)a(Rl_YYGh>e_QQuyX=#*9OiV1=RgonnoVVwlqS5j3U6bXO6SXdE zg$oys0VUo#n6!NHQuW>m9B3CkuPThKFOfw6thc+taILD?Uj7 z_3M+%tXmNH_u$CL8)@l>p@eKE1IhexZKn%ClqC*pieQI>LqhaddcJC~5TtsYYRbyV zUDP&S32r+J!iA17fmK~^n~IVilNpJtf_&-*Q}tQ-K7JsLNRcuYdl zb9u6rlbhSR_9a-d?QnyB|M0I5+^0`xX2@glE*(_uj1Q5*B7F6$3+{co6nM4|Cz2ssDPP z%Z}+c27#sM)H;JlZJu$NQ;?SKN?%)V@<9QU29Mdf+#LfJsKE?IPEP(MHg*w=`%KKW zzP)WUlm(tf_4mw7e;^hqpT{W+?~Eh9N|rn|JNtfgyoZN}+d=^0cq2@7VPOG05DP(X z4{r9(RX`ug*M~-;R6X6Ww6?p01R{Cz*VEclYj1N z_N?k`)?))irO{;B&Iro2l-#n9PU# z%FWFU#`!`-Yy5+uo<+Z9%5mEFpx4i`GJ#*D?z~NIR*hsl@TIMM2aCMq}+1s(2w$ZK00IAjVCGW zYOk>oLH0E^_RrLmoRSibVQ08;$7kYc7~&?5{ID=1!~fT>=ZlMr=U0sg4+{5nYMbhn z*wSgp3@tlH!j->;=@(*m9&LRm18yS*N=pMZ>oKXdA5$ensh#x^LT(*>JF_Z+M z0o<0OdYmUt@`4D&+kvqh5IleWeD*6h7x~iT9x#W&nHdEoB_$YnZA}fUCgCNX=FZN} zjW~8kXQv@&!d)m55fNe0EXjbm3MBPAPb^)SqeMU*9bbYSpQ&{j`tzq{V<;OV19&^XQ#r>#O^qxn+NhuMBiHU$AYK$EQfkt_=!YYs zw>6q?WNcjQyfYcvld8m%Dw_J&a@adbaxB06gISf0F8Tr8JZ@j#O zLGYNF}kTFlCd1#vTn=+9C}(g5pNG%z?~0fnxCsDu*3 zsI;r(97fEw8f{-(Tznr5O+`ba3)nwQuUO+DI(qdlYQ{JJiF3EHVVlXy!otE|;^InO z_H==ZwjQqZ5{r5ZQBzZU9wp7S0qgcd!&y9VEt=W^cw}j5NgU(}Fysj#AwCgNSI<}G zYLFR3)mgy3SHlH&o2I6cT7z)TaK?CkgAM5c2<~oafiabpm0?!TKs}d8r=6#)%PK2X zR8=KZRECUWDB|!zx;<+|crnPwgE+;nudgq(--L1_ehBi{XAp!z_9YT@W?@z@prfMt z2*TFgRPP4h;ot`vYDOy{<0KjFPl0f-CODqw%Ix;!! zxS`>krmVF`_q<1BvAHX3r<*aY&7$0Z2vsVa>|1trP}5Vw*r~ec#U2)=?n*0m; z;z|!*{{D$Q#|WXIhzR=l5vixQ7X*K5A)#b?x!7ma^nW?b$7p5yFrvU_U<$2+*y4Z9 zqCn+`K=yx?Mc3AE|F62?|0=Ai0I221figNMjd0J|>@@Ef?bM%6-Q@i`wK8fwJ^a@U z3M3skG+`4GuR)<_?{%n37+GG9yT;xtC_14yAafSn;rK!adWL8JAfMi7?^%Xh+0s9l zsk);AIyV4JysN7VDZRG#D$%MEB;@R)7RYf}SeUC&s%6Q}H(*lp&U1WlG)ZLu9(8nd z)LFRpljCAzqobl;OG=^|8ynM-&ju5ZWT@`krYt`hvwt7wA%&jgeH3xM7C!m7gVo4{}iEmka^D4w3K0Fib{;u@TB~oqH1FdR8Mza01OSetG_?9 zrsmQCTG`N$8XD7Bd{p?x~i`!!yJp{~$UO?nAX=v=duIj9Z4iv6e8yzn3^cYZDMg3(sxMb=L(L!2Qu@cCt_HDgWq!o`j9eG}lqDQ&ZpmpZ=#)EVfvQPo&$rIn560ovnk|sbJN=ZopE{zJl$dXSG z)7B=_)zuyIM4(}lr32^TcUaXvvW885VNwAgm$o5oOViBkS#xtUnUHHFz{X+Dd}DoK zXBoXlv?t9$jZNe==FWag13}fj$T}|+6$y+=Pn6)l_h-_IEH2~Dk(0pw!`G~n1SV}= zCZxUe=tGcos#4xR*`4f=gZ(t@hmUcdNqVDw{}G(5G~HGxz1r)+ypd(APGM6@JSH{q zWxC-}XP8US1INMH%?^*%M-(+)c#c)Ju>_Gf0}et%`|L`2w%V1v;R}@+^WzC`bj<~r z4I~9g{$(*2T6Wjxc3@fVlB7v#LRJ>T_05fx6$}sypo+p3ZET1$sI9Ht*xp_S>9)g& zbHTp43l7iz@xxF8PioC$+w(C%;*CXKI&gp*6f7;b%!2F`!Y)f6D80wtO6^PEmM5J3 zhE3q<#Jz#;r8FnRSUM4zAf@Sq(yybJa)zWdZOO3JZOQ~W$DmNyU>@`23ss-%$y~l0 z_0Hcz2$x%rv7g>*?o0PB?faK5#PRtH)EICOWqVS|g`x z8jYn;>1UYPjVm_D6= zFZ|TMW4jjLGs}dte>8bC=lRtdtv5$_3$@hmxX~kC^+%*ap>Z^1H^cICKxD>OA$KT^ zY-UJs^4d3NC__@kn#$^Si{P_QZ_Y&J6VI}H`Mb3cED7z3)50csQ6Vh1m(_F4!YfAD zW=TSwm8CYl6wgVut7@CbHuajt(E0=1o}^ecS^LkQ_dFlXm|(jW;kkHBVcoflBf%dW z%3*t(CVz-sn;8 zuMbxh)vi0O8H)FnG&$NS1exKDZG#`gMsxR+-|B`8VXYo82^|j^kE2;HrJt`rN(QRq zAve#;3#|(V7F`4BVN>5(3 z;fh7aaGfu9++Oooez_8(^+fs*CDiVQ-ftSE*Om^;${ek_gMn+FB9nmEM9gHSl{RMN58KwvC_?!ch<@_5$Z97kd95YDbj}9}PTZ$~;7V z^MYInruwSe9xZ$+LFh;pyS$%*J!naz$d}s%Fri&uQ@o2m>sv0W_!PNDaogpkMi_F7+E>}wp;Ag+Q$D0>lZXt z+N^nM%mBe55z=P>_T?@Tm6YJMvP(-#H`!F;R9iiZlXDLv7mNjn6_3v!(_9zOn+hc3COck)ta1WJ)XJAfOH);Bj7 zN420UOA(^G2v2VW;CdV#9dRir6lG<5-dq7XY31f@F1x(^jzj=Cv!l#>=wrje6@yZ0 z-*Aq~1SoU?r2vM^Z*9o|_@1ql*0JHZxV9!`Z+{qB{|lQ^L>{0n0R91Dbhz571jt_O z^=o7-EG)pGL`O$I#KvY|V~YSYJ!L$-L*D>ez^pViHTx2|F<>wlAT9vkMg^c5h{f#Q z*RDv;d$Tj5>T#_LdZ2s-t980FC8eT*4{93#{LVUEK$Ht7;}-*2TP^qN@USXUU0ofh z7Kjd$XQU;Cncl?lRt$g52qYO^ZIl~LgXnD|Zqd#0zvWi=f8TtitX@bpJLflLiie6t zSO`gJ$AArVa51NF_qHA+Gf_jex&u~(-y7YG36yx?$w2BclO`0p!^4c?1UBwrD)DO~ z%2Vso>GQ5_FjpsqcwxF=n#{oV{2wrD)=rBZ-MVzU zx}o^sQ_wqIXXa`d5*AtY=-hX&&FSx@TN=S+cq7_2ZI0bi>!MrHdafR7HtYw$% zqRj<5G23@jPYe9N1bb3f*v#}Sv<9)&ZVS#`V1qjJ%9pmLZdHkAf7{YnV!Gion!&vd z3uk<@2Z^FOoVZsndNpE5f~$LF7HWx&>L|jOq;lepkv8pP-;ENrM04i`AKPRZNuf^7 z{iL&z5y*w&w0Q|7eLmwU>OW9o2_>Urhlpavpt(pvv>e)bs02Rk?+SlWZ=HTN-zW22 zOSr0sSw9uU*1n`gL0bC>K@(9P`5~IA3^jcg-KeK2gIWx!*o)uq#8xp#yDBqm$10Z| zZscX!j#Xe3t63R}tI?l6#VMZLRnV%(Xq<0&gO&Y!<55Duj_1-+!S{1Blm(Xp{r6vp zm4YZ2#LMll1v`?yesQB3{J44;^U~FVsc`?*Pvra+)f5iHhzewNGgGwOIovb60Ugrr zXFR1w{Xg0sI1kPrGZ;1D+LcqTz2mV%&dus?=VlBwJvua3l-+<;8~?W4{_gR`(JGLX zk%y&zTwL3BnBYPq*GfAaDTM0A1U>bnqKMp*TklZ~xGQ8nugjN!aK8WG0kRi*RdO;}OKWQaFO=fN zix+@HL;gK60V*#~F$;_5uV25enxW+~Jv=$gvl)(24iru}{!&f!YPt+}@>ipi4d_-N|t6}=q^1vS;UmgiVutZ^FF=-EJKyl81a?1 z+Vl1qhbszS`O~b!{n95C_R;QFnZzHCmL>4uUKJ58@7_kfal`5h3#VmuWPZ^3OD_>i zXyuD~b4Jq6s~2v9p%1Tn4D%A_&VKiM7shyHr}8xeR|FTpVs@>X|j)G<$`ON5~|)(b;w_I!j-*S z(4*oi@OQJGf2!QcxKAp#$bvb8+BW}iQnowfL-3>Q>N5Wilw8TrzY(A<Y&1X$fgDewmdHHdcL)mC#0oDkh7+DBvDG z+i?4aqgc_`$WV**AZvG;@LT(Gt46V#*f)X?_j0q3Wz62F^A3g4gTqI;tk4(JzN6mHon z(xL0QQ+i|ZYx|1!TMSXRN8D@fo+(4gQm49vc4s0TB@S#|dIWJFCzQ^&@{{Z@%El_I@WX6HcIXt$t+tTgx;KKp>; z;>C^B>>HitAu_%Zq#=0!kCTn7iiPBebeT3K2fcZ!43V_&I6HkQalte9!$mX>DAR2(HT!ZMnvEMK9P?M8?^I?d2PsUZ*M_}CV06ygQ>0Ou;|;6p&Aj? zaw59gxfXZfALF_vo|gzkPRtS7X;Y~Pf!sO{1)O*^O>XO8x(60SudGtUHIWFi()C@uaD2CO`PRZ8BnD$DQ6m zne{yQQglElYO++#hGj{XGpDIAdG27Rn}Zc^#mL$rKX725I3)IrnO|YpI#kaEon8S~ zSyQZffvO!_-6{xm@U0fcYdZ<7(HlC3fHxIRMz@`N&l2KfEiCZD?YyMQa(`f8F7BZGmw9W3)isKvBj)f!5P2S^re{0?6;SszCeJbz! zAd#}0*L-=LO~{o3!Nn$aMc)ZbyaOky#q#}sOM3LaeIWc2c1|XW*q@GL;95Z6$h(o83+3JY zM8*k9-k({>ye4&mLiam#7Z$5~jvn)|;!d+(!Z=w7uGd?3Q2RnM`rsxv%!q-ZH{C3< z^^xo5%Lu#P8p40l|x= zbE*m09uDVi4bWI)l_dgD-R_^33p*wXC1o0Q<%)AH)AQ%wfBpoN(FaWKm$Q0P#1=oB zKx-7h>ajGs16LvO0WDBpw8wK8UV0ea)g7s+6g9QAfL7@%TC%jZ&IIK}e-iH*tPn6S zr>D*x5tK@=ULiR-IlbiOeoRc<-5tYdZej7gqM|}{(0R3w82Bjoym^)MrFm@z@XMW@ zoogi=B!SH!nsk74{*09s(E2{05!h?Ba#RicNCzUr^l{g+HhgWGn_a_Z5QW`_)v}@S zd@<;q2c@-mu6y>IxwnlLaiN4@uIyVQL=|P;>fb~#e~A`)=(Z?MN4UNd(5ZSAJmHB z4RM-cDM`c@nVvb9KyJxvkJR?ZT~t^RYK_5N+|CWfQzgb2=;-Ku$^3n+6p%9g=~6xy zsGc}$MxKUv^oz)X9|?ILrtwo}Jo~F+N%v=o(r$&VN}^8dNBSO_{aD_K>k`73R$Xq_ zOlK}ferJbW2YHc|F(TXD{faDf&46r1=HS4jrB{~fl42WGyh2=^bG_A@QqWxVl5r7x zwZuV-0ls1qb2%fW$u2Ya%!TgYHTLeZZBFo=?LmG-VRU{+WnM zz}nBypIS>-lPmBKjm$H!&q@p5V771T7?Z38M~{|wB}RoR0wqF&qU$`9^KEo5J1HS` ziVhU?8_c%J2>0`|_Ey7tO7O4IuhUrPTo{MBKl7WvC{;UX+KJge9y0N&`zw$0*R@vmx^JdUS^8d zYXefQbp3&^=P21+J#gINjQ=9_IHT{OpoD~m{zy+pfqkt?^luOKQK#kE|@zxZZZal>$yN zqoyVi9JkfQz(s;)Z0>qApa9+nWi(ceC@5Jcr>210+@RCbwJt`A-vS_VwgQl&$ zMscs&@|W4ZU1Sa2m3RuOEwjeoCjCyAUvRLqLU3ZFc~+u^B0?V+oaiX9{(O1})bqfBB^p8m-$ zOM06vF7NCoTAs*5aX}`&)#fOopalIg@wmqZr3+pa{!69>Z@Y{-c$mYuMQ_o28F(X) z-l0=8kvw_Gx<*y{G==N)}AGhVZeo4DNW+c4zV#7+>LVD0Cq+Zt{#^Ar? zRgsLhmQCP46`UR&9fRWjC*{RL)libH7M~u&?>SNzuhz^T^4KwHmAsB+4jXA`s2VNB zN)`H~qEyrmY%5|X)tEzaa@yWZK1?HPKc|+AJ!cu4ddm{koguo9Pf;rzc{nZ9GcaRV zJy6qRK)-)kQ~UIe@`++A{`BdQVwwmbRGC53H#08}Gqn9q9CO#rN8H}L+=&p7qN1WeiDi3vY(8zndv}@AQv7rnQ7w>9 zkdTsY?Cxe|WMqg=aPJ>o?5Mtf52OKCfoIv!s@klqtlM!U5YIv9r`pQiECa|+^mvk( zo;?HDDgngoTSFvvfam~mY+E}6svrH*iMy_Tp#Cuq|2PngQD#rCZ-Wc zMK@PlySpCZ6(BJH@Bn((mxXCZou1E7A}(yhPD^Xv?J=$JYsn09V63t-(pPIPmkDST zH;HVY>|m(aEkg}jLs3Hs`HBDuBDCe>a3qzmq#}I?>8xe5Zn+9ixL=doCAu5fu!U-P zc~3bHUVM^?MHCuSq}k-v5#XZDX&1NSV?@6~>SDLQAdTSLa zGUwAi6;_J9&E(|}5r5O~8vZm|eTRx)D7h)z)4qbxpet=D#jL0H>zIce;^H~@l}wSZ z!sZxh>=nU?j;O1S+&m0vMyJH5KUzZ=SrYhQkb60qKhyoI&9U@T!aujNqpX0PuvXJP%o+7Ds0BdPn65^*vrb?J^^XnR~mn%WsFD zD!N8e>Nu^ubacZv;ISoKdFSspBI9g@;=(>C|HpsFs+Y}R<+!c6uy`YfPAiRms~yW$ z3Xg~DWo4pWpA6kemUUjQXNbIV$dQws?H12-@fbI{Z+oNtBDB~?kcxv%5AO^Kt@%Fl z>DKiJPO0rY=nhB7C8dUXczl9l(y9Dy*5ByKawB3|wynr8$nTS|CaZgI>~N(-ygpHV zS5!+-DxCaE`^#{d&qQ3q<3BU1sTNH_6W-lT-T&?iW#;FH0iDV$c#*ZvCGG^`!K0w{RRpupsg{twr(FAi_?PEe+B%(UFvai;s(j39rS$zFbM5W zw>3eduA`RdoS&038o(?7hU{u*02fNYrYkQmj|p1BcUJ@rX3(>91%#sfKD2kSFa>4c8-3~Y$2LgeBWOXMJvbMJV44@s5A&H5xay^- z6nOm_G9?$m79AN%;8CB+UT)?T6(a2ep)5s@+p02NGLv&v)f3Ofct83*yMf$}K6 z{Jqn50j?;SJ=H}ohd%)lZKgSQ#AU&zpVd@CNa={*0;S@x?|YV{m2dk>^tknjRdT20#Y`cfV|sm7NfJ0>YD-CjVu+FZbf6+>s}(*=ikXX z@8dCa6{vT=uT-t1!kIS79%4MBh7&j;CcVr;Qy`>$_JAW)(@Tqlv6`FZqv8p(Vn3ES`KylD}h`sexSw3yW6Emya=g^mT;z*5)0yD2dA~yfS zaNI}h7g_rm3FlLcUV&Jl|0;God4S*~j(ipS(w#O%$yU3+Bo~OF+Qu4hPjbWIy}hBp zu})zrk&&+e@92AoO#cS_p0 z7ip=fB4%XjhZ~08wEGs;HYE1@?UU||@7|q0##s$r__hykH2P5-IOol51KQmFG25a- z3J1w)`?jBE&z?SxB25U2=1n!y(Rr>U6#ZS7g_Fj@<(g4xul#5n9;YKD_4A)156fz* z!Wz&LNNNSz{5^x(b0AHlr3`JHPC+T7E)p8dKyl}J*v)u+ddlgts|~udQi60nJw50+ zwKdtoKSVs|x^gqwv&lMw@C|mqf1``*Yelu2tB7#ci?dD3Y1!}z^u?^;W-LB65w5`p zvr6$+cE<4{u<_dzUsAC(5+qtbE(ebEs5nwu@Bigcs6Fp*P`l{x*;E>Otz%Qip-u zazS~ottUsTDPWyHvsgZ2-nDz@dBa_Qn5k#-$Mw%&lOoOdTm;MhpBVq|-?WM{O#k%K{`pO8_y4=>ze=Az6U^#PzP+LGmlQ@~ zSzv5v$S*E#?0q3`Ud9)=1{A1^3f!0ep5WoipFe+m;Tn6nx=;-nCeczhp!H{slM~MR z`%1T{C&$NtOtKXq1uqZio?QOx4Tn~yaq#v)|BRxPDPetm>xaJtR}vBpbYM>V#9Lu$ z6NFIc(&iYY&40^qmP<)S_r3m}3r$+k|M!)Lz^`APi@I54{97#Z&l*Otah&{LuR;`# zu4c^+VvGI#6b;kED*ye8#dJ}$@(QC;m?If4S%hgBZ6v9f2gXi~T0yvX)qh4dd>K~R zv`D%AxP~}UzqXVdG?StktHw`gT%z>8x;OPpQZSlSLWxPU5%B_XeRak+!Zq3aAH(P> zH~H+0#G4#$k~k%VS<5Ch(_(_WFN~K8kd_$X#}VHv6+9 z8AO>P+&f-LhwZmktCYucNx}49i=4u&;)$D_J$GB~@}+}EdcKAvQTnrdN>58pR!)pk z>fQyaAN^jn$jF@0tE2VtA7{GnlDfE$sB7t{4{QA}H=>~=CwPDSdjg4mhmObR2u{dy z=JY}y%nQ6Ylu_J|(yS6Mz>n!L#e}`*owCOD$eeg*UL>@`)0xs7Ej^Pj?q*D%ep=yV zINAC_6>myhOAaGd*KeL_C|-b`h(vbcY!{+|czyHi&GY}YRL;YK%J2t-WnW92hCIml z-Yfl>^5b9)c`vH1Xk|&Q#Z@{18I-Pt5}{)>b_gFa&TC!rAb{3r=K!*nwkOwCy2p0C zl@yk7J^wCN{@F@C3<8%*LHFEZM1*#X-L{0sgq67v-}i5~-rF2htcG@X^QxZo~TIkGkZL9Avcdco(a-tgX#EBfWdC+_s2IE{3v=~3zo!S;s zRWOWT!#7X?g3<@_2LT<^PS;bl+3_{ob`;5kO$%X-i!0&;$_;0RfBZsSEtj0bhk1s! zZO{gLDOd4D{j}=#vjS++(roTolT$h7qeWP+8ZcPC>q}|!eQfG3$!O0 zXlkVg@G1W3-@cv8y{;a3F8Osa!*akJ>0 z{0_3T@IEB&^yR@LlhZ#V8G*jp>rO!2959?}bKm#ii_IEbGeDIeu7k5sJpIKPO%C-G z^$46=f+k)0+G8PC=wwn~k(^($*VpKtz}+HwEI&zUnK0BhFd$+6gHH@gNXt8=g_g1& zA)WN^%;Wd9wY^lENs%7gHNCj0AYr&Jl)4!F&TiJVaxvE^b+RmYadAd4KgHg~t%MO& zs%t9s4m{V6t7nUJ_1?SKbDf36`wR?oy?z+J&0jl@5T`uZ;RJSnVx)Zs2Xb_vQRRC? zBMN%Oj8P5Oig?$bTrcKy7mA|V{6rxGs%vQ13kf@}a~FJ~8uPsi>fXJ*L0;7>f)QL> zZ2~;2?}x@0nv3MAs81~Ol6jF0BQ=KnLc1mpDXw}*56;o_9I=E9UXab43ha4%eyYKK z_%PhK`zE(~V>%~iA`YIji)3ILzSh>PEYefBmR0Dl!#B(5;Ks!q)S5ljOxDrg+t{j} zeT9AK#rO4!0J=)>ZpZ@HN=|R^u(sN~4*C7w!PT0BT?Z@%0^>?O_1d~PiB)D`x!@4} zKr{`z;i)JanzhCiGA59Vo$Jqw#Ng(Sx)8jj#{Zl!w>*}cbqrBQmupn0!4i_vUCY4= z7=A+eYJ#z_!ui^O~bX>OjWPv&7(!8to4sqnd?w86$0 zynRyl^*~ntw!jCaULuGuV|K~v?F0GWRE7WR+xB6YTXu#Q-72)?ote|zWWpcBX`9T6LOt#{}hIPjGUk^wu ze_Eg#miXnEpgXvb#G!hS_#Nxq{VHH4v!(SB%}&Y+bwEq7ah7aqa;apH5@oU4H;9UdvF z6Qlja`7MXgtEG_E@6*0_OoX@dgyr~9SYWS4JJhA@cZFyO zZ1UH5an&lK>;xEDcQ2{d2IR<;#&ehpH7|J{Bj{`PyPXwn_Nfhn159vf36E&+0XKc8+5O4h@OLv9 z`1p(H>s2k>b3h zGPeca;=D#@`H(1)$2PpY28j>-#TplPdrg7%OW1$nM}kGU9{M5q@l}`yWFgZ9BWDBM zaPtYquF8d#`-XKmcHb+U#p@Hx@L+mp-`5VB6vSGGte4f8@n4!09Ac{6Hdlfgj$Nzv zJ=z_=HvaG|eB1CN>hP2M2YLOrjzImFv4?}Zo)%#t5`n~Js;f~4-qbs<6n0HYK5aI~ zb}57m5m6Gz7vcTq-Bf!lokrozfuy33@6YHLe1*q1%K{53*>44|f-(FO-6HH5~*TN^gDz6G^tFCBlM22&I@o;u-G;QnpYzW4*YHtIodQG}~4yLLGEiGz?9@F!^G$w}M=PZblvKl}i zPV&#D`g>ECNX6MNaW4_O|H9a$DzrAEa?|8cVK9y!69}m5;kJS~(Mn~-Msy@<4<9bF>3vM3+(CGIl`k(n)&C2P^1J;O zs;(ekShsLZoH5Jw^-DY*o%ahVS9+df5z9AX+WcEwrrS&-Cv$CTsaJ!_YUR7ebGJO} zyk8b&+#;hotzDGvQMqLVrrq=oS0HXFJTaEu^IAUR2t_;~4PatR~xQ!CQwJmUa|`|ZkZ&HOO3Q5{C=q%9mQWn$rzQ{ zYpa#uSS=!}$12h-+S zG%AV~lOjqFjJ}hn1SB>!2{C93#xT(;5spPehxa$Bi7uneKlhUjynjP%HCq-HCTPOp zEcP+$WaK3|2D|fVT=klglIU92r&97csg)Qo(_X{V6o|=cFrAjVcU+p)cvsCBbm7xb zzxvwXNy8e{aHa9~%Spe&OXn{fzbs$6Z07fgmS?M~S8ukx)@6ps4ju4$(4v{sHjT@) zV;ZkNxCy)0wRL*UNx+)ea{6>`!8A#4u``xkv@tNvbIrVB*Da==JTrq4`5q=2PpYMf zg1(i>9AeIoP9_@sWSqsFjTDAk7t^N5tyy~}L#>6pgnmy-Mq?H{qfpY5LkWY8%U;_u zxLp)^n4)YAk;08KyP$yzCIdTZtCvy4pPwbR1y@40GQ8dTZhPVq_*uH6 zb}U_wi_5J%Z{HNuY{opP+Zq0L;pT5fMIk75IQ*20h{Nt4aV^h~BVCjKM4F-VYot?0 z;h6Og-q-o%rrIkHi%T<#&&snkt1W01iiggGeio)>NxZ;ObhGYpKteWvRKyW4)HPMU`H3H7m3E`5f#YNZk&em1bcs1TI0? zrV=E3*Vu|xK1%ZDiwTqEdFO~f?v0@>rSCIP+mM3Zf~!s+@~2!%aZ( zks$4M@FE`QT9bCbm%22KSBo%h1&G(;G@=?=}1QJDUYR$E+tmpS{;$uegd~_4(XKg-pe+Pk;d> zauB%adzaG5NTBi?Mmja7HWaJd*FyT|Vq}TbZ3D+T(t|w4UT+TrUb1=OwXAbRY=V$M zokDD7tJb?U#HTz+_Uo@TH{^pt9=`Z7k9xZe?HSjp4P@-i)kJKE%HPH)MVH&r)+!<8 z*G|+O^sP)Mx|Tara@lNO9@H39_Fw5Ac3(=F1mhN+HQ6LawD`y9uxg5f`fDy9{{NaNulX;gv{vokmijeoIIy2Q}^K zHvP(-FeT#jg7z})`XTk(}3%_lY7?{Ak1q=-eixwyPvlp@JYd)j1 zUHj%Yx}`Q9AQ=|28sCo;+7oQt%S$^<-ZL6I5B?Kz5WpmOG2z#!cNEK=H!Bh{#gObt z8RXFKtCe7XXyj{zgMuo**fY(YH>uoy`GdM3RZDU^BwMrcl*;<1Q&~G184G^c*Nasa zmNL*1LC~6Is#$zHUri}x^7ANVwlb#U$57ScPK1c{GZhgB${6TmN6lJl=HdyrYMpYA z@YwEh`Q^Z`vF4rfJW<1*s28LYmj?#m9mtO$bV{YqFP~A{o-UbFmvH%Xb?+HOuk!wQ z^)auRnkZ5cM&-6lWyfd9wC^|o^+Nm^5=6{QM$ePa^?J7^*ulN}`e9oO^&^C*yqjVJ zqHdw^58AyfCcDCCN7-TA*PC(h(&9}`-OHFpZz=EpF;<)ULV?VCaY`${^7`}Ubh}kv z7NluOy;c-IH&@(=gjivq*)*}rF$#+X3Iq{8>i^*q@9 zyiA$fl3%RGLJs|4b6vq@UOIAT$YdE76H8V*qRHP-!X2HNv{8M+XXnDlA-OL{uc9 z^CRPRbM)zO`fV}f>tAJAc%Sau91fk9c!?Ux$M-CMi{x;|q`l-WI&+CQTJri~HaFtO z`g1_3Yd@-0|H#H0G5n)V67`{C-Pa5C6quSji7id@EIF2ysAur`!P)6`sYSkVJ8U?z zk6d=&Y)nPkZ#foWv;ns??@b*LhB@^L#_bE*MUHuwC$Anmf3GDO_rm1-^huHM`lDAP zEHUjR8sGTuSJCnXi9!^vTY+N4Z%X5JN)n!G@sw`z3MP1N8D(h~2ksO?SF24IpJ2j2 zN+kDf?HaX!w>ux*Lvz~^g*E%Xi9!E=t(|pTRNMFWK`;=Iln@DJC_!3ULK+DP>5^8E zZjcb^?gr_SMmhxP6p(HhKstubXV1MC^nQQwyq?$V;U5@g=A3=jS$nOu*E#3&PDk|h zU}a-9UspD~J)Ofa`%S#N@*TC>2r(p9wtHVAQEI9lwq+hwM6JpFv2o?g@U5Z}7ox(UiemFlT(1k4rxULGW@p+k z>JqMbJ;~F@sJ#}>2VWN)a%xjxH5_!}R)bjWbc=EGXq6^to{vVS6gp%`raFE^!4!O^ zFR-kfTuO?HAPokxOjQqtpr{x#e2HM`1ZQS4C z7qYJ$TwaX9&Sv8}kP#x=UCYh)eILiGss2`ZeZNpy9kKL%4(6)e&SK;{uNWvGMX`-x z!nY6}N+`N#5Sx)%+VQ^XaKpHeju8_JFQ-3B4SUHk0%LAW2dAMrtt&H*H^OQ8_BaWF z#drMU0a2=Oe2(@5_VRvkot`JI;~8p0`+NCT>~|kZVJzhk@iIfk<8Uo#d5$hhYuu;{ zHUBhJO}W-wb=megxk1Txx!f-Eyh-6iXMBgG2sGHR`P-)1n$MbYfqSMZFBe~``Q8FoSsbYiG3-*7lLb=~_1ZMchlh*md8N%w2vH59 z!(yNNVId)*^$-aks7?PuKq~bL>u(6G+m9bpANeNW#WFXprc!G@u6C*zX7Qkc4O5D! z7s{DzXxcxv`ZZQE_L)cRg}M3n2QH*t&^Vcyj`t%0RMzWKO_^NF1pM60s=#iS zZe}lKWU|R-EX1T>-t+1EfTO{_os6-JfF2*%64AsciEnt4ZFL^yRwoT~-y^`HMe>dw zV{!Ug4V%8@avfbvM{O`J%e*p9gVT<%%SZ&oO33ih#yWE>^JQih<9yo#LnhWDZZnc6nsYsGw zk&PF{ZpadFnb3KD@10;7%F(7oKYEeigMYvDlbdVJR9JrW&j!QNF&McsuD%@>VTt$W zi*wa^Z<#$??CTAlXqU=MT)(0jNlR6zET$Q9*z>(As377J=>PW(eh_zZ3L6$85)J-p zHUFtXBpS2oX&?@N?-5b#c29fZ2E}IOU-M&^(`Bs!M>$PKg86u+~pB&o$9>a$h z%nk|V<;dRmh##{W&ECY%bS!h$sw`g7ps-_dBsVZl4NMXA4vUR_D{%d#6*PB#SCGUB zxvZ)4ealgkwvyxwIUK(v1_T65OAB5NCa15ny?ypq@d0X*q3kLec#QqCt1I`lsl$3R zTrV%cGa2(Am;Wvz4?Z$D7dw(?UYk?yyEM&}p&=RS!T%V)pGxO?EHuy7BdQg`Q09H7 zrEiE)I&mXqg!L)?GlZX_DiPJl*oC~UBbS?NJSA)cPU6--fcy z>;L(5Ixqc?@bJ5+t(jcGyjU#y;}hcPwXZOt+gL`1lG+zLO+|* zms+7?TtIKywqQfTG4FV_6S8>5!j@#&a&H&D6ph(6;}cuFz|^<9#K4p0c}{h<&hD_y zE?Z)D@?@s++2sp9?U|DIH!ruhh9Hy-^J=baUk$a={dY;8Yh4|&qi>>|V_q}jJs}*( z?fY_$HZ;QIgPcYAe)nH?Wg_IKFf%^9^4U8GM?zUm zvJcUZzae>PruD|Okz32-+fgiCeHyM$(UPmHx8IV6km_gZ{HRF24?%%Fx4B?M%yD5D zeRDYM_pxpm`C_g4g_|gMnc4MfZxZ+@DivoK%jE0vh}^h?xHCd)zdH7A^^o!oT70u8 zZ&ip&ivXFlMhkPNYlTO<>>Yg>oy{qKnl9e9okv(tT+1ScxKknHNS{O`=gDFC%xk;7 z+~G!FQqPnke|n`s?qGNJ>JPNx6>qPakO>^I%gELj1ZjAa89Nigc)5cIOvtb@EsyVN zX8U7qkwR)_4WcHWhrWRs2rFOi+_GT zE_og=8Im_%J`~EL2~izF$Id2hzG9T=Zs=0v9D&38Z{9!m zC8Ey1gi-%Eo4?!1F09?H&{;tL$WDlDZ0dute_*S<75<%G0=Gx}?Y!FVah-F1D@tz~_uBV$YtPK4N{3XxGQ^xCq8se=2tW zYvE9-`TVbnR*qUvDRglHwr~oqSkXsc=}u3;Wn8l8Si9*qpQ#nx$b_%AZyyZHem&gd z6BNZTCqo>g!hrT^_lGfqCG~dVR{kS(4MC_^6|}s(e;l!~n4S5#6(=qG>ta)9yl1CK z5zdacz{8y%mxKa@ZhsodPva!~taqV77l#cwneaZ^gzf({dC6#l331;OIL7^OWRMxO z+F82ru&pC=J?NAgNlYaBtYYg`Jd)j<6{ z-XgI2=tz7`r&Sy`{@fyrszxnHkh}JMY&luVD@?H;F1Xm<3lM~NBnzbPq?7L(iPu^M zXGRe)xvi^P4%&<2OOe$SSvgc&-BGWLxxGp48FlBi3{P{Xl(GG0`)5Qj~kcSEqV-f02k^C=dQNkei+T0*EGS1;z1=rz+)hF%HnKB;-9GPh2 zTlf0BSYu8+PifATiC_2e2p=!q?Q~_2JT>j)UEA^Oh*U5M3b~vU?yh?xcJ4}_QBt+0 z7{EZro}bh{F6wY(j@4MlEj^Q8M)$(QElRzUmpwVhLq=bq_l`C{3aoxNc(PKLxbF+K zq2Qu?E#o3lH}^978qswYOs~%r70xl&9i-S&Uk!}O!S3#SOzd-J%ekmqKRPrPMpjan zbRsCL)8=HG$ZtV7cxyzi?*09)-~e4~Jc#N?$vRyo;pQ1fOQXB`6n(M{IdS?kfpReu zodxm}qQco{!MAhlS@=6PF55Lm>a9>3^aLq_&#jR*cJ9o1-AUJ%mkUFs>Y@$Ib6D@^ z8jr8Q+;p29pn+xyoGBYB$pF1SWWSh;(8uLpJP1kYkyDWe+=C$bZQ85enV~fWVN20T zI{Je~C4*tjTz8etWw1I%ly=XDZnqOB2{R8z+Pn5TBxIsZl$%CcriZdm$j zP&VpP>FIvqFy;emgPT;*Z%1(Dj!j}#BWZnc^>8F9eFAG^3)Pckj*h))%oXc}Qmaftkzt1E9dySxT(gBuzDNJD# z|3qaFi;R&v{;YTmZGDrg5gTu^#%C`wZ*26H%v2IW3YKuK)q8d~OnI|Q=KRL2?8!2Z zYA&t?TqurYmrnDj$&K3{(B=C47RnewX=?s6^O$iZcSM1bwg~3)Oowh_e7AFr<&3XZ zvw=^AxIaR*xTA$jVTeZWH@*aLKkJnbd~h+&1;5yNfX6xRXs906YqxfV!iooOg(uS}tmzsp7F8tlT!-$<;l04q*w4}((>W>@eAX<{M7g@+fa%-%E4=%N8zESqkhse+O}%G}9ve*ZB#-^B z@~ib6f70x?HT|wG(>LqlrE^F&cyUZk9FJ@Gg#&EDOiuR^LHq0;rCH?A3>#iBV9k~-5sZqocU_cJ~W=tz2WJ|kYQdkQN=H-M87pl}*xnG^t4Hsmr|ReBD$P4JvXf2;MbVcrc4{b% ze+_1un3c3=Zg(dudXToZHe@!1k$c{nn*_t#_a=DubQfyG<|(XF#=b!|(0|V1ky&y? zbXaPyh@vulz2-ULFO`2XG>+38^nwugj<{FyXfIpw%9Audv)anG@&FAV+2SLM4FWQ z0l6)1Nr|)_Bk?E+WfX}U`&#zY#P=$EZeD63Mb(eP4#!)d?P~dmtXO+`y`G=qo?j;+E$8++9C02tauq}6mhb_GyrQ0 zjUPU*yxPynLjUEO*6HbG)?Zx#G(zSh?DWAJCN)(YG-593^ZIvOoQ>2Bg*lXyu6I=O z_s>RHBG-x8qx+=$bP+6aT~A!IiR;`b*rh)gX(LP|IR$y8j93n33ruxyY>rO_+_r3g z_aRWL;po(2QS*z8VvSH=k?Ihi|nQ(lFkLW2Ki3K z3kW0+7Yu!V7G#z$$Q=C|a!{1GuG<#w5pxMGebzptN=gA)Seb#My>TEH$56u+Z-OoDS@n4xd%TSBOM7|ZIZ$IJqB=?@|(Hyp= zXp)nu-N>d3PvD~k|8`D=u9wD7a;EWge+Kkfwe{!{@?*4~>dPrJ$2G4p?8MKU1&w=f zs&ilZch{t@QLLMuq5Y0#j+gfA!Z|KacfM0qbJI+YT6Y}UgMuOSgKTRcZEZT!)j@_gBLV`XCsDjyqGsfomY3A#Bfdut=XK;`Dp_QCbXKMVtP%$1SCnVWs3)HYs- z(HVoo!^0DAuW}M(Uj;k_0lFsVpb=s0OUfJi(Rn(0d?LJAO_h*Y?@r?^|H)y6!Br0_ z3^_!SBrE@EW249Ij?RZdj*hb*m((I0;|~rX`MzvHB*x3lC}x3I7QnVP^gMr`89(h3wZ+YAf3>t~xHgmYMUPEX!Y2HatKzaBCzEqwLi9GTp=T+Ih{7N&_D zM<18=v+q++j_wtNRTI=LOw+}9ib~Y z;qUa>Mbz8*+JeT?H(dpatewTeo~)wyFn!CxyY+RoUbBJE&($>!luGw*%V5!{G%J}g zP}pP9h>kp6Jf&SDMcx(z1cKrCbNfeVsl z6cinA&_GIbpp!oLzyIZU3eQ$(0dnfy{xqh!TZTTJ6^lHsGNf-PgW?4w2~y21f!3=P zv6{VD+~5>2j;KGmAB;-lp!O)|Tr9wzxuc!LtCv1WU}f}0HEl|ZR-v}TvFhq!c{r~g zYep%4$?W)~mCKvQ3=E4g`18zH_X0Fht%>1wFA#zIru%JJ-WU?UCL({{eSIJp@G_)LdhjWM|JOo}Go zqlV#L-H2sD-1l0TwF07frJp{Zir@!T-VCK>^VxmX++_QJAHPmxPY(*7kyWK7v?Udg zTda!tgvBq(?mB*a=P!44>Je=vG~_~O=oi=Wbjog9#aMrTfj6xn7Q*qhk4|?#Q$y$; zh1k7z{iU!|n%oQem&PBvkGjklT^~Zq^WThh;%CpyNHa#bh#(^W@{v1r=FD?#@LaMF z<7bSYJX=#XKcu@mNLJ;FbYG?*Gjj*QH$Yv2&ygF|0BUDTEo@BVnwqfcMZMwiB0YJ` z<*V+q#b>ev3QcDX%1r^GiG?qjNwS_JTfaZOf4uK;wgKBnHw;c&FBk5vVMZqYZ~IxIzJt;j*=;};jlNzADX^!mr+8bS*w*lmLy^a-t#eZ7XOMWs_Mke=6FD)rS-OF~>J zvxF#HInX(8S`PE$4d=z6oKL;SkT8>@oe^cl=oh5ahf=h^EbhB}{hO>&dtW83iTmr6YLC_y0((o`?L zZckzqk!<9GiukWmY#(C%kgT>UX-N>#@}&d~VYtj@NJWqF z*f+mq#a9*hmVQ)Bj<4LHIgOAxzYL!8%qXKGpOQ6+jt!rI$s!LUZu7FFUC}7nV-Z@F zmT-a*z9z58VCz;&iJ@J61yg_QcG@>`oBY2xh|8-AlBh#8*bWs0?vi2Nt+VN<`(fng zXN4lPmZN@w`xS-kzxKp%HfM=-YMNNLWH28-^9?&gC}z)9z7QHxLFMUqzsOTZK5MqHurm7*`LOb+DvjO#%RO;R?La|1T4@qEY z9@AY&&gGE2LfdZaepPHhc{A-lfo^~k%80$5i%@hBLSiFzWUPkU- zIpy)4agkJH>f@hERdyX3bO|nwh~K_NqE>EgwoE!5s^4W;>glZy;w0_#ih_5A1oo34 zDf2nFo}afD>@2pTH|Oh*DT=J_(~bytBsy@HwxQMfxLr-!58GoC{iq+mTXv)dDZl&( znOZkPhN$X5+`mk&m+}2=QU!(meQEGTtS+V_qj9-zg$Et!DLP1Wj%Q-ce*~-17rwxVlwS{ zcOzsc3OPi$ce`||f~*SXC4*6NuC5_xl*t$EmM+;B@_3eq-PZ3qlT&wx^ywPrUCl?n zR^du@+{FHQVem9Gh|KeLF10JAL^_hsu-uO2qYBr`9}L&!v*EA)t);7+=8z*~$A*LS z(L?aLBSPaVJof?z6w4XaRtch>MNffTwqe;Da>dP8h>@6qSO;m?4I7uE#R!n!u93wMOLD)RJMKjunXAG6)WlPFTcwqJB&WyrCPZ90B05#v}Y}br#YX>SNThShAlx#F# za6?Vam)qxNS1x^SvC`km{nuqiPy%O4INI_GlMAMcuH{VOxnogut6Jh)we4-+0BxqT zRrs~%Z){#z6MCML|Ew=@ zC*G)v=+)?M%JYB(Q@p)hQqtSd7j;z?JLdhlHi;fw3yirm8zQNu_`I~-@ZCXk(4^`_kTPQRLsQt`IKXZuqBQ8qX z@nsCy69ML9*G~1No(eJ>w*L3871)}oYxSR0;q!2dJCVhobrtG~bU4&=5#P?%QW9Uh z@E23K+9pN}iH*d0v3-N>b&m$3A+ePyzp6o}O?h4AYQ%sN30(Ki=}nVqj<_<2+`G|# zEexptSS5g7M{bd}NiOUc4ilfx#Yy31b%p#tm(n5PCGx9sKBk(2$JI+#$wh`p_wN(= z)Os_8o0)#rdHuBGa69hG8^yO2|G4g&DFOY8pPlQUP|6=+l$%mgouu66gwN9dN_g>v zachp^dH~bU{^zUM?nwy>SIvi<2$KSxm5OAYwhP+<@B2*WOg4LJ!PI;nQu=TEJ9bF|45R)=)T$g5RXg__V7NR!>6u`)x7QpL(iu9ya&eE<(ZKm z7ruT~uS2M!Ti^Kw>qouW?fp}$nB(J{xEU2V$AT1n&o40h%NpM73_apdl{qHw%0}tY z?j@#xKJojPTRg)qOvl#?Tf(tvmeQnDj(9v`QZ<}L@GZ&@T=k7z5DWP>KdKboh^ z|LMdFP`|OQ z)ljmop+|Q$$i3;+{-o=5h4?@VXdvgZNA;h6rklEMBS50JoV4thcU_(z)&Xi$oz(SR z94i{XWV8Oe8$%ASlP2gGtNi)m?;9xo?&@9}|3B^|`J)j-D7MyCtk*^nd{thC?YUUc zjR}zD!f-hw9)yd7i zihsqh{@o8(dGNXcPxEZ@f9xGC|6z3r&VNOqKaT$TT&MrMvuAtbgVdil)6f!K?+Fp! zOakp97DmucJ@Jf=0SBH^_guU-Bl3};7b6e37}<}83i)e$ui}JtER=nv-~fP+6agfL zO2(l=3YSsa&-C89qU{fOVgx*H?b|-N{`?0yph{T$-J38W(m?>`SeEsZ)IY6lyraGS z*9Pmgg-*T%1fYSgQp2pnKc0WogrCQ*lLXXEFU~beWUjWiqJDC?)#r-?Z;&MZ_C5*D z-%DI^iK;)A+P_Dh^Cm0eBmyu+%%Sa})6xqcsA44#Z0}xeIZ^446p(92%()0Qv_hXfk3bpv)OeLFBNyqQsG5ET{eM@i_&}qfPtzW-p zGom$hrmAg((qx&LnPXVrVp}bBzuBH`tc%G1$J9Al>h&^PMTUJOL8N@WLrPje`(**> z)y<3YonQg2y%pO{a0tF4X=ntDZlI-T1@xwe^VQlgT(*&bm)~pJ@1iV&Up)lfe@>7)w)A8iM`iXnW52Y=LyykG5bI zaGEj!45HzDqCp>=&9gzia~wbrd(#m{0SCeH97Dr_3BADqz`6kPPT}_8_S|=sBJIYU zphO^>2?t~471m2MxSYoTAQK$ahIyyR<=hb0*ryG@_mLI5WMQgcm z0>Ts-fc*i>Cpq5p75W$!hP_z}lU6L$>;VippyES8Mdj_ZS+%Ti*yDzX1m|KQ!Xa6O zwYzr##s#i42jDd&mWvVqCL&FZJD)~+P7N@HPXShI{un$jaB+4F$T1#p`U;>4?(~?s zgo{C%?CN2}fYMh5&_PFY7_MR*4=H0Mncw}S<^{AmAgCB)wKP6D3P<0-!Bi=)emy;; z1%BO(BLhdR0XF1uyC`o{8}9)V0)R4Q=j6OOJKBLW+-5E>4#BytLN+IpxK!RwSnKd8OWi1IUFLEEn+>yJoOOb29HDF0g>)7r zQ`WPFcMrtV-_~KJU$irQo=3+uE2{D_aYwJLG8uLHe(X^q{YpXdW6Tol1U2dFFpS5z z@FvT4>=ukCXpCpu_}juxk=YEdgoFeT$9Tla8Ef`oO^yA%U6uM7fGjQm#Ugti5^&ET z95x6v<$$wZY9DS+@$CPUhm(;irXBr(^X&j*`VSdISj3F)l_$;m$ z&I`O;TwF&x!LDfE;O7^pv$h2hlLLKtIP(yw&;pcY7m-#j=S1Q+9Njc1 zjRogD7U-dAIxOC=-;FE;zJ3GF4YZtZMoDtLa9CYiqoJo?0;eC05w33!NO6EncC&JY zdmIRB0@bAK{QQixG>^}p$y^Rfljjx|th^hr{!p#3SD>-M2jG}(FlCbfstJfp0V1Rh zAW^ATS$e{y=z%aYP#;VKVpM<%l!i|B>=_`L;QNP^8 z{m$ci-X7iElHCR@;GWL;M7!y#l;HY$UO?OfEE@#CTN(t2Eih+p19l-$vT8FZg(Jb{ zthu}sy@8r8;5h>KMe_dM2#(vx%#4bK1;-8Wun>Ba`7q!?8tC!X0$H4x9s@Wx1xWn6 zUci#w-Ji$MYg7vXNFR`s1A4tck_zs~!1&-74j!JZ;OOAUh$sk-KsNguztQrJ{b;of zT=z~NNcI4`+pdqg550Sqv^Kk}255guO88PzQi4fq+FC%I3rN_#Qc^Np&v`bf?&Rob zf4)Bg@=k+@ni z!!8V_JCH68=!=6te+oG}^H^9|ByigW0SY1F?Nv^hg2dz#9IQn48^6T- zf;=~(WccUwerHB8fmIn$`kS?_3CsloYzACKBNsz~%vI z<)6dD*tobt>gox_*3%$T!ecWW*9pR^dYxk=m}3$zUjlEM9WzYMC@c)tI$u?S>!X9Y zMg+5;_oWK(O9y@nP*?%lP)DHNERuZ_lYl@>O^pbMjv)ZGv|`gKE+9e+kBh+CfF3l! z(Ew5yzNUTS(FFjkQE_p_0ifH0WfeSp0BYp)ZW<%E*%5|uY|Re2fqS@HXzE*#Kg2dT8!kjzczyN@L_lI#U2$%MS>^~BqK=Sh%W4sr7J^LxzA9S^(~NFc)V4ZveU0C)mUKm!*CVbE|H zY;Y{VVnEFquo|_=5+0yw-8%erGCopoFu4%*R1HK}!jg*Nwq;e2VF3vcUM=**JpRAr{psz72Jw%2f^IsXap!+o9|W+r2&WyL=Bc)_z!S~+qZHDL27!Rz+Gvk zXm5WM!h5S>YkeJA`($rLK~WJz1YI7bydeoNLI4;1@`Y|;8EqCsJ}Mxi8%V@1_xkls zehZ78_cQ%RNA{ptVNX59{Vf-RNPag1I!K5H0RmEp0TLL%Z2`#xh~g_KDZyte@YQGr zttEi_7&T!t0EZ7v{^fCtRvRb`GsXAp?eF(bPImh<)Egz}GRK;7Q2|vs01&E=C&55L znFHkx03%1IranH{oazE%`YNEL2!Vmg2Nb1KN=gPQW!!)sA0XHP%~mp2)`+ZRmj`Y@ zMi>E90i5Z%nfdt}UX0ld4auM?l2uoiR8oqz-~+ndAPNH^CGe%$_E2(AJP;rb&l1D~ z=Inr$n%YFsVO&Cjq^T)A1qH>~K}7=vIk|^nl0)kqZ4eR1#>Rl=IIbI<9}FS~!2&>h z%BiYy={;m%U;rEC04z}uDZT;CJ^(cUryx5oj~omQsN(@VE4STdI$$1DOuXk=i{EH? zR%r*IY|TY&$@cRo)6Os{pxZYJ6!r3y3MpAw29cn2>UH zIe-E>h{s3A$5VSe01N|<55@%}Gc#t$H}U*ivXy-U1NF~O z_Te)Pz!HJRp#wBjG{8v{$R>j5EW!tz5BLq@C0_`@;OYXEQ^_QrSOA?f--U{U@N1$D z&-6fY)PAe(kTF&g3WXvdJ@WoOHw%c+xlGfu1OO-d-6aanFa_$nfN^LAlurTmMQ7bY zk1ZZ7EYJaE@F9n}8=xRYqZ6?aB%cEJRVmT)?Vr)+2MD)DP{V`r00K%BAhigm)PU>& zib8~0PzERPIE39Mv3CQ)z}rA&Zb*6BjKf3s9{rAeop?B9F(56&!4q)cbZ;VeM|U^t zi&!w!?j6xW*-5`Tz^bYib4!y=wt- zd7zj^(Df|>Lk7MMtXq3|ae8!gMDVh9$`2^nAI`Y)!QroPx+XwO0>mzyCoCs7P&BeW z(*Q4f!$7V9#gQq;^w3ZX5J3i~bZ)-IA3^X2bHzjth%a!x*_@oWqvwG@s~N~BFN0-N zMp01+*fTs4gL($6@c?R<(R7jn%&0!TOP;#AI#5dhfGAL&W&G#`aEPGNkg>9YgPYe_88(L ztpL;#kmIV%=Wc+c2WqT9ko4f21|(yEF)c4=gM*y4wH;YBWdnGE#QiMEc+Twp|SrX@(l(pfnEEzEkc zognfbY|X&c*8!R7s5JY~knoaYhz2BUy`l4KX12FyI#PD8ATxeO7rw- z#@DYyclru|IAjml#@%l~%@yQq=fj#AIEow;;8j-3zqYp6pVWbU1{lVI;_tEP%t}a`c__o&!}$X(?iWo82}c5UPij>mpS+|B)Y{;Vd>><7TJHipEkK z8inc){F&ZM*@9rSwHlKw+HkhWV8QY5>|~^Yq?B`gq5@8^2e?qsg1Ny^yWR9On)Y`= zffd>(ZSys<9p#Okbs%_ft}g?S)Ip6R2;^-6COzQBANq`;P6;n)s&t6}vtx}0&VLWw z$NlZ2LeP5w*|ktphBS6X-9HGXKJCAL#2H>|NP$0?S4D6oRE*z=I*}YU$NcLZE(Mz3 zr8IaaO*-XYxYB@XEKfP#aBPvkzN*{eQtftjX-s_XUY#FNtMx7Cpr7J9oq9q??xdWk=y&*V_PZZy z8OJ0hf%s%ZEZzC8j@+jCreGEpzq0kif*)=&gMZ7U{w;v$ED%V&93n%{43Hw3)d=hd zB^v8IL~SKmq-4XW+vS+cH;2^@v?&*h(aBLG9%hZ!J8)<5h(qa>8wbQtIq0o+UND%l z{D9GzHq%CVUfO)m`o;gp=ixPRh@Uyn;FPm zWG85Dg7-2>_50b8dz;lkKK|Hn%}1^LzSi|}+1+003zq@E?+Y^Kdq`g{8+9R$Hdaqu z@%0M;AY-Rg&l~L^K}2zruVEeeM3veBM!{=hHM<)Kp)n*hCVfdhiuz5uquiD1@=M|- zuWJ*fezD%-UCY$&ABGgJgAKYL%*khxNdr!G5Y=W*eOjZ8In-zQc!OeJDwUcTq-#F8 zu6VJqsv3QEJ&Kh@wzS@?)N^AeG=*i1eR7!KbRtWxl{)}qWnoo92ri77`U?dWw<8p${R>%YzU)AX5*<977 zT=U~&LsxIk^P189Xfe4YEwNFXsmk>sg$l3I?YunkosCw-a__UmiQ?wVPc1ln6Tu>X z7@D^VF5fIG%d}n$#~Oe7H2FmNXgxc7k>pKMNK=f|{9&!UWpGxWX4U2Qo!EMTe%We3GMs#=dY^@8*TNL71_4d>8 zjU(repZb&A@3;J#q91^dj3CW zYO5Gb#!oWc#x5cRr5VOH%HHL8zRRsIu4DlxP47)k zdTgaR-9i}Yrl&>=MmJ5qSWLG@A6!oM9$*xP?rIJ1PLVn%?_*HSyNZ55tlTnj{=-=a zZ9EzkKpKWaC)V6?sUuFDflqFv3^`vm=K*MhwdtK<>EF`@&nw{DuGCMME8tnR-WP`+ zA*d_mmsQrH9I_)_=()b7p}3?Ceji`RblDi2E_Af8YLap>@N7Pcw{?TLuc)1oL%GRa z_l=(L?QcWIxlY)>2Orw^>Fyg|!-8iCOWzuu*Aq><-9sVIi{kVT&#gl1d|}5+7)>J?kumW>Y-S-0l-r!Of?8Ht zSlcpzs~umm$PXL$ae;B&#-*oQ) zuGbQvV|4w~o-I%Pzvovjn3&9-Jr4l?1%Wk3oZ7mG(|kHI0?2{y1)U;%o=lR+1^3iw;>0SfqOlh@w^ ze%*5vl~H{FF0TiWQ1EYJCkYKF6S@!>{sv1!>w%okkOU!Kw3=V2h?zJ|#+R?`xm7&b>c1{M zFZ2}gzb?oW9)DQqKiAJv2B*h=y&}dy z9^&e4Io)5+vLJWkNfBIp+Db- z4Q^x=6-DIcnsi2l?GOrLF*t46rFB@4OR1`k;WH@z{qbUJ$t?D0{HmHN_D-^4SHx?Q z&7FfsI5_tE(rJNfdNTTvacut*x;xcTN%JmX@TS`2QY30StqXzpA?W0Df}~FVtyp z(SV&@`J{TEXr}sHY#Q8`EGjCx?DD-t^}Rk!3sJ*vUGGmihuQk}u11LrklHrd4_~GE zT$rbN9mpUJB)@1c@i}I^2Jf<+ay}x-cjO{j@IhE#AM4$GQpr=)nb_A`J7xK2iX0@( zb{Vmg+c3`h4F@p)WJP)`EG#Ey=QmnfJ#e2>0T=j!&=ULk`T6BKZ_D!0=BW3Uxw$#9 zix4U{#oD~<;{7L2pWaXEcNsR~7Z5-eadmZ#a^pKVcjTH0c8Ksu;dlNJ8Tk;5%Td!? z#}cmd&&=1fOi5sOC85J+Yh_&&?c2wX2?!(|9XTT+BF?;;??mMn6tw?x(24O7zB*Dt z+HFSIkUi|e-&|Gpz9x&P&UlxlyNFmg{aR8&FD!greo;TM(C`mhepcD2iscm-v*`L> zIrsGT?jx>f>F5sHDX*ikh0osCEObeJcBTn`Y({7UY_Uw=%DMbcw zl?46T^z~16rVHQIJ&x`E5lJrajEO0`u8ufs_~*`a#lA;V+^0_lJV~1MP7Iownn;4D zbB?v|SZ+i1Qek_t#PsUo7y^OV4GNvUE8WdY^+10w0B?*nAI-h`($`^v15sORp37Vifr3?p$4=M%mrie0aWy=Lr+ipva9Nl3YBKLB|JtRdw}`pFf9; zZbB~4_UBw?t>x2%y`?v5a&m&ONO{1EWi&L1z;Ga@rYdS`9gc%SQXU@sb#--M$RU%u zo)J=%-f=Rqbo;h9C$=ES`)jdECoiO=q9}|AKt0O>gKgPy_`>8lMK8jo}V}l_c#HL*a z1_s`{#W28Al+el4`^jgltWoVD*rOvO{@sw3X2fpR*RP>b!WW@Z6z+iu2}BdcI=!2t zdG-zSfgvFkknWGI@U{%G5H|#@#@xaJ0M1|&-p`aHQCdbOqoEheeh0>(?(|y=r@JotKjnlb9&u zL2+ctHCQ2I!V zir%H7qDtnozxx}l4+-G#c8>ryp?&)F7^9Pfl=OxB0qvVNZ~7A0k@H5ods$n;yH+!@ zvH}Qo-Tah<&jZKCRC5(mWOa1r?^`mnu$TZ~Cdku)puKSV{ivk*;yFry-*~}WBaXzg zZM~ZwF!~qvEB6-9I(b7QBPsSsKE=fiO-)J5%A)V@?}wA}7AyItq@;i_8?q7A?$&Sr z-r6!;?Ti2;^xxgJnJChhl9R*GL(EJj2)c8Cfn8agAg&tER-j~jc1TJ6l3+qHF)@Tq z5C0AqeijM8v#TreBT~{{=9;#D$1m|IB^>r7Llt>CBM|AWv`lf7g7*15hRy} z6vS>rRAC|0rH=?VH#Z1SOibI>ctLkxADLYmSi4VPO0fV|Zq^5D-D~UX4&b#&uhrCo zW??3SsX{+~{D@9U>h(UI59u&mZuLV(u5N;KKUOc%?e9zEWO)Ak`}T3U#rSidvvx{{ zE^^nU!}H+E+~K@5AFz<*6{dsh86gxarXmPpuzG;A4Y)`Wg}wRv`}+YnBPoQ?UphNG zKVgznP#`}d11#yCos%=XurL4+{=#AH0SpFXdRH6W0B`mjI-De}pZA0}%{fo%fbE=e z8#A!03=Iu6$_(!-=EVYRfdKY=55hnk-<(@QxJbJD`+s$bT-&z{<$s>H*+4Ab_$-mA zsjIJ?BKFU{?xCVO&O1-;U%`EE{8bLrR8?PVYs-Q7iQJqIx-a>mYLx1?y@$W~i;4?O zRP!daYwf7gybjPBT;V40g(fE5#ssjC_yKKfYdoFd!~xxq`Xw#7CK`3HG49-@QSrzt zZ+Ps1*!lfCy{Za7ZBR-~47ug{xC9x2d3*(ea)-@+MLeB8S>WcljfQdUlmfrTZvtSknQ1z0p$X|M+o9pS{BDDO{BTTAMp zSaVN>#wR8|CM5jqj->~S<&KGhJU>4V5?ib1k(=OEWKe4Q7T_8`hC3=MD(oZ?jW^c_ zz?r31)8(y4_AU)q{u_sf10pRlGBQAexa>^5($*#gm_nxDb=lE)$3h4&<(l?JhMk=q z$!ew&4J^O7_&wW}D;|)Y1A~IFHc50oEG!0`A8y?8mGIdTGLP+oypNACSQGCP7#6PQ zVBSCZGW3Z1TgE6rp_GCG7TC0Y!%~1-{g8|hC$O=}NynY3GM}!Av9VGY*i7q~9q*i7 zd#Od)EDY&32h7Z9bw-l+)-)d%`5^EJ2@iW1OZ01IWdQh{V0qEek3b09udfj9s}a1R z5fM3nobF=~93_6SeR8Y%95KY9FFJI1X!w3j~E;j7j zx98P1^F1pa&_p(ayHB4!y-m1WJUjsM$SU7K5Tn6b4`)f$0Y;KmRHWnLimR^XDK9T) zIlt`q@x$(P-t};|0bXvqDEz&>-47#btEaDT?ME1H8+SCI|WU%!6ca+Rx;Hc)H7`izCGc2kAI>ikC3u`1ts3j!92{qF$uc5r~EhSa!W(@ruR3 zz<^B9?NQ039AL=h%X>1Pa0WmT0<<@~MO0EmtOWTmXG-kHd0%0guEPFh|bQ{-YeDuK_Q z8Vn_zQX~~botMpcq307LNLx8TU@tA{gO34lq&GFCfPwlPWl_e&$9DoKqoJd(RL|OM zR|t>H)j8g|<$tzB`Rwd$Bq2*Wok$=J_E>KYSOu?+Mu7%FPE#;Mx~P_H@>j&@TI*yJ3c=CEhEm_ zG!!lR01%*3dPNg+nk+f-zwkIR)1Q(2XMJ(*h&61>-_)%OcWEw)8ybGcXO(Q8O7+-c zC{$+zk4A}H6QvDy8AS;ZB#bEiLw(}SWZAABn)08~0< z#RCW-xAm{OW{puaBR2d2(1c397o)>0Vt>6$viocC=6}^hdJq4vMHSDt43*L4qBU4C z`MygEYR$(M)3w>AcU28~rt=e9|N4IL4~cVxJD$3`R73Qe;Ywe|psu+k%SFGWY5ix;TN?(#^%xAHoeylgp5LEc%)aee5 z45G=}kM)jAt#{eN!HIcww)N~PJ^H|7@b|bKb((4F8S6o$4n*WF^DoLt4#T>kL~5SG z#kM?VB#PvaL$|Ax4{{Ak(0>!tPwsyB>FOy$v&sU0dV1PTkm8oYq@=n^XIVgo-rR9_ z(bLl#1S*Lyd$qoy0f_w1e$K z)C@H}eaO_*RIl*cw*lsr7`2dfwnE(1y>N^M{;N7U&C@ad4?03obMo=hnXr7wT&4e0 zPU;dxENbe5al^1qp0?m|jx(Eq%t?&~-XN*#=}7M>J(_*xt0-pGA1v$pngp$)6Fuj6 z&9$HAd0+f2e^}%F2dl)-Yi9ca8RnOibiq$?ad6ri-48=Qd?49x?la*8#XW!=;ng2NEz~ zx59Z_U0GQ<6bfx96b2%Kh}VV;lxh&bU!TW2&CXVW6eR_qyPkW`U4D1|Lg_j{tsB3S zT1^*;Pgr^$H8|pS!>TE?O09Gca4L(MJe{Rayt^}EhbhahC24GybF=@md>BTe$TG3Z zuKmZVITz>cKNCAgp9NZ*A}XWq0t{(xYfI@O@OJcTh~mPGsIG?v zvKkgeANxZBpFN6HW|k;4=(yzfNp%M}htwb%pNiu3h1UnhluD8; zd!~2YI=w10*8C$Yzc1jX&(6O3ClhZbAf4uEPwx%b^jK;eSWzd|6q)=g z#PDTqblE;EoL84nq1Px3gZMadGn#7I!#q-NE|Y>9u7y6=ZQPxoalL_>%9$Sg%wjAh zogdrnp|SO3P*ZqhtYo^mMaE&I@E$r+qifXLW|7QnQ_82YAB(C9d2YN)>b_H8^BosY z#!2!a_F_zACI?Q8uFdo6X2pd_4vTq{!hN1T9lLA#GySyv0ilwLvh?sTD1^J|(jzTb z&*~1TSv_p+)1J}7`|rvsaV>ZHJByNS))X52>XSBmwv?C$l|IkYD>HmtD?G4K#p|j( zyo3Uc7_$|Ax!ag}-IP~z(3hosCp7uyNlVk{9bNhkchYHPWeKCt_h-X9*5>L$?_mt- zzPh&b&8w{srsLJ1gY36vF@_a9&znnnshGy9GL?{MVsyA1!1sCf_0Au9ba1Y$uKoy0 zI-+T(>j!xtSAT#)&8@6xK^YkyjtOL<>##K;*dD_hi$G$7l$1^%$M3R3l&6#iDx||< zDato0Dgnc0kd+@{pwNDVhsR}x0NnlY<6{d8i`%3GiY}l%rcytDMr{R}5{Szs%9}G( zz$BoGi9B8KjLKKZTe0KYa}(T|t-;P44eN$bKYR8d309FuAQefLk(qg0(d5b}ih?2< z37d0nm zEWrBh+-z;>LApz_sYiq6Y@Ex&kNnjOK7ozyKD1q7)b;R7QW7u~_{bib3?zrO>Hl`s zDR$1H;9q7p(u-@)B*Go=_NBjJWqo|9)B@?I-Q#0?CP3Vg*L|gdN~@l{(*YzO^YQ1 zNke!tBDRbVI(0U|uUjEJfP9FOAUtSB)pyq^Mf=x^(;e0;b5f>0DpxhyVq{;_cE;_{ zFK28}x+9S}es3y9`bF8e>4=JFQCKC`PgpkZtSdU|Z!f&+U{4UhYE@8hril*}-;uO~ zd8UY57R4Od7A>nMg(xk~wr=}Y>w9`VMdMQTt|fC_fz2fmhvbinjq&kHY)_Px2tdcN zO&%#QDn=>z#fHAaPvW&*-&<}coI44iyj;o@i!O=J{r=hA+>s_-D za}Lz2lUFTH*`QCqAKS!`yPk^fF^h|>`LnfOga>BwT9O0UxsRrGdIyfrRrv(;*Ee>B z790-rn9~_xEEKg}!FBUto;#*72@G_x+;z}WV!u7JR)zD<&u*~Md+KxNkI+wR%L%e^h&672q^Tm{xa{#utx3~9u39>+iX@(=57IlR4pcxf=jxALn40|M+2xIZ_@33k7SsDN+LJuuK|ShlwuLOC)qF#-1`=d*hc^kHmr zGDy&<85tRV)))j#tu{4AY(y*`-dkH+KYMx%K^f6rtA*U4HMk`yd=Czw6 zQk;3>uMWQq-c29D!s9x!VTEiYsyg^o2RdOy6Ls}u_;BQMrxcOww32#;_>#T$K{ zE+_hNMdAug6gJtQLgoGpDhQnOA(XCr2=st%v%Fn$R zvXLGIdrR_1%A|3t%#Yn$Efn`{z9}0Pcb*(_LaA*fWcVW&A!|8#dAP*HGVbm#K)H2m zFNL(f0@e=jo|rVt?_~{3TUb1&^u1&U{xpy%*tIZ+34aS48xvp#op}iZcmsga($gb9 zBA!0PPha(phd}_w!y5nZQ+e>4sO+4OT^vJ4h_0aJ6r13^`QbNV< zYv7FSR9RYaW<6(2P&dJz`fJA-sN**0rQx=F|GB(|_U0*OdB~^m9Vc`>AVZFc=MtJi zgDSX2WW!RUcMx)6Z#~$fWB;m@}}QxzgdA`*jcnwP@E5 z`_Rdw6|&_^Ay3ETh8*Atmi6{p>)|BA1cqY_@Z*5}1q>p(XU{^x@&nNgEK(JHy_Utn z=?WlXwn*$|e+4Q62LU()Sip$_$`yGT?I?UVKR>^1bzh&2D1pPcC*AsZ;sj{%BX=P> zllQ2n$RG#%tYo;F3r7^cxn_lY<^bBk!r@YZrjcvrgw z4F?)^h!rLqJH@#{aS;|ycrla`rBXTnb#;bX_|N>~u3GMH{JO!f8|H2IE#Mn$txxV+DRzq3&G z$^Y#&lw6|b@aL7L2I_-NadAmyc>hj6?;RRQc-Aev`(o}>Q|QizJAAnxKzNGROMrPxd(a3 zF4jQEnkIm&%Ss`CPtVhr{g0pH_4G$)=VMCBD9|UEsWbnqEuJ#X`##-4xNS32?}}*xd1<&V`& zYR*^T3%M0Ah^*7~P;_-1ioKU!G0d`~EJ*iwZ>z7}rJa!z|Lu1g zquwqbVNHqO$mT-IR~GaRek#0Cg)?RLpc>$V-QuRE^yK8^pp#0cl-lQqjA~|M(+P7y&2{HY z>c4e@LF)$Odoye6oQjIr@83oF`8`rSypD#Y#>U4D*oeSZ0`5&%vN8QJ&Of|M`|trBG~ZY^6Bw@wZN^$^cC7O=cBE+ulyLC{4jHUm?GWDs zsVLK;n;vvEM-(C|!g4UkHTrEVv>N@K>6!91A%QJF7WEcF&*Kxt>nx{F^GOGaI*h-R zMKf(5TKTw>=jISk(X`DEeR%OSHVz~5N%=?TjUqBHx+tt!jJ(m!RpP&B?XyG6w*JB_@`?Uz*D5Js+>YxO+I}xBrBO4aOuiZ zn#1{}PpxUS$f|G9rPT2XMVDg3WSNVRAPPFeLJD2StW=Io+7d#Tk&{YQ-X~#9vLnq3 z9l7+NrrwzP+4v%byrgkJ?u|`+t_J%X8J>A?7Gd!AEP%86(Aw1wihJ4M8Ajby(^KPD zDAi5(8!sjC7+Xx*Ro=?GA0jQL?u{!qwue1!lf)}hP2NJ1duH%5Tj(LQAkg0*5*m;@ zV8&r;QffCrpnE;5#p6N9&N<;f`77Jm3MDZNc@Zgd6_z0KHDdy+`q0I3Vr(gq4WnU~ z{EzefRsp2(+X4q50+9HQivS>JfFR(OK4W27zdBvKbtWh&l_VuQ(`Ny9eJ$uu;ss49 z1!?IApihYWlt`xr969df!G%T#APjgK1w}GG> z1r5ntRDf%YAe zvWg05gQ2)<@pK)0HjQ>Z!oBba>K?OKO5P$RUmbD7UJPV&#U7NUv zi*x=Rnp_ba;^l5N_pxh+d^Z&_94Nl7J$Qv<9|Is*KhsYn7 zM=*AFcH|aZ7;+Vo2p)U{)hE|Ojm2!4*aR+f<)y`qNkfiA6if}^xraqX!4GG?sTJH6 zVbyCE+;e>W`cZ{Rzag-(v+P8DLFLzVphFMII6!0#uiF-CKKcZH!H2zEs4fP5;dp>oR#yae_ZR@VTV1~tT zpj>v%pv&JB+C|y(9o>#8ieB$4-S%hfir*s>$A20FF_x-;J#Cwg2|(Kew5Ow_rH_rB z_Lg2fXJiCs0BD4B8g*gR z?-mLAG&3t1Wrpsft&ui0dJ+z_0MSFLQ_gK|e6eL5|7Sg)$#lTc`b3bxEDWDBKe zJHB0cKn(i;1my>_{G3{SRBnah)Xj?>2BwBnZAj$FQQicT&5b(auML|R^)3zv8~Jne z%d-ERQleRAF>MrUV-9#VnQACz|blJPiAe*TvPV3bEu-a@ z-x&9gyT(w5Yp?aLH=cLSXFhYjp>i^x(O$fM0RsbrCN3td00V>A1Oo%h_#6?q!+%p~ z1^k2HASkZ%9JoB68-)P>CvX%|b5yi3adgqQH-<5_wy`p1a4@ttHnw*7V&ixM-^LF- z#Av3Z<|t%utnX-MV@;-HW@QZAgn{|>ecYFfnUich;8)GBDl%4P*7syA>^$$ec$m3z zT(sL@V8~#^g+D2|rXMbQIVx?pfFE3_u{&j0;icfP(_xUA+Yyj43K8B+=yklSEeuwx zpYC+c!X0fm0 z(SAl^Cb6gkhf>}?2!fr8uFw5`@7Aa!rf7NS&eniQ(n}x%;01YxjyxIRrx)Uzp@dA| zkSAAvkHQ=k`IE~(v6B(&$wlz91fE@v%W~p1kEo_c@~8|SwbYX)w}vR+y$hRr!_rM4 z6dJnM7GnOfv&?pG>x&|0upz=|00KQOPJHN-4|=8ulVhc(rJdeIu^J?ouELeWA~$IW z_1SWX>eVeG8E`%MHde!+8hzq%NkMKyiarZ6WYVVXVj{TqiWwOh!lwW9L4xL&FJFGK zzyNFdz`t~Ma&|V~6MXu6he749`T2Pt$fc(2lfjac!%OKWJ?UKts>X|^C&Lpq`gJ=I zq`hwYz;|6Dkeufx(u;-wx4i1&>^!lw^&0bOs>{jw z`GHAUfsr^_emC(?%D`^|&`p8sP0|Nf@pD+UHgCSR`)ww-t(ecQd$~!sOV9xt(AH@m zDN%jSZ zr6H0{%Ox%hNfc84H~XyRS3;-0XrT7ZxNG6(>c$In@w9 z{W4y{rG%_rMU@);{h_Hq*L&%WjSVjMi??WKXu{+%)yEFMf4%wIv1Xhy*6MW!Q-4s_ zWZSfyWE_Fw^uJq=dbo}v;54F6|jp7Ln>6~!$r88sHO3hL_OrlvGz zW@bwsCoRo)$4$*w3l>Y>cSpk+ACmBNJ!7h>SiNs2K`%*3G1^T*UcK2-{1Qq^uh>k6 z$v8Rjil+zjq|@Hg(ysp=&sL+yH5pF!GfO>OX-P{?#>ZvQ5O#LvfN6VxoFF6m^WJR5 zEjzg1Y$v$^e+Gt!x0+TV#{|2OZfsc?+dg6!X0r)On5&c3u`UdO;a}f{)GPF0xw*NQ z`_z<_y8B3dq=4^Mn~WHoZuF>?wlFPM8ur1sUd@}rs@2=R3CCkHd4NJ*;o@$b-{5oG zQ`W7x)5X!q@|T}4&drH^`UHCiKA~Y`j66KF+!+JODl6kW_G_TOUvIw3*z->ZQi*zX zP%w#mh(%dLkk4J6Pc|?`z*n1Rxo| zqvLyB$i8aBUS8VhfyO^D2J(uTi{ZBj^sV@lAbi`3_$Mg z?Nv}v=v=gEL;GlD#qc?j=nXr20v3fRFj=G(4!bhcQpq1RH3`d`&t3pOa$B?kI5ILe zX0hAouC`|Lx^=9os&Z#w|5BrI>dNcr=qRVA)(>C^vAwvwbr8VYXM1~A^kDyu4TG@o z@UaCj(D#ACL4)CBmiO=9|5N*GZx4&0t~yZ{DFqhRr?!D9bM# z*9*sk(z-K$(t8+~q@f-@@RAU)6EiY0reYN|Cl(gJI@ zEI|0dnf|er1KkH67-ePU0Kqr>*K6>xv9W5kmIUA>2aF*73aiE1>Z=ypbwQww!JlT6 zZy6YR-b-6I9dR7DfOV|fAkO45{ce2K=Buq~@2roT&t<4(Glw(zJib_2QPI+d_JreYp5MHsr+-B6a2n^y&r{hJ zQQYuA3_c<`R_y0#L5g55fG>Qnak5m%H7ueo0-SESj2{$Ov$NcGf8a9EYWo7e!{P=oyW)GnG(Ru)` zkcxw&wyA}wD+mof3z#GTV7|wYvE0H!WUdCHE#zk)8xO=%HQ(+R->+l%ka2UT08_4~;lQgt0suamFD4`{=PLYwCDy}7{DtFvvAx#epPU!kwa!&~BrIlct~N10@3v4& zBbYifGgBSOZqy&mU$@8I8!FdhQXK;VMfFT5hq!FCd2!oG0T{^1&3)YTzQ=>P091H* zctV89m;3P1gJl=-8sVx8`y!o~T9Pv}BYOZHk(j z;mg)1Wwl|Ek;mvVD}Yf23}UArJd(^}U2ScmaF5~&S?*xU4vFmem>}YUZ=9MayXqkE=mBJoTTF(y0vAbp{dyby*=+E1$Z2iV@%356 zYxc0C#k%vm)rZWWAVdKAO-U<~Vq#pfdx=QsZ8FK z2k6Oz$#SF9*6uE7mc3D~FOqoErR|Q`us324ef&puw(O!cUJ|rvhBg}knv~NJLBJLS*zSYw?(PbU*|KBf1NYPq zE{trZqd7G-2`wIAz+)_#wz(|XA#pC*!UH`v1RpQIXJ^k~k>ZX6e6aU*7b&az#h0Su zVgi6)2hhb0IG^$H@g?_z z(w0mgc8eK$n6j2DjS>|)fF=HRr=IBnSOfLL8Ph{2KyC-_Z_fSVBtKs{0=_*C@an++ zpKtNt1o=R@fmR%yozDj8$}tHEhekM8hk@qpnwH~}k`$Gdopfe@3)cMn2_vVY6FGZe z49xH2H}kDbYc$j=4W23HNp%2(1K=IbOi@oK8IP%mYR>UC)e|!8(k-i@vA<0sir7Gt z=?WLz%=7HKh4E_GLaLgmVC0ugj<(hIX?|~`m=H? z{`CMNL!kB(xRA4cp*?*0Pm@?NpDg5pwV~RCv`ZSZCy-lb%bef-&=au1w3YVI{g^~FW=gZOvS558BO|@{>aw%p+g4X0w*VPV-sxGgxHi~x^9G-+$^!KB*|TR#%F5au z>e?j!Jcnmi9>K8^q<9yJR_9g6r@DU@>%2_o+jEYyFD>WJs1PZfP&(iZ0Ug)fJxAsc@rkMD6S-VX1oWw_4v0E_;8q^7I zx(LO@IZ2drqx95S2J>*{M@}C&;jfkn&a|$#RIFnEJ;Pg7dxwWc$4d=c+uN`eZs#WG zB)qNz5E3AE08BjT?-#Bd)=OfVnu~5n9#n#r06mr0&~P8M0;~rUEow=5`R=mID%HzS z7-sK#*R!)TF&UY>>gw|!cP$#~)~6Ux zklFbbuFloN!R&wutPxf34yAECF~!c(;*G>?#XbcF#{E*@LF|KPPtNUwb$eQ~@8>+i zq=k8LQSwoF8KT|EZJOenp7U)}^b>j+dlJ{=XS;6J6tvJBUn46n_v9Wm!1Rm{Oe0=;6>k42M=9=Bu9-RbmA7CT^<(2mE_yBCRNAC%c zGhPx5d3kvVKlJKo5g-hJVXj`i<4=;$76tr#g@bjq-KHon$(RV}4zLlA4m*W>63#<;OwoS)+dyrHUsgMPA z%j*$NZY~LrE@!Y?kvNF*_3U7H8m%5S{}%dtYu!}M)!C2&Y;`z=4XKOyi@7;DKR>kU zn`zx*ihvKlot<_MEkH?s*43SVv+;xv?-3-!%ql5~sI9FXdMTDs;Qsmx5E&dgq(PGx zf!X?EX4bIfjp+Z0)H%h8s>Jh$Z_zC?i@5cU*SQR?>`_rNE5@tp#)|kNe>8-ywPY{O zs3mK;i*7chF`xLm>ZV$h<97xls~nr97}#;~L6h&_l=hK*Vj`TysoIO<`KnJB)Fr;J zYTs~2?J|pOS(Nj8n|u&__gw9z-Pq9fXd2%|$s((0lQ`c>zK8jXqlcSUJ*4gfX|aAd z&yNmN>p(TeU7(yrwT+DePQD45Ii}V#7$~lIp*fXnHffih6tx zHXaV+Ydz9zTi**a?2l2h#1}~l7+fzbK1f!+4nDm1P^~OhfEf4 z?=7EC$ID%tv*56M3*vK$=0=}hdfMmDKliGL?OUm+zOT%!XTZGA31Kg{?$soP>k_}^ zOsckYo;3|{bES~w`-ug!n2vLQhR&JHKZr70sqcY?zs|LqWM>`wjePgef^J!N+i!UlqhMO?OVq#w zZ$T{hzIs$#ues8{ukQX^zGF z`oiZwMf8x_H6wuw;+8LYIK6a;X(sb{)Y~kOTGKM#9{+8Bx$8cX`F5?7(b6Jkss1uf zrCzMF$*--&1#|xbyP0#z*1_vl;2Exh@rNf{Xyh2bAlDaEefR~Ol z>CZTa-Io)a(t?$=YG%J%9y-V~9~4=3E_$|Bce+c!3XL5eReTDc#~;+i?I`_wTy{2C z1zlHlBu~8s^xMr<6fb;KN@nXH}|uPoEE&f{arH!#}0N{v_2!xv*uS zd$=P`PU@>#v_zLv0T$_E_B(0<=Xb*{v3)G}IAU^+4oK2Fl9=K! ze`5sh1$4g~5|_?j+<8yMRAKK0zlU;SbgD+@2g$YMT0C#Q^>eU%!E&M`KZ`gzH^dqF zAA-=2*8$J~KwCmdNJx-MX7+m{6y#WEwc45iI2b@BdX4~Rxzd~h_zOU59i4Zkh4X^} z4D_6(Hdqqi)8aBR)BuVev_Xj36|^8Da@(Kwbg@ zFc?f691#Np1F%E0yZ7qURDeGIFh~Go%Oz!LNpEayY|3{Gv}C{4j|J#oQTq6gs>yp! zP7p^M5YRt5Ick}7F$)Vipn0%30Adkg5s`5~b4_H>wB^YFq@73Ncm};Ysdhaz zfB_<_M|}@)n{7D`-W;lTEscOfP*<#0OXowOTT6)-vshNNT-Y#PKk9o}@d$wjzvnEZ z$uxesN9^oY7q5^M-{rqLzzuE2=5&=T;9Id)Y3%rx%Msy~(Jokv<@vcOTu{u%C8s33;s>;=nn-b4dMb+ANVK!LaQqUh z^WPxF7!{6@#TKiJkVEgPfUrg_1#K9W!_Bu&EX4BinaE-jN5?L<2Ga9nfXZGHoFK~^=zig4N^ z!QXx;J`iO~a(yHN4C_}yFg{`Wt&c(Yw{9a-)wySw^x4PSjSp(3FZ{noK(28a>>U35}@DM7(b?nTC4fKG{0 zz63G@kHVB{>lu#k@isavAYsi{o63T`lvP#P0A29-MZwRX?*ZgY6`z&tp11c#k^1zW zz#14DvY=)+o$YJ&wE(hASsT=yD6-7so`uEK8>V5}{0O~c)N$;fd+9YHp_#R{$$DoX z5aI)p9iS=80y}B$$QcIMMvc2Ot7TUnPX7Fd`#l@vRwbWK^+`W1?b_LX@(dQjH=K+_ z($2RiD5g04!_2aGc=SCwYB~zaR_wu1e~*wwcNmteRB~$yy%E+diHk@}s&Qo zAEjOs*+-(`V*l`*>nkkRk5)%*bS};j>w-tHMhdMeg?vr(=X3j(C+D&utf4CK=ILcTMHal9YMvDB}oscA0G&-!%yv z>7f$y#M}7XE#6<2`{cH^w%&EIQBY)`WRzC`5JD&{MbV2mC&FmF)ia9b%THGJxslCW z$msc+PMFNTL!ZzE)5?RM@~L_3A$>vz%^L1|^$D&uivRQiWZq0_pj{dk$3xmg8l&Cwo1I-F`dLF=|!1BS@Ay7Lns_Rlkp*4}iw#`?q6hC>nXX@|h z%HCQgA3J|ioD5SBheIDTm z12WO0z6z)pfSlUhd({#l`Sz6o5LN?e0>a-fzQ`cRC2eT+Ew8LZnx!t|nC-Fxa#gL( z>L{U2^Cu0B*ML9mGT??FN=izi0KU5!2z{3Y4gjHauF`N>e|FokX0`avAW$2I7}6Bw zc28hyI;z!yfX@+rPs+GYoUDFC141*X+|cnPZBR6LZb_%7Y?myLt>7LgI#Vd=x|Y@g z-FLu~2YKNIEu-0vKl%$Ar@;-2W;eec0v@p>O2)5mw%E&S#( z?@pa3d$*sZJA=ZpW@LCb#!jc!dO_?oyiH$m?SH7Bkru_QzNqC;V7!u-p6UcxfBF>Ycrj_$5zLFaxh-sTBec$J}(VR=Gn~ zaD(|sxFpwbunFNAsHyvWxS4s4WWIh4TTb4DKP;$>I~`GixldE6c4sqU8lagprfJTP zPOwQoIfWtCM?6%;oTQ9Mc%$3A>iT!Y$4J+-9ND+|y}3CZ$kEW_qM+c?b1}T#KRo2M zSnLUlilX6Z1dqhYy%h!oA0YigNlguGVj;kRfV|KEfZA>LvbddXO)k*mN`hGf@%BAO z#oxZ#KTk0L)S<_$5#Zh)wS7-dUThkfZi7n9P+@oCU_e5sU9>*HfkDqHzR_96qpM;r zF671RJeK%=()_AjRH7>57cA4XshhwDQJ$>I$fC8B#fHGlqlT$)jNzE+}^15iXv zVSSn1x_Y|ov8zCj5ABb}QVaA^c@8NMs3O~iH1e9nWhb&NUkEfij(I@6n}@1UZnyCo zBv?Mo;fAhWhBzotq~~JHFj_d-D9BkHCojHs{;UF=zWWxbmcP@cxJ&w~PUTNOxH@FM zDWx=ctfeJH%;zOx za!fpIc&olIN9@;cV;Rt<*n2NYJmQbi6B;7dou6NO(C2=MKE=T}WXR8PL{g?OiDAzx z?omDP2U;0)+>~&Rl^Qav@+DPY78Jqovc3rv2)uxO3_cFFl z0c?QF@i!&|1H*d`4h3c9z!8&2-U(#Is;m|{B1!lpfMwAcJ=U^<6joPP-xZraN6?mp zt*xmUUswq1F?dYk&doh%58NgCQPtr$vHJnds^aCKSoOtpR8zuwIQ|BuJPTuIp zRZb<)>;#eXB`$;a^Hli%tpyOA;z(T{yJViI9*EE#NMkCY*g2T22;P6Yi1&4K%(Yr3 z<#X+(`b=BJ>w_OsS{%=(kwQ+5*0~LP;{6XlSnKyG2EJ;J8}R3BvNc`xJ@CIQfyO2D zI4sQ>2wr0dnLE#(%SE`tJJ>wSMOrrE&X`*qd^@k^HytOI?v{*sQSY}$#x^89PWa67 zizMYiE%v3c%+9b&_02Y%4nCH_3MG;#mzZ`_TzZPB$4k|aeT>29sIqUyeS;w0g18@? zOAX(W+sgn{*R^b{`$nFHso97IOefPBJXpxGSGe&0>?dw>FS+1^|BQQ@UDx%MI*FZ095w(lG ztU={ysZUI}!VKp{FR{|O-w}Zd+V88?D(d=|*Czfc*sH&o|GTZkWA+3frDO55ir2rhqwx9M-vdg2E|6;lsOk8`L?@tsrT{vvP!OvAQoS7! zuWR(>!7MhQe*!|OnWg0+db+!}5A`n3F~Ec6R8)FzFAoSSAq1;QsYOeNI$KwhSAo+eIf`Xg3 zCBN&z2l^~YaIJ_-pwd`u7%Xo=C+$lP!d!QA6A-#oEXA#Hb4@zt6OkN^s*OI;%0gDj zCCYVWRL%sCn`R|C2&rD(n^C+$B`Q4c2gSjv*qSnt8?L6kYEhKlalwmeo0ILxo94Ys zM6N{S`26CSBq6#sW!?ztMU@*#*e`X=a+q$sgh!iGQ6D|s^CrY8IyU9=jMS_;bU`4X z+@4LO$rC}EPE_FqK^>FvXoAm7dPx6tY57=?T?73?*}wuCp_(#Dr(HApp45^C~ zADwP2EFqeh*mUTshz*i>jto&;c33Vea*`cEc&@cw?c8)x7iNsCi7TI>gn@u6mKuwT zT|6Sv%Q-Pd;H*w#vQ}GW3|_&k&I5@xEg6|E(0Vb&lpM$;Zho+-k88e#<0$b++`v>r zBfJ_CV?t8RynxHmlHG3j?lWXy7$FBXL zTD7bf@eli?sBXuxf!simzcs%SAU){WyA91McHg(`7;IQz>;~#IZm#OuygJUq!@>-p z_czPs`7#-gVnma!Z0h?^@i^*?T3snAsd5NRS<`VNn>Pr^NiIMEXhlY%n~bK512To* zM_&fb+UVqDR}I}q@3{$m1W{g^_5Niw5cW^*cyu<5F3w-@wstTAs``{$1JWt+X2nip{Sj_71O z+x|yhUI8sTo$|H*>*h4tCF7p+s6thDgM8%a*>%qE-kr|lEq_~xrYOmem%C|H;RF*h*qOYb9!<>y`1+1dW@9<6)wbbC)PFgF%Z2lJL z8!Uk`5y#woW<8*g#95hd)*R@Nsz|$2!`s7s$$r_(KEk&jUXjfK+FfA8Qqw@o3mdo@ zT!FD_O`$n0f~6{YJeR|S%$Sgnba_MK?VhxPOQfd6GAFnCyxJC^tE}t)KSu#n zdI13>kUIZ}`mYi))k-l+Ag8Rl4ZSMdh%2Z(|4dDGR*c90f}^$pR2du%#k^qt~70SG11e021Sm~kmOZ6 zd<=T^^qpd1py;Mj$RLC*=q0w{QJXi?yMN_Yu=Z@=t0MlJ6ZtE8?BCA%Kk_rBKuuZ^ zh9?JR*Wcmgf1XQ<0HU5Jm(j2Pvv^KLNwT8wTtZgx$y35x25LZNfid59E{EMQ0w`b0 z$QZnM`aoGcFpmbo-I%7RRMdG7e&CM+c;$m4bg`7}=rN1(iqLT8b#|WX7%>0HW z)_wZ24C@GbBr(ck5e@@?*?;QkczDR+S)`aszZ*X0DzC4vVM#TgzT;l4ku44+QUUh$ zQ4zb#;N@+uu4LPVJ&w5r2AkvWUvzwEPv#VBPyhF??>}pT?@HT%o*}v;3;B+Y%KXT# zaeO+D{nL~@JgK9jquvKL05pF8X0n7$c{+bupWtH!iFsYWkOe($J%%X-Xmz3M2%aV4 z>EoUQU%WbCjSz*B@v6MG$dO(=Lr&Rs^~%-$WtS45!RU2n5>D##=N&iljxuW$Tf-bU z{hzn{aahUpXW6skkPMQGRdXVL(D;mwJ*dJqQD~QQ@l9ehM(1&Ry&@OR$f_8zK_U?bZW@C)}}taJL!Db`w}W4@P;^=qv2?ovGPGCiE; zaUhT#1+Sx|UJHP+VTL)d$yt^c({FDLl7k0n-8YE`ucomMnQbG-HWC*d2E^c`NO2BU zjfD2B_chuRx2O+lKdAHeI0t3k$2T`-?(30bA0a{+=-hUsnf#(dLvbuT$;~q9t#3@w z3r|0G=dgQ#nC2Z}v5*WnM_b#(zqKo=kj2OI*0vM}l z{^$16oLZ9GP|Q#>0#{MZ(<26xOG&D0zh7mX>P?k!Z81Tn&BW)nRD=)ruW?M@_3+3E zo_b>+z>vlAPDHa^{otZu&ehh`>log&6AG6qT9Sffvb@PJUm z#kB`s&sY{@0ojWYF7?r^-Yv#B_dYifq=B(TZ4j|-Ir$Lxj$s)6XDZLaACM@#(CB~}&n26SKH3@7 zN{g^h+gC5%ncIsKyX1lYt3Lv!r+?b`ek^4`+XNhH~bLUjs!<@j88@U=l)cIQ>QJ86+u>k zC7N}S(?0Y+-Wf#mc<_|5W%&COxQ0K-&mTNV^=|KVnBaa4$oq=53QbXSQP5=0Ex~%5C&Qa;C+SJBd%qtd> zr7o#`e#Sgkn~<%auMVyF->qs4eL(UUh2Mx>s{c%Q4Nj=o=`rx+i!A>^8#z^Iy%DJ* zcac9GkK`vuoRHvjE#A#GEtEPWz7cBtf&xtm;L-_W-9-21iWgOb&~$`b=2>P`A=XaOVA#b zPqOf9@iSRV+39U8eraP&+^wphjxi%n;EJj@VW1)fM~+#fHMIGl9d>fgCSX&XUu3m- zYS?p*fl=jI>u0m6c%N5r%sRX(J_sko{h1LFsSY1n5sIPneIk{f@>2kkV#w6-J*30DN&Dz`Y%IpyJi zk1#3?%D&0XOOW_f#!i4+wjv$m8XIDxd&EbhNGM%~2awZ42q7osCen(}`wl&iTL-4^ zMo#+4AE-abmcPqg+kREW=t>~)VQ*D!H1@izsJzjlYM_lXIB1q+x9)^PPL=R0_82tm z(sroj#z^k-dYr7hmg1*ef#6@Ko9FcEGEhhOhdfi)eFi3D520ZmdE@QDHxI`po5}{C zieQ*eN&jpJw1!%_q9a($H&Z;1v`pmtiBOjdcv6sop)sv7lwM{EhNrD6z!*gqdiV2N zg+7d5FCy2`i+@%jM9T}2@{l!Ru9fpOWkg|0y&+xUQcK3*_q&2{wNoQ!hM`?L&7piG^29m<*1xL97yvOWavw-PX6gA*@!0_n>$TT>8&6^-t@6Ok^o3x4{q5 zM-*)iE}=yvqR-V+WXIn#$|d}z(vilLq(E#}eSM5mq84lCt}PWD>bCI0O~sM}{<+*; z%EMG|_$z86{&R~-UFn`kp0D{zj0BY|FbJ>VcMs>qB&eKnaL7v$;91Rs6RE#;o!$$#<6HMt z5b0JiA7)?uNx5?wRTt~6z?>E-etW$o703L?lP#)5pSq=*)<0P-E7wnNaehoXDY=z{ ztFSb2zYE6suuHZXqom$it2gXU#nESbq&~#aUX9!tMNap#6(Q!S`~h2sL7#Wz*HSq$ zVSMHdCVFLYx$PT=1bt6 z&BIG~ET{l9@rS<(uM0GGyIL0Uwdg)qIxbVIbg}D9lHhf9oLSVvvZ-6+D}{7K1oKms z6wH%eHbgFfQ}AO)2$v`msyV=r1#Jy$;mYh0By-t*tL^X;QkwlVlM}}fyrMg_&xgsY zATs@_-MQK3P+M66iKD{Y>jiiu#oxjLYen@TF29!QWl>r0Pp;&+ZNw6zQG0nUrM}(= z2qAie-N(0xV=jqKO!KBrMpYLd`U<>S114&oxsnXhY))Z+aqS-&$=VphSso%auw%80 z_%v`Oq2pmqg%d>j@Qle}PH1i@NSSWlGv{?VX@r@&RGr^Zqg1+Pc%etRuM;SDts)tL ze6#;9hLG`s0Sna8Y$oC=z_=dxP(;07ERACHsR>_#m^D~`c^(d@E@2J2EzGkc?K@694bOz{}N5SO#&RDtnIly zQ?FrzL?4?snUsHyO4|>RG^^6=B2fxn@{BqOF>+%QcfWsT_Ko|pCIbkN)zD}dcWJ$7 zR)wLl>h(d0e~uTVOU=5td%v-fbh2=~9MNe0@UEZ)IfjcRoC>@XqwhQan+68+O#a4> zd)s(BJ}IGU(ZzjRDYft0r|9Ly=49WPwRU|q!IQe6x%)fd35bj;@f`_IcbJJXXOI?o~S`Nt1ko z_sW}m<~{6uN!t&}J?hnrlS7f(pF+TE;!XYfPhx*WwZB48dkmnSRM6A&ew!o@Zxu_x z%&ZWeC-0&IpkM>53QHUMdlW+hJbm`=tbe{5)46T*NJJdoxfzM?x5s<^Q#Rh81jzL4 zqcM1=_#ig?=)p2S^v11s#?r>)rPUQR%8K#?%@frzI$sZ0RHXY8KOK`lds5fP>WV66 zJUgEKnSjNh`>`9!&f2AbV4cDht32a09g1*zQ_2+=(OQS|Pc+zo;9pi%Oq=zNgu6rT zms3sE+$+a_xORUQ8`-~)YxQq419uF4lbHV{0x$&w5#^yXgXWWfi<}(t7?%2G{#OzH z50H~Od;_$h*`JXN@c-!s7S>H{rOqBQs>bDZiMKTxH2rgfK+`VkH)nzD^(puQ1Pk7=AI#$QA-#p60#OEv5yh z<+BGn}QlcSrj+A5J&6&iI!4*dMP)%UcTLr+w6-Y%Umk8?I0mK=L?hq_^mSJCJFixej!}GBt$pQOxjqz7M3>*k{rfg!`nBl=wL}zUYel=AA zRqk0MlHz9Yv?xhcu6amf>A71Ym5MD50gYk;KS|%_=1|9^=SudcZs^Z&o~gfY^czW| zW7%t32J0iQyh+*erXd{5LB;iUVaZHnm8cC~<6U?HZDGU(V6A}k(PMWiWYh=SphNb! zvMw(j%nfr=_g~vax;Pk23m&*~(oQL88+NY0+h2H@!Uf%`@+-tvWO-d&_`-hRsAJz8 zPV}AG0F4H5PUBI4z++;pcsb|T7eisGUe?I<)Ou+^PE#A@Vw&+EQ%BDF2cR-M3aiYR zU0QDIn0_40FC*dv!fOnp0zZ-=Fnof;@~^)pxtlwhL&o~D9=izN0h6b%cQS8TEhHJO za%+x(`Gq4il+&HJeYs4s0m|V3saWyk0LtX&9m1in z-;pbQ5edV6l^gF~xAIftV75xT>2BF#S-Wi!>I^w9TeNPQaW1Y^-bbr?`@_UfR7nnV zJPSc8K+ix-j5_6wR4f5&+?LVV9mS_EX=-Gtpr+Z)M)$quF>VlecX-X|^!P4)%ye$^ z>F8tdVoX#uG|VX{(!IyylH;E-)ZB4R9J87qaJ36l8>f+Zk*lAUdg^%m9+KQ|E$9OA zhN6_DpPj~w$BCWIo{F5uWCzcwPJXhSd1fSx;j$#GVvR^N*N6AHQ9T%3Sx!JLllmOh zMeB(KMtNocg|4^V2IzvLbeD&pL%9x$ccMeYxn1m3L$qYWE-Z_Sk9AiVa1$F38!ik5bVW> zQ9OmhZc51erpBfwiWt!+%OyO@hGpi=&Yku@-Tucx0Hiu15O{yXV3YiRc;DDWCPeu4 z(_V0o3FpjDFA_%lPq%H?K2lEn!_$EX-;J7lq-^pHAe*kNtW5q}BqhkHt4k^3Rht8C~jfd`>=m-Cc3w&1$m)P`lpfqX2 z%&h+DfW!p4ep6xo**tX>tBRoDn0b|GH#TpAcfr}r1A%R9^!R=7!PMsI5udFHJfN)3 zQ;R+nd8dNCkxX!;tPyf4H8?_W@c!vU+h>k1c>n9hjKaUqF^p>LUSvLT=;Y+~){|-f zzVUy*^KSt3s}H>@6mDs00S>SLrx>~B+eHij6khwHa1LXNUuNRgolPw zdu(*G@tfec5PjjLo>?67^E;Qy!>2Ye{>H_@)fZ~Ol80Z_M`nVLi1a!wC?dr`T55Qh zH`{=ZkMBJPcW^{cZ%^#DZMqgcM`Fove>Z?XGkcDxcer?jpG|fG*!X9rrvs}SjQiC* zwTRIBQb=r(}!tMhK*COup4x(9x>g|9E;mp&@4j&&9vte_B&*u9nIOpyyKS|Ca-X$8< zM90S3FBlLL>!7=d;t_(3fMaXlxMqNJ;4Utl;^N{IMa81;_ABaIm@Ko=z84pxBrT3~ zm(c(C@uQa~<1e)LC;#5t`#!K|Bq%D{-zmlZAC0R&6c{6VEeYl1IvF)JHNBx|&iuA> zQ>9u7C1r9SPr~1?p54J;d+GpZL!);K5dTwDO`xHxtE)ze8iBqj_NKe1uecxkaSz5g z2nv2piI1Op`XrFNIU*+3Cu9OP+Nrqse~rUSEEbmUlC;ww{{z_XZoF3dgml0&JANZf z|8bV1&z$ZKgh*7;DF1rqB{yI&o;5c9*A8q&WW5&q%c4-e*F3wf_=Xc>@~@Ns{aBlQ zAmfp;h>Huc9B!+KHE|vM_nlm!Fs&a$#=5k=4^$hbY*0v%I6& z#qUBIw=AS2cx&7coLjoH+q?q#PLr4oC+au(qel4tGoNy!;jh1ZO_P@89|f(P7;WU@ z#j;Y@5v?rjeL-YD$XpAZZu*_3)tQrdbiZDiufC{fIAffWp4OK2_xLxK7?CAPjvlm@UKRHJdy`a5^ZfK1;xL(G%;qKWl8|m!@I^!MZ;N7@!BtUR8%}u^ zy9+8x?1Xfo_?GB`L%I-&G@hMvZYFcG$ybT@zhO-ft+oO#zZJ)A_iQ_EvTc9+%36G6E2u%PxQRwI9mX@$ZewQNieJx*)W+{w-R_NH&>cd zcxW`cLSXTCv-Ebz6Nd+SQT6Hz-_mVoWL(xaO3j_^*zIPpiJjOhw6?~(@LP3azu$bD zJo1fmlsx}|Je{<8a44T^rkZS43y1Q0k8~6}gIv z2=bg+HC*JcZmFF)T%RW&z0&r==G57{Hjjt|;1_d*xvdA)Jd)3D6}K>g4)!eMqQlzg1x~H#vwcoC! z%lct$tZuZ>p#18J>g-hxj$HJN5G1(R?UaEAW^{y3T~SAtj3xN1IBhq2O-ayrd!qn< zU*0>6x%_BQ!q*XVzc1J()d@=|`SPCM(Ylny=NF`>qU>qAe}Q2tPfZl6P~I{Qce&4r z_Yjt!b*#}4#ht%xZ4TH=+S2<*(sA>bp)$-GyQFQ&9oq9c!Ruph44Q6?S^;~1ve~o0 z)dFQILB$)m-$a2(*?)~kaL}-ikf2JUi{LG=)TmT%Z!5fmhq12ZeIPP!N+T;yPMKt7 zsc9&jKiQcRnHHLn(XJ`ctxRR8@h-u`jV3(G`*9&#vdH-*9{Ez*M|&qVO)~74jz1f@A8>tCv-D*U9<$I`P&s5j8lH#O)!&ydZRvmU_1@8NesA=s z79xU#=skkyy$>RVB!o{$^j=2v-bZgCdhZf~h;FpedpDvRox$jgUIur<=kvYyuKQcp z9~O&u)_LFeoafokv-jDj^*GFyF>{l#AIE@=c@77!(dq1AQ3htq`}dppVd>1q^wWI| z^m7t!|48h^w{VPhrh+vOp8gq@!>}_!&^GGGn{lU2#2@TRi~2FA$;eaj{T8i%2>P*$ z$&j$62Hu5h0raKUzdR_XI{Gqn+vpG%Zp|1XMV-O+BOyEZ>j#g$Hg=es@@#y(dTQ#? zDew6+LGo`@`=g_TM??+orUH*?4(k3?seW&l$M|l<5~T(r6LrSr6GPJKN={bf75QI8 zmd;-bMEnHyX0=Cj9ye55au#MzDZy4CT-qXL2JZ5AIVlc}_Ju{#1k-TC@-ZSyc~>ub z^*_^wnv1N9pKQx=sTKJaj=wXeSm`G2h_lkj!Rs`h6RLaowIbF;Ja$L{j!C>iuj)=m zC0OwFji|1y$G{7~#QQ}2bn@?=?{Y}PDuSCh!MV+h$3hT%gPRH+M{C|(t0eLc{Wxxm~tZLxOUf3sveL8$YNR26jxt^u| z>+lxYv~iumrprX@nrJWKW=!)W)uIi5L4jC651hKGIi0gDk1^ZANKC%3n%n+ zVKD+5Eq)`E@Q2O1xzY!2LNvmjH`y@@Usi*cMU@UzKb%Eal{9;bsFU0L1fII+o$<11 z4)a(L`HSB;gjpGIvNK)f42~s9b(YEuu?)k-JqG+E#U7MX#}aHfe2WCvQ~U(<}?#@xkej z7V}`!3yhA|o(ayHr*>E6S^3_daS$POA(UV5f#{SrEkFE`c;0)axQ$%=J=Zfjw8tDO z1RNr=Z~D8I-clYzqzU^+f_~uCNXdTM40@fb56E*@>ZJON9TChPWtqhD9bUz~J*O=j zG7g&6)4ke8ujtXBBu8@k_d|ML4VsPD29S?{9m*K$ae^VyET>$+wR>ve zYg#80b@$J(HOzR7ynkS)x|W$9s#!>I|1^^<>%uq(*CHM862Ifw{&7MfT3^n++SRc+ zyLd8EzXhvy7o6E7u(NcZf0bSoFZs` z_o+=?8UN(?Y{MEAXrSG`pX76u|N2AIu1OxpD}i4+S7Npn6vK_HXSEMInYDPqTq-oxeLaAb^)+SE|9w`bkgh4t&uLEBk(R5PNIQ0cJZa0 z^M_CAtAWV%6{`XD8>h2i^)2ZOqFp8q>&;&WM0wQf8suT*GB1XgN2Q4GE>xY09jcJ} zR|%&ihsN@Tbi5McG^0NYpJuAxj`nq=h&SjgRrj$w*m6L`jQsC~F^*bU^%hf(Mu*L^ zs3JVfb?btko`~Q4Lz1&~2fzL9u6t=|YfG%%&iT~Vh2>fDf88D^znArKd!}*SKFtfC z9L`wxS0Dc?^HTGR|H2V;7iV^sB=oMs;Sd>mP!n;cbCbo;dV`RE8e3!IvkpwQV7wiF zOi$=rutJ*Pt;1MP@A}q`H0R;(e`{6z!9-Bv4vfW&8hf%kx5&Ld_TmI%ZA^2v3WSNS zDDSwDaGg(zv*zY*Z#p~P0P=5PQP24^ol9rgz*Jr18ga1SVY|A!yDHgkJ8)ao%n|+p z+(XrRa8{x$TIQ{KPuPZ`W4b3pBy@q9 zp^b{T>ZU~MO7r`B6De+9YoeS14qKI_-rEy9Mef$T<&L(?mlRq|Us$E6K@5QQoZPAa zTs~D0VgYP*(6c7AeSABcbHX${BC;jC7Glr~-v#n{Sr4_8O)+_ZH zOyVr7+4nitxT4TXV~gU&!3vd3hNRvF5T~aJ#EUS#xzVp8Y7=RgzyE6+_t>^%B|*7( zKo3L!nfn}HtlfJU+7IzbB(wvsb|!%SsJ9W;C^J>N2$mLmN4m{8teHiur19H*wq6~q z`0$Bdh>wikv9jDR?+nW(P4(^d_Zo=i$XsDP1K75}KojZF^EhDRRLxeU)#n7wva?$j86VHWNi<=g8I6Y4;y8d4gJJiY5S zAS9G$G$;OV%tgI8xN-;cPlsU0!-=Yer<1Rm$pyTy z_+XJWC-&$T+n}gz=EzNs^C#7l3v?@J)-A_+Wk{nX))IIA;a1V|pflNimA1xMZR~M3 z$T4_0U|6#^Oy1=P?||a4XO86v7c05TELNt~9yK|~hf05W_v{=<@=NnnTW>0* zW&Cuue-^(z>NMAYdy8Jb7f+5~#_fxtNunmP1ngkMV!rs$DEh^2cqdmqE3u%og$Np? zcoJsXyzNWtuV4XRs9&r*R9FvM%oiYET0CC3-ZctSje1D={W=5T*5pFn-z;N16~cF$ zN1p-E2$?z#&A=aziN3r@2Sfq{%~Rv$$#b`Dg_5PL$-k|sAzy2j*-$2pgyI|n3=?nesM_Jfz zv-DUQdRo&DllfBX7=3G)ePbvmHiF5m5hJ#9?Fj|sikUk_XQegIZ?x#aalZC(=g@$K z_Q&v_+fhD0iz)&oc}3wKH=nEdl2(Z+Mj)$H-e|S;c}#al zivbsqmjP!}5W@#aq@!zQMs5RqU}>5LZ~iy6>~6G#mlF=@TUr1`VZyU?H_6tmL!)Hy zJ8ICBQIHZthVREKOa`YXc5pAp=K|OeqLRz(Sc=~k_&U-NkGYdcth*9z*sl8XGW{M~ z2c@c?k2jZe#mBejF6aypj_xE=dMmZ--o^w6f$WjImzySE=0sP-8}X!BS#!Py+Fqdo zy92BVa}-h~ATp)tIR9%#L4)771hP~$dkcDCQQG%TEn{%4DDzT@bt|cbg$CPT@Bh;{ zsc>C2TJ}0%HLSmPx*{sIgd_~U^Tc~gy5zVNk)*9Wx^tUR(%-aI1u~&~SWif!)YSD5BpCyw7m5;Nn62|u*YhN@>W7Fg z2yLg!IW_(rL(jXf>J^ZjnKEqb*Mq>sL^CW%1qA*cM;&zPb|^ImFz`yd2uB&>WLSA@Mm2b~Fdn8}J{Mav z%5mr16E+bzoFTt2vWV1t7g}gE=wsCZI>ahs<<(<|wqTQ?pseHNyiI)pl{L2$wRdfx zeC=AafQZ;5?)S{M8iJyU(gV8RmMt`v{%aN-#89J?#o&bAmmY~hM@3c+Idg!EX_pgd z)=Ol|YLk@Z`BkcxgH2OZT0T)-$m2D7mF%FO>mCw#rB=(w%WRmIPm{UT6f-a-e3|R@ z?}7B*Hu%2ARbx?1?W(9>Tc(`#4J#)}jFlLc9j+p<-}6d8<=kSDv7HhpbiI2qy! zx{scdqln+s2kE;Rg~0%k-#QyXfAM8}H&q<<7p~gsgY7WFvD0MxmDQLr>dtUn-Q`wq3!M5qG%E>~-^P%=?;X>F! zkROZXgL5FUFkO@EmVXfIGct{3mcWh`H2O*l@0z zK;Hr1m50(ahk$Xqb@uWm6INXBX4?6F0>NcA9D{d4w7VFD;Ox( zK5b2G_sWLUwz-^cC>nlz1MkPfmy*<|0`gYha|LfN8_(aTdAIw|h=6^E=da>R3z6eX zn)~5Hz}S0M;xLV?<845!UdPs!t4F&MzTuucOat9hpUzy`p-?wY z)edjR@_VJHsQO;6vZx2&{r6O5f0Wc{FckxIPTOtL8eS2Ey=RY3fd9RodmlF_NTm*C z{bw>M!L-AI49_^OmdnD0MTGyUrE;5Y@J%SvnHiR+t~u;0O#5YpG&~~2@r=^+xO%41 zt<8_wIEU-xahYaT?bjF>AfH9EzJDyEqfs6!&)F1~CV@@q+Y1OvNt$B!86vEHnTN=F zo!`H|v>{}yAmCS;_`8mN1OdYcNR6Pe({zoiFfx-67Tg_Lj3upF*Hv;4Zg0(JP zF5b=dq{0+KEuLkmJK7>k2Y<`F-i*3vPm1`5T<_O&%6kKrru)Kfs4KyCpNJ-9oOr?3 zKOBjNUPFaz%6?jMn_6ZWD^w<+QfkUfCSLeaS(}{{*Ze`gXWzqSx8_RRK#3XrD>>q@&6vzSVceUCxhIR#D!*v zC9T#BF<$*nOTOx}@ID_ZHL9RE+}R@>#@&lU2 z{>Cb-?__z`Vp&#v4kRbWlI?U@<{lGw} zmsxa98Lr3HgcPj3`4P0@qz+y~BA)N@8Ky+PN+d&N;6L#>^&F^#zz)W2H4%M=!`KAt zT31g@2VK^#*D==$A-6@0gW4Bcnf{Y)37Rm#-MvY^)~`%X4r+eN(YPPq75bj{8E~nz zYbBxtoQo^4%Cm^q5B!L39Zg$Uq+?>u4eNN!VTG}=E*4Dp<++|ZJZ}v)&W?E9!taO) z<}EYa+#ja$L?L3p|9}pqxat5Qfl!Z=U1w5Cv-X&s7FxpOe7kljg_IOqY*%hi8MJdU zx^3fci@=?iHi(us#uOZ-9k^D*uhwJJzGmx?9=uJ~4suBJwlwP^bSOiY|7Z_gD&veh z*$7n7>vCdL`&goKm*)IUL0l*r$o%S^%y63jR}6t>aQ|%w{0S~Blw*EM!;wMvUsC|a zYH{G4%&ITH&?GDS)mNU&9DO`|lYRt}IZSgu)-X>_5&N zzxXfBLRh+97B29R%>C|erT>4s9#0>CtZ9~BvHx!*F{EgQ`@i1HVd(#E*Q$4E2F7Dk?bLeA|K@3^xOC=PBDnw^5!y_LIY#C7 zGoNjT&+E>1;yv(E!+haHpyzk^MZXd{E_Q!X9I3Yin7lZup#Yf3LP`;n-05)By)^YBJt7Ii5pB!OK#PNA^J%wagE9HyF9J4bpd3`Nz17f=o($8XP5wh z`%C9gTkUi5`C1f%fz5O%uF(Ihesy9qRR(nCRll^k49R^`#Smv3KYF|aYdOr7v~y;Q zmb7H=Uo$z48m{{$eAAeztj)yk!&AePA$w6q=Hz?fnh8IjHs`vze#j-?Cd;;WtxQ(^ z#;5m`Esb9S`)aF5$Y!xT-{nu-9~ry8@aDy9Td`m$T@i4wxnyN@-H&yl1H#qp^$-2u zXB-25TYIvF^%dQv+#{IzayS3{7Z}8RPIoNk`bvGOFwN#)92OX2M@d1*lqayf4{|hr zGB`W<9++JR30D!V-K=5{L`=65@LHKP8$TxI<)#(umOl^EF9T+UF3;Q~nyRK3U5=|- zAwO){y0}O7il#zv(fH$x)e61A0Hn=r>0N_)II^mfwPQRZ*!*KN+w<(2jI~c66n2pA zS$kt~`N!D#6S7NzW(tnIcczKj%SqM!+_1k+#B-e{`8<-r>4PWfx@pvr3#++W{9TU(klCXj$HL@9_!i?+l1y^ElD4 z-Nq51uXZZ!9#_HU-JdrBAio-%GqLte{XCPl??jbcL=?6* z-x146+f9*DtnI!g8Zh4=FdLs#l53?d)%2wwKWR~rL;YZ12BY^jE1WHyadUEzB)jju z;_4$>;J%OmQId1cyJoE+FZv;uSezLj^w#%>4XX{zXIn}qaB5u&B3_qQvqnfOmynpq@YM5>J>-6_ft!W9=b(j}RW&kBA-IPyTIAc_&7S5XJ5`9iaG{#^ zIr7xZKr$umwyiBbcpFd^{)?yLne0*7?Bsni^F#9<0cb>*dcl}qR@Mx0IHm*LSTKJ1 z=VlF#+La=Xuwm?|R>R3abJwrp1I}F+`nSiJJzePHBrMS-0uSl{%!zWv^X&w-SI!W) zgKMRUHz&`_^E8-x6;xV6hg5n{wtnSi!Wk3ST{KgW%@VxiH1a0*WGi=&qZ|(dXzaB? zBFpPtOrYc&M}@OR^<$xXW(K3zw`s|N{J|tiFvbOE`R!DEn{4`%xL$Hxv*q0B5 z4GUjhm%zTkmgDfU4XIs}yYim6ir-zVttL zQfA^(q)>#%uFzRsI$@jY;^w^@tsTStKX9t@`m@G%IyBFx--q4%Vn4DTm|bKX*?p4q zORhy39wUUcccWPf&z{yH`_Fqql5v@opu#*0GzsZguI_NS4De-gte4RnJlqpq+QW_WdazJy&VzWV{rUE8l{2eP${Oc# z|COh`O%@id;WK>MwUOCXAh^okI0da9v;ifvbFg<|JsNEei7#z`=T(fag}3ut82VmC zNQ_1ViIPk~8B8x??mW>;Y@gZMf>kctQ?tU>oroj=(xje%S_{#Gqr=O$Pa|M8P)QG^ zVe(iKzgM2@p5~H~x!o(5awoqY==P7@o0V~HMdFR**&has)}Bwf8PPl1dig@SyK)X| zz0VgMu0ms9Q#i~p2X*6ED>j>ok19J|KZ4MyFAOf|NOeTq1-kCa#k;+kZ+Fa!E;Lpp~aQN#B%io*PqbJWCCUf{pHkE4*!4bs2?iFi;LDE%$b9 zo1>l5mZjaI+e0LkdDf(RmY_Mtc*NDqlAu~2sChv+jVO;*dF9v>wB;K5Oc*yWV^W0= z<%U&S;%E~uI=uzWAxO;lNxQBR6C0o5*eY;k?G=4 z-qC?Gvg0Cg<*mbW`pXDTLRvPnLwj;*&mhj*s_5Y%k>Q6?LO!|A?}L$K=~RvbP6-cp zLS18U8-}Bm*{OJIW|2{5XyHs*=Q4cRPK@=>t@M}0s(g3XCN+H!qocDcCWWd=1MN|& znL^~@;qk@FA=874Cy}drm|wLhG&CiJGPu>RD^E4DGufyI+Lw*ig$H9t3KV;^!{#c{-~_Eg|O(#20eiO9iWjK zIoc1(IODD)H5ovk1Y=aL@ii(+W={1EQ;S;$Ilc-1x(yp29`=*s{t$78@Wr=S!fE8u zUuXo5H@|(Wlzbdh{#T{00|EfS;v@yP(ED}Qr)(H%Rbcg%ctv>S?TYxCp3E%{P@sH? z<~8AQvHxjlpFI^2sARh%m3s>APkQS<`TAm9!myvNDmw;e+VT*2<{5CHx9X4s#9Pbh;b-F@cmrOz@C z5N<~|sBkid5WUhHH?#;B6)W$3@+6HY^8$cXueXelxunR1?Mg2pTEl-=0ZxWw;FEiF zKHDaNp0@>Y47e3tVdi^2K->>_f#{XO`QqfUf7W(}v2@>ASag588_zt#ZB0-?_ZR`V zgzVwSqqe6$4)#OmzYc}AFwIYC^G&`+d-oo>866pL#beXs`YqG64;yCrK^mHYR z)2AM>vT$EAaro7D-VQ`-2$mkeZ=Wo1iC+2dJ6f??JPq+)+K=ng!Q@U`u$!y+e&9<-he{J{R#47-vdnt zvVH0L$d^WAoBl@W=8c$)TSAiP=cS{xvS+ladd}kP`ptgapO0xDX!W8+zGhx_zeqUgD@ z1=-WSHd7!ha~s;*X1PfJ^q1rjsj%s|Ipq-S@7VrGe{wA?>7QH4otEXrb{QY?uCXkd zjpt!IXx+3MVFNnRDUo37Ys%T{K7B(*Y%SiwqW+`;Q1xxHW^DgYmzbWGnEh1VKY&MR ziS7FOB1D!5CcW$Li6Npa2YuP0KbOtgPb5yXz#87>B=+=d$~HIQ%?f4Surn$VS2G%0 zkj7wKf_0_9ZtdmNmF&H!i4KSUStFhed*sT*gKOoshnckl0{-xJALS2K`ukg_r{LaE z1r+~a9uI=)_XijH#$}iXxOsPYb8Zbr&20G*g*1 zWcU}PxSf1fsjk4AQQrMt+y6>8gGSju!2cV`{@8@d`P#QzywcuaZjV}|642;2^)i!=kG|V0NxHv##c=;&IqHr6BdndHd(#_^KDb$p zL~F>`6ri+Z^MxE<5oE_CVLL6uMMUBYb+L&s$)QS{)szLRmXw;?-Vyj%TyK6pu$zMM zk7Zk;>Hw;ffL*#8{%5?UF8`({kzBA-;fA6=FCrWJ@LXxF#MORfavEtx)qHla7&36I z*Oq51i7QPLzbA>KNx^^BGqmT7Tv?;;BXSy{HU%O=7V@SG9miSu{VW&>z?`Z|C}C$SSm3s^sd_yRZe_9Tu;Q_{vyiA<0r2E0b%wA z|BRzw^Gx<>b8UTe?3b2(u=%AKKy&p6)c2D%tBkh8W0sG4^KJ;$%wpuonAuZ7=chML zhfjFK4{qowcdVvu?U1=t*n?R-E+Q|ctlw|xgZ)ln7WK;SePb+ zcY)XYvSn@ej#N%zde`tAp!D&{V@YVAH9^T@3BKuo9>W8STwo=3N1o!E)=~##$(7b@HSUuBvc!z4Jfq7#ta_t zdd{-{^q8|MJQ{ftIJS<{1YX|)A$pE@%4ENNYqqq>Nib2_SkCwd(*5d~Edk)k7sQ|! zH_*RF3$}Gp=H&GuH|RU+KVKTdVI;Kl(l>m!d0$;0GKgQnr1VE+kK#{PT0_8-~UJJ}J+u)jxt6mIqs9NS= ztHuI$?(VzHOxz@nmcLJsptQ5r%8!r7gli37N@;U|qCd4+6LaM)zE$n22_XIrLhneK zp-0`o>Q8Hbl>&xtc*9;kD8f?sHG(CJg-`jB-zZy7!lHYMwK$Z&cY19EqR8fzqEs!K zk}@}lsy6d*nVExa9OcxEj!N|cW1SF2W)Y#G)zrpMtV`+My$*Q%5J&cTG1mKn*x&xy zXIGdGAAe!JiCDV=0Z;*lSKdRbo=RT1O$<=+Z$12Cu%oR76`gDROQ|3+qQs@vxAWNy z$bBKw66@wwbq1HKr;{oZ?mO!+E-yQtjim?S&3bP(5T;_bK>?;VU+v2lhr8L|AsKM+{T$x(ljfWVVv1W%l*U#xwlH`!74thNbODTc8=bf#5 z3KXl+o_Pnj1W_PQk_Bq~a7w@SKT5s)qAbDXsO^(-vHP;`0Y|XYUm3WQ?}$=qQA65R z8g1S#yOM2=G#ovbyT^(|qWf(jRYEH($XRQkT;v7Gs;n&!m%d=8_N{DNh$u%n# z^%X9y{XaLoW&m~4Ze{|T<+TpJc*UCjFXybL?tz_d;WP9b{fo~WAir?wV6oFgA9FJ>gn zb_10T+Aeb&tnK!%?z#UwpKE|@F)HIOOJFPDu+Jai578+v$Ji>GI)FII^O0eonlYDIy%-_S2;Rgxs2^~yZPI9O4|)0 z+Yvf04qOnh8JN1|@SbhfTvDPQ%WV6)F|tY(f3{oUn@H}z3rc(=cahST~{PeukC|;CEakT`j>90jW50) z2sf`}O&rl8vre)ct65JX0-TtABlumIh1|?fg32m! zFbHx~FH$O;Scmd5P?upDje@yUGEL-+(BN^8-Q31|smdf6v{WfxKAJWK*=HHfRx-=1 zc56v}$$vEULBV~2;=MR$=9UpU!Nw;q!U)I@Jok)5j(W6We5^BckI=|9O&QL#JWL!wV8nu%zWsTWT93A_I^97~Z)6OZS zs%EmcjD-dyQMBg-&1dV3n%!wB*AcLRovY{f#m_^Mh$;#QmsJJaY=9Qcm-XX5dR>Jd z$mtyT@{gJ;|-eM!49cLD$QYv!{3S~xm1Ka?8Zjm}3Z0+|)tjH@o?j3^+vDvM= z-A|5Jc)OoO~d? zL-0J2U`Ft7Rox^IEa>9&&R@43(yKwt3quyURt5hSrBbl!pd8yiYlnyq4K0Lxr)ZyT zW;haN)8VP;G9z*Ws4yx*16uvXAMfMcKfWlT_;P~D%2l8Sy@|Xm5F3}BsC|avPtTy_ zNTTW0^tu{cUlCe;q+_$o(F3!i*54Pp*&kuO{&8BsUMz$SG-6Lr=uV$J1sAX+WX-wn zZf62lUug5W*n(^$>&jzNqe>7XOeRhNq91qQ# z7z0tX`!Dob*Bwh->r%~W#8cb!VjdmV4(pJXEPp2;r_uUF#J2Bi>^n)##Jig5@|(t0 zaBEa=V@ZRSd*{VAWQXcuPSC33$k}3smNXb~uoeimu&F#8^AfesM?7QLE?iC#wr_CT ztCAAD@a^IyIvA)P9k`tMFiW#aY{Z+e4nIfzTv0Z4mVWd=#r|h(maSxupqwD5E&V`6 zVEI7C4dEIVPQ#NV5OnC943oFX;~|qyIfxp1MwQ^SQ%TlkBYY9F|M*_PGsIkrO?S$L zih>^vEP=yK|6dQ1JbzCDwEJPZ64)w#?hT$7&X7lL(ODbQI;)PqY?tAhNfx^=t zl9Jl?nDhrzhxy!CT7Zix#V$)zk<;ueY5mW+wL5uzlHPe3-S_FE-9;P8f1Zbb{=}MW zcbeJ&tZ>5Z(WzfB^|~;gwLcjm#l5VuT@)B1w{@Qiz*PL#pMfC(x&F3soa>eJI~L?Smyt zH%NP0zHAbu9*QUq(^G)W| zLknUp4@<8#1l@M))m-R`md2H3maeghu95S-1H#yBN@auSpeJrNC=gb${1&9fQ%atD z@{Zbd-s_uPx*m;s-zgi>{ zDkwrut-F0-l0jA$#=>Iygq=O-d1X+6cVlWzlx{y*Gee%HkO&DMWJ^H}ZU7uVlp^_h zD)8dbagEK~#&5SkgTE3@gd7xC}_${~slO6A>S((^P@o6KL*vd4qu1Ng`eyrF^R z%@s@hmoFD!dKk%E0~uaYZ`Lcl2er-5b4IX%o+4Cg#%7tP(p}3NFb%D(0#tTb9q{Yc#p;~2r#SIK zVpRM3kAuSpvxb5vM~YTvJ`{o74FhrmTVLbR@)~wmXMCzo zE;kb^>%bBRLo8FV9j5|BtpKM8*$QF}xv$lB_ie4kFQvs>hRXs_=ih2gt&RY<+Wp{H zXFb77nst0CR9Vf+=$~aXEW@H`EAQh3w13PkoOw&|4)=R?@?_0~9I@Lm^MqE5)agJ= zScunNNp6wpS1Oa0gXK1%itrrw&3USZ^Ng4D<=wH`d=a91%_$2$%=df^cJN)Q*aS~g zGxyXZ$6}JPr8gsh6-ABLnsre8jFs`IO)CD}XbM{auqOiXBcDe>`=2#CV;{8U4Q z7Jhb}or2mLb0ebvg#d#CKIV}23RK#C_x81?Hd|XWCv~?!e+{gXaIdd8YzUC2{-Q|L zo-U}5j37TK`p3HnU%#2E({XU!%|F7sA+hO{otvLL9C#4>12y#yS`ykW9a}rf#=b#@ zj~o|9=C&%@a70@$4gG0rO2wT1li=#5%2_bcWSZ~PC?b|Gg-Z~(Qx4K}t*Do3^&nnd zdYva$hh>t7G#O+Uoez>B@LoYL=ginS*T?VY6VY-~e{X z*x{U>2+LIiFJ+AK?A>S5--6gfhoj`_hT5|;=3hw<8ZzZprFiWMvU|VZyy}Rc>O508 zsQ$ZInx|$doK813MYp{<(2#g5@EpKrcn!f*0UoaSWX&BO{@mMFzR8)iSH%VIdZue4 zbk+?fM!Hj~oO};hp@^l>t9U#E2R_T*oB^$o1zACH$ENl;M_h|{#5s-8oj#v?mcb*4 z`I{W*#wDWcW7(1X6E3=Sgx=@$lSiC+$Eb8igb%PY!_2#nvNn8%9${;{#U^ERXLv)w zlUE$H-_5HVThYeQ{Mu@QR$`fiIWu2VyS+sy=3Wf~&d$^Ad4Xz9Pjy&xG&8){yx{74 ztPPBh?Fm zkg=>$SM?cu=AB~NYBjhPknkCB0|~fs_X3QEG#j{jl0e9raZ=fNir2pPb}{STqva~d z>)193Y77V?)%^%~_0XIhI1v2BRQ_>NTO;WQ0A!Dm_nCFz$mG-6Xhs;}PJAHfVcO^k;k z;m+j;c8@}=pOO22qAge^RK_B(g}Ch{qv!m}2sLzSm<8X35W#AEi_;E{N4yuK9*GH` z5g5roa@`RPeYbv2G%~!F-?*#V#%9T^Pb2o`(oe?dIf!f7+}nq7xk<-(`=oX9)UyAp z@tW&d?|`6;+0l7GXT#-nCfRAmd2g40{o=SFgJ#6R%4IZu3RDCCi zfyp4RO_FT0BOJ%N@}sscpe@DaA~0uJ?r>~QHFUuxP&7>DN4XRl#BxT34}Rx6q2vW^ znn7o2Qmk;w_FK3lEkzR#U1T|;rf5MoG=!*0U9@oL9{LO=q}47TPQ8}4xQ1Tuw63gw zM=TKCEI5a)P>WfvCB#5#$Pd7}A?~ZZc<%LN1Bp*E--F{Oo%}^lGqNS7lp5Im+EAf@ z6ib|>Z*%jno1Co|=F(JH71u=R$N>5dfo85wvao^0#PbeuW~xvQ<$gY}&;89s zrEO+>vB3Tn2DX{j`{r@^2c@6(w_=$A^)fhlF9eO0r3v&2c<>!K?bnU~-1)D6_)LiGY=$Bw4k2+YQC7GgvNV$^n zzC@j;hN3FgAIU7ZMl;lOMW?wFHa9ravcK5x=XGl}UyH%3+l)?cRgJT7H?n2HEA3~V zUl^Deq1F?l^Ph6-%9lKYi8?~W>06W`Gs0h=ompig(Jz)(urf1%^s~sf@biWM-5nv3^u--){eKq7zqy+{6E(Wo zzD>?6oQ3f9$RC57SVnTmmmfsK`&yj(1u5lBUqcz~euHNT>`-T+1a*2%9MkLtR&Am# z4@G?T@&@Y`mQjD%XPs1oNjn>XJFSL31Kn}fLrd@Ak5rUko2EsF z4@l(WC_MjGrg4R)?3eUmQNhXa84^9YDf?CF?2m%oK#Pqw2-W$ zcI~{oTGF`>nV$Y@SLYCPyUtT!&YNR@66yZ7_8vdRT;HFNm+E%g0elzy<6O{pe2M)y zDyn=Yr1)PaN%frDjA)RA`04-eDCqs?WwSPK7W2a<=$C`4(f1AZYLB*S~Yzewr^CQ6b|H6JHHkiU$MdL6u5S!b8yj@1WQ>%>ac2Rp`wc`U#F zGL_d2EX#(fAW#R~&%jR1^3Dd(VVvr31a+qoNApj|WNqh3uI}|`k9J2{tw_Uaw{~GB zM5dk5UDyrBef4f(nM-(rgLA!p(~Y27cit?udi+k!cWGj2^-WUP@+*6lbA4*p;i7%e zj5&j>LuPM>G-iuAY`l5XV>YJ$tGvJ9ifie*Kw%`fyE}p4?v?<7Bv>E>cXx-zA-EIV zAvnR^T^fhr?(R1h2VGl?Y30H(zn&lstgIvw|8*h#v2j9-uY9 zFxq=aBwH=W>e}(4&?OVG5-b*C9f={fi&Rt^Xn(K3#eu^Biwu{Cds|;$OdI=N2se&@ z38;5Nuks$1y8Z5f_;!9EttzBt*LX@>Jbvp(b6Y8RN?x?&NYHzW`n0+3$Thy5LUsvO zx}oZ!jVzuoh+P0#tLi0^?PfuW7dJ`i;Pyj$!o|1Un!6|lCo=NuM#LucD#In6 zTOW0W8f#GnF~QuD7n?70W%^Su?yXWx0(`97nM)2Wi>JAsNAUHD%3pmL12_aCTQ%|R z$K_1n275#;Zt<@66c~%Fd`V7yQu`M6xCN?#*xq2Dxvv7=0^nLt1As%G2Tqyw#OX>O zcHOes7DpJ$J+suwRAn4X39k~Di73W$%x7^#=G=|$%nmB8N4^?;4~B$DXhL%u+g*dx zrnj&-s2lf7S?|V!Dx)u>SB-o6zc>0xl^)!WXii$91}-0KHUyPr&1|8iRcebtq;{Ne z8;qj3*cW)45TeCmz-;cM6{M#c@s?%t0#b2MD<}0;7PK<{js8HYYBj%uuISuwZmq5l zyS@k6_Y-1x%-ZhG0GNfn!14QRA`+sEARE2sSy+D9p9_1xf))7A^2P-HTTB+%c@r-; z3Y=R-IU_rsRe-+^6KmFyyuVIg`L&NW#WlPrE6CS7e|4@XDW{Kj7D6d70Xa=xU{-CJ z*v+x<$`)EKRGD+xwpwnTk+U9K*doqlXLvULPOc8Z1crJY;a15?(0yF<^7E_L0c3A$ zt5DR(Z4vg~Z|Y86S2HKktaG-ShKUPsqu51ETGn z3E;Qw3*qE{)?Z)-Zbwy^7g9~rUMLK6q=%dBsAX%yIj#@S6!Ej`FF%mZQV16S3xj!( z_HW)K_`T$q-7>or}^mvlaB+2>lWIRLv>zrI|R2zY@?q)+-ufMHKnxl)-- z9USUg6M(_jHY}7&`m~Nu;!j4KIVCXX?J&`r zdx+eT>ZSYUw&gfVF=n7G}we(TTc_f}j-bLB>HTjr+j>EHMtFFFbS2g`WXqo9_s&ngu4UA8NCvt(=P1tNX$|)08 zlSXfzj&$(j6_qxQO=;eR&>nwAKI{%LOncpO4i~wjS31#9BYs2a zB-;5M0XGgmZD`RY%`f{8E$Y0c)O32nH&15?9t&&yfz&RSXJCy8`w5@z4RaI3mW7MS z@MHP5X!@jGgC_^BvtzWcc93%Jd}X<3x05O+B2U~k%>eG=!H1yB zN8Pd=GebnfFT7j?wXJ zavRjVCWPDV(y|3+PFR{OXMaBiR|X7EIC{gg3Koh5s`V9eDo-m^jQyVSYo4FX}Vn9s#`#a0)ZmZ(M~J%j7K zrTf)MEp+KpRo_%bzJkvfReCwFc6wR5o&9XHN?SiJZDb6cmSkqIkmfov+G(uDIPYmSE%a!(k;* z-x`0x$t910(f@0oQFFFdv8?&nxGY_s6I>q=Lq6<&f?#on0R{us2#KP$GCBK;W7@P%V@ zwIfB23EUY%@e#v-4cDbqpddx?BE+}ht1H%!uDs&yAG1HWT$?wWfK&|I%De! zB2>jgielrb5~hVD;iMMwA>cNv{>j7l(s~y-%^$l{-Vs5Vth$IT_odM~J@PtUUI-&< zBd}|{TS9kOXJzhbc~#Nh;uk^FjzAo}2=2_>+YCO3B^c<%Pn1=2s8}AUXrlHT=>8&$ z7qle!Uw#*zvswL5H(nm;I~})sUkU+qM4d37e!V-H{DaaY6%^5 z{{19>+ML=}5o`?NV@>w}D3Qa1DY6Vb97EoCuzn0D;9^>NgT}+}uR>>X69C|>;bK22 z%U?u@T9t_i^5h4R{hIta*lIaes_Gsh=Ck=D-oU$IQ~L=XWy>~sJflIb*Fx{>*3ebb z_ooA8s_2(sEsfb58<}eloGR<<(UK02y@i_CHQS4yd>|YA2(HaCR((tBieX~VCGd=I zGF}8SSRK6&{f@--(#j zE(uen&-ZT9+`P&nJ6hNXXcR@mwRa50OuO2ys@@dOSDBMl)T+C>FZ9;DVC)wvK%=S@ ztU>bSEm){X5d}dYw(WZquYU8Aq+Jz5Fqh1u$4d}|RpExmC4jzK@4%B32t`hsjBugV zpdt6Bn5hWKB#sCpQ-fY799EhW6MY>+-0yec36R63bb8Y&Ky+fs8>}0$TE6e~mRc8q zV=KHfUbx7s#&B2!>S5TU>_hwFZS2b<+0e1jGrPEo1TJ zLqwwSXwxIr@526vH-z1gO+#|x2Z7sJ#`lQd_Axd4qL(-bBlhnzpO5AbN4D!*93Ge1 z4Na&}Ok7Sw6Os(``|dSep7X<+0Jq*tl*^qVU8gGh;2TK8JxlCa}VNKemg`k2h zU;k3Hopf3`cXNn>Sbr=i9;v*=Acqs@;#8PqIE{=;$=cx8`!S9ys~dri!fL2|4$YNXbUfn`N@)czg+ z)g5UO#7`;9k08sc=eTJBe2X`H!`WDvABIPQp-43Lb{zA*2GO@`s8_%-Srnf#=>iz{ zbT;F0Kg}1TzWdG#*%!;P*#C5<#E;4fI}JuospI&~DIFkQ&-SI3@hkpY6ovN^Ns zp=g-<9M^t?Mn(EPz;UaD$?d?6{(dXFfKze;_NoP@h$sTknHZZfy*)-Xh1)&1oiDO1 zwWPjueDeqvpLRjZsgT^Z?D+|@?#{PGcWr&1r|*p#q~Fj4PeYEf4K8|5(IgN=GKgMk zRQ=Fn-?aZ5sfej)`5TDQ9;9aM_}1*_+w9z`hkI!(}Ei`pQTw!3ua@mmaYy%5l=<=~pxFxv3CL^?blu=007zyR{^Ul1?6#M5}^8vXGp@5@a zTetc~RdO<^QXNVThiAuhc^GIu2scm1h02*=o|_rGEa9N;CGNe9FFw7o5MT8}+g#@Z zu8bqhbjCSmv3h?Pc-GQF9zo4Z^nn?|7`TN5KfxEc+?1C%H`mr3rVS+(0ii?+%osMM zlM;~kE!ZOe#HJ@zADU`Hv&ts(&QUI}2sG&id;MHlE8@ty_V@vs+>}U@uVNE$#=n*MkG7TBex9O_HGeZnwyX#UNrK?n(zhsiHye=^8;nWHk-}XmGqS^H>luIp zAl7Z*iW%*5;t2FZk95XVID<$_)-O54xtB<*dBv`YI2}TLYFu>v6A=>UUl2EkFDVY^ zM3hnYndtE$J|&V5idO1@`F0Kan>)OV%b)ceAy%HRSvo}n<7-d}N4mRZVce$&pr$qO zRm1PG&+i11(y!)^7`Gt+xT;t_L+XQ7WD5;T{%dnQK2zD=h=ddw0!7fS;EQ#i2~-44 zL_j6y1a_Ow#1hYSJ9bQo>T&!TCM$T#x28p7c=r8rXIJ4L0!?_`WQLS^hP7;(A@kI_ ze@}qu|MkmP@&AdWuWZU@_;`6Y&*}CxxL?3`863EMo>$fm=Nm)pXL@Iu>@^l^7juVR zv5^lb9?*JtBSVi$eLm%F6MMBzm8wL?SqGX7@-OuOMvG~$cKgwIpi7>M9;7hJiLDSjko)z=bN&C@GJxDe0TLgS|ky?t_85@|9@Bjq0F4nS%CjO$x-}U zVF7cj_HR0$LblE|$1l9C=nk~4Bb|huj35LNCdOS;;mMhZH6~+5Ye(Q<5MMm!%|!PY zFqqiqXZ_`;{6w|}_8Q6Mx&$-q<(ayu!mTPH|<78OXcT3vuVtpplN8`y5?s80bVakZumyNn<5%UNCJ3Qpm3N!U!`BnhWN z@AgjBY+)MTH$thsGlRy~U$@6A*YBso$egOUn2IgGM)ys4x&~a`UtpL@xA9>uxtNrq zI-QLzFWV`cK8Kyqmz5{;sV3>Cv?NPkTKCq)U#^~kZbj(Dvp$kWlf93K%sFE>!} z6;Sh>(1(W}Hn|JJDf_hB7iqqrhH<9 z#M%!5F?k!i0z_V3&s1DSu?J9d6O1t0pR*4&4nG-sy3c8L2W7NgnX>VTp3|I?>W(MY zd0e12Prhxvkr$W^jIOqtquqHY7+R(3G<0>{Zm9K6ER4Sv_tMyb$DN6!M?}04R0Ny#H33z>y0D@$$3= z>1?4fJOSuYH81Rd+MXX5%6Q-9{LPMt(7r2Ya&Fo=wTVPd7fO-TCu} zQPDa+ON2sF6(rHwpgP{;S;UI;9$zYScEg4gq$XhqU7^#cZ`G?hWyFao{c;^mqP9JH*@Y$wm1J7g{#tgV zAV2I2L7r(rMjG0+r%iKB6gw-b3NVlOf~@4g&E;;n@ky$bf$o!B57t?Bar54wl4EV+ zdk3ii^$;m>Z68LP+ColZg0W_<1PuF4SDc7yjzvskEh0#;`R?1(w%F~HW~yy>a?MW) zA5-{SGZ3A|QqGD{ZlsfDNHdMdRxulwOIqlAIlM8uHJTqd@~N9O45@rEBUQYl>gH+> zqq$iQEmQD>(Yz#vsO0H|*bl2U%2%DxzfQ*uz@EA)>%b_(P7ED|tXo|$isuW2rO49F z%a*i3xYn~%9SAGpBOP63DEwV!X8{Z?RiZjCrwyy70WkN>*5A}a@dUS(^|A?F6T`V@sWRdgT!a%3`l zHoo`c_k_PHk5GgCv{onV0d#tQ#)`4ViHfW?n~p@`AwvbXp~cnLCIDB9X0^I7O)h<$ z9*eWhr^g_}5a+Y3qfTD*Kr5pNPAm)iZ&kU;#4@Z`)j?a{&h{?t`{{hA$Jrc>M=N#m z;tV*0!jIAVXbZ9(UBLF}xhhdFDn8og`SvE#shit9945(q8fl#k`#l<5Gb1&DD?R-{QqdBcGOG%y=fD`@h+>ya^=G>;S@V+)_PT)N z1+-W_Hxr#FKgOwE%hC{9xM083*hmWhmoT@ZXeoTzaUdx{=T^{23XX@L5NuQ-%E{w9 zFW5K48I7sS)A31_k6Xl>Cd_-~I$Xb~$r^OxM)xsf?#^>%ZPJc?3nZ+b=R+9)RJ;<` z?a{L?j}V&S`zyiO_M`P%bNuuczHgaoojvz-oznNW*r`%NmGs0&+}|rrW#E9vZ_|H! zZ`ymeS*SU|1ZpvbQt?6ma{NB9?}cwKOozwrsKj9l(LIZQ ztmqcy0z7S62jOHXY{MSZkGK1^)jt@A$M{}BX^IwiE8V?|8}Z+tx_Ur$Av(W5G8s>l z=-pY7(~I-<41 zkfkLqe4y&?_rf<>0rO>Vx=(YPz=PZMV$t5ymA8#j<9jihTn|qU91szkSmY^!m?IS= zJ*9<|`){@CobRs2GUrmj>;m@PeaRfDE3ZZfCxkF>WB4fc&EI6%sw@uv#eT!u&IwD& z9iRj25dvv(0O5`}v1Zi&=8beyaA8S{=k#APIo`=1?NgT5m>$PgY`ZTi0bx3vY=b(M z7UD?b2FVn}<%0ZVQ&ODUk_5A* zW={bRTTSk0fZ?P#xk!!eWT=LGE&O?zN6h7_vAjn}7V9Wnu0LF~u;gZzr~&A)qKd(+ zmwWPyi48G6tZ&M7sVpNS?X*gokFr^tow#K$7YoZ5ZNcp2OCz^D6&sdZ2J(X@Iwtyi*pb%W^6|EYkN6nSvdPvd zvby!@aHb}L^LyuaJyNSnwMifq8ya6E%U#q&xvcpshDi3m#t+t#l%b!qzEzZ! zjaGd~PH4RjM)bRWu3bm47uBqd`moGW%jr?xTVZ#PxmC@H2S@-l4q4r$BYNhD_X=1- zC2I}`IqHGsb^+zxiiUT*q8Kqu(ak>zyn|TJp89i_q5gyf1(5en9IdLYv3m`^Jh?wT z$kW%F`thYWZMDZlx_GQKu84(D@f}Q9_A(c=^`rHm6h?LGPo1_P4_I9g12~fKd`#rx zGPc59=}1om@KwL;V2fYyUhXpQWtwY?;8<&Y#JO0NwA8HiK-gsfUACP|&Enf`N3Q%B zGtFj+Bayy|IFcsky<81yD}CuP5w|xXbXzK9DFXn&5B8;B!*lzN`GUN$K(3!7S!uci>0Y7oe$Kzu~Y@|AY`^-uU!K(}(@z zIPD}$lTr?3l5o^oV#;jW1{Nuk`;ER`Q=Fc@bd1&5qIEF2=vNtYZjeM@u9qH{w>^x7 ze627$37b`=zN|A&egt9KQa#;2_9X4y0MG^g7>7}~MzcftQw6=J^c~D2(s>P@J`)L< z+}(;tL0}4a)@R25`lj*cF=zo|-bgS6mB)b$L_LvfB-fLH5?HA4_Dw5B5L$v`x4%rc zAzFhlKcJ*?v2yM2UW)EtrIh3EMX-F6>+u&co?`6ovx4xiA-INtN8YM$?Gn;jVlu?2 z5E>-H>vk>HhO|U{F(~t>st7_3zlVpd+WIE z86g#2g(4R2yjuGMbHYgAaH5K)sK-HO~EG#iL(VmRra!d@p; z&5#yA;sHXwQ>H9@t@;dG|ItgGQS*qh983q7S} zLlBCD6hX`r*4VhQl=cjnr{d^YCotzinivu>WNj4o>VKWu`@=s#f>&@vUpSF2H}ePP*FQ8}66Rz%Y?S8K24w%W zkF-Q&FD{Z=kY5+uk0NI_jJ1^R=_{t8pu!HFa+iG-$H#MTBwk0oH1E~Cqvl3{h|Gz+rQnd1u6IM zln1=pZm+Kc_l>k%Evc!gtRFdEJC!6EzUK2kT_|a5BZG8{A?$B)0Ia4WjVEaNN6(}d z;{X4Hy=jS!jkV)zWc#T2`W=DXyXmN<6KV#A0|(W=$Q((@W-SP7zo4LCNN8x+)`ea1 z0*dd74GjksbkdTXOt_DkdA%}(`NW=&+wQ?>_&&dhgntE+7|hPbT05A6npgTpDB!SN znV(+}0kq~|qOdQ{6+bx=vB;?V`WO=vzs+~}YW%imXomHfz ze`|la{aHTKqJ6z~0`fV-YqiKIHZD%U`4BfVu8@`ATG;_RS1NK-*^!HUd@wvVG2N)k zqHc2eIDc@9sGhrGPR8(?sYYzy$o@nw+q==dtBF7JP0GLfgkvELA^I|0(WIX(ERYKo zvVbdpToos!=;#b;@*(w){f1ZA?G^_lt$yz%B_=2Pu9)QZo%QcHU@%x48Nl$SMNWB( zopSBHO@=Up)V_gflyA%_yoYVnl8}*MPa)(2My*k-_p%p2XhEU?Gvl}v!WdpfQY^MHp+j3uZ$kHX{SyVoyzbuC5B66Bv1v zw#Hsagvw!LVublu?p?afIXE~X#z%hT=KAOI)b%97fAy*j;({Fd(7CR?NFjohS+x7B zQ=%Zln8JbX-}PS3nq}iWu+TU{hMt!$0 zmc%^&YGu8yScoEE9pnu9_rt%d*#BRg)W6?4^eI)!yvpC}Yq=Wo{|Mm#p3J|}`YM80 zO$H4Adlyw^xPM94Uaznnmaq3ebpW-haF1UF?e!8dOo{(r>4b6XGTtlW%0G|ZgzY?? z@JA8EK~_F~U{>z0=eYOdj@BS{GPFupLG~fCH;+JPH7xAc1*2+1^3>`#vZNO5|C>G4 zu=9<&fZ^4^Z#@1jlma*sFDry}%K*s|Cts}L^3pK#It)evhwPyW>H{f zwEk{%=;t<@WJ@{+)=1TRLB;<}J8hWVca9Bfre8Fk`b2$%>?3aY61U46MTws}xOH}p zq&)t!A|x@(86gLy#DeH+qU-=V$dm(pkpAjQ2MudO|GPpUrzR?jqk?EMxQv3-U6+s{ z+YqWp`{hjmq@C)2R~IT}>mDCLJFb?GV0VUFI4TXKW6l3vk9iauJ(dS{3EH(!LR!WF z7!_@1_pq+$wuaB5dmmZ0jz%FKU*xeUaq}`>6C;obn*LFASxWt?k436n^uIT{rqQ}R zb<;LwUm|o{lS%GqA-)2rav29Q~dwEYGah>eO-~`<3ua1q#s+9l(-^m2%9YP!z=fV%+j4a)G4Ax6N6?*X0Zmo|FR`K^Z7xz|0e?hq_Ta zt1(44wOyOy7%Siv!*wD%K5{T}(8O)Mm?>XKZ$V;-R;9!K1!+~O6_ZK_yVQUZD_rs` zzzIiv2xcri5-Q*X7Fc<& zYRH3yl+spfHBnmMY$B@hUh4S0sq-_nHaWJiO%Cd>n#}6Cuqu?7 z1UM5mnb8b6E7$vm=@l^PTGm0+uB$bW>uE}&y$fT&d^7UOKnkrrl+7<2r{euNl(DT% zesO!~tP5-*kpkrv)vf|)i}X*ajqkv_5sr)6H8S*{yN5H(YjNE*qT}fSzqXn4tMp>y9_?iz=Q-r1a>l&fLax%YiFxbQqPLFt~iLLC0Cv#34D8`Px4V=t3jmhsDvAlSEoZ@E{Q#=h%m1CQk6qVR$ z(<+NJE-B(uP~3iZQiwVkkW{o*M^Bq(ncgO!Q$4D^9oAvp82C&=GpiuKDr^$%7&ty- zYq$_(L97s1x!6T?L~k0FHJfUIPL5_kMEB$O)w|Tp5S+@@XIL=?$C`ZvxD}K=UP$4Q zevBrQeg_I$gcxkj;O6d@!EQSM`dBqIOBQ=j>yKx<2ZzO>feSkgD7v=2{>@B z?oV^g`4w#T5_FYyd3Dov+w$YBR{CS&Rub%1l}*MlRJ*-Q#C*SZMAjM4kXj&j7136k z5U`uJx?QBqS!?zLWdxg9aIxdGN@gO|6nDFg2<>f zd^tx7u1ErbH=7XgyZZwS2I!EqF;G@kU&?pz*yZh$%y?5>V%gEq!o>%fJCQ8@aOtZ_ zb}|uR(_j=^3-o)qDWnL}uZ_#xU;d-cwepW-4J-E2AyrudhL^UQx@a*U4w>l2dik}7 z+ZVNBn{kw3O-Sw>t_CA{%oa4|7sA%KAnGld1O8Y6GUTCy{tEa%2^YSsEWNeT21HD! z)Fg|IMt<+esN3nYy6xyp@69CULmcrAda{St!xWjPa*3t^g~GtlFsFhNYV4gkPCYUW zrP4pn01a*-2^jEiR0G5bD-ZWlT#FSje21oUz(kW9bK_jVx;JlmSz&g9U3JO0w=d3; z`hy0X(O%6u7D3sWwSn~oiDa}}>M}p#sYX}z=m#a!5yM*%`0VK71&5Mbl$MdNp{hY1 zq4qtQpki}kF}$^3Lrqq8`CN~o>WyXYj6<_Ec`KtRAIVX^5sF0nb4os>weB(Ge(v4zNATz5MGVJ6HQwIaUYAj05W>3fowQ zGfIlherp-J10WP7R*^jq6t$oF;zgNZlMX8F2U`e%3=*7G+_?R(1(p8l4a*FnsUrp& z_L^}`g!K3OxooN`&{yDgzq(;?8VGxGU}#W(C_qw6jp+L80 zE5qGHcu{-8Aepw{4vC+V{fY2Vw3yz_fbMryXHu@&{1qb_1w2*NUa#+!4TjDcnwkZ# zEX-DOe~i^1J3Bb%o3fD*%YF;Eo+J97$33CZnSgs_rMhR#+dFZ5&$le;>}J;4IeG0_ z&y8mD-v_HWYVNvJ=>l-xBE@i%dnSM|-VA1#)I4Umr>BH7q#j_fl_R8cE6?FHzbxox zQDIl`W4krl;g9z1v|j4Y2yO_i-8a}cbw34^Nx(1iy2C}`4>`Wd; z|41L3Is1Ip8*H`!wp@Mmzy#_PVUx&Ok+}93V99@@!}dAF{BBFSlZ;mIUE-s2$aH@u z4fsbUXIM-!ImW6^G4qK(-myif>FpJqY!uvi+_Bk4VM#-csmf6P9%s8`={lSwJGdOzN zBVD<+_D>ji5zZiqgb&|z9Hz>*Cv*vIR^X_)kdrcKaNo=fxel6~PX4puUNPR&cqnRt zY|59hJ95UBV>)87plvH3Fetb=hr&#lyw^r;T*15XWs*l*ufE=oEN3V0Lw7ALODU); zML5H@)os5e=VFBywceovEBvu_r~lU}hj=07 zywt>{3hu%)-ghjd6BnwaB)o#pn;qk4K3;l{l#zGGr3v~EgYNSRv)fK8FD7u7!&9HU zgpo+~0Jqget7%c9V;_knVaPHFJb)qlEluNxE9{+uJ~!X3o#uIaB1995g0(GHc(Q-` z$d{Ue#;lcb!G2^jj&3gckn;q_&Y%s#^=gpuGZf+0?xj_xm}jHr_9q5g%I?KaB=Vc{j%A8?S%>H#4pvuJ+SV z?LH3FEntIt4{8P3lBDgfri_lJ&9e=ha8^1D_;mjL(~>nUZy0ia zuP#b_hDK>(HG02V@#se!?Hl!TA4puuWeAK%&j5mhevFde{gA4~KGBG(Wmuf*|tP@JrD*TYVj}mPk&FWxhln=zA+KKXxNHxf>QbZ%%{P(^tTOG-d-YODdzud>R&8FhSUb0`PK#2kQ*Mz{uYS&>!A`k zP-D||J=$I$Ena!3PR`sSodmx)T&Qh(IffG26JWj=X+3Tkt1&A6q{V+`Yg;BM}Dm-$-2`esnY(HiLKL-c)F6z{9XYynoo!&%A z@IL%1nRKb*w--D?9Qk1G%ZH@lY^aPqwIsx{@VB$BDFFkEWq z15U9Ib>b^hSJ_{N(Chy!>aRzHnm!rA$%etp>$v6ffh?K%8&a!>3=*w*Lq4-}`077D zr)K~J71%h{G*t!{@s=v>4Csu%#V5eSH_{1r0R&|j7Bq$~GgR(U++&lSKxNt%6vP+E z^Y9Z<_{F?uhK>W>QBE6jvh+TR3-zB zyR}jOFe*UOb3)^MDZVSr?dvuFu$k5MG$>cP)a(a7vfCUTFx5(}@cACoMikRc6F8+_ zSLL_U!PMtM$iG4dT_Z+wDpDVr?k4Q+Afh?Tmfa20bI>h92Rp|OMSpOWnNwsXqB#`4 zumCU5l^_smerGV1%*E$F2eG^ADYSBHQnI{_t5JITk8QosW)qa^bFi5vY26H{!Y`GA zl>0W{OL`IuuI$Z`{oh7#DtTL6xbD>Bd*&z^t#8y-!TPdt0a{64YKtHH(?6#p%!p+8 zQZmOSdm!T|zy>Z(EZxhZ0R_?C1+n&(EDtLG$LE@am3|Nw1Uz|mf}At&lWX3xVR8s- zu}#{yg2smhCil?XJsnt%KJj?Sw_K#!P?s6DcI3x?%hXbO=-`>RmbqXAaK8OdoXmZl zFiBw!VFz{<1?d-;>o!+K=y|~wVUk#K_Gh*+QZd;KzZNSJFWG4}P;>FX`29hM$^LR-^hJ_F}6A=?eq=a2G|<>GpN{|_~{ BGcy1H literal 0 HcmV?d00001 diff --git a/docs/running-relayer.md b/docs/running-relayer.md new file mode 100644 index 0000000000000..cda127cf0a8a5 --- /dev/null +++ b/docs/running-relayer.md @@ -0,0 +1,344 @@ +# Running your own bridge relayer + +:warning: :construction: Please read the [Disclaimer](#disclaimer) section first :construction: :warning: + +## Disclaimer + +There are several things you should know before running your own relayer: + +- initial bridge version (we call it bridges v1) supports any number of relayers, but **there's no guaranteed +compensation** for running a relayer and/or submitting valid bridge transactions. Most probably you'll end up +spending more funds than getting from rewards - please accept this fact; + +- even if your relayer has managed to submit a valid bridge transaction that has been included into the bridge +hub block, there's no guarantee that you will be able to claim your compensation for that transaction. That's +because compensations are paid from the account, controlled by relay chain governance and it could have no funds +to compensate your useful actions. We'll be working on a proper process to resupply it on-time, but we can't +provide any guarantee until that process is well established. + +## A Brief Introduction into Relayers and our Compensations Scheme + +Omitting details, relayer is an offchain process that is connected to both bridged chains. It looks at the +outbound bridge messages queue and submits message delivery transactions to the target chain. There's a lot +of details behind that simple phrase - you could find more info in the +[High-Level Bridge Overview](./high-level-overview.md) document. + +Reward that is paid to relayer has two parts. The first part static and is controlled by the governance. +It is rather small initially - e.g. you need to deliver `10_000` Kusama -> Polkadot messages to gain single +KSM token. + +The other reward part is dynamic. So to deliver an XCM message from one BridgeHub to another, we'll need to +submit two transactions on different chains. Every transaction has its cost, which is: + +- dynamic, because e.g. message size can change and/or fee factor of the target chain may change; + +- quite large, because those transactions are quite heavy (mostly in terms of size, not weight). + +We are compensating the cost of **valid**, **minimal** and **useful** bridge-related transactions to +relayer, that has submitted such transaction. Valid here means that the transaction doesn't fail. Minimal +means that all data within transaction call is actually required for the transaction to succeed. Useful +means that all supplied data in transaction is new and yet unknown to the target chain. + +We have implemented a relayer that is able to craft such transactions. The rest of document contains a detailed +information on how to deploy this software on your own node. + +## Relayers Concurrency + +As it has been said above, we are not compensating cost of transactions that are not **useful**. For +example, if message `100` has already been delivered from Kusama Bridge Hub to Polkadot Bridge Hub, then another +transaction that delivers the same message `100` won't be **useful**. Hence, no compensation to relayer that +has submitted that second transaction. + +But what if there are several relayers running? They are noticing the same queued message `100` and +simultaneously submit identical message delivery transactions. You may expect that there'll be one lucky +relayer, whose transaction would win the "race" and which will receive the compensation and reward. And +there'll be several other relayers, losing some funds on their unuseful transactions. + +But actually, we have a solution that invalidates transactions of "unlucky" relayers before they are +included into the block. So at least you may be sure that you won't waste your funds on duplicate transactions. + +

+Some details? + +All **unuseful** transactions are rejected by our +[transaction extension](https://github.com/paritytech/polkadot-sdk/blob/master/bridges/bin/runtime-common/src/refund_relayer_extension.rs), +which also handles transaction fee compensations. You may find more info on unuseful (aka obsolete) transactions +by lurking in the code. + +We also have the WiP prototype of relayers coordination protocol, where relayers will get some guarantee +that their transactions will be prioritized over other relayers transactions at their assigned slots. +That is planned for the future version of bridge and the progress is +[tracked here](https://github.com/paritytech/parity-bridges-common/issues/2486). + +
+ +## Prerequisites + +Let's focus on the bridge between Polkadot and Kusama Bridge Hubs. Let's also assume that we want to start +a relayer that "serves" an initial lane [`0x00000001`](https://github.com/polkadot-fellows/runtimes/blob/9ce1bbbbcd7843b3c76ba4d43c036bc311959e9f/system-parachains/bridge-hubs/bridge-hub-kusama/src/bridge_to_polkadot_config.rs#L54). + +
+Lane? + +Think of lane as a queue of messages that need to be delivered to the other/bridged chain. The lane is +bidirectional, meaning that there are four "endpoints". Two "outbound" endpoints (one at every chain), contain +messages that need to be delivered to the bridged chain. Two "inbound" are accepting messages from the bridged +chain and also remember the relayer, who has delivered message(s) to reward it later. + +
+ +The same steps may be performed for other lanes and bridges as well - you'll just need to change several parameters. + +So to start your relayer instance, you'll need to prepare: + +- an address of ws/wss RPC endpoint of the Kusama relay chain; + +- an address of ws/wss RPC endpoint of the Polkadot relay chain; + +- an address of ws/wss RPC endpoint of the Kusama Bridge Hub chain; + +- an address of ws/wss RPC endpoint of the Polkadot Bridge Hub chain; + +- an account on Kusama Bridge Hub; + +- an account on Polkadot Bridge Hub. + +For RPC endpoints, you could start your own nodes, or use some public community nodes. Nodes are not meant to be +archive or provide access to insecure RPC calls. + +To create an account on Bridge Hubs, you could use XCM teleport functionality. E.g. if you have an account on +the relay chain, you could use the `teleportAssets` call of `xcmPallet` and send asset +`V3 { id: Concrete(0, Here), Fungible: }` to beneficiary `V3(0, X1(AccountId32()))` +on destination `V3(0, X1(Parachain(1002)))`. To estimate amounts you need, please refer to the [Costs](#costs) +section of the document. + +## Registering your Relayer Account (Optional, But Please Read) + +Bridge transactions are quite heavy and expensive. We want to minimize block space that can be occupied by +invalid bridge transactions and prioritize valid transactions over invalid. That is achieved by **optional** +relayer registration. Transactions, signed by relayers with active registration, gain huge priority boost. +In exchange, such relayers may be slashed if they submit **invalid** or **non-minimal** transaction. + +Transactions, signed by relayers **without** active registration, on the other hand, receive no priority +boost. It means that if there is active registered relayer, most likely all transactions from unregistered +will be counted as **unuseful**, not included into the block and unregistered relayer won't get any reward +for his operations. + +Before registering, you should know several things about your funds: + +- to register, you need to hold significant amount of funds on your relayer account. As of now, it is + [100 KSM](https://github.com/polkadot-fellows/runtimes/blob/9ce1bbbbcd7843b3c76ba4d43c036bc311959e9f/system-parachains/bridge-hubs/bridge-hub-kusama/src/bridge_to_polkadot_config.rs#L71C14-L71C43) + for registration on Kusama Bridge Hub and + [500 DOT](https://github.com/polkadot-fellows/runtimes/blob/9ce1bbbbcd7843b3c76ba4d43c036bc311959e9f/system-parachains/bridge-hubs/bridge-hub-polkadot/src/bridge_to_kusama_config.rs#L71C14-L71C43) + for registration on Polkadot Bridge Hub; + +- when you are registered, those funds are reserved on relayer account and you can't transfer them. + +The registration itself, has three states: active, inactive or expired. Initially, it is active, meaning that all +your transactions that are **validated** on top of block, where it is active get priority boost. Registration +becomes expired when the block with the number you have specified during registration is "mined". It is the +`validTill` parameter of the `register` call (see below). After that `validTill` block, you may unregister and get +your reserved funds back. There's also an intermediate point between those blocks - it is the `validTill - LEASE`, +where `LEASE` is the the chain constant, controlled by the governance. Initially it is set to `300` blocks. +All your transactions, **validated** between the `validTill - LEASE` and `validTill` blocks do not get the +priority boost. Also, it is forbidden to specify `validTill` such that the `validTill - currentBlock` is less +than the `LEASE`. + +
+Example? + +| Bridge Hub Block | Registration State | Comment | +| ----------------- | ------------------ | ------------------------------------------------------ | +| 100 | Active | You have submitted a tx with the `register(1000)` call | +| 101 | Active | Your message delivery transactions are boosted | +| 102 | Active | Your message delivery transactions are boosted | +| ... | Active | Your message delivery transactions are boosted | +| 700 | Inactive | Your message delivery transactions are not boosted | +| 701 | Inactive | Your message delivery transactions are not boosted | +| ... | Inactive | Your message delivery transactions are not boosted | +| 1000 | Expired | Your may submit a tx with the `deregister` call | + +
+ +So once you have enough funds on your account and have selected the `validTill` parameter value, you +could use the Polkadot JS apps to submit an extrinsic. If you want priority boost for your transactions +on the Kusama Bridge Hub, open the +[Polkadot JS Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama-bridge-hub-rpc.polkadot.io#/extrinsics) +and submit the `register` extrinsic from the `bridgeRelayers` pallet: + +![Register Extrinsic](./bridge-relayers-register.png) + +To deregister, submit the simple `deregister` extrinsic when registration is expired: + +![Deregister Extrinsic](./bridge-relayers-deregister.png) + +At any time, you can prolong your registration by calling the `register` with the larger `validTill`. + +## Costs + +Your relayer account (on both Bridge Hubs) must hold enough funds to be able to pay costs of bridge +transactions. If your relayer behaves correctly, those costs will be compensated and you will be +able to claim it later. + +**IMPORTANT**: you may add tip to your bridge transactions to boost their priority. But our +compensation mechanism never refunds transaction tip, so all tip tokens will be lost. + +
+Types of bridge transactions + +There are two types of bridge transactions: + +- message delivery transaction brings queued message(s) from one Bridge Hub to another. We record + the fact that this specific (your) relayer has delivered those messages; + +- message confirmation transaction confirms that some message have been delivered and also brings + back information on how many messages (your) relayer has delivered. We use this information later + to register delivery rewards on the source chain. + +Several messages/confirmations may be included in a single bridge transaction. Apart from this +data, bridge transaction may include finality and storage proofs, required to prove authenticity of +this data. + +
+ +To deliver and get reward for a single message, the relayer needs to submit two transactions. One +at the source Bridge Hub and one at the target Bridge Hub. Below are costs for Polkadot <> Kusama +messages (as of today): + +- to deliver a single Polkadot -> Kusama message, you would need to pay around `0.06 KSM` at Kusama + Bridge Hub and around `1.62 DOT` at Polkadot Bridge Hub; + +- to deliver a single Kusama -> Polkadot message, you would need to pay around `1.70 DOT` at Polkadot + Bridge Hub and around `0.05 KSM` at Kusama Bridge Hub. + +Those values are not constants - they depend on call weights (that may change from release to release), +on transaction sizes (that depends on message size and chain state) and congestion factor. In any +case - it is your duty to make sure that the relayer has enough funds to pay transaction fees. + +## Claiming your Compensations and Rewards + +Hopefully you have successfully delivered some messages and now can claim your compensation and reward. +This requires submitting several transactions. But first, let's check that you actually have something to +claim. For that, let's check the state of the pallet that tracks all rewards. + +To check your rewards at the Kusama Bridge Hub, go to the +[Polkadot JS Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama-bridge-hub-rpc.polkadot.io#/chainstate) +targeting Kusama Bridge Hub, select the `bridgeRelayers` pallet, choose `relayerRewards` map and +your relayer account. Then: + +- set the `laneId` to `0x00000001` + +- set the `bridgedChainId` to `bhpd`; + +- check the both variants of the `owner` field: `ThisChain` is used to pay for message delivery transactions + and `BridgedChain` is used to pay for message confirmation transactions. + +If check shows that you have some rewards, you can craft the claim transaction, with similar parameters. +For that, go to `Extrinsics` tab of the +[Polkadot JS Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama-bridge-hub-rpc.polkadot.io#/extrinsics) +and submit the following transaction (make sure to change `owner` before): + +![Claim Rewards Extrinsic](./bridge-relayers-claim-rewards.png) + +To claim rewards on Polkadot Bridge Hub you can follow the same process. The only difference is that you +need to set value of the `bridgedChainId` to `bhks`. + +## Starting your Relayer + +### Starting your Rococo <> Westend Relayer + +We are using the following docker image to run our own Rococo <> Westend relayer: + +[paritytech/bridges-common-relay:v2024-02-16-rococo-westend-relayer](https://hub.docker.com/layers/paritytech/bridges-common-relay/v2024-02-16-rococo-westend-relayer/images/sha256-5ba4260d6bc2ac9e97c2e05d875f6dc44ee9265011311f268b66b8a5a672ada3?context=explore) + +You can grab the sources and build it manually: + +[v2024-02-16-rococo-westend-relayer](https://github.com/paritytech/parity-bridges-common/releases/tag/v2024-02-16-rococo-westend-relayer) + +Once you have the docker, update variables and run the following script: +```sh +export DOCKER_IMAGE= + +export ROCOCO_HOST= +export ROCOCO_PORT= +# or set it to '--rococo-secure' if wss is used above +export ROCOCO_IS_SECURE= +export BRIDGE_HUB_ROCOCO_HOST= +export BRIDGE_HUB_ROCOCO_PORT= +# or set it to '--bridge-hub-rococo-secure' if wss is used above +export BRIDGE_HUB_ROCOCO_IS_SECURE= +export BRIDGE_HUB_ROCOCO_KEY_FILE= + +export WESTEND_HOST= +export WESTEND_PORT= +# or set it to '--westend-secure' if wss is used above +export WESTEND_IS_SECURE= +export BRIDGE_HUB_WESTEND_HOST= +export BRIDGE_HUB_WESTEND_PORT= +# or set it to '--bridge-hub-westend-secure ' if wss is used above +export BRIDGE_HUB_WESTEND_IS_SECURE= +export BRIDGE_HUB_WESTEND_KEY_FILE= + +# you can get extended relay logs (e.g. for debugging issues) by passing `-e RUST_LOG=bridge=trace` +# argument to the `docker` binary +docker run \ + -v $BRIDGE_HUB_ROCOCO_KEY_FILE:/bhr.key \ + -v $BRIDGE_HUB_WESTEND_KEY_FILE:/bhw.key \ + $DOCKER_IMAGE \ + relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \ + --rococo-host $ROCOCO_HOST \ + --rococo-port $ROCOCO_PORT \ + $ROCOCO_IS_SECURE \ + --rococo-version-mode Auto \ + --bridge-hub-rococo-host $BRIDGE_HUB_ROCOCO_HOST \ + --bridge-hub-rococo-port $BRIDGE_HUB_ROCOCO_PORT \ + $BRIDGE_HUB_ROCOCO_IS_SECURE \ + --bridge-hub-rococo-version-mode Auto \ + --bridge-hub-rococo-signer-file /bhr.key \ + --bridge-hub-rococo-transactions-mortality 16 \ + --westend-host $WESTEND_HOST \ + --westend-port $WESTEND_PORT \ + $WESTEND_IS_SECURE \ + --westend-version-mode Auto \ + --bridge-hub-westend-host $BRIDGE_HUB_WESTEND_HOST \ + --bridge-hub-westend-port $BRIDGE_HUB_WESTEND_PORT \ + $BRIDGE_HUB_WESTEND_IS_SECURE \ + --bridge-hub-westend-version-mode Auto \ + --bridge-hub-westend-signer-file /bhw.key \ + --bridge-hub-westend-transactions-mortality 16 \ + --lane 00000002 +``` + +### Starting your Polkadot <> Kusama Relayer + +*Work in progress, coming soon* + +### Watching your relayer state + +Our relayer provides some Prometheus metrics that you may convert into some fancy Grafana dashboards +and alerts. By default, metrics are exposed at port `9616`. To expose endpoint to the localhost, change +the docker command by adding following two lines: + +```sh +docker run \ + .. + -p 127.0.0.1:9616:9616 \ # tell Docker to bind container port 9616 to host port 9616 + # and listen for connections on the host' localhost interface + .. + $DOCKER_IMAGE \ + relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \ + --prometheus-host 0.0.0.0 \ # tell `substrate-relay` binary to accept Prometheus endpoint + # connections from everywhere + .. +``` + +You can find more info on configuring Prometheus and Grafana in the +[Monitor your node](https://wiki.polkadot.network/docs/maintain-guides-how-to-monitor-your-node) +guide from Polkadot wiki. + +We have our own set of Grafana dashboards and alerts. You may use them for inspiration. +Please find them in this folder: + +- for Rococo <> Westend bridge: [rococo-westend](https://github.com/paritytech/parity-bridges-common/tree/master/deployments/bridges/rococo-westend). + +- for Polkadot <> Kusama bridge: *work in progress, coming soon* From 53165a9945a1c8cbc75fa60edc494b55f4d3f090 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 1 Mar 2024 12:50:20 +0300 Subject: [PATCH 1185/1210] [Do Not Merge until RBH/WBH upgrade] Relayers use new submit_finality_proof_ex call in Rococo <> Westend bridge (#2827) * use codegen runtime in WBH + update codegen files for RBH + WBH * use submit_finality_proof_ex for Rococo <> Westend bridge --- ...b_rococo_messages_to_bridge_hub_westend.rs | 4 +- ...b_westend_messages_to_bridge_hub_rococo.rs | 4 +- .../rococo_headers_to_bridge_hub_westend.rs | 6 +- ...rococo_parachains_to_bridge_hub_westend.rs | 4 +- .../westend_headers_to_bridge_hub_rococo.rs | 4 +- relays/bin-substrate/src/cli/init_bridge.rs | 6 +- .../src/codegen_runtime.rs | 2090 ++++++-- relays/client-bridge-hub-westend/Cargo.toml | 2 +- .../src/codegen_runtime.rs | 4705 +++++++++++++++++ relays/client-bridge-hub-westend/src/lib.rs | 44 +- .../src/runtime_wrapper.rs | 116 - .../lib-substrate-relay/src/finality/mod.rs | 40 + 12 files changed, 6560 insertions(+), 465 deletions(-) create mode 100644 relays/client-bridge-hub-westend/src/codegen_runtime.rs delete mode 100644 relays/client-bridge-hub-westend/src/runtime_wrapper.rs diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs index 353fa7df32a4e..cbf122a2d4b08 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs @@ -35,8 +35,8 @@ impl MessagesCliBridge for BridgeHubRococoToBridgeHubWestendMessagesCliBridge { substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubRococoMessagesToBridgeHubWestendMessageLane, BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_westend_client::runtime::Call::BridgeRococoMessages, - relay_bridge_hub_westend_client::runtime::BridgeRococoMessagesCall::receive_messages_proof + relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoMessages, + relay_bridge_hub_westend_client::BridgeMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs index ceea252db4216..bb823981bf89e 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs @@ -42,8 +42,8 @@ substrate_relay_helper::generate_receive_message_proof_call_builder!( substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubWestendMessagesToBridgeHubRococoMessageLane, BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_westend_client::runtime::Call::BridgeRococoMessages, - relay_bridge_hub_westend_client::runtime::BridgeRococoMessagesCall::receive_messages_delivery_proof + relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoMessages, + relay_bridge_hub_westend_client::BridgeMessagesCall::receive_messages_delivery_proof ); /// Description of BridgeHubWestend -> BridgeHubRococo messages bridge. diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs index 24d0b6603157a..6e6661d5417c8 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs @@ -31,11 +31,11 @@ use substrate_relay_helper::{ #[derive(Clone, Debug)] pub struct RococoFinalityToBridgeHubWestend; -substrate_relay_helper::generate_submit_finality_proof_call_builder!( +substrate_relay_helper::generate_submit_finality_proof_ex_call_builder!( RococoFinalityToBridgeHubWestend, SubmitFinalityProofCallBuilder, - relay_bridge_hub_westend_client::runtime::Call::BridgeRococoGrandpa, - relay_bridge_hub_westend_client::runtime::BridgeRococoGrandpaCall::submit_finality_proof + relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoGrandpa, + relay_bridge_hub_westend_client::BridgeGrandpaCall::submit_finality_proof_ex ); substrate_relay_helper::generate_report_equivocation_call_builder!( diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs index edd600acc4d5b..16b646233eed8 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs @@ -44,8 +44,8 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_westend_client::runtime::Call::BridgeRococoParachains( - relay_bridge_hub_westend_client::runtime::BridgeParachainCall::submit_parachain_heads { + relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoParachains( + relay_bridge_hub_westend_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs index 451089b2ce009..6f4ebb84a834e 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs @@ -31,11 +31,11 @@ use substrate_relay_helper::{ #[derive(Clone, Debug)] pub struct WestendFinalityToBridgeHubRococo; -substrate_relay_helper::generate_submit_finality_proof_call_builder!( +substrate_relay_helper::generate_submit_finality_proof_ex_call_builder!( WestendFinalityToBridgeHubRococo, SubmitFinalityProofCallBuilder, relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendGrandpa, - relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof + relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof_ex ); substrate_relay_helper::generate_report_equivocation_call_builder!( diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 027dd4c482f87..52cb28014f454 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -122,10 +122,8 @@ impl BridgeInitializer for RococoToBridgeHubWestendCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - relay_bridge_hub_westend_client::runtime::Call::BridgeRococoGrandpa( - relay_bridge_hub_westend_client::runtime::BridgeRococoGrandpaCall::initialize { - init_data, - }, + relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoGrandpa( + relay_bridge_hub_westend_client::BridgeGrandpaCall::initialize { init_data }, ) } } diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs index 2afdeb2489363..bfb7c3e9d3d1f 100644 --- a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs @@ -17,8 +17,8 @@ //! Autogenerated runtime API //! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen //! EXECUTED COMMAND: target/debug/runtime-codegen --from-wasm-file -//! /home/svyatonik/dev/polkadot-sdk/target/debug/wbuild/bridge-hub-rococo-runtime/ -//! bridge_hub_rococo_runtime.wasm +//! ../../../polkadot-sdk/target/release/wbuild/bridge-hub-rococo-runtime/bridge_hub_rococo_runtime. +//! compact.compressed.wasm #[allow(dead_code, unused_imports, non_camel_case_types)] #[allow(clippy::all)] @@ -240,6 +240,23 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct StrippableError; } + pub mod bridge_hub_common { + use super::runtime_types; + pub mod message_queue { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + Parent, + #[codec(index = 2)] + Sibling(runtime_types::polkadot_parachain_primitives::primitives::Id), + #[codec(index = 3)] + Snowbridge(runtime_types::snowbridge_core::ChannelId), + } + } + } pub mod bridge_hub_rococo_runtime { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -269,6 +286,8 @@ pub mod api { ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), #[codec(index = 2)] Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 3)] + ParachainInfo(runtime_types::staging_parachain_info::pallet::Call), #[codec(index = 10)] Balances(runtime_types::pallet_balances::pallet::Call), #[codec(index = 21)] @@ -279,24 +298,38 @@ pub mod api { XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), #[codec(index = 31)] PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Call), #[codec(index = 40)] Utility(runtime_types::pallet_utility::pallet::Call), #[codec(index = 36)] Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 47)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), #[codec(index = 48)] BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 60)] - BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call2), #[codec(index = 49)] BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Call), #[codec(index = 51)] BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 60)] + BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call2), #[codec(index = 61)] BridgePolkadotBulletinMessages( runtime_types::pallet_bridge_messages::pallet::Call2, ), - #[codec(index = 47)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + #[codec(index = 80)] + EthereumInboundQueue(runtime_types::snowbridge_pallet_inbound_queue::pallet::Call), + #[codec(index = 81)] + EthereumOutboundQueue( + runtime_types::snowbridge_pallet_outbound_queue::pallet::Call, + ), + #[codec(index = 82)] + EthereumBeaconClient( + runtime_types::snowbridge_pallet_ethereum_client::pallet::Call, + ), + #[codec(index = 83)] + EthereumSystem(runtime_types::snowbridge_pallet_system::pallet::Call), #[codec(index = 250)] MessageQueue(runtime_types::pallet_message_queue::pallet::Call), } @@ -320,20 +353,32 @@ pub mod api { Utility(runtime_types::pallet_utility::pallet::Error), #[codec(index = 36)] Multisig(runtime_types::pallet_multisig::pallet::Error), + #[codec(index = 47)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), #[codec(index = 48)] BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), - #[codec(index = 52)] - BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error2), #[codec(index = 49)] BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Error), #[codec(index = 51)] BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Error), - #[codec(index = 53)] + #[codec(index = 60)] + BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error2), + #[codec(index = 61)] BridgePolkadotBulletinMessages( runtime_types::pallet_bridge_messages::pallet::Error2, ), - #[codec(index = 47)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), + #[codec(index = 80)] + EthereumInboundQueue(runtime_types::snowbridge_pallet_inbound_queue::pallet::Error), + #[codec(index = 81)] + EthereumOutboundQueue( + runtime_types::snowbridge_pallet_outbound_queue::pallet::Error, + ), + #[codec(index = 82)] + EthereumBeaconClient( + runtime_types::snowbridge_pallet_ethereum_client::pallet::Error, + ), + #[codec(index = 83)] + EthereumSystem(runtime_types::snowbridge_pallet_system::pallet::Error), #[codec(index = 250)] MessageQueue(runtime_types::pallet_message_queue::pallet::Error), } @@ -361,20 +406,32 @@ pub mod api { Utility(runtime_types::pallet_utility::pallet::Event), #[codec(index = 36)] Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 47)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), #[codec(index = 48)] BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 52)] - BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event2), #[codec(index = 49)] BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Event), #[codec(index = 51)] BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Event), - #[codec(index = 53)] + #[codec(index = 60)] + BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event2), + #[codec(index = 61)] BridgePolkadotBulletinMessages( runtime_types::pallet_bridge_messages::pallet::Event2, ), - #[codec(index = 47)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 80)] + EthereumInboundQueue(runtime_types::snowbridge_pallet_inbound_queue::pallet::Event), + #[codec(index = 81)] + EthereumOutboundQueue( + runtime_types::snowbridge_pallet_outbound_queue::pallet::Event, + ), + #[codec(index = 82)] + EthereumBeaconClient( + runtime_types::snowbridge_pallet_ethereum_client::pallet::Event, + ), + #[codec(index = 83)] + EthereumSystem(runtime_types::snowbridge_pallet_system::pallet::Event), #[codec(index = 250)] MessageQueue(runtime_types::pallet_message_queue::pallet::Event), } @@ -444,15 +501,13 @@ pub mod api { #[codec(index = 2)] ValidationFunctionDiscarded, #[codec(index = 3)] - UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] DownwardMessagesReceived { count: ::core::primitive::u32 }, - #[codec(index = 5)] + #[codec(index = 4)] DownwardMessagesProcessed { weight_used: ::sp_weights::Weight, dmq_head: ::subxt::utils::H256, }, - #[codec(index = 6)] + #[codec(index = 5)] UpwardMessageSent { message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, }, @@ -482,17 +537,14 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CodeUpgradeAuthorization { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } } pub mod cumulus_pallet_xcm { use super::runtime_types; pub mod pallet { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] InvalidFormat([::core::primitive::u8; 32usize]), @@ -501,7 +553,7 @@ pub mod api { #[codec(index = 2)] ExecutedDownward( [::core::primitive::u8; 32usize], - runtime_types::xcm::v3::traits::Outcome, + runtime_types::staging_xcm::v4::traits::Outcome, ), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -565,21 +617,6 @@ pub mod api { pub suspend_threshold: ::core::primitive::u32, pub drop_threshold: ::core::primitive::u32, pub resume_threshold: ::core::primitive::u32, - pub threshold_weight: ::sp_weights::Weight, - pub weight_restrict_decay: ::sp_weights::Weight, - pub xcmp_max_individual_weight: ::sp_weights::Weight, - } - } - pub mod cumulus_primitives_core { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - Parent, - #[codec(index = 2)] - Sibling(runtime_types::polkadot_parachain_primitives::primitives::Id), } } pub mod cumulus_primitives_parachain_inherent { @@ -800,6 +837,12 @@ pub mod api { }, #[codec(index = 7)] remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 9)] + authorize_upgrade { code_hash: ::subxt::utils::H256 }, + #[codec(index = 10)] + authorize_upgrade_without_checks { code_hash: ::subxt::utils::H256 }, + #[codec(index = 11)] + apply_authorized_upgrade { code: ::std::vec::Vec<::core::primitive::u8> }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { @@ -815,6 +858,10 @@ pub mod api { NonZeroRefCount, #[codec(index = 5)] CallFiltered, + #[codec(index = 6)] + NothingAuthorized, + #[codec(index = 7)] + Unauthorized, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { @@ -835,6 +882,11 @@ pub mod api { KilledAccount { account: ::sp_core::crypto::AccountId32 }, #[codec(index = 5)] Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + #[codec(index = 6)] + UpgradeAuthorized { + code_hash: ::subxt::utils::H256, + check_version: ::core::primitive::bool, + }, } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] @@ -846,6 +898,11 @@ pub mod api { pub data: _1, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CodeUpgradeAuthorization { + pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct EventRecord<_0, _1> { pub phase: runtime_types::frame_system::Phase, pub event: _0, @@ -910,6 +967,12 @@ pub mod api { #[codec(compact)] new_free: ::core::primitive::u128, }, + #[codec(index = 9)] + force_adjust_total_issuance { + direction: runtime_types::pallet_balances::types::AdjustmentDirection, + #[codec(compact)] + delta: ::core::primitive::u128, + }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { @@ -933,6 +996,10 @@ pub mod api { TooManyHolds, #[codec(index = 9)] TooManyFreezes, + #[codec(index = 10)] + IssuanceDeactivated, + #[codec(index = 11)] + DeltaZero, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { @@ -1015,6 +1082,11 @@ pub mod api { Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, #[codec(index = 20)] Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 21)] + TotalIssuanceForced { + old: ::core::primitive::u128, + new: ::core::primitive::u128, + }, } } pub mod types { @@ -1027,6 +1099,13 @@ pub mod api { pub flags: runtime_types::pallet_balances::types::ExtraFlags, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AdjustmentDirection { + #[codec(index = 0)] + Increase, + #[codec(index = 1)] + Decrease, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct BalanceLock<_0> { pub id: [::core::primitive::u8; 8usize], pub amount: _0, @@ -1098,6 +1177,22 @@ pub mod api { set_operating_mode { operating_mode: runtime_types::bp_runtime::BasicOperatingMode, }, + #[codec(index = 4)] + submit_finality_proof_ex { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + current_set_id: ::core::primitive::u64, + }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Call2 { @@ -1131,6 +1226,22 @@ pub mod api { set_operating_mode { operating_mode: runtime_types::bp_runtime::BasicOperatingMode, }, + #[codec(index = 4)] + submit_finality_proof_ex { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + current_set_id: ::core::primitive::u64, + }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { @@ -1150,6 +1261,8 @@ pub mod api { TooManyAuthoritiesInSet, #[codec(index = 7)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + #[codec(index = 8)] + InvalidAuthoritySetId, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error2 { @@ -1169,6 +1282,8 @@ pub mod api { TooManyAuthoritiesInSet, #[codec(index = 7)] BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + #[codec(index = 8)] + InvalidAuthoritySetId, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { @@ -1251,10 +1366,10 @@ pub mod api { # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error2 { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } @@ -1512,13 +1627,13 @@ pub mod api { #[codec(index = 0)] reap_page { message_origin: - runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, page_index: ::core::primitive::u32, }, #[codec(index = 1)] execute_overweight { message_origin: - runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, page: ::core::primitive::u32, index: ::core::primitive::u32, weight_limit: ::sp_weights::Weight, @@ -1542,32 +1657,38 @@ pub mod api { TemporarilyUnprocessable, #[codec(index = 7)] QueuePaused, + #[codec(index = 8)] + RecursiveDisallowed, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] ProcessingFailed { - id: [::core::primitive::u8; 32usize], - origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + id: ::subxt::utils::H256, + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, error: runtime_types::frame_support::traits::messages::ProcessMessageError, }, #[codec(index = 1)] Processed { - id: [::core::primitive::u8; 32usize], - origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + id: ::subxt::utils::H256, + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, weight_used: ::sp_weights::Weight, success: ::core::primitive::bool, }, #[codec(index = 2)] OverweightEnqueued { id: [::core::primitive::u8; 32usize], - origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, page_index: ::core::primitive::u32, message_index: ::core::primitive::u32, }, #[codec(index = 3)] PageReaped { - origin: runtime_types::cumulus_primitives_core::AggregateMessageOrigin, + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, index: ::core::primitive::u32, }, } @@ -1876,21 +1997,21 @@ pub mod api { pub enum Call { #[codec(index = 0)] send { - dest: ::std::boxed::Box, + dest: ::std::boxed::Box, message: ::std::boxed::Box, }, #[codec(index = 1)] teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, fee_asset_item: ::core::primitive::u32, }, #[codec(index = 2)] reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, fee_asset_item: ::core::primitive::u32, }, #[codec(index = 3)] @@ -1900,9 +2021,8 @@ pub mod api { }, #[codec(index = 4)] force_xcm_version { - location: ::std::boxed::Box< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, + location: + ::std::boxed::Box, version: ::core::primitive::u32, }, #[codec(index = 5)] @@ -1911,30 +2031,38 @@ pub mod api { }, #[codec(index = 6)] force_subscribe_version_notify { - location: ::std::boxed::Box, + location: ::std::boxed::Box, }, #[codec(index = 7)] force_unsubscribe_version_notify { - location: ::std::boxed::Box, + location: ::std::boxed::Box, }, #[codec(index = 8)] limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, fee_asset_item: ::core::primitive::u32, weight_limit: runtime_types::xcm::v3::WeightLimit, }, #[codec(index = 9)] limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, fee_asset_item: ::core::primitive::u32, weight_limit: runtime_types::xcm::v3::WeightLimit, }, #[codec(index = 10)] force_suspension { suspended: ::core::primitive::bool }, + #[codec(index = 11)] + transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Error { @@ -1992,23 +2120,23 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Event { #[codec(index = 0)] - Attempted { outcome: runtime_types::xcm::v3::traits::Outcome }, + Attempted { outcome: runtime_types::staging_xcm::v4::traits::Outcome }, #[codec(index = 1)] Sent { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - message: runtime_types::xcm::v3::Xcm, + origin: runtime_types::staging_xcm::v4::location::Location, + destination: runtime_types::staging_xcm::v4::location::Location, + message: runtime_types::staging_xcm::v4::Xcm, message_id: [::core::primitive::u8; 32usize], }, #[codec(index = 2)] UnexpectedResponse { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + origin: runtime_types::staging_xcm::v4::location::Location, query_id: ::core::primitive::u64, }, #[codec(index = 3)] ResponseReady { query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, + response: runtime_types::staging_xcm::v4::Response, }, #[codec(index = 4)] Notified { @@ -2038,15 +2166,15 @@ pub mod api { }, #[codec(index = 8)] InvalidResponder { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + origin: runtime_types::staging_xcm::v4::location::Location, query_id: ::core::primitive::u64, expected_location: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, + runtime_types::staging_xcm::v4::location::Location, >, }, #[codec(index = 9)] InvalidResponderVersion { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + origin: runtime_types::staging_xcm::v4::location::Location, query_id: ::core::primitive::u64, }, #[codec(index = 10)] @@ -2054,98 +2182,97 @@ pub mod api { #[codec(index = 11)] AssetsTrapped { hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, + origin: runtime_types::staging_xcm::v4::location::Location, + assets: runtime_types::xcm::VersionedAssets, }, #[codec(index = 12)] VersionChangeNotified { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + destination: runtime_types::staging_xcm::v4::location::Location, result: ::core::primitive::u32, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, + cost: runtime_types::staging_xcm::v4::asset::Assets, message_id: [::core::primitive::u8; 32usize], }, #[codec(index = 13)] SupportedVersionChanged { - location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + location: runtime_types::staging_xcm::v4::location::Location, version: ::core::primitive::u32, }, #[codec(index = 14)] NotifyTargetSendFail { - location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + location: runtime_types::staging_xcm::v4::location::Location, query_id: ::core::primitive::u64, error: runtime_types::xcm::v3::traits::Error, }, #[codec(index = 15)] NotifyTargetMigrationFail { - location: runtime_types::xcm::VersionedMultiLocation, + location: runtime_types::xcm::VersionedLocation, query_id: ::core::primitive::u64, }, #[codec(index = 16)] InvalidQuerierVersion { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + origin: runtime_types::staging_xcm::v4::location::Location, query_id: ::core::primitive::u64, }, #[codec(index = 17)] InvalidQuerier { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + origin: runtime_types::staging_xcm::v4::location::Location, query_id: ::core::primitive::u64, - expected_querier: - runtime_types::staging_xcm::v3::multilocation::MultiLocation, + expected_querier: runtime_types::staging_xcm::v4::location::Location, maybe_actual_querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, + runtime_types::staging_xcm::v4::location::Location, >, }, #[codec(index = 18)] VersionNotifyStarted { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, + destination: runtime_types::staging_xcm::v4::location::Location, + cost: runtime_types::staging_xcm::v4::asset::Assets, message_id: [::core::primitive::u8; 32usize], }, #[codec(index = 19)] VersionNotifyRequested { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, + destination: runtime_types::staging_xcm::v4::location::Location, + cost: runtime_types::staging_xcm::v4::asset::Assets, message_id: [::core::primitive::u8; 32usize], }, #[codec(index = 20)] VersionNotifyUnrequested { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, + destination: runtime_types::staging_xcm::v4::location::Location, + cost: runtime_types::staging_xcm::v4::asset::Assets, message_id: [::core::primitive::u8; 32usize], }, #[codec(index = 21)] FeesPaid { - paying: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - fees: runtime_types::xcm::v3::multiasset::MultiAssets, + paying: runtime_types::staging_xcm::v4::location::Location, + fees: runtime_types::staging_xcm::v4::asset::Assets, }, #[codec(index = 22)] AssetsClaimed { hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, + origin: runtime_types::staging_xcm::v4::location::Location, + assets: runtime_types::xcm::VersionedAssets, }, } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Origin { #[codec(index = 0)] - Xcm(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + Xcm(runtime_types::staging_xcm::v4::location::Location), #[codec(index = 1)] - Response(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + Response(runtime_types::staging_xcm::v4::location::Location), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum QueryStatus<_0> { #[codec(index = 0)] Pending { - responder: runtime_types::xcm::VersionedMultiLocation, + responder: runtime_types::xcm::VersionedLocation, maybe_match_querier: - ::core::option::Option, + ::core::option::Option, maybe_notify: ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, timeout: _0, }, #[codec(index = 1)] VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, + origin: runtime_types::xcm::VersionedLocation, is_active: ::core::primitive::bool, }, #[codec(index = 2)] @@ -2154,8 +2281,8 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RemoteLockedFungibleRecord<_0> { pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, + pub owner: runtime_types::xcm::VersionedLocation, + pub locker: runtime_types::xcm::VersionedLocation, pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( _0, ::core::primitive::u128, @@ -2268,243 +2395,1561 @@ pub mod api { } } } - pub mod sp_arithmetic { + pub mod primitive_types { use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } + pub struct U256(pub [::core::primitive::u64; 4usize]); } - pub mod sp_consensus_aura { + pub mod snowbridge_amcl { use super::runtime_types; - pub mod sr25519 { + pub mod bls381 { use super::runtime_types; - pub mod app_sr25519 { + pub mod big { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); + pub struct Big { + pub w: [::core::primitive::i32; 14usize], + } + } + pub mod ecp { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ECP { + pub x: runtime_types::snowbridge_amcl::bls381::fp::FP, + pub y: runtime_types::snowbridge_amcl::bls381::fp::FP, + pub z: runtime_types::snowbridge_amcl::bls381::fp::FP, + } + } + pub mod fp { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FP { + pub x: runtime_types::snowbridge_amcl::bls381::big::Big, + pub xes: ::core::primitive::i32, + } } } } - pub mod sp_consensus_grandpa { + pub mod snowbridge_beacon_primitives { use super::runtime_types; - pub mod app { + pub mod bls { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + pub enum BlsError { + #[codec(index = 0)] + InvalidSignature, + #[codec(index = 1)] + InvalidPublicKey, + #[codec(index = 2)] + InvalidAggregatePublicKeys, + #[codec(index = 3)] + SignatureVerificationFailed, + } } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { + pub mod types { use super::runtime_types; + pub mod deneb { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutionPayloadHeader { + pub parent_hash: ::subxt::utils::H256, + pub fee_recipient: ::subxt::utils::H160, + pub state_root: ::subxt::utils::H256, + pub receipts_root: ::subxt::utils::H256, + pub logs_bloom: ::std::vec::Vec<::core::primitive::u8>, + pub prev_randao: ::subxt::utils::H256, + pub block_number: ::core::primitive::u64, + pub gas_limit: ::core::primitive::u64, + pub gas_used: ::core::primitive::u64, + pub timestamp: ::core::primitive::u64, + pub extra_data: ::std::vec::Vec<::core::primitive::u8>, + pub base_fee_per_gas: runtime_types::primitive_types::U256, + pub block_hash: ::subxt::utils::H256, + pub transactions_root: ::subxt::utils::H256, + pub withdrawals_root: ::subxt::utils::H256, + pub blob_gas_used: ::core::primitive::u64, + pub excess_blob_gas: ::core::primitive::u64, + } + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; + pub struct BeaconHeader { + pub slot: ::core::primitive::u64, + pub proposer_index: ::core::primitive::u64, + pub parent_root: ::subxt::utils::H256, + pub state_root: ::subxt::utils::H256, + pub body_root: ::subxt::utils::H256, + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; + pub struct CompactBeaconState { + #[codec(compact)] + pub slot: ::core::primitive::u64, + pub block_roots_root: ::subxt::utils::H256, + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); + pub struct CompactExecutionHeader { + pub parent_hash: ::subxt::utils::H256, + #[codec(compact)] + pub block_number: ::core::primitive::u64, + pub state_root: ::subxt::utils::H256, + pub receipts_root: ::subxt::utils::H256, + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); + pub struct ExecutionHeaderState { + pub beacon_block_root: ::subxt::utils::H256, + pub beacon_slot: ::core::primitive::u64, + pub block_hash: ::subxt::utils::H256, + pub block_number: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutionPayloadHeader { + pub parent_hash: ::subxt::utils::H256, + pub fee_recipient: ::subxt::utils::H160, + pub state_root: ::subxt::utils::H256, + pub receipts_root: ::subxt::utils::H256, + pub logs_bloom: ::std::vec::Vec<::core::primitive::u8>, + pub prev_randao: ::subxt::utils::H256, + pub block_number: ::core::primitive::u64, + pub gas_limit: ::core::primitive::u64, + pub gas_used: ::core::primitive::u64, + pub timestamp: ::core::primitive::u64, + pub extra_data: ::std::vec::Vec<::core::primitive::u8>, + pub base_fee_per_gas: runtime_types::primitive_types::U256, + pub block_hash: ::subxt::utils::H256, + pub transactions_root: ::subxt::utils::H256, + pub withdrawals_root: ::subxt::utils::H256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Fork { + pub version: [::core::primitive::u8; 4usize], + pub epoch: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ForkVersions { + pub genesis: runtime_types::snowbridge_beacon_primitives::types::Fork, + pub altair: runtime_types::snowbridge_beacon_primitives::types::Fork, + pub bellatrix: runtime_types::snowbridge_beacon_primitives::types::Fork, + pub capella: runtime_types::snowbridge_beacon_primitives::types::Fork, + pub deneb: runtime_types::snowbridge_beacon_primitives::types::Fork, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PublicKey(pub [::core::primitive::u8; 48usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 96usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SyncAggregate { + pub sync_committee_bits: [::core::primitive::u8; 64usize], + pub sync_committee_signature: + runtime_types::snowbridge_beacon_primitives::types::Signature, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SyncCommittee { + pub pubkeys: + [runtime_types::snowbridge_beacon_primitives::types::PublicKey; 512usize], + pub aggregate_pubkey: + runtime_types::snowbridge_beacon_primitives::types::PublicKey, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SyncCommitteePrepared { + pub root: ::subxt::utils::H256, + pub pubkeys: ::std::boxed::Box< + [runtime_types::snowbridge_milagro_bls::keys::PublicKey; 512usize], + >, + pub aggregate_pubkey: runtime_types::snowbridge_milagro_bls::keys::PublicKey, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedExecutionPayloadHeader { + # [codec (index = 0)] Capella (runtime_types :: snowbridge_beacon_primitives :: types :: ExecutionPayloadHeader ,) , # [codec (index = 1)] Deneb (runtime_types :: snowbridge_beacon_primitives :: types :: deneb :: ExecutionPayloadHeader ,) , } } - pub mod sr25519 { + pub mod updates { use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); + pub struct AncestryProof { + pub header_branch: ::std::vec::Vec<::subxt::utils::H256>, + pub finalized_block_root: ::subxt::utils::H256, + } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); + pub struct CheckpointUpdate { + pub header: runtime_types::snowbridge_beacon_primitives::types::BeaconHeader, + pub current_sync_committee: + runtime_types::snowbridge_beacon_primitives::types::SyncCommittee, + pub current_sync_committee_branch: ::std::vec::Vec<::subxt::utils::H256>, + pub validators_root: ::subxt::utils::H256, + pub block_roots_root: ::subxt::utils::H256, + pub block_roots_branch: ::std::vec::Vec<::subxt::utils::H256>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ExecutionHeaderUpdate { pub header : runtime_types :: snowbridge_beacon_primitives :: types :: BeaconHeader , pub ancestry_proof : :: core :: option :: Option < runtime_types :: snowbridge_beacon_primitives :: updates :: AncestryProof > , pub execution_header : runtime_types :: snowbridge_beacon_primitives :: types :: VersionedExecutionPayloadHeader , pub execution_branch : :: std :: vec :: Vec < :: subxt :: utils :: H256 > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct NextSyncCommitteeUpdate { + pub next_sync_committee: + runtime_types::snowbridge_beacon_primitives::types::SyncCommittee, + pub next_sync_committee_branch: ::std::vec::Vec<::subxt::utils::H256>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Update { pub attested_header : runtime_types :: snowbridge_beacon_primitives :: types :: BeaconHeader , pub sync_aggregate : runtime_types :: snowbridge_beacon_primitives :: types :: SyncAggregate , pub signature_slot : :: core :: primitive :: u64 , pub next_sync_committee_update : :: core :: option :: Option < runtime_types :: snowbridge_beacon_primitives :: updates :: NextSyncCommitteeUpdate > , pub finalized_header : runtime_types :: snowbridge_beacon_primitives :: types :: BeaconHeader , pub finality_branch : :: std :: vec :: Vec < :: subxt :: utils :: H256 > , pub block_roots_root : :: subxt :: utils :: H256 , pub block_roots_branch : :: std :: vec :: Vec < :: subxt :: utils :: H256 > , } } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} } - pub mod sp_runtime { + pub mod snowbridge_core { use super::runtime_types; - pub mod generic { + pub mod inbound { use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Log { + pub address: ::subxt::utils::H160, + pub topics: ::std::vec::Vec<::subxt::utils::H256>, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Message { + pub event_log: runtime_types::snowbridge_core::inbound::Log, + pub proof: runtime_types::snowbridge_core::inbound::Proof, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Proof { + pub block_hash: ::subxt::utils::H256, + pub tx_index: ::core::primitive::u32, + pub data: ( + ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VerificationError { + #[codec(index = 0)] + HeaderNotFound, + #[codec(index = 1)] + LogNotFound, + #[codec(index = 2)] + InvalidLog, + #[codec(index = 3)] + InvalidProof, + } + } + pub mod operating_mode { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + } + pub mod outbound { + use super::runtime_types; + pub mod v1 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Initializer { + pub params: ::std::vec::Vec<::core::primitive::u8>, + pub maximum_required_gas: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + RejectingOutboundMessages, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SendError { + #[codec(index = 0)] + MessageTooLarge, + #[codec(index = 1)] + Halted, + #[codec(index = 2)] + InvalidChannel, + } + } + pub mod pricing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PricingParameters<_0> { + pub exchange_rate: runtime_types::sp_arithmetic::fixed_point::FixedU128, + pub rewards: runtime_types::snowbridge_core::pricing::Rewards<_0>, + pub fee_per_gas: runtime_types::primitive_types::U256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Rewards<_0> { + pub local: _0, + pub remote: runtime_types::primitive_types::U256, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Channel { + pub agent_id: ::subxt::utils::H256, + pub para_id: runtime_types::polkadot_parachain_primitives::primitives::Id, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChannelId(pub [::core::primitive::u8; 32usize]); + } + pub mod snowbridge_milagro_bls { + use super::runtime_types; + pub mod keys { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PublicKey { + pub point: runtime_types::snowbridge_amcl::bls381::ecp::ECP, + } + } + } + pub mod snowbridge_pallet_ethereum_client { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] force_checkpoint { update : :: std :: boxed :: Box < runtime_types :: snowbridge_beacon_primitives :: updates :: CheckpointUpdate > , } , # [codec (index = 1)] submit { update : :: std :: boxed :: Box < runtime_types :: snowbridge_beacon_primitives :: updates :: Update > , } , # [codec (index = 2)] submit_execution_header { update : :: std :: boxed :: Box < runtime_types :: snowbridge_beacon_primitives :: updates :: ExecutionHeaderUpdate > , } , # [codec (index = 3)] set_operating_mode { mode : runtime_types :: snowbridge_core :: operating_mode :: BasicOperatingMode , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + SkippedSyncCommitteePeriod, + #[codec(index = 1)] + IrrelevantUpdate, + #[codec(index = 2)] + NotBootstrapped, + #[codec(index = 3)] + SyncCommitteeParticipantsNotSupermajority, + #[codec(index = 4)] + InvalidHeaderMerkleProof, + #[codec(index = 5)] + InvalidSyncCommitteeMerkleProof, + #[codec(index = 6)] + InvalidExecutionHeaderProof, + #[codec(index = 7)] + InvalidAncestryMerkleProof, + #[codec(index = 8)] + InvalidBlockRootsRootMerkleProof, + #[codec(index = 9)] + HeaderNotFinalized, + #[codec(index = 10)] + BlockBodyHashTreeRootFailed, + #[codec(index = 11)] + HeaderHashTreeRootFailed, + #[codec(index = 12)] + SyncCommitteeHashTreeRootFailed, + #[codec(index = 13)] + SigningRootHashTreeRootFailed, + #[codec(index = 14)] + ForkDataHashTreeRootFailed, + #[codec(index = 15)] + ExpectedFinalizedHeaderNotStored, + #[codec(index = 16)] + BLSPreparePublicKeysFailed, + #[codec(index = 17)] + BLSVerificationFailed( + runtime_types::snowbridge_beacon_primitives::bls::BlsError, + ), + #[codec(index = 18)] + InvalidUpdateSlot, + #[codec(index = 19)] + InvalidSyncCommitteeUpdate, + #[codec(index = 20)] + ExecutionHeaderTooFarBehind, + #[codec(index = 21)] + ExecutionHeaderSkippedBlock, + #[codec(index = 22)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BeaconHeaderImported { + block_hash: ::subxt::utils::H256, + slot: ::core::primitive::u64, + }, + #[codec(index = 1)] + ExecutionHeaderImported { + block_hash: ::subxt::utils::H256, + block_number: ::core::primitive::u64, + }, + #[codec(index = 2)] + SyncCommitteeUpdated { period: ::core::primitive::u64 }, + #[codec(index = 3)] + OperatingModeChanged { + mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, + }, + } + } + } + pub mod snowbridge_pallet_inbound_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit { message: runtime_types::snowbridge_core::inbound::Message }, + #[codec(index = 1)] + set_operating_mode { + mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidGateway, + #[codec(index = 1)] + InvalidEnvelope, + #[codec(index = 2)] + InvalidNonce, + #[codec(index = 3)] + InvalidPayload, + #[codec(index = 4)] + InvalidChannel, + #[codec(index = 5)] + MaxNonceReached, + #[codec(index = 6)] + InvalidAccountConversion, + #[codec(index = 7)] + Halted, + #[codec(index = 8)] + Verification(runtime_types::snowbridge_core::inbound::VerificationError), + #[codec(index = 9)] + Send(runtime_types::snowbridge_pallet_inbound_queue::pallet::SendError), + #[codec(index = 10)] + ConvertMessage( + runtime_types::snowbridge_router_primitives::inbound::ConvertMessageError, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + MessageReceived { + channel_id: runtime_types::snowbridge_core::ChannelId, + nonce: ::core::primitive::u64, + message_id: [::core::primitive::u8; 32usize], + fee_burned: ::core::primitive::u128, + }, + #[codec(index = 1)] + OperatingModeChanged { + mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum SendError { + #[codec(index = 0)] + NotApplicable, + #[codec(index = 1)] + NotRoutable, + #[codec(index = 2)] + Transport, + #[codec(index = 3)] + DestinationUnsupported, + #[codec(index = 4)] + ExceedsMaxMessageSize, + #[codec(index = 5)] + MissingArgument, + #[codec(index = 6)] + Fees, + } + } + } + pub mod snowbridge_pallet_outbound_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_operating_mode { + mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MessageTooLarge, + #[codec(index = 1)] + Halted, + #[codec(index = 2)] + InvalidChannel, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + MessageQueued { id: ::subxt::utils::H256 }, + #[codec(index = 1)] + MessageAccepted { id: ::subxt::utils::H256, nonce: ::core::primitive::u64 }, + #[codec(index = 2)] + MessagesCommitted { root: ::subxt::utils::H256, count: ::core::primitive::u64 }, + #[codec(index = 3)] + OperatingModeChanged { + mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CommittedMessage { + pub channel_id: runtime_types::snowbridge_core::ChannelId, + #[codec(compact)] + pub nonce: ::core::primitive::u64, + pub command: ::core::primitive::u8, + pub params: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + pub max_dispatch_gas: ::core::primitive::u64, + #[codec(compact)] + pub max_fee_per_gas: ::core::primitive::u128, + #[codec(compact)] + pub reward: ::core::primitive::u128, + pub id: ::subxt::utils::H256, + } + } + } + pub mod snowbridge_pallet_system { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + upgrade { + impl_address: ::subxt::utils::H160, + impl_code_hash: ::subxt::utils::H256, + initializer: ::core::option::Option< + runtime_types::snowbridge_core::outbound::v1::Initializer, + >, + }, + #[codec(index = 1)] + set_operating_mode { + mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, + }, + #[codec(index = 2)] + set_pricing_parameters { + params: runtime_types::snowbridge_core::pricing::PricingParameters< + ::core::primitive::u128, + >, + }, + #[codec(index = 3)] + create_agent, + #[codec(index = 4)] + create_channel { + mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, + }, + #[codec(index = 5)] + update_channel { + mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, + }, + #[codec(index = 6)] + force_update_channel { + channel_id: runtime_types::snowbridge_core::ChannelId, + mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, + }, + #[codec(index = 7)] + transfer_native_from_agent { + recipient: ::subxt::utils::H160, + amount: ::core::primitive::u128, + }, + #[codec(index = 8)] + force_transfer_native_from_agent { + location: ::std::boxed::Box, + recipient: ::subxt::utils::H160, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + set_token_transfer_fees { + create_asset_xcm: ::core::primitive::u128, + transfer_asset_xcm: ::core::primitive::u128, + register_token: runtime_types::primitive_types::U256, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + LocationConversionFailed, + #[codec(index = 1)] + AgentAlreadyCreated, + #[codec(index = 2)] + NoAgent, + #[codec(index = 3)] + ChannelAlreadyCreated, + #[codec(index = 4)] + NoChannel, + #[codec(index = 5)] + UnsupportedLocationVersion, + #[codec(index = 6)] + InvalidLocation, + #[codec(index = 7)] + Send(runtime_types::snowbridge_core::outbound::SendError), + #[codec(index = 8)] + InvalidTokenTransferFees, + #[codec(index = 9)] + InvalidPricingParameters, + #[codec(index = 10)] + InvalidUpgradeParameters, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Upgrade { + impl_address: ::subxt::utils::H160, + impl_code_hash: ::subxt::utils::H256, + initializer_params_hash: ::core::option::Option<::subxt::utils::H256>, + }, + #[codec(index = 1)] + CreateAgent { + location: + ::std::boxed::Box, + agent_id: ::subxt::utils::H256, + }, + #[codec(index = 2)] + CreateChannel { + channel_id: runtime_types::snowbridge_core::ChannelId, + agent_id: ::subxt::utils::H256, + }, + #[codec(index = 3)] + UpdateChannel { + channel_id: runtime_types::snowbridge_core::ChannelId, + mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, + }, + #[codec(index = 4)] + SetOperatingMode { + mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, + }, + #[codec(index = 5)] + TransferNativeFromAgent { + agent_id: ::subxt::utils::H256, + recipient: ::subxt::utils::H160, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + SetTokenTransferFees { + create_asset_xcm: ::core::primitive::u128, + transfer_asset_xcm: ::core::primitive::u128, + register_token: runtime_types::primitive_types::U256, + }, + #[codec(index = 7)] + PricingParametersChanged { + params: runtime_types::snowbridge_core::pricing::PricingParameters< + ::core::primitive::u128, + >, + }, + } + } + } + pub mod snowbridge_router_primitives { + use super::runtime_types; + pub mod inbound { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ConvertMessageError { + #[codec(index = 0)] + UnsupportedVersion, + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_consensus_aura { + use super::runtime_types; + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_trie { + use super::runtime_types; + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StorageProof { + pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod staging_parachain_info { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + } + } + pub mod staging_xcm { + use super::runtime_types; + pub mod v3 { + use super::runtime_types; + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + } + pub mod v4 { + use super::runtime_types; + pub mod asset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Asset { + pub id: runtime_types::staging_xcm::v4::asset::AssetId, + pub fun: runtime_types::staging_xcm::v4::asset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetFilter { #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), + Definite(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 1)] + Wild(runtime_types::staging_xcm::v4::asset::WildAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AssetId(pub runtime_types::staging_xcm::v4::location::Location); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Assets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::staging_xcm::v4::asset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::staging_xcm::v4::asset::AssetId, + fun: runtime_types::staging_xcm::v4::asset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::staging_xcm::v4::asset::AssetId, + fun: runtime_types::staging_xcm::v4::asset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + } + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: ::core::option::Option< + runtime_types::staging_xcm::v4::junction::NetworkId, + >, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: ::core::option::Option< + runtime_types::staging_xcm::v4::junction::NetworkId, + >, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: ::core::option::Option< + runtime_types::staging_xcm::v4::junction::NetworkId, + >, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::staging_xcm::v4::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + #[codec(index = 10)] + PolkadotBulletin, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1([runtime_types::staging_xcm::v4::junction::Junction; 1usize]), + #[codec(index = 2)] + X2([runtime_types::staging_xcm::v4::junction::Junction; 2usize]), + #[codec(index = 3)] + X3([runtime_types::staging_xcm::v4::junction::Junction; 3usize]), + #[codec(index = 4)] + X4([runtime_types::staging_xcm::v4::junction::Junction; 4usize]), + #[codec(index = 5)] + X5([runtime_types::staging_xcm::v4::junction::Junction; 5usize]), + #[codec(index = 6)] + X6([runtime_types::staging_xcm::v4::junction::Junction; 6usize]), + #[codec(index = 7)] + X7([runtime_types::staging_xcm::v4::junction::Junction; 7usize]), #[codec(index = 8)] - RuntimeEnvironmentUpdated, + X8([runtime_types::staging_xcm::v4::junction::Junction; 8usize]), + } + } + pub mod location { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Location { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::staging_xcm::v4::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete { used: ::sp_weights::Weight }, + #[codec(index = 1)] + Incomplete { + used: ::sp_weights::Weight, + error: runtime_types::xcm::v3::traits::Error, + }, + #[codec(index = 2)] + Error { error: runtime_types::xcm::v3::traits::Error }, } } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_trie { - use super::runtime_types; - pub mod storage_proof { - use super::runtime_types; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StorageProof { - pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::staging_xcm::v4::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::staging_xcm::v4::asset::AssetFilter, + want: runtime_types::staging_xcm::v4::asset::Assets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + reserve: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::staging_xcm::v4::asset::Asset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::staging_xcm::v4::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::staging_xcm::v4::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + ticket: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 29)] + ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::staging_xcm::v4::junction::NetworkId, + destination: runtime_types::staging_xcm::v4::junctions::Junctions, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + unlocker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + target: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::staging_xcm::v4::asset::Asset, + owner: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::staging_xcm::v4::asset::Asset, + locker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v4::location::Location), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::staging_xcm::v4::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::staging_xcm::v4::asset::AssetFilter, + want: runtime_types::staging_xcm::v4::asset::Assets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + reserve: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::staging_xcm::v4::asset::Asset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::staging_xcm::v4::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::staging_xcm::v4::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + ticket: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 29)] + ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::staging_xcm::v4::junction::NetworkId, + destination: runtime_types::staging_xcm::v4::junctions::Junctions, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + unlocker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + target: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::staging_xcm::v4::asset::Asset, + owner: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::staging_xcm::v4::asset::Asset, + locker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v4::location::Location), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod staging_xcm { - use super::runtime_types; - pub mod v3 { - use super::runtime_types; - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::staging_xcm::v4::location::Location, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::staging_xcm::v4::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); } } pub mod xcm { @@ -3279,6 +4724,8 @@ pub mod api { BitcoinCore, #[codec(index = 9)] BitcoinCash, + #[codec(index = 10)] + PolkadotBulletin, } } pub mod junctions { @@ -3506,15 +4953,6 @@ pub mod api { #[codec(index = 39)] ExceedsStackLimit, } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum Instruction { @@ -4015,20 +5453,26 @@ pub mod api { pub enum VersionedAssetId { #[codec(index = 3)] V3(runtime_types::xcm::v3::multiasset::AssetId), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::asset::AssetId), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { + pub enum VersionedAssets { #[codec(index = 1)] V2(runtime_types::xcm::v2::multiasset::MultiAssets), #[codec(index = 3)] V3(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::asset::Assets), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { + pub enum VersionedLocation { #[codec(index = 1)] V2(runtime_types::xcm::v2::multilocation::MultiLocation), #[codec(index = 3)] V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::location::Location), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedResponse { @@ -4036,6 +5480,8 @@ pub mod api { V2(runtime_types::xcm::v2::Response), #[codec(index = 3)] V3(runtime_types::xcm::v3::Response), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::Response), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedXcm { @@ -4043,6 +5489,8 @@ pub mod api { V2(runtime_types::xcm::v2::Xcm), #[codec(index = 3)] V3(runtime_types::xcm::v3::Xcm), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::Xcm), } #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub enum VersionedXcm2 { @@ -4050,6 +5498,8 @@ pub mod api { V2(runtime_types::xcm::v2::Xcm2), #[codec(index = 3)] V3(runtime_types::xcm::v3::Xcm2), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::Xcm2), } } } diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml index ecc23ec81d9de..18b4f3230ede2 100644 --- a/relays/client-bridge-hub-westend/Cargo.toml +++ b/relays/client-bridge-hub-westend/Cargo.toml @@ -15,9 +15,9 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } bp-bridge-hub-westend = { path = "../../primitives/chain-bridge-hub-westend" } bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-rococo = { path = "../../primitives/chain-rococo" } diff --git a/relays/client-bridge-hub-westend/src/codegen_runtime.rs b/relays/client-bridge-hub-westend/src/codegen_runtime.rs new file mode 100644 index 0000000000000..3db044fcf5ec5 --- /dev/null +++ b/relays/client-bridge-hub-westend/src/codegen_runtime.rs @@ -0,0 +1,4705 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-wasm-file +//! ../../../polkadot-sdk/target/release/wbuild/bridge-hub-westend-runtime/ +//! bridge_hub_westend_runtime.compact.compressed.wasm + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +#[allow(rustdoc::broken_intra_doc_links)] +pub mod api { + #[allow(unused_imports)] + mod root_mod { + pub use super::*; + } + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_btree_set { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedBTreeSet<_0>(pub ::std::vec::Vec<_0>); + } + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod bp_header_chain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AuthoritySet { + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HeaderChainError { + #[codec(index = 0)] + UnknownHeader, + #[codec(index = 1)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderFinalityInfo<_0, _1> { + pub finality_proof: _0, + pub new_verification_context: ::core::option::Option<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredHeaderData<_0, _1> { + pub number: _0, + pub state_root: _1, + } + } + pub mod bp_messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DeliveredMessages { + pub begin: ::core::primitive::u64, + pub end: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundLaneData<_0> { + pub relayers: ::std::vec::Vec>, + pub last_confirmed_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LaneId(pub [::core::primitive::u8; 4usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageKey { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MessagesOperatingMode { + #[codec(index = 0)] + Basic(runtime_types::bp_runtime::BasicOperatingMode), + #[codec(index = 1)] + RejectingOutboundMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundLaneData { + pub oldest_unpruned_nonce: ::core::primitive::u64, + pub latest_received_nonce: ::core::primitive::u64, + pub latest_generated_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalResult<_0> { + #[codec(index = 0)] + Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), + #[codec(index = 1)] + InvalidNonce, + #[codec(index = 2)] + TooManyUnrewardedRelayers, + #[codec(index = 3)] + TooManyUnconfirmedMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceivedMessages<_0> { + pub lane: runtime_types::bp_messages::LaneId, + pub receive_results: ::std::vec::Vec<( + ::core::primitive::u64, + runtime_types::bp_messages::ReceivalResult<_0>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnrewardedRelayer<_0> { + pub relayer: _0, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VerificationError { + #[codec(index = 0)] + EmptyMessageProof, + #[codec(index = 1)] + HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 2)] + InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 3)] + InvalidMessageWeight, + #[codec(index = 4)] + MessagesCountMismatch, + #[codec(index = 5)] + MessageStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 6)] + MessageTooLarge, + #[codec(index = 7)] + OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 8)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 9)] + Other, + } + } + pub mod bp_parachains { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BestParaHeadHash { + pub at_relay_block_number: ::core::primitive::u32, + pub head_hash: ::subxt::utils::H256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo { + pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, + pub next_imported_hash_position: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); + } + pub mod bp_relayers { + use super::runtime_types; + pub mod registration { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0, _1> { + pub valid_till: _0, + pub stake: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardsAccountOwner { + #[codec(index = 0)] + ThisChain, + #[codec(index = 1)] + BridgedChain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardsAccountParams { + pub lane_id: runtime_types::bp_messages::LaneId, + pub bridged_chain_id: [::core::primitive::u8; 4usize], + pub owner: runtime_types::bp_relayers::RewardsAccountOwner, + } + } + pub mod bp_runtime { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageDispatchResult<_0> { + pub unspent_weight: ::sp_weights::Weight, + pub dispatch_level_result: _0, + } + } + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateNodesInProof, + #[codec(index = 1)] + UnusedNodesInTheProof, + #[codec(index = 2)] + StorageRootMismatch, + #[codec(index = 3)] + StorageValueUnavailable, + #[codec(index = 4)] + StorageValueEmpty, + #[codec(index = 5)] + StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderId<_0, _1>(pub _1, pub _0); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OwnedBridgeModuleError { + #[codec(index = 0)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StrippableError; + } + pub mod bridge_hub_common { + use super::runtime_types; + pub mod message_queue { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AggregateMessageOrigin { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + Parent, + #[codec(index = 2)] + Sibling(runtime_types::polkadot_parachain_primitives::primitives::Id), + #[codec(index = 3)] + Snowbridge(runtime_types::snowbridge_core::ChannelId), + } + } + } + pub mod bridge_hub_westend_runtime { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BridgeRejectObsoleteHeadersAndMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + #[codec(index = 0)] + system( + runtime_types::frame_support::dispatch::RawOrigin< + ::sp_core::crypto::AccountId32, + >, + ), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), + #[codec(index = 3)] + Void(runtime_types::sp_core::Void), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 3)] + ParachainInfo(runtime_types::staging_parachain_info::pallet::Call), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Call), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 36)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 41)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + #[codec(index = 42)] + BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 43)] + BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 44)] + BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), + #[codec(index = 250)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeError { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Error), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Error), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Error), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Error), + #[codec(index = 36)] + Multisig(runtime_types::pallet_multisig::pallet::Error), + #[codec(index = 41)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), + #[codec(index = 42)] + BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), + #[codec(index = 43)] + BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Error), + #[codec(index = 44)] + BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Error), + #[codec(index = 250)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 11)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 36)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 41)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 42)] + BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 43)] + BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 44)] + BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), + #[codec(index = 250)] + MessageQueue(runtime_types::pallet_message_queue::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeHoldReason {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, + } + } + pub mod bridge_runtime_common { + use super::runtime_types; + pub mod messages_xcm_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmBlobMessageDispatchResult { + #[codec(index = 0)] + InvalidPayload, + #[codec(index = 1)] + Dispatched, + #[codec(index = 2)] + NotDispatched, + } + } + pub mod refund_relayer_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundBridgedParachainMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundSignedExtensionAdapter<_0>(pub _0); + } + } + pub mod cumulus_pallet_parachain_system { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OverlappingUpgrades, + #[codec(index = 1)] + ProhibitedByPolkadot, + #[codec(index = 2)] + TooBig, + #[codec(index = 3)] + ValidationDataNotAvailable, + #[codec(index = 4)] + HostConfigurationNotAvailable, + #[codec(index = 5)] + NotScheduled, + #[codec(index = 6)] + NothingAuthorized, + #[codec(index = 7)] + Unauthorized, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ValidationFunctionStored, + #[codec(index = 1)] + ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, + #[codec(index = 2)] + ValidationFunctionDiscarded, + #[codec(index = 3)] + DownwardMessagesReceived { count: ::core::primitive::u32 }, + #[codec(index = 4)] + DownwardMessagesProcessed { + weight_used: ::sp_weights::Weight, + dmq_head: ::subxt::utils::H256, + }, + #[codec(index = 5)] + UpwardMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + pub mod relay_state_snapshot { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RelayDispatchQueueRemainingCapacity { + pub remaining_count: ::core::primitive::u32, + pub remaining_size: ::core::primitive::u32, + } + } + pub mod unincluded_segment { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelUpdate { + pub msg_count: ::core::primitive::u32, + pub total_bytes: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } + } + } + pub mod cumulus_pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + UnsupportedVersion([::core::primitive::u8; 32usize]), + #[codec(index = 2)] + ExecutedDownward( + [::core::primitive::u8; 32usize], + runtime_types::staging_xcm::v4::traits::Outcome, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Relay, + #[codec(index = 1)] + SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), + } + } + } + pub mod cumulus_pallet_xcmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 1)] + suspend_xcm_execution, + #[codec(index = 2)] + resume_xcm_execution, + #[codec(index = 3)] + update_suspend_threshold { new: ::core::primitive::u32 }, + #[codec(index = 4)] + update_drop_threshold { new: ::core::primitive::u32 }, + #[codec(index = 5)] + update_resume_threshold { new: ::core::primitive::u32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + BadQueueConfig, + #[codec(index = 1)] + AlreadySuspended, + #[codec(index = 2)] + AlreadyResumed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundChannelDetails { + pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, + pub signals_exist: ::core::primitive::bool, + pub first_index: ::core::primitive::u16, + pub last_index: ::core::primitive::u16, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OutboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueueConfigData { + pub suspend_threshold: ::core::primitive::u32, + pub drop_threshold: ::core::primitive::u32, + pub resume_threshold: ::core::primitive::u32, + } + } + pub mod cumulus_primitives_parachain_inherent { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageQueueChain(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParachainInherentData { + pub validation_data: + runtime_types::polkadot_primitives::v6::PersistedValidationData< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, + pub downward_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundDownwardMessage< + ::core::primitive::u32, + >, + >, + pub horizontal_messages: ::subxt::utils::KeyedVec< + runtime_types::polkadot_parachain_primitives::primitives::Id, + ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundHrmpMessage< + ::core::primitive::u32, + >, + >, + >, + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commit<_0, _1, _2, _3> { + pub target_hash: _0, + pub target_number: _1, + pub precommits: ::std::vec::Vec< + runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedPrecommit<_0, _1, _2, _3> { + pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, + pub signature: _2, + pub id: _3, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ProcessMessageError { + #[codec(index = 0)] + BadFormat, + #[codec(index = 1)] + Corrupt, + #[codec(index = 2)] + Unsupported, + #[codec(index = 3)] + Overweight(::sp_weights::Weight), + #[codec(index = 4)] + Yield, + } + } + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 9)] + authorize_upgrade { code_hash: ::subxt::utils::H256 }, + #[codec(index = 10)] + authorize_upgrade_without_checks { code_hash: ::subxt::utils::H256 }, + #[codec(index = 11)] + apply_authorized_upgrade { code: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + #[codec(index = 6)] + NothingAuthorized, + #[codec(index = 7)] + Unauthorized, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + #[codec(index = 6)] + UpgradeAuthorized { + code_hash: ::subxt::utils::H256, + check_version: ::core::primitive::bool, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: ::core::primitive::u32, + pub providers: ::core::primitive::u32, + pub sufficients: ::core::primitive::u32, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CodeUpgradeAuthorization { + pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + #[codec(index = 9)] + force_adjust_total_issuance { + direction: runtime_types::pallet_balances::types::AdjustmentDirection, + #[codec(compact)] + delta: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + #[codec(index = 10)] + IssuanceDeactivated, + #[codec(index = 11)] + DeltaZero, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 21)] + TotalIssuanceForced { + old: ::core::primitive::u128, + new: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AdjustmentDirection { + #[codec(index = 0)] + Increase, + #[codec(index = 1)] + Decrease, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_bridge_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 1)] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 2)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + #[codec(index = 4)] + submit_finality_proof_ex { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + current_set_id: ::core::primitive::u64, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidJustification, + #[codec(index = 1)] + InvalidAuthoritySet, + #[codec(index = 2)] + OldHeader, + #[codec(index = 3)] + UnsupportedScheduledChange, + #[codec(index = 4)] + NotInitialized, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooManyAuthoritiesInSet, + #[codec(index = 7)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + #[codec(index = 8)] + InvalidAuthoritySetId, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u32, + hash: ::subxt::utils::H256, + grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< + ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + runtime_types::bp_header_chain::AuthoritySet, + >, + }, + } + } + pub mod storage_types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredAuthoritySet { + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + } + } + pub mod pallet_bridge_messages { + use super::runtime_types; + pub mod outbound_lane { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalConfirmationError { + #[codec(index = 0)] + FailedToConfirmFutureMessages, + #[codec(index = 1)] + EmptyUnrewardedRelayerEntry, + #[codec(index = 2)] + NonConsecutiveUnrewardedRelayerEntries, + #[codec(index = 3)] + TryingToConfirmMoreMessagesThanExpected, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } + } + } + pub mod pallet_bridge_parachains { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_parachain_heads { + at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), + parachains: ::std::vec::Vec<( + ::bp_polkadot_core::parachains::ParaId, + ::subxt::utils::H256, + )>, + parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, + }, + #[codec(index = 1)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 2)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnknownRelayChainBlock, + #[codec(index = 1)] + InvalidRelayChainBlockNumber, + #[codec(index = 2)] + HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 3)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 1)] + MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 2)] + IncorrectParachainHeadHash { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + actual_parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + RejectedObsoleteParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 4)] + RejectedLargeParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + parachain_head_size: ::core::primitive::u32, + }, + #[codec(index = 5)] + UpdatedParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + } + } + } + pub mod pallet_bridge_relayers { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim_rewards { + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + }, + #[codec(index = 1)] + register { valid_till: ::core::primitive::u32 }, + #[codec(index = 2)] + deregister, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NoRewardForRelayer, + #[codec(index = 1)] + FailedToPayReward, + #[codec(index = 2)] + InvalidRegistrationLease, + #[codec(index = 3)] + CannotReduceRegistrationLease, + #[codec(index = 4)] + FailedToReserve, + #[codec(index = 5)] + FailedToUnreserve, + #[codec(index = 6)] + NotRegistered, + #[codec(index = 7)] + RegistrationIsStillActive, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RewardRegistered { + relayer: ::sp_core::crypto::AccountId32, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + reward: ::core::primitive::u128, + }, + #[codec(index = 1)] + RewardPaid { + relayer: ::sp_core::crypto::AccountId32, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + reward: ::core::primitive::u128, + }, + #[codec(index = 2)] + RegistrationUpdated { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + #[codec(index = 3)] + Deregistered { relayer: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + SlashedAndDeregistered { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + } + } + } + pub mod pallet_collator_selection { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 1)] + set_desired_candidates { max: ::core::primitive::u32 }, + #[codec(index = 2)] + set_candidacy_bond { bond: ::core::primitive::u128 }, + #[codec(index = 3)] + register_as_candidate, + #[codec(index = 4)] + leave_intent, + #[codec(index = 5)] + add_invulnerable { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 7)] + update_bond { new_deposit: ::core::primitive::u128 }, + #[codec(index = 8)] + take_candidate_slot { + deposit: ::core::primitive::u128, + target: ::sp_core::crypto::AccountId32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateInfo<_0, _1> { + pub who: _0, + pub deposit: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCandidates, + #[codec(index = 1)] + TooFewEligibleCollators, + #[codec(index = 2)] + AlreadyCandidate, + #[codec(index = 3)] + NotCandidate, + #[codec(index = 4)] + TooManyInvulnerables, + #[codec(index = 5)] + AlreadyInvulnerable, + #[codec(index = 6)] + NotInvulnerable, + #[codec(index = 7)] + NoAssociatedValidatorId, + #[codec(index = 8)] + ValidatorNotRegistered, + #[codec(index = 9)] + InsertToCandidateListFailed, + #[codec(index = 10)] + RemoveFromCandidateListFailed, + #[codec(index = 11)] + DepositTooLow, + #[codec(index = 12)] + UpdateCandidateListFailed, + #[codec(index = 13)] + InsufficientBond, + #[codec(index = 14)] + TargetIsNotCandidate, + #[codec(index = 15)] + IdenticalDeposit, + #[codec(index = 16)] + InvalidUnreserve, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewInvulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 1)] + InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 2)] + InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, + #[codec(index = 4)] + NewCandidacyBond { bond_amount: ::core::primitive::u128 }, + #[codec(index = 5)] + CandidateAdded { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 6)] + CandidateBondUpdated { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 7)] + CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 8)] + CandidateReplaced { + old: ::sp_core::crypto::AccountId32, + new: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 9)] + InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, + } + } + } + pub mod pallet_message_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + reap_page { + message_origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, + page_index: ::core::primitive::u32, + }, + #[codec(index = 1)] + execute_overweight { + message_origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, + page: ::core::primitive::u32, + index: ::core::primitive::u32, + weight_limit: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NotReapable, + #[codec(index = 1)] + NoPage, + #[codec(index = 2)] + NoMessage, + #[codec(index = 3)] + AlreadyProcessed, + #[codec(index = 4)] + Queued, + #[codec(index = 5)] + InsufficientWeight, + #[codec(index = 6)] + TemporarilyUnprocessable, + #[codec(index = 7)] + QueuePaused, + #[codec(index = 8)] + RecursiveDisallowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ProcessingFailed { + id: ::subxt::utils::H256, + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, + error: runtime_types::frame_support::traits::messages::ProcessMessageError, + }, + #[codec(index = 1)] + Processed { + id: ::subxt::utils::H256, + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, + weight_used: ::sp_weights::Weight, + success: ::core::primitive::bool, + }, + #[codec(index = 2)] + OverweightEnqueued { + id: [::core::primitive::u8; 32usize], + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, + page_index: ::core::primitive::u32, + message_index: ::core::primitive::u32, + }, + #[codec(index = 3)] + PageReaped { + origin: + runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, + index: ::core::primitive::u32, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BookState<_0> { + pub begin: ::core::primitive::u32, + pub end: ::core::primitive::u32, + pub count: ::core::primitive::u32, + pub ready_neighbours: + ::core::option::Option>, + pub message_count: ::core::primitive::u64, + pub size: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Neighbours<_0> { + pub prev: _0, + pub next: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Page<_0> { + pub remaining: _0, + pub remaining_size: _0, + pub first_index: _0, + pub first: _0, + pub last: _0, + pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box< + runtime_types::bridge_hub_westend_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_westend_runtime::RuntimeCall, + >, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: ::core::primitive::u32, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::bridge_hub_westend_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { + calls: + ::std::vec::Vec, + }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box< + runtime_types::bridge_hub_westend_runtime::RuntimeCall, + >, + }, + #[codec(index = 2)] + batch_all { + calls: + ::std::vec::Vec, + }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box< + runtime_types::bridge_hub_westend_runtime::OriginCaller, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_westend_runtime::RuntimeCall, + >, + }, + #[codec(index = 4)] + force_batch { + calls: + ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box< + runtime_types::bridge_hub_westend_runtime::RuntimeCall, + >, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: + ::std::boxed::Box, + version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + #[codec(index = 11)] + transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + CannotCheckOutTeleport, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + #[codec(index = 20)] + InvalidAssetNotConcrete, + #[codec(index = 21)] + InvalidAssetUnknownReserve, + #[codec(index = 22)] + InvalidAssetUnsupportedReserve, + #[codec(index = 23)] + TooManyReserves, + #[codec(index = 24)] + LocalExecutionIncomplete, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted { outcome: runtime_types::staging_xcm::v4::traits::Outcome }, + #[codec(index = 1)] + Sent { + origin: runtime_types::staging_xcm::v4::location::Location, + destination: runtime_types::staging_xcm::v4::location::Location, + message: runtime_types::staging_xcm::v4::Xcm, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + UnexpectedResponse { + origin: runtime_types::staging_xcm::v4::location::Location, + query_id: ::core::primitive::u64, + }, + #[codec(index = 3)] + ResponseReady { + query_id: ::core::primitive::u64, + response: runtime_types::staging_xcm::v4::Response, + }, + #[codec(index = 4)] + Notified { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 5)] + NotifyOverweight { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + actual_weight: ::sp_weights::Weight, + max_budgeted_weight: ::sp_weights::Weight, + }, + #[codec(index = 6)] + NotifyDispatchError { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 7)] + NotifyDecodeFailed { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 8)] + InvalidResponder { + origin: runtime_types::staging_xcm::v4::location::Location, + query_id: ::core::primitive::u64, + expected_location: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + #[codec(index = 9)] + InvalidResponderVersion { + origin: runtime_types::staging_xcm::v4::location::Location, + query_id: ::core::primitive::u64, + }, + #[codec(index = 10)] + ResponseTaken { query_id: ::core::primitive::u64 }, + #[codec(index = 11)] + AssetsTrapped { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v4::location::Location, + assets: runtime_types::xcm::VersionedAssets, + }, + #[codec(index = 12)] + VersionChangeNotified { + destination: runtime_types::staging_xcm::v4::location::Location, + result: ::core::primitive::u32, + cost: runtime_types::staging_xcm::v4::asset::Assets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 13)] + SupportedVersionChanged { + location: runtime_types::staging_xcm::v4::location::Location, + version: ::core::primitive::u32, + }, + #[codec(index = 14)] + NotifyTargetSendFail { + location: runtime_types::staging_xcm::v4::location::Location, + query_id: ::core::primitive::u64, + error: runtime_types::xcm::v3::traits::Error, + }, + #[codec(index = 15)] + NotifyTargetMigrationFail { + location: runtime_types::xcm::VersionedLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 16)] + InvalidQuerierVersion { + origin: runtime_types::staging_xcm::v4::location::Location, + query_id: ::core::primitive::u64, + }, + #[codec(index = 17)] + InvalidQuerier { + origin: runtime_types::staging_xcm::v4::location::Location, + query_id: ::core::primitive::u64, + expected_querier: runtime_types::staging_xcm::v4::location::Location, + maybe_actual_querier: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + #[codec(index = 18)] + VersionNotifyStarted { + destination: runtime_types::staging_xcm::v4::location::Location, + cost: runtime_types::staging_xcm::v4::asset::Assets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 19)] + VersionNotifyRequested { + destination: runtime_types::staging_xcm::v4::location::Location, + cost: runtime_types::staging_xcm::v4::asset::Assets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 20)] + VersionNotifyUnrequested { + destination: runtime_types::staging_xcm::v4::location::Location, + cost: runtime_types::staging_xcm::v4::asset::Assets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 21)] + FeesPaid { + paying: runtime_types::staging_xcm::v4::location::Location, + fees: runtime_types::staging_xcm::v4::asset::Assets, + }, + #[codec(index = 22)] + AssetsClaimed { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v4::location::Location, + assets: runtime_types::xcm::VersionedAssets, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::staging_xcm::v4::location::Location), + #[codec(index = 1)] + Response(runtime_types::staging_xcm::v4::location::Location), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedLocation, + pub locker: runtime_types::xcm::VersionedLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain_primitives { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v6 { + use super::runtime_types; + pub mod async_backing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHostConfiguration { + pub max_code_size: ::core::primitive::u32, + pub max_head_data_size: ::core::primitive::u32, + pub max_upward_queue_count: ::core::primitive::u32, + pub max_upward_queue_size: ::core::primitive::u32, + pub max_upward_message_size: ::core::primitive::u32, + pub max_upward_message_num_per_candidate: ::core::primitive::u32, + pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, + pub validation_upgrade_cooldown: ::core::primitive::u32, + pub validation_upgrade_delay: ::core::primitive::u32, + pub async_backing_params: + runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PersistedValidationData<_0, _1> { + pub parent_head: + runtime_types::polkadot_parachain_primitives::primitives::HeadData, + pub relay_parent_number: _1, + pub relay_parent_storage_root: _0, + pub max_pov_size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + } + } + pub mod snowbridge_core { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChannelId(pub [::core::primitive::u8; 32usize]); + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_consensus_aura { + use super::runtime_types; + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_trie { + use super::runtime_types; + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StorageProof { + pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod staging_parachain_info { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call {} + } + } + pub mod staging_xcm { + use super::runtime_types; + pub mod v3 { + use super::runtime_types; + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + } + pub mod v4 { + use super::runtime_types; + pub mod asset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Asset { + pub id: runtime_types::staging_xcm::v4::asset::AssetId, + pub fun: runtime_types::staging_xcm::v4::asset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetFilter { + #[codec(index = 0)] + Definite(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 1)] + Wild(runtime_types::staging_xcm::v4::asset::WildAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AssetId(pub runtime_types::staging_xcm::v4::location::Location); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Assets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::staging_xcm::v4::asset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::staging_xcm::v4::asset::AssetId, + fun: runtime_types::staging_xcm::v4::asset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::staging_xcm::v4::asset::AssetId, + fun: runtime_types::staging_xcm::v4::asset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + } + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: ::core::option::Option< + runtime_types::staging_xcm::v4::junction::NetworkId, + >, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: ::core::option::Option< + runtime_types::staging_xcm::v4::junction::NetworkId, + >, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: ::core::option::Option< + runtime_types::staging_xcm::v4::junction::NetworkId, + >, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::staging_xcm::v4::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + #[codec(index = 10)] + PolkadotBulletin, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1([runtime_types::staging_xcm::v4::junction::Junction; 1usize]), + #[codec(index = 2)] + X2([runtime_types::staging_xcm::v4::junction::Junction; 2usize]), + #[codec(index = 3)] + X3([runtime_types::staging_xcm::v4::junction::Junction; 3usize]), + #[codec(index = 4)] + X4([runtime_types::staging_xcm::v4::junction::Junction; 4usize]), + #[codec(index = 5)] + X5([runtime_types::staging_xcm::v4::junction::Junction; 5usize]), + #[codec(index = 6)] + X6([runtime_types::staging_xcm::v4::junction::Junction; 6usize]), + #[codec(index = 7)] + X7([runtime_types::staging_xcm::v4::junction::Junction; 7usize]), + #[codec(index = 8)] + X8([runtime_types::staging_xcm::v4::junction::Junction; 8usize]), + } + } + pub mod location { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Location { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::staging_xcm::v4::junctions::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete { used: ::sp_weights::Weight }, + #[codec(index = 1)] + Incomplete { + used: ::sp_weights::Weight, + error: runtime_types::xcm::v3::traits::Error, + }, + #[codec(index = 2)] + Error { error: runtime_types::xcm::v3::traits::Error }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::staging_xcm::v4::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::staging_xcm::v4::asset::AssetFilter, + want: runtime_types::staging_xcm::v4::asset::Assets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + reserve: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::staging_xcm::v4::asset::Asset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::staging_xcm::v4::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::staging_xcm::v4::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + ticket: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 29)] + ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::staging_xcm::v4::junction::NetworkId, + destination: runtime_types::staging_xcm::v4::junctions::Junctions, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + unlocker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + target: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::staging_xcm::v4::asset::Asset, + owner: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::staging_xcm::v4::asset::Asset, + locker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v4::location::Location), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::staging_xcm::v4::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + beneficiary: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::staging_xcm::v4::asset::AssetFilter, + want: runtime_types::staging_xcm::v4::asset::Assets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + reserve: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + dest: runtime_types::staging_xcm::v4::location::Location, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + assets: runtime_types::staging_xcm::v4::asset::AssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::staging_xcm::v4::asset::Asset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::staging_xcm::v4::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::staging_xcm::v4::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::staging_xcm::v4::asset::Assets, + ticket: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 29)] + ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::staging_xcm::v4::junction::NetworkId, + destination: runtime_types::staging_xcm::v4::junctions::Junctions, + xcm: runtime_types::staging_xcm::v4::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + unlocker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::staging_xcm::v4::asset::Asset, + target: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::staging_xcm::v4::asset::Asset, + owner: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::staging_xcm::v4::asset::Asset, + locker: runtime_types::staging_xcm::v4::location::Location, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v4::location::Location), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v4::location::Location, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::staging_xcm::v4::location::Location, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::staging_xcm::v4::asset::Assets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::staging_xcm::v4::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded2 { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + #[codec(index = 10)] + PolkadotBulletin, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::asset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::asset::Assets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::location::Location), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::Xcm), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm2 { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm2), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm2), + #[codec(index = 4)] + V4(runtime_types::staging_xcm::v4::Xcm2), + } + } + } +} diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs index 825082e10a11a..5e38ef65bc34a 100644 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -16,21 +16,28 @@ //! Types used to connect to the BridgeHub-Westend-Substrate parachain. -use bp_bridge_hub_westend::AVERAGE_BLOCK_INTERVAL; +pub mod codegen_runtime; + +use bp_bridge_hub_westend::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -/// Re-export runtime wrapper -pub mod runtime_wrapper; -pub use runtime_wrapper as runtime; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::bridge_hub_westend_runtime::RuntimeCall; +pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; +type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic; +type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Westend chain definition #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -47,7 +54,7 @@ impl Chain for BridgeHubWestend { const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_westend::SignedBlock; - type Call = runtime::Call; + type Call = RuntimeCall; } impl ChainWithBalances for BridgeHubWestend { @@ -56,13 +63,22 @@ impl ChainWithBalances for BridgeHubWestend { } } +impl From> for RuntimeCall { + fn from(value: MockUtilityCall) -> RuntimeCall { + match value { + MockUtilityCall::batch_all(calls) => + RuntimeCall::Utility(UtilityCall::batch_all { calls }), + } + } +} + impl ChainWithUtilityPallet for BridgeHubWestend { - type UtilityPallet = MockedRuntimeUtilityPallet; + type UtilityPallet = MockedRuntimeUtilityPallet; } impl ChainWithTransactions for BridgeHubWestend { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = runtime::UncheckedExtrinsic; + type SignedTransaction = UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -70,7 +86,7 @@ impl ChainWithTransactions for BridgeHubWestend { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::SignedExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -85,7 +101,7 @@ impl ChainWithTransactions for BridgeHubWestend { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(runtime::UncheckedExtrinsic::new_signed( + Ok(UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -127,10 +143,12 @@ mod tests { use super::*; use relay_substrate_client::TransactionEra; + type SystemCall = runtime_types::frame_system::pallet::Call; + #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) .into(), nonce: 777, tip: 888, diff --git a/relays/client-bridge-hub-westend/src/runtime_wrapper.rs b/relays/client-bridge-hub-westend/src/runtime_wrapper.rs deleted file mode 100644 index b4ff36cde7a30..0000000000000 --- a/relays/client-bridge-hub-westend/src/runtime_wrapper.rs +++ /dev/null @@ -1,116 +0,0 @@ -// 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 . - -//! Types that are specific to the BridgeHubWestend runtime. -// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945) - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_bridge_hub_westend::SignedExtension; -pub use bp_header_chain::BridgeGrandpaCallOf; -pub use bp_parachains::BridgeParachainCall; -pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; - -/// Unchecked BridgeHubWestend extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic; - -/// The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWestend`. -pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf; -/// The indirect pallet call used to sync `BridgeHubRococo` messages to `BridgeHubWestend`. -pub type BridgeRococoMessagesCall = BridgeMessagesCallOf; - -/// `BridgeHubWestend` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `BridgeHubWestend` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `BridgeHubWestend` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - #[cfg(test)] - #[codec(index = 0)] - System(SystemCall), - /// Utility pallet. - #[codec(index = 40)] - Utility(UtilityCall), - - /// Rococo grandpa bridge pallet. - #[codec(index = 42)] - BridgeRococoGrandpa(BridgeRococoGrandpaCall), - /// Rococo parachains bridge pallet. - #[codec(index = 43)] - BridgeRococoParachains(BridgeParachainCall), - /// Rococo messages bridge pallet. - #[codec(index = 44)] - BridgeRococoMessages(BridgeRococoMessagesCall), -} - -impl From> for Call { - fn from(call: UtilityCall) -> Call { - Call::Utility(call) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_runtime::BasicOperatingMode; - use sp_consensus_grandpa::AuthorityList; - use sp_core::hexdisplay::HexDisplay; - use sp_runtime::traits::Header; - use std::str::FromStr; - - pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; - pub type RelayBlockHasher = bp_polkadot_core::Hasher; - pub type RelayBlockHeader = sp_runtime::generic::Header; - - #[test] - fn encode_decode_calls() { - let header = RelayBlockHeader::new( - 75, - bp_polkadot_core::Hash::from_str( - "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", - ) - .expect("invalid value"), - Default::default(), - ); - let init_data = bp_header_chain::InitializationData { - header: Box::new(header), - authority_list: AuthorityList::default(), - set_id: 6, - operating_mode: BasicOperatingMode::Normal, - }; - let call = BridgeRococoGrandpaCall::initialize { init_data }; - let tx = Call::BridgeRococoGrandpa(call); - - // encode call as hex string - let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); - assert_eq!(hex_encoded_call, "0x2a01ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); - } -} diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/relays/lib-substrate-relay/src/finality/mod.rs index ea7c4e0362b85..206f628b143b8 100644 --- a/relays/lib-substrate-relay/src/finality/mod.rs +++ b/relays/lib-substrate-relay/src/finality/mod.rs @@ -191,6 +191,46 @@ macro_rules! generate_submit_finality_proof_call_builder { }; } +/// Macro that generates `SubmitFinalityProofCallBuilder` implementation for the case when +/// you only have an access to the mocked version of target chain runtime. In this case you +/// should provide "name" of the call variant for the bridge GRANDPA calls and the "name" of +/// the variant for the `submit_finality_proof_ex` call within that first option. +#[rustfmt::skip] +#[macro_export] +macro_rules! generate_submit_finality_proof_ex_call_builder { + ($pipeline:ident, $mocked_builder:ident, $bridge_grandpa:path, $submit_finality_proof:path) => { + pub struct $mocked_builder; + + impl $crate::finality::SubmitFinalityProofCallBuilder<$pipeline> + for $mocked_builder + { + fn build_submit_finality_proof_call( + header: relay_substrate_client::SyncHeader< + relay_substrate_client::HeaderOf< + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain + > + >, + proof: bp_header_chain::justification::GrandpaJustification< + relay_substrate_client::HeaderOf< + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::SourceChain + > + >, + context: bp_header_chain::justification::JustificationVerificationContext, + ) -> relay_substrate_client::CallOf< + <$pipeline as $crate::finality_base::SubstrateFinalityPipeline>::TargetChain + > { + bp_runtime::paste::item! { + $bridge_grandpa($submit_finality_proof { + finality_target: Box::new(header.into_inner()), + justification: proof, + current_set_id: context.authority_set_id + }) + } + } + } + }; +} + /// Run Substrate-to-Substrate finality sync loop. pub async fn run( source_client: Client, From 766d76ca2e4c7635a795ec75e61a7d41351c2d02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 02:27:06 +0000 Subject: [PATCH 1186/1210] Bump log from 0.4.20 to 0.4.21 Bumps [log](https://github.com/rust-lang/log) from 0.4.20 to 0.4.21. - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.20...0.4.21) --- updated-dependencies: - dependency-name: log dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/runtime-common/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- modules/xcm-bridge-hub/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/equivocation/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 88bd3422d0e76..b33667d9be67c 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 9e9a23c2fff7b..3ff70eaafd231 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", optional = true } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index b1480c7024635..33ba0f1f0fdcf 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 9d7a1e3b9d397..75efb2ed57333 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index d44b434bff7fa..ff58c8f43d2b9 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index b0c32f4c7df65..d532db3b89f70 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 56e9ae8f08ca5..8c4b62428e75a 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 86644f8e4c961..b107461ef16f4 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.20", default-features = false } +log = { version = "0.4.21", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 211737e4efc7f..542b696533aae 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" -log = { version = "0.4.19", default-features = false } +log = { version = "0.4.21", default-features = false } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index f87c24fa77d55..f4cd80696d106 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5" } env_logger = "0.11" futures = "0.3.30" hex = "0.4" -log = "0.4.20" +log = "0.4.21" num-format = "0.4" num-traits = "0.2" rbtag = "0.3" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index e72b5d6cb8cc2..56bdd150a9a83 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,7 +14,7 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } -log = "0.4.20" +log = "0.4.21" num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 2cc41dd60ec23..99cf88a4045b2 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -16,6 +16,6 @@ bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } futures = "0.3.30" -log = "0.4.20" +log = "0.4.21" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 1f2173630e08b..8c162294f9c76 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.30" -log = "0.4.20" +log = "0.4.21" num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index fe74168d7bf28..169da263ddcaf 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -17,7 +17,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" hex = "0.4" num-traits = "0.2" -log = "0.4.20" +log = "0.4.21" # Bridge dependencies diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index c03699b01eab9..14d3f191701a0 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -14,7 +14,7 @@ async-trait = "0.1" env_logger = "0.11" futures = "0.3.30" hex = "0.4" -log = "0.4.20" +log = "0.4.21" num-traits = "0.2" parking_lot = "0.12.1" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 12d5d8e928134..62c9934af332f 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true async-std = "1.6.5" async-trait = "0.1" futures = "0.3.30" -log = "0.4.20" +log = "0.4.21" relay-utils = { path = "../utils" } # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 774586f3fc193..b41cd7e84a194 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -18,7 +18,7 @@ isahc = "1.2" env_logger = "0.11.2" futures = "0.3.30" jsonpath_lib = "0.3" -log = "0.4.20" +log = "0.4.21" num-traits = "0.2" serde_json = "1.0" sysinfo = "0.30" From cf31989c7fc3d2af3a0517bccb870b10da6e293c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 4 Mar 2024 17:46:09 +0300 Subject: [PATCH 1187/1210] Some remaining fixes (mostly insubstantial) for relay (#2859) * if bundled version is `None` and cli said "use bundled" => error * update chain spec and transaction versions * use generated runtime wrapper for PBH and KBH * trigger CI * Revert "trigger CI" This reverts commit 7d9f51e34829d9224b352300d062e365243def5e. * Revert "Revert "trigger CI"" This reverts commit c86ca0e264367e39abad29b9f09f09578a980568. * Revert "Revert "Revert "trigger CI""" This reverts commit 95e7da258bb2ace4ed2cafdb01833317f38cfcfc. --- ..._kusama_messages_to_bridge_hub_polkadot.rs | 8 +- ..._polkadot_messages_to_bridge_hub_kusama.rs | 8 +- .../kusama_headers_to_bridge_hub_polkadot.rs | 4 +- ...usama_parachains_to_bridge_hub_polkadot.rs | 4 +- .../polkadot_headers_to_bridge_hub_kusama.rs | 4 +- ...olkadot_parachains_to_bridge_hub_kusama.rs | 4 +- ..._polkadot_messages_to_polkadot_bulletin.rs | 5 +- ...bulletin_headers_to_bridge_hub_polkadot.rs | 5 +- ...ulletin_messages_to_bridge_hub_polkadot.rs | 5 +- relays/bin-substrate/src/chains/kusama.rs | 5 +- relays/bin-substrate/src/chains/polkadot.rs | 5 +- relays/bin-substrate/src/chains/rococo.rs | 5 +- relays/bin-substrate/src/chains/westend.rs | 5 +- relays/bin-substrate/src/cli/chain_schema.rs | 4 +- relays/bin-substrate/src/cli/init_bridge.rs | 17 +- relays/client-bridge-hub-kusama/Cargo.toml | 9 +- .../src/codegen_runtime.rs | 4053 ++++++++++++++++ relays/client-bridge-hub-kusama/src/lib.rs | 48 +- relays/client-bridge-hub-polkadot/Cargo.toml | 13 +- .../src/codegen_runtime.rs | 4056 +++++++++++++++++ relays/client-bridge-hub-polkadot/src/lib.rs | 48 +- 21 files changed, 8234 insertions(+), 81 deletions(-) create mode 100644 relays/client-bridge-hub-kusama/src/codegen_runtime.rs create mode 100644 relays/client-bridge-hub-polkadot/src/codegen_runtime.rs diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs index 9abec22b98109..e57302315560d 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs @@ -36,15 +36,15 @@ impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge { substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane, BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaMessages, - relay_bridge_hub_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_proof + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, + relay_bridge_hub_polkadot_client::BridgeKusamaMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane, BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotMessages, - relay_bridge_hub_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_delivery_proof + relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotMessages, + relay_bridge_hub_kusama_client::BridgeMessagesCall::receive_messages_delivery_proof ); /// BridgeHubKusama-to-BridgeHubPolkadot messages lane. diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs index 191a84b27c270..0a1b21cd11243 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs @@ -36,15 +36,15 @@ impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge { substrate_relay_helper::generate_receive_message_proof_call_builder!( BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane, BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotMessages, - relay_bridge_hub_kusama_client::runtime::BridgePolkadotMessagesCall::receive_messages_proof + relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotMessages, + relay_bridge_hub_kusama_client::BridgeMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane, BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaMessages, - relay_bridge_hub_polkadot_client::runtime::BridgeKusamaMessagesCall::receive_messages_delivery_proof + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, + relay_bridge_hub_polkadot_client::BridgeKusamaMessagesCall::receive_messages_delivery_proof ); /// BridgeHubPolkadot-to-BridgeHubKusama messages lane. diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs index 2dc9c131305ad..dafb5f568263d 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -34,8 +34,8 @@ pub struct KusamaFinalityToBridgeHubPolkadot; substrate_relay_helper::generate_submit_finality_proof_call_builder!( KusamaFinalityToBridgeHubPolkadot, SubmitFinalityProofCallBuilder, - relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaGrandpa, - relay_bridge_hub_polkadot_client::runtime::BridgeKusamaGrandpaCall::submit_finality_proof + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa, + relay_bridge_hub_polkadot_client::BridgeKusamaGrandpaCall::submit_finality_proof ); substrate_relay_helper::generate_report_equivocation_call_builder!( diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs index e5936640cb3b8..9b76cdbfa63ea 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs @@ -44,8 +44,8 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaParachain( - relay_bridge_hub_polkadot_client::runtime::BridgeParachainCall::submit_parachain_heads { + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaParachains( + relay_bridge_hub_polkadot_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs index 589bf2546e8c1..019afab0bb3d6 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -34,8 +34,8 @@ pub struct PolkadotFinalityToBridgeHubKusama; substrate_relay_helper::generate_submit_finality_proof_call_builder!( PolkadotFinalityToBridgeHubKusama, SubmitFinalityProofCallBuilder, - relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotGrandpa, - relay_bridge_hub_kusama_client::runtime::BridgePolkadotGrandpaCall::submit_finality_proof + relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotGrandpa, + relay_bridge_hub_kusama_client::BridgeGrandpaCall::submit_finality_proof ); substrate_relay_helper::generate_report_equivocation_call_builder!( diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs index f2a7f7309cf1d..439eddaa1a6cd 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs @@ -44,8 +44,8 @@ impl SubmitParachainHeadsCallBuilder parachains: Vec<(ParaId, ParaHash)>, parachain_heads_proof: ParaHeadsProof, ) -> CallOf { - relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotParachain( - bp_parachains::BridgeParachainCall::submit_parachain_heads { + relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotParachains( + relay_bridge_hub_kusama_client::BridgeParachainCall::submit_parachain_heads { at_relay_block: (at_relay_block.0, at_relay_block.1), parachains, parachain_heads_proof, diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs index ba80d96a93cc2..ba177271db15f 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs @@ -43,8 +43,9 @@ substrate_relay_helper::generate_receive_message_proof_call_builder!( substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane, BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinMessages, - relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinMessagesCall::receive_messages_delivery_proof + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinMessages + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, + relay_bridge_hub_polkadot_client::BridgePolkadotBulletinMessagesCall::receive_messages_delivery_proof ); /// BridgeHubPolkadot-to-PolkadotBulletin messages lane. diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs index dbf89ddeec398..7019a6b55a36a 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs @@ -35,8 +35,9 @@ pub struct PolkadotBulletinFinalityToBridgeHubPolkadot; substrate_relay_helper::generate_submit_finality_proof_call_builder!( PolkadotBulletinFinalityToBridgeHubPolkadot, SubmitFinalityProofCallBuilder, - relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinGrandpa, - relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinGrandpaCall::submit_finality_proof + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinGrandpa + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa, + relay_bridge_hub_polkadot_client::BridgePolkadotBulletinGrandpaCall::submit_finality_proof ); substrate_relay_helper::generate_report_equivocation_call_builder!( diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs index 1db77b6ed47b0..1b5f3e5f69e84 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs @@ -36,8 +36,9 @@ impl MessagesCliBridge for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge substrate_relay_helper::generate_receive_message_proof_call_builder!( PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane, PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinMessages, - relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinMessagesCall::receive_messages_proof + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinMessages + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, + relay_bridge_hub_polkadot_client::BridgePolkadotBulletinMessagesCall::receive_messages_proof ); substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs index 0a30a0c07a095..80ffdfed0037a 100644 --- a/relays/bin-substrate/src/chains/kusama.rs +++ b/relays/bin-substrate/src/chains/kusama.rs @@ -22,10 +22,11 @@ use relay_kusama_client::Kusama; use relay_substrate_client::SimpleRuntimeVersion; impl CliChain for Kusama { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); } impl CliChain for BridgeHubKusama { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9410, transaction_version: 21 }); + Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 }); } diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs index b2585dbb3050d..1f1c607916a19 100644 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ b/relays/bin-substrate/src/chains/polkadot.rs @@ -22,10 +22,11 @@ use relay_polkadot_client::Polkadot; use relay_substrate_client::SimpleRuntimeVersion; impl CliChain for Polkadot { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); } impl CliChain for BridgeHubPolkadot { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 9410, transaction_version: 22 }); + Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 }); } diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs index fa376f0967471..0640447fdc515 100644 --- a/relays/bin-substrate/src/chains/rococo.rs +++ b/relays/bin-substrate/src/chains/rococo.rs @@ -22,10 +22,11 @@ use relay_rococo_client::Rococo; use relay_substrate_client::SimpleRuntimeVersion; impl CliChain for Rococo { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); } impl CliChain for BridgeHubRococo { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); } diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs index be26a36627ad8..41f5fc4e96c8f 100644 --- a/relays/bin-substrate/src/chains/westend.rs +++ b/relays/bin-substrate/src/chains/westend.rs @@ -22,10 +22,11 @@ use relay_substrate_client::SimpleRuntimeVersion; use relay_westend_client::Westend; impl CliChain for Westend { - const RUNTIME_VERSION: Option = None; + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); } impl CliChain for BridgeHubWestend { const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); } diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 7c647dfbfd1df..65559397ac2a7 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -75,7 +75,9 @@ macro_rules! declare_chain_runtime_version_params_cli_schema { }, RuntimeVersionType::Bundle => match bundle_runtime_version { Some(runtime_version) => ChainRuntimeVersion::Custom(runtime_version), - None => ChainRuntimeVersion::Auto + None => { + return Err(anyhow::format_err!("Cannot use bundled runtime version of {}: it is not known to the relay", stringify!($chain_prefix))); + } }, }) } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 52cb28014f454..0b2f9aa7e1ec7 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -146,10 +146,8 @@ impl BridgeInitializer for KusamaToBridgeHubPolkadotCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - relay_bridge_hub_polkadot_client::runtime::Call::BridgeKusamaGrandpa( - relay_bridge_hub_polkadot_client::runtime::BridgeKusamaGrandpaCall::initialize { - init_data, - }, + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa( + relay_bridge_hub_polkadot_client::BridgeKusamaGrandpaCall::initialize { init_data }, ) } } @@ -160,10 +158,8 @@ impl BridgeInitializer for PolkadotToBridgeHubKusamaCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - relay_bridge_hub_kusama_client::runtime::Call::BridgePolkadotGrandpa( - relay_bridge_hub_kusama_client::runtime::BridgePolkadotGrandpaCall::initialize { - init_data, - }, + relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotGrandpa( + relay_bridge_hub_kusama_client::BridgeGrandpaCall::initialize { init_data }, ) } } @@ -191,8 +187,9 @@ impl BridgeInitializer for PolkadotBulletinToBridgeHubPolkadotCliBridge { fn encode_init_bridge( init_data: >::InitializationData, ) -> ::Call { - relay_bridge_hub_polkadot_client::runtime::Call::BridgePolkadotBulletinGrandpa( - relay_bridge_hub_polkadot_client::runtime::BridgePolkadotBulletinGrandpaCall::initialize { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinGrandpa + relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa( + relay_bridge_hub_polkadot_client::BridgePolkadotBulletinGrandpaCall::initialize { init_data, }, ) diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index ea94dac7de4b3..30177443c3e50 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -11,19 +11,22 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -relay-substrate-client = { path = "../client-substrate" } +#relay-substrate-client = { path = "../client-substrate" } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } -bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot = { path = "../../primitives/chain-polkadot" } - +bp-polkadot-core = { path = "../../primitives/polkadot-core" } bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-kusama/src/codegen_runtime.rs b/relays/client-bridge-hub-kusama/src/codegen_runtime.rs new file mode 100644 index 0000000000000..78ae788b32d57 --- /dev/null +++ b/relays/client-bridge-hub-kusama/src/codegen_runtime.rs @@ -0,0 +1,4053 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url +//! wss://kusama-bridge-hub-rpc.polkadot.io + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +#[allow(rustdoc::broken_intra_doc_links)] +pub mod api { + #[allow(unused_imports)] + mod root_mod { + pub use super::*; + } + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod bp_header_chain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AuthoritySet { + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HeaderChainError { + #[codec(index = 0)] + UnknownHeader, + #[codec(index = 1)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderFinalityInfo<_0, _1> { + pub finality_proof: _0, + pub new_verification_context: ::core::option::Option<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredHeaderData<_0, _1> { + pub number: _0, + pub state_root: _1, + } + } + pub mod bp_messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DeliveredMessages { + pub begin: ::core::primitive::u64, + pub end: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundLaneData<_0> { + pub relayers: ::std::vec::Vec>, + pub last_confirmed_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundMessageDetails { + pub dispatch_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LaneId(pub [::core::primitive::u8; 4usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageKey { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MessagesOperatingMode { + #[codec(index = 0)] + Basic(runtime_types::bp_runtime::BasicOperatingMode), + #[codec(index = 1)] + RejectingOutboundMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundLaneData { + pub oldest_unpruned_nonce: ::core::primitive::u64, + pub latest_received_nonce: ::core::primitive::u64, + pub latest_generated_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundMessageDetails { + pub nonce: ::core::primitive::u64, + pub dispatch_weight: ::sp_weights::Weight, + pub size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalResult<_0> { + #[codec(index = 0)] + Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), + #[codec(index = 1)] + InvalidNonce, + #[codec(index = 2)] + TooManyUnrewardedRelayers, + #[codec(index = 3)] + TooManyUnconfirmedMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceivedMessages<_0> { + pub lane: runtime_types::bp_messages::LaneId, + pub receive_results: ::std::vec::Vec<( + ::core::primitive::u64, + runtime_types::bp_messages::ReceivalResult<_0>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnrewardedRelayer<_0> { + pub relayer: _0, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VerificationError { + #[codec(index = 0)] + EmptyMessageProof, + #[codec(index = 1)] + HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 2)] + InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 3)] + InvalidMessageWeight, + #[codec(index = 4)] + MessagesCountMismatch, + #[codec(index = 5)] + MessageStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 6)] + MessageTooLarge, + #[codec(index = 7)] + OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 8)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 9)] + Other, + } + } + pub mod bp_parachains { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BestParaHeadHash { + pub at_relay_block_number: ::core::primitive::u32, + pub head_hash: ::subxt::utils::H256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo { + pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, + pub next_imported_hash_position: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); + } + pub mod bp_relayers { + use super::runtime_types; + pub mod registration { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0, _1> { + pub valid_till: _0, + pub stake: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardsAccountOwner { + #[codec(index = 0)] + ThisChain, + #[codec(index = 1)] + BridgedChain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardsAccountParams { + pub lane_id: runtime_types::bp_messages::LaneId, + pub bridged_chain_id: [::core::primitive::u8; 4usize], + pub owner: runtime_types::bp_relayers::RewardsAccountOwner, + } + } + pub mod bp_runtime { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageDispatchResult<_0> { + pub unspent_weight: ::sp_weights::Weight, + pub dispatch_level_result: _0, + } + } + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateNodesInProof, + #[codec(index = 1)] + UnusedNodesInTheProof, + #[codec(index = 2)] + StorageRootMismatch, + #[codec(index = 3)] + StorageValueUnavailable, + #[codec(index = 4)] + StorageValueEmpty, + #[codec(index = 5)] + StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderId<_0, _1>(pub _1, pub _0); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OwnedBridgeModuleError { + #[codec(index = 0)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StrippableError; + } + pub mod bridge_hub_kusama_runtime { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BridgeRejectObsoleteHeadersAndMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + #[codec(index = 0)] + system( + runtime_types::frame_support::dispatch::RawOrigin< + ::sp_core::crypto::AccountId32, + >, + ), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), + #[codec(index = 3)] + Void(runtime_types::sp_core::Void), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 41)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 50)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + #[codec(index = 51)] + BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 52)] + BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 53)] + BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeError { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Error), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Error), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Error), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Error), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Error), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Error), + #[codec(index = 41)] + Multisig(runtime_types::pallet_multisig::pallet::Error), + #[codec(index = 50)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), + #[codec(index = 51)] + BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), + #[codec(index = 52)] + BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Error), + #[codec(index = 53)] + BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 11)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 41)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 50)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 51)] + BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 52)] + BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 53)] + BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeHoldReason {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, + } + } + pub mod bridge_runtime_common { + use super::runtime_types; + pub mod messages_xcm_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmBlobMessageDispatchResult { + #[codec(index = 0)] + InvalidPayload, + #[codec(index = 1)] + Dispatched, + #[codec(index = 2)] + NotDispatched, + } + } + pub mod refund_relayer_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundBridgedParachainMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundSignedExtensionAdapter<_0>(pub _0); + } + } + pub mod cumulus_pallet_dmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + OverLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 1)] + UnsupportedVersion { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 2)] + ExecutedDownward { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + outcome: runtime_types::xcm::v3::traits::Outcome, + }, + #[codec(index = 3)] + WeightExhausted { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + remaining_weight: ::sp_weights::Weight, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + OverweightEnqueued { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + overweight_index: ::core::primitive::u64, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 5)] + OverweightServiced { + overweight_index: ::core::primitive::u64, + weight_used: ::sp_weights::Weight, + }, + #[codec(index = 6)] + MaxMessagesExhausted { message_hash: [::core::primitive::u8; 32usize] }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ConfigData { + pub max_individual: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PageIndexData { + pub begin_used: ::core::primitive::u32, + pub end_used: ::core::primitive::u32, + pub overweight_count: ::core::primitive::u64, + } + } + pub mod cumulus_pallet_parachain_system { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OverlappingUpgrades, + #[codec(index = 1)] + ProhibitedByPolkadot, + #[codec(index = 2)] + TooBig, + #[codec(index = 3)] + ValidationDataNotAvailable, + #[codec(index = 4)] + HostConfigurationNotAvailable, + #[codec(index = 5)] + NotScheduled, + #[codec(index = 6)] + NothingAuthorized, + #[codec(index = 7)] + Unauthorized, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ValidationFunctionStored, + #[codec(index = 1)] + ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, + #[codec(index = 2)] + ValidationFunctionDiscarded, + #[codec(index = 3)] + UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + DownwardMessagesReceived { count: ::core::primitive::u32 }, + #[codec(index = 5)] + DownwardMessagesProcessed { + weight_used: ::sp_weights::Weight, + dmq_head: ::subxt::utils::H256, + }, + #[codec(index = 6)] + UpwardMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + pub mod relay_state_snapshot { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RelayDispatchQueueRemainingCapacity { + pub remaining_count: ::core::primitive::u32, + pub remaining_size: ::core::primitive::u32, + } + } + pub mod unincluded_segment { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelUpdate { + pub msg_count: ::core::primitive::u32, + pub total_bytes: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CodeUpgradeAuthorization { + pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, + } + } + pub mod cumulus_pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + UnsupportedVersion([::core::primitive::u8; 32usize]), + #[codec(index = 2)] + ExecutedDownward( + [::core::primitive::u8; 32usize], + runtime_types::xcm::v3::traits::Outcome, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Relay, + #[codec(index = 1)] + SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), + } + } + } + pub mod cumulus_pallet_xcmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + #[codec(index = 1)] + suspend_xcm_execution, + #[codec(index = 2)] + resume_xcm_execution, + #[codec(index = 3)] + update_suspend_threshold { new: ::core::primitive::u32 }, + #[codec(index = 4)] + update_drop_threshold { new: ::core::primitive::u32 }, + #[codec(index = 5)] + update_resume_threshold { new: ::core::primitive::u32 }, + #[codec(index = 6)] + update_threshold_weight { new: ::sp_weights::Weight }, + #[codec(index = 7)] + update_weight_restrict_decay { new: ::sp_weights::Weight }, + #[codec(index = 8)] + update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSend, + #[codec(index = 1)] + BadXcmOrigin, + #[codec(index = 2)] + BadXcm, + #[codec(index = 3)] + BadOverweightIndex, + #[codec(index = 4)] + WeightOverLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Success { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + weight: ::sp_weights::Weight, + }, + #[codec(index = 1)] + Fail { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + error: runtime_types::xcm::v3::traits::Error, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + BadVersion { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 3)] + BadFormat { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 4)] + XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 5)] + OverweightEnqueued { + sender: runtime_types::polkadot_parachain_primitives::primitives::Id, + sent_at: ::core::primitive::u32, + index: ::core::primitive::u64, + required: ::sp_weights::Weight, + }, + #[codec(index = 6)] + OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundChannelDetails { + pub sender: runtime_types::polkadot_parachain_primitives::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, + pub message_metadata: ::std::vec::Vec<( + ::core::primitive::u32, + runtime_types::polkadot_parachain_primitives::primitives::XcmpMessageFormat, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundChannelDetails { + pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, + pub signals_exist: ::core::primitive::bool, + pub first_index: ::core::primitive::u16, + pub last_index: ::core::primitive::u16, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OutboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueueConfigData { + pub suspend_threshold: ::core::primitive::u32, + pub drop_threshold: ::core::primitive::u32, + pub resume_threshold: ::core::primitive::u32, + pub threshold_weight: ::sp_weights::Weight, + pub weight_restrict_decay: ::sp_weights::Weight, + pub xcmp_max_individual_weight: ::sp_weights::Weight, + } + } + pub mod cumulus_primitives_core { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CollationInfo { + pub upward_messages: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub horizontal_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain_primitives::primitives::Id, + >, + >, + pub new_validation_code: ::core::option::Option< + runtime_types::polkadot_parachain_primitives::primitives::ValidationCode, + >, + pub processed_downward_messages: ::core::primitive::u32, + pub hrmp_watermark: ::core::primitive::u32, + pub head_data: runtime_types::polkadot_parachain_primitives::primitives::HeadData, + } + } + pub mod cumulus_primitives_parachain_inherent { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageQueueChain(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParachainInherentData { + pub validation_data: + runtime_types::polkadot_primitives::v6::PersistedValidationData< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, + pub downward_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundDownwardMessage< + ::core::primitive::u32, + >, + >, + pub horizontal_messages: ::subxt::utils::KeyedVec< + runtime_types::polkadot_parachain_primitives::primitives::Id, + ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundHrmpMessage< + ::core::primitive::u32, + >, + >, + >, + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commit<_0, _1, _2, _3> { + pub target_hash: _0, + pub target_number: _1, + pub precommits: ::std::vec::Vec< + runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedPrecommit<_0, _1, _2, _3> { + pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, + pub signature: _2, + pub id: _3, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: ::core::primitive::u32, + pub providers: ::core::primitive::u32, + pub sufficients: ::core::primitive::u32, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_bridge_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 1)] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 2)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidJustification, + #[codec(index = 1)] + InvalidAuthoritySet, + #[codec(index = 2)] + OldHeader, + #[codec(index = 3)] + UnsupportedScheduledChange, + #[codec(index = 4)] + NotInitialized, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooManyAuthoritiesInSet, + #[codec(index = 7)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u32, + hash: ::subxt::utils::H256, + grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< + ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + runtime_types::bp_header_chain::AuthoritySet, + >, + }, + } + } + pub mod storage_types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredAuthoritySet { + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + } + } + pub mod pallet_bridge_messages { + use super::runtime_types; + pub mod outbound_lane { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalConfirmationError { + #[codec(index = 0)] + FailedToConfirmFutureMessages, + #[codec(index = 1)] + EmptyUnrewardedRelayerEntry, + #[codec(index = 2)] + NonConsecutiveUnrewardedRelayerEntries, + #[codec(index = 3)] + TryingToConfirmMoreMessagesThanExpected, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } + } + } + pub mod pallet_bridge_parachains { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_parachain_heads { + at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), + parachains: ::std::vec::Vec<( + ::bp_polkadot_core::parachains::ParaId, + ::subxt::utils::H256, + )>, + parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, + }, + #[codec(index = 1)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 2)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnknownRelayChainBlock, + #[codec(index = 1)] + InvalidRelayChainBlockNumber, + #[codec(index = 2)] + HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 3)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 1)] + MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 2)] + IncorrectParachainHeadHash { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + actual_parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + RejectedObsoleteParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 4)] + RejectedLargeParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + parachain_head_size: ::core::primitive::u32, + }, + #[codec(index = 5)] + UpdatedParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + } + } + } + pub mod pallet_bridge_relayers { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim_rewards { + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + }, + #[codec(index = 1)] + register { valid_till: ::core::primitive::u32 }, + #[codec(index = 2)] + deregister, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NoRewardForRelayer, + #[codec(index = 1)] + FailedToPayReward, + #[codec(index = 2)] + InvalidRegistrationLease, + #[codec(index = 3)] + CannotReduceRegistrationLease, + #[codec(index = 4)] + FailedToReserve, + #[codec(index = 5)] + FailedToUnreserve, + #[codec(index = 6)] + NotRegistered, + #[codec(index = 7)] + RegistrationIsStillActive, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RewardPaid { + relayer: ::sp_core::crypto::AccountId32, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + reward: ::core::primitive::u128, + }, + #[codec(index = 1)] + RegistrationUpdated { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + Deregistered { relayer: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + SlashedAndDeregistered { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + } + } + } + pub mod pallet_collator_selection { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 1)] + set_desired_candidates { max: ::core::primitive::u32 }, + #[codec(index = 2)] + set_candidacy_bond { bond: ::core::primitive::u128 }, + #[codec(index = 3)] + register_as_candidate, + #[codec(index = 4)] + leave_intent, + #[codec(index = 5)] + add_invulnerable { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateInfo<_0, _1> { + pub who: _0, + pub deposit: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCandidates, + #[codec(index = 1)] + TooFewEligibleCollators, + #[codec(index = 2)] + AlreadyCandidate, + #[codec(index = 3)] + NotCandidate, + #[codec(index = 4)] + TooManyInvulnerables, + #[codec(index = 5)] + AlreadyInvulnerable, + #[codec(index = 6)] + NotInvulnerable, + #[codec(index = 7)] + NoAssociatedValidatorId, + #[codec(index = 8)] + ValidatorNotRegistered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewInvulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 1)] + InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 2)] + InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, + #[codec(index = 4)] + NewCandidacyBond { bond_amount: ::core::primitive::u128 }, + #[codec(index = 5)] + CandidateAdded { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 6)] + CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 7)] + InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, + } + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box< + runtime_types::bridge_hub_kusama_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_kusama_runtime::RuntimeCall, + >, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: ::core::primitive::u32, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::bridge_hub_kusama_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FeeDetails<_0> { + pub inclusion_fee: ::core::option::Option< + runtime_types::pallet_transaction_payment::types::InclusionFee<_0>, + >, + pub tip: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InclusionFee<_0> { + pub base_fee: _0, + pub len_fee: _0, + pub adjusted_weight_fee: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDispatchInfo<_0, _1> { + pub weight: _1, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub partial_fee: _0, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { + calls: + ::std::vec::Vec, + }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box< + runtime_types::bridge_hub_kusama_runtime::RuntimeCall, + >, + }, + #[codec(index = 2)] + batch_all { + calls: + ::std::vec::Vec, + }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box< + runtime_types::bridge_hub_kusama_runtime::OriginCaller, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_kusama_runtime::RuntimeCall, + >, + }, + #[codec(index = 4)] + force_batch { + calls: + ::std::vec::Vec, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box< + runtime_types::bridge_hub_kusama_runtime::RuntimeCall, + >, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: ::std::boxed::Box< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted { outcome: runtime_types::xcm::v3::traits::Outcome }, + #[codec(index = 1)] + Sent { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + message: runtime_types::xcm::v3::Xcm, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + UnexpectedResponse { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 3)] + ResponseReady { + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + }, + #[codec(index = 4)] + Notified { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 5)] + NotifyOverweight { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + actual_weight: ::sp_weights::Weight, + max_budgeted_weight: ::sp_weights::Weight, + }, + #[codec(index = 6)] + NotifyDispatchError { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 7)] + NotifyDecodeFailed { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 8)] + InvalidResponder { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + expected_location: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 9)] + InvalidResponderVersion { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 10)] + ResponseTaken { query_id: ::core::primitive::u64 }, + #[codec(index = 11)] + AssetsTrapped { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + }, + #[codec(index = 12)] + VersionChangeNotified { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + result: ::core::primitive::u32, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 13)] + SupportedVersionChanged { + location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + version: ::core::primitive::u32, + }, + #[codec(index = 14)] + NotifyTargetSendFail { + location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + error: runtime_types::xcm::v3::traits::Error, + }, + #[codec(index = 15)] + NotifyTargetMigrationFail { + location: runtime_types::xcm::VersionedMultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 16)] + InvalidQuerierVersion { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 17)] + InvalidQuerier { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + expected_querier: + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + maybe_actual_querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 18)] + VersionNotifyStarted { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 19)] + VersionNotifyRequested { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 20)] + VersionNotifyUnrequested { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 21)] + FeesPaid { + paying: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + fees: runtime_types::xcm::v3::multiasset::MultiAssets, + }, + #[codec(index = 22)] + AssetsClaimed { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain_primitives { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmpMessageFormat { + #[codec(index = 0)] + ConcatenatedVersionedXcm, + #[codec(index = 1)] + ConcatenatedEncodedBlob, + #[codec(index = 2)] + Signals, + } + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v6 { + use super::runtime_types; + pub mod async_backing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHostConfiguration { + pub max_code_size: ::core::primitive::u32, + pub max_head_data_size: ::core::primitive::u32, + pub max_upward_queue_count: ::core::primitive::u32, + pub max_upward_queue_size: ::core::primitive::u32, + pub max_upward_message_size: ::core::primitive::u32, + pub max_upward_message_num_per_candidate: ::core::primitive::u32, + pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, + pub validation_upgrade_cooldown: ::core::primitive::u32, + pub validation_upgrade_delay: ::core::primitive::u32, + pub async_backing_params: + runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PersistedValidationData<_0, _1> { + pub parent_head: + runtime_types::polkadot_parachain_primitives::primitives::HeadData, + pub relay_parent_number: _1, + pub relay_parent_storage_root: _0, + pub max_pov_size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_consensus_aura { + use super::runtime_types; + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct SlotDuration(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMetadata(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_inherents { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckInherentsResult { + pub okay: ::core::primitive::bool, + pub fatal_error: ::core::primitive::bool, + pub errors: runtime_types::sp_inherents::InherentData, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData { + pub data: ::subxt::utils::KeyedVec< + [::core::primitive::u8; 8usize], + ::std::vec::Vec<::core::primitive::u8>, + >, + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod block { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Block<_0, _1> { + pub header: _0, + pub extrinsics: ::std::vec::Vec<_1>, + } + } + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + } + pub mod transaction_validity { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidTransaction { + #[codec(index = 0)] + Call, + #[codec(index = 1)] + Payment, + #[codec(index = 2)] + Future, + #[codec(index = 3)] + Stale, + #[codec(index = 4)] + BadProof, + #[codec(index = 5)] + AncientBirthBlock, + #[codec(index = 6)] + ExhaustsResources, + #[codec(index = 7)] + Custom(::core::primitive::u8), + #[codec(index = 8)] + BadMandatory, + #[codec(index = 9)] + MandatoryValidation, + #[codec(index = 10)] + BadSigner, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionSource { + #[codec(index = 0)] + InBlock, + #[codec(index = 1)] + Local, + #[codec(index = 2)] + External, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionValidityError { + #[codec(index = 0)] + Invalid(runtime_types::sp_runtime::transaction_validity::InvalidTransaction), + #[codec(index = 1)] + Unknown(runtime_types::sp_runtime::transaction_validity::UnknownTransaction), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UnknownTransaction { + #[codec(index = 0)] + CannotLookup, + #[codec(index = 1)] + NoUnsignedValidator, + #[codec(index = 2)] + Custom(::core::primitive::u8), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidTransaction { + pub priority: ::core::primitive::u64, + pub requires: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub provides: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub longevity: ::core::primitive::u64, + pub propagate: ::core::primitive::bool, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_trie { + use super::runtime_types; + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StorageProof { + pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod staging_xcm { + use super::runtime_types; + pub mod v3 { + use super::runtime_types; + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded2 { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm2 { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm2), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm2), + } + } + } +} diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index d4bb057de1c23..b11301b0e0f8a 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -16,21 +16,28 @@ //! Types used to connect to the BridgeHub-Kusama-Substrate parachain. -use bp_bridge_hub_kusama::AVERAGE_BLOCK_INTERVAL; +pub mod codegen_runtime; + +use bp_bridge_hub_kusama::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_polkadot::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -/// Re-export runtime wrapper -pub mod runtime_wrapper; -pub use runtime_wrapper as runtime; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::bridge_hub_kusama_runtime::RuntimeCall; +pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; +type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; +type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Kusama chain definition #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -47,7 +54,7 @@ impl Chain for BridgeHubKusama { const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_kusama::SignedBlock; - type Call = runtime::Call; + type Call = RuntimeCall; } impl ChainWithBalances for BridgeHubKusama { @@ -56,13 +63,22 @@ impl ChainWithBalances for BridgeHubKusama { } } +impl From> for RuntimeCall { + fn from(value: MockUtilityCall) -> RuntimeCall { + match value { + MockUtilityCall::batch_all(calls) => + RuntimeCall::Utility(UtilityCall::batch_all { calls }), + } + } +} + impl ChainWithUtilityPallet for BridgeHubKusama { - type UtilityPallet = MockedRuntimeUtilityPallet; + type UtilityPallet = MockedRuntimeUtilityPallet; } impl ChainWithTransactions for BridgeHubKusama { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = runtime::UncheckedExtrinsic; + type SignedTransaction = UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -70,7 +86,7 @@ impl ChainWithTransactions for BridgeHubKusama { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::SignedExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -85,7 +101,7 @@ impl ChainWithTransactions for BridgeHubKusama { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(runtime::UncheckedExtrinsic::new_signed( + Ok(UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -127,13 +143,13 @@ mod tests { use super::*; use relay_substrate_client::TransactionEra; + type SystemCall = runtime_types::frame_system::pallet::Call; + #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(relay_substrate_client::calls::SystemCall::remark( - b"Hello world!".to_vec(), - )) - .into(), + call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) + .into(), nonce: 777, tip: 888, era: TransactionEra::immortal(), diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index 2fd950efabe57..a85e2d685c486 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -11,26 +11,23 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -relay-substrate-client = { path = "../client-substrate" } +subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } +bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } +bp-polkadot = { path = "../../primitives/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-kusama = { path = "../../primitives/chain-kusama" } bp-runtime = { path = "../../primitives/runtime" } - bridge-runtime-common = { path = "../../bin/runtime-common" } +relay-substrate-client = { path = "../client-substrate" } # Substrate Dependencies sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[dev-dependencies] -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } +sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs b/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs new file mode 100644 index 0000000000000..c8c063b5e19cb --- /dev/null +++ b/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs @@ -0,0 +1,4056 @@ +// Copyright 2019-2023 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 . + +//! Autogenerated runtime API +//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen +//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url +//! wss://polkadot-bridge-hub-rpc.polkadot.io + +#[allow(dead_code, unused_imports, non_camel_case_types)] +#[allow(clippy::all)] +#[allow(rustdoc::broken_intra_doc_links)] +pub mod api { + #[allow(unused_imports)] + mod root_mod { + pub use super::*; + } + pub mod runtime_types { + use super::runtime_types; + pub mod bounded_collections { + use super::runtime_types; + pub mod bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + pub mod weak_bounded_vec { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); + } + } + pub mod bp_header_chain { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AuthoritySet { + pub authorities: ::std::vec::Vec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum HeaderChainError { + #[codec(index = 0)] + UnknownHeader, + #[codec(index = 1)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderFinalityInfo<_0, _1> { + pub finality_proof: _0, + pub new_verification_context: ::core::option::Option<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredHeaderData<_0, _1> { + pub number: _0, + pub state_root: _1, + } + } + pub mod bp_messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DeliveredMessages { + pub begin: ::core::primitive::u64, + pub end: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundLaneData<_0> { + pub relayers: ::std::vec::Vec>, + pub last_confirmed_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundMessageDetails { + pub dispatch_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LaneId(pub [::core::primitive::u8; 4usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageKey { + pub lane_id: runtime_types::bp_messages::LaneId, + pub nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MessagesOperatingMode { + #[codec(index = 0)] + Basic(runtime_types::bp_runtime::BasicOperatingMode), + #[codec(index = 1)] + RejectingOutboundMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundLaneData { + pub oldest_unpruned_nonce: ::core::primitive::u64, + pub latest_received_nonce: ::core::primitive::u64, + pub latest_generated_nonce: ::core::primitive::u64, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundMessageDetails { + pub nonce: ::core::primitive::u64, + pub dispatch_weight: ::sp_weights::Weight, + pub size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalResult<_0> { + #[codec(index = 0)] + Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), + #[codec(index = 1)] + InvalidNonce, + #[codec(index = 2)] + TooManyUnrewardedRelayers, + #[codec(index = 3)] + TooManyUnconfirmedMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReceivedMessages<_0> { + pub lane: runtime_types::bp_messages::LaneId, + pub receive_results: ::std::vec::Vec<( + ::core::primitive::u64, + runtime_types::bp_messages::ReceivalResult<_0>, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UnrewardedRelayer<_0> { + pub relayer: _0, + pub messages: runtime_types::bp_messages::DeliveredMessages, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VerificationError { + #[codec(index = 0)] + EmptyMessageProof, + #[codec(index = 1)] + HeaderChain(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 2)] + InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 3)] + InvalidMessageWeight, + #[codec(index = 4)] + MessagesCountMismatch, + #[codec(index = 5)] + MessageStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 6)] + MessageTooLarge, + #[codec(index = 7)] + OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 8)] + StorageProof(runtime_types::bp_runtime::storage_proof::Error), + #[codec(index = 9)] + Other, + } + } + pub mod bp_parachains { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BestParaHeadHash { + pub at_relay_block_number: ::core::primitive::u32, + pub head_hash: ::subxt::utils::H256, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaInfo { + pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, + pub next_imported_hash_position: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); + } + pub mod bp_relayers { + use super::runtime_types; + pub mod registration { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Registration<_0, _1> { + pub valid_till: _0, + pub stake: _1, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RewardsAccountOwner { + #[codec(index = 0)] + ThisChain, + #[codec(index = 1)] + BridgedChain, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RewardsAccountParams { + pub lane_id: runtime_types::bp_messages::LaneId, + pub bridged_chain_id: [::core::primitive::u8; 4usize], + pub owner: runtime_types::bp_relayers::RewardsAccountOwner, + } + } + pub mod bp_runtime { + use super::runtime_types; + pub mod messages { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageDispatchResult<_0> { + pub unspent_weight: ::sp_weights::Weight, + pub dispatch_level_result: _0, + } + } + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + DuplicateNodesInProof, + #[codec(index = 1)] + UnusedNodesInTheProof, + #[codec(index = 2)] + StorageRootMismatch, + #[codec(index = 3)] + StorageValueUnavailable, + #[codec(index = 4)] + StorageValueEmpty, + #[codec(index = 5)] + StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BasicOperatingMode { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeaderId<_0, _1>(pub _1, pub _0); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OwnedBridgeModuleError { + #[codec(index = 0)] + Halted, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StrippableError; + } + pub mod bridge_hub_polkadot_runtime { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BridgeRejectObsoleteHeadersAndMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginCaller { + #[codec(index = 0)] + system( + runtime_types::frame_support::dispatch::RawOrigin< + ::sp_core::crypto::AccountId32, + >, + ), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), + #[codec(index = 3)] + Void(runtime_types::sp_core::Void), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Runtime; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeCall { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Call), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), + #[codec(index = 2)] + Timestamp(runtime_types::pallet_timestamp::pallet::Call), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Call), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Call), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Call), + #[codec(index = 41)] + Multisig(runtime_types::pallet_multisig::pallet::Call), + #[codec(index = 50)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), + #[codec(index = 51)] + BridgeKusamaGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), + #[codec(index = 52)] + BridgeKusamaParachains(runtime_types::pallet_bridge_parachains::pallet::Call), + #[codec(index = 53)] + BridgeKusamaMessages(runtime_types::pallet_bridge_messages::pallet::Call), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeError { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Error), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Error), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Error), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Error), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Error), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Error), + #[codec(index = 41)] + Multisig(runtime_types::pallet_multisig::pallet::Error), + #[codec(index = 50)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), + #[codec(index = 51)] + BridgeKusamaGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), + #[codec(index = 52)] + BridgeKusamaParachains(runtime_types::pallet_bridge_parachains::pallet::Error), + #[codec(index = 53)] + BridgeKusamaMessages(runtime_types::pallet_bridge_messages::pallet::Error), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeEvent { + #[codec(index = 0)] + System(runtime_types::frame_system::pallet::Event), + #[codec(index = 1)] + ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), + #[codec(index = 10)] + Balances(runtime_types::pallet_balances::pallet::Event), + #[codec(index = 11)] + TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), + #[codec(index = 21)] + CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), + #[codec(index = 22)] + Session(runtime_types::pallet_session::pallet::Event), + #[codec(index = 30)] + XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), + #[codec(index = 31)] + PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), + #[codec(index = 32)] + CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), + #[codec(index = 33)] + DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), + #[codec(index = 40)] + Utility(runtime_types::pallet_utility::pallet::Event), + #[codec(index = 41)] + Multisig(runtime_types::pallet_multisig::pallet::Event), + #[codec(index = 50)] + BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), + #[codec(index = 51)] + BridgeKusamaGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), + #[codec(index = 52)] + BridgeKusamaParachains(runtime_types::pallet_bridge_parachains::pallet::Event), + #[codec(index = 53)] + BridgeKusamaMessages(runtime_types::pallet_bridge_messages::pallet::Event), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RuntimeHoldReason {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SessionKeys { + pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, + } + } + pub mod bridge_runtime_common { + use super::runtime_types; + pub mod messages_xcm_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmBlobMessageDispatchResult { + #[codec(index = 0)] + InvalidPayload, + #[codec(index = 1)] + Dispatched, + #[codec(index = 2)] + NotDispatched, + } + } + pub mod refund_relayer_extension { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundBridgedParachainMessages; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RefundSignedExtensionAdapter<_0>(pub _0); + } + } + pub mod cumulus_pallet_dmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unknown, + #[codec(index = 1)] + OverLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 1)] + UnsupportedVersion { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 2)] + ExecutedDownward { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + outcome: runtime_types::xcm::v3::traits::Outcome, + }, + #[codec(index = 3)] + WeightExhausted { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + remaining_weight: ::sp_weights::Weight, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + OverweightEnqueued { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + overweight_index: ::core::primitive::u64, + required_weight: ::sp_weights::Weight, + }, + #[codec(index = 5)] + OverweightServiced { + overweight_index: ::core::primitive::u64, + weight_used: ::sp_weights::Weight, + }, + #[codec(index = 6)] + MaxMessagesExhausted { message_hash: [::core::primitive::u8; 32usize] }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ConfigData { + pub max_individual: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PageIndexData { + pub begin_used: ::core::primitive::u32, + pub end_used: ::core::primitive::u32, + pub overweight_count: ::core::primitive::u64, + } + } + pub mod cumulus_pallet_parachain_system { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + OverlappingUpgrades, + #[codec(index = 1)] + ProhibitedByPolkadot, + #[codec(index = 2)] + TooBig, + #[codec(index = 3)] + ValidationDataNotAvailable, + #[codec(index = 4)] + HostConfigurationNotAvailable, + #[codec(index = 5)] + NotScheduled, + #[codec(index = 6)] + NothingAuthorized, + #[codec(index = 7)] + Unauthorized, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ValidationFunctionStored, + #[codec(index = 1)] + ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, + #[codec(index = 2)] + ValidationFunctionDiscarded, + #[codec(index = 3)] + UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, + #[codec(index = 4)] + DownwardMessagesReceived { count: ::core::primitive::u32 }, + #[codec(index = 5)] + DownwardMessagesProcessed { + weight_used: ::sp_weights::Weight, + dmq_head: ::subxt::utils::H256, + }, + #[codec(index = 6)] + UpwardMessageSent { + message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, + }, + } + } + pub mod relay_state_snapshot { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RelayDispatchQueueRemainingCapacity { + pub remaining_count: ::core::primitive::u32, + pub remaining_size: ::core::primitive::u32, + } + } + pub mod unincluded_segment { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HrmpChannelUpdate { + pub msg_count: ::core::primitive::u32, + pub total_bytes: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CodeUpgradeAuthorization { + pub code_hash: ::subxt::utils::H256, + pub check_version: ::core::primitive::bool, + } + } + pub mod cumulus_pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error {} + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + InvalidFormat([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + UnsupportedVersion([::core::primitive::u8; 32usize]), + #[codec(index = 2)] + ExecutedDownward( + [::core::primitive::u8; 32usize], + runtime_types::xcm::v3::traits::Outcome, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Relay, + #[codec(index = 1)] + SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), + } + } + } + pub mod cumulus_pallet_xcmp_queue { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + service_overweight { + index: ::core::primitive::u64, + weight_limit: ::sp_weights::Weight, + }, + #[codec(index = 1)] + suspend_xcm_execution, + #[codec(index = 2)] + resume_xcm_execution, + #[codec(index = 3)] + update_suspend_threshold { new: ::core::primitive::u32 }, + #[codec(index = 4)] + update_drop_threshold { new: ::core::primitive::u32 }, + #[codec(index = 5)] + update_resume_threshold { new: ::core::primitive::u32 }, + #[codec(index = 6)] + update_threshold_weight { new: ::sp_weights::Weight }, + #[codec(index = 7)] + update_weight_restrict_decay { new: ::sp_weights::Weight }, + #[codec(index = 8)] + update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + FailedToSend, + #[codec(index = 1)] + BadXcmOrigin, + #[codec(index = 2)] + BadXcm, + #[codec(index = 3)] + BadOverweightIndex, + #[codec(index = 4)] + WeightOverLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Success { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + weight: ::sp_weights::Weight, + }, + #[codec(index = 1)] + Fail { + message_hash: [::core::primitive::u8; 32usize], + message_id: [::core::primitive::u8; 32usize], + error: runtime_types::xcm::v3::traits::Error, + weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + BadVersion { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 3)] + BadFormat { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 4)] + XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, + #[codec(index = 5)] + OverweightEnqueued { + sender: runtime_types::polkadot_parachain_primitives::primitives::Id, + sent_at: ::core::primitive::u32, + index: ::core::primitive::u64, + required: ::sp_weights::Weight, + }, + #[codec(index = 6)] + OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundChannelDetails { + pub sender: runtime_types::polkadot_parachain_primitives::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, + pub message_metadata: ::std::vec::Vec<( + ::core::primitive::u32, + runtime_types::polkadot_parachain_primitives::primitives::XcmpMessageFormat, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundChannelDetails { + pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, + pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, + pub signals_exist: ::core::primitive::bool, + pub first_index: ::core::primitive::u16, + pub last_index: ::core::primitive::u16, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OutboundState { + #[codec(index = 0)] + Ok, + #[codec(index = 1)] + Suspended, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueueConfigData { + pub suspend_threshold: ::core::primitive::u32, + pub drop_threshold: ::core::primitive::u32, + pub resume_threshold: ::core::primitive::u32, + pub threshold_weight: ::sp_weights::Weight, + pub weight_restrict_decay: ::sp_weights::Weight, + pub xcmp_max_individual_weight: ::sp_weights::Weight, + } + } + pub mod cumulus_primitives_core { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CollationInfo { + pub upward_messages: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub horizontal_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::OutboundHrmpMessage< + runtime_types::polkadot_parachain_primitives::primitives::Id, + >, + >, + pub new_validation_code: ::core::option::Option< + runtime_types::polkadot_parachain_primitives::primitives::ValidationCode, + >, + pub processed_downward_messages: ::core::primitive::u32, + pub hrmp_watermark: ::core::primitive::u32, + pub head_data: runtime_types::polkadot_parachain_primitives::primitives::HeadData, + } + } + pub mod cumulus_primitives_parachain_inherent { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MessageQueueChain(pub ::subxt::utils::H256); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ParachainInherentData { + pub validation_data: + runtime_types::polkadot_primitives::v6::PersistedValidationData< + ::subxt::utils::H256, + ::core::primitive::u32, + >, + pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, + pub downward_messages: ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundDownwardMessage< + ::core::primitive::u32, + >, + >, + pub horizontal_messages: ::subxt::utils::KeyedVec< + runtime_types::polkadot_parachain_primitives::primitives::Id, + ::std::vec::Vec< + runtime_types::polkadot_core_primitives::InboundHrmpMessage< + ::core::primitive::u32, + >, + >, + >, + } + } + pub mod finality_grandpa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Commit<_0, _1, _2, _3> { + pub target_hash: _0, + pub target_number: _1, + pub precommits: ::std::vec::Vec< + runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Precommit<_0, _1> { + pub target_hash: _0, + pub target_number: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct SignedPrecommit<_0, _1, _2, _3> { + pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, + pub signature: _2, + pub id: _3, + } + } + pub mod frame_support { + use super::runtime_types; + pub mod dispatch { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchClass { + #[codec(index = 0)] + Normal, + #[codec(index = 1)] + Operational, + #[codec(index = 2)] + Mandatory, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DispatchInfo { + pub weight: ::sp_weights::Weight, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub pays_fee: runtime_types::frame_support::dispatch::Pays, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Pays { + #[codec(index = 0)] + Yes, + #[codec(index = 1)] + No, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PerDispatchClass<_0> { + pub normal: _0, + pub operational: _0, + pub mandatory: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum RawOrigin<_0> { + #[codec(index = 0)] + Root, + #[codec(index = 1)] + Signed(_0), + #[codec(index = 2)] + None, + } + } + pub mod traits { + use super::runtime_types; + pub mod tokens { + use super::runtime_types; + pub mod misc { + use super::runtime_types; + #[derive( + :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, + )] + pub enum BalanceStatus { + #[codec(index = 0)] + Free, + #[codec(index = 1)] + Reserved, + } + } + } + } + } + pub mod frame_system { + use super::runtime_types; + pub mod extensions { + use super::runtime_types; + pub mod check_genesis { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckGenesis; + } + pub mod check_mortality { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckMortality(pub ::sp_runtime::generic::Era); + } + pub mod check_non_zero_sender { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonZeroSender; + } + pub mod check_nonce { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); + } + pub mod check_spec_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckSpecVersion; + } + pub mod check_tx_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckTxVersion; + } + pub mod check_weight { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckWeight; + } + } + pub mod limits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockLength { + pub max: runtime_types::frame_support::dispatch::PerDispatchClass< + ::core::primitive::u32, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BlockWeights { + pub base_block: ::sp_weights::Weight, + pub max_block: ::sp_weights::Weight, + pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< + runtime_types::frame_system::limits::WeightsPerClass, + >, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct WeightsPerClass { + pub base_extrinsic: ::sp_weights::Weight, + pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, + pub max_total: ::core::option::Option<::sp_weights::Weight>, + pub reserved: ::core::option::Option<::sp_weights::Weight>, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + remark { remark: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 1)] + set_heap_pages { pages: ::core::primitive::u64 }, + #[codec(index = 2)] + set_code { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 3)] + set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, + #[codec(index = 4)] + set_storage { + items: ::std::vec::Vec<( + ::std::vec::Vec<::core::primitive::u8>, + ::std::vec::Vec<::core::primitive::u8>, + )>, + }, + #[codec(index = 5)] + kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, + #[codec(index = 6)] + kill_prefix { + prefix: ::std::vec::Vec<::core::primitive::u8>, + subkeys: ::core::primitive::u32, + }, + #[codec(index = 7)] + remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidSpecName, + #[codec(index = 1)] + SpecVersionNeedsToIncrease, + #[codec(index = 2)] + FailedToExtractRuntimeVersion, + #[codec(index = 3)] + NonDefaultComposite, + #[codec(index = 4)] + NonZeroRefCount, + #[codec(index = 5)] + CallFiltered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + ExtrinsicSuccess { + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 1)] + ExtrinsicFailed { + dispatch_error: runtime_types::sp_runtime::DispatchError, + dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, + }, + #[codec(index = 2)] + CodeUpdated, + #[codec(index = 3)] + NewAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 4)] + KilledAccount { account: ::sp_core::crypto::AccountId32 }, + #[codec(index = 5)] + Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountInfo<_0, _1> { + pub nonce: _0, + pub consumers: ::core::primitive::u32, + pub providers: ::core::primitive::u32, + pub sufficients: ::core::primitive::u32, + pub data: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct EventRecord<_0, _1> { + pub phase: runtime_types::frame_system::Phase, + pub event: _0, + pub topics: ::std::vec::Vec<_1>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct LastRuntimeUpgradeInfo { + #[codec(compact)] + pub spec_version: ::core::primitive::u32, + pub spec_name: ::std::string::String, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Phase { + #[codec(index = 0)] + ApplyExtrinsic(::core::primitive::u32), + #[codec(index = 1)] + Finalization, + #[codec(index = 2)] + Initialization, + } + } + pub mod pallet_balances { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + transfer_allow_death { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 2)] + force_transfer { + source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 3)] + transfer_keep_alive { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + value: ::core::primitive::u128, + }, + #[codec(index = 4)] + transfer_all { + dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + keep_alive: ::core::primitive::bool, + }, + #[codec(index = 5)] + force_unreserve { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 8)] + force_set_balance { + who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, + #[codec(compact)] + new_free: ::core::primitive::u128, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + VestingBalance, + #[codec(index = 1)] + LiquidityRestrictions, + #[codec(index = 2)] + InsufficientBalance, + #[codec(index = 3)] + ExistentialDeposit, + #[codec(index = 4)] + Expendability, + #[codec(index = 5)] + ExistingVestingSchedule, + #[codec(index = 6)] + DeadAccount, + #[codec(index = 7)] + TooManyReserves, + #[codec(index = 8)] + TooManyHolds, + #[codec(index = 9)] + TooManyFreezes, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Endowed { + account: ::sp_core::crypto::AccountId32, + free_balance: ::core::primitive::u128, + }, + #[codec(index = 1)] + DustLost { + account: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 2)] + Transfer { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 3)] + BalanceSet { + who: ::sp_core::crypto::AccountId32, + free: ::core::primitive::u128, + }, + #[codec(index = 4)] + Reserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 5)] + Unreserved { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 6)] + ReserveRepatriated { + from: ::sp_core::crypto::AccountId32, + to: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + destination_status: + runtime_types::frame_support::traits::tokens::misc::BalanceStatus, + }, + #[codec(index = 7)] + Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 8)] + Withdraw { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 9)] + Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 10)] + Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 11)] + Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 12)] + Suspended { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 13)] + Restored { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 14)] + Upgraded { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 15)] + Issued { amount: ::core::primitive::u128 }, + #[codec(index = 16)] + Rescinded { amount: ::core::primitive::u128 }, + #[codec(index = 17)] + Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 18)] + Unlocked { + who: ::sp_core::crypto::AccountId32, + amount: ::core::primitive::u128, + }, + #[codec(index = 19)] + Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + #[codec(index = 20)] + Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AccountData<_0> { + pub free: _0, + pub reserved: _0, + pub frozen: _0, + pub flags: runtime_types::pallet_balances::types::ExtraFlags, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct BalanceLock<_0> { + pub id: [::core::primitive::u8; 8usize], + pub amount: _0, + pub reasons: runtime_types::pallet_balances::types::Reasons, + } + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct ExtraFlags(pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct IdAmount<_0, _1> { + pub id: _0, + pub amount: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Reasons { + #[codec(index = 0)] + Fee, + #[codec(index = 1)] + Misc, + #[codec(index = 2)] + All, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ReserveData<_0, _1> { + pub id: _0, + pub amount: _1, + } + } + } + pub mod pallet_bridge_grandpa { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_finality_proof { + finality_target: ::std::boxed::Box< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + justification: ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 1)] + initialize { + init_data: ::bp_header_chain::InitializationData< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + }, + #[codec(index = 2)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 3)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidJustification, + #[codec(index = 1)] + InvalidAuthoritySet, + #[codec(index = 2)] + OldHeader, + #[codec(index = 3)] + UnsupportedScheduledChange, + #[codec(index = 4)] + NotInitialized, + #[codec(index = 5)] + AlreadyInitialized, + #[codec(index = 6)] + TooManyAuthoritiesInSet, + #[codec(index = 7)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UpdatedBestFinalizedHeader { + number: ::core::primitive::u32, + hash: ::subxt::utils::H256, + grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< + ::bp_header_chain::justification::GrandpaJustification< + ::sp_runtime::generic::Header< + ::core::primitive::u32, + ::sp_runtime::traits::BlakeTwo256, + >, + >, + runtime_types::bp_header_chain::AuthoritySet, + >, + }, + } + } + pub mod storage_types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StoredAuthoritySet { + pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + runtime_types::sp_consensus_grandpa::app::Public, + ::core::primitive::u64, + )>, + pub set_id: ::core::primitive::u64, + } + } + } + pub mod pallet_bridge_messages { + use super::runtime_types; + pub mod outbound_lane { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ReceivalConfirmationError { + #[codec(index = 0)] + FailedToConfirmFutureMessages, + #[codec(index = 1)] + EmptyUnrewardedRelayerEntry, + #[codec(index = 2)] + NonConsecutiveUnrewardedRelayerEntries, + #[codec(index = 3)] + TryingToConfirmMoreMessagesThanExpected, + } + } + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } + } + } + pub mod pallet_bridge_parachains { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + submit_parachain_heads { + at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), + parachains: ::std::vec::Vec<( + ::bp_polkadot_core::parachains::ParaId, + ::subxt::utils::H256, + )>, + parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, + }, + #[codec(index = 1)] + set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, + #[codec(index = 2)] + set_operating_mode { + operating_mode: runtime_types::bp_runtime::BasicOperatingMode, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + UnknownRelayChainBlock, + #[codec(index = 1)] + InvalidRelayChainBlockNumber, + #[codec(index = 2)] + HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), + #[codec(index = 3)] + BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 1)] + MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, + #[codec(index = 2)] + IncorrectParachainHeadHash { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + actual_parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 3)] + RejectedObsoleteParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + #[codec(index = 4)] + RejectedLargeParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + parachain_head_size: ::core::primitive::u32, + }, + #[codec(index = 5)] + UpdatedParachainHead { + parachain: ::bp_polkadot_core::parachains::ParaId, + parachain_head_hash: ::subxt::utils::H256, + }, + } + } + } + pub mod pallet_bridge_relayers { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + claim_rewards { + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + }, + #[codec(index = 1)] + register { valid_till: ::core::primitive::u32 }, + #[codec(index = 2)] + deregister, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + NoRewardForRelayer, + #[codec(index = 1)] + FailedToPayReward, + #[codec(index = 2)] + InvalidRegistrationLease, + #[codec(index = 3)] + CannotReduceRegistrationLease, + #[codec(index = 4)] + FailedToReserve, + #[codec(index = 5)] + FailedToUnreserve, + #[codec(index = 6)] + NotRegistered, + #[codec(index = 7)] + RegistrationIsStillActive, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + RewardPaid { + relayer: ::sp_core::crypto::AccountId32, + rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, + reward: ::core::primitive::u128, + }, + #[codec(index = 1)] + RegistrationUpdated { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + #[codec(index = 2)] + Deregistered { relayer: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + SlashedAndDeregistered { + relayer: ::sp_core::crypto::AccountId32, + registration: runtime_types::bp_relayers::registration::Registration< + ::core::primitive::u32, + ::core::primitive::u128, + >, + }, + } + } + } + pub mod pallet_collator_selection { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, + #[codec(index = 1)] + set_desired_candidates { max: ::core::primitive::u32 }, + #[codec(index = 2)] + set_candidacy_bond { bond: ::core::primitive::u128 }, + #[codec(index = 3)] + register_as_candidate, + #[codec(index = 4)] + leave_intent, + #[codec(index = 5)] + add_invulnerable { who: ::sp_core::crypto::AccountId32 }, + #[codec(index = 6)] + remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CandidateInfo<_0, _1> { + pub who: _0, + pub deposit: _1, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCandidates, + #[codec(index = 1)] + TooFewEligibleCollators, + #[codec(index = 2)] + AlreadyCandidate, + #[codec(index = 3)] + NotCandidate, + #[codec(index = 4)] + TooManyInvulnerables, + #[codec(index = 5)] + AlreadyInvulnerable, + #[codec(index = 6)] + NotInvulnerable, + #[codec(index = 7)] + NoAssociatedValidatorId, + #[codec(index = 8)] + ValidatorNotRegistered, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewInvulnerables { + invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + }, + #[codec(index = 1)] + InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 2)] + InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 3)] + NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, + #[codec(index = 4)] + NewCandidacyBond { bond_amount: ::core::primitive::u128 }, + #[codec(index = 5)] + CandidateAdded { + account_id: ::sp_core::crypto::AccountId32, + deposit: ::core::primitive::u128, + }, + #[codec(index = 6)] + CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, + #[codec(index = 7)] + InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, + } + } + } + pub mod pallet_multisig { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + as_multi_threshold_1 { + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + call: ::std::boxed::Box< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 2)] + approve_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + maybe_timepoint: ::core::option::Option< + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + >, + call_hash: [::core::primitive::u8; 32usize], + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 3)] + cancel_as_multi { + threshold: ::core::primitive::u16, + other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + call_hash: [::core::primitive::u8; 32usize], + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + MinimumThreshold, + #[codec(index = 1)] + AlreadyApproved, + #[codec(index = 2)] + NoApprovalsNeeded, + #[codec(index = 3)] + TooFewSignatories, + #[codec(index = 4)] + TooManySignatories, + #[codec(index = 5)] + SignatoriesOutOfOrder, + #[codec(index = 6)] + SenderInSignatories, + #[codec(index = 7)] + NotFound, + #[codec(index = 8)] + NotOwner, + #[codec(index = 9)] + NoTimepoint, + #[codec(index = 10)] + WrongTimepoint, + #[codec(index = 11)] + UnexpectedTimepoint, + #[codec(index = 12)] + MaxWeightTooLow, + #[codec(index = 13)] + AlreadyStored, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewMultisig { + approving: ::sp_core::crypto::AccountId32, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 1)] + MultisigApproval { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + MultisigExecuted { + approving: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + #[codec(index = 3)] + MultisigCancelled { + cancelling: ::sp_core::crypto::AccountId32, + timepoint: + runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, + multisig: ::sp_core::crypto::AccountId32, + call_hash: [::core::primitive::u8; 32usize], + }, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Multisig<_0, _1, _2> { + pub when: runtime_types::pallet_multisig::Timepoint<_0>, + pub deposit: _1, + pub depositor: _2, + pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Timepoint<_0> { + pub height: _0, + pub index: ::core::primitive::u32, + } + } + pub mod pallet_session { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set_keys { + keys: runtime_types::bridge_hub_polkadot_runtime::SessionKeys, + proof: ::std::vec::Vec<::core::primitive::u8>, + }, + #[codec(index = 1)] + purge_keys, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + InvalidProof, + #[codec(index = 1)] + NoAssociatedValidatorId, + #[codec(index = 2)] + DuplicatedKey, + #[codec(index = 3)] + NoKeys, + #[codec(index = 4)] + NoAccount, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + NewSession { session_index: ::core::primitive::u32 }, + } + } + } + pub mod pallet_timestamp { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + set { + #[codec(compact)] + now: ::core::primitive::u64, + }, + } + } + } + pub mod pallet_transaction_payment { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + TransactionFeePaid { + who: ::sp_core::crypto::AccountId32, + actual_fee: ::core::primitive::u128, + tip: ::core::primitive::u128, + }, + } + } + pub mod types { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct FeeDetails<_0> { + pub inclusion_fee: ::core::option::Option< + runtime_types::pallet_transaction_payment::types::InclusionFee<_0>, + >, + pub tip: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InclusionFee<_0> { + pub base_fee: _0, + pub len_fee: _0, + pub adjusted_weight_fee: _0, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDispatchInfo<_0, _1> { + pub weight: _1, + pub class: runtime_types::frame_support::dispatch::DispatchClass, + pub partial_fee: _0, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Releases { + #[codec(index = 0)] + V1Ancient, + #[codec(index = 1)] + V2, + } + } + pub mod pallet_utility { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + batch { + calls: ::std::vec::Vec< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 1)] + as_derivative { + index: ::core::primitive::u16, + call: ::std::boxed::Box< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 2)] + batch_all { + calls: ::std::vec::Vec< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 3)] + dispatch_as { + as_origin: ::std::boxed::Box< + runtime_types::bridge_hub_polkadot_runtime::OriginCaller, + >, + call: ::std::boxed::Box< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 4)] + force_batch { + calls: ::std::vec::Vec< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + }, + #[codec(index = 5)] + with_weight { + call: ::std::boxed::Box< + runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, + >, + weight: ::sp_weights::Weight, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + TooManyCalls, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + BatchInterrupted { + index: ::core::primitive::u32, + error: runtime_types::sp_runtime::DispatchError, + }, + #[codec(index = 1)] + BatchCompleted, + #[codec(index = 2)] + BatchCompletedWithErrors, + #[codec(index = 3)] + ItemCompleted, + #[codec(index = 4)] + ItemFailed { error: runtime_types::sp_runtime::DispatchError }, + #[codec(index = 5)] + DispatchedAs { + result: + ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, + }, + } + } + } + pub mod pallet_xcm { + use super::runtime_types; + pub mod pallet { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Call { + #[codec(index = 0)] + send { + dest: ::std::boxed::Box, + message: ::std::boxed::Box, + }, + #[codec(index = 1)] + teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 2)] + reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + }, + #[codec(index = 3)] + execute { + message: ::std::boxed::Box, + max_weight: ::sp_weights::Weight, + }, + #[codec(index = 4)] + force_xcm_version { + location: ::std::boxed::Box< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + version: ::core::primitive::u32, + }, + #[codec(index = 5)] + force_default_xcm_version { + maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, + }, + #[codec(index = 6)] + force_subscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 7)] + force_unsubscribe_version_notify { + location: ::std::boxed::Box, + }, + #[codec(index = 8)] + limited_reserve_transfer_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 9)] + limited_teleport_assets { + dest: ::std::boxed::Box, + beneficiary: ::std::boxed::Box, + assets: ::std::boxed::Box, + fee_asset_item: ::core::primitive::u32, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 10)] + force_suspension { suspended: ::core::primitive::bool }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Unreachable, + #[codec(index = 1)] + SendFailure, + #[codec(index = 2)] + Filtered, + #[codec(index = 3)] + UnweighableMessage, + #[codec(index = 4)] + DestinationNotInvertible, + #[codec(index = 5)] + Empty, + #[codec(index = 6)] + CannotReanchor, + #[codec(index = 7)] + TooManyAssets, + #[codec(index = 8)] + InvalidOrigin, + #[codec(index = 9)] + BadVersion, + #[codec(index = 10)] + BadLocation, + #[codec(index = 11)] + NoSubscription, + #[codec(index = 12)] + AlreadySubscribed, + #[codec(index = 13)] + InvalidAsset, + #[codec(index = 14)] + LowBalance, + #[codec(index = 15)] + TooManyLocks, + #[codec(index = 16)] + AccountNotSovereign, + #[codec(index = 17)] + FeesNotMet, + #[codec(index = 18)] + LockNotFound, + #[codec(index = 19)] + InUse, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Event { + #[codec(index = 0)] + Attempted { outcome: runtime_types::xcm::v3::traits::Outcome }, + #[codec(index = 1)] + Sent { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + message: runtime_types::xcm::v3::Xcm, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + UnexpectedResponse { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 3)] + ResponseReady { + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + }, + #[codec(index = 4)] + Notified { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 5)] + NotifyOverweight { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + actual_weight: ::sp_weights::Weight, + max_budgeted_weight: ::sp_weights::Weight, + }, + #[codec(index = 6)] + NotifyDispatchError { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 7)] + NotifyDecodeFailed { + query_id: ::core::primitive::u64, + pallet_index: ::core::primitive::u8, + call_index: ::core::primitive::u8, + }, + #[codec(index = 8)] + InvalidResponder { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + expected_location: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 9)] + InvalidResponderVersion { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 10)] + ResponseTaken { query_id: ::core::primitive::u64 }, + #[codec(index = 11)] + AssetsTrapped { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + }, + #[codec(index = 12)] + VersionChangeNotified { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + result: ::core::primitive::u32, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 13)] + SupportedVersionChanged { + location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + version: ::core::primitive::u32, + }, + #[codec(index = 14)] + NotifyTargetSendFail { + location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + error: runtime_types::xcm::v3::traits::Error, + }, + #[codec(index = 15)] + NotifyTargetMigrationFail { + location: runtime_types::xcm::VersionedMultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 16)] + InvalidQuerierVersion { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + }, + #[codec(index = 17)] + InvalidQuerier { + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + query_id: ::core::primitive::u64, + expected_querier: + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + maybe_actual_querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 18)] + VersionNotifyStarted { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 19)] + VersionNotifyRequested { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 20)] + VersionNotifyUnrequested { + destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + cost: runtime_types::xcm::v3::multiasset::MultiAssets, + message_id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 21)] + FeesPaid { + paying: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + fees: runtime_types::xcm::v3::multiasset::MultiAssets, + }, + #[codec(index = 22)] + AssetsClaimed { + hash: ::subxt::utils::H256, + origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + assets: runtime_types::xcm::VersionedMultiAssets, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Origin { + #[codec(index = 0)] + Xcm(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Response(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum QueryStatus<_0> { + #[codec(index = 0)] + Pending { + responder: runtime_types::xcm::VersionedMultiLocation, + maybe_match_querier: + ::core::option::Option, + maybe_notify: + ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, + timeout: _0, + }, + #[codec(index = 1)] + VersionNotifier { + origin: runtime_types::xcm::VersionedMultiLocation, + is_active: ::core::primitive::bool, + }, + #[codec(index = 2)] + Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RemoteLockedFungibleRecord<_0> { + pub amount: ::core::primitive::u128, + pub owner: runtime_types::xcm::VersionedMultiLocation, + pub locker: runtime_types::xcm::VersionedMultiLocation, + pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( + _0, + ::core::primitive::u128, + )>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionMigrationStage { + #[codec(index = 0)] + MigrateSupportedVersion, + #[codec(index = 1)] + MigrateVersionNotifiers, + #[codec(index = 2)] + NotifyCurrentTargets( + ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, + ), + #[codec(index = 3)] + MigrateAndNotifyOldTargets, + } + } + } + pub mod polkadot_core_primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundDownwardMessage<_0> { + pub sent_at: _0, + pub msg: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InboundHrmpMessage<_0> { + pub sent_at: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OutboundHrmpMessage<_0> { + pub recipient: _0, + pub data: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod polkadot_parachain_primitives { + use super::runtime_types; + pub mod primitives { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Id(pub ::core::primitive::u32); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum XcmpMessageFormat { + #[codec(index = 0)] + ConcatenatedVersionedXcm, + #[codec(index = 1)] + ConcatenatedEncodedBlob, + #[codec(index = 2)] + Signals, + } + } + } + pub mod polkadot_primitives { + use super::runtime_types; + pub mod v6 { + use super::runtime_types; + pub mod async_backing { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AsyncBackingParams { + pub max_candidate_depth: ::core::primitive::u32, + pub allowed_ancestry_len: ::core::primitive::u32, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHostConfiguration { + pub max_code_size: ::core::primitive::u32, + pub max_head_data_size: ::core::primitive::u32, + pub max_upward_queue_count: ::core::primitive::u32, + pub max_upward_queue_size: ::core::primitive::u32, + pub max_upward_message_size: ::core::primitive::u32, + pub max_upward_message_num_per_candidate: ::core::primitive::u32, + pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, + pub validation_upgrade_cooldown: ::core::primitive::u32, + pub validation_upgrade_delay: ::core::primitive::u32, + pub async_backing_params: + runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct AbridgedHrmpChannel { + pub max_capacity: ::core::primitive::u32, + pub max_total_size: ::core::primitive::u32, + pub max_message_size: ::core::primitive::u32, + pub msg_count: ::core::primitive::u32, + pub total_size: ::core::primitive::u32, + pub mqc_head: ::core::option::Option<::subxt::utils::H256>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PersistedValidationData<_0, _1> { + pub parent_head: + runtime_types::polkadot_parachain_primitives::primitives::HeadData, + pub relay_parent_number: _1, + pub relay_parent_storage_root: _0, + pub max_pov_size: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeGoAhead { + #[codec(index = 0)] + Abort, + #[codec(index = 1)] + GoAhead, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UpgradeRestriction { + #[codec(index = 0)] + Present, + } + } + } + pub mod sp_arithmetic { + use super::runtime_types; + pub mod fixed_point { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct FixedU128(pub ::core::primitive::u128); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum ArithmeticError { + #[codec(index = 0)] + Underflow, + #[codec(index = 1)] + Overflow, + #[codec(index = 2)] + DivisionByZero, + } + } + pub mod sp_consensus_aura { + use super::runtime_types; + pub mod sr25519 { + use super::runtime_types; + pub mod app_sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::sr25519::Public); + } + } + } + pub mod sp_consensus_grandpa { + use super::runtime_types; + pub mod app { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub runtime_types::sp_core::ed25519::Public); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); + } + } + pub mod sp_consensus_slots { + use super::runtime_types; + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct Slot(pub ::core::primitive::u64); + #[derive( + :: codec :: Decode, + :: codec :: Encode, + :: subxt :: ext :: codec :: CompactAs, + Clone, + Debug, + PartialEq, + )] + pub struct SlotDuration(pub ::core::primitive::u64); + } + pub mod sp_core { + use super::runtime_types; + pub mod crypto { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); + } + pub mod ecdsa { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 65usize]); + } + pub mod ed25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + pub mod sr25519 { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Public(pub [::core::primitive::u8; 32usize]); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Signature(pub [::core::primitive::u8; 64usize]); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct OpaqueMetadata(pub ::std::vec::Vec<::core::primitive::u8>); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Void {} + } + pub mod sp_inherents { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct CheckInherentsResult { + pub okay: ::core::primitive::bool, + pub fatal_error: ::core::primitive::bool, + pub errors: runtime_types::sp_inherents::InherentData, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct InherentData { + pub data: ::subxt::utils::KeyedVec< + [::core::primitive::u8; 8usize], + ::std::vec::Vec<::core::primitive::u8>, + >, + } + } + pub mod sp_runtime { + use super::runtime_types; + pub mod generic { + use super::runtime_types; + pub mod block { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Block<_0, _1> { + pub header: _0, + pub extrinsics: ::std::vec::Vec<_1>, + } + } + pub mod digest { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DigestItem { + #[codec(index = 6)] + PreRuntime( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 4)] + Consensus( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 5)] + Seal( + [::core::primitive::u8; 4usize], + ::std::vec::Vec<::core::primitive::u8>, + ), + #[codec(index = 0)] + Other(::std::vec::Vec<::core::primitive::u8>), + #[codec(index = 8)] + RuntimeEnvironmentUpdated, + } + } + } + pub mod transaction_validity { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum InvalidTransaction { + #[codec(index = 0)] + Call, + #[codec(index = 1)] + Payment, + #[codec(index = 2)] + Future, + #[codec(index = 3)] + Stale, + #[codec(index = 4)] + BadProof, + #[codec(index = 5)] + AncientBirthBlock, + #[codec(index = 6)] + ExhaustsResources, + #[codec(index = 7)] + Custom(::core::primitive::u8), + #[codec(index = 8)] + BadMandatory, + #[codec(index = 9)] + MandatoryValidation, + #[codec(index = 10)] + BadSigner, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionSource { + #[codec(index = 0)] + InBlock, + #[codec(index = 1)] + Local, + #[codec(index = 2)] + External, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionValidityError { + #[codec(index = 0)] + Invalid(runtime_types::sp_runtime::transaction_validity::InvalidTransaction), + #[codec(index = 1)] + Unknown(runtime_types::sp_runtime::transaction_validity::UnknownTransaction), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum UnknownTransaction { + #[codec(index = 0)] + CannotLookup, + #[codec(index = 1)] + NoUnsignedValidator, + #[codec(index = 2)] + Custom(::core::primitive::u8), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ValidTransaction { + pub priority: ::core::primitive::u64, + pub requires: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub provides: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + pub longevity: ::core::primitive::u64, + pub propagate: ::core::primitive::bool, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum DispatchError { + #[codec(index = 0)] + Other, + #[codec(index = 1)] + CannotLookup, + #[codec(index = 2)] + BadOrigin, + #[codec(index = 3)] + Module(runtime_types::sp_runtime::ModuleError), + #[codec(index = 4)] + ConsumerRemaining, + #[codec(index = 5)] + NoProviders, + #[codec(index = 6)] + TooManyConsumers, + #[codec(index = 7)] + Token(runtime_types::sp_runtime::TokenError), + #[codec(index = 8)] + Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), + #[codec(index = 9)] + Transactional(runtime_types::sp_runtime::TransactionalError), + #[codec(index = 10)] + Exhausted, + #[codec(index = 11)] + Corruption, + #[codec(index = 12)] + Unavailable, + #[codec(index = 13)] + RootNotAllowed, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct ModuleError { + pub index: ::core::primitive::u8, + pub error: [::core::primitive::u8; 4usize], + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiSignature { + #[codec(index = 0)] + Ed25519(runtime_types::sp_core::ed25519::Signature), + #[codec(index = 1)] + Sr25519(runtime_types::sp_core::sr25519::Signature), + #[codec(index = 2)] + Ecdsa(runtime_types::sp_core::ecdsa::Signature), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TokenError { + #[codec(index = 0)] + FundsUnavailable, + #[codec(index = 1)] + OnlyProvider, + #[codec(index = 2)] + BelowMinimum, + #[codec(index = 3)] + CannotCreate, + #[codec(index = 4)] + UnknownAsset, + #[codec(index = 5)] + Frozen, + #[codec(index = 6)] + Unsupported, + #[codec(index = 7)] + CannotCreateHold, + #[codec(index = 8)] + NotExpendable, + #[codec(index = 9)] + Blocked, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum TransactionalError { + #[codec(index = 0)] + LimitReached, + #[codec(index = 1)] + NoLayer, + } + } + pub mod sp_trie { + use super::runtime_types; + pub mod storage_proof { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct StorageProof { + pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, + } + } + } + pub mod sp_version { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeVersion { + pub spec_name: ::std::string::String, + pub impl_name: ::std::string::String, + pub authoring_version: ::core::primitive::u32, + pub spec_version: ::core::primitive::u32, + pub impl_version: ::core::primitive::u32, + pub apis: + ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, + pub transaction_version: ::core::primitive::u32, + pub state_version: ::core::primitive::u8, + } + } + pub mod sp_weights { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct RuntimeDbWeight { + pub read: ::core::primitive::u64, + pub write: ::core::primitive::u64, + } + } + pub mod staging_xcm { + use super::runtime_types; + pub mod v3 { + use super::runtime_types; + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v3::junctions::Junctions, + } + } + } + } + pub mod xcm { + use super::runtime_types; + pub mod double_encoded { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct DoubleEncoded2 { + pub encoded: ::std::vec::Vec<::core::primitive::u8>, + } + } + pub mod v2 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: runtime_types::xcm::v2::NetworkId, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: runtime_types::xcm::v2::NetworkId, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: runtime_types::xcm::v2::NetworkId, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v2::BodyId, + part: runtime_types::xcm::v2::BodyPart, + }, + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + #[codec(index = 6)] + Blob(::std::vec::Vec<::core::primitive::u8>), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v2::multiasset::AssetId, + pub fun: runtime_types::xcm::v2::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v2::multiasset::AssetId, + fun: runtime_types::xcm::v2::multiasset::WildFungibility, + }, + } + } + pub mod multilocation { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v2::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + runtime_types::xcm::v2::junction::Junction, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiLocation { + pub parents: ::core::primitive::u8, + pub interior: runtime_types::xcm::v2::multilocation::Junctions, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + MultiLocationFull, + #[codec(index = 5)] + MultiLocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + UnhandledXcmVersion, + #[codec(index = 23)] + WeightLimitReached(::core::primitive::u64), + #[codec(index = 24)] + Barrier, + #[codec(index = 25)] + WeightNotComputable, + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v2::Response, + #[codec(compact)] + max_weight: ::core::primitive::u64, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_type: runtime_types::xcm::v2::OriginKind, + #[codec(compact)] + require_weight_at_most: ::core::primitive::u64, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), + #[codec(index = 12)] + ReportError { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_assets: ::core::primitive::u32, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + receive: runtime_types::xcm::v2::multiasset::MultiAssets, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + reserve: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + xcm: runtime_types::xcm::v2::Xcm, + }, + #[codec(index = 18)] + QueryHolding { + #[codec(compact)] + query_id: ::core::primitive::u64, + dest: runtime_types::xcm::v2::multilocation::MultiLocation, + assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v2::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v2::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v2::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v2::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v2::multiasset::MultiAssets, + ticket: runtime_types::xcm::v2::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + #[codec(compact)] + max_response_weight: ::core::primitive::u64, + }, + #[codec(index = 27)] + UnsubscribeVersion, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + Any, + #[codec(index = 1)] + Named( + runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum OriginKind { + #[codec(index = 0)] + Native, + #[codec(index = 1)] + SovereignAccount, + #[codec(index = 2)] + Superuser, + #[codec(index = 3)] + Xcm, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v2::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(#[codec(compact)] ::core::primitive::u64), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + pub mod v3 { + use super::runtime_types; + pub mod junction { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyId { + #[codec(index = 0)] + Unit, + #[codec(index = 1)] + Moniker([::core::primitive::u8; 4usize]), + #[codec(index = 2)] + Index(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + Executive, + #[codec(index = 4)] + Technical, + #[codec(index = 5)] + Legislative, + #[codec(index = 6)] + Judicial, + #[codec(index = 7)] + Defense, + #[codec(index = 8)] + Administration, + #[codec(index = 9)] + Treasury, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum BodyPart { + #[codec(index = 0)] + Voice, + #[codec(index = 1)] + Members { + #[codec(compact)] + count: ::core::primitive::u32, + }, + #[codec(index = 2)] + Fraction { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 3)] + AtLeastProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + #[codec(index = 4)] + MoreThanProportion { + #[codec(compact)] + nom: ::core::primitive::u32, + #[codec(compact)] + denom: ::core::primitive::u32, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junction { + #[codec(index = 0)] + Parachain(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 1)] + AccountId32 { + network: + ::core::option::Option, + id: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + AccountIndex64 { + network: + ::core::option::Option, + #[codec(compact)] + index: ::core::primitive::u64, + }, + #[codec(index = 3)] + AccountKey20 { + network: + ::core::option::Option, + key: [::core::primitive::u8; 20usize], + }, + #[codec(index = 4)] + PalletInstance(::core::primitive::u8), + #[codec(index = 5)] + GeneralIndex(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 6)] + GeneralKey { + length: ::core::primitive::u8, + data: [::core::primitive::u8; 32usize], + }, + #[codec(index = 7)] + OnlyChild, + #[codec(index = 8)] + Plurality { + id: runtime_types::xcm::v3::junction::BodyId, + part: runtime_types::xcm::v3::junction::BodyPart, + }, + #[codec(index = 9)] + GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum NetworkId { + #[codec(index = 0)] + ByGenesis([::core::primitive::u8; 32usize]), + #[codec(index = 1)] + ByFork { + block_number: ::core::primitive::u64, + block_hash: [::core::primitive::u8; 32usize], + }, + #[codec(index = 2)] + Polkadot, + #[codec(index = 3)] + Kusama, + #[codec(index = 4)] + Westend, + #[codec(index = 5)] + Rococo, + #[codec(index = 6)] + Wococo, + #[codec(index = 7)] + Ethereum { + #[codec(compact)] + chain_id: ::core::primitive::u64, + }, + #[codec(index = 8)] + BitcoinCore, + #[codec(index = 9)] + BitcoinCash, + } + } + pub mod junctions { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Junctions { + #[codec(index = 0)] + Here, + #[codec(index = 1)] + X1(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 2)] + X2( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 3)] + X3( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 4)] + X4( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 5)] + X5( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 6)] + X6( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 7)] + X7( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + #[codec(index = 8)] + X8( + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + runtime_types::xcm::v3::junction::Junction, + ), + } + } + pub mod multiasset { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetId { + #[codec(index = 0)] + Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 1)] + Abstract([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum AssetInstance { + #[codec(index = 0)] + Undefined, + #[codec(index = 1)] + Index(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 2)] + Array4([::core::primitive::u8; 4usize]), + #[codec(index = 3)] + Array8([::core::primitive::u8; 8usize]), + #[codec(index = 4)] + Array16([::core::primitive::u8; 16usize]), + #[codec(index = 5)] + Array32([::core::primitive::u8; 32usize]), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Fungibility { + #[codec(index = 0)] + Fungible(#[codec(compact)] ::core::primitive::u128), + #[codec(index = 1)] + NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAsset { + pub id: runtime_types::xcm::v3::multiasset::AssetId, + pub fun: runtime_types::xcm::v3::multiasset::Fungibility, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MultiAssetFilter { + #[codec(index = 0)] + Definite(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct MultiAssets( + pub ::std::vec::Vec, + ); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildFungibility { + #[codec(index = 0)] + Fungible, + #[codec(index = 1)] + NonFungible, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WildMultiAsset { + #[codec(index = 0)] + All, + #[codec(index = 1)] + AllOf { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + }, + #[codec(index = 2)] + AllCounted(#[codec(compact)] ::core::primitive::u32), + #[codec(index = 3)] + AllOfCounted { + id: runtime_types::xcm::v3::multiasset::AssetId, + fun: runtime_types::xcm::v3::multiasset::WildFungibility, + #[codec(compact)] + count: ::core::primitive::u32, + }, + } + } + pub mod traits { + use super::runtime_types; + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Error { + #[codec(index = 0)] + Overflow, + #[codec(index = 1)] + Unimplemented, + #[codec(index = 2)] + UntrustedReserveLocation, + #[codec(index = 3)] + UntrustedTeleportLocation, + #[codec(index = 4)] + LocationFull, + #[codec(index = 5)] + LocationNotInvertible, + #[codec(index = 6)] + BadOrigin, + #[codec(index = 7)] + InvalidLocation, + #[codec(index = 8)] + AssetNotFound, + #[codec(index = 9)] + FailedToTransactAsset, + #[codec(index = 10)] + NotWithdrawable, + #[codec(index = 11)] + LocationCannotHold, + #[codec(index = 12)] + ExceedsMaxMessageSize, + #[codec(index = 13)] + DestinationUnsupported, + #[codec(index = 14)] + Transport, + #[codec(index = 15)] + Unroutable, + #[codec(index = 16)] + UnknownClaim, + #[codec(index = 17)] + FailedToDecode, + #[codec(index = 18)] + MaxWeightInvalid, + #[codec(index = 19)] + NotHoldingFees, + #[codec(index = 20)] + TooExpensive, + #[codec(index = 21)] + Trap(::core::primitive::u64), + #[codec(index = 22)] + ExpectationFalse, + #[codec(index = 23)] + PalletNotFound, + #[codec(index = 24)] + NameMismatch, + #[codec(index = 25)] + VersionIncompatible, + #[codec(index = 26)] + HoldingWouldOverflow, + #[codec(index = 27)] + ExportError, + #[codec(index = 28)] + ReanchorFailed, + #[codec(index = 29)] + NoDeal, + #[codec(index = 30)] + FeesNotMet, + #[codec(index = 31)] + LockError, + #[codec(index = 32)] + NoPermission, + #[codec(index = 33)] + Unanchored, + #[codec(index = 34)] + NotDepositable, + #[codec(index = 35)] + UnhandledXcmVersion, + #[codec(index = 36)] + WeightLimitReached(::sp_weights::Weight), + #[codec(index = 37)] + Barrier, + #[codec(index = 38)] + WeightNotComputable, + #[codec(index = 39)] + ExceedsStackLimit, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Outcome { + #[codec(index = 0)] + Complete(::sp_weights::Weight), + #[codec(index = 1)] + Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), + #[codec(index = 2)] + Error(runtime_types::xcm::v3::traits::Error), + } + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Instruction2 { + #[codec(index = 0)] + WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 1)] + ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 3)] + QueryResponse { + #[codec(compact)] + query_id: ::core::primitive::u64, + response: runtime_types::xcm::v3::Response, + max_weight: ::sp_weights::Weight, + querier: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + #[codec(index = 4)] + TransferAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 5)] + TransferReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 6)] + Transact { + origin_kind: runtime_types::xcm::v2::OriginKind, + require_weight_at_most: ::sp_weights::Weight, + call: runtime_types::xcm::double_encoded::DoubleEncoded2, + }, + #[codec(index = 7)] + HrmpNewChannelOpenRequest { + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + max_message_size: ::core::primitive::u32, + #[codec(compact)] + max_capacity: ::core::primitive::u32, + }, + #[codec(index = 8)] + HrmpChannelAccepted { + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 9)] + HrmpChannelClosing { + #[codec(compact)] + initiator: ::core::primitive::u32, + #[codec(compact)] + sender: ::core::primitive::u32, + #[codec(compact)] + recipient: ::core::primitive::u32, + }, + #[codec(index = 10)] + ClearOrigin, + #[codec(index = 11)] + DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), + #[codec(index = 12)] + ReportError(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 13)] + DepositAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 14)] + DepositReserveAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 15)] + ExchangeAsset { + give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + want: runtime_types::xcm::v3::multiasset::MultiAssets, + maximal: ::core::primitive::bool, + }, + #[codec(index = 16)] + InitiateReserveWithdraw { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 17)] + InitiateTeleport { + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 18)] + ReportHolding { + response_info: runtime_types::xcm::v3::QueryResponseInfo, + assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, + }, + #[codec(index = 19)] + BuyExecution { + fees: runtime_types::xcm::v3::multiasset::MultiAsset, + weight_limit: runtime_types::xcm::v3::WeightLimit, + }, + #[codec(index = 20)] + RefundSurplus, + #[codec(index = 21)] + SetErrorHandler(runtime_types::xcm::v3::Xcm2), + #[codec(index = 22)] + SetAppendix(runtime_types::xcm::v3::Xcm2), + #[codec(index = 23)] + ClearError, + #[codec(index = 24)] + ClaimAsset { + assets: runtime_types::xcm::v3::multiasset::MultiAssets, + ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 25)] + Trap(#[codec(compact)] ::core::primitive::u64), + #[codec(index = 26)] + SubscribeVersion { + #[codec(compact)] + query_id: ::core::primitive::u64, + max_response_weight: ::sp_weights::Weight, + }, + #[codec(index = 27)] + UnsubscribeVersion, + #[codec(index = 28)] + BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 29)] + ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 30)] + ExpectOrigin( + ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + ), + #[codec(index = 31)] + ExpectError( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 32)] + ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), + #[codec(index = 33)] + QueryPallet { + module_name: ::std::vec::Vec<::core::primitive::u8>, + response_info: runtime_types::xcm::v3::QueryResponseInfo, + }, + #[codec(index = 34)] + ExpectPallet { + #[codec(compact)] + index: ::core::primitive::u32, + name: ::std::vec::Vec<::core::primitive::u8>, + module_name: ::std::vec::Vec<::core::primitive::u8>, + #[codec(compact)] + crate_major: ::core::primitive::u32, + #[codec(compact)] + min_crate_minor: ::core::primitive::u32, + }, + #[codec(index = 35)] + ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), + #[codec(index = 36)] + ClearTransactStatus, + #[codec(index = 37)] + UniversalOrigin(runtime_types::xcm::v3::junction::Junction), + #[codec(index = 38)] + ExportMessage { + network: runtime_types::xcm::v3::junction::NetworkId, + destination: runtime_types::xcm::v3::junctions::Junctions, + xcm: runtime_types::xcm::v3::Xcm, + }, + #[codec(index = 39)] + LockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 40)] + UnlockAsset { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 41)] + NoteUnlockable { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 42)] + RequestUnlock { + asset: runtime_types::xcm::v3::multiasset::MultiAsset, + locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + }, + #[codec(index = 43)] + SetFeesMode { jit_withdraw: ::core::primitive::bool }, + #[codec(index = 44)] + SetTopic([::core::primitive::u8; 32usize]), + #[codec(index = 45)] + ClearTopic, + #[codec(index = 46)] + AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + #[codec(index = 47)] + UnpaidExecution { + weight_limit: runtime_types::xcm::v3::WeightLimit, + check_origin: ::core::option::Option< + runtime_types::staging_xcm::v3::multilocation::MultiLocation, + >, + }, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum MaybeErrorCode { + #[codec(index = 0)] + Success, + #[codec(index = 1)] + Error( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + #[codec(index = 2)] + TruncatedError( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + ), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct PalletInfo { + #[codec(compact)] + pub index: ::core::primitive::u32, + pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< + ::core::primitive::u8, + >, + #[codec(compact)] + pub major: ::core::primitive::u32, + #[codec(compact)] + pub minor: ::core::primitive::u32, + #[codec(compact)] + pub patch: ::core::primitive::u32, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct QueryResponseInfo { + pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, + #[codec(compact)] + pub query_id: ::core::primitive::u64, + pub max_weight: ::sp_weights::Weight, + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum Response { + #[codec(index = 0)] + Null, + #[codec(index = 1)] + Assets(runtime_types::xcm::v3::multiasset::MultiAssets), + #[codec(index = 2)] + ExecutionResult( + ::core::option::Option<( + ::core::primitive::u32, + runtime_types::xcm::v3::traits::Error, + )>, + ), + #[codec(index = 3)] + Version(::core::primitive::u32), + #[codec(index = 4)] + PalletsInfo( + runtime_types::bounded_collections::bounded_vec::BoundedVec< + runtime_types::xcm::v3::PalletInfo, + >, + ), + #[codec(index = 5)] + DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum WeightLimit { + #[codec(index = 0)] + Unlimited, + #[codec(index = 1)] + Limited(::sp_weights::Weight), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm(pub ::std::vec::Vec); + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub struct Xcm2(pub ::std::vec::Vec); + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedAssetId { + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::AssetId), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiAssets { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multiasset::MultiAssets), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::multiasset::MultiAssets), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedMultiLocation { + #[codec(index = 1)] + V2(runtime_types::xcm::v2::multilocation::MultiLocation), + #[codec(index = 3)] + V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedResponse { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Response), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Response), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm), + } + #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] + pub enum VersionedXcm2 { + #[codec(index = 2)] + V2(runtime_types::xcm::v2::Xcm2), + #[codec(index = 3)] + V3(runtime_types::xcm::v3::Xcm2), + } + } + } +} diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index 00006da303008..7bcf189e10965 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -16,21 +16,32 @@ //! Types used to connect to the BridgeHub-Polkadot-Substrate parachain. -use bp_bridge_hub_polkadot::AVERAGE_BLOCK_INTERVAL; +pub mod codegen_runtime; + +use bp_bridge_hub_polkadot::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; use std::time::Duration; -/// Re-export runtime wrapper -pub mod runtime_wrapper; -pub use runtime_wrapper as runtime; +pub use codegen_runtime::api::runtime_types; + +pub type RuntimeCall = runtime_types::bridge_hub_polkadot_runtime::RuntimeCall; +// TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - regenerate when ready +pub type BridgePolkadotBulletinMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +pub type BridgeKusamaMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; +// TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - regenerate when ready +pub type BridgePolkadotBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeKusamaGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; +pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; +type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; +type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Polkadot chain definition #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -47,7 +58,7 @@ impl Chain for BridgeHubPolkadot { const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; type SignedBlock = bp_bridge_hub_polkadot::SignedBlock; - type Call = runtime::Call; + type Call = RuntimeCall; } impl ChainWithBalances for BridgeHubPolkadot { @@ -56,13 +67,22 @@ impl ChainWithBalances for BridgeHubPolkadot { } } +impl From> for RuntimeCall { + fn from(value: MockUtilityCall) -> RuntimeCall { + match value { + MockUtilityCall::batch_all(calls) => + RuntimeCall::Utility(UtilityCall::batch_all { calls }), + } + } +} + impl ChainWithUtilityPallet for BridgeHubPolkadot { - type UtilityPallet = MockedRuntimeUtilityPallet; + type UtilityPallet = MockedRuntimeUtilityPallet; } impl ChainWithTransactions for BridgeHubPolkadot { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = runtime::UncheckedExtrinsic; + type SignedTransaction = UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -70,7 +90,7 @@ impl ChainWithTransactions for BridgeHubPolkadot { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - runtime::SignedExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -85,7 +105,7 @@ impl ChainWithTransactions for BridgeHubPolkadot { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(runtime::UncheckedExtrinsic::new_signed( + Ok(UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -127,10 +147,12 @@ mod tests { use super::*; use relay_substrate_client::TransactionEra; + type SystemCall = runtime_types::frame_system::pallet::Call; + #[test] fn parse_transaction_works() { let unsigned = UnsignedTransaction { - call: runtime::Call::System(runtime::SystemCall::remark(b"Hello world!".to_vec())) + call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) .into(), nonce: 777, tip: 888, From 7bf580dec9e8bee8f12cd77457fa91c5c19faa91 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 5 Mar 2024 00:27:40 +0300 Subject: [PATCH 1188/1210] Document: how to make relayer releases (#2860) * RELEASE.md * updated running-relayer.md --- docs/running-relayer.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/running-relayer.md b/docs/running-relayer.md index cda127cf0a8a5..710810a476e4d 100644 --- a/docs/running-relayer.md +++ b/docs/running-relayer.md @@ -247,15 +247,14 @@ need to set value of the `bridgedChainId` to `bhks`. ### Starting your Rococo <> Westend Relayer -We are using the following docker image to run our own Rococo <> Westend relayer: - -[paritytech/bridges-common-relay:v2024-02-16-rococo-westend-relayer](https://hub.docker.com/layers/paritytech/bridges-common-relay/v2024-02-16-rococo-westend-relayer/images/sha256-5ba4260d6bc2ac9e97c2e05d875f6dc44ee9265011311f268b66b8a5a672ada3?context=explore) - -You can grab the sources and build it manually: - -[v2024-02-16-rococo-westend-relayer](https://github.com/paritytech/parity-bridges-common/releases/tag/v2024-02-16-rococo-westend-relayer) - -Once you have the docker, update variables and run the following script: +You may find the relayer image reference in the +[Releases](https://github.com/paritytech/parity-bridges-common/releases) +of this repository. Make sure to check supported (bundled) versions +of release there. For Rococo <> Westend bridge, normally you may use the +latest published release. The release notes always contain the docker +image reference and source files, required to build relayer manually. + +Once you have the docker image, update variables and run the following script: ```sh export DOCKER_IMAGE= From b01a08391a929fda891e9919de936108aed58b35 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 5 Mar 2024 11:15:04 +0300 Subject: [PATCH 1189/1210] Prepare P<> K relay release: 1.2.0 (#2863) * cargo update -p mio * bump relayer version: v1.2.0 * Cargo.lock --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index f4cd80696d106..c5a7d118e28ad 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-relay" -version = "1.0.1" +version = "1.2.0" authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" From 9b26eb4b290b227dda54a801464f5aceaeff82cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 03:01:59 +0000 Subject: [PATCH 1190/1210] Bump env_logger from 0.11.2 to 0.11.3 Bumps [env_logger](https://github.com/rust-cli/env_logger) from 0.11.2 to 0.11.3. - [Release notes](https://github.com/rust-cli/env_logger/releases) - [Changelog](https://github.com/rust-cli/env_logger/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-cli/env_logger/compare/v0.11.2...v0.11.3) --- updated-dependencies: - dependency-name: env_logger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/utils/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index b41cd7e84a194..ae406933288e3 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -15,7 +15,7 @@ async-std = "1.6.5" async-trait = "0.1" backoff = "0.4" isahc = "1.2" -env_logger = "0.11.2" +env_logger = "0.11.3" futures = "0.3.30" jsonpath_lib = "0.3" log = "0.4.21" From 734f6058bf39530babd04c30538608e00ad06215 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 03:02:20 +0000 Subject: [PATCH 1191/1210] Bump strum from 0.26.1 to 0.26.2 Bumps [strum](https://github.com/Peternator7/strum) from 0.26.1 to 0.26.2. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index c5a7d118e28ad..1bcb410ddfc4e 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -23,7 +23,7 @@ rbtag = "0.3" structopt = "0.3" signal-hook = "0.3.15" signal-hook-async-std = "0.2.2" -strum = { version = "0.26.1", features = ["derive"] } +strum = { version = "0.26.2", features = ["derive"] } # Bridge dependencies bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } From da6c63b8a72a75836056e3e29dd00f52cfbc6f03 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 12 Mar 2024 14:53:52 +0300 Subject: [PATCH 1192/1210] backport changes from polkadot-sdk (#2872) --- bin/runtime-common/Cargo.toml | 3 +- bin/runtime-common/src/lib.rs | 72 ++++---- bin/runtime-common/src/mock.rs | 2 +- bin/runtime-common/src/priority_calculator.rs | 11 +- .../src/refund_relayer_extension.rs | 154 ++++++++++++------ modules/beefy/Cargo.toml | 4 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- modules/xcm-bridge-hub/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- .../chain-bridge-hub-cumulus/src/lib.rs | 4 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 2 +- primitives/chain-kusama/src/lib.rs | 4 +- primitives/chain-polkadot-bulletin/src/lib.rs | 51 +++--- primitives/chain-polkadot/src/lib.rs | 4 +- primitives/chain-rococo/src/lib.rs | 4 +- primitives/chain-westend/src/lib.rs | 4 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/polkadot-core/src/lib.rs | 37 +++-- primitives/runtime/Cargo.toml | 4 +- primitives/runtime/src/chain.rs | 11 ++ primitives/runtime/src/extensions.rs | 135 +++++++-------- primitives/test-utils/src/lib.rs | 2 +- relays/bin-substrate/Cargo.toml | 2 +- .../src/bridges/rococo_bulletin/mod.rs | 25 --- .../src/codegen_runtime.rs | 2 +- relays/client-bridge-hub-kusama/src/lib.rs | 58 +------ .../src/runtime_wrapper.rs | 4 +- .../src/codegen_runtime.rs | 2 +- relays/client-bridge-hub-polkadot/src/lib.rs | 58 +------ .../src/runtime_wrapper.rs | 4 +- .../src/codegen_runtime.rs | 2 +- relays/client-bridge-hub-rococo/src/lib.rs | 58 +------ .../src/codegen_runtime.rs | 2 +- relays/client-bridge-hub-westend/src/lib.rs | 58 +------ relays/client-kusama/src/lib.rs | 22 +-- relays/client-polkadot-bulletin/src/lib.rs | 24 +-- relays/client-polkadot/src/lib.rs | 22 +-- relays/client-rococo/src/lib.rs | 22 +-- relays/client-substrate/Cargo.toml | 4 +- relays/client-substrate/src/chain.rs | 11 -- relays/client-westend/src/lib.rs | 22 +-- relays/equivocation/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 4 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 6 +- 53 files changed, 362 insertions(+), 586 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index b33667d9be67c..af0c658a0516d 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } @@ -93,6 +93,7 @@ runtime-benchmarks = [ "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", + "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 2722f6f1c6d14..035077408c40b 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -105,43 +105,48 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { ($call:ty, $account_id:ty, $($filter_call:ty),*) => { #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, sp_runtime::RuntimeDebug, scale_info::TypeInfo)] pub struct BridgeRejectObsoleteHeadersAndMessages; - impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { + impl sp_runtime::traits::TransactionExtensionBase for BridgeRejectObsoleteHeadersAndMessages { const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; - type AccountId = $account_id; - type Call = $call; - type AdditionalSigned = (); + type Implicit = (); + } + impl sp_runtime::traits::TransactionExtension<$call, Context> for BridgeRejectObsoleteHeadersAndMessages { type Pre = (); - - fn additional_signed(&self) -> sp_std::result::Result< - (), - sp_runtime::transaction_validity::TransactionValidityError, - > { - Ok(()) - } + type Val = (); fn validate( &self, - _who: &Self::AccountId, - call: &Self::Call, - _info: &sp_runtime::traits::DispatchInfoOf, + origin: <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, + call: &$call, + _info: &sp_runtime::traits::DispatchInfoOf<$call>, _len: usize, - ) -> sp_runtime::transaction_validity::TransactionValidity { - let valid = sp_runtime::transaction_validity::ValidTransaction::default(); + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl codec::Encode, + ) -> Result< + ( + sp_runtime::transaction_validity::ValidTransaction, + Self::Val, + <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, + ), sp_runtime::transaction_validity::TransactionValidityError + > { + let tx_validity = sp_runtime::transaction_validity::ValidTransaction::default(); $( - let valid = valid - .combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?); + let call_filter_validity = <$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?; + let tx_validity = tx_validity.combine_with(call_filter_validity); )* - Ok(valid) + Ok((tx_validity, (), origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - info: &sp_runtime::traits::DispatchInfoOf, - len: usize, + _val: Self::Val, + _origin: &<$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, + _call: &$call, + _info: &sp_runtime::traits::DispatchInfoOf<$call>, + _len: usize, + _context: &Context, ) -> Result { - self.validate(who, call, info, len).map(drop) + Ok(()) } } }; @@ -150,12 +155,14 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { #[cfg(test)] mod tests { use crate::BridgeRuntimeFilterCall; - use frame_support::{assert_err, assert_ok}; + use codec::Encode; + use frame_support::assert_err; use sp_runtime::{ - traits::SignedExtension, + traits::DispatchTransaction, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, }; + #[derive(Encode)] pub struct MockCall { data: u32, } @@ -206,17 +213,20 @@ mod tests { ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 1 }, &(), 0), InvalidTransaction::Custom(1) ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 2 }, &(), 0), InvalidTransaction::Custom(2) ); - assert_ok!( - BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0), + assert_eq!( + BridgeRejectObsoleteHeadersAndMessages + .validate_only((), &MockCall { data: 3 }, &(), 0) + .unwrap() + .0, ValidTransaction { priority: 3, ..Default::default() } ) } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index 8877a4fd95ce3..f147f1404f06f 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -164,6 +164,7 @@ impl pallet_balances::Config for TestRuntime { type AccountStore = System; } +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] impl pallet_transaction_payment::Config for TestRuntime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; @@ -176,7 +177,6 @@ impl pallet_transaction_payment::Config for TestRuntime { MinimumMultiplier, MaximumMultiplier, >; - type RuntimeEvent = RuntimeEvent; } impl pallet_bridge_grandpa::Config for TestRuntime { diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs index a597fb9e2f492..0c53018330ea0 100644 --- a/bin/runtime-common/src/priority_calculator.rs +++ b/bin/runtime-common/src/priority_calculator.rs @@ -169,12 +169,15 @@ mod integrity_tests { // nodes to the proof (x0.5 because we expect some nodes to be reused) let estimated_message_size = 512; // let's say all our messages have the same dispatch weight - let estimated_message_dispatch_weight = - Runtime::WeightInfo::message_dispatch_weight(estimated_message_size); + let estimated_message_dispatch_weight = >::WeightInfo::message_dispatch_weight( + estimated_message_size + ); // messages proof argument size is (for every message) messages size + some additional // trie nodes. Some of them are reused by different messages, so let's take 2/3 of default // "overhead" constant - let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size() + let messages_proof_size = >::WeightInfo::expected_extra_storage_proof_size() .saturating_mul(2) .saturating_div(3) .saturating_add(estimated_message_size) @@ -182,7 +185,7 @@ mod integrity_tests { // finally we are able to estimate transaction size and weight let transaction_size = base_tx_size.saturating_add(messages_proof_size); - let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight( + let transaction_weight = >::WeightInfo::receive_messages_proof_weight( &PreComputedSize(transaction_size as _), messages as _, estimated_message_dispatch_weight.saturating_mul(messages), diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index bfcb82ad166c3..b912f8445ac1b 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -48,9 +48,12 @@ use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTra use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, SignedExtension, Zero}, + traits::{ + AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, + TransactionExtension, TransactionExtensionBase, ValidateResult, Zero, + }, transaction_validity::{ - TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder, + InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransactionBuilder, }, DispatchResult, FixedPointOperand, RuntimeDebug, }; @@ -239,8 +242,8 @@ pub enum RelayerAccountAction { Slash(AccountId, RewardsAccountParams), } -/// Everything common among our refund signed extensions. -pub trait RefundSignedExtension: +/// Everything common among our refund transaction extensions. +pub trait RefundTransactionExtension: 'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo where >::BridgedChain: @@ -456,8 +459,8 @@ where } } -/// Adapter that allow implementing `sp_runtime::traits::SignedExtension` for any -/// `RefundSignedExtension`. +/// Adapter that allow implementing `sp_runtime::traits::TransactionExtension` for any +/// `RefundTransactionExtension`. #[derive( DefaultNoBound, CloneNoBound, @@ -468,12 +471,13 @@ where RuntimeDebugNoBound, TypeInfo, )] -pub struct RefundSignedExtensionAdapter(T) +pub struct RefundTransactionExtensionAdapter(T) where >::BridgedChain: Chain; -impl SignedExtension for RefundSignedExtensionAdapter +impl TransactionExtensionBase + for RefundTransactionExtensionAdapter where >::BridgedChain: Chain, @@ -483,22 +487,35 @@ where + MessagesCallSubType::Instance>, { const IDENTIFIER: &'static str = T::Id::STR; - type AccountId = AccountIdOf; - type Call = CallOf; - type AdditionalSigned = (); - type Pre = Option>>; + type Implicit = (); +} - fn additional_signed(&self) -> Result<(), TransactionValidityError> { - Ok(()) - } +impl TransactionExtension, Context> + for RefundTransactionExtensionAdapter +where + >::BridgedChain: + Chain, + CallOf: Dispatchable + + IsSubType, T::Runtime>> + + GrandpaCallSubType + + MessagesCallSubType::Instance>, + as Dispatchable>::RuntimeOrigin: + AsSystemOriginSigner> + Clone, +{ + type Pre = Option>>; + type Val = Option; fn validate( &self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + origin: as Dispatchable>::RuntimeOrigin, + call: &CallOf, + _info: &DispatchInfoOf>, _len: usize, - ) -> TransactionValidity { + _context: &mut Context, + _self_implicit: Self::Implicit, + _inherited_implication: &impl Encode, + ) -> ValidateResult> { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; // this is the only relevant line of code for the `pre_dispatch` // // we're not calling `validate` from `pre_dispatch` directly because of performance @@ -511,12 +528,12 @@ where // we only boost priority of presumably correct message delivery transactions let bundled_messages = match T::bundled_messages_for_priority_boost(parsed_call.as_ref()) { Some(bundled_messages) => bundled_messages, - None => return Ok(Default::default()), + None => return Ok((Default::default(), parsed_call, origin)), }; // we only boost priority if relayer has staked required balance if !RelayersPallet::::is_registration_active(who) { - return Ok(Default::default()) + return Ok((Default::default(), parsed_call, origin)) } // compute priority boost @@ -535,20 +552,21 @@ where priority_boost, ); - valid_transaction.build() + let validity = valid_transaction.build()?; + Ok((validity, parsed_call, origin)) } - fn pre_dispatch( + fn prepare( self, - who: &Self::AccountId, - call: &Self::Call, - _info: &DispatchInfoOf, + val: Self::Val, + origin: & as Dispatchable>::RuntimeOrigin, + _call: &CallOf, + _info: &DispatchInfoOf>, _len: usize, + _context: &Context, ) -> Result { - // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) - let parsed_call = T::parse_and_check_for_obsolete_call(call)?; - - Ok(parsed_call.map(|call_info| { + let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + Ok(val.map(|call_info| { log::trace!( target: "runtime::bridge", "{} via {:?} parsed bridge transaction in pre-dispatch: {:?}", @@ -561,13 +579,14 @@ where } fn post_dispatch( - pre: Option, - info: &DispatchInfoOf, - post_info: &PostDispatchInfoOf, + pre: Self::Pre, + info: &DispatchInfoOf>, + post_info: &PostDispatchInfoOf>, len: usize, result: &DispatchResult, + _context: &Context, ) -> Result<(), TransactionValidityError> { - let call_result = T::analyze_call_result(pre, info, post_info, len, result); + let call_result = T::analyze_call_result(Some(pre), info, post_info, len, result); match call_result { RelayerAccountAction::None => (), @@ -595,7 +614,7 @@ where } } -/// Signed extension that refunds a relayer for new messages coming from a parachain. +/// Transaction extension that refunds a relayer for new messages coming from a parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and @@ -636,7 +655,7 @@ pub struct RefundBridgedParachainMessages, ); -impl RefundSignedExtension +impl RefundTransactionExtension for RefundBridgedParachainMessages where Self: 'static + Send + Sync, @@ -730,13 +749,13 @@ where } } -/// Signed extension that refunds a relayer for new messages coming from a standalone (GRANDPA) +/// Transaction extension that refunds a relayer for new messages coming from a standalone (GRANDPA) /// chain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and -/// parachain head, or just parachain head. Corresponding headers must be used in messages -/// proof verification. +/// parachain head, or just parachain head. Corresponding headers must be used in messages proof +/// verification. /// /// Extension does not refund transaction tip due to security reasons. #[derive( @@ -771,7 +790,7 @@ pub struct RefundBridgedGrandpaMessages, ); -impl RefundSignedExtension +impl RefundTransactionExtension for RefundBridgedGrandpaMessages where Self: 'static + Send + Sync, @@ -869,8 +888,8 @@ mod tests { Call as ParachainsCall, Pallet as ParachainsPallet, RelayBlockHash, }; use sp_runtime::{ - traits::{ConstU64, Header as HeaderT}, - transaction_validity::{InvalidTransaction, ValidTransaction}, + traits::{ConstU64, DispatchTransaction, Header as HeaderT}, + transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, DispatchError, }; @@ -899,7 +918,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestGrandpaExtension = RefundSignedExtensionAdapter; + type TestGrandpaExtension = RefundTransactionExtensionAdapter; type TestExtensionProvider = RefundBridgedParachainMessages< TestRuntime, DefaultRefundableParachainId<(), TestParachain>, @@ -908,7 +927,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestExtension = RefundSignedExtensionAdapter; + type TestExtension = RefundTransactionExtensionAdapter; fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance { let test_stake: ThisChainBalance = TestStake::get(); @@ -1407,14 +1426,28 @@ mod tests { fn run_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestExtension = - RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension + .validate_only( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|res| res.0) } fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestGrandpaExtension = - RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension + .validate_only( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|res| res.0) } fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { @@ -1428,16 +1461,30 @@ mod tests { call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestExtension = - RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension + .validate_and_prepare( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|(pre, _)| pre) } fn run_grandpa_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestGrandpaExtension = - RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) + RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension + .validate_and_prepare( + Some(relayer_account_at_this_chain()).into(), + &call, + &DispatchInfo::default(), + 0, + ) + .map(|(pre, _)| pre) } fn dispatch_info() -> DispatchInfo { @@ -1460,11 +1507,12 @@ mod tests { dispatch_result: DispatchResult, ) { let post_dispatch_result = TestExtension::post_dispatch( - Some(pre_dispatch_data), + pre_dispatch_data, &dispatch_info(), &post_dispatch_info(), 1024, &dispatch_result, + &(), ); assert_eq!(post_dispatch_result, Ok(())); } diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 3ff70eaafd231..30c91feb56da6 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -11,9 +11,9 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true } +serde = { optional = true, workspace = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 33ba0f1f0fdcf..1a5bfeff16e9d 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 75efb2ed57333..f6b1e71203dd1 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index ff58c8f43d2b9..2011f2cbbcc5e 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index d532db3b89f70..5e93e31965b39 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 8c4b62428e75a..280eeac942bae 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index b107461ef16f4..aaa1149414336 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -log = { version = "0.4.21", default-features = false } +log = { workspace = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 74e8f0492d8a3..4785f8297ba06 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } -serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +serde = { default-features = false, features = ["alloc", "derive"], workspace = true } # Bridge Dependencies diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index c49aa4b856397..f186f6427ae7d 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -26,7 +26,7 @@ pub use bp_polkadot_core::{ }; use bp_messages::*; -use bp_polkadot_core::SuffixedCommonSignedExtension; +use bp_polkadot_core::SuffixedCommonTransactionExtension; use bp_runtime::extensions::{ BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, }; @@ -164,7 +164,7 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// Signed extension that is used by all bridge hubs. -pub type SignedExtension = SuffixedCommonSignedExtension<( +pub type TransactionExtension = SuffixedCommonTransactionExtension<( BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, )>; diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index c4e697fbe9526..992ef1bd7a10f 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -107,5 +107,5 @@ frame_support::parameter_types! { /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_829_647; + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_904_835; } diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index e3b4d0520f61c..253a1010e83df 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Kusama { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The SignedExtension used by Kusama. -pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; +// The TransactionExtension used by Kusama. +pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; /// Name of the parachains pallet in the Kusama runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/primitives/chain-polkadot-bulletin/src/lib.rs index f2eebf9312470..73dd122bd1538 100644 --- a/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/primitives/chain-polkadot-bulletin/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, extensions::{ CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, - CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema, + CheckWeight, GenericTransactionExtension, GenericTransactionExtensionSchema, }, Chain, ChainId, TransactionEra, }; @@ -37,7 +37,12 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; -use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidityError, Perbill}; +use sp_runtime::{ + impl_tx_ext_default, + traits::{Dispatchable, TransactionExtensionBase}, + transaction_validity::TransactionValidityError, + Perbill, +}; // This chain reuses most of Polkadot primitives. pub use bp_polkadot_core::{ @@ -71,10 +76,10 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// This signed extension is used to ensure that the chain transactions are signed by proper -pub type ValidateSigned = GenericSignedExtensionSchema<(), ()>; +pub type ValidateSigned = GenericTransactionExtensionSchema<(), ()>; /// Signed extension schema, used by Polkadot Bulletin. -pub type SignedExtensionSchema = GenericSignedExtension<( +pub type TransactionExtensionSchema = GenericTransactionExtension<( ( CheckNonZeroSender, CheckSpecVersion, @@ -87,34 +92,30 @@ pub type SignedExtensionSchema = GenericSignedExtension<( ValidateSigned, )>; -/// Signed extension, used by Polkadot Bulletin. +/// Transaction extension, used by Polkadot Bulletin. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct SignedExtension(SignedExtensionSchema); +pub struct TransactionExtension(TransactionExtensionSchema); -impl sp_runtime::traits::SignedExtension for SignedExtension { +impl TransactionExtensionBase for TransactionExtension { const IDENTIFIER: &'static str = "Not needed."; - type AccountId = (); - type Call = (); - type AdditionalSigned = - ::AdditionalSigned; - type Pre = (); + type Implicit = ::Implicit; - fn additional_signed(&self) -> Result { - self.0.additional_signed() + fn implicit(&self) -> Result { + ::implicit(&self.0) } +} - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } +impl sp_runtime::traits::TransactionExtension for TransactionExtension +where + C: Dispatchable, +{ + type Pre = (); + type Val = (); + + impl_tx_ext_default!(C; Context; validate prepare); } -impl SignedExtension { +impl TransactionExtension { /// Create signed extension from its components. pub fn from_params( spec_version: u32, @@ -123,7 +124,7 @@ impl SignedExtension { genesis_hash: Hash, nonce: Nonce, ) -> Self { - Self(GenericSignedExtension::new( + Self(GenericTransactionExtension::new( ( ( (), // non-zero sender diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index fc5e10308a8e3..e5e2e7c3a042a 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -61,8 +61,8 @@ impl ChainWithGrandpa for Polkadot { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -/// The SignedExtension used by Polkadot. -pub type SignedExtension = SuffixedCommonSignedExtension; +/// The TransactionExtension used by Polkadot. +pub type TransactionExtension = SuffixedCommonTransactionExtension; /// Name of the parachains pallet in the Polkadot runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index f1b256f0f090f..267c6b2b1f029 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Rococo { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The SignedExtension used by Rococo. -pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; +// The TransactionExtension used by Rococo. +pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index f03fd2160a700..afa02e8ee541e 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The SignedExtension used by Westend. -pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; +// The TransactionExtension used by Westend. +pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index e42959164e4ca..7167c41046025 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 1092be13d899e..d121b69314648 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } -serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 5ef9920d7f196..c28f3f2e34e46 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { default-features = false, features = ["derive"], optional = true, workspace = true } # Bridge Dependencies diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index df2836495bbe1..d59b99db4b586 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -24,8 +24,8 @@ use bp_runtime::{ self, extensions::{ ChargeTransactionPayment, CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, - CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, - SignedExtensionSchema, + CheckSpecVersion, CheckTxVersion, CheckWeight, GenericTransactionExtension, + TransactionExtensionSchema, }, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, }; @@ -229,8 +229,12 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic, Signature, SignedExt>; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< + AccountAddress, + EncodedOrDecodedCall, + Signature, + TransactionExt, +>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; @@ -275,7 +279,7 @@ impl AccountInfoStorageMapKeyProvider { } /// Extra signed extension data that is used by most chains. -pub type CommonSignedExtra = ( +pub type CommonTransactionExtra = ( CheckNonZeroSender, CheckSpecVersion, CheckTxVersion, @@ -286,12 +290,12 @@ pub type CommonSignedExtra = ( ChargeTransactionPayment, ); -/// Extra signed extension data that starts with `CommonSignedExtra`. -pub type SuffixedCommonSignedExtension = - GenericSignedExtension<(CommonSignedExtra, Suffix)>; +/// Extra transaction extension data that starts with `CommonTransactionExtra`. +pub type SuffixedCommonTransactionExtension = + GenericTransactionExtension<(CommonTransactionExtra, Suffix)>; -/// Helper trait to define some extra methods on `SuffixedCommonSignedExtension`. -pub trait SuffixedCommonSignedExtensionExt { +/// Helper trait to define some extra methods on `SuffixedCommonTransactionExtension`. +pub trait SuffixedCommonTransactionExtensionExt { /// Create signed extension from its components. fn from_params( spec_version: u32, @@ -300,7 +304,7 @@ pub trait SuffixedCommonSignedExtensionExt { genesis_hash: Hash, nonce: Nonce, tip: Balance, - extra: (Suffix::Payload, Suffix::AdditionalSigned), + extra: (Suffix::Payload, Suffix::Implicit), ) -> Self; /// Return transaction nonce. @@ -310,9 +314,10 @@ pub trait SuffixedCommonSignedExtensionExt { fn tip(&self) -> Balance; } -impl SuffixedCommonSignedExtensionExt for SuffixedCommonSignedExtension +impl SuffixedCommonTransactionExtensionExt + for SuffixedCommonTransactionExtension where - Suffix: SignedExtensionSchema, + Suffix: TransactionExtensionSchema, { fn from_params( spec_version: u32, @@ -321,9 +326,9 @@ where genesis_hash: Hash, nonce: Nonce, tip: Balance, - extra: (Suffix::Payload, Suffix::AdditionalSigned), + extra: (Suffix::Payload, Suffix::Implicit), ) -> Self { - GenericSignedExtension::new( + GenericTransactionExtension::new( ( ( (), // non-zero sender @@ -365,7 +370,7 @@ where } /// Signed extension that is used by most chains. -pub type CommonSignedExtension = SuffixedCommonSignedExtension<()>; +pub type CommonTransactionExtension = SuffixedCommonTransactionExtension<()>; #[cfg(test)] mod tests { diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index 542b696533aae..d7cef6a10320b 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -13,10 +13,10 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" -log = { version = "0.4.21", default-features = false } +log = { workspace = true } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +serde = { features = ["alloc", "derive"], workspace = true } # Substrate Dependencies diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 9ba21a1cddf13..00bea2b3ca613 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -98,6 +98,17 @@ impl Encode for EncodedOrDecodedCall { } } +// dummy implementation to satisfy `SignedPayload` requirements +impl sp_runtime::traits::Dispatchable for EncodedOrDecodedCall { + type RuntimeOrigin = (); + type Config = (); + type Info = (); + type PostInfo = (); + fn dispatch(self, _origin: ()) -> sp_runtime::DispatchResultWithInfo<()> { + unreachable!("never used by relayer; qed") + } +} + /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { /// Chain id. diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index d896bc92efffc..a31e7b5bb47a6 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -20,135 +20,138 @@ use codec::{Compact, Decode, Encode}; use impl_trait_for_tuples::impl_for_tuples; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_runtime::{ - traits::{DispatchInfoOf, SignedExtension}, + impl_tx_ext_default, + traits::{Dispatchable, TransactionExtension, TransactionExtensionBase}, transaction_validity::TransactionValidityError, }; use sp_std::{fmt::Debug, marker::PhantomData}; -/// Trait that describes some properties of a `SignedExtension` that are needed in order to send a -/// transaction to the chain. -pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo { +/// Trait that describes some properties of a `TransactionExtension` that are needed in order to +/// send a transaction to the chain. +pub trait TransactionExtensionSchema: + Encode + Decode + Debug + Eq + Clone + StaticTypeInfo +{ /// A type of the data encoded as part of the transaction. type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). - type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo; + type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; } -impl SignedExtensionSchema for () { +impl TransactionExtensionSchema for () { type Payload = (); - type AdditionalSigned = (); + type Implicit = (); } -/// An implementation of `SignedExtensionSchema` using generic params. +/// An implementation of `TransactionExtensionSchema` using generic params. #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] -pub struct GenericSignedExtensionSchema(PhantomData<(P, S)>); +pub struct GenericTransactionExtensionSchema(PhantomData<(P, S)>); -impl SignedExtensionSchema for GenericSignedExtensionSchema +impl TransactionExtensionSchema for GenericTransactionExtensionSchema where P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, - S: Encode + Debug + Eq + Clone + StaticTypeInfo, + S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, { type Payload = P; - type AdditionalSigned = S; + type Implicit = S; } -/// The `SignedExtensionSchema` for `frame_system::CheckNonZeroSender`. -pub type CheckNonZeroSender = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`. +pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `frame_system::CheckSpecVersion`. -pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>; +/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`. +pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>; -/// The `SignedExtensionSchema` for `frame_system::CheckTxVersion`. -pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>; +/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`. +pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>; -/// The `SignedExtensionSchema` for `frame_system::CheckGenesis`. -pub type CheckGenesis = GenericSignedExtensionSchema<(), Hash>; +/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`. +pub type CheckGenesis = GenericTransactionExtensionSchema<(), Hash>; -/// The `SignedExtensionSchema` for `frame_system::CheckEra`. -pub type CheckEra = GenericSignedExtensionSchema; +/// The `TransactionExtensionSchema` for `frame_system::CheckEra`. +pub type CheckEra = GenericTransactionExtensionSchema; -/// The `SignedExtensionSchema` for `frame_system::CheckNonce`. -pub type CheckNonce = GenericSignedExtensionSchema, ()>; +/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`. +pub type CheckNonce = GenericTransactionExtensionSchema, ()>; -/// The `SignedExtensionSchema` for `frame_system::CheckWeight`. -pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`. +pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. -pub type ChargeTransactionPayment = GenericSignedExtensionSchema, ()>; +/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. +pub type ChargeTransactionPayment = + GenericTransactionExtensionSchema, ()>; -/// The `SignedExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. -pub type PrevalidateAttests = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. +pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. -pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; +/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. +pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>; -/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`. +/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`. /// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as /// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), /// ())` is the same. So runtime can contains any kind of tuple: /// `(BridgeRefundBridgeHubRococoMessages)` /// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)` /// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` -pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; +pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>; #[impl_for_tuples(1, 12)] -impl SignedExtensionSchema for Tuple { +impl TransactionExtensionSchema for Tuple { for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); - for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); + for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); ); } /// A simplified version of signed extensions meant for producing signed transactions /// and signed payloads in the client code. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct GenericSignedExtension { +pub struct GenericTransactionExtension { /// A payload that is included in the transaction. pub payload: S::Payload, #[codec(skip)] // It may be set to `None` if extensions are decoded. We are never reconstructing transactions - // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to - // read fields of the `payload`. And when resigning transaction, we're reconstructing - // `SignedExtensions` from scratch. - additional_signed: Option, + // (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only + // used to read fields of the `payload`. And when resigning transaction, we're reconstructing + // `TransactionExtensions` from scratch. + implicit: Option, } -impl GenericSignedExtension { - /// Create new `GenericSignedExtension` object. - pub fn new(payload: S::Payload, additional_signed: Option) -> Self { - Self { payload, additional_signed } +impl GenericTransactionExtension { + /// Create new `GenericTransactionExtension` object. + pub fn new(payload: S::Payload, implicit: Option) -> Self { + Self { payload, implicit } } } -impl SignedExtension for GenericSignedExtension +impl TransactionExtensionBase for GenericTransactionExtension where - S: SignedExtensionSchema, + S: TransactionExtensionSchema, S::Payload: Send + Sync, - S::AdditionalSigned: Send + Sync, + S::Implicit: Send + Sync, { const IDENTIFIER: &'static str = "Not needed."; - type AccountId = (); - type Call = (); - type AdditionalSigned = S::AdditionalSigned; - type Pre = (); + type Implicit = S::Implicit; - fn additional_signed(&self) -> Result { + fn implicit(&self) -> Result { // we shall not ever see this error in relay, because we are never signing decoded // transactions. Instead we're constructing and signing new transactions. So the error code // is kinda random here - self.additional_signed.clone().ok_or( - frame_support::unsigned::TransactionValidityError::Unknown( + self.implicit + .clone() + .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( frame_support::unsigned::UnknownTransaction::Custom(0xFF), - ), - ) + )) } +} +impl TransactionExtension for GenericTransactionExtension +where + C: Dispatchable, + S: TransactionExtensionSchema, + S::Payload: Send + Sync, + S::Implicit: Send + Sync, +{ + type Pre = (); + type Val = (); - fn pre_dispatch( - self, - _who: &Self::AccountId, - _call: &Self::Call, - _info: &DispatchInfoOf, - _len: usize, - ) -> Result { - Ok(()) - } + impl_tx_ext_default!(C; Context; validate prepare); } diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index f23ddd1a10d36..1d80890779bf8 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -129,7 +129,7 @@ pub fn make_justification_for_header( votes_ancestries.push(child.clone()); } - // The header we need to use when pre-commiting is the one at the highest height + // The header we need to use when pre-committing is the one at the highest height // on our chain. let precommit_candidate = chain.last().map(|h| (h.hash(), *h.number())).unwrap(); unsigned_precommits.push(precommit_candidate); diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 1bcb410ddfc4e..d5873752e22f8 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -16,7 +16,7 @@ codec = { package = "parity-scale-codec", version = "3.1.5" } env_logger = "0.11" futures = "0.3.30" hex = "0.4" -log = "0.4.21" +log = { workspace = true } num-format = "0.4" num-traits = "0.2" rbtag = "0.3" diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs index 196978c16e8c9..2d7b5aec1fd19 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs @@ -125,18 +125,6 @@ impl relay_substrate_client::ChainWithTransactions for RococoAsPolkadot { unsigned.switch_chain(), ) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - relay_rococo_client::Rococo::is_signed(tx) - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - relay_rococo_client::Rococo::is_signed_by(signer, tx) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - relay_rococo_client::Rococo::parse_transaction(tx).map(|tx| tx.switch_chain()) - } } impl CliChain for RococoAsPolkadot { @@ -232,19 +220,6 @@ impl relay_substrate_client::ChainWithTransactions for BridgeHubRococoAsBridgeHu unsigned.switch_chain(), ) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - relay_bridge_hub_rococo_client::BridgeHubRococo::is_signed(tx) - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - relay_bridge_hub_rococo_client::BridgeHubRococo::is_signed_by(signer, tx) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - relay_bridge_hub_rococo_client::BridgeHubRococo::parse_transaction(tx) - .map(|tx| tx.switch_chain()) - } } impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPolkadot { diff --git a/relays/client-bridge-hub-kusama/src/codegen_runtime.rs b/relays/client-bridge-hub-kusama/src/codegen_runtime.rs index 78ae788b32d57..2da4c3014b254 100644 --- a/relays/client-bridge-hub-kusama/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-kusama/src/codegen_runtime.rs @@ -392,7 +392,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RefundBridgedParachainMessages; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundSignedExtensionAdapter<_0>(pub _0); + pub struct RefundTransactionExtensionAdapter<_0>(pub _0); } } pub mod cumulus_pallet_dmp_queue { diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index b11301b0e0f8a..4ad6d2e2fb7e0 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_kusama::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot::SuffixedCommonSignedExtensionExt; +use bp_bridge_hub_kusama::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -36,7 +36,8 @@ pub type RuntimeCall = runtime_types::bridge_hub_kusama_runtime::RuntimeCall; pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; +type UncheckedExtrinsic = + bp_bridge_hub_kusama::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Kusama chain definition @@ -86,7 +87,7 @@ impl ChainWithTransactions for BridgeHubKusama { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - SignedExtension::from_params( + TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -108,24 +109,6 @@ impl ChainWithTransactions for BridgeHubKusama { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_bridge_hub_kusama::Address::Id(signer.public().into()) - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } impl ChainWithMessages for BridgeHubKusama { @@ -137,34 +120,3 @@ impl ChainWithMessages for BridgeHubKusama { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; } - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - type SystemCall = runtime_types::frame_system::pallet::Call; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = BridgeHubKusama::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = BridgeHubKusama::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs index 96a5b4fe033c7..176cb173e5334 100644 --- a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs @@ -20,14 +20,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -pub use bp_bridge_hub_kusama::SignedExtension; +pub use bp_bridge_hub_kusama::TransactionExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubKusama extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; // The indirect pallet call used to sync `Polkadot` GRANDPA finality to `BHKusama`. pub type BridgePolkadotGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs b/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs index c8c063b5e19cb..1ce9d0588024a 100644 --- a/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs @@ -392,7 +392,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RefundBridgedParachainMessages; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundSignedExtensionAdapter<_0>(pub _0); + pub struct RefundTransactionExtensionAdapter<_0>(pub _0); } } pub mod cumulus_pallet_dmp_queue { diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index 7bcf189e10965..8ac6569210aa8 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_polkadot::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_bridge_hub_polkadot::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -40,7 +40,8 @@ pub type BridgeKusamaMessagesCall = runtime_types::pallet_bridge_messages::palle pub type BridgePolkadotBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeKusamaGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; +type UncheckedExtrinsic = + bp_bridge_hub_polkadot::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Polkadot chain definition @@ -90,7 +91,7 @@ impl ChainWithTransactions for BridgeHubPolkadot { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - SignedExtension::from_params( + TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -112,24 +113,6 @@ impl ChainWithTransactions for BridgeHubPolkadot { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_bridge_hub_polkadot::Address::Id(signer.public().into()) - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } impl ChainWithMessages for BridgeHubPolkadot { @@ -141,34 +124,3 @@ impl ChainWithMessages for BridgeHubPolkadot { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; } - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - type SystemCall = runtime_types::frame_system::pallet::Call; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = BridgeHubPolkadot::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = BridgeHubPolkadot::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs index ded177996df94..f59b35253b1ba 100644 --- a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs @@ -20,14 +20,14 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -pub use bp_bridge_hub_polkadot::SignedExtension; +pub use bp_bridge_hub_polkadot::TransactionExtension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubPolkadot extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; /// The indirect pallet call used to sync `Kusama` GRANDPA finality to `BHPolkadot`. pub type BridgeKusamaGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs index bfb7c3e9d3d1f..e5c7c8b3e7679 100644 --- a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs @@ -463,7 +463,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RefundBridgedParachainMessages; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundSignedExtensionAdapter<_0>(pub _0); + pub struct RefundTransactionExtensionAdapter<_0>(pub _0); } } pub mod cumulus_pallet_parachain_system { diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 80a6316a454bf..7ec58453474a0 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_rococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_bridge_hub_rococo::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -38,7 +38,8 @@ pub type BridgeBulletinMessagesCall = runtime_types::pallet_bridge_messages::pal pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call2; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; +type UncheckedExtrinsic = + bp_bridge_hub_rococo::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Rococo chain definition @@ -88,7 +89,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - SignedExtension::from_params( + TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -110,24 +111,6 @@ impl ChainWithTransactions for BridgeHubRococo { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_bridge_hub_rococo::Address::Id(signer.public().into()) - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } impl ChainWithMessages for BridgeHubRococo { @@ -139,34 +122,3 @@ impl ChainWithMessages for BridgeHubRococo { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; } - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - type SystemCall = runtime_types::frame_system::pallet::Call; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = BridgeHubRococo::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = BridgeHubRococo::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/client-bridge-hub-westend/src/codegen_runtime.rs b/relays/client-bridge-hub-westend/src/codegen_runtime.rs index 3db044fcf5ec5..51d0b7f8c423f 100644 --- a/relays/client-bridge-hub-westend/src/codegen_runtime.rs +++ b/relays/client-bridge-hub-westend/src/codegen_runtime.rs @@ -407,7 +407,7 @@ pub mod api { #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] pub struct RefundBridgedParachainMessages; #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundSignedExtensionAdapter<_0>(pub _0); + pub struct RefundTransactionExtensionAdapter<_0>(pub _0); } } pub mod cumulus_pallet_parachain_system { diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs index 5e38ef65bc34a..c6bf1b45dd184 100644 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_westend::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_bridge_hub_westend::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -36,7 +36,8 @@ pub type RuntimeCall = runtime_types::bridge_hub_westend_runtime::RuntimeCall; pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic; +type UncheckedExtrinsic = + bp_bridge_hub_westend::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Westend chain definition @@ -86,7 +87,7 @@ impl ChainWithTransactions for BridgeHubWestend { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - SignedExtension::from_params( + TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -108,24 +109,6 @@ impl ChainWithTransactions for BridgeHubWestend { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| { - *address == bp_bridge_hub_westend::Address::Id(signer.public().into()) - }) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } impl ChainWithMessages for BridgeHubWestend { @@ -137,34 +120,3 @@ impl ChainWithMessages for BridgeHubWestend { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_westend::FROM_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; } - -#[cfg(test)] -mod tests { - use super::*; - use relay_substrate_client::TransactionEra; - - type SystemCall = runtime_types::frame_system::pallet::Call; - - #[test] - fn parse_transaction_works() { - let unsigned = UnsignedTransaction { - call: RuntimeCall::System(SystemCall::remark { remark: b"Hello world!".to_vec() }) - .into(), - nonce: 777, - tip: 888, - era: TransactionEra::immortal(), - }; - let signed_transaction = BridgeHubWestend::sign_transaction( - SignParam { - spec_version: 42, - transaction_version: 50000, - genesis_hash: [42u8; 32].into(), - signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(), - }, - unsigned.clone(), - ) - .unwrap(); - let parsed_transaction = BridgeHubWestend::parse_transaction(signed_transaction).unwrap(); - assert_eq!(parsed_transaction, unsigned); - } -} diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 42350ccc52f74..0f412284e79e4 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -19,7 +19,7 @@ pub mod codegen_runtime; use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, @@ -83,7 +83,7 @@ impl RelayChain for Kusama { impl ChainWithTransactions for Kusama { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -91,7 +91,7 @@ impl ChainWithTransactions for Kusama { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_kusama::SignedExtension::from_params( + bp_kusama::TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -113,20 +113,4 @@ impl ChainWithTransactions for Kusama { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs index 647df2ada32ec..b5bbeda802565 100644 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -99,8 +99,10 @@ impl ChainWithBalances for PolkadotBulletin { impl ChainWithTransactions for PolkadotBulletin { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_bulletin::UncheckedExtrinsic; + type SignedTransaction = bp_polkadot_bulletin::UncheckedExtrinsic< + Self::Call, + bp_polkadot_bulletin::TransactionExtension, + >; fn sign_transaction( param: SignParam, @@ -108,7 +110,7 @@ impl ChainWithTransactions for PolkadotBulletin { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot_bulletin::SignedExtension::from_params( + bp_polkadot_bulletin::TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -128,20 +130,4 @@ impl ChainWithTransactions for PolkadotBulletin { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce())) - } } diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 8e2a2c81748b7..638e01d1b6ace 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -19,7 +19,7 @@ mod codegen_runtime; use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, @@ -83,7 +83,7 @@ impl RelayChain for Polkadot { impl ChainWithTransactions for Polkadot { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -91,7 +91,7 @@ impl ChainWithTransactions for Polkadot { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot::SignedExtension::from_params( + bp_polkadot::TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -113,20 +113,4 @@ impl ChainWithTransactions for Polkadot { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index c96e421fa28d5..7843af241c1db 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -18,7 +18,7 @@ pub mod codegen_runtime; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ @@ -83,7 +83,7 @@ impl RelayChain for Rococo { impl ChainWithTransactions for Rococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -91,7 +91,7 @@ impl ChainWithTransactions for Rococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_rococo::SignedExtension::from_params( + bp_rococo::TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -113,20 +113,4 @@ impl ChainWithTransactions for Rococo { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 56bdd150a9a83..7ff2e2f45e727 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -14,12 +14,12 @@ async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } -log = "0.4.21" +log = { workspace = true } num-traits = "0.2" rand = "0.8" scale-info = { version = "2.10.0", features = ["derive"] } tokio = { version = "1.36", features = ["rt-multi-thread"] } -thiserror = "1.0.57" +thiserror = { workspace = true } # Bridge dependencies diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 9de7308c5bdd3..4f9467ec59daf 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -203,17 +203,6 @@ pub trait ChainWithTransactions: Chain { ) -> Result where Self: Sized; - - /// Returns true if transaction is signed. - fn is_signed(tx: &Self::SignedTransaction) -> bool; - - /// Returns true if transaction is signed by given signer. - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool; - - /// Parse signed transaction into its unsigned part. - /// - /// Returns `None` if signed transaction has unsupported format. - fn parse_transaction(tx: Self::SignedTransaction) -> Option>; } /// Sign transaction parameters diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 789599bbb1d29..8067f67a2bbd6 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -18,7 +18,7 @@ pub mod codegen_runtime; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; +use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ @@ -83,7 +83,7 @@ impl ChainWithBalances for Westend { impl ChainWithTransactions for Westend { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -91,7 +91,7 @@ impl ChainWithTransactions for Westend { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_westend::SignedExtension::from_params( + bp_westend::TransactionExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -113,20 +113,4 @@ impl ChainWithTransactions for Westend { extra, )) } - - fn is_signed(tx: &Self::SignedTransaction) -> bool { - tx.signature.is_some() - } - - fn is_signed_by(signer: &Self::AccountKeyPair, tx: &Self::SignedTransaction) -> bool { - tx.signature - .as_ref() - .map(|(address, _, _)| *address == Address::Id(signer.public().into())) - .unwrap_or(false) - } - - fn parse_transaction(tx: Self::SignedTransaction) -> Option> { - let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) - } } diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 99cf88a4045b2..0b4a7e983a3a8 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -16,6 +16,6 @@ bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } futures = "0.3.30" -log = "0.4.21" +log = { workspace = true } num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 8c162294f9c76..9e8bf56f53aaa 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.30" -log = "0.4.21" +log = { workspace = true } num-traits = "0.2" relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 169da263ddcaf..161548ac4d5e2 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,14 +10,14 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = "1.0.57" +thiserror = { workspace = true } async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" hex = "0.4" num-traits = "0.2" -log = "0.4.21" +log = { workspace = true } # Bridge dependencies diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 14d3f191701a0..3367e4bbd4439 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -14,7 +14,7 @@ async-trait = "0.1" env_logger = "0.11" futures = "0.3.30" hex = "0.4" -log = "0.4.21" +log = { workspace = true } num-traits = "0.2" parking_lot = "0.12.1" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 62c9934af332f..9dc35343b48c6 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true async-std = "1.6.5" async-trait = "0.1" futures = "0.3.30" -log = "0.4.21" +log = { workspace = true } relay-utils = { path = "../utils" } # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ae406933288e3..ed6093318a0dc 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -18,13 +18,13 @@ isahc = "1.2" env_logger = "0.11.3" futures = "0.3.30" jsonpath_lib = "0.3" -log = "0.4.21" +log = { workspace = true } num-traits = "0.2" -serde_json = "1.0" +serde_json = { workspace = true, default-features = true } sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } tokio = { version = "1.36", features = ["rt"] } -thiserror = "1.0.57" +thiserror = { workspace = true } # Bridge dependencies From c28ccccc5150e323553c77a94979aa7a2ac3de3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 02:56:35 +0000 Subject: [PATCH 1193/1210] Bump scale-info from 2.10.0 to 2.11.0 Bumps [scale-info](https://github.com/paritytech/scale-info) from 2.10.0 to 2.11.0. - [Release notes](https://github.com/paritytech/scale-info/releases) - [Changelog](https://github.com/paritytech/scale-info/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/scale-info/compare/v2.10.0...v2.11.0) --- updated-dependencies: - dependency-name: scale-info dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- bin/runtime-common/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- modules/xcm-bridge-hub/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/chain-asset-hub-rococo/Cargo.toml | 2 +- primitives/chain-asset-hub-westend/Cargo.toml | 2 +- primitives/chain-polkadot-bulletin/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/xcm-bridge-hub-router/Cargo.toml | 2 +- relays/client-bridge-hub-kusama/Cargo.toml | 2 +- relays/client-bridge-hub-polkadot/Cargo.toml | 2 +- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-westend/Cargo.toml | 2 +- relays/client-kusama/Cargo.toml | 2 +- relays/client-polkadot-bulletin/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-westend/Cargo.toml | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index af0c658a0516d..835a8cf1318f3 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -14,7 +14,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 30c91feb56da6..4ead33c44314f 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 1a5bfeff16e9d..eb7ad6a2772fa 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -15,7 +15,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index f6b1e71203dd1..55b48cc03ce32 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 2011f2cbbcc5e..2b8445b794b13 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 5e93e31965b39..972b4c33ab474 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 280eeac942bae..926b704bd8530 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive", "serde"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index aaa1149414336..4d5d012345a4c 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../../primitives/messages", default-features = false } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 4785f8297ba06..b6bb2698689b6 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } serde = { default-features = false, features = ["alloc", "derive"], workspace = true } # Bridge Dependencies diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/primitives/chain-asset-hub-rococo/Cargo.toml index ad0eb39f9e3ae..08be719bfd98c 100644 --- a/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/primitives/chain-asset-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/chain-asset-hub-westend/Cargo.toml b/primitives/chain-asset-hub-westend/Cargo.toml index 15b17f4d02d4d..d8245c7a89586 100644 --- a/primitives/chain-asset-hub-westend/Cargo.toml +++ b/primitives/chain-asset-hub-westend/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/primitives/chain-polkadot-bulletin/Cargo.toml index 86f05624d016d..797a893b21c39 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/primitives/chain-polkadot-bulletin/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 7167c41046025..6e9178f3c492c 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index d121b69314648..282ef93d38c53 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index e62ae6a8d423c..3e148d5289d10 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index c28f3f2e34e46..dd3912429d669 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { default-features = false, features = ["derive"], optional = true, workspace = true } # Bridge Dependencies diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 19aed6b038bcd..3ee433974d602 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index d7cef6a10320b..b6ed0bc06d172 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -15,7 +15,7 @@ hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" log = { workspace = true } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Substrate Dependencies diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index a9f584e2a0316..c7bae8443f1fd 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index 30177443c3e50..6e41bb3fcee8e 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } #relay-substrate-client = { path = "../client-substrate" } subxt = { version = "0.32.1", default-features = false, features = ["native"] } diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index a85e2d685c486..f5fc69d02be21 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index ea59240fd9274..efccfa5fb60e4 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml index 18b4f3230ede2..188839e2dba46 100644 --- a/relays/client-bridge-hub-westend/Cargo.toml +++ b/relays/client-bridge-hub-westend/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 3fa32aa4844a5..6d3a71b3855e4 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml index b0eafc963389a..2160a35fb8ffe 100644 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index 52c836e14566a..daa3423bbd424 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index ba546396fac78..7a6b7d3bae224 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 7ff2e2f45e727..ea02a0ad20159 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -17,7 +17,7 @@ jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = { workspace = true } num-traits = "0.2" rand = "0.8" -scale-info = { version = "2.10.0", features = ["derive"] } +scale-info = { version = "2.11.0", features = ["derive"] } tokio = { version = "1.36", features = ["rt-multi-thread"] } thiserror = { workspace = true } diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 1933a1f4130c6..2c9aacc16e69b 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies From 5a6edc04211684a052e1484c6a82cea0d40c4db7 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 20 Mar 2024 09:45:43 +0100 Subject: [PATCH 1194/1210] Move generic CLI logic to different crate (#2885) * Move generic CLI logic to separate crate * Move and rename `CliChain` trait definition Move it to `relay-substrate-client` * Move generic cli logic to substrate-relay-helper * Fix docs warnings --- ..._kusama_messages_to_bridge_hub_polkadot.rs | 7 +- ..._polkadot_messages_to_bridge_hub_kusama.rs | 7 +- .../kusama_headers_to_bridge_hub_polkadot.rs | 2 +- ...usama_parachains_to_bridge_hub_polkadot.rs | 6 +- .../polkadot_headers_to_bridge_hub_kusama.rs | 2 +- ...olkadot_parachains_to_bridge_hub_kusama.rs | 6 +- ..._polkadot_messages_to_polkadot_bulletin.rs | 7 +- ...bulletin_headers_to_bridge_hub_polkadot.rs | 10 +- ...ulletin_messages_to_bridge_hub_polkadot.rs | 7 +- .../polkadot_headers_to_polkadot_bulletin.rs | 8 +- ...olkadot_parachains_to_polkadot_bulletin.rs | 4 +- ..._hub_rococo_messages_to_rococo_bulletin.rs | 7 +- .../src/bridges/rococo_bulletin/mod.rs | 9 +- ...o_bulletin_headers_to_bridge_hub_rococo.rs | 9 +- ..._bulletin_messages_to_bridge_hub_rococo.rs | 7 +- .../rococo_headers_to_rococo_bulletin.rs | 7 +- .../rococo_parachains_to_rococo_bulletin.rs | 2 +- ...b_rococo_messages_to_bridge_hub_westend.rs | 7 +- ...b_westend_messages_to_bridge_hub_rococo.rs | 7 +- .../rococo_headers_to_bridge_hub_westend.rs | 8 +- ...rococo_parachains_to_bridge_hub_westend.rs | 6 +- .../westend_headers_to_bridge_hub_rococo.rs | 8 +- ...westend_parachains_to_bridge_hub_rococo.rs | 6 +- relays/bin-substrate/src/chains/kusama.rs | 32 -- relays/bin-substrate/src/chains/mod.rs | 23 - relays/bin-substrate/src/chains/polkadot.rs | 32 -- .../src/chains/polkadot_bulletin.rs | 26 - relays/bin-substrate/src/chains/rococo.rs | 32 -- relays/bin-substrate/src/chains/westend.rs | 32 -- relays/bin-substrate/src/cli/chain_schema.rs | 238 +-------- .../src/cli/detect_equivocations.rs | 65 +-- relays/bin-substrate/src/cli/init_bridge.rs | 158 ++---- relays/bin-substrate/src/cli/mod.rs | 208 +------- relays/bin-substrate/src/cli/relay_headers.rs | 60 +-- .../mod.rs => relay_headers_and_messages.rs} | 354 ++----------- .../bin-substrate/src/cli/relay_messages.rs | 88 +--- .../bin-substrate/src/cli/relay_parachains.rs | 78 +-- relays/bin-substrate/src/main.rs | 1 - relays/client-bridge-hub-kusama/src/lib.rs | 10 +- relays/client-bridge-hub-polkadot/src/lib.rs | 10 +- relays/client-bridge-hub-rococo/src/lib.rs | 10 +- relays/client-bridge-hub-westend/src/lib.rs | 10 +- relays/client-kusama/src/lib.rs | 10 +- relays/client-polkadot-bulletin/src/lib.rs | 10 +- relays/client-polkadot/src/lib.rs | 10 +- relays/client-rococo/src/lib.rs | 10 +- relays/client-substrate/src/chain.rs | 11 + relays/client-substrate/src/lib.rs | 6 +- relays/client-westend/src/lib.rs | 10 +- relays/lib-substrate-relay/Cargo.toml | 7 +- .../src/cli/bridge.rs | 37 +- .../src/cli/chain_schema.rs | 250 +++++++++ .../src/cli/detect_equivocations.rs | 65 +++ .../src/cli/init_bridge.rs | 85 +++ relays/lib-substrate-relay/src/cli/mod.rs | 192 +++++++ .../src/cli/relay_headers.rs | 76 +++ .../src/cli/relay_headers_and_messages/mod.rs | 484 ++++++++++++++++++ .../parachain_to_parachain.rs | 54 +- .../relay_to_parachain.rs | 42 +- .../relay_to_relay.rs | 24 +- .../src/cli/relay_messages.rs | 89 ++++ .../src/cli/relay_parachains.rs | 91 ++++ relays/lib-substrate-relay/src/lib.rs | 1 + 63 files changed, 1744 insertions(+), 1436 deletions(-) delete mode 100644 relays/bin-substrate/src/chains/kusama.rs delete mode 100644 relays/bin-substrate/src/chains/mod.rs delete mode 100644 relays/bin-substrate/src/chains/polkadot.rs delete mode 100644 relays/bin-substrate/src/chains/polkadot_bulletin.rs delete mode 100644 relays/bin-substrate/src/chains/rococo.rs delete mode 100644 relays/bin-substrate/src/chains/westend.rs rename relays/bin-substrate/src/cli/{relay_headers_and_messages/mod.rs => relay_headers_and_messages.rs} (52%) rename relays/{bin-substrate => lib-substrate-relay}/src/cli/bridge.rs (81%) create mode 100644 relays/lib-substrate-relay/src/cli/chain_schema.rs create mode 100644 relays/lib-substrate-relay/src/cli/detect_equivocations.rs create mode 100644 relays/lib-substrate-relay/src/cli/init_bridge.rs create mode 100644 relays/lib-substrate-relay/src/cli/mod.rs create mode 100644 relays/lib-substrate-relay/src/cli/relay_headers.rs create mode 100644 relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs rename relays/{bin-substrate => lib-substrate-relay}/src/cli/relay_headers_and_messages/parachain_to_parachain.rs (82%) rename relays/{bin-substrate => lib-substrate-relay}/src/cli/relay_headers_and_messages/relay_to_parachain.rs (88%) rename relays/{bin-substrate => lib-substrate-relay}/src/cli/relay_headers_and_messages/relay_to_relay.rs (91%) create mode 100644 relays/lib-substrate-relay/src/cli/relay_messages.rs create mode 100644 relays/lib-substrate-relay/src/cli/relay_parachains.rs diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs index e57302315560d..fc239ca1ed387 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs @@ -16,10 +16,13 @@ //! BridgeHubKusama-to-BridgeHubPolkadot messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_kusama_client::BridgeHubKusama; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubKusama-to-BridgeHubPolkadot messages bridge. pub struct BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs index 0a1b21cd11243..8d8e5e0c35e56 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs @@ -16,10 +16,13 @@ //! BridgeHubPolkadot-to-BridgeHubKusama messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_kusama_client::BridgeHubKusama; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubPolkadot-to-BridgeHubKusama messages bridge. pub struct BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs index dafb5f568263d..196a22cd70d79 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs @@ -16,7 +16,7 @@ //! Kusama-to-BridgeHubPolkadot headers sync entrypoint. -use crate::cli::bridge::{ +use substrate_relay_helper::cli::bridge::{ CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, }; diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs index 9b76cdbfa63ea..b39b970080534 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs @@ -16,11 +16,11 @@ //! Kusama-to-BridgeHubPolkadot parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// Kusama-to-BridgeHubPolkadot parachain sync description. diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs index 019afab0bb3d6..d96326a288de9 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs @@ -16,7 +16,7 @@ //! Polkadot-to-KusamaBridgeHub headers sync entrypoint. -use crate::cli::bridge::{ +use substrate_relay_helper::cli::bridge::{ CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, }; diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs index 439eddaa1a6cd..25ce53cb5990d 100644 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs +++ b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs @@ -16,11 +16,11 @@ //! Polkadot-to-BridgeHubKusama parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// Polkadot-to-BridgeHubKusama parachain sync description. diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs index ba177271db15f..8114d23296f0c 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs @@ -16,10 +16,13 @@ //! BridgeHubPolkadot-to-PolkadotBulletin messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; use relay_polkadot_bulletin_client::PolkadotBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubPolkadot-to-PolkadotBulletin messages bridge. pub struct BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs index 7019a6b55a36a..eb63785d3bb39 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs @@ -16,11 +16,6 @@ //! PolkadotBulletin-to-BridgeHubPolkadot headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -28,6 +23,11 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; + /// Description of `PolkadotBulletin` -> `PolkadotBridgeHub` finalized headers bridge. #[derive(Clone, Debug)] pub struct PolkadotBulletinFinalityToBridgeHubPolkadot; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs index 1b5f3e5f69e84..1c04f87881016 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs @@ -16,10 +16,13 @@ //! PolkadotBulletin-to-BridgeHubPolkadot messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; use relay_polkadot_bulletin_client::PolkadotBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// PolkadotBulletin-to-BridgeHubPolkadot messages bridge. pub struct PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs index 897c2ac884f91..7996d1613c8dd 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs @@ -16,10 +16,6 @@ //! Polkadot-to-PolkadotBulletin headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -27,6 +23,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Polkadot -> `PolkadotBulletin` finalized headers bridge. #[derive(Clone, Debug)] pub struct PolkadotFinalityToPolkadotBulletin; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs index 674c84adb39c6..0bfce11ba710e 100644 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs +++ b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs @@ -16,7 +16,9 @@ //! Polkadot-to-PolkadotBulletin parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, +}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::Chain; diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs index a2de83831c9bf..b8e95556bff11 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs @@ -17,9 +17,12 @@ //! BridgeHubRococo-to-RococoBulletin messages sync entrypoint. use super::BridgeHubRococoAsBridgeHubPolkadot; -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// BridgeHubRococo-to-RococoBulletin messages bridge. pub struct BridgeHubRococoToRococoBulletinMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs index 2d7b5aec1fd19..738fea8c5281e 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs @@ -16,8 +16,6 @@ //! Declaration of all bridges between Rococo Bulletin Chain and Rococo Bridge Hub. -use crate::cli::CliChain; - use bp_messages::MessageNonce; use bp_runtime::{ AccountIdOf, BalanceOf, BlockNumberOf, ChainId, HashOf, HasherOf, HeaderOf, NonceOf, @@ -25,7 +23,8 @@ use bp_runtime::{ }; use frame_support::pallet_prelude::Weight; use relay_substrate_client::{ - Error as SubstrateError, SignParam, SimpleRuntimeVersion, UnsignedTransaction, + ChainWithRuntimeVersion, Error as SubstrateError, SignParam, SimpleRuntimeVersion, + UnsignedTransaction, }; use sp_core::storage::StorageKey; use std::time::Duration; @@ -127,7 +126,7 @@ impl relay_substrate_client::ChainWithTransactions for RococoAsPolkadot { } } -impl CliChain for RococoAsPolkadot { +impl ChainWithRuntimeVersion for RococoAsPolkadot { const RUNTIME_VERSION: Option = None; } @@ -232,7 +231,7 @@ impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPol relay_bridge_hub_polkadot_client::BridgeHubPolkadot::FROM_CHAIN_MESSAGE_DETAILS_METHOD; } -impl CliChain for BridgeHubRococoAsBridgeHubPolkadot { +impl ChainWithRuntimeVersion for BridgeHubRococoAsBridgeHubPolkadot { const RUNTIME_VERSION: Option = Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); } diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs index e897cd85967df..0d54fd21018d1 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs @@ -17,10 +17,6 @@ //! RococoBulletin-to-BridgeHubRococo headers sync entrypoint. use super::BridgeHubRococoAsBridgeHubPolkadot; -use crate::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; use async_trait::async_trait; use substrate_relay_helper::{ @@ -29,6 +25,11 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, + RelayToRelayHeadersCliBridge, +}; + /// Description of `RococoBulletin` -> `RococoBridgeHub` finalized headers bridge. #[derive(Clone, Debug)] pub struct RococoBulletinFinalityToBridgeHubRococo; diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs index 856be9cf6f2a8..d192ec0381e58 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs @@ -17,9 +17,12 @@ //! RococoBulletin-to-BridgeHubRococo messages sync entrypoint. use super::BridgeHubRococoAsBridgeHubPolkadot; -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; /// RococoBulletin-to-BridgeHubRococo messages bridge. pub struct RococoBulletinToBridgeHubRococoMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs index 8a4b44eec27b9..45c890267ffba 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs @@ -17,9 +17,6 @@ //! Rococo-to-RococoBulletin headers sync entrypoint. use super::RococoAsPolkadot; -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; use async_trait::async_trait; use substrate_relay_helper::{ @@ -28,6 +25,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Rococo -> `RococoBulletin` finalized headers bridge. #[derive(Clone, Debug)] pub struct RococoFinalityToRococoBulletin; diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs index ee44bad523b4f..d14a133d23c43 100644 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs +++ b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs @@ -17,12 +17,12 @@ //! Rococo-to-RococoBulletin parachains sync entrypoint. use super::{BridgeHubRococoAsBridgeHubPolkadot, RococoAsPolkadot}; -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_runtime::Chain; use relay_substrate_client::{CallOf, HeaderIdOf}; use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, messages_lane::MessagesRelayLimits, parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs index cbf122a2d4b08..ec6b07d982afe 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs @@ -16,10 +16,13 @@ //! BridgeHubRococo-to-BridgeHubWestend messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_westend_client::BridgeHubWestend; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; pub struct BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs index bb823981bf89e..4e978cd8356cf 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs @@ -16,10 +16,13 @@ //! BridgeHubWestend-to-BridgeHubRococo messages sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge}; use relay_bridge_hub_rococo_client::BridgeHubRococo; use relay_bridge_hub_westend_client::BridgeHubWestend; -use substrate_relay_helper::{messages_lane::SubstrateMessageLane, UtilityPalletBatchCallBuilder}; +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge}, + messages_lane::SubstrateMessageLane, + UtilityPalletBatchCallBuilder, +}; pub struct BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs index 6e6661d5417c8..bf30a87bf2d48 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs @@ -16,10 +16,6 @@ //! Rococo-to-Westend bridge hubs headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -27,6 +23,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Rococo -> Westend finalized headers bridge. #[derive(Clone, Debug)] pub struct RococoFinalityToBridgeHubWestend; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs index 16b646233eed8..31de8c4d1d1c5 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs @@ -16,11 +16,11 @@ //! Westend-to-Rococo parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// BridgeHub-to-BridgeHub parachain sync description. diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs index 6f4ebb84a834e..4a1419f06dcdf 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs @@ -16,10 +16,6 @@ //! Westend-to-Rococo bridge hubs headers sync entrypoint. -use crate::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - use async_trait::async_trait; use substrate_relay_helper::{ equivocation::SubstrateEquivocationDetectionPipeline, @@ -27,6 +23,10 @@ use substrate_relay_helper::{ finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, }; +use substrate_relay_helper::cli::bridge::{ + CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, +}; + /// Description of Westend -> Rococo finalized headers bridge. #[derive(Clone, Debug)] pub struct WestendFinalityToBridgeHubRococo; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs index dac915dc3ba9e..fc6f6532836fd 100644 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs +++ b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs @@ -16,11 +16,11 @@ //! Rococo-to-Westend parachains sync entrypoint. -use crate::cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::parachains::{ - SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline, +use substrate_relay_helper::{ + cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, }; /// BridgeHub-to-BridgeHub parachain sync description. diff --git a/relays/bin-substrate/src/chains/kusama.rs b/relays/bin-substrate/src/chains/kusama.rs deleted file mode 100644 index 80ffdfed0037a..0000000000000 --- a/relays/bin-substrate/src/chains/kusama.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 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 . - -//! Kusama + Kusama parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_kusama_client::BridgeHubKusama; -use relay_kusama_client::Kusama; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for Kusama { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); -} - -impl CliChain for BridgeHubKusama { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 }); -} diff --git a/relays/bin-substrate/src/chains/mod.rs b/relays/bin-substrate/src/chains/mod.rs deleted file mode 100644 index ab15a9e679cd5..0000000000000 --- a/relays/bin-substrate/src/chains/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 . - -//! Chain-specific relayer configuration. - -mod kusama; -mod polkadot; -mod polkadot_bulletin; -mod rococo; -mod westend; diff --git a/relays/bin-substrate/src/chains/polkadot.rs b/relays/bin-substrate/src/chains/polkadot.rs deleted file mode 100644 index 1f1c607916a19..0000000000000 --- a/relays/bin-substrate/src/chains/polkadot.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 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 . - -//! Polkadot + Polkadot parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use relay_polkadot_client::Polkadot; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for Polkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); -} - -impl CliChain for BridgeHubPolkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 }); -} diff --git a/relays/bin-substrate/src/chains/polkadot_bulletin.rs b/relays/bin-substrate/src/chains/polkadot_bulletin.rs deleted file mode 100644 index ee7edbd9f4231..0000000000000 --- a/relays/bin-substrate/src/chains/polkadot_bulletin.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2022 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 . - -//! Polkadot + Polkadot parachains specification for CLI. - -use crate::cli::CliChain; -use relay_polkadot_bulletin_client::PolkadotBulletin; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for PolkadotBulletin { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 }); -} diff --git a/relays/bin-substrate/src/chains/rococo.rs b/relays/bin-substrate/src/chains/rococo.rs deleted file mode 100644 index 0640447fdc515..0000000000000 --- a/relays/bin-substrate/src/chains/rococo.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 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 . - -//! Rococo + Rococo parachains specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_rococo_client::BridgeHubRococo; -use relay_rococo_client::Rococo; -use relay_substrate_client::SimpleRuntimeVersion; - -impl CliChain for Rococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); -} - -impl CliChain for BridgeHubRococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); -} diff --git a/relays/bin-substrate/src/chains/westend.rs b/relays/bin-substrate/src/chains/westend.rs deleted file mode 100644 index 41f5fc4e96c8f..0000000000000 --- a/relays/bin-substrate/src/chains/westend.rs +++ /dev/null @@ -1,32 +0,0 @@ -// 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 . - -//! Westend chain specification for CLI. - -use crate::cli::CliChain; -use relay_bridge_hub_westend_client::BridgeHubWestend; -use relay_substrate_client::SimpleRuntimeVersion; -use relay_westend_client::Westend; - -impl CliChain for Westend { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); -} - -impl CliChain for BridgeHubWestend { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); -} diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs index 65559397ac2a7..4422332a59324 100644 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ b/relays/bin-substrate/src/cli/chain_schema.rs @@ -12,248 +12,12 @@ // 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 . -use relay_substrate_client::{AccountKeyPairOf, ChainWithTransactions}; -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; - -use crate::cli::CliChain; -pub use relay_substrate_client::{ChainRuntimeVersion, SimpleRuntimeVersion}; -use substrate_relay_helper::TransactionParams; - -#[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] -pub enum RuntimeVersionType { - /// Auto query version from chain - Auto, - /// Custom `spec_version` and `transaction_version` - Custom, - /// Read version from bundle dependencies directly. - Bundle, -} - -/// Create chain-specific set of runtime version parameters. -#[macro_export] -macro_rules! declare_chain_runtime_version_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = $chain " runtime version params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] - pub struct [<$chain RuntimeVersionParams>] { - #[doc = "The type of runtime version for chain " $chain] - #[structopt(long, default_value = "Bundle")] - pub [<$chain_prefix _version_mode>]: RuntimeVersionType, - #[doc = "The custom sepc_version for chain " $chain] - #[structopt(long)] - pub [<$chain_prefix _spec_version>]: Option, - #[doc = "The custom transaction_version for chain " $chain] - #[structopt(long)] - pub [<$chain_prefix _transaction_version>]: Option, - } - - impl [<$chain RuntimeVersionParams>] { - /// Converts self into `ChainRuntimeVersion`. - pub fn into_runtime_version( - self, - bundle_runtime_version: Option, - ) -> anyhow::Result { - Ok(match self.[<$chain_prefix _version_mode>] { - RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, - RuntimeVersionType::Custom => { - let custom_spec_version = self.[<$chain_prefix _spec_version>] - .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; - let custom_transaction_version = self.[<$chain_prefix _transaction_version>] - .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; - ChainRuntimeVersion::Custom( - SimpleRuntimeVersion { - spec_version: custom_spec_version, - transaction_version: custom_transaction_version - } - ) - }, - RuntimeVersionType::Bundle => match bundle_runtime_version { - Some(runtime_version) => ChainRuntimeVersion::Custom(runtime_version), - None => { - return Err(anyhow::format_err!("Cannot use bundled runtime version of {}: it is not known to the relay", stringify!($chain_prefix))); - } - }, - }) - } - } - } - }; -} - -/// Create chain-specific set of runtime version parameters. -#[macro_export] -macro_rules! declare_chain_connection_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = $chain " connection params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] - pub struct [<$chain ConnectionParams>] { - #[doc = "Connect to " $chain " node at given host."] - #[structopt(long, default_value = "127.0.0.1")] - pub [<$chain_prefix _host>]: String, - #[doc = "Connect to " $chain " node websocket server at given port."] - #[structopt(long, default_value = "9944")] - pub [<$chain_prefix _port>]: u16, - #[doc = "Use secure websocket connection."] - #[structopt(long)] - pub [<$chain_prefix _secure>]: bool, - #[doc = "Custom runtime version"] - #[structopt(flatten)] - pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], - } - - impl [<$chain ConnectionParams>] { - /// Convert connection params into Substrate client. - #[allow(dead_code)] - pub async fn into_client( - self, - ) -> anyhow::Result> { - let chain_runtime_version = self - .[<$chain_prefix _runtime_version>] - .into_runtime_version(Chain::RUNTIME_VERSION)?; - Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { - host: self.[<$chain_prefix _host>], - port: self.[<$chain_prefix _port>], - secure: self.[<$chain_prefix _secure>], - chain_runtime_version, - }) - .await - ) - } - } - } - }; -} - -/// Create chain-specific set of signing parameters. -#[macro_export] -macro_rules! declare_chain_signing_params_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - bp_runtime::paste::item! { - #[doc = $chain " signing params."] - #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] - pub struct [<$chain SigningParams>] { - #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _signer>]: Option, - #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] - #[structopt(long)] - pub [<$chain_prefix _signer_password>]: Option, - - #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] - #[structopt(long)] - pub [<$chain_prefix _signer_file>]: Option, - #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] - #[structopt(long)] - pub [<$chain_prefix _signer_password_file>]: Option, - - #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] - #[structopt(long)] - pub [<$chain_prefix _transactions_mortality>]: Option, - } - - impl [<$chain SigningParams>] { - /// Return transactions mortality. - #[allow(dead_code)] - pub fn transactions_mortality(&self) -> anyhow::Result> { - self.[<$chain_prefix _transactions_mortality>] - .map(|transactions_mortality| { - if !(4..=65536).contains(&transactions_mortality) - || !transactions_mortality.is_power_of_two() - { - Err(anyhow::format_err!( - "Transactions mortality {} is not a power of two in a [4; 65536] range", - transactions_mortality, - )) - } else { - Ok(transactions_mortality) - } - }) - .transpose() - } - - /// Parse signing params into chain-specific KeyPair. - #[allow(dead_code)] - pub fn to_keypair(&self) -> anyhow::Result> { - let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { - (Some(suri), _) => suri.to_owned(), - (None, Some(suri_file)) => std::fs::read_to_string(suri_file) - .map_err(|err| anyhow::format_err!( - "Failed to read SURI from file {:?}: {}", - suri_file, - err, - ))?, - (None, None) => return Err(anyhow::format_err!( - "One of options must be specified: '{}' or '{}'", - stringify!([<$chain_prefix _signer>]), - stringify!([<$chain_prefix _signer_file>]), - )), - }; - - let suri_password = match ( - self.[<$chain_prefix _signer_password>].as_ref(), - self.[<$chain_prefix _signer_password_file>].as_ref(), - ) { - (Some(suri_password), _) => Some(suri_password.to_owned()), - (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) - .map(Some) - .map_err(|err| anyhow::format_err!( - "Failed to read SURI password from file {:?}: {}", - suri_password_file, - err, - ))?, - _ => None, - }; - - use sp_core::crypto::Pair; - - AccountKeyPairOf::::from_string( - &suri, - suri_password.as_deref() - ).map_err(|e| anyhow::format_err!("{:?}", e)) - } - - /// Return transaction parameters. - #[allow(dead_code)] - pub fn transaction_params( - &self, - ) -> anyhow::Result>> { - Ok(TransactionParams { - mortality: self.transactions_mortality()?, - signer: self.to_keypair::()?, - }) - } - } - } - }; -} - -/// Create chain-specific set of configuration objects: connection parameters, -/// signing parameters and bridge initialization parameters. -#[macro_export] -macro_rules! declare_chain_cli_schema { - ($chain:ident, $chain_prefix:ident) => { - $crate::declare_chain_runtime_version_params_cli_schema!($chain, $chain_prefix); - $crate::declare_chain_connection_params_cli_schema!($chain, $chain_prefix); - $crate::declare_chain_signing_params_cli_schema!($chain, $chain_prefix); - }; -} - -declare_chain_cli_schema!(Source, source); -declare_chain_cli_schema!(Target, target); -declare_chain_cli_schema!(Relaychain, relaychain); -declare_chain_cli_schema!(Parachain, parachain); - #[cfg(test)] mod tests { - use super::*; use sp_core::Pair; + use substrate_relay_helper::cli::chain_schema::TargetSigningParams; #[test] fn reads_suri_from_file() { diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs index a8f1ed35f3afb..7717b50153754 100644 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ b/relays/bin-substrate/src/cli/detect_equivocations.rs @@ -14,25 +14,23 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::{ - bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - rococo_westend::{ - rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, - westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, - }, +use crate::bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, + rococo_westend::{ + rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, + westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, }, - cli::{bridge::*, chain_schema::*, PrometheusParams}, }; -use async_trait::async_trait; -use relay_substrate_client::ChainWithTransactions; use structopt::StructOpt; use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{equivocation, equivocation::SubstrateEquivocationDetectionPipeline}; + +use substrate_relay_helper::cli::detect_equivocations::{ + DetectEquivocationsParams, EquivocationsDetector, +}; /// Start equivocation detection loop. #[derive(StructOpt)] @@ -40,13 +38,7 @@ pub struct DetectEquivocations { #[structopt(possible_values = DetectEquivocationsBridge::VARIANTS, case_insensitive = true)] bridge: DetectEquivocationsBridge, #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, + params: DetectEquivocationsParams, } #[derive(Debug, EnumString, VariantNames)] @@ -59,29 +51,6 @@ pub enum DetectEquivocationsBridge { WestendToBridgeHubRococo, } -#[async_trait] -trait EquivocationsDetector: RelayToRelayEquivocationDetectionCliBridge -where - Self::Source: ChainWithTransactions, -{ - async fn start(data: DetectEquivocations) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - Self::Equivocation::start_relay_guards( - &source_client, - source_client.can_start_version_guard(), - ) - .await?; - - equivocation::run::( - source_client, - data.target.into_client::().await?, - data.source_sign.transaction_params::()?, - data.prometheus_params.into_metrics_params()?, - ) - .await - } -} - impl EquivocationsDetector for KusamaToBridgeHubPolkadotCliBridge {} impl EquivocationsDetector for PolkadotToBridgeHubKusamaCliBridge {} impl EquivocationsDetector for RococoToBridgeHubWestendCliBridge {} @@ -92,13 +61,13 @@ impl DetectEquivocations { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { DetectEquivocationsBridge::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::start(self), + KusamaToBridgeHubPolkadotCliBridge::start(self.params), DetectEquivocationsBridge::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::start(self), + PolkadotToBridgeHubKusamaCliBridge::start(self.params), DetectEquivocationsBridge::RococoToBridgeHubWestend => - RococoToBridgeHubWestendCliBridge::start(self), + RococoToBridgeHubWestendCliBridge::start(self.params), DetectEquivocationsBridge::WestendToBridgeHubRococo => - WestendToBridgeHubRococoCliBridge::start(self), + WestendToBridgeHubRococoCliBridge::start(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs index 0b2f9aa7e1ec7..441487b35a966 100644 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ b/relays/bin-substrate/src/cli/init_bridge.rs @@ -14,107 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use async_trait::async_trait; -use codec::Encode; - -use crate::{ - bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::{ - polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, - polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - }, - rococo_bulletin::{ - rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, - rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - }, - rococo_westend::{ - rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, - westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, - }, +use crate::bridges::{ + kusama_polkadot::{ + kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, + polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, + }, + polkadot_bulletin::{ + polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, + polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, + }, + rococo_bulletin::{ + rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, + rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, + }, + rococo_westend::{ + rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, + westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, }, - cli::{bridge::CliBridgeBase, chain_schema::*}, }; -use bp_runtime::Chain as ChainBase; -use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; -use sp_core::Pair; +use relay_substrate_client::Chain; use structopt::StructOpt; use strum::{EnumString, VariantNames}; -use substrate_relay_helper::finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}; - -/// Initialize bridge pallet. -#[derive(StructOpt)] -pub struct InitBridge { - /// A bridge instance to initialize. - #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] - bridge: InitBridgeName, - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - /// Generates all required data, but does not submit extrinsic - #[structopt(long)] - dry_run: bool, -} - -#[derive(Debug, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Bridge to initialize. -pub enum InitBridgeName { - KusamaToBridgeHubPolkadot, - PolkadotToBridgeHubKusama, - PolkadotToPolkadotBulletin, - PolkadotBulletinToBridgeHubPolkadot, - RococoToRococoBulletin, - RococoBulletinToBridgeHubRococo, - RococoToBridgeHubWestend, - WestendToBridgeHubRococo, -} - -#[async_trait] -trait BridgeInitializer: CliBridgeBase -where - ::AccountId: From< as Pair>::Public>, -{ - type Engine: Engine; - - /// Get the encoded call to init the bridge. - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call; - - /// Initialize the bridge. - async fn init_bridge(data: InitBridge) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let target_client = data.target.into_client::().await?; - let target_sign = data.target_sign.to_keypair::()?; - let dry_run = data.dry_run; - - substrate_relay_helper::finality::initialize::initialize::( - source_client, - target_client.clone(), - target_sign, - move |transaction_nonce, initialization_data| { - let call = Self::encode_init_bridge(initialization_data); - log::info!( - target: "bridge", - "Initialize bridge call encoded as hex string: {:?}", - format!("0x{}", hex::encode(call.encode())) - ); - Ok(UnsignedTransaction::new(call.into(), transaction_nonce)) - }, - dry_run, - ) - .await; - - Ok(()) - } -} +use substrate_relay_helper::{ + cli::init_bridge::{BridgeInitializer, InitBridgeParams}, + finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}, +}; impl BridgeInitializer for RococoToBridgeHubWestendCliBridge { type Engine = GrandpaFinalityEngine; @@ -225,26 +149,50 @@ impl BridgeInitializer for RococoBulletinToBridgeHubRococoCliBridge { } } +/// Initialize bridge pallet. +#[derive(StructOpt)] +pub struct InitBridge { + /// A bridge instance to initialize. + #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] + bridge: InitBridgeName, + #[structopt(flatten)] + params: InitBridgeParams, +} + +#[derive(Debug, EnumString, VariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Bridge to initialize. +pub enum InitBridgeName { + KusamaToBridgeHubPolkadot, + PolkadotToBridgeHubKusama, + PolkadotToPolkadotBulletin, + PolkadotBulletinToBridgeHubPolkadot, + RococoToRococoBulletin, + RococoBulletinToBridgeHubRococo, + RococoToBridgeHubWestend, + WestendToBridgeHubRococo, +} + impl InitBridge { /// Run the command. pub async fn run(self) -> anyhow::Result<()> { match self.bridge { InitBridgeName::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::init_bridge(self), + KusamaToBridgeHubPolkadotCliBridge::init_bridge(self.params), InitBridgeName::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::init_bridge(self), + PolkadotToBridgeHubKusamaCliBridge::init_bridge(self.params), InitBridgeName::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::init_bridge(self), + PolkadotToPolkadotBulletinCliBridge::init_bridge(self.params), InitBridgeName::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self), + PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self.params), InitBridgeName::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::init_bridge(self), + RococoToRococoBulletinCliBridge::init_bridge(self.params), InitBridgeName::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoCliBridge::init_bridge(self), + RococoBulletinToBridgeHubRococoCliBridge::init_bridge(self.params), InitBridgeName::RococoToBridgeHubWestend => - RococoToBridgeHubWestendCliBridge::init_bridge(self), + RococoToBridgeHubWestendCliBridge::init_bridge(self.params), InitBridgeName::WestendToBridgeHubRococo => - WestendToBridgeHubRococoCliBridge::init_bridge(self), + WestendToBridgeHubRococoCliBridge::init_bridge(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs index 6d799023cdbc0..504058894c21f 100644 --- a/relays/bin-substrate/src/cli/mod.rs +++ b/relays/bin-substrate/src/cli/mod.rs @@ -17,18 +17,10 @@ //! Deal with CLI args of substrate-to-substrate relay. use async_std::prelude::*; -use codec::{Decode, Encode}; use futures::{select, FutureExt}; -use rbtag::BuildInfo; use signal_hook::consts::*; use signal_hook_async_std::Signals; -use structopt::{clap::arg_enum, StructOpt}; -use strum::{EnumString, VariantNames}; - -use bp_messages::LaneId; -use relay_substrate_client::SimpleRuntimeVersion; - -pub(crate) mod bridge; +use structopt::StructOpt; mod chain_schema; mod detect_equivocations; @@ -50,11 +42,17 @@ pub fn parse_args() -> Command { #[derive(StructOpt)] #[structopt(about = "Substrate-to-Substrate relay")] pub enum Command { + /// Initialize on-chain bridge pallet with current header data. + /// + /// Sends initialization transaction to bootstrap the bridge with current finalized block data. + InitBridge(init_bridge::InitBridge), /// Start headers relay between two chains. /// /// The on-chain bridge component should have been already initialized with /// `init-bridge` sub-command. RelayHeaders(relay_headers::RelayHeaders), + /// Relay parachain heads. + RelayParachains(relay_parachains::RelayParachains), /// Start messages relay between two chains. /// /// Ties up to `Messages` pallets on both chains and starts relaying messages. @@ -67,12 +65,6 @@ pub enum Command { /// the message relays - i.e. when there are messages or confirmations that needs to be /// relayed between chains. RelayHeadersAndMessages(Box), - /// Initialize on-chain bridge pallet with current header data. - /// - /// Sends initialization transaction to bootstrap the bridge with current finalized block data. - InitBridge(init_bridge::InitBridge), - /// Relay parachain heads. - RelayParachains(relay_parachains::RelayParachains), /// Detect and report equivocations. /// /// Parses the source chain headers that were synchronized with the target chain looking for @@ -86,10 +78,10 @@ impl Command { use relay_utils::initialize::{initialize_logger, initialize_relay}; match self { + Self::InitBridge(_) | Self::RelayHeaders(_) | Self::RelayMessages(_) | - Self::RelayHeadersAndMessages(_) | - Self::InitBridge(_) => { + Self::RelayHeadersAndMessages(_) => { initialize_relay(); }, _ => { @@ -101,11 +93,11 @@ impl Command { /// Run the command. async fn do_run(self) -> anyhow::Result<()> { match self { + Self::InitBridge(arg) => arg.run().await?, Self::RelayHeaders(arg) => arg.run().await?, + Self::RelayParachains(arg) => arg.run().await?, Self::RelayMessages(arg) => arg.run().await?, Self::RelayHeadersAndMessages(arg) => arg.run().await?, - Self::InitBridge(arg) => arg.run().await?, - Self::RelayParachains(arg) => arg.run().await?, Self::DetectEquivocations(arg) => arg.run().await?, } Ok(()) @@ -137,181 +129,3 @@ impl Command { } } } - -arg_enum! { - #[derive(Debug)] - /// The origin to use when dispatching the message on the target chain. - /// - /// - `Target` uses account existing on the target chain (requires target private key). - /// - `Origin` uses account derived from the source-chain account. - pub enum Origins { - Target, - Source, - } -} - -/// Bridge-supported network definition. -/// -/// Used to abstract away CLI commands. -pub trait CliChain: relay_substrate_client::Chain { - /// Current version of the chain runtime, known to relay. - /// - /// can be `None` if relay is not going to submit transactions to that chain. - const RUNTIME_VERSION: Option; -} - -/// Lane id. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct HexLaneId(pub [u8; 4]); - -impl From for LaneId { - fn from(lane_id: HexLaneId) -> LaneId { - LaneId(lane_id.0) - } -} - -impl std::str::FromStr for HexLaneId { - type Err = hex::FromHexError; - - fn from_str(s: &str) -> Result { - let mut lane_id = [0u8; 4]; - hex::decode_to_slice(s, &mut lane_id)?; - Ok(HexLaneId(lane_id)) - } -} - -/// Nicer formatting for raw bytes vectors. -#[derive(Default, Encode, Decode, PartialEq, Eq)] -pub struct HexBytes(pub Vec); - -impl std::str::FromStr for HexBytes { - type Err = hex::FromHexError; - - fn from_str(s: &str) -> Result { - Ok(Self(hex::decode(s)?)) - } -} - -impl std::fmt::Debug for HexBytes { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "0x{self}") - } -} - -impl std::fmt::Display for HexBytes { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(fmt, "{}", hex::encode(&self.0)) - } -} - -/// Prometheus metrics params. -#[derive(Clone, Debug, PartialEq, StructOpt)] -pub struct PrometheusParams { - /// Do not expose a Prometheus metric endpoint. - #[structopt(long)] - pub no_prometheus: bool, - /// Expose Prometheus endpoint at given interface. - #[structopt(long, default_value = "127.0.0.1")] - pub prometheus_host: String, - /// Expose Prometheus endpoint at given port. - #[structopt(long, default_value = "9616")] - pub prometheus_port: u16, -} - -/// Struct to get git commit info and build time. -#[derive(BuildInfo)] -struct SubstrateRelayBuildInfo; - -impl SubstrateRelayBuildInfo { - /// Get git commit in form ``. - pub fn get_git_commit() -> String { - // on gitlab we use images without git installed, so we can't use `rbtag` there - // locally we don't have `CI_*` env variables, so we can't rely on them - // => we are using `CI_*` env variables or else `rbtag` - let maybe_sha_from_ci = option_env!("CI_COMMIT_SHORT_SHA"); - maybe_sha_from_ci - .map(|short_sha| { - // we assume that on CI the copy is always clean - format!("{short_sha}-clean") - }) - .unwrap_or_else(|| SubstrateRelayBuildInfo.get_build_commit().into()) - } -} - -impl PrometheusParams { - /// Tries to convert CLI metrics params into metrics params, used by the relay. - pub fn into_metrics_params(self) -> anyhow::Result { - let metrics_address = if !self.no_prometheus { - Some(relay_utils::metrics::MetricsAddress { - host: self.prometheus_host, - port: self.prometheus_port, - }) - } else { - None - }; - - let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); - let relay_commit = SubstrateRelayBuildInfo::get_git_commit(); - relay_utils::metrics::MetricsParams::new( - metrics_address, - relay_version.into(), - relay_commit, - ) - .map_err(|e| anyhow::format_err!("{:?}", e)) - } -} - -/// Either explicit or maximal allowed value. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ExplicitOrMaximal { - /// User has explicitly specified argument value. - Explicit(V), - /// Maximal allowed value for this argument. - Maximal, -} - -impl std::str::FromStr for ExplicitOrMaximal -where - V::Err: std::fmt::Debug, -{ - type Err = String; - - fn from_str(s: &str) -> Result { - if s.to_lowercase() == "max" { - return Ok(ExplicitOrMaximal::Maximal) - } - - V::from_str(s) - .map(ExplicitOrMaximal::Explicit) - .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'max' or explicit value")) - } -} - -#[doc = "Runtime version params."] -#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] -pub enum RuntimeVersionType { - /// Auto query version from chain - Auto, - /// Custom `spec_version` and `transaction_version` - Custom, - /// Read version from bundle dependencies directly. - Bundle, -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn hex_bytes_display_matches_from_str_for_clap() { - // given - let hex = HexBytes(vec![1, 2, 3, 4]); - let display = format!("{hex}"); - - // when - let hex2: HexBytes = display.parse().unwrap(); - - // then - assert_eq!(hex.0, hex2.0); - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs index a3b5c4c9f82dd..e244d0e9a248f 100644 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ b/relays/bin-substrate/src/cli/relay_headers.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use async_trait::async_trait; use structopt::StructOpt; use strum::{EnumString, VariantNames}; @@ -32,10 +31,8 @@ use crate::bridges::{ rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, }, }; -use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; -use substrate_relay_helper::finality::SubstrateFinalitySyncPipeline; -use crate::cli::{bridge::*, chain_schema::*, PrometheusParams}; +use substrate_relay_helper::cli::relay_headers::{HeadersRelayer, RelayHeadersParams}; /// Start headers relayer process. #[derive(StructOpt)] @@ -43,18 +40,8 @@ pub struct RelayHeaders { /// A bridge instance to relay headers for. #[structopt(possible_values = RelayHeadersBridge::VARIANTS, case_insensitive = true)] bridge: RelayHeadersBridge, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) - /// are relayed. - #[structopt(long)] - only_mandatory_headers: bool, #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, + params: RelayHeadersParams, } #[derive(Debug, EnumString, VariantNames)] @@ -69,37 +56,6 @@ pub enum RelayHeadersBridge { RococoBulletinToBridgeHubRococo, } -#[async_trait] -trait HeadersRelayer: RelayToRelayHeadersCliBridge { - /// Relay headers. - async fn relay_headers(data: RelayHeaders) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let target_client = data.target.into_client::().await?; - let target_transactions_mortality = data.target_sign.target_transactions_mortality; - let target_sign = data.target_sign.to_keypair::()?; - - let metrics_params: relay_utils::metrics::MetricsParams = - data.prometheus_params.into_metrics_params()?; - GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - - let target_transactions_params = substrate_relay_helper::TransactionParams { - signer: target_sign, - mortality: target_transactions_mortality, - }; - Self::Finality::start_relay_guards(&target_client, target_client.can_start_version_guard()) - .await?; - - substrate_relay_helper::finality::run::( - source_client, - target_client, - data.only_mandatory_headers, - target_transactions_params, - metrics_params, - ) - .await - } -} - impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} impl HeadersRelayer for PolkadotToPolkadotBulletinCliBridge {} @@ -112,17 +68,17 @@ impl RelayHeaders { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { RelayHeadersBridge::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::relay_headers(self), + KusamaToBridgeHubPolkadotCliBridge::relay_headers(self.params), RelayHeadersBridge::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::relay_headers(self), + PolkadotToBridgeHubKusamaCliBridge::relay_headers(self.params), RelayHeadersBridge::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::relay_headers(self), + PolkadotToPolkadotBulletinCliBridge::relay_headers(self.params), RelayHeadersBridge::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self), + PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self.params), RelayHeadersBridge::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::relay_headers(self), + RococoToRococoBulletinCliBridge::relay_headers(self.params), RelayHeadersBridge::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoCliBridge::relay_headers(self), + RococoBulletinToBridgeHubRococoCliBridge::relay_headers(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs similarity index 52% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs rename to relays/bin-substrate/src/cli/relay_headers_and_messages.rs index c445bdddcc936..229661748ed6b 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -23,176 +23,48 @@ //! `declare_chain_to_parachain_bridge_schema` for the bridge. //! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it. -#[macro_use] -mod parachain_to_parachain; -#[macro_use] -mod relay_to_relay; -#[macro_use] -mod relay_to_parachain; - use async_trait::async_trait; -use std::{marker::PhantomData, sync::Arc}; use structopt::StructOpt; -use futures::{FutureExt, TryFutureExt}; -use relay_to_parachain::*; - -use crate::{ - bridges::{ - kusama_polkadot::{ - kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, - polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::{ - polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, - polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - }, - rococo_bulletin::{ - rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, - rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - BridgeHubRococoAsBridgeHubPolkadot, - }, - rococo_westend::{ - rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, - westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, - }, +use crate::bridges::{ + kusama_polkadot::{ + kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, + polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, + }, + polkadot_bulletin::{ + polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, + polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, }, + rococo_bulletin::{ + rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, + rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, + BridgeHubRococoAsBridgeHubPolkadot, + }, + rococo_westend::{ + rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, + westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, + }, +}; +use relay_substrate_client::{ + AccountKeyPairOf, ChainRuntimeVersion, ChainWithRuntimeVersion, ChainWithTransactions, + Parachain, SimpleRuntimeVersion, +}; +use substrate_relay_helper::{ cli::{ bridge::{ CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, RelayToRelayHeadersCliBridge, }, chain_schema::*, - relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge, - CliChain, HexLaneId, PrometheusParams, + relay_headers_and_messages::{ + parachain_to_parachain::ParachainToParachainBridge, relay_to_parachain::*, + BridgeEndCommonParams, Full2WayBridge, Full2WayBridgeCommonParams, + HeadersAndMessagesSharedParams, + }, }, - declare_chain_cli_schema, + declare_chain_cli_schema, declare_parachain_to_parachain_bridge_schema, + declare_relay_to_parachain_bridge_schema, TransactionParams, }; -use bp_messages::LaneId; -use bp_runtime::BalanceOf; -use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, Client, Parachain, -}; -use relay_utils::metrics::MetricsParams; -use sp_core::Pair; -use substrate_relay_helper::{ - messages_lane::{MessagesRelayLimits, MessagesRelayParams}, - on_demand::OnDemandRelay, - TaggedAccount, TransactionParams, -}; - -/// Parameters that have the same names across all bridges. -#[derive(Debug, PartialEq, StructOpt)] -pub struct HeadersAndMessagesSharedParams { - /// Hex-encoded lane identifiers that should be served by the complex relay. - #[structopt(long, default_value = "00000000")] - pub lane: Vec, - /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) - /// are relayed. - #[structopt(long)] - pub only_mandatory_headers: bool, - #[structopt(flatten)] - pub prometheus_params: PrometheusParams, -} - -/// Bridge parameters, shared by all bridge types. -pub struct Full2WayBridgeCommonParams< - Left: ChainWithTransactions + CliChain, - Right: ChainWithTransactions + CliChain, -> { - /// Shared parameters. - pub shared: HeadersAndMessagesSharedParams, - /// Parameters of the left chain. - pub left: BridgeEndCommonParams, - /// Parameters of the right chain. - pub right: BridgeEndCommonParams, - - /// Common metric parameters. - pub metrics_params: MetricsParams, -} - -impl - Full2WayBridgeCommonParams -{ - /// Creates new bridge parameters from its components. - pub fn new>( - shared: HeadersAndMessagesSharedParams, - left: BridgeEndCommonParams, - right: BridgeEndCommonParams, - ) -> anyhow::Result { - // Create metrics registry. - let metrics_params = shared.prometheus_params.clone().into_metrics_params()?; - let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); - - Ok(Self { shared, left, right, metrics_params }) - } -} - -/// Parameters that are associated with one side of the bridge. -pub struct BridgeEndCommonParams { - /// Chain client. - pub client: Client, - /// Params used for sending transactions to the chain. - pub tx_params: TransactionParams>, - /// Accounts, which balances are exposed as metrics by the relay process. - pub accounts: Vec>>, -} - -/// All data of the bidirectional complex relay. -struct FullBridge< - 'a, - Source: ChainWithTransactions + CliChain, - Target: ChainWithTransactions + CliChain, - Bridge: MessagesCliBridge, -> { - source: &'a mut BridgeEndCommonParams, - target: &'a mut BridgeEndCommonParams, - metrics_params: &'a MetricsParams, - _phantom_data: PhantomData, -} - -impl< - 'a, - Source: ChainWithTransactions + CliChain, - Target: ChainWithTransactions + CliChain, - Bridge: MessagesCliBridge, - > FullBridge<'a, Source, Target, Bridge> -where - AccountIdOf: From< as Pair>::Public>, - AccountIdOf: From< as Pair>::Public>, - BalanceOf: TryFrom> + Into, -{ - /// Construct complex relay given it components. - fn new( - source: &'a mut BridgeEndCommonParams, - target: &'a mut BridgeEndCommonParams, - metrics_params: &'a MetricsParams, - ) -> Self { - Self { source, target, metrics_params, _phantom_data: Default::default() } - } - - /// Returns message relay parameters. - fn messages_relay_params( - &self, - source_to_target_headers_relay: Arc>, - target_to_source_headers_relay: Arc>, - lane_id: LaneId, - maybe_limits: Option, - ) -> MessagesRelayParams { - MessagesRelayParams { - source_client: self.source.client.clone(), - source_transaction_params: self.source.tx_params.clone(), - target_client: self.target.client.clone(), - target_transaction_params: self.target.tx_params.clone(), - source_to_target_headers_relay: Some(source_to_target_headers_relay), - target_to_source_headers_relay: Some(target_to_source_headers_relay), - lane_id, - limits: maybe_limits, - metrics_params: self.metrics_params.clone().disable(), - } - } -} // All supported chains. declare_chain_cli_schema!(Rococo, rococo); @@ -247,171 +119,6 @@ declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHub declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); declare_relay_to_parachain_bridge_schema!(RococoBulletin, BridgeHubRococo, Rococo); -/// Base portion of the bidirectional complex relay. -/// -/// This main purpose of extracting this trait is that in different relays the implementation -/// of `start_on_demand_headers_relayers` method will be different. But the number of -/// implementations is limited to relay <> relay, parachain <> relay and parachain <> parachain. -/// This trait allows us to reuse these implementations in different bridges. -#[async_trait] -trait Full2WayBridgeBase: Sized + Send + Sync { - /// The CLI params for the bridge. - type Params; - /// The left relay chain. - type Left: ChainWithTransactions + CliChain; - /// The right destination chain (it can be a relay or a parachain). - type Right: ChainWithTransactions + CliChain; - - /// Reference to common relay parameters. - fn common(&self) -> &Full2WayBridgeCommonParams; - - /// Mutable reference to common relay parameters. - fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams; - - /// Start on-demand headers relays. - async fn start_on_demand_headers_relayers( - &mut self, - ) -> anyhow::Result<( - Arc>, - Arc>, - )>; -} - -/// Bidirectional complex relay. -#[async_trait] -trait Full2WayBridge: Sized + Sync -where - AccountIdOf: From< as Pair>::Public>, - AccountIdOf: From< as Pair>::Public>, - BalanceOf: TryFrom> + Into, - BalanceOf: TryFrom> + Into, -{ - /// Base portion of the bidirectional complex relay. - type Base: Full2WayBridgeBase; - - /// The left relay chain. - type Left: ChainWithTransactions + ChainWithBalances + ChainWithMessages + CliChain; - /// The right relay chain. - type Right: ChainWithTransactions + ChainWithBalances + ChainWithMessages + CliChain; - - /// Left to Right bridge. - type L2R: MessagesCliBridge; - /// Right to Left bridge - type R2L: MessagesCliBridge; - - /// Construct new bridge. - fn new(params: ::Params) -> anyhow::Result; - - /// Reference to the base relay portion. - fn base(&self) -> &Self::Base; - - /// Mutable reference to the base relay portion. - fn mut_base(&mut self) -> &mut Self::Base; - - /// Creates and returns Left to Right complex relay. - fn left_to_right(&mut self) -> FullBridge { - let common = self.mut_base().mut_common(); - FullBridge::<_, _, Self::L2R>::new( - &mut common.left, - &mut common.right, - &common.metrics_params, - ) - } - - /// Creates and returns Right to Left complex relay. - fn right_to_left(&mut self) -> FullBridge { - let common = self.mut_base().mut_common(); - FullBridge::<_, _, Self::R2L>::new( - &mut common.right, - &mut common.left, - &common.metrics_params, - ) - } - - /// Start complex relay. - async fn run(&mut self) -> anyhow::Result<()> { - // Register standalone metrics. - { - let common = self.mut_base().mut_common(); - common.left.accounts.push(TaggedAccount::Messages { - id: common.left.tx_params.signer.public().into(), - bridged_chain: Self::Right::NAME.to_string(), - }); - common.right.accounts.push(TaggedAccount::Messages { - id: common.right.tx_params.signer.public().into(), - bridged_chain: Self::Left::NAME.to_string(), - }); - } - - // start on-demand header relays - let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = - self.mut_base().start_on_demand_headers_relayers().await?; - - // add balance-related metrics - let lanes = self - .base() - .common() - .shared - .lane - .iter() - .cloned() - .map(Into::into) - .collect::>(); - { - let common = self.mut_base().mut_common(); - substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Right>( - common.left.client.clone(), - &common.metrics_params, - &common.left.accounts, - &lanes, - ) - .await?; - substrate_relay_helper::messages_metrics::add_relay_balances_metrics::<_, Self::Left>( - common.right.client.clone(), - &common.metrics_params, - &common.right.accounts, - &lanes, - ) - .await?; - } - - // Need 2x capacity since we consider both directions for each lane - let mut message_relays = Vec::with_capacity(lanes.len() * 2); - for lane in lanes { - let left_to_right_messages = substrate_relay_helper::messages_lane::run::< - ::MessagesLane, - >(self.left_to_right().messages_relay_params( - left_to_right_on_demand_headers.clone(), - right_to_left_on_demand_headers.clone(), - lane, - Self::L2R::maybe_messages_limits(), - )) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - message_relays.push(left_to_right_messages); - - let right_to_left_messages = substrate_relay_helper::messages_lane::run::< - ::MessagesLane, - >(self.right_to_left().messages_relay_params( - right_to_left_on_demand_headers.clone(), - left_to_right_on_demand_headers.clone(), - lane, - Self::R2L::maybe_messages_limits(), - )) - .map_err(|e| anyhow::format_err!("{}", e)) - .boxed(); - message_relays.push(right_to_left_messages); - } - - relay_utils::relay_metrics(self.base().common().metrics_params.clone()) - .expose() - .await - .map_err(|e| anyhow::format_err!("{}", e))?; - - futures::future::select_all(message_relays).await.0 - } -} - /// BridgeHubRococo <> BridgeHubWestend complex relay. pub struct BridgeHubRococoBridgeHubWestendFull2WayBridge { base: ::Base, @@ -556,6 +263,7 @@ impl RelayHeadersAndMessages { #[cfg(test)] mod tests { use super::*; + use substrate_relay_helper::cli::{HexLaneId, PrometheusParams}; #[test] fn should_parse_parachain_to_parachain_options() { diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs index b20725b53c743..92b98f4d983a3 100644 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ b/relays/bin-substrate/src/cli/relay_messages.rs @@ -14,10 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use async_trait::async_trait; -use sp_core::Pair; use structopt::StructOpt; -use strum::VariantNames; +use strum::{EnumString, VariantNames}; use crate::bridges::{ kusama_polkadot::{ @@ -37,10 +35,21 @@ use crate::bridges::{ bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, }, }; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithTransactions}; -use substrate_relay_helper::{messages_lane::MessagesRelayParams, TransactionParams}; +use substrate_relay_helper::cli::relay_messages::{MessagesRelayer, RelayMessagesParams}; -use crate::cli::{bridge::*, chain_schema::*, CliChain, HexLaneId, PrometheusParams}; +#[derive(Debug, PartialEq, Eq, EnumString, VariantNames)] +#[strum(serialize_all = "kebab_case")] +/// Supported full bridges (headers + messages). +pub enum FullBridge { + BridgeHubRococoToBridgeHubWestend, + BridgeHubWestendToBridgeHubRococo, + BridgeHubKusamaToBridgeHubPolkadot, + BridgeHubPolkadotToBridgeHubKusama, + PolkadotBulletinToBridgeHubPolkadot, + BridgeHubPolkadotToPolkadotBulletin, + RococoBulletinToBridgeHubRococo, + BridgeHubRococoToRococoBulletin, +} /// Start messages relayer process. #[derive(StructOpt)] @@ -48,57 +57,8 @@ pub struct RelayMessages { /// A bridge instance to relay messages for. #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] bridge: FullBridge, - /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. - #[structopt(long, default_value = "00000000")] - lane: HexLaneId, - #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - source_sign: SourceSigningParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, #[structopt(flatten)] - prometheus_params: PrometheusParams, -} - -#[async_trait] -trait MessagesRelayer: MessagesCliBridge -where - Self::Source: ChainWithTransactions + CliChain, - AccountIdOf: From< as Pair>::Public>, - AccountIdOf: From< as Pair>::Public>, - BalanceOf: TryFrom>, -{ - async fn relay_messages(data: RelayMessages) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let source_sign = data.source_sign.to_keypair::()?; - let source_transactions_mortality = data.source_sign.transactions_mortality()?; - let target_client = data.target.into_client::().await?; - let target_sign = data.target_sign.to_keypair::()?; - let target_transactions_mortality = data.target_sign.transactions_mortality()?; - - substrate_relay_helper::messages_lane::run::(MessagesRelayParams { - source_client, - source_transaction_params: TransactionParams { - signer: source_sign, - mortality: source_transactions_mortality, - }, - target_client, - target_transaction_params: TransactionParams { - signer: target_sign, - mortality: target_transactions_mortality, - }, - source_to_target_headers_relay: None, - target_to_source_headers_relay: None, - lane_id: data.lane.into(), - limits: Self::maybe_messages_limits(), - metrics_params: data.prometheus_params.into_metrics_params()?, - }) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - } + params: RelayMessagesParams, } impl MessagesRelayer for BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} @@ -115,21 +75,21 @@ impl RelayMessages { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { FullBridge::BridgeHubRococoToBridgeHubWestend => - BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self), + BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubWestendToBridgeHubRococo => - BridgeHubWestendToBridgeHubRococoMessagesCliBridge::relay_messages(self), + BridgeHubWestendToBridgeHubRococoMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubKusamaToBridgeHubPolkadot => - BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), + BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubPolkadotToBridgeHubKusama => - BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self), + BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self.params), FullBridge::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self), + PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubPolkadotToPolkadotBulletin => - BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self), + BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self.params), FullBridge::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoMessagesCliBridge::relay_messages(self), + RococoBulletinToBridgeHubRococoMessagesCliBridge::relay_messages(self.params), FullBridge::BridgeHubRococoToRococoBulletin => - BridgeHubRococoToRococoBulletinMessagesCliBridge::relay_messages(self), + BridgeHubRococoToRococoBulletinMessagesCliBridge::relay_messages(self.params), } .await } diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs index dc1c5ad362f42..65382d1ca11b9 100644 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ b/relays/bin-substrate/src/cli/relay_parachains.rs @@ -26,24 +26,9 @@ use crate::bridges::{ westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, }, }; -use async_std::sync::Mutex; -use async_trait::async_trait; -use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; -use relay_substrate_client::Parachain; -use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; -use std::sync::Arc; use structopt::StructOpt; use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{ - parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, - TransactionParams, -}; - -use crate::cli::{ - bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}, - chain_schema::*, - PrometheusParams, -}; +use substrate_relay_helper::cli::relay_parachains::{ParachainsRelayer, RelayParachainsParams}; /// Start parachain heads relayer process. #[derive(StructOpt)] @@ -52,13 +37,7 @@ pub struct RelayParachains { #[structopt(possible_values = RelayParachainsBridge::VARIANTS, case_insensitive = true)] bridge: RelayParachainsBridge, #[structopt(flatten)] - source: SourceConnectionParams, - #[structopt(flatten)] - target: TargetConnectionParams, - #[structopt(flatten)] - target_sign: TargetSigningParams, - #[structopt(flatten)] - prometheus_params: PrometheusParams, + params: RelayParachainsParams, } /// Parachain heads relay bridge. @@ -73,47 +52,6 @@ pub enum RelayParachainsBridge { WestendToBridgeHubRococo, } -#[async_trait] -trait ParachainsRelayer: ParachainToRelayHeadersCliBridge -where - ParachainsSource: - SourceClient>, - ParachainsTarget: - TargetClient>, - ::Source: Parachain, -{ - async fn relay_parachains(data: RelayParachains) -> anyhow::Result<()> { - let source_client = data.source.into_client::().await?; - let source_client = ParachainsSource::::new( - source_client, - Arc::new(Mutex::new(AvailableHeader::Missing)), - ); - - let target_transaction_params = TransactionParams { - signer: data.target_sign.to_keypair::()?, - mortality: data.target_sign.target_transactions_mortality, - }; - let target_client = data.target.into_client::().await?; - let target_client = ParachainsTarget::::new( - target_client.clone(), - target_transaction_params, - ); - - let metrics_params: relay_utils::metrics::MetricsParams = - data.prometheus_params.into_metrics_params()?; - GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; - - parachains_relay::parachains_loop::run( - source_client, - target_client, - metrics_params, - futures::future::pending(), - ) - .await - .map_err(|e| anyhow::format_err!("{}", e)) - } -} - impl ParachainsRelayer for BridgeHubRococoToBridgeHubWestendCliBridge {} impl ParachainsRelayer for BridgeHubWestendToBridgeHubRococoCliBridge {} impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} @@ -126,17 +64,17 @@ impl RelayParachains { pub async fn run(self) -> anyhow::Result<()> { match self.bridge { RelayParachainsBridge::RococoToBridgeHubWestend => - BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self), + BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self.params), RelayParachainsBridge::WestendToBridgeHubRococo => - BridgeHubWestendToBridgeHubRococoCliBridge::relay_parachains(self), + BridgeHubWestendToBridgeHubRococoCliBridge::relay_parachains(self.params), RelayParachainsBridge::KusamaToBridgeHubPolkadot => - BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self), + BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self.params), RelayParachainsBridge::PolkadotToBridgeHubKusama => - BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self), + BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self.params), RelayParachainsBridge::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::relay_parachains(self), + PolkadotToPolkadotBulletinCliBridge::relay_parachains(self.params), RelayParachainsBridge::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::relay_parachains(self), + RococoToRococoBulletinCliBridge::relay_parachains(self.params), } .await } diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs index 33a423b076628..214bfa60e24a4 100644 --- a/relays/bin-substrate/src/main.rs +++ b/relays/bin-substrate/src/main.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] mod bridges; -mod chains; mod cli; fn main() { diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index 4ad6d2e2fb7e0..80f621dee302b 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -120,3 +121,8 @@ impl ChainWithMessages for BridgeHubKusama { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubKusama { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 }); +} diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index 8ac6569210aa8..ed147e92d5bd5 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -124,3 +125,8 @@ impl ChainWithMessages for BridgeHubPolkadot { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubPolkadot { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 }); +} diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 7ec58453474a0..169135646d94b 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -122,3 +123,8 @@ impl ChainWithMessages for BridgeHubRococo { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubRococo { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); +} diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs index c6bf1b45dd184..5e4462f863aa1 100644 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -23,8 +23,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, - MockedRuntimeUtilityPallet, SignParam, UnderlyingChainProvider, UnsignedTransaction, + ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, + Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -120,3 +121,8 @@ impl ChainWithMessages for BridgeHubWestend { const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = bp_bridge_hub_westend::FROM_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; } + +impl ChainWithRuntimeVersion for BridgeHubWestend { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); +} diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 0f412284e79e4..a953a383e1290 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -22,8 +22,9 @@ use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Kusama { )) } } + +impl ChainWithRuntimeVersion for Kusama { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); +} diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs index b5bbeda802565..a6cdd8ee675cf 100644 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -21,8 +21,9 @@ mod codegen_runtime; use bp_polkadot_bulletin::POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithRuntimeVersion, + ChainWithTransactions, Error as SubstrateError, SignParam, SimpleRuntimeVersion, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -131,3 +132,8 @@ impl ChainWithTransactions for PolkadotBulletin { )) } } + +impl ChainWithRuntimeVersion for PolkadotBulletin { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 }); +} diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 638e01d1b6ace..af75f0dbb8713 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -22,8 +22,9 @@ use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRAN use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Polkadot { )) } } + +impl ChainWithRuntimeVersion for Polkadot { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); +} diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 7843af241c1db..5fad80d5c9886 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -22,8 +22,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Rococo { )) } } + +impl ChainWithRuntimeVersion for Rococo { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); +} diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index 4f9467ec59daf..2aba5f5674d97 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,6 +16,7 @@ use crate::calls::UtilityCall; +use crate::SimpleRuntimeVersion; use bp_header_chain::ChainWithGrandpa as ChainWithGrandpaBase; use bp_messages::ChainWithMessages as ChainWithMessagesBase; use bp_runtime::{ @@ -58,6 +59,16 @@ pub trait Chain: ChainBase + Clone { type Call: Clone + Codec + Debug + Send + Sync; } +/// Bridge-supported network definition. +/// +/// Used to abstract away CLI commands. +pub trait ChainWithRuntimeVersion: Chain { + /// Current version of the chain runtime, known to relay. + /// + /// can be `None` if relay is not going to submit transactions to that chain. + const RUNTIME_VERSION: Option; +} + /// Substrate-based relay chain that supports parachains. /// /// We assume that the parachains are supported using `runtime_parachains::paras` pallet. diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 84c2ad10cf8f6..6c62b8e1cd548 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -35,9 +35,9 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, - FullRuntimeUtilityPallet, MockedRuntimeUtilityPallet, Parachain, RelayChain, SignParam, - TransactionStatusOf, UnsignedTransaction, UtilityPallet, + ChainWithGrandpa, ChainWithMessages, ChainWithRuntimeVersion, ChainWithTransactions, + ChainWithUtilityPallet, FullRuntimeUtilityPallet, MockedRuntimeUtilityPallet, Parachain, + RelayChain, SignParam, TransactionStatusOf, UnsignedTransaction, UtilityPallet, }, client::{ is_ancient_block, ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 8067f67a2bbd6..737c6c08519e1 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -22,8 +22,9 @@ use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithTransactions, Error as SubstrateError, - RelayChain, SignParam, UnderlyingChainProvider, UnsignedTransaction, + Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, + Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, + UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; @@ -114,3 +115,8 @@ impl ChainWithTransactions for Westend { )) } } + +impl ChainWithRuntimeVersion for Westend { + const RUNTIME_VERSION: Option = + Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); +} diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 161548ac4d5e2..d85e2762a4e33 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -10,14 +10,17 @@ workspace = true [dependencies] anyhow = "1.0" -thiserror = { workspace = true } async-std = "1.9.0" async-trait = "0.1" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" hex = "0.4" -num-traits = "0.2" log = { workspace = true } +num-traits = "0.2" +rbtag = "0.3" +structopt = "0.3" +strum = { version = "0.26.2", features = ["derive"] } +thiserror = { workspace = true } # Bridge dependencies diff --git a/relays/bin-substrate/src/cli/bridge.rs b/relays/lib-substrate-relay/src/cli/bridge.rs similarity index 81% rename from relays/bin-substrate/src/cli/bridge.rs rename to relays/lib-substrate-relay/src/cli/bridge.rs index 9457dfa5c0680..316f59a2b0c86 100644 --- a/relays/bin-substrate/src/cli/bridge.rs +++ b/relays/lib-substrate-relay/src/cli/bridge.rs @@ -14,38 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::cli::CliChain; -use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; -use relay_substrate_client::{Chain, ChainWithTransactions, Parachain, RelayChain}; -use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{ +//! Basic traits for exposing bridges in the CLI. + +use crate::{ equivocation::SubstrateEquivocationDetectionPipeline, finality::SubstrateFinalitySyncPipeline, messages_lane::{MessagesRelayLimits, SubstrateMessageLane}, parachains::SubstrateParachainsPipeline, }; - -#[derive(Debug, PartialEq, Eq, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Supported full bridges (headers + messages). -pub enum FullBridge { - BridgeHubRococoToBridgeHubWestend, - BridgeHubWestendToBridgeHubRococo, - BridgeHubKusamaToBridgeHubPolkadot, - BridgeHubPolkadotToBridgeHubKusama, - PolkadotBulletinToBridgeHubPolkadot, - BridgeHubPolkadotToPolkadotBulletin, - RococoBulletinToBridgeHubRococo, - BridgeHubRococoToRococoBulletin, -} +use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; +use relay_substrate_client::{ + Chain, ChainWithRuntimeVersion, ChainWithTransactions, Parachain, RelayChain, +}; /// Minimal bridge representation that can be used from the CLI. /// It connects a source chain to a target chain. pub trait CliBridgeBase: Sized { /// The source chain. - type Source: Chain + CliChain; + type Source: Chain + ChainWithRuntimeVersion; /// The target chain. - type Target: ChainWithTransactions + CliChain; + type Target: ChainWithTransactions + ChainWithRuntimeVersion; } /// Bridge representation that can be used from the CLI for relaying headers @@ -60,6 +48,7 @@ pub trait RelayToRelayHeadersCliBridge: CliBridgeBase { /// Convenience trait that adds bounds to `CliBridgeBase`. pub trait RelayToRelayEquivocationDetectionCliBridgeBase: CliBridgeBase { + /// The source chain with extra bounds. type BoundedSource: ChainWithTransactions; } @@ -89,10 +78,10 @@ pub trait ParachainToRelayHeadersCliBridge: CliBridgeBase where Self::Source: Parachain, { - // The `CliBridgeBase` type represents the parachain in this situation. - // We need to add an extra type for the relay chain. + /// The `CliBridgeBase` type represents the parachain in this situation. + /// We need to add an extra type for the relay chain. type SourceRelay: Chain - + CliChain + + ChainWithRuntimeVersion + RelayChain; /// Finality proofs synchronization pipeline (source parachain -> target). type ParachainFinality: SubstrateParachainsPipeline< diff --git a/relays/lib-substrate-relay/src/cli/chain_schema.rs b/relays/lib-substrate-relay/src/cli/chain_schema.rs new file mode 100644 index 0000000000000..c5b802173ad94 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/chain_schema.rs @@ -0,0 +1,250 @@ +// Copyright 2019-2022 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 . + +//! Primitives related to chain CLI options. + +use relay_substrate_client::{AccountKeyPairOf, ChainWithTransactions}; +use structopt::StructOpt; +use strum::{EnumString, VariantNames}; + +use relay_substrate_client::{ChainRuntimeVersion, ChainWithRuntimeVersion, SimpleRuntimeVersion}; + +use crate::TransactionParams; + +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + +/// Create chain-specific set of runtime version parameters. +#[macro_export] +macro_rules! declare_chain_runtime_version_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + bp_runtime::paste::item! { + #[doc = $chain " runtime version params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy)] + pub struct [<$chain RuntimeVersionParams>] { + #[doc = "The type of runtime version for chain " $chain] + #[structopt(long, default_value = "Bundle")] + pub [<$chain_prefix _version_mode>]: RuntimeVersionType, + #[doc = "The custom sepc_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _spec_version>]: Option, + #[doc = "The custom transaction_version for chain " $chain] + #[structopt(long)] + pub [<$chain_prefix _transaction_version>]: Option, + } + + impl [<$chain RuntimeVersionParams>] { + /// Converts self into `ChainRuntimeVersion`. + pub fn into_runtime_version( + self, + bundle_runtime_version: Option, + ) -> anyhow::Result { + Ok(match self.[<$chain_prefix _version_mode>] { + RuntimeVersionType::Auto => ChainRuntimeVersion::Auto, + RuntimeVersionType::Custom => { + let custom_spec_version = self.[<$chain_prefix _spec_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-spec-version is required when choose custom mode", stringify!($chain_prefix))))?; + let custom_transaction_version = self.[<$chain_prefix _transaction_version>] + .ok_or_else(|| anyhow::Error::msg(format!("The {}-transaction-version is required when choose custom mode", stringify!($chain_prefix))))?; + ChainRuntimeVersion::Custom( + SimpleRuntimeVersion { + spec_version: custom_spec_version, + transaction_version: custom_transaction_version + } + ) + }, + RuntimeVersionType::Bundle => match bundle_runtime_version { + Some(runtime_version) => ChainRuntimeVersion::Custom(runtime_version), + None => { + return Err(anyhow::format_err!("Cannot use bundled runtime version of {}: it is not known to the relay", stringify!($chain_prefix))); + } + }, + }) + } + } + } + }; +} + +/// Create chain-specific set of runtime version parameters. +#[macro_export] +macro_rules! declare_chain_connection_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + bp_runtime::paste::item! { + #[doc = $chain " connection params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain ConnectionParams>] { + #[doc = "Connect to " $chain " node at given host."] + #[structopt(long, default_value = "127.0.0.1")] + pub [<$chain_prefix _host>]: String, + #[doc = "Connect to " $chain " node websocket server at given port."] + #[structopt(long, default_value = "9944")] + pub [<$chain_prefix _port>]: u16, + #[doc = "Use secure websocket connection."] + #[structopt(long)] + pub [<$chain_prefix _secure>]: bool, + #[doc = "Custom runtime version"] + #[structopt(flatten)] + pub [<$chain_prefix _runtime_version>]: [<$chain RuntimeVersionParams>], + } + + impl [<$chain ConnectionParams>] { + /// Convert connection params into Substrate client. + #[allow(dead_code)] + pub async fn into_client( + self, + ) -> anyhow::Result> { + let chain_runtime_version = self + .[<$chain_prefix _runtime_version>] + .into_runtime_version(Chain::RUNTIME_VERSION)?; + Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { + host: self.[<$chain_prefix _host>], + port: self.[<$chain_prefix _port>], + secure: self.[<$chain_prefix _secure>], + chain_runtime_version, + }) + .await + ) + } + } + } + }; +} + +/// Create chain-specific set of signing parameters. +#[macro_export] +macro_rules! declare_chain_signing_params_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + bp_runtime::paste::item! { + #[doc = $chain " signing params."] + #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] + pub struct [<$chain SigningParams>] { + #[doc = "The SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _signer>]: Option, + #[doc = "The password for the SURI of secret key to use when transactions are submitted to the " $chain " node."] + #[structopt(long)] + pub [<$chain_prefix _signer_password>]: Option, + + #[doc = "Path to the file, that contains SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer option."] + #[structopt(long)] + pub [<$chain_prefix _signer_file>]: Option, + #[doc = "Path to the file, that password for the SURI of secret key to use when transactions are submitted to the " $chain " node. Can be overridden with " $chain_prefix "_signer_password option."] + #[structopt(long)] + pub [<$chain_prefix _signer_password_file>]: Option, + + #[doc = "Transactions mortality period, in blocks. MUST be a power of two in [4; 65536] range. MAY NOT be larger than `BlockHashCount` parameter of the chain system module."] + #[structopt(long)] + pub [<$chain_prefix _transactions_mortality>]: Option, + } + + impl [<$chain SigningParams>] { + /// Return transactions mortality. + #[allow(dead_code)] + pub fn transactions_mortality(&self) -> anyhow::Result> { + self.[<$chain_prefix _transactions_mortality>] + .map(|transactions_mortality| { + if !(4..=65536).contains(&transactions_mortality) + || !transactions_mortality.is_power_of_two() + { + Err(anyhow::format_err!( + "Transactions mortality {} is not a power of two in a [4; 65536] range", + transactions_mortality, + )) + } else { + Ok(transactions_mortality) + } + }) + .transpose() + } + + /// Parse signing params into chain-specific KeyPair. + #[allow(dead_code)] + pub fn to_keypair(&self) -> anyhow::Result> { + let suri = match (self.[<$chain_prefix _signer>].as_ref(), self.[<$chain_prefix _signer_file>].as_ref()) { + (Some(suri), _) => suri.to_owned(), + (None, Some(suri_file)) => std::fs::read_to_string(suri_file) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI from file {:?}: {}", + suri_file, + err, + ))?, + (None, None) => return Err(anyhow::format_err!( + "One of options must be specified: '{}' or '{}'", + stringify!([<$chain_prefix _signer>]), + stringify!([<$chain_prefix _signer_file>]), + )), + }; + + let suri_password = match ( + self.[<$chain_prefix _signer_password>].as_ref(), + self.[<$chain_prefix _signer_password_file>].as_ref(), + ) { + (Some(suri_password), _) => Some(suri_password.to_owned()), + (None, Some(suri_password_file)) => std::fs::read_to_string(suri_password_file) + .map(Some) + .map_err(|err| anyhow::format_err!( + "Failed to read SURI password from file {:?}: {}", + suri_password_file, + err, + ))?, + _ => None, + }; + + use sp_core::crypto::Pair; + + AccountKeyPairOf::::from_string( + &suri, + suri_password.as_deref() + ).map_err(|e| anyhow::format_err!("{:?}", e)) + } + + /// Return transaction parameters. + #[allow(dead_code)] + pub fn transaction_params( + &self, + ) -> anyhow::Result>> { + Ok(TransactionParams { + mortality: self.transactions_mortality()?, + signer: self.to_keypair::()?, + }) + } + } + } + }; +} + +/// Create chain-specific set of configuration objects: connection parameters, +/// signing parameters and bridge initialization parameters. +#[macro_export] +macro_rules! declare_chain_cli_schema { + ($chain:ident, $chain_prefix:ident) => { + $crate::declare_chain_runtime_version_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_connection_params_cli_schema!($chain, $chain_prefix); + $crate::declare_chain_signing_params_cli_schema!($chain, $chain_prefix); + }; +} + +declare_chain_cli_schema!(Source, source); +declare_chain_cli_schema!(Target, target); diff --git a/relays/lib-substrate-relay/src/cli/detect_equivocations.rs b/relays/lib-substrate-relay/src/cli/detect_equivocations.rs new file mode 100644 index 0000000000000..b98e41b2a43e4 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/detect_equivocations.rs @@ -0,0 +1,65 @@ +// Copyright 2019-2023 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 . + +//! Primitives for exposing the equivocation detection functionality in the CLI. + +use crate::{ + cli::{bridge::*, chain_schema::*, PrometheusParams}, + equivocation, + equivocation::SubstrateEquivocationDetectionPipeline, +}; + +use async_trait::async_trait; +use relay_substrate_client::ChainWithTransactions; +use structopt::StructOpt; + +/// Start equivocation detection loop. +#[derive(StructOpt)] +pub struct DetectEquivocationsParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for starting the equivocation detection loop between 2 chains. +#[async_trait] +pub trait EquivocationsDetector: RelayToRelayEquivocationDetectionCliBridge +where + Self::Source: ChainWithTransactions, +{ + /// Start the equivocation detection loop. + async fn start(data: DetectEquivocationsParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + Self::Equivocation::start_relay_guards( + &source_client, + source_client.can_start_version_guard(), + ) + .await?; + + equivocation::run::( + source_client, + data.target.into_client::().await?, + data.source_sign.transaction_params::()?, + data.prometheus_params.into_metrics_params()?, + ) + .await + } +} diff --git a/relays/lib-substrate-relay/src/cli/init_bridge.rs b/relays/lib-substrate-relay/src/cli/init_bridge.rs new file mode 100644 index 0000000000000..bf7c86437ba77 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/init_bridge.rs @@ -0,0 +1,85 @@ +// 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 . + +//! Primitives for exposing the bridge initialization functionality in the CLI. + +use async_trait::async_trait; +use codec::Encode; + +use crate::{ + cli::{bridge::CliBridgeBase, chain_schema::*}, + finality_base::engine::Engine, +}; +use bp_runtime::Chain as ChainBase; +use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; +use sp_core::Pair; +use structopt::StructOpt; + +/// Bridge initialization params. +#[derive(StructOpt)] +pub struct InitBridgeParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + /// Generates all required data, but does not submit extrinsic + #[structopt(long)] + dry_run: bool, +} + +/// Trait used for bridge initializing. +#[async_trait] +pub trait BridgeInitializer: CliBridgeBase +where + ::AccountId: From< as Pair>::Public>, +{ + /// The finality engine used by the source chain. + type Engine: Engine; + + /// Get the encoded call to init the bridge. + fn encode_init_bridge( + init_data: >::InitializationData, + ) -> ::Call; + + /// Initialize the bridge. + async fn init_bridge(data: InitBridgeParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + let dry_run = data.dry_run; + + crate::finality::initialize::initialize::( + source_client, + target_client.clone(), + target_sign, + move |transaction_nonce, initialization_data| { + let call = Self::encode_init_bridge(initialization_data); + log::info!( + target: "bridge", + "Initialize bridge call encoded as hex string: {:?}", + format!("0x{}", hex::encode(call.encode())) + ); + Ok(UnsignedTransaction::new(call.into(), transaction_nonce)) + }, + dry_run, + ) + .await; + + Ok(()) + } +} diff --git a/relays/lib-substrate-relay/src/cli/mod.rs b/relays/lib-substrate-relay/src/cli/mod.rs new file mode 100644 index 0000000000000..0dd0d5474b3a5 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/mod.rs @@ -0,0 +1,192 @@ +// 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 . + +//! Deal with CLI args of substrate-to-substrate relay. + +use codec::{Decode, Encode}; +use rbtag::BuildInfo; +use structopt::StructOpt; +use strum::{EnumString, VariantNames}; + +use bp_messages::LaneId; + +pub mod bridge; +pub mod chain_schema; +pub mod detect_equivocations; +pub mod init_bridge; +pub mod relay_headers; +pub mod relay_headers_and_messages; +pub mod relay_messages; +pub mod relay_parachains; + +/// The target that will be used when publishing logs related to this pallet. +pub const LOG_TARGET: &str = "bridge"; + +/// Lane id. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct HexLaneId(pub [u8; 4]); + +impl From for LaneId { + fn from(lane_id: HexLaneId) -> LaneId { + LaneId(lane_id.0) + } +} + +impl std::str::FromStr for HexLaneId { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + let mut lane_id = [0u8; 4]; + hex::decode_to_slice(s, &mut lane_id)?; + Ok(HexLaneId(lane_id)) + } +} + +/// Nicer formatting for raw bytes vectors. +#[derive(Default, Encode, Decode, PartialEq, Eq)] +pub struct HexBytes(pub Vec); + +impl std::str::FromStr for HexBytes { + type Err = hex::FromHexError; + + fn from_str(s: &str) -> Result { + Ok(Self(hex::decode(s)?)) + } +} + +impl std::fmt::Debug for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "0x{self}") + } +} + +impl std::fmt::Display for HexBytes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(fmt, "{}", hex::encode(&self.0)) + } +} + +/// Prometheus metrics params. +#[derive(Clone, Debug, PartialEq, StructOpt)] +pub struct PrometheusParams { + /// Do not expose a Prometheus metric endpoint. + #[structopt(long)] + pub no_prometheus: bool, + /// Expose Prometheus endpoint at given interface. + #[structopt(long, default_value = "127.0.0.1")] + pub prometheus_host: String, + /// Expose Prometheus endpoint at given port. + #[structopt(long, default_value = "9616")] + pub prometheus_port: u16, +} + +/// Struct to get git commit info and build time. +#[derive(BuildInfo)] +struct SubstrateRelayBuildInfo; + +impl SubstrateRelayBuildInfo { + /// Get git commit in form ``. + pub fn get_git_commit() -> String { + // on gitlab we use images without git installed, so we can't use `rbtag` there + // locally we don't have `CI_*` env variables, so we can't rely on them + // => we are using `CI_*` env variables or else `rbtag` + let maybe_sha_from_ci = option_env!("CI_COMMIT_SHORT_SHA"); + maybe_sha_from_ci + .map(|short_sha| { + // we assume that on CI the copy is always clean + format!("{short_sha}-clean") + }) + .unwrap_or_else(|| SubstrateRelayBuildInfo.get_build_commit().into()) + } +} + +impl PrometheusParams { + /// Tries to convert CLI metrics params into metrics params, used by the relay. + pub fn into_metrics_params(self) -> anyhow::Result { + let metrics_address = if !self.no_prometheus { + Some(relay_utils::metrics::MetricsAddress { + host: self.prometheus_host, + port: self.prometheus_port, + }) + } else { + None + }; + + let relay_version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"); + let relay_commit = SubstrateRelayBuildInfo::get_git_commit(); + relay_utils::metrics::MetricsParams::new( + metrics_address, + relay_version.into(), + relay_commit, + ) + .map_err(|e| anyhow::format_err!("{:?}", e)) + } +} + +/// Either explicit or maximal allowed value. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ExplicitOrMaximal { + /// User has explicitly specified argument value. + Explicit(V), + /// Maximal allowed value for this argument. + Maximal, +} + +impl std::str::FromStr for ExplicitOrMaximal +where + V::Err: std::fmt::Debug, +{ + type Err = String; + + fn from_str(s: &str) -> Result { + if s.to_lowercase() == "max" { + return Ok(ExplicitOrMaximal::Maximal) + } + + V::from_str(s) + .map(ExplicitOrMaximal::Explicit) + .map_err(|e| format!("Failed to parse '{e:?}'. Expected 'max' or explicit value")) + } +} + +#[doc = "Runtime version params."] +#[derive(StructOpt, Debug, PartialEq, Eq, Clone, Copy, EnumString, VariantNames)] +pub enum RuntimeVersionType { + /// Auto query version from chain + Auto, + /// Custom `spec_version` and `transaction_version` + Custom, + /// Read version from bundle dependencies directly. + Bundle, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn hex_bytes_display_matches_from_str_for_clap() { + // given + let hex = HexBytes(vec![1, 2, 3, 4]); + let display = format!("{hex}"); + + // when + let hex2: HexBytes = display.parse().unwrap(); + + // then + assert_eq!(hex.0, hex2.0); + } +} diff --git a/relays/lib-substrate-relay/src/cli/relay_headers.rs b/relays/lib-substrate-relay/src/cli/relay_headers.rs new file mode 100644 index 0000000000000..90558ed461383 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_headers.rs @@ -0,0 +1,76 @@ +// 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 . + +//! Primitives for exposing the headers relaying functionality in the CLI. + +use async_trait::async_trait; +use structopt::StructOpt; + +use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; + +use crate::{ + cli::{bridge::*, chain_schema::*, PrometheusParams}, + finality::SubstrateFinalitySyncPipeline, +}; + +/// Chain headers relaying params. +#[derive(StructOpt)] +pub struct RelayHeadersParams { + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. + #[structopt(long)] + only_mandatory_headers: bool, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for relaying headers between 2 chains. +#[async_trait] +pub trait HeadersRelayer: RelayToRelayHeadersCliBridge { + /// Relay headers. + async fn relay_headers(data: RelayHeadersParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let target_client = data.target.into_client::().await?; + let target_transactions_mortality = data.target_sign.target_transactions_mortality; + let target_sign = data.target_sign.to_keypair::()?; + + let metrics_params: relay_utils::metrics::MetricsParams = + data.prometheus_params.into_metrics_params()?; + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + + let target_transactions_params = crate::TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }; + Self::Finality::start_relay_guards(&target_client, target_client.can_start_version_guard()) + .await?; + + crate::finality::run::( + source_client, + target_client, + data.only_mandatory_headers, + target_transactions_params, + metrics_params, + ) + .await + } +} diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs new file mode 100644 index 0000000000000..d404f714b5878 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs @@ -0,0 +1,484 @@ +// Copyright 2019-2022 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 . + +//! Complex 2-ways headers+messages relays support. +//! +//! To add new complex relay between `ChainA` and `ChainB`, you must: +//! +//! 1) ensure that there's a `declare_chain_cli_schema!(...)` for both chains. +//! 2) add `declare_chain_to_chain_bridge_schema!(...)` or +//! `declare_chain_to_parachain_bridge_schema` for the bridge. +//! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it. + +#[macro_use] +pub mod parachain_to_parachain; +#[macro_use] +pub mod relay_to_relay; +#[macro_use] +pub mod relay_to_parachain; + +use async_trait::async_trait; +use std::{marker::PhantomData, sync::Arc}; +use structopt::StructOpt; + +use futures::{FutureExt, TryFutureExt}; + +use crate::{ + cli::{bridge::MessagesCliBridge, HexLaneId, PrometheusParams}, + messages_lane::{MessagesRelayLimits, MessagesRelayParams}, + on_demand::OnDemandRelay, + TaggedAccount, TransactionParams, +}; +use bp_messages::LaneId; +use bp_runtime::BalanceOf; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, Chain, ChainWithBalances, ChainWithMessages, + ChainWithRuntimeVersion, ChainWithTransactions, Client, +}; +use relay_utils::metrics::MetricsParams; +use sp_core::Pair; + +/// Parameters that have the same names across all bridges. +#[derive(Debug, PartialEq, StructOpt)] +pub struct HeadersAndMessagesSharedParams { + /// Hex-encoded lane identifiers that should be served by the complex relay. + #[structopt(long, default_value = "00000000")] + pub lane: Vec, + /// If passed, only mandatory headers (headers that are changing the GRANDPA authorities set) + /// are relayed. + #[structopt(long)] + pub only_mandatory_headers: bool, + #[structopt(flatten)] + /// Prometheus metrics params. + pub prometheus_params: PrometheusParams, +} + +/// Bridge parameters, shared by all bridge types. +pub struct Full2WayBridgeCommonParams< + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion, +> { + /// Shared parameters. + pub shared: HeadersAndMessagesSharedParams, + /// Parameters of the left chain. + pub left: BridgeEndCommonParams, + /// Parameters of the right chain. + pub right: BridgeEndCommonParams, + + /// Common metric parameters. + pub metrics_params: MetricsParams, +} + +impl< + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion, + > Full2WayBridgeCommonParams +{ + /// Creates new bridge parameters from its components. + pub fn new>( + shared: HeadersAndMessagesSharedParams, + left: BridgeEndCommonParams, + right: BridgeEndCommonParams, + ) -> anyhow::Result { + // Create metrics registry. + let metrics_params = shared.prometheus_params.clone().into_metrics_params()?; + let metrics_params = relay_utils::relay_metrics(metrics_params).into_params(); + + Ok(Self { shared, left, right, metrics_params }) + } +} + +/// Parameters that are associated with one side of the bridge. +pub struct BridgeEndCommonParams { + /// Chain client. + pub client: Client, + /// Params used for sending transactions to the chain. + pub tx_params: TransactionParams>, + /// Accounts, which balances are exposed as metrics by the relay process. + pub accounts: Vec>>, +} + +/// All data of the bidirectional complex relay. +pub struct FullBridge< + 'a, + Source: ChainWithTransactions + ChainWithRuntimeVersion, + Target: ChainWithTransactions + ChainWithRuntimeVersion, + Bridge: MessagesCliBridge, +> { + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + _phantom_data: PhantomData, +} + +impl< + 'a, + Source: ChainWithTransactions + ChainWithRuntimeVersion, + Target: ChainWithTransactions + ChainWithRuntimeVersion, + Bridge: MessagesCliBridge, + > FullBridge<'a, Source, Target, Bridge> +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, +{ + /// Construct complex relay given it components. + fn new( + source: &'a mut BridgeEndCommonParams, + target: &'a mut BridgeEndCommonParams, + metrics_params: &'a MetricsParams, + ) -> Self { + Self { source, target, metrics_params, _phantom_data: Default::default() } + } + + /// Returns message relay parameters. + fn messages_relay_params( + &self, + source_to_target_headers_relay: Arc>, + target_to_source_headers_relay: Arc>, + lane_id: LaneId, + maybe_limits: Option, + ) -> MessagesRelayParams { + MessagesRelayParams { + source_client: self.source.client.clone(), + source_transaction_params: self.source.tx_params.clone(), + target_client: self.target.client.clone(), + target_transaction_params: self.target.tx_params.clone(), + source_to_target_headers_relay: Some(source_to_target_headers_relay), + target_to_source_headers_relay: Some(target_to_source_headers_relay), + lane_id, + limits: maybe_limits, + metrics_params: self.metrics_params.clone().disable(), + } + } +} + +/// Base portion of the bidirectional complex relay. +/// +/// This main purpose of extracting this trait is that in different relays the implementation +/// of `start_on_demand_headers_relayers` method will be different. But the number of +/// implementations is limited to relay <> relay, parachain <> relay and parachain <> parachain. +/// This trait allows us to reuse these implementations in different bridges. +#[async_trait] +pub trait Full2WayBridgeBase: Sized + Send + Sync { + /// The CLI params for the bridge. + type Params; + /// The left relay chain. + type Left: ChainWithTransactions + ChainWithRuntimeVersion; + /// The right destination chain (it can be a relay or a parachain). + type Right: ChainWithTransactions + ChainWithRuntimeVersion; + + /// Reference to common relay parameters. + fn common(&self) -> &Full2WayBridgeCommonParams; + + /// Mutable reference to common relay parameters. + fn mut_common(&mut self) -> &mut Full2WayBridgeCommonParams; + + /// Start on-demand headers relays. + async fn start_on_demand_headers_relayers( + &mut self, + ) -> anyhow::Result<( + Arc>, + Arc>, + )>; +} + +/// Bidirectional complex relay. +#[async_trait] +pub trait Full2WayBridge: Sized + Sync +where + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom> + Into, + BalanceOf: TryFrom> + Into, +{ + /// Base portion of the bidirectional complex relay. + type Base: Full2WayBridgeBase; + + /// The left relay chain. + type Left: ChainWithTransactions + + ChainWithBalances + + ChainWithMessages + + ChainWithRuntimeVersion; + /// The right relay chain. + type Right: ChainWithTransactions + + ChainWithBalances + + ChainWithMessages + + ChainWithRuntimeVersion; + + /// Left to Right bridge. + type L2R: MessagesCliBridge; + /// Right to Left bridge + type R2L: MessagesCliBridge; + + /// Construct new bridge. + fn new(params: ::Params) -> anyhow::Result; + + /// Reference to the base relay portion. + fn base(&self) -> &Self::Base; + + /// Mutable reference to the base relay portion. + fn mut_base(&mut self) -> &mut Self::Base; + + /// Creates and returns Left to Right complex relay. + fn left_to_right(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::L2R>::new( + &mut common.left, + &mut common.right, + &common.metrics_params, + ) + } + + /// Creates and returns Right to Left complex relay. + fn right_to_left(&mut self) -> FullBridge { + let common = self.mut_base().mut_common(); + FullBridge::<_, _, Self::R2L>::new( + &mut common.right, + &mut common.left, + &common.metrics_params, + ) + } + + /// Start complex relay. + async fn run(&mut self) -> anyhow::Result<()> { + // Register standalone metrics. + { + let common = self.mut_base().mut_common(); + common.left.accounts.push(TaggedAccount::Messages { + id: common.left.tx_params.signer.public().into(), + bridged_chain: Self::Right::NAME.to_string(), + }); + common.right.accounts.push(TaggedAccount::Messages { + id: common.right.tx_params.signer.public().into(), + bridged_chain: Self::Left::NAME.to_string(), + }); + } + + // start on-demand header relays + let (left_to_right_on_demand_headers, right_to_left_on_demand_headers) = + self.mut_base().start_on_demand_headers_relayers().await?; + + // add balance-related metrics + let lanes = self + .base() + .common() + .shared + .lane + .iter() + .cloned() + .map(Into::into) + .collect::>(); + { + let common = self.mut_base().mut_common(); + crate::messages_metrics::add_relay_balances_metrics::<_, Self::Right>( + common.left.client.clone(), + &common.metrics_params, + &common.left.accounts, + &lanes, + ) + .await?; + crate::messages_metrics::add_relay_balances_metrics::<_, Self::Left>( + common.right.client.clone(), + &common.metrics_params, + &common.right.accounts, + &lanes, + ) + .await?; + } + + // Need 2x capacity since we consider both directions for each lane + let mut message_relays = Vec::with_capacity(lanes.len() * 2); + for lane in lanes { + let left_to_right_messages = crate::messages_lane::run::< + ::MessagesLane, + >(self.left_to_right().messages_relay_params( + left_to_right_on_demand_headers.clone(), + right_to_left_on_demand_headers.clone(), + lane, + Self::L2R::maybe_messages_limits(), + )) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + message_relays.push(left_to_right_messages); + + let right_to_left_messages = crate::messages_lane::run::< + ::MessagesLane, + >(self.right_to_left().messages_relay_params( + right_to_left_on_demand_headers.clone(), + left_to_right_on_demand_headers.clone(), + lane, + Self::R2L::maybe_messages_limits(), + )) + .map_err(|e| anyhow::format_err!("{}", e)) + .boxed(); + message_relays.push(right_to_left_messages); + } + + relay_utils::relay_metrics(self.base().common().metrics_params.clone()) + .expose() + .await + .map_err(|e| anyhow::format_err!("{}", e))?; + + futures::future::select_all(message_relays).await.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{cli::chain_schema::RuntimeVersionType, declare_chain_cli_schema}; + + use relay_substrate_client::{ChainRuntimeVersion, Parachain, SimpleRuntimeVersion}; + + #[test] + // We need `#[allow(dead_code)]` because some of the methods generated by the macros + // are not used. + #[allow(dead_code)] + fn should_parse_parachain_to_parachain_options() { + // Chains. + declare_chain_cli_schema!(Kusama, kusama); + declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); + declare_chain_cli_schema!(Polkadot, polkadot); + declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); + // Means to override signers of different layer transactions. + declare_chain_cli_schema!( + KusamaHeadersToBridgeHubPolkadot, + kusama_headers_to_bridge_hub_polkadot + ); + declare_chain_cli_schema!( + KusamaParachainsToBridgeHubPolkadot, + kusama_parachains_to_bridge_hub_polkadot + ); + declare_chain_cli_schema!( + PolkadotHeadersToBridgeHubKusama, + polkadot_headers_to_bridge_hub_kusama + ); + declare_chain_cli_schema!( + PolkadotParachainsToBridgeHubKusama, + polkadot_parachains_to_bridge_hub_kusama + ); + // Bridges. + declare_parachain_to_parachain_bridge_schema!( + BridgeHubKusama, + Kusama, + BridgeHubPolkadot, + Polkadot + ); + + let res = BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages::from_iter(vec![ + "bridge-hub-kusama-bridge-hub-polkadot-headers-and-messages", + "--bridge-hub-kusama-host", + "bridge-hub-kusama-node-collator1", + "--bridge-hub-kusama-port", + "9944", + "--bridge-hub-kusama-signer", + "//Iden", + "--bridge-hub-kusama-transactions-mortality", + "64", + "--kusama-host", + "kusama-alice", + "--kusama-port", + "9944", + "--bridge-hub-polkadot-host", + "bridge-hub-polkadot-collator1", + "--bridge-hub-polkadot-port", + "9944", + "--bridge-hub-polkadot-signer", + "//George", + "--bridge-hub-polkadot-transactions-mortality", + "64", + "--polkadot-host", + "polkadot-alice", + "--polkadot-port", + "9944", + "--lane", + "00000000", + "--prometheus-host", + "0.0.0.0", + ]); + + // then + assert_eq!( + res, + BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages { + shared: HeadersAndMessagesSharedParams { + lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], + only_mandatory_headers: false, + prometheus_params: PrometheusParams { + no_prometheus: false, + prometheus_host: "0.0.0.0".into(), + prometheus_port: 9616, + }, + }, + left: BridgeHubKusamaConnectionParams { + bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(), + bridge_hub_kusama_port: 9944, + bridge_hub_kusama_secure: false, + bridge_hub_kusama_runtime_version: BridgeHubKusamaRuntimeVersionParams { + bridge_hub_kusama_version_mode: RuntimeVersionType::Bundle, + bridge_hub_kusama_spec_version: None, + bridge_hub_kusama_transaction_version: None, + }, + }, + left_sign: BridgeHubKusamaSigningParams { + bridge_hub_kusama_signer: Some("//Iden".into()), + bridge_hub_kusama_signer_password: None, + bridge_hub_kusama_signer_file: None, + bridge_hub_kusama_signer_password_file: None, + bridge_hub_kusama_transactions_mortality: Some(64), + }, + left_relay: KusamaConnectionParams { + kusama_host: "kusama-alice".into(), + kusama_port: 9944, + kusama_secure: false, + kusama_runtime_version: KusamaRuntimeVersionParams { + kusama_version_mode: RuntimeVersionType::Bundle, + kusama_spec_version: None, + kusama_transaction_version: None, + }, + }, + right: BridgeHubPolkadotConnectionParams { + bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(), + bridge_hub_polkadot_port: 9944, + bridge_hub_polkadot_secure: false, + bridge_hub_polkadot_runtime_version: BridgeHubPolkadotRuntimeVersionParams { + bridge_hub_polkadot_version_mode: RuntimeVersionType::Bundle, + bridge_hub_polkadot_spec_version: None, + bridge_hub_polkadot_transaction_version: None, + }, + }, + right_sign: BridgeHubPolkadotSigningParams { + bridge_hub_polkadot_signer: Some("//George".into()), + bridge_hub_polkadot_signer_password: None, + bridge_hub_polkadot_signer_file: None, + bridge_hub_polkadot_signer_password_file: None, + bridge_hub_polkadot_transactions_mortality: Some(64), + }, + right_relay: PolkadotConnectionParams { + polkadot_host: "polkadot-alice".into(), + polkadot_port: 9944, + polkadot_secure: false, + polkadot_runtime_version: PolkadotRuntimeVersionParams { + polkadot_version_mode: RuntimeVersionType::Bundle, + polkadot_spec_version: None, + polkadot_transaction_version: None, + }, + }, + } + ); + } +} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs similarity index 82% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs rename to relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs index 32ba6b3ddadce..76accfa290506 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/parachain_to_parachain.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs @@ -14,26 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Parachain to parachain relayer CLI primitives. + use async_trait::async_trait; use std::sync::Arc; -use crate::cli::{ - bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, - CliChain, +use crate::{ + cli::{ + bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + }, + finality::SubstrateFinalitySyncPipeline, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, + }, }; use bp_polkadot_core::parachains::ParaHash; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, Client, + Parachain, }; use sp_core::Pair; -use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, - on_demand::{ - headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, - }, -}; /// A base relay between two parachain from different consensus systems. /// @@ -55,6 +57,8 @@ pub struct ParachainToParachainBridge< pub right_relay: Client<::SourceRelay>, } +/// Create set of configuration objects specific to parachain-to-parachain relayer. +#[macro_export] macro_rules! declare_parachain_to_parachain_bridge_schema { // left-parachain, relay-chain-of-left-parachain, right-parachain, relay-chain-of-right-parachain ($left_parachain:ident, $left_chain:ident, $right_parachain:ident, $right_chain:ident) => { @@ -87,20 +91,20 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { impl [<$left_parachain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain + Parachain, - LeftRelay: CliChain, - Right: ChainWithTransactions + CliChain + Parachain, - RightRelay: CliChain, - L2R: CliBridgeBase + Left: ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + LeftRelay: ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + RightRelay: ChainWithRuntimeVersion, + L2R: $crate::cli::bridge::CliBridgeBase + MessagesCliBridge - + ParachainToRelayHeadersCliBridge, - R2L: CliBridgeBase + + $crate::cli::bridge::ParachainToRelayHeadersCliBridge, + R2L: $crate::cli::bridge::CliBridgeBase + MessagesCliBridge - + ParachainToRelayHeadersCliBridge, + + $crate::cli::bridge::ParachainToRelayHeadersCliBridge, >( self, - ) -> anyhow::Result> { - Ok(ParachainToParachainBridge { + ) -> anyhow::Result<$crate::cli::relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge> { + Ok($crate::cli::relay_headers_and_messages::parachain_to_parachain::ParachainToParachainBridge { common: Full2WayBridgeCommonParams::new::( self.shared, BridgeEndCommonParams { @@ -125,12 +129,12 @@ macro_rules! declare_parachain_to_parachain_bridge_schema { #[async_trait] impl< - Left: Chain + ChainWithTransactions + CliChain + Parachain, - Right: Chain + ChainWithTransactions + CliChain + Parachain, + Left: Chain + ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + Right: Chain + ChainWithTransactions + ChainWithRuntimeVersion + Parachain, LeftRelay: Chain - + CliChain, + + ChainWithRuntimeVersion, RightRelay: Chain - + CliChain, + + ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + ParachainToRelayHeadersCliBridge, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs similarity index 88% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs rename to relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs index fd885b6ea6c6c..b75ac3e60c269 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_parachain.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs @@ -14,29 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +//! Relay chain to parachain relayer CLI primitives. + use async_trait::async_trait; use std::sync::Arc; -use crate::cli::{ - bridge::{ - CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, - RelayToRelayHeadersCliBridge, +use crate::{ + cli::{ + bridge::{ + CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, + RelayToRelayHeadersCliBridge, + }, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + }, + finality::SubstrateFinalitySyncPipeline, + on_demand::{ + headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, }, - relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, - CliChain, }; use bp_polkadot_core::parachains::ParaHash; use pallet_bridge_parachains::{RelayBlockHash, RelayBlockHasher, RelayBlockNumber}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainWithTransactions, Client, Parachain, + AccountIdOf, AccountKeyPairOf, Chain, ChainWithRuntimeVersion, ChainWithTransactions, Client, + Parachain, }; use sp_core::Pair; -use substrate_relay_helper::{ - finality::SubstrateFinalitySyncPipeline, - on_demand::{ - headers::OnDemandHeadersRelay, parachains::OnDemandParachainsRelay, OnDemandRelay, - }, -}; /// A base relay between standalone (relay) chain and a parachain from another consensus system. /// @@ -55,6 +57,8 @@ pub struct RelayToParachainBridge< pub right_relay: Client<::SourceRelay>, } +/// Create set of configuration objects specific to relay-to-parachain relayer. +#[macro_export] macro_rules! declare_relay_to_parachain_bridge_schema { // chain, parachain, relay-chain-of-parachain ($left_chain:ident, $right_parachain:ident, $right_chain:ident) => { @@ -84,9 +88,9 @@ macro_rules! declare_relay_to_parachain_bridge_schema { impl [<$left_chain $right_parachain HeadersAndMessages>] { async fn into_bridge< - Left: ChainWithTransactions + CliChain, - Right: ChainWithTransactions + CliChain + Parachain, - RightRelay: CliChain, + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion + Parachain, + RightRelay: ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, R2L: CliBridgeBase + MessagesCliBridge @@ -118,10 +122,10 @@ macro_rules! declare_relay_to_parachain_bridge_schema { #[async_trait] impl< - Left: ChainWithTransactions + CliChain, - Right: Chain + ChainWithTransactions + CliChain + Parachain, + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: Chain + ChainWithTransactions + ChainWithRuntimeVersion + Parachain, RightRelay: Chain - + CliChain, + + ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs similarity index 91% rename from relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs rename to relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs index 11425035de287..b397ff50a20a6 100644 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages/relay_to_relay.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs @@ -18,20 +18,23 @@ // future #![allow(unused_macros)] +//! Relay chain to Relay chain relayer CLI primitives. + use async_trait::async_trait; use std::sync::Arc; -use crate::cli::{ - bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}, - relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, - CliChain, -}; -use relay_substrate_client::{AccountIdOf, AccountKeyPairOf, ChainWithTransactions}; -use sp_core::Pair; -use substrate_relay_helper::{ +use crate::{ + cli::{ + bridge::{CliBridgeBase, MessagesCliBridge, RelayToRelayHeadersCliBridge}, + relay_headers_and_messages::{Full2WayBridgeBase, Full2WayBridgeCommonParams}, + }, finality::SubstrateFinalitySyncPipeline, on_demand::{headers::OnDemandHeadersRelay, OnDemandRelay}, }; +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, ChainWithRuntimeVersion, ChainWithTransactions, +}; +use sp_core::Pair; /// A base relay between two standalone (relay) chains. /// @@ -45,6 +48,7 @@ pub struct RelayToRelayBridge< Full2WayBridgeCommonParams<::Target, ::Target>, } +/// Create set of configuration objects specific to relay-to-relay relayer. macro_rules! declare_relay_to_relay_bridge_schema { ($left_chain:ident, $right_chain:ident) => { bp_runtime::paste::item! { @@ -101,8 +105,8 @@ macro_rules! declare_relay_to_relay_bridge_schema { #[async_trait] impl< - Left: ChainWithTransactions + CliChain, - Right: ChainWithTransactions + CliChain, + Left: ChainWithTransactions + ChainWithRuntimeVersion, + Right: ChainWithTransactions + ChainWithRuntimeVersion, L2R: CliBridgeBase + MessagesCliBridge + RelayToRelayHeadersCliBridge, diff --git a/relays/lib-substrate-relay/src/cli/relay_messages.rs b/relays/lib-substrate-relay/src/cli/relay_messages.rs new file mode 100644 index 0000000000000..b672bd4f9b868 --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_messages.rs @@ -0,0 +1,89 @@ +// 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 . + +//! Primitives for exposing the messages relaying functionality in the CLI. + +use crate::{ + cli::{bridge::*, chain_schema::*, HexLaneId, PrometheusParams}, + messages_lane::MessagesRelayParams, + TransactionParams, +}; + +use async_trait::async_trait; +use sp_core::Pair; +use structopt::StructOpt; + +use relay_substrate_client::{ + AccountIdOf, AccountKeyPairOf, BalanceOf, ChainWithRuntimeVersion, ChainWithTransactions, +}; + +/// Messages relaying params. +#[derive(StructOpt)] +pub struct RelayMessagesParams { + /// Hex-encoded lane id that should be served by the relay. Defaults to `00000000`. + #[structopt(long, default_value = "00000000")] + lane: HexLaneId, + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + source_sign: SourceSigningParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for relaying messages between 2 chains. +#[async_trait] +pub trait MessagesRelayer: MessagesCliBridge +where + Self::Source: ChainWithTransactions + ChainWithRuntimeVersion, + AccountIdOf: From< as Pair>::Public>, + AccountIdOf: From< as Pair>::Public>, + BalanceOf: TryFrom>, +{ + /// Start relaying messages. + async fn relay_messages(data: RelayMessagesParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let source_sign = data.source_sign.to_keypair::()?; + let source_transactions_mortality = data.source_sign.transactions_mortality()?; + let target_client = data.target.into_client::().await?; + let target_sign = data.target_sign.to_keypair::()?; + let target_transactions_mortality = data.target_sign.transactions_mortality()?; + + crate::messages_lane::run::(MessagesRelayParams { + source_client, + source_transaction_params: TransactionParams { + signer: source_sign, + mortality: source_transactions_mortality, + }, + target_client, + target_transaction_params: TransactionParams { + signer: target_sign, + mortality: target_transactions_mortality, + }, + source_to_target_headers_relay: None, + target_to_source_headers_relay: None, + lane_id: data.lane.into(), + limits: Self::maybe_messages_limits(), + metrics_params: data.prometheus_params.into_metrics_params()?, + }) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} diff --git a/relays/lib-substrate-relay/src/cli/relay_parachains.rs b/relays/lib-substrate-relay/src/cli/relay_parachains.rs new file mode 100644 index 0000000000000..e5a52349469bb --- /dev/null +++ b/relays/lib-substrate-relay/src/cli/relay_parachains.rs @@ -0,0 +1,91 @@ +// 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 . + +//! Primitives for exposing the parachains finality relaying functionality in the CLI. + +use async_std::sync::Mutex; +use async_trait::async_trait; +use parachains_relay::parachains_loop::{AvailableHeader, SourceClient, TargetClient}; +use relay_substrate_client::Parachain; +use relay_utils::metrics::{GlobalMetrics, StandaloneMetric}; +use std::sync::Arc; +use structopt::StructOpt; + +use crate::{ + cli::{ + bridge::{CliBridgeBase, ParachainToRelayHeadersCliBridge}, + chain_schema::*, + PrometheusParams, + }, + parachains::{source::ParachainsSource, target::ParachainsTarget, ParachainsPipelineAdapter}, + TransactionParams, +}; + +/// Parachains heads relaying params. +#[derive(StructOpt)] +pub struct RelayParachainsParams { + #[structopt(flatten)] + source: SourceConnectionParams, + #[structopt(flatten)] + target: TargetConnectionParams, + #[structopt(flatten)] + target_sign: TargetSigningParams, + #[structopt(flatten)] + prometheus_params: PrometheusParams, +} + +/// Trait used for relaying parachains finality between 2 chains. +#[async_trait] +pub trait ParachainsRelayer: ParachainToRelayHeadersCliBridge +where + ParachainsSource: + SourceClient>, + ParachainsTarget: + TargetClient>, + ::Source: Parachain, +{ + /// Start relaying parachains finality. + async fn relay_parachains(data: RelayParachainsParams) -> anyhow::Result<()> { + let source_client = data.source.into_client::().await?; + let source_client = ParachainsSource::::new( + source_client, + Arc::new(Mutex::new(AvailableHeader::Missing)), + ); + + let target_transaction_params = TransactionParams { + signer: data.target_sign.to_keypair::()?, + mortality: data.target_sign.target_transactions_mortality, + }; + let target_client = data.target.into_client::().await?; + let target_client = ParachainsTarget::::new( + target_client.clone(), + target_transaction_params, + ); + + let metrics_params: relay_utils::metrics::MetricsParams = + data.prometheus_params.into_metrics_params()?; + GlobalMetrics::new()?.register_and_spawn(&metrics_params.registry)?; + + parachains_relay::parachains_loop::run( + source_client, + target_client, + metrics_params, + futures::future::pending(), + ) + .await + .map_err(|e| anyhow::format_err!("{}", e)) + } +} diff --git a/relays/lib-substrate-relay/src/lib.rs b/relays/lib-substrate-relay/src/lib.rs index 6e62038665133..b90453ae0db2d 100644 --- a/relays/lib-substrate-relay/src/lib.rs +++ b/relays/lib-substrate-relay/src/lib.rs @@ -22,6 +22,7 @@ use relay_substrate_client::{Chain, ChainWithUtilityPallet, UtilityPallet}; use std::marker::PhantomData; +pub mod cli; pub mod equivocation; pub mod error; pub mod finality; From ae23c1d039cdc7d41ee9054bafc275ba09ab9c59 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 25 Mar 2024 08:50:57 +0100 Subject: [PATCH 1195/1210] Backport changes from `polkadot-sdk/master` (#2887) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add two new zombienet tests for bridges (manual run) (#3072) extracted useful code from #2982 This PR: - adds test 2 for Rococo <> Westend bridge: checks that relayer doesn't submit any extra headers while there are no any messages; - adds test 3 for Rococo <> Westend bridge: checks that relayer doesn't submit any extra headers when there are messages; - fixes most of comments from #2439 (like: log names, ability to run specify test number when calling `run-tests.sh`). Right now of all our tests, only test 2 is working (until BHs will be upgraded to use async backing), so you can test it with `./bridges/zombienet/run-tests.sh --test 2` locally. (cherry picked from commit 2e6067d768a84e780258aa4580116f7180e24290) * [cumulus] Improved check for sane bridge fees calculations (#3175) - [x] change constants when CI fails (should fail :) ) On the AssetHubRococo: 1701175800126 -> 1700929825257 = 0.15 % decreased. ``` Feb 02 12:59:05.520 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 1701175800126 for runtime: statemine-1006000 (statemine-0.tx14.au1) Feb 02 13:02:40.647 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 1700929825257 for runtime: statemine-1006000 (statemine-0.tx14.au1) ``` On the AssetHubWestend: 2116038876326 -> 1641718372993 = 22.4 % decreased. ``` Feb 02 12:56:00.880 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 2116038876326 for runtime: westmint-1006000 (westmint-0.tx14.au1) Feb 02 13:04:42.515 ERROR bridges::estimate: `bridging::XcmBridgeHubRouterBaseFee` actual value: 1641718372993 for runtime: westmint-1006000 (westmint-0.tx14.au1) ``` (cherry picked from commit 74b597fcaf143d8dd7f8d40e59f51065514f21d7) * Enable async backing on all testnet system chains (#2949) Built on top of https://github.com/paritytech/polkadot-sdk/pull/2826/ which was a trial run. Guide: https://github.com/w3f/polkadot-wiki/blob/master/docs/maintain/maintain-guides-async-backing.md --------- Signed-off-by: georgepisaltu Co-authored-by: Branislav Kontur Co-authored-by: Dónal Murray Co-authored-by: Dmitry Sinyavin Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Bastian Köcher Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com> (cherry picked from commit 700d5f85b768fe1867660938aa5edfcf4b26f632) * Introduce submit_finality_proof_ex call to bridges GRANDPA pallet (#3225) backport of https://github.com/paritytech/parity-bridges-common/pull/2821 (see detailed description there) (cherry picked from commit a462207158360b162228d9877fed7b9ca1f23fc2) * Bridge zombienet tests refactoring (#3260) Related to https://github.com/paritytech/polkadot-sdk/issues/3242 Reorganizing the bridge zombienet tests in order to: - separate the environment spawning from the actual tests - offer better control over the tests and some possibility to orchestrate them as opposed to running everything from the zndsl file Only rewrote the asset transfer test using this new "framework". The old logic and old tests weren't functionally modified or deleted. The plan is to get feedback on this approach first and if this is agreed upon, migrate the other 2 tests later in separate PRs and also do other improvements later. (cherry picked from commit dfc8e4696c6edfb76ccb05f469a221ebb5b270ff) * Bridges: add test 0002 to CI (#3310) Bridges: add test 0002 to CI (cherry picked from commit 1b66bb51b52d3e6cacf155bd3e038b6ef44ac5da) * Bridge zombienet tests - move all test scripts to the same folder (#3333) Related to https://github.com/paritytech/polkadot-sdk/issues/3242 (cherry picked from commit 5fc7622cb312f2d32ec8365012ee0a49622db8c8) * Lift dependencies to the workspace (Part 2/x) (#3366) Lifting some more dependencies to the workspace. Just using the most-often updated ones for now. It can be reproduced locally. ```sh $ zepter transpose dependency lift-to-workspace --ignore-errors syn quote thiserror "regex:^serde.*" $ zepter transpose dependency lift-to-workspace --version-resolver=highest syn quote thiserror "regex:^serde.*" --fix $ taplo format --config .config/taplo.toml ``` --------- Signed-off-by: Oliver Tale-Yazdi (cherry picked from commit e89d0fca351de0712f104c55fe45ed124b5c6968) * Add support for BHP local and BHK local (#3443) Related to https://github.com/paritytech/polkadot-sdk/issues/3400 Extracting small parts of https://github.com/paritytech/polkadot-sdk/pull/3429 into separate PR: - Add support for BHP local and BHK local - Increase the timeout for the bridge zomienet tests (cherry picked from commit e4b6b8cd7973633f86d1b92a56abf2a946b7be84) * Bridge zombienet tests: move all "framework" files under one folder (#3462) Related to https://github.com/paritytech/polkadot-sdk/issues/3400 Moving all bridges testing "framework" files under one folder in order to be able to download the entire folder when we want to add tests in other repos No significant functional changes (cherry picked from commit 6fc1d41d4487b9164451cd8214674ce195ab06a0) * Bridge zombienet tests: Check amount received at destination (#3490) Related to https://github.com/paritytech/polkadot-sdk/issues/3475 (cherry picked from commit 2cdda0e62dd3088d2fd09cea627059674070c277) * FRAME: Create `TransactionExtension` as a replacement for `SignedExtension` (#2280) Closes #2160 First part of [Extrinsic Horizon](https://github.com/paritytech/polkadot-sdk/issues/2415) Introduces a new trait `TransactionExtension` to replace `SignedExtension`. Introduce the idea of transactions which obey the runtime's extensions and have according Extension data (né Extra data) yet do not have hard-coded signatures. Deprecate the terminology of "Unsigned" when used for transactions/extrinsics owing to there now being "proper" unsigned transactions which obey the extension framework and "old-style" unsigned which do not. Instead we have __*General*__ for the former and __*Bare*__ for the latter. (Ultimately, the latter will be phased out as a type of transaction, and Bare will only be used for Inherents.) Types of extrinsic are now therefore: - Bare (no hardcoded signature, no Extra data; used to be known as "Unsigned") - Bare transactions (deprecated): Gossiped, validated with `ValidateUnsigned` (deprecated) and the `_bare_compat` bits of `TransactionExtension` (deprecated). - Inherents: Not gossiped, validated with `ProvideInherent`. - Extended (Extra data): Gossiped, validated via `TransactionExtension`. - Signed transactions (with a hardcoded signature). - General transactions (without a hardcoded signature). `TransactionExtension` differs from `SignedExtension` because: - A signature on the underlying transaction may validly not be present. - It may alter the origin during validation. - `pre_dispatch` is renamed to `prepare` and need not contain the checks present in `validate`. - `validate` and `prepare` is passed an `Origin` rather than a `AccountId`. - `validate` may pass arbitrary information into `prepare` via a new user-specifiable type `Val`. - `AdditionalSigned`/`additional_signed` is renamed to `Implicit`/`implicit`. It is encoded *for the entire transaction* and passed in to each extension as a new argument to `validate`. This facilitates the ability of extensions to acts as underlying crypto. There is a new `DispatchTransaction` trait which contains only default function impls and is impl'ed for any `TransactionExtension` impler. It provides several utility functions which reduce some of the tedium from using `TransactionExtension` (indeed, none of its regular functions should now need to be called directly). Three transaction version discriminator ("versions") are now permissible: - 0b000000100: Bare (used to be called "Unsigned"): contains Signature or Extra (extension data). After bare transactions are no longer supported, this will strictly identify an Inherents only. - 0b100000100: Old-school "Signed" Transaction: contains Signature and Extra (extension data). - 0b010000100: New-school "General" Transaction: contains Extra (extension data), but no Signature. For the New-school General Transaction, it becomes trivial for authors to publish extensions to the mechanism for authorizing an Origin, e.g. through new kinds of key-signing schemes, ZK proofs, pallet state, mutations over pre-authenticated origins or any combination of the above. Wrap your `SignedExtension`s in `AsTransactionExtension`. This should be accompanied by renaming your aggregate type in line with the new terminology. E.g. Before: ```rust /// The SignedExtension to the basic transaction logic. pub type SignedExtra = ( /* snip */ MySpecialSignedExtension, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; ``` After: ```rust /// The extension to the basic transaction logic. pub type TxExtension = ( /* snip */ AsTransactionExtension, ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; ``` You'll also need to alter any transaction building logic to add a `.into()` to make the conversion happen. E.g. Before: ```rust fn construct_extrinsic( /* snip */ ) -> UncheckedExtrinsic { let extra: SignedExtra = ( /* snip */ MySpecialSignedExtension::new(/* snip */), ); let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( /* snip */ Signature::Sr25519(signature), extra, ) } ``` After: ```rust fn construct_extrinsic( /* snip */ ) -> UncheckedExtrinsic { let tx_ext: TxExtension = ( /* snip */ MySpecialSignedExtension::new(/* snip */).into(), ); let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); let signature = payload.using_encoded(|e| sender.sign(e)); UncheckedExtrinsic::new_signed( /* snip */ Signature::Sr25519(signature), tx_ext, ) } ``` Most `SignedExtension`s can be trivially converted to become a `TransactionExtension`. There are a few things to know. - Instead of a single trait like `SignedExtension`, you should now implement two traits individually: `TransactionExtensionBase` and `TransactionExtension`. - Weights are now a thing and must be provided via the new function `fn weight`. This trait takes care of anything which is not dependent on types specific to your runtime, most notably `Call`. - `AdditionalSigned`/`additional_signed` is renamed to `Implicit`/`implicit`. - Weight must be returned by implementing the `weight` function. If your extension is associated with a pallet, you'll probably want to do this via the pallet's existing benchmarking infrastructure. Generally: - `pre_dispatch` is now `prepare` and you *should not reexecute the `validate` functionality in there*! - You don't get an account ID any more; you get an origin instead. If you need to presume an account ID, then you can use the trait function `AsSystemOriginSigner::as_system_origin_signer`. - You get an additional ticket, similar to `Pre`, called `Val`. This defines data which is passed from `validate` into `prepare`. This is important since you should not be duplicating logic from `validate` to `prepare`, you need a way of passing your working from the former into the latter. This is it. - This trait takes two type parameters: `Call` and `Context`. `Call` is the runtime call type which used to be an associated type; you can just move it to become a type parameter for your trait impl. `Context` is not currently used and you can safely implement over it as an unbounded type. - There's no `AccountId` associated type any more. Just remove it. Regarding `validate`: - You get three new parameters in `validate`; all can be ignored when migrating from `SignedExtension`. - `validate` returns a tuple on success; the second item in the tuple is the new ticket type `Self::Val` which gets passed in to `prepare`. If you use any information extracted during `validate` (off-chain and on-chain, non-mutating) in `prepare` (on-chain, mutating) then you can pass it through with this. For the tuple's last item, just return the `origin` argument. Regarding `prepare`: - This is renamed from `pre_dispatch`, but there is one change: - FUNCTIONALITY TO VALIDATE THE TRANSACTION NEED NOT BE DUPLICATED FROM `validate`!! - (This is different to `SignedExtension` which was required to run the same checks in `pre_dispatch` as in `validate`.) Regarding `post_dispatch`: - Since there are no unsigned transactions handled by `TransactionExtension`, `Pre` is always defined, so the first parameter is `Self::Pre` rather than `Option`. If you make use of `SignedExtension::validate_unsigned` or `SignedExtension::pre_dispatch_unsigned`, then: - Just use the regular versions of these functions instead. - Have your logic execute in the case that the `origin` is `None`. - Ensure your transaction creation logic creates a General Transaction rather than a Bare Transaction; this means having to include all `TransactionExtension`s' data. - `ValidateUnsigned` can still be used (for now) if you need to be able to construct transactions which contain none of the extension data, however these will be phased out in stage 2 of the Transactions Horizon, so you should consider moving to an extension-centric design. - [x] Introduce `CheckSignature` impl of `TransactionExtension` to ensure it's possible to have crypto be done wholly in a `TransactionExtension`. - [x] Deprecate `SignedExtension` and move all uses in codebase to `TransactionExtension`. - [x] `ChargeTransactionPayment` - [x] `DummyExtension` - [x] `ChargeAssetTxPayment` (asset-tx-payment) - [x] `ChargeAssetTxPayment` (asset-conversion-tx-payment) - [x] `CheckWeight` - [x] `CheckTxVersion` - [x] `CheckSpecVersion` - [x] `CheckNonce` - [x] `CheckNonZeroSender` - [x] `CheckMortality` - [x] `CheckGenesis` - [x] `CheckOnlySudoAccount` - [x] `WatchDummy` - [x] `PrevalidateAttests` - [x] `GenericSignedExtension` - [x] `SignedExtension` (chain-polkadot-bulletin) - [x] `RefundSignedExtensionAdapter` - [x] Implement `fn weight` across the board. - [ ] Go through all pre-existing extensions which assume an account signer and explicitly handle the possibility of another kind of origin. - [x] `CheckNonce` should probably succeed in the case of a non-account origin. - [x] `CheckNonZeroSender` should succeed in the case of a non-account origin. - [x] `ChargeTransactionPayment` and family should fail in the case of a non-account origin. - [ ] - [x] Fix any broken tests. --------- Signed-off-by: georgepisaltu Signed-off-by: Alexandru Vasile Signed-off-by: dependabot[bot] Signed-off-by: Oliver Tale-Yazdi Signed-off-by: Alexandru Gheorghe Signed-off-by: Andrei Sandu Co-authored-by: Nikhil Gupta <17176722+gupnik@users.noreply.github.com> Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com> Co-authored-by: Chevdor Co-authored-by: Bastian Köcher Co-authored-by: Maciej Co-authored-by: Javier Viola Co-authored-by: Marcin S. Co-authored-by: Tsvetomir Dimitrov Co-authored-by: Javier Bullrich Co-authored-by: Koute Co-authored-by: Adrian Catangiu Co-authored-by: Vladimir Istyufeev Co-authored-by: Ross Bulat Co-authored-by: Gonçalo Pestana Co-authored-by: Liam Aharon Co-authored-by: Svyatoslav Nikolsky Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: Oliver Tale-Yazdi Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: ordian Co-authored-by: Sebastian Kunert Co-authored-by: Aaro Altonen <48052676+altonen@users.noreply.github.com> Co-authored-by: Dmitry Markin Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Co-authored-by: Alexander Samusev <41779041+alvicsam@users.noreply.github.com> Co-authored-by: Julian Eager Co-authored-by: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com> Co-authored-by: Davide Galassi Co-authored-by: Dónal Murray Co-authored-by: yjh Co-authored-by: Tom Mi Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Will | Paradox | ParaNodes.io <79228812+paradox-tt@users.noreply.github.com> Co-authored-by: Bastian Köcher Co-authored-by: Joshy Orndorff Co-authored-by: Joshy Orndorff Co-authored-by: PG Herveou Co-authored-by: Alexander Theißen Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: Juan Girini Co-authored-by: bader y Co-authored-by: James Wilson Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: asynchronous rob Co-authored-by: Parth Co-authored-by: Andrew Jones Co-authored-by: Jonathan Udd Co-authored-by: Serban Iorga Co-authored-by: Egor_P Co-authored-by: Branislav Kontur Co-authored-by: Evgeny Snitko Co-authored-by: Just van Stam Co-authored-by: Francisco Aguirre Co-authored-by: gupnik Co-authored-by: dzmitry-lahoda Co-authored-by: zhiqiangxu <652732310@qq.com> Co-authored-by: Nazar Mokrynskyi Co-authored-by: Anwesh Co-authored-by: cheme Co-authored-by: Sam Johnson Co-authored-by: kianenigma Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Co-authored-by: Muharem Co-authored-by: joepetrowski Co-authored-by: Alexandru Gheorghe <49718502+alexggh@users.noreply.github.com> Co-authored-by: Gabriel Facco de Arruda Co-authored-by: Squirrel Co-authored-by: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Co-authored-by: georgepisaltu Co-authored-by: command-bot <> (cherry picked from commit fd5f9292f500652e1d4792b09fb8ac60e1268ce4) * Revert "FRAME: Create `TransactionExtension` as a replacement for `SignedExtension` (#2280)" (#3665) This PR reverts #2280 which introduced `TransactionExtension` to replace `SignedExtension`. As a result of the discussion [here](https://github.com/paritytech/polkadot-sdk/pull/3623#issuecomment-1986789700), the changes will be reverted for now with plans to reintroduce the concept in the future. --------- Signed-off-by: georgepisaltu (cherry picked from commit bbd51ce867967f71657b901f1a956ad4f75d352e) * Increase timeout for assertions (#3680) Prevents timeouts in ci like https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5516019 (cherry picked from commit c4c9257386036a9e27e7ee001fe8eadb80958cc0) * Removes `as [disambiguation_path]` from `derive_impl` usage (#3652) Step in https://github.com/paritytech/polkadot-sdk/issues/171 This PR removes `as [disambiguation_path]` syntax from `derive_impl` usage across the polkadot-sdk as introduced in https://github.com/paritytech/polkadot-sdk/pull/3505 (cherry picked from commit 7099f6e1b1fa3c8cd894693902263d9ed0e38978) * Fix typo (#3691) (cherry picked from commit 6b1179f13b4815685769c9f523720ec9ed0e2ff4) * Bridge zombienet tests: remove unneeded accounts (#3700) Bridge zombienet tests: remove unneeded accounts (cherry picked from commit 0c6c837f689a287583508506e342ba07687e8d26) * Fix typos (#3753) (cherry picked from commit 7241a8db7b3496816503c6058dae67f66c666b00) * Update polkadot-sdk refs * Fix dependency conflicts * Fix build * cargo fmt * Fix spellcheck test --------- Co-authored-by: Svyatoslav Nikolsky Co-authored-by: Branislav Kontur Co-authored-by: Marcin S Co-authored-by: Oliver Tale-Yazdi Co-authored-by: Gavin Wood Co-authored-by: georgepisaltu <52418509+georgepisaltu@users.noreply.github.com> Co-authored-by: Javier Viola <363911+pepoviola@users.noreply.github.com> Co-authored-by: gupnik Co-authored-by: jokess123 <163112061+jokess123@users.noreply.github.com> Co-authored-by: slicejoke <163888128+slicejoke@users.noreply.github.com> --- bin/runtime-common/Cargo.toml | 1 - bin/runtime-common/src/lib.rs | 72 +- bin/runtime-common/src/mock.rs | 7 +- bin/runtime-common/src/priority_calculator.rs | 13 +- .../src/refund_relayer_extension.rs | 156 ++-- modules/grandpa/README.md | 2 +- modules/grandpa/src/mock.rs | 2 +- modules/messages/src/mock.rs | 4 +- modules/parachains/src/mock.rs | 2 +- modules/relayers/src/mock.rs | 4 +- modules/xcm-bridge-hub-router/src/mock.rs | 2 +- modules/xcm-bridge-hub/src/mock.rs | 4 +- .../chain-bridge-hub-cumulus/src/lib.rs | 4 +- primitives/chain-bridge-hub-rococo/src/lib.rs | 2 +- primitives/chain-kusama/src/lib.rs | 4 +- primitives/chain-polkadot-bulletin/src/lib.rs | 51 +- primitives/chain-polkadot/src/lib.rs | 4 +- primitives/chain-rococo/src/lib.rs | 4 +- primitives/chain-westend/src/lib.rs | 4 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/polkadot-core/src/lib.rs | 37 +- primitives/runtime/src/extensions.rs | 135 ++-- relays/bin-substrate/Cargo.toml | 2 +- relays/client-bridge-hub-kusama/src/lib.rs | 9 +- relays/client-bridge-hub-polkadot/src/lib.rs | 9 +- relays/client-bridge-hub-rococo/src/lib.rs | 9 +- relays/client-bridge-hub-westend/src/lib.rs | 9 +- relays/client-kusama/src/lib.rs | 6 +- relays/client-polkadot-bulletin/src/lib.rs | 8 +- relays/client-polkadot/src/lib.rs | 6 +- relays/client-rococo/src/lib.rs | 6 +- relays/client-substrate/Cargo.toml | 2 +- relays/client-westend/src/lib.rs | 6 +- relays/equivocation/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- testing/README.md | 31 + .../bridge_hub_rococo_local_network.toml | 88 ++ .../bridge_hub_westend_local_network.toml | 88 ++ .../rococo-westend/bridges_rococo_westend.sh | 401 +++++++++ testing/environments/rococo-westend/helper.sh | 3 + .../rococo-westend/rococo-init.zndsl | 8 + .../environments/rococo-westend/rococo.zndsl | 7 + testing/environments/rococo-westend/spawn.sh | 70 ++ .../rococo-westend/start_relayer.sh | 23 + .../rococo-westend/westend-init.zndsl | 7 + .../environments/rococo-westend/westend.zndsl | 6 + .../best-finalized-header-at-bridged-chain.js | 25 + .../js-helpers/chains/rococo-at-westend.js | 6 + .../js-helpers/chains/westend-at-rococo.js | 6 + .../native-assets-balance-increased.js | 21 + ...only-mandatory-headers-synced-when-idle.js | 44 + .../only-required-headers-synced-when-idle.js | 81 ++ .../framework/js-helpers/relayer-rewards.js | 28 + testing/framework/js-helpers/utils.js | 103 +++ .../js-helpers/wait-hrmp-channel-opened.js | 22 + .../js-helpers/wrapped-assets-balance.js | 26 + testing/framework/utils/bridges.sh | 309 +++++++ testing/framework/utils/common.sh | 45 ++ .../utils/generate_hex_encoded_call/index.js | 165 ++++ .../package-lock.json | 759 ++++++++++++++++++ .../generate_hex_encoded_call/package.json | 11 + testing/framework/utils/zombienet.sh | 39 + testing/run-new-test.sh | 48 ++ testing/run-tests.sh | 138 ++++ testing/scripts/invoke-script.sh | 7 + testing/scripts/start-relayer.sh | 7 + testing/scripts/sync-exit.sh | 14 + .../roc-reaches-westend.zndsl | 12 + testing/tests/0001-asset-transfer/run.sh | 25 + .../wnd-reaches-rococo.zndsl | 12 + .../wroc-reaches-rococo.zndsl | 10 + .../wwnd-reaches-westend.zndsl | 10 + .../rococo-to-westend.zndsl | 8 + .../run.sh | 35 + .../westend-to-rococo.zndsl | 7 + ...ynced-while-active-rococo-to-westend.zndsl | 26 + ...ynced-while-active-westend-to-rococo.zndsl | 26 + 81 files changed, 3069 insertions(+), 338 deletions(-) create mode 100644 testing/README.md create mode 100644 testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml create mode 100644 testing/environments/rococo-westend/bridge_hub_westend_local_network.toml create mode 100755 testing/environments/rococo-westend/bridges_rococo_westend.sh create mode 100755 testing/environments/rococo-westend/helper.sh create mode 100644 testing/environments/rococo-westend/rococo-init.zndsl create mode 100644 testing/environments/rococo-westend/rococo.zndsl create mode 100755 testing/environments/rococo-westend/spawn.sh create mode 100755 testing/environments/rococo-westend/start_relayer.sh create mode 100644 testing/environments/rococo-westend/westend-init.zndsl create mode 100644 testing/environments/rococo-westend/westend.zndsl create mode 100644 testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js create mode 100644 testing/framework/js-helpers/chains/rococo-at-westend.js create mode 100644 testing/framework/js-helpers/chains/westend-at-rococo.js create mode 100644 testing/framework/js-helpers/native-assets-balance-increased.js create mode 100644 testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js create mode 100644 testing/framework/js-helpers/only-required-headers-synced-when-idle.js create mode 100644 testing/framework/js-helpers/relayer-rewards.js create mode 100644 testing/framework/js-helpers/utils.js create mode 100644 testing/framework/js-helpers/wait-hrmp-channel-opened.js create mode 100644 testing/framework/js-helpers/wrapped-assets-balance.js create mode 100755 testing/framework/utils/bridges.sh create mode 100644 testing/framework/utils/common.sh create mode 100644 testing/framework/utils/generate_hex_encoded_call/index.js create mode 100644 testing/framework/utils/generate_hex_encoded_call/package-lock.json create mode 100644 testing/framework/utils/generate_hex_encoded_call/package.json create mode 100644 testing/framework/utils/zombienet.sh create mode 100755 testing/run-new-test.sh create mode 100755 testing/run-tests.sh create mode 100755 testing/scripts/invoke-script.sh create mode 100755 testing/scripts/start-relayer.sh create mode 100755 testing/scripts/sync-exit.sh create mode 100644 testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl create mode 100755 testing/tests/0001-asset-transfer/run.sh create mode 100644 testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl create mode 100644 testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl create mode 100644 testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl create mode 100644 testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl create mode 100755 testing/tests/0002-mandatory-headers-synced-while-idle/run.sh create mode 100644 testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl create mode 100644 testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl create mode 100644 testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index 835a8cf1318f3..e3c05d1bebbce 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -93,7 +93,6 @@ runtime-benchmarks = [ "pallet-bridge-messages/runtime-benchmarks", "pallet-bridge-parachains/runtime-benchmarks", "pallet-bridge-relayers/runtime-benchmarks", - "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", diff --git a/bin/runtime-common/src/lib.rs b/bin/runtime-common/src/lib.rs index 035077408c40b..2722f6f1c6d14 100644 --- a/bin/runtime-common/src/lib.rs +++ b/bin/runtime-common/src/lib.rs @@ -105,48 +105,43 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { ($call:ty, $account_id:ty, $($filter_call:ty),*) => { #[derive(Clone, codec::Decode, Default, codec::Encode, Eq, PartialEq, sp_runtime::RuntimeDebug, scale_info::TypeInfo)] pub struct BridgeRejectObsoleteHeadersAndMessages; - impl sp_runtime::traits::TransactionExtensionBase for BridgeRejectObsoleteHeadersAndMessages { + impl sp_runtime::traits::SignedExtension for BridgeRejectObsoleteHeadersAndMessages { const IDENTIFIER: &'static str = "BridgeRejectObsoleteHeadersAndMessages"; - type Implicit = (); - } - impl sp_runtime::traits::TransactionExtension<$call, Context> for BridgeRejectObsoleteHeadersAndMessages { + type AccountId = $account_id; + type Call = $call; + type AdditionalSigned = (); type Pre = (); - type Val = (); + + fn additional_signed(&self) -> sp_std::result::Result< + (), + sp_runtime::transaction_validity::TransactionValidityError, + > { + Ok(()) + } fn validate( &self, - origin: <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, - call: &$call, - _info: &sp_runtime::traits::DispatchInfoOf<$call>, + _who: &Self::AccountId, + call: &Self::Call, + _info: &sp_runtime::traits::DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl codec::Encode, - ) -> Result< - ( - sp_runtime::transaction_validity::ValidTransaction, - Self::Val, - <$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, - ), sp_runtime::transaction_validity::TransactionValidityError - > { - let tx_validity = sp_runtime::transaction_validity::ValidTransaction::default(); + ) -> sp_runtime::transaction_validity::TransactionValidity { + let valid = sp_runtime::transaction_validity::ValidTransaction::default(); $( - let call_filter_validity = <$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?; - let tx_validity = tx_validity.combine_with(call_filter_validity); + let valid = valid + .combine_with(<$filter_call as $crate::BridgeRuntimeFilterCall<$call>>::validate(call)?); )* - Ok((tx_validity, (), origin)) + Ok(valid) } - fn prepare( + fn pre_dispatch( self, - _val: Self::Val, - _origin: &<$call as sp_runtime::traits::Dispatchable>::RuntimeOrigin, - _call: &$call, - _info: &sp_runtime::traits::DispatchInfoOf<$call>, - _len: usize, - _context: &Context, + who: &Self::AccountId, + call: &Self::Call, + info: &sp_runtime::traits::DispatchInfoOf, + len: usize, ) -> Result { - Ok(()) + self.validate(who, call, info, len).map(drop) } } }; @@ -155,14 +150,12 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages { #[cfg(test)] mod tests { use crate::BridgeRuntimeFilterCall; - use codec::Encode; - use frame_support::assert_err; + use frame_support::{assert_err, assert_ok}; use sp_runtime::{ - traits::DispatchTransaction, + traits::SignedExtension, transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, }; - #[derive(Encode)] pub struct MockCall { data: u32, } @@ -213,20 +206,17 @@ mod tests { ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 1 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 1 }, &(), 0), InvalidTransaction::Custom(1) ); assert_err!( - BridgeRejectObsoleteHeadersAndMessages.validate_only((), &MockCall { data: 2 }, &(), 0), + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 2 }, &(), 0), InvalidTransaction::Custom(2) ); - assert_eq!( - BridgeRejectObsoleteHeadersAndMessages - .validate_only((), &MockCall { data: 3 }, &(), 0) - .unwrap() - .0, + assert_ok!( + BridgeRejectObsoleteHeadersAndMessages.validate(&(), &MockCall { data: 3 }, &(), 0), ValidTransaction { priority: 3, ..Default::default() } ) } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index f147f1404f06f..deee4524e8586 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -141,7 +141,7 @@ parameter_types! { pub const ReserveId: [u8; 8] = *b"brdgrlrs"; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Hash = ThisChainHash; type Hashing = ThisChainHasher; @@ -158,13 +158,13 @@ impl pallet_utility::Config for TestRuntime { type WeightInfo = (); } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; } -#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig as pallet_transaction_payment::DefaultConfig)] +#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)] impl pallet_transaction_payment::Config for TestRuntime { type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; @@ -177,6 +177,7 @@ impl pallet_transaction_payment::Config for TestRuntime { MinimumMultiplier, MaximumMultiplier, >; + type RuntimeEvent = RuntimeEvent; } impl pallet_bridge_grandpa::Config for TestRuntime { diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs index 0c53018330ea0..c2737128e3422 100644 --- a/bin/runtime-common/src/priority_calculator.rs +++ b/bin/runtime-common/src/priority_calculator.rs @@ -128,7 +128,7 @@ mod integrity_tests { Runtime::RuntimeCall: Dispatchable, BalanceOf: Send + Sync + FixedPointOperand, { - // esimate priority of transaction that delivers one message and has large tip + // estimate priority of transaction that delivers one message and has large tip let maximal_messages_in_delivery_transaction = Runtime::MaxUnconfirmedMessagesAtInboundLane::get(); let small_with_tip_priority = @@ -169,15 +169,12 @@ mod integrity_tests { // nodes to the proof (x0.5 because we expect some nodes to be reused) let estimated_message_size = 512; // let's say all our messages have the same dispatch weight - let estimated_message_dispatch_weight = >::WeightInfo::message_dispatch_weight( - estimated_message_size - ); + let estimated_message_dispatch_weight = + Runtime::WeightInfo::message_dispatch_weight(estimated_message_size); // messages proof argument size is (for every message) messages size + some additional // trie nodes. Some of them are reused by different messages, so let's take 2/3 of default // "overhead" constant - let messages_proof_size = >::WeightInfo::expected_extra_storage_proof_size() + let messages_proof_size = Runtime::WeightInfo::expected_extra_storage_proof_size() .saturating_mul(2) .saturating_div(3) .saturating_add(estimated_message_size) @@ -185,7 +182,7 @@ mod integrity_tests { // finally we are able to estimate transaction size and weight let transaction_size = base_tx_size.saturating_add(messages_proof_size); - let transaction_weight = >::WeightInfo::receive_messages_proof_weight( + let transaction_weight = Runtime::WeightInfo::receive_messages_proof_weight( &PreComputedSize(transaction_size as _), messages as _, estimated_message_dispatch_weight.saturating_mul(messages), diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index b912f8445ac1b..8e901d72821fe 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -16,7 +16,7 @@ //! Signed extension that refunds relayer if he has delivered some new messages. //! It also refunds transaction cost if the transaction is an `utility.batchAll()` -//! with calls that are: delivering new messsage and all necessary underlying headers +//! with calls that are: delivering new message and all necessary underlying headers //! (parachain or relay chain). use crate::messages_call_ext::{ @@ -48,12 +48,9 @@ use pallet_transaction_payment::{Config as TransactionPaymentConfig, OnChargeTra use pallet_utility::{Call as UtilityCall, Config as UtilityConfig, Pallet as UtilityPallet}; use scale_info::TypeInfo; use sp_runtime::{ - traits::{ - AsSystemOriginSigner, DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, - TransactionExtension, TransactionExtensionBase, ValidateResult, Zero, - }, + traits::{DispatchInfoOf, Dispatchable, Get, PostDispatchInfoOf, SignedExtension, Zero}, transaction_validity::{ - InvalidTransaction, TransactionPriority, TransactionValidityError, ValidTransactionBuilder, + TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransactionBuilder, }, DispatchResult, FixedPointOperand, RuntimeDebug, }; @@ -242,8 +239,8 @@ pub enum RelayerAccountAction { Slash(AccountId, RewardsAccountParams), } -/// Everything common among our refund transaction extensions. -pub trait RefundTransactionExtension: +/// Everything common among our refund signed extensions. +pub trait RefundSignedExtension: 'static + Clone + Codec + sp_std::fmt::Debug + Default + Eq + PartialEq + Send + Sync + TypeInfo where >::BridgedChain: @@ -459,8 +456,8 @@ where } } -/// Adapter that allow implementing `sp_runtime::traits::TransactionExtension` for any -/// `RefundTransactionExtension`. +/// Adapter that allow implementing `sp_runtime::traits::SignedExtension` for any +/// `RefundSignedExtension`. #[derive( DefaultNoBound, CloneNoBound, @@ -471,13 +468,12 @@ where RuntimeDebugNoBound, TypeInfo, )] -pub struct RefundTransactionExtensionAdapter(T) +pub struct RefundSignedExtensionAdapter(T) where >::BridgedChain: Chain; -impl TransactionExtensionBase - for RefundTransactionExtensionAdapter +impl SignedExtension for RefundSignedExtensionAdapter where >::BridgedChain: Chain, @@ -487,35 +483,22 @@ where + MessagesCallSubType::Instance>, { const IDENTIFIER: &'static str = T::Id::STR; - type Implicit = (); -} - -impl TransactionExtension, Context> - for RefundTransactionExtensionAdapter -where - >::BridgedChain: - Chain, - CallOf: Dispatchable - + IsSubType, T::Runtime>> - + GrandpaCallSubType - + MessagesCallSubType::Instance>, - as Dispatchable>::RuntimeOrigin: - AsSystemOriginSigner> + Clone, -{ + type AccountId = AccountIdOf; + type Call = CallOf; + type AdditionalSigned = (); type Pre = Option>>; - type Val = Option; + + fn additional_signed(&self) -> Result<(), TransactionValidityError> { + Ok(()) + } fn validate( &self, - origin: as Dispatchable>::RuntimeOrigin, - call: &CallOf, - _info: &DispatchInfoOf>, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &mut Context, - _self_implicit: Self::Implicit, - _inherited_implication: &impl Encode, - ) -> ValidateResult> { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; + ) -> TransactionValidity { // this is the only relevant line of code for the `pre_dispatch` // // we're not calling `validate` from `pre_dispatch` directly because of performance @@ -528,12 +511,12 @@ where // we only boost priority of presumably correct message delivery transactions let bundled_messages = match T::bundled_messages_for_priority_boost(parsed_call.as_ref()) { Some(bundled_messages) => bundled_messages, - None => return Ok((Default::default(), parsed_call, origin)), + None => return Ok(Default::default()), }; // we only boost priority if relayer has staked required balance if !RelayersPallet::::is_registration_active(who) { - return Ok((Default::default(), parsed_call, origin)) + return Ok(Default::default()) } // compute priority boost @@ -552,21 +535,20 @@ where priority_boost, ); - let validity = valid_transaction.build()?; - Ok((validity, parsed_call, origin)) + valid_transaction.build() } - fn prepare( + fn pre_dispatch( self, - val: Self::Val, - origin: & as Dispatchable>::RuntimeOrigin, - _call: &CallOf, - _info: &DispatchInfoOf>, + who: &Self::AccountId, + call: &Self::Call, + _info: &DispatchInfoOf, _len: usize, - _context: &Context, ) -> Result { - let who = origin.as_system_origin_signer().ok_or(InvalidTransaction::BadSigner)?; - Ok(val.map(|call_info| { + // this is a relevant piece of `validate` that we need here (in `pre_dispatch`) + let parsed_call = T::parse_and_check_for_obsolete_call(call)?; + + Ok(parsed_call.map(|call_info| { log::trace!( target: "runtime::bridge", "{} via {:?} parsed bridge transaction in pre-dispatch: {:?}", @@ -579,14 +561,13 @@ where } fn post_dispatch( - pre: Self::Pre, - info: &DispatchInfoOf>, - post_info: &PostDispatchInfoOf>, + pre: Option, + info: &DispatchInfoOf, + post_info: &PostDispatchInfoOf, len: usize, result: &DispatchResult, - _context: &Context, ) -> Result<(), TransactionValidityError> { - let call_result = T::analyze_call_result(Some(pre), info, post_info, len, result); + let call_result = T::analyze_call_result(pre, info, post_info, len, result); match call_result { RelayerAccountAction::None => (), @@ -614,7 +595,7 @@ where } } -/// Transaction extension that refunds a relayer for new messages coming from a parachain. +/// Signed extension that refunds a relayer for new messages coming from a parachain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and @@ -655,7 +636,7 @@ pub struct RefundBridgedParachainMessages, ); -impl RefundTransactionExtension +impl RefundSignedExtension for RefundBridgedParachainMessages where Self: 'static + Send + Sync, @@ -749,13 +730,13 @@ where } } -/// Transaction extension that refunds a relayer for new messages coming from a standalone (GRANDPA) +/// Signed extension that refunds a relayer for new messages coming from a standalone (GRANDPA) /// chain. /// /// Also refunds relayer for successful finality delivery if it comes in batch (`utility.batchAll`) /// with message delivery transaction. Batch may deliver either both relay chain header and -/// parachain head, or just parachain head. Corresponding headers must be used in messages proof -/// verification. +/// parachain head, or just parachain head. Corresponding headers must be used in messages +/// proof verification. /// /// Extension does not refund transaction tip due to security reasons. #[derive( @@ -790,7 +771,7 @@ pub struct RefundBridgedGrandpaMessages, ); -impl RefundTransactionExtension +impl RefundSignedExtension for RefundBridgedGrandpaMessages where Self: 'static + Send + Sync, @@ -888,8 +869,8 @@ mod tests { Call as ParachainsCall, Pallet as ParachainsPallet, RelayBlockHash, }; use sp_runtime::{ - traits::{ConstU64, DispatchTransaction, Header as HeaderT}, - transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction}, + traits::{ConstU64, Header as HeaderT}, + transaction_validity::{InvalidTransaction, ValidTransaction}, DispatchError, }; @@ -918,7 +899,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestGrandpaExtension = RefundTransactionExtensionAdapter; + type TestGrandpaExtension = RefundSignedExtensionAdapter; type TestExtensionProvider = RefundBridgedParachainMessages< TestRuntime, DefaultRefundableParachainId<(), TestParachain>, @@ -927,7 +908,7 @@ mod tests { ConstU64<1>, StrTestExtension, >; - type TestExtension = RefundTransactionExtensionAdapter; + type TestExtension = RefundSignedExtensionAdapter; fn initial_balance_of_relayer_account_at_this_chain() -> ThisChainBalance { let test_stake: ThisChainBalance = TestStake::get(); @@ -1426,28 +1407,14 @@ mod tests { fn run_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestExtension = - RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension - .validate_only( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|res| res.0) + RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_grandpa_validate(call: RuntimeCall) -> TransactionValidity { let extension: TestGrandpaExtension = - RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension - .validate_only( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|res| res.0) + RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension.validate(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_validate_ignore_priority(call: RuntimeCall) -> TransactionValidity { @@ -1461,30 +1428,16 @@ mod tests { call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestExtension = - RefundTransactionExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); - extension - .validate_and_prepare( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|(pre, _)| pre) + RefundSignedExtensionAdapter(RefundBridgedParachainMessages(PhantomData)); + extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn run_grandpa_pre_dispatch( call: RuntimeCall, ) -> Result>, TransactionValidityError> { let extension: TestGrandpaExtension = - RefundTransactionExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); - extension - .validate_and_prepare( - Some(relayer_account_at_this_chain()).into(), - &call, - &DispatchInfo::default(), - 0, - ) - .map(|(pre, _)| pre) + RefundSignedExtensionAdapter(RefundBridgedGrandpaMessages(PhantomData)); + extension.pre_dispatch(&relayer_account_at_this_chain(), &call, &DispatchInfo::default(), 0) } fn dispatch_info() -> DispatchInfo { @@ -1507,12 +1460,11 @@ mod tests { dispatch_result: DispatchResult, ) { let post_dispatch_result = TestExtension::post_dispatch( - pre_dispatch_data, + Some(pre_dispatch_data), &dispatch_info(), &post_dispatch_info(), 1024, &dispatch_result, - &(), ); assert_eq!(post_dispatch_result, Ok(())); } diff --git a/modules/grandpa/README.md b/modules/grandpa/README.md index 43ee5c316d1b7..992bd2cc47228 100644 --- a/modules/grandpa/README.md +++ b/modules/grandpa/README.md @@ -27,7 +27,7 @@ for provided header. There are two main things in GRANDPA that help building light clients: - there's no need to import all headers of the bridged chain. Light client may import finalized headers or just - some of finalized headders that it consider useful. While the validators set stays the same, the client may + some of finalized headers that it consider useful. While the validators set stays the same, the client may import any header that is finalized by this set; - when validators set changes, the GRANDPA gadget adds next set to the header. So light client doesn't need to diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index e41e89341b312..4318d663a2e17 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -42,7 +42,7 @@ construct_runtime! { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; } diff --git a/modules/messages/src/mock.rs b/modules/messages/src/mock.rs index af92120539854..ec63f15b94b52 100644 --- a/modules/messages/src/mock.rs +++ b/modules/messages/src/mock.rs @@ -77,14 +77,14 @@ frame_support::construct_runtime! { pub type DbWeight = RocksDbWeight; -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; type AccountData = pallet_balances::AccountData; type DbWeight = DbWeight; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 143f11d986371..3af3fd3e76398 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -161,7 +161,7 @@ construct_runtime! { } } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; } diff --git a/modules/relayers/src/mock.rs b/modules/relayers/src/mock.rs index 667b10e5c125e..3124787896c3e 100644 --- a/modules/relayers/src/mock.rs +++ b/modules/relayers/src/mock.rs @@ -59,14 +59,14 @@ parameter_types! { pub const Lease: BlockNumber = 8; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; type AccountData = pallet_balances::AccountData; type DbWeight = DbWeight; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type ReserveIdentifier = [u8; 8]; type AccountStore = System; diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/modules/xcm-bridge-hub-router/src/mock.rs index 6dbfba5f6fdc1..54e10966d51b2 100644 --- a/modules/xcm-bridge-hub-router/src/mock.rs +++ b/modules/xcm-bridge-hub-router/src/mock.rs @@ -64,7 +64,7 @@ parameter_types! { pub UnknownXcmVersionLocation: Location = Location::new(2, [GlobalConsensus(BridgedNetworkId::get()), Parachain(9999)]); } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type Block = Block; } diff --git a/modules/xcm-bridge-hub/src/mock.rs b/modules/xcm-bridge-hub/src/mock.rs index e40e1f9fb6515..4c09bce56d73e 100644 --- a/modules/xcm-bridge-hub/src/mock.rs +++ b/modules/xcm-bridge-hub/src/mock.rs @@ -64,7 +64,7 @@ parameter_types! { pub const ExistentialDeposit: Balance = 1; } -#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] impl frame_system::Config for TestRuntime { type AccountId = AccountId; type AccountData = pallet_balances::AccountData; @@ -72,7 +72,7 @@ impl frame_system::Config for TestRuntime { type Lookup = IdentityLookup; } -#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)] +#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)] impl pallet_balances::Config for TestRuntime { type AccountStore = System; } diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index f186f6427ae7d..c49aa4b856397 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -26,7 +26,7 @@ pub use bp_polkadot_core::{ }; use bp_messages::*; -use bp_polkadot_core::SuffixedCommonTransactionExtension; +use bp_polkadot_core::SuffixedCommonSignedExtension; use bp_runtime::extensions::{ BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, }; @@ -164,7 +164,7 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// Signed extension that is used by all bridge hubs. -pub type TransactionExtension = SuffixedCommonTransactionExtension<( +pub type SignedExtension = SuffixedCommonSignedExtension<( BridgeRejectObsoleteHeadersAndMessages, RefundBridgedParachainMessagesSchema, )>; diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/primitives/chain-bridge-hub-rococo/src/lib.rs index 992ef1bd7a10f..c4e697fbe9526 100644 --- a/primitives/chain-bridge-hub-rococo/src/lib.rs +++ b/primitives/chain-bridge-hub-rococo/src/lib.rs @@ -107,5 +107,5 @@ frame_support::parameter_types! { /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. /// (initially was calculated by test `BridgeHubRococo::can_calculate_fee_for_complex_message_confirmation_transaction` + `33%`) - pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_904_835; + pub const BridgeHubRococoBaseConfirmationFeeInRocs: u128 = 5_380_829_647; } diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 253a1010e83df..e3b4d0520f61c 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Kusama { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The TransactionExtension used by Kusama. -pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; +// The SignedExtension used by Kusama. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; /// Name of the parachains pallet in the Kusama runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/primitives/chain-polkadot-bulletin/src/lib.rs index 73dd122bd1538..f2eebf9312470 100644 --- a/primitives/chain-polkadot-bulletin/src/lib.rs +++ b/primitives/chain-polkadot-bulletin/src/lib.rs @@ -25,7 +25,7 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, extensions::{ CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, CheckSpecVersion, CheckTxVersion, - CheckWeight, GenericTransactionExtension, GenericTransactionExtensionSchema, + CheckWeight, GenericSignedExtension, GenericSignedExtensionSchema, }, Chain, ChainId, TransactionEra, }; @@ -37,12 +37,7 @@ use frame_support::{ }; use frame_system::limits; use scale_info::TypeInfo; -use sp_runtime::{ - impl_tx_ext_default, - traits::{Dispatchable, TransactionExtensionBase}, - transaction_validity::TransactionValidityError, - Perbill, -}; +use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidityError, Perbill}; // This chain reuses most of Polkadot primitives. pub use bp_polkadot_core::{ @@ -76,10 +71,10 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; /// This signed extension is used to ensure that the chain transactions are signed by proper -pub type ValidateSigned = GenericTransactionExtensionSchema<(), ()>; +pub type ValidateSigned = GenericSignedExtensionSchema<(), ()>; /// Signed extension schema, used by Polkadot Bulletin. -pub type TransactionExtensionSchema = GenericTransactionExtension<( +pub type SignedExtensionSchema = GenericSignedExtension<( ( CheckNonZeroSender, CheckSpecVersion, @@ -92,30 +87,34 @@ pub type TransactionExtensionSchema = GenericTransactionExtension<( ValidateSigned, )>; -/// Transaction extension, used by Polkadot Bulletin. +/// Signed extension, used by Polkadot Bulletin. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct TransactionExtension(TransactionExtensionSchema); +pub struct SignedExtension(SignedExtensionSchema); -impl TransactionExtensionBase for TransactionExtension { +impl sp_runtime::traits::SignedExtension for SignedExtension { const IDENTIFIER: &'static str = "Not needed."; - type Implicit = ::Implicit; + type AccountId = (); + type Call = (); + type AdditionalSigned = + ::AdditionalSigned; + type Pre = (); - fn implicit(&self) -> Result { - ::implicit(&self.0) + fn additional_signed(&self) -> Result { + self.0.additional_signed() } -} -impl sp_runtime::traits::TransactionExtension for TransactionExtension -where - C: Dispatchable, -{ - type Pre = (); - type Val = (); - - impl_tx_ext_default!(C; Context; validate prepare); + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } } -impl TransactionExtension { +impl SignedExtension { /// Create signed extension from its components. pub fn from_params( spec_version: u32, @@ -124,7 +123,7 @@ impl TransactionExtension { genesis_hash: Hash, nonce: Nonce, ) -> Self { - Self(GenericTransactionExtension::new( + Self(GenericSignedExtension::new( ( ( (), // non-zero sender diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index e5e2e7c3a042a..fc5e10308a8e3 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -61,8 +61,8 @@ impl ChainWithGrandpa for Polkadot { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -/// The TransactionExtension used by Polkadot. -pub type TransactionExtension = SuffixedCommonTransactionExtension; +/// The SignedExtension used by Polkadot. +pub type SignedExtension = SuffixedCommonSignedExtension; /// Name of the parachains pallet in the Polkadot runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index 267c6b2b1f029..f1b256f0f090f 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Rococo { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The TransactionExtension used by Rococo. -pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; +// The SignedExtension used by Rococo. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index afa02e8ee541e..f03fd2160a700 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -59,8 +59,8 @@ impl ChainWithGrandpa for Westend { const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } -// The TransactionExtension used by Westend. -pub use bp_polkadot_core::CommonTransactionExtension as TransactionExtension; +// The SignedExtension used by Westend. +pub use bp_polkadot_core::CommonSignedExtension as SignedExtension; /// Name of the parachains pallet in the Rococo runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index dd3912429d669..4851ce14c0dad 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -serde = { default-features = false, features = ["derive"], optional = true, workspace = true } +serde = { optional = true, features = ["derive"], workspace = true, default-features = true } # Bridge Dependencies diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index d59b99db4b586..df2836495bbe1 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -24,8 +24,8 @@ use bp_runtime::{ self, extensions::{ ChargeTransactionPayment, CheckEra, CheckGenesis, CheckNonZeroSender, CheckNonce, - CheckSpecVersion, CheckTxVersion, CheckWeight, GenericTransactionExtension, - TransactionExtensionSchema, + CheckSpecVersion, CheckTxVersion, CheckWeight, GenericSignedExtension, + SignedExtensionSchema, }, EncodedOrDecodedCall, StorageMapKeyProvider, TransactionEra, }; @@ -229,12 +229,8 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< - AccountAddress, - EncodedOrDecodedCall, - Signature, - TransactionExt, ->; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic, Signature, SignedExt>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; @@ -279,7 +275,7 @@ impl AccountInfoStorageMapKeyProvider { } /// Extra signed extension data that is used by most chains. -pub type CommonTransactionExtra = ( +pub type CommonSignedExtra = ( CheckNonZeroSender, CheckSpecVersion, CheckTxVersion, @@ -290,12 +286,12 @@ pub type CommonTransactionExtra = ( ChargeTransactionPayment, ); -/// Extra transaction extension data that starts with `CommonTransactionExtra`. -pub type SuffixedCommonTransactionExtension = - GenericTransactionExtension<(CommonTransactionExtra, Suffix)>; +/// Extra signed extension data that starts with `CommonSignedExtra`. +pub type SuffixedCommonSignedExtension = + GenericSignedExtension<(CommonSignedExtra, Suffix)>; -/// Helper trait to define some extra methods on `SuffixedCommonTransactionExtension`. -pub trait SuffixedCommonTransactionExtensionExt { +/// Helper trait to define some extra methods on `SuffixedCommonSignedExtension`. +pub trait SuffixedCommonSignedExtensionExt { /// Create signed extension from its components. fn from_params( spec_version: u32, @@ -304,7 +300,7 @@ pub trait SuffixedCommonTransactionExtensionExt Self; /// Return transaction nonce. @@ -314,10 +310,9 @@ pub trait SuffixedCommonTransactionExtensionExt Balance; } -impl SuffixedCommonTransactionExtensionExt - for SuffixedCommonTransactionExtension +impl SuffixedCommonSignedExtensionExt for SuffixedCommonSignedExtension where - Suffix: TransactionExtensionSchema, + Suffix: SignedExtensionSchema, { fn from_params( spec_version: u32, @@ -326,9 +321,9 @@ where genesis_hash: Hash, nonce: Nonce, tip: Balance, - extra: (Suffix::Payload, Suffix::Implicit), + extra: (Suffix::Payload, Suffix::AdditionalSigned), ) -> Self { - GenericTransactionExtension::new( + GenericSignedExtension::new( ( ( (), // non-zero sender @@ -370,7 +365,7 @@ where } /// Signed extension that is used by most chains. -pub type CommonTransactionExtension = SuffixedCommonTransactionExtension<()>; +pub type CommonSignedExtension = SuffixedCommonSignedExtension<()>; #[cfg(test)] mod tests { diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index a31e7b5bb47a6..d896bc92efffc 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -20,138 +20,135 @@ use codec::{Compact, Decode, Encode}; use impl_trait_for_tuples::impl_for_tuples; use scale_info::{StaticTypeInfo, TypeInfo}; use sp_runtime::{ - impl_tx_ext_default, - traits::{Dispatchable, TransactionExtension, TransactionExtensionBase}, + traits::{DispatchInfoOf, SignedExtension}, transaction_validity::TransactionValidityError, }; use sp_std::{fmt::Debug, marker::PhantomData}; -/// Trait that describes some properties of a `TransactionExtension` that are needed in order to -/// send a transaction to the chain. -pub trait TransactionExtensionSchema: - Encode + Decode + Debug + Eq + Clone + StaticTypeInfo -{ +/// Trait that describes some properties of a `SignedExtension` that are needed in order to send a +/// transaction to the chain. +pub trait SignedExtensionSchema: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo { /// A type of the data encoded as part of the transaction. type Payload: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; /// Parameters which are part of the payload used to produce transaction signature, /// but don't end up in the transaction itself (i.e. inherent part of the runtime). - type Implicit: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo; + type AdditionalSigned: Encode + Debug + Eq + Clone + StaticTypeInfo; } -impl TransactionExtensionSchema for () { +impl SignedExtensionSchema for () { type Payload = (); - type Implicit = (); + type AdditionalSigned = (); } -/// An implementation of `TransactionExtensionSchema` using generic params. +/// An implementation of `SignedExtensionSchema` using generic params. #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] -pub struct GenericTransactionExtensionSchema(PhantomData<(P, S)>); +pub struct GenericSignedExtensionSchema(PhantomData<(P, S)>); -impl TransactionExtensionSchema for GenericTransactionExtensionSchema +impl SignedExtensionSchema for GenericSignedExtensionSchema where P: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, - S: Encode + Decode + Debug + Eq + Clone + StaticTypeInfo, + S: Encode + Debug + Eq + Clone + StaticTypeInfo, { type Payload = P; - type Implicit = S; + type AdditionalSigned = S; } -/// The `TransactionExtensionSchema` for `frame_system::CheckNonZeroSender`. -pub type CheckNonZeroSender = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `frame_system::CheckNonZeroSender`. +pub type CheckNonZeroSender = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `frame_system::CheckSpecVersion`. -pub type CheckSpecVersion = GenericTransactionExtensionSchema<(), u32>; +/// The `SignedExtensionSchema` for `frame_system::CheckSpecVersion`. +pub type CheckSpecVersion = GenericSignedExtensionSchema<(), u32>; -/// The `TransactionExtensionSchema` for `frame_system::CheckTxVersion`. -pub type CheckTxVersion = GenericTransactionExtensionSchema<(), u32>; +/// The `SignedExtensionSchema` for `frame_system::CheckTxVersion`. +pub type CheckTxVersion = GenericSignedExtensionSchema<(), u32>; -/// The `TransactionExtensionSchema` for `frame_system::CheckGenesis`. -pub type CheckGenesis = GenericTransactionExtensionSchema<(), Hash>; +/// The `SignedExtensionSchema` for `frame_system::CheckGenesis`. +pub type CheckGenesis = GenericSignedExtensionSchema<(), Hash>; -/// The `TransactionExtensionSchema` for `frame_system::CheckEra`. -pub type CheckEra = GenericTransactionExtensionSchema; +/// The `SignedExtensionSchema` for `frame_system::CheckEra`. +pub type CheckEra = GenericSignedExtensionSchema; -/// The `TransactionExtensionSchema` for `frame_system::CheckNonce`. -pub type CheckNonce = GenericTransactionExtensionSchema, ()>; +/// The `SignedExtensionSchema` for `frame_system::CheckNonce`. +pub type CheckNonce = GenericSignedExtensionSchema, ()>; -/// The `TransactionExtensionSchema` for `frame_system::CheckWeight`. -pub type CheckWeight = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `frame_system::CheckWeight`. +pub type CheckWeight = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. -pub type ChargeTransactionPayment = - GenericTransactionExtensionSchema, ()>; +/// The `SignedExtensionSchema` for `pallet_transaction_payment::ChargeTransactionPayment`. +pub type ChargeTransactionPayment = GenericSignedExtensionSchema, ()>; -/// The `TransactionExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. -pub type PrevalidateAttests = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `polkadot-runtime-common::PrevalidateAttests`. +pub type PrevalidateAttests = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. -pub type BridgeRejectObsoleteHeadersAndMessages = GenericTransactionExtensionSchema<(), ()>; +/// The `SignedExtensionSchema` for `BridgeRejectObsoleteHeadersAndMessages`. +pub type BridgeRejectObsoleteHeadersAndMessages = GenericSignedExtensionSchema<(), ()>; -/// The `TransactionExtensionSchema` for `RefundBridgedParachainMessages`. +/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`. /// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as /// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), /// ())` is the same. So runtime can contains any kind of tuple: /// `(BridgeRefundBridgeHubRococoMessages)` /// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWestendMessages)` /// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` -pub type RefundBridgedParachainMessagesSchema = GenericTransactionExtensionSchema<(), ()>; +pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; #[impl_for_tuples(1, 12)] -impl TransactionExtensionSchema for Tuple { +impl SignedExtensionSchema for Tuple { for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); - for_tuples!( type Implicit = ( #( Tuple::Implicit ),* ); ); + for_tuples!( type AdditionalSigned = ( #( Tuple::AdditionalSigned ),* ); ); } /// A simplified version of signed extensions meant for producing signed transactions /// and signed payloads in the client code. #[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub struct GenericTransactionExtension { +pub struct GenericSignedExtension { /// A payload that is included in the transaction. pub payload: S::Payload, #[codec(skip)] // It may be set to `None` if extensions are decoded. We are never reconstructing transactions - // (and it makes no sense to do that) => decoded version of `TransactionExtensions` is only - // used to read fields of the `payload`. And when resigning transaction, we're reconstructing - // `TransactionExtensions` from scratch. - implicit: Option, + // (and it makes no sense to do that) => decoded version of `SignedExtensions` is only used to + // read fields of the `payload`. And when resigning transaction, we're reconstructing + // `SignedExtensions` from scratch. + additional_signed: Option, } -impl GenericTransactionExtension { - /// Create new `GenericTransactionExtension` object. - pub fn new(payload: S::Payload, implicit: Option) -> Self { - Self { payload, implicit } +impl GenericSignedExtension { + /// Create new `GenericSignedExtension` object. + pub fn new(payload: S::Payload, additional_signed: Option) -> Self { + Self { payload, additional_signed } } } -impl TransactionExtensionBase for GenericTransactionExtension +impl SignedExtension for GenericSignedExtension where - S: TransactionExtensionSchema, + S: SignedExtensionSchema, S::Payload: Send + Sync, - S::Implicit: Send + Sync, + S::AdditionalSigned: Send + Sync, { const IDENTIFIER: &'static str = "Not needed."; - type Implicit = S::Implicit; + type AccountId = (); + type Call = (); + type AdditionalSigned = S::AdditionalSigned; + type Pre = (); - fn implicit(&self) -> Result { + fn additional_signed(&self) -> Result { // we shall not ever see this error in relay, because we are never signing decoded // transactions. Instead we're constructing and signing new transactions. So the error code // is kinda random here - self.implicit - .clone() - .ok_or(frame_support::unsigned::TransactionValidityError::Unknown( + self.additional_signed.clone().ok_or( + frame_support::unsigned::TransactionValidityError::Unknown( frame_support::unsigned::UnknownTransaction::Custom(0xFF), - )) + ), + ) } -} -impl TransactionExtension for GenericTransactionExtension -where - C: Dispatchable, - S: TransactionExtensionSchema, - S::Payload: Send + Sync, - S::Implicit: Send + Sync, -{ - type Pre = (); - type Val = (); - impl_tx_ext_default!(C; Context; validate prepare); + fn pre_dispatch( + self, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, + ) -> Result { + Ok(()) + } } diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index d5873752e22f8..2b89ce4f1989c 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] anyhow = "1.0" async-std = "1.9.0" -async-trait = "0.1" +async-trait = "0.1.74" codec = { package = "parity-scale-codec", version = "3.1.5" } env_logger = "0.11" futures = "0.3.30" diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs index 80f621dee302b..43dd53d2d83a2 100644 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ b/relays/client-bridge-hub-kusama/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_kusama::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot::SuffixedCommonTransactionExtensionExt; +use bp_bridge_hub_kusama::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -37,8 +37,7 @@ pub type RuntimeCall = runtime_types::bridge_hub_kusama_runtime::RuntimeCall; pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = - bp_bridge_hub_kusama::UncheckedExtrinsic; +type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Kusama chain definition @@ -88,7 +87,7 @@ impl ChainWithTransactions for BridgeHubKusama { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - TransactionExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs index ed147e92d5bd5..88b69065f8421 100644 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ b/relays/client-bridge-hub-polkadot/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_polkadot::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_bridge_hub_polkadot::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -41,8 +41,7 @@ pub type BridgeKusamaMessagesCall = runtime_types::pallet_bridge_messages::palle pub type BridgePolkadotBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeKusamaGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = - bp_bridge_hub_polkadot::UncheckedExtrinsic; +type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Polkadot chain definition @@ -92,7 +91,7 @@ impl ChainWithTransactions for BridgeHubPolkadot { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - TransactionExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index 169135646d94b..cae9e4f77a501 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_rococo::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_bridge_hub_rococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -39,8 +39,7 @@ pub type BridgeBulletinMessagesCall = runtime_types::pallet_bridge_messages::pal pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call2; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = - bp_bridge_hub_rococo::UncheckedExtrinsic; +type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Rococo chain definition @@ -90,7 +89,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - TransactionExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs index 5e4462f863aa1..049fa4649609e 100644 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ b/relays/client-bridge-hub-westend/src/lib.rs @@ -18,8 +18,8 @@ pub mod codegen_runtime; -use bp_bridge_hub_westend::{TransactionExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_bridge_hub_westend::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, @@ -37,8 +37,7 @@ pub type RuntimeCall = runtime_types::bridge_hub_westend_runtime::RuntimeCall; pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = - bp_bridge_hub_westend::UncheckedExtrinsic; +type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic; type UtilityCall = runtime_types::pallet_utility::pallet::Call; /// Westend chain definition @@ -88,7 +87,7 @@ impl ChainWithTransactions for BridgeHubWestend { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - TransactionExtension::from_params( + SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index a953a383e1290..24a6adfe95d4c 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -19,7 +19,7 @@ pub mod codegen_runtime; use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, @@ -84,7 +84,7 @@ impl RelayChain for Kusama { impl ChainWithTransactions for Kusama { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -92,7 +92,7 @@ impl ChainWithTransactions for Kusama { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_kusama::TransactionExtension::from_params( + bp_kusama::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs index a6cdd8ee675cf..1f18b25a9054a 100644 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ b/relays/client-polkadot-bulletin/src/lib.rs @@ -100,10 +100,8 @@ impl ChainWithBalances for PolkadotBulletin { impl ChainWithTransactions for PolkadotBulletin { type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = bp_polkadot_bulletin::UncheckedExtrinsic< - Self::Call, - bp_polkadot_bulletin::TransactionExtension, - >; + type SignedTransaction = + bp_polkadot_bulletin::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -111,7 +109,7 @@ impl ChainWithTransactions for PolkadotBulletin { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot_bulletin::TransactionExtension::from_params( + bp_polkadot_bulletin::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index af75f0dbb8713..9b655528b6e4e 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -19,7 +19,7 @@ mod codegen_runtime; use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use codec::Encode; use relay_substrate_client::{ Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, @@ -84,7 +84,7 @@ impl RelayChain for Polkadot { impl ChainWithTransactions for Polkadot { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -92,7 +92,7 @@ impl ChainWithTransactions for Polkadot { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_polkadot::TransactionExtension::from_params( + bp_polkadot::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index 5fad80d5c9886..575660504b3a5 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -18,7 +18,7 @@ pub mod codegen_runtime; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ @@ -84,7 +84,7 @@ impl RelayChain for Rococo { impl ChainWithTransactions for Rococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -92,7 +92,7 @@ impl ChainWithTransactions for Rococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_rococo::TransactionExtension::from_params( + bp_rococo::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index ea02a0ad20159..48895eff39dae 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1" +async-trait = "0.1.74" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 737c6c08519e1..42206baecf8f6 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -18,7 +18,7 @@ pub mod codegen_runtime; -use bp_polkadot_core::SuffixedCommonTransactionExtensionExt; +use bp_polkadot_core::SuffixedCommonSignedExtensionExt; use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; use codec::Encode; use relay_substrate_client::{ @@ -84,7 +84,7 @@ impl ChainWithBalances for Westend { impl ChainWithTransactions for Westend { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; + bp_polkadot_core::UncheckedExtrinsic; fn sign_transaction( param: SignParam, @@ -92,7 +92,7 @@ impl ChainWithTransactions for Westend { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_westend::TransactionExtension::from_params( + bp_westend::SignedExtension::from_params( param.spec_version, param.transaction_version, unsigned.era, diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 0b4a7e983a3a8..23dd4a087f97b 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1" +async-trait = "0.1.74" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 9e8bf56f53aaa..80159b4db62a7 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-std = "1.6.5" -async-trait = "0.1" +async-trait = "0.1.74" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.30" diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index d85e2762a4e33..27c5ee02c759f 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] anyhow = "1.0" async-std = "1.9.0" -async-trait = "0.1" +async-trait = "0.1.74" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" hex = "0.4" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 3367e4bbd4439..699649dd619d7 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1" +async-trait = "0.1.74" env_logger = "0.11" futures = "0.3.30" hex = "0.4" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 9dc35343b48c6..d2eea9eb6a77a 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] async-std = "1.6.5" -async-trait = "0.1" +async-trait = "0.1.74" futures = "0.3.30" log = { workspace = true } relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index ed6093318a0dc..81574a6855148 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -12,7 +12,7 @@ workspace = true ansi_term = "0.12" anyhow = "1.0" async-std = "1.6.5" -async-trait = "0.1" +async-trait = "0.1.74" backoff = "0.4" isahc = "1.2" env_logger = "0.11.3" diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 0000000000000..bd467a410d013 --- /dev/null +++ b/testing/README.md @@ -0,0 +1,31 @@ +# Bridges Tests for Local Rococo <> Westend Bridge + +This folder contains [zombienet](https://github.com/paritytech/zombienet/) based integration tests for both +onchain and offchain bridges code. Due to some +[technical difficulties](https://github.com/paritytech/parity-bridges-common/pull/2649#issue-1965339051), we +are using native zombienet provider, which means that you need to build some binaries locally. + +To start those tests, you need to: + +- download latest [zombienet release](https://github.com/paritytech/zombienet/releases); + +- build Polkadot binary by running `cargo build -p polkadot --release --features fast-runtime` command in the +[`polkadot-sdk`](https://github.com/paritytech/polkadot-sdk) repository clone; + +- build Polkadot Parachain binary by running `cargo build -p polkadot-parachain-bin --release` command in the +[`polkadot-sdk`](https://github.com/paritytech/polkadot-sdk) repository clone; + +- ensure that you have [`node`](https://nodejs.org/en) installed. Additionally, we'll need globally installed +`polkadot/api-cli` package (use `npm install -g @polkadot/api-cli@beta` to install it); + +- build Substrate relay by running `cargo build -p substrate-relay --release` command in the +[`parity-bridges-common`](https://github.com/paritytech/parity-bridges-common) repository clone. + +- copy fresh `substrate-relay` binary, built in previous point, to the `~/local_bridge_testing/bin/substrate-relay`; + +- change the `POLKADOT_SDK_PATH` and `ZOMBIENET_BINARY_PATH` (and ensure that the nearby variables +have correct values) in the `./run-tests.sh`. + +After that, you could run tests with the `./run-tests.sh` command. Hopefully, it'll show the +"All tests have completed successfully" message in the end. Otherwise, it'll print paths to zombienet +process logs, which, in turn, may be used to track locations of all spinned relay and parachain nodes. diff --git a/testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml b/testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml new file mode 100644 index 0000000000000..52271f9442131 --- /dev/null +++ b/testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml @@ -0,0 +1,88 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY}}" +default_args = [ "-lparachain=debug,xcm=trace" ] +chain = "rococo-local" + + [[relaychain.nodes]] + name = "alice-rococo-validator" + validator = true + rpc_port = 9932 + ws_port = 9942 + balance = 2000000000000 + + [[relaychain.nodes]] + name = "bob-rococo-validator" + validator = true + rpc_port = 9933 + ws_port = 9943 + balance = 2000000000000 + + [[relaychain.nodes]] + name = "charlie-rococo-validator" + validator = true + rpc_port = 9934 + ws_port = 9944 + balance = 2000000000000 + +[[parachains]] +id = 1013 +chain = "bridge-hub-rococo-local" +cumulus_based = true + + # run alice as parachain collator + [[parachains.collators]] + name = "bridge-hub-rococo-collator1" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY}}" + rpc_port = 8933 + ws_port = 8943 + args = [ + "-lparachain=debug,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" + ] + + # run bob as parachain collator + [[parachains.collators]] + name = "bridge-hub-rococo-collator2" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY}}" + rpc_port = 8934 + ws_port = 8944 + args = [ + "-lparachain=trace,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" + ] + +[[parachains]] +id = 1000 +chain = "asset-hub-rococo-local" +cumulus_based = true + + [[parachains.collators]] + name = "asset-hub-rococo-collator1" + rpc_port = 9911 + ws_port = 9910 + command = "{{POLKADOT_PARACHAIN_BINARY}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" + ] + + [[parachains.collators]] + name = "asset-hub-rococo-collator2" + command = "{{POLKADOT_PARACHAIN_BINARY}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" + ] + +#[[hrmp_channels]] +#sender = 1000 +#recipient = 1013 +#max_capacity = 4 +#max_message_size = 524288 +# +#[[hrmp_channels]] +#sender = 1013 +#recipient = 1000 +#max_capacity = 4 +#max_message_size = 524288 diff --git a/testing/environments/rococo-westend/bridge_hub_westend_local_network.toml b/testing/environments/rococo-westend/bridge_hub_westend_local_network.toml new file mode 100644 index 0000000000000..f2550bcc99596 --- /dev/null +++ b/testing/environments/rococo-westend/bridge_hub_westend_local_network.toml @@ -0,0 +1,88 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY}}" +default_args = [ "-lparachain=debug,xcm=trace" ] +chain = "westend-local" + + [[relaychain.nodes]] + name = "alice-westend-validator" + validator = true + rpc_port = 9935 + ws_port = 9945 + balance = 2000000000000 + + [[relaychain.nodes]] + name = "bob-westend-validator" + validator = true + rpc_port = 9936 + ws_port = 9946 + balance = 2000000000000 + + [[relaychain.nodes]] + name = "charlie-westend-validator" + validator = true + rpc_port = 9937 + ws_port = 9947 + balance = 2000000000000 + +[[parachains]] +id = 1002 +chain = "bridge-hub-westend-local" +cumulus_based = true + + # run alice as parachain collator + [[parachains.collators]] + name = "bridge-hub-westend-collator1" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY}}" + rpc_port = 8935 + ws_port = 8945 + args = [ + "-lparachain=debug,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" + ] + + # run bob as parachain collator + [[parachains.collators]] + name = "bridge-hub-westend-collator2" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY}}" + rpc_port = 8936 + ws_port = 8946 + args = [ + "-lparachain=trace,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" + ] + +[[parachains]] +id = 1000 +chain = "asset-hub-westend-local" +cumulus_based = true + + [[parachains.collators]] + name = "asset-hub-westend-collator1" + rpc_port = 9011 + ws_port = 9010 + command = "{{POLKADOT_PARACHAIN_BINARY}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" + ] + + [[parachains.collators]] + name = "asset-hub-westend-collator2" + command = "{{POLKADOT_PARACHAIN_BINARY}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" + ] + +#[[hrmp_channels]] +#sender = 1000 +#recipient = 1002 +#max_capacity = 4 +#max_message_size = 524288 +# +#[[hrmp_channels]] +#sender = 1002 +#recipient = 1000 +#max_capacity = 4 +#max_message_size = 524288 diff --git a/testing/environments/rococo-westend/bridges_rococo_westend.sh b/testing/environments/rococo-westend/bridges_rococo_westend.sh new file mode 100755 index 0000000000000..66c9ddc037b8e --- /dev/null +++ b/testing/environments/rococo-westend/bridges_rococo_westend.sh @@ -0,0 +1,401 @@ +#!/bin/bash + +# import common functions +source "$FRAMEWORK_PATH/utils/bridges.sh" + +# Expected sovereign accounts. +# +# Generated by: +# +# #[test] +# fn generate_sovereign_accounts() { +# use sp_core::crypto::Ss58Codec; +# use polkadot_parachain_primitives::primitives::Sibling; +# +# parameter_types! { +# pub UniversalLocationAHR: InteriorMultiLocation = X2(GlobalConsensus(Rococo), Parachain(1000)); +# pub UniversalLocationAHW: InteriorMultiLocation = X2(GlobalConsensus(Westend), Parachain(1000)); +# } +# +# // SS58=42 +# println!("GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# +# // SS58=42 +# println!("GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Westend)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# } +GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT="5GxRGwT8bU1JeBPTUXc7LEjZMxNrK8MyL2NJnkWFQJTQ4sii" +ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" +GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT="5He2Qdztyxxa4GoagY6q1jaiLMmKy1gXS7PdZkhfj8ZG9hk5" +ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" + +# Expected sovereign accounts for rewards on BridgeHubs. +# +# Generated by: +# #[test] +# fn generate_sovereign_accounts_for_rewards() { +# use bp_messages::LaneId; +# use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams}; +# use sp_core::crypto::Ss58Codec; +# +# // SS58=42 +# println!( +# "ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 2]), +# *b"bhwd", +# RewardsAccountOwner::ThisChain +# )) +# ) +# .to_ss58check_with_version(42_u16.into()) +# ); +# // SS58=42 +# println!( +# "ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 2]), +# *b"bhwd", +# RewardsAccountOwner::BridgedChain +# )) +# ) +# .to_ss58check_with_version(42_u16.into()) +# ); +# +# // SS58=42 +# println!( +# "ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 2]), +# *b"bhro", +# RewardsAccountOwner::ThisChain +# )) +# ) +# .to_ss58check_with_version(42_u16.into()) +# ); +# // SS58=42 +# println!( +# "ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 2]), +# *b"bhro", +# RewardsAccountOwner::BridgedChain +# )) +# ) +# .to_ss58check_with_version(42_u16.into()) +# ); +# } +ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain="5EHnXaT5BhiSGP5hbdsoVGtzi2sQVgpDNToTxLYeQvKoMPEm" +ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain="5EHnXaT5BhiSGP5hbdt5EJSapXYbxEv678jyWHEUskCXcjqo" +ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain="5EHnXaT5BhiSGP5h9Rg8sgUJqoLym3iEaWUiboT8S9AT5xFh" +ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain="5EHnXaT5BhiSGP5h9RgQci1txJ2BDbp7KBRE9k8xty3BMUSi" + +LANE_ID="00000002" +XCM_VERSION=3 + +function init_ro_wnd() { + local relayer_path=$(ensure_relayer) + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + $relayer_path init-bridge rococo-to-bridge-hub-westend \ + --source-host localhost \ + --source-port 9942 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8945 \ + --target-version-mode Auto \ + --target-signer //Bob +} + +function init_wnd_ro() { + local relayer_path=$(ensure_relayer) + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + $relayer_path init-bridge westend-to-bridge-hub-rococo \ + --source-host localhost \ + --source-port 9945 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8943 \ + --target-version-mode Auto \ + --target-signer //Bob +} + +function run_relay() { + local relayer_path=$(ensure_relayer) + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + $relayer_path relay-headers-and-messages bridge-hub-rococo-bridge-hub-westend \ + --rococo-host localhost \ + --rococo-port 9942 \ + --rococo-version-mode Auto \ + --bridge-hub-rococo-host localhost \ + --bridge-hub-rococo-port 8943 \ + --bridge-hub-rococo-version-mode Auto \ + --bridge-hub-rococo-signer //Charlie \ + --bridge-hub-rococo-transactions-mortality 4 \ + --westend-host localhost \ + --westend-port 9945 \ + --westend-version-mode Auto \ + --bridge-hub-westend-host localhost \ + --bridge-hub-westend-port 8945 \ + --bridge-hub-westend-version-mode Auto \ + --bridge-hub-westend-signer //Charlie \ + --bridge-hub-westend-transactions-mortality 4 \ + --lane "${LANE_ID}" +} + +case "$1" in + run-relay) + init_wnd_ro + init_ro_wnd + run_relay + ;; + init-asset-hub-rococo-local) + ensure_polkadot_js_api + # create foreign assets for native Westend token (governance call on Rococo) + force_create_foreign_asset \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9910" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } }')" \ + "$GLOBAL_CONSENSUS_WESTEND_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 1013 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1013 1000 4 524288 + # set XCM version of remote AssetHubWestend + force_xcm_version \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9910" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } }')" \ + $XCM_VERSION + ;; + init-bridge-hub-rococo-local) + ensure_polkadot_js_api + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO" \ + $((1000000000000 + 50000000000 * 20)) + # drip SA of lane dedicated to asset hub for paying rewards for delivery + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain" \ + $((1000000000000 + 2000000000000)) + # drip SA of lane dedicated to asset hub for paying rewards for delivery confirmation + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ON_BRIDGE_HUB_ROCOCO_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain" \ + $((1000000000000 + 2000000000000)) + # set XCM version of remote BridgeHubWestend + force_xcm_version \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1013 \ + "ws://127.0.0.1:8943" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1002 } ] } }')" \ + $XCM_VERSION + ;; + init-asset-hub-westend-local) + ensure_polkadot_js_api + # create foreign assets for native Rococo token (governance call on Westend) + force_create_foreign_asset \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9010" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } }')" \ + "$GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1002 1000 4 524288 + # set XCM version of remote AssetHubRococo + force_xcm_version \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9010" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } }')" \ + $XCM_VERSION + ;; + init-bridge-hub-westend-local) + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ASSET_HUB_WESTEND_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WESTEND" \ + $((1000000000000000 + 50000000000 * 20)) + # drip SA of lane dedicated to asset hub for paying rewards for delivery + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain" \ + $((1000000000000000 + 2000000000000)) + # drip SA of lane dedicated to asset hub for paying rewards for delivery confirmation + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ON_BRIDGE_HUB_WESTEND_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain" \ + $((1000000000000000 + 2000000000000)) + # set XCM version of remote BridgeHubRococo + force_xcm_version \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1002 \ + "ws://127.0.0.1:8945" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1013 } ] } }')" \ + $XCM_VERSION + ;; + reserve-transfer-assets-from-asset-hub-rococo-local) + amount=$2 + ensure_polkadot_js_api + # send ROCs to Alice account on AHW + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + withdraw-reserve-assets-from-asset-hub-rococo-local) + amount=$2 + ensure_polkadot_js_api + # send back only 100000000000 wrappedWNDs to Alice account on AHW + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + reserve-transfer-assets-from-asset-hub-westend-local) + amount=$2 + ensure_polkadot_js_api + # send WNDs to Alice account on AHR + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + withdraw-reserve-assets-from-asset-hub-westend-local) + amount=$2 + ensure_polkadot_js_api + # send back only 100000000000 wrappedROCs to Alice account on AHR + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + claim-rewards-bridge-hub-rococo-local) + ensure_polkadot_js_api + # bhwd -> [62, 68, 77, 64] -> 0x62687764 + claim_rewards \ + "ws://127.0.0.1:8943" \ + "//Charlie" \ + "0x${LANE_ID}" \ + "0x62687764" \ + "ThisChain" + claim_rewards \ + "ws://127.0.0.1:8943" \ + "//Charlie" \ + "0x${LANE_ID}" \ + "0x62687764" \ + "BridgedChain" + ;; + claim-rewards-bridge-hub-westend-local) + # bhro -> [62, 68, 72, 6f] -> 0x6268726f + claim_rewards \ + "ws://127.0.0.1:8945" \ + "//Charlie" \ + "0x${LANE_ID}" \ + "0x6268726f" \ + "ThisChain" + claim_rewards \ + "ws://127.0.0.1:8945" \ + "//Charlie" \ + "0x${LANE_ID}" \ + "0x6268726f" \ + "BridgedChain" + ;; + stop) + pkill -f polkadot + pkill -f parachain + ;; + import) + # to avoid trigger anything here + ;; + *) + echo "A command is require. Supported commands for: + Local (zombienet) run: + - run-relay + - init-asset-hub-rococo-local + - init-bridge-hub-rococo-local + - init-asset-hub-westend-local + - init-bridge-hub-westend-local + - reserve-transfer-assets-from-asset-hub-rococo-local + - withdraw-reserve-assets-from-asset-hub-rococo-local + - reserve-transfer-assets-from-asset-hub-westend-local + - withdraw-reserve-assets-from-asset-hub-westend-local + - claim-rewards-bridge-hub-rococo-local + - claim-rewards-bridge-hub-westend-local"; + exit 1 + ;; +esac diff --git a/testing/environments/rococo-westend/helper.sh b/testing/environments/rococo-westend/helper.sh new file mode 100755 index 0000000000000..0a13ded213f5d --- /dev/null +++ b/testing/environments/rococo-westend/helper.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +$ENV_PATH/bridges_rococo_westend.sh "$@" diff --git a/testing/environments/rococo-westend/rococo-init.zndsl b/testing/environments/rococo-westend/rococo-init.zndsl new file mode 100644 index 0000000000000..c913e4db31f49 --- /dev/null +++ b/testing/environments/rococo-westend/rococo-init.zndsl @@ -0,0 +1,8 @@ +Description: Check if the HRMP channel between Rococo BH and Rococo AH was opened successfully +Network: ./bridge_hub_rococo_local_network.toml +Creds: config + +# ensure that initialization has completed +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1013" within 300 seconds + + diff --git a/testing/environments/rococo-westend/rococo.zndsl b/testing/environments/rococo-westend/rococo.zndsl new file mode 100644 index 0000000000000..5b49c7c632fa4 --- /dev/null +++ b/testing/environments/rococo-westend/rococo.zndsl @@ -0,0 +1,7 @@ +Description: Check if the with-Westend GRANPDA pallet was initialized at Rococo BH +Network: ./bridge_hub_rococo_local_network.toml +Creds: config + +# relay is already started - let's wait until with-Westend GRANPDA pallet is initialized at Rococo +bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds + diff --git a/testing/environments/rococo-westend/spawn.sh b/testing/environments/rococo-westend/spawn.sh new file mode 100755 index 0000000000000..cbd0b1bc623ab --- /dev/null +++ b/testing/environments/rococo-westend/spawn.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -e + +trap "trap - SIGTERM && kill -9 -$$" SIGINT SIGTERM EXIT + +source "$FRAMEWORK_PATH/utils/zombienet.sh" + +# whether to init the chains (open HRMP channels, set XCM version, create reserve assets, etc) +init=0 +start_relayer=0 +while [ $# -ne 0 ] +do + arg="$1" + case "$arg" in + --init) + init=1 + ;; + --start-relayer) + start_relayer=1 + ;; + esac + shift +done + +logs_dir=$TEST_DIR/logs +helper_script="${BASH_SOURCE%/*}/helper.sh" + +rococo_def=${BASH_SOURCE%/*}/bridge_hub_rococo_local_network.toml +start_zombienet $TEST_DIR $rococo_def rococo_dir rococo_pid +echo + +westend_def=${BASH_SOURCE%/*}/bridge_hub_westend_local_network.toml +start_zombienet $TEST_DIR $westend_def westend_dir westend_pid +echo + +if [[ $init -eq 1 ]]; then + rococo_init_log=$logs_dir/rococo-init.log + echo -e "Setting up the rococo side of the bridge. Logs available at: $rococo_init_log\n" + + westend_init_log=$logs_dir/westend-init.log + echo -e "Setting up the westend side of the bridge. Logs available at: $westend_init_log\n" + + $helper_script init-asset-hub-rococo-local >> $rococo_init_log 2>&1 & + rococo_init_pid=$! + $helper_script init-asset-hub-westend-local >> $westend_init_log 2>&1 & + westend_init_pid=$! + wait -n $rococo_init_pid $westend_init_pid + + + $helper_script init-bridge-hub-rococo-local >> $rococo_init_log 2>&1 & + rococo_init_pid=$! + $helper_script init-bridge-hub-westend-local >> $westend_init_log 2>&1 & + westend_init_pid=$! + wait -n $rococo_init_pid $westend_init_pid + + run_zndsl ${BASH_SOURCE%/*}/rococo-init.zndsl $rococo_dir + run_zndsl ${BASH_SOURCE%/*}/westend-init.zndsl $westend_dir +fi + +if [[ $start_relayer -eq 1 ]]; then + ${BASH_SOURCE%/*}/start_relayer.sh $rococo_dir $westend_dir relayer_pid +fi + +echo $rococo_dir > $TEST_DIR/rococo.env +echo $westend_dir > $TEST_DIR/westend.env +echo + +wait -n $rococo_pid $westend_pid $relayer_pid +kill -9 -$$ diff --git a/testing/environments/rococo-westend/start_relayer.sh b/testing/environments/rococo-westend/start_relayer.sh new file mode 100755 index 0000000000000..7ddd312d395aa --- /dev/null +++ b/testing/environments/rococo-westend/start_relayer.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +source "$FRAMEWORK_PATH/utils/common.sh" +source "$FRAMEWORK_PATH/utils/zombienet.sh" + +rococo_dir=$1 +westend_dir=$2 +__relayer_pid=$3 + +logs_dir=$TEST_DIR/logs +helper_script="${BASH_SOURCE%/*}/helper.sh" + +relayer_log=$logs_dir/relayer.log +echo -e "Starting rococo-westend relayer. Logs available at: $relayer_log\n" +start_background_process "$helper_script run-relay" $relayer_log relayer_pid + +run_zndsl ${BASH_SOURCE%/*}/rococo.zndsl $rococo_dir +run_zndsl ${BASH_SOURCE%/*}/westend.zndsl $westend_dir + +eval $__relayer_pid="'$relayer_pid'" + diff --git a/testing/environments/rococo-westend/westend-init.zndsl b/testing/environments/rococo-westend/westend-init.zndsl new file mode 100644 index 0000000000000..0f5428eed3b01 --- /dev/null +++ b/testing/environments/rococo-westend/westend-init.zndsl @@ -0,0 +1,7 @@ +Description: Check if the HRMP channel between Westend BH and Westend AH was opened successfully +Network: ./bridge_hub_westend_local_network.toml +Creds: config + +# ensure that initialization has completed +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds + diff --git a/testing/environments/rococo-westend/westend.zndsl b/testing/environments/rococo-westend/westend.zndsl new file mode 100644 index 0000000000000..07968838852f7 --- /dev/null +++ b/testing/environments/rococo-westend/westend.zndsl @@ -0,0 +1,6 @@ +Description: Check if the with-Rococo GRANPDA pallet was initialized at Westend BH +Network: ./bridge_hub_westend_local_network.toml +Creds: config + +# relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Westend +bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds diff --git a/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js b/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js new file mode 100644 index 0000000000000..af4f18aee9b27 --- /dev/null +++ b/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js @@ -0,0 +1,25 @@ +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later + const bridgedChainName = args[0]; + const expectedBridgedChainHeaderNumber = Number(args[1]); + const runtimeApiMethod = bridgedChainName + "FinalityApi_best_finalized"; + + while (true) { + const encodedBestFinalizedHeaderId = await api.rpc.state.call(runtimeApiMethod, []); + const bestFinalizedHeaderId = api.createType("Option", encodedBestFinalizedHeaderId); + if (bestFinalizedHeaderId.isSome) { + const bestFinalizedHeaderNumber = Number(bestFinalizedHeaderId.unwrap().toHuman()[0]); + if (bestFinalizedHeaderNumber > expectedBridgedChainHeaderNumber) { + return bestFinalizedHeaderNumber; + } + } + + // else sleep and retry + await new Promise((resolve) => setTimeout(resolve, 6000)); + } +} + +module.exports = { run } diff --git a/testing/framework/js-helpers/chains/rococo-at-westend.js b/testing/framework/js-helpers/chains/rococo-at-westend.js new file mode 100644 index 0000000000000..bcce3b3a303f5 --- /dev/null +++ b/testing/framework/js-helpers/chains/rococo-at-westend.js @@ -0,0 +1,6 @@ +module.exports = { + grandpaPalletName: "bridgeRococoGrandpa", + parachainsPalletName: "bridgeRococoParachains", + messagesPalletName: "bridgeRococoMessages", + bridgedBridgeHubParaId: 1013, +} diff --git a/testing/framework/js-helpers/chains/westend-at-rococo.js b/testing/framework/js-helpers/chains/westend-at-rococo.js new file mode 100644 index 0000000000000..6a15b64a23b7c --- /dev/null +++ b/testing/framework/js-helpers/chains/westend-at-rococo.js @@ -0,0 +1,6 @@ +module.exports = { + grandpaPalletName: "bridgeWestendGrandpa", + parachainsPalletName: "bridgeWestendParachains", + messagesPalletName: "bridgeWestendMessages", + bridgedBridgeHubParaId: 1002, +} diff --git a/testing/framework/js-helpers/native-assets-balance-increased.js b/testing/framework/js-helpers/native-assets-balance-increased.js new file mode 100644 index 0000000000000..749c3e2fec32a --- /dev/null +++ b/testing/framework/js-helpers/native-assets-balance-increased.js @@ -0,0 +1,21 @@ +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + const accountAddress = args[0]; + const expectedIncrease = BigInt(args[1]); + const initialAccountData = await api.query.system.account(accountAddress); + const initialAccountBalance = initialAccountData.data['free']; + while (true) { + const accountData = await api.query.system.account(accountAddress); + const accountBalance = accountData.data['free']; + if (accountBalance > initialAccountBalance + expectedIncrease) { + return accountBalance; + } + + // else sleep and retry + await new Promise((resolve) => setTimeout(resolve, 6000)); + } +} + +module.exports = {run} diff --git a/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js b/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js new file mode 100644 index 0000000000000..979179245ebe9 --- /dev/null +++ b/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js @@ -0,0 +1,44 @@ +const utils = require("./utils"); + +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // parse arguments + const exitAfterSeconds = Number(args[0]); + const bridgedChain = require("./chains/" + args[1]); + + // start listening to new blocks + let totalGrandpaHeaders = 0; + let initialParachainHeaderImported = false; + api.rpc.chain.subscribeNewHeads(async function (header) { + const apiAtParent = await api.at(header.parentHash); + const apiAtCurrent = await api.at(header.hash); + const currentEvents = await apiAtCurrent.query.system.events(); + + totalGrandpaHeaders += await utils.ensureOnlyMandatoryGrandpaHeadersImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + initialParachainHeaderImported = await utils.ensureOnlyInitialParachainHeaderImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + }); + + // wait given time + await new Promise(resolve => setTimeout(resolve, exitAfterSeconds * 1000)); + // if we haven't seen any new GRANDPA or parachain headers => fail + if (totalGrandpaHeaders == 0) { + throw new Error("No bridged relay chain headers imported"); + } + if (!initialParachainHeaderImported) { + throw new Error("No bridged parachain headers imported"); + } +} + +module.exports = { run } diff --git a/testing/framework/js-helpers/only-required-headers-synced-when-idle.js b/testing/framework/js-helpers/only-required-headers-synced-when-idle.js new file mode 100644 index 0000000000000..8c3130e4fd960 --- /dev/null +++ b/testing/framework/js-helpers/only-required-headers-synced-when-idle.js @@ -0,0 +1,81 @@ +const utils = require("./utils"); + +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // parse arguments + const exitAfterSeconds = Number(args[0]); + const bridgedChain = require("./chains/" + args[1]); + + // start listening to new blocks + let atLeastOneMessageReceived = false; + let atLeastOneMessageDelivered = false; + const unsubscribe = await api.rpc.chain.subscribeNewHeads(async function (header) { + const apiAtParent = await api.at(header.parentHash); + const apiAtCurrent = await api.at(header.hash); + const currentEvents = await apiAtCurrent.query.system.events(); + + const messagesReceived = currentEvents.find((record) => { + return record.event.section == bridgedChain.messagesPalletName + && record.event.method == "MessagesReceived"; + }) != undefined; + const messagesDelivered = currentEvents.find((record) => { + return record.event.section == bridgedChain.messagesPalletName && + record.event.method == "MessagesDelivered"; + }) != undefined; + const hasMessageUpdates = messagesReceived || messagesDelivered; + atLeastOneMessageReceived = atLeastOneMessageReceived || messagesReceived; + atLeastOneMessageDelivered = atLeastOneMessageDelivered || messagesDelivered; + + if (!hasMessageUpdates) { + // if there are no any message update transactions, we only expect mandatory GRANDPA + // headers and initial parachain headers + await utils.ensureOnlyMandatoryGrandpaHeadersImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + await utils.ensureOnlyInitialParachainHeaderImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + } else { + const messageTransactions = (messagesReceived ? 1 : 0) + (messagesDelivered ? 1 : 0); + + // otherwise we only accept at most one GRANDPA header + const newGrandpaHeaders = utils.countGrandpaHeaderImports(bridgedChain, currentEvents); + if (newGrandpaHeaders > 1) { + utils.logEvents(currentEvents); + throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + messageTransactions); + } + + // ...and at most one parachain header + const newParachainHeaders = utils.countParachainHeaderImports(bridgedChain, currentEvents); + if (newParachainHeaders > 1) { + utils.logEvents(currentEvents); + throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + messageTransactions); + } + } + }); + + // wait until we have received + delivered messages OR until timeout + await utils.pollUntil( + exitAfterSeconds, + () => { return atLeastOneMessageReceived && atLeastOneMessageDelivered; }, + () => { unsubscribe(); }, + () => { + if (!atLeastOneMessageReceived) { + throw new Error("No messages received from bridged chain"); + } + if (!atLeastOneMessageDelivered) { + throw new Error("No messages delivered to bridged chain"); + } + }, + ); +} + +module.exports = { run } diff --git a/testing/framework/js-helpers/relayer-rewards.js b/testing/framework/js-helpers/relayer-rewards.js new file mode 100644 index 0000000000000..5347c649604fc --- /dev/null +++ b/testing/framework/js-helpers/relayer-rewards.js @@ -0,0 +1,28 @@ +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later + const relayerAccountAddress = args[0]; + const laneId = args[1]; + const bridgedChainId = args[2]; + const relayerFundOwner = args[3]; + const expectedRelayerReward = BigInt(args[4]); + while (true) { + const relayerReward = await api.query.bridgeRelayers.relayerRewards( + relayerAccountAddress, + { laneId: laneId, bridgedChainId: bridgedChainId, owner: relayerFundOwner } + ); + if (relayerReward.isSome) { + const relayerRewardBalance = relayerReward.unwrap().toBigInt(); + if (relayerRewardBalance > expectedRelayerReward) { + return relayerRewardBalance; + } + } + + // else sleep and retry + await new Promise((resolve) => setTimeout(resolve, 6000)); + } +} + +module.exports = { run } diff --git a/testing/framework/js-helpers/utils.js b/testing/framework/js-helpers/utils.js new file mode 100644 index 0000000000000..f6e9f5623b47b --- /dev/null +++ b/testing/framework/js-helpers/utils.js @@ -0,0 +1,103 @@ +module.exports = { + logEvents: function(events) { + let stringifiedEvents = ""; + events.forEach((record) => { + if (stringifiedEvents != "") { + stringifiedEvents += ", "; + } + stringifiedEvents += record.event.section + "::" + record.event.method; + }); + console.log("Block events: " + stringifiedEvents); + }, + countGrandpaHeaderImports: function(bridgedChain, events) { + return events.reduce( + (count, record) => { + const { event } = record; + if (event.section == bridgedChain.grandpaPalletName && event.method == "UpdatedBestFinalizedHeader") { + count += 1; + } + return count; + }, + 0, + ); + }, + countParachainHeaderImports: function(bridgedChain, events) { + return events.reduce( + (count, record) => { + const { event } = record; + if (event.section == bridgedChain.parachainsPalletName && event.method == "UpdatedParachainHead") { + count += 1; + } + return count; + }, + 0, + ); + }, + pollUntil: async function( + timeoutInSecs, + predicate, + cleanup, + onFailure, + ) { + const begin = new Date().getTime(); + const end = begin + timeoutInSecs * 1000; + while (new Date().getTime() < end) { + if (predicate()) { + cleanup(); + return; + } + await new Promise(resolve => setTimeout(resolve, 100)); + } + + cleanup(); + onFailure(); + }, + ensureOnlyMandatoryGrandpaHeadersImported: async function( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ) { + // remember id of bridged relay chain GRANDPA authorities set at parent block + const authoritySetAtParent = await apiAtParent.query[bridgedChain.grandpaPalletName].currentAuthoritySet(); + const authoritySetIdAtParent = authoritySetAtParent["setId"]; + + // now read the id of bridged relay chain GRANDPA authorities set at current block + const authoritySetAtCurrent = await apiAtCurrent.query[bridgedChain.grandpaPalletName].currentAuthoritySet(); + const authoritySetIdAtCurrent = authoritySetAtCurrent["setId"]; + + // we expect to see no more than `authoritySetIdAtCurrent - authoritySetIdAtParent` new GRANDPA headers + const maxNewGrandpaHeaders = authoritySetIdAtCurrent - authoritySetIdAtParent; + const newGrandpaHeaders = module.exports.countGrandpaHeaderImports(bridgedChain, currentEvents); + + // check that our assumptions are correct + if (newGrandpaHeaders > maxNewGrandpaHeaders) { + module.exports.logEvents(currentEvents); + throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + maxNewGrandpaHeaders); + } + + return newGrandpaHeaders; + }, + ensureOnlyInitialParachainHeaderImported: async function( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ) { + // remember whether we already know bridged parachain header at a parent block + const bestBridgedParachainHeader = await apiAtParent.query[bridgedChain.parachainsPalletName].parasInfo(bridgedChain.bridgedBridgeHubParaId);; + const hasBestBridgedParachainHeader = bestBridgedParachainHeader.isSome; + + // we expect to see: no more than `1` bridged parachain header if there were no parachain header before. + const maxNewParachainHeaders = hasBestBridgedParachainHeader ? 0 : 1; + const newParachainHeaders = module.exports.countParachainHeaderImports(bridgedChain, currentEvents); + + // check that our assumptions are correct + if (newParachainHeaders > maxNewParachainHeaders) { + module.exports.logEvents(currentEvents); + throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + maxNewParachainHeaders); + } + + return hasBestBridgedParachainHeader; + }, +} diff --git a/testing/framework/js-helpers/wait-hrmp-channel-opened.js b/testing/framework/js-helpers/wait-hrmp-channel-opened.js new file mode 100644 index 0000000000000..765d48cc49848 --- /dev/null +++ b/testing/framework/js-helpers/wait-hrmp-channel-opened.js @@ -0,0 +1,22 @@ +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + const sibling = args[0]; + + while (true) { + const messagingStateAsObj = await api.query.parachainSystem.relevantMessagingState(); + const messagingState = api.createType("Option", messagingStateAsObj); + if (messagingState.isSome) { + const egressChannels = messagingState.unwrap().egressChannels; + if (egressChannels.find(x => x[0] == sibling)) { + return; + } + } + + // else sleep and retry + await new Promise((resolve) => setTimeout(resolve, 6000)); + } +} + +module.exports = { run } diff --git a/testing/framework/js-helpers/wrapped-assets-balance.js b/testing/framework/js-helpers/wrapped-assets-balance.js new file mode 100644 index 0000000000000..27287118547f7 --- /dev/null +++ b/testing/framework/js-helpers/wrapped-assets-balance.js @@ -0,0 +1,26 @@ +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later + const accountAddress = args[0]; + const expectedForeignAssetBalance = BigInt(args[1]); + const bridgedNetworkName = args[2]; + while (true) { + const foreignAssetAccount = await api.query.foreignAssets.account( + { parents: 2, interior: { X1: { GlobalConsensus: bridgedNetworkName } } }, + accountAddress + ); + if (foreignAssetAccount.isSome) { + const foreignAssetAccountBalance = foreignAssetAccount.unwrap().balance.toBigInt(); + if (foreignAssetAccountBalance > expectedForeignAssetBalance) { + return foreignAssetAccountBalance; + } + } + + // else sleep and retry + await new Promise((resolve) => setTimeout(resolve, 6000)); + } +} + +module.exports = { run } diff --git a/testing/framework/utils/bridges.sh b/testing/framework/utils/bridges.sh new file mode 100755 index 0000000000000..7c8399461584a --- /dev/null +++ b/testing/framework/utils/bridges.sh @@ -0,0 +1,309 @@ +#!/bin/bash + +function relayer_path() { + local default_path=~/local_bridge_testing/bin/substrate-relay + local path="${SUBSTRATE_RELAY_BINARY:-$default_path}" + echo "$path" +} + +function ensure_relayer() { + local path=$(relayer_path) + if [[ ! -f "$path" ]]; then + echo " Required substrate-relay binary '$path' does not exist!" + echo " You need to build it and copy to this location!" + echo " Please, check ./parachains/runtimes/bridge-hubs/README.md (Prepare/Build/Deploy)" + exit 1 + fi + + echo $path +} + +function ensure_polkadot_js_api() { + if ! which polkadot-js-api &> /dev/null; then + echo '' + echo 'Required command `polkadot-js-api` not in PATH, please, install, e.g.:' + echo "npm install -g @polkadot/api-cli@beta" + echo " or" + echo "yarn global add @polkadot/api-cli" + echo '' + exit 1 + fi + if ! which jq &> /dev/null; then + echo '' + echo 'Required command `jq` not in PATH, please, install, e.g.:' + echo "apt install -y jq" + echo '' + exit 1 + fi + generate_hex_encoded_call_data "check" "--" + local retVal=$? + if [ $retVal -ne 0 ]; then + echo "" + echo "" + echo "-------------------" + echo "Installing (nodejs) sub module: ${BASH_SOURCE%/*}/generate_hex_encoded_call" + pushd ${BASH_SOURCE%/*}/generate_hex_encoded_call + npm install + popd + fi +} + +function call_polkadot_js_api() { + # --noWait: without that argument `polkadot-js-api` waits until transaction is included into the block. + # With it, it just submits it to the tx pool and exits. + # --nonce -1: means to compute transaction nonce using `system_accountNextIndex` RPC, which includes all + # transaction that are in the tx pool. + polkadot-js-api --noWait --nonce -1 "$@" +} + +function generate_hex_encoded_call_data() { + local type=$1 + local endpoint=$2 + local output=$3 + shift + shift + shift + echo "Input params: $@" + + node ${BASH_SOURCE%/*}/../utils/generate_hex_encoded_call "$type" "$endpoint" "$output" "$@" + local retVal=$? + + if [ $type != "check" ]; then + local hex_encoded_data=$(cat $output) + echo "Generated hex-encoded bytes to file '$output': $hex_encoded_data" + fi + + return $retVal +} + +function transfer_balance() { + local runtime_para_endpoint=$1 + local seed=$2 + local target_account=$3 + local amount=$4 + echo " calling transfer_balance:" + echo " runtime_para_endpoint: ${runtime_para_endpoint}" + echo " seed: ${seed}" + echo " target_account: ${target_account}" + echo " amount: ${amount}" + echo "--------------------------------------------------" + + call_polkadot_js_api \ + --ws "${runtime_para_endpoint}" \ + --seed "${seed?}" \ + tx.balances.transferAllowDeath \ + "${target_account}" \ + "${amount}" +} + +function send_governance_transact() { + local relay_url=$1 + local relay_chain_seed=$2 + local para_id=$3 + local hex_encoded_data=$4 + local require_weight_at_most_ref_time=$5 + local require_weight_at_most_proof_size=$6 + echo " calling send_governance_transact:" + echo " relay_url: ${relay_url}" + echo " relay_chain_seed: ${relay_chain_seed}" + echo " para_id: ${para_id}" + echo " hex_encoded_data: ${hex_encoded_data}" + echo " require_weight_at_most_ref_time: ${require_weight_at_most_ref_time}" + echo " require_weight_at_most_proof_size: ${require_weight_at_most_proof_size}" + echo " params:" + + local dest=$(jq --null-input \ + --arg para_id "$para_id" \ + '{ "V3": { "parents": 0, "interior": { "X1": { "Parachain": $para_id } } } }') + + local message=$(jq --null-input \ + --argjson hex_encoded_data $hex_encoded_data \ + --arg require_weight_at_most_ref_time "$require_weight_at_most_ref_time" \ + --arg require_weight_at_most_proof_size "$require_weight_at_most_proof_size" \ + ' + { + "V3": [ + { + "UnpaidExecution": { + "weight_limit": "Unlimited" + } + }, + { + "Transact": { + "origin_kind": "Superuser", + "require_weight_at_most": { + "ref_time": $require_weight_at_most_ref_time, + "proof_size": $require_weight_at_most_proof_size, + }, + "call": { + "encoded": $hex_encoded_data + } + } + } + ] + } + ') + + echo "" + echo " dest:" + echo "${dest}" + echo "" + echo " message:" + echo "${message}" + echo "" + echo "--------------------------------------------------" + + call_polkadot_js_api \ + --ws "${relay_url?}" \ + --seed "${relay_chain_seed?}" \ + --sudo \ + tx.xcmPallet.send \ + "${dest}" \ + "${message}" +} + +function open_hrmp_channels() { + local relay_url=$1 + local relay_chain_seed=$2 + local sender_para_id=$3 + local recipient_para_id=$4 + local max_capacity=$5 + local max_message_size=$6 + echo " calling open_hrmp_channels:" + echo " relay_url: ${relay_url}" + echo " relay_chain_seed: ${relay_chain_seed}" + echo " sender_para_id: ${sender_para_id}" + echo " recipient_para_id: ${recipient_para_id}" + echo " max_capacity: ${max_capacity}" + echo " max_message_size: ${max_message_size}" + echo " params:" + echo "--------------------------------------------------" + call_polkadot_js_api \ + --ws "${relay_url?}" \ + --seed "${relay_chain_seed?}" \ + --sudo \ + tx.hrmp.forceOpenHrmpChannel \ + ${sender_para_id} \ + ${recipient_para_id} \ + ${max_capacity} \ + ${max_message_size} +} + +function force_xcm_version() { + local relay_url=$1 + local relay_chain_seed=$2 + local runtime_para_id=$3 + local runtime_para_endpoint=$4 + local dest=$5 + local xcm_version=$6 + echo " calling force_xcm_version:" + echo " relay_url: ${relay_url}" + echo " relay_chain_seed: ${relay_chain_seed}" + echo " runtime_para_id: ${runtime_para_id}" + echo " runtime_para_endpoint: ${runtime_para_endpoint}" + echo " dest: ${dest}" + echo " xcm_version: ${xcm_version}" + echo " params:" + + # 1. generate data for Transact (PolkadotXcm::force_xcm_version) + local tmp_output_file=$(mktemp) + generate_hex_encoded_call_data "force-xcm-version" "${runtime_para_endpoint}" "${tmp_output_file}" "$dest" "$xcm_version" + local hex_encoded_data=$(cat $tmp_output_file) + + # 2. trigger governance call + send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 +} + +function force_create_foreign_asset() { + local relay_url=$1 + local relay_chain_seed=$2 + local runtime_para_id=$3 + local runtime_para_endpoint=$4 + local asset_multilocation=$5 + local asset_owner_account_id=$6 + local min_balance=$7 + local is_sufficient=$8 + echo " calling force_create_foreign_asset:" + echo " relay_url: ${relay_url}" + echo " relay_chain_seed: ${relay_chain_seed}" + echo " runtime_para_id: ${runtime_para_id}" + echo " runtime_para_endpoint: ${runtime_para_endpoint}" + echo " asset_multilocation: ${asset_multilocation}" + echo " asset_owner_account_id: ${asset_owner_account_id}" + echo " min_balance: ${min_balance}" + echo " is_sufficient: ${is_sufficient}" + echo " params:" + + # 1. generate data for Transact (ForeignAssets::force_create) + local tmp_output_file=$(mktemp) + generate_hex_encoded_call_data "force-create-asset" "${runtime_para_endpoint}" "${tmp_output_file}" "$asset_multilocation" "$asset_owner_account_id" $is_sufficient $min_balance + local hex_encoded_data=$(cat $tmp_output_file) + + # 2. trigger governance call + send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 +} + +function limited_reserve_transfer_assets() { + local url=$1 + local seed=$2 + local destination=$3 + local beneficiary=$4 + local assets=$5 + local fee_asset_item=$6 + local weight_limit=$7 + echo " calling limited_reserve_transfer_assets:" + echo " url: ${url}" + echo " seed: ${seed}" + echo " destination: ${destination}" + echo " beneficiary: ${beneficiary}" + echo " assets: ${assets}" + echo " fee_asset_item: ${fee_asset_item}" + echo " weight_limit: ${weight_limit}" + echo "" + echo "--------------------------------------------------" + + call_polkadot_js_api \ + --ws "${url?}" \ + --seed "${seed?}" \ + tx.polkadotXcm.limitedReserveTransferAssets \ + "${destination}" \ + "${beneficiary}" \ + "${assets}" \ + "${fee_asset_item}" \ + "${weight_limit}" +} + +function claim_rewards() { + local runtime_para_endpoint=$1 + local seed=$2 + local lane_id=$3 + local bridged_chain_id=$4 + local owner=$5 + echo " calling claim_rewards:" + echo " runtime_para_endpoint: ${runtime_para_endpoint}" + echo " seed: ${seed}" + echo " lane_id: ${lane_id}" + echo " bridged_chain_id: ${bridged_chain_id}" + echo " owner: ${owner}" + echo "" + + local rewards_account_params=$(jq --null-input \ + --arg lane_id "$lane_id" \ + --arg bridged_chain_id "$bridged_chain_id" \ + --arg owner "$owner" \ + '{ + "laneId": $lane_id, + "bridgedChainId": $bridged_chain_id, + "owner": $owner + }') + + echo " rewards_account_params:" + echo "${rewards_account_params}" + echo "--------------------------------------------------" + + call_polkadot_js_api \ + --ws "${runtime_para_endpoint}" \ + --seed "${seed?}" \ + tx.bridgeRelayers.claimRewards \ + "${rewards_account_params}" +} \ No newline at end of file diff --git a/testing/framework/utils/common.sh b/testing/framework/utils/common.sh new file mode 100644 index 0000000000000..06f41320be135 --- /dev/null +++ b/testing/framework/utils/common.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +function start_background_process() { + local command=$1 + local log_file=$2 + local __pid=$3 + + $command > $log_file 2>&1 & + eval $__pid="'$!'" +} + +function wait_for_process_file() { + local pid=$1 + local file=$2 + local timeout=$3 + local __found=$4 + + local time=0 + until [ -e $file ]; do + if ! kill -0 $pid; then + echo "Process finished unsuccessfully" + return + fi + if (( time++ >= timeout )); then + echo "Timeout waiting for file $file: $timeout seconds" + eval $__found=0 + return + fi + sleep 1 + done + + echo "File $file found after $time seconds" + eval $__found=1 +} + +function ensure_process_file() { + local pid=$1 + local file=$2 + local timeout=$3 + + wait_for_process_file $pid $file $timeout file_found + if [ "$file_found" != "1" ]; then + exit 1 + fi +} diff --git a/testing/framework/utils/generate_hex_encoded_call/index.js b/testing/framework/utils/generate_hex_encoded_call/index.js new file mode 100644 index 0000000000000..30f89d754ceb7 --- /dev/null +++ b/testing/framework/utils/generate_hex_encoded_call/index.js @@ -0,0 +1,165 @@ +const fs = require("fs"); +const { exit } = require("process"); +const { WsProvider, ApiPromise } = require("@polkadot/api"); +const util = require("@polkadot/util"); + +// connect to a substrate chain and return the api object +async function connect(endpoint, types = {}) { + const provider = new WsProvider(endpoint); + const api = await ApiPromise.create({ + provider, + types, + throwOnConnect: false, + }); + return api; +} + +function writeHexEncodedBytesToOutput(method, outputFile) { + console.log("Payload (hex): ", method.toHex()); + console.log("Payload (bytes): ", Array.from(method.toU8a())); + console.log("Payload (plain): ", JSON.stringify(method)); + fs.writeFileSync(outputFile, JSON.stringify(Array.from(method.toU8a()))); +} + +function remarkWithEvent(endpoint, outputFile) { + console.log(`Generating remarkWithEvent from RPC endpoint: ${endpoint} to outputFile: ${outputFile}`); + connect(endpoint) + .then((api) => { + const call = api.tx.system.remarkWithEvent("Hello"); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +function addExporterConfig(endpoint, outputFile, bridgedNetwork, bridgeConfig) { + console.log(`Generating addExporterConfig from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on bridgedNetwork: ${bridgedNetwork}, bridgeConfig: ${bridgeConfig}`); + connect(endpoint) + .then((api) => { + const call = api.tx.bridgeTransfer.addExporterConfig(bridgedNetwork, JSON.parse(bridgeConfig)); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +function addUniversalAlias(endpoint, outputFile, location, junction) { + console.log(`Generating addUniversalAlias from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on location: ${location}, junction: ${junction}`); + connect(endpoint) + .then((api) => { + const call = api.tx.bridgeTransfer.addUniversalAlias(JSON.parse(location), JSON.parse(junction)); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +function addReserveLocation(endpoint, outputFile, reserve_location) { + console.log(`Generating addReserveLocation from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on reserve_location: ${reserve_location}`); + connect(endpoint) + .then((api) => { + const call = api.tx.bridgeTransfer.addReserveLocation(JSON.parse(reserve_location)); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +function removeExporterConfig(endpoint, outputFile, bridgedNetwork) { + console.log(`Generating removeExporterConfig from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on bridgedNetwork: ${bridgedNetwork}`); + connect(endpoint) + .then((api) => { + const call = api.tx.bridgeTransfer.removeExporterConfig(bridgedNetwork); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +function forceCreateAsset(endpoint, outputFile, assetId, assetOwnerAccountId, isSufficient, minBalance) { + var isSufficient = isSufficient == "true" ? true : false; + console.log(`Generating forceCreateAsset from RPC endpoint: ${endpoint} to outputFile: ${outputFile} based on assetId: ${assetId}, assetOwnerAccountId: ${assetOwnerAccountId}, isSufficient: ${isSufficient}, minBalance: ${minBalance}`); + connect(endpoint) + .then((api) => { + const call = api.tx.foreignAssets.forceCreate(JSON.parse(assetId), assetOwnerAccountId, isSufficient, minBalance); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +function forceXcmVersion(endpoint, outputFile, dest, xcm_version) { + console.log(`Generating forceXcmVersion from RPC endpoint: ${endpoint} to outputFile: ${outputFile}, dest: ${dest}, xcm_version: ${xcm_version}`); + connect(endpoint) + .then((api) => { + const call = api.tx.polkadotXcm.forceXcmVersion(JSON.parse(dest), xcm_version); + writeHexEncodedBytesToOutput(call.method, outputFile); + exit(0); + }) + .catch((e) => { + console.error(e); + exit(1); + }); +} + +if (!process.argv[2] || !process.argv[3]) { + console.log("usage: node ./script/generate_hex_encoded_call "); + exit(1); +} + +const type = process.argv[2]; +const rpcEnpoint = process.argv[3]; +const output = process.argv[4]; +const inputArgs = process.argv.slice(5, process.argv.length); +console.log(`Generating hex-encoded call data for:`); +console.log(` type: ${type}`); +console.log(` rpcEnpoint: ${rpcEnpoint}`); +console.log(` output: ${output}`); +console.log(` inputArgs: ${inputArgs}`); + +switch (type) { + case 'remark-with-event': + remarkWithEvent(rpcEnpoint, output); + break; + case 'add-exporter-config': + addExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + break; + case 'remove-exporter-config': + removeExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + break; + case 'add-universal-alias': + addUniversalAlias(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + break; + case 'add-reserve-location': + addReserveLocation(rpcEnpoint, output, inputArgs[0]); + break; + case 'force-create-asset': + forceCreateAsset(rpcEnpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]); + break; + case 'force-xcm-version': + forceXcmVersion(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + break; + case 'check': + console.log(`Checking nodejs installation, if you see this everything is ready!`); + break; + default: + console.log(`Sorry, we are out of ${type} - not yet supported!`); +} diff --git a/testing/framework/utils/generate_hex_encoded_call/package-lock.json b/testing/framework/utils/generate_hex_encoded_call/package-lock.json new file mode 100644 index 0000000000000..b2dddaa19ed15 --- /dev/null +++ b/testing/framework/utils/generate_hex_encoded_call/package-lock.json @@ -0,0 +1,759 @@ +{ + "name": "y", + "version": "y", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "y", + "version": "y", + "license": "MIT", + "dependencies": { + "@polkadot/api": "^10.11", + "@polkadot/util": "^12.6" + } + }, + "node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@polkadot/api": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.11.2.tgz", + "integrity": "sha512-AorCZxCWCoTtdbl4DPUZh+ACe/pbLIS1BkdQY0AFJuZllm0x/yWzjgampcPd5jQAA/O3iKShRBkZqj6Mk9yG/A==", + "dependencies": { + "@polkadot/api-augment": "10.11.2", + "@polkadot/api-base": "10.11.2", + "@polkadot/api-derive": "10.11.2", + "@polkadot/keyring": "^12.6.2", + "@polkadot/rpc-augment": "10.11.2", + "@polkadot/rpc-core": "10.11.2", + "@polkadot/rpc-provider": "10.11.2", + "@polkadot/types": "10.11.2", + "@polkadot/types-augment": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/types-create": "10.11.2", + "@polkadot/types-known": "10.11.2", + "@polkadot/util": "^12.6.2", + "@polkadot/util-crypto": "^12.6.2", + "eventemitter3": "^5.0.1", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/api-augment": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.11.2.tgz", + "integrity": "sha512-PTpnqpezc75qBqUtgrc0GYB8h9UHjfbHSRZamAbecIVAJ2/zc6CqtnldeaBlIu1IKTgBzi3FFtTyYu+ZGbNT2Q==", + "dependencies": { + "@polkadot/api-base": "10.11.2", + "@polkadot/rpc-augment": "10.11.2", + "@polkadot/types": "10.11.2", + "@polkadot/types-augment": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/api-base": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.11.2.tgz", + "integrity": "sha512-4LIjaUfO9nOzilxo7XqzYKCNMtmUypdk8oHPdrRnSjKEsnK7vDsNi+979z2KXNXd2KFSCFHENmI523fYnMnReg==", + "dependencies": { + "@polkadot/rpc-core": "10.11.2", + "@polkadot/types": "10.11.2", + "@polkadot/util": "^12.6.2", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/api-derive": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.11.2.tgz", + "integrity": "sha512-m3BQbPionkd1iSlknddxnL2hDtolPIsT+aRyrtn4zgMRPoLjHFmTmovvg8RaUyYofJtZeYrnjMw0mdxiSXx7eA==", + "dependencies": { + "@polkadot/api": "10.11.2", + "@polkadot/api-augment": "10.11.2", + "@polkadot/api-base": "10.11.2", + "@polkadot/rpc-core": "10.11.2", + "@polkadot/types": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "@polkadot/util-crypto": "^12.6.2", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/keyring": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.6.2.tgz", + "integrity": "sha512-O3Q7GVmRYm8q7HuB3S0+Yf/q/EB2egKRRU3fv9b3B7V+A52tKzA+vIwEmNVaD1g5FKW9oB97rmpggs0zaKFqHw==", + "dependencies": { + "@polkadot/util": "12.6.2", + "@polkadot/util-crypto": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "12.6.2", + "@polkadot/util-crypto": "12.6.2" + } + }, + "node_modules/@polkadot/networks": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.6.2.tgz", + "integrity": "sha512-1oWtZm1IvPWqvMrldVH6NI2gBoCndl5GEwx7lAuQWGr7eNL+6Bdc5K3Z9T0MzFvDGoi2/CBqjX9dRKo39pDC/w==", + "dependencies": { + "@polkadot/util": "12.6.2", + "@substrate/ss58-registry": "^1.44.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/rpc-augment": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.11.2.tgz", + "integrity": "sha512-9AhT0WW81/8jYbRcAC6PRmuxXqNhJje8OYiulBQHbG1DTCcjAfz+6VQBke9BwTStzPq7d526+yyBKD17O3zlAA==", + "dependencies": { + "@polkadot/rpc-core": "10.11.2", + "@polkadot/types": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/rpc-core": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.11.2.tgz", + "integrity": "sha512-Ot0CFLWx8sZhLZog20WDuniPA01Bk2StNDsdAQgcFKPwZw6ShPaZQCHuKLQK6I6DodOrem9FXX7c1hvoKJP5Ww==", + "dependencies": { + "@polkadot/rpc-augment": "10.11.2", + "@polkadot/rpc-provider": "10.11.2", + "@polkadot/types": "10.11.2", + "@polkadot/util": "^12.6.2", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/rpc-provider": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.11.2.tgz", + "integrity": "sha512-he5jWMpDJp7e+vUzTZDzpkB7ps3H8psRally+/ZvZZScPvFEjfczT7I1WWY9h58s8+ImeVP/lkXjL9h/gUOt3Q==", + "dependencies": { + "@polkadot/keyring": "^12.6.2", + "@polkadot/types": "10.11.2", + "@polkadot/types-support": "10.11.2", + "@polkadot/util": "^12.6.2", + "@polkadot/util-crypto": "^12.6.2", + "@polkadot/x-fetch": "^12.6.2", + "@polkadot/x-global": "^12.6.2", + "@polkadot/x-ws": "^12.6.2", + "eventemitter3": "^5.0.1", + "mock-socket": "^9.3.1", + "nock": "^13.4.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@substrate/connect": "0.7.35" + } + }, + "node_modules/@polkadot/types": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.11.2.tgz", + "integrity": "sha512-d52j3xXni+C8GdYZVTSfu8ROAnzXFMlyRvXtor0PudUc8UQHOaC4+mYAkTBGA2gKdmL8MHSfRSbhcxHhsikY6Q==", + "dependencies": { + "@polkadot/keyring": "^12.6.2", + "@polkadot/types-augment": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/types-create": "10.11.2", + "@polkadot/util": "^12.6.2", + "@polkadot/util-crypto": "^12.6.2", + "rxjs": "^7.8.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types-augment": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.11.2.tgz", + "integrity": "sha512-8eB8ew04wZiE5GnmFvEFW1euJWmF62SGxb1O+8wL3zoUtB9Xgo1vB6w6xbTrd+HLV6jNSeXXnbbF1BEUvi9cNg==", + "dependencies": { + "@polkadot/types": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types-codec": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.11.2.tgz", + "integrity": "sha512-3xjOQL+LOOMzYqlgP9ROL0FQnzU8lGflgYewzau7AsDlFziSEtb49a9BpYo6zil4koC+QB8zQ9OHGFumG08T8w==", + "dependencies": { + "@polkadot/util": "^12.6.2", + "@polkadot/x-bigint": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types-create": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.11.2.tgz", + "integrity": "sha512-SJt23NxYvefRxVZZm6mT9ed1pR6FDoIGQ3xUpbjhTLfU2wuhpKjekMVorYQ6z/gK2JLMu2kV92Ardsz+6GX5XQ==", + "dependencies": { + "@polkadot/types-codec": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types-known": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.11.2.tgz", + "integrity": "sha512-kbEIX7NUQFxpDB0FFGNyXX/odY7jbp56RGD+Z4A731fW2xh/DgAQrI994xTzuh0c0EqPE26oQm3kATSpseqo9w==", + "dependencies": { + "@polkadot/networks": "^12.6.2", + "@polkadot/types": "10.11.2", + "@polkadot/types-codec": "10.11.2", + "@polkadot/types-create": "10.11.2", + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/types-support": { + "version": "10.11.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.11.2.tgz", + "integrity": "sha512-X11hoykFYv/3efg4coZy2hUOUc97JhjQMJLzDhHniFwGLlYU8MeLnPdCVGkXx0xDDjTo4/ptS1XpZ5HYcg+gRw==", + "dependencies": { + "@polkadot/util": "^12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/util": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.6.2.tgz", + "integrity": "sha512-l8TubR7CLEY47240uki0TQzFvtnxFIO7uI/0GoWzpYD/O62EIAMRsuY01N4DuwgKq2ZWD59WhzsLYmA5K6ksdw==", + "dependencies": { + "@polkadot/x-bigint": "12.6.2", + "@polkadot/x-global": "12.6.2", + "@polkadot/x-textdecoder": "12.6.2", + "@polkadot/x-textencoder": "12.6.2", + "@types/bn.js": "^5.1.5", + "bn.js": "^5.2.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/util-crypto": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.6.2.tgz", + "integrity": "sha512-FEWI/dJ7wDMNN1WOzZAjQoIcCP/3vz3wvAp5QQm+lOrzOLj0iDmaIGIcBkz8HVm3ErfSe/uKP0KS4jgV/ib+Mg==", + "dependencies": { + "@noble/curves": "^1.3.0", + "@noble/hashes": "^1.3.3", + "@polkadot/networks": "12.6.2", + "@polkadot/util": "12.6.2", + "@polkadot/wasm-crypto": "^7.3.2", + "@polkadot/wasm-util": "^7.3.2", + "@polkadot/x-bigint": "12.6.2", + "@polkadot/x-randomvalues": "12.6.2", + "@scure/base": "^1.1.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "12.6.2" + } + }, + "node_modules/@polkadot/wasm-bridge": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.3.2.tgz", + "integrity": "sha512-AJEXChcf/nKXd5Q/YLEV5dXQMle3UNT7jcXYmIffZAo/KI394a+/24PaISyQjoNC0fkzS1Q8T5pnGGHmXiVz2g==", + "dependencies": { + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.3.2.tgz", + "integrity": "sha512-+neIDLSJ6jjVXsjyZ5oLSv16oIpwp+PxFqTUaZdZDoA2EyFRQB8pP7+qLsMNk+WJuhuJ4qXil/7XiOnZYZ+wxw==", + "dependencies": { + "@polkadot/wasm-bridge": "7.3.2", + "@polkadot/wasm-crypto-asmjs": "7.3.2", + "@polkadot/wasm-crypto-init": "7.3.2", + "@polkadot/wasm-crypto-wasm": "7.3.2", + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-asmjs": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.3.2.tgz", + "integrity": "sha512-QP5eiUqUFur/2UoF2KKKYJcesc71fXhQFLT3D4ZjG28Mfk2ZPI0QNRUfpcxVQmIUpV5USHg4geCBNuCYsMm20Q==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-init": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.3.2.tgz", + "integrity": "sha512-FPq73zGmvZtnuJaFV44brze3Lkrki3b4PebxCy9Fplw8nTmisKo9Xxtfew08r0njyYh+uiJRAxPCXadkC9sc8g==", + "dependencies": { + "@polkadot/wasm-bridge": "7.3.2", + "@polkadot/wasm-crypto-asmjs": "7.3.2", + "@polkadot/wasm-crypto-wasm": "7.3.2", + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-wasm": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.3.2.tgz", + "integrity": "sha512-15wd0EMv9IXs5Abp1ZKpKKAVyZPhATIAHfKsyoWCEFDLSOA0/K0QGOxzrAlsrdUkiKZOq7uzSIgIDgW8okx2Mw==", + "dependencies": { + "@polkadot/wasm-util": "7.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-util": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.3.2.tgz", + "integrity": "sha512-bmD+Dxo1lTZyZNxbyPE380wd82QsX+43mgCm40boyKrRppXEyQmWT98v/Poc7chLuskYb6X8IQ6lvvK2bGR4Tg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/x-bigint": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.6.2.tgz", + "integrity": "sha512-HSIk60uFPX4GOFZSnIF7VYJz7WZA7tpFJsne7SzxOooRwMTWEtw3fUpFy5cYYOeLh17/kHH1Y7SVcuxzVLc74Q==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-fetch": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.6.2.tgz", + "integrity": "sha512-8wM/Z9JJPWN1pzSpU7XxTI1ldj/AfC8hKioBlUahZ8gUiJaOF7K9XEFCrCDLis/A1BoOu7Ne6WMx/vsJJIbDWw==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "node-fetch": "^3.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-global": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.6.2.tgz", + "integrity": "sha512-a8d6m+PW98jmsYDtAWp88qS4dl8DyqUBsd0S+WgyfSMtpEXu6v9nXDgPZgwF5xdDvXhm+P0ZfVkVTnIGrScb5g==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-randomvalues": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.6.2.tgz", + "integrity": "sha512-Vr8uG7rH2IcNJwtyf5ebdODMcr0XjoCpUbI91Zv6AlKVYOGKZlKLYJHIwpTaKKB+7KPWyQrk4Mlym/rS7v9feg==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@polkadot/util": "12.6.2", + "@polkadot/wasm-util": "*" + } + }, + "node_modules/@polkadot/x-textdecoder": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.6.2.tgz", + "integrity": "sha512-M1Bir7tYvNappfpFWXOJcnxUhBUFWkUFIdJSyH0zs5LmFtFdbKAeiDXxSp2Swp5ddOZdZgPac294/o2TnQKN1w==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-textencoder": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.6.2.tgz", + "integrity": "sha512-4N+3UVCpI489tUJ6cv3uf0PjOHvgGp9Dl+SZRLgFGt9mvxnvpW/7+XBADRMtlG4xi5gaRK7bgl5bmY6OMDsNdw==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polkadot/x-ws": { + "version": "12.6.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.6.2.tgz", + "integrity": "sha512-cGZWo7K5eRRQCRl2LrcyCYsrc3lRbTlixZh3AzgU8uX4wASVGRlNWi/Hf4TtHNe1ExCDmxabJzdIsABIfrr7xw==", + "dependencies": { + "@polkadot/x-global": "12.6.2", + "tslib": "^2.6.2", + "ws": "^8.15.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@scure/base": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", + "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@substrate/connect": { + "version": "0.7.35", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.35.tgz", + "integrity": "sha512-Io8vkalbwaye+7yXfG1Nj52tOOoJln2bMlc7Q9Yy3vEWqZEVkgKmcPVzbwV0CWL3QD+KMPDA2Dnw/X7EdwgoLw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@substrate/connect-extension-protocol": "^1.0.1", + "smoldot": "2.0.7" + } + }, + "node_modules/@substrate/connect-extension-protocol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", + "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", + "optional": true + }, + "node_modules/@substrate/ss58-registry": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.44.0.tgz", + "integrity": "sha512-7lQ/7mMCzVNSEfDS4BCqnRnKCFKpcOaPrxMeGTXHX1YQzM/m2BBHjbK2C3dJvjv7GYxMiaTq/HdWQj1xS6ss+A==" + }, + "node_modules/@types/bn.js": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/mock-socket": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz", + "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nock": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.4.0.tgz", + "integrity": "sha512-W8NVHjO/LCTNA64yxAPHV/K47LpGYcVzgKd3Q0n6owhwvD0Dgoterc25R4rnZbckJEb6Loxz1f5QMuJpJnbSyQ==", + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/smoldot": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.7.tgz", + "integrity": "sha512-VAOBqEen6vises36/zgrmAT1GWk2qE3X8AGnO7lmQFdskbKx8EovnwS22rtPAG+Y1Rk23/S22kDJUdPANyPkBA==", + "optional": true, + "dependencies": { + "ws": "^8.8.1" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/testing/framework/utils/generate_hex_encoded_call/package.json b/testing/framework/utils/generate_hex_encoded_call/package.json new file mode 100644 index 0000000000000..ecf0a2483db10 --- /dev/null +++ b/testing/framework/utils/generate_hex_encoded_call/package.json @@ -0,0 +1,11 @@ +{ + "name": "y", + "version": "y", + "description": "create a scale hex-encoded call values from given message", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@polkadot/api": "^10.11", + "@polkadot/util": "^12.6" + } +} diff --git a/testing/framework/utils/zombienet.sh b/testing/framework/utils/zombienet.sh new file mode 100644 index 0000000000000..bbcd1a3062025 --- /dev/null +++ b/testing/framework/utils/zombienet.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +source "${BASH_SOURCE%/*}/common.sh" + +function start_zombienet() { + local test_dir=$1 + local definition_path=$2 + local __zombienet_dir=$3 + local __zombienet_pid=$4 + + local zombienet_name=`basename $definition_path .toml` + local zombienet_dir=$test_dir/$zombienet_name + eval $__zombienet_dir="'$zombienet_dir'" + mkdir -p $zombienet_dir + rm -rf $zombienet_dir + + local logs_dir=$test_dir/logs + mkdir -p $logs_dir + local zombienet_log=$logs_dir/$zombienet_name.log + + echo "Starting $zombienet_name zombienet. Logs available at: $zombienet_log" + start_background_process \ + "$ZOMBIENET_BINARY spawn --dir $zombienet_dir --provider native $definition_path" \ + "$zombienet_log" zombienet_pid + + ensure_process_file $zombienet_pid "$zombienet_dir/zombie.json" 180 + echo "$zombienet_name zombienet started successfully" + + eval $__zombienet_pid="'$zombienet_pid'" +} + +function run_zndsl() { + local zndsl_file=$1 + local zombienet_dir=$2 + + echo "Running $zndsl_file." + $ZOMBIENET_BINARY test --dir $zombienet_dir --provider native $zndsl_file $zombienet_dir/zombie.json + echo +} diff --git a/testing/run-new-test.sh b/testing/run-new-test.sh new file mode 100755 index 0000000000000..7c84a69aa47de --- /dev/null +++ b/testing/run-new-test.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -e + +trap 'kill -9 -$$ || echo "Environment already teared down"' SIGINT SIGTERM EXIT + +test=$1 +shift + +# whether to use paths for zombienet+bridges tests container or for local testing +ZOMBIENET_DOCKER_PATHS=0 +while [ $# -ne 0 ] +do + arg="$1" + case "$arg" in + --docker) + ZOMBIENET_DOCKER_PATHS=1 + ;; + esac + shift +done + +export POLKADOT_SDK_PATH=`realpath ${BASH_SOURCE%/*}/../..` +export FRAMEWORK_PATH=`realpath ${BASH_SOURCE%/*}/framework` + +# set path to binaries +if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then + # otherwise zombienet uses some hardcoded paths + unset RUN_IN_CONTAINER + unset ZOMBIENET_IMAGE + + export POLKADOT_BINARY=/usr/local/bin/polkadot + export POLKADOT_PARACHAIN_BINARY=/usr/local/bin/polkadot-parachain + + export ZOMBIENET_BINARY=/usr/local/bin/zombie + export SUBSTRATE_RELAY_BINARY=/usr/local/bin/substrate-relay +else + export POLKADOT_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot + export POLKADOT_PARACHAIN_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot-parachain + + export ZOMBIENET_BINARY=~/local_bridge_testing/bin/zombienet-linux-x64 + export SUBSTRATE_RELAY_BINARY=~/local_bridge_testing/bin/substrate-relay +fi + +export TEST_DIR=`mktemp -d /tmp/bridges-tests-run-XXXXX` +echo -e "Test folder: $TEST_DIR\n" + +${BASH_SOURCE%/*}/tests/$test/run.sh diff --git a/testing/run-tests.sh b/testing/run-tests.sh new file mode 100755 index 0000000000000..6149d9912653c --- /dev/null +++ b/testing/run-tests.sh @@ -0,0 +1,138 @@ +#!/bin/bash +set -x +shopt -s nullglob + +trap "trap - SIGINT SIGTERM EXIT && killall -q -9 substrate-relay && kill -- -$$" SIGINT SIGTERM EXIT + +# run tests in range [TESTS_BEGIN; TESTS_END) +TESTS_BEGIN=1 +TESTS_END=1000 +# whether to use paths for zombienet+bridges tests container or for local testing +ZOMBIENET_DOCKER_PATHS=0 +while [ $# -ne 0 ] +do + arg="$1" + case "$arg" in + --docker) + ZOMBIENET_DOCKER_PATHS=1 + ;; + --test) + shift + TESTS_BEGIN="$1" + TESTS_END="$1" + ;; + esac + shift +done + +# assuming that we'll be using native provide && all processes will be executing locally +# (we need absolute paths here, because they're used when scripts are called by zombienet from tmp folders) +export POLKADOT_SDK_PATH=`realpath $(dirname "$0")/../..` +export BRIDGE_TESTS_FOLDER=$POLKADOT_SDK_PATH/bridges/testing/tests + +# set pathc to binaries +if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then + export POLKADOT_BINARY=/usr/local/bin/polkadot + export POLKADOT_PARACHAIN_BINARY=/usr/local/bin/polkadot-parachain + + export SUBSTRATE_RELAY_BINARY=/usr/local/bin/substrate-relay + export ZOMBIENET_BINARY_PATH=/usr/local/bin/zombie +else + export POLKADOT_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot + export POLKADOT_PARACHAIN_BINARY=$POLKADOT_SDK_PATH/target/release/polkadot-parachain + + export SUBSTRATE_RELAY_BINARY=~/local_bridge_testing/bin/substrate-relay + export ZOMBIENET_BINARY_PATH=~/local_bridge_testing/bin/zombienet-linux +fi + +# check if `wait` supports -p flag +if [ `printf "$BASH_VERSION\n5.1" | sort -V | head -n 1` = "5.1" ]; then IS_BASH_5_1=1; else IS_BASH_5_1=0; fi + +# bridge configuration +export LANE_ID="00000002" + +# tests configuration +ALL_TESTS_FOLDER=`mktemp -d /tmp/bridges-zombienet-tests.XXXXX` + +function start_coproc() { + local command=$1 + local name=$2 + local logname=`basename $name` + local coproc_log=`mktemp -p $TEST_FOLDER $logname.XXXXX` + coproc COPROC { + # otherwise zombienet uses some hardcoded paths + unset RUN_IN_CONTAINER + unset ZOMBIENET_IMAGE + + $command >$coproc_log 2>&1 + } + TEST_COPROCS[$COPROC_PID, 0]=$name + TEST_COPROCS[$COPROC_PID, 1]=$coproc_log + echo "Spawned $name coprocess. StdOut + StdErr: $coproc_log" + + return $COPROC_PID +} + +# execute every test from tests folder +TEST_INDEX=$TESTS_BEGIN +while true +do + declare -A TEST_COPROCS + TEST_COPROCS_COUNT=0 + TEST_PREFIX=$(printf "%04d" $TEST_INDEX) + + # it'll be used by the `sync-exit.sh` script + export TEST_FOLDER=`mktemp -d -p $ALL_TESTS_FOLDER test-$TEST_PREFIX.XXXXX` + + # check if there are no more tests + zndsl_files=($BRIDGE_TESTS_FOLDER/$TEST_PREFIX-*.zndsl) + if [ ${#zndsl_files[@]} -eq 0 ]; then + break + fi + + # start tests + for zndsl_file in "${zndsl_files[@]}"; do + start_coproc "$ZOMBIENET_BINARY_PATH --provider native test $zndsl_file" "$zndsl_file" + echo -n "1">>$TEST_FOLDER/exit-sync + ((TEST_COPROCS_COUNT++)) + done + # wait until all tests are completed + for n in `seq 1 $TEST_COPROCS_COUNT`; do + if [ "$IS_BASH_5_1" -eq 1 ]; then + wait -n -p COPROC_PID + exit_code=$? + coproc_name=${TEST_COPROCS[$COPROC_PID, 0]} + coproc_log=${TEST_COPROCS[$COPROC_PID, 1]} + coproc_stdout=$(cat $coproc_log) + else + wait -n + exit_code=$? + coproc_name="" + coproc_stdout="" + fi + echo "Process $coproc_name has finished with exit code: $exit_code" + + # if exit code is not zero, exit + if [ $exit_code -ne 0 ]; then + echo "=====================================================================" + echo "=== Shutting down. Log of failed process below ===" + echo "=====================================================================" + echo "$coproc_stdout" + + exit 1 + fi + done + + # proceed to next index + ((TEST_INDEX++)) + if [ "$TEST_INDEX" -ge "$TESTS_END" ]; then + break + fi + + # kill relay here - it is started manually by tests + killall substrate-relay +done + +echo "=====================================================================" +echo "=== All tests have completed successfully ===" +echo "=====================================================================" diff --git a/testing/scripts/invoke-script.sh b/testing/scripts/invoke-script.sh new file mode 100755 index 0000000000000..cd0557b071bba --- /dev/null +++ b/testing/scripts/invoke-script.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +INVOKE_LOG=`mktemp -p $TEST_FOLDER invoke.XXXXX` + +pushd $POLKADOT_SDK_PATH/bridges/testing/environments/rococo-westend +./bridges_rococo_westend.sh $1 >$INVOKE_LOG 2>&1 +popd diff --git a/testing/scripts/start-relayer.sh b/testing/scripts/start-relayer.sh new file mode 100755 index 0000000000000..38ea62fad5244 --- /dev/null +++ b/testing/scripts/start-relayer.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +RELAY_LOG=`mktemp -p $TEST_FOLDER relay.XXXXX` + +pushd $POLKADOT_SDK_PATH/bridges/testing/environments/rococo-westend +./bridges_rococo_westend.sh run-relay >$RELAY_LOG 2>&1& +popd diff --git a/testing/scripts/sync-exit.sh b/testing/scripts/sync-exit.sh new file mode 100755 index 0000000000000..cc20b098e7830 --- /dev/null +++ b/testing/scripts/sync-exit.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +# every network adds a char to the file, let's remove ours +truncate -s -1 $TEST_FOLDER/exit-sync + +# when all chars are removed, then our test is done +while true +do + if [ `stat --printf="%s" $TEST_FOLDER/exit-sync` -eq 0 ]; then + exit + fi + sleep 100 +done diff --git a/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl b/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl new file mode 100644 index 0000000000000..cdb7d28e940cf --- /dev/null +++ b/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl @@ -0,0 +1,12 @@ +Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml +Creds: config + +# send 5 ROC to //Alice from Rococo AH to Westend AH +asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-rococo-local 5000000000000" within 120 seconds + +# check that //Alice received at least 4.8 ROC on Westend AH +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Rococo" within 600 seconds + +# check that the relayer //Charlie is rewarded by Westend AH +bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 30 seconds diff --git a/testing/tests/0001-asset-transfer/run.sh b/testing/tests/0001-asset-transfer/run.sh new file mode 100755 index 0000000000000..a7bb122919b40 --- /dev/null +++ b/testing/tests/0001-asset-transfer/run.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -e + +source "${BASH_SOURCE%/*}/../../framework/utils/common.sh" +source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh" + +export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/rococo-westend` + +$ENV_PATH/spawn.sh --init --start-relayer & +env_pid=$! + +ensure_process_file $env_pid $TEST_DIR/rococo.env 600 +rococo_dir=`cat $TEST_DIR/rococo.env` +echo + +ensure_process_file $env_pid $TEST_DIR/westend.env 300 +westend_dir=`cat $TEST_DIR/westend.env` +echo + +run_zndsl ${BASH_SOURCE%/*}/roc-reaches-westend.zndsl $westend_dir +run_zndsl ${BASH_SOURCE%/*}/wnd-reaches-rococo.zndsl $rococo_dir + +run_zndsl ${BASH_SOURCE%/*}/wroc-reaches-rococo.zndsl $rococo_dir +run_zndsl ${BASH_SOURCE%/*}/wwnd-reaches-westend.zndsl $westend_dir diff --git a/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl b/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl new file mode 100644 index 0000000000000..dbc03864e2b6e --- /dev/null +++ b/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl @@ -0,0 +1,12 @@ +Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Hub and back +Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml +Creds: config + +# send 5 WND to //Alice from Westend AH to Rococo AH +asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-westend-local 5000000000000" within 120 seconds + +# check that //Alice received at least 4.8 WND on Rococo AH +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Westend" within 600 seconds + +# check that the relayer //Charlie is rewarded by Rococo AH +bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 30 seconds diff --git a/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl b/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl new file mode 100644 index 0000000000000..9967732cabe15 --- /dev/null +++ b/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl @@ -0,0 +1,10 @@ +Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml +Creds: config + +# send 3 wROC back to Alice from Westend AH to Rococo AH +asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-westend-local 3000000000000" within 120 seconds + +# check that //Alice received at least 2.8 wROC on Rococo AH +# (we wait until //Alice account increases here - there are no other transactions that may increase it) +asset-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds diff --git a/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl b/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl new file mode 100644 index 0000000000000..2037b0baf3c0a --- /dev/null +++ b/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl @@ -0,0 +1,10 @@ +Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Hub and back +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml +Creds: config + +# send 3 wWND back to Alice from Rococo AH to Westend AH +asset-hub-westend-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local 3000000000000" within 120 seconds + +# check that //Alice received at least 2.8 wWND on Westend AH +# (we wait until //Alice account increases here - there are no other transactions that may increase it) +asset-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl b/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl new file mode 100644 index 0000000000000..6e381f5377329 --- /dev/null +++ b/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl @@ -0,0 +1,8 @@ +Description: While relayer is idle, we only sync mandatory Rococo (and a single Rococo BH) headers to Westend BH. +Network: {{ENV_PATH}}/bridge_hub_westend_local_network.toml +Creds: config + +# ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were +# generated while relay was offline and those in the next 100 seconds while script is active. +bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-mandatory-headers-synced-when-idle.js with "300,rococo-at-westend" within 600 seconds + diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh b/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh new file mode 100755 index 0000000000000..7d5b8d9273664 --- /dev/null +++ b/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e + +source "${BASH_SOURCE%/*}/../../framework/utils/common.sh" +source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh" + +export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/rococo-westend` + +$ENV_PATH/spawn.sh & +env_pid=$! + +ensure_process_file $env_pid $TEST_DIR/rococo.env 600 +rococo_dir=`cat $TEST_DIR/rococo.env` +echo + +ensure_process_file $env_pid $TEST_DIR/westend.env 300 +westend_dir=`cat $TEST_DIR/westend.env` +echo + +# Sleep for some time before starting the relayer. We want to sleep for at least 1 session, +# which is expected to be 60 seconds for the test environment. +echo -e "Sleeping 90s before starting relayer ...\n" +sleep 90 +${BASH_SOURCE%/*}/../../environments/rococo-westend/start_relayer.sh $rococo_dir $westend_dir relayer_pid + +# Sometimes the relayer syncs multiple parachain heads in the begining leading to test failures. +# See issue: https://github.com/paritytech/parity-bridges-common/issues/2838. +# TODO: Remove this sleep after the issue is fixed. +echo -e "Sleeping 180s before runing the tests ...\n" +sleep 180 + +run_zndsl ${BASH_SOURCE%/*}/rococo-to-westend.zndsl $westend_dir +run_zndsl ${BASH_SOURCE%/*}/westend-to-rococo.zndsl $rococo_dir + diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl b/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl new file mode 100644 index 0000000000000..b4b3e43679162 --- /dev/null +++ b/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl @@ -0,0 +1,7 @@ +Description: While relayer is idle, we only sync mandatory Westend (and a single Westend BH) headers to Rococo BH. +Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml +Creds: config + +# ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were +# generated while relay was offline and those in the next 100 seconds while script is active. +bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-mandatory-headers-synced-when-idle.js with "300,westend-at-rococo" within 600 seconds diff --git a/testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl b/testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl new file mode 100644 index 0000000000000..07b91481dc7cf --- /dev/null +++ b/testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl @@ -0,0 +1,26 @@ +Description: While relayer is active, we only sync mandatory and required Rococo (and Rococo BH) headers to Westend BH. +Network: ../environments/rococo-westend/bridge_hub_westend_local_network.toml +Creds: config + +# step 1: initialize Westend AH +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-westend-local" within 60 seconds + +# step 2: initialize Westend bridge hub +bridge-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-westend-local" within 60 seconds + +# step 3: ensure that initialization has completed +asset-hub-westend-collator1: js-script ../js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds + +# step 4: send message from Westend to Rococo +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 60 seconds + +# step 5: start relayer +# (we are starting it after sending the message to be sure that relayer won't relay messages before our js script +# will be started at step 6) +# (it is started by sibling 0003-required-headers-synced-while-active-westend-to-rococo.zndsl) + +# step 6: ensure that relayer won't sync any extra headers while delivering messages and confirmations +bridge-hub-westend-collator1: js-script ../js-helpers/only-required-headers-synced-when-active.js with "500,rococo-at-westend" within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-westend-collator1: run ../scripts/sync-exit.sh within 600 seconds diff --git a/testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl b/testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl new file mode 100644 index 0000000000000..a6b11fc24052a --- /dev/null +++ b/testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl @@ -0,0 +1,26 @@ +Description: While relayer is active, we only sync mandatory and required Westend (and Westend BH) headers to Rococo BH. +Network: ../environments/rococo-westend/bridge_hub_rococo_local_network.toml +Creds: config + +# step 1: initialize Rococo AH +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-rococo-local" within 60 seconds + +# step 2: initialize Rococo bridge hub +bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 60 seconds + +# step 3: ensure that initialization has completed +asset-hub-rococo-collator1: js-script ../js-helpers/wait-hrmp-channel-opened.js with "1013" within 600 seconds + +# step 4: send message from Rococo to Westend +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 60 seconds + +# step 5: start relayer +# (we are starting it after sending the message to be sure that relayer won't relay messages before our js script +# will be started at step 6) +bridge-hub-rococo-collator1: run ../scripts/start-relayer.sh within 60 seconds + +# step 6: ensure that relayer won't sync any extra headers while delivering messages and confirmations +bridge-hub-rococo-collator1: js-script ../js-helpers/only-required-headers-synced-when-active.js with "500,westend-at-rococo" within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-rococo-collator1: run ../scripts/sync-exit.sh within 600 seconds From a5454420161dcf71381c2a4ed065db16605de53c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 09:09:18 +0000 Subject: [PATCH 1196/1210] Bump async-trait from 0.1.78 to 0.1.79 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.78 to 0.1.79. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.78...0.1.79) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- relays/bin-substrate/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- relays/equivocation/Cargo.toml | 2 +- relays/finality/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- relays/messages/Cargo.toml | 2 +- relays/parachains/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 2b89ce4f1989c..032fc8ce741e8 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] anyhow = "1.0" async-std = "1.9.0" -async-trait = "0.1.74" +async-trait = "0.1.79" codec = { package = "parity-scale-codec", version = "3.1.5" } env_logger = "0.11" futures = "0.3.30" diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 48895eff39dae..c1dea9b501523 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.74" +async-trait = "0.1.79" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 23dd4a087f97b..6f65d40fcbe7a 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.74" +async-trait = "0.1.79" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 80159b4db62a7..8cf3d409cfe98 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] async-std = "1.6.5" -async-trait = "0.1.74" +async-trait = "0.1.79" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } futures = "0.3.30" diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 27c5ee02c759f..db4f37417be4a 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] anyhow = "1.0" async-std = "1.9.0" -async-trait = "0.1.74" +async-trait = "0.1.79" codec = { package = "parity-scale-codec", version = "3.1.5" } futures = "0.3.30" hex = "0.4" diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 699649dd619d7..1233c8af741a5 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -async-trait = "0.1.74" +async-trait = "0.1.79" env_logger = "0.11" futures = "0.3.30" hex = "0.4" diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index d2eea9eb6a77a..05a995b8514a4 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -10,7 +10,7 @@ workspace = true [dependencies] async-std = "1.6.5" -async-trait = "0.1.74" +async-trait = "0.1.79" futures = "0.3.30" log = { workspace = true } relay-utils = { path = "../utils" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 81574a6855148..d1eeba2b8fd11 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -12,7 +12,7 @@ workspace = true ansi_term = "0.12" anyhow = "1.0" async-std = "1.6.5" -async-trait = "0.1.74" +async-trait = "0.1.79" backoff = "0.4" isahc = "1.2" env_logger = "0.11.3" From c7eec4949365227691207bd8d301ddea38148658 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 25 Mar 2024 14:07:25 +0100 Subject: [PATCH 1197/1210] [Backport from `polkadot-sdk`] Move chain definitions to separate folder (#2892) * [Bridges] Move chain definitions to separate folder (#3822) Related to https://github.com/paritytech/parity-bridges-common/issues/2538 This PR doesn't contain any functional changes. The PR moves specific bridged chain definitions from `bridges/primitives` to `bridges/chains` folder in order to facilitate the migration of the `parity-bridges-repo` into `polkadot-sdk` as discussed in https://hackmd.io/LprWjZ0bQXKpFeveYHIRXw?view Apart from this it also includes some cosmetic changes to some `Cargo.toml` files as a result of running `diener workspacify`. (cherry picked from commit 0711729d251efebf3486db602119ecfa67d98366) * diener workspacify --- .../chain-asset-hub-rococo/Cargo.toml | 2 +- .../chain-asset-hub-rococo/src/lib.rs | 0 .../chain-asset-hub-westend/Cargo.toml | 2 +- .../chain-asset-hub-westend/src/lib.rs | 0 .../chain-bridge-hub-cumulus/Cargo.toml | 0 .../chain-bridge-hub-cumulus/src/lib.rs | 0 .../chain-bridge-hub-kusama/Cargo.toml | 0 .../chain-bridge-hub-kusama/src/lib.rs | 0 .../chain-bridge-hub-polkadot/Cargo.toml | 0 .../chain-bridge-hub-polkadot/src/lib.rs | 0 .../chain-bridge-hub-rococo/Cargo.toml | 0 .../chain-bridge-hub-rococo/src/lib.rs | 0 .../chain-bridge-hub-westend/Cargo.toml | 0 .../chain-bridge-hub-westend/src/lib.rs | 0 {primitives => chains}/chain-kusama/Cargo.toml | 6 +++--- {primitives => chains}/chain-kusama/src/lib.rs | 0 .../chain-polkadot-bulletin/Cargo.toml | 8 ++++---- .../chain-polkadot-bulletin/src/lib.rs | 0 {primitives => chains}/chain-polkadot/Cargo.toml | 6 +++--- {primitives => chains}/chain-polkadot/src/lib.rs | 0 {primitives => chains}/chain-rococo/Cargo.toml | 6 +++--- {primitives => chains}/chain-rococo/src/lib.rs | 0 {primitives => chains}/chain-westend/Cargo.toml | 6 +++--- {primitives => chains}/chain-westend/src/lib.rs | 0 relays/bin-substrate/Cargo.toml | 10 +++++----- relays/client-bridge-hub-kusama/Cargo.toml | 4 ++-- relays/client-bridge-hub-polkadot/Cargo.toml | 6 +++--- relays/client-bridge-hub-rococo/Cargo.toml | 2 +- relays/client-bridge-hub-westend/Cargo.toml | 4 ++-- relays/client-kusama/Cargo.toml | 2 +- relays/client-polkadot-bulletin/Cargo.toml | 2 +- relays/client-polkadot/Cargo.toml | 2 +- relays/client-rococo/Cargo.toml | 2 +- relays/client-westend/Cargo.toml | 2 +- relays/lib-substrate-relay/Cargo.toml | 2 +- 35 files changed, 37 insertions(+), 37 deletions(-) rename {primitives => chains}/chain-asset-hub-rococo/Cargo.toml (87%) rename {primitives => chains}/chain-asset-hub-rococo/src/lib.rs (100%) rename {primitives => chains}/chain-asset-hub-westend/Cargo.toml (87%) rename {primitives => chains}/chain-asset-hub-westend/src/lib.rs (100%) rename {primitives => chains}/chain-bridge-hub-cumulus/Cargo.toml (100%) rename {primitives => chains}/chain-bridge-hub-cumulus/src/lib.rs (100%) rename {primitives => chains}/chain-bridge-hub-kusama/Cargo.toml (100%) rename {primitives => chains}/chain-bridge-hub-kusama/src/lib.rs (100%) rename {primitives => chains}/chain-bridge-hub-polkadot/Cargo.toml (100%) rename {primitives => chains}/chain-bridge-hub-polkadot/src/lib.rs (100%) rename {primitives => chains}/chain-bridge-hub-rococo/Cargo.toml (100%) rename {primitives => chains}/chain-bridge-hub-rococo/src/lib.rs (100%) rename {primitives => chains}/chain-bridge-hub-westend/Cargo.toml (100%) rename {primitives => chains}/chain-bridge-hub-westend/src/lib.rs (100%) rename {primitives => chains}/chain-kusama/Cargo.toml (75%) rename {primitives => chains}/chain-kusama/src/lib.rs (100%) rename {primitives => chains}/chain-polkadot-bulletin/Cargo.toml (80%) rename {primitives => chains}/chain-polkadot-bulletin/src/lib.rs (100%) rename {primitives => chains}/chain-polkadot/Cargo.toml (75%) rename {primitives => chains}/chain-polkadot/src/lib.rs (100%) rename {primitives => chains}/chain-rococo/Cargo.toml (75%) rename {primitives => chains}/chain-rococo/src/lib.rs (100%) rename {primitives => chains}/chain-westend/Cargo.toml (75%) rename {primitives => chains}/chain-westend/src/lib.rs (100%) diff --git a/primitives/chain-asset-hub-rococo/Cargo.toml b/chains/chain-asset-hub-rococo/Cargo.toml similarity index 87% rename from primitives/chain-asset-hub-rococo/Cargo.toml rename to chains/chain-asset-hub-rococo/Cargo.toml index 08be719bfd98c..336e2b4d4022f 100644 --- a/primitives/chain-asset-hub-rococo/Cargo.toml +++ b/chains/chain-asset-hub-rococo/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { version = "2.11.0", default-features = false, features = ["derive frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } +bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-asset-hub-rococo/src/lib.rs b/chains/chain-asset-hub-rococo/src/lib.rs similarity index 100% rename from primitives/chain-asset-hub-rococo/src/lib.rs rename to chains/chain-asset-hub-rococo/src/lib.rs diff --git a/primitives/chain-asset-hub-westend/Cargo.toml b/chains/chain-asset-hub-westend/Cargo.toml similarity index 87% rename from primitives/chain-asset-hub-westend/Cargo.toml rename to chains/chain-asset-hub-westend/Cargo.toml index d8245c7a89586..99b6c26e2638b 100644 --- a/primitives/chain-asset-hub-westend/Cargo.toml +++ b/chains/chain-asset-hub-westend/Cargo.toml @@ -17,7 +17,7 @@ scale-info = { version = "2.11.0", default-features = false, features = ["derive frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } # Bridge Dependencies -bp-xcm-bridge-hub-router = { path = "../xcm-bridge-hub-router", default-features = false } +bp-xcm-bridge-hub-router = { path = "../../primitives/xcm-bridge-hub-router", default-features = false } [features] default = ["std"] diff --git a/primitives/chain-asset-hub-westend/src/lib.rs b/chains/chain-asset-hub-westend/src/lib.rs similarity index 100% rename from primitives/chain-asset-hub-westend/src/lib.rs rename to chains/chain-asset-hub-westend/src/lib.rs diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/chains/chain-bridge-hub-cumulus/Cargo.toml similarity index 100% rename from primitives/chain-bridge-hub-cumulus/Cargo.toml rename to chains/chain-bridge-hub-cumulus/Cargo.toml diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/chains/chain-bridge-hub-cumulus/src/lib.rs similarity index 100% rename from primitives/chain-bridge-hub-cumulus/src/lib.rs rename to chains/chain-bridge-hub-cumulus/src/lib.rs diff --git a/primitives/chain-bridge-hub-kusama/Cargo.toml b/chains/chain-bridge-hub-kusama/Cargo.toml similarity index 100% rename from primitives/chain-bridge-hub-kusama/Cargo.toml rename to chains/chain-bridge-hub-kusama/Cargo.toml diff --git a/primitives/chain-bridge-hub-kusama/src/lib.rs b/chains/chain-bridge-hub-kusama/src/lib.rs similarity index 100% rename from primitives/chain-bridge-hub-kusama/src/lib.rs rename to chains/chain-bridge-hub-kusama/src/lib.rs diff --git a/primitives/chain-bridge-hub-polkadot/Cargo.toml b/chains/chain-bridge-hub-polkadot/Cargo.toml similarity index 100% rename from primitives/chain-bridge-hub-polkadot/Cargo.toml rename to chains/chain-bridge-hub-polkadot/Cargo.toml diff --git a/primitives/chain-bridge-hub-polkadot/src/lib.rs b/chains/chain-bridge-hub-polkadot/src/lib.rs similarity index 100% rename from primitives/chain-bridge-hub-polkadot/src/lib.rs rename to chains/chain-bridge-hub-polkadot/src/lib.rs diff --git a/primitives/chain-bridge-hub-rococo/Cargo.toml b/chains/chain-bridge-hub-rococo/Cargo.toml similarity index 100% rename from primitives/chain-bridge-hub-rococo/Cargo.toml rename to chains/chain-bridge-hub-rococo/Cargo.toml diff --git a/primitives/chain-bridge-hub-rococo/src/lib.rs b/chains/chain-bridge-hub-rococo/src/lib.rs similarity index 100% rename from primitives/chain-bridge-hub-rococo/src/lib.rs rename to chains/chain-bridge-hub-rococo/src/lib.rs diff --git a/primitives/chain-bridge-hub-westend/Cargo.toml b/chains/chain-bridge-hub-westend/Cargo.toml similarity index 100% rename from primitives/chain-bridge-hub-westend/Cargo.toml rename to chains/chain-bridge-hub-westend/Cargo.toml diff --git a/primitives/chain-bridge-hub-westend/src/lib.rs b/chains/chain-bridge-hub-westend/src/lib.rs similarity index 100% rename from primitives/chain-bridge-hub-westend/src/lib.rs rename to chains/chain-bridge-hub-westend/src/lib.rs diff --git a/primitives/chain-kusama/Cargo.toml b/chains/chain-kusama/Cargo.toml similarity index 75% rename from primitives/chain-kusama/Cargo.toml rename to chains/chain-kusama/Cargo.toml index 465acf121d408..56a4386afb8f3 100644 --- a/primitives/chain-kusama/Cargo.toml +++ b/chains/chain-kusama/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chain-kusama/src/lib.rs b/chains/chain-kusama/src/lib.rs similarity index 100% rename from primitives/chain-kusama/src/lib.rs rename to chains/chain-kusama/src/lib.rs diff --git a/primitives/chain-polkadot-bulletin/Cargo.toml b/chains/chain-polkadot-bulletin/Cargo.toml similarity index 80% rename from primitives/chain-polkadot-bulletin/Cargo.toml rename to chains/chain-polkadot-bulletin/Cargo.toml index 797a893b21c39..1e2bbaf6b8af0 100644 --- a/primitives/chain-polkadot-bulletin/Cargo.toml +++ b/chains/chain-polkadot-bulletin/Cargo.toml @@ -15,10 +15,10 @@ scale-info = { version = "2.11.0", default-features = false, features = ["derive # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-messages = { path = "../messages", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-messages = { path = "../../primitives/messages", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chain-polkadot-bulletin/src/lib.rs b/chains/chain-polkadot-bulletin/src/lib.rs similarity index 100% rename from primitives/chain-polkadot-bulletin/src/lib.rs rename to chains/chain-polkadot-bulletin/src/lib.rs diff --git a/primitives/chain-polkadot/Cargo.toml b/chains/chain-polkadot/Cargo.toml similarity index 75% rename from primitives/chain-polkadot/Cargo.toml rename to chains/chain-polkadot/Cargo.toml index 20080a7901b69..5faee3bd34ad4 100644 --- a/primitives/chain-polkadot/Cargo.toml +++ b/chains/chain-polkadot/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chain-polkadot/src/lib.rs b/chains/chain-polkadot/src/lib.rs similarity index 100% rename from primitives/chain-polkadot/src/lib.rs rename to chains/chain-polkadot/src/lib.rs diff --git a/primitives/chain-rococo/Cargo.toml b/chains/chain-rococo/Cargo.toml similarity index 75% rename from primitives/chain-rococo/Cargo.toml rename to chains/chain-rococo/Cargo.toml index 459ee6f9f0517..401611bebbe47 100644 --- a/primitives/chain-rococo/Cargo.toml +++ b/chains/chain-rococo/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chain-rococo/src/lib.rs b/chains/chain-rococo/src/lib.rs similarity index 100% rename from primitives/chain-rococo/src/lib.rs rename to chains/chain-rococo/src/lib.rs diff --git a/primitives/chain-westend/Cargo.toml b/chains/chain-westend/Cargo.toml similarity index 75% rename from primitives/chain-westend/Cargo.toml rename to chains/chain-westend/Cargo.toml index 4710da7bb335d..d697e2b36c42c 100644 --- a/primitives/chain-westend/Cargo.toml +++ b/chains/chain-westend/Cargo.toml @@ -13,9 +13,9 @@ workspace = true # Bridge Dependencies -bp-header-chain = { path = "../header-chain", default-features = false } -bp-polkadot-core = { path = "../polkadot-core", default-features = false } -bp-runtime = { path = "../runtime", default-features = false } +bp-header-chain = { path = "../../primitives/header-chain", default-features = false } +bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies diff --git a/primitives/chain-westend/src/lib.rs b/chains/chain-westend/src/lib.rs similarity index 100% rename from primitives/chain-westend/src/lib.rs rename to chains/chain-westend/src/lib.rs diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml index 032fc8ce741e8..6c0ac1da6fc58 100644 --- a/relays/bin-substrate/Cargo.toml +++ b/relays/bin-substrate/Cargo.toml @@ -26,15 +26,15 @@ signal-hook-async-std = "0.2.2" strum = { version = "0.26.2", features = ["derive"] } # Bridge dependencies -bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } -bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } +bp-bridge-hub-polkadot = { path = "../../chains/chain-bridge-hub-polkadot" } +bp-bridge-hub-rococo = { path = "../../chains/chain-bridge-hub-rococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot-bulletin = { path = "../../chains/chain-polkadot-bulletin" } +bp-polkadot = { path = "../../chains/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../primitives/chain-rococo" } +bp-rococo = { path = "../../chains/chain-rococo" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } pallet-bridge-parachains = { path = "../../modules/parachains" } diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml index 6e41bb3fcee8e..a02dc26a0a8d3 100644 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ b/relays/client-bridge-hub-kusama/Cargo.toml @@ -16,11 +16,11 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-bridge-hub-kusama = { path = "../../primitives/chain-bridge-hub-kusama" } +bp-bridge-hub-kusama = { path = "../../chains/chain-bridge-hub-kusama" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot = { path = "../../chains/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml index f5fc69d02be21..abfd5bae4f025 100644 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ b/relays/client-bridge-hub-polkadot/Cargo.toml @@ -15,13 +15,13 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-bridge-hub-polkadot = { path = "../../primitives/chain-bridge-hub-polkadot" } +bp-bridge-hub-polkadot = { path = "../../chains/chain-bridge-hub-polkadot" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot = { path = "../../chains/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-kusama = { path = "../../primitives/chain-kusama" } +bp-kusama = { path = "../../chains/chain-kusama" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml index efccfa5fb60e4..70d65ac19453c 100644 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ b/relays/client-bridge-hub-rococo/Cargo.toml @@ -15,7 +15,7 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-bridge-hub-rococo = { path = "../../primitives/chain-bridge-hub-rococo" } +bp-bridge-hub-rococo = { path = "../../chains/chain-bridge-hub-rococo" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml index 188839e2dba46..c65c7ec0014b8 100644 --- a/relays/client-bridge-hub-westend/Cargo.toml +++ b/relays/client-bridge-hub-westend/Cargo.toml @@ -15,12 +15,12 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-bridge-hub-westend = { path = "../../primitives/chain-bridge-hub-westend" } +bp-bridge-hub-westend = { path = "../../chains/chain-bridge-hub-westend" } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-parachains = { path = "../../primitives/parachains" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../primitives/chain-rococo" } +bp-rococo = { path = "../../chains/chain-rococo" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml index 6d3a71b3855e4..c459f347af1ed 100644 --- a/relays/client-kusama/Cargo.toml +++ b/relays/client-kusama/Cargo.toml @@ -15,7 +15,7 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-kusama = { path = "../../primitives/chain-kusama" } +bp-kusama = { path = "../../chains/chain-kusama" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml index 2160a35fb8ffe..842b53c48ef25 100644 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ b/relays/client-polkadot-bulletin/Cargo.toml @@ -18,7 +18,7 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } bp-header-chain = { path = "../../primitives/header-chain" } bp-messages = { path = "../../primitives/messages" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-polkadot-bulletin = { path = "../../primitives/chain-polkadot-bulletin" } +bp-polkadot-bulletin = { path = "../../chains/chain-polkadot-bulletin" } bp-runtime = { path = "../../primitives/runtime" } bridge-runtime-common = { path = "../../bin/runtime-common" } relay-substrate-client = { path = "../client-substrate" } diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml index daa3423bbd424..19cf9f9335bc5 100644 --- a/relays/client-polkadot/Cargo.toml +++ b/relays/client-polkadot/Cargo.toml @@ -15,7 +15,7 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies -bp-polkadot = { path = "../../primitives/chain-polkadot" } +bp-polkadot = { path = "../../chains/chain-polkadot" } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml index 7a6b7d3bae224..5e847600f4660 100644 --- a/relays/client-rococo/Cargo.toml +++ b/relays/client-rococo/Cargo.toml @@ -16,7 +16,7 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } # Bridge dependencies bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../primitives/chain-rococo" } +bp-rococo = { path = "../../chains/chain-rococo" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml index 2c9aacc16e69b..8b56e51d084d2 100644 --- a/relays/client-westend/Cargo.toml +++ b/relays/client-westend/Cargo.toml @@ -17,7 +17,7 @@ subxt = { version = "0.32.1", default-features = false, features = ["native"] } bp-polkadot-core = { path = "../../primitives/polkadot-core" } bp-runtime = { path = "../../primitives/runtime" } -bp-westend = { path = "../../primitives/chain-westend" } +bp-westend = { path = "../../chains/chain-westend" } relay-substrate-client = { path = "../client-substrate" } relay-utils = { path = "../utils" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index db4f37417be4a..db4c3a7f8875c 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -56,7 +56,7 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", bra sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] -bp-rococo = { path = "../../primitives/chain-rococo" } +bp-rococo = { path = "../../chains/chain-rococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } relay-bridge-hub-westend-client = { path = "../client-bridge-hub-westend" } From 62bd711a202fc192e4fd8cdb7d916a458f058acb Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Mon, 25 Mar 2024 15:14:25 +0100 Subject: [PATCH 1198/1210] Move relay clients to separate folder (#2893) --- relays/bin-substrate/Cargo.toml | 66 - ..._kusama_messages_to_bridge_hub_polkadot.rs | 68 - ..._polkadot_messages_to_bridge_hub_kusama.rs | 68 - .../kusama_headers_to_bridge_hub_polkadot.rs | 80 - ...usama_parachains_to_bridge_hub_polkadot.rs | 75 - .../src/bridges/kusama_polkadot/mod.rs | 24 - .../polkadot_headers_to_bridge_hub_kusama.rs | 80 - ...olkadot_parachains_to_bridge_hub_kusama.rs | 75 - relays/bin-substrate/src/bridges/mod.rs | 22 - ..._polkadot_messages_to_polkadot_bulletin.rs | 69 - .../src/bridges/polkadot_bulletin/mod.rs | 23 - ...bulletin_headers_to_bridge_hub_polkadot.rs | 86 - ...ulletin_messages_to_bridge_hub_polkadot.rs | 69 - .../polkadot_headers_to_polkadot_bulletin.rs | 80 - ...olkadot_parachains_to_polkadot_bulletin.rs | 94 - ..._hub_rococo_messages_to_rococo_bulletin.rs | 68 - .../src/bridges/rococo_bulletin/mod.rs | 237 - ...o_bulletin_headers_to_bridge_hub_rococo.rs | 87 - ..._bulletin_messages_to_bridge_hub_rococo.rs | 68 - .../rococo_headers_to_rococo_bulletin.rs | 82 - .../rococo_parachains_to_rococo_bulletin.rs | 91 - ...b_rococo_messages_to_bridge_hub_westend.rs | 67 - ...b_westend_messages_to_bridge_hub_rococo.rs | 67 - .../src/bridges/rococo_westend/mod.rs | 24 - .../rococo_headers_to_bridge_hub_westend.rs | 80 - ...rococo_parachains_to_bridge_hub_westend.rs | 75 - .../westend_headers_to_bridge_hub_rococo.rs | 80 - ...westend_parachains_to_bridge_hub_rococo.rs | 75 - relays/bin-substrate/src/cli/chain_schema.rs | 110 - .../src/cli/detect_equivocations.rs | 74 - relays/bin-substrate/src/cli/init_bridge.rs | 199 - relays/bin-substrate/src/cli/mod.rs | 131 - relays/bin-substrate/src/cli/relay_headers.rs | 85 - .../src/cli/relay_headers_and_messages.rs | 377 - .../bin-substrate/src/cli/relay_messages.rs | 96 - .../bin-substrate/src/cli/relay_parachains.rs | 81 - relays/bin-substrate/src/main.rs | 28 - relays/client-bridge-hub-kusama/Cargo.toml | 32 - .../src/codegen_runtime.rs | 4053 -------- relays/client-bridge-hub-kusama/src/lib.rs | 127 - .../src/runtime_wrapper.rs | 71 - relays/client-bridge-hub-polkadot/Cargo.toml | 33 - .../src/codegen_runtime.rs | 4056 -------- relays/client-bridge-hub-polkadot/src/lib.rs | 131 - .../src/runtime_wrapper.rs | 130 - relays/client-bridge-hub-rococo/Cargo.toml | 32 - .../src/codegen_runtime.rs | 5506 ----------- relays/client-bridge-hub-rococo/src/lib.rs | 129 - relays/client-bridge-hub-westend/Cargo.toml | 36 - .../src/codegen_runtime.rs | 4705 --------- relays/client-bridge-hub-westend/src/lib.rs | 127 - relays/client-kusama/Cargo.toml | 31 - relays/client-kusama/src/codegen_runtime.rs | 8338 ---------------- relays/client-kusama/src/lib.rs | 122 - relays/client-polkadot-bulletin/Cargo.toml | 33 - .../src/codegen_runtime.rs | 1622 ---- relays/client-polkadot-bulletin/src/lib.rs | 137 - relays/client-polkadot/Cargo.toml | 31 - relays/client-polkadot/src/codegen_runtime.rs | 8399 ----------------- relays/client-polkadot/src/lib.rs | 122 - relays/client-rococo/Cargo.toml | 30 - relays/client-rococo/src/codegen_runtime.rs | 7441 --------------- relays/client-rococo/src/lib.rs | 122 - relays/client-westend/Cargo.toml | 31 - relays/client-westend/src/codegen_runtime.rs | 6945 -------------- relays/client-westend/src/lib.rs | 122 - relays/lib-substrate-relay/Cargo.toml | 6 +- 67 files changed, 3 insertions(+), 55958 deletions(-) delete mode 100644 relays/bin-substrate/Cargo.toml delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs delete mode 100644 relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs delete mode 100644 relays/bin-substrate/src/bridges/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs delete mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs delete mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs delete mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs delete mode 100644 relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/mod.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs delete mode 100644 relays/bin-substrate/src/cli/chain_schema.rs delete mode 100644 relays/bin-substrate/src/cli/detect_equivocations.rs delete mode 100644 relays/bin-substrate/src/cli/init_bridge.rs delete mode 100644 relays/bin-substrate/src/cli/mod.rs delete mode 100644 relays/bin-substrate/src/cli/relay_headers.rs delete mode 100644 relays/bin-substrate/src/cli/relay_headers_and_messages.rs delete mode 100644 relays/bin-substrate/src/cli/relay_messages.rs delete mode 100644 relays/bin-substrate/src/cli/relay_parachains.rs delete mode 100644 relays/bin-substrate/src/main.rs delete mode 100644 relays/client-bridge-hub-kusama/Cargo.toml delete mode 100644 relays/client-bridge-hub-kusama/src/codegen_runtime.rs delete mode 100644 relays/client-bridge-hub-kusama/src/lib.rs delete mode 100644 relays/client-bridge-hub-kusama/src/runtime_wrapper.rs delete mode 100644 relays/client-bridge-hub-polkadot/Cargo.toml delete mode 100644 relays/client-bridge-hub-polkadot/src/codegen_runtime.rs delete mode 100644 relays/client-bridge-hub-polkadot/src/lib.rs delete mode 100644 relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs delete mode 100644 relays/client-bridge-hub-rococo/Cargo.toml delete mode 100644 relays/client-bridge-hub-rococo/src/codegen_runtime.rs delete mode 100644 relays/client-bridge-hub-rococo/src/lib.rs delete mode 100644 relays/client-bridge-hub-westend/Cargo.toml delete mode 100644 relays/client-bridge-hub-westend/src/codegen_runtime.rs delete mode 100644 relays/client-bridge-hub-westend/src/lib.rs delete mode 100644 relays/client-kusama/Cargo.toml delete mode 100644 relays/client-kusama/src/codegen_runtime.rs delete mode 100644 relays/client-kusama/src/lib.rs delete mode 100644 relays/client-polkadot-bulletin/Cargo.toml delete mode 100644 relays/client-polkadot-bulletin/src/codegen_runtime.rs delete mode 100644 relays/client-polkadot-bulletin/src/lib.rs delete mode 100644 relays/client-polkadot/Cargo.toml delete mode 100644 relays/client-polkadot/src/codegen_runtime.rs delete mode 100644 relays/client-polkadot/src/lib.rs delete mode 100644 relays/client-rococo/Cargo.toml delete mode 100644 relays/client-rococo/src/codegen_runtime.rs delete mode 100644 relays/client-rococo/src/lib.rs delete mode 100644 relays/client-westend/Cargo.toml delete mode 100644 relays/client-westend/src/codegen_runtime.rs delete mode 100644 relays/client-westend/src/lib.rs diff --git a/relays/bin-substrate/Cargo.toml b/relays/bin-substrate/Cargo.toml deleted file mode 100644 index 6c0ac1da6fc58..0000000000000 --- a/relays/bin-substrate/Cargo.toml +++ /dev/null @@ -1,66 +0,0 @@ -[package] -name = "substrate-relay" -version = "1.2.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -anyhow = "1.0" -async-std = "1.9.0" -async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.1.5" } -env_logger = "0.11" -futures = "0.3.30" -hex = "0.4" -log = { workspace = true } -num-format = "0.4" -num-traits = "0.2" -rbtag = "0.3" -structopt = "0.3" -signal-hook = "0.3.15" -signal-hook-async-std = "0.2.2" -strum = { version = "0.26.2", features = ["derive"] } - -# Bridge dependencies -bp-bridge-hub-polkadot = { path = "../../chains/chain-bridge-hub-polkadot" } -bp-bridge-hub-rococo = { path = "../../chains/chain-bridge-hub-rococo" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-bulletin = { path = "../../chains/chain-polkadot-bulletin" } -bp-polkadot = { path = "../../chains/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../chains/chain-rococo" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } -pallet-bridge-parachains = { path = "../../modules/parachains" } -parachains-relay = { path = "../parachains" } -relay-bridge-hub-kusama-client = { path = "../client-bridge-hub-kusama" } -relay-bridge-hub-polkadot-client = { path = "../client-bridge-hub-polkadot" } -relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } -relay-bridge-hub-westend-client = { path = "../client-bridge-hub-westend" } -relay-kusama-client = { path = "../client-kusama" } -relay-polkadot-client = { path = "../client-polkadot" } -relay-polkadot-bulletin-client = { path = "../client-polkadot-bulletin" } -relay-rococo-client = { path = "../client-rococo" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } -relay-westend-client = { path = "../client-westend" } -substrate-relay-helper = { path = "../lib-substrate-relay" } - -# Substrate Dependencies - -frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[dev-dependencies] -bp-test-utils = { path = "../../primitives/test-utils" } -hex-literal = "0.4" -sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -tempfile = "3.10" -finality-grandpa = { version = "0.16.2" } diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs deleted file mode 100644 index fc239ca1ed387..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_kusama_messages_to_bridge_hub_polkadot.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubKusama-to-BridgeHubPolkadot messages sync entrypoint. - -use relay_bridge_hub_kusama_client::BridgeHubKusama; -use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -/// BridgeHubKusama-to-BridgeHubPolkadot messages bridge. -pub struct BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge { - type Source = BridgeHubKusama; - type Target = BridgeHubPolkadot; -} - -impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge { - type MessagesLane = BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane, - BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, - relay_bridge_hub_polkadot_client::BridgeKusamaMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane, - BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotMessages, - relay_bridge_hub_kusama_client::BridgeMessagesCall::receive_messages_delivery_proof -); - -/// BridgeHubKusama-to-BridgeHubPolkadot messages lane. -#[derive(Clone, Debug)] -pub struct BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane; - -impl SubstrateMessageLane for BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane { - type SourceChain = BridgeHubKusama; - type TargetChain = BridgeHubPolkadot; - - type ReceiveMessagesProofCallBuilder = - BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs deleted file mode 100644 index 8d8e5e0c35e56..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/bridge_hub_polkadot_messages_to_bridge_hub_kusama.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubPolkadot-to-BridgeHubKusama messages sync entrypoint. - -use relay_bridge_hub_kusama_client::BridgeHubKusama; -use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -/// BridgeHubPolkadot-to-BridgeHubKusama messages bridge. -pub struct BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge { - type Source = BridgeHubPolkadot; - type Target = BridgeHubKusama; -} - -impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge { - type MessagesLane = BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane, - BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotMessages, - relay_bridge_hub_kusama_client::BridgeMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane, - BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, - relay_bridge_hub_polkadot_client::BridgeKusamaMessagesCall::receive_messages_delivery_proof -); - -/// BridgeHubPolkadot-to-BridgeHubKusama messages lane. -#[derive(Clone, Debug)] -pub struct BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane; - -impl SubstrateMessageLane for BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane { - type SourceChain = BridgeHubPolkadot; - type TargetChain = BridgeHubKusama; - - type ReceiveMessagesProofCallBuilder = - BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs deleted file mode 100644 index 196a22cd70d79..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_headers_to_bridge_hub_polkadot.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Kusama-to-BridgeHubPolkadot headers sync entrypoint. - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Kusama -> PolkadotBridgeHub finalized headers bridge. -#[derive(Clone, Debug)] -pub struct KusamaFinalityToBridgeHubPolkadot; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - KusamaFinalityToBridgeHubPolkadot, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa, - relay_bridge_hub_polkadot_client::BridgeKusamaGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - KusamaFinalityToBridgeHubPolkadot, - ReportEquivocationCallBuilder, - relay_kusama_client::RuntimeCall::Grandpa, - relay_kusama_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for KusamaFinalityToBridgeHubPolkadot { - type SourceChain = relay_kusama_client::Kusama; - type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for KusamaFinalityToBridgeHubPolkadot { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for KusamaFinalityToBridgeHubPolkadot { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Kusama` to BridgeHub `Polkadot` bridge definition. -pub struct KusamaToBridgeHubPolkadotCliBridge {} - -impl CliBridgeBase for KusamaToBridgeHubPolkadotCliBridge { - type Source = relay_kusama_client::Kusama; - type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -} - -impl RelayToRelayHeadersCliBridge for KusamaToBridgeHubPolkadotCliBridge { - type Finality = KusamaFinalityToBridgeHubPolkadot; -} - -impl RelayToRelayEquivocationDetectionCliBridge for KusamaToBridgeHubPolkadotCliBridge { - type Equivocation = KusamaFinalityToBridgeHubPolkadot; -} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs deleted file mode 100644 index b39b970080534..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/kusama_parachains_to_bridge_hub_polkadot.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Kusama-to-BridgeHubPolkadot parachains sync entrypoint. - -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, -}; - -/// Kusama-to-BridgeHubPolkadot parachain sync description. -#[derive(Clone, Debug)] -pub struct BridgeHubKusamaToBridgeHubPolkadot; - -impl SubstrateParachainsPipeline for BridgeHubKusamaToBridgeHubPolkadot { - type SourceParachain = relay_bridge_hub_kusama_client::BridgeHubKusama; - type SourceRelayChain = relay_kusama_client::Kusama; - type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - - type SubmitParachainHeadsCallBuilder = BridgeHubKusamaToBridgeHubPolkadotCallBuilder; -} - -pub struct BridgeHubKusamaToBridgeHubPolkadotCallBuilder; -impl SubmitParachainHeadsCallBuilder - for BridgeHubKusamaToBridgeHubPolkadotCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaParachains( - relay_bridge_hub_polkadot_client::BridgeParachainCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// Kusama-to-BridgeHubPolkadot parachain sync description for the CLI. -pub struct BridgeHubKusamaToBridgeHubPolkadotCliBridge {} - -impl ParachainToRelayHeadersCliBridge for BridgeHubKusamaToBridgeHubPolkadotCliBridge { - type SourceRelay = relay_kusama_client::Kusama; - type ParachainFinality = BridgeHubKusamaToBridgeHubPolkadot; - type RelayFinality = - crate::bridges::kusama_polkadot::kusama_headers_to_bridge_hub_polkadot::KusamaFinalityToBridgeHubPolkadot; -} - -impl CliBridgeBase for BridgeHubKusamaToBridgeHubPolkadotCliBridge { - type Source = relay_bridge_hub_kusama_client::BridgeHubKusama; - type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -} - -impl MessagesCliBridge for BridgeHubKusamaToBridgeHubPolkadotCliBridge { - type MessagesLane = - crate::bridges::kusama_polkadot::bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaMessagesToBridgeHubPolkadotMessageLane; -} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs deleted file mode 100644 index 65cd8d9ded6cd..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Kusama Bridge Hub and Polkadot Bridge Hub. - -pub mod bridge_hub_kusama_messages_to_bridge_hub_polkadot; -pub mod bridge_hub_polkadot_messages_to_bridge_hub_kusama; -pub mod kusama_headers_to_bridge_hub_polkadot; -pub mod kusama_parachains_to_bridge_hub_polkadot; -pub mod polkadot_headers_to_bridge_hub_kusama; -pub mod polkadot_parachains_to_bridge_hub_kusama; diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs deleted file mode 100644 index d96326a288de9..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_headers_to_bridge_hub_kusama.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Polkadot-to-KusamaBridgeHub headers sync entrypoint. - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -/// Description of Polkadot -> KusamaBridgeHub finalized headers bridge. -#[derive(Clone, Debug)] -pub struct PolkadotFinalityToBridgeHubKusama; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - PolkadotFinalityToBridgeHubKusama, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotGrandpa, - relay_bridge_hub_kusama_client::BridgeGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - PolkadotFinalityToBridgeHubKusama, - ReportEquivocationCallBuilder, - relay_polkadot_client::RuntimeCall::Grandpa, - relay_polkadot_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for PolkadotFinalityToBridgeHubKusama { - type SourceChain = relay_polkadot_client::Polkadot; - type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for PolkadotFinalityToBridgeHubKusama { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for PolkadotFinalityToBridgeHubKusama { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Polkadot` to BridgeHub `Kusama` bridge definition. -pub struct PolkadotToBridgeHubKusamaCliBridge {} - -impl CliBridgeBase for PolkadotToBridgeHubKusamaCliBridge { - type Source = relay_polkadot_client::Polkadot; - type Target = relay_bridge_hub_kusama_client::BridgeHubKusama; -} - -impl RelayToRelayHeadersCliBridge for PolkadotToBridgeHubKusamaCliBridge { - type Finality = PolkadotFinalityToBridgeHubKusama; -} - -impl RelayToRelayEquivocationDetectionCliBridge for PolkadotToBridgeHubKusamaCliBridge { - type Equivocation = PolkadotFinalityToBridgeHubKusama; -} diff --git a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs b/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs deleted file mode 100644 index 25ce53cb5990d..0000000000000 --- a/relays/bin-substrate/src/bridges/kusama_polkadot/polkadot_parachains_to_bridge_hub_kusama.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Polkadot-to-BridgeHubKusama parachains sync entrypoint. - -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, -}; - -/// Polkadot-to-BridgeHubKusama parachain sync description. -#[derive(Clone, Debug)] -pub struct BridgeHubPolkadotToBridgeHubKusama; - -impl SubstrateParachainsPipeline for BridgeHubPolkadotToBridgeHubKusama { - type SourceParachain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - type SourceRelayChain = relay_polkadot_client::Polkadot; - type TargetChain = relay_bridge_hub_kusama_client::BridgeHubKusama; - - type SubmitParachainHeadsCallBuilder = BridgeHubPolkadotToBridgeHubKusamaCallBuilder; -} - -pub struct BridgeHubPolkadotToBridgeHubKusamaCallBuilder; -impl SubmitParachainHeadsCallBuilder - for BridgeHubPolkadotToBridgeHubKusamaCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotParachains( - relay_bridge_hub_kusama_client::BridgeParachainCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// Polkadot-to-BridgeHubKusama parachain sync description for the CLI. -pub struct BridgeHubPolkadotToBridgeHubKusamaCliBridge {} - -impl ParachainToRelayHeadersCliBridge for BridgeHubPolkadotToBridgeHubKusamaCliBridge { - type SourceRelay = relay_polkadot_client::Polkadot; - type ParachainFinality = BridgeHubPolkadotToBridgeHubKusama; - type RelayFinality = - crate::bridges::kusama_polkadot::polkadot_headers_to_bridge_hub_kusama::PolkadotFinalityToBridgeHubKusama; -} - -impl CliBridgeBase for BridgeHubPolkadotToBridgeHubKusamaCliBridge { - type Source = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - type Target = relay_bridge_hub_kusama_client::BridgeHubKusama; -} - -impl MessagesCliBridge for BridgeHubPolkadotToBridgeHubKusamaCliBridge { - type MessagesLane = - crate::bridges::kusama_polkadot::bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotMessagesToBridgeHubKusamaMessageLane; -} diff --git a/relays/bin-substrate/src/bridges/mod.rs b/relays/bin-substrate/src/bridges/mod.rs deleted file mode 100644 index cfe59c87567da..0000000000000 --- a/relays/bin-substrate/src/bridges/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 . - -//! Declaration of all bridges that the relay is able to serve. - -pub mod kusama_polkadot; -pub mod polkadot_bulletin; -pub mod rococo_bulletin; -pub mod rococo_westend; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs deleted file mode 100644 index 8114d23296f0c..0000000000000 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/bridge_hub_polkadot_messages_to_polkadot_bulletin.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubPolkadot-to-PolkadotBulletin messages sync entrypoint. - -use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use relay_polkadot_bulletin_client::PolkadotBulletin; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -/// BridgeHubPolkadot-to-PolkadotBulletin messages bridge. -pub struct BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge { - type Source = BridgeHubPolkadot; - type Target = PolkadotBulletin; -} - -impl MessagesCliBridge for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge { - type MessagesLane = BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane, - BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, - relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane, - BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder, - // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinMessages - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, - relay_bridge_hub_polkadot_client::BridgePolkadotBulletinMessagesCall::receive_messages_delivery_proof -); - -/// BridgeHubPolkadot-to-PolkadotBulletin messages lane. -#[derive(Clone, Debug)] -pub struct BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane; - -impl SubstrateMessageLane for BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane { - type SourceChain = BridgeHubPolkadot; - type TargetChain = PolkadotBulletin; - - type ReceiveMessagesProofCallBuilder = - BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubPolkadotMessagesToPolkadotBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = (); -} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs deleted file mode 100644 index d7c740f601abc..0000000000000 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Polkadot Bulletin Chain and Polkadot Bridge Hub. - -pub mod bridge_hub_polkadot_messages_to_polkadot_bulletin; -pub mod polkadot_bulletin_headers_to_bridge_hub_polkadot; -pub mod polkadot_bulletin_messages_to_bridge_hub_polkadot; -pub mod polkadot_headers_to_polkadot_bulletin; -pub mod polkadot_parachains_to_polkadot_bulletin; diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs deleted file mode 100644 index eb63785d3bb39..0000000000000 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_headers_to_bridge_hub_polkadot.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2022 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 . - -//! PolkadotBulletin-to-BridgeHubPolkadot headers sync entrypoint. - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; - -/// Description of `PolkadotBulletin` -> `PolkadotBridgeHub` finalized headers bridge. -#[derive(Clone, Debug)] -pub struct PolkadotBulletinFinalityToBridgeHubPolkadot; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - PolkadotBulletinFinalityToBridgeHubPolkadot, - SubmitFinalityProofCallBuilder, - // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinGrandpa - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa, - relay_bridge_hub_polkadot_client::BridgePolkadotBulletinGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - PolkadotBulletinFinalityToBridgeHubPolkadot, - ReportEquivocationCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::Grandpa, - relay_polkadot_bulletin_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { - type SourceChain = relay_polkadot_bulletin_client::PolkadotBulletin; - type TargetChain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for PolkadotBulletinFinalityToBridgeHubPolkadot { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `PolkadotBulletin` to BridgeHub `Polkadot` bridge definition. -pub struct PolkadotBulletinToBridgeHubPolkadotCliBridge {} - -impl CliBridgeBase for PolkadotBulletinToBridgeHubPolkadotCliBridge { - type Source = relay_polkadot_bulletin_client::PolkadotBulletin; - type Target = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -} - -impl RelayToRelayHeadersCliBridge for PolkadotBulletinToBridgeHubPolkadotCliBridge { - type Finality = PolkadotBulletinFinalityToBridgeHubPolkadot; -} - -impl RelayToRelayEquivocationDetectionCliBridge for PolkadotBulletinToBridgeHubPolkadotCliBridge { - type Equivocation = PolkadotBulletinFinalityToBridgeHubPolkadot; -} - -impl MessagesCliBridge for PolkadotBulletinToBridgeHubPolkadotCliBridge { - type MessagesLane = crate::bridges::polkadot_bulletin::polkadot_bulletin_messages_to_bridge_hub_polkadot::PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane; -} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs deleted file mode 100644 index 1c04f87881016..0000000000000 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_bulletin_messages_to_bridge_hub_polkadot.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2022 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 . - -//! PolkadotBulletin-to-BridgeHubPolkadot messages sync entrypoint. - -use relay_bridge_hub_polkadot_client::BridgeHubPolkadot; -use relay_polkadot_bulletin_client::PolkadotBulletin; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -/// PolkadotBulletin-to-BridgeHubPolkadot messages bridge. -pub struct PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} - -impl CliBridgeBase for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge { - type Source = PolkadotBulletin; - type Target = BridgeHubPolkadot; -} - -impl MessagesCliBridge for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge { - type MessagesLane = PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane, - PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder, - // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinMessages - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaMessages, - relay_bridge_hub_polkadot_client::BridgePolkadotBulletinMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane, - PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, - relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_delivery_proof -); - -/// PolkadotBulletin-to-BridgeHubPolkadot messages lane. -#[derive(Clone, Debug)] -pub struct PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane; - -impl SubstrateMessageLane for PolkadotBulletinMessagesToBridgeHubPolkadotMessageLane { - type SourceChain = PolkadotBulletin; - type TargetChain = BridgeHubPolkadot; - - type ReceiveMessagesProofCallBuilder = - PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - PolkadotBulletinMessagesToBridgeHubPolkadotMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs deleted file mode 100644 index 7996d1613c8dd..0000000000000 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_headers_to_polkadot_bulletin.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Polkadot-to-PolkadotBulletin headers sync entrypoint. - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -/// Description of Polkadot -> `PolkadotBulletin` finalized headers bridge. -#[derive(Clone, Debug)] -pub struct PolkadotFinalityToPolkadotBulletin; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - PolkadotFinalityToPolkadotBulletin, - SubmitFinalityProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotGrandpa, - relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - PolkadotFinalityToPolkadotBulletin, - ReportEquivocationCallBuilder, - relay_polkadot_client::RuntimeCall::Grandpa, - relay_polkadot_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for PolkadotFinalityToPolkadotBulletin { - type SourceChain = relay_polkadot_client::Polkadot; - type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for PolkadotFinalityToPolkadotBulletin { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for PolkadotFinalityToPolkadotBulletin { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Polkadot` to BridgeHub `PolkadotBulletin` bridge definition. -pub struct PolkadotToPolkadotBulletinCliBridge {} - -impl CliBridgeBase for PolkadotToPolkadotBulletinCliBridge { - type Source = relay_polkadot_client::Polkadot; - type Target = relay_polkadot_bulletin_client::PolkadotBulletin; -} - -impl RelayToRelayHeadersCliBridge for PolkadotToPolkadotBulletinCliBridge { - type Finality = PolkadotFinalityToPolkadotBulletin; -} - -impl RelayToRelayEquivocationDetectionCliBridge for PolkadotToPolkadotBulletinCliBridge { - type Equivocation = PolkadotFinalityToPolkadotBulletin; -} diff --git a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs b/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs deleted file mode 100644 index 0bfce11ba710e..0000000000000 --- a/relays/bin-substrate/src/bridges/polkadot_bulletin/polkadot_parachains_to_polkadot_bulletin.rs +++ /dev/null @@ -1,94 +0,0 @@ -// 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 . - -//! Polkadot-to-PolkadotBulletin parachains sync entrypoint. - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, -}; - -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use bp_runtime::Chain; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::{ - messages_lane::MessagesRelayLimits, - parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, -}; - -/// Polkadot-to-PolkadotBulletin parachain sync description. -#[derive(Clone, Debug)] -pub struct PolkadotToPolkadotBulletin; - -impl SubstrateParachainsPipeline for PolkadotToPolkadotBulletin { - type SourceParachain = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - type SourceRelayChain = relay_polkadot_client::Polkadot; - type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; - - type SubmitParachainHeadsCallBuilder = PolkadotToPolkadotBulletinCallBuilder; -} - -pub struct PolkadotToPolkadotBulletinCallBuilder; -impl SubmitParachainHeadsCallBuilder - for PolkadotToPolkadotBulletinCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotParachains( - relay_polkadot_bulletin_client::BridgePolkadotParachainsCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// Polkadot-to-PolkadotBulletin parachain sync description for the CLI. -pub struct PolkadotToPolkadotBulletinCliBridge {} - -impl ParachainToRelayHeadersCliBridge for PolkadotToPolkadotBulletinCliBridge { - type SourceRelay = relay_polkadot_client::Polkadot; - type ParachainFinality = PolkadotToPolkadotBulletin; - type RelayFinality = - crate::bridges::polkadot_bulletin::polkadot_headers_to_polkadot_bulletin::PolkadotFinalityToPolkadotBulletin; -} - -impl CliBridgeBase for PolkadotToPolkadotBulletinCliBridge { - type Source = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - type Target = relay_polkadot_bulletin_client::PolkadotBulletin; -} - -impl MessagesCliBridge for PolkadotToPolkadotBulletinCliBridge { - type MessagesLane = - crate::bridges::polkadot_bulletin::bridge_hub_polkadot_messages_to_polkadot_bulletin::BridgeHubPolkadotMessagesToPolkadotBulletinMessageLane; - - fn maybe_messages_limits() -> Option { - // Polkadot Bulletin chain is missing the `TransactionPayment` runtime API (as well as the - // transaction payment pallet itself), so we can't estimate limits using runtime calls. - // Let's do it here. - // - // Folloiung constants are just safe **underestimations**. Normally, we are able to deliver - // and dispatch thousands of messages in the same transaction. - Some(MessagesRelayLimits { - max_messages_in_single_batch: 128, - max_messages_weight_in_single_batch: - bp_polkadot_bulletin::PolkadotBulletin::max_extrinsic_weight() / 20, - }) - } -} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs deleted file mode 100644 index b8e95556bff11..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/bridge_hub_rococo_messages_to_rococo_bulletin.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubRococo-to-RococoBulletin messages sync entrypoint. - -use super::BridgeHubRococoAsBridgeHubPolkadot; -use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -/// BridgeHubRococo-to-RococoBulletin messages bridge. -pub struct BridgeHubRococoToRococoBulletinMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubRococoToRococoBulletinMessagesCliBridge { - type Source = BridgeHubRococoAsBridgeHubPolkadot; - type Target = RococoBulletin; -} - -impl MessagesCliBridge for BridgeHubRococoToRococoBulletinMessagesCliBridge { - type MessagesLane = BridgeHubRococoMessagesToRococoBulletinMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubRococoMessagesToRococoBulletinMessageLane, - BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, - relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubRococoMessagesToRococoBulletinMessageLane, - BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinMessages, - relay_bridge_hub_rococo_client::BridgeBulletinMessagesCall::receive_messages_delivery_proof -); - -/// BridgeHubRococo-to-RococoBulletin messages lane. -#[derive(Clone, Debug)] -pub struct BridgeHubRococoMessagesToRococoBulletinMessageLane; - -impl SubstrateMessageLane for BridgeHubRococoMessagesToRococoBulletinMessageLane { - type SourceChain = BridgeHubRococoAsBridgeHubPolkadot; - type TargetChain = RococoBulletin; - - type ReceiveMessagesProofCallBuilder = - BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubRococoMessagesToRococoBulletinMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = (); -} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs deleted file mode 100644 index 738fea8c5281e..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/mod.rs +++ /dev/null @@ -1,237 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Rococo Bulletin Chain and Rococo Bridge Hub. - -use bp_messages::MessageNonce; -use bp_runtime::{ - AccountIdOf, BalanceOf, BlockNumberOf, ChainId, HashOf, HasherOf, HeaderOf, NonceOf, - SignatureOf, -}; -use frame_support::pallet_prelude::Weight; -use relay_substrate_client::{ - ChainWithRuntimeVersion, Error as SubstrateError, SignParam, SimpleRuntimeVersion, - UnsignedTransaction, -}; -use sp_core::storage::StorageKey; -use std::time::Duration; - -pub mod bridge_hub_rococo_messages_to_rococo_bulletin; -pub mod rococo_bulletin_headers_to_bridge_hub_rococo; -pub mod rococo_bulletin_messages_to_bridge_hub_rococo; -pub mod rococo_headers_to_rococo_bulletin; -pub mod rococo_parachains_to_rococo_bulletin; - -/// Base `Chain` implementation of Rococo, pretending to be Polkadot. -pub struct RococoBaseAsPolkadot; - -impl bp_runtime::Chain for RococoBaseAsPolkadot { - const ID: ChainId = relay_rococo_client::Rococo::ID; - - type BlockNumber = BlockNumberOf; - type Hash = HashOf; - type Hasher = HasherOf; - type Header = HeaderOf; - - type AccountId = AccountIdOf; - type Balance = BalanceOf; - type Nonce = NonceOf; - type Signature = SignatureOf; - - fn max_extrinsic_size() -> u32 { - bp_rococo::Rococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_rococo::Rococo::max_extrinsic_weight() - } -} - -impl bp_header_chain::ChainWithGrandpa for RococoBaseAsPolkadot { - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = - bp_polkadot::Polkadot::WITH_CHAIN_GRANDPA_PALLET_NAME; - const MAX_AUTHORITIES_COUNT: u32 = bp_rococo::Rococo::MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - bp_rococo::Rococo::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; - const MAX_MANDATORY_HEADER_SIZE: u32 = bp_rococo::Rococo::MAX_MANDATORY_HEADER_SIZE; - const AVERAGE_HEADER_SIZE: u32 = bp_rococo::Rococo::AVERAGE_HEADER_SIZE; -} - -/// Relay `Chain` implementation of Rococo, pretending to be Polkadot. -#[derive(Debug, Clone, Copy)] -pub struct RococoAsPolkadot; - -impl bp_runtime::UnderlyingChainProvider for RococoAsPolkadot { - type Chain = RococoBaseAsPolkadot; -} - -impl relay_substrate_client::Chain for RococoAsPolkadot { - const NAME: &'static str = relay_rococo_client::Rococo::NAME; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - relay_polkadot_client::Polkadot::BEST_FINALIZED_HEADER_ID_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = relay_rococo_client::Rococo::AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = ::SignedBlock; - type Call = ::Call; -} - -impl relay_substrate_client::ChainWithGrandpa for RococoAsPolkadot { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - relay_polkadot_client::Polkadot::SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = - ::KeyOwnerProof; -} - -impl relay_substrate_client::ChainWithBalances for RococoAsPolkadot { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - relay_rococo_client::Rococo::account_info_storage_key(account_id) - } -} - -impl relay_substrate_client::RelayChain for RococoAsPolkadot { - const PARAS_PALLET_NAME: &'static str = relay_rococo_client::Rococo::PARAS_PALLET_NAME; -} - -impl relay_substrate_client::ChainWithTransactions for RococoAsPolkadot { - type AccountKeyPair = ::AccountKeyPair; - type SignedTransaction = ::SignedTransaction; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - relay_rococo_client::Rococo::sign_transaction( - SignParam { - spec_version: param.spec_version, - transaction_version: param.transaction_version, - genesis_hash: param.genesis_hash, - signer: param.signer, - }, - unsigned.switch_chain(), - ) - } -} - -impl ChainWithRuntimeVersion for RococoAsPolkadot { - const RUNTIME_VERSION: Option = None; -} - -/// Base `Chain` implementation of Rococo Bridge Hub, pretending to be a Polkadot Bridge Hub. -pub struct BaseBridgeHubRococoAsBridgeHubPolkadot; - -impl bp_runtime::Chain for BaseBridgeHubRococoAsBridgeHubPolkadot { - const ID: ChainId = relay_bridge_hub_rococo_client::BridgeHubRococo::ID; - - type BlockNumber = BlockNumberOf; - type Hash = HashOf; - type Hasher = HasherOf; - type Header = HeaderOf; - - type AccountId = AccountIdOf; - type Balance = BalanceOf; - type Nonce = NonceOf; - type Signature = SignatureOf; - - fn max_extrinsic_size() -> u32 { - bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_size() - } - - fn max_extrinsic_weight() -> Weight { - bp_bridge_hub_rococo::BridgeHubRococo::max_extrinsic_weight() - } -} - -impl bp_runtime::Parachain for BaseBridgeHubRococoAsBridgeHubPolkadot { - const PARACHAIN_ID: u32 = bp_bridge_hub_rococo::BridgeHubRococo::PARACHAIN_ID; -} - -impl bp_messages::ChainWithMessages for BaseBridgeHubRococoAsBridgeHubPolkadot { - const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = - relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_MESSAGES_PALLET_NAME; - - const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = - relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; - const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = - relay_bridge_hub_rococo_client::BridgeHubRococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; -} - -/// Relay `Chain` implementation of Rococo Bridge Hub, pretending to be a Polkadot Bridge Hub. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct BridgeHubRococoAsBridgeHubPolkadot; - -impl bp_runtime::UnderlyingChainProvider for BridgeHubRococoAsBridgeHubPolkadot { - type Chain = BaseBridgeHubRococoAsBridgeHubPolkadot; -} - -impl relay_substrate_client::Chain for BridgeHubRococoAsBridgeHubPolkadot { - const NAME: &'static str = relay_bridge_hub_rococo_client::BridgeHubRococo::NAME; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - relay_bridge_hub_polkadot_client::BridgeHubPolkadot::BEST_FINALIZED_HEADER_ID_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = - relay_bridge_hub_rococo_client::BridgeHubRococo::AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = ::SignedBlock; - type Call = - ::Call; -} - -impl relay_substrate_client::ChainWithBalances for BridgeHubRococoAsBridgeHubPolkadot { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - relay_bridge_hub_rococo_client::BridgeHubRococo::account_info_storage_key(account_id) - } -} - -impl relay_substrate_client::ChainWithUtilityPallet for BridgeHubRococoAsBridgeHubPolkadot { - type UtilityPallet = relay_substrate_client::MockedRuntimeUtilityPallet< - relay_bridge_hub_rococo_client::RuntimeCall, - >; -} - -impl relay_substrate_client::ChainWithTransactions for BridgeHubRococoAsBridgeHubPolkadot { - type AccountKeyPair = ::AccountKeyPair; - type SignedTransaction = ::SignedTransaction; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - relay_bridge_hub_rococo_client::BridgeHubRococo::sign_transaction( - SignParam { - spec_version: param.spec_version, - transaction_version: param.transaction_version, - genesis_hash: param.genesis_hash, - signer: param.signer, - }, - unsigned.switch_chain(), - ) - } -} - -impl relay_substrate_client::ChainWithMessages for BridgeHubRococoAsBridgeHubPolkadot { - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = - relay_bridge_hub_polkadot_client::BridgeHubPolkadot::WITH_CHAIN_RELAYERS_PALLET_NAME; - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - relay_bridge_hub_polkadot_client::BridgeHubPolkadot::TO_CHAIN_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - relay_bridge_hub_polkadot_client::BridgeHubPolkadot::FROM_CHAIN_MESSAGE_DETAILS_METHOD; -} - -impl ChainWithRuntimeVersion for BridgeHubRococoAsBridgeHubPolkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_003_000, transaction_version: 3 }); -} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs deleted file mode 100644 index 0d54fd21018d1..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_headers_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2022 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 . - -//! RococoBulletin-to-BridgeHubRococo headers sync entrypoint. - -use super::BridgeHubRococoAsBridgeHubPolkadot; - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, MessagesCliBridge, RelayToRelayEquivocationDetectionCliBridge, - RelayToRelayHeadersCliBridge, -}; - -/// Description of `RococoBulletin` -> `RococoBridgeHub` finalized headers bridge. -#[derive(Clone, Debug)] -pub struct RococoBulletinFinalityToBridgeHubRococo; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - RococoBulletinFinalityToBridgeHubRococo, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinGrandpa, - relay_bridge_hub_rococo_client::BridgeBulletinGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - RococoBulletinFinalityToBridgeHubRococo, - ReportEquivocationCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::Grandpa, - relay_polkadot_bulletin_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for RococoBulletinFinalityToBridgeHubRococo { - type SourceChain = relay_polkadot_bulletin_client::PolkadotBulletin; - type TargetChain = BridgeHubRococoAsBridgeHubPolkadot; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for RococoBulletinFinalityToBridgeHubRococo { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for RococoBulletinFinalityToBridgeHubRococo { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `RococoBulletin` to BridgeHub `Rococo` bridge definition. -pub struct RococoBulletinToBridgeHubRococoCliBridge {} - -impl CliBridgeBase for RococoBulletinToBridgeHubRococoCliBridge { - type Source = relay_polkadot_bulletin_client::PolkadotBulletin; - type Target = BridgeHubRococoAsBridgeHubPolkadot; -} - -impl RelayToRelayHeadersCliBridge for RococoBulletinToBridgeHubRococoCliBridge { - type Finality = RococoBulletinFinalityToBridgeHubRococo; -} - -impl RelayToRelayEquivocationDetectionCliBridge for RococoBulletinToBridgeHubRococoCliBridge { - type Equivocation = RococoBulletinFinalityToBridgeHubRococo; -} - -impl MessagesCliBridge for RococoBulletinToBridgeHubRococoCliBridge { - type MessagesLane = crate::bridges::rococo_bulletin::rococo_bulletin_messages_to_bridge_hub_rococo::RococoBulletinMessagesToBridgeHubRococoMessageLane; -} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs deleted file mode 100644 index d192ec0381e58..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_bulletin_messages_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2022 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 . - -//! RococoBulletin-to-BridgeHubRococo messages sync entrypoint. - -use super::BridgeHubRococoAsBridgeHubPolkadot; -use relay_polkadot_bulletin_client::PolkadotBulletin as RococoBulletin; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -/// RococoBulletin-to-BridgeHubRococo messages bridge. -pub struct RococoBulletinToBridgeHubRococoMessagesCliBridge {} - -impl CliBridgeBase for RococoBulletinToBridgeHubRococoMessagesCliBridge { - type Source = RococoBulletin; - type Target = BridgeHubRococoAsBridgeHubPolkadot; -} - -impl MessagesCliBridge for RococoBulletinToBridgeHubRococoMessagesCliBridge { - type MessagesLane = RococoBulletinMessagesToBridgeHubRococoMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - RococoBulletinMessagesToBridgeHubRococoMessageLane, - RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinMessages, - relay_bridge_hub_rococo_client::BridgeBulletinMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - RococoBulletinMessagesToBridgeHubRococoMessageLane, - RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotMessages, - relay_polkadot_bulletin_client::BridgePolkadotMessagesCall::receive_messages_delivery_proof -); - -/// RococoBulletin-to-BridgeHubRococo messages lane. -#[derive(Clone, Debug)] -pub struct RococoBulletinMessagesToBridgeHubRococoMessageLane; - -impl SubstrateMessageLane for RococoBulletinMessagesToBridgeHubRococoMessageLane { - type SourceChain = RococoBulletin; - type TargetChain = BridgeHubRococoAsBridgeHubPolkadot; - - type ReceiveMessagesProofCallBuilder = - RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - RococoBulletinMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs deleted file mode 100644 index 45c890267ffba..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_headers_to_rococo_bulletin.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2022 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 . - -//! Rococo-to-RococoBulletin headers sync entrypoint. - -use super::RococoAsPolkadot; - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -/// Description of Rococo -> `RococoBulletin` finalized headers bridge. -#[derive(Clone, Debug)] -pub struct RococoFinalityToRococoBulletin; - -substrate_relay_helper::generate_submit_finality_proof_call_builder!( - RococoFinalityToRococoBulletin, - SubmitFinalityProofCallBuilder, - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotGrandpa, - relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall::submit_finality_proof -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - RococoFinalityToRococoBulletin, - ReportEquivocationCallBuilder, - relay_rococo_client::RuntimeCall::Grandpa, - relay_rococo_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for RococoFinalityToRococoBulletin { - type SourceChain = RococoAsPolkadot; - type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for RococoFinalityToRococoBulletin { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for RococoFinalityToRococoBulletin { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Rococo` to BridgeHub `RococoBulletin` bridge definition. -pub struct RococoToRococoBulletinCliBridge {} - -impl CliBridgeBase for RococoToRococoBulletinCliBridge { - type Source = RococoAsPolkadot; - type Target = relay_polkadot_bulletin_client::PolkadotBulletin; -} - -impl RelayToRelayHeadersCliBridge for RococoToRococoBulletinCliBridge { - type Finality = RococoFinalityToRococoBulletin; -} - -impl RelayToRelayEquivocationDetectionCliBridge for RococoToRococoBulletinCliBridge { - type Equivocation = RococoFinalityToRococoBulletin; -} diff --git a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs b/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs deleted file mode 100644 index d14a133d23c43..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_bulletin/rococo_parachains_to_rococo_bulletin.rs +++ /dev/null @@ -1,91 +0,0 @@ -// 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 . - -//! Rococo-to-RococoBulletin parachains sync entrypoint. - -use super::{BridgeHubRococoAsBridgeHubPolkadot, RococoAsPolkadot}; - -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use bp_runtime::Chain; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - messages_lane::MessagesRelayLimits, - parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, -}; - -/// Rococo-to-RococoBulletin parachain sync description. -#[derive(Clone, Debug)] -pub struct RococoToRococoBulletin; - -impl SubstrateParachainsPipeline for RococoToRococoBulletin { - type SourceParachain = BridgeHubRococoAsBridgeHubPolkadot; - type SourceRelayChain = RococoAsPolkadot; - type TargetChain = relay_polkadot_bulletin_client::PolkadotBulletin; - - type SubmitParachainHeadsCallBuilder = RococoToRococoBulletinCallBuilder; -} - -pub struct RococoToRococoBulletinCallBuilder; -impl SubmitParachainHeadsCallBuilder for RococoToRococoBulletinCallBuilder { - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_polkadot_bulletin_client::RuntimeCall::BridgePolkadotParachains( - relay_polkadot_bulletin_client::BridgePolkadotParachainsCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// Rococo-to-RococoBulletin parachain sync description for the CLI. -pub struct RococoToRococoBulletinCliBridge {} - -impl ParachainToRelayHeadersCliBridge for RococoToRococoBulletinCliBridge { - type SourceRelay = RococoAsPolkadot; - type ParachainFinality = RococoToRococoBulletin; - type RelayFinality = - crate::bridges::rococo_bulletin::rococo_headers_to_rococo_bulletin::RococoFinalityToRococoBulletin; -} - -impl CliBridgeBase for RococoToRococoBulletinCliBridge { - type Source = BridgeHubRococoAsBridgeHubPolkadot; - type Target = relay_polkadot_bulletin_client::PolkadotBulletin; -} - -impl MessagesCliBridge for RococoToRococoBulletinCliBridge { - type MessagesLane = - crate::bridges::rococo_bulletin::bridge_hub_rococo_messages_to_rococo_bulletin::BridgeHubRococoMessagesToRococoBulletinMessageLane; - - fn maybe_messages_limits() -> Option { - // Rococo Bulletin chain is missing the `TransactionPayment` runtime API (as well as the - // transaction payment pallet itself), so we can't estimate limits using runtime calls. - // Let's do it here. - // - // Folloiung constants are just safe **underestimations**. Normally, we are able to deliver - // and dispatch thousands of messages in the same transaction. - Some(MessagesRelayLimits { - max_messages_in_single_batch: 128, - max_messages_weight_in_single_batch: - bp_polkadot_bulletin::PolkadotBulletin::max_extrinsic_weight() / 20, - }) - } -} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs deleted file mode 100644 index ec6b07d982afe..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_rococo_messages_to_bridge_hub_westend.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubRococo-to-BridgeHubWestend messages sync entrypoint. - -use relay_bridge_hub_rococo_client::BridgeHubRococo; -use relay_bridge_hub_westend_client::BridgeHubWestend; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -pub struct BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubRococoToBridgeHubWestendMessagesCliBridge { - type Source = BridgeHubRococo; - type Target = BridgeHubWestend; -} - -impl MessagesCliBridge for BridgeHubRococoToBridgeHubWestendMessagesCliBridge { - type MessagesLane = BridgeHubRococoMessagesToBridgeHubWestendMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubRococoMessagesToBridgeHubWestendMessageLane, - BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoMessages, - relay_bridge_hub_westend_client::BridgeMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubRococoMessagesToBridgeHubWestendMessageLane, - BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendMessages, - relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_delivery_proof -); - -/// Description of BridgeHubRococo -> BridgeHubWestendWestend messages bridge. -#[derive(Clone, Debug)] -pub struct BridgeHubRococoMessagesToBridgeHubWestendMessageLane; - -impl SubstrateMessageLane for BridgeHubRococoMessagesToBridgeHubWestendMessageLane { - type SourceChain = BridgeHubRococo; - type TargetChain = BridgeHubWestend; - - type ReceiveMessagesProofCallBuilder = - BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubRococoMessagesToBridgeHubWestendMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs deleted file mode 100644 index 4e978cd8356cf..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/bridge_hub_westend_messages_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2022 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 . - -//! BridgeHubWestend-to-BridgeHubRococo messages sync entrypoint. - -use relay_bridge_hub_rococo_client::BridgeHubRococo; -use relay_bridge_hub_westend_client::BridgeHubWestend; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge}, - messages_lane::SubstrateMessageLane, - UtilityPalletBatchCallBuilder, -}; - -pub struct BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} - -impl CliBridgeBase for BridgeHubWestendToBridgeHubRococoMessagesCliBridge { - type Source = BridgeHubWestend; - type Target = BridgeHubRococo; -} - -impl MessagesCliBridge for BridgeHubWestendToBridgeHubRococoMessagesCliBridge { - type MessagesLane = BridgeHubWestendMessagesToBridgeHubRococoMessageLane; -} - -substrate_relay_helper::generate_receive_message_proof_call_builder!( - BridgeHubWestendMessagesToBridgeHubRococoMessageLane, - BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendMessages, - relay_bridge_hub_rococo_client::BridgeMessagesCall::receive_messages_proof -); - -substrate_relay_helper::generate_receive_message_delivery_proof_call_builder!( - BridgeHubWestendMessagesToBridgeHubRococoMessageLane, - BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder, - relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoMessages, - relay_bridge_hub_westend_client::BridgeMessagesCall::receive_messages_delivery_proof -); - -/// Description of BridgeHubWestend -> BridgeHubRococo messages bridge. -#[derive(Clone, Debug)] -pub struct BridgeHubWestendMessagesToBridgeHubRococoMessageLane; - -impl SubstrateMessageLane for BridgeHubWestendMessagesToBridgeHubRococoMessageLane { - type SourceChain = BridgeHubWestend; - type TargetChain = BridgeHubRococo; - - type ReceiveMessagesProofCallBuilder = - BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesProofCallBuilder; - type ReceiveMessagesDeliveryProofCallBuilder = - BridgeHubWestendMessagesToBridgeHubRococoMessageLaneReceiveMessagesDeliveryProofCallBuilder; - - type SourceBatchCallBuilder = UtilityPalletBatchCallBuilder; - type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; -} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/mod.rs b/relays/bin-substrate/src/bridges/rococo_westend/mod.rs deleted file mode 100644 index 965d3e0561f99..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -// 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 . - -//! Declaration of all bridges between Rococo Bridge Hub and Westend Bridge Hub. - -pub mod bridge_hub_rococo_messages_to_bridge_hub_westend; -pub mod bridge_hub_westend_messages_to_bridge_hub_rococo; -pub mod rococo_headers_to_bridge_hub_westend; -pub mod rococo_parachains_to_bridge_hub_westend; -pub mod westend_headers_to_bridge_hub_rococo; -pub mod westend_parachains_to_bridge_hub_rococo; diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs deleted file mode 100644 index bf30a87bf2d48..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_headers_to_bridge_hub_westend.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Rococo-to-Westend bridge hubs headers sync entrypoint. - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -/// Description of Rococo -> Westend finalized headers bridge. -#[derive(Clone, Debug)] -pub struct RococoFinalityToBridgeHubWestend; - -substrate_relay_helper::generate_submit_finality_proof_ex_call_builder!( - RococoFinalityToBridgeHubWestend, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoGrandpa, - relay_bridge_hub_westend_client::BridgeGrandpaCall::submit_finality_proof_ex -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - RococoFinalityToBridgeHubWestend, - ReportEquivocationCallBuilder, - relay_rococo_client::RuntimeCall::Grandpa, - relay_rococo_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for RococoFinalityToBridgeHubWestend { - type SourceChain = relay_rococo_client::Rococo; - type TargetChain = relay_bridge_hub_westend_client::BridgeHubWestend; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for RococoFinalityToBridgeHubWestend { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for RococoFinalityToBridgeHubWestend { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Rococo` to BridgeHub `Westend` bridge definition. -pub struct RococoToBridgeHubWestendCliBridge {} - -impl CliBridgeBase for RococoToBridgeHubWestendCliBridge { - type Source = relay_rococo_client::Rococo; - type Target = relay_bridge_hub_westend_client::BridgeHubWestend; -} - -impl RelayToRelayHeadersCliBridge for RococoToBridgeHubWestendCliBridge { - type Finality = RococoFinalityToBridgeHubWestend; -} - -impl RelayToRelayEquivocationDetectionCliBridge for RococoToBridgeHubWestendCliBridge { - type Equivocation = RococoFinalityToBridgeHubWestend; -} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs b/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs deleted file mode 100644 index 31de8c4d1d1c5..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/rococo_parachains_to_bridge_hub_westend.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Westend-to-Rococo parachains sync entrypoint. - -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, -}; - -/// BridgeHub-to-BridgeHub parachain sync description. -#[derive(Clone, Debug)] -pub struct BridgeHubRococoToBridgeHubWestend; - -impl SubstrateParachainsPipeline for BridgeHubRococoToBridgeHubWestend { - type SourceParachain = relay_bridge_hub_rococo_client::BridgeHubRococo; - type SourceRelayChain = relay_rococo_client::Rococo; - type TargetChain = relay_bridge_hub_westend_client::BridgeHubWestend; - - type SubmitParachainHeadsCallBuilder = BridgeHubRococoToBridgeHubWestendCallBuilder; -} - -pub struct BridgeHubRococoToBridgeHubWestendCallBuilder; -impl SubmitParachainHeadsCallBuilder - for BridgeHubRococoToBridgeHubWestendCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoParachains( - relay_bridge_hub_westend_client::BridgeParachainCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. -pub struct BridgeHubRococoToBridgeHubWestendCliBridge {} - -impl ParachainToRelayHeadersCliBridge for BridgeHubRococoToBridgeHubWestendCliBridge { - type SourceRelay = relay_rococo_client::Rococo; - type ParachainFinality = BridgeHubRococoToBridgeHubWestend; - type RelayFinality = - crate::bridges::rococo_westend::rococo_headers_to_bridge_hub_westend::RococoFinalityToBridgeHubWestend; -} - -impl CliBridgeBase for BridgeHubRococoToBridgeHubWestendCliBridge { - type Source = relay_bridge_hub_rococo_client::BridgeHubRococo; - type Target = relay_bridge_hub_westend_client::BridgeHubWestend; -} - -impl MessagesCliBridge for BridgeHubRococoToBridgeHubWestendCliBridge { - type MessagesLane = - crate::bridges::rococo_westend::bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoMessagesToBridgeHubWestendMessageLane; -} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs deleted file mode 100644 index 4a1419f06dcdf..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_headers_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2022 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 . - -//! Westend-to-Rococo bridge hubs headers sync entrypoint. - -use async_trait::async_trait; -use substrate_relay_helper::{ - equivocation::SubstrateEquivocationDetectionPipeline, - finality::SubstrateFinalitySyncPipeline, - finality_base::{engine::Grandpa as GrandpaFinalityEngine, SubstrateFinalityPipeline}, -}; - -use substrate_relay_helper::cli::bridge::{ - CliBridgeBase, RelayToRelayEquivocationDetectionCliBridge, RelayToRelayHeadersCliBridge, -}; - -/// Description of Westend -> Rococo finalized headers bridge. -#[derive(Clone, Debug)] -pub struct WestendFinalityToBridgeHubRococo; - -substrate_relay_helper::generate_submit_finality_proof_ex_call_builder!( - WestendFinalityToBridgeHubRococo, - SubmitFinalityProofCallBuilder, - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendGrandpa, - relay_bridge_hub_rococo_client::BridgeGrandpaCall::submit_finality_proof_ex -); - -substrate_relay_helper::generate_report_equivocation_call_builder!( - WestendFinalityToBridgeHubRococo, - ReportEquivocationCallBuilder, - relay_westend_client::RuntimeCall::Grandpa, - relay_westend_client::GrandpaCall::report_equivocation -); - -#[async_trait] -impl SubstrateFinalityPipeline for WestendFinalityToBridgeHubRococo { - type SourceChain = relay_westend_client::Westend; - type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; - - type FinalityEngine = GrandpaFinalityEngine; -} - -#[async_trait] -impl SubstrateFinalitySyncPipeline for WestendFinalityToBridgeHubRococo { - type SubmitFinalityProofCallBuilder = SubmitFinalityProofCallBuilder; -} - -#[async_trait] -impl SubstrateEquivocationDetectionPipeline for WestendFinalityToBridgeHubRococo { - type ReportEquivocationCallBuilder = ReportEquivocationCallBuilder; -} - -/// `Westend` to BridgeHub `Rococo` bridge definition. -pub struct WestendToBridgeHubRococoCliBridge {} - -impl CliBridgeBase for WestendToBridgeHubRococoCliBridge { - type Source = relay_westend_client::Westend; - type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; -} - -impl RelayToRelayHeadersCliBridge for WestendToBridgeHubRococoCliBridge { - type Finality = WestendFinalityToBridgeHubRococo; -} - -impl RelayToRelayEquivocationDetectionCliBridge for WestendToBridgeHubRococoCliBridge { - type Equivocation = WestendFinalityToBridgeHubRococo; -} diff --git a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs b/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs deleted file mode 100644 index fc6f6532836fd..0000000000000 --- a/relays/bin-substrate/src/bridges/rococo_westend/westend_parachains_to_bridge_hub_rococo.rs +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -//! Rococo-to-Westend parachains sync entrypoint. - -use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; -use relay_substrate_client::{CallOf, HeaderIdOf}; -use substrate_relay_helper::{ - cli::bridge::{CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge}, - parachains::{SubmitParachainHeadsCallBuilder, SubstrateParachainsPipeline}, -}; - -/// BridgeHub-to-BridgeHub parachain sync description. -#[derive(Clone, Debug)] -pub struct BridgeHubWestendToBridgeHubRococo; - -impl SubstrateParachainsPipeline for BridgeHubWestendToBridgeHubRococo { - type SourceParachain = relay_bridge_hub_westend_client::BridgeHubWestend; - type SourceRelayChain = relay_westend_client::Westend; - type TargetChain = relay_bridge_hub_rococo_client::BridgeHubRococo; - - type SubmitParachainHeadsCallBuilder = BridgeHubWestendToBridgeHubRococoCallBuilder; -} - -pub struct BridgeHubWestendToBridgeHubRococoCallBuilder; -impl SubmitParachainHeadsCallBuilder - for BridgeHubWestendToBridgeHubRococoCallBuilder -{ - fn build_submit_parachain_heads_call( - at_relay_block: HeaderIdOf, - parachains: Vec<(ParaId, ParaHash)>, - parachain_heads_proof: ParaHeadsProof, - ) -> CallOf { - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendParachains( - relay_bridge_hub_rococo_client::BridgeParachainCall::submit_parachain_heads { - at_relay_block: (at_relay_block.0, at_relay_block.1), - parachains, - parachain_heads_proof, - }, - ) - } -} - -/// `BridgeHubParachain` to `BridgeHubParachain` bridge definition. -pub struct BridgeHubWestendToBridgeHubRococoCliBridge {} - -impl ParachainToRelayHeadersCliBridge for BridgeHubWestendToBridgeHubRococoCliBridge { - type SourceRelay = relay_westend_client::Westend; - type ParachainFinality = BridgeHubWestendToBridgeHubRococo; - type RelayFinality = - crate::bridges::rococo_westend::westend_headers_to_bridge_hub_rococo::WestendFinalityToBridgeHubRococo; -} - -impl CliBridgeBase for BridgeHubWestendToBridgeHubRococoCliBridge { - type Source = relay_bridge_hub_westend_client::BridgeHubWestend; - type Target = relay_bridge_hub_rococo_client::BridgeHubRococo; -} - -impl MessagesCliBridge for BridgeHubWestendToBridgeHubRococoCliBridge { - type MessagesLane = - crate::bridges::rococo_westend::bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendMessagesToBridgeHubRococoMessageLane; -} diff --git a/relays/bin-substrate/src/cli/chain_schema.rs b/relays/bin-substrate/src/cli/chain_schema.rs deleted file mode 100644 index 4422332a59324..0000000000000 --- a/relays/bin-substrate/src/cli/chain_schema.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2019-2022 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 . - -#[cfg(test)] -mod tests { - use sp_core::Pair; - use substrate_relay_helper::cli::chain_schema::TargetSigningParams; - - #[test] - fn reads_suri_from_file() { - const ALICE: &str = "//Alice"; - const BOB: &str = "//Bob"; - const ALICE_PASSWORD: &str = "alice_password"; - const BOB_PASSWORD: &str = "bob_password"; - - let alice: sp_core::sr25519::Pair = Pair::from_string(ALICE, Some(ALICE_PASSWORD)).unwrap(); - let bob: sp_core::sr25519::Pair = Pair::from_string(BOB, Some(BOB_PASSWORD)).unwrap(); - let bob_with_alice_password = - sp_core::sr25519::Pair::from_string(BOB, Some(ALICE_PASSWORD)).unwrap(); - - let temp_dir = tempfile::tempdir().unwrap(); - let mut suri_file_path = temp_dir.path().to_path_buf(); - let mut password_file_path = temp_dir.path().to_path_buf(); - suri_file_path.push("suri"); - password_file_path.push("password"); - std::fs::write(&suri_file_path, BOB.as_bytes()).unwrap(); - std::fs::write(&password_file_path, BOB_PASSWORD.as_bytes()).unwrap(); - - // when both seed and password are read from file - assert_eq!( - TargetSigningParams { - target_signer: Some(ALICE.into()), - target_signer_password: Some(ALICE_PASSWORD.into()), - - target_signer_file: None, - target_signer_password_file: None, - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(alice.public()), - ); - - // when both seed and password are read from file - assert_eq!( - TargetSigningParams { - target_signer: None, - target_signer_password: None, - - target_signer_file: Some(suri_file_path.clone()), - target_signer_password_file: Some(password_file_path.clone()), - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(bob.public()), - ); - - // when password are is overriden by cli option - assert_eq!( - TargetSigningParams { - target_signer: None, - target_signer_password: Some(ALICE_PASSWORD.into()), - - target_signer_file: Some(suri_file_path.clone()), - target_signer_password_file: Some(password_file_path.clone()), - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(bob_with_alice_password.public()), - ); - - // when both seed and password are overriden by cli options - assert_eq!( - TargetSigningParams { - target_signer: Some(ALICE.into()), - target_signer_password: Some(ALICE_PASSWORD.into()), - - target_signer_file: Some(suri_file_path), - target_signer_password_file: Some(password_file_path), - - target_transactions_mortality: None, - } - .to_keypair::() - .map(|p| p.public()) - .map_err(drop), - Ok(alice.public()), - ); - } -} diff --git a/relays/bin-substrate/src/cli/detect_equivocations.rs b/relays/bin-substrate/src/cli/detect_equivocations.rs deleted file mode 100644 index 7717b50153754..0000000000000 --- a/relays/bin-substrate/src/cli/detect_equivocations.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2019-2023 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 . - -use crate::bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - rococo_westend::{ - rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, - westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, - }, -}; - -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; - -use substrate_relay_helper::cli::detect_equivocations::{ - DetectEquivocationsParams, EquivocationsDetector, -}; - -/// Start equivocation detection loop. -#[derive(StructOpt)] -pub struct DetectEquivocations { - #[structopt(possible_values = DetectEquivocationsBridge::VARIANTS, case_insensitive = true)] - bridge: DetectEquivocationsBridge, - #[structopt(flatten)] - params: DetectEquivocationsParams, -} - -#[derive(Debug, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Equivocations detection bridge. -pub enum DetectEquivocationsBridge { - KusamaToBridgeHubPolkadot, - PolkadotToBridgeHubKusama, - RococoToBridgeHubWestend, - WestendToBridgeHubRococo, -} - -impl EquivocationsDetector for KusamaToBridgeHubPolkadotCliBridge {} -impl EquivocationsDetector for PolkadotToBridgeHubKusamaCliBridge {} -impl EquivocationsDetector for RococoToBridgeHubWestendCliBridge {} -impl EquivocationsDetector for WestendToBridgeHubRococoCliBridge {} - -impl DetectEquivocations { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - DetectEquivocationsBridge::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::start(self.params), - DetectEquivocationsBridge::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::start(self.params), - DetectEquivocationsBridge::RococoToBridgeHubWestend => - RococoToBridgeHubWestendCliBridge::start(self.params), - DetectEquivocationsBridge::WestendToBridgeHubRococo => - WestendToBridgeHubRococoCliBridge::start(self.params), - } - .await - } -} diff --git a/relays/bin-substrate/src/cli/init_bridge.rs b/relays/bin-substrate/src/cli/init_bridge.rs deleted file mode 100644 index 441487b35a966..0000000000000 --- a/relays/bin-substrate/src/cli/init_bridge.rs +++ /dev/null @@ -1,199 +0,0 @@ -// 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 . - -use crate::bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::{ - polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, - polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - }, - rococo_bulletin::{ - rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, - rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - }, - rococo_westend::{ - rococo_headers_to_bridge_hub_westend::RococoToBridgeHubWestendCliBridge, - westend_headers_to_bridge_hub_rococo::WestendToBridgeHubRococoCliBridge, - }, -}; -use relay_substrate_client::Chain; -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; -use substrate_relay_helper::{ - cli::init_bridge::{BridgeInitializer, InitBridgeParams}, - finality_base::engine::{Engine, Grandpa as GrandpaFinalityEngine}, -}; - -impl BridgeInitializer for RococoToBridgeHubWestendCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_westend_client::RuntimeCall::BridgeRococoGrandpa( - relay_bridge_hub_westend_client::BridgeGrandpaCall::initialize { init_data }, - ) - } -} - -impl BridgeInitializer for WestendToBridgeHubRococoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_rococo_client::RuntimeCall::BridgeWestendGrandpa( - relay_bridge_hub_rococo_client::BridgeGrandpaCall::initialize { init_data }, - ) - } -} - -impl BridgeInitializer for KusamaToBridgeHubPolkadotCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa( - relay_bridge_hub_polkadot_client::BridgeKusamaGrandpaCall::initialize { init_data }, - ) - } -} - -impl BridgeInitializer for PolkadotToBridgeHubKusamaCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_kusama_client::RuntimeCall::BridgePolkadotGrandpa( - relay_bridge_hub_kusama_client::BridgeGrandpaCall::initialize { init_data }, - ) - } -} - -impl BridgeInitializer for PolkadotToPolkadotBulletinCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - type RuntimeCall = relay_polkadot_bulletin_client::RuntimeCall; - type BridgePolkadotGrandpaCall = relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall; - type SudoCall = relay_polkadot_bulletin_client::SudoCall; - - let initialize_call = - RuntimeCall::BridgePolkadotGrandpa(BridgePolkadotGrandpaCall::initialize { init_data }); - - RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(initialize_call) }) - } -} - -impl BridgeInitializer for PolkadotBulletinToBridgeHubPolkadotCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - // TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - use BridgePolkadotBulletinGrandpa - relay_bridge_hub_polkadot_client::RuntimeCall::BridgeKusamaGrandpa( - relay_bridge_hub_polkadot_client::BridgePolkadotBulletinGrandpaCall::initialize { - init_data, - }, - ) - } -} - -impl BridgeInitializer for RococoToRococoBulletinCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - type RuntimeCall = relay_polkadot_bulletin_client::RuntimeCall; - type BridgePolkadotGrandpaCall = relay_polkadot_bulletin_client::BridgePolkadotGrandpaCall; - type SudoCall = relay_polkadot_bulletin_client::SudoCall; - - let initialize_call = - RuntimeCall::BridgePolkadotGrandpa(BridgePolkadotGrandpaCall::initialize { init_data }); - - RuntimeCall::Sudo(SudoCall::sudo { call: Box::new(initialize_call) }) - } -} - -impl BridgeInitializer for RococoBulletinToBridgeHubRococoCliBridge { - type Engine = GrandpaFinalityEngine; - - fn encode_init_bridge( - init_data: >::InitializationData, - ) -> ::Call { - relay_bridge_hub_rococo_client::RuntimeCall::BridgePolkadotBulletinGrandpa( - relay_bridge_hub_rococo_client::BridgeBulletinGrandpaCall::initialize { init_data }, - ) - } -} - -/// Initialize bridge pallet. -#[derive(StructOpt)] -pub struct InitBridge { - /// A bridge instance to initialize. - #[structopt(possible_values = InitBridgeName::VARIANTS, case_insensitive = true)] - bridge: InitBridgeName, - #[structopt(flatten)] - params: InitBridgeParams, -} - -#[derive(Debug, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Bridge to initialize. -pub enum InitBridgeName { - KusamaToBridgeHubPolkadot, - PolkadotToBridgeHubKusama, - PolkadotToPolkadotBulletin, - PolkadotBulletinToBridgeHubPolkadot, - RococoToRococoBulletin, - RococoBulletinToBridgeHubRococo, - RococoToBridgeHubWestend, - WestendToBridgeHubRococo, -} - -impl InitBridge { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - InitBridgeName::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::init_bridge(self.params), - InitBridgeName::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::init_bridge(self.params), - InitBridgeName::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::init_bridge(self.params), - InitBridgeName::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotCliBridge::init_bridge(self.params), - InitBridgeName::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::init_bridge(self.params), - InitBridgeName::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoCliBridge::init_bridge(self.params), - InitBridgeName::RococoToBridgeHubWestend => - RococoToBridgeHubWestendCliBridge::init_bridge(self.params), - InitBridgeName::WestendToBridgeHubRococo => - WestendToBridgeHubRococoCliBridge::init_bridge(self.params), - } - .await - } -} diff --git a/relays/bin-substrate/src/cli/mod.rs b/relays/bin-substrate/src/cli/mod.rs deleted file mode 100644 index 504058894c21f..0000000000000 --- a/relays/bin-substrate/src/cli/mod.rs +++ /dev/null @@ -1,131 +0,0 @@ -// 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 . - -//! Deal with CLI args of substrate-to-substrate relay. - -use async_std::prelude::*; -use futures::{select, FutureExt}; -use signal_hook::consts::*; -use signal_hook_async_std::Signals; -use structopt::StructOpt; - -mod chain_schema; -mod detect_equivocations; -mod init_bridge; -mod relay_headers; -mod relay_headers_and_messages; -mod relay_messages; -mod relay_parachains; - -/// The target that will be used when publishing logs related to this pallet. -pub const LOG_TARGET: &str = "bridge"; - -/// Parse relay CLI args. -pub fn parse_args() -> Command { - Command::from_args() -} - -/// Substrate-to-Substrate bridge utilities. -#[derive(StructOpt)] -#[structopt(about = "Substrate-to-Substrate relay")] -pub enum Command { - /// Initialize on-chain bridge pallet with current header data. - /// - /// Sends initialization transaction to bootstrap the bridge with current finalized block data. - InitBridge(init_bridge::InitBridge), - /// Start headers relay between two chains. - /// - /// The on-chain bridge component should have been already initialized with - /// `init-bridge` sub-command. - RelayHeaders(relay_headers::RelayHeaders), - /// Relay parachain heads. - RelayParachains(relay_parachains::RelayParachains), - /// Start messages relay between two chains. - /// - /// Ties up to `Messages` pallets on both chains and starts relaying messages. - /// Requires the header relay to be already running. - RelayMessages(relay_messages::RelayMessages), - /// Start headers and messages relay between two Substrate chains. - /// - /// This high-level relay internally starts four low-level relays: two `RelayHeaders` - /// and two `RelayMessages` relays. Headers are only relayed when they are required by - /// the message relays - i.e. when there are messages or confirmations that needs to be - /// relayed between chains. - RelayHeadersAndMessages(Box), - /// Detect and report equivocations. - /// - /// Parses the source chain headers that were synchronized with the target chain looking for - /// equivocations. If any equivocation is found, it is reported to the source chain. - DetectEquivocations(detect_equivocations::DetectEquivocations), -} - -impl Command { - // Initialize logger depending on the command. - fn init_logger(&self) { - use relay_utils::initialize::{initialize_logger, initialize_relay}; - - match self { - Self::InitBridge(_) | - Self::RelayHeaders(_) | - Self::RelayMessages(_) | - Self::RelayHeadersAndMessages(_) => { - initialize_relay(); - }, - _ => { - initialize_logger(false); - }, - } - } - - /// Run the command. - async fn do_run(self) -> anyhow::Result<()> { - match self { - Self::InitBridge(arg) => arg.run().await?, - Self::RelayHeaders(arg) => arg.run().await?, - Self::RelayParachains(arg) => arg.run().await?, - Self::RelayMessages(arg) => arg.run().await?, - Self::RelayHeadersAndMessages(arg) => arg.run().await?, - Self::DetectEquivocations(arg) => arg.run().await?, - } - Ok(()) - } - - /// Run the command. - pub async fn run(self) { - self.init_logger(); - - let exit_signals = match Signals::new([SIGINT, SIGTERM]) { - Ok(signals) => signals, - Err(e) => { - log::error!(target: LOG_TARGET, "Could not register exit signals: {}", e); - return - }, - }; - let run = self.do_run().fuse(); - futures::pin_mut!(exit_signals, run); - - select! { - signal = exit_signals.next().fuse() => { - log::info!(target: LOG_TARGET, "Received exit signal {:?}", signal); - }, - result = run => { - if let Err(e) = result { - log::error!(target: LOG_TARGET, "substrate-relay: {}", e); - } - }, - } - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers.rs b/relays/bin-substrate/src/cli/relay_headers.rs deleted file mode 100644 index e244d0e9a248f..0000000000000 --- a/relays/bin-substrate/src/cli/relay_headers.rs +++ /dev/null @@ -1,85 +0,0 @@ -// 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 . - -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; - -use crate::bridges::{ - kusama_polkadot::{ - kusama_headers_to_bridge_hub_polkadot::KusamaToBridgeHubPolkadotCliBridge, - polkadot_headers_to_bridge_hub_kusama::PolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::{ - polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, - polkadot_headers_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - }, - rococo_bulletin::{ - rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, - rococo_headers_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - }, -}; - -use substrate_relay_helper::cli::relay_headers::{HeadersRelayer, RelayHeadersParams}; - -/// Start headers relayer process. -#[derive(StructOpt)] -pub struct RelayHeaders { - /// A bridge instance to relay headers for. - #[structopt(possible_values = RelayHeadersBridge::VARIANTS, case_insensitive = true)] - bridge: RelayHeadersBridge, - #[structopt(flatten)] - params: RelayHeadersParams, -} - -#[derive(Debug, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Headers relay bridge. -pub enum RelayHeadersBridge { - KusamaToBridgeHubPolkadot, - PolkadotToBridgeHubKusama, - PolkadotToPolkadotBulletin, - PolkadotBulletinToBridgeHubPolkadot, - RococoToRococoBulletin, - RococoBulletinToBridgeHubRococo, -} - -impl HeadersRelayer for KusamaToBridgeHubPolkadotCliBridge {} -impl HeadersRelayer for PolkadotToBridgeHubKusamaCliBridge {} -impl HeadersRelayer for PolkadotToPolkadotBulletinCliBridge {} -impl HeadersRelayer for PolkadotBulletinToBridgeHubPolkadotCliBridge {} -impl HeadersRelayer for RococoToRococoBulletinCliBridge {} -impl HeadersRelayer for RococoBulletinToBridgeHubRococoCliBridge {} - -impl RelayHeaders { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - RelayHeadersBridge::KusamaToBridgeHubPolkadot => - KusamaToBridgeHubPolkadotCliBridge::relay_headers(self.params), - RelayHeadersBridge::PolkadotToBridgeHubKusama => - PolkadotToBridgeHubKusamaCliBridge::relay_headers(self.params), - RelayHeadersBridge::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::relay_headers(self.params), - RelayHeadersBridge::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotCliBridge::relay_headers(self.params), - RelayHeadersBridge::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::relay_headers(self.params), - RelayHeadersBridge::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoCliBridge::relay_headers(self.params), - } - .await - } -} diff --git a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/relays/bin-substrate/src/cli/relay_headers_and_messages.rs deleted file mode 100644 index 229661748ed6b..0000000000000 --- a/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2019-2022 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 . - -//! Complex 2-ways headers+messages relays support. -//! -//! To add new complex relay between `ChainA` and `ChainB`, you must: -//! -//! 1) ensure that there's a `declare_chain_cli_schema!(...)` for both chains. -//! 2) add `declare_chain_to_chain_bridge_schema!(...)` or -//! `declare_chain_to_parachain_bridge_schema` for the bridge. -//! 3) declare a new struct for the added bridge and implement the `Full2WayBridge` trait for it. - -use async_trait::async_trait; -use structopt::StructOpt; - -use crate::bridges::{ - kusama_polkadot::{ - kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, - polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::{ - polkadot_bulletin_headers_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotCliBridge, - polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - }, - rococo_bulletin::{ - rococo_bulletin_headers_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoCliBridge, - rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - BridgeHubRococoAsBridgeHubPolkadot, - }, - rococo_westend::{ - rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, - westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, - }, -}; -use relay_substrate_client::{ - AccountKeyPairOf, ChainRuntimeVersion, ChainWithRuntimeVersion, ChainWithTransactions, - Parachain, SimpleRuntimeVersion, -}; -use substrate_relay_helper::{ - cli::{ - bridge::{ - CliBridgeBase, MessagesCliBridge, ParachainToRelayHeadersCliBridge, - RelayToRelayHeadersCliBridge, - }, - chain_schema::*, - relay_headers_and_messages::{ - parachain_to_parachain::ParachainToParachainBridge, relay_to_parachain::*, - BridgeEndCommonParams, Full2WayBridge, Full2WayBridgeCommonParams, - HeadersAndMessagesSharedParams, - }, - }, - declare_chain_cli_schema, declare_parachain_to_parachain_bridge_schema, - declare_relay_to_parachain_bridge_schema, TransactionParams, -}; - -// All supported chains. -declare_chain_cli_schema!(Rococo, rococo); -declare_chain_cli_schema!(BridgeHubRococo, bridge_hub_rococo); -declare_chain_cli_schema!(Westend, westend); -declare_chain_cli_schema!(BridgeHubWestend, bridge_hub_westend); -declare_chain_cli_schema!(Kusama, kusama); -declare_chain_cli_schema!(BridgeHubKusama, bridge_hub_kusama); -declare_chain_cli_schema!(Polkadot, polkadot); -declare_chain_cli_schema!(BridgeHubPolkadot, bridge_hub_polkadot); -declare_chain_cli_schema!(PolkadotBulletin, polkadot_bulletin); -declare_chain_cli_schema!(RococoBulletin, rococo_bulletin); -// Means to override signers of different layer transactions. -declare_chain_cli_schema!(RococoHeadersToBridgeHubWestend, rococo_headers_to_bridge_hub_westend); -declare_chain_cli_schema!( - RococoParachainsToBridgeHubWestend, - rococo_parachains_to_bridge_hub_westend -); -declare_chain_cli_schema!(WestendHeadersToBridgeHubRococo, westend_headers_to_bridge_hub_rococo); -declare_chain_cli_schema!( - WestendParachainsToBridgeHubRococo, - westend_parachains_to_bridge_hub_rococo -); -declare_chain_cli_schema!(KusamaHeadersToBridgeHubPolkadot, kusama_headers_to_bridge_hub_polkadot); -declare_chain_cli_schema!( - KusamaParachainsToBridgeHubPolkadot, - kusama_parachains_to_bridge_hub_polkadot -); -declare_chain_cli_schema!(PolkadotHeadersToBridgeHubKusama, polkadot_headers_to_bridge_hub_kusama); -declare_chain_cli_schema!( - PolkadotParachainsToBridgeHubKusama, - polkadot_parachains_to_bridge_hub_kusama -); -declare_chain_cli_schema!( - PolkadotBulletinHeadersToBridgeHubPolkadot, - polkadot_bulletin_headers_to_bridge_hub_polkadot -); -declare_chain_cli_schema!( - RococoBulletinHeadersToBridgeHubRococo, - rococo_bulletin_headers_to_bridge_hub_rococo -); -declare_chain_cli_schema!(PolkadotHeadersToPolkadotBulletin, polkadot_headers_to_polkadot_bulletin); -declare_chain_cli_schema!(RococoHeadersToRococoBulletin, rococo_headers_to_rococo_bulletin); -declare_chain_cli_schema!( - PolkadotParachainsToPolkadotBulletin, - polkadot_parachains_to_polkadot_bulletin -); -declare_chain_cli_schema!(RococoParachainsToRococoBulletin, rococo_parachains_to_rococo_bulletin); -// All supported bridges. -declare_parachain_to_parachain_bridge_schema!(BridgeHubRococo, Rococo, BridgeHubWestend, Westend); -declare_parachain_to_parachain_bridge_schema!(BridgeHubKusama, Kusama, BridgeHubPolkadot, Polkadot); -declare_relay_to_parachain_bridge_schema!(PolkadotBulletin, BridgeHubPolkadot, Polkadot); -declare_relay_to_parachain_bridge_schema!(RococoBulletin, BridgeHubRococo, Rococo); - -/// BridgeHubRococo <> BridgeHubWestend complex relay. -pub struct BridgeHubRococoBridgeHubWestendFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for BridgeHubRococoBridgeHubWestendFull2WayBridge { - type Base = ParachainToParachainBridge; - type Left = relay_bridge_hub_rococo_client::BridgeHubRococo; - type Right = relay_bridge_hub_westend_client::BridgeHubWestend; - type L2R = BridgeHubRococoToBridgeHubWestendCliBridge; - type R2L = BridgeHubWestendToBridgeHubRococoCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - -/// BridgeHubKusama <> BridgeHubPolkadot complex relay. -pub struct BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for BridgeHubKusamaBridgeHubPolkadotFull2WayBridge { - type Base = ParachainToParachainBridge; - type Left = relay_bridge_hub_kusama_client::BridgeHubKusama; - type Right = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - type L2R = BridgeHubKusamaToBridgeHubPolkadotCliBridge; - type R2L = BridgeHubPolkadotToBridgeHubKusamaCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - -/// `PolkadotBulletin` <> `BridgeHubPolkadot` complex relay. -pub struct PolkadotBulletinBridgeHubPolkadotFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for PolkadotBulletinBridgeHubPolkadotFull2WayBridge { - type Base = RelayToParachainBridge; - type Left = relay_polkadot_bulletin_client::PolkadotBulletin; - type Right = relay_bridge_hub_polkadot_client::BridgeHubPolkadot; - type L2R = PolkadotBulletinToBridgeHubPolkadotCliBridge; - type R2L = PolkadotToPolkadotBulletinCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - -/// `RococoBulletin` <> `BridgeHubRococo` complex relay. -pub struct RococoBulletinBridgeHubRococoFull2WayBridge { - base: ::Base, -} - -#[async_trait] -impl Full2WayBridge for RococoBulletinBridgeHubRococoFull2WayBridge { - type Base = RelayToParachainBridge; - type Left = relay_polkadot_bulletin_client::PolkadotBulletin; - type Right = BridgeHubRococoAsBridgeHubPolkadot; - type L2R = RococoBulletinToBridgeHubRococoCliBridge; - type R2L = RococoToRococoBulletinCliBridge; - - fn new(base: Self::Base) -> anyhow::Result { - Ok(Self { base }) - } - - fn base(&self) -> &Self::Base { - &self.base - } - - fn mut_base(&mut self) -> &mut Self::Base { - &mut self.base - } -} - -/// Complex headers+messages relay. -#[derive(Debug, PartialEq, StructOpt)] -pub enum RelayHeadersAndMessages { - /// BridgeHubKusama <> BridgeHubPolkadot relay. - BridgeHubKusamaBridgeHubPolkadot(BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages), - /// `PolkadotBulletin` <> `BridgeHubPolkadot` relay. - PolkadotBulletinBridgeHubPolkadot(PolkadotBulletinBridgeHubPolkadotHeadersAndMessages), - /// `RococoBulletin` <> `BridgeHubRococo` relay. - RococoBulletinBridgeHubRococo(RococoBulletinBridgeHubRococoHeadersAndMessages), - /// BridgeHubRococo <> BridgeHubWestend relay. - BridgeHubRococoBridgeHubWestend(BridgeHubRococoBridgeHubWestendHeadersAndMessages), -} - -impl RelayHeadersAndMessages { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self { - RelayHeadersAndMessages::BridgeHubRococoBridgeHubWestend(params) => - BridgeHubRococoBridgeHubWestendFull2WayBridge::new(params.into_bridge().await?)? - .run() - .await, - RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot(params) => - BridgeHubKusamaBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? - .run() - .await, - RelayHeadersAndMessages::PolkadotBulletinBridgeHubPolkadot(params) => - PolkadotBulletinBridgeHubPolkadotFull2WayBridge::new(params.into_bridge().await?)? - .run() - .await, - RelayHeadersAndMessages::RococoBulletinBridgeHubRococo(params) => - RococoBulletinBridgeHubRococoFull2WayBridge::new(params.into_bridge().await?)? - .run() - .await, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use substrate_relay_helper::cli::{HexLaneId, PrometheusParams}; - - #[test] - fn should_parse_parachain_to_parachain_options() { - // when - let res = RelayHeadersAndMessages::from_iter(vec![ - "relay-headers-and-messages", - "bridge-hub-kusama-bridge-hub-polkadot", - "--bridge-hub-kusama-host", - "bridge-hub-kusama-node-collator1", - "--bridge-hub-kusama-port", - "9944", - "--bridge-hub-kusama-signer", - "//Iden", - "--bridge-hub-kusama-transactions-mortality", - "64", - "--kusama-host", - "kusama-alice", - "--kusama-port", - "9944", - "--bridge-hub-polkadot-host", - "bridge-hub-polkadot-collator1", - "--bridge-hub-polkadot-port", - "9944", - "--bridge-hub-polkadot-signer", - "//George", - "--bridge-hub-polkadot-transactions-mortality", - "64", - "--polkadot-host", - "polkadot-alice", - "--polkadot-port", - "9944", - "--lane", - "00000000", - "--prometheus-host", - "0.0.0.0", - ]); - - // then - assert_eq!( - res, - RelayHeadersAndMessages::BridgeHubKusamaBridgeHubPolkadot( - BridgeHubKusamaBridgeHubPolkadotHeadersAndMessages { - shared: HeadersAndMessagesSharedParams { - lane: vec![HexLaneId([0x00, 0x00, 0x00, 0x00])], - only_mandatory_headers: false, - prometheus_params: PrometheusParams { - no_prometheus: false, - prometheus_host: "0.0.0.0".into(), - prometheus_port: 9616, - }, - }, - left_relay: KusamaConnectionParams { - kusama_host: "kusama-alice".into(), - kusama_port: 9944, - kusama_secure: false, - kusama_runtime_version: KusamaRuntimeVersionParams { - kusama_version_mode: RuntimeVersionType::Bundle, - kusama_spec_version: None, - kusama_transaction_version: None, - }, - }, - left: BridgeHubKusamaConnectionParams { - bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(), - bridge_hub_kusama_port: 9944, - bridge_hub_kusama_secure: false, - bridge_hub_kusama_runtime_version: BridgeHubKusamaRuntimeVersionParams { - bridge_hub_kusama_version_mode: RuntimeVersionType::Bundle, - bridge_hub_kusama_spec_version: None, - bridge_hub_kusama_transaction_version: None, - }, - }, - left_sign: BridgeHubKusamaSigningParams { - bridge_hub_kusama_signer: Some("//Iden".into()), - bridge_hub_kusama_signer_password: None, - bridge_hub_kusama_signer_file: None, - bridge_hub_kusama_signer_password_file: None, - bridge_hub_kusama_transactions_mortality: Some(64), - }, - right: BridgeHubPolkadotConnectionParams { - bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(), - bridge_hub_polkadot_port: 9944, - bridge_hub_polkadot_secure: false, - bridge_hub_polkadot_runtime_version: - BridgeHubPolkadotRuntimeVersionParams { - bridge_hub_polkadot_version_mode: RuntimeVersionType::Bundle, - bridge_hub_polkadot_spec_version: None, - bridge_hub_polkadot_transaction_version: None, - }, - }, - right_sign: BridgeHubPolkadotSigningParams { - bridge_hub_polkadot_signer: Some("//George".into()), - bridge_hub_polkadot_signer_password: None, - bridge_hub_polkadot_signer_file: None, - bridge_hub_polkadot_signer_password_file: None, - bridge_hub_polkadot_transactions_mortality: Some(64), - }, - right_relay: PolkadotConnectionParams { - polkadot_host: "polkadot-alice".into(), - polkadot_port: 9944, - polkadot_secure: false, - polkadot_runtime_version: PolkadotRuntimeVersionParams { - polkadot_version_mode: RuntimeVersionType::Bundle, - polkadot_spec_version: None, - polkadot_transaction_version: None, - }, - }, - } - ), - ); - } -} diff --git a/relays/bin-substrate/src/cli/relay_messages.rs b/relays/bin-substrate/src/cli/relay_messages.rs deleted file mode 100644 index 92b98f4d983a3..0000000000000 --- a/relays/bin-substrate/src/cli/relay_messages.rs +++ /dev/null @@ -1,96 +0,0 @@ -// 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 . - -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; - -use crate::bridges::{ - kusama_polkadot::{ - bridge_hub_kusama_messages_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge, - bridge_hub_polkadot_messages_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge, - }, - polkadot_bulletin::{ - bridge_hub_polkadot_messages_to_polkadot_bulletin::BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge, - polkadot_bulletin_messages_to_bridge_hub_polkadot::PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge, - }, - rococo_bulletin::{ - bridge_hub_rococo_messages_to_rococo_bulletin::BridgeHubRococoToRococoBulletinMessagesCliBridge, - rococo_bulletin_messages_to_bridge_hub_rococo::RococoBulletinToBridgeHubRococoMessagesCliBridge, - }, - rococo_westend::{ - bridge_hub_rococo_messages_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendMessagesCliBridge, - bridge_hub_westend_messages_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoMessagesCliBridge, - }, -}; -use substrate_relay_helper::cli::relay_messages::{MessagesRelayer, RelayMessagesParams}; - -#[derive(Debug, PartialEq, Eq, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -/// Supported full bridges (headers + messages). -pub enum FullBridge { - BridgeHubRococoToBridgeHubWestend, - BridgeHubWestendToBridgeHubRococo, - BridgeHubKusamaToBridgeHubPolkadot, - BridgeHubPolkadotToBridgeHubKusama, - PolkadotBulletinToBridgeHubPolkadot, - BridgeHubPolkadotToPolkadotBulletin, - RococoBulletinToBridgeHubRococo, - BridgeHubRococoToRococoBulletin, -} - -/// Start messages relayer process. -#[derive(StructOpt)] -pub struct RelayMessages { - /// A bridge instance to relay messages for. - #[structopt(possible_values = FullBridge::VARIANTS, case_insensitive = true)] - bridge: FullBridge, - #[structopt(flatten)] - params: RelayMessagesParams, -} - -impl MessagesRelayer for BridgeHubRococoToBridgeHubWestendMessagesCliBridge {} -impl MessagesRelayer for BridgeHubWestendToBridgeHubRococoMessagesCliBridge {} -impl MessagesRelayer for BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge {} -impl MessagesRelayer for BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge {} -impl MessagesRelayer for PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge {} -impl MessagesRelayer for BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge {} -impl MessagesRelayer for RococoBulletinToBridgeHubRococoMessagesCliBridge {} -impl MessagesRelayer for BridgeHubRococoToRococoBulletinMessagesCliBridge {} - -impl RelayMessages { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - FullBridge::BridgeHubRococoToBridgeHubWestend => - BridgeHubRococoToBridgeHubWestendMessagesCliBridge::relay_messages(self.params), - FullBridge::BridgeHubWestendToBridgeHubRococo => - BridgeHubWestendToBridgeHubRococoMessagesCliBridge::relay_messages(self.params), - FullBridge::BridgeHubKusamaToBridgeHubPolkadot => - BridgeHubKusamaToBridgeHubPolkadotMessagesCliBridge::relay_messages(self.params), - FullBridge::BridgeHubPolkadotToBridgeHubKusama => - BridgeHubPolkadotToBridgeHubKusamaMessagesCliBridge::relay_messages(self.params), - FullBridge::PolkadotBulletinToBridgeHubPolkadot => - PolkadotBulletinToBridgeHubPolkadotMessagesCliBridge::relay_messages(self.params), - FullBridge::BridgeHubPolkadotToPolkadotBulletin => - BridgeHubPolkadotToPolkadotBulletinMessagesCliBridge::relay_messages(self.params), - FullBridge::RococoBulletinToBridgeHubRococo => - RococoBulletinToBridgeHubRococoMessagesCliBridge::relay_messages(self.params), - FullBridge::BridgeHubRococoToRococoBulletin => - BridgeHubRococoToRococoBulletinMessagesCliBridge::relay_messages(self.params), - } - .await - } -} diff --git a/relays/bin-substrate/src/cli/relay_parachains.rs b/relays/bin-substrate/src/cli/relay_parachains.rs deleted file mode 100644 index 65382d1ca11b9..0000000000000 --- a/relays/bin-substrate/src/cli/relay_parachains.rs +++ /dev/null @@ -1,81 +0,0 @@ -// 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 . - -use crate::bridges::{ - kusama_polkadot::{ - kusama_parachains_to_bridge_hub_polkadot::BridgeHubKusamaToBridgeHubPolkadotCliBridge, - polkadot_parachains_to_bridge_hub_kusama::BridgeHubPolkadotToBridgeHubKusamaCliBridge, - }, - polkadot_bulletin::polkadot_parachains_to_polkadot_bulletin::PolkadotToPolkadotBulletinCliBridge, - rococo_bulletin::rococo_parachains_to_rococo_bulletin::RococoToRococoBulletinCliBridge, - rococo_westend::{ - rococo_parachains_to_bridge_hub_westend::BridgeHubRococoToBridgeHubWestendCliBridge, - westend_parachains_to_bridge_hub_rococo::BridgeHubWestendToBridgeHubRococoCliBridge, - }, -}; -use structopt::StructOpt; -use strum::{EnumString, VariantNames}; -use substrate_relay_helper::cli::relay_parachains::{ParachainsRelayer, RelayParachainsParams}; - -/// Start parachain heads relayer process. -#[derive(StructOpt)] -pub struct RelayParachains { - /// A bridge instance to relay parachains heads for. - #[structopt(possible_values = RelayParachainsBridge::VARIANTS, case_insensitive = true)] - bridge: RelayParachainsBridge, - #[structopt(flatten)] - params: RelayParachainsParams, -} - -/// Parachain heads relay bridge. -#[derive(Debug, EnumString, VariantNames)] -#[strum(serialize_all = "kebab_case")] -pub enum RelayParachainsBridge { - KusamaToBridgeHubPolkadot, - PolkadotToBridgeHubKusama, - PolkadotToPolkadotBulletin, - RococoToRococoBulletin, - RococoToBridgeHubWestend, - WestendToBridgeHubRococo, -} - -impl ParachainsRelayer for BridgeHubRococoToBridgeHubWestendCliBridge {} -impl ParachainsRelayer for BridgeHubWestendToBridgeHubRococoCliBridge {} -impl ParachainsRelayer for BridgeHubKusamaToBridgeHubPolkadotCliBridge {} -impl ParachainsRelayer for BridgeHubPolkadotToBridgeHubKusamaCliBridge {} -impl ParachainsRelayer for PolkadotToPolkadotBulletinCliBridge {} -impl ParachainsRelayer for RococoToRococoBulletinCliBridge {} - -impl RelayParachains { - /// Run the command. - pub async fn run(self) -> anyhow::Result<()> { - match self.bridge { - RelayParachainsBridge::RococoToBridgeHubWestend => - BridgeHubRococoToBridgeHubWestendCliBridge::relay_parachains(self.params), - RelayParachainsBridge::WestendToBridgeHubRococo => - BridgeHubWestendToBridgeHubRococoCliBridge::relay_parachains(self.params), - RelayParachainsBridge::KusamaToBridgeHubPolkadot => - BridgeHubKusamaToBridgeHubPolkadotCliBridge::relay_parachains(self.params), - RelayParachainsBridge::PolkadotToBridgeHubKusama => - BridgeHubPolkadotToBridgeHubKusamaCliBridge::relay_parachains(self.params), - RelayParachainsBridge::PolkadotToPolkadotBulletin => - PolkadotToPolkadotBulletinCliBridge::relay_parachains(self.params), - RelayParachainsBridge::RococoToRococoBulletin => - RococoToRococoBulletinCliBridge::relay_parachains(self.params), - } - .await - } -} diff --git a/relays/bin-substrate/src/main.rs b/relays/bin-substrate/src/main.rs deleted file mode 100644 index 214bfa60e24a4..0000000000000 --- a/relays/bin-substrate/src/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -// 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 . - -//! Substrate-to-substrate relay entrypoint. - -#![warn(missing_docs)] - -mod bridges; -mod cli; - -fn main() { - let command = cli::parse_args(); - let run = command.run(); - async_std::task::block_on(run); -} diff --git a/relays/client-bridge-hub-kusama/Cargo.toml b/relays/client-bridge-hub-kusama/Cargo.toml deleted file mode 100644 index a02dc26a0a8d3..0000000000000 --- a/relays/client-bridge-hub-kusama/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "relay-bridge-hub-kusama-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -#relay-substrate-client = { path = "../client-substrate" } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-bridge-hub-kusama = { path = "../../chains/chain-bridge-hub-kusama" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot = { path = "../../chains/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-substrate-client = { path = "../client-substrate" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-kusama/src/codegen_runtime.rs b/relays/client-bridge-hub-kusama/src/codegen_runtime.rs deleted file mode 100644 index 2da4c3014b254..0000000000000 --- a/relays/client-bridge-hub-kusama/src/codegen_runtime.rs +++ /dev/null @@ -1,4053 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url -//! wss://kusama-bridge-hub-rpc.polkadot.io - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -#[allow(rustdoc::broken_intra_doc_links)] -pub mod api { - #[allow(unused_imports)] - mod root_mod { - pub use super::*; - } - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod bp_header_chain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AuthoritySet { - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HeaderChainError { - #[codec(index = 0)] - UnknownHeader, - #[codec(index = 1)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderFinalityInfo<_0, _1> { - pub finality_proof: _0, - pub new_verification_context: ::core::option::Option<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredHeaderData<_0, _1> { - pub number: _0, - pub state_root: _1, - } - } - pub mod bp_messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DeliveredMessages { - pub begin: ::core::primitive::u64, - pub end: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundLaneData<_0> { - pub relayers: ::std::vec::Vec>, - pub last_confirmed_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundMessageDetails { - pub dispatch_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageKey { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MessagesOperatingMode { - #[codec(index = 0)] - Basic(runtime_types::bp_runtime::BasicOperatingMode), - #[codec(index = 1)] - RejectingOutboundMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundLaneData { - pub oldest_unpruned_nonce: ::core::primitive::u64, - pub latest_received_nonce: ::core::primitive::u64, - pub latest_generated_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundMessageDetails { - pub nonce: ::core::primitive::u64, - pub dispatch_weight: ::sp_weights::Weight, - pub size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalResult<_0> { - #[codec(index = 0)] - Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), - #[codec(index = 1)] - InvalidNonce, - #[codec(index = 2)] - TooManyUnrewardedRelayers, - #[codec(index = 3)] - TooManyUnconfirmedMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceivedMessages<_0> { - pub lane: runtime_types::bp_messages::LaneId, - pub receive_results: ::std::vec::Vec<( - ::core::primitive::u64, - runtime_types::bp_messages::ReceivalResult<_0>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnrewardedRelayer<_0> { - pub relayer: _0, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VerificationError { - #[codec(index = 0)] - EmptyMessageProof, - #[codec(index = 1)] - HeaderChain(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 2)] - InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 3)] - InvalidMessageWeight, - #[codec(index = 4)] - MessagesCountMismatch, - #[codec(index = 5)] - MessageStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 6)] - MessageTooLarge, - #[codec(index = 7)] - OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 8)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 9)] - Other, - } - } - pub mod bp_parachains { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BestParaHeadHash { - pub at_relay_block_number: ::core::primitive::u32, - pub head_hash: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo { - pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, - pub next_imported_hash_position: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod bp_relayers { - use super::runtime_types; - pub mod registration { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0, _1> { - pub valid_till: _0, - pub stake: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardsAccountOwner { - #[codec(index = 0)] - ThisChain, - #[codec(index = 1)] - BridgedChain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardsAccountParams { - pub lane_id: runtime_types::bp_messages::LaneId, - pub bridged_chain_id: [::core::primitive::u8; 4usize], - pub owner: runtime_types::bp_relayers::RewardsAccountOwner, - } - } - pub mod bp_runtime { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageDispatchResult<_0> { - pub unspent_weight: ::sp_weights::Weight, - pub dispatch_level_result: _0, - } - } - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateNodesInProof, - #[codec(index = 1)] - UnusedNodesInTheProof, - #[codec(index = 2)] - StorageRootMismatch, - #[codec(index = 3)] - StorageValueUnavailable, - #[codec(index = 4)] - StorageValueEmpty, - #[codec(index = 5)] - StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OwnedBridgeModuleError { - #[codec(index = 0)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StrippableError; - } - pub mod bridge_hub_kusama_runtime { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::sp_core::crypto::AccountId32, - >, - ), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), - #[codec(index = 3)] - Void(runtime_types::sp_core::Void), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 41)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 50)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), - #[codec(index = 51)] - BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 52)] - BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 53)] - BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeError { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Error), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Error), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Error), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Error), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Error), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Error), - #[codec(index = 41)] - Multisig(runtime_types::pallet_multisig::pallet::Error), - #[codec(index = 50)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), - #[codec(index = 51)] - BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), - #[codec(index = 52)] - BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Error), - #[codec(index = 53)] - BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 11)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 41)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 50)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), - #[codec(index = 51)] - BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 52)] - BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 53)] - BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeHoldReason {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, - } - } - pub mod bridge_runtime_common { - use super::runtime_types; - pub mod messages_xcm_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmBlobMessageDispatchResult { - #[codec(index = 0)] - InvalidPayload, - #[codec(index = 1)] - Dispatched, - #[codec(index = 2)] - NotDispatched, - } - } - pub mod refund_relayer_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundBridgedParachainMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundTransactionExtensionAdapter<_0>(pub _0); - } - } - pub mod cumulus_pallet_dmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - OverLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 1)] - UnsupportedVersion { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 2)] - ExecutedDownward { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - outcome: runtime_types::xcm::v3::traits::Outcome, - }, - #[codec(index = 3)] - WeightExhausted { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - remaining_weight: ::sp_weights::Weight, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - OverweightEnqueued { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - overweight_index: ::core::primitive::u64, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 5)] - OverweightServiced { - overweight_index: ::core::primitive::u64, - weight_used: ::sp_weights::Weight, - }, - #[codec(index = 6)] - MaxMessagesExhausted { message_hash: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ConfigData { - pub max_individual: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PageIndexData { - pub begin_used: ::core::primitive::u32, - pub end_used: ::core::primitive::u32, - pub overweight_count: ::core::primitive::u64, - } - } - pub mod cumulus_pallet_parachain_system { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OverlappingUpgrades, - #[codec(index = 1)] - ProhibitedByPolkadot, - #[codec(index = 2)] - TooBig, - #[codec(index = 3)] - ValidationDataNotAvailable, - #[codec(index = 4)] - HostConfigurationNotAvailable, - #[codec(index = 5)] - NotScheduled, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidationFunctionStored, - #[codec(index = 1)] - ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, - #[codec(index = 2)] - ValidationFunctionDiscarded, - #[codec(index = 3)] - UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - DownwardMessagesReceived { count: ::core::primitive::u32 }, - #[codec(index = 5)] - DownwardMessagesProcessed { - weight_used: ::sp_weights::Weight, - dmq_head: ::subxt::utils::H256, - }, - #[codec(index = 6)] - UpwardMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - pub mod relay_state_snapshot { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RelayDispatchQueueRemainingCapacity { - pub remaining_count: ::core::primitive::u32, - pub remaining_size: ::core::primitive::u32, - } - } - pub mod unincluded_segment { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelUpdate { - pub msg_count: ::core::primitive::u32, - pub total_bytes: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CodeUpgradeAuthorization { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } - } - pub mod cumulus_pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - UnsupportedVersion([::core::primitive::u8; 32usize]), - #[codec(index = 2)] - ExecutedDownward( - [::core::primitive::u8; 32usize], - runtime_types::xcm::v3::traits::Outcome, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Relay, - #[codec(index = 1)] - SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), - } - } - } - pub mod cumulus_pallet_xcmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - #[codec(index = 1)] - suspend_xcm_execution, - #[codec(index = 2)] - resume_xcm_execution, - #[codec(index = 3)] - update_suspend_threshold { new: ::core::primitive::u32 }, - #[codec(index = 4)] - update_drop_threshold { new: ::core::primitive::u32 }, - #[codec(index = 5)] - update_resume_threshold { new: ::core::primitive::u32 }, - #[codec(index = 6)] - update_threshold_weight { new: ::sp_weights::Weight }, - #[codec(index = 7)] - update_weight_restrict_decay { new: ::sp_weights::Weight }, - #[codec(index = 8)] - update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSend, - #[codec(index = 1)] - BadXcmOrigin, - #[codec(index = 2)] - BadXcm, - #[codec(index = 3)] - BadOverweightIndex, - #[codec(index = 4)] - WeightOverLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Success { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - weight: ::sp_weights::Weight, - }, - #[codec(index = 1)] - Fail { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - error: runtime_types::xcm::v3::traits::Error, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - BadVersion { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 3)] - BadFormat { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 4)] - XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 5)] - OverweightEnqueued { - sender: runtime_types::polkadot_parachain_primitives::primitives::Id, - sent_at: ::core::primitive::u32, - index: ::core::primitive::u64, - required: ::sp_weights::Weight, - }, - #[codec(index = 6)] - OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundChannelDetails { - pub sender: runtime_types::polkadot_parachain_primitives::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, - pub message_metadata: ::std::vec::Vec<( - ::core::primitive::u32, - runtime_types::polkadot_parachain_primitives::primitives::XcmpMessageFormat, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundChannelDetails { - pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, - pub signals_exist: ::core::primitive::bool, - pub first_index: ::core::primitive::u16, - pub last_index: ::core::primitive::u16, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OutboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueueConfigData { - pub suspend_threshold: ::core::primitive::u32, - pub drop_threshold: ::core::primitive::u32, - pub resume_threshold: ::core::primitive::u32, - pub threshold_weight: ::sp_weights::Weight, - pub weight_restrict_decay: ::sp_weights::Weight, - pub xcmp_max_individual_weight: ::sp_weights::Weight, - } - } - pub mod cumulus_primitives_core { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CollationInfo { - pub upward_messages: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub horizontal_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain_primitives::primitives::Id, - >, - >, - pub new_validation_code: ::core::option::Option< - runtime_types::polkadot_parachain_primitives::primitives::ValidationCode, - >, - pub processed_downward_messages: ::core::primitive::u32, - pub hrmp_watermark: ::core::primitive::u32, - pub head_data: runtime_types::polkadot_parachain_primitives::primitives::HeadData, - } - } - pub mod cumulus_primitives_parachain_inherent { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainInherentData { - pub validation_data: - runtime_types::polkadot_primitives::v6::PersistedValidationData< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, - pub downward_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundDownwardMessage< - ::core::primitive::u32, - >, - >, - pub horizontal_messages: ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain_primitives::primitives::Id, - ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundHrmpMessage< - ::core::primitive::u32, - >, - >, - >, - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commit<_0, _1, _2, _3> { - pub target_hash: _0, - pub target_number: _1, - pub precommits: ::std::vec::Vec< - runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedPrecommit<_0, _1, _2, _3> { - pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, - pub signature: _2, - pub id: _3, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: ::core::primitive::u32, - pub providers: ::core::primitive::u32, - pub sufficients: ::core::primitive::u32, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bridge_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u32, - hash: ::subxt::utils::H256, - grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< - ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - runtime_types::bp_header_chain::AuthoritySet, - >, - }, - } - } - pub mod storage_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - } - } - pub mod pallet_bridge_messages { - use super::runtime_types; - pub mod outbound_lane { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalConfirmationError { - #[codec(index = 0)] - FailedToConfirmFutureMessages, - #[codec(index = 1)] - EmptyUnrewardedRelayerEntry, - #[codec(index = 2)] - NonConsecutiveUnrewardedRelayerEntries, - #[codec(index = 3)] - TryingToConfirmMoreMessagesThanExpected, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - } - } - pub mod pallet_bridge_parachains { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_parachain_heads { - at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), - parachains: ::std::vec::Vec<( - ::bp_polkadot_core::parachains::ParaId, - ::subxt::utils::H256, - )>, - parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, - }, - #[codec(index = 1)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 2)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnknownRelayChainBlock, - #[codec(index = 1)] - InvalidRelayChainBlockNumber, - #[codec(index = 2)] - HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 3)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 1)] - MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 2)] - IncorrectParachainHeadHash { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - actual_parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - RejectedObsoleteParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 4)] - RejectedLargeParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - parachain_head_size: ::core::primitive::u32, - }, - #[codec(index = 5)] - UpdatedParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - } - } - } - pub mod pallet_bridge_relayers { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim_rewards { - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - }, - #[codec(index = 1)] - register { valid_till: ::core::primitive::u32 }, - #[codec(index = 2)] - deregister, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NoRewardForRelayer, - #[codec(index = 1)] - FailedToPayReward, - #[codec(index = 2)] - InvalidRegistrationLease, - #[codec(index = 3)] - CannotReduceRegistrationLease, - #[codec(index = 4)] - FailedToReserve, - #[codec(index = 5)] - FailedToUnreserve, - #[codec(index = 6)] - NotRegistered, - #[codec(index = 7)] - RegistrationIsStillActive, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RewardPaid { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 1)] - RegistrationUpdated { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - #[codec(index = 2)] - Deregistered { relayer: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - SlashedAndDeregistered { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - } - } - } - pub mod pallet_collator_selection { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 1)] - set_desired_candidates { max: ::core::primitive::u32 }, - #[codec(index = 2)] - set_candidacy_bond { bond: ::core::primitive::u128 }, - #[codec(index = 3)] - register_as_candidate, - #[codec(index = 4)] - leave_intent, - #[codec(index = 5)] - add_invulnerable { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateInfo<_0, _1> { - pub who: _0, - pub deposit: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCandidates, - #[codec(index = 1)] - TooFewEligibleCollators, - #[codec(index = 2)] - AlreadyCandidate, - #[codec(index = 3)] - NotCandidate, - #[codec(index = 4)] - TooManyInvulnerables, - #[codec(index = 5)] - AlreadyInvulnerable, - #[codec(index = 6)] - NotInvulnerable, - #[codec(index = 7)] - NoAssociatedValidatorId, - #[codec(index = 8)] - ValidatorNotRegistered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewInvulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 1)] - InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 2)] - InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, - #[codec(index = 4)] - NewCandidacyBond { bond_amount: ::core::primitive::u128 }, - #[codec(index = 5)] - CandidateAdded { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 6)] - CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 7)] - InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, - } - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box< - runtime_types::bridge_hub_kusama_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_kusama_runtime::RuntimeCall, - >, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: ::core::primitive::u32, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::bridge_hub_kusama_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FeeDetails<_0> { - pub inclusion_fee: ::core::option::Option< - runtime_types::pallet_transaction_payment::types::InclusionFee<_0>, - >, - pub tip: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InclusionFee<_0> { - pub base_fee: _0, - pub len_fee: _0, - pub adjusted_weight_fee: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDispatchInfo<_0, _1> { - pub weight: _1, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub partial_fee: _0, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { - calls: - ::std::vec::Vec, - }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box< - runtime_types::bridge_hub_kusama_runtime::RuntimeCall, - >, - }, - #[codec(index = 2)] - batch_all { - calls: - ::std::vec::Vec, - }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box< - runtime_types::bridge_hub_kusama_runtime::OriginCaller, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_kusama_runtime::RuntimeCall, - >, - }, - #[codec(index = 4)] - force_batch { - calls: - ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box< - runtime_types::bridge_hub_kusama_runtime::RuntimeCall, - >, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: ::std::boxed::Box< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted { outcome: runtime_types::xcm::v3::traits::Outcome }, - #[codec(index = 1)] - Sent { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - message: runtime_types::xcm::v3::Xcm, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - UnexpectedResponse { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 3)] - ResponseReady { - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - }, - #[codec(index = 4)] - Notified { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 5)] - NotifyOverweight { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - actual_weight: ::sp_weights::Weight, - max_budgeted_weight: ::sp_weights::Weight, - }, - #[codec(index = 6)] - NotifyDispatchError { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 7)] - NotifyDecodeFailed { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 8)] - InvalidResponder { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - expected_location: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 9)] - InvalidResponderVersion { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 10)] - ResponseTaken { query_id: ::core::primitive::u64 }, - #[codec(index = 11)] - AssetsTrapped { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - }, - #[codec(index = 12)] - VersionChangeNotified { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - result: ::core::primitive::u32, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 13)] - SupportedVersionChanged { - location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - version: ::core::primitive::u32, - }, - #[codec(index = 14)] - NotifyTargetSendFail { - location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - error: runtime_types::xcm::v3::traits::Error, - }, - #[codec(index = 15)] - NotifyTargetMigrationFail { - location: runtime_types::xcm::VersionedMultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 16)] - InvalidQuerierVersion { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 17)] - InvalidQuerier { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - expected_querier: - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - maybe_actual_querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 18)] - VersionNotifyStarted { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 19)] - VersionNotifyRequested { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 20)] - VersionNotifyUnrequested { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 21)] - FeesPaid { - paying: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - fees: runtime_types::xcm::v3::multiasset::MultiAssets, - }, - #[codec(index = 22)] - AssetsClaimed { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Response(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedMultiLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain_primitives { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmpMessageFormat { - #[codec(index = 0)] - ConcatenatedVersionedXcm, - #[codec(index = 1)] - ConcatenatedEncodedBlob, - #[codec(index = 2)] - Signals, - } - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v6 { - use super::runtime_types; - pub mod async_backing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHostConfiguration { - pub max_code_size: ::core::primitive::u32, - pub max_head_data_size: ::core::primitive::u32, - pub max_upward_queue_count: ::core::primitive::u32, - pub max_upward_queue_size: ::core::primitive::u32, - pub max_upward_message_size: ::core::primitive::u32, - pub max_upward_message_num_per_candidate: ::core::primitive::u32, - pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, - pub validation_upgrade_cooldown: ::core::primitive::u32, - pub validation_upgrade_delay: ::core::primitive::u32, - pub async_backing_params: - runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PersistedValidationData<_0, _1> { - pub parent_head: - runtime_types::polkadot_parachain_primitives::primitives::HeadData, - pub relay_parent_number: _1, - pub relay_parent_storage_root: _0, - pub max_pov_size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_consensus_aura { - use super::runtime_types; - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct SlotDuration(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMetadata(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_inherents { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckInherentsResult { - pub okay: ::core::primitive::bool, - pub fatal_error: ::core::primitive::bool, - pub errors: runtime_types::sp_inherents::InherentData, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData { - pub data: ::subxt::utils::KeyedVec< - [::core::primitive::u8; 8usize], - ::std::vec::Vec<::core::primitive::u8>, - >, - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod block { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Block<_0, _1> { - pub header: _0, - pub extrinsics: ::std::vec::Vec<_1>, - } - } - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - } - pub mod transaction_validity { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidTransaction { - #[codec(index = 0)] - Call, - #[codec(index = 1)] - Payment, - #[codec(index = 2)] - Future, - #[codec(index = 3)] - Stale, - #[codec(index = 4)] - BadProof, - #[codec(index = 5)] - AncientBirthBlock, - #[codec(index = 6)] - ExhaustsResources, - #[codec(index = 7)] - Custom(::core::primitive::u8), - #[codec(index = 8)] - BadMandatory, - #[codec(index = 9)] - MandatoryValidation, - #[codec(index = 10)] - BadSigner, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionSource { - #[codec(index = 0)] - InBlock, - #[codec(index = 1)] - Local, - #[codec(index = 2)] - External, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionValidityError { - #[codec(index = 0)] - Invalid(runtime_types::sp_runtime::transaction_validity::InvalidTransaction), - #[codec(index = 1)] - Unknown(runtime_types::sp_runtime::transaction_validity::UnknownTransaction), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UnknownTransaction { - #[codec(index = 0)] - CannotLookup, - #[codec(index = 1)] - NoUnsignedValidator, - #[codec(index = 2)] - Custom(::core::primitive::u8), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidTransaction { - pub priority: ::core::primitive::u64, - pub requires: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub provides: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub longevity: ::core::primitive::u64, - pub propagate: ::core::primitive::bool, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_trie { - use super::runtime_types; - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StorageProof { - pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod staging_xcm { - use super::runtime_types; - pub mod v3 { - use super::runtime_types; - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded2 { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm2 { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm2), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm2), - } - } - } -} diff --git a/relays/client-bridge-hub-kusama/src/lib.rs b/relays/client-bridge-hub-kusama/src/lib.rs deleted file mode 100644 index 43dd53d2d83a2..0000000000000 --- a/relays/client-bridge-hub-kusama/src/lib.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2022 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 . - -//! Types used to connect to the BridgeHub-Kusama-Substrate parachain. - -pub mod codegen_runtime; - -use bp_bridge_hub_kusama::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot::SuffixedCommonSignedExtensionExt; -use codec::Encode; -use relay_substrate_client::{ - calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, - UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::bridge_hub_kusama_runtime::RuntimeCall; -pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; -pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; -type UtilityCall = runtime_types::pallet_utility::pallet::Call; - -/// Kusama chain definition -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct BridgeHubKusama; - -impl UnderlyingChainProvider for BridgeHubKusama { - type Chain = bp_bridge_hub_kusama::BridgeHubKusama; -} - -impl Chain for BridgeHubKusama { - const NAME: &'static str = "BridgeHubKusama"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_bridge_hub_kusama::BEST_FINALIZED_BRIDGE_HUB_KUSAMA_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = bp_bridge_hub_kusama::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithBalances for BridgeHubKusama { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_bridge_hub_kusama::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl From> for RuntimeCall { - fn from(value: MockUtilityCall) -> RuntimeCall { - match value { - MockUtilityCall::batch_all(calls) => - RuntimeCall::Utility(UtilityCall::batch_all { calls }), - } - } -} - -impl ChainWithUtilityPallet for BridgeHubKusama { - type UtilityPallet = MockedRuntimeUtilityPallet; -} - -impl ChainWithTransactions for BridgeHubKusama { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - (((), ()), ((), ())), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(UncheckedExtrinsic::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithMessages for BridgeHubKusama { - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = - Some(bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME); - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_kusama::TO_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_kusama::FROM_BRIDGE_HUB_KUSAMA_MESSAGE_DETAILS_METHOD; -} - -impl ChainWithRuntimeVersion for BridgeHubKusama { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 4 }); -} diff --git a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs b/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs deleted file mode 100644 index 176cb173e5334..0000000000000 --- a/relays/client-bridge-hub-kusama/src/runtime_wrapper.rs +++ /dev/null @@ -1,71 +0,0 @@ -// 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 . - -//! Types that are specific to the BridgeHubKusama runtime. -// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945) - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_bridge_hub_kusama::TransactionExtension; -pub use bp_header_chain::BridgeGrandpaCallOf; -pub use bp_parachains::BridgeParachainCall; -pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; - -/// Unchecked BridgeHubKusama extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_kusama::UncheckedExtrinsic; - -// The indirect pallet call used to sync `Polkadot` GRANDPA finality to `BHKusama`. -pub type BridgePolkadotGrandpaCall = BridgeGrandpaCallOf; -// The indirect pallet call used to sync `BridgeHubPolkadot` messages to `BHKusama`. -pub type BridgePolkadotMessagesCall = - BridgeMessagesCallOf; - -/// `BridgeHubKusama` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `BridgeHubKusama` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `BridgeHubKusama` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - #[cfg(test)] - #[codec(index = 0)] - System(SystemCall), - /// Utility pallet. - #[codec(index = 40)] - Utility(UtilityCall), - - /// Polkadot bridge pallet. - #[codec(index = 51)] - BridgePolkadotGrandpa(BridgePolkadotGrandpaCall), - /// Polkadot parachain bridge pallet. - #[codec(index = 52)] - BridgePolkadotParachain(BridgeParachainCall), - /// Polkadot messages bridge pallet. - #[codec(index = 53)] - BridgePolkadotMessages(BridgePolkadotMessagesCall), -} - -impl From> for Call { - fn from(call: UtilityCall) -> Call { - Call::Utility(call) - } -} diff --git a/relays/client-bridge-hub-polkadot/Cargo.toml b/relays/client-bridge-hub-polkadot/Cargo.toml deleted file mode 100644 index abfd5bae4f025..0000000000000 --- a/relays/client-bridge-hub-polkadot/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "relay-bridge-hub-polkadot-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-bridge-hub-polkadot = { path = "../../chains/chain-bridge-hub-polkadot" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot = { path = "../../chains/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-kusama = { path = "../../chains/chain-kusama" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-substrate-client = { path = "../client-substrate" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs b/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs deleted file mode 100644 index 1ce9d0588024a..0000000000000 --- a/relays/client-bridge-hub-polkadot/src/codegen_runtime.rs +++ /dev/null @@ -1,4056 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url -//! wss://polkadot-bridge-hub-rpc.polkadot.io - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -#[allow(rustdoc::broken_intra_doc_links)] -pub mod api { - #[allow(unused_imports)] - mod root_mod { - pub use super::*; - } - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod bp_header_chain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AuthoritySet { - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HeaderChainError { - #[codec(index = 0)] - UnknownHeader, - #[codec(index = 1)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderFinalityInfo<_0, _1> { - pub finality_proof: _0, - pub new_verification_context: ::core::option::Option<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredHeaderData<_0, _1> { - pub number: _0, - pub state_root: _1, - } - } - pub mod bp_messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DeliveredMessages { - pub begin: ::core::primitive::u64, - pub end: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundLaneData<_0> { - pub relayers: ::std::vec::Vec>, - pub last_confirmed_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundMessageDetails { - pub dispatch_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageKey { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MessagesOperatingMode { - #[codec(index = 0)] - Basic(runtime_types::bp_runtime::BasicOperatingMode), - #[codec(index = 1)] - RejectingOutboundMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundLaneData { - pub oldest_unpruned_nonce: ::core::primitive::u64, - pub latest_received_nonce: ::core::primitive::u64, - pub latest_generated_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundMessageDetails { - pub nonce: ::core::primitive::u64, - pub dispatch_weight: ::sp_weights::Weight, - pub size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalResult<_0> { - #[codec(index = 0)] - Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), - #[codec(index = 1)] - InvalidNonce, - #[codec(index = 2)] - TooManyUnrewardedRelayers, - #[codec(index = 3)] - TooManyUnconfirmedMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceivedMessages<_0> { - pub lane: runtime_types::bp_messages::LaneId, - pub receive_results: ::std::vec::Vec<( - ::core::primitive::u64, - runtime_types::bp_messages::ReceivalResult<_0>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnrewardedRelayer<_0> { - pub relayer: _0, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VerificationError { - #[codec(index = 0)] - EmptyMessageProof, - #[codec(index = 1)] - HeaderChain(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 2)] - InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 3)] - InvalidMessageWeight, - #[codec(index = 4)] - MessagesCountMismatch, - #[codec(index = 5)] - MessageStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 6)] - MessageTooLarge, - #[codec(index = 7)] - OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 8)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 9)] - Other, - } - } - pub mod bp_parachains { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BestParaHeadHash { - pub at_relay_block_number: ::core::primitive::u32, - pub head_hash: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo { - pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, - pub next_imported_hash_position: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod bp_relayers { - use super::runtime_types; - pub mod registration { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0, _1> { - pub valid_till: _0, - pub stake: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardsAccountOwner { - #[codec(index = 0)] - ThisChain, - #[codec(index = 1)] - BridgedChain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardsAccountParams { - pub lane_id: runtime_types::bp_messages::LaneId, - pub bridged_chain_id: [::core::primitive::u8; 4usize], - pub owner: runtime_types::bp_relayers::RewardsAccountOwner, - } - } - pub mod bp_runtime { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageDispatchResult<_0> { - pub unspent_weight: ::sp_weights::Weight, - pub dispatch_level_result: _0, - } - } - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateNodesInProof, - #[codec(index = 1)] - UnusedNodesInTheProof, - #[codec(index = 2)] - StorageRootMismatch, - #[codec(index = 3)] - StorageValueUnavailable, - #[codec(index = 4)] - StorageValueEmpty, - #[codec(index = 5)] - StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OwnedBridgeModuleError { - #[codec(index = 0)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StrippableError; - } - pub mod bridge_hub_polkadot_runtime { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::sp_core::crypto::AccountId32, - >, - ), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), - #[codec(index = 3)] - Void(runtime_types::sp_core::Void), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Call), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 41)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 50)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), - #[codec(index = 51)] - BridgeKusamaGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 52)] - BridgeKusamaParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 53)] - BridgeKusamaMessages(runtime_types::pallet_bridge_messages::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeError { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Error), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Error), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Error), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Error), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Error), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Error), - #[codec(index = 41)] - Multisig(runtime_types::pallet_multisig::pallet::Error), - #[codec(index = 50)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), - #[codec(index = 51)] - BridgeKusamaGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), - #[codec(index = 52)] - BridgeKusamaParachains(runtime_types::pallet_bridge_parachains::pallet::Error), - #[codec(index = 53)] - BridgeKusamaMessages(runtime_types::pallet_bridge_messages::pallet::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 11)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), - #[codec(index = 33)] - DmpQueue(runtime_types::cumulus_pallet_dmp_queue::pallet::Event), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 41)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 50)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), - #[codec(index = 51)] - BridgeKusamaGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 52)] - BridgeKusamaParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 53)] - BridgeKusamaMessages(runtime_types::pallet_bridge_messages::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeHoldReason {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, - } - } - pub mod bridge_runtime_common { - use super::runtime_types; - pub mod messages_xcm_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmBlobMessageDispatchResult { - #[codec(index = 0)] - InvalidPayload, - #[codec(index = 1)] - Dispatched, - #[codec(index = 2)] - NotDispatched, - } - } - pub mod refund_relayer_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundBridgedParachainMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundTransactionExtensionAdapter<_0>(pub _0); - } - } - pub mod cumulus_pallet_dmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - OverLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 1)] - UnsupportedVersion { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 2)] - ExecutedDownward { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - outcome: runtime_types::xcm::v3::traits::Outcome, - }, - #[codec(index = 3)] - WeightExhausted { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - remaining_weight: ::sp_weights::Weight, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - OverweightEnqueued { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - overweight_index: ::core::primitive::u64, - required_weight: ::sp_weights::Weight, - }, - #[codec(index = 5)] - OverweightServiced { - overweight_index: ::core::primitive::u64, - weight_used: ::sp_weights::Weight, - }, - #[codec(index = 6)] - MaxMessagesExhausted { message_hash: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ConfigData { - pub max_individual: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PageIndexData { - pub begin_used: ::core::primitive::u32, - pub end_used: ::core::primitive::u32, - pub overweight_count: ::core::primitive::u64, - } - } - pub mod cumulus_pallet_parachain_system { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OverlappingUpgrades, - #[codec(index = 1)] - ProhibitedByPolkadot, - #[codec(index = 2)] - TooBig, - #[codec(index = 3)] - ValidationDataNotAvailable, - #[codec(index = 4)] - HostConfigurationNotAvailable, - #[codec(index = 5)] - NotScheduled, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidationFunctionStored, - #[codec(index = 1)] - ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, - #[codec(index = 2)] - ValidationFunctionDiscarded, - #[codec(index = 3)] - UpgradeAuthorized { code_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - DownwardMessagesReceived { count: ::core::primitive::u32 }, - #[codec(index = 5)] - DownwardMessagesProcessed { - weight_used: ::sp_weights::Weight, - dmq_head: ::subxt::utils::H256, - }, - #[codec(index = 6)] - UpwardMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - pub mod relay_state_snapshot { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RelayDispatchQueueRemainingCapacity { - pub remaining_count: ::core::primitive::u32, - pub remaining_size: ::core::primitive::u32, - } - } - pub mod unincluded_segment { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelUpdate { - pub msg_count: ::core::primitive::u32, - pub total_bytes: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CodeUpgradeAuthorization { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } - } - pub mod cumulus_pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - UnsupportedVersion([::core::primitive::u8; 32usize]), - #[codec(index = 2)] - ExecutedDownward( - [::core::primitive::u8; 32usize], - runtime_types::xcm::v3::traits::Outcome, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Relay, - #[codec(index = 1)] - SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), - } - } - } - pub mod cumulus_pallet_xcmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - service_overweight { - index: ::core::primitive::u64, - weight_limit: ::sp_weights::Weight, - }, - #[codec(index = 1)] - suspend_xcm_execution, - #[codec(index = 2)] - resume_xcm_execution, - #[codec(index = 3)] - update_suspend_threshold { new: ::core::primitive::u32 }, - #[codec(index = 4)] - update_drop_threshold { new: ::core::primitive::u32 }, - #[codec(index = 5)] - update_resume_threshold { new: ::core::primitive::u32 }, - #[codec(index = 6)] - update_threshold_weight { new: ::sp_weights::Weight }, - #[codec(index = 7)] - update_weight_restrict_decay { new: ::sp_weights::Weight }, - #[codec(index = 8)] - update_xcmp_max_individual_weight { new: ::sp_weights::Weight }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSend, - #[codec(index = 1)] - BadXcmOrigin, - #[codec(index = 2)] - BadXcm, - #[codec(index = 3)] - BadOverweightIndex, - #[codec(index = 4)] - WeightOverLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Success { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - weight: ::sp_weights::Weight, - }, - #[codec(index = 1)] - Fail { - message_hash: [::core::primitive::u8; 32usize], - message_id: [::core::primitive::u8; 32usize], - error: runtime_types::xcm::v3::traits::Error, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - BadVersion { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 3)] - BadFormat { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 4)] - XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, - #[codec(index = 5)] - OverweightEnqueued { - sender: runtime_types::polkadot_parachain_primitives::primitives::Id, - sent_at: ::core::primitive::u32, - index: ::core::primitive::u64, - required: ::sp_weights::Weight, - }, - #[codec(index = 6)] - OverweightServiced { index: ::core::primitive::u64, used: ::sp_weights::Weight }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundChannelDetails { - pub sender: runtime_types::polkadot_parachain_primitives::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::InboundState, - pub message_metadata: ::std::vec::Vec<( - ::core::primitive::u32, - runtime_types::polkadot_parachain_primitives::primitives::XcmpMessageFormat, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundChannelDetails { - pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, - pub signals_exist: ::core::primitive::bool, - pub first_index: ::core::primitive::u16, - pub last_index: ::core::primitive::u16, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OutboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueueConfigData { - pub suspend_threshold: ::core::primitive::u32, - pub drop_threshold: ::core::primitive::u32, - pub resume_threshold: ::core::primitive::u32, - pub threshold_weight: ::sp_weights::Weight, - pub weight_restrict_decay: ::sp_weights::Weight, - pub xcmp_max_individual_weight: ::sp_weights::Weight, - } - } - pub mod cumulus_primitives_core { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CollationInfo { - pub upward_messages: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub horizontal_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain_primitives::primitives::Id, - >, - >, - pub new_validation_code: ::core::option::Option< - runtime_types::polkadot_parachain_primitives::primitives::ValidationCode, - >, - pub processed_downward_messages: ::core::primitive::u32, - pub hrmp_watermark: ::core::primitive::u32, - pub head_data: runtime_types::polkadot_parachain_primitives::primitives::HeadData, - } - } - pub mod cumulus_primitives_parachain_inherent { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainInherentData { - pub validation_data: - runtime_types::polkadot_primitives::v6::PersistedValidationData< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, - pub downward_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundDownwardMessage< - ::core::primitive::u32, - >, - >, - pub horizontal_messages: ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain_primitives::primitives::Id, - ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundHrmpMessage< - ::core::primitive::u32, - >, - >, - >, - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commit<_0, _1, _2, _3> { - pub target_hash: _0, - pub target_number: _1, - pub precommits: ::std::vec::Vec< - runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedPrecommit<_0, _1, _2, _3> { - pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, - pub signature: _2, - pub id: _3, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: ::core::primitive::u32, - pub providers: ::core::primitive::u32, - pub sufficients: ::core::primitive::u32, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bridge_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u32, - hash: ::subxt::utils::H256, - grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< - ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - runtime_types::bp_header_chain::AuthoritySet, - >, - }, - } - } - pub mod storage_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - } - } - pub mod pallet_bridge_messages { - use super::runtime_types; - pub mod outbound_lane { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalConfirmationError { - #[codec(index = 0)] - FailedToConfirmFutureMessages, - #[codec(index = 1)] - EmptyUnrewardedRelayerEntry, - #[codec(index = 2)] - NonConsecutiveUnrewardedRelayerEntries, - #[codec(index = 3)] - TryingToConfirmMoreMessagesThanExpected, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - } - } - pub mod pallet_bridge_parachains { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_parachain_heads { - at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), - parachains: ::std::vec::Vec<( - ::bp_polkadot_core::parachains::ParaId, - ::subxt::utils::H256, - )>, - parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, - }, - #[codec(index = 1)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 2)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnknownRelayChainBlock, - #[codec(index = 1)] - InvalidRelayChainBlockNumber, - #[codec(index = 2)] - HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 3)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 1)] - MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 2)] - IncorrectParachainHeadHash { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - actual_parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - RejectedObsoleteParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 4)] - RejectedLargeParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - parachain_head_size: ::core::primitive::u32, - }, - #[codec(index = 5)] - UpdatedParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - } - } - } - pub mod pallet_bridge_relayers { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim_rewards { - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - }, - #[codec(index = 1)] - register { valid_till: ::core::primitive::u32 }, - #[codec(index = 2)] - deregister, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NoRewardForRelayer, - #[codec(index = 1)] - FailedToPayReward, - #[codec(index = 2)] - InvalidRegistrationLease, - #[codec(index = 3)] - CannotReduceRegistrationLease, - #[codec(index = 4)] - FailedToReserve, - #[codec(index = 5)] - FailedToUnreserve, - #[codec(index = 6)] - NotRegistered, - #[codec(index = 7)] - RegistrationIsStillActive, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RewardPaid { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 1)] - RegistrationUpdated { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - #[codec(index = 2)] - Deregistered { relayer: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - SlashedAndDeregistered { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - } - } - } - pub mod pallet_collator_selection { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 1)] - set_desired_candidates { max: ::core::primitive::u32 }, - #[codec(index = 2)] - set_candidacy_bond { bond: ::core::primitive::u128 }, - #[codec(index = 3)] - register_as_candidate, - #[codec(index = 4)] - leave_intent, - #[codec(index = 5)] - add_invulnerable { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateInfo<_0, _1> { - pub who: _0, - pub deposit: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCandidates, - #[codec(index = 1)] - TooFewEligibleCollators, - #[codec(index = 2)] - AlreadyCandidate, - #[codec(index = 3)] - NotCandidate, - #[codec(index = 4)] - TooManyInvulnerables, - #[codec(index = 5)] - AlreadyInvulnerable, - #[codec(index = 6)] - NotInvulnerable, - #[codec(index = 7)] - NoAssociatedValidatorId, - #[codec(index = 8)] - ValidatorNotRegistered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewInvulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 1)] - InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 2)] - InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, - #[codec(index = 4)] - NewCandidacyBond { bond_amount: ::core::primitive::u128 }, - #[codec(index = 5)] - CandidateAdded { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 6)] - CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 7)] - InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, - } - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: ::core::primitive::u32, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::bridge_hub_polkadot_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FeeDetails<_0> { - pub inclusion_fee: ::core::option::Option< - runtime_types::pallet_transaction_payment::types::InclusionFee<_0>, - >, - pub tip: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InclusionFee<_0> { - pub base_fee: _0, - pub len_fee: _0, - pub adjusted_weight_fee: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDispatchInfo<_0, _1> { - pub weight: _1, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub partial_fee: _0, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { - calls: ::std::vec::Vec< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 2)] - batch_all { - calls: ::std::vec::Vec< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box< - runtime_types::bridge_hub_polkadot_runtime::OriginCaller, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 4)] - force_batch { - calls: ::std::vec::Vec< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box< - runtime_types::bridge_hub_polkadot_runtime::RuntimeCall, - >, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: ::std::boxed::Box< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted { outcome: runtime_types::xcm::v3::traits::Outcome }, - #[codec(index = 1)] - Sent { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - message: runtime_types::xcm::v3::Xcm, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - UnexpectedResponse { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 3)] - ResponseReady { - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - }, - #[codec(index = 4)] - Notified { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 5)] - NotifyOverweight { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - actual_weight: ::sp_weights::Weight, - max_budgeted_weight: ::sp_weights::Weight, - }, - #[codec(index = 6)] - NotifyDispatchError { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 7)] - NotifyDecodeFailed { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 8)] - InvalidResponder { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - expected_location: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 9)] - InvalidResponderVersion { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 10)] - ResponseTaken { query_id: ::core::primitive::u64 }, - #[codec(index = 11)] - AssetsTrapped { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - }, - #[codec(index = 12)] - VersionChangeNotified { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - result: ::core::primitive::u32, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 13)] - SupportedVersionChanged { - location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - version: ::core::primitive::u32, - }, - #[codec(index = 14)] - NotifyTargetSendFail { - location: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - error: runtime_types::xcm::v3::traits::Error, - }, - #[codec(index = 15)] - NotifyTargetMigrationFail { - location: runtime_types::xcm::VersionedMultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 16)] - InvalidQuerierVersion { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 17)] - InvalidQuerier { - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - query_id: ::core::primitive::u64, - expected_querier: - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - maybe_actual_querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 18)] - VersionNotifyStarted { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 19)] - VersionNotifyRequested { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 20)] - VersionNotifyUnrequested { - destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - cost: runtime_types::xcm::v3::multiasset::MultiAssets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 21)] - FeesPaid { - paying: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - fees: runtime_types::xcm::v3::multiasset::MultiAssets, - }, - #[codec(index = 22)] - AssetsClaimed { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - assets: runtime_types::xcm::VersionedMultiAssets, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Response(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedMultiLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain_primitives { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmpMessageFormat { - #[codec(index = 0)] - ConcatenatedVersionedXcm, - #[codec(index = 1)] - ConcatenatedEncodedBlob, - #[codec(index = 2)] - Signals, - } - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v6 { - use super::runtime_types; - pub mod async_backing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHostConfiguration { - pub max_code_size: ::core::primitive::u32, - pub max_head_data_size: ::core::primitive::u32, - pub max_upward_queue_count: ::core::primitive::u32, - pub max_upward_queue_size: ::core::primitive::u32, - pub max_upward_message_size: ::core::primitive::u32, - pub max_upward_message_num_per_candidate: ::core::primitive::u32, - pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, - pub validation_upgrade_cooldown: ::core::primitive::u32, - pub validation_upgrade_delay: ::core::primitive::u32, - pub async_backing_params: - runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PersistedValidationData<_0, _1> { - pub parent_head: - runtime_types::polkadot_parachain_primitives::primitives::HeadData, - pub relay_parent_number: _1, - pub relay_parent_storage_root: _0, - pub max_pov_size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_consensus_aura { - use super::runtime_types; - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct SlotDuration(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMetadata(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_inherents { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckInherentsResult { - pub okay: ::core::primitive::bool, - pub fatal_error: ::core::primitive::bool, - pub errors: runtime_types::sp_inherents::InherentData, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData { - pub data: ::subxt::utils::KeyedVec< - [::core::primitive::u8; 8usize], - ::std::vec::Vec<::core::primitive::u8>, - >, - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod block { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Block<_0, _1> { - pub header: _0, - pub extrinsics: ::std::vec::Vec<_1>, - } - } - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - } - pub mod transaction_validity { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidTransaction { - #[codec(index = 0)] - Call, - #[codec(index = 1)] - Payment, - #[codec(index = 2)] - Future, - #[codec(index = 3)] - Stale, - #[codec(index = 4)] - BadProof, - #[codec(index = 5)] - AncientBirthBlock, - #[codec(index = 6)] - ExhaustsResources, - #[codec(index = 7)] - Custom(::core::primitive::u8), - #[codec(index = 8)] - BadMandatory, - #[codec(index = 9)] - MandatoryValidation, - #[codec(index = 10)] - BadSigner, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionSource { - #[codec(index = 0)] - InBlock, - #[codec(index = 1)] - Local, - #[codec(index = 2)] - External, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionValidityError { - #[codec(index = 0)] - Invalid(runtime_types::sp_runtime::transaction_validity::InvalidTransaction), - #[codec(index = 1)] - Unknown(runtime_types::sp_runtime::transaction_validity::UnknownTransaction), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UnknownTransaction { - #[codec(index = 0)] - CannotLookup, - #[codec(index = 1)] - NoUnsignedValidator, - #[codec(index = 2)] - Custom(::core::primitive::u8), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidTransaction { - pub priority: ::core::primitive::u64, - pub requires: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub provides: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub longevity: ::core::primitive::u64, - pub propagate: ::core::primitive::bool, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_trie { - use super::runtime_types; - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StorageProof { - pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod staging_xcm { - use super::runtime_types; - pub mod v3 { - use super::runtime_types; - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded2 { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm2 { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm2), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm2), - } - } - } -} diff --git a/relays/client-bridge-hub-polkadot/src/lib.rs b/relays/client-bridge-hub-polkadot/src/lib.rs deleted file mode 100644 index 88b69065f8421..0000000000000 --- a/relays/client-bridge-hub-polkadot/src/lib.rs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2022 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 . - -//! Types used to connect to the BridgeHub-Polkadot-Substrate parachain. - -pub mod codegen_runtime; - -use bp_bridge_hub_polkadot::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use codec::Encode; -use relay_substrate_client::{ - calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, - UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::bridge_hub_polkadot_runtime::RuntimeCall; -// TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - regenerate when ready -pub type BridgePolkadotBulletinMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; -pub type BridgeKusamaMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; -// TODO: https://github.com/paritytech/parity-bridges-common/issues/2547 - regenerate when ready -pub type BridgePolkadotBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeKusamaGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; -type UtilityCall = runtime_types::pallet_utility::pallet::Call; - -/// Polkadot chain definition -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct BridgeHubPolkadot; - -impl UnderlyingChainProvider for BridgeHubPolkadot { - type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; -} - -impl Chain for BridgeHubPolkadot { - const NAME: &'static str = "BridgeHubPolkadot"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_bridge_hub_polkadot::BEST_FINALIZED_BRIDGE_HUB_POLKADOT_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = bp_bridge_hub_polkadot::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithBalances for BridgeHubPolkadot { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_bridge_hub_polkadot::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl From> for RuntimeCall { - fn from(value: MockUtilityCall) -> RuntimeCall { - match value { - MockUtilityCall::batch_all(calls) => - RuntimeCall::Utility(UtilityCall::batch_all { calls }), - } - } -} - -impl ChainWithUtilityPallet for BridgeHubPolkadot { - type UtilityPallet = MockedRuntimeUtilityPallet; -} - -impl ChainWithTransactions for BridgeHubPolkadot { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - (((), ()), ((), ())), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(UncheckedExtrinsic::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithMessages for BridgeHubPolkadot { - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = - Some(bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME); - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_polkadot::TO_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_polkadot::FROM_BRIDGE_HUB_POLKADOT_MESSAGE_DETAILS_METHOD; -} - -impl ChainWithRuntimeVersion for BridgeHubPolkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_000, transaction_version: 3 }); -} diff --git a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs b/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs deleted file mode 100644 index f59b35253b1ba..0000000000000 --- a/relays/client-bridge-hub-polkadot/src/runtime_wrapper.rs +++ /dev/null @@ -1,130 +0,0 @@ -// 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 . - -//! Types that are specific to the BridgeHubPolkadot runtime. -// TODO: regenerate me using `runtime-codegen` tool? (https://github.com/paritytech/parity-bridges-common/issues/1945) - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; - -pub use bp_bridge_hub_polkadot::TransactionExtension; -pub use bp_header_chain::BridgeGrandpaCallOf; -pub use bp_parachains::BridgeParachainCall; -pub use bridge_runtime_common::messages::BridgeMessagesCallOf; -pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; - -/// Unchecked BridgeHubPolkadot extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_polkadot::UncheckedExtrinsic; - -/// The indirect pallet call used to sync `Kusama` GRANDPA finality to `BHPolkadot`. -pub type BridgeKusamaGrandpaCall = BridgeGrandpaCallOf; -/// The indirect pallet call used to sync `BridgeHubKusama` messages to `BridgeHubPolkadot`. -pub type BridgeKusamaMessagesCall = BridgeMessagesCallOf; - -/// The indirect pallet call used to sync `PolkadotBulletin` GRANDPA finality to `BHPolkadot`. -pub type BridgePolkadotBulletinGrandpaCall = - BridgeGrandpaCallOf; -/// The indirect pallet call used to sync `PolkadotBulletin` messages to `BridgeHubPolkadot`. -pub type BridgePolkadotBulletinMessagesCall = - BridgeMessagesCallOf; - -/// `BridgeHubPolkadot` Runtime `Call` enum. -/// -/// The enum represents a subset of possible `Call`s we can send to `BridgeHubPolkadot` chain. -/// Ideally this code would be auto-generated from metadata, because we want to -/// avoid depending directly on the ENTIRE runtime just to get the encoding of `Dispatchable`s. -/// -/// All entries here (like pretty much in the entire file) must be kept in sync with -/// `BridgeHubPolkadot` `construct_runtime`, so that we maintain SCALE-compatibility. -#[allow(clippy::large_enum_variant)] -#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)] -pub enum Call { - #[cfg(test)] - #[codec(index = 0)] - System(SystemCall), - /// Utility pallet. - #[codec(index = 40)] - Utility(UtilityCall), - - /// Kusama grandpa bridge pallet. - #[codec(index = 51)] - BridgeKusamaGrandpa(BridgeKusamaGrandpaCall), - /// Kusama parachains bridge pallet. - #[codec(index = 52)] - BridgeKusamaParachain(BridgeParachainCall), - /// Kusama messages bridge pallet. - #[codec(index = 53)] - BridgeKusamaMessages(BridgeKusamaMessagesCall), - - /// Polkadot Bulletin grandpa bridge pallet. - #[codec(index = 55)] - BridgePolkadotBulletinGrandpa(BridgePolkadotBulletinGrandpaCall), - /// Polkadot Bulletin messages bridge pallet. - #[codec(index = 56)] - BridgePolkadotBulletinMessages(BridgePolkadotBulletinMessagesCall), -} - -impl From> for Call { - fn from(call: UtilityCall) -> Call { - Call::Utility(call) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use bp_runtime::BasicOperatingMode; - use sp_consensus_grandpa::AuthorityList; - use sp_core::hexdisplay::HexDisplay; - use sp_runtime::traits::Header; - use std::str::FromStr; - - pub type RelayBlockNumber = bp_polkadot_core::BlockNumber; - pub type RelayBlockHasher = bp_polkadot_core::Hasher; - pub type RelayBlockHeader = sp_runtime::generic::Header; - - #[test] - fn encode_decode_calls() { - let header = RelayBlockHeader::new( - 75, - bp_polkadot_core::Hash::from_str( - "0xd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0x92b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141b", - ) - .expect("invalid value"), - bp_polkadot_core::Hash::from_str( - "0xae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d", - ) - .expect("invalid value"), - Default::default(), - ); - let init_data = bp_header_chain::InitializationData { - header: Box::new(header), - authority_list: AuthorityList::default(), - set_id: 6, - operating_mode: BasicOperatingMode::Normal, - }; - let call = BridgeKusamaGrandpaCall::initialize { init_data }; - let tx = Call::BridgeKusamaGrandpa(call); - - // encode call as hex string - let hex_encoded_call = format!("0x{:?}", HexDisplay::from(&Encode::encode(&tx))); - assert_eq!(hex_encoded_call, "0x3301ae4a25acf250d72ed02c149ecc7dd3c9ee976d41a2888fc551de8064521dc01d2d0192b965f0656a4e0e5fc0167da2d4b5ee72b3be2c1583c4c1e5236c8c12aa141bd2c0afaab32de0cb8f7f0d89217e37c5ea302c1ffb5a7a83e10d20f12c32874d0000060000000000000000"); - } -} diff --git a/relays/client-bridge-hub-rococo/Cargo.toml b/relays/client-bridge-hub-rococo/Cargo.toml deleted file mode 100644 index 70d65ac19453c..0000000000000 --- a/relays/client-bridge-hub-rococo/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "relay-bridge-hub-rococo-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-bridge-hub-rococo = { path = "../../chains/chain-bridge-hub-rococo" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } - -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-substrate-client = { path = "../client-substrate" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs b/relays/client-bridge-hub-rococo/src/codegen_runtime.rs deleted file mode 100644 index e5c7c8b3e7679..0000000000000 --- a/relays/client-bridge-hub-rococo/src/codegen_runtime.rs +++ /dev/null @@ -1,5506 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-wasm-file -//! ../../../polkadot-sdk/target/release/wbuild/bridge-hub-rococo-runtime/bridge_hub_rococo_runtime. -//! compact.compressed.wasm - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -#[allow(rustdoc::broken_intra_doc_links)] -pub mod api { - #[allow(unused_imports)] - mod root_mod { - pub use super::*; - } - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_btree_set { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedBTreeSet<_0>(pub ::std::vec::Vec<_0>); - } - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod bp_header_chain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AuthoritySet { - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HeaderChainError { - #[codec(index = 0)] - UnknownHeader, - #[codec(index = 1)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderFinalityInfo<_0, _1> { - pub finality_proof: _0, - pub new_verification_context: ::core::option::Option<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredHeaderData<_0, _1> { - pub number: _0, - pub state_root: _1, - } - } - pub mod bp_messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DeliveredMessages { - pub begin: ::core::primitive::u64, - pub end: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundLaneData<_0> { - pub relayers: ::std::vec::Vec>, - pub last_confirmed_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageKey { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MessagesOperatingMode { - #[codec(index = 0)] - Basic(runtime_types::bp_runtime::BasicOperatingMode), - #[codec(index = 1)] - RejectingOutboundMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundLaneData { - pub oldest_unpruned_nonce: ::core::primitive::u64, - pub latest_received_nonce: ::core::primitive::u64, - pub latest_generated_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalResult<_0> { - #[codec(index = 0)] - Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), - #[codec(index = 1)] - InvalidNonce, - #[codec(index = 2)] - TooManyUnrewardedRelayers, - #[codec(index = 3)] - TooManyUnconfirmedMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceivedMessages<_0> { - pub lane: runtime_types::bp_messages::LaneId, - pub receive_results: ::std::vec::Vec<( - ::core::primitive::u64, - runtime_types::bp_messages::ReceivalResult<_0>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnrewardedRelayer<_0> { - pub relayer: _0, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VerificationError { - #[codec(index = 0)] - EmptyMessageProof, - #[codec(index = 1)] - HeaderChain(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 2)] - InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 3)] - InvalidMessageWeight, - #[codec(index = 4)] - MessagesCountMismatch, - #[codec(index = 5)] - MessageStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 6)] - MessageTooLarge, - #[codec(index = 7)] - OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 8)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 9)] - Other, - } - } - pub mod bp_parachains { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BestParaHeadHash { - pub at_relay_block_number: ::core::primitive::u32, - pub head_hash: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo { - pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, - pub next_imported_hash_position: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod bp_relayers { - use super::runtime_types; - pub mod registration { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0, _1> { - pub valid_till: _0, - pub stake: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardsAccountOwner { - #[codec(index = 0)] - ThisChain, - #[codec(index = 1)] - BridgedChain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardsAccountParams { - pub lane_id: runtime_types::bp_messages::LaneId, - pub bridged_chain_id: [::core::primitive::u8; 4usize], - pub owner: runtime_types::bp_relayers::RewardsAccountOwner, - } - } - pub mod bp_runtime { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageDispatchResult<_0> { - pub unspent_weight: ::sp_weights::Weight, - pub dispatch_level_result: _0, - } - } - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateNodesInProof, - #[codec(index = 1)] - UnusedNodesInTheProof, - #[codec(index = 2)] - StorageRootMismatch, - #[codec(index = 3)] - StorageValueUnavailable, - #[codec(index = 4)] - StorageValueEmpty, - #[codec(index = 5)] - StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OwnedBridgeModuleError { - #[codec(index = 0)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StrippableError; - } - pub mod bridge_hub_common { - use super::runtime_types; - pub mod message_queue { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - Parent, - #[codec(index = 2)] - Sibling(runtime_types::polkadot_parachain_primitives::primitives::Id), - #[codec(index = 3)] - Snowbridge(runtime_types::snowbridge_core::ChannelId), - } - } - } - pub mod bridge_hub_rococo_runtime { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::sp_core::crypto::AccountId32, - >, - ), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), - #[codec(index = 3)] - Void(runtime_types::sp_core::Void), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 3)] - ParachainInfo(runtime_types::staging_parachain_info::pallet::Call), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Call), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 36)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 47)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), - #[codec(index = 48)] - BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 49)] - BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 51)] - BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Call), - #[codec(index = 60)] - BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call2), - #[codec(index = 61)] - BridgePolkadotBulletinMessages( - runtime_types::pallet_bridge_messages::pallet::Call2, - ), - #[codec(index = 80)] - EthereumInboundQueue(runtime_types::snowbridge_pallet_inbound_queue::pallet::Call), - #[codec(index = 81)] - EthereumOutboundQueue( - runtime_types::snowbridge_pallet_outbound_queue::pallet::Call, - ), - #[codec(index = 82)] - EthereumBeaconClient( - runtime_types::snowbridge_pallet_ethereum_client::pallet::Call, - ), - #[codec(index = 83)] - EthereumSystem(runtime_types::snowbridge_pallet_system::pallet::Call), - #[codec(index = 250)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeError { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Error), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Error), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Error), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Error), - #[codec(index = 36)] - Multisig(runtime_types::pallet_multisig::pallet::Error), - #[codec(index = 47)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), - #[codec(index = 48)] - BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), - #[codec(index = 49)] - BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Error), - #[codec(index = 51)] - BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Error), - #[codec(index = 60)] - BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error2), - #[codec(index = 61)] - BridgePolkadotBulletinMessages( - runtime_types::pallet_bridge_messages::pallet::Error2, - ), - #[codec(index = 80)] - EthereumInboundQueue(runtime_types::snowbridge_pallet_inbound_queue::pallet::Error), - #[codec(index = 81)] - EthereumOutboundQueue( - runtime_types::snowbridge_pallet_outbound_queue::pallet::Error, - ), - #[codec(index = 82)] - EthereumBeaconClient( - runtime_types::snowbridge_pallet_ethereum_client::pallet::Error, - ), - #[codec(index = 83)] - EthereumSystem(runtime_types::snowbridge_pallet_system::pallet::Error), - #[codec(index = 250)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 11)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 36)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 47)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), - #[codec(index = 48)] - BridgeWestendGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 49)] - BridgeWestendParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 51)] - BridgeWestendMessages(runtime_types::pallet_bridge_messages::pallet::Event), - #[codec(index = 60)] - BridgePolkadotBulletinGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event2), - #[codec(index = 61)] - BridgePolkadotBulletinMessages( - runtime_types::pallet_bridge_messages::pallet::Event2, - ), - #[codec(index = 80)] - EthereumInboundQueue(runtime_types::snowbridge_pallet_inbound_queue::pallet::Event), - #[codec(index = 81)] - EthereumOutboundQueue( - runtime_types::snowbridge_pallet_outbound_queue::pallet::Event, - ), - #[codec(index = 82)] - EthereumBeaconClient( - runtime_types::snowbridge_pallet_ethereum_client::pallet::Event, - ), - #[codec(index = 83)] - EthereumSystem(runtime_types::snowbridge_pallet_system::pallet::Event), - #[codec(index = 250)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeHoldReason {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, - } - } - pub mod bridge_runtime_common { - use super::runtime_types; - pub mod messages_xcm_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmBlobMessageDispatchResult { - #[codec(index = 0)] - InvalidPayload, - #[codec(index = 1)] - Dispatched, - #[codec(index = 2)] - NotDispatched, - } - } - pub mod refund_relayer_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundBridgedGrandpaMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundBridgedParachainMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundTransactionExtensionAdapter<_0>(pub _0); - } - } - pub mod cumulus_pallet_parachain_system { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OverlappingUpgrades, - #[codec(index = 1)] - ProhibitedByPolkadot, - #[codec(index = 2)] - TooBig, - #[codec(index = 3)] - ValidationDataNotAvailable, - #[codec(index = 4)] - HostConfigurationNotAvailable, - #[codec(index = 5)] - NotScheduled, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidationFunctionStored, - #[codec(index = 1)] - ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, - #[codec(index = 2)] - ValidationFunctionDiscarded, - #[codec(index = 3)] - DownwardMessagesReceived { count: ::core::primitive::u32 }, - #[codec(index = 4)] - DownwardMessagesProcessed { - weight_used: ::sp_weights::Weight, - dmq_head: ::subxt::utils::H256, - }, - #[codec(index = 5)] - UpwardMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - pub mod relay_state_snapshot { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RelayDispatchQueueRemainingCapacity { - pub remaining_count: ::core::primitive::u32, - pub remaining_size: ::core::primitive::u32, - } - } - pub mod unincluded_segment { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelUpdate { - pub msg_count: ::core::primitive::u32, - pub total_bytes: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } - } - } - pub mod cumulus_pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - UnsupportedVersion([::core::primitive::u8; 32usize]), - #[codec(index = 2)] - ExecutedDownward( - [::core::primitive::u8; 32usize], - runtime_types::staging_xcm::v4::traits::Outcome, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Relay, - #[codec(index = 1)] - SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), - } - } - } - pub mod cumulus_pallet_xcmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 1)] - suspend_xcm_execution, - #[codec(index = 2)] - resume_xcm_execution, - #[codec(index = 3)] - update_suspend_threshold { new: ::core::primitive::u32 }, - #[codec(index = 4)] - update_drop_threshold { new: ::core::primitive::u32 }, - #[codec(index = 5)] - update_resume_threshold { new: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - BadQueueConfig, - #[codec(index = 1)] - AlreadySuspended, - #[codec(index = 2)] - AlreadyResumed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundChannelDetails { - pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, - pub signals_exist: ::core::primitive::bool, - pub first_index: ::core::primitive::u16, - pub last_index: ::core::primitive::u16, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OutboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueueConfigData { - pub suspend_threshold: ::core::primitive::u32, - pub drop_threshold: ::core::primitive::u32, - pub resume_threshold: ::core::primitive::u32, - } - } - pub mod cumulus_primitives_parachain_inherent { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainInherentData { - pub validation_data: - runtime_types::polkadot_primitives::v6::PersistedValidationData< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, - pub downward_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundDownwardMessage< - ::core::primitive::u32, - >, - >, - pub horizontal_messages: ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain_primitives::primitives::Id, - ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundHrmpMessage< - ::core::primitive::u32, - >, - >, - >, - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commit<_0, _1, _2, _3> { - pub target_hash: _0, - pub target_number: _1, - pub precommits: ::std::vec::Vec< - runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedPrecommit<_0, _1, _2, _3> { - pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, - pub signature: _2, - pub id: _3, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProcessMessageError { - #[codec(index = 0)] - BadFormat, - #[codec(index = 1)] - Corrupt, - #[codec(index = 2)] - Unsupported, - #[codec(index = 3)] - Overweight(::sp_weights::Weight), - #[codec(index = 4)] - Yield, - } - } - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 9)] - authorize_upgrade { code_hash: ::subxt::utils::H256 }, - #[codec(index = 10)] - authorize_upgrade_without_checks { code_hash: ::subxt::utils::H256 }, - #[codec(index = 11)] - apply_authorized_upgrade { code: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - #[codec(index = 6)] - UpgradeAuthorized { - code_hash: ::subxt::utils::H256, - check_version: ::core::primitive::bool, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: ::core::primitive::u32, - pub providers: ::core::primitive::u32, - pub sufficients: ::core::primitive::u32, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CodeUpgradeAuthorization { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - #[codec(index = 9)] - force_adjust_total_issuance { - direction: runtime_types::pallet_balances::types::AdjustmentDirection, - #[codec(compact)] - delta: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - #[codec(index = 10)] - IssuanceDeactivated, - #[codec(index = 11)] - DeltaZero, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 21)] - TotalIssuanceForced { - old: ::core::primitive::u128, - new: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AdjustmentDirection { - #[codec(index = 0)] - Increase, - #[codec(index = 1)] - Decrease, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bridge_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - #[codec(index = 4)] - submit_finality_proof_ex { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - current_set_id: ::core::primitive::u64, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call2 { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - #[codec(index = 4)] - submit_finality_proof_ex { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - current_set_id: ::core::primitive::u64, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - #[codec(index = 8)] - InvalidAuthoritySetId, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error2 { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - #[codec(index = 8)] - InvalidAuthoritySetId, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u32, - hash: ::subxt::utils::H256, - grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< - ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - runtime_types::bp_header_chain::AuthoritySet, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event2 { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u32, - hash: ::subxt::utils::H256, - grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< - ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - runtime_types::bp_header_chain::AuthoritySet, - >, - }, - } - } - pub mod storage_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet2 { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - } - } - pub mod pallet_bridge_messages { - use super::runtime_types; - pub mod outbound_lane { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalConfirmationError { - #[codec(index = 0)] - FailedToConfirmFutureMessages, - #[codec(index = 1)] - EmptyUnrewardedRelayerEntry, - #[codec(index = 2)] - NonConsecutiveUnrewardedRelayerEntries, - #[codec(index = 3)] - TryingToConfirmMoreMessagesThanExpected, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call2 { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error2 { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event2 { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - } - } - pub mod pallet_bridge_parachains { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_parachain_heads { - at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), - parachains: ::std::vec::Vec<( - ::bp_polkadot_core::parachains::ParaId, - ::subxt::utils::H256, - )>, - parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, - }, - #[codec(index = 1)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 2)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnknownRelayChainBlock, - #[codec(index = 1)] - InvalidRelayChainBlockNumber, - #[codec(index = 2)] - HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 3)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 1)] - MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 2)] - IncorrectParachainHeadHash { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - actual_parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - RejectedObsoleteParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 4)] - RejectedLargeParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - parachain_head_size: ::core::primitive::u32, - }, - #[codec(index = 5)] - UpdatedParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - } - } - } - pub mod pallet_bridge_relayers { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim_rewards { - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - }, - #[codec(index = 1)] - register { valid_till: ::core::primitive::u32 }, - #[codec(index = 2)] - deregister, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NoRewardForRelayer, - #[codec(index = 1)] - FailedToPayReward, - #[codec(index = 2)] - InvalidRegistrationLease, - #[codec(index = 3)] - CannotReduceRegistrationLease, - #[codec(index = 4)] - FailedToReserve, - #[codec(index = 5)] - FailedToUnreserve, - #[codec(index = 6)] - NotRegistered, - #[codec(index = 7)] - RegistrationIsStillActive, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RewardRegistered { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 1)] - RewardPaid { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 2)] - RegistrationUpdated { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - #[codec(index = 3)] - Deregistered { relayer: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - SlashedAndDeregistered { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - } - } - } - pub mod pallet_collator_selection { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 1)] - set_desired_candidates { max: ::core::primitive::u32 }, - #[codec(index = 2)] - set_candidacy_bond { bond: ::core::primitive::u128 }, - #[codec(index = 3)] - register_as_candidate, - #[codec(index = 4)] - leave_intent, - #[codec(index = 5)] - add_invulnerable { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 7)] - update_bond { new_deposit: ::core::primitive::u128 }, - #[codec(index = 8)] - take_candidate_slot { - deposit: ::core::primitive::u128, - target: ::sp_core::crypto::AccountId32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateInfo<_0, _1> { - pub who: _0, - pub deposit: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCandidates, - #[codec(index = 1)] - TooFewEligibleCollators, - #[codec(index = 2)] - AlreadyCandidate, - #[codec(index = 3)] - NotCandidate, - #[codec(index = 4)] - TooManyInvulnerables, - #[codec(index = 5)] - AlreadyInvulnerable, - #[codec(index = 6)] - NotInvulnerable, - #[codec(index = 7)] - NoAssociatedValidatorId, - #[codec(index = 8)] - ValidatorNotRegistered, - #[codec(index = 9)] - InsertToCandidateListFailed, - #[codec(index = 10)] - RemoveFromCandidateListFailed, - #[codec(index = 11)] - DepositTooLow, - #[codec(index = 12)] - UpdateCandidateListFailed, - #[codec(index = 13)] - InsufficientBond, - #[codec(index = 14)] - TargetIsNotCandidate, - #[codec(index = 15)] - IdenticalDeposit, - #[codec(index = 16)] - InvalidUnreserve, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewInvulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 1)] - InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 2)] - InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, - #[codec(index = 4)] - NewCandidacyBond { bond_amount: ::core::primitive::u128 }, - #[codec(index = 5)] - CandidateAdded { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 6)] - CandidateBondUpdated { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 7)] - CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 8)] - CandidateReplaced { - old: ::sp_core::crypto::AccountId32, - new: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 9)] - InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, - } - } - } - pub mod pallet_message_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - reap_page { - message_origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - page_index: ::core::primitive::u32, - }, - #[codec(index = 1)] - execute_overweight { - message_origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - page: ::core::primitive::u32, - index: ::core::primitive::u32, - weight_limit: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotReapable, - #[codec(index = 1)] - NoPage, - #[codec(index = 2)] - NoMessage, - #[codec(index = 3)] - AlreadyProcessed, - #[codec(index = 4)] - Queued, - #[codec(index = 5)] - InsufficientWeight, - #[codec(index = 6)] - TemporarilyUnprocessable, - #[codec(index = 7)] - QueuePaused, - #[codec(index = 8)] - RecursiveDisallowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ProcessingFailed { - id: ::subxt::utils::H256, - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - error: runtime_types::frame_support::traits::messages::ProcessMessageError, - }, - #[codec(index = 1)] - Processed { - id: ::subxt::utils::H256, - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - weight_used: ::sp_weights::Weight, - success: ::core::primitive::bool, - }, - #[codec(index = 2)] - OverweightEnqueued { - id: [::core::primitive::u8; 32usize], - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - page_index: ::core::primitive::u32, - message_index: ::core::primitive::u32, - }, - #[codec(index = 3)] - PageReaped { - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - index: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BookState<_0> { - pub begin: ::core::primitive::u32, - pub end: ::core::primitive::u32, - pub count: ::core::primitive::u32, - pub ready_neighbours: - ::core::option::Option>, - pub message_count: ::core::primitive::u64, - pub size: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Neighbours<_0> { - pub prev: _0, - pub next: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Page<_0> { - pub remaining: _0, - pub remaining_size: _0, - pub first_index: _0, - pub first: _0, - pub last: _0, - pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box< - runtime_types::bridge_hub_rococo_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_rococo_runtime::RuntimeCall, - >, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: ::core::primitive::u32, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::bridge_hub_rococo_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { - calls: - ::std::vec::Vec, - }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box< - runtime_types::bridge_hub_rococo_runtime::RuntimeCall, - >, - }, - #[codec(index = 2)] - batch_all { - calls: - ::std::vec::Vec, - }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box< - runtime_types::bridge_hub_rococo_runtime::OriginCaller, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_rococo_runtime::RuntimeCall, - >, - }, - #[codec(index = 4)] - force_batch { - calls: - ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box< - runtime_types::bridge_hub_rococo_runtime::RuntimeCall, - >, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - #[codec(index = 11)] - transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - CannotCheckOutTeleport, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - #[codec(index = 20)] - InvalidAssetNotConcrete, - #[codec(index = 21)] - InvalidAssetUnknownReserve, - #[codec(index = 22)] - InvalidAssetUnsupportedReserve, - #[codec(index = 23)] - TooManyReserves, - #[codec(index = 24)] - LocalExecutionIncomplete, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted { outcome: runtime_types::staging_xcm::v4::traits::Outcome }, - #[codec(index = 1)] - Sent { - origin: runtime_types::staging_xcm::v4::location::Location, - destination: runtime_types::staging_xcm::v4::location::Location, - message: runtime_types::staging_xcm::v4::Xcm, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - UnexpectedResponse { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - }, - #[codec(index = 3)] - ResponseReady { - query_id: ::core::primitive::u64, - response: runtime_types::staging_xcm::v4::Response, - }, - #[codec(index = 4)] - Notified { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 5)] - NotifyOverweight { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - actual_weight: ::sp_weights::Weight, - max_budgeted_weight: ::sp_weights::Weight, - }, - #[codec(index = 6)] - NotifyDispatchError { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 7)] - NotifyDecodeFailed { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 8)] - InvalidResponder { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - expected_location: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 9)] - InvalidResponderVersion { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - }, - #[codec(index = 10)] - ResponseTaken { query_id: ::core::primitive::u64 }, - #[codec(index = 11)] - AssetsTrapped { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v4::location::Location, - assets: runtime_types::xcm::VersionedAssets, - }, - #[codec(index = 12)] - VersionChangeNotified { - destination: runtime_types::staging_xcm::v4::location::Location, - result: ::core::primitive::u32, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 13)] - SupportedVersionChanged { - location: runtime_types::staging_xcm::v4::location::Location, - version: ::core::primitive::u32, - }, - #[codec(index = 14)] - NotifyTargetSendFail { - location: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - error: runtime_types::xcm::v3::traits::Error, - }, - #[codec(index = 15)] - NotifyTargetMigrationFail { - location: runtime_types::xcm::VersionedLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 16)] - InvalidQuerierVersion { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - }, - #[codec(index = 17)] - InvalidQuerier { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - expected_querier: runtime_types::staging_xcm::v4::location::Location, - maybe_actual_querier: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 18)] - VersionNotifyStarted { - destination: runtime_types::staging_xcm::v4::location::Location, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 19)] - VersionNotifyRequested { - destination: runtime_types::staging_xcm::v4::location::Location, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 20)] - VersionNotifyUnrequested { - destination: runtime_types::staging_xcm::v4::location::Location, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 21)] - FeesPaid { - paying: runtime_types::staging_xcm::v4::location::Location, - fees: runtime_types::staging_xcm::v4::asset::Assets, - }, - #[codec(index = 22)] - AssetsClaimed { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v4::location::Location, - assets: runtime_types::xcm::VersionedAssets, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::staging_xcm::v4::location::Location), - #[codec(index = 1)] - Response(runtime_types::staging_xcm::v4::location::Location), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedLocation, - pub locker: runtime_types::xcm::VersionedLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain_primitives { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v6 { - use super::runtime_types; - pub mod async_backing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHostConfiguration { - pub max_code_size: ::core::primitive::u32, - pub max_head_data_size: ::core::primitive::u32, - pub max_upward_queue_count: ::core::primitive::u32, - pub max_upward_queue_size: ::core::primitive::u32, - pub max_upward_message_size: ::core::primitive::u32, - pub max_upward_message_num_per_candidate: ::core::primitive::u32, - pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, - pub validation_upgrade_cooldown: ::core::primitive::u32, - pub validation_upgrade_delay: ::core::primitive::u32, - pub async_backing_params: - runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PersistedValidationData<_0, _1> { - pub parent_head: - runtime_types::polkadot_parachain_primitives::primitives::HeadData, - pub relay_parent_number: _1, - pub relay_parent_storage_root: _0, - pub max_pov_size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - } - } - pub mod primitive_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct U256(pub [::core::primitive::u64; 4usize]); - } - pub mod snowbridge_amcl { - use super::runtime_types; - pub mod bls381 { - use super::runtime_types; - pub mod big { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Big { - pub w: [::core::primitive::i32; 14usize], - } - } - pub mod ecp { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ECP { - pub x: runtime_types::snowbridge_amcl::bls381::fp::FP, - pub y: runtime_types::snowbridge_amcl::bls381::fp::FP, - pub z: runtime_types::snowbridge_amcl::bls381::fp::FP, - } - } - pub mod fp { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FP { - pub x: runtime_types::snowbridge_amcl::bls381::big::Big, - pub xes: ::core::primitive::i32, - } - } - } - } - pub mod snowbridge_beacon_primitives { - use super::runtime_types; - pub mod bls { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BlsError { - #[codec(index = 0)] - InvalidSignature, - #[codec(index = 1)] - InvalidPublicKey, - #[codec(index = 2)] - InvalidAggregatePublicKeys, - #[codec(index = 3)] - SignatureVerificationFailed, - } - } - pub mod types { - use super::runtime_types; - pub mod deneb { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutionPayloadHeader { - pub parent_hash: ::subxt::utils::H256, - pub fee_recipient: ::subxt::utils::H160, - pub state_root: ::subxt::utils::H256, - pub receipts_root: ::subxt::utils::H256, - pub logs_bloom: ::std::vec::Vec<::core::primitive::u8>, - pub prev_randao: ::subxt::utils::H256, - pub block_number: ::core::primitive::u64, - pub gas_limit: ::core::primitive::u64, - pub gas_used: ::core::primitive::u64, - pub timestamp: ::core::primitive::u64, - pub extra_data: ::std::vec::Vec<::core::primitive::u8>, - pub base_fee_per_gas: runtime_types::primitive_types::U256, - pub block_hash: ::subxt::utils::H256, - pub transactions_root: ::subxt::utils::H256, - pub withdrawals_root: ::subxt::utils::H256, - pub blob_gas_used: ::core::primitive::u64, - pub excess_blob_gas: ::core::primitive::u64, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BeaconHeader { - pub slot: ::core::primitive::u64, - pub proposer_index: ::core::primitive::u64, - pub parent_root: ::subxt::utils::H256, - pub state_root: ::subxt::utils::H256, - pub body_root: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CompactBeaconState { - #[codec(compact)] - pub slot: ::core::primitive::u64, - pub block_roots_root: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CompactExecutionHeader { - pub parent_hash: ::subxt::utils::H256, - #[codec(compact)] - pub block_number: ::core::primitive::u64, - pub state_root: ::subxt::utils::H256, - pub receipts_root: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutionHeaderState { - pub beacon_block_root: ::subxt::utils::H256, - pub beacon_slot: ::core::primitive::u64, - pub block_hash: ::subxt::utils::H256, - pub block_number: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutionPayloadHeader { - pub parent_hash: ::subxt::utils::H256, - pub fee_recipient: ::subxt::utils::H160, - pub state_root: ::subxt::utils::H256, - pub receipts_root: ::subxt::utils::H256, - pub logs_bloom: ::std::vec::Vec<::core::primitive::u8>, - pub prev_randao: ::subxt::utils::H256, - pub block_number: ::core::primitive::u64, - pub gas_limit: ::core::primitive::u64, - pub gas_used: ::core::primitive::u64, - pub timestamp: ::core::primitive::u64, - pub extra_data: ::std::vec::Vec<::core::primitive::u8>, - pub base_fee_per_gas: runtime_types::primitive_types::U256, - pub block_hash: ::subxt::utils::H256, - pub transactions_root: ::subxt::utils::H256, - pub withdrawals_root: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Fork { - pub version: [::core::primitive::u8; 4usize], - pub epoch: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ForkVersions { - pub genesis: runtime_types::snowbridge_beacon_primitives::types::Fork, - pub altair: runtime_types::snowbridge_beacon_primitives::types::Fork, - pub bellatrix: runtime_types::snowbridge_beacon_primitives::types::Fork, - pub capella: runtime_types::snowbridge_beacon_primitives::types::Fork, - pub deneb: runtime_types::snowbridge_beacon_primitives::types::Fork, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PublicKey(pub [::core::primitive::u8; 48usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 96usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SyncAggregate { - pub sync_committee_bits: [::core::primitive::u8; 64usize], - pub sync_committee_signature: - runtime_types::snowbridge_beacon_primitives::types::Signature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SyncCommittee { - pub pubkeys: - [runtime_types::snowbridge_beacon_primitives::types::PublicKey; 512usize], - pub aggregate_pubkey: - runtime_types::snowbridge_beacon_primitives::types::PublicKey, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SyncCommitteePrepared { - pub root: ::subxt::utils::H256, - pub pubkeys: ::std::boxed::Box< - [runtime_types::snowbridge_milagro_bls::keys::PublicKey; 512usize], - >, - pub aggregate_pubkey: runtime_types::snowbridge_milagro_bls::keys::PublicKey, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedExecutionPayloadHeader { - # [codec (index = 0)] Capella (runtime_types :: snowbridge_beacon_primitives :: types :: ExecutionPayloadHeader ,) , # [codec (index = 1)] Deneb (runtime_types :: snowbridge_beacon_primitives :: types :: deneb :: ExecutionPayloadHeader ,) , } - } - pub mod updates { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AncestryProof { - pub header_branch: ::std::vec::Vec<::subxt::utils::H256>, - pub finalized_block_root: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckpointUpdate { - pub header: runtime_types::snowbridge_beacon_primitives::types::BeaconHeader, - pub current_sync_committee: - runtime_types::snowbridge_beacon_primitives::types::SyncCommittee, - pub current_sync_committee_branch: ::std::vec::Vec<::subxt::utils::H256>, - pub validators_root: ::subxt::utils::H256, - pub block_roots_root: ::subxt::utils::H256, - pub block_roots_branch: ::std::vec::Vec<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutionHeaderUpdate { pub header : runtime_types :: snowbridge_beacon_primitives :: types :: BeaconHeader , pub ancestry_proof : :: core :: option :: Option < runtime_types :: snowbridge_beacon_primitives :: updates :: AncestryProof > , pub execution_header : runtime_types :: snowbridge_beacon_primitives :: types :: VersionedExecutionPayloadHeader , pub execution_branch : :: std :: vec :: Vec < :: subxt :: utils :: H256 > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct NextSyncCommitteeUpdate { - pub next_sync_committee: - runtime_types::snowbridge_beacon_primitives::types::SyncCommittee, - pub next_sync_committee_branch: ::std::vec::Vec<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Update { pub attested_header : runtime_types :: snowbridge_beacon_primitives :: types :: BeaconHeader , pub sync_aggregate : runtime_types :: snowbridge_beacon_primitives :: types :: SyncAggregate , pub signature_slot : :: core :: primitive :: u64 , pub next_sync_committee_update : :: core :: option :: Option < runtime_types :: snowbridge_beacon_primitives :: updates :: NextSyncCommitteeUpdate > , pub finalized_header : runtime_types :: snowbridge_beacon_primitives :: types :: BeaconHeader , pub finality_branch : :: std :: vec :: Vec < :: subxt :: utils :: H256 > , pub block_roots_root : :: subxt :: utils :: H256 , pub block_roots_branch : :: std :: vec :: Vec < :: subxt :: utils :: H256 > , } - } - } - pub mod snowbridge_core { - use super::runtime_types; - pub mod inbound { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Log { - pub address: ::subxt::utils::H160, - pub topics: ::std::vec::Vec<::subxt::utils::H256>, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Message { - pub event_log: runtime_types::snowbridge_core::inbound::Log, - pub proof: runtime_types::snowbridge_core::inbound::Proof, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Proof { - pub block_hash: ::subxt::utils::H256, - pub tx_index: ::core::primitive::u32, - pub data: ( - ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VerificationError { - #[codec(index = 0)] - HeaderNotFound, - #[codec(index = 1)] - LogNotFound, - #[codec(index = 2)] - InvalidLog, - #[codec(index = 3)] - InvalidProof, - } - } - pub mod operating_mode { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - } - pub mod outbound { - use super::runtime_types; - pub mod v1 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Initializer { - pub params: ::std::vec::Vec<::core::primitive::u8>, - pub maximum_required_gas: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - RejectingOutboundMessages, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SendError { - #[codec(index = 0)] - MessageTooLarge, - #[codec(index = 1)] - Halted, - #[codec(index = 2)] - InvalidChannel, - } - } - pub mod pricing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PricingParameters<_0> { - pub exchange_rate: runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub rewards: runtime_types::snowbridge_core::pricing::Rewards<_0>, - pub fee_per_gas: runtime_types::primitive_types::U256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Rewards<_0> { - pub local: _0, - pub remote: runtime_types::primitive_types::U256, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Channel { - pub agent_id: ::subxt::utils::H256, - pub para_id: runtime_types::polkadot_parachain_primitives::primitives::Id, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChannelId(pub [::core::primitive::u8; 32usize]); - } - pub mod snowbridge_milagro_bls { - use super::runtime_types; - pub mod keys { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PublicKey { - pub point: runtime_types::snowbridge_amcl::bls381::ecp::ECP, - } - } - } - pub mod snowbridge_pallet_ethereum_client { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] force_checkpoint { update : :: std :: boxed :: Box < runtime_types :: snowbridge_beacon_primitives :: updates :: CheckpointUpdate > , } , # [codec (index = 1)] submit { update : :: std :: boxed :: Box < runtime_types :: snowbridge_beacon_primitives :: updates :: Update > , } , # [codec (index = 2)] submit_execution_header { update : :: std :: boxed :: Box < runtime_types :: snowbridge_beacon_primitives :: updates :: ExecutionHeaderUpdate > , } , # [codec (index = 3)] set_operating_mode { mode : runtime_types :: snowbridge_core :: operating_mode :: BasicOperatingMode , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - SkippedSyncCommitteePeriod, - #[codec(index = 1)] - IrrelevantUpdate, - #[codec(index = 2)] - NotBootstrapped, - #[codec(index = 3)] - SyncCommitteeParticipantsNotSupermajority, - #[codec(index = 4)] - InvalidHeaderMerkleProof, - #[codec(index = 5)] - InvalidSyncCommitteeMerkleProof, - #[codec(index = 6)] - InvalidExecutionHeaderProof, - #[codec(index = 7)] - InvalidAncestryMerkleProof, - #[codec(index = 8)] - InvalidBlockRootsRootMerkleProof, - #[codec(index = 9)] - HeaderNotFinalized, - #[codec(index = 10)] - BlockBodyHashTreeRootFailed, - #[codec(index = 11)] - HeaderHashTreeRootFailed, - #[codec(index = 12)] - SyncCommitteeHashTreeRootFailed, - #[codec(index = 13)] - SigningRootHashTreeRootFailed, - #[codec(index = 14)] - ForkDataHashTreeRootFailed, - #[codec(index = 15)] - ExpectedFinalizedHeaderNotStored, - #[codec(index = 16)] - BLSPreparePublicKeysFailed, - #[codec(index = 17)] - BLSVerificationFailed( - runtime_types::snowbridge_beacon_primitives::bls::BlsError, - ), - #[codec(index = 18)] - InvalidUpdateSlot, - #[codec(index = 19)] - InvalidSyncCommitteeUpdate, - #[codec(index = 20)] - ExecutionHeaderTooFarBehind, - #[codec(index = 21)] - ExecutionHeaderSkippedBlock, - #[codec(index = 22)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BeaconHeaderImported { - block_hash: ::subxt::utils::H256, - slot: ::core::primitive::u64, - }, - #[codec(index = 1)] - ExecutionHeaderImported { - block_hash: ::subxt::utils::H256, - block_number: ::core::primitive::u64, - }, - #[codec(index = 2)] - SyncCommitteeUpdated { period: ::core::primitive::u64 }, - #[codec(index = 3)] - OperatingModeChanged { - mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, - }, - } - } - } - pub mod snowbridge_pallet_inbound_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit { message: runtime_types::snowbridge_core::inbound::Message }, - #[codec(index = 1)] - set_operating_mode { - mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidGateway, - #[codec(index = 1)] - InvalidEnvelope, - #[codec(index = 2)] - InvalidNonce, - #[codec(index = 3)] - InvalidPayload, - #[codec(index = 4)] - InvalidChannel, - #[codec(index = 5)] - MaxNonceReached, - #[codec(index = 6)] - InvalidAccountConversion, - #[codec(index = 7)] - Halted, - #[codec(index = 8)] - Verification(runtime_types::snowbridge_core::inbound::VerificationError), - #[codec(index = 9)] - Send(runtime_types::snowbridge_pallet_inbound_queue::pallet::SendError), - #[codec(index = 10)] - ConvertMessage( - runtime_types::snowbridge_router_primitives::inbound::ConvertMessageError, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - MessageReceived { - channel_id: runtime_types::snowbridge_core::ChannelId, - nonce: ::core::primitive::u64, - message_id: [::core::primitive::u8; 32usize], - fee_burned: ::core::primitive::u128, - }, - #[codec(index = 1)] - OperatingModeChanged { - mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SendError { - #[codec(index = 0)] - NotApplicable, - #[codec(index = 1)] - NotRoutable, - #[codec(index = 2)] - Transport, - #[codec(index = 3)] - DestinationUnsupported, - #[codec(index = 4)] - ExceedsMaxMessageSize, - #[codec(index = 5)] - MissingArgument, - #[codec(index = 6)] - Fees, - } - } - } - pub mod snowbridge_pallet_outbound_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_operating_mode { - mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MessageTooLarge, - #[codec(index = 1)] - Halted, - #[codec(index = 2)] - InvalidChannel, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - MessageQueued { id: ::subxt::utils::H256 }, - #[codec(index = 1)] - MessageAccepted { id: ::subxt::utils::H256, nonce: ::core::primitive::u64 }, - #[codec(index = 2)] - MessagesCommitted { root: ::subxt::utils::H256, count: ::core::primitive::u64 }, - #[codec(index = 3)] - OperatingModeChanged { - mode: runtime_types::snowbridge_core::operating_mode::BasicOperatingMode, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommittedMessage { - pub channel_id: runtime_types::snowbridge_core::ChannelId, - #[codec(compact)] - pub nonce: ::core::primitive::u64, - pub command: ::core::primitive::u8, - pub params: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - pub max_dispatch_gas: ::core::primitive::u64, - #[codec(compact)] - pub max_fee_per_gas: ::core::primitive::u128, - #[codec(compact)] - pub reward: ::core::primitive::u128, - pub id: ::subxt::utils::H256, - } - } - } - pub mod snowbridge_pallet_system { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - upgrade { - impl_address: ::subxt::utils::H160, - impl_code_hash: ::subxt::utils::H256, - initializer: ::core::option::Option< - runtime_types::snowbridge_core::outbound::v1::Initializer, - >, - }, - #[codec(index = 1)] - set_operating_mode { - mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, - }, - #[codec(index = 2)] - set_pricing_parameters { - params: runtime_types::snowbridge_core::pricing::PricingParameters< - ::core::primitive::u128, - >, - }, - #[codec(index = 3)] - create_agent, - #[codec(index = 4)] - create_channel { - mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, - }, - #[codec(index = 5)] - update_channel { - mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, - }, - #[codec(index = 6)] - force_update_channel { - channel_id: runtime_types::snowbridge_core::ChannelId, - mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, - }, - #[codec(index = 7)] - transfer_native_from_agent { - recipient: ::subxt::utils::H160, - amount: ::core::primitive::u128, - }, - #[codec(index = 8)] - force_transfer_native_from_agent { - location: ::std::boxed::Box, - recipient: ::subxt::utils::H160, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - set_token_transfer_fees { - create_asset_xcm: ::core::primitive::u128, - transfer_asset_xcm: ::core::primitive::u128, - register_token: runtime_types::primitive_types::U256, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - LocationConversionFailed, - #[codec(index = 1)] - AgentAlreadyCreated, - #[codec(index = 2)] - NoAgent, - #[codec(index = 3)] - ChannelAlreadyCreated, - #[codec(index = 4)] - NoChannel, - #[codec(index = 5)] - UnsupportedLocationVersion, - #[codec(index = 6)] - InvalidLocation, - #[codec(index = 7)] - Send(runtime_types::snowbridge_core::outbound::SendError), - #[codec(index = 8)] - InvalidTokenTransferFees, - #[codec(index = 9)] - InvalidPricingParameters, - #[codec(index = 10)] - InvalidUpgradeParameters, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Upgrade { - impl_address: ::subxt::utils::H160, - impl_code_hash: ::subxt::utils::H256, - initializer_params_hash: ::core::option::Option<::subxt::utils::H256>, - }, - #[codec(index = 1)] - CreateAgent { - location: - ::std::boxed::Box, - agent_id: ::subxt::utils::H256, - }, - #[codec(index = 2)] - CreateChannel { - channel_id: runtime_types::snowbridge_core::ChannelId, - agent_id: ::subxt::utils::H256, - }, - #[codec(index = 3)] - UpdateChannel { - channel_id: runtime_types::snowbridge_core::ChannelId, - mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, - }, - #[codec(index = 4)] - SetOperatingMode { - mode: runtime_types::snowbridge_core::outbound::v1::OperatingMode, - }, - #[codec(index = 5)] - TransferNativeFromAgent { - agent_id: ::subxt::utils::H256, - recipient: ::subxt::utils::H160, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - SetTokenTransferFees { - create_asset_xcm: ::core::primitive::u128, - transfer_asset_xcm: ::core::primitive::u128, - register_token: runtime_types::primitive_types::U256, - }, - #[codec(index = 7)] - PricingParametersChanged { - params: runtime_types::snowbridge_core::pricing::PricingParameters< - ::core::primitive::u128, - >, - }, - } - } - } - pub mod snowbridge_router_primitives { - use super::runtime_types; - pub mod inbound { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConvertMessageError { - #[codec(index = 0)] - UnsupportedVersion, - } - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_consensus_aura { - use super::runtime_types; - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_trie { - use super::runtime_types; - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StorageProof { - pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod staging_parachain_info { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - } - } - pub mod staging_xcm { - use super::runtime_types; - pub mod v3 { - use super::runtime_types; - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - } - pub mod v4 { - use super::runtime_types; - pub mod asset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Asset { - pub id: runtime_types::staging_xcm::v4::asset::AssetId, - pub fun: runtime_types::staging_xcm::v4::asset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetFilter { - #[codec(index = 0)] - Definite(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 1)] - Wild(runtime_types::staging_xcm::v4::asset::WildAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AssetId(pub runtime_types::staging_xcm::v4::location::Location); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Assets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::staging_xcm::v4::asset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::staging_xcm::v4::asset::AssetId, - fun: runtime_types::staging_xcm::v4::asset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::staging_xcm::v4::asset::AssetId, - fun: runtime_types::staging_xcm::v4::asset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - } - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: ::core::option::Option< - runtime_types::staging_xcm::v4::junction::NetworkId, - >, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: ::core::option::Option< - runtime_types::staging_xcm::v4::junction::NetworkId, - >, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: ::core::option::Option< - runtime_types::staging_xcm::v4::junction::NetworkId, - >, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::staging_xcm::v4::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - #[codec(index = 10)] - PolkadotBulletin, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1([runtime_types::staging_xcm::v4::junction::Junction; 1usize]), - #[codec(index = 2)] - X2([runtime_types::staging_xcm::v4::junction::Junction; 2usize]), - #[codec(index = 3)] - X3([runtime_types::staging_xcm::v4::junction::Junction; 3usize]), - #[codec(index = 4)] - X4([runtime_types::staging_xcm::v4::junction::Junction; 4usize]), - #[codec(index = 5)] - X5([runtime_types::staging_xcm::v4::junction::Junction; 5usize]), - #[codec(index = 6)] - X6([runtime_types::staging_xcm::v4::junction::Junction; 6usize]), - #[codec(index = 7)] - X7([runtime_types::staging_xcm::v4::junction::Junction; 7usize]), - #[codec(index = 8)] - X8([runtime_types::staging_xcm::v4::junction::Junction; 8usize]), - } - } - pub mod location { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Location { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::staging_xcm::v4::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete { used: ::sp_weights::Weight }, - #[codec(index = 1)] - Incomplete { - used: ::sp_weights::Weight, - error: runtime_types::xcm::v3::traits::Error, - }, - #[codec(index = 2)] - Error { error: runtime_types::xcm::v3::traits::Error }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::staging_xcm::v4::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::staging_xcm::v4::asset::AssetFilter, - want: runtime_types::staging_xcm::v4::asset::Assets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - reserve: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::staging_xcm::v4::asset::Asset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::staging_xcm::v4::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::staging_xcm::v4::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - ticket: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 29)] - ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::staging_xcm::v4::junction::NetworkId, - destination: runtime_types::staging_xcm::v4::junctions::Junctions, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - unlocker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - target: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::staging_xcm::v4::asset::Asset, - owner: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::staging_xcm::v4::asset::Asset, - locker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v4::location::Location), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::staging_xcm::v4::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::staging_xcm::v4::asset::AssetFilter, - want: runtime_types::staging_xcm::v4::asset::Assets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - reserve: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::staging_xcm::v4::asset::Asset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::staging_xcm::v4::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::staging_xcm::v4::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - ticket: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 29)] - ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::staging_xcm::v4::junction::NetworkId, - destination: runtime_types::staging_xcm::v4::junctions::Junctions, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - unlocker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - target: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::staging_xcm::v4::asset::Asset, - owner: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::staging_xcm::v4::asset::Asset, - locker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v4::location::Location), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::staging_xcm::v4::location::Location, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::staging_xcm::v4::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded2 { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - #[codec(index = 10)] - PolkadotBulletin, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::asset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::asset::Assets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::location::Location), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::Xcm), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm2 { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm2), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm2), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::Xcm2), - } - } - } -} diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs deleted file mode 100644 index cae9e4f77a501..0000000000000 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2022 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 . - -//! Types used to connect to the BridgeHub-Rococo-Substrate parachain. - -pub mod codegen_runtime; - -use bp_bridge_hub_rococo::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use codec::Encode; -use relay_substrate_client::{ - calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, - UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::bridge_hub_rococo_runtime::RuntimeCall; -pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; -pub type BridgeBulletinMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call2; -pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeBulletinGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call2; -pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; -type UtilityCall = runtime_types::pallet_utility::pallet::Call; - -/// Rococo chain definition -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct BridgeHubRococo; - -impl UnderlyingChainProvider for BridgeHubRococo { - type Chain = bp_bridge_hub_rococo::BridgeHubRococo; -} - -impl Chain for BridgeHubRococo { - const NAME: &'static str = "BridgeHubRococo"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_bridge_hub_rococo::BEST_FINALIZED_BRIDGE_HUB_ROCOCO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = bp_bridge_hub_rococo::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithBalances for BridgeHubRococo { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_bridge_hub_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl From> for RuntimeCall { - fn from(value: MockUtilityCall) -> RuntimeCall { - match value { - MockUtilityCall::batch_all(calls) => - RuntimeCall::Utility(UtilityCall::batch_all { calls }), - } - } -} - -impl ChainWithUtilityPallet for BridgeHubRococo { - type UtilityPallet = MockedRuntimeUtilityPallet; -} - -impl ChainWithTransactions for BridgeHubRococo { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - (((), ()), ((), ())), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(UncheckedExtrinsic::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithMessages for BridgeHubRococo { - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = - Some(bp_bridge_hub_rococo::WITH_BRIDGE_HUB_ROCOCO_RELAYERS_PALLET_NAME); - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_rococo::TO_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_rococo::FROM_BRIDGE_HUB_ROCOCO_MESSAGE_DETAILS_METHOD; -} - -impl ChainWithRuntimeVersion for BridgeHubRococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); -} diff --git a/relays/client-bridge-hub-westend/Cargo.toml b/relays/client-bridge-hub-westend/Cargo.toml deleted file mode 100644 index c65c7ec0014b8..0000000000000 --- a/relays/client-bridge-hub-westend/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "relay-bridge-hub-westend-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-bridge-hub-westend = { path = "../../chains/chain-bridge-hub-westend" } -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-parachains = { path = "../../primitives/parachains" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../chains/chain-rococo" } - -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-substrate-client = { path = "../client-substrate" } - -# Substrate Dependencies - -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } - -[dev-dependencies] -bp-runtime = { path = "../../primitives/runtime" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-bridge-hub-westend/src/codegen_runtime.rs b/relays/client-bridge-hub-westend/src/codegen_runtime.rs deleted file mode 100644 index 51d0b7f8c423f..0000000000000 --- a/relays/client-bridge-hub-westend/src/codegen_runtime.rs +++ /dev/null @@ -1,4705 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-wasm-file -//! ../../../polkadot-sdk/target/release/wbuild/bridge-hub-westend-runtime/ -//! bridge_hub_westend_runtime.compact.compressed.wasm - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -#[allow(rustdoc::broken_intra_doc_links)] -pub mod api { - #[allow(unused_imports)] - mod root_mod { - pub use super::*; - } - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_btree_set { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedBTreeSet<_0>(pub ::std::vec::Vec<_0>); - } - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod bp_header_chain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AuthoritySet { - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HeaderChainError { - #[codec(index = 0)] - UnknownHeader, - #[codec(index = 1)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderFinalityInfo<_0, _1> { - pub finality_proof: _0, - pub new_verification_context: ::core::option::Option<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredHeaderData<_0, _1> { - pub number: _0, - pub state_root: _1, - } - } - pub mod bp_messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DeliveredMessages { - pub begin: ::core::primitive::u64, - pub end: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundLaneData<_0> { - pub relayers: ::std::vec::Vec>, - pub last_confirmed_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageKey { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MessagesOperatingMode { - #[codec(index = 0)] - Basic(runtime_types::bp_runtime::BasicOperatingMode), - #[codec(index = 1)] - RejectingOutboundMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundLaneData { - pub oldest_unpruned_nonce: ::core::primitive::u64, - pub latest_received_nonce: ::core::primitive::u64, - pub latest_generated_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalResult<_0> { - #[codec(index = 0)] - Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), - #[codec(index = 1)] - InvalidNonce, - #[codec(index = 2)] - TooManyUnrewardedRelayers, - #[codec(index = 3)] - TooManyUnconfirmedMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceivedMessages<_0> { - pub lane: runtime_types::bp_messages::LaneId, - pub receive_results: ::std::vec::Vec<( - ::core::primitive::u64, - runtime_types::bp_messages::ReceivalResult<_0>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnrewardedRelayer<_0> { - pub relayer: _0, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VerificationError { - #[codec(index = 0)] - EmptyMessageProof, - #[codec(index = 1)] - HeaderChain(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 2)] - InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 3)] - InvalidMessageWeight, - #[codec(index = 4)] - MessagesCountMismatch, - #[codec(index = 5)] - MessageStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 6)] - MessageTooLarge, - #[codec(index = 7)] - OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 8)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 9)] - Other, - } - } - pub mod bp_parachains { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BestParaHeadHash { - pub at_relay_block_number: ::core::primitive::u32, - pub head_hash: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo { - pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, - pub next_imported_hash_position: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod bp_relayers { - use super::runtime_types; - pub mod registration { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0, _1> { - pub valid_till: _0, - pub stake: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardsAccountOwner { - #[codec(index = 0)] - ThisChain, - #[codec(index = 1)] - BridgedChain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardsAccountParams { - pub lane_id: runtime_types::bp_messages::LaneId, - pub bridged_chain_id: [::core::primitive::u8; 4usize], - pub owner: runtime_types::bp_relayers::RewardsAccountOwner, - } - } - pub mod bp_runtime { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageDispatchResult<_0> { - pub unspent_weight: ::sp_weights::Weight, - pub dispatch_level_result: _0, - } - } - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateNodesInProof, - #[codec(index = 1)] - UnusedNodesInTheProof, - #[codec(index = 2)] - StorageRootMismatch, - #[codec(index = 3)] - StorageValueUnavailable, - #[codec(index = 4)] - StorageValueEmpty, - #[codec(index = 5)] - StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OwnedBridgeModuleError { - #[codec(index = 0)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StrippableError; - } - pub mod bridge_hub_common { - use super::runtime_types; - pub mod message_queue { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - Parent, - #[codec(index = 2)] - Sibling(runtime_types::polkadot_parachain_primitives::primitives::Id), - #[codec(index = 3)] - Snowbridge(runtime_types::snowbridge_core::ChannelId), - } - } - } - pub mod bridge_hub_westend_runtime { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::sp_core::crypto::AccountId32, - >, - ), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Origin), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Origin), - #[codec(index = 3)] - Void(runtime_types::sp_core::Void), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 3)] - ParachainInfo(runtime_types::staging_parachain_info::pallet::Call), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Call), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Call), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Call), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 36)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 41)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Call), - #[codec(index = 42)] - BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 43)] - BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 44)] - BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Call), - #[codec(index = 250)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeError { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Error), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Error), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Error), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Error), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Error), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Error), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Error), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Error), - #[codec(index = 36)] - Multisig(runtime_types::pallet_multisig::pallet::Error), - #[codec(index = 41)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Error), - #[codec(index = 42)] - BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), - #[codec(index = 43)] - BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Error), - #[codec(index = 44)] - BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Error), - #[codec(index = 250)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 1)] - ParachainSystem(runtime_types::cumulus_pallet_parachain_system::pallet::Event), - #[codec(index = 10)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 11)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 21)] - CollatorSelection(runtime_types::pallet_collator_selection::pallet::Event), - #[codec(index = 22)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 30)] - XcmpQueue(runtime_types::cumulus_pallet_xcmp_queue::pallet::Event), - #[codec(index = 31)] - PolkadotXcm(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 32)] - CumulusXcm(runtime_types::cumulus_pallet_xcm::pallet::Event), - #[codec(index = 40)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 36)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 41)] - BridgeRelayers(runtime_types::pallet_bridge_relayers::pallet::Event), - #[codec(index = 42)] - BridgeRococoGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 43)] - BridgeRococoParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 44)] - BridgeRococoMessages(runtime_types::pallet_bridge_messages::pallet::Event), - #[codec(index = 250)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeHoldReason {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub aura: runtime_types::sp_consensus_aura::sr25519::app_sr25519::Public, - } - } - pub mod bridge_runtime_common { - use super::runtime_types; - pub mod messages_xcm_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmBlobMessageDispatchResult { - #[codec(index = 0)] - InvalidPayload, - #[codec(index = 1)] - Dispatched, - #[codec(index = 2)] - NotDispatched, - } - } - pub mod refund_relayer_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundBridgedParachainMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RefundTransactionExtensionAdapter<_0>(pub _0); - } - } - pub mod cumulus_pallet_parachain_system { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_data { data : runtime_types :: cumulus_primitives_parachain_inherent :: ParachainInherentData , } , # [codec (index = 1)] sudo_send_upward_message { message : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , # [codec (index = 2)] authorize_upgrade { code_hash : :: subxt :: utils :: H256 , check_version : :: core :: primitive :: bool , } , # [codec (index = 3)] enact_authorized_upgrade { code : :: std :: vec :: Vec < :: core :: primitive :: u8 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OverlappingUpgrades, - #[codec(index = 1)] - ProhibitedByPolkadot, - #[codec(index = 2)] - TooBig, - #[codec(index = 3)] - ValidationDataNotAvailable, - #[codec(index = 4)] - HostConfigurationNotAvailable, - #[codec(index = 5)] - NotScheduled, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidationFunctionStored, - #[codec(index = 1)] - ValidationFunctionApplied { relay_chain_block_num: ::core::primitive::u32 }, - #[codec(index = 2)] - ValidationFunctionDiscarded, - #[codec(index = 3)] - DownwardMessagesReceived { count: ::core::primitive::u32 }, - #[codec(index = 4)] - DownwardMessagesProcessed { - weight_used: ::sp_weights::Weight, - dmq_head: ::subxt::utils::H256, - }, - #[codec(index = 5)] - UpwardMessageSent { - message_hash: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - pub mod relay_state_snapshot { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessagingStateSnapshot { pub dmq_mqc_head : :: subxt :: utils :: H256 , pub relay_dispatch_queue_remaining_capacity : runtime_types :: cumulus_pallet_parachain_system :: relay_state_snapshot :: RelayDispatchQueueRemainingCapacity , pub ingress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , pub egress_channels : :: std :: vec :: Vec < (runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: polkadot_primitives :: v6 :: AbridgedHrmpChannel ,) > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RelayDispatchQueueRemainingCapacity { - pub remaining_count: ::core::primitive::u32, - pub remaining_size: ::core::primitive::u32, - } - } - pub mod unincluded_segment { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Ancestor < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub para_head_hash : :: core :: option :: Option < _0 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelUpdate { - pub msg_count: ::core::primitive::u32, - pub total_bytes: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SegmentTracker < _0 > { pub used_bandwidth : runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: UsedBandwidth , pub hrmp_watermark : :: core :: option :: Option < :: core :: primitive :: u32 > , pub consumed_go_ahead_signal : :: core :: option :: Option < runtime_types :: polkadot_primitives :: v6 :: UpgradeGoAhead > , # [codec (skip)] pub __subxt_unused_type_params : :: core :: marker :: PhantomData < _0 > } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UsedBandwidth { pub ump_msg_count : :: core :: primitive :: u32 , pub ump_total_bytes : :: core :: primitive :: u32 , pub hrmp_outgoing : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_parachain_primitives :: primitives :: Id , runtime_types :: cumulus_pallet_parachain_system :: unincluded_segment :: HrmpChannelUpdate > , } - } - } - pub mod cumulus_pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - InvalidFormat([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - UnsupportedVersion([::core::primitive::u8; 32usize]), - #[codec(index = 2)] - ExecutedDownward( - [::core::primitive::u8; 32usize], - runtime_types::staging_xcm::v4::traits::Outcome, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Relay, - #[codec(index = 1)] - SiblingParachain(runtime_types::polkadot_parachain_primitives::primitives::Id), - } - } - } - pub mod cumulus_pallet_xcmp_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 1)] - suspend_xcm_execution, - #[codec(index = 2)] - resume_xcm_execution, - #[codec(index = 3)] - update_suspend_threshold { new: ::core::primitive::u32 }, - #[codec(index = 4)] - update_drop_threshold { new: ::core::primitive::u32 }, - #[codec(index = 5)] - update_resume_threshold { new: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - BadQueueConfig, - #[codec(index = 1)] - AlreadySuspended, - #[codec(index = 2)] - AlreadyResumed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - XcmpMessageSent { message_hash: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundChannelDetails { - pub recipient: runtime_types::polkadot_parachain_primitives::primitives::Id, - pub state: runtime_types::cumulus_pallet_xcmp_queue::OutboundState, - pub signals_exist: ::core::primitive::bool, - pub first_index: ::core::primitive::u16, - pub last_index: ::core::primitive::u16, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OutboundState { - #[codec(index = 0)] - Ok, - #[codec(index = 1)] - Suspended, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueueConfigData { - pub suspend_threshold: ::core::primitive::u32, - pub drop_threshold: ::core::primitive::u32, - pub resume_threshold: ::core::primitive::u32, - } - } - pub mod cumulus_primitives_parachain_inherent { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageQueueChain(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainInherentData { - pub validation_data: - runtime_types::polkadot_primitives::v6::PersistedValidationData< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - pub relay_chain_state: runtime_types::sp_trie::storage_proof::StorageProof, - pub downward_messages: ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundDownwardMessage< - ::core::primitive::u32, - >, - >, - pub horizontal_messages: ::subxt::utils::KeyedVec< - runtime_types::polkadot_parachain_primitives::primitives::Id, - ::std::vec::Vec< - runtime_types::polkadot_core_primitives::InboundHrmpMessage< - ::core::primitive::u32, - >, - >, - >, - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commit<_0, _1, _2, _3> { - pub target_hash: _0, - pub target_number: _1, - pub precommits: ::std::vec::Vec< - runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedPrecommit<_0, _1, _2, _3> { - pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, - pub signature: _2, - pub id: _3, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProcessMessageError { - #[codec(index = 0)] - BadFormat, - #[codec(index = 1)] - Corrupt, - #[codec(index = 2)] - Unsupported, - #[codec(index = 3)] - Overweight(::sp_weights::Weight), - #[codec(index = 4)] - Yield, - } - } - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 9)] - authorize_upgrade { code_hash: ::subxt::utils::H256 }, - #[codec(index = 10)] - authorize_upgrade_without_checks { code_hash: ::subxt::utils::H256 }, - #[codec(index = 11)] - apply_authorized_upgrade { code: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - #[codec(index = 6)] - NothingAuthorized, - #[codec(index = 7)] - Unauthorized, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - #[codec(index = 6)] - UpgradeAuthorized { - code_hash: ::subxt::utils::H256, - check_version: ::core::primitive::bool, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: ::core::primitive::u32, - pub providers: ::core::primitive::u32, - pub sufficients: ::core::primitive::u32, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CodeUpgradeAuthorization { - pub code_hash: ::subxt::utils::H256, - pub check_version: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - #[codec(index = 9)] - force_adjust_total_issuance { - direction: runtime_types::pallet_balances::types::AdjustmentDirection, - #[codec(compact)] - delta: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - #[codec(index = 10)] - IssuanceDeactivated, - #[codec(index = 11)] - DeltaZero, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 21)] - TotalIssuanceForced { - old: ::core::primitive::u128, - new: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AdjustmentDirection { - #[codec(index = 0)] - Increase, - #[codec(index = 1)] - Decrease, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bridge_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - #[codec(index = 4)] - submit_finality_proof_ex { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - current_set_id: ::core::primitive::u64, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - #[codec(index = 8)] - InvalidAuthoritySetId, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u32, - hash: ::subxt::utils::H256, - grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< - ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - runtime_types::bp_header_chain::AuthoritySet, - >, - }, - } - } - pub mod storage_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - } - } - pub mod pallet_bridge_messages { - use super::runtime_types; - pub mod outbound_lane { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalConfirmationError { - #[codec(index = 0)] - FailedToConfirmFutureMessages, - #[codec(index = 1)] - EmptyUnrewardedRelayerEntry, - #[codec(index = 2)] - NonConsecutiveUnrewardedRelayerEntries, - #[codec(index = 3)] - TryingToConfirmMoreMessagesThanExpected, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] FailedToWithdrawMessageFee , # [codec (index = 6)] TooManyMessagesInTheProof , # [codec (index = 7)] InvalidMessagesProof , # [codec (index = 8)] InvalidMessagesDeliveryProof , # [codec (index = 9)] InvalidUnrewardedRelayersState , # [codec (index = 10)] InsufficientDispatchWeight , # [codec (index = 11)] MessageIsNotYetSent , # [codec (index = 12)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 13)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - } - } - pub mod pallet_bridge_parachains { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_parachain_heads { - at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), - parachains: ::std::vec::Vec<( - ::bp_polkadot_core::parachains::ParaId, - ::subxt::utils::H256, - )>, - parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, - }, - #[codec(index = 1)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 2)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnknownRelayChainBlock, - #[codec(index = 1)] - InvalidRelayChainBlockNumber, - #[codec(index = 2)] - HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 3)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 1)] - MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 2)] - IncorrectParachainHeadHash { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - actual_parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - RejectedObsoleteParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 4)] - RejectedLargeParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - parachain_head_size: ::core::primitive::u32, - }, - #[codec(index = 5)] - UpdatedParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - } - } - } - pub mod pallet_bridge_relayers { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim_rewards { - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - }, - #[codec(index = 1)] - register { valid_till: ::core::primitive::u32 }, - #[codec(index = 2)] - deregister, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NoRewardForRelayer, - #[codec(index = 1)] - FailedToPayReward, - #[codec(index = 2)] - InvalidRegistrationLease, - #[codec(index = 3)] - CannotReduceRegistrationLease, - #[codec(index = 4)] - FailedToReserve, - #[codec(index = 5)] - FailedToUnreserve, - #[codec(index = 6)] - NotRegistered, - #[codec(index = 7)] - RegistrationIsStillActive, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RewardRegistered { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 1)] - RewardPaid { - relayer: ::sp_core::crypto::AccountId32, - rewards_account_params: runtime_types::bp_relayers::RewardsAccountParams, - reward: ::core::primitive::u128, - }, - #[codec(index = 2)] - RegistrationUpdated { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - #[codec(index = 3)] - Deregistered { relayer: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - SlashedAndDeregistered { - relayer: ::sp_core::crypto::AccountId32, - registration: runtime_types::bp_relayers::registration::Registration< - ::core::primitive::u32, - ::core::primitive::u128, - >, - }, - } - } - } - pub mod pallet_collator_selection { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_invulnerables { new: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 1)] - set_desired_candidates { max: ::core::primitive::u32 }, - #[codec(index = 2)] - set_candidacy_bond { bond: ::core::primitive::u128 }, - #[codec(index = 3)] - register_as_candidate, - #[codec(index = 4)] - leave_intent, - #[codec(index = 5)] - add_invulnerable { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - remove_invulnerable { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 7)] - update_bond { new_deposit: ::core::primitive::u128 }, - #[codec(index = 8)] - take_candidate_slot { - deposit: ::core::primitive::u128, - target: ::sp_core::crypto::AccountId32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateInfo<_0, _1> { - pub who: _0, - pub deposit: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCandidates, - #[codec(index = 1)] - TooFewEligibleCollators, - #[codec(index = 2)] - AlreadyCandidate, - #[codec(index = 3)] - NotCandidate, - #[codec(index = 4)] - TooManyInvulnerables, - #[codec(index = 5)] - AlreadyInvulnerable, - #[codec(index = 6)] - NotInvulnerable, - #[codec(index = 7)] - NoAssociatedValidatorId, - #[codec(index = 8)] - ValidatorNotRegistered, - #[codec(index = 9)] - InsertToCandidateListFailed, - #[codec(index = 10)] - RemoveFromCandidateListFailed, - #[codec(index = 11)] - DepositTooLow, - #[codec(index = 12)] - UpdateCandidateListFailed, - #[codec(index = 13)] - InsufficientBond, - #[codec(index = 14)] - TargetIsNotCandidate, - #[codec(index = 15)] - IdenticalDeposit, - #[codec(index = 16)] - InvalidUnreserve, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewInvulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 1)] - InvulnerableAdded { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 2)] - InvulnerableRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 3)] - NewDesiredCandidates { desired_candidates: ::core::primitive::u32 }, - #[codec(index = 4)] - NewCandidacyBond { bond_amount: ::core::primitive::u128 }, - #[codec(index = 5)] - CandidateAdded { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 6)] - CandidateBondUpdated { - account_id: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 7)] - CandidateRemoved { account_id: ::sp_core::crypto::AccountId32 }, - #[codec(index = 8)] - CandidateReplaced { - old: ::sp_core::crypto::AccountId32, - new: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 9)] - InvalidInvulnerableSkipped { account_id: ::sp_core::crypto::AccountId32 }, - } - } - } - pub mod pallet_message_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - reap_page { - message_origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - page_index: ::core::primitive::u32, - }, - #[codec(index = 1)] - execute_overweight { - message_origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - page: ::core::primitive::u32, - index: ::core::primitive::u32, - weight_limit: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotReapable, - #[codec(index = 1)] - NoPage, - #[codec(index = 2)] - NoMessage, - #[codec(index = 3)] - AlreadyProcessed, - #[codec(index = 4)] - Queued, - #[codec(index = 5)] - InsufficientWeight, - #[codec(index = 6)] - TemporarilyUnprocessable, - #[codec(index = 7)] - QueuePaused, - #[codec(index = 8)] - RecursiveDisallowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ProcessingFailed { - id: ::subxt::utils::H256, - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - error: runtime_types::frame_support::traits::messages::ProcessMessageError, - }, - #[codec(index = 1)] - Processed { - id: ::subxt::utils::H256, - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - weight_used: ::sp_weights::Weight, - success: ::core::primitive::bool, - }, - #[codec(index = 2)] - OverweightEnqueued { - id: [::core::primitive::u8; 32usize], - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - page_index: ::core::primitive::u32, - message_index: ::core::primitive::u32, - }, - #[codec(index = 3)] - PageReaped { - origin: - runtime_types::bridge_hub_common::message_queue::AggregateMessageOrigin, - index: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BookState<_0> { - pub begin: ::core::primitive::u32, - pub end: ::core::primitive::u32, - pub count: ::core::primitive::u32, - pub ready_neighbours: - ::core::option::Option>, - pub message_count: ::core::primitive::u64, - pub size: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Neighbours<_0> { - pub prev: _0, - pub next: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Page<_0> { - pub remaining: _0, - pub remaining_size: _0, - pub first_index: _0, - pub first: _0, - pub last: _0, - pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box< - runtime_types::bridge_hub_westend_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_westend_runtime::RuntimeCall, - >, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: ::core::primitive::u32, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::bridge_hub_westend_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { - calls: - ::std::vec::Vec, - }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box< - runtime_types::bridge_hub_westend_runtime::RuntimeCall, - >, - }, - #[codec(index = 2)] - batch_all { - calls: - ::std::vec::Vec, - }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box< - runtime_types::bridge_hub_westend_runtime::OriginCaller, - >, - call: ::std::boxed::Box< - runtime_types::bridge_hub_westend_runtime::RuntimeCall, - >, - }, - #[codec(index = 4)] - force_batch { - calls: - ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box< - runtime_types::bridge_hub_westend_runtime::RuntimeCall, - >, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - #[codec(index = 11)] - transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - CannotCheckOutTeleport, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - #[codec(index = 20)] - InvalidAssetNotConcrete, - #[codec(index = 21)] - InvalidAssetUnknownReserve, - #[codec(index = 22)] - InvalidAssetUnsupportedReserve, - #[codec(index = 23)] - TooManyReserves, - #[codec(index = 24)] - LocalExecutionIncomplete, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted { outcome: runtime_types::staging_xcm::v4::traits::Outcome }, - #[codec(index = 1)] - Sent { - origin: runtime_types::staging_xcm::v4::location::Location, - destination: runtime_types::staging_xcm::v4::location::Location, - message: runtime_types::staging_xcm::v4::Xcm, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - UnexpectedResponse { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - }, - #[codec(index = 3)] - ResponseReady { - query_id: ::core::primitive::u64, - response: runtime_types::staging_xcm::v4::Response, - }, - #[codec(index = 4)] - Notified { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 5)] - NotifyOverweight { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - actual_weight: ::sp_weights::Weight, - max_budgeted_weight: ::sp_weights::Weight, - }, - #[codec(index = 6)] - NotifyDispatchError { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 7)] - NotifyDecodeFailed { - query_id: ::core::primitive::u64, - pallet_index: ::core::primitive::u8, - call_index: ::core::primitive::u8, - }, - #[codec(index = 8)] - InvalidResponder { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - expected_location: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 9)] - InvalidResponderVersion { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - }, - #[codec(index = 10)] - ResponseTaken { query_id: ::core::primitive::u64 }, - #[codec(index = 11)] - AssetsTrapped { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v4::location::Location, - assets: runtime_types::xcm::VersionedAssets, - }, - #[codec(index = 12)] - VersionChangeNotified { - destination: runtime_types::staging_xcm::v4::location::Location, - result: ::core::primitive::u32, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 13)] - SupportedVersionChanged { - location: runtime_types::staging_xcm::v4::location::Location, - version: ::core::primitive::u32, - }, - #[codec(index = 14)] - NotifyTargetSendFail { - location: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - error: runtime_types::xcm::v3::traits::Error, - }, - #[codec(index = 15)] - NotifyTargetMigrationFail { - location: runtime_types::xcm::VersionedLocation, - query_id: ::core::primitive::u64, - }, - #[codec(index = 16)] - InvalidQuerierVersion { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - }, - #[codec(index = 17)] - InvalidQuerier { - origin: runtime_types::staging_xcm::v4::location::Location, - query_id: ::core::primitive::u64, - expected_querier: runtime_types::staging_xcm::v4::location::Location, - maybe_actual_querier: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 18)] - VersionNotifyStarted { - destination: runtime_types::staging_xcm::v4::location::Location, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 19)] - VersionNotifyRequested { - destination: runtime_types::staging_xcm::v4::location::Location, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 20)] - VersionNotifyUnrequested { - destination: runtime_types::staging_xcm::v4::location::Location, - cost: runtime_types::staging_xcm::v4::asset::Assets, - message_id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 21)] - FeesPaid { - paying: runtime_types::staging_xcm::v4::location::Location, - fees: runtime_types::staging_xcm::v4::asset::Assets, - }, - #[codec(index = 22)] - AssetsClaimed { - hash: ::subxt::utils::H256, - origin: runtime_types::staging_xcm::v4::location::Location, - assets: runtime_types::xcm::VersionedAssets, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::staging_xcm::v4::location::Location), - #[codec(index = 1)] - Response(runtime_types::staging_xcm::v4::location::Location), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedLocation, - pub locker: runtime_types::xcm::VersionedLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain_primitives { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v6 { - use super::runtime_types; - pub mod async_backing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHostConfiguration { - pub max_code_size: ::core::primitive::u32, - pub max_head_data_size: ::core::primitive::u32, - pub max_upward_queue_count: ::core::primitive::u32, - pub max_upward_queue_size: ::core::primitive::u32, - pub max_upward_message_size: ::core::primitive::u32, - pub max_upward_message_num_per_candidate: ::core::primitive::u32, - pub hrmp_max_message_num_per_candidate: ::core::primitive::u32, - pub validation_upgrade_cooldown: ::core::primitive::u32, - pub validation_upgrade_delay: ::core::primitive::u32, - pub async_backing_params: - runtime_types::polkadot_primitives::v6::async_backing::AsyncBackingParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AbridgedHrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PersistedValidationData<_0, _1> { - pub parent_head: - runtime_types::polkadot_parachain_primitives::primitives::HeadData, - pub relay_parent_number: _1, - pub relay_parent_storage_root: _0, - pub max_pov_size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - } - } - pub mod snowbridge_core { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChannelId(pub [::core::primitive::u8; 32usize]); - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_consensus_aura { - use super::runtime_types; - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_trie { - use super::runtime_types; - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StorageProof { - pub trie_nodes: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod staging_parachain_info { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - } - } - pub mod staging_xcm { - use super::runtime_types; - pub mod v3 { - use super::runtime_types; - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - } - pub mod v4 { - use super::runtime_types; - pub mod asset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Asset { - pub id: runtime_types::staging_xcm::v4::asset::AssetId, - pub fun: runtime_types::staging_xcm::v4::asset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetFilter { - #[codec(index = 0)] - Definite(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 1)] - Wild(runtime_types::staging_xcm::v4::asset::WildAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AssetId(pub runtime_types::staging_xcm::v4::location::Location); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Assets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::staging_xcm::v4::asset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::staging_xcm::v4::asset::AssetId, - fun: runtime_types::staging_xcm::v4::asset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::staging_xcm::v4::asset::AssetId, - fun: runtime_types::staging_xcm::v4::asset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - } - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: ::core::option::Option< - runtime_types::staging_xcm::v4::junction::NetworkId, - >, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: ::core::option::Option< - runtime_types::staging_xcm::v4::junction::NetworkId, - >, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: ::core::option::Option< - runtime_types::staging_xcm::v4::junction::NetworkId, - >, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::staging_xcm::v4::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - #[codec(index = 10)] - PolkadotBulletin, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1([runtime_types::staging_xcm::v4::junction::Junction; 1usize]), - #[codec(index = 2)] - X2([runtime_types::staging_xcm::v4::junction::Junction; 2usize]), - #[codec(index = 3)] - X3([runtime_types::staging_xcm::v4::junction::Junction; 3usize]), - #[codec(index = 4)] - X4([runtime_types::staging_xcm::v4::junction::Junction; 4usize]), - #[codec(index = 5)] - X5([runtime_types::staging_xcm::v4::junction::Junction; 5usize]), - #[codec(index = 6)] - X6([runtime_types::staging_xcm::v4::junction::Junction; 6usize]), - #[codec(index = 7)] - X7([runtime_types::staging_xcm::v4::junction::Junction; 7usize]), - #[codec(index = 8)] - X8([runtime_types::staging_xcm::v4::junction::Junction; 8usize]), - } - } - pub mod location { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Location { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::staging_xcm::v4::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete { used: ::sp_weights::Weight }, - #[codec(index = 1)] - Incomplete { - used: ::sp_weights::Weight, - error: runtime_types::xcm::v3::traits::Error, - }, - #[codec(index = 2)] - Error { error: runtime_types::xcm::v3::traits::Error }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::staging_xcm::v4::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::staging_xcm::v4::asset::AssetFilter, - want: runtime_types::staging_xcm::v4::asset::Assets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - reserve: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::staging_xcm::v4::asset::Asset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::staging_xcm::v4::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::staging_xcm::v4::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - ticket: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 29)] - ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::staging_xcm::v4::junction::NetworkId, - destination: runtime_types::staging_xcm::v4::junctions::Junctions, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - unlocker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - target: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::staging_xcm::v4::asset::Asset, - owner: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::staging_xcm::v4::asset::Asset, - locker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v4::location::Location), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::staging_xcm::v4::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::staging_xcm::v4::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - beneficiary: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::staging_xcm::v4::asset::AssetFilter, - want: runtime_types::staging_xcm::v4::asset::Assets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - reserve: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - dest: runtime_types::staging_xcm::v4::location::Location, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - assets: runtime_types::staging_xcm::v4::asset::AssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::staging_xcm::v4::asset::Asset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::staging_xcm::v4::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::staging_xcm::v4::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::staging_xcm::v4::asset::Assets, - ticket: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 29)] - ExpectAsset(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::staging_xcm::v4::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::staging_xcm::v4::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::staging_xcm::v4::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::staging_xcm::v4::junction::NetworkId, - destination: runtime_types::staging_xcm::v4::junctions::Junctions, - xcm: runtime_types::staging_xcm::v4::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - unlocker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::staging_xcm::v4::asset::Asset, - target: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::staging_xcm::v4::asset::Asset, - owner: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::staging_xcm::v4::asset::Asset, - locker: runtime_types::staging_xcm::v4::location::Location, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v4::location::Location), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v4::location::Location, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::staging_xcm::v4::location::Location, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::staging_xcm::v4::asset::Assets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::staging_xcm::v4::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded2 { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - #[codec(index = 10)] - PolkadotBulletin, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction2 { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded2, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm2), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm2), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::staging_xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::staging_xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm2(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::asset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::asset::Assets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::staging_xcm::v3::multilocation::MultiLocation), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::location::Location), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::Xcm), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm2 { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm2), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm2), - #[codec(index = 4)] - V4(runtime_types::staging_xcm::v4::Xcm2), - } - } - } -} diff --git a/relays/client-bridge-hub-westend/src/lib.rs b/relays/client-bridge-hub-westend/src/lib.rs deleted file mode 100644 index 049fa4649609e..0000000000000 --- a/relays/client-bridge-hub-westend/src/lib.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2022 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 . - -//! Types used to connect to the BridgeHub-Westend-Substrate parachain. - -pub mod codegen_runtime; - -use bp_bridge_hub_westend::{SignedExtension, AVERAGE_BLOCK_INTERVAL}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use codec::Encode; -use relay_substrate_client::{ - calls::UtilityCall as MockUtilityCall, Chain, ChainWithBalances, ChainWithMessages, - ChainWithRuntimeVersion, ChainWithTransactions, ChainWithUtilityPallet, - Error as SubstrateError, MockedRuntimeUtilityPallet, SignParam, SimpleRuntimeVersion, - UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::bridge_hub_westend_runtime::RuntimeCall; -pub type BridgeMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; -pub type BridgeGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -pub type BridgeParachainCall = runtime_types::pallet_bridge_parachains::pallet::Call; -type UncheckedExtrinsic = bp_bridge_hub_westend::UncheckedExtrinsic; -type UtilityCall = runtime_types::pallet_utility::pallet::Call; - -/// Westend chain definition -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct BridgeHubWestend; - -impl UnderlyingChainProvider for BridgeHubWestend { - type Chain = bp_bridge_hub_westend::BridgeHubWestend; -} - -impl Chain for BridgeHubWestend { - const NAME: &'static str = "BridgeHubWestend"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_bridge_hub_westend::BEST_FINALIZED_BRIDGE_HUB_WESTEND_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = AVERAGE_BLOCK_INTERVAL; - - type SignedBlock = bp_bridge_hub_westend::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithBalances for BridgeHubWestend { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_bridge_hub_westend::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl From> for RuntimeCall { - fn from(value: MockUtilityCall) -> RuntimeCall { - match value { - MockUtilityCall::batch_all(calls) => - RuntimeCall::Utility(UtilityCall::batch_all { calls }), - } - } -} - -impl ChainWithUtilityPallet for BridgeHubWestend { - type UtilityPallet = MockedRuntimeUtilityPallet; -} - -impl ChainWithTransactions for BridgeHubWestend { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - (((), ()), ((), ())), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(UncheckedExtrinsic::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithMessages for BridgeHubWestend { - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = - Some(bp_bridge_hub_westend::WITH_BRIDGE_HUB_WESTEND_RELAYERS_PALLET_NAME); - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_westend::TO_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_bridge_hub_westend::FROM_BRIDGE_HUB_WESTEND_MESSAGE_DETAILS_METHOD; -} - -impl ChainWithRuntimeVersion for BridgeHubWestend { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 4 }); -} diff --git a/relays/client-kusama/Cargo.toml b/relays/client-kusama/Cargo.toml deleted file mode 100644 index c459f347af1ed..0000000000000 --- a/relays/client-kusama/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "relay-kusama-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-kusama = { path = "../../chains/chain-kusama" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } - -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies - -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-kusama/src/codegen_runtime.rs b/relays/client-kusama/src/codegen_runtime.rs deleted file mode 100644 index 3c37d61f4cf19..0000000000000 --- a/relays/client-kusama/src/codegen_runtime.rs +++ /dev/null @@ -1,8338 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://kusama-rpc.polkadot.io:443 - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -pub mod api { - use super::api as root_mod; - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_btree_map { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedBTreeMap<_0, _1>(pub ::subxt::utils::KeyedVec<_0, _1>); - } - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Equivocation<_0, _1, _2> { - pub round_number: ::core::primitive::u64, - pub identity: _0, - pub first: (_1, _2), - pub second: (_1, _2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Prevote<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PostDispatchInfo { - pub actual_weight: ::core::option::Option<::sp_weights::Weight>, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProcessMessageError { - #[codec(index = 0)] - BadFormat, - #[codec(index = 1)] - Corrupt, - #[codec(index = 2)] - Unsupported, - #[codec(index = 3)] - Overweight(::sp_weights::Weight), - #[codec(index = 4)] - Yield, - } - } - pub mod misc { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WrapperOpaque<_0>( - #[codec(compact)] pub ::core::primitive::u32, - pub _0, - ); - } - pub mod preimages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Bounded<_0> { - #[codec(index = 0)] - Legacy { - hash: ::subxt::utils::H256, - }, - #[codec(index = 1)] - Inline( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Lookup { - hash: ::subxt::utils::H256, - len: ::core::primitive::u32, - }, - __Ignore(::core::marker::PhantomData<_0>), - } - } - pub mod schedule { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchTime<_0> { - #[codec(index = 0)] - At(_0), - #[codec(index = 1)] - After(_0), - } - } - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletId(pub [::core::primitive::u8; 8usize]); - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod kusama_runtime { - use super::runtime_types; - pub mod governance { - use super::runtime_types; - pub mod origins { - use super::runtime_types; - pub mod pallet_custom_origins { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Origin { - #[codec(index = 0)] - StakingAdmin, - #[codec(index = 1)] - Treasurer, - #[codec(index = 2)] - FellowshipAdmin, - #[codec(index = 3)] - GeneralAdmin, - #[codec(index = 4)] - AuctionAdmin, - #[codec(index = 5)] - LeaseAdmin, - #[codec(index = 6)] - ReferendumCanceller, - #[codec(index = 7)] - ReferendumKiller, - #[codec(index = 8)] - SmallTipper, - #[codec(index = 9)] - BigTipper, - #[codec(index = 10)] - SmallSpender, - #[codec(index = 11)] - MediumSpender, - #[codec(index = 12)] - BigSpender, - #[codec(index = 13)] - WhitelistedCaller, - #[codec(index = 14)] - FellowshipInitiates, - #[codec(index = 15)] - Fellows, - #[codec(index = 16)] - FellowshipExperts, - #[codec(index = 17)] - FellowshipMasters, - #[codec(index = 18)] - Fellowship1Dan, - #[codec(index = 19)] - Fellowship2Dan, - #[codec(index = 20)] - Fellowship3Dan, - #[codec(index = 21)] - Fellowship4Dan, - #[codec(index = 22)] - Fellowship5Dan, - #[codec(index = 23)] - Fellowship6Dan, - #[codec(index = 24)] - Fellowship7Dan, - #[codec(index = 25)] - Fellowship8Dan, - #[codec(index = 26)] - Fellowship9Dan, - } - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct NposCompactSolution24 { - pub votes1: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes2: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - ( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ), - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes3: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 2usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes4: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 3usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes5: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 4usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes6: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 5usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes7: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 6usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes8: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 7usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes9: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 8usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes10: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 9usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes11: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 10usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes12: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 11usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes13: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 12usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes14: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 13usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes15: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 14usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes16: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 15usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes17: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 16usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes18: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 17usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes19: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 18usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes20: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 19usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes21: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 20usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes22: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 21usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes23: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 22usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes24: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 23usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - # [codec (index = 0)] system (runtime_types :: frame_support :: dispatch :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 43)] Origins (runtime_types :: kusama_runtime :: governance :: origins :: pallet_custom_origins :: Origin ,) , # [codec (index = 50)] ParachainsOrigin (runtime_types :: polkadot_runtime_parachains :: origin :: pallet :: Origin ,) , # [codec (index = 99)] XcmPallet (runtime_types :: pallet_xcm :: pallet :: Origin ,) , # [codec (index = 4)] Void (runtime_types :: sp_core :: Void ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProxyType { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - NonTransfer, - #[codec(index = 2)] - Governance, - #[codec(index = 3)] - Staking, - #[codec(index = 4)] - IdentityJudgement, - #[codec(index = 5)] - CancelProxy, - #[codec(index = 6)] - Auction, - #[codec(index = 7)] - Society, - #[codec(index = 8)] - NominationPools, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - Babe(runtime_types::pallet_babe::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 3)] - Indices(runtime_types::pallet_indices::pallet::Call), - #[codec(index = 4)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 6)] - Staking(runtime_types::pallet_staking::pallet::pallet::Call), - #[codec(index = 8)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 10)] - Grandpa(runtime_types::pallet_grandpa::pallet::Call), - #[codec(index = 11)] - ImOnline(runtime_types::pallet_im_online::pallet::Call), - #[codec(index = 18)] - Treasury(runtime_types::pallet_treasury::pallet::Call), - #[codec(index = 20)] - ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Call), - #[codec(index = 21)] - Referenda(runtime_types::pallet_referenda::pallet::Call), - #[codec(index = 22)] - FellowshipCollective(runtime_types::pallet_ranked_collective::pallet::Call), - #[codec(index = 23)] - FellowshipReferenda(runtime_types::pallet_referenda::pallet::Call), - #[codec(index = 44)] - Whitelist(runtime_types::pallet_whitelist::pallet::Call), - #[codec(index = 19)] - Claims(runtime_types::polkadot_runtime_common::claims::pallet::Call), - #[codec(index = 24)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 25)] - Identity(runtime_types::pallet_identity::pallet::Call), - #[codec(index = 26)] - Society(runtime_types::pallet_society::pallet::Call), - #[codec(index = 27)] - Recovery(runtime_types::pallet_recovery::pallet::Call), - #[codec(index = 28)] - Vesting(runtime_types::pallet_vesting::pallet::Call), - #[codec(index = 29)] - Scheduler(runtime_types::pallet_scheduler::pallet::Call), - #[codec(index = 30)] - Proxy(runtime_types::pallet_proxy::pallet::Call), - #[codec(index = 31)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 32)] - Preimage(runtime_types::pallet_preimage::pallet::Call), - #[codec(index = 35)] - Bounties(runtime_types::pallet_bounties::pallet::Call), - #[codec(index = 40)] - ChildBounties(runtime_types::pallet_child_bounties::pallet::Call), - #[codec(index = 37)] - ElectionProviderMultiPhase( - runtime_types::pallet_election_provider_multi_phase::pallet::Call, - ), - #[codec(index = 38)] - Nis(runtime_types::pallet_nis::pallet::Call), - #[codec(index = 45)] - NisCounterpartBalances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 39)] - VoterList(runtime_types::pallet_bags_list::pallet::Call), - #[codec(index = 41)] - NominationPools(runtime_types::pallet_nomination_pools::pallet::Call), - #[codec(index = 42)] - FastUnstake(runtime_types::pallet_fast_unstake::pallet::Call), - #[codec(index = 51)] - Configuration( - runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, - ), - #[codec(index = 52)] - ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), - #[codec(index = 53)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), - #[codec(index = 54)] - ParaInherent( - runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, - ), - #[codec(index = 56)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), - #[codec(index = 57)] - Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), - #[codec(index = 60)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), - #[codec(index = 62)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), - #[codec(index = 63)] - ParasSlashing( - runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, - ), - #[codec(index = 70)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), - #[codec(index = 71)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), - #[codec(index = 72)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), - #[codec(index = 73)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 100)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 3)] - Indices(runtime_types::pallet_indices::pallet::Event), - #[codec(index = 4)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 33)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 6)] - Staking(runtime_types::pallet_staking::pallet::pallet::Event), - #[codec(index = 7)] - Offences(runtime_types::pallet_offences::pallet::Event), - #[codec(index = 8)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 10)] - Grandpa(runtime_types::pallet_grandpa::pallet::Event), - #[codec(index = 11)] - ImOnline(runtime_types::pallet_im_online::pallet::Event), - #[codec(index = 18)] - Treasury(runtime_types::pallet_treasury::pallet::Event), - #[codec(index = 20)] - ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Event), - #[codec(index = 21)] - Referenda(runtime_types::pallet_referenda::pallet::Event), - #[codec(index = 22)] - FellowshipCollective(runtime_types::pallet_ranked_collective::pallet::Event), - #[codec(index = 23)] - FellowshipReferenda(runtime_types::pallet_referenda::pallet::Event), - #[codec(index = 44)] - Whitelist(runtime_types::pallet_whitelist::pallet::Event), - #[codec(index = 19)] - Claims(runtime_types::polkadot_runtime_common::claims::pallet::Event), - #[codec(index = 24)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 25)] - Identity(runtime_types::pallet_identity::pallet::Event), - #[codec(index = 26)] - Society(runtime_types::pallet_society::pallet::Event), - #[codec(index = 27)] - Recovery(runtime_types::pallet_recovery::pallet::Event), - #[codec(index = 28)] - Vesting(runtime_types::pallet_vesting::pallet::Event), - #[codec(index = 29)] - Scheduler(runtime_types::pallet_scheduler::pallet::Event), - #[codec(index = 30)] - Proxy(runtime_types::pallet_proxy::pallet::Event), - #[codec(index = 31)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 32)] - Preimage(runtime_types::pallet_preimage::pallet::Event), - #[codec(index = 35)] - Bounties(runtime_types::pallet_bounties::pallet::Event), - #[codec(index = 40)] - ChildBounties(runtime_types::pallet_child_bounties::pallet::Event), - #[codec(index = 37)] - ElectionProviderMultiPhase( - runtime_types::pallet_election_provider_multi_phase::pallet::Event, - ), - #[codec(index = 38)] - Nis(runtime_types::pallet_nis::pallet::Event), - #[codec(index = 45)] - NisCounterpartBalances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 39)] - VoterList(runtime_types::pallet_bags_list::pallet::Event), - #[codec(index = 41)] - NominationPools(runtime_types::pallet_nomination_pools::pallet::Event), - #[codec(index = 42)] - FastUnstake(runtime_types::pallet_fast_unstake::pallet::Event), - #[codec(index = 53)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), - #[codec(index = 56)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), - #[codec(index = 60)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), - #[codec(index = 62)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), - #[codec(index = 70)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), - #[codec(index = 71)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), - #[codec(index = 72)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), - #[codec(index = 73)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 100)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeHoldReason { - #[codec(index = 38)] - Nis(runtime_types::pallet_nis::pallet::HoldReason), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, - pub babe: runtime_types::sp_consensus_babe::app::Public, - pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, - pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, - pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, - } - } - pub mod pallet_babe { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - plan_config_change { - config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEquivocationProof, - #[codec(index = 1)] - InvalidKeyOwnershipProof, - #[codec(index = 2)] - DuplicateOffenceReport, - #[codec(index = 3)] - InvalidConfiguration, - } - } - } - pub mod pallet_bags_list { - use super::runtime_types; - pub mod list { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bag { - pub head: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub tail: ::core::option::Option<::sp_core::crypto::AccountId32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ListError { - #[codec(index = 0)] - Duplicate, - #[codec(index = 1)] - NotHeavier, - #[codec(index = 2)] - NotInSameBag, - #[codec(index = 3)] - NodeNotFound, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Node { - pub id: ::sp_core::crypto::AccountId32, - pub prev: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub next: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub bag_upper: ::core::primitive::u64, - pub score: ::core::primitive::u64, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - rebag { - dislocated: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - put_in_front_of { - lighter: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - List(runtime_types::pallet_bags_list::list::ListError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Rebagged { - who: ::sp_core::crypto::AccountId32, - from: ::core::primitive::u64, - to: ::core::primitive::u64, - }, - #[codec(index = 1)] - ScoreUpdated { - who: ::sp_core::crypto::AccountId32, - new_score: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - set_balance_deprecated { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - #[codec(compact)] - old_reserved: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 7)] - transfer { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bounties { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose_bounty { - #[codec(compact)] - value: ::core::primitive::u128, - description: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - approve_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 2)] - propose_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 3)] - unassign_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 4)] - accept_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 5)] - award_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - claim_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 7)] - close_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 8)] - extend_bounty_expiry { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - remark: ::std::vec::Vec<::core::primitive::u8>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InsufficientProposersBalance, - #[codec(index = 1)] - InvalidIndex, - #[codec(index = 2)] - ReasonTooBig, - #[codec(index = 3)] - UnexpectedStatus, - #[codec(index = 4)] - RequireCurator, - #[codec(index = 5)] - InvalidValue, - #[codec(index = 6)] - InvalidFee, - #[codec(index = 7)] - PendingPayout, - #[codec(index = 8)] - Premature, - #[codec(index = 9)] - HasActiveChildBounty, - #[codec(index = 10)] - TooManyQueued, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BountyProposed { index: ::core::primitive::u32 }, - #[codec(index = 1)] - BountyRejected { index: ::core::primitive::u32, bond: ::core::primitive::u128 }, - #[codec(index = 2)] - BountyBecameActive { index: ::core::primitive::u32 }, - #[codec(index = 3)] - BountyAwarded { - index: ::core::primitive::u32, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 4)] - BountyClaimed { - index: ::core::primitive::u32, - payout: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 5)] - BountyCanceled { index: ::core::primitive::u32 }, - #[codec(index = 6)] - BountyExtended { index: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bounty<_0, _1, _2> { - pub proposer: _0, - pub value: _1, - pub fee: _1, - pub curator_deposit: _1, - pub bond: _1, - pub status: runtime_types::pallet_bounties::BountyStatus<_0, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BountyStatus<_0, _1> { - #[codec(index = 0)] - Proposed, - #[codec(index = 1)] - Approved, - #[codec(index = 2)] - Funded, - #[codec(index = 3)] - CuratorProposed { curator: _0 }, - #[codec(index = 4)] - Active { curator: _0, update_due: _1 }, - #[codec(index = 5)] - PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, - } - } - pub mod pallet_child_bounties { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - value: ::core::primitive::u128, - description: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - propose_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 2)] - accept_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 3)] - unassign_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 4)] - award_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - claim_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 6)] - close_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParentBountyNotActive, - #[codec(index = 1)] - InsufficientBountyBalance, - #[codec(index = 2)] - TooManyChildBounties, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Added { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, - #[codec(index = 1)] - Awarded { - index: ::core::primitive::u32, - child_index: ::core::primitive::u32, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 2)] - Claimed { - index: ::core::primitive::u32, - child_index: ::core::primitive::u32, - payout: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Canceled { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChildBounty<_0, _1, _2> { - pub parent_bounty: _2, - pub value: _1, - pub fee: _1, - pub curator_deposit: _1, - pub status: runtime_types::pallet_child_bounties::ChildBountyStatus<_0, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ChildBountyStatus<_0, _1> { - #[codec(index = 0)] - Added, - #[codec(index = 1)] - CuratorProposed { curator: _0 }, - #[codec(index = 2)] - Active { curator: _0 }, - #[codec(index = 3)] - PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, - } - } - pub mod pallet_conviction_voting { - use super::runtime_types; - pub mod conviction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Conviction { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Locked1x, - #[codec(index = 2)] - Locked2x, - #[codec(index = 3)] - Locked3x, - #[codec(index = 4)] - Locked4x, - #[codec(index = 5)] - Locked5x, - #[codec(index = 6)] - Locked6x, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vote { - #[codec(compact)] - poll_index: ::core::primitive::u32, - vote: runtime_types::pallet_conviction_voting::vote::AccountVote< - ::core::primitive::u128, - >, - }, - #[codec(index = 1)] - delegate { - class: ::core::primitive::u16, - to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, - balance: ::core::primitive::u128, - }, - #[codec(index = 2)] - undelegate { class: ::core::primitive::u16 }, - #[codec(index = 3)] - unlock { - class: ::core::primitive::u16, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - remove_vote { - class: ::core::option::Option<::core::primitive::u16>, - index: ::core::primitive::u32, - }, - #[codec(index = 5)] - remove_other_vote { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - class: ::core::primitive::u16, - index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotOngoing, - #[codec(index = 1)] - NotVoter, - #[codec(index = 2)] - NoPermission, - #[codec(index = 3)] - NoPermissionYet, - #[codec(index = 4)] - AlreadyDelegating, - #[codec(index = 5)] - AlreadyVoting, - #[codec(index = 6)] - InsufficientFunds, - #[codec(index = 7)] - NotDelegating, - #[codec(index = 8)] - Nonsense, - #[codec(index = 9)] - MaxVotesReached, - #[codec(index = 10)] - ClassNeeded, - #[codec(index = 11)] - BadClass, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Delegated(::sp_core::crypto::AccountId32, ::sp_core::crypto::AccountId32), - #[codec(index = 1)] - Undelegated(::sp_core::crypto::AccountId32), - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Delegations<_0> { - pub votes: _0, - pub capital: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Tally<_0> { - pub ayes: _0, - pub nays: _0, - pub support: _0, - } - } - pub mod vote { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AccountVote<_0> { - #[codec(index = 0)] - Standard { - vote: runtime_types::pallet_conviction_voting::vote::Vote, - balance: _0, - }, - #[codec(index = 1)] - Split { aye: _0, nay: _0 }, - #[codec(index = 2)] - SplitAbstain { aye: _0, nay: _0, abstain: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Casting<_0, _1, _2> { - pub votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _1, - runtime_types::pallet_conviction_voting::vote::AccountVote<_0>, - )>, - pub delegations: - runtime_types::pallet_conviction_voting::types::Delegations<_0>, - pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_1, _0>, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Delegating<_0, _1, _2> { - pub balance: _0, - pub target: _1, - pub conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, - pub delegations: - runtime_types::pallet_conviction_voting::types::Delegations<_0>, - pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_2, _0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PriorLock<_0, _1>(pub _0, pub _1); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Vote(pub ::core::primitive::u8); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Voting<_0, _1, _2, _3> { - #[codec(index = 0)] - Casting(runtime_types::pallet_conviction_voting::vote::Casting<_0, _2, _2>), - #[codec(index = 1)] - Delegating( - runtime_types::pallet_conviction_voting::vote::Delegating<_0, _1, _2>, - ), - __Ignore(::core::marker::PhantomData<_3>), - } - } - } - pub mod pallet_election_provider_multi_phase { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] submit_unsigned { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: kusama_runtime :: NposCompactSolution24 > > , witness : runtime_types :: pallet_election_provider_multi_phase :: SolutionOrSnapshotSize , } , # [codec (index = 1)] set_minimum_untrusted_score { maybe_next_score : :: core :: option :: Option < runtime_types :: sp_npos_elections :: ElectionScore > , } , # [codec (index = 2)] set_emergency_election_result { supports : :: std :: vec :: Vec < (:: sp_core :: crypto :: AccountId32 , runtime_types :: sp_npos_elections :: Support < :: sp_core :: crypto :: AccountId32 > ,) > , } , # [codec (index = 3)] submit { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: kusama_runtime :: NposCompactSolution24 > > , } , # [codec (index = 4)] governance_fallback { maybe_max_voters : :: core :: option :: Option < :: core :: primitive :: u32 > , maybe_max_targets : :: core :: option :: Option < :: core :: primitive :: u32 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PreDispatchEarlySubmission, - #[codec(index = 1)] - PreDispatchWrongWinnerCount, - #[codec(index = 2)] - PreDispatchWeakSubmission, - #[codec(index = 3)] - SignedQueueFull, - #[codec(index = 4)] - SignedCannotPayDeposit, - #[codec(index = 5)] - SignedInvalidWitness, - #[codec(index = 6)] - SignedTooMuchWeight, - #[codec(index = 7)] - OcwCallWrongEra, - #[codec(index = 8)] - MissingSnapshotMetadata, - #[codec(index = 9)] - InvalidSubmissionIndex, - #[codec(index = 10)] - CallNotAllowed, - #[codec(index = 11)] - FallbackFailed, - #[codec(index = 12)] - BoundNotMet, - #[codec(index = 13)] - TooManyWinners, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - SolutionStored { - compute: - runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - origin: ::core::option::Option<::sp_core::crypto::AccountId32>, - prev_ejected: ::core::primitive::bool, - }, - #[codec(index = 1)] - ElectionFinalized { - compute: - runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - score: runtime_types::sp_npos_elections::ElectionScore, - }, - #[codec(index = 2)] - ElectionFailed, - #[codec(index = 3)] - Rewarded { - account: ::sp_core::crypto::AccountId32, - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - Slashed { - account: ::sp_core::crypto::AccountId32, - value: ::core::primitive::u128, - }, - #[codec(index = 5)] - PhaseTransitioned { - from: runtime_types::pallet_election_provider_multi_phase::Phase< - ::core::primitive::u32, - >, - to: runtime_types::pallet_election_provider_multi_phase::Phase< - ::core::primitive::u32, - >, - round: ::core::primitive::u32, - }, - } - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedSubmission<_0, _1, _2> { - pub who: _0, - pub deposit: _1, - pub raw_solution: - runtime_types::pallet_election_provider_multi_phase::RawSolution<_2>, - pub call_fee: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ElectionCompute { - #[codec(index = 0)] - OnChain, - #[codec(index = 1)] - Signed, - #[codec(index = 2)] - Unsigned, - #[codec(index = 3)] - Fallback, - #[codec(index = 4)] - Emergency, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase<_0> { - #[codec(index = 0)] - Off, - #[codec(index = 1)] - Signed, - #[codec(index = 2)] - Unsigned((::core::primitive::bool, _0)), - #[codec(index = 3)] - Emergency, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RawSolution<_0> { - pub solution: _0, - pub score: runtime_types::sp_npos_elections::ElectionScore, - pub round: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReadySolution { - pub supports: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::sp_core::crypto::AccountId32, - runtime_types::sp_npos_elections::Support<::sp_core::crypto::AccountId32>, - )>, - pub score: runtime_types::sp_npos_elections::ElectionScore, - pub compute: runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RoundSnapshot<_0, _1> { - pub voters: ::std::vec::Vec<_1>, - pub targets: ::std::vec::Vec<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SolutionOrSnapshotSize { - #[codec(compact)] - pub voters: ::core::primitive::u32, - #[codec(compact)] - pub targets: ::core::primitive::u32, - } - } - pub mod pallet_fast_unstake { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register_fast_unstake, - #[codec(index = 1)] - deregister, - #[codec(index = 2)] - control { eras_to_check: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotController, - #[codec(index = 1)] - AlreadyQueued, - #[codec(index = 2)] - NotFullyBonded, - #[codec(index = 3)] - NotQueued, - #[codec(index = 4)] - AlreadyHead, - #[codec(index = 5)] - CallNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Unstaked { - stash: ::sp_core::crypto::AccountId32, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - Slashed { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - InternalError, - #[codec(index = 3)] - BatchChecked { eras: ::std::vec::Vec<::core::primitive::u32> }, - #[codec(index = 4)] - BatchFinished { size: ::core::primitive::u32 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnstakeRequest { - pub stashes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - )>, - pub checked: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u32, - >, - } - } - } - pub mod pallet_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - note_stalled { - delay: ::core::primitive::u32, - best_finalized_block_number: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PauseFailed, - #[codec(index = 1)] - ResumeFailed, - #[codec(index = 2)] - ChangePending, - #[codec(index = 3)] - TooSoon, - #[codec(index = 4)] - InvalidKeyOwnershipProof, - #[codec(index = 5)] - InvalidEquivocationProof, - #[codec(index = 6)] - DuplicateOffenceReport, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewAuthorities { - authority_set: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - }, - #[codec(index = 1)] - Paused, - #[codec(index = 2)] - Resumed, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredPendingChange<_0> { - pub scheduled_at: _0, - pub delay: _0, - pub next_authorities: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub forced: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StoredState<_0> { - #[codec(index = 0)] - Live, - #[codec(index = 1)] - PendingPause { scheduled_at: _0, delay: _0 }, - #[codec(index = 2)] - Paused, - #[codec(index = 3)] - PendingResume { scheduled_at: _0, delay: _0 }, - } - } - pub mod pallet_identity { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_registrar { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - set_identity { - info: - ::std::boxed::Box, - }, - #[codec(index = 2)] - set_subs { - subs: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_identity::types::Data, - )>, - }, - #[codec(index = 3)] - clear_identity, - #[codec(index = 4)] - request_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - #[codec(compact)] - max_fee: ::core::primitive::u128, - }, - #[codec(index = 5)] - cancel_request { reg_index: ::core::primitive::u32 }, - #[codec(index = 6)] - set_fee { - #[codec(compact)] - index: ::core::primitive::u32, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 7)] - set_account_id { - #[codec(compact)] - index: ::core::primitive::u32, - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 8)] - set_fields { - #[codec(compact)] - index: ::core::primitive::u32, - fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - }, - #[codec(index = 9)] - provide_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - judgement: runtime_types::pallet_identity::types::Judgement< - ::core::primitive::u128, - >, - identity: ::subxt::utils::H256, - }, - #[codec(index = 10)] - kill_identity { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 11)] - add_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 12)] - rename_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 13)] - remove_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 14)] - quit_sub, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManySubAccounts, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotNamed, - #[codec(index = 3)] - EmptyIndex, - #[codec(index = 4)] - FeeChanged, - #[codec(index = 5)] - NoIdentity, - #[codec(index = 6)] - StickyJudgement, - #[codec(index = 7)] - JudgementGiven, - #[codec(index = 8)] - InvalidJudgement, - #[codec(index = 9)] - InvalidIndex, - #[codec(index = 10)] - InvalidTarget, - #[codec(index = 11)] - TooManyFields, - #[codec(index = 12)] - TooManyRegistrars, - #[codec(index = 13)] - AlreadyClaimed, - #[codec(index = 14)] - NotSub, - #[codec(index = 15)] - NotOwned, - #[codec(index = 16)] - JudgementForDifferentIdentity, - #[codec(index = 17)] - JudgementPaymentFailed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IdentitySet { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - IdentityCleared { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 2)] - IdentityKilled { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 3)] - JudgementRequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 4)] - JudgementUnrequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 5)] - JudgementGiven { - target: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - RegistrarAdded { registrar_index: ::core::primitive::u32 }, - #[codec(index = 7)] - SubIdentityAdded { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 8)] - SubIdentityRemoved { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 9)] - SubIdentityRevoked { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct BitFlags<_0>( - pub ::core::primitive::u64, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Data { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Raw0([::core::primitive::u8; 0usize]), - #[codec(index = 2)] - Raw1([::core::primitive::u8; 1usize]), - #[codec(index = 3)] - Raw2([::core::primitive::u8; 2usize]), - #[codec(index = 4)] - Raw3([::core::primitive::u8; 3usize]), - #[codec(index = 5)] - Raw4([::core::primitive::u8; 4usize]), - #[codec(index = 6)] - Raw5([::core::primitive::u8; 5usize]), - #[codec(index = 7)] - Raw6([::core::primitive::u8; 6usize]), - #[codec(index = 8)] - Raw7([::core::primitive::u8; 7usize]), - #[codec(index = 9)] - Raw8([::core::primitive::u8; 8usize]), - #[codec(index = 10)] - Raw9([::core::primitive::u8; 9usize]), - #[codec(index = 11)] - Raw10([::core::primitive::u8; 10usize]), - #[codec(index = 12)] - Raw11([::core::primitive::u8; 11usize]), - #[codec(index = 13)] - Raw12([::core::primitive::u8; 12usize]), - #[codec(index = 14)] - Raw13([::core::primitive::u8; 13usize]), - #[codec(index = 15)] - Raw14([::core::primitive::u8; 14usize]), - #[codec(index = 16)] - Raw15([::core::primitive::u8; 15usize]), - #[codec(index = 17)] - Raw16([::core::primitive::u8; 16usize]), - #[codec(index = 18)] - Raw17([::core::primitive::u8; 17usize]), - #[codec(index = 19)] - Raw18([::core::primitive::u8; 18usize]), - #[codec(index = 20)] - Raw19([::core::primitive::u8; 19usize]), - #[codec(index = 21)] - Raw20([::core::primitive::u8; 20usize]), - #[codec(index = 22)] - Raw21([::core::primitive::u8; 21usize]), - #[codec(index = 23)] - Raw22([::core::primitive::u8; 22usize]), - #[codec(index = 24)] - Raw23([::core::primitive::u8; 23usize]), - #[codec(index = 25)] - Raw24([::core::primitive::u8; 24usize]), - #[codec(index = 26)] - Raw25([::core::primitive::u8; 25usize]), - #[codec(index = 27)] - Raw26([::core::primitive::u8; 26usize]), - #[codec(index = 28)] - Raw27([::core::primitive::u8; 27usize]), - #[codec(index = 29)] - Raw28([::core::primitive::u8; 28usize]), - #[codec(index = 30)] - Raw29([::core::primitive::u8; 29usize]), - #[codec(index = 31)] - Raw30([::core::primitive::u8; 30usize]), - #[codec(index = 32)] - Raw31([::core::primitive::u8; 31usize]), - #[codec(index = 33)] - Raw32([::core::primitive::u8; 32usize]), - #[codec(index = 34)] - BlakeTwo256([::core::primitive::u8; 32usize]), - #[codec(index = 35)] - Sha256([::core::primitive::u8; 32usize]), - #[codec(index = 36)] - Keccak256([::core::primitive::u8; 32usize]), - #[codec(index = 37)] - ShaThree256([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum IdentityField { - #[codec(index = 1)] - Display, - #[codec(index = 2)] - Legal, - #[codec(index = 4)] - Web, - #[codec(index = 8)] - Riot, - #[codec(index = 16)] - Email, - #[codec(index = 32)] - PgpFingerprint, - #[codec(index = 64)] - Image, - #[codec(index = 128)] - Twitter, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdentityInfo { - pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::pallet_identity::types::Data, - runtime_types::pallet_identity::types::Data, - )>, - pub display: runtime_types::pallet_identity::types::Data, - pub legal: runtime_types::pallet_identity::types::Data, - pub web: runtime_types::pallet_identity::types::Data, - pub riot: runtime_types::pallet_identity::types::Data, - pub email: runtime_types::pallet_identity::types::Data, - pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, - pub image: runtime_types::pallet_identity::types::Data, - pub twitter: runtime_types::pallet_identity::types::Data, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Judgement<_0> { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - FeePaid(_0), - #[codec(index = 2)] - Reasonable, - #[codec(index = 3)] - KnownGood, - #[codec(index = 4)] - OutOfDate, - #[codec(index = 5)] - LowQuality, - #[codec(index = 6)] - Erroneous, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RegistrarInfo<_0, _1> { - pub account: _1, - pub fee: _0, - pub fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0> { - pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::core::primitive::u32, - runtime_types::pallet_identity::types::Judgement<_0>, - )>, - pub deposit: _0, - pub info: runtime_types::pallet_identity::types::IdentityInfo, - } - } - } - pub mod pallet_im_online { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - heartbeat { - heartbeat: - runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, - signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidKey, - #[codec(index = 1)] - DuplicatedHeartbeat, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - HeartbeatReceived { - authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - }, - #[codec(index = 1)] - AllGood, - #[codec(index = 2)] - SomeOffline { - offline: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_staking::Exposure< - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - >, - )>, - }, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedOpaqueNetworkState { - pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - pub external_addresses: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Heartbeat<_0> { - pub block_number: _0, - pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, - pub session_index: _0, - pub authority_index: _0, - pub validators_len: _0, - } - } - pub mod pallet_indices { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { index: ::core::primitive::u32 }, - #[codec(index = 1)] - transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - }, - #[codec(index = 2)] - free { index: ::core::primitive::u32 }, - #[codec(index = 3)] - force_transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - freeze: ::core::primitive::bool, - }, - #[codec(index = 4)] - freeze { index: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAssigned, - #[codec(index = 1)] - NotOwner, - #[codec(index = 2)] - InUse, - #[codec(index = 3)] - NotTransfer, - #[codec(index = 4)] - Permanent, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IndexAssigned { - who: ::sp_core::crypto::AccountId32, - index: ::core::primitive::u32, - }, - #[codec(index = 1)] - IndexFreed { index: ::core::primitive::u32 }, - #[codec(index = 2)] - IndexFrozen { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - }, - } - } - } - pub mod pallet_message_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotReapable, - #[codec(index = 1)] - NoPage, - #[codec(index = 2)] - NoMessage, - #[codec(index = 3)] - AlreadyProcessed, - #[codec(index = 4)] - Queued, - #[codec(index = 5)] - InsufficientWeight, - #[codec(index = 6)] - TemporarilyUnprocessable, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BookState<_0> { - pub begin: ::core::primitive::u32, - pub end: ::core::primitive::u32, - pub count: ::core::primitive::u32, - pub ready_neighbours: - ::core::option::Option>, - pub message_count: ::core::primitive::u64, - pub size: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Neighbours<_0> { - pub prev: _0, - pub next: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Page<_0> { - pub remaining: _0, - pub remaining_size: _0, - pub first_index: _0, - pub first: _0, - pub last: _0, - pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: _0, - } - } - pub mod pallet_nis { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bid<_0, _1> { - pub amount: _0, - pub who: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - place_bid { - #[codec(compact)] - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 1)] - retract_bid { - #[codec(compact)] - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 2)] - fund_deficit, - #[codec(index = 3)] - thaw_private { - #[codec(compact)] - index: ::core::primitive::u32, - maybe_proportion: ::core::option::Option< - runtime_types::sp_arithmetic::per_things::Perquintill, - >, - }, - #[codec(index = 4)] - thaw_communal { - #[codec(compact)] - index: ::core::primitive::u32, - }, - #[codec(index = 5)] - communify { - #[codec(compact)] - index: ::core::primitive::u32, - }, - #[codec(index = 6)] - privatize { - #[codec(compact)] - index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DurationTooSmall, - #[codec(index = 1)] - DurationTooBig, - #[codec(index = 2)] - AmountTooSmall, - #[codec(index = 3)] - BidTooLow, - #[codec(index = 4)] - UnknownReceipt, - #[codec(index = 5)] - NotOwner, - #[codec(index = 6)] - NotExpired, - #[codec(index = 7)] - UnknownBid, - #[codec(index = 8)] - PortionTooBig, - #[codec(index = 9)] - Unfunded, - #[codec(index = 10)] - AlreadyFunded, - #[codec(index = 11)] - Throttled, - #[codec(index = 12)] - MakesDust, - #[codec(index = 13)] - AlreadyCommunal, - #[codec(index = 14)] - AlreadyPrivate, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BidPlaced { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 1)] - BidRetracted { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 2)] - BidDropped { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 3)] - Issued { - index: ::core::primitive::u32, - expiry: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - proportion: runtime_types::sp_arithmetic::per_things::Perquintill, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - Thawed { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - proportion: runtime_types::sp_arithmetic::per_things::Perquintill, - amount: ::core::primitive::u128, - dropped: ::core::primitive::bool, - }, - #[codec(index = 5)] - Funded { deficit: ::core::primitive::u128 }, - #[codec(index = 6)] - Transferred { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HoldReason { - #[codec(index = 0)] - NftReceipt, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceiptRecord<_0, _1, _2> { - pub proportion: runtime_types::sp_arithmetic::per_things::Perquintill, - pub owner: ::core::option::Option<(_0, _2)>, - pub expiry: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SummaryRecord<_0, _1> { - pub proportion_owed: runtime_types::sp_arithmetic::per_things::Perquintill, - pub index: _0, - pub thawed: runtime_types::sp_arithmetic::per_things::Perquintill, - pub last_period: _0, - pub receipts_on_hold: _1, - } - } - } - pub mod pallet_nomination_pools { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - join { - #[codec(compact)] - amount: ::core::primitive::u128, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 1)] - bond_extra { - extra: runtime_types::pallet_nomination_pools::BondExtra< - ::core::primitive::u128, - >, - }, - #[codec(index = 2)] - claim_payout, - #[codec(index = 3)] - unbond { - member_account: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - unbonding_points: ::core::primitive::u128, - }, - #[codec(index = 4)] - pool_withdraw_unbonded { - pool_id: ::core::primitive::u32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 5)] - withdraw_unbonded { - member_account: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 6)] - create { - #[codec(compact)] - amount: ::core::primitive::u128, - root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 7)] - create_with_pool_id { - #[codec(compact)] - amount: ::core::primitive::u128, - root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 8)] - nominate { - pool_id: ::core::primitive::u32, - validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 9)] - set_state { - pool_id: ::core::primitive::u32, - state: runtime_types::pallet_nomination_pools::PoolState, - }, - #[codec(index = 10)] - set_metadata { - pool_id: ::core::primitive::u32, - metadata: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 11)] - set_configs { - min_join_bond: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u128, - >, - min_create_bond: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u128, - >, - max_pools: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - max_members: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - max_members_per_pool: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - global_max_commission: runtime_types::pallet_nomination_pools::ConfigOp< - runtime_types::sp_arithmetic::per_things::Perbill, - >, - }, - #[codec(index = 12)] - update_roles { - pool_id: ::core::primitive::u32, - new_root: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - new_nominator: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - new_bouncer: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 13)] - chill { pool_id: ::core::primitive::u32 }, - #[codec(index = 14)] - bond_extra_other { - member: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - extra: runtime_types::pallet_nomination_pools::BondExtra< - ::core::primitive::u128, - >, - }, - #[codec(index = 15)] - set_claim_permission { - permission: runtime_types::pallet_nomination_pools::ClaimPermission, - }, - #[codec(index = 16)] - claim_payout_other { other: ::sp_core::crypto::AccountId32 }, - #[codec(index = 17)] - set_commission { - pool_id: ::core::primitive::u32, - new_commission: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - }, - #[codec(index = 18)] - set_commission_max { - pool_id: ::core::primitive::u32, - max_commission: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 19)] - set_commission_change_rate { - pool_id: ::core::primitive::u32, - change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - }, - #[codec(index = 20)] - claim_commission { pool_id: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DefensiveError { - #[codec(index = 0)] - NotEnoughSpaceInUnbondPool, - #[codec(index = 1)] - PoolNotFound, - #[codec(index = 2)] - RewardPoolNotFound, - #[codec(index = 3)] - SubPoolsNotFound, - #[codec(index = 4)] - BondedStashKilledPrematurely, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PoolNotFound, - #[codec(index = 1)] - PoolMemberNotFound, - #[codec(index = 2)] - RewardPoolNotFound, - #[codec(index = 3)] - SubPoolsNotFound, - #[codec(index = 4)] - AccountBelongsToOtherPool, - #[codec(index = 5)] - FullyUnbonding, - #[codec(index = 6)] - MaxUnbondingLimit, - #[codec(index = 7)] - CannotWithdrawAny, - #[codec(index = 8)] - MinimumBondNotMet, - #[codec(index = 9)] - OverflowRisk, - #[codec(index = 10)] - NotDestroying, - #[codec(index = 11)] - NotNominator, - #[codec(index = 12)] - NotKickerOrDestroying, - #[codec(index = 13)] - NotOpen, - #[codec(index = 14)] - MaxPools, - #[codec(index = 15)] - MaxPoolMembers, - #[codec(index = 16)] - CanNotChangeState, - #[codec(index = 17)] - DoesNotHavePermission, - #[codec(index = 18)] - MetadataExceedsMaxLen, - #[codec(index = 19)] - Defensive(runtime_types::pallet_nomination_pools::pallet::DefensiveError), - #[codec(index = 20)] - PartialUnbondNotAllowedPermissionlessly, - #[codec(index = 21)] - MaxCommissionRestricted, - #[codec(index = 22)] - CommissionExceedsMaximum, - #[codec(index = 23)] - CommissionChangeThrottled, - #[codec(index = 24)] - CommissionChangeRateNotAllowed, - #[codec(index = 25)] - NoPendingCommission, - #[codec(index = 26)] - NoCommissionCurrentSet, - #[codec(index = 27)] - PoolIdInUse, - #[codec(index = 28)] - InvalidPoolId, - #[codec(index = 29)] - BondExtraRestricted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { - depositor: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 1)] - Bonded { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - bonded: ::core::primitive::u128, - joined: ::core::primitive::bool, - }, - #[codec(index = 2)] - PaidOut { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - payout: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unbonded { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - points: ::core::primitive::u128, - era: ::core::primitive::u32, - }, - #[codec(index = 4)] - Withdrawn { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - points: ::core::primitive::u128, - }, - #[codec(index = 5)] - Destroyed { pool_id: ::core::primitive::u32 }, - #[codec(index = 6)] - StateChanged { - pool_id: ::core::primitive::u32, - new_state: runtime_types::pallet_nomination_pools::PoolState, - }, - #[codec(index = 7)] - MemberRemoved { - pool_id: ::core::primitive::u32, - member: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - RolesUpdated { - root: ::core::option::Option<::sp_core::crypto::AccountId32>, - bouncer: ::core::option::Option<::sp_core::crypto::AccountId32>, - nominator: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 9)] - PoolSlashed { - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - }, - #[codec(index = 10)] - UnbondingPoolSlashed { - pool_id: ::core::primitive::u32, - era: ::core::primitive::u32, - balance: ::core::primitive::u128, - }, - #[codec(index = 11)] - PoolCommissionUpdated { - pool_id: ::core::primitive::u32, - current: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - }, - #[codec(index = 12)] - PoolMaxCommissionUpdated { - pool_id: ::core::primitive::u32, - max_commission: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 13)] - PoolCommissionChangeRateUpdated { - pool_id: ::core::primitive::u32, - change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - }, - #[codec(index = 14)] - PoolCommissionClaimed { - pool_id: ::core::primitive::u32, - commission: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BondExtra<_0> { - #[codec(index = 0)] - FreeBalance(_0), - #[codec(index = 1)] - Rewards, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BondedPoolInner { - pub commission: runtime_types::pallet_nomination_pools::Commission, - pub member_counter: ::core::primitive::u32, - pub points: ::core::primitive::u128, - pub roles: runtime_types::pallet_nomination_pools::PoolRoles< - ::sp_core::crypto::AccountId32, - >, - pub state: runtime_types::pallet_nomination_pools::PoolState, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ClaimPermission { - #[codec(index = 0)] - Permissioned, - #[codec(index = 1)] - PermissionlessCompound, - #[codec(index = 2)] - PermissionlessWithdraw, - #[codec(index = 3)] - PermissionlessAll, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commission { - pub current: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - pub max: ::core::option::Option, - pub change_rate: ::core::option::Option< - runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - >, - pub throttle_from: ::core::option::Option<::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommissionChangeRate<_0> { - pub max_increase: runtime_types::sp_arithmetic::per_things::Perbill, - pub min_delay: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConfigOp<_0> { - #[codec(index = 0)] - Noop, - #[codec(index = 1)] - Set(_0), - #[codec(index = 2)] - Remove, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PoolMember { - pub pool_id: ::core::primitive::u32, - pub points: ::core::primitive::u128, - pub last_recorded_reward_counter: - runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub unbonding_eras: - runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< - ::core::primitive::u32, - ::core::primitive::u128, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PoolRoles<_0> { - pub depositor: _0, - pub root: ::core::option::Option<_0>, - pub nominator: ::core::option::Option<_0>, - pub bouncer: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PoolState { - #[codec(index = 0)] - Open, - #[codec(index = 1)] - Blocked, - #[codec(index = 2)] - Destroying, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardPool { - pub last_recorded_reward_counter: - runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub last_recorded_total_payouts: ::core::primitive::u128, - pub total_rewards_claimed: ::core::primitive::u128, - pub total_commission_pending: ::core::primitive::u128, - pub total_commission_claimed: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SubPools { - pub no_era: runtime_types::pallet_nomination_pools::UnbondPool, - pub with_era: - runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< - ::core::primitive::u32, - runtime_types::pallet_nomination_pools::UnbondPool, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnbondPool { - pub points: ::core::primitive::u128, - pub balance: ::core::primitive::u128, - } - } - pub mod pallet_offences { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Offence { - kind: [::core::primitive::u8; 16usize], - timeslot: ::std::vec::Vec<::core::primitive::u8>, - }, - } - } - } - pub mod pallet_preimage { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - unnote_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - request_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 3)] - unrequest_preimage { hash: ::subxt::utils::H256 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooBig, - #[codec(index = 1)] - AlreadyNoted, - #[codec(index = 2)] - NotAuthorized, - #[codec(index = 3)] - NotNoted, - #[codec(index = 4)] - Requested, - #[codec(index = 5)] - NotRequested, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Noted { hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - Requested { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - Cleared { hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RequestStatus<_0, _1> { - #[codec(index = 0)] - Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, - #[codec(index = 1)] - Requested { - deposit: ::core::option::Option<(_0, _1)>, - count: ::core::primitive::u32, - len: ::core::option::Option<::core::primitive::u32>, - }, - } - } - pub mod pallet_proxy { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - proxy { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - add_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::kusama_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 2)] - remove_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::kusama_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 3)] - remove_proxies, - #[codec(index = 4)] - create_pure { - proxy_type: runtime_types::kusama_runtime::ProxyType, - delay: ::core::primitive::u32, - index: ::core::primitive::u16, - }, - #[codec(index = 5)] - kill_pure { - spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::kusama_runtime::ProxyType, - index: ::core::primitive::u16, - #[codec(compact)] - height: ::core::primitive::u32, - #[codec(compact)] - ext_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - announce { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 7)] - remove_announcement { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 8)] - reject_announcement { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 9)] - proxy_announced { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooMany, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotProxy, - #[codec(index = 3)] - Unproxyable, - #[codec(index = 4)] - Duplicate, - #[codec(index = 5)] - NoPermission, - #[codec(index = 6)] - Unannounced, - #[codec(index = 7)] - NoSelfProxy, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ProxyExecuted { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - PureCreated { - pure: ::sp_core::crypto::AccountId32, - who: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::kusama_runtime::ProxyType, - disambiguation_index: ::core::primitive::u16, - }, - #[codec(index = 2)] - Announced { - real: ::sp_core::crypto::AccountId32, - proxy: ::sp_core::crypto::AccountId32, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - ProxyAdded { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::kusama_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 4)] - ProxyRemoved { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::kusama_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Announcement<_0, _1, _2> { - pub real: _0, - pub call_hash: _1, - pub height: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ProxyDefinition<_0, _1, _2> { - pub delegate: _0, - pub proxy_type: _1, - pub delay: _2, - } - } - pub mod pallet_ranked_collective { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - promote_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - demote_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - remove_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - min_rank: ::core::primitive::u16, - }, - #[codec(index = 4)] - vote { poll: ::core::primitive::u32, aye: ::core::primitive::bool }, - #[codec(index = 5)] - cleanup_poll { poll_index: ::core::primitive::u32, max: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AlreadyMember, - #[codec(index = 1)] - NotMember, - #[codec(index = 2)] - NotPolling, - #[codec(index = 3)] - Ongoing, - #[codec(index = 4)] - NoneRemaining, - #[codec(index = 5)] - Corruption, - #[codec(index = 6)] - RankTooLow, - #[codec(index = 7)] - InvalidWitness, - #[codec(index = 8)] - NoPermission, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - MemberAdded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - RankChanged { - who: ::sp_core::crypto::AccountId32, - rank: ::core::primitive::u16, - }, - #[codec(index = 2)] - MemberRemoved { - who: ::sp_core::crypto::AccountId32, - rank: ::core::primitive::u16, - }, - #[codec(index = 3)] - Voted { - who: ::sp_core::crypto::AccountId32, - poll: ::core::primitive::u32, - vote: runtime_types::pallet_ranked_collective::VoteRecord, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - } - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct MemberRecord { - pub rank: ::core::primitive::u16, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Tally { - pub bare_ayes: ::core::primitive::u32, - pub ayes: ::core::primitive::u32, - pub nays: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VoteRecord { - #[codec(index = 0)] - Aye(::core::primitive::u32), - #[codec(index = 1)] - Nay(::core::primitive::u32), - } - } - pub mod pallet_recovery { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_recovered { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - set_recovered { - lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - create_recovery { - friends: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - threshold: ::core::primitive::u16, - delay_period: ::core::primitive::u32, - }, - #[codec(index = 3)] - initiate_recovery { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - vouch_recovery { - lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - claim_recovery { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - close_recovery { - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 7)] - remove_recovery, - #[codec(index = 8)] - cancel_recovered { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAllowed, - #[codec(index = 1)] - ZeroThreshold, - #[codec(index = 2)] - NotEnoughFriends, - #[codec(index = 3)] - MaxFriends, - #[codec(index = 4)] - NotSorted, - #[codec(index = 5)] - NotRecoverable, - #[codec(index = 6)] - AlreadyRecoverable, - #[codec(index = 7)] - AlreadyStarted, - #[codec(index = 8)] - NotStarted, - #[codec(index = 9)] - NotFriend, - #[codec(index = 10)] - DelayPeriod, - #[codec(index = 11)] - AlreadyVouched, - #[codec(index = 12)] - Threshold, - #[codec(index = 13)] - StillActive, - #[codec(index = 14)] - AlreadyProxy, - #[codec(index = 15)] - BadState, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RecoveryCreated { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - RecoveryInitiated { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 2)] - RecoveryVouched { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - sender: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - RecoveryClosed { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 4)] - AccountRecovered { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 5)] - RecoveryRemoved { lost_account: ::sp_core::crypto::AccountId32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ActiveRecovery<_0, _1, _2> { - pub created: _0, - pub deposit: _1, - pub friends: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RecoveryConfig<_0, _1, _2> { - pub delay_period: _0, - pub deposit: _1, - pub friends: _2, - pub threshold: ::core::primitive::u16, - } - } - pub mod pallet_referenda { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit { - proposal_origin: - ::std::boxed::Box, - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::kusama_runtime::RuntimeCall, - >, - enactment_moment: - runtime_types::frame_support::traits::schedule::DispatchTime< - ::core::primitive::u32, - >, - }, - #[codec(index = 1)] - place_decision_deposit { index: ::core::primitive::u32 }, - #[codec(index = 2)] - refund_decision_deposit { index: ::core::primitive::u32 }, - #[codec(index = 3)] - cancel { index: ::core::primitive::u32 }, - #[codec(index = 4)] - kill { index: ::core::primitive::u32 }, - #[codec(index = 5)] - nudge_referendum { index: ::core::primitive::u32 }, - #[codec(index = 6)] - one_fewer_deciding { track: ::core::primitive::u16 }, - #[codec(index = 7)] - refund_submission_deposit { index: ::core::primitive::u32 }, - #[codec(index = 8)] - set_metadata { - index: ::core::primitive::u32, - maybe_hash: ::core::option::Option<::subxt::utils::H256>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotOngoing, - #[codec(index = 1)] - HasDeposit, - #[codec(index = 2)] - BadTrack, - #[codec(index = 3)] - Full, - #[codec(index = 4)] - QueueEmpty, - #[codec(index = 5)] - BadReferendum, - #[codec(index = 6)] - NothingToDo, - #[codec(index = 7)] - NoTrack, - #[codec(index = 8)] - Unfinished, - #[codec(index = 9)] - NoPermission, - #[codec(index = 10)] - NoDeposit, - #[codec(index = 11)] - BadStatus, - #[codec(index = 12)] - PreimageNotExist, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Submitted { - index: ::core::primitive::u32, - track: ::core::primitive::u16, - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::kusama_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - DecisionDepositPlaced { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - DecisionDepositRefunded { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - DepositSlashed { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - DecisionStarted { - index: ::core::primitive::u32, - track: ::core::primitive::u16, - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::kusama_runtime::RuntimeCall, - >, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 5)] - ConfirmStarted { index: ::core::primitive::u32 }, - #[codec(index = 6)] - ConfirmAborted { index: ::core::primitive::u32 }, - #[codec(index = 7)] - Confirmed { - index: ::core::primitive::u32, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 8)] - Approved { index: ::core::primitive::u32 }, - #[codec(index = 9)] - Rejected { - index: ::core::primitive::u32, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 10)] - TimedOut { - index: ::core::primitive::u32, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 11)] - Cancelled { - index: ::core::primitive::u32, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 12)] - Killed { - index: ::core::primitive::u32, - tally: runtime_types::pallet_ranked_collective::Tally, - }, - #[codec(index = 13)] - SubmissionDepositRefunded { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - MetadataSet { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, - #[codec(index = 15)] - MetadataCleared { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Curve { - #[codec(index = 0)] - LinearDecreasing { - length: runtime_types::sp_arithmetic::per_things::Perbill, - floor: runtime_types::sp_arithmetic::per_things::Perbill, - ceil: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 1)] - SteppedDecreasing { - begin: runtime_types::sp_arithmetic::per_things::Perbill, - end: runtime_types::sp_arithmetic::per_things::Perbill, - step: runtime_types::sp_arithmetic::per_things::Perbill, - period: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 2)] - Reciprocal { - factor: runtime_types::sp_arithmetic::fixed_point::FixedI64, - x_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, - y_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DecidingStatus<_0> { - pub since: _0, - pub confirming: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Deposit<_0, _1> { - pub who: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReferendumInfo<_0, _1, _2, _3, _4, _5, _6, _7> { - #[codec(index = 0)] - Ongoing( - runtime_types::pallet_referenda::types::ReferendumStatus< - _0, - _1, - _2, - _3, - _4, - _5, - _6, - _7, - >, - ), - #[codec(index = 1)] - Approved( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 2)] - Rejected( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 3)] - Cancelled( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 4)] - TimedOut( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 5)] - Killed(_2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReferendumStatus<_0, _1, _2, _3, _4, _5, _6, _7> { - pub track: _0, - pub origin: _1, - pub proposal: _3, - pub enactment: runtime_types::frame_support::traits::schedule::DispatchTime<_2>, - pub submitted: _2, - pub submission_deposit: runtime_types::pallet_referenda::types::Deposit<_6, _4>, - pub decision_deposit: ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - pub deciding: ::core::option::Option< - runtime_types::pallet_referenda::types::DecidingStatus<_2>, - >, - pub tally: _5, - pub in_queue: ::core::primitive::bool, - pub alarm: ::core::option::Option<(_2, _7)>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct TrackInfo<_0, _1> { - pub name: ::std::string::String, - pub max_deciding: _1, - pub decision_deposit: _0, - pub prepare_period: _1, - pub decision_period: _1, - pub confirm_period: _1, - pub min_enactment_period: _1, - pub min_approval: runtime_types::pallet_referenda::types::Curve, - pub min_support: runtime_types::pallet_referenda::types::Curve, - } - } - } - pub mod pallet_scheduler { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - schedule { - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - schedule_named { - id: [::core::primitive::u8; 32usize], - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 3)] - cancel_named { id: [::core::primitive::u8; 32usize] }, - #[codec(index = 4)] - schedule_after { - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 5)] - schedule_named_after { - id: [::core::primitive::u8; 32usize], - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSchedule, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - TargetBlockNumberInPast, - #[codec(index = 3)] - RescheduleNoChange, - #[codec(index = 4)] - Named, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 1)] - Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - Dispatched { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - CallUnavailable { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 4)] - PeriodicFailed { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 5)] - PermanentlyOverweight { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Scheduled<_0, _1, _2, _3, _4> { - pub maybe_id: ::core::option::Option<_0>, - pub priority: ::core::primitive::u8, - pub call: _1, - pub maybe_periodic: ::core::option::Option<(_2, _2)>, - pub origin: _3, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::kusama_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_society { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - bid { value: ::core::primitive::u128 }, - #[codec(index = 1)] - unbid { pos: ::core::primitive::u32 }, - #[codec(index = 2)] - vouch { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - value: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - #[codec(index = 3)] - unvouch { pos: ::core::primitive::u32 }, - #[codec(index = 4)] - vote { - candidate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - approve: ::core::primitive::bool, - }, - #[codec(index = 5)] - defender_vote { approve: ::core::primitive::bool }, - #[codec(index = 6)] - payout, - #[codec(index = 7)] - found { - founder: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - max_members: ::core::primitive::u32, - rules: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 8)] - unfound, - #[codec(index = 9)] - judge_suspended_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - forgive: ::core::primitive::bool, - }, - #[codec(index = 10)] - judge_suspended_candidate { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - judgement: runtime_types::pallet_society::Judgement, - }, - #[codec(index = 11)] - set_max_members { max: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - BadPosition, - #[codec(index = 1)] - NotMember, - #[codec(index = 2)] - AlreadyMember, - #[codec(index = 3)] - Suspended, - #[codec(index = 4)] - NotSuspended, - #[codec(index = 5)] - NoPayout, - #[codec(index = 6)] - AlreadyFounded, - #[codec(index = 7)] - InsufficientPot, - #[codec(index = 8)] - AlreadyVouching, - #[codec(index = 9)] - NotVouching, - #[codec(index = 10)] - Head, - #[codec(index = 11)] - Founder, - #[codec(index = 12)] - AlreadyBid, - #[codec(index = 13)] - AlreadyCandidate, - #[codec(index = 14)] - NotCandidate, - #[codec(index = 15)] - MaxMembers, - #[codec(index = 16)] - NotFounder, - #[codec(index = 17)] - NotHead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Founded { founder: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - Bid { - candidate_id: ::sp_core::crypto::AccountId32, - offer: ::core::primitive::u128, - }, - #[codec(index = 2)] - Vouch { - candidate_id: ::sp_core::crypto::AccountId32, - offer: ::core::primitive::u128, - vouching: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - AutoUnbid { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - Unbid { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Unvouch { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - Inducted { - primary: ::sp_core::crypto::AccountId32, - candidates: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 7)] - SuspendedMemberJudgement { - who: ::sp_core::crypto::AccountId32, - judged: ::core::primitive::bool, - }, - #[codec(index = 8)] - CandidateSuspended { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 9)] - MemberSuspended { member: ::sp_core::crypto::AccountId32 }, - #[codec(index = 10)] - Challenged { member: ::sp_core::crypto::AccountId32 }, - #[codec(index = 11)] - Vote { - candidate: ::sp_core::crypto::AccountId32, - voter: ::sp_core::crypto::AccountId32, - vote: ::core::primitive::bool, - }, - #[codec(index = 12)] - DefenderVote { - voter: ::sp_core::crypto::AccountId32, - vote: ::core::primitive::bool, - }, - #[codec(index = 13)] - NewMaxMembers { max: ::core::primitive::u32 }, - #[codec(index = 14)] - Unfounded { founder: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Deposit { value: ::core::primitive::u128 }, - #[codec(index = 16)] - SkepticsChosen { skeptics: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bid<_0, _1> { - pub who: _0, - pub kind: runtime_types::pallet_society::BidKind<_0, _1>, - pub value: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BidKind<_0, _1> { - #[codec(index = 0)] - Deposit(_1), - #[codec(index = 1)] - Vouch(_0, _1), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Judgement { - #[codec(index = 0)] - Rebid, - #[codec(index = 1)] - Reject, - #[codec(index = 2)] - Approve, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Vote { - #[codec(index = 0)] - Skeptic, - #[codec(index = 1)] - Reject, - #[codec(index = 2)] - Approve, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VouchingStatus { - #[codec(index = 0)] - Vouching, - #[codec(index = 1)] - Banned, - } - } - pub mod pallet_staking { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - bond { - #[codec(compact)] - value: ::core::primitive::u128, - payee: runtime_types::pallet_staking::RewardDestination< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 1)] - bond_extra { - #[codec(compact)] - max_additional: ::core::primitive::u128, - }, - #[codec(index = 2)] - unbond { - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - withdraw_unbonded { num_slashing_spans: ::core::primitive::u32 }, - #[codec(index = 4)] - validate { prefs: runtime_types::pallet_staking::ValidatorPrefs }, - #[codec(index = 5)] - nominate { - targets: ::std::vec::Vec< - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - >, - }, - #[codec(index = 6)] - chill, - #[codec(index = 7)] - set_payee { - payee: runtime_types::pallet_staking::RewardDestination< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 8)] - set_controller, - #[codec(index = 9)] - set_validator_count { - #[codec(compact)] - new: ::core::primitive::u32, - }, - #[codec(index = 10)] - increase_validator_count { - #[codec(compact)] - additional: ::core::primitive::u32, - }, - #[codec(index = 11)] - scale_validator_count { - factor: runtime_types::sp_arithmetic::per_things::Percent, - }, - #[codec(index = 12)] - force_no_eras, - #[codec(index = 13)] - force_new_era, - #[codec(index = 14)] - set_invulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 15)] - force_unstake { - stash: ::sp_core::crypto::AccountId32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 16)] - force_new_era_always, - #[codec(index = 17)] - cancel_deferred_slash { - era: ::core::primitive::u32, - slash_indices: ::std::vec::Vec<::core::primitive::u32>, - }, - #[codec(index = 18)] - payout_stakers { - validator_stash: ::sp_core::crypto::AccountId32, - era: ::core::primitive::u32, - }, - #[codec(index = 19)] - rebond { - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 20)] - reap_stash { - stash: ::sp_core::crypto::AccountId32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 21)] - kick { - who: ::std::vec::Vec< - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - >, - }, - #[codec(index = 22)] - set_staking_configs { - min_nominator_bond: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u128, - >, - min_validator_bond: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u128, - >, - max_nominator_count: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u32, - >, - max_validator_count: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u32, - >, - chill_threshold: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - runtime_types::sp_arithmetic::per_things::Percent, - >, - min_commission: runtime_types::pallet_staking::pallet::pallet::ConfigOp< - runtime_types::sp_arithmetic::per_things::Perbill, - >, - }, - #[codec(index = 23)] - chill_other { controller: ::sp_core::crypto::AccountId32 }, - #[codec(index = 24)] - force_apply_min_commission { - validator_stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 25)] - set_min_commission { - new: runtime_types::sp_arithmetic::per_things::Perbill, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConfigOp<_0> { - #[codec(index = 0)] - Noop, - #[codec(index = 1)] - Set(_0), - #[codec(index = 2)] - Remove, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotController, - #[codec(index = 1)] - NotStash, - #[codec(index = 2)] - AlreadyBonded, - #[codec(index = 3)] - AlreadyPaired, - #[codec(index = 4)] - EmptyTargets, - #[codec(index = 5)] - DuplicateIndex, - #[codec(index = 6)] - InvalidSlashIndex, - #[codec(index = 7)] - InsufficientBond, - #[codec(index = 8)] - NoMoreChunks, - #[codec(index = 9)] - NoUnlockChunk, - #[codec(index = 10)] - FundedTarget, - #[codec(index = 11)] - InvalidEraToReward, - #[codec(index = 12)] - InvalidNumberOfNominations, - #[codec(index = 13)] - NotSortedAndUnique, - #[codec(index = 14)] - AlreadyClaimed, - #[codec(index = 15)] - IncorrectHistoryDepth, - #[codec(index = 16)] - IncorrectSlashingSpans, - #[codec(index = 17)] - BadState, - #[codec(index = 18)] - TooManyTargets, - #[codec(index = 19)] - BadTarget, - #[codec(index = 20)] - CannotChillOther, - #[codec(index = 21)] - TooManyNominators, - #[codec(index = 22)] - TooManyValidators, - #[codec(index = 23)] - CommissionTooLow, - #[codec(index = 24)] - BoundNotMet, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - EraPaid { - era_index: ::core::primitive::u32, - validator_payout: ::core::primitive::u128, - remainder: ::core::primitive::u128, - }, - #[codec(index = 1)] - Rewarded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Slashed { - staker: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - SlashReported { - validator: ::sp_core::crypto::AccountId32, - fraction: runtime_types::sp_arithmetic::per_things::Perbill, - slash_era: ::core::primitive::u32, - }, - #[codec(index = 4)] - OldSlashingReportDiscarded { session_index: ::core::primitive::u32 }, - #[codec(index = 5)] - StakersElected, - #[codec(index = 6)] - Bonded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 7)] - Unbonded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 8)] - Withdrawn { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Kicked { - nominator: ::sp_core::crypto::AccountId32, - stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 10)] - StakingElectionFailed, - #[codec(index = 11)] - Chilled { stash: ::sp_core::crypto::AccountId32 }, - #[codec(index = 12)] - PayoutStarted { - era_index: ::core::primitive::u32, - validator_stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 13)] - ValidatorPrefsSet { - stash: ::sp_core::crypto::AccountId32, - prefs: runtime_types::pallet_staking::ValidatorPrefs, - }, - #[codec(index = 14)] - ForceEra { mode: runtime_types::pallet_staking::Forcing }, - } - } - } - pub mod slashing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SlashingSpans { - pub span_index: ::core::primitive::u32, - pub last_start: ::core::primitive::u32, - pub last_nonzero_slash: ::core::primitive::u32, - pub prior: ::std::vec::Vec<::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SpanRecord<_0> { - pub slashed: _0, - pub paid_out: _0, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ActiveEraInfo { - pub index: ::core::primitive::u32, - pub start: ::core::option::Option<::core::primitive::u64>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EraRewardPoints<_0> { - pub total: ::core::primitive::u32, - pub individual: ::subxt::utils::KeyedVec<_0, ::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Exposure<_0, _1> { - #[codec(compact)] - pub total: _1, - #[codec(compact)] - pub own: _1, - pub others: - ::std::vec::Vec>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Forcing { - #[codec(index = 0)] - NotForcing, - #[codec(index = 1)] - ForceNew, - #[codec(index = 2)] - ForceNone, - #[codec(index = 3)] - ForceAlways, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndividualExposure<_0, _1> { - pub who: _0, - #[codec(compact)] - pub value: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Nominations { - pub targets: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::sp_core::crypto::AccountId32, - >, - pub submitted_in: ::core::primitive::u32, - pub suppressed: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardDestination<_0> { - #[codec(index = 0)] - Staked, - #[codec(index = 1)] - Stash, - #[codec(index = 2)] - Controller, - #[codec(index = 3)] - Account(_0), - #[codec(index = 4)] - None, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StakingLedger { - pub stash: ::sp_core::crypto::AccountId32, - #[codec(compact)] - pub total: ::core::primitive::u128, - #[codec(compact)] - pub active: ::core::primitive::u128, - pub unlocking: runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_staking::UnlockChunk<::core::primitive::u128>, - >, - pub claimed_rewards: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnappliedSlash<_0, _1> { - pub validator: _0, - pub own: _1, - pub others: ::std::vec::Vec<(_0, _1)>, - pub reporters: ::std::vec::Vec<_0>, - pub payout: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnlockChunk<_0> { - #[codec(compact)] - pub value: _0, - #[codec(compact)] - pub era: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidatorPrefs { - #[codec(compact)] - pub commission: runtime_types::sp_arithmetic::per_things::Perbill, - pub blocked: ::core::primitive::bool, - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_treasury { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose_spend { - #[codec(compact)] - value: ::core::primitive::u128, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - reject_proposal { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - #[codec(index = 2)] - approve_proposal { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - #[codec(index = 3)] - spend { - #[codec(compact)] - amount: ::core::primitive::u128, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - remove_approval { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InsufficientProposersBalance, - #[codec(index = 1)] - InvalidIndex, - #[codec(index = 2)] - TooManyApprovals, - #[codec(index = 3)] - InsufficientPermission, - #[codec(index = 4)] - ProposalNotApproved, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { proposal_index: ::core::primitive::u32 }, - #[codec(index = 1)] - Spending { budget_remaining: ::core::primitive::u128 }, - #[codec(index = 2)] - Awarded { - proposal_index: ::core::primitive::u32, - award: ::core::primitive::u128, - account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Rejected { - proposal_index: ::core::primitive::u32, - slashed: ::core::primitive::u128, - }, - #[codec(index = 4)] - Burnt { burnt_funds: ::core::primitive::u128 }, - #[codec(index = 5)] - Rollover { rollover_balance: ::core::primitive::u128 }, - #[codec(index = 6)] - Deposit { value: ::core::primitive::u128 }, - #[codec(index = 7)] - SpendApproved { - proposal_index: ::core::primitive::u32, - amount: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - UpdatedInactive { - reactivated: ::core::primitive::u128, - deactivated: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Proposal<_0, _1> { - pub proposer: _0, - pub value: _1, - pub beneficiary: _0, - pub bond: _1, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { calls: ::std::vec::Vec }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box, - }, - #[codec(index = 2)] - batch_all { calls: ::std::vec::Vec }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box, - call: ::std::boxed::Box, - }, - #[codec(index = 4)] - force_batch { - calls: ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_vesting { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vest, - #[codec(index = 1)] - vest_other { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - vested_transfer { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 3)] - force_vested_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 4)] - merge_schedules { - schedule1_index: ::core::primitive::u32, - schedule2_index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotVesting, - #[codec(index = 1)] - AtMaxVestingSchedules, - #[codec(index = 2)] - AmountLow, - #[codec(index = 3)] - ScheduleIndexOutOfBounds, - #[codec(index = 4)] - InvalidScheduleParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - VestingUpdated { - account: ::sp_core::crypto::AccountId32, - unvested: ::core::primitive::u128, - }, - #[codec(index = 1)] - VestingCompleted { account: ::sp_core::crypto::AccountId32 }, - } - } - pub mod vesting_info { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VestingInfo<_0, _1> { - pub locked: _0, - pub per_block: _0, - pub starting_block: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V0, - #[codec(index = 1)] - V1, - } - } - pub mod pallet_whitelist { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - whitelist_call { call_hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - remove_whitelisted_call { call_hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - dispatch_whitelisted_call { - call_hash: ::subxt::utils::H256, - call_encoded_len: ::core::primitive::u32, - call_weight_witness: ::sp_weights::Weight, - }, - #[codec(index = 3)] - dispatch_whitelisted_call_with_preimage { - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnavailablePreImage, - #[codec(index = 1)] - UndecodableCall, - #[codec(index = 2)] - InvalidCallWeightWitness, - #[codec(index = 3)] - CallIsNotWhitelisted, - #[codec(index = 4)] - CallAlreadyWhitelisted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CallWhitelisted { call_hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - WhitelistedCallRemoved { call_hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - WhitelistedCallDispatched { - call_hash: ::subxt::utils::H256, - result: ::core::result::Result< - runtime_types::frame_support::dispatch::PostDispatchInfo, - runtime_types::sp_runtime::DispatchErrorWithPostInfo< - runtime_types::frame_support::dispatch::PostDispatchInfo, - >, - >, - }, - } - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - xcm_version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted(runtime_types::xcm::v3::traits::Outcome), - #[codec(index = 1)] - Sent( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::Xcm, - ), - #[codec(index = 2)] - UnexpectedResponse( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 3)] - ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), - #[codec(index = 4)] - Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), - #[codec(index = 5)] - NotifyOverweight( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ::sp_weights::Weight, - ::sp_weights::Weight, - ), - #[codec(index = 6)] - NotifyDispatchError( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 7)] - NotifyDecodeFailed( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 8)] - InvalidResponder( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 9)] - InvalidResponderVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 10)] - ResponseTaken(::core::primitive::u64), - #[codec(index = 11)] - AssetsTrapped( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - #[codec(index = 12)] - VersionChangeNotified( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 13)] - SupportedVersionChanged( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - ), - #[codec(index = 14)] - NotifyTargetSendFail( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::traits::Error, - ), - #[codec(index = 15)] - NotifyTargetMigrationFail( - runtime_types::xcm::VersionedMultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 16)] - InvalidQuerierVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 17)] - InvalidQuerier( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 18)] - VersionNotifyStarted( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 19)] - VersionNotifyRequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 20)] - VersionNotifyUnrequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 21)] - FeesPaid( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 22)] - AssetsClaimed( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Response(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedMultiLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateHash(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelId { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub recipient: runtime_types::polkadot_parachain::primitives::Id, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCodeHash(pub ::subxt::utils::H256); - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v4 { - use super::runtime_types; - pub mod assignment_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod collator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - pub mod executor_params { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ExecutorParam { - #[codec(index = 1)] - MaxMemoryPages(::core::primitive::u32), - #[codec(index = 2)] - StackLogicalMax(::core::primitive::u32), - #[codec(index = 3)] - StackNativeMax(::core::primitive::u32), - #[codec(index = 4)] - PrecheckingMaxMemory(::core::primitive::u64), - #[codec(index = 5)] - PvfPrepTimeout( - runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 6)] - PvfExecTimeout( - runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 7)] - WasmExtBulkMemory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutorParams( - pub ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, - >, - ); - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedSigned<_0, _1> { - pub payload: _0, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - pub signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, - } - } - pub mod validator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfield( - pub ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BackedCandidate<_0> { - pub candidate: - runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, - pub validity_votes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::ValidityAttestation, - >, - pub validator_indices: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateCommitments<_0> { - pub upward_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::std::vec::Vec<::core::primitive::u8>, - >, - pub horizontal_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain::primitives::Id, - >, - >, - pub new_validation_code: ::core::option::Option< - runtime_types::polkadot_parachain::primitives::ValidationCode, - >, - pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, - pub processed_downward_messages: _0, - pub hrmp_watermark: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateDescriptor<_0> { - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub relay_parent: _0, - pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, - pub persisted_validation_data_hash: _0, - pub pov_hash: _0, - pub erasure_root: _0, - pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, - pub para_head: _0, - pub validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments_hash: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommittedCandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< - ::core::primitive::u32, - >, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct CoreIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum CoreOccupied { - #[codec(index = 0)] - Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), - #[codec(index = 1)] - Parachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeState<_0> { - pub validators_for: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub validators_against: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub start: _0, - pub concluded_at: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeStatement { - #[codec(index = 0)] - Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), - #[codec(index = 1)] - Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeStatementSet { - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub session: ::core::primitive::u32, - pub statements: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::DisputeStatement, - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Signature, - )>, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct GroupIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndexedVec<_0, _1>( - pub ::std::vec::Vec<_1>, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData<_0> { - pub bitfields: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - >, - >, - pub backed_candidates: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::BackedCandidate< - ::subxt::utils::H256, - >, - >, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - pub parent_header: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaim( - pub runtime_types::polkadot_parachain::primitives::Id, - pub runtime_types::polkadot_primitives::v4::collator_app::Public, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadEntry { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, - pub retries: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckStatement { - pub accept: ::core::primitive::bool, - pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - pub session_index: ::core::primitive::u32, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfExecTimeoutKind { - #[codec(index = 0)] - Backing, - #[codec(index = 1)] - Approval, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfPrepTimeoutKind { - #[codec(index = 0)] - Precheck, - #[codec(index = 1)] - Lenient, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ScrapedOnChainVotes<_0> { - pub session: ::core::primitive::u32, - pub backing_validators_per_candidate: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, - ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::ValidityAttestation, - )>, - )>, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionInfo { - pub active_validator_indices: - ::std::vec::Vec, - pub random_seed: [::core::primitive::u8; 32usize], - pub dispute_period: ::core::primitive::u32, - pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub discovery_keys: - ::std::vec::Vec, - pub assignment_keys: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::assignment_app::Public, - >, - pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::GroupIndex, - ::std::vec::Vec, - >, - pub n_cores: ::core::primitive::u32, - pub zeroth_delay_tranche_width: ::core::primitive::u32, - pub relay_vrf_modulo_samples: ::core::primitive::u32, - pub n_delay_tranches: ::core::primitive::u32, - pub no_show_slots: ::core::primitive::u32, - pub needed_approvals: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - #[codec(index = 1)] - BackingSeconded(::subxt::utils::H256), - #[codec(index = 2)] - BackingValid(::subxt::utils::H256), - #[codec(index = 3)] - ApprovalChecking, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ValidatorIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidityAttestation { - #[codec(index = 1)] - Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - #[codec(index = 2)] - Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - } - } - pub mod vstaging { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - } - pub mod polkadot_runtime_common { - use super::runtime_types; - pub mod auctions { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - new_auction { - #[codec(compact)] - duration: ::core::primitive::u32, - #[codec(compact)] - lease_period_index: ::core::primitive::u32, - }, - #[codec(index = 1)] - bid { - #[codec(compact)] - para: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - auction_index: ::core::primitive::u32, - #[codec(compact)] - first_slot: ::core::primitive::u32, - #[codec(compact)] - last_slot: ::core::primitive::u32, - #[codec(compact)] - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - cancel_auction, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AuctionInProgress, - #[codec(index = 1)] - LeasePeriodInPast, - #[codec(index = 2)] - ParaNotRegistered, - #[codec(index = 3)] - NotCurrentAuction, - #[codec(index = 4)] - NotAuction, - #[codec(index = 5)] - AuctionEnded, - #[codec(index = 6)] - AlreadyLeasedOut, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - AuctionStarted { - auction_index: ::core::primitive::u32, - lease_period: ::core::primitive::u32, - ending: ::core::primitive::u32, - }, - #[codec(index = 1)] - AuctionClosed { auction_index: ::core::primitive::u32 }, - #[codec(index = 2)] - Reserved { - bidder: ::sp_core::crypto::AccountId32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unreserved { - bidder: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - ReserveConfiscated { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - BidAccepted { - bidder: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - first_slot: ::core::primitive::u32, - last_slot: ::core::primitive::u32, - }, - #[codec(index = 6)] - WinningOffset { - auction_index: ::core::primitive::u32, - block_number: ::core::primitive::u32, - }, - } - } - } - pub mod claims { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { - dest: ::sp_core::crypto::AccountId32, - ethereum_signature: - runtime_types::polkadot_runtime_common::claims::EcdsaSignature, - }, - #[codec(index = 1)] - mint_claim { - who: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - value: ::core::primitive::u128, - vesting_schedule: ::core::option::Option<( - ::core::primitive::u128, - ::core::primitive::u128, - ::core::primitive::u32, - )>, - statement: ::core::option::Option< - runtime_types::polkadot_runtime_common::claims::StatementKind, - >, - }, - #[codec(index = 2)] - claim_attest { - dest: ::sp_core::crypto::AccountId32, - ethereum_signature: - runtime_types::polkadot_runtime_common::claims::EcdsaSignature, - statement: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 3)] - attest { statement: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - move_claim { - old: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - new: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - maybe_preclaim: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEthereumSignature, - #[codec(index = 1)] - SignerHasNoClaim, - #[codec(index = 2)] - SenderHasNoClaim, - #[codec(index = 3)] - PotUnderflow, - #[codec(index = 4)] - InvalidStatement, - #[codec(index = 5)] - VestedBalanceExists, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Claimed { - who: ::sp_core::crypto::AccountId32, - ethereum_address: - runtime_types::polkadot_runtime_common::claims::EthereumAddress, - amount: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EcdsaSignature(pub [::core::primitive::u8; 65usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EthereumAddress(pub [::core::primitive::u8; 20usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StatementKind { - #[codec(index = 0)] - Regular, - #[codec(index = 1)] - Saft, - } - } - pub mod crowdloan { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - create { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 1)] - contribute { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - value: ::core::primitive::u128, - signature: - ::core::option::Option, - }, - #[codec(index = 2)] - withdraw { - who: ::sp_core::crypto::AccountId32, - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 3)] - refund { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - dissolve { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - edit { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 6)] - add_memo { - index: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 7)] - poke { index: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - contribute_all { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - signature: - ::core::option::Option, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FirstPeriodInPast, - #[codec(index = 1)] - FirstPeriodTooFarInFuture, - #[codec(index = 2)] - LastPeriodBeforeFirstPeriod, - #[codec(index = 3)] - LastPeriodTooFarInFuture, - #[codec(index = 4)] - CannotEndInPast, - #[codec(index = 5)] - EndTooFarInFuture, - #[codec(index = 6)] - Overflow, - #[codec(index = 7)] - ContributionTooSmall, - #[codec(index = 8)] - InvalidParaId, - #[codec(index = 9)] - CapExceeded, - #[codec(index = 10)] - ContributionPeriodOver, - #[codec(index = 11)] - InvalidOrigin, - #[codec(index = 12)] - NotParachain, - #[codec(index = 13)] - LeaseActive, - #[codec(index = 14)] - BidOrLeaseActive, - #[codec(index = 15)] - FundNotEnded, - #[codec(index = 16)] - NoContributions, - #[codec(index = 17)] - NotReadyToDissolve, - #[codec(index = 18)] - InvalidSignature, - #[codec(index = 19)] - MemoTooLarge, - #[codec(index = 20)] - AlreadyInNewRaise, - #[codec(index = 21)] - VrfDelayInProgress, - #[codec(index = 22)] - NoLeasePeriod, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 1)] - Contributed { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Withdrew { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - PartiallyRefunded { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 6)] - HandleBidResult { - para_id: runtime_types::polkadot_parachain::primitives::Id, - result: ::core::result::Result< - (), - runtime_types::sp_runtime::DispatchError, - >, - }, - #[codec(index = 7)] - Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - MemoUpdated { - who: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 9)] - AddedToNewRaise { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FundInfo<_0, _1, _2, _3> { - pub depositor: _0, - pub verifier: ::core::option::Option, - pub deposit: _1, - pub raised: _1, - pub end: _2, - pub cap: _1, - pub last_contribution: - runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, - pub first_period: _2, - pub last_period: _2, - pub fund_index: _2, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum LastContribution<_0> { - #[codec(index = 0)] - Never, - #[codec(index = 1)] - PreEnding(_0), - #[codec(index = 2)] - Ending(_0), - } - } - pub mod paras_registrar { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register { - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_register { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 2)] - deregister { id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 3)] - swap { - id: runtime_types::polkadot_parachain::primitives::Id, - other: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - reserve, - #[codec(index = 6)] - add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 7)] - schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 8)] - set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - AlreadyRegistered, - #[codec(index = 2)] - NotOwner, - #[codec(index = 3)] - CodeTooLarge, - #[codec(index = 4)] - HeadDataTooLarge, - #[codec(index = 5)] - NotParachain, - #[codec(index = 6)] - NotParathread, - #[codec(index = 7)] - CannotDeregister, - #[codec(index = 8)] - CannotDowngrade, - #[codec(index = 9)] - CannotUpgrade, - #[codec(index = 10)] - ParaLocked, - #[codec(index = 11)] - NotReserved, - #[codec(index = 12)] - EmptyCode, - #[codec(index = 13)] - CannotSwap, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Registered { - para_id: runtime_types::polkadot_parachain::primitives::Id, - manager: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 1)] - Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - Reserved { - para_id: runtime_types::polkadot_parachain::primitives::Id, - who: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Swapped { - para_id: runtime_types::polkadot_parachain::primitives::Id, - other_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo<_0, _1> { - pub manager: _0, - pub deposit: _1, - pub locked: ::core::primitive::bool, - } - } - pub mod slots { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_lease { - para: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - }, - #[codec(index = 1)] - clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaNotOnboarding, - #[codec(index = 1)] - LeaseError, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewLeasePeriod { lease_period: ::core::primitive::u32 }, - #[codec(index = 1)] - Leased { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - } - } - } - } - pub mod polkadot_runtime_parachains { - use super::runtime_types; - pub mod configuration { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidNewValue, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HostConfiguration<_0> { - pub max_code_size: _0, - pub max_head_data_size: _0, - pub max_upward_queue_count: _0, - pub max_upward_queue_size: _0, - pub max_upward_message_size: _0, - pub max_upward_message_num_per_candidate: _0, - pub hrmp_max_message_num_per_candidate: _0, - pub validation_upgrade_cooldown: _0, - pub validation_upgrade_delay: _0, - pub async_backing_params: - runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, - pub max_pov_size: _0, - pub max_downward_message_size: _0, - pub hrmp_max_parachain_outbound_channels: _0, - pub hrmp_max_parathread_outbound_channels: _0, - pub hrmp_sender_deposit: ::core::primitive::u128, - pub hrmp_recipient_deposit: ::core::primitive::u128, - pub hrmp_channel_max_capacity: _0, - pub hrmp_channel_max_total_size: _0, - pub hrmp_max_parachain_inbound_channels: _0, - pub hrmp_max_parathread_inbound_channels: _0, - pub hrmp_channel_max_message_size: _0, - pub executor_params: - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, - pub code_retention_period: _0, - pub parathread_cores: _0, - pub parathread_retries: _0, - pub group_rotation_frequency: _0, - pub chain_availability_period: _0, - pub thread_availability_period: _0, - pub scheduling_lookahead: _0, - pub max_validators_per_core: ::core::option::Option<_0>, - pub max_validators: ::core::option::Option<_0>, - pub dispute_period: _0, - pub dispute_post_conclusion_acceptance_period: _0, - pub no_show_slots: _0, - pub n_delay_tranches: _0, - pub zeroth_delay_tranche_width: _0, - pub needed_approvals: _0, - pub relay_vrf_modulo_samples: _0, - pub pvf_checking_enabled: ::core::primitive::bool, - pub pvf_voting_ttl: _0, - pub minimum_validation_upgrade_delay: _0, - } - } - pub mod disputes { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_unfreeze, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateDisputeStatementSets, - #[codec(index = 1)] - AncientDisputeStatement, - #[codec(index = 2)] - ValidatorIndexOutOfBounds, - #[codec(index = 3)] - InvalidSignature, - #[codec(index = 4)] - DuplicateStatement, - #[codec(index = 5)] - SingleSidedDispute, - #[codec(index = 6)] - MaliciousBacker, - #[codec(index = 7)] - MissingBackingVotes, - #[codec(index = 8)] - UnconfirmedDispute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - DisputeInitiated( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, - ), - #[codec(index = 1)] - DisputeConcluded( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, - ), - #[codec(index = 2)] - Revert(::core::primitive::u32), - } - } - pub mod slashing { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Call { - # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Error { - #[codec(index = 0)] - InvalidKeyOwnershipProof, - #[codec(index = 1)] - InvalidSessionIndex, - #[codec(index = 2)] - InvalidCandidateHash, - #[codec(index = 3)] - InvalidValidatorIndex, - #[codec(index = 4)] - ValidatorIndexIdMismatch, - #[codec(index = 5)] - DuplicateSlashingReport, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputesTimeSlot { - pub session_index: ::core::primitive::u32, - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SlashingOffenceKind { - #[codec(index = 0)] - ForInvalid, - #[codec(index = 1)] - AgainstValid, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeLocation { - #[codec(index = 0)] - Local, - #[codec(index = 1)] - Remote, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeResult { - #[codec(index = 0)] - Valid, - #[codec(index = 1)] - Invalid, - } - } - pub mod hrmp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - hrmp_init_open_channel { - recipient: runtime_types::polkadot_parachain::primitives::Id, - proposed_max_capacity: ::core::primitive::u32, - proposed_max_message_size: ::core::primitive::u32, - }, - #[codec(index = 1)] - hrmp_accept_open_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 2)] - hrmp_close_channel { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - }, - #[codec(index = 3)] - force_clean_hrmp { - para: runtime_types::polkadot_parachain::primitives::Id, - inbound: ::core::primitive::u32, - outbound: ::core::primitive::u32, - }, - #[codec(index = 4)] - force_process_hrmp_open { channels: ::core::primitive::u32 }, - #[codec(index = 5)] - force_process_hrmp_close { channels: ::core::primitive::u32 }, - #[codec(index = 6)] - hrmp_cancel_open_request { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - open_requests: ::core::primitive::u32, - }, - #[codec(index = 7)] - force_open_hrmp_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - recipient: runtime_types::polkadot_parachain::primitives::Id, - max_capacity: ::core::primitive::u32, - max_message_size: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OpenHrmpChannelToSelf, - #[codec(index = 1)] - OpenHrmpChannelInvalidRecipient, - #[codec(index = 2)] - OpenHrmpChannelZeroCapacity, - #[codec(index = 3)] - OpenHrmpChannelCapacityExceedsLimit, - #[codec(index = 4)] - OpenHrmpChannelZeroMessageSize, - #[codec(index = 5)] - OpenHrmpChannelMessageSizeExceedsLimit, - #[codec(index = 6)] - OpenHrmpChannelAlreadyExists, - #[codec(index = 7)] - OpenHrmpChannelAlreadyRequested, - #[codec(index = 8)] - OpenHrmpChannelLimitExceeded, - #[codec(index = 9)] - AcceptHrmpChannelDoesntExist, - #[codec(index = 10)] - AcceptHrmpChannelAlreadyConfirmed, - #[codec(index = 11)] - AcceptHrmpChannelLimitExceeded, - #[codec(index = 12)] - CloseHrmpChannelUnauthorized, - #[codec(index = 13)] - CloseHrmpChannelDoesntExist, - #[codec(index = 14)] - CloseHrmpChannelAlreadyUnderway, - #[codec(index = 15)] - CancelHrmpOpenChannelUnauthorized, - #[codec(index = 16)] - OpenHrmpChannelDoesntExist, - #[codec(index = 17)] - OpenHrmpChannelAlreadyConfirmed, - #[codec(index = 18)] - WrongWitness, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - OpenChannelRequested( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - #[codec(index = 1)] - OpenChannelCanceled( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 2)] - OpenChannelAccepted( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 3)] - ChannelClosed( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 4)] - HrmpChannelForceOpened( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - pub sender_deposit: ::core::primitive::u128, - pub recipient_deposit: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpOpenChannelRequest { - pub confirmed: ::core::primitive::bool, - pub _age: ::core::primitive::u32, - pub sender_deposit: ::core::primitive::u128, - pub max_message_size: ::core::primitive::u32, - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - } - } - pub mod inclusion { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnsortedOrDuplicateValidatorIndices, - #[codec(index = 1)] - UnsortedOrDuplicateDisputeStatementSet, - #[codec(index = 2)] - UnsortedOrDuplicateBackedCandidates, - #[codec(index = 3)] - UnexpectedRelayParent, - #[codec(index = 4)] - WrongBitfieldSize, - #[codec(index = 5)] - BitfieldAllZeros, - #[codec(index = 6)] - BitfieldDuplicateOrUnordered, - #[codec(index = 7)] - ValidatorIndexOutOfBounds, - #[codec(index = 8)] - InvalidBitfieldSignature, - #[codec(index = 9)] - UnscheduledCandidate, - #[codec(index = 10)] - CandidateScheduledBeforeParaFree, - #[codec(index = 11)] - WrongCollator, - #[codec(index = 12)] - ScheduledOutOfOrder, - #[codec(index = 13)] - HeadDataTooLarge, - #[codec(index = 14)] - PrematureCodeUpgrade, - #[codec(index = 15)] - NewCodeTooLarge, - #[codec(index = 16)] - CandidateNotInParentContext, - #[codec(index = 17)] - InvalidGroupIndex, - #[codec(index = 18)] - InsufficientBacking, - #[codec(index = 19)] - InvalidBacking, - #[codec(index = 20)] - NotCollatorSigned, - #[codec(index = 21)] - ValidationDataHashMismatch, - #[codec(index = 22)] - IncorrectDownwardMessageHandling, - #[codec(index = 23)] - InvalidUpwardMessages, - #[codec(index = 24)] - HrmpWatermarkMishandling, - #[codec(index = 25)] - InvalidOutboundHrmp, - #[codec(index = 26)] - InvalidValidationCodeHash, - #[codec(index = 27)] - ParaHeadMismatch, - #[codec(index = 28)] - BitfieldReferencesFreedCore, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CandidateBacked( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 1)] - CandidateIncluded( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 2)] - CandidateTimedOut( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - ), - #[codec(index = 3)] - UpwardMessagesReceived { - from: runtime_types::polkadot_parachain::primitives::Id, - count: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfieldRecord<_0> { - pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - pub submitted_at: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidatePendingAvailability<_0, _1> { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub availability_votes: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub backers: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub relay_parent_number: _1, - pub backed_in_number: _1, - pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UmpQueueId { - #[codec(index = 0)] - Para(runtime_types::polkadot_parachain::primitives::Id), - } - } - pub mod initializer { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_approve { up_to: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BufferedSessionChange { - pub validators: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub queued: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub session_index: ::core::primitive::u32, - } - } - pub mod origin { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Parachain(runtime_types::polkadot_parachain::primitives::Id), - } - } - } - pub mod paras { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_set_current_code { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 2)] - force_schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - relay_parent_number: ::core::primitive::u32, - }, - #[codec(index = 3)] - force_note_new_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 4)] - force_queue_action { - para: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - add_trusted_validation_code { - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 6)] - poke_unused_validation_code { - validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - }, - #[codec(index = 7)] - include_pvf_check_statement { - stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, - signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - CannotOnboard, - #[codec(index = 2)] - CannotOffboard, - #[codec(index = 3)] - CannotUpgrade, - #[codec(index = 4)] - CannotDowngrade, - #[codec(index = 5)] - PvfCheckStatementStale, - #[codec(index = 6)] - PvfCheckStatementFuture, - #[codec(index = 7)] - PvfCheckValidatorIndexOutOfBounds, - #[codec(index = 8)] - PvfCheckInvalidSignature, - #[codec(index = 9)] - PvfCheckDoubleVote, - #[codec(index = 10)] - PvfCheckSubjectInvalid, - #[codec(index = 11)] - CannotUpgradeCode, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 2)] - CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 3)] - NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 4)] - ActionQueued( - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ), - #[codec(index = 5)] - PvfCheckStarted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 6)] - PvfCheckAccepted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 7)] - PvfCheckRejected( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaGenesisArgs { - pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - pub validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - pub para_kind: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ParaLifecycle { - #[codec(index = 0)] - Onboarding, - #[codec(index = 1)] - Parathread, - #[codec(index = 2)] - Parachain, - #[codec(index = 3)] - UpgradingParathread, - #[codec(index = 4)] - DowngradingParachain, - #[codec(index = 5)] - OffboardingParathread, - #[codec(index = 6)] - OffboardingParachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaPastCodeMeta<_0> { - pub upgrade_times: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, - >, - pub last_pruned: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckActiveVoteState<_0> { - pub votes_accept: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub votes_reject: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub age: _0, - pub created_at: _0, - pub causes: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfCheckCause<_0> { - #[codec(index = 0)] - Onboarding(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - Upgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - relay_parent_number: _0, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReplacementTimes<_0> { - pub expected_at: _0, - pub activated_at: _0, - } - } - pub mod paras_inherent { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - enter { - data: runtime_types::polkadot_primitives::v4::InherentData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyInclusionInherents, - #[codec(index = 1)] - InvalidParentHeader, - #[codec(index = 2)] - CandidateConcludedInvalid, - #[codec(index = 3)] - InherentOverweight, - #[codec(index = 4)] - DisputeStatementsUnsortedOrDuplicates, - #[codec(index = 5)] - DisputeInvalid, - } - } - } - pub mod scheduler { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssignmentKind { - #[codec(index = 0)] - Parachain, - #[codec(index = 1)] - Parathread( - runtime_types::polkadot_primitives::v4::collator_app::Public, - ::core::primitive::u32, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CoreAssignment { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, - pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaimQueue { - pub queue: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, - >, - pub next_core_offset: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueuedParathread { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, - pub core_offset: ::core::primitive::u32, - } - } - pub mod shared { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - } - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FixedI64(pub ::core::primitive::i64); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - pub mod per_things { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct PerU16(pub ::core::primitive::u16); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Perbill(pub ::core::primitive::u32); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Percent(pub ::core::primitive::u8); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Permill(pub ::core::primitive::u32); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Perquintill(pub ::core::primitive::u64); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_authority_discovery { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - pub mod sp_consensus_babe { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod digests { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NextConfigDescriptor { - #[codec(index = 1)] - V1 { - c: (::core::primitive::u64, ::core::primitive::u64), - allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PreDigest { - #[codec(index = 1)] - Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), - #[codec(index = 2)] - SecondaryPlain( - runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, - ), - #[codec(index = 3)] - SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PrimaryPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryPlainPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryVRFPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AllowedSlots { - #[codec(index = 0)] - PrimarySlots, - #[codec(index = 1)] - PrimaryAndSecondaryPlainSlots, - #[codec(index = 2)] - PrimaryAndSecondaryVRFSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BabeEpochConfiguration { - pub c: (::core::primitive::u64, ::core::primitive::u64), - pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Equivocation<_0, _1> { - #[codec(index = 0)] - Prevote( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Prevote<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - #[codec(index = 1)] - Precommit( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Precommit<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EquivocationProof<_0, _1> { - pub offender: _1, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub first_header: _0, - pub second_header: _0, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 33usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod offchain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueNetworkState { - pub peer_id: runtime_types::sp_core::OpaquePeerId, - pub external_addresses: - ::std::vec::Vec, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod vrf { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VrfSignature { - pub output: [::core::primitive::u8; 32usize], - pub proof: [::core::primitive::u8; 64usize], - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_npos_elections { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ElectionScore { - pub minimal_stake: ::core::primitive::u128, - pub sum_stake: ::core::primitive::u128, - pub sum_stake_squared: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Support<_0> { - pub total: ::core::primitive::u128, - pub voters: ::std::vec::Vec<(_0, ::core::primitive::u128)>, - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, - ); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchErrorWithPostInfo<_0> { - pub post_info: _0, - pub error: runtime_types::sp_runtime::DispatchError, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSigner { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Public), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Public), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Public), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_staking { - use super::runtime_types; - pub mod offence { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OffenceDetails<_0, _1> { - pub offender: _1, - pub reporters: ::std::vec::Vec<_0>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - } - } -} diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs deleted file mode 100644 index 24a6adfe95d4c..0000000000000 --- a/relays/client-kusama/src/lib.rs +++ /dev/null @@ -1,122 +0,0 @@ -// 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 . - -//! Types used to connect to the Kusama chain. - -pub mod codegen_runtime; - -use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, - Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, - UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use sp_session::MembershipProof; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::kusama_runtime::RuntimeCall; - -pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; - -/// Kusama header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Kusama header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Kusama chain definition -#[derive(Debug, Clone, Copy)] -pub struct Kusama; - -impl UnderlyingChainProvider for Kusama { - type Chain = bp_kusama::Kusama; -} - -impl Chain for Kusama { - const NAME: &'static str = "Kusama"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_kusama::BEST_FINALIZED_KUSAMA_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_kusama::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithGrandpa for Kusama { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - KUSAMA_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl ChainWithBalances for Kusama { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl RelayChain for Kusama { - const PARAS_PALLET_NAME: &'static str = bp_kusama::PARAS_PALLET_NAME; -} - -impl ChainWithTransactions for Kusama { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_kusama::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - ((), ()), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithRuntimeVersion for Kusama { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); -} diff --git a/relays/client-polkadot-bulletin/Cargo.toml b/relays/client-polkadot-bulletin/Cargo.toml deleted file mode 100644 index 842b53c48ef25..0000000000000 --- a/relays/client-polkadot-bulletin/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "relay-polkadot-bulletin-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-header-chain = { path = "../../primitives/header-chain" } -bp-messages = { path = "../../primitives/messages" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-polkadot-bulletin = { path = "../../chains/chain-polkadot-bulletin" } -bp-runtime = { path = "../../primitives/runtime" } -bridge-runtime-common = { path = "../../bin/runtime-common" } -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies - -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-polkadot-bulletin/src/codegen_runtime.rs b/relays/client-polkadot-bulletin/src/codegen_runtime.rs deleted file mode 100644 index 601a2dd973cd6..0000000000000 --- a/relays/client-polkadot-bulletin/src/codegen_runtime.rs +++ /dev/null @@ -1,1622 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url ws://127.0.0.1:10000 - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -#[allow(rustdoc::broken_intra_doc_links)] -pub mod api { - #[allow(unused_imports)] - mod root_mod { - pub use super::*; - } - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod bp_header_chain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AuthoritySet { - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HeaderChainError { - #[codec(index = 0)] - UnknownHeader, - #[codec(index = 1)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderFinalityInfo<_0, _1> { - pub finality_proof: _0, - pub new_verification_context: ::core::option::Option<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredHeaderData<_0, _1> { - pub number: _0, - pub state_root: _1, - } - } - pub mod bp_messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DeliveredMessages { - pub begin: ::core::primitive::u64, - pub end: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundLaneData<_0> { - pub relayers: ::std::vec::Vec>, - pub last_confirmed_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundMessageDetails { - pub dispatch_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LaneId(pub [::core::primitive::u8; 4usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageKey { - pub lane_id: runtime_types::bp_messages::LaneId, - pub nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MessagesOperatingMode { - #[codec(index = 0)] - Basic(runtime_types::bp_runtime::BasicOperatingMode), - #[codec(index = 1)] - RejectingOutboundMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundLaneData { - pub oldest_unpruned_nonce: ::core::primitive::u64, - pub latest_received_nonce: ::core::primitive::u64, - pub latest_generated_nonce: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundMessageDetails { - pub nonce: ::core::primitive::u64, - pub dispatch_weight: ::sp_weights::Weight, - pub size: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalResult<_0> { - #[codec(index = 0)] - Dispatched(runtime_types::bp_runtime::messages::MessageDispatchResult<_0>), - #[codec(index = 1)] - InvalidNonce, - #[codec(index = 2)] - TooManyUnrewardedRelayers, - #[codec(index = 3)] - TooManyUnconfirmedMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceivedMessages<_0> { - pub lane: runtime_types::bp_messages::LaneId, - pub receive_results: ::std::vec::Vec<( - ::core::primitive::u64, - runtime_types::bp_messages::ReceivalResult<_0>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnrewardedRelayer<_0> { - pub relayer: _0, - pub messages: runtime_types::bp_messages::DeliveredMessages, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VerificationError { - #[codec(index = 0)] - EmptyMessageProof, - #[codec(index = 1)] - HeaderChain(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 2)] - InboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 3)] - InvalidMessageWeight, - #[codec(index = 4)] - MessagesCountMismatch, - #[codec(index = 5)] - MessageStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 6)] - MessageTooLarge, - #[codec(index = 7)] - OutboundLaneStorage(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 8)] - StorageProof(runtime_types::bp_runtime::storage_proof::Error), - #[codec(index = 9)] - Other, - } - } - pub mod bp_parachains { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BestParaHeadHash { - pub at_relay_block_number: ::core::primitive::u32, - pub head_hash: ::subxt::utils::H256, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo { - pub best_head_hash: runtime_types::bp_parachains::BestParaHeadHash, - pub next_imported_hash_position: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaStoredHeaderData(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod bp_runtime { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MessageDispatchResult<_0> { - pub unspent_weight: ::sp_weights::Weight, - pub dispatch_level_result: _0, - } - } - pub mod storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateNodesInProof, - #[codec(index = 1)] - UnusedNodesInTheProof, - #[codec(index = 2)] - StorageRootMismatch, - #[codec(index = 3)] - StorageValueUnavailable, - #[codec(index = 4)] - StorageValueEmpty, - #[codec(index = 5)] - StorageValueDecodeFailed(runtime_types::bp_runtime::StrippableError), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BasicOperatingMode { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeaderId<_0, _1>(pub _1, pub _0); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OwnedBridgeModuleError { - #[codec(index = 0)] - Halted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StrippableError; - } - pub mod bridge_runtime_common { - use super::runtime_types; - pub mod messages_xcm_extension { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum XcmBlobMessageDispatchResult { - #[codec(index = 0)] - InvalidPayload, - #[codec(index = 1)] - Dispatched, - #[codec(index = 2)] - NotDispatched, - } - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commit<_0, _1, _2, _3> { - pub target_hash: _0, - pub target_number: _1, - pub precommits: ::std::vec::Vec< - runtime_types::finality_grandpa::SignedPrecommit<_0, _1, _2, _3>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Equivocation<_0, _1, _2> { - pub round_number: ::core::primitive::u64, - pub identity: _0, - pub first: (_1, _2), - pub second: (_1, _2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Prevote<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedPrecommit<_0, _1, _2, _3> { - pub precommit: runtime_types::finality_grandpa::Precommit<_0, _1>, - pub signature: _2, - pub id: _3, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - } - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: ::core::primitive::u32, - pub providers: ::core::primitive::u32, - pub sufficients: ::core::primitive::u32, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_babe { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - plan_config_change { - config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEquivocationProof, - #[codec(index = 1)] - InvalidKeyOwnershipProof, - #[codec(index = 2)] - DuplicateOffenceReport, - #[codec(index = 3)] - InvalidConfiguration, - } - } - } - pub mod pallet_bridge_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_finality_proof { - finality_target: ::std::boxed::Box< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - justification: ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 1)] - initialize { - init_data: ::bp_header_chain::InitializationData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - #[codec(index = 2)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 3)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidJustification, - #[codec(index = 1)] - InvalidAuthoritySet, - #[codec(index = 2)] - OldHeader, - #[codec(index = 3)] - UnsupportedScheduledChange, - #[codec(index = 4)] - NotInitialized, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooManyAuthoritiesInSet, - #[codec(index = 7)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UpdatedBestFinalizedHeader { - number: ::core::primitive::u32, - hash: ::subxt::utils::H256, - grandpa_info: runtime_types::bp_header_chain::HeaderFinalityInfo< - ::bp_header_chain::justification::GrandpaJustification< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - runtime_types::bp_header_chain::AuthoritySet, - >, - }, - } - } - pub mod storage_types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredAuthoritySet { - pub authorities: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub set_id: ::core::primitive::u64, - } - } - } - pub mod pallet_bridge_messages { - use super::runtime_types; - pub mod outbound_lane { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReceivalConfirmationError { - #[codec(index = 0)] - FailedToConfirmFutureMessages, - #[codec(index = 1)] - EmptyUnrewardedRelayerEntry, - #[codec(index = 2)] - NonConsecutiveUnrewardedRelayerEntries, - #[codec(index = 3)] - TryingToConfirmMoreMessagesThanExpected, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_owner { new_owner : :: core :: option :: Option < :: sp_core :: crypto :: AccountId32 > , } , # [codec (index = 1)] set_operating_mode { operating_mode : runtime_types :: bp_messages :: MessagesOperatingMode , } , # [codec (index = 2)] receive_messages_proof { relayer_id_at_bridged_chain : :: sp_core :: crypto :: AccountId32 , proof : :: bridge_runtime_common :: messages :: target :: FromBridgedChainMessagesProof < :: subxt :: utils :: H256 > , messages_count : :: core :: primitive :: u32 , dispatch_weight : :: sp_weights :: Weight , } , # [codec (index = 3)] receive_messages_delivery_proof { proof : :: bridge_runtime_common :: messages :: source :: FromBridgedChainMessagesDeliveryProof < :: subxt :: utils :: H256 > , relayers_state : :: bp_messages :: UnrewardedRelayersState , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - # [codec (index = 0)] NotOperatingNormally , # [codec (index = 1)] InactiveOutboundLane , # [codec (index = 2)] MessageDispatchInactive , # [codec (index = 3)] MessageRejectedByChainVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 4)] MessageRejectedByLaneVerifier (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 5)] MessageRejectedByPallet (runtime_types :: bp_messages :: VerificationError ,) , # [codec (index = 6)] FailedToWithdrawMessageFee , # [codec (index = 7)] TooManyMessagesInTheProof , # [codec (index = 8)] InvalidMessagesProof , # [codec (index = 9)] InvalidMessagesDeliveryProof , # [codec (index = 10)] InvalidUnrewardedRelayersState , # [codec (index = 11)] InsufficientDispatchWeight , # [codec (index = 12)] MessageIsNotYetSent , # [codec (index = 13)] ReceivalConfirmation (runtime_types :: pallet_bridge_messages :: outbound_lane :: ReceivalConfirmationError ,) , # [codec (index = 14)] BridgeModule (runtime_types :: bp_runtime :: OwnedBridgeModuleError ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] MessageAccepted { lane_id : runtime_types :: bp_messages :: LaneId , nonce : :: core :: primitive :: u64 , } , # [codec (index = 1)] MessagesReceived (:: std :: vec :: Vec < runtime_types :: bp_messages :: ReceivedMessages < runtime_types :: bridge_runtime_common :: messages_xcm_extension :: XcmBlobMessageDispatchResult > > ,) , # [codec (index = 2)] MessagesDelivered { lane_id : runtime_types :: bp_messages :: LaneId , messages : runtime_types :: bp_messages :: DeliveredMessages , } , } - } - } - pub mod pallet_bridge_parachains { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit_parachain_heads { - at_relay_block: (::core::primitive::u32, ::subxt::utils::H256), - parachains: ::std::vec::Vec<( - ::bp_polkadot_core::parachains::ParaId, - ::subxt::utils::H256, - )>, - parachain_heads_proof: ::bp_polkadot_core::parachains::ParaHeadsProof, - }, - #[codec(index = 1)] - set_owner { new_owner: ::core::option::Option<::sp_core::crypto::AccountId32> }, - #[codec(index = 2)] - set_operating_mode { - operating_mode: runtime_types::bp_runtime::BasicOperatingMode, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnknownRelayChainBlock, - #[codec(index = 1)] - InvalidRelayChainBlockNumber, - #[codec(index = 2)] - HeaderChainStorageProof(runtime_types::bp_header_chain::HeaderChainError), - #[codec(index = 3)] - BridgeModule(runtime_types::bp_runtime::OwnedBridgeModuleError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - UntrackedParachainRejected { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 1)] - MissingParachainHead { parachain: ::bp_polkadot_core::parachains::ParaId }, - #[codec(index = 2)] - IncorrectParachainHeadHash { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - actual_parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - RejectedObsoleteParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - #[codec(index = 4)] - RejectedLargeParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - parachain_head_size: ::core::primitive::u32, - }, - #[codec(index = 5)] - UpdatedParachainHead { - parachain: ::bp_polkadot_core::parachains::ParaId, - parachain_head_hash: ::subxt::utils::H256, - }, - } - } - } - pub mod pallet_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - note_stalled { - delay: ::core::primitive::u32, - best_finalized_block_number: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PauseFailed, - #[codec(index = 1)] - ResumeFailed, - #[codec(index = 2)] - ChangePending, - #[codec(index = 3)] - TooSoon, - #[codec(index = 4)] - InvalidKeyOwnershipProof, - #[codec(index = 5)] - InvalidEquivocationProof, - #[codec(index = 6)] - DuplicateOffenceReport, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewAuthorities { - authority_set: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - }, - #[codec(index = 1)] - Paused, - #[codec(index = 2)] - Resumed, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredPendingChange<_0> { - pub scheduled_at: _0, - pub delay: _0, - pub next_authorities: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub forced: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StoredState<_0> { - #[codec(index = 0)] - Live, - #[codec(index = 1)] - PendingPause { scheduled_at: _0, delay: _0 }, - #[codec(index = 2)] - Paused, - #[codec(index = 3)] - PendingResume { scheduled_at: _0, delay: _0 }, - } - } - pub mod pallet_im_online { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - heartbeat { - heartbeat: - runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, - signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidKey, - #[codec(index = 1)] - DuplicatedHeartbeat, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - HeartbeatReceived { - authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - }, - #[codec(index = 1)] - AllGood, - #[codec(index = 2)] - SomeOffline { - offline: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - ::sp_core::crypto::AccountId32, - )>, - }, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Heartbeat<_0> { - pub block_number: _0, - pub session_index: ::core::primitive::u32, - pub authority_index: ::core::primitive::u32, - pub validators_len: ::core::primitive::u32, - } - } - pub mod pallet_offences { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Offence { - kind: [::core::primitive::u8; 16usize], - timeslot: ::std::vec::Vec<::core::primitive::u8>, - }, - } - } - } - pub mod pallet_relayer_set { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Duplicate, - #[codec(index = 1)] - NotARelayer, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RelayerAdded(::sp_core::crypto::AccountId32), - #[codec(index = 1)] - RelayerRemoved(::sp_core::crypto::AccountId32), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Relayer<_0> { - pub min_bridge_tx_block: _0, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::polkadot_bulletin_chain_runtime::opaque::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_sudo { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - sudo { - call: ::std::boxed::Box< - runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - sudo_unchecked_weight { - call: ::std::boxed::Box< - runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall, - >, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - set_key { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - sudo_as { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: ::std::boxed::Box< - runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - RequireSudo, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Sudid { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - KeyChanged { - old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 2)] - SudoAsDone { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_storage { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - store { data: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - renew { block: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - check_proof { - proof: runtime_types::sp_transaction_storage_proof::TransactionStorageProof, - }, - #[codec(index = 3)] - authorize_account { - who: ::sp_core::crypto::AccountId32, - transactions: ::core::primitive::u32, - bytes: ::core::primitive::u64, - }, - #[codec(index = 4)] - authorize_preimage { - hash: [::core::primitive::u8; 32usize], - max_size: ::core::primitive::u64, - }, - #[codec(index = 5)] - remove_expired_account_authorization { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - remove_expired_preimage_authorization { hash: [::core::primitive::u8; 32usize] }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - BadContext, - #[codec(index = 1)] - BadDataSize, - #[codec(index = 2)] - TooManyTransactions, - #[codec(index = 3)] - RenewedNotFound, - #[codec(index = 4)] - UnexpectedProof, - #[codec(index = 5)] - InvalidProof, - #[codec(index = 6)] - MissingStateData, - #[codec(index = 7)] - DoubleCheck, - #[codec(index = 8)] - AuthorizationNotFound, - #[codec(index = 9)] - AuthorizationNotExpired, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Stored { index: ::core::primitive::u32 }, - #[codec(index = 1)] - Renewed { index: ::core::primitive::u32 }, - #[codec(index = 2)] - ProofChecked, - #[codec(index = 3)] - AccountAuthorized { - who: ::sp_core::crypto::AccountId32, - transactions: ::core::primitive::u32, - bytes: ::core::primitive::u64, - }, - #[codec(index = 4)] - PreimageAuthorized { - hash: [::core::primitive::u8; 32usize], - max_size: ::core::primitive::u64, - }, - #[codec(index = 5)] - ExpiredAccountAuthorizationRemoved { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - ExpiredPreimageAuthorizationRemoved { hash: [::core::primitive::u8; 32usize] }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Authorization<_0> { - pub extent: runtime_types::pallet_transaction_storage::AuthorizationExtent, - pub expiration: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AuthorizationExtent { - pub transactions: ::core::primitive::u32, - pub bytes: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AuthorizationScope<_0> { - #[codec(index = 0)] - Account(_0), - #[codec(index = 1)] - Preimage([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct TransactionInfo { - pub chunk_root: ::subxt::utils::H256, - pub content_hash: ::subxt::utils::H256, - pub size: ::core::primitive::u32, - pub block_chunks: ::core::primitive::u32, - } - } - pub mod pallet_validator_set { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Duplicate, - #[codec(index = 1)] - NotAValidator, - #[codec(index = 2)] - TooManyValidators, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidatorAdded(::sp_core::crypto::AccountId32), - #[codec(index = 1)] - ValidatorRemoved(::sp_core::crypto::AccountId32), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Validator<_0> { - pub min_set_keys_block: _0, - } - } - pub mod polkadot_bulletin_chain_runtime { - use super::runtime_types; - pub mod opaque { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub babe: runtime_types::sp_consensus_babe::app::Public, - pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, - pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BridgeRejectObsoleteHeadersAndMessages; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - Babe(runtime_types::pallet_babe::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 14)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 15)] - ImOnline(runtime_types::pallet_im_online::pallet::Call), - #[codec(index = 16)] - Grandpa(runtime_types::pallet_grandpa::pallet::Call), - #[codec(index = 40)] - TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Call), - #[codec(index = 51)] - BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Call), - #[codec(index = 52)] - BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Call), - #[codec(index = 53)] - BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Call), - #[codec(index = 255)] - Sudo(runtime_types::pallet_sudo::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeError { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Error), - #[codec(index = 1)] - Babe(runtime_types::pallet_babe::pallet::Error), - #[codec(index = 13)] - ValidatorSet(runtime_types::pallet_validator_set::pallet::Error), - #[codec(index = 14)] - Session(runtime_types::pallet_session::pallet::Error), - #[codec(index = 15)] - ImOnline(runtime_types::pallet_im_online::pallet::Error), - #[codec(index = 16)] - Grandpa(runtime_types::pallet_grandpa::pallet::Error), - #[codec(index = 40)] - TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Error), - #[codec(index = 50)] - RelayerSet(runtime_types::pallet_relayer_set::pallet::Error), - #[codec(index = 51)] - BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Error), - #[codec(index = 52)] - BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Error), - #[codec(index = 53)] - BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Error), - #[codec(index = 255)] - Sudo(runtime_types::pallet_sudo::pallet::Error), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 11)] - Offences(runtime_types::pallet_offences::pallet::Event), - #[codec(index = 13)] - ValidatorSet(runtime_types::pallet_validator_set::pallet::Event), - #[codec(index = 14)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 15)] - ImOnline(runtime_types::pallet_im_online::pallet::Event), - #[codec(index = 16)] - Grandpa(runtime_types::pallet_grandpa::pallet::Event), - #[codec(index = 40)] - TransactionStorage(runtime_types::pallet_transaction_storage::pallet::Event), - #[codec(index = 50)] - RelayerSet(runtime_types::pallet_relayer_set::pallet::Event), - #[codec(index = 51)] - BridgePolkadotGrandpa(runtime_types::pallet_bridge_grandpa::pallet::Event), - #[codec(index = 52)] - BridgePolkadotParachains(runtime_types::pallet_bridge_parachains::pallet::Event), - #[codec(index = 53)] - BridgePolkadotMessages(runtime_types::pallet_bridge_messages::pallet::Event), - #[codec(index = 255)] - Sudo(runtime_types::pallet_sudo::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidateSigned; - } - pub mod sp_arithmetic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_consensus_babe { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod digests { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NextConfigDescriptor { - #[codec(index = 1)] - V1 { - c: (::core::primitive::u64, ::core::primitive::u64), - allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PreDigest { - #[codec(index = 1)] - Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), - #[codec(index = 2)] - SecondaryPlain( - runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, - ), - #[codec(index = 3)] - SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PrimaryPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryPlainPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryVRFPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AllowedSlots { - #[codec(index = 0)] - PrimarySlots, - #[codec(index = 1)] - PrimaryAndSecondaryPlainSlots, - #[codec(index = 2)] - PrimaryAndSecondaryVRFSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BabeConfiguration { - pub slot_duration: ::core::primitive::u64, - pub epoch_length: ::core::primitive::u64, - pub c: (::core::primitive::u64, ::core::primitive::u64), - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_babe::app::Public, - ::core::primitive::u64, - )>, - pub randomness: [::core::primitive::u8; 32usize], - pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BabeEpochConfiguration { - pub c: (::core::primitive::u64, ::core::primitive::u64), - pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Epoch { - pub epoch_index: ::core::primitive::u64, - pub start_slot: runtime_types::sp_consensus_slots::Slot, - pub duration: ::core::primitive::u64, - pub authorities: ::std::vec::Vec<( - runtime_types::sp_consensus_babe::app::Public, - ::core::primitive::u64, - )>, - pub randomness: [::core::primitive::u8; 32usize], - pub config: runtime_types::sp_consensus_babe::BabeEpochConfiguration, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueKeyOwnershipProof(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Equivocation<_0, _1> { - #[codec(index = 0)] - Prevote( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Prevote<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - #[codec(index = 1)] - Precommit( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Precommit<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueKeyOwnershipProof(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EquivocationProof<_0, _1> { - pub offender: _1, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub first_header: _0, - pub second_header: _0, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod sr25519 { - use super::runtime_types; - pub mod vrf { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VrfSignature { - pub output: [::core::primitive::u8; 32usize], - pub proof: [::core::primitive::u8; 64usize], - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMetadata(pub ::std::vec::Vec<::core::primitive::u8>); - } - pub mod sp_inherents { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckInherentsResult { - pub okay: ::core::primitive::bool, - pub fatal_error: ::core::primitive::bool, - pub errors: runtime_types::sp_inherents::InherentData, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData { - pub data: ::subxt::utils::KeyedVec< - [::core::primitive::u8; 8usize], - ::std::vec::Vec<::core::primitive::u8>, - >, - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod block { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Block<_0, _1> { - pub header: _0, - pub extrinsics: ::std::vec::Vec<_1>, - } - } - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - } - pub mod transaction_validity { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidTransaction { - #[codec(index = 0)] - Call, - #[codec(index = 1)] - Payment, - #[codec(index = 2)] - Future, - #[codec(index = 3)] - Stale, - #[codec(index = 4)] - BadProof, - #[codec(index = 5)] - AncientBirthBlock, - #[codec(index = 6)] - ExhaustsResources, - #[codec(index = 7)] - Custom(::core::primitive::u8), - #[codec(index = 8)] - BadMandatory, - #[codec(index = 9)] - MandatoryValidation, - #[codec(index = 10)] - BadSigner, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionSource { - #[codec(index = 0)] - InBlock, - #[codec(index = 1)] - Local, - #[codec(index = 2)] - External, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionValidityError { - #[codec(index = 0)] - Invalid(runtime_types::sp_runtime::transaction_validity::InvalidTransaction), - #[codec(index = 1)] - Unknown(runtime_types::sp_runtime::transaction_validity::UnknownTransaction), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UnknownTransaction { - #[codec(index = 0)] - CannotLookup, - #[codec(index = 1)] - NoUnsignedValidator, - #[codec(index = 2)] - Custom(::core::primitive::u8), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidTransaction { - pub priority: ::core::primitive::u64, - pub requires: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub provides: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - pub longevity: ::core::primitive::u64, - pub propagate: ::core::primitive::bool, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_staking { - use super::runtime_types; - pub mod offence { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OffenceDetails<_0, _1> { - pub offender: _1, - pub reporters: ::std::vec::Vec<_0>, - } - } - } - pub mod sp_transaction_storage_proof { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct TransactionStorageProof { - pub chunk: ::std::vec::Vec<::core::primitive::u8>, - pub proof: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - } -} diff --git a/relays/client-polkadot-bulletin/src/lib.rs b/relays/client-polkadot-bulletin/src/lib.rs deleted file mode 100644 index 1f18b25a9054a..0000000000000 --- a/relays/client-polkadot-bulletin/src/lib.rs +++ /dev/null @@ -1,137 +0,0 @@ -// 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 . - -//! Types used to connect to the Polkadot Bulletin chain. - -mod codegen_runtime; - -use bp_polkadot_bulletin::POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, ChainWithRuntimeVersion, - ChainWithTransactions, Error as SubstrateError, SignParam, SimpleRuntimeVersion, - UnderlyingChainProvider, UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use sp_session::MembershipProof; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -/// Call of the Polkadot Bulletin Chain runtime. -pub type RuntimeCall = runtime_types::polkadot_bulletin_chain_runtime::RuntimeCall; -/// Call of the `Sudo` pallet. -pub type SudoCall = runtime_types::pallet_sudo::pallet::Call; -/// Call of the GRANDPA pallet. -pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; -/// Call of the with-PolkadotBridgeHub bridge GRANDPA pallet. -pub type BridgePolkadotGrandpaCall = runtime_types::pallet_bridge_grandpa::pallet::Call; -/// Call of the with-PolkadotBridgeHub bridge parachains pallet. -pub type BridgePolkadotParachainsCall = runtime_types::pallet_bridge_parachains::pallet::Call; -/// Call of the with-PolkadotBridgeHub bridge messages pallet. -pub type BridgePolkadotMessagesCall = runtime_types::pallet_bridge_messages::pallet::Call; - -/// Polkadot header id. -pub type HeaderId = - relay_utils::HeaderId; - -/// Polkadot header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Polkadot chain definition -#[derive(Debug, Clone, Copy)] -pub struct PolkadotBulletin; - -impl UnderlyingChainProvider for PolkadotBulletin { - type Chain = bp_polkadot_bulletin::PolkadotBulletin; -} - -impl Chain for PolkadotBulletin { - const NAME: &'static str = "PolkadotBulletin"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_polkadot_bulletin::BEST_FINALIZED_POLKADOT_BULLETIN_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_polkadot_bulletin::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithGrandpa for PolkadotBulletin { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - POLKADOT_BULLETIN_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl ChainWithMessages for PolkadotBulletin { - // this is not critical (some metrics will be missing from the storage), but probably it needs - // to be changed when we'll polish the bridge configuration - const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; - - const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot_bulletin::TO_POLKADOT_BULLETIN_MESSAGE_DETAILS_METHOD; - const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = - bp_polkadot_bulletin::FROM_POLKADOT_BULLETIN_MESSAGE_DETAILS_METHOD; -} - -impl ChainWithBalances for PolkadotBulletin { - fn account_info_storage_key(_account_id: &Self::AccountId) -> StorageKey { - // no balances at this chain - StorageKey(vec![]) - } -} - -impl ChainWithTransactions for PolkadotBulletin { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_bulletin::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_polkadot_bulletin::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithRuntimeVersion for PolkadotBulletin { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 100, transaction_version: 1 }); -} diff --git a/relays/client-polkadot/Cargo.toml b/relays/client-polkadot/Cargo.toml deleted file mode 100644 index 19cf9f9335bc5..0000000000000 --- a/relays/client-polkadot/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "relay-polkadot-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-polkadot = { path = "../../chains/chain-polkadot" } -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } - -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies - -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-polkadot/src/codegen_runtime.rs b/relays/client-polkadot/src/codegen_runtime.rs deleted file mode 100644 index aa4b37cec502a..0000000000000 --- a/relays/client-polkadot/src/codegen_runtime.rs +++ /dev/null @@ -1,8399 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://rpc.polkadot.io:443 - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -pub mod api { - use super::api as root_mod; - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_btree_map { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedBTreeMap<_0, _1>(pub ::subxt::utils::KeyedVec<_0, _1>); - } - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Equivocation<_0, _1, _2> { - pub round_number: ::core::primitive::u64, - pub identity: _0, - pub first: (_1, _2), - pub second: (_1, _2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Prevote<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PostDispatchInfo { - pub actual_weight: ::core::option::Option<::sp_weights::Weight>, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProcessMessageError { - #[codec(index = 0)] - BadFormat, - #[codec(index = 1)] - Corrupt, - #[codec(index = 2)] - Unsupported, - #[codec(index = 3)] - Overweight(::sp_weights::Weight), - #[codec(index = 4)] - Yield, - } - } - pub mod misc { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WrapperOpaque<_0>( - #[codec(compact)] pub ::core::primitive::u32, - pub _0, - ); - } - pub mod preimages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Bounded<_0> { - #[codec(index = 0)] - Legacy { - hash: ::subxt::utils::H256, - }, - #[codec(index = 1)] - Inline( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Lookup { - hash: ::subxt::utils::H256, - len: ::core::primitive::u32, - }, - __Ignore(::core::marker::PhantomData<_0>), - } - } - pub mod schedule { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchTime<_0> { - #[codec(index = 0)] - At(_0), - #[codec(index = 1)] - After(_0), - } - } - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletId(pub [::core::primitive::u8; 8usize]); - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_babe { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - plan_config_change { - config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEquivocationProof, - #[codec(index = 1)] - InvalidKeyOwnershipProof, - #[codec(index = 2)] - DuplicateOffenceReport, - #[codec(index = 3)] - InvalidConfiguration, - } - } - } - pub mod pallet_bags_list { - use super::runtime_types; - pub mod list { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bag { - pub head: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub tail: ::core::option::Option<::sp_core::crypto::AccountId32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ListError { - #[codec(index = 0)] - Duplicate, - #[codec(index = 1)] - NotHeavier, - #[codec(index = 2)] - NotInSameBag, - #[codec(index = 3)] - NodeNotFound, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Node { - pub id: ::sp_core::crypto::AccountId32, - pub prev: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub next: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub bag_upper: ::core::primitive::u64, - pub score: ::core::primitive::u64, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - rebag { - dislocated: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - put_in_front_of { - lighter: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - List(runtime_types::pallet_bags_list::list::ListError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Rebagged { - who: ::sp_core::crypto::AccountId32, - from: ::core::primitive::u64, - to: ::core::primitive::u64, - }, - #[codec(index = 1)] - ScoreUpdated { - who: ::sp_core::crypto::AccountId32, - new_score: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - set_balance_deprecated { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - #[codec(compact)] - old_reserved: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 7)] - transfer { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_bounties { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose_bounty { - #[codec(compact)] - value: ::core::primitive::u128, - description: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - approve_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 2)] - propose_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 3)] - unassign_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 4)] - accept_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 5)] - award_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - claim_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 7)] - close_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 8)] - extend_bounty_expiry { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - remark: ::std::vec::Vec<::core::primitive::u8>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InsufficientProposersBalance, - #[codec(index = 1)] - InvalidIndex, - #[codec(index = 2)] - ReasonTooBig, - #[codec(index = 3)] - UnexpectedStatus, - #[codec(index = 4)] - RequireCurator, - #[codec(index = 5)] - InvalidValue, - #[codec(index = 6)] - InvalidFee, - #[codec(index = 7)] - PendingPayout, - #[codec(index = 8)] - Premature, - #[codec(index = 9)] - HasActiveChildBounty, - #[codec(index = 10)] - TooManyQueued, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BountyProposed { index: ::core::primitive::u32 }, - #[codec(index = 1)] - BountyRejected { index: ::core::primitive::u32, bond: ::core::primitive::u128 }, - #[codec(index = 2)] - BountyBecameActive { index: ::core::primitive::u32 }, - #[codec(index = 3)] - BountyAwarded { - index: ::core::primitive::u32, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 4)] - BountyClaimed { - index: ::core::primitive::u32, - payout: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 5)] - BountyCanceled { index: ::core::primitive::u32 }, - #[codec(index = 6)] - BountyExtended { index: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bounty<_0, _1, _2> { - pub proposer: _0, - pub value: _1, - pub fee: _1, - pub curator_deposit: _1, - pub bond: _1, - pub status: runtime_types::pallet_bounties::BountyStatus<_0, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BountyStatus<_0, _1> { - #[codec(index = 0)] - Proposed, - #[codec(index = 1)] - Approved, - #[codec(index = 2)] - Funded, - #[codec(index = 3)] - CuratorProposed { curator: _0 }, - #[codec(index = 4)] - Active { curator: _0, update_due: _1 }, - #[codec(index = 5)] - PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, - } - } - pub mod pallet_child_bounties { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - value: ::core::primitive::u128, - description: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - propose_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 2)] - accept_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 3)] - unassign_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 4)] - award_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - claim_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 6)] - close_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParentBountyNotActive, - #[codec(index = 1)] - InsufficientBountyBalance, - #[codec(index = 2)] - TooManyChildBounties, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Added { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, - #[codec(index = 1)] - Awarded { - index: ::core::primitive::u32, - child_index: ::core::primitive::u32, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 2)] - Claimed { - index: ::core::primitive::u32, - child_index: ::core::primitive::u32, - payout: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Canceled { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChildBounty<_0, _1, _2> { - pub parent_bounty: _2, - pub value: _1, - pub fee: _1, - pub curator_deposit: _1, - pub status: runtime_types::pallet_child_bounties::ChildBountyStatus<_0, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ChildBountyStatus<_0, _1> { - #[codec(index = 0)] - Added, - #[codec(index = 1)] - CuratorProposed { curator: _0 }, - #[codec(index = 2)] - Active { curator: _0 }, - #[codec(index = 3)] - PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, - } - } - pub mod pallet_collective { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_members { - new_members: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - prime: ::core::option::Option<::sp_core::crypto::AccountId32>, - old_count: ::core::primitive::u32, - }, - #[codec(index = 1)] - execute { - proposal: ::std::boxed::Box, - #[codec(compact)] - length_bound: ::core::primitive::u32, - }, - #[codec(index = 2)] - propose { - #[codec(compact)] - threshold: ::core::primitive::u32, - proposal: ::std::boxed::Box, - #[codec(compact)] - length_bound: ::core::primitive::u32, - }, - #[codec(index = 3)] - vote { - proposal: ::subxt::utils::H256, - #[codec(compact)] - index: ::core::primitive::u32, - approve: ::core::primitive::bool, - }, - #[codec(index = 5)] - disapprove_proposal { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 6)] - close { - proposal_hash: ::subxt::utils::H256, - #[codec(compact)] - index: ::core::primitive::u32, - proposal_weight_bound: ::sp_weights::Weight, - #[codec(compact)] - length_bound: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotMember, - #[codec(index = 1)] - DuplicateProposal, - #[codec(index = 2)] - ProposalMissing, - #[codec(index = 3)] - WrongIndex, - #[codec(index = 4)] - DuplicateVote, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooEarly, - #[codec(index = 7)] - TooManyProposals, - #[codec(index = 8)] - WrongProposalWeight, - #[codec(index = 9)] - WrongProposalLength, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { - account: ::sp_core::crypto::AccountId32, - proposal_index: ::core::primitive::u32, - proposal_hash: ::subxt::utils::H256, - threshold: ::core::primitive::u32, - }, - #[codec(index = 1)] - Voted { - account: ::sp_core::crypto::AccountId32, - proposal_hash: ::subxt::utils::H256, - voted: ::core::primitive::bool, - yes: ::core::primitive::u32, - no: ::core::primitive::u32, - }, - #[codec(index = 2)] - Approved { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 3)] - Disapproved { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - Executed { - proposal_hash: ::subxt::utils::H256, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 5)] - MemberExecuted { - proposal_hash: ::subxt::utils::H256, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 6)] - Closed { - proposal_hash: ::subxt::utils::H256, - yes: ::core::primitive::u32, - no: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Members(::core::primitive::u32, ::core::primitive::u32), - #[codec(index = 1)] - Member(_0), - #[codec(index = 2)] - _Phantom, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Votes<_0, _1> { - pub index: _1, - pub threshold: _1, - pub ayes: ::std::vec::Vec<_0>, - pub nays: ::std::vec::Vec<_0>, - pub end: _1, - } - } - pub mod pallet_conviction_voting { - use super::runtime_types; - pub mod conviction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Conviction { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Locked1x, - #[codec(index = 2)] - Locked2x, - #[codec(index = 3)] - Locked3x, - #[codec(index = 4)] - Locked4x, - #[codec(index = 5)] - Locked5x, - #[codec(index = 6)] - Locked6x, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vote { - #[codec(compact)] - poll_index: ::core::primitive::u32, - vote: runtime_types::pallet_conviction_voting::vote::AccountVote< - ::core::primitive::u128, - >, - }, - #[codec(index = 1)] - delegate { - class: ::core::primitive::u16, - to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, - balance: ::core::primitive::u128, - }, - #[codec(index = 2)] - undelegate { class: ::core::primitive::u16 }, - #[codec(index = 3)] - unlock { - class: ::core::primitive::u16, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - remove_vote { - class: ::core::option::Option<::core::primitive::u16>, - index: ::core::primitive::u32, - }, - #[codec(index = 5)] - remove_other_vote { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - class: ::core::primitive::u16, - index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotOngoing, - #[codec(index = 1)] - NotVoter, - #[codec(index = 2)] - NoPermission, - #[codec(index = 3)] - NoPermissionYet, - #[codec(index = 4)] - AlreadyDelegating, - #[codec(index = 5)] - AlreadyVoting, - #[codec(index = 6)] - InsufficientFunds, - #[codec(index = 7)] - NotDelegating, - #[codec(index = 8)] - Nonsense, - #[codec(index = 9)] - MaxVotesReached, - #[codec(index = 10)] - ClassNeeded, - #[codec(index = 11)] - BadClass, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Delegated(::sp_core::crypto::AccountId32, ::sp_core::crypto::AccountId32), - #[codec(index = 1)] - Undelegated(::sp_core::crypto::AccountId32), - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Delegations<_0> { - pub votes: _0, - pub capital: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Tally<_0> { - pub ayes: _0, - pub nays: _0, - pub support: _0, - } - } - pub mod vote { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AccountVote<_0> { - #[codec(index = 0)] - Standard { - vote: runtime_types::pallet_conviction_voting::vote::Vote, - balance: _0, - }, - #[codec(index = 1)] - Split { aye: _0, nay: _0 }, - #[codec(index = 2)] - SplitAbstain { aye: _0, nay: _0, abstain: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Casting<_0, _1, _2> { - pub votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _1, - runtime_types::pallet_conviction_voting::vote::AccountVote<_0>, - )>, - pub delegations: - runtime_types::pallet_conviction_voting::types::Delegations<_0>, - pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_1, _0>, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Delegating<_0, _1, _2> { - pub balance: _0, - pub target: _1, - pub conviction: runtime_types::pallet_conviction_voting::conviction::Conviction, - pub delegations: - runtime_types::pallet_conviction_voting::types::Delegations<_0>, - pub prior: runtime_types::pallet_conviction_voting::vote::PriorLock<_2, _0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PriorLock<_0, _1>(pub _0, pub _1); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Vote(pub ::core::primitive::u8); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Voting<_0, _1, _2, _3> { - #[codec(index = 0)] - Casting(runtime_types::pallet_conviction_voting::vote::Casting<_0, _2, _2>), - #[codec(index = 1)] - Delegating( - runtime_types::pallet_conviction_voting::vote::Delegating<_0, _1, _2>, - ), - __Ignore(::core::marker::PhantomData<_3>), - } - } - } - pub mod pallet_democracy { - use super::runtime_types; - pub mod conviction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Conviction { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Locked1x, - #[codec(index = 2)] - Locked2x, - #[codec(index = 3)] - Locked3x, - #[codec(index = 4)] - Locked4x, - #[codec(index = 5)] - Locked5x, - #[codec(index = 6)] - Locked6x, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - second { - #[codec(compact)] - proposal: ::core::primitive::u32, - }, - #[codec(index = 2)] - vote { - #[codec(compact)] - ref_index: ::core::primitive::u32, - vote: runtime_types::pallet_democracy::vote::AccountVote< - ::core::primitive::u128, - >, - }, - #[codec(index = 3)] - emergency_cancel { ref_index: ::core::primitive::u32 }, - #[codec(index = 4)] - external_propose { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 5)] - external_propose_majority { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 6)] - external_propose_default { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 7)] - fast_track { - proposal_hash: ::subxt::utils::H256, - voting_period: ::core::primitive::u32, - delay: ::core::primitive::u32, - }, - #[codec(index = 8)] - veto_external { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 9)] - cancel_referendum { - #[codec(compact)] - ref_index: ::core::primitive::u32, - }, - #[codec(index = 10)] - delegate { - to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - conviction: runtime_types::pallet_democracy::conviction::Conviction, - balance: ::core::primitive::u128, - }, - #[codec(index = 11)] - undelegate, - #[codec(index = 12)] - clear_public_proposals, - #[codec(index = 13)] - unlock { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 14)] - remove_vote { index: ::core::primitive::u32 }, - #[codec(index = 15)] - remove_other_vote { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - }, - #[codec(index = 16)] - blacklist { - proposal_hash: ::subxt::utils::H256, - maybe_ref_index: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 17)] - cancel_proposal { - #[codec(compact)] - prop_index: ::core::primitive::u32, - }, - #[codec(index = 18)] - set_metadata { - owner: runtime_types::pallet_democracy::types::MetadataOwner, - maybe_hash: ::core::option::Option<::subxt::utils::H256>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ValueLow, - #[codec(index = 1)] - ProposalMissing, - #[codec(index = 2)] - AlreadyCanceled, - #[codec(index = 3)] - DuplicateProposal, - #[codec(index = 4)] - ProposalBlacklisted, - #[codec(index = 5)] - NotSimpleMajority, - #[codec(index = 6)] - InvalidHash, - #[codec(index = 7)] - NoProposal, - #[codec(index = 8)] - AlreadyVetoed, - #[codec(index = 9)] - ReferendumInvalid, - #[codec(index = 10)] - NoneWaiting, - #[codec(index = 11)] - NotVoter, - #[codec(index = 12)] - NoPermission, - #[codec(index = 13)] - AlreadyDelegating, - #[codec(index = 14)] - InsufficientFunds, - #[codec(index = 15)] - NotDelegating, - #[codec(index = 16)] - VotesExist, - #[codec(index = 17)] - InstantNotAllowed, - #[codec(index = 18)] - Nonsense, - #[codec(index = 19)] - WrongUpperBound, - #[codec(index = 20)] - MaxVotesReached, - #[codec(index = 21)] - TooMany, - #[codec(index = 22)] - VotingPeriodLow, - #[codec(index = 23)] - PreimageNotExist, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { - proposal_index: ::core::primitive::u32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 1)] - Tabled { - proposal_index: ::core::primitive::u32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 2)] - ExternalTabled, - #[codec(index = 3)] - Started { - ref_index: ::core::primitive::u32, - threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, - }, - #[codec(index = 4)] - Passed { ref_index: ::core::primitive::u32 }, - #[codec(index = 5)] - NotPassed { ref_index: ::core::primitive::u32 }, - #[codec(index = 6)] - Cancelled { ref_index: ::core::primitive::u32 }, - #[codec(index = 7)] - Delegated { - who: ::sp_core::crypto::AccountId32, - target: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - Undelegated { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 9)] - Vetoed { - who: ::sp_core::crypto::AccountId32, - proposal_hash: ::subxt::utils::H256, - until: ::core::primitive::u32, - }, - #[codec(index = 10)] - Blacklisted { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 11)] - Voted { - voter: ::sp_core::crypto::AccountId32, - ref_index: ::core::primitive::u32, - vote: runtime_types::pallet_democracy::vote::AccountVote< - ::core::primitive::u128, - >, - }, - #[codec(index = 12)] - Seconded { - seconder: ::sp_core::crypto::AccountId32, - prop_index: ::core::primitive::u32, - }, - #[codec(index = 13)] - ProposalCanceled { prop_index: ::core::primitive::u32 }, - #[codec(index = 14)] - MetadataSet { - owner: runtime_types::pallet_democracy::types::MetadataOwner, - hash: ::subxt::utils::H256, - }, - #[codec(index = 15)] - MetadataCleared { - owner: runtime_types::pallet_democracy::types::MetadataOwner, - hash: ::subxt::utils::H256, - }, - #[codec(index = 16)] - MetadataTransferred { - prev_owner: runtime_types::pallet_democracy::types::MetadataOwner, - owner: runtime_types::pallet_democracy::types::MetadataOwner, - hash: ::subxt::utils::H256, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Delegations<_0> { - pub votes: _0, - pub capital: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MetadataOwner { - #[codec(index = 0)] - External, - #[codec(index = 1)] - Proposal(::core::primitive::u32), - #[codec(index = 2)] - Referendum(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReferendumInfo<_0, _1, _2> { - #[codec(index = 0)] - Ongoing(runtime_types::pallet_democracy::types::ReferendumStatus<_0, _1, _2>), - #[codec(index = 1)] - Finished { approved: ::core::primitive::bool, end: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReferendumStatus<_0, _1, _2> { - pub end: _0, - pub proposal: _1, - pub threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, - pub delay: _0, - pub tally: runtime_types::pallet_democracy::types::Tally<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Tally<_0> { - pub ayes: _0, - pub nays: _0, - pub turnout: _0, - } - } - pub mod vote { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AccountVote<_0> { - #[codec(index = 0)] - Standard { vote: runtime_types::pallet_democracy::vote::Vote, balance: _0 }, - #[codec(index = 1)] - Split { aye: _0, nay: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PriorLock<_0, _1>(pub _0, pub _1); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Vote(pub ::core::primitive::u8); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Voting<_0, _1, _2> { - #[codec(index = 0)] - Direct { - votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _2, - runtime_types::pallet_democracy::vote::AccountVote<_0>, - )>, - delegations: runtime_types::pallet_democracy::types::Delegations<_0>, - prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, - }, - #[codec(index = 1)] - Delegating { - balance: _0, - target: _1, - conviction: runtime_types::pallet_democracy::conviction::Conviction, - delegations: runtime_types::pallet_democracy::types::Delegations<_0>, - prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, - }, - } - } - pub mod vote_threshold { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VoteThreshold { - #[codec(index = 0)] - SuperMajorityApprove, - #[codec(index = 1)] - SuperMajorityAgainst, - #[codec(index = 2)] - SimpleMajority, - } - } - } - pub mod pallet_election_provider_multi_phase { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] submit_unsigned { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: polkadot_runtime :: NposCompactSolution16 > > , witness : runtime_types :: pallet_election_provider_multi_phase :: SolutionOrSnapshotSize , } , # [codec (index = 1)] set_minimum_untrusted_score { maybe_next_score : :: core :: option :: Option < runtime_types :: sp_npos_elections :: ElectionScore > , } , # [codec (index = 2)] set_emergency_election_result { supports : :: std :: vec :: Vec < (:: sp_core :: crypto :: AccountId32 , runtime_types :: sp_npos_elections :: Support < :: sp_core :: crypto :: AccountId32 > ,) > , } , # [codec (index = 3)] submit { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: polkadot_runtime :: NposCompactSolution16 > > , } , # [codec (index = 4)] governance_fallback { maybe_max_voters : :: core :: option :: Option < :: core :: primitive :: u32 > , maybe_max_targets : :: core :: option :: Option < :: core :: primitive :: u32 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PreDispatchEarlySubmission, - #[codec(index = 1)] - PreDispatchWrongWinnerCount, - #[codec(index = 2)] - PreDispatchWeakSubmission, - #[codec(index = 3)] - SignedQueueFull, - #[codec(index = 4)] - SignedCannotPayDeposit, - #[codec(index = 5)] - SignedInvalidWitness, - #[codec(index = 6)] - SignedTooMuchWeight, - #[codec(index = 7)] - OcwCallWrongEra, - #[codec(index = 8)] - MissingSnapshotMetadata, - #[codec(index = 9)] - InvalidSubmissionIndex, - #[codec(index = 10)] - CallNotAllowed, - #[codec(index = 11)] - FallbackFailed, - #[codec(index = 12)] - BoundNotMet, - #[codec(index = 13)] - TooManyWinners, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - SolutionStored { - compute: - runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - origin: ::core::option::Option<::sp_core::crypto::AccountId32>, - prev_ejected: ::core::primitive::bool, - }, - #[codec(index = 1)] - ElectionFinalized { - compute: - runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - score: runtime_types::sp_npos_elections::ElectionScore, - }, - #[codec(index = 2)] - ElectionFailed, - #[codec(index = 3)] - Rewarded { - account: ::sp_core::crypto::AccountId32, - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - Slashed { - account: ::sp_core::crypto::AccountId32, - value: ::core::primitive::u128, - }, - #[codec(index = 5)] - PhaseTransitioned { - from: runtime_types::pallet_election_provider_multi_phase::Phase< - ::core::primitive::u32, - >, - to: runtime_types::pallet_election_provider_multi_phase::Phase< - ::core::primitive::u32, - >, - round: ::core::primitive::u32, - }, - } - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedSubmission<_0, _1, _2> { - pub who: _0, - pub deposit: _1, - pub raw_solution: - runtime_types::pallet_election_provider_multi_phase::RawSolution<_2>, - pub call_fee: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ElectionCompute { - #[codec(index = 0)] - OnChain, - #[codec(index = 1)] - Signed, - #[codec(index = 2)] - Unsigned, - #[codec(index = 3)] - Fallback, - #[codec(index = 4)] - Emergency, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase<_0> { - #[codec(index = 0)] - Off, - #[codec(index = 1)] - Signed, - #[codec(index = 2)] - Unsigned((::core::primitive::bool, _0)), - #[codec(index = 3)] - Emergency, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RawSolution<_0> { - pub solution: _0, - pub score: runtime_types::sp_npos_elections::ElectionScore, - pub round: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReadySolution { - pub supports: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::sp_core::crypto::AccountId32, - runtime_types::sp_npos_elections::Support<::sp_core::crypto::AccountId32>, - )>, - pub score: runtime_types::sp_npos_elections::ElectionScore, - pub compute: runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RoundSnapshot<_0, _1> { - pub voters: ::std::vec::Vec<_1>, - pub targets: ::std::vec::Vec<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SolutionOrSnapshotSize { - #[codec(compact)] - pub voters: ::core::primitive::u32, - #[codec(compact)] - pub targets: ::core::primitive::u32, - } - } - pub mod pallet_elections_phragmen { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vote { - votes: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - remove_voter, - #[codec(index = 2)] - submit_candidacy { - #[codec(compact)] - candidate_count: ::core::primitive::u32, - }, - #[codec(index = 3)] - renounce_candidacy { - renouncing: runtime_types::pallet_elections_phragmen::Renouncing, - }, - #[codec(index = 4)] - remove_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - slash_bond: ::core::primitive::bool, - rerun_election: ::core::primitive::bool, - }, - #[codec(index = 5)] - clean_defunct_voters { - num_voters: ::core::primitive::u32, - num_defunct: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnableToVote, - #[codec(index = 1)] - NoVotes, - #[codec(index = 2)] - TooManyVotes, - #[codec(index = 3)] - MaximumVotesExceeded, - #[codec(index = 4)] - LowBalance, - #[codec(index = 5)] - UnableToPayBond, - #[codec(index = 6)] - MustBeVoter, - #[codec(index = 7)] - DuplicatedCandidate, - #[codec(index = 8)] - TooManyCandidates, - #[codec(index = 9)] - MemberSubmit, - #[codec(index = 10)] - RunnerUpSubmit, - #[codec(index = 11)] - InsufficientCandidateFunds, - #[codec(index = 12)] - NotMember, - #[codec(index = 13)] - InvalidWitnessData, - #[codec(index = 14)] - InvalidVoteCount, - #[codec(index = 15)] - InvalidRenouncing, - #[codec(index = 16)] - InvalidReplacement, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewTerm { - new_members: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - )>, - }, - #[codec(index = 1)] - EmptyTerm, - #[codec(index = 2)] - ElectionError, - #[codec(index = 3)] - MemberKicked { member: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - Renounced { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - CandidateSlashed { - candidate: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - SeatHolderSlashed { - seat_holder: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Renouncing { - #[codec(index = 0)] - Member, - #[codec(index = 1)] - RunnerUp, - #[codec(index = 2)] - Candidate(#[codec(compact)] ::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SeatHolder<_0, _1> { - pub who: _0, - pub stake: _1, - pub deposit: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Voter<_0, _1> { - pub votes: ::std::vec::Vec<_0>, - pub stake: _1, - pub deposit: _1, - } - } - pub mod pallet_fast_unstake { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register_fast_unstake, - #[codec(index = 1)] - deregister, - #[codec(index = 2)] - control { eras_to_check: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotController, - #[codec(index = 1)] - AlreadyQueued, - #[codec(index = 2)] - NotFullyBonded, - #[codec(index = 3)] - NotQueued, - #[codec(index = 4)] - AlreadyHead, - #[codec(index = 5)] - CallNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Unstaked { - stash: ::sp_core::crypto::AccountId32, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - Slashed { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - InternalError, - #[codec(index = 3)] - BatchChecked { eras: ::std::vec::Vec<::core::primitive::u32> }, - #[codec(index = 4)] - BatchFinished { size: ::core::primitive::u32 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnstakeRequest { - pub stashes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - )>, - pub checked: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u32, - >, - } - } - } - pub mod pallet_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - note_stalled { - delay: ::core::primitive::u32, - best_finalized_block_number: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PauseFailed, - #[codec(index = 1)] - ResumeFailed, - #[codec(index = 2)] - ChangePending, - #[codec(index = 3)] - TooSoon, - #[codec(index = 4)] - InvalidKeyOwnershipProof, - #[codec(index = 5)] - InvalidEquivocationProof, - #[codec(index = 6)] - DuplicateOffenceReport, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewAuthorities { - authority_set: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - }, - #[codec(index = 1)] - Paused, - #[codec(index = 2)] - Resumed, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredPendingChange<_0> { - pub scheduled_at: _0, - pub delay: _0, - pub next_authorities: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub forced: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StoredState<_0> { - #[codec(index = 0)] - Live, - #[codec(index = 1)] - PendingPause { scheduled_at: _0, delay: _0 }, - #[codec(index = 2)] - Paused, - #[codec(index = 3)] - PendingResume { scheduled_at: _0, delay: _0 }, - } - } - pub mod pallet_identity { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_registrar { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - set_identity { - info: - ::std::boxed::Box, - }, - #[codec(index = 2)] - set_subs { - subs: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_identity::types::Data, - )>, - }, - #[codec(index = 3)] - clear_identity, - #[codec(index = 4)] - request_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - #[codec(compact)] - max_fee: ::core::primitive::u128, - }, - #[codec(index = 5)] - cancel_request { reg_index: ::core::primitive::u32 }, - #[codec(index = 6)] - set_fee { - #[codec(compact)] - index: ::core::primitive::u32, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 7)] - set_account_id { - #[codec(compact)] - index: ::core::primitive::u32, - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 8)] - set_fields { - #[codec(compact)] - index: ::core::primitive::u32, - fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - }, - #[codec(index = 9)] - provide_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - judgement: runtime_types::pallet_identity::types::Judgement< - ::core::primitive::u128, - >, - identity: ::subxt::utils::H256, - }, - #[codec(index = 10)] - kill_identity { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 11)] - add_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 12)] - rename_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 13)] - remove_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 14)] - quit_sub, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManySubAccounts, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotNamed, - #[codec(index = 3)] - EmptyIndex, - #[codec(index = 4)] - FeeChanged, - #[codec(index = 5)] - NoIdentity, - #[codec(index = 6)] - StickyJudgement, - #[codec(index = 7)] - JudgementGiven, - #[codec(index = 8)] - InvalidJudgement, - #[codec(index = 9)] - InvalidIndex, - #[codec(index = 10)] - InvalidTarget, - #[codec(index = 11)] - TooManyFields, - #[codec(index = 12)] - TooManyRegistrars, - #[codec(index = 13)] - AlreadyClaimed, - #[codec(index = 14)] - NotSub, - #[codec(index = 15)] - NotOwned, - #[codec(index = 16)] - JudgementForDifferentIdentity, - #[codec(index = 17)] - JudgementPaymentFailed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IdentitySet { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - IdentityCleared { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 2)] - IdentityKilled { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 3)] - JudgementRequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 4)] - JudgementUnrequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 5)] - JudgementGiven { - target: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - RegistrarAdded { registrar_index: ::core::primitive::u32 }, - #[codec(index = 7)] - SubIdentityAdded { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 8)] - SubIdentityRemoved { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 9)] - SubIdentityRevoked { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct BitFlags<_0>( - pub ::core::primitive::u64, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Data { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Raw0([::core::primitive::u8; 0usize]), - #[codec(index = 2)] - Raw1([::core::primitive::u8; 1usize]), - #[codec(index = 3)] - Raw2([::core::primitive::u8; 2usize]), - #[codec(index = 4)] - Raw3([::core::primitive::u8; 3usize]), - #[codec(index = 5)] - Raw4([::core::primitive::u8; 4usize]), - #[codec(index = 6)] - Raw5([::core::primitive::u8; 5usize]), - #[codec(index = 7)] - Raw6([::core::primitive::u8; 6usize]), - #[codec(index = 8)] - Raw7([::core::primitive::u8; 7usize]), - #[codec(index = 9)] - Raw8([::core::primitive::u8; 8usize]), - #[codec(index = 10)] - Raw9([::core::primitive::u8; 9usize]), - #[codec(index = 11)] - Raw10([::core::primitive::u8; 10usize]), - #[codec(index = 12)] - Raw11([::core::primitive::u8; 11usize]), - #[codec(index = 13)] - Raw12([::core::primitive::u8; 12usize]), - #[codec(index = 14)] - Raw13([::core::primitive::u8; 13usize]), - #[codec(index = 15)] - Raw14([::core::primitive::u8; 14usize]), - #[codec(index = 16)] - Raw15([::core::primitive::u8; 15usize]), - #[codec(index = 17)] - Raw16([::core::primitive::u8; 16usize]), - #[codec(index = 18)] - Raw17([::core::primitive::u8; 17usize]), - #[codec(index = 19)] - Raw18([::core::primitive::u8; 18usize]), - #[codec(index = 20)] - Raw19([::core::primitive::u8; 19usize]), - #[codec(index = 21)] - Raw20([::core::primitive::u8; 20usize]), - #[codec(index = 22)] - Raw21([::core::primitive::u8; 21usize]), - #[codec(index = 23)] - Raw22([::core::primitive::u8; 22usize]), - #[codec(index = 24)] - Raw23([::core::primitive::u8; 23usize]), - #[codec(index = 25)] - Raw24([::core::primitive::u8; 24usize]), - #[codec(index = 26)] - Raw25([::core::primitive::u8; 25usize]), - #[codec(index = 27)] - Raw26([::core::primitive::u8; 26usize]), - #[codec(index = 28)] - Raw27([::core::primitive::u8; 27usize]), - #[codec(index = 29)] - Raw28([::core::primitive::u8; 28usize]), - #[codec(index = 30)] - Raw29([::core::primitive::u8; 29usize]), - #[codec(index = 31)] - Raw30([::core::primitive::u8; 30usize]), - #[codec(index = 32)] - Raw31([::core::primitive::u8; 31usize]), - #[codec(index = 33)] - Raw32([::core::primitive::u8; 32usize]), - #[codec(index = 34)] - BlakeTwo256([::core::primitive::u8; 32usize]), - #[codec(index = 35)] - Sha256([::core::primitive::u8; 32usize]), - #[codec(index = 36)] - Keccak256([::core::primitive::u8; 32usize]), - #[codec(index = 37)] - ShaThree256([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum IdentityField { - #[codec(index = 1)] - Display, - #[codec(index = 2)] - Legal, - #[codec(index = 4)] - Web, - #[codec(index = 8)] - Riot, - #[codec(index = 16)] - Email, - #[codec(index = 32)] - PgpFingerprint, - #[codec(index = 64)] - Image, - #[codec(index = 128)] - Twitter, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdentityInfo { - pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::pallet_identity::types::Data, - runtime_types::pallet_identity::types::Data, - )>, - pub display: runtime_types::pallet_identity::types::Data, - pub legal: runtime_types::pallet_identity::types::Data, - pub web: runtime_types::pallet_identity::types::Data, - pub riot: runtime_types::pallet_identity::types::Data, - pub email: runtime_types::pallet_identity::types::Data, - pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, - pub image: runtime_types::pallet_identity::types::Data, - pub twitter: runtime_types::pallet_identity::types::Data, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Judgement<_0> { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - FeePaid(_0), - #[codec(index = 2)] - Reasonable, - #[codec(index = 3)] - KnownGood, - #[codec(index = 4)] - OutOfDate, - #[codec(index = 5)] - LowQuality, - #[codec(index = 6)] - Erroneous, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RegistrarInfo<_0, _1> { - pub account: _1, - pub fee: _0, - pub fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0> { - pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::core::primitive::u32, - runtime_types::pallet_identity::types::Judgement<_0>, - )>, - pub deposit: _0, - pub info: runtime_types::pallet_identity::types::IdentityInfo, - } - } - } - pub mod pallet_im_online { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - heartbeat { - heartbeat: - runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, - signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidKey, - #[codec(index = 1)] - DuplicatedHeartbeat, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - HeartbeatReceived { - authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - }, - #[codec(index = 1)] - AllGood, - #[codec(index = 2)] - SomeOffline { - offline: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_staking::Exposure< - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - >, - )>, - }, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedOpaqueNetworkState { - pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - pub external_addresses: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Heartbeat<_0> { - pub block_number: _0, - pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, - pub session_index: _0, - pub authority_index: _0, - pub validators_len: _0, - } - } - pub mod pallet_indices { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { index: ::core::primitive::u32 }, - #[codec(index = 1)] - transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - }, - #[codec(index = 2)] - free { index: ::core::primitive::u32 }, - #[codec(index = 3)] - force_transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - freeze: ::core::primitive::bool, - }, - #[codec(index = 4)] - freeze { index: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAssigned, - #[codec(index = 1)] - NotOwner, - #[codec(index = 2)] - InUse, - #[codec(index = 3)] - NotTransfer, - #[codec(index = 4)] - Permanent, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IndexAssigned { - who: ::sp_core::crypto::AccountId32, - index: ::core::primitive::u32, - }, - #[codec(index = 1)] - IndexFreed { index: ::core::primitive::u32 }, - #[codec(index = 2)] - IndexFrozen { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - }, - } - } - } - pub mod pallet_membership { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - remove_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - swap_member { - remove: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - add: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - reset_members { members: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 4)] - change_key { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - set_prime { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - clear_prime, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AlreadyMember, - #[codec(index = 1)] - NotMember, - #[codec(index = 2)] - TooManyMembers, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - MemberAdded, - #[codec(index = 1)] - MemberRemoved, - #[codec(index = 2)] - MembersSwapped, - #[codec(index = 3)] - MembersReset, - #[codec(index = 4)] - KeyChanged, - #[codec(index = 5)] - Dummy, - } - } - } - pub mod pallet_message_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotReapable, - #[codec(index = 1)] - NoPage, - #[codec(index = 2)] - NoMessage, - #[codec(index = 3)] - AlreadyProcessed, - #[codec(index = 4)] - Queued, - #[codec(index = 5)] - InsufficientWeight, - #[codec(index = 6)] - TemporarilyUnprocessable, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BookState<_0> { - pub begin: ::core::primitive::u32, - pub end: ::core::primitive::u32, - pub count: ::core::primitive::u32, - pub ready_neighbours: - ::core::option::Option>, - pub message_count: ::core::primitive::u64, - pub size: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Neighbours<_0> { - pub prev: _0, - pub next: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Page<_0> { - pub remaining: _0, - pub remaining_size: _0, - pub first_index: _0, - pub first: _0, - pub last: _0, - pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: _0, - } - } - pub mod pallet_nomination_pools { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - join { - #[codec(compact)] - amount: ::core::primitive::u128, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 1)] - bond_extra { - extra: runtime_types::pallet_nomination_pools::BondExtra< - ::core::primitive::u128, - >, - }, - #[codec(index = 2)] - claim_payout, - #[codec(index = 3)] - unbond { - member_account: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - unbonding_points: ::core::primitive::u128, - }, - #[codec(index = 4)] - pool_withdraw_unbonded { - pool_id: ::core::primitive::u32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 5)] - withdraw_unbonded { - member_account: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 6)] - create { - #[codec(compact)] - amount: ::core::primitive::u128, - root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 7)] - create_with_pool_id { - #[codec(compact)] - amount: ::core::primitive::u128, - root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 8)] - nominate { - pool_id: ::core::primitive::u32, - validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 9)] - set_state { - pool_id: ::core::primitive::u32, - state: runtime_types::pallet_nomination_pools::PoolState, - }, - #[codec(index = 10)] - set_metadata { - pool_id: ::core::primitive::u32, - metadata: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 11)] - set_configs { - min_join_bond: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u128, - >, - min_create_bond: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u128, - >, - max_pools: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - max_members: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - max_members_per_pool: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - global_max_commission: runtime_types::pallet_nomination_pools::ConfigOp< - runtime_types::sp_arithmetic::per_things::Perbill, - >, - }, - #[codec(index = 12)] - update_roles { - pool_id: ::core::primitive::u32, - new_root: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - new_nominator: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - new_bouncer: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 13)] - chill { pool_id: ::core::primitive::u32 }, - #[codec(index = 14)] - bond_extra_other { - member: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - extra: runtime_types::pallet_nomination_pools::BondExtra< - ::core::primitive::u128, - >, - }, - #[codec(index = 15)] - set_claim_permission { - permission: runtime_types::pallet_nomination_pools::ClaimPermission, - }, - #[codec(index = 16)] - claim_payout_other { other: ::sp_core::crypto::AccountId32 }, - #[codec(index = 17)] - set_commission { - pool_id: ::core::primitive::u32, - new_commission: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - }, - #[codec(index = 18)] - set_commission_max { - pool_id: ::core::primitive::u32, - max_commission: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 19)] - set_commission_change_rate { - pool_id: ::core::primitive::u32, - change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - }, - #[codec(index = 20)] - claim_commission { pool_id: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DefensiveError { - #[codec(index = 0)] - NotEnoughSpaceInUnbondPool, - #[codec(index = 1)] - PoolNotFound, - #[codec(index = 2)] - RewardPoolNotFound, - #[codec(index = 3)] - SubPoolsNotFound, - #[codec(index = 4)] - BondedStashKilledPrematurely, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PoolNotFound, - #[codec(index = 1)] - PoolMemberNotFound, - #[codec(index = 2)] - RewardPoolNotFound, - #[codec(index = 3)] - SubPoolsNotFound, - #[codec(index = 4)] - AccountBelongsToOtherPool, - #[codec(index = 5)] - FullyUnbonding, - #[codec(index = 6)] - MaxUnbondingLimit, - #[codec(index = 7)] - CannotWithdrawAny, - #[codec(index = 8)] - MinimumBondNotMet, - #[codec(index = 9)] - OverflowRisk, - #[codec(index = 10)] - NotDestroying, - #[codec(index = 11)] - NotNominator, - #[codec(index = 12)] - NotKickerOrDestroying, - #[codec(index = 13)] - NotOpen, - #[codec(index = 14)] - MaxPools, - #[codec(index = 15)] - MaxPoolMembers, - #[codec(index = 16)] - CanNotChangeState, - #[codec(index = 17)] - DoesNotHavePermission, - #[codec(index = 18)] - MetadataExceedsMaxLen, - #[codec(index = 19)] - Defensive(runtime_types::pallet_nomination_pools::pallet::DefensiveError), - #[codec(index = 20)] - PartialUnbondNotAllowedPermissionlessly, - #[codec(index = 21)] - MaxCommissionRestricted, - #[codec(index = 22)] - CommissionExceedsMaximum, - #[codec(index = 23)] - CommissionChangeThrottled, - #[codec(index = 24)] - CommissionChangeRateNotAllowed, - #[codec(index = 25)] - NoPendingCommission, - #[codec(index = 26)] - NoCommissionCurrentSet, - #[codec(index = 27)] - PoolIdInUse, - #[codec(index = 28)] - InvalidPoolId, - #[codec(index = 29)] - BondExtraRestricted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { - depositor: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 1)] - Bonded { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - bonded: ::core::primitive::u128, - joined: ::core::primitive::bool, - }, - #[codec(index = 2)] - PaidOut { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - payout: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unbonded { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - points: ::core::primitive::u128, - era: ::core::primitive::u32, - }, - #[codec(index = 4)] - Withdrawn { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - points: ::core::primitive::u128, - }, - #[codec(index = 5)] - Destroyed { pool_id: ::core::primitive::u32 }, - #[codec(index = 6)] - StateChanged { - pool_id: ::core::primitive::u32, - new_state: runtime_types::pallet_nomination_pools::PoolState, - }, - #[codec(index = 7)] - MemberRemoved { - pool_id: ::core::primitive::u32, - member: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - RolesUpdated { - root: ::core::option::Option<::sp_core::crypto::AccountId32>, - bouncer: ::core::option::Option<::sp_core::crypto::AccountId32>, - nominator: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 9)] - PoolSlashed { - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - }, - #[codec(index = 10)] - UnbondingPoolSlashed { - pool_id: ::core::primitive::u32, - era: ::core::primitive::u32, - balance: ::core::primitive::u128, - }, - #[codec(index = 11)] - PoolCommissionUpdated { - pool_id: ::core::primitive::u32, - current: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - }, - #[codec(index = 12)] - PoolMaxCommissionUpdated { - pool_id: ::core::primitive::u32, - max_commission: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 13)] - PoolCommissionChangeRateUpdated { - pool_id: ::core::primitive::u32, - change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - }, - #[codec(index = 14)] - PoolCommissionClaimed { - pool_id: ::core::primitive::u32, - commission: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BondExtra<_0> { - #[codec(index = 0)] - FreeBalance(_0), - #[codec(index = 1)] - Rewards, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BondedPoolInner { - pub commission: runtime_types::pallet_nomination_pools::Commission, - pub member_counter: ::core::primitive::u32, - pub points: ::core::primitive::u128, - pub roles: runtime_types::pallet_nomination_pools::PoolRoles< - ::sp_core::crypto::AccountId32, - >, - pub state: runtime_types::pallet_nomination_pools::PoolState, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ClaimPermission { - #[codec(index = 0)] - Permissioned, - #[codec(index = 1)] - PermissionlessCompound, - #[codec(index = 2)] - PermissionlessWithdraw, - #[codec(index = 3)] - PermissionlessAll, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commission { - pub current: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - pub max: ::core::option::Option, - pub change_rate: ::core::option::Option< - runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - >, - pub throttle_from: ::core::option::Option<::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommissionChangeRate<_0> { - pub max_increase: runtime_types::sp_arithmetic::per_things::Perbill, - pub min_delay: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConfigOp<_0> { - #[codec(index = 0)] - Noop, - #[codec(index = 1)] - Set(_0), - #[codec(index = 2)] - Remove, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PoolMember { - pub pool_id: ::core::primitive::u32, - pub points: ::core::primitive::u128, - pub last_recorded_reward_counter: - runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub unbonding_eras: - runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< - ::core::primitive::u32, - ::core::primitive::u128, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PoolRoles<_0> { - pub depositor: _0, - pub root: ::core::option::Option<_0>, - pub nominator: ::core::option::Option<_0>, - pub bouncer: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PoolState { - #[codec(index = 0)] - Open, - #[codec(index = 1)] - Blocked, - #[codec(index = 2)] - Destroying, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardPool { - pub last_recorded_reward_counter: - runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub last_recorded_total_payouts: ::core::primitive::u128, - pub total_rewards_claimed: ::core::primitive::u128, - pub total_commission_pending: ::core::primitive::u128, - pub total_commission_claimed: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SubPools { - pub no_era: runtime_types::pallet_nomination_pools::UnbondPool, - pub with_era: - runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< - ::core::primitive::u32, - runtime_types::pallet_nomination_pools::UnbondPool, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnbondPool { - pub points: ::core::primitive::u128, - pub balance: ::core::primitive::u128, - } - } - pub mod pallet_offences { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Offence { - kind: [::core::primitive::u8; 16usize], - timeslot: ::std::vec::Vec<::core::primitive::u8>, - }, - } - } - } - pub mod pallet_preimage { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - unnote_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - request_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 3)] - unrequest_preimage { hash: ::subxt::utils::H256 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooBig, - #[codec(index = 1)] - AlreadyNoted, - #[codec(index = 2)] - NotAuthorized, - #[codec(index = 3)] - NotNoted, - #[codec(index = 4)] - Requested, - #[codec(index = 5)] - NotRequested, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Noted { hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - Requested { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - Cleared { hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RequestStatus<_0, _1> { - #[codec(index = 0)] - Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, - #[codec(index = 1)] - Requested { - deposit: ::core::option::Option<(_0, _1)>, - count: ::core::primitive::u32, - len: ::core::option::Option<::core::primitive::u32>, - }, - } - } - pub mod pallet_proxy { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - proxy { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - add_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::polkadot_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 2)] - remove_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::polkadot_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 3)] - remove_proxies, - #[codec(index = 4)] - create_pure { - proxy_type: runtime_types::polkadot_runtime::ProxyType, - delay: ::core::primitive::u32, - index: ::core::primitive::u16, - }, - #[codec(index = 5)] - kill_pure { - spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::polkadot_runtime::ProxyType, - index: ::core::primitive::u16, - #[codec(compact)] - height: ::core::primitive::u32, - #[codec(compact)] - ext_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - announce { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 7)] - remove_announcement { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 8)] - reject_announcement { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 9)] - proxy_announced { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooMany, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotProxy, - #[codec(index = 3)] - Unproxyable, - #[codec(index = 4)] - Duplicate, - #[codec(index = 5)] - NoPermission, - #[codec(index = 6)] - Unannounced, - #[codec(index = 7)] - NoSelfProxy, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ProxyExecuted { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - PureCreated { - pure: ::sp_core::crypto::AccountId32, - who: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::polkadot_runtime::ProxyType, - disambiguation_index: ::core::primitive::u16, - }, - #[codec(index = 2)] - Announced { - real: ::sp_core::crypto::AccountId32, - proxy: ::sp_core::crypto::AccountId32, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - ProxyAdded { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::polkadot_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 4)] - ProxyRemoved { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::polkadot_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Announcement<_0, _1, _2> { - pub real: _0, - pub call_hash: _1, - pub height: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ProxyDefinition<_0, _1, _2> { - pub delegate: _0, - pub proxy_type: _1, - pub delay: _2, - } - } - pub mod pallet_referenda { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - submit { - proposal_origin: - ::std::boxed::Box, - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - enactment_moment: - runtime_types::frame_support::traits::schedule::DispatchTime< - ::core::primitive::u32, - >, - }, - #[codec(index = 1)] - place_decision_deposit { index: ::core::primitive::u32 }, - #[codec(index = 2)] - refund_decision_deposit { index: ::core::primitive::u32 }, - #[codec(index = 3)] - cancel { index: ::core::primitive::u32 }, - #[codec(index = 4)] - kill { index: ::core::primitive::u32 }, - #[codec(index = 5)] - nudge_referendum { index: ::core::primitive::u32 }, - #[codec(index = 6)] - one_fewer_deciding { track: ::core::primitive::u16 }, - #[codec(index = 7)] - refund_submission_deposit { index: ::core::primitive::u32 }, - #[codec(index = 8)] - set_metadata { - index: ::core::primitive::u32, - maybe_hash: ::core::option::Option<::subxt::utils::H256>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotOngoing, - #[codec(index = 1)] - HasDeposit, - #[codec(index = 2)] - BadTrack, - #[codec(index = 3)] - Full, - #[codec(index = 4)] - QueueEmpty, - #[codec(index = 5)] - BadReferendum, - #[codec(index = 6)] - NothingToDo, - #[codec(index = 7)] - NoTrack, - #[codec(index = 8)] - Unfinished, - #[codec(index = 9)] - NoPermission, - #[codec(index = 10)] - NoDeposit, - #[codec(index = 11)] - BadStatus, - #[codec(index = 12)] - PreimageNotExist, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Submitted { - index: ::core::primitive::u32, - track: ::core::primitive::u16, - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - }, - #[codec(index = 1)] - DecisionDepositPlaced { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - DecisionDepositRefunded { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - DepositSlashed { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - DecisionStarted { - index: ::core::primitive::u32, - track: ::core::primitive::u16, - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::polkadot_runtime::RuntimeCall, - >, - tally: runtime_types::pallet_conviction_voting::types::Tally< - ::core::primitive::u128, - >, - }, - #[codec(index = 5)] - ConfirmStarted { index: ::core::primitive::u32 }, - #[codec(index = 6)] - ConfirmAborted { index: ::core::primitive::u32 }, - #[codec(index = 7)] - Confirmed { - index: ::core::primitive::u32, - tally: runtime_types::pallet_conviction_voting::types::Tally< - ::core::primitive::u128, - >, - }, - #[codec(index = 8)] - Approved { index: ::core::primitive::u32 }, - #[codec(index = 9)] - Rejected { - index: ::core::primitive::u32, - tally: runtime_types::pallet_conviction_voting::types::Tally< - ::core::primitive::u128, - >, - }, - #[codec(index = 10)] - TimedOut { - index: ::core::primitive::u32, - tally: runtime_types::pallet_conviction_voting::types::Tally< - ::core::primitive::u128, - >, - }, - #[codec(index = 11)] - Cancelled { - index: ::core::primitive::u32, - tally: runtime_types::pallet_conviction_voting::types::Tally< - ::core::primitive::u128, - >, - }, - #[codec(index = 12)] - Killed { - index: ::core::primitive::u32, - tally: runtime_types::pallet_conviction_voting::types::Tally< - ::core::primitive::u128, - >, - }, - #[codec(index = 13)] - SubmissionDepositRefunded { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - MetadataSet { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, - #[codec(index = 15)] - MetadataCleared { index: ::core::primitive::u32, hash: ::subxt::utils::H256 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Curve { - #[codec(index = 0)] - LinearDecreasing { - length: runtime_types::sp_arithmetic::per_things::Perbill, - floor: runtime_types::sp_arithmetic::per_things::Perbill, - ceil: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 1)] - SteppedDecreasing { - begin: runtime_types::sp_arithmetic::per_things::Perbill, - end: runtime_types::sp_arithmetic::per_things::Perbill, - step: runtime_types::sp_arithmetic::per_things::Perbill, - period: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 2)] - Reciprocal { - factor: runtime_types::sp_arithmetic::fixed_point::FixedI64, - x_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, - y_offset: runtime_types::sp_arithmetic::fixed_point::FixedI64, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DecidingStatus<_0> { - pub since: _0, - pub confirming: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Deposit<_0, _1> { - pub who: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReferendumInfo<_0, _1, _2, _3, _4, _5, _6, _7> { - #[codec(index = 0)] - Ongoing( - runtime_types::pallet_referenda::types::ReferendumStatus< - _0, - _1, - _2, - _3, - _4, - _5, - _6, - _7, - >, - ), - #[codec(index = 1)] - Approved( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 2)] - Rejected( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 3)] - Cancelled( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 4)] - TimedOut( - _2, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - ), - #[codec(index = 5)] - Killed(_2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReferendumStatus<_0, _1, _2, _3, _4, _5, _6, _7> { - pub track: _0, - pub origin: _1, - pub proposal: _3, - pub enactment: runtime_types::frame_support::traits::schedule::DispatchTime<_2>, - pub submitted: _2, - pub submission_deposit: runtime_types::pallet_referenda::types::Deposit<_6, _4>, - pub decision_deposit: ::core::option::Option< - runtime_types::pallet_referenda::types::Deposit<_6, _4>, - >, - pub deciding: ::core::option::Option< - runtime_types::pallet_referenda::types::DecidingStatus<_2>, - >, - pub tally: _5, - pub in_queue: ::core::primitive::bool, - pub alarm: ::core::option::Option<(_2, _7)>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct TrackInfo<_0, _1> { - pub name: ::std::string::String, - pub max_deciding: _1, - pub decision_deposit: _0, - pub prepare_period: _1, - pub decision_period: _1, - pub confirm_period: _1, - pub min_enactment_period: _1, - pub min_approval: runtime_types::pallet_referenda::types::Curve, - pub min_support: runtime_types::pallet_referenda::types::Curve, - } - } - } - pub mod pallet_scheduler { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - schedule { - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - schedule_named { - id: [::core::primitive::u8; 32usize], - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 3)] - cancel_named { id: [::core::primitive::u8; 32usize] }, - #[codec(index = 4)] - schedule_after { - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 5)] - schedule_named_after { - id: [::core::primitive::u8; 32usize], - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSchedule, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - TargetBlockNumberInPast, - #[codec(index = 3)] - RescheduleNoChange, - #[codec(index = 4)] - Named, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 1)] - Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - Dispatched { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - CallUnavailable { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 4)] - PeriodicFailed { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 5)] - PermanentlyOverweight { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Scheduled<_0, _1, _2, _3, _4> { - pub maybe_id: ::core::option::Option<_0>, - pub priority: ::core::primitive::u8, - pub call: _1, - pub maybe_periodic: ::core::option::Option<(_2, _2)>, - pub origin: _3, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::polkadot_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_staking { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - bond { - #[codec(compact)] - value: ::core::primitive::u128, - payee: runtime_types::pallet_staking::RewardDestination< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 1)] - bond_extra { - #[codec(compact)] - max_additional: ::core::primitive::u128, - }, - #[codec(index = 2)] - unbond { - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - withdraw_unbonded { num_slashing_spans: ::core::primitive::u32 }, - #[codec(index = 4)] - validate { prefs: runtime_types::pallet_staking::ValidatorPrefs }, - #[codec(index = 5)] - nominate { - targets: ::std::vec::Vec< - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - >, - }, - #[codec(index = 6)] - chill, - #[codec(index = 7)] - set_payee { - payee: runtime_types::pallet_staking::RewardDestination< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 8)] - set_controller, - #[codec(index = 9)] - set_validator_count { - #[codec(compact)] - new: ::core::primitive::u32, - }, - #[codec(index = 10)] - increase_validator_count { - #[codec(compact)] - additional: ::core::primitive::u32, - }, - #[codec(index = 11)] - scale_validator_count { - factor: runtime_types::sp_arithmetic::per_things::Percent, - }, - #[codec(index = 12)] - force_no_eras, - #[codec(index = 13)] - force_new_era, - #[codec(index = 14)] - set_invulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 15)] - force_unstake { - stash: ::sp_core::crypto::AccountId32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 16)] - force_new_era_always, - #[codec(index = 17)] - cancel_deferred_slash { - era: ::core::primitive::u32, - slash_indices: ::std::vec::Vec<::core::primitive::u32>, - }, - #[codec(index = 18)] - payout_stakers { - validator_stash: ::sp_core::crypto::AccountId32, - era: ::core::primitive::u32, - }, - #[codec(index = 19)] - rebond { - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 20)] - reap_stash { - stash: ::sp_core::crypto::AccountId32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 21)] - kick { - who: ::std::vec::Vec< - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - >, - }, - #[codec(index = 22)] - set_staking_configs { - min_nominator_bond: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u128, - >, - min_validator_bond: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u128, - >, - max_nominator_count: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u32, - >, - max_validator_count: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u32, - >, - chill_threshold: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - runtime_types::sp_arithmetic::per_things::Percent, - >, - min_commission: runtime_types::pallet_staking::pallet::pallet::ConfigOp< - runtime_types::sp_arithmetic::per_things::Perbill, - >, - }, - #[codec(index = 23)] - chill_other { controller: ::sp_core::crypto::AccountId32 }, - #[codec(index = 24)] - force_apply_min_commission { - validator_stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 25)] - set_min_commission { - new: runtime_types::sp_arithmetic::per_things::Perbill, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConfigOp<_0> { - #[codec(index = 0)] - Noop, - #[codec(index = 1)] - Set(_0), - #[codec(index = 2)] - Remove, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotController, - #[codec(index = 1)] - NotStash, - #[codec(index = 2)] - AlreadyBonded, - #[codec(index = 3)] - AlreadyPaired, - #[codec(index = 4)] - EmptyTargets, - #[codec(index = 5)] - DuplicateIndex, - #[codec(index = 6)] - InvalidSlashIndex, - #[codec(index = 7)] - InsufficientBond, - #[codec(index = 8)] - NoMoreChunks, - #[codec(index = 9)] - NoUnlockChunk, - #[codec(index = 10)] - FundedTarget, - #[codec(index = 11)] - InvalidEraToReward, - #[codec(index = 12)] - InvalidNumberOfNominations, - #[codec(index = 13)] - NotSortedAndUnique, - #[codec(index = 14)] - AlreadyClaimed, - #[codec(index = 15)] - IncorrectHistoryDepth, - #[codec(index = 16)] - IncorrectSlashingSpans, - #[codec(index = 17)] - BadState, - #[codec(index = 18)] - TooManyTargets, - #[codec(index = 19)] - BadTarget, - #[codec(index = 20)] - CannotChillOther, - #[codec(index = 21)] - TooManyNominators, - #[codec(index = 22)] - TooManyValidators, - #[codec(index = 23)] - CommissionTooLow, - #[codec(index = 24)] - BoundNotMet, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - EraPaid { - era_index: ::core::primitive::u32, - validator_payout: ::core::primitive::u128, - remainder: ::core::primitive::u128, - }, - #[codec(index = 1)] - Rewarded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Slashed { - staker: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - SlashReported { - validator: ::sp_core::crypto::AccountId32, - fraction: runtime_types::sp_arithmetic::per_things::Perbill, - slash_era: ::core::primitive::u32, - }, - #[codec(index = 4)] - OldSlashingReportDiscarded { session_index: ::core::primitive::u32 }, - #[codec(index = 5)] - StakersElected, - #[codec(index = 6)] - Bonded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 7)] - Unbonded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 8)] - Withdrawn { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Kicked { - nominator: ::sp_core::crypto::AccountId32, - stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 10)] - StakingElectionFailed, - #[codec(index = 11)] - Chilled { stash: ::sp_core::crypto::AccountId32 }, - #[codec(index = 12)] - PayoutStarted { - era_index: ::core::primitive::u32, - validator_stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 13)] - ValidatorPrefsSet { - stash: ::sp_core::crypto::AccountId32, - prefs: runtime_types::pallet_staking::ValidatorPrefs, - }, - #[codec(index = 14)] - ForceEra { mode: runtime_types::pallet_staking::Forcing }, - } - } - } - pub mod slashing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SlashingSpans { - pub span_index: ::core::primitive::u32, - pub last_start: ::core::primitive::u32, - pub last_nonzero_slash: ::core::primitive::u32, - pub prior: ::std::vec::Vec<::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SpanRecord<_0> { - pub slashed: _0, - pub paid_out: _0, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ActiveEraInfo { - pub index: ::core::primitive::u32, - pub start: ::core::option::Option<::core::primitive::u64>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EraRewardPoints<_0> { - pub total: ::core::primitive::u32, - pub individual: ::subxt::utils::KeyedVec<_0, ::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Exposure<_0, _1> { - #[codec(compact)] - pub total: _1, - #[codec(compact)] - pub own: _1, - pub others: - ::std::vec::Vec>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Forcing { - #[codec(index = 0)] - NotForcing, - #[codec(index = 1)] - ForceNew, - #[codec(index = 2)] - ForceNone, - #[codec(index = 3)] - ForceAlways, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndividualExposure<_0, _1> { - pub who: _0, - #[codec(compact)] - pub value: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Nominations { - pub targets: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::sp_core::crypto::AccountId32, - >, - pub submitted_in: ::core::primitive::u32, - pub suppressed: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardDestination<_0> { - #[codec(index = 0)] - Staked, - #[codec(index = 1)] - Stash, - #[codec(index = 2)] - Controller, - #[codec(index = 3)] - Account(_0), - #[codec(index = 4)] - None, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StakingLedger { - pub stash: ::sp_core::crypto::AccountId32, - #[codec(compact)] - pub total: ::core::primitive::u128, - #[codec(compact)] - pub active: ::core::primitive::u128, - pub unlocking: runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_staking::UnlockChunk<::core::primitive::u128>, - >, - pub claimed_rewards: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnappliedSlash<_0, _1> { - pub validator: _0, - pub own: _1, - pub others: ::std::vec::Vec<(_0, _1)>, - pub reporters: ::std::vec::Vec<_0>, - pub payout: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnlockChunk<_0> { - #[codec(compact)] - pub value: _0, - #[codec(compact)] - pub era: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidatorPrefs { - #[codec(compact)] - pub commission: runtime_types::sp_arithmetic::per_things::Perbill, - pub blocked: ::core::primitive::bool, - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_tips { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_awesome { - reason: ::std::vec::Vec<::core::primitive::u8>, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - retract_tip { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - tip_new { - reason: ::std::vec::Vec<::core::primitive::u8>, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - tip_value: ::core::primitive::u128, - }, - #[codec(index = 3)] - tip { - hash: ::subxt::utils::H256, - #[codec(compact)] - tip_value: ::core::primitive::u128, - }, - #[codec(index = 4)] - close_tip { hash: ::subxt::utils::H256 }, - #[codec(index = 5)] - slash_tip { hash: ::subxt::utils::H256 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ReasonTooBig, - #[codec(index = 1)] - AlreadyKnown, - #[codec(index = 2)] - UnknownTip, - #[codec(index = 3)] - NotFinder, - #[codec(index = 4)] - StillOpen, - #[codec(index = 5)] - Premature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewTip { tip_hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - TipClosing { tip_hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - TipClosed { - tip_hash: ::subxt::utils::H256, - who: ::sp_core::crypto::AccountId32, - payout: ::core::primitive::u128, - }, - #[codec(index = 3)] - TipRetracted { tip_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - TipSlashed { - tip_hash: ::subxt::utils::H256, - finder: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpenTip<_0, _1, _2, _3> { - pub reason: _3, - pub who: _0, - pub finder: _0, - pub deposit: _1, - pub closes: ::core::option::Option<_2>, - pub tips: ::std::vec::Vec<(_0, _1)>, - pub finders_fee: ::core::primitive::bool, - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_treasury { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose_spend { - #[codec(compact)] - value: ::core::primitive::u128, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - reject_proposal { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - #[codec(index = 2)] - approve_proposal { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - #[codec(index = 3)] - spend { - #[codec(compact)] - amount: ::core::primitive::u128, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - remove_approval { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InsufficientProposersBalance, - #[codec(index = 1)] - InvalidIndex, - #[codec(index = 2)] - TooManyApprovals, - #[codec(index = 3)] - InsufficientPermission, - #[codec(index = 4)] - ProposalNotApproved, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { proposal_index: ::core::primitive::u32 }, - #[codec(index = 1)] - Spending { budget_remaining: ::core::primitive::u128 }, - #[codec(index = 2)] - Awarded { - proposal_index: ::core::primitive::u32, - award: ::core::primitive::u128, - account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Rejected { - proposal_index: ::core::primitive::u32, - slashed: ::core::primitive::u128, - }, - #[codec(index = 4)] - Burnt { burnt_funds: ::core::primitive::u128 }, - #[codec(index = 5)] - Rollover { rollover_balance: ::core::primitive::u128 }, - #[codec(index = 6)] - Deposit { value: ::core::primitive::u128 }, - #[codec(index = 7)] - SpendApproved { - proposal_index: ::core::primitive::u32, - amount: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - UpdatedInactive { - reactivated: ::core::primitive::u128, - deactivated: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Proposal<_0, _1> { - pub proposer: _0, - pub value: _1, - pub beneficiary: _0, - pub bond: _1, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { calls: ::std::vec::Vec }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box, - }, - #[codec(index = 2)] - batch_all { - calls: ::std::vec::Vec, - }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box, - call: ::std::boxed::Box, - }, - #[codec(index = 4)] - force_batch { - calls: ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_vesting { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vest, - #[codec(index = 1)] - vest_other { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - vested_transfer { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 3)] - force_vested_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 4)] - merge_schedules { - schedule1_index: ::core::primitive::u32, - schedule2_index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotVesting, - #[codec(index = 1)] - AtMaxVestingSchedules, - #[codec(index = 2)] - AmountLow, - #[codec(index = 3)] - ScheduleIndexOutOfBounds, - #[codec(index = 4)] - InvalidScheduleParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - VestingUpdated { - account: ::sp_core::crypto::AccountId32, - unvested: ::core::primitive::u128, - }, - #[codec(index = 1)] - VestingCompleted { account: ::sp_core::crypto::AccountId32 }, - } - } - pub mod vesting_info { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VestingInfo<_0, _1> { - pub locked: _0, - pub per_block: _0, - pub starting_block: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V0, - #[codec(index = 1)] - V1, - } - } - pub mod pallet_whitelist { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - whitelist_call { call_hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - remove_whitelisted_call { call_hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - dispatch_whitelisted_call { - call_hash: ::subxt::utils::H256, - call_encoded_len: ::core::primitive::u32, - call_weight_witness: ::sp_weights::Weight, - }, - #[codec(index = 3)] - dispatch_whitelisted_call_with_preimage { - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnavailablePreImage, - #[codec(index = 1)] - UndecodableCall, - #[codec(index = 2)] - InvalidCallWeightWitness, - #[codec(index = 3)] - CallIsNotWhitelisted, - #[codec(index = 4)] - CallAlreadyWhitelisted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CallWhitelisted { call_hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - WhitelistedCallRemoved { call_hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - WhitelistedCallDispatched { - call_hash: ::subxt::utils::H256, - result: ::core::result::Result< - runtime_types::frame_support::dispatch::PostDispatchInfo, - runtime_types::sp_runtime::DispatchErrorWithPostInfo< - runtime_types::frame_support::dispatch::PostDispatchInfo, - >, - >, - }, - } - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - xcm_version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted(runtime_types::xcm::v3::traits::Outcome), - #[codec(index = 1)] - Sent( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::Xcm, - ), - #[codec(index = 2)] - UnexpectedResponse( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 3)] - ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), - #[codec(index = 4)] - Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), - #[codec(index = 5)] - NotifyOverweight( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ::sp_weights::Weight, - ::sp_weights::Weight, - ), - #[codec(index = 6)] - NotifyDispatchError( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 7)] - NotifyDecodeFailed( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 8)] - InvalidResponder( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 9)] - InvalidResponderVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 10)] - ResponseTaken(::core::primitive::u64), - #[codec(index = 11)] - AssetsTrapped( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - #[codec(index = 12)] - VersionChangeNotified( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 13)] - SupportedVersionChanged( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - ), - #[codec(index = 14)] - NotifyTargetSendFail( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::traits::Error, - ), - #[codec(index = 15)] - NotifyTargetMigrationFail( - runtime_types::xcm::VersionedMultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 16)] - InvalidQuerierVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 17)] - InvalidQuerier( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 18)] - VersionNotifyStarted( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 19)] - VersionNotifyRequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 20)] - VersionNotifyUnrequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 21)] - FeesPaid( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 22)] - AssetsClaimed( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Response(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedMultiLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateHash(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelId { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub recipient: runtime_types::polkadot_parachain::primitives::Id, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCodeHash(pub ::subxt::utils::H256); - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v4 { - use super::runtime_types; - pub mod assignment_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod collator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - pub mod executor_params { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ExecutorParam { - #[codec(index = 1)] - MaxMemoryPages(::core::primitive::u32), - #[codec(index = 2)] - StackLogicalMax(::core::primitive::u32), - #[codec(index = 3)] - StackNativeMax(::core::primitive::u32), - #[codec(index = 4)] - PrecheckingMaxMemory(::core::primitive::u64), - #[codec(index = 5)] - PvfPrepTimeout( - runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 6)] - PvfExecTimeout( - runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 7)] - WasmExtBulkMemory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutorParams( - pub ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, - >, - ); - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedSigned<_0, _1> { - pub payload: _0, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - pub signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, - } - } - pub mod validator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfield( - pub ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BackedCandidate<_0> { - pub candidate: - runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, - pub validity_votes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::ValidityAttestation, - >, - pub validator_indices: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateCommitments<_0> { - pub upward_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::std::vec::Vec<::core::primitive::u8>, - >, - pub horizontal_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain::primitives::Id, - >, - >, - pub new_validation_code: ::core::option::Option< - runtime_types::polkadot_parachain::primitives::ValidationCode, - >, - pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, - pub processed_downward_messages: _0, - pub hrmp_watermark: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateDescriptor<_0> { - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub relay_parent: _0, - pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, - pub persisted_validation_data_hash: _0, - pub pov_hash: _0, - pub erasure_root: _0, - pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, - pub para_head: _0, - pub validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments_hash: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommittedCandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< - ::core::primitive::u32, - >, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct CoreIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum CoreOccupied { - #[codec(index = 0)] - Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), - #[codec(index = 1)] - Parachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeState<_0> { - pub validators_for: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub validators_against: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub start: _0, - pub concluded_at: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeStatement { - #[codec(index = 0)] - Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), - #[codec(index = 1)] - Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeStatementSet { - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub session: ::core::primitive::u32, - pub statements: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::DisputeStatement, - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Signature, - )>, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct GroupIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndexedVec<_0, _1>( - pub ::std::vec::Vec<_1>, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData<_0> { - pub bitfields: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - >, - >, - pub backed_candidates: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::BackedCandidate< - ::subxt::utils::H256, - >, - >, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - pub parent_header: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaim( - pub runtime_types::polkadot_parachain::primitives::Id, - pub runtime_types::polkadot_primitives::v4::collator_app::Public, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadEntry { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, - pub retries: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckStatement { - pub accept: ::core::primitive::bool, - pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - pub session_index: ::core::primitive::u32, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfExecTimeoutKind { - #[codec(index = 0)] - Backing, - #[codec(index = 1)] - Approval, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfPrepTimeoutKind { - #[codec(index = 0)] - Precheck, - #[codec(index = 1)] - Lenient, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ScrapedOnChainVotes<_0> { - pub session: ::core::primitive::u32, - pub backing_validators_per_candidate: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, - ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::ValidityAttestation, - )>, - )>, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionInfo { - pub active_validator_indices: - ::std::vec::Vec, - pub random_seed: [::core::primitive::u8; 32usize], - pub dispute_period: ::core::primitive::u32, - pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub discovery_keys: - ::std::vec::Vec, - pub assignment_keys: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::assignment_app::Public, - >, - pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::GroupIndex, - ::std::vec::Vec, - >, - pub n_cores: ::core::primitive::u32, - pub zeroth_delay_tranche_width: ::core::primitive::u32, - pub relay_vrf_modulo_samples: ::core::primitive::u32, - pub n_delay_tranches: ::core::primitive::u32, - pub no_show_slots: ::core::primitive::u32, - pub needed_approvals: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - #[codec(index = 1)] - BackingSeconded(::subxt::utils::H256), - #[codec(index = 2)] - BackingValid(::subxt::utils::H256), - #[codec(index = 3)] - ApprovalChecking, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ValidatorIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidityAttestation { - #[codec(index = 1)] - Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - #[codec(index = 2)] - Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - } - } - pub mod vstaging { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - } - pub mod polkadot_runtime { - use super::runtime_types; - pub mod governance { - use super::runtime_types; - pub mod origins { - use super::runtime_types; - pub mod pallet_custom_origins { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Origin { - #[codec(index = 0)] - StakingAdmin, - #[codec(index = 1)] - Treasurer, - #[codec(index = 2)] - FellowshipAdmin, - #[codec(index = 3)] - GeneralAdmin, - #[codec(index = 4)] - AuctionAdmin, - #[codec(index = 5)] - LeaseAdmin, - #[codec(index = 6)] - ReferendumCanceller, - #[codec(index = 7)] - ReferendumKiller, - #[codec(index = 8)] - SmallTipper, - #[codec(index = 9)] - BigTipper, - #[codec(index = 10)] - SmallSpender, - #[codec(index = 11)] - MediumSpender, - #[codec(index = 12)] - BigSpender, - #[codec(index = 13)] - WhitelistedCaller, - } - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct NposCompactSolution16 { - pub votes1: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes2: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - ( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ), - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes3: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 2usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes4: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 3usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes5: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 4usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes6: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 5usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes7: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 6usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes8: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 7usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes9: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 8usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes10: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 9usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes11: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 10usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes12: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 11usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes13: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 12usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes14: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 13usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes15: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 14usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes16: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 15usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - # [codec (index = 0)] system (runtime_types :: frame_support :: dispatch :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 15)] Council (runtime_types :: pallet_collective :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 16)] TechnicalCommittee (runtime_types :: pallet_collective :: RawOrigin < :: sp_core :: crypto :: AccountId32 > ,) , # [codec (index = 22)] Origins (runtime_types :: polkadot_runtime :: governance :: origins :: pallet_custom_origins :: Origin ,) , # [codec (index = 50)] ParachainsOrigin (runtime_types :: polkadot_runtime_parachains :: origin :: pallet :: Origin ,) , # [codec (index = 99)] XcmPallet (runtime_types :: pallet_xcm :: pallet :: Origin ,) , # [codec (index = 6)] Void (runtime_types :: sp_core :: Void ,) , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProxyType { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - NonTransfer, - #[codec(index = 2)] - Governance, - #[codec(index = 3)] - Staking, - #[codec(index = 5)] - IdentityJudgement, - #[codec(index = 6)] - CancelProxy, - #[codec(index = 7)] - Auction, - #[codec(index = 8)] - NominationPools, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - Scheduler(runtime_types::pallet_scheduler::pallet::Call), - #[codec(index = 10)] - Preimage(runtime_types::pallet_preimage::pallet::Call), - #[codec(index = 2)] - Babe(runtime_types::pallet_babe::pallet::Call), - #[codec(index = 3)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 4)] - Indices(runtime_types::pallet_indices::pallet::Call), - #[codec(index = 5)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 7)] - Staking(runtime_types::pallet_staking::pallet::pallet::Call), - #[codec(index = 9)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 11)] - Grandpa(runtime_types::pallet_grandpa::pallet::Call), - #[codec(index = 12)] - ImOnline(runtime_types::pallet_im_online::pallet::Call), - #[codec(index = 14)] - Democracy(runtime_types::pallet_democracy::pallet::Call), - #[codec(index = 15)] - Council(runtime_types::pallet_collective::pallet::Call), - #[codec(index = 16)] - TechnicalCommittee(runtime_types::pallet_collective::pallet::Call), - #[codec(index = 17)] - PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Call), - #[codec(index = 18)] - TechnicalMembership(runtime_types::pallet_membership::pallet::Call), - #[codec(index = 19)] - Treasury(runtime_types::pallet_treasury::pallet::Call), - #[codec(index = 20)] - ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Call), - #[codec(index = 21)] - Referenda(runtime_types::pallet_referenda::pallet::Call), - #[codec(index = 23)] - Whitelist(runtime_types::pallet_whitelist::pallet::Call), - #[codec(index = 24)] - Claims(runtime_types::polkadot_runtime_common::claims::pallet::Call), - #[codec(index = 25)] - Vesting(runtime_types::pallet_vesting::pallet::Call), - #[codec(index = 26)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 28)] - Identity(runtime_types::pallet_identity::pallet::Call), - #[codec(index = 29)] - Proxy(runtime_types::pallet_proxy::pallet::Call), - #[codec(index = 30)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 34)] - Bounties(runtime_types::pallet_bounties::pallet::Call), - #[codec(index = 38)] - ChildBounties(runtime_types::pallet_child_bounties::pallet::Call), - #[codec(index = 35)] - Tips(runtime_types::pallet_tips::pallet::Call), - #[codec(index = 36)] - ElectionProviderMultiPhase( - runtime_types::pallet_election_provider_multi_phase::pallet::Call, - ), - #[codec(index = 37)] - VoterList(runtime_types::pallet_bags_list::pallet::Call), - #[codec(index = 39)] - NominationPools(runtime_types::pallet_nomination_pools::pallet::Call), - #[codec(index = 40)] - FastUnstake(runtime_types::pallet_fast_unstake::pallet::Call), - #[codec(index = 51)] - Configuration( - runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, - ), - #[codec(index = 52)] - ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), - #[codec(index = 53)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), - #[codec(index = 54)] - ParaInherent( - runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, - ), - #[codec(index = 56)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), - #[codec(index = 57)] - Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), - #[codec(index = 60)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), - #[codec(index = 62)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), - #[codec(index = 63)] - ParasSlashing( - runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, - ), - #[codec(index = 70)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), - #[codec(index = 71)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), - #[codec(index = 72)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), - #[codec(index = 73)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 100)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 1)] - Scheduler(runtime_types::pallet_scheduler::pallet::Event), - #[codec(index = 10)] - Preimage(runtime_types::pallet_preimage::pallet::Event), - #[codec(index = 4)] - Indices(runtime_types::pallet_indices::pallet::Event), - #[codec(index = 5)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 32)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 7)] - Staking(runtime_types::pallet_staking::pallet::pallet::Event), - #[codec(index = 8)] - Offences(runtime_types::pallet_offences::pallet::Event), - #[codec(index = 9)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 11)] - Grandpa(runtime_types::pallet_grandpa::pallet::Event), - #[codec(index = 12)] - ImOnline(runtime_types::pallet_im_online::pallet::Event), - #[codec(index = 14)] - Democracy(runtime_types::pallet_democracy::pallet::Event), - #[codec(index = 15)] - Council(runtime_types::pallet_collective::pallet::Event), - #[codec(index = 16)] - TechnicalCommittee(runtime_types::pallet_collective::pallet::Event), - #[codec(index = 17)] - PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Event), - #[codec(index = 18)] - TechnicalMembership(runtime_types::pallet_membership::pallet::Event), - #[codec(index = 19)] - Treasury(runtime_types::pallet_treasury::pallet::Event), - #[codec(index = 20)] - ConvictionVoting(runtime_types::pallet_conviction_voting::pallet::Event), - #[codec(index = 21)] - Referenda(runtime_types::pallet_referenda::pallet::Event), - #[codec(index = 23)] - Whitelist(runtime_types::pallet_whitelist::pallet::Event), - #[codec(index = 24)] - Claims(runtime_types::polkadot_runtime_common::claims::pallet::Event), - #[codec(index = 25)] - Vesting(runtime_types::pallet_vesting::pallet::Event), - #[codec(index = 26)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 28)] - Identity(runtime_types::pallet_identity::pallet::Event), - #[codec(index = 29)] - Proxy(runtime_types::pallet_proxy::pallet::Event), - #[codec(index = 30)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 34)] - Bounties(runtime_types::pallet_bounties::pallet::Event), - #[codec(index = 38)] - ChildBounties(runtime_types::pallet_child_bounties::pallet::Event), - #[codec(index = 35)] - Tips(runtime_types::pallet_tips::pallet::Event), - #[codec(index = 36)] - ElectionProviderMultiPhase( - runtime_types::pallet_election_provider_multi_phase::pallet::Event, - ), - #[codec(index = 37)] - VoterList(runtime_types::pallet_bags_list::pallet::Event), - #[codec(index = 39)] - NominationPools(runtime_types::pallet_nomination_pools::pallet::Event), - #[codec(index = 40)] - FastUnstake(runtime_types::pallet_fast_unstake::pallet::Event), - #[codec(index = 53)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), - #[codec(index = 56)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), - #[codec(index = 60)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), - #[codec(index = 62)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), - #[codec(index = 70)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), - #[codec(index = 71)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), - #[codec(index = 72)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), - #[codec(index = 73)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 100)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, - pub babe: runtime_types::sp_consensus_babe::app::Public, - pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, - pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, - pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, - } - } - pub mod polkadot_runtime_common { - use super::runtime_types; - pub mod auctions { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - new_auction { - #[codec(compact)] - duration: ::core::primitive::u32, - #[codec(compact)] - lease_period_index: ::core::primitive::u32, - }, - #[codec(index = 1)] - bid { - #[codec(compact)] - para: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - auction_index: ::core::primitive::u32, - #[codec(compact)] - first_slot: ::core::primitive::u32, - #[codec(compact)] - last_slot: ::core::primitive::u32, - #[codec(compact)] - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - cancel_auction, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AuctionInProgress, - #[codec(index = 1)] - LeasePeriodInPast, - #[codec(index = 2)] - ParaNotRegistered, - #[codec(index = 3)] - NotCurrentAuction, - #[codec(index = 4)] - NotAuction, - #[codec(index = 5)] - AuctionEnded, - #[codec(index = 6)] - AlreadyLeasedOut, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - AuctionStarted { - auction_index: ::core::primitive::u32, - lease_period: ::core::primitive::u32, - ending: ::core::primitive::u32, - }, - #[codec(index = 1)] - AuctionClosed { auction_index: ::core::primitive::u32 }, - #[codec(index = 2)] - Reserved { - bidder: ::sp_core::crypto::AccountId32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unreserved { - bidder: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - ReserveConfiscated { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - BidAccepted { - bidder: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - first_slot: ::core::primitive::u32, - last_slot: ::core::primitive::u32, - }, - #[codec(index = 6)] - WinningOffset { - auction_index: ::core::primitive::u32, - block_number: ::core::primitive::u32, - }, - } - } - } - pub mod claims { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { - dest: ::sp_core::crypto::AccountId32, - ethereum_signature: - runtime_types::polkadot_runtime_common::claims::EcdsaSignature, - }, - #[codec(index = 1)] - mint_claim { - who: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - value: ::core::primitive::u128, - vesting_schedule: ::core::option::Option<( - ::core::primitive::u128, - ::core::primitive::u128, - ::core::primitive::u32, - )>, - statement: ::core::option::Option< - runtime_types::polkadot_runtime_common::claims::StatementKind, - >, - }, - #[codec(index = 2)] - claim_attest { - dest: ::sp_core::crypto::AccountId32, - ethereum_signature: - runtime_types::polkadot_runtime_common::claims::EcdsaSignature, - statement: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 3)] - attest { statement: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - move_claim { - old: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - new: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - maybe_preclaim: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEthereumSignature, - #[codec(index = 1)] - SignerHasNoClaim, - #[codec(index = 2)] - SenderHasNoClaim, - #[codec(index = 3)] - PotUnderflow, - #[codec(index = 4)] - InvalidStatement, - #[codec(index = 5)] - VestedBalanceExists, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Claimed { - who: ::sp_core::crypto::AccountId32, - ethereum_address: - runtime_types::polkadot_runtime_common::claims::EthereumAddress, - amount: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EcdsaSignature(pub [::core::primitive::u8; 65usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EthereumAddress(pub [::core::primitive::u8; 20usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PrevalidateAttests; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StatementKind { - #[codec(index = 0)] - Regular, - #[codec(index = 1)] - Saft, - } - } - pub mod crowdloan { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - create { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 1)] - contribute { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - value: ::core::primitive::u128, - signature: - ::core::option::Option, - }, - #[codec(index = 2)] - withdraw { - who: ::sp_core::crypto::AccountId32, - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 3)] - refund { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - dissolve { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - edit { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 6)] - add_memo { - index: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 7)] - poke { index: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - contribute_all { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - signature: - ::core::option::Option, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FirstPeriodInPast, - #[codec(index = 1)] - FirstPeriodTooFarInFuture, - #[codec(index = 2)] - LastPeriodBeforeFirstPeriod, - #[codec(index = 3)] - LastPeriodTooFarInFuture, - #[codec(index = 4)] - CannotEndInPast, - #[codec(index = 5)] - EndTooFarInFuture, - #[codec(index = 6)] - Overflow, - #[codec(index = 7)] - ContributionTooSmall, - #[codec(index = 8)] - InvalidParaId, - #[codec(index = 9)] - CapExceeded, - #[codec(index = 10)] - ContributionPeriodOver, - #[codec(index = 11)] - InvalidOrigin, - #[codec(index = 12)] - NotParachain, - #[codec(index = 13)] - LeaseActive, - #[codec(index = 14)] - BidOrLeaseActive, - #[codec(index = 15)] - FundNotEnded, - #[codec(index = 16)] - NoContributions, - #[codec(index = 17)] - NotReadyToDissolve, - #[codec(index = 18)] - InvalidSignature, - #[codec(index = 19)] - MemoTooLarge, - #[codec(index = 20)] - AlreadyInNewRaise, - #[codec(index = 21)] - VrfDelayInProgress, - #[codec(index = 22)] - NoLeasePeriod, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 1)] - Contributed { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Withdrew { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - PartiallyRefunded { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 6)] - HandleBidResult { - para_id: runtime_types::polkadot_parachain::primitives::Id, - result: ::core::result::Result< - (), - runtime_types::sp_runtime::DispatchError, - >, - }, - #[codec(index = 7)] - Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - MemoUpdated { - who: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 9)] - AddedToNewRaise { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FundInfo<_0, _1, _2, _3> { - pub depositor: _0, - pub verifier: ::core::option::Option, - pub deposit: _1, - pub raised: _1, - pub end: _2, - pub cap: _1, - pub last_contribution: - runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, - pub first_period: _2, - pub last_period: _2, - pub fund_index: _2, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum LastContribution<_0> { - #[codec(index = 0)] - Never, - #[codec(index = 1)] - PreEnding(_0), - #[codec(index = 2)] - Ending(_0), - } - } - pub mod paras_registrar { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register { - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_register { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 2)] - deregister { id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 3)] - swap { - id: runtime_types::polkadot_parachain::primitives::Id, - other: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - reserve, - #[codec(index = 6)] - add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 7)] - schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 8)] - set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - AlreadyRegistered, - #[codec(index = 2)] - NotOwner, - #[codec(index = 3)] - CodeTooLarge, - #[codec(index = 4)] - HeadDataTooLarge, - #[codec(index = 5)] - NotParachain, - #[codec(index = 6)] - NotParathread, - #[codec(index = 7)] - CannotDeregister, - #[codec(index = 8)] - CannotDowngrade, - #[codec(index = 9)] - CannotUpgrade, - #[codec(index = 10)] - ParaLocked, - #[codec(index = 11)] - NotReserved, - #[codec(index = 12)] - EmptyCode, - #[codec(index = 13)] - CannotSwap, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Registered { - para_id: runtime_types::polkadot_parachain::primitives::Id, - manager: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 1)] - Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - Reserved { - para_id: runtime_types::polkadot_parachain::primitives::Id, - who: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Swapped { - para_id: runtime_types::polkadot_parachain::primitives::Id, - other_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo<_0, _1> { - pub manager: _0, - pub deposit: _1, - pub locked: ::core::primitive::bool, - } - } - pub mod slots { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_lease { - para: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - }, - #[codec(index = 1)] - clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaNotOnboarding, - #[codec(index = 1)] - LeaseError, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewLeasePeriod { lease_period: ::core::primitive::u32 }, - #[codec(index = 1)] - Leased { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - } - } - } - } - pub mod polkadot_runtime_parachains { - use super::runtime_types; - pub mod configuration { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidNewValue, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HostConfiguration<_0> { - pub max_code_size: _0, - pub max_head_data_size: _0, - pub max_upward_queue_count: _0, - pub max_upward_queue_size: _0, - pub max_upward_message_size: _0, - pub max_upward_message_num_per_candidate: _0, - pub hrmp_max_message_num_per_candidate: _0, - pub validation_upgrade_cooldown: _0, - pub validation_upgrade_delay: _0, - pub async_backing_params: - runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, - pub max_pov_size: _0, - pub max_downward_message_size: _0, - pub hrmp_max_parachain_outbound_channels: _0, - pub hrmp_max_parathread_outbound_channels: _0, - pub hrmp_sender_deposit: ::core::primitive::u128, - pub hrmp_recipient_deposit: ::core::primitive::u128, - pub hrmp_channel_max_capacity: _0, - pub hrmp_channel_max_total_size: _0, - pub hrmp_max_parachain_inbound_channels: _0, - pub hrmp_max_parathread_inbound_channels: _0, - pub hrmp_channel_max_message_size: _0, - pub executor_params: - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, - pub code_retention_period: _0, - pub parathread_cores: _0, - pub parathread_retries: _0, - pub group_rotation_frequency: _0, - pub chain_availability_period: _0, - pub thread_availability_period: _0, - pub scheduling_lookahead: _0, - pub max_validators_per_core: ::core::option::Option<_0>, - pub max_validators: ::core::option::Option<_0>, - pub dispute_period: _0, - pub dispute_post_conclusion_acceptance_period: _0, - pub no_show_slots: _0, - pub n_delay_tranches: _0, - pub zeroth_delay_tranche_width: _0, - pub needed_approvals: _0, - pub relay_vrf_modulo_samples: _0, - pub pvf_checking_enabled: ::core::primitive::bool, - pub pvf_voting_ttl: _0, - pub minimum_validation_upgrade_delay: _0, - } - } - pub mod disputes { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_unfreeze, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateDisputeStatementSets, - #[codec(index = 1)] - AncientDisputeStatement, - #[codec(index = 2)] - ValidatorIndexOutOfBounds, - #[codec(index = 3)] - InvalidSignature, - #[codec(index = 4)] - DuplicateStatement, - #[codec(index = 5)] - SingleSidedDispute, - #[codec(index = 6)] - MaliciousBacker, - #[codec(index = 7)] - MissingBackingVotes, - #[codec(index = 8)] - UnconfirmedDispute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - DisputeInitiated( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, - ), - #[codec(index = 1)] - DisputeConcluded( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, - ), - #[codec(index = 2)] - Revert(::core::primitive::u32), - } - } - pub mod slashing { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Call { - # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Error { - #[codec(index = 0)] - InvalidKeyOwnershipProof, - #[codec(index = 1)] - InvalidSessionIndex, - #[codec(index = 2)] - InvalidCandidateHash, - #[codec(index = 3)] - InvalidValidatorIndex, - #[codec(index = 4)] - ValidatorIndexIdMismatch, - #[codec(index = 5)] - DuplicateSlashingReport, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputesTimeSlot { - pub session_index: ::core::primitive::u32, - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SlashingOffenceKind { - #[codec(index = 0)] - ForInvalid, - #[codec(index = 1)] - AgainstValid, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeLocation { - #[codec(index = 0)] - Local, - #[codec(index = 1)] - Remote, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeResult { - #[codec(index = 0)] - Valid, - #[codec(index = 1)] - Invalid, - } - } - pub mod hrmp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - hrmp_init_open_channel { - recipient: runtime_types::polkadot_parachain::primitives::Id, - proposed_max_capacity: ::core::primitive::u32, - proposed_max_message_size: ::core::primitive::u32, - }, - #[codec(index = 1)] - hrmp_accept_open_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 2)] - hrmp_close_channel { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - }, - #[codec(index = 3)] - force_clean_hrmp { - para: runtime_types::polkadot_parachain::primitives::Id, - inbound: ::core::primitive::u32, - outbound: ::core::primitive::u32, - }, - #[codec(index = 4)] - force_process_hrmp_open { channels: ::core::primitive::u32 }, - #[codec(index = 5)] - force_process_hrmp_close { channels: ::core::primitive::u32 }, - #[codec(index = 6)] - hrmp_cancel_open_request { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - open_requests: ::core::primitive::u32, - }, - #[codec(index = 7)] - force_open_hrmp_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - recipient: runtime_types::polkadot_parachain::primitives::Id, - max_capacity: ::core::primitive::u32, - max_message_size: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OpenHrmpChannelToSelf, - #[codec(index = 1)] - OpenHrmpChannelInvalidRecipient, - #[codec(index = 2)] - OpenHrmpChannelZeroCapacity, - #[codec(index = 3)] - OpenHrmpChannelCapacityExceedsLimit, - #[codec(index = 4)] - OpenHrmpChannelZeroMessageSize, - #[codec(index = 5)] - OpenHrmpChannelMessageSizeExceedsLimit, - #[codec(index = 6)] - OpenHrmpChannelAlreadyExists, - #[codec(index = 7)] - OpenHrmpChannelAlreadyRequested, - #[codec(index = 8)] - OpenHrmpChannelLimitExceeded, - #[codec(index = 9)] - AcceptHrmpChannelDoesntExist, - #[codec(index = 10)] - AcceptHrmpChannelAlreadyConfirmed, - #[codec(index = 11)] - AcceptHrmpChannelLimitExceeded, - #[codec(index = 12)] - CloseHrmpChannelUnauthorized, - #[codec(index = 13)] - CloseHrmpChannelDoesntExist, - #[codec(index = 14)] - CloseHrmpChannelAlreadyUnderway, - #[codec(index = 15)] - CancelHrmpOpenChannelUnauthorized, - #[codec(index = 16)] - OpenHrmpChannelDoesntExist, - #[codec(index = 17)] - OpenHrmpChannelAlreadyConfirmed, - #[codec(index = 18)] - WrongWitness, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - OpenChannelRequested( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - #[codec(index = 1)] - OpenChannelCanceled( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 2)] - OpenChannelAccepted( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 3)] - ChannelClosed( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 4)] - HrmpChannelForceOpened( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - pub sender_deposit: ::core::primitive::u128, - pub recipient_deposit: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpOpenChannelRequest { - pub confirmed: ::core::primitive::bool, - pub _age: ::core::primitive::u32, - pub sender_deposit: ::core::primitive::u128, - pub max_message_size: ::core::primitive::u32, - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - } - } - pub mod inclusion { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnsortedOrDuplicateValidatorIndices, - #[codec(index = 1)] - UnsortedOrDuplicateDisputeStatementSet, - #[codec(index = 2)] - UnsortedOrDuplicateBackedCandidates, - #[codec(index = 3)] - UnexpectedRelayParent, - #[codec(index = 4)] - WrongBitfieldSize, - #[codec(index = 5)] - BitfieldAllZeros, - #[codec(index = 6)] - BitfieldDuplicateOrUnordered, - #[codec(index = 7)] - ValidatorIndexOutOfBounds, - #[codec(index = 8)] - InvalidBitfieldSignature, - #[codec(index = 9)] - UnscheduledCandidate, - #[codec(index = 10)] - CandidateScheduledBeforeParaFree, - #[codec(index = 11)] - WrongCollator, - #[codec(index = 12)] - ScheduledOutOfOrder, - #[codec(index = 13)] - HeadDataTooLarge, - #[codec(index = 14)] - PrematureCodeUpgrade, - #[codec(index = 15)] - NewCodeTooLarge, - #[codec(index = 16)] - CandidateNotInParentContext, - #[codec(index = 17)] - InvalidGroupIndex, - #[codec(index = 18)] - InsufficientBacking, - #[codec(index = 19)] - InvalidBacking, - #[codec(index = 20)] - NotCollatorSigned, - #[codec(index = 21)] - ValidationDataHashMismatch, - #[codec(index = 22)] - IncorrectDownwardMessageHandling, - #[codec(index = 23)] - InvalidUpwardMessages, - #[codec(index = 24)] - HrmpWatermarkMishandling, - #[codec(index = 25)] - InvalidOutboundHrmp, - #[codec(index = 26)] - InvalidValidationCodeHash, - #[codec(index = 27)] - ParaHeadMismatch, - #[codec(index = 28)] - BitfieldReferencesFreedCore, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CandidateBacked( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 1)] - CandidateIncluded( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 2)] - CandidateTimedOut( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - ), - #[codec(index = 3)] - UpwardMessagesReceived { - from: runtime_types::polkadot_parachain::primitives::Id, - count: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfieldRecord<_0> { - pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - pub submitted_at: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidatePendingAvailability<_0, _1> { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub availability_votes: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub backers: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub relay_parent_number: _1, - pub backed_in_number: _1, - pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UmpQueueId { - #[codec(index = 0)] - Para(runtime_types::polkadot_parachain::primitives::Id), - } - } - pub mod initializer { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_approve { up_to: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BufferedSessionChange { - pub validators: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub queued: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub session_index: ::core::primitive::u32, - } - } - pub mod origin { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Parachain(runtime_types::polkadot_parachain::primitives::Id), - } - } - } - pub mod paras { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_set_current_code { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 2)] - force_schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - relay_parent_number: ::core::primitive::u32, - }, - #[codec(index = 3)] - force_note_new_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 4)] - force_queue_action { - para: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - add_trusted_validation_code { - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 6)] - poke_unused_validation_code { - validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - }, - #[codec(index = 7)] - include_pvf_check_statement { - stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, - signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - CannotOnboard, - #[codec(index = 2)] - CannotOffboard, - #[codec(index = 3)] - CannotUpgrade, - #[codec(index = 4)] - CannotDowngrade, - #[codec(index = 5)] - PvfCheckStatementStale, - #[codec(index = 6)] - PvfCheckStatementFuture, - #[codec(index = 7)] - PvfCheckValidatorIndexOutOfBounds, - #[codec(index = 8)] - PvfCheckInvalidSignature, - #[codec(index = 9)] - PvfCheckDoubleVote, - #[codec(index = 10)] - PvfCheckSubjectInvalid, - #[codec(index = 11)] - CannotUpgradeCode, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 2)] - CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 3)] - NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 4)] - ActionQueued( - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ), - #[codec(index = 5)] - PvfCheckStarted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 6)] - PvfCheckAccepted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 7)] - PvfCheckRejected( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaGenesisArgs { - pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - pub validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - pub para_kind: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ParaLifecycle { - #[codec(index = 0)] - Onboarding, - #[codec(index = 1)] - Parathread, - #[codec(index = 2)] - Parachain, - #[codec(index = 3)] - UpgradingParathread, - #[codec(index = 4)] - DowngradingParachain, - #[codec(index = 5)] - OffboardingParathread, - #[codec(index = 6)] - OffboardingParachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaPastCodeMeta<_0> { - pub upgrade_times: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, - >, - pub last_pruned: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckActiveVoteState<_0> { - pub votes_accept: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub votes_reject: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub age: _0, - pub created_at: _0, - pub causes: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfCheckCause<_0> { - #[codec(index = 0)] - Onboarding(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - Upgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - relay_parent_number: _0, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReplacementTimes<_0> { - pub expected_at: _0, - pub activated_at: _0, - } - } - pub mod paras_inherent { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - enter { - data: runtime_types::polkadot_primitives::v4::InherentData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyInclusionInherents, - #[codec(index = 1)] - InvalidParentHeader, - #[codec(index = 2)] - CandidateConcludedInvalid, - #[codec(index = 3)] - InherentOverweight, - #[codec(index = 4)] - DisputeStatementsUnsortedOrDuplicates, - #[codec(index = 5)] - DisputeInvalid, - } - } - } - pub mod scheduler { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssignmentKind { - #[codec(index = 0)] - Parachain, - #[codec(index = 1)] - Parathread( - runtime_types::polkadot_primitives::v4::collator_app::Public, - ::core::primitive::u32, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CoreAssignment { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, - pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaimQueue { - pub queue: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, - >, - pub next_core_offset: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueuedParathread { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, - pub core_offset: ::core::primitive::u32, - } - } - pub mod shared { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - } - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FixedI64(pub ::core::primitive::i64); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - pub mod per_things { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct PerU16(pub ::core::primitive::u16); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Perbill(pub ::core::primitive::u32); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Percent(pub ::core::primitive::u8); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Permill(pub ::core::primitive::u32); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_authority_discovery { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - pub mod sp_consensus_babe { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod digests { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NextConfigDescriptor { - #[codec(index = 1)] - V1 { - c: (::core::primitive::u64, ::core::primitive::u64), - allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PreDigest { - #[codec(index = 1)] - Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), - #[codec(index = 2)] - SecondaryPlain( - runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, - ), - #[codec(index = 3)] - SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PrimaryPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryPlainPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryVRFPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AllowedSlots { - #[codec(index = 0)] - PrimarySlots, - #[codec(index = 1)] - PrimaryAndSecondaryPlainSlots, - #[codec(index = 2)] - PrimaryAndSecondaryVRFSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BabeEpochConfiguration { - pub c: (::core::primitive::u64, ::core::primitive::u64), - pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Equivocation<_0, _1> { - #[codec(index = 0)] - Prevote( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Prevote<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - #[codec(index = 1)] - Precommit( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Precommit<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EquivocationProof<_0, _1> { - pub offender: _1, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub first_header: _0, - pub second_header: _0, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 33usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod offchain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueNetworkState { - pub peer_id: runtime_types::sp_core::OpaquePeerId, - pub external_addresses: - ::std::vec::Vec, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod vrf { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VrfSignature { - pub output: [::core::primitive::u8; 32usize], - pub proof: [::core::primitive::u8; 64usize], - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_npos_elections { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ElectionScore { - pub minimal_stake: ::core::primitive::u128, - pub sum_stake: ::core::primitive::u128, - pub sum_stake_squared: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Support<_0> { - pub total: ::core::primitive::u128, - pub voters: ::std::vec::Vec<(_0, ::core::primitive::u128)>, - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_1, _0, _2, _3)>, - ); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchErrorWithPostInfo<_0> { - pub post_info: _0, - pub error: runtime_types::sp_runtime::DispatchError, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSigner { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Public), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Public), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Public), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_staking { - use super::runtime_types; - pub mod offence { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OffenceDetails<_0, _1> { - pub offender: _1, - pub reporters: ::std::vec::Vec<_0>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - } - } -} diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs deleted file mode 100644 index 9b655528b6e4e..0000000000000 --- a/relays/client-polkadot/src/lib.rs +++ /dev/null @@ -1,122 +0,0 @@ -// 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 . - -//! Types used to connect to the Polkadot chain. - -mod codegen_runtime; - -use bp_polkadot::{AccountInfoStorageMapKeyProvider, POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD}; -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, - Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, - UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use sp_session::MembershipProof; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::polkadot_runtime::RuntimeCall; - -pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; - -/// Polkadot header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Polkadot header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Polkadot chain definition -#[derive(Debug, Clone, Copy)] -pub struct Polkadot; - -impl UnderlyingChainProvider for Polkadot { - type Chain = bp_polkadot::Polkadot; -} - -impl Chain for Polkadot { - const NAME: &'static str = "Polkadot"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_polkadot::BEST_FINALIZED_POLKADOT_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_polkadot::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithGrandpa for Polkadot { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - POLKADOT_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl ChainWithBalances for Polkadot { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl RelayChain for Polkadot { - const PARAS_PALLET_NAME: &'static str = bp_polkadot::PARAS_PALLET_NAME; -} - -impl ChainWithTransactions for Polkadot { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_polkadot::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - ((), ()), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithRuntimeVersion for Polkadot { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_001_002, transaction_version: 25 }); -} diff --git a/relays/client-rococo/Cargo.toml b/relays/client-rococo/Cargo.toml deleted file mode 100644 index 5e847600f4660..0000000000000 --- a/relays/client-rococo/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "relay-rococo-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-rococo = { path = "../../chains/chain-rococo" } - -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies - -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-rococo/src/codegen_runtime.rs b/relays/client-rococo/src/codegen_runtime.rs deleted file mode 100644 index 959812b11ba02..0000000000000 --- a/relays/client-rococo/src/codegen_runtime.rs +++ /dev/null @@ -1,7441 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://rococo-rpc.polkadot.io:443 - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -pub mod api { - use super::api as root_mod; - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Equivocation<_0, _1, _2> { - pub round_number: ::core::primitive::u64, - pub identity: _0, - pub first: (_1, _2), - pub second: (_1, _2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Prevote<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProcessMessageError { - #[codec(index = 0)] - BadFormat, - #[codec(index = 1)] - Corrupt, - #[codec(index = 2)] - Unsupported, - #[codec(index = 3)] - Overweight(::sp_weights::Weight), - #[codec(index = 4)] - Yield, - } - } - pub mod misc { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WrapperOpaque<_0>( - #[codec(compact)] pub ::core::primitive::u32, - pub _0, - ); - } - pub mod preimages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Bounded<_0> { - #[codec(index = 0)] - Legacy { - hash: ::subxt::utils::H256, - }, - #[codec(index = 1)] - Inline( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Lookup { - hash: ::subxt::utils::H256, - len: ::core::primitive::u32, - }, - __Ignore(::core::marker::PhantomData<_0>), - } - } - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletId(pub [::core::primitive::u8; 8usize]); - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_babe { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - plan_config_change { - config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEquivocationProof, - #[codec(index = 1)] - InvalidKeyOwnershipProof, - #[codec(index = 2)] - DuplicateOffenceReport, - #[codec(index = 3)] - InvalidConfiguration, - } - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - set_balance_deprecated { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - #[codec(compact)] - old_reserved: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 7)] - transfer { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_beefy { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_beefy::EquivocationProof< - ::core::primitive::u32, - runtime_types::sp_consensus_beefy::crypto::Public, - runtime_types::sp_consensus_beefy::crypto::Signature, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_beefy::EquivocationProof< - ::core::primitive::u32, - runtime_types::sp_consensus_beefy::crypto::Public, - runtime_types::sp_consensus_beefy::crypto::Signature, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidKeyOwnershipProof, - #[codec(index = 1)] - InvalidEquivocationProof, - #[codec(index = 2)] - DuplicateOffenceReport, - } - } - } - pub mod pallet_bounties { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose_bounty { - #[codec(compact)] - value: ::core::primitive::u128, - description: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - approve_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 2)] - propose_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 3)] - unassign_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 4)] - accept_curator { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 5)] - award_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - claim_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 7)] - close_bounty { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - }, - #[codec(index = 8)] - extend_bounty_expiry { - #[codec(compact)] - bounty_id: ::core::primitive::u32, - remark: ::std::vec::Vec<::core::primitive::u8>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InsufficientProposersBalance, - #[codec(index = 1)] - InvalidIndex, - #[codec(index = 2)] - ReasonTooBig, - #[codec(index = 3)] - UnexpectedStatus, - #[codec(index = 4)] - RequireCurator, - #[codec(index = 5)] - InvalidValue, - #[codec(index = 6)] - InvalidFee, - #[codec(index = 7)] - PendingPayout, - #[codec(index = 8)] - Premature, - #[codec(index = 9)] - HasActiveChildBounty, - #[codec(index = 10)] - TooManyQueued, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BountyProposed { index: ::core::primitive::u32 }, - #[codec(index = 1)] - BountyRejected { index: ::core::primitive::u32, bond: ::core::primitive::u128 }, - #[codec(index = 2)] - BountyBecameActive { index: ::core::primitive::u32 }, - #[codec(index = 3)] - BountyAwarded { - index: ::core::primitive::u32, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 4)] - BountyClaimed { - index: ::core::primitive::u32, - payout: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 5)] - BountyCanceled { index: ::core::primitive::u32 }, - #[codec(index = 6)] - BountyExtended { index: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bounty<_0, _1, _2> { - pub proposer: _0, - pub value: _1, - pub fee: _1, - pub curator_deposit: _1, - pub bond: _1, - pub status: runtime_types::pallet_bounties::BountyStatus<_0, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BountyStatus<_0, _1> { - #[codec(index = 0)] - Proposed, - #[codec(index = 1)] - Approved, - #[codec(index = 2)] - Funded, - #[codec(index = 3)] - CuratorProposed { curator: _0 }, - #[codec(index = 4)] - Active { curator: _0, update_due: _1 }, - #[codec(index = 5)] - PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, - } - } - pub mod pallet_child_bounties { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - value: ::core::primitive::u128, - description: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - propose_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - curator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 2)] - accept_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 3)] - unassign_curator { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 4)] - award_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - claim_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - #[codec(index = 6)] - close_child_bounty { - #[codec(compact)] - parent_bounty_id: ::core::primitive::u32, - #[codec(compact)] - child_bounty_id: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParentBountyNotActive, - #[codec(index = 1)] - InsufficientBountyBalance, - #[codec(index = 2)] - TooManyChildBounties, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Added { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, - #[codec(index = 1)] - Awarded { - index: ::core::primitive::u32, - child_index: ::core::primitive::u32, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 2)] - Claimed { - index: ::core::primitive::u32, - child_index: ::core::primitive::u32, - payout: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Canceled { index: ::core::primitive::u32, child_index: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChildBounty<_0, _1, _2> { - pub parent_bounty: _2, - pub value: _1, - pub fee: _1, - pub curator_deposit: _1, - pub status: runtime_types::pallet_child_bounties::ChildBountyStatus<_0, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ChildBountyStatus<_0, _1> { - #[codec(index = 0)] - Added, - #[codec(index = 1)] - CuratorProposed { curator: _0 }, - #[codec(index = 2)] - Active { curator: _0 }, - #[codec(index = 3)] - PendingPayout { curator: _0, beneficiary: _0, unlock_at: _1 }, - } - } - pub mod pallet_collective { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_members { - new_members: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - prime: ::core::option::Option<::sp_core::crypto::AccountId32>, - old_count: ::core::primitive::u32, - }, - #[codec(index = 1)] - execute { - proposal: ::std::boxed::Box, - #[codec(compact)] - length_bound: ::core::primitive::u32, - }, - #[codec(index = 2)] - propose { - #[codec(compact)] - threshold: ::core::primitive::u32, - proposal: ::std::boxed::Box, - #[codec(compact)] - length_bound: ::core::primitive::u32, - }, - #[codec(index = 3)] - vote { - proposal: ::subxt::utils::H256, - #[codec(compact)] - index: ::core::primitive::u32, - approve: ::core::primitive::bool, - }, - #[codec(index = 5)] - disapprove_proposal { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 6)] - close { - proposal_hash: ::subxt::utils::H256, - #[codec(compact)] - index: ::core::primitive::u32, - proposal_weight_bound: ::sp_weights::Weight, - #[codec(compact)] - length_bound: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotMember, - #[codec(index = 1)] - DuplicateProposal, - #[codec(index = 2)] - ProposalMissing, - #[codec(index = 3)] - WrongIndex, - #[codec(index = 4)] - DuplicateVote, - #[codec(index = 5)] - AlreadyInitialized, - #[codec(index = 6)] - TooEarly, - #[codec(index = 7)] - TooManyProposals, - #[codec(index = 8)] - WrongProposalWeight, - #[codec(index = 9)] - WrongProposalLength, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { - account: ::sp_core::crypto::AccountId32, - proposal_index: ::core::primitive::u32, - proposal_hash: ::subxt::utils::H256, - threshold: ::core::primitive::u32, - }, - #[codec(index = 1)] - Voted { - account: ::sp_core::crypto::AccountId32, - proposal_hash: ::subxt::utils::H256, - voted: ::core::primitive::bool, - yes: ::core::primitive::u32, - no: ::core::primitive::u32, - }, - #[codec(index = 2)] - Approved { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 3)] - Disapproved { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - Executed { - proposal_hash: ::subxt::utils::H256, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 5)] - MemberExecuted { - proposal_hash: ::subxt::utils::H256, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 6)] - Closed { - proposal_hash: ::subxt::utils::H256, - yes: ::core::primitive::u32, - no: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Members(::core::primitive::u32, ::core::primitive::u32), - #[codec(index = 1)] - Member(_0), - #[codec(index = 2)] - _Phantom, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Votes<_0, _1> { - pub index: _1, - pub threshold: _1, - pub ayes: ::std::vec::Vec<_0>, - pub nays: ::std::vec::Vec<_0>, - pub end: _1, - } - } - pub mod pallet_democracy { - use super::runtime_types; - pub mod conviction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Conviction { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Locked1x, - #[codec(index = 2)] - Locked2x, - #[codec(index = 3)] - Locked3x, - #[codec(index = 4)] - Locked4x, - #[codec(index = 5)] - Locked5x, - #[codec(index = 6)] - Locked6x, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::rococo_runtime::RuntimeCall, - >, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - second { - #[codec(compact)] - proposal: ::core::primitive::u32, - }, - #[codec(index = 2)] - vote { - #[codec(compact)] - ref_index: ::core::primitive::u32, - vote: runtime_types::pallet_democracy::vote::AccountVote< - ::core::primitive::u128, - >, - }, - #[codec(index = 3)] - emergency_cancel { ref_index: ::core::primitive::u32 }, - #[codec(index = 4)] - external_propose { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::rococo_runtime::RuntimeCall, - >, - }, - #[codec(index = 5)] - external_propose_majority { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::rococo_runtime::RuntimeCall, - >, - }, - #[codec(index = 6)] - external_propose_default { - proposal: runtime_types::frame_support::traits::preimages::Bounded< - runtime_types::rococo_runtime::RuntimeCall, - >, - }, - #[codec(index = 7)] - fast_track { - proposal_hash: ::subxt::utils::H256, - voting_period: ::core::primitive::u32, - delay: ::core::primitive::u32, - }, - #[codec(index = 8)] - veto_external { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 9)] - cancel_referendum { - #[codec(compact)] - ref_index: ::core::primitive::u32, - }, - #[codec(index = 10)] - delegate { - to: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - conviction: runtime_types::pallet_democracy::conviction::Conviction, - balance: ::core::primitive::u128, - }, - #[codec(index = 11)] - undelegate, - #[codec(index = 12)] - clear_public_proposals, - #[codec(index = 13)] - unlock { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 14)] - remove_vote { index: ::core::primitive::u32 }, - #[codec(index = 15)] - remove_other_vote { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - }, - #[codec(index = 16)] - blacklist { - proposal_hash: ::subxt::utils::H256, - maybe_ref_index: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 17)] - cancel_proposal { - #[codec(compact)] - prop_index: ::core::primitive::u32, - }, - #[codec(index = 18)] - set_metadata { - owner: runtime_types::pallet_democracy::types::MetadataOwner, - maybe_hash: ::core::option::Option<::subxt::utils::H256>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ValueLow, - #[codec(index = 1)] - ProposalMissing, - #[codec(index = 2)] - AlreadyCanceled, - #[codec(index = 3)] - DuplicateProposal, - #[codec(index = 4)] - ProposalBlacklisted, - #[codec(index = 5)] - NotSimpleMajority, - #[codec(index = 6)] - InvalidHash, - #[codec(index = 7)] - NoProposal, - #[codec(index = 8)] - AlreadyVetoed, - #[codec(index = 9)] - ReferendumInvalid, - #[codec(index = 10)] - NoneWaiting, - #[codec(index = 11)] - NotVoter, - #[codec(index = 12)] - NoPermission, - #[codec(index = 13)] - AlreadyDelegating, - #[codec(index = 14)] - InsufficientFunds, - #[codec(index = 15)] - NotDelegating, - #[codec(index = 16)] - VotesExist, - #[codec(index = 17)] - InstantNotAllowed, - #[codec(index = 18)] - Nonsense, - #[codec(index = 19)] - WrongUpperBound, - #[codec(index = 20)] - MaxVotesReached, - #[codec(index = 21)] - TooMany, - #[codec(index = 22)] - VotingPeriodLow, - #[codec(index = 23)] - PreimageNotExist, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { - proposal_index: ::core::primitive::u32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 1)] - Tabled { - proposal_index: ::core::primitive::u32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 2)] - ExternalTabled, - #[codec(index = 3)] - Started { - ref_index: ::core::primitive::u32, - threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, - }, - #[codec(index = 4)] - Passed { ref_index: ::core::primitive::u32 }, - #[codec(index = 5)] - NotPassed { ref_index: ::core::primitive::u32 }, - #[codec(index = 6)] - Cancelled { ref_index: ::core::primitive::u32 }, - #[codec(index = 7)] - Delegated { - who: ::sp_core::crypto::AccountId32, - target: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - Undelegated { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 9)] - Vetoed { - who: ::sp_core::crypto::AccountId32, - proposal_hash: ::subxt::utils::H256, - until: ::core::primitive::u32, - }, - #[codec(index = 10)] - Blacklisted { proposal_hash: ::subxt::utils::H256 }, - #[codec(index = 11)] - Voted { - voter: ::sp_core::crypto::AccountId32, - ref_index: ::core::primitive::u32, - vote: runtime_types::pallet_democracy::vote::AccountVote< - ::core::primitive::u128, - >, - }, - #[codec(index = 12)] - Seconded { - seconder: ::sp_core::crypto::AccountId32, - prop_index: ::core::primitive::u32, - }, - #[codec(index = 13)] - ProposalCanceled { prop_index: ::core::primitive::u32 }, - #[codec(index = 14)] - MetadataSet { - owner: runtime_types::pallet_democracy::types::MetadataOwner, - hash: ::subxt::utils::H256, - }, - #[codec(index = 15)] - MetadataCleared { - owner: runtime_types::pallet_democracy::types::MetadataOwner, - hash: ::subxt::utils::H256, - }, - #[codec(index = 16)] - MetadataTransferred { - prev_owner: runtime_types::pallet_democracy::types::MetadataOwner, - owner: runtime_types::pallet_democracy::types::MetadataOwner, - hash: ::subxt::utils::H256, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Delegations<_0> { - pub votes: _0, - pub capital: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MetadataOwner { - #[codec(index = 0)] - External, - #[codec(index = 1)] - Proposal(::core::primitive::u32), - #[codec(index = 2)] - Referendum(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ReferendumInfo<_0, _1, _2> { - #[codec(index = 0)] - Ongoing(runtime_types::pallet_democracy::types::ReferendumStatus<_0, _1, _2>), - #[codec(index = 1)] - Finished { approved: ::core::primitive::bool, end: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReferendumStatus<_0, _1, _2> { - pub end: _0, - pub proposal: _1, - pub threshold: runtime_types::pallet_democracy::vote_threshold::VoteThreshold, - pub delay: _0, - pub tally: runtime_types::pallet_democracy::types::Tally<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Tally<_0> { - pub ayes: _0, - pub nays: _0, - pub turnout: _0, - } - } - pub mod vote { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AccountVote<_0> { - #[codec(index = 0)] - Standard { vote: runtime_types::pallet_democracy::vote::Vote, balance: _0 }, - #[codec(index = 1)] - Split { aye: _0, nay: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PriorLock<_0, _1>(pub _0, pub _1); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Vote(pub ::core::primitive::u8); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Voting<_0, _1, _2> { - #[codec(index = 0)] - Direct { - votes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _2, - runtime_types::pallet_democracy::vote::AccountVote<_0>, - )>, - delegations: runtime_types::pallet_democracy::types::Delegations<_0>, - prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, - }, - #[codec(index = 1)] - Delegating { - balance: _0, - target: _1, - conviction: runtime_types::pallet_democracy::conviction::Conviction, - delegations: runtime_types::pallet_democracy::types::Delegations<_0>, - prior: runtime_types::pallet_democracy::vote::PriorLock<_2, _0>, - }, - } - } - pub mod vote_threshold { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VoteThreshold { - #[codec(index = 0)] - SuperMajorityApprove, - #[codec(index = 1)] - SuperMajorityAgainst, - #[codec(index = 2)] - SimpleMajority, - } - } - } - pub mod pallet_elections_phragmen { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vote { - votes: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - remove_voter, - #[codec(index = 2)] - submit_candidacy { - #[codec(compact)] - candidate_count: ::core::primitive::u32, - }, - #[codec(index = 3)] - renounce_candidacy { - renouncing: runtime_types::pallet_elections_phragmen::Renouncing, - }, - #[codec(index = 4)] - remove_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - slash_bond: ::core::primitive::bool, - rerun_election: ::core::primitive::bool, - }, - #[codec(index = 5)] - clean_defunct_voters { - num_voters: ::core::primitive::u32, - num_defunct: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnableToVote, - #[codec(index = 1)] - NoVotes, - #[codec(index = 2)] - TooManyVotes, - #[codec(index = 3)] - MaximumVotesExceeded, - #[codec(index = 4)] - LowBalance, - #[codec(index = 5)] - UnableToPayBond, - #[codec(index = 6)] - MustBeVoter, - #[codec(index = 7)] - DuplicatedCandidate, - #[codec(index = 8)] - TooManyCandidates, - #[codec(index = 9)] - MemberSubmit, - #[codec(index = 10)] - RunnerUpSubmit, - #[codec(index = 11)] - InsufficientCandidateFunds, - #[codec(index = 12)] - NotMember, - #[codec(index = 13)] - InvalidWitnessData, - #[codec(index = 14)] - InvalidVoteCount, - #[codec(index = 15)] - InvalidRenouncing, - #[codec(index = 16)] - InvalidReplacement, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewTerm { - new_members: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - )>, - }, - #[codec(index = 1)] - EmptyTerm, - #[codec(index = 2)] - ElectionError, - #[codec(index = 3)] - MemberKicked { member: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - Renounced { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - CandidateSlashed { - candidate: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - SeatHolderSlashed { - seat_holder: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Renouncing { - #[codec(index = 0)] - Member, - #[codec(index = 1)] - RunnerUp, - #[codec(index = 2)] - Candidate(#[codec(compact)] ::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SeatHolder<_0, _1> { - pub who: _0, - pub stake: _1, - pub deposit: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Voter<_0, _1> { - pub votes: ::std::vec::Vec<_0>, - pub stake: _1, - pub deposit: _1, - } - } - pub mod pallet_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - note_stalled { - delay: ::core::primitive::u32, - best_finalized_block_number: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PauseFailed, - #[codec(index = 1)] - ResumeFailed, - #[codec(index = 2)] - ChangePending, - #[codec(index = 3)] - TooSoon, - #[codec(index = 4)] - InvalidKeyOwnershipProof, - #[codec(index = 5)] - InvalidEquivocationProof, - #[codec(index = 6)] - DuplicateOffenceReport, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewAuthorities { - authority_set: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - }, - #[codec(index = 1)] - Paused, - #[codec(index = 2)] - Resumed, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredPendingChange<_0> { - pub scheduled_at: _0, - pub delay: _0, - pub next_authorities: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub forced: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StoredState<_0> { - #[codec(index = 0)] - Live, - #[codec(index = 1)] - PendingPause { scheduled_at: _0, delay: _0 }, - #[codec(index = 2)] - Paused, - #[codec(index = 3)] - PendingResume { scheduled_at: _0, delay: _0 }, - } - } - pub mod pallet_identity { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_registrar { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - set_identity { - info: - ::std::boxed::Box, - }, - #[codec(index = 2)] - set_subs { - subs: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_identity::types::Data, - )>, - }, - #[codec(index = 3)] - clear_identity, - #[codec(index = 4)] - request_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - #[codec(compact)] - max_fee: ::core::primitive::u128, - }, - #[codec(index = 5)] - cancel_request { reg_index: ::core::primitive::u32 }, - #[codec(index = 6)] - set_fee { - #[codec(compact)] - index: ::core::primitive::u32, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 7)] - set_account_id { - #[codec(compact)] - index: ::core::primitive::u32, - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 8)] - set_fields { - #[codec(compact)] - index: ::core::primitive::u32, - fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - }, - #[codec(index = 9)] - provide_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - judgement: runtime_types::pallet_identity::types::Judgement< - ::core::primitive::u128, - >, - identity: ::subxt::utils::H256, - }, - #[codec(index = 10)] - kill_identity { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 11)] - add_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 12)] - rename_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 13)] - remove_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 14)] - quit_sub, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManySubAccounts, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotNamed, - #[codec(index = 3)] - EmptyIndex, - #[codec(index = 4)] - FeeChanged, - #[codec(index = 5)] - NoIdentity, - #[codec(index = 6)] - StickyJudgement, - #[codec(index = 7)] - JudgementGiven, - #[codec(index = 8)] - InvalidJudgement, - #[codec(index = 9)] - InvalidIndex, - #[codec(index = 10)] - InvalidTarget, - #[codec(index = 11)] - TooManyFields, - #[codec(index = 12)] - TooManyRegistrars, - #[codec(index = 13)] - AlreadyClaimed, - #[codec(index = 14)] - NotSub, - #[codec(index = 15)] - NotOwned, - #[codec(index = 16)] - JudgementForDifferentIdentity, - #[codec(index = 17)] - JudgementPaymentFailed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IdentitySet { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - IdentityCleared { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 2)] - IdentityKilled { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 3)] - JudgementRequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 4)] - JudgementUnrequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 5)] - JudgementGiven { - target: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - RegistrarAdded { registrar_index: ::core::primitive::u32 }, - #[codec(index = 7)] - SubIdentityAdded { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 8)] - SubIdentityRemoved { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 9)] - SubIdentityRevoked { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct BitFlags<_0>( - pub ::core::primitive::u64, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Data { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Raw0([::core::primitive::u8; 0usize]), - #[codec(index = 2)] - Raw1([::core::primitive::u8; 1usize]), - #[codec(index = 3)] - Raw2([::core::primitive::u8; 2usize]), - #[codec(index = 4)] - Raw3([::core::primitive::u8; 3usize]), - #[codec(index = 5)] - Raw4([::core::primitive::u8; 4usize]), - #[codec(index = 6)] - Raw5([::core::primitive::u8; 5usize]), - #[codec(index = 7)] - Raw6([::core::primitive::u8; 6usize]), - #[codec(index = 8)] - Raw7([::core::primitive::u8; 7usize]), - #[codec(index = 9)] - Raw8([::core::primitive::u8; 8usize]), - #[codec(index = 10)] - Raw9([::core::primitive::u8; 9usize]), - #[codec(index = 11)] - Raw10([::core::primitive::u8; 10usize]), - #[codec(index = 12)] - Raw11([::core::primitive::u8; 11usize]), - #[codec(index = 13)] - Raw12([::core::primitive::u8; 12usize]), - #[codec(index = 14)] - Raw13([::core::primitive::u8; 13usize]), - #[codec(index = 15)] - Raw14([::core::primitive::u8; 14usize]), - #[codec(index = 16)] - Raw15([::core::primitive::u8; 15usize]), - #[codec(index = 17)] - Raw16([::core::primitive::u8; 16usize]), - #[codec(index = 18)] - Raw17([::core::primitive::u8; 17usize]), - #[codec(index = 19)] - Raw18([::core::primitive::u8; 18usize]), - #[codec(index = 20)] - Raw19([::core::primitive::u8; 19usize]), - #[codec(index = 21)] - Raw20([::core::primitive::u8; 20usize]), - #[codec(index = 22)] - Raw21([::core::primitive::u8; 21usize]), - #[codec(index = 23)] - Raw22([::core::primitive::u8; 22usize]), - #[codec(index = 24)] - Raw23([::core::primitive::u8; 23usize]), - #[codec(index = 25)] - Raw24([::core::primitive::u8; 24usize]), - #[codec(index = 26)] - Raw25([::core::primitive::u8; 25usize]), - #[codec(index = 27)] - Raw26([::core::primitive::u8; 26usize]), - #[codec(index = 28)] - Raw27([::core::primitive::u8; 27usize]), - #[codec(index = 29)] - Raw28([::core::primitive::u8; 28usize]), - #[codec(index = 30)] - Raw29([::core::primitive::u8; 29usize]), - #[codec(index = 31)] - Raw30([::core::primitive::u8; 30usize]), - #[codec(index = 32)] - Raw31([::core::primitive::u8; 31usize]), - #[codec(index = 33)] - Raw32([::core::primitive::u8; 32usize]), - #[codec(index = 34)] - BlakeTwo256([::core::primitive::u8; 32usize]), - #[codec(index = 35)] - Sha256([::core::primitive::u8; 32usize]), - #[codec(index = 36)] - Keccak256([::core::primitive::u8; 32usize]), - #[codec(index = 37)] - ShaThree256([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum IdentityField { - #[codec(index = 1)] - Display, - #[codec(index = 2)] - Legal, - #[codec(index = 4)] - Web, - #[codec(index = 8)] - Riot, - #[codec(index = 16)] - Email, - #[codec(index = 32)] - PgpFingerprint, - #[codec(index = 64)] - Image, - #[codec(index = 128)] - Twitter, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdentityInfo { - pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::pallet_identity::types::Data, - runtime_types::pallet_identity::types::Data, - )>, - pub display: runtime_types::pallet_identity::types::Data, - pub legal: runtime_types::pallet_identity::types::Data, - pub web: runtime_types::pallet_identity::types::Data, - pub riot: runtime_types::pallet_identity::types::Data, - pub email: runtime_types::pallet_identity::types::Data, - pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, - pub image: runtime_types::pallet_identity::types::Data, - pub twitter: runtime_types::pallet_identity::types::Data, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Judgement<_0> { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - FeePaid(_0), - #[codec(index = 2)] - Reasonable, - #[codec(index = 3)] - KnownGood, - #[codec(index = 4)] - OutOfDate, - #[codec(index = 5)] - LowQuality, - #[codec(index = 6)] - Erroneous, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RegistrarInfo<_0, _1> { - pub account: _1, - pub fee: _0, - pub fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0> { - pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::core::primitive::u32, - runtime_types::pallet_identity::types::Judgement<_0>, - )>, - pub deposit: _0, - pub info: runtime_types::pallet_identity::types::IdentityInfo, - } - } - } - pub mod pallet_im_online { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - heartbeat { - heartbeat: - runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, - signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidKey, - #[codec(index = 1)] - DuplicatedHeartbeat, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - HeartbeatReceived { - authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - }, - #[codec(index = 1)] - AllGood, - #[codec(index = 2)] - SomeOffline { offline: ::std::vec::Vec<(::sp_core::crypto::AccountId32, ())> }, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedOpaqueNetworkState { - pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - pub external_addresses: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Heartbeat<_0> { - pub block_number: _0, - pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, - pub session_index: _0, - pub authority_index: _0, - pub validators_len: _0, - } - } - pub mod pallet_indices { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { index: ::core::primitive::u32 }, - #[codec(index = 1)] - transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - }, - #[codec(index = 2)] - free { index: ::core::primitive::u32 }, - #[codec(index = 3)] - force_transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - freeze: ::core::primitive::bool, - }, - #[codec(index = 4)] - freeze { index: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAssigned, - #[codec(index = 1)] - NotOwner, - #[codec(index = 2)] - InUse, - #[codec(index = 3)] - NotTransfer, - #[codec(index = 4)] - Permanent, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IndexAssigned { - who: ::sp_core::crypto::AccountId32, - index: ::core::primitive::u32, - }, - #[codec(index = 1)] - IndexFreed { index: ::core::primitive::u32 }, - #[codec(index = 2)] - IndexFrozen { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - }, - } - } - } - pub mod pallet_membership { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - remove_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - swap_member { - remove: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - add: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - reset_members { members: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 4)] - change_key { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - set_prime { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - clear_prime, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AlreadyMember, - #[codec(index = 1)] - NotMember, - #[codec(index = 2)] - TooManyMembers, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - MemberAdded, - #[codec(index = 1)] - MemberRemoved, - #[codec(index = 2)] - MembersSwapped, - #[codec(index = 3)] - MembersReset, - #[codec(index = 4)] - KeyChanged, - #[codec(index = 5)] - Dummy, - } - } - } - pub mod pallet_message_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotReapable, - #[codec(index = 1)] - NoPage, - #[codec(index = 2)] - NoMessage, - #[codec(index = 3)] - AlreadyProcessed, - #[codec(index = 4)] - Queued, - #[codec(index = 5)] - InsufficientWeight, - #[codec(index = 6)] - TemporarilyUnprocessable, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BookState<_0> { - pub begin: ::core::primitive::u32, - pub end: ::core::primitive::u32, - pub count: ::core::primitive::u32, - pub ready_neighbours: - ::core::option::Option>, - pub message_count: ::core::primitive::u64, - pub size: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Neighbours<_0> { - pub prev: _0, - pub next: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Page<_0> { - pub remaining: _0, - pub remaining_size: _0, - pub first_index: _0, - pub first: _0, - pub last: _0, - pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: _0, - } - } - pub mod pallet_nis { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bid<_0, _1> { - pub amount: _0, - pub who: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - place_bid { - #[codec(compact)] - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 1)] - retract_bid { - #[codec(compact)] - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 2)] - fund_deficit, - #[codec(index = 3)] - thaw_private { - #[codec(compact)] - index: ::core::primitive::u32, - maybe_proportion: ::core::option::Option< - runtime_types::sp_arithmetic::per_things::Perquintill, - >, - }, - #[codec(index = 4)] - thaw_communal { - #[codec(compact)] - index: ::core::primitive::u32, - }, - #[codec(index = 5)] - communify { - #[codec(compact)] - index: ::core::primitive::u32, - }, - #[codec(index = 6)] - privatize { - #[codec(compact)] - index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DurationTooSmall, - #[codec(index = 1)] - DurationTooBig, - #[codec(index = 2)] - AmountTooSmall, - #[codec(index = 3)] - BidTooLow, - #[codec(index = 4)] - UnknownReceipt, - #[codec(index = 5)] - NotOwner, - #[codec(index = 6)] - NotExpired, - #[codec(index = 7)] - UnknownBid, - #[codec(index = 8)] - PortionTooBig, - #[codec(index = 9)] - Unfunded, - #[codec(index = 10)] - AlreadyFunded, - #[codec(index = 11)] - Throttled, - #[codec(index = 12)] - MakesDust, - #[codec(index = 13)] - AlreadyCommunal, - #[codec(index = 14)] - AlreadyPrivate, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BidPlaced { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 1)] - BidRetracted { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 2)] - BidDropped { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - duration: ::core::primitive::u32, - }, - #[codec(index = 3)] - Issued { - index: ::core::primitive::u32, - expiry: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - proportion: runtime_types::sp_arithmetic::per_things::Perquintill, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - Thawed { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - proportion: runtime_types::sp_arithmetic::per_things::Perquintill, - amount: ::core::primitive::u128, - dropped: ::core::primitive::bool, - }, - #[codec(index = 5)] - Funded { deficit: ::core::primitive::u128 }, - #[codec(index = 6)] - Transferred { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum HoldReason { - #[codec(index = 0)] - NftReceipt, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReceiptRecord<_0, _1, _2> { - pub proportion: runtime_types::sp_arithmetic::per_things::Perquintill, - pub owner: ::core::option::Option<(_0, _2)>, - pub expiry: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SummaryRecord<_0, _1> { - pub proportion_owed: runtime_types::sp_arithmetic::per_things::Perquintill, - pub index: _0, - pub thawed: runtime_types::sp_arithmetic::per_things::Perquintill, - pub last_period: _0, - pub receipts_on_hold: _1, - } - } - } - pub mod pallet_offences { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Offence { - kind: [::core::primitive::u8; 16usize], - timeslot: ::std::vec::Vec<::core::primitive::u8>, - }, - } - } - } - pub mod pallet_preimage { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - unnote_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - request_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 3)] - unrequest_preimage { hash: ::subxt::utils::H256 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooBig, - #[codec(index = 1)] - AlreadyNoted, - #[codec(index = 2)] - NotAuthorized, - #[codec(index = 3)] - NotNoted, - #[codec(index = 4)] - Requested, - #[codec(index = 5)] - NotRequested, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Noted { hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - Requested { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - Cleared { hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RequestStatus<_0, _1> { - #[codec(index = 0)] - Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, - #[codec(index = 1)] - Requested { - deposit: ::core::option::Option<(_0, _1)>, - count: ::core::primitive::u32, - len: ::core::option::Option<::core::primitive::u32>, - }, - } - } - pub mod pallet_proxy { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - proxy { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - add_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::rococo_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 2)] - remove_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::rococo_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 3)] - remove_proxies, - #[codec(index = 4)] - create_pure { - proxy_type: runtime_types::rococo_runtime::ProxyType, - delay: ::core::primitive::u32, - index: ::core::primitive::u16, - }, - #[codec(index = 5)] - kill_pure { - spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::rococo_runtime::ProxyType, - index: ::core::primitive::u16, - #[codec(compact)] - height: ::core::primitive::u32, - #[codec(compact)] - ext_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - announce { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 7)] - remove_announcement { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 8)] - reject_announcement { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 9)] - proxy_announced { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooMany, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotProxy, - #[codec(index = 3)] - Unproxyable, - #[codec(index = 4)] - Duplicate, - #[codec(index = 5)] - NoPermission, - #[codec(index = 6)] - Unannounced, - #[codec(index = 7)] - NoSelfProxy, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ProxyExecuted { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - PureCreated { - pure: ::sp_core::crypto::AccountId32, - who: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::rococo_runtime::ProxyType, - disambiguation_index: ::core::primitive::u16, - }, - #[codec(index = 2)] - Announced { - real: ::sp_core::crypto::AccountId32, - proxy: ::sp_core::crypto::AccountId32, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - ProxyAdded { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::rococo_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 4)] - ProxyRemoved { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::rococo_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Announcement<_0, _1, _2> { - pub real: _0, - pub call_hash: _1, - pub height: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ProxyDefinition<_0, _1, _2> { - pub delegate: _0, - pub proxy_type: _1, - pub delay: _2, - } - } - pub mod pallet_recovery { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_recovered { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - set_recovered { - lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - create_recovery { - friends: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - threshold: ::core::primitive::u16, - delay_period: ::core::primitive::u32, - }, - #[codec(index = 3)] - initiate_recovery { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - vouch_recovery { - lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - claim_recovery { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - close_recovery { - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 7)] - remove_recovery, - #[codec(index = 8)] - cancel_recovered { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAllowed, - #[codec(index = 1)] - ZeroThreshold, - #[codec(index = 2)] - NotEnoughFriends, - #[codec(index = 3)] - MaxFriends, - #[codec(index = 4)] - NotSorted, - #[codec(index = 5)] - NotRecoverable, - #[codec(index = 6)] - AlreadyRecoverable, - #[codec(index = 7)] - AlreadyStarted, - #[codec(index = 8)] - NotStarted, - #[codec(index = 9)] - NotFriend, - #[codec(index = 10)] - DelayPeriod, - #[codec(index = 11)] - AlreadyVouched, - #[codec(index = 12)] - Threshold, - #[codec(index = 13)] - StillActive, - #[codec(index = 14)] - AlreadyProxy, - #[codec(index = 15)] - BadState, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RecoveryCreated { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - RecoveryInitiated { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 2)] - RecoveryVouched { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - sender: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - RecoveryClosed { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 4)] - AccountRecovered { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 5)] - RecoveryRemoved { lost_account: ::sp_core::crypto::AccountId32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ActiveRecovery<_0, _1, _2> { - pub created: _0, - pub deposit: _1, - pub friends: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RecoveryConfig<_0, _1, _2> { - pub delay_period: _0, - pub deposit: _1, - pub friends: _2, - pub threshold: ::core::primitive::u16, - } - } - pub mod pallet_scheduler { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - schedule { - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - schedule_named { - id: [::core::primitive::u8; 32usize], - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 3)] - cancel_named { id: [::core::primitive::u8; 32usize] }, - #[codec(index = 4)] - schedule_after { - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 5)] - schedule_named_after { - id: [::core::primitive::u8; 32usize], - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSchedule, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - TargetBlockNumberInPast, - #[codec(index = 3)] - RescheduleNoChange, - #[codec(index = 4)] - Named, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 1)] - Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - Dispatched { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - CallUnavailable { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 4)] - PeriodicFailed { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 5)] - PermanentlyOverweight { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Scheduled<_0, _1, _2, _3, _4> { - pub maybe_id: ::core::option::Option<_0>, - pub priority: ::core::primitive::u8, - pub call: _1, - pub maybe_periodic: ::core::option::Option<(_2, _2)>, - pub origin: _3, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::rococo_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_society { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - bid { value: ::core::primitive::u128 }, - #[codec(index = 1)] - unbid { pos: ::core::primitive::u32 }, - #[codec(index = 2)] - vouch { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - value: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - #[codec(index = 3)] - unvouch { pos: ::core::primitive::u32 }, - #[codec(index = 4)] - vote { - candidate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - approve: ::core::primitive::bool, - }, - #[codec(index = 5)] - defender_vote { approve: ::core::primitive::bool }, - #[codec(index = 6)] - payout, - #[codec(index = 7)] - found { - founder: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - max_members: ::core::primitive::u32, - rules: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 8)] - unfound, - #[codec(index = 9)] - judge_suspended_member { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - forgive: ::core::primitive::bool, - }, - #[codec(index = 10)] - judge_suspended_candidate { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - judgement: runtime_types::pallet_society::Judgement, - }, - #[codec(index = 11)] - set_max_members { max: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - BadPosition, - #[codec(index = 1)] - NotMember, - #[codec(index = 2)] - AlreadyMember, - #[codec(index = 3)] - Suspended, - #[codec(index = 4)] - NotSuspended, - #[codec(index = 5)] - NoPayout, - #[codec(index = 6)] - AlreadyFounded, - #[codec(index = 7)] - InsufficientPot, - #[codec(index = 8)] - AlreadyVouching, - #[codec(index = 9)] - NotVouching, - #[codec(index = 10)] - Head, - #[codec(index = 11)] - Founder, - #[codec(index = 12)] - AlreadyBid, - #[codec(index = 13)] - AlreadyCandidate, - #[codec(index = 14)] - NotCandidate, - #[codec(index = 15)] - MaxMembers, - #[codec(index = 16)] - NotFounder, - #[codec(index = 17)] - NotHead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Founded { founder: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - Bid { - candidate_id: ::sp_core::crypto::AccountId32, - offer: ::core::primitive::u128, - }, - #[codec(index = 2)] - Vouch { - candidate_id: ::sp_core::crypto::AccountId32, - offer: ::core::primitive::u128, - vouching: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - AutoUnbid { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - Unbid { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Unvouch { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 6)] - Inducted { - primary: ::sp_core::crypto::AccountId32, - candidates: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 7)] - SuspendedMemberJudgement { - who: ::sp_core::crypto::AccountId32, - judged: ::core::primitive::bool, - }, - #[codec(index = 8)] - CandidateSuspended { candidate: ::sp_core::crypto::AccountId32 }, - #[codec(index = 9)] - MemberSuspended { member: ::sp_core::crypto::AccountId32 }, - #[codec(index = 10)] - Challenged { member: ::sp_core::crypto::AccountId32 }, - #[codec(index = 11)] - Vote { - candidate: ::sp_core::crypto::AccountId32, - voter: ::sp_core::crypto::AccountId32, - vote: ::core::primitive::bool, - }, - #[codec(index = 12)] - DefenderVote { - voter: ::sp_core::crypto::AccountId32, - vote: ::core::primitive::bool, - }, - #[codec(index = 13)] - NewMaxMembers { max: ::core::primitive::u32 }, - #[codec(index = 14)] - Unfounded { founder: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Deposit { value: ::core::primitive::u128 }, - #[codec(index = 16)] - SkepticsChosen { skeptics: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bid<_0, _1> { - pub who: _0, - pub kind: runtime_types::pallet_society::BidKind<_0, _1>, - pub value: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BidKind<_0, _1> { - #[codec(index = 0)] - Deposit(_1), - #[codec(index = 1)] - Vouch(_0, _1), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Judgement { - #[codec(index = 0)] - Rebid, - #[codec(index = 1)] - Reject, - #[codec(index = 2)] - Approve, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Vote { - #[codec(index = 0)] - Skeptic, - #[codec(index = 1)] - Reject, - #[codec(index = 2)] - Approve, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VouchingStatus { - #[codec(index = 0)] - Vouching, - #[codec(index = 1)] - Banned, - } - } - pub mod pallet_state_trie_migration { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - control_auto_migration { - maybe_config: ::core::option::Option< - runtime_types::pallet_state_trie_migration::pallet::MigrationLimits, - >, - }, - #[codec(index = 1)] - continue_migrate { - limits: runtime_types::pallet_state_trie_migration::pallet::MigrationLimits, - real_size_upper: ::core::primitive::u32, - witness_task: - runtime_types::pallet_state_trie_migration::pallet::MigrationTask, - }, - #[codec(index = 2)] - migrate_custom_top { - keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - witness_size: ::core::primitive::u32, - }, - #[codec(index = 3)] - migrate_custom_child { - root: ::std::vec::Vec<::core::primitive::u8>, - child_keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, - total_size: ::core::primitive::u32, - }, - #[codec(index = 4)] - set_signed_max_limits { - limits: runtime_types::pallet_state_trie_migration::pallet::MigrationLimits, - }, - #[codec(index = 5)] - force_set_progress { - progress_top: runtime_types::pallet_state_trie_migration::pallet::Progress, - progress_child: - runtime_types::pallet_state_trie_migration::pallet::Progress, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MaxSignedLimits, - #[codec(index = 1)] - KeyTooLong, - #[codec(index = 2)] - NotEnoughFunds, - #[codec(index = 3)] - BadWitness, - #[codec(index = 4)] - SignedMigrationNotAllowed, - #[codec(index = 5)] - BadChildRoot, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Migrated { - top: ::core::primitive::u32, - child: ::core::primitive::u32, - compute: - runtime_types::pallet_state_trie_migration::pallet::MigrationCompute, - }, - #[codec(index = 1)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 2)] - AutoMigrationFinished, - #[codec(index = 3)] - Halted { error: runtime_types::pallet_state_trie_migration::pallet::Error }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MigrationCompute { - #[codec(index = 0)] - Signed, - #[codec(index = 1)] - Auto, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MigrationLimits { - pub size: ::core::primitive::u32, - pub item: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MigrationTask { - pub progress_top: runtime_types::pallet_state_trie_migration::pallet::Progress, - pub progress_child: - runtime_types::pallet_state_trie_migration::pallet::Progress, - pub size: ::core::primitive::u32, - pub top_items: ::core::primitive::u32, - pub child_items: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Progress { - #[codec(index = 0)] - ToStart, - #[codec(index = 1)] - LastKey( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Complete, - } - } - } - pub mod pallet_sudo { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - sudo { call: ::std::boxed::Box }, - #[codec(index = 1)] - sudo_unchecked_weight { - call: ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - set_key { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - sudo_as { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - RequireSudo, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Sudid { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - KeyChanged { - old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 2)] - SudoAsDone { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_tips { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_awesome { - reason: ::std::vec::Vec<::core::primitive::u8>, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - retract_tip { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - tip_new { - reason: ::std::vec::Vec<::core::primitive::u8>, - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - tip_value: ::core::primitive::u128, - }, - #[codec(index = 3)] - tip { - hash: ::subxt::utils::H256, - #[codec(compact)] - tip_value: ::core::primitive::u128, - }, - #[codec(index = 4)] - close_tip { hash: ::subxt::utils::H256 }, - #[codec(index = 5)] - slash_tip { hash: ::subxt::utils::H256 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ReasonTooBig, - #[codec(index = 1)] - AlreadyKnown, - #[codec(index = 2)] - UnknownTip, - #[codec(index = 3)] - NotFinder, - #[codec(index = 4)] - StillOpen, - #[codec(index = 5)] - Premature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewTip { tip_hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - TipClosing { tip_hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - TipClosed { - tip_hash: ::subxt::utils::H256, - who: ::sp_core::crypto::AccountId32, - payout: ::core::primitive::u128, - }, - #[codec(index = 3)] - TipRetracted { tip_hash: ::subxt::utils::H256 }, - #[codec(index = 4)] - TipSlashed { - tip_hash: ::subxt::utils::H256, - finder: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpenTip<_0, _1, _2, _3> { - pub reason: _3, - pub who: _0, - pub finder: _0, - pub deposit: _1, - pub closes: ::core::option::Option<_2>, - pub tips: ::std::vec::Vec<(_0, _1)>, - pub finders_fee: ::core::primitive::bool, - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_treasury { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - propose_spend { - #[codec(compact)] - value: ::core::primitive::u128, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - reject_proposal { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - #[codec(index = 2)] - approve_proposal { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - #[codec(index = 3)] - spend { - #[codec(compact)] - amount: ::core::primitive::u128, - beneficiary: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - remove_approval { - #[codec(compact)] - proposal_id: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InsufficientProposersBalance, - #[codec(index = 1)] - InvalidIndex, - #[codec(index = 2)] - TooManyApprovals, - #[codec(index = 3)] - InsufficientPermission, - #[codec(index = 4)] - ProposalNotApproved, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Proposed { proposal_index: ::core::primitive::u32 }, - #[codec(index = 1)] - Spending { budget_remaining: ::core::primitive::u128 }, - #[codec(index = 2)] - Awarded { - proposal_index: ::core::primitive::u32, - award: ::core::primitive::u128, - account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Rejected { - proposal_index: ::core::primitive::u32, - slashed: ::core::primitive::u128, - }, - #[codec(index = 4)] - Burnt { burnt_funds: ::core::primitive::u128 }, - #[codec(index = 5)] - Rollover { rollover_balance: ::core::primitive::u128 }, - #[codec(index = 6)] - Deposit { value: ::core::primitive::u128 }, - #[codec(index = 7)] - SpendApproved { - proposal_index: ::core::primitive::u32, - amount: ::core::primitive::u128, - beneficiary: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - UpdatedInactive { - reactivated: ::core::primitive::u128, - deactivated: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Proposal<_0, _1> { - pub proposer: _0, - pub value: _1, - pub beneficiary: _0, - pub bond: _1, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { calls: ::std::vec::Vec }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box, - }, - #[codec(index = 2)] - batch_all { calls: ::std::vec::Vec }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box, - call: ::std::boxed::Box, - }, - #[codec(index = 4)] - force_batch { - calls: ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_vesting { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vest, - #[codec(index = 1)] - vest_other { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - vested_transfer { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 3)] - force_vested_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 4)] - merge_schedules { - schedule1_index: ::core::primitive::u32, - schedule2_index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotVesting, - #[codec(index = 1)] - AtMaxVestingSchedules, - #[codec(index = 2)] - AmountLow, - #[codec(index = 3)] - ScheduleIndexOutOfBounds, - #[codec(index = 4)] - InvalidScheduleParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - VestingUpdated { - account: ::sp_core::crypto::AccountId32, - unvested: ::core::primitive::u128, - }, - #[codec(index = 1)] - VestingCompleted { account: ::sp_core::crypto::AccountId32 }, - } - } - pub mod vesting_info { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VestingInfo<_0, _1> { - pub locked: _0, - pub per_block: _0, - pub starting_block: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V0, - #[codec(index = 1)] - V1, - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - xcm_version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted(runtime_types::xcm::v3::traits::Outcome), - #[codec(index = 1)] - Sent( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::Xcm, - ), - #[codec(index = 2)] - UnexpectedResponse( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 3)] - ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), - #[codec(index = 4)] - Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), - #[codec(index = 5)] - NotifyOverweight( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ::sp_weights::Weight, - ::sp_weights::Weight, - ), - #[codec(index = 6)] - NotifyDispatchError( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 7)] - NotifyDecodeFailed( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 8)] - InvalidResponder( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 9)] - InvalidResponderVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 10)] - ResponseTaken(::core::primitive::u64), - #[codec(index = 11)] - AssetsTrapped( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - #[codec(index = 12)] - VersionChangeNotified( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 13)] - SupportedVersionChanged( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - ), - #[codec(index = 14)] - NotifyTargetSendFail( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::traits::Error, - ), - #[codec(index = 15)] - NotifyTargetMigrationFail( - runtime_types::xcm::VersionedMultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 16)] - InvalidQuerierVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 17)] - InvalidQuerier( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 18)] - VersionNotifyStarted( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 19)] - VersionNotifyRequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 20)] - VersionNotifyUnrequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 21)] - FeesPaid( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 22)] - AssetsClaimed( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Response(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedMultiLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateHash(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelId { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub recipient: runtime_types::polkadot_parachain::primitives::Id, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCodeHash(pub ::subxt::utils::H256); - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v4 { - use super::runtime_types; - pub mod assignment_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod collator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - pub mod executor_params { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ExecutorParam { - #[codec(index = 1)] - MaxMemoryPages(::core::primitive::u32), - #[codec(index = 2)] - StackLogicalMax(::core::primitive::u32), - #[codec(index = 3)] - StackNativeMax(::core::primitive::u32), - #[codec(index = 4)] - PrecheckingMaxMemory(::core::primitive::u64), - #[codec(index = 5)] - PvfPrepTimeout( - runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 6)] - PvfExecTimeout( - runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 7)] - WasmExtBulkMemory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutorParams( - pub ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, - >, - ); - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedSigned<_0, _1> { - pub payload: _0, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - pub signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, - } - } - pub mod validator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfield( - pub ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BackedCandidate<_0> { - pub candidate: - runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, - pub validity_votes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::ValidityAttestation, - >, - pub validator_indices: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateCommitments<_0> { - pub upward_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::std::vec::Vec<::core::primitive::u8>, - >, - pub horizontal_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain::primitives::Id, - >, - >, - pub new_validation_code: ::core::option::Option< - runtime_types::polkadot_parachain::primitives::ValidationCode, - >, - pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, - pub processed_downward_messages: _0, - pub hrmp_watermark: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateDescriptor<_0> { - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub relay_parent: _0, - pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, - pub persisted_validation_data_hash: _0, - pub pov_hash: _0, - pub erasure_root: _0, - pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, - pub para_head: _0, - pub validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments_hash: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommittedCandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< - ::core::primitive::u32, - >, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct CoreIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum CoreOccupied { - #[codec(index = 0)] - Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), - #[codec(index = 1)] - Parachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeState<_0> { - pub validators_for: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub validators_against: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub start: _0, - pub concluded_at: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeStatement { - #[codec(index = 0)] - Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), - #[codec(index = 1)] - Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeStatementSet { - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub session: ::core::primitive::u32, - pub statements: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::DisputeStatement, - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Signature, - )>, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct GroupIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndexedVec<_0, _1>( - pub ::std::vec::Vec<_1>, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData<_0> { - pub bitfields: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - >, - >, - pub backed_candidates: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::BackedCandidate< - ::subxt::utils::H256, - >, - >, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - pub parent_header: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaim( - pub runtime_types::polkadot_parachain::primitives::Id, - pub runtime_types::polkadot_primitives::v4::collator_app::Public, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadEntry { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, - pub retries: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckStatement { - pub accept: ::core::primitive::bool, - pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - pub session_index: ::core::primitive::u32, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfExecTimeoutKind { - #[codec(index = 0)] - Backing, - #[codec(index = 1)] - Approval, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfPrepTimeoutKind { - #[codec(index = 0)] - Precheck, - #[codec(index = 1)] - Lenient, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ScrapedOnChainVotes<_0> { - pub session: ::core::primitive::u32, - pub backing_validators_per_candidate: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, - ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::ValidityAttestation, - )>, - )>, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionInfo { - pub active_validator_indices: - ::std::vec::Vec, - pub random_seed: [::core::primitive::u8; 32usize], - pub dispute_period: ::core::primitive::u32, - pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub discovery_keys: - ::std::vec::Vec, - pub assignment_keys: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::assignment_app::Public, - >, - pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::GroupIndex, - ::std::vec::Vec, - >, - pub n_cores: ::core::primitive::u32, - pub zeroth_delay_tranche_width: ::core::primitive::u32, - pub relay_vrf_modulo_samples: ::core::primitive::u32, - pub n_delay_tranches: ::core::primitive::u32, - pub no_show_slots: ::core::primitive::u32, - pub needed_approvals: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - #[codec(index = 1)] - BackingSeconded(::subxt::utils::H256), - #[codec(index = 2)] - BackingValid(::subxt::utils::H256), - #[codec(index = 3)] - ApprovalChecking, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ValidatorIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidityAttestation { - #[codec(index = 1)] - Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - #[codec(index = 2)] - Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - } - } - pub mod vstaging { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - } - pub mod polkadot_runtime_common { - use super::runtime_types; - pub mod assigned_slots { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] assign_perm_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , # [codec (index = 1)] assign_temp_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , lease_period_start : runtime_types :: polkadot_runtime_common :: assigned_slots :: SlotLeasePeriodStart , } , # [codec (index = 2)] unassign_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaDoesntExist, - #[codec(index = 1)] - NotParathread, - #[codec(index = 2)] - CannotUpgrade, - #[codec(index = 3)] - CannotDowngrade, - #[codec(index = 4)] - SlotAlreadyAssigned, - #[codec(index = 5)] - SlotNotAssigned, - #[codec(index = 6)] - OngoingLeaseExists, - #[codec(index = 7)] - MaxPermanentSlotsExceeded, - #[codec(index = 8)] - MaxTemporarySlotsExceeded, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - PermanentSlotAssigned(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - TemporarySlotAssigned(runtime_types::polkadot_parachain::primitives::Id), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainTemporarySlot<_0, _1> { - pub manager: _0, - pub period_begin: _1, - pub period_count: _1, - pub last_lease: ::core::option::Option<_1>, - pub lease_count: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SlotLeasePeriodStart { - #[codec(index = 0)] - Current, - #[codec(index = 1)] - Next, - } - } - pub mod auctions { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - new_auction { - #[codec(compact)] - duration: ::core::primitive::u32, - #[codec(compact)] - lease_period_index: ::core::primitive::u32, - }, - #[codec(index = 1)] - bid { - #[codec(compact)] - para: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - auction_index: ::core::primitive::u32, - #[codec(compact)] - first_slot: ::core::primitive::u32, - #[codec(compact)] - last_slot: ::core::primitive::u32, - #[codec(compact)] - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - cancel_auction, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AuctionInProgress, - #[codec(index = 1)] - LeasePeriodInPast, - #[codec(index = 2)] - ParaNotRegistered, - #[codec(index = 3)] - NotCurrentAuction, - #[codec(index = 4)] - NotAuction, - #[codec(index = 5)] - AuctionEnded, - #[codec(index = 6)] - AlreadyLeasedOut, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - AuctionStarted { - auction_index: ::core::primitive::u32, - lease_period: ::core::primitive::u32, - ending: ::core::primitive::u32, - }, - #[codec(index = 1)] - AuctionClosed { auction_index: ::core::primitive::u32 }, - #[codec(index = 2)] - Reserved { - bidder: ::sp_core::crypto::AccountId32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unreserved { - bidder: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - ReserveConfiscated { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - BidAccepted { - bidder: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - first_slot: ::core::primitive::u32, - last_slot: ::core::primitive::u32, - }, - #[codec(index = 6)] - WinningOffset { - auction_index: ::core::primitive::u32, - block_number: ::core::primitive::u32, - }, - } - } - } - pub mod claims { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { - dest: ::sp_core::crypto::AccountId32, - ethereum_signature: - runtime_types::polkadot_runtime_common::claims::EcdsaSignature, - }, - #[codec(index = 1)] - mint_claim { - who: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - value: ::core::primitive::u128, - vesting_schedule: ::core::option::Option<( - ::core::primitive::u128, - ::core::primitive::u128, - ::core::primitive::u32, - )>, - statement: ::core::option::Option< - runtime_types::polkadot_runtime_common::claims::StatementKind, - >, - }, - #[codec(index = 2)] - claim_attest { - dest: ::sp_core::crypto::AccountId32, - ethereum_signature: - runtime_types::polkadot_runtime_common::claims::EcdsaSignature, - statement: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 3)] - attest { statement: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - move_claim { - old: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - new: runtime_types::polkadot_runtime_common::claims::EthereumAddress, - maybe_preclaim: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEthereumSignature, - #[codec(index = 1)] - SignerHasNoClaim, - #[codec(index = 2)] - SenderHasNoClaim, - #[codec(index = 3)] - PotUnderflow, - #[codec(index = 4)] - InvalidStatement, - #[codec(index = 5)] - VestedBalanceExists, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Claimed { - who: ::sp_core::crypto::AccountId32, - ethereum_address: - runtime_types::polkadot_runtime_common::claims::EthereumAddress, - amount: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EcdsaSignature(pub [::core::primitive::u8; 65usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EthereumAddress(pub [::core::primitive::u8; 20usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StatementKind { - #[codec(index = 0)] - Regular, - #[codec(index = 1)] - Saft, - } - } - pub mod crowdloan { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - create { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 1)] - contribute { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - value: ::core::primitive::u128, - signature: - ::core::option::Option, - }, - #[codec(index = 2)] - withdraw { - who: ::sp_core::crypto::AccountId32, - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 3)] - refund { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - dissolve { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - edit { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 6)] - add_memo { - index: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 7)] - poke { index: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - contribute_all { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - signature: - ::core::option::Option, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FirstPeriodInPast, - #[codec(index = 1)] - FirstPeriodTooFarInFuture, - #[codec(index = 2)] - LastPeriodBeforeFirstPeriod, - #[codec(index = 3)] - LastPeriodTooFarInFuture, - #[codec(index = 4)] - CannotEndInPast, - #[codec(index = 5)] - EndTooFarInFuture, - #[codec(index = 6)] - Overflow, - #[codec(index = 7)] - ContributionTooSmall, - #[codec(index = 8)] - InvalidParaId, - #[codec(index = 9)] - CapExceeded, - #[codec(index = 10)] - ContributionPeriodOver, - #[codec(index = 11)] - InvalidOrigin, - #[codec(index = 12)] - NotParachain, - #[codec(index = 13)] - LeaseActive, - #[codec(index = 14)] - BidOrLeaseActive, - #[codec(index = 15)] - FundNotEnded, - #[codec(index = 16)] - NoContributions, - #[codec(index = 17)] - NotReadyToDissolve, - #[codec(index = 18)] - InvalidSignature, - #[codec(index = 19)] - MemoTooLarge, - #[codec(index = 20)] - AlreadyInNewRaise, - #[codec(index = 21)] - VrfDelayInProgress, - #[codec(index = 22)] - NoLeasePeriod, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 1)] - Contributed { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Withdrew { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - PartiallyRefunded { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 6)] - HandleBidResult { - para_id: runtime_types::polkadot_parachain::primitives::Id, - result: ::core::result::Result< - (), - runtime_types::sp_runtime::DispatchError, - >, - }, - #[codec(index = 7)] - Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - MemoUpdated { - who: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 9)] - AddedToNewRaise { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FundInfo<_0, _1, _2, _3> { - pub depositor: _0, - pub verifier: ::core::option::Option, - pub deposit: _1, - pub raised: _1, - pub end: _2, - pub cap: _1, - pub last_contribution: - runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, - pub first_period: _2, - pub last_period: _2, - pub fund_index: _2, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum LastContribution<_0> { - #[codec(index = 0)] - Never, - #[codec(index = 1)] - PreEnding(_0), - #[codec(index = 2)] - Ending(_0), - } - } - pub mod paras_registrar { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register { - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_register { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 2)] - deregister { id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 3)] - swap { - id: runtime_types::polkadot_parachain::primitives::Id, - other: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - reserve, - #[codec(index = 6)] - add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 7)] - schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 8)] - set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - AlreadyRegistered, - #[codec(index = 2)] - NotOwner, - #[codec(index = 3)] - CodeTooLarge, - #[codec(index = 4)] - HeadDataTooLarge, - #[codec(index = 5)] - NotParachain, - #[codec(index = 6)] - NotParathread, - #[codec(index = 7)] - CannotDeregister, - #[codec(index = 8)] - CannotDowngrade, - #[codec(index = 9)] - CannotUpgrade, - #[codec(index = 10)] - ParaLocked, - #[codec(index = 11)] - NotReserved, - #[codec(index = 12)] - EmptyCode, - #[codec(index = 13)] - CannotSwap, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Registered { - para_id: runtime_types::polkadot_parachain::primitives::Id, - manager: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 1)] - Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - Reserved { - para_id: runtime_types::polkadot_parachain::primitives::Id, - who: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Swapped { - para_id: runtime_types::polkadot_parachain::primitives::Id, - other_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo<_0, _1> { - pub manager: _0, - pub deposit: _1, - pub locked: ::core::primitive::bool, - } - } - pub mod paras_sudo_wrapper { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - sudo_schedule_para_initialize { - id: runtime_types::polkadot_parachain::primitives::Id, - genesis: - runtime_types::polkadot_runtime_parachains::paras::ParaGenesisArgs, - }, - #[codec(index = 1)] - sudo_schedule_para_cleanup { - id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 2)] - sudo_schedule_parathread_upgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 3)] - sudo_schedule_parachain_downgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - sudo_queue_downward_xcm { - id: runtime_types::polkadot_parachain::primitives::Id, - xcm: ::std::boxed::Box, - }, - #[codec(index = 5)] - sudo_establish_hrmp_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - recipient: runtime_types::polkadot_parachain::primitives::Id, - max_capacity: ::core::primitive::u32, - max_message_size: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaDoesntExist, - #[codec(index = 1)] - ParaAlreadyExists, - #[codec(index = 2)] - ExceedsMaxMessageSize, - #[codec(index = 3)] - CouldntCleanup, - #[codec(index = 4)] - NotParathread, - #[codec(index = 5)] - NotParachain, - #[codec(index = 6)] - CannotUpgrade, - #[codec(index = 7)] - CannotDowngrade, - } - } - } - pub mod slots { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_lease { - para: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - }, - #[codec(index = 1)] - clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaNotOnboarding, - #[codec(index = 1)] - LeaseError, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewLeasePeriod { lease_period: ::core::primitive::u32 }, - #[codec(index = 1)] - Leased { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - } - } - } - } - pub mod polkadot_runtime_parachains { - use super::runtime_types; - pub mod configuration { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidNewValue, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HostConfiguration<_0> { - pub max_code_size: _0, - pub max_head_data_size: _0, - pub max_upward_queue_count: _0, - pub max_upward_queue_size: _0, - pub max_upward_message_size: _0, - pub max_upward_message_num_per_candidate: _0, - pub hrmp_max_message_num_per_candidate: _0, - pub validation_upgrade_cooldown: _0, - pub validation_upgrade_delay: _0, - pub async_backing_params: - runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, - pub max_pov_size: _0, - pub max_downward_message_size: _0, - pub hrmp_max_parachain_outbound_channels: _0, - pub hrmp_max_parathread_outbound_channels: _0, - pub hrmp_sender_deposit: ::core::primitive::u128, - pub hrmp_recipient_deposit: ::core::primitive::u128, - pub hrmp_channel_max_capacity: _0, - pub hrmp_channel_max_total_size: _0, - pub hrmp_max_parachain_inbound_channels: _0, - pub hrmp_max_parathread_inbound_channels: _0, - pub hrmp_channel_max_message_size: _0, - pub executor_params: - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, - pub code_retention_period: _0, - pub parathread_cores: _0, - pub parathread_retries: _0, - pub group_rotation_frequency: _0, - pub chain_availability_period: _0, - pub thread_availability_period: _0, - pub scheduling_lookahead: _0, - pub max_validators_per_core: ::core::option::Option<_0>, - pub max_validators: ::core::option::Option<_0>, - pub dispute_period: _0, - pub dispute_post_conclusion_acceptance_period: _0, - pub no_show_slots: _0, - pub n_delay_tranches: _0, - pub zeroth_delay_tranche_width: _0, - pub needed_approvals: _0, - pub relay_vrf_modulo_samples: _0, - pub pvf_checking_enabled: ::core::primitive::bool, - pub pvf_voting_ttl: _0, - pub minimum_validation_upgrade_delay: _0, - } - } - pub mod disputes { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_unfreeze, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateDisputeStatementSets, - #[codec(index = 1)] - AncientDisputeStatement, - #[codec(index = 2)] - ValidatorIndexOutOfBounds, - #[codec(index = 3)] - InvalidSignature, - #[codec(index = 4)] - DuplicateStatement, - #[codec(index = 5)] - SingleSidedDispute, - #[codec(index = 6)] - MaliciousBacker, - #[codec(index = 7)] - MissingBackingVotes, - #[codec(index = 8)] - UnconfirmedDispute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - DisputeInitiated( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, - ), - #[codec(index = 1)] - DisputeConcluded( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, - ), - #[codec(index = 2)] - Revert(::core::primitive::u32), - } - } - pub mod slashing { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Call { - # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Error { - #[codec(index = 0)] - InvalidKeyOwnershipProof, - #[codec(index = 1)] - InvalidSessionIndex, - #[codec(index = 2)] - InvalidCandidateHash, - #[codec(index = 3)] - InvalidValidatorIndex, - #[codec(index = 4)] - ValidatorIndexIdMismatch, - #[codec(index = 5)] - DuplicateSlashingReport, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputesTimeSlot { - pub session_index: ::core::primitive::u32, - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SlashingOffenceKind { - #[codec(index = 0)] - ForInvalid, - #[codec(index = 1)] - AgainstValid, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeLocation { - #[codec(index = 0)] - Local, - #[codec(index = 1)] - Remote, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeResult { - #[codec(index = 0)] - Valid, - #[codec(index = 1)] - Invalid, - } - } - pub mod hrmp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - hrmp_init_open_channel { - recipient: runtime_types::polkadot_parachain::primitives::Id, - proposed_max_capacity: ::core::primitive::u32, - proposed_max_message_size: ::core::primitive::u32, - }, - #[codec(index = 1)] - hrmp_accept_open_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 2)] - hrmp_close_channel { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - }, - #[codec(index = 3)] - force_clean_hrmp { - para: runtime_types::polkadot_parachain::primitives::Id, - inbound: ::core::primitive::u32, - outbound: ::core::primitive::u32, - }, - #[codec(index = 4)] - force_process_hrmp_open { channels: ::core::primitive::u32 }, - #[codec(index = 5)] - force_process_hrmp_close { channels: ::core::primitive::u32 }, - #[codec(index = 6)] - hrmp_cancel_open_request { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - open_requests: ::core::primitive::u32, - }, - #[codec(index = 7)] - force_open_hrmp_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - recipient: runtime_types::polkadot_parachain::primitives::Id, - max_capacity: ::core::primitive::u32, - max_message_size: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OpenHrmpChannelToSelf, - #[codec(index = 1)] - OpenHrmpChannelInvalidRecipient, - #[codec(index = 2)] - OpenHrmpChannelZeroCapacity, - #[codec(index = 3)] - OpenHrmpChannelCapacityExceedsLimit, - #[codec(index = 4)] - OpenHrmpChannelZeroMessageSize, - #[codec(index = 5)] - OpenHrmpChannelMessageSizeExceedsLimit, - #[codec(index = 6)] - OpenHrmpChannelAlreadyExists, - #[codec(index = 7)] - OpenHrmpChannelAlreadyRequested, - #[codec(index = 8)] - OpenHrmpChannelLimitExceeded, - #[codec(index = 9)] - AcceptHrmpChannelDoesntExist, - #[codec(index = 10)] - AcceptHrmpChannelAlreadyConfirmed, - #[codec(index = 11)] - AcceptHrmpChannelLimitExceeded, - #[codec(index = 12)] - CloseHrmpChannelUnauthorized, - #[codec(index = 13)] - CloseHrmpChannelDoesntExist, - #[codec(index = 14)] - CloseHrmpChannelAlreadyUnderway, - #[codec(index = 15)] - CancelHrmpOpenChannelUnauthorized, - #[codec(index = 16)] - OpenHrmpChannelDoesntExist, - #[codec(index = 17)] - OpenHrmpChannelAlreadyConfirmed, - #[codec(index = 18)] - WrongWitness, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - OpenChannelRequested( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - #[codec(index = 1)] - OpenChannelCanceled( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 2)] - OpenChannelAccepted( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 3)] - ChannelClosed( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 4)] - HrmpChannelForceOpened( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - pub sender_deposit: ::core::primitive::u128, - pub recipient_deposit: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpOpenChannelRequest { - pub confirmed: ::core::primitive::bool, - pub _age: ::core::primitive::u32, - pub sender_deposit: ::core::primitive::u128, - pub max_message_size: ::core::primitive::u32, - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - } - } - pub mod inclusion { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnsortedOrDuplicateValidatorIndices, - #[codec(index = 1)] - UnsortedOrDuplicateDisputeStatementSet, - #[codec(index = 2)] - UnsortedOrDuplicateBackedCandidates, - #[codec(index = 3)] - UnexpectedRelayParent, - #[codec(index = 4)] - WrongBitfieldSize, - #[codec(index = 5)] - BitfieldAllZeros, - #[codec(index = 6)] - BitfieldDuplicateOrUnordered, - #[codec(index = 7)] - ValidatorIndexOutOfBounds, - #[codec(index = 8)] - InvalidBitfieldSignature, - #[codec(index = 9)] - UnscheduledCandidate, - #[codec(index = 10)] - CandidateScheduledBeforeParaFree, - #[codec(index = 11)] - WrongCollator, - #[codec(index = 12)] - ScheduledOutOfOrder, - #[codec(index = 13)] - HeadDataTooLarge, - #[codec(index = 14)] - PrematureCodeUpgrade, - #[codec(index = 15)] - NewCodeTooLarge, - #[codec(index = 16)] - CandidateNotInParentContext, - #[codec(index = 17)] - InvalidGroupIndex, - #[codec(index = 18)] - InsufficientBacking, - #[codec(index = 19)] - InvalidBacking, - #[codec(index = 20)] - NotCollatorSigned, - #[codec(index = 21)] - ValidationDataHashMismatch, - #[codec(index = 22)] - IncorrectDownwardMessageHandling, - #[codec(index = 23)] - InvalidUpwardMessages, - #[codec(index = 24)] - HrmpWatermarkMishandling, - #[codec(index = 25)] - InvalidOutboundHrmp, - #[codec(index = 26)] - InvalidValidationCodeHash, - #[codec(index = 27)] - ParaHeadMismatch, - #[codec(index = 28)] - BitfieldReferencesFreedCore, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CandidateBacked( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 1)] - CandidateIncluded( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 2)] - CandidateTimedOut( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - ), - #[codec(index = 3)] - UpwardMessagesReceived { - from: runtime_types::polkadot_parachain::primitives::Id, - count: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfieldRecord<_0> { - pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - pub submitted_at: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidatePendingAvailability<_0, _1> { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub availability_votes: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub backers: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub relay_parent_number: _1, - pub backed_in_number: _1, - pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UmpQueueId { - #[codec(index = 0)] - Para(runtime_types::polkadot_parachain::primitives::Id), - } - } - pub mod initializer { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_approve { up_to: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BufferedSessionChange { - pub validators: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub queued: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub session_index: ::core::primitive::u32, - } - } - pub mod origin { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Parachain(runtime_types::polkadot_parachain::primitives::Id), - } - } - } - pub mod paras { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_set_current_code { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 2)] - force_schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - relay_parent_number: ::core::primitive::u32, - }, - #[codec(index = 3)] - force_note_new_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 4)] - force_queue_action { - para: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - add_trusted_validation_code { - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 6)] - poke_unused_validation_code { - validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - }, - #[codec(index = 7)] - include_pvf_check_statement { - stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, - signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - CannotOnboard, - #[codec(index = 2)] - CannotOffboard, - #[codec(index = 3)] - CannotUpgrade, - #[codec(index = 4)] - CannotDowngrade, - #[codec(index = 5)] - PvfCheckStatementStale, - #[codec(index = 6)] - PvfCheckStatementFuture, - #[codec(index = 7)] - PvfCheckValidatorIndexOutOfBounds, - #[codec(index = 8)] - PvfCheckInvalidSignature, - #[codec(index = 9)] - PvfCheckDoubleVote, - #[codec(index = 10)] - PvfCheckSubjectInvalid, - #[codec(index = 11)] - CannotUpgradeCode, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 2)] - CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 3)] - NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 4)] - ActionQueued( - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ), - #[codec(index = 5)] - PvfCheckStarted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 6)] - PvfCheckAccepted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 7)] - PvfCheckRejected( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaGenesisArgs { - pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - pub validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - pub para_kind: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ParaLifecycle { - #[codec(index = 0)] - Onboarding, - #[codec(index = 1)] - Parathread, - #[codec(index = 2)] - Parachain, - #[codec(index = 3)] - UpgradingParathread, - #[codec(index = 4)] - DowngradingParachain, - #[codec(index = 5)] - OffboardingParathread, - #[codec(index = 6)] - OffboardingParachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaPastCodeMeta<_0> { - pub upgrade_times: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, - >, - pub last_pruned: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckActiveVoteState<_0> { - pub votes_accept: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub votes_reject: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub age: _0, - pub created_at: _0, - pub causes: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfCheckCause<_0> { - #[codec(index = 0)] - Onboarding(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - Upgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - relay_parent_number: _0, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReplacementTimes<_0> { - pub expected_at: _0, - pub activated_at: _0, - } - } - pub mod paras_inherent { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - enter { - data: runtime_types::polkadot_primitives::v4::InherentData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyInclusionInherents, - #[codec(index = 1)] - InvalidParentHeader, - #[codec(index = 2)] - CandidateConcludedInvalid, - #[codec(index = 3)] - InherentOverweight, - #[codec(index = 4)] - DisputeStatementsUnsortedOrDuplicates, - #[codec(index = 5)] - DisputeInvalid, - } - } - } - pub mod scheduler { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssignmentKind { - #[codec(index = 0)] - Parachain, - #[codec(index = 1)] - Parathread( - runtime_types::polkadot_primitives::v4::collator_app::Public, - ::core::primitive::u32, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CoreAssignment { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, - pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaimQueue { - pub queue: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, - >, - pub next_core_offset: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueuedParathread { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, - pub core_offset: ::core::primitive::u32, - } - } - pub mod shared { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - } - } - } - pub mod rococo_runtime { - use super::runtime_types; - pub mod validator_manager { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register_validators { - validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 1)] - deregister_validators { - validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ValidatorsRegistered(::std::vec::Vec<::sp_core::crypto::AccountId32>), - #[codec(index = 1)] - ValidatorsDeregistered(::std::vec::Vec<::sp_core::crypto::AccountId32>), - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::sp_core::crypto::AccountId32, - >, - ), - #[codec(index = 14)] - Council( - runtime_types::pallet_collective::RawOrigin<::sp_core::crypto::AccountId32>, - ), - #[codec(index = 15)] - TechnicalCommittee( - runtime_types::pallet_collective::RawOrigin<::sp_core::crypto::AccountId32>, - ), - #[codec(index = 50)] - ParachainsOrigin( - runtime_types::polkadot_runtime_parachains::origin::pallet::Origin, - ), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Origin), - #[codec(index = 5)] - Void(runtime_types::sp_core::Void), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProxyType { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - NonTransfer, - #[codec(index = 2)] - Governance, - #[codec(index = 3)] - IdentityJudgement, - #[codec(index = 4)] - CancelProxy, - #[codec(index = 5)] - Auction, - #[codec(index = 6)] - Society, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - Babe(runtime_types::pallet_babe::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 3)] - Indices(runtime_types::pallet_indices::pallet::Call), - #[codec(index = 4)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 8)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 10)] - Grandpa(runtime_types::pallet_grandpa::pallet::Call), - #[codec(index = 11)] - ImOnline(runtime_types::pallet_im_online::pallet::Call), - #[codec(index = 13)] - Democracy(runtime_types::pallet_democracy::pallet::Call), - #[codec(index = 14)] - Council(runtime_types::pallet_collective::pallet::Call), - #[codec(index = 15)] - TechnicalCommittee(runtime_types::pallet_collective::pallet::Call), - #[codec(index = 16)] - PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Call), - #[codec(index = 17)] - TechnicalMembership(runtime_types::pallet_membership::pallet::Call), - #[codec(index = 18)] - Treasury(runtime_types::pallet_treasury::pallet::Call), - #[codec(index = 19)] - Claims(runtime_types::polkadot_runtime_common::claims::pallet::Call), - #[codec(index = 24)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 25)] - Identity(runtime_types::pallet_identity::pallet::Call), - #[codec(index = 26)] - Society(runtime_types::pallet_society::pallet::Call), - #[codec(index = 27)] - Recovery(runtime_types::pallet_recovery::pallet::Call), - #[codec(index = 28)] - Vesting(runtime_types::pallet_vesting::pallet::Call), - #[codec(index = 29)] - Scheduler(runtime_types::pallet_scheduler::pallet::Call), - #[codec(index = 30)] - Proxy(runtime_types::pallet_proxy::pallet::Call), - #[codec(index = 31)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 32)] - Preimage(runtime_types::pallet_preimage::pallet::Call), - #[codec(index = 35)] - Bounties(runtime_types::pallet_bounties::pallet::Call), - #[codec(index = 40)] - ChildBounties(runtime_types::pallet_child_bounties::pallet::Call), - #[codec(index = 36)] - Tips(runtime_types::pallet_tips::pallet::Call), - #[codec(index = 38)] - Nis(runtime_types::pallet_nis::pallet::Call), - #[codec(index = 45)] - NisCounterpartBalances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 51)] - Configuration( - runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, - ), - #[codec(index = 52)] - ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), - #[codec(index = 53)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), - #[codec(index = 54)] - ParaInherent( - runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, - ), - #[codec(index = 56)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), - #[codec(index = 57)] - Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), - #[codec(index = 60)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), - #[codec(index = 62)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), - #[codec(index = 63)] - ParasSlashing( - runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, - ), - #[codec(index = 64)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Call), - #[codec(index = 70)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), - #[codec(index = 71)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), - #[codec(index = 72)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), - #[codec(index = 73)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 240)] - Beefy(runtime_types::pallet_beefy::pallet::Call), - #[codec(index = 250)] - ParasSudoWrapper( - runtime_types::polkadot_runtime_common::paras_sudo_wrapper::pallet::Call, - ), - #[codec(index = 251)] - AssignedSlots(runtime_types::polkadot_runtime_common::assigned_slots::pallet::Call), - #[codec(index = 252)] - ValidatorManager(runtime_types::rococo_runtime::validator_manager::pallet::Call), - #[codec(index = 254)] - StateTrieMigration(runtime_types::pallet_state_trie_migration::pallet::Call), - #[codec(index = 255)] - Sudo(runtime_types::pallet_sudo::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 3)] - Indices(runtime_types::pallet_indices::pallet::Event), - #[codec(index = 4)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 33)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 7)] - Offences(runtime_types::pallet_offences::pallet::Event), - #[codec(index = 8)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 10)] - Grandpa(runtime_types::pallet_grandpa::pallet::Event), - #[codec(index = 11)] - ImOnline(runtime_types::pallet_im_online::pallet::Event), - #[codec(index = 13)] - Democracy(runtime_types::pallet_democracy::pallet::Event), - #[codec(index = 14)] - Council(runtime_types::pallet_collective::pallet::Event), - #[codec(index = 15)] - TechnicalCommittee(runtime_types::pallet_collective::pallet::Event), - #[codec(index = 16)] - PhragmenElection(runtime_types::pallet_elections_phragmen::pallet::Event), - #[codec(index = 17)] - TechnicalMembership(runtime_types::pallet_membership::pallet::Event), - #[codec(index = 18)] - Treasury(runtime_types::pallet_treasury::pallet::Event), - #[codec(index = 19)] - Claims(runtime_types::polkadot_runtime_common::claims::pallet::Event), - #[codec(index = 24)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 25)] - Identity(runtime_types::pallet_identity::pallet::Event), - #[codec(index = 26)] - Society(runtime_types::pallet_society::pallet::Event), - #[codec(index = 27)] - Recovery(runtime_types::pallet_recovery::pallet::Event), - #[codec(index = 28)] - Vesting(runtime_types::pallet_vesting::pallet::Event), - #[codec(index = 29)] - Scheduler(runtime_types::pallet_scheduler::pallet::Event), - #[codec(index = 30)] - Proxy(runtime_types::pallet_proxy::pallet::Event), - #[codec(index = 31)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 32)] - Preimage(runtime_types::pallet_preimage::pallet::Event), - #[codec(index = 35)] - Bounties(runtime_types::pallet_bounties::pallet::Event), - #[codec(index = 40)] - ChildBounties(runtime_types::pallet_child_bounties::pallet::Event), - #[codec(index = 36)] - Tips(runtime_types::pallet_tips::pallet::Event), - #[codec(index = 38)] - Nis(runtime_types::pallet_nis::pallet::Event), - #[codec(index = 45)] - NisCounterpartBalances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 53)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), - #[codec(index = 56)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), - #[codec(index = 60)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), - #[codec(index = 62)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), - #[codec(index = 64)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Event), - #[codec(index = 70)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), - #[codec(index = 71)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), - #[codec(index = 72)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), - #[codec(index = 73)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 251)] - AssignedSlots( - runtime_types::polkadot_runtime_common::assigned_slots::pallet::Event, - ), - #[codec(index = 252)] - ValidatorManager(runtime_types::rococo_runtime::validator_manager::pallet::Event), - #[codec(index = 254)] - StateTrieMigration(runtime_types::pallet_state_trie_migration::pallet::Event), - #[codec(index = 255)] - Sudo(runtime_types::pallet_sudo::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeHoldReason { - #[codec(index = 38)] - Nis(runtime_types::pallet_nis::pallet::HoldReason), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, - pub babe: runtime_types::sp_consensus_babe::app::Public, - pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, - pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, - pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, - pub beefy: runtime_types::sp_consensus_beefy::crypto::Public, - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - pub mod per_things { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Percent(pub ::core::primitive::u8); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Permill(pub ::core::primitive::u32); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Perquintill(pub ::core::primitive::u64); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_authority_discovery { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - pub mod sp_consensus_babe { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod digests { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NextConfigDescriptor { - #[codec(index = 1)] - V1 { - c: (::core::primitive::u64, ::core::primitive::u64), - allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PreDigest { - #[codec(index = 1)] - Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), - #[codec(index = 2)] - SecondaryPlain( - runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, - ), - #[codec(index = 3)] - SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PrimaryPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryPlainPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryVRFPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AllowedSlots { - #[codec(index = 0)] - PrimarySlots, - #[codec(index = 1)] - PrimaryAndSecondaryPlainSlots, - #[codec(index = 2)] - PrimaryAndSecondaryVRFSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BabeEpochConfiguration { - pub c: (::core::primitive::u64, ::core::primitive::u64), - pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - } - } - pub mod sp_consensus_beefy { - use super::runtime_types; - pub mod commitment { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commitment<_0> { - pub payload: runtime_types::sp_consensus_beefy::payload::Payload, - pub block_number: _0, - pub validator_set_id: ::core::primitive::u64, - } - } - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ecdsa::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ecdsa::Signature); - } - pub mod mmr { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BeefyAuthoritySet<_0> { - pub id: ::core::primitive::u64, - pub len: ::core::primitive::u32, - pub root: _0, - } - } - pub mod payload { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Payload( - pub ::std::vec::Vec<( - [::core::primitive::u8; 2usize], - ::std::vec::Vec<::core::primitive::u8>, - )>, - ); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EquivocationProof<_0, _1, _2> { - pub first: runtime_types::sp_consensus_beefy::VoteMessage<_0, _1, _2>, - pub second: runtime_types::sp_consensus_beefy::VoteMessage<_0, _1, _2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VoteMessage<_0, _1, _2> { - pub commitment: runtime_types::sp_consensus_beefy::commitment::Commitment<_0>, - pub id: _1, - pub signature: _2, - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Equivocation<_0, _1> { - #[codec(index = 0)] - Prevote( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Prevote<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - #[codec(index = 1)] - Precommit( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Precommit<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EquivocationProof<_0, _1> { - pub offender: _1, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub first_header: _0, - pub second_header: _0, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 33usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod offchain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueNetworkState { - pub peer_id: runtime_types::sp_core::OpaquePeerId, - pub external_addresses: - ::std::vec::Vec, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod vrf { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VrfSignature { - pub output: [::core::primitive::u8; 32usize], - pub proof: [::core::primitive::u8; 64usize], - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1, _2, _3)>, - ); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSigner { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Public), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Public), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Public), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_staking { - use super::runtime_types; - pub mod offence { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OffenceDetails<_0, _1> { - pub offender: _1, - pub reporters: ::std::vec::Vec<_0>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - } - } -} diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs deleted file mode 100644 index 575660504b3a5..0000000000000 --- a/relays/client-rococo/src/lib.rs +++ /dev/null @@ -1,122 +0,0 @@ -// 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 . - -//! Types used to connect to the Rococo-Substrate chain. - -pub mod codegen_runtime; - -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_rococo::ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, - Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, - UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use sp_session::MembershipProof; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::rococo_runtime::RuntimeCall; - -pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; - -/// Rococo header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Rococo header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Rococo chain definition -#[derive(Debug, Clone, Copy)] -pub struct Rococo; - -impl UnderlyingChainProvider for Rococo { - type Chain = bp_rococo::Rococo; -} - -impl Chain for Rococo { - const NAME: &'static str = "Rococo"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_rococo::BEST_FINALIZED_ROCOCO_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_rococo::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithGrandpa for Rococo { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - ROCOCO_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl ChainWithBalances for Rococo { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl RelayChain for Rococo { - const PARAS_PALLET_NAME: &'static str = bp_rococo::PARAS_PALLET_NAME; -} - -impl ChainWithTransactions for Rococo { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_rococo::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - ((), ()), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithRuntimeVersion for Rococo { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); -} diff --git a/relays/client-westend/Cargo.toml b/relays/client-westend/Cargo.toml deleted file mode 100644 index 8b56e51d084d2..0000000000000 --- a/relays/client-westend/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "relay-westend-client" -version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "GPL-3.0-or-later WITH Classpath-exception-2.0" - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } -subxt = { version = "0.32.1", default-features = false, features = ["native"] } - -# Bridge dependencies - -bp-polkadot-core = { path = "../../primitives/polkadot-core" } -bp-runtime = { path = "../../primitives/runtime" } -bp-westend = { path = "../../chains/chain-westend" } - -relay-substrate-client = { path = "../client-substrate" } -relay-utils = { path = "../utils" } - -# Substrate Dependencies - -sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-session = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -sp-weights = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/client-westend/src/codegen_runtime.rs b/relays/client-westend/src/codegen_runtime.rs deleted file mode 100644 index 9422622e48c50..0000000000000 --- a/relays/client-westend/src/codegen_runtime.rs +++ /dev/null @@ -1,6945 +0,0 @@ -// Copyright 2019-2023 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 . - -//! Autogenerated runtime API -//! THIS FILE WAS AUTOGENERATED USING parity-bridges-common::runtime-codegen -//! EXECUTED COMMAND: target/debug/runtime-codegen --from-node-url wss://westend-rpc.polkadot.io:443 - -#[allow(dead_code, unused_imports, non_camel_case_types)] -#[allow(clippy::all)] -pub mod api { - use super::api as root_mod; - pub mod runtime_types { - use super::runtime_types; - pub mod bounded_collections { - use super::runtime_types; - pub mod bounded_btree_map { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedBTreeMap<_0, _1>(pub ::subxt::utils::KeyedVec<_0, _1>); - } - pub mod bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - pub mod weak_bounded_vec { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeakBoundedVec<_0>(pub ::std::vec::Vec<_0>); - } - } - pub mod finality_grandpa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Equivocation<_0, _1, _2> { - pub round_number: ::core::primitive::u64, - pub identity: _0, - pub first: (_1, _2), - pub second: (_1, _2), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Precommit<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Prevote<_0, _1> { - pub target_hash: _0, - pub target_number: _1, - } - } - pub mod frame_support { - use super::runtime_types; - pub mod dispatch { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchClass { - #[codec(index = 0)] - Normal, - #[codec(index = 1)] - Operational, - #[codec(index = 2)] - Mandatory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DispatchInfo { - pub weight: ::sp_weights::Weight, - pub class: runtime_types::frame_support::dispatch::DispatchClass, - pub pays_fee: runtime_types::frame_support::dispatch::Pays, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Pays { - #[codec(index = 0)] - Yes, - #[codec(index = 1)] - No, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PerDispatchClass<_0> { - pub normal: _0, - pub operational: _0, - pub mandatory: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RawOrigin<_0> { - #[codec(index = 0)] - Root, - #[codec(index = 1)] - Signed(_0), - #[codec(index = 2)] - None, - } - } - pub mod traits { - use super::runtime_types; - pub mod messages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProcessMessageError { - #[codec(index = 0)] - BadFormat, - #[codec(index = 1)] - Corrupt, - #[codec(index = 2)] - Unsupported, - #[codec(index = 3)] - Overweight(::sp_weights::Weight), - #[codec(index = 4)] - Yield, - } - } - pub mod misc { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WrapperOpaque<_0>( - #[codec(compact)] pub ::core::primitive::u32, - pub _0, - ); - } - pub mod preimages { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Bounded<_0> { - #[codec(index = 0)] - Legacy { - hash: ::subxt::utils::H256, - }, - #[codec(index = 1)] - Inline( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Lookup { - hash: ::subxt::utils::H256, - len: ::core::primitive::u32, - }, - __Ignore(::core::marker::PhantomData<_0>), - } - } - pub mod tokens { - use super::runtime_types; - pub mod misc { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum BalanceStatus { - #[codec(index = 0)] - Free, - #[codec(index = 1)] - Reserved, - } - } - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletId(pub [::core::primitive::u8; 8usize]); - } - pub mod frame_system { - use super::runtime_types; - pub mod extensions { - use super::runtime_types; - pub mod check_genesis { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckGenesis; - } - pub mod check_mortality { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckMortality(pub ::sp_runtime::generic::Era); - } - pub mod check_non_zero_sender { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonZeroSender; - } - pub mod check_nonce { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckNonce(#[codec(compact)] pub ::core::primitive::u32); - } - pub mod check_spec_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckSpecVersion; - } - pub mod check_tx_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckTxVersion; - } - pub mod check_weight { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CheckWeight; - } - } - pub mod limits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockLength { - pub max: runtime_types::frame_support::dispatch::PerDispatchClass< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BlockWeights { - pub base_block: ::sp_weights::Weight, - pub max_block: ::sp_weights::Weight, - pub per_class: runtime_types::frame_support::dispatch::PerDispatchClass< - runtime_types::frame_system::limits::WeightsPerClass, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct WeightsPerClass { - pub base_extrinsic: ::sp_weights::Weight, - pub max_extrinsic: ::core::option::Option<::sp_weights::Weight>, - pub max_total: ::core::option::Option<::sp_weights::Weight>, - pub reserved: ::core::option::Option<::sp_weights::Weight>, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - remark { remark: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - set_heap_pages { pages: ::core::primitive::u64 }, - #[codec(index = 2)] - set_code { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 3)] - set_code_without_checks { code: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 4)] - set_storage { - items: ::std::vec::Vec<( - ::std::vec::Vec<::core::primitive::u8>, - ::std::vec::Vec<::core::primitive::u8>, - )>, - }, - #[codec(index = 5)] - kill_storage { keys: ::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>> }, - #[codec(index = 6)] - kill_prefix { - prefix: ::std::vec::Vec<::core::primitive::u8>, - subkeys: ::core::primitive::u32, - }, - #[codec(index = 7)] - remark_with_event { remark: ::std::vec::Vec<::core::primitive::u8> }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidSpecName, - #[codec(index = 1)] - SpecVersionNeedsToIncrease, - #[codec(index = 2)] - FailedToExtractRuntimeVersion, - #[codec(index = 3)] - NonDefaultComposite, - #[codec(index = 4)] - NonZeroRefCount, - #[codec(index = 5)] - CallFiltered, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ExtrinsicSuccess { - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 1)] - ExtrinsicFailed { - dispatch_error: runtime_types::sp_runtime::DispatchError, - dispatch_info: runtime_types::frame_support::dispatch::DispatchInfo, - }, - #[codec(index = 2)] - CodeUpdated, - #[codec(index = 3)] - NewAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 4)] - KilledAccount { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 5)] - Remarked { sender: ::sp_core::crypto::AccountId32, hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountInfo<_0, _1> { - pub nonce: _0, - pub consumers: _0, - pub providers: _0, - pub sufficients: _0, - pub data: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EventRecord<_0, _1> { - pub phase: runtime_types::frame_system::Phase, - pub event: _0, - pub topics: ::std::vec::Vec<_1>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct LastRuntimeUpgradeInfo { - #[codec(compact)] - pub spec_version: ::core::primitive::u32, - pub spec_name: ::std::string::String, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase { - #[codec(index = 0)] - ApplyExtrinsic(::core::primitive::u32), - #[codec(index = 1)] - Finalization, - #[codec(index = 2)] - Initialization, - } - } - pub mod pallet_babe { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - runtime_types::sp_consensus_slots::EquivocationProof< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - runtime_types::sp_consensus_babe::app::Public, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - plan_config_change { - config: runtime_types::sp_consensus_babe::digests::NextConfigDescriptor, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidEquivocationProof, - #[codec(index = 1)] - InvalidKeyOwnershipProof, - #[codec(index = 2)] - DuplicateOffenceReport, - #[codec(index = 3)] - InvalidConfiguration, - } - } - } - pub mod pallet_bags_list { - use super::runtime_types; - pub mod list { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Bag { - pub head: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub tail: ::core::option::Option<::sp_core::crypto::AccountId32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ListError { - #[codec(index = 0)] - Duplicate, - #[codec(index = 1)] - NotHeavier, - #[codec(index = 2)] - NotInSameBag, - #[codec(index = 3)] - NodeNotFound, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Node { - pub id: ::sp_core::crypto::AccountId32, - pub prev: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub next: ::core::option::Option<::sp_core::crypto::AccountId32>, - pub bag_upper: ::core::primitive::u64, - pub score: ::core::primitive::u64, - } - } - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - rebag { - dislocated: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - put_in_front_of { - lighter: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - List(runtime_types::pallet_bags_list::list::ListError), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Rebagged { - who: ::sp_core::crypto::AccountId32, - from: ::core::primitive::u64, - to: ::core::primitive::u64, - }, - #[codec(index = 1)] - ScoreUpdated { - who: ::sp_core::crypto::AccountId32, - new_score: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_balances { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - transfer_allow_death { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 1)] - set_balance_deprecated { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - #[codec(compact)] - old_reserved: ::core::primitive::u128, - }, - #[codec(index = 2)] - force_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - transfer_keep_alive { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - transfer_all { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - keep_alive: ::core::primitive::bool, - }, - #[codec(index = 5)] - force_unreserve { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - upgrade_accounts { who: ::std::vec::Vec<::sp_core::crypto::AccountId32> }, - #[codec(index = 7)] - transfer { - dest: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 8)] - force_set_balance { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - new_free: ::core::primitive::u128, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - VestingBalance, - #[codec(index = 1)] - LiquidityRestrictions, - #[codec(index = 2)] - InsufficientBalance, - #[codec(index = 3)] - ExistentialDeposit, - #[codec(index = 4)] - Expendability, - #[codec(index = 5)] - ExistingVestingSchedule, - #[codec(index = 6)] - DeadAccount, - #[codec(index = 7)] - TooManyReserves, - #[codec(index = 8)] - TooManyHolds, - #[codec(index = 9)] - TooManyFreezes, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Endowed { - account: ::sp_core::crypto::AccountId32, - free_balance: ::core::primitive::u128, - }, - #[codec(index = 1)] - DustLost { - account: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Transfer { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - BalanceSet { - who: ::sp_core::crypto::AccountId32, - free: ::core::primitive::u128, - }, - #[codec(index = 4)] - Reserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - Unreserved { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 6)] - ReserveRepatriated { - from: ::sp_core::crypto::AccountId32, - to: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - destination_status: - runtime_types::frame_support::traits::tokens::misc::BalanceStatus, - }, - #[codec(index = 7)] - Deposit { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 8)] - Withdraw { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Slashed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 10)] - Minted { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 11)] - Burned { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 12)] - Suspended { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 13)] - Restored { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 14)] - Upgraded { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 15)] - Issued { amount: ::core::primitive::u128 }, - #[codec(index = 16)] - Rescinded { amount: ::core::primitive::u128 }, - #[codec(index = 17)] - Locked { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 18)] - Unlocked { - who: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 19)] - Frozen { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - #[codec(index = 20)] - Thawed { who: ::sp_core::crypto::AccountId32, amount: ::core::primitive::u128 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AccountData<_0> { - pub free: _0, - pub reserved: _0, - pub frozen: _0, - pub flags: runtime_types::pallet_balances::types::ExtraFlags, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BalanceLock<_0> { - pub id: [::core::primitive::u8; 8usize], - pub amount: _0, - pub reasons: runtime_types::pallet_balances::types::Reasons, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ExtraFlags(pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdAmount<_0, _1> { - pub id: _0, - pub amount: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Reasons { - #[codec(index = 0)] - Fee, - #[codec(index = 1)] - Misc, - #[codec(index = 2)] - All, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReserveData<_0, _1> { - pub id: _0, - pub amount: _1, - } - } - } - pub mod pallet_election_provider_multi_phase { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] submit_unsigned { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: westend_runtime :: NposCompactSolution16 > > , witness : runtime_types :: pallet_election_provider_multi_phase :: SolutionOrSnapshotSize , } , # [codec (index = 1)] set_minimum_untrusted_score { maybe_next_score : :: core :: option :: Option < runtime_types :: sp_npos_elections :: ElectionScore > , } , # [codec (index = 2)] set_emergency_election_result { supports : :: std :: vec :: Vec < (:: sp_core :: crypto :: AccountId32 , runtime_types :: sp_npos_elections :: Support < :: sp_core :: crypto :: AccountId32 > ,) > , } , # [codec (index = 3)] submit { raw_solution : :: std :: boxed :: Box < runtime_types :: pallet_election_provider_multi_phase :: RawSolution < runtime_types :: westend_runtime :: NposCompactSolution16 > > , } , # [codec (index = 4)] governance_fallback { maybe_max_voters : :: core :: option :: Option < :: core :: primitive :: u32 > , maybe_max_targets : :: core :: option :: Option < :: core :: primitive :: u32 > , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PreDispatchEarlySubmission, - #[codec(index = 1)] - PreDispatchWrongWinnerCount, - #[codec(index = 2)] - PreDispatchWeakSubmission, - #[codec(index = 3)] - SignedQueueFull, - #[codec(index = 4)] - SignedCannotPayDeposit, - #[codec(index = 5)] - SignedInvalidWitness, - #[codec(index = 6)] - SignedTooMuchWeight, - #[codec(index = 7)] - OcwCallWrongEra, - #[codec(index = 8)] - MissingSnapshotMetadata, - #[codec(index = 9)] - InvalidSubmissionIndex, - #[codec(index = 10)] - CallNotAllowed, - #[codec(index = 11)] - FallbackFailed, - #[codec(index = 12)] - BoundNotMet, - #[codec(index = 13)] - TooManyWinners, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - SolutionStored { - compute: - runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - origin: ::core::option::Option<::sp_core::crypto::AccountId32>, - prev_ejected: ::core::primitive::bool, - }, - #[codec(index = 1)] - ElectionFinalized { - compute: - runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - score: runtime_types::sp_npos_elections::ElectionScore, - }, - #[codec(index = 2)] - ElectionFailed, - #[codec(index = 3)] - Rewarded { - account: ::sp_core::crypto::AccountId32, - value: ::core::primitive::u128, - }, - #[codec(index = 4)] - Slashed { - account: ::sp_core::crypto::AccountId32, - value: ::core::primitive::u128, - }, - #[codec(index = 5)] - PhaseTransitioned { - from: runtime_types::pallet_election_provider_multi_phase::Phase< - ::core::primitive::u32, - >, - to: runtime_types::pallet_election_provider_multi_phase::Phase< - ::core::primitive::u32, - >, - round: ::core::primitive::u32, - }, - } - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SignedSubmission<_0, _1, _2> { - pub who: _0, - pub deposit: _1, - pub raw_solution: - runtime_types::pallet_election_provider_multi_phase::RawSolution<_2>, - pub call_fee: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ElectionCompute { - #[codec(index = 0)] - OnChain, - #[codec(index = 1)] - Signed, - #[codec(index = 2)] - Unsigned, - #[codec(index = 3)] - Fallback, - #[codec(index = 4)] - Emergency, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Phase<_0> { - #[codec(index = 0)] - Off, - #[codec(index = 1)] - Signed, - #[codec(index = 2)] - Unsigned((::core::primitive::bool, _0)), - #[codec(index = 3)] - Emergency, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RawSolution<_0> { - pub solution: _0, - pub score: runtime_types::sp_npos_elections::ElectionScore, - pub round: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReadySolution { - pub supports: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::sp_core::crypto::AccountId32, - runtime_types::sp_npos_elections::Support<::sp_core::crypto::AccountId32>, - )>, - pub score: runtime_types::sp_npos_elections::ElectionScore, - pub compute: runtime_types::pallet_election_provider_multi_phase::ElectionCompute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RoundSnapshot<_0, _1> { - pub voters: ::std::vec::Vec<_1>, - pub targets: ::std::vec::Vec<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SolutionOrSnapshotSize { - #[codec(compact)] - pub voters: ::core::primitive::u32, - #[codec(compact)] - pub targets: ::core::primitive::u32, - } - } - pub mod pallet_fast_unstake { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register_fast_unstake, - #[codec(index = 1)] - deregister, - #[codec(index = 2)] - control { eras_to_check: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotController, - #[codec(index = 1)] - AlreadyQueued, - #[codec(index = 2)] - NotFullyBonded, - #[codec(index = 3)] - NotQueued, - #[codec(index = 4)] - AlreadyHead, - #[codec(index = 5)] - CallNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Unstaked { - stash: ::sp_core::crypto::AccountId32, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - Slashed { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - InternalError, - #[codec(index = 3)] - BatchChecked { eras: ::std::vec::Vec<::core::primitive::u32> }, - #[codec(index = 4)] - BatchFinished { size: ::core::primitive::u32 }, - } - } - pub mod types { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnstakeRequest { - pub stashes: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - )>, - pub checked: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u32, - >, - } - } - } - pub mod pallet_grandpa { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - report_equivocation { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 1)] - report_equivocation_unsigned { - equivocation_proof: ::std::boxed::Box< - ::sp_consensus_grandpa::EquivocationProof< - ::subxt::utils::H256, - ::core::primitive::u32, - >, - >, - key_owner_proof: ::sp_session::MembershipProof, - }, - #[codec(index = 2)] - note_stalled { - delay: ::core::primitive::u32, - best_finalized_block_number: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PauseFailed, - #[codec(index = 1)] - ResumeFailed, - #[codec(index = 2)] - ChangePending, - #[codec(index = 3)] - TooSoon, - #[codec(index = 4)] - InvalidKeyOwnershipProof, - #[codec(index = 5)] - InvalidEquivocationProof, - #[codec(index = 6)] - DuplicateOffenceReport, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewAuthorities { - authority_set: ::std::vec::Vec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - }, - #[codec(index = 1)] - Paused, - #[codec(index = 2)] - Resumed, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StoredPendingChange<_0> { - pub scheduled_at: _0, - pub delay: _0, - pub next_authorities: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec<( - runtime_types::sp_consensus_grandpa::app::Public, - ::core::primitive::u64, - )>, - pub forced: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum StoredState<_0> { - #[codec(index = 0)] - Live, - #[codec(index = 1)] - PendingPause { scheduled_at: _0, delay: _0 }, - #[codec(index = 2)] - Paused, - #[codec(index = 3)] - PendingResume { scheduled_at: _0, delay: _0 }, - } - } - pub mod pallet_identity { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - add_registrar { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 1)] - set_identity { - info: - ::std::boxed::Box, - }, - #[codec(index = 2)] - set_subs { - subs: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_identity::types::Data, - )>, - }, - #[codec(index = 3)] - clear_identity, - #[codec(index = 4)] - request_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - #[codec(compact)] - max_fee: ::core::primitive::u128, - }, - #[codec(index = 5)] - cancel_request { reg_index: ::core::primitive::u32 }, - #[codec(index = 6)] - set_fee { - #[codec(compact)] - index: ::core::primitive::u32, - #[codec(compact)] - fee: ::core::primitive::u128, - }, - #[codec(index = 7)] - set_account_id { - #[codec(compact)] - index: ::core::primitive::u32, - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 8)] - set_fields { - #[codec(compact)] - index: ::core::primitive::u32, - fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - }, - #[codec(index = 9)] - provide_judgement { - #[codec(compact)] - reg_index: ::core::primitive::u32, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - judgement: runtime_types::pallet_identity::types::Judgement< - ::core::primitive::u128, - >, - identity: ::subxt::utils::H256, - }, - #[codec(index = 10)] - kill_identity { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 11)] - add_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 12)] - rename_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - data: runtime_types::pallet_identity::types::Data, - }, - #[codec(index = 13)] - remove_sub { - sub: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 14)] - quit_sub, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManySubAccounts, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotNamed, - #[codec(index = 3)] - EmptyIndex, - #[codec(index = 4)] - FeeChanged, - #[codec(index = 5)] - NoIdentity, - #[codec(index = 6)] - StickyJudgement, - #[codec(index = 7)] - JudgementGiven, - #[codec(index = 8)] - InvalidJudgement, - #[codec(index = 9)] - InvalidIndex, - #[codec(index = 10)] - InvalidTarget, - #[codec(index = 11)] - TooManyFields, - #[codec(index = 12)] - TooManyRegistrars, - #[codec(index = 13)] - AlreadyClaimed, - #[codec(index = 14)] - NotSub, - #[codec(index = 15)] - NotOwned, - #[codec(index = 16)] - JudgementForDifferentIdentity, - #[codec(index = 17)] - JudgementPaymentFailed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IdentitySet { who: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - IdentityCleared { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 2)] - IdentityKilled { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 3)] - JudgementRequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 4)] - JudgementUnrequested { - who: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 5)] - JudgementGiven { - target: ::sp_core::crypto::AccountId32, - registrar_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - RegistrarAdded { registrar_index: ::core::primitive::u32 }, - #[codec(index = 7)] - SubIdentityAdded { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 8)] - SubIdentityRemoved { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - #[codec(index = 9)] - SubIdentityRevoked { - sub: ::sp_core::crypto::AccountId32, - main: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - }, - } - } - pub mod types { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct BitFlags<_0>( - pub ::core::primitive::u64, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Data { - #[codec(index = 0)] - None, - #[codec(index = 1)] - Raw0([::core::primitive::u8; 0usize]), - #[codec(index = 2)] - Raw1([::core::primitive::u8; 1usize]), - #[codec(index = 3)] - Raw2([::core::primitive::u8; 2usize]), - #[codec(index = 4)] - Raw3([::core::primitive::u8; 3usize]), - #[codec(index = 5)] - Raw4([::core::primitive::u8; 4usize]), - #[codec(index = 6)] - Raw5([::core::primitive::u8; 5usize]), - #[codec(index = 7)] - Raw6([::core::primitive::u8; 6usize]), - #[codec(index = 8)] - Raw7([::core::primitive::u8; 7usize]), - #[codec(index = 9)] - Raw8([::core::primitive::u8; 8usize]), - #[codec(index = 10)] - Raw9([::core::primitive::u8; 9usize]), - #[codec(index = 11)] - Raw10([::core::primitive::u8; 10usize]), - #[codec(index = 12)] - Raw11([::core::primitive::u8; 11usize]), - #[codec(index = 13)] - Raw12([::core::primitive::u8; 12usize]), - #[codec(index = 14)] - Raw13([::core::primitive::u8; 13usize]), - #[codec(index = 15)] - Raw14([::core::primitive::u8; 14usize]), - #[codec(index = 16)] - Raw15([::core::primitive::u8; 15usize]), - #[codec(index = 17)] - Raw16([::core::primitive::u8; 16usize]), - #[codec(index = 18)] - Raw17([::core::primitive::u8; 17usize]), - #[codec(index = 19)] - Raw18([::core::primitive::u8; 18usize]), - #[codec(index = 20)] - Raw19([::core::primitive::u8; 19usize]), - #[codec(index = 21)] - Raw20([::core::primitive::u8; 20usize]), - #[codec(index = 22)] - Raw21([::core::primitive::u8; 21usize]), - #[codec(index = 23)] - Raw22([::core::primitive::u8; 22usize]), - #[codec(index = 24)] - Raw23([::core::primitive::u8; 23usize]), - #[codec(index = 25)] - Raw24([::core::primitive::u8; 24usize]), - #[codec(index = 26)] - Raw25([::core::primitive::u8; 25usize]), - #[codec(index = 27)] - Raw26([::core::primitive::u8; 26usize]), - #[codec(index = 28)] - Raw27([::core::primitive::u8; 27usize]), - #[codec(index = 29)] - Raw28([::core::primitive::u8; 28usize]), - #[codec(index = 30)] - Raw29([::core::primitive::u8; 29usize]), - #[codec(index = 31)] - Raw30([::core::primitive::u8; 30usize]), - #[codec(index = 32)] - Raw31([::core::primitive::u8; 31usize]), - #[codec(index = 33)] - Raw32([::core::primitive::u8; 32usize]), - #[codec(index = 34)] - BlakeTwo256([::core::primitive::u8; 32usize]), - #[codec(index = 35)] - Sha256([::core::primitive::u8; 32usize]), - #[codec(index = 36)] - Keccak256([::core::primitive::u8; 32usize]), - #[codec(index = 37)] - ShaThree256([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum IdentityField { - #[codec(index = 1)] - Display, - #[codec(index = 2)] - Legal, - #[codec(index = 4)] - Web, - #[codec(index = 8)] - Riot, - #[codec(index = 16)] - Email, - #[codec(index = 32)] - PgpFingerprint, - #[codec(index = 64)] - Image, - #[codec(index = 128)] - Twitter, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IdentityInfo { - pub additional: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - runtime_types::pallet_identity::types::Data, - runtime_types::pallet_identity::types::Data, - )>, - pub display: runtime_types::pallet_identity::types::Data, - pub legal: runtime_types::pallet_identity::types::Data, - pub web: runtime_types::pallet_identity::types::Data, - pub riot: runtime_types::pallet_identity::types::Data, - pub email: runtime_types::pallet_identity::types::Data, - pub pgp_fingerprint: ::core::option::Option<[::core::primitive::u8; 20usize]>, - pub image: runtime_types::pallet_identity::types::Data, - pub twitter: runtime_types::pallet_identity::types::Data, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Judgement<_0> { - #[codec(index = 0)] - Unknown, - #[codec(index = 1)] - FeePaid(_0), - #[codec(index = 2)] - Reasonable, - #[codec(index = 3)] - KnownGood, - #[codec(index = 4)] - OutOfDate, - #[codec(index = 5)] - LowQuality, - #[codec(index = 6)] - Erroneous, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RegistrarInfo<_0, _1> { - pub account: _1, - pub fee: _0, - pub fields: runtime_types::pallet_identity::types::BitFlags< - runtime_types::pallet_identity::types::IdentityField, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Registration<_0> { - pub judgements: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - ::core::primitive::u32, - runtime_types::pallet_identity::types::Judgement<_0>, - )>, - pub deposit: _0, - pub info: runtime_types::pallet_identity::types::IdentityInfo, - } - } - } - pub mod pallet_im_online { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - heartbeat { - heartbeat: - runtime_types::pallet_im_online::Heartbeat<::core::primitive::u32>, - signature: runtime_types::pallet_im_online::sr25519::app_sr25519::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidKey, - #[codec(index = 1)] - DuplicatedHeartbeat, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - HeartbeatReceived { - authority_id: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - }, - #[codec(index = 1)] - AllGood, - #[codec(index = 2)] - SomeOffline { - offline: ::std::vec::Vec<( - ::sp_core::crypto::AccountId32, - runtime_types::pallet_staking::Exposure< - ::sp_core::crypto::AccountId32, - ::core::primitive::u128, - >, - )>, - }, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod app_sr25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BoundedOpaqueNetworkState { - pub peer_id: runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - pub external_addresses: - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Heartbeat<_0> { - pub block_number: _0, - pub network_state: runtime_types::sp_core::offchain::OpaqueNetworkState, - pub session_index: _0, - pub authority_index: _0, - pub validators_len: _0, - } - } - pub mod pallet_indices { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - claim { index: ::core::primitive::u32 }, - #[codec(index = 1)] - transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - }, - #[codec(index = 2)] - free { index: ::core::primitive::u32 }, - #[codec(index = 3)] - force_transfer { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - index: ::core::primitive::u32, - freeze: ::core::primitive::bool, - }, - #[codec(index = 4)] - freeze { index: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAssigned, - #[codec(index = 1)] - NotOwner, - #[codec(index = 2)] - InUse, - #[codec(index = 3)] - NotTransfer, - #[codec(index = 4)] - Permanent, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - IndexAssigned { - who: ::sp_core::crypto::AccountId32, - index: ::core::primitive::u32, - }, - #[codec(index = 1)] - IndexFreed { index: ::core::primitive::u32 }, - #[codec(index = 2)] - IndexFrozen { - index: ::core::primitive::u32, - who: ::sp_core::crypto::AccountId32, - }, - } - } - } - pub mod pallet_message_queue { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] reap_page { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , } , # [codec (index = 1)] execute_overweight { message_origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page : :: core :: primitive :: u32 , index : :: core :: primitive :: u32 , weight_limit : :: sp_weights :: Weight , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotReapable, - #[codec(index = 1)] - NoPage, - #[codec(index = 2)] - NoMessage, - #[codec(index = 3)] - AlreadyProcessed, - #[codec(index = 4)] - Queued, - #[codec(index = 5)] - InsufficientWeight, - #[codec(index = 6)] - TemporarilyUnprocessable, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - # [codec (index = 0)] ProcessingFailed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , error : runtime_types :: frame_support :: traits :: messages :: ProcessMessageError , } , # [codec (index = 1)] Processed { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , weight_used : :: sp_weights :: Weight , success : :: core :: primitive :: bool , } , # [codec (index = 2)] OverweightEnqueued { id : [:: core :: primitive :: u8 ; 32usize] , origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , page_index : :: core :: primitive :: u32 , message_index : :: core :: primitive :: u32 , } , # [codec (index = 3)] PageReaped { origin : runtime_types :: polkadot_runtime_parachains :: inclusion :: AggregateMessageOrigin , index : :: core :: primitive :: u32 , } , } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BookState<_0> { - pub begin: ::core::primitive::u32, - pub end: ::core::primitive::u32, - pub count: ::core::primitive::u32, - pub ready_neighbours: - ::core::option::Option>, - pub message_count: ::core::primitive::u64, - pub size: ::core::primitive::u64, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Neighbours<_0> { - pub prev: _0, - pub next: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Page<_0> { - pub remaining: _0, - pub remaining_size: _0, - pub first_index: _0, - pub first: _0, - pub last: _0, - pub heap: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - } - } - pub mod pallet_multisig { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_multi_threshold_1 { - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - approve_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - maybe_timepoint: ::core::option::Option< - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - >, - call_hash: [::core::primitive::u8; 32usize], - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 3)] - cancel_as_multi { - threshold: ::core::primitive::u16, - other_signatories: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - call_hash: [::core::primitive::u8; 32usize], - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - MinimumThreshold, - #[codec(index = 1)] - AlreadyApproved, - #[codec(index = 2)] - NoApprovalsNeeded, - #[codec(index = 3)] - TooFewSignatories, - #[codec(index = 4)] - TooManySignatories, - #[codec(index = 5)] - SignatoriesOutOfOrder, - #[codec(index = 6)] - SenderInSignatories, - #[codec(index = 7)] - NotFound, - #[codec(index = 8)] - NotOwner, - #[codec(index = 9)] - NoTimepoint, - #[codec(index = 10)] - WrongTimepoint, - #[codec(index = 11)] - UnexpectedTimepoint, - #[codec(index = 12)] - MaxWeightTooLow, - #[codec(index = 13)] - AlreadyStored, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewMultisig { - approving: ::sp_core::crypto::AccountId32, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 1)] - MultisigApproval { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - MultisigExecuted { - approving: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - MultisigCancelled { - cancelling: ::sp_core::crypto::AccountId32, - timepoint: - runtime_types::pallet_multisig::Timepoint<::core::primitive::u32>, - multisig: ::sp_core::crypto::AccountId32, - call_hash: [::core::primitive::u8; 32usize], - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Multisig<_0, _1, _2> { - pub when: runtime_types::pallet_multisig::Timepoint<_0>, - pub deposit: _1, - pub depositor: _2, - pub approvals: runtime_types::bounded_collections::bounded_vec::BoundedVec<_2>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Timepoint<_0> { - pub height: _0, - pub index: _0, - } - } - pub mod pallet_nomination_pools { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - join { - #[codec(compact)] - amount: ::core::primitive::u128, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 1)] - bond_extra { - extra: runtime_types::pallet_nomination_pools::BondExtra< - ::core::primitive::u128, - >, - }, - #[codec(index = 2)] - claim_payout, - #[codec(index = 3)] - unbond { - member_account: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - #[codec(compact)] - unbonding_points: ::core::primitive::u128, - }, - #[codec(index = 4)] - pool_withdraw_unbonded { - pool_id: ::core::primitive::u32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 5)] - withdraw_unbonded { - member_account: - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 6)] - create { - #[codec(compact)] - amount: ::core::primitive::u128, - root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 7)] - create_with_pool_id { - #[codec(compact)] - amount: ::core::primitive::u128, - root: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - nominator: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - bouncer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 8)] - nominate { - pool_id: ::core::primitive::u32, - validators: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 9)] - set_state { - pool_id: ::core::primitive::u32, - state: runtime_types::pallet_nomination_pools::PoolState, - }, - #[codec(index = 10)] - set_metadata { - pool_id: ::core::primitive::u32, - metadata: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 11)] - set_configs { - min_join_bond: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u128, - >, - min_create_bond: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u128, - >, - max_pools: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - max_members: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - max_members_per_pool: runtime_types::pallet_nomination_pools::ConfigOp< - ::core::primitive::u32, - >, - global_max_commission: runtime_types::pallet_nomination_pools::ConfigOp< - runtime_types::sp_arithmetic::per_things::Perbill, - >, - }, - #[codec(index = 12)] - update_roles { - pool_id: ::core::primitive::u32, - new_root: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - new_nominator: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - new_bouncer: runtime_types::pallet_nomination_pools::ConfigOp< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 13)] - chill { pool_id: ::core::primitive::u32 }, - #[codec(index = 14)] - bond_extra_other { - member: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - extra: runtime_types::pallet_nomination_pools::BondExtra< - ::core::primitive::u128, - >, - }, - #[codec(index = 15)] - set_claim_permission { - permission: runtime_types::pallet_nomination_pools::ClaimPermission, - }, - #[codec(index = 16)] - claim_payout_other { other: ::sp_core::crypto::AccountId32 }, - #[codec(index = 17)] - set_commission { - pool_id: ::core::primitive::u32, - new_commission: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - }, - #[codec(index = 18)] - set_commission_max { - pool_id: ::core::primitive::u32, - max_commission: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 19)] - set_commission_change_rate { - pool_id: ::core::primitive::u32, - change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - }, - #[codec(index = 20)] - claim_commission { pool_id: ::core::primitive::u32 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DefensiveError { - #[codec(index = 0)] - NotEnoughSpaceInUnbondPool, - #[codec(index = 1)] - PoolNotFound, - #[codec(index = 2)] - RewardPoolNotFound, - #[codec(index = 3)] - SubPoolsNotFound, - #[codec(index = 4)] - BondedStashKilledPrematurely, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - PoolNotFound, - #[codec(index = 1)] - PoolMemberNotFound, - #[codec(index = 2)] - RewardPoolNotFound, - #[codec(index = 3)] - SubPoolsNotFound, - #[codec(index = 4)] - AccountBelongsToOtherPool, - #[codec(index = 5)] - FullyUnbonding, - #[codec(index = 6)] - MaxUnbondingLimit, - #[codec(index = 7)] - CannotWithdrawAny, - #[codec(index = 8)] - MinimumBondNotMet, - #[codec(index = 9)] - OverflowRisk, - #[codec(index = 10)] - NotDestroying, - #[codec(index = 11)] - NotNominator, - #[codec(index = 12)] - NotKickerOrDestroying, - #[codec(index = 13)] - NotOpen, - #[codec(index = 14)] - MaxPools, - #[codec(index = 15)] - MaxPoolMembers, - #[codec(index = 16)] - CanNotChangeState, - #[codec(index = 17)] - DoesNotHavePermission, - #[codec(index = 18)] - MetadataExceedsMaxLen, - #[codec(index = 19)] - Defensive(runtime_types::pallet_nomination_pools::pallet::DefensiveError), - #[codec(index = 20)] - PartialUnbondNotAllowedPermissionlessly, - #[codec(index = 21)] - MaxCommissionRestricted, - #[codec(index = 22)] - CommissionExceedsMaximum, - #[codec(index = 23)] - CommissionChangeThrottled, - #[codec(index = 24)] - CommissionChangeRateNotAllowed, - #[codec(index = 25)] - NoPendingCommission, - #[codec(index = 26)] - NoCommissionCurrentSet, - #[codec(index = 27)] - PoolIdInUse, - #[codec(index = 28)] - InvalidPoolId, - #[codec(index = 29)] - BondExtraRestricted, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { - depositor: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - }, - #[codec(index = 1)] - Bonded { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - bonded: ::core::primitive::u128, - joined: ::core::primitive::bool, - }, - #[codec(index = 2)] - PaidOut { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - payout: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unbonded { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - points: ::core::primitive::u128, - era: ::core::primitive::u32, - }, - #[codec(index = 4)] - Withdrawn { - member: ::sp_core::crypto::AccountId32, - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - points: ::core::primitive::u128, - }, - #[codec(index = 5)] - Destroyed { pool_id: ::core::primitive::u32 }, - #[codec(index = 6)] - StateChanged { - pool_id: ::core::primitive::u32, - new_state: runtime_types::pallet_nomination_pools::PoolState, - }, - #[codec(index = 7)] - MemberRemoved { - pool_id: ::core::primitive::u32, - member: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 8)] - RolesUpdated { - root: ::core::option::Option<::sp_core::crypto::AccountId32>, - bouncer: ::core::option::Option<::sp_core::crypto::AccountId32>, - nominator: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 9)] - PoolSlashed { - pool_id: ::core::primitive::u32, - balance: ::core::primitive::u128, - }, - #[codec(index = 10)] - UnbondingPoolSlashed { - pool_id: ::core::primitive::u32, - era: ::core::primitive::u32, - balance: ::core::primitive::u128, - }, - #[codec(index = 11)] - PoolCommissionUpdated { - pool_id: ::core::primitive::u32, - current: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - }, - #[codec(index = 12)] - PoolMaxCommissionUpdated { - pool_id: ::core::primitive::u32, - max_commission: runtime_types::sp_arithmetic::per_things::Perbill, - }, - #[codec(index = 13)] - PoolCommissionChangeRateUpdated { - pool_id: ::core::primitive::u32, - change_rate: runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - }, - #[codec(index = 14)] - PoolCommissionClaimed { - pool_id: ::core::primitive::u32, - commission: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BondExtra<_0> { - #[codec(index = 0)] - FreeBalance(_0), - #[codec(index = 1)] - Rewards, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BondedPoolInner { - pub commission: runtime_types::pallet_nomination_pools::Commission, - pub member_counter: ::core::primitive::u32, - pub points: ::core::primitive::u128, - pub roles: runtime_types::pallet_nomination_pools::PoolRoles< - ::sp_core::crypto::AccountId32, - >, - pub state: runtime_types::pallet_nomination_pools::PoolState, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ClaimPermission { - #[codec(index = 0)] - Permissioned, - #[codec(index = 1)] - PermissionlessCompound, - #[codec(index = 2)] - PermissionlessWithdraw, - #[codec(index = 3)] - PermissionlessAll, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Commission { - pub current: ::core::option::Option<( - runtime_types::sp_arithmetic::per_things::Perbill, - ::sp_core::crypto::AccountId32, - )>, - pub max: ::core::option::Option, - pub change_rate: ::core::option::Option< - runtime_types::pallet_nomination_pools::CommissionChangeRate< - ::core::primitive::u32, - >, - >, - pub throttle_from: ::core::option::Option<::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommissionChangeRate<_0> { - pub max_increase: runtime_types::sp_arithmetic::per_things::Perbill, - pub min_delay: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConfigOp<_0> { - #[codec(index = 0)] - Noop, - #[codec(index = 1)] - Set(_0), - #[codec(index = 2)] - Remove, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PoolMember { - pub pool_id: ::core::primitive::u32, - pub points: ::core::primitive::u128, - pub last_recorded_reward_counter: - runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub unbonding_eras: - runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< - ::core::primitive::u32, - ::core::primitive::u128, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PoolRoles<_0> { - pub depositor: _0, - pub root: ::core::option::Option<_0>, - pub nominator: ::core::option::Option<_0>, - pub bouncer: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PoolState { - #[codec(index = 0)] - Open, - #[codec(index = 1)] - Blocked, - #[codec(index = 2)] - Destroying, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RewardPool { - pub last_recorded_reward_counter: - runtime_types::sp_arithmetic::fixed_point::FixedU128, - pub last_recorded_total_payouts: ::core::primitive::u128, - pub total_rewards_claimed: ::core::primitive::u128, - pub total_commission_pending: ::core::primitive::u128, - pub total_commission_claimed: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SubPools { - pub no_era: runtime_types::pallet_nomination_pools::UnbondPool, - pub with_era: - runtime_types::bounded_collections::bounded_btree_map::BoundedBTreeMap< - ::core::primitive::u32, - runtime_types::pallet_nomination_pools::UnbondPool, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnbondPool { - pub points: ::core::primitive::u128, - pub balance: ::core::primitive::u128, - } - } - pub mod pallet_offences { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Offence { - kind: [::core::primitive::u8; 16usize], - timeslot: ::std::vec::Vec<::core::primitive::u8>, - }, - } - } - } - pub mod pallet_preimage { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - note_preimage { bytes: ::std::vec::Vec<::core::primitive::u8> }, - #[codec(index = 1)] - unnote_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - request_preimage { hash: ::subxt::utils::H256 }, - #[codec(index = 3)] - unrequest_preimage { hash: ::subxt::utils::H256 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooBig, - #[codec(index = 1)] - AlreadyNoted, - #[codec(index = 2)] - NotAuthorized, - #[codec(index = 3)] - NotNoted, - #[codec(index = 4)] - Requested, - #[codec(index = 5)] - NotRequested, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Noted { hash: ::subxt::utils::H256 }, - #[codec(index = 1)] - Requested { hash: ::subxt::utils::H256 }, - #[codec(index = 2)] - Cleared { hash: ::subxt::utils::H256 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RequestStatus<_0, _1> { - #[codec(index = 0)] - Unrequested { deposit: (_0, _1), len: ::core::primitive::u32 }, - #[codec(index = 1)] - Requested { - deposit: ::core::option::Option<(_0, _1)>, - count: ::core::primitive::u32, - len: ::core::option::Option<::core::primitive::u32>, - }, - } - } - pub mod pallet_proxy { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - proxy { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - add_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::westend_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 2)] - remove_proxy { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::westend_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 3)] - remove_proxies, - #[codec(index = 4)] - create_pure { - proxy_type: runtime_types::westend_runtime::ProxyType, - delay: ::core::primitive::u32, - index: ::core::primitive::u16, - }, - #[codec(index = 5)] - kill_pure { - spawner: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - proxy_type: runtime_types::westend_runtime::ProxyType, - index: ::core::primitive::u16, - #[codec(compact)] - height: ::core::primitive::u32, - #[codec(compact)] - ext_index: ::core::primitive::u32, - }, - #[codec(index = 6)] - announce { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 7)] - remove_announcement { - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 8)] - reject_announcement { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 9)] - proxy_announced { - delegate: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - real: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - force_proxy_type: - ::core::option::Option, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooMany, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - NotProxy, - #[codec(index = 3)] - Unproxyable, - #[codec(index = 4)] - Duplicate, - #[codec(index = 5)] - NoPermission, - #[codec(index = 6)] - Unannounced, - #[codec(index = 7)] - NoSelfProxy, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - ProxyExecuted { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - PureCreated { - pure: ::sp_core::crypto::AccountId32, - who: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::westend_runtime::ProxyType, - disambiguation_index: ::core::primitive::u16, - }, - #[codec(index = 2)] - Announced { - real: ::sp_core::crypto::AccountId32, - proxy: ::sp_core::crypto::AccountId32, - call_hash: ::subxt::utils::H256, - }, - #[codec(index = 3)] - ProxyAdded { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::westend_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - #[codec(index = 4)] - ProxyRemoved { - delegator: ::sp_core::crypto::AccountId32, - delegatee: ::sp_core::crypto::AccountId32, - proxy_type: runtime_types::westend_runtime::ProxyType, - delay: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Announcement<_0, _1, _2> { - pub real: _0, - pub call_hash: _1, - pub height: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ProxyDefinition<_0, _1, _2> { - pub delegate: _0, - pub proxy_type: _1, - pub delay: _2, - } - } - pub mod pallet_recovery { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - as_recovered { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - set_recovered { - lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - create_recovery { - friends: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - threshold: ::core::primitive::u16, - delay_period: ::core::primitive::u32, - }, - #[codec(index = 3)] - initiate_recovery { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 4)] - vouch_recovery { - lost: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 5)] - claim_recovery { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 6)] - close_recovery { - rescuer: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 7)] - remove_recovery, - #[codec(index = 8)] - cancel_recovered { - account: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotAllowed, - #[codec(index = 1)] - ZeroThreshold, - #[codec(index = 2)] - NotEnoughFriends, - #[codec(index = 3)] - MaxFriends, - #[codec(index = 4)] - NotSorted, - #[codec(index = 5)] - NotRecoverable, - #[codec(index = 6)] - AlreadyRecoverable, - #[codec(index = 7)] - AlreadyStarted, - #[codec(index = 8)] - NotStarted, - #[codec(index = 9)] - NotFriend, - #[codec(index = 10)] - DelayPeriod, - #[codec(index = 11)] - AlreadyVouched, - #[codec(index = 12)] - Threshold, - #[codec(index = 13)] - StillActive, - #[codec(index = 14)] - AlreadyProxy, - #[codec(index = 15)] - BadState, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - RecoveryCreated { account: ::sp_core::crypto::AccountId32 }, - #[codec(index = 1)] - RecoveryInitiated { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 2)] - RecoveryVouched { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - sender: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - RecoveryClosed { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 4)] - AccountRecovered { - lost_account: ::sp_core::crypto::AccountId32, - rescuer_account: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 5)] - RecoveryRemoved { lost_account: ::sp_core::crypto::AccountId32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ActiveRecovery<_0, _1, _2> { - pub created: _0, - pub deposit: _1, - pub friends: _2, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RecoveryConfig<_0, _1, _2> { - pub delay_period: _0, - pub deposit: _1, - pub friends: _2, - pub threshold: ::core::primitive::u16, - } - } - pub mod pallet_scheduler { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - schedule { - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 1)] - cancel { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - schedule_named { - id: [::core::primitive::u8; 32usize], - when: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 3)] - cancel_named { id: [::core::primitive::u8; 32usize] }, - #[codec(index = 4)] - schedule_after { - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - #[codec(index = 5)] - schedule_named_after { - id: [::core::primitive::u8; 32usize], - after: ::core::primitive::u32, - maybe_periodic: ::core::option::Option<( - ::core::primitive::u32, - ::core::primitive::u32, - )>, - priority: ::core::primitive::u8, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FailedToSchedule, - #[codec(index = 1)] - NotFound, - #[codec(index = 2)] - TargetBlockNumberInPast, - #[codec(index = 3)] - RescheduleNoChange, - #[codec(index = 4)] - Named, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Scheduled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 1)] - Canceled { when: ::core::primitive::u32, index: ::core::primitive::u32 }, - #[codec(index = 2)] - Dispatched { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 3)] - CallUnavailable { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 4)] - PeriodicFailed { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - #[codec(index = 5)] - PermanentlyOverweight { - task: (::core::primitive::u32, ::core::primitive::u32), - id: ::core::option::Option<[::core::primitive::u8; 32usize]>, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Scheduled<_0, _1, _2, _3, _4> { - pub maybe_id: ::core::option::Option<_0>, - pub priority: ::core::primitive::u8, - pub call: _1, - pub maybe_periodic: ::core::option::Option<(_2, _2)>, - pub origin: _3, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_4>, - } - } - pub mod pallet_session { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set_keys { - keys: runtime_types::westend_runtime::SessionKeys, - proof: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 1)] - purge_keys, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidProof, - #[codec(index = 1)] - NoAssociatedValidatorId, - #[codec(index = 2)] - DuplicatedKey, - #[codec(index = 3)] - NoKeys, - #[codec(index = 4)] - NoAccount, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewSession { session_index: ::core::primitive::u32 }, - } - } - } - pub mod pallet_staking { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - bond { - #[codec(compact)] - value: ::core::primitive::u128, - payee: runtime_types::pallet_staking::RewardDestination< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 1)] - bond_extra { - #[codec(compact)] - max_additional: ::core::primitive::u128, - }, - #[codec(index = 2)] - unbond { - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 3)] - withdraw_unbonded { num_slashing_spans: ::core::primitive::u32 }, - #[codec(index = 4)] - validate { prefs: runtime_types::pallet_staking::ValidatorPrefs }, - #[codec(index = 5)] - nominate { - targets: ::std::vec::Vec< - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - >, - }, - #[codec(index = 6)] - chill, - #[codec(index = 7)] - set_payee { - payee: runtime_types::pallet_staking::RewardDestination< - ::sp_core::crypto::AccountId32, - >, - }, - #[codec(index = 8)] - set_controller, - #[codec(index = 9)] - set_validator_count { - #[codec(compact)] - new: ::core::primitive::u32, - }, - #[codec(index = 10)] - increase_validator_count { - #[codec(compact)] - additional: ::core::primitive::u32, - }, - #[codec(index = 11)] - scale_validator_count { - factor: runtime_types::sp_arithmetic::per_things::Percent, - }, - #[codec(index = 12)] - force_no_eras, - #[codec(index = 13)] - force_new_era, - #[codec(index = 14)] - set_invulnerables { - invulnerables: ::std::vec::Vec<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 15)] - force_unstake { - stash: ::sp_core::crypto::AccountId32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 16)] - force_new_era_always, - #[codec(index = 17)] - cancel_deferred_slash { - era: ::core::primitive::u32, - slash_indices: ::std::vec::Vec<::core::primitive::u32>, - }, - #[codec(index = 18)] - payout_stakers { - validator_stash: ::sp_core::crypto::AccountId32, - era: ::core::primitive::u32, - }, - #[codec(index = 19)] - rebond { - #[codec(compact)] - value: ::core::primitive::u128, - }, - #[codec(index = 20)] - reap_stash { - stash: ::sp_core::crypto::AccountId32, - num_slashing_spans: ::core::primitive::u32, - }, - #[codec(index = 21)] - kick { - who: ::std::vec::Vec< - ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - >, - }, - #[codec(index = 22)] - set_staking_configs { - min_nominator_bond: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u128, - >, - min_validator_bond: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u128, - >, - max_nominator_count: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u32, - >, - max_validator_count: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - ::core::primitive::u32, - >, - chill_threshold: - runtime_types::pallet_staking::pallet::pallet::ConfigOp< - runtime_types::sp_arithmetic::per_things::Percent, - >, - min_commission: runtime_types::pallet_staking::pallet::pallet::ConfigOp< - runtime_types::sp_arithmetic::per_things::Perbill, - >, - }, - #[codec(index = 23)] - chill_other { controller: ::sp_core::crypto::AccountId32 }, - #[codec(index = 24)] - force_apply_min_commission { - validator_stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 25)] - set_min_commission { - new: runtime_types::sp_arithmetic::per_things::Perbill, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ConfigOp<_0> { - #[codec(index = 0)] - Noop, - #[codec(index = 1)] - Set(_0), - #[codec(index = 2)] - Remove, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotController, - #[codec(index = 1)] - NotStash, - #[codec(index = 2)] - AlreadyBonded, - #[codec(index = 3)] - AlreadyPaired, - #[codec(index = 4)] - EmptyTargets, - #[codec(index = 5)] - DuplicateIndex, - #[codec(index = 6)] - InvalidSlashIndex, - #[codec(index = 7)] - InsufficientBond, - #[codec(index = 8)] - NoMoreChunks, - #[codec(index = 9)] - NoUnlockChunk, - #[codec(index = 10)] - FundedTarget, - #[codec(index = 11)] - InvalidEraToReward, - #[codec(index = 12)] - InvalidNumberOfNominations, - #[codec(index = 13)] - NotSortedAndUnique, - #[codec(index = 14)] - AlreadyClaimed, - #[codec(index = 15)] - IncorrectHistoryDepth, - #[codec(index = 16)] - IncorrectSlashingSpans, - #[codec(index = 17)] - BadState, - #[codec(index = 18)] - TooManyTargets, - #[codec(index = 19)] - BadTarget, - #[codec(index = 20)] - CannotChillOther, - #[codec(index = 21)] - TooManyNominators, - #[codec(index = 22)] - TooManyValidators, - #[codec(index = 23)] - CommissionTooLow, - #[codec(index = 24)] - BoundNotMet, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - EraPaid { - era_index: ::core::primitive::u32, - validator_payout: ::core::primitive::u128, - remainder: ::core::primitive::u128, - }, - #[codec(index = 1)] - Rewarded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Slashed { - staker: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - SlashReported { - validator: ::sp_core::crypto::AccountId32, - fraction: runtime_types::sp_arithmetic::per_things::Perbill, - slash_era: ::core::primitive::u32, - }, - #[codec(index = 4)] - OldSlashingReportDiscarded { session_index: ::core::primitive::u32 }, - #[codec(index = 5)] - StakersElected, - #[codec(index = 6)] - Bonded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 7)] - Unbonded { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 8)] - Withdrawn { - stash: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 9)] - Kicked { - nominator: ::sp_core::crypto::AccountId32, - stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 10)] - StakingElectionFailed, - #[codec(index = 11)] - Chilled { stash: ::sp_core::crypto::AccountId32 }, - #[codec(index = 12)] - PayoutStarted { - era_index: ::core::primitive::u32, - validator_stash: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 13)] - ValidatorPrefsSet { - stash: ::sp_core::crypto::AccountId32, - prefs: runtime_types::pallet_staking::ValidatorPrefs, - }, - #[codec(index = 14)] - ForceEra { mode: runtime_types::pallet_staking::Forcing }, - } - } - } - pub mod slashing { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SlashingSpans { - pub span_index: ::core::primitive::u32, - pub last_start: ::core::primitive::u32, - pub last_nonzero_slash: ::core::primitive::u32, - pub prior: ::std::vec::Vec<::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SpanRecord<_0> { - pub slashed: _0, - pub paid_out: _0, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ActiveEraInfo { - pub index: ::core::primitive::u32, - pub start: ::core::option::Option<::core::primitive::u64>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EraRewardPoints<_0> { - pub total: ::core::primitive::u32, - pub individual: ::subxt::utils::KeyedVec<_0, ::core::primitive::u32>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Exposure<_0, _1> { - #[codec(compact)] - pub total: _1, - #[codec(compact)] - pub own: _1, - pub others: - ::std::vec::Vec>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Forcing { - #[codec(index = 0)] - NotForcing, - #[codec(index = 1)] - ForceNew, - #[codec(index = 2)] - ForceNone, - #[codec(index = 3)] - ForceAlways, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndividualExposure<_0, _1> { - pub who: _0, - #[codec(compact)] - pub value: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Nominations { - pub targets: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::sp_core::crypto::AccountId32, - >, - pub submitted_in: ::core::primitive::u32, - pub suppressed: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RewardDestination<_0> { - #[codec(index = 0)] - Staked, - #[codec(index = 1)] - Stash, - #[codec(index = 2)] - Controller, - #[codec(index = 3)] - Account(_0), - #[codec(index = 4)] - None, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct StakingLedger { - pub stash: ::sp_core::crypto::AccountId32, - #[codec(compact)] - pub total: ::core::primitive::u128, - #[codec(compact)] - pub active: ::core::primitive::u128, - pub unlocking: runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::pallet_staking::UnlockChunk<::core::primitive::u128>, - >, - pub claimed_rewards: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u32, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnappliedSlash<_0, _1> { - pub validator: _0, - pub own: _1, - pub others: ::std::vec::Vec<(_0, _1)>, - pub reporters: ::std::vec::Vec<_0>, - pub payout: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UnlockChunk<_0> { - #[codec(compact)] - pub value: _0, - #[codec(compact)] - pub era: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidatorPrefs { - #[codec(compact)] - pub commission: runtime_types::sp_arithmetic::per_things::Perbill, - pub blocked: ::core::primitive::bool, - } - } - pub mod pallet_sudo { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - sudo { call: ::std::boxed::Box }, - #[codec(index = 1)] - sudo_unchecked_weight { - call: ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - #[codec(index = 2)] - set_key { - new: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 3)] - sudo_as { - who: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - call: ::std::boxed::Box, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - RequireSudo, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Sudid { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - #[codec(index = 1)] - KeyChanged { - old_sudoer: ::core::option::Option<::sp_core::crypto::AccountId32>, - }, - #[codec(index = 2)] - SudoAsDone { - sudo_result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_timestamp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - set { - #[codec(compact)] - now: ::core::primitive::u64, - }, - } - } - } - pub mod pallet_transaction_payment { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - TransactionFeePaid { - who: ::sp_core::crypto::AccountId32, - actual_fee: ::core::primitive::u128, - tip: ::core::primitive::u128, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ChargeTransactionPayment(#[codec(compact)] pub ::core::primitive::u128); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V1Ancient, - #[codec(index = 1)] - V2, - } - } - pub mod pallet_utility { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - batch { calls: ::std::vec::Vec }, - #[codec(index = 1)] - as_derivative { - index: ::core::primitive::u16, - call: ::std::boxed::Box, - }, - #[codec(index = 2)] - batch_all { - calls: ::std::vec::Vec, - }, - #[codec(index = 3)] - dispatch_as { - as_origin: ::std::boxed::Box, - call: ::std::boxed::Box, - }, - #[codec(index = 4)] - force_batch { - calls: ::std::vec::Vec, - }, - #[codec(index = 5)] - with_weight { - call: ::std::boxed::Box, - weight: ::sp_weights::Weight, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyCalls, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - BatchInterrupted { - index: ::core::primitive::u32, - error: runtime_types::sp_runtime::DispatchError, - }, - #[codec(index = 1)] - BatchCompleted, - #[codec(index = 2)] - BatchCompletedWithErrors, - #[codec(index = 3)] - ItemCompleted, - #[codec(index = 4)] - ItemFailed { error: runtime_types::sp_runtime::DispatchError }, - #[codec(index = 5)] - DispatchedAs { - result: - ::core::result::Result<(), runtime_types::sp_runtime::DispatchError>, - }, - } - } - } - pub mod pallet_vesting { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - vest, - #[codec(index = 1)] - vest_other { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - }, - #[codec(index = 2)] - vested_transfer { - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 3)] - force_vested_transfer { - source: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - target: ::subxt::utils::MultiAddress<::sp_core::crypto::AccountId32, ()>, - schedule: runtime_types::pallet_vesting::vesting_info::VestingInfo< - ::core::primitive::u128, - ::core::primitive::u32, - >, - }, - #[codec(index = 4)] - merge_schedules { - schedule1_index: ::core::primitive::u32, - schedule2_index: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotVesting, - #[codec(index = 1)] - AtMaxVestingSchedules, - #[codec(index = 2)] - AmountLow, - #[codec(index = 3)] - ScheduleIndexOutOfBounds, - #[codec(index = 4)] - InvalidScheduleParams, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - VestingUpdated { - account: ::sp_core::crypto::AccountId32, - unvested: ::core::primitive::u128, - }, - #[codec(index = 1)] - VestingCompleted { account: ::sp_core::crypto::AccountId32 }, - } - } - pub mod vesting_info { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VestingInfo<_0, _1> { - pub locked: _0, - pub per_block: _0, - pub starting_block: _1, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Releases { - #[codec(index = 0)] - V0, - #[codec(index = 1)] - V1, - } - } - pub mod pallet_xcm { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - send { - dest: ::std::boxed::Box, - message: ::std::boxed::Box, - }, - #[codec(index = 1)] - teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 2)] - reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - }, - #[codec(index = 3)] - execute { - message: ::std::boxed::Box, - max_weight: ::sp_weights::Weight, - }, - #[codec(index = 4)] - force_xcm_version { - location: - ::std::boxed::Box, - xcm_version: ::core::primitive::u32, - }, - #[codec(index = 5)] - force_default_xcm_version { - maybe_xcm_version: ::core::option::Option<::core::primitive::u32>, - }, - #[codec(index = 6)] - force_subscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 7)] - force_unsubscribe_version_notify { - location: ::std::boxed::Box, - }, - #[codec(index = 8)] - limited_reserve_transfer_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 9)] - limited_teleport_assets { - dest: ::std::boxed::Box, - beneficiary: ::std::boxed::Box, - assets: ::std::boxed::Box, - fee_asset_item: ::core::primitive::u32, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 10)] - force_suspension { suspended: ::core::primitive::bool }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Unreachable, - #[codec(index = 1)] - SendFailure, - #[codec(index = 2)] - Filtered, - #[codec(index = 3)] - UnweighableMessage, - #[codec(index = 4)] - DestinationNotInvertible, - #[codec(index = 5)] - Empty, - #[codec(index = 6)] - CannotReanchor, - #[codec(index = 7)] - TooManyAssets, - #[codec(index = 8)] - InvalidOrigin, - #[codec(index = 9)] - BadVersion, - #[codec(index = 10)] - BadLocation, - #[codec(index = 11)] - NoSubscription, - #[codec(index = 12)] - AlreadySubscribed, - #[codec(index = 13)] - InvalidAsset, - #[codec(index = 14)] - LowBalance, - #[codec(index = 15)] - TooManyLocks, - #[codec(index = 16)] - AccountNotSovereign, - #[codec(index = 17)] - FeesNotMet, - #[codec(index = 18)] - LockNotFound, - #[codec(index = 19)] - InUse, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Attempted(runtime_types::xcm::v3::traits::Outcome), - #[codec(index = 1)] - Sent( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::Xcm, - ), - #[codec(index = 2)] - UnexpectedResponse( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 3)] - ResponseReady(::core::primitive::u64, runtime_types::xcm::v3::Response), - #[codec(index = 4)] - Notified(::core::primitive::u64, ::core::primitive::u8, ::core::primitive::u8), - #[codec(index = 5)] - NotifyOverweight( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ::sp_weights::Weight, - ::sp_weights::Weight, - ), - #[codec(index = 6)] - NotifyDispatchError( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 7)] - NotifyDecodeFailed( - ::core::primitive::u64, - ::core::primitive::u8, - ::core::primitive::u8, - ), - #[codec(index = 8)] - InvalidResponder( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 9)] - InvalidResponderVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 10)] - ResponseTaken(::core::primitive::u64), - #[codec(index = 11)] - AssetsTrapped( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - #[codec(index = 12)] - VersionChangeNotified( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 13)] - SupportedVersionChanged( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u32, - ), - #[codec(index = 14)] - NotifyTargetSendFail( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::traits::Error, - ), - #[codec(index = 15)] - NotifyTargetMigrationFail( - runtime_types::xcm::VersionedMultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 16)] - InvalidQuerierVersion( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - ), - #[codec(index = 17)] - InvalidQuerier( - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::primitive::u64, - runtime_types::xcm::v3::multilocation::MultiLocation, - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 18)] - VersionNotifyStarted( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 19)] - VersionNotifyRequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 20)] - VersionNotifyUnrequested( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 21)] - FeesPaid( - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::v3::multiasset::MultiAssets, - ), - #[codec(index = 22)] - AssetsClaimed( - ::subxt::utils::H256, - runtime_types::xcm::v3::multilocation::MultiLocation, - runtime_types::xcm::VersionedMultiAssets, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Xcm(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Response(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum QueryStatus<_0> { - #[codec(index = 0)] - Pending { - responder: runtime_types::xcm::VersionedMultiLocation, - maybe_match_querier: - ::core::option::Option, - maybe_notify: - ::core::option::Option<(::core::primitive::u8, ::core::primitive::u8)>, - timeout: _0, - }, - #[codec(index = 1)] - VersionNotifier { - origin: runtime_types::xcm::VersionedMultiLocation, - is_active: ::core::primitive::bool, - }, - #[codec(index = 2)] - Ready { response: runtime_types::xcm::VersionedResponse, at: _0 }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RemoteLockedFungibleRecord<_0> { - pub amount: ::core::primitive::u128, - pub owner: runtime_types::xcm::VersionedMultiLocation, - pub locker: runtime_types::xcm::VersionedMultiLocation, - pub consumers: runtime_types::bounded_collections::bounded_vec::BoundedVec<( - _0, - ::core::primitive::u128, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionMigrationStage { - #[codec(index = 0)] - MigrateSupportedVersion, - #[codec(index = 1)] - MigrateVersionNotifiers, - #[codec(index = 2)] - NotifyCurrentTargets( - ::core::option::Option<::std::vec::Vec<::core::primitive::u8>>, - ), - #[codec(index = 3)] - MigrateAndNotifyOldTargets, - } - } - } - pub mod polkadot_core_primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateHash(pub ::subxt::utils::H256); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundDownwardMessage<_0> { - pub sent_at: _0, - pub msg: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InboundHrmpMessage<_0> { - pub sent_at: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OutboundHrmpMessage<_0> { - pub recipient: _0, - pub data: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod polkadot_parachain { - use super::runtime_types; - pub mod primitives { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HeadData(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannelId { - pub sender: runtime_types::polkadot_parachain::primitives::Id, - pub recipient: runtime_types::polkadot_parachain::primitives::Id, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Id(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCode(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ValidationCodeHash(pub ::subxt::utils::H256); - } - } - pub mod polkadot_primitives { - use super::runtime_types; - pub mod v4 { - use super::runtime_types; - pub mod assignment_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod collator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - pub mod executor_params { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ExecutorParam { - #[codec(index = 1)] - MaxMemoryPages(::core::primitive::u32), - #[codec(index = 2)] - StackLogicalMax(::core::primitive::u32), - #[codec(index = 3)] - StackNativeMax(::core::primitive::u32), - #[codec(index = 4)] - PrecheckingMaxMemory(::core::primitive::u64), - #[codec(index = 5)] - PvfPrepTimeout( - runtime_types::polkadot_primitives::v4::PvfPrepTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 6)] - PvfExecTimeout( - runtime_types::polkadot_primitives::v4::PvfExecTimeoutKind, - ::core::primitive::u64, - ), - #[codec(index = 7)] - WasmExtBulkMemory, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ExecutorParams( - pub ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParam, - >, - ); - } - pub mod signed { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedSigned<_0, _1> { - pub payload: _0, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - pub signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_1>, - } - } - pub mod validator_app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::sr25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfield( - pub ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BackedCandidate<_0> { - pub candidate: - runtime_types::polkadot_primitives::v4::CommittedCandidateReceipt<_0>, - pub validity_votes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::ValidityAttestation, - >, - pub validator_indices: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateCommitments<_0> { - pub upward_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::std::vec::Vec<::core::primitive::u8>, - >, - pub horizontal_messages: - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::polkadot_core_primitives::OutboundHrmpMessage< - runtime_types::polkadot_parachain::primitives::Id, - >, - >, - pub new_validation_code: ::core::option::Option< - runtime_types::polkadot_parachain::primitives::ValidationCode, - >, - pub head_data: runtime_types::polkadot_parachain::primitives::HeadData, - pub processed_downward_messages: _0, - pub hrmp_watermark: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateDescriptor<_0> { - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub relay_parent: _0, - pub collator: runtime_types::polkadot_primitives::v4::collator_app::Public, - pub persisted_validation_data_hash: _0, - pub pov_hash: _0, - pub erasure_root: _0, - pub signature: runtime_types::polkadot_primitives::v4::collator_app::Signature, - pub para_head: _0, - pub validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments_hash: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CommittedCandidateReceipt<_0> { - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub commitments: runtime_types::polkadot_primitives::v4::CandidateCommitments< - ::core::primitive::u32, - >, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct CoreIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum CoreOccupied { - #[codec(index = 0)] - Parathread(runtime_types::polkadot_primitives::v4::ParathreadEntry), - #[codec(index = 1)] - Parachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeState<_0> { - pub validators_for: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub validators_against: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub start: _0, - pub concluded_at: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeStatement { - #[codec(index = 0)] - Valid(runtime_types::polkadot_primitives::v4::ValidDisputeStatementKind), - #[codec(index = 1)] - Invalid(runtime_types::polkadot_primitives::v4::InvalidDisputeStatementKind), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeStatementSet { - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub session: ::core::primitive::u32, - pub statements: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::DisputeStatement, - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Signature, - )>, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct GroupIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct IndexedVec<_0, _1>( - pub ::std::vec::Vec<_1>, - #[codec(skip)] pub ::core::marker::PhantomData<_0>, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct InherentData<_0> { - pub bitfields: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::signed::UncheckedSigned< - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - >, - >, - pub backed_candidates: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::BackedCandidate< - ::subxt::utils::H256, - >, - >, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - pub parent_header: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum InvalidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaim( - pub runtime_types::polkadot_parachain::primitives::Id, - pub runtime_types::polkadot_primitives::v4::collator_app::Public, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadEntry { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadClaim, - pub retries: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckStatement { - pub accept: ::core::primitive::bool, - pub subject: runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - pub session_index: ::core::primitive::u32, - pub validator_index: runtime_types::polkadot_primitives::v4::ValidatorIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfExecTimeoutKind { - #[codec(index = 0)] - Backing, - #[codec(index = 1)] - Approval, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfPrepTimeoutKind { - #[codec(index = 0)] - Precheck, - #[codec(index = 1)] - Lenient, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ScrapedOnChainVotes<_0> { - pub session: ::core::primitive::u32, - pub backing_validators_per_candidate: ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::CandidateReceipt<_0>, - ::std::vec::Vec<( - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::ValidityAttestation, - )>, - )>, - pub disputes: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::DisputeStatementSet, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionInfo { - pub active_validator_indices: - ::std::vec::Vec, - pub random_seed: [::core::primitive::u8; 32usize], - pub dispute_period: ::core::primitive::u32, - pub validators: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::ValidatorIndex, - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub discovery_keys: - ::std::vec::Vec, - pub assignment_keys: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::assignment_app::Public, - >, - pub validator_groups: runtime_types::polkadot_primitives::v4::IndexedVec< - runtime_types::polkadot_primitives::v4::GroupIndex, - ::std::vec::Vec, - >, - pub n_cores: ::core::primitive::u32, - pub zeroth_delay_tranche_width: ::core::primitive::u32, - pub relay_vrf_modulo_samples: ::core::primitive::u32, - pub n_delay_tranches: ::core::primitive::u32, - pub no_show_slots: ::core::primitive::u32, - pub needed_approvals: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeGoAhead { - #[codec(index = 0)] - Abort, - #[codec(index = 1)] - GoAhead, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UpgradeRestriction { - #[codec(index = 0)] - Present, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidDisputeStatementKind { - #[codec(index = 0)] - Explicit, - #[codec(index = 1)] - BackingSeconded(::subxt::utils::H256), - #[codec(index = 2)] - BackingValid(::subxt::utils::H256), - #[codec(index = 3)] - ApprovalChecking, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct ValidatorIndex(pub ::core::primitive::u32); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ValidityAttestation { - #[codec(index = 1)] - Implicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - #[codec(index = 2)] - Explicit(runtime_types::polkadot_primitives::v4::validator_app::Signature), - } - } - pub mod vstaging { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AsyncBackingParams { - pub max_candidate_depth: ::core::primitive::u32, - pub allowed_ancestry_len: ::core::primitive::u32, - } - } - } - pub mod polkadot_runtime_common { - use super::runtime_types; - pub mod assigned_slots { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] assign_perm_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , # [codec (index = 1)] assign_temp_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , lease_period_start : runtime_types :: polkadot_runtime_common :: assigned_slots :: SlotLeasePeriodStart , } , # [codec (index = 2)] unassign_parachain_slot { id : runtime_types :: polkadot_parachain :: primitives :: Id , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaDoesntExist, - #[codec(index = 1)] - NotParathread, - #[codec(index = 2)] - CannotUpgrade, - #[codec(index = 3)] - CannotDowngrade, - #[codec(index = 4)] - SlotAlreadyAssigned, - #[codec(index = 5)] - SlotNotAssigned, - #[codec(index = 6)] - OngoingLeaseExists, - #[codec(index = 7)] - MaxPermanentSlotsExceeded, - #[codec(index = 8)] - MaxTemporarySlotsExceeded, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - PermanentSlotAssigned(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - TemporarySlotAssigned(runtime_types::polkadot_parachain::primitives::Id), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParachainTemporarySlot<_0, _1> { - pub manager: _0, - pub period_begin: _1, - pub period_count: _1, - pub last_lease: ::core::option::Option<_1>, - pub lease_count: _1, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SlotLeasePeriodStart { - #[codec(index = 0)] - Current, - #[codec(index = 1)] - Next, - } - } - pub mod auctions { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - new_auction { - #[codec(compact)] - duration: ::core::primitive::u32, - #[codec(compact)] - lease_period_index: ::core::primitive::u32, - }, - #[codec(index = 1)] - bid { - #[codec(compact)] - para: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - auction_index: ::core::primitive::u32, - #[codec(compact)] - first_slot: ::core::primitive::u32, - #[codec(compact)] - last_slot: ::core::primitive::u32, - #[codec(compact)] - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - cancel_auction, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - AuctionInProgress, - #[codec(index = 1)] - LeasePeriodInPast, - #[codec(index = 2)] - ParaNotRegistered, - #[codec(index = 3)] - NotCurrentAuction, - #[codec(index = 4)] - NotAuction, - #[codec(index = 5)] - AuctionEnded, - #[codec(index = 6)] - AlreadyLeasedOut, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - AuctionStarted { - auction_index: ::core::primitive::u32, - lease_period: ::core::primitive::u32, - ending: ::core::primitive::u32, - }, - #[codec(index = 1)] - AuctionClosed { auction_index: ::core::primitive::u32 }, - #[codec(index = 2)] - Reserved { - bidder: ::sp_core::crypto::AccountId32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - Unreserved { - bidder: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 4)] - ReserveConfiscated { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - }, - #[codec(index = 5)] - BidAccepted { - bidder: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - first_slot: ::core::primitive::u32, - last_slot: ::core::primitive::u32, - }, - #[codec(index = 6)] - WinningOffset { - auction_index: ::core::primitive::u32, - block_number: ::core::primitive::u32, - }, - } - } - } - pub mod crowdloan { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - create { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 1)] - contribute { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - value: ::core::primitive::u128, - signature: - ::core::option::Option, - }, - #[codec(index = 2)] - withdraw { - who: ::sp_core::crypto::AccountId32, - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 3)] - refund { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - dissolve { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - edit { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - #[codec(compact)] - cap: ::core::primitive::u128, - #[codec(compact)] - first_period: ::core::primitive::u32, - #[codec(compact)] - last_period: ::core::primitive::u32, - #[codec(compact)] - end: ::core::primitive::u32, - verifier: - ::core::option::Option, - }, - #[codec(index = 6)] - add_memo { - index: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 7)] - poke { index: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - contribute_all { - #[codec(compact)] - index: runtime_types::polkadot_parachain::primitives::Id, - signature: - ::core::option::Option, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - FirstPeriodInPast, - #[codec(index = 1)] - FirstPeriodTooFarInFuture, - #[codec(index = 2)] - LastPeriodBeforeFirstPeriod, - #[codec(index = 3)] - LastPeriodTooFarInFuture, - #[codec(index = 4)] - CannotEndInPast, - #[codec(index = 5)] - EndTooFarInFuture, - #[codec(index = 6)] - Overflow, - #[codec(index = 7)] - ContributionTooSmall, - #[codec(index = 8)] - InvalidParaId, - #[codec(index = 9)] - CapExceeded, - #[codec(index = 10)] - ContributionPeriodOver, - #[codec(index = 11)] - InvalidOrigin, - #[codec(index = 12)] - NotParachain, - #[codec(index = 13)] - LeaseActive, - #[codec(index = 14)] - BidOrLeaseActive, - #[codec(index = 15)] - FundNotEnded, - #[codec(index = 16)] - NoContributions, - #[codec(index = 17)] - NotReadyToDissolve, - #[codec(index = 18)] - InvalidSignature, - #[codec(index = 19)] - MemoTooLarge, - #[codec(index = 20)] - AlreadyInNewRaise, - #[codec(index = 21)] - VrfDelayInProgress, - #[codec(index = 22)] - NoLeasePeriod, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Created { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 1)] - Contributed { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 2)] - Withdrew { - who: ::sp_core::crypto::AccountId32, - fund_index: runtime_types::polkadot_parachain::primitives::Id, - amount: ::core::primitive::u128, - }, - #[codec(index = 3)] - PartiallyRefunded { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - AllRefunded { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - Dissolved { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 6)] - HandleBidResult { - para_id: runtime_types::polkadot_parachain::primitives::Id, - result: ::core::result::Result< - (), - runtime_types::sp_runtime::DispatchError, - >, - }, - #[codec(index = 7)] - Edited { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 8)] - MemoUpdated { - who: ::sp_core::crypto::AccountId32, - para_id: runtime_types::polkadot_parachain::primitives::Id, - memo: ::std::vec::Vec<::core::primitive::u8>, - }, - #[codec(index = 9)] - AddedToNewRaise { - para_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct FundInfo<_0, _1, _2, _3> { - pub depositor: _0, - pub verifier: ::core::option::Option, - pub deposit: _1, - pub raised: _1, - pub end: _2, - pub cap: _1, - pub last_contribution: - runtime_types::polkadot_runtime_common::crowdloan::LastContribution<_2>, - pub first_period: _2, - pub last_period: _2, - pub fund_index: _2, - #[codec(skip)] - pub __subxt_unused_type_params: ::core::marker::PhantomData<_3>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum LastContribution<_0> { - #[codec(index = 0)] - Never, - #[codec(index = 1)] - PreEnding(_0), - #[codec(index = 2)] - Ending(_0), - } - } - pub mod paras_registrar { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - register { - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_register { - who: ::sp_core::crypto::AccountId32, - deposit: ::core::primitive::u128, - id: runtime_types::polkadot_parachain::primitives::Id, - genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 2)] - deregister { id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 3)] - swap { - id: runtime_types::polkadot_parachain::primitives::Id, - other: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - remove_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 5)] - reserve, - #[codec(index = 6)] - add_lock { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 7)] - schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 8)] - set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - AlreadyRegistered, - #[codec(index = 2)] - NotOwner, - #[codec(index = 3)] - CodeTooLarge, - #[codec(index = 4)] - HeadDataTooLarge, - #[codec(index = 5)] - NotParachain, - #[codec(index = 6)] - NotParathread, - #[codec(index = 7)] - CannotDeregister, - #[codec(index = 8)] - CannotDowngrade, - #[codec(index = 9)] - CannotUpgrade, - #[codec(index = 10)] - ParaLocked, - #[codec(index = 11)] - NotReserved, - #[codec(index = 12)] - EmptyCode, - #[codec(index = 13)] - CannotSwap, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - Registered { - para_id: runtime_types::polkadot_parachain::primitives::Id, - manager: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 1)] - Deregistered { para_id: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - Reserved { - para_id: runtime_types::polkadot_parachain::primitives::Id, - who: ::sp_core::crypto::AccountId32, - }, - #[codec(index = 3)] - Swapped { - para_id: runtime_types::polkadot_parachain::primitives::Id, - other_id: runtime_types::polkadot_parachain::primitives::Id, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaInfo<_0, _1> { - pub manager: _0, - pub deposit: _1, - pub locked: ::core::primitive::bool, - } - } - pub mod paras_sudo_wrapper { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - sudo_schedule_para_initialize { - id: runtime_types::polkadot_parachain::primitives::Id, - genesis: - runtime_types::polkadot_runtime_parachains::paras::ParaGenesisArgs, - }, - #[codec(index = 1)] - sudo_schedule_para_cleanup { - id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 2)] - sudo_schedule_parathread_upgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 3)] - sudo_schedule_parachain_downgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 4)] - sudo_queue_downward_xcm { - id: runtime_types::polkadot_parachain::primitives::Id, - xcm: ::std::boxed::Box, - }, - #[codec(index = 5)] - sudo_establish_hrmp_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - recipient: runtime_types::polkadot_parachain::primitives::Id, - max_capacity: ::core::primitive::u32, - max_message_size: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaDoesntExist, - #[codec(index = 1)] - ParaAlreadyExists, - #[codec(index = 2)] - ExceedsMaxMessageSize, - #[codec(index = 3)] - CouldntCleanup, - #[codec(index = 4)] - NotParathread, - #[codec(index = 5)] - NotParachain, - #[codec(index = 6)] - CannotUpgrade, - #[codec(index = 7)] - CannotDowngrade, - } - } - } - pub mod slots { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_lease { - para: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - amount: ::core::primitive::u128, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - }, - #[codec(index = 1)] - clear_all_leases { para: runtime_types::polkadot_parachain::primitives::Id }, - #[codec(index = 2)] - trigger_onboard { para: runtime_types::polkadot_parachain::primitives::Id }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - ParaNotOnboarding, - #[codec(index = 1)] - LeaseError, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - NewLeasePeriod { lease_period: ::core::primitive::u32 }, - #[codec(index = 1)] - Leased { - para_id: runtime_types::polkadot_parachain::primitives::Id, - leaser: ::sp_core::crypto::AccountId32, - period_begin: ::core::primitive::u32, - period_count: ::core::primitive::u32, - extra_reserved: ::core::primitive::u128, - total_amount: ::core::primitive::u128, - }, - } - } - } - } - pub mod polkadot_runtime_parachains { - use super::runtime_types; - pub mod configuration { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - # [codec (index = 0)] set_validation_upgrade_cooldown { new : :: core :: primitive :: u32 , } , # [codec (index = 1)] set_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 2)] set_code_retention_period { new : :: core :: primitive :: u32 , } , # [codec (index = 3)] set_max_code_size { new : :: core :: primitive :: u32 , } , # [codec (index = 4)] set_max_pov_size { new : :: core :: primitive :: u32 , } , # [codec (index = 5)] set_max_head_data_size { new : :: core :: primitive :: u32 , } , # [codec (index = 6)] set_parathread_cores { new : :: core :: primitive :: u32 , } , # [codec (index = 7)] set_parathread_retries { new : :: core :: primitive :: u32 , } , # [codec (index = 8)] set_group_rotation_frequency { new : :: core :: primitive :: u32 , } , # [codec (index = 9)] set_chain_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 10)] set_thread_availability_period { new : :: core :: primitive :: u32 , } , # [codec (index = 11)] set_scheduling_lookahead { new : :: core :: primitive :: u32 , } , # [codec (index = 12)] set_max_validators_per_core { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 13)] set_max_validators { new : :: core :: option :: Option < :: core :: primitive :: u32 > , } , # [codec (index = 14)] set_dispute_period { new : :: core :: primitive :: u32 , } , # [codec (index = 15)] set_dispute_post_conclusion_acceptance_period { new : :: core :: primitive :: u32 , } , # [codec (index = 18)] set_no_show_slots { new : :: core :: primitive :: u32 , } , # [codec (index = 19)] set_n_delay_tranches { new : :: core :: primitive :: u32 , } , # [codec (index = 20)] set_zeroth_delay_tranche_width { new : :: core :: primitive :: u32 , } , # [codec (index = 21)] set_needed_approvals { new : :: core :: primitive :: u32 , } , # [codec (index = 22)] set_relay_vrf_modulo_samples { new : :: core :: primitive :: u32 , } , # [codec (index = 23)] set_max_upward_queue_count { new : :: core :: primitive :: u32 , } , # [codec (index = 24)] set_max_upward_queue_size { new : :: core :: primitive :: u32 , } , # [codec (index = 25)] set_max_downward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 27)] set_max_upward_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 28)] set_max_upward_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 29)] set_hrmp_open_request_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 30)] set_hrmp_sender_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 31)] set_hrmp_recipient_deposit { new : :: core :: primitive :: u128 , } , # [codec (index = 32)] set_hrmp_channel_max_capacity { new : :: core :: primitive :: u32 , } , # [codec (index = 33)] set_hrmp_channel_max_total_size { new : :: core :: primitive :: u32 , } , # [codec (index = 34)] set_hrmp_max_parachain_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 35)] set_hrmp_max_parathread_inbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 36)] set_hrmp_channel_max_message_size { new : :: core :: primitive :: u32 , } , # [codec (index = 37)] set_hrmp_max_parachain_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 38)] set_hrmp_max_parathread_outbound_channels { new : :: core :: primitive :: u32 , } , # [codec (index = 39)] set_hrmp_max_message_num_per_candidate { new : :: core :: primitive :: u32 , } , # [codec (index = 41)] set_pvf_checking_enabled { new : :: core :: primitive :: bool , } , # [codec (index = 42)] set_pvf_voting_ttl { new : :: core :: primitive :: u32 , } , # [codec (index = 43)] set_minimum_validation_upgrade_delay { new : :: core :: primitive :: u32 , } , # [codec (index = 44)] set_bypass_consistency_check { new : :: core :: primitive :: bool , } , # [codec (index = 45)] set_async_backing_params { new : runtime_types :: polkadot_primitives :: vstaging :: AsyncBackingParams , } , # [codec (index = 46)] set_executor_params { new : runtime_types :: polkadot_primitives :: v4 :: executor_params :: ExecutorParams , } , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - InvalidNewValue, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HostConfiguration<_0> { - pub max_code_size: _0, - pub max_head_data_size: _0, - pub max_upward_queue_count: _0, - pub max_upward_queue_size: _0, - pub max_upward_message_size: _0, - pub max_upward_message_num_per_candidate: _0, - pub hrmp_max_message_num_per_candidate: _0, - pub validation_upgrade_cooldown: _0, - pub validation_upgrade_delay: _0, - pub async_backing_params: - runtime_types::polkadot_primitives::vstaging::AsyncBackingParams, - pub max_pov_size: _0, - pub max_downward_message_size: _0, - pub hrmp_max_parachain_outbound_channels: _0, - pub hrmp_max_parathread_outbound_channels: _0, - pub hrmp_sender_deposit: ::core::primitive::u128, - pub hrmp_recipient_deposit: ::core::primitive::u128, - pub hrmp_channel_max_capacity: _0, - pub hrmp_channel_max_total_size: _0, - pub hrmp_max_parachain_inbound_channels: _0, - pub hrmp_max_parathread_inbound_channels: _0, - pub hrmp_channel_max_message_size: _0, - pub executor_params: - runtime_types::polkadot_primitives::v4::executor_params::ExecutorParams, - pub code_retention_period: _0, - pub parathread_cores: _0, - pub parathread_retries: _0, - pub group_rotation_frequency: _0, - pub chain_availability_period: _0, - pub thread_availability_period: _0, - pub scheduling_lookahead: _0, - pub max_validators_per_core: ::core::option::Option<_0>, - pub max_validators: ::core::option::Option<_0>, - pub dispute_period: _0, - pub dispute_post_conclusion_acceptance_period: _0, - pub no_show_slots: _0, - pub n_delay_tranches: _0, - pub zeroth_delay_tranche_width: _0, - pub needed_approvals: _0, - pub relay_vrf_modulo_samples: _0, - pub pvf_checking_enabled: ::core::primitive::bool, - pub pvf_voting_ttl: _0, - pub minimum_validation_upgrade_delay: _0, - } - } - pub mod disputes { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_unfreeze, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - DuplicateDisputeStatementSets, - #[codec(index = 1)] - AncientDisputeStatement, - #[codec(index = 2)] - ValidatorIndexOutOfBounds, - #[codec(index = 3)] - InvalidSignature, - #[codec(index = 4)] - DuplicateStatement, - #[codec(index = 5)] - SingleSidedDispute, - #[codec(index = 6)] - MaliciousBacker, - #[codec(index = 7)] - MissingBackingVotes, - #[codec(index = 8)] - UnconfirmedDispute, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - DisputeInitiated( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeLocation, - ), - #[codec(index = 1)] - DisputeConcluded( - runtime_types::polkadot_core_primitives::CandidateHash, - runtime_types::polkadot_runtime_parachains::disputes::DisputeResult, - ), - #[codec(index = 2)] - Revert(::core::primitive::u32), - } - } - pub mod slashing { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Call { - # [codec (index = 0)] report_dispute_lost_unsigned { dispute_proof : :: std :: boxed :: Box < runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputeProof > , key_owner_proof : :: sp_session :: MembershipProof , } , } - #[derive( - :: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq, - )] - pub enum Error { - #[codec(index = 0)] - InvalidKeyOwnershipProof, - #[codec(index = 1)] - InvalidSessionIndex, - #[codec(index = 2)] - InvalidCandidateHash, - #[codec(index = 3)] - InvalidValidatorIndex, - #[codec(index = 4)] - ValidatorIndexIdMismatch, - #[codec(index = 5)] - DuplicateSlashingReport, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputeProof { pub time_slot : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: DisputesTimeSlot , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , pub validator_index : runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , pub validator_id : runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DisputesTimeSlot { - pub session_index: ::core::primitive::u32, - pub candidate_hash: runtime_types::polkadot_core_primitives::CandidateHash, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PendingSlashes { pub keys : :: subxt :: utils :: KeyedVec < runtime_types :: polkadot_primitives :: v4 :: ValidatorIndex , runtime_types :: polkadot_primitives :: v4 :: validator_app :: Public > , pub kind : runtime_types :: polkadot_runtime_parachains :: disputes :: slashing :: SlashingOffenceKind , } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum SlashingOffenceKind { - #[codec(index = 0)] - ForInvalid, - #[codec(index = 1)] - AgainstValid, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeLocation { - #[codec(index = 0)] - Local, - #[codec(index = 1)] - Remote, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DisputeResult { - #[codec(index = 0)] - Valid, - #[codec(index = 1)] - Invalid, - } - } - pub mod hrmp { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - hrmp_init_open_channel { - recipient: runtime_types::polkadot_parachain::primitives::Id, - proposed_max_capacity: ::core::primitive::u32, - proposed_max_message_size: ::core::primitive::u32, - }, - #[codec(index = 1)] - hrmp_accept_open_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 2)] - hrmp_close_channel { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - }, - #[codec(index = 3)] - force_clean_hrmp { - para: runtime_types::polkadot_parachain::primitives::Id, - inbound: ::core::primitive::u32, - outbound: ::core::primitive::u32, - }, - #[codec(index = 4)] - force_process_hrmp_open { channels: ::core::primitive::u32 }, - #[codec(index = 5)] - force_process_hrmp_close { channels: ::core::primitive::u32 }, - #[codec(index = 6)] - hrmp_cancel_open_request { - channel_id: - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - open_requests: ::core::primitive::u32, - }, - #[codec(index = 7)] - force_open_hrmp_channel { - sender: runtime_types::polkadot_parachain::primitives::Id, - recipient: runtime_types::polkadot_parachain::primitives::Id, - max_capacity: ::core::primitive::u32, - max_message_size: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - OpenHrmpChannelToSelf, - #[codec(index = 1)] - OpenHrmpChannelInvalidRecipient, - #[codec(index = 2)] - OpenHrmpChannelZeroCapacity, - #[codec(index = 3)] - OpenHrmpChannelCapacityExceedsLimit, - #[codec(index = 4)] - OpenHrmpChannelZeroMessageSize, - #[codec(index = 5)] - OpenHrmpChannelMessageSizeExceedsLimit, - #[codec(index = 6)] - OpenHrmpChannelAlreadyExists, - #[codec(index = 7)] - OpenHrmpChannelAlreadyRequested, - #[codec(index = 8)] - OpenHrmpChannelLimitExceeded, - #[codec(index = 9)] - AcceptHrmpChannelDoesntExist, - #[codec(index = 10)] - AcceptHrmpChannelAlreadyConfirmed, - #[codec(index = 11)] - AcceptHrmpChannelLimitExceeded, - #[codec(index = 12)] - CloseHrmpChannelUnauthorized, - #[codec(index = 13)] - CloseHrmpChannelDoesntExist, - #[codec(index = 14)] - CloseHrmpChannelAlreadyUnderway, - #[codec(index = 15)] - CancelHrmpOpenChannelUnauthorized, - #[codec(index = 16)] - OpenHrmpChannelDoesntExist, - #[codec(index = 17)] - OpenHrmpChannelAlreadyConfirmed, - #[codec(index = 18)] - WrongWitness, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - OpenChannelRequested( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - #[codec(index = 1)] - OpenChannelCanceled( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 2)] - OpenChannelAccepted( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 3)] - ChannelClosed( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::HrmpChannelId, - ), - #[codec(index = 4)] - HrmpChannelForceOpened( - runtime_types::polkadot_parachain::primitives::Id, - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ::core::primitive::u32, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpChannel { - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - pub max_message_size: ::core::primitive::u32, - pub msg_count: ::core::primitive::u32, - pub total_size: ::core::primitive::u32, - pub mqc_head: ::core::option::Option<::subxt::utils::H256>, - pub sender_deposit: ::core::primitive::u128, - pub recipient_deposit: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct HrmpOpenChannelRequest { - pub confirmed: ::core::primitive::bool, - pub _age: ::core::primitive::u32, - pub sender_deposit: ::core::primitive::u128, - pub max_message_size: ::core::primitive::u32, - pub max_capacity: ::core::primitive::u32, - pub max_total_size: ::core::primitive::u32, - } - } - pub mod inclusion { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - UnsortedOrDuplicateValidatorIndices, - #[codec(index = 1)] - UnsortedOrDuplicateDisputeStatementSet, - #[codec(index = 2)] - UnsortedOrDuplicateBackedCandidates, - #[codec(index = 3)] - UnexpectedRelayParent, - #[codec(index = 4)] - WrongBitfieldSize, - #[codec(index = 5)] - BitfieldAllZeros, - #[codec(index = 6)] - BitfieldDuplicateOrUnordered, - #[codec(index = 7)] - ValidatorIndexOutOfBounds, - #[codec(index = 8)] - InvalidBitfieldSignature, - #[codec(index = 9)] - UnscheduledCandidate, - #[codec(index = 10)] - CandidateScheduledBeforeParaFree, - #[codec(index = 11)] - WrongCollator, - #[codec(index = 12)] - ScheduledOutOfOrder, - #[codec(index = 13)] - HeadDataTooLarge, - #[codec(index = 14)] - PrematureCodeUpgrade, - #[codec(index = 15)] - NewCodeTooLarge, - #[codec(index = 16)] - CandidateNotInParentContext, - #[codec(index = 17)] - InvalidGroupIndex, - #[codec(index = 18)] - InsufficientBacking, - #[codec(index = 19)] - InvalidBacking, - #[codec(index = 20)] - NotCollatorSigned, - #[codec(index = 21)] - ValidationDataHashMismatch, - #[codec(index = 22)] - IncorrectDownwardMessageHandling, - #[codec(index = 23)] - InvalidUpwardMessages, - #[codec(index = 24)] - HrmpWatermarkMishandling, - #[codec(index = 25)] - InvalidOutboundHrmp, - #[codec(index = 26)] - InvalidValidationCodeHash, - #[codec(index = 27)] - ParaHeadMismatch, - #[codec(index = 28)] - BitfieldReferencesFreedCore, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CandidateBacked( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 1)] - CandidateIncluded( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - runtime_types::polkadot_primitives::v4::GroupIndex, - ), - #[codec(index = 2)] - CandidateTimedOut( - runtime_types::polkadot_primitives::v4::CandidateReceipt< - ::subxt::utils::H256, - >, - runtime_types::polkadot_parachain::primitives::HeadData, - runtime_types::polkadot_primitives::v4::CoreIndex, - ), - #[codec(index = 3)] - UpwardMessagesReceived { - from: runtime_types::polkadot_parachain::primitives::Id, - count: ::core::primitive::u32, - }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AggregateMessageOrigin { - #[codec(index = 0)] - Ump(runtime_types::polkadot_runtime_parachains::inclusion::UmpQueueId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct AvailabilityBitfieldRecord<_0> { - pub bitfield: runtime_types::polkadot_primitives::v4::AvailabilityBitfield, - pub submitted_at: _0, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CandidatePendingAvailability<_0, _1> { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub hash: runtime_types::polkadot_core_primitives::CandidateHash, - pub descriptor: runtime_types::polkadot_primitives::v4::CandidateDescriptor<_0>, - pub availability_votes: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub backers: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub relay_parent_number: _1, - pub backed_in_number: _1, - pub backing_group: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum UmpQueueId { - #[codec(index = 0)] - Para(runtime_types::polkadot_parachain::primitives::Id), - } - } - pub mod initializer { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_approve { up_to: ::core::primitive::u32 }, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BufferedSessionChange { - pub validators: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub queued: ::std::vec::Vec< - runtime_types::polkadot_primitives::v4::validator_app::Public, - >, - pub session_index: ::core::primitive::u32, - } - } - pub mod origin { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Origin { - #[codec(index = 0)] - Parachain(runtime_types::polkadot_parachain::primitives::Id), - } - } - } - pub mod paras { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - force_set_current_code { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 1)] - force_set_current_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 2)] - force_schedule_code_upgrade { - para: runtime_types::polkadot_parachain::primitives::Id, - new_code: runtime_types::polkadot_parachain::primitives::ValidationCode, - relay_parent_number: ::core::primitive::u32, - }, - #[codec(index = 3)] - force_note_new_head { - para: runtime_types::polkadot_parachain::primitives::Id, - new_head: runtime_types::polkadot_parachain::primitives::HeadData, - }, - #[codec(index = 4)] - force_queue_action { - para: runtime_types::polkadot_parachain::primitives::Id, - }, - #[codec(index = 5)] - add_trusted_validation_code { - validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - }, - #[codec(index = 6)] - poke_unused_validation_code { - validation_code_hash: - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - }, - #[codec(index = 7)] - include_pvf_check_statement { - stmt: runtime_types::polkadot_primitives::v4::PvfCheckStatement, - signature: - runtime_types::polkadot_primitives::v4::validator_app::Signature, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - NotRegistered, - #[codec(index = 1)] - CannotOnboard, - #[codec(index = 2)] - CannotOffboard, - #[codec(index = 3)] - CannotUpgrade, - #[codec(index = 4)] - CannotDowngrade, - #[codec(index = 5)] - PvfCheckStatementStale, - #[codec(index = 6)] - PvfCheckStatementFuture, - #[codec(index = 7)] - PvfCheckValidatorIndexOutOfBounds, - #[codec(index = 8)] - PvfCheckInvalidSignature, - #[codec(index = 9)] - PvfCheckDoubleVote, - #[codec(index = 10)] - PvfCheckSubjectInvalid, - #[codec(index = 11)] - CannotUpgradeCode, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Event { - #[codec(index = 0)] - CurrentCodeUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - CurrentHeadUpdated(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 2)] - CodeUpgradeScheduled(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 3)] - NewHeadNoted(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 4)] - ActionQueued( - runtime_types::polkadot_parachain::primitives::Id, - ::core::primitive::u32, - ), - #[codec(index = 5)] - PvfCheckStarted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 6)] - PvfCheckAccepted( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - #[codec(index = 7)] - PvfCheckRejected( - runtime_types::polkadot_parachain::primitives::ValidationCodeHash, - runtime_types::polkadot_parachain::primitives::Id, - ), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaGenesisArgs { - pub genesis_head: runtime_types::polkadot_parachain::primitives::HeadData, - pub validation_code: - runtime_types::polkadot_parachain::primitives::ValidationCode, - pub para_kind: ::core::primitive::bool, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ParaLifecycle { - #[codec(index = 0)] - Onboarding, - #[codec(index = 1)] - Parathread, - #[codec(index = 2)] - Parachain, - #[codec(index = 3)] - UpgradingParathread, - #[codec(index = 4)] - DowngradingParachain, - #[codec(index = 5)] - OffboardingParathread, - #[codec(index = 6)] - OffboardingParachain, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParaPastCodeMeta<_0> { - pub upgrade_times: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::ReplacementTimes<_0>, - >, - pub last_pruned: ::core::option::Option<_0>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PvfCheckActiveVoteState<_0> { - pub votes_accept: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub votes_reject: ::subxt::utils::bits::DecodedBits< - ::core::primitive::u8, - ::subxt::utils::bits::Lsb0, - >, - pub age: _0, - pub created_at: _0, - pub causes: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::paras::PvfCheckCause<_0>, - >, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PvfCheckCause<_0> { - #[codec(index = 0)] - Onboarding(runtime_types::polkadot_parachain::primitives::Id), - #[codec(index = 1)] - Upgrade { - id: runtime_types::polkadot_parachain::primitives::Id, - relay_parent_number: _0, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ReplacementTimes<_0> { - pub expected_at: _0, - pub activated_at: _0, - } - } - pub mod paras_inherent { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call { - #[codec(index = 0)] - enter { - data: runtime_types::polkadot_primitives::v4::InherentData< - ::sp_runtime::generic::Header< - ::core::primitive::u32, - ::sp_runtime::traits::BlakeTwo256, - >, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - TooManyInclusionInherents, - #[codec(index = 1)] - InvalidParentHeader, - #[codec(index = 2)] - CandidateConcludedInvalid, - #[codec(index = 3)] - InherentOverweight, - #[codec(index = 4)] - DisputeStatementsUnsortedOrDuplicates, - #[codec(index = 5)] - DisputeInvalid, - } - } - } - pub mod scheduler { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssignmentKind { - #[codec(index = 0)] - Parachain, - #[codec(index = 1)] - Parathread( - runtime_types::polkadot_primitives::v4::collator_app::Public, - ::core::primitive::u32, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct CoreAssignment { - pub core: runtime_types::polkadot_primitives::v4::CoreIndex, - pub para_id: runtime_types::polkadot_parachain::primitives::Id, - pub kind: runtime_types::polkadot_runtime_parachains::scheduler::AssignmentKind, - pub group_idx: runtime_types::polkadot_primitives::v4::GroupIndex, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ParathreadClaimQueue { - pub queue: ::std::vec::Vec< - runtime_types::polkadot_runtime_parachains::scheduler::QueuedParathread, - >, - pub next_core_offset: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueuedParathread { - pub claim: runtime_types::polkadot_primitives::v4::ParathreadEntry, - pub core_offset: ::core::primitive::u32, - } - } - pub mod shared { - use super::runtime_types; - pub mod pallet { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Call {} - } - } - } - pub mod sp_arithmetic { - use super::runtime_types; - pub mod fixed_point { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct FixedU128(pub ::core::primitive::u128); - } - pub mod per_things { - use super::runtime_types; - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct PerU16(pub ::core::primitive::u16); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Perbill(pub ::core::primitive::u32); - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Percent(pub ::core::primitive::u8); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ArithmeticError { - #[codec(index = 0)] - Underflow, - #[codec(index = 1)] - Overflow, - #[codec(index = 2)] - DivisionByZero, - } - } - pub mod sp_authority_discovery { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - } - pub mod sp_consensus_babe { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::sr25519::Public); - } - pub mod digests { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NextConfigDescriptor { - #[codec(index = 1)] - V1 { - c: (::core::primitive::u64, ::core::primitive::u64), - allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum PreDigest { - #[codec(index = 1)] - Primary(runtime_types::sp_consensus_babe::digests::PrimaryPreDigest), - #[codec(index = 2)] - SecondaryPlain( - runtime_types::sp_consensus_babe::digests::SecondaryPlainPreDigest, - ), - #[codec(index = 3)] - SecondaryVRF(runtime_types::sp_consensus_babe::digests::SecondaryVRFPreDigest), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PrimaryPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryPlainPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SecondaryVRFPreDigest { - pub authority_index: ::core::primitive::u32, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub vrf_signature: runtime_types::sp_core::sr25519::vrf::VrfSignature, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AllowedSlots { - #[codec(index = 0)] - PrimarySlots, - #[codec(index = 1)] - PrimaryAndSecondaryPlainSlots, - #[codec(index = 2)] - PrimaryAndSecondaryVRFSlots, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct BabeEpochConfiguration { - pub c: (::core::primitive::u64, ::core::primitive::u64), - pub allowed_slots: runtime_types::sp_consensus_babe::AllowedSlots, - } - } - pub mod sp_consensus_grandpa { - use super::runtime_types; - pub mod app { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub runtime_types::sp_core::ed25519::Public); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub runtime_types::sp_core::ed25519::Signature); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Equivocation<_0, _1> { - #[codec(index = 0)] - Prevote( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Prevote<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - #[codec(index = 1)] - Precommit( - runtime_types::finality_grandpa::Equivocation< - runtime_types::sp_consensus_grandpa::app::Public, - runtime_types::finality_grandpa::Precommit<_0, _1>, - runtime_types::sp_consensus_grandpa::app::Signature, - >, - ), - } - } - pub mod sp_consensus_slots { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct EquivocationProof<_0, _1> { - pub offender: _1, - pub slot: runtime_types::sp_consensus_slots::Slot, - pub first_header: _0, - pub second_header: _0, - } - #[derive( - :: codec :: Decode, - :: codec :: Encode, - :: subxt :: ext :: codec :: CompactAs, - Clone, - Debug, - PartialEq, - )] - pub struct Slot(pub ::core::primitive::u64); - } - pub mod sp_core { - use super::runtime_types; - pub mod crypto { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct KeyTypeId(pub [::core::primitive::u8; 4usize]); - } - pub mod ecdsa { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 33usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 65usize]); - } - pub mod ed25519 { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - pub mod offchain { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueMultiaddr(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaqueNetworkState { - pub peer_id: runtime_types::sp_core::OpaquePeerId, - pub external_addresses: - ::std::vec::Vec, - } - } - pub mod sr25519 { - use super::runtime_types; - pub mod vrf { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct VrfSignature { - pub output: [::core::primitive::u8; 32usize], - pub proof: [::core::primitive::u8; 64usize], - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Public(pub [::core::primitive::u8; 32usize]); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Signature(pub [::core::primitive::u8; 64usize]); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OpaquePeerId(pub ::std::vec::Vec<::core::primitive::u8>); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Void {} - } - pub mod sp_npos_elections { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ElectionScore { - pub minimal_stake: ::core::primitive::u128, - pub sum_stake: ::core::primitive::u128, - pub sum_stake_squared: ::core::primitive::u128, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Support<_0> { - pub total: ::core::primitive::u128, - pub voters: ::std::vec::Vec<(_0, ::core::primitive::u128)>, - } - } - pub mod sp_runtime { - use super::runtime_types; - pub mod generic { - use super::runtime_types; - pub mod digest { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DigestItem { - #[codec(index = 6)] - PreRuntime( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 4)] - Consensus( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 5)] - Seal( - [::core::primitive::u8; 4usize], - ::std::vec::Vec<::core::primitive::u8>, - ), - #[codec(index = 0)] - Other(::std::vec::Vec<::core::primitive::u8>), - #[codec(index = 8)] - RuntimeEnvironmentUpdated, - } - } - pub mod unchecked_extrinsic { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct UncheckedExtrinsic<_0, _1, _2, _3>( - pub ::std::vec::Vec<::core::primitive::u8>, - #[codec(skip)] pub ::core::marker::PhantomData<(_0, _1, _2, _3)>, - ); - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum DispatchError { - #[codec(index = 0)] - Other, - #[codec(index = 1)] - CannotLookup, - #[codec(index = 2)] - BadOrigin, - #[codec(index = 3)] - Module(runtime_types::sp_runtime::ModuleError), - #[codec(index = 4)] - ConsumerRemaining, - #[codec(index = 5)] - NoProviders, - #[codec(index = 6)] - TooManyConsumers, - #[codec(index = 7)] - Token(runtime_types::sp_runtime::TokenError), - #[codec(index = 8)] - Arithmetic(runtime_types::sp_arithmetic::ArithmeticError), - #[codec(index = 9)] - Transactional(runtime_types::sp_runtime::TransactionalError), - #[codec(index = 10)] - Exhausted, - #[codec(index = 11)] - Corruption, - #[codec(index = 12)] - Unavailable, - #[codec(index = 13)] - RootNotAllowed, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct ModuleError { - pub index: ::core::primitive::u8, - pub error: [::core::primitive::u8; 4usize], - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSignature { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Signature), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Signature), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Signature), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiSigner { - #[codec(index = 0)] - Ed25519(runtime_types::sp_core::ed25519::Public), - #[codec(index = 1)] - Sr25519(runtime_types::sp_core::sr25519::Public), - #[codec(index = 2)] - Ecdsa(runtime_types::sp_core::ecdsa::Public), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TokenError { - #[codec(index = 0)] - FundsUnavailable, - #[codec(index = 1)] - OnlyProvider, - #[codec(index = 2)] - BelowMinimum, - #[codec(index = 3)] - CannotCreate, - #[codec(index = 4)] - UnknownAsset, - #[codec(index = 5)] - Frozen, - #[codec(index = 6)] - Unsupported, - #[codec(index = 7)] - CannotCreateHold, - #[codec(index = 8)] - NotExpendable, - #[codec(index = 9)] - Blocked, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum TransactionalError { - #[codec(index = 0)] - LimitReached, - #[codec(index = 1)] - NoLayer, - } - } - pub mod sp_staking { - use super::runtime_types; - pub mod offence { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct OffenceDetails<_0, _1> { - pub offender: _1, - pub reporters: ::std::vec::Vec<_0>, - } - } - } - pub mod sp_version { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeVersion { - pub spec_name: ::std::string::String, - pub impl_name: ::std::string::String, - pub authoring_version: ::core::primitive::u32, - pub spec_version: ::core::primitive::u32, - pub impl_version: ::core::primitive::u32, - pub apis: - ::std::vec::Vec<([::core::primitive::u8; 8usize], ::core::primitive::u32)>, - pub transaction_version: ::core::primitive::u32, - pub state_version: ::core::primitive::u8, - } - } - pub mod sp_weights { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct RuntimeDbWeight { - pub read: ::core::primitive::u64, - pub write: ::core::primitive::u64, - } - } - pub mod westend_runtime { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct NposCompactSolution16 { - pub votes1: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes2: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - ( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ), - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes3: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 2usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes4: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 3usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes5: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 4usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes6: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 5usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes7: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 6usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes8: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 7usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes9: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 8usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes10: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 9usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes11: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 10usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes12: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 11usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes13: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 12usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes14: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 13usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes15: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 14usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - pub votes16: ::std::vec::Vec<( - ::subxt::ext::codec::Compact<::core::primitive::u32>, - [( - ::subxt::ext::codec::Compact<::core::primitive::u16>, - ::subxt::ext::codec::Compact< - runtime_types::sp_arithmetic::per_things::PerU16, - >, - ); 15usize], - ::subxt::ext::codec::Compact<::core::primitive::u16>, - )>, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginCaller { - #[codec(index = 0)] - system( - runtime_types::frame_support::dispatch::RawOrigin< - ::sp_core::crypto::AccountId32, - >, - ), - #[codec(index = 41)] - ParachainsOrigin( - runtime_types::polkadot_runtime_parachains::origin::pallet::Origin, - ), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Origin), - #[codec(index = 3)] - Void(runtime_types::sp_core::Void), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum ProxyType { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - NonTransfer, - #[codec(index = 2)] - Staking, - #[codec(index = 3)] - SudoBalances, - #[codec(index = 4)] - IdentityJudgement, - #[codec(index = 5)] - CancelProxy, - #[codec(index = 6)] - Auction, - #[codec(index = 7)] - NominationPools, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Runtime; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeCall { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Call), - #[codec(index = 1)] - Babe(runtime_types::pallet_babe::pallet::Call), - #[codec(index = 2)] - Timestamp(runtime_types::pallet_timestamp::pallet::Call), - #[codec(index = 3)] - Indices(runtime_types::pallet_indices::pallet::Call), - #[codec(index = 4)] - Balances(runtime_types::pallet_balances::pallet::Call), - #[codec(index = 6)] - Staking(runtime_types::pallet_staking::pallet::pallet::Call), - #[codec(index = 8)] - Session(runtime_types::pallet_session::pallet::Call), - #[codec(index = 10)] - Grandpa(runtime_types::pallet_grandpa::pallet::Call), - #[codec(index = 11)] - ImOnline(runtime_types::pallet_im_online::pallet::Call), - #[codec(index = 16)] - Utility(runtime_types::pallet_utility::pallet::Call), - #[codec(index = 17)] - Identity(runtime_types::pallet_identity::pallet::Call), - #[codec(index = 18)] - Recovery(runtime_types::pallet_recovery::pallet::Call), - #[codec(index = 19)] - Vesting(runtime_types::pallet_vesting::pallet::Call), - #[codec(index = 20)] - Scheduler(runtime_types::pallet_scheduler::pallet::Call), - #[codec(index = 28)] - Preimage(runtime_types::pallet_preimage::pallet::Call), - #[codec(index = 21)] - Sudo(runtime_types::pallet_sudo::pallet::Call), - #[codec(index = 22)] - Proxy(runtime_types::pallet_proxy::pallet::Call), - #[codec(index = 23)] - Multisig(runtime_types::pallet_multisig::pallet::Call), - #[codec(index = 24)] - ElectionProviderMultiPhase( - runtime_types::pallet_election_provider_multi_phase::pallet::Call, - ), - #[codec(index = 25)] - VoterList(runtime_types::pallet_bags_list::pallet::Call), - #[codec(index = 29)] - NominationPools(runtime_types::pallet_nomination_pools::pallet::Call), - #[codec(index = 30)] - FastUnstake(runtime_types::pallet_fast_unstake::pallet::Call), - #[codec(index = 42)] - Configuration( - runtime_types::polkadot_runtime_parachains::configuration::pallet::Call, - ), - #[codec(index = 43)] - ParasShared(runtime_types::polkadot_runtime_parachains::shared::pallet::Call), - #[codec(index = 44)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Call), - #[codec(index = 45)] - ParaInherent( - runtime_types::polkadot_runtime_parachains::paras_inherent::pallet::Call, - ), - #[codec(index = 47)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Call), - #[codec(index = 48)] - Initializer(runtime_types::polkadot_runtime_parachains::initializer::pallet::Call), - #[codec(index = 51)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Call), - #[codec(index = 53)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Call), - #[codec(index = 54)] - ParasSlashing( - runtime_types::polkadot_runtime_parachains::disputes::slashing::pallet::Call, - ), - #[codec(index = 60)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Call), - #[codec(index = 61)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Call), - #[codec(index = 62)] - ParasSudoWrapper( - runtime_types::polkadot_runtime_common::paras_sudo_wrapper::pallet::Call, - ), - #[codec(index = 63)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Call), - #[codec(index = 64)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Call), - #[codec(index = 65)] - AssignedSlots(runtime_types::polkadot_runtime_common::assigned_slots::pallet::Call), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Call), - #[codec(index = 100)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Call), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum RuntimeEvent { - #[codec(index = 0)] - System(runtime_types::frame_system::pallet::Event), - #[codec(index = 3)] - Indices(runtime_types::pallet_indices::pallet::Event), - #[codec(index = 4)] - Balances(runtime_types::pallet_balances::pallet::Event), - #[codec(index = 26)] - TransactionPayment(runtime_types::pallet_transaction_payment::pallet::Event), - #[codec(index = 6)] - Staking(runtime_types::pallet_staking::pallet::pallet::Event), - #[codec(index = 7)] - Offences(runtime_types::pallet_offences::pallet::Event), - #[codec(index = 8)] - Session(runtime_types::pallet_session::pallet::Event), - #[codec(index = 10)] - Grandpa(runtime_types::pallet_grandpa::pallet::Event), - #[codec(index = 11)] - ImOnline(runtime_types::pallet_im_online::pallet::Event), - #[codec(index = 16)] - Utility(runtime_types::pallet_utility::pallet::Event), - #[codec(index = 17)] - Identity(runtime_types::pallet_identity::pallet::Event), - #[codec(index = 18)] - Recovery(runtime_types::pallet_recovery::pallet::Event), - #[codec(index = 19)] - Vesting(runtime_types::pallet_vesting::pallet::Event), - #[codec(index = 20)] - Scheduler(runtime_types::pallet_scheduler::pallet::Event), - #[codec(index = 28)] - Preimage(runtime_types::pallet_preimage::pallet::Event), - #[codec(index = 21)] - Sudo(runtime_types::pallet_sudo::pallet::Event), - #[codec(index = 22)] - Proxy(runtime_types::pallet_proxy::pallet::Event), - #[codec(index = 23)] - Multisig(runtime_types::pallet_multisig::pallet::Event), - #[codec(index = 24)] - ElectionProviderMultiPhase( - runtime_types::pallet_election_provider_multi_phase::pallet::Event, - ), - #[codec(index = 25)] - VoterList(runtime_types::pallet_bags_list::pallet::Event), - #[codec(index = 29)] - NominationPools(runtime_types::pallet_nomination_pools::pallet::Event), - #[codec(index = 30)] - FastUnstake(runtime_types::pallet_fast_unstake::pallet::Event), - #[codec(index = 44)] - ParaInclusion(runtime_types::polkadot_runtime_parachains::inclusion::pallet::Event), - #[codec(index = 47)] - Paras(runtime_types::polkadot_runtime_parachains::paras::pallet::Event), - #[codec(index = 51)] - Hrmp(runtime_types::polkadot_runtime_parachains::hrmp::pallet::Event), - #[codec(index = 53)] - ParasDisputes(runtime_types::polkadot_runtime_parachains::disputes::pallet::Event), - #[codec(index = 60)] - Registrar(runtime_types::polkadot_runtime_common::paras_registrar::pallet::Event), - #[codec(index = 61)] - Slots(runtime_types::polkadot_runtime_common::slots::pallet::Event), - #[codec(index = 63)] - Auctions(runtime_types::polkadot_runtime_common::auctions::pallet::Event), - #[codec(index = 64)] - Crowdloan(runtime_types::polkadot_runtime_common::crowdloan::pallet::Event), - #[codec(index = 65)] - AssignedSlots( - runtime_types::polkadot_runtime_common::assigned_slots::pallet::Event, - ), - #[codec(index = 99)] - XcmPallet(runtime_types::pallet_xcm::pallet::Event), - #[codec(index = 100)] - MessageQueue(runtime_types::pallet_message_queue::pallet::Event), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct SessionKeys { - pub grandpa: runtime_types::sp_consensus_grandpa::app::Public, - pub babe: runtime_types::sp_consensus_babe::app::Public, - pub im_online: runtime_types::pallet_im_online::sr25519::app_sr25519::Public, - pub para_validator: runtime_types::polkadot_primitives::v4::validator_app::Public, - pub para_assignment: runtime_types::polkadot_primitives::v4::assignment_app::Public, - pub authority_discovery: runtime_types::sp_authority_discovery::app::Public, - } - } - pub mod xcm { - use super::runtime_types; - pub mod double_encoded { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct DoubleEncoded { - pub encoded: ::std::vec::Vec<::core::primitive::u8>, - } - } - pub mod v2 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: runtime_types::xcm::v2::NetworkId, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: runtime_types::xcm::v2::NetworkId, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: runtime_types::xcm::v2::NetworkId, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v2::BodyId, - part: runtime_types::xcm::v2::BodyPart, - }, - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - #[codec(index = 6)] - Blob(::std::vec::Vec<::core::primitive::u8>), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v2::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v2::multiasset::AssetId, - pub fun: runtime_types::xcm::v2::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v2::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v2::multiasset::AssetId, - fun: runtime_types::xcm::v2::multiasset::WildFungibility, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v2::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - runtime_types::xcm::v2::junction::Junction, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v2::multilocation::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - MultiLocationFull, - #[codec(index = 5)] - MultiLocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - UnhandledXcmVersion, - #[codec(index = 23)] - WeightLimitReached(::core::primitive::u64), - #[codec(index = 24)] - Barrier, - #[codec(index = 25)] - WeightNotComputable, - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v2::Response, - #[codec(compact)] - max_weight: ::core::primitive::u64, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_type: runtime_types::xcm::v2::OriginKind, - #[codec(compact)] - require_weight_at_most: ::core::primitive::u64, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v2::multilocation::Junctions), - #[codec(index = 12)] - ReportError { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - beneficiary: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_assets: ::core::primitive::u32, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - receive: runtime_types::xcm::v2::multiasset::MultiAssets, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - xcm: runtime_types::xcm::v2::Xcm, - }, - #[codec(index = 18)] - QueryHolding { - #[codec(compact)] - query_id: ::core::primitive::u64, - dest: runtime_types::xcm::v2::multilocation::MultiLocation, - assets: runtime_types::xcm::v2::multiasset::MultiAssetFilter, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v2::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v2::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v2::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v2::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v2::multiasset::MultiAssets, - ticket: runtime_types::xcm::v2::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - #[codec(compact)] - max_response_weight: ::core::primitive::u64, - }, - #[codec(index = 27)] - UnsubscribeVersion, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - Any, - #[codec(index = 1)] - Named( - runtime_types::bounded_collections::weak_bounded_vec::WeakBoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum OriginKind { - #[codec(index = 0)] - Native, - #[codec(index = 1)] - SovereignAccount, - #[codec(index = 2)] - Superuser, - #[codec(index = 3)] - Xcm, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v2::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(#[codec(compact)] ::core::primitive::u64), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - pub mod v3 { - use super::runtime_types; - pub mod junction { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyId { - #[codec(index = 0)] - Unit, - #[codec(index = 1)] - Moniker([::core::primitive::u8; 4usize]), - #[codec(index = 2)] - Index(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - Executive, - #[codec(index = 4)] - Technical, - #[codec(index = 5)] - Legislative, - #[codec(index = 6)] - Judicial, - #[codec(index = 7)] - Defense, - #[codec(index = 8)] - Administration, - #[codec(index = 9)] - Treasury, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum BodyPart { - #[codec(index = 0)] - Voice, - #[codec(index = 1)] - Members { - #[codec(compact)] - count: ::core::primitive::u32, - }, - #[codec(index = 2)] - Fraction { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 3)] - AtLeastProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - #[codec(index = 4)] - MoreThanProportion { - #[codec(compact)] - nom: ::core::primitive::u32, - #[codec(compact)] - denom: ::core::primitive::u32, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junction { - #[codec(index = 0)] - Parachain(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 1)] - AccountId32 { - network: - ::core::option::Option, - id: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - AccountIndex64 { - network: - ::core::option::Option, - #[codec(compact)] - index: ::core::primitive::u64, - }, - #[codec(index = 3)] - AccountKey20 { - network: - ::core::option::Option, - key: [::core::primitive::u8; 20usize], - }, - #[codec(index = 4)] - PalletInstance(::core::primitive::u8), - #[codec(index = 5)] - GeneralIndex(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 6)] - GeneralKey { - length: ::core::primitive::u8, - data: [::core::primitive::u8; 32usize], - }, - #[codec(index = 7)] - OnlyChild, - #[codec(index = 8)] - Plurality { - id: runtime_types::xcm::v3::junction::BodyId, - part: runtime_types::xcm::v3::junction::BodyPart, - }, - #[codec(index = 9)] - GlobalConsensus(runtime_types::xcm::v3::junction::NetworkId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum NetworkId { - #[codec(index = 0)] - ByGenesis([::core::primitive::u8; 32usize]), - #[codec(index = 1)] - ByFork { - block_number: ::core::primitive::u64, - block_hash: [::core::primitive::u8; 32usize], - }, - #[codec(index = 2)] - Polkadot, - #[codec(index = 3)] - Kusama, - #[codec(index = 4)] - Westend, - #[codec(index = 5)] - Rococo, - #[codec(index = 6)] - Wococo, - #[codec(index = 7)] - Ethereum { - #[codec(compact)] - chain_id: ::core::primitive::u64, - }, - #[codec(index = 8)] - BitcoinCore, - #[codec(index = 9)] - BitcoinCash, - } - } - pub mod junctions { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Junctions { - #[codec(index = 0)] - Here, - #[codec(index = 1)] - X1(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 2)] - X2( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 3)] - X3( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 4)] - X4( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 5)] - X5( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 6)] - X6( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 7)] - X7( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - #[codec(index = 8)] - X8( - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - runtime_types::xcm::v3::junction::Junction, - ), - } - } - pub mod multiasset { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetId { - #[codec(index = 0)] - Concrete(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 1)] - Abstract([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum AssetInstance { - #[codec(index = 0)] - Undefined, - #[codec(index = 1)] - Index(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 2)] - Array4([::core::primitive::u8; 4usize]), - #[codec(index = 3)] - Array8([::core::primitive::u8; 8usize]), - #[codec(index = 4)] - Array16([::core::primitive::u8; 16usize]), - #[codec(index = 5)] - Array32([::core::primitive::u8; 32usize]), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Fungibility { - #[codec(index = 0)] - Fungible(#[codec(compact)] ::core::primitive::u128), - #[codec(index = 1)] - NonFungible(runtime_types::xcm::v3::multiasset::AssetInstance), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAsset { - pub id: runtime_types::xcm::v3::multiasset::AssetId, - pub fun: runtime_types::xcm::v3::multiasset::Fungibility, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MultiAssetFilter { - #[codec(index = 0)] - Definite(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - Wild(runtime_types::xcm::v3::multiasset::WildMultiAsset), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiAssets( - pub ::std::vec::Vec, - ); - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildFungibility { - #[codec(index = 0)] - Fungible, - #[codec(index = 1)] - NonFungible, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WildMultiAsset { - #[codec(index = 0)] - All, - #[codec(index = 1)] - AllOf { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - }, - #[codec(index = 2)] - AllCounted(#[codec(compact)] ::core::primitive::u32), - #[codec(index = 3)] - AllOfCounted { - id: runtime_types::xcm::v3::multiasset::AssetId, - fun: runtime_types::xcm::v3::multiasset::WildFungibility, - #[codec(compact)] - count: ::core::primitive::u32, - }, - } - } - pub mod multilocation { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct MultiLocation { - pub parents: ::core::primitive::u8, - pub interior: runtime_types::xcm::v3::junctions::Junctions, - } - } - pub mod traits { - use super::runtime_types; - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Error { - #[codec(index = 0)] - Overflow, - #[codec(index = 1)] - Unimplemented, - #[codec(index = 2)] - UntrustedReserveLocation, - #[codec(index = 3)] - UntrustedTeleportLocation, - #[codec(index = 4)] - LocationFull, - #[codec(index = 5)] - LocationNotInvertible, - #[codec(index = 6)] - BadOrigin, - #[codec(index = 7)] - InvalidLocation, - #[codec(index = 8)] - AssetNotFound, - #[codec(index = 9)] - FailedToTransactAsset, - #[codec(index = 10)] - NotWithdrawable, - #[codec(index = 11)] - LocationCannotHold, - #[codec(index = 12)] - ExceedsMaxMessageSize, - #[codec(index = 13)] - DestinationUnsupported, - #[codec(index = 14)] - Transport, - #[codec(index = 15)] - Unroutable, - #[codec(index = 16)] - UnknownClaim, - #[codec(index = 17)] - FailedToDecode, - #[codec(index = 18)] - MaxWeightInvalid, - #[codec(index = 19)] - NotHoldingFees, - #[codec(index = 20)] - TooExpensive, - #[codec(index = 21)] - Trap(::core::primitive::u64), - #[codec(index = 22)] - ExpectationFalse, - #[codec(index = 23)] - PalletNotFound, - #[codec(index = 24)] - NameMismatch, - #[codec(index = 25)] - VersionIncompatible, - #[codec(index = 26)] - HoldingWouldOverflow, - #[codec(index = 27)] - ExportError, - #[codec(index = 28)] - ReanchorFailed, - #[codec(index = 29)] - NoDeal, - #[codec(index = 30)] - FeesNotMet, - #[codec(index = 31)] - LockError, - #[codec(index = 32)] - NoPermission, - #[codec(index = 33)] - Unanchored, - #[codec(index = 34)] - NotDepositable, - #[codec(index = 35)] - UnhandledXcmVersion, - #[codec(index = 36)] - WeightLimitReached(::sp_weights::Weight), - #[codec(index = 37)] - Barrier, - #[codec(index = 38)] - WeightNotComputable, - #[codec(index = 39)] - ExceedsStackLimit, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Outcome { - #[codec(index = 0)] - Complete(::sp_weights::Weight), - #[codec(index = 1)] - Incomplete(::sp_weights::Weight, runtime_types::xcm::v3::traits::Error), - #[codec(index = 2)] - Error(runtime_types::xcm::v3::traits::Error), - } - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Instruction { - #[codec(index = 0)] - WithdrawAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 1)] - ReserveAssetDeposited(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ReceiveTeleportedAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 3)] - QueryResponse { - #[codec(compact)] - query_id: ::core::primitive::u64, - response: runtime_types::xcm::v3::Response, - max_weight: ::sp_weights::Weight, - querier: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - #[codec(index = 4)] - TransferAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 5)] - TransferReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 6)] - Transact { - origin_kind: runtime_types::xcm::v2::OriginKind, - require_weight_at_most: ::sp_weights::Weight, - call: runtime_types::xcm::double_encoded::DoubleEncoded, - }, - #[codec(index = 7)] - HrmpNewChannelOpenRequest { - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - max_message_size: ::core::primitive::u32, - #[codec(compact)] - max_capacity: ::core::primitive::u32, - }, - #[codec(index = 8)] - HrmpChannelAccepted { - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 9)] - HrmpChannelClosing { - #[codec(compact)] - initiator: ::core::primitive::u32, - #[codec(compact)] - sender: ::core::primitive::u32, - #[codec(compact)] - recipient: ::core::primitive::u32, - }, - #[codec(index = 10)] - ClearOrigin, - #[codec(index = 11)] - DescendOrigin(runtime_types::xcm::v3::junctions::Junctions), - #[codec(index = 12)] - ReportError(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 13)] - DepositAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - beneficiary: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 14)] - DepositReserveAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 15)] - ExchangeAsset { - give: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - want: runtime_types::xcm::v3::multiasset::MultiAssets, - maximal: ::core::primitive::bool, - }, - #[codec(index = 16)] - InitiateReserveWithdraw { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - reserve: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 17)] - InitiateTeleport { - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - dest: runtime_types::xcm::v3::multilocation::MultiLocation, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 18)] - ReportHolding { - response_info: runtime_types::xcm::v3::QueryResponseInfo, - assets: runtime_types::xcm::v3::multiasset::MultiAssetFilter, - }, - #[codec(index = 19)] - BuyExecution { - fees: runtime_types::xcm::v3::multiasset::MultiAsset, - weight_limit: runtime_types::xcm::v3::WeightLimit, - }, - #[codec(index = 20)] - RefundSurplus, - #[codec(index = 21)] - SetErrorHandler(runtime_types::xcm::v3::Xcm), - #[codec(index = 22)] - SetAppendix(runtime_types::xcm::v3::Xcm), - #[codec(index = 23)] - ClearError, - #[codec(index = 24)] - ClaimAsset { - assets: runtime_types::xcm::v3::multiasset::MultiAssets, - ticket: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 25)] - Trap(#[codec(compact)] ::core::primitive::u64), - #[codec(index = 26)] - SubscribeVersion { - #[codec(compact)] - query_id: ::core::primitive::u64, - max_response_weight: ::sp_weights::Weight, - }, - #[codec(index = 27)] - UnsubscribeVersion, - #[codec(index = 28)] - BurnAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 29)] - ExpectAsset(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 30)] - ExpectOrigin( - ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - ), - #[codec(index = 31)] - ExpectError( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 32)] - ExpectTransactStatus(runtime_types::xcm::v3::MaybeErrorCode), - #[codec(index = 33)] - QueryPallet { - module_name: ::std::vec::Vec<::core::primitive::u8>, - response_info: runtime_types::xcm::v3::QueryResponseInfo, - }, - #[codec(index = 34)] - ExpectPallet { - #[codec(compact)] - index: ::core::primitive::u32, - name: ::std::vec::Vec<::core::primitive::u8>, - module_name: ::std::vec::Vec<::core::primitive::u8>, - #[codec(compact)] - crate_major: ::core::primitive::u32, - #[codec(compact)] - min_crate_minor: ::core::primitive::u32, - }, - #[codec(index = 35)] - ReportTransactStatus(runtime_types::xcm::v3::QueryResponseInfo), - #[codec(index = 36)] - ClearTransactStatus, - #[codec(index = 37)] - UniversalOrigin(runtime_types::xcm::v3::junction::Junction), - #[codec(index = 38)] - ExportMessage { - network: runtime_types::xcm::v3::junction::NetworkId, - destination: runtime_types::xcm::v3::junctions::Junctions, - xcm: runtime_types::xcm::v3::Xcm, - }, - #[codec(index = 39)] - LockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - unlocker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 40)] - UnlockAsset { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - target: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 41)] - NoteUnlockable { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - owner: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 42)] - RequestUnlock { - asset: runtime_types::xcm::v3::multiasset::MultiAsset, - locker: runtime_types::xcm::v3::multilocation::MultiLocation, - }, - #[codec(index = 43)] - SetFeesMode { jit_withdraw: ::core::primitive::bool }, - #[codec(index = 44)] - SetTopic([::core::primitive::u8; 32usize]), - #[codec(index = 45)] - ClearTopic, - #[codec(index = 46)] - AliasOrigin(runtime_types::xcm::v3::multilocation::MultiLocation), - #[codec(index = 47)] - UnpaidExecution { - weight_limit: runtime_types::xcm::v3::WeightLimit, - check_origin: ::core::option::Option< - runtime_types::xcm::v3::multilocation::MultiLocation, - >, - }, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum MaybeErrorCode { - #[codec(index = 0)] - Success, - #[codec(index = 1)] - Error( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - #[codec(index = 2)] - TruncatedError( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - ), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct PalletInfo { - #[codec(compact)] - pub index: ::core::primitive::u32, - pub name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - pub module_name: runtime_types::bounded_collections::bounded_vec::BoundedVec< - ::core::primitive::u8, - >, - #[codec(compact)] - pub major: ::core::primitive::u32, - #[codec(compact)] - pub minor: ::core::primitive::u32, - #[codec(compact)] - pub patch: ::core::primitive::u32, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct QueryResponseInfo { - pub destination: runtime_types::xcm::v3::multilocation::MultiLocation, - #[codec(compact)] - pub query_id: ::core::primitive::u64, - pub max_weight: ::sp_weights::Weight, - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum Response { - #[codec(index = 0)] - Null, - #[codec(index = 1)] - Assets(runtime_types::xcm::v3::multiasset::MultiAssets), - #[codec(index = 2)] - ExecutionResult( - ::core::option::Option<( - ::core::primitive::u32, - runtime_types::xcm::v3::traits::Error, - )>, - ), - #[codec(index = 3)] - Version(::core::primitive::u32), - #[codec(index = 4)] - PalletsInfo( - runtime_types::bounded_collections::bounded_vec::BoundedVec< - runtime_types::xcm::v3::PalletInfo, - >, - ), - #[codec(index = 5)] - DispatchResult(runtime_types::xcm::v3::MaybeErrorCode), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum WeightLimit { - #[codec(index = 0)] - Unlimited, - #[codec(index = 1)] - Limited(::sp_weights::Weight), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub struct Xcm(pub ::std::vec::Vec); - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedAssetId { - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::AssetId), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiAssets { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multiasset::MultiAssets), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multiasset::MultiAssets), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedMultiLocation { - #[codec(index = 1)] - V2(runtime_types::xcm::v2::multilocation::MultiLocation), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::multilocation::MultiLocation), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedResponse { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Response), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Response), - } - #[derive(:: codec :: Decode, :: codec :: Encode, Clone, Debug, PartialEq)] - pub enum VersionedXcm { - #[codec(index = 2)] - V2(runtime_types::xcm::v2::Xcm), - #[codec(index = 3)] - V3(runtime_types::xcm::v3::Xcm), - } - } - } -} diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs deleted file mode 100644 index 42206baecf8f6..0000000000000 --- a/relays/client-westend/src/lib.rs +++ /dev/null @@ -1,122 +0,0 @@ -// 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 . - -//! Types used to connect to the Westend chain. - -pub mod codegen_runtime; - -use bp_polkadot_core::SuffixedCommonSignedExtensionExt; -use bp_westend::WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; -use codec::Encode; -use relay_substrate_client::{ - Chain, ChainWithBalances, ChainWithGrandpa, ChainWithRuntimeVersion, ChainWithTransactions, - Error as SubstrateError, RelayChain, SignParam, SimpleRuntimeVersion, UnderlyingChainProvider, - UnsignedTransaction, -}; -use sp_core::{storage::StorageKey, Pair}; -use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount, MultiAddress}; -use sp_session::MembershipProof; -use std::time::Duration; - -pub use codegen_runtime::api::runtime_types; - -pub type RuntimeCall = runtime_types::westend_runtime::RuntimeCall; - -pub type GrandpaCall = runtime_types::pallet_grandpa::pallet::Call; - -/// Westend header id. -pub type HeaderId = relay_utils::HeaderId; - -/// Westend header type used in headers sync. -pub type SyncHeader = relay_substrate_client::SyncHeader; - -/// The address format for describing accounts. -pub type Address = MultiAddress; - -/// Westend chain definition -#[derive(Debug, Clone, Copy)] -pub struct Westend; - -impl UnderlyingChainProvider for Westend { - type Chain = bp_westend::Westend; -} - -impl Chain for Westend { - const NAME: &'static str = "Westend"; - const BEST_FINALIZED_HEADER_ID_METHOD: &'static str = - bp_westend::BEST_FINALIZED_WESTEND_HEADER_METHOD; - const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6); - - type SignedBlock = bp_westend::SignedBlock; - type Call = RuntimeCall; -} - -impl ChainWithGrandpa for Westend { - const SYNCED_HEADERS_GRANDPA_INFO_METHOD: &'static str = - WESTEND_SYNCED_HEADERS_GRANDPA_INFO_METHOD; - - type KeyOwnerProof = MembershipProof; -} - -impl RelayChain for Westend { - const PARAS_PALLET_NAME: &'static str = bp_westend::PARAS_PALLET_NAME; -} - -impl ChainWithBalances for Westend { - fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { - bp_westend::AccountInfoStorageMapKeyProvider::final_key(account_id) - } -} - -impl ChainWithTransactions for Westend { - type AccountKeyPair = sp_core::sr25519::Pair; - type SignedTransaction = - bp_polkadot_core::UncheckedExtrinsic; - - fn sign_transaction( - param: SignParam, - unsigned: UnsignedTransaction, - ) -> Result { - let raw_payload = SignedPayload::new( - unsigned.call, - bp_westend::SignedExtension::from_params( - param.spec_version, - param.transaction_version, - unsigned.era, - param.genesis_hash, - unsigned.nonce, - unsigned.tip, - ((), ()), - ), - )?; - - let signature = raw_payload.using_encoded(|payload| param.signer.sign(payload)); - let signer: sp_runtime::MultiSigner = param.signer.public().into(); - let (call, extra, _) = raw_payload.deconstruct(); - - Ok(Self::SignedTransaction::new_signed( - call, - signer.into_account().into(), - signature.into(), - extra, - )) - } -} - -impl ChainWithRuntimeVersion for Westend { - const RUNTIME_VERSION: Option = - Some(SimpleRuntimeVersion { spec_version: 1_008_000, transaction_version: 24 }); -} diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index db4c3a7f8875c..5bd14bb832008 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -58,6 +58,6 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas [dev-dependencies] bp-rococo = { path = "../../chains/chain-rococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -relay-bridge-hub-rococo-client = { path = "../client-bridge-hub-rococo" } -relay-bridge-hub-westend-client = { path = "../client-bridge-hub-westend" } -relay-rococo-client = { path = "../client-rococo" } +relay-bridge-hub-rococo-client = { path = "../../relay-clients/client-bridge-hub-rococo" } +relay-bridge-hub-westend-client = { path = "../../relay-clients/client-bridge-hub-westend" } +relay-rococo-client = { path = "../../relay-clients/client-rococo" } From 817ccfc72ca8d175c2c83f1a16c56502660187e3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 26 Mar 2024 11:34:22 +0300 Subject: [PATCH 1199/1210] relayer waits until chain spec version matches the configured in Client constructor/reconnect (#2894) --- relays/client-substrate/Cargo.toml | 2 +- relays/client-substrate/src/client.rs | 141 ++++++++++++++++++++++++-- relays/client-substrate/src/error.rs | 12 +++ relays/client-substrate/src/guard.rs | 10 +- 4 files changed, 153 insertions(+), 12 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index c1dea9b501523..9240af7b59c5b 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -52,7 +52,7 @@ sp-version = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas # Polkadot Dependencies -xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } +xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [features] default = [] diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 8328e1ce8bec1..676fea487b35b 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -18,6 +18,7 @@ use crate::{ chain::{Chain, ChainWithTransactions}, + guard::Environment, rpc::{ SubstrateAuthorClient, SubstrateChainClient, SubstrateFinalityClient, SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, @@ -49,7 +50,7 @@ use sp_runtime::{ }; use sp_trie::StorageProof; use sp_version::RuntimeVersion; -use std::future::Future; +use std::{cmp::Ordering, future::Future}; const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities"; const SUB_API_GRANDPA_GENERATE_KEY_OWNERSHIP_PROOF: &str = @@ -101,7 +102,7 @@ impl SimpleRuntimeVersion { } /// Chain runtime version in client -#[derive(Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub enum ChainRuntimeVersion { /// Auto query from chain. Auto, @@ -164,7 +165,7 @@ impl Clone for Client { fn clone(&self) -> Self { Client { params: self.params.clone(), - chain_runtime_version: self.chain_runtime_version.clone(), + chain_runtime_version: self.chain_runtime_version, submit_signed_extrinsic_lock: self.submit_signed_extrinsic_lock.clone(), genesis_hash: self.genesis_hash, data: self.data.clone(), @@ -214,14 +215,48 @@ impl Client { }) .await??; - let chain_runtime_version = params.chain_runtime_version.clone(); - Ok(Self { + let chain_runtime_version = params.chain_runtime_version; + let mut client = Self { params, chain_runtime_version, submit_signed_extrinsic_lock: Arc::new(Mutex::new(())), genesis_hash, data: Arc::new(RwLock::new(ClientData { tokio, client })), - }) + }; + Self::ensure_correct_runtime_version(&mut client, chain_runtime_version).await?; + Ok(client) + } + + // Check runtime version to understand if we need are connected to expected version, or we + // need to wait for upgrade, we need to abort immediately. + async fn ensure_correct_runtime_version>( + env: &mut E, + expected: ChainRuntimeVersion, + ) -> Result<()> { + // we are only interested if version mode is bundled or passed using CLI + let expected = match expected { + ChainRuntimeVersion::Auto => return Ok(()), + ChainRuntimeVersion::Custom(expected) => expected, + }; + + // we need to wait if actual version is < than expected, we are OK of versions are the + // same and we need to abort if actual version is > than expected + let actual = SimpleRuntimeVersion::from_runtime_version(&env.runtime_version().await?); + match actual.spec_version.cmp(&expected.spec_version) { + Ordering::Less => + Err(Error::WaitingForRuntimeUpgrade { chain: C::NAME.into(), expected, actual }), + Ordering::Equal => Ok(()), + Ordering::Greater => { + log::error!( + target: "bridge", + "The {} client is configured to use runtime version {expected:?} and actual \ + version is {actual:?}. Aborting", + C::NAME, + ); + env.abort().await; + Err(Error::Custom("Aborted".into())) + }, + } } /// Build client to use in connection. @@ -849,3 +884,97 @@ impl Subscription { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{guard::tests::TestEnvironment, test_chain::TestChain}; + use futures::{channel::mpsc::unbounded, FutureExt}; + + async fn run_ensure_correct_runtime_version( + expected: ChainRuntimeVersion, + actual: RuntimeVersion, + ) -> Result<()> { + let ( + (mut runtime_version_tx, runtime_version_rx), + (slept_tx, _slept_rx), + (aborted_tx, mut aborted_rx), + ) = (unbounded(), unbounded(), unbounded()); + runtime_version_tx.send(actual).await.unwrap(); + let mut env = TestEnvironment { runtime_version_rx, slept_tx, aborted_tx }; + + let ensure_correct_runtime_version = + Client::::ensure_correct_runtime_version(&mut env, expected).boxed(); + let aborted = aborted_rx.next().map(|_| Err(Error::Custom("".into()))).boxed(); + futures::pin_mut!(ensure_correct_runtime_version, aborted); + futures::future::select(ensure_correct_runtime_version, aborted) + .await + .into_inner() + .0 + } + + #[async_std::test] + async fn ensure_correct_runtime_version_works() { + // when we are configured to use auto version + assert!(matches!( + run_ensure_correct_runtime_version( + ChainRuntimeVersion::Auto, + RuntimeVersion { + spec_version: 100, + transaction_version: 100, + ..Default::default() + }, + ) + .await, + Ok(()), + )); + // when actual == expected + assert!(matches!( + run_ensure_correct_runtime_version( + ChainRuntimeVersion::Custom(SimpleRuntimeVersion { + spec_version: 100, + transaction_version: 100 + }), + RuntimeVersion { + spec_version: 100, + transaction_version: 100, + ..Default::default() + }, + ) + .await, + Ok(()), + )); + // when actual spec version < expected spec version + assert!(matches!( + run_ensure_correct_runtime_version( + ChainRuntimeVersion::Custom(SimpleRuntimeVersion { + spec_version: 100, + transaction_version: 100 + }), + RuntimeVersion { spec_version: 99, transaction_version: 100, ..Default::default() }, + ) + .await, + Err(Error::WaitingForRuntimeUpgrade { + expected: SimpleRuntimeVersion { spec_version: 100, transaction_version: 100 }, + actual: SimpleRuntimeVersion { spec_version: 99, transaction_version: 100 }, + .. + }), + )); + // when actual spec version > expected spec version + assert!(matches!( + run_ensure_correct_runtime_version( + ChainRuntimeVersion::Custom(SimpleRuntimeVersion { + spec_version: 100, + transaction_version: 100 + }), + RuntimeVersion { + spec_version: 101, + transaction_version: 100, + ..Default::default() + }, + ) + .await, + Err(Error::Custom(_)), + )); + } +} diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 40015c122bbe9..257771b70b1f1 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -16,6 +16,7 @@ //! Substrate node RPC errors. +use crate::SimpleRuntimeVersion; use bp_polkadot_core::parachains::ParaId; use jsonrpsee::core::Error as RpcError; use relay_utils::MaybeConnectionError; @@ -117,6 +118,17 @@ pub enum Error { /// The Substrate transaction is invalid. #[error("Substrate transaction is invalid: {0:?}")] TransactionInvalid(#[from] TransactionValidityError), + /// The client is configured to use newer runtime version than the connected chain uses. + /// The client will keep waiting until chain is upgraded to given version. + #[error("Waiting for {chain} runtime upgrade: expected {expected:?} actual {actual:?}")] + WaitingForRuntimeUpgrade { + /// Name of the chain where the error has happened. + chain: String, + /// Expected runtime version. + expected: SimpleRuntimeVersion, + /// Actual runtime version. + actual: SimpleRuntimeVersion, + }, /// Custom logic error. #[error("{0}")] Custom(String), diff --git a/relays/client-substrate/src/guard.rs b/relays/client-substrate/src/guard.rs index 545396b30b859..47454892cd039 100644 --- a/relays/client-substrate/src/guard.rs +++ b/relays/client-substrate/src/guard.rs @@ -107,7 +107,7 @@ impl Environment for Client { } #[cfg(test)] -mod tests { +pub(crate) mod tests { use super::*; use crate::test_chain::TestChain; use futures::{ @@ -117,10 +117,10 @@ mod tests { SinkExt, }; - struct TestEnvironment { - runtime_version_rx: UnboundedReceiver, - slept_tx: UnboundedSender<()>, - aborted_tx: UnboundedSender<()>, + pub struct TestEnvironment { + pub runtime_version_rx: UnboundedReceiver, + pub slept_tx: UnboundedSender<()>, + pub aborted_tx: UnboundedSender<()>, } #[async_trait] From 912761469dd7482bf37e68e14e32635e07d059d2 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 26 Mar 2024 12:57:23 +0100 Subject: [PATCH 1200/1210] polkadot-sdk backport leftovers (#2896) --- bin/.keep | 0 primitives/runtime/src/chain.rs | 11 ----------- 2 files changed, 11 deletions(-) delete mode 100644 bin/.keep diff --git a/bin/.keep b/bin/.keep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 00bea2b3ca613..9ba21a1cddf13 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -98,17 +98,6 @@ impl Encode for EncodedOrDecodedCall { } } -// dummy implementation to satisfy `SignedPayload` requirements -impl sp_runtime::traits::Dispatchable for EncodedOrDecodedCall { - type RuntimeOrigin = (); - type Config = (); - type Info = (); - type PostInfo = (); - fn dispatch(self, _origin: ()) -> sp_runtime::DispatchResultWithInfo<()> { - unreachable!("never used by relayer; qed") - } -} - /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { /// Chain id. From 62e9e3dab2ebc96ade565fa268b3d2b799fed74c Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 27 Mar 2024 12:16:30 +0100 Subject: [PATCH 1201/1210] Remove test dependecies on specific relay clients (#2898) --- relays/client-substrate/src/test_chain.rs | 17 ++++++++-- relays/lib-substrate-relay/Cargo.toml | 4 +-- .../src/messages_source.rs | 34 +++++++------------ .../src/on_demand/headers.rs | 3 +- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/relays/client-substrate/src/test_chain.rs b/relays/client-substrate/src/test_chain.rs index 214f8d87a1f9f..77240d15884f4 100644 --- a/relays/client-substrate/src/test_chain.rs +++ b/relays/client-substrate/src/test_chain.rs @@ -21,7 +21,8 @@ #![cfg(any(feature = "test-helpers", test))] -use crate::{Chain, ChainWithBalances}; +use crate::{Chain, ChainWithBalances, ChainWithMessages}; +use bp_messages::{ChainWithMessages as ChainWithMessagesBase, MessageNonce}; use bp_runtime::ChainId; use frame_support::weights::Weight; use std::time::Duration; @@ -44,7 +45,7 @@ impl bp_runtime::Chain for TestChain { type Signature = sp_runtime::testing::TestSignature; fn max_extrinsic_size() -> u32 { - unreachable!() + 100000 } fn max_extrinsic_weight() -> Weight { @@ -69,6 +70,18 @@ impl ChainWithBalances for TestChain { } } +impl ChainWithMessagesBase for TestChain { + const WITH_CHAIN_MESSAGES_PALLET_NAME: &'static str = "Test"; + const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 0; + const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 0; +} + +impl ChainWithMessages for TestChain { + const WITH_CHAIN_RELAYERS_PALLET_NAME: Option<&'static str> = None; + const TO_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "TestMessagesDetailsMethod"; + const FROM_CHAIN_MESSAGE_DETAILS_METHOD: &'static str = "TestFromMessagesDetailsMethod"; +} + /// Primitives-level parachain that may be used in tests. #[derive(Clone, Debug, PartialEq, Eq)] pub struct TestParachainBase; diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 5bd14bb832008..99ff91a750619 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -58,6 +58,4 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas [dev-dependencies] bp-rococo = { path = "../../chains/chain-rococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -relay-bridge-hub-rococo-client = { path = "../../relay-clients/client-bridge-hub-rococo" } -relay-bridge-hub-westend-client = { path = "../../relay-clients/client-bridge-hub-westend" } -relay-rococo-client = { path = "../../relay-clients/client-rococo" } +relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/relays/lib-substrate-relay/src/messages_source.rs index 26e10f8868cea..49deff046f9ca 100644 --- a/relays/lib-substrate-relay/src/messages_source.rs +++ b/relays/lib-substrate-relay/src/messages_source.rs @@ -554,9 +554,7 @@ fn split_msgs_to_refine( #[cfg(test)] mod tests { use super::*; - use bp_runtime::Chain as ChainBase; - use relay_bridge_hub_rococo_client::BridgeHubRococo; - use relay_bridge_hub_westend_client::BridgeHubWestend; + use relay_substrate_client::test_chain::TestChain; fn message_details_from_rpc( nonces: RangeInclusive, @@ -573,20 +571,14 @@ mod tests { #[test] fn validate_out_msgs_details_succeeds_if_no_messages_are_missing() { - assert!(validate_out_msgs_details::( - &message_details_from_rpc(1..=3), - 1..=3, - ) - .is_ok()); + assert!(validate_out_msgs_details::(&message_details_from_rpc(1..=3), 1..=3,) + .is_ok()); } #[test] fn validate_out_msgs_details_succeeds_if_head_messages_are_missing() { - assert!(validate_out_msgs_details::( - &message_details_from_rpc(2..=3), - 1..=3, - ) - .is_ok()) + assert!(validate_out_msgs_details::(&message_details_from_rpc(2..=3), 1..=3,) + .is_ok()) } #[test] @@ -594,7 +586,7 @@ mod tests { let mut message_details_from_rpc = message_details_from_rpc(1..=3); message_details_from_rpc.remove(1); assert!(matches!( - validate_out_msgs_details::(&message_details_from_rpc, 1..=3,), + validate_out_msgs_details::(&message_details_from_rpc, 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -602,7 +594,7 @@ mod tests { #[test] fn validate_out_msgs_details_map_fails_if_tail_messages_are_missing() { assert!(matches!( - validate_out_msgs_details::(&message_details_from_rpc(1..=2), 1..=3,), + validate_out_msgs_details::(&message_details_from_rpc(1..=2), 1..=3,), Err(SubstrateError::Custom(_)) )); } @@ -610,7 +602,7 @@ mod tests { #[test] fn validate_out_msgs_details_fails_if_all_messages_are_missing() { assert!(matches!( - validate_out_msgs_details::(&[], 1..=3), + validate_out_msgs_details::(&[], 1..=3), Err(SubstrateError::Custom(_)) )); } @@ -618,7 +610,7 @@ mod tests { #[test] fn validate_out_msgs_details_fails_if_more_messages_than_nonces() { assert!(matches!( - validate_out_msgs_details::(&message_details_from_rpc(1..=5), 2..=5,), + validate_out_msgs_details::(&message_details_from_rpc(1..=5), 2..=5,), Err(SubstrateError::Custom(_)) )); } @@ -644,10 +636,8 @@ mod tests { msgs_to_refine.push((payload, out_msg_details)); } - let maybe_batches = split_msgs_to_refine::( - Default::default(), - msgs_to_refine, - ); + let maybe_batches = + split_msgs_to_refine::(Default::default(), msgs_to_refine); match expected_batches { Ok(expected_batches) => { let batches = maybe_batches.unwrap(); @@ -669,7 +659,7 @@ mod tests { #[test] fn test_split_msgs_to_refine() { - let max_extrinsic_size = BridgeHubRococo::max_extrinsic_size() as usize; + let max_extrinsic_size = 100000; // Check that an error is returned when one of the messages is too big. check_split_msgs_to_refine(vec![max_extrinsic_size], Err(())); diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 8b58552d292c4..99ca1d4d5a726 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -526,8 +526,7 @@ fn on_demand_headers_relay_name() -> Str #[cfg(test)] mod tests { use super::*; - - type TestChain = relay_rococo_client::Rococo; + use relay_substrate_client::test_chain::TestChain; const AT_SOURCE: Option = Some(10); const AT_TARGET: Option = Some(1); From 5047d8b4c168a257e999e0eb14695ea4522de5fd Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 27 Mar 2024 12:44:50 +0100 Subject: [PATCH 1202/1210] Backport changes from polkadot-sdk (#2899) * Fix spelling mistakes across the whole repository (#3808) **Update:** Pushed additional changes based on the review comments. **This pull request fixes various spelling mistakes in this repository.** Most of the changes are contained in the first **3** commits: - `Fix spelling mistakes in comments and docs` - `Fix spelling mistakes in test names` - `Fix spelling mistakes in error messages, panic messages, logs and tracing` Other source code spelling mistakes are separated into individual commits for easier reviewing: - `Fix the spelling of 'authority'` - `Fix the spelling of 'REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY'` - `Fix the spelling of 'prev_enqueud_messages'` - `Fix the spelling of 'endpoint'` - `Fix the spelling of 'children'` - `Fix the spelling of 'PenpalSiblingSovereignAccount'` - `Fix the spelling of 'PenpalSudoAccount'` - `Fix the spelling of 'insufficient'` - `Fix the spelling of 'PalletXcmExtrinsicsBenchmark'` - `Fix the spelling of 'subtracted'` - `Fix the spelling of 'CandidatePendingAvailability'` - `Fix the spelling of 'exclusive'` - `Fix the spelling of 'until'` - `Fix the spelling of 'discriminator'` - `Fix the spelling of 'nonexistent'` - `Fix the spelling of 'subsystem'` - `Fix the spelling of 'indices'` - `Fix the spelling of 'committed'` - `Fix the spelling of 'topology'` - `Fix the spelling of 'response'` - `Fix the spelling of 'beneficiary'` - `Fix the spelling of 'formatted'` - `Fix the spelling of 'UNKNOWN_PROOF_REQUEST'` - `Fix the spelling of 'succeeded'` - `Fix the spelling of 'reopened'` - `Fix the spelling of 'proposer'` - `Fix the spelling of 'InstantiationNonce'` - `Fix the spelling of 'depositor'` - `Fix the spelling of 'expiration'` - `Fix the spelling of 'phantom'` - `Fix the spelling of 'AggregatedKeyValue'` - `Fix the spelling of 'randomness'` - `Fix the spelling of 'defendant'` - `Fix the spelling of 'AquaticMammal'` - `Fix the spelling of 'transactions'` - `Fix the spelling of 'PassingTracingSubscriber'` - `Fix the spelling of 'TxSignaturePayload'` - `Fix the spelling of 'versioning'` - `Fix the spelling of 'descendant'` - `Fix the spelling of 'overridden'` - `Fix the spelling of 'network'` Let me know if this structure is adequate. **Note:** The usage of the words `Merkle`, `Merkelize`, `Merklization`, `Merkelization`, `Merkleization`, is somewhat inconsistent but I left it as it is. ~~**Note:** In some places the term `Receival` is used to refer to message reception, IMO `Reception` is the correct word here, but I left it as it is.~~ ~~**Note:** In some places the term `Overlayed` is used instead of the more acceptable version `Overlaid` but I also left it as it is.~~ ~~**Note:** In some places the term `Applyable` is used instead of the correct version `Applicable` but I also left it as it is.~~ **Note:** Some usage of British vs American english e.g. `judgement` vs `judgment`, `initialise` vs `initialize`, `optimise` vs `optimize` etc. are both present in different places, but I suppose that's understandable given the number of contributors. ~~**Note:** There is a spelling mistake in `.github/CODEOWNERS` but it triggers errors in CI when I make changes to it, so I left it as it is.~~ (cherry picked from commit 002d9260f9a0f844f87eefd0abce8bd95aae351b) * Fix --------- Co-authored-by: Dcompoze --- bin/runtime-common/src/messages_api.rs | 2 +- .../src/messages_xcm_extension.rs | 2 +- bin/runtime-common/src/mock.rs | 2 +- bin/runtime-common/src/priority_calculator.rs | 2 +- .../src/refund_relayer_extension.rs | 4 +- chains/chain-kusama/src/lib.rs | 4 +- chains/chain-polkadot-bulletin/src/lib.rs | 8 ++-- chains/chain-polkadot/src/lib.rs | 4 +- chains/chain-rococo/src/lib.rs | 4 +- chains/chain-westend/src/lib.rs | 4 +- modules/grandpa/README.md | 2 +- modules/grandpa/src/call_ext.rs | 8 ++-- modules/grandpa/src/lib.rs | 4 +- modules/grandpa/src/mock.rs | 2 +- modules/messages/src/inbound_lane.rs | 40 +++++++++---------- modules/messages/src/lib.rs | 30 +++++++------- modules/messages/src/outbound_lane.rs | 30 +++++++------- modules/parachains/src/mock.rs | 4 +- modules/xcm-bridge-hub-router/src/lib.rs | 2 +- modules/xcm-bridge-hub/Cargo.toml | 2 +- .../header-chain/src/justification/mod.rs | 2 +- .../src/justification/verification/mod.rs | 2 +- primitives/header-chain/src/lib.rs | 8 ++-- primitives/messages/src/lib.rs | 8 ++-- primitives/polkadot-core/src/lib.rs | 2 +- primitives/runtime/src/chain.rs | 6 +-- primitives/runtime/src/lib.rs | 4 +- primitives/test-utils/src/lib.rs | 2 +- .../environments/rococo-westend/rococo.zndsl | 4 +- .../environments/rococo-westend/westend.zndsl | 4 +- .../utils/generate_hex_encoded_call/index.js | 18 ++++----- testing/run-tests.sh | 2 +- .../run.sh | 2 +- 33 files changed, 112 insertions(+), 112 deletions(-) diff --git a/bin/runtime-common/src/messages_api.rs b/bin/runtime-common/src/messages_api.rs index ccf1c754041ed..7fbdeb3661247 100644 --- a/bin/runtime-common/src/messages_api.rs +++ b/bin/runtime-common/src/messages_api.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -//! Helpers for implementing various message-related runtime API mthods. +//! Helpers for implementing various message-related runtime API methods. use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bin/runtime-common/src/messages_xcm_extension.rs index e3da6155f08a1..46ed4da0d8548 100644 --- a/bin/runtime-common/src/messages_xcm_extension.rs +++ b/bin/runtime-common/src/messages_xcm_extension.rs @@ -248,7 +248,7 @@ impl LocalXcmQueueManager { sender_and_lane: &SenderAndLane, enqueued_messages: MessageNonce, ) { - // skip if we dont want to handle congestion + // skip if we don't want to handle congestion if !H::supports_congestion_detection() { return } diff --git a/bin/runtime-common/src/mock.rs b/bin/runtime-common/src/mock.rs index deee4524e8586..8c4cb2233e17c 100644 --- a/bin/runtime-common/src/mock.rs +++ b/bin/runtime-common/src/mock.rs @@ -379,7 +379,7 @@ impl Chain for BridgedUnderlyingChain { impl ChainWithGrandpa for BridgedUnderlyingChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } diff --git a/bin/runtime-common/src/priority_calculator.rs b/bin/runtime-common/src/priority_calculator.rs index c2737128e3422..5035553f508df 100644 --- a/bin/runtime-common/src/priority_calculator.rs +++ b/bin/runtime-common/src/priority_calculator.rs @@ -163,7 +163,7 @@ mod integrity_tests { { // just an estimation of extra transaction bytes that are added to every transaction // (including signature, signed extensions extra and etc + in our case it includes - // all call arguments extept the proof itself) + // all call arguments except the proof itself) let base_tx_size = 512; // let's say we are relaying similar small messages and for every message we add more trie // nodes to the proof (x0.5 because we expect some nodes to be reused) diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bin/runtime-common/src/refund_relayer_extension.rs index 8e901d72821fe..455392a0a277f 100644 --- a/bin/runtime-common/src/refund_relayer_extension.rs +++ b/bin/runtime-common/src/refund_relayer_extension.rs @@ -1538,7 +1538,7 @@ mod tests { } #[test] - fn validate_boosts_priority_of_message_delivery_transactons() { + fn validate_boosts_priority_of_message_delivery_transactions() { run_test(|| { initialize_environment(100, 100, 100); @@ -1568,7 +1568,7 @@ mod tests { } #[test] - fn validate_does_not_boost_priority_of_message_delivery_transactons_with_too_many_messages() { + fn validate_does_not_boost_priority_of_message_delivery_transactions_with_too_many_messages() { run_test(|| { initialize_environment(100, 100, 100); diff --git a/chains/chain-kusama/src/lib.rs b/chains/chain-kusama/src/lib.rs index e3b4d0520f61c..a81004afe8127 100644 --- a/chains/chain-kusama/src/lib.rs +++ b/chains/chain-kusama/src/lib.rs @@ -53,8 +53,8 @@ impl Chain for Kusama { impl ChainWithGrandpa for Kusama { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_KUSAMA_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/chains/chain-polkadot-bulletin/src/lib.rs b/chains/chain-polkadot-bulletin/src/lib.rs index f2eebf9312470..f3d300567f2b4 100644 --- a/chains/chain-polkadot-bulletin/src/lib.rs +++ b/chains/chain-polkadot-bulletin/src/lib.rs @@ -43,7 +43,7 @@ use sp_runtime::{traits::DispatchInfoOf, transaction_validity::TransactionValidi pub use bp_polkadot_core::{ AccountAddress, AccountId, Balance, Block, BlockNumber, Hash, Hasher, Header, Nonce, Signature, SignedBlock, UncheckedExtrinsic, AVERAGE_HEADER_SIZE, EXTRA_STORAGE_PROOF_SIZE, - MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, + MAX_MANDATORY_HEADER_SIZE, REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY, }; /// Maximal number of GRANDPA authorities at Polkadot Bulletin chain. @@ -62,7 +62,7 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(90); // Re following constants - we are using the same values at Cumulus parachains. They are limited // by the maximal transaction weight/size. Since block limits at Bulletin Chain are larger than -// at the Cumulus Bridgeg Hubs, we could reuse the same values. +// at the Cumulus Bridge Hubs, we could reuse the same values. /// Maximal number of unrewarded relayer entries at inbound lane for Cumulus-based parachains. pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; @@ -207,8 +207,8 @@ impl Chain for PolkadotBulletin { impl ChainWithGrandpa for PolkadotBulletin { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_POLKADOT_BULLETIN_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/chains/chain-polkadot/src/lib.rs b/chains/chain-polkadot/src/lib.rs index fc5e10308a8e3..00d35783a9b61 100644 --- a/chains/chain-polkadot/src/lib.rs +++ b/chains/chain-polkadot/src/lib.rs @@ -55,8 +55,8 @@ impl Chain for Polkadot { impl ChainWithGrandpa for Polkadot { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_POLKADOT_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/chains/chain-rococo/src/lib.rs b/chains/chain-rococo/src/lib.rs index f1b256f0f090f..2385dd2cbb250 100644 --- a/chains/chain-rococo/src/lib.rs +++ b/chains/chain-rococo/src/lib.rs @@ -53,8 +53,8 @@ impl Chain for Rococo { impl ChainWithGrandpa for Rococo { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_ROCOCO_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/chains/chain-westend/src/lib.rs b/chains/chain-westend/src/lib.rs index f03fd2160a700..b344b7f4bf933 100644 --- a/chains/chain-westend/src/lib.rs +++ b/chains/chain-westend/src/lib.rs @@ -53,8 +53,8 @@ impl Chain for Westend { impl ChainWithGrandpa for Westend { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = WITH_WESTEND_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = AVERAGE_HEADER_SIZE; } diff --git a/modules/grandpa/README.md b/modules/grandpa/README.md index 992bd2cc47228..4a3099b8afc65 100644 --- a/modules/grandpa/README.md +++ b/modules/grandpa/README.md @@ -10,7 +10,7 @@ It is used by the parachains light client (bridge parachains pallet) and by mess ## A Brief Introduction into GRANDPA Finality You can find detailed information on GRANDPA, by exploring its [repository](https://github.com/paritytech/finality-grandpa). -Here is the minimal reqiuired GRANDPA information to understand how pallet works. +Here is the minimal required GRANDPA information to understand how pallet works. Any Substrate chain may use different block authorship algorithms (like BABE or Aura) to determine block producers and generate blocks. This has nothing common with finality, though - the task of block authorship is to coordinate diff --git a/modules/grandpa/src/call_ext.rs b/modules/grandpa/src/call_ext.rs index e3c778b480baa..4a7ebb3cc8d42 100644 --- a/modules/grandpa/src/call_ext.rs +++ b/modules/grandpa/src/call_ext.rs @@ -205,7 +205,7 @@ pub(crate) fn submit_finality_proof_info_from_args, I: 'static>( // as an extra weight. let votes_ancestries_len = justification.votes_ancestries.len().saturated_into(); let extra_weight = - if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY { + if votes_ancestries_len > T::BridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY { T::WeightInfo::submit_finality_proof(precommits_len, votes_ancestries_len) } else { Weight::zero() @@ -396,11 +396,11 @@ mod tests { let finality_target = test_header(1); let mut justification_params = JustificationGeneratorParams { header: finality_target.clone(), - ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY, + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY, ..Default::default() }; - // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY` headers => no refund + // when there are `REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY` headers => no refund let justification = make_justification_for_header(justification_params.clone()); let call = RuntimeCall::Grandpa(crate::Call::submit_finality_proof_ex { finality_target: Box::new(finality_target.clone()), @@ -409,7 +409,7 @@ mod tests { }); assert_eq!(call.submit_finality_proof_info().unwrap().extra_weight, Weight::zero()); - // when there are `REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + 1` headers => full refund + // when there are `REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY + 1` headers => full refund justification_params.ancestors += 1; let justification = make_justification_for_header(justification_params); let call_weight = ::WeightInfo::submit_finality_proof( diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index ce2c47da954fa..9e095651ef81d 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -935,7 +935,7 @@ mod tests { } #[test] - fn succesfully_imports_header_with_valid_finality() { + fn successfully_imports_header_with_valid_finality() { run_test(|| { initialize_substrate_bridge(); @@ -1192,7 +1192,7 @@ mod tests { header.digest = change_log(0); let justification = make_justification_for_header(JustificationGeneratorParams { header: header.clone(), - ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY + 1, + ancestors: TestBridgedChain::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY + 1, ..Default::default() }); diff --git a/modules/grandpa/src/mock.rs b/modules/grandpa/src/mock.rs index 4318d663a2e17..e689e520c92ff 100644 --- a/modules/grandpa/src/mock.rs +++ b/modules/grandpa/src/mock.rs @@ -87,7 +87,7 @@ impl Chain for TestBridgedChain { impl ChainWithGrandpa for TestBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = MAX_BRIDGED_AUTHORITIES; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } diff --git a/modules/messages/src/inbound_lane.rs b/modules/messages/src/inbound_lane.rs index 966ec939e70e2..da1698e6e0370 100644 --- a/modules/messages/src/inbound_lane.rs +++ b/modules/messages/src/inbound_lane.rs @@ -21,7 +21,7 @@ use crate::Config; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, OutboundLaneData, - ReceivalResult, UnrewardedRelayer, + ReceptionResult, UnrewardedRelayer, }; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; use frame_support::traits::Get; @@ -170,21 +170,21 @@ impl InboundLane { relayer_at_bridged_chain: &S::Relayer, nonce: MessageNonce, message_data: DispatchMessageData, - ) -> ReceivalResult { + ) -> ReceptionResult { let mut data = self.storage.get_or_init_data(); if Some(nonce) != data.last_delivered_nonce().checked_add(1) { - return ReceivalResult::InvalidNonce + return ReceptionResult::InvalidNonce } // if there are more unrewarded relayer entries than we may accept, reject this message if data.relayers.len() as MessageNonce >= self.storage.max_unrewarded_relayer_entries() { - return ReceivalResult::TooManyUnrewardedRelayers + return ReceptionResult::TooManyUnrewardedRelayers } // if there are more unconfirmed messages than we may accept, reject this message let unconfirmed_messages_count = nonce.saturating_sub(data.last_confirmed_nonce); if unconfirmed_messages_count > self.storage.max_unconfirmed_messages() { - return ReceivalResult::TooManyUnconfirmedMessages + return ReceptionResult::TooManyUnconfirmedMessages } // then, dispatch message @@ -207,7 +207,7 @@ impl InboundLane { }; self.storage.set_data(data); - ReceivalResult::Dispatched(dispatch_result) + ReceptionResult::Dispatched(dispatch_result) } } @@ -235,7 +235,7 @@ mod tests { nonce, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); } @@ -362,7 +362,7 @@ mod tests { 10, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::InvalidNonce + ReceptionResult::InvalidNonce ); assert_eq!(lane.storage.get_or_init_data().last_delivered_nonce(), 0); }); @@ -381,7 +381,7 @@ mod tests { current_nonce, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); } // Fails to dispatch new message from different than latest relayer. @@ -391,7 +391,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnrewardedRelayers, + ReceptionResult::TooManyUnrewardedRelayers, ); // Fails to dispatch new messages from latest relayer. Prevents griefing attacks. assert_eq!( @@ -400,7 +400,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnrewardedRelayers, + ReceptionResult::TooManyUnrewardedRelayers, ); }); } @@ -417,7 +417,7 @@ mod tests { current_nonce, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); } // Fails to dispatch new message from different than latest relayer. @@ -427,7 +427,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnconfirmedMessages, + ReceptionResult::TooManyUnconfirmedMessages, ); // Fails to dispatch new messages from latest relayer. assert_eq!( @@ -436,7 +436,7 @@ mod tests { max_nonce + 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::TooManyUnconfirmedMessages, + ReceptionResult::TooManyUnconfirmedMessages, ); }); } @@ -451,7 +451,7 @@ mod tests { 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.receive_message::( @@ -459,7 +459,7 @@ mod tests { 2, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.receive_message::( @@ -467,7 +467,7 @@ mod tests { 3, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.storage.get_or_init_data().relayers, @@ -490,7 +490,7 @@ mod tests { 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::Dispatched(dispatch_result(0)) + ReceptionResult::Dispatched(dispatch_result(0)) ); assert_eq!( lane.receive_message::( @@ -498,7 +498,7 @@ mod tests { 1, inbound_message_data(REGULAR_PAYLOAD) ), - ReceivalResult::InvalidNonce, + ReceptionResult::InvalidNonce, ); }); } @@ -524,7 +524,7 @@ mod tests { 1, inbound_message_data(payload) ), - ReceivalResult::Dispatched(dispatch_result(1)) + ReceptionResult::Dispatched(dispatch_result(1)) ); }); } diff --git a/modules/messages/src/lib.rs b/modules/messages/src/lib.rs index a86cb326cf040..bc00db9eba5ba 100644 --- a/modules/messages/src/lib.rs +++ b/modules/messages/src/lib.rs @@ -47,7 +47,7 @@ pub use weights_ext::{ use crate::{ inbound_lane::{InboundLane, InboundLaneStorage}, - outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmationError}, + outbound_lane::{OutboundLane, OutboundLaneStorage, ReceptionConfirmationError}, }; use bp_messages::{ @@ -90,7 +90,7 @@ pub const LOG_TARGET: &str = "runtime::bridge-messages"; #[frame_support::pallet] pub mod pallet { use super::*; - use bp_messages::{ReceivalResult, ReceivedMessages}; + use bp_messages::{ReceivedMessages, ReceptionResult}; use bp_runtime::RangeInclusiveExt; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; @@ -376,13 +376,13 @@ pub mod pallet { // delivery transaction cost anyway. And base cost covers everything except // dispatch, so we have a balance here. let unspent_weight = match &receival_result { - ReceivalResult::Dispatched(dispatch_result) => { + ReceptionResult::Dispatched(dispatch_result) => { valid_messages += 1; dispatch_result.unspent_weight }, - ReceivalResult::InvalidNonce | - ReceivalResult::TooManyUnrewardedRelayers | - ReceivalResult::TooManyUnconfirmedMessages => message_dispatch_weight, + ReceptionResult::InvalidNonce | + ReceptionResult::TooManyUnrewardedRelayers | + ReceptionResult::TooManyUnconfirmedMessages => message_dispatch_weight, }; lane_messages_received_status.push(message.key.nonce, receival_result); @@ -455,7 +455,7 @@ pub mod pallet { last_delivered_nonce, &lane_data.relayers, ) - .map_err(Error::::ReceivalConfirmation)?; + .map_err(Error::::ReceptionConfirmation)?; if let Some(confirmed_messages) = confirmed_messages { // emit 'delivered' event @@ -563,7 +563,7 @@ pub mod pallet { /// The message someone is trying to work with (i.e. increase fee) is not yet sent. MessageIsNotYetSent, /// Error confirming messages receival. - ReceivalConfirmation(ReceivalConfirmationError), + ReceptionConfirmation(ReceptionConfirmationError), /// Error generated by the `OwnedBridgeModule` trait. BridgeModule(bp_runtime::OwnedBridgeModuleError), } @@ -923,7 +923,7 @@ mod tests { PAYLOAD_REJECTED_BY_TARGET_CHAIN, REGULAR_PAYLOAD, TEST_LANE_ID, TEST_LANE_ID_2, TEST_LANE_ID_3, TEST_RELAYER_A, TEST_RELAYER_B, }, - outbound_lane::ReceivalConfirmationError, + outbound_lane::ReceptionConfirmationError, }; use bp_messages::{ source_chain::MessagesBridge, BridgeMessagesCall, UnrewardedRelayer, @@ -950,11 +950,11 @@ mod tests { let outbound_lane = outbound_lane::(lane_id); let message_nonce = outbound_lane.data().latest_generated_nonce + 1; - let prev_enqueud_messages = outbound_lane.data().queued_messages().saturating_len(); + let prev_enqueued_messages = outbound_lane.data().queued_messages().saturating_len(); let valid_message = Pallet::::validate_message(lane_id, ®ULAR_PAYLOAD) .expect("validate_message has failed"); let artifacts = Pallet::::send_message(valid_message); - assert_eq!(artifacts.enqueued_messages, prev_enqueud_messages + 1); + assert_eq!(artifacts.enqueued_messages, prev_enqueued_messages + 1); // check event with assigned nonce assert_eq!( @@ -1541,7 +1541,7 @@ mod tests { } #[test] - fn actual_dispatch_weight_does_not_overlow() { + fn actual_dispatch_weight_does_not_overflow() { run_test(|| { let message1 = message(1, message_payload(0, u64::MAX / 2)); let message2 = message(2, message_payload(0, u64::MAX / 2)); @@ -1775,7 +1775,7 @@ mod tests { // returns `last_confirmed_nonce`; // 3) it means that we're going to confirm delivery of messages 1..=1; // 4) so the number of declared messages (see `UnrewardedRelayersState`) is `0` and - // numer of actually confirmed messages is `1`. + // number of actually confirmed messages is `1`. assert_noop!( Pallet::::receive_messages_delivery_proof( RuntimeOrigin::signed(1), @@ -1785,8 +1785,8 @@ mod tests { ))), UnrewardedRelayersState { last_delivered_nonce: 1, ..Default::default() }, ), - Error::::ReceivalConfirmation( - ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected + Error::::ReceptionConfirmation( + ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected ), ); }); diff --git a/modules/messages/src/outbound_lane.rs b/modules/messages/src/outbound_lane.rs index 431c2cfb7eef3..acef5546d2a64 100644 --- a/modules/messages/src/outbound_lane.rs +++ b/modules/messages/src/outbound_lane.rs @@ -53,7 +53,7 @@ pub type StoredMessagePayload = BoundedVec>::MaximalOu /// Result of messages receival confirmation. #[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)] -pub enum ReceivalConfirmationError { +pub enum ReceptionConfirmationError { /// Bridged chain is trying to confirm more messages than we have generated. May be a result /// of invalid bridged chain storage. FailedToConfirmFutureMessages, @@ -103,7 +103,7 @@ impl OutboundLane { max_allowed_messages: MessageNonce, latest_delivered_nonce: MessageNonce, relayers: &VecDeque>, - ) -> Result, ReceivalConfirmationError> { + ) -> Result, ReceptionConfirmationError> { let mut data = self.storage.data(); let confirmed_messages = DeliveredMessages { begin: data.latest_received_nonce.saturating_add(1), @@ -113,7 +113,7 @@ impl OutboundLane { return Ok(None) } if confirmed_messages.end > data.latest_generated_nonce { - return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages) + return Err(ReceptionConfirmationError::FailedToConfirmFutureMessages) } if confirmed_messages.total_messages() > max_allowed_messages { // that the relayer has declared correct number of messages that the proof contains (it @@ -127,7 +127,7 @@ impl OutboundLane { confirmed_messages.total_messages(), max_allowed_messages, ); - return Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected) + return Err(ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected) } ensure_unrewarded_relayers_are_correct(confirmed_messages.end, relayers)?; @@ -176,24 +176,24 @@ impl OutboundLane { fn ensure_unrewarded_relayers_are_correct( latest_received_nonce: MessageNonce, relayers: &VecDeque>, -) -> Result<(), ReceivalConfirmationError> { +) -> Result<(), ReceptionConfirmationError> { let mut expected_entry_begin = relayers.front().map(|entry| entry.messages.begin); for entry in relayers { // unrewarded relayer entry must have at least 1 unconfirmed message // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end < entry.messages.begin { - return Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry) + return Err(ReceptionConfirmationError::EmptyUnrewardedRelayerEntry) } // every entry must confirm range of messages that follows previous entry range // (guaranteed by the `InboundLane::receive_message()`) if expected_entry_begin != Some(entry.messages.begin) { - return Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries) + return Err(ReceptionConfirmationError::NonConsecutiveUnrewardedRelayerEntries) } expected_entry_begin = entry.messages.end.checked_add(1); // entry can't confirm messages larger than `inbound_lane_data.latest_received_nonce()` // (guaranteed by the `InboundLane::receive_message()`) if entry.messages.end > latest_received_nonce { - return Err(ReceivalConfirmationError::FailedToConfirmFutureMessages) + return Err(ReceptionConfirmationError::FailedToConfirmFutureMessages) } } @@ -228,7 +228,7 @@ mod tests { fn assert_3_messages_confirmation_fails( latest_received_nonce: MessageNonce, relayers: &VecDeque>, - ) -> Result, ReceivalConfirmationError> { + ) -> Result, ReceptionConfirmationError> { run_test(|| { let mut lane = outbound_lane::(TEST_LANE_ID); lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); @@ -299,7 +299,7 @@ mod tests { fn confirm_delivery_rejects_nonce_larger_than_last_generated() { assert_eq!( assert_3_messages_confirmation_fails(10, &unrewarded_relayers(1..=10),), - Err(ReceivalConfirmationError::FailedToConfirmFutureMessages), + Err(ReceptionConfirmationError::FailedToConfirmFutureMessages), ); } @@ -314,7 +314,7 @@ mod tests { .chain(unrewarded_relayers(3..=3).into_iter()) .collect(), ), - Err(ReceivalConfirmationError::FailedToConfirmFutureMessages), + Err(ReceptionConfirmationError::FailedToConfirmFutureMessages), ); } @@ -330,7 +330,7 @@ mod tests { .chain(unrewarded_relayers(2..=3).into_iter()) .collect(), ), - Err(ReceivalConfirmationError::EmptyUnrewardedRelayerEntry), + Err(ReceptionConfirmationError::EmptyUnrewardedRelayerEntry), ); } @@ -345,7 +345,7 @@ mod tests { .chain(unrewarded_relayers(2..=2).into_iter()) .collect(), ), - Err(ReceivalConfirmationError::NonConsecutiveUnrewardedRelayerEntries), + Err(ReceptionConfirmationError::NonConsecutiveUnrewardedRelayerEntries), ); } @@ -409,11 +409,11 @@ mod tests { lane.send_message(outbound_message_data(REGULAR_PAYLOAD)); assert_eq!( lane.confirm_delivery(0, 3, &unrewarded_relayers(1..=3)), - Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), + Err(ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected), ); assert_eq!( lane.confirm_delivery(2, 3, &unrewarded_relayers(1..=3)), - Err(ReceivalConfirmationError::TryingToConfirmMoreMessagesThanExpected), + Err(ReceptionConfirmationError::TryingToConfirmMoreMessagesThanExpected), ); assert_eq!( lane.confirm_delivery(3, 3, &unrewarded_relayers(1..=3)), diff --git a/modules/parachains/src/mock.rs b/modules/parachains/src/mock.rs index 3af3fd3e76398..d9cbabf850ec9 100644 --- a/modules/parachains/src/mock.rs +++ b/modules/parachains/src/mock.rs @@ -261,7 +261,7 @@ impl Chain for TestBridgedChain { impl ChainWithGrandpa for TestBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } @@ -294,7 +294,7 @@ impl Chain for OtherBridgedChain { impl ChainWithGrandpa for OtherBridgedChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ""; const MAX_AUTHORITIES_COUNT: u32 = 16; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 8; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 8; const MAX_MANDATORY_HEADER_SIZE: u32 = 256; const AVERAGE_HEADER_SIZE: u32 = 64; } diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/modules/xcm-bridge-hub-router/src/lib.rs index f219be78f9e1b..5d0be41b1b558 100644 --- a/modules/xcm-bridge-hub-router/src/lib.rs +++ b/modules/xcm-bridge-hub-router/src/lib.rs @@ -427,7 +427,7 @@ mod tests { run_test(|| { Bridge::::put(uncongested_bridge(FixedU128::from_rational(125, 100))); - // it shold eventually decreased to one + // it should eventually decreased to one while XcmBridgeHubRouter::bridge().delivery_fee_factor > MINIMAL_DELIVERY_FEE_FACTOR { XcmBridgeHubRouter::on_initialize(One::one()); } diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 4d5d012345a4c..1200af48345b5 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-xcm-bridge-hub" -description = "Module that adds dynamic bridges/lanes support to XCM infrastucture at the bridge hub." +description = "Module that adds dynamic bridges/lanes support to XCM infrastructure at the bridge hub." version = "0.2.0" authors.workspace = true edition.workspace = true diff --git a/primitives/header-chain/src/justification/mod.rs b/primitives/header-chain/src/justification/mod.rs index b32d8bdb5f1d8..d7c2cbf429e2b 100644 --- a/primitives/header-chain/src/justification/mod.rs +++ b/primitives/header-chain/src/justification/mod.rs @@ -83,7 +83,7 @@ impl GrandpaJustification { .saturating_add(HashOf::::max_encoded_len().saturated_into()); let max_expected_votes_ancestries_size = - C::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE); + C::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY.saturating_mul(C::AVERAGE_HEADER_SIZE); // justification is round number (u64=8b), a signed GRANDPA commit and the // `votes_ancestries` vector diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/primitives/header-chain/src/justification/verification/mod.rs index c71149bf9c28e..9df3511e1035e 100644 --- a/primitives/header-chain/src/justification/verification/mod.rs +++ b/primitives/header-chain/src/justification/verification/mod.rs @@ -318,7 +318,7 @@ trait JustificationVerifier { } // check that the cumulative weight of validators that voted for the justification target - // (or one of its descendents) is larger than the required threshold. + // (or one of its descendants) is larger than the required threshold. if cumulative_weight < threshold { return Err(Error::TooLowCumulativeWeight) } diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 84a6a881a835b..98fb9ff83d833 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -283,7 +283,7 @@ pub trait ChainWithGrandpa: Chain { /// ancestry and the pallet will accept such justification. The limit is only used to compute /// maximal refund amount and submitting justifications which exceed the limit, may be costly /// to submitter. - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32; /// Maximal size of the mandatory chain header. Mandatory header is the header that enacts new /// GRANDPA authorities set (so it has large digest inside). @@ -317,8 +317,8 @@ where const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = ::WITH_CHAIN_GRANDPA_PALLET_NAME; const MAX_AUTHORITIES_COUNT: u32 = ::MAX_AUTHORITIES_COUNT; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = - ::REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = + ::REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY; const MAX_MANDATORY_HEADER_SIZE: u32 = ::MAX_MANDATORY_HEADER_SIZE; const AVERAGE_HEADER_SIZE: u32 = ::AVERAGE_HEADER_SIZE; @@ -373,7 +373,7 @@ mod tests { impl ChainWithGrandpa for TestChain { const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = "Test"; const MAX_AUTHORITIES_COUNT: u32 = 128; - const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; + const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 2; const MAX_MANDATORY_HEADER_SIZE: u32 = 100_000; const AVERAGE_HEADER_SIZE: u32 = 1_024; } diff --git a/primitives/messages/src/lib.rs b/primitives/messages/src/lib.rs index 51b3f25f71518..c3f79b3ee388c 100644 --- a/primitives/messages/src/lib.rs +++ b/primitives/messages/src/lib.rs @@ -289,27 +289,27 @@ pub struct ReceivedMessages { /// Id of the lane which is receiving messages. pub lane: LaneId, /// Result of messages which we tried to dispatch - pub receive_results: Vec<(MessageNonce, ReceivalResult)>, + pub receive_results: Vec<(MessageNonce, ReceptionResult)>, } impl ReceivedMessages { /// Creates new `ReceivedMessages` structure from given results. pub fn new( lane: LaneId, - receive_results: Vec<(MessageNonce, ReceivalResult)>, + receive_results: Vec<(MessageNonce, ReceptionResult)>, ) -> Self { ReceivedMessages { lane, receive_results } } /// Push `result` of the `message` delivery onto `receive_results` vector. - pub fn push(&mut self, message: MessageNonce, result: ReceivalResult) { + pub fn push(&mut self, message: MessageNonce, result: ReceptionResult) { self.receive_results.push((message, result)); } } /// Result of single message receival. #[derive(RuntimeDebug, Encode, Decode, PartialEq, Eq, Clone, TypeInfo)] -pub enum ReceivalResult { +pub enum ReceptionResult { /// Message has been received and dispatched. Note that we don't care whether dispatch has /// been successful or not - in both case message falls into this category. /// diff --git a/primitives/polkadot-core/src/lib.rs b/primitives/polkadot-core/src/lib.rs index df2836495bbe1..e83be59b23890 100644 --- a/primitives/polkadot-core/src/lib.rs +++ b/primitives/polkadot-core/src/lib.rs @@ -71,7 +71,7 @@ pub const MAX_AUTHORITIES_COUNT: u32 = 1_256; /// justifications with any additional headers in votes ancestry, so reasonable headers may /// be set to zero. But we assume that there may be small GRANDPA lags, so we're leaving some /// reserve here. -pub const REASONABLE_HEADERS_IN_JUSTIFICATON_ANCESTRY: u32 = 2; +pub const REASONABLE_HEADERS_IN_JUSTIFICATION_ANCESTRY: u32 = 2; /// Average header size in `votes_ancestries` field of justification on Polkadot-like /// chains. diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 9ba21a1cddf13..4ec5a001a99ec 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -104,7 +104,7 @@ pub trait Chain: Send + Sync + 'static { const ID: ChainId; /// 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` + // Constraints 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 // @@ -125,7 +125,7 @@ pub trait Chain: Send + Sync + 'static { + MaxEncodedLen; /// 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` + // Constraints 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 @@ -143,7 +143,7 @@ pub trait Chain: Send + Sync + 'static { /// 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` + // Constraints 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; diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 850318923dc76..c9c5c9412913b 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -56,7 +56,7 @@ mod chain; mod storage_proof; mod storage_types; -// Re-export macro to aviod include paste dependency everywhere +// Re-export macro to avoid include paste dependency everywhere pub use sp_runtime::paste; /// Use this when something must be shared among all instances. @@ -461,7 +461,7 @@ macro_rules! generate_static_str_provider { }; } -/// Error message that is only dispayable in `std` environment. +/// Error message that is only displayable in `std` environment. #[derive(Encode, Decode, Clone, Eq, PartialEq, PalletError, TypeInfo)] #[scale_info(skip_type_params(T))] pub struct StrippableError { diff --git a/primitives/test-utils/src/lib.rs b/primitives/test-utils/src/lib.rs index 1d80890779bf8..f4fe4a242e79c 100644 --- a/primitives/test-utils/src/lib.rs +++ b/primitives/test-utils/src/lib.rs @@ -88,7 +88,7 @@ pub fn make_default_justification(header: &H) -> GrandpaJustificatio /// Generate justifications in a way where we are able to tune the number of pre-commits /// and vote ancestries which are included in the justification. /// -/// This is useful for benchmarkings where we want to generate valid justifications with +/// This is useful for benchmarks where we want to generate valid justifications with /// a specific number of pre-commits (tuned with the number of "authorities") and/or a specific /// number of vote ancestries (tuned with the "votes" parameter). /// diff --git a/testing/environments/rococo-westend/rococo.zndsl b/testing/environments/rococo-westend/rococo.zndsl index 5b49c7c632fa4..a75286445a240 100644 --- a/testing/environments/rococo-westend/rococo.zndsl +++ b/testing/environments/rococo-westend/rococo.zndsl @@ -1,7 +1,7 @@ -Description: Check if the with-Westend GRANPDA pallet was initialized at Rococo BH +Description: Check if the with-Westend GRANDPA pallet was initialized at Rococo BH Network: ./bridge_hub_rococo_local_network.toml Creds: config -# relay is already started - let's wait until with-Westend GRANPDA pallet is initialized at Rococo +# relay is already started - let's wait until with-Westend GRANDPA pallet is initialized at Rococo bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds diff --git a/testing/environments/rococo-westend/westend.zndsl b/testing/environments/rococo-westend/westend.zndsl index 07968838852f7..21d4ebf3b05b0 100644 --- a/testing/environments/rococo-westend/westend.zndsl +++ b/testing/environments/rococo-westend/westend.zndsl @@ -1,6 +1,6 @@ -Description: Check if the with-Rococo GRANPDA pallet was initialized at Westend BH +Description: Check if the with-Rococo GRANDPA pallet was initialized at Westend BH Network: ./bridge_hub_westend_local_network.toml Creds: config -# relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Westend +# relay is already started - let's wait until with-Rococo GRANDPA pallet is initialized at Westend bridge-hub-westend-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds diff --git a/testing/framework/utils/generate_hex_encoded_call/index.js b/testing/framework/utils/generate_hex_encoded_call/index.js index 30f89d754ceb7..c8e361b25a9ce 100644 --- a/testing/framework/utils/generate_hex_encoded_call/index.js +++ b/testing/framework/utils/generate_hex_encoded_call/index.js @@ -126,36 +126,36 @@ if (!process.argv[2] || !process.argv[3]) { } const type = process.argv[2]; -const rpcEnpoint = process.argv[3]; +const rpcEndpoint = process.argv[3]; const output = process.argv[4]; const inputArgs = process.argv.slice(5, process.argv.length); console.log(`Generating hex-encoded call data for:`); console.log(` type: ${type}`); -console.log(` rpcEnpoint: ${rpcEnpoint}`); +console.log(` rpcEndpoint: ${rpcEndpoint}`); console.log(` output: ${output}`); console.log(` inputArgs: ${inputArgs}`); switch (type) { case 'remark-with-event': - remarkWithEvent(rpcEnpoint, output); + remarkWithEvent(rpcEndpoint, output); break; case 'add-exporter-config': - addExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + addExporterConfig(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'remove-exporter-config': - removeExporterConfig(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + removeExporterConfig(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'add-universal-alias': - addUniversalAlias(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + addUniversalAlias(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'add-reserve-location': - addReserveLocation(rpcEnpoint, output, inputArgs[0]); + addReserveLocation(rpcEndpoint, output, inputArgs[0]); break; case 'force-create-asset': - forceCreateAsset(rpcEnpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]); + forceCreateAsset(rpcEndpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]); break; case 'force-xcm-version': - forceXcmVersion(rpcEnpoint, output, inputArgs[0], inputArgs[1]); + forceXcmVersion(rpcEndpoint, output, inputArgs[0], inputArgs[1]); break; case 'check': console.log(`Checking nodejs installation, if you see this everything is ready!`); diff --git a/testing/run-tests.sh b/testing/run-tests.sh index 6149d9912653c..fd12b57f53349 100755 --- a/testing/run-tests.sh +++ b/testing/run-tests.sh @@ -30,7 +30,7 @@ done export POLKADOT_SDK_PATH=`realpath $(dirname "$0")/../..` export BRIDGE_TESTS_FOLDER=$POLKADOT_SDK_PATH/bridges/testing/tests -# set pathc to binaries +# set path to binaries if [ "$ZOMBIENET_DOCKER_PATHS" -eq 1 ]; then export POLKADOT_BINARY=/usr/local/bin/polkadot export POLKADOT_PARACHAIN_BINARY=/usr/local/bin/polkadot-parachain diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh b/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh index 7d5b8d9273664..3a604b3876d96 100755 --- a/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh +++ b/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh @@ -24,7 +24,7 @@ echo -e "Sleeping 90s before starting relayer ...\n" sleep 90 ${BASH_SOURCE%/*}/../../environments/rococo-westend/start_relayer.sh $rococo_dir $westend_dir relayer_pid -# Sometimes the relayer syncs multiple parachain heads in the begining leading to test failures. +# Sometimes the relayer syncs multiple parachain heads in the beginning leading to test failures. # See issue: https://github.com/paritytech/parity-bridges-common/issues/2838. # TODO: Remove this sleep after the issue is fixed. echo -e "Sleeping 180s before runing the tests ...\n" From 36d567f6267a9ff17b948176d15bbeec13bf341e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 27 Mar 2024 13:25:37 +0100 Subject: [PATCH 1203/1210] Leftover (#2900) --- relays/lib-substrate-relay/Cargo.toml | 1 - relays/lib-substrate-relay/src/on_demand/headers.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 99ff91a750619..c064f11b22eb9 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -56,6 +56,5 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/polkadot-sdk", bra sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } [dev-dependencies] -bp-rococo = { path = "../../chains/chain-rococo" } pallet-transaction-payment = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/relays/lib-substrate-relay/src/on_demand/headers.rs index 99ca1d4d5a726..e8a2a3c6c58aa 100644 --- a/relays/lib-substrate-relay/src/on_demand/headers.rs +++ b/relays/lib-substrate-relay/src/on_demand/headers.rs @@ -528,8 +528,8 @@ mod tests { use super::*; use relay_substrate_client::test_chain::TestChain; - const AT_SOURCE: Option = Some(10); - const AT_TARGET: Option = Some(1); + const AT_SOURCE: Option> = Some(10); + const AT_TARGET: Option> = Some(1); #[async_std::test] async fn mandatory_headers_scan_range_selects_range_if_some_headers_are_missing() { From 2c142d9d29f7fd3ecdb104c9303e75100b357e6f Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 27 Mar 2024 17:05:13 +0100 Subject: [PATCH 1204/1210] Fix polkadot-sdk CI failures (#2901) * taplo * markdown * publish = false * feature propagation --- modules/beefy/Cargo.toml | 13 ++++++++++--- primitives/beefy/Cargo.toml | 6 ++++-- relays/client-substrate/Cargo.toml | 1 + relays/equivocation/Cargo.toml | 1 + relays/finality/Cargo.toml | 1 + relays/finality/README.md | 22 ++++++++++++---------- relays/lib-substrate-relay/Cargo.toml | 1 + relays/messages/Cargo.toml | 1 + relays/parachains/Cargo.toml | 1 + relays/parachains/README.md | 13 +++++++------ relays/utils/Cargo.toml | 1 + 11 files changed, 40 insertions(+), 21 deletions(-) diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 4ead33c44314f..53c8006f878ac 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -5,6 +5,7 @@ description = "Module implementing BEEFY on-chain light client used for bridging authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true @@ -38,7 +39,7 @@ sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" bp-test-utils = { path = "../../primitives/test-utils" } [features] -default = [ "std" ] +default = ["std"] std = [ "bp-beefy/std", "bp-runtime/std", @@ -47,9 +48,15 @@ std = [ "frame-system/std", "log/std", "scale-info/std", - "serde", + "serde/std", "sp-core/std", "sp-runtime/std", "sp-std/std", ] -try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime" ] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-beefy-mmr/try-runtime", + "pallet-mmr/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index b6bb2698689b6..0a282090f7f2e 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -5,12 +5,13 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive", "bit-vec"] } +codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } serde = { default-features = false, features = ["alloc", "derive"], workspace = true } @@ -29,8 +30,9 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "mas sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ + "binary-merkle-tree/std", "bp-runtime/std", "codec/std", "frame-support/std", diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 9240af7b59c5b..3049d8350b706 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 6f65d40fcbe7a..3b99e4349e037 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Equivocation detector" +publish = false [lints] workspace = true diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 8cf3d409cfe98..53d2ce579f6be 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" +publish = false [lints] workspace = true diff --git a/relays/finality/README.md b/relays/finality/README.md index 0a8d6a4c8b128..92e765cea0e50 100644 --- a/relays/finality/README.md +++ b/relays/finality/README.md @@ -3,7 +3,7 @@ The finality relay is able to work with different finality engines. In the modern Substrate world they are GRANDPA and BEEFY. Let's talk about GRANDPA here, because BEEFY relay and bridge BEEFY pallet are in development. -In general, the relay works as follows: it connects to the source and target chain. The source chain must have the +In general, the relay works as follows: it connects to the source and target chain. The source chain must have the [GRANDPA gadget](https://github.com/paritytech/finality-grandpa) running (so it can't be a parachain). The target chain must have the [bridge GRANDPA pallet](../../modules/grandpa/) deployed at its runtime. The relay subscribes to the GRANDPA finality notifications at the source chain and when the new justification is received, it is submitted @@ -41,18 +41,20 @@ Finality relay provides several metrics. Metrics names depend on names of source shows metrics names for Rococo (source chain) to BridgeHubWestend (target chain) finality relay. For other chains, simply change chain names. So the metrics are: -- `Rococo_to_BridgeHubWestend_Sync_best_source_block_number` - returns best finalized source chain (Rococo) block number, known - to the relay. If relay is running in [on-demand mode](../bin-substrate/src/cli/relay_headers_and_messages/), the +- `Rococo_to_BridgeHubWestend_Sync_best_source_block_number` - returns best finalized source chain (Rococo) block + number, known to the relay. + If relay is running in [on-demand mode](../bin-substrate/src/cli/relay_headers_and_messages/), the number may not match (it may be far behind) the actual best finalized number; -- `Rococo_to_BridgeHubWestend_Sync_best_source_at_target_block_number` - returns best finalized source chain (Rococo) block - number that is known to the bridge GRANDPA pallet at the target chain. +- `Rococo_to_BridgeHubWestend_Sync_best_source_at_target_block_number` - returns best finalized source chain (Rococo) + block number that is known to the bridge GRANDPA pallet at the target chain. -- `Rococo_to_BridgeHubWestend_Sync_is_source_and_source_at_target_using_different_forks` - if this metrics is set to `1`, then - the best source chain header, known to the target chain doesn't match the same-number-header at the source chain. - It means that the GRANDPA validators set has crafted the duplicate justification and it has been submitted to the - target chain. Normally (if majority of validators are honest and if you're running finality relay without large - breaks) this shall not happen and the metric will have `0` value. +- `Rococo_to_BridgeHubWestend_Sync_is_source_and_source_at_target_using_different_forks` - if this metrics is set + to `1`, then the best source chain header known to the target chain doesn't match the same-number-header + at the source chain. It means that the GRANDPA validators set has crafted the duplicate justification + and it has been submitted to the target chain. + Normally (if majority of validators are honest and if you're running finality relay without large breaks) + this shall not happen and the metric will have `0` value. If relay operates properly, you should see that the `Rococo_to_BridgeHubWestend_Sync_best_source_at_target_block_number` tries to reach the `Rococo_to_BridgeHubWestend_Sync_best_source_block_number`. And the latter one always increases. diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index c064f11b22eb9..76be5a92a794a 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index 1233c8af741a5..b3f0a9fd19185 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index 05a995b8514a4..f37e636a9c598 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true diff --git a/relays/parachains/README.md b/relays/parachains/README.md index bacd28594d807..9043b0b0a9cdd 100644 --- a/relays/parachains/README.md +++ b/relays/parachains/README.md @@ -1,7 +1,7 @@ # Parachains Finality Relay The parachains finality relay works with two chains - source relay chain and target chain (which may be standalone -chain, relay chain or a parachain). The source chain must have the +chain, relay chain or a parachain). The source chain must have the [`paras` pallet](https://github.com/paritytech/polkadot/tree/master/runtime/parachains/src/paras) deployed at its runtime. The target chain must have the [bridge parachains pallet](../../modules/parachains/) deployed at its runtime. @@ -39,11 +39,12 @@ Rococo (source relay chain) to BridgeHubWestend (target chain) parachains finali change chain names. So the metrics are: - `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_source` - returns best known parachain block - number, registered in the `paras` pallet at the source relay chain (Rococo in our example); + number, registered in the `paras` pallet at the source relay chain (Rococo in our example); - `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_target` - returns best known parachain block - number, registered in the bridge parachains pallet at the target chain (BridgeHubWestend in our example). + number, registered in the bridge parachains pallet at the target chain (BridgeHubWestend in our example). -If relay operates properly, you should see that the `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_target` -tries to reach the `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_source`. And the latter one -always increases. +If relay operates properly, you should see that +the `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_target` tries to reach +the `Rococo_to_BridgeHubWestend_Parachains_best_parachain_block_number_at_source`. +And the latter one always increases. diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index d1eeba2b8fd11..bc894b34e471e 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +publish = false [lints] workspace = true From 2dce2ae52787ab2855427b81afb445ea7e11782c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:30:42 +0000 Subject: [PATCH 1205/1210] Bump scale-info from 2.11.0 to 2.11.1 Bumps [scale-info](https://github.com/paritytech/scale-info) from 2.11.0 to 2.11.1. - [Release notes](https://github.com/paritytech/scale-info/releases) - [Changelog](https://github.com/paritytech/scale-info/blob/master/CHANGELOG.md) - [Commits](https://github.com/paritytech/scale-info/compare/v2.11.0...v2.11.1) --- updated-dependencies: - dependency-name: scale-info dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bin/runtime-common/Cargo.toml | 2 +- chains/chain-asset-hub-rococo/Cargo.toml | 2 +- chains/chain-asset-hub-westend/Cargo.toml | 2 +- chains/chain-polkadot-bulletin/Cargo.toml | 2 +- modules/beefy/Cargo.toml | 2 +- modules/grandpa/Cargo.toml | 2 +- modules/messages/Cargo.toml | 2 +- modules/parachains/Cargo.toml | 2 +- modules/relayers/Cargo.toml | 2 +- modules/xcm-bridge-hub-router/Cargo.toml | 2 +- modules/xcm-bridge-hub/Cargo.toml | 2 +- primitives/beefy/Cargo.toml | 2 +- primitives/header-chain/Cargo.toml | 2 +- primitives/messages/Cargo.toml | 2 +- primitives/parachains/Cargo.toml | 2 +- primitives/polkadot-core/Cargo.toml | 2 +- primitives/relayers/Cargo.toml | 2 +- primitives/runtime/Cargo.toml | 2 +- primitives/xcm-bridge-hub-router/Cargo.toml | 2 +- relays/client-substrate/Cargo.toml | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index e3c05d1bebbce..d71e9f6bae710 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -14,7 +14,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } static_assertions = { version = "1.1", optional = true } # Bridge dependencies diff --git a/chains/chain-asset-hub-rococo/Cargo.toml b/chains/chain-asset-hub-rococo/Cargo.toml index 336e2b4d4022f..ae1f05e0e7f53 100644 --- a/chains/chain-asset-hub-rococo/Cargo.toml +++ b/chains/chain-asset-hub-rococo/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/chains/chain-asset-hub-westend/Cargo.toml b/chains/chain-asset-hub-westend/Cargo.toml index 99b6c26e2638b..14c049f134dfd 100644 --- a/chains/chain-asset-hub-westend/Cargo.toml +++ b/chains/chain-asset-hub-westend/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate Dependencies frame-support = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/chains/chain-polkadot-bulletin/Cargo.toml b/chains/chain-polkadot-bulletin/Cargo.toml index 1e2bbaf6b8af0..121f0c57c34a9 100644 --- a/chains/chain-polkadot-bulletin/Cargo.toml +++ b/chains/chain-polkadot-bulletin/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index 53c8006f878ac..ab3447f657c5c 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true } # Bridge Dependencies diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index eb7ad6a2772fa..2388767f972ca 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -15,7 +15,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index 55b48cc03ce32..ebe7db4085a72 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -13,7 +13,7 @@ workspace = true codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 2b8445b794b13..068e9a907fe26 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 972b4c33ab474..9073b9bbe082e 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 926b704bd8530..89c02f706c270 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive", "serde"] } +scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive", "serde"] } # Bridge dependencies diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 1200af48345b5..8654c65f66c1d 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } log = { workspace = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge Dependencies bp-messages = { path = "../../primitives/messages", default-features = false } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index 0a282090f7f2e..eef3dcf96e860 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } serde = { default-features = false, features = ["alloc", "derive"], workspace = true } # Bridge Dependencies diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 6e9178f3c492c..8dc9a8ae776da 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 282ef93d38c53..93b0efa276569 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Bridge dependencies diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 3e148d5289d10..610b7b3361358 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge dependencies diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 4851ce14c0dad..6c20d64da3fb2 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -12,7 +12,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } # Bridge Dependencies diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 3ee433974d602..441d240600356 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index b6ed0bc06d172..c2b2a794b3e65 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -15,7 +15,7 @@ hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" log = { workspace = true } num-traits = { version = "0.2", default-features = false } -scale-info = { version = "2.11.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } # Substrate Dependencies diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index c7bae8443f1fd..bc0ff5c605e89 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } -scale-info = { version = "2.11.0", default-features = false, features = ["bit-vec", "derive"] } +scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 3049d8350b706..8c02c82b5f210 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -18,7 +18,7 @@ jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } log = { workspace = true } num-traits = "0.2" rand = "0.8" -scale-info = { version = "2.11.0", features = ["derive"] } +scale-info = { version = "2.11.1", features = ["derive"] } tokio = { version = "1.36", features = ["rt-multi-thread"] } thiserror = { workspace = true } From 2f63b6282cddf5f33998fb8483a7d70644fbcfd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 07:31:36 +0000 Subject: [PATCH 1206/1210] Bump tokio from 1.36.0 to 1.37.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.36.0 to 1.37.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.36.0...tokio-1.37.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- relays/client-substrate/Cargo.toml | 2 +- relays/utils/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 8c02c82b5f210..51e3edefaf979 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -19,7 +19,7 @@ log = { workspace = true } num-traits = "0.2" rand = "0.8" scale-info = { version = "2.11.1", features = ["derive"] } -tokio = { version = "1.36", features = ["rt-multi-thread"] } +tokio = { version = "1.37", features = ["rt-multi-thread"] } thiserror = { workspace = true } # Bridge dependencies diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index bc894b34e471e..13fda477351b9 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -24,7 +24,7 @@ num-traits = "0.2" serde_json = { workspace = true, default-features = true } sysinfo = "0.30" time = { version = "0.3", features = ["formatting", "local-offset", "std"] } -tokio = { version = "1.36", features = ["rt"] } +tokio = { version = "1.37", features = ["rt"] } thiserror = { workspace = true } # Bridge dependencies From 2c70b46f93561269581f74fbdb516dc903db79ea Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 1 Apr 2024 12:30:39 +0300 Subject: [PATCH 1207/1210] Some relayer improvments (#2902) * added CLI arguments: full WS URI + separate for WS path URI component + additional log * URI -> URL? * added TODO * fmt --- relays/client-substrate/src/client.rs | 22 ++++++++++++++----- relays/client-substrate/src/lib.rs | 7 ++++++ .../src/cli/chain_schema.rs | 15 +++++++++++-- .../src/cli/relay_headers_and_messages/mod.rs | 8 +++++++ .../src/parachains/source.rs | 7 ++++++ 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/relays/client-substrate/src/client.rs b/relays/client-substrate/src/client.rs index 676fea487b35b..afbda8599b2aa 100644 --- a/relays/client-substrate/src/client.rs +++ b/relays/client-substrate/src/client.rs @@ -264,12 +264,22 @@ impl Client { params: &ConnectionParams, ) -> Result<(Arc, Arc)> { let tokio = tokio::runtime::Runtime::new()?; - let uri = format!( - "{}://{}:{}", - if params.secure { "wss" } else { "ws" }, - params.host, - params.port, - ); + + let uri = match params.uri { + Some(ref uri) => uri.clone(), + None => { + format!( + "{}://{}:{}{}", + if params.secure { "wss" } else { "ws" }, + params.host, + params.port, + match params.path { + Some(ref path) => format!("/{}", path), + None => String::new(), + }, + ) + }, + }; log::info!(target: "bridge", "Connecting to {} node at {}", C::NAME, uri); let client = tokio diff --git a/relays/client-substrate/src/lib.rs b/relays/client-substrate/src/lib.rs index 6c62b8e1cd548..d5b8d4dcced2d 100644 --- a/relays/client-substrate/src/lib.rs +++ b/relays/client-substrate/src/lib.rs @@ -57,10 +57,15 @@ pub use bp_runtime::{ /// Substrate-over-websocket connection params. #[derive(Debug, Clone)] pub struct ConnectionParams { + /// Websocket endpoint URL. Overrides all other URL components (`host`, `port`, `path` and + /// `secure`). + pub uri: Option, /// Websocket server host name. pub host: String, /// Websocket server TCP port. pub port: u16, + /// Websocket endpoint path at server. + pub path: Option, /// Use secure websocket connection. pub secure: bool, /// Defined chain runtime version @@ -70,8 +75,10 @@ pub struct ConnectionParams { impl Default for ConnectionParams { fn default() -> Self { ConnectionParams { + uri: None, host: "localhost".into(), port: 9944, + path: None, secure: false, chain_runtime_version: ChainRuntimeVersion::Auto, } diff --git a/relays/lib-substrate-relay/src/cli/chain_schema.rs b/relays/lib-substrate-relay/src/cli/chain_schema.rs index c5b802173ad94..6246bdbf01515 100644 --- a/relays/lib-substrate-relay/src/cli/chain_schema.rs +++ b/relays/lib-substrate-relay/src/cli/chain_schema.rs @@ -92,15 +92,24 @@ macro_rules! declare_chain_runtime_version_params_cli_schema { macro_rules! declare_chain_connection_params_cli_schema { ($chain:ident, $chain_prefix:ident) => { bp_runtime::paste::item! { + // TODO: https://github.com/paritytech/parity-bridges-common/issues/2909 + // remove all obsolete arguments (separate URI components) + #[doc = $chain " connection params."] #[derive(StructOpt, Debug, PartialEq, Eq, Clone)] pub struct [<$chain ConnectionParams>] { - #[doc = "Connect to " $chain " node at given host."] + #[doc = "WS endpoint of " $chain ": full URI. Overrides all other connection string components (host, port, path, secure)."] + #[structopt(long)] + pub [<$chain_prefix _uri>]: Option, + #[doc = "WS endpoint of " $chain ": host component."] #[structopt(long, default_value = "127.0.0.1")] pub [<$chain_prefix _host>]: String, - #[doc = "Connect to " $chain " node websocket server at given port."] + #[doc = "WS endpoint of " $chain ": port component."] #[structopt(long, default_value = "9944")] pub [<$chain_prefix _port>]: u16, + #[doc = "WS endpoint of " $chain ": path component."] + #[structopt(long)] + pub [<$chain_prefix _path>]: Option, #[doc = "Use secure websocket connection."] #[structopt(long)] pub [<$chain_prefix _secure>]: bool, @@ -119,8 +128,10 @@ macro_rules! declare_chain_connection_params_cli_schema { .[<$chain_prefix _runtime_version>] .into_runtime_version(Chain::RUNTIME_VERSION)?; Ok(relay_substrate_client::Client::new(relay_substrate_client::ConnectionParams { + uri: self.[<$chain_prefix _uri>], host: self.[<$chain_prefix _host>], port: self.[<$chain_prefix _port>], + path: self.[<$chain_prefix _path>], secure: self.[<$chain_prefix _secure>], chain_runtime_version, }) diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs index d404f714b5878..27e9f1c21ba0d 100644 --- a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs +++ b/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs @@ -425,8 +425,10 @@ mod tests { }, }, left: BridgeHubKusamaConnectionParams { + bridge_hub_kusama_uri: None, bridge_hub_kusama_host: "bridge-hub-kusama-node-collator1".into(), bridge_hub_kusama_port: 9944, + bridge_hub_kusama_path: None, bridge_hub_kusama_secure: false, bridge_hub_kusama_runtime_version: BridgeHubKusamaRuntimeVersionParams { bridge_hub_kusama_version_mode: RuntimeVersionType::Bundle, @@ -442,8 +444,10 @@ mod tests { bridge_hub_kusama_transactions_mortality: Some(64), }, left_relay: KusamaConnectionParams { + kusama_uri: None, kusama_host: "kusama-alice".into(), kusama_port: 9944, + kusama_path: None, kusama_secure: false, kusama_runtime_version: KusamaRuntimeVersionParams { kusama_version_mode: RuntimeVersionType::Bundle, @@ -452,8 +456,10 @@ mod tests { }, }, right: BridgeHubPolkadotConnectionParams { + bridge_hub_polkadot_uri: None, bridge_hub_polkadot_host: "bridge-hub-polkadot-collator1".into(), bridge_hub_polkadot_port: 9944, + bridge_hub_polkadot_path: None, bridge_hub_polkadot_secure: false, bridge_hub_polkadot_runtime_version: BridgeHubPolkadotRuntimeVersionParams { bridge_hub_polkadot_version_mode: RuntimeVersionType::Bundle, @@ -469,8 +475,10 @@ mod tests { bridge_hub_polkadot_transactions_mortality: Some(64), }, right_relay: PolkadotConnectionParams { + polkadot_uri: None, polkadot_host: "polkadot-alice".into(), polkadot_port: 9944, + polkadot_path: None, polkadot_secure: false, polkadot_runtime_version: PolkadotRuntimeVersionParams { polkadot_version_mode: RuntimeVersionType::Bundle, diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/relays/lib-substrate-relay/src/parachains/source.rs index 32d70cf425f0b..4cc512b9d9b45 100644 --- a/relays/lib-substrate-relay/src/parachains/source.rs +++ b/relays/lib-substrate-relay/src/parachains/source.rs @@ -106,6 +106,13 @@ where // parachain head - we simply return `Unavailable` let best_block_number = self.client.best_finalized_header_number().await?; if is_ancient_block(at_block.number(), best_block_number) { + log::trace!( + target: "bridge", + "{} block {:?} is ancient. Cannot prove the {} header there", + P::SourceRelayChain::NAME, + at_block, + P::SourceParachain::NAME, + ); return Ok(AvailableHeader::Unavailable) } From aecae6f1ae8cafa810c3922885dff368c7eceb0d Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 2 Apr 2024 00:00:56 +0300 Subject: [PATCH 1208/1210] Address migration comments (#2910) * Use workspace.[authors|edition] * Add repository.workspace = true * Upgrade dependencies to the polkadot-sdk versions * Upgrade async-std version * Update jsonrpsee version * cargo update * use ci-unified image --- README.md | 6 +++--- bin/runtime-common/Cargo.toml | 2 +- chains/chain-asset-hub-rococo/Cargo.toml | 3 ++- chains/chain-asset-hub-westend/Cargo.toml | 3 ++- chains/chain-bridge-hub-cumulus/Cargo.toml | 1 + chains/chain-bridge-hub-kusama/Cargo.toml | 1 + chains/chain-bridge-hub-polkadot/Cargo.toml | 1 + chains/chain-bridge-hub-rococo/Cargo.toml | 1 + chains/chain-bridge-hub-westend/Cargo.toml | 1 + chains/chain-kusama/Cargo.toml | 1 + chains/chain-polkadot-bulletin/Cargo.toml | 3 ++- chains/chain-polkadot/Cargo.toml | 1 + chains/chain-rococo/Cargo.toml | 1 + chains/chain-westend/Cargo.toml | 1 + modules/beefy/Cargo.toml | 9 +++++---- modules/grandpa/Cargo.toml | 3 ++- modules/messages/Cargo.toml | 3 ++- modules/parachains/Cargo.toml | 3 ++- modules/relayers/Cargo.toml | 3 ++- modules/xcm-bridge-hub-router/Cargo.toml | 3 ++- modules/xcm-bridge-hub/Cargo.toml | 3 ++- primitives/beefy/Cargo.toml | 7 ++++--- primitives/header-chain/Cargo.toml | 3 ++- primitives/messages/Cargo.toml | 3 ++- primitives/parachains/Cargo.toml | 3 ++- primitives/polkadot-core/Cargo.toml | 3 ++- primitives/relayers/Cargo.toml | 3 ++- primitives/runtime/Cargo.toml | 3 ++- primitives/test-utils/Cargo.toml | 3 ++- primitives/xcm-bridge-hub-router/Cargo.toml | 3 ++- primitives/xcm-bridge-hub/Cargo.toml | 1 + relays/client-substrate/Cargo.toml | 13 +++++++------ relays/client-substrate/src/error.rs | 2 +- relays/client-substrate/src/rpc.rs | 14 ++++++++++---- relays/equivocation/Cargo.toml | 7 ++++--- relays/finality/Cargo.toml | 7 ++++--- relays/lib-substrate-relay/Cargo.toml | 7 ++++--- relays/messages/Cargo.toml | 7 ++++--- relays/messages/src/message_race_loop.rs | 2 +- relays/parachains/Cargo.toml | 9 +++++---- relays/utils/Cargo.toml | 7 ++++--- 41 files changed, 101 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index a2ce213d2541c..8bfa39841f51e 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,10 @@ cargo test --all ``` Also you can build the repo with [Parity CI Docker -image](https://github.com/paritytech/scripts/tree/master/dockerfiles/bridges-ci): +image](https://github.com/paritytech/scripts/tree/master/dockerfiles/ci-unified): ```bash -docker pull paritytech/bridges-ci:production +docker pull paritytech/ci-unified:latest mkdir ~/cache chown 1000:1000 ~/cache #processes in the container runs as "nonroot" user with UID 1000 docker run --rm -it -w /shellhere/parity-bridges-common \ @@ -49,7 +49,7 @@ docker run --rm -it -w /shellhere/parity-bridges-common \ -v "$(pwd)":/shellhere/parity-bridges-common \ -e CARGO_HOME=/cache/cargo/ \ -e SCCACHE_DIR=/cache/sccache/ \ - -e CARGO_TARGET_DIR=/cache/target/ paritytech/bridges-ci:production cargo build --all + -e CARGO_TARGET_DIR=/cache/target/ paritytech/ci-unified:latest cargo build --all #artifacts can be found in ~/cache/target ``` diff --git a/bin/runtime-common/Cargo.toml b/bin/runtime-common/Cargo.toml index d71e9f6bae710..6304c83b905b2 100644 --- a/bin/runtime-common/Cargo.toml +++ b/bin/runtime-common/Cargo.toml @@ -11,7 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } hash-db = { version = "0.16.0", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/chains/chain-asset-hub-rococo/Cargo.toml b/chains/chain-asset-hub-rococo/Cargo.toml index ae1f05e0e7f53..660f0f4dbfcf0 100644 --- a/chains/chain-asset-hub-rococo/Cargo.toml +++ b/chains/chain-asset-hub-rococo/Cargo.toml @@ -5,12 +5,13 @@ version = "0.4.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/chains/chain-asset-hub-westend/Cargo.toml b/chains/chain-asset-hub-westend/Cargo.toml index 14c049f134dfd..4022258acd030 100644 --- a/chains/chain-asset-hub-westend/Cargo.toml +++ b/chains/chain-asset-hub-westend/Cargo.toml @@ -5,12 +5,13 @@ version = "0.3.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Substrate Dependencies diff --git a/chains/chain-bridge-hub-cumulus/Cargo.toml b/chains/chain-bridge-hub-cumulus/Cargo.toml index 82c87d8bc13e3..b87b5fefd9c7f 100644 --- a/chains/chain-bridge-hub-cumulus/Cargo.toml +++ b/chains/chain-bridge-hub-cumulus/Cargo.toml @@ -5,6 +5,7 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-bridge-hub-kusama/Cargo.toml b/chains/chain-bridge-hub-kusama/Cargo.toml index 2075fe2543c67..71ee785d4b214 100644 --- a/chains/chain-bridge-hub-kusama/Cargo.toml +++ b/chains/chain-bridge-hub-kusama/Cargo.toml @@ -5,6 +5,7 @@ version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-bridge-hub-polkadot/Cargo.toml b/chains/chain-bridge-hub-polkadot/Cargo.toml index edef6e612372f..dd4729673c0ea 100644 --- a/chains/chain-bridge-hub-polkadot/Cargo.toml +++ b/chains/chain-bridge-hub-polkadot/Cargo.toml @@ -5,6 +5,7 @@ version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-bridge-hub-rococo/Cargo.toml b/chains/chain-bridge-hub-rococo/Cargo.toml index 0370fa1c6bb2c..a8e0003ee68ea 100644 --- a/chains/chain-bridge-hub-rococo/Cargo.toml +++ b/chains/chain-bridge-hub-rococo/Cargo.toml @@ -5,6 +5,7 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-bridge-hub-westend/Cargo.toml b/chains/chain-bridge-hub-westend/Cargo.toml index ea452d89dba54..09bf743c66447 100644 --- a/chains/chain-bridge-hub-westend/Cargo.toml +++ b/chains/chain-bridge-hub-westend/Cargo.toml @@ -5,6 +5,7 @@ version = "0.3.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-kusama/Cargo.toml b/chains/chain-kusama/Cargo.toml index 56a4386afb8f3..2a59937daa760 100644 --- a/chains/chain-kusama/Cargo.toml +++ b/chains/chain-kusama/Cargo.toml @@ -5,6 +5,7 @@ version = "0.5.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-polkadot-bulletin/Cargo.toml b/chains/chain-polkadot-bulletin/Cargo.toml index 121f0c57c34a9..c20a94cfdaab4 100644 --- a/chains/chain-polkadot-bulletin/Cargo.toml +++ b/chains/chain-polkadot-bulletin/Cargo.toml @@ -5,12 +5,13 @@ version = "0.4.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } # Bridge Dependencies diff --git a/chains/chain-polkadot/Cargo.toml b/chains/chain-polkadot/Cargo.toml index 5faee3bd34ad4..f942e4fe8dd48 100644 --- a/chains/chain-polkadot/Cargo.toml +++ b/chains/chain-polkadot/Cargo.toml @@ -5,6 +5,7 @@ version = "0.5.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-rococo/Cargo.toml b/chains/chain-rococo/Cargo.toml index 401611bebbe47..a86e875517b39 100644 --- a/chains/chain-rococo/Cargo.toml +++ b/chains/chain-rococo/Cargo.toml @@ -5,6 +5,7 @@ version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/chains/chain-westend/Cargo.toml b/chains/chain-westend/Cargo.toml index d697e2b36c42c..6f5c48139c6ea 100644 --- a/chains/chain-westend/Cargo.toml +++ b/chains/chain-westend/Cargo.toml @@ -5,6 +5,7 @@ version = "0.3.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index ab3447f657c5c..d0e5204dcbea1 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -2,16 +2,17 @@ name = "pallet-bridge-beefy" version = "0.1.0" description = "Module implementing BEEFY on-chain light client used for bridging consensus of substrate-based chains." -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, workspace = true } @@ -34,7 +35,7 @@ sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branc mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.3.2" } pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -rand = "0.8" +rand = "0.8.5" sp-io = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } bp-test-utils = { path = "../../primitives/test-utils" } diff --git a/modules/grandpa/Cargo.toml b/modules/grandpa/Cargo.toml index 2388767f972ca..b3deefc879231 100644 --- a/modules/grandpa/Cargo.toml +++ b/modules/grandpa/Cargo.toml @@ -5,6 +5,7 @@ description = "Module implementing GRANDPA on-chain light client used for bridgi authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true @@ -12,7 +13,7 @@ workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/modules/messages/Cargo.toml b/modules/messages/Cargo.toml index ebe7db4085a72..24ad437be09da 100644 --- a/modules/messages/Cargo.toml +++ b/modules/messages/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } log = { workspace = true } num-traits = { version = "0.2", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/modules/parachains/Cargo.toml b/modules/parachains/Cargo.toml index 068e9a907fe26..6352b21b8f8b5 100644 --- a/modules/parachains/Cargo.toml +++ b/modules/parachains/Cargo.toml @@ -5,12 +5,13 @@ description = "Module that allows bridged relay chains to exchange information o authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/modules/relayers/Cargo.toml b/modules/relayers/Cargo.toml index 9073b9bbe082e..ae57e36f7fb1e 100644 --- a/modules/relayers/Cargo.toml +++ b/modules/relayers/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/modules/xcm-bridge-hub-router/Cargo.toml index 89c02f706c270..af130c5e7b37e 100644 --- a/modules/xcm-bridge-hub-router/Cargo.toml +++ b/modules/xcm-bridge-hub-router/Cargo.toml @@ -5,12 +5,13 @@ version = "0.5.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive", "serde"] } diff --git a/modules/xcm-bridge-hub/Cargo.toml b/modules/xcm-bridge-hub/Cargo.toml index 8654c65f66c1d..d7e5625309142 100644 --- a/modules/xcm-bridge-hub/Cargo.toml +++ b/modules/xcm-bridge-hub/Cargo.toml @@ -5,12 +5,13 @@ version = "0.2.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } log = { workspace = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/primitives/beefy/Cargo.toml b/primitives/beefy/Cargo.toml index eef3dcf96e860..f1992e59b709a 100644 --- a/primitives/beefy/Cargo.toml +++ b/primitives/beefy/Cargo.toml @@ -2,16 +2,17 @@ name = "bp-beefy" description = "Primitives of pallet-bridge-beefy module." version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } serde = { default-features = false, features = ["alloc", "derive"], workspace = true } diff --git a/primitives/header-chain/Cargo.toml b/primitives/header-chain/Cargo.toml index 8dc9a8ae776da..f38d754544bba 100644 --- a/primitives/header-chain/Cargo.toml +++ b/primitives/header-chain/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { features = ["alloc", "derive"], workspace = true } diff --git a/primitives/messages/Cargo.toml b/primitives/messages/Cargo.toml index 93b0efa276569..8bacff709eb4e 100644 --- a/primitives/messages/Cargo.toml +++ b/primitives/messages/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } serde = { features = ["alloc", "derive"], workspace = true } diff --git a/primitives/parachains/Cargo.toml b/primitives/parachains/Cargo.toml index 610b7b3361358..1606dbfcd6423 100644 --- a/primitives/parachains/Cargo.toml +++ b/primitives/parachains/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } impl-trait-for-tuples = "0.2" scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } diff --git a/primitives/polkadot-core/Cargo.toml b/primitives/polkadot-core/Cargo.toml index 6c20d64da3fb2..b85586405ff32 100644 --- a/primitives/polkadot-core/Cargo.toml +++ b/primitives/polkadot-core/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } parity-util-mem = { version = "0.12.0", optional = true } scale-info = { version = "2.11.1", default-features = false, features = ["derive"] } serde = { optional = true, features = ["derive"], workspace = true, default-features = true } diff --git a/primitives/relayers/Cargo.toml b/primitives/relayers/Cargo.toml index 441d240600356..46bc034ef1154 100644 --- a/primitives/relayers/Cargo.toml +++ b/primitives/relayers/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } # Bridge Dependencies diff --git a/primitives/runtime/Cargo.toml b/primitives/runtime/Cargo.toml index c2b2a794b3e65..258b576828665 100644 --- a/primitives/runtime/Cargo.toml +++ b/primitives/runtime/Cargo.toml @@ -5,12 +5,13 @@ version = "0.7.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } hash-db = { version = "0.16.0", default-features = false } impl-trait-for-tuples = "0.2.2" log = { workspace = true } diff --git a/primitives/test-utils/Cargo.toml b/primitives/test-utils/Cargo.toml index 1b3ac9ee697cb..b46868a0a599c 100644 --- a/primitives/test-utils/Cargo.toml +++ b/primitives/test-utils/Cargo.toml @@ -5,6 +5,7 @@ description = "Utilities for testing substrate-based runtime bridge code" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true @@ -14,7 +15,7 @@ bp-header-chain = { path = "../header-chain", default-features = false } bp-parachains = { path = "../parachains", default-features = false } bp-polkadot-core = { path = "../polkadot-core", default-features = false } bp-runtime = { path = "../runtime", default-features = false } -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } ed25519-dalek = { version = "2.1", default-features = false } finality-grandpa = { version = "0.16.2", default-features = false } sp-application-crypto = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master", default-features = false } diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/primitives/xcm-bridge-hub-router/Cargo.toml index bc0ff5c605e89..c3fe409b68c20 100644 --- a/primitives/xcm-bridge-hub-router/Cargo.toml +++ b/primitives/xcm-bridge-hub-router/Cargo.toml @@ -5,12 +5,13 @@ version = "0.6.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true [dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["bit-vec", "derive"] } +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bit-vec", "derive"] } scale-info = { version = "2.11.1", default-features = false, features = ["bit-vec", "derive"] } # Substrate Dependencies diff --git a/primitives/xcm-bridge-hub/Cargo.toml b/primitives/xcm-bridge-hub/Cargo.toml index 1a5bb742eed47..9043071002a91 100644 --- a/primitives/xcm-bridge-hub/Cargo.toml +++ b/primitives/xcm-bridge-hub/Cargo.toml @@ -5,6 +5,7 @@ version = "0.2.0" authors.workspace = true edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true [lints] workspace = true diff --git a/relays/client-substrate/Cargo.toml b/relays/client-substrate/Cargo.toml index 51e3edefaf979..85ebce1f9b97f 100644 --- a/relays/client-substrate/Cargo.toml +++ b/relays/client-substrate/Cargo.toml @@ -1,23 +1,24 @@ [package] name = "relay-substrate-client" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] workspace = true [dependencies] -async-std = { version = "1.6.5", features = ["attributes"] } +async-std = { version = "1.9.0", features = ["attributes"] } async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.1.5" } +codec = { package = "parity-scale-codec", version = "3.6.1" } futures = "0.3.30" -jsonrpsee = { version = "0.17", features = ["macros", "ws-client"] } +jsonrpsee = { version = "0.22", features = ["macros", "ws-client"] } log = { workspace = true } num-traits = "0.2" -rand = "0.8" +rand = "0.8.5" scale-info = { version = "2.11.1", features = ["derive"] } tokio = { version = "1.37", features = ["rt-multi-thread"] } thiserror = { workspace = true } diff --git a/relays/client-substrate/src/error.rs b/relays/client-substrate/src/error.rs index 257771b70b1f1..0b44668181887 100644 --- a/relays/client-substrate/src/error.rs +++ b/relays/client-substrate/src/error.rs @@ -18,7 +18,7 @@ use crate::SimpleRuntimeVersion; use bp_polkadot_core::parachains::ParaId; -use jsonrpsee::core::Error as RpcError; +use jsonrpsee::core::ClientError as RpcError; use relay_utils::MaybeConnectionError; use sc_rpc_api::system::Health; use sp_core::storage::StorageKey; diff --git a/relays/client-substrate/src/rpc.rs b/relays/client-substrate/src/rpc.rs index 35ab08c0f4151..60c29cdeb5c77 100644 --- a/relays/client-substrate/src/rpc.rs +++ b/relays/client-substrate/src/rpc.rs @@ -21,7 +21,7 @@ use async_trait::async_trait; use crate::{Chain, ChainWithGrandpa, TransactionStatusOf}; use jsonrpsee::{ - core::{client::Subscription, RpcResult}, + core::{client::Subscription, ClientError}, proc_macros::rpc, ws_client::WsClient, }; @@ -110,7 +110,9 @@ pub(crate) trait SubstrateState { #[async_trait] pub trait SubstrateFinalityClient { /// Subscribe to finality justifications. - async fn subscribe_justifications(client: &WsClient) -> RpcResult>; + async fn subscribe_justifications( + client: &WsClient, + ) -> Result, ClientError>; } /// RPC methods of Substrate `grandpa` namespace, that we are using. @@ -125,7 +127,9 @@ pub(crate) trait SubstrateGrandpa { pub struct SubstrateGrandpaFinalityClient; #[async_trait] impl SubstrateFinalityClient for SubstrateGrandpaFinalityClient { - async fn subscribe_justifications(client: &WsClient) -> RpcResult> { + async fn subscribe_justifications( + client: &WsClient, + ) -> Result, ClientError> { SubstrateGrandpaClient::::subscribe_justifications(client).await } } @@ -144,7 +148,9 @@ pub struct SubstrateBeefyFinalityClient; // TODO: Use `ChainWithBeefy` instead of `Chain` after #1606 is merged #[async_trait] impl SubstrateFinalityClient for SubstrateBeefyFinalityClient { - async fn subscribe_justifications(client: &WsClient) -> RpcResult> { + async fn subscribe_justifications( + client: &WsClient, + ) -> Result, ClientError> { SubstrateBeefyClient::::subscribe_justifications(client).await } } diff --git a/relays/equivocation/Cargo.toml b/relays/equivocation/Cargo.toml index 3b99e4349e037..e7146e05f479c 100644 --- a/relays/equivocation/Cargo.toml +++ b/relays/equivocation/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "equivocation-detector" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true description = "Equivocation detector" publish = false @@ -11,7 +12,7 @@ publish = false workspace = true [dependencies] -async-std = { version = "1.6.5", features = ["attributes"] } +async-std = { version = "1.9.0", features = ["attributes"] } async-trait = "0.1.79" bp-header-chain = { path = "../../primitives/header-chain" } finality-relay = { path = "../finality" } diff --git a/relays/finality/Cargo.toml b/relays/finality/Cargo.toml index 53d2ce579f6be..5ee4b10fa638f 100644 --- a/relays/finality/Cargo.toml +++ b/relays/finality/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "finality-relay" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true description = "Finality proofs relay" publish = false @@ -11,7 +12,7 @@ publish = false workspace = true [dependencies] -async-std = "1.6.5" +async-std = "1.9.0" async-trait = "0.1.79" backoff = "0.4" bp-header-chain = { path = "../../primitives/header-chain" } diff --git a/relays/lib-substrate-relay/Cargo.toml b/relays/lib-substrate-relay/Cargo.toml index 76be5a92a794a..7e7e774d7253b 100644 --- a/relays/lib-substrate-relay/Cargo.toml +++ b/relays/lib-substrate-relay/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "substrate-relay-helper" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] @@ -13,7 +14,7 @@ workspace = true anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.79" -codec = { package = "parity-scale-codec", version = "3.1.5" } +codec = { package = "parity-scale-codec", version = "3.6.1" } futures = "0.3.30" hex = "0.4" log = { workspace = true } diff --git a/relays/messages/Cargo.toml b/relays/messages/Cargo.toml index b3f0a9fd19185..8a411e5082fa4 100644 --- a/relays/messages/Cargo.toml +++ b/relays/messages/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "messages-relay" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] workspace = true [dependencies] -async-std = { version = "1.6.5", features = ["attributes"] } +async-std = { version = "1.9.0", features = ["attributes"] } async-trait = "0.1.79" env_logger = "0.11" futures = "0.3.30" diff --git a/relays/messages/src/message_race_loop.rs b/relays/messages/src/message_race_loop.rs index f28be78842fc1..31341a9a0c0cd 100644 --- a/relays/messages/src/message_race_loop.rs +++ b/relays/messages/src/message_race_loop.rs @@ -313,7 +313,7 @@ where } fn nonces_to_submit(&self) -> Option> { - self.nonces_to_submit.as_ref().map(|(_, nonces, _)| nonces.clone()) + self.nonces_to_submit.clone().map(|(_, nonces, _)| nonces) } fn reset_nonces_to_submit(&mut self) { diff --git a/relays/parachains/Cargo.toml b/relays/parachains/Cargo.toml index f37e636a9c598..e691168e72d08 100644 --- a/relays/parachains/Cargo.toml +++ b/relays/parachains/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "parachains-relay" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2018" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] workspace = true [dependencies] -async-std = "1.6.5" +async-std = "1.9.0" async-trait = "0.1.79" futures = "0.3.30" log = { workspace = true } @@ -22,6 +23,6 @@ bp-polkadot-core = { path = "../../primitives/polkadot-core" } relay-substrate-client = { path = "../client-substrate" } [dev-dependencies] -codec = { package = "parity-scale-codec", version = "3.1.5" } +codec = { package = "parity-scale-codec", version = "3.6.1" } relay-substrate-client = { path = "../client-substrate", features = ["test-helpers"] } sp-core = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } diff --git a/relays/utils/Cargo.toml b/relays/utils/Cargo.toml index 13fda477351b9..8d9addb9beef0 100644 --- a/relays/utils/Cargo.toml +++ b/relays/utils/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "relay-utils" version = "0.1.0" -authors = ["Parity Technologies "] -edition = "2021" +authors.workspace = true +edition.workspace = true license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +repository.workspace = true publish = false [lints] @@ -12,7 +13,7 @@ workspace = true [dependencies] ansi_term = "0.12" anyhow = "1.0" -async-std = "1.6.5" +async-std = "1.9.0" async-trait = "0.1.79" backoff = "0.4" isahc = "1.2" From 044fe8a576639062bc43a166c370b8588991d56e Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 2 Apr 2024 13:55:07 +0300 Subject: [PATCH 1209/1210] ckb-merkle-mountain-range -> 0.5.2 (#2911) --- modules/beefy/Cargo.toml | 2 +- modules/beefy/src/mock_chain.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/beefy/Cargo.toml b/modules/beefy/Cargo.toml index d0e5204dcbea1..2c552430c98f9 100644 --- a/modules/beefy/Cargo.toml +++ b/modules/beefy/Cargo.toml @@ -32,7 +32,7 @@ sp-std = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" [dev-dependencies] sp-consensus-beefy = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } -mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.3.2" } +mmr-lib = { package = "ckb-merkle-mountain-range", version = "0.5.2" } pallet-beefy-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } pallet-mmr = { git = "https://github.com/paritytech/polkadot-sdk", branch = "master" } rand = "0.8.5" diff --git a/modules/beefy/src/mock_chain.rs b/modules/beefy/src/mock_chain.rs index c4fa74915bfeb..c83907f839568 100644 --- a/modules/beefy/src/mock_chain.rs +++ b/modules/beefy/src/mock_chain.rs @@ -290,10 +290,10 @@ pub struct BridgedMmrHashMerge; impl mmr_lib::Merge for BridgedMmrHashMerge { type Item = TestBridgedMmrNode; - fn merge(left: &Self::Item, right: &Self::Item) -> Self::Item { + fn merge(left: &Self::Item, right: &Self::Item) -> mmr_lib::Result { let mut concat = left.hash().as_ref().to_vec(); concat.extend_from_slice(right.hash().as_ref()); - TestBridgedMmrNode::Hash(TestBridgedMmrHashing::hash(&concat)) + Ok(TestBridgedMmrNode::Hash(TestBridgedMmrHashing::hash(&concat))) } } From 146f0781c5514a2242317b7dd20c2cb057831cbc Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Fri, 5 Apr 2024 22:26:07 +0300 Subject: [PATCH 1210/1210] Prepare polkadot-sdk folder structure --- CODE_OF_CONDUCT.md => bridges/CODE_OF_CONDUCT.md | 0 LICENSE => bridges/LICENSE | 0 README.md => bridges/README.md | 0 SECURITY.md => bridges/SECURITY.md | 0 {bin => bridges/bin}/runtime-common/Cargo.toml | 0 .../bin}/runtime-common/src/integrity.rs | 0 {bin => bridges/bin}/runtime-common/src/lib.rs | 0 {bin => bridges/bin}/runtime-common/src/messages.rs | 0 .../bin}/runtime-common/src/messages_api.rs | 0 .../runtime-common/src/messages_benchmarking.rs | 0 .../bin}/runtime-common/src/messages_call_ext.rs | 0 .../bin}/runtime-common/src/messages_generation.rs | 0 .../runtime-common/src/messages_xcm_extension.rs | 0 {bin => bridges/bin}/runtime-common/src/mock.rs | 0 .../runtime-common/src/parachains_benchmarking.rs | 0 .../bin}/runtime-common/src/priority_calculator.rs | 0 .../runtime-common/src/refund_relayer_extension.rs | 0 .../chains}/chain-asset-hub-rococo/Cargo.toml | 0 .../chains}/chain-asset-hub-rococo/src/lib.rs | 0 .../chains}/chain-asset-hub-westend/Cargo.toml | 0 .../chains}/chain-asset-hub-westend/src/lib.rs | 0 .../chains}/chain-bridge-hub-cumulus/Cargo.toml | 0 .../chains}/chain-bridge-hub-cumulus/src/lib.rs | 0 .../chains}/chain-bridge-hub-kusama/Cargo.toml | 0 .../chains}/chain-bridge-hub-kusama/src/lib.rs | 0 .../chains}/chain-bridge-hub-polkadot/Cargo.toml | 0 .../chains}/chain-bridge-hub-polkadot/src/lib.rs | 0 .../chains}/chain-bridge-hub-rococo/Cargo.toml | 0 .../chains}/chain-bridge-hub-rococo/src/lib.rs | 0 .../chains}/chain-bridge-hub-westend/Cargo.toml | 0 .../chains}/chain-bridge-hub-westend/src/lib.rs | 0 {chains => bridges/chains}/chain-kusama/Cargo.toml | 0 {chains => bridges/chains}/chain-kusama/src/lib.rs | 0 .../chains}/chain-polkadot-bulletin/Cargo.toml | 0 .../chains}/chain-polkadot-bulletin/src/lib.rs | 0 .../chains}/chain-polkadot/Cargo.toml | 0 .../chains}/chain-polkadot/src/lib.rs | 0 {chains => bridges/chains}/chain-rococo/Cargo.toml | 0 {chains => bridges/chains}/chain-rococo/src/lib.rs | 0 {chains => bridges/chains}/chain-westend/Cargo.toml | 0 {chains => bridges/chains}/chain-westend/src/lib.rs | 0 .../docs}/bridge-relayers-claim-rewards.png | Bin .../docs}/bridge-relayers-deregister.png | Bin {docs => bridges/docs}/bridge-relayers-register.png | Bin {docs => bridges/docs}/complex-relay.html | 0 {docs => bridges/docs}/grandpa-finality-relay.html | 0 {docs => bridges/docs}/high-level-overview.md | 0 {docs => bridges/docs}/messages-relay.html | 0 .../docs}/parachains-finality-relay.html | 0 .../docs}/polkadot-kusama-bridge-overview.md | 0 {docs => bridges/docs}/polkadot-kusama-bridge.html | 0 {docs => bridges/docs}/running-relayer.md | 0 {modules => bridges/modules}/beefy/Cargo.toml | 0 {modules => bridges/modules}/beefy/src/lib.rs | 0 {modules => bridges/modules}/beefy/src/mock.rs | 0 .../modules}/beefy/src/mock_chain.rs | 0 {modules => bridges/modules}/beefy/src/utils.rs | 0 {modules => bridges/modules}/grandpa/Cargo.toml | 0 {modules => bridges/modules}/grandpa/README.md | 0 .../modules}/grandpa/src/benchmarking.rs | 0 .../modules}/grandpa/src/call_ext.rs | 0 {modules => bridges/modules}/grandpa/src/lib.rs | 0 {modules => bridges/modules}/grandpa/src/mock.rs | 0 .../modules}/grandpa/src/storage_types.rs | 0 {modules => bridges/modules}/grandpa/src/weights.rs | 0 {modules => bridges/modules}/messages/Cargo.toml | 0 {modules => bridges/modules}/messages/README.md | 0 .../modules}/messages/src/benchmarking.rs | 0 .../modules}/messages/src/inbound_lane.rs | 0 {modules => bridges/modules}/messages/src/lib.rs | 0 {modules => bridges/modules}/messages/src/mock.rs | 0 .../modules}/messages/src/outbound_lane.rs | 0 .../modules}/messages/src/weights.rs | 0 .../modules}/messages/src/weights_ext.rs | 0 {modules => bridges/modules}/parachains/Cargo.toml | 0 {modules => bridges/modules}/parachains/README.md | 0 .../modules}/parachains/src/benchmarking.rs | 0 .../modules}/parachains/src/call_ext.rs | 0 {modules => bridges/modules}/parachains/src/lib.rs | 0 {modules => bridges/modules}/parachains/src/mock.rs | 0 .../modules}/parachains/src/weights.rs | 0 .../modules}/parachains/src/weights_ext.rs | 0 {modules => bridges/modules}/relayers/Cargo.toml | 0 {modules => bridges/modules}/relayers/README.md | 0 .../modules}/relayers/src/benchmarking.rs | 0 {modules => bridges/modules}/relayers/src/lib.rs | 0 {modules => bridges/modules}/relayers/src/mock.rs | 0 .../modules}/relayers/src/payment_adapter.rs | 0 .../modules}/relayers/src/stake_adapter.rs | 0 .../modules}/relayers/src/weights.rs | 0 .../modules}/relayers/src/weights_ext.rs | 0 .../modules}/xcm-bridge-hub-router/Cargo.toml | 0 .../xcm-bridge-hub-router/src/benchmarking.rs | 0 .../modules}/xcm-bridge-hub-router/src/lib.rs | 0 .../modules}/xcm-bridge-hub-router/src/mock.rs | 0 .../modules}/xcm-bridge-hub-router/src/weights.rs | 0 .../modules}/xcm-bridge-hub/Cargo.toml | 0 .../modules}/xcm-bridge-hub/src/exporter.rs | 0 .../modules}/xcm-bridge-hub/src/lib.rs | 0 .../modules}/xcm-bridge-hub/src/mock.rs | 0 {primitives => bridges/primitives}/beefy/Cargo.toml | 0 {primitives => bridges/primitives}/beefy/src/lib.rs | 0 .../primitives}/header-chain/Cargo.toml | 0 .../header-chain/src/justification/mod.rs | 0 .../src/justification/verification/equivocation.rs | 0 .../src/justification/verification/mod.rs | 0 .../src/justification/verification/optimizer.rs | 0 .../src/justification/verification/strict.rs | 0 .../primitives}/header-chain/src/lib.rs | 0 .../primitives}/header-chain/src/storage_keys.rs | 0 .../header-chain/tests/implementation_match.rs | 0 .../tests/justification/equivocation.rs | 0 .../header-chain/tests/justification/optimizer.rs | 0 .../header-chain/tests/justification/strict.rs | 0 .../primitives}/header-chain/tests/tests.rs | 0 .../primitives}/messages/Cargo.toml | 0 .../primitives}/messages/src/lib.rs | 0 .../primitives}/messages/src/source_chain.rs | 0 .../primitives}/messages/src/storage_keys.rs | 0 .../primitives}/messages/src/target_chain.rs | 0 .../primitives}/parachains/Cargo.toml | 0 .../primitives}/parachains/src/lib.rs | 0 .../primitives}/polkadot-core/Cargo.toml | 0 .../primitives}/polkadot-core/src/lib.rs | 0 .../primitives}/polkadot-core/src/parachains.rs | 0 .../primitives}/relayers/Cargo.toml | 0 .../primitives}/relayers/src/lib.rs | 0 .../primitives}/relayers/src/registration.rs | 0 .../primitives}/runtime/Cargo.toml | 0 .../primitives}/runtime/src/chain.rs | 0 .../primitives}/runtime/src/extensions.rs | 0 .../primitives}/runtime/src/lib.rs | 0 .../primitives}/runtime/src/messages.rs | 0 .../primitives}/runtime/src/storage_proof.rs | 0 .../primitives}/runtime/src/storage_types.rs | 0 .../primitives}/test-utils/Cargo.toml | 0 .../primitives}/test-utils/src/keyring.rs | 0 .../primitives}/test-utils/src/lib.rs | 0 .../primitives}/xcm-bridge-hub-router/Cargo.toml | 0 .../primitives}/xcm-bridge-hub-router/src/lib.rs | 0 .../primitives}/xcm-bridge-hub/Cargo.toml | 0 .../primitives}/xcm-bridge-hub/src/lib.rs | 0 .../relays}/client-substrate/Cargo.toml | 0 .../relays}/client-substrate/src/calls.rs | 0 .../relays}/client-substrate/src/chain.rs | 0 .../relays}/client-substrate/src/client.rs | 0 .../relays}/client-substrate/src/error.rs | 0 .../relays}/client-substrate/src/guard.rs | 0 .../relays}/client-substrate/src/lib.rs | 0 .../src/metrics/float_storage_value.rs | 0 .../relays}/client-substrate/src/metrics/mod.rs | 0 .../relays}/client-substrate/src/rpc.rs | 0 .../relays}/client-substrate/src/sync_header.rs | 0 .../relays}/client-substrate/src/test_chain.rs | 0 .../client-substrate/src/transaction_tracker.rs | 0 {relays => bridges/relays}/equivocation/Cargo.toml | 0 .../relays}/equivocation/src/block_checker.rs | 0 .../relays}/equivocation/src/equivocation_loop.rs | 0 {relays => bridges/relays}/equivocation/src/lib.rs | 0 {relays => bridges/relays}/equivocation/src/mock.rs | 0 .../relays}/equivocation/src/reporter.rs | 0 {relays => bridges/relays}/finality/Cargo.toml | 0 {relays => bridges/relays}/finality/README.md | 0 {relays => bridges/relays}/finality/src/base.rs | 0 .../relays}/finality/src/finality_loop.rs | 0 .../relays}/finality/src/finality_proofs.rs | 0 {relays => bridges/relays}/finality/src/headers.rs | 0 {relays => bridges/relays}/finality/src/lib.rs | 0 {relays => bridges/relays}/finality/src/mock.rs | 0 .../relays}/finality/src/sync_loop_metrics.rs | 0 .../relays}/lib-substrate-relay/Cargo.toml | 0 .../relays}/lib-substrate-relay/src/cli/bridge.rs | 0 .../lib-substrate-relay/src/cli/chain_schema.rs | 0 .../src/cli/detect_equivocations.rs | 0 .../lib-substrate-relay/src/cli/init_bridge.rs | 0 .../relays}/lib-substrate-relay/src/cli/mod.rs | 0 .../lib-substrate-relay/src/cli/relay_headers.rs | 0 .../src/cli/relay_headers_and_messages/mod.rs | 0 .../parachain_to_parachain.rs | 0 .../relay_to_parachain.rs | 0 .../relay_headers_and_messages/relay_to_relay.rs | 0 .../lib-substrate-relay/src/cli/relay_messages.rs | 0 .../lib-substrate-relay/src/cli/relay_parachains.rs | 0 .../lib-substrate-relay/src/equivocation/mod.rs | 0 .../lib-substrate-relay/src/equivocation/source.rs | 0 .../lib-substrate-relay/src/equivocation/target.rs | 0 .../relays}/lib-substrate-relay/src/error.rs | 0 .../lib-substrate-relay/src/finality/initialize.rs | 0 .../relays}/lib-substrate-relay/src/finality/mod.rs | 0 .../lib-substrate-relay/src/finality/source.rs | 0 .../lib-substrate-relay/src/finality/target.rs | 0 .../lib-substrate-relay/src/finality_base/engine.rs | 0 .../lib-substrate-relay/src/finality_base/mod.rs | 0 .../relays}/lib-substrate-relay/src/lib.rs | 0 .../lib-substrate-relay/src/messages_lane.rs | 0 .../lib-substrate-relay/src/messages_metrics.rs | 0 .../lib-substrate-relay/src/messages_source.rs | 0 .../lib-substrate-relay/src/messages_target.rs | 0 .../lib-substrate-relay/src/on_demand/headers.rs | 0 .../lib-substrate-relay/src/on_demand/mod.rs | 0 .../lib-substrate-relay/src/on_demand/parachains.rs | 0 .../lib-substrate-relay/src/parachains/mod.rs | 0 .../lib-substrate-relay/src/parachains/source.rs | 0 .../lib-substrate-relay/src/parachains/target.rs | 0 {relays => bridges/relays}/messages/Cargo.toml | 0 {relays => bridges/relays}/messages/src/lib.rs | 0 .../relays}/messages/src/message_lane.rs | 0 .../relays}/messages/src/message_lane_loop.rs | 0 .../relays}/messages/src/message_race_delivery.rs | 0 .../relays}/messages/src/message_race_limits.rs | 0 .../relays}/messages/src/message_race_loop.rs | 0 .../relays}/messages/src/message_race_receiving.rs | 0 .../relays}/messages/src/message_race_strategy.rs | 0 {relays => bridges/relays}/messages/src/metrics.rs | 0 {relays => bridges/relays}/parachains/Cargo.toml | 0 {relays => bridges/relays}/parachains/README.md | 0 {relays => bridges/relays}/parachains/src/lib.rs | 0 .../relays}/parachains/src/parachains_loop.rs | 0 .../parachains/src/parachains_loop_metrics.rs | 0 {relays => bridges/relays}/utils/Cargo.toml | 0 {relays => bridges/relays}/utils/src/error.rs | 0 {relays => bridges/relays}/utils/src/initialize.rs | 0 {relays => bridges/relays}/utils/src/lib.rs | 0 {relays => bridges/relays}/utils/src/metrics.rs | 0 .../relays}/utils/src/metrics/float_json_value.rs | 0 .../relays}/utils/src/metrics/global.rs | 0 {relays => bridges/relays}/utils/src/relay_loop.rs | 0 {testing => bridges/testing}/README.md | 0 .../bridge_hub_rococo_local_network.toml | 0 .../bridge_hub_westend_local_network.toml | 0 .../rococo-westend/bridges_rococo_westend.sh | 0 .../testing}/environments/rococo-westend/helper.sh | 0 .../environments/rococo-westend/rococo-init.zndsl | 0 .../environments/rococo-westend/rococo.zndsl | 0 .../testing}/environments/rococo-westend/spawn.sh | 0 .../environments/rococo-westend/start_relayer.sh | 0 .../environments/rococo-westend/westend-init.zndsl | 0 .../environments/rococo-westend/westend.zndsl | 0 .../best-finalized-header-at-bridged-chain.js | 0 .../js-helpers/chains/rococo-at-westend.js | 0 .../js-helpers/chains/westend-at-rococo.js | 0 .../js-helpers/native-assets-balance-increased.js | 0 .../only-mandatory-headers-synced-when-idle.js | 0 .../only-required-headers-synced-when-idle.js | 0 .../framework/js-helpers/relayer-rewards.js | 0 .../testing}/framework/js-helpers/utils.js | 0 .../js-helpers/wait-hrmp-channel-opened.js | 0 .../framework/js-helpers/wrapped-assets-balance.js | 0 .../testing}/framework/utils/bridges.sh | 0 .../testing}/framework/utils/common.sh | 0 .../utils/generate_hex_encoded_call/index.js | 0 .../generate_hex_encoded_call/package-lock.json | 0 .../utils/generate_hex_encoded_call/package.json | 0 .../testing}/framework/utils/zombienet.sh | 0 {testing => bridges/testing}/run-new-test.sh | 0 {testing => bridges/testing}/run-tests.sh | 0 .../testing}/scripts/invoke-script.sh | 0 .../testing}/scripts/start-relayer.sh | 0 {testing => bridges/testing}/scripts/sync-exit.sh | 0 .../0001-asset-transfer/roc-reaches-westend.zndsl | 0 .../testing}/tests/0001-asset-transfer/run.sh | 0 .../0001-asset-transfer/wnd-reaches-rococo.zndsl | 0 .../0001-asset-transfer/wroc-reaches-rococo.zndsl | 0 .../0001-asset-transfer/wwnd-reaches-westend.zndsl | 0 .../rococo-to-westend.zndsl | 0 .../0002-mandatory-headers-synced-while-idle/run.sh | 0 .../westend-to-rococo.zndsl | 0 ...ders-synced-while-active-rococo-to-westend.zndsl | 0 ...ders-synced-while-active-westend-to-rococo.zndsl | 0 269 files changed, 0 insertions(+), 0 deletions(-) rename CODE_OF_CONDUCT.md => bridges/CODE_OF_CONDUCT.md (100%) rename LICENSE => bridges/LICENSE (100%) rename README.md => bridges/README.md (100%) rename SECURITY.md => bridges/SECURITY.md (100%) rename {bin => bridges/bin}/runtime-common/Cargo.toml (100%) rename {bin => bridges/bin}/runtime-common/src/integrity.rs (100%) rename {bin => bridges/bin}/runtime-common/src/lib.rs (100%) rename {bin => bridges/bin}/runtime-common/src/messages.rs (100%) rename {bin => bridges/bin}/runtime-common/src/messages_api.rs (100%) rename {bin => bridges/bin}/runtime-common/src/messages_benchmarking.rs (100%) rename {bin => bridges/bin}/runtime-common/src/messages_call_ext.rs (100%) rename {bin => bridges/bin}/runtime-common/src/messages_generation.rs (100%) rename {bin => bridges/bin}/runtime-common/src/messages_xcm_extension.rs (100%) rename {bin => bridges/bin}/runtime-common/src/mock.rs (100%) rename {bin => bridges/bin}/runtime-common/src/parachains_benchmarking.rs (100%) rename {bin => bridges/bin}/runtime-common/src/priority_calculator.rs (100%) rename {bin => bridges/bin}/runtime-common/src/refund_relayer_extension.rs (100%) rename {chains => bridges/chains}/chain-asset-hub-rococo/Cargo.toml (100%) rename {chains => bridges/chains}/chain-asset-hub-rococo/src/lib.rs (100%) rename {chains => bridges/chains}/chain-asset-hub-westend/Cargo.toml (100%) rename {chains => bridges/chains}/chain-asset-hub-westend/src/lib.rs (100%) rename {chains => bridges/chains}/chain-bridge-hub-cumulus/Cargo.toml (100%) rename {chains => bridges/chains}/chain-bridge-hub-cumulus/src/lib.rs (100%) rename {chains => bridges/chains}/chain-bridge-hub-kusama/Cargo.toml (100%) rename {chains => bridges/chains}/chain-bridge-hub-kusama/src/lib.rs (100%) rename {chains => bridges/chains}/chain-bridge-hub-polkadot/Cargo.toml (100%) rename {chains => bridges/chains}/chain-bridge-hub-polkadot/src/lib.rs (100%) rename {chains => bridges/chains}/chain-bridge-hub-rococo/Cargo.toml (100%) rename {chains => bridges/chains}/chain-bridge-hub-rococo/src/lib.rs (100%) rename {chains => bridges/chains}/chain-bridge-hub-westend/Cargo.toml (100%) rename {chains => bridges/chains}/chain-bridge-hub-westend/src/lib.rs (100%) rename {chains => bridges/chains}/chain-kusama/Cargo.toml (100%) rename {chains => bridges/chains}/chain-kusama/src/lib.rs (100%) rename {chains => bridges/chains}/chain-polkadot-bulletin/Cargo.toml (100%) rename {chains => bridges/chains}/chain-polkadot-bulletin/src/lib.rs (100%) rename {chains => bridges/chains}/chain-polkadot/Cargo.toml (100%) rename {chains => bridges/chains}/chain-polkadot/src/lib.rs (100%) rename {chains => bridges/chains}/chain-rococo/Cargo.toml (100%) rename {chains => bridges/chains}/chain-rococo/src/lib.rs (100%) rename {chains => bridges/chains}/chain-westend/Cargo.toml (100%) rename {chains => bridges/chains}/chain-westend/src/lib.rs (100%) rename {docs => bridges/docs}/bridge-relayers-claim-rewards.png (100%) rename {docs => bridges/docs}/bridge-relayers-deregister.png (100%) rename {docs => bridges/docs}/bridge-relayers-register.png (100%) rename {docs => bridges/docs}/complex-relay.html (100%) rename {docs => bridges/docs}/grandpa-finality-relay.html (100%) rename {docs => bridges/docs}/high-level-overview.md (100%) rename {docs => bridges/docs}/messages-relay.html (100%) rename {docs => bridges/docs}/parachains-finality-relay.html (100%) rename {docs => bridges/docs}/polkadot-kusama-bridge-overview.md (100%) rename {docs => bridges/docs}/polkadot-kusama-bridge.html (100%) rename {docs => bridges/docs}/running-relayer.md (100%) rename {modules => bridges/modules}/beefy/Cargo.toml (100%) rename {modules => bridges/modules}/beefy/src/lib.rs (100%) rename {modules => bridges/modules}/beefy/src/mock.rs (100%) rename {modules => bridges/modules}/beefy/src/mock_chain.rs (100%) rename {modules => bridges/modules}/beefy/src/utils.rs (100%) rename {modules => bridges/modules}/grandpa/Cargo.toml (100%) rename {modules => bridges/modules}/grandpa/README.md (100%) rename {modules => bridges/modules}/grandpa/src/benchmarking.rs (100%) rename {modules => bridges/modules}/grandpa/src/call_ext.rs (100%) rename {modules => bridges/modules}/grandpa/src/lib.rs (100%) rename {modules => bridges/modules}/grandpa/src/mock.rs (100%) rename {modules => bridges/modules}/grandpa/src/storage_types.rs (100%) rename {modules => bridges/modules}/grandpa/src/weights.rs (100%) rename {modules => bridges/modules}/messages/Cargo.toml (100%) rename {modules => bridges/modules}/messages/README.md (100%) rename {modules => bridges/modules}/messages/src/benchmarking.rs (100%) rename {modules => bridges/modules}/messages/src/inbound_lane.rs (100%) rename {modules => bridges/modules}/messages/src/lib.rs (100%) rename {modules => bridges/modules}/messages/src/mock.rs (100%) rename {modules => bridges/modules}/messages/src/outbound_lane.rs (100%) rename {modules => bridges/modules}/messages/src/weights.rs (100%) rename {modules => bridges/modules}/messages/src/weights_ext.rs (100%) rename {modules => bridges/modules}/parachains/Cargo.toml (100%) rename {modules => bridges/modules}/parachains/README.md (100%) rename {modules => bridges/modules}/parachains/src/benchmarking.rs (100%) rename {modules => bridges/modules}/parachains/src/call_ext.rs (100%) rename {modules => bridges/modules}/parachains/src/lib.rs (100%) rename {modules => bridges/modules}/parachains/src/mock.rs (100%) rename {modules => bridges/modules}/parachains/src/weights.rs (100%) rename {modules => bridges/modules}/parachains/src/weights_ext.rs (100%) rename {modules => bridges/modules}/relayers/Cargo.toml (100%) rename {modules => bridges/modules}/relayers/README.md (100%) rename {modules => bridges/modules}/relayers/src/benchmarking.rs (100%) rename {modules => bridges/modules}/relayers/src/lib.rs (100%) rename {modules => bridges/modules}/relayers/src/mock.rs (100%) rename {modules => bridges/modules}/relayers/src/payment_adapter.rs (100%) rename {modules => bridges/modules}/relayers/src/stake_adapter.rs (100%) rename {modules => bridges/modules}/relayers/src/weights.rs (100%) rename {modules => bridges/modules}/relayers/src/weights_ext.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub-router/Cargo.toml (100%) rename {modules => bridges/modules}/xcm-bridge-hub-router/src/benchmarking.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub-router/src/lib.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub-router/src/mock.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub-router/src/weights.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub/Cargo.toml (100%) rename {modules => bridges/modules}/xcm-bridge-hub/src/exporter.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub/src/lib.rs (100%) rename {modules => bridges/modules}/xcm-bridge-hub/src/mock.rs (100%) rename {primitives => bridges/primitives}/beefy/Cargo.toml (100%) rename {primitives => bridges/primitives}/beefy/src/lib.rs (100%) rename {primitives => bridges/primitives}/header-chain/Cargo.toml (100%) rename {primitives => bridges/primitives}/header-chain/src/justification/mod.rs (100%) rename {primitives => bridges/primitives}/header-chain/src/justification/verification/equivocation.rs (100%) rename {primitives => bridges/primitives}/header-chain/src/justification/verification/mod.rs (100%) rename {primitives => bridges/primitives}/header-chain/src/justification/verification/optimizer.rs (100%) rename {primitives => bridges/primitives}/header-chain/src/justification/verification/strict.rs (100%) rename {primitives => bridges/primitives}/header-chain/src/lib.rs (100%) rename {primitives => bridges/primitives}/header-chain/src/storage_keys.rs (100%) rename {primitives => bridges/primitives}/header-chain/tests/implementation_match.rs (100%) rename {primitives => bridges/primitives}/header-chain/tests/justification/equivocation.rs (100%) rename {primitives => bridges/primitives}/header-chain/tests/justification/optimizer.rs (100%) rename {primitives => bridges/primitives}/header-chain/tests/justification/strict.rs (100%) rename {primitives => bridges/primitives}/header-chain/tests/tests.rs (100%) rename {primitives => bridges/primitives}/messages/Cargo.toml (100%) rename {primitives => bridges/primitives}/messages/src/lib.rs (100%) rename {primitives => bridges/primitives}/messages/src/source_chain.rs (100%) rename {primitives => bridges/primitives}/messages/src/storage_keys.rs (100%) rename {primitives => bridges/primitives}/messages/src/target_chain.rs (100%) rename {primitives => bridges/primitives}/parachains/Cargo.toml (100%) rename {primitives => bridges/primitives}/parachains/src/lib.rs (100%) rename {primitives => bridges/primitives}/polkadot-core/Cargo.toml (100%) rename {primitives => bridges/primitives}/polkadot-core/src/lib.rs (100%) rename {primitives => bridges/primitives}/polkadot-core/src/parachains.rs (100%) rename {primitives => bridges/primitives}/relayers/Cargo.toml (100%) rename {primitives => bridges/primitives}/relayers/src/lib.rs (100%) rename {primitives => bridges/primitives}/relayers/src/registration.rs (100%) rename {primitives => bridges/primitives}/runtime/Cargo.toml (100%) rename {primitives => bridges/primitives}/runtime/src/chain.rs (100%) rename {primitives => bridges/primitives}/runtime/src/extensions.rs (100%) rename {primitives => bridges/primitives}/runtime/src/lib.rs (100%) rename {primitives => bridges/primitives}/runtime/src/messages.rs (100%) rename {primitives => bridges/primitives}/runtime/src/storage_proof.rs (100%) rename {primitives => bridges/primitives}/runtime/src/storage_types.rs (100%) rename {primitives => bridges/primitives}/test-utils/Cargo.toml (100%) rename {primitives => bridges/primitives}/test-utils/src/keyring.rs (100%) rename {primitives => bridges/primitives}/test-utils/src/lib.rs (100%) rename {primitives => bridges/primitives}/xcm-bridge-hub-router/Cargo.toml (100%) rename {primitives => bridges/primitives}/xcm-bridge-hub-router/src/lib.rs (100%) rename {primitives => bridges/primitives}/xcm-bridge-hub/Cargo.toml (100%) rename {primitives => bridges/primitives}/xcm-bridge-hub/src/lib.rs (100%) rename {relays => bridges/relays}/client-substrate/Cargo.toml (100%) rename {relays => bridges/relays}/client-substrate/src/calls.rs (100%) rename {relays => bridges/relays}/client-substrate/src/chain.rs (100%) rename {relays => bridges/relays}/client-substrate/src/client.rs (100%) rename {relays => bridges/relays}/client-substrate/src/error.rs (100%) rename {relays => bridges/relays}/client-substrate/src/guard.rs (100%) rename {relays => bridges/relays}/client-substrate/src/lib.rs (100%) rename {relays => bridges/relays}/client-substrate/src/metrics/float_storage_value.rs (100%) rename {relays => bridges/relays}/client-substrate/src/metrics/mod.rs (100%) rename {relays => bridges/relays}/client-substrate/src/rpc.rs (100%) rename {relays => bridges/relays}/client-substrate/src/sync_header.rs (100%) rename {relays => bridges/relays}/client-substrate/src/test_chain.rs (100%) rename {relays => bridges/relays}/client-substrate/src/transaction_tracker.rs (100%) rename {relays => bridges/relays}/equivocation/Cargo.toml (100%) rename {relays => bridges/relays}/equivocation/src/block_checker.rs (100%) rename {relays => bridges/relays}/equivocation/src/equivocation_loop.rs (100%) rename {relays => bridges/relays}/equivocation/src/lib.rs (100%) rename {relays => bridges/relays}/equivocation/src/mock.rs (100%) rename {relays => bridges/relays}/equivocation/src/reporter.rs (100%) rename {relays => bridges/relays}/finality/Cargo.toml (100%) rename {relays => bridges/relays}/finality/README.md (100%) rename {relays => bridges/relays}/finality/src/base.rs (100%) rename {relays => bridges/relays}/finality/src/finality_loop.rs (100%) rename {relays => bridges/relays}/finality/src/finality_proofs.rs (100%) rename {relays => bridges/relays}/finality/src/headers.rs (100%) rename {relays => bridges/relays}/finality/src/lib.rs (100%) rename {relays => bridges/relays}/finality/src/mock.rs (100%) rename {relays => bridges/relays}/finality/src/sync_loop_metrics.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/Cargo.toml (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/bridge.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/chain_schema.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/detect_equivocations.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/init_bridge.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_headers.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_messages.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/cli/relay_parachains.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/equivocation/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/equivocation/source.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/equivocation/target.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/error.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/finality/initialize.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/finality/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/finality/source.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/finality/target.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/finality_base/engine.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/finality_base/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/lib.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/messages_lane.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/messages_metrics.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/messages_source.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/messages_target.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/on_demand/headers.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/on_demand/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/on_demand/parachains.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/parachains/mod.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/parachains/source.rs (100%) rename {relays => bridges/relays}/lib-substrate-relay/src/parachains/target.rs (100%) rename {relays => bridges/relays}/messages/Cargo.toml (100%) rename {relays => bridges/relays}/messages/src/lib.rs (100%) rename {relays => bridges/relays}/messages/src/message_lane.rs (100%) rename {relays => bridges/relays}/messages/src/message_lane_loop.rs (100%) rename {relays => bridges/relays}/messages/src/message_race_delivery.rs (100%) rename {relays => bridges/relays}/messages/src/message_race_limits.rs (100%) rename {relays => bridges/relays}/messages/src/message_race_loop.rs (100%) rename {relays => bridges/relays}/messages/src/message_race_receiving.rs (100%) rename {relays => bridges/relays}/messages/src/message_race_strategy.rs (100%) rename {relays => bridges/relays}/messages/src/metrics.rs (100%) rename {relays => bridges/relays}/parachains/Cargo.toml (100%) rename {relays => bridges/relays}/parachains/README.md (100%) rename {relays => bridges/relays}/parachains/src/lib.rs (100%) rename {relays => bridges/relays}/parachains/src/parachains_loop.rs (100%) rename {relays => bridges/relays}/parachains/src/parachains_loop_metrics.rs (100%) rename {relays => bridges/relays}/utils/Cargo.toml (100%) rename {relays => bridges/relays}/utils/src/error.rs (100%) rename {relays => bridges/relays}/utils/src/initialize.rs (100%) rename {relays => bridges/relays}/utils/src/lib.rs (100%) rename {relays => bridges/relays}/utils/src/metrics.rs (100%) rename {relays => bridges/relays}/utils/src/metrics/float_json_value.rs (100%) rename {relays => bridges/relays}/utils/src/metrics/global.rs (100%) rename {relays => bridges/relays}/utils/src/relay_loop.rs (100%) rename {testing => bridges/testing}/README.md (100%) rename {testing => bridges/testing}/environments/rococo-westend/bridge_hub_rococo_local_network.toml (100%) rename {testing => bridges/testing}/environments/rococo-westend/bridge_hub_westend_local_network.toml (100%) rename {testing => bridges/testing}/environments/rococo-westend/bridges_rococo_westend.sh (100%) rename {testing => bridges/testing}/environments/rococo-westend/helper.sh (100%) rename {testing => bridges/testing}/environments/rococo-westend/rococo-init.zndsl (100%) rename {testing => bridges/testing}/environments/rococo-westend/rococo.zndsl (100%) rename {testing => bridges/testing}/environments/rococo-westend/spawn.sh (100%) rename {testing => bridges/testing}/environments/rococo-westend/start_relayer.sh (100%) rename {testing => bridges/testing}/environments/rococo-westend/westend-init.zndsl (100%) rename {testing => bridges/testing}/environments/rococo-westend/westend.zndsl (100%) rename {testing => bridges/testing}/framework/js-helpers/best-finalized-header-at-bridged-chain.js (100%) rename {testing => bridges/testing}/framework/js-helpers/chains/rococo-at-westend.js (100%) rename {testing => bridges/testing}/framework/js-helpers/chains/westend-at-rococo.js (100%) rename {testing => bridges/testing}/framework/js-helpers/native-assets-balance-increased.js (100%) rename {testing => bridges/testing}/framework/js-helpers/only-mandatory-headers-synced-when-idle.js (100%) rename {testing => bridges/testing}/framework/js-helpers/only-required-headers-synced-when-idle.js (100%) rename {testing => bridges/testing}/framework/js-helpers/relayer-rewards.js (100%) rename {testing => bridges/testing}/framework/js-helpers/utils.js (100%) rename {testing => bridges/testing}/framework/js-helpers/wait-hrmp-channel-opened.js (100%) rename {testing => bridges/testing}/framework/js-helpers/wrapped-assets-balance.js (100%) rename {testing => bridges/testing}/framework/utils/bridges.sh (100%) rename {testing => bridges/testing}/framework/utils/common.sh (100%) rename {testing => bridges/testing}/framework/utils/generate_hex_encoded_call/index.js (100%) rename {testing => bridges/testing}/framework/utils/generate_hex_encoded_call/package-lock.json (100%) rename {testing => bridges/testing}/framework/utils/generate_hex_encoded_call/package.json (100%) rename {testing => bridges/testing}/framework/utils/zombienet.sh (100%) rename {testing => bridges/testing}/run-new-test.sh (100%) rename {testing => bridges/testing}/run-tests.sh (100%) rename {testing => bridges/testing}/scripts/invoke-script.sh (100%) rename {testing => bridges/testing}/scripts/start-relayer.sh (100%) rename {testing => bridges/testing}/scripts/sync-exit.sh (100%) rename {testing => bridges/testing}/tests/0001-asset-transfer/roc-reaches-westend.zndsl (100%) rename {testing => bridges/testing}/tests/0001-asset-transfer/run.sh (100%) rename {testing => bridges/testing}/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl (100%) rename {testing => bridges/testing}/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl (100%) rename {testing => bridges/testing}/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl (100%) rename {testing => bridges/testing}/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl (100%) rename {testing => bridges/testing}/tests/0002-mandatory-headers-synced-while-idle/run.sh (100%) rename {testing => bridges/testing}/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl (100%) rename {testing => bridges/testing}/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl (100%) rename {testing => bridges/testing}/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl (100%) diff --git a/CODE_OF_CONDUCT.md b/bridges/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to bridges/CODE_OF_CONDUCT.md diff --git a/LICENSE b/bridges/LICENSE similarity index 100% rename from LICENSE rename to bridges/LICENSE diff --git a/README.md b/bridges/README.md similarity index 100% rename from README.md rename to bridges/README.md diff --git a/SECURITY.md b/bridges/SECURITY.md similarity index 100% rename from SECURITY.md rename to bridges/SECURITY.md diff --git a/bin/runtime-common/Cargo.toml b/bridges/bin/runtime-common/Cargo.toml similarity index 100% rename from bin/runtime-common/Cargo.toml rename to bridges/bin/runtime-common/Cargo.toml diff --git a/bin/runtime-common/src/integrity.rs b/bridges/bin/runtime-common/src/integrity.rs similarity index 100% rename from bin/runtime-common/src/integrity.rs rename to bridges/bin/runtime-common/src/integrity.rs diff --git a/bin/runtime-common/src/lib.rs b/bridges/bin/runtime-common/src/lib.rs similarity index 100% rename from bin/runtime-common/src/lib.rs rename to bridges/bin/runtime-common/src/lib.rs diff --git a/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs similarity index 100% rename from bin/runtime-common/src/messages.rs rename to bridges/bin/runtime-common/src/messages.rs diff --git a/bin/runtime-common/src/messages_api.rs b/bridges/bin/runtime-common/src/messages_api.rs similarity index 100% rename from bin/runtime-common/src/messages_api.rs rename to bridges/bin/runtime-common/src/messages_api.rs diff --git a/bin/runtime-common/src/messages_benchmarking.rs b/bridges/bin/runtime-common/src/messages_benchmarking.rs similarity index 100% rename from bin/runtime-common/src/messages_benchmarking.rs rename to bridges/bin/runtime-common/src/messages_benchmarking.rs diff --git a/bin/runtime-common/src/messages_call_ext.rs b/bridges/bin/runtime-common/src/messages_call_ext.rs similarity index 100% rename from bin/runtime-common/src/messages_call_ext.rs rename to bridges/bin/runtime-common/src/messages_call_ext.rs diff --git a/bin/runtime-common/src/messages_generation.rs b/bridges/bin/runtime-common/src/messages_generation.rs similarity index 100% rename from bin/runtime-common/src/messages_generation.rs rename to bridges/bin/runtime-common/src/messages_generation.rs diff --git a/bin/runtime-common/src/messages_xcm_extension.rs b/bridges/bin/runtime-common/src/messages_xcm_extension.rs similarity index 100% rename from bin/runtime-common/src/messages_xcm_extension.rs rename to bridges/bin/runtime-common/src/messages_xcm_extension.rs diff --git a/bin/runtime-common/src/mock.rs b/bridges/bin/runtime-common/src/mock.rs similarity index 100% rename from bin/runtime-common/src/mock.rs rename to bridges/bin/runtime-common/src/mock.rs diff --git a/bin/runtime-common/src/parachains_benchmarking.rs b/bridges/bin/runtime-common/src/parachains_benchmarking.rs similarity index 100% rename from bin/runtime-common/src/parachains_benchmarking.rs rename to bridges/bin/runtime-common/src/parachains_benchmarking.rs diff --git a/bin/runtime-common/src/priority_calculator.rs b/bridges/bin/runtime-common/src/priority_calculator.rs similarity index 100% rename from bin/runtime-common/src/priority_calculator.rs rename to bridges/bin/runtime-common/src/priority_calculator.rs diff --git a/bin/runtime-common/src/refund_relayer_extension.rs b/bridges/bin/runtime-common/src/refund_relayer_extension.rs similarity index 100% rename from bin/runtime-common/src/refund_relayer_extension.rs rename to bridges/bin/runtime-common/src/refund_relayer_extension.rs diff --git a/chains/chain-asset-hub-rococo/Cargo.toml b/bridges/chains/chain-asset-hub-rococo/Cargo.toml similarity index 100% rename from chains/chain-asset-hub-rococo/Cargo.toml rename to bridges/chains/chain-asset-hub-rococo/Cargo.toml diff --git a/chains/chain-asset-hub-rococo/src/lib.rs b/bridges/chains/chain-asset-hub-rococo/src/lib.rs similarity index 100% rename from chains/chain-asset-hub-rococo/src/lib.rs rename to bridges/chains/chain-asset-hub-rococo/src/lib.rs diff --git a/chains/chain-asset-hub-westend/Cargo.toml b/bridges/chains/chain-asset-hub-westend/Cargo.toml similarity index 100% rename from chains/chain-asset-hub-westend/Cargo.toml rename to bridges/chains/chain-asset-hub-westend/Cargo.toml diff --git a/chains/chain-asset-hub-westend/src/lib.rs b/bridges/chains/chain-asset-hub-westend/src/lib.rs similarity index 100% rename from chains/chain-asset-hub-westend/src/lib.rs rename to bridges/chains/chain-asset-hub-westend/src/lib.rs diff --git a/chains/chain-bridge-hub-cumulus/Cargo.toml b/bridges/chains/chain-bridge-hub-cumulus/Cargo.toml similarity index 100% rename from chains/chain-bridge-hub-cumulus/Cargo.toml rename to bridges/chains/chain-bridge-hub-cumulus/Cargo.toml diff --git a/chains/chain-bridge-hub-cumulus/src/lib.rs b/bridges/chains/chain-bridge-hub-cumulus/src/lib.rs similarity index 100% rename from chains/chain-bridge-hub-cumulus/src/lib.rs rename to bridges/chains/chain-bridge-hub-cumulus/src/lib.rs diff --git a/chains/chain-bridge-hub-kusama/Cargo.toml b/bridges/chains/chain-bridge-hub-kusama/Cargo.toml similarity index 100% rename from chains/chain-bridge-hub-kusama/Cargo.toml rename to bridges/chains/chain-bridge-hub-kusama/Cargo.toml diff --git a/chains/chain-bridge-hub-kusama/src/lib.rs b/bridges/chains/chain-bridge-hub-kusama/src/lib.rs similarity index 100% rename from chains/chain-bridge-hub-kusama/src/lib.rs rename to bridges/chains/chain-bridge-hub-kusama/src/lib.rs diff --git a/chains/chain-bridge-hub-polkadot/Cargo.toml b/bridges/chains/chain-bridge-hub-polkadot/Cargo.toml similarity index 100% rename from chains/chain-bridge-hub-polkadot/Cargo.toml rename to bridges/chains/chain-bridge-hub-polkadot/Cargo.toml diff --git a/chains/chain-bridge-hub-polkadot/src/lib.rs b/bridges/chains/chain-bridge-hub-polkadot/src/lib.rs similarity index 100% rename from chains/chain-bridge-hub-polkadot/src/lib.rs rename to bridges/chains/chain-bridge-hub-polkadot/src/lib.rs diff --git a/chains/chain-bridge-hub-rococo/Cargo.toml b/bridges/chains/chain-bridge-hub-rococo/Cargo.toml similarity index 100% rename from chains/chain-bridge-hub-rococo/Cargo.toml rename to bridges/chains/chain-bridge-hub-rococo/Cargo.toml diff --git a/chains/chain-bridge-hub-rococo/src/lib.rs b/bridges/chains/chain-bridge-hub-rococo/src/lib.rs similarity index 100% rename from chains/chain-bridge-hub-rococo/src/lib.rs rename to bridges/chains/chain-bridge-hub-rococo/src/lib.rs diff --git a/chains/chain-bridge-hub-westend/Cargo.toml b/bridges/chains/chain-bridge-hub-westend/Cargo.toml similarity index 100% rename from chains/chain-bridge-hub-westend/Cargo.toml rename to bridges/chains/chain-bridge-hub-westend/Cargo.toml diff --git a/chains/chain-bridge-hub-westend/src/lib.rs b/bridges/chains/chain-bridge-hub-westend/src/lib.rs similarity index 100% rename from chains/chain-bridge-hub-westend/src/lib.rs rename to bridges/chains/chain-bridge-hub-westend/src/lib.rs diff --git a/chains/chain-kusama/Cargo.toml b/bridges/chains/chain-kusama/Cargo.toml similarity index 100% rename from chains/chain-kusama/Cargo.toml rename to bridges/chains/chain-kusama/Cargo.toml diff --git a/chains/chain-kusama/src/lib.rs b/bridges/chains/chain-kusama/src/lib.rs similarity index 100% rename from chains/chain-kusama/src/lib.rs rename to bridges/chains/chain-kusama/src/lib.rs diff --git a/chains/chain-polkadot-bulletin/Cargo.toml b/bridges/chains/chain-polkadot-bulletin/Cargo.toml similarity index 100% rename from chains/chain-polkadot-bulletin/Cargo.toml rename to bridges/chains/chain-polkadot-bulletin/Cargo.toml diff --git a/chains/chain-polkadot-bulletin/src/lib.rs b/bridges/chains/chain-polkadot-bulletin/src/lib.rs similarity index 100% rename from chains/chain-polkadot-bulletin/src/lib.rs rename to bridges/chains/chain-polkadot-bulletin/src/lib.rs diff --git a/chains/chain-polkadot/Cargo.toml b/bridges/chains/chain-polkadot/Cargo.toml similarity index 100% rename from chains/chain-polkadot/Cargo.toml rename to bridges/chains/chain-polkadot/Cargo.toml diff --git a/chains/chain-polkadot/src/lib.rs b/bridges/chains/chain-polkadot/src/lib.rs similarity index 100% rename from chains/chain-polkadot/src/lib.rs rename to bridges/chains/chain-polkadot/src/lib.rs diff --git a/chains/chain-rococo/Cargo.toml b/bridges/chains/chain-rococo/Cargo.toml similarity index 100% rename from chains/chain-rococo/Cargo.toml rename to bridges/chains/chain-rococo/Cargo.toml diff --git a/chains/chain-rococo/src/lib.rs b/bridges/chains/chain-rococo/src/lib.rs similarity index 100% rename from chains/chain-rococo/src/lib.rs rename to bridges/chains/chain-rococo/src/lib.rs diff --git a/chains/chain-westend/Cargo.toml b/bridges/chains/chain-westend/Cargo.toml similarity index 100% rename from chains/chain-westend/Cargo.toml rename to bridges/chains/chain-westend/Cargo.toml diff --git a/chains/chain-westend/src/lib.rs b/bridges/chains/chain-westend/src/lib.rs similarity index 100% rename from chains/chain-westend/src/lib.rs rename to bridges/chains/chain-westend/src/lib.rs diff --git a/docs/bridge-relayers-claim-rewards.png b/bridges/docs/bridge-relayers-claim-rewards.png similarity index 100% rename from docs/bridge-relayers-claim-rewards.png rename to bridges/docs/bridge-relayers-claim-rewards.png diff --git a/docs/bridge-relayers-deregister.png b/bridges/docs/bridge-relayers-deregister.png similarity index 100% rename from docs/bridge-relayers-deregister.png rename to bridges/docs/bridge-relayers-deregister.png diff --git a/docs/bridge-relayers-register.png b/bridges/docs/bridge-relayers-register.png similarity index 100% rename from docs/bridge-relayers-register.png rename to bridges/docs/bridge-relayers-register.png diff --git a/docs/complex-relay.html b/bridges/docs/complex-relay.html similarity index 100% rename from docs/complex-relay.html rename to bridges/docs/complex-relay.html diff --git a/docs/grandpa-finality-relay.html b/bridges/docs/grandpa-finality-relay.html similarity index 100% rename from docs/grandpa-finality-relay.html rename to bridges/docs/grandpa-finality-relay.html diff --git a/docs/high-level-overview.md b/bridges/docs/high-level-overview.md similarity index 100% rename from docs/high-level-overview.md rename to bridges/docs/high-level-overview.md diff --git a/docs/messages-relay.html b/bridges/docs/messages-relay.html similarity index 100% rename from docs/messages-relay.html rename to bridges/docs/messages-relay.html diff --git a/docs/parachains-finality-relay.html b/bridges/docs/parachains-finality-relay.html similarity index 100% rename from docs/parachains-finality-relay.html rename to bridges/docs/parachains-finality-relay.html diff --git a/docs/polkadot-kusama-bridge-overview.md b/bridges/docs/polkadot-kusama-bridge-overview.md similarity index 100% rename from docs/polkadot-kusama-bridge-overview.md rename to bridges/docs/polkadot-kusama-bridge-overview.md diff --git a/docs/polkadot-kusama-bridge.html b/bridges/docs/polkadot-kusama-bridge.html similarity index 100% rename from docs/polkadot-kusama-bridge.html rename to bridges/docs/polkadot-kusama-bridge.html diff --git a/docs/running-relayer.md b/bridges/docs/running-relayer.md similarity index 100% rename from docs/running-relayer.md rename to bridges/docs/running-relayer.md diff --git a/modules/beefy/Cargo.toml b/bridges/modules/beefy/Cargo.toml similarity index 100% rename from modules/beefy/Cargo.toml rename to bridges/modules/beefy/Cargo.toml diff --git a/modules/beefy/src/lib.rs b/bridges/modules/beefy/src/lib.rs similarity index 100% rename from modules/beefy/src/lib.rs rename to bridges/modules/beefy/src/lib.rs diff --git a/modules/beefy/src/mock.rs b/bridges/modules/beefy/src/mock.rs similarity index 100% rename from modules/beefy/src/mock.rs rename to bridges/modules/beefy/src/mock.rs diff --git a/modules/beefy/src/mock_chain.rs b/bridges/modules/beefy/src/mock_chain.rs similarity index 100% rename from modules/beefy/src/mock_chain.rs rename to bridges/modules/beefy/src/mock_chain.rs diff --git a/modules/beefy/src/utils.rs b/bridges/modules/beefy/src/utils.rs similarity index 100% rename from modules/beefy/src/utils.rs rename to bridges/modules/beefy/src/utils.rs diff --git a/modules/grandpa/Cargo.toml b/bridges/modules/grandpa/Cargo.toml similarity index 100% rename from modules/grandpa/Cargo.toml rename to bridges/modules/grandpa/Cargo.toml diff --git a/modules/grandpa/README.md b/bridges/modules/grandpa/README.md similarity index 100% rename from modules/grandpa/README.md rename to bridges/modules/grandpa/README.md diff --git a/modules/grandpa/src/benchmarking.rs b/bridges/modules/grandpa/src/benchmarking.rs similarity index 100% rename from modules/grandpa/src/benchmarking.rs rename to bridges/modules/grandpa/src/benchmarking.rs diff --git a/modules/grandpa/src/call_ext.rs b/bridges/modules/grandpa/src/call_ext.rs similarity index 100% rename from modules/grandpa/src/call_ext.rs rename to bridges/modules/grandpa/src/call_ext.rs diff --git a/modules/grandpa/src/lib.rs b/bridges/modules/grandpa/src/lib.rs similarity index 100% rename from modules/grandpa/src/lib.rs rename to bridges/modules/grandpa/src/lib.rs diff --git a/modules/grandpa/src/mock.rs b/bridges/modules/grandpa/src/mock.rs similarity index 100% rename from modules/grandpa/src/mock.rs rename to bridges/modules/grandpa/src/mock.rs diff --git a/modules/grandpa/src/storage_types.rs b/bridges/modules/grandpa/src/storage_types.rs similarity index 100% rename from modules/grandpa/src/storage_types.rs rename to bridges/modules/grandpa/src/storage_types.rs diff --git a/modules/grandpa/src/weights.rs b/bridges/modules/grandpa/src/weights.rs similarity index 100% rename from modules/grandpa/src/weights.rs rename to bridges/modules/grandpa/src/weights.rs diff --git a/modules/messages/Cargo.toml b/bridges/modules/messages/Cargo.toml similarity index 100% rename from modules/messages/Cargo.toml rename to bridges/modules/messages/Cargo.toml diff --git a/modules/messages/README.md b/bridges/modules/messages/README.md similarity index 100% rename from modules/messages/README.md rename to bridges/modules/messages/README.md diff --git a/modules/messages/src/benchmarking.rs b/bridges/modules/messages/src/benchmarking.rs similarity index 100% rename from modules/messages/src/benchmarking.rs rename to bridges/modules/messages/src/benchmarking.rs diff --git a/modules/messages/src/inbound_lane.rs b/bridges/modules/messages/src/inbound_lane.rs similarity index 100% rename from modules/messages/src/inbound_lane.rs rename to bridges/modules/messages/src/inbound_lane.rs diff --git a/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs similarity index 100% rename from modules/messages/src/lib.rs rename to bridges/modules/messages/src/lib.rs diff --git a/modules/messages/src/mock.rs b/bridges/modules/messages/src/mock.rs similarity index 100% rename from modules/messages/src/mock.rs rename to bridges/modules/messages/src/mock.rs diff --git a/modules/messages/src/outbound_lane.rs b/bridges/modules/messages/src/outbound_lane.rs similarity index 100% rename from modules/messages/src/outbound_lane.rs rename to bridges/modules/messages/src/outbound_lane.rs diff --git a/modules/messages/src/weights.rs b/bridges/modules/messages/src/weights.rs similarity index 100% rename from modules/messages/src/weights.rs rename to bridges/modules/messages/src/weights.rs diff --git a/modules/messages/src/weights_ext.rs b/bridges/modules/messages/src/weights_ext.rs similarity index 100% rename from modules/messages/src/weights_ext.rs rename to bridges/modules/messages/src/weights_ext.rs diff --git a/modules/parachains/Cargo.toml b/bridges/modules/parachains/Cargo.toml similarity index 100% rename from modules/parachains/Cargo.toml rename to bridges/modules/parachains/Cargo.toml diff --git a/modules/parachains/README.md b/bridges/modules/parachains/README.md similarity index 100% rename from modules/parachains/README.md rename to bridges/modules/parachains/README.md diff --git a/modules/parachains/src/benchmarking.rs b/bridges/modules/parachains/src/benchmarking.rs similarity index 100% rename from modules/parachains/src/benchmarking.rs rename to bridges/modules/parachains/src/benchmarking.rs diff --git a/modules/parachains/src/call_ext.rs b/bridges/modules/parachains/src/call_ext.rs similarity index 100% rename from modules/parachains/src/call_ext.rs rename to bridges/modules/parachains/src/call_ext.rs diff --git a/modules/parachains/src/lib.rs b/bridges/modules/parachains/src/lib.rs similarity index 100% rename from modules/parachains/src/lib.rs rename to bridges/modules/parachains/src/lib.rs diff --git a/modules/parachains/src/mock.rs b/bridges/modules/parachains/src/mock.rs similarity index 100% rename from modules/parachains/src/mock.rs rename to bridges/modules/parachains/src/mock.rs diff --git a/modules/parachains/src/weights.rs b/bridges/modules/parachains/src/weights.rs similarity index 100% rename from modules/parachains/src/weights.rs rename to bridges/modules/parachains/src/weights.rs diff --git a/modules/parachains/src/weights_ext.rs b/bridges/modules/parachains/src/weights_ext.rs similarity index 100% rename from modules/parachains/src/weights_ext.rs rename to bridges/modules/parachains/src/weights_ext.rs diff --git a/modules/relayers/Cargo.toml b/bridges/modules/relayers/Cargo.toml similarity index 100% rename from modules/relayers/Cargo.toml rename to bridges/modules/relayers/Cargo.toml diff --git a/modules/relayers/README.md b/bridges/modules/relayers/README.md similarity index 100% rename from modules/relayers/README.md rename to bridges/modules/relayers/README.md diff --git a/modules/relayers/src/benchmarking.rs b/bridges/modules/relayers/src/benchmarking.rs similarity index 100% rename from modules/relayers/src/benchmarking.rs rename to bridges/modules/relayers/src/benchmarking.rs diff --git a/modules/relayers/src/lib.rs b/bridges/modules/relayers/src/lib.rs similarity index 100% rename from modules/relayers/src/lib.rs rename to bridges/modules/relayers/src/lib.rs diff --git a/modules/relayers/src/mock.rs b/bridges/modules/relayers/src/mock.rs similarity index 100% rename from modules/relayers/src/mock.rs rename to bridges/modules/relayers/src/mock.rs diff --git a/modules/relayers/src/payment_adapter.rs b/bridges/modules/relayers/src/payment_adapter.rs similarity index 100% rename from modules/relayers/src/payment_adapter.rs rename to bridges/modules/relayers/src/payment_adapter.rs diff --git a/modules/relayers/src/stake_adapter.rs b/bridges/modules/relayers/src/stake_adapter.rs similarity index 100% rename from modules/relayers/src/stake_adapter.rs rename to bridges/modules/relayers/src/stake_adapter.rs diff --git a/modules/relayers/src/weights.rs b/bridges/modules/relayers/src/weights.rs similarity index 100% rename from modules/relayers/src/weights.rs rename to bridges/modules/relayers/src/weights.rs diff --git a/modules/relayers/src/weights_ext.rs b/bridges/modules/relayers/src/weights_ext.rs similarity index 100% rename from modules/relayers/src/weights_ext.rs rename to bridges/modules/relayers/src/weights_ext.rs diff --git a/modules/xcm-bridge-hub-router/Cargo.toml b/bridges/modules/xcm-bridge-hub-router/Cargo.toml similarity index 100% rename from modules/xcm-bridge-hub-router/Cargo.toml rename to bridges/modules/xcm-bridge-hub-router/Cargo.toml diff --git a/modules/xcm-bridge-hub-router/src/benchmarking.rs b/bridges/modules/xcm-bridge-hub-router/src/benchmarking.rs similarity index 100% rename from modules/xcm-bridge-hub-router/src/benchmarking.rs rename to bridges/modules/xcm-bridge-hub-router/src/benchmarking.rs diff --git a/modules/xcm-bridge-hub-router/src/lib.rs b/bridges/modules/xcm-bridge-hub-router/src/lib.rs similarity index 100% rename from modules/xcm-bridge-hub-router/src/lib.rs rename to bridges/modules/xcm-bridge-hub-router/src/lib.rs diff --git a/modules/xcm-bridge-hub-router/src/mock.rs b/bridges/modules/xcm-bridge-hub-router/src/mock.rs similarity index 100% rename from modules/xcm-bridge-hub-router/src/mock.rs rename to bridges/modules/xcm-bridge-hub-router/src/mock.rs diff --git a/modules/xcm-bridge-hub-router/src/weights.rs b/bridges/modules/xcm-bridge-hub-router/src/weights.rs similarity index 100% rename from modules/xcm-bridge-hub-router/src/weights.rs rename to bridges/modules/xcm-bridge-hub-router/src/weights.rs diff --git a/modules/xcm-bridge-hub/Cargo.toml b/bridges/modules/xcm-bridge-hub/Cargo.toml similarity index 100% rename from modules/xcm-bridge-hub/Cargo.toml rename to bridges/modules/xcm-bridge-hub/Cargo.toml diff --git a/modules/xcm-bridge-hub/src/exporter.rs b/bridges/modules/xcm-bridge-hub/src/exporter.rs similarity index 100% rename from modules/xcm-bridge-hub/src/exporter.rs rename to bridges/modules/xcm-bridge-hub/src/exporter.rs diff --git a/modules/xcm-bridge-hub/src/lib.rs b/bridges/modules/xcm-bridge-hub/src/lib.rs similarity index 100% rename from modules/xcm-bridge-hub/src/lib.rs rename to bridges/modules/xcm-bridge-hub/src/lib.rs diff --git a/modules/xcm-bridge-hub/src/mock.rs b/bridges/modules/xcm-bridge-hub/src/mock.rs similarity index 100% rename from modules/xcm-bridge-hub/src/mock.rs rename to bridges/modules/xcm-bridge-hub/src/mock.rs diff --git a/primitives/beefy/Cargo.toml b/bridges/primitives/beefy/Cargo.toml similarity index 100% rename from primitives/beefy/Cargo.toml rename to bridges/primitives/beefy/Cargo.toml diff --git a/primitives/beefy/src/lib.rs b/bridges/primitives/beefy/src/lib.rs similarity index 100% rename from primitives/beefy/src/lib.rs rename to bridges/primitives/beefy/src/lib.rs diff --git a/primitives/header-chain/Cargo.toml b/bridges/primitives/header-chain/Cargo.toml similarity index 100% rename from primitives/header-chain/Cargo.toml rename to bridges/primitives/header-chain/Cargo.toml diff --git a/primitives/header-chain/src/justification/mod.rs b/bridges/primitives/header-chain/src/justification/mod.rs similarity index 100% rename from primitives/header-chain/src/justification/mod.rs rename to bridges/primitives/header-chain/src/justification/mod.rs diff --git a/primitives/header-chain/src/justification/verification/equivocation.rs b/bridges/primitives/header-chain/src/justification/verification/equivocation.rs similarity index 100% rename from primitives/header-chain/src/justification/verification/equivocation.rs rename to bridges/primitives/header-chain/src/justification/verification/equivocation.rs diff --git a/primitives/header-chain/src/justification/verification/mod.rs b/bridges/primitives/header-chain/src/justification/verification/mod.rs similarity index 100% rename from primitives/header-chain/src/justification/verification/mod.rs rename to bridges/primitives/header-chain/src/justification/verification/mod.rs diff --git a/primitives/header-chain/src/justification/verification/optimizer.rs b/bridges/primitives/header-chain/src/justification/verification/optimizer.rs similarity index 100% rename from primitives/header-chain/src/justification/verification/optimizer.rs rename to bridges/primitives/header-chain/src/justification/verification/optimizer.rs diff --git a/primitives/header-chain/src/justification/verification/strict.rs b/bridges/primitives/header-chain/src/justification/verification/strict.rs similarity index 100% rename from primitives/header-chain/src/justification/verification/strict.rs rename to bridges/primitives/header-chain/src/justification/verification/strict.rs diff --git a/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs similarity index 100% rename from primitives/header-chain/src/lib.rs rename to bridges/primitives/header-chain/src/lib.rs diff --git a/primitives/header-chain/src/storage_keys.rs b/bridges/primitives/header-chain/src/storage_keys.rs similarity index 100% rename from primitives/header-chain/src/storage_keys.rs rename to bridges/primitives/header-chain/src/storage_keys.rs diff --git a/primitives/header-chain/tests/implementation_match.rs b/bridges/primitives/header-chain/tests/implementation_match.rs similarity index 100% rename from primitives/header-chain/tests/implementation_match.rs rename to bridges/primitives/header-chain/tests/implementation_match.rs diff --git a/primitives/header-chain/tests/justification/equivocation.rs b/bridges/primitives/header-chain/tests/justification/equivocation.rs similarity index 100% rename from primitives/header-chain/tests/justification/equivocation.rs rename to bridges/primitives/header-chain/tests/justification/equivocation.rs diff --git a/primitives/header-chain/tests/justification/optimizer.rs b/bridges/primitives/header-chain/tests/justification/optimizer.rs similarity index 100% rename from primitives/header-chain/tests/justification/optimizer.rs rename to bridges/primitives/header-chain/tests/justification/optimizer.rs diff --git a/primitives/header-chain/tests/justification/strict.rs b/bridges/primitives/header-chain/tests/justification/strict.rs similarity index 100% rename from primitives/header-chain/tests/justification/strict.rs rename to bridges/primitives/header-chain/tests/justification/strict.rs diff --git a/primitives/header-chain/tests/tests.rs b/bridges/primitives/header-chain/tests/tests.rs similarity index 100% rename from primitives/header-chain/tests/tests.rs rename to bridges/primitives/header-chain/tests/tests.rs diff --git a/primitives/messages/Cargo.toml b/bridges/primitives/messages/Cargo.toml similarity index 100% rename from primitives/messages/Cargo.toml rename to bridges/primitives/messages/Cargo.toml diff --git a/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs similarity index 100% rename from primitives/messages/src/lib.rs rename to bridges/primitives/messages/src/lib.rs diff --git a/primitives/messages/src/source_chain.rs b/bridges/primitives/messages/src/source_chain.rs similarity index 100% rename from primitives/messages/src/source_chain.rs rename to bridges/primitives/messages/src/source_chain.rs diff --git a/primitives/messages/src/storage_keys.rs b/bridges/primitives/messages/src/storage_keys.rs similarity index 100% rename from primitives/messages/src/storage_keys.rs rename to bridges/primitives/messages/src/storage_keys.rs diff --git a/primitives/messages/src/target_chain.rs b/bridges/primitives/messages/src/target_chain.rs similarity index 100% rename from primitives/messages/src/target_chain.rs rename to bridges/primitives/messages/src/target_chain.rs diff --git a/primitives/parachains/Cargo.toml b/bridges/primitives/parachains/Cargo.toml similarity index 100% rename from primitives/parachains/Cargo.toml rename to bridges/primitives/parachains/Cargo.toml diff --git a/primitives/parachains/src/lib.rs b/bridges/primitives/parachains/src/lib.rs similarity index 100% rename from primitives/parachains/src/lib.rs rename to bridges/primitives/parachains/src/lib.rs diff --git a/primitives/polkadot-core/Cargo.toml b/bridges/primitives/polkadot-core/Cargo.toml similarity index 100% rename from primitives/polkadot-core/Cargo.toml rename to bridges/primitives/polkadot-core/Cargo.toml diff --git a/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs similarity index 100% rename from primitives/polkadot-core/src/lib.rs rename to bridges/primitives/polkadot-core/src/lib.rs diff --git a/primitives/polkadot-core/src/parachains.rs b/bridges/primitives/polkadot-core/src/parachains.rs similarity index 100% rename from primitives/polkadot-core/src/parachains.rs rename to bridges/primitives/polkadot-core/src/parachains.rs diff --git a/primitives/relayers/Cargo.toml b/bridges/primitives/relayers/Cargo.toml similarity index 100% rename from primitives/relayers/Cargo.toml rename to bridges/primitives/relayers/Cargo.toml diff --git a/primitives/relayers/src/lib.rs b/bridges/primitives/relayers/src/lib.rs similarity index 100% rename from primitives/relayers/src/lib.rs rename to bridges/primitives/relayers/src/lib.rs diff --git a/primitives/relayers/src/registration.rs b/bridges/primitives/relayers/src/registration.rs similarity index 100% rename from primitives/relayers/src/registration.rs rename to bridges/primitives/relayers/src/registration.rs diff --git a/primitives/runtime/Cargo.toml b/bridges/primitives/runtime/Cargo.toml similarity index 100% rename from primitives/runtime/Cargo.toml rename to bridges/primitives/runtime/Cargo.toml diff --git a/primitives/runtime/src/chain.rs b/bridges/primitives/runtime/src/chain.rs similarity index 100% rename from primitives/runtime/src/chain.rs rename to bridges/primitives/runtime/src/chain.rs diff --git a/primitives/runtime/src/extensions.rs b/bridges/primitives/runtime/src/extensions.rs similarity index 100% rename from primitives/runtime/src/extensions.rs rename to bridges/primitives/runtime/src/extensions.rs diff --git a/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs similarity index 100% rename from primitives/runtime/src/lib.rs rename to bridges/primitives/runtime/src/lib.rs diff --git a/primitives/runtime/src/messages.rs b/bridges/primitives/runtime/src/messages.rs similarity index 100% rename from primitives/runtime/src/messages.rs rename to bridges/primitives/runtime/src/messages.rs diff --git a/primitives/runtime/src/storage_proof.rs b/bridges/primitives/runtime/src/storage_proof.rs similarity index 100% rename from primitives/runtime/src/storage_proof.rs rename to bridges/primitives/runtime/src/storage_proof.rs diff --git a/primitives/runtime/src/storage_types.rs b/bridges/primitives/runtime/src/storage_types.rs similarity index 100% rename from primitives/runtime/src/storage_types.rs rename to bridges/primitives/runtime/src/storage_types.rs diff --git a/primitives/test-utils/Cargo.toml b/bridges/primitives/test-utils/Cargo.toml similarity index 100% rename from primitives/test-utils/Cargo.toml rename to bridges/primitives/test-utils/Cargo.toml diff --git a/primitives/test-utils/src/keyring.rs b/bridges/primitives/test-utils/src/keyring.rs similarity index 100% rename from primitives/test-utils/src/keyring.rs rename to bridges/primitives/test-utils/src/keyring.rs diff --git a/primitives/test-utils/src/lib.rs b/bridges/primitives/test-utils/src/lib.rs similarity index 100% rename from primitives/test-utils/src/lib.rs rename to bridges/primitives/test-utils/src/lib.rs diff --git a/primitives/xcm-bridge-hub-router/Cargo.toml b/bridges/primitives/xcm-bridge-hub-router/Cargo.toml similarity index 100% rename from primitives/xcm-bridge-hub-router/Cargo.toml rename to bridges/primitives/xcm-bridge-hub-router/Cargo.toml diff --git a/primitives/xcm-bridge-hub-router/src/lib.rs b/bridges/primitives/xcm-bridge-hub-router/src/lib.rs similarity index 100% rename from primitives/xcm-bridge-hub-router/src/lib.rs rename to bridges/primitives/xcm-bridge-hub-router/src/lib.rs diff --git a/primitives/xcm-bridge-hub/Cargo.toml b/bridges/primitives/xcm-bridge-hub/Cargo.toml similarity index 100% rename from primitives/xcm-bridge-hub/Cargo.toml rename to bridges/primitives/xcm-bridge-hub/Cargo.toml diff --git a/primitives/xcm-bridge-hub/src/lib.rs b/bridges/primitives/xcm-bridge-hub/src/lib.rs similarity index 100% rename from primitives/xcm-bridge-hub/src/lib.rs rename to bridges/primitives/xcm-bridge-hub/src/lib.rs diff --git a/relays/client-substrate/Cargo.toml b/bridges/relays/client-substrate/Cargo.toml similarity index 100% rename from relays/client-substrate/Cargo.toml rename to bridges/relays/client-substrate/Cargo.toml diff --git a/relays/client-substrate/src/calls.rs b/bridges/relays/client-substrate/src/calls.rs similarity index 100% rename from relays/client-substrate/src/calls.rs rename to bridges/relays/client-substrate/src/calls.rs diff --git a/relays/client-substrate/src/chain.rs b/bridges/relays/client-substrate/src/chain.rs similarity index 100% rename from relays/client-substrate/src/chain.rs rename to bridges/relays/client-substrate/src/chain.rs diff --git a/relays/client-substrate/src/client.rs b/bridges/relays/client-substrate/src/client.rs similarity index 100% rename from relays/client-substrate/src/client.rs rename to bridges/relays/client-substrate/src/client.rs diff --git a/relays/client-substrate/src/error.rs b/bridges/relays/client-substrate/src/error.rs similarity index 100% rename from relays/client-substrate/src/error.rs rename to bridges/relays/client-substrate/src/error.rs diff --git a/relays/client-substrate/src/guard.rs b/bridges/relays/client-substrate/src/guard.rs similarity index 100% rename from relays/client-substrate/src/guard.rs rename to bridges/relays/client-substrate/src/guard.rs diff --git a/relays/client-substrate/src/lib.rs b/bridges/relays/client-substrate/src/lib.rs similarity index 100% rename from relays/client-substrate/src/lib.rs rename to bridges/relays/client-substrate/src/lib.rs diff --git a/relays/client-substrate/src/metrics/float_storage_value.rs b/bridges/relays/client-substrate/src/metrics/float_storage_value.rs similarity index 100% rename from relays/client-substrate/src/metrics/float_storage_value.rs rename to bridges/relays/client-substrate/src/metrics/float_storage_value.rs diff --git a/relays/client-substrate/src/metrics/mod.rs b/bridges/relays/client-substrate/src/metrics/mod.rs similarity index 100% rename from relays/client-substrate/src/metrics/mod.rs rename to bridges/relays/client-substrate/src/metrics/mod.rs diff --git a/relays/client-substrate/src/rpc.rs b/bridges/relays/client-substrate/src/rpc.rs similarity index 100% rename from relays/client-substrate/src/rpc.rs rename to bridges/relays/client-substrate/src/rpc.rs diff --git a/relays/client-substrate/src/sync_header.rs b/bridges/relays/client-substrate/src/sync_header.rs similarity index 100% rename from relays/client-substrate/src/sync_header.rs rename to bridges/relays/client-substrate/src/sync_header.rs diff --git a/relays/client-substrate/src/test_chain.rs b/bridges/relays/client-substrate/src/test_chain.rs similarity index 100% rename from relays/client-substrate/src/test_chain.rs rename to bridges/relays/client-substrate/src/test_chain.rs diff --git a/relays/client-substrate/src/transaction_tracker.rs b/bridges/relays/client-substrate/src/transaction_tracker.rs similarity index 100% rename from relays/client-substrate/src/transaction_tracker.rs rename to bridges/relays/client-substrate/src/transaction_tracker.rs diff --git a/relays/equivocation/Cargo.toml b/bridges/relays/equivocation/Cargo.toml similarity index 100% rename from relays/equivocation/Cargo.toml rename to bridges/relays/equivocation/Cargo.toml diff --git a/relays/equivocation/src/block_checker.rs b/bridges/relays/equivocation/src/block_checker.rs similarity index 100% rename from relays/equivocation/src/block_checker.rs rename to bridges/relays/equivocation/src/block_checker.rs diff --git a/relays/equivocation/src/equivocation_loop.rs b/bridges/relays/equivocation/src/equivocation_loop.rs similarity index 100% rename from relays/equivocation/src/equivocation_loop.rs rename to bridges/relays/equivocation/src/equivocation_loop.rs diff --git a/relays/equivocation/src/lib.rs b/bridges/relays/equivocation/src/lib.rs similarity index 100% rename from relays/equivocation/src/lib.rs rename to bridges/relays/equivocation/src/lib.rs diff --git a/relays/equivocation/src/mock.rs b/bridges/relays/equivocation/src/mock.rs similarity index 100% rename from relays/equivocation/src/mock.rs rename to bridges/relays/equivocation/src/mock.rs diff --git a/relays/equivocation/src/reporter.rs b/bridges/relays/equivocation/src/reporter.rs similarity index 100% rename from relays/equivocation/src/reporter.rs rename to bridges/relays/equivocation/src/reporter.rs diff --git a/relays/finality/Cargo.toml b/bridges/relays/finality/Cargo.toml similarity index 100% rename from relays/finality/Cargo.toml rename to bridges/relays/finality/Cargo.toml diff --git a/relays/finality/README.md b/bridges/relays/finality/README.md similarity index 100% rename from relays/finality/README.md rename to bridges/relays/finality/README.md diff --git a/relays/finality/src/base.rs b/bridges/relays/finality/src/base.rs similarity index 100% rename from relays/finality/src/base.rs rename to bridges/relays/finality/src/base.rs diff --git a/relays/finality/src/finality_loop.rs b/bridges/relays/finality/src/finality_loop.rs similarity index 100% rename from relays/finality/src/finality_loop.rs rename to bridges/relays/finality/src/finality_loop.rs diff --git a/relays/finality/src/finality_proofs.rs b/bridges/relays/finality/src/finality_proofs.rs similarity index 100% rename from relays/finality/src/finality_proofs.rs rename to bridges/relays/finality/src/finality_proofs.rs diff --git a/relays/finality/src/headers.rs b/bridges/relays/finality/src/headers.rs similarity index 100% rename from relays/finality/src/headers.rs rename to bridges/relays/finality/src/headers.rs diff --git a/relays/finality/src/lib.rs b/bridges/relays/finality/src/lib.rs similarity index 100% rename from relays/finality/src/lib.rs rename to bridges/relays/finality/src/lib.rs diff --git a/relays/finality/src/mock.rs b/bridges/relays/finality/src/mock.rs similarity index 100% rename from relays/finality/src/mock.rs rename to bridges/relays/finality/src/mock.rs diff --git a/relays/finality/src/sync_loop_metrics.rs b/bridges/relays/finality/src/sync_loop_metrics.rs similarity index 100% rename from relays/finality/src/sync_loop_metrics.rs rename to bridges/relays/finality/src/sync_loop_metrics.rs diff --git a/relays/lib-substrate-relay/Cargo.toml b/bridges/relays/lib-substrate-relay/Cargo.toml similarity index 100% rename from relays/lib-substrate-relay/Cargo.toml rename to bridges/relays/lib-substrate-relay/Cargo.toml diff --git a/relays/lib-substrate-relay/src/cli/bridge.rs b/bridges/relays/lib-substrate-relay/src/cli/bridge.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/bridge.rs rename to bridges/relays/lib-substrate-relay/src/cli/bridge.rs diff --git a/relays/lib-substrate-relay/src/cli/chain_schema.rs b/bridges/relays/lib-substrate-relay/src/cli/chain_schema.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/chain_schema.rs rename to bridges/relays/lib-substrate-relay/src/cli/chain_schema.rs diff --git a/relays/lib-substrate-relay/src/cli/detect_equivocations.rs b/bridges/relays/lib-substrate-relay/src/cli/detect_equivocations.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/detect_equivocations.rs rename to bridges/relays/lib-substrate-relay/src/cli/detect_equivocations.rs diff --git a/relays/lib-substrate-relay/src/cli/init_bridge.rs b/bridges/relays/lib-substrate-relay/src/cli/init_bridge.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/init_bridge.rs rename to bridges/relays/lib-substrate-relay/src/cli/init_bridge.rs diff --git a/relays/lib-substrate-relay/src/cli/mod.rs b/bridges/relays/lib-substrate-relay/src/cli/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/mod.rs rename to bridges/relays/lib-substrate-relay/src/cli/mod.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_headers.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_headers.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_headers.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/mod.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/parachain_to_parachain.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_parachain.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_headers_and_messages/relay_to_relay.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_messages.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_messages.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_messages.rs diff --git a/relays/lib-substrate-relay/src/cli/relay_parachains.rs b/bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs similarity index 100% rename from relays/lib-substrate-relay/src/cli/relay_parachains.rs rename to bridges/relays/lib-substrate-relay/src/cli/relay_parachains.rs diff --git a/relays/lib-substrate-relay/src/equivocation/mod.rs b/bridges/relays/lib-substrate-relay/src/equivocation/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/equivocation/mod.rs rename to bridges/relays/lib-substrate-relay/src/equivocation/mod.rs diff --git a/relays/lib-substrate-relay/src/equivocation/source.rs b/bridges/relays/lib-substrate-relay/src/equivocation/source.rs similarity index 100% rename from relays/lib-substrate-relay/src/equivocation/source.rs rename to bridges/relays/lib-substrate-relay/src/equivocation/source.rs diff --git a/relays/lib-substrate-relay/src/equivocation/target.rs b/bridges/relays/lib-substrate-relay/src/equivocation/target.rs similarity index 100% rename from relays/lib-substrate-relay/src/equivocation/target.rs rename to bridges/relays/lib-substrate-relay/src/equivocation/target.rs diff --git a/relays/lib-substrate-relay/src/error.rs b/bridges/relays/lib-substrate-relay/src/error.rs similarity index 100% rename from relays/lib-substrate-relay/src/error.rs rename to bridges/relays/lib-substrate-relay/src/error.rs diff --git a/relays/lib-substrate-relay/src/finality/initialize.rs b/bridges/relays/lib-substrate-relay/src/finality/initialize.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality/initialize.rs rename to bridges/relays/lib-substrate-relay/src/finality/initialize.rs diff --git a/relays/lib-substrate-relay/src/finality/mod.rs b/bridges/relays/lib-substrate-relay/src/finality/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality/mod.rs rename to bridges/relays/lib-substrate-relay/src/finality/mod.rs diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/bridges/relays/lib-substrate-relay/src/finality/source.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality/source.rs rename to bridges/relays/lib-substrate-relay/src/finality/source.rs diff --git a/relays/lib-substrate-relay/src/finality/target.rs b/bridges/relays/lib-substrate-relay/src/finality/target.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality/target.rs rename to bridges/relays/lib-substrate-relay/src/finality/target.rs diff --git a/relays/lib-substrate-relay/src/finality_base/engine.rs b/bridges/relays/lib-substrate-relay/src/finality_base/engine.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality_base/engine.rs rename to bridges/relays/lib-substrate-relay/src/finality_base/engine.rs diff --git a/relays/lib-substrate-relay/src/finality_base/mod.rs b/bridges/relays/lib-substrate-relay/src/finality_base/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/finality_base/mod.rs rename to bridges/relays/lib-substrate-relay/src/finality_base/mod.rs diff --git a/relays/lib-substrate-relay/src/lib.rs b/bridges/relays/lib-substrate-relay/src/lib.rs similarity index 100% rename from relays/lib-substrate-relay/src/lib.rs rename to bridges/relays/lib-substrate-relay/src/lib.rs diff --git a/relays/lib-substrate-relay/src/messages_lane.rs b/bridges/relays/lib-substrate-relay/src/messages_lane.rs similarity index 100% rename from relays/lib-substrate-relay/src/messages_lane.rs rename to bridges/relays/lib-substrate-relay/src/messages_lane.rs diff --git a/relays/lib-substrate-relay/src/messages_metrics.rs b/bridges/relays/lib-substrate-relay/src/messages_metrics.rs similarity index 100% rename from relays/lib-substrate-relay/src/messages_metrics.rs rename to bridges/relays/lib-substrate-relay/src/messages_metrics.rs diff --git a/relays/lib-substrate-relay/src/messages_source.rs b/bridges/relays/lib-substrate-relay/src/messages_source.rs similarity index 100% rename from relays/lib-substrate-relay/src/messages_source.rs rename to bridges/relays/lib-substrate-relay/src/messages_source.rs diff --git a/relays/lib-substrate-relay/src/messages_target.rs b/bridges/relays/lib-substrate-relay/src/messages_target.rs similarity index 100% rename from relays/lib-substrate-relay/src/messages_target.rs rename to bridges/relays/lib-substrate-relay/src/messages_target.rs diff --git a/relays/lib-substrate-relay/src/on_demand/headers.rs b/bridges/relays/lib-substrate-relay/src/on_demand/headers.rs similarity index 100% rename from relays/lib-substrate-relay/src/on_demand/headers.rs rename to bridges/relays/lib-substrate-relay/src/on_demand/headers.rs diff --git a/relays/lib-substrate-relay/src/on_demand/mod.rs b/bridges/relays/lib-substrate-relay/src/on_demand/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/on_demand/mod.rs rename to bridges/relays/lib-substrate-relay/src/on_demand/mod.rs diff --git a/relays/lib-substrate-relay/src/on_demand/parachains.rs b/bridges/relays/lib-substrate-relay/src/on_demand/parachains.rs similarity index 100% rename from relays/lib-substrate-relay/src/on_demand/parachains.rs rename to bridges/relays/lib-substrate-relay/src/on_demand/parachains.rs diff --git a/relays/lib-substrate-relay/src/parachains/mod.rs b/bridges/relays/lib-substrate-relay/src/parachains/mod.rs similarity index 100% rename from relays/lib-substrate-relay/src/parachains/mod.rs rename to bridges/relays/lib-substrate-relay/src/parachains/mod.rs diff --git a/relays/lib-substrate-relay/src/parachains/source.rs b/bridges/relays/lib-substrate-relay/src/parachains/source.rs similarity index 100% rename from relays/lib-substrate-relay/src/parachains/source.rs rename to bridges/relays/lib-substrate-relay/src/parachains/source.rs diff --git a/relays/lib-substrate-relay/src/parachains/target.rs b/bridges/relays/lib-substrate-relay/src/parachains/target.rs similarity index 100% rename from relays/lib-substrate-relay/src/parachains/target.rs rename to bridges/relays/lib-substrate-relay/src/parachains/target.rs diff --git a/relays/messages/Cargo.toml b/bridges/relays/messages/Cargo.toml similarity index 100% rename from relays/messages/Cargo.toml rename to bridges/relays/messages/Cargo.toml diff --git a/relays/messages/src/lib.rs b/bridges/relays/messages/src/lib.rs similarity index 100% rename from relays/messages/src/lib.rs rename to bridges/relays/messages/src/lib.rs diff --git a/relays/messages/src/message_lane.rs b/bridges/relays/messages/src/message_lane.rs similarity index 100% rename from relays/messages/src/message_lane.rs rename to bridges/relays/messages/src/message_lane.rs diff --git a/relays/messages/src/message_lane_loop.rs b/bridges/relays/messages/src/message_lane_loop.rs similarity index 100% rename from relays/messages/src/message_lane_loop.rs rename to bridges/relays/messages/src/message_lane_loop.rs diff --git a/relays/messages/src/message_race_delivery.rs b/bridges/relays/messages/src/message_race_delivery.rs similarity index 100% rename from relays/messages/src/message_race_delivery.rs rename to bridges/relays/messages/src/message_race_delivery.rs diff --git a/relays/messages/src/message_race_limits.rs b/bridges/relays/messages/src/message_race_limits.rs similarity index 100% rename from relays/messages/src/message_race_limits.rs rename to bridges/relays/messages/src/message_race_limits.rs diff --git a/relays/messages/src/message_race_loop.rs b/bridges/relays/messages/src/message_race_loop.rs similarity index 100% rename from relays/messages/src/message_race_loop.rs rename to bridges/relays/messages/src/message_race_loop.rs diff --git a/relays/messages/src/message_race_receiving.rs b/bridges/relays/messages/src/message_race_receiving.rs similarity index 100% rename from relays/messages/src/message_race_receiving.rs rename to bridges/relays/messages/src/message_race_receiving.rs diff --git a/relays/messages/src/message_race_strategy.rs b/bridges/relays/messages/src/message_race_strategy.rs similarity index 100% rename from relays/messages/src/message_race_strategy.rs rename to bridges/relays/messages/src/message_race_strategy.rs diff --git a/relays/messages/src/metrics.rs b/bridges/relays/messages/src/metrics.rs similarity index 100% rename from relays/messages/src/metrics.rs rename to bridges/relays/messages/src/metrics.rs diff --git a/relays/parachains/Cargo.toml b/bridges/relays/parachains/Cargo.toml similarity index 100% rename from relays/parachains/Cargo.toml rename to bridges/relays/parachains/Cargo.toml diff --git a/relays/parachains/README.md b/bridges/relays/parachains/README.md similarity index 100% rename from relays/parachains/README.md rename to bridges/relays/parachains/README.md diff --git a/relays/parachains/src/lib.rs b/bridges/relays/parachains/src/lib.rs similarity index 100% rename from relays/parachains/src/lib.rs rename to bridges/relays/parachains/src/lib.rs diff --git a/relays/parachains/src/parachains_loop.rs b/bridges/relays/parachains/src/parachains_loop.rs similarity index 100% rename from relays/parachains/src/parachains_loop.rs rename to bridges/relays/parachains/src/parachains_loop.rs diff --git a/relays/parachains/src/parachains_loop_metrics.rs b/bridges/relays/parachains/src/parachains_loop_metrics.rs similarity index 100% rename from relays/parachains/src/parachains_loop_metrics.rs rename to bridges/relays/parachains/src/parachains_loop_metrics.rs diff --git a/relays/utils/Cargo.toml b/bridges/relays/utils/Cargo.toml similarity index 100% rename from relays/utils/Cargo.toml rename to bridges/relays/utils/Cargo.toml diff --git a/relays/utils/src/error.rs b/bridges/relays/utils/src/error.rs similarity index 100% rename from relays/utils/src/error.rs rename to bridges/relays/utils/src/error.rs diff --git a/relays/utils/src/initialize.rs b/bridges/relays/utils/src/initialize.rs similarity index 100% rename from relays/utils/src/initialize.rs rename to bridges/relays/utils/src/initialize.rs diff --git a/relays/utils/src/lib.rs b/bridges/relays/utils/src/lib.rs similarity index 100% rename from relays/utils/src/lib.rs rename to bridges/relays/utils/src/lib.rs diff --git a/relays/utils/src/metrics.rs b/bridges/relays/utils/src/metrics.rs similarity index 100% rename from relays/utils/src/metrics.rs rename to bridges/relays/utils/src/metrics.rs diff --git a/relays/utils/src/metrics/float_json_value.rs b/bridges/relays/utils/src/metrics/float_json_value.rs similarity index 100% rename from relays/utils/src/metrics/float_json_value.rs rename to bridges/relays/utils/src/metrics/float_json_value.rs diff --git a/relays/utils/src/metrics/global.rs b/bridges/relays/utils/src/metrics/global.rs similarity index 100% rename from relays/utils/src/metrics/global.rs rename to bridges/relays/utils/src/metrics/global.rs diff --git a/relays/utils/src/relay_loop.rs b/bridges/relays/utils/src/relay_loop.rs similarity index 100% rename from relays/utils/src/relay_loop.rs rename to bridges/relays/utils/src/relay_loop.rs diff --git a/testing/README.md b/bridges/testing/README.md similarity index 100% rename from testing/README.md rename to bridges/testing/README.md diff --git a/testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml b/bridges/testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml similarity index 100% rename from testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml rename to bridges/testing/environments/rococo-westend/bridge_hub_rococo_local_network.toml diff --git a/testing/environments/rococo-westend/bridge_hub_westend_local_network.toml b/bridges/testing/environments/rococo-westend/bridge_hub_westend_local_network.toml similarity index 100% rename from testing/environments/rococo-westend/bridge_hub_westend_local_network.toml rename to bridges/testing/environments/rococo-westend/bridge_hub_westend_local_network.toml diff --git a/testing/environments/rococo-westend/bridges_rococo_westend.sh b/bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh similarity index 100% rename from testing/environments/rococo-westend/bridges_rococo_westend.sh rename to bridges/testing/environments/rococo-westend/bridges_rococo_westend.sh diff --git a/testing/environments/rococo-westend/helper.sh b/bridges/testing/environments/rococo-westend/helper.sh similarity index 100% rename from testing/environments/rococo-westend/helper.sh rename to bridges/testing/environments/rococo-westend/helper.sh diff --git a/testing/environments/rococo-westend/rococo-init.zndsl b/bridges/testing/environments/rococo-westend/rococo-init.zndsl similarity index 100% rename from testing/environments/rococo-westend/rococo-init.zndsl rename to bridges/testing/environments/rococo-westend/rococo-init.zndsl diff --git a/testing/environments/rococo-westend/rococo.zndsl b/bridges/testing/environments/rococo-westend/rococo.zndsl similarity index 100% rename from testing/environments/rococo-westend/rococo.zndsl rename to bridges/testing/environments/rococo-westend/rococo.zndsl diff --git a/testing/environments/rococo-westend/spawn.sh b/bridges/testing/environments/rococo-westend/spawn.sh similarity index 100% rename from testing/environments/rococo-westend/spawn.sh rename to bridges/testing/environments/rococo-westend/spawn.sh diff --git a/testing/environments/rococo-westend/start_relayer.sh b/bridges/testing/environments/rococo-westend/start_relayer.sh similarity index 100% rename from testing/environments/rococo-westend/start_relayer.sh rename to bridges/testing/environments/rococo-westend/start_relayer.sh diff --git a/testing/environments/rococo-westend/westend-init.zndsl b/bridges/testing/environments/rococo-westend/westend-init.zndsl similarity index 100% rename from testing/environments/rococo-westend/westend-init.zndsl rename to bridges/testing/environments/rococo-westend/westend-init.zndsl diff --git a/testing/environments/rococo-westend/westend.zndsl b/bridges/testing/environments/rococo-westend/westend.zndsl similarity index 100% rename from testing/environments/rococo-westend/westend.zndsl rename to bridges/testing/environments/rococo-westend/westend.zndsl diff --git a/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js b/bridges/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js similarity index 100% rename from testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js rename to bridges/testing/framework/js-helpers/best-finalized-header-at-bridged-chain.js diff --git a/testing/framework/js-helpers/chains/rococo-at-westend.js b/bridges/testing/framework/js-helpers/chains/rococo-at-westend.js similarity index 100% rename from testing/framework/js-helpers/chains/rococo-at-westend.js rename to bridges/testing/framework/js-helpers/chains/rococo-at-westend.js diff --git a/testing/framework/js-helpers/chains/westend-at-rococo.js b/bridges/testing/framework/js-helpers/chains/westend-at-rococo.js similarity index 100% rename from testing/framework/js-helpers/chains/westend-at-rococo.js rename to bridges/testing/framework/js-helpers/chains/westend-at-rococo.js diff --git a/testing/framework/js-helpers/native-assets-balance-increased.js b/bridges/testing/framework/js-helpers/native-assets-balance-increased.js similarity index 100% rename from testing/framework/js-helpers/native-assets-balance-increased.js rename to bridges/testing/framework/js-helpers/native-assets-balance-increased.js diff --git a/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js b/bridges/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js similarity index 100% rename from testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js rename to bridges/testing/framework/js-helpers/only-mandatory-headers-synced-when-idle.js diff --git a/testing/framework/js-helpers/only-required-headers-synced-when-idle.js b/bridges/testing/framework/js-helpers/only-required-headers-synced-when-idle.js similarity index 100% rename from testing/framework/js-helpers/only-required-headers-synced-when-idle.js rename to bridges/testing/framework/js-helpers/only-required-headers-synced-when-idle.js diff --git a/testing/framework/js-helpers/relayer-rewards.js b/bridges/testing/framework/js-helpers/relayer-rewards.js similarity index 100% rename from testing/framework/js-helpers/relayer-rewards.js rename to bridges/testing/framework/js-helpers/relayer-rewards.js diff --git a/testing/framework/js-helpers/utils.js b/bridges/testing/framework/js-helpers/utils.js similarity index 100% rename from testing/framework/js-helpers/utils.js rename to bridges/testing/framework/js-helpers/utils.js diff --git a/testing/framework/js-helpers/wait-hrmp-channel-opened.js b/bridges/testing/framework/js-helpers/wait-hrmp-channel-opened.js similarity index 100% rename from testing/framework/js-helpers/wait-hrmp-channel-opened.js rename to bridges/testing/framework/js-helpers/wait-hrmp-channel-opened.js diff --git a/testing/framework/js-helpers/wrapped-assets-balance.js b/bridges/testing/framework/js-helpers/wrapped-assets-balance.js similarity index 100% rename from testing/framework/js-helpers/wrapped-assets-balance.js rename to bridges/testing/framework/js-helpers/wrapped-assets-balance.js diff --git a/testing/framework/utils/bridges.sh b/bridges/testing/framework/utils/bridges.sh similarity index 100% rename from testing/framework/utils/bridges.sh rename to bridges/testing/framework/utils/bridges.sh diff --git a/testing/framework/utils/common.sh b/bridges/testing/framework/utils/common.sh similarity index 100% rename from testing/framework/utils/common.sh rename to bridges/testing/framework/utils/common.sh diff --git a/testing/framework/utils/generate_hex_encoded_call/index.js b/bridges/testing/framework/utils/generate_hex_encoded_call/index.js similarity index 100% rename from testing/framework/utils/generate_hex_encoded_call/index.js rename to bridges/testing/framework/utils/generate_hex_encoded_call/index.js diff --git a/testing/framework/utils/generate_hex_encoded_call/package-lock.json b/bridges/testing/framework/utils/generate_hex_encoded_call/package-lock.json similarity index 100% rename from testing/framework/utils/generate_hex_encoded_call/package-lock.json rename to bridges/testing/framework/utils/generate_hex_encoded_call/package-lock.json diff --git a/testing/framework/utils/generate_hex_encoded_call/package.json b/bridges/testing/framework/utils/generate_hex_encoded_call/package.json similarity index 100% rename from testing/framework/utils/generate_hex_encoded_call/package.json rename to bridges/testing/framework/utils/generate_hex_encoded_call/package.json diff --git a/testing/framework/utils/zombienet.sh b/bridges/testing/framework/utils/zombienet.sh similarity index 100% rename from testing/framework/utils/zombienet.sh rename to bridges/testing/framework/utils/zombienet.sh diff --git a/testing/run-new-test.sh b/bridges/testing/run-new-test.sh similarity index 100% rename from testing/run-new-test.sh rename to bridges/testing/run-new-test.sh diff --git a/testing/run-tests.sh b/bridges/testing/run-tests.sh similarity index 100% rename from testing/run-tests.sh rename to bridges/testing/run-tests.sh diff --git a/testing/scripts/invoke-script.sh b/bridges/testing/scripts/invoke-script.sh similarity index 100% rename from testing/scripts/invoke-script.sh rename to bridges/testing/scripts/invoke-script.sh diff --git a/testing/scripts/start-relayer.sh b/bridges/testing/scripts/start-relayer.sh similarity index 100% rename from testing/scripts/start-relayer.sh rename to bridges/testing/scripts/start-relayer.sh diff --git a/testing/scripts/sync-exit.sh b/bridges/testing/scripts/sync-exit.sh similarity index 100% rename from testing/scripts/sync-exit.sh rename to bridges/testing/scripts/sync-exit.sh diff --git a/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl similarity index 100% rename from testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl rename to bridges/testing/tests/0001-asset-transfer/roc-reaches-westend.zndsl diff --git a/testing/tests/0001-asset-transfer/run.sh b/bridges/testing/tests/0001-asset-transfer/run.sh similarity index 100% rename from testing/tests/0001-asset-transfer/run.sh rename to bridges/testing/tests/0001-asset-transfer/run.sh diff --git a/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl similarity index 100% rename from testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl rename to bridges/testing/tests/0001-asset-transfer/wnd-reaches-rococo.zndsl diff --git a/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl b/bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl similarity index 100% rename from testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl rename to bridges/testing/tests/0001-asset-transfer/wroc-reaches-rococo.zndsl diff --git a/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl b/bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl similarity index 100% rename from testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl rename to bridges/testing/tests/0001-asset-transfer/wwnd-reaches-westend.zndsl diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl similarity index 100% rename from testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl rename to bridges/testing/tests/0002-mandatory-headers-synced-while-idle/rococo-to-westend.zndsl diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh similarity index 100% rename from testing/tests/0002-mandatory-headers-synced-while-idle/run.sh rename to bridges/testing/tests/0002-mandatory-headers-synced-while-idle/run.sh diff --git a/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl b/bridges/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl similarity index 100% rename from testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl rename to bridges/testing/tests/0002-mandatory-headers-synced-while-idle/westend-to-rococo.zndsl diff --git a/testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl b/bridges/testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl similarity index 100% rename from testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl rename to bridges/testing/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl diff --git a/testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl b/bridges/testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl similarity index 100% rename from testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl rename to bridges/testing/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl